From lkp at intel.com  Sat Mar  1 00:36:51 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 1 Mar 2025 16:36:51 +0800
Subject: [PATCH v1] spi: mt65xx: add PM QoS support
In-Reply-To: <20250228062246.24186-1-leilk.liu@mediatek.com>
References: <20250228062246.24186-1-leilk.liu@mediatek.com>
Message-ID: <202503011637.9HYajsft-lkp@intel.com>

Hi Leilk,

kernel test robot noticed the following build warnings:

[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Leilk-Liu/spi-mt65xx-add-PM-QoS-support/20250228-142359
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
patch link:    https://lore.kernel.org/r/20250228062246.24186-1-leilk.liu%40mediatek.com
patch subject: [PATCH v1] spi: mt65xx: add PM QoS support
config: sh-randconfig-002-20250301 (https://download.01.org/0day-ci/archive/20250301/202503011637.9HYajsft-lkp at intel.com/config)
compiler: sh4-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250301/202503011637.9HYajsft-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503011637.9HYajsft-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/spi/spi-mt65xx.c:177: warning: Function parameter or struct member 'qos_request' not described in 'mtk_spi'


vim +177 drivers/spi/spi-mt65xx.c

a568231f463225 Leilk Liu                  2015-08-07  132  
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  133  /**
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  134   * struct mtk_spi - SPI driver instance
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  135   * @base:		Start address of the SPI controller registers
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  136   * @state:		SPI controller state
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  137   * @pad_num:		Number of pad_sel entries
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  138   * @pad_sel:		Groups of pins to select
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  139   * @parent_clk:		Parent of sel_clk
cae1578847e60a Yang Yingliang             2023-08-23  140   * @sel_clk:		SPI host mux clock
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  141   * @spi_clk:		Peripheral clock
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  142   * @spi_hclk:		AHB bus clock
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  143   * @cur_transfer:	Currently processed SPI transfer
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  144   * @xfer_len:		Number of bytes to transfer
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  145   * @num_xfered:		Number of transferred bytes
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  146   * @tx_sgl:		TX transfer scatterlist
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  147   * @rx_sgl:		RX transfer scatterlist
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  148   * @tx_sgl_len:		Size of TX DMA transfer
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  149   * @rx_sgl_len:		Size of RX DMA transfer
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  150   * @dev_comp:		Device data structure
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  151   * @spi_clk_hz:		Current SPI clock in Hz
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  152   * @spimem_done:	SPI-MEM operation completion
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  153   * @use_spimem:		Enables SPI-MEM
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  154   * @dev:		Device pointer
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  155   * @tx_dma:		DMA start for SPI-MEM TX
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  156   * @rx_dma:		DMA start for SPI-MEM RX
3c5cd2e23fe4c8 AngeloGioacchino Del Regno 2022-04-07  157   */
a568231f463225 Leilk Liu                  2015-08-07  158  struct mtk_spi {
a568231f463225 Leilk Liu                  2015-08-07  159  	void __iomem *base;
a568231f463225 Leilk Liu                  2015-08-07  160  	u32 state;
37457607ecaffe Leilk Liu                  2015-10-26  161  	int pad_num;
37457607ecaffe Leilk Liu                  2015-10-26  162  	u32 *pad_sel;
a740f4e684c020 Leilk Liu                  2022-03-21  163  	struct clk *parent_clk, *sel_clk, *spi_clk, *spi_hclk;
a568231f463225 Leilk Liu                  2015-08-07  164  	struct spi_transfer *cur_transfer;
a568231f463225 Leilk Liu                  2015-08-07  165  	u32 xfer_len;
00bca73bfca4fb Peter Shih                 2018-09-10  166  	u32 num_xfered;
a568231f463225 Leilk Liu                  2015-08-07  167  	struct scatterlist *tx_sgl, *rx_sgl;
a568231f463225 Leilk Liu                  2015-08-07  168  	u32 tx_sgl_len, rx_sgl_len;
a568231f463225 Leilk Liu                  2015-08-07  169  	const struct mtk_spi_compatible *dev_comp;
b0677bc0b5f41e Leilk Liu                  2025-02-28  170  	struct pm_qos_request qos_request;
162a31effc4182 Mason Zhang                2021-06-29  171  	u32 spi_clk_hz;
9f763fd20da7d8 Leilk Liu                  2022-03-21  172  	struct completion spimem_done;
9f763fd20da7d8 Leilk Liu                  2022-03-21  173  	bool use_spimem;
9f763fd20da7d8 Leilk Liu                  2022-03-21  174  	struct device *dev;
9f763fd20da7d8 Leilk Liu                  2022-03-21  175  	dma_addr_t tx_dma;
9f763fd20da7d8 Leilk Liu                  2022-03-21  176  	dma_addr_t rx_dma;
a568231f463225 Leilk Liu                  2015-08-07 @177  };
a568231f463225 Leilk Liu                  2015-08-07  178  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 01:07:36 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 1 Mar 2025 17:07:36 +0800
Subject: [PATCH v2 3/4] arm64: dts: exynos: add initial support for
 Samsung Galaxy S22+
In-Reply-To: <20250223123044.725493-4-ivo.ivanov.ivanov1@gmail.com>
References: <20250223123044.725493-4-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <202503011651.Vto3vDw7-lkp@intel.com>

Hi Ivaylo,

kernel test robot noticed the following build errors:

[auto build test ERROR on krzk/for-next]
[also build test ERROR on robh/for-next krzk-dt/for-next pinctrl-samsung/for-next linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ivaylo-Ivanov/dt-bindings-arm-samsung-document-g0s-board-binding/20250223-203243
base:   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git for-next
patch link:    https://lore.kernel.org/r/20250223123044.725493-4-ivo.ivanov.ivanov1%40gmail.com
patch subject: [PATCH v2 3/4] arm64: dts: exynos: add initial support for Samsung Galaxy S22+
config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20250301/202503011651.Vto3vDw7-lkp at intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250301/202503011651.Vto3vDw7-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503011651.Vto3vDw7-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from arch/arm64/boot/dts/exynos/exynos2200-g0s.dts:9:
>> arch/arm64/boot/dts/exynos/exynos2200.dtsi:8:10: fatal error: 'dt-bindings/clock/samsung,exynos2200-cmu.h' file not found
       8 | #include <dt-bindings/clock/samsung,exynos2200-cmu.h>
         |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 error generated.


vim +8 arch/arm64/boot/dts/exynos/exynos2200.dtsi

b661f5fc96c5e9 Ivaylo Ivanov 2025-02-23  @8  #include <dt-bindings/clock/samsung,exynos2200-cmu.h>
b661f5fc96c5e9 Ivaylo Ivanov 2025-02-23   9  #include <dt-bindings/interrupt-controller/arm-gic.h>
b661f5fc96c5e9 Ivaylo Ivanov 2025-02-23  10  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From piotr.oniszczuk at gmail.com  Sat Mar  1 01:11:54 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Sat, 1 Mar 2025 10:11:54 +0100
Subject: [PATCH v7 0/3] Add HDMI audio on the rk3588 SoC
In-Reply-To: <3337030.aeNJFYEL58@trenzalore>
References: <20250217215641.372723-1-detlev.casanova@collabora.com>
 <87frk2sumw.wl-kuninori.morimoto.gx@renesas.com>
 <8734g2sg4t.wl-kuninori.morimoto.gx@renesas.com>
 <3337030.aeNJFYEL58@trenzalore>
Message-ID: <0A30138B-183E-4816-80FF-AACDCFE3B3A6@gmail.com>



> Wiadomo?? napisana przez Detlev Casanova <detlev.casanova at collabora.com> w dniu 25 lut 2025, o godz. 15:58:
> 
> From what I see, the error is not present anymore on linux 6.14-rc4. I tried 
> reverting your patch "ASoC: simple-card-utils.c: add missing dlc->of_node" 
> (dabbd325b25edb5cdd99c94391817202dd54b651) and the error reappears.

Guys,

Just FYI:

On 6.14-rc4 without 0001-ASoC-simple-card-utils-Don-t-use-__free-device_node-.patch - i still have oops like this: https://gist.github.com/warpme/ed75c05d3b68f995d429dbd9097005ba
They are happening not every boot - but still happening.

However applying 0001-ASoC-simple-card-utils-Don-t-use-__free-device_node-.patch (with some adaptations as it not applies cleanly on 6.140rc4) - dmesg becomes clean (10 boots; all ok)







From maxime.chevallier at bootlin.com  Sat Mar  1 01:53:52 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat, 1 Mar 2025 10:53:52 +0100
Subject: [PATCH net 2/2] net: ethtool: netlink: Pass a context for
 default ethnl notifications
In-Reply-To: <20250228182440.3c7f4709@kernel.org>
References: <20250227182454.1998236-1-maxime.chevallier@bootlin.com>
	<20250227182454.1998236-3-maxime.chevallier@bootlin.com>
	<20250228182440.3c7f4709@kernel.org>
Message-ID: <20250301105352.2951af4c@fedora.home>

On Fri, 28 Feb 2025 18:24:40 -0800
Jakub Kicinski <kuba at kernel.org> wrote:

> On Thu, 27 Feb 2025 19:24:52 +0100 Maxime Chevallier wrote:
> > The only relevant user for now is PLCA, and it very likely that we never
> > ended-up in a situation where the follow-up notif wasn't targeting the
> > correct PHY as :  
> 
> PLCA uses the ethnl_default_* handlers but it seems to operate on PHYs
> now. How does the dump work? Shoehorning the PHY support into
> the ethnl_default_* handlers is starting to look pretty messy.

I agree, that's the less ugly quick solution I could think of :(

So maybe we need some generic PHY dump support for all PHY commands ?

I should probably re-send patch 1 only to fix the crash, and rework the
dump/notify for PHY commands separately if this is OK for you ?

Maxime


From dmitry.baryshkov at linaro.org  Sat Mar  1 02:03:57 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat,  1 Mar 2025 12:03:57 +0200
Subject: [PATCH 0/7] gpu: ipu-v3: Remove unused functions
In-Reply-To: <20241226022752.219399-1-linux@treblig.org>
References: <20241226022752.219399-1-linux@treblig.org>
Message-ID: <174082343297.2941786.11452976094065423321.b4-ty@linaro.org>

On Thu, 26 Dec 2024 02:27:45 +0000, linux at treblig.org wrote:
> From: "Dr. David Alan Gilbert" <linux at treblig.org>
> 
> Hi,
>   This set removes a bunch of functions in ipu-v3 that
> have been unused for a long time (since 2012-2017).
> 
>   No changes to functions are made, just full deletions.
> 
> [...]

Applied to drm-misc-next, thanks!

[1/7] gpu: ipu-v3: ipu-ic: Remove unused ipu_ic_task_graphics_init
      commit: 16e3bf497fb2d379f3d461fa0c85d14de0a3d183
[2/7] gpu: ipu-v3: Remove unused ipu_rot_mode_to_degrees
      commit: a52ba18c254c0a3819e632e6371554f1c6f5bd16
[3/7] gpu: ipu-v3: Remove unused ipu_idmac_channel_busy
      commit: 4f9c64e95c3510f4a5192bd401de5611c1dd5637
[4/7] gpu: ipu-v3: Remove unused ipu_image_convert_* functions
      commit: 96e9d754b35e87a5be2de7dce3c810ffdd769c84
[5/7] gpu: ipu-v3: Remove unused ipu_vdi_unsetup
      commit: 27985c86e283e1e5ac8a9809f189f03643a6f5f2
[6/7] gpu: ipu-v3: ipu-csi: Remove unused functions
      commit: c687c3147d5de801ed835b077802b68fe85d8a3d
[7/7] gpu: ipu-v3 ipu-cpmem: Remove unused functions
      commit: 2800028d5bdee8e9a3cda2fec782dadc32225d8d

Best regards,
-- 
With best wishes
Dmitry



From patrick at blueri.se  Sat Mar  1 02:32:06 2025
From: patrick at blueri.se (Patrick Wildt)
Date: Sat, 1 Mar 2025 11:32:06 +0100
Subject: [PATCH v4 2/2] arm64: dts: rockchip: add MNT Reform 2
In-Reply-To: <2700899.tdWV9SEqCh@phil>
References: <Z7OaTzIpeJ-IACrl@windev.fritz.box>
 <Z7OahO_OtwYSmtmQ@windev.fritz.box>
 <2700899.tdWV9SEqCh@phil>
Message-ID: <Z8LiJgNkurF3xt3k@windev.fritz.box>

On Sun, Feb 23, 2025 at 12:38:40AM +0100, Heiko Stuebner wrote:
> Hi Patrick,
> 
> Am Montag, 17. Februar 2025, 21:22:28 MEZ schrieb Patrick Wildt:
> > MNT Reform 2 is an open source laptop with replaceable CPU modules,
> > including a version with the RK3588-based MNT RCORE[1], which is based
> > on Firefly's iCore-3588Q SoM:
> > 
> > - Rockchip RK3588
> > - Quad A76 and Quad A55 CPU
> > - 6 TOPS NPU
> > - up to 32GB LPDDR4x RAM
> > - SD Card slot
> > - Gigabit ethernet port
> > - HDMI port
> > - 2x mPCIe ports for WiFi or NVMe
> > - 3x USB 3.0 Type-A HOST port
> > 
> > [1] https://shop.mntre.com/products/mnt-reform
> > 
> > Signed-off-by: Lukas F. Hartmann <lukas at mntre.com>
> > Signed-off-by: Patrick Wildt <patrick at blueri.se>
> 
> bureaucracy question, what is Lukas' relationship with the patch?
> Two options:
> (1) Lukas initially developed the patch, then the "From:" should be
>     set accordingly
> (2) Both of you developed it together, then we should have a
>     Co-Developed-by: Lukas F. Hartmann <lukas at mntre.com>
>     up there
> 

Thanks, will send a v5 with Co-developed-by tag added! :)

> 
> Some more style things below...
> 

Are there further execptions to the alphabetical rule? For regulators
I often see min before max, which I think makes sense to understand
the range but isn't technically alphabetical. The same for pinctrl-0
and pinctrl-names.

Thanks,
Patrick

> 
> > ---
> > Changes for v4:
> > - Added chassis-type.
> > - Removed unused nodes.
> > - Sorted nodes alphabetically.
> > Changes for v3:
> > - Split DT as it's based on a Firefly iCore-3588Q SoM.
> > Changes for v2:
> > - Aligned with bindings and schemas to appease DTB check warnings.
> > - Aligned with format of other RK3588 boards for consistency.
> > 
> >  arch/arm64/boot/dts/rockchip/Makefile         |   1 +
> >  .../rockchip/rk3588-firefly-icore-3588q.dtsi  | 451 ++++++++++++++++++
> >  .../boot/dts/rockchip/rk3588-mnt-reform2.dts  | 336 +++++++++++++
> >  3 files changed, 788 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
> >  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
> > index def1222c1907..88381d9a20e3 100644
> > --- a/arch/arm64/boot/dts/rockchip/Makefile
> > +++ b/arch/arm64/boot/dts/rockchip/Makefile
> > @@ -145,6 +145,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-firefly-itx-3588j.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-friendlyelec-cm3588-nas.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-h96-max-v58.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-jaguar.dtb
> > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-mnt-reform2.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6-lts.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-ok3588-c.dtb
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
> > new file mode 100644
> > index 000000000000..898a7b29692f
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
> > @@ -0,0 +1,451 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <dt-bindings/pinctrl/rockchip.h>
> > +
> > +#include "rk3588.dtsi"
> > +
> > +/ {
> > +	compatible = "firefly,icore-3588q", "rockchip,rk3588";
> > +
> > +	aliases {
> > +		mmc0 = &sdhci;
> > +	};
> > +};
> > +
> > +&cpu_b0 {
> > +	cpu-supply = <&vdd_cpu_big0_s0>;
> > +	mem-supply = <&vdd_cpu_big0_s0>;
> 
> you don't need the unspecified mem-supply for the cpu cores,
> that is vendor-kernel voodoo and not part of the upstream binding.
> 
> Same for all cores.
> 
> 
> > +};
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts b/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
> > new file mode 100644
> > index 000000000000..936dd959524f
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
> > @@ -0,0 +1,336 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +/*
> > + * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
> > + * Copyright (c) 2024 MNT Research GmbH
> > + */
> > +
> > +/dts-v1/;
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <dt-bindings/input/input.h>
> > +#include <dt-bindings/pinctrl/rockchip.h>
> > +#include <dt-bindings/soc/rockchip,vop2.h>
> > +#include <dt-bindings/usb/pd.h>
> > +
> > +#include "rk3588-firefly-icore-3588q.dtsi"
> > +
> > +/ {
> > +	model = "MNT Reform 2 with RCORE RK3588 Module";
> > +	compatible = "mntre,reform2-rcore", "firefly,icore-3588q", "rockchip,rk3588";
> > +	chassis-type = "laptop";
> > +
> > +	aliases {
> > +		ethernet0 = &gmac0;
> > +		mmc1 = &sdmmc;
> > +	};
> > +
> > +	chosen {
> > +		stdout-path = "serial2:1500000n8";
> > +	};
> > +
> > +	backlight: backlight {
> > +		compatible = "pwm-backlight";
> > +		pwms = <&pwm8 0 10000 0>;
> > +		enable-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
> > +		brightness-levels = <0 8 16 32 64 128 160 200 255>;
> > +		default-brightness-level = <128>;
> 
> please sort standard properties alphabetically (compatible at the top,
> status at the bottom, rest alphabetically)
> 
> > +	};
> > +
> > +&pcie2x1l2 {
> > +	reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
> > +	pinctrl-0 = <&pcie2_0_rst>;
> 
> more sorting
> 
> > +	status = "okay";
> > +};
> > +
> 
> > +&pcie3x4 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pcie3_reset>;
> > +	reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>;
> > +	num-lanes = <1>;
> 
> again sorting
> 
> > +	vpcie3v3-supply = <&vcc3v3_pcie30>;
> > +	status = "okay";
> > +};
> > +
> 
> > +&sdmmc {
> > +	bus-width = <4>;
> > +	max-frequency = <40000000>;
> > +	no-sdio;
> > +	no-mmc;
> > +	no-1-8-v;
> > +	cap-sd-highspeed;
> > +	vqmmc-supply = <&vcc3v3_pcie30>;
> > +	vmmc-supply = <&vcc3v3_pcie30>;
> > +	cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
> > +	disable-wp;
> 
> more sorting
> 
> > +	status = "okay";
> > +};
> > +
> 
> 
> Heiko
> 
> 


From maxime.chevallier at bootlin.com  Sat Mar  1 02:38:43 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat, 1 Mar 2025 11:38:43 +0100
Subject: [PATCH net 2/2] net: ethtool: netlink: Pass a context for
 default ethnl notifications
In-Reply-To: <20250228182440.3c7f4709@kernel.org>
References: <20250227182454.1998236-1-maxime.chevallier@bootlin.com>
	<20250227182454.1998236-3-maxime.chevallier@bootlin.com>
	<20250228182440.3c7f4709@kernel.org>
Message-ID: <20250301113843.3b9df0fe@fedora.home>

On Fri, 28 Feb 2025 18:24:40 -0800
Jakub Kicinski <kuba at kernel.org> wrote:

> On Thu, 27 Feb 2025 19:24:52 +0100 Maxime Chevallier wrote:
> > The only relevant user for now is PLCA, and it very likely that we never
> > ended-up in a situation where the follow-up notif wasn't targeting the
> > correct PHY as :  
> 
> PLCA uses the ethnl_default_* handlers but it seems to operate on PHYs
> now. How does the dump work? Shoehorning the PHY support into
> the ethnl_default_* handlers is starting to look pretty messy.

Thinking more about this, this patch shouldn't have targetted -net in
the first place, as no usecase regressed yet (we don't have any
multi-PHY PLCA setup that exists). The DUMP keeps working as it did
before for that command, in that we dump the PLCA info for
netdev->phydev.

That DUMP / notify situation needs to be addressed as tome point thouh,
before the multi-PHY support through muxes lands (haven't sent it yet,
I'm still on the preliminary series for phy_ports).

So I think that indeed, I'll resend patch 1, and find a more graceful
solution for the phy-targetting commands in a separate series.

Maxime


From ziyao at disroot.org  Sat Mar  1 02:47:24 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:47:24 +0000
Subject: [PATCH 6/8] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104724.36399-1-ziyao@disroot.org>

These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
tuning purpose. Add their definitions and register them in driver if
corresponding GRF is available.

GRFs are looked up by compatible to simplify devicetree binding.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-rk3528.c | 56 ++++++++++++++++++++++++++++---
 drivers/clk/rockchip/clk.h        |  3 ++
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3528.c b/drivers/clk/rockchip/clk-rk3528.c
index b8b577b902a0..b89440dd7448 100644
--- a/drivers/clk/rockchip/clk-rk3528.c
+++ b/drivers/clk/rockchip/clk-rk3528.c
@@ -10,6 +10,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
 
 #include <dt-bindings/clock/rockchip,rk3528-cru.h>
 
@@ -1061,23 +1062,62 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = {
 			0, 1, 1),
 };
 
+static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(0), 1),
+	MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(1), 1),
+};
+
+static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(0), 1),
+	MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(1), 1),
+	MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(0), 1),
+	MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(1), 1),
+};
+
 static int __init clk_rk3528_probe(struct platform_device *pdev)
 {
+	unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
+	unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
+	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
 	struct rockchip_clk_provider *ctx;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
-	unsigned long nr_clks;
+	struct regmap *vo_grf, *vpu_grf;
 	void __iomem *reg_base;
-
-	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
-					       nr_branches) + 1;
+	unsigned long nr_clks;
 
 	reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(reg_base))
 		return dev_err_probe(dev, PTR_ERR(reg_base),
 				     "could not map cru region");
 
+	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
+					       nr_branches) + 1;
+
+	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
+	if (!IS_ERR(vo_grf))
+		nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
+							   nr_vo_branches) + 1,
+			      nr_clks);
+	else if (PTR_ERR(vo_grf) != ENODEV)
+		return dev_err_probe(dev, PTR_ERR(vo_grf),
+				     "failed to look up VO GRF\n");
+
+	vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
+	if (!IS_ERR(vpu_grf))
+		nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
+							   nr_vpu_branches) + 1,
+			      nr_clks);
+	else if (PTR_ERR(vpu_grf) != ENODEV)
+		return dev_err_probe(dev, PTR_ERR(vpu_grf),
+				     "failed to look up VPU GRF\n");
+
 	ctx = rockchip_clk_init(np, reg_base, nr_clks);
 	if (IS_ERR(ctx))
 		return dev_err_probe(dev, PTR_ERR(ctx),
@@ -1091,6 +1131,12 @@ static int __init clk_rk3528_probe(struct platform_device *pdev)
 				     &rk3528_cpuclk_data, rk3528_cpuclk_rates,
 				     ARRAY_SIZE(rk3528_cpuclk_rates));
 	rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches);
+	if (!IS_ERR(vo_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vo_clk_branches,
+						   vo_grf, nr_vo_branches);
+	if (!IS_ERR(vpu_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vpu_clk_branches,
+						   vpu_grf, nr_vpu_branches);
 
 	rk3528_rst_init(np, reg_base);
 
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 5d82ec5facfa..02d4ca0012d7 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -217,6 +217,9 @@ struct clk;
 #define RK3528_CLKSEL_CON(x)		((x) * 0x4 + 0x300)
 #define RK3528_CLKGATE_CON(x)		((x) * 0x4 + 0x800)
 #define RK3528_SOFTRST_CON(x)		((x) * 0x4 + 0xa00)
+#define RK3528_SDMMC_CON(x)		((x) * 0x4 + 0x24)
+#define RK3528_SDIO0_CON(x)		((x) * 0x4 + 0x4)
+#define RK3528_SDIO1_CON(x)		((x) * 0x4 + 0xc)
 #define RK3528_PMU_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE)
 #define RK3528_PMU_CLKGATE_CON(x)	((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE)
 #define RK3528_PCIE_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE)
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:47:49 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:47:49 +0000
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104749.36423-1-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller, describe
them in devicetree. Since their sample and drive clocks are located in
the VO and VPU GRFs, corresponding syscons are added to make these
clocks available.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 5b334690356a..078c97fa1d9f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -7,6 +7,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/clock/rockchip,rk3528-cru.h>
+#include <dt-bindings/reset/rockchip,rk3528-cru.h>
 
 / {
 	compatible = "rockchip,rk3528";
@@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
 			#interrupt-cells = <3>;
 		};
 
+		vpu_grf: syscon at ff340000 {
+			compatible = "rockchip,rk3528-vpu-grf", "syscon";
+			reg = <0x0 0xff340000 0x0 0x8000>;
+		};
+
+		vo_grf: syscon at ff360000 {
+			compatible = "rockchip,rk3528-vo-grf", "syscon";
+			reg = <0x0 0xff360000 0x0 0x10000>;
+		};
+
 		cru: clock-controller at ff4a0000 {
 			compatible = "rockchip,rk3528-cru";
 			reg = <0x0 0xff4a0000 0x0 0x30000>;
@@ -251,5 +262,56 @@ uart7: serial at ffa28000 {
 			reg-shift = <2>;
 			status = "disabled";
 		};
+
+		sdio0: mmc at ffc10000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc10000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO0>,
+				 <&cru CCLK_SRC_SDIO0>,
+				 <&cru SCLK_SDIO0_DRV>,
+				 <&cru SCLK_SDIO0_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			resets = <&cru SRST_H_SDIO0>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdio1: mmc at ffc20000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc20000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO1>,
+				 <&cru CCLK_SRC_SDIO1>,
+				 <&cru SCLK_SDIO1_DRV>,
+				 <&cru SCLK_SDIO1_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			resets = <&cru SRST_H_SDIO1>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdmmc: mmc at ffc30000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc30000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDMMC0>,
+				 <&cru CCLK_SRC_SDMMC0>,
+				 <&cru SCLK_SDMMC_DRV>,
+				 <&cru SCLK_SDMMC_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			resets = <&cru SRST_H_SDMMC0>;
+			reset-names = "reset";
+			status = "disabled";
+		};
 	};
 };
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:48:35 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:48:35 +0000
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104835.36439-1-ziyao@disroot.org>

SD-card is available on Radxa E20C board.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index d2cdb63d4a9d..473065aa4228 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -12,6 +12,10 @@ / {
 	model = "Radxa E20C";
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
+	aliases {
+		mmc0 = &sdmmc;
+	};
+
 	chosen {
 		stdout-path = "serial0:1500000n8";
 	};
@@ -20,3 +24,13 @@ chosen {
 &uart0 {
 	status = "okay";
 };
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+	rockchip,default-sample-phase = <90>;
+	sd-uhs-sdr104;
+	status = "okay";
+};
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:42:42 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:42:42 +0000
Subject: [PATCH 0/8] Support SD/SDIO controllers on RK3528
Message-ID: <20250301104250.36295-1-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller. This
series adds essential support for their tuning clocks, document the
controller in dt-bindings and bring the SD/MMC one up on Radxa E20C
board with pinctrl set up by the previous bootloader. Both HS and SDR104
mode are verified.

Yao Zi (8):
  dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
  dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
  dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
  dt-bindings: clock: Add GRF clock definition for RK3528
  clk: rockchip: Support MMC clocks in GRF region
  clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
  arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
  arm64: dts: rockchip: Enable SD-card interface on Radxa E20C

 .../bindings/mmc/rockchip-dw-mshc.yaml        |  1 +
 .../devicetree/bindings/soc/rockchip/grf.yaml |  2 +
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 14 +++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 62 +++++++++++++++++++
 drivers/clk/rockchip/clk-mmc-phase.c          | 24 +++++--
 drivers/clk/rockchip/clk-rk3528.c             | 56 +++++++++++++++--
 drivers/clk/rockchip/clk.c                    | 42 +++++++++++++
 drivers/clk/rockchip/clk.h                    | 23 ++++++-
 .../dt-bindings/clock/rockchip,rk3528-cru.h   |  6 ++
 9 files changed, 220 insertions(+), 10 deletions(-)

-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:42:43 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:42:43 +0000
Subject: [PATCH 1/8] dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104250.36295-2-ziyao@disroot.org>

Add compatible string for VO GRF found on RK3528 SoC.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index 61f38b68a4a3..7936be79159e 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -15,6 +15,7 @@ properties:
       - items:
           - enum:
               - rockchip,rk3288-sgrf
+              - rockchip,rk3528-vo-grf
               - rockchip,rk3566-pipe-grf
               - rockchip,rk3568-pcie3-phy-grf
               - rockchip,rk3568-pipe-grf
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:42:44 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:42:44 +0000
Subject: [PATCH 2/8] dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104250.36295-3-ziyao@disroot.org>

Add compatible string for VPU GRF found on RK3528 SoC.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index 7936be79159e..d43c3f7e74fa 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -16,6 +16,7 @@ properties:
           - enum:
               - rockchip,rk3288-sgrf
               - rockchip,rk3528-vo-grf
+              - rockchip,rk3528-vpu-grf
               - rockchip,rk3566-pipe-grf
               - rockchip,rk3568-pcie3-phy-grf
               - rockchip,rk3568-pipe-grf
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:42:45 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:42:45 +0000
Subject: [PATCH 3/8] dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104250.36295-4-ziyao@disroot.org>

Add RK3528 compatible string for SD/SDIO interface.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
index 06df1269f247..ea0feb733e32 100644
--- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
@@ -38,6 +38,7 @@ properties:
               - rockchip,rk3328-dw-mshc
               - rockchip,rk3368-dw-mshc
               - rockchip,rk3399-dw-mshc
+              - rockchip,rk3528-dw-mshc
               - rockchip,rk3568-dw-mshc
               - rockchip,rk3588-dw-mshc
               - rockchip,rv1108-dw-mshc
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:42:46 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:42:46 +0000
Subject: [PATCH 4/8] dt-bindings: clock: Add GRF clock definition for RK3528
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104250.36295-5-ziyao@disroot.org>

These clocks are for SD/SDIO tuning purpose and come with registers
in GRF syscon.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h
index 55a448f5ed6d..0245a53fc334 100644
--- a/include/dt-bindings/clock/rockchip,rk3528-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h
@@ -414,6 +414,12 @@
 #define MCLK_I2S2_2CH_SAI_SRC_PRE	402
 #define MCLK_I2S3_8CH_SAI_SRC_PRE	403
 #define MCLK_SDPDIF_SRC_PRE		404
+#define SCLK_SDMMC_DRV			405
+#define SCLK_SDMMC_SAMPLE		406
+#define SCLK_SDIO0_DRV			407
+#define SCLK_SDIO0_SAMPLE		408
+#define SCLK_SDIO1_DRV			409
+#define SCLK_SDIO1_SAMPLE		410
 
 /* scmi-clocks indices */
 #define SCMI_PCLK_KEYREADER		0
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:44:13 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:44:13 +0000
Subject: [PATCH 4/8] dt-bindings: clock: Add GRF clock definition for RK3528
Message-ID: <20250301104413.36335-1-ziyao@disroot.org>

These clocks are for SD/SDIO tuning purpose and come with registers
in GRF syscon.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h
index 55a448f5ed6d..0245a53fc334 100644
--- a/include/dt-bindings/clock/rockchip,rk3528-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h
@@ -414,6 +414,12 @@
 #define MCLK_I2S2_2CH_SAI_SRC_PRE	402
 #define MCLK_I2S3_8CH_SAI_SRC_PRE	403
 #define MCLK_SDPDIF_SRC_PRE		404
+#define SCLK_SDMMC_DRV			405
+#define SCLK_SDMMC_SAMPLE		406
+#define SCLK_SDIO0_DRV			407
+#define SCLK_SDIO0_SAMPLE		408
+#define SCLK_SDIO1_DRV			409
+#define SCLK_SDIO1_SAMPLE		410
 
 /* scmi-clocks indices */
 #define SCMI_PCLK_KEYREADER		0
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:46:21 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat,  1 Mar 2025 10:46:21 +0000
Subject: [PATCH 5/8] clk: rockchip: Support MMC clocks in GRF region
In-Reply-To: <20250301104250.36295-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
Message-ID: <20250301104621.36375-1-ziyao@disroot.org>

Registers of MMC drive/sample clocks in Rockchip RV1106 and RK3528
locate in GRF regions. Adjust MMC clock code to support register
operations through regmap. Also add a helper to ease registration of GRF
clocks.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-mmc-phase.c | 24 +++++++++++++---
 drivers/clk/rockchip/clk.c           | 42 ++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h           | 20 ++++++++++++-
 3 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 91012078681b..b3ed8e7523e5 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -9,11 +9,14 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct regmap	*grf;
+	int		grf_reg;
 	int		shift;
 	int		cached_phase;
 	struct notifier_block clk_rate_change_nb;
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
 	if (!rate)
 		return 0;
 
-	raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
+	if (mmc_clock->grf)
+		regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
+	else
+		raw_value = readl(mmc_clock->reg);
+
+	raw_value >>= mmc_clock->shift;
 
 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
 
@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
 	raw_value |= nineties;
-	writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
-	       mmc_clock->reg);
+	raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
+
+	if (mmc_clock->grf)
+		regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
+	else
+		writel(raw_value, mmc_clock->reg);
 
 	pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
 		clk_hw_get_name(hw), degrees, delay_num,
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift)
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift)
 {
 	struct clk_init_data init;
 	struct rockchip_mmc_clock *mmc_clock;
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 
 	mmc_clock->hw.init = &init;
 	mmc_clock->reg = reg;
+	mmc_clock->grf = grf;
+	mmc_clock->grf_reg = grf_reg;
 	mmc_clock->shift = shift;
 
 	clk = clk_register(NULL, &mmc_clock->hw);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index cbf93ea119a9..ce2f3323d84e 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -590,6 +590,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 				list->name,
 				list->parent_names, list->num_parents,
 				ctx->reg_base + list->muxdiv_offset,
+				NULL, 0,
 				list->div_shift
 			);
 			break;
@@ -619,6 +620,11 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 			break;
 		case branch_linked_gate:
 			/* must be registered late, fall-through for error message */
+		case branch_mmc_grf:
+			/*
+			 * must be registered through rockchip_clk_register_grf_branches,
+			 * fall-through for error message
+			 */
 			break;
 		}
 
@@ -665,6 +671,42 @@ void rockchip_clk_register_late_branches(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(rockchip_clk_register_late_branches);
 
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk)
+{
+	unsigned int idx;
+	struct clk *clk;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = NULL;
+
+		switch (list->branch_type) {
+		case branch_mmc_grf:
+			clk = rockchip_clk_register_mmc(
+				list->name,
+				list->parent_names, list->num_parents,
+				NULL,
+				grf, list->muxdiv_offset,
+				list->div_shift
+			);
+			break;
+		default:
+			pr_err("%s: unknown clock type %d\n",
+			       __func__, list->branch_type);
+			break;
+		}
+
+		if (!clk)
+			pr_err("%s: failed to register clock %s: %ld\n",
+			       __func__, list->name, PTR_ERR(clk));
+		else
+			rockchip_clk_set_lookup(ctx, clk, list->id);
+	}
+}
+EXPORT_SYMBOL_GPL(rockchip_clk_register_grf_branches);
+
 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
 				  unsigned int lookup_id,
 				  const char *name, const char *const *parent_names,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index b322d42dc879..5d82ec5facfa 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -555,7 +555,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift);
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift);
 
 /*
  * DDRCLK flags, including method of setting the rate
@@ -594,6 +596,7 @@ enum rockchip_clk_branch_type {
 	branch_gate,
 	branch_linked_gate,
 	branch_mmc,
+	branch_mmc_grf,
 	branch_inverter,
 	branch_factor,
 	branch_ddrclk,
@@ -944,6 +947,17 @@ struct rockchip_clk_branch {
 		.div_shift	= shift,			\
 	}
 
+#define MMC_GRF(_id, cname, pname, offset, shift)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_mmc_grf,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.muxdiv_offset	= offset,			\
+		.div_shift	= shift,			\
+	}
+
 #define INVERTER(_id, cname, pname, io, is, if)			\
 	{							\
 		.id		= _id,				\
@@ -1093,6 +1107,10 @@ void rockchip_clk_register_late_branches(struct device *dev,
 					 struct rockchip_clk_provider *ctx,
 					 struct rockchip_clk_branch *list,
 					 unsigned int nr_clk);
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk);
 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
 				struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  1 02:53:21 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat, 1 Mar 2025 10:53:21 +0000
Subject: [PATCH 4/8] dt-bindings: clock: Add GRF clock definition for
 RK3528
In-Reply-To: <20250301104413.36335-1-ziyao@disroot.org>
References: <20250301104413.36335-1-ziyao@disroot.org>
Message-ID: <Z8LnIfDWZtuwoUrk@pie.lan>

On Sat, Mar 01, 2025 at 10:44:13AM +0000, Yao Zi wrote:
> These clocks are for SD/SDIO tuning purpose and come with registers
> in GRF syscon.

Please ignore this e-mail and refer to the series[1] instead, I missed
--in-reply-to when sending. Sorry for the noise.

Best regards,
Yao Zi

[1]: https://lore.kernel.org/all/20250301104250.36295-1-ziyao at disroot.org/

> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h
> index 55a448f5ed6d..0245a53fc334 100644
> --- a/include/dt-bindings/clock/rockchip,rk3528-cru.h
> +++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h
> @@ -414,6 +414,12 @@
>  #define MCLK_I2S2_2CH_SAI_SRC_PRE	402
>  #define MCLK_I2S3_8CH_SAI_SRC_PRE	403
>  #define MCLK_SDPDIF_SRC_PRE		404
> +#define SCLK_SDMMC_DRV			405
> +#define SCLK_SDMMC_SAMPLE		406
> +#define SCLK_SDIO0_DRV			407
> +#define SCLK_SDIO0_SAMPLE		408
> +#define SCLK_SDIO1_DRV			409
> +#define SCLK_SDIO1_SAMPLE		410
>  
>  /* scmi-clocks indices */
>  #define SCMI_PCLK_KEYREADER		0
> -- 
> 2.48.1
> 


From sven at svenpeter.dev  Sat Mar  1 03:11:54 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 01 Mar 2025 12:11:54 +0100
Subject: [PATCH 0/9] arm64: dts: apple: Add CPU cache information for Apple A7-A11,
 T2 SoCs
In-Reply-To: <20250220-caches-v1-0-2c7011097768@gmail.com>
References: <20250220-caches-v1-0-2c7011097768@gmail.com>
Message-ID: <4670e5f8-2a92-46bd-8faa-dd3774517f3e@app.fastmail.com>

Hi,

On Thu, Feb 20, 2025, at 13:21, Nick Chan wrote:
> Add CPU cache information for Apple A7-A11, T2 SoCs. On Apple
> A10 (T8010), A10X (T8011), T2 (T8012), only the caches in one of the
> CPU clusters can be used due to the "Apple Fusion Architecture"
> big.LITTLE switcher. The values for the P-cluster is used in this
> case.

So this means that the cache information will be "wrong" when the CPU
is in the lower power states and only correct for the higher ones?
I'm not familiar with how these values are used; are you and do you
know if this will have any weird or unexpected effects?
Would it be better to use the cache size for the lower rather than
the higher states or does this not matter much?



Best,


Sven


From maz at kernel.org  Sat Mar  1 03:10:35 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 01 Mar 2025 11:10:35 +0000
Subject: [PATCH v15 02/15] irqdomain: Add IRQ_DOMAIN_FLAG_MSI_IMMUTABLE and irq_domain_is_msi_immutable()
In-Reply-To: <20250211-ep-msi-v15-2-bcacc1f2b1a9@nxp.com>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
	<20250211-ep-msi-v15-2-bcacc1f2b1a9@nxp.com>
Message-ID: <86plj1ovkk.wl-maz@kernel.org>

On Tue, 11 Feb 2025 19:21:55 +0000,
Frank Li <Frank.Li at nxp.com> wrote:
> 
> Add the flag IRQ_DOMAIN_FLAG_MSI_IMMUTABLE and the API function
> irq_domain_is_msi_immutable() to check if the MSI controller retains an
> immutable address/data pair during irq_set_affinity().
> 
> Ensure compatibility with MSI users like PCIe Endpoint Doorbell, which
> require the address/data pair to remain unchanged after setup. Use this
> function to verify if the MSI controller is immutable.

Why is that a requirement? Why should a driver even care?

	M.

-- 
Without deviation from the norm, progress is not possible.


From heiko at sntech.de  Sat Mar  1 03:10:41 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sat, 01 Mar 2025 12:10:41 +0100
Subject: [PATCH v4 2/2] arm64: dts: rockchip: add MNT Reform 2
In-Reply-To: <Z8LiJgNkurF3xt3k@windev.fritz.box>
References: <Z7OaTzIpeJ-IACrl@windev.fritz.box> <2700899.tdWV9SEqCh@phil>
 <Z8LiJgNkurF3xt3k@windev.fritz.box>
Message-ID: <3309912.5fSG56mABF@diego>

Am Samstag, 1. M?rz 2025, 11:32:06 MEZ schrieb Patrick Wildt:
> On Sun, Feb 23, 2025 at 12:38:40AM +0100, Heiko Stuebner wrote:
> > Hi Patrick,
> > 
> > Am Montag, 17. Februar 2025, 21:22:28 MEZ schrieb Patrick Wildt:
> > > MNT Reform 2 is an open source laptop with replaceable CPU modules,
> > > including a version with the RK3588-based MNT RCORE[1], which is based
> > > on Firefly's iCore-3588Q SoM:
> > > 
> > > - Rockchip RK3588
> > > - Quad A76 and Quad A55 CPU
> > > - 6 TOPS NPU
> > > - up to 32GB LPDDR4x RAM
> > > - SD Card slot
> > > - Gigabit ethernet port
> > > - HDMI port
> > > - 2x mPCIe ports for WiFi or NVMe
> > > - 3x USB 3.0 Type-A HOST port
> > > 
> > > [1] https://shop.mntre.com/products/mnt-reform
> > > 
> > > Signed-off-by: Lukas F. Hartmann <lukas at mntre.com>
> > > Signed-off-by: Patrick Wildt <patrick at blueri.se>
> > 
> > bureaucracy question, what is Lukas' relationship with the patch?
> > Two options:
> > (1) Lukas initially developed the patch, then the "From:" should be
> >     set accordingly
> > (2) Both of you developed it together, then we should have a
> >     Co-Developed-by: Lukas F. Hartmann <lukas at mntre.com>
> >     up there
> > 
> 
> Thanks, will send a v5 with Co-developed-by tag added! :)
> 
> > 
> > Some more style things below...
> > 
> 
> Are there further execptions to the alphabetical rule? For regulators
> I often see min before max, which I think makes sense to understand
> the range but isn't technically alphabetical. The same for pinctrl-0
> and pinctrl-names.

The "preferred" rules are in [0], and in recent times I've come to
appreciate not needing to explain exceptions ;-) .

But I do see them as guidelines, especially in a leaf-dt (for a device)
concessions are possible.

So yes, I can definitly see min before max as beneficial and if you want
to sort that way, that is fine by me


Heiko

[0] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/dts-coding-style.rst#n112




From catalin.marinas at arm.com  Sat Mar  1 03:11:28 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Sat, 1 Mar 2025 11:11:28 +0000
Subject: [PATCH V2 0/7] arm64/boot: Enable EL2 requirements for
 FEAT_PMUv3p9
In-Reply-To: <20250301075849.GA28249@willie-the-truck>
References: <20250203050828.1049370-1-anshuman.khandual@arm.com>
 <20250301075849.GA28249@willie-the-truck>
Message-ID: <Z8LrYBD7WHjOnJgT@arm.com>

On Sat, Mar 01, 2025 at 07:58:50AM +0000, Will Deacon wrote:
> On Mon, Feb 03, 2025 at 10:38:21AM +0530, Anshuman Khandual wrote:
> > This series adds fine grained trap control in EL2 required for FEAT_PMUv3p9
> > registers like PMICNTR_EL0, PMICFILTR_EL0, and PMUACR_EL1 which are already
> > being used in the kernel. This is required to prevent their EL1 access trap
> > into EL2.
> > 
> > PMZR_EL0 register trap control i.e HDFGWTR2_EL2.nPMZR_EL0 remains unchanged
> > for now as it does not get accessed in the kernel, and there is no plan for
> > its access from user space.
> > 
> > I have taken the liberty to pick up all the review tags for patches related
> > to tools sysreg update from the KVM FGT2 V2 patch series posted earlier.
> > 
> > https://lore.kernel.org/all/20241210055311.780688-1-anshuman.khandual at arm.com/
> > 
> > Rob had earler mentioned about FEAT_FGT2 based trap control requirement for
> > FEAT_PMUv3p9 registers that are currently being used in kernel. The context
> > can be found here.
> > 
> > https://lore.kernel.org/all/20241216234251.GA629562-robh at kernel.org/
> > 
> > This series is based on v6.14-rc1
> > 
> > Changes in V2:
> > 
> > - Rebased on v6.14-rc1
> > - Updated tools sysreg patches with latest DDI0601 2024-12 definitions
> > - Updated document version as DDI0601 2024-12 in all commit messages
> > - Added latest tags from Rob Herring for the last patch
> 
> I know these have been applied already but, fwiw, patches 1-6 look correct
> when compared against the .xml:
> 
> Acked-by: Will Deacon <will at kernel.org>

Thanks Will.

> I presume Catalin will drop/replace the last patch.

I dropped it already, I'll queue the new one.

-- 
Catalin


From hkallweit1 at gmail.com  Sat Mar  1 03:16:23 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Sat, 1 Mar 2025 12:16:23 +0100
Subject: [PATCH net-next v2 0/8] net: phy: move PHY package code to its
 own source file
In-Reply-To: <8b290ccf-ca0c-422f-b853-6fc7af045f99@gmail.com>
References: <8b290ccf-ca0c-422f-b853-6fc7af045f99@gmail.com>
Message-ID: <6cb88f4b-15c9-4b6c-8226-63442b79492c@gmail.com>

On 28.02.2025 22:44, Heiner Kallweit wrote:
> This series contributes to cleaning up phylib by moving PHY package
> related code to its own source file.
> 
> v2:
> - rename the getters
> - add a new header file phylib.h, which is used by PHY drivers only
> 
> Heiner Kallweit (8):
>   net: phy: move PHY package code from phy_device.c to own source file
>   net: phy: add getters for public members in struct phy_package_shared
>   net: phy: qca807x: use new phy_package_shared getters
>   net: phy: micrel: use new phy_package_shared getters
>   net: phy: mediatek: use new phy_package_shared getters
>   net: phy: mscc: use new phy_package_shared getters
>   net: phy: move PHY package related code from phy.h to phy_package.c
>   net: phy: remove remaining PHY package related definitions from phy.h
> 
>  drivers/net/phy/Makefile              |   3 +-
>  drivers/net/phy/mediatek/mtk-ge-soc.c |   7 +-
>  drivers/net/phy/micrel.c              |   9 +-
>  drivers/net/phy/mscc/mscc_main.c      |   2 +
>  drivers/net/phy/mscc/mscc_ptp.c       |  14 +-
>  drivers/net/phy/phy-core.c            |   1 +
>  drivers/net/phy/phy_device.c          | 237 -----------------
>  drivers/net/phy/phy_package.c         | 350 ++++++++++++++++++++++++++
>  drivers/net/phy/phylib-internal.h     |   2 +
>  drivers/net/phy/phylib.h              |  28 +++
>  drivers/net/phy/qcom/qca807x.c        |  16 +-
>  include/linux/phy.h                   | 124 ---------
>  12 files changed, 409 insertions(+), 384 deletions(-)
>  create mode 100644 drivers/net/phy/phy_package.c
>  create mode 100644 drivers/net/phy/phylib.h
> 

CI is complaining about one issue in patch 7 which I have to correct.
Will wait for other feedback before resubmitting.
--
pw-bot: cr



From maz at kernel.org  Sat Mar  1 03:37:14 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 01 Mar 2025 11:37:14 +0000
Subject: [PATCH v15 04/15] irqchip/gic-v3-its: Add support for device tree msi-map and msi-mask
In-Reply-To: <20250211-ep-msi-v15-4-bcacc1f2b1a9@nxp.com>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
	<20250211-ep-msi-v15-4-bcacc1f2b1a9@nxp.com>
Message-ID: <86o6ylouc5.wl-maz@kernel.org>

On Tue, 11 Feb 2025 19:21:57 +0000,
Frank Li <Frank.Li at nxp.com> wrote:
> 
> Some platform devices create child devices dynamically and require the
> parent device's msi-map to map device IDs to actual sideband information.
> 
> A typical use case is using ITS as a PCIe Endpoint Controller(EPC)'s
> doorbell function, where PCI hosts send TLP memory writes to the EP
> controller. The EP controller converts these writes to AXI transactions
> and appends platform-specific sideband information.  See below figure.
> 
>                ??????????????????????????????????
>                ?                                ?
>                ?     PCI Endpoint Controller    ?
>                ?                                ?
>                ?  ???????   ???????     ??????? ?
>     PCI Bus    ?  ?     ?   ?     ?     ?     ? ?
>     ?????????? ?  ?Func1?   ?Func2? ... ?Func ? ?
>     TLP Memory ?  ?     ?   ?     ?     ?<n>  ? ?
>     Write Push ?  ?     ?   ?     ?     ?     ? ?
>     DoorBell   ?  ???????   ???????     ??????? ?
>                ?    ? ?        ?           ?    ?
>                ??????????????????????????????????
>         sideband    ? ? Address?           ?
>         information ? ? /Data  ?           ?
>                    ??????????????????????????
>                    ?    MSI Controller      ?
>                    ??????????????????????????
>

Please stop using these figures in commit messages. I don't think they
help, and they are not in consistent with the way the commit messages
are managed.

> EPC's DTS will provide such information by msi-map and msi-mask. A
> simplified dts as
> 
> pcie-ep at 10000000 {
> 	...
> 	msi-map = <0 &its 0xc 8>;
>                           ^^^ 0xc is implement defined sideband information,
> 			      which append to AXI write transaction.
> 	           ^ 0 is function index.

What does this sideband field represent? How is the ITS driver
supposed to use that data? Is it the full devid as presented to the
ITS? Something combined with the "function index"? Is the "function
index" a full RID, as defined in the documentation?

Also, msi-map is so far reserved to a PCIe RC, not this sort of wonky
contraption. This needs to be documented.

> 
> 	msi-mask = <0x7>
> }
> 
> Check msi-map if msi-parent missed to keep compatility with existed system.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
> change from v14 to v15
> - none
> 
> change from v13 to v14
> new patch
> ---
>  drivers/irqchip/irq-gic-v3-its-msi-parent.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> index e150365fbe892..6c7389bb84a4a 100644
> --- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> +++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> @@ -118,6 +118,14 @@ static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
>  		index++;
>  	} while (!ret);
>  
> +	if (ret) {
> +		struct device_node *np = NULL;
> +
> +		ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
> +		if (np)
> +			of_node_put(np);
> +	}
> +
>  	return ret;
>  }
>  
> 

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From peter.griffin at linaro.org  Sat Mar  1 03:43:19 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Sat, 01 Mar 2025 11:43:19 +0000
Subject: [PATCH v2 1/4] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
Message-ID: <20250301-pinctrl-fltcon-suspend-v2-1-a7eef9bb443b@linaro.org>

On gs101 SoC the fltcon0 (filter configuration 0) offset
isn't at a fixed offset like previous SoCs as the fltcon1
register only exists when there are more than 4 pins in the
bank.

Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
macros that take an additional fltcon_offs variable.

This can then be used in suspend/resume callbacks to
save and restore the fltcon0 and fltcon1 registers.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 98 +++++++++++++-------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       | 22 ++++++
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  1 +
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  4 ++
 4 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 3ea7106ce5ea..e28fe8177646 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1370,83 +1370,83 @@ const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = {
 
 /* pin banks of gs101 pin-controller (ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10),
-	EXYNOS850_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14),
-	EXYNOS850_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18),
-	EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08, 0x10),
+	GS101_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c, 0x18),
+	GS101_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10, 0x1c),
+	GS101_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14, 0x20),
+	GS101_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18, 0x28),
+	GS101_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c, 0x30),
 };
 
 /* pin banks of gs101 pin-controller (FAR_ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_far_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c, 0x14),
 };
 
 /* pin banks of gs101 pin-controller (GSACORE) */
 static const struct samsung_pin_bank_data gs101_pin_gsacore[] = {
-	EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04, 0x04),
+	GS101_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08, 0x0c),
 };
 
 /* pin banks of gs101 pin-controller (GSACTRL) */
 static const struct samsung_pin_bank_data gs101_pin_gsactrl[] = {
-	EXYNOS850_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00),
+	GS101_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00, 0x00),
 };
 
 /* pin banks of gs101 pin-controller (PERIC0) */
 static const struct samsung_pin_bank_data gs101_pin_peric0[] = {
-	EXYNOS850_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c),
+	GS101_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10, 0x14),
+	GS101_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18, 0x1c),
+	GS101_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20, 0x24),
+	GS101_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24, 0x28),
+	GS101_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28, 0x2c),
+	GS101_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c, 0x30),
+	GS101_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30, 0x34),
+	GS101_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34, 0x38),
+	GS101_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38, 0x3c),
+	GS101_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c, 0x40),
+	GS101_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40, 0x44),
+	GS101_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44, 0x48),
+	GS101_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48, 0x4c),
+	GS101_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c, 0x50),
 };
 
 /* pin banks of gs101 pin-controller (PERIC1) */
 static const struct samsung_pin_bank_data gs101_pin_peric1[] = {
-	EXYNOS850_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c),
+	GS101_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14, 0x1c),
+	GS101_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c, 0x28),
 };
 
 /* pin banks of gs101 pin-controller (HSI1) */
 static const struct samsung_pin_bank_data gs101_pin_hsi1[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04, 0x08),
 };
 
 /* pin banks of gs101 pin-controller (HSI2) */
 static const struct samsung_pin_bank_data gs101_pin_hsi2[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08, 0x0c),
 };
 
 static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 7b7ff7ffeb56..33df21d5c9d6 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -175,6 +175,28 @@
 		.name			= id				\
 	}
 
+#define GS101_PIN_BANK_EINTG(pins, reg, id, offs, fltcon_offs) \
+	{							\
+		.type			= &exynos850_bank_type_off,	\
+		.pctl_offset		= reg,			\
+		.nr_pins		= pins,			\
+		.eint_type		= EINT_TYPE_GPIO,	\
+		.eint_offset		= offs,			\
+		.eint_fltcon_offset	= fltcon_offs,		\
+		.name			= id			\
+	}
+
+#define GS101_PIN_BANK_EINTW(pins, reg, id, offs, fltcon_offs) \
+	{								\
+		.type			= &exynos850_bank_type_alive,	\
+		.pctl_offset		= reg,				\
+		.nr_pins		= pins,				\
+		.eint_type		= EINT_TYPE_WKUP,		\
+		.eint_offset		= offs,				\
+		.eint_fltcon_offset	= fltcon_offs,			\
+		.name			= id				\
+	}
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index cfced7afd4ca..963060920301 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1230,6 +1230,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
 		bank->eint_con_offset = bdata->eint_con_offset;
 		bank->eint_mask_offset = bdata->eint_mask_offset;
 		bank->eint_pend_offset = bdata->eint_pend_offset;
+		bank->eint_fltcon_offset = bdata->eint_fltcon_offset;
 		bank->name = bdata->name;
 
 		raw_spin_lock_init(&bank->slock);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index bb0689d52ea0..371e4f02bbfb 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -144,6 +144,7 @@ struct samsung_pin_bank_type {
  * @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  */
 struct samsung_pin_bank_data {
@@ -158,6 +159,7 @@ struct samsung_pin_bank_data {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 };
 
@@ -175,6 +177,7 @@ struct samsung_pin_bank_data {
  * @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  * @id: id of the bank, propagated to the pin range.
  * @pin_base: starting pin number of the bank.
@@ -201,6 +204,7 @@ struct samsung_pin_bank {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 	u32		id;
 

-- 
2.48.1.711.g2feabab25a-goog



From peter.griffin at linaro.org  Sat Mar  1 03:43:20 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Sat, 01 Mar 2025 11:43:20 +0000
Subject: [PATCH v2 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
Message-ID: <20250301-pinctrl-fltcon-suspend-v2-2-a7eef9bb443b@linaro.org>

gs101 needs it's own suspend/resume callbacks to use the newly
added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
registers. It also differs to previous SoCs in that fltcon1
register doesn't always exist for each bank.

exynosautov920 also has dedicated logic for using eint_con_offset
and eint_mask_offset for saving & restoring it's registers.

Refactor the existing platform specific suspend/resume callback
so that each SoC variant has their own callback containing the
SoC specific logic.

Additionally we now call drvdata->suspend() & drvdata->resume()
from within the loop that iterates the banks in
samsung_pinctrl_suspend() and samsung_pinctrl_resume().

This simplifies the logic, and allows us to remove the
clk_enable() and clk_disable() from the callbacks.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v1:
* Split code refactor & gs101 parts into separate patches (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |  28 ++--
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 201 ++++++++++---------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |   6 +-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  11 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |   8 +-
 5 files changed, 111 insertions(+), 143 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index e28fe8177646..57c98d2451b5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks0,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
 		.eint_wkup_init	= exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 		.retention_data	= &exynosautov920_retention_data,
 	}, {
 		/* pin-controller instance 1 AUD data */
@@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 3 HSI1 data */
 		.pin_banks	= exynosautov920_pin_banks3,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 4 HSI2 data */
 		.pin_banks	= exynosautov920_pin_banks4,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 5 HSI2UFS data */
 		.pin_banks	= exynosautov920_pin_banks5,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 6 PERIC0 data */
 		.pin_banks	= exynosautov920_pin_banks6,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 7 PERIC1 data */
 		.pin_banks	= exynosautov920_pin_banks7,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index ac6dc22b37c9..d65a9fba0781 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -761,153 +761,118 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	return 0;
 }
 
-static void exynos_pinctrl_suspend_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+static void exynos_set_wakeup(struct samsung_pin_bank *bank)
 {
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	const void __iomem *regs = bank->eint_base;
+	struct exynos_irq_chip *irq_chip = NULL;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_WKUP) {
+		if (bank->irq_chip) {
+			irq_chip = bank->irq_chip;
+			irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
+		}
 	}
-
-	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
-	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
-					    struct samsung_pin_bank *bank)
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
+	exynos_set_wakeup(bank);
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset);
+		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset + 4);
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		pr_debug("%s: save fltcon1 %#010x\n",
+			 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
 	}
-
-	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
-	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	struct exynos_irq_chip *irq_chip = NULL;
-	int i;
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
 
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_suspend_bank(drvdata, bank);
-			else
-				exynos_pinctrl_suspend_bank(drvdata, bank);
-		}
-		else if (bank->eint_type == EINT_TYPE_WKUP) {
-			if (!irq_chip) {
-				irq_chip = bank->irq_chip;
-				irq_chip->set_eint_wakeup_mask(drvdata,
-							       irq_chip);
-			}
-		}
+	exynos_set_wakeup(bank);
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + bank->pctl_offset +
+				       bank->eint_con_offset);
+		save->eint_mask = readl(regs + bank->pctl_offset +
+					bank->eint_mask_offset);
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
 	}
 }
 
-static void exynos_pinctrl_resume_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset), save->eint_fltcon0);
+		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset + 4),
+			       save->eint_fltcon1);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset);
+		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_ECON_OFFSET
-			+ bank->eint_offset), save->eint_con);
-	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset), save->eint_fltcon0);
-	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-			readl(regs + bank->irq_chip->eint_mask
-			+ bank->eint_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
 }
 
-static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
-					   struct samsung_pin_bank *bank)
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		/* exynosautov920 has eint_con_offset for all but one bank */
+		if (!bank->eint_con_offset)
+			exynos_pinctrl_resume(bank);
+
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
+			       save->eint_con);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset +
+			       bank->eint_mask_offset), save->eint_mask);
+
+		writel(save->eint_con,
+		       regs + bank->pctl_offset + bank->eint_con_offset);
+		writel(save->eint_mask,
+		       regs + bank->pctl_offset + bank->eint_mask_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
-	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-}
-
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	int i;
-
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_resume_bank(drvdata, bank);
-			else
-				exynos_pinctrl_resume_bank(drvdata, bank);
-		}
 }
 
 static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 33df21d5c9d6..35c2bc4ea488 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -221,8 +221,10 @@ struct exynos_muxed_weint_data {
 
 int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
 int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 963060920301..375634d8cc79 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->suspend)
+			drvdata->suspend(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
@@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 
 	clk_disable(drvdata->pclk);
 
-	if (drvdata->suspend)
-		drvdata->suspend(drvdata);
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
 		drvdata->retention_ctrl->enable(drvdata);
 
@@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		return ret;
 	}
 
-	if (drvdata->resume)
-		drvdata->resume(drvdata);
-
 	for (i = 0; i < drvdata->nr_banks; i++) {
 		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
 		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
@@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->resume)
+			drvdata->resume(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 371e4f02bbfb..e939e5bb0347 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
 	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
 	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
 	void		(*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
-	void		(*suspend)(struct samsung_pinctrl_drv_data *);
-	void		(*resume)(struct samsung_pinctrl_drv_data *);
+	void		(*suspend)(struct samsung_pin_bank *bank);
+	void		(*resume)(struct samsung_pin_bank *bank);
 };
 
 /**
@@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
 
 	struct samsung_retention_ctrl	*retention_ctrl;
 
-	void (*suspend)(struct samsung_pinctrl_drv_data *);
-	void (*resume)(struct samsung_pinctrl_drv_data *);
+	void (*suspend)(struct samsung_pin_bank *bank);
+	void (*resume)(struct samsung_pin_bank *bank);
 };
 
 /**

-- 
2.48.1.711.g2feabab25a-goog



From peter.griffin at linaro.org  Sat Mar  1 03:43:21 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Sat, 01 Mar 2025 11:43:21 +0000
Subject: [PATCH v2 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
Message-ID: <20250301-pinctrl-fltcon-suspend-v2-3-a7eef9bb443b@linaro.org>

gs101 differs to other SoCs in that fltcon1 register doesn't
always exist. Additionally the offset of fltcon0 is not fixed
and needs to use the newly added eint_fltcon_offset variable.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 71 ++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  2 +
 3 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 57c98d2451b5..fca447ebc5f5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1455,15 +1455,15 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (FAR_ALIVE) */
 		.pin_banks	= gs101_pin_far_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_far_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (GSACORE) */
 		.pin_banks	= gs101_pin_gsacore,
@@ -1477,29 +1477,29 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_peric0,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric0),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (PERIC1) */
 		.pin_banks	= gs101_pin_peric1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume	= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI1) */
 		.pin_banks	= gs101_pin_hsi1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI2) */
 		.pin_banks	= gs101_pin_hsi2,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi2),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index d65a9fba0781..ddc7245ec2e5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -801,6 +801,41 @@ void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 	}
 }
 
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
+
+	exynos_set_wakeup(bank);
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET +
+					   bank->eint_fltcon_offset);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			save->eint_fltcon1 = readl(regs +
+						EXYNOS_GPIO_EFLTCON_OFFSET +
+						bank->eint_fltcon_offset + 4);
+
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		if (bank->nr_pins > 4)
+			pr_debug("%s: save fltcon1 %#010x\n",
+				 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	}
+}
+
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
@@ -820,6 +855,42 @@ void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 	}
 }
 
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+
+	void __iomem *regs = bank->eint_base;
+	void __iomem *eint_fltcfg0 = regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		     + bank->eint_fltcon_offset;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(eint_fltcfg0), save->eint_fltcon0);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4) {
+			pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+				 readl(eint_fltcfg0 + 4), save->eint_fltcon1);
+		}
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, eint_fltcfg0);
+
+		if (bank->nr_pins > 4)
+			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
+	}
+}
+
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 35c2bc4ea488..773f161a82a3 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -225,6 +225,8 @@ void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank);
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);

-- 
2.48.1.711.g2feabab25a-goog



From peter.griffin at linaro.org  Sat Mar  1 03:43:22 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Sat, 01 Mar 2025 11:43:22 +0000
Subject: [PATCH v2 4/4] pinctrl: samsung: Add filter selection support for
 alive bank on gs101
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
Message-ID: <20250301-pinctrl-fltcon-suspend-v2-4-a7eef9bb443b@linaro.org>

Newer Exynos based SoCs have a filter selection bitfield in the filter
configuration registers on alive bank pins. This allows the selection of
a digital or analog delay filter for each pin. Add support for selecting
and enabling the filter.

On suspend we set the analog filter to all pins in the bank (as the
digital filter relies on a clock). On resume the digital filter is
reapplied to all pins in the bank. The digital filter is working via
a clock and has an adjustable filter delay flt_width bitfield, whereas
the analog filter uses a fixed delay.

The filter determines to what extent signal fluctuations received through
the pad are considered glitches.

The code path can be exercised using
echo mem > /sys/power/state
And then wake the device using a eint gpio

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---

Changes since v1:
* Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
* Move filter config comment to header (Andre)
* Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
* Remove misleading old comment (Andre)
* Refactor exynos_eint_update_flt_reg() into a loop (Andre)

Note: this patch was previously sent as part of the initial gs101/ Pixel 6
series and was dropped in v6. This new version incorporates the review
feedback from Sam Protsenko here in v5.

Link: https://lore.kernel.org/all/20231201160925.3136868-1-peter.griffin at linaro.org/T/#m79ced98939e895c840d812c8b4c2b3f33ce604c8

Changes since previous version
* Drop fltcon_type enum and use bool eint_flt_selectable (Sam)
* Refactor and add exynos_eint_update_flt_reg() (Sam)
* Rename function to exynos_eint_set_filter() for easier readability (Sam)
* Remove comments and `if bank->fltcon_type != FLT_DEFAULT)` checks and indentation (Sam)
---
 drivers/pinctrl/samsung/pinctrl-exynos.c | 35 ++++++++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h | 21 +++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index ddc7245ec2e5..4c467651b034 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -369,6 +369,39 @@ struct exynos_eint_gpio_save {
 	u32 eint_mask;
 };
 
+static void exynos_eint_update_flt_reg(void __iomem *reg, int cnt, int con)
+{
+	unsigned int val, shift;
+	int i;
+
+	val = readl(reg);
+	for (i = 0; i < cnt; i++) {
+		shift = i * EXYNOS_FLTCON_LEN;
+		val |= con << shift;
+	}
+	writel(val, reg);
+}
+
+/*
+ * Set the desired filter (digital or analog delay) and enable it to
+ * every pin in the bank. Note the filter selection bitfield is only
+ * found on alive banks. The filter determines to what extent signal
+ * fluctuations received through the pad are considered glitches.
+ */
+static void exynos_eint_set_filter(struct samsung_pin_bank *bank, int filter)
+{
+	unsigned int off = EXYNOS_GPIO_EFLTCON_OFFSET + bank->eint_fltcon_offset;
+	void __iomem *reg = bank->drvdata->virt_base + off;
+	unsigned int con = EXYNOS_FLTCON_EN | filter;
+
+	if (bank->eint_type != EINT_TYPE_WKUP)
+		return;
+
+	for (int n = 0; n < bank->nr_pins; n += 4)
+		exynos_eint_update_flt_reg(reg + n,
+					   min(bank->nr_pins - n, 4), con);
+}
+
 /*
  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
  * @d: driver data of samsung pinctrl driver.
@@ -834,6 +867,7 @@ void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
 		pr_debug("%s: save    mask %#010x\n",
 			 bank->name, save->eint_mask);
 	}
+	exynos_eint_set_filter(bank, EXYNOS_FLTCON_ANALOG);
 }
 
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
@@ -889,6 +923,7 @@ void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
 		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 		       + bank->eint_offset);
 	}
+	exynos_eint_set_filter(bank, EXYNOS_FLTCON_DIGITAL);
 }
 
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 773f161a82a3..203d4b76a956 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -52,6 +52,27 @@
 #define EXYNOS_EINT_MAX_PER_BANK	8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
+/*
+ * EINT filter configuration register (on alive banks) has
+ * the following layout.
+ *
+ * BitfieldName[PinNum][Bit:Bit]
+ * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24]
+ * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16]
+ * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8]
+ * FLT_EN[0][7]  FLT_SEL[0][6]  FLT_WIDTH[0][5:0]
+ *
+ * FLT_EN	0x0 = Disable, 0x1=Enable
+ * FLT_SEL	0x0 = Analog delay filter, 0x1 Digital filter (clock count)
+ * FLT_WIDTH	Filtering width. Valid when FLT_SEL is 0x1
+ */
+
+#define EXYNOS_FLTCON_EN		BIT(7)
+#define EXYNOS_FLTCON_DIGITAL		BIT(6)
+#define EXYNOS_FLTCON_ANALOG		(0 << 6)
+#define EXYNOS_FLTCON_MASK		GENMASK(7, 0)
+#define EXYNOS_FLTCON_LEN		8
+
 #define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
 	{						\
 		.type		= &bank_type_off,	\

-- 
2.48.1.711.g2feabab25a-goog



From maz at kernel.org  Sat Mar  1 03:44:50 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 01 Mar 2025 11:44:50 +0000
Subject: [PATCH v15 07/15] PCI: endpoint: pci-ep-msi: Add MSI address/data pair mutable check
In-Reply-To: <20250211-ep-msi-v15-7-bcacc1f2b1a9@nxp.com>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
	<20250211-ep-msi-v15-7-bcacc1f2b1a9@nxp.com>
Message-ID: <86mse5otzh.wl-maz@kernel.org>

On Tue, 11 Feb 2025 19:22:00 +0000,
Frank Li <Frank.Li at nxp.com> wrote:
> 
> Some MSI controller change address/data pair when irq_set_affinity().
> Current PCI endpoint can't support this type MSI controller. So add flag
> MSI_FLAG_MUTABLE in include/linux/msi.h and check it when allocate
> doorbell.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
> change from v14 to v15
> - none
> 
> change from  v13 to v14
> - bring v10 back
> 
> Change from v9 to v10
> - new patch
> ---
>  drivers/pci/endpoint/pci-ep-msi.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/pci/endpoint/pci-ep-msi.c b/drivers/pci/endpoint/pci-ep-msi.c
> index 549b55b864d0e..c0e2d806ee658 100644
> --- a/drivers/pci/endpoint/pci-ep-msi.c
> +++ b/drivers/pci/endpoint/pci-ep-msi.c
> @@ -44,6 +44,14 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)
>  
>  	dev_set_msi_domain(dev, dom);
>  
> +	if (!irq_domain_is_msi_parent(dom))
> +		return -EINVAL;
> +
> +	if (!irq_domain_is_msi_immutable(dom)) {
> +		dev_err(dev, "Can't support mutable address/data pair MSI controller\n");
> +		return -EINVAL;
> +	}
> +
>  	msg = kcalloc(num_db, sizeof(struct pci_epf_doorbell_msg), GFP_KERNEL);
>  	if (!msg)
>  		return -ENOMEM;
> 

I really don't think this brings much to the table. These systems are
not built by picking up random bits that can be put together by hand.
They are integrated in an SoC, and I can't imagine that the MSI
controller is picked randomly.

So my conclusion is that this is either *designed* to work, or it
doesn't exist, and that this code is just dead code.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From peter.griffin at linaro.org  Sat Mar  1 03:43:18 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Sat, 01 Mar 2025 11:43:18 +0000
Subject: [PATCH v2 0/4] samsung: pinctrl: Add support for
 eint_fltcon_offset and filter selection on gs101
Message-ID: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>

Hi folks,

This series fixes support for correctly saving and restoring fltcon0
and fltcon1 registers on gs101 for non-alive banks where the fltcon
register offset is not at a fixed offset (unlike previous SoCs).
This is done by adding a eint_fltcon_offset and providing GS101
specific pin macros that take an additional parameter (similar to
how exynosautov920 handles it's eint_con_offset).

Additionally the SoC specific suspend and resume callbacks are
re-factored so that each SoC variant has it's own callback containing
the peculiarities for that SoC.

Finally support for filter selection on alive banks is added, this is
currently only enabled for gs101. The code path can be excercised using
`echo mem > /sys/power/state`

regards,

Peter

To: Krzysztof Kozlowski <krzk at kernel.org>
To: Sylwester Nawrocki <s.nawrocki at samsung.com>
To: Alim Akhtar <alim.akhtar at samsung.com>
To: Linus Walleij <linus.walleij at linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-gpio at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: andre.draszik at linaro.org
Cc: tudor.ambarus at linaro.org
Cc: willmcvicker at google.com
Cc: semen.protsenko at linaro.org
Cc: kernel-team at android.com
Cc: jaewon02.kim at samsung.com

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes in v2:
- Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
- Move filter config register comment to header file (Andre)
- Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
- Remove misleading old comment (Andre)
- Refactor exynos_eint_update_flt_reg() into a loop (Andre)
- Split refactor of suspend/resume callbacks & gs101 parts into separate patches (Andre)
- Link to v1: https://lore.kernel.org/r/20250120-pinctrl-fltcon-suspend-v1-0-e77900b2a854 at linaro.org

---
Peter Griffin (4):
      pinctrl: samsung: add support for eint_fltcon_offset
      pinctrl: samsung: add dedicated SoC eint suspend/resume callbacks
      pinctrl: samsung: add gs101 specific eint suspend/resume callbacks
      pinctrl: samsung: Add filter selection support for alive bank on gs101

 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 150 ++++++-------
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 293 +++++++++++++++----------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  51 ++++-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  12 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  12 +-
 5 files changed, 321 insertions(+), 197 deletions(-)
---
base-commit: f7da3699c901aea6a009d38116d24c67a4c9662e
change-id: 20250120-pinctrl-fltcon-suspend-2333a137c4d4

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From dario.binacchi at amarulasolutions.com  Sat Mar  1 03:51:09 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Sat,  1 Mar 2025 12:51:09 +0100
Subject: [PATCH] ARM: dts: stm32: use IRQ_TYPE_EDGE_FALLING on stm32mp157c-dk2
Message-ID: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com>

Replace the number 2 with the appropriate numerical constant defined in
dt-bindings/interrupt-controller/irq.h.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

 arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
index 5f9c0160a9c4..dcf17c493022 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
@@ -11,6 +11,7 @@
 #include "stm32mp15-pinctrl.dtsi"
 #include "stm32mp15xxac-pinctrl.dtsi"
 #include "stm32mp15xx-dkx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
@@ -67,7 +68,7 @@ &i2c1 {
 	touchscreen at 38 {
 		compatible = "focaltech,ft6236";
 		reg = <0x38>;
-		interrupts = <2 2>;
+		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
 		interrupt-parent = <&gpiof>;
 		touchscreen-size-x = <480>;
 		touchscreen-size-y = <800>;
-- 
2.43.0



From maz at kernel.org  Sat Mar  1 04:02:09 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 01 Mar 2025 12:02:09 +0000
Subject: [PATCH v15 00/15] PCI: EP: Add RC-to-EP doorbell with platform MSI controller
In-Reply-To: <Z7eKBsxrmthtElpz@lizhi-Precision-Tower-5810>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
	<Z7eKBsxrmthtElpz@lizhi-Precision-Tower-5810>
Message-ID: <86ldtpot6m.wl-maz@kernel.org>

On Thu, 20 Feb 2025 20:01:10 +0000,
Frank Li <Frank.li at nxp.com> wrote:
> 
> On Tue, Feb 11, 2025 at 02:21:53PM -0500, Frank Li wrote:
> 
> Thomas Gleixner and Marc Zyngier:
> 
> 	Do you have any comments about irq/msi part?

It certainly looks better and less invasive than the previous
incarnations. Things to fix:

- Documentation: the msi-map property usage is undefined outside of a
  PCIe RC, and the way you describe its use is so vague I read
  anything in it. Please update
  Documentation/devicetree/bindings/pci/pci-msi.txt to reflect the new
  use case.

- This IMMUTABLE thing serves no purpose, because you don't randomly
  plug this end-point block on any MSI controller. They come as part
  of an SoC.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From cki-project at redhat.com  Sat Mar  1 04:12:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Sat, 01 Mar 2025 12:12:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc4,
 upstream-arm-next, e056da87)
Message-ID: <45245.125030107120700279@us-mta-223.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1694600197

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1694600197-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From maz at kernel.org  Sat Mar  1 04:17:47 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 01 Mar 2025 12:17:47 +0000
Subject: [PATCH v15 01/15] platform-msi: Add msi_remove_device_irq_domain() in platform_device_msi_free_irqs_all()
In-Reply-To: <20250211-ep-msi-v15-1-bcacc1f2b1a9@nxp.com>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
	<20250211-ep-msi-v15-1-bcacc1f2b1a9@nxp.com>
Message-ID: <86jz99osgk.wl-maz@kernel.org>

On Tue, 11 Feb 2025 19:21:54 +0000,
Frank Li <Frank.Li at nxp.com> wrote:
> 
> The follow steps trigger kernel dump warning and
> platform_device_msi_init_and_alloc_irqs() return false.
> 
> 1: platform_device_msi_init_and_alloc_irqs();
> 2: platform_device_msi_free_irqs_all();
> 3: platform_device_msi_init_and_alloc_irqs();
> 
> [   76.713677] WARNING: CPU: 3 PID: 134 at kernel/irq/msi.c:1028 msi_create_device_irq_domain+0x1bc/0x22c
> [   76.723010] Modules linked in:
> [   76.726082] CPU: 3 UID: 0 PID: 134 Comm: kworker/3:1H Not tainted 6.13.0-rc1-00015-gd60b98003b43-dirty #57
> [   76.735741] Hardware name: NXP i.MX95 19X19 board (DT)
> [   76.740883] Workqueue: kpcitest pci_epf_test_cmd_handler
> [   76.746212] pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [   76.753172] pc : msi_create_device_irq_domain+0x1bc/0x22c
> [   76.758586] lr : msi_create_device_irq_domain+0x104/0x22c
> [   76.763988] sp : ffff800083f43be0
> [   76.767313] x29: ffff800083f43be0 x28: 0000000000000000 x27: ffff8000827a7000
> [   76.774466] x26: ffff00008085f400 x25: ffff00008000b180 x24: ffff000080fc6410
> [   76.781624] x23: ffff000085704cc0 x22: ffff8000811c8828 x21: ffff000085704cc0
> [   76.788774] x20: ffff000082814000 x19: 0000000000000000 x18: ffffffffffffffff
> [   76.795933] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
> [   76.803083] x14: 0000000000000000 x13: 0000000f00000000 x12: 0000000000000000
> [   76.810233] x11: 0000000000000000 x10: 000000000000002d x9 : ffff800083f43ba0
> [   76.817383] x8 : 00000000ffffffff x7 : 0000000000000019 x6 : ffff0000857e443a
> [   76.824533] x5 : 0000000000000000 x4 : ffffffffffffffff x3 : ffff000085704ce8
> [   76.831683] x2 : ffff000080835640 x1 : 0000000000000213 x0 : ffff0000877189c0
> [   76.838840] Call trace:
> [   76.841287]  msi_create_device_irq_domain+0x1bc/0x22c (P)
> [   76.846701]  msi_create_device_irq_domain+0x104/0x22c (L)
> [   76.852118]  platform_device_msi_init_and_alloc_irqs+0x6c/0xb8
> 
> Do below two things in platform_device_msi_init_and_alloc_irqs().
> - msi_create_device_irq_domain()
> - msi_domain_alloc_irqs_range()
> 
> But only call msi_domain_free_irqs_all() in
> platform_device_msi_free_irqs_all(), which missed call
> msi_remove_device_irq_domain(). This cause above kernel dump when call
> platform_device_msi_init_and_alloc_irqs() again.

I don't think this commit message makes much sense, and doesn't
explain the essential problem, which is the lack of symmetry. I'd
suggest something like:

"platform_device_msi_init_and_alloc_irqs() performs two tasks:
allocating the MSI domain for a platform device, and allocate a number
of MSIs in that domain.

platform_device_msi_free_irqs_all() only frees the MSIs, and leaves
the MSI domain alive.

Given that platform_device_msi_init_and_alloc_irqs() is the sole tool
a platform device has to allocate platform MSIs, it would make sense
for platform_device_msi_free_irqs_all() to teardown the MSI domain at
the same time as the MSIs.

This also avoids warnings and unexpected behaviours when a driver
repeatedly allocates and frees MSIs."

With that:

Acked-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From andyshrk at 163.com  Sat Mar  1 04:24:34 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sat, 1 Mar 2025 20:24:34 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <AC3DE87B-64B1-4C34-8E1B-3900E2C53AA3@gmail.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <AC3DE87B-64B1-4C34-8E1B-3900E2C53AA3@gmail.com>
Message-ID: <7b8767fc.3607.19551aa5f74.Coremail.andyshrk@163.com>


Hi Piotr,

? 2025-03-01 04:30:33?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 23 lut 2025, o godz. 12:30:
>> 
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> 
>> There are two DW DPTX based DisplayPort Controller on rk3588 which
>> are compliant with the DisplayPort Specification Version 1.4 with
>> the following features:
>> 
>> * DisplayPort 1.4a
>> * Main Link: 1/2/4 lanes
>> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> * AUX channel 1Mbps
>> * Single Stream Transport(SST)
>> * Multistream Transport (MST)
>> *?Type-C support (alternate mode)
>> * HDCP 2.2, HDCP 1.3
>> * Supports up to 8/10 bits per color component
>> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> * Pixel clock up to 594MHz
>> * I2S, SPDIF audio interface
>> 
>> The current version of this patch series only supports basic display outputs.
>> I conducted tests in 1080p and 4K at 60 YCbCr4:2:0 modes; the ALT/Type-C mode
>> hasn't been tested yet, but I suspect it will likely work. HDCP and audio
>> features remain unimplemented. For RK3588, it's only support SST, while in
>> the upcoming RK3576, it can support MST output.
>> 
>
>Andy,
>
>Is tis series enough to get usbc1/dp1 working as video output ?
>(assuming i will add necessary code in dt) 
>
>rock5-itx has second hdmi port using usbc1/dp1 lanes 2,3 to ra620 dp->hdmi converter
>
>is it worth to play with this or it is too early?

I think you could give it a try if it using the Standard DP?non-ALT mode? port for output. 
Since I don't currently have a development board with DP1 output available, I haven't been
able to test it yet. As for the Type-C Alternate Mode output, some patches are still required 
I'll  send it with V2 tomorrow or next week.
Feel free to let me know if If you encounter any issues?


> 

From towinchenmi at gmail.com  Sat Mar  1 04:32:10 2025
From: towinchenmi at gmail.com (Nick Chan)
Date: Sat, 1 Mar 2025 20:32:10 +0800
Subject: [PATCH 0/9] arm64: dts: apple: Add CPU cache information for
 Apple A7-A11, T2 SoCs
In-Reply-To: <4670e5f8-2a92-46bd-8faa-dd3774517f3e@app.fastmail.com>
References: <20250220-caches-v1-0-2c7011097768@gmail.com>
 <4670e5f8-2a92-46bd-8faa-dd3774517f3e@app.fastmail.com>
Message-ID: <83130117-509a-45ff-bf96-26beb77246e1@gmail.com>


Sven Peter ? 2025/3/1 ??7:11 ??:
> Hi,
>
> On Thu, Feb 20, 2025, at 13:21, Nick Chan wrote:
>> Add CPU cache information for Apple A7-A11, T2 SoCs. On Apple
>> A10 (T8010), A10X (T8011), T2 (T8012), only the caches in one of the
>> CPU clusters can be used due to the "Apple Fusion Architecture"
>> big.LITTLE switcher. The values for the P-cluster is used in this
>> case.
> So this means that the cache information will be "wrong" when the CPU
> is in the lower power states and only correct for the higher ones?
> I'm not familiar with how these values are used; are you and do you
> know if this will have any weird or unexpected effects?
> Would it be better to use the cache size for the lower rather than
> the higher states or does this not matter much?
The information in the device tree is only used for reporting cache sizes in /sys/devices/system/cpu.
It represents the physical cache size which may not be the same as the architecturally visible cache
size. Cache operations in the kernel consult ccsidr_el1 and csselr_el1, so it should be fine.
>
>
>
> Best,
>
>
> Sven
Nick Chan



From linux at treblig.org  Sat Mar  1 04:35:56 2025
From: linux at treblig.org (Dr. David Alan Gilbert)
Date: Sat, 1 Mar 2025 12:35:56 +0000
Subject: [PATCH 0/7] gpu: ipu-v3: Remove unused functions
In-Reply-To: <174082343297.2941786.11452976094065423321.b4-ty@linaro.org>
References: <20241226022752.219399-1-linux@treblig.org>
 <174082343297.2941786.11452976094065423321.b4-ty@linaro.org>
Message-ID: <Z8L_LOkOfRXUAKN6@gallifrey>

* Dmitry Baryshkov (dmitry.baryshkov at linaro.org) wrote:
> On Thu, 26 Dec 2024 02:27:45 +0000, linux at treblig.org wrote:
> > From: "Dr. David Alan Gilbert" <linux at treblig.org>
> > 
> > Hi,
> >   This set removes a bunch of functions in ipu-v3 that
> > have been unused for a long time (since 2012-2017).
> > 
> >   No changes to functions are made, just full deletions.
> > 
> > [...]
> 
> Applied to drm-misc-next, thanks!

Thanks!

Dave

> [1/7] gpu: ipu-v3: ipu-ic: Remove unused ipu_ic_task_graphics_init
>       commit: 16e3bf497fb2d379f3d461fa0c85d14de0a3d183
> [2/7] gpu: ipu-v3: Remove unused ipu_rot_mode_to_degrees
>       commit: a52ba18c254c0a3819e632e6371554f1c6f5bd16
> [3/7] gpu: ipu-v3: Remove unused ipu_idmac_channel_busy
>       commit: 4f9c64e95c3510f4a5192bd401de5611c1dd5637
> [4/7] gpu: ipu-v3: Remove unused ipu_image_convert_* functions
>       commit: 96e9d754b35e87a5be2de7dce3c810ffdd769c84
> [5/7] gpu: ipu-v3: Remove unused ipu_vdi_unsetup
>       commit: 27985c86e283e1e5ac8a9809f189f03643a6f5f2
> [6/7] gpu: ipu-v3: ipu-csi: Remove unused functions
>       commit: c687c3147d5de801ed835b077802b68fe85d8a3d
> [7/7] gpu: ipu-v3 ipu-cpmem: Remove unused functions
>       commit: 2800028d5bdee8e9a3cda2fec782dadc32225d8d
> 
> Best regards,
> -- 
> With best wishes
> Dmitry
> 
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


From andyshrk at 163.com  Sat Mar  1 04:38:01 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sat, 1 Mar 2025 20:38:01 +0800 (CST)
Subject: [PATCH v1 1/1] arm64: dts: rockchip: Add USB-C support to ROCK
 5B
In-Reply-To: <20241210163615.120594-1-sebastian.reichel@collabora.com>
References: <20241210163615.120594-1-sebastian.reichel@collabora.com>
Message-ID: <12e97e18.367e.19551b6aea2.Coremail.andyshrk@163.com>


Hi Sebastian,
 
At 2024-12-11 00:36:01, "Sebastian Reichel" <sebastian.reichel at collabora.com> wrote:
>Add hardware description for the USB-C port in the Radxa Rock 5 Model B.
>This describes the OHCI, EHCI and XHCI USB parts, but not yet the
>DisplayPort AltMode (bindings are not yet upstream).
>
>The fusb302 node is marked with status "fail", since the board is usually
>powered through the USB-C port. Handling of errors can result in hard
>resets, which removed the bus power for some time resulting in a board
>reset.
>
>The main problem is that devices are supposed to interact with the
>power-supply within 5 seconds after the plug event according to the
>USB PD specification. This is more or less impossible to achieve when
>the kernel is the first software communicating with the power-supply.
>
>Recent U-Boot (v2025.01) will start doing USB-PD communication, which
>solves this issue. Upstream U-Boot doing USB-PD communication will also
>set the fusb302 node status to "okay". That way booting a kernel with
>the updated DT on an old U-Boot avoids a reset loop.

    Do you have any plans to continue working on this patch?
    I've been working on enabling the DP Alt Mode output recently
   and think the Rock 5b  is a good starting point?
     
>
>Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
>---
> .../boot/dts/rockchip/rk3588-rock-5b.dts      | 121 ++++++++++++++++++
> 1 file changed, 121 insertions(+)
>
>diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>index d597112f1d5b..cb5990df6ccb 100644
>--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>@@ -5,6 +5,7 @@
> #include <dt-bindings/gpio/gpio.h>
> #include <dt-bindings/leds/common.h>
> #include <dt-bindings/soc/rockchip,vop2.h>
>+#include <dt-bindings/usb/pd.h>
> #include "rk3588.dtsi"
> 
> / {
>@@ -84,6 +85,15 @@ rfkill-bt {
> 		shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
> 	};
> 
>+	vcc12v_dcin: regulator-vcc12v-dcin {
>+		compatible = "regulator-fixed";
>+		regulator-name = "vcc12v_dcin";
>+		regulator-always-on;
>+		regulator-boot-on;
>+		regulator-min-microvolt = <12000000>;
>+		regulator-max-microvolt = <12000000>;
>+	};
>+
> 	vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
> 		compatible = "regulator-fixed";
> 		enable-active-high;
>@@ -142,6 +152,7 @@ vcc5v0_sys: regulator-vcc5v0-sys {
> 		regulator-boot-on;
> 		regulator-min-microvolt = <5000000>;
> 		regulator-max-microvolt = <5000000>;
>+		vin-supply = <&vcc12v_dcin>;
> 	};
> 
> 	vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
>@@ -264,6 +275,67 @@ regulator-state-mem {
> 	};
> };
> 
>+&i2c4 {
>+	pinctrl-names = "default";
>+	pinctrl-0 = <&i2c4m1_xfer>;
>+	status = "okay";
>+
>+	usbc0: usb-typec at 22 {
>+		compatible = "fcs,fusb302";
>+		reg = <0x22>;
>+		interrupt-parent = <&gpio3>;
>+		interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
>+		pinctrl-names = "default";
>+		pinctrl-0 = <&usbc0_int>;
>+		vbus-supply = <&vcc12v_dcin>;
>+		/*
>+		 * When the board is starting to send power-delivery messages
>+		 * too late (5 seconds according to the specification), the
>+		 * power-supply reacts with a hard-reset. That removes the
>+		 * power from VBUS for some time, which resets te whole board.
>+		 */
>+		status = "fail";
>+
>+		usb_con: connector {
>+			compatible = "usb-c-connector";
>+			label = "USB-C";
>+			data-role = "dual";
>+			power-role = "sink";
>+			try-power-role = "sink";
>+			op-sink-microwatt = <1000000>;
>+			sink-pdos =
>+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>,
>+				<PDO_VAR(5000, 20000, 5000)>;
>+
>+			ports {
>+				#address-cells = <1>;
>+				#size-cells = <0>;
>+
>+				port at 0 {
>+					reg = <0>;
>+					usbc0_role_sw: endpoint {
>+						remote-endpoint = <&dwc3_0_role_switch>;
>+					};
>+				};
>+
>+				port at 1 {
>+					reg = <1>;
>+					usbc0_orien_sw: endpoint {
>+						remote-endpoint = <&usbdp_phy0_orientation_switch>;
>+					};
>+				};
>+
>+				port at 2 {
>+					reg = <2>;
>+					dp_altmode_mux: endpoint {
>+						remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
>+					};
>+				};
>+			};
>+		};
>+	};
>+};
>+
> &i2c6 {
> 	status = "okay";
> 
>@@ -423,6 +495,10 @@ usb {
> 		vcc5v0_host_en: vcc5v0-host-en {
> 			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
> 		};
>+
>+		usbc0_int: usbc0-int {
>+			rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
>+		};
> 	};
> };
> 
>@@ -835,6 +911,14 @@ &uart2 {
> 	status = "okay";
> };
> 
>+&u2phy0 {
>+	status = "okay";
>+};
>+
>+&u2phy0_otg {
>+	status = "okay";
>+};
>+
> &u2phy1 {
> 	status = "okay";
> };
>@@ -866,6 +950,29 @@ &usbdp_phy1 {
> 	status = "okay";
> };
> 
>+&usbdp_phy0 {
>+	mode-switch;
>+	orientation-switch;
>+	sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
>+	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
>+	status = "okay";
>+
>+	port {
>+		#address-cells = <1>;
>+		#size-cells = <0>;
>+
>+		usbdp_phy0_orientation_switch: endpoint at 0 {
>+			reg = <0>;
>+			remote-endpoint = <&usbc0_orien_sw>;
>+		};
>+
>+		usbdp_phy0_dp_altmode_mux: endpoint at 1 {
>+			reg = <1>;
>+			remote-endpoint = <&dp_altmode_mux>;
>+		};
>+	};
>+};
>+
> &usb_host0_ehci {
> 	status = "okay";
> };
>@@ -874,6 +981,20 @@ &usb_host0_ohci {
> 	status = "okay";
> };
> 
>+&usb_host0_xhci {
>+	usb-role-switch;
>+	status = "okay";
>+
>+	port {
>+		#address-cells = <1>;
>+		#size-cells = <0>;
>+
>+		dwc3_0_role_switch: endpoint {
>+			remote-endpoint = <&usbc0_role_sw>;
>+		};
>+	};
>+};
>+
> &usb_host1_ehci {
> 	status = "okay";
> };
>-- 
>2.45.2
>

From jonas at kwiboo.se  Sat Mar  1 04:47:47 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 1 Mar 2025 13:47:47 +0100
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for
 RK3528
In-Reply-To: <20250301104749.36423-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104749.36423-1-ziyao@disroot.org>
Message-ID: <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se>

Hi,

On 2025-03-01 11:47, Yao Zi wrote:
> RK3528 features two SDIO controllers and one SD/MMC controller, describe
> them in devicetree. Since their sample and drive clocks are located in
> the VO and VPU GRFs, corresponding syscons are added to make these
> clocks available.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 5b334690356a..078c97fa1d9f 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -7,6 +7,7 @@
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>  #include <dt-bindings/interrupt-controller/irq.h>
>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
> +#include <dt-bindings/reset/rockchip,rk3528-cru.h>
>  
>  / {
>  	compatible = "rockchip,rk3528";
> @@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
>  			#interrupt-cells = <3>;
>  		};
>  
> +		vpu_grf: syscon at ff340000 {
> +			compatible = "rockchip,rk3528-vpu-grf", "syscon";

vpu_grf is also used for gmac1, so should possible be a "syscon",
"simple-mfd", or have I misunderstood when to use simple-mfd ?

> +			reg = <0x0 0xff340000 0x0 0x8000>;
> +		};
> +
> +		vo_grf: syscon at ff360000 {
> +			compatible = "rockchip,rk3528-vo-grf", "syscon";

similar here, vo_grf is also used for gmac0.

> +			reg = <0x0 0xff360000 0x0 0x10000>;
> +		};
> +
>  		cru: clock-controller at ff4a0000 {
>  			compatible = "rockchip,rk3528-cru";
>  			reg = <0x0 0xff4a0000 0x0 0x30000>;
> @@ -251,5 +262,56 @@ uart7: serial at ffa28000 {
>  			reg-shift = <2>;
>  			status = "disabled";
>  		};
> +
> +		sdio0: mmc at ffc10000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc10000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO0>,
> +				 <&cru CCLK_SRC_SDIO0>,
> +				 <&cru SCLK_SDIO0_DRV>,
> +				 <&cru SCLK_SDIO0_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			resets = <&cru SRST_H_SDIO0>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};
> +
> +		sdio1: mmc at ffc20000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc20000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO1>,
> +				 <&cru CCLK_SRC_SDIO1>,
> +				 <&cru SCLK_SDIO1_DRV>,
> +				 <&cru SCLK_SDIO1_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			resets = <&cru SRST_H_SDIO1>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};
> +
> +		sdmmc: mmc at ffc30000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc30000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDMMC0>,
> +				 <&cru CCLK_SRC_SDMMC0>,
> +				 <&cru SCLK_SDMMC_DRV>,
> +				 <&cru SCLK_SDMMC_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			resets = <&cru SRST_H_SDMMC0>;
> +			reset-names = "reset";

Suggest adding default pinctrl props here:

  pinctrl-names = "default";
  pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_det>;

And possible also for sdio0 and sdio1.

Regards,
Jonas

> +			status = "disabled";
> +		};
>  	};
>  };



From antonio.borneo at foss.st.com  Sat Mar  1 04:45:08 2025
From: antonio.borneo at foss.st.com (Antonio Borneo)
Date: Sat, 1 Mar 2025 13:45:08 +0100
Subject: [Linux-stm32] [PATCH] ARM: dts: stm32: use
 IRQ_TYPE_EDGE_FALLING on stm32mp157c-dk2
In-Reply-To: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com>
References: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com>
Message-ID: <1ae59b115cb2e4570c6e77a01bcdac11dff03ae1.camel@foss.st.com>

On Sat, 2025-03-01 at 12:51 +0100, Dario Binacchi wrote:
> Replace the number 2 with the appropriate numerical constant defined in
> dt-bindings/interrupt-controller/irq.h.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> 
> ---
> 
> ?arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 3 ++-
> ?1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> index 5f9c0160a9c4..dcf17c493022 100644
> --- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> @@ -11,6 +11,7 @@
> ?#include "stm32mp15-pinctrl.dtsi"
> ?#include "stm32mp15xxac-pinctrl.dtsi"
> ?#include "stm32mp15xx-dkx.dtsi"
> +#include <dt-bindings/interrupt-controller/irq.h>
> ?
> ?/ {
> ????????model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
> @@ -67,7 +68,7 @@ &i2c1 {
> ????????touchscreen at 38 {
> ????????????????compatible = "focaltech,ft6236";
> ????????????????reg = <0x38>;
> -???????????????interrupts = <2 2>;
> +???????????????interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
> ????????????????interrupt-parent = <&gpiof>;
> ????????????????touchscreen-size-x = <480>;
> ????????????????touchscreen-size-y = <800>;

Thanks!

Reviewed-by: Antonio Borneo <antonio.borneo at foss.st.com>

From heiko at sntech.de  Sat Mar  1 04:55:53 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sat, 01 Mar 2025 13:55:53 +0100
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
In-Reply-To: <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104749.36423-1-ziyao@disroot.org>
 <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se>
Message-ID: <3574922.QJadu78ljV@diego>

Hey Joas,

Am Samstag, 1. M?rz 2025, 13:47:47 MEZ schrieb Jonas Karlman:
> On 2025-03-01 11:47, Yao Zi wrote:
> > RK3528 features two SDIO controllers and one SD/MMC controller, describe
> > them in devicetree. Since their sample and drive clocks are located in
> > the VO and VPU GRFs, corresponding syscons are added to make these
> > clocks available.
> > 
> > Signed-off-by: Yao Zi <ziyao at disroot.org>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
> >  1 file changed, 62 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > index 5b334690356a..078c97fa1d9f 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > @@ -7,6 +7,7 @@
> >  #include <dt-bindings/interrupt-controller/arm-gic.h>
> >  #include <dt-bindings/interrupt-controller/irq.h>
> >  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
> > +#include <dt-bindings/reset/rockchip,rk3528-cru.h>
> >  
> >  / {
> >  	compatible = "rockchip,rk3528";
> > @@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
> >  			#interrupt-cells = <3>;
> >  		};
> >  
> > +		vpu_grf: syscon at ff340000 {
> > +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
> 
> vpu_grf is also used for gmac1, so should possible be a "syscon",
> "simple-mfd", or have I misunderstood when to use simple-mfd ?

simple-mfd is needed when the additional device is completely contained
inside the particular syscon.

For example, the usb2phy0 on rk3588 is completely living inside the
usb2phy0-grf.

Similarly the power-domains are living inside the rk3588 pmugrf.
But the pmugrf also contains more stuff, so the power-domains are a
subset of the pmugrf.

Both of these above are a case for a simple-mfd.


Similarly, gmac1 on rk3588 is ethernet at fe1c0000 , so a completely separate
io-memory area, but references both the sysgrf as well as the php-grf
as syscons for additional settings.

So here the syscon does not need to be a simple-mfd.


Hope that helps a bit
Heiko




From jonas at kwiboo.se  Sat Mar  1 05:01:05 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 1 Mar 2025 14:01:05 +0100
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <20250301104835.36439-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104835.36439-1-ziyao@disroot.org>
Message-ID: <0aefd292-7980-434d-9c18-4ab9f6a0b40e@kwiboo.se>

Hi,

On 2025-03-01 11:48, Yao Zi wrote:
> SD-card is available on Radxa E20C board.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> index d2cdb63d4a9d..473065aa4228 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> @@ -12,6 +12,10 @@ / {
>  	model = "Radxa E20C";
>  	compatible = "radxa,e20c", "rockchip,rk3528";
>  
> +	aliases {
> +		mmc0 = &sdmmc;

Suggest using mmc1 for sd-card because the e20c typically have onboard
emmc, compared to removable sd-card.

> +	};
> +
>  	chosen {
>  		stdout-path = "serial0:1500000n8";
>  	};
> @@ -20,3 +24,13 @@ chosen {
>  &uart0 {
>  	status = "okay";
>  };
> +
> +&sdmmc {
> +	bus-width = <4>;
> +	cap-mmc-highspeed;
> +	cap-sd-highspeed;
> +	disable-wp;
> +	rockchip,default-sample-phase = <90>;
> +	sd-uhs-sdr104;

Are you sure uhs-sdr104 works as is should? Vendor kernel use a
different "v2" tuning and this is also missing the vccio_sd vqmmc-supply
to switch between 3v3 and 1v8.

You could add following regulator for sdmmc:

	vccio_sd: regulator-vccio-sd {
		compatible = "regulator-gpio";
		gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&sdmmc_vol_ctrl_h>;
		regulator-name = "vccio_sd";
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <3300000>;
		states = <1800000 0x0>, <3300000 0x1>;
	};

and following pinctrl:

	sdmmc {
		sdmmc_vol_ctrl_h: sdmmc-vol-ctrl-h {
			rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};

add then the power supplies to the sdmmc node:

	vmmc-supply = <&vcc_3v3>;
	vqmmc-supply = <&vccio_sd>;

That matches the schematics for e20c, and works when testing non-uhs modes.

Regards,
Jonas

> +	status = "okay";
> +};



From krzk at kernel.org  Sat Mar  1 05:18:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:18:37 +0100
Subject: [PATCH 17/18] rtc: max77686: use dev_err_probe() where
 appropriate
In-Reply-To: <20250228-rtc-cleanups-v1-17-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
 <20250228-rtc-cleanups-v1-17-b44cec078481@linaro.org>
Message-ID: <87877293-a6e2-4c36-8932-9e6357a0385b@kernel.org>

On 28/02/2025 15:07, Andr? Draszik wrote:
> dev_err_probe() exists to simplify code and harmonise error messages,
> there's no reason not to use it here.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  drivers/rtc/rtc-max77686.c | 29 ++++++++++++-----------------
>  1 file changed, 12 insertions(+), 17 deletions(-)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 05:19:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:19:37 +0100
Subject: [PATCH 18/18] rtc: s5m: convert to dev_err_probe() where
 appropriate
In-Reply-To: <20250228-rtc-cleanups-v1-18-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
 <20250228-rtc-cleanups-v1-18-b44cec078481@linaro.org>
Message-ID: <d11ddca7-2569-431e-b34c-74739832f7f4@kernel.org>

On 28/02/2025 15:07, Andr? Draszik wrote:
> dev_err_probe() exists to simplify code and harmonise error messages,
> there's no reason not to use it here.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  drivers/rtc/rtc-s5m.c | 50 +++++++++++++++++++++------------------------


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From ziyao at disroot.org  Sat Mar  1 05:33:15 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat, 1 Mar 2025 13:33:15 +0000
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for
 RK3528
In-Reply-To: <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104749.36423-1-ziyao@disroot.org>
 <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se>
Message-ID: <Z8MMm7X31p_CrStZ@pie>

On Sat, Mar 01, 2025 at 01:47:47PM +0100, Jonas Karlman wrote:
> Hi,
> 
> On 2025-03-01 11:47, Yao Zi wrote:
> > RK3528 features two SDIO controllers and one SD/MMC controller, describe
> > them in devicetree. Since their sample and drive clocks are located in
> > the VO and VPU GRFs, corresponding syscons are added to make these
> > clocks available.
> > 
> > Signed-off-by: Yao Zi <ziyao at disroot.org>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
> >  1 file changed, 62 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > index 5b334690356a..078c97fa1d9f 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > @@ -7,6 +7,7 @@
> >  #include <dt-bindings/interrupt-controller/arm-gic.h>
> >  #include <dt-bindings/interrupt-controller/irq.h>
> >  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
> > +#include <dt-bindings/reset/rockchip,rk3528-cru.h>
> >  
> >  / {
> >  	compatible = "rockchip,rk3528";
> > @@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
> >  			#interrupt-cells = <3>;
> >  		};
> >  
> > +		vpu_grf: syscon at ff340000 {
> > +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
> 
> vpu_grf is also used for gmac1, so should possible be a "syscon",
> "simple-mfd", or have I misunderstood when to use simple-mfd ?

Just as Heiko explained, "simple-mfd" is only required when the child
nodes should be populated automatically. Here these two GRFs are only
referenced and have no child, thus "simple-mfd" compatible isn't useful.

> > +			reg = <0x0 0xff340000 0x0 0x8000>;
> > +		};
> > +
> > +		vo_grf: syscon at ff360000 {
> > +			compatible = "rockchip,rk3528-vo-grf", "syscon";
> 
> similar here, vo_grf is also used for gmac0.
> 
> > +			reg = <0x0 0xff360000 0x0 0x10000>;
> > +		};
> > +
> >  		cru: clock-controller at ff4a0000 {
> >  			compatible = "rockchip,rk3528-cru";
> >  			reg = <0x0 0xff4a0000 0x0 0x30000>;
> > @@ -251,5 +262,56 @@ uart7: serial at ffa28000 {
> >  			reg-shift = <2>;
> >  			status = "disabled";
> >  		};
> > +
> > +		sdio0: mmc at ffc10000 {
> > +			compatible = "rockchip,rk3528-dw-mshc",
> > +				     "rockchip,rk3288-dw-mshc";
> > +			reg = <0x0 0xffc10000 0x0 0x4000>;
> > +			clocks = <&cru HCLK_SDIO0>,
> > +				 <&cru CCLK_SRC_SDIO0>,
> > +				 <&cru SCLK_SDIO0_DRV>,
> > +				 <&cru SCLK_SDIO0_SAMPLE>;
> > +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> > +			fifo-depth = <0x100>;
> > +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> > +			max-frequency = <150000000>;
> > +			resets = <&cru SRST_H_SDIO0>;
> > +			reset-names = "reset";
> > +			status = "disabled";
> > +		};
> > +
> > +		sdio1: mmc at ffc20000 {
> > +			compatible = "rockchip,rk3528-dw-mshc",
> > +				     "rockchip,rk3288-dw-mshc";
> > +			reg = <0x0 0xffc20000 0x0 0x4000>;
> > +			clocks = <&cru HCLK_SDIO1>,
> > +				 <&cru CCLK_SRC_SDIO1>,
> > +				 <&cru SCLK_SDIO1_DRV>,
> > +				 <&cru SCLK_SDIO1_SAMPLE>;
> > +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> > +			fifo-depth = <0x100>;
> > +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> > +			max-frequency = <150000000>;
> > +			resets = <&cru SRST_H_SDIO1>;
> > +			reset-names = "reset";
> > +			status = "disabled";
> > +		};
> > +
> > +		sdmmc: mmc at ffc30000 {
> > +			compatible = "rockchip,rk3528-dw-mshc",
> > +				     "rockchip,rk3288-dw-mshc";
> > +			reg = <0x0 0xffc30000 0x0 0x4000>;
> > +			clocks = <&cru HCLK_SDMMC0>,
> > +				 <&cru CCLK_SRC_SDMMC0>,
> > +				 <&cru SCLK_SDMMC_DRV>,
> > +				 <&cru SCLK_SDMMC_SAMPLE>;
> > +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> > +			fifo-depth = <0x100>;
> > +			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
> > +			max-frequency = <150000000>;
> > +			resets = <&cru SRST_H_SDMMC0>;
> > +			reset-names = "reset";
> 
> Suggest adding default pinctrl props here:
> 
>   pinctrl-names = "default";
>   pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_det>;
> 
> And possible also for sdio0 and sdio1.
> 
> Regards,
> Jonas

It makes sense. As mentioned in the cover letter, I depended on the
bootloader to setup pinctrl, to minimize dependency of the series.

Will complete the pinctrl properties in next version.

> > +			status = "disabled";
> > +		};
> >  	};
> >  };
> 

Best regards,
Yao Zi


From krzk at kernel.org  Sat Mar  1 05:46:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:46:06 +0100
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
Message-ID: <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>

On 28/02/2025 21:18, Wilson Ding wrote:
> 
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: Thursday, February 27, 2025 10:57 PM
>> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
>> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
>> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
>> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
>> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset
>> controller node
>>
>> On 27/02/2025 20:?25, Wilson Ding wrote: > Add the reset controller node as
>> a sub-node to the system controller > node. > > Signed-off-by: Wilson Ding
>> <dingwei@?marvell.?com> > --- > arch/arm64/boot/dts/marvell/armada-
>> cp11x.?dtsi
>>
>> On 27/02/2025 20:25, Wilson Ding wrote:
>>> Add the reset controller node as a sub-node to the system controller
>>> node.
>>>
>>> Signed-off-by: Wilson Ding <dingwei at marvell.com>
>>> ---
>>>  arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>> b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>> index 161beec0b6b0..c27058d1534e 100644
>>> --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>> +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>> @@ -226,6 +226,8 @@ CP11X_LABEL(rtc): rtc at 284000 {
>>>  		CP11X_LABEL(syscon0): system-controller at 440000 {
>>>  			compatible = "syscon", "simple-mfd";
>>>  			reg = <0x440000 0x2000>;
>>> +			#address-cells = <1>;
>>> +			#size-cells = <1>;
>>>
>>>  			CP11X_LABEL(clk): clock {
>>
>> Wait, no unit address here.
> 
> This subnode came from the existing code. I didn't touch this subnode
> in my patch. As you can see, the system-controller has a wide address
> range, which includes clock, GPIO registers as well as the unit-softreset
> register.
> 
>>
>>>  				compatible = "marvell,cp110-clock";
>>> @@ -273,6 +275,12 @@ CP11X_LABEL(gpio2): gpio at 140 {
>>>  					 <&CP11X_LABEL(clk) 1 17>;
>>>  				status = "disabled";
>>>  			};
>>> +
>>> +			CP11X_LABEL(swrst): reset-controller at 268 {
>>
>>
>> So why here it appeared? This is wrong and not even necessary. Entire
>> child should be folded into parent, so finally you will fix the
>> incomplete parent compatible.
> 
> We do need the reset-controller as a subnode under system-controller node
> for the following reasons:
> 
> - We need to have 'reg' property in this subnode so that we can get the offset
>   to system-controller register base defined in parent node. This is suggested
>   by Rob in V2 comments. 
>   And we need to know the register size to calculate the number of reset lines.
>   This is suggested by Philipp in V1 comments.

You do not need and you received that comment as well. It is implied by
compatible.

> 
> - We also need to define the 'reset-cells' in this subnode. And the consumer of
>   the reset controller uses the label of this subnode for the phandle and reset
>   specifier pair. 

reset-cells will be in the parent once you fold it.

> 
> As I mentioned in my reply to the first comment, the reset-controller is not the
> only device within the system-controller register spaces. Do you still think I

You provided very little hardware description of the device. So based on
hardware description you provided: yes.

> should fold it into the parent node. And what I proposed is exactly same as
> that the armada_thermal driver did (See below). I wonder why what was accepted
> in the past become not accepted now. 

We did not discuss here drivers, but if you insist talking about
"marvell,armada-cp110-thermal" then point me to review or ack from DT
people. You claim it was accepted so how did we accept it?

It was 2013 so that's another answer: many things done 12 years ago were
done not according to best practices. Also best practices evolved.

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 05:49:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:49:07 +0100
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
Message-ID: <20946ee0-4973-4831-bc77-4d9942f1a348@kernel.org>

On 01/03/2025 14:46, Krzysztof Kozlowski wrote:
>>>> Signed-off-by: Wilson Ding <dingwei at marvell.com>
>>>> ---
>>>>  arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 8 ++++++++
>>>>  1 file changed, 8 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>> b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>> index 161beec0b6b0..c27058d1534e 100644
>>>> --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>> +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>> @@ -226,6 +226,8 @@ CP11X_LABEL(rtc): rtc at 284000 {
>>>>  		CP11X_LABEL(syscon0): system-controller at 440000 {
>>>>  			compatible = "syscon", "simple-mfd";
>>>>  			reg = <0x440000 0x2000>;
>>>> +			#address-cells = <1>;
>>>> +			#size-cells = <1>;
>>>>
>>>>  			CP11X_LABEL(clk): clock {
>>>
>>> Wait, no unit address here.
>>
>> This subnode came from the existing code. I didn't touch this subnode
>> in my patch. As you can see, the system-controller has a wide address
>> range, which includes clock, GPIO registers as well as the unit-softreset
>> register.
>>
>>>
>>>>  				compatible = "marvell,cp110-clock";
>>>> @@ -273,6 +275,12 @@ CP11X_LABEL(gpio2): gpio at 140 {
>>>>  					 <&CP11X_LABEL(clk) 1 17>;
>>>>  				status = "disabled";
>>>>  			};
>>>> +
>>>> +			CP11X_LABEL(swrst): reset-controller at 268 {
>>>
>>>
>>> So why here it appeared? This is wrong and not even necessary. Entire
>>> child should be folded into parent, so finally you will fix the
>>> incomplete parent compatible.
>>
>> We do need the reset-controller as a subnode under system-controller node
>> for the following reasons:
>>
>> - We need to have 'reg' property in this subnode so that we can get the offset
>>   to system-controller register base defined in parent node. This is suggested
>>   by Rob in V2 comments. 
>>   And we need to know the register size to calculate the number of reset lines.
>>   This is suggested by Philipp in V1 comments.
> 
> You do not need and you received that comment as well. It is implied by
> compatible.
> 
>>
>> - We also need to define the 'reset-cells' in this subnode. And the consumer of
>>   the reset controller uses the label of this subnode for the phandle and reset
>>   specifier pair. 
> 
> reset-cells will be in the parent once you fold it.
> 
>>
>> As I mentioned in my reply to the first comment, the reset-controller is not the
>> only device within the system-controller register spaces. Do you still think I
> 
> You provided very little hardware description of the device. So based on
> hardware description you provided: yes.

and to clarify - by device I mean the parent node, the system controller.

Your commit even mentions driver, not the hardware:
"Add device-tree binding documentation for the Armada8K reset driver..."
not hardware, so you will get the review as good as you describe things.

Bindings are about hardware so if you disagree with the review here,
please provide arguments in terms of hardware.

> 
>> should fold it into the parent node. And what I proposed is exactly same as
>> that the armada_thermal driver did (See below). I wonder why what was accepted
>> in the past become not accepted now. 
> 
> We did not discuss here drivers, but if you insist talking about
> "marvell,armada-cp110-thermal" then point me to review or ack from DT
> people. You claim it was accepted so how did we accept it?
> 
> It was 2013 so that's another answer: many things done 12 years ago were
> done not according to best practices. Also best practices evolved.



Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 05:56:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:56:07 +0100
Subject: [PATCH 1/5] arm64: dts: exynos990: Enable watchdog timer
In-Reply-To: <20250217-exynos990-dt-changes-febuary-v1-1-99935218cbf4@mentallysanemainliners.org>
References: <20250217-exynos990-dt-changes-febuary-v1-0-99935218cbf4@mentallysanemainliners.org>
 <20250217-exynos990-dt-changes-febuary-v1-1-99935218cbf4@mentallysanemainliners.org>
Message-ID: <cba16ab1-cd5c-4a00-81ac-896de2b4c2ad@kernel.org>

On 17/02/2025 22:32, Igor Belwon wrote:
> Enable the two watchdog timer clusters (cl0, cl2) present
> on the Exynos990 SoC.
> 
> Signed-off-by: Igor Belwon <igor.belwon at mentallysanemainliners.org>
> ---
>  arch/arm64/boot/dts/exynos/exynos990.dtsi | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/exynos/exynos990.dtsi b/arch/arm64/boot/dts/exynos/exynos990.dtsi
> index dd7f99f51a75412f5c3b91c3425a63652546fa5e..4446a1a54ba2de56879353c9c4a898b1d697fc13 100644
> --- a/arch/arm64/boot/dts/exynos/exynos990.dtsi
> +++ b/arch/arm64/boot/dts/exynos/exynos990.dtsi
> @@ -211,6 +211,30 @@ timer at 10040000 {
>  				     <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>;
>  		};
>  
> +		watchdog_cl0: watchdog at 10050000 {
> +			compatible = "samsung,exynos990-wdt";

I don't see bindings in the next, so I am dropping this patch from my
queue. Please resend when they hit the next.

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 05:56:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:56:47 +0100
Subject: [PATCH 2/5] arm64: dts: exynos990: Add USB nodes
In-Reply-To: <20250217-exynos990-dt-changes-febuary-v1-2-99935218cbf4@mentallysanemainliners.org>
References: <20250217-exynos990-dt-changes-febuary-v1-0-99935218cbf4@mentallysanemainliners.org>
 <20250217-exynos990-dt-changes-febuary-v1-2-99935218cbf4@mentallysanemainliners.org>
Message-ID: <e2369731-9b2f-4a18-b057-ac37aedcbca5@kernel.org>

On 17/02/2025 22:32, Igor Belwon wrote:
> +			usbdrd_dwc3: usb at 0 {
> +				compatible = "snps,dwc3";
> +				reg = <0x0 0x10000>;
> +				interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
> +				phys = <&usbdrd_phy 0>;
> +				phy-names = "usb2-phy";
> +			};
> +		};
> +
> +		usbdrd_phy: phy at 10c00000 {
> +			compatible = "samsung,exynos990-usbdrd-phy";
Same here.

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 05:59:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 14:59:26 +0100
Subject: [PATCH v7 1/2] arm64: dts: fsd: Add Ethernet support for FSYS0
 Block of FSD SoC
In-Reply-To: <20250220073527.22233-2-swathi.ks@samsung.com>
References: <20250220073527.22233-1-swathi.ks@samsung.com>
 <CGME20250220073944epcas5p495ee305ca577a7e1be51ff916f20fc53@epcas5p4.samsung.com>
 <20250220073527.22233-2-swathi.ks@samsung.com>
Message-ID: <7328e538-31cf-4674-83d2-943f1a2d1455@kernel.org>

On 20/02/2025 08:35, Swathi K S wrote:
>  &pinctrl_peric {
> diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi b/arch/arm64/boot/dts/tesla/fsd.dtsi
> index 690b4ed9c29b..01850fbf761f 100644
> --- a/arch/arm64/boot/dts/tesla/fsd.dtsi
> +++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
> @@ -1007,6 +1007,26 @@
>  			clocks = <&clock_fsys0 UFS0_MPHY_REFCLK_IXTAL26>;
>  			clock-names = "ref_clk";
>  		};
> +
> +		ethernet0: ethernet at 15300000 {
> +			compatible = "tesla,fsd-ethqos";

I don't see bindings in the linux-next, so I am dropping this patch from
my queue. Please resend when the bindings hit the linux-next.

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 06:01:12 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 15:01:12 +0100
Subject: [PATCH v2 1/3] dt-bindings: clock: add Exynos2200 SoC
In-Reply-To: <20250223115601.723886-2-ivo.ivanov.ivanov1@gmail.com>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223115601.723886-2-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <8b85be4a-ecd9-4ea4-9cfc-905bb4bd5642@kernel.org>

On 23/02/2025 12:55, Ivaylo Ivanov wrote:
> Provide dt-schema documentation for Exynos2200 SoC clock controller.
> Add device tree clock binding definitions for the following CMU blocks:
> - CMU_ALIVE
> - CMU_CMGP
> - CMU_HSI0
> - CMU_PERIC0/1/2
> - CMU_PERIS
> - CMU_TOP
> - CMU_UFS
> - CMU_VTS
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  .../clock/samsung,exynos2200-cmu.yaml         | 247 ++++++++++
>  .../clock/samsung,exynos2200-cmu.h            | 431 ++++++++++++++++++
>  2 files changed, 678 insertions(+)


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 06:04:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 15:04:54 +0100
Subject: [PATCH v5 1/2] dt-bindings: clock: add clock definitions and
 documentation for exynos7870 CMU
In-Reply-To: <20250301-exynos7870-pmu-clocks-v5-1-715b646d5206@disroot.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org>
 <20250301-exynos7870-pmu-clocks-v5-1-715b646d5206@disroot.org>
Message-ID: <a95607b3-6f3c-44e8-99f3-7b1deec43270@kernel.org>

On 01/03/2025 04:57, Kaustabh Chakraborty wrote:
> Add unique identifiers for exynos7870 clocks for every bank. It adds all
> clocks of CMU_MIF, CMU_DISPAUD, CMU_G3D, CMU_ISP, CMU_MFCMSCL, and
> CMU_PERI. Document the devicetree bindings as well.
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
> ---


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From maxime.chevallier at bootlin.com  Sat Mar  1 06:11:13 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  1 Mar 2025 15:11:13 +0100
Subject: [PATCH net v2] net: ethtool: netlink: Allow NULL nlattrs when getting a phy_device
Message-ID: <20250301141114.97204-1-maxime.chevallier@bootlin.com>

ethnl_req_get_phydev() is used to lookup a phy_device, in the case an
ethtool netlink command targets a specific phydev within a netdev's
topology.

It takes as a parameter a const struct nlattr *header that's used for
error handling :

       if (!phydev) {
               NL_SET_ERR_MSG_ATTR(extack, header,
                                   "no phy matching phyindex");
               return ERR_PTR(-ENODEV);
       }

In the notify path after a ->set operation however, there's no request
attributes available.

The typical callsite for the above function looks like:

	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_XXX_HEADER],
				      info->extack);

So, when tb is NULL (such as in the ethnl notify path), we have a nice
crash.

It turns out that there's only the PLCA command that is in that case, as
the other phydev-specific commands don't have a notification.

This commit fixes the crash by passing the cmd index and the nlattr
array separately, allowing NULL-checking it directly inside the helper.

Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some commands")
Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---

V2: Send this patch as a standalone fix instead of including it in a
series [1] containing patches that don't belong to net. No modifications
were made besides a rebase on -net.

[1]: https://lore.kernel.org/netdev/20250227182454.1998236-1-maxime.chevallier at bootlin.com/

 net/ethtool/cabletest.c | 8 ++++----
 net/ethtool/linkstate.c | 2 +-
 net/ethtool/netlink.c   | 6 +++---
 net/ethtool/netlink.h   | 5 +++--
 net/ethtool/phy.c       | 2 +-
 net/ethtool/plca.c      | 6 +++---
 net/ethtool/pse-pd.c    | 4 ++--
 net/ethtool/stats.c     | 2 +-
 net/ethtool/strset.c    | 2 +-
 9 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/net/ethtool/cabletest.c b/net/ethtool/cabletest.c
index f22051f33868..84096f6b0236 100644
--- a/net/ethtool/cabletest.c
+++ b/net/ethtool/cabletest.c
@@ -72,8 +72,8 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
 	dev = req_info.dev;
 
 	rtnl_lock();
-	phydev = ethnl_req_get_phydev(&req_info,
-				      tb[ETHTOOL_A_CABLE_TEST_HEADER],
+	phydev = ethnl_req_get_phydev(&req_info, tb,
+				      ETHTOOL_A_CABLE_TEST_HEADER,
 				      info->extack);
 	if (IS_ERR_OR_NULL(phydev)) {
 		ret = -EOPNOTSUPP;
@@ -339,8 +339,8 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
 		goto out_dev_put;
 
 	rtnl_lock();
-	phydev = ethnl_req_get_phydev(&req_info,
-				      tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER],
+	phydev = ethnl_req_get_phydev(&req_info, tb,
+				      ETHTOOL_A_CABLE_TEST_TDR_HEADER,
 				      info->extack);
 	if (IS_ERR_OR_NULL(phydev)) {
 		ret = -EOPNOTSUPP;
diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
index af19e1bed303..05a5f72c99fa 100644
--- a/net/ethtool/linkstate.c
+++ b/net/ethtool/linkstate.c
@@ -103,7 +103,7 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
 	struct phy_device *phydev;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_LINKSTATE_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_LINKSTATE_HEADER,
 				      info->extack);
 	if (IS_ERR(phydev)) {
 		ret = PTR_ERR(phydev);
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index b4c45207fa32..734849a57369 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -211,7 +211,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
 }
 
 struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info,
-					const struct nlattr *header,
+					struct nlattr **tb, unsigned int header,
 					struct netlink_ext_ack *extack)
 {
 	struct phy_device *phydev;
@@ -225,8 +225,8 @@ struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info,
 		return req_info->dev->phydev;
 
 	phydev = phy_link_topo_get_phy(req_info->dev, req_info->phy_index);
-	if (!phydev) {
-		NL_SET_ERR_MSG_ATTR(extack, header,
+	if (!phydev && tb) {
+		NL_SET_ERR_MSG_ATTR(extack, tb[header],
 				    "no phy matching phyindex");
 		return ERR_PTR(-ENODEV);
 	}
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index ff69ca0715de..ec6ab5443a6f 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -275,7 +275,8 @@ static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info)
  * ethnl_req_get_phydev() - Gets the phy_device targeted by this request,
  *			    if any. Must be called under rntl_lock().
  * @req_info:	The ethnl request to get the phy from.
- * @header:	The netlink header, used for error reporting.
+ * @tb:		The netlink attributes array, for error reporting.
+ * @header:	The netlink header index, used for error reporting.
  * @extack:	The netlink extended ACK, for error reporting.
  *
  * The caller must hold RTNL, until it's done interacting with the returned
@@ -289,7 +290,7 @@ static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info)
  *	   is returned.
  */
 struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info,
-					const struct nlattr *header,
+					struct nlattr **tb, unsigned int header,
 					struct netlink_ext_ack *extack);
 
 /**
diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c
index ed8f690f6bac..e067cc234419 100644
--- a/net/ethtool/phy.c
+++ b/net/ethtool/phy.c
@@ -125,7 +125,7 @@ static int ethnl_phy_parse_request(struct ethnl_req_info *req_base,
 	struct phy_req_info *req_info = PHY_REQINFO(req_base);
 	struct phy_device *phydev;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PHY_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PHY_HEADER,
 				      extack);
 	if (!phydev)
 		return 0;
diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c
index d95d92f173a6..e1f7820a6158 100644
--- a/net/ethtool/plca.c
+++ b/net/ethtool/plca.c
@@ -62,7 +62,7 @@ static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base,
 	struct phy_device *phydev;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PLCA_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER,
 				      info->extack);
 	// check that the PHY device is available and connected
 	if (IS_ERR_OR_NULL(phydev)) {
@@ -152,7 +152,7 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info)
 	bool mod = false;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_info, tb[ETHTOOL_A_PLCA_HEADER],
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PLCA_HEADER,
 				      info->extack);
 	// check that the PHY device is available and connected
 	if (IS_ERR_OR_NULL(phydev))
@@ -211,7 +211,7 @@ static int plca_get_status_prepare_data(const struct ethnl_req_info *req_base,
 	struct phy_device *phydev;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PLCA_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER,
 				      info->extack);
 	// check that the PHY device is available and connected
 	if (IS_ERR_OR_NULL(phydev)) {
diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
index 2819e2ba6be2..4f6b99eab2a6 100644
--- a/net/ethtool/pse-pd.c
+++ b/net/ethtool/pse-pd.c
@@ -64,7 +64,7 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base,
 	if (ret < 0)
 		return ret;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PSE_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PSE_HEADER,
 				      info->extack);
 	if (IS_ERR(phydev))
 		return -ENODEV;
@@ -261,7 +261,7 @@ ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info)
 	struct phy_device *phydev;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_info, tb[ETHTOOL_A_PSE_HEADER],
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PSE_HEADER,
 				      info->extack);
 	ret = ethnl_set_pse_validate(phydev, info);
 	if (ret)
diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c
index 038a2558f052..3ca8eb2a3b31 100644
--- a/net/ethtool/stats.c
+++ b/net/ethtool/stats.c
@@ -138,7 +138,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
 	struct phy_device *phydev;
 	int ret;
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_STATS_HEADER],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_STATS_HEADER,
 				      info->extack);
 	if (IS_ERR(phydev))
 		return PTR_ERR(phydev);
diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
index 6b76c05caba4..f6a67109beda 100644
--- a/net/ethtool/strset.c
+++ b/net/ethtool/strset.c
@@ -309,7 +309,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
 		return 0;
 	}
 
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_HEADER_FLAGS],
+	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_HEADER_FLAGS,
 				      info->extack);
 
 	/* phydev can be NULL, check for errors only */
-- 
2.48.1



From krzysztof.kozlowski at linaro.org  Sat Mar  1 06:13:29 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sat, 01 Mar 2025 15:13:29 +0100
Subject: (subset) [PATCH v2 3/3] clk: samsung: introduce Exynos2200
 clock driver
In-Reply-To: <20250223115601.723886-4-ivo.ivanov.ivanov1@gmail.com>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223115601.723886-4-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <174083840951.17657.11144069313199701338.b4-ty@linaro.org>


On Sun, 23 Feb 2025 13:56:00 +0200, Ivaylo Ivanov wrote:
> CMU_TOP is the top level clock management unit which contains PLLs,
> muxes, dividers and gates that feed the other clock management units.
> 
> CMU_ALIVE provides clocks for SPMI, the new MCT and other clock
> management units
> 
> CMU_CMGP provides clocks for USI blocks
> CMU_HSI0 provides clocks for USB
> CMU_PERIC0 provides clocks for USI4 and I3C blocks
> CMU_PERIC1 provides clocks for USI blocks
> CMU_PERIC2 provides clocks for USI and I3C blocks
> CMU_PERIS provides clocks for GIC and the legacy MCT
> CMU_UFS provides clocks for UFS
> CMU_VTS provides clocks for other clock management units
> like CMU_AUD, which will be added in the future.
> 
> [...]

Applied, thanks!

[3/3] clk: samsung: introduce Exynos2200 clock driver
      https://git.kernel.org/krzk/linux/c/11fd259b7a9c386179f4bb9657c7597c8e8de067

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Sat Mar  1 06:13:32 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sat, 01 Mar 2025 15:13:32 +0100
Subject: (subset) [PATCH v5 2/2] clk: samsung: add initial exynos7870
 clock driver
In-Reply-To: <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org>
 <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
Message-ID: <174083841272.17657.12697906967603393824.b4-ty@linaro.org>


On Sat, 01 Mar 2025 09:27:13 +0530, Kaustabh Chakraborty wrote:
> This is a basic implementation of the clock driver required by
> Samsung's Exynos7870 SoC. It implements CMU_MIF, CMU_DISPAUD, CMU_FSYS,
> CMU_G3D, CMU_ISP, CMU_MFCMSCL, and CMU_PERI. all other CMUs depend on
> CMU_MIF.
> 
> 

Applied, thanks!

[2/2] clk: samsung: add initial exynos7870 clock driver
      https://git.kernel.org/krzk/linux/c/4149066a5e958963f7123be51d3a65d336045c21

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Sat Mar  1 06:13:20 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sat, 01 Mar 2025 15:13:20 +0100
Subject: (subset) [PATCH v2 1/3] dt-bindings: clock: add Exynos2200 SoC
In-Reply-To: <20250223115601.723886-2-ivo.ivanov.ivanov1@gmail.com>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223115601.723886-2-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <174083840012.17657.16502862587559253626.b4-ty@linaro.org>


On Sun, 23 Feb 2025 13:55:58 +0200, Ivaylo Ivanov wrote:
> Provide dt-schema documentation for Exynos2200 SoC clock controller.
> Add device tree clock binding definitions for the following CMU blocks:
> - CMU_ALIVE
> - CMU_CMGP
> - CMU_HSI0
> - CMU_PERIC0/1/2
> - CMU_PERIS
> - CMU_TOP
> - CMU_UFS
> - CMU_VTS
> 
> [...]

Applied, thanks!

[1/3] dt-bindings: clock: add Exynos2200 SoC
      https://git.kernel.org/krzk/linux/c/6662c09c0ddf10ef97b430533bb9e2f0a8fbe471

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Sat Mar  1 06:13:23 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sat, 01 Mar 2025 15:13:23 +0100
Subject: (subset) [PATCH v5 1/2] dt-bindings: clock: add clock
 definitions and documentation for exynos7870 CMU
In-Reply-To: <20250301-exynos7870-pmu-clocks-v5-1-715b646d5206@disroot.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org>
 <20250301-exynos7870-pmu-clocks-v5-1-715b646d5206@disroot.org>
Message-ID: <174083840306.17657.2523115679702297451.b4-ty@linaro.org>


On Sat, 01 Mar 2025 09:27:12 +0530, Kaustabh Chakraborty wrote:
> Add unique identifiers for exynos7870 clocks for every bank. It adds all
> clocks of CMU_MIF, CMU_DISPAUD, CMU_G3D, CMU_ISP, CMU_MFCMSCL, and
> CMU_PERI. Document the devicetree bindings as well.
> 
> 

Applied, thanks!

[1/2] dt-bindings: clock: add clock definitions and documentation for exynos7870 CMU
      https://git.kernel.org/krzk/linux/c/35b2b3328c2e02b544f49d010170fe981f20ff11

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Sat Mar  1 06:13:26 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sat, 01 Mar 2025 15:13:26 +0100
Subject: (subset) [PATCH v2 2/3] clk: samsung: clk-pll: add support for
 pll_4311
In-Reply-To: <20250223115601.723886-3-ivo.ivanov.ivanov1@gmail.com>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223115601.723886-3-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <174083840636.17657.13627418806102780540.b4-ty@linaro.org>


On Sun, 23 Feb 2025 13:55:59 +0200, Ivaylo Ivanov wrote:
> pll4311 (also known in the vendor kernel as frd_4311_rpll) is a PLL used
> in the Exynos2200 SoC. It's an integer/fractional PLL with mid frequency
> FVCO (650 to 3500Mhz).
> 
> The PLL is functionally similar enough to pll531x, so the same code can
> handle both.
> 
> [...]

Applied, thanks!

[2/3] clk: samsung: clk-pll: add support for pll_4311
      https://git.kernel.org/krzk/linux/c/f33807c30664d2b134ba17f2ae0740acbe91986a

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzk at kernel.org  Sat Mar  1 06:14:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 15:14:37 +0100
Subject: [PATCH v2 2/2] clk: samsung: update PLL locktime for PLL142XX
 used on FSD platform
In-Reply-To: <20250225131918.50925-3-v.pavani@samsung.com>
References: <20250225131918.50925-1-v.pavani@samsung.com>
 <CGME20250225132507epcas5p455347acbd580b26ee807e467d3a6a05e@epcas5p4.samsung.com>
 <20250225131918.50925-3-v.pavani@samsung.com>
Message-ID: <c5cef589-8091-41ce-94e7-82b56ba4143f@kernel.org>

On 25/02/2025 14:19, Varada Pavani wrote:
> Currently PLL142XX locktime is 270. As per spec, it should be 150. Hence
> update PLL142XX controller locktime to 150.
> 
> Cc: stable at vger.kernel.org

Fixes commit?

> Signed-off-by: Varada Pavani <v.pavani at samsung.com>
> ---
>  drivers/clk/samsung/clk-pll.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
> index 2e94bba6c396..023a25af73c4 100644
> --- a/drivers/clk/samsung/clk-pll.c
> +++ b/drivers/clk/samsung/clk-pll.c
> @@ -206,6 +206,7 @@ static const struct clk_ops samsung_pll3000_clk_ops = {
>   */
>  /* Maximum lock time can be 270 * PDIV cycles */
>  #define PLL35XX_LOCK_FACTOR	(270)
> +#define PLL142XX_LOCK_FACTOR	(150)
>  
>  #define PLL35XX_MDIV_MASK       (0x3FF)
>  #define PLL35XX_PDIV_MASK       (0x3F)
> @@ -272,7 +273,11 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
>  	}
>  
>  	/* Set PLL lock time. */
> -	writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
> +	if (pll->type == pll_142xx)
> +		writel_relaxed(rate->pdiv * PLL142XX_LOCK_FACTOR,
> +			pll->lock_reg);
> +	else
> +		writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
>  			pll->lock_reg);
>  
>  	/* Change PLL PMS values */


Best regards,
Krzysztof


From laurent.pinchart at ideasonboard.com  Sat Mar  1 06:34:53 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Sat, 1 Mar 2025 16:34:53 +0200
Subject: [PATCH 1/3] media: rkisp1: Set format defaults based on
 requested color space
In-Reply-To: <20250301010252.GI7342@pendragon.ideasonboard.com>
References: <20250227114558.3097101-1-stefan.klug@ideasonboard.com>
 <20250227114558.3097101-2-stefan.klug@ideasonboard.com>
 <20250301010252.GI7342@pendragon.ideasonboard.com>
Message-ID: <20250301143453.GJ7342@pendragon.ideasonboard.com>

On Sat, Mar 01, 2025 at 03:02:54AM +0200, Laurent Pinchart wrote:
> On Thu, Feb 27, 2025 at 12:44:59PM +0100, Stefan Klug wrote:
> > When color space JPEG is requested, the ISP sets the quantization
> > incorrectly to limited range. To fix that, set the xfer_func, ycbcr_enc
> > and quantization to the defaults for the requested color space if they
> > are not specified explicitly.
> 
> The commit message fails to explain why you're addressing xfer_func and
> ycbcr_enc to fix the quantization issue.
> 
> > Do this only in case we are converting
> > from RAW to YUV.
> 
> And this should explain why.
> 
> > Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
> > ---
> >  .../media/platform/rockchip/rkisp1/rkisp1-isp.c   | 15 ++++++++++++++-
> >  1 file changed, 14 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > index d94917211828..468f5a7d03c7 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > @@ -680,10 +680,23 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
> 
> Adding a bit more context:
> 
> 	set_csc = format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC;
> 
> 	if (set_csc && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
> 
> If V4L2_MBUS_FRAMEFMT_SET_CSC isn't set, the colorspace fields on the
> source pad will be copied from the sink pad, which doesn't seem right.

Thinking some more about it, it's not wrong either. The colorspace and
xfer_func fields are not used by the driver, as the related ISP
processing blocks are configured through ISP parameters. Without
userspace providing the value of the fields on the source pad, the
driver can't know what colorspace and xfer_func is produced. Copying the
values from the sink pad is as good of a guess as we can make.

The ycbcr_enc and quantization fields are different, as they are taken
into account by the driver to configure the ISP. Copying ycbcr_enc from
the sink pad means that it will be set to V4L2_YCBCR_ENC_601 when the
sink format is bayer and the source format is YUV. As the sink
colorspace is most likely going to be V4L2_COLORSPACE_RAW in that case,
that's a fine default, and is identical to what we would get from
V4L2_MAP_YCBCR_ENC_DEFAULT(). Setting the quantization to
V4L2_QUANTIZATION_LIM_RANGE also seems fine as a default, and it what
V4L2_MAP_QUANTIZATION_DEFAULT() would give us.

TL;DR: there's probably no need to change the current behaviour when
V4L2_MBUS_FRAMEFMT_SET_CSC isn't set.

> It's a separate issue, but fixing both together may lead to better code.
> 
> >  		if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
> >  			if (format->colorspace != V4L2_COLORSPACE_DEFAULT)
> >  				src_fmt->colorspace = format->colorspace;
> > -			if (format->xfer_func != V4L2_XFER_FUNC_DEFAULT)
> > +
> > +			if (format->xfer_func == V4L2_XFER_FUNC_DEFAULT)
> 
> Are you sure the condition should be inverted ?
> 
> >  				src_fmt->xfer_func = format->xfer_func;
> > +			else
> > +				src_fmt->xfer_func =
> > +					V4L2_MAP_XFER_FUNC_DEFAULT(format->colorspace);
> > +
> >  			if (format->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT)
> >  				src_fmt->ycbcr_enc = format->ycbcr_enc;
> > +			else
> > +				src_fmt->ycbcr_enc =
> > +					V4L2_MAP_YCBCR_ENC_DEFAULT(format->colorspace);
> > +
> > +			if (format->quantization == V4L2_QUANTIZATION_DEFAULT)
> > +				src_fmt->quantization =
> > +					V4L2_MAP_QUANTIZATION_DEFAULT(false,
> > +						format->colorspace, format->ycbcr_enc);
> 
> Shouldn't this use src_fmt instead of format ?
> 
> I think quantization handling could be moved below.
> 
> >  		}
> >  
> >  		if (format->quantization != V4L2_QUANTIZATION_DEFAULT)

Now I'm wondering if this is right. As far as I can tell, the
quantization isn't taken into account by the driver when the ISP is
bypassed (capturing raw bayer data, or capturing YUV data from a YUV
sensor).

How about something like this ?

diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
index d94917211828..9c215c9bb30f 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
@@ -659,11 +659,10 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
 		src_fmt->quantization = sink_fmt->quantization;

 	/*
-	 * Allow setting the source color space fields when the SET_CSC flag is
-	 * set and the source format is YUV. If the sink format is YUV, don't
-	 * set the color primaries, transfer function or YCbCr encoding as the
-	 * ISP is bypassed in that case and passes YUV data through without
-	 * modifications.
+	 * Allow setting the source color space fields when the SET_CSC flag.
+	 * This is restricted to the case where the sink format is raw and the
+	 * source format is YUV, as in other cases the ISP is bypassed and the
+	 * input data is passed through without modifications.
 	 *
 	 * The color primaries and transfer function are configured through the
 	 * cross-talk matrix and tone curve respectively. Settings for those
@@ -676,18 +675,30 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
 	 */
 	set_csc = format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC;

-	if (set_csc && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
-		if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
-			if (format->colorspace != V4L2_COLORSPACE_DEFAULT)
-				src_fmt->colorspace = format->colorspace;
-			if (format->xfer_func != V4L2_XFER_FUNC_DEFAULT)
-				src_fmt->xfer_func = format->xfer_func;
-			if (format->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT)
-				src_fmt->ycbcr_enc = format->ycbcr_enc;
-		}
+	if (set_csc && sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER &&
+	    src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
+		if (format->colorspace != V4L2_COLORSPACE_DEFAULT)
+			src_fmt->colorspace = format->colorspace;
+
+		if (format->xfer_func != V4L2_XFER_FUNC_DEFAULT)
+			src_fmt->xfer_func = format->xfer_func;
+		else
+			src_fmt->xfer_func =
+				V4L2_MAP_XFER_FUNC_DEFAULT(src_fmt->colorspace);
+
+		if (format->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT)
+			src_fmt->ycbcr_enc = format->ycbcr_enc;
+		else
+			src_fmt->ycbcr_enc =
+				V4L2_MAP_YCBCR_ENC_DEFAULT(src_fmt->colorspace);

 		if (format->quantization != V4L2_QUANTIZATION_DEFAULT)
 			src_fmt->quantization = format->quantization;
+		else
+			src_fmt->quantization =
+				V4L2_MAP_QUANTIZATION_DEFAULT(false,
+							      src_fmt->colorspace,
+							      src_fmt->ycbcr_enc);
 	}

 	*format = *src_fmt;

Can I let you write a commit message ? :-)

-- 
Regards,

Laurent Pinchart


From kw at linux.com  Sat Mar  1 06:48:31 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Sat, 1 Mar 2025 23:48:31 +0900
Subject: [PATCH v2 0/8] PCI: brcmstb: Misc small tweaks and fixes
In-Reply-To: <20250214173944.47506-1-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
Message-ID: <20250301144831.GA846783@rocinante>

Hello,

[...]
>   Six small fixes and improvements for the driver.  This may be applied
>   before or after Stan's V5 [1] on pci-next (they should not conflict).

Applied to controller/brcmstb, thank you!

	Krzysztof


From krzk at kernel.org  Sat Mar  1 06:50:03 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 15:50:03 +0100
Subject: [PATCH v2 4/4] MAINTAINERS: add entry for Samsung Exynos2200 SoC
In-Reply-To: <20250223123044.725493-5-ivo.ivanov.ivanov1@gmail.com>
References: <20250223123044.725493-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223123044.725493-5-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <7cd3bc4c-318e-4327-a00d-bfe42d4504c9@kernel.org>

On 23/02/2025 13:30, Ivaylo Ivanov wrote:
> Add maintainers entry for the Samsung Exynos2200 SoC based platforms.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  MAINTAINERS | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e4f5d8f68..7da20faf7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20937,6 +20937,18 @@ B:	mailto:linux-samsung-soc at vger.kernel.org
>  F:	Documentation/devicetree/bindings/sound/samsung*
>  F:	sound/soc/samsung/
>  
> +SAMSUNG EXYNOS2200 SoC SUPPORT
> +M:	Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> +L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> +L:	linux-samsung-soc at vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/clock/samsung,exynos2200-cmu.yaml
> +F:	Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
> +F:	arch/arm64/boot/dts/exynos/exynos2200*
> +F:	drivers/clk/samsung/clk-exynos2200.c
> +F:	drivers/phy/samsung/phy-exynos2200-usbcon.c

Please add separate entry for the PHY driver.


Best regards,
Krzysztof


From krzk at kernel.org  Sat Mar  1 06:55:46 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 1 Mar 2025 15:55:46 +0100
Subject: [PATCH v2 0/4] arm64: dts: exynos: add initial support for
 Samsung Galaxy S22+
In-Reply-To: <20250223123044.725493-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250223123044.725493-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <e4c83aa1-5da0-4420-a43a-bc7e91414da6@kernel.org>

On 23/02/2025 13:30, Ivaylo Ivanov wrote:
> 
> Samsung Galaxy S22+ (SM-S906B), codenamed g0s, is a mobile phone from
> 2022. It features 8GB RAM, 128/256GB UFS 3.1, Exynos 2200 SoC and a
> 1080x2340 Dynamic AMOLED display.
> 
> Further platform support will be added over time.
> 
> I expect [1], [2], [3], [4], [5], [6] to be merged before this patchset
> because it relies on the aforementioned series for drivers and device
> tree bindings.
> 
> [1] https://lore.kernel.org/all/20250215112716.159110-1-ivo.ivanov.ivanov1 at gmail.com/

This was already merged. Update your dependencies once they are not a
dependency for documented binding anymore.

> [2] https://lore.kernel.org/all/20250215113248.159386-1-ivo.ivanov.ivanov1 at gmail.com/

This too.

> [3] https://lore.kernel.org/all/20250223115601.723886-1-ivo.ivanov.ivanov1 at gmail.com/
> [4] https://lore.kernel.org/all/20250223122227.725233-1-ivo.ivanov.ivanov1 at gmail.com/

This looks not, so patchset will wait.

> [5] https://lore.kernel.org/all/20250215123453.163434-1-ivo.ivanov.ivanov1 at gmail.com/
> [6] https://lore.kernel.org/all/20250215123922.163630-1-ivo.ivanov.ivanov1 at gmail.com/

BTW, you mixed dependencies here - like clock headers - with documenting
bindings. Clearly separate what is the dependency and where are the
bindings, if they are not merged at the time of sending this patchset.

> 
> Best regards,
> Ivaylo
> 


Best regards,
Krzysztof


From ziyao at disroot.org  Sat Mar  1 07:15:32 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat, 1 Mar 2025 15:15:32 +0000
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <0aefd292-7980-434d-9c18-4ab9f6a0b40e@kwiboo.se>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104835.36439-1-ziyao@disroot.org>
 <0aefd292-7980-434d-9c18-4ab9f6a0b40e@kwiboo.se>
Message-ID: <Z8MklJfFz2EA6oNS@pie.lan>

On Sat, Mar 01, 2025 at 02:01:05PM +0100, Jonas Karlman wrote:
> Hi,
> 
> On 2025-03-01 11:48, Yao Zi wrote:
> > SD-card is available on Radxa E20C board.
> > 
> > Signed-off-by: Yao Zi <ziyao at disroot.org>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> > index d2cdb63d4a9d..473065aa4228 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> > @@ -12,6 +12,10 @@ / {
> >  	model = "Radxa E20C";
> >  	compatible = "radxa,e20c", "rockchip,rk3528";
> >  
> > +	aliases {
> > +		mmc0 = &sdmmc;
> 
> Suggest using mmc1 for sd-card because the e20c typically have onboard
> emmc, compared to removable sd-card.

My board doesn't have an eMMC: it's optional as well, but all variants
of Radxa E20C come with an SD-card interface. The vendor devicetree sets
sdmmc as mmc0 as well[1].

I won't insist on it and am willing to take the change if you still
consider mmc0 is better.

> > +	};
> > +
> >  	chosen {
> >  		stdout-path = "serial0:1500000n8";
> >  	};
> > @@ -20,3 +24,13 @@ chosen {
> >  &uart0 {
> >  	status = "okay";
> >  };
> > +
> > +&sdmmc {
> > +	bus-width = <4>;
> > +	cap-mmc-highspeed;
> > +	cap-sd-highspeed;
> > +	disable-wp;
> > +	rockchip,default-sample-phase = <90>;
> > +	sd-uhs-sdr104;
> 
> Are you sure uhs-sdr104 works as is should?

In fact yes, tuning succeeds at 148.5MHz and results in 66MB/s reading
speed.

> Vendor kernel use a different "v2" tuning

This isn't a problem. IMHO V2 tuning is more like a quick path, which
tries inheritting the phase from firmware and then re-tunes roughly.
Fine tunning is still a fallback here in case of failure, see the commit
message in the downstream kernel[2]. And testing proves it's okay for
RK3528 to issue fine-tuning always.

> and this is also missing the vccio_sd vqmmc-supply to switch between
> 3v3 and 1v8.

But this is a problem, thanks for catching it! Somehow my card managed
to run at 148.5MHz with 3v3 voltage level, but it's definitely a
compatiblity issue. I'm surprised that the driver doesn't complain when
switching to SDR modes without a regulator configured.

> You could add following regulator for sdmmc:
> 
> 	vccio_sd: regulator-vccio-sd {
> 		compatible = "regulator-gpio";
> 		gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
> 		pinctrl-names = "default";
> 		pinctrl-0 = <&sdmmc_vol_ctrl_h>;
> 		regulator-name = "vccio_sd";
> 		regulator-min-microvolt = <1800000>;
> 		regulator-max-microvolt = <3300000>;
> 		states = <1800000 0x0>, <3300000 0x1>;
> 	};
>
> and following pinctrl:
> 
> 	sdmmc {
> 		sdmmc_vol_ctrl_h: sdmmc-vol-ctrl-h {
> 			rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
> 		};
> 	};
> 
> add then the power supplies to the sdmmc node:
> 
> 	vmmc-supply = <&vcc_3v3>;
> 	vqmmc-supply = <&vccio_sd>;
> 
> That matches the schematics for e20c, and works when testing non-uhs modes.

Thanks for the hints. Will rebase on your pinctrl series and get
regulators and pinctrl settings applied in the next version.

> Regards,
> Jonas
> 
> > +	status = "okay";
> > +};
> 

Cheers,
Yao Zi

[1]: https://github.com/radxa/kernel/blob/2b0c8de7dc4c68947cda206dcc2e457e9677e426/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts#L22-L26
[2]: https://github.com/rockchip-linux/kernel/commit/795e052cc8610aa59a64b104f975cc4a45493d5d


From claudiu.beznea at tuxon.dev  Sat Mar  1 07:24:03 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Sat, 1 Mar 2025 17:24:03 +0200
Subject: [PATCH v2 0/4] ARM: dts: at91: calao_usb: improve support
In-Reply-To: <20250226084938.3436-6-wsa+renesas@sang-engineering.com>
References: <20250226084938.3436-6-wsa+renesas@sang-engineering.com>
Message-ID: <35dd6819-591a-4dcb-9c01-f32e7f1db54a@tuxon.dev>



On 26.02.2025 10:49, Wolfram Sang wrote:
> Wolfram Sang (4):
>   dt-bindings: ARM: at91: make separate entry for Olimex board
>   dt-bindings: ARM: at91: add Calao USB boards

Applied to at91-soc, thanks!

>   ARM: dts: at91: usb_a9263: fix wrong vendor
>   ARM: dts: at91: fix faulty ohci/ehci node names

Applied to at91-dt, thanks!


From ericwouds at gmail.com  Sat Mar  1 07:47:32 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Sat, 1 Mar 2025 16:47:32 +0100
Subject: [PATCH v8 net-next 01/15] net: pppoe: avoid zero-length arrays in
 struct pppoe_hdr
In-Reply-To: <20250228201533.23836-2-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
 <20250228201533.23836-2-ericwouds@gmail.com>
Message-ID: <fc5129dd-35a8-4bcc-8e54-b8facda2cbc4@gmail.com>



On 2/28/25 9:15 PM, Eric Woudstra wrote:
>  drivers/net/ppp/pppoe.c       | 2 +-
>  include/uapi/linux/if_pppox.h | 4 ++++
>  2 files changed, 5 insertions(+), 1 deletion(-)

The maintainers email: Michal Ostrowski <mostrows at earthlink.net>
Returns 403: 550 5.5.1 Recipient rejected. This mailbox does not exist here.


From heiko at sntech.de  Sat Mar  1 09:35:45 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  1 Mar 2025 18:35:45 +0100
Subject: [PATCH v2 0/2] drm/rockchip: lvds: probe logging improvements
Message-ID: <20250301173547.710245-1-heiko@sntech.de>

Getting the panel already uses dev_err_probe to stay silent, when
the panel just probes later, and the lvds defers.

But the phy needed on px30, also has the capability to probe after
the lvds. So make the rest of the lvds probe/bind logic also use
more modern logging than DRM_DEV_ERR, that is deprecated anyway.

changes in v2:
- reword the messages about getting (and preparing) pclk (Quentin)
- use a ret = dev_err_probe(dev, -EINVAL, ...) pattern
  in some (additional) places (Quentin)

Heiko Stuebner (2):
  drm/rockchip: lvds: move pclk preparation in with clk_get
  drm/rockchip: lvds: Hide scary error messages on probe deferral

 drivers/gpu/drm/rockchip/rockchip_lvds.c | 78 +++++++++---------------
 1 file changed, 28 insertions(+), 50 deletions(-)

-- 
2.47.2



From heiko at sntech.de  Sat Mar  1 09:35:46 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  1 Mar 2025 18:35:46 +0100
Subject: [PATCH v2 1/2] drm/rockchip: lvds: move pclk preparation in with clk_get
In-Reply-To: <20250301173547.710245-1-heiko@sntech.de>
References: <20250301173547.710245-1-heiko@sntech.de>
Message-ID: <20250301173547.710245-2-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

The LVDS block needs a separate pclk only on some socs, so currently
requests and prepares it in the soc-specific probe function, but common
code is required to unprepare it in the error path or on driver remove.

While this works because clk_unprepare just does nothing if clk is NULL,
this mismatch of who is responsible still is not very nice.
The clock-framework already has a helper for clk-get-and-prepare even
with devres support in devm_clk_get_prepared().

This will get and prepare the clock and also unprepare it on driver
removal, saving the driver from having to handle it "manually".

Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>
Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 385cf6881504..ecfae8d5da89 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -448,15 +448,13 @@ struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs = {
 static int rk3288_lvds_probe(struct platform_device *pdev,
 			     struct rockchip_lvds *lvds)
 {
-	int ret;
-
 	lvds->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(lvds->regs))
 		return PTR_ERR(lvds->regs);
 
-	lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
+	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
 	if (IS_ERR(lvds->pclk)) {
-		DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
+		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
 		return PTR_ERR(lvds->pclk);
 	}
 
@@ -480,12 +478,6 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 		}
 	}
 
-	ret = clk_prepare(lvds->pclk);
-	if (ret < 0) {
-		DRM_DEV_ERROR(lvds->dev, "failed to prepare pclk_lvds\n");
-		return ret;
-	}
-
 	return 0;
 }
 
@@ -728,20 +720,15 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
 	dev_set_drvdata(dev, lvds);
 
 	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
-	if (ret < 0) {
+	if (ret < 0)
 		DRM_DEV_ERROR(dev, "failed to add component\n");
-		clk_unprepare(lvds->pclk);
-	}
 
 	return ret;
 }
 
 static void rockchip_lvds_remove(struct platform_device *pdev)
 {
-	struct rockchip_lvds *lvds = platform_get_drvdata(pdev);
-
 	component_del(&pdev->dev, &rockchip_lvds_component_ops);
-	clk_unprepare(lvds->pclk);
 }
 
 struct platform_driver rockchip_lvds_driver = {
-- 
2.47.2



From heiko at sntech.de  Sat Mar  1 09:35:47 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  1 Mar 2025 18:35:47 +0100
Subject: [PATCH v2 2/2] drm/rockchip: lvds: Hide scary error messages on probe deferral
In-Reply-To: <20250301173547.710245-1-heiko@sntech.de>
References: <20250301173547.710245-1-heiko@sntech.de>
Message-ID: <20250301173547.710245-3-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

Commit 52d11c863ac9 ("drm/rockchip: lvds: do not print scary message when
probing defer") already started hiding scary messages that are not relevant
if the requested supply just returned EPROBE_DEFER, but there are more
possible sources - like the phy.

So modernize the whole logging in the probe path by replacing the
remaining deprecated DRM_DEV_ERROR with appropriate dev_err(_probe)
and drm_err calls.

The distinction here is that all messages talking about mishaps of the
lvds element use dev_err(_probe) while messages caused by interaction
with the main Rockchip drm-device use drm_err.

Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 61 ++++++++++--------------
 1 file changed, 26 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index ecfae8d5da89..d8b2007123fa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -453,10 +453,9 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 		return PTR_ERR(lvds->regs);
 
 	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
-	if (IS_ERR(lvds->pclk)) {
-		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
-		return PTR_ERR(lvds->pclk);
-	}
+	if (IS_ERR(lvds->pclk))
+		return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk),
+				     "could not get or prepare pclk_lvds\n");
 
 	lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
 				  GFP_KERNEL);
@@ -465,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 
 	lvds->pins->p = devm_pinctrl_get(lvds->dev);
 	if (IS_ERR(lvds->pins->p)) {
-		DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
+		dev_err(lvds->dev, "no pinctrl handle\n");
 		devm_kfree(lvds->dev, lvds->pins);
 		lvds->pins = NULL;
 	} else {
 		lvds->pins->default_state =
 			pinctrl_lookup_state(lvds->pins->p, "lcdc");
 		if (IS_ERR(lvds->pins->default_state)) {
-			DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
+			dev_err(lvds->dev, "no default pinctrl state\n");
 			devm_kfree(lvds->dev, lvds->pins);
 			lvds->pins = NULL;
 		}
@@ -547,11 +546,10 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	lvds->drm_dev = drm_dev;
 	port = of_graph_get_port_by_id(dev->of_node, 1);
-	if (!port) {
-		DRM_DEV_ERROR(dev,
-			      "can't found port point, please init lvds panel port!\n");
-		return -EINVAL;
-	}
+	if (!port)
+		return dev_err_probe(dev, -EINVAL,
+				     "can't found port point, please init lvds panel port!\n");
+
 	for_each_child_of_node(port, endpoint) {
 		child_count++;
 		of_property_read_u32(endpoint, "reg", &endpoint_id);
@@ -563,8 +561,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		}
 	}
 	if (!child_count) {
-		DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
-		ret = -EINVAL;
+		ret = dev_err_probe(dev, -EINVAL, "lvds port does not have any children\n");
 		goto err_put_port;
 	} else if (ret) {
 		dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
@@ -581,8 +578,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		lvds->output = rockchip_lvds_name_to_output(name);
 
 	if (lvds->output < 0) {
-		DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name);
-		ret = lvds->output;
+		ret = dev_err_probe(dev, lvds->output, "invalid output type [%s]\n", name);
 		goto err_put_remote;
 	}
 
@@ -593,7 +589,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		lvds->format = rockchip_lvds_name_to_format(name);
 
 	if (lvds->format < 0) {
-		DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
+		dev_err(dev, "invalid data-mapping format [%s]\n", name);
 		ret = lvds->format;
 		goto err_put_remote;
 	}
@@ -604,8 +600,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_LVDS);
 	if (ret < 0) {
-		DRM_DEV_ERROR(drm_dev->dev,
-			      "failed to initialize encoder: %d\n", ret);
+		drm_err(drm_dev,
+			"failed to initialize encoder: %d\n", ret);
 		goto err_put_remote;
 	}
 
@@ -618,8 +614,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 					 &rockchip_lvds_connector_funcs,
 					 DRM_MODE_CONNECTOR_LVDS);
 		if (ret < 0) {
-			DRM_DEV_ERROR(drm_dev->dev,
-				      "failed to initialize connector: %d\n", ret);
+			drm_err(drm_dev,
+				"failed to initialize connector: %d\n", ret);
 			goto err_free_encoder;
 		}
 
@@ -633,9 +629,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 		connector = drm_bridge_connector_init(lvds->drm_dev, encoder);
 		if (IS_ERR(connector)) {
-			DRM_DEV_ERROR(drm_dev->dev,
-				      "failed to initialize bridge connector: %pe\n",
-				      connector);
+			drm_err(drm_dev,
+				"failed to initialize bridge connector: %pe\n",
+				connector);
 			ret = PTR_ERR(connector);
 			goto err_free_encoder;
 		}
@@ -643,8 +639,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	ret = drm_connector_attach_encoder(connector, encoder);
 	if (ret < 0) {
-		DRM_DEV_ERROR(drm_dev->dev,
-			      "failed to attach encoder: %d\n", ret);
+		drm_err(drm_dev, "failed to attach encoder: %d\n", ret);
 		goto err_free_connector;
 	}
 
@@ -706,24 +701,20 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
 
 	lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
 						    "rockchip,grf");
-	if (IS_ERR(lvds->grf)) {
-		DRM_DEV_ERROR(dev, "missing rockchip,grf property\n");
-		return PTR_ERR(lvds->grf);
-	}
+	if (IS_ERR(lvds->grf))
+		return dev_err_probe(dev, PTR_ERR(lvds->grf), "missing rockchip,grf property\n");
 
 	ret = lvds->soc_data->probe(pdev, lvds);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Platform initialization failed\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Platform initialization failed\n");
 
 	dev_set_drvdata(dev, lvds);
 
 	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
 	if (ret < 0)
-		DRM_DEV_ERROR(dev, "failed to add component\n");
+		return dev_err_probe(dev, ret, "failed to add component\n");
 
-	return ret;
+	return 0;
 }
 
 static void rockchip_lvds_remove(struct platform_device *pdev)
-- 
2.47.2



From lkp at intel.com  Sat Mar  1 09:47:17 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 01:47:17 +0800
Subject: [PATCH 02/18] rtc: s5m: drop needless struct s5m_rtc_info::i2c
 member
In-Reply-To: <20250228-rtc-cleanups-v1-2-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-2-b44cec078481@linaro.org>
Message-ID: <202503020150.LkqTktVQ-lkp@intel.com>

Hi Andr?,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 0226d0ce98a477937ed295fb7df4cc30b46fc304]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Draszik/rtc-max77686-drop-needless-struct-max77686_rtc_info-rtc-member/20250228-221320
base:   0226d0ce98a477937ed295fb7df4cc30b46fc304
patch link:    https://lore.kernel.org/r/20250228-rtc-cleanups-v1-2-b44cec078481%40linaro.org
patch subject: [PATCH 02/18] rtc: s5m: drop needless struct s5m_rtc_info::i2c member
config: arm-randconfig-004-20250301 (https://download.01.org/0day-ci/archive/20250302/202503020150.LkqTktVQ-lkp at intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020150.LkqTktVQ-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020150.LkqTktVQ-lkp at intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/rtc/rtc-s5m.c:11:
   In file included from include/linux/i2c.h:19:
   In file included from include/linux/regulator/consumer.h:35:
   In file included from include/linux/suspend.h:5:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:21:
   In file included from include/linux/mm.h:2287:
   include/linux/vmstat.h:507:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     507 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
>> drivers/rtc/rtc-s5m.c:678:46: warning: variable 'i2c' is uninitialized when used here [-Wuninitialized]
     678 |         i2c = devm_i2c_new_dummy_device(&pdev->dev, i2c->adapter,
         |                                                     ^~~
   drivers/rtc/rtc-s5m.c:642:24: note: initialize the variable 'i2c' to silence this warning
     642 |         struct i2c_client *i2c;
         |                               ^
         |                                = NULL
   2 warnings generated.


vim +/i2c +678 drivers/rtc/rtc-s5m.c

   637	
   638	static int s5m_rtc_probe(struct platform_device *pdev)
   639	{
   640		struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
   641		struct s5m_rtc_info *info;
   642		struct i2c_client *i2c;
   643		const struct regmap_config *regmap_cfg;
   644		int ret, alarm_irq;
   645	
   646		info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
   647		if (!info)
   648			return -ENOMEM;
   649	
   650		switch (platform_get_device_id(pdev)->driver_data) {
   651		case S2MPS15X:
   652			regmap_cfg = &s2mps14_rtc_regmap_config;
   653			info->regs = &s2mps15_rtc_regs;
   654			alarm_irq = S2MPS14_IRQ_RTCA0;
   655			break;
   656		case S2MPS14X:
   657			regmap_cfg = &s2mps14_rtc_regmap_config;
   658			info->regs = &s2mps14_rtc_regs;
   659			alarm_irq = S2MPS14_IRQ_RTCA0;
   660			break;
   661		case S2MPS13X:
   662			regmap_cfg = &s2mps14_rtc_regmap_config;
   663			info->regs = &s2mps13_rtc_regs;
   664			alarm_irq = S2MPS14_IRQ_RTCA0;
   665			break;
   666		case S5M8767X:
   667			regmap_cfg = &s5m_rtc_regmap_config;
   668			info->regs = &s5m_rtc_regs;
   669			alarm_irq = S5M8767_IRQ_RTCA1;
   670			break;
   671		default:
   672			dev_err(&pdev->dev,
   673					"Device type %lu is not supported by RTC driver\n",
   674					platform_get_device_id(pdev)->driver_data);
   675			return -ENODEV;
   676		}
   677	
 > 678		i2c = devm_i2c_new_dummy_device(&pdev->dev, i2c->adapter,
   679						RTC_I2C_ADDR);
   680		if (IS_ERR(i2c)) {
   681			dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
   682			return PTR_ERR(i2c);
   683		}
   684	
   685		info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
   686		if (IS_ERR(info->regmap)) {
   687			ret = PTR_ERR(info->regmap);
   688			dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
   689					ret);
   690			return ret;
   691		}
   692	
   693		info->dev = &pdev->dev;
   694		info->s5m87xx = s5m87xx;
   695		info->device_type = platform_get_device_id(pdev)->driver_data;
   696	
   697		if (s5m87xx->irq_data) {
   698			info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
   699			if (info->irq <= 0) {
   700				dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
   701					alarm_irq);
   702				return -EINVAL;
   703			}
   704		}
   705	
   706		platform_set_drvdata(pdev, info);
   707	
   708		ret = s5m8767_rtc_init_reg(info);
   709		if (ret)
   710			return ret;
   711	
   712		info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
   713		if (IS_ERR(info->rtc_dev))
   714			return PTR_ERR(info->rtc_dev);
   715	
   716		info->rtc_dev->ops = &s5m_rtc_ops;
   717	
   718		info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
   719		info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
   720	
   721		if (!info->irq) {
   722			clear_bit(RTC_FEATURE_ALARM, info->rtc_dev->features);
   723		} else {
   724			ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
   725							s5m_rtc_alarm_irq, 0, "rtc-alarm0",
   726							info);
   727			if (ret < 0) {
   728				dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
   729					info->irq, ret);
   730				return ret;
   731			}
   732			device_init_wakeup(&pdev->dev, true);
   733		}
   734	
   735		return devm_rtc_register_device(info->rtc_dev);
   736	}
   737	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From tglx at linutronix.de  Sat Mar  1 10:09:35 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Sat, 01 Mar 2025 19:09:35 +0100
Subject: [PATCH v15 00/15] PCI: EP: Add RC-to-EP doorbell with platform
 MSI controller
In-Reply-To: <86ldtpot6m.wl-maz@kernel.org>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
 <Z7eKBsxrmthtElpz@lizhi-Precision-Tower-5810>
 <86ldtpot6m.wl-maz@kernel.org>
Message-ID: <87senwd3mo.ffs@tglx>

On Sat, Mar 01 2025 at 12:02, Marc Zyngier wrote:
> - This IMMUTABLE thing serves no purpose, because you don't randomly
>   plug this end-point block on any MSI controller. They come as part
>   of an SoC.

Yes and no. The problem is that the EP implementation is meant to be a
generic library and while GIC-ITS guarantees immutability of the
address/data pair after setup, there are architectures (x86, loongson,
riscv) where the base MSI controller does not and immutability is only
achieved when interrupt remapping is enabled. The latter can be disabled
at boot-time and then the EP implementation becomes a lottery across
affinity changes.

That was my concern about this library implementation and that's why I
asked for a mechanism to ensure that the underlying irqdomain provides a
immutable address/data pair.

So it does not matter for GIC-ITS, but in the larger picture it matters.

Thanks,

        tglx


From linus.walleij at linaro.org  Sat Mar  1 10:11:56 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Sat, 1 Mar 2025 19:11:56 +0100
Subject: [PATCH 10/18] rtc: pl030: drop needless struct pl030_rtc::rtc member
In-Reply-To: <20250228-rtc-cleanups-v1-10-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org> <20250228-rtc-cleanups-v1-10-b44cec078481@linaro.org>
Message-ID: <CACRpkdamF4B1y+zr-Y_XB8gAoSv2Q2U4VxuZd+ivZq7KV1Quyw@mail.gmail.com>

On Fri, Feb 28, 2025 at 3:07?PM Andr? Draszik <andre.draszik at linaro.org> wrote:

> The memory pointed to by the ::rtc member is managed via devres, and
> no code in this driver uses it past _probe().
>
> We can drop it from the structure and just use a local temporary
> variable, reducing runtime memory consumption by a few bytes.
>
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From linus.walleij at linaro.org  Sat Mar  1 10:12:25 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Sat, 1 Mar 2025 19:12:25 +0100
Subject: [PATCH 06/18] rtc: ftrtc010: drop needless struct
 ftrtc010_rtc::rtc_dev member
In-Reply-To: <20250228-rtc-cleanups-v1-6-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org> <20250228-rtc-cleanups-v1-6-b44cec078481@linaro.org>
Message-ID: <CACRpkdaWjTiqSUj59YiQZ1jsJWzHZPMo3xS6n4_JwdAW6B_Kfg@mail.gmail.com>

On Fri, Feb 28, 2025 at 3:07?PM Andr? Draszik <andre.draszik at linaro.org> wrote:

> The memory pointed to by the ::rtc_dev member is managed via devres,
> and no code in this driver uses it past _probe().
>
> We can drop it from the structure and just use a local temporary
> variable, reducing runtime memory consumption by a few bytes.
>
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From dmitry.baryshkov at linaro.org  Sat Mar  1 10:14:19 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat, 1 Mar 2025 20:14:19 +0200
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <20250223113036.74252-3-andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
Message-ID: <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>

On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> The DW DP TX Controller is compliant with the DisplayPort Specification
> Version 1.4 with the following features:
> 
> * DisplayPort 1.4a
> * Main Link: 1/2/4 lanes
> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
> * AUX channel 1Mbps
> * Single Stream Transport(SST)
> * Multistream Transport (MST)
> *?Type-C support (alternate mode)
> * HDCP 2.2, HDCP 1.3
> * Supports up to 8/10 bits per color component
> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
> * Pixel clock up to 594MHz
> * I2S, SPDIF audio interface
> 
> Add library with common helpers to make it can be shared with
> other SoC.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> 
> drm/bridge: cleanup

Stray line?

> 
> ---
> 
>  drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
>  drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
>  drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
>  include/drm/bridge/dw_dp.h               |   19 +
>  4 files changed, 2182 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
>  create mode 100644 include/drm/bridge/dw_dp.h
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
> index f3ab2f985f8c..2c5e532410de 100644
> --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
> +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
> @@ -1,4 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> +config DRM_DW_DP
> +	tristate
> +	select DRM_DISPLAY_HELPER
> +	select DRM_DISPLAY_DP_HELPER
> +	select DRM_KMS_HELPER
> +	select REGMAP_MMIO
> +
>  config DRM_DW_HDMI
>  	tristate
>  	select DRM_DISPLAY_HDMI_HELPER
> diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
> index 9dc376d220ad..4dada44029ac 100644
> --- a/drivers/gpu/drm/bridge/synopsys/Makefile
> +++ b/drivers/gpu/drm/bridge/synopsys/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_DRM_DW_DP) += dw-dp.o
>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> new file mode 100644
> index 000000000000..6ecbe9851369
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> @@ -0,0 +1,2155 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Synopsys DesignWare Cores DisplayPort Transmitter Controller
> + *
> + * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
> + *
> + * Author: Andy Yan <andy.yan at rock-chips.com>
> + */
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/iopoll.h>
> +#include <linux/irq.h>
> +#include <linux/of_device.h>
> +#include <linux/of_graph.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/phy/phy.h>
> +#include <linux/unaligned.h>
> +
> +#include <drm/bridge/dw_dp.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_bridge_connector.h>
> +#include <drm/display/drm_dp_helper.h>
> +#include <drm/display/drm_hdmi_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +
> +#include <uapi/linux/media-bus-format.h>
> +
> +#define DW_DP_VERSION_NUMBER			0x0000
> +#define DW_DP_VERSION_TYPE			0x0004
> +#define DW_DP_ID					0x0008
> +
> +#define DW_DP_CONFIG_REG1			0x0100
> +#define DW_DP_CONFIG_REG2			0x0104
> +#define DW_DP_CONFIG_REG3			0x0108
> +
> +#define DW_DP_CCTL				0x0200
> +#define FORCE_HPD				BIT(4)
> +#define DEFAULT_FAST_LINK_TRAIN_EN		BIT(2)
> +#define ENHANCE_FRAMING_EN			BIT(1)
> +#define SCRAMBLE_DIS				BIT(0)
> +#define DW_DP_SOFT_RESET_CTRL			0x0204
> +#define VIDEO_RESET				BIT(5)
> +#define AUX_RESET				BIT(4)
> +#define AUDIO_SAMPLER_RESET			BIT(3)
> +#define HDCP_MODULE_RESET			BIT(2)
> +#define PHY_SOFT_RESET				BIT(1)
> +#define CONTROLLER_RESET			BIT(0)
> +
> +#define DW_DP_VSAMPLE_CTRL			0x0300
> +#define PIXEL_MODE_SELECT			GENMASK(22, 21)
> +#define VIDEO_MAPPING				GENMASK(20, 16)
> +#define VIDEO_STREAM_ENABLE			BIT(5)
> +
> +#define DW_DP_VSAMPLE_STUFF_CTRL1		0x0304
> +
> +#define DW_DP_VSAMPLE_STUFF_CTRL2		0x0308
> +
> +#define DW_DP_VINPUT_POLARITY_CTRL		0x030c
> +#define DE_IN_POLARITY				BIT(2)
> +#define HSYNC_IN_POLARITY			BIT(1)
> +#define VSYNC_IN_POLARITY			BIT(0)
> +
> +#define DW_DP_VIDEO_CONFIG1			0x0310
> +#define HACTIVE					GENMASK(31, 16)
> +#define HBLANK					GENMASK(15, 2)
> +#define I_P					BIT(1)
> +#define R_V_BLANK_IN_OSC			BIT(0)
> +
> +#define DW_DP_VIDEO_CONFIG2			0x0314
> +#define VBLANK					GENMASK(31, 16)
> +#define VACTIVE					GENMASK(15, 0)
> +
> +#define DW_DP_VIDEO_CONFIG3			0x0318
> +#define H_SYNC_WIDTH				GENMASK(31, 16)
> +#define H_FRONT_PORCH				GENMASK(15, 0)
> +
> +#define DW_DP_VIDEO_CONFIG4			0x031c
> +#define V_SYNC_WIDTH				GENMASK(31, 16)
> +#define V_FRONT_PORCH				GENMASK(15, 0)
> +
> +#define DW_DP_VIDEO_CONFIG5			0x0320
> +#define INIT_THRESHOLD_HI			GENMASK(22, 21)
> +#define AVERAGE_BYTES_PER_TU_FRAC		GENMASK(19, 16)
> +#define INIT_THRESHOLD				GENMASK(13, 7)
> +#define AVERAGE_BYTES_PER_TU			GENMASK(6, 0)
> +
> +#define DW_DP_VIDEO_MSA1				0x0324
> +#define VSTART					GENMASK(31, 16)
> +#define HSTART					GENMASK(15, 0)
> +
> +#define DW_DP_VIDEO_MSA2			0x0328
> +#define MISC0					GENMASK(31, 24)
> +
> +#define DW_DP_VIDEO_MSA3			0x032c
> +#define MISC1					GENMASK(31, 24)
> +
> +#define DW_DP_VIDEO_HBLANK_INTERVAL		0x0330
> +#define HBLANK_INTERVAL_EN			BIT(16)
> +#define HBLANK_INTERVAL				GENMASK(15, 0)
> +
> +#define DW_DP_AUD_CONFIG1			0x0400
> +#define AUDIO_TIMESTAMP_VERSION_NUM		GENMASK(29, 24)
> +#define AUDIO_PACKET_ID				GENMASK(23, 16)
> +#define AUDIO_MUTE				BIT(15)
> +#define NUM_CHANNELS				GENMASK(14, 12)
> +#define HBR_MODE_ENABLE				BIT(10)
> +#define AUDIO_DATA_WIDTH			GENMASK(9, 5)
> +#define AUDIO_DATA_IN_EN			GENMASK(4, 1)
> +#define AUDIO_INF_SELECT			BIT(0)
> +
> +#define DW_DP_SDP_VERTICAL_CTRL			0x0500
> +#define EN_VERTICAL_SDP				BIT(2)
> +#define EN_AUDIO_STREAM_SDP			BIT(1)
> +#define EN_AUDIO_TIMESTAMP_SDP			BIT(0)
> +#define DW_DP_SDP_HORIZONTAL_CTRL		0x0504
> +#define EN_HORIZONTAL_SDP			BIT(2)
> +#define DW_DP_SDP_STATUS_REGISTER		0x0508
> +#define DW_DP_SDP_MANUAL_CTRL			0x050c
> +#define DW_DP_SDP_STATUS_EN			0x0510
> +
> +#define DW_DP_SDP_REGISTER_BANK			0x0600
> +#define SDP_REGS				GENMASK(31, 0)
> +
> +#define DW_DP_PHYIF_CTRL			0x0a00
> +#define PHY_WIDTH				BIT(25)
> +#define PHY_POWERDOWN				GENMASK(20, 17)
> +#define PHY_BUSY				GENMASK(15, 12)
> +#define SSC_DIS					BIT(16)
> +#define XMIT_ENABLE				GENMASK(11, 8)
> +#define PHY_LANES				GENMASK(7, 6)
> +#define PHY_RATE				GENMASK(5, 4)
> +#define TPS_SEL					GENMASK(3, 0)
> +
> +#define DW_DP_PHY_TX_EQ				0x0a04
> +#define DW_DP_CUSTOMPAT0			0x0a08
> +#define DW_DP_CUSTOMPAT1			0x0a0c
> +#define DW_DP_CUSTOMPAT2			0x0a10
> +#define DW_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	0x0a14
> +#define DW_DP_PHYIF_PWRDOWN_CTRL		0x0a18
> +
> +#define DW_DP_AUX_CMD				0x0b00
> +#define AUX_CMD_TYPE				GENMASK(31, 28)
> +#define AUX_ADDR				GENMASK(27, 8)
> +#define I2C_ADDR_ONLY				BIT(4)
> +#define AUX_LEN_REQ				GENMASK(3, 0)
> +
> +#define DW_DP_AUX_STATUS			0x0b04
> +#define AUX_TIMEOUT				BIT(17)
> +#define AUX_BYTES_READ				GENMASK(23, 19)
> +#define AUX_STATUS				GENMASK(7, 4)
> +
> +#define DW_DP_AUX_DATA0				0x0b08
> +#define DW_DP_AUX_DATA1				0x0b0c
> +#define DW_DP_AUX_DATA2				0x0b10
> +#define DW_DP_AUX_DATA3				0x0b14
> +
> +#define DW_DP_GENERAL_INTERRUPT			0x0d00
> +#define VIDEO_FIFO_OVERFLOW_STREAM0		BIT(6)
> +#define AUDIO_FIFO_OVERFLOW_STREAM0		BIT(5)
> +#define SDP_EVENT_STREAM0			BIT(4)
> +#define AUX_CMD_INVALID				BIT(3)
> +#define HDCP_EVENT				BIT(2)
> +#define AUX_REPLY_EVENT				BIT(1)
> +#define HPD_EVENT				BIT(0)
> +
> +#define DW_DP_GENERAL_INTERRUPT_ENABLE		0x0d04
> +#define HDCP_EVENT_EN				BIT(2)
> +#define AUX_REPLY_EVENT_EN			BIT(1)
> +#define HPD_EVENT_EN				BIT(0)
> +
> +#define DW_DP_HPD_STATUS			0x0d08
> +#define HPD_STATE				GENMASK(11, 9)
> +#define HPD_STATUS				BIT(8)
> +#define HPD_HOT_UNPLUG				BIT(2)
> +#define HPD_HOT_PLUG				BIT(1)
> +#define HPD_IRQ					BIT(0)
> +
> +#define DW_DP_HPD_INTERRUPT_ENABLE		0x0d0c
> +#define HPD_UNPLUG_ERR_EN			BIT(3)
> +#define HPD_UNPLUG_EN				BIT(2)
> +#define HPD_PLUG_EN				BIT(1)
> +#define HPD_IRQ_EN				BIT(0)
> +
> +#define DW_DP_HDCP_CFG				0x0e00
> +#define DPCD12PLUS				BIT(7)
> +#define CP_IRQ					BIT(6)
> +#define BYPENCRYPTION				BIT(5)
> +#define HDCP_LOCK				BIT(4)
> +#define ENCRYPTIONDISABLE			BIT(3)
> +#define ENABLE_HDCP_13				BIT(2)
> +#define ENABLE_HDCP				BIT(1)
> +
> +#define DW_DP_HDCP_OBS				0x0e04
> +#define HDCP22_RE_AUTHENTICATION_REQ		BIT(31)
> +#define HDCP22_AUTHENTICATION_FAILED		BIT(30)
> +#define HDCP22_AUTHENTICATION_SUCCESS		BIT(29)
> +#define HDCP22_CAPABLE_SINK			BIT(28)
> +#define HDCP22_SINK_CAP_CHECK_COMPLETE		BIT(27)
> +#define HDCP22_STATE				GENMASK(26, 24)
> +#define HDCP22_BOOTED				BIT(23)
> +#define HDCP13_BSTATUS				GENMASK(22, 19)
> +#define REPEATER				BIT(18)
> +#define HDCP_CAPABLE				BIT(17)
> +#define STATEE					GENMASK(16, 14)
> +#define STATEOEG				GENMASK(13, 11)
> +#define STATER					GENMASK(10, 8)
> +#define STATEA					GENMASK(7, 4)
> +#define SUBSTATEA				GENMASK(3, 1)
> +#define HDCPENGAGED				BIT(0)
> +
> +#define DW_DP_HDCP_APIINTCLR			0x0e08
> +#define DW_DP_HDCP_APIINTSTAT			0x0e0c
> +#define DW_DP_HDCP_APIINTMSK			0x0e10
> +#define HDCP22_GPIOINT				BIT(8)
> +#define HDCP_ENGAGED				BIT(7)
> +#define HDCP_FAILED				BIT(6)
> +#define KSVSHA1CALCDONEINT			BIT(5)
> +#define AUXRESPNACK7TIMES			BIT(4)
> +#define AUXRESPTIMEOUT				BIT(3)
> +#define AUXRESPDEFER7TIMES			BIT(2)
> +#define KSVACCESSINT				BIT(0)
> +
> +#define DW_DP_HDCP_KSVMEMCTRL			0x0e18
> +#define KSVSHA1STATUS				BIT(4)
> +#define KSVMEMACCESS				BIT(1)
> +#define KSVMEMREQUEST				BIT(0)
> +
> +#define DW_DP_HDCP_REG_BKSV0			0x3600
> +#define DW_DP_HDCP_REG_BKSV1			0x3604
> +#define DW_DP_HDCP_REG_ANCONF			0x3608
> +#define AN_BYPASS				BIT(0)
> +
> +#define DW_DP_HDCP_REG_AN0			0x360c
> +#define DW_DP_HDCP_REG_AN1			0x3610
> +#define DW_DP_HDCP_REG_RMLCTL			0x3614
> +#define ODPK_DECRYPT_ENABLE			BIT(0)
> +
> +#define DW_DP_HDCP_REG_RMLSTS			0x3618
> +#define IDPK_WR_OK_STS				BIT(6)
> +#define	IDPK_DATA_INDEX				GENMASK(5, 0)
> +#define DW_DP_HDCP_REG_SEED			0x361c
> +#define DW_DP_HDCP_REG_DPK0			0x3620
> +#define DW_DP_HDCP_REG_DPK1			0x3624
> +#define DW_DP_HDCP22_GPIOSTS			0x3628
> +#define DW_DP_HDCP22_GPIOCHNGSTS		0x362c
> +#define DW_DP_HDCP_REG_DPK_CRC			0x3630
> +
> +#define DW_DP_MAX_REGISTER			DW_DP_HDCP_REG_DPK_CRC
> +
> +#define SDP_REG_BANK_SIZE			16
> +
> +struct dw_dp_link_caps {
> +	bool enhanced_framing;
> +	bool tps3_supported;
> +	bool tps4_supported;
> +	bool fast_training;
> +	bool channel_coding;
> +	bool ssc;
> +};
> +
> +struct dw_dp_link_train_set {
> +	unsigned int voltage_swing[4];
> +	unsigned int pre_emphasis[4];
> +	bool voltage_max_reached[4];
> +	bool pre_max_reached[4];
> +};
> +
> +struct dw_dp_link_train {
> +	struct dw_dp_link_train_set request;
> +	struct dw_dp_link_train_set adjust;
> +	bool clock_recovered;
> +	bool channel_equalized;
> +};
> +
> +struct dw_dp_link {
> +	u8 dpcd[DP_RECEIVER_CAP_SIZE];
> +	unsigned char revision;
> +	unsigned int rate;
> +	unsigned int lanes;
> +	u8 sink_count;
> +	u8 vsc_sdp_supported;
> +	struct dw_dp_link_caps caps;
> +	struct dw_dp_link_train train;
> +	struct drm_dp_desc desc;
> +};
> +
> +struct dw_dp_video {
> +	struct drm_display_mode mode;
> +	u8 video_mapping;
> +	u8 pixel_mode;
> +	u8 color_format;
> +	u8 bpc;
> +	u8 bpp;
> +};
> +
> +struct dw_dp_sdp {
> +	struct dp_sdp_header header;
> +	u8 db[32];

struct dp_sdp, please

> +	unsigned long flags;
> +};
> +
> +struct dw_dp_hotplug {
> +	bool long_hpd;
> +};
> +
> +struct dw_dp {
> +	struct drm_bridge bridge;
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct phy *phy;
> +	struct clk *apb_clk;
> +	struct clk *aux_clk;
> +	struct clk *i2s_clk;
> +	struct clk *spdif_clk;
> +	struct clk *hdcp_clk;
> +	struct reset_control *rstc;
> +	struct completion complete;
> +	int irq;
> +	struct work_struct hpd_work;
> +	struct dw_dp_hotplug hotplug;
> +	struct mutex irq_lock;
> +
> +	struct drm_dp_aux aux;
> +
> +	struct dw_dp_link link;
> +	struct dw_dp_video video;
> +	const struct dw_dp_plat_data *plat_data;
> +
> +	DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> +};
> +
> +enum {
> +	DW_DP_RGB_6BIT,
> +	DW_DP_RGB_8BIT,
> +	DW_DP_RGB_10BIT,
> +	DW_DP_RGB_12BIT,
> +	DW_DP_RGB_16BIT,
> +	DW_DP_YCBCR444_8BIT,
> +	DW_DP_YCBCR444_10BIT,
> +	DW_DP_YCBCR444_12BIT,
> +	DW_DP_YCBCR444_16BIT,
> +	DW_DP_YCBCR422_8BIT,
> +	DW_DP_YCBCR422_10BIT,
> +	DW_DP_YCBCR422_12BIT,
> +	DW_DP_YCBCR422_16BIT,
> +	DW_DP_YCBCR420_8BIT,
> +	DW_DP_YCBCR420_10BIT,
> +	DW_DP_YCBCR420_12BIT,
> +	DW_DP_YCBCR420_16BIT,
> +};
> +
> +enum {
> +	DW_DP_MP_SINGLE_PIXEL,
> +	DW_DP_MP_DUAL_PIXEL,
> +	DW_DP_MP_QUAD_PIXEL,
> +};
> +
> +enum {
> +	DW_DP_SDP_VERTICAL_INTERVAL = BIT(0),
> +	DW_DP_SDP_HORIZONTAL_INTERVAL = BIT(1),
> +};
> +
> +enum {
> +	DW_DP_HPD_STATE_IDLE,
> +	DW_DP_HPD_STATE_UNPLUG,
> +	DP_DP_HPD_STATE_TIMEOUT = 4,
> +	DW_DP_HPD_STATE_PLUG = 7
> +};
> +
> +enum {
> +	DW_DP_PHY_PATTERN_NONE,
> +	DW_DP_PHY_PATTERN_TPS_1,
> +	DW_DP_PHY_PATTERN_TPS_2,
> +	DW_DP_PHY_PATTERN_TPS_3,
> +	DW_DP_PHY_PATTERN_TPS_4,
> +	DW_DP_PHY_PATTERN_SERM,
> +	DW_DP_PHY_PATTERN_PBRS7,
> +	DW_DP_PHY_PATTERN_CUSTOM_80BIT,
> +	DW_DP_PHY_PATTERN_CP2520_1,
> +	DW_DP_PHY_PATTERN_CP2520_2,
> +};
> +
> +struct dw_dp_output_format {
> +	u32 bus_format;
> +	u32 color_format;
> +	u8 video_mapping;
> +	u8 bpc;
> +	u8 bpp;
> +};
> +
> +static const struct dw_dp_output_format dw_dp_output_formats[] = {
> +	{ MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
> +	{ MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
> +	{ MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
> +	{ MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
> +	{ MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
> +	{ MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
> +	{ MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
> +	{ MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
> +	{ MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
> +};
> +
> +static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++)
> +		if (dw_dp_output_formats[i].bus_format == bus_format)
> +			return &dw_dp_output_formats[i];
> +
> +	return &dw_dp_output_formats[1];

Why? Shouldn't it be NULL?

> +}
> +
> +static inline struct dw_dp *bridge_to_dp(struct drm_bridge *b)
> +{
> +	return container_of(b, struct dw_dp, bridge);
> +}
> +
> +static inline void dw_dp_phy_set_pattern(struct dw_dp *dp, u32 pattern)
> +{
> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, TPS_SEL,
> +			   FIELD_PREP(TPS_SEL, pattern));
> +}
> +
> +static void dw_dp_phy_xmit_enable(struct dw_dp *dp, u32 lanes)
> +{
> +	u32 xmit_enable;
> +
> +	switch (lanes) {
> +	case 4:
> +	case 2:
> +	case 1:
> +		xmit_enable = GENMASK(lanes - 1, 0);
> +		break;
> +	case 0:
> +	default:
> +		xmit_enable = 0;
> +		break;
> +	}
> +
> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, XMIT_ENABLE,
> +			   FIELD_PREP(XMIT_ENABLE, xmit_enable));
> +}
> +
> +static bool dw_dp_bandwidth_ok(struct dw_dp *dp,
> +			       const struct drm_display_mode *mode, u32 bpp,
> +			       unsigned int lanes, unsigned int rate)
> +{
> +	u32 max_bw, req_bw;
> +
> +	req_bw = mode->clock * bpp / 8;
> +	max_bw = lanes * rate;
> +	if (req_bw > max_bw)
> +		return false;
> +
> +	return true;
> +}
> +
> +static bool dw_dp_hpd_detect(struct dw_dp *dp)
> +{
> +	u32 value;
> +
> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> +
> +	return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> +}
> +
> +static void dw_dp_link_caps_reset(struct dw_dp_link_caps *caps)
> +{
> +	caps->enhanced_framing = false;
> +	caps->tps3_supported = false;
> +	caps->tps4_supported = false;
> +	caps->fast_training = false;
> +	caps->channel_coding = false;
> +}
> +
> +static void dw_dp_link_reset(struct dw_dp_link *link)
> +{
> +	link->vsc_sdp_supported = 0;
> +	link->sink_count = 0;
> +	link->revision = 0;
> +	link->rate = 0;
> +	link->lanes = 0;
> +
> +	dw_dp_link_caps_reset(&link->caps);
> +	memset(link->dpcd, 0, sizeof(link->dpcd));
> +}
> +
> +static int dw_dp_link_power_up(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	int ret;
> +	u8 value;
> +
> +	if (link->revision < DP_DPCD_REV_11)
> +		return 0;
> +
> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> +	if (ret < 0)
> +		return ret;
> +
> +	value &= ~DP_SET_POWER_MASK;
> +	value |= DP_SET_POWER_D0;
> +
> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(1000, 2000);
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_power_down(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	int ret;
> +	u8 value;
> +
> +	if (link->revision < DP_DPCD_REV_11)
> +		return 0;
> +
> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> +	if (ret < 0)
> +		return ret;
> +
> +	value &= ~DP_SET_POWER_MASK;
> +	value |= DP_SET_POWER_D3;
> +
> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> +	if (ret < 0)
> +		return ret;
> +

Would you please mind pulling these two functions to DRM DP helpers?
There are enough users to make this into a common code.

> +	return 0;
> +}
> +
> +static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				 const struct drm_dp_desc *desc)
> +{
> +	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
> +	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
> +	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);


isn't it drm_dp_read_sink_count_cap() ?

> +}
> +
> +static int dw_dp_link_parse(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	u8 dpcd;
> +	int ret;
> +
> +	dw_dp_link_reset(link);
> +
> +	ret = drm_dp_read_dpcd_caps(&dp->aux, link->dpcd);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_dp_read_desc(&dp->aux, &link->desc, drm_dp_is_branch(link->dpcd));
> +
> +	if (dw_dp_has_sink_count(link->dpcd, &link->desc)) {
> +		ret = drm_dp_read_sink_count(&dp->aux);
> +		if (ret < 0)
> +			return ret;
> +
> +		link->sink_count = ret;
> +
> +		/* Dongle connected, but no display */
> +		if (!link->sink_count)
> +			return -ENODEV;
> +	}
> +
> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dpcd);
> +	if (ret < 0)
> +		return ret;
> +
> +	link->vsc_sdp_supported = !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
> +
> +	link->revision = link->dpcd[DP_DPCD_REV];
> +	link->rate = min_t(u32, min(dp->plat_data->max_link_rate,
> +				    dp->phy->attrs.max_link_rate * 100),
> +			   drm_dp_max_link_rate(link->dpcd));
> +	link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
> +			    drm_dp_max_lane_count(link->dpcd));
> +
> +	link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
> +	link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
> +	link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
> +	link->caps.fast_training = drm_dp_fast_training_cap(link->dpcd);
> +	link->caps.channel_coding = drm_dp_channel_coding_supported(link->dpcd);
> +	link->caps.ssc = !!(link->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
> +
> +	return 0;
> +}
> +
> +static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes,
> +				    struct dw_dp_link_train_set *train_set)
> +{
> +	union phy_configure_opts phy_cfg;
> +	unsigned int *vs, *pe;
> +	u8 buf[4];
> +	int i, ret;
> +
> +	vs = train_set->voltage_swing;
> +	pe = train_set->pre_emphasis;
> +
> +	for (i = 0; i < lanes; i++) {
> +		phy_cfg.dp.voltage[i] = vs[i];
> +		phy_cfg.dp.pre[i] = pe[i];
> +	}
> +
> +	phy_cfg.dp.lanes = lanes;
> +	phy_cfg.dp.link_rate = rate / 100;
> +	phy_cfg.dp.set_lanes = false;
> +	phy_cfg.dp.set_rate = false;

You don't need to set lanes / link_rate if set_lanes and set_rate is
false.

> +	phy_cfg.dp.set_voltages = true;
> +
> +	ret = phy_configure(dp->phy, &phy_cfg);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < lanes; i++) {
> +		buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
> +			 (pe[i] << DP_TRAIN_PRE_EMPHASIS_SHIFT);
> +		if (train_set->voltage_max_reached[i])
> +			buf[i] |= DP_TRAIN_MAX_SWING_REACHED;
> +		if (train_set->pre_max_reached[i])
> +			buf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
> +	}
> +
> +	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, lanes);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_train_update_vs_emph(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	struct dw_dp_link_train_set *request = &link->train.request;
> +
> +	return dw_dp_phy_update_vs_emph(dp, dp->link.rate, dp->link.lanes, request);

Inline it mayeb?

> +}
> +
> +static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
> +			       unsigned int lanes, bool ssc)
> +{
> +	union phy_configure_opts phy_cfg;
> +	int ret;
> +
> +	/* Move PHY to P3 */
> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
> +			   FIELD_PREP(PHY_POWERDOWN, 0x3));
> +
> +	phy_cfg.dp.lanes = lanes;
> +	phy_cfg.dp.link_rate = rate / 100;
> +	phy_cfg.dp.ssc = ssc;
> +	phy_cfg.dp.set_lanes = true;
> +	phy_cfg.dp.set_rate = true;
> +	phy_cfg.dp.set_voltages = false;
> +	ret = phy_configure(dp->phy, &phy_cfg);
> +	if (ret)
> +		return ret;
> +
> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_LANES,
> +			   FIELD_PREP(PHY_LANES, lanes / 2));
> +
> +	/* Move PHY to P0 */
> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
> +			   FIELD_PREP(PHY_POWERDOWN, 0x0));
> +
> +	dw_dp_phy_xmit_enable(dp, lanes);
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_configure(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	u8 buf[2];
> +	int ret;
> +
> +	ret = dw_dp_phy_configure(dp, link->rate, link->lanes, link->caps.ssc);
> +	if (ret)
> +		return ret;
> +
> +	buf[0] = drm_dp_link_rate_to_bw_code(link->rate);
> +	buf[1] = link->lanes;
> +
> +	if (link->caps.enhanced_framing) {
> +		buf[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 1));
> +	} else {
> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 0));
> +	}
> +
> +	ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, sizeof(buf));
> +	if (ret < 0)
> +		return ret;
> +
> +	buf[0] = link->caps.ssc ? DP_SPREAD_AMP_0_5 : 0;
> +	buf[1] = link->caps.channel_coding ? DP_SET_ANSI_8B10B : 0;
> +
> +	ret = drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf));
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static void dw_dp_link_train_init(struct dw_dp_link_train *train)
> +{
> +	struct dw_dp_link_train_set *request = &train->request;
> +	struct dw_dp_link_train_set *adjust = &train->adjust;
> +	unsigned int i;
> +
> +	for (i = 0; i < 4; i++) {
> +		request->voltage_swing[i] = 0;
> +		adjust->voltage_swing[i] = 0;
> +
> +		request->pre_emphasis[i] = 0;
> +		adjust->pre_emphasis[i] = 0;
> +
> +		request->voltage_max_reached[i] = false;
> +		adjust->voltage_max_reached[i] = false;
> +
> +		request->pre_max_reached[i] = false;
> +		adjust->pre_max_reached[i] = false;
> +	}
> +
> +	train->clock_recovered = false;
> +	train->channel_equalized = false;
> +}
> +
> +static bool dw_dp_link_train_valid(const struct dw_dp_link_train *train)
> +{
> +	return train->clock_recovered && train->channel_equalized;
> +}
> +
> +static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
> +{
> +	u8 buf = 0;
> +	int ret;
> +
> +	if (pattern && pattern != DP_TRAINING_PATTERN_4) {
> +		buf |= DP_LINK_SCRAMBLING_DISABLE;
> +
> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
> +				   FIELD_PREP(SCRAMBLE_DIS, 1));
> +	} else {
> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
> +				   FIELD_PREP(SCRAMBLE_DIS, 0));
> +	}
> +
> +	switch (pattern) {
> +	case DP_TRAINING_PATTERN_DISABLE:
> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_NONE);
> +		break;
> +	case DP_TRAINING_PATTERN_1:
> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_1);
> +		break;
> +	case DP_TRAINING_PATTERN_2:
> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_2);
> +		break;
> +	case DP_TRAINING_PATTERN_3:
> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_3);
> +		break;
> +	case DP_TRAINING_PATTERN_4:
> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_4);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
> +				 buf | pattern);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static u8 dw_dp_voltage_max(u8 preemph)
> +{
> +	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
> +	case DP_TRAIN_PRE_EMPH_LEVEL_0:
> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
> +	case DP_TRAIN_PRE_EMPH_LEVEL_1:
> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
> +	case DP_TRAIN_PRE_EMPH_LEVEL_2:
> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
> +	case DP_TRAIN_PRE_EMPH_LEVEL_3:
> +	default:
> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
> +	}
> +}
> +
> +static void dw_dp_link_get_adjustments(struct dw_dp_link *link,
> +				       u8 status[DP_LINK_STATUS_SIZE])
> +{
> +	struct dw_dp_link_train_set *adjust = &link->train.adjust;
> +	u8 v = 0;
> +	u8 p = 0;
> +	unsigned int i;
> +
> +	for (i = 0; i < link->lanes; i++) {
> +		v = drm_dp_get_adjust_request_voltage(status, i);
> +		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
> +		if (p >=  DP_TRAIN_PRE_EMPH_LEVEL_3) {
> +			adjust->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
> +						  DP_TRAIN_PRE_EMPHASIS_SHIFT;
> +			adjust->pre_max_reached[i] = true;
> +		} else {
> +			adjust->pre_emphasis[i] = p >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
> +			adjust->pre_max_reached[i] = false;
> +		}
> +		v = min(v, dw_dp_voltage_max(p));
> +		if (v >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) {
> +			adjust->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
> +						   DP_TRAIN_VOLTAGE_SWING_SHIFT;
> +			adjust->voltage_max_reached[i] = true;
> +		} else {
> +			adjust->voltage_swing[i] = v >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
> +			adjust->voltage_max_reached[i] = false;
> +		}
> +	}
> +}
> +
> +static void dw_dp_link_train_adjust(struct dw_dp_link_train *train)
> +{
> +	struct dw_dp_link_train_set *request = &train->request;
> +	struct dw_dp_link_train_set *adjust = &train->adjust;
> +	unsigned int i;
> +
> +	for (i = 0; i < 4; i++) {

Shouldn't it be a loop up to link->lanes?

> +		if (request->voltage_swing[i] != adjust->voltage_swing[i])
> +			request->voltage_swing[i] = adjust->voltage_swing[i];
> +		if (request->voltage_max_reached[i] != adjust->voltage_max_reached[i])
> +			request->voltage_max_reached[i] = adjust->voltage_max_reached[i];
> +	}
> +
> +	for (i = 0; i < 4; i++) {
> +		if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
> +			request->pre_emphasis[i] = adjust->pre_emphasis[i];
> +		if (request->pre_max_reached[i] != adjust->pre_max_reached[i])
> +			request->pre_max_reached[i] = adjust->pre_max_reached[i];

Why do you need separate request and adjustment structs?

> +	}
> +}
> +
> +static int dw_dp_link_clock_recovery(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	u8 status[DP_LINK_STATUS_SIZE];
> +	unsigned int tries = 0;
> +	int ret;
> +
> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
> +	if (ret)
> +		return ret;
> +
> +	for (;;) {
> +		ret = dw_dp_link_train_update_vs_emph(dp);
> +		if (ret)
> +			return ret;
> +
> +		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
> +
> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> +		if (ret < 0) {
> +			dev_err(dp->dev, "failed to read link status: %d\n", ret);
> +			return ret;
> +		}
> +
> +		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
> +			link->train.clock_recovered = true;
> +			break;
> +		}
> +
> +		dw_dp_link_get_adjustments(link, status);
> +
> +		if (link->train.request.voltage_swing[0] ==
> +		    link->train.adjust.voltage_swing[0])

Should this take all lanes to account? I think it might be posssible to
drop the adjust / request split and adjust tries in
dw_dp_link_get_adjustments() instead.

> +			tries++;
> +		else
> +			tries = 0;
> +
> +		if (tries == 5)
> +			break;
> +
> +		dw_dp_link_train_adjust(&link->train);
> +	}
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_channel_equalization(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	u8 status[DP_LINK_STATUS_SIZE], pattern;
> +	unsigned int tries;
> +	int ret;
> +
> +	if (link->caps.tps4_supported)
> +		pattern = DP_TRAINING_PATTERN_4;
> +	else if (link->caps.tps3_supported)
> +		pattern = DP_TRAINING_PATTERN_3;
> +	else
> +		pattern = DP_TRAINING_PATTERN_2;
> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
> +	if (ret)
> +		return ret;
> +
> +	for (tries = 1; tries < 5; tries++) {
> +		ret = dw_dp_link_train_update_vs_emph(dp);
> +		if (ret)
> +			return ret;
> +
> +		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
> +
> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> +		if (ret < 0)
> +			return ret;
> +
> +		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
> +			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
> +			link->train.clock_recovered = false;
> +			break;
> +		}
> +
> +		if (drm_dp_channel_eq_ok(status, link->lanes)) {
> +			link->train.channel_equalized = true;
> +			break;
> +		}
> +
> +		dw_dp_link_get_adjustments(link, status);
> +		dw_dp_link_train_adjust(&link->train);
> +	}
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_downgrade(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	struct dw_dp_video *video = &dp->video;
> +
> +	switch (link->rate) {
> +	case 162000:
> +		return -EINVAL;
> +	case 270000:
> +		link->rate = 162000;
> +		break;
> +	case 540000:
> +		link->rate = 270000;
> +		break;
> +	case 810000:
> +		link->rate = 540000;
> +		break;
> +	}
> +
> +	if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
> +				link->rate))
> +		return -E2BIG;
> +
> +	return 0;
> +}
> +
> +static int dw_dp_link_train_full(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	int ret;
> +
> +retry:
> +	dw_dp_link_train_init(&link->train);
> +
> +	dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
> +
> +	ret = dw_dp_link_configure(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = dw_dp_link_clock_recovery(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "clock recovery failed: %d\n", ret);
> +		goto out;
> +	}
> +
> +	if (!link->train.clock_recovered) {
> +		dev_err(dp->dev, "clock recovery failed, downgrading link\n");
> +
> +		ret = dw_dp_link_downgrade(dp);
> +		if (ret < 0)
> +			goto out;
> +		else
> +			goto retry;
> +	}
> +
> +	dev_dbg(dp->dev, "clock recovery succeeded\n");
> +
> +	ret = dw_dp_link_channel_equalization(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "channel equalization failed: %d\n", ret);
> +		goto out;
> +	}
> +
> +	if (!link->train.channel_equalized) {
> +		dev_err(dp->dev, "channel equalization failed, downgrading link\n");
> +
> +		ret = dw_dp_link_downgrade(dp);
> +		if (ret < 0)
> +			goto out;
> +		else
> +			goto retry;
> +	}
> +
> +	dev_dbg(dp->dev, "channel equalization succeeded\n");
> +
> +out:
> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
> +	return ret;
> +}
> +
> +static int dw_dp_link_train_fast(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	int ret;
> +	u8 status[DP_LINK_STATUS_SIZE];
> +	u8 pattern;
> +
> +	dw_dp_link_train_init(&link->train);
> +
> +	dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
> +
> +	ret = dw_dp_link_configure(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
> +	if (ret)
> +		goto out;
> +
> +	usleep_range(500, 1000);
> +
> +	if (link->caps.tps4_supported)
> +		pattern = DP_TRAINING_PATTERN_4;
> +	else if (link->caps.tps3_supported)
> +		pattern = DP_TRAINING_PATTERN_3;
> +	else
> +		pattern = DP_TRAINING_PATTERN_2;
> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
> +	if (ret)
> +		goto out;
> +
> +	usleep_range(500, 1000);
> +
> +	ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "failed to read link status: %d\n", ret);
> +		goto out;
> +	}
> +
> +	if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
> +		dev_err(dp->dev, "clock recovery failed\n");
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	if (!drm_dp_channel_eq_ok(status, link->lanes)) {
> +		dev_err(dp->dev, "channel equalization failed\n");
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +out:
> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
> +	return ret;
> +}
> +
> +static int dw_dp_link_train(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	int ret;
> +
> +	if (link->caps.fast_training) {
> +		if (dw_dp_link_train_valid(&link->train)) {
> +			ret = dw_dp_link_train_fast(dp);
> +			if (ret < 0)
> +				dev_err(dp->dev, "fast link training failed: %d\n", ret);
> +			else
> +				return 0;
> +		}
> +	}
> +
> +	ret = dw_dp_link_train_full(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "full link training failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dw_dp_send_sdp(struct dw_dp *dp, struct dw_dp_sdp *sdp)
> +{
> +	const u8 *payload = sdp->db;
> +	u32 reg;
> +	int i, nr;
> +
> +	nr = find_first_zero_bit(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
> +	if (nr < SDP_REG_BANK_SIZE)
> +		set_bit(nr, dp->sdp_reg_bank);
> +	else
> +		return -EBUSY;
> +
> +	reg = DW_DP_SDP_REGISTER_BANK + nr * 9 * 4;
> +
> +	/* SDP header */
> +	regmap_write(dp->regmap, reg, get_unaligned_le32(&sdp->header));
> +
> +	/* SDP data payload */
> +	for (i = 1; i < 9; i++, payload += 4)
> +		regmap_write(dp->regmap, reg + i * 4,
> +			     FIELD_PREP(SDP_REGS, get_unaligned_le32(payload)));
> +
> +	if (sdp->flags & DW_DP_SDP_VERTICAL_INTERVAL)
> +		regmap_update_bits(dp->regmap, DW_DP_SDP_VERTICAL_CTRL,
> +				   EN_VERTICAL_SDP << nr,
> +				   EN_VERTICAL_SDP << nr);
> +
> +	if (sdp->flags & DW_DP_SDP_HORIZONTAL_INTERVAL)
> +		regmap_update_bits(dp->regmap, DW_DP_SDP_HORIZONTAL_CTRL,
> +				   EN_HORIZONTAL_SDP << nr,
> +				   EN_HORIZONTAL_SDP << nr);
> +
> +	return 0;
> +}
> +
> +static void dw_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> +			       struct dw_dp_sdp *sdp)

Use drm_dp_vsc_sdp_pack() instead.

> +{
> +	sdp->header.HB0 = 0;
> +	sdp->header.HB1 = DP_SDP_VSC;
> +	sdp->header.HB2 = vsc->revision;
> +	sdp->header.HB3 = vsc->length;
> +
> +	sdp->db[16] = (vsc->pixelformat & 0xf) << 4;
> +	sdp->db[16] |= vsc->colorimetry & 0xf;
> +
> +	switch (vsc->bpc) {
> +	case 8:
> +		sdp->db[17] = 0x1;
> +		break;
> +	case 10:
> +		sdp->db[17] = 0x2;
> +		break;
> +	case 12:
> +		sdp->db[17] = 0x3;
> +		break;
> +	case 16:
> +		sdp->db[17] = 0x4;
> +		break;
> +	case 6:
> +	default:
> +		break;
> +	}
> +
> +	if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
> +		sdp->db[17] |= 0x80;
> +
> +	sdp->db[18] = vsc->content_type & 0x7;
> +
> +	sdp->flags |= DW_DP_SDP_VERTICAL_INTERVAL;
> +}
> +
> +static int dw_dp_send_vsc_sdp(struct dw_dp *dp)
> +{
> +	struct dw_dp_video *video = &dp->video;
> +	struct drm_dp_vsc_sdp vsc = {};
> +	struct dw_dp_sdp sdp = {};
> +
> +	vsc.revision = 0x5;
> +	vsc.length = 0x13;
> +
> +	switch (video->color_format) {
> +	case DRM_COLOR_FORMAT_YCBCR444:
> +		vsc.pixelformat = DP_PIXELFORMAT_YUV444;
> +		break;
> +	case DRM_COLOR_FORMAT_YCBCR420:
> +		vsc.pixelformat = DP_PIXELFORMAT_YUV420;
> +		break;
> +	case DRM_COLOR_FORMAT_YCBCR422:
> +		vsc.pixelformat = DP_PIXELFORMAT_YUV422;
> +		break;
> +	case DRM_COLOR_FORMAT_RGB444:
> +	default:
> +		vsc.pixelformat = DP_PIXELFORMAT_RGB;
> +		break;
> +	}
> +
> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
> +	} else {
> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> +	}
> +
> +	vsc.bpc = video->bpc;
> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
> +
> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
> +
> +	return dw_dp_send_sdp(dp, &sdp);
> +}
> +
> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
> +{
> +	switch (pixel_mode) {
> +	case DW_DP_MP_SINGLE_PIXEL:
> +	case DW_DP_MP_DUAL_PIXEL:
> +	case DW_DP_MP_QUAD_PIXEL:
> +		break;
> +	default:
> +		return -EINVAL;

Is it possible?

> +	}
> +
> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
> +			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
> +
> +	return 0;
> +}
> +
> +static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	struct dw_dp_video *video = &dp->video;
> +
> +	if (!link->vsc_sdp_supported)
> +		return false;
> +
> +	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
> +		return true;
> +
> +	return false;
> +}
> +
> +static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
> +			       u16 vstart, u16 hstart)
> +{
> +	u16 misc = 0;
> +
> +	if (dw_dp_video_need_vsc_sdp(dp))
> +		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
> +
> +	switch (color_format) {
> +	case DRM_COLOR_FORMAT_RGB444:
> +		misc |= DP_MSA_MISC_COLOR_RGB;
> +		break;
> +	case DRM_COLOR_FORMAT_YCBCR444:
> +		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
> +		break;
> +	case DRM_COLOR_FORMAT_YCBCR422:
> +		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
> +		break;
> +	case DRM_COLOR_FORMAT_YCBCR420:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (bpc) {
> +	case 6:
> +		misc |= DP_MSA_MISC_6_BPC;
> +		break;
> +	case 8:
> +		misc |= DP_MSA_MISC_8_BPC;
> +		break;
> +	case 10:
> +		misc |= DP_MSA_MISC_10_BPC;
> +		break;
> +	case 12:
> +		misc |= DP_MSA_MISC_12_BPC;
> +		break;
> +	case 16:
> +		misc |= DP_MSA_MISC_16_BPC;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
> +		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
> +
> +	return 0;
> +}
> +
> +static void dw_dp_video_disable(struct dw_dp *dp)
> +{
> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
> +}
> +
> +static int dw_dp_video_enable(struct dw_dp *dp)
> +{
> +	struct dw_dp_video *video = &dp->video;
> +	struct dw_dp_link *link = &dp->link;
> +	struct drm_display_mode *mode = &video->mode;
> +	u8 color_format = video->color_format;
> +	u8 bpc = video->bpc;
> +	u8 pixel_mode = video->pixel_mode;
> +	u8 bpp = video->bpp, init_threshold, vic;
> +	u32 hactive, hblank, h_sync_width, h_front_porch;
> +	u32 vactive, vblank, v_sync_width, v_front_porch;
> +	u32 vstart = mode->vtotal - mode->vsync_start;
> +	u32 hstart = mode->htotal - mode->hsync_start;
> +	u32 peak_stream_bandwidth, link_bandwidth;
> +	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
> +	u32 ts, hblank_interval;
> +	u32 value;
> +	int ret;
> +
> +	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
> +	if (ret)
> +		return ret;
> +
> +	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
> +	if (ret)
> +		return ret;
> +
> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
> +			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
> +
> +	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
> +	value = 0;
> +	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
> +		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
> +	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
> +		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
> +	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
> +
> +	/* Configure DW_DP_VIDEO_CONFIG1 register */
> +	hactive = mode->hdisplay;
> +	hblank = mode->htotal - mode->hdisplay;
> +	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
> +	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> +		value |= FIELD_PREP(I_P, 1);
> +	vic = drm_match_cea_mode(mode);
> +	if (vic == 5 || vic == 6 || vic == 7 ||
> +	    vic == 10 || vic == 11 || vic == 20 ||
> +	    vic == 21 || vic == 22 || vic == 39 ||
> +	    vic == 25 || vic == 26 || vic == 40 ||
> +	    vic == 44 || vic == 45 || vic == 46 ||
> +	    vic == 50 || vic == 51 || vic == 54 ||
> +	    vic == 55 || vic == 58 || vic  == 59)
> +		value |= R_V_BLANK_IN_OSC;
> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
> +
> +	/* Configure DW_DP_VIDEO_CONFIG2 register */
> +	vblank = mode->vtotal - mode->vdisplay;
> +	vactive = mode->vdisplay;
> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
> +		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
> +
> +	/* Configure DW_DP_VIDEO_CONFIG3 register */
> +	h_sync_width = mode->hsync_end - mode->hsync_start;
> +	h_front_porch = mode->hsync_start - mode->hdisplay;
> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
> +		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
> +		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
> +
> +	/* Configure DW_DP_VIDEO_CONFIG4 register */
> +	v_sync_width = mode->vsync_end - mode->vsync_start;
> +	v_front_porch = mode->vsync_start - mode->vdisplay;
> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
> +		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
> +		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
> +
> +	/* Configure DW_DP_VIDEO_CONFIG5 register */
> +	peak_stream_bandwidth = mode->clock * bpp / 8;
> +	link_bandwidth = (link->rate / 1000) * link->lanes;
> +	ts = peak_stream_bandwidth * 64 / link_bandwidth;
> +	average_bytes_per_tu = ts / 1000;
> +	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
> +	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
> +		if (average_bytes_per_tu < 6)
> +			init_threshold = 32;
> +		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
> +			init_threshold = 12;
> +		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
> +			init_threshold = 3;
> +		else
> +			init_threshold = 16;
> +	} else {
> +		u32 t1 = 0, t2 = 0, t3 = 0;
> +
> +		switch (bpc) {
> +		case 6:
> +			t1 = (4 * 1000 / 9) * link->lanes;
> +			break;
> +		case 8:
> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> +				t1 = (1000 / 2) * link->lanes;
> +			} else {
> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> +					t1 = (1000 / 3) * link->lanes;
> +				else
> +					t1 = (3000 / 16) * link->lanes;
> +			}
> +			break;
> +		case 10:
> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
> +				t1 = (2000 / 5) * link->lanes;
> +			else
> +				t1 = (4000 / 15) * link->lanes;
> +			break;
> +		case 12:
> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> +					t1 = (1000 / 6) * link->lanes;
> +				else
> +					t1 = (1000 / 3) * link->lanes;
> +			} else {
> +				t1 = (2000 / 9) * link->lanes;
> +			}
> +			break;
> +		case 16:
> +			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
> +			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
> +				t1 = (1000 / 6) * link->lanes;
> +			else
> +				t1 = (1000 / 4) * link->lanes;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +
> +		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
> +			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
> +		else
> +			t2 = (link->rate / 4) * 1000 / mode->clock;
> +
> +		if (average_bytes_per_tu_frac)
> +			t3 = average_bytes_per_tu + 1;
> +		else
> +			t3 = average_bytes_per_tu;
> +		init_threshold = t1 * t2 * t3 / (1000 * 1000);
> +		if (init_threshold <= 16 || average_bytes_per_tu < 10)
> +			init_threshold = 40;
> +	}
> +
> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
> +		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
> +		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
> +
> +	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
> +	hblank_interval = hblank * (link->rate / 4) / mode->clock;
> +	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
> +		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
> +		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
> +
> +	/* Video stream enable */
> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
> +
> +	if (dw_dp_video_need_vsc_sdp(dp))
> +		dw_dp_send_vsc_sdp(dp);
> +
> +	return 0;
> +}
> +
> +static void dw_dp_hpd_init(struct dw_dp *dp)
> +{
> +	/* Enable all HPD interrupts */
> +	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
> +			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
> +			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
> +			   FIELD_PREP(HPD_PLUG_EN, 1) |
> +			   FIELD_PREP(HPD_IRQ_EN, 1));
> +
> +	/* Enable all top-level interrupts */
> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> +			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
> +}
> +
> +static void dw_dp_aux_init(struct dw_dp *dp)
> +{
> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> +			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
> +}
> +
> +static void dw_dp_init_hw(struct dw_dp *dp)
> +{
> +	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
> +			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
> +
> +	dw_dp_hpd_init(dp);
> +	dw_dp_aux_init(dp);
> +}
> +
> +static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
> +{
> +	size_t i, j;
> +
> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> +		size_t num = min_t(size_t, size - i * 4, 4);
> +		u32 value = 0;
> +
> +		for (j = 0; j < num; j++)
> +			value |= buffer[i * 4 + j] << (j * 8);
> +
> +		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
> +	}
> +
> +	return size;
> +}
> +
> +static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
> +{
> +	size_t i, j;
> +
> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> +		size_t num = min_t(size_t, size - i * 4, 4);
> +		u32 value;
> +
> +		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
> +
> +		for (j = 0; j < num; j++)
> +			buffer[i * 4 + j] = value >> (j * 8);
> +	}
> +
> +	return size;
> +}
> +
> +static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
> +				  struct drm_dp_aux_msg *msg)
> +{
> +	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
> +	unsigned long timeout = msecs_to_jiffies(10);
> +	u32 status, value;
> +	ssize_t ret = 0;
> +
> +	if (WARN_ON(msg->size > 16))
> +		return -E2BIG;
> +
> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
> +	case DP_AUX_NATIVE_WRITE:
> +	case DP_AUX_I2C_WRITE:
> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
> +		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
> +		if (ret < 0)
> +			return ret;
> +		break;
> +	case DP_AUX_NATIVE_READ:
> +	case DP_AUX_I2C_READ:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (msg->size > 0)
> +		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
> +	else
> +		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
> +	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
> +	value |= FIELD_PREP(AUX_ADDR, msg->address);
> +	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
> +
> +	status = wait_for_completion_timeout(&dp->complete, timeout);
> +	if (!status) {
> +		dev_err(dp->dev, "timeout waiting for AUX reply\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
> +	if (value & AUX_TIMEOUT)
> +		return -ETIMEDOUT;
> +
> +	msg->reply = FIELD_GET(AUX_STATUS, value);
> +
> +	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
> +		if (msg->request & DP_AUX_I2C_READ) {
> +			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
> +
> +			if (count != msg->size)
> +				return -EBUSY;
> +
> +			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
> +			if (ret < 0)
> +				return ret;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/*
> + * Limits for the video timing output by DP:
> + * 1. the hfp should be 2 pixels aligned;
> + * 2. the minimum hsync should be 9 pixel;
> + * 3. the minimum hbp should be 16 pixel;
> + */
> +static bool dw_dp_bridge_mode_fixup(struct drm_bridge *bridge,
> +				    const struct drm_display_mode *mode,
> +				    struct drm_display_mode *adjusted_mode)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	int min_hbp = 16;
> +	int min_hsync = 9;
> +
> +	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
> +		adjusted_mode->hsync_start += 1;
> +		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
> +	}
> +	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
> +		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
> +		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
> +	}
> +	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
> +		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
> +		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
> +	}
> +
> +	return true;
> +}
> +
> +static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
> +						    const struct drm_display_info *info,
> +						    const struct drm_display_mode *mode)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	struct dw_dp_link *link = &dp->link;
> +	u32 min_bpp;
> +
> +	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
> +	    link->vsc_sdp_supported &&
> +	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
> +		min_bpp = 12;
> +	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
> +		min_bpp = 16;
> +	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
> +		min_bpp = 18;
> +	else
> +		min_bpp = 24;
> +
> +	if (!link->vsc_sdp_supported &&
> +	    drm_mode_is_420_only(info, mode))
> +		return MODE_NO_420;
> +
> +	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
> +		return MODE_CLOCK_HIGH;
> +
> +	return MODE_OK;
> +}
> +
> +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> +					   struct drm_bridge_state *old_bridge_state)
> +{
> +	struct drm_atomic_state *state = old_bridge_state->base.state;
> +	struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	struct dw_dp_video *video = &dp->video;
> +	struct drm_display_mode *m = &video->mode;
> +	struct drm_bridge_state *bridge_state;
> +	const struct dw_dp_output_format *fmt;
> +
> +	drm_mode_copy(m, &crtc_state->adjusted_mode);
> +
> +	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> +	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);

Should it be a part of the atomic_check() instead?

> +
> +	video->video_mapping = fmt->video_mapping;
> +	video->color_format = fmt->color_format;
> +	video->bpc = fmt->bpc;
> +	video->bpp = fmt->bpp;
> +}
> +
> +static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +	u8 link_status[DP_LINK_STATUS_SIZE];
> +
> +	if (!dw_dp_link_train_valid(&link->train))
> +		return false;
> +
> +	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
> +		return false;
> +
> +	/* Retrain if Channel EQ or CR not ok */
> +	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
> +}
> +
> +static void dw_dp_link_disable(struct dw_dp *dp)
> +{
> +	struct dw_dp_link *link = &dp->link;
> +
> +	if (dw_dp_hpd_detect(dp))
> +		dw_dp_link_power_down(dp);
> +
> +	dw_dp_phy_xmit_enable(dp, 0);
> +
> +	phy_power_off(dp->phy);
> +
> +	link->train.clock_recovered = false;
> +	link->train.channel_equalized = false;
> +}
> +
> +static int dw_dp_link_enable(struct dw_dp *dp)
> +{
> +	int ret;
> +
> +	ret = phy_power_on(dp->phy);
> +	if (ret)
> +		return ret;
> +
> +	ret = dw_dp_link_power_up(dp);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = dw_dp_link_train(dp);
> +
> +	return ret;
> +}
> +
> +static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
> +				       struct drm_bridge_state *old_state)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	struct drm_atomic_state *state = old_state->base.state;
> +	struct drm_connector *connector;
> +	struct drm_connector_state *conn_state;
> +	int ret;
> +
> +	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
> +	if (!connector) {
> +		dev_err(dp->dev, "failed to get connector\n");
> +		return;
> +	}
> +
> +	conn_state = drm_atomic_get_new_connector_state(state, connector);
> +	if (!conn_state) {
> +		dev_err(dp->dev, "failed to get connector state\n");
> +		return;
> +	}
> +
> +	set_bit(0, dp->sdp_reg_bank);
> +
> +	ret = dw_dp_link_enable(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "failed to enable link: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = dw_dp_video_enable(dp);
> +	if (ret < 0) {
> +		dev_err(dp->dev, "failed to enable video: %d\n", ret);
> +		return;
> +	}
> +}
> +
> +static void dw_dp_reset(struct dw_dp *dp)
> +{
> +	int val;
> +
> +	disable_irq(dp->irq);
> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> +			   FIELD_PREP(CONTROLLER_RESET, 1));
> +	udelay(10);
> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> +			   FIELD_PREP(CONTROLLER_RESET, 0));
> +
> +	dw_dp_init_hw(dp);
> +	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
> +				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
> +	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> +	enable_irq(dp->irq);
> +}
> +
> +static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
> +					struct drm_bridge_state *old_bridge_state)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +
> +	dw_dp_video_disable(dp);
> +	dw_dp_link_disable(dp);
> +	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
> +	dw_dp_reset(dp);
> +}
> +
> +static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
> +{
> +	int ret;
> +
> +	ret = phy_power_on(dp->phy);
> +	if (ret < 0)
> +		return false;
> +	ret = dw_dp_link_parse(dp);
> +	phy_power_off(dp->phy);
> +
> +	return !ret;
> +}
> +
> +static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +
> +	if (!dw_dp_hpd_detect(dp))
> +		return connector_status_disconnected;
> +
> +	if (!dw_dp_hpd_detect_link(dp))
> +		return connector_status_disconnected;
> +
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
> +						     struct drm_connector *connector)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	const struct drm_edid *edid;
> +	int ret;
> +
> +	ret = phy_power_on(dp->phy);
> +	if (ret)
> +		return NULL;
> +
> +	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
> +
> +	phy_power_off(dp->phy);
> +
> +	return edid;
> +}
> +
> +static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> +						    struct drm_bridge_state *bridge_state,
> +						    struct drm_crtc_state *crtc_state,
> +						    struct drm_connector_state *conn_state,
> +						    unsigned int *num_output_fmts)
> +{
> +	struct dw_dp *dp = bridge_to_dp(bridge);
> +	struct dw_dp_link *link = &dp->link;
> +	struct drm_display_info *di = &conn_state->connector->display_info;
> +	struct drm_display_mode mode = crtc_state->mode;
> +	const struct dw_dp_output_format *fmt;
> +	u32 i, j = 0;
> +	u32 *output_fmts;
> +
> +	*num_output_fmts = 0;
> +
> +	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
> +	if (!output_fmts)
> +		return NULL;
> +
> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
> +		fmt = &dw_dp_output_formats[i];
> +
> +		if (fmt->bpc > conn_state->max_bpc)
> +			continue;
> +
> +		if (!(fmt->color_format & di->color_formats))
> +			continue;
> +
> +		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
> +		    !link->vsc_sdp_supported)
> +			continue;
> +
> +		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
> +		    drm_mode_is_420_only(di, &mode))
> +			continue;
> +
> +		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
> +			continue;
> +
> +		output_fmts[j++] = fmt->bus_format;
> +	}
> +
> +	*num_output_fmts = j;
> +
> +	return output_fmts;
> +}
> +
> +static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
> +	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> +	.atomic_reset = drm_atomic_helper_bridge_reset,
> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
> +	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
> +	.mode_fixup = dw_dp_bridge_mode_fixup,
> +	.mode_valid = dw_dp_bridge_mode_valid,
> +	.atomic_pre_enable = dw_dp_bridge_atomic_pre_enable,
> +	.atomic_enable = dw_dp_bridge_atomic_enable,
> +	.atomic_disable = dw_dp_bridge_atomic_disable,
> +	.detect = dw_dp_bridge_detect,
> +	.edid_read = dw_dp_bridge_edid_read,
> +};
> +
> +static int dw_dp_link_retrain(struct dw_dp *dp)
> +{
> +	struct drm_device *dev = dp->bridge.dev;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret;
> +
> +	if (!dw_dp_needs_link_retrain(dp))
> +		return 0;
> +
> +	dev_dbg(dp->dev, "Retraining link\n");
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +	for (;;) {
> +		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
> +		if (ret != -EDEADLK)
> +			break;

I think it's an error to continue in such a case. There should be a
return after the loop if ret is not 0.

> +
> +		drm_modeset_backoff(&ctx);
> +	}
> +
> +	ret = dw_dp_link_train(dp);
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret;
> +}
> +
> +static void dw_dp_hpd_work(struct work_struct *work)
> +{
> +	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
> +	bool long_hpd;
> +	int ret;
> +
> +	mutex_lock(&dp->irq_lock);
> +	long_hpd = dp->hotplug.long_hpd;
> +	mutex_unlock(&dp->irq_lock);
> +
> +	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
> +
> +	if (!long_hpd) {
> +		if (dw_dp_needs_link_retrain(dp)) {
> +			ret = dw_dp_link_retrain(dp);
> +			if (ret)
> +				dev_warn(dp->dev, "Retrain link failed\n");
> +		}
> +	} else {
> +		drm_helper_hpd_irq_event(dp->bridge.dev);
> +	}
> +}
> +
> +static void dw_dp_handle_hpd_event(struct dw_dp *dp)
> +{
> +	u32 value;
> +
> +	mutex_lock(&dp->irq_lock);
> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> +
> +	if (value & HPD_IRQ) {
> +		dev_dbg(dp->dev, "IRQ from the HPD\n");
> +		dp->hotplug.long_hpd = false;
> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
> +	}
> +
> +	if (value & HPD_HOT_PLUG) {
> +		dev_dbg(dp->dev, "Hot plug detected\n");
> +		dp->hotplug.long_hpd = true;
> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> +	}
> +
> +	if (value & HPD_HOT_UNPLUG) {
> +		dev_dbg(dp->dev, "Unplug detected\n");
> +		dp->hotplug.long_hpd = true;
> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
> +	}
> +	mutex_unlock(&dp->irq_lock);
> +
> +	schedule_work(&dp->hpd_work);
> +}
> +
> +static irqreturn_t dw_dp_irq(int irq, void *data)
> +{
> +	struct dw_dp *dp = data;
> +	u32 value;
> +
> +	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
> +	if (!value)
> +		return IRQ_NONE;
> +
> +	if (value & HPD_EVENT)
> +		dw_dp_handle_hpd_event(dp);
> +
> +	if (value & AUX_REPLY_EVENT) {
> +		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
> +		complete(&dp->complete);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct regmap_range dw_dp_readable_ranges[] = {
> +	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
> +	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
> +	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
> +	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
> +	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
> +	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
> +	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
> +	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
> +	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
> +};
> +
> +static const struct regmap_access_table dw_dp_readable_table = {
> +	.yes_ranges     = dw_dp_readable_ranges,
> +	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
> +};
> +
> +static const struct regmap_config dw_dp_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +	.fast_io = true,
> +	.max_register = DW_DP_MAX_REGISTER,
> +	.rd_table = &dw_dp_readable_table,
> +};
> +
> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> +			 const struct dw_dp_plat_data *plat_data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct dw_dp *dp;
> +	struct drm_bridge *bridge;
> +	void __iomem *res;
> +	int ret;
> +
> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
> +	if (!dp)
> +		return ERR_PTR(-ENOMEM);
> +
> +	dp->dev = dev;
> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
> +
> +	dp->plat_data = plat_data;
> +	bridge = &dp->bridge;
> +	mutex_init(&dp->irq_lock);
> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
> +	init_completion(&dp->complete);
> +
> +	res = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(res))
> +		return ERR_CAST(res);
> +
> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
> +	if (IS_ERR(dp->regmap)) {
> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
> +		return ERR_CAST(dp->regmap);
> +	}
> +
> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
> +	if (IS_ERR(dp->phy)) {
> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
> +		return ERR_CAST(dp->phy);
> +	}
> +
> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
> +	if (IS_ERR(dp->apb_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
> +		return ERR_CAST(dp->apb_clk);
> +	}
> +
> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
> +	if (IS_ERR(dp->aux_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
> +		return ERR_CAST(dp->aux_clk);
> +	}
> +
> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
> +	if (IS_ERR(dp->i2s_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
> +		return ERR_CAST(dp->i2s_clk);
> +	}
> +
> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
> +	if (IS_ERR(dp->spdif_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
> +		return ERR_CAST(dp->spdif_clk);
> +	}
> +
> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
> +	if (IS_ERR(dp->hdcp_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
> +		return ERR_CAST(dp->hdcp_clk);
> +	}
> +
> +	dp->rstc = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(dp->rstc)) {
> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
> +		return ERR_CAST(dp->rstc);
> +	}
> +
> +	dp->irq = platform_get_irq(pdev, 0);
> +	if (dp->irq < 0)
> +		return ERR_PTR(ret);
> +
> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
> +					IRQF_ONESHOT, dev_name(dev), dp);

Are you ready to handle the IRQ here, before the bridge is filled?

> +	if (ret) {
> +		dev_err_probe(dev, ret, "failed to request irq\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	bridge->of_node = dev->of_node;
> +	bridge->funcs = &dw_dp_bridge_funcs;
> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
> +	bridge->ycbcr_420_allowed = true;
> +	bridge->vendor = "Synopsys";
> +	bridge->product = "DW DP TX";

These two are unused

> +
> +	platform_set_drvdata(pdev, dp);

Unused

> +
> +	dp->aux.dev = dev;
> +	dp->aux.drm_dev = encoder->dev;
> +	dp->aux.name = dev_name(dev);
> +	dp->aux.transfer = dw_dp_aux_transfer;
> +	ret = drm_dp_aux_register(&dp->aux);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "Aux register failed\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
> +
> +	dw_dp_init_hw(dp);
> +
> +	return dp;
> +}
> +MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
> +MODULE_DESCRIPTION("DW DP Core Library");
> +MODULE_LICENSE("GPL");
> diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
> new file mode 100644
> index 000000000000..07845f609eca
> --- /dev/null
> +++ b/include/drm/bridge/dw_dp.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef __DW_DP__
> +#define __DW_DP__
> +
> +struct device;
> +struct drm_encoder;
> +struct dw_dp;
> +
> +struct dw_dp_plat_data {
> +	u32 max_link_rate;
> +};
> +
> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> +			 const struct dw_dp_plat_data *plat_data);
> +#endif /* __DW_DP__ */
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sat Mar  1 10:19:24 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat, 1 Mar 2025 20:19:24 +0200
Subject: [PATCH 3/6] drm/rockchip: Add RK3588 DPTX output support
In-Reply-To: <20250223113036.74252-4-andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-4-andyshrk@163.com>
Message-ID: <63xbqyzdlv7jssbmvoeicz4gech3di6nr3tsyvhbhxrmvthh3f@tlf73esqcwgt>

On Sun, Feb 23, 2025 at 07:30:26PM +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Add driver extension for Synopsys DesignWare DPTX IP used
> on Rockchip RK3588 SoC.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
>  drivers/gpu/drm/rockchip/Kconfig            |   7 +
>  drivers/gpu/drm/rockchip/Makefile           |   1 +
>  drivers/gpu/drm/rockchip/dw_dp-rockchip.c   | 162 ++++++++++++++++++++
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
>  5 files changed, 172 insertions(+)
>  create mode 100644 drivers/gpu/drm/rockchip/dw_dp-rockchip.c
> 
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 26c4410b2407..c8638baf9641 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
>  	select DRM_PANEL
>  	select VIDEOMODE_HELPERS
>  	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
> +	select DRM_DW_DP if ROCKCHIP_DW_DP
>  	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
>  	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
>  	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
> @@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
>  	  RK3399 based SoC, you should select this
>  	  option.
>  
> +config ROCKCHIP_DW_DP
> +	bool "Rockchip specific extensions for Synopsys DW DP"
> +	help
> +	  Choose this option for Synopsys DesignWare Cores DisplayPort
> +	  transmit controller support on Rockchip SoC.
> +
>  config ROCKCHIP_DW_HDMI
>  	bool "Rockchip specific extensions for Synopsys DW HDMI"
>  	help
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 2b867cebbc12..097f062399c7 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -14,6 +14,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI2) += dw-mipi-dsi2-rockchip.o
> +rockchipdrm-$(CONFIG_ROCKCHIP_DW_DP) += dw_dp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_RGB) += rockchip_rgb.o
> diff --git a/drivers/gpu/drm/rockchip/dw_dp-rockchip.c b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
> new file mode 100644
> index 000000000000..b41a41eb74d7
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
> @@ -0,0 +1,162 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
> + *
> + * Author: Zhang Yubing <yubing.zhang at rock-chips.com>
> + * Author: Andy Yan <andy.yan at rock-chips.com>
> + */
> +
> +#include <linux/component.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <drm/bridge/dw_dp.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_bridge_connector.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +
> +#include <uapi/linux/media-bus-format.h>
> +#include <uapi/linux/videodev2.h>

I'd say, include those two headers directly. Rockchip / Synopsys are the
only drivers including these uapi headers directly.

> +
> +#include "rockchip_drm_drv.h"
> +#include "rockchip_drm_vop.h"
> +
> +struct rockchip_dw_dp {
> +	struct dw_dp *base;
> +	struct device *dev;
> +	struct rockchip_encoder encoder;
> +};
> +
> +static inline struct rockchip_dw_dp *encoder_to_dp(struct drm_encoder *encoder)
> +{
> +	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
> +
> +	return container_of(rkencoder, struct rockchip_dw_dp, encoder);
> +}
> +
> +static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder,
> +				      struct drm_crtc_state *crtc_state,
> +				      struct drm_connector_state *conn_state)
> +{
> +	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
> +	struct drm_atomic_state *state = conn_state->state;
> +	struct drm_display_info *di = &conn_state->connector->display_info;
> +	struct drm_bridge *bridge  = drm_bridge_chain_get_first_bridge(encoder);
> +	struct drm_bridge_state *bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> +	u32 bus_format = bridge_state->input_bus_cfg.format;
> +
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
> +	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
> +		s->output_mode = ROCKCHIP_OUT_MODE_YUV420;
> +		break;
> +	case MEDIA_BUS_FMT_YUYV10_1X20:
> +	case MEDIA_BUS_FMT_YUYV8_1X16:
> +		s->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
> +		break;
> +	case MEDIA_BUS_FMT_RGB101010_1X30:
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	default:
> +		s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
> +		break;
> +	}
> +
> +	s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
> +	s->bus_format = bus_format;
> +	s->bus_flags = di->bus_flags;
> +	s->color_space = V4L2_COLORSPACE_DEFAULT;
> +
> +	return 0;
> +}
> +
> +static const struct drm_encoder_helper_funcs dw_dp_encoder_helper_funcs = {
> +	.atomic_check		= dw_dp_encoder_atomic_check,
> +};
> +
> +static int dw_dp_rockchip_bind(struct device *dev, struct device *master, void *data)
> +{
> +	struct dw_dp_plat_data plat_data;
> +	struct drm_device *drm_dev = data;
> +	struct rockchip_dw_dp *dp;
> +	struct drm_encoder *encoder;
> +	struct drm_connector *connector;
> +	int ret;
> +
> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
> +	if (!dp)
> +		return -ENOMEM;
> +
> +	dp->dev = dev;
> +	plat_data.max_link_rate = 810000;
> +	encoder = &dp->encoder.encoder;
> +	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
> +	rockchip_drm_encoder_set_crtc_endpoint_id(&dp->encoder, dev->of_node, 0, 0);
> +
> +	drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);

drmm_encoder_init() ? This will allow you to get rid of
drm_encoder_cleanup() calls.

> +	drm_encoder_helper_add(encoder, &dw_dp_encoder_helper_funcs);
> +
> +	dp->base = dw_dp_bind(dev, encoder, &plat_data);
> +	if (IS_ERR(dp->base)) {
> +		ret = PTR_ERR(dp->base);
> +		drm_encoder_cleanup(encoder);
> +		return ret;
> +	}
> +
> +	connector = drm_bridge_connector_init(drm_dev, encoder);
> +	if (IS_ERR(connector)) {
> +		ret = PTR_ERR(connector);
> +		dev_err(dev, "Failed to init bridge connector: %d\n", ret);
> +		return ret;
> +	}
> +
> +	drm_connector_attach_encoder(connector, encoder);
> +
> +	return 0;
> +}
> +
> +static void dw_dp_rockchip_unbind(struct device *dev, struct device *master, void *data)
> +{
> +	struct rockchip_dw_dp *dp = dev_get_drvdata(dev);
> +
> +	drm_encoder_cleanup(&dp->encoder.encoder);
> +}
> +
> +static const struct component_ops dw_dp_rockchip_component_ops = {
> +	.bind = dw_dp_rockchip_bind,
> +	.unbind = dw_dp_rockchip_unbind,
> +};
> +
> +static int dw_dp_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +
> +	return component_add(dev, &dw_dp_rockchip_component_ops);
> +}
> +
> +static void dw_dp_remove(struct platform_device *pdev)
> +{
> +	struct rockchip_dw_dp *dp = platform_get_drvdata(pdev);
> +
> +	component_del(dp->dev, &dw_dp_rockchip_component_ops);
> +}
> +
> +static const struct of_device_id dw_dp_of_match[] = {
> +	{ .compatible = "rockchip,rk3588-dp", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, dw_dp_of_match);
> +
> +struct platform_driver dw_dp_driver = {
> +	.probe	= dw_dp_probe,
> +	.remove = dw_dp_remove,
> +	.driver = {
> +		.name = "dw-dp",
> +		.of_match_table = dw_dp_of_match,
> +	},
> +};
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index 9cf311b5dec1..2b245491c71d 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -529,6 +529,7 @@ static int __init rockchip_drm_init(void)
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
>  				CONFIG_ROCKCHIP_ANALOGIX_DP);
>  	ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
> +	ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP);
>  	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
>  				CONFIG_ROCKCHIP_DW_HDMI);
>  	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index c183e82a42a5..2e86ad00979c 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -87,6 +87,7 @@ int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder,
>  					      struct device_node *np, int port, int reg);
>  int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
>  extern struct platform_driver cdn_dp_driver;
> +extern struct platform_driver dw_dp_driver;
>  extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
>  extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
>  extern struct platform_driver dw_mipi_dsi_rockchip_driver;
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


From heiko at sntech.de  Sat Mar  1 10:27:52 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sat, 01 Mar 2025 19:27:52 +0100
Subject: [PATCH v7 0/3] Add HDMI audio on the rk3588 SoC
In-Reply-To: <0A30138B-183E-4816-80FF-AACDCFE3B3A6@gmail.com>
References: <20250217215641.372723-1-detlev.casanova@collabora.com>
 <3337030.aeNJFYEL58@trenzalore>
 <0A30138B-183E-4816-80FF-AACDCFE3B3A6@gmail.com>
Message-ID: <23891130.6Emhk5qWAg@diego>

Am Samstag, 1. M?rz 2025, 10:11:54 MEZ schrieb Piotr Oniszczuk:
> 
> > Wiadomo?? napisana przez Detlev Casanova <detlev.casanova at collabora.com> w dniu 25 lut 2025, o godz. 15:58:
> > 
> > From what I see, the error is not present anymore on linux 6.14-rc4. I tried 
> > reverting your patch "ASoC: simple-card-utils.c: add missing dlc->of_node" 
> > (dabbd325b25edb5cdd99c94391817202dd54b651) and the error reappears.
> 
> Guys,
> 
> Just FYI:
> 
> On 6.14-rc4 without 0001-ASoC-simple-card-utils-Don-t-use-__free-device_node-.patch - i still have oops like this: https://gist.github.com/warpme/ed75c05d3b68f995d429dbd9097005ba
> They are happening not every boot - but still happening.
> 
> However applying 0001-ASoC-simple-card-utils-Don-t-use-__free-device_node-.patch (with some adaptations as it not applies cleanly on 6.140rc4) - dmesg becomes clean (10 boots; all ok)

that patch was submitted yesterday [0], so hopefully will make its
way into 6.14-rc next week or so.



[0] https://lore.kernel.org/all/87eczisyhh.wl-kuninori.morimoto.gx at renesas.com/T/#me866307a928c2d592a2ba883867f028c5c8b9b40




From lkp at intel.com  Sat Mar  1 10:49:36 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 02:49:36 +0800
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
References: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
Message-ID: <202503020214.QiJLAEK2-lkp@intel.com>

Hi Robin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Robin-Murphy/dt-bindings-dma-Add-Arm-DMA-350/20250301-012733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link:    https://lore.kernel.org/r/55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy%40arm.com
patch subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
config: hexagon-randconfig-001-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020214.QiJLAEK2-lkp at intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020214.QiJLAEK2-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020214.QiJLAEK2-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/dma/arm-dma350.c:485:13: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
     485 |         } else if (!ch_status & CH_STAT_INTR_DONE) {
         |                    ^          ~
   drivers/dma/arm-dma350.c:485:13: note: add parentheses after the '!' to evaluate the bitwise operator first
     485 |         } else if (!ch_status & CH_STAT_INTR_DONE) {
         |                    ^                             
         |                     (                            )
   drivers/dma/arm-dma350.c:485:13: note: add parentheses around left hand side expression to silence this warning
     485 |         } else if (!ch_status & CH_STAT_INTR_DONE) {
         |                    ^
         |                    (         )
   1 warning generated.


vim +485 drivers/dma/arm-dma350.c

   462	
   463	static irqreturn_t d350_irq(int irq, void *data)
   464	{
   465		struct d350_chan *dch = data;
   466		struct device *dev = dch->vc.chan.device->dev;
   467		struct virt_dma_desc *vd = &dch->desc->vd;
   468		u32 ch_status;
   469	
   470		ch_status = readl(dch->base + CH_STATUS);
   471		if (!ch_status)
   472			return IRQ_NONE;
   473	
   474		if (ch_status & CH_STAT_INTR_ERR) {
   475			u32 errinfo = readl_relaxed(dch->base + CH_ERRINFO);
   476	
   477			if (errinfo & (CH_ERRINFO_AXIRDPOISERR | CH_ERRINFO_AXIRDRESPERR))
   478				vd->tx_result.result = DMA_TRANS_READ_FAILED;
   479			else if (errinfo & CH_ERRINFO_AXIWRRESPERR)
   480				vd->tx_result.result = DMA_TRANS_WRITE_FAILED;
   481			else
   482				vd->tx_result.result = DMA_TRANS_ABORTED;
   483	
   484			vd->tx_result.residue = d350_get_residue(dch);
 > 485		} else if (!ch_status & CH_STAT_INTR_DONE) {
   486			dev_warn(dev, "Unexpected IRQ source? 0x%08x\n", ch_status);
   487		}
   488		writel_relaxed(ch_status, dch->base + CH_STATUS);
   489	
   490		spin_lock(&dch->vc.lock);
   491		vchan_cookie_complete(vd);
   492		if (ch_status & CH_STAT_INTR_DONE) {
   493			dch->status = DMA_COMPLETE;
   494			dch->residue = 0;
   495			d350_start_next(dch);
   496		} else {
   497			dch->status = DMA_ERROR;
   498			dch->residue = vd->tx_result.residue;
   499		}
   500		spin_unlock(&dch->vc.lock);
   501	
   502		return IRQ_HANDLED;
   503	}
   504	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 10:49:37 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 02:49:37 +0800
Subject: [PATCH v9 2/9] preempt: Introduce __preempt_count_{sub,
 add}_return()
In-Reply-To: <20250227221924.265259-3-lyude@redhat.com>
References: <20250227221924.265259-3-lyude@redhat.com>
Message-ID: <202503020258.CSGrY5E6-lkp@intel.com>

Hi Lyude,

kernel test robot noticed the following build errors:

[auto build test ERROR on 2014c95afecee3e76ca4a56956a936e23283f05b]

url:    https://github.com/intel-lab-lkp/linux/commits/Lyude-Paul/preempt-Introduce-HARDIRQ_DISABLE_BITS/20250228-062508
base:   2014c95afecee3e76ca4a56956a936e23283f05b
patch link:    https://lore.kernel.org/r/20250227221924.265259-3-lyude%40redhat.com
patch subject: [PATCH v9 2/9] preempt: Introduce __preempt_count_{sub, add}_return()
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250302/202503020258.CSGrY5E6-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020258.CSGrY5E6-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020258.CSGrY5E6-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:7:
   In file included from include/linux/hardirq.h:5:
   In file included from include/linux/context_tracking_state.h:5:
   In file included from include/linux/percpu.h:5:
   In file included from include/linux/alloc_tag.h:11:
   In file included from include/linux/preempt.h:85:
>> arch/s390/include/asm/preempt.h:109:15: error: invalid operands to binary expression ('int' and 'void')
     109 |                         return val + __atomic_add_const(val, &get_lowcore()->preempt_count);
         |                                ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:98:11: warning: array index 3 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
      98 |                 return (set->sig[3] | set->sig[2] |
         |                         ^        ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:98:25: warning: array index 2 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
      98 |                 return (set->sig[3] | set->sig[2] |
         |                                       ^        ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:99:4: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
      99 |                         set->sig[1] | set->sig[0]) == 0;
         |                         ^        ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:101:11: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
     101 |                 return (set->sig[1] | set->sig[0]) == 0;
         |                         ^        ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:114:11: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     114 |                 return  (set1->sig[3] == set2->sig[3]) &&
         |                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:114:27: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     114 |                 return  (set1->sig[3] == set2->sig[3]) &&
         |                                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:115:5: warning: array index 2 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     115 |                         (set1->sig[2] == set2->sig[2]) &&
         |                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:115:21: warning: array index 2 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     115 |                         (set1->sig[2] == set2->sig[2]) &&
         |                                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:116:5: warning: array index 1 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     116 |                         (set1->sig[1] == set2->sig[1]) &&
         |                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:116:21: warning: array index 1 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     116 |                         (set1->sig[1] == set2->sig[1]) &&
         |                                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:119:11: warning: array index 1 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     119 |                 return  (set1->sig[1] == set2->sig[1]) &&
         |                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:
   include/linux/signal.h:119:27: warning: array index 1 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
     119 |                 return  (set1->sig[1] == set2->sig[1]) &&
         |                                          ^         ~
   arch/s390/include/asm/signal.h:22:9: note: array 'sig' declared here
      22 |         unsigned long sig[_NSIG_WORDS];
         |         ^
   In file included from arch/s390/kernel/asm-offsets.c:11:
   In file included from include/linux/kvm_host.h:11:


vim +109 arch/s390/include/asm/preempt.h

   100	
   101	static __always_inline int __preempt_count_add_return(int val)
   102	{
   103		/*
   104		 * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES
   105		 * enabled, gcc 12 fails to handle __builtin_constant_p().
   106		 */
   107		if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) {
   108			if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) {
 > 109				return val + __atomic_add_const(val, &get_lowcore()->preempt_count);
   110			}
   111		}
   112		return val + __atomic_add(val, &get_lowcore()->preempt_count);
   113	}
   114	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 11:00:19 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 03:00:19 +0800
Subject: [PATCH v9 2/9] preempt: Introduce __preempt_count_{sub,
 add}_return()
In-Reply-To: <20250227221924.265259-3-lyude@redhat.com>
References: <20250227221924.265259-3-lyude@redhat.com>
Message-ID: <202503020203.USVBw4Bn-lkp@intel.com>

Hi Lyude,

kernel test robot noticed the following build errors:

[auto build test ERROR on 2014c95afecee3e76ca4a56956a936e23283f05b]

url:    https://github.com/intel-lab-lkp/linux/commits/Lyude-Paul/preempt-Introduce-HARDIRQ_DISABLE_BITS/20250228-062508
base:   2014c95afecee3e76ca4a56956a936e23283f05b
patch link:    https://lore.kernel.org/r/20250227221924.265259-3-lyude%40redhat.com
patch subject: [PATCH v9 2/9] preempt: Introduce __preempt_count_{sub, add}_return()
config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20250302/202503020203.USVBw4Bn-lkp at intel.com/config)
compiler: s390-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020203.USVBw4Bn-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020203.USVBw4Bn-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/preempt.h:85,
                    from include/linux/alloc_tag.h:11,
                    from include/linux/percpu.h:5,
                    from include/linux/context_tracking_state.h:5,
                    from include/linux/hardirq.h:5,
                    from include/linux/kvm_host.h:7,
                    from arch/s390/kernel/asm-offsets.c:11:
   arch/s390/include/asm/preempt.h: In function '__preempt_count_add_return':
>> arch/s390/include/asm/preempt.h:109:38: error: void value not ignored as it ought to be
     109 |                         return val + __atomic_add_const(val, &get_lowcore()->preempt_count);
         |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   make[3]: *** [scripts/Makefile.build:102: arch/s390/kernel/asm-offsets.s] Error 1
   make[3]: Target 'prepare' not remade because of errors.
   make[2]: *** [Makefile:1264: prepare0] Error 2
   make[2]: Target 'prepare' not remade because of errors.
   make[1]: *** [Makefile:251: __sub-make] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:251: __sub-make] Error 2
   make: Target 'prepare' not remade because of errors.


vim +109 arch/s390/include/asm/preempt.h

   100	
   101	static __always_inline int __preempt_count_add_return(int val)
   102	{
   103		/*
   104		 * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES
   105		 * enabled, gcc 12 fails to handle __builtin_constant_p().
   106		 */
   107		if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) {
   108			if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) {
 > 109				return val + __atomic_add_const(val, &get_lowcore()->preempt_count);
   110			}
   111		}
   112		return val + __atomic_add(val, &get_lowcore()->preempt_count);
   113	}
   114	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 11:10:48 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 03:10:48 +0800
Subject: [PATCH net-next v2 7/8] net: phy: move PHY package related code
 from phy.h to phy_package.c
In-Reply-To: <edba99c5-0f95-40bd-8398-98d811068369@gmail.com>
References: <edba99c5-0f95-40bd-8398-98d811068369@gmail.com>
Message-ID: <202503020223.C2TbkgPv-lkp@intel.com>

Hi Heiner,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heiner-Kallweit/net-phy-move-PHY-package-code-from-phy_device-c-to-own-source-file/20250301-055302
base:   net-next/main
patch link:    https://lore.kernel.org/r/edba99c5-0f95-40bd-8398-98d811068369%40gmail.com
patch subject: [PATCH net-next v2 7/8] net: phy: move PHY package related code from phy.h to phy_package.c
config: arc-randconfig-001-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020223.C2TbkgPv-lkp at intel.com/config)
compiler: arceb-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020223.C2TbkgPv-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020223.C2TbkgPv-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/net/phy/bcm54140.c: In function 'bcm54140_base_read_rdb':
>> drivers/net/phy/bcm54140.c:436:15: error: implicit declaration of function '__phy_package_write'; did you mean '__phy_package_write_mmd'? [-Werror=implicit-function-declaration]
     436 |         ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~~
         |               __phy_package_write_mmd
>> drivers/net/phy/bcm54140.c:441:15: error: implicit declaration of function '__phy_package_read'; did you mean '__phy_package_read_mmd'? [-Werror=implicit-function-declaration]
     441 |         ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~
         |               __phy_package_read_mmd
   cc1: some warnings being treated as errors


vim +436 drivers/net/phy/bcm54140.c

4406d36dfdf1fb Michael Walle     2020-04-20  430  
6937602ed3f9eb Michael Walle     2020-04-20  431  static int bcm54140_base_read_rdb(struct phy_device *phydev, u16 rdb)
6937602ed3f9eb Michael Walle     2020-04-20  432  {
6937602ed3f9eb Michael Walle     2020-04-20  433  	int ret;
6937602ed3f9eb Michael Walle     2020-04-20  434  
dc9989f173289f Michael Walle     2020-05-06  435  	phy_lock_mdio_bus(phydev);
9eea577eb1155f Christian Marangi 2023-12-15 @436  	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
9eea577eb1155f Christian Marangi 2023-12-15  437  				  MII_BCM54XX_RDB_ADDR, rdb);
6937602ed3f9eb Michael Walle     2020-04-20  438  	if (ret < 0)
6937602ed3f9eb Michael Walle     2020-04-20  439  		goto out;
6937602ed3f9eb Michael Walle     2020-04-20  440  
9eea577eb1155f Christian Marangi 2023-12-15 @441  	ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
9eea577eb1155f Christian Marangi 2023-12-15  442  				 MII_BCM54XX_RDB_DATA);
6937602ed3f9eb Michael Walle     2020-04-20  443  
6937602ed3f9eb Michael Walle     2020-04-20  444  out:
dc9989f173289f Michael Walle     2020-05-06  445  	phy_unlock_mdio_bus(phydev);
6937602ed3f9eb Michael Walle     2020-04-20  446  	return ret;
6937602ed3f9eb Michael Walle     2020-04-20  447  }
6937602ed3f9eb Michael Walle     2020-04-20  448  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 11:22:22 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 03:22:22 +0800
Subject: [PATCH net-next v2 7/8] net: phy: move PHY package related code
 from phy.h to phy_package.c
In-Reply-To: <edba99c5-0f95-40bd-8398-98d811068369@gmail.com>
References: <edba99c5-0f95-40bd-8398-98d811068369@gmail.com>
Message-ID: <202503020328.FJG7PJon-lkp@intel.com>

Hi Heiner,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heiner-Kallweit/net-phy-move-PHY-package-code-from-phy_device-c-to-own-source-file/20250301-055302
base:   net-next/main
patch link:    https://lore.kernel.org/r/edba99c5-0f95-40bd-8398-98d811068369%40gmail.com
patch subject: [PATCH net-next v2 7/8] net: phy: move PHY package related code from phy.h to phy_package.c
config: loongarch-randconfig-001-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020328.FJG7PJon-lkp at intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020328.FJG7PJon-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020328.FJG7PJon-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/net/phy/bcm54140.c: In function 'bcm54140_base_read_rdb':
   drivers/net/phy/bcm54140.c:436:15: error: implicit declaration of function '__phy_package_write'; did you mean '__phy_package_write_mmd'? [-Wimplicit-function-declaration]
     436 |         ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~~
         |               __phy_package_write_mmd
   drivers/net/phy/bcm54140.c:441:15: error: implicit declaration of function '__phy_package_read'; did you mean '__phy_package_read_mmd'? [-Wimplicit-function-declaration]
     441 |         ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~
         |               __phy_package_read_mmd
   drivers/net/phy/bcm54140.c: In function 'bcm54140_probe':
>> drivers/net/phy/bcm54140.c:599:13: error: implicit declaration of function 'phy_package_init_once'; did you mean 'phy_package_write_mmd'? [-Wimplicit-function-declaration]
     599 |         if (phy_package_init_once(phydev)) {
         |             ^~~~~~~~~~~~~~~~~~~~~
         |             phy_package_write_mmd


vim +599 drivers/net/phy/bcm54140.c

6937602ed3f9ebd Michael Walle 2020-04-20  578  
6937602ed3f9ebd Michael Walle 2020-04-20  579  static int bcm54140_probe(struct phy_device *phydev)
6937602ed3f9ebd Michael Walle 2020-04-20  580  {
6937602ed3f9ebd Michael Walle 2020-04-20  581  	struct bcm54140_priv *priv;
6937602ed3f9ebd Michael Walle 2020-04-20  582  	int ret;
6937602ed3f9ebd Michael Walle 2020-04-20  583  
6937602ed3f9ebd Michael Walle 2020-04-20  584  	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
6937602ed3f9ebd Michael Walle 2020-04-20  585  	if (!priv)
6937602ed3f9ebd Michael Walle 2020-04-20  586  		return -ENOMEM;
6937602ed3f9ebd Michael Walle 2020-04-20  587  
6937602ed3f9ebd Michael Walle 2020-04-20  588  	phydev->priv = priv;
6937602ed3f9ebd Michael Walle 2020-04-20  589  
6937602ed3f9ebd Michael Walle 2020-04-20  590  	ret = bcm54140_get_base_addr_and_port(phydev);
6937602ed3f9ebd Michael Walle 2020-04-20  591  	if (ret)
6937602ed3f9ebd Michael Walle 2020-04-20  592  		return ret;
6937602ed3f9ebd Michael Walle 2020-04-20  593  
dc9989f173289f3 Michael Walle 2020-05-06  594  	devm_phy_package_join(&phydev->mdio.dev, phydev, priv->base_addr, 0);
dc9989f173289f3 Michael Walle 2020-05-06  595  
4406d36dfdf1fbd Michael Walle 2020-04-20  596  #if IS_ENABLED(CONFIG_HWMON)
4406d36dfdf1fbd Michael Walle 2020-04-20  597  	mutex_init(&priv->alarm_lock);
4406d36dfdf1fbd Michael Walle 2020-04-20  598  
dc9989f173289f3 Michael Walle 2020-05-06 @599  	if (phy_package_init_once(phydev)) {
4406d36dfdf1fbd Michael Walle 2020-04-20  600  		ret = bcm54140_probe_once(phydev);
4406d36dfdf1fbd Michael Walle 2020-04-20  601  		if (ret)
4406d36dfdf1fbd Michael Walle 2020-04-20  602  			return ret;
4406d36dfdf1fbd Michael Walle 2020-04-20  603  	}
4406d36dfdf1fbd Michael Walle 2020-04-20  604  #endif
4406d36dfdf1fbd Michael Walle 2020-04-20  605  
6937602ed3f9ebd Michael Walle 2020-04-20  606  	phydev_dbg(phydev, "probed (port %d, base PHY address %d)\n",
6937602ed3f9ebd Michael Walle 2020-04-20  607  		   priv->port, priv->base_addr);
6937602ed3f9ebd Michael Walle 2020-04-20  608  
6937602ed3f9ebd Michael Walle 2020-04-20  609  	return 0;
6937602ed3f9ebd Michael Walle 2020-04-20  610  }
6937602ed3f9ebd Michael Walle 2020-04-20  611  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 12:09:16 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 04:09:16 +0800
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
References: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
Message-ID: <202503020324.hFtOv6c7-lkp@intel.com>

Hi Robin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Robin-Murphy/dt-bindings-dma-Add-Arm-DMA-350/20250301-012733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link:    https://lore.kernel.org/r/55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy%40arm.com
patch subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
config: parisc-randconfig-002-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020324.hFtOv6c7-lkp at intel.com/config)
compiler: hppa-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020324.hFtOv6c7-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020324.hFtOv6c7-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/dma/arm-dma350.c:641:34: warning: 'd350_of_match' defined but not used [-Wunused-const-variable=]
     641 | static const struct of_device_id d350_of_match[] = {
         |                                  ^~~~~~~~~~~~~


vim +/d350_of_match +641 drivers/dma/arm-dma350.c

   640	
 > 641	static const struct of_device_id d350_of_match[] = {
   642		{ .compatible = "arm,dma-350" },
   643		{}
   644	};
   645	MODULE_DEVICE_TABLE(of, d350_of_match);
   646	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  1 12:19:55 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 04:19:55 +0800
Subject: [PATCH net-next v2 8/8] net: phy: remove remaining PHY package
 related definitions from phy.h
In-Reply-To: <6ad490fa-61ad-48b8-9660-bb525f756f41@gmail.com>
References: <6ad490fa-61ad-48b8-9660-bb525f756f41@gmail.com>
Message-ID: <202503020420.v2TkGxj1-lkp@intel.com>

Hi Heiner,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heiner-Kallweit/net-phy-move-PHY-package-code-from-phy_device-c-to-own-source-file/20250301-055302
base:   net-next/main
patch link:    https://lore.kernel.org/r/6ad490fa-61ad-48b8-9660-bb525f756f41%40gmail.com
patch subject: [PATCH net-next v2 8/8] net: phy: remove remaining PHY package related definitions from phy.h
config: arc-randconfig-001-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020420.v2TkGxj1-lkp at intel.com/config)
compiler: arceb-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020420.v2TkGxj1-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020420.v2TkGxj1-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/net/phy/bcm54140.c: In function 'bcm54140_base_read_rdb':
   drivers/net/phy/bcm54140.c:436:15: error: implicit declaration of function '__phy_package_write'; did you mean '__phy_package_write_mmd'? [-Werror=implicit-function-declaration]
     436 |         ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~~
         |               __phy_package_write_mmd
   drivers/net/phy/bcm54140.c:441:15: error: implicit declaration of function '__phy_package_read'; did you mean '__phy_package_read_mmd'? [-Werror=implicit-function-declaration]
     441 |         ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
         |               ^~~~~~~~~~~~~~~~~~
         |               __phy_package_read_mmd
   drivers/net/phy/bcm54140.c: In function 'bcm54140_probe':
>> drivers/net/phy/bcm54140.c:594:9: error: implicit declaration of function 'devm_phy_package_join' [-Werror=implicit-function-declaration]
     594 |         devm_phy_package_join(&phydev->mdio.dev, phydev, priv->base_addr, 0);
         |         ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/devm_phy_package_join +594 drivers/net/phy/bcm54140.c

6937602ed3f9eb Michael Walle 2020-04-20  578  
6937602ed3f9eb Michael Walle 2020-04-20  579  static int bcm54140_probe(struct phy_device *phydev)
6937602ed3f9eb Michael Walle 2020-04-20  580  {
6937602ed3f9eb Michael Walle 2020-04-20  581  	struct bcm54140_priv *priv;
6937602ed3f9eb Michael Walle 2020-04-20  582  	int ret;
6937602ed3f9eb Michael Walle 2020-04-20  583  
6937602ed3f9eb Michael Walle 2020-04-20  584  	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
6937602ed3f9eb Michael Walle 2020-04-20  585  	if (!priv)
6937602ed3f9eb Michael Walle 2020-04-20  586  		return -ENOMEM;
6937602ed3f9eb Michael Walle 2020-04-20  587  
6937602ed3f9eb Michael Walle 2020-04-20  588  	phydev->priv = priv;
6937602ed3f9eb Michael Walle 2020-04-20  589  
6937602ed3f9eb Michael Walle 2020-04-20  590  	ret = bcm54140_get_base_addr_and_port(phydev);
6937602ed3f9eb Michael Walle 2020-04-20  591  	if (ret)
6937602ed3f9eb Michael Walle 2020-04-20  592  		return ret;
6937602ed3f9eb Michael Walle 2020-04-20  593  
dc9989f173289f Michael Walle 2020-05-06 @594  	devm_phy_package_join(&phydev->mdio.dev, phydev, priv->base_addr, 0);
dc9989f173289f Michael Walle 2020-05-06  595  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From alexandre.belloni at bootlin.com  Sat Mar  1 12:36:58 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Sat, 1 Mar 2025 21:36:58 +0100
Subject: [PATCH 00/18] a few rtc driver cleanups
In-Reply-To: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
Message-ID: <20250301203658839d5482@mail.local>

On 28/02/2025 14:07:13+0000, Andr? Draszik wrote:
> Hi,
> 
> While looking at RTC, I noticed that various drivers are keeping
> pointers to data that they're not using themselves throughout their
> lifetime.
> 
> So I took the liberty to drop these pointers and this series is the
> result.
> 
> The last two patches also convert two drivers to using dev_err_probe(),
> as I looked slightly closer into those two. They don't exactly fit the
> general subject of removal of unneeded pointers, but I wanted to share
> them anyway, since they're ready.
> 
> All of this was compile-tested only.
> 
> Cheers,
> Andre'
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
> Andr? Draszik (18):
>       rtc: max77686: drop needless struct max77686_rtc_info::rtc member
>       rtc: s5m: drop needless struct s5m_rtc_info::i2c member
>       rtc: aspeed: drop needless struct aspeed_rtc::rtc_dev member
>       rtc: ds2404: drop needless struct ds2404::rtc member
>       rtc: ep93xx: drop needless struct ep93xx_rtc::rtc member
>       rtc: ftrtc010: drop needless struct ftrtc010_rtc::rtc_dev member
>       rtc: m48t86: drop needless struct m48t86_rtc_info::rtc member
>       rtc: meson: drop needless struct meson_rtc::rtc member
>       rtc: meson-vrtc: drop needless struct meson_vrtc_data::rtc member
>       rtc: pl030: drop needless struct pl030_rtc::rtc member
>       rtc: rx8581: drop needless struct rx8581::rtc member
>       rtc: s35390a: drop needless struct s35390a::rtc member
>       rtc: sd2405al: drop needless struct sd2405al::rtc member
>       rtc: sd3078: drop needless struct sd3078::rtc member

My main concern with this is that as soon as we introduce irq support,
we are going to need the rtc pointer back in the struct. But I guess
that most of them are old enough to say that nobody is interested in irq
support.

>       rtc: rx8581: drop needless struct rx8581
>       rtc: sd3078: drop needless struct sd3078

I guess you could squash those two with the previous ones touching the
respective drivers because you are the one removing the last remaining
struct member.

>       rtc: max77686: use dev_err_probe() where appropriate
>       rtc: s5m: convert to dev_err_probe() where appropriate
> 
>  drivers/rtc/rtc-aspeed.c     | 16 ++++-----
>  drivers/rtc/rtc-ds2404.c     | 14 ++++----
>  drivers/rtc/rtc-ep93xx.c     | 16 ++++-----
>  drivers/rtc/rtc-ftrtc010.c   | 17 +++++----
>  drivers/rtc/rtc-m48t86.c     | 14 ++++----
>  drivers/rtc/rtc-max77686.c   | 37 +++++++++----------
>  drivers/rtc/rtc-meson-vrtc.c | 12 +++----
>  drivers/rtc/rtc-meson.c      | 16 ++++-----
>  drivers/rtc/rtc-pl030.c      | 14 ++++----
>  drivers/rtc/rtc-rx8581.c     | 85 +++++++++++++++++++-------------------------
>  drivers/rtc/rtc-s35390a.c    | 22 ++++++------
>  drivers/rtc/rtc-s5m.c        | 58 +++++++++++++-----------------
>  drivers/rtc/rtc-sd2405al.c   | 16 ++++-----
>  drivers/rtc/rtc-sd3078.c     | 71 +++++++++++++++---------------------
>  14 files changed, 183 insertions(+), 225 deletions(-)
> ---
> base-commit: 0226d0ce98a477937ed295fb7df4cc30b46fc304
> change-id: 20250228-rtc-cleanups-12c0b5123ea4
> 
> Best regards,
> -- 
> Andr? Draszik <andre.draszik at linaro.org>
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From sebastian.reichel at collabora.com  Sat Mar  1 13:19:28 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Sat, 1 Mar 2025 22:19:28 +0100
Subject: [PATCH v2 2/2] phy: rockchip: usbdp: re-init the phy on
 orientation-change
In-Reply-To: <02757b21-7599-4ee7-9f97-247b04ba646a@cherry.de>
References: <20250226103810.3746018-1-heiko@sntech.de>
 <20250226103810.3746018-3-heiko@sntech.de>
 <02757b21-7599-4ee7-9f97-247b04ba646a@cherry.de>
Message-ID: <dkjpudmzuuxvaotz4mx46yx7iacof7q6ck746j3rrqvlgbq3hk@6vtvy3gy3kff>

Hello Quentin,

On Wed, Feb 26, 2025 at 01:38:10PM +0100, Quentin Schulz wrote:
> Unrelated to this patch (but may be triggered by this patch?), I'm wondering
> how flip is really handled.
> 
> It seems like we have flip store the orientation of the cable, but also if
> rockchip,dp-lane-mux is set to <0 1>. But wouldn't that break if we ignore
> that initial flipped lane-mux whenever a USB-C cable is inserted in reverse?
> Basically, shouldn't a reserve orientation of the cable when
> rockchip,dp-lane-mux is set to <0 1> mean "normal mux"?

If a USB-C connector is involved, the TypeC controller is supposed to
setup the lane muxing based on the connector orientation. This
happens via the typec API and in this hardware setup the PHY should
not have the rockchip,dp-lane-mux DT property set.

The rockchip,dp-lane-mux property is required if no USB-C connector
is involved. For example if the lanes are routed to a Displayport
connector. In that case the lane setup is fixed in hardware and
there is no TypeC controller involved, which could do any setup ;)

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250301/0df857cc/attachment.sig>

From will at kernel.org  Sat Mar  1 13:21:16 2025
From: will at kernel.org (Will Deacon)
Date: Sat, 1 Mar 2025 21:21:16 +0000
Subject: [GIT PULL] arm64 fixes for -rc5
Message-ID: <20250301212116.GA29069@willie-the-truck>

Hi Linus,

Ryan's been hard at work finding and fixing mm bugs in the arm64 code,
so here's a small crop of fixes for -rc5. The main changes are to fix
our zapping of non-present PTEs for hugetlb entries created using the
contiguous bit in the page-table rather than a block entry at the level
above. Prior to these fixes, we were pulling the contiguous bit back out
of the PTE in order to determine the size of the hugetlb page but this
is clearly bogus if the thing isn't present and consequently both the
clearing of the PTE(s) and the TLB invalidation were unreliable.

Although the problem was found by code inspection, we really don't want
this sitting around waiting to trigger and the changes are CC'd to stable
accordingly.

Note that the diffstat looks a lot worse than it really is;
huge_ptep_get_and_clear() now takes a size argument from the core code
and so all the arch implementations of that have been updated in a
pretty mechanical fashion. The patches have been in linux-next without
problems and Andrew is aware that they're coming via arm64 [1].

Cheers, and please pull.

Will

[1] https://lore.kernel.org/all/20250205235219.3c3a4b968087d1386d708b04 at linux-foundation.org/

--->8

The following changes since commit 0ad2507d5d93f39619fc42372c347d6006b64319:

  Linux 6.14-rc3 (2025-02-16 14:02:44 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes

for you to fetch changes up to eed6bfa8b28230382b797a88569f2c7569a1a419:

  arm64: hugetlb: Fix flush_hugetlb_tlb_range() invalidation level (2025-02-27 17:40:58 +0000)

----------------------------------------------------------------
arm64 fixes for -rc5

- Fix a sporadic boot failure due to incorrect randomization of the
  linear map on systems that support it

- Fix the zapping (both clearing the entries *and* invalidating the TLB)
  of hugetlb PTEs constructed using the contiguous bit

----------------------------------------------------------------
Ryan Roberts (4):
      arm64/mm: Fix Boot panic on Ampere Altra
      mm: hugetlb: Add huge page size param to huge_ptep_get_and_clear()
      arm64: hugetlb: Fix huge_ptep_get_and_clear() for non-present ptes
      arm64: hugetlb: Fix flush_hugetlb_tlb_range() invalidation level

 arch/arm64/include/asm/hugetlb.h     | 26 +++++++++++-----
 arch/arm64/mm/hugetlbpage.c          | 59 +++++++++++++++---------------------
 arch/arm64/mm/init.c                 |  7 +----
 arch/loongarch/include/asm/hugetlb.h |  6 ++--
 arch/mips/include/asm/hugetlb.h      |  6 ++--
 arch/parisc/include/asm/hugetlb.h    |  2 +-
 arch/parisc/mm/hugetlbpage.c         |  2 +-
 arch/powerpc/include/asm/hugetlb.h   |  6 ++--
 arch/riscv/include/asm/hugetlb.h     |  3 +-
 arch/riscv/mm/hugetlbpage.c          |  2 +-
 arch/s390/include/asm/hugetlb.h      | 16 +++++++---
 arch/s390/mm/hugetlbpage.c           |  4 +--
 arch/sparc/include/asm/hugetlb.h     |  2 +-
 arch/sparc/mm/hugetlbpage.c          |  2 +-
 include/asm-generic/hugetlb.h        |  2 +-
 include/linux/hugetlb.h              |  4 ++-
 mm/hugetlb.c                         |  4 +--
 17 files changed, 82 insertions(+), 71 deletions(-)


From lkp at intel.com  Sat Mar  1 13:45:30 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 05:45:30 +0800
Subject: [PATCH 4/9] drm/panthor: Implement optional reset
In-Reply-To: <20250227170012.124768-5-marex@denx.de>
References: <20250227170012.124768-5-marex@denx.de>
Message-ID: <202503020521.MBUsoVte-lkp@intel.com>

Hi Marek,

kernel test robot noticed the following build warnings:

[auto build test WARNING on shawnguo/for-next]
[also build test WARNING on robh/for-next arm64/for-next/core kvmarm/next rockchip/for-next soc/for-next linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Marek-Vasut/dt-bindings-reset-imx95-gpu-blk-ctrl-Document-Freescale-i-MX95-GPU-reset/20250228-011031
base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git for-next
patch link:    https://lore.kernel.org/r/20250227170012.124768-5-marex%40denx.de
patch subject: [PATCH 4/9] drm/panthor: Implement optional reset
config: x86_64-kismet-CONFIG_RESET_SIMPLE-CONFIG_DRM_PANTHOR-0-0 (https://download.01.org/0day-ci/archive/20250302/202503020521.MBUsoVte-lkp at intel.com/config)
reproduce: (https://download.01.org/0day-ci/archive/20250302/202503020521.MBUsoVte-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020521.MBUsoVte-lkp at intel.com/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for RESET_SIMPLE when selected by DRM_PANTHOR
   WARNING: unmet direct dependencies detected for RESET_SIMPLE
     Depends on [n]: RESET_CONTROLLER [=n] && HAS_IOMEM [=y]
     Selected by [y]:
     - DRM_PANTHOR [=y] && HAS_IOMEM [=y] && DRM [=y] && (ARM || ARM64 || COMPILE_TEST [=y]) && !GENERIC_ATOMIC64 [=n] && MMU [=y] && SOC_IMX9 [=y]

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From pr-tracker-bot at kernel.org  Sat Mar  1 13:48:13 2025
From: pr-tracker-bot at kernel.org (pr-tracker-bot at kernel.org)
Date: Sat, 01 Mar 2025 21:48:13 +0000
Subject: [GIT PULL] arm64 fixes for -rc5
In-Reply-To: <20250301212116.GA29069@willie-the-truck>
References: <20250301212116.GA29069@willie-the-truck>
Message-ID: <174086569337.2508762.431455640708983782.pr-tracker-bot@kernel.org>

The pull request you sent on Sat, 1 Mar 2025 21:21:16 +0000:

> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/9d20040d71ede4c0e5fc6ae7aaa92788de1e713a

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


From lkp at intel.com  Sat Mar  1 13:56:57 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 05:56:57 +0800
Subject: [rockchip:v6.15-clk/next 10/10]
 drivers/clk/rockchip/clk-rk3562.c:1081:38: error: invalid use of undefined
 type 'struct platform_device'
Message-ID: <202503020525.AVLjosKr-lkp@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git v6.15-clk/next
head:   36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a
commit: 36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a [10/10] clk: rockchip: Add clock controller for the RK3562
config: arm-allmodconfig (https://download.01.org/0day-ci/archive/20250302/202503020525.AVLjosKr-lkp at intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503020525.AVLjosKr-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020525.AVLjosKr-lkp at intel.com/

All error/warnings (new ones prefixed by >>):

>> drivers/clk/rockchip/clk-rk3562.c:1079:36: warning: 'struct platform_device' declared inside parameter list will not be visible outside of this definition or declaration
    1079 | static int clk_rk3562_probe(struct platform_device *pdev)
         |                                    ^~~~~~~~~~~~~~~
   drivers/clk/rockchip/clk-rk3562.c: In function 'clk_rk3562_probe':
>> drivers/clk/rockchip/clk-rk3562.c:1081:38: error: invalid use of undefined type 'struct platform_device'
    1081 |         struct device_node *np = pdev->dev.of_node;
         |                                      ^~
   drivers/clk/rockchip/clk-rk3562.c:1085:62: error: invalid use of undefined type 'struct platform_device'
    1085 |         match = of_match_device(clk_rk3562_match_table, &pdev->dev);
         |                                                              ^~
   drivers/clk/rockchip/clk-rk3562.c: At top level:
>> drivers/clk/rockchip/clk-rk3562.c:1096:15: error: variable 'clk_rk3562_driver' has initializer but incomplete type
    1096 | static struct platform_driver clk_rk3562_driver = {
         |               ^~~~~~~~~~~~~~~
>> drivers/clk/rockchip/clk-rk3562.c:1097:10: error: 'struct platform_driver' has no member named 'probe'
    1097 |         .probe          = clk_rk3562_probe,
         |          ^~~~~
>> drivers/clk/rockchip/clk-rk3562.c:1097:27: warning: excess elements in struct initializer
    1097 |         .probe          = clk_rk3562_probe,
         |                           ^~~~~~~~~~~~~~~~
   drivers/clk/rockchip/clk-rk3562.c:1097:27: note: (near initialization for 'clk_rk3562_driver')
>> drivers/clk/rockchip/clk-rk3562.c:1098:10: error: 'struct platform_driver' has no member named 'driver'
    1098 |         .driver         = {
         |          ^~~~~~
>> drivers/clk/rockchip/clk-rk3562.c:1098:27: error: extra brace group at end of initializer
    1098 |         .driver         = {
         |                           ^
   drivers/clk/rockchip/clk-rk3562.c:1098:27: note: (near initialization for 'clk_rk3562_driver')
   drivers/clk/rockchip/clk-rk3562.c:1098:27: warning: excess elements in struct initializer
   drivers/clk/rockchip/clk-rk3562.c:1098:27: note: (near initialization for 'clk_rk3562_driver')
>> drivers/clk/rockchip/clk-rk3562.c:1104:1: warning: data definition has no type or storage class
    1104 | module_platform_driver(clk_rk3562_driver);
         | ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/clk/rockchip/clk-rk3562.c:1104:1: error: type defaults to 'int' in declaration of 'module_platform_driver' [-Wimplicit-int]
>> drivers/clk/rockchip/clk-rk3562.c:1104:1: error: parameter names (without types) in function declaration [-Wdeclaration-missing-parameter-type]
>> drivers/clk/rockchip/clk-rk3562.c:1096:31: error: storage size of 'clk_rk3562_driver' isn't known
    1096 | static struct platform_driver clk_rk3562_driver = {
         |                               ^~~~~~~~~~~~~~~~~
>> drivers/clk/rockchip/clk-rk3562.c:1096:31: warning: 'clk_rk3562_driver' defined but not used [-Wunused-variable]


vim +1081 drivers/clk/rockchip/clk-rk3562.c

  1078	
> 1079	static int clk_rk3562_probe(struct platform_device *pdev)
  1080	{
> 1081		struct device_node *np = pdev->dev.of_node;
  1082		const struct of_device_id *match;
  1083		const struct clk_rk3562_inits *init_data;
  1084	
> 1085		match = of_match_device(clk_rk3562_match_table, &pdev->dev);
  1086		if (!match || !match->data)
  1087			return -EINVAL;
  1088	
  1089		init_data = match->data;
  1090		if (init_data->inits)
  1091			init_data->inits(np);
  1092	
  1093		return 0;
  1094	}
  1095	
> 1096	static struct platform_driver clk_rk3562_driver = {
> 1097		.probe		= clk_rk3562_probe,
> 1098		.driver		= {
  1099			.name	= "clk-rk3562",
  1100			.of_match_table = clk_rk3562_match_table,
  1101			.suppress_bind_attrs = true,
  1102		},
  1103	};
> 1104	module_platform_driver(clk_rk3562_driver);
  1105	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From sebastian.reichel at collabora.com  Sat Mar  1 14:42:51 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Sat, 1 Mar 2025 23:42:51 +0100
Subject: [PATCH v1 1/1] arm64: dts: rockchip: Add USB-C support to ROCK 5B
In-Reply-To: <12e97e18.367e.19551b6aea2.Coremail.andyshrk@163.com>
References: <20241210163615.120594-1-sebastian.reichel@collabora.com>
 <12e97e18.367e.19551b6aea2.Coremail.andyshrk@163.com>
Message-ID: <njeivdzwyy6qxome77asapmi3a3l34mpauk366f6zgpt2mvorz@ra77f5vjd5lf>

Hello Andy,

On Sat, Mar 01, 2025 at 08:38:01PM +0800, Andy Yan wrote:
> At 2024-12-11 00:36:01, "Sebastian Reichel" <sebastian.reichel at collabora.com> wrote:
> >Add hardware description for the USB-C port in the Radxa Rock 5 Model B.
> >This describes the OHCI, EHCI and XHCI USB parts, but not yet the
> >DisplayPort AltMode (bindings are not yet upstream).
> >
> >The fusb302 node is marked with status "fail", since the board is usually
> >powered through the USB-C port. Handling of errors can result in hard
> >resets, which removed the bus power for some time resulting in a board
> >reset.
> >
> >The main problem is that devices are supposed to interact with the
> >power-supply within 5 seconds after the plug event according to the
> >USB PD specification. This is more or less impossible to achieve when
> >the kernel is the first software communicating with the power-supply.
> >
> >Recent U-Boot (v2025.01) will start doing USB-PD communication, which
> >solves this issue. Upstream U-Boot doing USB-PD communication will also
> >set the fusb302 node status to "okay". That way booting a kernel with
> >the updated DT on an old U-Boot avoids a reset loop.
> 
> Do you have any plans to continue working on this patch?
> I've been working on enabling the DP Alt Mode output recently
> and think the Rock 5b is a good starting point?

This is still on my radar. I recently send an updates U-Boot series
with some TCPM improvements:

https://lore.kernel.org/u-boot/20250226184506.64114-1-sebastian.reichel at collabora.com/

Even with that there are more issues resulting in hard resets
happening in some circumstances (if they are happening depends a lot
on the specific powre supply being used). I'm still looking for the
root cause of these. It's also hard to tell when it is a good time
to apply this patch. Some people will probably see a regression due
to using power-supplies diverging too far from the standard :/

Greetings,

-- Sebastian

>      
> >
> >Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
> >---
> > .../boot/dts/rockchip/rk3588-rock-5b.dts      | 121 ++++++++++++++++++
> > 1 file changed, 121 insertions(+)
> >
> >diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
> >index d597112f1d5b..cb5990df6ccb 100644
> >--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
> >+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
> >@@ -5,6 +5,7 @@
> > #include <dt-bindings/gpio/gpio.h>
> > #include <dt-bindings/leds/common.h>
> > #include <dt-bindings/soc/rockchip,vop2.h>
> >+#include <dt-bindings/usb/pd.h>
> > #include "rk3588.dtsi"
> > 
> > / {
> >@@ -84,6 +85,15 @@ rfkill-bt {
> > 		shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
> > 	};
> > 
> >+	vcc12v_dcin: regulator-vcc12v-dcin {
> >+		compatible = "regulator-fixed";
> >+		regulator-name = "vcc12v_dcin";
> >+		regulator-always-on;
> >+		regulator-boot-on;
> >+		regulator-min-microvolt = <12000000>;
> >+		regulator-max-microvolt = <12000000>;
> >+	};
> >+
> > 	vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
> > 		compatible = "regulator-fixed";
> > 		enable-active-high;
> >@@ -142,6 +152,7 @@ vcc5v0_sys: regulator-vcc5v0-sys {
> > 		regulator-boot-on;
> > 		regulator-min-microvolt = <5000000>;
> > 		regulator-max-microvolt = <5000000>;
> >+		vin-supply = <&vcc12v_dcin>;
> > 	};
> > 
> > 	vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
> >@@ -264,6 +275,67 @@ regulator-state-mem {
> > 	};
> > };
> > 
> >+&i2c4 {
> >+	pinctrl-names = "default";
> >+	pinctrl-0 = <&i2c4m1_xfer>;
> >+	status = "okay";
> >+
> >+	usbc0: usb-typec at 22 {
> >+		compatible = "fcs,fusb302";
> >+		reg = <0x22>;
> >+		interrupt-parent = <&gpio3>;
> >+		interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
> >+		pinctrl-names = "default";
> >+		pinctrl-0 = <&usbc0_int>;
> >+		vbus-supply = <&vcc12v_dcin>;
> >+		/*
> >+		 * When the board is starting to send power-delivery messages
> >+		 * too late (5 seconds according to the specification), the
> >+		 * power-supply reacts with a hard-reset. That removes the
> >+		 * power from VBUS for some time, which resets te whole board.
> >+		 */
> >+		status = "fail";
> >+
> >+		usb_con: connector {
> >+			compatible = "usb-c-connector";
> >+			label = "USB-C";
> >+			data-role = "dual";
> >+			power-role = "sink";
> >+			try-power-role = "sink";
> >+			op-sink-microwatt = <1000000>;
> >+			sink-pdos =
> >+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>,
> >+				<PDO_VAR(5000, 20000, 5000)>;
> >+
> >+			ports {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+
> >+				port at 0 {
> >+					reg = <0>;
> >+					usbc0_role_sw: endpoint {
> >+						remote-endpoint = <&dwc3_0_role_switch>;
> >+					};
> >+				};
> >+
> >+				port at 1 {
> >+					reg = <1>;
> >+					usbc0_orien_sw: endpoint {
> >+						remote-endpoint = <&usbdp_phy0_orientation_switch>;
> >+					};
> >+				};
> >+
> >+				port at 2 {
> >+					reg = <2>;
> >+					dp_altmode_mux: endpoint {
> >+						remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
> >+					};
> >+				};
> >+			};
> >+		};
> >+	};
> >+};
> >+
> > &i2c6 {
> > 	status = "okay";
> > 
> >@@ -423,6 +495,10 @@ usb {
> > 		vcc5v0_host_en: vcc5v0-host-en {
> > 			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
> > 		};
> >+
> >+		usbc0_int: usbc0-int {
> >+			rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
> >+		};
> > 	};
> > };
> > 
> >@@ -835,6 +911,14 @@ &uart2 {
> > 	status = "okay";
> > };
> > 
> >+&u2phy0 {
> >+	status = "okay";
> >+};
> >+
> >+&u2phy0_otg {
> >+	status = "okay";
> >+};
> >+
> > &u2phy1 {
> > 	status = "okay";
> > };
> >@@ -866,6 +950,29 @@ &usbdp_phy1 {
> > 	status = "okay";
> > };
> > 
> >+&usbdp_phy0 {
> >+	mode-switch;
> >+	orientation-switch;
> >+	sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
> >+	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
> >+	status = "okay";
> >+
> >+	port {
> >+		#address-cells = <1>;
> >+		#size-cells = <0>;
> >+
> >+		usbdp_phy0_orientation_switch: endpoint at 0 {
> >+			reg = <0>;
> >+			remote-endpoint = <&usbc0_orien_sw>;
> >+		};
> >+
> >+		usbdp_phy0_dp_altmode_mux: endpoint at 1 {
> >+			reg = <1>;
> >+			remote-endpoint = <&dp_altmode_mux>;
> >+		};
> >+	};
> >+};
> >+
> > &usb_host0_ehci {
> > 	status = "okay";
> > };
> >@@ -874,6 +981,20 @@ &usb_host0_ohci {
> > 	status = "okay";
> > };
> > 
> >+&usb_host0_xhci {
> >+	usb-role-switch;
> >+	status = "okay";
> >+
> >+	port {
> >+		#address-cells = <1>;
> >+		#size-cells = <0>;
> >+
> >+		dwc3_0_role_switch: endpoint {
> >+			remote-endpoint = <&usbc0_role_sw>;
> >+		};
> >+	};
> >+};
> >+
> > &usb_host1_ehci {
> > 	status = "okay";
> > };
> >-- 
> >2.45.2
> >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250301/c0372821/attachment.sig>

From lkp at intel.com  Sat Mar  1 18:08:48 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 10:08:48 +0800
Subject: [PATCH v2 5/8] phy: phy-snps-eusb2: make repeater optional
In-Reply-To: <20250223122227.725233-6-ivo.ivanov.ivanov1@gmail.com>
References: <20250223122227.725233-6-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <202503020920.Kw0H8Acs-lkp@intel.com>

Hi Ivaylo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ivaylo-Ivanov/dt-bindings-phy-rename-qcom-snps-eusb2-phy-binding-to-snps-eusb2-phy/20250223-202709
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250223122227.725233-6-ivo.ivanov.ivanov1%40gmail.com
patch subject: [PATCH v2 5/8] phy: phy-snps-eusb2: make repeater optional
config: microblaze-randconfig-r123-20250302 (https://download.01.org/0day-ci/archive/20250302/202503020920.Kw0H8Acs-lkp at intel.com/config)
compiler: microblaze-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250302/202503020920.Kw0H8Acs-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503020920.Kw0H8Acs-lkp at intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/phy/phy-snps-eusb2.c:464:59: sparse: sparse: Using plain integer as NULL pointer

vim +464 drivers/phy/phy-snps-eusb2.c

   398	
   399	static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
   400	{
   401		struct device *dev = &pdev->dev;
   402		struct device_node *np = dev->of_node;
   403		struct snps_eusb2_hsphy *phy;
   404		struct phy_provider *phy_provider;
   405		struct phy *generic_phy;
   406		const struct snps_eusb2_phy_drvdata *drv_data;
   407		int ret, i;
   408		int num;
   409	
   410		phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
   411		if (!phy)
   412			return -ENOMEM;
   413	
   414		drv_data = of_device_get_match_data(dev);
   415		if (!drv_data)
   416			return -EINVAL;
   417		phy->data = drv_data;
   418	
   419		phy->base = devm_platform_ioremap_resource(pdev, 0);
   420		if (IS_ERR(phy->base))
   421			return PTR_ERR(phy->base);
   422	
   423		phy->phy_reset = devm_reset_control_get_exclusive(dev, NULL);
   424		if (IS_ERR(phy->phy_reset))
   425			return PTR_ERR(phy->phy_reset);
   426	
   427		phy->clks = devm_kcalloc(dev,
   428					 phy->data->num_clks,
   429					 sizeof(*phy->clks),
   430					 GFP_KERNEL);
   431		if (!phy->clks)
   432			return -ENOMEM;
   433	
   434		for (int i = 0; i < phy->data->num_clks; ++i)
   435			phy->clks[i].id = phy->data->clk_names[i];
   436	
   437		ret = devm_clk_bulk_get(dev, phy->data->num_clks,
   438					phy->clks);
   439		if (ret)
   440			return dev_err_probe(dev, ret,
   441					     "failed to get phy clock(s)\n");
   442	
   443		phy->ref_clk = NULL;
   444		for (int i = 0; i < phy->data->num_clks; ++i) {
   445			if (!strcmp(phy->clks[i].id, "ref")) {
   446				phy->ref_clk = phy->clks[i].clk;
   447				break;
   448			}
   449		}
   450	
   451		if (IS_ERR_OR_NULL(phy->ref_clk))
   452			return dev_err_probe(dev, PTR_ERR(phy->ref_clk),
   453					     "failed to get ref clk\n");
   454	
   455		num = ARRAY_SIZE(phy->vregs);
   456		for (i = 0; i < num; i++)
   457			phy->vregs[i].supply = eusb2_hsphy_vreg_names[i];
   458	
   459		ret = devm_regulator_bulk_get(dev, num, phy->vregs);
   460		if (ret)
   461			return dev_err_probe(dev, ret,
   462					     "failed to get regulator supplies\n");
   463	
 > 464		phy->repeater = devm_of_phy_optional_get(dev, np, 0);
   465		if (IS_ERR(phy->repeater))
   466			return dev_err_probe(dev, PTR_ERR(phy->repeater),
   467					     "failed to get repeater\n");
   468	
   469		generic_phy = devm_phy_create(dev, NULL, &snps_eusb2_hsphy_ops);
   470		if (IS_ERR(generic_phy)) {
   471			dev_err(dev, "failed to create phy %d\n", ret);
   472			return PTR_ERR(generic_phy);
   473		}
   474	
   475		dev_set_drvdata(dev, phy);
   476		phy_set_drvdata(generic_phy, phy);
   477	
   478		phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
   479		if (IS_ERR(phy_provider))
   480			return PTR_ERR(phy_provider);
   481	
   482		dev_info(dev, "Registered Snps-eUSB2 phy\n");
   483	
   484		return 0;
   485	}
   486	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From jic23 at kernel.org  Sat Mar  1 18:44:34 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 02:44:34 +0000
Subject: [PATCH v3 3/9] iio: adc: Support ROHM BD79124 ADC
In-Reply-To: <125ab96e-1e92-4022-95fe-324cd47ce1d9@gmail.com>
References: <cover.1739967040.git.mazziesaccount@gmail.com>
	<67b7713724d7591f6321a8f5dfef8cd711f38d34.1739967040.git.mazziesaccount@gmail.com>
	<20250223162807.41960b6b@jic23-huawei>
	<125ab96e-1e92-4022-95fe-324cd47ce1d9@gmail.com>
Message-ID: <20250302024434.67ef4c90@jic23-huawei>

On Mon, 24 Feb 2025 08:14:23 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 23/02/2025 18:28, Jonathan Cameron wrote:
> > On Wed, 19 Feb 2025 14:30:43 +0200
> > Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> >   
> >> The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
> >> an automatic measurement mode, with an alarm interrupt for out-of-window
> >> measurements. The window is configurable for each channel.
> >>
> >> The I2C protocol for manual start of the measurement and data reading is
> >> somewhat peculiar. It requires the master to do clock stretching after
> >> sending the I2C slave-address until the slave has captured the data.
> >> Needless to say this is not well suopported by the I2C controllers.
> >>
> >> Thus the driver does not support the BD79124's manual measurement mode
> >> but implements the measurements using automatic measurement mode relying
> >> on the BD79124's ability of storing latest measurements into register.
> >>
> >> The driver does also support configuring the threshold events for
> >> detecting the out-of-window events.
> >>
> >> The BD79124 keeps asserting IRQ for as long as the measured voltage is
> >> out of the configured window. Thus the driver masks the received event
> >> for a fixed duration (1 second) when an event is handled. This prevents
> >> the user-space from choking on the events
> >>
> >> The ADC input pins can be also configured as general purpose outputs.
> >> Those pins which don't have corresponding ADC channel node in the
> >> device-tree will be controllable as GPO.
> >>
> >> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>  
> > Hi Matti,
> > 
> > Some fairly superficial review follows. I'm travelling for next few weeks
> > so not sure when I'll get time to take a more thorough look.  
> 
> Yeah, unfortunately people are allowed to have other life beyond the 
> ROHM drivers :D
> Enjoy your journey(s) ;)

So far so good.  Hi from Shenzhen.  Obligatory pilgrimage to SEG market
done ;)

> >> +	/* Set no channels to be manually measured */
> >> +	ret = regmap_write(data->map, BD79124_REG_MANUAL_CHANNELS, 0x0);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	/* Set the measurement interval to 0.75 mS */
> >> +	regval = FIELD_PREP(BD79124_MASK_AUTO_INTERVAL, BD79124_INTERVAL_075);
> >> +	ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
> >> +			BD79124_MASK_AUTO_INTERVAL, regval);  
> > 
> > Where it doesn't make any other difference, align after (
> > 
> > If you are going shorter, single tab only.  
> 
> Single tab only? You mean like:
> 
> ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
> 	BD79124_MASK_AUTO_INTERVAL, regval);
> 
> Do you prefer that even if the variable holding the return value was 
> longer than 8 chars? To me it looks odd if arguments on the next line 
> begin earlier than the function on previous line:
> 
> longvariable = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
> 	BD79124_MASK_AUTO_INTERVAL, regval);
> 
> (Just ensuring I understood your preference).
It's hard to come up with an absolute policy / preference on this but
whilst I agree it looks a bit odd, I think it's easier to say one
tab as 'default' choice.  Obviously if it's really hideous for some
reason feel free to do something else ;)

Jonathan


From jic23 at kernel.org  Sat Mar  1 19:20:54 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:20:54 +0000
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <9180ff11-888b-453d-9617-4b3a0fb38d91@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
	<0de7b0ac-eca5-49ba-b1b3-f249655f3646@baylibre.com>
	<1b308a10-9622-47f9-b489-bd969fbdfc34@gmail.com>
	<6f6e6550-5246-476f-9168-5e24151ab165@baylibre.com>
	<9180ff11-888b-453d-9617-4b3a0fb38d91@gmail.com>
Message-ID: <20250302032054.1fb8a011@jic23-huawei>

On Thu, 27 Feb 2025 09:46:06 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 26/02/2025 18:10, David Lechner wrote:
> > On 2/26/25 12:28 AM, Matti Vaittinen wrote:  
> >> Hi David,
> >>
> >> Thanks for taking a look at this :)
> >>
> >> On 26/02/2025 02:26, David Lechner wrote:  
> >>> On 2/24/25 12:33 PM, Matti Vaittinen wrote:  
> 
> ...
> 
> >>  
> >>> Similarly, on several drivers we added recently that make use of adc.yaml
> >>> (adi,ad7380, adi,ad4695) we wrote the bindings with the intention that
> >>> if a channel was wired in the default configuration, then you would just
> >>> omit the channel node for that input pin. Therefore, this helper couldn't
> >>> be used by these drivers since we always have a fixed number of channels
> >>> used in the driver regardless of if there are explicit channel nodes in
> >>> the devicetree or not.  
> >>
> >> I think this works with the ICs where channels, indeed, always are there. But this is not the case with _all_ ICs. And in order to keep the consistency I'd actually required that if channels are listed in the DT, then _all_ the channels must be listed. Else it becomes less straightforward for people to understand how many channels there are based on the device tree. I believe this was also proposed by Jonathan during the v1 review:
> >>  
> >>>> Hmm. That'd mean the ADC channels _must_ be defined in DT in order to be
> >>>> usable(?) Well, if this is the usual way, then it should be well known
> >>>> by users. Thanks.  

So there is some history here that complicates things.

1) Originally we always provided all channels.  Easy case :)
2) Along came SoC ADC users who were unhappy with this not so much because
   of the case Matti hit where the channel can be something else but more
   because it's not unusual to either not wire up some pins on an SoC
   or there are multiple packages that we don't otherwise distinguish
   (as no software differences really) in which some internal pins never
   reach the ones on the package.   Various solutions initially existed
   for this (you can find things like xxx,channels properties in some bindings.)
3) Then along came devices where we wanted per channel config.
   There were some 'interesting' bindings for that as well for a while but
   eventually we decided on channel nodes when needed.  Those always allowed
   drivers to supply extra channels that didn't have nodes though (that's
   a driver /binding choice and motivated somewhat by whether the unwired
   pin thing matters - there are ADC package variants where this happens
   but it is rare unlike for SoCs where it seems to be common).
   From this discussion it occurs to me that we maybe want to make sure
   that binding docs state what is expected here clearly.  If there is
   a concept of a 'default' for missing channel nodes then we need to say
   what it is.  Property defaults will give us most of that but don't cover
   everything.
4) Now we had channel nodes we can also use them for (2).  In those cases
   on a device specific case we allow for channels that don't have nodes
   to be hidden.   There is often a fallback for this which is more about
   how bindings evolved (sure they shouldn't evolve but they do unfortunately).
   In those cases, no channel nodes == all channel nodes with default settings.


> >>>
> >>> Yes. We basically have two types of binding wrt to channels.
> >>> 1) Always there - no explicit binding, but also no way to describe
> >>>  ??? anything specific about the channels.
> >>> 2) Subnode per channel with stuff from adc.yaml and anything device
> >>>  ??? specific.? Only channels that that have a node are enabled.
> >>>  
> > 
> > Hmm... does that mean we implemented it wrong on ad7380 and ad4695?  
> 
> I believe this is a question to Jonathan. With my ADC-driver experience 
> I am not the person to answer this :)
> 
> _If_ I commented something to this, I would say that: "I believe, this 
> question is a good example of why providing helpers is so powerful. In 
> my experience, when we provide helpers, then there will be a 'de facto' 
> way of doing things, which improves consistency". But as I feel I'm on 
> the verge of stepping on someones toes (and I am really the novice on 
> this area), I won't say that comment out loud.

Problem is always 'history'.  We already have a bunch of drivers
doing what the parts David called out do.  The bindings are clear and
ultimately it is a bit device specific to whether missing nodes logically
should default to default parameters or be hidden. In some cases there are
natural defaults, in others not even close as we have fully flexible
MUXes in front of differential ADCs and can in theory configure far more
combinations than we even have pins for.

So today the situation is we have all the options in tree and we aren't
really in a position to drop any of them:

a) custom bindings to configure channels - lots of these :(
b) everything on if no channel nodes.  Maybe everything on always.
c) channel nodes necessary for a channel to exist.

If I were starting all this again we'd probably reduce the options but
too late now :(

Only thing I'd request is if a binding uses channel nodes at all.
It should be possible to provide all nodes - whether or not some are
just the defaults.  That way we can advise writers of bindings to
provide all the channels they want to use.  The other cases then
become a case of whether they get more channels than expected, but
never that some they want aren't there!  A binding that didn't do
this wouldn't be wrong, it would just mean the writer read the binding
doc more carefully and knows what is expected for this device rather
than more generally.

There are some 'interesting' is it broken ABI backwards compatibility
questions when we retrofit channel nodes into a binding.  In those cases
we can't hide non specified nodes as it would mean channels disappear that
in an earlier kernel were present.  In theory that should never be a
problem but not all userspace code is going to be sufficient careful
to not be disrupted by channel number changes.  Even this I think we
broke once or twice because of cases like the one Matti has where they
are multipurpose pins on some chip variant we didn't know about when
the driver was written.

Jonathan

> 
> >>> There are a few drivers that for historical reasons support both
> >>> options with 'no channels' meaning 'all channels'.  
> >>
> >> https://lore.kernel.org/all/20250201162631.2eab9a9a at jic23-huawei/
> >>  
> >>> In my experience, the only time we don't populate all available channels
> >>> on an ADC, even if not used, is in cases like differential chips where
> >>> any two inputs can be mixed and matched to form a channel. Some of these,
> >>> like adi,ad7173-8 would have 100s or 1000s of channels if we tried to
> >>> include all possible channels. In those cases, we make an exception and
> >>> use a dynamic number of channels based on the devicetree. But for chips
> >>> that have less than 20 total possible channels or so we've always
> >>> provided all possible channels to userspace. It makes writing userspace
> >>> software for a specific chip easier if we can always assume that chip
> >>> has the same number of channels.  
> >>
> >> In any exception to this rule of describing all channels in DT should just avoid using these helpers and do things as they're done now. No one is forced to use them. But I am not really sure why would you not describe all the channels in the device-tree for ICs with less than 20 channels? I'd assume that if the channels are unconditionally usable in the hardware, then they should be in DT as well(?)  
> > 
> > I devicetree, I think the tendency is to be less verbose and only add
> > properties/nodes when there is something that is not the usual case.
> > Default values are chosen to be the most usual case so we don't have
> > to write so much in the .dts.  
> 
> On the other hand, I've received comments from the DTS people to expose 
> all HW blocks in the bindings. AFAIR, for example, marking 
> power-supplies as 'optional' in bindings is frowned upon, because they 
> are in the HW whether the SW needs to control them or not. Hence I think 
> marking either all or no channels in dt should be the way to go - but my 
> thinking is not done based on the years of experience on ADCs!

Even for power supplies there is a difference between the binding doc
saying they are there and what we do if they aren't (which is assume
a stub regulator representing an non controllable / unknowable power supply
is sufficient).    Also for power supplies there isn't really a 'default'
to use so it doesn't really work as a comparison.

Hindsight is a wonderful thing.  I'm not sure on what policy we should have
gone for, but now we are kind of stuck with this slightly messy situation.

Helper wise if it expands usefulness we may want a bool parameter to say
if we skip the missing or not + make sure a max expected channel is provided
(might already be - I didn't check!)

Jonathan

> 
> >>>> Add couple of helper functions which can be used to retrieve the channel
> >>>> information from the device node.
> >>>>
> >>>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>>>  
> >>
> >> Yours,
> >>  ????-- Matti  
> >   
> 



From jic23 at kernel.org  Sat Mar  1 19:27:13 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:27:13 +0000
Subject: [PATCH v4 07/10] iio: adc: ti-ads7924: Respect device tree
 config
In-Reply-To: <d391b012-0a8e-40ca-af56-ca73b3fd853b@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<20dd0e4ea72fe39b90b611f9c08dbd4bc1d5217f.1740421248.git.mazziesaccount@gmail.com>
	<f0d0f114-3953-46b5-b9f6-9b35537e6f8e@baylibre.com>
	<d391b012-0a8e-40ca-af56-ca73b3fd853b@gmail.com>
Message-ID: <20250302032713.1c834448@jic23-huawei>

On Wed, 26 Feb 2025 08:39:11 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 26/02/2025 02:09, David Lechner wrote:
> > On 2/24/25 12:34 PM, Matti Vaittinen wrote:  
> >> The ti-ads7924 driver ignores the device-tree ADC channel specification
> >> and always exposes all 4 channels to users whether they are present in
> >> the device-tree or not. Additionally, the "reg" values in the channel
> >> nodes are ignored, although an error is printed if they are out of range.
> >>
> >> Register only the channels described in the device-tree, and use the reg
> >> property as a channel ID.
> >>
> >> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>
> >> ---
> >> Revision history:
> >> v3 => v4:
> >>   - Adapt to 'drop diff-channel support' changes to ADC-helpers
> >>   - select ADC helpers in the Kconfig
> >> v2 => v3: New patch
> >>
> >> Please note that this is potentially breaking existing users if they
> >> have wrong values in the device-tree. I believe the device-tree should
> >> ideally be respected, and if it says device X has only one channel, then
> >> we should believe it and not register 4. Well, we don't live in the
> >> ideal world, so even though I believe this is TheRightThingToDo - it may
> >> cause havoc because correct device-tree has not been required from the
> >> day 1. So, please review and test and apply at your own risk :)  
> > 
> > The DT bindings on this one are a little weird. Usually, if we don't
> > use any extra properties from adc.yaml, we leave out the channels. In
> > this case it does seem kind of like the original intention was to work
> > like you are suggesting, but hard to say since the driver wasn't actually
> > implemented that way. I would be more inclined to actually not make the
> > breaking change here and instead relax the bindings to make channel nodes
> > optional and just have the driver ignore the channel nodes by dropping
> > the ads7924_get_channels_config() function completely. This would make
> > the driver simpler instead of more complex like this patch does.  
> 
> I have no strong opinion on this. I see this driver says 'Supported' in 
> MAINTAINERS. Maybe Hugo is able to provide some insight?
> 
This seems to be ABI breakage.  Never something we can take if there is
a significant chance of anyone noticing.  Here it looks like risk
is too high.

Anyhow, as discussed there has never been a clear statement on what default
is and whether the channels should be presented or not. It's always
been binding dependent, but it seems not as explicitly stated as it should
have been.  

Maybe there is some DT binding magic we can do to close this ambiguity but
I'm not sure what it is.  If not documentation may be the only way.


> >> As a side note, this might warrant a fixes tag but the adc-helper -stuff
> >> is hardly worth to be backported... (And I've already exceeded my time
> >> budget with this series - hence I'll leave crafting backportable fix to
> >> TI people ;) )
> >>
> >> This has only been compile tested! All testing is highly appreciated.
> >> ---  
> > 
> > ...
> >   
> >> -static int ads7924_get_channels_config(struct device *dev)
> >> +static int ads7924_get_channels_config(struct iio_dev *indio_dev,
> >> +				       struct device *dev)  
> > 
> > Could get dev from indio_dev->dev.parent and keep only one parameter
> > to this function.
> >   
> >>   {
> >> -	struct fwnode_handle *node;
> >> -	int num_channels = 0;
> >> +	struct iio_chan_spec *chan_array;
> >> +	int num_channels = 0, i;  
> > 
> > Don't need initialization here.
> >   
> >> +	static const char * const datasheet_names[] = {
> >> +		"AIN0", "AIN1", "AIN2", "AIN3"
> >> +	};  
> 
> Thanks for the review David! I do agree with the comments to the code.
> 
> Yours,
> 	-- Matti
> 
> 



From jic23 at kernel.org  Sat Mar  1 19:35:07 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:35:07 +0000
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
Message-ID: <20250302033507.7c166743@jic23-huawei>

On Mon, 24 Feb 2025 20:33:16 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
> 
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
I think it's worth exploring if we can tweak this slightly to make
that something a driver specifies.  Either skip the unspecified or
fill them with default values depending on a parameter.

Would make this code cover the existing cases better. 
Might be a little fiddly as we'd want to maintain ordering so
the code would need to index slightly differently. I've not tried it
so maybe not worth it for now.


> 
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> 
> ---
> Revision history:
> v3 => v4:
>  - Drop diff-channel support
>  - Drop iio_adc_device_channels_by_property()
>  - Add IIO_DEVICE namespace
>  - Move industrialio-adc.o to top of the Makefile
>  - Some styling as suggested by Andy
>  - Re-consider included headers
> v2 => v3: Mostly based on review comments by Jonathan
>  - Support differential and single-ended channels
>  - Rename iio_adc_device_get_channels() as
>    iio_adc_device_channels_by_property()
>  - Improve spelling
>  - Drop support for cases where DT comes from parent device's node
>  - Decrease loop indent by reverting node name check conditions
>  - Don't set 'chan->indexed' by number of channels to keep the
>    interface consistent no matter how many channels are connected.
>  - Fix ID range check and related comment
> RFC v1 => v2:
>  - New patch
> 
> iio: adc: helper: drop headers
> ---
>  drivers/iio/adc/Kconfig            |  3 +
>  drivers/iio/adc/Makefile           |  2 +
>  drivers/iio/adc/industrialio-adc.c | 89 ++++++++++++++++++++++++++++++
>  include/linux/iio/adc-helpers.h    | 22 ++++++++
>  4 files changed, 116 insertions(+)
>  create mode 100644 drivers/iio/adc/industrialio-adc.c
>  create mode 100644 include/linux/iio/adc-helpers.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 849c90203071..37b70a65da6f 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -6,6 +6,9 @@
>  
>  menu "Analog to digital converters"
>  
> +config IIO_ADC_HELPER
> +	tristate
> +
>  config AB8500_GPADC
>  	bool "ST-Ericsson AB8500 GPADC driver"
>  	depends on AB8500_CORE && REGULATOR_AB8500
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index ee19afba62b7..1c410f483029 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -3,6 +3,8 @@
>  # Makefile for IIO ADC drivers
>  #
>  
> +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
> +
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
>  obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
> new file mode 100644
> index 000000000000..d8e9e6825d2b
> --- /dev/null
> +++ b/drivers/iio/adc/industrialio-adc.c
> @@ -0,0 +1,89 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Helpers for parsing common ADC information from a firmware node.
> + *
> + * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include <linux/types.h>
> +
> +#include <linux/iio/adc-helpers.h>
> +#include <linux/iio/iio.h>
> +
> +int iio_adc_device_num_channels(struct device *dev)
> +{
> +	return device_get_child_node_count_named(dev, "channel");
> +}
> +EXPORT_SYMBOL_GPL(iio_adc_device_num_channels);

Maybe one to promote to a static inline in the header and avoid need for
the export given it is very simple.

> +
> +/**
> + * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
> + *
> + * Scan the device node for single-ended ADC channel information. Channel ID is
> + * expected to be found from the "reg" property. Allocate and populate the
> + * iio_chan_spec structure corresponding to channels that are found. The memory
> + * for iio_chan_spec structure will be freed upon device detach.
> + *
> + * @dev:		Pointer to the ADC device.
> + * @template:		Template iio_chan_spec from which the fields of all
> + *			found and allocated channels are initialized.
> + * @max_chan_id:	Maximum value of a channel ID. Use -1 if no checking
> + *			is required.
> + * @cs:			Location where pointer to allocated iio_chan_spec
> + *			should be stored.
> + *
> + * Return:	Number of found channels on succes. Negative value to indicate
> + *		failure.
> + */
> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> +				const struct iio_chan_spec *template,
> +				int max_chan_id,
> +				struct iio_chan_spec **cs)
> +{
> +	struct iio_chan_spec *chan_array, *chan;
> +	int num_chan = 0, ret;
> +
> +	num_chan = iio_adc_device_num_channels(dev);
> +	if (num_chan < 1)
> +		return num_chan;
> +
> +	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
> +				  GFP_KERNEL);
> +	if (!chan_array)
> +		return -ENOMEM;
> +
> +	chan = &chan_array[0];
> +
> +	device_for_each_child_node_scoped(dev, child) {
> +		u32 ch;
> +
> +		if (!fwnode_name_eq(child, "channel"))
> +			continue;
> +
> +		ret = fwnode_property_read_u32(child, "reg", &ch);
> +		if (ret)
> +			return ret;
> +
> +		if (max_chan_id != -1)
> +			if (ch > max_chan_id)
> +				return -ERANGE;

Might as well combine.
		if (max_chan_id != -1 && ch > max_chan_id)
			return -ERANGE; 
> +
> +		*chan = *template;
> +		chan->channel = ch;
> +		chan++;
> +	}
> +
> +	*cs = chan_array;
> +
> +	return num_chan;
> +}
> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
> +MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");



From jic23 at kernel.org  Sat Mar  1 19:40:42 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:40:42 +0000
Subject: [PATCH v4 04/10] iio: adc: rzg2l_adc: Use adc-helpers
In-Reply-To: <5658fbdd886cc7ada278a42c63a140bc14d1277d.1740421248.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<5658fbdd886cc7ada278a42c63a140bc14d1277d.1740421248.git.mazziesaccount@gmail.com>
Message-ID: <20250302034042.59d83f53@jic23-huawei>

On Mon, 24 Feb 2025 20:33:29 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
> drivers avoid open-coding the for_each_node -loop for getting the
> channel IDs. The helper provides standard way to detect the ADC channel
> nodes (by the node name), and a standard way to convert the "reg",
> "diff-channels", "single-channel" and the "common-mode-channel" to
> channel identification numbers used in the struct iio_chan_spec.

Needs an update to reflecting naming and functionality simplifications.

> Furthermore, the helper checks the ID is in range of 0 ... num-channels.
> 
> The original driver treated all found child nodes as channel nodes. The
> new helper requires channel nodes to be named channel[@N]. This should
> help avoid problems with devices which may contain also other but ADC
> child nodes. Quick grep from arch/* with the rzg2l_adc's compatible
> string didn't reveal any in-tree .dts with channel nodes named
> othervice. Also, same grep shows all the .dts seem to have channel IDs
otherwise

(othervice does sound cool though ;)

> between 0..num of channels.
> 
> Use the new helper.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> 
> ---
> Revision history:
> v3 => v4:
>  - Adapt to 'drop diff-channel support' changes to ADC-helpers
>  - select ADC helpers in the Kconfig
>  - Rebased to 6.14-rc3 => channel type can no longer come from the
>    template.
> 
> v2 => v3:
>  - New patch
> 
> I picked the rzg2l_adc in this series because it has a straightforward
> approach for populating the struct iio_chan_spec. Only other member
> in the stuct besides the .channel, which can't use a 'template' -data,
> is the .datasheet_name. This makes the rzg2l_adc well suited for example
> user of this new helper. I hope this patch helps to evaluate whether these
> helpers are worth the hassle.
This doesn't seem to match driver. It is messing with channel type.

> 
> The change is compile tested only!! Testing before applying is highly
> appreciated (as always!).
> ---
>  drivers/iio/adc/Kconfig     |  1 +
>  drivers/iio/adc/rzg2l_adc.c | 38 +++++++++++++++++--------------------
>  2 files changed, 18 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 37b70a65da6f..e4933de0c366 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -1222,6 +1222,7 @@ config RICHTEK_RTQ6056
>  config RZG2L_ADC
>  	tristate "Renesas RZ/G2L ADC driver"
>  	depends on ARCH_RZG2L || COMPILE_TEST
> +	select IIO_ADC_HELPER
>  	help
>  	  Say yes here to build support for the ADC found in Renesas
>  	  RZ/G2L family.
> diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c
> index 883c167c0670..51c87b1bdc98 100644
> --- a/drivers/iio/adc/rzg2l_adc.c
> +++ b/drivers/iio/adc/rzg2l_adc.c
> @@ -11,6 +11,7 @@
>  #include <linux/cleanup.h>
>  #include <linux/completion.h>
>  #include <linux/delay.h>
> +#include <linux/iio/adc-helpers.h>
>  #include <linux/iio/iio.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
> @@ -324,21 +325,30 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>  
> +static const struct iio_chan_spec rzg2l_adc_chan_template = {
> +	.indexed = 1,
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +};
> +
>  static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc)
>  {
>  	const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
>  	struct iio_chan_spec *chan_array;
>  	struct rzg2l_adc_data *data;
> -	unsigned int channel;
>  	int num_channels;
> -	int ret;
>  	u8 i;
>  
>  	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
>  	if (!data)
>  		return -ENOMEM;
>  
> -	num_channels = device_get_child_node_count(&pdev->dev);
> +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(&pdev->dev,
> +						&rzg2l_adc_chan_template,
> +						hw_params->num_channels - 1,
> +						&chan_array);
> +	if (num_channels < 0)
> +		return num_channels;
> +
>  	if (!num_channels)
>  		return dev_err_probe(&pdev->dev, -ENODEV, "no channel children\n");
>  
> @@ -346,26 +356,11 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l
>  		return dev_err_probe(&pdev->dev, -EINVAL,
>  				     "num of channel children out of range\n");
>  
> -	chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array),
> -				  GFP_KERNEL);
> -	if (!chan_array)
> -		return -ENOMEM;
> -
> -	i = 0;
> -	device_for_each_child_node_scoped(&pdev->dev, fwnode) {
> -		ret = fwnode_property_read_u32(fwnode, "reg", &channel);
> -		if (ret)
> -			return ret;
> -
> -		if (channel >= hw_params->num_channels)
> -			return -EINVAL;
> +	for (i = 0; i < num_channels; i++) {
> +		int channel = chan_array[i].channel;
>  
> -		chan_array[i].type = rzg2l_adc_channels[channel].type;
> -		chan_array[i].indexed = 1;
> -		chan_array[i].channel = channel;
> -		chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
>  		chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name;
> -		i++;
> +		chan_array[i].type = rzg2l_adc_channels[channel].type;
>  	}
>  
>  	data->num_channels = num_channels;
> @@ -626,3 +621,4 @@ module_platform_driver(rzg2l_adc_driver);
>  MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>");
>  MODULE_DESCRIPTION("Renesas RZ/G2L ADC driver");
>  MODULE_LICENSE("GPL v2");
> +MODULE_IMPORT_NS("IIO_DRIVER");



From jic23 at kernel.org  Sat Mar  1 19:42:21 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:42:21 +0000
Subject: [PATCH v4 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <a3c579cc96b35cae04f6090d98c7672c48fa8347.1740421248.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<a3c579cc96b35cae04f6090d98c7672c48fa8347.1740421248.git.mazziesaccount@gmail.com>
Message-ID: <20250302034221.3c70c95f@jic23-huawei>

On Mon, 24 Feb 2025 20:33:46 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
> drivers avoid open-coding the for_each_node -loop for getting the
> channel IDs. The helper provides standard way to detect the ADC channel
> nodes (by the node name), and a standard way to convert the "reg",
> "diff-channels", "single-channel" and the "common-mode-channel" to
> channel identification numbers used in the struct iio_chan_spec.
> Furthermore, the helper checks the ID is in range of 0 ... num-channels.
Needs update.

> 
> The original driver treated all found child nodes as channel nodes. The
> new helper requires channel nodes to be named channel[@N]. This should
> help avoid problems with devices which may contain also other but ADC
> child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
> string didn't reveal any in-tree .dts with channel nodes named
> othervice. Also, same grep shows all the in-tree .dts seem to have
> channel IDs between 0..num of channels.
> 
> Use the new helper.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> 
Otherwise looks good to me.

Jonathan


From jic23 at kernel.org  Sat Mar  1 19:46:49 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:46:49 +0000
Subject: [PATCH v4 06/10] iio: adc: ti-ads7924 Drop unnecessary function
 parameters
In-Reply-To: <38d39befcca110132fd4349c87fcb5d7ff51a2c8.1740421248.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<38d39befcca110132fd4349c87fcb5d7ff51a2c8.1740421248.git.mazziesaccount@gmail.com>
Message-ID: <20250302034649.2d9ec2a4@jic23-huawei>

On Mon, 24 Feb 2025 20:34:01 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> Device pointer is the only variable which is used by the
> ads7924_get_channels_config() and which is declared outside this
> function. Still, the function gets the iio_device and i2c_client as
> parameters. The sole caller of this function (probe) already has the
> device pointer which it can directly pass to the function.
> 
> Simplify code by passing the device pointer directly as a parameter
> instead of digging it from the iio_device's private data.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Looking again at this function it doesn't seem to be doing anything
useful at all.  It checks the channel nodes are in range, but
does nothing with that data. I'd just drop it entirely.

Ah. I see David suggested the same.

We can't really 'fix' what this was perhaps intended to do now
as what it does has become ABI :(


Jonathan

> 
> ---
> This commit is compile-tested only! All further testing is appreciated.
> ---
>  drivers/iio/adc/ti-ads7924.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c
> index 66b54c0d75aa..b1f745f75dbe 100644
> --- a/drivers/iio/adc/ti-ads7924.c
> +++ b/drivers/iio/adc/ti-ads7924.c
> @@ -251,11 +251,8 @@ static const struct iio_info ads7924_info = {
>  	.read_raw = ads7924_read_raw,
>  };
>  
> -static int ads7924_get_channels_config(struct i2c_client *client,
> -				       struct iio_dev *indio_dev)
> +static int ads7924_get_channels_config(struct device *dev)
>  {
> -	struct ads7924_data *priv = iio_priv(indio_dev);
> -	struct device *dev = priv->dev;
>  	struct fwnode_handle *node;
>  	int num_channels = 0;
>  
> @@ -380,7 +377,7 @@ static int ads7924_probe(struct i2c_client *client)
>  	indio_dev->num_channels = ARRAY_SIZE(ads7924_channels);
>  	indio_dev->info = &ads7924_info;
>  
> -	ret = ads7924_get_channels_config(client, indio_dev);
> +	ret = ads7924_get_channels_config(dev);
>  	if (ret < 0)
>  		return dev_err_probe(dev, ret,
>  				     "failed to get channels configuration\n");



From jic23 at kernel.org  Sat Mar  1 19:48:07 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 03:48:07 +0000
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
Message-ID: <20250302034807.680a3971@jic23-huawei>

On Mon, 24 Feb 2025 20:33:16 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
> 
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
> 
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> 
> ---
> Revision history:
> v3 => v4:
>  - Drop diff-channel support
>  - Drop iio_adc_device_channels_by_property()
>  - Add IIO_DEVICE namespace
>  - Move industrialio-adc.o to top of the Makefile
>  - Some styling as suggested by Andy
>  - Re-consider included headers
> v2 => v3: Mostly based on review comments by Jonathan
>  - Support differential and single-ended channels
>  - Rename iio_adc_device_get_channels() as
>    iio_adc_device_channels_by_property()
>  - Improve spelling
>  - Drop support for cases where DT comes from parent device's node
>  - Decrease loop indent by reverting node name check conditions
>  - Don't set 'chan->indexed' by number of channels to keep the
>    interface consistent no matter how many channels are connected.
>  - Fix ID range check and related comment
> RFC v1 => v2:
>  - New patch
> 
> iio: adc: helper: drop headers
> ---
>  drivers/iio/adc/Kconfig            |  3 +
>  drivers/iio/adc/Makefile           |  2 +
>  drivers/iio/adc/industrialio-adc.c | 89 ++++++++++++++++++++++++++++++
>  include/linux/iio/adc-helpers.h    | 22 ++++++++
>  4 files changed, 116 insertions(+)
>  create mode 100644 drivers/iio/adc/industrialio-adc.c
>  create mode 100644 include/linux/iio/adc-helpers.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 849c90203071..37b70a65da6f 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -6,6 +6,9 @@
>  
>  menu "Analog to digital converters"
>  
> +config IIO_ADC_HELPER
> +	tristate
> +
>  config AB8500_GPADC
>  	bool "ST-Ericsson AB8500 GPADC driver"
>  	depends on AB8500_CORE && REGULATOR_AB8500
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index ee19afba62b7..1c410f483029 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -3,6 +3,8 @@
>  # Makefile for IIO ADC drivers
>  #
>  
> +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
> +
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
>  obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
> new file mode 100644
> index 000000000000..d8e9e6825d2b
> --- /dev/null
> +++ b/drivers/iio/adc/industrialio-adc.c
> @@ -0,0 +1,89 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Helpers for parsing common ADC information from a firmware node.
> + *
> + * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include <linux/types.h>
> +
> +#include <linux/iio/adc-helpers.h>
> +#include <linux/iio/iio.h>
> +
> +int iio_adc_device_num_channels(struct device *dev)
> +{
> +	return device_get_child_node_count_named(dev, "channel");
> +}
> +EXPORT_SYMBOL_GPL(iio_adc_device_num_channels);
Just noticed, this isn't namespaces which is a bit odd.  I'd drop
the export anyway in favour of static inline but if you don't match
the namespace of the next one.


From jic23 at kernel.org  Sat Mar  1 20:10:46 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 2 Mar 2025 04:10:46 +0000
Subject: [PATCH v4 08/10] iio: adc: Support ROHM BD79124 ADC
In-Reply-To: <4d1bf5df8f3b0f760422b6b67fcc8245ebf520e0.1740421249.git.mazziesaccount@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<4d1bf5df8f3b0f760422b6b67fcc8245ebf520e0.1740421249.git.mazziesaccount@gmail.com>
Message-ID: <20250302041046.7fde3c68@jic23-huawei>

On Mon, 24 Feb 2025 20:34:30 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
> an automatic measurement mode, with an alarm interrupt for out-of-window
> measurements. The window is configurable for each channel.
> 
> The I2C protocol for manual start of the measurement and data reading is
> somewhat peculiar. It requires the master to do clock stretching after
> sending the I2C slave-address until the slave has captured the data.
> Needless to say this is not well suopported by the I2C controllers.
> 
> Thus the driver does not support the BD79124's manual measurement mode
> but implements the measurements using automatic measurement mode relying
> on the BD79124's ability of storing latest measurements into register.
> 
> The driver does also support configuring the threshold events for
> detecting the out-of-window events.
> 
> The BD79124 keeps asserting IRQ for as long as the measured voltage is
> out of the configured window. Thus the driver masks the received event
> for a fixed duration (1 second) when an event is handled. This prevents
> the user-space from choking on the events
> 
> The ADC input pins can be also configured as general purpose outputs.
> Those pins which don't have corresponding ADC channel node in the
> device-tree will be controllable as GPO.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Some minor stuff inline.

Thanks,

Jonathan

> +
> +#define BD79124_REG_SYSTEM_STATUS	0x0
> +#define BD79124_REG_GEN_CFG		0x01
> +#define BD79124_REG_OPMODE_CFG		0x04
> +#define BD79124_REG_PINCFG		0x05
> +#define BD79124_REG_GPO_VAL		0x0B
> +#define BD79124_REG_SEQUENCE_CFG	0x10
> +#define BD79124_REG_MANUAL_CHANNELS	0x11
> +#define BD79124_REG_AUTO_CHANNELS	0x12
> +#define BD79124_REG_ALERT_CH_SEL	0x14
> +#define BD79124_REG_EVENT_FLAG		0x18
> +#define BD79124_REG_EVENT_FLAG_HI	0x1a
> +#define BD79124_REG_EVENT_FLAG_LO	0x1c
> +#define BD79124_REG_HYSTERESIS_CH0	0x20
> +#define BD79124_REG_EVENTCOUNT_CH0	0x22
> +#define BD79124_REG_RECENT_CH0_LSB	0xa0
> +#define BD79124_REG_RECENT_CH7_MSB	0xaf
> +
> +#define BD79124_ADC_BITS 12
> +#define BD79124_MASK_CONV_MODE GENMASK(6, 5)
> +#define BD79124_MASK_AUTO_INTERVAL GENMASK(1, 0)
> +#define BD79124_CONV_MODE_MANSEQ 0
> +#define BD79124_CONV_MODE_AUTO 1
> +#define BD79124_INTERVAL_075 0

Can we make these units in these explicit?
#define BD79124_INTERVAL_MS_0_75 
maybe?  Nice to avoid need for comments on what the units are where
you use these.

> +#define BD79124_INTERVAL_150 1
> +#define BD79124_INTERVAL_300 2
> +#define BD79124_INTERVAL_600 3

> +
> +static int bd79124_enable_event(struct bd79124_data *data,
> +		enum iio_event_direction dir, unsigned int channel)
> +{
> +	int dir_bit = BIT(dir);
> +	int reg;
> +	u16 *limit;
> +	int ret;
> +
> +	guard(mutex)(&data->mutex);
> +	/* Set channel to be measured */
> +	ret = bd79124_start_measurement(data, channel);
> +	if (ret)
> +		return ret;
> +
> +	data->alarm_monitored[channel] |= dir_bit;
> +
> +	/* Add the channel to the list of monitored channels */
> +	ret = regmap_set_bits(data->map, BD79124_REG_ALERT_CH_SEL,
> +			      BIT(channel));
> +	if (ret)
> +		return ret;
> +
> +	if (dir == IIO_EV_DIR_RISING) {
> +		limit = &data->alarm_f_limit[channel];
> +		reg = BD79124_GET_HIGH_LIMIT_REG(channel);
> +	} else {
> +		limit = &data->alarm_f_limit[channel];
> +		reg = BD79124_GET_LOW_LIMIT_REG(channel);
> +	}
> +	/* Don't write the new limit to the hardware if we are in the
> +	 * rate-limit period. The timer which re-enables the event will set
> +	 * the limit.
> +	 */
/*
 * Don't

Check for other cases of this...


> +static void bd79124_re_enable_hi(struct bd79124_data *data, unsigned int channel)
> +{
> +	int ret, evbit = BIT(IIO_EV_DIR_RISING);
> +
> +	if (!(data->alarm_suppressed[channel] & evbit))
> +		return;
> +
> +	data->alarm_suppressed[channel] &= (~evbit);

No brackets around the ~evbit.
Check for other cases of this.
Otherwise we'll get some script written 'cleanup'.


> +
> +	if (!(data->alarm_monitored[channel] & evbit))
> +		return;
> +
> +	ret = bd79124_write_int_to_reg(data, BD79124_GET_HIGH_LIMIT_REG(channel),
> +				       data->alarm_r_limit[channel]);
> +	if (ret)
> +		dev_warn(data->dev, "High limit enabling failed for channel%d\n",
> +			 channel);
> +}
> +
> +static void bd79124_alm_enable_worker(struct work_struct *work)
> +{
> +	int i;
> +	struct bd79124_data *data = container_of(work, struct bd79124_data,
> +						 alm_enable_work.work);
> +
> +	guard(mutex)(&data->mutex);
> +	/*
> +	 * We should not re-enable the event if user has disabled it while
> +	 * rate-limiting was enabled.
> +	 */

Is this comment suggesting something that isn't done or referring to specific
code?  I think it wants to be in the function above where the decision is made.

> +	for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) {
> +		bd79124_re_enable_hi(data, i);
> +		bd79124_re_enable_lo(data, i);
> +	}
> +}
> +

> +

> +static irqreturn_t bd79124_event_handler(int irq, void *priv)
> +{
> +	int ret, i_hi, i_lo, i;
> +	struct iio_dev *iio_dev = priv;
> +	struct bd79124_data *data = iio_priv(iio_dev);
> +
> +	/*
> +	 * Return IRQ_NONE if bailing-out without acking. This allows the IRQ
> +	 * subsystem to disable the offending IRQ line if we get a hardware
> +	 * problem. This behaviour has saved my poor bottom a few times in the
> +	 * past as, instead of getting unusably unresponsive, the system has
> +	 * spilled out the magic words "...nobody cared".
> +	 */
> +	ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_HI, &i_hi);
> +	if (ret)
> +		return IRQ_NONE;
> +
> +	ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_LO, &i_lo);
> +	if (ret)
> +		return IRQ_NONE;
> +
> +	if (!i_lo && !i_hi)
> +		return IRQ_NONE;
> +
> +	for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) {
> +		u64 ecode;
> +
> +		if (BIT(i) & i_hi) {
> +			ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,

> +					IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING);
Align this to less tabs as per discussion on previous version.

> +
> +
> +struct bd79124_reg_init {
> +	int reg;
> +	int val;
> +};

Not used any more.

> +
> +static int bd79124_chan_init(struct bd79124_data *data, int channel)
> +{
> +	int ret;
> +
> +	ret = regmap_write(data->map, BD79124_GET_HIGH_LIMIT_REG(channel), 4095);
> +	if (ret)
> +		return ret;
> +
> +	return regmap_write(data->map, BD79124_GET_LOW_LIMIT_REG(channel), 0);
> +}

> +
> +static int bd79124_init_mux(struct bd79124_data *data, int gpio_pins)
> +{
> +	return regmap_write(data->map, BD79124_REG_PINCFG, gpio_pins);

Maybe squash this inline.  Doesn't seem to add a lot to have the helper.

> +}
> +
> +static int bd79124_hw_init(struct bd79124_data *data, int gpio_pins)
> +{
...

> +
> +	/* Set the measurement interval to 0.75 mS */

This lead me to comment on defines.  I'd rather code was fully self
documenting and remove the comment if we can.  Makes for less chance of it
becoming out of sync over time.

> +	regval = FIELD_PREP(BD79124_MASK_AUTO_INTERVAL, BD79124_INTERVAL_075);
> +	ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG,
> +				 BD79124_MASK_AUTO_INTERVAL, regval);
> +	if (ret)
> +		return ret;






From lkp at intel.com  Sat Mar  1 21:53:23 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 2 Mar 2025 13:53:23 +0800
Subject: [rockchip:v6.15-clk/next 10/10]
 drivers/clk/rockchip/clk-rk3562.c:1081:31: error: incomplete definition of
 type 'struct platform_device'
Message-ID: <202503021302.FjsycBI2-lkp@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git v6.15-clk/next
head:   36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a
commit: 36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a [10/10] clk: rockchip: Add clock controller for the RK3562
config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20250302/202503021302.FjsycBI2-lkp at intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503021302.FjsycBI2-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503021302.FjsycBI2-lkp at intel.com/

All error/warnings (new ones prefixed by >>):

>> drivers/clk/rockchip/clk-rk3562.c:1079:36: warning: declaration of 'struct platform_device' will not be visible outside of this function [-Wvisibility]
    1079 | static int clk_rk3562_probe(struct platform_device *pdev)
         |                                    ^
>> drivers/clk/rockchip/clk-rk3562.c:1081:31: error: incomplete definition of type 'struct platform_device'
    1081 |         struct device_node *np = pdev->dev.of_node;
         |                                  ~~~~^
   drivers/clk/rockchip/clk-rk3562.c:1079:36: note: forward declaration of 'struct platform_device'
    1079 | static int clk_rk3562_probe(struct platform_device *pdev)
         |                                    ^
   drivers/clk/rockchip/clk-rk3562.c:1085:55: error: incomplete definition of type 'struct platform_device'
    1085 |         match = of_match_device(clk_rk3562_match_table, &pdev->dev);
         |                                                          ~~~~^
   drivers/clk/rockchip/clk-rk3562.c:1079:36: note: forward declaration of 'struct platform_device'
    1079 | static int clk_rk3562_probe(struct platform_device *pdev)
         |                                    ^
>> drivers/clk/rockchip/clk-rk3562.c:1096:31: error: variable has incomplete type 'struct platform_driver'
    1096 | static struct platform_driver clk_rk3562_driver = {
         |                               ^
   drivers/clk/rockchip/clk-rk3562.c:1096:15: note: forward declaration of 'struct platform_driver'
    1096 | static struct platform_driver clk_rk3562_driver = {
         |               ^
>> drivers/clk/rockchip/clk-rk3562.c:1104:1: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int]
    1104 | module_platform_driver(clk_rk3562_driver);
         | ^
         | int
>> drivers/clk/rockchip/clk-rk3562.c:1104:24: error: a parameter list without types is only allowed in a function definition
    1104 | module_platform_driver(clk_rk3562_driver);
         |                        ^
   1 warning and 5 errors generated.


vim +1081 drivers/clk/rockchip/clk-rk3562.c

  1078	
> 1079	static int clk_rk3562_probe(struct platform_device *pdev)
  1080	{
> 1081		struct device_node *np = pdev->dev.of_node;
  1082		const struct of_device_id *match;
  1083		const struct clk_rk3562_inits *init_data;
  1084	
  1085		match = of_match_device(clk_rk3562_match_table, &pdev->dev);
  1086		if (!match || !match->data)
  1087			return -EINVAL;
  1088	
  1089		init_data = match->data;
  1090		if (init_data->inits)
  1091			init_data->inits(np);
  1092	
  1093		return 0;
  1094	}
  1095	
> 1096	static struct platform_driver clk_rk3562_driver = {
  1097		.probe		= clk_rk3562_probe,
  1098		.driver		= {
  1099			.name	= "clk-rk3562",
  1100			.of_match_table = clk_rk3562_match_table,
  1101			.suppress_bind_attrs = true,
  1102		},
  1103	};
> 1104	module_platform_driver(clk_rk3562_driver);
  1105	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From damon.ding at rock-chips.com  Sat Mar  1 23:15:30 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Sun, 2 Mar 2025 15:15:30 +0800
Subject: [PATCH v7 04/15] drm/bridge: analogix_dp: Remove the unnecessary
 calls to clk_disable_unprepare() during probing
In-Reply-To: <CAD=FV=X7iWOyAvdfRDyFA9kdr+utU_aAaJ5F7nAsaHp2fMQgVw@mail.gmail.com>
References: <20250224081325.96724-1-damon.ding@rock-chips.com>
 <20250224081325.96724-5-damon.ding@rock-chips.com>
 <CAD=FV=X7iWOyAvdfRDyFA9kdr+utU_aAaJ5F7nAsaHp2fMQgVw@mail.gmail.com>
Message-ID: <f835a852-24b8-4279-8e4b-42517d694493@rock-chips.com>

Hi Doug,

On 2025/2/25 9:40, Doug Anderson wrote:
> Hi,
> 
> On Mon, Feb 24, 2025 at 12:14?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>>
>> With the commit f37952339cc2 ("drm/bridge: analogix_dp: handle clock via
>> runtime PM"), the PM operations can help enable/disable the clock. The
>> err_disable_clk label and clk_disable_unprepare() operations are no
>> longer necessary because the analogix_dp_resume() will not be called
>> during probing.
>>
>> Fixes: f37952339cc2 ("drm/bridge: analogix_dp: handle clock via runtime PM")
> 
> When possible "Fixes" should be pushed to the start of your series so
> it's obvious they have no dependencies when being picked to stable
> kernels. That should be possible here.
> 
>> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
>> ---
>>   .../gpu/drm/bridge/analogix/analogix_dp_core.c | 18 +++++-------------
>>   1 file changed, 5 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index e23af674d91c..d9dafb038e7a 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -1608,10 +1608,8 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
>>          res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>
>>          dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
> 
> There is a context conflict when I apply to drm-misc-next because of
> commit 43c00fb1a518 ("drm/bridge: analogix_dp: Use
> devm_platform_ioremap_resource()"). You probably should rebase and
> re-apply.
> 
> Aside from the context conflict, this looks great to me:
> 
> Suggested-by: Douglas Anderson <dianders at chromium.org>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> 
> 

After rebasing, I found the conflict. I will move this patch to a 
separate series and ensure it has no dependencies.

Best regards
Damon



From andyshrk at 163.com  Sat Mar  1 23:56:42 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sun, 2 Mar 2025 15:56:42 +0800 (CST)
Subject: [PATCH v1 1/1] arm64: dts: rockchip: Add USB-C support to
 ROCK 5B
In-Reply-To: <njeivdzwyy6qxome77asapmi3a3l34mpauk366f6zgpt2mvorz@ra77f5vjd5lf>
References: <20241210163615.120594-1-sebastian.reichel@collabora.com>
 <12e97e18.367e.19551b6aea2.Coremail.andyshrk@163.com>
 <njeivdzwyy6qxome77asapmi3a3l34mpauk366f6zgpt2mvorz@ra77f5vjd5lf>
Message-ID: <551de5ae.17d2.19555db7b4f.Coremail.andyshrk@163.com>



Hello Sebastian,

At 2025-03-02 06:42:51, "Sebastian Reichel" <sebastian.reichel at collabora.com> wrote:
>Hello Andy,
>
>On Sat, Mar 01, 2025 at 08:38:01PM +0800, Andy Yan wrote:
>> At 2024-12-11 00:36:01, "Sebastian Reichel" <sebastian.reichel at collabora.com> wrote:
>> >Add hardware description for the USB-C port in the Radxa Rock 5 Model B.
>> >This describes the OHCI, EHCI and XHCI USB parts, but not yet the
>> >DisplayPort AltMode (bindings are not yet upstream).
>> >
>> >The fusb302 node is marked with status "fail", since the board is usually
>> >powered through the USB-C port. Handling of errors can result in hard
>> >resets, which removed the bus power for some time resulting in a board
>> >reset.
>> >
>> >The main problem is that devices are supposed to interact with the
>> >power-supply within 5 seconds after the plug event according to the
>> >USB PD specification. This is more or less impossible to achieve when
>> >the kernel is the first software communicating with the power-supply.
>> >
>> >Recent U-Boot (v2025.01) will start doing USB-PD communication, which
>> >solves this issue. Upstream U-Boot doing USB-PD communication will also
>> >set the fusb302 node status to "okay". That way booting a kernel with
>> >the updated DT on an old U-Boot avoids a reset loop.
>> 
>> Do you have any plans to continue working on this patch?
>> I've been working on enabling the DP Alt Mode output recently
>> and think the Rock 5b is a good starting point?
>
>This is still on my radar. I recently send an updates U-Boot series
>with some TCPM improvements:
>
>https://lore.kernel.org/u-boot/20250226184506.64114-1-sebastian.reichel at collabora.com/
>
>Even with that there are more issues resulting in hard resets
>happening in some circumstances (if they are happening depends a lot
>on the specific powre supply being used). I'm still looking for the
>root cause of these. It's also hard to tell when it is a good time
>to apply this patch. Some people will probably see a regression due
>to using power-supplies diverging too far from the standard :/

Yes,  I have observed similar issues on Rock5B with a USB-C hub as well.
Even after upgrading U-Boot to version v2025.01 and applying your new tcpm patch, 
the system still requires three to four automatic resets before successful boot-up once?

Thank you for your clarification and  thank you for  your work.


>
>Greetings,
>
>-- Sebastian
>
>>      
>> >
>> >Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
>> >---
>> > .../boot/dts/rockchip/rk3588-rock-5b.dts      | 121 ++++++++++++++++++
>> > 1 file changed, 121 insertions(+)
>> >
>> >diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>> >index d597112f1d5b..cb5990df6ccb 100644
>> >--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>> >+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
>> >@@ -5,6 +5,7 @@
>> > #include <dt-bindings/gpio/gpio.h>
>> > #include <dt-bindings/leds/common.h>
>> > #include <dt-bindings/soc/rockchip,vop2.h>
>> >+#include <dt-bindings/usb/pd.h>
>> > #include "rk3588.dtsi"
>> > 
>> > / {
>> >@@ -84,6 +85,15 @@ rfkill-bt {
>> > 		shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
>> > 	};
>> > 
>> >+	vcc12v_dcin: regulator-vcc12v-dcin {
>> >+		compatible = "regulator-fixed";
>> >+		regulator-name = "vcc12v_dcin";
>> >+		regulator-always-on;
>> >+		regulator-boot-on;
>> >+		regulator-min-microvolt = <12000000>;
>> >+		regulator-max-microvolt = <12000000>;
>> >+	};
>> >+
>> > 	vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
>> > 		compatible = "regulator-fixed";
>> > 		enable-active-high;
>> >@@ -142,6 +152,7 @@ vcc5v0_sys: regulator-vcc5v0-sys {
>> > 		regulator-boot-on;
>> > 		regulator-min-microvolt = <5000000>;
>> > 		regulator-max-microvolt = <5000000>;
>> >+		vin-supply = <&vcc12v_dcin>;
>> > 	};
>> > 
>> > 	vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
>> >@@ -264,6 +275,67 @@ regulator-state-mem {
>> > 	};
>> > };
>> > 
>> >+&i2c4 {
>> >+	pinctrl-names = "default";
>> >+	pinctrl-0 = <&i2c4m1_xfer>;
>> >+	status = "okay";
>> >+
>> >+	usbc0: usb-typec at 22 {
>> >+		compatible = "fcs,fusb302";
>> >+		reg = <0x22>;
>> >+		interrupt-parent = <&gpio3>;
>> >+		interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
>> >+		pinctrl-names = "default";
>> >+		pinctrl-0 = <&usbc0_int>;
>> >+		vbus-supply = <&vcc12v_dcin>;
>> >+		/*
>> >+		 * When the board is starting to send power-delivery messages
>> >+		 * too late (5 seconds according to the specification), the
>> >+		 * power-supply reacts with a hard-reset. That removes the
>> >+		 * power from VBUS for some time, which resets te whole board.
>> >+		 */
>> >+		status = "fail";
>> >+
>> >+		usb_con: connector {
>> >+			compatible = "usb-c-connector";
>> >+			label = "USB-C";
>> >+			data-role = "dual";
>> >+			power-role = "sink";
>> >+			try-power-role = "sink";
>> >+			op-sink-microwatt = <1000000>;
>> >+			sink-pdos =
>> >+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>,
>> >+				<PDO_VAR(5000, 20000, 5000)>;
>> >+
>> >+			ports {
>> >+				#address-cells = <1>;
>> >+				#size-cells = <0>;
>> >+
>> >+				port at 0 {
>> >+					reg = <0>;
>> >+					usbc0_role_sw: endpoint {
>> >+						remote-endpoint = <&dwc3_0_role_switch>;
>> >+					};
>> >+				};
>> >+
>> >+				port at 1 {
>> >+					reg = <1>;
>> >+					usbc0_orien_sw: endpoint {
>> >+						remote-endpoint = <&usbdp_phy0_orientation_switch>;
>> >+					};
>> >+				};
>> >+
>> >+				port at 2 {
>> >+					reg = <2>;
>> >+					dp_altmode_mux: endpoint {
>> >+						remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
>> >+					};
>> >+				};
>> >+			};
>> >+		};
>> >+	};
>> >+};
>> >+
>> > &i2c6 {
>> > 	status = "okay";
>> > 
>> >@@ -423,6 +495,10 @@ usb {
>> > 		vcc5v0_host_en: vcc5v0-host-en {
>> > 			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
>> > 		};
>> >+
>> >+		usbc0_int: usbc0-int {
>> >+			rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
>> >+		};
>> > 	};
>> > };
>> > 
>> >@@ -835,6 +911,14 @@ &uart2 {
>> > 	status = "okay";
>> > };
>> > 
>> >+&u2phy0 {
>> >+	status = "okay";
>> >+};
>> >+
>> >+&u2phy0_otg {
>> >+	status = "okay";
>> >+};
>> >+
>> > &u2phy1 {
>> > 	status = "okay";
>> > };
>> >@@ -866,6 +950,29 @@ &usbdp_phy1 {
>> > 	status = "okay";
>> > };
>> > 
>> >+&usbdp_phy0 {
>> >+	mode-switch;
>> >+	orientation-switch;
>> >+	sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
>> >+	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
>> >+	status = "okay";
>> >+
>> >+	port {
>> >+		#address-cells = <1>;
>> >+		#size-cells = <0>;
>> >+
>> >+		usbdp_phy0_orientation_switch: endpoint at 0 {
>> >+			reg = <0>;
>> >+			remote-endpoint = <&usbc0_orien_sw>;
>> >+		};
>> >+
>> >+		usbdp_phy0_dp_altmode_mux: endpoint at 1 {
>> >+			reg = <1>;
>> >+			remote-endpoint = <&dp_altmode_mux>;
>> >+		};
>> >+	};
>> >+};
>> >+
>> > &usb_host0_ehci {
>> > 	status = "okay";
>> > };
>> >@@ -874,6 +981,20 @@ &usb_host0_ohci {
>> > 	status = "okay";
>> > };
>> > 
>> >+&usb_host0_xhci {
>> >+	usb-role-switch;
>> >+	status = "okay";
>> >+
>> >+	port {
>> >+		#address-cells = <1>;
>> >+		#size-cells = <0>;
>> >+
>> >+		dwc3_0_role_switch: endpoint {
>> >+			remote-endpoint = <&usbc0_role_sw>;
>> >+		};
>> >+	};
>> >+};
>> >+
>> > &usb_host1_ehci {
>> > 	status = "okay";
>> > };
>> >-- 
>> >2.45.2
>> >

From akihiko.odaki at daynix.com  Sun Mar  2 00:12:54 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sun, 02 Mar 2025 17:12:54 +0900
Subject: [PATCH] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Message-ID: <20250302-pmc-v1-1-caff989093dc@daynix.com>

Reset the current perf event when setting the vPMU counter (vPMC)
registers (PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change
corresponding to commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

Fix this by calling kvm_pmu_set_counter_value(), which resests the
current perf event as well.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/sys_regs.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 42791971f75887796afab905cc12f49fead39e10..1de990edc6a3e9be2a05a711621bb1bcbeac236a 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 	return 0;
 }
 
+static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+			  u64 val)
+{
+	u64 idx;
+
+	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+		/* PMCCNTR_EL0 */
+		idx = ARMV8_PMU_CYCLE_IDX;
+	else
+		/* PMEVCNTRn_EL0 */
+		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+	kvm_pmu_set_counter_value(vcpu, idx, val);
+	return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      const struct sys_reg_desc *r)
@@ -1328,6 +1344,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 #define PMU_PMEVCNTR_EL0(n)						\
 	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
 	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
+	  .set_user = set_pmu_evcntr,					\
 	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -2682,7 +2699,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  .access = access_pmceid, .reset = NULL },
 	{ PMU_SYS_REG(PMCCNTR_EL0),
 	  .access = access_pmu_evcntr, .reset = reset_unknown,
-	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
+	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr, .set_user = set_pmu_evcntr },
 	{ PMU_SYS_REG(PMXEVTYPER_EL0),
 	  .access = access_pmu_evtyper, .reset = NULL },
 	{ PMU_SYS_REG(PMXEVCNTR_EL0),

---
base-commit: 97eab90817fc214843ca8ccd4cdf68b8115ed424
change-id: 20250302-pmc-b90a86af945c

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From maz at kernel.org  Sun Mar  2 00:41:18 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun,  2 Mar 2025 08:41:18 +0000
Subject: [PATCH 0/2] KVM: arm64: PSCI relay fixes
In-Reply-To: <20250227180526.1204723-1-mark.rutland@arm.com>
References: <20250227180526.1204723-1-mark.rutland@arm.com>
Message-ID: <174090487063.2316303.3603727860925384915.b4-ty@kernel.org>

On Thu, 27 Feb 2025 18:05:24 +0000, Mark Rutland wrote:
> These patches fix some missing initialization in the PSCI relay code
> which can result in host kernel crashes shortly after entering the cold
> entry points used by PSCI CPU_ON, CPU_SUSPEND, and SYSTEM_SUSPEND.
> 
> The SCTLR_EL1 issue was originally reported by Leo Yan and debugged by
> Ahmed Genidi. While looking at Ahmed's patch I spotted a more general
> issue with E2H, so I've fixed that up with patch 1, and I've tweaked his
> patch accordingly. Any errors there are my fault.
> 
> [...]

Applied to fixes, thanks!

[1/2] KVM: arm64: Initialize HCR_EL2.E2H early
      commit: 7a68b55ff39b0a1638acb1694c185d49f6077a0d
[2/2] KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu()
      commit: 3855a7b91d42ebf3513b7ccffc44807274978b3d

Cheers,

	M.
-- 
Without deviation from the norm, progress is not possible.




From ivo.ivanov.ivanov1 at gmail.com  Sun Mar  2 01:16:38 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Sun, 2 Mar 2025 11:16:38 +0200
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
Message-ID: <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>

On 2/25/25 10:11, Krzysztof Kozlowski wrote:
> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>
>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>> ---
>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>  1 file changed, 76 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>> You have undocumented dependencies which prevent merging this file.
>>> First, dependencies have to be clearly expressed.
>> They are, in the cover letter.
> Where? I read it twice. Dependencies is the most important thing and
> should scream at beginning of the cover letter, so if you bury them
> somewhere deep it also would not matter - just like they were missing.
>
>>> Second, you should
>>> rather decouple the code from header dependencies, otherwise this cannot
>>> be merged for current release (just use clocks with long names, without IDs).
>> Sure
>
>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>> new file mode 100644
>>>> index 000000000..7d879ec8b
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>> @@ -0,0 +1,76 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Exynos2200 USB controller PHY
>>>> +
>>>> +maintainers:
>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>> +
>>>> +description:
>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>> It's not (I think). There's a few reasons I've decided to make this separate
>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>
>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
> USBDRD phy does not provide UTMI and PIPE on its own either if you look
> at diagram - they call it phy controller.

Ughm. What? So in most exynos cases, there's a combination of multiple phys?

>
>> for them, and all that is needed from it is to disable HWACG, assert/
>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>> initialization can be done and USB2 works. If the USBCON phy is not set
>> up before the eUSB2 one, the device hangs, so there is definitely a
>> dependancy between them. For PIPE3 we'd need to control the pipe3
>> attaching/deattaching and then initialize the synopsys USBDP combophy.
> Does it mean there is no USB DRD phy controller as before?
>
> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.

So...

DWC3 -> USBDRD (USBCON) -> PHYs?

...with usbdrd controller connecting and controlling the USB2 and USB3
phys, as well as dual role mode? Well, where is the DRD part in the exynos5
driver?

I guess it does perfectly fit the job of a usbdrd controller then (if it
even deals with DRD). But then again,? this brings up two questions:
1. Should this driver even be named exynos2200-usbcon and not, for
example, exynos2200-usbdrd?
2. Are the exynos5-usbdrd phys really only USBDRD, or do they implement
USB speed functionality? What is the UTMI/PIPE3 setup for then?

ps: dealing with this without any documentations sucks.

Best regards,
Ivaylo

>
>
>> 2. With the way it's modelled, we need to parse phandles from eUSB2 and
>> USBDP to the controller. Adding that to the usbdrd driver would be...
>> weird. It makes more sense to model it as a separate driver, because
>> it functions in a different way.
> Just to be clear: we don't talk about drivers here.
>
>
> Best regards,
> Krzysztof



From rppt at kernel.org  Sun Mar  2 01:52:22 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Sun, 2 Mar 2025 11:52:22 +0200
Subject: [PATCH v4 00/14] kexec: introduce Kexec HandOver (KHO)
In-Reply-To: <mafs0h64dk6wf.fsf@kernel.org>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <mafs0cyf4ii4k.fsf@kernel.org>
 <Z8Iah6FgrhSzApwf@kernel.org>
 <mafs0h64dk6wf.fsf@kernel.org>
Message-ID: <Z8QqVrqvR_p_CaUV@kernel.org>

On Fri, Feb 28, 2025 at 11:04:48PM +0000, Pratyush Yadav wrote:
> On Fri, Feb 28 2025, Mike Rapoport wrote:
> > On Wed, Feb 26, 2025 at 08:08:27PM +0000, Pratyush Yadav wrote:
> >> On Thu, Feb 06 2025, Mike Rapoport wrote:
> >> 
> >> > From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> >> >
> >> > Hi,
> >> >
> >> > This a next version of Alex's "kexec: Allow preservation of ftrace buffers"
> >> > series (https://lore.kernel.org/all/20240117144704.602-1-graf at amazon.com),
> >> > just to make things simpler instead of ftrace we decided to preserve
> >> > "reserve_mem" regions.
> >> [...]
> >> 
> >> I applied the patches on top of v6.14-rc1 and tried them out on an x86
> >> qemu machine . When I do a plain KHO activate and kexec, I get the below
> >> errors on boot. This causes networking to fail on the VM. The errors are
> >> consistent and happen every kexec-reboot, though fairly late in boot
> >> after systemd tries to bring up network. The same setup has worked fine
> >> with Alex's v3 of KHO patches.
> >> 
> >> Do you see anything obvious that might cause this? I can try to debug
> >> this tomorrow, but if it rings any loud bells it would be nice to know.
> >
> > Thanks for the report!
> > It didn't ring any bells, but after I've found the issue and a
> > fast-and-dirty fix.
> >
> > The scratch areas are allocated from high addresses and there is no scratch
> > memory to satisfy memblock_alloc_low() in swiotb, so second kernel produces
> > a couple of 
> >
> > software IO TLB: swiotlb_memblock_alloc: Failed to allocate 67108864 bytes for tlb structure
> 
> I also did some digging today and ended up finding the same thing out
> but it seems you got there before me :-)
> 
> >
> > and without those buffers e1000 can't dma :(
> >
> > A quick fix would be to add another scratch area in the lower memory
> > (below). I'll work on a better fix.
> 
> I have already written a less-quick fix (patch pasted below) so I
> suppose we can use that to review the idea instead. It adds a dedicated
> scratch area for lowmem, similar to your patch, and adds some tracking
> to calculate the size.
> 
> I am not sure if the size estimation is completely right though, since
> it is possible that allocations that don't _need_ to be in lowmem end up
> being there, causing the scratch area to be too big (or perhaps even
> causing allocation failures if the scale is big enough). Maybe we would
> be better off tracking lowmem allocation requests separately?

Normally memblock allocates top-down, so if there is enough memory
allocations that do not limit memory ranges won't end up in lowmem.
And on systems with smaller memory (e.g 4G and less) we'd anyway have
scratch areas in lowmem.

Yet, there is an issue with swiotlb_init() and estimation of the size for
lowmem scratch area we need to address. swiotlb_init() is called from
mem_init() and the memory it allocates won't be accounted by the time of
kho_memory_init().

I've been meaning to pull out common parts of mem_init() from arch-specific
code to mm_init for a while now, maybe the time has come :)
 
> ----- 8< -----
> From d60aeb2c4a1c0eea05e1a13b48b268d6192a615e Mon Sep 17 00:00:00 2001
> From: Pratyush Yadav <ptyadav at amazon.de>
> Date: Fri, 28 Feb 2025 22:36:06 +0000
> Subject: [PATCH] KHO: always have a lowmem scratch region
> 
> During initialization, some callers need to allocate low memory from
> memblock. One such caller is swiotlb_memblock_alloc() on x86. The global
> and per-node scratch regions are allocated without any constraints on
> the range. This can lead to having no scratch region in lowmem. If that
> happens, the lowmem allocations can fail, leading to failures during
> boot or later down the line.
> 
> Always ensure there is some scratch memory available in low memory by
> having a separate scratch area for it, along with the global and
> per-node ones, and allow specifying its size via the command line.
> 
> To more accurately guess suitable scratch sizes, add
> memblock_reserved_kern_lowmem_size() and
> memblock_reserved_kern_highmem_size() which calculate how much memory
> was allocated in low and high memory, along with some helper functions
> to calculate scratch sizes.
> 
> Signed-off-by: Pratyush Yadav <ptyadav at amazon.de>
> ---
>  .../admin-guide/kernel-parameters.txt         |  9 +-
>  Documentation/kho/usage.rst                   | 10 +--
>  include/linux/memblock.h                      |  2 +
>  kernel/kexec_handover.c                       | 83 ++++++++++++++-----
>  mm/memblock.c                                 | 28 +++++++
>  5 files changed, 103 insertions(+), 29 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index ed656e2fb05ef..7c5afd45ad9dc 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -2705,7 +2705,7 @@
>  			"1" | "on" | "y" - kexec handover is enabled
>  
>  	kho_scratch=	[KEXEC,EARLY]
> -			Format: nn[KMG],mm[KMG] | nn%
> +			Format: ll[KMG],nn[KMG],mm[KMG] | nn%
>  			Defines the size of the KHO scratch region. The KHO
>  			scratch regions are physically contiguous memory
>  			ranges that can only be used for non-kernel
> @@ -2715,9 +2715,10 @@
>  			bootstrap itself.
>  
>  			It is possible to specify the exact amount of
> -			memory in the form of "nn[KMG],mm[KMG]" where the
> -			first parameter defines the size of a global
> -			scratch area and the second parameter defines the
> +			memory in the form of "ll[KMG],nn[KMG],mm[KMG]" where the
> +			first parameter defines the size of a low memory scratch
> +			area, the second parameter defines the size of a global
> +			scratch area and the third parameter defines the
>  			size of additional per-node scratch areas.
>  			The form "nn%" defines scale factor (in percents)
>  			of memory that was used during boot.
> diff --git a/Documentation/kho/usage.rst b/Documentation/kho/usage.rst
> index e7300fbb309c1..6a6011809795d 100644
> --- a/Documentation/kho/usage.rst
> +++ b/Documentation/kho/usage.rst
> @@ -19,11 +19,11 @@ at compile time. Every KHO producer may have its own config option that you
>  need to enable if you would like to preserve their respective state across
>  kexec.
>  
> -To use KHO, please boot the kernel with the ``kho=on`` command line
> -parameter. You may use ``kho_scratch`` parameter to define size of the
> -scratch regions. For example ``kho_scratch=512M,512M`` will reserve a 512
> -MiB for a global scratch region and 512 MiB per NUMA node scratch regions
> -on boot.
> +To use KHO, please boot the kernel with the ``kho=on`` command line parameter.
> +You may use ``kho_scratch`` parameter to define size of the scratch regions. For
> +example ``kho_scratch=128M,512M,512M`` will reserve a 128 MiB low memory scratch
> +region, a 512 MiB global scratch region and 512 MiB per NUMA node scratch
> +regions on boot.
>  
>  Perform a KHO kexec
>  -------------------
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 20887e199cdbd..9f5c5aec4b1d4 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -504,6 +504,8 @@ static inline __init_memblock bool memblock_bottom_up(void)
>  phys_addr_t memblock_phys_mem_size(void);
>  phys_addr_t memblock_reserved_size(void);
>  phys_addr_t memblock_reserved_kern_size(int nid);
> +phys_addr_t memblock_reserved_kern_lowmem_size(void);
> +phys_addr_t memblock_reserved_kern_highmem_size(void);
>  unsigned long memblock_estimated_nr_free_pages(void);
>  phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
> diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
> index c26753d613cbc..29eeed09ceb31 100644
> --- a/kernel/kexec_handover.c
> +++ b/kernel/kexec_handover.c
> @@ -547,20 +547,21 @@ late_initcall(kho_init);
>   *
>   * kho_scratch=N%
>   *
> - * It is also possible to explicitly define size for a global and per-node
> - * scratch areas:
> + * It is also possible to explicitly define size for a lowmem, a global and
> + * per-node scratch areas:
>   *
> - * kho_scratch=n[KMG],m[KMG]
> + * kho_scratch=l[KMG],n[KMG],m[KMG]
>   *
>   * The explicit size definition takes precedence over scale definition.
>   */
>  static unsigned int scratch_scale __initdata = 200;
>  static phys_addr_t scratch_size_global __initdata;
>  static phys_addr_t scratch_size_pernode __initdata;
> +static phys_addr_t scratch_size_lowmem __initdata;
>  
>  static int __init kho_parse_scratch_size(char *p)
>  {
> -	unsigned long size, size_pernode;
> +	unsigned long size, size_pernode, size_global;
>  	char *endptr, *oldp = p;
>  
>  	if (!p)
> @@ -578,15 +579,25 @@ static int __init kho_parse_scratch_size(char *p)
>  		if (*p != ',')
>  			return -EINVAL;
>  
> +		oldp = p;
> +		size_global = memparse(p + 1, &p);
> +		if (!size_global || p == oldp)
> +			return -EINVAL;
> +
> +		if (*p != ',')
> +			return -EINVAL;
> +
>  		size_pernode = memparse(p + 1, &p);
>  		if (!size_pernode)
>  			return -EINVAL;
>  
> -		scratch_size_global = size;
> +		scratch_size_lowmem = size;
> +		scratch_size_global = size_global;
>  		scratch_size_pernode = size_pernode;
>  		scratch_scale = 0;
>  
> -		pr_notice("scratch areas: global: %lluMB pernode: %lldMB\n",
> +		pr_notice("scratch areas: lowmem: %lluMB global: %lluMB pernode: %lldMB\n",
> +			  (u64)(scratch_size_lowmem >> 20),
>  			  (u64)(scratch_size_global >> 20),
>  			  (u64)(scratch_size_pernode >> 20));
>  	}
> @@ -595,18 +606,38 @@ static int __init kho_parse_scratch_size(char *p)
>  }
>  early_param("kho_scratch", kho_parse_scratch_size);
>  
> -static phys_addr_t __init scratch_size(int nid)
> +static phys_addr_t __init scratch_size_low(void)
> +{
> +	phys_addr_t size;
> +
> +	if (scratch_scale)
> +		size = memblock_reserved_kern_lowmem_size() * scratch_scale / 100;
> +	else
> +		size = scratch_size_lowmem;
> +
> +	return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
> +}
> +
> +static phys_addr_t __init scratch_size_high(void)
> +{
> +	phys_addr_t size;
> +
> +	if (scratch_scale)
> +		size = memblock_reserved_kern_highmem_size() * scratch_scale / 100;
> +	else
> +		size = scratch_size_global;
> +
> +	return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
> +}
> +
> +static phys_addr_t __init scratch_size_node(int nid)
>  {
>  	phys_addr_t size;
>  
> -	if (scratch_scale) {
> +	if (scratch_scale)
>  		size = memblock_reserved_kern_size(nid) * scratch_scale / 100;
> -	} else {
> -		if (numa_valid_node(nid))
> -			size = scratch_size_pernode;
> -		else
> -			size = scratch_size_global;
> -	}
> +	else
> +		size = scratch_size_pernode;
>  
>  	return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
>  }
> @@ -623,29 +654,41 @@ static phys_addr_t __init scratch_size(int nid)
>  static void kho_reserve_scratch(void)
>  {
>  	phys_addr_t addr, size;
> -	int nid, i = 1;
> +	int nid, i = 0;
>  
>  	if (!kho_enable)
>  		return;
>  
>  	/* FIXME: deal with node hot-plug/remove */
> -	kho_scratch_cnt = num_online_nodes() + 1;
> +	kho_scratch_cnt = num_online_nodes() + 2;
>  	size = kho_scratch_cnt * sizeof(*kho_scratch);
>  	kho_scratch = memblock_alloc(size, PAGE_SIZE);
>  	if (!kho_scratch)
>  		goto err_disable_kho;
>  
> -	/* reserve large contiguous area for allocations without nid */
> -	size = scratch_size(NUMA_NO_NODE);
> -	addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES);
> +	/* reserve area for lowmem allocations. */
> +	size = scratch_size_low();
> +	addr = memblock_phys_alloc_range(size, CMA_MIN_ALIGNMENT_BYTES, 0,
> +					 ARCH_LOW_ADDRESS_LIMIT);
>  	if (!addr)
>  		goto err_free_scratch_desc;
>  
>  	kho_scratch[0].addr = addr;
>  	kho_scratch[0].size = size;
> +	i++;
> +
> +	/* reserve large contiguous area for allocations without nid */
> +	size = scratch_size_high();
> +	addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES);
> +	if (!addr)
> +		goto err_free_scratch_areas;
> +
> +	kho_scratch[1].addr = addr;
> +	kho_scratch[1].size = size;
> +	i++;
>  
>  	for_each_online_node(nid) {
> -		size = scratch_size(nid);
> +		size = scratch_size_node(nid);
>  		addr = memblock_alloc_range_nid(size, CMA_MIN_ALIGNMENT_BYTES,
>  						0, MEMBLOCK_ALLOC_ACCESSIBLE,
>  						nid, true);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index fdb08b60efc17..da7abf5e5e504 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1837,6 +1837,34 @@ phys_addr_t __init_memblock memblock_reserved_size(void)
>  	return memblock.reserved.total_size;
>  }
>  
> +phys_addr_t __init_memblock memblock_reserved_kern_lowmem_size(void)
> +{
> +	struct memblock_region *r;
> +	phys_addr_t total = 0;
> +
> +	for_each_reserved_mem_region(r) {
> +		if ((r->flags & MEMBLOCK_RSRV_KERN) &&
> +		    (r->base + r->size <= ARCH_LOW_ADDRESS_LIMIT))
> +			total += r->size;
> +	}
> +
> +	return total;
> +}
> +
> +phys_addr_t __init_memblock memblock_reserved_kern_highmem_size(void)
> +{
> +	struct memblock_region *r;
> +	phys_addr_t total = 0;
> +
> +	for_each_reserved_mem_region(r) {
> +		if ((r->flags & MEMBLOCK_RSRV_KERN) &&
> +		    (r->base + r->size > ARCH_LOW_ADDRESS_LIMIT))
> +			total += r->size;
> +	}
> +
> +	return total;
> +}
> +
>  phys_addr_t __init_memblock memblock_reserved_kern_size(int nid)
>  {
>  	struct memblock_region *r;
> -- 
> Regards,
> Pratyush Yadav
> 

-- 
Sincerely yours,
Mike.


From chunkuang.hu at kernel.org  Sun Mar  2 02:34:33 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 18:34:33 +0800
Subject: [PATCH v7 01/43] dt-bindings: display: mediatek: dpi: Add MT8195
 and MT8188 compat
In-Reply-To: <20250217154836.108895-2-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-2-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_9GJ9FRLZVu3EguCKHipK7SfwtVKJtm2cjTSZPTMzz7MA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> Add compatibles for the Digital Parallel Interface (DPI) block
> found in the MT8195 and MT8188 SoCs: inside of the chip, this one
> is directly connected to the HDMI block.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  .../devicetree/bindings/display/mediatek/mediatek,dpi.yaml   | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> index 0f1e556dc8ef..5670715efa5c 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> @@ -27,6 +27,7 @@ properties:
>            - mediatek,mt8188-dp-intf
>            - mediatek,mt8192-dpi
>            - mediatek,mt8195-dp-intf
> +          - mediatek,mt8195-dpi
>        - items:
>            - enum:
>                - mediatek,mt6795-dpi
> @@ -35,6 +36,10 @@ properties:
>            - enum:
>                - mediatek,mt8365-dpi
>            - const: mediatek,mt8192-dpi
> +      - items:
> +          - enum:
> +              - mediatek,mt8188-dpi
> +          - const: mediatek,mt8195-dpi
>
>    reg:
>      maxItems: 1
> --
> 2.48.1
>


From andyshrk at 163.com  Sun Mar  2 02:34:22 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sun, 2 Mar 2025 18:34:22 +0800 (CST)
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
Message-ID: <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>



Hi Dmitry?
   Thank you for your review?
   Please also review my inline reply.
      
? 2025-03-02 02:14:19?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
>On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> The DW DP TX Controller is compliant with the DisplayPort Specification
>> Version 1.4 with the following features:
>> 
>> * DisplayPort 1.4a
>> * Main Link: 1/2/4 lanes
>> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> * AUX channel 1Mbps
>> * Single Stream Transport(SST)
>> * Multistream Transport (MST)
>> *?Type-C support (alternate mode)
>> * HDCP 2.2, HDCP 1.3
>> * Supports up to 8/10 bits per color component
>> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> * Pixel clock up to 594MHz
>> * I2S, SPDIF audio interface
>> 
>> Add library with common helpers to make it can be shared with
>> other SoC.
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> 
>> drm/bridge: cleanup
>
>Stray line?

Sorry, will be removed.

>
>> 
>> ---
>> 
>>  drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
>>  drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
>>  drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
>>  include/drm/bridge/dw_dp.h               |   19 +
>>  4 files changed, 2182 insertions(+)
>>  create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
>>  create mode 100644 include/drm/bridge/dw_dp.h
>> 
>> diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
>> index f3ab2f985f8c..2c5e532410de 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
>> +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
>> @@ -1,4 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>> +config DRM_DW_DP
>> +	tristate
>> +	select DRM_DISPLAY_HELPER
>> +	select DRM_DISPLAY_DP_HELPER
>> +	select DRM_KMS_HELPER
>> +	select REGMAP_MMIO
>> +
>>  config DRM_DW_HDMI
>>  	tristate
>>  	select DRM_DISPLAY_HDMI_HELPER
>> diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
>> index 9dc376d220ad..4dada44029ac 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/Makefile
>> +++ b/drivers/gpu/drm/bridge/synopsys/Makefile
>> @@ -1,4 +1,5 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>> +obj-$(CONFIG_DRM_DW_DP) += dw-dp.o
>>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>>  obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
>> new file mode 100644
>> index 000000000000..6ecbe9851369
>> --- /dev/null
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
>> @@ -0,0 +1,2155 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Synopsys DesignWare Cores DisplayPort Transmitter Controller
>> + *
>> + * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
>> + *
>> + * Author: Andy Yan <andy.yan at rock-chips.com>
>> + */
>> +#include <linux/bitfield.h>
>> +#include <linux/clk.h>
>> +#include <linux/component.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/irq.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_graph.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/reset.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/unaligned.h>
>> +
>> +#include <drm/bridge/dw_dp.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_bridge.h>
>> +#include <drm/drm_bridge_connector.h>
>> +#include <drm/display/drm_dp_helper.h>
>> +#include <drm/display/drm_hdmi_helper.h>
>> +#include <drm/drm_edid.h>
>> +#include <drm/drm_of.h>
>> +#include <drm/drm_print.h>
>> +#include <drm/drm_probe_helper.h>
>> +#include <drm/drm_simple_kms_helper.h>
>> +
>> +#include <uapi/linux/media-bus-format.h>
>> +
>> +#define DW_DP_VERSION_NUMBER			0x0000
>> +#define DW_DP_VERSION_TYPE			0x0004
>> +#define DW_DP_ID					0x0008
>> +
>> +#define DW_DP_CONFIG_REG1			0x0100
>> +#define DW_DP_CONFIG_REG2			0x0104
>> +#define DW_DP_CONFIG_REG3			0x0108
>> +
>> +#define DW_DP_CCTL				0x0200
>> +#define FORCE_HPD				BIT(4)
>> +#define DEFAULT_FAST_LINK_TRAIN_EN		BIT(2)
>> +#define ENHANCE_FRAMING_EN			BIT(1)
>> +#define SCRAMBLE_DIS				BIT(0)
>> +#define DW_DP_SOFT_RESET_CTRL			0x0204
>> +#define VIDEO_RESET				BIT(5)
>> +#define AUX_RESET				BIT(4)
>> +#define AUDIO_SAMPLER_RESET			BIT(3)
>> +#define HDCP_MODULE_RESET			BIT(2)
>> +#define PHY_SOFT_RESET				BIT(1)
>> +#define CONTROLLER_RESET			BIT(0)
>> +
>> +#define DW_DP_VSAMPLE_CTRL			0x0300
>> +#define PIXEL_MODE_SELECT			GENMASK(22, 21)
>> +#define VIDEO_MAPPING				GENMASK(20, 16)
>> +#define VIDEO_STREAM_ENABLE			BIT(5)
>> +
>> +#define DW_DP_VSAMPLE_STUFF_CTRL1		0x0304
>> +
>> +#define DW_DP_VSAMPLE_STUFF_CTRL2		0x0308
>> +
>> +#define DW_DP_VINPUT_POLARITY_CTRL		0x030c
>> +#define DE_IN_POLARITY				BIT(2)
>> +#define HSYNC_IN_POLARITY			BIT(1)
>> +#define VSYNC_IN_POLARITY			BIT(0)
>> +
>> +#define DW_DP_VIDEO_CONFIG1			0x0310
>> +#define HACTIVE					GENMASK(31, 16)
>> +#define HBLANK					GENMASK(15, 2)
>> +#define I_P					BIT(1)
>> +#define R_V_BLANK_IN_OSC			BIT(0)
>> +
>> +#define DW_DP_VIDEO_CONFIG2			0x0314
>> +#define VBLANK					GENMASK(31, 16)
>> +#define VACTIVE					GENMASK(15, 0)
>> +
>> +#define DW_DP_VIDEO_CONFIG3			0x0318
>> +#define H_SYNC_WIDTH				GENMASK(31, 16)
>> +#define H_FRONT_PORCH				GENMASK(15, 0)
>> +
>> +#define DW_DP_VIDEO_CONFIG4			0x031c
>> +#define V_SYNC_WIDTH				GENMASK(31, 16)
>> +#define V_FRONT_PORCH				GENMASK(15, 0)
>> +
>> +#define DW_DP_VIDEO_CONFIG5			0x0320
>> +#define INIT_THRESHOLD_HI			GENMASK(22, 21)
>> +#define AVERAGE_BYTES_PER_TU_FRAC		GENMASK(19, 16)
>> +#define INIT_THRESHOLD				GENMASK(13, 7)
>> +#define AVERAGE_BYTES_PER_TU			GENMASK(6, 0)
>> +
>> +#define DW_DP_VIDEO_MSA1				0x0324
>> +#define VSTART					GENMASK(31, 16)
>> +#define HSTART					GENMASK(15, 0)
>> +
>> +#define DW_DP_VIDEO_MSA2			0x0328
>> +#define MISC0					GENMASK(31, 24)
>> +
>> +#define DW_DP_VIDEO_MSA3			0x032c
>> +#define MISC1					GENMASK(31, 24)
>> +
>> +#define DW_DP_VIDEO_HBLANK_INTERVAL		0x0330
>> +#define HBLANK_INTERVAL_EN			BIT(16)
>> +#define HBLANK_INTERVAL				GENMASK(15, 0)
>> +
>> +#define DW_DP_AUD_CONFIG1			0x0400
>> +#define AUDIO_TIMESTAMP_VERSION_NUM		GENMASK(29, 24)
>> +#define AUDIO_PACKET_ID				GENMASK(23, 16)
>> +#define AUDIO_MUTE				BIT(15)
>> +#define NUM_CHANNELS				GENMASK(14, 12)
>> +#define HBR_MODE_ENABLE				BIT(10)
>> +#define AUDIO_DATA_WIDTH			GENMASK(9, 5)
>> +#define AUDIO_DATA_IN_EN			GENMASK(4, 1)
>> +#define AUDIO_INF_SELECT			BIT(0)
>> +
>> +#define DW_DP_SDP_VERTICAL_CTRL			0x0500
>> +#define EN_VERTICAL_SDP				BIT(2)
>> +#define EN_AUDIO_STREAM_SDP			BIT(1)
>> +#define EN_AUDIO_TIMESTAMP_SDP			BIT(0)
>> +#define DW_DP_SDP_HORIZONTAL_CTRL		0x0504
>> +#define EN_HORIZONTAL_SDP			BIT(2)
>> +#define DW_DP_SDP_STATUS_REGISTER		0x0508
>> +#define DW_DP_SDP_MANUAL_CTRL			0x050c
>> +#define DW_DP_SDP_STATUS_EN			0x0510
>> +
>> +#define DW_DP_SDP_REGISTER_BANK			0x0600
>> +#define SDP_REGS				GENMASK(31, 0)
>> +
>> +#define DW_DP_PHYIF_CTRL			0x0a00
>> +#define PHY_WIDTH				BIT(25)
>> +#define PHY_POWERDOWN				GENMASK(20, 17)
>> +#define PHY_BUSY				GENMASK(15, 12)
>> +#define SSC_DIS					BIT(16)
>> +#define XMIT_ENABLE				GENMASK(11, 8)
>> +#define PHY_LANES				GENMASK(7, 6)
>> +#define PHY_RATE				GENMASK(5, 4)
>> +#define TPS_SEL					GENMASK(3, 0)
>> +
>> +#define DW_DP_PHY_TX_EQ				0x0a04
>> +#define DW_DP_CUSTOMPAT0			0x0a08
>> +#define DW_DP_CUSTOMPAT1			0x0a0c
>> +#define DW_DP_CUSTOMPAT2			0x0a10
>> +#define DW_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	0x0a14
>> +#define DW_DP_PHYIF_PWRDOWN_CTRL		0x0a18
>> +
>> +#define DW_DP_AUX_CMD				0x0b00
>> +#define AUX_CMD_TYPE				GENMASK(31, 28)
>> +#define AUX_ADDR				GENMASK(27, 8)
>> +#define I2C_ADDR_ONLY				BIT(4)
>> +#define AUX_LEN_REQ				GENMASK(3, 0)
>> +
>> +#define DW_DP_AUX_STATUS			0x0b04
>> +#define AUX_TIMEOUT				BIT(17)
>> +#define AUX_BYTES_READ				GENMASK(23, 19)
>> +#define AUX_STATUS				GENMASK(7, 4)
>> +
>> +#define DW_DP_AUX_DATA0				0x0b08
>> +#define DW_DP_AUX_DATA1				0x0b0c
>> +#define DW_DP_AUX_DATA2				0x0b10
>> +#define DW_DP_AUX_DATA3				0x0b14
>> +
>> +#define DW_DP_GENERAL_INTERRUPT			0x0d00
>> +#define VIDEO_FIFO_OVERFLOW_STREAM0		BIT(6)
>> +#define AUDIO_FIFO_OVERFLOW_STREAM0		BIT(5)
>> +#define SDP_EVENT_STREAM0			BIT(4)
>> +#define AUX_CMD_INVALID				BIT(3)
>> +#define HDCP_EVENT				BIT(2)
>> +#define AUX_REPLY_EVENT				BIT(1)
>> +#define HPD_EVENT				BIT(0)
>> +
>> +#define DW_DP_GENERAL_INTERRUPT_ENABLE		0x0d04
>> +#define HDCP_EVENT_EN				BIT(2)
>> +#define AUX_REPLY_EVENT_EN			BIT(1)
>> +#define HPD_EVENT_EN				BIT(0)
>> +
>> +#define DW_DP_HPD_STATUS			0x0d08
>> +#define HPD_STATE				GENMASK(11, 9)
>> +#define HPD_STATUS				BIT(8)
>> +#define HPD_HOT_UNPLUG				BIT(2)
>> +#define HPD_HOT_PLUG				BIT(1)
>> +#define HPD_IRQ					BIT(0)
>> +
>> +#define DW_DP_HPD_INTERRUPT_ENABLE		0x0d0c
>> +#define HPD_UNPLUG_ERR_EN			BIT(3)
>> +#define HPD_UNPLUG_EN				BIT(2)
>> +#define HPD_PLUG_EN				BIT(1)
>> +#define HPD_IRQ_EN				BIT(0)
>> +
>> +#define DW_DP_HDCP_CFG				0x0e00
>> +#define DPCD12PLUS				BIT(7)
>> +#define CP_IRQ					BIT(6)
>> +#define BYPENCRYPTION				BIT(5)
>> +#define HDCP_LOCK				BIT(4)
>> +#define ENCRYPTIONDISABLE			BIT(3)
>> +#define ENABLE_HDCP_13				BIT(2)
>> +#define ENABLE_HDCP				BIT(1)
>> +
>> +#define DW_DP_HDCP_OBS				0x0e04
>> +#define HDCP22_RE_AUTHENTICATION_REQ		BIT(31)
>> +#define HDCP22_AUTHENTICATION_FAILED		BIT(30)
>> +#define HDCP22_AUTHENTICATION_SUCCESS		BIT(29)
>> +#define HDCP22_CAPABLE_SINK			BIT(28)
>> +#define HDCP22_SINK_CAP_CHECK_COMPLETE		BIT(27)
>> +#define HDCP22_STATE				GENMASK(26, 24)
>> +#define HDCP22_BOOTED				BIT(23)
>> +#define HDCP13_BSTATUS				GENMASK(22, 19)
>> +#define REPEATER				BIT(18)
>> +#define HDCP_CAPABLE				BIT(17)
>> +#define STATEE					GENMASK(16, 14)
>> +#define STATEOEG				GENMASK(13, 11)
>> +#define STATER					GENMASK(10, 8)
>> +#define STATEA					GENMASK(7, 4)
>> +#define SUBSTATEA				GENMASK(3, 1)
>> +#define HDCPENGAGED				BIT(0)
>> +
>> +#define DW_DP_HDCP_APIINTCLR			0x0e08
>> +#define DW_DP_HDCP_APIINTSTAT			0x0e0c
>> +#define DW_DP_HDCP_APIINTMSK			0x0e10
>> +#define HDCP22_GPIOINT				BIT(8)
>> +#define HDCP_ENGAGED				BIT(7)
>> +#define HDCP_FAILED				BIT(6)
>> +#define KSVSHA1CALCDONEINT			BIT(5)
>> +#define AUXRESPNACK7TIMES			BIT(4)
>> +#define AUXRESPTIMEOUT				BIT(3)
>> +#define AUXRESPDEFER7TIMES			BIT(2)
>> +#define KSVACCESSINT				BIT(0)
>> +
>> +#define DW_DP_HDCP_KSVMEMCTRL			0x0e18
>> +#define KSVSHA1STATUS				BIT(4)
>> +#define KSVMEMACCESS				BIT(1)
>> +#define KSVMEMREQUEST				BIT(0)
>> +
>> +#define DW_DP_HDCP_REG_BKSV0			0x3600
>> +#define DW_DP_HDCP_REG_BKSV1			0x3604
>> +#define DW_DP_HDCP_REG_ANCONF			0x3608
>> +#define AN_BYPASS				BIT(0)
>> +
>> +#define DW_DP_HDCP_REG_AN0			0x360c
>> +#define DW_DP_HDCP_REG_AN1			0x3610
>> +#define DW_DP_HDCP_REG_RMLCTL			0x3614
>> +#define ODPK_DECRYPT_ENABLE			BIT(0)
>> +
>> +#define DW_DP_HDCP_REG_RMLSTS			0x3618
>> +#define IDPK_WR_OK_STS				BIT(6)
>> +#define	IDPK_DATA_INDEX				GENMASK(5, 0)
>> +#define DW_DP_HDCP_REG_SEED			0x361c
>> +#define DW_DP_HDCP_REG_DPK0			0x3620
>> +#define DW_DP_HDCP_REG_DPK1			0x3624
>> +#define DW_DP_HDCP22_GPIOSTS			0x3628
>> +#define DW_DP_HDCP22_GPIOCHNGSTS		0x362c
>> +#define DW_DP_HDCP_REG_DPK_CRC			0x3630
>> +
>> +#define DW_DP_MAX_REGISTER			DW_DP_HDCP_REG_DPK_CRC
>> +
>> +#define SDP_REG_BANK_SIZE			16
>> +
>> +struct dw_dp_link_caps {
>> +	bool enhanced_framing;
>> +	bool tps3_supported;
>> +	bool tps4_supported;
>> +	bool fast_training;
>> +	bool channel_coding;
>> +	bool ssc;
>> +};
>> +
>> +struct dw_dp_link_train_set {
>> +	unsigned int voltage_swing[4];
>> +	unsigned int pre_emphasis[4];
>> +	bool voltage_max_reached[4];
>> +	bool pre_max_reached[4];
>> +};
>> +
>> +struct dw_dp_link_train {
>> +	struct dw_dp_link_train_set request;
>> +	struct dw_dp_link_train_set adjust;
>> +	bool clock_recovered;
>> +	bool channel_equalized;
>> +};
>> +
>> +struct dw_dp_link {
>> +	u8 dpcd[DP_RECEIVER_CAP_SIZE];
>> +	unsigned char revision;
>> +	unsigned int rate;
>> +	unsigned int lanes;
>> +	u8 sink_count;
>> +	u8 vsc_sdp_supported;
>> +	struct dw_dp_link_caps caps;
>> +	struct dw_dp_link_train train;
>> +	struct drm_dp_desc desc;
>> +};
>> +
>> +struct dw_dp_video {
>> +	struct drm_display_mode mode;
>> +	u8 video_mapping;
>> +	u8 pixel_mode;
>> +	u8 color_format;
>> +	u8 bpc;
>> +	u8 bpp;
>> +};
>> +
>> +struct dw_dp_sdp {
>> +	struct dp_sdp_header header;
>> +	u8 db[32];
>
>struct dp_sdp, please

Ok, will do.

>
>> +	unsigned long flags;
>> +};
>> +
>> +struct dw_dp_hotplug {
>> +	bool long_hpd;
>> +};
>> +
>> +struct dw_dp {
>> +	struct drm_bridge bridge;
>> +	struct device *dev;
>> +	struct regmap *regmap;
>> +	struct phy *phy;
>> +	struct clk *apb_clk;
>> +	struct clk *aux_clk;
>> +	struct clk *i2s_clk;
>> +	struct clk *spdif_clk;
>> +	struct clk *hdcp_clk;
>> +	struct reset_control *rstc;
>> +	struct completion complete;
>> +	int irq;
>> +	struct work_struct hpd_work;
>> +	struct dw_dp_hotplug hotplug;
>> +	struct mutex irq_lock;
>> +
>> +	struct drm_dp_aux aux;
>> +
>> +	struct dw_dp_link link;
>> +	struct dw_dp_video video;
>> +	const struct dw_dp_plat_data *plat_data;
>> +
>> +	DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
>> +};
>> +
>> +enum {
>> +	DW_DP_RGB_6BIT,
>> +	DW_DP_RGB_8BIT,
>> +	DW_DP_RGB_10BIT,
>> +	DW_DP_RGB_12BIT,
>> +	DW_DP_RGB_16BIT,
>> +	DW_DP_YCBCR444_8BIT,
>> +	DW_DP_YCBCR444_10BIT,
>> +	DW_DP_YCBCR444_12BIT,
>> +	DW_DP_YCBCR444_16BIT,
>> +	DW_DP_YCBCR422_8BIT,
>> +	DW_DP_YCBCR422_10BIT,
>> +	DW_DP_YCBCR422_12BIT,
>> +	DW_DP_YCBCR422_16BIT,
>> +	DW_DP_YCBCR420_8BIT,
>> +	DW_DP_YCBCR420_10BIT,
>> +	DW_DP_YCBCR420_12BIT,
>> +	DW_DP_YCBCR420_16BIT,
>> +};
>> +
>> +enum {
>> +	DW_DP_MP_SINGLE_PIXEL,
>> +	DW_DP_MP_DUAL_PIXEL,
>> +	DW_DP_MP_QUAD_PIXEL,
>> +};
>> +
>> +enum {
>> +	DW_DP_SDP_VERTICAL_INTERVAL = BIT(0),
>> +	DW_DP_SDP_HORIZONTAL_INTERVAL = BIT(1),
>> +};
>> +
>> +enum {
>> +	DW_DP_HPD_STATE_IDLE,
>> +	DW_DP_HPD_STATE_UNPLUG,
>> +	DP_DP_HPD_STATE_TIMEOUT = 4,
>> +	DW_DP_HPD_STATE_PLUG = 7
>> +};
>> +
>> +enum {
>> +	DW_DP_PHY_PATTERN_NONE,
>> +	DW_DP_PHY_PATTERN_TPS_1,
>> +	DW_DP_PHY_PATTERN_TPS_2,
>> +	DW_DP_PHY_PATTERN_TPS_3,
>> +	DW_DP_PHY_PATTERN_TPS_4,
>> +	DW_DP_PHY_PATTERN_SERM,
>> +	DW_DP_PHY_PATTERN_PBRS7,
>> +	DW_DP_PHY_PATTERN_CUSTOM_80BIT,
>> +	DW_DP_PHY_PATTERN_CP2520_1,
>> +	DW_DP_PHY_PATTERN_CP2520_2,
>> +};
>> +
>> +struct dw_dp_output_format {
>> +	u32 bus_format;
>> +	u32 color_format;
>> +	u8 video_mapping;
>> +	u8 bpc;
>> +	u8 bpp;
>> +};
>> +
>> +static const struct dw_dp_output_format dw_dp_output_formats[] = {
>> +	{ MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
>> +	{ MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
>> +	{ MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
>> +	{ MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
>> +	{ MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
>> +	{ MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
>> +	{ MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
>> +	{ MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
>> +	{ MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
>> +};
>> +
>> +static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++)
>> +		if (dw_dp_output_formats[i].bus_format == bus_format)
>> +			return &dw_dp_output_formats[i];
>> +
>> +	return &dw_dp_output_formats[1];
>
>Why? Shouldn't it be NULL?

At first, we considered RGB888_1X24  to be universally applicable across all scenarios, 
but upon re-evaluation, this assumption proved inaccurate. Specifically, RGB888 may
encounter bandwidth limitations in high-resolution or high-refresh-rate environments

So returning NULL would be more appropriate here.

>
>> +}
>> +
>> +static inline struct dw_dp *bridge_to_dp(struct drm_bridge *b)
>> +{
>> +	return container_of(b, struct dw_dp, bridge);
>> +}
>> +
>> +static inline void dw_dp_phy_set_pattern(struct dw_dp *dp, u32 pattern)
>> +{
>> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, TPS_SEL,
>> +			   FIELD_PREP(TPS_SEL, pattern));
>> +}
>> +
>> +static void dw_dp_phy_xmit_enable(struct dw_dp *dp, u32 lanes)
>> +{
>> +	u32 xmit_enable;
>> +
>> +	switch (lanes) {
>> +	case 4:
>> +	case 2:
>> +	case 1:
>> +		xmit_enable = GENMASK(lanes - 1, 0);
>> +		break;
>> +	case 0:
>> +	default:
>> +		xmit_enable = 0;
>> +		break;
>> +	}
>> +
>> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, XMIT_ENABLE,
>> +			   FIELD_PREP(XMIT_ENABLE, xmit_enable));
>> +}
>> +
>> +static bool dw_dp_bandwidth_ok(struct dw_dp *dp,
>> +			       const struct drm_display_mode *mode, u32 bpp,
>> +			       unsigned int lanes, unsigned int rate)
>> +{
>> +	u32 max_bw, req_bw;
>> +
>> +	req_bw = mode->clock * bpp / 8;
>> +	max_bw = lanes * rate;
>> +	if (req_bw > max_bw)
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>> +static bool dw_dp_hpd_detect(struct dw_dp *dp)
>> +{
>> +	u32 value;
>> +
>> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
>> +
>> +	return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
>> +}
>> +
>> +static void dw_dp_link_caps_reset(struct dw_dp_link_caps *caps)
>> +{
>> +	caps->enhanced_framing = false;
>> +	caps->tps3_supported = false;
>> +	caps->tps4_supported = false;
>> +	caps->fast_training = false;
>> +	caps->channel_coding = false;
>> +}
>> +
>> +static void dw_dp_link_reset(struct dw_dp_link *link)
>> +{
>> +	link->vsc_sdp_supported = 0;
>> +	link->sink_count = 0;
>> +	link->revision = 0;
>> +	link->rate = 0;
>> +	link->lanes = 0;
>> +
>> +	dw_dp_link_caps_reset(&link->caps);
>> +	memset(link->dpcd, 0, sizeof(link->dpcd));
>> +}
>> +
>> +static int dw_dp_link_power_up(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	int ret;
>> +	u8 value;
>> +
>> +	if (link->revision < DP_DPCD_REV_11)
>> +		return 0;
>> +
>> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	value &= ~DP_SET_POWER_MASK;
>> +	value |= DP_SET_POWER_D0;
>> +
>> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	usleep_range(1000, 2000);
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_power_down(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	int ret;
>> +	u8 value;
>> +
>> +	if (link->revision < DP_DPCD_REV_11)
>> +		return 0;
>> +
>> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	value &= ~DP_SET_POWER_MASK;
>> +	value |= DP_SET_POWER_D3;
>> +
>> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
>> +	if (ret < 0)
>> +		return ret;
>> +
>
>Would you please mind pulling these two functions to DRM DP helpers?
>There are enough users to make this into a common code.

Yes, when developing this patch, I had the same realization. 
The processing logic for MSM/Cadence/ANX6345/tegra follows
a similar approach.
I had originally planned to defer this refactoring until the series of patches is accepted. 
Additionally, I have other pending tasks in my TODO list, such as fully decoupling the 
bridge driver and encoder/connector components across all Rockchip platforms?
But I prioritize completing these foundational features before go to next steps,
Is this acceptable ?

>
>> +	return 0;
>> +}
>> +
>> +static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>> +				 const struct drm_dp_desc *desc)
>> +{
>> +	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
>> +	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
>> +	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);
>
>
>isn't it drm_dp_read_sink_count_cap() ?

I will have a try, since this drm_dp_read_sink_count_cap requires a connector parameter, 
I need to figure out how to get the connector here.

>
>> +}
>> +
>> +static int dw_dp_link_parse(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 dpcd;
>> +	int ret;
>> +
>> +	dw_dp_link_reset(link);
>> +
>> +	ret = drm_dp_read_dpcd_caps(&dp->aux, link->dpcd);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	drm_dp_read_desc(&dp->aux, &link->desc, drm_dp_is_branch(link->dpcd));
>> +
>> +	if (dw_dp_has_sink_count(link->dpcd, &link->desc)) {
>> +		ret = drm_dp_read_sink_count(&dp->aux);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		link->sink_count = ret;
>> +
>> +		/* Dongle connected, but no display */
>> +		if (!link->sink_count)
>> +			return -ENODEV;
>> +	}
>> +
>> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dpcd);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	link->vsc_sdp_supported = !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
>> +
>> +	link->revision = link->dpcd[DP_DPCD_REV];
>> +	link->rate = min_t(u32, min(dp->plat_data->max_link_rate,
>> +				    dp->phy->attrs.max_link_rate * 100),
>> +			   drm_dp_max_link_rate(link->dpcd));
>> +	link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
>> +			    drm_dp_max_lane_count(link->dpcd));
>> +
>> +	link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
>> +	link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
>> +	link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
>> +	link->caps.fast_training = drm_dp_fast_training_cap(link->dpcd);
>> +	link->caps.channel_coding = drm_dp_channel_coding_supported(link->dpcd);
>> +	link->caps.ssc = !!(link->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes,
>> +				    struct dw_dp_link_train_set *train_set)
>> +{
>> +	union phy_configure_opts phy_cfg;
>> +	unsigned int *vs, *pe;
>> +	u8 buf[4];
>> +	int i, ret;
>> +
>> +	vs = train_set->voltage_swing;
>> +	pe = train_set->pre_emphasis;
>> +
>> +	for (i = 0; i < lanes; i++) {
>> +		phy_cfg.dp.voltage[i] = vs[i];
>> +		phy_cfg.dp.pre[i] = pe[i];
>> +	}
>> +
>> +	phy_cfg.dp.lanes = lanes;
>> +	phy_cfg.dp.link_rate = rate / 100;
>> +	phy_cfg.dp.set_lanes = false;
>> +	phy_cfg.dp.set_rate = false;
>
>You don't need to set lanes / link_rate if set_lanes and set_rate is
>false.
This is because the rk_udphy_dp_phy_configure function first verifies the rate and lane settings,
treating any uninitialized parameters as invalid configurations

>
>> +	phy_cfg.dp.set_voltages = true;
>> +
>> +	ret = phy_configure(dp->phy, &phy_cfg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	for (i = 0; i < lanes; i++) {
>> +		buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
>> +			 (pe[i] << DP_TRAIN_PRE_EMPHASIS_SHIFT);
>> +		if (train_set->voltage_max_reached[i])
>> +			buf[i] |= DP_TRAIN_MAX_SWING_REACHED;
>> +		if (train_set->pre_max_reached[i])
>> +			buf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
>> +	}
>> +
>> +	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, lanes);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_train_update_vs_emph(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	struct dw_dp_link_train_set *request = &link->train.request;
>> +
>> +	return dw_dp_phy_update_vs_emph(dp, dp->link.rate, dp->link.lanes, request);
>
>Inline it mayeb?

Okay? will do?
>
>> +}
>> +
>> +static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
>> +			       unsigned int lanes, bool ssc)
>> +{
>> +	union phy_configure_opts phy_cfg;
>> +	int ret;
>> +
>> +	/* Move PHY to P3 */
>> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
>> +			   FIELD_PREP(PHY_POWERDOWN, 0x3));
>> +
>> +	phy_cfg.dp.lanes = lanes;
>> +	phy_cfg.dp.link_rate = rate / 100;
>> +	phy_cfg.dp.ssc = ssc;
>> +	phy_cfg.dp.set_lanes = true;
>> +	phy_cfg.dp.set_rate = true;
>> +	phy_cfg.dp.set_voltages = false;
>> +	ret = phy_configure(dp->phy, &phy_cfg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_LANES,
>> +			   FIELD_PREP(PHY_LANES, lanes / 2));
>> +
>> +	/* Move PHY to P0 */
>> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
>> +			   FIELD_PREP(PHY_POWERDOWN, 0x0));
>> +
>> +	dw_dp_phy_xmit_enable(dp, lanes);
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_configure(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 buf[2];
>> +	int ret;
>> +
>> +	ret = dw_dp_phy_configure(dp, link->rate, link->lanes, link->caps.ssc);
>> +	if (ret)
>> +		return ret;
>> +
>> +	buf[0] = drm_dp_link_rate_to_bw_code(link->rate);
>> +	buf[1] = link->lanes;
>> +
>> +	if (link->caps.enhanced_framing) {
>> +		buf[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
>> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
>> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 1));
>> +	} else {
>> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
>> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 0));
>> +	}
>> +
>> +	ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, sizeof(buf));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	buf[0] = link->caps.ssc ? DP_SPREAD_AMP_0_5 : 0;
>> +	buf[1] = link->caps.channel_coding ? DP_SET_ANSI_8B10B : 0;
>> +
>> +	ret = drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf));
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static void dw_dp_link_train_init(struct dw_dp_link_train *train)
>> +{
>> +	struct dw_dp_link_train_set *request = &train->request;
>> +	struct dw_dp_link_train_set *adjust = &train->adjust;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		request->voltage_swing[i] = 0;
>> +		adjust->voltage_swing[i] = 0;
>> +
>> +		request->pre_emphasis[i] = 0;
>> +		adjust->pre_emphasis[i] = 0;
>> +
>> +		request->voltage_max_reached[i] = false;
>> +		adjust->voltage_max_reached[i] = false;
>> +
>> +		request->pre_max_reached[i] = false;
>> +		adjust->pre_max_reached[i] = false;
>> +	}
>> +
>> +	train->clock_recovered = false;
>> +	train->channel_equalized = false;
>> +}
>> +
>> +static bool dw_dp_link_train_valid(const struct dw_dp_link_train *train)
>> +{
>> +	return train->clock_recovered && train->channel_equalized;
>> +}
>> +
>> +static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
>> +{
>> +	u8 buf = 0;
>> +	int ret;
>> +
>> +	if (pattern && pattern != DP_TRAINING_PATTERN_4) {
>> +		buf |= DP_LINK_SCRAMBLING_DISABLE;
>> +
>> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
>> +				   FIELD_PREP(SCRAMBLE_DIS, 1));
>> +	} else {
>> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
>> +				   FIELD_PREP(SCRAMBLE_DIS, 0));
>> +	}
>> +
>> +	switch (pattern) {
>> +	case DP_TRAINING_PATTERN_DISABLE:
>> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_NONE);
>> +		break;
>> +	case DP_TRAINING_PATTERN_1:
>> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_1);
>> +		break;
>> +	case DP_TRAINING_PATTERN_2:
>> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_2);
>> +		break;
>> +	case DP_TRAINING_PATTERN_3:
>> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_3);
>> +		break;
>> +	case DP_TRAINING_PATTERN_4:
>> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_4);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
>> +				 buf | pattern);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static u8 dw_dp_voltage_max(u8 preemph)
>> +{
>> +	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_0:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_1:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_2:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_3:
>> +	default:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
>> +	}
>> +}
>> +
>> +static void dw_dp_link_get_adjustments(struct dw_dp_link *link,
>> +				       u8 status[DP_LINK_STATUS_SIZE])
>> +{
>> +	struct dw_dp_link_train_set *adjust = &link->train.adjust;
>> +	u8 v = 0;
>> +	u8 p = 0;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < link->lanes; i++) {
>> +		v = drm_dp_get_adjust_request_voltage(status, i);
>> +		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
>> +		if (p >=  DP_TRAIN_PRE_EMPH_LEVEL_3) {
>> +			adjust->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
>> +						  DP_TRAIN_PRE_EMPHASIS_SHIFT;
>> +			adjust->pre_max_reached[i] = true;
>> +		} else {
>> +			adjust->pre_emphasis[i] = p >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
>> +			adjust->pre_max_reached[i] = false;
>> +		}
>> +		v = min(v, dw_dp_voltage_max(p));
>> +		if (v >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) {
>> +			adjust->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
>> +						   DP_TRAIN_VOLTAGE_SWING_SHIFT;
>> +			adjust->voltage_max_reached[i] = true;
>> +		} else {
>> +			adjust->voltage_swing[i] = v >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
>> +			adjust->voltage_max_reached[i] = false;
>> +		}
>> +	}
>> +}
>> +
>> +static void dw_dp_link_train_adjust(struct dw_dp_link_train *train)
>> +{
>> +	struct dw_dp_link_train_set *request = &train->request;
>> +	struct dw_dp_link_train_set *adjust = &train->adjust;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < 4; i++) {
>
>Shouldn't it be a loop up to link->lanes?

Yeah, this makes sense?


>
>> +		if (request->voltage_swing[i] != adjust->voltage_swing[i])
>> +			request->voltage_swing[i] = adjust->voltage_swing[i];
>> +		if (request->voltage_max_reached[i] != adjust->voltage_max_reached[i])
>> +			request->voltage_max_reached[i] = adjust->voltage_max_reached[i];
>> +	}
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
>> +			request->pre_emphasis[i] = adjust->pre_emphasis[i];
>> +		if (request->pre_max_reached[i] != adjust->pre_max_reached[i])
>> +			request->pre_max_reached[i] = adjust->pre_max_reached[i];
>
>Why do you need separate request and adjustment structs?

I need to think about this issue further and will confirm how to proceed later.


>
>> +	}
>> +}
>> +
>> +static int dw_dp_link_clock_recovery(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 status[DP_LINK_STATUS_SIZE];
>> +	unsigned int tries = 0;
>> +	int ret;
>> +
>> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
>> +	if (ret)
>> +		return ret;
>> +
>> +	for (;;) {
>> +		ret = dw_dp_link_train_update_vs_emph(dp);
>> +		if (ret)
>> +			return ret;
>> +
>> +		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
>> +
>> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
>> +		if (ret < 0) {
>> +			dev_err(dp->dev, "failed to read link status: %d\n", ret);
>> +			return ret;
>> +		}
>> +
>> +		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
>> +			link->train.clock_recovered = true;
>> +			break;
>> +		}
>> +
>> +		dw_dp_link_get_adjustments(link, status);
>> +
>> +		if (link->train.request.voltage_swing[0] ==
>> +		    link->train.adjust.voltage_swing[0])
>
>Should this take all lanes to account? I think it might be posssible to
>drop the adjust / request split and adjust tries in
>dw_dp_link_get_adjustments() instead.

Let me figure it out later?

>
>> +			tries++;
>> +		else
>> +			tries = 0;
>> +
>> +		if (tries == 5)
>> +			break;
>> +
>> +		dw_dp_link_train_adjust(&link->train);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_channel_equalization(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 status[DP_LINK_STATUS_SIZE], pattern;
>> +	unsigned int tries;
>> +	int ret;
>> +
>> +	if (link->caps.tps4_supported)
>> +		pattern = DP_TRAINING_PATTERN_4;
>> +	else if (link->caps.tps3_supported)
>> +		pattern = DP_TRAINING_PATTERN_3;
>> +	else
>> +		pattern = DP_TRAINING_PATTERN_2;
>> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
>> +	if (ret)
>> +		return ret;
>> +
>> +	for (tries = 1; tries < 5; tries++) {
>> +		ret = dw_dp_link_train_update_vs_emph(dp);
>> +		if (ret)
>> +			return ret;
>> +
>> +		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
>> +
>> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
>> +			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
>> +			link->train.clock_recovered = false;
>> +			break;
>> +		}
>> +
>> +		if (drm_dp_channel_eq_ok(status, link->lanes)) {
>> +			link->train.channel_equalized = true;
>> +			break;
>> +		}
>> +
>> +		dw_dp_link_get_adjustments(link, status);
>> +		dw_dp_link_train_adjust(&link->train);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_downgrade(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	struct dw_dp_video *video = &dp->video;
>> +
>> +	switch (link->rate) {
>> +	case 162000:
>> +		return -EINVAL;
>> +	case 270000:
>> +		link->rate = 162000;
>> +		break;
>> +	case 540000:
>> +		link->rate = 270000;
>> +		break;
>> +	case 810000:
>> +		link->rate = 540000;
>> +		break;
>> +	}
>> +
>> +	if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
>> +				link->rate))
>> +		return -E2BIG;
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_train_full(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	int ret;
>> +
>> +retry:
>> +	dw_dp_link_train_init(&link->train);
>> +
>> +	dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
>> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
>> +
>> +	ret = dw_dp_link_configure(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = dw_dp_link_clock_recovery(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "clock recovery failed: %d\n", ret);
>> +		goto out;
>> +	}
>> +
>> +	if (!link->train.clock_recovered) {
>> +		dev_err(dp->dev, "clock recovery failed, downgrading link\n");
>> +
>> +		ret = dw_dp_link_downgrade(dp);
>> +		if (ret < 0)
>> +			goto out;
>> +		else
>> +			goto retry;
>> +	}
>> +
>> +	dev_dbg(dp->dev, "clock recovery succeeded\n");
>> +
>> +	ret = dw_dp_link_channel_equalization(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "channel equalization failed: %d\n", ret);
>> +		goto out;
>> +	}
>> +
>> +	if (!link->train.channel_equalized) {
>> +		dev_err(dp->dev, "channel equalization failed, downgrading link\n");
>> +
>> +		ret = dw_dp_link_downgrade(dp);
>> +		if (ret < 0)
>> +			goto out;
>> +		else
>> +			goto retry;
>> +	}
>> +
>> +	dev_dbg(dp->dev, "channel equalization succeeded\n");
>> +
>> +out:
>> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
>> +	return ret;
>> +}
>> +
>> +static int dw_dp_link_train_fast(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	int ret;
>> +	u8 status[DP_LINK_STATUS_SIZE];
>> +	u8 pattern;
>> +
>> +	dw_dp_link_train_init(&link->train);
>> +
>> +	dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
>> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
>> +
>> +	ret = dw_dp_link_configure(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
>> +	if (ret)
>> +		goto out;
>> +
>> +	usleep_range(500, 1000);
>> +
>> +	if (link->caps.tps4_supported)
>> +		pattern = DP_TRAINING_PATTERN_4;
>> +	else if (link->caps.tps3_supported)
>> +		pattern = DP_TRAINING_PATTERN_3;
>> +	else
>> +		pattern = DP_TRAINING_PATTERN_2;
>> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
>> +	if (ret)
>> +		goto out;
>> +
>> +	usleep_range(500, 1000);
>> +
>> +	ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "failed to read link status: %d\n", ret);
>> +		goto out;
>> +	}
>> +
>> +	if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
>> +		dev_err(dp->dev, "clock recovery failed\n");
>> +		ret = -EIO;
>> +		goto out;
>> +	}
>> +
>> +	if (!drm_dp_channel_eq_ok(status, link->lanes)) {
>> +		dev_err(dp->dev, "channel equalization failed\n");
>> +		ret = -EIO;
>> +		goto out;
>> +	}
>> +
>> +out:
>> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
>> +	return ret;
>> +}
>> +
>> +static int dw_dp_link_train(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	int ret;
>> +
>> +	if (link->caps.fast_training) {
>> +		if (dw_dp_link_train_valid(&link->train)) {
>> +			ret = dw_dp_link_train_fast(dp);
>> +			if (ret < 0)
>> +				dev_err(dp->dev, "fast link training failed: %d\n", ret);
>> +			else
>> +				return 0;
>> +		}
>> +	}
>> +
>> +	ret = dw_dp_link_train_full(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "full link training failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_send_sdp(struct dw_dp *dp, struct dw_dp_sdp *sdp)
>> +{
>> +	const u8 *payload = sdp->db;
>> +	u32 reg;
>> +	int i, nr;
>> +
>> +	nr = find_first_zero_bit(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
>> +	if (nr < SDP_REG_BANK_SIZE)
>> +		set_bit(nr, dp->sdp_reg_bank);
>> +	else
>> +		return -EBUSY;
>> +
>> +	reg = DW_DP_SDP_REGISTER_BANK + nr * 9 * 4;
>> +
>> +	/* SDP header */
>> +	regmap_write(dp->regmap, reg, get_unaligned_le32(&sdp->header));
>> +
>> +	/* SDP data payload */
>> +	for (i = 1; i < 9; i++, payload += 4)
>> +		regmap_write(dp->regmap, reg + i * 4,
>> +			     FIELD_PREP(SDP_REGS, get_unaligned_le32(payload)));
>> +
>> +	if (sdp->flags & DW_DP_SDP_VERTICAL_INTERVAL)
>> +		regmap_update_bits(dp->regmap, DW_DP_SDP_VERTICAL_CTRL,
>> +				   EN_VERTICAL_SDP << nr,
>> +				   EN_VERTICAL_SDP << nr);
>> +
>> +	if (sdp->flags & DW_DP_SDP_HORIZONTAL_INTERVAL)
>> +		regmap_update_bits(dp->regmap, DW_DP_SDP_HORIZONTAL_CTRL,
>> +				   EN_HORIZONTAL_SDP << nr,
>> +				   EN_HORIZONTAL_SDP << nr);
>> +
>> +	return 0;
>> +}
>> +
>> +static void dw_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
>> +			       struct dw_dp_sdp *sdp)
>
>Use drm_dp_vsc_sdp_pack() instead.

Ok? I will try?

>
>> +{
>> +	sdp->header.HB0 = 0;
>> +	sdp->header.HB1 = DP_SDP_VSC;
>> +	sdp->header.HB2 = vsc->revision;
>> +	sdp->header.HB3 = vsc->length;
>> +
>> +	sdp->db[16] = (vsc->pixelformat & 0xf) << 4;
>> +	sdp->db[16] |= vsc->colorimetry & 0xf;
>> +
>> +	switch (vsc->bpc) {
>> +	case 8:
>> +		sdp->db[17] = 0x1;
>> +		break;
>> +	case 10:
>> +		sdp->db[17] = 0x2;
>> +		break;
>> +	case 12:
>> +		sdp->db[17] = 0x3;
>> +		break;
>> +	case 16:
>> +		sdp->db[17] = 0x4;
>> +		break;
>> +	case 6:
>> +	default:
>> +		break;
>> +	}
>> +
>> +	if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
>> +		sdp->db[17] |= 0x80;
>> +
>> +	sdp->db[18] = vsc->content_type & 0x7;
>> +
>> +	sdp->flags |= DW_DP_SDP_VERTICAL_INTERVAL;
>> +}
>> +
>> +static int dw_dp_send_vsc_sdp(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_video *video = &dp->video;
>> +	struct drm_dp_vsc_sdp vsc = {};
>> +	struct dw_dp_sdp sdp = {};
>> +
>> +	vsc.revision = 0x5;
>> +	vsc.length = 0x13;
>> +
>> +	switch (video->color_format) {
>> +	case DRM_COLOR_FORMAT_YCBCR444:
>> +		vsc.pixelformat = DP_PIXELFORMAT_YUV444;
>> +		break;
>> +	case DRM_COLOR_FORMAT_YCBCR420:
>> +		vsc.pixelformat = DP_PIXELFORMAT_YUV420;
>> +		break;
>> +	case DRM_COLOR_FORMAT_YCBCR422:
>> +		vsc.pixelformat = DP_PIXELFORMAT_YUV422;
>> +		break;
>> +	case DRM_COLOR_FORMAT_RGB444:
>> +	default:
>> +		vsc.pixelformat = DP_PIXELFORMAT_RGB;
>> +		break;
>> +	}
>> +
>> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
>> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
>> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
>> +	} else {
>> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
>> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>> +	}
>> +
>> +	vsc.bpc = video->bpc;
>> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
>> +
>> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
>> +
>> +	return dw_dp_send_sdp(dp, &sdp);
>> +}
>> +
>> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
>> +{
>> +	switch (pixel_mode) {
>> +	case DW_DP_MP_SINGLE_PIXEL:
>> +	case DW_DP_MP_DUAL_PIXEL:
>> +	case DW_DP_MP_QUAD_PIXEL:
>> +		break;
>> +	default:
>> +		return -EINVAL;
>
>Is it possible?

This IP is configurable for single/dual/quad pixel modes?
It's  quad pixel mode on rk3588 and dual pixel mode on rk3576,
so we add this check here.


>
>> +	}
>> +
>> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
>> +			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
>> +
>> +	return 0;
>> +}
>> +
>> +static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	struct dw_dp_video *video = &dp->video;
>> +
>> +	if (!link->vsc_sdp_supported)
>> +		return false;
>> +
>> +	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
>> +		return true;
>> +
>> +	return false;
>> +}
>> +
>> +static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
>> +			       u16 vstart, u16 hstart)
>> +{
>> +	u16 misc = 0;
>> +
>> +	if (dw_dp_video_need_vsc_sdp(dp))
>> +		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
>> +
>> +	switch (color_format) {
>> +	case DRM_COLOR_FORMAT_RGB444:
>> +		misc |= DP_MSA_MISC_COLOR_RGB;
>> +		break;
>> +	case DRM_COLOR_FORMAT_YCBCR444:
>> +		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
>> +		break;
>> +	case DRM_COLOR_FORMAT_YCBCR422:
>> +		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
>> +		break;
>> +	case DRM_COLOR_FORMAT_YCBCR420:
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	switch (bpc) {
>> +	case 6:
>> +		misc |= DP_MSA_MISC_6_BPC;
>> +		break;
>> +	case 8:
>> +		misc |= DP_MSA_MISC_8_BPC;
>> +		break;
>> +	case 10:
>> +		misc |= DP_MSA_MISC_10_BPC;
>> +		break;
>> +	case 12:
>> +		misc |= DP_MSA_MISC_12_BPC;
>> +		break;
>> +	case 16:
>> +		misc |= DP_MSA_MISC_16_BPC;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
>> +		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
>> +
>> +	return 0;
>> +}
>> +
>> +static void dw_dp_video_disable(struct dw_dp *dp)
>> +{
>> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
>> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
>> +}
>> +
>> +static int dw_dp_video_enable(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_video *video = &dp->video;
>> +	struct dw_dp_link *link = &dp->link;
>> +	struct drm_display_mode *mode = &video->mode;
>> +	u8 color_format = video->color_format;
>> +	u8 bpc = video->bpc;
>> +	u8 pixel_mode = video->pixel_mode;
>> +	u8 bpp = video->bpp, init_threshold, vic;
>> +	u32 hactive, hblank, h_sync_width, h_front_porch;
>> +	u32 vactive, vblank, v_sync_width, v_front_porch;
>> +	u32 vstart = mode->vtotal - mode->vsync_start;
>> +	u32 hstart = mode->htotal - mode->hsync_start;
>> +	u32 peak_stream_bandwidth, link_bandwidth;
>> +	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
>> +	u32 ts, hblank_interval;
>> +	u32 value;
>> +	int ret;
>> +
>> +	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
>> +	if (ret)
>> +		return ret;
>> +
>> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
>> +			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
>> +
>> +	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
>> +	value = 0;
>> +	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
>> +		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
>> +	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
>> +		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
>> +	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
>> +
>> +	/* Configure DW_DP_VIDEO_CONFIG1 register */
>> +	hactive = mode->hdisplay;
>> +	hblank = mode->htotal - mode->hdisplay;
>> +	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
>> +	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>> +		value |= FIELD_PREP(I_P, 1);
>> +	vic = drm_match_cea_mode(mode);
>> +	if (vic == 5 || vic == 6 || vic == 7 ||
>> +	    vic == 10 || vic == 11 || vic == 20 ||
>> +	    vic == 21 || vic == 22 || vic == 39 ||
>> +	    vic == 25 || vic == 26 || vic == 40 ||
>> +	    vic == 44 || vic == 45 || vic == 46 ||
>> +	    vic == 50 || vic == 51 || vic == 54 ||
>> +	    vic == 55 || vic == 58 || vic  == 59)
>> +		value |= R_V_BLANK_IN_OSC;
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
>> +
>> +	/* Configure DW_DP_VIDEO_CONFIG2 register */
>> +	vblank = mode->vtotal - mode->vdisplay;
>> +	vactive = mode->vdisplay;
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
>> +		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
>> +
>> +	/* Configure DW_DP_VIDEO_CONFIG3 register */
>> +	h_sync_width = mode->hsync_end - mode->hsync_start;
>> +	h_front_porch = mode->hsync_start - mode->hdisplay;
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
>> +		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
>> +		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
>> +
>> +	/* Configure DW_DP_VIDEO_CONFIG4 register */
>> +	v_sync_width = mode->vsync_end - mode->vsync_start;
>> +	v_front_porch = mode->vsync_start - mode->vdisplay;
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
>> +		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
>> +		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
>> +
>> +	/* Configure DW_DP_VIDEO_CONFIG5 register */
>> +	peak_stream_bandwidth = mode->clock * bpp / 8;
>> +	link_bandwidth = (link->rate / 1000) * link->lanes;
>> +	ts = peak_stream_bandwidth * 64 / link_bandwidth;
>> +	average_bytes_per_tu = ts / 1000;
>> +	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
>> +	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
>> +		if (average_bytes_per_tu < 6)
>> +			init_threshold = 32;
>> +		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
>> +			init_threshold = 12;
>> +		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
>> +			init_threshold = 3;
>> +		else
>> +			init_threshold = 16;
>> +	} else {
>> +		u32 t1 = 0, t2 = 0, t3 = 0;
>> +
>> +		switch (bpc) {
>> +		case 6:
>> +			t1 = (4 * 1000 / 9) * link->lanes;
>> +			break;
>> +		case 8:
>> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
>> +				t1 = (1000 / 2) * link->lanes;
>> +			} else {
>> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> +					t1 = (1000 / 3) * link->lanes;
>> +				else
>> +					t1 = (3000 / 16) * link->lanes;
>> +			}
>> +			break;
>> +		case 10:
>> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
>> +				t1 = (2000 / 5) * link->lanes;
>> +			else
>> +				t1 = (4000 / 15) * link->lanes;
>> +			break;
>> +		case 12:
>> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
>> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> +					t1 = (1000 / 6) * link->lanes;
>> +				else
>> +					t1 = (1000 / 3) * link->lanes;
>> +			} else {
>> +				t1 = (2000 / 9) * link->lanes;
>> +			}
>> +			break;
>> +		case 16:
>> +			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
>> +			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> +				t1 = (1000 / 6) * link->lanes;
>> +			else
>> +				t1 = (1000 / 4) * link->lanes;
>> +			break;
>> +		default:
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
>> +			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
>> +		else
>> +			t2 = (link->rate / 4) * 1000 / mode->clock;
>> +
>> +		if (average_bytes_per_tu_frac)
>> +			t3 = average_bytes_per_tu + 1;
>> +		else
>> +			t3 = average_bytes_per_tu;
>> +		init_threshold = t1 * t2 * t3 / (1000 * 1000);
>> +		if (init_threshold <= 16 || average_bytes_per_tu < 10)
>> +			init_threshold = 40;
>> +	}
>> +
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
>> +		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
>> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
>> +		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
>> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
>> +
>> +	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
>> +	hblank_interval = hblank * (link->rate / 4) / mode->clock;
>> +	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
>> +		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
>> +		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
>> +
>> +	/* Video stream enable */
>> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
>> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
>> +
>> +	if (dw_dp_video_need_vsc_sdp(dp))
>> +		dw_dp_send_vsc_sdp(dp);
>> +
>> +	return 0;
>> +}
>> +
>> +static void dw_dp_hpd_init(struct dw_dp *dp)
>> +{
>> +	/* Enable all HPD interrupts */
>> +	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
>> +			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
>> +			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
>> +			   FIELD_PREP(HPD_PLUG_EN, 1) |
>> +			   FIELD_PREP(HPD_IRQ_EN, 1));
>> +
>> +	/* Enable all top-level interrupts */
>> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
>> +			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
>> +}
>> +
>> +static void dw_dp_aux_init(struct dw_dp *dp)
>> +{
>> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
>> +			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
>> +}
>> +
>> +static void dw_dp_init_hw(struct dw_dp *dp)
>> +{
>> +	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
>> +			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
>> +
>> +	dw_dp_hpd_init(dp);
>> +	dw_dp_aux_init(dp);
>> +}
>> +
>> +static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
>> +{
>> +	size_t i, j;
>> +
>> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
>> +		size_t num = min_t(size_t, size - i * 4, 4);
>> +		u32 value = 0;
>> +
>> +		for (j = 0; j < num; j++)
>> +			value |= buffer[i * 4 + j] << (j * 8);
>> +
>> +		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
>> +	}
>> +
>> +	return size;
>> +}
>> +
>> +static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
>> +{
>> +	size_t i, j;
>> +
>> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
>> +		size_t num = min_t(size_t, size - i * 4, 4);
>> +		u32 value;
>> +
>> +		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
>> +
>> +		for (j = 0; j < num; j++)
>> +			buffer[i * 4 + j] = value >> (j * 8);
>> +	}
>> +
>> +	return size;
>> +}
>> +
>> +static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
>> +				  struct drm_dp_aux_msg *msg)
>> +{
>> +	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
>> +	unsigned long timeout = msecs_to_jiffies(10);
>> +	u32 status, value;
>> +	ssize_t ret = 0;
>> +
>> +	if (WARN_ON(msg->size > 16))
>> +		return -E2BIG;
>> +
>> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
>> +	case DP_AUX_NATIVE_WRITE:
>> +	case DP_AUX_I2C_WRITE:
>> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
>> +		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
>> +		if (ret < 0)
>> +			return ret;
>> +		break;
>> +	case DP_AUX_NATIVE_READ:
>> +	case DP_AUX_I2C_READ:
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (msg->size > 0)
>> +		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
>> +	else
>> +		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
>> +	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
>> +	value |= FIELD_PREP(AUX_ADDR, msg->address);
>> +	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
>> +
>> +	status = wait_for_completion_timeout(&dp->complete, timeout);
>> +	if (!status) {
>> +		dev_err(dp->dev, "timeout waiting for AUX reply\n");
>> +		return -ETIMEDOUT;
>> +	}
>> +
>> +	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
>> +	if (value & AUX_TIMEOUT)
>> +		return -ETIMEDOUT;
>> +
>> +	msg->reply = FIELD_GET(AUX_STATUS, value);
>> +
>> +	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
>> +		if (msg->request & DP_AUX_I2C_READ) {
>> +			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
>> +
>> +			if (count != msg->size)
>> +				return -EBUSY;
>> +
>> +			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
>> +			if (ret < 0)
>> +				return ret;
>> +		}
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +/*
>> + * Limits for the video timing output by DP:
>> + * 1. the hfp should be 2 pixels aligned;
>> + * 2. the minimum hsync should be 9 pixel;
>> + * 3. the minimum hbp should be 16 pixel;
>> + */
>> +static bool dw_dp_bridge_mode_fixup(struct drm_bridge *bridge,
>> +				    const struct drm_display_mode *mode,
>> +				    struct drm_display_mode *adjusted_mode)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	int min_hbp = 16;
>> +	int min_hsync = 9;
>> +
>> +	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
>> +		adjusted_mode->hsync_start += 1;
>> +		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
>> +	}
>> +	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
>> +		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
>> +		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
>> +	}
>> +	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
>> +		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
>> +		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
>> +	}
>> +
>> +	return true;
>> +}
>> +
>> +static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
>> +						    const struct drm_display_info *info,
>> +						    const struct drm_display_mode *mode)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	struct dw_dp_link *link = &dp->link;
>> +	u32 min_bpp;
>> +
>> +	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
>> +	    link->vsc_sdp_supported &&
>> +	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
>> +		min_bpp = 12;
>> +	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
>> +		min_bpp = 16;
>> +	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
>> +		min_bpp = 18;
>> +	else
>> +		min_bpp = 24;
>> +
>> +	if (!link->vsc_sdp_supported &&
>> +	    drm_mode_is_420_only(info, mode))
>> +		return MODE_NO_420;
>> +
>> +	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
>> +		return MODE_CLOCK_HIGH;
>> +
>> +	return MODE_OK;
>> +}
>> +
>> +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
>> +					   struct drm_bridge_state *old_bridge_state)
>> +{
>> +	struct drm_atomic_state *state = old_bridge_state->base.state;
>> +	struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	struct dw_dp_video *video = &dp->video;
>> +	struct drm_display_mode *m = &video->mode;
>> +	struct drm_bridge_state *bridge_state;
>> +	const struct dw_dp_output_format *fmt;
>> +
>> +	drm_mode_copy(m, &crtc_state->adjusted_mode);
>> +
>> +	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
>> +	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);
>
>Should it be a part of the atomic_check() instead?

Since we have modef_fixup in this driver, which is mutually exclusive with atomic_check.



>
>> +
>> +	video->video_mapping = fmt->video_mapping;
>> +	video->color_format = fmt->color_format;
>> +	video->bpc = fmt->bpc;
>> +	video->bpp = fmt->bpp;
>> +}
>> +
>> +static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 link_status[DP_LINK_STATUS_SIZE];
>> +
>> +	if (!dw_dp_link_train_valid(&link->train))
>> +		return false;
>> +
>> +	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
>> +		return false;
>> +
>> +	/* Retrain if Channel EQ or CR not ok */
>> +	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
>> +}
>> +
>> +static void dw_dp_link_disable(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +
>> +	if (dw_dp_hpd_detect(dp))
>> +		dw_dp_link_power_down(dp);
>> +
>> +	dw_dp_phy_xmit_enable(dp, 0);
>> +
>> +	phy_power_off(dp->phy);
>> +
>> +	link->train.clock_recovered = false;
>> +	link->train.channel_equalized = false;
>> +}
>> +
>> +static int dw_dp_link_enable(struct dw_dp *dp)
>> +{
>> +	int ret;
>> +
>> +	ret = phy_power_on(dp->phy);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = dw_dp_link_power_up(dp);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = dw_dp_link_train(dp);
>> +
>> +	return ret;
>> +}
>> +
>> +static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
>> +				       struct drm_bridge_state *old_state)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	struct drm_atomic_state *state = old_state->base.state;
>> +	struct drm_connector *connector;
>> +	struct drm_connector_state *conn_state;
>> +	int ret;
>> +
>> +	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
>> +	if (!connector) {
>> +		dev_err(dp->dev, "failed to get connector\n");
>> +		return;
>> +	}
>> +
>> +	conn_state = drm_atomic_get_new_connector_state(state, connector);
>> +	if (!conn_state) {
>> +		dev_err(dp->dev, "failed to get connector state\n");
>> +		return;
>> +	}
>> +
>> +	set_bit(0, dp->sdp_reg_bank);
>> +
>> +	ret = dw_dp_link_enable(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "failed to enable link: %d\n", ret);
>> +		return;
>> +	}
>> +
>> +	ret = dw_dp_video_enable(dp);
>> +	if (ret < 0) {
>> +		dev_err(dp->dev, "failed to enable video: %d\n", ret);
>> +		return;
>> +	}
>> +}
>> +
>> +static void dw_dp_reset(struct dw_dp *dp)
>> +{
>> +	int val;
>> +
>> +	disable_irq(dp->irq);
>> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
>> +			   FIELD_PREP(CONTROLLER_RESET, 1));
>> +	udelay(10);
>> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
>> +			   FIELD_PREP(CONTROLLER_RESET, 0));
>> +
>> +	dw_dp_init_hw(dp);
>> +	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
>> +				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
>> +	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
>> +	enable_irq(dp->irq);
>> +}
>> +
>> +static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
>> +					struct drm_bridge_state *old_bridge_state)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +
>> +	dw_dp_video_disable(dp);
>> +	dw_dp_link_disable(dp);
>> +	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
>> +	dw_dp_reset(dp);
>> +}
>> +
>> +static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
>> +{
>> +	int ret;
>> +
>> +	ret = phy_power_on(dp->phy);
>> +	if (ret < 0)
>> +		return false;
>> +	ret = dw_dp_link_parse(dp);
>> +	phy_power_off(dp->phy);
>> +
>> +	return !ret;
>> +}
>> +
>> +static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +
>> +	if (!dw_dp_hpd_detect(dp))
>> +		return connector_status_disconnected;
>> +
>> +	if (!dw_dp_hpd_detect_link(dp))
>> +		return connector_status_disconnected;
>> +
>> +	return connector_status_connected;
>> +}
>> +
>> +static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
>> +						     struct drm_connector *connector)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	const struct drm_edid *edid;
>> +	int ret;
>> +
>> +	ret = phy_power_on(dp->phy);
>> +	if (ret)
>> +		return NULL;
>> +
>> +	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
>> +
>> +	phy_power_off(dp->phy);
>> +
>> +	return edid;
>> +}
>> +
>> +static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
>> +						    struct drm_bridge_state *bridge_state,
>> +						    struct drm_crtc_state *crtc_state,
>> +						    struct drm_connector_state *conn_state,
>> +						    unsigned int *num_output_fmts)
>> +{
>> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> +	struct dw_dp_link *link = &dp->link;
>> +	struct drm_display_info *di = &conn_state->connector->display_info;
>> +	struct drm_display_mode mode = crtc_state->mode;
>> +	const struct dw_dp_output_format *fmt;
>> +	u32 i, j = 0;
>> +	u32 *output_fmts;
>> +
>> +	*num_output_fmts = 0;
>> +
>> +	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
>> +	if (!output_fmts)
>> +		return NULL;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
>> +		fmt = &dw_dp_output_formats[i];
>> +
>> +		if (fmt->bpc > conn_state->max_bpc)
>> +			continue;
>> +
>> +		if (!(fmt->color_format & di->color_formats))
>> +			continue;
>> +
>> +		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
>> +		    !link->vsc_sdp_supported)
>> +			continue;
>> +
>> +		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
>> +		    drm_mode_is_420_only(di, &mode))
>> +			continue;
>> +
>> +		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
>> +			continue;
>> +
>> +		output_fmts[j++] = fmt->bus_format;
>> +	}
>> +
>> +	*num_output_fmts = j;
>> +
>> +	return output_fmts;
>> +}
>> +
>> +static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
>> +	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>> +	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>> +	.atomic_reset = drm_atomic_helper_bridge_reset,
>> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
>> +	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
>> +	.mode_fixup = dw_dp_bridge_mode_fixup,
>> +	.mode_valid = dw_dp_bridge_mode_valid,
>> +	.atomic_pre_enable = dw_dp_bridge_atomic_pre_enable,
>> +	.atomic_enable = dw_dp_bridge_atomic_enable,
>> +	.atomic_disable = dw_dp_bridge_atomic_disable,
>> +	.detect = dw_dp_bridge_detect,
>> +	.edid_read = dw_dp_bridge_edid_read,
>> +};
>> +
>> +static int dw_dp_link_retrain(struct dw_dp *dp)
>> +{
>> +	struct drm_device *dev = dp->bridge.dev;
>> +	struct drm_modeset_acquire_ctx ctx;
>> +	int ret;
>> +
>> +	if (!dw_dp_needs_link_retrain(dp))
>> +		return 0;
>> +
>> +	dev_dbg(dp->dev, "Retraining link\n");
>> +
>> +	drm_modeset_acquire_init(&ctx, 0);
>> +	for (;;) {
>> +		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
>> +		if (ret != -EDEADLK)
>> +			break;
>
>I think it's an error to continue in such a case. There should be a
>return after the loop if ret is not 0.

Thank you for catching this? I will add a check fater the loop.


>
>> +
>> +		drm_modeset_backoff(&ctx);
>> +	}
>> +
>> +	ret = dw_dp_link_train(dp);
>> +	drm_modeset_drop_locks(&ctx);
>> +	drm_modeset_acquire_fini(&ctx);
>> +
>> +	return ret;
>> +}
>> +
>> +static void dw_dp_hpd_work(struct work_struct *work)
>> +{
>> +	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
>> +	bool long_hpd;
>> +	int ret;
>> +
>> +	mutex_lock(&dp->irq_lock);
>> +	long_hpd = dp->hotplug.long_hpd;
>> +	mutex_unlock(&dp->irq_lock);
>> +
>> +	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
>> +
>> +	if (!long_hpd) {
>> +		if (dw_dp_needs_link_retrain(dp)) {
>> +			ret = dw_dp_link_retrain(dp);
>> +			if (ret)
>> +				dev_warn(dp->dev, "Retrain link failed\n");
>> +		}
>> +	} else {
>> +		drm_helper_hpd_irq_event(dp->bridge.dev);
>> +	}
>> +}
>> +
>> +static void dw_dp_handle_hpd_event(struct dw_dp *dp)
>> +{
>> +	u32 value;
>> +
>> +	mutex_lock(&dp->irq_lock);
>> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
>> +
>> +	if (value & HPD_IRQ) {
>> +		dev_dbg(dp->dev, "IRQ from the HPD\n");
>> +		dp->hotplug.long_hpd = false;
>> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
>> +	}
>> +
>> +	if (value & HPD_HOT_PLUG) {
>> +		dev_dbg(dp->dev, "Hot plug detected\n");
>> +		dp->hotplug.long_hpd = true;
>> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
>> +	}
>> +
>> +	if (value & HPD_HOT_UNPLUG) {
>> +		dev_dbg(dp->dev, "Unplug detected\n");
>> +		dp->hotplug.long_hpd = true;
>> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
>> +	}
>> +	mutex_unlock(&dp->irq_lock);
>> +
>> +	schedule_work(&dp->hpd_work);
>> +}
>> +
>> +static irqreturn_t dw_dp_irq(int irq, void *data)
>> +{
>> +	struct dw_dp *dp = data;
>> +	u32 value;
>> +
>> +	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
>> +	if (!value)
>> +		return IRQ_NONE;
>> +
>> +	if (value & HPD_EVENT)
>> +		dw_dp_handle_hpd_event(dp);
>> +
>> +	if (value & AUX_REPLY_EVENT) {
>> +		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
>> +		complete(&dp->complete);
>> +	}
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static const struct regmap_range dw_dp_readable_ranges[] = {
>> +	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
>> +	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
>> +	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
>> +	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
>> +	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
>> +	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
>> +	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
>> +	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
>> +	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
>> +};
>> +
>> +static const struct regmap_access_table dw_dp_readable_table = {
>> +	.yes_ranges     = dw_dp_readable_ranges,
>> +	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
>> +};
>> +
>> +static const struct regmap_config dw_dp_regmap_config = {
>> +	.reg_bits = 32,
>> +	.reg_stride = 4,
>> +	.val_bits = 32,
>> +	.fast_io = true,
>> +	.max_register = DW_DP_MAX_REGISTER,
>> +	.rd_table = &dw_dp_readable_table,
>> +};
>> +
>> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>> +			 const struct dw_dp_plat_data *plat_data)
>> +{
>> +	struct platform_device *pdev = to_platform_device(dev);
>> +	struct dw_dp *dp;
>> +	struct drm_bridge *bridge;
>> +	void __iomem *res;
>> +	int ret;
>> +
>> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
>> +	if (!dp)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	dp->dev = dev;
>> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
>> +
>> +	dp->plat_data = plat_data;
>> +	bridge = &dp->bridge;
>> +	mutex_init(&dp->irq_lock);
>> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
>> +	init_completion(&dp->complete);
>> +
>> +	res = devm_platform_ioremap_resource(pdev, 0);
>> +	if (IS_ERR(res))
>> +		return ERR_CAST(res);
>> +
>> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
>> +	if (IS_ERR(dp->regmap)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
>> +		return ERR_CAST(dp->regmap);
>> +	}
>> +
>> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
>> +	if (IS_ERR(dp->phy)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
>> +		return ERR_CAST(dp->phy);
>> +	}
>> +
>> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
>> +	if (IS_ERR(dp->apb_clk)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
>> +		return ERR_CAST(dp->apb_clk);
>> +	}
>> +
>> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
>> +	if (IS_ERR(dp->aux_clk)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
>> +		return ERR_CAST(dp->aux_clk);
>> +	}
>> +
>> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
>> +	if (IS_ERR(dp->i2s_clk)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
>> +		return ERR_CAST(dp->i2s_clk);
>> +	}
>> +
>> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
>> +	if (IS_ERR(dp->spdif_clk)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
>> +		return ERR_CAST(dp->spdif_clk);
>> +	}
>> +
>> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
>> +	if (IS_ERR(dp->hdcp_clk)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
>> +		return ERR_CAST(dp->hdcp_clk);
>> +	}
>> +
>> +	dp->rstc = devm_reset_control_get(dev, NULL);
>> +	if (IS_ERR(dp->rstc)) {
>> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
>> +		return ERR_CAST(dp->rstc);
>> +	}
>> +
>> +	dp->irq = platform_get_irq(pdev, 0);
>> +	if (dp->irq < 0)
>> +		return ERR_PTR(ret);
>> +
>> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
>> +					IRQF_ONESHOT, dev_name(dev), dp);
>
>Are you ready to handle the IRQ here, before the bridge is filled?

I will move to  devm_request_threaded_irq after dw_dp_init_hw.


>
>> +	if (ret) {
>> +		dev_err_probe(dev, ret, "failed to request irq\n");
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	bridge->of_node = dev->of_node;
>> +	bridge->funcs = &dw_dp_bridge_funcs;
>> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
>> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
>> +	bridge->ycbcr_420_allowed = true;
>> +	bridge->vendor = "Synopsys";
>> +	bridge->product = "DW DP TX";
>
>These two are unused
>
>> +
>> +	platform_set_drvdata(pdev, dp);
>
>Unused

I will remove them.

Thanks again.


>
>> +
>> +	dp->aux.dev = dev;
>> +	dp->aux.drm_dev = encoder->dev;
>> +	dp->aux.name = dev_name(dev);
>> +	dp->aux.transfer = dw_dp_aux_transfer;
>> +	ret = drm_dp_aux_register(&dp->aux);
>> +	if (ret) {
>> +		dev_err_probe(dev, ret, "Aux register failed\n");
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>> +	if (ret)
>> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
>> +
>> +	dw_dp_init_hw(dp);
>> +
>> +	return dp;
>> +}
>> +MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
>> +MODULE_DESCRIPTION("DW DP Core Library");
>> +MODULE_LICENSE("GPL");
>> diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
>> new file mode 100644
>> index 000000000000..07845f609eca
>> --- /dev/null
>> +++ b/include/drm/bridge/dw_dp.h
>> @@ -0,0 +1,19 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> +/*
>> + * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#ifndef __DW_DP__
>> +#define __DW_DP__
>> +
>> +struct device;
>> +struct drm_encoder;
>> +struct dw_dp;
>> +
>> +struct dw_dp_plat_data {
>> +	u32 max_link_rate;
>> +};
>> +
>> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>> +			 const struct dw_dp_plat_data *plat_data);
>> +#endif /* __DW_DP__ */
>> -- 
>> 2.34.1
>> 
>
>-- 
>With best wishes
>Dmitry

From damon.ding at rock-chips.com  Sun Mar  2 02:36:37 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Sun, 2 Mar 2025 18:36:37 +0800
Subject: [PATCH v7 09/15] drm/bridge: analogix_dp: Add support to get
 panel from the DP AUX bus
In-Reply-To: <CAD=FV=WoigDDTG6wTK0smsxASVfK5BzzW6KNpKWq97v4GAgvmw@mail.gmail.com>
References: <20250224081325.96724-1-damon.ding@rock-chips.com>
 <20250224081325.96724-10-damon.ding@rock-chips.com>
 <CAD=FV=WoigDDTG6wTK0smsxASVfK5BzzW6KNpKWq97v4GAgvmw@mail.gmail.com>
Message-ID: <1d066210-3d24-4d17-a51c-115f305c5de9@rock-chips.com>

Hi Doug,

On 2025/2/25 9:41, Doug Anderson wrote:
> Hi,
> 
> On Mon, Feb 24, 2025 at 12:14?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>>
>> The main modification is moving the DP AUX initialization from function
>> analogix_dp_bind() to analogix_dp_probe(). In order to get the EDID of
>> eDP panel during probing, it is also needed to advance PM operations to
>> ensure that eDP controller and phy are prepared for AUX transmission.
>>
>> Additionally, add support for &drm_dp_aux.wait_hpd_asserted() to help
>> confirm the HPD state before doing AUX transfers.
> 
> Maybe move the addition of the analogix_dpaux_wait_hpd_asserted() to a
> separate patch?
> 

It would be a good idea.

> 
>> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
>>
>> ---
>>
>> Changes in v4:
>> - Use done_probing() to call drm_of_find_panel_or_bridge() and
>>    component_add() when getting panel from the DP AUX bus
>>
>> Changes in v5:
>> - Advance PM operations to make eDP AUX work well
>>
>> Changes in v6:
>> - Use devm_pm_runtime_enable() instead of devm_add_action_or_reset()
>> - Add a new function analogix_dp_remove() to ensure symmetry for PM
>>    operations
>>
>> Changes in v7:
>> - Fix the misspelling of word 'operations' in commit message
>> - Remove the check related to CONFIG_PM
>> - Remove the unnecessary call to pm_runtime_dont_use_autosuspend() if
>>    devm_pm_runtime_enable() fails
>> - Remove unnecessary function analogix_dp_remove()
>> - Add new function analogix_dpaux_wait_hpd_asserted()
>> ---
>>   .../drm/bridge/analogix/analogix_dp_core.c    | 37 ++++++++++++++-----
>>   1 file changed, 28 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index a57e06d303a1..ff81c37dbe1d 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -1548,6 +1548,22 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
>>          return ret;
>>   }
>>
>> +static int analogix_dpaux_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
>> +{
>> +       struct analogix_dp_device *dp = to_dp(aux);
>> +       int val;
>> +       int ret;
>> +
>> +       pm_runtime_get_sync(dp->dev);
>> +
>> +       ret = readx_poll_timeout(analogix_dp_detect_hpd, dp, val, !val, wait_us / 100, wait_us);
> 
> More than happy if someone else wants to overrule me, but it seems
> weird that you're looping over a function that already has a loop.
> Shouldn't you be calling analogix_dp_get_plug_in_status() directly?
> ...and if "dp->force_hpd" you probably shouldn't be polling at all. If
> HPD is not hooked up I think we decided in sn65dsi86 that we should
> just sleep for the maximum time (choosing a conservative value if told
> to wait forever).
> 

Yes, I think there is no need to use analogix_dp_detect_hpd(), and the 
code as you recommended is better:

static int analogix_dpaux_wait_hpd_asserted(struct drm_dp_aux *aux, 
unsigned long wait_us)
{
	struct analogix_dp_device *dp = to_dp(aux);
	int val;
	int ret;

	if (dp->force_hpd)
		return 0;

	pm_runtime_get_sync(dp->dev);

	ret = readx_poll_timeout(analogix_dp_get_plug_in_status, dp, val, !val,
				 wait_us / 100, wait_us);

	pm_runtime_mark_last_busy(dp->dev);
	pm_runtime_put_autosuspend(dp->dev);

	return ret;
}

> 
> Aside from that and the idea of moving
> analogix_dpaux_wait_hpd_asserted() to a separate patch this looks good
> to me.
> 

Best regards
Damon



From chunkuang.hu at kernel.org  Sun Mar  2 02:38:01 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 18:38:01 +0800
Subject: [PATCH v7 02/43] drm/mediatek: mtk_dpi: Add support for Pattern
 Generator in debugfs
In-Reply-To: <20250217154836.108895-3-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-3-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_-dk8qtn_uHifQs3Gcgkh=1LZ1K6YNK+37tuDzNgNyn6A@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> This IP includes a Pattern Generator which is useful for debugging
> and testing purposes: add the relevant register and bits to the
> mtk_dpi_regs.h header, and implement support for it in mtk_dpi.
>
> Adding this required to introduce a .debugfs_init() callback for
> the DPI bridge, which creates a "dpi_test_pattern" file in the
> directory of the appropriate connector.
>
> The pattern generator can generate various internal patterns and
> this submission includes support for:
>  - 256 or 1024 shades of gray in a Vertical or Horizontal Pattern
>  - Vertical Color Bars
>  - Frame border
>  - Dot Moire
>
> This generator also supports filling the entire screen with one
> custom color, but support for that is not included in this commit.
>
> Enabling and disabling this generator can be done by sending a
> string to the dpi_test_pattern debugfs file; the pattern is
> expected to be formatted as follows:
>
>          <enable (1) or disable (0)> <pattern number>
>
> where the pattern number can be a number from 0 to 7, excluding 5.
>
> Of course 5 is excluded because that activates custom color fill
> which, again, is not supported in this commit.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c      | 108 ++++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_dpi_regs.h |   4 +
>  2 files changed, 112 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 1864eb02dbf5..fc937490feda 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -4,8 +4,10 @@
>   * Author: Jie Qiu <jie.qiu at mediatek.com>
>   */
>
> +#include <linux/bitfield.h>
>  #include <linux/clk.h>
>  #include <linux/component.h>
> +#include <linux/debugfs.h>
>  #include <linux/interrupt.h>
>  #include <linux/kernel.h>
>  #include <linux/media-bus-format.h>
> @@ -166,6 +168,18 @@ static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
>         writel(tmp, dpi->regs + offset);
>  }
>
> +static void mtk_dpi_test_pattern_en(struct mtk_dpi *dpi, u8 type, bool enable)
> +{
> +       u32 val;
> +
> +       if (enable)
> +               val = FIELD_PREP(DPI_PAT_SEL, type) | DPI_PAT_EN;
> +       else
> +               val = 0;
> +
> +       mtk_dpi_mask(dpi, DPI_PATTERN0, val, DPI_PAT_SEL | DPI_PAT_EN);
> +}
> +
>  static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset)
>  {
>         mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST);
> @@ -767,6 +781,99 @@ mtk_dpi_bridge_mode_valid(struct drm_bridge *bridge,
>         return MODE_OK;
>  }
>
> +static int mtk_dpi_debug_tp_show(struct seq_file *m, void *arg)
> +{
> +       struct mtk_dpi *dpi = m->private;
> +       bool en;
> +       u32 val;
> +
> +       if (!dpi)
> +               return -EINVAL;
> +
> +       val = readl(dpi->regs + DPI_PATTERN0);
> +       en = val & DPI_PAT_EN;
> +       val = FIELD_GET(DPI_PAT_SEL, val);
> +
> +       seq_printf(m, "DPI Test Pattern: %s\n", en ? "Enabled" : "Disabled");
> +
> +       if (en) {
> +               seq_printf(m, "Internal pattern %d: ", val);
> +               switch (val) {
> +               case 0:
> +                       seq_puts(m, "256 Vertical Gray\n");
> +                       break;
> +               case 1:
> +                       seq_puts(m, "1024 Vertical Gray\n");
> +                       break;
> +               case 2:
> +                       seq_puts(m, "256 Horizontal Gray\n");
> +                       break;
> +               case 3:
> +                       seq_puts(m, "1024 Horizontal Gray\n");
> +                       break;
> +               case 4:
> +                       seq_puts(m, "Vertical Color bars\n");
> +                       break;
> +               case 6:
> +                       seq_puts(m, "Frame border\n");
> +                       break;
> +               case 7:
> +                       seq_puts(m, "Dot moire\n");
> +                       break;
> +               default:
> +                       seq_puts(m, "Invalid selection\n");
> +                       break;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static ssize_t mtk_dpi_debug_tp_write(struct file *file, const char __user *ubuf,
> +                                     size_t len, loff_t *offp)
> +{
> +       struct seq_file *m = file->private_data;
> +       u32 en, type;
> +       char buf[6];
> +
> +       if (!m || !m->private || *offp || len > sizeof(buf) - 1)
> +               return -EINVAL;
> +
> +       memset(buf, 0, sizeof(buf));
> +       if (copy_from_user(buf, ubuf, len))
> +               return -EFAULT;
> +
> +       if (sscanf(buf, "%u %u", &en, &type) != 2)
> +               return -EINVAL;
> +
> +       if (en < 0 || en > 1 || type < 0 || type > 7)
> +               return -EINVAL;
> +
> +       mtk_dpi_test_pattern_en((struct mtk_dpi *)m->private, type, en);
> +       return len;
> +}
> +
> +static int mtk_dpi_debug_tp_open(struct inode *inode, struct file *file)
> +{
> +       return single_open(file, mtk_dpi_debug_tp_show, inode->i_private);
> +}
> +
> +static const struct file_operations mtk_dpi_debug_tp_fops = {
> +       .owner = THIS_MODULE,
> +       .open = mtk_dpi_debug_tp_open,
> +       .read = seq_read,
> +       .write = mtk_dpi_debug_tp_write,
> +       .llseek = seq_lseek,
> +       .release = single_release,
> +};
> +
> +static void mtk_dpi_debugfs_init(struct drm_bridge *bridge, struct dentry *root)
> +{
> +       struct mtk_dpi *dpi = bridge_to_dpi(bridge);
> +
> +       debugfs_create_file("dpi_test_pattern", 0640, root, dpi, &mtk_dpi_debug_tp_fops);
> +}
> +
>  static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
>         .attach = mtk_dpi_bridge_attach,
>         .mode_set = mtk_dpi_bridge_mode_set,
> @@ -779,6 +886,7 @@ static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
>         .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>         .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>         .atomic_reset = drm_atomic_helper_bridge_reset,
> +       .debugfs_init = mtk_dpi_debugfs_init,
>  };
>
>  void mtk_dpi_start(struct device *dev)
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> index 62bd4931b344..a0b1d18bbbf7 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> @@ -235,4 +235,8 @@
>  #define MATRIX_SEL_RGB_TO_JPEG         0
>  #define MATRIX_SEL_RGB_TO_BT601                2
>
> +#define DPI_PATTERN0           0xf00
> +#define DPI_PAT_EN                     BIT(0)
> +#define DPI_PAT_SEL                    GENMASK(6, 4)
> +
>  #endif /* __MTK_DPI_REGS_H */
> --
> 2.48.1
>


From andyshrk at 163.com  Sun Mar  2 02:37:25 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sun, 2 Mar 2025 18:37:25 +0800 (CST)
Subject: [PATCH 3/6] drm/rockchip: Add RK3588 DPTX output support
In-Reply-To: <63xbqyzdlv7jssbmvoeicz4gech3di6nr3tsyvhbhxrmvthh3f@tlf73esqcwgt>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-4-andyshrk@163.com>
 <63xbqyzdlv7jssbmvoeicz4gech3di6nr3tsyvhbhxrmvthh3f@tlf73esqcwgt>
Message-ID: <7be797ff.219d.195566ea038.Coremail.andyshrk@163.com>


Hi Dmitry,

At 2025-03-02 02:19:24, "Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> wrote:
>On Sun, Feb 23, 2025 at 07:30:26PM +0800, Andy Yan wrote:
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> Add driver extension for Synopsys DesignWare DPTX IP used
>> on Rockchip RK3588 SoC.
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> ---
>> 
>>  drivers/gpu/drm/rockchip/Kconfig            |   7 +
>>  drivers/gpu/drm/rockchip/Makefile           |   1 +
>>  drivers/gpu/drm/rockchip/dw_dp-rockchip.c   | 162 ++++++++++++++++++++
>>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   1 +
>>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
>>  5 files changed, 172 insertions(+)
>>  create mode 100644 drivers/gpu/drm/rockchip/dw_dp-rockchip.c
>> 
>> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
>> index 26c4410b2407..c8638baf9641 100644
>> --- a/drivers/gpu/drm/rockchip/Kconfig
>> +++ b/drivers/gpu/drm/rockchip/Kconfig
>> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
>>  	select DRM_PANEL
>>  	select VIDEOMODE_HELPERS
>>  	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
>> +	select DRM_DW_DP if ROCKCHIP_DW_DP
>>  	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
>>  	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
>>  	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
>> @@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
>>  	  RK3399 based SoC, you should select this
>>  	  option.
>>  
>> +config ROCKCHIP_DW_DP
>> +	bool "Rockchip specific extensions for Synopsys DW DP"
>> +	help
>> +	  Choose this option for Synopsys DesignWare Cores DisplayPort
>> +	  transmit controller support on Rockchip SoC.
>> +
>>  config ROCKCHIP_DW_HDMI
>>  	bool "Rockchip specific extensions for Synopsys DW HDMI"
>>  	help
>> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
>> index 2b867cebbc12..097f062399c7 100644
>> --- a/drivers/gpu/drm/rockchip/Makefile
>> +++ b/drivers/gpu/drm/rockchip/Makefile
>> @@ -14,6 +14,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI2) += dw-mipi-dsi2-rockchip.o
>> +rockchipdrm-$(CONFIG_ROCKCHIP_DW_DP) += dw_dp-rockchip.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
>>  rockchipdrm-$(CONFIG_ROCKCHIP_RGB) += rockchip_rgb.o
>> diff --git a/drivers/gpu/drm/rockchip/dw_dp-rockchip.c b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
>> new file mode 100644
>> index 000000000000..b41a41eb74d7
>> --- /dev/null
>> +++ b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
>> @@ -0,0 +1,162 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
>> + *
>> + * Author: Zhang Yubing <yubing.zhang at rock-chips.com>
>> + * Author: Andy Yan <andy.yan at rock-chips.com>
>> + */
>> +
>> +#include <linux/component.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <drm/bridge/dw_dp.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_bridge.h>
>> +#include <drm/drm_bridge_connector.h>
>> +#include <drm/drm_of.h>
>> +#include <drm/drm_print.h>
>> +#include <drm/drm_probe_helper.h>
>> +#include <drm/drm_simple_kms_helper.h>
>> +
>> +#include <uapi/linux/media-bus-format.h>
>> +#include <uapi/linux/videodev2.h>
>
>I'd say, include those two headers directly. Rockchip / Synopsys are the
>only drivers including these uapi headers directly.

Okay, I will include them directly in V2 like this:

+#include <linux/media-bus-format.h>
+#include <linux/videodev2.h>

>
>> +
>> +#include "rockchip_drm_drv.h"
>> +#include "rockchip_drm_vop.h"
>> +
>> +struct rockchip_dw_dp {
>> +	struct dw_dp *base;
>> +	struct device *dev;
>> +	struct rockchip_encoder encoder;
>> +};
>> +
>> +static inline struct rockchip_dw_dp *encoder_to_dp(struct drm_encoder *encoder)
>> +{
>> +	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
>> +
>> +	return container_of(rkencoder, struct rockchip_dw_dp, encoder);
>> +}
>> +
>> +static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder,
>> +				      struct drm_crtc_state *crtc_state,
>> +				      struct drm_connector_state *conn_state)
>> +{
>> +	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
>> +	struct drm_atomic_state *state = conn_state->state;
>> +	struct drm_display_info *di = &conn_state->connector->display_info;
>> +	struct drm_bridge *bridge  = drm_bridge_chain_get_first_bridge(encoder);
>> +	struct drm_bridge_state *bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
>> +	u32 bus_format = bridge_state->input_bus_cfg.format;
>> +
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
>> +	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
>> +		s->output_mode = ROCKCHIP_OUT_MODE_YUV420;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUYV10_1X20:
>> +	case MEDIA_BUS_FMT_YUYV8_1X16:
>> +		s->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB101010_1X30:
>> +	case MEDIA_BUS_FMT_RGB888_1X24:
>> +	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	default:
>> +		s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
>> +		break;
>> +	}
>> +
>> +	s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
>> +	s->bus_format = bus_format;
>> +	s->bus_flags = di->bus_flags;
>> +	s->color_space = V4L2_COLORSPACE_DEFAULT;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct drm_encoder_helper_funcs dw_dp_encoder_helper_funcs = {
>> +	.atomic_check		= dw_dp_encoder_atomic_check,
>> +};
>> +
>> +static int dw_dp_rockchip_bind(struct device *dev, struct device *master, void *data)
>> +{
>> +	struct dw_dp_plat_data plat_data;
>> +	struct drm_device *drm_dev = data;
>> +	struct rockchip_dw_dp *dp;
>> +	struct drm_encoder *encoder;
>> +	struct drm_connector *connector;
>> +	int ret;
>> +
>> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
>> +	if (!dp)
>> +		return -ENOMEM;
>> +
>> +	dp->dev = dev;
>> +	plat_data.max_link_rate = 810000;
>> +	encoder = &dp->encoder.encoder;
>> +	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
>> +	rockchip_drm_encoder_set_crtc_endpoint_id(&dp->encoder, dev->of_node, 0, 0);
>> +
>> +	drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
>
>drmm_encoder_init() ? This will allow you to get rid of
>drm_encoder_cleanup() calls.

Okay, I will try in V2.


>
>> +	drm_encoder_helper_add(encoder, &dw_dp_encoder_helper_funcs);
>> +
>> +	dp->base = dw_dp_bind(dev, encoder, &plat_data);
>> +	if (IS_ERR(dp->base)) {
>> +		ret = PTR_ERR(dp->base);
>> +		drm_encoder_cleanup(encoder);
>> +		return ret;
>> +	}
>> +
>> +	connector = drm_bridge_connector_init(drm_dev, encoder);
>> +	if (IS_ERR(connector)) {
>> +		ret = PTR_ERR(connector);
>> +		dev_err(dev, "Failed to init bridge connector: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	drm_connector_attach_encoder(connector, encoder);
>> +
>> +	return 0;
>> +}
>> +
>> +static void dw_dp_rockchip_unbind(struct device *dev, struct device *master, void *data)
>> +{
>> +	struct rockchip_dw_dp *dp = dev_get_drvdata(dev);
>> +
>> +	drm_encoder_cleanup(&dp->encoder.encoder);
>> +}
>> +
>> +static const struct component_ops dw_dp_rockchip_component_ops = {
>> +	.bind = dw_dp_rockchip_bind,
>> +	.unbind = dw_dp_rockchip_unbind,
>> +};
>> +
>> +static int dw_dp_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +
>> +	return component_add(dev, &dw_dp_rockchip_component_ops);
>> +}
>> +
>> +static void dw_dp_remove(struct platform_device *pdev)
>> +{
>> +	struct rockchip_dw_dp *dp = platform_get_drvdata(pdev);
>> +
>> +	component_del(dp->dev, &dw_dp_rockchip_component_ops);
>> +}
>> +
>> +static const struct of_device_id dw_dp_of_match[] = {
>> +	{ .compatible = "rockchip,rk3588-dp", },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(of, dw_dp_of_match);
>> +
>> +struct platform_driver dw_dp_driver = {
>> +	.probe	= dw_dp_probe,
>> +	.remove = dw_dp_remove,
>> +	.driver = {
>> +		.name = "dw-dp",
>> +		.of_match_table = dw_dp_of_match,
>> +	},
>> +};
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> index 9cf311b5dec1..2b245491c71d 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> @@ -529,6 +529,7 @@ static int __init rockchip_drm_init(void)
>>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
>>  				CONFIG_ROCKCHIP_ANALOGIX_DP);
>>  	ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
>> +	ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP);
>>  	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
>>  				CONFIG_ROCKCHIP_DW_HDMI);
>>  	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> index c183e82a42a5..2e86ad00979c 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> @@ -87,6 +87,7 @@ int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder,
>>  					      struct device_node *np, int port, int reg);
>>  int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
>>  extern struct platform_driver cdn_dp_driver;
>> +extern struct platform_driver dw_dp_driver;
>>  extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
>>  extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
>>  extern struct platform_driver dw_mipi_dsi_rockchip_driver;
>> -- 
>> 2.34.1
>> 
>
>-- 
>With best wishes
>Dmitry

From chunkuang.hu at kernel.org  Sun Mar  2 02:53:26 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 18:53:26 +0800
Subject: [PATCH v7 03/43] drm/mediatek: mtk_dpi: Use an array for pixclk
 factor calculation
In-Reply-To: <20250217154836.108895-4-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-4-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_97vGqWn93-esp3H-41Z4bHoBXoBOmKRnOFCCOU8LXnqA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> Setting the TVD PLL clock requires to multiply the target pixel
> clock by a specific constant factor to achieve the target PLL
> frequency, and this is done to reduce jitter to acceptable levels.
>
> On all MediaTek SoCs, the factor is not retrieved by any real kind
> of calculation but rather by checking if the target pixel clock
> is less than a specified frequency, hence assigning a function
> pointer for just a bunch of if branches does enlarge the code
> size for little reason.
>
> Remove all SoC-specific functions, add a structure `mtk_dpi_factor`
> that holds a clock frequency and corresponding PLL factor, and
> declare the constraints for each SoC in form of an array of said
> structure.
> Instead of function pointers, this structure (and its size) is then
> assigned to each SoC's platform data.
>
> The "calculation" is then performed with a new static function
> mtk_dpi_calculate_factor(dpi, mode_clk) that iterates through all
> of the entries of the aforementioned array and returns the right
> factor.
>
> If no factor is found, the lowest possible factor is returned,
> mimicking the same flow as all of the old per-SoC calculation
> functions.
>
> This commit brings no functional change.

After fix build error, applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 103 +++++++++++++++--------------
>  1 file changed, 52 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index fc937490feda..41fdc193891a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -118,9 +118,15 @@ struct mtk_dpi_yc_limit {
>         u16 c_bottom;
>  };
>
> +struct mtk_dpi_factor {
> +       u32 clock;
> +       u8 factor;
> +};
> +
>  /**
>   * struct mtk_dpi_conf - Configuration of mediatek dpi.
> - * @cal_factor: Callback function to calculate factor value.
> + * @dpi_factor: SoC-specific pixel clock PLL factor values.
> + * @num_dpi_factor: Number of pixel clock PLL factor values.
>   * @reg_h_fre_con: Register address of frequency control.
>   * @max_clock_khz: Max clock frequency supported for this SoCs in khz units.
>   * @edge_sel_en: Enable of edge selection.
> @@ -141,7 +147,8 @@ struct mtk_dpi_yc_limit {
>   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
>   */
>  struct mtk_dpi_conf {
> -       unsigned int (*cal_factor)(int clock);
> +       const struct mtk_dpi_factor *dpi_factor;
> +       const u8 num_dpi_factor;
>         u32 reg_h_fre_con;
>         u32 max_clock_khz;
>         bool edge_sel_en;
> @@ -516,6 +523,20 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
>         return ret;
>  }
>
> +static unsigned int mtk_dpi_calculate_factor(struct mtk_dpi *dpi, int mode_clk)
> +{
> +       const struct mtk_dpi_factor *dpi_factor = dpi->conf->dpi_factor;
> +       int i;
> +
> +       for (i = 0; i < dpi->conf->num_dpi_factor; i++) {
> +               if (mode_clk <= dpi_factor[i].clock)
> +                       return dpi_factor[i].factor;
> +       }
> +
> +       /* If no match try the lowest possible factor */
> +       return dpi_factor[dpi->conf->num_dpi_factor - 1].factor;
> +}
> +
>  static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>                                     struct drm_display_mode *mode)
>  {
> @@ -530,7 +551,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>         unsigned int factor;
>
>         /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
> -       factor = dpi->conf->cal_factor(mode->clock);
> +       factor = mtk_dpi_calculate_factor(dpi, mode_clk);
>         drm_display_mode_to_videomode(mode, &vm);
>         pll_rate = vm.pixelclock * factor;
>
> @@ -965,48 +986,6 @@ static const struct component_ops mtk_dpi_component_ops = {
>         .unbind = mtk_dpi_unbind,
>  };
>
> -static unsigned int mt8173_calculate_factor(int clock)
> -{
> -       if (clock <= 27000)
> -               return 3 << 4;
> -       else if (clock <= 84000)
> -               return 3 << 3;
> -       else if (clock <= 167000)
> -               return 3 << 2;
> -       else
> -               return 3 << 1;
> -}
> -
> -static unsigned int mt2701_calculate_factor(int clock)
> -{
> -       if (clock <= 64000)
> -               return 4;
> -       else if (clock <= 128000)
> -               return 2;
> -       else
> -               return 1;
> -}
> -
> -static unsigned int mt8183_calculate_factor(int clock)
> -{
> -       if (clock <= 27000)
> -               return 8;
> -       else if (clock <= 167000)
> -               return 4;
> -       else
> -               return 2;
> -}
> -
> -static unsigned int mt8195_dpintf_calculate_factor(int clock)
> -{
> -       if (clock < 70000)
> -               return 4;
> -       else if (clock < 200000)
> -               return 2;
> -       else
> -               return 1;
> -}
> -
>  static const u32 mt8173_output_fmts[] = {
>         MEDIA_BUS_FMT_RGB888_1X24,
>  };
> @@ -1021,8 +1000,25 @@ static const u32 mt8195_output_fmts[] = {
>         MEDIA_BUS_FMT_YUYV8_1X16,
>  };
>
> +static const struct mtk_dpi_factor dpi_factor_mt2701[] = {
> +       { 64000, 4 }, { 128000, 2 }, { U32_MAX, 1 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8173[] = {
> +       { 27000, 48 }, { 84000, 24 }, { 167000, 12 }, { U32_MAX, 6 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8183[] = {
> +       { 27000, 8 }, { 167000, 4 }, { U32_MAX, 2 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8195_dp_intf[] = {
> +       { 70000 - 1, 4 }, { 200000 - 1, 2 }, { U32_MAX, 1 }
> +};
> +
>  static const struct mtk_dpi_conf mt8173_conf = {
> -       .cal_factor = mt8173_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8173,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8173),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 300000,
>         .output_fmts = mt8173_output_fmts,
> @@ -1039,7 +1035,8 @@ static const struct mtk_dpi_conf mt8173_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt2701_conf = {
> -       .cal_factor = mt2701_calculate_factor,
> +       .dpi_factor = dpi_factor_mt2701,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt2701),
>         .reg_h_fre_con = 0xb0,
>         .edge_sel_en = true,
>         .max_clock_khz = 150000,
> @@ -1057,7 +1054,8 @@ static const struct mtk_dpi_conf mt2701_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8183_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 100000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1074,7 +1072,8 @@ static const struct mtk_dpi_conf mt8183_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8186_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 150000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1092,7 +1091,8 @@ static const struct mtk_dpi_conf mt8186_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8192_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 150000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1109,7 +1109,8 @@ static const struct mtk_dpi_conf mt8192_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8195_dpintf_conf = {
> -       .cal_factor = mt8195_dpintf_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8195_dp_intf,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf),
>         .max_clock_khz = 600000,
>         .output_fmts = mt8195_output_fmts,
>         .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
> --
> 2.48.1
>


From jonas at kwiboo.se  Sun Mar  2 03:01:29 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 2 Mar 2025 12:01:29 +0100
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for
 RK3528
In-Reply-To: <3574922.QJadu78ljV@diego>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104749.36423-1-ziyao@disroot.org>
 <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se> <3574922.QJadu78ljV@diego>
Message-ID: <3cb87f70-1838-4492-b78e-0cd98457cb83@kwiboo.se>

Hi Heiko,

On 2025-03-01 13:55, Heiko St?bner wrote:
> Hey Joas,
> 
> Am Samstag, 1. M?rz 2025, 13:47:47 MEZ schrieb Jonas Karlman:
>> On 2025-03-01 11:47, Yao Zi wrote:
>>> RK3528 features two SDIO controllers and one SD/MMC controller, describe
>>> them in devicetree. Since their sample and drive clocks are located in
>>> the VO and VPU GRFs, corresponding syscons are added to make these
>>> clocks available.
>>>
>>> Signed-off-by: Yao Zi <ziyao at disroot.org>
>>> ---
>>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
>>>  1 file changed, 62 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> index 5b334690356a..078c97fa1d9f 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> @@ -7,6 +7,7 @@
>>>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>>>  #include <dt-bindings/interrupt-controller/irq.h>
>>>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
>>> +#include <dt-bindings/reset/rockchip,rk3528-cru.h>
>>>  
>>>  / {
>>>  	compatible = "rockchip,rk3528";
>>> @@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
>>>  			#interrupt-cells = <3>;
>>>  		};
>>>  
>>> +		vpu_grf: syscon at ff340000 {
>>> +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
>>
>> vpu_grf is also used for gmac1, so should possible be a "syscon",
>> "simple-mfd", or have I misunderstood when to use simple-mfd ?
> 
> simple-mfd is needed when the additional device is completely contained
> inside the particular syscon.
> 
> For example, the usb2phy0 on rk3588 is completely living inside the
> usb2phy0-grf.
> 
> Similarly the power-domains are living inside the rk3588 pmugrf.
> But the pmugrf also contains more stuff, so the power-domains are a
> subset of the pmugrf.
> 
> Both of these above are a case for a simple-mfd.
> 
> 
> Similarly, gmac1 on rk3588 is ethernet at fe1c0000 , so a completely separate
> io-memory area, but references both the sysgrf as well as the php-grf
> as syscons for additional settings.
> 
> So here the syscon does not need to be a simple-mfd.
> 
> 
> Hope that helps a bit

Thanks for this explanation, it helped me better understand the meaning
of simple-mfd :-)

Regards,
Jonas

> Heiko
> 
> 



From chunkuang.hu at kernel.org  Sun Mar  2 03:03:09 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:03:09 +0800
Subject: [PATCH v7 03/43] drm/mediatek: mtk_dpi: Use an array for pixclk
 factor calculation
In-Reply-To: <20250217154836.108895-4-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-4-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_8KFgSQEYC7v+6Asi_KdYjdsj==fOt6LR1FnOvFF+-BvA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> Setting the TVD PLL clock requires to multiply the target pixel
> clock by a specific constant factor to achieve the target PLL
> frequency, and this is done to reduce jitter to acceptable levels.
>
> On all MediaTek SoCs, the factor is not retrieved by any real kind
> of calculation but rather by checking if the target pixel clock
> is less than a specified frequency, hence assigning a function
> pointer for just a bunch of if branches does enlarge the code
> size for little reason.
>
> Remove all SoC-specific functions, add a structure `mtk_dpi_factor`
> that holds a clock frequency and corresponding PLL factor, and
> declare the constraints for each SoC in form of an array of said
> structure.
> Instead of function pointers, this structure (and its size) is then
> assigned to each SoC's platform data.
>
> The "calculation" is then performed with a new static function
> mtk_dpi_calculate_factor(dpi, mode_clk) that iterates through all
> of the entries of the aforementioned array and returns the right
> factor.
>
> If no factor is found, the lowest possible factor is returned,
> mimicking the same flow as all of the old per-SoC calculation
> functions.
>
> This commit brings no functional change.

After fix conflicts, applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 103 +++++++++++++++--------------
>  1 file changed, 52 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index fc937490feda..41fdc193891a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -118,9 +118,15 @@ struct mtk_dpi_yc_limit {
>         u16 c_bottom;
>  };
>
> +struct mtk_dpi_factor {
> +       u32 clock;
> +       u8 factor;
> +};
> +
>  /**
>   * struct mtk_dpi_conf - Configuration of mediatek dpi.
> - * @cal_factor: Callback function to calculate factor value.
> + * @dpi_factor: SoC-specific pixel clock PLL factor values.
> + * @num_dpi_factor: Number of pixel clock PLL factor values.
>   * @reg_h_fre_con: Register address of frequency control.
>   * @max_clock_khz: Max clock frequency supported for this SoCs in khz units.
>   * @edge_sel_en: Enable of edge selection.
> @@ -141,7 +147,8 @@ struct mtk_dpi_yc_limit {
>   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
>   */
>  struct mtk_dpi_conf {
> -       unsigned int (*cal_factor)(int clock);
> +       const struct mtk_dpi_factor *dpi_factor;
> +       const u8 num_dpi_factor;
>         u32 reg_h_fre_con;
>         u32 max_clock_khz;
>         bool edge_sel_en;
> @@ -516,6 +523,20 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
>         return ret;
>  }
>
> +static unsigned int mtk_dpi_calculate_factor(struct mtk_dpi *dpi, int mode_clk)
> +{
> +       const struct mtk_dpi_factor *dpi_factor = dpi->conf->dpi_factor;
> +       int i;
> +
> +       for (i = 0; i < dpi->conf->num_dpi_factor; i++) {
> +               if (mode_clk <= dpi_factor[i].clock)
> +                       return dpi_factor[i].factor;
> +       }
> +
> +       /* If no match try the lowest possible factor */
> +       return dpi_factor[dpi->conf->num_dpi_factor - 1].factor;
> +}
> +
>  static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>                                     struct drm_display_mode *mode)
>  {
> @@ -530,7 +551,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>         unsigned int factor;
>
>         /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
> -       factor = dpi->conf->cal_factor(mode->clock);
> +       factor = mtk_dpi_calculate_factor(dpi, mode_clk);
>         drm_display_mode_to_videomode(mode, &vm);
>         pll_rate = vm.pixelclock * factor;
>
> @@ -965,48 +986,6 @@ static const struct component_ops mtk_dpi_component_ops = {
>         .unbind = mtk_dpi_unbind,
>  };
>
> -static unsigned int mt8173_calculate_factor(int clock)
> -{
> -       if (clock <= 27000)
> -               return 3 << 4;
> -       else if (clock <= 84000)
> -               return 3 << 3;
> -       else if (clock <= 167000)
> -               return 3 << 2;
> -       else
> -               return 3 << 1;
> -}
> -
> -static unsigned int mt2701_calculate_factor(int clock)
> -{
> -       if (clock <= 64000)
> -               return 4;
> -       else if (clock <= 128000)
> -               return 2;
> -       else
> -               return 1;
> -}
> -
> -static unsigned int mt8183_calculate_factor(int clock)
> -{
> -       if (clock <= 27000)
> -               return 8;
> -       else if (clock <= 167000)
> -               return 4;
> -       else
> -               return 2;
> -}
> -
> -static unsigned int mt8195_dpintf_calculate_factor(int clock)
> -{
> -       if (clock < 70000)
> -               return 4;
> -       else if (clock < 200000)
> -               return 2;
> -       else
> -               return 1;
> -}
> -
>  static const u32 mt8173_output_fmts[] = {
>         MEDIA_BUS_FMT_RGB888_1X24,
>  };
> @@ -1021,8 +1000,25 @@ static const u32 mt8195_output_fmts[] = {
>         MEDIA_BUS_FMT_YUYV8_1X16,
>  };
>
> +static const struct mtk_dpi_factor dpi_factor_mt2701[] = {
> +       { 64000, 4 }, { 128000, 2 }, { U32_MAX, 1 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8173[] = {
> +       { 27000, 48 }, { 84000, 24 }, { 167000, 12 }, { U32_MAX, 6 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8183[] = {
> +       { 27000, 8 }, { 167000, 4 }, { U32_MAX, 2 }
> +};
> +
> +static const struct mtk_dpi_factor dpi_factor_mt8195_dp_intf[] = {
> +       { 70000 - 1, 4 }, { 200000 - 1, 2 }, { U32_MAX, 1 }
> +};
> +
>  static const struct mtk_dpi_conf mt8173_conf = {
> -       .cal_factor = mt8173_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8173,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8173),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 300000,
>         .output_fmts = mt8173_output_fmts,
> @@ -1039,7 +1035,8 @@ static const struct mtk_dpi_conf mt8173_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt2701_conf = {
> -       .cal_factor = mt2701_calculate_factor,
> +       .dpi_factor = dpi_factor_mt2701,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt2701),
>         .reg_h_fre_con = 0xb0,
>         .edge_sel_en = true,
>         .max_clock_khz = 150000,
> @@ -1057,7 +1054,8 @@ static const struct mtk_dpi_conf mt2701_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8183_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 100000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1074,7 +1072,8 @@ static const struct mtk_dpi_conf mt8183_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8186_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 150000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1092,7 +1091,8 @@ static const struct mtk_dpi_conf mt8186_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8192_conf = {
> -       .cal_factor = mt8183_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8183,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8183),
>         .reg_h_fre_con = 0xe0,
>         .max_clock_khz = 150000,
>         .output_fmts = mt8183_output_fmts,
> @@ -1109,7 +1109,8 @@ static const struct mtk_dpi_conf mt8192_conf = {
>  };
>
>  static const struct mtk_dpi_conf mt8195_dpintf_conf = {
> -       .cal_factor = mt8195_dpintf_calculate_factor,
> +       .dpi_factor = dpi_factor_mt8195_dp_intf,
> +       .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf),
>         .max_clock_khz = 600000,
>         .output_fmts = mt8195_output_fmts,
>         .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
> --
> 2.48.1
>


From chunkuang.hu at kernel.org  Sun Mar  2 03:06:53 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:06:53 +0800
Subject: [PATCH v7 05/43] drm/mediatek: mtk_dpi: Add checks for
 reg_h_fre_con existence
In-Reply-To: <20250217154836.108895-6-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-6-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_8BgMwzxa8N-LfwF2E0R0fp390aTc-w320DdeuOrUb=LQ@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> In preparation for adding support for newer DPI instances which
> do support direct-pin but do not have any H_FRE_CON register,
> like the one found in MT8195 and MT8188, add a branch to check
> if the reg_h_fre_con variable was declared in the mtk_dpi_conf
> structure for the probed SoC DPI version.
>
> As a note, this is useful specifically only for cases in which
> the support_direct_pin variable is true, so mt8195-dpintf is
> not affected by any issue.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 59c2e4f32a61..bb1a17f1384b 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -431,12 +431,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
>
>  static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
>  {
> -       mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
> +       if (dpi->conf->reg_h_fre_con)
> +               mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
>  }
>
>  static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
>  {
> -       if (dpi->conf->edge_sel_en)
> +       if (dpi->conf->edge_sel_en && dpi->conf->reg_h_fre_con)
>                 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
>  }
>
> --
> 2.48.1
>


From chunkuang.hu at kernel.org  Sun Mar  2 03:08:08 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:08:08 +0800
Subject: [PATCH v7 04/43] drm/mediatek: mtk_dpi: Move pixel clock setting
 flow to function
In-Reply-To: <20250217154836.108895-5-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-5-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY__DqCA3+-nsi7+svqHTbjdpTU5+8yDqWwNMnU8V=euQbQ@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> In preparation for adding support for the DPI IP found in MT8195
> and in MT8188 used for HDMI, move the code flow for calculation
> and setting of the DPI pixel clock to a separate function called
> mtk_dpi_set_pixel_clk().
>
> This was done because, on those platforms, the DPI instance that
> is used for HDMI will get its pixel clock from the HDMI clock,
> hence it is not necessary, nor desirable, to calculate or set
> the pixel clock in DPI.

After fix conflicts, applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 43 +++++++++++++++++-------------
>  1 file changed, 24 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 41fdc193891a..59c2e4f32a61 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -537,26 +537,17 @@ static unsigned int mtk_dpi_calculate_factor(struct mtk_dpi *dpi, int mode_clk)
>         return dpi_factor[dpi->conf->num_dpi_factor - 1].factor;
>  }
>
> -static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
> -                                   struct drm_display_mode *mode)
> +static void mtk_dpi_set_pixel_clk(struct mtk_dpi *dpi, struct videomode *vm, int mode_clk)
>  {
> -       struct mtk_dpi_polarities dpi_pol;
> -       struct mtk_dpi_sync_param hsync;
> -       struct mtk_dpi_sync_param vsync_lodd = { 0 };
> -       struct mtk_dpi_sync_param vsync_leven = { 0 };
> -       struct mtk_dpi_sync_param vsync_rodd = { 0 };
> -       struct mtk_dpi_sync_param vsync_reven = { 0 };
> -       struct videomode vm = { 0 };
>         unsigned long pll_rate;
>         unsigned int factor;
>
>         /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
>         factor = mtk_dpi_calculate_factor(dpi, mode_clk);
> -       drm_display_mode_to_videomode(mode, &vm);
> -       pll_rate = vm.pixelclock * factor;
> +       pll_rate = vm->pixelclock * factor;
>
>         dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",
> -               pll_rate, vm.pixelclock);
> +               pll_rate, vm->pixelclock);
>
>         clk_set_rate(dpi->tvd_clk, pll_rate);
>         pll_rate = clk_get_rate(dpi->tvd_clk);
> @@ -566,20 +557,34 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>          * pixels for each iteration: divide the clock by this number and
>          * adjust the display porches accordingly.
>          */
> -       vm.pixelclock = pll_rate / factor;
> -       vm.pixelclock /= dpi->conf->pixels_per_iter;
> +       vm->pixelclock = pll_rate / factor;
> +       vm->pixelclock /= dpi->conf->pixels_per_iter;
>
>         if ((dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE) ||
>             (dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_BE))
> -               clk_set_rate(dpi->pixel_clk, vm.pixelclock * 2);
> +               clk_set_rate(dpi->pixel_clk, vm->pixelclock * 2);
>         else
> -               clk_set_rate(dpi->pixel_clk, vm.pixelclock);
> +               clk_set_rate(dpi->pixel_clk, vm->pixelclock);
>
> -
> -       vm.pixelclock = clk_get_rate(dpi->pixel_clk);
> +       vm->pixelclock = clk_get_rate(dpi->pixel_clk);
>
>         dev_dbg(dpi->dev, "Got  PLL %lu Hz, pixel clock %lu Hz\n",
> -               pll_rate, vm.pixelclock);
> +               pll_rate, vm->pixelclock);
> +}
> +
> +static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
> +                                   struct drm_display_mode *mode)
> +{
> +       struct mtk_dpi_polarities dpi_pol;
> +       struct mtk_dpi_sync_param hsync;
> +       struct mtk_dpi_sync_param vsync_lodd = { 0 };
> +       struct mtk_dpi_sync_param vsync_leven = { 0 };
> +       struct mtk_dpi_sync_param vsync_rodd = { 0 };
> +       struct mtk_dpi_sync_param vsync_reven = { 0 };
> +       struct videomode vm = { 0 };
> +
> +       drm_display_mode_to_videomode(mode, &vm);
> +       mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock);
>
>         dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING;
>         dpi_pol.de_pol = MTK_DPI_POLARITY_RISING;
> --
> 2.48.1
>


From chunkuang.hu at kernel.org  Sun Mar  2 03:14:48 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:14:48 +0800
Subject: [PATCH v7 06/43] drm/mediatek: mtk_dpi: Move the input_2p_en bit
 to platform data
In-Reply-To: <20250217154836.108895-7-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-7-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_8ztRjpES-JVYeznG6ZjutYiifQSX3poyZoSqbqXYJ+aw@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> In preparation for adding support for MT8195's HDMI reserved DPI
> instance, move the input_2p_en bit for DP_INTF to platform data.
>
> While at it, remove the input_2pixel member from platform data as
> having this bit implies that the 2pixel feature must be enabled.

Remember to run check patch, after fix check patch error, applied to
mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index bb1a17f1384b..9a6c0f75f764 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -135,14 +135,14 @@ struct mtk_dpi_factor {
>   * @is_ck_de_pol: Support CK/DE polarity.
>   * @swap_input_support: Support input swap function.
>   * @support_direct_pin: IP supports direct connection to dpi panels.
> - * @input_2pixel: Input pixel of dp_intf is 2 pixel per round, so enable this
> - *               config to enable this feature.
>   * @dimension_mask: Mask used for HWIDTH, HPORCH, VSYNC_WIDTH and VSYNC_PORCH
>   *                 (no shift).
>   * @hvsize_mask: Mask of HSIZE and VSIZE mask (no shift).
>   * @channel_swap_shift: Shift value of channel swap.
>   * @yuv422_en_bit: Enable bit of yuv422.
>   * @csc_enable_bit: Enable bit of CSC.
> + * @input_2p_en_bit: Enable bit for input two pixel per round feature.
> +                     If present, implies that the feature must be enabled.
>   * @pixels_per_iter: Quantity of transferred pixels per iteration.
>   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
>   */
> @@ -157,12 +157,12 @@ struct mtk_dpi_conf {
>         bool is_ck_de_pol;
>         bool swap_input_support;
>         bool support_direct_pin;
> -       bool input_2pixel;
>         u32 dimension_mask;
>         u32 hvsize_mask;
>         u32 channel_swap_shift;
>         u32 yuv422_en_bit;
>         u32 csc_enable_bit;
> +       u32 input_2p_en_bit;
>         u32 pixels_per_iter;
>         bool edge_cfg_in_mmsys;
>  };
> @@ -651,9 +651,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>                 mtk_dpi_dual_edge(dpi);
>                 mtk_dpi_config_disable_edge(dpi);
>         }
> -       if (dpi->conf->input_2pixel) {
> -               mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN,
> -                            DPINTF_INPUT_2P_EN);
> +       if (dpi->conf->input_2p_en_bit) {
> +               mtk_dpi_mask(dpi, DPI_CON, dpi->conf->input_2p_en_bit,
> +                            dpi->conf->input_2p_en_bit);
>         }
>         mtk_dpi_sw_reset(dpi, false);
>
> @@ -1121,12 +1121,12 @@ static const struct mtk_dpi_conf mt8195_dpintf_conf = {
>         .output_fmts = mt8195_output_fmts,
>         .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
>         .pixels_per_iter = 4,
> -       .input_2pixel = true,
>         .dimension_mask = DPINTF_HPW_MASK,
>         .hvsize_mask = DPINTF_HSIZE_MASK,
>         .channel_swap_shift = DPINTF_CH_SWAP,
>         .yuv422_en_bit = DPINTF_YUV422_EN,
>         .csc_enable_bit = DPINTF_CSC_ENABLE,
> +       .input_2p_en_bit = DPINTF_INPUT_2P_EN,
>  };
>
>  static int mtk_dpi_probe(struct platform_device *pdev)
> --
> 2.48.1
>


From jonas at kwiboo.se  Sun Mar  2 03:14:48 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 2 Mar 2025 12:14:48 +0100
Subject: [PATCH 4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for
 RK3528
In-Reply-To: <Z8GT3rUEyXrTUgtJ@pie.lan>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
 <20250228064024.3200000-5-jonas@kwiboo.se> <Z8GT3rUEyXrTUgtJ@pie.lan>
Message-ID: <3f0cd767-1fd8-4c65-b8b4-e948288cd02a@kwiboo.se>

Hi Yao Zi,

On 2025-02-28 11:46, Yao Zi wrote:
> On Fri, Feb 28, 2025 at 06:40:10AM +0000, Jonas Karlman wrote:
>> Add pinctrl and gpio nodes for RK3528 and import rk3528-pinctrl.dtsi
>> from vendor linux-6.1-stan-rkr5 kernel with the hdmi-pins-idle node
>> removed due to missing label reference to pcfg_output_low_pull_down.
>>
>> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
>> ---
>> This was mostly imported from vendor kernel, however the main commit [1]
>> list 28 signed-off-by tags, unclear who I should use as author and what
>> signed-off-by tags to include.
>>
>> [1] https://github.com/rockchip-linux/kernel/commit/c17d6325959f0ec1af901e8a17919163454190a2
>> ---
>>  .../boot/dts/rockchip/rk3528-pinctrl.dtsi     | 1397 +++++++++++++++++
>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi      |   82 +
>>  2 files changed, 1479 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi
>>
> 
>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>> index 0fb90f5c291c..d3e2a64ff2d5 100644
>> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>> @@ -4,8 +4,10 @@
>>   * Copyright (c) 2024 Yao Zi <ziyao at disroot.org>
>>   */
>>  
>> +#include <dt-bindings/gpio/gpio.h>
>>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>>  #include <dt-bindings/interrupt-controller/irq.h>
>> +#include <dt-bindings/pinctrl/rockchip.h>
>>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
>>  #include <dt-bindings/reset/rockchip,rk3528-cru.h>
>>  
>> @@ -17,6 +19,11 @@ / {
>>  	#size-cells = <2>;
>>  
>>  	aliases {
>> +		gpio0 = &gpio0;
>> +		gpio1 = &gpio1;
>> +		gpio2 = &gpio2;
>> +		gpio3 = &gpio3;
>> +		gpio4 = &gpio4;
>>  		serial0 = &uart0;
>>  		serial1 = &uart1;
>>  		serial2 = &uart2;
>> @@ -166,6 +173,11 @@ cru: clock-controller at ff4a0000 {
>>  			#reset-cells = <1>;
>>  		};
>>  
>> +		ioc_grf: syscon at ff540000 {
>> +			compatible = "rockchip,rk3528-ioc-grf", "syscon";
>> +			reg = <0x0 0xff540000 0x0 0x40000>;
>> +		};
>> +
>>  		uart0: serial at ff9f0000 {
>>  			compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
>>  			reg = <0x0 0xff9f0000 0x0 0x100>;
>> @@ -264,5 +276,75 @@ saradc: adc at ffae0000 {
>>  			#io-channel-cells = <1>;
>>  			status = "disabled";
>>  		};
>> +
>> +		pinctrl: pinctrl {
>> +			compatible = "rockchip,rk3528-pinctrl";
>> +			rockchip,grf = <&ioc_grf>;
>> +			#address-cells = <2>;
>> +			#size-cells = <2>;
>> +			ranges;
> 
> I doubt whether the pincontroller should be placed under simple-bus:
> without a reg property, it doesn't look like a MMIO device.
> 
> Actually it is, although all the registers stay in the ioc grf. Maybe
> it should be considered as child of the grf.

This follows how pinctrl was added for RK3576 and what is proposed for
RK3562 [2]. I have too little knowledge to know if this needs to change
or if this should follow similar SoCs.

[2] https://lore.kernel.org/r/20250227111913.2344207-15-kever.yang at rock-chips.com

Regards,
Jonas

> 
> Best regards,
> Yao Zi



From chunkuang.hu at kernel.org  Sun Mar  2 03:24:02 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:24:02 +0800
Subject: [PATCH v7 07/43] drm/mediatek: mtk_dpi: Add support for DPI input
 clock from HDMI
In-Reply-To: <20250217154836.108895-8-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-8-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_8LmRTabeuwXnwDxxodiPRkRD4P9diCO=5CHrwtT4h2QA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> On some SoCs, like MT8195 and MT8188, the DPI instance that is
> reserved to the HDMI Transmitter uses a different clock topology.
>
> In this case, the DPI is clocked by the HDMI IP, and this outputs
> its clock to the MM input of dpi_pixel_clk, which is essential to
> enable register access to the DPI IP.
>
> Add a `clocked_by_hdmi` member to struct mtk_dpi_conf, and check
> it to avoid enabling the DPI clocks in the mediatek-drm internal
> .start() callback (and avoid disabing in the .stop() component
> callback): this will make sure that the clock configuration
> sequence is respected during display pipeline setup by following
> the bridge ops between DPI and HDMI, where the HDMI driver is
> expected to enable the clocks in the bridge's pre_enable(), and
> DPI in the enable() cb.

After fix conflicts, applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 9a6c0f75f764..9f83e82437dd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -145,6 +145,8 @@ struct mtk_dpi_factor {
>                       If present, implies that the feature must be enabled.
>   * @pixels_per_iter: Quantity of transferred pixels per iteration.
>   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
> + * @clocked_by_hdmi: HDMI IP outputs clock to dpi_pixel_clk input clock, needed
> + *                  for DPI registers access.
>   */
>  struct mtk_dpi_conf {
>         const struct mtk_dpi_factor *dpi_factor;
> @@ -165,6 +167,7 @@ struct mtk_dpi_conf {
>         u32 input_2p_en_bit;
>         u32 pixels_per_iter;
>         bool edge_cfg_in_mmsys;
> +       bool clocked_by_hdmi;
>  };
>
>  static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
> @@ -585,7 +588,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>         struct videomode vm = { 0 };
>
>         drm_display_mode_to_videomode(mode, &vm);
> -       mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock);
> +
> +       if (!dpi->conf->clocked_by_hdmi)
> +               mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock);
>
>         dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING;
>         dpi_pol.de_pol = MTK_DPI_POLARITY_RISING;
> @@ -920,14 +925,16 @@ void mtk_dpi_start(struct device *dev)
>  {
>         struct mtk_dpi *dpi = dev_get_drvdata(dev);
>
> -       mtk_dpi_power_on(dpi);
> +       if (!dpi->conf->clocked_by_hdmi)
> +               mtk_dpi_power_on(dpi);
>  }
>
>  void mtk_dpi_stop(struct device *dev)
>  {
>         struct mtk_dpi *dpi = dev_get_drvdata(dev);
>
> -       mtk_dpi_power_off(dpi);
> +       if (!dpi->conf->clocked_by_hdmi)
> +               mtk_dpi_power_off(dpi);
>  }
>
>  unsigned int mtk_dpi_encoder_index(struct device *dev)
> --
> 2.48.1
>


From chunkuang.hu at kernel.org  Sun Mar  2 03:29:13 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 19:29:13 +0800
Subject: [PATCH v7 08/43] drm/mediatek: mtk_dpi: Support AFIFO 1T1P output
 and conversion
In-Reply-To: <20250217154836.108895-9-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-9-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY_8kxxaj+jum6CkJGHKrpjiX_cNt4FT345yET8GWR2QSFA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> On some SoCs, like MT8195 and MT8188, the DPI's FIFO controller
> (afifo) supports outputting either one or two pixels per round
> regardless of the input being 1T1P or 1T2P.
>
> Add a `output_1pixel` member to struct mtk_dpi_conf which, if
> set, will enable outputting one pixel per clock.
>
> In case the input is two pixel per clock (1T2P), the AFIFO HW
> will automatically (and internally) convert it to 1T1P.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 9f83e82437dd..e12dc73ed79c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -147,6 +147,8 @@ struct mtk_dpi_factor {
>   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
>   * @clocked_by_hdmi: HDMI IP outputs clock to dpi_pixel_clk input clock, needed
>   *                  for DPI registers access.
> + * @output_1pixel: Enable outputting one pixel per round; if the input is two pixel per
> + *                 round, the DPI hardware will internally transform it to 1T1P.
>   */
>  struct mtk_dpi_conf {
>         const struct mtk_dpi_factor *dpi_factor;
> @@ -168,6 +170,7 @@ struct mtk_dpi_conf {
>         u32 pixels_per_iter;
>         bool edge_cfg_in_mmsys;
>         bool clocked_by_hdmi;
> +       bool output_1pixel;
>  };
>
>  static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
> @@ -653,7 +656,13 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>         if (dpi->conf->support_direct_pin) {
>                 mtk_dpi_config_yc_map(dpi, dpi->yc_map);
>                 mtk_dpi_config_2n_h_fre(dpi);
> -               mtk_dpi_dual_edge(dpi);
> +
> +               /* DPI can connect to either an external bridge or the internal HDMI encoder */
> +               if (dpi->conf->output_1pixel)
> +                       mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN);
> +               else
> +                       mtk_dpi_dual_edge(dpi);
> +
>                 mtk_dpi_config_disable_edge(dpi);
>         }
>         if (dpi->conf->input_2p_en_bit) {
> --
> 2.48.1
>


From jonas at kwiboo.se  Sun Mar  2 03:33:53 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 2 Mar 2025 12:33:53 +0100
Subject: [PATCH 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for
 RK3528
In-Reply-To: <Z8MMm7X31p_CrStZ@pie>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104749.36423-1-ziyao@disroot.org>
 <9fd51bcb-3e6a-46b6-b1f7-ff16fa562d9e@kwiboo.se> <Z8MMm7X31p_CrStZ@pie>
Message-ID: <b92c0f59-c721-4e91-ac41-267a81758916@kwiboo.se>

Hi Yao Zi,

On 2025-03-01 14:33, Yao Zi wrote:
> On Sat, Mar 01, 2025 at 01:47:47PM +0100, Jonas Karlman wrote:
>> Hi,
>>
>> On 2025-03-01 11:47, Yao Zi wrote:
>>> RK3528 features two SDIO controllers and one SD/MMC controller, describe
>>> them in devicetree. Since their sample and drive clocks are located in
>>> the VO and VPU GRFs, corresponding syscons are added to make these
>>> clocks available.
>>>
>>> Signed-off-by: Yao Zi <ziyao at disroot.org>
>>> ---
>>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 62 ++++++++++++++++++++++++
>>>  1 file changed, 62 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> index 5b334690356a..078c97fa1d9f 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> @@ -7,6 +7,7 @@
>>>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>>>  #include <dt-bindings/interrupt-controller/irq.h>
>>>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
>>> +#include <dt-bindings/reset/rockchip,rk3528-cru.h>
>>>  
>>>  / {
>>>  	compatible = "rockchip,rk3528";
>>> @@ -122,6 +123,16 @@ gic: interrupt-controller at fed01000 {
>>>  			#interrupt-cells = <3>;
>>>  		};
>>>  
>>> +		vpu_grf: syscon at ff340000 {
>>> +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
>>
>> vpu_grf is also used for gmac1, so should possible be a "syscon",
>> "simple-mfd", or have I misunderstood when to use simple-mfd ?
> 
> Just as Heiko explained, "simple-mfd" is only required when the child
> nodes should be populated automatically. Here these two GRFs are only
> referenced and have no child, thus "simple-mfd" compatible isn't useful.

Thanks for the explanations.

> 
>>> +			reg = <0x0 0xff340000 0x0 0x8000>;
>>> +		};
>>> +
>>> +		vo_grf: syscon at ff360000 {
>>> +			compatible = "rockchip,rk3528-vo-grf", "syscon";
>>
>> similar here, vo_grf is also used for gmac0.
>>
>>> +			reg = <0x0 0xff360000 0x0 0x10000>;
>>> +		};
>>> +
>>>  		cru: clock-controller at ff4a0000 {
>>>  			compatible = "rockchip,rk3528-cru";
>>>  			reg = <0x0 0xff4a0000 0x0 0x30000>;
>>> @@ -251,5 +262,56 @@ uart7: serial at ffa28000 {
>>>  			reg-shift = <2>;
>>>  			status = "disabled";
>>>  		};
>>> +
>>> +		sdio0: mmc at ffc10000 {
>>> +			compatible = "rockchip,rk3528-dw-mshc",
>>> +				     "rockchip,rk3288-dw-mshc";
>>> +			reg = <0x0 0xffc10000 0x0 0x4000>;
>>> +			clocks = <&cru HCLK_SDIO0>,
>>> +				 <&cru CCLK_SRC_SDIO0>,
>>> +				 <&cru SCLK_SDIO0_DRV>,
>>> +				 <&cru SCLK_SDIO0_SAMPLE>;
>>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
>>> +			fifo-depth = <0x100>;
>>> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
>>> +			max-frequency = <150000000>;
>>> +			resets = <&cru SRST_H_SDIO0>;
>>> +			reset-names = "reset";
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		sdio1: mmc at ffc20000 {
>>> +			compatible = "rockchip,rk3528-dw-mshc",
>>> +				     "rockchip,rk3288-dw-mshc";
>>> +			reg = <0x0 0xffc20000 0x0 0x4000>;
>>> +			clocks = <&cru HCLK_SDIO1>,
>>> +				 <&cru CCLK_SRC_SDIO1>,
>>> +				 <&cru SCLK_SDIO1_DRV>,
>>> +				 <&cru SCLK_SDIO1_SAMPLE>;
>>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
>>> +			fifo-depth = <0x100>;
>>> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
>>> +			max-frequency = <150000000>;
>>> +			resets = <&cru SRST_H_SDIO1>;
>>> +			reset-names = "reset";
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		sdmmc: mmc at ffc30000 {
>>> +			compatible = "rockchip,rk3528-dw-mshc",
>>> +				     "rockchip,rk3288-dw-mshc";
>>> +			reg = <0x0 0xffc30000 0x0 0x4000>;
>>> +			clocks = <&cru HCLK_SDMMC0>,
>>> +				 <&cru CCLK_SRC_SDMMC0>,
>>> +				 <&cru SCLK_SDMMC_DRV>,
>>> +				 <&cru SCLK_SDMMC_SAMPLE>;
>>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
>>> +			fifo-depth = <0x100>;
>>> +			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
>>> +			max-frequency = <150000000>;
>>> +			resets = <&cru SRST_H_SDMMC0>;
>>> +			reset-names = "reset";
>>
>> Suggest adding default pinctrl props here:
>>
>>   pinctrl-names = "default";
>>   pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_det>;
>>
>> And possible also for sdio0 and sdio1.
>>
>> Regards,
>> Jonas
> 
> It makes sense. As mentioned in the cover letter, I depended on the
> bootloader to setup pinctrl, to minimize dependency of the series.

BootROM typically setup pinctrl for the storage media when probing for
idblock and mainline U-Boot will setup pinctrl based on the board device
tree synced from Linux. Adding pinctrl early in Linux will help avoid a
need for using workarounds in U-Boot.

For RK3528 there only seem to be one option for sdmmc/sdio pins, adding
a default to soc dtsi should help reduce duplication in future board
device trees.

> 
> Will complete the pinctrl properties in next version.

Thanks :-)

Regards,
Jonas

> 
>>> +			status = "disabled";
>>> +		};
>>>  	};
>>>  };
>>
> 
> Best regards,
> Yao Zi



From sven at svenpeter.dev  Sun Mar  2 03:38:42 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sun,  2 Mar 2025 12:38:42 +0100
Subject: [GIT PULL] Apple SoC RTKit IPC library updates for v6.15
Message-ID: <20250302113842.58092-1-sven@svenpeter.dev>

Hi,

Please merge these Apple SoC RTKit IPC library updates for v6.15.
This batch includes a bunch of minor improvements and bugfixes mostly
required for our downstream drivers (e.g. DCP) which we are planning to
upstream in the next months.
There's one API change which requires a single line adjustment to our
NVMe driver as well which has been reviewed by a NVMe maintainer.


Best,


Sven

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://github.com/AsahiLinux/linux.git tags/asahi-soc-rtkit-6.15

for you to fetch changes up to e210227f0259d2666cc41b28ed1b7b0b0a99ed4d:

  soc: apple: rtkit: Cut syslog messages after the first '\0' (2025-02-28 21:36:45 +0000)

----------------------------------------------------------------
Apple SoC RTKit IPC library updates for 6.15:

- Additional logging for errors
- A few minor improvements and bugfixes required for drivers that are
  yet to be upstreamed

----------------------------------------------------------------
Asahi Lina (2):
      soc: apple: rtkit: Check & log more failures
      soc: apple: rtkit: Pass the crashlog to the crashed() callback

Harshit Mogalapalli (1):
      soc: apple: rtkit: Fix use-after-free in apple_rtkit_crashlog_rx()

Hector Martin (1):
      soc: apple: rtkit: Implement OSLog buffers properly

Janne Grunau (3):
      soc: apple: rtkit: Add and use PWR_STATE_INIT instead of _ON
      soc: apple: rtkit: Use high prio work queue
      soc: apple: rtkit: Cut syslog messages after the first '\0'

 drivers/nvme/host/apple.c          |   2 +-
 drivers/soc/apple/rtkit-internal.h |   1 +
 drivers/soc/apple/rtkit.c          | 112 +++++++++++++++++++++++++------------
 include/linux/soc/apple/rtkit.h    |   2 +-
 4 files changed, 78 insertions(+), 39 deletions(-)


From heiko at sntech.de  Sun Mar  2 03:52:18 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sun, 02 Mar 2025 12:52:18 +0100
Subject: [PATCH 4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
In-Reply-To: <3f0cd767-1fd8-4c65-b8b4-e948288cd02a@kwiboo.se>
References: <20250228064024.3200000-1-jonas@kwiboo.se> <Z8GT3rUEyXrTUgtJ@pie.lan>
 <3f0cd767-1fd8-4c65-b8b4-e948288cd02a@kwiboo.se>
Message-ID: <116104909.nniJfEyVGO@diego>

Am Sonntag, 2. M?rz 2025, 12:14:48 MEZ schrieb Jonas Karlman:
> Hi Yao Zi,
> 
> On 2025-02-28 11:46, Yao Zi wrote:
> > On Fri, Feb 28, 2025 at 06:40:10AM +0000, Jonas Karlman wrote:
> >> Add pinctrl and gpio nodes for RK3528 and import rk3528-pinctrl.dtsi
> >> from vendor linux-6.1-stan-rkr5 kernel with the hdmi-pins-idle node
> >> removed due to missing label reference to pcfg_output_low_pull_down.
> >>
> >> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> >> ---
> >> This was mostly imported from vendor kernel, however the main commit [1]
> >> list 28 signed-off-by tags, unclear who I should use as author and what
> >> signed-off-by tags to include.
> >>
> >> [1] https://github.com/rockchip-linux/kernel/commit/c17d6325959f0ec1af901e8a17919163454190a2
> >> ---
> >>  .../boot/dts/rockchip/rk3528-pinctrl.dtsi     | 1397 +++++++++++++++++
> >>  arch/arm64/boot/dts/rockchip/rk3528.dtsi      |   82 +
> >>  2 files changed, 1479 insertions(+)
> >>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi
> >>
> > 
> >> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> >> index 0fb90f5c291c..d3e2a64ff2d5 100644
> >> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> >> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> >> @@ -4,8 +4,10 @@
> >>   * Copyright (c) 2024 Yao Zi <ziyao at disroot.org>
> >>   */
> >>  
> >> +#include <dt-bindings/gpio/gpio.h>
> >>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> >>  #include <dt-bindings/interrupt-controller/irq.h>
> >> +#include <dt-bindings/pinctrl/rockchip.h>
> >>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
> >>  #include <dt-bindings/reset/rockchip,rk3528-cru.h>
> >>  
> >> @@ -17,6 +19,11 @@ / {
> >>  	#size-cells = <2>;
> >>  
> >>  	aliases {
> >> +		gpio0 = &gpio0;
> >> +		gpio1 = &gpio1;
> >> +		gpio2 = &gpio2;
> >> +		gpio3 = &gpio3;
> >> +		gpio4 = &gpio4;
> >>  		serial0 = &uart0;
> >>  		serial1 = &uart1;
> >>  		serial2 = &uart2;
> >> @@ -166,6 +173,11 @@ cru: clock-controller at ff4a0000 {
> >>  			#reset-cells = <1>;
> >>  		};
> >>  
> >> +		ioc_grf: syscon at ff540000 {
> >> +			compatible = "rockchip,rk3528-ioc-grf", "syscon";
> >> +			reg = <0x0 0xff540000 0x0 0x40000>;
> >> +		};
> >> +
> >>  		uart0: serial at ff9f0000 {
> >>  			compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
> >>  			reg = <0x0 0xff9f0000 0x0 0x100>;
> >> @@ -264,5 +276,75 @@ saradc: adc at ffae0000 {
> >>  			#io-channel-cells = <1>;
> >>  			status = "disabled";
> >>  		};
> >> +
> >> +		pinctrl: pinctrl {
> >> +			compatible = "rockchip,rk3528-pinctrl";
> >> +			rockchip,grf = <&ioc_grf>;
> >> +			#address-cells = <2>;
> >> +			#size-cells = <2>;
> >> +			ranges;
> > 
> > I doubt whether the pincontroller should be placed under simple-bus:
> > without a reg property, it doesn't look like a MMIO device.
> > 
> > Actually it is, although all the registers stay in the ioc grf. Maybe
> > it should be considered as child of the grf.
> 
> This follows how pinctrl was added for RK3576 and what is proposed for
> RK3562 [2]. I have too little knowledge to know if this needs to change
> or if this should follow similar SoCs.
> 
> [2] https://lore.kernel.org/r/20250227111913.2344207-15-kever.yang at rock-chips.com

The reg address shouldn't matter here I think.

The "soc"-bus describes the elements contained in the soc (surrounding the
cpu cores) and the pinctrl controller definitly is part of the soc itself.

So when looking at the scope, it does belong there and also the
 gpio-controller elements do have mmio addresses :-)


Heiko




From andyshrk at 163.com  Sun Mar  2 03:52:25 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sun,  2 Mar 2025 19:52:25 +0800
Subject: [PATCH] phy: rockchip: usbdp: Avoid call hpd_event_trigger in dp_phy_init
Message-ID: <20250302115257.188774-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Function rk_udphy_dp_hpd_event_trigger will set vogrf let it
trigger HPD interrupt to DP by Type-C. This configuration is only
required when the DP work in Alternate Mode, and called by
typec_mux_set. In standard DP mode, such settings will prevent
the DP from receiving HPD interrupts.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 drivers/phy/rockchip/phy-rockchip-usbdp.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 5b1e8a3806ed..c04cf64f8a35 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1045,7 +1045,6 @@ static int rk_udphy_dp_phy_init(struct phy *phy)
 	mutex_lock(&udphy->mutex);
 
 	udphy->dp_in_use = true;
-	rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
 
 	mutex_unlock(&udphy->mutex);
 
-- 
2.34.1



From jonas at kwiboo.se  Sun Mar  2 03:56:42 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 2 Mar 2025 12:56:42 +0100
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <Z8MklJfFz2EA6oNS@pie.lan>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104835.36439-1-ziyao@disroot.org>
 <0aefd292-7980-434d-9c18-4ab9f6a0b40e@kwiboo.se> <Z8MklJfFz2EA6oNS@pie.lan>
Message-ID: <d6928adc-1df2-494f-a3d3-7b028c220547@kwiboo.se>

Hi Yao Zi,

On 2025-03-01 16:15, Yao Zi wrote:
> On Sat, Mar 01, 2025 at 02:01:05PM +0100, Jonas Karlman wrote:
>> Hi,
>>
>> On 2025-03-01 11:48, Yao Zi wrote:
>>> SD-card is available on Radxa E20C board.
>>>
>>> Signed-off-by: Yao Zi <ziyao at disroot.org>
>>> ---
>>>  arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 14 ++++++++++++++
>>>  1 file changed, 14 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
>>> index d2cdb63d4a9d..473065aa4228 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
>>> @@ -12,6 +12,10 @@ / {
>>>  	model = "Radxa E20C";
>>>  	compatible = "radxa,e20c", "rockchip,rk3528";
>>>  
>>> +	aliases {
>>> +		mmc0 = &sdmmc;
>>
>> Suggest using mmc1 for sd-card because the e20c typically have onboard
>> emmc, compared to removable sd-card.
> 
> My board doesn't have an eMMC: it's optional as well, but all variants
> of Radxa E20C come with an SD-card interface. The vendor devicetree sets
> sdmmc as mmc0 as well[1].

This is strange as Radxa typically want to align with mmc0=emmc and
mmc1=sd-card, as seen in [3] and [4].

  Align with other Radxa products.
  - mmc0 is eMMC
  - mmc1 is microSD

Also mainline U-Boot for Rockchip SoCs typically always treat mmc0 as
emmc and mmc1 as sd-card, and for most SoCs it will even override the
board aliases to have some predictability across boards.

> 
> I won't insist on it and am willing to take the change if you still
> consider mmc0 is better.

Yes, my position is that we should use following:

  mmc0 = &sdhci;
  mmc1 = &sdmmc;

I will send out a short sdhci series based on top of v2 of this series.
Driver changes was not needed to get basic sdhci working on RK3528 and
is only required to get HS400 modes working.

[3] https://lore.kernel.org/r/20240620224435.2752-1-naoki at radxa.com
[4] https://lore.kernel.org/r/20240619050047.1217-2-naoki at radxa.com

> 
>>> +	};
>>> +
>>>  	chosen {
>>>  		stdout-path = "serial0:1500000n8";
>>>  	};
>>> @@ -20,3 +24,13 @@ chosen {
>>>  &uart0 {
>>>  	status = "okay";
>>>  };
>>> +
>>> +&sdmmc {

This node should be placed above &uart0 to be in alphabetical order.

>>> +	bus-width = <4>;
>>> +	cap-mmc-highspeed;
>>> +	cap-sd-highspeed;
>>> +	disable-wp;
>>> +	rockchip,default-sample-phase = <90>;
>>> +	sd-uhs-sdr104;
>>
>> Are you sure uhs-sdr104 works as is should?
> 
> In fact yes, tuning succeeds at 148.5MHz and results in 66MB/s reading
> speed.
> 
>> Vendor kernel use a different "v2" tuning
> 
> This isn't a problem. IMHO V2 tuning is more like a quick path, which
> tries inheritting the phase from firmware and then re-tunes roughly.
> Fine tunning is still a fallback here in case of failure, see the commit
> message in the downstream kernel[2]. And testing proves it's okay for
> RK3528 to issue fine-tuning always.

Thanks for this information, I did not inspect exactly what the v2
tuning meant, only observed that vendor kernel (incorrectly) used a DT
prop to indicate when v2 tuning should be used.

> 
>> and this is also missing the vccio_sd vqmmc-supply to switch between
>> 3v3 and 1v8.
> 
> But this is a problem, thanks for catching it! Somehow my card managed
> to run at 148.5MHz with 3v3 voltage level, but it's definitely a
> compatiblity issue. I'm surprised that the driver doesn't complain when
> switching to SDR modes without a regulator configured.
> 
>> You could add following regulator for sdmmc:
>>
>> 	vccio_sd: regulator-vccio-sd {
>> 		compatible = "regulator-gpio";
>> 		gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
>> 		pinctrl-names = "default";
>> 		pinctrl-0 = <&sdmmc_vol_ctrl_h>;
>> 		regulator-name = "vccio_sd";
>> 		regulator-min-microvolt = <1800000>;
>> 		regulator-max-microvolt = <3300000>;
>> 		states = <1800000 0x0>, <3300000 0x1>;

This should also have something like:

  vin-supply = <&vcc5v0_sys>;

>> 	};
>>
>> and following pinctrl:
>>
>> 	sdmmc {
>> 		sdmmc_vol_ctrl_h: sdmmc-vol-ctrl-h {
>> 			rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
>> 		};
>> 	};
>>
>> add then the power supplies to the sdmmc node:
>>
>> 	vmmc-supply = <&vcc_3v3>;
>> 	vqmmc-supply = <&vccio_sd>;
>>
>> That matches the schematics for e20c, and works when testing non-uhs modes.
> 
> Thanks for the hints. Will rebase on your pinctrl series and get
> regulators and pinctrl settings applied in the next version.

Thanks :-)

Regards,
Jonas

> 
>> Regards,
>> Jonas
>>
>>> +	status = "okay";
>>> +};
>>
> 
> Cheers,
> Yao Zi
> 
> [1]: https://github.com/radxa/kernel/blob/2b0c8de7dc4c68947cda206dcc2e457e9677e426/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts#L22-L26
> [2]: https://github.com/rockchip-linux/kernel/commit/795e052cc8610aa59a64b104f975cc4a45493d5d



From sven at svenpeter.dev  Sun Mar  2 03:58:08 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sun,  2 Mar 2025 12:58:08 +0100
Subject: [GIT PULL] Second batch of Apple SoC DT updates for v6.15
Message-ID: <20250302115808.59172-1-sven@svenpeter.dev>

Hi,

this is the second batch of device tree updates for Apple SoCs based
on the first PR sent earlier [1].
This one adds nodes for SPI controller, SPI NOR flash and NVRAM partitions
for M1 and M2 devices. The SPI controller driver has been merged for a while
already and we just forgot to pick the device tree changes up.
It also adds the touchbar digitizer nodes. The corresponding driver and
dt-bindings are already in -next and should be part of the 6.15 merge window
as well.


Best,

Sven


[1] https://lore.kernel.org/soc/20250209135558.8243-1-sven at svenpeter.dev/

The following changes since commit ca96d759d8d24d90b1726c2cc7c568ff4728bb42:

  arm64: dts: apple: t8015: Add cpufreq nodes (2025-02-09 11:50:13 +0000)

are available in the Git repository at:

  https://github.com/AsahiLinux/linux.git tags/asahi-soc-dt-6.15-v2

for you to fetch changes up to 44db68dee1f77260d7037319e911e9883a6ffe0e:

  arm64: dts: apple: Add touchbar digitizer nodes (2025-02-26 15:33:46 +0000)

----------------------------------------------------------------
Apple SoC DT updates for 6.15, second batch:

- Added a missing p-state for iPad mini 4
- Added SPI controller nodes for M1 and M2 devices
- Added SPI NOR flash nodes and NVRAM partitions
- Added touchbar digitizer nodes for M1 and M2 devices

----------------------------------------------------------------
Hector Martin (1):
      arm64: dts: apple: t8103: Fix spi4 power domain sort order

Janne Grunau (4):
      arm64: dts: apple: t8103: Add spi controller nodes
      arm64: dts: apple: t8112: Add spi controller nodes
      arm64: dts: apple: t600x: Add spi controller nodes
      arm64: dts: apple: Add SPI NOR nvram partition to all devices

Nick Chan (1):
      arm64: dts: apple: t7000: Add missing CPU p-state 7 for J96 and J97

Sasha Finkelstein (1):
      arm64: dts: apple: Add touchbar digitizer nodes

 arch/arm64/boot/dts/apple/spi1-nvram.dtsi      | 39 +++++++++++++
 arch/arm64/boot/dts/apple/t600x-common.dtsi    |  7 +++
 arch/arm64/boot/dts/apple/t600x-die0.dtsi      | 28 ++++++++++
 arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi | 14 +++++
 arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi |  2 +
 arch/arm64/boot/dts/apple/t600x-j375.dtsi      |  2 +
 arch/arm64/boot/dts/apple/t7000-mini4.dtsi     |  4 ++
 arch/arm64/boot/dts/apple/t7000.dtsi           |  6 ++
 arch/arm64/boot/dts/apple/t8103-j293.dts       | 27 +++++++++
 arch/arm64/boot/dts/apple/t8103-jxxx.dtsi      |  2 +
 arch/arm64/boot/dts/apple/t8103-pmgr.dtsi      | 18 +++---
 arch/arm64/boot/dts/apple/t8103.dtsi           | 76 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/apple/t8112-j493.dts       | 23 ++++++++
 arch/arm64/boot/dts/apple/t8112-jxxx.dtsi      |  2 +
 arch/arm64/boot/dts/apple/t8112.dtsi           | 44 ++++++++++++++-
 15 files changed, 284 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm64/boot/dts/apple/spi1-nvram.dtsi


From andyshrk at 163.com  Sun Mar  2 04:01:38 2025
From: andyshrk at 163.com (Andy Yan)
Date: Sun, 2 Mar 2025 20:01:38 +0800 (CST)
Subject: [PATCH v15 00/13] VOP Support for rk3576
In-Reply-To: <20250218112744.34433-1-andyshrk@163.com>
References: <20250218112744.34433-1-andyshrk@163.com>
Message-ID: <5302ddd1.2591.19556bbbb3d.Coremail.andyshrk@163.com>


Hello Heiko?
     At your earliest convenience, could you kindly have a look whether this patch series is currently eligible for merge ? 
    I still hope it can land Linux 6.15 merge window. Please let me know if i need do some fix or rebase"
  
At 2025-02-18 19:27:27, "Andy Yan" <andyshrk at 163.com> wrote:
>From: Andy Yan <andy.yan at rock-chips.com>
>
>
>PATCH 1~9 are preparations for rk3576 support
>PATCH 10~13 are real support for rk376
>
>I test it with a 1080P/4K HDMI output with modetest and weston
>output.
>
>If there are some one want to have a try, I have a tree based on
>Linux 6.14-rc1 here[0]
>
>[0]https://github.com/andyshrk/linux/tree/rk3576-vop2-upstream-v14
>
>
>Changes in v15:
>- Remove AFBC/AFBCD prefix of TRANSFORM_OFFSET register
>- Remove redundant blank line before function vop2_lock
>- Fix nr_regs arguments for smart windows register.
>- Link to v14: https://lore.kernel.org/linux-rockchip/20250212093530.52961-1-andyshrk at 163.com/
>
>Changes in v14:
>- Rebase on drm-misc-next
>- Set maxItems constraint of clocks for rk3588 to 9 as a recently
>  merged patch added two optional clocks[0]:
>  [0]https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-1-d71c6a196e58 at collabora.com
>
>Changes in v13:
>- Add maxItems constraint for clocks
>- Remove constraint for interrupts in allOf block, as the current
>  maxItems is already 1.
>- typo fix
>- Explain the function of this property.
>- Use maxItems constraint for clocks in allOf block
>
>Changes in v12:
>- Only change the description method for existing SoC.
>- Split from patch 10/13
>- Split from patch 10/13
>
>Changes in v11:
>- Remove redundant min/maxItems constraint
>- Remove redundant min/maxItems constraint
>
>Changes in v10:
>- Move interrupt-names back to top level
>- Add constraint of interrupts for all platform
>- Add constraint for all grf phandles
>- Reorder some properties
>- Move interrupt-names back to top level
>- Add constraint of interrupts for all platform
>- Add constraint for all grf phandles
>- Reorder some properties
>
>Changes in v9:
>- Drop 'vop-' prefix of interrupt-names.
>- Add blank line between DT properties
>- Remove list interrupt-names in top level
>- Drop 'vop-' prefix of interrupt-names.
>- Add blank line between DT properties
>- Remove list interrupt-names in top level
>- Drop 'vop-' prefix of interrupt-names.
>
>Changes in v8:
>- Remove redundant blank line before drm_bus_format_enum_list
>- Add a blank line before DRM_ENUM_NAME_FN
>- Fix dt_binding_check errors
>- ordered by soc name
>- Link to the previous version:
>  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u
>- Fix dt_binding_check errors
>- ordered by soc name
>- Link to the previous version:
>  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u
>
>Changes in v7:
>- Fix rk3588 dp+dsi maxclk verification
>
>Changes in v6:
>- Add a blank line after hardware version check code
>-  More specific explanation about the AXI_BUS_ID register bit of
>   cluster window.
>
>Changes in v5:
>- Add axi id configuration
>- Remove the non-existent CBCR scale register.
>
>Changes in v4:
>- Typo fix: selet->select
>- describe constraint SOC by SOC, as interrupts of rk3576 is very
>  different from others
>- Drop Krzysztof's Reviewed-by, as this version changed a lot.
>- describe constraint SOC by SOC, as interrupts of rk3576 is very
>  different from others
>- Drop Krzysztof's Reviewed-by, as this version changed a lot.
>
>Changes in v3:
>- Add comments for why we should treat rk3566 with special care.
>- Add hardware version check
>- Add comments for why we should treat rk3566 with special care.
>- ordered by soc name
>- Add description for newly added interrupt
>- ordered by soc name
>- Add description for newly added interrupt
>- Share the alpha setup function with rk3568
>- recoder the code block by soc
>
>Changes in v2:
>- Add platform specific callback
>- Introduce vop hardware version
>- Add dt bindings
>- Add dt bindings
>- Add platform specific callback
>
>Andy Yan (12):
>  drm/rockchip: vop2: Remove AFBC from TRANSFORM_OFFSET register macro
>  drm/rockchip: vop2: Add platform specific callback
>  drm/rockchip: vop2: Merge vop2_cluster/esmart_init function
>  drm/rockchip: vop2: Support for different layer select configuration
>    between VPs
>  drm/rockchip: vop2: Introduce vop hardware version
>  drm/rockchip: vop2: Register the primary plane and overlay plane
>    separately
>  drm/rockchip: vop2: Set plane possible crtcs by possible vp mask
>  drm/rockchip: vop2: Add uv swap for cluster window
>  dt-bindings: display: vop2: describe constraint SoC by SoC
>  dt-bindings: display: vop2: Add missing rockchip,grf property for
>    rk3566/8
>  dt-bindings: display: vop2: Add rk3576 support
>  drm/rockchip: vop2: Add support for rk3576
>
>Heiko Stuebner (1):
>  drm/rockchip: vop2: use devm_regmap_field_alloc for cluster-regs
>
> .../display/rockchip/rockchip-vop2.yaml       |   99 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 1472 +++-----------
> drivers/gpu/drm/rockchip/rockchip_drm_vop2.h  |  277 ++-
> drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  | 1798 ++++++++++++++++-
> 4 files changed, 2377 insertions(+), 1269 deletions(-)
>
>-- 
>2.34.1

From mazziesaccount at gmail.com  Sun Mar  2 04:21:20 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 14:21:20 +0200
Subject: [PATCH v4 02/10] property: Add
 device_get_child_node_count_named()
In-Reply-To: <CAL_Jsq+tkXAAVK2D_AtENuXJZOF2eK=sUnjv3=7PM8nAyAB7Xw@mail.gmail.com>
References: <29ec24f1498392cafbecc0e0c0e23e1ce3289565.1740421248.git.mazziesaccount@gmail.com>
 <Z72QAOA9xXbP16K-@kuha.fi.intel.com> <Z72Zp8tpnvlFGdQ_@smile.fi.intel.com>
 <ad39b453-7e5b-49bd-a4fd-6a4988636130@gmail.com>
 <Z72d7TzZ21WITW3f@smile.fi.intel.com>
 <893a3c45-537e-47ad-afbd-1e5d3b9abe2c@gmail.com>
 <Z73M3Ua6u1FpgBEK@smile.fi.intel.com>
 <720f9c69-ca1f-45cb-9f6e-c8e4703c9aad@gmail.com>
 <Z78g_uiXumn4mvET@smile.fi.intel.com>
 <d7982b76-3da7-47ff-b2b2-f964610af1f7@gmail.com>
 <Z8B7h4_IWz43gFhO@smile.fi.intel.com>
 <c9424f3e-1ff0-4c01-823a-19801cc3e7a7@gmail.com>
 <CAL_Jsq+tkXAAVK2D_AtENuXJZOF2eK=sUnjv3=7PM8nAyAB7Xw@mail.gmail.com>
Message-ID: <863ce320-c5cd-47f6-a66b-c43fac98a4b0@gmail.com>

On 28/02/2025 18:59, Rob Herring wrote:
> On Thu, Feb 27, 2025 at 9:06?AM Matti Vaittinen
> <mazziesaccount at gmail.com> wrote:
>>
>>>
> Sigh. This is not that hard.
> 
> - unsigned int num_grps = gfar_of_group_count(np);
> + unsigned int num_grps =
> device_get_child_node_count_named(&ofdev->dev, "queue-groups");
> 
> And remove gfar_of_group_count() of course.

Thanks Rob. That's what I (already twice) wrote I'll do:

 >>>> alter the gianfar code by dropping the gfar_of_group_count(),

and

 >>  I prefer killing whole
 >> gfar_of_group_count().

I just wanted to understand what Andy suggested.

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 04:22:55 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 14:22:55 +0200
Subject: [PATCH v4 02/10] property: Add
 device_get_child_node_count_named()
In-Reply-To: <CAL_Jsq+av-fptMQqBeVieKwA9c7+uUCaqZMLGu-RVJzWZ_7+Vg@mail.gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <29ec24f1498392cafbecc0e0c0e23e1ce3289565.1740421248.git.mazziesaccount@gmail.com>
 <CAL_Jsq+av-fptMQqBeVieKwA9c7+uUCaqZMLGu-RVJzWZ_7+Vg@mail.gmail.com>
Message-ID: <44b1cc7f-a5e1-4c61-8b9c-1ba0c51e6343@gmail.com>

On 28/02/2025 19:07, Rob Herring wrote:
> On Mon, Feb 24, 2025 at 12:33?PM Matti Vaittinen
> <mazziesaccount at gmail.com> wrote:
>>
>> There are some use-cases where child nodes with a specific name need to
>> be parsed. In a few cases the data from the found nodes is added to an
>> array which is allocated based on the number of found nodes. One example
>> of such use is the IIO subsystem's ADC channel nodes, where the relevant
>> nodes are named as channel[@N].
>>
>> Add a helper for counting device's sub-nodes with certain name instead
>> of open-coding this in every user.
>>
>> Suggested-by: Jonathan Cameron <jic23 at kernel.org>
>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
>> ---
>> Revision history:
>> v3 => v4:
>>   - New patch as suggested by Jonathan, see discussion in:
>> https://lore.kernel.org/lkml/20250223161338.5c896280 at jic23-huawei/
>> ---
>>   drivers/base/property.c  | 28 ++++++++++++++++++++++++++++
>>   include/linux/property.h |  2 ++
>>   2 files changed, 30 insertions(+)
>>
>> diff --git a/drivers/base/property.c b/drivers/base/property.c
>> index c1392743df9c..3f85818183cd 100644
>> --- a/drivers/base/property.c
>> +++ b/drivers/base/property.c
>> @@ -945,6 +945,34 @@ unsigned int device_get_child_node_count(const struct device *dev)
>>   }
>>   EXPORT_SYMBOL_GPL(device_get_child_node_count);
>>
>> +/**
>> + * device_get_child_node_count_named - number of child nodes with given name
>> + *
>> + * Scan device's child nodes and find all the nodes with a specific name and
>> + * return the number of found nodes. Potential '@number' -ending for scanned
>> + * names is ignored. Eg,
>> + * device_get_child_node_count(dev, "channel");
>> + * would match all the nodes:
>> + * channel { }, channel at 0 {}, channel at 0xabba {}...
>> + *
>> + * @dev: Device to count the child nodes for
>> + *
>> + * Return: the number of child nodes with a matching name for a given device.
>> + */
>> +unsigned int device_get_child_node_count_named(const struct device *dev,
>> +                                              const char *name)
> 
> I think this should be implemented as
> fwnode_get_child_node_count_named() with the device variant being just
> a wrapper.

I thought of that but it'll mean we had two very little used APIs 
instead of just one. Well, perhaps we see new users though so I'll 
follow this suggestion for v5.

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 04:54:16 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 14:54:16 +0200
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <20250302032054.1fb8a011@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
 <0de7b0ac-eca5-49ba-b1b3-f249655f3646@baylibre.com>
 <1b308a10-9622-47f9-b489-bd969fbdfc34@gmail.com>
 <6f6e6550-5246-476f-9168-5e24151ab165@baylibre.com>
 <9180ff11-888b-453d-9617-4b3a0fb38d91@gmail.com>
 <20250302032054.1fb8a011@jic23-huawei>
Message-ID: <eaede287-658d-4c23-b217-5bc8053e64ed@gmail.com>

On 02/03/2025 05:20, Jonathan Cameron wrote:
> On Thu, 27 Feb 2025 09:46:06 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> On 26/02/2025 18:10, David Lechner wrote:
>>> On 2/26/25 12:28 AM, Matti Vaittinen wrote:

...

> So today the situation is we have all the options in tree and we aren't
> really in a position to drop any of them:

Sure. I am only really interested whether we want to prefer some 
approach for (majority of) new drivers. Furthermore, I believe there 
will always be corner cases and oddities which won't fit to the 'de 
facto' model. That doesn't mean we shouldn't help those which don't have 
such 'oddities' to work with some generic code.

> Hindsight is a wonderful thing.  I'm not sure on what policy we should have
> gone for, but now we are kind of stuck with this slightly messy situation.

Sorry if my comments came out as criticism. It was not intention, I just 
try to justify the helpers by trying to think what new drivers should 
prefer.

> Helper wise if it expands usefulness we may want a bool parameter to say
> if we skip the missing or not + make sure a max expected channel is provided
> (might already be - I didn't check!)

This far it only had (optional) maximum channel ID for sanity checking 
(useful for callers which use the ID to index an array). The bool 
parameter would also require a parameter specifying the number of 
expected channels. That'd make 3 parameters which may be used or unused.

I don't think I saw existing code which would have used these 
parameters. It might be cleaner to add new APIs when we get such 
use-cases. That should simplify the use for current cases.

Thank You for the long explanation of current system + the history :) I 
appreciate your guidance!

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 05:00:21 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 15:00:21 +0200
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <20250302033507.7c166743@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
 <20250302033507.7c166743@jic23-huawei>
Message-ID: <f8f7154b-460a-4ca5-b31b-746bd23a3d61@gmail.com>

On 02/03/2025 05:35, Jonathan Cameron wrote:
> On Mon, 24 Feb 2025 20:33:16 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> There are ADC ICs which may have some of the AIN pins usable for other
>> functions. These ICs may have some of the AIN pins wired so that they
>> should not be used for ADC.
>>
>> (Preferred?) way for marking pins which can be used as ADC inputs is to
>> add corresponding channels at N nodes in the device tree as described in
>> the ADC binding yaml.
> I think it's worth exploring if we can tweak this slightly to make
> that something a driver specifies.  Either skip the unspecified or
> fill them with default values depending on a parameter.
> 
> Would make this code cover the existing cases better.
> Might be a little fiddly as we'd want to maintain ordering so
> the code would need to index slightly differently. I've not tried it
> so maybe not worth it for now.

Thanks for the review!

I don't remember seeing users which would have benefited from this (but 
maybe I just quickly discarded them as unsuitable for this API and 
forgot them). Anyways, I think it might be cleaner (from the caller's 
perspective) to have own function for supporting such cases.


>> +
>> +int iio_adc_device_num_channels(struct device *dev)
>> +{
>> +	return device_get_child_node_count_named(dev, "channel");
>> +}
>> +EXPORT_SYMBOL_GPL(iio_adc_device_num_channels);
> 
> Maybe one to promote to a static inline in the header and avoid need for
> the export given it is very simple.

Makes sense, thanks.

...

>> +
>> +		if (max_chan_id != -1)
>> +			if (ch > max_chan_id)
>> +				return -ERANGE;
> 
> Might as well combine.
> 		if (max_chan_id != -1 && ch > max_chan_id)
> 			return -ERANGE;

Ack.

Yours,
	-- Matti



From mazziesaccount at gmail.com  Sun Mar  2 05:01:49 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 15:01:49 +0200
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <20250302034807.680a3971@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
 <20250302034807.680a3971@jic23-huawei>
Message-ID: <023c8a59-55df-4484-a2c2-f629b237e21f@gmail.com>

On 02/03/2025 05:48, Jonathan Cameron wrote:
> On Mon, 24 Feb 2025 20:33:16 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 

...

>> +int iio_adc_device_num_channels(struct device *dev)
>> +{
>> +	return device_get_child_node_count_named(dev, "channel");
>> +}
>> +EXPORT_SYMBOL_GPL(iio_adc_device_num_channels);
> Just noticed, this isn't namespaces which is a bit odd.  I'd drop
> the export anyway in favour of static inline but if you don't match
> the namespace of the next one.

Indeed, thanks. I'll inline this in v5.

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 05:06:46 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 15:06:46 +0200
Subject: [PATCH v4 04/10] iio: adc: rzg2l_adc: Use adc-helpers
In-Reply-To: <20250302034042.59d83f53@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <5658fbdd886cc7ada278a42c63a140bc14d1277d.1740421248.git.mazziesaccount@gmail.com>
 <20250302034042.59d83f53@jic23-huawei>
Message-ID: <45c0bf5a-f821-498e-8a9c-99e53bba5307@gmail.com>

On 02/03/2025 05:40, Jonathan Cameron wrote:
> On Mon, 24 Feb 2025 20:33:29 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
>> drivers avoid open-coding the for_each_node -loop for getting the
>> channel IDs. The helper provides standard way to detect the ADC channel
>> nodes (by the node name), and a standard way to convert the "reg",
>> "diff-channels", "single-channel" and the "common-mode-channel" to
>> channel identification numbers used in the struct iio_chan_spec.
> 
> Needs an update to reflecting naming and functionality simplifications.

Thanks! I should've noticed this. I'll re-read and alter all the commits 
for the v5.

> 
>> Furthermore, the helper checks the ID is in range of 0 ... num-channels.
>>
>> The original driver treated all found child nodes as channel nodes. The
>> new helper requires channel nodes to be named channel[@N]. This should
>> help avoid problems with devices which may contain also other but ADC
>> child nodes. Quick grep from arch/* with the rzg2l_adc's compatible
>> string didn't reveal any in-tree .dts with channel nodes named
>> othervice. Also, same grep shows all the .dts seem to have channel IDs
> otherwise
> 
> (othervice does sound cool though ;)

Thanks :D For some reason I always have difficulties spelling it!

...

>> I picked the rzg2l_adc in this series because it has a straightforward
>> approach for populating the struct iio_chan_spec. Only other member
>> in the stuct besides the .channel, which can't use a 'template' -data,
>> is the .datasheet_name. This makes the rzg2l_adc well suited for example
>> user of this new helper. I hope this patch helps to evaluate whether these
>> helpers are worth the hassle.
> This doesn't seem to match driver. It is messing with channel type.

Ah. Yes. It was simple until I rebased to never version. I'll change 
this. Thanks!

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 05:10:12 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 15:10:12 +0200
Subject: [PATCH v4 07/10] iio: adc: ti-ads7924: Respect device tree config
In-Reply-To: <20250302032713.1c834448@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <20dd0e4ea72fe39b90b611f9c08dbd4bc1d5217f.1740421248.git.mazziesaccount@gmail.com>
 <f0d0f114-3953-46b5-b9f6-9b35537e6f8e@baylibre.com>
 <d391b012-0a8e-40ca-af56-ca73b3fd853b@gmail.com>
 <20250302032713.1c834448@jic23-huawei>
Message-ID: <7c79ce3a-0dc4-4aa4-941a-e05be9a34fb8@gmail.com>

On 02/03/2025 05:27, Jonathan Cameron wrote:
> On Wed, 26 Feb 2025 08:39:11 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> On 26/02/2025 02:09, David Lechner wrote:
>>> On 2/24/25 12:34 PM, Matti Vaittinen wrote:
>>>> The ti-ads7924 driver ignores the device-tree ADC channel specification
>>>> and always exposes all 4 channels to users whether they are present in
>>>> the device-tree or not. Additionally, the "reg" values in the channel
>>>> nodes are ignored, although an error is printed if they are out of range.
>>>>
>>>> Register only the channels described in the device-tree, and use the reg
>>>> property as a channel ID.
>>>>
>>>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
>>>>
>>>> ---
>>>> Revision history:
>>>> v3 => v4:
>>>>    - Adapt to 'drop diff-channel support' changes to ADC-helpers
>>>>    - select ADC helpers in the Kconfig
>>>> v2 => v3: New patch
>>>>
>>>> Please note that this is potentially breaking existing users if they
>>>> have wrong values in the device-tree. I believe the device-tree should
>>>> ideally be respected, and if it says device X has only one channel, then
>>>> we should believe it and not register 4. Well, we don't live in the
>>>> ideal world, so even though I believe this is TheRightThingToDo - it may
>>>> cause havoc because correct device-tree has not been required from the
>>>> day 1. So, please review and test and apply at your own risk :)
>>>
>>> The DT bindings on this one are a little weird. Usually, if we don't
>>> use any extra properties from adc.yaml, we leave out the channels. In
>>> this case it does seem kind of like the original intention was to work
>>> like you are suggesting, but hard to say since the driver wasn't actually
>>> implemented that way. I would be more inclined to actually not make the
>>> breaking change here and instead relax the bindings to make channel nodes
>>> optional and just have the driver ignore the channel nodes by dropping
>>> the ads7924_get_channels_config() function completely. This would make
>>> the driver simpler instead of more complex like this patch does.
>>
>> I have no strong opinion on this. I see this driver says 'Supported' in
>> MAINTAINERS. Maybe Hugo is able to provide some insight?
>>
> This seems to be ABI breakage.  Never something we can take if there is
> a significant chance of anyone noticing.  Here it looks like risk
> is too high.

Ok. I'll just drop this patch then. Thanks David & Jonathan :)

Yours,
	-- Matti


From mazziesaccount at gmail.com  Sun Mar  2 05:15:45 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Sun, 2 Mar 2025 15:15:45 +0200
Subject: [PATCH v4 08/10] iio: adc: Support ROHM BD79124 ADC
In-Reply-To: <20250302041046.7fde3c68@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <4d1bf5df8f3b0f760422b6b67fcc8245ebf520e0.1740421249.git.mazziesaccount@gmail.com>
 <20250302041046.7fde3c68@jic23-huawei>
Message-ID: <ccac509c-d063-42f4-a092-bee4014ec9da@gmail.com>

On 02/03/2025 06:10, Jonathan Cameron wrote:
> On Mon, 24 Feb 2025 20:34:30 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
>> an automatic measurement mode, with an alarm interrupt for out-of-window
>> measurements. The window is configurable for each channel.
>>
>> The I2C protocol for manual start of the measurement and data reading is
>> somewhat peculiar. It requires the master to do clock stretching after
>> sending the I2C slave-address until the slave has captured the data.
>> Needless to say this is not well suopported by the I2C controllers.
>>
>> Thus the driver does not support the BD79124's manual measurement mode
>> but implements the measurements using automatic measurement mode relying
>> on the BD79124's ability of storing latest measurements into register.
>>
>> The driver does also support configuring the threshold events for
>> detecting the out-of-window events.
>>
>> The BD79124 keeps asserting IRQ for as long as the measured voltage is
>> out of the configured window. Thus the driver masks the received event
>> for a fixed duration (1 second) when an event is handled. This prevents
>> the user-space from choking on the events
>>
>> The ADC input pins can be also configured as general purpose outputs.
>> Those pins which don't have corresponding ADC channel node in the
>> device-tree will be controllable as GPO.
>>
>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> Some minor stuff inline.

...

>> +#define BD79124_INTERVAL_075 0
> 
> Can we make these units in these explicit?
> #define BD79124_INTERVAL_MS_0_75
> maybe?  Nice to avoid need for comments on what the units are where
> you use these.
> 

Sure, thanks.

>> +#define BD79124_INTERVAL_150 1
>> +#define BD79124_INTERVAL_300 2
>> +#define BD79124_INTERVAL_600 3

...

> 
>> +static void bd79124_re_enable_hi(struct bd79124_data *data, unsigned int channel)
>> +{
>> +	int ret, evbit = BIT(IIO_EV_DIR_RISING);
>> +
>> +	if (!(data->alarm_suppressed[channel] & evbit))
>> +		return;
>> +
>> +	data->alarm_suppressed[channel] &= (~evbit);
> 
> No brackets around the ~evbit.
> Check for other cases of this.
> Otherwise we'll get some script written 'cleanup'.

Sigh. I had a lengthy discussion about this with Andy explaining why I 
like having the parenthesis to avoid any confusion. Well, I suppose I 
have no options if you're strongly opposing them.

...

>> +static void bd79124_alm_enable_worker(struct work_struct *work)
>> +{
>> +	int i;
>> +	struct bd79124_data *data = container_of(work, struct bd79124_data,
>> +						 alm_enable_work.work);
>> +
>> +	guard(mutex)(&data->mutex);
>> +	/*
>> +	 * We should not re-enable the event if user has disabled it while
>> +	 * rate-limiting was enabled.
>> +	 */
> 
> Is this comment suggesting something that isn't done or referring to specific
> code?  I think it wants to be in the function above where the decision is made.

I have to take another look but it seems it got misplaced during the 
road. Thanks!

Agreeing with all the rest, thanks!

Yours,
	-- Matti


From vigneshr at ti.com  Sun Mar  2 05:19:08 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:49:08 +0530
Subject: [PATCH v2] arm64: dts: ti: k3-j784s4-j742s2-main-common: Correct the GICD size
In-Reply-To: <20250218052248.4734-1-j-keerthy@ti.com>
References: <20250218052248.4734-1-j-keerthy@ti.com>
Message-ID: <174092143355.3272913.10095422286018964990.b4-ty@ti.com>

Hi Keerthy,

On Tue, 18 Feb 2025 10:52:48 +0530, Keerthy wrote:
> Currently we get the warning:
> 
> "GICv3: [Firmware Bug]: GICR region 0x0000000001900000 has
> overlapping address"
> 
> As per TRM GICD is 64 KB. Fix it by correcting the size of GICD.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-j784s4-j742s2-main-common: Correct the GICD size
      commit: 398898f9cca1a19a83184430c675562680e57c7b

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:19:33 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:49:33 +0530
Subject: [PATCH v2] arm64: dts: ti: k3-j784s4-evm-quad-port-eth-exp1: Remove duplicate hogs
In-Reply-To: <20250110105753.223049-1-j-choudhary@ti.com>
References: <20250110105753.223049-1-j-choudhary@ti.com>
Message-ID: <174092143352.3272913.15934714323142045116.b4-ty@ti.com>

Hi Jayesh Choudhary,

On Fri, 10 Jan 2025 16:27:53 +0530, Jayesh Choudhary wrote:
> The j784s4-evm board dts now has the gpio hogs for MUX2 after integration
> of audio support. Remove duplicate gpio-hogs from the overlay dtso to
> prevent mux probe failures leading to can-phy3 deferred probe:
> 'gpio-mux mux-controller: probe with driver gpio-mux failed with error -16'
> 
> 

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-j784s4-evm-quad-port-eth-exp1: Remove duplicate hogs
      commit: 8a3629a6a9e52b30c55910b26c9c0dbc376f9d29

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:19:50 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:49:50 +0530
Subject: [PATCH v1] arm64: dts: ti: k3-am62p: Enable AUDIO_REFCLKx
In-Reply-To: <20250206153911.414702-1-francesco@dolcini.it>
References: <20250206153911.414702-1-francesco@dolcini.it>
Message-ID: <174092143360.3272913.6825110714284930452.b4-ty@ti.com>

Hi Francesco Dolcini,

On Thu, 06 Feb 2025 16:39:11 +0100, Francesco Dolcini wrote:
> On AM62P-based SoCs the AUDIO_REFCLKx clocks can be used as an input to
> external peripherals when configured through CTRL_MMR, so add the
> clock nodes.
> 
> 

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62p: Enable AUDIO_REFCLKx
      commit: a5a7b2be9506d4483ddc9b4bd20e8948c456a8cb

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:20:12 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:50:12 +0530
Subject: [PATCH] arm64: dts: ti: k3-am62a-mcu: enable mcu domain pinmux
In-Reply-To: <20250120075442.181191-1-s-adivi@ti.com>
References: <20250120075442.181191-1-s-adivi@ti.com>
Message-ID: <174092143352.3272913.2726139010475904694.b4-ty@ti.com>

Hi Sai Sree Kartheek Adivi,

On Mon, 20 Jan 2025 13:24:42 +0530, Sai Sree Kartheek Adivi wrote:
> Enable mcu domain pinmux by default to be able to access mcu domain
> peripherals from main domain.
> 
> This also makes it consistent with the rest of the k3 platforms where
> mcu domain pinmux is enabled by default.
> 
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62a-mcu: enable mcu domain pinmux
      commit: 9e999a702701b621be7427a6f2cc29bd04defa7f

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:17:41 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:47:41 +0530
Subject: [PATCH] arm64: dts: ti: k3-am625-beagleplay: Reserve 128MiB of global CMA
In-Reply-To: <20250131173508.1338842-1-nm@ti.com>
References: <20250131173508.1338842-1-nm@ti.com>
Message-ID: <174092143357.3272913.16342762135985998493.b4-ty@ti.com>

Hi Nishanth Menon,

On Fri, 31 Jan 2025 11:35:08 -0600, Nishanth Menon wrote:
> In the same lines of commit 9e8560556f9c ("arm64: dts: ti:
> k3-am62x-sk-common: Reserve 128MiB of global CMA"), reserve global CMA
> pool for:
> 
> LCD Display: 16MiB, HDMI (1080p): 16MiB, GPU: 16MiB, CSI2 1 1080p
> sensor: 32MiB with a 32MiB set for other peripherals and a 16MiB
> buffer.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am625-beagleplay: Reserve 128MiB of global CMA
      commit: 47ab49247b68423c399717f2c8623e7f5d70153e

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:18:10 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:48:10 +0530
Subject: [PATCH] arm64: dts: ti: k3-j721s2-som-p0: Add flash partition details
In-Reply-To: <20250215070059.1593489-1-u-kumar1@ti.com>
References: <20250215070059.1593489-1-u-kumar1@ti.com>
Message-ID: <174092143356.3272913.16335037194305409116.b4-ty@ti.com>

Hi Udit Kumar,

On Sat, 15 Feb 2025 12:30:59 +0530, Udit Kumar wrote:
> When used as boot device, OSPI flash hosts different  boot
> binaries and rootfs etc.
> So Add partition details for images hosted on OSPI flash.
> 
> 

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-j721s2-som-p0: Add flash partition details
      commit: d9f17c11650c205fd4802033a5e880bf79662ace

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:18:43 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:48:43 +0530
Subject: [PATCH v2] arm64: dts: ti: k3-am62a7-sk: Add alias for RTC
In-Reply-To: <20250214232212.1158505-1-k-willis@ti.com>
References: <20250214232212.1158505-1-k-willis@ti.com>
Message-ID: <174092143356.3272913.3416298233282580231.b4-ty@ti.com>

Hi Kendall Willis,

On Fri, 14 Feb 2025 17:22:12 -0600, Kendall Willis wrote:
> Adds alias for SoC RTC so that it gets assigned rtc0. PMIC node is
> assigned rtc1 so that PMIC RTC gets probed as rtc1. This makes it
> consistent for testing rtcwake with other AM62 devices where rtc0
> is SoC RTC.
> 
> 

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62a7-sk: Add alias for RTC
      commit: 34887f2dab33b30de2730005681c796114fba351

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 05:20:35 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Sun, 2 Mar 2025 18:50:35 +0530
Subject: [PATCH v1] arm64: dts: ti: k3-am62-verdin-dahlia: add Microphone Jack to sound card
In-Reply-To: <20250217144643.178222-1-eichest@gmail.com>
References: <20250217144643.178222-1-eichest@gmail.com>
Message-ID: <174092143355.3272913.9537150435807250847.b4-ty@ti.com>

Hi Stefan Eichenberger,

On Mon, 17 Feb 2025 15:46:04 +0100, Stefan Eichenberger wrote:
> The simple-audio-card's microphone widget currently connects to the
> headphone jack. Routing the microphone input to the microphone jack
> allows for independent operation of the microphone and headphones.
> 
> This resolves the following boot-time kernel log message, which
> indicated a conflict when the microphone and headphone functions were
> not separated:
>   debugfs: File 'Headphone Jack' in directory 'dapm' already present!
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62-verdin-dahlia: add Microphone Jack to sound card
      commit: 7139df64e7c13c079b754476355c62b490213055

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From chunkuang.hu at kernel.org  Sun Mar  2 06:01:15 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 22:01:15 +0800
Subject: [PATCH v7 08/43] drm/mediatek: mtk_dpi: Support AFIFO 1T1P output
 and conversion
In-Reply-To: <CAAOTY_8kxxaj+jum6CkJGHKrpjiX_cNt4FT345yET8GWR2QSFA@mail.gmail.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com>
 <20250217154836.108895-9-angelogioacchino.delregno@collabora.com> <CAAOTY_8kxxaj+jum6CkJGHKrpjiX_cNt4FT345yET8GWR2QSFA@mail.gmail.com>
Message-ID: <CAAOTY_9tjf8xw8n9euVK1OH7LLopNYwx5qzLJpQyQ+sKfVH6og@mail.gmail.com>

Chun-Kuang Hu <chunkuang.hu at kernel.org> ? 2025?3?2? ?? ??7:29???
>
> Hi, Angelo:
>
> AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
> 2025?2?17? ?? ??11:49???
> >
> > On some SoCs, like MT8195 and MT8188, the DPI's FIFO controller
> > (afifo) supports outputting either one or two pixels per round
> > regardless of the input being 1T1P or 1T2P.
> >
> > Add a `output_1pixel` member to struct mtk_dpi_conf which, if
> > set, will enable outputting one pixel per clock.
> >
> > In case the input is two pixel per clock (1T2P), the AFIFO HW
> > will automatically (and internally) convert it to 1T1P.
>
> Applied to mediatek-drm-next [1], thanks.
>
> [1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Fix build error then apply. Be care of patch quality.

Regards,
Chun-Kuang.

>
> Regards,
> Chun-Kuang.
>
> >
> > Reviewed-by: CK Hu <ck.hu at mediatek.com>
> > Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dpi.c | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> > index 9f83e82437dd..e12dc73ed79c 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> > @@ -147,6 +147,8 @@ struct mtk_dpi_factor {
> >   * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
> >   * @clocked_by_hdmi: HDMI IP outputs clock to dpi_pixel_clk input clock, needed
> >   *                  for DPI registers access.
> > + * @output_1pixel: Enable outputting one pixel per round; if the input is two pixel per
> > + *                 round, the DPI hardware will internally transform it to 1T1P.
> >   */
> >  struct mtk_dpi_conf {
> >         const struct mtk_dpi_factor *dpi_factor;
> > @@ -168,6 +170,7 @@ struct mtk_dpi_conf {
> >         u32 pixels_per_iter;
> >         bool edge_cfg_in_mmsys;
> >         bool clocked_by_hdmi;
> > +       bool output_1pixel;
> >  };
> >
> >  static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
> > @@ -653,7 +656,13 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
> >         if (dpi->conf->support_direct_pin) {
> >                 mtk_dpi_config_yc_map(dpi, dpi->yc_map);
> >                 mtk_dpi_config_2n_h_fre(dpi);
> > -               mtk_dpi_dual_edge(dpi);
> > +
> > +               /* DPI can connect to either an external bridge or the internal HDMI encoder */
> > +               if (dpi->conf->output_1pixel)
> > +                       mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN);
> > +               else
> > +                       mtk_dpi_dual_edge(dpi);
> > +
> >                 mtk_dpi_config_disable_edge(dpi);
> >         }
> >         if (dpi->conf->input_2p_en_bit) {
> > --
> > 2.48.1
> >


From chunkuang.hu at kernel.org  Sun Mar  2 06:05:50 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 22:05:50 +0800
Subject: [PATCH v7 09/43] drm/mediatek: mtk_dpi: Explicitly manage TVD
 clock in power on/off
In-Reply-To: <20250217154836.108895-10-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-10-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY__zrRM9oyDtuDAzJ+ddOU2as2-vy9FkGs_Wzqjo_==RvA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> In preparation for adding support for MT8195's HDMI reserved
> DPI, add calls to clk_prepare_enable() / clk_disable_unprepare()
> for the TVD clock: in this particular case, the aforementioned
> clock is not (and cannot be) parented to neither pixel or engine
> clocks hence it won't get enabled automatically by the clock
> framework.
>
> Please note that on all of the currently supported MediaTek
> platforms, the TVD clock is always a parent of either pixel or
> engine clocks, and this means that the common clock framework
> is already enabling this clock before the children.
> On such platforms, this commit will only increase the refcount
> of the TVD clock without any functional change.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index e12dc73ed79c..ee952785866c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -499,6 +499,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
>
>         mtk_dpi_disable(dpi);
>         clk_disable_unprepare(dpi->pixel_clk);
> +       clk_disable_unprepare(dpi->tvd_clk);
>         clk_disable_unprepare(dpi->engine_clk);
>  }
>
> @@ -515,6 +516,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
>                 goto err_refcount;
>         }
>
> +       ret = clk_prepare_enable(dpi->tvd_clk);
> +       if (ret) {
> +               dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret);
> +               goto err_engine;
> +       }
> +
>         ret = clk_prepare_enable(dpi->pixel_clk);
>         if (ret) {
>                 dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret);
> @@ -524,6 +531,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
>         return 0;
>
>  err_pixel:
> +       clk_disable_unprepare(dpi->tvd_clk);
> +err_engine:
>         clk_disable_unprepare(dpi->engine_clk);
>  err_refcount:
>         dpi->refcount--;
> --
> 2.48.1
>


From chunkuang.hu at kernel.org  Sun Mar  2 06:14:55 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Sun, 2 Mar 2025 22:14:55 +0800
Subject: [PATCH v7 10/43] drm/mediatek: Add support for MT8195 Digital
 Parallel Interface
In-Reply-To: <20250217154836.108895-11-angelogioacchino.delregno@collabora.com>
References: <20250217154836.108895-1-angelogioacchino.delregno@collabora.com> <20250217154836.108895-11-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY__ZZCDDiqhUBscXL-kKkmw87Lv_DmuZT-9cO4BcrmG5Yg@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?17? ?? ??11:49???
>
> Add support for the DPI block found in the MT8195 and MT8188 SoCs.
> Inside of the SoC, this block is directly connected to the HDMI IP.

After fix conflicts, applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c      | 19 +++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_dpi_regs.h |  6 ++++++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  2 ++
>  3 files changed, 27 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index ee952785866c..d066fbd6ffb6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -1139,6 +1139,24 @@ static const struct mtk_dpi_conf mt8192_conf = {
>         .csc_enable_bit = CSC_ENABLE,
>  };
>
> +static const struct mtk_dpi_conf mt8195_conf = {
> +       .max_clock_khz = 594000,
> +       .output_fmts = mt8183_output_fmts,
> +       .num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),
> +       .pixels_per_iter = 1,
> +       .is_ck_de_pol = true,
> +       .swap_input_support = true,
> +       .support_direct_pin = true,
> +       .dimension_mask = HPW_MASK,
> +       .hvsize_mask = HSIZE_MASK,
> +       .channel_swap_shift = CH_SWAP,
> +       .yuv422_en_bit = YUV422_EN,
> +       .csc_enable_bit = CSC_ENABLE,
> +       .input_2p_en_bit = DPI_INPUT_2P_EN,
> +       .clocked_by_hdmi = true,
> +       .output_1pixel = true,
> +};
> +
>  static const struct mtk_dpi_conf mt8195_dpintf_conf = {
>         .dpi_factor = dpi_factor_mt8195_dp_intf,
>         .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf),
> @@ -1242,6 +1260,7 @@ static const struct of_device_id mtk_dpi_of_ids[] = {
>         { .compatible = "mediatek,mt8188-dp-intf", .data = &mt8195_dpintf_conf },
>         { .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf },
>         { .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf },
> +       { .compatible = "mediatek,mt8195-dpi", .data = &mt8195_conf },
>         { /* sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> index a0b1d18bbbf7..3c24d9e9f241 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> @@ -40,6 +40,12 @@
>  #define FAKE_DE_LEVEN                  BIT(21)
>  #define FAKE_DE_RODD                   BIT(22)
>  #define FAKE_DE_REVEN                  BIT(23)
> +
> +/* DPI_CON: DPI instances */
> +#define DPI_OUTPUT_1T1P_EN             BIT(24)
> +#define DPI_INPUT_2P_EN                        BIT(25)
> +
> +/* DPI_CON: DPINTF instances */
>  #define DPINTF_YUV422_EN               BIT(24)
>  #define DPINTF_CSC_ENABLE              BIT(26)
>  #define DPINTF_INPUT_2P_EN             BIT(29)
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index f22ad2882697..772c3d0f5d14 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -810,6 +810,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
>           .data = (void *)MTK_DPI },
>         { .compatible = "mediatek,mt8195-dp-intf",
>           .data = (void *)MTK_DP_INTF },
> +       { .compatible = "mediatek,mt8195-dpi",
> +         .data = (void *)MTK_DPI },
>         { .compatible = "mediatek,mt2701-dsi",
>           .data = (void *)MTK_DSI },
>         { .compatible = "mediatek,mt8173-dsi",
> --
> 2.48.1
>


From phil995511 at proton.me  Sun Mar  2 07:23:20 2025
From: phil995511 at proton.me (phil995511)
Date: Sun, 02 Mar 2025 15:23:20 +0000
Subject: [GIT PULL] Generic entry for ARM
Message-ID: <0oXU8PP2CHCw1Qblhw1cKOTt90K2CLbHo4BLw9LOs-J1klN1Y_N7IagulWZHR7bGhmxyPXlZTOUEqVZDtwcXj9j93_BxdrdnmW7qk3uIrU4=@proton.me>

It is a very bad idea to want to code the Linux kernel for ARM in C++ !!!

Our ARM CPUs on RPi and others are not powerful enough to use a Linux kernel written in C++ and therefore lose performance, while these ARM CPUs are already extremely low-performance !!!

Suggesting to code like this is to be in favor of planned obsolescence, of the scrapping of thousands of small machines ;-(

Regards.

https://lore.kernel.org/lkml/CACRpkdZCiiMTwf7eGJJ9aCKFOC3_xTGv1JKQUijjyp+_++cZ_A at mail.gmail.com/

Envoy? avec la messagerie s?curis?e Proton Mail.





From marex at denx.de  Sun Mar  2 07:25:14 2025
From: marex at denx.de (Marek Vasut)
Date: Sun,  2 Mar 2025 16:25:14 +0100
Subject: [PATCH] ARM: dts: stm32: Add support for STM32MP13xx DHCOR SoM and DHSBC rev.200 board
Message-ID: <20250302152605.54792-1-marex@denx.de>

LDO2 is expansion connector supply on STM32MP13xx DHCOR DHSBC rev.200.
LDO5 is carrier board supply on STM32MP13xx DHCOR DHSBC rev.200. Keep
both regulators always enabled to make sure both the carrier board and
the expansion connector is always powered on and supplied with correct
voltage.

Describe ST33TPHF2XSPI TPM 2.0 chip interrupt and reset lines.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Alexandre Torgue <alexandre.torgue at foss.st.com>
Cc: Christoph Niedermaier <cniedermaier at dh-electronics.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
Cc: Rob Herring <robh at kernel.org>
Cc: devicetree at vger.kernel.org
Cc: kernel at dh-electronics.com
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-stm32 at st-md-mailman.stormreply.com
---
 .../boot/dts/st/stm32mp135f-dhcor-dhsbc.dts   | 30 +++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
index 853dc21449d99..9902849ed0406 100644
--- a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
+++ b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
@@ -176,7 +176,7 @@ &gpioa {
 	gpio-line-names = "", "", "", "",
 			  "", "DHSBC_USB_PWR_CC1", "", "",
 			  "", "", "", "DHSBC_nETH1_RST",
-			  "", "DHCOR_HW-CODING_0", "", "";
+			  "", "DHCOR_HW-CODING_0", "", "DHSBC_HW-CODE_2";
 };
 
 &gpiob {
@@ -197,7 +197,7 @@ &gpiod {
 	gpio-line-names = "", "", "", "",
 			  "", "DHCOR_RAM-CODING_0", "", "",
 			  "", "DHCOR_RAM-CODING_1", "", "",
-			  "", "", "", "";
+			  "", "DHSBC_HW-CODE_1", "", "";
 };
 
 &gpioe {
@@ -221,6 +221,13 @@ &gpiog {
 			  "DHSBC_ETH1_INTB", "", "", "DHSBC_ETH2_INTB";
 };
 
+&gpioh {
+	gpio-line-names = "", "", "", "DHSBC_HW-CODE_0",
+			  "", "", "", "",
+			  "", "", "", "",
+			  "", "", "", "";
+};
+
 &gpioi {
 	gpio-line-names = "DHCOR_RTC_nINT", "DHCOR_HW-CODING_1",
 			  "DHCOR_BT_REG_ON", "DHCOR_PMIC_nINT",
@@ -296,6 +303,9 @@ &spi2 {
 	st33htph: tpm at 0 {
 		compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi";
 		reg = <0>;
+		interrupt-parent = <&gpioe>;
+		interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+		reset-gpios = <&gpioe 12 GPIO_ACTIVE_LOW>;
 		spi-max-frequency = <24000000>;
 	};
 };
@@ -419,3 +429,19 @@ connector {
 		type = "micro";
 	};
 };
+
+/* LDO2 is expansion connector 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
+&vdd_ldo2 {
+	regulator-always-on;
+	regulator-boot-on;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+};
+
+/* LDO5 is carrier board 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
+&vdd_sd {
+	regulator-always-on;
+	regulator-boot-on;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+};
-- 
2.47.2



From c-vankar at ti.com  Sun Mar  2 07:35:00 2025
From: c-vankar at ti.com (Chintan Vankar)
Date: Sun, 2 Mar 2025 21:05:00 +0530
Subject: [PATCH v2 0/2] Add bootph-all property to necessary nodes to enable ethernet boot for AM68-SK, J722s and AM62p-SK
Message-ID: <20250302153502.181832-1-c-vankar@ti.com>

This series adds bootph-all property to necessary nodes to enable
ethernet boot support for AM68-SK, J722s and AM62p-SK.

This series is based on linux-next tagged next-20250228.

Link to v1:
https://lore.kernel.org/r/20250106123122.3531845-1-c-vankar at ti.com/

Changes from v1 to v2:
- Updated order of "bootph-all" in [PATCH 1/1].

Chintan Vankar (2):
  arm64: dts: ti: k3-am68-sk/k3-j721s2-mcu: Add bootph-all property to
    enable Ethernet boot
  arm64: dts: ti: k3-am62p5*/k3-j722s: Add bootph-all property to enable
    Ethernet boot

 arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi | 3 +++
 arch/arm64/boot/dts/ti/k3-am62p5-sk.dts                | 2 ++
 arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts       | 3 +++
 arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi       | 4 ++++
 arch/arm64/boot/dts/ti/k3-j722s-evm.dts                | 3 +++
 5 files changed, 15 insertions(+)

-- 
2.34.1



From c-vankar at ti.com  Sun Mar  2 07:35:02 2025
From: c-vankar at ti.com (Chintan Vankar)
Date: Sun, 2 Mar 2025 21:05:02 +0530
Subject: [PATCH v2 2/2] arm64: dts: ti: k3-am62p5*/k3-j722s: Add bootph-all property to enable Ethernet boot
In-Reply-To: <20250302153502.181832-1-c-vankar@ti.com>
References: <20250302153502.181832-1-c-vankar@ti.com>
Message-ID: <20250302153502.181832-3-c-vankar@ti.com>

Ethernet boot requires CPSW nodes to be present starting from R5 SPL
stage. Add bootph-all property to required nodes to enable Ethernet boot
for AM62p-SK and J722s.

Reviewed-by: Roger Quadros <rogerq at kernel.org>
Signed-off-by: Chintan Vankar <c-vankar at ti.com>
---

Link to v1:
https://lore.kernel.org/r/20250106123122.3531845-3-c-vankar at ti.com/

Changes from v1 to v2:
- Updated order of "bootph-all" property for cpsw_port1 node in
  "k3-am62p-j722s-common-main.dtsi".

 arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi | 3 +++
 arch/arm64/boot/dts/ti/k3-am62p5-sk.dts                | 2 ++
 arch/arm64/boot/dts/ti/k3-j722s-evm.dts                | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
index 6e3beb5c2e01..b88b8fa5f28a 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
@@ -50,6 +50,7 @@ phy_gmii_sel: phy at 4044 {
 			compatible = "ti,am654-phy-gmii-sel";
 			reg = <0x4044 0x8>;
 			#phy-cells = <1>;
+			bootph-all;
 		};
 
 		epwm_tbclk: clock-controller at 4130 {
@@ -721,6 +722,7 @@ cpsw_port1: port at 1 {
 				mac-address = [00 00 00 00 00 00];
 				ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
 				status = "disabled";
+				bootph-all;
 			};
 
 			cpsw_port2: port at 2 {
@@ -742,6 +744,7 @@ cpsw3g_mdio: mdio at f00 {
 			clock-names = "fck";
 			bus_freq = <1000000>;
 			status = "disabled";
+			bootph-all;
 		};
 
 		cpts at 3d000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index ad71d2f27f53..28b08eb79da3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -226,6 +226,7 @@ main_mdio1_pins_default: main-mdio1-default-pins {
 			AM62PX_IOPAD(0x0160, PIN_OUTPUT, 0) /* (F17) MDIO0_MDC */
 			AM62PX_IOPAD(0x015c, PIN_INPUT, 0) /* (F16) MDIO0_MDIO */
 		>;
+		bootph-all;
 	};
 
 	main_mmc1_pins_default: main-mmc1-default-pins {
@@ -495,6 +496,7 @@ &cpsw3g_mdio {
 
 	cpsw3g_phy0: ethernet-phy at 0 {
 		reg = <0>;
+		bootph-all;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 		ti,min-output-impedance;
diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
index d184e9c1a0a5..054425afd764 100644
--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
@@ -303,6 +303,7 @@ mdio_pins_default: mdio-default-pins {
 			J722S_IOPAD(0x0160, PIN_OUTPUT, 0) /* (AC24) MDIO0_MDC */
 			J722S_IOPAD(0x015c, PIN_INPUT, 0) /* (AD25) MDIO0_MDIO */
 		>;
+		bootph-all;
 	};
 
 	ospi0_pins_default: ospi0-default-pins {
@@ -337,6 +338,7 @@ J722S_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AF24) RGMII1_TD3 */
 			J722S_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AG26) RGMII1_TXC */
 			J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */
 		>;
+		bootph-all;
 	};
 
 	main_usb1_pins_default: main-usb1-default-pins {
@@ -381,6 +383,7 @@ &cpsw3g_mdio {
 
 	cpsw3g_phy0: ethernet-phy at 0 {
 		reg = <0>;
+		bootph-all;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 		ti,min-output-impedance;
-- 
2.34.1



From c-vankar at ti.com  Sun Mar  2 07:35:01 2025
From: c-vankar at ti.com (Chintan Vankar)
Date: Sun, 2 Mar 2025 21:05:01 +0530
Subject: [PATCH v2 1/2] arm64: dts: ti: k3-am68-sk/k3-j721s2-mcu: Add bootph-all property to enable Ethernet boot
In-Reply-To: <20250302153502.181832-1-c-vankar@ti.com>
References: <20250302153502.181832-1-c-vankar@ti.com>
Message-ID: <20250302153502.181832-2-c-vankar@ti.com>

Ethernet boot requires CPSW nodes to be present starting from R5 SPL
stage. Add bootph-all property to required nodes to enable Ethernet boot
on AM68-SK and J721S2-EVM.

Signed-off-by: Chintan Vankar <c-vankar at ti.com>
---

Link to v1:
https://lore.kernel.org/r/20250106123122.3531845-2-c-vankar at ti.com/

Changes from v1 to v2:
- No changes.

 arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 3 +++
 arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
index 11522b36e0ce..8e9101dd2152 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
@@ -333,6 +333,7 @@ J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
 			J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
 			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
 		>;
+		bootph-all;
 	};
 
 	mcu_mdio_pins_default: mcu-mdio-default-pins {
@@ -340,6 +341,7 @@ mcu_mdio_pins_default: mcu-mdio-default-pins {
 			J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
 			J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
 		>;
+		bootph-all;
 	};
 
 	mcu_mcan0_pins_default: mcu-mcan0-default-pins {
@@ -615,6 +617,7 @@ &mcu_cpsw {
 &davinci_mdio {
 	phy0: ethernet-phy at 0 {
 		reg = <0>;
+		bootph-all;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 		ti,min-output-impedance;
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
index bc31266126d0..29cd4b1ffbbf 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
@@ -154,12 +154,14 @@ mcu_conf: bus at 40f00000 {
 		cpsw_mac_syscon: ethernet-mac-syscon at 200 {
 			compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
 			reg = <0x200 0x8>;
+			bootph-all;
 		};
 
 		phy_gmii_sel: phy at 4040 {
 			compatible = "ti,am654-phy-gmii-sel";
 			reg = <0x4040 0x4>;
 			#phy-cells = <1>;
+			bootph-all;
 		};
 
 	};
@@ -538,6 +540,7 @@ mcu_cpsw: ethernet at 46000000 {
 		clocks = <&k3_clks 29 28>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 29 TI_SCI_PD_EXCLUSIVE>;
+		bootph-all;
 
 		dmas = <&mcu_udmap 0xf000>,
 		       <&mcu_udmap 0xf001>,
@@ -562,6 +565,7 @@ cpsw_port1: port at 1 {
 				label = "port1";
 				ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
 				phys = <&phy_gmii_sel 1>;
+				bootph-all;
 			};
 		};
 
-- 
2.34.1



From olivier.benjamin at bootlin.com  Sun Mar  2 07:41:02 2025
From: olivier.benjamin at bootlin.com (Olivier Benjamin)
Date: Sun, 02 Mar 2025 16:41:02 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: describe I2c Bus 1 and IMX258
 world camera on PinePhone Pro
In-Reply-To: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
References: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
Message-ID: <20250302-camera-v2-1-312b44b4a89c@bootlin.com>

Add the description of the rear/world camera (IMX258) on the PinePhone Pro
to the device dts file.
It receives commands on the I2C Bus 1 at address 0x1a and transmits data
over CSI-MIPI.

The I2C address for IMX258 can be found in the IMX258-0AQH5 Software
Reference Manual, page 24, section 2.3.1: 0b0011010 = 0x1a.
Section 3 indicates the module has 4 pairs of data lines. While 4-lane
mode is nominal, 2-lane mode should also be supported.

The pin muxing info was extracted from the PinePhone Pro schematic v1.0
as well as the RK3399 datasheet revision 1.8.

Table 2-3 in section 2.8 of the RK3399 datasheet contains the mapping
of IO functions for the SoC pins. Page 52 shows GPIO1_A0, page 54 shows
GPIO2_D4.

For I2C power, the PinePhone Pro schematic page 11 quadrants A4 and A5:
RK3399_J.AA8 and RK3399_J.Y8 get power from vcaa1v8_codec, so turn it on

The IMX258 also uses the following regulators, expected by its driver:
 - vana (2.8V analog), called AVDD2V8_DVP on P.18 q.C1 and derived from
   VCC1V8_S3 on P.13 q.B2
 - vdig (1.2V digital core), called DVDD_DVP on P.18 q.C1 and shown on
   P.18 q.D3 to be equivalent to VCC1V2_DVP derived from VCC3V3_SYS on
   P.13 q.B3. Note that this regulator's voltage is inconsistently
   labeled either 1.2V or 1.5V

RK3399_J.AG1 is GPIO4_A1/I2C1_SDA, RK3399_J.Y6 is GPIO4_A2/I2C1_SCL
This is the default pinctrl "i2c1_xfer" for i2c1 from rk3399-base.

For the reset (RESET) signal:
page 11 quadrant D2             | p.18 q.C3-4 | p.18 q.C2
RK3399_E.R25 -> GPIO1_A0 -> Camera_RST -> MIPI_RST0 -> IMX258.12

For the powerdown (PWDN) signal:
page 11 quadrants B4-5          | p.18 q.C2
RK3399_G.AF8 -> GPIO2_D4 -> DVP_PDN1_H -> IMX258.14

Helped-by: Dragan Simic <dsimic at manjaro.org>
Co-developed-by: Ondrej Jirman <megi at xff.cz>
Signed-off-by: Ondrej Jirman <megi at xff.cz>
Signed-off-by: Olivier Benjamin <olivier.benjamin at bootlin.com>
---
 .../boot/dts/rockchip/rk3399-pinephone-pro.dts     | 93 ++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 04ba4c4565d0a205e2e46d7535c6a3190993621d..7f8fe7577d240f330328b6ea44ea6b06bbc8595b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -114,6 +114,16 @@ vcc3v3_sys: regulator-vcc3v3-sys {
 		vin-supply = <&vcc_sys>;
 	};
 
+	avdd2v8_dvp: regulator-avdd2v8-dvp {
+		compatible = "regulator-fixed";
+		regulator-name = "avdd2v8_dvp";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		vin-supply = <&vcc3v3_sys>;
+	};
+
 	vcca1v8_s3: regulator-vcc1v8-s3 {
 		compatible = "regulator-fixed";
 		regulator-name = "vcca1v8_s3";
@@ -136,6 +146,16 @@ vcc1v8_codec: regulator-vcc1v8-codec {
 		vin-supply = <&vcc3v3_sys>;
 	};
 
+	vcc1v2_dvp: regulator-vcc1v2-dvp {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc1v2_dvp";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		vin-supply = <&vcca1v8_s3>;
+	};
+
 	wifi_pwrseq: sdio-wifi-pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		clocks = <&rk818 1>;
@@ -312,6 +332,8 @@ vcc3v0_touch: LDO_REG2 {
 
 			vcca1v8_codec: LDO_REG3 {
 				regulator-name = "vcca1v8_codec";
+				regulator-always-on;
+				regulator-boot-on;
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
 			};
@@ -420,6 +442,45 @@ regulator-state-mem {
 	};
 };
 
+&i2c1 {
+	clock-frequency = <400000>;
+	pinctrl-0 = <&i2c1_xfer &cif_clkouta>;
+	assigned-clocks = <&cru SCLK_CIF_OUT>;
+	assigned-clock-rates = <24000000>;
+	status = "okay";
+
+	wcam: camera at 1a {
+		compatible = "sony,imx258";
+		reg = <0x1a>;
+		clocks = <&cru SCLK_CIF_OUT>; /* MIPI_MCLK0, derived from CIF_CLKO */
+		clock-names = "xvclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wcam_rst>;
+		/* Note: both cameras also depend on vcca1v8_codec to power the I2C bus. */
+		vif-supply = <&vcc1v8_dvp>;
+		vana-supply = <&avdd2v8_dvp>;
+		vdig-supply = <&vcc1v2_dvp>; /* DVDD_DVP is the same as VCC1V2_DVP */
+		reset-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_LOW>;
+		orientation = <1>; /* V4L2_CAMERA_ORIENTATION_BACK */
+		rotation = <270>;
+		lens-focus = <&wcam_lens>;
+
+		port {
+			wcam_out: endpoint {
+				remote-endpoint = <&mipi_in_wcam>;
+				data-lanes = <1 2 3 4>;
+			};
+		};
+	};
+
+	wcam_lens: camera-lens at c {
+		compatible = "dongwoon,dw9714";
+		reg = <0x0c>;
+		/* Same I2c bus as both cameras, depends on vcca1v8_codec for power. */
+		vcc-supply = <&vcc1v8_dvp>;
+	};
+};
+
 &i2c3 {
 	i2c-scl-rising-time-ns = <450>;
 	i2c-scl-falling-time-ns = <15>;
@@ -462,6 +523,28 @@ &io_domains {
 	status = "okay";
 };
 
+&isp1 {
+	status = "okay";
+
+	ports {
+		port at 0 {
+			mipi_in_wcam: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&wcam_out>;
+				data-lanes = <1 2 3 4>;
+			};
+		};
+	};
+};
+
+&mipi_dphy_rx0 {
+	status = "okay";
+};
+
+&isp1_mmu {
+	status = "okay";
+};
+
 &mipi_dsi {
 	status = "okay";
 	clock-master;
@@ -495,6 +578,10 @@ mipi_in_panel: endpoint {
 	};
 };
 
+&mipi_dsi1 {
+	status = "okay";
+};
+
 &pmu_io_domains {
 	pmu1830-supply = <&vcc_1v8>;
 	status = "okay";
@@ -507,6 +594,12 @@ pwrbtn_pin: pwrbtn-pin {
 		};
 	};
 
+	camera {
+		wcam_rst: wcam-rst {
+			rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	leds {
 		red_led_pin: red-led-pin {
 			rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;

-- 
2.48.1



From olivier.benjamin at bootlin.com  Sun Mar  2 07:41:03 2025
From: olivier.benjamin at bootlin.com (Olivier Benjamin)
Date: Sun, 02 Mar 2025 16:41:03 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: describe the OV8858 user
 camera on PinePhone Pro
In-Reply-To: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
References: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
Message-ID: <20250302-camera-v2-2-312b44b4a89c@bootlin.com>

Add the description of the front/user camera (OV8858) on the PinePhone Pro
to the device dts file.
It receives commands over SCCB, an I2C-compatible protocol, at
I2C address 0x36 and transmits data over CSI-MIPI.
I confirmed this address experimentally.

The pin control mapping was again extracted from the PinePhone Pro
schematic v1.0 as well as the RK3399 datasheet revision 1.8.

Table 2-3 in section 2.8 of the RK3399 datasheet contains the mapping
of IO functions for the SoC pins. Page 52 shows GPIO1_A4, page 54 shows
GPIO2_B4.

For the reset (RESET) signal:
page 11 quadrant D2             | p.18 q.B3-4 | p.18 q.C2
RK3399_E.R28 -> GPIO1_A4 -> Camera2_RST -> MIPI_RST1 -> OV8858.12

For the powerdown (PWDN) signal:
page 9 quadrants D4-5          | p.18 q.B2
RK3399_L.F31 -> GPIO2_B4 -> DVP_PDN0_H -> OV8858.14

Helped-by: Dragan Simic <dsimic at manjaro.org>
Co-developed-by: Ondrej Jirman <megi at xff.cz>
Signed-off-by: Ondrej Jirman <megi at xff.cz>
Signed-off-by: Olivier Benjamin <olivier.benjamin at bootlin.com>
---
 .../boot/dts/rockchip/rk3399-pinephone-pro.dts     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 7f8fe7577d240f330328b6ea44ea6b06bbc8595b..9c965a00fcf6dbf4c618e1f4668d82a028c76143 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -479,6 +479,27 @@ wcam_lens: camera-lens at c {
 		/* Same I2c bus as both cameras, depends on vcca1v8_codec for power. */
 		vcc-supply = <&vcc1v8_dvp>;
 	};
+
+	ucam: camera at 36 {
+		compatible = "ovti,ov8858";
+		reg = <0x36>;
+		clocks = <&cru SCLK_CIF_OUT>; /* MIPI_MCLK1, derived from CIF_CLK0 */
+		clock-names = "xvclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ucam_rst &ucam_pwdn>;
+		dovdd-supply = <&vcc1v8_dvp>;
+		reset-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_LOW>;
+		powerdown-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>;
+		orientation = <0>; /* V4L2_CAMERA_ORIENTATION_FRONT */
+		rotation = <90>;
+
+		port {
+			ucam_out: endpoint {
+				remote-endpoint = <&mipi_in_ucam>;
+				data-lanes = <1 2 3 4>;
+			};
+		};
+	};
 };
 
 &i2c3 {
@@ -523,6 +544,24 @@ &io_domains {
 	status = "okay";
 };
 
+&isp0 {
+	status = "okay";
+
+	ports {
+		port at 0 {
+			mipi_in_ucam: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&ucam_out>;
+				data-lanes = <1 2 3 4>;
+			};
+		};
+	};
+};
+
+&isp0_mmu {
+	status = "okay";
+};
+
 &isp1 {
 	status = "okay";
 
@@ -598,6 +637,12 @@ camera {
 		wcam_rst: wcam-rst {
 			rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
+		ucam_rst: ucam-rst {
+			rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+		ucam_pwdn: ucam-pwdn {
+			rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
 	};
 
 	leds {

-- 
2.48.1



From olivier.benjamin at bootlin.com  Sun Mar  2 07:41:01 2025
From: olivier.benjamin at bootlin.com (Olivier Benjamin)
Date: Sun, 02 Mar 2025 16:41:01 +0100
Subject: [PATCH v2 0/2] Describe the cameras in the PinePhone Pro dts
Message-ID: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>

This series adds support for the Pine64 PinePhone Pro's rear and front
cameras in Device Tree.
This is based on some of Ondrej Jirman's patches hosted in his tree at
https://codeberg.org/megi/linux, but I have also fully reviewed and
re-written the code from the RK3399 datasheet, the PinePhone Pro
schematic, and the IMX258-0AQH5 software reference manual.

I have tested these changes on my PinePhone Pro and am able to take
photos from both cameras using libcamera's cam.

Signed-off-by: Olivier Benjamin <olivier.benjamin at bootlin.com>
---
Changes in v2:
- Rebase on mainline
- Change patch subject to arm64: dts: rockchip
- Rename new regulators to fit preferred form for fixed regulators
- Link to v1: https://lore.kernel.org/r/20250228-camera-v1-0-c51869f94e97 at bootlin.com

---
Olivier Benjamin (2):
      arm64: dts: rockchip: describe I2c Bus 1 and IMX258 world camera on PinePhone Pro
      arm64: dts: rockchip: describe the OV8858 user camera on PinePhone Pro

 .../boot/dts/rockchip/rk3399-pinephone-pro.dts     | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)
---
-- 
Olivier Benjamin <olivier.benjamin at bootlin.com>



From chunkuang.hu at kernel.org  Sun Mar  2 08:07:48 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 00:07:48 +0800
Subject: [PATCH] dt-bindings: display: mediatek: dsc: Add MT8188 compatible
In-Reply-To: <20250218090427.20318-1-angelogioacchino.delregno@collabora.com>
References: <20250218090427.20318-1-angelogioacchino.delregno@collabora.com>
Message-ID: <CAAOTY__aFqL=LnE5vU2RP9JHmQEgkrvPmiYjxmETWo9CvwiwLA@mail.gmail.com>

Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> ?
2025?2?18? ?? ??5:04???
>
> Add compatible for Display Stream Compression (DSC) IP found in
> the display controller of the MT8188 SoC.
>
> This IP is fully compatible with the one found on MT8195.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
>  .../devicetree/bindings/display/mediatek/mediatek,dsc.yaml     | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
> index 846de6c17d93..a5b88eb97e3b 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
> @@ -22,6 +22,9 @@ properties:
>      oneOf:
>        - enum:
>            - mediatek,mt8195-disp-dsc
> +      - items:
> +          - const: mediatek,mt8188-disp-dsc
> +          - const: mediatek,mt8195-disp-dsc
>
>    reg:
>      maxItems: 1
> --
> 2.48.1
>


From ziyao at disroot.org  Sun Mar  2 08:09:01 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun, 2 Mar 2025 16:09:01 +0000
Subject: [PATCH 4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for
 RK3528
In-Reply-To: <116104909.nniJfEyVGO@diego>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
 <Z8GT3rUEyXrTUgtJ@pie.lan>
 <3f0cd767-1fd8-4c65-b8b4-e948288cd02a@kwiboo.se>
 <116104909.nniJfEyVGO@diego>
Message-ID: <Z8SCnfZxH-H0iGwf@pie.lan>

On Sun, Mar 02, 2025 at 12:52:18PM +0100, Heiko St?bner wrote:
> Am Sonntag, 2. M?rz 2025, 12:14:48 MEZ schrieb Jonas Karlman:
> > Hi Yao Zi,
> > 
> > On 2025-02-28 11:46, Yao Zi wrote:
> > > On Fri, Feb 28, 2025 at 06:40:10AM +0000, Jonas Karlman wrote:
> > >> Add pinctrl and gpio nodes for RK3528 and import rk3528-pinctrl.dtsi
> > >> from vendor linux-6.1-stan-rkr5 kernel with the hdmi-pins-idle node
> > >> removed due to missing label reference to pcfg_output_low_pull_down.
> > >>
> > >> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> > >> ---
> > >> This was mostly imported from vendor kernel, however the main commit [1]
> > >> list 28 signed-off-by tags, unclear who I should use as author and what
> > >> signed-off-by tags to include.
> > >>
> > >> [1] https://github.com/rockchip-linux/kernel/commit/c17d6325959f0ec1af901e8a17919163454190a2
> > >> ---
> > >>  .../boot/dts/rockchip/rk3528-pinctrl.dtsi     | 1397 +++++++++++++++++
> > >>  arch/arm64/boot/dts/rockchip/rk3528.dtsi      |   82 +
> > >>  2 files changed, 1479 insertions(+)
> > >>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi
> > >>
> > > 
> > >> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > >> index 0fb90f5c291c..d3e2a64ff2d5 100644
> > >> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > >> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > >> @@ -4,8 +4,10 @@
> > >>   * Copyright (c) 2024 Yao Zi <ziyao at disroot.org>
> > >>   */
> > >>  
> > >> +#include <dt-bindings/gpio/gpio.h>
> > >>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> > >>  #include <dt-bindings/interrupt-controller/irq.h>
> > >> +#include <dt-bindings/pinctrl/rockchip.h>
> > >>  #include <dt-bindings/clock/rockchip,rk3528-cru.h>
> > >>  #include <dt-bindings/reset/rockchip,rk3528-cru.h>
> > >>  
> > >> @@ -17,6 +19,11 @@ / {
> > >>  	#size-cells = <2>;
> > >>  
> > >>  	aliases {
> > >> +		gpio0 = &gpio0;
> > >> +		gpio1 = &gpio1;
> > >> +		gpio2 = &gpio2;
> > >> +		gpio3 = &gpio3;
> > >> +		gpio4 = &gpio4;
> > >>  		serial0 = &uart0;
> > >>  		serial1 = &uart1;
> > >>  		serial2 = &uart2;
> > >> @@ -166,6 +173,11 @@ cru: clock-controller at ff4a0000 {
> > >>  			#reset-cells = <1>;
> > >>  		};
> > >>  
> > >> +		ioc_grf: syscon at ff540000 {
> > >> +			compatible = "rockchip,rk3528-ioc-grf", "syscon";
> > >> +			reg = <0x0 0xff540000 0x0 0x40000>;
> > >> +		};
> > >> +
> > >>  		uart0: serial at ff9f0000 {
> > >>  			compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
> > >>  			reg = <0x0 0xff9f0000 0x0 0x100>;
> > >> @@ -264,5 +276,75 @@ saradc: adc at ffae0000 {
> > >>  			#io-channel-cells = <1>;
> > >>  			status = "disabled";
> > >>  		};
> > >> +
> > >> +		pinctrl: pinctrl {
> > >> +			compatible = "rockchip,rk3528-pinctrl";
> > >> +			rockchip,grf = <&ioc_grf>;
> > >> +			#address-cells = <2>;
> > >> +			#size-cells = <2>;
> > >> +			ranges;
> > > 
> > > I doubt whether the pincontroller should be placed under simple-bus:
> > > without a reg property, it doesn't look like a MMIO device.
> > > 
> > > Actually it is, although all the registers stay in the ioc grf. Maybe
> > > it should be considered as child of the grf.
> > 
> > This follows how pinctrl was added for RK3576 and what is proposed for
> > RK3562 [2]. I have too little knowledge to know if this needs to change
> > or if this should follow similar SoCs.
> > 
> > [2] https://lore.kernel.org/r/20250227111913.2344207-15-kever.yang at rock-chips.com
> 
> The reg address shouldn't matter here I think.
> 
> The "soc"-bus describes the elements contained in the soc (surrounding the
> cpu cores) and the pinctrl controller definitly is part of the soc itself.
> 
> So when looking at the scope, it does belong there and also the
>  gpio-controller elements do have mmio addresses :-)

Thanks for the explanation, it makes sense to me.

> Heiko
> 

Best regards,
Yao Zi



From ziyao at disroot.org  Sun Mar  2 08:16:36 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun, 2 Mar 2025 16:16:36 +0000
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <d6928adc-1df2-494f-a3d3-7b028c220547@kwiboo.se>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104835.36439-1-ziyao@disroot.org>
 <0aefd292-7980-434d-9c18-4ab9f6a0b40e@kwiboo.se>
 <Z8MklJfFz2EA6oNS@pie.lan>
 <d6928adc-1df2-494f-a3d3-7b028c220547@kwiboo.se>
Message-ID: <Z8SEZOoQWiS4jl7n@pie.lan>

On Sun, Mar 02, 2025 at 12:56:42PM +0100, Jonas Karlman wrote:
> Hi Yao Zi,
> 
> On 2025-03-01 16:15, Yao Zi wrote:
> > On Sat, Mar 01, 2025 at 02:01:05PM +0100, Jonas Karlman wrote:
> >> Hi,
> >>
> >> On 2025-03-01 11:48, Yao Zi wrote:
> >>> SD-card is available on Radxa E20C board.
> >>>
> >>> Signed-off-by: Yao Zi <ziyao at disroot.org>
> >>> ---
> >>>  arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 14 ++++++++++++++
> >>>  1 file changed, 14 insertions(+)
> >>>
> >>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> >>> index d2cdb63d4a9d..473065aa4228 100644
> >>> --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> >>> +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> >>> @@ -12,6 +12,10 @@ / {
> >>>  	model = "Radxa E20C";
> >>>  	compatible = "radxa,e20c", "rockchip,rk3528";
> >>>  
> >>> +	aliases {
> >>> +		mmc0 = &sdmmc;
> >>
> >> Suggest using mmc1 for sd-card because the e20c typically have onboard
> >> emmc, compared to removable sd-card.
> > 
> > My board doesn't have an eMMC: it's optional as well, but all variants
> > of Radxa E20C come with an SD-card interface. The vendor devicetree sets
> > sdmmc as mmc0 as well[1].
> 
> This is strange as Radxa typically want to align with mmc0=emmc and
> mmc1=sd-card, as seen in [3] and [4].
> 
>   Align with other Radxa products.
>   - mmc0 is eMMC
>   - mmc1 is microSD
> 
> Also mainline U-Boot for Rockchip SoCs typically always treat mmc0 as
> emmc and mmc1 as sd-card, and for most SoCs it will even override the
> board aliases to have some predictability across boards.
> 
> > 
> > I won't insist on it and am willing to take the change if you still
> > consider mmc0 is better.
> 
> Yes, my position is that we should use following:

Ack. I got your point but there's a typo (s/mmc0/mmc1) in my reply.

>   mmc0 = &sdhci;
>   mmc1 = &sdmmc;
> 
> I will send out a short sdhci series based on top of v2 of this series.
> Driver changes was not needed to get basic sdhci working on RK3528 and
> is only required to get HS400 modes working.
> 
> [3] https://lore.kernel.org/r/20240620224435.2752-1-naoki at radxa.com
> [4] https://lore.kernel.org/r/20240619050047.1217-2-naoki at radxa.com
> 
> > 
> >>> +	};
> >>> +
> >>>  	chosen {
> >>>  		stdout-path = "serial0:1500000n8";
> >>>  	};
> >>> @@ -20,3 +24,13 @@ chosen {
> >>>  &uart0 {
> >>>  	status = "okay";
> >>>  };
> >>> +
> >>> +&sdmmc {
> 
> This node should be placed above &uart0 to be in alphabetical order.
> 

The original patch keeps the order of nodes in the SoC devicetree
(sorted by MMIO address), but alphabetical order seems more common. Will
fix in v2, thanks.

> >>> +	bus-width = <4>;
> >>> +	cap-mmc-highspeed;
> >>> +	cap-sd-highspeed;
> >>> +	disable-wp;
> >>> +	rockchip,default-sample-phase = <90>;
> >>> +	sd-uhs-sdr104;
 
Thanks,
Yao Zi


From dmitry.baryshkov at linaro.org  Sun Mar  2 08:21:06 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 2 Mar 2025 18:21:06 +0200
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
 <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>
Message-ID: <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>

On Sun, Mar 02, 2025 at 06:34:22PM +0800, Andy Yan wrote:
> 
> 
> Hi Dmitry?
>    Thank you for your review?
>    Please also review my inline reply.
>       
> ? 2025-03-02 02:14:19?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
> >On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
> >> From: Andy Yan <andy.yan at rock-chips.com>
> >> 
> >> The DW DP TX Controller is compliant with the DisplayPort Specification
> >> Version 1.4 with the following features:
> >> 
> >> * DisplayPort 1.4a
> >> * Main Link: 1/2/4 lanes
> >> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
> >> * AUX channel 1Mbps
> >> * Single Stream Transport(SST)
> >> * Multistream Transport (MST)
> >> *?Type-C support (alternate mode)
> >> * HDCP 2.2, HDCP 1.3
> >> * Supports up to 8/10 bits per color component
> >> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
> >> * Pixel clock up to 594MHz
> >> * I2S, SPDIF audio interface
> >> 
> >> Add library with common helpers to make it can be shared with
> >> other SoC.
> >> 
> >> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> >> 
> >> drm/bridge: cleanup
> >
> >Stray line?
> 
> Sorry, will be removed.
> 
> >
> >> 
> >> ---
> >> 
> >>  drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
> >>  drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
> >>  drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
> >>  include/drm/bridge/dw_dp.h               |   19 +
> >>  4 files changed, 2182 insertions(+)
> >>  create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
> >>  create mode 100644 include/drm/bridge/dw_dp.h
> >> 
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
> >> index f3ab2f985f8c..2c5e532410de 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
> >> +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
> >> @@ -1,4 +1,11 @@
> >>  # SPDX-License-Identifier: GPL-2.0-only
> >> +config DRM_DW_DP
> >> +	tristate
> >> +	select DRM_DISPLAY_HELPER
> >> +	select DRM_DISPLAY_DP_HELPER
> >> +	select DRM_KMS_HELPER
> >> +	select REGMAP_MMIO
> >> +
> >>  config DRM_DW_HDMI
> >>  	tristate
> >>  	select DRM_DISPLAY_HDMI_HELPER
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
> >> index 9dc376d220ad..4dada44029ac 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/Makefile
> >> +++ b/drivers/gpu/drm/bridge/synopsys/Makefile
> >> @@ -1,4 +1,5 @@
> >>  # SPDX-License-Identifier: GPL-2.0-only
> >> +obj-$(CONFIG_DRM_DW_DP) += dw-dp.o
> >>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
> >>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
> >>  obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> >> new file mode 100644
> >> index 000000000000..6ecbe9851369
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> >> @@ -0,0 +1,2155 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Synopsys DesignWare Cores DisplayPort Transmitter Controller
> >> + *
> >> + * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
> >> + *
> >> + * Author: Andy Yan <andy.yan at rock-chips.com>
> >> + */
> >> +#include <linux/bitfield.h>
> >> +#include <linux/clk.h>
> >> +#include <linux/component.h>
> >> +#include <linux/iopoll.h>
> >> +#include <linux/irq.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/of_graph.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/regmap.h>
> >> +#include <linux/reset.h>
> >> +#include <linux/phy/phy.h>
> >> +#include <linux/unaligned.h>
> >> +
> >> +#include <drm/bridge/dw_dp.h>
> >> +#include <drm/drm_atomic_helper.h>
> >> +#include <drm/drm_bridge.h>
> >> +#include <drm/drm_bridge_connector.h>
> >> +#include <drm/display/drm_dp_helper.h>
> >> +#include <drm/display/drm_hdmi_helper.h>
> >> +#include <drm/drm_edid.h>
> >> +#include <drm/drm_of.h>
> >> +#include <drm/drm_print.h>
> >> +#include <drm/drm_probe_helper.h>
> >> +#include <drm/drm_simple_kms_helper.h>
> >> +
> >> +#include <uapi/linux/media-bus-format.h>
> >> +
> >> +#define DW_DP_VERSION_NUMBER			0x0000
> >> +#define DW_DP_VERSION_TYPE			0x0004
> >> +#define DW_DP_ID					0x0008
> >> +
> >> +#define DW_DP_CONFIG_REG1			0x0100
> >> +#define DW_DP_CONFIG_REG2			0x0104
> >> +#define DW_DP_CONFIG_REG3			0x0108
> >> +
> >> +#define DW_DP_CCTL				0x0200
> >> +#define FORCE_HPD				BIT(4)
> >> +#define DEFAULT_FAST_LINK_TRAIN_EN		BIT(2)
> >> +#define ENHANCE_FRAMING_EN			BIT(1)
> >> +#define SCRAMBLE_DIS				BIT(0)
> >> +#define DW_DP_SOFT_RESET_CTRL			0x0204
> >> +#define VIDEO_RESET				BIT(5)
> >> +#define AUX_RESET				BIT(4)
> >> +#define AUDIO_SAMPLER_RESET			BIT(3)
> >> +#define HDCP_MODULE_RESET			BIT(2)
> >> +#define PHY_SOFT_RESET				BIT(1)
> >> +#define CONTROLLER_RESET			BIT(0)
> >> +
> >> +#define DW_DP_VSAMPLE_CTRL			0x0300
> >> +#define PIXEL_MODE_SELECT			GENMASK(22, 21)
> >> +#define VIDEO_MAPPING				GENMASK(20, 16)
> >> +#define VIDEO_STREAM_ENABLE			BIT(5)
> >> +
> >> +#define DW_DP_VSAMPLE_STUFF_CTRL1		0x0304
> >> +
> >> +#define DW_DP_VSAMPLE_STUFF_CTRL2		0x0308
> >> +
> >> +#define DW_DP_VINPUT_POLARITY_CTRL		0x030c
> >> +#define DE_IN_POLARITY				BIT(2)
> >> +#define HSYNC_IN_POLARITY			BIT(1)
> >> +#define VSYNC_IN_POLARITY			BIT(0)
> >> +
> >> +#define DW_DP_VIDEO_CONFIG1			0x0310
> >> +#define HACTIVE					GENMASK(31, 16)
> >> +#define HBLANK					GENMASK(15, 2)
> >> +#define I_P					BIT(1)
> >> +#define R_V_BLANK_IN_OSC			BIT(0)
> >> +
> >> +#define DW_DP_VIDEO_CONFIG2			0x0314
> >> +#define VBLANK					GENMASK(31, 16)
> >> +#define VACTIVE					GENMASK(15, 0)
> >> +
> >> +#define DW_DP_VIDEO_CONFIG3			0x0318
> >> +#define H_SYNC_WIDTH				GENMASK(31, 16)
> >> +#define H_FRONT_PORCH				GENMASK(15, 0)
> >> +
> >> +#define DW_DP_VIDEO_CONFIG4			0x031c
> >> +#define V_SYNC_WIDTH				GENMASK(31, 16)
> >> +#define V_FRONT_PORCH				GENMASK(15, 0)
> >> +
> >> +#define DW_DP_VIDEO_CONFIG5			0x0320
> >> +#define INIT_THRESHOLD_HI			GENMASK(22, 21)
> >> +#define AVERAGE_BYTES_PER_TU_FRAC		GENMASK(19, 16)
> >> +#define INIT_THRESHOLD				GENMASK(13, 7)
> >> +#define AVERAGE_BYTES_PER_TU			GENMASK(6, 0)
> >> +
> >> +#define DW_DP_VIDEO_MSA1				0x0324
> >> +#define VSTART					GENMASK(31, 16)
> >> +#define HSTART					GENMASK(15, 0)
> >> +
> >> +#define DW_DP_VIDEO_MSA2			0x0328
> >> +#define MISC0					GENMASK(31, 24)
> >> +
> >> +#define DW_DP_VIDEO_MSA3			0x032c
> >> +#define MISC1					GENMASK(31, 24)
> >> +
> >> +#define DW_DP_VIDEO_HBLANK_INTERVAL		0x0330
> >> +#define HBLANK_INTERVAL_EN			BIT(16)
> >> +#define HBLANK_INTERVAL				GENMASK(15, 0)
> >> +
> >> +#define DW_DP_AUD_CONFIG1			0x0400
> >> +#define AUDIO_TIMESTAMP_VERSION_NUM		GENMASK(29, 24)
> >> +#define AUDIO_PACKET_ID				GENMASK(23, 16)
> >> +#define AUDIO_MUTE				BIT(15)
> >> +#define NUM_CHANNELS				GENMASK(14, 12)
> >> +#define HBR_MODE_ENABLE				BIT(10)
> >> +#define AUDIO_DATA_WIDTH			GENMASK(9, 5)
> >> +#define AUDIO_DATA_IN_EN			GENMASK(4, 1)
> >> +#define AUDIO_INF_SELECT			BIT(0)
> >> +
> >> +#define DW_DP_SDP_VERTICAL_CTRL			0x0500
> >> +#define EN_VERTICAL_SDP				BIT(2)
> >> +#define EN_AUDIO_STREAM_SDP			BIT(1)
> >> +#define EN_AUDIO_TIMESTAMP_SDP			BIT(0)
> >> +#define DW_DP_SDP_HORIZONTAL_CTRL		0x0504
> >> +#define EN_HORIZONTAL_SDP			BIT(2)
> >> +#define DW_DP_SDP_STATUS_REGISTER		0x0508
> >> +#define DW_DP_SDP_MANUAL_CTRL			0x050c
> >> +#define DW_DP_SDP_STATUS_EN			0x0510
> >> +
> >> +#define DW_DP_SDP_REGISTER_BANK			0x0600
> >> +#define SDP_REGS				GENMASK(31, 0)
> >> +
> >> +#define DW_DP_PHYIF_CTRL			0x0a00
> >> +#define PHY_WIDTH				BIT(25)
> >> +#define PHY_POWERDOWN				GENMASK(20, 17)
> >> +#define PHY_BUSY				GENMASK(15, 12)
> >> +#define SSC_DIS					BIT(16)
> >> +#define XMIT_ENABLE				GENMASK(11, 8)
> >> +#define PHY_LANES				GENMASK(7, 6)
> >> +#define PHY_RATE				GENMASK(5, 4)
> >> +#define TPS_SEL					GENMASK(3, 0)
> >> +
> >> +#define DW_DP_PHY_TX_EQ				0x0a04
> >> +#define DW_DP_CUSTOMPAT0			0x0a08
> >> +#define DW_DP_CUSTOMPAT1			0x0a0c
> >> +#define DW_DP_CUSTOMPAT2			0x0a10
> >> +#define DW_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	0x0a14
> >> +#define DW_DP_PHYIF_PWRDOWN_CTRL		0x0a18
> >> +
> >> +#define DW_DP_AUX_CMD				0x0b00
> >> +#define AUX_CMD_TYPE				GENMASK(31, 28)
> >> +#define AUX_ADDR				GENMASK(27, 8)
> >> +#define I2C_ADDR_ONLY				BIT(4)
> >> +#define AUX_LEN_REQ				GENMASK(3, 0)
> >> +
> >> +#define DW_DP_AUX_STATUS			0x0b04
> >> +#define AUX_TIMEOUT				BIT(17)
> >> +#define AUX_BYTES_READ				GENMASK(23, 19)
> >> +#define AUX_STATUS				GENMASK(7, 4)
> >> +
> >> +#define DW_DP_AUX_DATA0				0x0b08
> >> +#define DW_DP_AUX_DATA1				0x0b0c
> >> +#define DW_DP_AUX_DATA2				0x0b10
> >> +#define DW_DP_AUX_DATA3				0x0b14
> >> +
> >> +#define DW_DP_GENERAL_INTERRUPT			0x0d00
> >> +#define VIDEO_FIFO_OVERFLOW_STREAM0		BIT(6)
> >> +#define AUDIO_FIFO_OVERFLOW_STREAM0		BIT(5)
> >> +#define SDP_EVENT_STREAM0			BIT(4)
> >> +#define AUX_CMD_INVALID				BIT(3)
> >> +#define HDCP_EVENT				BIT(2)
> >> +#define AUX_REPLY_EVENT				BIT(1)
> >> +#define HPD_EVENT				BIT(0)
> >> +
> >> +#define DW_DP_GENERAL_INTERRUPT_ENABLE		0x0d04
> >> +#define HDCP_EVENT_EN				BIT(2)
> >> +#define AUX_REPLY_EVENT_EN			BIT(1)
> >> +#define HPD_EVENT_EN				BIT(0)
> >> +
> >> +#define DW_DP_HPD_STATUS			0x0d08
> >> +#define HPD_STATE				GENMASK(11, 9)
> >> +#define HPD_STATUS				BIT(8)
> >> +#define HPD_HOT_UNPLUG				BIT(2)
> >> +#define HPD_HOT_PLUG				BIT(1)
> >> +#define HPD_IRQ					BIT(0)
> >> +
> >> +#define DW_DP_HPD_INTERRUPT_ENABLE		0x0d0c
> >> +#define HPD_UNPLUG_ERR_EN			BIT(3)
> >> +#define HPD_UNPLUG_EN				BIT(2)
> >> +#define HPD_PLUG_EN				BIT(1)
> >> +#define HPD_IRQ_EN				BIT(0)
> >> +
> >> +#define DW_DP_HDCP_CFG				0x0e00
> >> +#define DPCD12PLUS				BIT(7)
> >> +#define CP_IRQ					BIT(6)
> >> +#define BYPENCRYPTION				BIT(5)
> >> +#define HDCP_LOCK				BIT(4)
> >> +#define ENCRYPTIONDISABLE			BIT(3)
> >> +#define ENABLE_HDCP_13				BIT(2)
> >> +#define ENABLE_HDCP				BIT(1)
> >> +
> >> +#define DW_DP_HDCP_OBS				0x0e04
> >> +#define HDCP22_RE_AUTHENTICATION_REQ		BIT(31)
> >> +#define HDCP22_AUTHENTICATION_FAILED		BIT(30)
> >> +#define HDCP22_AUTHENTICATION_SUCCESS		BIT(29)
> >> +#define HDCP22_CAPABLE_SINK			BIT(28)
> >> +#define HDCP22_SINK_CAP_CHECK_COMPLETE		BIT(27)
> >> +#define HDCP22_STATE				GENMASK(26, 24)
> >> +#define HDCP22_BOOTED				BIT(23)
> >> +#define HDCP13_BSTATUS				GENMASK(22, 19)
> >> +#define REPEATER				BIT(18)
> >> +#define HDCP_CAPABLE				BIT(17)
> >> +#define STATEE					GENMASK(16, 14)
> >> +#define STATEOEG				GENMASK(13, 11)
> >> +#define STATER					GENMASK(10, 8)
> >> +#define STATEA					GENMASK(7, 4)
> >> +#define SUBSTATEA				GENMASK(3, 1)
> >> +#define HDCPENGAGED				BIT(0)
> >> +
> >> +#define DW_DP_HDCP_APIINTCLR			0x0e08
> >> +#define DW_DP_HDCP_APIINTSTAT			0x0e0c
> >> +#define DW_DP_HDCP_APIINTMSK			0x0e10
> >> +#define HDCP22_GPIOINT				BIT(8)
> >> +#define HDCP_ENGAGED				BIT(7)
> >> +#define HDCP_FAILED				BIT(6)
> >> +#define KSVSHA1CALCDONEINT			BIT(5)
> >> +#define AUXRESPNACK7TIMES			BIT(4)
> >> +#define AUXRESPTIMEOUT				BIT(3)
> >> +#define AUXRESPDEFER7TIMES			BIT(2)
> >> +#define KSVACCESSINT				BIT(0)
> >> +
> >> +#define DW_DP_HDCP_KSVMEMCTRL			0x0e18
> >> +#define KSVSHA1STATUS				BIT(4)
> >> +#define KSVMEMACCESS				BIT(1)
> >> +#define KSVMEMREQUEST				BIT(0)
> >> +
> >> +#define DW_DP_HDCP_REG_BKSV0			0x3600
> >> +#define DW_DP_HDCP_REG_BKSV1			0x3604
> >> +#define DW_DP_HDCP_REG_ANCONF			0x3608
> >> +#define AN_BYPASS				BIT(0)
> >> +
> >> +#define DW_DP_HDCP_REG_AN0			0x360c
> >> +#define DW_DP_HDCP_REG_AN1			0x3610
> >> +#define DW_DP_HDCP_REG_RMLCTL			0x3614
> >> +#define ODPK_DECRYPT_ENABLE			BIT(0)
> >> +
> >> +#define DW_DP_HDCP_REG_RMLSTS			0x3618
> >> +#define IDPK_WR_OK_STS				BIT(6)
> >> +#define	IDPK_DATA_INDEX				GENMASK(5, 0)
> >> +#define DW_DP_HDCP_REG_SEED			0x361c
> >> +#define DW_DP_HDCP_REG_DPK0			0x3620
> >> +#define DW_DP_HDCP_REG_DPK1			0x3624
> >> +#define DW_DP_HDCP22_GPIOSTS			0x3628
> >> +#define DW_DP_HDCP22_GPIOCHNGSTS		0x362c
> >> +#define DW_DP_HDCP_REG_DPK_CRC			0x3630
> >> +
> >> +#define DW_DP_MAX_REGISTER			DW_DP_HDCP_REG_DPK_CRC
> >> +
> >> +#define SDP_REG_BANK_SIZE			16
> >> +
> >> +struct dw_dp_link_caps {
> >> +	bool enhanced_framing;
> >> +	bool tps3_supported;
> >> +	bool tps4_supported;
> >> +	bool fast_training;
> >> +	bool channel_coding;
> >> +	bool ssc;
> >> +};
> >> +
> >> +struct dw_dp_link_train_set {
> >> +	unsigned int voltage_swing[4];
> >> +	unsigned int pre_emphasis[4];
> >> +	bool voltage_max_reached[4];
> >> +	bool pre_max_reached[4];
> >> +};
> >> +
> >> +struct dw_dp_link_train {
> >> +	struct dw_dp_link_train_set request;
> >> +	struct dw_dp_link_train_set adjust;
> >> +	bool clock_recovered;
> >> +	bool channel_equalized;
> >> +};
> >> +
> >> +struct dw_dp_link {
> >> +	u8 dpcd[DP_RECEIVER_CAP_SIZE];
> >> +	unsigned char revision;
> >> +	unsigned int rate;
> >> +	unsigned int lanes;
> >> +	u8 sink_count;
> >> +	u8 vsc_sdp_supported;
> >> +	struct dw_dp_link_caps caps;
> >> +	struct dw_dp_link_train train;
> >> +	struct drm_dp_desc desc;
> >> +};
> >> +
> >> +struct dw_dp_video {
> >> +	struct drm_display_mode mode;
> >> +	u8 video_mapping;
> >> +	u8 pixel_mode;
> >> +	u8 color_format;
> >> +	u8 bpc;
> >> +	u8 bpp;
> >> +};
> >> +
> >> +struct dw_dp_sdp {
> >> +	struct dp_sdp_header header;
> >> +	u8 db[32];
> >
> >struct dp_sdp, please
> 
> Ok, will do.
> 
> >
> >> +	unsigned long flags;
> >> +};
> >> +
> >> +struct dw_dp_hotplug {
> >> +	bool long_hpd;
> >> +};
> >> +
> >> +struct dw_dp {
> >> +	struct drm_bridge bridge;
> >> +	struct device *dev;
> >> +	struct regmap *regmap;
> >> +	struct phy *phy;
> >> +	struct clk *apb_clk;
> >> +	struct clk *aux_clk;
> >> +	struct clk *i2s_clk;
> >> +	struct clk *spdif_clk;
> >> +	struct clk *hdcp_clk;
> >> +	struct reset_control *rstc;
> >> +	struct completion complete;
> >> +	int irq;
> >> +	struct work_struct hpd_work;
> >> +	struct dw_dp_hotplug hotplug;
> >> +	struct mutex irq_lock;
> >> +
> >> +	struct drm_dp_aux aux;
> >> +
> >> +	struct dw_dp_link link;
> >> +	struct dw_dp_video video;
> >> +	const struct dw_dp_plat_data *plat_data;
> >> +
> >> +	DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> >> +};
> >> +
> >> +enum {
> >> +	DW_DP_RGB_6BIT,
> >> +	DW_DP_RGB_8BIT,
> >> +	DW_DP_RGB_10BIT,
> >> +	DW_DP_RGB_12BIT,
> >> +	DW_DP_RGB_16BIT,
> >> +	DW_DP_YCBCR444_8BIT,
> >> +	DW_DP_YCBCR444_10BIT,
> >> +	DW_DP_YCBCR444_12BIT,
> >> +	DW_DP_YCBCR444_16BIT,
> >> +	DW_DP_YCBCR422_8BIT,
> >> +	DW_DP_YCBCR422_10BIT,
> >> +	DW_DP_YCBCR422_12BIT,
> >> +	DW_DP_YCBCR422_16BIT,
> >> +	DW_DP_YCBCR420_8BIT,
> >> +	DW_DP_YCBCR420_10BIT,
> >> +	DW_DP_YCBCR420_12BIT,
> >> +	DW_DP_YCBCR420_16BIT,
> >> +};
> >> +
> >> +enum {
> >> +	DW_DP_MP_SINGLE_PIXEL,
> >> +	DW_DP_MP_DUAL_PIXEL,
> >> +	DW_DP_MP_QUAD_PIXEL,
> >> +};
> >> +
> >> +enum {
> >> +	DW_DP_SDP_VERTICAL_INTERVAL = BIT(0),
> >> +	DW_DP_SDP_HORIZONTAL_INTERVAL = BIT(1),
> >> +};
> >> +
> >> +enum {
> >> +	DW_DP_HPD_STATE_IDLE,
> >> +	DW_DP_HPD_STATE_UNPLUG,
> >> +	DP_DP_HPD_STATE_TIMEOUT = 4,
> >> +	DW_DP_HPD_STATE_PLUG = 7
> >> +};
> >> +
> >> +enum {
> >> +	DW_DP_PHY_PATTERN_NONE,
> >> +	DW_DP_PHY_PATTERN_TPS_1,
> >> +	DW_DP_PHY_PATTERN_TPS_2,
> >> +	DW_DP_PHY_PATTERN_TPS_3,
> >> +	DW_DP_PHY_PATTERN_TPS_4,
> >> +	DW_DP_PHY_PATTERN_SERM,
> >> +	DW_DP_PHY_PATTERN_PBRS7,
> >> +	DW_DP_PHY_PATTERN_CUSTOM_80BIT,
> >> +	DW_DP_PHY_PATTERN_CP2520_1,
> >> +	DW_DP_PHY_PATTERN_CP2520_2,
> >> +};
> >> +
> >> +struct dw_dp_output_format {
> >> +	u32 bus_format;
> >> +	u32 color_format;
> >> +	u8 video_mapping;
> >> +	u8 bpc;
> >> +	u8 bpp;
> >> +};
> >> +
> >> +static const struct dw_dp_output_format dw_dp_output_formats[] = {
> >> +	{ MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
> >> +	{ MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
> >> +	{ MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
> >> +	{ MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
> >> +	{ MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
> >> +	{ MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
> >> +	{ MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
> >> +	{ MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
> >> +	{ MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
> >> +};
> >> +
> >> +static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++)
> >> +		if (dw_dp_output_formats[i].bus_format == bus_format)
> >> +			return &dw_dp_output_formats[i];
> >> +
> >> +	return &dw_dp_output_formats[1];
> >
> >Why? Shouldn't it be NULL?
> 
> At first, we considered RGB888_1X24  to be universally applicable across all scenarios, 
> but upon re-evaluation, this assumption proved inaccurate. Specifically, RGB888 may
> encounter bandwidth limitations in high-resolution or high-refresh-rate environments
> 
> So returning NULL would be more appropriate here.
> 
> >
> >> +}
> >> +
> >> +static inline struct dw_dp *bridge_to_dp(struct drm_bridge *b)
> >> +{
> >> +	return container_of(b, struct dw_dp, bridge);
> >> +}
> >> +
> >> +static inline void dw_dp_phy_set_pattern(struct dw_dp *dp, u32 pattern)
> >> +{
> >> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, TPS_SEL,
> >> +			   FIELD_PREP(TPS_SEL, pattern));
> >> +}
> >> +
> >> +static void dw_dp_phy_xmit_enable(struct dw_dp *dp, u32 lanes)
> >> +{
> >> +	u32 xmit_enable;
> >> +
> >> +	switch (lanes) {
> >> +	case 4:
> >> +	case 2:
> >> +	case 1:
> >> +		xmit_enable = GENMASK(lanes - 1, 0);
> >> +		break;
> >> +	case 0:
> >> +	default:
> >> +		xmit_enable = 0;
> >> +		break;
> >> +	}
> >> +
> >> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, XMIT_ENABLE,
> >> +			   FIELD_PREP(XMIT_ENABLE, xmit_enable));
> >> +}
> >> +
> >> +static bool dw_dp_bandwidth_ok(struct dw_dp *dp,
> >> +			       const struct drm_display_mode *mode, u32 bpp,
> >> +			       unsigned int lanes, unsigned int rate)
> >> +{
> >> +	u32 max_bw, req_bw;
> >> +
> >> +	req_bw = mode->clock * bpp / 8;
> >> +	max_bw = lanes * rate;
> >> +	if (req_bw > max_bw)
> >> +		return false;
> >> +
> >> +	return true;
> >> +}
> >> +
> >> +static bool dw_dp_hpd_detect(struct dw_dp *dp)
> >> +{
> >> +	u32 value;
> >> +
> >> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >> +
> >> +	return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> >> +}
> >> +
> >> +static void dw_dp_link_caps_reset(struct dw_dp_link_caps *caps)
> >> +{
> >> +	caps->enhanced_framing = false;
> >> +	caps->tps3_supported = false;
> >> +	caps->tps4_supported = false;
> >> +	caps->fast_training = false;
> >> +	caps->channel_coding = false;
> >> +}
> >> +
> >> +static void dw_dp_link_reset(struct dw_dp_link *link)
> >> +{
> >> +	link->vsc_sdp_supported = 0;
> >> +	link->sink_count = 0;
> >> +	link->revision = 0;
> >> +	link->rate = 0;
> >> +	link->lanes = 0;
> >> +
> >> +	dw_dp_link_caps_reset(&link->caps);
> >> +	memset(link->dpcd, 0, sizeof(link->dpcd));
> >> +}
> >> +
> >> +static int dw_dp_link_power_up(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	int ret;
> >> +	u8 value;
> >> +
> >> +	if (link->revision < DP_DPCD_REV_11)
> >> +		return 0;
> >> +
> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	value &= ~DP_SET_POWER_MASK;
> >> +	value |= DP_SET_POWER_D0;
> >> +
> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	usleep_range(1000, 2000);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_power_down(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	int ret;
> >> +	u8 value;
> >> +
> >> +	if (link->revision < DP_DPCD_REV_11)
> >> +		return 0;
> >> +
> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	value &= ~DP_SET_POWER_MASK;
> >> +	value |= DP_SET_POWER_D3;
> >> +
> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >
> >Would you please mind pulling these two functions to DRM DP helpers?
> >There are enough users to make this into a common code.
> 
> Yes, when developing this patch, I had the same realization. 
> The processing logic for MSM/Cadence/ANX6345/tegra follows
> a similar approach.
> I had originally planned to defer this refactoring until the series of patches is accepted. 
> Additionally, I have other pending tasks in my TODO list, such as fully decoupling the 
> bridge driver and encoder/connector components across all Rockchip platforms?
> But I prioritize completing these foundational features before go to next steps,
> Is this acceptable ?

You can add necessary helpers as one of the first patches in the
series. Convert one or several platforms that use drm-misc (i.e. not
MSM, AMD, i915, nouveau) and send conversion of the rest of the
platforms as followups.

> 
> >
> >> +	return 0;
> >> +}
> >> +
> >> +static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >> +				 const struct drm_dp_desc *desc)
> >> +{
> >> +	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
> >> +	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
> >> +	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);
> >
> >
> >isn't it drm_dp_read_sink_count_cap() ?
> 
> I will have a try, since this drm_dp_read_sink_count_cap requires a connector parameter, 
> I need to figure out how to get the connector here.

Maybe Maxime's series will you here, see [1].

[1] https://lore.kernel.org/dri-devel/20250225-bridge-connector-v4-4-7ecb07b09cad at kernel.org/

> 
> >
> >> +}
> >> +
> >> +static int dw_dp_link_parse(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u8 dpcd;
> >> +	int ret;
> >> +
> >> +	dw_dp_link_reset(link);
> >> +
> >> +	ret = drm_dp_read_dpcd_caps(&dp->aux, link->dpcd);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	drm_dp_read_desc(&dp->aux, &link->desc, drm_dp_is_branch(link->dpcd));
> >> +
> >> +	if (dw_dp_has_sink_count(link->dpcd, &link->desc)) {
> >> +		ret = drm_dp_read_sink_count(&dp->aux);
> >> +		if (ret < 0)
> >> +			return ret;
> >> +
> >> +		link->sink_count = ret;
> >> +
> >> +		/* Dongle connected, but no display */
> >> +		if (!link->sink_count)
> >> +			return -ENODEV;
> >> +	}
> >> +
> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dpcd);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	link->vsc_sdp_supported = !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
> >> +
> >> +	link->revision = link->dpcd[DP_DPCD_REV];
> >> +	link->rate = min_t(u32, min(dp->plat_data->max_link_rate,
> >> +				    dp->phy->attrs.max_link_rate * 100),
> >> +			   drm_dp_max_link_rate(link->dpcd));
> >> +	link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
> >> +			    drm_dp_max_lane_count(link->dpcd));
> >> +
> >> +	link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
> >> +	link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
> >> +	link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
> >> +	link->caps.fast_training = drm_dp_fast_training_cap(link->dpcd);
> >> +	link->caps.channel_coding = drm_dp_channel_coding_supported(link->dpcd);
> >> +	link->caps.ssc = !!(link->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes,
> >> +				    struct dw_dp_link_train_set *train_set)
> >> +{
> >> +	union phy_configure_opts phy_cfg;
> >> +	unsigned int *vs, *pe;
> >> +	u8 buf[4];
> >> +	int i, ret;
> >> +
> >> +	vs = train_set->voltage_swing;
> >> +	pe = train_set->pre_emphasis;
> >> +
> >> +	for (i = 0; i < lanes; i++) {
> >> +		phy_cfg.dp.voltage[i] = vs[i];
> >> +		phy_cfg.dp.pre[i] = pe[i];
> >> +	}
> >> +
> >> +	phy_cfg.dp.lanes = lanes;
> >> +	phy_cfg.dp.link_rate = rate / 100;
> >> +	phy_cfg.dp.set_lanes = false;
> >> +	phy_cfg.dp.set_rate = false;
> >
> >You don't need to set lanes / link_rate if set_lanes and set_rate is
> >false.
> This is because the rk_udphy_dp_phy_configure function first verifies the rate and lane settings,
> treating any uninitialized parameters as invalid configurations

I think this breaks the API. One should not be verifying the fields
which are not to be set. Please update the PHY driver.

> 
> >
> >> +	phy_cfg.dp.set_voltages = true;
> >> +
> >> +	ret = phy_configure(dp->phy, &phy_cfg);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	for (i = 0; i < lanes; i++) {
> >> +		buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
> >> +			 (pe[i] << DP_TRAIN_PRE_EMPHASIS_SHIFT);
> >> +		if (train_set->voltage_max_reached[i])
> >> +			buf[i] |= DP_TRAIN_MAX_SWING_REACHED;
> >> +		if (train_set->pre_max_reached[i])
> >> +			buf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
> >> +	}
> >> +
> >> +	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, lanes);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_train_update_vs_emph(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	struct dw_dp_link_train_set *request = &link->train.request;
> >> +
> >> +	return dw_dp_phy_update_vs_emph(dp, dp->link.rate, dp->link.lanes, request);
> >
> >Inline it mayeb?
> 
> Okay? will do?
> >
> >> +}
> >> +
> >> +static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
> >> +			       unsigned int lanes, bool ssc)
> >> +{
> >> +	union phy_configure_opts phy_cfg;
> >> +	int ret;
> >> +
> >> +	/* Move PHY to P3 */
> >> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
> >> +			   FIELD_PREP(PHY_POWERDOWN, 0x3));
> >> +
> >> +	phy_cfg.dp.lanes = lanes;
> >> +	phy_cfg.dp.link_rate = rate / 100;
> >> +	phy_cfg.dp.ssc = ssc;
> >> +	phy_cfg.dp.set_lanes = true;
> >> +	phy_cfg.dp.set_rate = true;
> >> +	phy_cfg.dp.set_voltages = false;
> >> +	ret = phy_configure(dp->phy, &phy_cfg);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_LANES,
> >> +			   FIELD_PREP(PHY_LANES, lanes / 2));
> >> +
> >> +	/* Move PHY to P0 */
> >> +	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
> >> +			   FIELD_PREP(PHY_POWERDOWN, 0x0));
> >> +
> >> +	dw_dp_phy_xmit_enable(dp, lanes);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_configure(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u8 buf[2];
> >> +	int ret;
> >> +
> >> +	ret = dw_dp_phy_configure(dp, link->rate, link->lanes, link->caps.ssc);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	buf[0] = drm_dp_link_rate_to_bw_code(link->rate);
> >> +	buf[1] = link->lanes;
> >> +
> >> +	if (link->caps.enhanced_framing) {
> >> +		buf[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
> >> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
> >> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 1));
> >> +	} else {
> >> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
> >> +				   FIELD_PREP(ENHANCE_FRAMING_EN, 0));
> >> +	}
> >> +
> >> +	ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, sizeof(buf));
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	buf[0] = link->caps.ssc ? DP_SPREAD_AMP_0_5 : 0;
> >> +	buf[1] = link->caps.channel_coding ? DP_SET_ANSI_8B10B : 0;
> >> +
> >> +	ret = drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf));
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void dw_dp_link_train_init(struct dw_dp_link_train *train)
> >> +{
> >> +	struct dw_dp_link_train_set *request = &train->request;
> >> +	struct dw_dp_link_train_set *adjust = &train->adjust;
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < 4; i++) {
> >> +		request->voltage_swing[i] = 0;
> >> +		adjust->voltage_swing[i] = 0;
> >> +
> >> +		request->pre_emphasis[i] = 0;
> >> +		adjust->pre_emphasis[i] = 0;
> >> +
> >> +		request->voltage_max_reached[i] = false;
> >> +		adjust->voltage_max_reached[i] = false;
> >> +
> >> +		request->pre_max_reached[i] = false;
> >> +		adjust->pre_max_reached[i] = false;
> >> +	}
> >> +
> >> +	train->clock_recovered = false;
> >> +	train->channel_equalized = false;
> >> +}
> >> +
> >> +static bool dw_dp_link_train_valid(const struct dw_dp_link_train *train)
> >> +{
> >> +	return train->clock_recovered && train->channel_equalized;
> >> +}
> >> +
> >> +static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
> >> +{
> >> +	u8 buf = 0;
> >> +	int ret;
> >> +
> >> +	if (pattern && pattern != DP_TRAINING_PATTERN_4) {
> >> +		buf |= DP_LINK_SCRAMBLING_DISABLE;
> >> +
> >> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
> >> +				   FIELD_PREP(SCRAMBLE_DIS, 1));
> >> +	} else {
> >> +		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
> >> +				   FIELD_PREP(SCRAMBLE_DIS, 0));
> >> +	}
> >> +
> >> +	switch (pattern) {
> >> +	case DP_TRAINING_PATTERN_DISABLE:
> >> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_NONE);
> >> +		break;
> >> +	case DP_TRAINING_PATTERN_1:
> >> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_1);
> >> +		break;
> >> +	case DP_TRAINING_PATTERN_2:
> >> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_2);
> >> +		break;
> >> +	case DP_TRAINING_PATTERN_3:
> >> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_3);
> >> +		break;
> >> +	case DP_TRAINING_PATTERN_4:
> >> +		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_4);
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
> >> +				 buf | pattern);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static u8 dw_dp_voltage_max(u8 preemph)
> >> +{
> >> +	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
> >> +	case DP_TRAIN_PRE_EMPH_LEVEL_0:
> >> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
> >> +	case DP_TRAIN_PRE_EMPH_LEVEL_1:
> >> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
> >> +	case DP_TRAIN_PRE_EMPH_LEVEL_2:
> >> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
> >> +	case DP_TRAIN_PRE_EMPH_LEVEL_3:
> >> +	default:
> >> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
> >> +	}
> >> +}
> >> +
> >> +static void dw_dp_link_get_adjustments(struct dw_dp_link *link,
> >> +				       u8 status[DP_LINK_STATUS_SIZE])
> >> +{
> >> +	struct dw_dp_link_train_set *adjust = &link->train.adjust;
> >> +	u8 v = 0;
> >> +	u8 p = 0;
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < link->lanes; i++) {
> >> +		v = drm_dp_get_adjust_request_voltage(status, i);
> >> +		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
> >> +		if (p >=  DP_TRAIN_PRE_EMPH_LEVEL_3) {
> >> +			adjust->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
> >> +						  DP_TRAIN_PRE_EMPHASIS_SHIFT;
> >> +			adjust->pre_max_reached[i] = true;
> >> +		} else {
> >> +			adjust->pre_emphasis[i] = p >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
> >> +			adjust->pre_max_reached[i] = false;
> >> +		}
> >> +		v = min(v, dw_dp_voltage_max(p));
> >> +		if (v >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) {
> >> +			adjust->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
> >> +						   DP_TRAIN_VOLTAGE_SWING_SHIFT;
> >> +			adjust->voltage_max_reached[i] = true;
> >> +		} else {
> >> +			adjust->voltage_swing[i] = v >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
> >> +			adjust->voltage_max_reached[i] = false;
> >> +		}
> >> +	}
> >> +}
> >> +
> >> +static void dw_dp_link_train_adjust(struct dw_dp_link_train *train)
> >> +{
> >> +	struct dw_dp_link_train_set *request = &train->request;
> >> +	struct dw_dp_link_train_set *adjust = &train->adjust;
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < 4; i++) {
> >
> >Shouldn't it be a loop up to link->lanes?
> 
> Yeah, this makes sense?
> 
> 
> >
> >> +		if (request->voltage_swing[i] != adjust->voltage_swing[i])
> >> +			request->voltage_swing[i] = adjust->voltage_swing[i];
> >> +		if (request->voltage_max_reached[i] != adjust->voltage_max_reached[i])
> >> +			request->voltage_max_reached[i] = adjust->voltage_max_reached[i];
> >> +	}
> >> +
> >> +	for (i = 0; i < 4; i++) {
> >> +		if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
> >> +			request->pre_emphasis[i] = adjust->pre_emphasis[i];
> >> +		if (request->pre_max_reached[i] != adjust->pre_max_reached[i])
> >> +			request->pre_max_reached[i] = adjust->pre_max_reached[i];
> >
> >Why do you need separate request and adjustment structs?
> 
> I need to think about this issue further and will confirm how to proceed later.

Thanks! I really like your link training implementation, it is pretty
clear.

> 
> 
> >
> >> +	}
> >> +}
> >> +
> >> +static int dw_dp_link_clock_recovery(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u8 status[DP_LINK_STATUS_SIZE];
> >> +	unsigned int tries = 0;
> >> +	int ret;
> >> +
> >> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	for (;;) {
> >> +		ret = dw_dp_link_train_update_vs_emph(dp);
> >> +		if (ret)
> >> +			return ret;
> >> +
> >> +		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
> >> +
> >> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> >> +		if (ret < 0) {
> >> +			dev_err(dp->dev, "failed to read link status: %d\n", ret);
> >> +			return ret;
> >> +		}
> >> +
> >> +		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
> >> +			link->train.clock_recovered = true;
> >> +			break;
> >> +		}
> >> +
> >> +		dw_dp_link_get_adjustments(link, status);
> >> +
> >> +		if (link->train.request.voltage_swing[0] ==
> >> +		    link->train.adjust.voltage_swing[0])
> >
> >Should this take all lanes to account? I think it might be posssible to
> >drop the adjust / request split and adjust tries in
> >dw_dp_link_get_adjustments() instead.
> 
> Let me figure it out later?
> 
> >
> >> +			tries++;
> >> +		else
> >> +			tries = 0;
> >> +
> >> +		if (tries == 5)
> >> +			break;
> >> +
> >> +		dw_dp_link_train_adjust(&link->train);
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_channel_equalization(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u8 status[DP_LINK_STATUS_SIZE], pattern;
> >> +	unsigned int tries;
> >> +	int ret;
> >> +
> >> +	if (link->caps.tps4_supported)
> >> +		pattern = DP_TRAINING_PATTERN_4;
> >> +	else if (link->caps.tps3_supported)
> >> +		pattern = DP_TRAINING_PATTERN_3;
> >> +	else
> >> +		pattern = DP_TRAINING_PATTERN_2;
> >> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	for (tries = 1; tries < 5; tries++) {
> >> +		ret = dw_dp_link_train_update_vs_emph(dp);
> >> +		if (ret)
> >> +			return ret;
> >> +
> >> +		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
> >> +
> >> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> >> +		if (ret < 0)
> >> +			return ret;
> >> +
> >> +		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
> >> +			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
> >> +			link->train.clock_recovered = false;
> >> +			break;
> >> +		}
> >> +
> >> +		if (drm_dp_channel_eq_ok(status, link->lanes)) {
> >> +			link->train.channel_equalized = true;
> >> +			break;
> >> +		}
> >> +
> >> +		dw_dp_link_get_adjustments(link, status);
> >> +		dw_dp_link_train_adjust(&link->train);
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_downgrade(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	struct dw_dp_video *video = &dp->video;
> >> +
> >> +	switch (link->rate) {
> >> +	case 162000:
> >> +		return -EINVAL;
> >> +	case 270000:
> >> +		link->rate = 162000;
> >> +		break;
> >> +	case 540000:
> >> +		link->rate = 270000;
> >> +		break;
> >> +	case 810000:
> >> +		link->rate = 540000;
> >> +		break;
> >> +	}
> >> +
> >> +	if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
> >> +				link->rate))
> >> +		return -E2BIG;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_link_train_full(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	int ret;
> >> +
> >> +retry:
> >> +	dw_dp_link_train_init(&link->train);
> >> +
> >> +	dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
> >> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
> >> +
> >> +	ret = dw_dp_link_configure(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
> >> +		return ret;
> >> +	}
> >> +
> >> +	ret = dw_dp_link_clock_recovery(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "clock recovery failed: %d\n", ret);
> >> +		goto out;
> >> +	}
> >> +
> >> +	if (!link->train.clock_recovered) {
> >> +		dev_err(dp->dev, "clock recovery failed, downgrading link\n");
> >> +
> >> +		ret = dw_dp_link_downgrade(dp);
> >> +		if (ret < 0)
> >> +			goto out;
> >> +		else
> >> +			goto retry;
> >> +	}
> >> +
> >> +	dev_dbg(dp->dev, "clock recovery succeeded\n");
> >> +
> >> +	ret = dw_dp_link_channel_equalization(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "channel equalization failed: %d\n", ret);
> >> +		goto out;
> >> +	}
> >> +
> >> +	if (!link->train.channel_equalized) {
> >> +		dev_err(dp->dev, "channel equalization failed, downgrading link\n");
> >> +
> >> +		ret = dw_dp_link_downgrade(dp);
> >> +		if (ret < 0)
> >> +			goto out;
> >> +		else
> >> +			goto retry;
> >> +	}
> >> +
> >> +	dev_dbg(dp->dev, "channel equalization succeeded\n");
> >> +
> >> +out:
> >> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
> >> +	return ret;
> >> +}
> >> +
> >> +static int dw_dp_link_train_fast(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	int ret;
> >> +	u8 status[DP_LINK_STATUS_SIZE];
> >> +	u8 pattern;
> >> +
> >> +	dw_dp_link_train_init(&link->train);
> >> +
> >> +	dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
> >> +		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
> >> +
> >> +	ret = dw_dp_link_configure(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
> >> +		return ret;
> >> +	}
> >> +
> >> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
> >> +	if (ret)
> >> +		goto out;
> >> +
> >> +	usleep_range(500, 1000);
> >> +
> >> +	if (link->caps.tps4_supported)
> >> +		pattern = DP_TRAINING_PATTERN_4;
> >> +	else if (link->caps.tps3_supported)
> >> +		pattern = DP_TRAINING_PATTERN_3;
> >> +	else
> >> +		pattern = DP_TRAINING_PATTERN_2;
> >> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
> >> +	if (ret)
> >> +		goto out;
> >> +
> >> +	usleep_range(500, 1000);
> >> +
> >> +	ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "failed to read link status: %d\n", ret);
> >> +		goto out;
> >> +	}
> >> +
> >> +	if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
> >> +		dev_err(dp->dev, "clock recovery failed\n");
> >> +		ret = -EIO;
> >> +		goto out;
> >> +	}
> >> +
> >> +	if (!drm_dp_channel_eq_ok(status, link->lanes)) {
> >> +		dev_err(dp->dev, "channel equalization failed\n");
> >> +		ret = -EIO;
> >> +		goto out;
> >> +	}
> >> +
> >> +out:
> >> +	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
> >> +	return ret;
> >> +}
> >> +
> >> +static int dw_dp_link_train(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	int ret;
> >> +
> >> +	if (link->caps.fast_training) {
> >> +		if (dw_dp_link_train_valid(&link->train)) {
> >> +			ret = dw_dp_link_train_fast(dp);
> >> +			if (ret < 0)
> >> +				dev_err(dp->dev, "fast link training failed: %d\n", ret);
> >> +			else
> >> +				return 0;
> >> +		}
> >> +	}
> >> +
> >> +	ret = dw_dp_link_train_full(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "full link training failed: %d\n", ret);
> >> +		return ret;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int dw_dp_send_sdp(struct dw_dp *dp, struct dw_dp_sdp *sdp)
> >> +{
> >> +	const u8 *payload = sdp->db;
> >> +	u32 reg;
> >> +	int i, nr;
> >> +
> >> +	nr = find_first_zero_bit(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
> >> +	if (nr < SDP_REG_BANK_SIZE)
> >> +		set_bit(nr, dp->sdp_reg_bank);
> >> +	else
> >> +		return -EBUSY;
> >> +
> >> +	reg = DW_DP_SDP_REGISTER_BANK + nr * 9 * 4;
> >> +
> >> +	/* SDP header */
> >> +	regmap_write(dp->regmap, reg, get_unaligned_le32(&sdp->header));
> >> +
> >> +	/* SDP data payload */
> >> +	for (i = 1; i < 9; i++, payload += 4)
> >> +		regmap_write(dp->regmap, reg + i * 4,
> >> +			     FIELD_PREP(SDP_REGS, get_unaligned_le32(payload)));
> >> +
> >> +	if (sdp->flags & DW_DP_SDP_VERTICAL_INTERVAL)
> >> +		regmap_update_bits(dp->regmap, DW_DP_SDP_VERTICAL_CTRL,
> >> +				   EN_VERTICAL_SDP << nr,
> >> +				   EN_VERTICAL_SDP << nr);
> >> +
> >> +	if (sdp->flags & DW_DP_SDP_HORIZONTAL_INTERVAL)
> >> +		regmap_update_bits(dp->regmap, DW_DP_SDP_HORIZONTAL_CTRL,
> >> +				   EN_HORIZONTAL_SDP << nr,
> >> +				   EN_HORIZONTAL_SDP << nr);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void dw_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
> >> +			       struct dw_dp_sdp *sdp)
> >
> >Use drm_dp_vsc_sdp_pack() instead.
> 
> Ok? I will try?
> 
> >
> >> +{
> >> +	sdp->header.HB0 = 0;
> >> +	sdp->header.HB1 = DP_SDP_VSC;
> >> +	sdp->header.HB2 = vsc->revision;
> >> +	sdp->header.HB3 = vsc->length;
> >> +
> >> +	sdp->db[16] = (vsc->pixelformat & 0xf) << 4;
> >> +	sdp->db[16] |= vsc->colorimetry & 0xf;
> >> +
> >> +	switch (vsc->bpc) {
> >> +	case 8:
> >> +		sdp->db[17] = 0x1;
> >> +		break;
> >> +	case 10:
> >> +		sdp->db[17] = 0x2;
> >> +		break;
> >> +	case 12:
> >> +		sdp->db[17] = 0x3;
> >> +		break;
> >> +	case 16:
> >> +		sdp->db[17] = 0x4;
> >> +		break;
> >> +	case 6:
> >> +	default:
> >> +		break;
> >> +	}
> >> +
> >> +	if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
> >> +		sdp->db[17] |= 0x80;
> >> +
> >> +	sdp->db[18] = vsc->content_type & 0x7;
> >> +
> >> +	sdp->flags |= DW_DP_SDP_VERTICAL_INTERVAL;
> >> +}
> >> +
> >> +static int dw_dp_send_vsc_sdp(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_video *video = &dp->video;
> >> +	struct drm_dp_vsc_sdp vsc = {};
> >> +	struct dw_dp_sdp sdp = {};
> >> +
> >> +	vsc.revision = 0x5;
> >> +	vsc.length = 0x13;
> >> +
> >> +	switch (video->color_format) {
> >> +	case DRM_COLOR_FORMAT_YCBCR444:
> >> +		vsc.pixelformat = DP_PIXELFORMAT_YUV444;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_YCBCR420:
> >> +		vsc.pixelformat = DP_PIXELFORMAT_YUV420;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_YCBCR422:
> >> +		vsc.pixelformat = DP_PIXELFORMAT_YUV422;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_RGB444:
> >> +	default:
> >> +		vsc.pixelformat = DP_PIXELFORMAT_RGB;
> >> +		break;
> >> +	}
> >> +
> >> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
> >> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
> >> +	} else {
> >> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> >> +	}
> >> +
> >> +	vsc.bpc = video->bpc;
> >> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
> >> +
> >> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
> >> +
> >> +	return dw_dp_send_sdp(dp, &sdp);
> >> +}
> >> +
> >> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
> >> +{
> >> +	switch (pixel_mode) {
> >> +	case DW_DP_MP_SINGLE_PIXEL:
> >> +	case DW_DP_MP_DUAL_PIXEL:
> >> +	case DW_DP_MP_QUAD_PIXEL:
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >
> >Is it possible?
> 
> This IP is configurable for single/dual/quad pixel modes?
> It's  quad pixel mode on rk3588 and dual pixel mode on rk3576,
> so we add this check here.

My question was slightly different: is it possible to end up here in the
'default' branch?

> 
> 
> >
> >> +	}
> >> +
> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
> >> +			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	struct dw_dp_video *video = &dp->video;
> >> +
> >> +	if (!link->vsc_sdp_supported)
> >> +		return false;
> >> +
> >> +	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> +		return true;
> >> +
> >> +	return false;
> >> +}
> >> +
> >> +static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
> >> +			       u16 vstart, u16 hstart)
> >> +{
> >> +	u16 misc = 0;
> >> +
> >> +	if (dw_dp_video_need_vsc_sdp(dp))
> >> +		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
> >> +
> >> +	switch (color_format) {
> >> +	case DRM_COLOR_FORMAT_RGB444:
> >> +		misc |= DP_MSA_MISC_COLOR_RGB;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_YCBCR444:
> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_YCBCR422:
> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
> >> +		break;
> >> +	case DRM_COLOR_FORMAT_YCBCR420:
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	switch (bpc) {
> >> +	case 6:
> >> +		misc |= DP_MSA_MISC_6_BPC;
> >> +		break;
> >> +	case 8:
> >> +		misc |= DP_MSA_MISC_8_BPC;
> >> +		break;
> >> +	case 10:
> >> +		misc |= DP_MSA_MISC_10_BPC;
> >> +		break;
> >> +	case 12:
> >> +		misc |= DP_MSA_MISC_12_BPC;
> >> +		break;
> >> +	case 16:
> >> +		misc |= DP_MSA_MISC_16_BPC;
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
> >> +		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void dw_dp_video_disable(struct dw_dp *dp)
> >> +{
> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
> >> +}
> >> +
> >> +static int dw_dp_video_enable(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_video *video = &dp->video;
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	struct drm_display_mode *mode = &video->mode;
> >> +	u8 color_format = video->color_format;
> >> +	u8 bpc = video->bpc;
> >> +	u8 pixel_mode = video->pixel_mode;
> >> +	u8 bpp = video->bpp, init_threshold, vic;
> >> +	u32 hactive, hblank, h_sync_width, h_front_porch;
> >> +	u32 vactive, vblank, v_sync_width, v_front_porch;
> >> +	u32 vstart = mode->vtotal - mode->vsync_start;
> >> +	u32 hstart = mode->htotal - mode->hsync_start;
> >> +	u32 peak_stream_bandwidth, link_bandwidth;
> >> +	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
> >> +	u32 ts, hblank_interval;
> >> +	u32 value;
> >> +	int ret;
> >> +
> >> +	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
> >> +			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
> >> +
> >> +	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
> >> +	value = 0;
> >> +	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
> >> +		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
> >> +	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
> >> +		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
> >> +	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
> >> +
> >> +	/* Configure DW_DP_VIDEO_CONFIG1 register */
> >> +	hactive = mode->hdisplay;
> >> +	hblank = mode->htotal - mode->hdisplay;
> >> +	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
> >> +	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> >> +		value |= FIELD_PREP(I_P, 1);
> >> +	vic = drm_match_cea_mode(mode);
> >> +	if (vic == 5 || vic == 6 || vic == 7 ||
> >> +	    vic == 10 || vic == 11 || vic == 20 ||
> >> +	    vic == 21 || vic == 22 || vic == 39 ||
> >> +	    vic == 25 || vic == 26 || vic == 40 ||
> >> +	    vic == 44 || vic == 45 || vic == 46 ||
> >> +	    vic == 50 || vic == 51 || vic == 54 ||
> >> +	    vic == 55 || vic == 58 || vic  == 59)
> >> +		value |= R_V_BLANK_IN_OSC;
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
> >> +
> >> +	/* Configure DW_DP_VIDEO_CONFIG2 register */
> >> +	vblank = mode->vtotal - mode->vdisplay;
> >> +	vactive = mode->vdisplay;
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
> >> +		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
> >> +
> >> +	/* Configure DW_DP_VIDEO_CONFIG3 register */
> >> +	h_sync_width = mode->hsync_end - mode->hsync_start;
> >> +	h_front_porch = mode->hsync_start - mode->hdisplay;
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
> >> +		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
> >> +		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
> >> +
> >> +	/* Configure DW_DP_VIDEO_CONFIG4 register */
> >> +	v_sync_width = mode->vsync_end - mode->vsync_start;
> >> +	v_front_porch = mode->vsync_start - mode->vdisplay;
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
> >> +		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
> >> +		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
> >> +
> >> +	/* Configure DW_DP_VIDEO_CONFIG5 register */
> >> +	peak_stream_bandwidth = mode->clock * bpp / 8;
> >> +	link_bandwidth = (link->rate / 1000) * link->lanes;
> >> +	ts = peak_stream_bandwidth * 64 / link_bandwidth;
> >> +	average_bytes_per_tu = ts / 1000;
> >> +	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
> >> +	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
> >> +		if (average_bytes_per_tu < 6)
> >> +			init_threshold = 32;
> >> +		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
> >> +			init_threshold = 12;
> >> +		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> +			init_threshold = 3;
> >> +		else
> >> +			init_threshold = 16;
> >> +	} else {
> >> +		u32 t1 = 0, t2 = 0, t3 = 0;
> >> +
> >> +		switch (bpc) {
> >> +		case 6:
> >> +			t1 = (4 * 1000 / 9) * link->lanes;
> >> +			break;
> >> +		case 8:
> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> >> +				t1 = (1000 / 2) * link->lanes;
> >> +			} else {
> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> +					t1 = (1000 / 3) * link->lanes;
> >> +				else
> >> +					t1 = (3000 / 16) * link->lanes;
> >> +			}
> >> +			break;
> >> +		case 10:
> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
> >> +				t1 = (2000 / 5) * link->lanes;
> >> +			else
> >> +				t1 = (4000 / 15) * link->lanes;
> >> +			break;
> >> +		case 12:
> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> +					t1 = (1000 / 6) * link->lanes;
> >> +				else
> >> +					t1 = (1000 / 3) * link->lanes;
> >> +			} else {
> >> +				t1 = (2000 / 9) * link->lanes;
> >> +			}
> >> +			break;
> >> +		case 16:
> >> +			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
> >> +			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> +				t1 = (1000 / 6) * link->lanes;
> >> +			else
> >> +				t1 = (1000 / 4) * link->lanes;
> >> +			break;
> >> +		default:
> >> +			return -EINVAL;
> >> +		}
> >> +
> >> +		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> +			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
> >> +		else
> >> +			t2 = (link->rate / 4) * 1000 / mode->clock;
> >> +
> >> +		if (average_bytes_per_tu_frac)
> >> +			t3 = average_bytes_per_tu + 1;
> >> +		else
> >> +			t3 = average_bytes_per_tu;
> >> +		init_threshold = t1 * t2 * t3 / (1000 * 1000);
> >> +		if (init_threshold <= 16 || average_bytes_per_tu < 10)
> >> +			init_threshold = 40;
> >> +	}
> >> +
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
> >> +		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
> >> +		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
> >> +
> >> +	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
> >> +	hblank_interval = hblank * (link->rate / 4) / mode->clock;
> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
> >> +		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
> >> +		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
> >> +
> >> +	/* Video stream enable */
> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
> >> +
> >> +	if (dw_dp_video_need_vsc_sdp(dp))
> >> +		dw_dp_send_vsc_sdp(dp);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void dw_dp_hpd_init(struct dw_dp *dp)
> >> +{
> >> +	/* Enable all HPD interrupts */
> >> +	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
> >> +			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
> >> +			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
> >> +			   FIELD_PREP(HPD_PLUG_EN, 1) |
> >> +			   FIELD_PREP(HPD_IRQ_EN, 1));
> >> +
> >> +	/* Enable all top-level interrupts */
> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> >> +			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
> >> +}
> >> +
> >> +static void dw_dp_aux_init(struct dw_dp *dp)
> >> +{
> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> >> +			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
> >> +}
> >> +
> >> +static void dw_dp_init_hw(struct dw_dp *dp)
> >> +{
> >> +	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
> >> +			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
> >> +
> >> +	dw_dp_hpd_init(dp);
> >> +	dw_dp_aux_init(dp);
> >> +}
> >> +
> >> +static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
> >> +{
> >> +	size_t i, j;
> >> +
> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> >> +		size_t num = min_t(size_t, size - i * 4, 4);
> >> +		u32 value = 0;
> >> +
> >> +		for (j = 0; j < num; j++)
> >> +			value |= buffer[i * 4 + j] << (j * 8);
> >> +
> >> +		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
> >> +	}
> >> +
> >> +	return size;
> >> +}
> >> +
> >> +static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
> >> +{
> >> +	size_t i, j;
> >> +
> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> >> +		size_t num = min_t(size_t, size - i * 4, 4);
> >> +		u32 value;
> >> +
> >> +		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
> >> +
> >> +		for (j = 0; j < num; j++)
> >> +			buffer[i * 4 + j] = value >> (j * 8);
> >> +	}
> >> +
> >> +	return size;
> >> +}
> >> +
> >> +static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
> >> +				  struct drm_dp_aux_msg *msg)
> >> +{
> >> +	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
> >> +	unsigned long timeout = msecs_to_jiffies(10);
> >> +	u32 status, value;
> >> +	ssize_t ret = 0;
> >> +
> >> +	if (WARN_ON(msg->size > 16))
> >> +		return -E2BIG;
> >> +
> >> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
> >> +	case DP_AUX_NATIVE_WRITE:
> >> +	case DP_AUX_I2C_WRITE:
> >> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
> >> +		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
> >> +		if (ret < 0)
> >> +			return ret;
> >> +		break;
> >> +	case DP_AUX_NATIVE_READ:
> >> +	case DP_AUX_I2C_READ:
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	if (msg->size > 0)
> >> +		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
> >> +	else
> >> +		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
> >> +	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
> >> +	value |= FIELD_PREP(AUX_ADDR, msg->address);
> >> +	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
> >> +
> >> +	status = wait_for_completion_timeout(&dp->complete, timeout);
> >> +	if (!status) {
> >> +		dev_err(dp->dev, "timeout waiting for AUX reply\n");
> >> +		return -ETIMEDOUT;
> >> +	}
> >> +
> >> +	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
> >> +	if (value & AUX_TIMEOUT)
> >> +		return -ETIMEDOUT;
> >> +
> >> +	msg->reply = FIELD_GET(AUX_STATUS, value);
> >> +
> >> +	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
> >> +		if (msg->request & DP_AUX_I2C_READ) {
> >> +			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
> >> +
> >> +			if (count != msg->size)
> >> +				return -EBUSY;
> >> +
> >> +			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
> >> +			if (ret < 0)
> >> +				return ret;
> >> +		}
> >> +	}
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +/*
> >> + * Limits for the video timing output by DP:
> >> + * 1. the hfp should be 2 pixels aligned;
> >> + * 2. the minimum hsync should be 9 pixel;
> >> + * 3. the minimum hbp should be 16 pixel;
> >> + */
> >> +static bool dw_dp_bridge_mode_fixup(struct drm_bridge *bridge,
> >> +				    const struct drm_display_mode *mode,
> >> +				    struct drm_display_mode *adjusted_mode)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	int min_hbp = 16;
> >> +	int min_hsync = 9;
> >> +
> >> +	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
> >> +		adjusted_mode->hsync_start += 1;
> >> +		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
> >> +	}
> >> +	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
> >> +		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
> >> +		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
> >> +	}
> >> +	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
> >> +		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
> >> +		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
> >> +	}
> >> +
> >> +	return true;
> >> +}
> >> +
> >> +static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
> >> +						    const struct drm_display_info *info,
> >> +						    const struct drm_display_mode *mode)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u32 min_bpp;
> >> +
> >> +	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
> >> +	    link->vsc_sdp_supported &&
> >> +	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
> >> +		min_bpp = 12;
> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
> >> +		min_bpp = 16;
> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
> >> +		min_bpp = 18;
> >> +	else
> >> +		min_bpp = 24;
> >> +
> >> +	if (!link->vsc_sdp_supported &&
> >> +	    drm_mode_is_420_only(info, mode))
> >> +		return MODE_NO_420;
> >> +
> >> +	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
> >> +		return MODE_CLOCK_HIGH;
> >> +
> >> +	return MODE_OK;
> >> +}
> >> +
> >> +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> >> +					   struct drm_bridge_state *old_bridge_state)
> >> +{
> >> +	struct drm_atomic_state *state = old_bridge_state->base.state;
> >> +	struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	struct dw_dp_video *video = &dp->video;
> >> +	struct drm_display_mode *m = &video->mode;
> >> +	struct drm_bridge_state *bridge_state;
> >> +	const struct dw_dp_output_format *fmt;
> >> +
> >> +	drm_mode_copy(m, &crtc_state->adjusted_mode);
> >> +
> >> +	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> >> +	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);
> >
> >Should it be a part of the atomic_check() instead?
> 
> Since we have modef_fixup in this driver, which is mutually exclusive with atomic_check.

You can convet .mode_fixup into .atomic_check. The latter can change the
crtc_state->adjusted_mode. It is better to reject the invalid
combinations from the .atomic_check rather than having to handled them
later.

> 
> 
> 
> >
> >> +
> >> +	video->video_mapping = fmt->video_mapping;
> >> +	video->color_format = fmt->color_format;
> >> +	video->bpc = fmt->bpc;
> >> +	video->bpp = fmt->bpp;
> >> +}
> >> +
> >> +static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	u8 link_status[DP_LINK_STATUS_SIZE];
> >> +
> >> +	if (!dw_dp_link_train_valid(&link->train))
> >> +		return false;
> >> +
> >> +	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
> >> +		return false;
> >> +
> >> +	/* Retrain if Channel EQ or CR not ok */
> >> +	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
> >> +}
> >> +
> >> +static void dw_dp_link_disable(struct dw_dp *dp)
> >> +{
> >> +	struct dw_dp_link *link = &dp->link;
> >> +
> >> +	if (dw_dp_hpd_detect(dp))
> >> +		dw_dp_link_power_down(dp);
> >> +
> >> +	dw_dp_phy_xmit_enable(dp, 0);
> >> +
> >> +	phy_power_off(dp->phy);
> >> +
> >> +	link->train.clock_recovered = false;
> >> +	link->train.channel_equalized = false;
> >> +}
> >> +
> >> +static int dw_dp_link_enable(struct dw_dp *dp)
> >> +{
> >> +	int ret;
> >> +
> >> +	ret = phy_power_on(dp->phy);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	ret = dw_dp_link_power_up(dp);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	ret = dw_dp_link_train(dp);
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
> >> +				       struct drm_bridge_state *old_state)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	struct drm_atomic_state *state = old_state->base.state;
> >> +	struct drm_connector *connector;
> >> +	struct drm_connector_state *conn_state;
> >> +	int ret;
> >> +
> >> +	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
> >> +	if (!connector) {
> >> +		dev_err(dp->dev, "failed to get connector\n");
> >> +		return;
> >> +	}
> >> +
> >> +	conn_state = drm_atomic_get_new_connector_state(state, connector);
> >> +	if (!conn_state) {
> >> +		dev_err(dp->dev, "failed to get connector state\n");
> >> +		return;
> >> +	}
> >> +
> >> +	set_bit(0, dp->sdp_reg_bank);
> >> +
> >> +	ret = dw_dp_link_enable(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "failed to enable link: %d\n", ret);
> >> +		return;
> >> +	}
> >> +
> >> +	ret = dw_dp_video_enable(dp);
> >> +	if (ret < 0) {
> >> +		dev_err(dp->dev, "failed to enable video: %d\n", ret);
> >> +		return;
> >> +	}
> >> +}
> >> +
> >> +static void dw_dp_reset(struct dw_dp *dp)
> >> +{
> >> +	int val;
> >> +
> >> +	disable_irq(dp->irq);
> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> >> +			   FIELD_PREP(CONTROLLER_RESET, 1));
> >> +	udelay(10);
> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> >> +			   FIELD_PREP(CONTROLLER_RESET, 0));
> >> +
> >> +	dw_dp_init_hw(dp);
> >> +	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
> >> +				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
> >> +	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> >> +	enable_irq(dp->irq);
> >> +}
> >> +
> >> +static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
> >> +					struct drm_bridge_state *old_bridge_state)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +
> >> +	dw_dp_video_disable(dp);
> >> +	dw_dp_link_disable(dp);
> >> +	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
> >> +	dw_dp_reset(dp);
> >> +}
> >> +
> >> +static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
> >> +{
> >> +	int ret;
> >> +
> >> +	ret = phy_power_on(dp->phy);
> >> +	if (ret < 0)
> >> +		return false;
> >> +	ret = dw_dp_link_parse(dp);
> >> +	phy_power_off(dp->phy);
> >> +
> >> +	return !ret;
> >> +}
> >> +
> >> +static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +
> >> +	if (!dw_dp_hpd_detect(dp))
> >> +		return connector_status_disconnected;
> >> +
> >> +	if (!dw_dp_hpd_detect_link(dp))
> >> +		return connector_status_disconnected;
> >> +
> >> +	return connector_status_connected;
> >> +}
> >> +
> >> +static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
> >> +						     struct drm_connector *connector)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	const struct drm_edid *edid;
> >> +	int ret;
> >> +
> >> +	ret = phy_power_on(dp->phy);
> >> +	if (ret)
> >> +		return NULL;
> >> +
> >> +	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
> >> +
> >> +	phy_power_off(dp->phy);
> >> +
> >> +	return edid;
> >> +}
> >> +
> >> +static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> >> +						    struct drm_bridge_state *bridge_state,
> >> +						    struct drm_crtc_state *crtc_state,
> >> +						    struct drm_connector_state *conn_state,
> >> +						    unsigned int *num_output_fmts)
> >> +{
> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> +	struct dw_dp_link *link = &dp->link;
> >> +	struct drm_display_info *di = &conn_state->connector->display_info;
> >> +	struct drm_display_mode mode = crtc_state->mode;
> >> +	const struct dw_dp_output_format *fmt;
> >> +	u32 i, j = 0;
> >> +	u32 *output_fmts;
> >> +
> >> +	*num_output_fmts = 0;
> >> +
> >> +	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
> >> +	if (!output_fmts)
> >> +		return NULL;
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
> >> +		fmt = &dw_dp_output_formats[i];
> >> +
> >> +		if (fmt->bpc > conn_state->max_bpc)
> >> +			continue;
> >> +
> >> +		if (!(fmt->color_format & di->color_formats))
> >> +			continue;
> >> +
> >> +		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
> >> +		    !link->vsc_sdp_supported)
> >> +			continue;
> >> +
> >> +		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
> >> +		    drm_mode_is_420_only(di, &mode))
> >> +			continue;
> >> +
> >> +		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
> >> +			continue;
> >> +
> >> +		output_fmts[j++] = fmt->bus_format;
> >> +	}
> >> +
> >> +	*num_output_fmts = j;
> >> +
> >> +	return output_fmts;
> >> +}
> >> +
> >> +static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
> >> +	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
> >> +	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> >> +	.atomic_reset = drm_atomic_helper_bridge_reset,
> >> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
> >> +	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
> >> +	.mode_fixup = dw_dp_bridge_mode_fixup,
> >> +	.mode_valid = dw_dp_bridge_mode_valid,
> >> +	.atomic_pre_enable = dw_dp_bridge_atomic_pre_enable,
> >> +	.atomic_enable = dw_dp_bridge_atomic_enable,
> >> +	.atomic_disable = dw_dp_bridge_atomic_disable,
> >> +	.detect = dw_dp_bridge_detect,
> >> +	.edid_read = dw_dp_bridge_edid_read,
> >> +};
> >> +
> >> +static int dw_dp_link_retrain(struct dw_dp *dp)
> >> +{
> >> +	struct drm_device *dev = dp->bridge.dev;
> >> +	struct drm_modeset_acquire_ctx ctx;
> >> +	int ret;
> >> +
> >> +	if (!dw_dp_needs_link_retrain(dp))
> >> +		return 0;
> >> +
> >> +	dev_dbg(dp->dev, "Retraining link\n");
> >> +
> >> +	drm_modeset_acquire_init(&ctx, 0);
> >> +	for (;;) {
> >> +		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
> >> +		if (ret != -EDEADLK)
> >> +			break;
> >
> >I think it's an error to continue in such a case. There should be a
> >return after the loop if ret is not 0.
> 
> Thank you for catching this? I will add a check fater the loop.
> 
> 
> >
> >> +
> >> +		drm_modeset_backoff(&ctx);
> >> +	}
> >> +
> >> +	ret = dw_dp_link_train(dp);
> >> +	drm_modeset_drop_locks(&ctx);
> >> +	drm_modeset_acquire_fini(&ctx);
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +static void dw_dp_hpd_work(struct work_struct *work)
> >> +{
> >> +	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
> >> +	bool long_hpd;
> >> +	int ret;
> >> +
> >> +	mutex_lock(&dp->irq_lock);
> >> +	long_hpd = dp->hotplug.long_hpd;
> >> +	mutex_unlock(&dp->irq_lock);
> >> +
> >> +	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
> >> +
> >> +	if (!long_hpd) {
> >> +		if (dw_dp_needs_link_retrain(dp)) {
> >> +			ret = dw_dp_link_retrain(dp);
> >> +			if (ret)
> >> +				dev_warn(dp->dev, "Retrain link failed\n");
> >> +		}
> >> +	} else {
> >> +		drm_helper_hpd_irq_event(dp->bridge.dev);
> >> +	}
> >> +}
> >> +
> >> +static void dw_dp_handle_hpd_event(struct dw_dp *dp)
> >> +{
> >> +	u32 value;
> >> +
> >> +	mutex_lock(&dp->irq_lock);
> >> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >> +
> >> +	if (value & HPD_IRQ) {
> >> +		dev_dbg(dp->dev, "IRQ from the HPD\n");
> >> +		dp->hotplug.long_hpd = false;
> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
> >> +	}
> >> +
> >> +	if (value & HPD_HOT_PLUG) {
> >> +		dev_dbg(dp->dev, "Hot plug detected\n");
> >> +		dp->hotplug.long_hpd = true;
> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> >> +	}
> >> +
> >> +	if (value & HPD_HOT_UNPLUG) {
> >> +		dev_dbg(dp->dev, "Unplug detected\n");
> >> +		dp->hotplug.long_hpd = true;
> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
> >> +	}
> >> +	mutex_unlock(&dp->irq_lock);
> >> +
> >> +	schedule_work(&dp->hpd_work);
> >> +}
> >> +
> >> +static irqreturn_t dw_dp_irq(int irq, void *data)
> >> +{
> >> +	struct dw_dp *dp = data;
> >> +	u32 value;
> >> +
> >> +	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
> >> +	if (!value)
> >> +		return IRQ_NONE;
> >> +
> >> +	if (value & HPD_EVENT)
> >> +		dw_dp_handle_hpd_event(dp);
> >> +
> >> +	if (value & AUX_REPLY_EVENT) {
> >> +		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
> >> +		complete(&dp->complete);
> >> +	}
> >> +
> >> +	return IRQ_HANDLED;
> >> +}
> >> +
> >> +static const struct regmap_range dw_dp_readable_ranges[] = {
> >> +	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
> >> +	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
> >> +	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
> >> +	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
> >> +	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
> >> +	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
> >> +	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
> >> +	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
> >> +	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
> >> +};
> >> +
> >> +static const struct regmap_access_table dw_dp_readable_table = {
> >> +	.yes_ranges     = dw_dp_readable_ranges,
> >> +	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
> >> +};
> >> +
> >> +static const struct regmap_config dw_dp_regmap_config = {
> >> +	.reg_bits = 32,
> >> +	.reg_stride = 4,
> >> +	.val_bits = 32,
> >> +	.fast_io = true,
> >> +	.max_register = DW_DP_MAX_REGISTER,
> >> +	.rd_table = &dw_dp_readable_table,
> >> +};
> >> +
> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> >> +			 const struct dw_dp_plat_data *plat_data)
> >> +{
> >> +	struct platform_device *pdev = to_platform_device(dev);
> >> +	struct dw_dp *dp;
> >> +	struct drm_bridge *bridge;
> >> +	void __iomem *res;
> >> +	int ret;
> >> +
> >> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
> >> +	if (!dp)
> >> +		return ERR_PTR(-ENOMEM);
> >> +
> >> +	dp->dev = dev;
> >> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
> >> +
> >> +	dp->plat_data = plat_data;
> >> +	bridge = &dp->bridge;
> >> +	mutex_init(&dp->irq_lock);
> >> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
> >> +	init_completion(&dp->complete);
> >> +
> >> +	res = devm_platform_ioremap_resource(pdev, 0);
> >> +	if (IS_ERR(res))
> >> +		return ERR_CAST(res);
> >> +
> >> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
> >> +	if (IS_ERR(dp->regmap)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
> >> +		return ERR_CAST(dp->regmap);
> >> +	}
> >> +
> >> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
> >> +	if (IS_ERR(dp->phy)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
> >> +		return ERR_CAST(dp->phy);
> >> +	}
> >> +
> >> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
> >> +	if (IS_ERR(dp->apb_clk)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
> >> +		return ERR_CAST(dp->apb_clk);
> >> +	}
> >> +
> >> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
> >> +	if (IS_ERR(dp->aux_clk)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
> >> +		return ERR_CAST(dp->aux_clk);
> >> +	}
> >> +
> >> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
> >> +	if (IS_ERR(dp->i2s_clk)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
> >> +		return ERR_CAST(dp->i2s_clk);
> >> +	}
> >> +
> >> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
> >> +	if (IS_ERR(dp->spdif_clk)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
> >> +		return ERR_CAST(dp->spdif_clk);
> >> +	}
> >> +
> >> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
> >> +	if (IS_ERR(dp->hdcp_clk)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
> >> +		return ERR_CAST(dp->hdcp_clk);
> >> +	}
> >> +
> >> +	dp->rstc = devm_reset_control_get(dev, NULL);
> >> +	if (IS_ERR(dp->rstc)) {
> >> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
> >> +		return ERR_CAST(dp->rstc);
> >> +	}
> >> +
> >> +	dp->irq = platform_get_irq(pdev, 0);
> >> +	if (dp->irq < 0)
> >> +		return ERR_PTR(ret);
> >> +
> >> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
> >> +					IRQF_ONESHOT, dev_name(dev), dp);
> >
> >Are you ready to handle the IRQ here, before the bridge is filled?
> 
> I will move to  devm_request_threaded_irq after dw_dp_init_hw.
> 
> 
> >
> >> +	if (ret) {
> >> +		dev_err_probe(dev, ret, "failed to request irq\n");
> >> +		return ERR_PTR(ret);
> >> +	}
> >> +
> >> +	bridge->of_node = dev->of_node;
> >> +	bridge->funcs = &dw_dp_bridge_funcs;
> >> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> >> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
> >> +	bridge->ycbcr_420_allowed = true;
> >> +	bridge->vendor = "Synopsys";
> >> +	bridge->product = "DW DP TX";
> >
> >These two are unused
> >
> >> +
> >> +	platform_set_drvdata(pdev, dp);
> >
> >Unused
> 
> I will remove them.
> 
> Thanks again.
> 
> 
> >
> >> +
> >> +	dp->aux.dev = dev;
> >> +	dp->aux.drm_dev = encoder->dev;
> >> +	dp->aux.name = dev_name(dev);
> >> +	dp->aux.transfer = dw_dp_aux_transfer;
> >> +	ret = drm_dp_aux_register(&dp->aux);
> >> +	if (ret) {
> >> +		dev_err_probe(dev, ret, "Aux register failed\n");
> >> +		return ERR_PTR(ret);
> >> +	}
> >> +
> >> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >> +	if (ret)
> >> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
> >> +
> >> +	dw_dp_init_hw(dp);
> >> +
> >> +	return dp;
> >> +}
> >> +MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
> >> +MODULE_DESCRIPTION("DW DP Core Library");
> >> +MODULE_LICENSE("GPL");
> >> diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
> >> new file mode 100644
> >> index 000000000000..07845f609eca
> >> --- /dev/null
> >> +++ b/include/drm/bridge/dw_dp.h
> >> @@ -0,0 +1,19 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> >> +/*
> >> + * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
> >> + */
> >> +
> >> +#ifndef __DW_DP__
> >> +#define __DW_DP__
> >> +
> >> +struct device;
> >> +struct drm_encoder;
> >> +struct dw_dp;
> >> +
> >> +struct dw_dp_plat_data {
> >> +	u32 max_link_rate;
> >> +};
> >> +
> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> >> +			 const struct dw_dp_plat_data *plat_data);
> >> +#endif /* __DW_DP__ */
> >> -- 
> >> 2.34.1
> >> 
> >
> >-- 
> >With best wishes
> >Dmitry

-- 
With best wishes
Dmitry


From maxime.chevallier at bootlin.com  Sun Mar  2 08:21:36 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sun,  2 Mar 2025 17:21:36 +0100
Subject: [PATCH net] net: ethtool: Set the req_info->dev on DUMP requests for each dev
Message-ID: <20250302162137.698092-1-maxime.chevallier@bootlin.com>

There are a few netlink commands that rely on the req_info->dev field
being populated by ethnl in their ->prepare_data() and ->fill_reply().

For a regular GET request, this will be set by ethnl_default_parse(),
which calls ethnl_parse_header_dev_get().

In the case of a DUMP request, the ->prepare_data() and ->fill_reply()
callbacks will be called with the req_info->dev being NULL, which can
cause discrepancies in the behaviour between GET and DUMP results.

The main impact is that ethnl_req_get_phydev() will not find any
phy_device, impacting :
 - plca
 - pse-pd
 - stats

Some other commands rely on req_info->dev, namely :
 - coalesce in ->fill_reply to look for an irq_moder

Although cable_test and tunnels also rely on req_info->dev being set,
that's not a problem for these commands as :
 - cable_test doesn't support DUMP
 - tunnels rolls its own ->dumpit (and sets dev in the req_info).
 - phy also has its own ->dumpit

All other commands use reply_data->dev (probably the correct way of
doing things) and aren't facing this issue.

Simply set the dev in the req_info context when iterating to dump each
dev.

Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some commands")
Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---

Fixes tag targets the phy-index commit, as it introduced a change in
behaviour for PLCA. From what I can tell, coalesce never correctly
detected irq_moder in DUMP requests.

We could also consider fixing all individual commands that use
req_info->dev, however I'm not actually sure it's incorrect to do so,
feel free to correct me though.

Maxime

 net/ethtool/netlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index b4c45207fa32..de967961d8fe 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -582,6 +582,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 		dev_hold(dev);
 		rcu_read_unlock();
 
+		ctx->req_info->dev = dev;
 		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
 
 		rcu_read_lock();
-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:44 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:44 -0300
Subject: [PATCH v2 05/20] ASoC: mediatek: mt6359-accdet: Handle
 hp-eint-high property
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-5-5bd633ee0d47@collabora.com>

Now that the dt-binding was introduced, the property that governs the
eint polarity is a boolean called mediatek,hp-eint-high, while the
current code handles a u32 property called mediatek,eint-level-pol.
Update the driver handling accordingly.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 +----
 sound/soc/codecs/mt6359-accdet.h | 2 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 9bbd4497e8d481ee125693be2fc576b439574b39..ca3be59d2d0ecaadccd9ba399649ba93f20490c4 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -578,10 +578,7 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!ret)
 		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
 
-	ret = of_property_read_u32(node, "mediatek,eint-level-pol",
-				   &priv->data->eint_pol);
-	if (ret)
-		priv->data->eint_pol = 8;
+	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index c234f2f4276a12853a6fe0b13c4198dfc551b6b4..a54a328bdf3797ce642da446c0cc6792f72ec939 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -86,7 +86,7 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	unsigned int plugout_deb;
-	unsigned int eint_pol;
+	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	struct three_key_threshold three_key;
 	struct four_key_threshold four_key;

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:45 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:45 -0300
Subject: [PATCH v2 06/20] ASoC: mediatek: mt6359-accdet: Implement HP_EINT
 polarity configuration
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-6-5bd633ee0d47@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

The driver currently reads the HP_EINT polarity from the Devicetree but
never actually configures the hardware accordingly.

Implement the polarity configuration in hardware.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ca3be59d2d0ecaadccd9ba399649ba93f20490c4..1d4481109f6e4f473610e0797c9d3c636bdf12cf 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -730,6 +730,17 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 		}
 	}
+
+	if (priv->data->hp_eint_high) {
+		/* EINT polarity inverse */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT,
+				   BIT(ACCDET_EINT_IN_INVERSE_SFT));
+	} else {
+		/* EINT polarity normal */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT, 0);
+	}
 }
 
 static void config_eint_init_by_mode(struct mt6359_accdet *priv)

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:46 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:46 -0300
Subject: [PATCH v2 07/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT/GPIO IRQ handling
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-7-5bd633ee0d47@collabora.com>

The ACCDET supports two modes for IRQ generation: PMIC EINT or AP GPIO,
which in principle could be configured through a DT property. However
this DT property has no user nor is documented in a binding, and the
driver only implements the PMIC EINT case, so drop the unused code
intended to handle both cases.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 1d4481109f6e4f473610e0797c9d3c636bdf12cf..ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,9 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT_IRQ		BIT(0)
-#define ACCDET_AP_GPIO_EINT		BIT(1)
-
 #define ACCDET_PMIC_EINT0		BIT(2)
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
@@ -448,8 +445,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		mt6359_accdet_recover_jd_setting(priv);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ)
-		recover_eint_setting(priv);
+	recover_eint_setting(priv);
 	mutex_unlock(&priv->res_lock);
 }
 
@@ -580,14 +576,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT_IRQ;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_AP_GPIO_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
 				   &priv->data->eint_detect_mode);
 	if (ret) {
@@ -902,10 +890,8 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 				   0x3 << RG_ANALOGFDEN_SFT);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ) {
-		config_eint_init_by_mode(priv);
-		config_digital_init_by_mode(priv);
-	}
+	config_eint_init_by_mode(priv);
+	config_digital_init_by_mode(priv);
 }
 
 int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:47 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:47 -0300
Subject: [PATCH v2 08/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT trigger setting
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-8-5bd633ee0d47@collabora.com>

None of the EINT trigger options are implemented and the DT property is
not described in the binding. Remove the unused code.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0..a21c6544174517e3eebc8cf25d1ea3029ba014f6 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -35,8 +35,6 @@
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
 
-#define ACCDET_PMIC_GPIO_TRIG_EINT	BIT(5)
-#define ACCDET_PMIC_INVERTER_TRIG_EINT	BIT(6)
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_THREE_KEY		BIT(8)
@@ -593,15 +591,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-trig-mode",
-				   &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
 				   &priv->data->eint_use_ext_res);
 	if (ret) {

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:48 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:48 -0300
Subject: [PATCH v2 09/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 button detection
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-9-5bd633ee0d47@collabora.com>

The button detection functionality depends on a calibration voltage
value which is currently not updated anywhere in the driver code, and
hence it doesn't actually do anything. Remove this unused code.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 92 ++--------------------------------------
 sound/soc/codecs/mt6359-accdet.h | 17 --------
 2 files changed, 3 insertions(+), 106 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a21c6544174517e3eebc8cf25d1ea3029ba014f6..6b0178976d91e37c32540991693ebfd8e29c11f5 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -37,9 +37,6 @@
 
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
-#define ACCDET_THREE_KEY		BIT(8)
-#define ACCDET_FOUR_KEY			BIT(9)
-#define ACCDET_TRI_KEY_CDD		BIT(10)
 #define ACCDET_RSV_KEY			BIT(11)
 
 #define ACCDET_ANALOG_FASTDISCHARGE	BIT(12)
@@ -255,7 +252,6 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 			    priv->data->pwm_deb->debounce3);
 
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_jack_report(priv);
 }
@@ -318,45 +314,10 @@ static void mt6359_accdet_jack_report(struct mt6359_accdet *priv)
 	if (!priv->jack)
 		return;
 
-	report = priv->jack_type | priv->btn_type;
+	report = priv->jack_type;
 	snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK);
 }
 
-static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v)
-{
-	if (priv->caps & ACCDET_FOUR_KEY) {
-		if (v < priv->data->four_key.down &&
-		    v >= priv->data->four_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->four_key.up &&
-		    v >= priv->data->four_key.voice)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->four_key.voice &&
-		    v >= priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_3;
-		if (v < priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	} else {
-		if (v < priv->data->three_key.down &&
-		    v >= priv->data->three_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->three_key.up &&
-		    v >= priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	}
-	return 0;
-}
-
-static void is_key_pressed(struct mt6359_accdet *priv, bool pressed)
-{
-	priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK;
-
-	if (pressed)
-		check_button(priv, priv->cali_voltage);
-}
-
 static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
@@ -368,15 +329,11 @@ static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 
 	switch (priv->accdet_status) {
 	case 0:
-		if (priv->jack_type == SND_JACK_HEADSET)
-			is_key_pressed(priv, true);
-		else
+		if (priv->jack_type != SND_JACK_HEADSET)
 			priv->jack_type = SND_JACK_HEADPHONE;
 		break;
 	case 1:
-		if (priv->jack_type == SND_JACK_HEADSET) {
-			is_key_pressed(priv, false);
-		} else {
+		if (priv->jack_type != SND_JACK_HEADSET) {
 			priv->jack_type = SND_JACK_HEADSET;
 			accdet_set_debounce(priv, eint_state011, 0x1);
 		}
@@ -603,48 +560,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->eint_comp_vth = 0x0;
 
-	ret = of_property_read_u32(node, "mediatek,key-mode", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_THREE_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,three-key-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	} else if (tmp == 1) {
-		int four_key[5];
-
-		priv->caps |= ACCDET_FOUR_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,four-key-thr",
-						 four_key,
-						 ARRAY_SIZE(four_key));
-		if (!ret) {
-			memcpy(&priv->data->four_key, four_key + 1,
-			       sizeof(struct four_key_threshold));
-		} else {
-			dev_warn(priv->dev,
-				 "accdet no 4-key-thrsh dts, use efuse\n");
-		}
-	} else if (tmp == 2) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_TRI_KEY_CDD;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,tri-key-cdd-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	}
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -1015,7 +930,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 
 	priv->jd_sts = M_PLUG_OUT;
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_init(priv);
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index a54a328bdf3797ce642da446c0cc6792f72ec939..09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,19 +50,6 @@ enum {
 	eint_inverter_state000,
 };
 
-struct three_key_threshold {
-	unsigned int mid;
-	unsigned int up;
-	unsigned int down;
-};
-
-struct four_key_threshold {
-	unsigned int mid;
-	unsigned int voice;
-	unsigned int up;
-	unsigned int down;
-};
-
 struct pwm_deb_settings {
 	unsigned int pwm_width;
 	unsigned int pwm_thresh;
@@ -88,8 +75,6 @@ struct dts_data {
 	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	struct three_key_threshold three_key;
-	struct four_key_threshold four_key;
 	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
@@ -112,10 +97,8 @@ struct mt6359_accdet {
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;
-	unsigned int btn_type;
 	unsigned int accdet_status;
 	unsigned int pre_accdet_status;
-	unsigned int cali_voltage;
 	unsigned int jd_sts;
 	struct work_struct accdet_work;
 	struct workqueue_struct *accdet_workqueue;

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:49 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:49 -0300
Subject: [PATCH v2 10/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 plugout-debounce
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-10-5bd633ee0d47@collabora.com>

The mediatek,plugout-debounce property is undocumented in the binding
and unhandled by the driver. Remove it.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 -----
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 6 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6b0178976d91e37c32540991693ebfd8e29c11f5..d78d7516342a5c2273b1c2962c0346646aa6390f 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -513,11 +513,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_vol = 8;
 
-	ret = of_property_read_u32(node, "mediatek,plugout-debounce",
-				   &priv->data->plugout_deb);
-	if (ret)
-		priv->data->plugout_deb = 1;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a..54a33a0f0e084f80df33386b3df9bba9525fa880 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -72,7 +72,6 @@ struct pwm_deb_settings {
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
-	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int moisture_detect_enable;

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:50 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:50 -0300
Subject: [PATCH v2 11/20] ASoC: mediatek: mt6359-accdet: Drop unused
 moisture variables
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-11-5bd633ee0d47@collabora.com>

The dts_data struct contains several variables for moisture
configuration that are simply never used. Drop them.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 54a33a0f0e084f80df33386b3df9bba9525fa880..38c36d59b9cc68bd90e16137a05a62b521b75ac1 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -74,14 +74,9 @@ struct dts_data {
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
-	unsigned int moisture_detect_mode;
-	unsigned int moisture_comp_vth;
-	unsigned int moisture_comp_vref2;
-	unsigned int moisture_use_ext_res;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:51 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:51 -0300
Subject: [PATCH v2 12/20] ASoC: mediatek: mt6359-accdet: Always use
 internal resistor
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-12-5bd633ee0d47@collabora.com>

The code currently reads a property mediatek,eint-use-ext-res with
values ranging between 0 and 4. Not only should this be a boolean
property, but there's no need for it to even be a DT property, seeing as
all current boards will use the internal resistor anyway. Since there's
no current dt-binding or Devicetree user of this property, remove its
handling and make the driver always configure the internal resistor.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 53 +++++++++++-----------------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 14 insertions(+), 40 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index d78d7516342a5c2273b1c2962c0346646aa6390f..e04cfb9a607aa5d38d46329eb1387545fda37ccc 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -82,14 +82,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 					   RG_EINT1CONFIGACCDET_MASK_SFT,
 					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
-		if (priv->data->eint_use_ext_res == 0x3 ||
-		    priv->data->eint_use_ext_res == 0x4) {
-			/*select 500k, use internal resistor */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0HIRENB_ADDR,
-					   RG_EINT0HIRENB_MASK_SFT,
-					   BIT(RG_EINT0HIRENB_SFT));
-		}
+		/*select 500k, use internal resistor */
+		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+				   RG_EINT0HIRENB_MASK_SFT,
+				   BIT(RG_EINT0HIRENB_SFT));
 	}
 	return 0;
 }
@@ -543,13 +539,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
-				   &priv->data->eint_use_ext_res);
-	if (ret) {
-		/* eint use internal resister */
-		priv->data->eint_use_ext_res = 0x0;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
 				   &priv->data->eint_comp_vth);
 	if (ret)
@@ -651,30 +640,16 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	if (priv->data->eint_detect_mode == 0x1 ||
 	    priv->data->eint_detect_mode == 0x2 ||
 	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->data->eint_use_ext_res == 0x1) {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   0);
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   0);
-			}
-		} else {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT0CONFIGACCDET_SFT));
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT1CONFIGACCDET_SFT));
-			}
+		if (priv->caps & ACCDET_PMIC_EINT0) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT0CONFIGACCDET_ADDR,
+					   RG_EINT0CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT0CONFIGACCDET_SFT));
+		} else if (priv->caps & ACCDET_PMIC_EINT1) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT1CONFIGACCDET_ADDR,
+					   RG_EINT1CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 38c36d59b9cc68bd90e16137a05a62b521b75ac1..99de5037a2294b62cb8535fc45dbf4c6fafb5c7f 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -75,7 +75,6 @@ struct dts_data {
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
-	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:52 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:52 -0300
Subject: [PATCH v2 13/20] ASoC: mediatek: mt6359-accdet: Make PWM debounce
 settings internal
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-13-5bd633ee0d47@collabora.com>

Instead of reading a bunch of PWM debounce settings from the Devicetree,
set reasonable values inside the driver that are known to work across
multiple boards. There are no current users of these DT properties, so
no backward compatibility needs to be maintained. The properties can be
properly introduced in the binding in the future if different boards
really need to override them.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 70 ++++++++++++++++++++++------------------
 sound/soc/codecs/mt6359-accdet.h | 20 ------------
 2 files changed, 38 insertions(+), 52 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index e04cfb9a607aa5d38d46329eb1387545fda37ccc..6728f1018c992fc9d4e4133dbaf091d256567683 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -43,6 +43,25 @@
 #define ACCDET_DIGITAL_FASTDISCHARGE	BIT(13)
 #define ACCDET_AD_FASTDISCHRAGE		BIT(14)
 
+/* Debounce time = (DEBOUNCE/32768) sec */
+#define ACCDET_DEBOUNCE0_625MS 0x800
+#define ACCDET_DEBOUNCE1_625MS 0x800
+#define ACCDET_DEBOUNCE3_976US 0x20
+#define ACCDET_DEBOUNCE_AUXADC_2MS 0x44
+/* PWM frequency = 32768/(PWM_WIDTH + 1) Hz */
+#define ACCDET_PWM_WIDTH_25_580HZ 0x500
+/* Duty cycle = (PWM_THRESH + 1) / (PWM_WIDTH + 1) */
+#define ACCDET_PWM_THRESH_100PERCENT ACCDET_PWM_WIDTH_25_580HZ
+#define ACCDET_RISE_DELAY 0x1f0
+#define ACCDET_FALL_DELAY 1
+#define ACCDET_EINT_DEBOUNCE0_1MS 5
+#define ACCDET_EINT_DEBOUNCE1_900US 3
+#define ACCDET_EINT_DEBOUNCE2_900US 3
+#define ACCDET_EINT_DEBOUNCE3_1MS 5
+#define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
+#define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
+#define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
 
@@ -130,7 +149,7 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 	} else if (priv->jd_sts == M_PLUG_OUT) {
 		/* set debounce to 1ms */
 		accdet_set_debounce(priv, eint_state000,
-				    priv->data->pwm_deb->eint_debounce0);
+				    ACCDET_EINT_DEBOUNCE0_1MS);
 	} else {
 		dev_dbg(priv->dev, "should not be here %s()\n", __func__);
 	}
@@ -241,11 +260,11 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 
 	/* recover accdet debounce0,3 */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 
 	priv->jack_type = 0;
 	priv->accdet_status = 0x3;
@@ -390,7 +409,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		priv->jack_plugged = false;
 
 		accdet_set_debounce(priv, accdet_state011,
-				    priv->data->pwm_deb->debounce3);
+				    ACCDET_DEBOUNCE3_976US);
 		regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,
 				   ACCDET_SW_EN_MASK_SFT, 0);
 		mt6359_accdet_recover_jd_setting(priv);
@@ -497,7 +516,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	int pwm_deb[15] = {0};
 	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
@@ -514,12 +532,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_mode = 2;
 
-	ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting",
-					 pwm_deb, ARRAY_SIZE(pwm_deb));
-	/* debounce8(auxadc debounce) is default, needn't get from dts */
-	if (!ret)
-		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
@@ -554,8 +566,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 {
 	/* enable eint cmpmem pwm */
 	regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR,
-		     (priv->data->pwm_deb->eint_pwm_width << 4 |
-		     priv->data->pwm_deb->eint_pwm_thresh));
+		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
+		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
 	if (priv->caps & ACCDET_PMIC_EINT0) {
 		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
@@ -675,22 +687,22 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 	mdelay(1);
 	/* init the debounce time (debounce/32768)sec */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 	accdet_set_debounce(priv, accdet_auxadc,
-			    priv->data->pwm_deb->debounce4);
+			    ACCDET_DEBOUNCE_AUXADC_2MS);
 
 	accdet_set_debounce(priv, eint_state000,
-			    priv->data->pwm_deb->eint_debounce0);
+			    ACCDET_EINT_DEBOUNCE0_1MS);
 	accdet_set_debounce(priv, eint_state001,
-			    priv->data->pwm_deb->eint_debounce1);
+			    ACCDET_EINT_DEBOUNCE1_900US);
 	accdet_set_debounce(priv, eint_state011,
-			    priv->data->pwm_deb->eint_debounce3);
+			    ACCDET_EINT_DEBOUNCE3_1MS);
 	accdet_set_debounce(priv, eint_inverter_state000,
-			    priv->data->pwm_deb->eint_inverter_debounce);
+			    ACCDET_EINT_INVERTER_DEBOUNCE_256MS);
 
 	regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,
 			   RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT));
@@ -705,12 +717,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 
 	/* init pwm frequency, duty & rise/falling delay */
 	regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_width));
+		     REGISTER_VAL(ACCDET_PWM_WIDTH_25_580HZ));
 	regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_thresh));
+		     REGISTER_VAL(ACCDET_PWM_THRESH_100PERCENT));
 	regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR,
-		     (priv->data->pwm_deb->fall_delay << 15 |
-		      priv->data->pwm_deb->rise_delay));
+		     (ACCDET_FALL_DELAY << 15 |
+		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
 	if (priv->data->mic_vol <= 7) {
@@ -806,12 +818,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	if (!priv->data)
 		return -ENOMEM;
 
-	priv->data->pwm_deb = devm_kzalloc(&pdev->dev,
-					   sizeof(struct pwm_deb_settings),
-					   GFP_KERNEL);
-	if (!priv->data->pwm_deb)
-		return -ENOMEM;
-
 	priv->regmap = mt6397->regmap;
 	if (IS_ERR(priv->regmap)) {
 		ret = PTR_ERR(priv->regmap);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 99de5037a2294b62cb8535fc45dbf4c6fafb5c7f..287201eebe0330fa170093fd6192bf5694c30469 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,30 +50,10 @@ enum {
 	eint_inverter_state000,
 };
 
-struct pwm_deb_settings {
-	unsigned int pwm_width;
-	unsigned int pwm_thresh;
-	unsigned int fall_delay;
-	unsigned int rise_delay;
-	unsigned int debounce0;
-	unsigned int debounce1;
-	unsigned int debounce3;
-	unsigned int debounce4;
-	unsigned int eint_pwm_width;
-	unsigned int eint_pwm_thresh;
-	unsigned int eint_debounce0;
-	unsigned int eint_debounce1;
-	unsigned int eint_debounce2;
-	unsigned int eint_debounce3;
-	unsigned int eint_inverter_debounce;
-
-};
-
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:53 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:53 -0300
Subject: [PATCH v2 14/20] ASoC: mediatek: mt6359-accdet: Always use eint
 detect mode 4
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-14-5bd633ee0d47@collabora.com>

The driver currently reads a mediatek,eint-detect-mode property from DT,
which determines certain register configurations. Since there are no
users of the property, it doesn't directly describe the hardware, and
the default value (4) is known to work across multiple boards, remove
the handling for this property and always assume mode 4 is used. The
property can be properly introduced in the binding in the future if
different boards actually need different configurations.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 208 +++++++++++++--------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 70 insertions(+), 139 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6728f1018c992fc9d4e4133dbaf091d256567683..83e65b6d5845dea00a8a77d68df4b7df1f62a87c 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -81,31 +81,22 @@ static void recover_eint_setting(struct mt6359_accdet *priv);
 
 static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches off */
-		regmap_update_bits(priv->regmap,
-				   RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-		/*select 500k, use internal resistor */
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT,
-				   BIT(RG_EINT0HIRENB_SFT));
+	/* ESD switches off */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT0CONFIGACCDET_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT1CONFIGACCDET_SFT));
 	}
+	/*select 500k, use internal resistor */
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
 	return 0;
 }
 
@@ -123,18 +114,14 @@ static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
 	}
 
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
 	}
 	return 0;
 }
@@ -159,27 +146,19 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 
 static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches on */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   1 << 8, 1 << 8);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* disable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* disable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-		}
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT, 0);
+	/* ESD switches on */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* disable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* disable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
 	}
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
@@ -193,37 +172,30 @@ static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_M_SW_EN_ADDR,
 				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
 	}
-	if (priv->data->eint_detect_mode == 0x4) {
+	if (priv->caps & ACCDET_PMIC_EINT0) {
 		/* enable eint0cen */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable eint0cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable eint1cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-		}
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable eint1cen */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
 	}
 
-	if (priv->data->eint_detect_mode != 0x1) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 }
 
@@ -534,13 +506,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
-				   &priv->data->eint_detect_mode);
-	if (ret) {
-		/* eint detection mode equals to EINT HW Mode */
-		priv->data->eint_detect_mode = 0x4;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
 	if (ret)
 		tmp = 0;
@@ -592,31 +557,16 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->data->eint_detect_mode == 0x1) {
-		/* disable inverter detection */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		}
-	} else {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 
 	if (priv->data->hp_eint_high) {
@@ -649,28 +599,10 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR,
 			   RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT));
 
-	if (priv->data->eint_detect_mode == 0x1 ||
-	    priv->data->eint_detect_mode == 0x2 ||
-	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-	}
-
-	if (priv->data->eint_detect_mode != 0x1) {
-		/* current detect set 0.25uA */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << RG_ACCDETSPARE_SFT,
-				   0x3 << RG_ACCDETSPARE_SFT);
-	}
+	/* current detect set 0.25uA */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
+			   0x3 << RG_ACCDETSPARE_SFT,
+			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
 		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
 }
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 287201eebe0330fa170093fd6192bf5694c30469..ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -54,7 +54,6 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:39 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:39 -0300
Subject: [PATCH v2 00/20] Get mt6359-accdet ready for usage in Devicetree
Message-ID: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>

This series prepares the MT6359 ACCDET for actual usage in the
Devicetree. Patches 1 and 2 add the required DT bindings, patches 3 and
4 get the mt6359-accdet driver probing, patches 5-18 clean up code
related to DT property parsing, patch 19 adds the node in the
Devicetree and patch 20 enables the kconfig for the driver.

Together with the series "Allow retrieving accessory detection reference
on MT8188" [1], and one extra patch on top enabling it on the
genio-700-evk DT, this series was tested on the Genio 700 EVK to get
audio jack detection working on it.

[1] https://lore.kernel.org/all/20250214-mt8188-accdet-v1-0-6bbd5483855b at collabora.com

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
Changes in v2:
- Removed all DT-binding properties except for EINT polarity one
  (mediatek,eint-level-pol / mediatek,hp-eint-high)
  - Added patches 12-18 to make those settings internal to driver
- Renamed mediatek,eint-level-pol to mediatek,hp-eint-high and made it
  bool
- Added patch 20 to enable the MT6359 ACCDET Kconfig in the defconfig
- Removed unused btn_type variable as part of "Drop dead code for button
  detection" patch.
- Link to v1: https://lore.kernel.org/r/20250214-mt6359-accdet-dts-v1-0-677a151b9b4c at collabora.com

---
Andrew Perepech (2):
      mfd: mt6397-core: Add mfd_cell for mt6359-accdet
      ASoC: mediatek: mt6359-accdet: Implement HP_EINT polarity configuration

N?colas F. R. A. Prado (18):
      ASoC: dt-bindings: Add document for mt6359-accdet
      dt-bindings: mfd: mediatek: mt6397: Add accdet subnode
      ASoC: mediatek: mt6359-accdet: Add compatible property
      ASoC: mediatek: mt6359-accdet: Handle hp-eint-high property
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT/GPIO IRQ handling
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT trigger setting
      ASoC: mediatek: mt6359-accdet: Drop dead code for button detection
      ASoC: mediatek: mt6359-accdet: Drop dead code for plugout-debounce
      ASoC: mediatek: mt6359-accdet: Drop unused moisture variables
      ASoC: mediatek: mt6359-accdet: Always use internal resistor
      ASoC: mediatek: mt6359-accdet: Make PWM debounce settings internal
      ASoC: mediatek: mt6359-accdet: Always use eint detect mode 4
      ASoC: mediatek: mt6359-accdet: Always set micbias1 to 2.8V
      ASoC: mediatek: mt6359-accdet: Always configure hardware as mic-mode 2
      ASoC: mediatek: mt6359-accdet: Always set comp-vth to 1.6V
      ASoC: mediatek: mt6359-accdet: Always use EINT0 IRQ
      arm64: dts: mt6359: Add accessory detect node
      arm64: defconfig: Enable MT6359 ACCDET

 .../devicetree/bindings/mfd/mediatek,mt6397.yaml   |   7 +
 .../bindings/sound/mediatek,mt6359-accdet.yaml     |  42 ++
 arch/arm64/boot/dts/mediatek/mt6359.dtsi           |   4 +
 arch/arm64/configs/defconfig                       |   1 +
 drivers/mfd/mt6397-core.c                          |  12 +
 sound/soc/codecs/mt6359-accdet.c                   | 599 +++++----------------
 sound/soc/codecs/mt6359-accdet.h                   |  55 +-
 7 files changed, 196 insertions(+), 524 deletions(-)
---
base-commit: c0eb65494e59d9834af7cbad983629e9017b25a1
change-id: 20250214-mt6359-accdet-dts-00b189847f3c

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Sun Mar  2 08:30:40 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:40 -0300
Subject: [PATCH v2 01/20] ASoC: dt-bindings: Add document for mt6359-accdet
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>

Add dt-binding for the MT6359 ACCDET hardware block.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d08a79301409374714c76135b061e20e8e8acfaf
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MT6359 Accessory Detection
+
+maintainers:
+  - N?colas F. R. A. Prado <nfraprado at collabora.com>
+
+description: |
+  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
+  detecting audio jack insertion and removal, as well as identifying the type of
+  events connected to the jack.
+
+properties:
+  compatible:
+    const: mediatek,mt6359-accdet
+
+  mediatek,hp-eint-high:
+    type: boolean
+    description:
+      By default, the HP_EINT pin is assumed to be pulled high and connected to
+      a normally open 3.5mm jack. Plug insertion is detected when the pin is
+      brought low in that case. Add this property if the behavior should be
+      inverted, for example if a normally closed 3.5mm jack is used, or if the
+      line is pulled low on open.
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    accdet: accdet {
+        compatible = "mediatek,mt6359-accdet";
+        mediatek,hp-eint-high;
+    };

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:41 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:41 -0300
Subject: [PATCH v2 02/20] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-2-5bd633ee0d47@collabora.com>

Describe the accdet as a possible subnode of the MT6359 PMIC.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..1a8c5748a28da6ad8aa091f8c0a74bc1dc709644 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -224,6 +224,13 @@ properties:
     description:
       Pin controller
 
+  accdet:
+    type: object
+    $ref: /schemas/sound/mediatek,mt6359-accdet.yaml
+    unevaluatedProperties: false
+    description:
+      Accessory Detection
+
 required:
   - compatible
   - regulators

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:42 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:42 -0300
Subject: [PATCH v2 03/20] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-3-5bd633ee0d47@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
allow the mt6359-accdet driver to probe.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 drivers/mfd/mt6397-core.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 0e5d59ae064a696ae2111e2b558b316667c14773..5f8ed898890783c0ce4e34c7eae0d8f678e7d7bc 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -84,6 +84,12 @@ static const struct resource mt6359_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
 };
 
+static const struct resource mt6359_accdet_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET, "accdet_irq"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT0, "accdet_eint0"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT1, "accdet_eint1"),
+};
+
 static const struct resource mt6323_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
@@ -239,6 +245,12 @@ static const struct mfd_cell mt6359_devs[] = {
 		.resources = mt6359_keys_resources,
 		.of_compatible = "mediatek,mt6359-keys"
 	},
+	{
+		.name = "mt6359-accdet",
+		.of_compatible = "mediatek,mt6359-accdet",
+		.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
+		.resources = mt6359_accdet_resources,
+	},
 };
 
 static const struct mfd_cell mt6397_devs[] = {

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:43 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:43 -0300
Subject: [PATCH v2 04/20] ASoC: mediatek: mt6359-accdet: Add compatible
 property
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-4-5bd633ee0d47@collabora.com>

Add a compatible property and add it to the module device table for the
mt6359-accdet platform driver to allow automatic module loading and
probing when the compatible is present in DT.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ed34cc15b80e856356c07fd53af22207124e0d19..9bbd4497e8d481ee125693be2fc576b439574b39 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -1047,9 +1047,16 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	return ret;
 }
 
+const struct of_device_id accdet_of_match[] = {
+	{ .compatible = "mediatek,mt6359-accdet", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, accdet_of_match);
+
 static struct platform_driver mt6359_accdet_driver = {
 	.driver = {
 		.name = "pmic-codec-accdet",
+		.of_match_table = accdet_of_match,
 	},
 	.probe = mt6359_accdet_probe,
 };

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:54 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:54 -0300
Subject: [PATCH v2 15/20] ASoC: mediatek: mt6359-accdet: Always set
 micbias1 to 2.8V
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-15-5bd633ee0d47@collabora.com>

The driver currently reads a mediatek,mic-vol property from DT to
determine the micbias1 setting to configure in hardware. Since there are
no current users of the property and the default value (2.8V) is known
to work on multiple boards, remove the code handling this property and
instead always configure the micbias1 to 2.8V. The property can be
properly introduced in the binding in the future if it really turns out
that different boards need different configurations.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 23 +++--------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 83e65b6d5845dea00a8a77d68df4b7df1f62a87c..a31e084560c7643b14fb71871699e3167075d9d9 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-vol",
-				   &priv->data->mic_vol);
-	if (ret)
-		priv->data->mic_vol = 8;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
@@ -657,22 +652,10 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
-	if (priv->data->mic_vol <= 7) {
-		/* micbias1 <= 2.7V */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 8) {
-		/* micbias1 = 2.8v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
+	/* micbias1 = 2.8v */
+	regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
+		     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 9) {
-		/* micbias1 = 2.85v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (1 << RG_AUDMICBIAS1HVEN_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	}
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
 	if (priv->data->mic_mode == HEADSET_MODE_1) {
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92..46dcd4759230a5190434b9b7c785e8b9ed12fd3d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -51,7 +51,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:58 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:58 -0300
Subject: [PATCH v2 19/20] arm64: dts: mt6359: Add accessory detect node
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-19-5bd633ee0d47@collabora.com>

Add audio jack detection node. PMIC accessory detect driver will
create an input device that will send key events on jack
insertion/removal or accessory device key presses.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/boot/dts/mediatek/mt6359.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
index 7b10f9c59819a9ad02319f00938f35c931091f9f..e24e4aeb3b9cafa2af56c62bc4c549df27d0ec73 100644
--- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
@@ -15,6 +15,10 @@ pmic_adc: adc {
 			#io-channel-cells = <1>;
 		};
 
+		accdet: accdet {
+			compatible = "mediatek,mt6359-accdet";
+		};
+
 		mt6359codec: audio-codec {
 			compatible = "mediatek,mt6359-codec";
 		};

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:59 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:59 -0300
Subject: [PATCH v2 20/20] arm64: defconfig: Enable MT6359 ACCDET
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-20-5bd633ee0d47@collabora.com>

Enable support for the ACCDET block in the MT6359 PMIC, which provides
jack detection capabilities to MediaTek platforms.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index e675bedbc170ccb191f4991e348e36b5de0707a7..dec4708d5e946fc890751cab8de2cf3f302e9447 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1065,6 +1065,7 @@ CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_SOC_WSA881X=m
 CONFIG_SND_SOC_WSA883X=m
 CONFIG_SND_SOC_WSA884X=m
+CONFIG_SND_SOC_MT6359_ACCDET=m
 CONFIG_SND_SOC_NAU8822=m
 CONFIG_SND_SOC_LPASS_WSA_MACRO=m
 CONFIG_SND_SOC_LPASS_VA_MACRO=m

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:55 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:55 -0300
Subject: [PATCH v2 16/20] ASoC: mediatek: mt6359-accdet: Always configure
 hardware as mic-mode 2
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-16-5bd633ee0d47@collabora.com>

The driver currently reads a mediatek,mic-mode property from DT to
determine certain register configurations. Since there are no current
users of the property, the property doesn't directly reflect the
hardware  and the default value (2) is known to work on
multiple boards, remove the code handling this property and instead
always configure the hardware according to the known to work default.
This property can be properly introduced in the binding in the future
if it really turns out that different boards need different
configurations.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 43 ++++++----------------------------------
 sound/soc/codecs/mt6359-accdet.h |  5 -----
 2 files changed, 6 insertions(+), 42 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a31e084560c7643b14fb71871699e3167075d9d9..12697b02faff1be39317116cd7d8ffa359f2cd4e 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-mode",
-				   &priv->data->mic_mode);
-	if (ret)
-		priv->data->mic_mode = 2;
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
@@ -658,38 +653,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
-	if (priv->data->mic_mode == HEADSET_MODE_1) {
-		/* ACC mode*/
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE1);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   RG_ANALOGFDEN_MASK_SFT,
-				   BIT(RG_ANALOGFDEN_SFT));
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << 11, 0x3 << 11);
-	} else if (priv->data->mic_mode == HEADSET_MODE_2) {
-		/* DCC mode Low cost mode without internal bias */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE2);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	} else if (priv->data->mic_mode == HEADSET_MODE_6) {
-		/* DCC mode Low cost mode with internal bias,
-		 * bit8 = 1 to use internal bias
-		 */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE6);
-		regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-				   RG_AUDMICBIAS1DCSW1PEN_MASK_SFT,
-				   BIT(RG_AUDMICBIAS1DCSW1PEN_SFT));
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	}
+	/* DCC mode Low cost mode without internal bias */
+	regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
+		     reg | RG_ACCDET_MODE_ANA11_MODE2);
+	/* enable analog fast discharge */
+	regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
+			   0x3 << RG_ANALOGFDEN_SFT, 0x3 << RG_ANALOGFDEN_SFT);
 
 	config_eint_init_by_mode(priv);
 	config_digital_init_by_mode(priv);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 46dcd4759230a5190434b9b7c785e8b9ed12fd3d..579373807c414130b2a7384db4978e01cf1d046c 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -12,10 +12,6 @@
 
 #define ACCDET_DEVNAME "accdet"
 
-#define HEADSET_MODE_1		(1)
-#define HEADSET_MODE_2		(2)
-#define HEADSET_MODE_6		(6)
-
 #define MT6359_ACCDET_NUM_BUTTONS 4
 #define MT6359_ACCDET_JACK_MASK (SND_JACK_HEADPHONE | \
 				SND_JACK_HEADSET | \
@@ -51,7 +47,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:56 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:56 -0300
Subject: [PATCH v2 17/20] ASoC: mediatek: mt6359-accdet: Always set
 comp-vth to 1.6V
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-17-5bd633ee0d47@collabora.com>

The driver currently reads a mediatek,eint-comp-vth property from DT to
determine the voltage threshold of the EINT comparator. Since there are
no current users of the property and setting it to 1.6V is known to work
across multiple boards, remove the code handling this property and
instead always configure it to 1.6V. The property can be properly
introduced in the binding in the future if it really turns out that
different boards need different configurations.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 8 ++------
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 12697b02faff1be39317116cd7d8ffa359f2cd4e..3f6a97e8de8d174e59e512d53135fadc5765b5c1 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -61,6 +61,7 @@
 #define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
 #define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
 #define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+#define ACCDET_EINT_COMP_VTH_1600MV 2
 
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
@@ -506,11 +507,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
-				   &priv->data->eint_comp_vth);
-	if (ret)
-		priv->data->eint_comp_vth = 0x0;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -594,7 +590,7 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 			   0x3 << RG_ACCDETSPARE_SFT,
 			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
-		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
+		     val | ACCDET_EINT_COMP_VTH_1600MV << RG_EINTCOMPVTH_SFT);
 }
 
 static void mt6359_accdet_init(struct mt6359_accdet *priv)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 579373807c414130b2a7384db4978e01cf1d046c..288b8fbf7c5efaee6520a2c0a5845e156f3b805d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -48,7 +48,6 @@ enum {
 
 struct dts_data {
 	bool hp_eint_high;
-	unsigned int eint_comp_vth;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Sun Mar  2 08:30:57 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Sun, 02 Mar 2025 13:30:57 -0300
Subject: [PATCH v2 18/20] ASoC: mediatek: mt6359-accdet: Always use EINT0
 IRQ
In-Reply-To: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
Message-ID: <20250302-mt6359-accdet-dts-v2-18-5bd633ee0d47@collabora.com>

The ACCDET block can generate two distinct EINT interrupts: EINT0 and
EINT1, and which is enabled is currently determined by mediatek,eint-num
property in DT. However, only EINT0 is used on the boards that are
known to have working ACCDET. Since there are no current users of the
property, remove its handling and instead always enable EINT0. The
property can be properly introduced in the binding in the future if it
really turns out that other boards require EINT1.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 187 +++++++++------------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 43 insertions(+), 145 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 3f6a97e8de8d174e59e512d53135fadc5765b5c1..b1e63f3f7fa44687b1cac47c0e33f68a28e15a47 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,10 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT0		BIT(2)
-#define ACCDET_PMIC_EINT1		BIT(3)
-#define ACCDET_PMIC_BI_EINT		BIT(4)
-
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_RSV_KEY			BIT(11)
@@ -84,17 +80,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches off */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT0CONFIGACCDET_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT1CONFIGACCDET_SFT));
-	}
+	/* enable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT,
+			   BIT(RG_EINT0CONFIGACCDET_SFT));
 	/*select 500k, use internal resistor */
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
@@ -103,27 +92,13 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 
 static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
-	}
+	/* disable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-	}
+	/* set DA stable signal */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
 	return 0;
 }
 
@@ -149,55 +124,26 @@ static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-	}
+	/* disable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_M_SW_EN_ADDR,
-				   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_M_SW_EN_ADDR,
-				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
-	}
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable eint0cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable eint1cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-	}
-
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_M_SW_EN_ADDR,
+			   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
+	/* enable eint0cen */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+			   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+
+	/* enable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 }
 
 static void recover_eint_setting(struct mt6359_accdet *priv)
@@ -486,10 +432,8 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
 
 static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 {
-	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
 	if (!node)
@@ -497,16 +441,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT0;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_EINT1;
-	else if (tmp == 2)
-		priv->caps |= ACCDET_PMIC_BI_EINT;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -520,13 +454,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
 		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT0_STABLE_VAL);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT1_STABLE_VAL);
-	}
+	regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
+		     ACCDET_EINT0_STABLE_VAL);
 	/* after receive n+1 number, interrupt issued. */
 	regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR,
 			   ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT,
@@ -543,17 +472,9 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 
 	if (priv->data->hp_eint_high) {
 		/* EINT polarity inverse */
@@ -571,13 +492,8 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR,
-				   RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR,
-				   RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR, RG_EINT0EN_MASK_SFT,
+			   BIT(RG_EINT0EN_SFT));
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
 			   1 << 8, 1 << 8);
@@ -727,35 +643,18 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		priv->accdet_eint0 = platform_get_irq(pdev, 1);
-		if (priv->accdet_eint0 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint0,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT0", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint0 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
-		}
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		priv->accdet_eint1 = platform_get_irq(pdev, 2);
-		if (priv->accdet_eint1 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint1,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT1", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint1 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
+	priv->accdet_eint0 = platform_get_irq(pdev, 1);
+	if (priv->accdet_eint0 >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+						priv->accdet_eint0,
+						NULL, mt6359_accdet_irq,
+						IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+						"ACCDET_EINT0", priv);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request eint0 IRQ (%d)\n",
+				ret);
+			return ret;
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 288b8fbf7c5efaee6520a2c0a5845e156f3b805d..4156cbc7f0a1744226d5f28746bd13fec6c615b4 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -58,7 +58,6 @@ struct mt6359_accdet {
 	unsigned int caps;
 	int accdet_irq;
 	int accdet_eint0;
-	int accdet_eint1;
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;

-- 
2.48.1



From heiko at sntech.de  Sun Mar  2 08:57:39 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sun, 02 Mar 2025 17:57:39 +0100
Subject: [rockchip:v6.15-clk/next 10/10]
 drivers/clk/rockchip/clk-rk3562.c:1081:31: error: incomplete definition of
 type 'struct platform_device'
In-Reply-To: <202503021302.FjsycBI2-lkp@intel.com>
References: <202503021302.FjsycBI2-lkp@intel.com>
Message-ID: <870511149.0ifERbkFSE@diego>

Am Sonntag, 2. M?rz 2025, 06:53:23 MEZ schrieb kernel test robot:
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git v6.15-clk/next
> head:   36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a
> commit: 36c7fdc8f585acbf11c8e5bc112fa9d8ef75146a [10/10] clk: rockchip: Add clock controller for the RK3562
> config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20250302/202503021302.FjsycBI2-lkp at intel.com/config)
> compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250302/202503021302.FjsycBI2-lkp at intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202503021302.FjsycBI2-lkp at intel.com/

I've "fixed" the error by moving this new driver to how we handle all
other clock drivers already - not allowing them to build as module.

I've amended the original commit for that and also included the lkp report.


Heiko




From linux at armlinux.org.uk  Sun Mar  2 09:17:42 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 2 Mar 2025 17:17:42 +0000
Subject: [GIT PULL] Generic entry for ARM
In-Reply-To: <0oXU8PP2CHCw1Qblhw1cKOTt90K2CLbHo4BLw9LOs-J1klN1Y_N7IagulWZHR7bGhmxyPXlZTOUEqVZDtwcXj9j93_BxdrdnmW7qk3uIrU4=@proton.me>
References: <0oXU8PP2CHCw1Qblhw1cKOTt90K2CLbHo4BLw9LOs-J1klN1Y_N7IagulWZHR7bGhmxyPXlZTOUEqVZDtwcXj9j93_BxdrdnmW7qk3uIrU4=@proton.me>
Message-ID: <Z8SSthQ-gK686k8u@shell.armlinux.org.uk>

On Sun, Mar 02, 2025 at 03:23:20PM +0000, phil995511 wrote:
> It is a very bad idea to want to code the Linux kernel for ARM in C++ !!!
> 
> Our ARM CPUs on RPi and others are not powerful enough to use a Linux kernel written in C++ and therefore lose performance, while these ARM CPUs are already extremely low-performance !!!
> 
> Suggesting to code like this is to be in favor of planned obsolescence, of the scrapping of thousands of small machines ;-(

With all due respect, you have your knickers in a twist.

This is not about C++, it's about plain old fashioned C, which has been
the preferred kernel programming language for decades. I have no idea
where you've got the idea that LinusW's commit has anything to do with
C++.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From heiko at sntech.de  Sun Mar  2 10:34:56 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun,  2 Mar 2025 19:34:56 +0100
Subject: (subset) [PATCH v15 00/13] VOP Support for rk3576
In-Reply-To: <20250218112744.34433-1-andyshrk@163.com>
References: <20250218112744.34433-1-andyshrk@163.com>
Message-ID: <174094048722.1377102.8343744540534603918.b4-ty@sntech.de>


On Tue, 18 Feb 2025 19:27:27 +0800, Andy Yan wrote:
> PATCH 1~9 are preparations for rk3576 support
> PATCH 10~13 are real support for rk376
> 
> I test it with a 1080P/4K HDMI output with modetest and weston
> output.
> 
> If there are some one want to have a try, I have a tree based on
> Linux 6.14-rc1 here[0]
> 
> [...]

Applied, thanks!

[01/13] drm/rockchip: vop2: use devm_regmap_field_alloc for cluster-regs
        commit: ff0b6c031ed3ed31024618340c795523a86e6688
[02/13] drm/rockchip: vop2: Remove AFBC from TRANSFORM_OFFSET register macro
        commit: 838a871a4d51b59fe56ac0422b97443203bfa55c
[03/13] drm/rockchip: vop2: Add platform specific callback
        commit: 328e6885996ca2c6eb8b07d3c9bb1439fdcb088f
[04/13] drm/rockchip: vop2: Merge vop2_cluster/esmart_init function
        commit: 145c9b36892a07bf5e2525b4938e1a6cc9b41b7a
[05/13] drm/rockchip: vop2: Support for different layer select configuration between VPs
        commit: 5439c4f3cb0ec11a3f3cb70be2b019770f6d183c
[06/13] drm/rockchip: vop2: Introduce vop hardware version
        commit: 301618ed1d8ab7cfaec39b107eded9f263da2299

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From dsimic at manjaro.org  Sun Mar  2 10:48:03 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Sun,  2 Mar 2025 19:48:03 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board dtsi
In-Reply-To: <cover.1740941097.git.dsimic@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
Message-ID: <df3d7e8fe74ed5e727e085b18c395260537bb5ac.1740941097.git.dsimic@manjaro.org>

Add missing "avdd-0v9-supply" and "avdd-1v8-supply" properties to the "hdmi"
node in the Pine64 RockPro64 board dtsi file.  To achieve this, also add the
associated "vcca_0v9" regulator that produces the 0.9 V supply, [1][2] which
hasn't been defined previously in the board dtsi file.

This also eliminates the following warnings from the kernel log:

  dwhdmi-rockchip ff940000.hdmi: supply avdd-0v9 not found, using dummy regulator
  dwhdmi-rockchip ff940000.hdmi: supply avdd-1v8 not found, using dummy regulator

There are no functional changes to the way board works with these additions,
because the "vcc1v8_dvp" and "vcca_0v9" regulators are always enabled, [1][2]
but these additions improve the accuracy of hardware description.

These changes apply to the both supported hardware revisions of the Pine64
RockPro64, i.e. to the production-run revisions 2.0 and 2.1. [1][2]

[1] https://files.pine64.org/doc/rockpro64/rockpro64_v21-SCH.pdf
[2] https://files.pine64.org/doc/rockpro64/rockpro64_v20-SCH.pdf

Fixes: e4f3fb490967 ("arm64: dts: rockchip: add initial dts support for Rockpro64")
Cc: stable at vger.kernel.org
Suggested-by: Diederik de Haas <didi.debian at cknow.org>
Signed-off-by: Dragan Simic <dsimic at manjaro.org>
---
 arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
index 69a9d6170649..47dc198706c8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
@@ -227,6 +227,16 @@ vcc5v0_usb: regulator-vcc5v0-usb {
 		vin-supply = <&vcc12v_dcin>;
 	};
 
+	vcca_0v9: regulator-vcca-0v9 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcca_0v9";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <900000>;
+		regulator-max-microvolt = <900000>;
+		vin-supply = <&vcc3v3_sys>;
+	};
+
 	vdd_log: regulator-vdd-log {
 		compatible = "pwm-regulator";
 		pwms = <&pwm2 0 25000 1>;
@@ -312,6 +322,8 @@ &gmac {
 };
 
 &hdmi {
+	avdd-0v9-supply = <&vcca_0v9>;
+	avdd-1v8-supply = <&vcc1v8_dvp>;
 	ddc-i2c-bus = <&i2c3>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&hdmi_cec>;


From dsimic at manjaro.org  Sun Mar  2 10:48:02 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Sun,  2 Mar 2025 19:48:02 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64 RockPro64
Message-ID: <cover.1740941097.git.dsimic@manjaro.org>

This is a small series that introduces small improvements to the way
Pine64 RockPro64 [1] single-board-computer is described in the DT files.
This applies to both production-run revisions of the RockPro64.

The introduced improvements boil down to eliminating some warnings from
the kernel log, by adding a previously undefined regulator and by adding
some previously missing references to the regulators.

The patch 2/2 also results in reliability improvements, by reportedly
resolving (some of) the longstanding issues resulting from using certain
PCI Express cards with the Pine64 RockPro64.

Changes in v2:
  - Dissolved the patch 2/2 notes into its description, according to the
    numerous power cycling/rebooting tests performed on a Pine64 RockPro64
    by @ChriChri and reported in the #rock64 channel on irc.pine64.org
  - Adjusted the cover letter to match the latest test results
  - Added "Fixes" and "Cc: stable" tags to both patches in the series
  - Added "Tested-by" to the patch 2/2, thanks to Chris' testing [2]
  - Added a few "Cc" tags to the patch 2/2, to make sure people involved
    in the earlier related patch [3] are in the loop

Link to v1: https://lore.kernel.org/linux-rockchip/cover.1740748439.git.dsimic at manjaro.org/T/#u

[1] https://wiki.pine64.org/wiki/ROCKPro64
[2] https://z9.de/hedgedoc/s/nF4d5G7rg#reboot-tests-for-PCIe-improvements
[3] https://lore.kernel.org/lkml/20230509153912.515218-1-vincenzopalazzodev at gmail.com/T/#u

Dragan Simic (2):
  arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board dtsi
  arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 board
    dtsi

 .../boot/dts/rockchip/rk3399-rockpro64.dtsi      | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)



From dsimic at manjaro.org  Sun Mar  2 10:48:04 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Sun,  2 Mar 2025 19:48:04 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 board dtsi
In-Reply-To: <cover.1740941097.git.dsimic@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
Message-ID: <b39cfd7490d8194f053bf3971f13a43472d1769e.1740941097.git.dsimic@manjaro.org>

Add missing "vpcie0v9-supply" and "vpcie1v8-supply" properties to the "pcie0"
node in the Pine64 RockPro64 board dtsi file.  This eliminates the following
warnings from the kernel log:

  rockchip-pcie f8000000.pcie: supply vpcie1v8 not found, using dummy regulator
  rockchip-pcie f8000000.pcie: supply vpcie0v9 not found, using dummy regulator

These additions improve the accuracy of hardware description of the RockPro64
and, in theory, they should result in no functional changes to the way board
works after the changes, because the "vcca_0v9" and "vcca_1v8" regulators are
always enabled. [1][2]  However, extended reliability testing, performed by
Chris, [3] has proven that the age-old issues with some PCI Express cards,
when used with a Pine64 RockPro64, are also resolved.

Those issues were already mentioned in the commit 43853e843aa6 (arm64: dts:
rockchip: Remove unsupported node from the Pinebook Pro dts, 2024-04-01),
together with a brief description of the out-of-tree enumeration delay patch
that reportedly resolves those issues.  In a nutshell, booting a RockPro64
with some PCI Express cards attached to it caused a kernel oops. [4]

Symptomatically enough, to the commit author's best knowledge, only the Pine64
RockPro64, out of all RK3399-based boards and devices supported upstream, has
been reported to suffer from those PCI Express issues, and only the RockPro64
had some of the PCI Express supplies missing in its DT.  Thus, perhaps some
weird timing issues exist that caused the "vcca_1v8" always-on regulator,
which is part of the RK808 PMIC, to actually not be enabled before the PCI
Express is initialized and enumerated on the RockPro64, causing oopses with
some PCIe cards, and the aforementioned enumeration delay patch [4] probably
acted as just a workaround for the underlying timing issue.

Admittedly, the Pine64 RockPro64 is a bit specific board by having a standard
PCI Express slot, allowing use of various standard cards, but pretty much
standard PCI Express cards have been attached to other RK3399 boards as well,
and the commit author is unaware ot such issues reported for them.

It's quite hard to be sure that the PCI Express issues are fully resolved by
these additions to the DT, without some really extensive and time-consuming
testing.  However, these additions to the DT can result in good things and
improvements anyway, making them perfectly safe from the standpoint of being
unable to do any harm or cause some unforeseen regressions.

Shuffle and reorder the "vpcie*-supply" properties a bit, so they're sorted
alphanumerically, which is a bit more logical and more useful than having
these properties listed in their strict alphabetical order.

These changes apply to the both supported hardware revisions of the Pine64
RockPro64, i.e. to the production-run revisions 2.0 and 2.1. [1][2]

[1] https://files.pine64.org/doc/rockpro64/rockpro64_v21-SCH.pdf
[2] https://files.pine64.org/doc/rockpro64/rockpro64_v20-SCH.pdf
[3] https://z9.de/hedgedoc/s/nF4d5G7rg#reboot-tests-for-PCIe-improvements
[4] https://lore.kernel.org/lkml/20230509153912.515218-1-vincenzopalazzodev at gmail.com/T/#u

Fixes: bba821f5479e ("arm64: dts: rockchip: add PCIe nodes on rk3399-rockpro64")
Cc: stable at vger.kernel.org
Cc: Vincenzo Palazzo <vincenzopalazzodev at gmail.com>
Cc: Peter Geis <pgwipeout at gmail.com>
Cc: Bjorn Helgaas <helgaas at kernel.org>
Reported-by: Diederik de Haas <didi.debian at cknow.org>
Tested-by: Chris Vogel <chris at z9.de>
Signed-off-by: Dragan Simic <dsimic at manjaro.org>
---
 arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
index 47dc198706c8..41ee381ff81f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
@@ -673,8 +673,10 @@ &pcie0 {
 	num-lanes = <4>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie_perst>;
-	vpcie12v-supply = <&vcc12v_dcin>;
+	vpcie0v9-supply = <&vcca_0v9>;
+	vpcie1v8-supply = <&vcca_1v8>;
 	vpcie3v3-supply = <&vcc3v3_pcie>;
+	vpcie12v-supply = <&vcc12v_dcin>;
 	status = "okay";
 };
 


From heiko at sntech.de  Sun Mar  2 10:57:50 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sun, 02 Mar 2025 19:57:50 +0100
Subject: [PATCH v15 07/13] drm/rockchip: vop2: Register the primary plane and
 overlay plane separately
In-Reply-To: <20250218112744.34433-8-andyshrk@163.com>
References: <20250218112744.34433-1-andyshrk@163.com>
 <20250218112744.34433-8-andyshrk@163.com>
Message-ID: <2759797.BddDVKsqQX@diego>

Hi Andy,

Am Dienstag, 18. Februar 2025, 12:27:34 MEZ schrieb Andy Yan:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> In the upcoming VOP of rk3576, a Window cannot attach to all Video Ports,
> so make sure all VP find it's suitable primary plane, then register the
> remain windows as overlay plane will make code easier.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
> Tested-by: Detlev Casanova <detlev.casanova at collabora.com>
> 
> ---

patches 7-9 look good to go, but ...

this needs a rebase to adapt to
"drm/rockchip: vop2: Consistently use dev_err_probe()" [0]

[0] https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/b06d1ef3355571383cdb463cf0195b7a02efdfbf


> -		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
> -			vp = find_vp_without_primary(vop2);
> -			if (vp) {
> +			if (vop2_is_mirror_win(win))
> +				continue;
> +
> +			if (win->type == DRM_PLANE_TYPE_PRIMARY) {
>  				possible_crtcs = BIT(nvp);
>  				vp->primary_plane = win;
> +				ret = vop2_plane_init(vop2, win, possible_crtcs);
> +				if (ret) {
> +					drm_err(vop2->drm, "failed to init primary plane %s: %d\n",
> +						win->data->name, ret);

should also use dev_err_probe


Heiko




From heiko at sntech.de  Sun Mar  2 11:09:52 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sun, 02 Mar 2025 20:09:52 +0100
Subject: [PATCH v15 13/13] drm/rockchip: vop2: Add support for rk3576
In-Reply-To: <20250218112901.34564-1-andyshrk@163.com>
References: <20250218112744.34433-1-andyshrk@163.com>
 <20250218112901.34564-1-andyshrk@163.com>
Message-ID: <2764042.X9hSmTKtgW@diego>

Hi Andy,

Am Dienstag, 18. Februar 2025, 12:28:58 MEZ schrieb Andy Yan:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> VOP2 on rk3576:
> Three video ports:
> VP0 Max 4096x2160
> VP1 Max 2560x1600
> VP2 Max 1920x1080
> 
> 2 4K Cluster windows with AFBC/RFBC, line RGB and YUV
> 4 Esmart windows with line RGB/YUV support:
> Esmart0/1: 4K
> Esmart2/3: 2k, or worked together as a single 4K plane at shared
> line buffer mode.
> 
> Compared to the previous VOP, another difference is that each VP
> has its own independent vsync interrupt number.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
> Tested-by: Detlev Casanova <detlev.casanova at collabora.com>

some minor style things, but overall looks really good


> @@ -2665,6 +2721,32 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
>  	if (ret)
>  		return ret;
>  
> +	if (vop2->version >= VOP_VERSION_RK3576) {
> +		struct drm_crtc *crtc;
> +
> +		drm_for_each_crtc(crtc, drm) {
> +			struct vop2_video_port *vp = to_vop2_video_port(crtc);
> +			int vp_irq;
> +			const char *irq_name = devm_kasprintf(dev, GFP_KERNEL, "vp%d", vp->id);
> +
> +			if (!irq_name)
> +				return -ENOMEM;
> +
> +			vp_irq = platform_get_irq_byname(pdev, irq_name);
> +			if (vp_irq < 0) {
> +				DRM_DEV_ERROR(dev, "cannot find irq for vop2 vp%d\n", vp->id);

return dev_err_probe

> +				return vp_irq;
> +			}
> +
> +			ret = devm_request_irq(dev, vp_irq, rk3576_vp_isr, IRQF_SHARED, irq_name,
> +					       vp);
> +			if (ret) {
> +				DRM_DEV_ERROR(dev, "request irq for vop2 vp%d failed\n", vp->id);

return dev_err_probe

> +				return ret;
> +			}
> +		}
> +	}
> +
>  	ret = vop2_find_rgb_encoder(vop2);
>  	if (ret >= 0) {
>  		vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc,


> +static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp)
> +{
> +	struct vop2 *vop2 = vp->vop2;
> +	struct drm_crtc *crtc = &vp->crtc;
> +	struct drm_plane *plane;
> +
> +	vp->win_mask = 0;
> +
> +	drm_atomic_crtc_for_each_plane(plane, crtc) {
> +		struct vop2_win *win = to_vop2_win(plane);
> +
> +		win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
> +

nit: we probably don't need this empty line

> +		vp->win_mask |= BIT(win->data->phys_id);
> +
> +		if (vop2_cluster_window(win))
> +			vop2_setup_cluster_alpha(vop2, win);
> +	}
> +
> +	if (!vp->win_mask)
> +		return;
> +
> +	rk3576_vop2_setup_layer_mixer(vp);
> +	vop2_setup_alpha(vp);
> +	rk3576_vop2_setup_dly_for_windows(vp);
> +}


Heiko




From patrick at blueri.se  Sun Mar  2 12:02:16 2025
From: patrick at blueri.se (Patrick Wildt)
Date: Sun, 2 Mar 2025 21:02:16 +0100
Subject: [PATCH v5 1/2] dt-bindings: arm: rockchip: Add MNT Reform 2 (RCORE)
Message-ID: <Z8S5SHqUqKYiT6Wd@windev.fritz.box>

Document board compatible bindings for the MNT Reform 2 with it's RCORE
SoM, which is based on Firefly's iCore-3588Q.

Signed-off-by: Patrick Wildt <patrick at blueri.se>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
Changes for v5:
- No changes
Changes for v4:
- Added acked-by
Changes for v3:
- Split DT as it's based on a Firefly iCore-3588Q SoM
Changes for v2:
- No changes

 Documentation/devicetree/bindings/arm/rockchip.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index 522a6f0450ea..e21c5c8fc2a3 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -178,6 +178,13 @@ properties:
           - const: engicam,px30-core
           - const: rockchip,px30
 
+      - description: Firefly iCore-3588Q-based boards
+        items:
+          - enum:
+              - mntre,reform2-rcore
+          - const: firefly,icore-3588q
+          - const: rockchip,rk3588
+
       - description: Firefly Core-3588J-based boards
         items:
           - enum:
-- 
2.48.1



From patrick at blueri.se  Sun Mar  2 12:08:24 2025
From: patrick at blueri.se (Patrick Wildt)
Date: Sun, 2 Mar 2025 21:08:24 +0100
Subject: [PATCH v5 2/2] arm64: dts: rockchip: add MNT Reform 2
In-Reply-To: <Z8S5SHqUqKYiT6Wd@windev.fritz.box>
References: <Z8S5SHqUqKYiT6Wd@windev.fritz.box>
Message-ID: <Z8S6uDM634KJuyKP@windev.fritz.box>

MNT Reform 2 is an open source laptop with replaceable CPU modules,
including a version with the RK3588-based MNT RCORE[1], which is based
on Firefly's iCore-3588Q SoM:

- Rockchip RK3588
- Quad A76 and Quad A55 CPU
- 6 TOPS NPU
- up to 32GB LPDDR4x RAM
- SD Card slot
- Gigabit ethernet port
- HDMI port
- 2x mPCIe ports for WiFi or NVMe
- 3x USB 3.0 Type-A HOST port

[1] https://shop.mntre.com/products/mnt-reform

Co-developed-by: Lukas F. Hartmann <lukas at mntre.com>
Signed-off-by: Lukas F. Hartmann <lukas at mntre.com>
Signed-off-by: Patrick Wildt <patrick at blueri.se>
---
Changes for v5:
- Added Co-developed-by for Lukas
- Removed mem-supply vendor fork voodoo
- Sorted some properties alphabetically
Changes for v4:
- Added chassis-type.
- Removed unused nodes.
- Sorted nodes alphabetically.
Changes for v3:
- Split DT as it's based on a Firefly iCore-3588Q SoM.
Changes for v2:
- Aligned with bindings and schemas to appease DTB check warnings.
- Aligned with format of other RK3588 boards for consistency.

 arch/arm64/boot/dts/rockchip/Makefile         |   1 +
 .../rockchip/rk3588-firefly-icore-3588q.dtsi  | 443 ++++++++++++++++++
 .../boot/dts/rockchip/rk3588-mnt-reform2.dts  | 336 +++++++++++++
 3 files changed, 780 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts

diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index def1222c1907..88381d9a20e3 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -145,6 +145,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-firefly-itx-3588j.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-friendlyelec-cm3588-nas.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-h96-max-v58.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-jaguar.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-mnt-reform2.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6-lts.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-ok3588-c.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
new file mode 100644
index 000000000000..6726eeb49255
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
@@ -0,0 +1,443 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+#include "rk3588.dtsi"
+
+/ {
+	compatible = "firefly,icore-3588q", "rockchip,rk3588";
+
+	aliases {
+		mmc0 = &sdhci;
+	};
+};
+
+&cpu_b0 {
+	cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+	cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+	cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+	cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+	cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+	cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+	cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+	cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0m2_xfer>;
+	status = "okay";
+
+	vdd_cpu_big0_s0: regulator at 42 {
+		compatible = "rockchip,rk8602";
+		reg = <0x42>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <550000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-name = "vdd_cpu_big0_s0";
+		regulator-ramp-delay = <2300>;
+		vin-supply = <&vcc5v0_sys>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+
+	vdd_cpu_big1_s0: regulator at 43 {
+		compatible = "rockchip,rk8603", "rockchip,rk8602";
+		reg = <0x43>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <550000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-name = "vdd_cpu_big1_s0";
+		regulator-ramp-delay = <2300>;
+		vin-supply = <&vcc5v0_sys>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1m2_xfer>;
+	status = "okay";
+
+	vdd_npu_s0: vdd_npu_mem_s0: regulator at 42 {
+		compatible = "rockchip,rk8602";
+		reg = <0x42>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <550000>;
+		regulator-max-microvolt = <950000>;
+		regulator-name = "vdd_npu_s0";
+		regulator-ramp-delay = <2300>;
+		vin-supply = <&vcc5v0_sys>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+};
+
+&sdhci {
+	bus-width = <8>;
+	no-sdio;
+	no-sd;
+	non-removable;
+	max-frequency = <150000000>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	status = "okay";
+};
+
+&spi2 {
+	assigned-clocks = <&cru CLK_SPI2>;
+	assigned-clock-rates = <200000000>;
+	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+	status = "okay";
+
+	pmic at 0 {
+		compatible = "rockchip,rk806";
+		reg = <0x0>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+			    <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+		spi-max-frequency = <1000000>;
+		system-power-controller;
+
+		vcc1-supply = <&vcc5v0_sys>;
+		vcc2-supply = <&vcc5v0_sys>;
+		vcc3-supply = <&vcc5v0_sys>;
+		vcc4-supply = <&vcc5v0_sys>;
+		vcc5-supply = <&vcc5v0_sys>;
+		vcc6-supply = <&vcc5v0_sys>;
+		vcc7-supply = <&vcc5v0_sys>;
+		vcc8-supply = <&vcc5v0_sys>;
+		vcc9-supply = <&vcc5v0_sys>;
+		vcc10-supply = <&vcc5v0_sys>;
+		vcc11-supply = <&vcc_2v0_pldo_s3>;
+		vcc12-supply = <&vcc5v0_sys>;
+		vcc13-supply = <&vcc_1v1_nldo_s3>;
+		vcc14-supply = <&vcc_1v1_nldo_s3>;
+		vcca-supply = <&vcc5v0_sys>;
+
+		rk806_dvs1_null: dvs1-null-pins {
+			pins = "gpio_pwrctrl1";
+			function = "pin_fun0";
+		};
+
+		rk806_dvs2_null: dvs2-null-pins {
+			pins = "gpio_pwrctrl2";
+			function = "pin_fun0";
+		};
+
+		rk806_dvs3_null: dvs3-null-pins {
+			pins = "gpio_pwrctrl3";
+			function = "pin_fun0";
+		};
+
+		regulators {
+			vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
+				regulator-boot-on;
+				regulator-min-microvolt = <550000>;
+				regulator-max-microvolt = <950000>;
+				regulator-ramp-delay = <12500>;
+				regulator-name = "vdd_gpu_s0";
+				regulator-enable-ramp-delay = <400>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <550000>;
+				regulator-max-microvolt = <950000>;
+				regulator-ramp-delay = <12500>;
+				regulator-name = "vdd_cpu_lit_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_log_s0: dcdc-reg3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <675000>;
+				regulator-max-microvolt = <750000>;
+				regulator-ramp-delay = <12500>;
+				regulator-name = "vdd_log_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <750000>;
+				};
+			};
+
+			vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <550000>;
+				regulator-max-microvolt = <950000>;
+				regulator-ramp-delay = <12500>;
+				regulator-name = "vdd_vdenc_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_ddr_s0: dcdc-reg5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <675000>;
+				regulator-max-microvolt = <950000>;
+				regulator-ramp-delay = <12500>;
+				regulator-name = "vdd_ddr_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <850000>;
+				};
+			};
+
+			vdd2_ddr_s3: dcdc-reg6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vdd2_ddr_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_2v0_pldo_s3: dcdc-reg7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-name = "vdd_2v0_pldo_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <2000000>;
+				};
+			};
+
+			vcc_3v3_s3: dcdc-reg8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_3v3_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vddq_ddr_s0: dcdc-reg9 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vddq_ddr_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_1v8_s3: dcdc-reg10 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_1v8_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			avcc_1v8_s0: pldo-reg1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "avcc_1v8_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_1v8_s0: pldo-reg2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_1v8_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			avdd_1v2_s0: pldo-reg3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-name = "avdd_1v2_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_3v3_s0: pldo-reg4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_3v3_s0";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vccio_sd_s0: pldo-reg5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			pldo6_s3: pldo-reg6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "pldo6_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vdd_0v75_s3: nldo-reg1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <750000>;
+				regulator-name = "vdd_0v75_s3";
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <750000>;
+				};
+			};
+
+			vdd_ddr_pll_s0: nldo-reg2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-name = "vdd_ddr_pll_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <850000>;
+				};
+			};
+
+			avdd_0v75_s0: nldo-reg3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <750000>;
+				regulator-name = "avdd_0v75_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_0v85_s0: nldo-reg4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-name = "vdd_0v85_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_0v75_s0: nldo-reg5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <750000>;
+				regulator-name = "vdd_0v75_s0";
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+		};
+	};
+};
+
+&uart2 {
+	pinctrl-0 = <&uart2m0_xfer>;
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts b/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
new file mode 100644
index 000000000000..3f75a753021c
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 MNT Research GmbH
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include <dt-bindings/usb/pd.h>
+
+#include "rk3588-firefly-icore-3588q.dtsi"
+
+/ {
+	model = "MNT Reform 2 with RCORE RK3588 Module";
+	compatible = "mntre,reform2-rcore", "firefly,icore-3588q", "rockchip,rk3588";
+	chassis-type = "laptop";
+
+	aliases {
+		ethernet0 = &gmac0;
+		mmc1 = &sdmmc;
+	};
+
+	chosen {
+		stdout-path = "serial2:1500000n8";
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <0 8 16 32 64 128 160 200 255>;
+		default-brightness-level = <128>;
+		enable-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm8 0 10000 0>;
+	};
+
+	gmac0_clkin: external-gmac0-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+		clock-output-names = "gmac0_clkin";
+	};
+
+	pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
+		compatible = "regulator-fixed";
+		regulator-boot-on;
+		regulator-always-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-name = "pcie30_avdd1v8";
+		vin-supply = <&avcc_1v8_s0>;
+	};
+
+	pcie30_avdd0v75: regulator-pcie30-avdd0v75 {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <750000>;
+		regulator-max-microvolt = <750000>;
+		regulator-name = "pcie30_avdd0v75";
+		vin-supply = <&avdd_0v75_s0>;
+	};
+
+	vcc12v_dcin: regulator-vcc12v-dcin {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-name = "vcc12v_dcin";
+	};
+
+	vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_1v1_nldo_s3";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-name = "vcc3v3_pcie30";
+		vin-supply = <&vcc12v_dcin>;
+	};
+
+	vcc5v0_host: regulator-vcc5v0-host {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-name = "vcc5v0_host";
+	};
+
+	vcc5v0_sys: regulator-vcc5v0-sys {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-name = "vcc5v0_sys";
+		vin-supply = <&vcc12v_dcin>;
+	};
+
+	vcc5v0_usb: regulator-vcc5v0-usb {
+		compatible = "regulator-fixed";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-name = "vcc5v0_usb";
+		vin-supply = <&vcc12v_dcin>;
+	};
+};
+
+&combphy0_ps {
+	status = "okay";
+};
+
+&gmac0 {
+	clock_in_out = "output";
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-id";
+	pinctrl-names = "default";
+	pinctrl-0 = <&gmac0_miim
+		     &gmac0_tx_bus2
+		     &gmac0_rx_bus2
+		     &gmac0_rgmii_clk
+		     &gmac0_rgmii_bus
+		     &gmac0_clkinout
+		     &eth_phy_reset>;
+	status = "okay";
+};
+
+&gpu {
+	mali-supply = <&vdd_gpu_s0>;
+	sram-supply = <&vdd_gpu_mem_s0>;
+	status = "okay";
+};
+
+&hdmi0 {
+	status = "okay";
+};
+
+&hdmi0_in {
+	hdmi0_in_vp2: endpoint {
+		remote-endpoint = <&vp2_out_hdmi0>;
+	};
+};
+
+&hdptxphy_hdmi0 {
+	status = "okay";
+};
+
+&i2c6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6m0_xfer>;
+	status = "okay";
+
+	rtc at 68 {
+		compatible = "nxp,pcf8523";
+		reg = <0x68>;
+	};
+};
+
+&mdio0 {
+	rgmii_phy: ethernet-phy at 0 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0x0>;
+	};
+};
+
+&pcie2x1l2 {
+	pinctrl-0 = <&pcie2_0_rst>;
+	reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pcie30phy {
+	status = "okay";
+};
+
+&pcie3x4 {
+	num-lanes = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_reset>;
+	reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>;
+	vpcie3v3-supply = <&vcc3v3_pcie30>;
+	status = "okay";
+};
+
+&pinctrl {
+	dp {
+		dp1_hpd: dp1-hpd {
+			rockchip,pins = <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pcie2 {
+		pcie2_0_rst: pcie2-0-rst {
+			rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pcie3 {
+		pcie3_reset: pcie3-reset {
+			rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	eth_phy {
+		eth_phy_reset: eth-phy-reset {
+			rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&pwm8 {
+	pinctrl-0 = <&pwm8m2_pins>;
+	status = "okay";
+};
+
+&saradc {
+	vref-supply = <&avcc_1v8_s0>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+	disable-wp;
+	max-frequency = <40000000>;
+	no-1-8-v;
+	no-mmc;
+	no-sdio;
+	vmmc-supply = <&vcc3v3_pcie30>;
+	vqmmc-supply = <&vcc3v3_pcie30>;
+	status = "okay";
+};
+
+&tsadc {
+	status = "okay";
+};
+
+&u2phy0 {
+	status = "okay";
+};
+
+&u2phy0_otg {
+	status = "okay";
+};
+
+&u2phy1 {
+	status = "okay";
+};
+
+&u2phy1_otg {
+	status = "okay";
+};
+
+&u2phy2 {
+	status = "okay";
+};
+
+&u2phy2_host {
+	phy-supply = <&vcc5v0_host>;
+	status = "okay";
+};
+
+&u2phy3 {
+	status = "okay";
+};
+
+&u2phy3_host {
+	phy-supply = <&vcc5v0_host>;
+	status = "okay";
+};
+
+&usbdp_phy0 {
+	status = "okay";
+};
+
+&usbdp_phy1 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&usb_host0_xhci {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb_host1_ehci {
+	status = "okay";
+};
+
+&usb_host1_ohci {
+	status = "okay";
+};
+
+&usb_host1_xhci {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp2 {
+	vp2_out_hdmi0: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+		remote-endpoint = <&hdmi0_in_vp2>;
+	};
+};
-- 
2.48.1



From lkp at intel.com  Sun Mar  2 13:41:40 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 3 Mar 2025 05:41:40 +0800
Subject: [PATCH] media: s5p-mfc: Support for handling RET_ENC_BUFFER_FULL
 interrupt
In-Reply-To: <20250228065952.14375-1-aakarsh.jain@samsung.com>
References: <20250228065952.14375-1-aakarsh.jain@samsung.com>
Message-ID: <202503030529.ccd21udL-lkp@intel.com>

Hi Aakarsh,

kernel test robot noticed the following build errors:

[auto build test ERROR on soc/for-next]
[also build test ERROR on linuxtv-media-pending/master linus/master sailus-media-tree/streams sailus-media-tree/master v6.14-rc4 next-20250228]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Aakarsh-Jain/media-s5p-mfc-Support-for-handling-RET_ENC_BUFFER_FULL-interrupt/20250228-175738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
patch link:    https://lore.kernel.org/r/20250228065952.14375-1-aakarsh.jain%40samsung.com
patch subject: [PATCH] media: s5p-mfc: Support for handling RET_ENC_BUFFER_FULL interrupt
config: loongarch-allyesconfig (https://download.01.org/0day-ci/archive/20250303/202503030529.ccd21udL-lkp at intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250303/202503030529.ccd21udL-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503030529.ccd21udL-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c: In function 's5p_mfc_irq':
>> drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c:742:14: error: 'S5P_MFC_R2H_CMD_ENC_BUFFER_FULL_RET' undeclared (first use in this function); did you mean 'S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET'?
     742 |         case S5P_MFC_R2H_CMD_ENC_BUFFER_FULL_RET:
         |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |              S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET
   drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c:742:14: note: each undeclared identifier is reported only once for each function it appears in


vim +742 drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c

   645	
   646	/* Interrupt processing */
   647	static irqreturn_t s5p_mfc_irq(int irq, void *priv)
   648	{
   649		struct s5p_mfc_dev *dev = priv;
   650		struct s5p_mfc_ctx *ctx;
   651		unsigned int reason;
   652		unsigned int err;
   653	
   654		mfc_debug_enter();
   655		/* Reset the timeout watchdog */
   656		atomic_set(&dev->watchdog_cnt, 0);
   657		spin_lock(&dev->irqlock);
   658		ctx = dev->ctx[dev->curr_ctx];
   659		/* Get the reason of interrupt and the error code */
   660		reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
   661		err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
   662		mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
   663		switch (reason) {
   664		case S5P_MFC_R2H_CMD_ERR_RET:
   665			/* An error has occurred */
   666			if (ctx->state == MFCINST_RUNNING &&
   667				(s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
   668					dev->warn_start ||
   669					err == S5P_FIMV_ERR_NO_VALID_SEQ_HDR ||
   670					err == S5P_FIMV_ERR_INCOMPLETE_FRAME ||
   671					err == S5P_FIMV_ERR_TIMEOUT))
   672				s5p_mfc_handle_frame(ctx, reason, err);
   673			else
   674				s5p_mfc_handle_error(dev, ctx, reason, err);
   675			clear_bit(0, &dev->enter_suspend);
   676			break;
   677	
   678		case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
   679		case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
   680		case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
   681			if (ctx->c_ops->post_frame_start) {
   682				if (ctx->c_ops->post_frame_start(ctx))
   683					mfc_err("post_frame_start() failed\n");
   684	
   685				if (ctx->state == MFCINST_FINISHING &&
   686							list_empty(&ctx->ref_queue)) {
   687					s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   688					s5p_mfc_handle_stream_complete(ctx);
   689					break;
   690				}
   691				s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   692				WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
   693				s5p_mfc_clock_off(dev);
   694				wake_up_ctx(ctx, reason, err);
   695				s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
   696			} else {
   697				s5p_mfc_handle_frame(ctx, reason, err);
   698			}
   699			break;
   700	
   701		case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
   702			s5p_mfc_handle_seq_done(ctx, reason, err);
   703			break;
   704	
   705		case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
   706			ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
   707			ctx->state = MFCINST_GOT_INST;
   708			goto irq_cleanup_hw;
   709	
   710		case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
   711			ctx->inst_no = MFC_NO_INSTANCE_SET;
   712			ctx->state = MFCINST_FREE;
   713			goto irq_cleanup_hw;
   714	
   715		case S5P_MFC_R2H_CMD_SYS_INIT_RET:
   716		case S5P_MFC_R2H_CMD_FW_STATUS_RET:
   717		case S5P_MFC_R2H_CMD_SLEEP_RET:
   718		case S5P_MFC_R2H_CMD_WAKEUP_RET:
   719			if (ctx)
   720				clear_work_bit(ctx);
   721			s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   722			clear_bit(0, &dev->hw_lock);
   723			clear_bit(0, &dev->enter_suspend);
   724			wake_up_dev(dev, reason, err);
   725			break;
   726	
   727		case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
   728			s5p_mfc_handle_init_buffers(ctx, reason, err);
   729			break;
   730	
   731		case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
   732			s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   733			ctx->int_type = reason;
   734			ctx->int_err = err;
   735			s5p_mfc_handle_stream_complete(ctx);
   736			break;
   737	
   738		case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
   739			ctx->state = MFCINST_RUNNING;
   740			goto irq_cleanup_hw;
   741	
 > 742		case S5P_MFC_R2H_CMD_ENC_BUFFER_FULL_RET:
   743			ctx->state = MFCINST_NAL_ABORT;
   744			s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   745			set_work_bit(ctx);
   746			WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
   747			s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
   748			break;
   749	
   750		case S5P_MFC_R2H_CMD_NAL_ABORT_RET:
   751			ctx->state = MFCINST_ERROR;
   752			s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
   753			s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
   754			goto irq_cleanup_hw;
   755	
   756		default:
   757			mfc_debug(2, "Unknown int reason\n");
   758			s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   759		}
   760		spin_unlock(&dev->irqlock);
   761		mfc_debug_leave();
   762		return IRQ_HANDLED;
   763	irq_cleanup_hw:
   764		s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
   765		ctx->int_type = reason;
   766		ctx->int_err = err;
   767		ctx->int_cond = 1;
   768		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
   769			mfc_err("Failed to unlock hw\n");
   770	
   771		s5p_mfc_clock_off(dev);
   772		clear_work_bit(ctx);
   773		wake_up(&ctx->queue);
   774	
   775		s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
   776		spin_unlock(&dev->irqlock);
   777		mfc_debug(2, "Exit via irq_cleanup_hw\n");
   778		return IRQ_HANDLED;
   779	}
   780	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From simons.philippe at gmail.com  Sun Mar  2 14:44:10 2025
From: simons.philippe at gmail.com (Philippe Simons)
Date: Sun, 2 Mar 2025 23:44:10 +0100
Subject: [PATCH 0/5] arm64: sunxi: h616: Enable Mali GPU
In-Reply-To: <20250221005802.11001-1-andre.przywara@arm.com>
References: <20250221005802.11001-1-andre.przywara@arm.com>
Message-ID: <01775d74-d72e-4a93-8a02-c13f7365d385@gmail.com>

Tested this on a RG35XX-H (H700),

launching glmark2-es2-drm completely hangs the board.

No kernel oops or error messages.

Philippe

On 21/02/2025 01:57, Andre Przywara wrote:
> The Allwinner H616/H618/H313/H700 SoCs contain a Mali G32 MP2 GPU. This
> IP is from the Bifrost family and is already supported by the panfrost
> driver, so enabling support for 3D graphics on this SoC is rather
> straight-forward.
> However Allwinner added some bits in the PRCM block, that control the
> power domain for the GPU - on top of its power *supply*.
>
> This series enables the Mali GPU on those SoCs, by first introducing a
> power domain driver for that SoC (patch 1/5: DT binding, patch 2/5:
> the actual driver). For the Mali GPU to work we literally need to flip a
> single bit (the BSP does this in the bootloader), and this full featured
> power domain driver is admittedly a bit over the top for that purpose.
> However it seems to be the right thing to do architecturally, and while
> at it I added the other power domains (for analogue, PLLs, and the
> management core), even though we won't use them in Linux and they would
> be always on. I have a simpler version of the driver which just covers
> this single bit controlling the GPU, please let me know if you prefer
> that.
> Please also note that this supersedes an RFC patch I sent a year ago,
> which included this power domain in the R-CCU driver:
> https://lore.kernel.org/linux-sunxi/20240225160616.15001-1-andre.przywara at arm.com/T/#u
>
> The rest of the patches enable the Mali GPU on the DT side: patch 3/5
> adds the compatible string to the Mali DT binding, while patch 4/5 adds
> the purely SoC specific DT nodes, for both the power domain and the Mali
> GPU. The final patch 5/5 then enables the GPU on all existing H616-family
> boards.
>
> There seems to be an existing problem with powering up the GPU, after it
> has been turned off by the kernel. Chances are this is a problem with the
> proper power-up (or power-down) sequence, where clock gates, reset lines
> and the power domain must be asserted in a specific order.
> A workaround used so far downstream is to keep the power domain enabled,
> by ignoring the power-off request. Observing any assumed "proper" sequence
> is a bit more tricky, since there is no Allwinner specific glue driver
> or anything, so things would need be changed in the generic panfrost
> code, where they have the potential of breaking other Mali users.
> I would be interested in hearing opinions about this.
>
> Cheers,
> Andre
>
> Andre Przywara (5):
>    dt-bindings: power: Add Allwinner H6/H616 PRCM PPU
>    pmdomain: sunxi: add H6 PRCM PPU driver
>    dt-bindings: gpu: mali-bifrost: Add Allwinner H616 compatible
>    arm64: dts: allwinner: h616: Add Mali GPU node
>    arm64: dts: allwinner: h616: enable Mali GPU for all boards
>
>   .../bindings/gpu/arm,mali-bifrost.yaml        |   1 +
>   .../power/allwinner,sun50i-h6-prcm-ppu.yaml   |  42 ++++
>   .../dts/allwinner/sun50i-h313-tanix-tx1.dts   |   5 +
>   .../sun50i-h616-bigtreetech-cb1.dtsi          |   5 +
>   .../allwinner/sun50i-h616-orangepi-zero.dtsi  |   4 +
>   .../allwinner/sun50i-h616-orangepi-zero2.dts  |   4 +
>   .../dts/allwinner/sun50i-h616-x96-mate.dts    |   5 +
>   .../arm64/boot/dts/allwinner/sun50i-h616.dtsi |  21 ++
>   .../sun50i-h618-longan-module-3h.dtsi         |   5 +
>   .../allwinner/sun50i-h618-orangepi-zero2w.dts |   5 +
>   .../allwinner/sun50i-h618-orangepi-zero3.dts  |   4 +
>   .../sun50i-h618-transpeed-8k618-t.dts         |   5 +
>   .../sun50i-h618-yuzukihd-chameleon.dts        |   5 +
>   .../sun50i-h700-anbernic-rg35xx-2024.dts      |   5 +
>   drivers/pmdomain/sunxi/Kconfig                |  10 +
>   drivers/pmdomain/sunxi/Makefile               |   1 +
>   drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c   | 191 ++++++++++++++++++
>   17 files changed, 318 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/power/allwinner,sun50i-h6-prcm-ppu.yaml
>   create mode 100644 drivers/pmdomain/sunxi/sun50i-h6-prcm-ppu.c
>


From gshan at redhat.com  Sun Mar  2 15:36:20 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 09:36:20 +1000
Subject: [PATCH v7 01/45] KVM: Prepare for handling only shared mappings
 in mmu_notifier events
In-Reply-To: <20250213161426.102987-2-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-2-steven.price@arm.com>
Message-ID: <8bf9ba6c-a8b2-42aa-9802-8e968bec1cd5@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> From: Sean Christopherson <seanjc at google.com>
> 
> Add flags to "struct kvm_gfn_range" to let notifier events target only
> shared and only private mappings, and write up the existing mmu_notifier
> events to be shared-only (private memory is never associated with a
> userspace virtual address, i.e. can't be reached via mmu_notifiers).
> 
> Add two flags so that KVM can handle the three possibilities (shared,
> private, and shared+private) without needing something like a tri-state
> enum.
> 
> Link: https://lore.kernel.org/all/ZJX0hk+KpQP0KUyB at google.com
> Signed-off-by: Sean Christopherson <seanjc at google.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   include/linux/kvm_host.h | 2 ++
>   virt/kvm/kvm_main.c      | 7 +++++++
>   2 files changed, 9 insertions(+)
> 
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 3cb9a32a6330..0de1e485452c 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -266,6 +266,8 @@ struct kvm_gfn_range {
>   	gfn_t end;
>   	union kvm_mmu_notifier_arg arg;
>   	enum kvm_gfn_range_filter attr_filter;
> +	bool only_private;
> +	bool only_shared;
>   	bool may_block;
>   };

The added members (only_private and only_shared) looks duplicated to the
member of attr_filter, which can be set to KVM_FILTER_SHARED, KVM_FILTER_PRIVATE,
or both of them. More details can be found from the following commit where
attr_filter was by dca6c88532322 ("KVM: Add member to struct kvm_gfn_range
to indicate private/shared").

I'm guessing Sean's suggestion was given before dca6c88532322 showed up.

>   bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index faf10671eed2..4f0136094fac 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -593,6 +593,13 @@ static __always_inline kvm_mn_ret_t __kvm_handle_hva_range(struct kvm *kvm,
>   			 * the second or later invocation of the handler).
>   			 */
>   			gfn_range.arg = range->arg;
> +
> +			/*
> +			 * HVA-based notifications aren't relevant to private
> +			 * mappings as they don't have a userspace mapping.
> +			 */
> +			gfn_range.only_private = false;
> +			gfn_range.only_shared = true;
>   			gfn_range.may_block = range->may_block;
>   			/*
>   			 * HVA-based notifications aren't relevant to private

Thanks,
Gavin



From gshan at redhat.com  Sun Mar  2 15:39:43 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 09:39:43 +1000
Subject: [PATCH v7 02/45] kvm: arm64: Include kvm_emulate.h in
 kvm/arm_psci.h
In-Reply-To: <20250213161426.102987-3-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-3-steven.price@arm.com>
Message-ID: <a7077902-4286-4b3d-913a-20083ff260f4@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> From: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Fix a potential build error (like below, when asm/kvm_emulate.h gets
> included after the kvm/arm_psci.h) by including the missing header file
> in kvm/arm_psci.h:
> 
> ./include/kvm/arm_psci.h: In function ?kvm_psci_version?:
> ./include/kvm/arm_psci.h:29:13: error: implicit declaration of function
>     ?vcpu_has_feature?; did you mean ?cpu_have_feature?? [-Werror=implicit-function-declaration]
>     29 |         if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_PSCI_0_2)) {
> 	         |             ^~~~~~~~~~~~~~~~
> 			       |             cpu_have_feature
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   include/kvm/arm_psci.h | 2 ++
>   1 file changed, 2 insertions(+)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From gshan at redhat.com  Sun Mar  2 15:43:52 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 09:43:52 +1000
Subject: [PATCH v7 03/45] arm64: RME: Handle Granule Protection Faults
 (GPFs)
In-Reply-To: <20250213161426.102987-4-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-4-steven.price@arm.com>
Message-ID: <9dbebd7b-b441-405d-8c45-0dfa4d3df9e3@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> If the host attempts to access granules that have been delegated for use
> in a realm these accesses will be caught and will trigger a Granule
> Protection Fault (GPF).
> 
> A fault during a page walk signals a bug in the kernel and is handled by
> oopsing the kernel. A non-page walk fault could be caused by user space
> having access to a page which has been delegated to the kernel and will
> trigger a SIGBUS to allow debugging why user space is trying to access a
> delegated page.
> 
> Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v2:
>   * Include missing "Granule Protection Fault at level -1"
> ---
>   arch/arm64/mm/fault.c | 31 +++++++++++++++++++++++++------
>   1 file changed, 25 insertions(+), 6 deletions(-)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From gshan at redhat.com  Sun Mar  2 15:52:05 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 09:52:05 +1000
Subject: [PATCH v7 04/45] arm64: RME: Add SMC definitions for calling the
 RMM
In-Reply-To: <20250213161426.102987-5-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-5-steven.price@arm.com>
Message-ID: <7c217ce9-588e-4e4a-b395-2cd5d014487e@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> The RMM (Realm Management Monitor) provides functionality that can be
> accessed by SMC calls from the host.
> 
> The SMC definitions are based on DEN0137[1] version 1.0-rel0
> 
> [1] https://developer.arm.com/documentation/den0137/1-0rel0/
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Renamed REC_ENTER_xxx defines to include 'FLAG' to make it obvious
>     these are flag values.
> Changes since v5:
>   * Sorted the SMC #defines by value.
>   * Renamed SMI_RxI_CALL to SMI_RMI_CALL since the macro is only used for
>     RMI calls.
>   * Renamed REC_GIC_NUM_LRS to REC_MAX_GIC_NUM_LRS since the actual
>     number of available list registers could be lower.
>   * Provided a define for the reserved fields of FeatureRegister0.
>   * Fix inconsistent names for padding fields.
> Changes since v4:
>   * Update to point to final released RMM spec.
>   * Minor rearrangements.
> Changes since v3:
>   * Update to match RMM spec v1.0-rel0-rc1.
> Changes since v2:
>   * Fix specification link.
>   * Rename rec_entry->rec_enter to match spec.
>   * Fix size of pmu_ovf_status to match spec.
> ---
>   arch/arm64/include/asm/rmi_smc.h | 259 +++++++++++++++++++++++++++++++
>   1 file changed, 259 insertions(+)
>   create mode 100644 arch/arm64/include/asm/rmi_smc.h
> 

One nitpick below, with it addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_smc.h
> new file mode 100644
> index 000000000000..f85a82072337
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_smc.h
> @@ -0,0 +1,259 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023-2024 ARM Ltd.
> + *
> + * The values and structures in this file are from the Realm Management Monitor
> + * specification (DEN0137) version 1.0-rel0:
> + * https://developer.arm.com/documentation/den0137/1-0rel0/
> + */
> +
> +#ifndef __ASM_RME_SMC_H
> +#define __ASM_RME_SMC_H
> +

#ifndef __ASM_RMI_SMC_H
#define __ASM_RMI_SMC_H


[...]

> +
> +struct rec_run {
> +	struct rec_enter enter;
> +	struct rec_exit exit;
> +};
> +
> +#endif

#endif /* __ASM_RMI_SMC_H */



From Macpaul.Lin at mediatek.com  Sun Mar  2 18:30:24 2025
From: Macpaul.Lin at mediatek.com (=?utf-8?B?TWFjcGF1bCBMaW4gKOael+aZuuaWjCk=?=)
Date: Mon, 3 Mar 2025 02:30:24 +0000
Subject: [PATCH v2 19/20] arm64: dts: mt6359: Add accessory detect node
In-Reply-To: <20250302-mt6359-accdet-dts-v2-19-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
	 <20250302-mt6359-accdet-dts-v2-19-5bd633ee0d47@collabora.com>
Message-ID: <3dd23bad242f1578a8084ad7acfce883a412cfe7.camel@mediatek.com>

On Sun, 2025-03-02 at 13:30 -0300, N?colas F. R. A. Prado wrote:
> 
> Add audio jack detection node. PMIC accessory detect driver will
> create an input device that will send key events on jack
> insertion/removal or accessory device key presses.
> 
> Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
> ?arch/arm64/boot/dts/mediatek/mt6359.dtsi | 4 ++++
> ?1 file changed, 4 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
> b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
> index
> 7b10f9c59819a9ad02319f00938f35c931091f9f..e24e4aeb3b9cafa2af56c62bc4c
> 549df27d0ec73 100644
> --- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
> @@ -15,6 +15,10 @@ pmic_adc: adc {
> ??????????????????????? #io-channel-cells = <1>;
> ??????????????? };
> 
> +?????????????? accdet: accdet {
> +?????????????????????? compatible = "mediatek,mt6359-accdet";
> +?????????????? };
> +
> ??????????????? mt6359codec: audio-codec {
> ??????????????????????? compatible = "mediatek,mt6359-codec";
> ??????????????? };
> 
> --
> 2.48.1
> 

Reviewed-by: Macpaul Lin <macpaul.lin at mediatek.com>

Thanks!
Macpaul Lin

From ck.hu at mediatek.com  Sun Mar  2 18:37:47 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 3 Mar 2025 02:37:47 +0000
Subject: [PATCH v4 3/4] uapi: linux: add MT8188 AIE
In-Reply-To: <20250220070114.15015-4-bo.kong@mediatek.com>
References: <20250220070114.15015-1-bo.kong@mediatek.com>
	 <20250220070114.15015-4-bo.kong@mediatek.com>
Message-ID: <059077301334d7b683df38cb62e96f74c7300b15.camel@mediatek.com>

On Thu, 2025-02-20 at 14:59 +0800, bo.kong wrote:
> From: Bo Kong <Bo.Kong at mediatek.com>
> 
> Add AIE control related definitions.
> 
> Signed-off-by: Bo Kong <Bo.Kong at mediatek.com>
> ---
> Changes in v4:
> 1. Add document to describe the detail of V4L2_META_FMT_MTFD_RESULT
> 2. Add the introduction of related variables
> 
> Changes in v3:
> None
> 
> Changes in v2:
> 1. Fix coding style
> ---
>  drivers/media/v4l2-core/v4l2-ioctl.c       |   3 +
>  include/uapi/linux/mtk_aie_v4l2_controls.h | 134 +++++++++++++++++++++
>  include/uapi/linux/videodev2.h             |   6 +
>  3 files changed, 143 insertions(+)
>  create mode 100644 include/uapi/linux/mtk_aie_v4l2_controls.h
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 0304daa8471d..4fdf693ddd1e 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -1477,6 +1477,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
>  	case V4L2_META_FMT_GENERIC_CSI2_16:	descr = "8-bit Generic Meta, 16b CSI-2"; break;
>  	case V4L2_META_FMT_GENERIC_CSI2_20:	descr = "8-bit Generic Meta, 20b CSI-2"; break;
>  	case V4L2_META_FMT_GENERIC_CSI2_24:	descr = "8-bit Generic Meta, 24b CSI-2"; break;
> +	case V4L2_META_FMT_MTFD_RESULT:
> +		descr = "MTK AIE Result Fmt";
> +	break;
>  
>  	default:
>  		/* Compressed formats */
> diff --git a/include/uapi/linux/mtk_aie_v4l2_controls.h b/include/uapi/linux/mtk_aie_v4l2_controls.h
> new file mode 100644
> index 000000000000..d8fd30f9288c
> --- /dev/null
> +++ b/include/uapi/linux/mtk_aie_v4l2_controls.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * AIE Controls Header
> + *
> + * Copyright (c) 2020 MediaTek Inc.
> + * Author: Fish Wu <fish.wu at mediatek.com>
> + */
> +
> +#ifndef __MTK_AIE_V4L2_CONTROLS_H__
> +#define __MTK_AIE_V4L2_CONTROLS_H__
> +
> +#include <linux/types.h>
> +
> +/*
> + * The base for the mediatek Face Detection driver controls.
> + * We reserve 16 controls for this driver.
> + * Each CID represents different stages of AIE, with different structures and functions
> + * and cannot be reused
> + */
> +#define V4L2_CID_USER_MTK_FD_BASE (V4L2_CID_USER_BASE + 0x1fd0)
> +
> +#define V4L2_CID_MTK_AIE_INIT (V4L2_CID_USER_MTK_FD_BASE + 1)
> +#define V4L2_CID_MTK_AIE_PARAM (V4L2_CID_USER_MTK_FD_BASE + 2)
> +
> +#define V4L2_FLD_MAX_FRAME 15
> +
> +/**
> + * struct v4l2_ctrl_aie_init - aie init parameters.
> + *
> + * @max_img_width: maximum width of the source image.
> + * @max_img_height: maximum height of the source image.
> + * @pyramid_width: maximum width of the base pyramid.
> + * @pyramid_height: maximum height of the base pyramid.
> + * @feature_threshold: feature threshold for hareware.

How to assign the feature_threshold?
0 ~ 100?
What's the effect for small value or large value?

> + */
> +struct v4l2_ctrl_aie_init {
> +	__u32 max_img_width;
> +	__u32 max_img_height;
> +	__u32 pyramid_width;
> +	__u32 pyramid_height;
> +	__s32 feature_threshold;
> +};
> +
> +/**
> + * struct v4l2_aie_roi - aie roi parameters.
> + *
> + * @x1: x1 of the roi coordinate.
> + * @y1: y1 of the roi coordinate.
> + * @x2: x2 of the roi coordinate.
> + * @y2: y2 of the roi coordinate.
> + */
> +struct v4l2_aie_roi {

struct v4l2_rect {};

> +	__u32 x1;
> +	__u32 y1;
> +	__u32 x2;
> +	__u32 y2;
> +};
> +
> +/**
> + * struct v4l2_aie_padding - aie padding parameters.
> + *
> + * @left: the size of padding left.
> + * @right: the size of padding right.
> + * @down: the size of padding below.
> + * @up: the size of padding above.
> + */
> +struct v4l2_aie_padding {

struct v4l2_rect {};

> +	__u32 left;
> +	__u32 right;
> +	__u32 down;
> +	__u32 up;
> +};
> +
> +/**
> + * struct v4l2_fld_crop_rip_rop - aie fld parameters.
> + *
> + * @fld_in_crop_x1: x1 of the crop coordinate.
> + * @fld_in_crop_y1: y1 of the crop coordinate.
> + * @fld_in_crop_x2: x2 of the crop coordinate.
> + * @fld_in_crop_y2: y2 of the crop coordinate.
> + * @fld_in_rip: fld in rip.
> + * @fld_in_rop: fld in rop.
> + */
> +struct v4l2_fld_crop_rip_rop {
> +	__u32 fld_in_crop_x1;
> +	__u32 fld_in_crop_y1;
> +	__u32 fld_in_crop_x2;
> +	__u32 fld_in_crop_y2;
> +	__u32 fld_in_rip;
> +	__u32 fld_in_rop;
> +};
> +
> +/**
> + * struct v4l2_fld_crop_rip_rop - aie fld parameters.
> + *
> + * @fd_mode: select a mode(FDMODE, ATTRIBUTEMODE, FLDMODE) for current fd.

The mode name is not clear for user to use it.
ATTRIBUTEMODE would output attribute string for each object?
What the attribute could be?
What's FLDMODE? Field mode? What's field mode?
Describe more about these mode so that user would understand select which mode to use.

> + * @src_img_fmt: source image format.
> + * @src_img_width: the width of the source image.
> + * @src_img_height: the height of the source image.
> + * @src_img_stride: the stride of the source image.

I'm not familiar with V4L2, but I think there is a standard interface to set source buffer format, width, height, stride.

> + * @pyramid_base_width: pyramid is the size of resizer, the width of the base pyramid.
> + * @pyramid_base_height: pyramid is the size of resizer, the width of the base pyramid.
> + * @number_of_pyramid: number of pyramid, min: 1, max: 3.
> + * @rotate_degree: the rotate degree of the image.
> + * @en_roi: enable roi(roi is a box diagram that selects a rectangle in a picture).
> + *          when en_roi is enable, AIE will return a rectangle face detection result
> + * @src_roi: roi params.
> + * @en_padding: enable padding.
> + * @src_padding: padding params.

In which case need padding?
For face detection, padding would not help any thing.

> + * @freq_level: frequency level, Get value from user space.

What's freq_level?
How to assign it?

> + * @fld_face_num: the number of faces in fld.
> + *                user space tells driver the number of detections.
> + * @fld_input: fld input params.
> + */
> +struct v4l2_ctrl_aie_param {
> +	__u32 fd_mode;
> +	__u32 src_img_fmt;
> +	__u32 src_img_width;
> +	__u32 src_img_height;
> +	__u32 src_img_stride;
> +	__u32 pyramid_base_width;
> +	__u32 pyramid_base_height;
> +	__u32 number_of_pyramid;
> +	__u32 rotate_degree;
> +	__s32 en_roi;
> +	struct v4l2_aie_roi src_roi;
> +	__s32 en_padding;
> +	struct v4l2_aie_padding src_padding;
> +	__u32 freq_level;
> +	__u32 fld_face_num;
> +	struct v4l2_fld_crop_rip_rop fld_input[V4L2_FLD_MAX_FRAME];
> +};
> +
> +#endif /* __MTK_AIE_V4L2_CONTROLS_H__ */
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index e7c4dce39007..8492f44eb55d 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -858,6 +858,9 @@ struct v4l2_pix_format {
>  #define V4L2_META_FMT_RK_ISP1_STAT_3A	v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */
>  #define V4L2_META_FMT_RK_ISP1_EXT_PARAMS	v4l2_fourcc('R', 'K', '1', 'E') /* Rockchip ISP1 3a Extensible Parameters */
>  
> +/* Vendor-specific definition: used for the MediaTek camera subsystem's face detection results */
> +#define V4L2_META_FMT_MTFD_RESULT	v4l2_fourcc('M', 'T', 'f', 'd')

Add document to describe the detail of V4L2_META_FMT_MTFD_RESULT. [1] is the example document for V4L2_META_FMT_RPI_FE_CFG.
There are many document in Documentation/userspace-api/media/v4l/ for your reference.

[1] https://patchwork.kernel.org/project/linux-media/patch/20241003-rp1-cfe-v6-1-d6762edd98a8 at ideasonboard.com/

Regards,
CK

> +
>  /* Vendor specific - used for RaspberryPi PiSP */
>  #define V4L2_META_FMT_RPI_BE_CFG	v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */
>  #define V4L2_META_FMT_RPI_FE_CFG	v4l2_fourcc('R', 'P', 'F', 'C') /* PiSP FE configuration */
> @@ -1961,6 +1964,9 @@ enum v4l2_ctrl_type {
>  	V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY = 0x281,
>  	V4L2_CTRL_TYPE_AV1_FRAME	    = 0x282,
>  	V4L2_CTRL_TYPE_AV1_FILM_GRAIN	    = 0x283,
> +
> +	V4L2_CTRL_TYPE_AIE_INIT		= 0x0290,
> +	V4L2_CTRL_TYPE_AIE_PARAM	= 0x0291,
>  };
>  
>  /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */


From ck.hu at mediatek.com  Sun Mar  2 18:50:39 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 3 Mar 2025 02:50:39 +0000
Subject: [PATCH v4 1/4] media: dt-bindings: add MT8188 AIE
In-Reply-To: <20250220070114.15015-2-bo.kong@mediatek.com>
References: <20250220070114.15015-1-bo.kong@mediatek.com>
	 <20250220070114.15015-2-bo.kong@mediatek.com>
Message-ID: <0475076e9d3d63a17eee37dc7e21dd6e029f52df.camel@mediatek.com>

On Thu, 2025-02-20 at 14:59 +0800, bo.kong wrote:
> From: Bo Kong <Bo.Kong at mediatek.com>
> 
> Add YAML device tree bindings for MT8188 AIE.
> 
> Signed-off-by: Bo Kong <Bo.Kong at mediatek.com>
> ---
> Changes in v4:
> 1. Remove address-cells and size-cells
> 2. Remove larb12 related content
> 3. Update id content
> 
> Changes in v3:
> None
> 
> Changes in v2:
> 1. Fix coding style
> ---
>  .../bindings/media/mediatek,mt8188-aie.yaml   | 90 +++++++++++++++++++
>  1 file changed, 90 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/mediatek,mt8188-aie.yaml
> 
> diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8188-aie.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8188-aie.yaml
> new file mode 100644
> index 000000000000..232b5afc2ad3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/mediatek,mt8188-aie.yaml
> @@ -0,0 +1,90 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/media/mediatek,mt8188-aie.yaml*__;Iw!!CTRNKA9wMg0ARbw!h_rGFkJMs1ZZbkcF6LQKevQAKnpW0IqNISMCq4sOSTcI7pJLTlEJkzrVd1x1gxq64Sncm_083_FeYusb$ 
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!h_rGFkJMs1ZZbkcF6LQKevQAKnpW0IqNISMCq4sOSTcI7pJLTlEJkzrVd1x1gxq64Sncm_083-s5lmoq$ 
> +
> +title: The AI Engine Unit of MediaTek Camera System
> +
> +maintainers:
> +  - Bo Kong <bo.kong at mediatek.com>
> +
> +description:
> +  AIE(AI Engine) is one of the units in mt8188 ISP which
> +  provides hardware accelerated face detection function,
> +  it can detect different sizes of faces in a raw image.
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: mediatek,mt8188-aie
> +
> +  reg:
> +    maxItems: 1
> +    description: Physical base address and length of the register space.
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  mediatek,larb:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      Must contain the local arbiters in the current SoCs, see
> +      Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
> +      for details.

You already remove mediatek,larb in example device node, so remove this also.

Regards,
CK

> +
> +  iommus:
> +    maxItems: 4
> +    description:
> +      Points to the respective IOMMU block with master port as argument, see
> +      Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml for details.
> +      Ports are according to the HW.
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: clock for imgsys main ipe
> +      - description: clock for ipe fdvt
> +      - description: clock for ipe top
> +
> +  clock-names:
> +    items:
> +      - const: img_ipe
> +      - const: ipe_fdvt
> +      - const: ipe_top
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - iommus
> +  - power-domains
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/memory/mediatek,mt8188-memory-port.h>
> +    #include <dt-bindings/power/mediatek,mt8188-power.h>
> +    #include <dt-bindings/clock/mediatek,mt8188-clk.h>
> +    aie at 15310000 {
> +      compatible = "mediatek,mt8188-aie";
> +      reg = <0x15310000 0x1000>;
> +      interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH 0>;
> +      iommus = <&vpp_iommu M4U_PORT_L12_FDVT_RDA_0>,
> +               <&vpp_iommu M4U_PORT_L12_FDVT_RDB_0>,
> +               <&vpp_iommu M4U_PORT_L12_FDVT_WRA_0>,
> +               <&vpp_iommu M4U_PORT_L12_FDVT_WRB_0>;
> +      power-domains = <&spm MT8188_POWER_DOMAIN_IPE>;
> +      clocks = <&imgsys CLK_IMGSYS_MAIN_IPE>,
> +               <&ipesys CLK_IPE_FDVT>,
> +               <&ipesys CLK_IPESYS_TOP>;
> +      clock-names = "img_ipe",
> +                    "ipe_fdvt",
> +                    "ipe_top";
> +    };


From peng.fan at oss.nxp.com  Sun Mar  2 18:53:25 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:25 +0800
Subject: [PATCH v3 4/7] firmware: arm_scmi: imx: Add i.MX95 CPU Protocol
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-4-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

This protocol allows an agent to start, stop a CPU or set reset vector. It
is used to manage auxiliary CPUs in an LM (e.g. additional cores in an AP
cluster).

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/firmware/arm_scmi/vendors/imx/Kconfig      |  11 +
 drivers/firmware/arm_scmi/vendors/imx/Makefile     |   1 +
 drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c | 276 +++++++++++++++++++++
 include/linux/scmi_imx_protocol.h                  |  10 +
 4 files changed, 298 insertions(+)

diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
index 1a936fc87d2350e2a21bccd45dfbeebfa3b90286..b5f13d0e40155e485f4d1696e9550645d888ef44 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
+++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
@@ -12,6 +12,17 @@ config IMX_SCMI_BBM_EXT
 	  To compile this driver as a module, choose M here: the
 	  module will be called imx-sm-bbm.
 
+config IMX_SCMI_CPU_EXT
+	tristate "i.MX SCMI CPU EXTENSION"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y if ARCH_MXC
+	help
+	  This enables i.MX System CPU Protocol to manage cpu
+	  start, stop and etc.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called imx-sm-cpu.
+
 config IMX_SCMI_LMM_EXT
 	tristate "i.MX SCMI LMM EXTENSION"
 	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
diff --git a/drivers/firmware/arm_scmi/vendors/imx/Makefile b/drivers/firmware/arm_scmi/vendors/imx/Makefile
index f39a99ccaf9af757475e8b112d224669444d7ddc..e3a5ea46345c89da1afae25e55698044672b7c28 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Makefile
+++ b/drivers/firmware/arm_scmi/vendors/imx/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o
+obj-$(CONFIG_IMX_SCMI_CPU_EXT) += imx-sm-cpu.o
 obj-$(CONFIG_IMX_SCMI_LMM_EXT) += imx-sm-lmm.o
 obj-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c
new file mode 100644
index 0000000000000000000000000000000000000000..7fa9a89d825396de00ae666f525e8d6a2d2aed18
--- /dev/null
+++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * System control and Management Interface (SCMI) NXP CPU Protocol
+ *
+ * Copyright 2025 NXP
+ */
+
+#include <linux/bits.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/scmi_imx_protocol.h>
+
+#include "../../protocols.h"
+#include "../../notify.h"
+
+#define SCMI_PROTOCOL_SUPPORTED_VERSION		0x10000
+
+enum scmi_imx_cpu_protocol_cmd {
+	SCMI_IMX_CPU_ATTRIBUTES	= 0x3,
+	SCMI_IMX_CPU_START = 0x4,
+	SCMI_IMX_CPU_STOP = 0x5,
+	SCMI_IMX_CPU_RESET_VECTOR_SET = 0x6,
+	SCMI_IMX_CPU_INFO_GET = 0xC,
+};
+
+struct scmi_imx_cpu_info {
+	u32 nr_cpu;
+};
+
+#define SCMI_IMX_CPU_NR_CPU_MASK	GENMASK(15, 0)
+struct scmi_msg_imx_cpu_protocol_attributes {
+	__le32 attributes;
+};
+
+struct scmi_msg_imx_cpu_attributes_out {
+	__le32 attributes;
+#define	CPU_MAX_NAME	16
+	u8 name[CPU_MAX_NAME];
+};
+
+struct scmi_imx_cpu_reset_vector_set_in {
+	__le32 cpuid;
+#define	CPU_VEC_FLAGS_RESUME	BIT(31)
+#define	CPU_VEC_FLAGS_START	BIT(30)
+#define	CPU_VEC_FLAGS_BOOT	BIT(29)
+	__le32 flags;
+	__le32 resetvectorlow;
+	__le32 resetvectorhigh;
+};
+
+struct scmi_imx_cpu_info_get_out {
+#define	CPU_RUN_MODE_START	0
+#define	CPU_RUN_MODE_HOLD	1
+#define	CPU_RUN_MODE_STOP	2
+#define	CPU_RUN_MODE_SLEEP	3
+	__le32 runmode;
+	__le32 sleepmode;
+	__le32 resetvectorlow;
+	__le32 resetvectorhigh;
+};
+
+static int scmi_imx_cpu_validate_cpuid(const struct scmi_protocol_handle *ph,
+				       u32 cpuid)
+{
+	struct scmi_imx_cpu_info *info = ph->get_priv(ph);
+
+	if (cpuid >= info->nr_cpu)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int scmi_imx_cpu_start(const struct scmi_protocol_handle *ph,
+			      u32 cpuid, bool start)
+{
+	struct scmi_xfer *t;
+	u8 msg_id;
+	int ret;
+
+	ret = scmi_imx_cpu_validate_cpuid(ph, cpuid);
+	if (ret)
+		return ret;
+
+	if (start)
+		msg_id = SCMI_IMX_CPU_START;
+	else
+		msg_id = SCMI_IMX_CPU_STOP;
+
+	ret = ph->xops->xfer_get_init(ph, msg_id, sizeof(u32), 0, &t);
+	if (ret)
+		return ret;
+
+	put_unaligned_le32(cpuid, t->tx.buf);
+	ret = ph->xops->do_xfer(ph, t);
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_cpu_reset_vector_set(const struct scmi_protocol_handle *ph,
+					 u32 cpuid, u64 vector, bool start,
+					 bool boot, bool resume)
+{
+	struct scmi_imx_cpu_reset_vector_set_in *in;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = scmi_imx_cpu_validate_cpuid(ph, cpuid);
+	if (ret)
+		return ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_RESET_VECTOR_SET, sizeof(*in),
+				      0, &t);
+	if (ret)
+		return ret;
+
+	in = t->tx.buf;
+	in->cpuid = cpu_to_le32(cpuid);
+	in->flags = cpu_to_le32(0);
+	if (start)
+		in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_START);
+	if (boot)
+		in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_BOOT);
+	if (resume)
+		in->flags |= le32_encode_bits(1, CPU_VEC_FLAGS_RESUME);
+	in->resetvectorlow = cpu_to_le32(lower_32_bits(vector));
+	in->resetvectorhigh = cpu_to_le32(upper_32_bits(vector));
+	ret = ph->xops->do_xfer(ph, t);
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_cpu_started(const struct scmi_protocol_handle *ph, u32 cpuid,
+				bool *started)
+{
+	struct scmi_imx_cpu_info_get_out *out;
+	struct scmi_xfer *t;
+	u32 mode;
+	int ret;
+
+	if (!started)
+		return -EINVAL;
+
+	*started = false;
+	ret = scmi_imx_cpu_validate_cpuid(ph, cpuid);
+	if (ret)
+		return ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_INFO_GET, sizeof(u32),
+				      0, &t);
+	if (ret)
+		return ret;
+
+	put_unaligned_le32(cpuid, t->tx.buf);
+	ret = ph->xops->do_xfer(ph, t);
+	if (!ret) {
+		out = t->rx.buf;
+		mode = le32_to_cpu(out->runmode);
+		if ((mode == CPU_RUN_MODE_START) || (mode == CPU_RUN_MODE_SLEEP))
+			*started = true;
+	}
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static const struct scmi_imx_cpu_proto_ops scmi_imx_cpu_proto_ops = {
+	.cpu_reset_vector_set = scmi_imx_cpu_reset_vector_set,
+	.cpu_start = scmi_imx_cpu_start,
+	.cpu_started = scmi_imx_cpu_started,
+};
+
+static int scmi_imx_cpu_protocol_attributes_get(const struct scmi_protocol_handle *ph,
+						struct scmi_imx_cpu_info *info)
+{
+	struct scmi_msg_imx_cpu_protocol_attributes *attr;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
+				      sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = ph->xops->do_xfer(ph, t);
+	if (!ret) {
+		info->nr_cpu = le32_get_bits(attr->attributes, SCMI_IMX_CPU_NR_CPU_MASK);
+		dev_info(ph->dev, "i.MX SM CPU: %d cpus\n",
+			 info->nr_cpu);
+	}
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_cpu_attributes_get(const struct scmi_protocol_handle *ph,
+				       u32 cpuid)
+{
+	struct scmi_msg_imx_cpu_attributes_out *out;
+	char name[SCMI_SHORT_NAME_MAX_SIZE] = {'\0'};
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_CPU_ATTRIBUTES, sizeof(u32), 0, &t);
+	if (ret)
+		return ret;
+
+	put_unaligned_le32(cpuid, t->tx.buf);
+	ret = ph->xops->do_xfer(ph, t);
+	if (!ret) {
+		out = t->rx.buf;
+		strscpy(name, out->name, SCMI_SHORT_NAME_MAX_SIZE);
+		dev_info(ph->dev, "i.MX CPU: name: %s\n", name);
+	} else {
+		dev_err(ph->dev, "i.MX cpu: Failed to get info of cpu(%u)\n", cpuid);
+	}
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_cpu_protocol_init(const struct scmi_protocol_handle *ph)
+{
+	struct scmi_imx_cpu_info *info;
+	u32 version;
+	int ret, i;
+
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
+
+	dev_info(ph->dev, "NXP SM CPU Protocol Version %d.%d\n",
+		 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	info = devm_kzalloc(ph->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	ret = scmi_imx_cpu_protocol_attributes_get(ph, info);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < info->nr_cpu; i++) {
+		ret = scmi_imx_cpu_attributes_get(ph, i);
+		if (ret)
+			return ret;
+	}
+
+	return ph->set_priv(ph, info, version);
+}
+
+static const struct scmi_protocol scmi_imx_cpu = {
+	.id = SCMI_PROTOCOL_IMX_CPU,
+	.owner = THIS_MODULE,
+	.instance_init = &scmi_imx_cpu_protocol_init,
+	.ops = &scmi_imx_cpu_proto_ops,
+	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
+	.vendor_id = SCMI_IMX_VENDOR,
+	.sub_vendor_id = SCMI_IMX_SUBVENDOR,
+};
+module_scmi_protocol(scmi_imx_cpu);
+
+MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_CPU) "-" SCMI_IMX_VENDOR);
+MODULE_DESCRIPTION("i.MX SCMI CPU driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/scmi_imx_protocol.h b/include/linux/scmi_imx_protocol.h
index 2a96fc29cb6f4dd1e4c29e0aaaa614ae9783da4a..27bd372cbfb142b6acb0b1cf4b82f061529d0d45 100644
--- a/include/linux/scmi_imx_protocol.h
+++ b/include/linux/scmi_imx_protocol.h
@@ -16,6 +16,7 @@
 
 #define SCMI_PROTOCOL_IMX_LMM	0x80
 #define	SCMI_PROTOCOL_IMX_BBM	0x81
+#define SCMI_PROTOCOL_IMX_CPU	0x82
 #define	SCMI_PROTOCOL_IMX_MISC	0x84
 
 #define SCMI_IMX_VENDOR		"NXP"
@@ -89,4 +90,13 @@ struct scmi_imx_lmm_proto_ops {
 			    u32 flags);
 };
 
+struct scmi_imx_cpu_proto_ops {
+	int (*cpu_reset_vector_set)(const struct scmi_protocol_handle *ph,
+				    u32 cpuid, u64 vector, bool start,
+				    bool boot, bool resume);
+	int (*cpu_start)(const struct scmi_protocol_handle *ph, u32 cpuid,
+			 bool start);
+	int (*cpu_started)(const struct scmi_protocol_handle *ph, u32 cpuid,
+			   bool *started);
+};
 #endif

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:28 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:28 +0800
Subject: [PATCH v3 7/7] MAINTAINERS: add entry for i.MX SCMI extensions
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-7-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

Add entry for i.MX SCMI extensions and myself as maintainer

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index bd15d86a3ad7f832e189451a2ebdbed1e5d46c96..23cac57ee9dffcfaa729f736457359841766106d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23169,6 +23169,15 @@ F:	include/linux/sc[mp]i_protocol.h
 F:	include/trace/events/scmi.h
 F:	include/uapi/linux/virtio_scmi.h
 
+SYSTEM CONTROL MANAGEMENT INTERFACE (SCMI) i.MX Extension Message Protocol drivers
+M:	Peng Fan <peng.fan at nxp.com>
+L:	arm-scmi at vger.kernel.org
+L:	imx at lists.linux.dev
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/firmware/nxp,*scmi.yaml
+F:	drivers/firmware/arm_scmi/vendors/imx/
+
 SYSTEM RESET/SHUTDOWN DRIVERS
 M:	Sebastian Reichel <sre at kernel.org>
 L:	linux-pm at vger.kernel.org

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:21 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:21 +0800
Subject: [PATCH v3 0/7] firmware: scmi/imx: Add i.MX95 LMM/CPU Protocol
Message-ID: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>

i.MX95 System Manager(SM) implements Logical Machine Management(LMM) and
CPU protocol to manage Logical Machine(LM) and CPUs(eg, M7).

To manage M7 in a separate LM or in same LM as Linux itself. LMM APIs
and CPU APIs are needed.

When M7 is in LM 'lm-m7', and this LM is managable by 'linux-lm',
linux could use LMM_BOOT, LMM_SHUTDOWN and etc to manage 'lm-m7'.

If in same LM, use CPU_START, CPU_STOP, CPU_RESET_VECTOR_SET and etc to
manage M7.

Both LMM/CPU APIs will be used by remoteproc driver. The remoteproc
patchset will be posted out after this patchset gets reviewed or in
good shape per Maitainer's view.

Build pass with COMPILE_TEST
Tested with remoteproc on i.MX95

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
Changes in v3:
Patch 1: Correct LMM_ATTRIBUTE return values
        Update the return status of LM_BOOT/RESET/SHUTDOWN/WAKE
        clarify sync/async in the Introduction chapter of LMM
        Update the Origin entry in LMM_RESET_REASON
        Clarify CPU run/sleep mode
        Add note for CPU protocol to indicate AP using PSCI, non-AP use OS.
        Specify mandatory for each command in LMM/CPU per firmware owner.
        For BBM/MISC which have optional command, I will update doc in separate patch later
Patch 2: Add description in binding doc
Patch 3: Unify scmi_imx_lmm_[boot,power_on], Use le32_get_bits
Patch 4: Unify scmi_imx_cpu_[start,stop], Use le32_encode_bits
	 Add pointer check in scmi_imx_cpu_started
	 correct nr_cpus calculation
Patch 5: Unify lmm shutdown,boot/power_on, update kconfig to avoid build bot issue
         Add R-b
Patch 6: Unity cpu start/stop, update Kconfig to avoid build bot issue.
         Add R-b

Ran smatch as below, no issue found.
~/smatch/smatch_scripts/kchecker drivers/firmware/arm_scmi/vendors/imx/
~/smatch/smatch_scripts/kchecker drivers/firmware/imx/

- Link to v2: https://lore.kernel.org/r/20250212-imx-lmm-cpu-v2-0-3aee005968c1 at nxp.com

Changes in v2:
- Add dt-bindings patch 2
- Add a maintainer entry with patch 7
- Update doc to address various questions and make it clear
- Use strscpy to use scmi server returned string
- Drop extra blank line
- Shrink scmi_imx_cpu_attributes_get function args.
- Typo fixes
- Add LMM_RESET_VECTOR_SET
- Link to v1: https://lore.kernel.org/r/20250121-imx-lmm-cpu-v1-0-0eab7e073e4e at nxp.com

---
Peng Fan (7):
      firmware: arm_scmi: imx: Add LMM and CPU documentation
      dt-bindings: firmware: Add i.MX95 SCMI LMM and CPU protocol
      firmware: arm_scmi: imx: Add i.MX95 LMM protocol
      firmware: arm_scmi: imx: Add i.MX95 CPU Protocol
      firmware: imx: Add i.MX95 SCMI LMM driver
      firmware: imx: Add i.MX95 SCMI CPU driver
      MAINTAINERS: add entry for i.MX SCMI extensions

 .../bindings/firmware/nxp,imx95-scmi.yaml          |  23 +
 MAINTAINERS                                        |   9 +
 drivers/firmware/arm_scmi/vendors/imx/Kconfig      |  24 +
 drivers/firmware/arm_scmi/vendors/imx/Makefile     |   2 +
 drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c | 276 +++++++
 drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c | 257 +++++++
 drivers/firmware/arm_scmi/vendors/imx/imx95.rst    | 801 +++++++++++++++++++++
 drivers/firmware/imx/Kconfig                       |  22 +
 drivers/firmware/imx/Makefile                      |   2 +
 drivers/firmware/imx/sm-cpu.c                      |  85 +++
 drivers/firmware/imx/sm-lmm.c                      |  91 +++
 include/linux/firmware/imx/sm.h                    |  19 +
 include/linux/scmi_imx_protocol.h                  |  42 ++
 13 files changed, 1653 insertions(+)
---
base-commit: fb2b3e3bd74b8a3f742eaade06f6565323cf4bdf
change-id: 20250120-imx-lmm-cpu-418daaa257e2

Best regards,
-- 
Peng Fan <peng.fan at nxp.com>



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:22 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:22 +0800
Subject: [PATCH v3 1/7] firmware: arm_scmi: imx: Add LMM and CPU
 documentation
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-1-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

Add i.MX95 Logical Machine Management and CPU Protocol documentation.

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/firmware/arm_scmi/vendors/imx/imx95.rst | 801 ++++++++++++++++++++++++
 1 file changed, 801 insertions(+)

diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx95.rst b/drivers/firmware/arm_scmi/vendors/imx/imx95.rst
index b2dfd6c46ca2f5f12f0475c24cb54c060e9fa421..74326bf2ea8586282a735713e0ab7eb90ccce8ff 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/imx95.rst
+++ b/drivers/firmware/arm_scmi/vendors/imx/imx95.rst
@@ -32,6 +32,501 @@ port, and deploy the SM on supported processors.
 The SM implements an interface compliant with the Arm SCMI Specification
 with additional vendor specific extensions.
 
+SCMI_LMM: System Control and Management Logical Machine Management Vendor Protocol
+==================================================================================
+
+This protocol is intended for boot, shutdown, and reset of other logical
+machines (LM). It is usually used to allow one LM(e.g. OSPM) to manage
+another LM which is usually an offload or accelerator engine.. Notifications
+from this protocol can also be used to manage a communication link to another
+LM. The LMM protocol provides functions to:
+
+- Describe the protocol version.
+- Discover implementation attributes.
+- Discover the LMs defined in the system.
+- Boot an LM.
+- Shutdown an LM (gracefully or forcibly).
+- Reset an LM (gracefully or forcibly).
+- Wake an LM from suspend.
+- Suspend an LM (gracefully).
+- Read boot/shutdown/reset information for an LM.
+- Get notifications when an LM boots or shuts down (e.g. LM[X] requested
+  notification of LM[Y] boots or shuts down, when LM[Y] boots or shuts down,
+  SCMI firmware will send notification to LM[X]).
+
+'Graceful' means asking LM itself to shutdown/reset/etc (e.g. sending
+notification to Linux, Then Linux reboots or powers down itself). It is async
+command that the SUCCESS of the command just means the command successfully
+return, not means reboot/reset successfully finished.
+'Forceful' means the SM will force shutdown/reset/etc the LM. It is sync
+command that the SUCCESS of the command means the LM has been successfully
+shutdown/reset/etc.
+If the commands not have Graceful/Forceful flag settings, such as WAKE, SUSEND,
+it is async command.
+
+Commands:
+_________
+
+PROTOCOL_VERSION
+~~~~~~~~~~~~~~~~
+
+message_id: 0x0
+protocol_id: 0x80
+This command is mandatory.
+
++---------------+--------------------------------------------------------------+
+|Return values                                                                 |
++---------------+--------------------------------------------------------------+
+|Name           |Description                                                   |
++---------------+--------------------------------------------------------------+
+|int32 status   | See ARM SCMI Specification for status code definitions.      |
++---------------+--------------------------------------------------------------+
+|uint32 version | For this revision of the specification, this value must be   |
+|               | 0x10000.                                                     |
++---------------+--------------------------------------------------------------+
+
+PROTOCOL_ATTRIBUTES
+~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x1
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      | See ARM SCMI Specification for status code definitions.   |
++------------------+-----------------------------------------------------------+
+|uint32 attributes |Protocol attributes:                                       |
+|                  |Bits[31:8] Reserved, must be zero.                         |
+|                  |Bits[7:0] Number of Logical Machines                       |
++------------------+-----------------------------------------------------------+
+
+PROTOCOL_MESSAGE_ATTRIBUTES
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x2
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: in case the message is implemented and available  |
+|                  |to use.                                                    |
+|                  |NOT_FOUND: if the message identified by message_id is      |
+|                  |invalid or not implemented                                 |
++------------------+-----------------------------------------------------------+
+|uint32 attributes |Flags that are associated with a specific function in the  |
+|                  |protocol. For all functions in this protocol, this         |
+|                  |parameter has a value of 0                                 |
++------------------+-----------------------------------------------------------+
+
+LMM_ATTRIBUTES
+~~~~~~~~~~~~~~
+
+message_id: 0x3
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if valid attributes are returned.                 |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |DENIED: if the agent does not have permission to get info  |
+|                  |for the LM specified by lmid.                              |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |Identifier of the LM whose identification is requested.    |
+|                  |This field is: Populated with the lmId of the calling      |
+|                  |agent, when the lmId parameter passed via the function is  |
+|                  |0xFFFFFFFF. Identical to the lmId field passed via the     |
+|                  |calling parameters, in all other cases                     |
++------------------+-----------------------------------------------------------+
+|uint32 attributes | Bits[31:0] reserved. must be zero                         |
++------------------+-----------------------------------------------------------+
+|uint32 state      | Current state of the LM                                   |
++------------------+-----------------------------------------------------------+
+|uint32 errStatus  | Last error status recorded                                |
++------------------+-----------------------------------------------------------+
+|char name[16]     | A NULL terminated ASCII string with the LM name, of up    |
+|                  | to 16 bytes                                               |
++------------------+-----------------------------------------------------------+
+
+LMM_BOOT
+~~~~~~~~
+
+message_id: 0x4
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if LM boots successfully started.                 |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_RESET
+~~~~~~~~~
+
+message_id: 0x5
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|uint32 flags      |Reset flags:                                               |
+|                  |Bits[31:1] Reserved, must be zero.                         |
+|                  |Bit[0] Graceful request:                                   |
+|                  |Set to 1 if the request is a graceful request.             |
+|                  |Set to 0 if the request is a forceful request.             |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: The LMM RESET command finished successfully in    |
+|                  |graceful reset or LM successfully resets in forceful reset.|
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_SHUTDOWN
+~~~~~~~~~~~~
+
+message_id: 0x6
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|uint32 flags      |Reset flags:                                               |
+|                  |Bits[31:1] Reserved, must be zero.                         |
+|                  |Bit[0] Graceful request:                                   |
+|                  |Set to 1 if the request is a graceful request.             |
+|                  |Set to 0 if the request is a forceful request.             |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: The LMM shutdown command finished successfully in |
+|                  |graceful request or LM successfully shutdown in forceful   |
+|                  |request.                                                   |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_WAKE
+~~~~~~~~
+
+message_id: 0x7
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if LM wake command successfully returns.          |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_SUSPEND
+~~~~~~~~~~~
+
+message_id: 0x8
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if LM suspend command successfully returns.       |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_NOTIFY
+~~~~~~~~~~
+
+message_id: 0x9
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|uint32 flags      |Notification flags:                                        |
+|                  |Bits[31:3] Reserved, must be zero.                         |
+|                  |Bit[3] Wake (resume) notification:                         |
+|                  |Set to 1 to send notification.                             |
+|                  |Set to 0 if no notification.                               |
+|                  |Bit[2] Suspend (sleep) notification:                       |
+|                  |Set to 1 to send notification.                             |
+|                  |Set to 0 if no notification.                               |
+|                  |Bit[1] Shutdown (off) notification:                        |
+|                  |Set to 1 to send notification.                             |
+|                  |Set to 0 if no notification.                               |
+|                  |Bit[0] Boot (on) notification:                             |
+|                  |Set to 1 to send notification.                             |
+|                  |Set to 0 if no notification                                |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if the notification state successfully updated.   |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if input attributes flag specifies     |
+|                  |unsupported or invalid configurations.                     |
+|                  |DENIED: if the agent does not have permission to request   |
+|                  |the notification.                                          |
++------------------+-----------------------------------------------------------+
+
+LMM_RESET_REASON
+~~~~~~~~~~~~~~~~
+
+message_id: 0xA
+protocol_id: 0x80
+This command is mandatory.
+
+This command is to return the reset reason that caused the last reset, such as
+POR, WDOG, JTAG and etc.
+
++---------------------+--------------------------------------------------------+
+|Parameters                                                                    |
++---------------------+--------------------------------------------------------+
+|Name                 |Description                                             |
++---------------------+--------------------------------------------------------+
+|uint32 lmid          |ID of the Logical Machine                               |
++---------------------+--------------------------------------------------------+
+|Return values                                                                 |
++---------------------+--------------------------------------------------------+
+|Name                 |Description                                             |
++---------------------+--------------------------------------------------------+
+|int32 status         |SUCCESS: if the reset reason of the LM successfully     |
+|                     |updated.                                                |
+|                     |NOT_FOUND: if lmId not points to a valid logical machine|
+|                     |DENIED: if the agent does not have permission to request|
+|                     |the reset reason.                                       |
++---------------------+--------------------------------------------------------+
+|uint32 bootflags     |Boot reason flags. This parameter has the format:       |
+|                     |Bits[31] Valid.                                         |
+|                     |Set to 1 if the entire reason is valid.                 |
+|                     |Set to 0 if the entire reason is not valid.             |
+|                     |Bits[30:29] Reserved, must be zero.                     |
+|                     |Bit[28] Valid origin:                                   |
+|                     |Set to 1 if the origin field is valid.                  |
+|                     |Set to 0 if the origin field is not valid.              |
+|                     |Bits[27:24] Origin.                                     |
+|                     |Logical Machine(LM) ID that causes the BOOT of this LM  |
+|                     |Bit[23] Valid err ID:                                   |
+|                     |Set to 1 if the error ID field is valid.                |
+|                     |Set to 0 if the error ID field is not valid.            |
+|                     |Bits[22:8] Error ID(Agent ID of the system).            |
+|                     |Bit[7:0] Reason(WDOG, POR, FCCU and etc)                |
++---------------------+--------------------------------------------------------+
+|uint32 shutdownflags |Shutdown reason flags. This parameter has the format:   |
+|                     |Bits[31] Valid.                                         |
+|                     |Set to 1 if the entire reason is valid.                 |
+|                     |Set to 0 if the entire reason is not valid.             |
+|                     |Bits[30:29] Number of valid extended info words.        |
+|                     |Bit[28] Valid origin:                                   |
+|                     |Set to 1 if the origin field is valid.                  |
+|                     |Set to 0 if the origin field is not valid.              |
+|                     |Bits[27:24] Origin.                                     |
+|                     |Logical Machine(LM) ID that causes the BOOT of this LM  |
+|                     |Bit[23] Valid err ID:                                   |
+|                     |Set to 1 if the error ID field is valid.                |
+|                     |Set to 0 if the error ID field is not valid.            |
+|                     |Bits[22:8] Error ID(Agent ID of the System).            |
+|                     |Bit[7:0] Reason                                         |
++---------------------+--------------------------------------------------------+
+|uint32 extinfo[3]    |Array of extended info words(e.g. fault pc)             |
++---------------------+--------------------------------------------------------+
+
+LMM_POWER_ON
+~~~~~~~~~~~~
+
+message_id: 0xB
+protocol_id: 0x80
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |ID of the Logical Machine                                  |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if LM successfully powers on.                     |
+|                  |NOT_FOUND: if lmId not points to a valid logical machine.  |
+|                  |INVALID_PARAMETERS: if lmId is same as the caller.         |
+|                  |DENIED: if the agent does not have permission to manage the|
+|                  |the LM specified by lmid.                                  |
++------------------+-----------------------------------------------------------+
+
+LMM_RESET_VECTOR_SET
+~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0xC
+protocol_id: 0x80
+This command is mandatory.
+
++-----------------------+------------------------------------------------------+
+|Parameters                                                                    |
++-----------------------+------------------------------------------------------+
+|Name                   |Description                                           |
++-----------------------+------------------------------------------------------+
+|uint32 lmid            |ID of the Logical Machine                             |
++-----------------------+------------------------------------------------------+
+|uint32 cpuid           |ID of the CPU inside the LM                           |
++-----------------------+------------------------------------------------------+
+|uint32 flags           |Reset vector flags                                    |
+|                       |Bits[31:0] Reserved, must be zero.                    |
++-----------------------+------------------------------------------------------+
+|uint32 resetVectorLow  |Lower vector                                          |
++-----------------------+------------------------------------------------------+
+|uint32 resetVectorHigh |Higher vector                                         |
++-----------------------+------------------------------------------------------+
+|Return values                                                                 |
++-----------------------+------------------------------------------------------+
+|Name                   |Description                                           |
++-----------------------+------------------------------------------------------+
+|int32 status           |SUCCESS: If reset vector is set successfully.         |
+|                       |NOT_FOUND: if lmId not points to a valid logical      |
+|                       |machine, or cpuId is not valid.                       |
+|                       |INVALID_PARAMETERS: if reset vector is invalid.       |
+|                       |DENIED: if the agent does not have permission to set  |
+|                       |the reset vector for the CPU in the LM.               |
++-----------------------+------------------------------------------------------+
+
+NEGOTIATE_PROTOCOL_VERSION
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x10
+protocol_id: 0x80
+This command is mandatory.
+
++--------------------+---------------------------------------------------------+
+|Parameters                                                                    |
++--------------------+---------------------------------------------------------+
+|Name                |Description                                              |
++--------------------+---------------------------------------------------------+
+|uint32 version      |The negotiated protocol version the agent intends to use |
++--------------------+---------------------------------------------------------+
+|Return values                                                                 |
++--------------------+---------------------------------------------------------+
+|Name                |Description                                              |
++--------------------+---------------------------------------------------------+
+|int32 status        |SUCCESS: if the negotiated protocol version is supported |
+|                    |by the platform. All commands, responses, and            |
+|                    |notifications post successful return of this command must|
+|                    |comply with the negotiated version.                      |
+|                    |NOT_SUPPORTED: if the protocol version is not supported. |
++--------------------+---------------------------------------------------------+
+
+Notifications
+_____________
+
+LMM_EVENT
+~~~~~~~~~
+
+message_id: 0x0
+protocol_id: 0x80
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 lmid       |Identifier for the LM that caused the transition.          |
++------------------+-----------------------------------------------------------+
+|uint32 eventlm    |Identifier of the LM this event refers to.                 |
++------------------+-----------------------------------------------------------+
+|uint32 flags      |LM events:                                                 |
+|                  |Bits[31:3] Reserved, must be zero.                         |
+|                  |Bit[3] Wake (resume) event:                                |
+|                  |1 LM has awakened.                                         |
+|                  |0 not a wake event.                                        |
+|                  |Bit[2] Suspend (sleep) event:                              |
+|                  |1 LM has suspended.                                        |
+|                  |0 not a suspend event.                                     |
+|                  |Bit[1] Shutdown (off) event:                               |
+|                  |1 LM has shutdown.                                         |
+|                  |0 not a shutdown event.                                    |
+|                  |Bit[0] Boot (on) event:                                    |
+|                  |1 LM has booted.                                           |
+|                  |0 not a boot event.                                        |
++------------------+-----------------------------------------------------------+
+
 SCMI_BBM: System Control and Management BBM Vendor Protocol
 ==============================================================
 
@@ -436,6 +931,312 @@ protocol_id: 0x81
 |                  |0 no button change detected.                               |
 +------------------+-----------------------------------------------------------+
 
+SCMI_CPU: System Control and Management CPU Vendor Protocol
+==============================================================
+
+This protocol allows an agent to start or stop a CPU. It is used to manage
+auxiliary CPUs in an LM (e.g. additional cores in an AP cluster or
+Cortex-M cores).
+Note:
+ - For cores in AP cluster, PSCI should be used and ATF will use CPU
+   protocol to handle them. For cores in non-AP cluster, Operating System(e.g.
+   Linux OS) could use CPU protocols to control Cortex-M7 cores.
+ - CPU indicates the core and its auxiliary peripherals(e.g. TCM) inside
+   i.MX SoC
+
+The CPU protocol provides functions to:
+
+- Describe the protocol version.
+- Discover implementation attributes.
+- Discover the CPUs defined in the system.
+- Start a CPU.
+- Stop a CPU.
+- Set the boot and resume addresses for a CPU.
+- Set the sleep mode of a CPU.
+- Configure wake-up sources for a CPU.
+- Configure power domain reactions (LPM mode and retention mask) for a CPU.
+- The CPU IDs can be found in the CPU section of the SoC DEVICE: SM Device
+  Interface. They can also be found in the SoC RM. See the CPU Mode Control
+  (CMC) list in General Power Controller (GPC) section.
+
+CPU settings are not aggregated and setting their state is normally exclusive
+to one client.
+
+Commands:
+_________
+
+PROTOCOL_VERSION
+~~~~~~~~~~~~~~~~
+
+message_id: 0x0
+protocol_id: 0x82
+This command is mandatory.
+
++---------------+--------------------------------------------------------------+
+|Return values                                                                 |
++---------------+--------------------------------------------------------------+
+|Name           |Description                                                   |
++---------------+--------------------------------------------------------------+
+|int32 status   | See ARM SCMI Specification for status code definitions.      |
++---------------+--------------------------------------------------------------+
+|uint32 version | For this revision of the specification, this value must be   |
+|               | 0x10000.                                                     |
++---------------+--------------------------------------------------------------+
+
+PROTOCOL_ATTRIBUTES
+~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x1
+protocol_id: 0x82
+This command is mandatory.
+
++---------------+--------------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      | See ARM SCMI Specification for status code definitions.   |
++------------------+-----------------------------------------------------------+
+|uint32 attributes |Protocol attributes:                                       |
+|                  |Bits[31:16] Reserved, must be zero.                        |
+|                  |Bits[15:0] Number of CPUs                                  |
++------------------+-----------------------------------------------------------+
+
+PROTOCOL_MESSAGE_ATTRIBUTES
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x2
+protocol_id: 0x82
+This command is mandatory.
+
++---------------+--------------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: in case the message is implemented and available  |
+|                  |to use.                                                    |
+|                  |NOT_FOUND: if the message identified by message_id is      |
+|                  |invalid or not implemented                                 |
++------------------+-----------------------------------------------------------+
+|uint32 attributes |Flags that are associated with a specific function in the  |
+|                  |protocol. For all functions in this protocol, this         |
+|                  |parameter has a value of 0                                 |
++------------------+-----------------------------------------------------------+
+
+CPU_ATTRIBUTES
+~~~~~~~~~~~~~~
+
+message_id: 0x4
+protocol_id: 0x82
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 cpuid      |Identifier for the CPU                                     |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if valid attributes are returned successfully.    |
+|                  |NOT_FOUND: if the cpuid is not valid.                      |
++------------------+-----------------------------------------------------------+
+|uint32 attributes |Bits[31:0] Reserved, must be zero                          |
++------------------+-----------------------------------------------------------+
+|char name[16]     |NULL terminated ASCII string with CPU name up to 16 bytes  |
++------------------+-----------------------------------------------------------+
+
+CPU_START
+~~~~~~~~~
+
+message_id: 0x4
+protocol_id: 0x82
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 cpuid      |Identifier for the CPU                                     |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if the cpu is started successfully.               |
+|                  |NOT_FOUND: if cpuid is not valid.                          |
+|                  |DENIED: the calling agent is not allowed to start this CPU.|
++------------------+-----------------------------------------------------------+
+
+CPU_STOP
+~~~~~~~~
+
+message_id: 0x5
+protocol_id: 0x82
+This command is mandatory.
+
++------------------+-----------------------------------------------------------+
+|Parameters                                                                    |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|uint32 cpuid      |Identifier for the CPU                                     |
++------------------+-----------------------------------------------------------+
+|Return values                                                                 |
++------------------+-----------------------------------------------------------+
+|Name              |Description                                                |
++------------------+-----------------------------------------------------------+
+|int32 status      |SUCCESS: if the cpu is started successfully.               |
+|                  |NOT_FOUND: if cpuid is not valid.                          |
+|                  |DENIED: the calling agent is not allowed to stop this CPU. |
++------------------+-----------------------------------------------------------+
+
+CPU_RESET_VECTOR_SET
+~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x6
+protocol_id: 0x82
+This command is mandatory.
+
++----------------------+-------------------------------------------------------+
+|Parameters                                                                    |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|uint32 cpuid          |Identifier for the CPU                                 |
++----------------------+-------------------------------------------------------+
+|uint32 flags          |Reset vector flags:                                    |
+|                      |Bit[31] Resume flag.                                   |
+|                      |Set to 1 to update the reset vector used on resume.    |
+|                      |Bit[30] Boot flag.                                     |
+|                      |Set to 1 to update the reset vector used for boot.     |
+|                      |Bits[29:1] Reserved, must be zero.                     |
+|                      |Bit[0] Table flag.                                     |
+|                      |Set to 1 if vector is the vector table base address.   |
++----------------------+-------------------------------------------------------+
+|uint32 resetVectorLow |Lower vector:                                          |
+|                      |If bit[0] of flags is 0, the lower 32 bits of the      |
+|                      |physical address where the CPU should execute from on  |
+|                      |reset. If bit[0] of flags is 1, the lower 32 bits of   |
+|                      |the vector table base address                          |
++----------------------+-------------------------------------------------------+
+|uint32 resetVectorhigh|Upper vector:                                          |
+|                      |If bit[0] of flags is 0, the upper 32 bits of the      |
+|                      |physical address where the CPU should execute from on  |
+|                      |reset. If bit[0] of flags is 1, the upper 32 bits of   |
+|                      |the vector table base address                          |
++----------------------+-------------------------------------------------------+
+|Return values                                                                 |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|int32 status          |SUCCESS: if the CPU reset vector is set successfully.  |
+|                      |NOT_FOUND: if cpuId does not point to a valid CPU.     |
+|                      |INVALID_PARAMETERS: the requested vector type is not   |
+|                      |supported by this CPU.                                 |
+|                      |DENIED: the calling agent is not allowed to set the    |
+|                      |reset vector of this CPU                               |
++----------------------+-------------------------------------------------------+
+
+CPU_SLEEP_MODE_SET
+~~~~~~~~~~~~~~~~~~
+
+message_id: 0x7
+protocol_id: 0x82
+This command is mandatory.
+
++----------------------+-------------------------------------------------------+
+|Parameters                                                                    |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|uint32 cpuid          |Identifier for the CPU                                 |
++----------------------+-------------------------------------------------------+
+|uint32 flags          |Sleep mode flags:                                      |
+|                      |Bits[31:1] Reserved, must be zero.                     |
+|                      |Bit[0] IRQ mux:                                        |
+|                      |If set to 1 the wakeup mux source is the GIC, else if 0|
+|                      |then the GPC                                           |
++----------------------+-------------------------------------------------------+
+|uint32 sleepmode      |target sleep mode. When CPU runs into WFI, the GPC mode|
+|                      |will be triggered to be in below modes:                |
+|                      |RUN(0), WAIT(1), STOP(2), SUSPEND(3)                   |
++----------------------+-------------------------------------------------------+
+|Return values                                                                 |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|int32 status          |SUCCESS: if the CPU sleep mode is set successfully.    |
+|                      |NOT_FOUND: if cpuId does not point to a valid CPU.     |
+|                      |INVALID_PARAMETERS: the sleepmode or flags is invalid. |
+|                      |DENIED: the calling agent is not allowed to configure  |
+|                      |the CPU                                                |
++----------------------+-------------------------------------------------------+
+
+CPU_INFO_GET
+~~~~~~~~~~~~
+
+message_id: 0xC
+protocol_id: 0x82
+This command is mandatory.
+
++----------------------+-------------------------------------------------------+
+|Parameters                                                                    |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|uint32 cpuid          |Identifier for the CPU                                 |
++----------------------+-------------------------------------------------------+
+|Return values                                                                 |
++----------------------+-------------------------------------------------------+
+|Name                  |Description                                            |
++----------------------+-------------------------------------------------------+
+|int32 status          |SUCCESS: if valid attributes are returned successfully.|
+|                      |NOT_FOUND: if the cpuid is not valid.                  |
++----------------------+-------------------------------------------------------+
+|uint32 runmode        |Run mode for the CPU                                   |
+|                      |RUN(0):cpu started                                     |
+|                      |HOLD(1):cpu powered up and reset asserted              |
+|                      |STOP(2):cpu reseted and hold cpu                       |
+|                      |SUSPEND(3):in cpuidle state                            |
++----------------------+-------------------------------------------------------+
+|uint32 sleepmode      |Sleep mode for the CPU, see CPU_SLEEP_MODE_SET         |
++----------------------+-------------------------------------------------------+
+|uint32 resetvectorlow |Reset vector low 32 bits for the CPU                   |
++----------------------+-------------------------------------------------------+
+|uint32 resetvecothigh |Reset vector high 32 bits for the CPU                  |
++----------------------+-------------------------------------------------------+
+
+NEGOTIATE_PROTOCOL_VERSION
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+message_id: 0x10
+protocol_id: 0x82
+This command is mandatory.
+
++--------------------+---------------------------------------------------------+
+|Parameters                                                                    |
++--------------------+---------------------------------------------------------+
+|Name                |Description                                              |
++--------------------+---------------------------------------------------------+
+|uint32 version      |The negotiated protocol version the agent intends to use |
++--------------------+---------------------------------------------------------+
+|Return values                                                                 |
++--------------------+---------------------------------------------------------+
+|Name                |Description                                              |
++--------------------+---------------------------------------------------------+
+|int32 status        |SUCCESS: if the negotiated protocol version is supported |
+|                    |by the platform. All commands, responses, and            |
+|                    |notifications post successful return of this command must|
+|                    |comply with the negotiated version.                      |
+|                    |NOT_SUPPORTED: if the protocol version is not supported. |
++--------------------+---------------------------------------------------------+
+
 SCMI_MISC: System Control and Management MISC Vendor Protocol
 ================================================================
 

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:23 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:23 +0800
Subject: [PATCH v3 2/7] dt-bindings: firmware: Add i.MX95 SCMI LMM and CPU
 protocol
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-2-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

Add i.MX SCMI Extension protocols bindings for:
- Logic Machine Management(LMM) Protocol
  intended for boot, shutdown, and reset of other logical machines (LM).
  It is usually used to allow one LM to manager another used as an offload
  or accelerator engine..
- CPU Protocol.
  allows an agent to start or stop a CPU. It is used to manage auxiliary
  CPUs in an LM (e.g. additional cores in an AP cluster).

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 .../bindings/firmware/nxp,imx95-scmi.yaml          | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/Documentation/devicetree/bindings/firmware/nxp,imx95-scmi.yaml b/Documentation/devicetree/bindings/firmware/nxp,imx95-scmi.yaml
index 1a95010a546b14b1d3d97aa990c0305a551f2620..2bda2e0e13693f12816762137e07dc308d2c49e4 100644
--- a/Documentation/devicetree/bindings/firmware/nxp,imx95-scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/nxp,imx95-scmi.yaml
@@ -11,6 +11,18 @@ maintainers:
   - Peng Fan <peng.fan at nxp.com>
 
 properties:
+  protocol at 80:
+    description:
+      SCMI LMM protocol which is for boot, shutdown, and reset of other logical
+      machines (LM). It is usually used to allow one LM to manage another used
+      as an offload or accelerator engine.
+    $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node'
+    unevaluatedProperties: false
+
+    properties:
+      reg:
+        const: 0x80
+
   protocol at 81:
     $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node'
     unevaluatedProperties: false
@@ -19,6 +31,17 @@ properties:
       reg:
         const: 0x81
 
+  protocol at 82:
+    description:
+      SCMI CPU Protocol which allows an agent to start or stop a CPU. It is
+      used to manage auxiliary CPUs in a LM.
+    $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node'
+    unevaluatedProperties: false
+
+    properties:
+      reg:
+        const: 0x82
+
   protocol at 84:
     $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node'
     unevaluatedProperties: false

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:24 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:24 +0800
Subject: [PATCH v3 3/7] firmware: arm_scmi: imx: Add i.MX95 LMM protocol
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-3-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

Add Logical Machine Management(LMM) protocol which is intended for boot,
shutdown, and reset of other logical machines (LM). It is usually used to
allow one LM to manager another used as an offload or accelerator engine.

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/firmware/arm_scmi/vendors/imx/Kconfig      |  11 +
 drivers/firmware/arm_scmi/vendors/imx/Makefile     |   1 +
 drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c | 257 +++++++++++++++++++++
 include/linux/scmi_imx_protocol.h                  |  32 +++
 4 files changed, 301 insertions(+)

diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
index a01bf5e47301d2f93c9bfc7eebc77e083ea4ed75..1a936fc87d2350e2a21bccd45dfbeebfa3b90286 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
+++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
@@ -12,6 +12,17 @@ config IMX_SCMI_BBM_EXT
 	  To compile this driver as a module, choose M here: the
 	  module will be called imx-sm-bbm.
 
+config IMX_SCMI_LMM_EXT
+	tristate "i.MX SCMI LMM EXTENSION"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y if ARCH_MXC
+	help
+	  This enables i.MX System Logical Machine Protocol to
+	  manage Logical Machines boot, shutdown and etc.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called imx-sm-lmm.
+
 config IMX_SCMI_MISC_EXT
 	tristate "i.MX SCMI MISC EXTENSION"
 	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
diff --git a/drivers/firmware/arm_scmi/vendors/imx/Makefile b/drivers/firmware/arm_scmi/vendors/imx/Makefile
index d3ee6d5449244a4f5cdf6abcf1845f312c512325..f39a99ccaf9af757475e8b112d224669444d7ddc 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Makefile
+++ b/drivers/firmware/arm_scmi/vendors/imx/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o
+obj-$(CONFIG_IMX_SCMI_LMM_EXT) += imx-sm-lmm.o
 obj-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c
new file mode 100644
index 0000000000000000000000000000000000000000..b56a566fb96ee72c025096c025847f4e9d0fefe9
--- /dev/null
+++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * System control and Management Interface (SCMI) NXP LMM Protocol
+ *
+ * Copyright 2025 NXP
+ */
+
+#include <linux/bits.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/scmi_imx_protocol.h>
+
+#include "../../protocols.h"
+#include "../../notify.h"
+
+#define SCMI_PROTOCOL_SUPPORTED_VERSION		0x10000
+
+enum scmi_imx_lmm_protocol_cmd {
+	SCMI_IMX_LMM_ATTRIBUTES	= 0x3,
+	SCMI_IMX_LMM_BOOT = 0x4,
+	SCMI_IMX_LMM_RESET = 0x5,
+	SCMI_IMX_LMM_SHUTDOWN = 0x6,
+	SCMI_IMX_LMM_WAKE = 0x7,
+	SCMI_IMX_LMM_SUSPEND = 0x8,
+	SCMI_IMX_LMM_NOTIFY = 0x9,
+	SCMI_IMX_LMM_RESET_REASON = 0xA,
+	SCMI_IMX_LMM_POWER_ON = 0xB,
+	SCMI_IMX_LMM_RESET_VECTOR_SET = 0xC,
+};
+
+struct scmi_imx_lmm_priv {
+	u32 nr_lmm;
+};
+
+#define SCMI_IMX_LMM_NR_LM_MASK	GENMASK(7, 0)
+struct scmi_msg_imx_lmm_protocol_attributes {
+	__le32 attributes;
+};
+
+struct scmi_msg_imx_lmm_attributes_out {
+	__le32 lmid;
+	__le32 attributes;
+	__le32 state;
+	__le32 errstatus;
+	u8 name[LMM_MAX_NAME];
+};
+
+struct scmi_imx_lmm_reset_vector_set_in {
+	__le32 lmid;
+	__le32 cpuid;
+	__le32 flags; /* reserved for future extension */
+	__le32 resetvectorlow;
+	__le32 resetvectorhigh;
+};
+
+struct scmi_imx_lmm_shutdown_in {
+	__le32 lmid;
+#define SCMI_IMX_LMM_SHUTDOWN_GRACEFUL	BIT(0)
+	__le32 flags;
+};
+
+static int scmi_imx_lmm_validate_lmid(const struct scmi_protocol_handle *ph, u32 lmid)
+{
+	struct scmi_imx_lmm_priv *priv = ph->get_priv(ph);
+
+	if (lmid >= priv->nr_lmm)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int scmi_imx_lmm_attributes(const struct scmi_protocol_handle *ph,
+				   u32 lmid, struct scmi_imx_lmm_info *info)
+{
+	struct scmi_msg_imx_lmm_attributes_out *out;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_ATTRIBUTES, sizeof(u32), 0, &t);
+	if (ret)
+		return ret;
+
+	put_unaligned_le32(lmid, t->tx.buf);
+	ret = ph->xops->do_xfer(ph, t);
+	if (!ret) {
+		out = t->rx.buf;
+		info->lmid = le32_to_cpu(out->lmid);
+		info->state = le32_to_cpu(out->state);
+		info->errstatus = le32_to_cpu(out->errstatus);
+		strscpy(info->name, out->name);
+		dev_dbg(ph->dev, "i.MX LMM: Logical Machine(%d), name: %s\n",
+			info->lmid, out->name);
+	} else {
+		dev_err(ph->dev, "i.MX LMM: Failed to get info of Logical Machine(%u)\n", lmid);
+	}
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int
+scmi_imx_lmm_power_boot(const struct scmi_protocol_handle *ph, u32 lmid, bool boot)
+{
+	struct scmi_xfer *t;
+	u8 msg_id;
+	int ret;
+
+	ret = scmi_imx_lmm_validate_lmid(ph, lmid);
+	if (ret)
+		return ret;
+
+	if (boot)
+		msg_id = SCMI_IMX_LMM_BOOT;
+	else
+		msg_id = SCMI_IMX_LMM_POWER_ON;
+
+	ret = ph->xops->xfer_get_init(ph, msg_id, sizeof(u32), 0, &t);
+	if (ret)
+		return ret;
+
+	put_unaligned_le32(lmid, t->tx.buf);
+	ret = ph->xops->do_xfer(ph, t);
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_lmm_reset_vector_set(const struct scmi_protocol_handle *ph,
+					 u32 lmid, u32 cpuid, u32 flags, u64 vector)
+{
+	struct scmi_imx_lmm_reset_vector_set_in *in;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_RESET_VECTOR_SET, sizeof(*in),
+				      0, &t);
+	if (ret)
+		return ret;
+
+	in = t->tx.buf;
+	in->lmid = cpu_to_le32(lmid);
+	in->cpuid = cpu_to_le32(cpuid);
+	in->flags = cpu_to_le32(0);
+	in->resetvectorlow = cpu_to_le32(lower_32_bits(vector));
+	in->resetvectorhigh = cpu_to_le32(upper_32_bits(vector));
+	ret = ph->xops->do_xfer(ph, t);
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_lmm_shutdown(const struct scmi_protocol_handle *ph, u32 lmid,
+				 u32 flags)
+{
+	struct scmi_imx_lmm_shutdown_in *in;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = scmi_imx_lmm_validate_lmid(ph, lmid);
+	if (ret)
+		return ret;
+
+	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_SHUTDOWN, sizeof(*in),
+				      0, &t);
+	if (ret)
+		return ret;
+
+	in = t->tx.buf;
+	in->lmid = cpu_to_le32(lmid);
+	if (flags & SCMI_IMX_LMM_SHUTDOWN_GRACEFUL)
+		in->flags = cpu_to_le32(SCMI_IMX_LMM_SHUTDOWN_GRACEFUL);
+	else
+		in->flags = cpu_to_le32(0);
+	ret = ph->xops->do_xfer(ph, t);
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static const struct scmi_imx_lmm_proto_ops scmi_imx_lmm_proto_ops = {
+	.lmm_power_boot = scmi_imx_lmm_power_boot,
+	.lmm_info = scmi_imx_lmm_attributes,
+	.lmm_reset_vector_set = scmi_imx_lmm_reset_vector_set,
+	.lmm_shutdown = scmi_imx_lmm_shutdown,
+};
+
+static int scmi_imx_lmm_protocol_attributes_get(const struct scmi_protocol_handle *ph,
+						struct scmi_imx_lmm_priv *priv)
+{
+	struct scmi_msg_imx_lmm_protocol_attributes *attr;
+	struct scmi_xfer *t;
+	int ret;
+
+	ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
+				      sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = ph->xops->do_xfer(ph, t);
+	if (!ret) {
+		priv->nr_lmm = le32_get_bits(attr->attributes, SCMI_IMX_LMM_NR_LM_MASK);
+		dev_info(ph->dev, "i.MX LMM: %d Logical Machines\n",
+			 priv->nr_lmm);
+	}
+
+	ph->xops->xfer_put(ph, t);
+
+	return ret;
+}
+
+static int scmi_imx_lmm_protocol_init(const struct scmi_protocol_handle *ph)
+{
+	struct scmi_imx_lmm_priv *info;
+	u32 version;
+	int ret;
+
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
+
+	dev_info(ph->dev, "NXP SM LMM Version %d.%d\n",
+		 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	info = devm_kzalloc(ph->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	ret = scmi_imx_lmm_protocol_attributes_get(ph, info);
+	if (ret)
+		return ret;
+
+	return ph->set_priv(ph, info, version);
+}
+
+static const struct scmi_protocol scmi_imx_lmm = {
+	.id = SCMI_PROTOCOL_IMX_LMM,
+	.owner = THIS_MODULE,
+	.instance_init = &scmi_imx_lmm_protocol_init,
+	.ops = &scmi_imx_lmm_proto_ops,
+	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
+	.vendor_id = SCMI_IMX_VENDOR,
+	.sub_vendor_id = SCMI_IMX_SUBVENDOR,
+};
+module_scmi_protocol(scmi_imx_lmm);
+
+MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_LMM) "-" SCMI_IMX_VENDOR);
+MODULE_DESCRIPTION("i.MX SCMI LMM driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/scmi_imx_protocol.h b/include/linux/scmi_imx_protocol.h
index 53b356a26414279f4aaaa8287c32209ed1ad57b4..2a96fc29cb6f4dd1e4c29e0aaaa614ae9783da4a 100644
--- a/include/linux/scmi_imx_protocol.h
+++ b/include/linux/scmi_imx_protocol.h
@@ -11,8 +11,10 @@
 #include <linux/bitfield.h>
 #include <linux/device.h>
 #include <linux/notifier.h>
+#include <linux/scmi_protocol.h>
 #include <linux/types.h>
 
+#define SCMI_PROTOCOL_IMX_LMM	0x80
 #define	SCMI_PROTOCOL_IMX_BBM	0x81
 #define	SCMI_PROTOCOL_IMX_MISC	0x84
 
@@ -57,4 +59,34 @@ struct scmi_imx_misc_proto_ops {
 	int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph,
 				    u32 ctrl_id, u32 evt_id, u32 flags);
 };
+
+/* See LMM_ATTRIBUTES in imx95.rst */
+#define	LMM_ID_DISCOVER	0xFFFFFFFFU
+#define	LMM_MAX_NAME	16
+
+enum scmi_imx_lmm_state {
+	LMM_STATE_LM_OFF,
+	LMM_STATE_LM_ON,
+	LMM_STATE_LM_SUSPEND,
+	LMM_STATE_LM_POWERED,
+};
+
+struct scmi_imx_lmm_info {
+	u32 lmid;
+	enum scmi_imx_lmm_state state;
+	u32 errstatus;
+	u8 name[LMM_MAX_NAME];
+};
+
+struct scmi_imx_lmm_proto_ops {
+	int (*lmm_power_boot)(const struct scmi_protocol_handle *ph, u32 lmid,
+			      bool boot);
+	int (*lmm_info)(const struct scmi_protocol_handle *ph, u32 lmid,
+			struct scmi_imx_lmm_info *info);
+	int (*lmm_reset_vector_set)(const struct scmi_protocol_handle *ph,
+				    u32 lmid, u32 cpuid, u32 flags, u64 vector);
+	int (*lmm_shutdown)(const struct scmi_protocol_handle *ph, u32 lmid,
+			    u32 flags);
+};
+
 #endif

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:27 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:27 +0800
Subject: [PATCH v3 6/7] firmware: imx: Add i.MX95 SCMI CPU driver
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-6-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

The i.MX95 System manager exports SCMI CPU protocol for linux to manage
cpu cores. The driver is to use the cpu Protocol interface to
start, stop a cpu cores (eg, M7).

Reviewed-by: Cristian Marussi <cristian.marussi at arm.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/firmware/arm_scmi/vendors/imx/Kconfig |  3 +-
 drivers/firmware/imx/Kconfig                  | 11 ++++
 drivers/firmware/imx/Makefile                 |  1 +
 drivers/firmware/imx/sm-cpu.c                 | 85 +++++++++++++++++++++++++++
 include/linux/firmware/imx/sm.h               |  5 ++
 5 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
index 4c24e17425f830810f8ba376ece9db93c8cded6d..9b4339b93826804599371f2e3a2e79f27449582b 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
+++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
@@ -15,7 +15,8 @@ config IMX_SCMI_BBM_EXT
 config IMX_SCMI_CPU_EXT
 	tristate "i.MX SCMI CPU EXTENSION"
 	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
-	default y if ARCH_MXC
+	depends on IMX_SCMI_CPU_DRV
+	default y if ARCH_MXC && ARM64
 	help
 	  This enables i.MX System CPU Protocol to manage cpu
 	  start, stop and etc.
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index 70c092424328067ea6b946cee59f072661e27e47..8236f81e054ff43c5fbc660a67c53ea9324ab402 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -23,6 +23,17 @@ config IMX_SCU
 	  This driver manages the IPC interface between host CPU and the
 	  SCU firmware running on M4.
 
+config IMX_SCMI_CPU_DRV
+	tristate "IMX SCMI CPU Protocol driver"
+	depends on ARCH_MXC && ARM64 || COMPILE_TEST
+	default y if ARCH_MXC && ARM64
+	help
+	  The System Controller Management Interface firmware (SCMI FW) is
+	  a low-level system function which runs on a dedicated Cortex-M
+	  core that could provide cpu management features.
+
+	  This driver can also be built as a module.
+
 config IMX_SCMI_LMM_DRV
 	tristate "IMX SCMI LMM Protocol driver"
 	depends on ARCH_MXC && ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 7762855d2a771169d4f1867d27e0d51be7c9ad03..3bbaffa6e3478112638ed031375602389f18ef09 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_IMX_DSP)		+= imx-dsp.o
 obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o
+obj-${CONFIG_IMX_SCMI_CPU_DRV}	+= sm-cpu.o
 obj-${CONFIG_IMX_SCMI_MISC_DRV}	+= sm-misc.o
 obj-${CONFIG_IMX_SCMI_LMM_DRV}	+= sm-lmm.o
diff --git a/drivers/firmware/imx/sm-cpu.c b/drivers/firmware/imx/sm-cpu.c
new file mode 100644
index 0000000000000000000000000000000000000000..091b014f739f68d815d71f9b53a2a7eaf0bd607b
--- /dev/null
+++ b/drivers/firmware/imx/sm-cpu.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/firmware/imx/sm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/scmi_imx_protocol.h>
+
+static const struct scmi_imx_cpu_proto_ops *imx_cpu_ops;
+static struct scmi_protocol_handle *ph;
+
+int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, bool boot,
+				  bool resume)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	return imx_cpu_ops->cpu_reset_vector_set(ph, cpuid, vector, start,
+						 boot, resume);
+}
+EXPORT_SYMBOL(scmi_imx_cpu_reset_vector_set);
+
+int scmi_imx_cpu_start(u32 cpuid, bool start)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	if (start)
+		return imx_cpu_ops->cpu_start(ph, cpuid, true);
+
+	return imx_cpu_ops->cpu_start(ph, cpuid, false);
+};
+EXPORT_SYMBOL(scmi_imx_cpu_start);
+
+int scmi_imx_cpu_started(u32 cpuid, bool *started)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	if (!started)
+		return -EINVAL;
+
+	return imx_cpu_ops->cpu_started(ph, cpuid, started);
+};
+EXPORT_SYMBOL(scmi_imx_cpu_started);
+
+static int scmi_imx_cpu_probe(struct scmi_device *sdev)
+{
+	const struct scmi_handle *handle = sdev->handle;
+
+	if (!handle)
+		return -ENODEV;
+
+	if (imx_cpu_ops) {
+		dev_err(&sdev->dev, "sm cpu already initialized\n");
+		return -EEXIST;
+	}
+
+	imx_cpu_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_CPU, &ph);
+	if (IS_ERR(imx_cpu_ops))
+		return PTR_ERR(imx_cpu_ops);
+
+	return 0;
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_IMX_CPU, "imx-cpu" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_imx_cpu_driver = {
+	.name = "scmi-imx-cpu",
+	.probe = scmi_imx_cpu_probe,
+	.id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_imx_cpu_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan at nxp.com>");
+MODULE_DESCRIPTION("IMX SM CPU driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/imx/sm.h b/include/linux/firmware/imx/sm.h
index bc27b04afb2f68b048955f51c07a106f4c7e5852..a8a17eeb7d907ef8ac074c4ed1d3ac83f1104627 100644
--- a/include/linux/firmware/imx/sm.h
+++ b/include/linux/firmware/imx/sm.h
@@ -21,6 +21,11 @@
 int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val);
 int scmi_imx_misc_ctrl_set(u32 id, u32 val);
 
+int scmi_imx_cpu_start(u32 cpuid, bool start);
+int scmi_imx_cpu_started(u32 cpuid, bool *started);
+int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, bool boot,
+				  bool resume);
+
 enum scmi_imx_lmm_op {
 	SCMI_IMX_LMM_BOOT,
 	SCMI_IMX_LMM_POWER_ON,

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 18:53:26 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Mon, 03 Mar 2025 10:53:26 +0800
Subject: [PATCH v3 5/7] firmware: imx: Add i.MX95 SCMI LMM driver
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250303-imx-lmm-cpu-v3-5-7695f6f61cfc@nxp.com>

From: Peng Fan <peng.fan at nxp.com>

The i.MX95 System manager exports SCMI LMM protocol for linux to manage
Logical Machines. The driver is to use the LMM Protocol interface to
boot, shutdown a LM.

Reviewed-by: Cristian Marussi <cristian.marussi at arm.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/firmware/arm_scmi/vendors/imx/Kconfig |  3 +-
 drivers/firmware/imx/Kconfig                  | 11 ++++
 drivers/firmware/imx/Makefile                 |  1 +
 drivers/firmware/imx/sm-lmm.c                 | 91 +++++++++++++++++++++++++++
 include/linux/firmware/imx/sm.h               | 14 +++++
 5 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
index b5f13d0e40155e485f4d1696e9550645d888ef44..4c24e17425f830810f8ba376ece9db93c8cded6d 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
+++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
@@ -26,7 +26,8 @@ config IMX_SCMI_CPU_EXT
 config IMX_SCMI_LMM_EXT
 	tristate "i.MX SCMI LMM EXTENSION"
 	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
-	default y if ARCH_MXC
+	depends on IMX_SCMI_LMM_DRV
+	default y if ARCH_MXC && ARM64
 	help
 	  This enables i.MX System Logical Machine Protocol to
 	  manage Logical Machines boot, shutdown and etc.
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index c964f4924359fcd375560ee8263021b0fe65db1b..70c092424328067ea6b946cee59f072661e27e47 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -23,6 +23,17 @@ config IMX_SCU
 	  This driver manages the IPC interface between host CPU and the
 	  SCU firmware running on M4.
 
+config IMX_SCMI_LMM_DRV
+	tristate "IMX SCMI LMM Protocol driver"
+	depends on ARCH_MXC && ARM64 || COMPILE_TEST
+	default y if ARCH_MXC && ARM64
+	help
+	  The System Controller Management Interface firmware (SCMI FW) is
+	  a low-level system function which runs on a dedicated Cortex-M
+	  core that could provide Logical Machine management features.
+
+	  This driver can also be built as a module.
+
 config IMX_SCMI_MISC_DRV
 	tristate "IMX SCMI MISC Protocol driver"
 	depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 8d046c341be878bb6dd1e6277992ff66ae90e292..7762855d2a771169d4f1867d27e0d51be7c9ad03 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_IMX_DSP)		+= imx-dsp.o
 obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o
 obj-${CONFIG_IMX_SCMI_MISC_DRV}	+= sm-misc.o
+obj-${CONFIG_IMX_SCMI_LMM_DRV}	+= sm-lmm.o
diff --git a/drivers/firmware/imx/sm-lmm.c b/drivers/firmware/imx/sm-lmm.c
new file mode 100644
index 0000000000000000000000000000000000000000..6807bf563c03d21a68022ecf3469c38bee4fc2f5
--- /dev/null
+++ b/drivers/firmware/imx/sm-lmm.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/firmware/imx/sm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/scmi_imx_protocol.h>
+
+static const struct scmi_imx_lmm_proto_ops *imx_lmm_ops;
+static struct scmi_protocol_handle *ph;
+
+int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	if (!info)
+		return -EINVAL;
+
+	return imx_lmm_ops->lmm_info(ph, lmid, info);
+};
+EXPORT_SYMBOL(scmi_imx_lmm_info);
+
+int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	return imx_lmm_ops->lmm_reset_vector_set(ph, lmid, cpuid, flags, vector);
+}
+EXPORT_SYMBOL(scmi_imx_lmm_reset_vector_set);
+
+int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags)
+{
+	if (!ph)
+		return -EPROBE_DEFER;
+
+	switch (op) {
+	case SCMI_IMX_LMM_BOOT:
+		return imx_lmm_ops->lmm_power_boot(ph, lmid, true);
+	case SCMI_IMX_LMM_POWER_ON:
+		return imx_lmm_ops->lmm_power_boot(ph, lmid, false);
+	case SCMI_IMX_LMM_SHUTDOWN:
+		return imx_lmm_ops->lmm_shutdown(ph, lmid, flags);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(scmi_imx_lmm_operation);
+
+static int scmi_imx_lmm_probe(struct scmi_device *sdev)
+{
+	const struct scmi_handle *handle = sdev->handle;
+
+	if (!handle)
+		return -ENODEV;
+
+	if (imx_lmm_ops) {
+		dev_err(&sdev->dev, "lmm already initialized\n");
+		return -EEXIST;
+	}
+
+	imx_lmm_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_LMM, &ph);
+	if (IS_ERR(imx_lmm_ops))
+		return PTR_ERR(imx_lmm_ops);
+
+	return 0;
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_IMX_LMM, "imx-lmm" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_imx_lmm_driver = {
+	.name = "scmi-imx-lmm",
+	.probe = scmi_imx_lmm_probe,
+	.id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_imx_lmm_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan at nxp.com>");
+MODULE_DESCRIPTION("IMX SM LMM driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/imx/sm.h b/include/linux/firmware/imx/sm.h
index 9b85a3f028d1b0a5287b453eb3ad8412a363fe6c..bc27b04afb2f68b048955f51c07a106f4c7e5852 100644
--- a/include/linux/firmware/imx/sm.h
+++ b/include/linux/firmware/imx/sm.h
@@ -8,6 +8,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/errno.h>
+#include <linux/scmi_imx_protocol.h>
 #include <linux/types.h>
 
 #define SCMI_IMX_CTRL_PDM_CLK_SEL	0	/* AON PDM clock sel */
@@ -20,4 +21,17 @@
 int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val);
 int scmi_imx_misc_ctrl_set(u32 id, u32 val);
 
+enum scmi_imx_lmm_op {
+	SCMI_IMX_LMM_BOOT,
+	SCMI_IMX_LMM_POWER_ON,
+	SCMI_IMX_LMM_SHUTDOWN,
+};
+
+/* For shutdown pperation */
+#define SCMI_IMX_LMM_OP_FORCEFUL	0
+#define SCMI_IMX_LMM_OP_GRACEFUL	BIT(0)
+
+int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags);
+int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info);
+int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector);
 #endif

-- 
2.37.1



From peng.fan at oss.nxp.com  Sun Mar  2 20:11:25 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Mon, 3 Mar 2025 12:11:25 +0800
Subject: [PATCH NOT APPLY v2 4/4] clk: scmi: Support spread spectrum
In-Reply-To: <Z6SqeNsAqbZM8nr1@pluto>
References: <20250205-clk-ssc-v2-0-fa73083caa92@nxp.com>
 <20250205-clk-ssc-v2-4-fa73083caa92@nxp.com>
 <Z6SqeNsAqbZM8nr1@pluto>
Message-ID: <20250303041125.GC13236@nxa18884-linux>

Hi Cristian,

On Thu, Feb 06, 2025 at 12:26:32PM +0000, Cristian Marussi wrote:
>On Wed, Feb 05, 2025 at 05:49:54PM +0800, Peng Fan (OSS) wrote:
>> From: Peng Fan <peng.fan at nxp.com>
>> 
>> Support Spread Spectrum with adding scmi_clk_set_spread_spectrum
>> 
>
>Hi,
>
>I forwarded ATG with our latest exchange on the possibility of using a
>standard OEM type instead of Vendor one if it is general enough....

Do you have any update?

Thanks,
Peng

>
>...waiting for their feedback on this before reviewing further...BUT
>just one comment down below
>
>> Signed-off-by: Peng Fan <peng.fan at nxp.com>
>> ---
>>  drivers/clk/clk-scmi.c        | 47 +++++++++++++++++++++++++++++++++++++++++--
>>  include/linux/scmi_protocol.h |  6 ++++++
>>  2 files changed, 51 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
>> index 15510c2ff21c0335f5cb30677343bd4ef59c0738..56b9d0166b0170807c1a83fff391033fecee2159 100644
>> --- a/drivers/clk/clk-scmi.c
>> +++ b/drivers/clk/clk-scmi.c
>> @@ -23,6 +23,7 @@ enum scmi_clk_feats {
>>  	SCMI_CLK_RATE_CTRL_SUPPORTED,
>>  	SCMI_CLK_PARENT_CTRL_SUPPORTED,
>>  	SCMI_CLK_DUTY_CYCLE_SUPPORTED,
>> +	SCMI_CLK_SSC_SUPPORTED,
>>  	SCMI_CLK_FEATS_COUNT
>>  };
>>  
>> @@ -98,6 +99,36 @@ static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
>>  	return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
>>  }
>>  
>> +static int scmi_clk_set_spread_spectrum(struct clk_hw *hw,
>> +					struct clk_spread_spectrum *clk_ss)
>> +{
>> +	struct scmi_clk *clk = to_scmi_clk(hw);
>> +	int ret;
>> +	u32 val;
>> +
>> +	/*
>> +	 * extConfigValue[7:0]   - spread percentage (%)
>> +	 * extConfigValue[23:8]  - Modulation Frequency (KHz)
>> +	 * extConfigValue[24]    - Enable/Disable
>> +	 * extConfigValue[31:25] - Modulation method
>> +	 */
>> +	val = FIELD_PREP(SCMI_CLOCK_EXT_SS_PERCENTAGE_MASK, clk_ss->spreaddepth);
>> +	val |= FIELD_PREP(SCMI_CLOCK_EXT_SS_MOD_FREQ_MASK, clk_ss->modfreq);
>> +	val |= FIELD_PREP(SCMI_CLOCK_EXT_SS_METHOD_MASK, clk_ss->method);
>> +	if (clk_ss->enable)
>> +		val |= SCMI_CLOCK_EXT_SS_ENABLE_MASK;
>> +	ret = scmi_proto_clk_ops->config_oem_set(clk->ph, clk->id,
>> +						 SCMI_CLOCK_CFG_SSC,
>> +						 val, false);
>> +	if (ret)
>> +		dev_warn(clk->dev,
>> +			 "Failed to set spread spectrum(%u,%u,%u) for clock ID %d\n",
>> +			 clk_ss->modfreq, clk_ss->spreaddepth, clk_ss->method,
>> +			 clk->id);
>> +
>> +	return ret;
>> +}
>> +
>>  static u8 scmi_clk_get_parent(struct clk_hw *hw)
>>  {
>>  	struct scmi_clk *clk = to_scmi_clk(hw);
>> @@ -316,9 +347,17 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
>>  		ops->set_duty_cycle = scmi_clk_set_duty_cycle;
>>  	}
>>  
>> +	if (feats_key & BIT(SCMI_CLK_SSC_SUPPORTED))
>> +		ops->set_spread_spectrum = scmi_clk_set_spread_spectrum;
>> +
>>  	return ops;
>>  }
>>  
>> +static const char * const scmi_clk_imxlist[] = {
>> +	"fsl,imx95",
>> +	NULL
>> +};
>> +
>>  /**
>>   * scmi_clk_ops_select() - Select a proper set of clock operations
>>   * @sclk: A reference to an SCMI clock descriptor
>> @@ -370,8 +409,12 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
>>  	if (!ci->parent_ctrl_forbidden)
>>  		feats_key |= BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED);
>>  
>> -	if (ci->extended_config)
>> -		feats_key |= BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED);
>> +	if (ci->extended_config) {
>> +		if (of_machine_compatible_match(scmi_clk_imxlist))
>
>... please NOT this also here if we use a standard OEM type :D..if it
>won't be a vendor thing anymore, you should query with CONFIG_GET, OR we
>should think also about adding some way in the spec to query the support
>for extended configs like we do for other clock features...
>
>Thanks,
>Cristian


From peng.fan at oss.nxp.com  Sun Mar  2 20:27:14 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Mon, 3 Mar 2025 12:27:14 +0800
Subject: [RFC] dt-bindings: firmware: scmi: Introduce compatible string
In-Reply-To: <Z8BRFezgiWDtmdd4@pluto>
References: <20250226094456.2351571-1-peng.fan@oss.nxp.com>
 <Z8BRFezgiWDtmdd4@pluto>
Message-ID: <20250303042714.GD13236@nxa18884-linux>

Hi Cristian,
On Thu, Feb 27, 2025 at 11:48:51AM +0000, Cristian Marussi wrote:
>On Wed, Feb 26, 2025 at 05:44:56PM +0800, Peng Fan (OSS) wrote:
>> From: Peng Fan <peng.fan at nxp.com>
>> 
>> Add compatible string for the protocols by adding new nodes
>> The current nodename pattern is "protocol@[0-9a-f]+$", the new node
>
>Hi Peng,
>
>> name will be "scmi-[a-z\-]+$".
>> With compatible string and new nodename, cpufreq and devfreq could be
>> separated into two nodes. And fwdevlink could correctly link suppliers
>> and consumers.
>
>beside the backward compatibility issues that Rob mentioned, the thing
>that worries me most is that, while the current bindings describe the
>SCMI protocols because the protocols are WHAT the platform FW exposes
>(and that is all that is needed by drivers to refer to a protocol and
>its resources)...here you are getting rid of all of this, and moving to
>describe basically the various devices that will use a protocol,
>potentially the same protocol, just to have a distinct fw_node ...
>(...I mean my understanding is that there wont be any protocol nodes
>left when the scmi- variant are present and, once, somehow, we will
>have transitioned into this...right ?)
>
>I haven't really had the time to go through properly your proposed
>solution to understand fully all its possible side-effects and how
>many SCMI features could be destroyed by removing protocol nodes
>descriptor as a whole...but...off the top of my head, as a quick
>example, how you will define a per-protocol dedicated transport
>channel in this new scenario ?

This is an issue for current RFC.

>...because You wont have anymore a protocol descriptor where to fit
>this AND you could have multiple DT nodes describing drivers that use
>that SAME protocol, so using this new nodes to fit the same
>transport-chan descriptors wont be possible either....

The other alternative would be

protocol at abc {
	//
	current property not change.

	// Add two new optional subnodes
	cpufreq {
		compatible = "arm,scmi-cpufreq";
	};
	devfreq {
		compatible = "arm,scmi-devfreq";
	};
};

protocol at abc {
	//
	current property not change.
	//add a new optional compatible
	compatible = "arm,scmi-pinctrl";
};

If compatible exists, the driver could use compatible to match.

>
>IOW, sincerely, I understand you want to resolve the problem with
>fw_devlink (me too), but nuking down everything, while loosing, possibly,
>a number of the existing functionalities of the SCMI stack just to make
>it work with fw_devlink at all cost it does not seem to me an acceptable
>trade-off...
>
>...killing the whole existing protocols descriptors structure seems to
>me a recipe for disaster, also because, it just goes against the very
>essence of the objects that the FW exposes and the bindings can describe:

no. I was trying to bring backwards compatible solution.

If compatible is there, use compatible. If no compatible, still use reg.

>as an example, the SCMI platform server manage and exposes PERF_PROTOCOL
>and its related DOMAINS (all fully discoverable without any bindings),
>so, THAT is what is described in the bindings and referred by SCMI driver
>users: SCMI FW does NOT handle/expose TWO distinct perf devices, like the
>cpufreq/devfreq-device that you are trying to describe...

I understand, fw only provides one interface, but linux use two distinct
drivers. But this depends on how to abstract the interface for OS usage.

The interface supports CPU freq scaling and peripherals freq scaling,
I think it should be ok to add one node for each, as below:
protocol at xx {
	cpufreq {}
	devfreq {}
}

Thanks,
Peng

>
>As Sudeep mentioned, IMHO this seems mostly an *unsolved* implementation
>problem more than an actual issue with the bindings and how we describe
>SCMI resources that we need to refer to..
>
>> With compatible string, and driver updated.
>> - Differnet vendor drivers with same SCMI protocol ID could be built in
>>   without concerning vendor A's driver got probed when using vendor B's
>>   SoC
>
>as said, this is a corner case that is easily solvable with the current
>layout (and I will post a patch soon-ish to addess this...)
>
>> - NXP scmi pinctrl and ARM scmi pinctrl could be both built in, without
>>   concerning arm scmi platform takes nxp scmi pinctrl node as supplier.
>> 
>
>..the only real issue is the general fw_devlink issue as in cpufreq vs
>devfreq...

Not sure iiodev or thermal has same issue or not.

>
>Thanks,
>Cristian


From peng.fan at oss.nxp.com  Sun Mar  2 20:35:51 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Mon, 3 Mar 2025 12:35:51 +0800
Subject: [RFC] dt-bindings: firmware: scmi: Introduce compatible string
In-Reply-To: <CAL_JsqLePri5m_dE989poUV4auasAxFvgAiYuXVuZHqLcOBGMg@mail.gmail.com>
References: <20250226094456.2351571-1-peng.fan@oss.nxp.com>
 <20250226160945.GA2505223-robh@kernel.org>
 <20250227030924.GB11411@nxa18884-linux>
 <CAL_JsqJOqKeDRuASWxCT=EA5LJbONpCX=Re8=XxKUbPToWy2Dg@mail.gmail.com>
 <Z8HCZQQLofaiGtpG@bogus>
 <CAL_JsqLePri5m_dE989poUV4auasAxFvgAiYuXVuZHqLcOBGMg@mail.gmail.com>
Message-ID: <20250303043551.GE13236@nxa18884-linux>

Hi Rob,
On Fri, Feb 28, 2025 at 08:17:03AM -0600, Rob Herring wrote:
>On Fri, Feb 28, 2025 at 8:04?AM Sudeep Holla <sudeep.holla at arm.com> wrote:
>>
>> On Fri, Feb 28, 2025 at 07:34:09AM -0600, Rob Herring wrote:
>> >
>> > - The parent driver creates child devices. The child devices can
>> > either reuse the parent DT node (i.e. set dev.of_node) or just get it
>> > from the parent device if needed.
>> >
>>
>> This is exactly what I was thinking to deal with the issue since this
>> discussion started. I will give this a go. I believe this must solve
>> the issue, but I didn't want to spit it out loud until I tried to hack
>> and check.
>

>The issue with fw_devlink is that it only checks the dependency of the
>parent which won't be enough. When the parent's probe creates the
>child device, that doesn't mean the child has probed. The child driver
>might not be loaded and/or probe is async. I don't think there's
>anyway for the parent probe to wait for child drivers to be probed and

Please forgive if my understanding is wrong.
Based on device tree, there is fwnode link created using fwnode_link_add,
then in device_add, the fw_devlink_link_device will do the device supplier
and consumer link. It is just device level link, not related to child's probe.

So if child device(work as supplier) is created only when a prarent's probe
done, the consumer of the child device will not have link ready and consumer
device's driver will not probe until the child device created and probe done.

Thanks,
Peng

>ready. I think there's similar issues with the DWC3 wrapper and core
>driver split.
>
>Rob


From quic_jiegan at quicinc.com  Sun Mar  2 19:29:23 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:23 +0800
Subject: [PATCH v15 02/10] Coresight: Add trace_id function to retrieving the trace ID
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-3-quic_jiegan@quicinc.com>

Add 'trace_id' function pointer in coresight_ops. It's responsible for retrieving
the device's trace ID.

Co-developed-by: James Clark <james.clark at linaro.org>
Signed-off-by: James Clark <james.clark at linaro.org>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-core.c  | 30 +++++++++++++++++++
 drivers/hwtracing/coresight/coresight-dummy.c | 13 +++++++-
 .../coresight/coresight-etm3x-core.c          |  1 +
 .../coresight/coresight-etm4x-core.c          |  1 +
 drivers/hwtracing/coresight/coresight-stm.c   | 11 +++++++
 drivers/hwtracing/coresight/coresight-tpda.c  | 11 +++++++
 include/linux/coresight.h                     |  5 ++++
 7 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index ab55e10d4b79..32aa07f4f8c1 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -24,6 +24,7 @@
 #include "coresight-etm-perf.h"
 #include "coresight-priv.h"
 #include "coresight-syscfg.h"
+#include "coresight-trace-id.h"
 
 /*
  * Mutex used to lock all sysfs enable and disable actions and loading and
@@ -1557,6 +1558,35 @@ void coresight_remove_driver(struct amba_driver *amba_drv,
 }
 EXPORT_SYMBOL_GPL(coresight_remove_driver);
 
+int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
+			       struct coresight_device *sink)
+{
+	int trace_id;
+	int cpu = source_ops(csdev)->cpu_id(csdev);
+
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		trace_id = coresight_trace_id_get_cpu_id(cpu);
+		break;
+	case CS_MODE_PERF:
+		if (WARN_ON(!sink))
+			return -EINVAL;
+
+		trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
+		break;
+	default:
+		trace_id = -EINVAL;
+		break;
+	}
+
+	if (!IS_VALID_CS_TRACE_ID(trace_id))
+		dev_err(&csdev->dev,
+			"Failed to allocate trace ID on CPU%d\n", cpu);
+
+	return trace_id;
+}
+EXPORT_SYMBOL_GPL(coresight_etm_get_trace_id);
+
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Pratik Patel <pratikp at codeaurora.org>");
 MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier at linaro.org>");
diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
index 9be53be8964b..b5692ba358c1 100644
--- a/drivers/hwtracing/coresight/coresight-dummy.c
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -41,6 +41,16 @@ static void dummy_source_disable(struct coresight_device *csdev,
 	dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
 }
 
+static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
+				 __maybe_unused struct coresight_device *sink)
+{
+	struct dummy_drvdata *drvdata;
+
+	drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return drvdata->traceid;
+}
+
 static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
 				void *data)
 {
@@ -62,7 +72,8 @@ static const struct coresight_ops_source dummy_source_ops = {
 };
 
 static const struct coresight_ops dummy_source_cs_ops = {
-	.source_ops = &dummy_source_ops,
+	.trace_id	= dummy_source_trace_id,
+	.source_ops	= &dummy_source_ops,
 };
 
 static const struct coresight_ops_sink dummy_sink_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index c103f4c70f5d..c1dda4bc4a2f 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -704,6 +704,7 @@ static const struct coresight_ops_source etm_source_ops = {
 };
 
 static const struct coresight_ops etm_cs_ops = {
+	.trace_id	= coresight_etm_get_trace_id,
 	.source_ops	= &etm_source_ops,
 };
 
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2c1a60577728..cfd116b87460 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1067,6 +1067,7 @@ static const struct coresight_ops_source etm4_source_ops = {
 };
 
 static const struct coresight_ops etm4_cs_ops = {
+	.trace_id	= coresight_etm_get_trace_id,
 	.source_ops	= &etm4_source_ops,
 };
 
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index b581a30a1cd9..aca25b5e3be2 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -281,12 +281,23 @@ static void stm_disable(struct coresight_device *csdev,
 	}
 }
 
+static int stm_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
+			__maybe_unused struct coresight_device *sink)
+{
+	struct stm_drvdata *drvdata;
+
+	drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return drvdata->traceid;
+}
+
 static const struct coresight_ops_source stm_source_ops = {
 	.enable		= stm_enable,
 	.disable	= stm_disable,
 };
 
 static const struct coresight_ops stm_cs_ops = {
+	.trace_id	= stm_trace_id,
 	.source_ops	= &stm_source_ops,
 };
 
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index 573da8427428..94c2201fc8d3 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -241,12 +241,23 @@ static void tpda_disable(struct coresight_device *csdev,
 	dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
 }
 
+static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
+			 __maybe_unused struct coresight_device *sink)
+{
+	struct tpda_drvdata *drvdata;
+
+	drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return drvdata->atid;
+}
+
 static const struct coresight_ops_link tpda_link_ops = {
 	.enable		= tpda_enable,
 	.disable	= tpda_disable,
 };
 
 static const struct coresight_ops tpda_cs_ops = {
+	.trace_id	= tpda_trace_id,
 	.link_ops	= &tpda_link_ops,
 };
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index c7cd5886c908..ce9a5e71b261 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -335,6 +335,7 @@ enum cs_mode {
 	CS_MODE_PERF,
 };
 
+#define coresight_ops(csdev)	csdev->ops
 #define source_ops(csdev)	csdev->ops->source_ops
 #define sink_ops(csdev)		csdev->ops->sink_ops
 #define link_ops(csdev)		csdev->ops->link_ops
@@ -421,6 +422,8 @@ struct coresight_ops_panic {
 };
 
 struct coresight_ops {
+	int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
+			struct coresight_device *sink);
 	const struct coresight_ops_sink *sink_ops;
 	const struct coresight_ops_link *link_ops;
 	const struct coresight_ops_source *source_ops;
@@ -709,4 +712,6 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv);
+int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
+			       struct coresight_device *sink);
 #endif		/* _LINUX_COREISGHT_H */
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:24 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:24 +0800
Subject: [PATCH v15 03/10] Coresight: Use coresight_etm_get_trace_id() in traceid_show()
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-4-quic_jiegan@quicinc.com>

From: James Clark <james.clark at linaro.org>

Use the new API, coresight_etm_get_trace_id, to read the traceid of the ETM
device when call traceid_show via sysfs node.

Signed-off-by: James Clark <james.clark at linaro.org>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 3 +--
 drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
index 68c644be9813..b9006451f515 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
@@ -1190,10 +1190,9 @@ static DEVICE_ATTR_RO(cpu);
 static ssize_t traceid_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	int trace_id;
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	int trace_id = coresight_etm_get_trace_id(drvdata->csdev, CS_MODE_SYSFS, NULL);
 
-	trace_id = etm_read_alloc_trace_id(drvdata);
 	if (trace_id < 0)
 		return trace_id;
 
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index c767f8ae4cf1..e5216c0f60da 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -4,6 +4,7 @@
  * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
  */
 
+#include <linux/coresight.h>
 #include <linux/pid_namespace.h>
 #include <linux/pm_runtime.h>
 #include <linux/sysfs.h>
@@ -2402,10 +2403,9 @@ static ssize_t trctraceid_show(struct device *dev,
 			       struct device_attribute *attr,
 			       char *buf)
 {
-	int trace_id;
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	int trace_id = coresight_etm_get_trace_id(drvdata->csdev, CS_MODE_SYSFS, NULL);
 
-	trace_id = etm4_read_alloc_trace_id(drvdata);
 	if (trace_id < 0)
 		return trace_id;
 
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:25 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:25 +0800
Subject: [PATCH v15 04/10] Coresight: Introduce a new struct coresight_path
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-5-quic_jiegan@quicinc.com>

Introduce a new strcuture, 'struct coresight_path', to store the data that
utilized by the devices in the path. The coresight_path will be built/released
by coresight_build_path/coresight_release_path functions.

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-core.c  | 16 +++++-----
 .../hwtracing/coresight/coresight-etm-perf.c  | 30 ++++++++++---------
 .../hwtracing/coresight/coresight-etm-perf.h  |  2 +-
 drivers/hwtracing/coresight/coresight-priv.h  |  6 ++--
 drivers/hwtracing/coresight/coresight-sysfs.c | 12 ++++----
 include/linux/coresight.h                     | 10 +++++++
 6 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 32aa07f4f8c1..ed0e9368324d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -670,7 +670,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
 static int _coresight_build_path(struct coresight_device *csdev,
 				 struct coresight_device *source,
 				 struct coresight_device *sink,
-				 struct list_head *path)
+				 struct coresight_path *path)
 {
 	int i, ret;
 	bool found = false;
@@ -723,25 +723,25 @@ static int _coresight_build_path(struct coresight_device *csdev,
 		return -ENOMEM;
 
 	node->csdev = csdev;
-	list_add(&node->link, path);
+	list_add(&node->link, &path->path_list);
 
 	return 0;
 }
 
-struct list_head *coresight_build_path(struct coresight_device *source,
+struct coresight_path *coresight_build_path(struct coresight_device *source,
 				       struct coresight_device *sink)
 {
-	struct list_head *path;
+	struct coresight_path *path;
 	int rc;
 
 	if (!sink)
 		return ERR_PTR(-EINVAL);
 
-	path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
+	path = kzalloc(sizeof(struct coresight_path), GFP_KERNEL);
 	if (!path)
 		return ERR_PTR(-ENOMEM);
 
-	INIT_LIST_HEAD(path);
+	INIT_LIST_HEAD(&path->path_list);
 
 	rc = _coresight_build_path(source, source, sink, path);
 	if (rc) {
@@ -759,12 +759,12 @@ struct list_head *coresight_build_path(struct coresight_device *source,
  * Go through all the elements of a path and 1) removed it from the list and
  * 2) free the memory allocated for each node.
  */
-void coresight_release_path(struct list_head *path)
+void coresight_release_path(struct coresight_path *path)
 {
 	struct coresight_device *csdev;
 	struct coresight_node *nd, *next;
 
-	list_for_each_entry_safe(nd, next, path, link) {
+	list_for_each_entry_safe(nd, next, &path->path_list, link) {
 		csdev = nd->csdev;
 
 		coresight_drop_device(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index ad6a8f4b70b6..b0426792f08a 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -136,13 +136,13 @@ static const struct attribute_group *etm_pmu_attr_groups[] = {
 	NULL,
 };
 
-static inline struct list_head **
+static inline struct coresight_path **
 etm_event_cpu_path_ptr(struct etm_event_data *data, int cpu)
 {
 	return per_cpu_ptr(data->path, cpu);
 }
 
-static inline struct list_head *
+static inline struct coresight_path *
 etm_event_cpu_path(struct etm_event_data *data, int cpu)
 {
 	return *etm_event_cpu_path_ptr(data, cpu);
@@ -197,6 +197,7 @@ static void free_sink_buffer(struct etm_event_data *event_data)
 	int cpu;
 	cpumask_t *mask = &event_data->mask;
 	struct coresight_device *sink;
+	struct coresight_path *path;
 
 	if (!event_data->snk_config)
 		return;
@@ -205,7 +206,8 @@ static void free_sink_buffer(struct etm_event_data *event_data)
 		return;
 
 	cpu = cpumask_first(mask);
-	sink = coresight_get_sink(etm_event_cpu_path(event_data, cpu));
+	path = etm_event_cpu_path(event_data, cpu);
+	sink = coresight_get_sink(&path->path_list);
 	sink_ops(sink)->free_buffer(event_data->snk_config);
 }
 
@@ -226,11 +228,11 @@ static void free_event_data(struct work_struct *work)
 		cscfg_deactivate_config(event_data->cfg_hash);
 
 	for_each_cpu(cpu, mask) {
-		struct list_head **ppath;
+		struct coresight_path **ppath;
 
 		ppath = etm_event_cpu_path_ptr(event_data, cpu);
 		if (!(IS_ERR_OR_NULL(*ppath))) {
-			struct coresight_device *sink = coresight_get_sink(*ppath);
+			struct coresight_device *sink = coresight_get_sink(&((*ppath)->path_list));
 
 			/*
 			 * Mark perf event as done for trace id allocator, but don't call
@@ -276,7 +278,7 @@ static void *alloc_event_data(int cpu)
 	 * unused memory when dealing with single CPU trace scenarios is small
 	 * compared to the cost of searching through an optimized array.
 	 */
-	event_data->path = alloc_percpu(struct list_head *);
+	event_data->path = alloc_percpu(struct coresight_path *);
 
 	if (!event_data->path) {
 		kfree(event_data);
@@ -352,7 +354,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 	 * CPUs, we can handle it and fail the session.
 	 */
 	for_each_cpu(cpu, mask) {
-		struct list_head *path;
+		struct coresight_path *path;
 		struct coresight_device *csdev;
 
 		csdev = per_cpu(csdev_src, cpu);
@@ -458,7 +460,7 @@ static void etm_event_start(struct perf_event *event, int flags)
 	struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
 	struct perf_output_handle *handle = &ctxt->handle;
 	struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
-	struct list_head *path;
+	struct coresight_path *path;
 	u64 hw_id;
 	u8 trace_id;
 
@@ -494,12 +496,12 @@ static void etm_event_start(struct perf_event *event, int flags)
 
 	path = etm_event_cpu_path(event_data, cpu);
 	/* We need a sink, no need to continue without one */
-	sink = coresight_get_sink(path);
+	sink = coresight_get_sink(&path->path_list);
 	if (WARN_ON_ONCE(!sink))
 		goto fail_end_stop;
 
 	/* Nothing will happen without a path */
-	if (coresight_enable_path(path, CS_MODE_PERF, handle))
+	if (coresight_enable_path(&path->path_list, CS_MODE_PERF, handle))
 		goto fail_end_stop;
 
 	/* Finally enable the tracer */
@@ -534,7 +536,7 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 
 fail_disable_path:
-	coresight_disable_path(path);
+	coresight_disable_path(&path->path_list);
 fail_end_stop:
 	/*
 	 * Check if the handle is still associated with the event,
@@ -558,7 +560,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
 	struct perf_output_handle *handle = &ctxt->handle;
 	struct etm_event_data *event_data;
-	struct list_head *path;
+	struct coresight_path *path;
 
 	/*
 	 * If we still have access to the event_data via handle,
@@ -599,7 +601,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	if (!path)
 		return;
 
-	sink = coresight_get_sink(path);
+	sink = coresight_get_sink(&path->path_list);
 	if (!sink)
 		return;
 
@@ -643,7 +645,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	}
 
 	/* Disabling the path make its elements available to other sessions */
-	coresight_disable_path(path);
+	coresight_disable_path(&path->path_list);
 }
 
 static int etm_event_add(struct perf_event *event, int mode)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
index 744531158d6b..5febbcdb8696 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.h
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
@@ -59,7 +59,7 @@ struct etm_event_data {
 	cpumask_t aux_hwid_done;
 	void *snk_config;
 	u32 cfg_hash;
-	struct list_head * __percpu *path;
+	struct coresight_path * __percpu *path;
 };
 
 int etm_perf_symlink(struct coresight_device *csdev, bool link);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 76403530f33e..27b7dc348d4a 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -139,9 +139,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path);
 struct coresight_device *coresight_get_sink_by_id(u32 id);
 struct coresight_device *
 coresight_find_default_sink(struct coresight_device *csdev);
-struct list_head *coresight_build_path(struct coresight_device *csdev,
-				       struct coresight_device *sink);
-void coresight_release_path(struct list_head *path);
+struct coresight_path *coresight_build_path(struct coresight_device *csdev,
+					    struct coresight_device *sink);
+void coresight_release_path(struct coresight_path *path);
 int coresight_add_sysfs_link(struct coresight_sysfs_link *info);
 void coresight_remove_sysfs_link(struct coresight_sysfs_link *info);
 int coresight_create_conns_sysfs_group(struct coresight_device *csdev);
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index a01c9e54e2ed..cb4c39732d26 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -22,7 +22,7 @@ static DEFINE_IDR(path_idr);
  * When operating Coresight drivers from the sysFS interface, only a single
  * path can exist from a tracer (associated to a CPU) to a sink.
  */
-static DEFINE_PER_CPU(struct list_head *, tracer_path);
+static DEFINE_PER_CPU(struct coresight_path *, tracer_path);
 
 ssize_t coresight_simple_show_pair(struct device *_dev,
 			      struct device_attribute *attr, char *buf)
@@ -167,7 +167,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 {
 	int cpu, ret = 0;
 	struct coresight_device *sink;
-	struct list_head *path;
+	struct coresight_path *path;
 	enum coresight_dev_subtype_source subtype;
 	u32 hash;
 
@@ -209,7 +209,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 		goto out;
 	}
 
-	ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL);
+	ret = coresight_enable_path(&path->path_list, CS_MODE_SYSFS, NULL);
 	if (ret)
 		goto err_path;
 
@@ -251,7 +251,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 	return ret;
 
 err_source:
-	coresight_disable_path(path);
+	coresight_disable_path(&path->path_list);
 
 err_path:
 	coresight_release_path(path);
@@ -262,7 +262,7 @@ EXPORT_SYMBOL_GPL(coresight_enable_sysfs);
 void coresight_disable_sysfs(struct coresight_device *csdev)
 {
 	int cpu, ret;
-	struct list_head *path = NULL;
+	struct coresight_path *path = NULL;
 	u32 hash;
 
 	mutex_lock(&coresight_mutex);
@@ -297,7 +297,7 @@ void coresight_disable_sysfs(struct coresight_device *csdev)
 		break;
 	}
 
-	coresight_disable_path(path);
+	coresight_disable_path(&path->path_list);
 	coresight_release_path(path);
 
 out:
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index ce9a5e71b261..67cf8bdbe5c0 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -329,6 +329,16 @@ static struct coresight_dev_list (var) = {				\
 
 #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
 
+/**
+ * struct coresight_path - data needed by enable/disable path
+ * @path:              path from source to sink.
+ * @trace_id:          trace_id of the whole path.
+ */
+struct coresight_path {
+	struct list_head	path_list;
+	u8			trace_id;
+};
+
 enum cs_mode {
 	CS_MODE_DISABLED,
 	CS_MODE_SYSFS,
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:26 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:26 +0800
Subject: [PATCH v15 05/10] Coresight: Allocate trace ID after building the path
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-6-quic_jiegan@quicinc.com>

The trace_id will be stored in coresight_path instead of being declared
everywhere and allocated after building the path.

Co-developed-by: James Clark <james.clark at linaro.org>
Signed-off-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-core.c  | 44 +++++++++++++++++++
 .../hwtracing/coresight/coresight-etm-perf.c  |  5 +--
 drivers/hwtracing/coresight/coresight-priv.h  |  2 +
 drivers/hwtracing/coresight/coresight-sysfs.c |  4 ++
 4 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index ed0e9368324d..6adc06995d76 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -655,6 +655,50 @@ static void coresight_drop_device(struct coresight_device *csdev)
 	}
 }
 
+/*
+ * coresight device will read their existing or alloc a trace ID, if their trace_id
+ * callback is set.
+ *
+ * Return 0 if the trace_id callback is not set.
+ * Return the result of the trace_id callback if it is set. The return value
+ * will be the trace_id if successful, and an error number if it fails.
+ */
+static int coresight_get_trace_id(struct coresight_device *csdev,
+				  enum cs_mode mode,
+				  struct coresight_device *sink)
+{
+	if (coresight_ops(csdev)->trace_id)
+		return coresight_ops(csdev)->trace_id(csdev, mode, sink);
+
+	return 0;
+}
+
+/*
+ * Call this after creating the path and before enabling it. This leaves
+ * the trace ID set on the path, or it remains 0 if it couldn't be assigned.
+ */
+void coresight_path_assign_trace_id(struct coresight_path *path,
+				    enum cs_mode mode)
+{
+	struct coresight_device *sink = coresight_get_sink(&path->path_list);
+	struct coresight_node *nd;
+	int trace_id;
+
+	list_for_each_entry(nd, &path->path_list, link) {
+		/* Assign a trace ID to the path for the first device that wants to do it */
+		trace_id = coresight_get_trace_id(nd->csdev, mode, sink);
+
+		/*
+		 * 0 in this context is that it didn't want to assign so keep searching.
+		 * Non 0 is either success or fail.
+		*/
+		if (trace_id != 0) {
+			path->trace_id = trace_id;
+			return;
+		}
+	}
+}
+
 /**
  * _coresight_build_path - recursively build a path from a @csdev to a sink.
  * @csdev:	The device to start from.
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index b0426792f08a..134290ab622e 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -319,7 +319,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 {
 	u32 id, cfg_hash;
 	int cpu = event->cpu;
-	int trace_id;
 	cpumask_t *mask;
 	struct coresight_device *sink = NULL;
 	struct coresight_device *user_sink = NULL, *last_sink = NULL;
@@ -409,8 +408,8 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 		}
 
 		/* ensure we can allocate a trace ID for this CPU */
-		trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
-		if (!IS_VALID_CS_TRACE_ID(trace_id)) {
+		coresight_path_assign_trace_id(path, CS_MODE_PERF);
+		if (!IS_VALID_CS_TRACE_ID(path->trace_id)) {
 			cpumask_clear_cpu(cpu, mask);
 			coresight_release_path(path);
 			continue;
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 27b7dc348d4a..2bea35bae0d4 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -152,6 +152,8 @@ int coresight_make_links(struct coresight_device *orig,
 void coresight_remove_links(struct coresight_device *orig,
 			    struct coresight_connection *conn);
 u32 coresight_get_sink_id(struct coresight_device *csdev);
+void coresight_path_assign_trace_id(struct coresight_path *path,
+				   enum cs_mode mode);
 
 #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
 extern int etm_readl_cp14(u32 off, unsigned int *val);
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index cb4c39732d26..d03751bf3d8a 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -209,6 +209,10 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 		goto out;
 	}
 
+	coresight_path_assign_trace_id(path, CS_MODE_SYSFS);
+	if (!IS_VALID_CS_TRACE_ID(path->trace_id))
+		goto err_path;
+
 	ret = coresight_enable_path(&path->path_list, CS_MODE_SYSFS, NULL);
 	if (ret)
 		goto err_path;
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:27 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:27 +0800
Subject: [PATCH v15 06/10] Coresight: Change to read the trace ID from coresight_path
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-7-quic_jiegan@quicinc.com>

The source device can directly read the trace ID from the coresight_path
which result in etm_read_alloc_trace_id and etm4_read_alloc_trace_id being
deleted.

Co-developed-by: James Clark <james.clark at linaro.org>
Signed-off-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-dummy.c |  2 +-
 .../hwtracing/coresight/coresight-etm-perf.c  |  8 +--
 drivers/hwtracing/coresight/coresight-etm.h   |  1 -
 .../coresight/coresight-etm3x-core.c          | 54 +++----------------
 .../coresight/coresight-etm4x-core.c          | 54 +++----------------
 drivers/hwtracing/coresight/coresight-etm4x.h |  1 -
 drivers/hwtracing/coresight/coresight-stm.c   |  2 +-
 drivers/hwtracing/coresight/coresight-sysfs.c |  7 +--
 drivers/hwtracing/coresight/coresight-tpdm.c  |  2 +-
 include/linux/coresight.h                     |  2 +-
 10 files changed, 25 insertions(+), 108 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
index b5692ba358c1..aaa92b5081e3 100644
--- a/drivers/hwtracing/coresight/coresight-dummy.c
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -24,7 +24,7 @@ DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
 
 static int dummy_source_enable(struct coresight_device *csdev,
 			       struct perf_event *event, enum cs_mode mode,
-			       __maybe_unused struct coresight_trace_id_map *id_map)
+			       __maybe_unused struct coresight_path *path)
 {
 	if (!coresight_take_mode(csdev, mode))
 		return -EBUSY;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 134290ab622e..300305d67a1d 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -461,7 +461,6 @@ static void etm_event_start(struct perf_event *event, int flags)
 	struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
 	struct coresight_path *path;
 	u64 hw_id;
-	u8 trace_id;
 
 	if (!csdev)
 		goto fail;
@@ -504,8 +503,7 @@ static void etm_event_start(struct perf_event *event, int flags)
 		goto fail_end_stop;
 
 	/* Finally enable the tracer */
-	if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF,
-				      &sink->perf_sink_id_map))
+	if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF, path))
 		goto fail_disable_path;
 
 	/*
@@ -515,13 +513,11 @@ static void etm_event_start(struct perf_event *event, int flags)
 	if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) {
 		cpumask_set_cpu(cpu, &event_data->aux_hwid_done);
 
-		trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map);
-
 		hw_id = FIELD_PREP(CS_AUX_HW_ID_MAJOR_VERSION_MASK,
 				CS_AUX_HW_ID_MAJOR_VERSION);
 		hw_id |= FIELD_PREP(CS_AUX_HW_ID_MINOR_VERSION_MASK,
 				CS_AUX_HW_ID_MINOR_VERSION);
-		hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, trace_id);
+		hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, path->trace_id);
 		hw_id |= FIELD_PREP(CS_AUX_HW_ID_SINK_ID_MASK, coresight_get_sink_id(sink));
 
 		perf_report_aux_output_id(event, hw_id);
diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index e02c3ea972c9..171f1384f7c0 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -284,6 +284,5 @@ extern const struct attribute_group *coresight_etm_groups[];
 void etm_set_default(struct etm_config *config);
 void etm_config_trace_mode(struct etm_config *config);
 struct etm_config *get_etm_config(struct etm_drvdata *drvdata);
-int etm_read_alloc_trace_id(struct etm_drvdata *drvdata);
 void etm_release_trace_id(struct etm_drvdata *drvdata);
 #endif
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index c1dda4bc4a2f..8927bfaf3af2 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -455,26 +455,6 @@ static int etm_cpu_id(struct coresight_device *csdev)
 	return drvdata->cpu;
 }
 
-int etm_read_alloc_trace_id(struct etm_drvdata *drvdata)
-{
-	int trace_id;
-
-	/*
-	 * This will allocate a trace ID to the cpu,
-	 * or return the one currently allocated.
-	 *
-	 * trace id function has its own lock
-	 */
-	trace_id = coresight_trace_id_get_cpu_id(drvdata->cpu);
-	if (IS_VALID_CS_TRACE_ID(trace_id))
-		drvdata->traceid = (u8)trace_id;
-	else
-		dev_err(&drvdata->csdev->dev,
-			"Failed to allocate trace ID for %s on CPU%d\n",
-			dev_name(&drvdata->csdev->dev), drvdata->cpu);
-	return trace_id;
-}
-
 void etm_release_trace_id(struct etm_drvdata *drvdata)
 {
 	coresight_trace_id_put_cpu_id(drvdata->cpu);
@@ -482,38 +462,22 @@ void etm_release_trace_id(struct etm_drvdata *drvdata)
 
 static int etm_enable_perf(struct coresight_device *csdev,
 			   struct perf_event *event,
-			   struct coresight_trace_id_map *id_map)
+			   struct coresight_path *path)
 {
 	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-	int trace_id;
 
 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return -EINVAL;
 
 	/* Configure the tracer based on the session's specifics */
 	etm_parse_event_config(drvdata, event);
-
-	/*
-	 * perf allocates cpu ids as part of _setup_aux() - device needs to use
-	 * the allocated ID. This reads the current version without allocation.
-	 *
-	 * This does not use the trace id lock to prevent lock_dep issues
-	 * with perf locks - we know the ID cannot change until perf shuts down
-	 * the session
-	 */
-	trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
-	if (!IS_VALID_CS_TRACE_ID(trace_id)) {
-		dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
-			dev_name(&drvdata->csdev->dev), drvdata->cpu);
-		return -EINVAL;
-	}
-	drvdata->traceid = (u8)trace_id;
+	drvdata->traceid = path->trace_id;
 
 	/* And enable it */
 	return etm_enable_hw(drvdata);
 }
 
-static int etm_enable_sysfs(struct coresight_device *csdev)
+static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path)
 {
 	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	struct etm_enable_arg arg = { };
@@ -521,10 +485,7 @@ static int etm_enable_sysfs(struct coresight_device *csdev)
 
 	spin_lock(&drvdata->spinlock);
 
-	/* sysfs needs to allocate and set a trace ID */
-	ret = etm_read_alloc_trace_id(drvdata);
-	if (ret < 0)
-		goto unlock_enable_sysfs;
+	drvdata->traceid = path->trace_id;
 
 	/*
 	 * Configure the ETM only if the CPU is online.  If it isn't online
@@ -545,7 +506,6 @@ static int etm_enable_sysfs(struct coresight_device *csdev)
 	if (ret)
 		etm_release_trace_id(drvdata);
 
-unlock_enable_sysfs:
 	spin_unlock(&drvdata->spinlock);
 
 	if (!ret)
@@ -554,7 +514,7 @@ static int etm_enable_sysfs(struct coresight_device *csdev)
 }
 
 static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
-		      enum cs_mode mode, struct coresight_trace_id_map *id_map)
+		      enum cs_mode mode, struct coresight_path *path)
 {
 	int ret;
 	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -566,10 +526,10 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
 
 	switch (mode) {
 	case CS_MODE_SYSFS:
-		ret = etm_enable_sysfs(csdev);
+		ret = etm_enable_sysfs(csdev, path);
 		break;
 	case CS_MODE_PERF:
-		ret = etm_enable_perf(csdev, event, id_map);
+		ret = etm_enable_perf(csdev, event, path);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index cfd116b87460..1ed957f5df61 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -233,25 +233,6 @@ static int etm4_cpu_id(struct coresight_device *csdev)
 	return drvdata->cpu;
 }
 
-int etm4_read_alloc_trace_id(struct etmv4_drvdata *drvdata)
-{
-	int trace_id;
-
-	/*
-	 * This will allocate a trace ID to the cpu,
-	 * or return the one currently allocated.
-	 * The trace id function has its own lock
-	 */
-	trace_id = coresight_trace_id_get_cpu_id(drvdata->cpu);
-	if (IS_VALID_CS_TRACE_ID(trace_id))
-		drvdata->trcid = (u8)trace_id;
-	else
-		dev_err(&drvdata->csdev->dev,
-			"Failed to allocate trace ID for %s on CPU%d\n",
-			dev_name(&drvdata->csdev->dev), drvdata->cpu);
-	return trace_id;
-}
-
 void etm4_release_trace_id(struct etmv4_drvdata *drvdata)
 {
 	coresight_trace_id_put_cpu_id(drvdata->cpu);
@@ -788,9 +769,9 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 
 static int etm4_enable_perf(struct coresight_device *csdev,
 			    struct perf_event *event,
-			    struct coresight_trace_id_map *id_map)
+			    struct coresight_path *path)
 {
-	int ret = 0, trace_id;
+	int ret = 0;
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) {
@@ -803,22 +784,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
 	if (ret)
 		goto out;
 
-	/*
-	 * perf allocates cpu ids as part of _setup_aux() - device needs to use
-	 * the allocated ID. This reads the current version without allocation.
-	 *
-	 * This does not use the trace id lock to prevent lock_dep issues
-	 * with perf locks - we know the ID cannot change until perf shuts down
-	 * the session
-	 */
-	trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
-	if (!IS_VALID_CS_TRACE_ID(trace_id)) {
-		dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
-			dev_name(&drvdata->csdev->dev), drvdata->cpu);
-		ret = -EINVAL;
-		goto out;
-	}
-	drvdata->trcid = (u8)trace_id;
+	drvdata->trcid = path->trace_id;
 
 	/* And enable it */
 	ret = etm4_enable_hw(drvdata);
@@ -827,7 +793,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
 	return ret;
 }
 
-static int etm4_enable_sysfs(struct coresight_device *csdev)
+static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path)
 {
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	struct etm4_enable_arg arg = { };
@@ -844,10 +810,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
 
 	spin_lock(&drvdata->spinlock);
 
-	/* sysfs needs to read and allocate a trace ID */
-	ret = etm4_read_alloc_trace_id(drvdata);
-	if (ret < 0)
-		goto unlock_sysfs_enable;
+	drvdata->trcid = path->trace_id;
 
 	/*
 	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
@@ -864,7 +827,6 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
 	if (ret)
 		etm4_release_trace_id(drvdata);
 
-unlock_sysfs_enable:
 	spin_unlock(&drvdata->spinlock);
 
 	if (!ret)
@@ -873,7 +835,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
 }
 
 static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
-		       enum cs_mode mode, struct coresight_trace_id_map *id_map)
+		       enum cs_mode mode, struct coresight_path *path)
 {
 	int ret;
 
@@ -884,10 +846,10 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
 
 	switch (mode) {
 	case CS_MODE_SYSFS:
-		ret = etm4_enable_sysfs(csdev);
+		ret = etm4_enable_sysfs(csdev, path);
 		break;
 	case CS_MODE_PERF:
-		ret = etm4_enable_perf(csdev, event, id_map);
+		ret = etm4_enable_perf(csdev, event, path);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 1119762b5cec..2b92de17b5a2 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -1066,6 +1066,5 @@ static inline bool etm4x_is_ete(struct etmv4_drvdata *drvdata)
 	return drvdata->arch >= ETM_ARCH_ETE;
 }
 
-int etm4_read_alloc_trace_id(struct etmv4_drvdata *drvdata);
 void etm4_release_trace_id(struct etmv4_drvdata *drvdata);
 #endif
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index aca25b5e3be2..26f9339f38b9 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -195,7 +195,7 @@ static void stm_enable_hw(struct stm_drvdata *drvdata)
 
 static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
 		      enum cs_mode mode,
-		      __maybe_unused struct coresight_trace_id_map *trace_id)
+		      __maybe_unused struct coresight_path *path)
 {
 	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index d03751bf3d8a..3ac5b52413a6 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -53,7 +53,8 @@ ssize_t coresight_simple_show32(struct device *_dev,
 EXPORT_SYMBOL_GPL(coresight_simple_show32);
 
 static int coresight_enable_source_sysfs(struct coresight_device *csdev,
-					 enum cs_mode mode, void *data)
+					 enum cs_mode mode,
+					 struct coresight_path *path)
 {
 	int ret;
 
@@ -64,7 +65,7 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev,
 	 */
 	lockdep_assert_held(&coresight_mutex);
 	if (coresight_get_mode(csdev) != CS_MODE_SYSFS) {
-		ret = source_ops(csdev)->enable(csdev, data, mode, NULL);
+		ret = source_ops(csdev)->enable(csdev, NULL, mode, path);
 		if (ret)
 			return ret;
 	}
@@ -217,7 +218,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 	if (ret)
 		goto err_path;
 
-	ret = coresight_enable_source_sysfs(csdev, CS_MODE_SYSFS, NULL);
+	ret = coresight_enable_source_sysfs(csdev, CS_MODE_SYSFS, path);
 	if (ret)
 		goto err_source;
 
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index afc4c18dd35d..e5f472e406bb 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -440,7 +440,7 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
 
 static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
 		       enum cs_mode mode,
-		       __maybe_unused struct coresight_trace_id_map *id_map)
+		       __maybe_unused struct coresight_path *path)
 {
 	struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 67cf8bdbe5c0..c7b17672df50 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -401,7 +401,7 @@ struct coresight_ops_link {
 struct coresight_ops_source {
 	int (*cpu_id)(struct coresight_device *csdev);
 	int (*enable)(struct coresight_device *csdev, struct perf_event *event,
-		      enum cs_mode mode, struct coresight_trace_id_map *id_map);
+		      enum cs_mode mode, struct coresight_path *path);
 	void (*disable)(struct coresight_device *csdev,
 			struct perf_event *event);
 };
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:28 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:28 +0800
Subject: [PATCH v15 07/10] Coresight: Change functions to accept the coresight_path
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-8-quic_jiegan@quicinc.com>

Modify following functions to accept the coresight_path. Devices in the path
can read data from coresight_path if needed.
 - coresight_enable_path
 - coresight_disable_path
 - coresight_get_source
 - coresight_get_sink
 - coresight_enable_helpers
 - coresight_disable_helpers

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-core.c  | 37 ++++++++++---------
 .../hwtracing/coresight/coresight-etm-perf.c  | 16 ++++----
 drivers/hwtracing/coresight/coresight-priv.h  |  6 +--
 drivers/hwtracing/coresight/coresight-sysfs.c |  6 +--
 4 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 6adc06995d76..630667673136 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -77,14 +77,14 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
 }
 EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
 
-static struct coresight_device *coresight_get_source(struct list_head *path)
+static struct coresight_device *coresight_get_source(struct coresight_path *path)
 {
 	struct coresight_device *csdev;
 
 	if (!path)
 		return NULL;
 
-	csdev = list_first_entry(path, struct coresight_node, link)->csdev;
+	csdev = list_first_entry(&path->path_list, struct coresight_node, link)->csdev;
 	if (!coresight_is_device_source(csdev))
 		return NULL;
 
@@ -333,12 +333,12 @@ static int coresight_enable_helper(struct coresight_device *csdev,
 	return helper_ops(csdev)->enable(csdev, mode, data);
 }
 
-static void coresight_disable_helper(struct coresight_device *csdev)
+static void coresight_disable_helper(struct coresight_device *csdev, void *data)
 {
-	helper_ops(csdev)->disable(csdev, NULL);
+	helper_ops(csdev)->disable(csdev, data);
 }
 
-static void coresight_disable_helpers(struct coresight_device *csdev)
+static void coresight_disable_helpers(struct coresight_device *csdev, void *data)
 {
 	int i;
 	struct coresight_device *helper;
@@ -346,7 +346,7 @@ static void coresight_disable_helpers(struct coresight_device *csdev)
 	for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
 		helper = csdev->pdata->out_conns[i]->dest_dev;
 		if (helper && coresight_is_helper(helper))
-			coresight_disable_helper(helper);
+			coresight_disable_helper(helper, data);
 	}
 }
 
@@ -363,7 +363,7 @@ static void coresight_disable_helpers(struct coresight_device *csdev)
 void coresight_disable_source(struct coresight_device *csdev, void *data)
 {
 	source_ops(csdev)->disable(csdev, data);
-	coresight_disable_helpers(csdev);
+	coresight_disable_helpers(csdev, NULL);
 }
 EXPORT_SYMBOL_GPL(coresight_disable_source);
 
@@ -372,16 +372,16 @@ EXPORT_SYMBOL_GPL(coresight_disable_source);
  * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
  * disabled.
  */
-static void coresight_disable_path_from(struct list_head *path,
+static void coresight_disable_path_from(struct coresight_path *path,
 					struct coresight_node *nd)
 {
 	u32 type;
 	struct coresight_device *csdev, *parent, *child;
 
 	if (!nd)
-		nd = list_first_entry(path, struct coresight_node, link);
+		nd = list_first_entry(&path->path_list, struct coresight_node, link);
 
-	list_for_each_entry_continue(nd, path, link) {
+	list_for_each_entry_continue(nd, &path->path_list, link) {
 		csdev = nd->csdev;
 		type = csdev->type;
 
@@ -419,11 +419,11 @@ static void coresight_disable_path_from(struct list_head *path,
 		}
 
 		/* Disable all helpers adjacent along the path last */
-		coresight_disable_helpers(csdev);
+		coresight_disable_helpers(csdev, path);
 	}
 }
 
-void coresight_disable_path(struct list_head *path)
+void coresight_disable_path(struct coresight_path *path)
 {
 	coresight_disable_path_from(path, NULL);
 }
@@ -448,7 +448,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
 	return 0;
 }
 
-int coresight_enable_path(struct list_head *path, enum cs_mode mode,
+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
 			  void *sink_data)
 {
 	int ret = 0;
@@ -458,12 +458,12 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
 	struct coresight_device *source;
 
 	source = coresight_get_source(path);
-	list_for_each_entry_reverse(nd, path, link) {
+	list_for_each_entry_reverse(nd, &path->path_list, link) {
 		csdev = nd->csdev;
 		type = csdev->type;
 
 		/* Enable all helpers adjacent to the path first */
-		ret = coresight_enable_helpers(csdev, mode, sink_data);
+		ret = coresight_enable_helpers(csdev, mode, path);
 		if (ret)
 			goto err;
 		/*
@@ -511,20 +511,21 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
 	goto out;
 }
 
-struct coresight_device *coresight_get_sink(struct list_head *path)
+struct coresight_device *coresight_get_sink(struct coresight_path *path)
 {
 	struct coresight_device *csdev;
 
 	if (!path)
 		return NULL;
 
-	csdev = list_last_entry(path, struct coresight_node, link)->csdev;
+	csdev = list_last_entry(&path->path_list, struct coresight_node, link)->csdev;
 	if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
 	    csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
 		return NULL;
 
 	return csdev;
 }
+EXPORT_SYMBOL_GPL(coresight_get_sink);
 
 u32 coresight_get_sink_id(struct coresight_device *csdev)
 {
@@ -680,7 +681,7 @@ static int coresight_get_trace_id(struct coresight_device *csdev,
 void coresight_path_assign_trace_id(struct coresight_path *path,
 				    enum cs_mode mode)
 {
-	struct coresight_device *sink = coresight_get_sink(&path->path_list);
+	struct coresight_device *sink = coresight_get_sink(path);
 	struct coresight_node *nd;
 	int trace_id;
 
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 300305d67a1d..f4cccd68e625 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -197,7 +197,6 @@ static void free_sink_buffer(struct etm_event_data *event_data)
 	int cpu;
 	cpumask_t *mask = &event_data->mask;
 	struct coresight_device *sink;
-	struct coresight_path *path;
 
 	if (!event_data->snk_config)
 		return;
@@ -206,8 +205,7 @@ static void free_sink_buffer(struct etm_event_data *event_data)
 		return;
 
 	cpu = cpumask_first(mask);
-	path = etm_event_cpu_path(event_data, cpu);
-	sink = coresight_get_sink(&path->path_list);
+	sink = coresight_get_sink(etm_event_cpu_path(event_data, cpu));
 	sink_ops(sink)->free_buffer(event_data->snk_config);
 }
 
@@ -232,7 +230,7 @@ static void free_event_data(struct work_struct *work)
 
 		ppath = etm_event_cpu_path_ptr(event_data, cpu);
 		if (!(IS_ERR_OR_NULL(*ppath))) {
-			struct coresight_device *sink = coresight_get_sink(&((*ppath)->path_list));
+			struct coresight_device *sink = coresight_get_sink(*ppath);
 
 			/*
 			 * Mark perf event as done for trace id allocator, but don't call
@@ -494,12 +492,12 @@ static void etm_event_start(struct perf_event *event, int flags)
 
 	path = etm_event_cpu_path(event_data, cpu);
 	/* We need a sink, no need to continue without one */
-	sink = coresight_get_sink(&path->path_list);
+	sink = coresight_get_sink(path);
 	if (WARN_ON_ONCE(!sink))
 		goto fail_end_stop;
 
 	/* Nothing will happen without a path */
-	if (coresight_enable_path(&path->path_list, CS_MODE_PERF, handle))
+	if (coresight_enable_path(path, CS_MODE_PERF, handle))
 		goto fail_end_stop;
 
 	/* Finally enable the tracer */
@@ -531,7 +529,7 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 
 fail_disable_path:
-	coresight_disable_path(&path->path_list);
+	coresight_disable_path(path);
 fail_end_stop:
 	/*
 	 * Check if the handle is still associated with the event,
@@ -596,7 +594,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	if (!path)
 		return;
 
-	sink = coresight_get_sink(&path->path_list);
+	sink = coresight_get_sink(path);
 	if (!sink)
 		return;
 
@@ -640,7 +638,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	}
 
 	/* Disabling the path make its elements available to other sessions */
-	coresight_disable_path(&path->path_list);
+	coresight_disable_path(path);
 }
 
 static int etm_event_add(struct perf_event *event, int mode)
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 2bea35bae0d4..82644aff8d2b 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -132,10 +132,10 @@ static inline void CS_UNLOCK(void __iomem *addr)
 	} while (0);
 }
 
-void coresight_disable_path(struct list_head *path);
-int coresight_enable_path(struct list_head *path, enum cs_mode mode,
+void coresight_disable_path(struct coresight_path *path);
+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
 			  void *sink_data);
-struct coresight_device *coresight_get_sink(struct list_head *path);
+struct coresight_device *coresight_get_sink(struct coresight_path *path);
 struct coresight_device *coresight_get_sink_by_id(u32 id);
 struct coresight_device *
 coresight_find_default_sink(struct coresight_device *csdev);
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index 3ac5b52413a6..feadaf065b53 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -214,7 +214,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 	if (!IS_VALID_CS_TRACE_ID(path->trace_id))
 		goto err_path;
 
-	ret = coresight_enable_path(&path->path_list, CS_MODE_SYSFS, NULL);
+	ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL);
 	if (ret)
 		goto err_path;
 
@@ -256,7 +256,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
 	return ret;
 
 err_source:
-	coresight_disable_path(&path->path_list);
+	coresight_disable_path(path);
 
 err_path:
 	coresight_release_path(path);
@@ -302,7 +302,7 @@ void coresight_disable_sysfs(struct coresight_device *csdev)
 		break;
 	}
 
-	coresight_disable_path(&path->path_list);
+	coresight_disable_path(path);
 	coresight_release_path(path);
 
 out:
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:29 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:29 +0800
Subject: [PATCH v15 08/10] dt-bindings: arm: Add Coresight TMC Control Unit hardware
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-9-quic_jiegan@quicinc.com>

Add binding file to specify how to define a Coresight TMC Control Unit device
in device tree.

It is responsible for controlling the data filter function based on the source
device's Trace ID for TMC ETR device. The trace data with that Trace id can get
into ETR's buffer while other trace data gets ignored.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 .../bindings/arm/qcom,coresight-ctcu.yaml     | 84 +++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml

diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
new file mode 100644
index 000000000000..843b52eaf872
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/qcom,coresight-ctcu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CoreSight TMC Control Unit
+
+maintainers:
+  - Yuanfang Zhang <quic_yuanfang at quicinc.com>
+  - Mao Jinlong <quic_jinlmao at quicinc.com>
+  - Jie Gan <quic_jiegan at quicinc.com>
+
+description: |
+  The Trace Memory Controller(TMC) is used for Embedded Trace Buffer(ETB),
+  Embedded Trace FIFO(ETF) and Embedded Trace Router(ETR) configurations.
+  The configuration mode (ETB, ETF, ETR) is discovered at boot time when
+  the device is probed.
+
+  The Coresight TMC Control unit controls various Coresight behaviors.
+  It works as a helper device when connected to TMC ETR device.
+  It is responsible for controlling the data filter function based on
+  the source device's Trace ID for TMC ETR device. The trace data with
+  that Trace id can get into ETR's buffer while other trace data gets
+  ignored.
+
+properties:
+  compatible:
+    enum:
+      - qcom,sa8775p-ctcu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: apb
+
+  in-ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    patternProperties:
+      '^port(@[0-1])?$':
+        description: Input connections from CoreSight Trace bus
+        $ref: /schemas/graph.yaml#/properties/port
+
+required:
+  - compatible
+  - reg
+  - in-ports
+
+additionalProperties: false
+
+examples:
+  - |
+    ctcu at 1001000 {
+        compatible = "qcom,sa8775p-ctcu";
+        reg = <0x1001000 0x1000>;
+
+        clocks = <&aoss_qmp>;
+        clock-names = "apb";
+
+        in-ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port at 0 {
+                reg = <0>;
+                ctcu_in_port0: endpoint {
+                    remote-endpoint = <&etr0_out_port>;
+                };
+            };
+
+            port at 1 {
+                reg = <1>;
+                ctcu_in_port1: endpoint {
+                    remote-endpoint = <&etr1_out_port>;
+                };
+            };
+        };
+    };
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:30 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:30 +0800
Subject: [PATCH v15 09/10] Coresight: Add Coresight TMC Control Unit driver
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-10-quic_jiegan@quicinc.com>

The Coresight TMC Control Unit hosts miscellaneous configuration registers
which control various features related to TMC ETR sink.

Based on the trace ID, which is programmed in the related CTCU ATID
register of a specific ETR, trace data with that trace ID gets into
the ETR buffer, while other trace data gets dropped.

Enabling source device sets one bit of the ATID register based on
source device's trace ID.
Disabling source device resets the bit according to the source
device's trace ID.

Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/Kconfig           |  12 +
 drivers/hwtracing/coresight/Makefile          |   2 +
 .../hwtracing/coresight/coresight-ctcu-core.c | 326 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-ctcu.h  |  39 +++
 include/linux/coresight.h                     |   3 +-
 5 files changed, 381 insertions(+), 1 deletion(-)
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-core.c
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu.h

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 06f0a7594169..ecd7086a5b83 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -133,6 +133,18 @@ config CORESIGHT_STM
 	  To compile this driver as a module, choose M here: the
 	  module will be called coresight-stm.
 
+config CORESIGHT_CTCU
+	tristate "CoreSight TMC Control Unit driver"
+	depends on CORESIGHT_LINK_AND_SINK_TMC
+	help
+	  This driver provides support for CoreSight TMC Control Unit
+	  that hosts miscellaneous configuration registers. This is
+	  primarily used for controlling the behaviors of the TMC
+	  ETR device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called coresight-ctcu.
+
 config CORESIGHT_CPU_DEBUG
 	tristate "CoreSight CPU Debug driver"
 	depends on ARM || ARM64
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 46ce7f39d05f..8e62c3150aeb 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -51,3 +51,5 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
 		   coresight-cti-sysfs.o
 obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
+obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
+coresight-ctcu-y := coresight-ctcu-core.o
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
new file mode 100644
index 000000000000..da35d8b4d579
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include "coresight-ctcu.h"
+#include "coresight-priv.h"
+
+DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
+
+#define ctcu_writel(drvdata, val, offset)	__raw_writel((val), drvdata->base + offset)
+#define ctcu_readl(drvdata, offset)		__raw_readl(drvdata->base + offset)
+
+/*
+ * The TMC Coresight Control Unit utilizes four ATID registers to control the data
+ * filter function based on the trace ID for each TMC ETR sink. The length of each
+ * ATID register is 32 bits. Therefore, an ETR device has a 128-bit long field
+ * in CTCU. Each trace ID is represented by one bit in that filed.
+ * e.g. ETR0ATID0 layout, set bit 5 for traceid 5
+ *                                           bit5
+ * ------------------------------------------------------
+ * |   |28|   |24|   |20|   |16|   |12|   |8|  1|4|   |0|
+ * ------------------------------------------------------
+ *
+ * e.g. ETR0:
+ * 127                     0 from ATID_offset for ETR0ATID0
+ * -------------------------
+ * |ATID3|ATID2|ATID1|ATID0|
+ */
+#define CTCU_ATID_REG_OFFSET(traceid, atid_offset) \
+		((traceid / 32) * 4 + atid_offset)
+
+#define CTCU_ATID_REG_BIT(traceid)	(traceid % 32)
+#define CTCU_ATID_REG_SIZE		0x10
+#define CTCU_ETR0_ATID0			0xf8
+#define CTCU_ETR1_ATID0			0x108
+
+static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
+	{
+		.atid_offset	= CTCU_ETR0_ATID0,
+		.port_num	= 0,
+	},
+	{
+		.atid_offset	= CTCU_ETR1_ATID0,
+		.port_num	= 1,
+	},
+};
+
+static const struct ctcu_config sa8775p_cfgs = {
+	.etr_cfgs	= sa8775p_etr_cfgs,
+	.num_etr_config	= ARRAY_SIZE(sa8775p_etr_cfgs),
+};
+
+static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset,
+				       u8 bit, bool enable)
+{
+	u32 val;
+
+	CS_UNLOCK(drvdata->base);
+	val = ctcu_readl(drvdata, reg_offset);
+	if (enable)
+		val |= BIT(bit);
+	else
+		val &= ~BIT(bit);
+
+	ctcu_writel(drvdata, val, reg_offset);
+	CS_LOCK(drvdata->base);
+}
+
+/*
+ * __ctcu_set_etr_traceid: Set bit in the ATID register based on trace ID when enable is true.
+ * Reset the bit of the ATID register based on trace ID when enable is false.
+ *
+ * @csdev:	coresight_device of CTCU.
+ * @traceid:	trace ID of the source tracer.
+ * @port_num:	port number connected to TMC ETR sink.
+ * @enable:	True for set bit and false for reset bit.
+ *
+ * Returns 0 indicates success. Non-zero result means failure.
+ */
+static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, int port_num,
+				  bool enable)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	u32 atid_offset, reg_offset;
+	u8 refcnt, bit;
+
+	atid_offset = drvdata->atid_offset[port_num];
+	if (atid_offset == 0)
+		return -EINVAL;
+
+	bit = CTCU_ATID_REG_BIT(traceid);
+	reg_offset = CTCU_ATID_REG_OFFSET(traceid, atid_offset);
+	if (reg_offset - atid_offset > CTCU_ATID_REG_SIZE)
+		return -EINVAL;
+
+	guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
+	refcnt = drvdata->traceid_refcnt[port_num][traceid];
+	/* Only program the atid register when the refcnt value is 1 or 0 */
+	if ((enable && !refcnt++) || (!enable && !--refcnt))
+		ctcu_program_atid_register(drvdata, reg_offset, bit, enable);
+
+	drvdata->traceid_refcnt[port_num][traceid] = refcnt;
+
+	return 0;
+}
+
+/*
+ * Searching the sink device from helper's view in case there are multiple helper devices
+ * connected to the sink device.
+ */
+static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
+{
+	struct coresight_platform_data *pdata = helper->pdata;
+	int i;
+
+	for (i = 0; i < pdata->nr_inconns; ++i) {
+		if (pdata->in_conns[i]->src_dev == sink)
+			return pdata->in_conns[i]->dest_port;
+	}
+
+	return -EINVAL;
+}
+
+static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight_path *path,
+				bool enable)
+{
+	struct coresight_device *sink = coresight_get_sink(path);
+	u8 traceid = path->trace_id;
+	int port_num;
+
+	if ((sink == NULL) || !IS_VALID_CS_TRACE_ID(traceid)) {
+		dev_err(&csdev->dev, "Invalid sink device or trace ID\n");
+		return -EINVAL;
+	}
+
+	port_num = ctcu_get_active_port(sink, csdev);
+	if (port_num < 0)
+		return -EINVAL;
+
+	dev_dbg(&csdev->dev, "traceid is %d\n", traceid);
+
+	return __ctcu_set_etr_traceid(csdev, traceid, port_num, enable);
+}
+
+static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
+{
+	struct coresight_path *path = (struct coresight_path *)data;
+
+	return ctcu_set_etr_traceid(csdev, path, true);
+}
+
+static int ctcu_disable(struct coresight_device *csdev, void *data)
+{
+	struct coresight_path *path = (struct coresight_path *)data;
+
+	return ctcu_set_etr_traceid(csdev, path, false);
+}
+
+static const struct coresight_ops_helper ctcu_helper_ops = {
+	.enable = ctcu_enable,
+	.disable = ctcu_disable,
+};
+
+static const struct coresight_ops ctcu_ops = {
+	.helper_ops = &ctcu_helper_ops,
+};
+
+static int ctcu_probe(struct platform_device *pdev)
+{
+	const struct ctcu_etr_config *etr_cfg;
+	struct coresight_platform_data *pdata;
+	struct coresight_desc desc = { 0 };
+	struct device *dev = &pdev->dev;
+	const struct ctcu_config *cfgs;
+	struct ctcu_drvdata *drvdata;
+	void __iomem *base;
+	int i;
+
+	desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
+	if (!desc.name)
+		return -ENOMEM;
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	pdata = coresight_get_platform_data(dev);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+	dev->platform_data = pdata;
+
+	base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+	if (!base)
+		return -ENOMEM;
+
+	drvdata->apb_clk = coresight_get_enable_apb_pclk(dev);
+	if (IS_ERR(drvdata->apb_clk))
+		return -ENODEV;
+
+	cfgs = of_device_get_match_data(dev);
+	if (cfgs) {
+		if (cfgs->num_etr_config <= ETR_MAX_NUM) {
+			for (i = 0; i < cfgs->num_etr_config; i++) {
+				etr_cfg = &cfgs->etr_cfgs[i];
+				drvdata->atid_offset[i] = etr_cfg->atid_offset;
+			}
+		}
+	}
+
+	drvdata->base = base;
+	drvdata->dev = dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	desc.type = CORESIGHT_DEV_TYPE_HELPER;
+	desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU;
+	desc.pdata = pdata;
+	desc.dev = dev;
+	desc.ops = &ctcu_ops;
+	desc.access = CSDEV_ACCESS_IOMEM(base);
+
+	drvdata->csdev = coresight_register(&desc);
+	if (IS_ERR(drvdata->csdev)) {
+		if (!IS_ERR_OR_NULL(drvdata->apb_clk))
+			clk_put(drvdata->apb_clk);
+
+		return PTR_ERR(drvdata->csdev);
+	}
+
+	return 0;
+}
+
+static void ctcu_remove(struct platform_device *pdev)
+{
+	struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+}
+
+static int ctcu_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = ctcu_probe(pdev);
+	pm_runtime_put(&pdev->dev);
+	if (ret)
+		pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static void ctcu_platform_remove(struct platform_device *pdev)
+{
+	struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	if (WARN_ON(!drvdata))
+		return;
+
+	ctcu_remove(pdev);
+	pm_runtime_disable(&pdev->dev);
+	if (!IS_ERR_OR_NULL(drvdata->apb_clk))
+		clk_put(drvdata->apb_clk);
+}
+
+#ifdef CONFIG_PM
+static int ctcu_runtime_suspend(struct device *dev)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR_OR_NULL(drvdata->apb_clk))
+		clk_disable_unprepare(drvdata->apb_clk);
+
+	return 0;
+}
+
+static int ctcu_runtime_resume(struct device *dev)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR_OR_NULL(drvdata->apb_clk))
+		clk_prepare_enable(drvdata->apb_clk);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops ctcu_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(ctcu_runtime_suspend, ctcu_runtime_resume, NULL)
+};
+
+static const struct of_device_id ctcu_match[] = {
+	{.compatible = "qcom,sa8775p-ctcu", .data = &sa8775p_cfgs},
+	{}
+};
+
+static struct platform_driver ctcu_driver = {
+	.probe          = ctcu_platform_probe,
+	.remove         = ctcu_platform_remove,
+	.driver         = {
+		.name   = "coresight-ctcu",
+		.of_match_table = ctcu_match,
+		.pm	= &ctcu_dev_pm_ops,
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(ctcu_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CoreSight TMC Control Unit driver");
diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h
new file mode 100644
index 000000000000..11201e8266ff
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-ctcu.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _CORESIGHT_CTCU_H
+#define _CORESIGHT_CTCU_H
+#include "coresight-trace-id.h"
+
+/* Maximum number of supported ETR devices for a single CTCU. */
+#define ETR_MAX_NUM 	2
+
+/**
+ * struct ctcu_etr_config
+ * @atid_offset:	offset to the ATID0 Register.
+ * @port_num:		in-port number of CTCU device that connected to ETR.
+ */
+struct ctcu_etr_config {
+	const u32 atid_offset;
+	const u32 port_num;
+};
+
+struct ctcu_config {
+	const struct ctcu_etr_config *etr_cfgs;
+	int num_etr_config;
+};
+
+struct ctcu_drvdata {
+	void __iomem		*base;
+	struct clk		*apb_clk;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	raw_spinlock_t		spin_lock;
+	u32			atid_offset[ETR_MAX_NUM];
+	/* refcnt for each traceid of each sink */
+	u8			traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
+};
+
+#endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index c7b17672df50..78b670d71e98 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -71,7 +71,8 @@ enum coresight_dev_subtype_source {
 
 enum coresight_dev_subtype_helper {
 	CORESIGHT_DEV_SUBTYPE_HELPER_CATU,
-	CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI
+	CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI,
+	CORESIGHT_DEV_SUBTYPE_HELPER_CTCU,
 };
 
 /**
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:31 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:31 +0800
Subject: [PATCH v15 10/10] arm64: dts: qcom: sa8775p: Add CTCU and ETR nodes
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-11-quic_jiegan@quicinc.com>

Add CTCU and ETR nodes in DT to enable related functionalities.

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sa8775p.dtsi | 153 ++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 3394ae2d1300..31aa94d2a043 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -2429,6 +2429,35 @@ crypto: crypto at 1dfa000 {
 			interconnect-names = "memory";
 		};
 
+		ctcu at 4001000 {
+			compatible = "qcom,sa8775p-ctcu";
+			reg = <0x0 0x04001000 0x0 0x1000>;
+
+			clocks = <&aoss_qmp>;
+			clock-names = "apb";
+
+			in-ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+
+					ctcu_in0: endpoint {
+						remote-endpoint = <&etr0_out>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+
+					ctcu_in1: endpoint {
+						remote-endpoint = <&etr1_out>;
+					};
+				};
+			};
+		};
+
 		stm: stm at 4002000 {
 			compatible = "arm,coresight-stm", "arm,primecell";
 			reg = <0x0 0x4002000 0x0 0x1000>,
@@ -2633,6 +2662,122 @@ qdss_funnel_in1: endpoint {
 			};
 		};
 
+		replicator at 4046000 {
+			compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+			reg = <0x0 0x04046000 0x0 0x1000>;
+
+			clocks = <&aoss_qmp>;
+			clock-names = "apb_pclk";
+
+			in-ports {
+				port {
+					qdss_rep_in: endpoint {
+						remote-endpoint = <&swao_rep_out0>;
+					};
+				};
+			};
+
+			out-ports {
+				port {
+					qdss_rep_out0: endpoint {
+						remote-endpoint = <&etr_rep_in>;
+					};
+				};
+			};
+		};
+
+		tmc_etr: tmc at 4048000 {
+			compatible = "arm,coresight-tmc", "arm,primecell";
+			reg = <0x0 0x04048000 0x0 0x1000>;
+
+			clocks = <&aoss_qmp>;
+			clock-names = "apb_pclk";
+			iommus = <&apps_smmu 0x04c0 0x00>;
+
+			arm,scatter-gather;
+
+			in-ports {
+				port {
+					etr0_in: endpoint {
+						remote-endpoint = <&etr_rep_out0>;
+					};
+				};
+			};
+
+			out-ports {
+				port {
+					etr0_out: endpoint {
+						remote-endpoint = <&ctcu_in0>;
+					};
+				};
+			};
+		};
+
+		replicator at 404e000 {
+			compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+			reg = <0x0 0x0404e000 0x0 0x1000>;
+
+			clocks = <&aoss_qmp>;
+			clock-names = "apb_pclk";
+
+			in-ports {
+				port {
+					etr_rep_in: endpoint {
+						remote-endpoint = <&qdss_rep_out0>;
+					};
+				};
+			};
+
+			out-ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+
+					etr_rep_out0: endpoint {
+						remote-endpoint = <&etr0_in>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+
+					etr_rep_out1: endpoint {
+						remote-endpoint = <&etr1_in>;
+					};
+				};
+			};
+		};
+
+		tmc_etr1: tmc at 404f000 {
+			compatible = "arm,coresight-tmc", "arm,primecell";
+			reg = <0x0 0x0404f000 0x0 0x1000>;
+
+			clocks = <&aoss_qmp>;
+			clock-names = "apb_pclk";
+			iommus = <&apps_smmu 0x04a0 0x40>;
+
+			arm,scatter-gather;
+			arm,buffer-size = <0x400000>;
+
+			in-ports {
+				port {
+					etr1_in: endpoint {
+						remote-endpoint = <&etr_rep_out1>;
+					};
+				};
+			};
+
+			out-ports {
+				port {
+					etr1_out: endpoint {
+						remote-endpoint = <&ctcu_in1>;
+					};
+				};
+			};
+		};
+
 		funnel at 4b04000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x0 0x4b04000 0x0 0x1000>;
@@ -2708,6 +2853,14 @@ out-ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
 
+				port at 0 {
+					reg = <0>;
+
+					swao_rep_out0: endpoint {
+						remote-endpoint = <&qdss_rep_in>;
+					};
+				};
+
 				port at 1 {
 					reg = <1>;
 					swao_rep_out1: endpoint {
-- 
2.34.1



From gshan at redhat.com  Sun Mar  2 19:42:29 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 13:42:29 +1000
Subject: [PATCH v7 05/45] arm64: RME: Add wrappers for RMI calls
In-Reply-To: <20250213161426.102987-6-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-6-steven.price@arm.com>
Message-ID: <8f08b96b-8219-4d51-8f46-bc367bbf2031@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> The wrappers make the call sites easier to read and deal with the
> boiler plate of handling the error codes from the RMM.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes from v5:
>   * Further improve comments
> Changes from v4:
>   * Improve comments
> Changes from v2:
>   * Make output arguments optional.
>   * Mask RIPAS value rmi_rtt_read_entry()
>   * Drop unused rmi_rtt_get_phys()
> ---
>   arch/arm64/include/asm/rmi_cmds.h | 508 ++++++++++++++++++++++++++++++
>   1 file changed, 508 insertions(+)
>   create mode 100644 arch/arm64/include/asm/rmi_cmds.h
> 

With the following nitpicks addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> new file mode 100644
> index 000000000000..043b7ff278ee
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -0,0 +1,508 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#ifndef __ASM_RMI_CMDS_H
> +#define __ASM_RMI_CMDS_H
> +

[...]

> +
> +/**
> + * rmi_rec_aux_count() - Get number of auxiliary granules required
> + * @rd: PA of the RD
> + * @aux_count: Number of pages written to this pointer
                   ^^^^^^^^^^^^^^^
                   Number of granules
> + *
> + * A REC may require extra auxiliary pages to be delegated for the RMM to
                                         ^^^^^
                                         granules

> + * store metadata (not visible to the normal world) in. This function provides
> + * the number of pages that are required.
                     ^^^^^
                     granules
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rec_aux_count(unsigned long rd, unsigned long *aux_count)
> +{
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_1_1_invoke(SMC_RMI_REC_AUX_COUNT, rd, &res);
> +
> +	if (aux_count)
> +		*aux_count = res.a1;
> +	return res.a0;
> +}
> +
> +/**
> + * rmi_rec_create() - Create a REC
> + * @rd: PA of the RD
> + * @rec: PA of the target REC
> + * @params_ptr: PA of REC parameters
> + *
> + * Create a REC using the parameters specified in the struct rec_params pointed
> + * to by @params_ptr.
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rec_create(unsigned long rd, unsigned long rec,
> +				 unsigned long params_ptr)
> +{
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_1_1_invoke(SMC_RMI_REC_CREATE, rd, rec, params_ptr, &res);
> +
> +	return res.a0;
> +}
> +

'params_ptr' may be renamed to 'params'.


[...]
> +#endif /* __ASM_RMI_CMDS_H */

Thanks,
Gavin



From andyshrk at 163.com  Sun Mar  2 19:44:19 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:19 +0800
Subject: [PATCH v16 5/7] dt-bindings: display: vop2: Add missing rockchip,grf property for rk3566/8
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-6-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The clock polarity of RGB signal output is controlled by GRF, this
property is already being used in the current device tree, but
forgot to describe it as a required property in the binding file.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v13)

Changes in v13:
- typo fix
- Explain the function of this property.

Changes in v12:
- Split from patch 10/13

 .../devicetree/bindings/display/rockchip/rockchip-vop2.yaml   | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
index a5771edd83b5..083eadcf0588 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -146,6 +146,9 @@ allOf:
         rockchip,vop-grf: false
         rockchip,pmu: false
 
+      required:
+        - rockchip,grf
+
   - if:
       properties:
         compatible:
@@ -200,6 +203,7 @@ examples:
                               "dclk_vp1",
                               "dclk_vp2";
                 power-domains = <&power RK3568_PD_VO>;
+                rockchip,grf = <&grf>;
                 iommus = <&vop_mmu>;
                 vop_out: ports {
                     #address-cells = <1>;
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:15 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:15 +0800
Subject: [PATCH v16 1/7] drm/rockchip: vop2: Register the primary plane and overlay plane separately
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-2-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

In the upcoming VOP of rk3576, a Window cannot attach to all Video Ports,
so make sure all VP find it's suitable primary plane, then register the
remain windows as overlay plane will make code easier.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
Tested-by: Detlev Casanova <detlev.casanova at collabora.com>

---

Changes in v16:
- Rebase on drm-misc-next
- Switch to dev_err_probe

Changes in v3:
- Add comments for why we should treat rk3566 with special care.

 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 99 ++++++++++++--------
 1 file changed, 60 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index bebe5bd70b90..0af5059ff7d8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -2264,22 +2264,29 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win,
 	return 0;
 }
 
-static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2)
+/*
+ * On RK3566 these windows don't have an independent
+ * framebuffer. They can only share/mirror the framebuffer
+ * with smart0, esmart0 and cluster0 respectively.
+ * And RK3566 share the same vop version with Rk3568, so we
+ * need to use soc_id for identification here.
+ */
+static bool vop2_is_mirror_win(struct vop2_win *win)
 {
-	int i;
-
-	for (i = 0; i < vop2->data->nr_vps; i++) {
-		struct vop2_video_port *vp = &vop2->vps[i];
-
-		if (!vp->crtc.port)
-			continue;
-		if (vp->primary_plane)
-			continue;
+	struct vop2 *vop2 = win->vop2;
 
-		return vp;
+	if (vop2->data->soc_id == 3566) {
+		switch (win->data->phys_id) {
+		case ROCKCHIP_VOP2_SMART1:
+		case ROCKCHIP_VOP2_ESMART1:
+		case ROCKCHIP_VOP2_CLUSTER1:
+			return true;
+		default:
+			return false;
+		}
+	} else {
+		return false;
 	}
-
-	return NULL;
 }
 
 static int vop2_create_crtcs(struct vop2 *vop2)
@@ -2290,7 +2297,9 @@ static int vop2_create_crtcs(struct vop2 *vop2)
 	struct drm_plane *plane;
 	struct device_node *port;
 	struct vop2_video_port *vp;
-	int i, nvp, nvps = 0;
+	struct vop2_win *win;
+	u32 possible_crtcs;
+	int i, j, nvp, nvps = 0;
 	int ret;
 
 	for (i = 0; i < vop2_data->nr_vps; i++) {
@@ -2326,42 +2335,54 @@ static int vop2_create_crtcs(struct vop2 *vop2)
 	}
 
 	nvp = 0;
-	for (i = 0; i < vop2->registered_num_wins; i++) {
-		struct vop2_win *win = &vop2->win[i];
-		u32 possible_crtcs = 0;
-
-		if (vop2->data->soc_id == 3566) {
-			/*
-			 * On RK3566 these windows don't have an independent
-			 * framebuffer. They share the framebuffer with smart0,
-			 * esmart0 and cluster0 respectively.
-			 */
-			switch (win->data->phys_id) {
-			case ROCKCHIP_VOP2_SMART1:
-			case ROCKCHIP_VOP2_ESMART1:
-			case ROCKCHIP_VOP2_CLUSTER1:
+	/* Register a primary plane for every crtc */
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		vp = &vop2->vps[i];
+
+		if (!vp->crtc.port)
+			continue;
+
+		for (j = 0; j < vop2->registered_num_wins; j++) {
+			win = &vop2->win[j];
+
+			/* Aready registered as primary plane */
+			if (win->base.type == DRM_PLANE_TYPE_PRIMARY)
+				continue;
+
+			if (vop2_is_mirror_win(win))
 				continue;
-			}
-		}
 
-		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
-			vp = find_vp_without_primary(vop2);
-			if (vp) {
+			if (win->type == DRM_PLANE_TYPE_PRIMARY) {
 				possible_crtcs = BIT(nvp);
 				vp->primary_plane = win;
+				ret = vop2_plane_init(vop2, win, possible_crtcs);
+				if (ret)
+					return dev_err_probe(drm->dev, ret,
+							     "failed to init primary plane %s\n",
+							     win->data->name);
 				nvp++;
-			} else {
-				/* change the unused primary window to overlay window */
-				win->type = DRM_PLANE_TYPE_OVERLAY;
+				break;
 			}
 		}
+	}
+
+	/* Register all unused window as overlay plane */
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+
+		/* Aready registered as primary plane */
+		if (win->base.type == DRM_PLANE_TYPE_PRIMARY)
+			continue;
+
+		if (vop2_is_mirror_win(win))
+			continue;
 
-		if (win->type == DRM_PLANE_TYPE_OVERLAY)
-			possible_crtcs = (1 << nvps) - 1;
+		win->type = DRM_PLANE_TYPE_OVERLAY;
 
+		possible_crtcs = (1 << nvps) - 1;
 		ret = vop2_plane_init(vop2, win, possible_crtcs);
 		if (ret)
-			return dev_err_probe(drm->dev, ret, "failed to init plane %s\n",
+			return dev_err_probe(drm->dev, ret, "failed to init overlay plane %s\n",
 					     win->data->name);
 	}
 
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:20 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:20 +0800
Subject: [PATCH v16 6/7] dt-bindings: display: vop2: Add rk3576 support
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-7-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Add vop found on rk3576, the main difference between rk3576 and the
previous vop is that each VP has its own interrupt line.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v13)

Changes in v13:
- Use maxItems constraint for clocks in allOf block

Changes in v12:
- Split from patch 10/13

Changes in v11:
- Remove redundant min/maxItems constraint

Changes in v10:
- Move interrupt-names back to top level
- Add constraint of interrupts for all platform
- Add constraint for all grf phandles
- Reorder some properties

Changes in v9:
- Drop 'vop-' prefix of interrupt-names.
- Add blank line between DT properties
- Remove list interrupt-names in top level

Changes in v8:
- Fix dt_binding_check errors
- ordered by soc name
- Link to the previous version:
  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u

Changes in v4:
- describe constraint SOC by SOC, as interrupts of rk3576 is very
  different from others
- Drop Krzysztof's Reviewed-by, as this version changed a lot.

Changes in v3:
- ordered by soc name
- Add description for newly added interrupt

Changes in v2:
- Add dt bindings

 .../display/rockchip/rockchip-vop2.yaml       | 61 ++++++++++++++++++-
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
index 083eadcf0588..f546d481b7e5 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -21,6 +21,7 @@ properties:
     enum:
       - rockchip,rk3566-vop
       - rockchip,rk3568-vop
+      - rockchip,rk3576-vop
       - rockchip,rk3588-vop
 
   reg:
@@ -38,10 +39,21 @@ properties:
       - const: gamma-lut
 
   interrupts:
-    maxItems: 1
+    minItems: 1
+    maxItems: 4
     description:
-      The VOP interrupt is shared by several interrupt sources, such as
-      frame start (VSYNC), line flag and other status interrupts.
+      For VOP version under rk3576, the interrupt is shared by several interrupt
+      sources, such as frame start (VSYNC), line flag and other interrupt status.
+      For VOP version from rk3576 there is a system interrupt for bus error, and
+      every video port has it's independent interrupts for vsync and other video
+      port related error interrupts.
+
+  interrupt-names:
+    items:
+      - const: sys
+      - const: vp0
+      - const: vp1
+      - const: vp2
 
   # See compatible-specific constraints below.
   clocks:
@@ -136,6 +148,11 @@ allOf:
         clock-names:
           maxItems: 5
 
+        interrupts:
+          maxItems: 1
+
+        interrupt-names: false
+
         ports:
           required:
             - port at 0
@@ -149,6 +166,39 @@ allOf:
       required:
         - rockchip,grf
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,rk3576-vop
+    then:
+      properties:
+        clocks:
+          maxItems: 5
+
+        clock-names:
+          maxItems: 5
+
+        interrupts:
+          minItems: 4
+
+        interrupt-names:
+          minItems: 4
+
+        ports:
+          required:
+            - port at 0
+            - port at 1
+            - port at 2
+
+        rockchip,vo1-grf: false
+        rockchip,vop-grf: false
+
+      required:
+        - rockchip,grf
+        - rockchip,pmu
+
   - if:
       properties:
         compatible:
@@ -164,6 +214,11 @@ allOf:
           minItems: 7
           maxItems: 9
 
+        interrupts:
+          maxItems: 1
+
+        interrupt-names: false
+
         ports:
           required:
             - port at 0
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:16 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:16 +0800
Subject: [PATCH v16 2/7] drm/rockchip: vop2: Set plane possible crtcs by possible vp mask
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-3-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

In the upcoming VOP of rk3576, a window cannot attach to all Video
Ports, we introduce a possible_vp_mask for every window to indicate
which Video Ports this window can attach to.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
Tested-by: Detlev Casanova <detlev.casanova at collabora.com>
---

(no changes since v1)

 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 18 +++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h |  1 +
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 14 ++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 0af5059ff7d8..1280c5f07557 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -2349,6 +2349,10 @@ static int vop2_create_crtcs(struct vop2 *vop2)
 			if (win->base.type == DRM_PLANE_TYPE_PRIMARY)
 				continue;
 
+			/* If this win can not attached to this VP */
+			if (!(win->data->possible_vp_mask & BIT(vp->id)))
+				continue;
+
 			if (vop2_is_mirror_win(win))
 				continue;
 
@@ -2379,7 +2383,19 @@ static int vop2_create_crtcs(struct vop2 *vop2)
 
 		win->type = DRM_PLANE_TYPE_OVERLAY;
 
-		possible_crtcs = (1 << nvps) - 1;
+		possible_crtcs = 0;
+		nvp = 0;
+		for (j = 0; j < vop2_data->nr_vps; j++) {
+			vp = &vop2->vps[j];
+
+			if (!vp->crtc.port)
+				continue;
+
+			if (win->data->possible_vp_mask & BIT(vp->id))
+				possible_crtcs |= BIT(nvp);
+			nvp++;
+		}
+
 		ret = vop2_plane_init(vop2, win, possible_crtcs);
 		if (ret)
 			return dev_err_probe(drm->dev, ret, "failed to init overlay plane %s\n",
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
index a309042aa8e6..46d37c61279e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -167,6 +167,7 @@ struct vop2_win_data {
 	unsigned int phys_id;
 
 	u32 base;
+	u32 possible_vp_mask;
 	enum drm_plane_type type;
 
 	u32 nformats;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 0afef24db144..97df9d479f11 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -347,6 +347,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 		.name = "Smart0-win0",
 		.phys_id = ROCKCHIP_VOP2_SMART0,
 		.base = 0x1c00,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_smart,
 		.nformats = ARRAY_SIZE(formats_smart),
 		.format_modifiers = format_modifiers,
@@ -360,6 +361,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 	}, {
 		.name = "Smart1-win0",
 		.phys_id = ROCKCHIP_VOP2_SMART1,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_smart,
 		.nformats = ARRAY_SIZE(formats_smart),
 		.format_modifiers = format_modifiers,
@@ -373,6 +375,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 	}, {
 		.name = "Esmart1-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_rk356x_esmart,
 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
 		.format_modifiers = format_modifiers,
@@ -386,6 +389,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 	}, {
 		.name = "Esmart0-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_rk356x_esmart,
 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
 		.format_modifiers = format_modifiers,
@@ -400,6 +404,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 		.name = "Cluster0-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
 		.base = 0x1000,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -415,6 +420,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 		.name = "Cluster1-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
 		.base = 0x1200,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -580,6 +586,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 		.name = "Cluster0-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
 		.base = 0x1000,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -598,6 +605,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 		.name = "Cluster1-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
 		.base = 0x1200,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -616,6 +624,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 		.name = "Cluster2-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
 		.base = 0x1400,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -634,6 +643,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 		.name = "Cluster3-win0",
 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
 		.base = 0x1600,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_cluster,
 		.nformats = ARRAY_SIZE(formats_cluster),
 		.format_modifiers = format_modifiers_afbc,
@@ -651,6 +661,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 	}, {
 		.name = "Esmart0-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_esmart,
 		.nformats = ARRAY_SIZE(formats_esmart),
 		.format_modifiers = format_modifiers,
@@ -667,6 +678,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 	}, {
 		.name = "Esmart1-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_esmart,
 		.nformats = ARRAY_SIZE(formats_esmart),
 		.format_modifiers = format_modifiers,
@@ -684,6 +696,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 		.name = "Esmart2-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART2,
 		.base = 0x1c00,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_esmart,
 		.nformats = ARRAY_SIZE(formats_esmart),
 		.format_modifiers = format_modifiers,
@@ -699,6 +712,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
 	}, {
 		.name = "Esmart3-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART3,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
 		.formats = formats_esmart,
 		.nformats = ARRAY_SIZE(formats_esmart),
 		.format_modifiers = format_modifiers,
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:14 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:14 +0800
Subject: [PATCH v16 0/7] VOP Support for rk3576
Message-ID: <20250303034436.192400-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Here is the v16
Patches that have already been merged in drm-misc-next are dropped.

I test it with a 1080P/4K HDMI output with modetest and weston
output.

If there are some one want to have a try, I have a tree based on
Linux 6.14-rc1 here[0]

[0]https://github.com/andyshrk/linux/tree/rk3576-vop2-upstream-v16

Thanks.

Changes in v16:
- Link to v15: https://lore.kernel.org/linux-rockchip/20250218112744.34433-1-andyshrk at 163.com/
- Rebase on drm-misc-next
- Switch to dev_err_probe
- Remove redundant empty line

Changes in v15:
- Link to v14: https://lore.kernel.org/linux-rockchip/20250212093530.52961-1-andyshrk at 163.com/
- Remove AFBC/AFBCD prefix of TRANSFORM_OFFSET register
- Remove redundant blank line before function vop2_lock
- Fix nr_regs arguments for smart windows register.

Changes in v14:
- Set maxItems constraint of clocks for rk3588 to 9 as a recently
  merged patch added two optional clocks[0]:
  [0]https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-1-d71c6a196e58 at collabora.com

Changes in v13:
- Add maxItems constraint for clocks
- Remove constraint for interrupts in allOf block, as the current
  maxItems is already 1.
- typo fix
- Explain the function of this property.
- Use maxItems constraint for clocks in allOf block

Changes in v12:
- Only change the description method for existing SoC.
- Split from patch 10/13
- Split from patch 10/13

Changes in v11:
- Remove redundant min/maxItems constraint
- Remove redundant min/maxItems constraint

Changes in v10:
- Move interrupt-names back to top level
- Add constraint of interrupts for all platform
- Add constraint for all grf phandles
- Reorder some properties
- Move interrupt-names back to top level
- Add constraint of interrupts for all platform
- Add constraint for all grf phandles
- Reorder some properties

Changes in v9:
- Drop 'vop-' prefix of interrupt-names.
- Add blank line between DT properties
- Remove list interrupt-names in top level
- Drop 'vop-' prefix of interrupt-names.
- Add blank line between DT properties
- Remove list interrupt-names in top level
- Drop 'vop-' prefix of interrupt-names.

Changes in v8:
- Fix dt_binding_check errors
- ordered by soc name
- Link to the previous version:
  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u
- Fix dt_binding_check errors
- ordered by soc name
- Link to the previous version:
  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u

Changes in v6:
-  More specific explanation about the AXI_BUS_ID register bit of
   cluster window.

Changes in v5:
- Add axi id configuration
- Remove the non-existent CBCR scale register.

Changes in v4:
- describe constraint SOC by SOC, as interrupts of rk3576 is very
  different from others
- Drop Krzysztof's Reviewed-by, as this version changed a lot.
- describe constraint SOC by SOC, as interrupts of rk3576 is very
  different from others
- Drop Krzysztof's Reviewed-by, as this version changed a lot.

Changes in v3:
- Add comments for why we should treat rk3566 with special care.
- ordered by soc name
- Add description for newly added interrupt
- ordered by soc name
- Add description for newly added interrupt
- Share the alpha setup function with rk3568
- recoder the code block by soc

Changes in v2:
- Add dt bindings
- Add dt bindings
- Add platform specific callback

Andy Yan (7):
  drm/rockchip: vop2: Register the primary plane and overlay plane
    separately
  drm/rockchip: vop2: Set plane possible crtcs by possible vp mask
  drm/rockchip: vop2: Add uv swap for cluster window
  dt-bindings: display: vop2: describe constraint SoC by SoC
  dt-bindings: display: vop2: Add missing rockchip,grf property for
    rk3566/8
  dt-bindings: display: vop2: Add rk3576 support
  drm/rockchip: vop2: Add support for rk3576

 .../display/rockchip/rockchip-vop2.yaml       |  99 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 259 +++--
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h  |  88 ++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  | 954 ++++++++++++++++--
 4 files changed, 1223 insertions(+), 177 deletions(-)

-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:17 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:17 +0800
Subject: [PATCH v16 3/7] drm/rockchip: vop2: Add uv swap for cluster window
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-4-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The Cluster windows of upcoming VOP on rk3576 also support
linear YUV support, we need to set uv swap bit for it.

As the VOP2_WIN_UV_SWA register defined on rk3568/rk3588 is
0xffffffff, so this register will not be touched on these
two platforms.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
Tested-by: Detlev Casanova <detlev.casanova at collabora.com>
---

(no changes since v1)

 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 1280c5f07557..338cfb69e1cf 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -1377,10 +1377,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
 
 	rb_swap = vop2_win_rb_swap(fb->format->format);
 	vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap);
-	if (!vop2_cluster_window(win)) {
-		uv_swap = vop2_win_uv_swap(fb->format->format);
-		vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
-	}
+	uv_swap = vop2_win_uv_swap(fb->format->format);
+	vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
 
 	if (fb->format->is_yuv) {
 		vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4));
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:18 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:18 +0800
Subject: [PATCH v16 4/7] dt-bindings: display: vop2: describe constraint SoC by SoC
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-5-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

As more SoCs variants are introduced, each SoC brings its own
unique set of constraints, describe this constraints SoC by
SoC will make things easier.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v14)

Changes in v14:
- Set maxItems constraint of clocks for rk3588 to 9 as a recently
  merged patch added two optional clocks[0]:
  [0]https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-1-d71c6a196e58 at collabora.com

Changes in v13:
- Add maxItems constraint for clocks
- Remove constraint for interrupts in allOf block, as the current
  maxItems is already 1.

Changes in v12:
- Only change the description method for existing SoC.

Changes in v11:
- Remove redundant min/maxItems constraint

Changes in v10:
- Move interrupt-names back to top level
- Add constraint of interrupts for all platform
- Add constraint for all grf phandles
- Reorder some properties

Changes in v9:
- Drop 'vop-' prefix of interrupt-names.
- Add blank line between DT properties
- Remove list interrupt-names in top level

Changes in v8:
- Fix dt_binding_check errors
- ordered by soc name
- Link to the previous version:
  https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p at ztg4mqyiqmjf/T/#u

Changes in v4:
- describe constraint SOC by SOC, as interrupts of rk3576 is very
  different from others
- Drop Krzysztof's Reviewed-by, as this version changed a lot.

Changes in v3:
- ordered by soc name
- Add description for newly added interrupt

Changes in v2:
- Add dt bindings

 .../display/rockchip/rockchip-vop2.yaml       | 40 ++++++++++++-------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
index 46d956e63338..a5771edd83b5 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -14,6 +14,7 @@ description:
 maintainers:
   - Sandy Huang <hjc at rock-chips.com>
   - Heiko Stuebner <heiko at sntech.de>
+  - Andy Yan <andyshrk at 163.com>
 
 properties:
   compatible:
@@ -124,43 +125,54 @@ allOf:
       properties:
         compatible:
           contains:
-            const: rockchip,rk3588-vop
+            enum:
+              - rockchip,rk3566-vop
+              - rockchip,rk3568-vop
     then:
       properties:
         clocks:
-          minItems: 7
+          maxItems: 5
+
         clock-names:
-          minItems: 7
+          maxItems: 5
 
         ports:
           required:
             - port at 0
             - port at 1
             - port at 2
-            - port at 3
 
-      required:
-        - rockchip,grf
-        - rockchip,vo1-grf
-        - rockchip,vop-grf
-        - rockchip,pmu
-
-    else:
-      properties:
         rockchip,vo1-grf: false
         rockchip,vop-grf: false
         rockchip,pmu: false
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: rockchip,rk3588-vop
+    then:
+      properties:
         clocks:
-          maxItems: 5
+          minItems: 7
+          maxItems: 9
+
         clock-names:
-          maxItems: 5
+          minItems: 7
+          maxItems: 9
 
         ports:
           required:
             - port at 0
             - port at 1
             - port at 2
+            - port at 3
+
+      required:
+        - rockchip,grf
+        - rockchip,vo1-grf
+        - rockchip,vop-grf
+        - rockchip,pmu
 
 additionalProperties: false
 
-- 
2.34.1



From andyshrk at 163.com  Sun Mar  2 19:44:21 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon,  3 Mar 2025 11:44:21 +0800
Subject: [PATCH v16 7/7] drm/rockchip: vop2: Add support for rk3576
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <20250303034436.192400-8-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

VOP2 on rk3576:
Three video ports:
VP0 Max 4096x2160
VP1 Max 2560x1600
VP2 Max 1920x1080

2 4K Cluster windows with AFBC/RFBC, line RGB and YUV
4 Esmart windows with line RGB/YUV support:
Esmart0/1: 4K
Esmart2/3: 2k, or worked together as a single 4K plane at shared
line buffer mode.

Compared to the previous VOP, another difference is that each VP
has its own independent vsync interrupt number.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
Tested-by: Detlev Casanova <detlev.casanova at collabora.com>

---

Changes in v16:
- Remove redundant empty line
- Switch to dev_err_probe

Changes in v9:
- Drop 'vop-' prefix of interrupt-names.

Changes in v6:
-  More specific explanation about the AXI_BUS_ID register bit of
   cluster window.

Changes in v5:
- Add axi id configuration
- Remove the non-existent CBCR scale register.

Changes in v3:
- Share the alpha setup function with rk3568
- recoder the code block by soc

Changes in v2:
- Add platform specific callback

 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 138 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h |  87 ++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 950 +++++++++++++++++--
 3 files changed, 1050 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 338cfb69e1cf..d0f5fea15e21 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -1280,6 +1280,9 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
 		vop2_win_write(win, VOP2_WIN_AXI_UV_R_ID, win->data->axi_uv_r_id);
 	}
 
+	if (vop2->version >= VOP_VERSION_RK3576)
+		vop2_win_write(win, VOP2_WIN_VP_SEL, vp->id);
+
 	if (vop2_cluster_window(win))
 		vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, half_block_en);
 
@@ -1344,6 +1347,11 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
 		else
 			vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0);
 
+		if (vop2->version >= VOP_VERSION_RK3576) {
+			vop2_win_write(win, VOP2_WIN_AFBC_PLD_OFFSET_EN, 1);
+			vop2_win_write(win, VOP2_WIN_AFBC_PLD_OFFSET, yrgb_mst);
+		}
+
 		transform_offset = vop2_afbc_transform_offset(pstate, half_block_en);
 		vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst);
 		vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info);
@@ -2159,6 +2167,52 @@ static const struct drm_crtc_funcs vop2_crtc_funcs = {
 	.late_register = vop2_crtc_late_register,
 };
 
+static irqreturn_t rk3576_vp_isr(int irq, void *data)
+{
+	struct vop2_video_port *vp = data;
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_crtc *crtc = &vp->crtc;
+	uint32_t irqs;
+	int ret = IRQ_NONE;
+
+	if (!pm_runtime_get_if_in_use(vop2->dev))
+		return IRQ_NONE;
+
+	irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id));
+	vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs);
+
+	if (irqs & VP_INT_DSP_HOLD_VALID) {
+		complete(&vp->dsp_hold_completion);
+		ret = IRQ_HANDLED;
+	}
+
+	if (irqs & VP_INT_FS_FIELD) {
+		drm_crtc_handle_vblank(crtc);
+		spin_lock(&crtc->dev->event_lock);
+		if (vp->event) {
+			u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
+
+			if (!(val & BIT(vp->id))) {
+				drm_crtc_send_vblank_event(crtc, vp->event);
+				vp->event = NULL;
+				drm_crtc_vblank_put(crtc);
+			}
+		}
+		spin_unlock(&crtc->dev->event_lock);
+
+		ret = IRQ_HANDLED;
+	}
+
+	if (irqs & VP_INT_POST_BUF_EMPTY) {
+		drm_err_ratelimited(vop2->drm, "POST_BUF_EMPTY irq err at vp%d\n", vp->id);
+		ret = IRQ_HANDLED;
+	}
+
+	pm_runtime_put(vop2->dev);
+
+	return ret;
+}
+
 static irqreturn_t vop2_isr(int irq, void *data)
 {
 	struct vop2 *vop2 = data;
@@ -2174,41 +2228,43 @@ static irqreturn_t vop2_isr(int irq, void *data)
 	if (!pm_runtime_get_if_in_use(vop2->dev))
 		return IRQ_NONE;
 
-	for (i = 0; i < vop2_data->nr_vps; i++) {
-		struct vop2_video_port *vp = &vop2->vps[i];
-		struct drm_crtc *crtc = &vp->crtc;
-		u32 irqs;
+	if (vop2->version < VOP_VERSION_RK3576) {
+		for (i = 0; i < vop2_data->nr_vps; i++) {
+			struct vop2_video_port *vp = &vop2->vps[i];
+			struct drm_crtc *crtc = &vp->crtc;
+			u32 irqs;
 
-		irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id));
-		vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs);
+			irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id));
+			vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs);
 
-		if (irqs & VP_INT_DSP_HOLD_VALID) {
-			complete(&vp->dsp_hold_completion);
-			ret = IRQ_HANDLED;
-		}
-
-		if (irqs & VP_INT_FS_FIELD) {
-			drm_crtc_handle_vblank(crtc);
-			spin_lock(&crtc->dev->event_lock);
-			if (vp->event) {
-				u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
+			if (irqs & VP_INT_DSP_HOLD_VALID) {
+				complete(&vp->dsp_hold_completion);
+				ret = IRQ_HANDLED;
+			}
 
-				if (!(val & BIT(vp->id))) {
-					drm_crtc_send_vblank_event(crtc, vp->event);
-					vp->event = NULL;
-					drm_crtc_vblank_put(crtc);
+			if (irqs & VP_INT_FS_FIELD) {
+				drm_crtc_handle_vblank(crtc);
+				spin_lock(&crtc->dev->event_lock);
+				if (vp->event) {
+					u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
+
+					if (!(val & BIT(vp->id))) {
+						drm_crtc_send_vblank_event(crtc, vp->event);
+						vp->event = NULL;
+						drm_crtc_vblank_put(crtc);
+					}
 				}
-			}
-			spin_unlock(&crtc->dev->event_lock);
+				spin_unlock(&crtc->dev->event_lock);
 
-			ret = IRQ_HANDLED;
-		}
+				ret = IRQ_HANDLED;
+			}
 
-		if (irqs & VP_INT_POST_BUF_EMPTY) {
-			drm_err_ratelimited(vop2->drm,
-					    "POST_BUF_EMPTY irq err at vp%d\n",
-					    vp->id);
-			ret = IRQ_HANDLED;
+			if (irqs & VP_INT_POST_BUF_EMPTY) {
+				drm_err_ratelimited(vop2->drm,
+						    "POST_BUF_EMPTY irq err at vp%d\n",
+						    vp->id);
+				ret = IRQ_HANDLED;
+			}
 		}
 	}
 
@@ -2677,6 +2733,30 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		return ret;
 
+	if (vop2->version >= VOP_VERSION_RK3576) {
+		struct drm_crtc *crtc;
+
+		drm_for_each_crtc(crtc, drm) {
+			struct vop2_video_port *vp = to_vop2_video_port(crtc);
+			int vp_irq;
+			const char *irq_name = devm_kasprintf(dev, GFP_KERNEL, "vp%d", vp->id);
+
+			if (!irq_name)
+				return -ENOMEM;
+
+			vp_irq = platform_get_irq_byname(pdev, irq_name);
+			if (vp_irq < 0)
+				return dev_err_probe(drm->dev, vp_irq,
+						     "cannot find irq for vop2 vp%d\n", vp->id);
+
+			ret = devm_request_irq(dev, vp_irq, rk3576_vp_isr, IRQF_SHARED, irq_name,
+					       vp);
+			if (ret)
+				dev_err_probe(drm->dev, ret,
+					      "request irq for vop2 vp%d failed\n", vp->id);
+		}
+	}
+
 	ret = vop2_find_rgb_encoder(vop2);
 	if (ret >= 0) {
 		vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
index 46d37c61279e..680bedbb770e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -44,6 +44,13 @@ enum win_dly_mode {
 	VOP2_DLY_MODE_MAX,
 };
 
+enum vop2_dly_module {
+	VOP2_DLY_WIN,           /** Win delay cycle for this VP */
+	VOP2_DLY_LAYER_MIX,     /** Layer Mix delay cycle for this VP */
+	VOP2_DLY_HDR_MIX,       /** HDR delay cycle for this VP */
+	VOP2_DLY_MAX,
+};
+
 enum vop2_scale_up_mode {
 	VOP2_SCALE_UP_NRST_NBOR,
 	VOP2_SCALE_UP_BIL,
@@ -140,16 +147,22 @@ enum vop2_win_regs {
 	VOP2_WIN_AFBC_UV_SWAP,
 	VOP2_WIN_AFBC_AUTO_GATING_EN,
 	VOP2_WIN_AFBC_BLOCK_SPLIT_EN,
+	VOP2_WIN_AFBC_PLD_OFFSET_EN,
 	VOP2_WIN_AFBC_PIC_VIR_WIDTH,
 	VOP2_WIN_AFBC_TILE_NUM,
 	VOP2_WIN_AFBC_PIC_OFFSET,
 	VOP2_WIN_AFBC_PIC_SIZE,
 	VOP2_WIN_AFBC_DSP_OFFSET,
+	VOP2_WIN_AFBC_PLD_OFFSET,
 	VOP2_WIN_TRANSFORM_OFFSET,
 	VOP2_WIN_AFBC_HDR_PTR,
 	VOP2_WIN_AFBC_HALF_BLOCK_EN,
 	VOP2_WIN_AFBC_ROTATE_270,
 	VOP2_WIN_AFBC_ROTATE_90,
+
+	VOP2_WIN_VP_SEL,
+	VOP2_WIN_DLY_NUM,
+
 	VOP2_WIN_MAX_REG,
 };
 
@@ -215,6 +228,10 @@ struct vop2_video_port_data {
 	struct vop_rect max_output;
 	const u8 pre_scan_max_dly[4];
 	unsigned int offset;
+	/**
+	 * @pixel_rate: pixel per cycle
+	 */
+	u8 pixel_rate;
 };
 
 struct vop2_video_port {
@@ -375,10 +392,13 @@ enum dst_factor_mode {
 #define RK3568_REG_CFG_DONE			0x000
 #define RK3568_VERSION_INFO			0x004
 #define RK3568_SYS_AUTO_GATING_CTRL		0x008
+#define RK3576_SYS_MMU_CTRL_IMD			0x020
 #define RK3568_SYS_AXI_LUT_CTRL			0x024
 #define RK3568_DSP_IF_EN			0x028
+#define RK3576_SYS_PORT_CTRL_IMD		0x028
 #define RK3568_DSP_IF_CTRL			0x02c
 #define RK3568_DSP_IF_POL			0x030
+#define RK3576_SYS_CLUSTER_PD_CTRL_IMD		0x030
 #define RK3588_SYS_PD_CTRL			0x034
 #define RK3568_WB_CTRL				0x40
 #define RK3568_WB_XSCAL_FACTOR			0x44
@@ -398,6 +418,55 @@ enum dst_factor_mode {
 #define RK3568_VP_INT_CLR(vp)			(0xA4 + (vp) * 0x10)
 #define RK3568_VP_INT_STATUS(vp)		(0xA8 + (vp) * 0x10)
 #define RK3568_VP_INT_RAW_STATUS(vp)		(0xAC + (vp) * 0x10)
+#define RK3576_WB_CTRL				0x100
+#define RK3576_WB_XSCAL_FACTOR			0x104
+#define RK3576_WB_YRGB_MST			0x108
+#define RK3576_WB_CBR_MST			0x10C
+#define RK3576_WB_VIR_STRIDE			0x110
+#define RK3576_WB_TIMEOUT_CTRL			0x114
+#define RK3576_MIPI0_IF_CTRL			0x180
+#define RK3576_HDMI0_IF_CTRL			0x184
+#define RK3576_EDP0_IF_CTRL			0x188
+#define RK3576_DP0_IF_CTRL			0x18C
+#define RK3576_RGB_IF_CTRL			0x194
+#define RK3576_DP1_IF_CTRL			0x1A4
+#define RK3576_DP2_IF_CTRL			0x1B0
+
+/* Extra OVL register definition */
+#define RK3576_SYS_EXTRA_ALPHA_CTRL		0x500
+#define RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
+#define RK3576_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
+#define RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
+#define RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
+#define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL	0x540
+#define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL	0x544
+#define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL	0x548
+#define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL	0x54c
+
+/* OVL registers for Video Port definition */
+#define RK3576_OVL_CTRL(vp)			(0x600 + (vp) * 0x100)
+#define RK3576_OVL_LAYER_SEL(vp)		(0x604 + (vp) * 0x100)
+#define RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp)	(0x620 + (vp) * 0x100)
+#define RK3576_OVL_MIX0_DST_COLOR_CTRL(vp)	(0x624 + (vp) * 0x100)
+#define RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp)	(0x628 + (vp) * 0x100)
+#define RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp)	(0x62C + (vp) * 0x100)
+#define RK3576_OVL_MIX1_SRC_COLOR_CTRL(vp)	(0x630 + (vp) * 0x100)
+#define RK3576_OVL_MIX1_DST_COLOR_CTRL(vp)	(0x634 + (vp) * 0x100)
+#define RK3576_OVL_MIX1_SRC_ALPHA_CTRL(vp)	(0x638 + (vp) * 0x100)
+#define RK3576_OVL_MIX1_DST_ALPHA_CTRL(vp)	(0x63C + (vp) * 0x100)
+#define RK3576_OVL_MIX2_SRC_COLOR_CTRL(vp)	(0x640 + (vp) * 0x100)
+#define RK3576_OVL_MIX2_DST_COLOR_CTRL(vp)	(0x644 + (vp) * 0x100)
+#define RK3576_OVL_MIX2_SRC_ALPHA_CTRL(vp)	(0x648 + (vp) * 0x100)
+#define RK3576_OVL_MIX2_DST_ALPHA_CTRL(vp)	(0x64C + (vp) * 0x100)
+#define RK3576_EXTRA_OVL_SRC_COLOR_CTRL(vp)	(0x650 + (vp) * 0x100)
+#define RK3576_EXTRA_OVL_DST_COLOR_CTRL(vp)	(0x654 + (vp) * 0x100)
+#define RK3576_EXTRA_OVL_SRC_ALPHA_CTRL(vp)	(0x658 + (vp) * 0x100)
+#define RK3576_EXTRA_OVL_DST_ALPHA_CTRL(vp)	(0x65C + (vp) * 0x100)
+#define RK3576_OVL_HDR_SRC_COLOR_CTRL(vp)	(0x660 + (vp) * 0x100)
+#define RK3576_OVL_HDR_DST_COLOR_CTRL(vp)	(0x664 + (vp) * 0x100)
+#define RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp)	(0x668 + (vp) * 0x100)
+#define RK3576_OVL_HDR_DST_ALPHA_CTRL(vp)	(0x66C + (vp) * 0x100)
+#define RK3576_OVL_BG_MIX_CTRL(vp)		(0x670 + (vp) * 0x100)
 
 /* Video Port registers definition */
 #define RK3568_VP0_CTRL_BASE			0x0C00
@@ -480,7 +549,11 @@ enum dst_factor_mode {
 #define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET	0x68
 #define RK3568_CLUSTER_WIN_AFBCD_CTRL		0x6C
 
+#define RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET	0x78
+
 #define RK3568_CLUSTER_CTRL			0x100
+#define RK3576_CLUSTER_PORT_SEL_IMD		0x1F4
+#define RK3576_CLUSTER_DLY_NUM			0x1F8
 
 /* (E)smart register definition, offset relative to window base */
 #define RK3568_SMART_CTRL0			0x00
@@ -531,6 +604,9 @@ enum dst_factor_mode {
 #define RK3568_SMART_REGION3_SCL_FACTOR_CBR	0xC8
 #define RK3568_SMART_REGION3_SCL_OFFSET		0xCC
 #define RK3568_SMART_COLOR_KEY_CTRL		0xD0
+#define RK3576_SMART_ALPHA_MAP			0xD8
+#define RK3576_SMART_PORT_SEL_IMD		0xF4
+#define RK3576_SMART_DLY_NUM			0xF8
 
 /* HDR register definition */
 #define RK3568_HDR_LUT_CTRL			0x2000
@@ -679,6 +755,17 @@ enum dst_factor_mode {
 
 #define POLFLAG_DCLK_INV	BIT(3)
 
+#define RK3576_OVL_CTRL__YUV_MODE			BIT(0)
+#define RK3576_OVL_BG_MIX_CTRL__BG_DLY			GENMASK(31, 24)
+
+#define RK3576_DSP_IF_CFG_DONE_IMD			BIT(31)
+#define RK3576_DSP_IF_DCLK_SEL_OUT			BIT(21)
+#define RK3576_DSP_IF_PCLK_DIV				BIT(20)
+#define RK3576_DSP_IF_PIN_POL				GENMASK(5, 4)
+#define RK3576_DSP_IF_MUX				GENMASK(3, 2)
+#define RK3576_DSP_IF_CLK_OUT_EN			BIT(1)
+#define RK3576_DSP_IF_EN				BIT(0)
+
 enum vop2_layer_phy_id {
 	ROCKCHIP_VOP2_CLUSTER0 = 0,
 	ROCKCHIP_VOP2_CLUSTER1,
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 97df9d479f11..a1402622589a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -70,6 +70,37 @@ static const uint32_t formats_cluster[] = {
 	DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */
 };
 
+/*
+ * The cluster windows on rk3576 support:
+ * RGB: linear mode and afbc
+ * YUV: linear mode and rfbc
+ * rfbc is a rockchip defined non-linear mode, produced by
+ * Video decoder
+ */
+static const uint32_t formats_rk3576_cluster[] = {
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
+	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
+	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
+};
+
 static const uint32_t formats_esmart[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
@@ -116,6 +147,41 @@ static const uint32_t formats_rk356x_esmart[] = {
 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
 };
 
+/*
+ * Add XRGB2101010/ARGB2101010ARGB1555/XRGB1555
+ */
+static const uint32_t formats_rk3576_esmart[] = {
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_XBGR1555,
+	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
+	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
+	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
+	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
+	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
+	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
+	DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
+	DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
+};
+
 static const uint32_t formats_smart[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
@@ -169,6 +235,48 @@ static const uint64_t format_modifiers_afbc[] = {
 	DRM_FORMAT_MOD_INVALID,
 };
 
+/* used from rk3576, afbc 32*8 half mode */
+static const uint64_t format_modifiers_rk3576_afbc[] = {
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+
+	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID,
+};
+
 static const struct reg_field rk3568_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
 	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
 	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
@@ -301,6 +409,147 @@ static const struct reg_field rk3568_vop_smart_regs[VOP2_WIN_MAX_REG] = {
 	[VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
 };
 
+static const struct reg_field rk3576_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
+	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
+	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
+	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
+	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 17, 17),
+	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
+	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
+	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
+	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
+	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
+	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
+	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
+	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
+	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
+	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
+	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
+	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
+	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 4),
+	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 9),
+	/* Read only bit on rk3576, writing on this bit have no effect.*/
+	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13),
+
+	[VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_CLUSTER_PORT_SEL_IMD, 0, 1),
+	[VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_CLUSTER_DLY_NUM, 0, 7),
+
+	/* Scale */
+	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
+	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
+	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
+	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
+	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 22, 23),
+	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
+	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
+
+	/* cluster regs */
+	[VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
+	[VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
+	[VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
+
+	/* afbc regs */
+	[VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
+	[VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
+	[VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
+	[VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
+	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
+	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
+	[VOP2_WIN_AFBC_PLD_OFFSET_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 16, 16),
+	[VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
+	[VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
+	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
+	[VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
+	[VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
+	[VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
+	[VOP2_WIN_AFBC_PLD_OFFSET] = REG_FIELD(RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET, 0, 31),
+	[VOP2_WIN_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_TRANSFORM_OFFSET, 0, 31),
+	[VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
+	[VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
+	[VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
+	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
+	[VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
+	[VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
+	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
+	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
+	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
+	[VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
+};
+
+static const struct reg_field rk3576_vop_smart_regs[VOP2_WIN_MAX_REG] = {
+	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
+	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
+	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
+	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
+	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
+	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
+	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
+	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
+	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
+	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
+	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
+	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
+	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
+	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
+	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
+	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
+	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
+	[VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
+	[VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
+	[VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_SMART_PORT_SEL_IMD, 0, 1),
+	[VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_SMART_DLY_NUM, 0, 7),
+	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8),
+	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16),
+	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1),
+
+	/* Scale */
+	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
+	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
+	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
+	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
+	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
+	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
+	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
+	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
+	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
+	[VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
+	[VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
+	[VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
+
+	/* CBCR share the same scale factor as YRGB */
+	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
+	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff},
+	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff},
+	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff},
+
+	[VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
+	[VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
+	[VOP2_WIN_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
+	[VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
+};
+
 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
 	{
 		.id = 0,
@@ -355,98 +604,385 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
 		.layer_sel_id = { 3, 3, 3, 0xf },
 		.supported_rotations = DRM_MODE_REFLECT_Y,
 		.type = DRM_PLANE_TYPE_PRIMARY,
-		.max_upscale_factor = 8,
-		.max_downscale_factor = 8,
-		.dly = { 20, 47, 41 },
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+	}, {
+		.name = "Smart1-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART1,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
+		.formats = formats_smart,
+		.nformats = ARRAY_SIZE(formats_smart),
+		.format_modifiers = format_modifiers,
+		.base = 0x1e00,
+		.layer_sel_id = { 7, 7, 7, 0xf },
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+	}, {
+		.name = "Esmart1-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
+		.formats = formats_rk356x_esmart,
+		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
+		.format_modifiers = format_modifiers,
+		.base = 0x1a00,
+		.layer_sel_id = { 6, 6, 6, 0xf },
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+	}, {
+		.name = "Esmart0-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
+		.formats = formats_rk356x_esmart,
+		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
+		.format_modifiers = format_modifiers,
+		.base = 0x1800,
+		.layer_sel_id = { 2, 2, 2, 0xf },
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+	}, {
+		.name = "Cluster0-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1000,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
+		.formats = formats_cluster,
+		.nformats = ARRAY_SIZE(formats_cluster),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = { 0, 0, 0, 0xf },
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
+	}, {
+		.name = "Cluster1-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.base = 0x1200,
+		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
+		.formats = formats_cluster,
+		.nformats = ARRAY_SIZE(formats_cluster),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = { 1, 1, 1, 0xf },
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
+	},
+};
+
+static const struct vop2_regs_dump rk3568_regs_dump[] = {
+	{
+		.name = "SYS",
+		.base = RK3568_REG_CFG_DONE,
+		.size = 0x100,
+		.en_reg  = 0,
+		.en_val = 0,
+		.en_mask = 0
+	}, {
+		.name = "OVL",
+		.base = RK3568_OVL_CTRL,
+		.size = 0x100,
+		.en_reg = 0,
+		.en_val = 0,
+		.en_mask = 0,
+	}, {
+		.name = "VP0",
+		.base = RK3568_VP0_CTRL_BASE,
+		.size = 0x100,
+		.en_reg = RK3568_VP_DSP_CTRL,
+		.en_val = 0,
+		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
+	}, {
+		.name = "VP1",
+		.base = RK3568_VP1_CTRL_BASE,
+		.size = 0x100,
+		.en_reg = RK3568_VP_DSP_CTRL,
+		.en_val = 0,
+		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
+	}, {
+		.name = "VP2",
+		.base = RK3568_VP2_CTRL_BASE,
+		.size = 0x100,
+		.en_reg = RK3568_VP_DSP_CTRL,
+		.en_val = 0,
+		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
+
+	}, {
+		.name = "Cluster0",
+		.base = RK3568_CLUSTER0_CTRL_BASE,
+		.size = 0x110,
+		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
+		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
+		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
+	}, {
+		.name = "Cluster1",
+		.base = RK3568_CLUSTER1_CTRL_BASE,
+		.size = 0x110,
+		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
+		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
+		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
+	}, {
+		.name = "Esmart0",
+		.base = RK3568_ESMART0_CTRL_BASE,
+		.size = 0xf0,
+		.en_reg = RK3568_SMART_REGION0_CTRL,
+		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+	}, {
+		.name = "Esmart1",
+		.base = RK3568_ESMART1_CTRL_BASE,
+		.size = 0xf0,
+		.en_reg = RK3568_SMART_REGION0_CTRL,
+		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+	}, {
+		.name = "Smart0",
+		.base = RK3568_SMART0_CTRL_BASE,
+		.size = 0xf0,
+		.en_reg = RK3568_SMART_REGION0_CTRL,
+		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+	}, {
+		.name = "Smart1",
+		.base = RK3568_SMART1_CTRL_BASE,
+		.size = 0xf0,
+		.en_reg = RK3568_SMART_REGION0_CTRL,
+		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
+	},
+};
+
+static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
+	{
+		.id = 0,
+		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
+		.gamma_lut_len = 1024,
+		.cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
+		.max_output = { 4096, 2304 },
+		/* win layer_mix hdr  */
+		.pre_scan_max_dly = { 10, 8, 2, 0 },
+		.offset = 0xc00,
+		.pixel_rate = 2,
+	}, {
+		.id = 1,
+		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
+		.gamma_lut_len = 1024,
+		.cubic_lut_len = 729, /* 9x9x9 */
+		.max_output = { 2560, 1600 },
+		/* win layer_mix hdr  */
+		.pre_scan_max_dly = { 10, 6, 0, 0 },
+		.offset = 0xd00,
+		.pixel_rate = 1,
+	}, {
+		.id = 2,
+		.gamma_lut_len = 1024,
+		.max_output = { 1920, 1080 },
+		/* win layer_mix hdr  */
+		.pre_scan_max_dly = { 10, 6, 0, 0 },
+		.offset = 0xe00,
+		.pixel_rate = 1,
+	},
+};
+
+/*
+ * rk3576 vop with 2 cluster, 4 esmart win.
+ * Every cluster can work as 4K win or split into two 2K win.
+ * All win in cluster support AFBCD.
+ *
+ * Every esmart win support 4 Multi-region.
+ *
+ * VP0 can use Cluster0/1 and Esmart0/2
+ * VP1 can use Cluster0/1 and Esmart1/3
+ * VP2 can use Esmart0/1/2/3
+ *
+ * Scale filter mode:
+ *
+ * * Cluster:
+ * * Support prescale down:
+ * * H/V: gt2/avg2 or gt4/avg4
+ * * After prescale down:
+ *	* nearest-neighbor/bilinear/multi-phase filter for scale up
+ *	* nearest-neighbor/bilinear/multi-phase filter for scale down
+ *
+ * * Esmart:
+ * * Support prescale down:
+ * * H: gt2/avg2 or gt4/avg4
+ * * V: gt2 or gt4
+ * * After prescale down:
+ *	* nearest-neighbor/bilinear/bicubic for scale up
+ *	* nearest-neighbor/bilinear for scale down
+ *
+ * AXI config::
+ *
+ * * Cluster0 win0: 0xa,  0xb       [AXI0]
+ * * Cluster0 win1: 0xc,  0xd       [AXI0]
+ * * Cluster1 win0: 0x6,  0x7       [AXI0]
+ * * Cluster1 win1: 0x8,  0x9       [AXI0]
+ * * Esmart0:       0x10, 0x11      [AXI0]
+ * * Esmart1:       0x12, 0x13      [AXI0]
+ * * Esmart2:       0xa,  0xb       [AXI1]
+ * * Esmart3:       0xc,  0xd       [AXI1]
+ * * Lut dma rid:   0x1,  0x2,  0x3 [AXI0]
+ * * DCI dma rid:   0x4             [AXI0]
+ * * Metadata rid:  0x5             [AXI0]
+ *
+ * * Limit:
+ * * (1) Cluster0/1 are fixed on AXI0 by IC design
+ * * (2) 0x0 and 0xf can't be used;
+ * * (3) 5 Bits ID for eache axi bus
+ * * (3) cluster and lut/dci/metadata rid must smaller than 0xf,
+ * *     if Cluster rid is bigger than 0xf, VOP will dead at the
+ * *     system bandwidth very terrible scene.
+ */
+static const struct vop2_win_data rk3576_vop_win_data[] = {
+	{
+		.name = "Cluster0-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1000,
+		.possible_vp_mask = BIT(0) | BIT(1),
+		.formats = formats_rk3576_cluster,
+		.nformats = ARRAY_SIZE(formats_rk3576_cluster),
+		.format_modifiers = format_modifiers_rk3576_afbc,
+		.layer_sel_id = { 0, 0, 0xf, 0xf },
+		.supported_rotations =  DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.axi_bus_id = 0,
+		.axi_yrgb_r_id = 0xa,
+		.axi_uv_r_id = 0xb,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
 	}, {
-		.name = "Smart1-win0",
-		.phys_id = ROCKCHIP_VOP2_SMART1,
-		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
-		.formats = formats_smart,
-		.nformats = ARRAY_SIZE(formats_smart),
+		.name = "Cluster1-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.base = 0x1200,
+		.possible_vp_mask = BIT(0) | BIT(1),
+		.formats = formats_rk3576_cluster,
+		.nformats = ARRAY_SIZE(formats_rk3576_cluster),
+		.format_modifiers = format_modifiers_rk3576_afbc,
+		.layer_sel_id = { 1, 1, 0xf, 0xf },
+		.supported_rotations =  DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.axi_bus_id = 0,
+		.axi_yrgb_r_id = 6,
+		.axi_uv_r_id = 7,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
+	}, {
+		.name = "Esmart0-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.base = 0x1800,
+		.possible_vp_mask = BIT(0) | BIT(2),
+		.formats = formats_rk3576_esmart,
+		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
 		.format_modifiers = format_modifiers,
-		.base = 0x1e00,
-		.layer_sel_id = { 7, 7, 7, 0xf },
+		.layer_sel_id = { 2, 0xf, 0, 0xf },
 		.supported_rotations = DRM_MODE_REFLECT_Y,
-		.type = DRM_PLANE_TYPE_PRIMARY,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.axi_bus_id = 0,
+		.axi_yrgb_r_id = 0x10,
+		.axi_uv_r_id = 0x11,
 		.max_upscale_factor = 8,
 		.max_downscale_factor = 8,
-		.dly = { 20, 47, 41 },
 	}, {
 		.name = "Esmart1-win0",
 		.phys_id = ROCKCHIP_VOP2_ESMART1,
-		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
-		.formats = formats_rk356x_esmart,
-		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
-		.format_modifiers = format_modifiers,
 		.base = 0x1a00,
-		.layer_sel_id = { 6, 6, 6, 0xf },
+		.possible_vp_mask = BIT(1) | BIT(2),
+		.formats = formats_rk3576_esmart,
+		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
+		.format_modifiers = format_modifiers,
+		.layer_sel_id = { 0xf, 2, 1, 0xf },
 		.supported_rotations = DRM_MODE_REFLECT_Y,
-		.type = DRM_PLANE_TYPE_PRIMARY,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.axi_bus_id = 0,
+		.axi_yrgb_r_id = 0x12,
+		.axi_uv_r_id = 0x13,
 		.max_upscale_factor = 8,
 		.max_downscale_factor = 8,
-		.dly = { 20, 47, 41 },
 	}, {
-		.name = "Esmart0-win0",
-		.phys_id = ROCKCHIP_VOP2_ESMART0,
-		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
-		.formats = formats_rk356x_esmart,
-		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
+		.name = "Esmart2-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART2,
+		.base = 0x1c00,
+		.possible_vp_mask = BIT(0) | BIT(2),
+		.formats = formats_rk3576_esmart,
+		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
 		.format_modifiers = format_modifiers,
-		.base = 0x1800,
-		.layer_sel_id = { 2, 2, 2, 0xf },
+		.layer_sel_id = { 3, 0xf, 2, 0xf },
 		.supported_rotations = DRM_MODE_REFLECT_Y,
-		.type = DRM_PLANE_TYPE_PRIMARY,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.axi_bus_id = 1,
+		.axi_yrgb_r_id = 0x0a,
+		.axi_uv_r_id = 0x0b,
 		.max_upscale_factor = 8,
 		.max_downscale_factor = 8,
-		.dly = { 20, 47, 41 },
 	}, {
-		.name = "Cluster0-win0",
-		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
-		.base = 0x1000,
-		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
-		.formats = formats_cluster,
-		.nformats = ARRAY_SIZE(formats_cluster),
-		.format_modifiers = format_modifiers_afbc,
-		.layer_sel_id = { 0, 0, 0, 0xf },
-		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
-					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
-		.max_upscale_factor = 4,
-		.max_downscale_factor = 4,
-		.dly = { 0, 27, 21 },
-		.type = DRM_PLANE_TYPE_OVERLAY,
-		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
-	}, {
-		.name = "Cluster1-win0",
-		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
-		.base = 0x1200,
-		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
-		.formats = formats_cluster,
-		.nformats = ARRAY_SIZE(formats_cluster),
-		.format_modifiers = format_modifiers_afbc,
-		.layer_sel_id = { 1, 1, 1, 0xf },
-		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
-					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.name = "Esmart3-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART3,
+		.base = 0x1e00,
+		.possible_vp_mask = BIT(1) | BIT(2),
+		.formats = formats_rk3576_esmart,
+		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
+		.format_modifiers = format_modifiers,
+		.layer_sel_id = { 0xf, 3, 3, 0xf },
+		.supported_rotations = DRM_MODE_REFLECT_Y,
 		.type = DRM_PLANE_TYPE_OVERLAY,
-		.max_upscale_factor = 4,
-		.max_downscale_factor = 4,
-		.dly = { 0, 27, 21 },
-		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
+		.axi_bus_id = 1,
+		.axi_yrgb_r_id = 0x0c,
+		.axi_uv_r_id = 0x0d,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
 	},
 };
 
-static const struct vop2_regs_dump rk3568_regs_dump[] = {
+static const struct vop2_regs_dump rk3576_regs_dump[] = {
 	{
 		.name = "SYS",
 		.base = RK3568_REG_CFG_DONE,
-		.size = 0x100,
+		.size = 0x200,
 		.en_reg  = 0,
 		.en_val = 0,
 		.en_mask = 0
 	}, {
-		.name = "OVL",
-		.base = RK3568_OVL_CTRL,
-		.size = 0x100,
+		.name = "OVL_SYS",
+		.base = RK3576_SYS_EXTRA_ALPHA_CTRL,
+		.size = 0x50,
+		.en_reg = 0,
+		.en_val = 0,
+		.en_mask = 0,
+	}, {
+		.name = "OVL_VP0",
+		.base = RK3576_OVL_CTRL(0),
+		.size = 0x80,
+		.en_reg = 0,
+		.en_val = 0,
+		.en_mask = 0,
+	}, {
+		.name = "OVL_VP1",
+		.base = RK3576_OVL_CTRL(1),
+		.size = 0x80,
+		.en_reg = 0,
+		.en_val = 0,
+		.en_mask = 0,
+	}, {
+		.name = "OVL_VP2",
+		.base = RK3576_OVL_CTRL(2),
+		.size = 0x80,
 		.en_reg = 0,
 		.en_val = 0,
 		.en_mask = 0,
@@ -471,18 +1007,17 @@ static const struct vop2_regs_dump rk3568_regs_dump[] = {
 		.en_reg = RK3568_VP_DSP_CTRL,
 		.en_val = 0,
 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
-
 	}, {
 		.name = "Cluster0",
 		.base = RK3568_CLUSTER0_CTRL_BASE,
-		.size = 0x110,
+		.size = 0x200,
 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
 	}, {
 		.name = "Cluster1",
 		.base = RK3568_CLUSTER1_CTRL_BASE,
-		.size = 0x110,
+		.size = 0x200,
 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
@@ -501,15 +1036,15 @@ static const struct vop2_regs_dump rk3568_regs_dump[] = {
 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
 	}, {
-		.name = "Smart0",
-		.base = RK3568_SMART0_CTRL_BASE,
+		.name = "Esmart2",
+		.base = RK3588_ESMART2_CTRL_BASE,
 		.size = 0xf0,
 		.en_reg = RK3568_SMART_REGION0_CTRL,
 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
 	}, {
-		.name = "Smart1",
-		.base = RK3568_SMART1_CTRL_BASE,
+		.name = "Esmart3",
+		.base = RK3588_ESMART3_CTRL_BASE,
 		.size = 0xf0,
 		.en_reg = RK3568_SMART_REGION0_CTRL,
 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
@@ -908,6 +1443,84 @@ static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32
 	return crtc->state->adjusted_mode.crtc_clock  * 1000LL;
 }
 
+static unsigned long rk3576_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	u8 port_pix_rate = vp->data->pixel_rate;
+	int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_sel;
+	u32 ctrl, vp_clk_div, reg, dclk_div;
+	unsigned long dclk_in_rate, dclk_core_rate;
+
+	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 || adjusted_mode->crtc_clock > 600000)
+		dclk_div = 2;
+	else
+		dclk_div = 1;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
+		dclk_core_rate = adjusted_mode->crtc_clock / 2;
+	else
+		dclk_core_rate = adjusted_mode->crtc_clock / port_pix_rate;
+
+	dclk_in_rate = adjusted_mode->crtc_clock / dclk_div;
+
+	dclk_core_div = dclk_in_rate > dclk_core_rate ? 1 : 0;
+
+	if (vop2_output_if_is_edp(id))
+		if_pixclk_div = port_pix_rate == 2 ? RK3576_DSP_IF_PCLK_DIV : 0;
+	else
+		if_pixclk_div = port_pix_rate == 1 ? RK3576_DSP_IF_PCLK_DIV : 0;
+
+	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
+		if_dclk_sel = RK3576_DSP_IF_DCLK_SEL_OUT;
+		dclk_out_div = 1;
+	} else {
+		if_dclk_sel = 0;
+		dclk_out_div = 0;
+	}
+
+	switch (id) {
+	case ROCKCHIP_VOP2_EP_HDMI0:
+		reg = RK3576_HDMI0_IF_CTRL;
+		break;
+	case ROCKCHIP_VOP2_EP_EDP0:
+		reg = RK3576_EDP0_IF_CTRL;
+		break;
+	case ROCKCHIP_VOP2_EP_MIPI0:
+		reg = RK3576_MIPI0_IF_CTRL;
+		break;
+	case ROCKCHIP_VOP2_EP_DP0:
+		reg = RK3576_DP0_IF_CTRL;
+		break;
+	case ROCKCHIP_VOP2_EP_DP1:
+		reg = RK3576_DP1_IF_CTRL;
+		break;
+	default:
+		drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
+		return 0;
+	}
+
+	ctrl = vop2_readl(vop2, reg);
+	ctrl &= ~RK3576_DSP_IF_DCLK_SEL_OUT;
+	ctrl &= ~RK3576_DSP_IF_PCLK_DIV;
+	ctrl &= ~RK3576_DSP_IF_MUX;
+	ctrl |= RK3576_DSP_IF_CFG_DONE_IMD;
+	ctrl |= if_dclk_sel | if_pixclk_div;
+	ctrl |= RK3576_DSP_IF_CLK_OUT_EN | RK3576_DSP_IF_EN;
+	ctrl |= FIELD_PREP(RK3576_DSP_IF_MUX, vp->id);
+	ctrl |= FIELD_PREP(RK3576_DSP_IF_PIN_POL, polflags);
+	vop2_writel(vop2, reg, ctrl);
+
+	vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
+	vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
+
+	vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
+
+	return dclk_in_rate * 1000LL;
+}
+
 /*
  * calc the dclk on rk3588
  * the available div of dclk is 1, 2, 4
@@ -1246,6 +1859,7 @@ static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_wi
 	struct drm_plane_state *bottom_win_pstate;
 	bool src_pixel_alpha_en = false;
 	u16 src_glb_alpha_val, dst_glb_alpha_val;
+	u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
 	u32 offset = 0;
 	bool premulti_en = false;
 	bool swap = false;
@@ -1283,14 +1897,22 @@ static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_wi
 		break;
 	}
 
-	vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset,
-		    alpha.src_color_ctrl.val);
-	vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset,
-		    alpha.dst_color_ctrl.val);
-	vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset,
-		    alpha.src_alpha_ctrl.val);
-	vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset,
-		    alpha.dst_alpha_ctrl.val);
+	if (vop2->version <= VOP_VERSION_RK3588) {
+		src_color_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL;
+		dst_color_ctrl_reg = RK3568_CLUSTER0_MIX_DST_COLOR_CTRL;
+		src_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL;
+		dst_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL;
+	} else {
+		src_color_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL;
+		dst_color_ctrl_reg = RK3576_CLUSTER0_MIX_DST_COLOR_CTRL;
+		src_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL;
+		dst_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL;
+	}
+
+	vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
+	vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
+	vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
+	vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
 }
 
 static void vop2_setup_alpha(struct vop2_video_port *vp)
@@ -1303,11 +1925,16 @@ static void vop2_setup_alpha(struct vop2_video_port *vp)
 	int pixel_alpha_en;
 	int premulti_en, gpremulti_en = 0;
 	int mixer_id;
+	u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
 	u32 offset;
 	bool bottom_layer_alpha_en = false;
 	u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE;
 
-	mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
+	if (vop2->version <= VOP_VERSION_RK3588)
+		mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
+	else
+		mixer_id = 0;
+
 	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
 
 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
@@ -1326,6 +1953,18 @@ static void vop2_setup_alpha(struct vop2_video_port *vp)
 		}
 	}
 
+	if (vop2->version <= VOP_VERSION_RK3588) {
+		src_color_ctrl_reg = RK3568_MIX0_SRC_COLOR_CTRL;
+		dst_color_ctrl_reg = RK3568_MIX0_DST_COLOR_CTRL;
+		src_alpha_ctrl_reg = RK3568_MIX0_SRC_ALPHA_CTRL;
+		dst_alpha_ctrl_reg = RK3568_MIX0_DST_ALPHA_CTRL;
+	} else {
+		src_color_ctrl_reg = RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp->id);
+		dst_color_ctrl_reg = RK3576_OVL_MIX0_DST_COLOR_CTRL(vp->id);
+		src_alpha_ctrl_reg = RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp->id);
+		dst_alpha_ctrl_reg = RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp->id);
+	}
+
 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
 		struct vop2_win *win = to_vop2_win(plane);
 		int zpos = plane->state->normalized_zpos;
@@ -1372,17 +2011,26 @@ static void vop2_setup_alpha(struct vop2_video_port *vp)
 		vop2_parse_alpha(&alpha_config, &alpha);
 
 		offset = (mixer_id + zpos - 1) * 0x10;
-		vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset,
-			    alpha.src_color_ctrl.val);
-		vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset,
-			    alpha.dst_color_ctrl.val);
-		vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset,
-			    alpha.src_alpha_ctrl.val);
-		vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset,
-			    alpha.dst_alpha_ctrl.val);
+
+		vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
 	}
 
 	if (vp->id == 0) {
+		if (vop2->version <= VOP_VERSION_RK3588) {
+			src_color_ctrl_reg = RK3568_HDR0_SRC_COLOR_CTRL;
+			dst_color_ctrl_reg = RK3568_HDR0_DST_COLOR_CTRL;
+			src_alpha_ctrl_reg = RK3568_HDR0_SRC_ALPHA_CTRL;
+			dst_alpha_ctrl_reg = RK3568_HDR0_DST_ALPHA_CTRL;
+		} else {
+			src_color_ctrl_reg = RK3576_OVL_HDR_SRC_COLOR_CTRL(vp->id);
+			dst_color_ctrl_reg = RK3576_OVL_HDR_DST_COLOR_CTRL(vp->id);
+			src_alpha_ctrl_reg = RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp->id);
+			dst_alpha_ctrl_reg = RK3576_OVL_HDR_DST_ALPHA_CTRL(vp->id);
+		}
+
 		if (bottom_layer_alpha_en) {
 			/* Transfer pixel alpha to hdr mix */
 			alpha_config.src_premulti_en = gpremulti_en;
@@ -1390,18 +2038,15 @@ static void vop2_setup_alpha(struct vop2_video_port *vp)
 			alpha_config.src_pixel_alpha_en = true;
 			alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
 			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
+
 			vop2_parse_alpha(&alpha_config, &alpha);
 
-			vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL,
-				    alpha.src_color_ctrl.val);
-			vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL,
-				    alpha.dst_color_ctrl.val);
-			vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL,
-				    alpha.src_alpha_ctrl.val);
-			vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL,
-				    alpha.dst_alpha_ctrl.val);
+			vop2_writel(vop2, src_color_ctrl_reg, alpha.src_color_ctrl.val);
+			vop2_writel(vop2, dst_color_ctrl_reg, alpha.dst_color_ctrl.val);
+			vop2_writel(vop2, src_alpha_ctrl_reg, alpha.src_alpha_ctrl.val);
+			vop2_writel(vop2, dst_alpha_ctrl_reg, alpha.dst_alpha_ctrl.val);
 		} else {
-			vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0);
+			vop2_writel(vop2, src_color_ctrl_reg, 0);
 		}
 	}
 }
@@ -1611,6 +2256,71 @@ static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp)
 	rk3568_vop2_setup_dly_for_windows(vp);
 }
 
+static void rk3576_vop2_setup_layer_mixer(struct vop2_video_port *vp)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	u32 layer_sel = 0xffff; /* 0xf means this layer is disabled */
+	u32 ovl_ctrl;
+
+	ovl_ctrl = vop2_readl(vop2, RK3576_OVL_CTRL(vp->id));
+	if (vcstate->yuv_overlay)
+		ovl_ctrl |= RK3576_OVL_CTRL__YUV_MODE;
+	else
+		ovl_ctrl &= ~RK3576_OVL_CTRL__YUV_MODE;
+
+	vop2_writel(vop2, RK3576_OVL_CTRL(vp->id), ovl_ctrl);
+
+	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
+							  0xf);
+		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
+							 win->data->layer_sel_id[vp->id]);
+	}
+
+	vop2_writel(vop2, RK3576_OVL_LAYER_SEL(vp->id), layer_sel);
+}
+
+static void rk3576_vop2_setup_dly_for_windows(struct vop2_video_port *vp)
+{
+	struct drm_plane *plane;
+	struct vop2_win *win;
+
+	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
+		win = to_vop2_win(plane);
+		vop2_win_write(win, VOP2_WIN_DLY_NUM, 0);
+	}
+}
+
+static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_plane *plane;
+
+	vp->win_mask = 0;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
+		vp->win_mask |= BIT(win->data->phys_id);
+
+		if (vop2_cluster_window(win))
+			vop2_setup_cluster_alpha(vop2, win);
+	}
+
+	if (!vp->win_mask)
+		return;
+
+	rk3576_vop2_setup_layer_mixer(vp);
+	vop2_setup_alpha(vp);
+	rk3576_vop2_setup_dly_for_windows(vp);
+}
+
 static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp)
 {
 	struct drm_crtc *crtc = &vp->crtc;
@@ -1628,12 +2338,38 @@ static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp)
 	vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
 }
 
+static void rk3576_vop2_setup_bg_dly(struct vop2_video_port *vp)
+{
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	u16 hdisplay = mode->crtc_hdisplay;
+	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	u32 bg_dly;
+	u32 pre_scan_dly;
+
+	bg_dly = vp->data->pre_scan_max_dly[VOP2_DLY_WIN] +
+		 vp->data->pre_scan_max_dly[VOP2_DLY_LAYER_MIX] +
+		 vp->data->pre_scan_max_dly[VOP2_DLY_HDR_MIX];
+
+	vop2_writel(vp->vop2, RK3576_OVL_BG_MIX_CTRL(vp->id),
+		    FIELD_PREP(RK3576_OVL_BG_MIX_CTRL__BG_DLY, bg_dly));
+
+	pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
+	vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
+}
+
 static const struct vop2_ops rk3568_vop_ops = {
 	.setup_intf_mux = rk3568_set_intf_mux,
 	.setup_bg_dly = rk3568_vop2_setup_bg_dly,
 	.setup_overlay = rk3568_vop2_setup_overlay,
 };
 
+static const struct vop2_ops rk3576_vop_ops = {
+	.setup_intf_mux = rk3576_set_intf_mux,
+	.setup_bg_dly = rk3576_vop2_setup_bg_dly,
+	.setup_overlay = rk3576_vop2_setup_overlay,
+};
+
 static const struct vop2_ops rk3588_vop_ops = {
 	.setup_intf_mux = rk3588_set_intf_mux,
 	.setup_bg_dly = rk3568_vop2_setup_bg_dly,
@@ -1678,6 +2414,25 @@ static const struct vop2_data rk3568_vop = {
 	.soc_id = 3568,
 };
 
+static const struct vop2_data rk3576_vop = {
+	.version = VOP_VERSION_RK3576,
+	.feature = VOP2_FEATURE_HAS_SYS_PMU,
+	.nr_vps = 3,
+	.max_input = { 4096, 4320 },
+	.max_output = { 4096, 4320 },
+	.vp = rk3576_vop_video_ports,
+	.win = rk3576_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3576_vop_win_data),
+	.cluster_reg = rk3576_vop_cluster_regs,
+	.nr_cluster_regs = ARRAY_SIZE(rk3576_vop_cluster_regs),
+	.smart_reg = rk3576_vop_smart_regs,
+	.nr_smart_regs = ARRAY_SIZE(rk3576_vop_smart_regs),
+	.regs_dump = rk3576_regs_dump,
+	.regs_dump_size = ARRAY_SIZE(rk3576_regs_dump),
+	.ops = &rk3576_vop_ops,
+	.soc_id = 3576,
+};
+
 static const struct vop2_data rk3588_vop = {
 	.version = VOP_VERSION_RK3588,
 	.feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |
@@ -1705,6 +2460,9 @@ static const struct of_device_id vop2_dt_match[] = {
 	}, {
 		.compatible = "rockchip,rk3568-vop",
 		.data = &rk3568_vop,
+	}, {
+		.compatible = "rockchip,rk3576-vop",
+		.data = &rk3576_vop,
 	}, {
 		.compatible = "rockchip,rk3588-vop",
 		.data = &rk3588_vop
-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:21 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:21 +0800
Subject: [PATCH v15 00/10] Coresight: Add Coresight TMC Control Unit driver
Message-ID: <20250303032931.2500935-1-quic_jiegan@quicinc.com>

From: Jie Gan <jie.gan at oss.qualcomm.com>

The Coresight TMC Control Unit(CTCU) device hosts miscellaneous configuration
registers to control various features related to TMC ETR device.

The CTCU device works as a helper device physically connected to the TMC ETR device.
---------------------------------------------------------
             |ETR0|             |ETR1|
              . \                 / .
              .  \               /  .
              .   \             /   .
              .    \           /    .
---------------------------------------------------
ETR0ATID0-ETR0ATID3     CTCU    ETR1ATID0-ETR1ATID3
---------------------------------------------------
Each ETR has four ATID registers with 128 bits long in total.
e.g. ETR0ATID0-ETR0ATID3 registers are used by ETR0 device.

Based on the trace id which is programed in CTCU ATID register of
specific ETR, trace data with that trace id can get into ETR's buffer
while other trace data gets ignored. The number of CTCU ATID registers
depends on the number of defined TMC ETR devices. For example, two TMC
ETR devices need eight ATID registers. ETR0 with ETR0ATID0-ETR0ATID3
and ETR1 with ETR1ATID0-ETRATID3.

The significant challenge in enabling the data filter function is how
to collect the trace ID of the source device. The introduction of
trace_id callback function addresses this challenge. The callback function
collects trace ID of the device and return it back. The trace ID will be
stored in the structure called coresight_path and transmitted to helper
and sink devices.

The coresight_path structure is created to address how to transmit
parameters needs by coresight_enable_path/coresight_disbale_path
functions.

Here is the definition of the struct coresight_path:
/**
 * struct coresight_path - data needed by enable/disable path
 * @path:               path from source to sink.
 * @trace_id:           trace_id of the whole path.
 */
struct coresight_path {
        struct list_head                path;
        u8                              trace_id;
};

The atid_offset mentioned before is the offset to ATID register in CTCU
device.

Enabling the source device will configure one bit in the ATID register based
on its trace ID.
Disabling the source devices will reset the bit in the AITD register
based on its trace ID.

Useage:
Enable:
STM device with trace ID 5 and ETR0 is activated.
Bitmap before the enablement:
ETR0ATID0:
31..................543210
==========================
0000000000000000000000...0
==========================

Bitmap after the enablement:
31..................543210
==========================
0000000000000...0000100000
==========================

The bit 5 of the ETR0ATID0 register is configured to 1 when enabling the
STM device.

Disable:
STM device with trace ID 5 and ETR0 is activated.
Bitmap before the disablement:
ETR0ATID0:
31................6543210
=========================
000000000010111...0100000
=========================

Bitmap after the disablement
ETR0ATID0:
31................6543210
=========================
000000000010111...0000000
=========================

The bit 5 of the ETR0ATID0 register is reset to 0 when disabling the STM
device.

Sincere thanks to James Clark for providing an excellent idea to handle
the trace_id of the path.

---
Changes in V15:
1. Rebased on tag: next-20250228.
2. Optimize patch(2/10), add check process before using sink.
Link to V14 - https://lore.kernel.org/all/20250226041342.53933-1-quic_jiegan at quicinc.com/
---

---
Changes in V14:
1. Drop the reviewed-by tag for previous patch: Coresight-Introduce-a-new-struct-coresight_path
   due to a massive modification.
2. Split the patch, Coresight-Introduce-a-new-struct-coresight_path, into
   four patches.
   - Coresight-Introduce-a-new-struct-coresight_path
   - Coresight-Allocate-trace-ID-after-building-the-path
   - Coresight-Change-to-read-the-trace-ID-from-coresight_path
   - Coresight-Change-functions-to-accept-the-coresight_path
3. Change the type of the coresight_path_assign_trace_id function to void.
4. Change the type of the path_list from struct list_head * to struct list_head to avoid
   extra memory allocate/free.
5. Rename the file coresight-ctcu.c to coresight-ctcu-core.c to improve scalibility.
6. Add pm_ops for CTCU driver.
7. Rename the struct ctcu_atid_config to ctcu_etr_config to improve scalibility.
8. Optimize following functions of the CTCU driver to improve readability.
   - ctcu_program_atid_register
   - __ctcu_set_etr_traceid
9. Change the way to get the port number. The new solution is searching
   the sink device from CTCU's view.
10. Add desc.access for CTCU driver.
Link to V13 - https://lore.kernel.org/linux-arm-msm/20250221060543.2898845-1-quic_jiegan at quicinc.com/
---

---
Changes in V13:
1. Move the trace_id callback to coresight_ops to simplify the code.
Link to V12 - https://lore.kernel.org/linux-arm-msm/20250217093024.1133096-1-quic_jiegan at quicinc.com/
---

---
Changes in V12:
1. Update the method for allocating trace_id for perf mode.
Link to V11 - https://lore.kernel.org/linux-arm-msm/20250214024021.249655-1-quic_jiegan at quicinc.com/
---

---
Changes in V11:
1. Add reviewed-by tag to patch(2/7), (4/7), (6/7). Patch(3/7) is
   contributed by James, so didnot add reviewed-by tag of James.
2. Fix warning reported by kernel bot and verified with build(W=1).
3. Restore to the original logic that responsible for allocate trace_id
   of ETM device in perf mode according to James' comment.
Link to V10 - https://lore.kernel.org/linux-arm-msm/20250207064213.2314482-1-quic_jiegan at quicinc.com/
---

---
Changes in V10:
1. Introduce a new API to allocate and read trace_id after path is built.
2. Introduce a new API to allocate and read trace_id of ETM device.
3. Add a new patch: [PATCH v10 3/7] Coresight: Use coresight_etm_get_trace_id() in traceid_show()
4. Remove perf handle from coresight_path.
5. Use u8 instead of atomic_t for traceid_refcnt.
6. Optimize the part of code in CTCU drvier that is responsible for program atid register.
Link to V9 - https://lore.kernel.org/all/20250124072537.1801030-1-quic_jiegan at quicinc.com/

Changes in V9:
1. Rebased on tag next-20250113.
2. Separate the previous trace_id patch (patch 2/5 Coresight: Add trace_id function to
   retrieving the trace ID) into two patches.
3. Introduce a new struct coresight_path instead of cs_sink_data which was
   created in previous version. The coresight_path will be initialized
   and constructed in coresight_build_path function and released by
   coresight_release_path function.
   Detail of the struct coresight_path is shown below:
/**
 * struct coresight_path - data needed by enable/disable path
 * @path:               path from source to sink.
 * @trace_id:           trace_id of the whole path.
 */
struct coresight_path {
        struct list_head                *path;
        u8                              trace_id;
};

4. Introduce an array of atomic in CTCU driver to represent the refcnt or each
   enabled trace_id for each sink. The reason is there is a scenario that more
   than one TPDM device physically connected to the same TPDA device has
   been enabled. The CTCU driver must verify the refcnt before resetting the
   bit of the atid register according to the trace_id of the TPDA device.
5. Remove redundant codes in CTCU driver.
6. Add reviewed-by tag to the commit message for APB clock path(patch
   1/5).
Link to V8 - https://lore.kernel.org/all/20241226011022.1477160-1-quic_jiegan at quicinc.com/

Changes in V8:
1. Rebased on tag next-20241220.
2. Use raw_spinlock_t instead of spinlock_t.
3. Remove redundant codes in CTCU driver:
   - Eliminate unnecessary parameter validations.
   - Correct log level when an error occurs.
   - Optimize codes.
4. Correct the subject prefix for DT patch.
5. Collected reviewed-by tag from Konrad Dybcib for DT patch.
Link to V7 - https://lore.kernel.org/all/20241210031545.3468561-1-quic_jiegan at quicinc.com/

Changes in V7:
1. Rebased on tag next-20241204.
2. Fix format issue for dts patch.
   - Padding the address part to 8 digits
Link to V6 - https://lore.kernel.org/linux-arm-msm/20241009112503.1851585-1-quic_jiegan at quicinc.com/

Changes in V6:
1. Collected reviewed-by tag from Rob for dt-binding patch.
2. Rebased on tag next-20241008.
3. Dropped all depends-on tags.
Link to V5 - https://lore.kernel.org/linux-arm-msm/20240909033458.3118238-1-quic_jiegan at quicinc.com/

Changes in V5:
1. Fix the format issue for description paragrah in dt binding file.
2. Previous discussion for why use "in-ports" property instead of "ports".
Link to V4 - https://lore.kernel.org/linux-arm-msm/20240828012706.543605-1-quic_jiegan at quicinc.com/

Changes in V4:
1. Add TMC description in binding file.
2. Restrict the number of ports for the CTCU device to a range of 0 to 1 in the binding file,
   because the maximum number of CTCU devices is 2 for existing projects.
Link to V3 - https://lore.kernel.org/linux-arm-kernel/20240812024141.2867655-1-quic_jiegan at quicinc.com/

Changes in V3:
1. Rename the device to Coresight TMC Control Unit(CTCU).
2. Introduce a new way to define the platform related configs. The new
   structure, qcom_ctcu_config, is used to store configurations specific
   to a platform. Each platform should have its own qcom_ctcu_config structure.
3. In perf mode, the ETM devices allocate their trace IDs using the
   perf_sink_id_map. In sysfs mode, the ETM devices allocate their trace
   IDs using the id_map_default.
4. Considering the scenario where both ETR devices might be enabled simultaneously
   with multiple sources, retrieving and using trace IDs instead of id_map is more effective
   for the CTCU device in sysfs mode. For example, We can configure one ETR as sink for high
   throughput trace data like ETM and another ETR for low throughput trace data like STM.
   In this case, STM data won?t be flushed out by ETM data quickly. However, if we use id_map to
   manage the trace IDs, we need to create a separate id_map for each ETR device. Addtionally, We
   would need to iterate through the entire id_map for each configuration.
5. Add support for apb's clock name "apb". If the function fails to obtain the clock with
   the name "apb_pclk", it will attempt to acquire the clock with the name "apb".
Link to V2 - https://lore.kernel.org/linux-arm-msm/20240705090049.1656986-1-quic_jiegan at quicinc.com/T/#t

Changes in V2:
1. Rename the device to Coresight Control Unit.
2. Introduce the trace_id function pointer to address the challeng how to
   properly collect the trace ID of the device.
3. Introduce a new way to define the qcom,ccu-atid-offset property in
device tree.
4. Disabling the filter function blocked on acquiring the ATID-offset,
   which will be addressed in a separate patch once it?s ready.
Link to V1 - https://lore.kernel.org/lkml/20240618072726.3767974-1-quic_jiegan at quicinc.com/T/#t
---

James Clark (1):
  Coresight: Use coresight_etm_get_trace_id() in traceid_show()

Jie Gan (9):
  Coresight: Add support for new APB clock name
  Coresight: Add trace_id function to retrieving the trace ID
  Coresight: Introduce a new struct coresight_path
  Coresight: Allocate trace ID after building the path
  Coresight: Change to read the trace ID from coresight_path
  Coresight: Change functions to accept the coresight_path
  dt-bindings: arm: Add Coresight TMC Control Unit hardware
  Coresight: Add Coresight TMC Control Unit driver
  arm64: dts: qcom: sa8775p: Add CTCU and ETR nodes

 .../bindings/arm/qcom,coresight-ctcu.yaml     |  84 +++++
 arch/arm64/boot/dts/qcom/sa8775p.dtsi         | 153 ++++++++
 drivers/hwtracing/coresight/Kconfig           |  12 +
 drivers/hwtracing/coresight/Makefile          |   2 +
 drivers/hwtracing/coresight/coresight-core.c  | 125 +++++--
 .../hwtracing/coresight/coresight-ctcu-core.c | 326 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-ctcu.h  |  39 +++
 drivers/hwtracing/coresight/coresight-dummy.c |  15 +-
 .../hwtracing/coresight/coresight-etm-perf.c  |  27 +-
 .../hwtracing/coresight/coresight-etm-perf.h  |   2 +-
 drivers/hwtracing/coresight/coresight-etm.h   |   1 -
 .../coresight/coresight-etm3x-core.c          |  55 +--
 .../coresight/coresight-etm3x-sysfs.c         |   3 +-
 .../coresight/coresight-etm4x-core.c          |  55 +--
 .../coresight/coresight-etm4x-sysfs.c         |   4 +-
 drivers/hwtracing/coresight/coresight-etm4x.h |   1 -
 drivers/hwtracing/coresight/coresight-priv.h  |  14 +-
 drivers/hwtracing/coresight/coresight-stm.c   |  13 +-
 drivers/hwtracing/coresight/coresight-sysfs.c |  17 +-
 drivers/hwtracing/coresight/coresight-tpda.c  |  11 +
 drivers/hwtracing/coresight/coresight-tpdm.c  |   2 +-
 include/linux/coresight.h                     |  27 +-
 22 files changed, 827 insertions(+), 161 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-core.c
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu.h

-- 
2.34.1



From quic_jiegan at quicinc.com  Sun Mar  2 19:29:22 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 3 Mar 2025 11:29:22 +0800
Subject: [PATCH v15 01/10] Coresight: Add support for new APB clock name
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <20250303032931.2500935-2-quic_jiegan@quicinc.com>

Add support for new APB clock-name. If the function fails
to obtain the clock with the name "apb_pclk", it will
attempt to acquire the clock with the name "apb".

Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 include/linux/coresight.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 3eef4e91df3f..c7cd5886c908 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -471,8 +471,11 @@ static inline struct clk *coresight_get_enable_apb_pclk(struct device *dev)
 	int ret;
 
 	pclk = clk_get(dev, "apb_pclk");
-	if (IS_ERR(pclk))
-		return NULL;
+	if (IS_ERR(pclk)) {
+		pclk = clk_get(dev, "apb");
+		if (IS_ERR(pclk))
+			return NULL;
+	}
 
 	ret = clk_prepare_enable(pclk);
 	if (ret) {
-- 
2.34.1



From gshan at redhat.com  Sun Mar  2 19:58:31 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 13:58:31 +1000
Subject: [PATCH v7 06/45] arm64: RME: Check for RME support at KVM init
In-Reply-To: <20250213161426.102987-7-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-7-steven.price@arm.com>
Message-ID: <f3b31f6e-7960-432b-a522-3ec5f5ac7c6f@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> Query the RMI version number and check if it is a compatible version. A
> static key is also provided to signal that a supported RMM is available.
> 
> Functions are provided to query if a VM or VCPU is a realm (or rec)
> which currently will always return false.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Improved message for an unsupported RMI ABI version.
> Changes since v5:
>   * Reword "unsupported" message from "host supports" to "we want" to
>     clarify that 'we' are the 'host'.
> Changes since v2:
>   * Drop return value from kvm_init_rme(), it was always 0.
>   * Rely on the RMM return value to identify whether the RSI ABI is
>     compatible.
> ---
>   arch/arm64/include/asm/kvm_emulate.h | 18 +++++++++
>   arch/arm64/include/asm/kvm_host.h    |  4 ++
>   arch/arm64/include/asm/kvm_rme.h     | 56 ++++++++++++++++++++++++++++
>   arch/arm64/include/asm/virt.h        |  1 +
>   arch/arm64/kvm/Makefile              |  3 +-
>   arch/arm64/kvm/arm.c                 |  6 +++
>   arch/arm64/kvm/rme.c                 | 56 ++++++++++++++++++++++++++++
>   7 files changed, 143 insertions(+), 1 deletion(-)
>   create mode 100644 arch/arm64/include/asm/kvm_rme.h
>   create mode 100644 arch/arm64/kvm/rme.c
> 

It may be worthy to add one comments in the change log, something like "struct realm"
and its states aren't used until the ioctl interfaces are revised to support realm
and REC creation and destruction. Otherwise, the definition would belong to that
patch revising the ioctl interface.

With the following nitpick is addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 47f2cf408eed..52c7a8923c65 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -691,4 +691,22 @@ static inline bool guest_hyp_sve_traps_enabled(const struct kvm_vcpu *vcpu)
>   {
>   	return __guest_hyp_cptr_xen_trap_enabled(vcpu, ZEN);
>   }
> +
> +static inline bool kvm_is_realm(struct kvm *kvm)
> +{
> +	if (static_branch_unlikely(&kvm_rme_is_available) && kvm)
> +		return kvm->arch.is_realm;
> +	return false;
> +}
> +
> +static inline enum realm_state kvm_realm_state(struct kvm *kvm)
> +{
> +	return READ_ONCE(kvm->arch.realm.state);
> +}
> +
> +static inline bool vcpu_is_rec(struct kvm_vcpu *vcpu)
> +{
> +	return false;
> +}
> +
>   #endif /* __ARM64_KVM_EMULATE_H__ */
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 7cfa024de4e3..992eb2a6f56f 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -27,6 +27,7 @@
>   #include <asm/fpsimd.h>
>   #include <asm/kvm.h>
>   #include <asm/kvm_asm.h>
> +#include <asm/kvm_rme.h>
>   #include <asm/vncr_mapping.h>
>   
>   #define __KVM_HAVE_ARCH_INTC_INITIALIZED
> @@ -383,6 +384,9 @@ struct kvm_arch {
>   	 * the associated pKVM instance in the hypervisor.
>   	 */
>   	struct kvm_protected_vm pkvm;
> +
> +	bool is_realm;
> +	struct realm realm;
>   };
>   
>   struct kvm_vcpu_fault_info {
> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_rme.h
> new file mode 100644
> index 000000000000..69af5c3a1e44
> --- /dev/null
> +++ b/arch/arm64/include/asm/kvm_rme.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#ifndef __ASM_KVM_RME_H
> +#define __ASM_KVM_RME_H
> +
> +/**
> + * enum realm_state - State of a Realm
> + */
> +enum realm_state {
> +	/**
> +	 * @REALM_STATE_NONE:
> +	 *      Realm has not yet been created. rmi_realm_create() may be
> +	 *      called to create the realm.
> +	 */
> +	REALM_STATE_NONE,
> +	/**
> +	 * @REALM_STATE_NEW:
> +	 *      Realm is under construction, not eligible for execution. Pages
> +	 *      may be populated with rmi_data_create().
> +	 */
> +	REALM_STATE_NEW,
> +	/**
> +	 * @REALM_STATE_ACTIVE:
> +	 *      Realm has been created and is eligible for execution with
> +	 *      rmi_rec_enter(). Pages may no longer be populated with
> +	 *      rmi_data_create().
> +	 */
> +	REALM_STATE_ACTIVE,
> +	/**
> +	 * @REALM_STATE_DYING:
> +	 *      Realm is in the process of being destroyed or has already been
> +	 *      destroyed.
> +	 */
> +	REALM_STATE_DYING,
> +	/**
> +	 * @REALM_STATE_DEAD:
> +	 *      Realm has been destroyed.
> +	 */
> +	REALM_STATE_DEAD
> +};
> +
> +/**
> + * struct realm - Additional per VM data for a Realm
> + *
> + * @state: The lifetime state machine for the realm
> + */
> +struct realm {
> +	enum realm_state state;
> +};
> +
> +void kvm_init_rme(void);
> +
> +#endif

#endif /* __ASM_KVM_RME_H */

> diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> index ebf4a9f943ed..e45d47156dcf 100644
> --- a/arch/arm64/include/asm/virt.h
> +++ b/arch/arm64/include/asm/virt.h
> @@ -81,6 +81,7 @@ void __hyp_reset_vectors(void);
>   bool is_kvm_arm_initialised(void);
>   
>   DECLARE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
> +DECLARE_STATIC_KEY_FALSE(kvm_rme_is_available);
>   
>   static inline bool is_pkvm_initialized(void)
>   {
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 3cf7adb2b503..ce8a10d3161d 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -23,7 +23,8 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
>   	 vgic/vgic-v3.o vgic/vgic-v4.o \
>   	 vgic/vgic-mmio.o vgic/vgic-mmio-v2.o \
>   	 vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \
> -	 vgic/vgic-its.o vgic/vgic-debug.o
> +	 vgic/vgic-its.o vgic/vgic-debug.o \
> +	 rme.o
>   
>   kvm-$(CONFIG_HW_PERF_EVENTS)  += pmu-emul.o pmu.o
>   kvm-$(CONFIG_ARM64_PTR_AUTH)  += pauth.o
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 646e806c6ca6..6d371a2b648a 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -40,6 +40,7 @@
>   #include <asm/kvm_nested.h>
>   #include <asm/kvm_pkvm.h>
>   #include <asm/kvm_ptrauth.h>
> +#include <asm/kvm_rme.h>
>   #include <asm/sections.h>
>   
>   #include <kvm/arm_hypercalls.h>
> @@ -59,6 +60,8 @@ enum kvm_wfx_trap_policy {
>   static enum kvm_wfx_trap_policy kvm_wfi_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
>   static enum kvm_wfx_trap_policy kvm_wfe_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
>   
> +DEFINE_STATIC_KEY_FALSE(kvm_rme_is_available);
> +
>   DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
>   
>   DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_base);
> @@ -2759,6 +2762,9 @@ static __init int kvm_arm_init(void)
>   
>   	in_hyp_mode = is_kernel_in_hyp_mode();
>   
> +	if (in_hyp_mode)
> +		kvm_init_rme();
> +
>   	if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||
>   	    cpus_have_final_cap(ARM64_WORKAROUND_1508412))
>   		kvm_info("Guests without required CPU erratum workarounds can deadlock system!\n" \
> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> new file mode 100644
> index 000000000000..67cf2d94cb2d
> --- /dev/null
> +++ b/arch/arm64/kvm/rme.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#include <linux/kvm_host.h>
> +
> +#include <asm/rmi_cmds.h>
> +#include <asm/virt.h>
> +
> +static int rmi_check_version(void)
> +{
> +	struct arm_smccc_res res;
> +	unsigned short version_major, version_minor;
> +	unsigned long host_version = RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION,
> +						     RMI_ABI_MINOR_VERSION);
> +
> +	arm_smccc_1_1_invoke(SMC_RMI_VERSION, host_version, &res);
> +
> +	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> +		return -ENXIO;
> +
> +	version_major = RMI_ABI_VERSION_GET_MAJOR(res.a1);
> +	version_minor = RMI_ABI_VERSION_GET_MINOR(res.a1);
> +
> +	if (res.a0 != RMI_SUCCESS) {
> +		unsigned short high_version_major, high_version_minor;
> +
> +		high_version_major = RMI_ABI_VERSION_GET_MAJOR(res.a2);
> +		high_version_minor = RMI_ABI_VERSION_GET_MINOR(res.a2);
> +
> +		kvm_err("Unsupported RMI ABI (v%d.%d - v%d.%d) we want v%d.%d\n",
> +			version_major, version_minor,
> +			high_version_major, high_version_minor,
> +			RMI_ABI_MAJOR_VERSION,
> +			RMI_ABI_MINOR_VERSION);
> +		return -ENXIO;
> +	}
> +
> +	kvm_info("RMI ABI version %d.%d\n", version_major, version_minor);
> +
> +	return 0;
> +}
> +
> +void kvm_init_rme(void)
> +{
> +	if (PAGE_SIZE != SZ_4K)
> +		/* Only 4k page size on the host is supported */
> +		return;
> +
> +	if (rmi_check_version())
> +		/* Continue without realm support */
> +		return;
> +
> +	/* Future patch will enable static branch kvm_rme_is_available */
> +}

Thanks,
Gavin



From gshan at redhat.com  Sun Mar  2 20:10:24 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 14:10:24 +1000
Subject: [PATCH v7 07/45] arm64: RME: Define the user ABI
In-Reply-To: <20250213161426.102987-8-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-8-steven.price@arm.com>
Message-ID: <e130dd51-330e-43ef-b86f-41fd96cc9ec3@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> There is one (multiplexed) CAP which can be used to create, populate and
> then activate the realm.
> 
> Co-developed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Rename some of the symbols to make their usage clearer and avoid
>     repetition.
> Changes from v5:
>   * Actually expose the new VCPU capability (KVM_ARM_VCPU_REC) by bumping
>     KVM_VCPU_MAX_FEATURES - note this also exposes KVM_ARM_VCPU_HAS_EL2!
> ---
>   Documentation/virt/kvm/api.rst    |  1 +
>   arch/arm64/include/uapi/asm/kvm.h | 49 +++++++++++++++++++++++++++++++
>   include/uapi/linux/kvm.h          | 12 ++++++++
>   3 files changed, 62 insertions(+)
> 

The newly added ioctl commands need to be documented in Documentation/virt/kvm/api.rst.
Section 4 would be the right place for it. Other than that, it looks good to me except
the ioctl commands need to be fixed as suggested by Aneesh.

Thanks,
Gavin

> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 0d1c3a820ce6..06763d89c0d7 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -5094,6 +5094,7 @@ Recognised values for feature:
>   
>     =====      ===========================================
>     arm64      KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
> +  arm64      KVM_ARM_VCPU_REC (requires KVM_CAP_ARM_RME)
>     =====      ===========================================
>   
>   Finalizes the configuration of the specified vcpu feature.
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 568bf858f319..7eae0b1a482e 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -105,6 +105,7 @@ struct kvm_regs {
>   #define KVM_ARM_VCPU_PTRAUTH_ADDRESS	5 /* VCPU uses address authentication */
>   #define KVM_ARM_VCPU_PTRAUTH_GENERIC	6 /* VCPU uses generic authentication */
>   #define KVM_ARM_VCPU_HAS_EL2		7 /* Support nested virtualization */
> +#define KVM_ARM_VCPU_REC		8 /* VCPU REC state as part of Realm */
>   
>   struct kvm_vcpu_init {
>   	__u32 target;
> @@ -415,6 +416,54 @@ enum {
>   #define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES	3
>   #define   KVM_DEV_ARM_ITS_CTRL_RESET		4
>   
> +/* KVM_CAP_ARM_RME on VM fd */
> +#define KVM_CAP_ARM_RME_CONFIG_REALM		0
> +#define KVM_CAP_ARM_RME_CREATE_REALM		1
> +#define KVM_CAP_ARM_RME_INIT_RIPAS_REALM	2
> +#define KVM_CAP_ARM_RME_POPULATE_REALM		3
> +#define KVM_CAP_ARM_RME_ACTIVATE_REALM		4
> +
> +/* List of configuration items accepted for KVM_CAP_ARM_RME_CONFIG_REALM */
> +#define ARM_RME_CONFIG_RPV			0
> +#define ARM_RME_CONFIG_HASH_ALGO		1
> +
> +#define ARM_RME_CONFIG_MEASUREMENT_ALGO_SHA256		0
> +#define ARM_RME_CONFIG_MEASUREMENT_ALGO_SHA512		1
> +
> +#define ARM_RME_CONFIG_RPV_SIZE 64
> +
> +struct arm_rme_config {
> +	__u32 cfg;
> +	union {
> +		/* cfg == ARM_RME_CONFIG_RPV */
> +		struct {
> +			__u8	rpv[ARM_RME_CONFIG_RPV_SIZE];
> +		};
> +
> +		/* cfg == ARM_RME_CONFIG_HASH_ALGO */
> +		struct {
> +			__u32	hash_algo;
> +		};
> +
> +		/* Fix the size of the union */
> +		__u8	reserved[256];
> +	};
> +};
> +
> +#define KVM_ARM_RME_POPULATE_FLAGS_MEASURE	(1 << 0)
> +struct arm_rme_populate_realm {
> +	__u64 base;
> +	__u64 size;
> +	__u32 flags;
> +	__u32 reserved[3];
> +};
> +
> +struct arm_rme_init_ripas {
> +	__u64 base;
> +	__u64 size;
> +	__u64 reserved[2];
> +};
> +
>   /* Device Control API on vcpu fd */
>   #define KVM_ARM_VCPU_PMU_V3_CTRL	0
>   #define   KVM_ARM_VCPU_PMU_V3_IRQ	0
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 45e6d8fca9b9..fa8f45029dff 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -930,6 +930,8 @@ struct kvm_enable_cap {
>   #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
>   #define KVM_CAP_X86_GUEST_MODE 238
>   
> +#define KVM_CAP_ARM_RME 300 /* FIXME: Large number to prevent conflicts */
> +
>   struct kvm_irq_routing_irqchip {
>   	__u32 irqchip;
>   	__u32 pin;
> @@ -1581,4 +1583,14 @@ struct kvm_pre_fault_memory {
>   	__u64 padding[5];
>   };
>   
> +/* Available with KVM_CAP_ARM_RME, only for VMs with KVM_VM_TYPE_ARM_REALM  */
> +struct kvm_arm_rmm_psci_complete {
> +	__u64 target_mpidr;
> +	__u32 psci_status;
> +	__u32 padding[3];
> +};
> +
> +/* FIXME: Update nr (0xd2) when merging */
> +#define KVM_ARM_VCPU_RMM_PSCI_COMPLETE	_IOW(KVMIO, 0xd2, struct kvm_arm_rmm_psci_complete)
> +
>   #endif /* __LINUX_KVM_H */



From anshuman.khandual at arm.com  Sun Mar  2 20:18:34 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon,  3 Mar 2025 09:48:34 +0530
Subject: [PATCH] arm64/mm: Create level specific section mappings in map_range()
Message-ID: <20250303041834.2796751-1-anshuman.khandual@arm.com>

Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
section mapping at all page table levels except the last level. This works
fine as the section mapping masks are exactly the same (0x1UL) for all page
table levels.

This will change in the future with D128 page tables that have unique skip
level values (SKL) required for creating section mapping at different page
table levels. Hence use page table level specific section mapping macros
instead of the common PMD_TYPE_SECT.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
This patch applies on 6.14-rc5

PGD_TYPE_SECT for level -1 section map handling has been added for 4K
base pages with 52 bit VA configuration that has 5 page table levels.
In such cases (CONFIG_PGTABLE_LEVELS = 5) early_map_kernel() can call
map_range() eventually with -1 (i.e 4 - CONFIG_PGTABLE_LEVELS) as the
root_level.

 arch/arm64/include/asm/pgtable-hwdef.h |  1 +
 arch/arm64/kernel/pi/map_range.c       | 23 +++++++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index a9136cc551cc..fd0a82e8878c 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -99,6 +99,7 @@
 #define PGD_TYPE_TABLE		(_AT(pgdval_t, 3) << 0)
 #define PGD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
 #define PGD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
+#define PGD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
 #define PGD_TABLE_AF		(_AT(pgdval_t, 1) << 10)	/* Ignored if no FEAT_HAFT */
 #define PGD_TABLE_PXN		(_AT(pgdval_t, 1) << 59)
 #define PGD_TABLE_UXN		(_AT(pgdval_t, 1) << 60)
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..9ea869f5745f 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -44,8 +44,27 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	 * Set the right block/page bits for this level unless we are
 	 * clearing the mapping
 	 */
-	if (protval)
-		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
+	if (protval) {
+		switch (level) {
+		case 3:
+			protval |= PTE_TYPE_PAGE;
+			break;
+		case 2:
+			protval |= PMD_TYPE_SECT;
+			break;
+		case 1:
+			protval |= PUD_TYPE_SECT;
+			break;
+		case 0:
+			protval |= P4D_TYPE_SECT;
+			break;
+		case -1:
+			protval |= PGD_TYPE_SECT;
+			break;
+		default:
+			break;
+		}
+	}
 
 	while (start < end) {
 		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
-- 
2.30.2



From gshan at redhat.com  Sun Mar  2 20:42:04 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 14:42:04 +1000
Subject: [PATCH v7 08/45] arm64: RME: ioctls to create and configure
 realms
In-Reply-To: <20250213161426.102987-9-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-9-steven.price@arm.com>
Message-ID: <3413f278-2507-4bb5-8904-550abe93e459@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> Add the KVM_CAP_ARM_RME_CREATE_RD ioctl to create a realm. This involves
> delegating pages to the RMM to hold the Realm Descriptor (RD) and for
> the base level of the Realm Translation Tables (RTT). A VMID also need
> to be picked, since the RMM has a separate VMID address space a
> dedicated allocator is added for this purpose.
> 
> KVM_CAP_ARM_RME_CONFIG_REALM is provided to allow configuring the realm
> before it is created. Configuration options can be classified as:
> 
>   1. Parameters specific to the Realm stage2 (e.g. IPA Size, vmid, stage2
>      entry level, entry level RTTs, number of RTTs in start level, LPA2)
>      Most of these are not measured by RMM and comes from KVM book
>      keeping.
> 
>   2. Parameters controlling "Arm Architecture features for the VM". (e.g.
>      SVE VL, PMU counters, number of HW BRPs/WPs), configured by the VMM
>      using the "user ID register write" mechanism. These will be
>      supported in the later patches.
> 
>   3. Parameters are not part of the core Arm architecture but defined
>      by the RMM spec (e.g. Hash algorithm for measurement,
>      Personalisation value). These are programmed via
>      KVM_CAP_ARM_RME_CONFIG_REALM.
> 
> For the IPA size there is the possibility that the RMM supports a
> different size to the IPA size supported by KVM for normal guests. At
> the moment the 'normal limit' is exposed by KVM_CAP_ARM_VM_IPA_SIZE and
> the IPA size is configured by the bottom bits of vm_type in
> KVM_CREATE_VM. This means that it isn't easy for the VMM to discover
> what IPA sizes are supported for Realm guests. Since the IPA is part of
> the measurement of the realm guest the current expectation is that the
> VMM will be required to pick the IPA size demanded by attestation and
> therefore simply failing if this isn't available is fine. An option
> would be to expose a new capability ioctl to obtain the RMM's maximum
> IPA size if this is needed in the future.
> 
> Co-developed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Separate RMM RTT calculations from host PAGE_SIZE. This allows the
>     host page size to be larger than 4k while still communicating with an
>     RMM which uses 4k granules.
> Changes since v5:
>   * Introduce free_delegated_granule() to replace many
>     undelegate/free_page() instances and centralise the comment on
>     leaking when the undelegate fails.
>   * Several other minor improvements suggested by reviews - thanks for
>     the feedback!
> Changes since v2:
>   * Improved commit description.
>   * Improved return failures for rmi_check_version().
>   * Clear contents of PGD after it has been undelegated in case the RMM
>     left stale data.
>   * Minor changes to reflect changes in previous patches.
> ---
>   arch/arm64/include/asm/kvm_emulate.h |   5 +
>   arch/arm64/include/asm/kvm_rme.h     |  19 ++
>   arch/arm64/kvm/arm.c                 |  16 ++
>   arch/arm64/kvm/mmu.c                 |  22 +-
>   arch/arm64/kvm/rme.c                 | 322 +++++++++++++++++++++++++++
>   5 files changed, 382 insertions(+), 2 deletions(-)
> 

With below comments addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

[...]

> +
> +static int realm_create_rd(struct kvm *kvm)
> +{
> +	struct realm *realm = &kvm->arch.realm;
> +	struct realm_params *params = realm->params;
> +	void *rd = NULL;
> +	phys_addr_t rd_phys, params_phys;
> +	size_t pgd_size = kvm_pgtable_stage2_pgd_size(kvm->arch.mmu.vtcr);
> +	int i, r;
> +	int rtt_num_start;
> +
> +	realm->ia_bits = VTCR_EL2_IPA(kvm->arch.mmu.vtcr);
> +	rtt_num_start = realm_num_root_rtts(realm);
> +
> +	if (WARN_ON(realm->rd) || WARN_ON(!realm->params))
> +		return -EEXIST;
> +

Two WARN_ON() can be combined into one.

	if (WARN_ON(realm->rd || !realm->param))

> +	if (pgd_size / RMM_PAGE_SIZE < rtt_num_start)
> +		return -EINVAL;
> +
> +	rd = (void *)__get_free_page(GFP_KERNEL);
> +	if (!rd)
> +		return -ENOMEM;
> +
> +	rd_phys = virt_to_phys(rd);
> +	if (rmi_granule_delegate(rd_phys)) {
> +		r = -ENXIO;
> +		goto free_rd;
> +	}
> +
> +	for (i = 0; i < pgd_size; i += RMM_PAGE_SIZE) {
> +		phys_addr_t pgd_phys = kvm->arch.mmu.pgd_phys + i;
> +
> +		if (rmi_granule_delegate(pgd_phys)) {
> +			r = -ENXIO;
> +			goto out_undelegate_tables;
> +		}
> +	}
> +
> +	params->s2sz = VTCR_EL2_IPA(kvm->arch.mmu.vtcr);
> +	params->rtt_level_start = get_start_level(realm);
> +	params->rtt_num_start = rtt_num_start;
> +	params->rtt_base = kvm->arch.mmu.pgd_phys;
> +	params->vmid = realm->vmid;
> +
> +	params_phys = virt_to_phys(params);
> +
> +	if (rmi_realm_create(rd_phys, params_phys)) {
> +		r = -ENXIO;
> +		goto out_undelegate_tables;
> +	}
> +
> +	if (WARN_ON(rmi_rec_aux_count(rd_phys, &realm->num_aux))) {
> +		WARN_ON(rmi_realm_destroy(rd_phys));
> +		goto out_undelegate_tables;
> +	}
> +
> +	realm->rd = rd;
> +
> +	return 0;
> +
> +out_undelegate_tables:
> +	while (i > 0) {
> +		i -= RMM_PAGE_SIZE;
> +
> +		phys_addr_t pgd_phys = kvm->arch.mmu.pgd_phys + i;
> +
> +		if (WARN_ON(rmi_granule_undelegate(pgd_phys))) {
> +			/* Leak the pages if they cannot be returned */
> +			kvm->arch.mmu.pgt = NULL;
> +			break;
> +		}
> +	}
> +	if (WARN_ON(rmi_granule_undelegate(rd_phys))) {
> +		/* Leak the page if it isn't returned */
> +		return r;
> +	}
> +free_rd:
> +	free_page((unsigned long)rd);
> +	return r;
> +}
> +

[...]

> +
> +int kvm_init_realm_vm(struct kvm *kvm)
> +{
> +	struct realm_params *params;
> +
> +	params = (struct realm_params *)get_zeroed_page(GFP_KERNEL);
> +	if (!params)
> +		return -ENOMEM;
> +
> +	kvm->arch.realm.params = params;
> +	return 0;
> +}
> +

The local variable @params is unnecessary, something like below.

	kvm->arch.realm.params = (struct realm_parms *)get_zeroed_page(GFP_KERNEL);

>   void kvm_init_rme(void)
>   {
>   	if (PAGE_SIZE != SZ_4K)
> @@ -52,5 +368,11 @@ void kvm_init_rme(void)
>   		/* Continue without realm support */
>   		return;
>   
> +	if (WARN_ON(rmi_features(0, &rmm_feat_reg0)))
> +		return;
> +
> +	if (rme_vmid_init())
> +		return;
> +
>   	/* Future patch will enable static branch kvm_rme_is_available */
>   }

Thanks,
Gavin



From vigneshr at ti.com  Sun Mar  2 20:54:51 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:24:51 +0530
Subject: [PATCH 0/2] Add bootph-all to SERDES3 for USB DFU Boot on J721E
In-Reply-To: <20250209081738.1874749-1-s-vadapalli@ti.com>
References: <20250209081738.1874749-1-s-vadapalli@ti.com>
Message-ID: <174092143357.3272913.15267994610926405442.b4-ty@ti.com>

Hi Siddharth Vadapalli,

On Sun, 09 Feb 2025 13:47:31 +0530, Siddharth Vadapalli wrote:
> This series is based on linux-next tagged next-20250207.
> 
> J721E SoC supports USB DFU Boot via USB0 instance of USB. On both
> J721E-EVM - (J721E SoM + J7 Common Processor Board) and
> J721E-SK, the USB Type-C interface which is connected to USB0 via
> SERDES3 is used for USB DFU boot.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/2] arm64: dts: ti: k3-j721e-common-proc-board: Add boot phase tag to SERDES3
      commit: 59ac3f9f54db76f676ac5db05054586956c57e39
[2/2] arm64: dts: ti: k3-j721e-sk: Add boot phase tag to SERDES3
      commit: 871c73229bd276fbdb43c42fb3f5a25bcd8a9c85

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 20:55:21 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:25:21 +0530
Subject: [PATCH 0/2] Add boot phase tag to USB0 on AM62A7-SK and AM62P5-SK
In-Reply-To: <20250122124223.1118789-1-s-vadapalli@ti.com>
References: <20250122124223.1118789-1-s-vadapalli@ti.com>
Message-ID: <174092143354.3272913.1834909531649290105.b4-ty@ti.com>

Hi Siddharth Vadapalli,

On Wed, 22 Jan 2025 18:11:47 +0530, Siddharth Vadapalli wrote:
> This series adds the boot phase tag "bootph-all" to the device-tree node
> for USB0 on AM62A7-SK and AM62P5-SK boards. USB0 instance of USB on the
> AM62Ax and AM62Px SoCs which the aforementioned boards are based on, can
> be used for USB DFU boot. Since USB0 has to be enabled at all stages of
> the boot process when booting via USB DFU, the "bootph-all" tag is added
> in the USB0 node of the respective board files.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/2] arm64: dts: ti: k3-am62a7-sk: Add boot phase tag for USB0
      commit: e7ee00e314da736b00ebb26405f8e2cab84cfa22
[2/2] arm64: dts: ti: k3-am62p5-sk: Add boot phase tag for USB0
      commit: 732c4cffe463f222f7f694d469d1f730f4a3adab

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 20:55:22 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:25:22 +0530
Subject: [PATCH] arm64: dts: ti: k3-am62p5-sk: Support SoC wakeup using USB1 wakeup
In-Reply-To: <20250130062550.1554651-1-s-vadapalli@ti.com>
References: <20250130062550.1554651-1-s-vadapalli@ti.com>
Message-ID: <174092143358.3272913.4362724493070822448.b4-ty@ti.com>

Hi Siddharth Vadapalli,

On Thu, 30 Jan 2025 11:55:47 +0530, Siddharth Vadapalli wrote:
> After the SoC has entered the Deep Sleep mode, USB1 can be used to wakeup
> the SoC based on USB events triggered by USB devices. This requires that
> the pin corresponding to the Type-A connector remains pulled up even after
> the SoC has entered the Deep Sleep mode. Hence, enable Deep Sleep pullup /
> pulldown selection for the USB1_DRVBUS pin and set its Deep Sleep state to
> PULL_UP.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62p5-sk: Support SoC wakeup using USB1 wakeup
      commit: 115290c112952db27009668aa7ae2f29920704f0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 20:48:21 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:18:21 +0530
Subject: [PATCH] arm64: dts: ti: k3-j722s-evm: Fix USB2.0_MUX_SEL to select Type-C
In-Reply-To: <20250116125726.2549489-1-h-salunke@ti.com>
References: <20250116125726.2549489-1-h-salunke@ti.com>
Message-ID: <174092143353.3272913.3498123853092206909.b4-ty@ti.com>

Hi Hrushikesh Salunke,

On Thu, 16 Jan 2025 18:27:26 +0530, Hrushikesh Salunke wrote:
> J722S SOC has two usb controllers USB0 and USB1. USB0 is brought out on
> the EVM as a stacked USB connector which has one Type-A and one Type-C
> port. These Type-A and Type-C ports are connected to MUX so only
> one of them can be enabled at a time.
> 
> Commit under Fixes, tries to enable the USB0 instance of USB to
> interface with the Type-C port via the USB hub, by configuring the
> USB2.0_MUX_SEL to GPIO_ACTIVE_HIGH. But it is observed on J722S-EVM
> that Type-A port is enabled instead of Type-C port.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-j722s-evm: Fix USB2.0_MUX_SEL to select Type-C
      commit: bc8d9e6b5821c40ab5dd3a81e096cb114939de50

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From gshan at redhat.com  Sun Mar  2 20:48:44 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 14:48:44 +1000
Subject: [PATCH v7 09/45] kvm: arm64: Expose debug HW register numbers for
 Realm
In-Reply-To: <20250213161426.102987-10-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-10-steven.price@arm.com>
Message-ID: <cec600f2-2ddc-4c71-9bab-0a0403132b43@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> From: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Expose VM specific Debug HW register numbers.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/arm.c | 24 +++++++++++++++++++++---
>   1 file changed, 21 insertions(+), 3 deletions(-)
> 

Documentation/virt/kvm/api.rst needs to be updated accordingly.

> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index b8fa82be251c..df6eb5e9ca96 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -78,6 +78,22 @@ bool is_kvm_arm_initialised(void)
>   	return kvm_arm_initialised;
>   }
>   
> +static u32 kvm_arm_get_num_brps(struct kvm *kvm)
> +{
> +	if (!kvm_is_realm(kvm))
> +		return get_num_brps();
> +	/* Realm guest is not debuggable. */
> +	return 0;
> +}
> +
> +static u32 kvm_arm_get_num_wrps(struct kvm *kvm)
> +{
> +	if (!kvm_is_realm(kvm))
> +		return get_num_wrps();
> +	/* Realm guest is not debuggable. */
> +	return 0;
> +}
> +

The above two comments "Realm guest is not debuggable." can be dropped since
the code is self-explanatory, and those two functions are unnecessary to be
kept in that way, for example:

	case KVM_CAP_GUEST_DEBUG_HW_BPS:
		return kvm_is_realm(kvm) ? 0 : get_num_brps();
	case KVM_CAP_GUEST_DEBUG_HW_WRPS:
		return kvm_is_realm(kvm) ? 0 : get_num_wrps();


>   int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>   {
>   	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
> @@ -323,7 +339,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   	case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
>   	case KVM_CAP_ARM_NISV_TO_USER:
>   	case KVM_CAP_ARM_INJECT_EXT_DABT:
> -	case KVM_CAP_SET_GUEST_DEBUG:
>   	case KVM_CAP_VCPU_ATTRIBUTES:
>   	case KVM_CAP_PTP_KVM:
>   	case KVM_CAP_ARM_SYSTEM_SUSPEND:
> @@ -331,6 +346,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   	case KVM_CAP_COUNTER_OFFSET:
>   		r = 1;
>   		break;
> +	case KVM_CAP_SET_GUEST_DEBUG:
> +		r = !kvm_is_realm(kvm);
> +		break;
>   	case KVM_CAP_SET_GUEST_DEBUG2:
>   		return KVM_GUESTDBG_VALID_MASK;
>   	case KVM_CAP_ARM_SET_DEVICE_ADDR:
> @@ -376,10 +394,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   		r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
>   		break;
>   	case KVM_CAP_GUEST_DEBUG_HW_BPS:
> -		r = get_num_brps();
> +		r = kvm_arm_get_num_brps(kvm);
>   		break;
>   	case KVM_CAP_GUEST_DEBUG_HW_WPS:
> -		r = get_num_wrps();
> +		r = kvm_arm_get_num_wrps(kvm);
>   		break;
>   	case KVM_CAP_ARM_PMU_V3:
>   		r = kvm_arm_support_pmu_v3();

Thanks,
Gavin



From vigneshr at ti.com  Sun Mar  2 20:48:41 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:18:41 +0530
Subject: [PATCH 1/2] arm64: dts: ti: k3-am64-phycore-som: Reserve RTOS IPC memory
In-Reply-To: <20250131093531.1054924-1-w.egorov@phytec.de>
References: <20250131093531.1054924-1-w.egorov@phytec.de>
Message-ID: <174092143359.3272913.1513661794535250352.b4-ty@ti.com>

Hi Wadim Egorov,

On Fri, 31 Jan 2025 10:35:30 +0100, Wadim Egorov wrote:
> Reserve a portion of memory for inter-processor communication between
> all remote processors running RTOS or baremetal firmware.
> 
> 

I have applied the following to branch ti-next on [1].
Thank you!

[1/2] arm64: dts: ti: k3-am64-phycore-som: Reserve RTOS IPC memory
      commit: eeab4a777eb490b9eca670379720b938226b1c79
[2/2] arm64: dts: ti: k3-am62-phycore-som: Reserve RTOS IPC memory
      commit: 4ad59ca98c2764ee2a58e48c96338b6fb88ce85a

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 20:49:05 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:19:05 +0530
Subject: [PATCH] arm64: dts: ti: k3-am62p-j722s-common-wakeup: Configure ti-sysc for wkup_uart0
In-Reply-To: <20250212215248.746838-1-k-willis@ti.com>
References: <20250212215248.746838-1-k-willis@ti.com>
Message-ID: <174092143357.3272913.5649051492068672148.b4-ty@ti.com>

Hi Kendall Willis,

On Wed, 12 Feb 2025 15:52:48 -0600, Kendall Willis wrote:
> Similar to the TI K3-AM62x Soc commit ce27f7f9e328c8582a169f97f1466976561f1
> ("arm64: dts: ti: k3-am62-wakeup: Configure ti-sysc for wkup_uart0")
> The devices in the wkup domain are capable of waking up the system from
> suspend. We can configure the wkup domain devices in a generic way using
> the ti-sysc interconnect target module driver like we have done with the
> earlier TI SoCs.
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62p-j722s-common-wakeup: Configure ti-sysc for wkup_uart0
      commit: b0de0b2de409d99408c0f3a38af841ae3bcaa225

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Sun Mar  2 20:49:55 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 10:19:55 +0530
Subject: [PATCH 0/3] arm64: dts: ti: k3-am62*-sk: Add wkup/mcu_uart0 aliases
In-Reply-To: <20250203-topic-am62-serial-aliases-v6-14-v1-0-f26d4124a9f1@baylibre.com>
References: <20250203-topic-am62-serial-aliases-v6-14-v1-0-f26d4124a9f1@baylibre.com>
Message-ID: <174092143358.3272913.5963413997044284059.b4-ty@ti.com>

Hi Markus Schneider-Pargmann,

On Mon, 03 Feb 2025 10:34:09 +0100, Markus Schneider-Pargmann wrote:
> add serial aliases for wkup and mcu uart0. Add them to have the same
> order on all boards as well.
> 
> Best
> Markus
> 
> 
> [...]

I have applied the following to branch ti-next on [1].
Thank you!

[1/3] arm64: dts: ti: k3-am62x-sk-common: Add serial aliases
      commit: 3e7f622685e8c3ae3adb5d905f56008c4371c660
[2/3] arm64: dts: ti: k3-am62a7-sk: Add serial alias
      commit: 5a74aef8821885e3d567f4a67bc20ecd723731e7
[3/3] arm64: dts: ti: k3-am62p5-sk: Add serial alias
      commit: 8b0f601f9869b01e2dc35c5860eb0f8ce0650be5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From gshan at redhat.com  Sun Mar  2 20:53:39 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 14:53:39 +1000
Subject: [PATCH v7 10/45] arm64: kvm: Allow passing machine type in KVM
 creation
In-Reply-To: <20250213161426.102987-11-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-11-steven.price@arm.com>
Message-ID: <48b68e9c-e550-4fa9-b479-7b2aad4fd538@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> Previously machine type was used purely for specifying the physical
> address size of the guest. Reserve the higher bits to specify an ARM
> specific machine type and declare a new type 'KVM_VM_TYPE_ARM_REALM'
> used to create a realm guest.
> 
> Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Make the check for kvm_rme_is_available more visible and report an
>     error code of -EPERM (instead of -EINVAL) to make it explicit that
>     the kernel supports RME, but the platform doesn't.
> ---
>   arch/arm64/kvm/arm.c     | 15 +++++++++++++++
>   arch/arm64/kvm/mmu.c     |  3 ---
>   include/uapi/linux/kvm.h | 19 +++++++++++++++----
>   3 files changed, 30 insertions(+), 7 deletions(-)
> 

Section 4.2 of Documentation/virt/kvm/api.rst needs to be updated. Other
than that, it looks good to me:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index df6eb5e9ca96..917ee7c674f5 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -180,6 +180,21 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>   	mutex_unlock(&kvm->lock);
>   #endif
>   
> +	if (type & ~(KVM_VM_TYPE_ARM_MASK | KVM_VM_TYPE_ARM_IPA_SIZE_MASK))
> +		return -EINVAL;
> +
> +	switch (type & KVM_VM_TYPE_ARM_MASK) {
> +	case KVM_VM_TYPE_ARM_NORMAL:
> +		break;
> +	case KVM_VM_TYPE_ARM_REALM:
> +		if (!static_branch_unlikely(&kvm_rme_is_available))
> +			return -EPERM;
> +		kvm->arch.is_realm = true;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
>   	kvm_init_nested(kvm);
>   
>   	ret = kvm_share_hyp(kvm, kvm + 1);
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 8cda128aafef..f8ad8f88bbb8 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -886,9 +886,6 @@ static int kvm_init_ipa_range(struct kvm *kvm,
>   	if (kvm_is_realm(kvm))
>   		kvm_ipa_limit = kvm_realm_ipa_limit();
>   
> -	if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
> -		return -EINVAL;
> -
>   	phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
>   	if (is_protected_kvm_enabled()) {
>   		phys_shift = kvm_ipa_limit;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index fa8f45029dff..9cabf9b6a9b4 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -644,14 +644,25 @@ struct kvm_enable_cap {
>   #define KVM_S390_SIE_PAGE_OFFSET 1
>   
>   /*
> - * On arm64, machine type can be used to request the physical
> - * address size for the VM. Bits[7-0] are reserved for the guest
> - * PA size shift (i.e, log2(PA_Size)). For backward compatibility,
> - * value 0 implies the default IPA size, 40bits.
> + * On arm64, machine type can be used to request both the machine type and
> + * the physical address size for the VM.
> + *
> + * Bits[11-8] are reserved for the ARM specific machine type.
> + *
> + * Bits[7-0] are reserved for the guest PA size shift (i.e, log2(PA_Size)).
> + * For backward compatibility, value 0 implies the default IPA size, 40bits.
>    */
> +#define KVM_VM_TYPE_ARM_SHIFT		8
> +#define KVM_VM_TYPE_ARM_MASK		(0xfULL << KVM_VM_TYPE_ARM_SHIFT)
> +#define KVM_VM_TYPE_ARM(_type)		\
> +	(((_type) << KVM_VM_TYPE_ARM_SHIFT) & KVM_VM_TYPE_ARM_MASK)
> +#define KVM_VM_TYPE_ARM_NORMAL		KVM_VM_TYPE_ARM(0)
> +#define KVM_VM_TYPE_ARM_REALM		KVM_VM_TYPE_ARM(1)
> +
>   #define KVM_VM_TYPE_ARM_IPA_SIZE_MASK	0xffULL
>   #define KVM_VM_TYPE_ARM_IPA_SIZE(x)		\
>   	((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
> +
>   /*
>    * ioctls for /dev/kvm fds:
>    */

Thanks,
Gavin



From anshuman.khandual at arm.com  Sun Mar  2 21:02:23 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 3 Mar 2025 10:32:23 +0530
Subject: [PATCH V2 0/8] arm64/mm: Drop PXD_TABLE_BIT
In-Reply-To: <aa71c6ed-8ff2-4b52-b8f7-49147c7769ba@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
 <aa71c6ed-8ff2-4b52-b8f7-49147c7769ba@arm.com>
Message-ID: <a9600c92-bef0-4dd1-95d4-c696d686da18@arm.com>



On 2/28/25 21:02, Ryan Roberts wrote:
> On 21/02/2025 04:42, Anshuman Khandual wrote:
>> Remove the PXX_TABLE_BIT definitions and instead rely on PXX_TYPE_MASK,
>> PXX_TYPE_SECT and PXX_TYPE_TABLE. The latter versions are more abstract
>> and also include the PTE_VALID bit.
>>
>> This abstraction is valuable for the impending D128 page table support,
>> which doesn't have a single page table bit to determine table vs block.
>> Instead it has the skip level (SKL) field, where it will consider 0 to
>> mean table and any other value to mean a block entry. So PXX_TABLE_BIT
>> therefore doesn't fit into the D128 model well, but the type fields do.
> 
> All the patches look logically correct to me and I agree with the intention of
> removing PXX_TABLE_BIT. But personally I'd prefer to see a single patch that
> just does everything that's required to remove PXX_TABLE_BIT. And then a second
> patch for the pud_bad() fix/improvement (currently patch 6) which is orthogonal
> to the removal of PXX_TABLE_BIT.
> 
> That would make it much easier to review IMHO, and would also allow for writing
> a single commit log which provides the justification for the change. I find the
> current set of 7 commit logs to not be hugely helpful.

Dropping PXX_TABLE_BIT from individual functional components which stand on their
own progressively leads to its complete removal from the tree. Even though goal
is PXX_TABLE_BIT mask's complete removal, each patch here could be justified on
its own improving consistent reasoning around various section mapping creation
and identification while keeping the functionality unchanged and also improving
code readability as well.

> 
> But I wrote the original patches and wrote them as I'm suggesting, so I would
> say that :)

I can understand :) Although it also follows and expands on the previous attempt
in removing this mask that formed a patch series instead.

https://lore.kernel.org/all/20241005123824.1366397-1-anshuman.khandual at arm.com/

TBH this is not a big deal. I can merge all but last one into a single patch as
you have suggested if that's a general consensus. Although I would prefer the
current logically progressive series based approach but that's just me.

> 
> I'm guessing I shouldn't provide a Reviewed-By here, given I wrote the code
> originally...
> 
> Thanks,
> Ryan
> 
> 
>>
>> This series applies on v6.14-rc3.
>>
>> Changes in V2:
>>
>> - Changed pmd_mkhuge() and pud_mkhuge() implementation
>> - Changed pud_bad() implementation with an additional patch
>>
>> Changes in V1:
>>
>> https://lore.kernel.org/all/20241005123824.1366397-1-anshuman.khandual at arm.com/
>>
>> Cc: Marc Zyngier <maz at kernel.org>
>> Cc: Oliver Upton <oliver.upton at linux.dev>
>> Cc: James Morse <james.morse at arm.com>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: kvmarm at lists.linux.dev
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>>
>> Anshuman Khandual (6):
>>   KVM: arm64: ptdump: Test PMD_TYPE_MASK for block mapping
>>   arm64/ptdump: Test PMD_TYPE_MASK for block mapping
>>   arm64/mm: Clear PXX_TYPE_MASK in mk_[pmd|pud]_sect_prot()
>>   arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT in [pmd|pud]_mkhuge()
>>   arm64/mm: Check PXD_TYPE_TABLE in [p4d|pgd]_bad()
>>   arm64/mm: Drop PXD_TABLE_BIT
>>
>> Ryan Roberts (2):
>>   arm64/mm: Check PUD_TYPE_TABLE in pud_bad()
>>   arm64/mm: Check pmd_table() in pmd_trans_huge()
>>
>>  arch/arm64/include/asm/pgtable-hwdef.h |  5 --
>>  arch/arm64/include/asm/pgtable.h       | 65 ++++++++++++++++++--------
>>  arch/arm64/kvm/ptdump.c                |  4 +-
>>  arch/arm64/mm/ptdump.c                 |  4 +-
>>  4 files changed, 50 insertions(+), 28 deletions(-)
>>
> 


From yepeilin at google.com  Sun Mar  2 21:37:37 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:37 +0000
Subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin@google.com>

Introduce BPF instructions with load-acquire and store-release
semantics, as discussed in [1].  Define 2 new flags:

  #define BPF_LOAD_ACQ    0x100
  #define BPF_STORE_REL   0x110

A "load-acquire" is a BPF_STX | BPF_ATOMIC instruction with the 'imm'
field set to BPF_LOAD_ACQ (0x100).

Similarly, a "store-release" is a BPF_STX | BPF_ATOMIC instruction with
the 'imm' field set to BPF_STORE_REL (0x110).

Unlike existing atomic read-modify-write operations that only support
BPF_W (32-bit) and BPF_DW (64-bit) size modifiers, load-acquires and
store-releases also support BPF_B (8-bit) and BPF_H (16-bit).  An 8- or
16-bit load-acquire zero-extends the value before writing it to a 32-bit
register, just like ARM64 instruction LDARH and friends.

Similar to existing atomic read-modify-write operations, misaligned
load-acquires/store-releases are not allowed (even if
BPF_F_ANY_ALIGNMENT is set).

As an example, consider the following 64-bit load-acquire BPF
instruction (assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

Similarly, a 16-bit BPF store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

In arch/{arm64,s390,x86}/net/bpf_jit_comp.c, have
bpf_jit_supports_insn(..., /*in_arena=*/true) return false for the new
instructions, until the corresponding JIT compiler supports them in
arena.

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Acked-by: Ilya Leoshkevich <iii at linux.ibm.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit_comp.c  |  4 +++
 arch/s390/net/bpf_jit_comp.c   | 14 +++++---
 arch/x86/net/bpf_jit_comp.c    |  4 +++
 include/linux/bpf.h            | 15 ++++++++
 include/linux/filter.h         |  2 ++
 include/uapi/linux/bpf.h       |  3 ++
 kernel/bpf/core.c              | 63 ++++++++++++++++++++++++++++++----
 kernel/bpf/disasm.c            | 12 +++++++
 kernel/bpf/verifier.c          | 45 ++++++++++++++++++++++--
 tools/include/uapi/linux/bpf.h |  3 ++
 10 files changed, 152 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 7409c8acbde3..bdda5a77bb16 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -2667,8 +2667,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9d440a0b729e..0776dfde2dba 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -2919,10 +2919,16 @@ bool bpf_jit_supports_arena(void)
 
 bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 {
-	/*
-	 * Currently the verifier uses this function only to check which
-	 * atomic stores to arena are supported, and they all are.
-	 */
+	if (!in_arena)
+		return true;
+	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
+	case BPF_STX | BPF_ATOMIC | BPF_W:
+	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
+	}
 	return true;
 }
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a43fc5af973d..f0c31c940fb8 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3771,8 +3771,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 4c4028d865ee..b556a26d8150 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -991,6 +991,21 @@ static inline bool bpf_pseudo_func(const struct bpf_insn *insn)
 	return bpf_is_ldimm64(insn) && insn->src_reg == BPF_PSEUDO_FUNC;
 }
 
+/* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
+ * atomic load or store, and false if it is a read-modify-write instruction.
+ */
+static inline bool
+bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
+{
+	switch (atomic_insn->imm) {
+	case BPF_LOAD_ACQ:
+	case BPF_STORE_REL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 struct bpf_prog_ops {
 	int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
 			union bpf_attr __user *uattr);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3ed6eb9e7c73..24e94afb5622 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -364,6 +364,8 @@ static inline bool insn_is_cast_user(const struct bpf_insn *insn)
  *   BPF_XOR | BPF_FETCH      src_reg = atomic_fetch_xor(dst_reg + off16, src_reg);
  *   BPF_XCHG                 src_reg = atomic_xchg(dst_reg + off16, src_reg)
  *   BPF_CMPXCHG              r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg)
+ *   BPF_LOAD_ACQ             dst_reg = smp_load_acquire(src_reg + off16)
+ *   BPF_STORE_REL            smp_store_release(dst_reg + off16, src_reg)
  */
 
 #define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF)			\
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index a0200fbbace9..323af18d7d49 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1663,14 +1663,17 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
 	INSN_3(JMP, JSET, K),			\
 	INSN_2(JMP, JA),			\
 	INSN_2(JMP32, JA),			\
+	/* Atomic operations. */		\
+	INSN_3(STX, ATOMIC, B),			\
+	INSN_3(STX, ATOMIC, H),			\
+	INSN_3(STX, ATOMIC, W),			\
+	INSN_3(STX, ATOMIC, DW),		\
 	/* Store instructions. */		\
 	/*   Register based. */			\
 	INSN_3(STX, MEM,  B),			\
 	INSN_3(STX, MEM,  H),			\
 	INSN_3(STX, MEM,  W),			\
 	INSN_3(STX, MEM,  DW),			\
-	INSN_3(STX, ATOMIC, W),			\
-	INSN_3(STX, ATOMIC, DW),		\
 	/*   Immediate based. */		\
 	INSN_3(ST, MEM, B),			\
 	INSN_3(ST, MEM, H),			\
@@ -2152,24 +2155,33 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				atomic_##KOP((u32) SRC, (atomic_t *)(unsigned long) \
 					     (DST + insn->off));	\
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				atomic64_##KOP((u64) SRC, (atomic64_t *)(unsigned long) \
 					       (DST + insn->off));	\
+			else						\
+				goto default_label;			\
 			break;						\
 		case BOP | BPF_FETCH:					\
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				SRC = (u32) atomic_fetch_##KOP(		\
 					(u32) SRC,			\
 					(atomic_t *)(unsigned long) (DST + insn->off)); \
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				SRC = (u64) atomic64_fetch_##KOP(	\
 					(u64) SRC,			\
 					(atomic64_t *)(unsigned long) (DST + insn->off)); \
+			else						\
+				goto default_label;			\
 			break;
 
 	STX_ATOMIC_DW:
 	STX_ATOMIC_W:
+	STX_ATOMIC_H:
+	STX_ATOMIC_B:
 		switch (IMM) {
+		/* Atomic read-modify-write instructions support only W and DW
+		 * size modifiers.
+		 */
 		ATOMIC_ALU_OP(BPF_ADD, add)
 		ATOMIC_ALU_OP(BPF_AND, and)
 		ATOMIC_ALU_OP(BPF_OR, or)
@@ -2181,20 +2193,59 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 				SRC = (u32) atomic_xchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				SRC = (u64) atomic64_xchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) SRC);
+			else
+				goto default_label;
 			break;
 		case BPF_CMPXCHG:
 			if (BPF_SIZE(insn->code) == BPF_W)
 				BPF_R0 = (u32) atomic_cmpxchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) BPF_R0, (u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				BPF_R0 = (u64) atomic64_cmpxchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) BPF_R0, (u64) SRC);
+			else
+				goto default_label;
+			break;
+		/* Atomic load and store instructions support all size
+		 * modifiers.
+		 */
+		case BPF_LOAD_ACQ:
+			switch (BPF_SIZE(insn->code)) {
+#define LOAD_ACQUIRE(SIZEOP, SIZE)				\
+			case BPF_##SIZEOP:			\
+				DST = (SIZE)smp_load_acquire(	\
+					(SIZE *)(unsigned long)(SRC + insn->off));	\
+				break;
+			LOAD_ACQUIRE(B,   u8)
+			LOAD_ACQUIRE(H,  u16)
+			LOAD_ACQUIRE(W,  u32)
+			LOAD_ACQUIRE(DW, u64)
+#undef LOAD_ACQUIRE
+			default:
+				goto default_label;
+			}
+			break;
+		case BPF_STORE_REL:
+			switch (BPF_SIZE(insn->code)) {
+#define STORE_RELEASE(SIZEOP, SIZE)			\
+			case BPF_##SIZEOP:		\
+				smp_store_release(	\
+					(SIZE *)(unsigned long)(DST + insn->off), (SIZE)SRC);	\
+				break;
+			STORE_RELEASE(B,   u8)
+			STORE_RELEASE(H,  u16)
+			STORE_RELEASE(W,  u32)
+			STORE_RELEASE(DW, u64)
+#undef STORE_RELEASE
+			default:
+				goto default_label;
+			}
 			break;
 
 		default:
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c
index 309c4aa1b026..974d172d6735 100644
--- a/kernel/bpf/disasm.c
+++ b/kernel/bpf/disasm.c
@@ -267,6 +267,18 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
 				BPF_SIZE(insn->code) == BPF_DW ? "64" : "",
 				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
 				insn->dst_reg, insn->off, insn->src_reg);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_LOAD_ACQ) {
+			verbose(cbs->private_data, "(%02x) r%d = load_acquire((%s *)(r%d %+d))\n",
+				insn->code, insn->dst_reg,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->src_reg, insn->off);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_STORE_REL) {
+			verbose(cbs->private_data, "(%02x) store_release((%s *)(r%d %+d), r%d)\n",
+				insn->code,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->dst_reg, insn->off, insn->src_reg);
 		} else {
 			verbose(cbs->private_data, "BUG_%02x\n", insn->code);
 		}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 22c4edc8695c..dac7af73ac8a 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -579,6 +579,13 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
 	       insn->imm == BPF_CMPXCHG;
 }
 
+static bool is_atomic_load_insn(const struct bpf_insn *insn)
+{
+	return BPF_CLASS(insn->code) == BPF_STX &&
+	       BPF_MODE(insn->code) == BPF_ATOMIC &&
+	       insn->imm == BPF_LOAD_ACQ;
+}
+
 static int __get_spi(s32 off)
 {
 	return (-off - 1) / BPF_REG_SIZE;
@@ -3567,7 +3574,7 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
 	}
 
 	if (class == BPF_STX) {
-		/* BPF_STX (including atomic variants) has multiple source
+		/* BPF_STX (including atomic variants) has one or more source
 		 * operands, one of which is a ptr. Check whether the caller is
 		 * asking about it.
 		 */
@@ -4181,7 +4188,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
 			   * dreg still needs precision before this insn
 			   */
 		}
-	} else if (class == BPF_LDX) {
+	} else if (class == BPF_LDX || is_atomic_load_insn(insn)) {
 		if (!bt_is_reg_set(bt, dreg))
 			return 0;
 		bt_clear_reg(bt, dreg);
@@ -7766,6 +7773,32 @@ static int check_atomic_rmw(struct bpf_verifier_env *env,
 	return 0;
 }
 
+static int check_atomic_load(struct bpf_verifier_env *env,
+			     struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->src_reg, insn)) {
+		verbose(env, "BPF_ATOMIC loads from R%d %s is not allowed\n",
+			insn->src_reg,
+			reg_type_str(env, reg_state(env, insn->src_reg)->type));
+		return -EACCES;
+	}
+
+	return check_load_mem(env, insn, true, false, false, "atomic_load");
+}
+
+static int check_atomic_store(struct bpf_verifier_env *env,
+			      struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) {
+		verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n",
+			insn->dst_reg,
+			reg_type_str(env, reg_state(env, insn->dst_reg)->type));
+		return -EACCES;
+	}
+
+	return check_store_reg(env, insn, true);
+}
+
 static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
 	switch (insn->imm) {
@@ -7780,6 +7813,10 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 	case BPF_XCHG:
 	case BPF_CMPXCHG:
 		return check_atomic_rmw(env, insn);
+	case BPF_LOAD_ACQ:
+		return check_atomic_load(env, insn);
+	case BPF_STORE_REL:
+		return check_atomic_store(env, insn);
 	default:
 		verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
 			insn->imm);
@@ -20605,7 +20642,9 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 			   insn->code == (BPF_ST | BPF_MEM | BPF_W) ||
 			   insn->code == (BPF_ST | BPF_MEM | BPF_DW)) {
 			type = BPF_WRITE;
-		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
+		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_B) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_H) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
 			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_DW)) &&
 			   env->insn_aux_data[i + delta].ptr_type == PTR_TO_ARENA) {
 			insn->code = BPF_STX | BPF_PROBE_ATOMIC | BPF_SIZE(insn->code);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:44 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:44 +0000
Subject: [PATCH bpf-next v4 05/10] arm64: insn: Add BIT(23) to
 {load,store}_ex's mask
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <03ceb882fa759f503b3f4b7f4ff2a5ce69a0eb05.1740978603.git.yepeilin@google.com>

We are planning to add load-acquire (LDAR{,B,H}) and store-release
(STLR{,B,H}) instructions to insn.{c,h}; add BIT(23) to mask of load_ex
and store_ex to prevent aarch64_insn_is_{load,store}_ex() from returning
false-positives for load-acquire and store-release instructions.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.228 LDXR
  * C6.2.165 LDAXR
  * C6.2.161 LDAR
  * C6.2.393 STXR
  * C6.2.360 STLXR
  * C6.2.353 STLR

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index e390c432f546..2d8316b3abaf 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -351,8 +351,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
-__AARCH64_INSN_FUNCS(load_ex,	0x3F400000, 0x08400000)
-__AARCH64_INSN_FUNCS(store_ex,	0x3F400000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
+__AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
 __AARCH64_INSN_FUNCS(stp,	0x7FC00000, 0x29000000)
 __AARCH64_INSN_FUNCS(ldp,	0x7FC00000, 0x29400000)
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:50 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:50 +0000
Subject: [PATCH bpf-next v4 06/10] arm64: insn: Add load-acquire and
 store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <347830eb25b3bfea7687d4081852fb7d54e82307.1740978603.git.yepeilin@google.com>

Add load-acquire ("load_acq", LDAR{,B,H}) and store-release
("store_rel", STLR{,B,H}) instructions.  Breakdown of encoding:

                                size        L   (Rs)  o0 (Rt2) Rn    Rt
             mask (0x3fdffc00): 00 111111 1 1 0 11111 1  11111 00000 00000
  value, load_acq (0x08dffc00): 00 001000 1 1 0 11111 1  11111 00000 00000
 value, store_rel (0x089ffc00): 00 001000 1 0 0 11111 1  11111 00000 00000

As suggested by Xu [1], include all Should-Be-One (SBO) bits ("Rs" and
"Rt2" fields) in the "mask" and "value" numbers.

It is worth noting that we are adding the "no offset" variant of STLR
instead of the "pre-index" variant, which has a different encoding.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.161 LDAR
  * C6.2.353 STLR

[1] https://lore.kernel.org/bpf/4e6641ce-3f1e-4251-8daf-4dd4b77d08c4 at huaweicloud.com/

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h |  8 ++++++++
 arch/arm64/lib/insn.c         | 29 +++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 2d8316b3abaf..39577f1d079a 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -188,8 +188,10 @@ enum aarch64_insn_ldst_type {
 	AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX,
 	AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX,
 	AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX,
+	AARCH64_INSN_LDST_LOAD_ACQ,
 	AARCH64_INSN_LDST_LOAD_EX,
 	AARCH64_INSN_LDST_LOAD_ACQ_EX,
+	AARCH64_INSN_LDST_STORE_REL,
 	AARCH64_INSN_LDST_STORE_EX,
 	AARCH64_INSN_LDST_STORE_REL_EX,
 	AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET,
@@ -351,6 +353,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_acq,  0x3FDFFC00, 0x08DFFC00)
+__AARCH64_INSN_FUNCS(store_rel, 0x3FDFFC00, 0x089FFC00)
 __AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
 __AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
@@ -602,6 +606,10 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 				     int offset,
 				     enum aarch64_insn_variant variant,
 				     enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type);
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c
index b008a9b46a7f..9bef696e2230 100644
--- a/arch/arm64/lib/insn.c
+++ b/arch/arm64/lib/insn.c
@@ -540,6 +540,35 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 					     offset >> shift);
 }
 
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_ACQ:
+		insn = aarch64_insn_get_load_acq_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_REL:
+		insn = aarch64_insn_get_store_rel_value();
+		break;
+	default:
+		pr_err("%s: unknown load-acquire/store-release encoding %d\n",
+		       __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    reg);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+}
+
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:57 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:57 +0000
Subject: [PATCH bpf-next v4 07/10] bpf, arm64: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <3dcd54003b8dbb9ed74beb0535fee704db421515.1740978603.git.yepeilin@google.com>

Support BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions in the arm64 JIT compiler.  For example
(assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))
  95 00 00 00 00 00 00 00  exit

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

The JIT compiler would emit an LDAR instruction for the above, e.g.:

  ldar  x7, [x0]

Similarly, consider the following 16-bit store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)
  95 00 00 00 00 00 00 00  exit

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

An STLRH instruction would be emitted, e.g.:

  stlrh  w1, [x0]

For a complete mapping:

  load-acquire     8-bit  LDARB
 (BPF_LOAD_ACQ)   16-bit  LDARH
                  32-bit  LDAR (32-bit)
                  64-bit  LDAR (64-bit)
  store-release    8-bit  STLRB
 (BPF_STORE_REL)  16-bit  STLRH
                  32-bit  STLR (32-bit)
                  64-bit  STLR (64-bit)

Arena accesses are supported.
bpf_jit_supports_insn(..., /*in_arena=*/true) always returns true for
BPF_LOAD_ACQ and BPF_STORE_REL instructions, as they don't depend on
ARM64_HAS_LSE_ATOMICS.

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit.h      | 20 ++++++++
 arch/arm64/net/bpf_jit_comp.c | 90 ++++++++++++++++++++++++++++++++---
 2 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index b22ab2f97a30..a3b0e693a125 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -119,6 +119,26 @@
 	aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \
 				       AARCH64_INSN_LDST_STORE_REL_EX)
 
+/* Load-acquire & store-release */
+#define A64_LDAR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_LOAD_ACQ)
+#define A64_STLR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_STORE_REL)
+
+/* Rt = [Rn] (load acquire) */
+#define A64_LDARB(Wt, Xn)	A64_LDAR(Wt, Xn, 8)
+#define A64_LDARH(Wt, Xn)	A64_LDAR(Wt, Xn, 16)
+#define A64_LDAR32(Wt, Xn)	A64_LDAR(Wt, Xn, 32)
+#define A64_LDAR64(Xt, Xn)	A64_LDAR(Xt, Xn, 64)
+
+/* [Rn] = Rt (store release) */
+#define A64_STLRB(Wt, Xn)	A64_STLR(Wt, Xn, 8)
+#define A64_STLRH(Wt, Xn)	A64_STLR(Wt, Xn, 16)
+#define A64_STLR32(Wt, Xn)	A64_STLR(Wt, Xn, 32)
+#define A64_STLR64(Xt, Xn)	A64_STLR(Xt, Xn, 64)
+
 /*
  * LSE atomics
  *
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index bdda5a77bb16..70d7c89d3ac9 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -647,6 +647,81 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
 	return 0;
 }
 
+static int emit_atomic_ld_st(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s32 imm = insn->imm;
+	const s16 off = insn->off;
+	const u8 code = insn->code;
+	const bool arena = BPF_MODE(code) == BPF_PROBE_ATOMIC;
+	const u8 arena_vm_base = bpf2a64[ARENA_VM_START];
+	const u8 dst = bpf2a64[insn->dst_reg];
+	const u8 src = bpf2a64[insn->src_reg];
+	const u8 tmp = bpf2a64[TMP_REG_1];
+	u8 reg;
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		reg = src;
+		break;
+	case BPF_STORE_REL:
+		reg = dst;
+		break;
+	default:
+		pr_err_once("unknown atomic load/store op code %02x\n", imm);
+		return -EINVAL;
+	}
+
+	if (off) {
+		emit_a64_add_i(1, tmp, reg, tmp, off, ctx);
+		reg = tmp;
+	}
+	if (arena) {
+		emit(A64_ADD(1, tmp, reg, arena_vm_base), ctx);
+		reg = tmp;
+	}
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_LDARB(dst, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_LDARH(dst, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_LDAR32(dst, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_LDAR64(dst, reg), ctx);
+			break;
+		}
+		break;
+	case BPF_STORE_REL:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_STLRB(src, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_STLRH(src, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_STLR32(src, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_STLR64(src, reg), ctx);
+			break;
+		}
+		break;
+	default:
+		pr_err_once("unexpected atomic load/store op code %02x\n",
+			    imm);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
 {
@@ -1641,11 +1716,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
 			return ret;
 		break;
 
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
-		if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (bpf_atomic_is_load_store(insn))
+			ret = emit_atomic_ld_st(insn, ctx);
+		else if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			ret = emit_lse_atomic(insn, ctx);
 		else
 			ret = emit_ll_sc_atomic(insn, ctx);
@@ -2667,13 +2748,10 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
-		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (!bpf_atomic_is_load_store(insn) &&
+		    !cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
 	return true;
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:38:07 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:38:07 +0000
Subject: [PATCH bpf-next v4 08/10] bpf, x86: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <ea2754510513dce17a1d8f4fcab07d9d769e7b08.1740978603.git.yepeilin@google.com>

Recently we introduced BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions.  For x86-64, simply implement them as
regular BPF_LDX/BPF_STX loads and stores.  The verifier always rejects
misaligned load-acquires/store-releases (even if BPF_F_ANY_ALIGNMENT is
set), so emitted MOV* instructions are guaranteed to be atomic.

Arena accesses are supported.  8- and 16-bit load-acquires are
zero-extending (i.e., MOVZBQ, MOVZWQ).

Rename emit_atomic{,_index}() to emit_atomic_rmw{,_index}() to make it
clear that they only handle read-modify-write atomics, and extend their
@atomic_op parameter from u8 to u32, since we are starting to use more
than the lowest 8 bits of the 'imm' field.

Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/x86/net/bpf_jit_comp.c | 99 ++++++++++++++++++++++++++++++-------
 1 file changed, 82 insertions(+), 17 deletions(-)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index f0c31c940fb8..0263d98d92b0 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1242,8 +1242,8 @@ static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
 	emit_st_index(pprog, size, dst_reg, X86_REG_R12, off, imm);
 }
 
-static int emit_atomic(u8 **pprog, u8 atomic_op,
-		       u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
+static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
+			   u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
 {
 	u8 *prog = *pprog;
 
@@ -1283,8 +1283,9 @@ static int emit_atomic(u8 **pprog, u8 atomic_op,
 	return 0;
 }
 
-static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
-			     u32 dst_reg, u32 src_reg, u32 index_reg, int off)
+static int emit_atomic_rmw_index(u8 **pprog, u32 atomic_op, u32 size,
+				 u32 dst_reg, u32 src_reg, u32 index_reg,
+				 int off)
 {
 	u8 *prog = *pprog;
 
@@ -1297,7 +1298,7 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 		EMIT1(add_3mod(0x48, dst_reg, src_reg, index_reg));
 		break;
 	default:
-		pr_err("bpf_jit: 1 and 2 byte atomics are not supported\n");
+		pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
 		return -EFAULT;
 	}
 
@@ -1331,6 +1332,49 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 	return 0;
 }
 
+static int emit_atomic_ld_st(u8 **pprog, u32 atomic_op, u32 dst_reg,
+			     u32 src_reg, s16 off, u8 bpf_size)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + off16) */
+		emit_ldx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + off16, src_reg) */
+		emit_stx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int emit_atomic_ld_st_index(u8 **pprog, u32 atomic_op, u32 size,
+				   u32 dst_reg, u32 src_reg, u32 index_reg,
+				   int off)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + idx_reg + off16) */
+		emit_ldx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + idx_reg + off16, src_reg) */
+		emit_stx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
 #define DONT_CLEAR 1
 
 bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
@@ -2113,6 +2157,13 @@ st:			if (is_imm8(insn->off))
 			}
 			break;
 
+		case BPF_STX | BPF_ATOMIC | BPF_B:
+		case BPF_STX | BPF_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_ATOMIC | BPF_W:
 		case BPF_STX | BPF_ATOMIC | BPF_DW:
 			if (insn->imm == (BPF_AND | BPF_FETCH) ||
@@ -2148,10 +2199,10 @@ st:			if (is_imm8(insn->off))
 				EMIT2(simple_alu_opcodes[BPF_OP(insn->imm)],
 				      add_2reg(0xC0, AUX_REG, real_src_reg));
 				/* Attempt to swap in new value */
-				err = emit_atomic(&prog, BPF_CMPXCHG,
-						  real_dst_reg, AUX_REG,
-						  insn->off,
-						  BPF_SIZE(insn->code));
+				err = emit_atomic_rmw(&prog, BPF_CMPXCHG,
+						      real_dst_reg, AUX_REG,
+						      insn->off,
+						      BPF_SIZE(insn->code));
 				if (WARN_ON(err))
 					return err;
 				/*
@@ -2166,17 +2217,35 @@ st:			if (is_imm8(insn->off))
 				break;
 			}
 
-			err = emit_atomic(&prog, insn->imm, dst_reg, src_reg,
-					  insn->off, BPF_SIZE(insn->code));
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st(&prog, insn->imm, dst_reg, src_reg,
+							insn->off, BPF_SIZE(insn->code));
+			else
+				err = emit_atomic_rmw(&prog, insn->imm, dst_reg, src_reg,
+						      insn->off, BPF_SIZE(insn->code));
 			if (err)
 				return err;
 			break;
 
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
 			start_of_ldx = prog;
-			err = emit_atomic_index(&prog, insn->imm, BPF_SIZE(insn->code),
-						dst_reg, src_reg, X86_REG_R12, insn->off);
+
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st_index(&prog, insn->imm,
+							      BPF_SIZE(insn->code), dst_reg,
+							      src_reg, X86_REG_R12, insn->off);
+			else
+				err = emit_atomic_rmw_index(&prog, insn->imm, BPF_SIZE(insn->code),
+							    dst_reg, src_reg, X86_REG_R12,
+							    insn->off);
 			if (err)
 				return err;
 			goto populate_extable;
@@ -3771,12 +3840,8 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:38:18 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:38:18 +0000
Subject: [PATCH bpf-next v4 09/10] selftests/bpf: Add selftests for
 load-acquire and store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <c9c24b0659c14d7bcb79b3d2c92d3df59d6ed658.1740978603.git.yepeilin@google.com>

Add several ./test_progs tests:

  - arena_atomics/load_acquire
  - arena_atomics/store_release
  - verifier_load_acquire/*
  - verifier_store_release/*
  - verifier_precision/bpf_load_acquire
  - verifier_precision/bpf_store_release

The last two tests are added to check if backtrack_insn() handles the
new instructions correctly.

Additionally, the last test also makes sure that the verifier
"remembers" the value (in src_reg) we store-release into e.g. a stack
slot.  For example, if we take a look at the test program:

    #0:  r1 = 8;
      /* store_release((u64 *)(r10 - 8), r1); */
    #1:  .8byte %[store_release];
    #2:  r1 = *(u64 *)(r10 - 8);
    #3:  r2 = r10;
    #4:  r2 += r1;
    #5:  r0 = 0;
    #6:  exit;

At #1, if the verifier doesn't remember that we wrote 8 to the stack,
then later at #4 we would be adding an unbounded scalar value to the
stack pointer, which would cause the program to be rejected:

  VERIFIER LOG:
  =============
...
  math between fp pointer and register with unbounded min value is not allowed

For easier CI integration, instead of using built-ins like
__atomic_{load,store}_n() which depend on the new
__BPF_FEATURE_LOAD_ACQ_STORE_REL pre-defined macro, manually craft
load-acquire/store-release instructions using __imm_insn(), as suggested
by Eduard.

All new tests depend on:

  (1) Clang major version >= 18, and
  (2) ENABLE_ATOMICS_TESTS is defined (currently implies -mcpu=v3 or
      v4), and
  (3) JIT supports load-acquire/store-release (currently arm64 and
      x86-64)

In .../progs/arena_atomics.c:

  /* 8-byte-aligned */
  __u8 __arena_global load_acquire8_value = 0x12;
  /* 1-byte hole */
  __u16 __arena_global load_acquire16_value = 0x1234;

That 1-byte hole in the .addr_space.1 ELF section caused clang-17 to
crash:

  fatal error: error in backend: unable to write nop sequence of 1 bytes

To work around such llvm-17 CI job failures, conditionally define
__arena_global variables as 64-bit if __clang_major__ < 18, to make sure
.addr_space.1 has no holes.  Ideally we should avoid compiling this file
using clang-17 at all (arena tests depend on
__BPF_FEATURE_ADDR_SPACE_CAST, and are skipped for llvm-17 anyway), but
that is a separate topic.

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 6 files changed, 698 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
index 26e7c06c6cb4..d98577a6babc 100644
--- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
+++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
@@ -162,6 +162,66 @@ static void test_uaf(struct arena_atomics *skel)
 	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
 }
 
+static void test_load_acquire(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support load-acquire\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.load_acquire);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->load_acquire8_result, 0x12,
+		  "load_acquire8_result");
+	ASSERT_EQ(skel->arena->load_acquire16_result, 0x1234,
+		  "load_acquire16_result");
+	ASSERT_EQ(skel->arena->load_acquire32_result, 0x12345678,
+		  "load_acquire32_result");
+	ASSERT_EQ(skel->arena->load_acquire64_result, 0x1234567890abcdef,
+		  "load_acquire64_result");
+}
+
+static void test_store_release(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support store-release\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.store_release);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->store_release8_result, 0x12,
+		  "store_release8_result");
+	ASSERT_EQ(skel->arena->store_release16_result, 0x1234,
+		  "store_release16_result");
+	ASSERT_EQ(skel->arena->store_release32_result, 0x12345678,
+		  "store_release32_result");
+	ASSERT_EQ(skel->arena->store_release64_result, 0x1234567890abcdef,
+		  "store_release64_result");
+}
+
 void test_arena_atomics(void)
 {
 	struct arena_atomics *skel;
@@ -171,7 +231,7 @@ void test_arena_atomics(void)
 	if (!ASSERT_OK_PTR(skel, "arena atomics skeleton open"))
 		return;
 
-	if (skel->data->skip_tests) {
+	if (skel->data->skip_all_tests) {
 		printf("%s:SKIP:no ENABLE_ATOMICS_TESTS or no addr_space_cast support in clang",
 		       __func__);
 		test__skip();
@@ -198,6 +258,10 @@ void test_arena_atomics(void)
 		test_xchg(skel);
 	if (test__start_subtest("uaf"))
 		test_uaf(skel);
+	if (test__start_subtest("load_acquire"))
+		test_load_acquire(skel);
+	if (test__start_subtest("store_release"))
+		test_store_release(skel);
 
 cleanup:
 	arena_atomics__destroy(skel);
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index 8a0e1ff8a2dc..cfe47b529e01 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -45,6 +45,7 @@
 #include "verifier_ldsx.skel.h"
 #include "verifier_leak_ptr.skel.h"
 #include "verifier_linked_scalars.skel.h"
+#include "verifier_load_acquire.skel.h"
 #include "verifier_loops1.skel.h"
 #include "verifier_lwt.skel.h"
 #include "verifier_map_in_map.skel.h"
@@ -80,6 +81,7 @@
 #include "verifier_spill_fill.skel.h"
 #include "verifier_spin_lock.skel.h"
 #include "verifier_stack_ptr.skel.h"
+#include "verifier_store_release.skel.h"
 #include "verifier_subprog_precision.skel.h"
 #include "verifier_subreg.skel.h"
 #include "verifier_tailcall_jit.skel.h"
@@ -173,6 +175,7 @@ void test_verifier_int_ptr(void)              { RUN(verifier_int_ptr); }
 void test_verifier_iterating_callbacks(void)  { RUN(verifier_iterating_callbacks); }
 void test_verifier_jeq_infer_not_null(void)   { RUN(verifier_jeq_infer_not_null); }
 void test_verifier_jit_convergence(void)      { RUN(verifier_jit_convergence); }
+void test_verifier_load_acquire(void)         { RUN(verifier_load_acquire); }
 void test_verifier_ld_ind(void)               { RUN(verifier_ld_ind); }
 void test_verifier_ldsx(void)                  { RUN(verifier_ldsx); }
 void test_verifier_leak_ptr(void)             { RUN(verifier_leak_ptr); }
@@ -211,6 +214,7 @@ void test_verifier_sockmap_mutate(void)       { RUN(verifier_sockmap_mutate); }
 void test_verifier_spill_fill(void)           { RUN(verifier_spill_fill); }
 void test_verifier_spin_lock(void)            { RUN(verifier_spin_lock); }
 void test_verifier_stack_ptr(void)            { RUN(verifier_stack_ptr); }
+void test_verifier_store_release(void)        { RUN(verifier_store_release); }
 void test_verifier_subprog_precision(void)    { RUN(verifier_subprog_precision); }
 void test_verifier_subreg(void)               { RUN(verifier_subreg); }
 void test_verifier_tailcall_jit(void)         { RUN(verifier_tailcall_jit); }
diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/testing/selftests/bpf/progs/arena_atomics.c
index 40dd57fca5cc..a52feff98112 100644
--- a/tools/testing/selftests/bpf/progs/arena_atomics.c
+++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
@@ -6,6 +6,8 @@
 #include <stdbool.h>
 #include <stdatomic.h>
 #include "bpf_arena_common.h"
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
 
 struct {
 	__uint(type, BPF_MAP_TYPE_ARENA);
@@ -19,9 +21,17 @@ struct {
 } arena SEC(".maps");
 
 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST)
-bool skip_tests __attribute((__section__(".data"))) = false;
+bool skip_all_tests __attribute((__section__(".data"))) = false;
 #else
-bool skip_tests = true;
+bool skip_all_tests = true;
+#endif
+
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+bool skip_lacq_srel_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_lacq_srel_tests = true;
 #endif
 
 __u32 pid = 0;
@@ -274,4 +284,111 @@ int uaf(const void *ctx)
 	return 0;
 }
 
+#if __clang_major__ >= 18
+__u8 __arena_global load_acquire8_value = 0x12;
+__u16 __arena_global load_acquire16_value = 0x1234;
+__u32 __arena_global load_acquire32_value = 0x12345678;
+__u64 __arena_global load_acquire64_value = 0x1234567890abcdef;
+
+__u8 __arena_global load_acquire8_result = 0;
+__u16 __arena_global load_acquire16_result = 0;
+__u32 __arena_global load_acquire32_result = 0;
+__u64 __arena_global load_acquire64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global load_acquire8_value;
+__u64 __arena_global load_acquire16_value;
+__u64 __arena_global load_acquire32_value;
+__u64 __arena_global load_acquire64_value;
+
+__u64 __arena_global load_acquire8_result;
+__u64 __arena_global load_acquire16_result;
+__u64 __arena_global load_acquire32_result;
+__u64 __arena_global load_acquire64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int load_acquire(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define LOAD_ACQUIRE_ARENA(SIZEOP, SIZE, SRC, DST)	\
+	{ asm volatile (				\
+	"r1 = %[" #SRC "] ll;"				\
+	"r1 = addr_space_cast(r1, 0x0, 0x1);"		\
+	".8byte %[load_acquire_insn];"			\
+	"r3 = %[" #DST "] ll;"				\
+	"r3 = addr_space_cast(r3, 0x0, 0x1);"		\
+	"*(" #SIZE " *)(r3 + 0) = r2;"			\
+	:						\
+	: __imm_addr(SRC),				\
+	  __imm_insn(load_acquire_insn,			\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_LOAD_ACQ,	\
+				   BPF_REG_2, BPF_REG_1, 0)),	\
+	  __imm_addr(DST)				\
+	: __clobber_all); }				\
+
+	LOAD_ACQUIRE_ARENA(B, u8, load_acquire8_value, load_acquire8_result)
+	LOAD_ACQUIRE_ARENA(H, u16, load_acquire16_value,
+			   load_acquire16_result)
+	LOAD_ACQUIRE_ARENA(W, u32, load_acquire32_value,
+			   load_acquire32_result)
+	LOAD_ACQUIRE_ARENA(DW, u64, load_acquire64_value,
+			   load_acquire64_result)
+#undef LOAD_ACQUIRE_ARENA
+
+#endif
+	return 0;
+}
+
+#if __clang_major__ >= 18
+__u8 __arena_global store_release8_result = 0;
+__u16 __arena_global store_release16_result = 0;
+__u32 __arena_global store_release32_result = 0;
+__u64 __arena_global store_release64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global store_release8_result;
+__u64 __arena_global store_release16_result;
+__u64 __arena_global store_release32_result;
+__u64 __arena_global store_release64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int store_release(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define STORE_RELEASE_ARENA(SIZEOP, DST, VAL)	\
+	{ asm volatile (			\
+	"r1 = " VAL ";"				\
+	"r2 = %[" #DST "] ll;"			\
+	"r2 = addr_space_cast(r2, 0x0, 0x1);"	\
+	".8byte %[store_release_insn];"		\
+	:					\
+	: __imm_addr(DST),			\
+	  __imm_insn(store_release_insn,	\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_STORE_REL,	\
+				   BPF_REG_2, BPF_REG_1, 0))	\
+	: __clobber_all); }			\
+
+	STORE_RELEASE_ARENA(B, store_release8_result, "0x12")
+	STORE_RELEASE_ARENA(H, store_release16_result, "0x1234")
+	STORE_RELEASE_ARENA(W, store_release32_result, "0x12345678")
+	STORE_RELEASE_ARENA(DW, store_release64_result,
+			    "0x1234567890abcdef ll")
+#undef STORE_RELEASE_ARENA
+
+#endif
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
new file mode 100644
index 000000000000..ff308f24d745
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("load-acquire, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void load_acquire_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	"*(u8 *)(r10 - 1) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r10 - 1));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void load_acquire_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	"*(u16 *)(r10 - 2) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u16 *)(r10 - 2));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void load_acquire_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	"*(u32 *)(r10 - 4) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 4));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void load_acquire_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r10 - 8));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void load_acquire_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with non-pointer src_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void load_acquire_with_non_pointer_src_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned load-acquire")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void load_acquire_misaligned(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 5));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire from ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC loads from R1 ctx is not allowed")
+__naked void load_acquire_from_ctx_pointer(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("load-acquire from pkt pointer")
+__failure __msg("BPF_ATOMIC loads from R2 pkt is not allowed")
+__naked void load_acquire_from_pkt_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("load-acquire from flow_keys pointer")
+__failure __msg("BPF_ATOMIC loads from R2 flow_keys is not allowed")
+__naked void load_acquire_from_flow_keys_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("load-acquire from sock pointer")
+__failure __msg("BPF_ATOMIC loads from R2 sock is not allowed")
+__naked void load_acquire_from_sock_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support load-acquire, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 6b564d4c0986..6662d4b39969 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -2,6 +2,7 @@
 /* Copyright (C) 2023 SUSE LLC */
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
 #include "bpf_misc.h"
 
 SEC("?raw_tp")
@@ -90,6 +91,54 @@ __naked int bpf_end_bswap(void)
 		::: __clobber_all);
 }
 
+#if defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r3 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (db) r2 = load_acquire((u64 *)(r10 -8))")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (7b) *(u64 *)(r10 -8) = r1")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_load_acquire(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" /* r2 = load_acquire((u64 *)(r10 - 8)); */
+	"r3 = r10;"
+	"r3 += r2;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r1 stack= before 3: (bf) r2 = r10")
+__msg("mark_precise: frame0: regs=r1 stack= before 2: (79) r1 = *(u64 *)(r10 -8)")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (db) store_release((u64 *)(r10 -8), r1)")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_store_release(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	".8byte %[store_release_insn];" /* store_release((u64 *)(r10 - 8), r1); */
+	"r1 = *(u64 *)(r10 - 8);"
+	"r2 = r10;"
+	"r2 += r1;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+#endif /* load-acquire, store-release */
 #endif /* v4 instruction */
 
 SEC("?raw_tp")
diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/tools/testing/selftests/bpf/progs/verifier_store_release.c
new file mode 100644
index 000000000000..f1c64c08f25f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("store-release, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void store_release_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1);
+	"w0 = *(u8 *)(r10 - 1);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void store_release_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1);
+	"w0 = *(u16 *)(r10 - 2);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void store_release_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1);
+	"w0 = *(u32 *)(r10 - 4);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void store_release_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = *(u64 *)(r10 - 8);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r2);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_2, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized dst_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r2 - 8), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with non-pointer dst_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void store_release_with_non_pointer_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r1 + 0), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_1, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned store-release")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void store_release_misaligned(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 5), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_0, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release to ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC stores into R1 ctx is not allowed")
+__naked void store_release_to_ctx_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r1 + 0), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_1, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("store-release to pkt pointer")
+__failure __msg("BPF_ATOMIC stores into R2 pkt is not allowed")
+__naked void store_release_to_pkt_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("store-release to flow_keys pointer")
+__failure __msg("BPF_ATOMIC stores into R2 flow_keys is not allowed")
+__naked void store_release_to_flow_keys_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("store-release to sock pointer")
+__failure __msg("BPF_ATOMIC stores into R2 sock is not allowed")
+__naked void store_release_to_sock_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, leak pointer to stack")
+__success __success_unpriv __retval(0)
+__naked void store_release_leak_pointer_to_stack(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 1);
+	__type(key, long long);
+	__type(value, long long);
+} map_hash_8b SEC(".maps");
+
+SEC("socket")
+__description("store-release, leak pointer to map")
+__success __retval(0)
+__failure_unpriv __msg_unpriv("R6 leaks addr into map")
+__naked void store_release_leak_pointer_to_map(void)
+{
+	asm volatile (
+	"r6 = r1;"
+	"r1 = %[map_hash_8b] ll;"
+	"r2 = 0;"
+	"*(u64 *)(r10 - 8) = r2;"
+	"r2 = r10;"
+	"r2 += -8;"
+	"call %[bpf_map_lookup_elem];"
+	"if r0 == 0 goto l0_%=;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r0 + 0), r6);
+"l0_%=:"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_addr(map_hash_8b),
+	  __imm(bpf_map_lookup_elem),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_0, BPF_REG_6, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support store-release, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:38:29 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:38:29 +0000
Subject: [PATCH bpf-next v4 10/10] bpf, docs: Update instruction-set.rst for
 load-acquire and store-release instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <c835515c35ec4ed59232adc3c02e1e90aa8ed8be.1740978603.git.yepeilin@google.com>

Update documentation for the new load-acquire and store-release
instructions.  Rename existing atomic operations as "atomic
read-modify-write (RMW) operations".

Following RFC 9669, section 7.3. "Adding Instructions", create new
conformance groups "atomic32v2" and "atomic64v2", where:

  * atomic32v2: includes all instructions in "atomic32", plus the new
                8-bit, 16-bit and 32-bit atomic load-acquire and
                store-release instructions

  * atomic64v2: includes all instructions in "atomic64" and
                "atomic32v2", plus the new 64-bit atomic load-acquire
                and store-release instructions

Cc: bpf at ietf.org
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 .../bpf/standardization/instruction-set.rst   | 78 +++++++++++++++----
 1 file changed, 62 insertions(+), 16 deletions(-)

diff --git a/Documentation/bpf/standardization/instruction-set.rst b/Documentation/bpf/standardization/instruction-set.rst
index fbe975585236..1bed27572bca 100644
--- a/Documentation/bpf/standardization/instruction-set.rst
+++ b/Documentation/bpf/standardization/instruction-set.rst
@@ -139,8 +139,14 @@ This document defines the following conformance groups:
   specification unless otherwise noted.
 * base64: includes base32, plus instructions explicitly noted
   as being in the base64 conformance group.
-* atomic32: includes 32-bit atomic operation instructions (see `Atomic operations`_).
-* atomic64: includes atomic32, plus 64-bit atomic operation instructions.
+* atomic32: includes 32-bit atomic read-modify-write instructions (see
+  `Atomic operations`_).
+* atomic32v2: includes atomic32, plus 8-bit, 16-bit and 32-bit atomic
+  load-acquire and store-release instructions.
+* atomic64: includes atomic32, plus 64-bit atomic read-modify-write
+  instructions.
+* atomic64v2: unifies atomic32v2 and atomic64, plus 64-bit atomic load-acquire
+  and store-release instructions.
 * divmul32: includes 32-bit division, multiplication, and modulo instructions.
 * divmul64: includes divmul32, plus 64-bit division, multiplication,
   and modulo instructions.
@@ -661,20 +667,29 @@ Atomic operations are operations that operate on memory and can not be
 interrupted or corrupted by other access to the same memory region
 by other BPF programs or means outside of this specification.
 
-All atomic operations supported by BPF are encoded as store operations
-that use the ``ATOMIC`` mode modifier as follows:
+All atomic operations supported by BPF are encoded as ``STX`` instructions
+that use the ``ATOMIC`` mode modifier, with the 'imm' field encoding the
+actual atomic operation.  These operations fall into two categories, as
+described in the following sections:
 
-* ``{ATOMIC, W, STX}`` for 32-bit operations, which are
+* `Atomic read-modify-write operations`_
+* `Atomic load and store operations`_
+
+Atomic read-modify-write operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The atomic read-modify-write (RMW) operations are encoded as follows:
+
+* ``{ATOMIC, W, STX}`` for 32-bit RMW operations, which are
   part of the "atomic32" conformance group.
-* ``{ATOMIC, DW, STX}`` for 64-bit operations, which are
+* ``{ATOMIC, DW, STX}`` for 64-bit RMW operations, which are
   part of the "atomic64" conformance group.
-* 8-bit and 16-bit wide atomic operations are not supported.
+* 8-bit and 16-bit wide atomic RMW operations are not supported.
 
-The 'imm' field is used to encode the actual atomic operation.
-Simple atomic operation use a subset of the values defined to encode
-arithmetic operations in the 'imm' field to encode the atomic operation:
+Simple atomic RMW operation use a subset of the values defined to encode
+arithmetic operations in the 'imm' field to encode the atomic RMW operation:
 
-.. table:: Simple atomic operations
+.. table:: Simple atomic read-modify-write operations
 
   ========  =====  ===========
   imm       value  description
@@ -694,10 +709,10 @@ arithmetic operations in the 'imm' field to encode the atomic operation:
 
   *(u64 *)(dst + offset) += src
 
-In addition to the simple atomic operations, there also is a modifier and
-two complex atomic operations:
+In addition to the simple atomic RMW operations, there also is a modifier and
+two complex atomic RMW operations:
 
-.. table:: Complex atomic operations
+.. table:: Complex atomic read-modify-write operations
 
   ===========  ================  ===========================
   imm          value             description
@@ -707,8 +722,8 @@ two complex atomic operations:
   CMPXCHG      0xf0 | FETCH      atomic compare and exchange
   ===========  ================  ===========================
 
-The ``FETCH`` modifier is optional for simple atomic operations, and
-always set for the complex atomic operations.  If the ``FETCH`` flag
+The ``FETCH`` modifier is optional for simple atomic RMW operations, and
+always set for the complex atomic RMW operations.  If the ``FETCH`` flag
 is set, then the operation also overwrites ``src`` with the value that
 was in memory before it was modified.
 
@@ -721,6 +736,37 @@ The ``CMPXCHG`` operation atomically compares the value addressed by
 value that was at ``dst + offset`` before the operation is zero-extended
 and loaded back to ``R0``.
 
+Atomic load and store operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To encode an atomic load or store operation, the 'imm' field is one of:
+
+.. table:: Atomic load and store operations
+
+  ========= =====  ====================
+  imm       value  description
+  ========= =====  ====================
+  LOAD_ACQ  0x100  atomic load-acquire
+  STORE_REL 0x110  atomic store-release
+  ========= =====  ====================
+
+``{ATOMIC, <size>, STX}`` with 'imm' = LOAD_ACQ means::
+
+  dst = load_acquire((unsigned size *)(src + offset))
+
+``{ATOMIC, <size>, STX}`` with 'imm' = STORE_REL means::
+
+  store_release((unsigned size *)(dst + offset), src)
+
+Where '<size>' is one of: ``B``, ``H``, ``W``, or ``DW``, and 'unsigned size'
+is one of: u8, u16, u32, or u64.
+
+8-bit, 16-bit and 32-bit atomic load-acquire and store-release instructions
+are part of the "atomic32v2" conformance group.
+
+64-bit atomic load-acquire and store-release instructions are part of the
+"atomic64v2" conformance group.
+
 64-bit immediate instructions
 -----------------------------
 
-- 
2.48.1.711.g2feabab25a-goog



From s-vadapalli at ti.com  Sun Mar  2 21:44:53 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Mon, 3 Mar 2025 11:14:53 +0530
Subject: [PATCH v2 1/2] arm64: dts: ti: k3-am68-sk/k3-j721s2-mcu: Add
 bootph-all property to enable Ethernet boot
In-Reply-To: <20250302153502.181832-2-c-vankar@ti.com>
References: <20250302153502.181832-1-c-vankar@ti.com>
 <20250302153502.181832-2-c-vankar@ti.com>
Message-ID: <20250303054453.r6r7i25ewdoosyzk@uda0492258>

On Sun, Mar 02, 2025 at 09:05:01PM +0530, Chintan Vankar wrote:
> Ethernet boot requires CPSW nodes to be present starting from R5 SPL
> stage. Add bootph-all property to required nodes to enable Ethernet boot
> on AM68-SK and J721S2-EVM.
> 
> Signed-off-by: Chintan Vankar <c-vankar at ti.com>

Reviewed-by: Siddharth Vadapalli <s-vadapalli at ti.com>

Regards,
Siddharth.


From yepeilin at google.com  Sun Mar  2 21:36:27 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:36:27 +0000
Subject: [PATCH bpf-next v4 00/10] Introduce load-acquire and store-release
 BPF instructions
Message-ID: <cover.1740978603.git.yepeilin@google.com>

Hi all!

This patchset adds kernel support for BPF load-acquire and store-release
instructions (for background, please see [1]), including core/verifier,
arm64/x86-64 JIT compiler and Documentation/ changes, as well as
selftests.  riscv64 is also planned to be supported.  The corresponding
LLVM changes can be found at:

  https://github.com/llvm/llvm-project/pull/108636

Please refer to the LLVM PR and individual kernel patches for details.
Thanks!

v3: https://lore.kernel.org/bpf/cover.1740009184.git.yepeilin at google.com/
v3..v4 notable changes:

  o (Alexei) add x86-64 JIT support (including arena)
  o add Acked-by: tags from Xu

v2: https://lore.kernel.org/bpf/cover.1738888641.git.yepeilin at google.com/
v2..v3 notable changes:

  o (Alexei) change encoding to BPF_LOAD_ACQ=0x100, BPF_STORE_REL=0x110
  o add Acked-by: tags from Ilya and Eduard
  o make new selftests depend on:
    * __clang_major__ >= 18, and
    * ENABLE_ATOMICS_TESTS is defined (currently this means -mcpu=v3 or
      v4), and
    * JIT supports load_acq/store_rel (currenty only arm64)
  o work around llvm-17 CI job failure by conditionally define
    __arena_global variables as 64-bit if __clang_major__ < 18, to make
    sure .addr_space.1 has no holes
  o add Google copyright notice in new files

v1: https://lore.kernel.org/all/cover.1737763916.git.yepeilin at google.com/
v1..v2 notable changes:

  o (Eduard) for x86 and s390, make
             bpf_jit_supports_insn(..., /*in_arena=*/true) return false
	     for load_acq/store_rel
  o add Eduard's Acked-by: tag
  o (Eduard) extract LDX and non-ATOMIC STX handling into helpers, see
             PATCH v2 3/9
  o allow unpriv programs to store-release pointers to stack
  o (Alexei) make it clearer in the interpreter code (PATCH v2 4/9) that
             only W and DW are supported for atomic RMW
  o test misaligned load_acq/store_rel
  o (Eduard) other selftests/ changes:
    * test load_acq/store_rel with !atomic_ptr_type_ok() pointers:
      - PTR_TO_CTX, for is_ctx_reg()
      - PTR_TO_PACKET, for is_pkt_reg()
      - PTR_TO_FLOW_KEYS, for is_flow_key_reg()
      - PTR_TO_SOCKET, for is_sk_reg()
    * drop atomics/ tests
    * delete unnecessary 'pid' checks from arena_atomics/ tests
    * avoid depending on __BPF_FEATURE_LOAD_ACQ_STORE_REL, use
      __imm_insn() and inline asm macros instead

RFC v1: https://lore.kernel.org/all/cover.1734742802.git.yepeilin at google.com
RFC v1..v1 notable changes:

  o 1-2/8: minor verifier.c refactoring patches
  o   3/8: core/verifier changes
         * (Eduard) handle load-acquire properly in backtrack_insn()
         * (Eduard) avoid skipping checks (e.g.,
                    bpf_jit_supports_insn()) for load-acquires
         * track the value stored by store-releases, just like how
           non-atomic STX instructions are handled
         * (Eduard) add missing link in commit message
         * (Eduard) always print 'r' for disasm.c changes
  o   4/8: arm64/insn: avoid treating load_acq/store_rel as
           load_ex/store_ex
  o   5/8: arm64/insn: add load_acq/store_rel
         * (Xu) include Should-Be-One (SBO) bits in "mask" and "value",
                to avoid setting fixed bits during runtime (JIT-compile
                time)
  o   6/8: arm64 JIT compiler changes
         * (Xu) use emit_a64_add_i() for "pointer + offset" to optimize
                code emission
  o   7/8: selftests
         * (Eduard) avoid adding new tests to the 'test_verifier' runner
         * add more tests, e.g., checking mark_precise logic
  o   8/8: instruction-set.rst changes

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Thanks,
Peilin Ye (10):
  bpf/verifier: Factor out atomic_ptr_type_ok()
  bpf/verifier: Factor out check_atomic_rmw()
  bpf/verifier: Factor out check_load_mem() and check_store_reg()
  bpf: Introduce load-acquire and store-release instructions
  arm64: insn: Add BIT(23) to {load,store}_ex's mask
  arm64: insn: Add load-acquire and store-release instructions
  bpf, arm64: Support load-acquire and store-release instructions
  bpf, x86: Support load-acquire and store-release instructions
  selftests/bpf: Add selftests for load-acquire and store-release
    instructions
  bpf, docs: Update instruction-set.rst for load-acquire and
    store-release instructions

 .../bpf/standardization/instruction-set.rst   |  78 ++++--
 arch/arm64/include/asm/insn.h                 |  12 +-
 arch/arm64/lib/insn.c                         |  29 ++
 arch/arm64/net/bpf_jit.h                      |  20 ++
 arch/arm64/net/bpf_jit_comp.c                 |  86 +++++-
 arch/s390/net/bpf_jit_comp.c                  |  14 +-
 arch/x86/net/bpf_jit_comp.c                   |  95 ++++++-
 include/linux/bpf.h                           |  15 +
 include/linux/filter.h                        |   2 +
 include/uapi/linux/bpf.h                      |   3 +
 kernel/bpf/core.c                             |  63 ++++-
 kernel/bpf/disasm.c                           |  12 +
 kernel/bpf/verifier.c                         | 234 +++++++++++-----
 tools/include/uapi/linux/bpf.h                |   3 +
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 20 files changed, 1246 insertions(+), 121 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:07 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:07 +0000
Subject: [PATCH bpf-next v4 01/10] bpf/verifier: Factor out atomic_ptr_type_ok()
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <e5ef8b3116f3fffce78117a14060ddce05eba52a.1740978603.git.yepeilin@google.com>

Factor out atomic_ptr_type_ok() as a helper function to be used later.

Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 kernel/bpf/verifier.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index eb1624f6e743..66b19fa4be48 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -6195,6 +6195,26 @@ static bool is_arena_reg(struct bpf_verifier_env *env, int regno)
 	return reg->type == PTR_TO_ARENA;
 }
 
+/* Return false if @regno contains a pointer whose type isn't supported for
+ * atomic instruction @insn.
+ */
+static bool atomic_ptr_type_ok(struct bpf_verifier_env *env, int regno,
+			       struct bpf_insn *insn)
+{
+	if (is_ctx_reg(env, regno))
+		return false;
+	if (is_pkt_reg(env, regno))
+		return false;
+	if (is_flow_key_reg(env, regno))
+		return false;
+	if (is_sk_reg(env, regno))
+		return false;
+	if (is_arena_reg(env, regno))
+		return bpf_jit_supports_insn(insn, true);
+
+	return true;
+}
+
 static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] = {
 #ifdef CONFIG_NET
 	[PTR_TO_SOCKET] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK],
@@ -7652,11 +7672,7 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
 		return -EACCES;
 	}
 
-	if (is_ctx_reg(env, insn->dst_reg) ||
-	    is_pkt_reg(env, insn->dst_reg) ||
-	    is_flow_key_reg(env, insn->dst_reg) ||
-	    is_sk_reg(env, insn->dst_reg) ||
-	    (is_arena_reg(env, insn->dst_reg) && !bpf_jit_supports_insn(insn, true))) {
+	if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) {
 		verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n",
 			insn->dst_reg,
 			reg_type_str(env, reg_state(env, insn->dst_reg)->type));
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:19 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:19 +0000
Subject: [PATCH bpf-next v4 02/10] bpf/verifier: Factor out check_atomic_rmw()
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <6323ac8e73a10a1c8ee547c77ed68cf8eb6b90e1.1740978603.git.yepeilin@google.com>

Currently, check_atomic() only handles atomic read-modify-write (RMW)
instructions.  Since we are planning to introduce other types of atomic
instructions (i.e., atomic load/store), extract the existing RMW
handling logic into its own function named check_atomic_rmw().

Remove the @insn_idx parameter as it is not really necessary.  Use
'env->insn_idx' instead, as in other places in verifier.c.

Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 kernel/bpf/verifier.c | 53 +++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 66b19fa4be48..e3991ac72029 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7616,28 +7616,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
 static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type type,
 			     bool allow_trust_mismatch);
 
-static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_insn *insn)
+static int check_atomic_rmw(struct bpf_verifier_env *env,
+			    struct bpf_insn *insn)
 {
 	int load_reg;
 	int err;
 
-	switch (insn->imm) {
-	case BPF_ADD:
-	case BPF_ADD | BPF_FETCH:
-	case BPF_AND:
-	case BPF_AND | BPF_FETCH:
-	case BPF_OR:
-	case BPF_OR | BPF_FETCH:
-	case BPF_XOR:
-	case BPF_XOR | BPF_FETCH:
-	case BPF_XCHG:
-	case BPF_CMPXCHG:
-		break;
-	default:
-		verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", insn->imm);
-		return -EINVAL;
-	}
-
 	if (BPF_SIZE(insn->code) != BPF_W && BPF_SIZE(insn->code) != BPF_DW) {
 		verbose(env, "invalid atomic operand size\n");
 		return -EINVAL;
@@ -7699,12 +7683,12 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
 	/* Check whether we can read the memory, with second call for fetch
 	 * case to simulate the register fill.
 	 */
-	err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
+	err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
 			       BPF_SIZE(insn->code), BPF_READ, -1, true, false);
 	if (!err && load_reg >= 0)
-		err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
-				       BPF_SIZE(insn->code), BPF_READ, load_reg,
-				       true, false);
+		err = check_mem_access(env, env->insn_idx, insn->dst_reg,
+				       insn->off, BPF_SIZE(insn->code),
+				       BPF_READ, load_reg, true, false);
 	if (err)
 		return err;
 
@@ -7714,13 +7698,34 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
 			return err;
 	}
 	/* Check whether we can write into the same memory. */
-	err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
+	err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
 			       BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
 	if (err)
 		return err;
 	return 0;
 }
 
+static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
+{
+	switch (insn->imm) {
+	case BPF_ADD:
+	case BPF_ADD | BPF_FETCH:
+	case BPF_AND:
+	case BPF_AND | BPF_FETCH:
+	case BPF_OR:
+	case BPF_OR | BPF_FETCH:
+	case BPF_XOR:
+	case BPF_XOR | BPF_FETCH:
+	case BPF_XCHG:
+	case BPF_CMPXCHG:
+		return check_atomic_rmw(env, insn);
+	default:
+		verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
+			insn->imm);
+		return -EINVAL;
+	}
+}
+
 /* When register 'regno' is used to read the stack (either directly or through
  * a helper function) make sure that it's within stack boundary and, depending
  * on the access type and privileges, that all elements of the stack are
@@ -19224,7 +19229,7 @@ static int do_check(struct bpf_verifier_env *env)
 			enum bpf_reg_type dst_reg_type;
 
 			if (BPF_MODE(insn->code) == BPF_ATOMIC) {
-				err = check_atomic(env, env->insn_idx, insn);
+				err = check_atomic(env, insn);
 				if (err)
 					return err;
 				env->insn_idx++;
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:37:25 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon,  3 Mar 2025 05:37:25 +0000
Subject: [PATCH bpf-next v4 03/10] bpf/verifier: Factor out check_load_mem()
 and check_store_reg()
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com>

Extract BPF_LDX and most non-ATOMIC BPF_STX instruction handling logic
in do_check() into helper functions to be used later.  While we are
here, make that comment about "reserved fields" more specific.

Suggested-by: Eduard Zingerman <eddyz87 at gmail.com>
Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 kernel/bpf/verifier.c | 110 +++++++++++++++++++++++++-----------------
 1 file changed, 67 insertions(+), 43 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e3991ac72029..22c4edc8695c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7616,6 +7616,67 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
 static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type type,
 			     bool allow_trust_mismatch);
 
+static int check_load_mem(struct bpf_verifier_env *env, struct bpf_insn *insn,
+			  bool strict_alignment_once, bool is_ldsx,
+			  bool allow_trust_mismatch, const char *ctx)
+{
+	struct bpf_reg_state *regs = cur_regs(env);
+	enum bpf_reg_type src_reg_type;
+	int err;
+
+	/* check src operand */
+	err = check_reg_arg(env, insn->src_reg, SRC_OP);
+	if (err)
+		return err;
+
+	/* check dst operand */
+	err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
+	if (err)
+		return err;
+
+	src_reg_type = regs[insn->src_reg].type;
+
+	/* Check if (src_reg + off) is readable. The state of dst_reg will be
+	 * updated by this call.
+	 */
+	err = check_mem_access(env, env->insn_idx, insn->src_reg, insn->off,
+			       BPF_SIZE(insn->code), BPF_READ, insn->dst_reg,
+			       strict_alignment_once, is_ldsx);
+	err = err ?: save_aux_ptr_type(env, src_reg_type,
+				       allow_trust_mismatch);
+	err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], ctx);
+
+	return err;
+}
+
+static int check_store_reg(struct bpf_verifier_env *env, struct bpf_insn *insn,
+			   bool strict_alignment_once)
+{
+	struct bpf_reg_state *regs = cur_regs(env);
+	enum bpf_reg_type dst_reg_type;
+	int err;
+
+	/* check src1 operand */
+	err = check_reg_arg(env, insn->src_reg, SRC_OP);
+	if (err)
+		return err;
+
+	/* check src2 operand */
+	err = check_reg_arg(env, insn->dst_reg, SRC_OP);
+	if (err)
+		return err;
+
+	dst_reg_type = regs[insn->dst_reg].type;
+
+	/* Check if (dst_reg + off) is writeable. */
+	err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
+			       BPF_SIZE(insn->code), BPF_WRITE, insn->src_reg,
+			       strict_alignment_once, false);
+	err = err ?: save_aux_ptr_type(env, dst_reg_type, false);
+
+	return err;
+}
+
 static int check_atomic_rmw(struct bpf_verifier_env *env,
 			    struct bpf_insn *insn)
 {
@@ -19199,35 +19260,16 @@ static int do_check(struct bpf_verifier_env *env)
 				return err;
 
 		} else if (class == BPF_LDX) {
-			enum bpf_reg_type src_reg_type;
-
-			/* check for reserved fields is already done */
-
-			/* check src operand */
-			err = check_reg_arg(env, insn->src_reg, SRC_OP);
-			if (err)
-				return err;
+			bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
 
-			err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
-			if (err)
-				return err;
-
-			src_reg_type = regs[insn->src_reg].type;
-
-			/* check that memory (src_reg + off) is readable,
-			 * the state of dst_reg will be updated by this func
+			/* Check for reserved fields is already done in
+			 * resolve_pseudo_ldimm64().
 			 */
-			err = check_mem_access(env, env->insn_idx, insn->src_reg,
-					       insn->off, BPF_SIZE(insn->code),
-					       BPF_READ, insn->dst_reg, false,
-					       BPF_MODE(insn->code) == BPF_MEMSX);
-			err = err ?: save_aux_ptr_type(env, src_reg_type, true);
-			err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], "ldx");
+			err = check_load_mem(env, insn, false, is_ldsx, true,
+					     "ldx");
 			if (err)
 				return err;
 		} else if (class == BPF_STX) {
-			enum bpf_reg_type dst_reg_type;
-
 			if (BPF_MODE(insn->code) == BPF_ATOMIC) {
 				err = check_atomic(env, insn);
 				if (err)
@@ -19241,25 +19283,7 @@ static int do_check(struct bpf_verifier_env *env)
 				return -EINVAL;
 			}
 
-			/* check src1 operand */
-			err = check_reg_arg(env, insn->src_reg, SRC_OP);
-			if (err)
-				return err;
-			/* check src2 operand */
-			err = check_reg_arg(env, insn->dst_reg, SRC_OP);
-			if (err)
-				return err;
-
-			dst_reg_type = regs[insn->dst_reg].type;
-
-			/* check that memory (dst_reg + off) is writeable */
-			err = check_mem_access(env, env->insn_idx, insn->dst_reg,
-					       insn->off, BPF_SIZE(insn->code),
-					       BPF_WRITE, insn->src_reg, false, false);
-			if (err)
-				return err;
-
-			err = save_aux_ptr_type(env, dst_reg_type, false);
+			err = check_store_reg(env, insn, false);
 			if (err)
 				return err;
 		} else if (class == BPF_ST) {
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Sun Mar  2 21:46:10 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon, 3 Mar 2025 05:46:10 +0000
Subject: [PATCH bpf-next v4 08/10] bpf, x86: Support load-acquire and
 store-release instructions
In-Reply-To: <ea2754510513dce17a1d8f4fcab07d9d769e7b08.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
 <ea2754510513dce17a1d8f4fcab07d9d769e7b08.1740978603.git.yepeilin@google.com>
Message-ID: <Z8VCIrnJ10uBj0yN@google.com>

Hi Alexei,

On Mon, Mar 03, 2025 at 05:38:07AM +0000, Peilin Ye wrote:
> Recently we introduced BPF load-acquire (BPF_LOAD_ACQ) and store-release
> (BPF_STORE_REL) instructions.  For x86-64, simply implement them as
> regular BPF_LDX/BPF_STX loads and stores.  The verifier always rejects
> misaligned load-acquires/store-releases (even if BPF_F_ANY_ALIGNMENT is
> set), so emitted MOV* instructions are guaranteed to be atomic.
> 
> Arena accesses are supported.  8- and 16-bit load-acquires are
> zero-extending (i.e., MOVZBQ, MOVZWQ).
> 
> Rename emit_atomic{,_index}() to emit_atomic_rmw{,_index}() to make it
> clear that they only handle read-modify-write atomics, and extend their
> @atomic_op parameter from u8 to u32, since we are starting to use more
> than the lowest 8 bits of the 'imm' field.

For x86-64, v4 PATCH 08/10 implements ld_acq/st_rel as regular LDX/STX
(aligned) loads/stores.  Please take another look.  Thanks!

Peilin Ye



From andyshrk at 163.com  Sun Mar  2 22:17:50 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 3 Mar 2025 14:17:50 +0800 (CST)
Subject: [PATCH v15 07/13] drm/rockchip: vop2: Register the primary
 plane and overlay plane separately
In-Reply-To: <2759797.BddDVKsqQX@diego>
References: <20250218112744.34433-1-andyshrk@163.com>
 <20250218112744.34433-8-andyshrk@163.com> <2759797.BddDVKsqQX@diego>
Message-ID: <1c3ed06d.5e89.1955aa75521.Coremail.andyshrk@163.com>


Hi Heiko,

At 2025-03-03 02:57:50, "Heiko St?bner" <heiko at sntech.de> wrote:
>Hi Andy,
>
>Am Dienstag, 18. Februar 2025, 12:27:34 MEZ schrieb Andy Yan:
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> In the upcoming VOP of rk3576, a Window cannot attach to all Video Ports,
>> so make sure all VP find it's suitable primary plane, then register the
>> remain windows as overlay plane will make code easier.
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> Tested-by: Michael Riesch <michael.riesch at wolfvision.net> # on RK3568
>> Tested-by: Detlev Casanova <detlev.casanova at collabora.com>
>> 
>> ---
>
>patches 7-9 look good to go, but ...
>
>this needs a rebase to adapt to
>"drm/rockchip: vop2: Consistently use dev_err_probe()" [0]
>
>[0] https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/b06d1ef3355571383cdb463cf0195b7a02efdfbf


Thank you.
I sent V16 with the remaining patches rebased on drm-misc-next, and fix the style issues.


>
>
>> -		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
>> -			vp = find_vp_without_primary(vop2);
>> -			if (vp) {
>> +			if (vop2_is_mirror_win(win))
>> +				continue;
>> +
>> +			if (win->type == DRM_PLANE_TYPE_PRIMARY) {
>>  				possible_crtcs = BIT(nvp);
>>  				vp->primary_plane = win;
>> +				ret = vop2_plane_init(vop2, win, possible_crtcs);
>> +				if (ret) {
>> +					drm_err(vop2->drm, "failed to init primary plane %s: %d\n",
>> +						win->data->name, ret);
>
>should also use dev_err_probe
>
>
>Heiko
>
>

From gshan at redhat.com  Sun Mar  2 22:25:48 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 16:25:48 +1000
Subject: [PATCH v7 11/45] arm64: RME: RTT tear down
In-Reply-To: <20250213161426.102987-12-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-12-steven.price@arm.com>
Message-ID: <e432ee67-6afb-40c8-9542-48770834ee40@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> The RMM owns the stage 2 page tables for a realm, and KVM must request
> that the RMM creates/destroys entries as necessary. The physical pages
> to store the page tables are delegated to the realm as required, and can
> be undelegated when no longer used.
> 
> Creating new RTTs is the easy part, tearing down is a little more
> tricky. The result of realm_rtt_destroy() can be used to effectively
> walk the tree and destroy the entries (undelegating pages that were
> given to the realm).
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
> Changes since v6:
>   * Move rme_rtt_level_mapsize() and supporting defines from kvm_rme.h
>     into rme.c as they are only used in that file.
> Changes since v5:
>   * Rename some RME_xxx defines to do with page sizes as RMM_xxx - they are
>     a property of the RMM specification not the RME architecture.
> Changes since v2:
>   * Moved {alloc,free}_delegated_page() and ensure_spare_page() to a
>     later patch when they are actually used.
>   * Some simplifications now rmi_xxx() functions allow NULL as an output
>     parameter.
>   * Improved comments and code layout.
> ---
>   arch/arm64/include/asm/kvm_rme.h |   7 ++
>   arch/arm64/kvm/mmu.c             |   6 +-
>   arch/arm64/kvm/rme.c             | 128 +++++++++++++++++++++++++++++++
>   3 files changed, 138 insertions(+), 3 deletions(-)

Reviewed-by: Gavin Shan <gshan at redhat.com>



From bookyungwook at gmail.com  Sun Mar  2 22:48:42 2025
From: bookyungwook at gmail.com (Kyungwook Boo)
Date: Mon, 3 Mar 2025 15:48:42 +0900
Subject: Null-ptr-deref in xcv_init_hw()
Message-ID: <76e7268f-c4e3-43a3-957f-b7246d953c6a@gmail.com>

Hello,

It seems that xcv_init_hw() can be called in bgx_probe() regardless of whether
xcv_probe() has been executed, leading to a potential null pointer dereference.

The following is a call stack example:

bgx_probe
  ??? xcv_init_hw
  ?     ??? readq_relaxed(xcv->reg_base + XCV_RESET)  // NULL pointer dereference

In bgx_probe(), if the PCI device ID matched PCI_DEVICE_ID_THUNDER_RGX,
xcv_init_hw is called:

pci_read_config_word(pdev, PCI_DEVICE_ID, &sdevid);
if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) {
}
else{
    xcv_init_hw();
}

However, xcv_init_hw() performs an MMIO read on xcv->reg_base, which is expected
to be initialized by xcv_probe():

cfg = readq_relaxed(xcv->reg_base + XCV_RESET);


Could you check this?

Best regards,
Kyungwook Boo


From menglong8.dong at gmail.com  Sun Mar  2 22:53:43 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 14:53:43 +0800
Subject: [PATCH bpf-next v3 2/4] add per-function metadata storage support
In-Reply-To: <20250303065345.229298-1-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
Message-ID: <20250303065345.229298-3-dongml2@chinatelecom.cn>

For now, there isn't a way to set and get per-function metadata with
a low overhead, which is not convenient for some situations. Take
BPF trampoline for example, we need to create a trampoline for each
kernel function, as we have to store some information of the function
to the trampoline, such as BPF progs, function arg count, etc. The
performance overhead and memory consumption can be higher to create
these trampolines. With the supporting of per-function metadata storage,
we can store these information to the metadata, and create a global BPF
trampoline for all the kernel functions. In the global trampoline, we
get the information that we need from the function metadata through the
ip (function address) with almost no overhead.

Another beneficiary can be ftrace. For now, all the kernel functions that
are enabled by dynamic ftrace will be added to a filter hash if there are
more than one callbacks. And hash lookup will happen when the traced
functions are called, which has an impact on the performance, see
__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
metadata supporting, we can store the information that if the callback is
enabled on the kernel function to the metadata.

Support per-function metadata storage in the function padding, and
previous discussion can be found in [1]. Generally speaking, we have two
way to implement this feature:

1. Create a function metadata array, and prepend a insn which can hold
the index of the function metadata in the array. And store the insn to
the function padding.

2. Allocate the function metadata with kmalloc(), and prepend a insn which
hold the pointer of the metadata. And store the insn to the function
padding.

Compared with way 2, way 1 consume less space, but we need to do more work
on the global function metadata array. And we implement this function in
the way 1.

Link: https://lore.kernel.org/bpf/CADxym3anLzM6cAkn_z71GDd_VeKiqqk1ts=xuiP7pr4PO6USPA at mail.gmail.com/ [1]
Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
v2:
- add supporting for arm64
- split out arch relevant code
- refactor the commit log
---
 include/linux/kfunc_md.h |  25 ++++
 kernel/Makefile          |   1 +
 kernel/trace/Makefile    |   1 +
 kernel/trace/kfunc_md.c  | 239 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 266 insertions(+)
 create mode 100644 include/linux/kfunc_md.h
 create mode 100644 kernel/trace/kfunc_md.c

diff --git a/include/linux/kfunc_md.h b/include/linux/kfunc_md.h
new file mode 100644
index 000000000000..df616f0fcb36
--- /dev/null
+++ b/include/linux/kfunc_md.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KFUNC_MD_H
+#define _LINUX_KFUNC_MD_H
+
+#include <linux/kernel.h>
+
+struct kfunc_md {
+	int users;
+	/* we can use this field later, make sure it is 8-bytes aligned
+	 * for now.
+	 */
+	int pad0;
+	void *func;
+};
+
+extern struct kfunc_md *kfunc_mds;
+
+struct kfunc_md *kfunc_md_find(void *ip);
+struct kfunc_md *kfunc_md_get(void *ip);
+void kfunc_md_put(struct kfunc_md *meta);
+void kfunc_md_put_by_ip(void *ip);
+void kfunc_md_lock(void);
+void kfunc_md_unlock(void);
+
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index 87866b037fbe..7435674d5da3 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_TRACE_CLOCK) += trace/
 obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_TRACEPOINTS) += trace/
 obj-$(CONFIG_RETHOOK) += trace/
+obj-$(CONFIG_FUNCTION_METADATA) += trace/
 obj-$(CONFIG_IRQ_WORK) += irq_work.o
 obj-$(CONFIG_CPU_PM) += cpu_pm.o
 obj-$(CONFIG_BPF) += bpf/
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 057cd975d014..9780ee3f8d8d 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_FTRACE_RECORD_RECURSION) += trace_recursion_record.o
 obj-$(CONFIG_FPROBE) += fprobe.o
 obj-$(CONFIG_RETHOOK) += rethook.o
 obj-$(CONFIG_FPROBE_EVENTS) += trace_fprobe.o
+obj-$(CONFIG_FUNCTION_METADATA) += kfunc_md.o
 
 obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o
 obj-$(CONFIG_RV) += rv/
diff --git a/kernel/trace/kfunc_md.c b/kernel/trace/kfunc_md.c
new file mode 100644
index 000000000000..7ec25bcf778d
--- /dev/null
+++ b/kernel/trace/kfunc_md.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/slab.h>
+#include <linux/memory.h>
+#include <linux/rcupdate.h>
+#include <linux/ftrace.h>
+#include <linux/kfunc_md.h>
+
+#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct kfunc_md))
+
+static u32 kfunc_md_count = ENTRIES_PER_PAGE, kfunc_md_used;
+struct kfunc_md __rcu *kfunc_mds;
+EXPORT_SYMBOL_GPL(kfunc_mds);
+
+static DEFINE_MUTEX(kfunc_md_mutex);
+
+
+void kfunc_md_unlock(void)
+{
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_unlock);
+
+void kfunc_md_lock(void)
+{
+	mutex_lock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_lock);
+
+static u32 kfunc_md_get_index(void *ip)
+{
+	return *(u32 *)(ip - KFUNC_MD_DATA_OFFSET);
+}
+
+static void kfunc_md_init(struct kfunc_md *mds, u32 start, u32 end)
+{
+	u32 i;
+
+	for (i = start; i < end; i++)
+		mds[i].users = 0;
+}
+
+static int kfunc_md_page_order(void)
+{
+	return fls(DIV_ROUND_UP(kfunc_md_count, ENTRIES_PER_PAGE)) - 1;
+}
+
+/* Get next usable function metadata. On success, return the usable
+ * kfunc_md and store the index of it to *index. If no usable kfunc_md is
+ * found in kfunc_mds, a larger array will be allocated.
+ */
+static struct kfunc_md *kfunc_md_get_next(u32 *index)
+{
+	struct kfunc_md *new_mds, *mds;
+	u32 i, order;
+
+	mds = rcu_dereference(kfunc_mds);
+	if (mds == NULL) {
+		order = kfunc_md_page_order();
+		new_mds = (void *)__get_free_pages(GFP_KERNEL, order);
+		if (!new_mds)
+			return NULL;
+		kfunc_md_init(new_mds, 0, kfunc_md_count);
+		/* The first time to initialize kfunc_mds, so it is not
+		 * used anywhere yet, and we can update it directly.
+		 */
+		rcu_assign_pointer(kfunc_mds, new_mds);
+		mds = new_mds;
+	}
+
+	if (likely(kfunc_md_used < kfunc_md_count)) {
+		/* maybe we can manage the used function metadata entry
+		 * with a bit map ?
+		 */
+		for (i = 0; i < kfunc_md_count; i++) {
+			if (!mds[i].users) {
+				kfunc_md_used++;
+				*index = i;
+				mds[i].users++;
+				return mds + i;
+			}
+		}
+	}
+
+	order = kfunc_md_page_order();
+	/* no available function metadata, so allocate a bigger function
+	 * metadata array.
+	 */
+	new_mds = (void *)__get_free_pages(GFP_KERNEL, order + 1);
+	if (!new_mds)
+		return NULL;
+
+	memcpy(new_mds, mds, kfunc_md_count * sizeof(*new_mds));
+	kfunc_md_init(new_mds, kfunc_md_count, kfunc_md_count * 2);
+
+	rcu_assign_pointer(kfunc_mds, new_mds);
+	synchronize_rcu();
+	free_pages((u64)mds, order);
+
+	mds = new_mds + kfunc_md_count;
+	*index = kfunc_md_count;
+	kfunc_md_count <<= 1;
+	kfunc_md_used++;
+	mds->users++;
+
+	return mds;
+}
+
+static int kfunc_md_text_poke(void *ip, void *insn, void *nop)
+{
+	void *target;
+	int ret = 0;
+	u8 *prog;
+
+	target = ip - KFUNC_MD_INSN_OFFSET;
+	mutex_lock(&text_mutex);
+	if (insn) {
+		if (!memcmp(target, insn, KFUNC_MD_INSN_SIZE))
+			goto out;
+
+		if (memcmp(target, nop, KFUNC_MD_INSN_SIZE)) {
+			ret = -EBUSY;
+			goto out;
+		}
+		prog = insn;
+	} else {
+		if (!memcmp(target, nop, KFUNC_MD_INSN_SIZE))
+			goto out;
+		prog = nop;
+	}
+
+	ret = kfunc_md_arch_poke(target, prog);
+out:
+	mutex_unlock(&text_mutex);
+	return ret;
+}
+
+static bool __kfunc_md_put(struct kfunc_md *md)
+{
+	u8 nop_insn[KFUNC_MD_INSN_SIZE];
+
+	if (WARN_ON_ONCE(md->users <= 0))
+		return false;
+
+	md->users--;
+	if (md->users > 0)
+		return false;
+
+	if (!kfunc_md_arch_exist(md->func))
+		return false;
+
+	kfunc_md_arch_nops(nop_insn);
+	/* release the metadata by recovering the function padding to NOPS */
+	kfunc_md_text_poke(md->func, NULL, nop_insn);
+	/* TODO: we need a way to shrink the array "kfunc_mds" */
+	kfunc_md_used--;
+
+	return true;
+}
+
+/* Decrease the reference of the md, release it if "md->users <= 0" */
+void kfunc_md_put(struct kfunc_md *md)
+{
+	mutex_lock(&kfunc_md_mutex);
+	__kfunc_md_put(md);
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_put);
+
+/* Get a exist metadata by the function address, and NULL will be returned
+ * if not exist.
+ *
+ * NOTE: rcu lock should be held during reading the metadata, and
+ * kfunc_md_lock should be held if writing happens.
+ */
+struct kfunc_md *kfunc_md_find(void *ip)
+{
+	struct kfunc_md *md;
+	u32 index;
+
+	if (kfunc_md_arch_exist(ip)) {
+		index = kfunc_md_get_index(ip);
+		if (WARN_ON_ONCE(index >= kfunc_md_count))
+			return NULL;
+
+		md = rcu_dereference(kfunc_mds) + index;
+		return md;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(kfunc_md_find);
+
+void kfunc_md_put_by_ip(void *ip)
+{
+	struct kfunc_md *md;
+
+	mutex_lock(&kfunc_md_mutex);
+	md = kfunc_md_find(ip);
+	if (md)
+		__kfunc_md_put(md);
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_put_by_ip);
+
+/* Get a exist metadata by the function address, and create one if not
+ * exist. Reference of the metadata will increase 1.
+ *
+ * NOTE: always call this function with kfunc_md_lock held, and all
+ * updating to metadata should also hold the kfunc_md_lock.
+ */
+struct kfunc_md *kfunc_md_get(void *ip)
+{
+	u8 nop_insn[KFUNC_MD_INSN_SIZE], insn[KFUNC_MD_INSN_SIZE];
+	struct kfunc_md *md;
+	u32 index;
+
+	md = kfunc_md_find(ip);
+	if (md) {
+		md->users++;
+		return md;
+	}
+
+	md = kfunc_md_get_next(&index);
+	if (!md)
+		return NULL;
+
+	kfunc_md_arch_pretend(insn, index);
+	kfunc_md_arch_nops(nop_insn);
+
+	if (kfunc_md_text_poke(ip, insn, nop_insn)) {
+		kfunc_md_used--;
+		md->users = 0;
+		return NULL;
+	}
+	md->func = ip;
+
+	return md;
+}
+EXPORT_SYMBOL_GPL(kfunc_md_get);
-- 
2.39.5



From menglong8.dong at gmail.com  Sun Mar  2 22:53:44 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 14:53:44 +0800
Subject: [PATCH bpf-next v3 3/4] x86: implement per-function metadata storage for x86
In-Reply-To: <20250303065345.229298-1-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
Message-ID: <20250303065345.229298-4-dongml2@chinatelecom.cn>

With CONFIG_CALL_PADDING enabled, there will be 16-bytes padding space
before all the kernel functions. And some kernel features can use it,
such as MITIGATION_CALL_DEPTH_TRACKING, CFI_CLANG, FINEIBT, etc.

In my research, MITIGATION_CALL_DEPTH_TRACKING will consume the tail
9-bytes in the function padding, CFI_CLANG will consume the head 5-bytes,
and FINEIBT will consume all the 16 bytes if it is enabled. So there will
be no space for us if MITIGATION_CALL_DEPTH_TRACKING and CFI_CLANG are
both enabled, or FINEIBT is enabled.

In x86, we need 5-bytes to prepend a "mov %eax xxx" insn, which can hold
a 4-bytes index. So we have following logic:

1. use the head 5-bytes if CFI_CLANG is not enabled
2. use the tail 5-bytes if MITIGATION_CALL_DEPTH_TRACKING and FINEIBT are
   not enabled
3. compile the kernel with FUNCTION_ALIGNMENT_32B otherwise

In the third case, we make the kernel function 32 bytes aligned, and there
will be 32 bytes padding before the functions. According to my testing,
the text size didn't increase on this case, which is weird.

With 16-bytes padding:

-rwxr-xr-x 1 401190688  x86-dev/vmlinux*
-rw-r--r-- 1    251068  x86-dev/vmlinux.a
-rw-r--r-- 1 851892992  x86-dev/vmlinux.o
-rw-r--r-- 1  12395008  x86-dev/arch/x86/boot/bzImage

With 32-bytes padding:

-rwxr-xr-x 1 401318128 x86-dev/vmlinux*
-rw-r--r-- 1    251154 x86-dev/vmlinux.a
-rw-r--r-- 1 853636704 x86-dev/vmlinux.o
-rw-r--r-- 1  12509696 x86-dev/arch/x86/boot/bzImage

The way I tested should be right, and this is a good news for us. On the
third case, the layout of the padding space will be like this if fineibt
is enabled:

__cfi_func:
	mov	--	5	-- cfi, not used anymore
	nop
	nop
	nop
	mov	--	5	-- function metadata
	nop
	nop
	nop
	fineibt	--	16	-- fineibt
func:
	nopw	--	4
	......

I tested the fineibt with "cfi=fineibt" cmdline, and it works well
together with FUNCTION_METADATA enabled. And I also tested the
performance of this function by setting metadata for all the kernel
function, and it consumes 0.7s for 70k+ functions, not bad :/

I can't find a machine that support IBT, so I didn't test the IBT. I'd
appreciate it if someone can do this testing for me :/

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
v3:
- select FUNCTION_ALIGNMENT_32B on case3, instead of extra 5-bytes
---
 arch/x86/Kconfig              | 18 ++++++++++++
 arch/x86/include/asm/ftrace.h | 54 +++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index be2c311f5118..fe5a98401135 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2509,6 +2509,24 @@ config PREFIX_SYMBOLS
 	def_bool y
 	depends on CALL_PADDING && !CFI_CLANG
 
+config FUNCTION_METADATA
+	bool "Per-function metadata storage support"
+	default y
+	depends on CC_HAS_ENTRY_PADDING && OBJTOOL
+	select CALL_PADDING
+	select FUNCTION_ALIGNMENT_32B if ((CFI_CLANG && CALL_THUNKS) || FINEIBT)
+	help
+	  Support per-function metadata storage for kernel functions, and
+	  get the metadata of the function by its address with almost no
+	  overhead.
+
+	  The index of the metadata will be stored in the function padding
+	  and consumes 5-bytes. FUNCTION_ALIGNMENT_32B will be selected if
+	  "(CFI_CLANG && CALL_THUNKS) || FINEIBT" to make sure there is
+	  enough available padding space for this function. However, it
+	  seems that the text size almost don't change, compare with
+	  FUNCTION_ALIGNMENT_16B.
+
 menuconfig CPU_MITIGATIONS
 	bool "Mitigations for CPU vulnerabilities"
 	default y
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index f9cb4d07df58..d5cbb8e18fd7 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -4,6 +4,28 @@
 
 #include <asm/ptrace.h>
 
+#ifdef CONFIG_FUNCTION_METADATA
+#if (defined(CONFIG_CFI_CLANG) && defined(CONFIG_CALL_THUNKS)) || (defined(CONFIG_FINEIBT))
+  /* the CONFIG_FUNCTION_PADDING_BYTES is 32 in this case, use the
+   * range: [align + 8, align + 13].
+   */
+  #define KFUNC_MD_INSN_OFFSET		(CONFIG_FUNCTION_PADDING_BYTES - 8)
+  #define KFUNC_MD_DATA_OFFSET		(CONFIG_FUNCTION_PADDING_BYTES - 9)
+#else
+  #ifdef CONFIG_CFI_CLANG
+    /* use the space that CALL_THUNKS suppose to use */
+    #define KFUNC_MD_INSN_OFFSET	(5)
+    #define KFUNC_MD_DATA_OFFSET	(4)
+  #else
+    /* use the space that CFI_CLANG suppose to use */
+    #define KFUNC_MD_INSN_OFFSET	(CONFIG_FUNCTION_PADDING_BYTES)
+    #define KFUNC_MD_DATA_OFFSET	(CONFIG_FUNCTION_PADDING_BYTES - 1)
+  #endif
+#endif
+
+#define KFUNC_MD_INSN_SIZE		(5)
+#endif
+
 #ifdef CONFIG_FUNCTION_TRACER
 #ifndef CC_USING_FENTRY
 # error Compiler does not support fentry?
@@ -168,4 +190,36 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
 #endif /* !COMPILE_OFFSETS */
 #endif /* !__ASSEMBLY__ */
 
+#if !defined(__ASSEMBLY__) && defined(CONFIG_FUNCTION_METADATA)
+#include <asm/text-patching.h>
+
+static inline bool kfunc_md_arch_exist(void *ip)
+{
+	return *(u8 *)(ip - KFUNC_MD_INSN_OFFSET) == 0xB8;
+}
+
+static inline void kfunc_md_arch_pretend(u8 *insn, u32 index)
+{
+	*insn = 0xB8;
+	*(u32 *)(insn + 1) = index;
+}
+
+static inline void kfunc_md_arch_nops(u8 *insn)
+{
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+}
+
+static inline int kfunc_md_arch_poke(void *ip, u8 *insn)
+{
+	text_poke(ip, insn, KFUNC_MD_INSN_SIZE);
+	text_poke_sync();
+	return 0;
+}
+
+#endif
+
 #endif /* _ASM_X86_FTRACE_H */
-- 
2.39.5



From menglong8.dong at gmail.com  Sun Mar  2 22:53:45 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 14:53:45 +0800
Subject: [PATCH bpf-next v3 4/4] arm64: implement per-function metadata storage for arm64
In-Reply-To: <20250303065345.229298-1-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
Message-ID: <20250303065345.229298-5-dongml2@chinatelecom.cn>

The per-function metadata storage is already used by ftrace if
CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS is enabled, and it store the pointer
of the callback directly to the function padding, which consume 8-bytes,
in the commit
baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS").
So we can directly store the index to the function padding too, without
a prepending. With CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS enabled, the
function is 8-bytes aligned, and we will compile the kernel with extra
8-bytes (2 NOPS) padding space. Otherwise, the function is 4-bytes
aligned, and only extra 4-bytes (1 NOPS) is needed.

However, we have the same problem with Mark in the commit above: we can't
use the function padding together with CFI_CLANG, which can make the clang
compiles a wrong offset to the pre-function type hash. He said that he was
working with others on this problem 2 years ago. Hi Mark, is there any
progress on this problem?

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
 arch/arm64/Kconfig              | 15 +++++++++++++++
 arch/arm64/Makefile             | 23 ++++++++++++++++++++--
 arch/arm64/include/asm/ftrace.h | 34 +++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c      | 13 +++++++++++--
 4 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..7ed80f5eb267 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1536,6 +1536,21 @@ config NODES_SHIFT
 	  Specify the maximum number of NUMA Nodes available on the target
 	  system.  Increases memory reserved to accommodate various tables.
 
+config FUNCTION_METADATA
+	bool "Per-function metadata storage support"
+	default y
+	select HAVE_DYNAMIC_FTRACE_NO_PATCHABLE if !FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
+	depends on !CFI_CLANG
+	help
+	  Support per-function metadata storage for kernel functions, and
+	  get the metadata of the function by its address with almost no
+	  overhead.
+
+	  The index of the metadata will be stored in the function padding,
+	  which will consume 4-bytes. If FUNCTION_ALIGNMENT_8B is enabled,
+	  extra 8-bytes function padding will be reserved during compiling.
+	  Otherwise, only extra 4-bytes function padding is needed.
+
 source "kernel/Kconfig.hz"
 
 config ARCH_SPARSEMEM_ENABLE
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2b25d671365f..2df2b0f4dd90 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -144,12 +144,31 @@ endif
 
 CHECKFLAGS	+= -D__aarch64__
 
+ifeq ($(CONFIG_FUNCTION_METADATA),y)
+  ifeq ($(CONFIG_FUNCTION_ALIGNMENT_8B),y)
+  __padding_nops := 2
+  else
+  __padding_nops := 1
+  endif
+else
+  __padding_nops := 0
+endif
+
 ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS),y)
+  __padding_nops  := $(shell echo $(__padding_nops) + 2 | bc)
   KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
-  CC_FLAGS_FTRACE := -fpatchable-function-entry=4,2
+  CC_FLAGS_FTRACE := -fpatchable-function-entry=$(shell echo $(__padding_nops) + 2 | bc),$(__padding_nops)
 else ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y)
+  CC_FLAGS_FTRACE := -fpatchable-function-entry=$(shell echo $(__padding_nops) + 2 | bc),$(__padding_nops)
   KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
-  CC_FLAGS_FTRACE := -fpatchable-function-entry=2
+else ifeq ($(CONFIG_FUNCTION_METADATA),y)
+  CC_FLAGS_FTRACE += -fpatchable-function-entry=$(__padding_nops),$(__padding_nops)
+  ifneq ($(CONFIG_FUNCTION_TRACER),y)
+    KBUILD_CFLAGS += $(CC_FLAGS_FTRACE)
+    # some file need to remove this cflag when CONFIG_FUNCTION_TRACER
+    # is not enabled, so we need to export it here
+    export CC_FLAGS_FTRACE
+  endif
 endif
 
 ifeq ($(CONFIG_KASAN_SW_TAGS), y)
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index bfe3ce9df197..aa3eaa91bf82 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -24,6 +24,16 @@
 #define FTRACE_PLT_IDX		0
 #define NR_FTRACE_PLTS		1
 
+#ifdef CONFIG_FUNCTION_METADATA
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+#define KFUNC_MD_DATA_OFFSET	(AARCH64_INSN_SIZE * 3)
+#else
+#define KFUNC_MD_DATA_OFFSET	AARCH64_INSN_SIZE
+#endif
+#define KFUNC_MD_INSN_SIZE	AARCH64_INSN_SIZE
+#define KFUNC_MD_INSN_OFFSET	KFUNC_MD_DATA_OFFSET
+#endif
+
 /*
  * Currently, gcc tends to save the link register after the local variables
  * on the stack. This causes the max stack tracer to report the function
@@ -216,6 +226,30 @@ static inline bool arch_syscall_match_sym_name(const char *sym,
 	 */
 	return !strcmp(sym + 8, name);
 }
+
+#ifdef CONFIG_FUNCTION_METADATA
+#include <asm/text-patching.h>
+
+static inline bool kfunc_md_arch_exist(void *ip)
+{
+	return !aarch64_insn_is_nop(*(u32 *)(ip - KFUNC_MD_INSN_OFFSET));
+}
+
+static inline void kfunc_md_arch_pretend(u8 *insn, u32 index)
+{
+	*(u32 *)insn = index;
+}
+
+static inline void kfunc_md_arch_nops(u8 *insn)
+{
+	*(u32 *)insn = aarch64_insn_gen_nop();
+}
+
+static inline int kfunc_md_arch_poke(void *ip, u8 *insn)
+{
+	return aarch64_insn_patch_text_nosync(ip, *(u32 *)insn);
+}
+#endif
 #endif /* ifndef __ASSEMBLY__ */
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index d7c0d023dfe5..4191ff0037f5 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -88,8 +88,10 @@ unsigned long ftrace_call_adjust(unsigned long addr)
 	 * to `BL <caller>`, which is at `addr + 4` bytes in either case.
 	 *
 	 */
-	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
-		return addr + AARCH64_INSN_SIZE;
+	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS)) {
+		addr += AARCH64_INSN_SIZE;
+		goto out;
+	}
 
 	/*
 	 * When using patchable-function-entry with pre-function NOPs, addr is
@@ -139,6 +141,13 @@ unsigned long ftrace_call_adjust(unsigned long addr)
 
 	/* Skip the first NOP after function entry */
 	addr += AARCH64_INSN_SIZE;
+out:
+	if (IS_ENABLED(CONFIG_FUNCTION_METADATA)) {
+		if (IS_ENABLED(CONFIG_FUNCTION_ALIGNMENT_8B))
+			addr += 2 * AARCH64_INSN_SIZE;
+		else
+			addr += AARCH64_INSN_SIZE;
+	}
 
 	return addr;
 }
-- 
2.39.5



From menglong8.dong at gmail.com  Sun Mar  2 22:53:41 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 14:53:41 +0800
Subject: [PATCH bpf-next v3 0/4] per-function storage support
Message-ID: <20250303065345.229298-1-dongml2@chinatelecom.cn>

For now, there isn't a way to set and get per-function metadata with
a low overhead, which is not convenient for some situations. Take
BPF trampoline for example, we need to create a trampoline for each
kernel function, as we have to store some information of the function
to the trampoline, such as BPF progs, function arg count, etc. The
performance overhead and memory consumption can be higher to create
these trampolines. With the supporting of per-function metadata storage,
we can store these information to the metadata, and create a global BPF
trampoline for all the kernel functions. In the global trampoline, we
get the information that we need from the function metadata through the
ip (function address) with almost no overhead.

Another beneficiary can be ftrace. For now, all the kernel functions that
are enabled by dynamic ftrace will be added to a filter hash if there are
more than one callbacks. And hash lookup will happen when the traced
functions are called, which has an impact on the performance, see
__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
metadata supporting, we can store the information that if the callback is
enabled on the kernel function to the metadata.

In the 1st patch, we factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET to
make fineibt works on the kernel function is 32-bytes aligned.

In the 2nd patch, we implement the per-function metadata storage by
storing the index of the metadata to the function padding space.

In the 3rd and 4th patch, we implement the per-function metadata storage
for x86 and arm64. And in the feature, we can support more arch.

Changes since V2:
- split the patch into a series.
- considering the effect to cfi and fineibt and introduce the 1st patch.

Changes since V1:
- add supporting for arm64
- split out arch relevant code
- refactor the commit log

Menglong Dong (4):
  x86/ibt: factor out cfi and fineibt offset
  add per-function metadata storage support
  x86: implement per-function metadata storage for x86
  arm64: implement per-function metadata storage for arm64

 arch/arm64/Kconfig              |  15 ++
 arch/arm64/Makefile             |  23 ++-
 arch/arm64/include/asm/ftrace.h |  34 +++++
 arch/arm64/kernel/ftrace.c      |  13 +-
 arch/x86/Kconfig                |  16 +++
 arch/x86/include/asm/cfi.h      |  12 +-
 arch/x86/include/asm/ftrace.h   |  54 ++++++++
 arch/x86/kernel/alternative.c   |  27 +++-
 arch/x86/net/bpf_jit_comp.c     |  22 +--
 include/linux/kfunc_md.h        |  25 ++++
 kernel/Makefile                 |   1 +
 kernel/trace/Makefile           |   1 +
 kernel/trace/kfunc_md.c         | 239 ++++++++++++++++++++++++++++++++
 13 files changed, 456 insertions(+), 26 deletions(-)
 create mode 100644 include/linux/kfunc_md.h
 create mode 100644 kernel/trace/kfunc_md.c

-- 
2.39.5



From menglong8.dong at gmail.com  Sun Mar  2 22:53:42 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 14:53:42 +0800
Subject: [PATCH bpf-next v3 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250303065345.229298-1-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
Message-ID: <20250303065345.229298-2-dongml2@chinatelecom.cn>

For now, the layout of cfi and fineibt is hard coded, and the padding is
fixed on 16 bytes.

Factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET. CFI_INSN_OFFSET is
the offset of cfi, which is the same as FUNCTION_ALIGNMENT when
CALL_PADDING is enabled. And FINEIBT_INSN_OFFSET is the offset where we
put the fineibt preamble on, which is 16 for now.

When the FUNCTION_ALIGNMENT is bigger than 16, we place the fineibt
preamble on the last 16 bytes of the padding for better performance, which
means the fineibt preamble don't use the space that cfi uses.

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
 arch/x86/include/asm/cfi.h    | 12 ++++++++----
 arch/x86/kernel/alternative.c | 27 ++++++++++++++++++++-------
 arch/x86/net/bpf_jit_comp.c   | 22 +++++++++++-----------
 3 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h
index 31d19c815f99..ab51fa0ef6af 100644
--- a/arch/x86/include/asm/cfi.h
+++ b/arch/x86/include/asm/cfi.h
@@ -109,15 +109,19 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
 extern u32 cfi_bpf_hash;
 extern u32 cfi_bpf_subprog_hash;
 
+#ifdef CONFIG_CALL_PADDING
+#define FINEIBT_INSN_OFFSET	16
+#define CFI_INSN_OFFSET		CONFIG_FUNCTION_ALIGNMENT
+#else
+#define CFI_INSN_OFFSET		5
+#endif
+
 static inline int cfi_get_offset(void)
 {
 	switch (cfi_mode) {
 	case CFI_FINEIBT:
-		return 16;
 	case CFI_KCFI:
-		if (IS_ENABLED(CONFIG_CALL_PADDING))
-			return 16;
-		return 5;
+		return CFI_INSN_OFFSET;
 	default:
 		return 0;
 	}
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index c71b575bf229..ad050d09cb2b 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -908,7 +908,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end, struct mod
 
 		poison_endbr(addr, wr_addr, true);
 		if (IS_ENABLED(CONFIG_FINEIBT))
-			poison_cfi(addr - 16, wr_addr - 16);
+			poison_cfi(addr, wr_addr);
 	}
 }
 
@@ -974,12 +974,15 @@ u32 cfi_get_func_hash(void *func)
 {
 	u32 hash;
 
-	func -= cfi_get_offset();
 	switch (cfi_mode) {
+#ifdef CONFIG_FINEIBT
 	case CFI_FINEIBT:
+		func -= FINEIBT_INSN_OFFSET;
 		func += 7;
 		break;
+#endif
 	case CFI_KCFI:
+		func -= CFI_INSN_OFFSET;
 		func += 1;
 		break;
 	default:
@@ -1068,7 +1071,7 @@ early_param("cfi", cfi_parse_cmdline);
  *
  * caller:					caller:
  *	movl	$(-0x12345678),%r10d	 // 6	     movl   $0x12345678,%r10d	// 6
- *	addl	$-15(%r11),%r10d	 // 4	     sub    $16,%r11		// 4
+ *	addl	$-15(%r11),%r10d	 // 4	     sub    $FINEIBT_INSN_OFFSET,%r11 // 4
  *	je	1f			 // 2	     nop4			// 4
  *	ud2				 // 2
  * 1:	call	__x86_indirect_thunk_r11 // 5	     call   *%r11; nop2;	// 5
@@ -1092,10 +1095,14 @@ extern u8 fineibt_preamble_end[];
 #define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start)
 #define fineibt_preamble_hash 7
 
+#define ___OFFSET_STR(x)	#x
+#define __OFFSET_STR(x)		___OFFSET_STR(x)
+#define OFFSET_STR		__OFFSET_STR(FINEIBT_INSN_OFFSET)
+
 asm(	".pushsection .rodata			\n"
 	"fineibt_caller_start:			\n"
 	"	movl	$0x12345678, %r10d	\n"
-	"	sub	$16, %r11		\n"
+	"	sub	$"OFFSET_STR", %r11	\n"
 	ASM_NOP4
 	"fineibt_caller_end:			\n"
 	".popsection				\n"
@@ -1225,6 +1232,7 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end, struct module *mod)
 			 addr, addr, 5, addr))
 			return -EINVAL;
 
+		wr_addr += (CFI_INSN_OFFSET - FINEIBT_INSN_OFFSET);
 		text_poke_early(wr_addr, fineibt_preamble_start, fineibt_preamble_size);
 		WARN_ON(*(u32 *)(wr_addr + fineibt_preamble_hash) != 0x12345678);
 		text_poke_early(wr_addr + fineibt_preamble_hash, &hash, 4);
@@ -1241,7 +1249,8 @@ static void cfi_rewrite_endbr(s32 *start, s32 *end, struct module *mod)
 		void *addr = (void *)s + *s;
 		void *wr_addr = module_writable_address(mod, addr);
 
-		poison_endbr(addr + 16, wr_addr + 16, false);
+		poison_endbr(addr + CFI_INSN_OFFSET, wr_addr + CFI_INSN_OFFSET,
+			     false);
 	}
 }
 
@@ -1347,12 +1356,12 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
 		return;
 
 	case CFI_FINEIBT:
-		/* place the FineIBT preamble at func()-16 */
+		/* place the FineIBT preamble at func()-FINEIBT_INSN_OFFSET */
 		ret = cfi_rewrite_preamble(start_cfi, end_cfi, mod);
 		if (ret)
 			goto err;
 
-		/* rewrite the callers to target func()-16 */
+		/* rewrite the callers to target func()-FINEIBT_INSN_OFFSET */
 		ret = cfi_rewrite_callers(start_retpoline, end_retpoline, mod);
 		if (ret)
 			goto err;
@@ -1381,6 +1390,8 @@ static void poison_cfi(void *addr, void *wr_addr)
 {
 	switch (cfi_mode) {
 	case CFI_FINEIBT:
+		addr -= FINEIBT_INSN_OFFSET;
+		wr_addr -= FINEIBT_INSN_OFFSET;
 		/*
 		 * __cfi_\func:
 		 *	osp nopl (%rax)
@@ -1394,6 +1405,8 @@ static void poison_cfi(void *addr, void *wr_addr)
 		break;
 
 	case CFI_KCFI:
+		addr -= CFI_INSN_OFFSET;
+		wr_addr -= CFI_INSN_OFFSET;
 		/*
 		 * __cfi_\func:
 		 *	movl	$0, %eax
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a43fc5af973d..e0ddb0fd28e2 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -414,6 +414,12 @@ static void emit_nops(u8 **pprog, int len)
 static void emit_fineibt(u8 **pprog, u32 hash)
 {
 	u8 *prog = *pprog;
+#ifdef CONFIG_CALL_PADDING
+	int i;
+
+	for (i = 0; i < CFI_INSN_OFFSET - 16; i++)
+		EMIT1(0x90);
+#endif
 
 	EMIT_ENDBR();
 	EMIT3_off32(0x41, 0x81, 0xea, hash);		/* subl $hash, %r10d	*/
@@ -428,20 +434,14 @@ static void emit_fineibt(u8 **pprog, u32 hash)
 static void emit_kcfi(u8 **pprog, u32 hash)
 {
 	u8 *prog = *pprog;
+#ifdef CONFIG_CALL_PADDING
+	int i;
+#endif
 
 	EMIT1_off32(0xb8, hash);			/* movl $hash, %eax	*/
 #ifdef CONFIG_CALL_PADDING
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
+	for (i = 0; i < CFI_INSN_OFFSET - 5; i++)
+		EMIT1(0x90);
 #endif
 	EMIT_ENDBR();
 
-- 
2.39.5



From peng.fan at oss.nxp.com  Mon Mar  3 00:03:40 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Mon, 3 Mar 2025 16:03:40 +0800
Subject: [PATCH 0/7] rtc: Use devm_pm_set_wake_irq to simplify code
In-Reply-To: <20250205-rtc-cleanup-v1-0-66165678e089@nxp.com>
References: <20250205-rtc-cleanup-v1-0-66165678e089@nxp.com>
Message-ID: <20250303080340.GA29084@nxa18884-linux>

Hi Alexandre,

On Wed, Feb 05, 2025 at 08:58:18AM +0800, Peng Fan (OSS) wrote:
>This is a pick-up of patch 6-12 from patchset [1]
>
Do you have time to give a look on this patchset?

Thanks,
Peng

>Since devm_pm_set_wake_irq is in 6.14, so resend the rtc parts.
>
>R-b tags from Linus Walleij and Antonio Borneo are still kept.
>
>[1] https://lore.kernel.org/all/CAJZ5v0jb=0c5m=FeA-W-aG30H4706Ay_xCHTsiC1S-7MuGxqTQ at mail.gmail.com/#r


>
>Signed-off-by: Peng Fan <peng.fan at nxp.com>
>---
>Peng Fan (7):
>      rtc: stm32: Use resource managed API to simplify code
>      rtc: nxp-bbnsm: Use resource managed API to simplify code
>      rtc: ds1343: Use devm_pm_set_wake_irq
>      rtc: pm8xxx: Use devm_pm_set_wake_irq
>      rtc: ab8500: Use resource managed API to simplify code
>      rtc: mpfs: Use devm_pm_set_wake_irq
>      rtc: pl031: Use resource managed API to simplify code
>
> drivers/rtc/rtc-ab8500.c    | 11 ++---------
> drivers/rtc/rtc-ds1343.c    |  8 +-------
> drivers/rtc/rtc-mpfs.c      |  8 +-------
> drivers/rtc/rtc-nxp-bbnsm.c | 29 +++++++++--------------------
> drivers/rtc/rtc-pl031.c     |  6 ++----
> drivers/rtc/rtc-pm8xxx.c    | 12 +-----------
> drivers/rtc/rtc-stm32.c     | 10 ++--------
> 7 files changed, 18 insertions(+), 66 deletions(-)
>---
>base-commit: 40b8e93e17bff4a4e0cc129e04f9fdf5daa5397e
>change-id: 20250205-rtc-cleanup-d3d42ceb3d28
>
>Best regards,
>-- 
>Peng Fan <peng.fan at nxp.com>
>


From gshan at redhat.com  Sun Mar  2 23:08:04 2025
From: gshan at redhat.com (Gavin Shan)
Date: Mon, 3 Mar 2025 17:08:04 +1000
Subject: [PATCH v7 12/45] arm64: RME: Allocate/free RECs to match vCPUs
In-Reply-To: <20250213161426.102987-13-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-13-steven.price@arm.com>
Message-ID: <7639eca7-8fd8-491c-90bd-1be084fbd710@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> The RMM maintains a data structure known as the Realm Execution Context
> (or REC). It is similar to struct kvm_vcpu and tracks the state of the
> virtual CPUs. KVM must delegate memory and request the structures are
> created when vCPUs are created, and suitably tear down on destruction.
> 
> RECs must also be supplied with addition pages - auxiliary (or AUX)
> granules - for storing the larger registers state (e.g. for SVE). The
> number of AUX granules for a REC depends on the parameters with which
> the Realm was created - the RMM makes this information available via the
> RMI_REC_AUX_COUNT call performed after creating the Realm Descriptor (RD).
> 
> Note that only some of register state for the REC can be set by KVM, the
> rest is defined by the RMM (zeroed). The register state then cannot be
> changed by KVM after the REC is created (except when the guest
> explicitly requests this e.g. by performing a PSCI call). The RMM also
> requires that the VMM creates RECs in ascending order of the MPIDR.
> 
> See Realm Management Monitor specification (DEN0137) for more information:
> https://developer.arm.com/documentation/den0137/
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Avoid reporting the KVM_ARM_VCPU_REC feature if the guest isn't a
>     realm guest.
>   * Support host page size being larger than RMM's granule size when
>     allocating/freeing aux granules.
> Changes since v5:
>   * Separate the concept of vcpu_is_rec() and
>     kvm_arm_vcpu_rec_finalized() by using the KVM_ARM_VCPU_REC feature as
>     the indication that the VCPU is a REC.
> Changes since v2:
>   * Free rec->run earlier in kvm_destroy_realm() and adapt to previous patches.
> ---
>   arch/arm64/include/asm/kvm_emulate.h |   7 ++
>   arch/arm64/include/asm/kvm_host.h    |   3 +
>   arch/arm64/include/asm/kvm_rme.h     |  18 +++
>   arch/arm64/kvm/arm.c                 |  13 +-
>   arch/arm64/kvm/reset.c               |  11 ++
>   arch/arm64/kvm/rme.c                 | 179 +++++++++++++++++++++++++++
>   6 files changed, 229 insertions(+), 2 deletions(-)
> 

With the following one comment addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

[...]

>   
>   /*
> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_rme.h
> index 698bb48a8ae1..5db377943db4 100644
> --- a/arch/arm64/include/asm/kvm_rme.h
> +++ b/arch/arm64/include/asm/kvm_rme.h
> @@ -6,6 +6,7 @@
>   #ifndef __ASM_KVM_RME_H
>   #define __ASM_KVM_RME_H
>   
> +#include <asm/rmi_smc.h>
>   #include <uapi/linux/kvm.h>
>   
>   /**
> @@ -65,6 +66,21 @@ struct realm {
>   	unsigned int ia_bits;
>   };
>   
> +/**
> + * struct realm_rec - Additional per VCPU data for a Realm
> + *
> + * @mpidr: MPIDR (Multiprocessor Affinity Register) value to identify this VCPU
> + * @rec_page: Kernel VA of the RMM's private page for this REC
> + * @aux_pages: Additional pages private to the RMM for this REC
> + * @run: Kernel VA of the RmiRecRun structure shared with the RMM
> + */
> +struct realm_rec {
> +	unsigned long mpidr;
> +	void *rec_page;
> +	struct page *aux_pages[REC_PARAMS_AUX_GRANULES];
> +	struct rec_run *run;
> +};
> +

REC_PARAMS_AUX_GRANULES represents the maximal number of the auxiliary granules.
Since the base page size is always larger than or equal to granule size (4KB).
The capacity of array @aux_pages[] needs to be REC_PARAMS_AUX_GRANULES. Ideally,
the array's size can be computed dynamically and it's allocated in kvm_create_rec().

Alternatively, to keep the code simple, a comment is needed here to explain why
the array's size has been set to REC_PARAMS_AUX_GRANULES.

An relevant question: Do we plan to support differentiated sizes between page
and granule? I had the assumption this feature will be supported in the future
after the base model (equal page and granule size) gets merged first.

Thanks,
Gavin



From krzk at kernel.org  Sun Mar  2 23:24:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 3 Mar 2025 08:24:13 +0100
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
Message-ID: <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>

On 02/03/2025 10:16, Ivaylo Ivanov wrote:
> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>
>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>> ---
>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>  1 file changed, 76 insertions(+)
>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>> You have undocumented dependencies which prevent merging this file.
>>>> First, dependencies have to be clearly expressed.
>>> They are, in the cover letter.
>> Where? I read it twice. Dependencies is the most important thing and
>> should scream at beginning of the cover letter, so if you bury them
>> somewhere deep it also would not matter - just like they were missing.
>>
>>>> Second, you should
>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>> be merged for current release (just use clocks with long names, without IDs).
>>> Sure
>>
>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>> new file mode 100644
>>>>> index 000000000..7d879ec8b
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>> @@ -0,0 +1,76 @@
>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>> +%YAML 1.2
>>>>> +---
>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>> +
>>>>> +title: Exynos2200 USB controller PHY
>>>>> +
>>>>> +maintainers:
>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>> +
>>>>> +description:
>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>> It's not (I think). There's a few reasons I've decided to make this separate
>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>
>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>> at diagram - they call it phy controller.
> 
> Ughm. What? So in most exynos cases, there's a combination of multiple phys?


> 
>>
>>> for them, and all that is needed from it is to disable HWACG, assert/
>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>> Does it mean there is no USB DRD phy controller as before?
>>
>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
> 
> So...
> 
> DWC3 -> USBDRD (USBCON) -> PHYs?

No, drop last phy. You just wrote the same as me - two phys, because
usbdrd is the phy. In all existing designs there is no such controllable
object from the point of view of operating system.

> 
> ...with usbdrd controller connecting and controlling the USB2 and USB3
> phys, as well as dual role mode?

Yes.

> Well, where is the DRD part in the exynos5
> driver?

DRD? I believe it is part of DWC3, the same as in every other standard
implementation of Synopsys DWC3.

> 
> I guess it does perfectly fit the job of a usbdrd controller then (if it
> even deals with DRD). But then again,? this brings up two questions:
> 1. Should this driver even be named exynos2200-usbcon and not, for
> example, exynos2200-usbdrd?

Are you sure we talk about the same thing? USBDRD is IP block in the
Exynos and a device driver. Call your device as appropriate it is -
based on datasheet or downstream sources.

> 2. Are the exynos5-usbdrd phys really only USBDRD, or do they implement
> USB speed functionality? What is the UTMI/PIPE3 setup for then?

Dunno, I don't get what you mean by "exynos5-usbdrd phys really only
USBDRD". USBDRD is just the name of the device.

Best regards,
Krzysztof


From mazziesaccount at gmail.com  Sun Mar  2 23:33:05 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 3 Mar 2025 09:33:05 +0200
Subject: [PATCH v4 06/10] iio: adc: ti-ads7924 Drop unnecessary function
 parameters
In-Reply-To: <20250302034649.2d9ec2a4@jic23-huawei>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
 <38d39befcca110132fd4349c87fcb5d7ff51a2c8.1740421248.git.mazziesaccount@gmail.com>
 <20250302034649.2d9ec2a4@jic23-huawei>
Message-ID: <ce2c1a21-f418-4ed9-9cd3-fe2a68f08c31@gmail.com>

Hi dee Ho again Jonathan (and all),

On 02/03/2025 05:46, Jonathan Cameron wrote:
> On Mon, 24 Feb 2025 20:34:01 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> Device pointer is the only variable which is used by the
>> ads7924_get_channels_config() and which is declared outside this
>> function. Still, the function gets the iio_device and i2c_client as
>> parameters. The sole caller of this function (probe) already has the
>> device pointer which it can directly pass to the function.
>>
>> Simplify code by passing the device pointer directly as a parameter
>> instead of digging it from the iio_device's private data.
>>
>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> Looking again at this function it doesn't seem to be doing anything
> useful at all.  It checks the channel nodes are in range, but
> does nothing with that data. I'd just drop it entirely.
> 
> Ah. I see David suggested the same.
> 
> We can't really 'fix' what this was perhaps intended to do now
> as what it does has become ABI :(


I took another look at this.
The logic in the ads7924 driver (without this patch) is actually:

ads7924_get_channels_config(...)
{
	device_for_each_child_node(dev, node) {
		if (fwnode_property_read_u32(node, "reg", &pval)) ..
			continue;

		if (channel >= ADS7924_CHANNELS)
			continue;

		num_channels++;
	}

if (!num_channels)
	return -EINVAL;
}

...

ads7924_probe()
{
	ret = ads7924_get_channels_config(...);
	if (ret < 0)
		return dev_err_probe(...);
}

So, it still returns an error, if no channels with valid 'reg' property 
were found from the DT. It will also fail the probe().

Thus, this change is not quite as likely to cause things to break as it 
seemed. Still, for now anything with even single valid 'channel' has 
been Ok, even if all the rest were garbage. This new variant would fail 
if any of the 'channel' nodes contained no or bad 'reg'. Thus this can 
still break things.

Anyways, I'll follow your suggestion and drop this patch (unless you 
have second thoughts) - but I will keep the function so it still 
requires at least 1 valid channel node to be found.

Yours,
	-- Matti



From vigneshr at ti.com  Sun Mar  2 23:40:21 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 13:10:21 +0530
Subject: [PATCH 2/5] arm64: dts: ti: k3-am62a-phycore-som: Add boot phase
 tags
In-Reply-To: <20250228101817.865811-2-w.egorov@phytec.de>
References: <20250228101817.865811-1-w.egorov@phytec.de>
 <20250228101817.865811-2-w.egorov@phytec.de>
Message-ID: <3d01a502-47a6-467e-8743-392fde26e66e@ti.com>

Hi Wadim

[...]

On 28/02/25 15:48, Wadim Egorov wrote:
> @@ -168,6 +174,7 @@ &cpsw3g {
>  	status = "okay";
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&main_rgmii1_pins_default>;
> +	bootph-all;

One of the child nodes have bootph-all, so drop this from the parent.

BTW don't you need main_pktdma to have bootph-all to go along this for
ETH boot support?

>  };
>  
>  &cpsw_port1 {
> @@ -182,6 +189,7 @@ &cpsw3g_mdio {
>  	cpsw3g_phy1: ethernet-phy at 1 {
>  		compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
>  		reg = <1>;
> +		bootph-all;
>  		ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
>  		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
>  		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> @@ -196,6 +204,7 @@ &main_i2c0 {
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&main_i2c0_pins_default>;
>  	clock-frequency = <400000>;
> +	bootph-all;
>  	status = "okay";
>  
>  	pmic at 30 {
> @@ -318,6 +327,7 @@ serial_flash: flash at 0 {
>  		cdns,tchsh-ns = <60>;
>  		cdns,tslch-ns = <60>;
>  		cdns,read-delay = <0>;
> +		bootph-all;
>  	};
>  };
>  
> @@ -326,5 +336,6 @@ &sdhci0 {
>  	pinctrl-0 = <&main_mmc0_pins_default>;
>  	disable-wp;
>  	non-removable;
> +	bootph-all;
>  	status = "okay";
>  };
> -- 2.34.1

-- 
Regards
Vignesh
https://ti.com/opensource



From devnull+xianwei.zhao.amlogic.com at kernel.org  Sun Mar  2 23:53:20 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 03 Mar 2025 15:53:20 +0800
Subject: [PATCH] pinctrl: meson: fix pin input property for a4
Message-ID: <20250303-fix-a4-pinctl-v1-1-6579888b4272@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

The register of pin input attribute means the opposite.
value of reigster meaning is 1 for input and 0 for output.
So fix it.

Fixes: 6e9be3abb78c ("pinctrl: Add driver support for Amlogic SoCs")
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/pinctrl/meson/pinctrl-amlogic-a4.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
index a5218e8f1e03..35d5540b8eaa 100644
--- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
+++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
@@ -775,7 +775,7 @@ static int aml_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
 	if (ret)
 		return ret;
 
-	return BIT(bit) & val ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+	return BIT(bit) & val ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
 }
 
 static int aml_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
@@ -785,7 +785,7 @@ static int aml_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
 
 	aml_gpio_calc_reg_and_bit(bank, AML_REG_DIR, gpio, &reg, &bit);
 
-	return regmap_update_bits(bank->reg_gpio, reg, BIT(bit), 0);
+	return regmap_update_bits(bank->reg_gpio, reg, BIT(bit), BIT(bit));
 }
 
 static int aml_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
@@ -796,7 +796,7 @@ static int aml_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
 	int ret;
 
 	aml_gpio_calc_reg_and_bit(bank, AML_REG_DIR, gpio, &reg, &bit);
-	ret = regmap_update_bits(bank->reg_gpio, reg, BIT(bit), BIT(bit));
+	ret = regmap_update_bits(bank->reg_gpio, reg, BIT(bit), 0);
 	if (ret < 0)
 		return ret;
 

---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20250303-fix-a4-pinctl-4b215f3f9488

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From tabba at google.com  Sun Mar  2 23:57:00 2025
From: tabba at google.com (Fuad Tabba)
Date: Mon, 3 Mar 2025 07:57:00 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <Z8ISLxQRcsx2uuHw@google.com>
References: <20250226215520.1759218-1-tabba@google.com> <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com>
Message-ID: <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>

Hi Quentin,

On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
>
> On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> >  {
> > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > +     size_t pgd_sz, hyp_vm_sz;
> >       struct kvm_vcpu *host_vcpu;
> > -     pkvm_handle_t handle;
> >       void *pgd, *hyp_vm;
> >       unsigned long idx;
> >       int ret;
> > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> >       if (ret < 0)
> >               goto free_vm;
> >
> > -     handle = ret;
> > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
>
> What's the reason to make this a WRITE_ONCE? Does it mean we should
> update the readers to be READ_ONCE()?

I don't remember the original reason, to be honest. In this case, it
was to make it consistent with downstream code in Android. That said,
I plan on revising all of these soon and fixing this (and related
code) in light of Will's comment regarding potential specter gadgets:

https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/

Cheers,
/fuad

> > -     host_kvm->arch.pkvm.handle = handle;
> > -
> > -     /* Donate memory for the vcpus at hyp and initialize it. */
> > -     hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
> >       kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
> > -             void *hyp_vcpu;
> > -
> > -             /* Indexing of the vcpus to be sequential starting at 0. */
> > -             if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
> > -                     ret = -EINVAL;
> > -                     goto destroy_vm;
> > -             }
> > -
> > -             hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
> > -             if (!hyp_vcpu) {
> > -                     ret = -ENOMEM;
> > -                     goto destroy_vm;
> > -             }
> > -
> > -             ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, host_vcpu,
> > -                                     hyp_vcpu);
> > -             if (ret) {
> > -                     free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
> > +             ret = __pkvm_create_hyp_vcpu(host_vcpu);
> > +             if (ret)
> >                       goto destroy_vm;
> > -             }
> >       }
> >
> >       return 0;
> > --
> > 2.48.1.711.g2feabab25a-goog
> >


From dan.carpenter at linaro.org  Mon Mar  3 00:03:18 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 3 Mar 2025 11:03:18 +0300
Subject: [PATCH v3 3/7] firmware: arm_scmi: imx: Add i.MX95 LMM protocol
In-Reply-To: <20250303-imx-lmm-cpu-v3-3-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
 <20250303-imx-lmm-cpu-v3-3-7695f6f61cfc@nxp.com>
Message-ID: <2c8e8e93-4ce7-4260-94bd-eabba0b7732d@stanley.mountain>

On Mon, Mar 03, 2025 at 10:53:24AM +0800, Peng Fan (OSS) wrote:
> +static int scmi_imx_lmm_attributes(const struct scmi_protocol_handle *ph,
> +				   u32 lmid, struct scmi_imx_lmm_info *info)
> +{
> +	struct scmi_msg_imx_lmm_attributes_out *out;
> +	struct scmi_xfer *t;
> +	int ret;
> +
> +	ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_ATTRIBUTES, sizeof(u32), 0, &t);
> +	if (ret)
> +		return ret;
> +
> +	put_unaligned_le32(lmid, t->tx.buf);
> +	ret = ph->xops->do_xfer(ph, t);
> +	if (!ret) {
> +		out = t->rx.buf;
> +		info->lmid = le32_to_cpu(out->lmid);
> +		info->state = le32_to_cpu(out->state);
> +		info->errstatus = le32_to_cpu(out->errstatus);
> +		strscpy(info->name, out->name);
> +		dev_dbg(ph->dev, "i.MX LMM: Logical Machine(%d), name: %s\n",
> +			info->lmid, out->name);

Print info->name instead of out->name.

> +	} else {
> +		dev_err(ph->dev, "i.MX LMM: Failed to get info of Logical Machine(%u)\n", lmid);
> +	}
> +
> +	ph->xops->xfer_put(ph, t);
> +
> +	return ret;
> +}

regards,
dan carpenter



From vigneshr at ti.com  Mon Mar  3 00:14:57 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Mon, 3 Mar 2025 13:44:57 +0530
Subject: [PATCH v2 1/2] arm64: dts: ti: k3-am68-sk/k3-j721s2-mcu: Add
 bootph-all property to enable Ethernet boot
In-Reply-To: <20250302153502.181832-2-c-vankar@ti.com>
References: <20250302153502.181832-1-c-vankar@ti.com>
 <20250302153502.181832-2-c-vankar@ti.com>
Message-ID: <6b5839b3-84cb-42ee-8336-81ebf9b2e40d@ti.com>



On 02/03/25 21:05, Chintan Vankar wrote:
> Ethernet boot requires CPSW nodes to be present starting from R5 SPL
> stage. Add bootph-all property to required nodes to enable Ethernet boot
> on AM68-SK and J721S2-EVM.
> 
> Signed-off-by: Chintan Vankar <c-vankar at ti.com>
> ---
> 
> Link to v1:
> https://lore.kernel.org/r/20250106123122.3531845-2-c-vankar at ti.com/
> 
> Changes from v1 to v2:
> - No changes.
> 
>  arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 3 +++
>  arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 4 ++++
>  2 files changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
> index 11522b36e0ce..8e9101dd2152 100644
> --- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
> +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
> @@ -333,6 +333,7 @@ J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
>  			J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
>  			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
>  		>;
> +		bootph-all;
>  	};
>  
>  	mcu_mdio_pins_default: mcu-mdio-default-pins {
> @@ -340,6 +341,7 @@ mcu_mdio_pins_default: mcu-mdio-default-pins {
>  			J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
>  			J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
>  		>;
> +		bootph-all;
>  	};
>  
>  	mcu_mcan0_pins_default: mcu-mcan0-default-pins {
> @@ -615,6 +617,7 @@ &mcu_cpsw {
>  &davinci_mdio {
>  	phy0: ethernet-phy at 0 {
>  		reg = <0>;
> +		bootph-all;
>  		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
>  		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
>  		ti,min-output-impedance;
> diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
> index bc31266126d0..29cd4b1ffbbf 100644
> --- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
> @@ -154,12 +154,14 @@ mcu_conf: bus at 40f00000 {
>  		cpsw_mac_syscon: ethernet-mac-syscon at 200 {
>  			compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
>  			reg = <0x200 0x8>;
> +			bootph-all;
>  		};
>  
>  		phy_gmii_sel: phy at 4040 {
>  			compatible = "ti,am654-phy-gmii-sel";
>  			reg = <0x4040 0x4>;
>  			#phy-cells = <1>;
> +			bootph-all;
>  		};
>  
>  	};
> @@ -538,6 +540,7 @@ mcu_cpsw: ethernet at 46000000 {
>  		clocks = <&k3_clks 29 28>;
>  		clock-names = "fck";
>  		power-domains = <&k3_pds 29 TI_SCI_PD_EXCLUSIVE>;
> +		bootph-all;
>  

Since a child node has bootph-all, no need to put the same in the parent
hierarchy.

>  		dmas = <&mcu_udmap 0xf000>,
>  		       <&mcu_udmap 0xf001>,
> @@ -562,6 +565,7 @@ cpsw_port1: port at 1 {
>  				label = "port1";
>  				ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
>  				phys = <&phy_gmii_sel 1>;
> +				bootph-all;
>  			};
>  		};
>  


-- 
Regards
Vignesh
https://ti.com/opensource



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:26:49 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Mon, 3 Mar 2025 10:26:49 +0200
Subject: [PATCH v3 08/21] ARM: at91: Add PM support to sama7d65
In-Reply-To: <f4634d70f1e7002db059f2cc892fbbbfe1a95dac.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <f4634d70f1e7002db059f2cc892fbbbfe1a95dac.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <f03946a8-24bc-4a1a-8d06-d5652a4db34f@tuxon.dev>

Hi, Ryan,

On 27.02.2025 17:51, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add PM support to SAMA7D65 SoC.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> ---
>  arch/arm/mach-at91/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
> index 04bd91c72521..f3ff1220c0fb 100644
> --- a/arch/arm/mach-at91/Kconfig
> +++ b/arch/arm/mach-at91/Kconfig
> @@ -65,6 +65,7 @@ config SOC_SAMA7D65
>  	select HAVE_AT91_SAM9X60_PLL
>  	select HAVE_AT91_USB_CLK
>  	select HAVE_AT91_UTMI
> +	select PM_OPP

This is for OPP not PM support. For this series this should not be needed.


>  	select SOC_SAMA7
>  	help
>  	  Select this if you are using one of Microchip's SAMA7D65 family SoC.



From krzk at kernel.org  Mon Mar  3 00:29:23 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 3 Mar 2025 09:29:23 +0100
Subject: [PATCH v3 1/2] dt-bindings: usb: samsung,exynos-dwc3: add
 exynos7870 support
In-Reply-To: <20250301-exynos7870-usb-v3-1-f01697165d19@disroot.org>
References: <20250301-exynos7870-usb-v3-0-f01697165d19@disroot.org>
 <20250301-exynos7870-usb-v3-1-f01697165d19@disroot.org>
Message-ID: <929ed565-f842-49e6-9c7a-6d1df5266a62@kernel.org>

On 28/02/2025 20:40, Kaustabh Chakraborty wrote:
> Document compatible string for Exynos7870 DWC3-compatible USB 2.0
> driver. The devicetree node requires three clocks, named "bus_early",
> "ref", and "ctrl".
> 
> Unlike other variants, Exynos7870's USB controller requires a single
> 3.0V regulator. Assert that the other 1.0V regulator requirement is
> enforced on variants individually other than Exynos7870's.
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
> ---
>  .../bindings/usb/samsung,exynos-dwc3.yaml          | 28 +++++++++++++++++++++-
>  1 file changed, 27 insertions(+), 1 deletion(-)
> 

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From claudiu.beznea at tuxon.dev  Mon Mar  3 00:28:36 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Mon, 3 Mar 2025 10:28:36 +0200
Subject: [PATCH v3 14/21] ARM: dts: microchip: sama7d65: Add SRAM and DRAM
 components support
In-Reply-To: <ab4002faa1b672023ffc97bf91755720508c275e.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <ab4002faa1b672023ffc97bf91755720508c275e.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <3bdac1bc-b84f-43b0-86be-b9d9b18be25f@tuxon.dev>

Hi, Ryan,

On 27.02.2025 17:52, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add SRAM, secumod, UDDRC, and DDR3phy to enable support for low power modes.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> ---
>  arch/arm/boot/dts/microchip/sama7d65.dtsi | 35 +++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> index 92a5347e35b5..c10cc3558efd 100644
> --- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
> +++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> @@ -47,12 +47,37 @@ slow_xtal: clock-slowxtal {
>  		};
>  	};
>  
> +	ns_sram: sram at 100000 {
> +		compatible = "mmio-sram";
> +		reg = <0x100000 0x20000>;
> +		ranges;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +	};
> +
>  	soc {
>  		compatible = "simple-bus";
>  		ranges;
>  		#address-cells = <1>;
>  		#size-cells = <1>;
>  
> +		securam: sram at e0000800 {
> +			compatible = "microchip,sama7d65-securam", "atmel,sama5d2-securam", "mmio-sram";
> +			reg = <0xe0000800 0x4000>;
> +			ranges = <0 0xe0000800 0x4000>;
> +			clocks = <&pmc PMC_TYPE_PERIPHERAL 17>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			no-memory-wc;
> +		};
> +
> +		secumod: secumod at e0004000 {
> +			compatible = "microchip,sama7d65-secumod", "atmel,sama5d2-secumod", "syscon";

microchip,sama7d65-secumod is undocumented. I'll postpone this until a
documentation a patch will be posted.

> +			reg = <0xe0004000 0x4000>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
>  		pioa: pinctrl at e0014000 {
>  			compatible = "microchip,sama7d65-pinctrl", "microchip,sama7g5-pinctrl";
>  			reg = <0xe0014000 0x800>;
> @@ -190,6 +215,16 @@ i2c10: i2c at 600 {
>  			};
>  		};
>  
> +		uddrc: uddrc at e3800000 {
> +			compatible = "microchip,sama7d65-uddrc", "microchip,sama7g5-uddrc";
> +			reg = <0xe3800000 0x4000>;
> +		};
> +
> +		ddr3phy: ddr3phy at e3804000 {
> +			compatible = "microchip,sama7d65-ddr3phy", "microchip,sama7g5-ddr3phy";
> +			reg = <0xe3804000 0x1000>;
> +		};
> +
>  		gic: interrupt-controller at e8c11000 {
>  			compatible = "arm,cortex-a7-gic";
>  			reg = <0xe8c11000 0x1000>,



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:28:47 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Mon, 3 Mar 2025 10:28:47 +0200
Subject: [PATCH v3 17/21] ARM: dts: microchip: sama7d65: Add RTT and GPBR
 Support for sama7d65 SoC
In-Reply-To: <6a1c058edee3fe1459dcb3a93a0a789a9ffff5f3.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <6a1c058edee3fe1459dcb3a93a0a789a9ffff5f3.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <430f1dae-0123-4d4a-81c9-b3c1d9df285d@tuxon.dev>

Hi, Ryan,

On 27.02.2025 17:52, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add RTT support for SAMA7D65 SoC. The GPBR is added so the SoC is able
> to store the RTT time data.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> ---
>  arch/arm/boot/dts/microchip/sama7d65.dtsi | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> index b0a676623100..aadeea132289 100644
> --- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
> +++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> @@ -120,6 +120,13 @@ shdwc: poweroff at e001d200 {
>  			status = "disabled";
>  		};
>  
> +		rtt: rtc at e001d300 {
> +			compatible = "microchip,sama7d65-rtt", "atmel,at91sam9260-rtt";
> +			reg = <0xe001d300 0x30>;
> +			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&clk32k 0>;
> +		};
> +
>  		clk32k: clock-controller at e001d500 {
>  			compatible = "microchip,sama7d65-sckc", "microchip,sam9x60-sckc";
>  			reg = <0xe001d500 0x4>;
> @@ -132,6 +139,11 @@ chipid at e0020000 {
>  			reg = <0xe0020000 0x8>;
>  		};
>  
> +		gpbr: gpbr at e001d700 {
> +			compatible = "microchip,sama7d65-gpbr", "syscon";

This is not documented. I'll postpone this until a documentation patch will
be posted.

> +			reg = <0xe001d700 0x48>;
> +		};
> +
>  		dma2: dma-controller at e1200000 {
>  			compatible = "microchip,sama7d65-dma", "microchip,sama7g5-dma";
>  			reg = <0xe1200000 0x1000>;



From krzk at kernel.org  Mon Mar  3 00:29:44 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 3 Mar 2025 09:29:44 +0100
Subject: [PATCH v3 2/2] usb: dwc3: exynos: add support for exynos7870
In-Reply-To: <20250301-exynos7870-usb-v3-2-f01697165d19@disroot.org>
References: <20250301-exynos7870-usb-v3-0-f01697165d19@disroot.org>
 <20250301-exynos7870-usb-v3-2-f01697165d19@disroot.org>
Message-ID: <edbbd971-1bd8-42cb-89fe-c844d582a361@kernel.org>

On 28/02/2025 20:40, Kaustabh Chakraborty wrote:
> Exynos7870 devices have a DWC3 compatible USB 2.0 controller.
> Add support in the driver by:
>  - Adding its own compatible string, "samsung,exynos7870-dwusb3".
>  - Adding three USBDRD clocks named "bus_early", "ref", and "ctrl", to
>    be controlled by the driver.
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
> Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From linus.walleij at linaro.org  Mon Mar  3 00:41:41 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:41 +0100
Subject: [PATCH 1/6] ASoC: samsung: bells: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-1-56a2299dd928@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/bells.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 365b1aca4855c885e0b59a1101475d8edb86374f..b4c0857ae35134b58a125b0746af07a5fff040fa 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm5102.h"

-- 
2.48.1



From linus.walleij at linaro.org  Mon Mar  3 00:41:42 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:42 +0100
Subject: [PATCH 2/6] ASoC: samsung: littlemill: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-2-56a2299dd928@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/littlemill.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index c5260e101c2a136001c6273200fa35740e618829..9fa5e3ff9215164491839d6ffdf499a3eeadfbaa 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8994.h"

-- 
2.48.1



From linus.walleij at linaro.org  Mon Mar  3 00:41:43 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:43 +0100
Subject: [PATCH 3/6] ASoC: samsung: lowland: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-3-56a2299dd928@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/lowland.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
index 702cb4cc1ce9f07e55ddf9435b19c4691e0236e5..d4088b72d43c2295102d850197f8b9eac50d7120 100644
--- a/sound/soc/samsung/lowland.c
+++ b/sound/soc/samsung/lowland.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm5100.h"

-- 
2.48.1



From linus.walleij at linaro.org  Mon Mar  3 00:41:44 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:44 +0100
Subject: [PATCH 4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-4-56a2299dd928@linaro.org>

The Speyside ASoC uses a single GPIO from the WM8996
that we can provide from the local offset on that chip
rather than from the global GPIO numberspace as is being
done currently.

The offset 2 was done by calculating the base offset
for the CODEC (i.e. wm8996) GPIOs to 212, by reading
arch/arm/mach-s3c/gpio-samsung-s3c64xx.h and
arch/arm/mach-s3c/crag6410.h and adding up all the
offsets that were occasionally adding a +1 blank GPIO
between each GPIO provider.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/speyside.c | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 79476e8eb680984434a1198ff691ddd4b9fe07c1..947b85ff83f036a0814fd477f5f6f69253a2a2d8 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -7,13 +7,13 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8996.h"
 #include "../codecs/wm9081.h"
 
-#define WM8996_HPSEL_GPIO 214
 #define MCLK_AUDIO_RATE (512 * 48000)
 
 static int speyside_set_bias_level(struct snd_soc_card *card,
@@ -105,6 +105,7 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = {
 	},
 };
 
+static struct gpio_desc *speyside_hpsel_gpio;
 /* Default the headphone selection to active high */
 static int speyside_jack_polarity;
 
@@ -123,7 +124,7 @@ static void speyside_set_polarity(struct snd_soc_component *component,
 				  int polarity)
 {
 	speyside_jack_polarity = !polarity;
-	gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
+	gpiod_direction_output(speyside_hpsel_gpio, speyside_jack_polarity);
 
 	/* Re-run DAPM to make sure we're using the correct mic bias */
 	snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
@@ -145,16 +146,22 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
 	struct snd_soc_component *component = dai->component;
+	enum gpiod_flags flags;
 	int ret;
 
 	ret = snd_soc_dai_set_sysclk(dai, WM8996_SYSCLK_MCLK2, 32768, 0);
 	if (ret < 0)
 		return ret;
 
-	ret = gpio_request(WM8996_HPSEL_GPIO, "HP_SEL");
-	if (ret != 0)
-		pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
-	gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
+	if (speyside_jack_polarity)
+		flags = GPIOD_OUT_HIGH;
+	else
+		flags = GPIOD_OUT_LOW;
+	speyside_hpsel_gpio = devm_gpiod_get(rtd->card->dev,
+					     "hp-sel",
+					     flags);
+	if (IS_ERR(speyside_hpsel_gpio))
+		return PTR_ERR(speyside_hpsel_gpio);
 
 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset",
 					 SND_JACK_LINEOUT | SND_JACK_HEADSET |
@@ -325,6 +332,21 @@ static struct snd_soc_card speyside = {
 	.late_probe = speyside_late_probe,
 };
 
+static struct gpiod_lookup_table wm8996_gpiod_table = {
+	/* Hardcoded device name in board file mach-crag6410.c */
+	.dev_id = "speyside",
+	.table = {
+		/*
+		 * This line was hardcoded to 214 in the global GPIO
+		 * number space, S3C GPIO macros seems top set the
+		 * wm8996 codec GPIO start offset to 212, so this will
+		 * be GPIO 214 - 212 = 2 on the wm8996.
+		 */
+		GPIO_LOOKUP("wm8996", 2, "hp-sel", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static int speyside_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = &speyside;
@@ -332,6 +354,7 @@ static int speyside_probe(struct platform_device *pdev)
 
 	card->dev = &pdev->dev;
 
+	gpiod_add_lookup_table(&wm8996_gpiod_table);
 	ret = devm_snd_soc_register_card(&pdev->dev, card);
 	if (ret)
 		dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n");

-- 
2.48.1



From linus.walleij at linaro.org  Mon Mar  3 00:41:45 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:45 +0100
Subject: [PATCH 5/6] ASoC: samsung: tobermory: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-5-56a2299dd928@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/tobermory.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index 2bdd81bf821a5b9bdc56479bb2cd5d0089fab339..bc2608dbaddc4feeb9af77639699fed89540b44b 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8962.h"

-- 
2.48.1



From linus.walleij at linaro.org  Mon Mar  3 00:41:46 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:46 +0100
Subject: [PATCH 6/6] ASoC: samsung: tm2_wm5110: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <20250303-samsung-codecs-v1-6-56a2299dd928@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/tm2_wm5110.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
index 2417b91a328f083f991af8505c5586d3b27d9bbd..cc76963105d9fa37fe0bc45acf9a28720fdde158 100644
--- a/sound/soc/samsung/tm2_wm5110.c
+++ b/sound/soc/samsung/tm2_wm5110.c
@@ -6,7 +6,6 @@
 //          Sylwester Nawrocki <s.nawrocki at samsung.com>
 
 #include <linux/clk.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>

-- 
2.48.1



From andre.draszik at linaro.org  Mon Mar  3 00:45:47 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Mon, 03 Mar 2025 08:45:47 +0000
Subject: [PATCH 00/18] a few rtc driver cleanups
In-Reply-To: <20250301203658839d5482@mail.local>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
	 <20250301203658839d5482@mail.local>
Message-ID: <4d0042850eb4d9898559b56505291c4e849d44c5.camel@linaro.org>

Hi Alexandre,

On Sat, 2025-03-01 at 21:36 +0100, Alexandre Belloni wrote:
> On 28/02/2025 14:07:13+0000, Andr? Draszik wrote:
> > Hi,
> > 
> > While looking at RTC, I noticed that various drivers are keeping
> > pointers to data that they're not using themselves throughout their
> > lifetime.
> > 
> > So I took the liberty to drop these pointers and this series is the
> > result.
> > 
> > The last two patches also convert two drivers to using dev_err_probe(),
> > as I looked slightly closer into those two. They don't exactly fit the
> > general subject of removal of unneeded pointers, but I wanted to share
> > them anyway, since they're ready.
> > 
> > All of this was compile-tested only.
> > 
> > Cheers,
> > Andre'
> > 
> > Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> > ---
> > Andr? Draszik (18):
> > ????? rtc: max77686: drop needless struct max77686_rtc_info::rtc member
> > ????? rtc: s5m: drop needless struct s5m_rtc_info::i2c member
> > ????? rtc: aspeed: drop needless struct aspeed_rtc::rtc_dev member
> > ????? rtc: ds2404: drop needless struct ds2404::rtc member
> > ????? rtc: ep93xx: drop needless struct ep93xx_rtc::rtc member
> > ????? rtc: ftrtc010: drop needless struct ftrtc010_rtc::rtc_dev member
> > ????? rtc: m48t86: drop needless struct m48t86_rtc_info::rtc member
> > ????? rtc: meson: drop needless struct meson_rtc::rtc member
> > ????? rtc: meson-vrtc: drop needless struct meson_vrtc_data::rtc member
> > ????? rtc: pl030: drop needless struct pl030_rtc::rtc member
> > ????? rtc: rx8581: drop needless struct rx8581::rtc member
> > ????? rtc: s35390a: drop needless struct s35390a::rtc member
> > ????? rtc: sd2405al: drop needless struct sd2405al::rtc member
> > ????? rtc: sd3078: drop needless struct sd3078::rtc member
> 
> My main concern with this is that as soon as we introduce irq support,
> we are going to need the rtc pointer back in the struct. But I guess
> that most of them are old enough to say that nobody is interested in irq
> support.

Thanks for your thoughts Alexandre - I don't know the history of
these drivers and don't mind either way. I can drop those patches
that would require reintroducing if irq support is added in the
future. I think overall you're OK with keeping them, but please
let me know if I'm misunderstanding :-)

> 
> > ????? rtc: rx8581: drop needless struct rx8581
> > ????? rtc: sd3078: drop needless struct sd3078
> 
> I guess you could squash those two with the previous ones touching the
> respective drivers because you are the one removing the last remaining
> struct member.

Will do.

Cheers,
Andre'



From shameerali.kolothum.thodi at huawei.com  Mon Mar  3 00:49:02 2025
From: shameerali.kolothum.thodi at huawei.com (Shameerali Kolothum Thodi)
Date: Mon, 3 Mar 2025 08:49:02 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250228193221.GM5011@ziepe.ca>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
Message-ID: <b23aa37f8e864dea82a6143bece912d6@huawei.com>



> -----Original Message-----
> From: Jason Gunthorpe <jgg at ziepe.ca>
> Sent: Friday, February 28, 2025 7:32 PM
> To: Miko?aj Lenczewski <miko.lenczewski at arm.com>; Shameerali Kolothum
> Thodi <shameerali.kolothum.thodi at huawei.com>
> Cc: ryan.roberts at arm.com; suzuki.poulose at arm.com;
> yang at os.amperecomputing.com; catalin.marinas at arm.com;
> will at kernel.org; joro at 8bytes.org; jean-philippe at linaro.org;
> mark.rutland at arm.com; joey.gouly at arm.com; oliver.upton at linux.dev;
> james.morse at arm.com; broonie at kernel.org; maz at kernel.org;
> david at redhat.com; akpm at linux-foundation.org; nicolinc at nvidia.com;
> mshavit at google.com; jsnitsel at redhat.com; smostafa at google.com; linux-
> arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> iommu at lists.linux.dev
> Subject: Re: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
> 
> On Fri, Feb 28, 2025 at 06:24:04PM +0000, Miko?aj Lenczewski wrote:
> > For supporting BBM Level 2 for userspace mappings, we want to ensure
> > that the smmu also supports its own version of BBM Level 2. Luckily, the
> > smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
> > 0487K.a D8.16.2), so already guarantees that no aborts are raised when
> > BBM level 2 is claimed.
> >
> > Add the feature and testing for it under arm_smmu_sva_supported().
> >
> > Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> > ---
> >  arch/arm64/kernel/cpufeature.c                  | 7 +++----
> >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
> >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
> >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
> >  4 files changed, 13 insertions(+), 4 deletions(-)
> 
> This patch looks good, for what it does. However for bisection safety
> it should be earlier, before the patches that change the page table
> algorithms to be unsafe for the SMMU.
> 
> However, I've heard people talking about shipping chips that have CPUs
> with BBML2 but SMMUs without.
> 
> On such a system it seems like your series would break previously
> working SVA support because this patch will end up disabling it?
> 
> Though I see your MIDR_REV list is limited, so perhaps that worry
> doesn't effect any real chips made with those families? I am trying to
> check some NVIDIA products against this list..

We do have implementations that support CPUs with BBLM2 with TLB
conflict aborts and SMMUv3 with BBML2.  So don't think those platforms
be affected by this.  Will check with our hardware folks if there is
anything that will be affected by this.

Also we  have plans to try to use SMMUv3 BBML2 during VM live migration
to split block pages to 4K. I guess, in that case we can enable SMMU BBML2
independent of CPU side. 

Thanks,
Shameer

From lkp at intel.com  Mon Mar  3 00:55:03 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 3 Mar 2025 16:55:03 +0800
Subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin@google.com>
References: <2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin@google.com>
Message-ID: <202503031631.OeUhVRHz-lkp@intel.com>

Hi Peilin,

kernel test robot noticed the following build errors:

[auto build test ERROR on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Peilin-Ye/bpf-verifier-Factor-out-atomic_ptr_type_ok/20250303-134110
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin%40google.com
patch subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and store-release instructions
config: arc-randconfig-002-20250303 (https://download.01.org/0day-ci/archive/20250303/202503031631.OeUhVRHz-lkp at intel.com/config)
compiler: arc-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250303/202503031631.OeUhVRHz-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503031631.OeUhVRHz-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from <command-line>:
   kernel/bpf/core.c: In function '___bpf_prog_run':
>> include/linux/compiler_types.h:542:45: error: call to '__compiletime_assert_459' declared with attribute error: Need native word sized stores/loads for atomicity.
     542 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |                                             ^
   include/linux/compiler_types.h:523:25: note: in definition of macro '__compiletime_assert'
     523 |                         prefix ## suffix();                             \
         |                         ^~~~~~
   include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert'
     542 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |         ^~~~~~~~~~~~~~~~~~~
   include/linux/compiler_types.h:545:9: note: in expansion of macro 'compiletime_assert'
     545 |         compiletime_assert(__native_word(t),                            \
         |         ^~~~~~~~~~~~~~~~~~
   include/asm-generic/barrier.h:151:9: note: in expansion of macro 'compiletime_assert_atomic_type'
     151 |         compiletime_assert_atomic_type(*p);                             \
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/asm-generic/barrier.h:176:29: note: in expansion of macro '__smp_load_acquire'
     176 | #define smp_load_acquire(p) __smp_load_acquire(p)
         |                             ^~~~~~~~~~~~~~~~~~
   kernel/bpf/core.c:2222:45: note: in expansion of macro 'smp_load_acquire'
    2222 |                                 DST = (SIZE)smp_load_acquire(   \
         |                                             ^~~~~~~~~~~~~~~~
   kernel/bpf/core.c:2228:25: note: in expansion of macro 'LOAD_ACQUIRE'
    2228 |                         LOAD_ACQUIRE(DW, u64)
         |                         ^~~~~~~~~~~~
   include/linux/compiler_types.h:542:45: error: call to '__compiletime_assert_466' declared with attribute error: Need native word sized stores/loads for atomicity.
     542 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |                                             ^
   include/linux/compiler_types.h:523:25: note: in definition of macro '__compiletime_assert'
     523 |                         prefix ## suffix();                             \
         |                         ^~~~~~
   include/linux/compiler_types.h:542:9: note: in expansion of macro '_compiletime_assert'
     542 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |         ^~~~~~~~~~~~~~~~~~~
   include/linux/compiler_types.h:545:9: note: in expansion of macro 'compiletime_assert'
     545 |         compiletime_assert(__native_word(t),                            \
         |         ^~~~~~~~~~~~~~~~~~
   include/asm-generic/barrier.h:141:9: note: in expansion of macro 'compiletime_assert_atomic_type'
     141 |         compiletime_assert_atomic_type(*p);                             \
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/asm-generic/barrier.h:172:55: note: in expansion of macro '__smp_store_release'
     172 | #define smp_store_release(p, v) do { kcsan_release(); __smp_store_release(p, v); } while (0)
         |                                                       ^~~~~~~~~~~~~~~~~~~
   kernel/bpf/core.c:2238:33: note: in expansion of macro 'smp_store_release'
    2238 |                                 smp_store_release(      \
         |                                 ^~~~~~~~~~~~~~~~~
   kernel/bpf/core.c:2244:25: note: in expansion of macro 'STORE_RELEASE'
    2244 |                         STORE_RELEASE(DW, u64)
         |                         ^~~~~~~~~~~~~


vim +/__compiletime_assert_459 +542 include/linux/compiler_types.h

eb5c2d4b45e3d2 Will Deacon 2020-07-21  528  
eb5c2d4b45e3d2 Will Deacon 2020-07-21  529  #define _compiletime_assert(condition, msg, prefix, suffix) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21  530  	__compiletime_assert(condition, msg, prefix, suffix)
eb5c2d4b45e3d2 Will Deacon 2020-07-21  531  
eb5c2d4b45e3d2 Will Deacon 2020-07-21  532  /**
eb5c2d4b45e3d2 Will Deacon 2020-07-21  533   * compiletime_assert - break build and emit msg if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21  534   * @condition: a compile-time constant condition to check
eb5c2d4b45e3d2 Will Deacon 2020-07-21  535   * @msg:       a message to emit if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21  536   *
eb5c2d4b45e3d2 Will Deacon 2020-07-21  537   * In tradition of POSIX assert, this macro will break the build if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21  538   * supplied condition is *false*, emitting the supplied error message if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21  539   * compiler has support to do so.
eb5c2d4b45e3d2 Will Deacon 2020-07-21  540   */
eb5c2d4b45e3d2 Will Deacon 2020-07-21  541  #define compiletime_assert(condition, msg) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21 @542  	_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
eb5c2d4b45e3d2 Will Deacon 2020-07-21  543  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From david at redhat.com  Mon Mar  3 00:58:15 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 09:58:15 +0100
Subject: [PATCH v9 19/20] fs/dax: Properly refcount fs dax pages
In-Reply-To: <c7d886ad7468a20452ef6e0ddab6cfe220874e7c.1740713401.git-series.apopple@nvidia.com>
References: <cover.8068ad144a7eea4a813670301f4d2a86a8e68ec4.1740713401.git-series.apopple@nvidia.com>
 <c7d886ad7468a20452ef6e0ddab6cfe220874e7c.1740713401.git-series.apopple@nvidia.com>
Message-ID: <964e8991-44c0-4ff7-91cc-033ed7c09835@redhat.com>


> -static inline unsigned long dax_folio_share_put(struct folio *folio)
> +static inline unsigned long dax_folio_put(struct folio *folio)
>   {
> -	return --folio->page.share;
> +	unsigned long ref;
> +	int order, i;
> +
> +	if (!dax_folio_is_shared(folio))
> +		ref = 0;
> +	else
> +		ref = --folio->share;
> +

It would still be good to learn how this non-atomic update here is safe 
(@Dan?), but that's independent of this series.

Staring at it, I would have thought we have to us an atomic_t here.

Acked-by: David Hildenbrand <david at redhat.com>

-- 
Cheers,

David / dhildenb



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:37:33 2025
From: claudiu.beznea at tuxon.dev (claudiu beznea (tuxon))
Date: Mon, 3 Mar 2025 10:37:33 +0200
Subject: [PATCH v3 10/21] ARM: at91: pm: add DT compatible support for
 sama7d65
In-Reply-To: <06b64869f2de4b499835d153411ba30512409168.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <06b64869f2de4b499835d153411ba30512409168.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <81354810-14e6-4840-9e50-52bdd0e63b95@tuxon.dev>



On 2/27/25 17:51, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add support for SAMA7D65 new compatible strings in pm.c file for wakeup source
> IDs and PMC.
> This is the first bits of PM for this new SoC. PM depends on other patches.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> [nicolas.ferre at microchip.com: split patch and address only the pm.c changes]
> Signed-off-by: Nicolas Ferre <nicolas.ferre at microchip.com>
> ---
>   arch/arm/mach-at91/pm.c | 8 ++++++--
>   1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
> index 6c3e6aa22606..39644703244d 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -222,13 +222,16 @@ static const struct of_device_id sam9x60_ws_ids[] = {
>   	{ /* sentinel */ }
>   };
>   
> -static const struct of_device_id sama7g5_ws_ids[] = {
> +static const struct of_device_id sama7_ws_ids[] = {
> +	{ .compatible = "microchip,sama7d65-rtc",	.data = &ws_info[1] },
>   	{ .compatible = "microchip,sama7g5-rtc",	.data = &ws_info[1] },
>   	{ .compatible = "microchip,sama7g5-ohci",	.data = &ws_info[2] },
>   	{ .compatible = "usb-ohci",			.data = &ws_info[2] },
>   	{ .compatible = "atmel,at91sam9g45-ehci",	.data = &ws_info[2] },
>   	{ .compatible = "usb-ehci",			.data = &ws_info[2] },
> +	{ .compatible = "microchip,sama7d65-sdhci",	.data = &ws_info[3] },
>   	{ .compatible = "microchip,sama7g5-sdhci",	.data = &ws_info[3] },
> +	{ .compatible = "microchip,sama7d65-rtt",	.data = &ws_info[4] },
>   	{ .compatible = "microchip,sama7g5-rtt",	.data = &ws_info[4] },
>   	{ /* sentinel */ }
>   };
> @@ -1379,6 +1382,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = {
>   	{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
>   	{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
>   	{ .compatible = "microchip,sam9x7-pmc", .data = &pmc_infos[4] },
> +	{ .compatible = "microchip,sama7d65-pmc", .data = &pmc_infos[4] },

According to the chapter 42.18.3. PMC System Clock Status Register at [1] there 
is no AT91SAM926x_PMC_UDP for SAMA7D65 (which you are dropping in the next 
patch). This patch would have to reflect what the documentation say instead of 
fixing it in patch 12/21.

Thank you,
Claudiu

[1] 
https://ww1.microchip.com/downloads/aemDocuments/documents/MPU32/ProductDocuments/DataSheets/SAMA7D6-Series-Data-Sheet-DS60001851.pdf

>   	{ .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
>   	{ /* sentinel */ },
>   };
> @@ -1672,7 +1676,7 @@ void __init sama7_pm_init(void)
>   	at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
>   	at91_pm_init(NULL);
>   
> -	soc_pm.ws_ids = sama7g5_ws_ids;
> +	soc_pm.ws_ids = sama7_ws_ids;
>   	soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
>   
>   	soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:37:43 2025
From: claudiu.beznea at tuxon.dev (claudiu beznea (tuxon))
Date: Mon, 3 Mar 2025 10:37:43 +0200
Subject: [PATCH v3 11/21] ARM: at91: PM: Add Backup mode for SAMA7D65
In-Reply-To: <3a1f59af1ac9322b0203694b535d5d13120a31eb.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <3a1f59af1ac9322b0203694b535d5d13120a31eb.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <45713e88-57af-43c7-bf0b-4583383b10dc@tuxon.dev>



On 2/27/25 17:51, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add config check that enables Backup mode for SAMA7D65 SoC.
> 
> Add SHDWC_SR read to clear the status bits once finished exiting backup
> mode. This is only for SAMA7D65 SoCs. The SHDWC status register
> needs to be cleared after exiting backup mode to clear the wake up pin
> status.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> ---
>   arch/arm/mach-at91/pm.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
> index 39644703244d..d82a507bc8da 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -647,6 +647,11 @@ static void at91_pm_suspend(suspend_state_t state)
>   		at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
>   					     &at91_pm_suspend_in_sram,
>   					     at91_pm_suspend_in_sram_sz);
> +
> +		if (IS_ENABLED(CONFIG_SOC_SAMA7D65))
> +			/* SHDWC.SR */
> +			readl(soc_pm.data.shdwc + 0x08);
> +
>   	} else {
>   		at91_suspend_finish(0);
>   	}
> @@ -707,6 +712,7 @@ static int at91_pm_enter(suspend_state_t state)
>   static void at91_pm_end(void)
>   {
>   	at91_pm_config_ws(soc_pm.data.mode, false);
> +

Not needed. I'll drop it while applying.

>   }
>   
>   
> @@ -1065,7 +1071,8 @@ static int __init at91_pm_backup_init(void)
>   	int ret = -ENODEV, located = 0;
>   
>   	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
> -	    !IS_ENABLED(CONFIG_SOC_SAMA7G5))
> +	    !IS_ENABLED(CONFIG_SOC_SAMA7G5) &&
> +	    !IS_ENABLED(CONFIG_SOC_SAMA7D65))
>   		return -EPERM;
>   
>   	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:38:18 2025
From: claudiu.beznea at tuxon.dev (claudiu beznea (tuxon))
Date: Mon, 3 Mar 2025 10:38:18 +0200
Subject: [PATCH v3 17/21] ARM: dts: microchip: sama7d65: Add RTT and GPBR
 Support for sama7d65 SoC
In-Reply-To: <6a1c058edee3fe1459dcb3a93a0a789a9ffff5f3.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <6a1c058edee3fe1459dcb3a93a0a789a9ffff5f3.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <6d762706-27b5-4b0b-bcab-ae96a831c03a@tuxon.dev>



On 2/27/25 17:52, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> Add RTT support for SAMA7D65 SoC. The GPBR is added so the SoC is able
> to store the RTT time data.
> 
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> ---
>   arch/arm/boot/dts/microchip/sama7d65.dtsi | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> index b0a676623100..aadeea132289 100644
> --- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
> +++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
> @@ -120,6 +120,13 @@ shdwc: poweroff at e001d200 {
>   			status = "disabled";
>   		};
>   
> +		rtt: rtc at e001d300 {
> +			compatible = "microchip,sama7d65-rtt", "atmel,at91sam9260-rtt";
> +			reg = <0xe001d300 0x30>;
> +			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&clk32k 0>;
> +		};
> +
>   		clk32k: clock-controller at e001d500 {
>   			compatible = "microchip,sama7d65-sckc", "microchip,sam9x60-sckc";
>   			reg = <0xe001d500 0x4>;
> @@ -132,6 +139,11 @@ chipid at e0020000 {
>   			reg = <0xe0020000 0x8>;
>   		};
>   
> +		gpbr: gpbr at e001d700 {
> +			compatible = "microchip,sama7d65-gpbr", "syscon";
> +			reg = <0xe001d700 0x48>;
> +		};

This node should be before chipid one to have them sorted by node address.

> +
>   		dma2: dma-controller at e1200000 {
>   			compatible = "microchip,sama7d65-dma", "microchip,sama7g5-dma";
>   			reg = <0xe1200000 0x1000>;



From claudiu.beznea at tuxon.dev  Mon Mar  3 00:40:25 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Mon, 3 Mar 2025 10:40:25 +0200
Subject: [PATCH v3 00/21] Enable Power Modes Support for SAMA7D65 SoC
In-Reply-To: <cover.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <2a18e305-090c-41fe-9b27-97ebe93fd4e4@tuxon.dev>



On 27.02.2025 17:51, Ryan.Wanner at microchip.com wrote:
> Ryan Wanner (20):
>   ARM: at91: Add PM support to sama7d65
>   ARM: at91: pm: add DT compatible support for sama7d65
>   ARM: at91: PM: Add Backup mode for SAMA7D65
>   ARM: at91: pm: Enable ULP0/ULP1 for SAMA7D65

Applied to at91-soc with some adjustments, please check!

>   ARM: dts: microchip: sama7d65: Add Reset Controller to sama7d65 SoC
>   ARM: dts: microchip: sama7d65: Add Shutdown controller support
>   ARM: dts: microchip: sama7d65: Add RTC support for sama7d65
>   ARM: dts: microchip: sama7d65: Add SFRBU support to sama7d65
>   ARM: dts: microchip: sama7d65: Enable shutdown controller

Applied to at91-dt with some adjustments, please check!

Thank you!


From linus.walleij at linaro.org  Mon Mar  3 00:41:40 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 03 Mar 2025 09:41:40 +0100
Subject: [PATCH 0/6] ASoC: samsung: GPIO descriptor conversion
Message-ID: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>

This drops unused includes and converts one Samsung
codec to use GPIO descriptors.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
Linus Walleij (6):
      ASoC: samsung: bells: Drop unused include
      ASoC: samsung: littlemill: Drop unused include
      ASoC: samsung: lowland: Drop unused include
      ASoC: samsung: speyside: Convert to GPIO descriptor
      ASoC: samsung: tobermory: Drop unused include
      ASoC: samsung: tm2_wm5110: Drop unused include

 sound/soc/samsung/bells.c      |  1 -
 sound/soc/samsung/littlemill.c |  1 -
 sound/soc/samsung/lowland.c    |  1 -
 sound/soc/samsung/speyside.c   | 37 ++++++++++++++++++++++++++++++-------
 sound/soc/samsung/tm2_wm5110.c |  1 -
 sound/soc/samsung/tobermory.c  |  1 -
 6 files changed, 30 insertions(+), 12 deletions(-)
---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20250302-samsung-codecs-6366e1b3f283

Best regards,
-- 
Linus Walleij <linus.walleij at linaro.org>



From yubing.zhang at rock-chips.com  Mon Mar  3 00:59:50 2025
From: yubing.zhang at rock-chips.com (Yubing Zhang)
Date: Mon, 3 Mar 2025 16:59:50 +0800
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
Message-ID: <65706d63-18aa-41e0-81c4-4eab3d186250@rock-chips.com>

Hi Dmitry,

On 2025/3/2 2:14, Dmitry Baryshkov wrote:
> On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
>> From: Andy Yan <andy.yan at rock-chips.com>
>>
>> The DW DP TX Controller is compliant with the DisplayPort Specification
>> Version 1.4 with the following features:
>>
>> * DisplayPort 1.4a
>> * Main Link: 1/2/4 lanes
>> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> * AUX channel 1Mbps
>> * Single Stream Transport(SST)
>> * Multistream Transport (MST)
>> *?Type-C support (alternate mode)
>> * HDCP 2.2, HDCP 1.3
>> * Supports up to 8/10 bits per color component
>> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> * Pixel clock up to 594MHz
>> * I2S, SPDIF audio interface
>>
>> Add library with common helpers to make it can be shared with
>> other SoC.
>>
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>>
>> drm/bridge: cleanup
> 
> Stray line?
> 
>>
>> ---
>>
>>   drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
>>   drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
>>   drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
>>   include/drm/bridge/dw_dp.h               |   19 +
>>   4 files changed, 2182 insertions(+)
>>   create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c

......

>> +
>> +static u8 dw_dp_voltage_max(u8 preemph)
>> +{
>> +	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_0:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_1:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_2:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
>> +	case DP_TRAIN_PRE_EMPH_LEVEL_3:
>> +	default:
>> +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
>> +	}
>> +}
>> +
>> +static void dw_dp_link_get_adjustments(struct dw_dp_link *link,
>> +				       u8 status[DP_LINK_STATUS_SIZE])
>> +{
>> +	struct dw_dp_link_train_set *adjust = &link->train.adjust;
>> +	u8 v = 0;
>> +	u8 p = 0;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < link->lanes; i++) {
>> +		v = drm_dp_get_adjust_request_voltage(status, i);
>> +		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
>> +		if (p >=  DP_TRAIN_PRE_EMPH_LEVEL_3) {
>> +			adjust->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
>> +						  DP_TRAIN_PRE_EMPHASIS_SHIFT;
>> +			adjust->pre_max_reached[i] = true;
>> +		} else {
>> +			adjust->pre_emphasis[i] = p >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
>> +			adjust->pre_max_reached[i] = false;
>> +		}
>> +		v = min(v, dw_dp_voltage_max(p));
>> +		if (v >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) {
>> +			adjust->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
>> +						   DP_TRAIN_VOLTAGE_SWING_SHIFT;
>> +			adjust->voltage_max_reached[i] = true;
>> +		} else {
>> +			adjust->voltage_swing[i] = v >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
>> +			adjust->voltage_max_reached[i] = false;
>> +		}
>> +	}
>> +}
>> +
>> +static void dw_dp_link_train_adjust(struct dw_dp_link_train *train)
>> +{
>> +	struct dw_dp_link_train_set *request = &train->request;
>> +	struct dw_dp_link_train_set *adjust = &train->adjust;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < 4; i++) {
> 
> Shouldn't it be a loop up to link->lanes?
> 
>> +		if (request->voltage_swing[i] != adjust->voltage_swing[i])
>> +			request->voltage_swing[i] = adjust->voltage_swing[i];
>> +		if (request->voltage_max_reached[i] != adjust->voltage_max_reached[i])
>> +			request->voltage_max_reached[i] = adjust->voltage_max_reached[i];
>> +	}
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
>> +			request->pre_emphasis[i] = adjust->pre_emphasis[i];
>> +		if (request->pre_max_reached[i] != adjust->pre_max_reached[i])
>> +			request->pre_max_reached[i] = adjust->pre_max_reached[i];
> 
> Why do you need separate request and adjustment structs?
During link training cr sequence, if dprx keep the LANEx_CR_DONE bit(s) 
cleared, the request and adjustment structs are used to check the
old and new valud of ADJUST_REQUEST_LANEx_y register(s) is changed or not.

> 
>> +	}
>> +}
>> +
>> +static int dw_dp_link_clock_recovery(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 status[DP_LINK_STATUS_SIZE];
>> +	unsigned int tries = 0;
>> +	int ret;
>> +
>> +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
>> +	if (ret)
>> +		return ret;
>> +
>> +	for (;;) {
>> +		ret = dw_dp_link_train_update_vs_emph(dp);
>> +		if (ret)
>> +			return ret;
>> +
>> +		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
>> +
>> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
>> +		if (ret < 0) {
>> +			dev_err(dp->dev, "failed to read link status: %d\n", ret);
>> +			return ret;
>> +		}
>> +
>> +		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
>> +			link->train.clock_recovered = true;
>> +			break;
>> +		}
>> +
>> +		dw_dp_link_get_adjustments(link, status);
>> +
>> +		if (link->train.request.voltage_swing[0] ==
>> +		    link->train.adjust.voltage_swing[0])
> 
> Should this take all lanes to account? I think it might be posssible to
> drop the adjust / request split and adjust tries in
> dw_dp_link_get_adjustments() instead.
Yes, here shall compare both swing and pre-emphasis for all lanes. It's 
a good idea to drop the adjust / request split. The swing and 
pre-emphasis compare just need by cr sequence. But both cr and eq 
sequences use  dw_dp_link_get_adjustments(). It will be better to delete 
dw_dp_link_train_adjust() and add a new function to adjust tries for cr 
sequence.
> 
>> +			tries++;
>> +		else
>> +			tries = 0;
>> +
>> +		if (tries == 5)
>> +			break;
>> +
>> +		dw_dp_link_train_adjust(&link->train);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int dw_dp_link_channel_equalization(struct dw_dp *dp)
>> +{
>> +	struct dw_dp_link *link = &dp->link;
>> +	u8 status[DP_LINK_STATUS_SIZE], pattern;
>> +	unsigned int tries;
>> +	int ret;
>> +
>> +	if (link->caps.tps4_supported)
>> +		pattern = DP_TRAINING_PATTERN_4;
>> +	else if (link->caps.tps3_supported)
>> +		pattern = DP_TRAINING_PATTERN_3;
>> +	else
>> +		pattern = DP_TRAINING_PATTERN_2;
>> +	ret = dw_dp_link_train_set_pattern(dp, pattern);
>> +	if (ret)
>> +		return ret;
>> +
>> +	for (tries = 1; tries < 5; tries++) {
>> +		ret = dw_dp_link_train_update_vs_emph(dp);
>> +		if (ret)
>> +			return ret;
>> +
>> +		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
>> +
>> +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
>> +			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
>> +			link->train.clock_recovered = false;
>> +			break;
>> +		}
>> +
>> +		if (drm_dp_channel_eq_ok(status, link->lanes)) {
>> +			link->train.channel_equalized = true;
>> +			break;
>> +		}
>> +
>> +		dw_dp_link_get_adjustments(link, status);
>> +		dw_dp_link_train_adjust(&link->train);
>> +	}
>> +
>> +	return 0;
>> +}
......
>> +
>> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>> +			 const struct dw_dp_plat_data *plat_data);
>> +#endif /* __DW_DP__ */
>> -- 
>> 2.34.1
>>
> 



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:15 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:15 +0100
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for fixed-link configuration
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-10-maxime.chevallier@bootlin.com>

When phylink creates a fixed-link configuration, it finds a matching
linkmode to set as the advertised, lp_advertising and supported modes
based on the speed and duplex of the fixed link.

Use the newly introduced phy_caps_lookup to get these modes instead of
phy_lookup_settings(). This has the side effect that the matched
settings and configured linkmodes may now contain several linkmodes (the
intersection of supported linkmodes from the phylink settings and the
linkmodes that match speed/duplex) instead of the one from
phy_lookup_settings().

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Remove unnecessary linklmode_zero in phylink_set_fixed_link(),
follwing Russell's comment

 drivers/net/phy/phylink.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 6c67d5c9b787..0b9585cb508e 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -805,9 +805,10 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
 static int phylink_parse_fixedlink(struct phylink *pl,
 				   const struct fwnode_handle *fwnode)
 {
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(match) = { 0, };
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+	const struct link_capabilities *c;
 	struct fwnode_handle *fixed_node;
-	const struct phy_setting *s;
 	struct gpio_desc *desc;
 	u32 speed;
 	int ret;
@@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
 	linkmode_copy(pl->link_config.advertising, pl->supported);
 	phylink_validate(pl, pl->supported, &pl->link_config);
 
-	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
-			       pl->supported, true);
+	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
+			    pl->supported, true);
+	if (c)
+		linkmode_and(match, pl->supported, c->linkmodes);
 
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask);
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask);
@@ -889,9 +892,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
 
 	phylink_set(pl->supported, MII);
 
-	if (s) {
-		__set_bit(s->bit, pl->supported);
-		__set_bit(s->bit, pl->link_config.lp_advertising);
+	if (c) {
+		linkmode_or(pl->supported, pl->supported, match);
+		linkmode_or(pl->link_config.lp_advertising,
+			    pl->link_config.lp_advertising, match);
 	} else {
 		phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n",
 			     pl->link_config.duplex == DUPLEX_FULL ? "full" : "half",
@@ -1879,21 +1883,20 @@ static int phylink_register_sfp(struct phylink *pl,
 int phylink_set_fixed_link(struct phylink *pl,
 			   const struct phylink_link_state *state)
 {
-	const struct phy_setting *s;
+	const struct link_capabilities *c;
 	unsigned long *adv;
 
 	if (pl->cfg_link_an_mode != MLO_AN_PHY || !state ||
 	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
 		return -EINVAL;
 
-	s = phy_lookup_setting(state->speed, state->duplex,
-			       pl->supported, true);
-	if (!s)
+	c = phy_caps_lookup(state->speed, state->duplex,
+			    pl->supported, true);
+	if (!c)
 		return -EINVAL;
 
 	adv = pl->link_config.advertising;
-	linkmode_zero(adv);
-	linkmode_set_bit(s->bit, adv);
+	linkmode_and(adv, pl->supported, c->linkmodes);
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv);
 
 	pl->link_config.speed = state->speed;
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:16 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:16 +0100
Subject: [PATCH net-next v4 10/13] net: phy: drop phy_settings and the associated lookup helpers
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-11-maxime.chevallier@bootlin.com>

The phy_settings array is no longer relevant as it has now been replaced
by the link_caps array and associated phy_caps helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phy-core.c | 184 -------------------------------------
 include/linux/phy.h        |  13 ---
 2 files changed, 197 deletions(-)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 6cb8f857a7f1..e7d0137abd48 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -156,190 +156,6 @@ int phy_interface_num_ports(phy_interface_t interface)
 }
 EXPORT_SYMBOL_GPL(phy_interface_num_ports);
 
-/* A mapping of all SUPPORTED settings to speed/duplex.  This table
- * must be grouped by speed and sorted in descending match priority
- * - iow, descending speed.
- */
-
-#define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \
-			       .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}
-
-static const struct phy_setting settings[] = {
-	/* 800G */
-	PHY_SETTING( 800000, FULL, 800000baseCR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseKR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR8_2_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseSR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseVR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseCR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseKR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR4_2_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseSR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseVR4_Full		),
-	/* 400G */
-	PHY_SETTING( 400000, FULL, 400000baseCR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full	),
-	PHY_SETTING( 400000, FULL, 400000baseDR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseCR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseLR4_ER4_FR4_Full	),
-	PHY_SETTING( 400000, FULL, 400000baseDR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseCR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseDR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseDR2_2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseVR2_Full		),
-	/* 200G */
-	PHY_SETTING( 200000, FULL, 200000baseCR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full	),
-	PHY_SETTING( 200000, FULL, 200000baseDR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseCR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseLR2_ER2_FR2_Full	),
-	PHY_SETTING( 200000, FULL, 200000baseDR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseCR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseDR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseDR_2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseVR_Full		),
-	/* 100G */
-	PHY_SETTING( 100000, FULL, 100000baseCR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseSR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseCR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseDR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseSR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseCR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR_ER_FR_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseDR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseSR_Full		),
-	/* 56G */
-	PHY_SETTING(  56000, FULL,  56000baseCR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseKR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseLR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseSR4_Full	  	),
-	/* 50G */
-	PHY_SETTING(  50000, FULL,  50000baseCR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseKR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseSR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseCR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseKR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseLR_ER_FR_Full	),
-	PHY_SETTING(  50000, FULL,  50000baseDR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseSR_Full		),
-	/* 40G */
-	PHY_SETTING(  40000, FULL,  40000baseCR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseKR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseLR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseSR4_Full		),
-	/* 25G */
-	PHY_SETTING(  25000, FULL,  25000baseCR_Full		),
-	PHY_SETTING(  25000, FULL,  25000baseKR_Full		),
-	PHY_SETTING(  25000, FULL,  25000baseSR_Full		),
-	/* 20G */
-	PHY_SETTING(  20000, FULL,  20000baseKR2_Full		),
-	PHY_SETTING(  20000, FULL,  20000baseMLD2_Full		),
-	/* 10G */
-	PHY_SETTING(  10000, FULL,  10000baseCR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseER_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseKR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseKX4_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseLR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseLRM_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseR_FEC		),
-	PHY_SETTING(  10000, FULL,  10000baseSR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseT_Full		),
-	/* 5G */
-	PHY_SETTING(   5000, FULL,   5000baseT_Full		),
-	/* 2.5G */
-	PHY_SETTING(   2500, FULL,   2500baseT_Full		),
-	PHY_SETTING(   2500, FULL,   2500baseX_Full		),
-	/* 1G */
-	PHY_SETTING(   1000, FULL,   1000baseT_Full		),
-	PHY_SETTING(   1000, HALF,   1000baseT_Half		),
-	PHY_SETTING(   1000, FULL,   1000baseT1_Full		),
-	PHY_SETTING(   1000, FULL,   1000baseX_Full		),
-	PHY_SETTING(   1000, FULL,   1000baseKX_Full		),
-	/* 100M */
-	PHY_SETTING(    100, FULL,    100baseT_Full		),
-	PHY_SETTING(    100, FULL,    100baseT1_Full		),
-	PHY_SETTING(    100, HALF,    100baseT_Half		),
-	PHY_SETTING(    100, HALF,    100baseFX_Half		),
-	PHY_SETTING(    100, FULL,    100baseFX_Full		),
-	/* 10M */
-	PHY_SETTING(     10, FULL,     10baseT_Full		),
-	PHY_SETTING(     10, HALF,     10baseT_Half		),
-	PHY_SETTING(     10, FULL,     10baseT1L_Full		),
-	PHY_SETTING(     10, FULL,     10baseT1S_Full		),
-	PHY_SETTING(     10, HALF,     10baseT1S_Half		),
-	PHY_SETTING(     10, HALF,     10baseT1S_P2MP_Half	),
-	PHY_SETTING(     10, FULL,     10baseT1BRR_Full		),
-};
-#undef PHY_SETTING
-
-/**
- * phy_lookup_setting - lookup a PHY setting
- * @speed: speed to match
- * @duplex: duplex to match
- * @mask: allowed link modes
- * @exact: an exact match is required
- *
- * Search the settings array for a setting that matches the speed and
- * duplex, and which is supported.
- *
- * If @exact is unset, either an exact match or %NULL for no match will
- * be returned.
- *
- * If @exact is set, an exact match, the fastest supported setting at
- * or below the specified speed, the slowest supported setting, or if
- * they all fail, %NULL will be returned.
- */
-const struct phy_setting *
-phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
-{
-	const struct phy_setting *p, *match = NULL, *last = NULL;
-	int i;
-
-	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
-		if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
-		    test_bit(p->bit, mask)) {
-			last = p;
-			if (p->speed == speed && p->duplex == duplex) {
-				/* Exact match for speed and duplex */
-				match = p;
-				break;
-			} else if (!exact) {
-				if (!match && p->speed <= speed)
-					/* Candidate */
-					match = p;
-
-				if (p->speed < speed)
-					break;
-			}
-		}
-	}
-
-	if (!match && !exact)
-		match = last;
-
-	return match;
-}
-EXPORT_SYMBOL_GPL(phy_lookup_setting);
-
 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
 	phy_caps_linkmode_max_speed(max_speed, phydev->supported);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 5749aad96862..4a59aa7254f4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1310,19 +1310,6 @@ const char *phy_rate_matching_to_str(int rate_matching);
 
 int phy_interface_num_ports(phy_interface_t interface);
 
-/* A structure for mapping a particular speed and duplex
- * combination to a particular SUPPORTED and ADVERTISED value
- */
-struct phy_setting {
-	u32 speed;
-	u8 duplex;
-	u8 bit;
-};
-
-const struct phy_setting *
-phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
-		   bool exact);
-
 /**
  * phy_is_started - Convenience function to check whether PHY is started
  * @phydev: The phy_device struct
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:17 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:17 +0100
Subject: [PATCH net-next v4 11/13] net: phylink: Add a mapping between MAC_CAPS and LINK_CAPS
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-12-maxime.chevallier@bootlin.com>

phylink allows MAC drivers to report the capabilities in terms of speed,
duplex and pause support. This is done through a dedicated set of enum
values in the form of the MAC_ capabilities. They are very close to what
the LINK_CAPA_xxx can express, with the difference that LINK_CAPA don't
have any information about Pause/Asym Pause support.

To prepare converting phylink to using the phy_caps, add the mapping
between MAC capabilities and phy_caps. While doing so, we move the
phylink_caps_params array up a bit to simplify future commits.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phylink.c | 49 ++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0b9585cb508e..9cb3beec9f47 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -292,6 +292,31 @@ static int phylink_interface_max_speed(phy_interface_t interface)
 	return SPEED_UNKNOWN;
 }
 
+static struct {
+	unsigned long mask;
+	int speed;
+	unsigned int duplex;
+	unsigned int caps_bit;
+} phylink_caps_params[] = {
+	{ MAC_400000FD, SPEED_400000, DUPLEX_FULL, BIT(LINK_CAPA_400000FD) },
+	{ MAC_200000FD, SPEED_200000, DUPLEX_FULL, BIT(LINK_CAPA_200000FD) },
+	{ MAC_100000FD, SPEED_100000, DUPLEX_FULL, BIT(LINK_CAPA_100000FD) },
+	{ MAC_56000FD,  SPEED_56000,  DUPLEX_FULL, BIT(LINK_CAPA_56000FD) },
+	{ MAC_50000FD,  SPEED_50000,  DUPLEX_FULL, BIT(LINK_CAPA_50000FD) },
+	{ MAC_40000FD,  SPEED_40000,  DUPLEX_FULL, BIT(LINK_CAPA_40000FD) },
+	{ MAC_25000FD,  SPEED_25000,  DUPLEX_FULL, BIT(LINK_CAPA_25000FD) },
+	{ MAC_20000FD,  SPEED_20000,  DUPLEX_FULL, BIT(LINK_CAPA_20000FD) },
+	{ MAC_10000FD,  SPEED_10000,  DUPLEX_FULL, BIT(LINK_CAPA_10000FD) },
+	{ MAC_5000FD,   SPEED_5000,   DUPLEX_FULL, BIT(LINK_CAPA_5000FD) },
+	{ MAC_2500FD,   SPEED_2500,   DUPLEX_FULL, BIT(LINK_CAPA_2500FD) },
+	{ MAC_1000FD,   SPEED_1000,   DUPLEX_FULL, BIT(LINK_CAPA_1000FD) },
+	{ MAC_1000HD,   SPEED_1000,   DUPLEX_HALF, BIT(LINK_CAPA_1000HD) },
+	{ MAC_100FD,    SPEED_100,    DUPLEX_FULL, BIT(LINK_CAPA_100FD) },
+	{ MAC_100HD,    SPEED_100,    DUPLEX_HALF, BIT(LINK_CAPA_100HD) },
+	{ MAC_10FD,     SPEED_10,     DUPLEX_FULL, BIT(LINK_CAPA_10FD) },
+	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF, BIT(LINK_CAPA_10HD) },
+};
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -445,30 +470,6 @@ static void phylink_caps_to_linkmodes(unsigned long *linkmodes,
 	}
 }
 
-static struct {
-	unsigned long mask;
-	int speed;
-	unsigned int duplex;
-} phylink_caps_params[] = {
-	{ MAC_400000FD, SPEED_400000, DUPLEX_FULL },
-	{ MAC_200000FD, SPEED_200000, DUPLEX_FULL },
-	{ MAC_100000FD, SPEED_100000, DUPLEX_FULL },
-	{ MAC_56000FD,  SPEED_56000,  DUPLEX_FULL },
-	{ MAC_50000FD,  SPEED_50000,  DUPLEX_FULL },
-	{ MAC_40000FD,  SPEED_40000,  DUPLEX_FULL },
-	{ MAC_25000FD,  SPEED_25000,  DUPLEX_FULL },
-	{ MAC_20000FD,  SPEED_20000,  DUPLEX_FULL },
-	{ MAC_10000FD,  SPEED_10000,  DUPLEX_FULL },
-	{ MAC_5000FD,   SPEED_5000,   DUPLEX_FULL },
-	{ MAC_2500FD,   SPEED_2500,   DUPLEX_FULL },
-	{ MAC_1000FD,   SPEED_1000,   DUPLEX_FULL },
-	{ MAC_1000HD,   SPEED_1000,   DUPLEX_HALF },
-	{ MAC_100FD,    SPEED_100,    DUPLEX_FULL },
-	{ MAC_100HD,    SPEED_100,    DUPLEX_HALF },
-	{ MAC_10FD,     SPEED_10,     DUPLEX_FULL },
-	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF },
-};
-
 /**
  * phylink_limit_mac_speed - limit the phylink_config to a maximum speed
  * @config: pointer to a &struct phylink_config
-- 
2.48.1



From vdonnefort at google.com  Mon Mar  3 01:03:09 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Mon, 3 Mar 2025 09:03:09 +0000
Subject: [PATCH 2/9] KVM: arm64: Add a range to __pkvm_host_share_guest()
In-Reply-To: <Z8IJRpoQUoGazLku@google.com>
References: <20250228102530.1229089-1-vdonnefort@google.com>
 <20250228102530.1229089-3-vdonnefort@google.com>
 <Z8IJRpoQUoGazLku@google.com>
Message-ID: <Z8VwTf8nMvRNjgU_@google.com>

On Fri, Feb 28, 2025 at 07:06:46PM +0000, Quentin Perret wrote:
> On Friday 28 Feb 2025 at 10:25:18 (+0000), Vincent Donnefort wrote:
> > +int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
> >  			    enum kvm_pgtable_prot prot)
> >  {
> >  	struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
> >  	u64 phys = hyp_pfn_to_phys(pfn);
> >  	u64 ipa = hyp_pfn_to_phys(gfn);
> >  	struct hyp_page *page;
> > +	u64 size;
> >  	int ret;
> >  
> >  	if (prot & ~KVM_PGTABLE_PROT_RWX)
> >  		return -EINVAL;
> >  
> > -	ret = check_range_allowed_memory(phys, phys + PAGE_SIZE);
> 
> I'm not sure it is safe to drop this check here, see below.
> 
> > +	ret = __guest_check_transition_size(phys, ipa, nr_pages, &size);
> >  	if (ret)
> >  		return ret;
> >  
> >  	host_lock_component();
> >  	guest_lock_component(vm);
> >  
> > -	ret = __guest_check_page_state_range(vcpu, ipa, PAGE_SIZE, PKVM_NOPAGE);
> > +	ret = __guest_check_page_state_range(vm, ipa, size, PKVM_NOPAGE);
> >  	if (ret)
> >  		goto unlock;
> >  
> >  	page = hyp_phys_to_page(phys);
> 
> Phys really needs to be a valid memory address here for 'page' to be
> present in the vmemma -- dereference right below. So we can't rely on
> the check in __host_check_page_state_range() sadly ...

Haaa you're right. Sad to have this double check. Perhaps I won't use
__host_check_page_state_range() then.

> 
> > +	ret = __host_check_page_state_range(phys, size, page->host_state);
> > +	if (ret)
> > +		goto unlock;
> > +

[...]


From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:07 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:07 +0100
Subject: [PATCH net-next v4 01/13] net: ethtool: Export the link_mode_params definitions
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-2-maxime.chevallier@bootlin.com>

link_mode_params contains a lookup table of all 802.3 link modes that
are currently supported with structured data about each mode's speed,
duplex, number of lanes and mediums.

As a preparation for a port representation, export that table for the
rest of the net stack to use.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 include/linux/ethtool.h | 8 ++++++++
 net/ethtool/common.c    | 1 +
 net/ethtool/common.h    | 7 -------
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 7f222dccc7d1..8210ece94fa6 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -210,6 +210,14 @@ static inline u8 *ethtool_rxfh_context_key(struct ethtool_rxfh_context *ctx)
 
 void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id);
 
+struct link_mode_info {
+	int                             speed;
+	u8                              lanes;
+	u8                              duplex;
+};
+
+extern const struct link_mode_info link_mode_params[];
+
 /* declare a link mode bitmap */
 #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name)		\
 	DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS)
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index ac8b6107863e..c9d6302e88c9 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -423,6 +423,7 @@ const struct link_mode_info link_mode_params[] = {
 	__DEFINE_LINK_MODE_PARAMS(800000, VR4, Full),
 };
 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS);
+EXPORT_SYMBOL_GPL(link_mode_params);
 
 const char netif_msg_class_names[][ETH_GSTRING_LEN] = {
 	[NETIF_MSG_DRV_BIT]		= "drv",
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index a1088c2441d0..b4683d286a5a 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -15,12 +15,6 @@
 #define __SOF_TIMESTAMPING_CNT (const_ilog2(SOF_TIMESTAMPING_LAST) + 1)
 #define __HWTSTAMP_FLAG_CNT (const_ilog2(HWTSTAMP_FLAG_LAST) + 1)
 
-struct link_mode_info {
-	int				speed;
-	u8				lanes;
-	u8				duplex;
-};
-
 struct genl_info;
 struct hwtstamp_provider_desc;
 
@@ -33,7 +27,6 @@ tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
 extern const char
 phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
 extern const char link_mode_names[][ETH_GSTRING_LEN];
-extern const struct link_mode_info link_mode_params[];
 extern const char netif_msg_class_names[][ETH_GSTRING_LEN];
 extern const char wol_mode_names[][ETH_GSTRING_LEN];
 extern const char sof_timestamping_names[][ETH_GSTRING_LEN];
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:06 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:06 +0100
Subject: [PATCH net-next v4 00/13] net: phy: Rework linkmodes handling in a dedicated file
Message-ID: <20250303090321.805785-1-maxime.chevallier@bootlin.com>

Hello everyone,

This is V4 of the phy_caps series. In a nutshell, this series reworks the way
we maintain the list of speed/duplex capablities for each linkmode so that we
no longer have multiple definition of these associations.

That will help making sure that when people add new linkmodes in
include/uapi/linux/ethtool.h, they don't have to update phylib and phylink as
well, making the process more straightforward and less error-prone.

It also generalises the phy_caps interface to be able to lookup linkmodes
from phy_interface_t, which is needed for the multi-port work I've been working
on for a while.

This V4 addresses Russell's reviews, namely :

 - Introduce new iterators to traverse the link_caps array in ascending and
   descending order, making it more explicit and simple.
 - Remove an unneeded linkmode_zero in patch 9

V1 : https://lore.kernel.org/netdev/20250222142727.894124-1-maxime.chevallier at bootlin.com/
V2 : https://lore.kernel.org/netdev/20250226100929.1646454-1-maxime.chevallier at bootlin.com/
V3 : https://lore.kernel.org/netdev/20250228145540.2209551-1-maxime.chevallier at bootlin.com/

For context, The text below is an extract from the V1 cover :

Following the V4 of the phy_port series [1] we've discussed about attempting
to extract some of the linkmode <-> capabilities (speed/duplex) <-> interface
logic into a dedicated file, so that we can re-use that logic out of
phylink.

While trying to do that, I might have gotten a bit carried-away, and I'm
therefore submitting this series to rework the way we are currently
managing the linkmodes <-> capabilities handling.

We are currently defining all the possible Ethernet linkmodes in an
enum ethtool_link_mode_bit_indices value defined in uapi/linux/ethtool.h :

	ETHTOOL_LINK_MODE_10baseT_Half_BIT	= 0,
	ETHTOOL_LINK_MODE_10baseT_Full_BIT	= 1,
	...

Each of these modes represents a media-side link definition, and runs at
a given speed and duplex.

Specific attributes for each modes are stored in net/ethtool/common.c, as
an array of struct link_mode_info :

	struct link_mode_info {
		int				speed;
		u8				lanes;
		u8				duplex;
	}

The link_mode_params[] array is the canonical definition for these modes,
as (1) there are build-time checks to make sure any new linkmode
definition is also defined in this array and (2) this array is always
compiled-in, as it's part of the net stack (i.e. it is not phylib-specific).

This array is however not optimized for lookups, as it is not ordered in
any particular fashion (new modes go at the end, regardless of their speed
and duplex).

Phylib also includes a similar array, in the form of the phy_settings
array in drivers/net/phy/phy-core.c :

	struct phy_setting {
		u32 speed;
		u8 duplex;
		u8 bit; // The enum index for the linkmode
	};

The phy_settings array however is ordered by descending speeds. A variety
of helpers in phylib rely on that ordering to perform lookups, usually
to get one or any linkmode corresponding to a requested speed and duplex.

Finally, we have some helpers in phylink (phylink_caps_to_linkmodes) that
allows getting the list of linkmodes that match a set of speed and duplex
value, all at once.

While the phylink and phylib helpers allows for efficient lookups, they
have some drawbacks as well :

	(1) : It's easy to forget updating of all of these helpers and structures
		  when adding a new linkmode. New linkmodes are actually added fairly
		  often, lately either for slow BaseT1 flavours, or for crazy-fast
		  modes (800Gbps modes, but I guess people won't stop there)
		  
	(2) : Even though the phylink and phylib modes use carefull sorting
		  to speed-up the lookup process, the phylib lookups are usually
		  done in descending speed order and will therefore get slower
		  as people add even faster link speeds.
		  
This series introduces a new "link_capabilities" structure that is used
to build an array of link_caps :

	struct link_capabilities {
		int speed;                           
		unsigned int duplex;
		__ETHTOOL_DECLARE_LINK_MODE_MASK(linkmodes);
	};

We group these in an array, indexed with LINK_CAPA enums that are basically
identical to the phylink MAC_CAPS :

...
LINK_CAPA_1000HD,             
LINK_CAPA_1000FD,
LINK_CAPA_2500FD,
LINK_CAPA_5000FD,
...

We now have an associative array of <speed,duplex> <-> All compatible linkmodes

This array is initialized at phylib-init time based on the content of
the link_mode_params[] array from net/ethtool/common.c, that way it is
always up-to-date with new modes, and always properly ordered.

Patches 3 to 8 then convert all lookups from the phy_settings array into
lookups from this link_caps array, hopefully speeding-up lookups in the
meantime (we iterate over possible speeds instead of individual linkmodes)

This series is not meant to introduce changes in behaviour, however patches
9 and 10 do introduce functionnal changes. When configuring the advert
for speeds >= 1G in PHY devices, as well as when constructing the link
parameters for fixed links in phylink, we used to rely on phy_settings
lookups returning one, and only one, compatible linkmode. This series will
make so that the lookups will result on all matching linkmodes being
returned, and MAY cause advert/fixed-link configuring more linkmodes.

Patches 12 and 13 extract the conversion logic for interface <-> caps from
phylink.

There are cons as well for this, as this is a bit more init time for phylib,
but maybe more importantly, we lose in the precision for the lookups in
phy_settings. However, given all the uses for phy_settings (most are just
to get speed/duplex), I think this is actually ok, but any comment would
be very welcome.

This series was tested with :
 - 10/100/1000M links
 - 2,5, 5, 10G BaseT links
 - 1G Fixed link

I also made sure that this compiles with the following options :

CONFIG_PHYLIB=n

CNFIG_PHYLINK=m
CONFIG_PHYLIB=m

CNFIG_PHYLINK=m
CONFIG_PHYLIB=y

CNFIG_PHYLINK=y
CONFIG_PHYLIB=y

All the new helpers that were introduced (in drivers/net/phy/phy-caps.h)
are for internal use only (only users should be core stuff, such as phylib and
phylink, and in the future, phy_port).

Thanks,

Maxime

[1]: https://lore.kernel.org/netdev/20250213101606.1154014-1-maxime.chevallier at bootlin.com/

Maxime Chevallier (13):
  net: ethtool: Export the link_mode_params definitions
  net: phy: Use an internal, searchable storage for the linkmodes
  net: phy: phy_caps: Move phy_speeds to phy_caps
  net: phy: phy_caps: Move __set_linkmode_max_speed to phy_caps
  net: phy: phy_caps: Introduce phy_caps_valid
  net: phy: phy_caps: Implement link_capabilities lookup by linkmode
  net: phy: phy_caps: Allow looking-up link caps based on speed and
    duplex
  net: phy: phy_device: Use link_capabilities lookup for PHY aneg config
  net: phylink: Use phy_caps_lookup for fixed-link configuration
  net: phy: drop phy_settings and the associated lookup helpers
  net: phylink: Add a mapping between MAC_CAPS and LINK_CAPS
  net: phylink: Convert capabilities to linkmodes using phy_caps
  net: phy: phy_caps: Allow getting an phy_interface's capabilities

 drivers/net/phy/Makefile     |   2 +-
 drivers/net/phy/phy-caps.h   |  63 +++++++
 drivers/net/phy/phy-core.c   | 253 ++-----------------------
 drivers/net/phy/phy.c        |  37 +---
 drivers/net/phy/phy_caps.c   | 347 +++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c |  13 +-
 drivers/net/phy/phylink.c    | 338 +++++++++-------------------------
 include/linux/ethtool.h      |   8 +
 include/linux/phy.h          |  15 --
 net/ethtool/common.c         |   1 +
 net/ethtool/common.h         |   7 -
 11 files changed, 540 insertions(+), 544 deletions(-)
 create mode 100644 drivers/net/phy/phy-caps.h
 create mode 100644 drivers/net/phy/phy_caps.c

-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:08 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:08 +0100
Subject: [PATCH net-next v4 02/13] net: phy: Use an internal, searchable storage for the linkmodes
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-3-maxime.chevallier@bootlin.com>

The canonical definition for all the link modes is in linux/ethtool.h,
which is complemented by the link_mode_params array stored in
net/ethtool/common.h . That array contains all the metadata about each
of these modes, including the Speed and Duplex information.

Phylib and phylink needs that information as well for internal
management of the link, which was done by duplicating that information
in locally-stored arrays and lookup functions. This makes it easy for
developpers adding new modes to forget modifying phylib and phylink
accordingly.

However, the link_mode_params array in net/ethtool/common.c is fairly
inefficient to search through, as it isn't sorted in any manner. Phylib
and phylink perform a lot of lookup operations, mostly to filter modes
by speed and/or duplex.

We therefore introduce the link_caps private array in phy_caps.c, that
indexes linkmodes in a more efficient manner. Each element associated a
tuple <speed, duplex> to a bitfield of all the linkmodes runs at these
speed/duplex.

We end-up with an array that's fairly short, easily addressable and that
it optimised for the typical use-cases of phylib/phylink.

That array is initialized at the same time as phylib. As the
link_mode_params array is part of the net stack, which phylink depends
on, it should always be accessible from phylib.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Ditch the __LINK_CAPA_LAST (no longer needed)

 drivers/net/phy/Makefile     |  2 +-
 drivers/net/phy/phy-caps.h   | 43 ++++++++++++++++++++
 drivers/net/phy/phy_caps.c   | 78 ++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c |  2 +
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/phy/phy-caps.h
 create mode 100644 drivers/net/phy/phy_caps.c

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index c8dac6e92278..7e800619162b 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Linux PHY drivers
 
 libphy-y			:= phy.o phy-c45.o phy-core.o phy_device.o \
-				   linkmode.o phy_link_topology.o
+				   linkmode.o phy_link_topology.o phy_caps.o
 mdio-bus-y			+= mdio_bus.o mdio_device.o
 
 ifdef CONFIG_MDIO_DEVICE
diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
new file mode 100644
index 000000000000..8a0dc2c486bb
--- /dev/null
+++ b/drivers/net/phy/phy-caps.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * link caps internal header, for link modes <-> capabilities <-> interfaces
+ * conversions.
+ */
+
+#ifndef __PHY_CAPS_H
+#define __PHY_CAPS_H
+
+#include <linux/ethtool.h>
+
+enum {
+	LINK_CAPA_10HD = 0,
+	LINK_CAPA_10FD,
+	LINK_CAPA_100HD,
+	LINK_CAPA_100FD,
+	LINK_CAPA_1000HD,
+	LINK_CAPA_1000FD,
+	LINK_CAPA_2500FD,
+	LINK_CAPA_5000FD,
+	LINK_CAPA_10000FD,
+	LINK_CAPA_20000FD,
+	LINK_CAPA_25000FD,
+	LINK_CAPA_40000FD,
+	LINK_CAPA_50000FD,
+	LINK_CAPA_56000FD,
+	LINK_CAPA_100000FD,
+	LINK_CAPA_200000FD,
+	LINK_CAPA_400000FD,
+	LINK_CAPA_800000FD,
+
+	__LINK_CAPA_MAX,
+};
+
+struct link_capabilities {
+	int speed;
+	unsigned int duplex;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(linkmodes);
+};
+
+void phy_caps_init(void);
+
+#endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
new file mode 100644
index 000000000000..367ca7110ddc
--- /dev/null
+++ b/drivers/net/phy/phy_caps.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/ethtool.h>
+#include <linux/linkmode.h>
+#include <linux/phy.h>
+
+#include "phy-caps.h"
+
+static struct link_capabilities link_caps[__LINK_CAPA_MAX] __ro_after_init = {
+	{ SPEED_10, DUPLEX_HALF, {0} }, /* LINK_CAPA_10HD */
+	{ SPEED_10, DUPLEX_FULL, {0} }, /* LINK_CAPA_10FD */
+	{ SPEED_100, DUPLEX_HALF, {0} }, /* LINK_CAPA_100HD */
+	{ SPEED_100, DUPLEX_FULL, {0} }, /* LINK_CAPA_100FD */
+	{ SPEED_1000, DUPLEX_HALF, {0} }, /* LINK_CAPA_1000HD */
+	{ SPEED_1000, DUPLEX_FULL, {0} }, /* LINK_CAPA_1000FD */
+	{ SPEED_2500, DUPLEX_FULL, {0} }, /* LINK_CAPA_2500FD */
+	{ SPEED_5000, DUPLEX_FULL, {0} }, /* LINK_CAPA_5000FD */
+	{ SPEED_10000, DUPLEX_FULL, {0} }, /* LINK_CAPA_10000FD */
+	{ SPEED_20000, DUPLEX_FULL, {0} }, /* LINK_CAPA_20000FD */
+	{ SPEED_25000, DUPLEX_FULL, {0} }, /* LINK_CAPA_25000FD */
+	{ SPEED_40000, DUPLEX_FULL, {0} }, /* LINK_CAPA_40000FD */
+	{ SPEED_50000, DUPLEX_FULL, {0} }, /* LINK_CAPA_50000FD */
+	{ SPEED_56000, DUPLEX_FULL, {0} }, /* LINK_CAPA_56000FD */
+	{ SPEED_100000, DUPLEX_FULL, {0} }, /* LINK_CAPA_100000FD */
+	{ SPEED_200000, DUPLEX_FULL, {0} }, /* LINK_CAPA_200000FD */
+	{ SPEED_400000, DUPLEX_FULL, {0} }, /* LINK_CAPA_400000FD */
+	{ SPEED_800000, DUPLEX_FULL, {0} }, /* LINK_CAPA_800000FD */
+};
+
+static int speed_duplex_to_capa(int speed, unsigned int duplex)
+{
+	if (duplex == DUPLEX_UNKNOWN ||
+	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
+		return -EINVAL;
+
+	switch (speed) {
+	case SPEED_10: return duplex == DUPLEX_FULL ?
+			      LINK_CAPA_10FD : LINK_CAPA_10HD;
+	case SPEED_100: return duplex == DUPLEX_FULL ?
+			       LINK_CAPA_100FD : LINK_CAPA_100HD;
+	case SPEED_1000: return duplex == DUPLEX_FULL ?
+				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
+	case SPEED_2500: return LINK_CAPA_2500FD;
+	case SPEED_5000: return LINK_CAPA_5000FD;
+	case SPEED_10000: return LINK_CAPA_10000FD;
+	case SPEED_20000: return LINK_CAPA_20000FD;
+	case SPEED_25000: return LINK_CAPA_25000FD;
+	case SPEED_40000: return LINK_CAPA_40000FD;
+	case SPEED_50000: return LINK_CAPA_50000FD;
+	case SPEED_56000: return LINK_CAPA_56000FD;
+	case SPEED_100000: return LINK_CAPA_100000FD;
+	case SPEED_200000: return LINK_CAPA_200000FD;
+	case SPEED_400000: return LINK_CAPA_400000FD;
+	case SPEED_800000: return LINK_CAPA_800000FD;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
+ */
+void phy_caps_init(void)
+{
+	const struct link_mode_info *linkmode;
+	int i, capa;
+
+	/* Fill the caps array from net/ethtool/common.c */
+	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
+		linkmode = &link_mode_params[i];
+		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
+
+		if (capa < 0)
+			continue;
+
+		__set_bit(i, link_caps[capa].linkmodes);
+	}
+}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a38d399f244b..9c573555ac49 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -42,6 +42,7 @@
 #include <linux/unistd.h>
 
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 MODULE_DESCRIPTION("PHY library");
 MODULE_AUTHOR("Andy Fleming");
@@ -3795,6 +3796,7 @@ static int __init phy_init(void)
 	if (rc)
 		goto err_ethtool_phy_ops;
 
+	phy_caps_init();
 	features_init();
 
 	rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:09 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:09 +0100
Subject: [PATCH net-next v4 03/13] net: phy: phy_caps: Move phy_speeds to phy_caps
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-4-maxime.chevallier@bootlin.com>

Use the newly introduced link_capabilities array to derive the list of
possible speeds when given a combination of linkmodes. As
link_capabilities is indexed by speed, we don't have to iterate the
whole phy_settings array.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Switch to macro iterators for better readability (Russell)

 drivers/net/phy/phy-caps.h |  3 +++
 drivers/net/phy/phy-core.c | 15 ---------------
 drivers/net/phy/phy.c      |  3 ++-
 drivers/net/phy/phy_caps.c | 33 +++++++++++++++++++++++++++++++++
 include/linux/phy.h        |  2 --
 5 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 8a0dc2c486bb..52e2fb8cabab 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -40,4 +40,7 @@ struct link_capabilities {
 
 void phy_caps_init(void);
 
+size_t phy_caps_speeds(unsigned int *speeds, size_t size,
+		       unsigned long *linkmodes);
+
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index b1c1670de23b..8533e57c3500 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -339,21 +339,6 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
 }
 EXPORT_SYMBOL_GPL(phy_lookup_setting);
 
-size_t phy_speeds(unsigned int *speeds, size_t size,
-		  unsigned long *mask)
-{
-	size_t count;
-	int i;
-
-	for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
-		if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
-		    test_bit(settings[i].bit, mask) &&
-		    (count == 0 || speeds[count - 1] != settings[i].speed))
-			speeds[count++] = settings[i].speed;
-
-	return count;
-}
-
 static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
 {
 	const struct phy_setting *p;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 16ffc00b419c..3128df03feda 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -37,6 +37,7 @@
 #include <net/sock.h>
 
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 #define PHY_STATE_TIME	HZ
 
@@ -245,7 +246,7 @@ unsigned int phy_supported_speeds(struct phy_device *phy,
 				  unsigned int *speeds,
 				  unsigned int size)
 {
-	return phy_speeds(speeds, size, phy->supported);
+	return phy_caps_speeds(speeds, size, phy->supported);
 }
 
 /**
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 367ca7110ddc..827ded2729d8 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -57,6 +57,9 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex)
 	return -EINVAL;
 }
 
+#define for_each_link_caps_asc_speed(cap) \
+	for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
+
 /**
  * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
  */
@@ -76,3 +79,33 @@ void phy_caps_init(void)
 		__set_bit(i, link_caps[capa].linkmodes);
 	}
 }
+
+/**
+ * phy_caps_speeds() - Fill an array of supported SPEED_* values for given modes
+ * @speeds: Output array to store the speeds list into
+ * @size: Size of the output array
+ * @linkmodes: Linkmodes to get the speeds from
+ *
+ * Fills the speeds array with all possible speeds that can be achieved with
+ * the specified linkmodes.
+ *
+ * Returns: The number of speeds filled into the array. If the input array isn't
+ *	    big enough to store all speeds, fill it as much as possible.
+ */
+size_t phy_caps_speeds(unsigned int *speeds, size_t size,
+		       unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+	size_t count = 0;
+
+	for_each_link_caps_asc_speed(lcap) {
+		if (linkmode_intersects(lcap->linkmodes, linkmodes) &&
+		    (count == 0 || speeds[count - 1] != lcap->speed)) {
+			speeds[count++] = lcap->speed;
+			if (count >= size)
+				break;
+		}
+	}
+
+	return count;
+}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7bfbae51070a..5749aad96862 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1322,8 +1322,6 @@ struct phy_setting {
 const struct phy_setting *
 phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 		   bool exact);
-size_t phy_speeds(unsigned int *speeds, size_t size,
-		  unsigned long *mask);
 
 /**
  * phy_is_started - Convenience function to check whether PHY is started
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:11 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:11 +0100
Subject: [PATCH net-next v4 05/13] net: phy: phy_caps: Introduce phy_caps_valid
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-6-maxime.chevallier@bootlin.com>

With the link_capabilities array, it's trivial to validate a given mask
againts a <speed, duplex> tuple. Create a helper for that purpose, and
use it to replace a phy_settings lookup in phy_check_valid();

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phy-caps.h |  1 +
 drivers/net/phy/phy.c      |  2 +-
 drivers/net/phy/phy_caps.c | 19 +++++++++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index a44d983eaed8..f35ede4e557d 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -43,6 +43,7 @@ void phy_caps_init(void);
 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
+bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3128df03feda..8df37d221fba 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -260,7 +260,7 @@ unsigned int phy_supported_speeds(struct phy_device *phy,
  */
 bool phy_check_valid(int speed, int duplex, unsigned long *features)
 {
-	return !!phy_lookup_setting(speed, duplex, features, true);
+	return phy_caps_valid(speed, duplex, features);
 }
 EXPORT_SYMBOL(phy_check_valid);
 
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 132758d2eb8d..8ce7dca1acd0 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -128,3 +128,22 @@ void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
 		else
 			break;
 }
+
+/**
+ * phy_caps_valid() - Validate a linkmodes set agains given speed and duplex
+ * @speed: input speed to validate
+ * @duplex: input duplex to validate. Passing DUPLEX_UNKNOWN is always not valid
+ * @linkmodes: The linkmodes to validate
+ *
+ * Returns: True if at least one of the linkmodes in @linkmodes can function at
+ *          the given speed and duplex, false otherwise.
+ */
+bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
+{
+	int capa = speed_duplex_to_capa(speed, duplex);
+
+	if (capa < 0)
+		return false;
+
+	return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
+}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:10 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:10 +0100
Subject: [PATCH net-next v4 04/13] net: phy: phy_caps: Move __set_linkmode_max_speed to phy_caps
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-5-maxime.chevallier@bootlin.com>

Convert the __set_linkmode_max_speed to use the link_capabilities array.
This makes it easy to clamp the linkmodes to a given max speed.
Introduce a new helper phy_caps_linkmode_max_speed to replace the
previous one that used phy_settings.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Switch to macro iterators for better readability (Russell)

 drivers/net/phy/phy-caps.h |  2 ++
 drivers/net/phy/phy-core.c | 18 +++---------------
 drivers/net/phy/phy_caps.c | 19 +++++++++++++++++++
 3 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 52e2fb8cabab..a44d983eaed8 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -42,5 +42,7 @@ void phy_caps_init(void);
 
 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
+void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
+
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 8533e57c3500..f62bc1be67b2 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -7,6 +7,7 @@
 #include <linux/of.h>
 
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 /**
  * phy_speed_to_str - Return a string representing the PHY link speed
@@ -339,22 +340,9 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
 }
 EXPORT_SYMBOL_GPL(phy_lookup_setting);
 
-static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
-{
-	const struct phy_setting *p;
-	int i;
-
-	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
-		if (p->speed > max_speed)
-			linkmode_clear_bit(p->bit, addr);
-		else
-			break;
-	}
-}
-
 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
-	__set_linkmode_max_speed(max_speed, phydev->supported);
+	phy_caps_linkmode_max_speed(max_speed, phydev->supported);
 }
 
 /**
@@ -557,7 +545,7 @@ int phy_speed_down_core(struct phy_device *phydev)
 	if (min_common_speed == SPEED_UNKNOWN)
 		return -EINVAL;
 
-	__set_linkmode_max_speed(min_common_speed, phydev->advertising);
+	phy_caps_linkmode_max_speed(min_common_speed, phydev->advertising);
 
 	return 0;
 }
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 827ded2729d8..132758d2eb8d 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -60,6 +60,9 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex)
 #define for_each_link_caps_asc_speed(cap) \
 	for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
 
+#define for_each_link_caps_desc_speed(cap) \
+	for (cap = &link_caps[__LINK_CAPA_MAX - 1]; cap >= link_caps; cap--)
+
 /**
  * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
  */
@@ -109,3 +112,19 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 
 	return count;
 }
+
+/**
+ * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
+ * @max_speed: Speed limit for the linkmode set
+ * @linkmodes: Linkmodes to limit
+ */
+void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_desc_speed(lcap)
+		if (lcap->speed > max_speed)
+			linkmode_andnot(linkmodes, linkmodes, lcap->linkmodes);
+		else
+			break;
+}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:12 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:12 +0100
Subject: [PATCH net-next v4 06/13] net: phy: phy_caps: Implement link_capabilities lookup by linkmode
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-7-maxime.chevallier@bootlin.com>

In several occasions, phylib needs to lookup a set of matching speed and
duplex against a given linkmode set. Instead of relying on the
phy_settings array and thus iterate over the whole linkmodes list, use
the link_capabilities array to lookup these matches, as we aren't
interested in the actual link setting that matches but rather the speed
and duplex for that setting.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Switch to macro iterators for better readability (Russell)

 drivers/net/phy/phy-caps.h |  5 +++++
 drivers/net/phy/phy-core.c | 36 +++++++++++++-----------------
 drivers/net/phy/phy_caps.c | 45 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index f35ede4e557d..7103cf508d7e 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -45,5 +45,10 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
+
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only);
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index f62bc1be67b2..6cb8f857a7f1 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -468,16 +468,15 @@ EXPORT_SYMBOL_GPL(phy_resolve_aneg_pause);
 void phy_resolve_aneg_linkmode(struct phy_device *phydev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i;
+	const struct link_capabilities *c;
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	for (i = 0; i < ARRAY_SIZE(settings); i++)
-		if (test_bit(settings[i].bit, common)) {
-			phydev->speed = settings[i].speed;
-			phydev->duplex = settings[i].duplex;
-			break;
-		}
+	c = phy_caps_lookup_by_linkmode(common);
+	if (c) {
+		phydev->speed = c->speed;
+		phydev->duplex = c->duplex;
+	}
 
 	phy_resolve_aneg_pause(phydev);
 }
@@ -495,7 +494,8 @@ EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
 void phy_check_downshift(struct phy_device *phydev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i, speed = SPEED_UNKNOWN;
+	const struct link_capabilities *c;
+	int speed = SPEED_UNKNOWN;
 
 	phydev->downshifted_rate = 0;
 
@@ -505,11 +505,9 @@ void phy_check_downshift(struct phy_device *phydev)
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	for (i = 0; i < ARRAY_SIZE(settings); i++)
-		if (test_bit(settings[i].bit, common)) {
-			speed = settings[i].speed;
-			break;
-		}
+	c = phy_caps_lookup_by_linkmode(common);
+	if (c)
+		speed = c->speed;
 
 	if (speed == SPEED_UNKNOWN || phydev->speed >= speed)
 		return;
@@ -523,17 +521,13 @@ void phy_check_downshift(struct phy_device *phydev)
 static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i = ARRAY_SIZE(settings);
+	const struct link_capabilities *c;
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	while (--i >= 0) {
-		if (test_bit(settings[i].bit, common)) {
-			if (fdx_only && settings[i].duplex != DUPLEX_FULL)
-				continue;
-			return settings[i].speed;
-		}
-	}
+	c = phy_caps_lookup_by_linkmode_rev(common, fdx_only);
+	if (c)
+		return c->speed;
 
 	return SPEED_UNKNOWN;
 }
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 8ce7dca1acd0..8160cb53b5ae 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -113,6 +113,51 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 	return count;
 }
 
+/**
+ * phy_caps_lookup_by_linkmode() - Lookup the fastest matching link_capabilities
+ * @linkmodes: Linkmodes to match against
+ *
+ * Returns: The highest-speed link_capabilities that intersects the given
+ *	    linkmodes. In case several DUPLEX_ options exist at that speed,
+ *	    DUPLEX_FULL is matched first. NULL is returned if no match.
+ */
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode(const unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_desc_speed(lcap)
+		if (linkmode_intersects(lcap->linkmodes, linkmodes))
+			return lcap;
+
+	return NULL;
+}
+
+/**
+ * phy_caps_lookup_by_linkmode_rev() - Lookup the slowest matching link_capabilities
+ * @linkmodes: Linkmodes to match against
+ * @fdx_only: Full duplex match only when set
+ *
+ * Returns: The lowest-speed link_capabilities that intersects the given
+ *	    linkmodes. When set, fdx_only will ignore half-duplex matches.
+ *	    NULL is returned if no match.
+ */
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_asc_speed(lcap) {
+		if (fdx_only && lcap->duplex != DUPLEX_FULL)
+			continue;
+
+		if (linkmode_intersects(lcap->linkmodes, linkmodes))
+			return lcap;
+	}
+
+	return NULL;
+}
+
 /**
  * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
  * @max_speed: Speed limit for the linkmode set
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:13 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:13 +0100
Subject: [PATCH net-next v4 07/13] net: phy: phy_caps: Allow looking-up link caps based on speed and duplex
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-8-maxime.chevallier@bootlin.com>

As the link_caps array is efficient for <speed,duplex> lookups,
implement a function for speed/duplex lookups that matches a given
mask. This replicates to some extent the phy_lookup_settings()
behaviour, matching full link_capabilities instead of a single linkmode.

phy.c's phy_santize_settings() and phylink's
phylink_ethtool_ksettings_set() performs such lookup using the
phy_settings table, but are only interested in the actual speed/duplex
that were matched, rathet than the individual linkmode.

Similar to phy_lookup_settings(), the newly introduced phy_caps_lookup()
will run through the link_caps[] array by descending speed/duplex order.

If the link_capabilities for a given <speed/duplex> tuple intersects the
passed linkmodes, we consider that a match.

Similar to phy_lookup_settings(), we also allow passing an 'exact'
boolean, allowing non-exact match. Here, we MUST always match the
linkmodes mask, but we allow matching on lower speed settings.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: Switch to macro iterators for better readability (Russell)

 drivers/net/phy/phy-caps.h |  4 ++++
 drivers/net/phy/phy.c      | 32 ++++++--------------------
 drivers/net/phy/phy_caps.c | 47 ++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phylink.c  | 17 +++++++-------
 4 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 7103cf508d7e..8ae8dc42494f 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -51,4 +51,8 @@ phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only);
 
+const struct link_capabilities *
+phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
+		bool exact);
+
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8df37d221fba..562acde89224 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -213,25 +213,6 @@ int phy_aneg_done(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_aneg_done);
 
-/**
- * phy_find_valid - find a PHY setting that matches the requested parameters
- * @speed: desired speed
- * @duplex: desired duplex
- * @supported: mask of supported link modes
- *
- * Locate a supported phy setting that is, in priority order:
- * - an exact match for the specified speed and duplex mode
- * - a match for the specified speed, or slower speed
- * - the slowest supported speed
- * Returns the matched phy_setting entry, or %NULL if no supported phy
- * settings were found.
- */
-static const struct phy_setting *
-phy_find_valid(int speed, int duplex, unsigned long *supported)
-{
-	return phy_lookup_setting(speed, duplex, supported, false);
-}
-
 /**
  * phy_supported_speeds - return all speeds currently supported by a phy device
  * @phy: The phy device to return supported speeds of.
@@ -274,13 +255,14 @@ EXPORT_SYMBOL(phy_check_valid);
  */
 static void phy_sanitize_settings(struct phy_device *phydev)
 {
-	const struct phy_setting *setting;
+	const struct link_capabilities *c;
+
+	c = phy_caps_lookup(phydev->speed, phydev->duplex, phydev->supported,
+			    false);
 
-	setting = phy_find_valid(phydev->speed, phydev->duplex,
-				 phydev->supported);
-	if (setting) {
-		phydev->speed = setting->speed;
-		phydev->duplex = setting->duplex;
+	if (c) {
+		phydev->speed = c->speed;
+		phydev->duplex = c->duplex;
 	} else {
 		/* We failed to find anything (no supported speeds?) */
 		phydev->speed = SPEED_UNKNOWN;
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 8160cb53b5ae..8b90fb6d6b15 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -158,6 +158,53 @@ phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
 	return NULL;
 }
 
+/**
+ * phy_caps_lookup() - Lookup capabilities by speed/duplex that matches a mask
+ * @speed: Speed to match
+ * @duplex: Duplex to match
+ * @supported: Mask of linkmodes to match
+ * @exact: Perform an exact match or not.
+ *
+ * Lookup a link_capabilities entry that intersect the supported linkmodes mask,
+ * and that matches the passed speed and duplex.
+ *
+ * When @exact is set, an exact match is performed on speed and duplex, meaning
+ * that if the linkmodes for the given speed and duplex intersect the supported
+ * mask, this capability is returned, otherwise we don't have a match and return
+ * NULL.
+ *
+ * When @exact is not set, we return either an exact match, or matching capabilities
+ * at lower speed, or the lowest matching speed, or NULL.
+ *
+ * Returns: a matched link_capabilities according to the above process, NULL
+ *	    otherwise.
+ */
+const struct link_capabilities *
+phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
+		bool exact)
+{
+	const struct link_capabilities *lcap, *last = NULL;
+
+	for_each_link_caps_desc_speed(lcap) {
+		if (linkmode_intersects(lcap->linkmodes, supported)) {
+			last = lcap;
+			/* exact match on speed and duplex*/
+			if (lcap->speed == speed && lcap->duplex == duplex) {
+				return lcap;
+			} else if (!exact) {
+				if (lcap->speed <= speed)
+					return lcap;
+			}
+		}
+	}
+
+	if (!exact)
+		return last;
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(phy_caps_lookup);
+
 /**
  * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
  * @max_speed: Speed limit for the linkmode set
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3b186ab3854..6c67d5c9b787 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
+#include "phy-caps.h"
 #include "sfp.h"
 #include "swphy.h"
 
@@ -2852,8 +2853,8 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 				  const struct ethtool_link_ksettings *kset)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
+	const struct link_capabilities *c;
 	struct phylink_link_state config;
-	const struct phy_setting *s;
 
 	ASSERT_RTNL();
 
@@ -2896,23 +2897,23 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 		/* Autonegotiation disabled, select a suitable speed and
 		 * duplex.
 		 */
-		s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
-				       pl->supported, false);
-		if (!s)
+		c = phy_caps_lookup(kset->base.speed, kset->base.duplex,
+				    pl->supported, false);
+		if (!c)
 			return -EINVAL;
 
 		/* If we have a fixed link, refuse to change link parameters.
 		 * If the link parameters match, accept them but do nothing.
 		 */
 		if (pl->req_link_an_mode == MLO_AN_FIXED) {
-			if (s->speed != pl->link_config.speed ||
-			    s->duplex != pl->link_config.duplex)
+			if (c->speed != pl->link_config.speed ||
+			    c->duplex != pl->link_config.duplex)
 				return -EINVAL;
 			return 0;
 		}
 
-		config.speed = s->speed;
-		config.duplex = s->duplex;
+		config.speed = c->speed;
+		config.duplex = c->duplex;
 		break;
 
 	case AUTONEG_ENABLE:
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:14 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:14 +0100
Subject: [PATCH net-next v4 08/13] net: phy: phy_device: Use link_capabilities lookup for PHY aneg config
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-9-maxime.chevallier@bootlin.com>

When configuring PHY advertising with autoneg disabled, we lookd for an
exact linkmode to advertise and configure for the requested Speed and
Duplex, specially at or over 1G.

Using phy_caps_lookup allows us to build a list of the supported
linkmodes at that speed that we can advertise instead of the first mode
that matches.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phy_device.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 9c573555ac49..57b90ec6477e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2357,7 +2357,7 @@ EXPORT_SYMBOL(genphy_check_and_restart_aneg);
 int __genphy_config_aneg(struct phy_device *phydev, bool changed)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(fixed_advert);
-	const struct phy_setting *set;
+	const struct link_capabilities *c;
 	unsigned long *advert;
 	int err;
 
@@ -2383,10 +2383,11 @@ int __genphy_config_aneg(struct phy_device *phydev, bool changed)
 	} else {
 		linkmode_zero(fixed_advert);
 
-		set = phy_lookup_setting(phydev->speed, phydev->duplex,
-					 phydev->supported, true);
-		if (set)
-			linkmode_set_bit(set->bit, fixed_advert);
+		c = phy_caps_lookup(phydev->speed, phydev->duplex,
+				    phydev->supported, true);
+		if (c)
+			linkmode_and(fixed_advert, phydev->supported,
+				     c->linkmodes);
 
 		advert = fixed_advert;
 	}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:18 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:18 +0100
Subject: [PATCH net-next v4 12/13] net: phylink: Convert capabilities to linkmodes using phy_caps
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-13-maxime.chevallier@bootlin.com>

phylink_caps_to_linkmodes() is used to derive a list of linkmodes that
can be conceivably exposed using a given set of speeds and duplex
through phylink's MAC capabilities.

This list can be derived from the link_caps array in phy_caps, provided
we convert the MAC capabilities into a LINK_CAPA bitmask first.

Introduce an internal phylink helper phylink_caps_to_link_caps() to
convert from MAC capabilities into phy_caps, then  phy_caps_linkmodes()
to do the link_caps -> linkmodes conversion.

This avoids having to update phylink for every new linkmode.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phy-caps.h |   1 +
 drivers/net/phy/phy_caps.c |  14 ++++
 drivers/net/phy/phylink.c  | 155 +++++--------------------------------
 3 files changed, 36 insertions(+), 134 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 8ae8dc42494f..db53f380392e 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -44,6 +44,7 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
+void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes);
 
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 8b90fb6d6b15..0a64289a161b 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -239,3 +239,17 @@ bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
 
 	return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
 }
+
+/**
+ * phy_caps_linkmodes() - Convert a bitfield of capabilities into linkmodes
+ * @caps: The list of caps, each bit corresponding to a LINK_CAPA value
+ * @linkmodes: The set of linkmodes to fill. Must be previously initialized.
+ */
+void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
+{
+	unsigned long capa;
+
+	for_each_set_bit(capa, &caps, __LINK_CAPA_MAX)
+		linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
+}
+EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 9cb3beec9f47..30f0ecb084ef 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -317,6 +317,24 @@ static struct {
 	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF, BIT(LINK_CAPA_10HD) },
 };
 
+/**
+ * phylink_caps_to_link_caps() - Convert a set of MAC capabilities LINK caps
+ * @caps: A set of MAC capabilities
+ *
+ * Returns: The corresponding set of LINK_CAPA as defined in phy-caps.h
+ */
+static unsigned long phylink_caps_to_link_caps(unsigned long caps)
+{
+	unsigned long link_caps = 0;
+	int i;
+
+	for (i = 0; i <  ARRAY_SIZE(phylink_caps_params); i++)
+		if (caps & phylink_caps_params[i].mask)
+			link_caps |= phylink_caps_params[i].caps_bit;
+
+	return link_caps;
+}
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -328,146 +346,15 @@ static struct {
 static void phylink_caps_to_linkmodes(unsigned long *linkmodes,
 				      unsigned long caps)
 {
+	unsigned long link_caps = phylink_caps_to_link_caps(caps);
+
 	if (caps & MAC_SYM_PAUSE)
 		__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes);
 
 	if (caps & MAC_ASYM_PAUSE)
 		__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes);
 
-	if (caps & MAC_10HD) {
-		__set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT, linkmodes);
-	}
-
-	if (caps & MAC_10FD) {
-		__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100HD) {
-		__set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100FD) {
-		__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_1000HD)
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, linkmodes);
-
-	if (caps & MAC_1000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_2500FD) {
-		__set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_5000FD)
-		__set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, linkmodes);
-
-	if (caps & MAC_10000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_25000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_40000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_50000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_56000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseDR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_200000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_400000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, linkmodes);
-	}
+	phy_caps_linkmodes(link_caps, linkmodes);
 }
 
 /**
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar  3 01:03:19 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon,  3 Mar 2025 10:03:19 +0100
Subject: [PATCH net-next v4 13/13] net: phy: phy_caps: Allow getting an phy_interface's capabilities
In-Reply-To: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303090321.805785-14-maxime.chevallier@bootlin.com>

Phylink has internal code to get the MAC capabilities of a given PHY
interface (what are the supported speed and duplex).

Extract that into phy_caps, but use the link_capa for conversion. Add an
internal phylink helper for the link caps -> mac caps conversion, and
use this in phylink_caps_to_linkmodes().

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: No changes

 drivers/net/phy/phy-caps.h |  4 ++
 drivers/net/phy/phy_caps.c | 92 ++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phylink.c  | 90 ++++++-------------------------------
 3 files changed, 110 insertions(+), 76 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index db53f380392e..e1fe19d11e5f 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -8,6 +8,7 @@
 #define __PHY_CAPS_H
 
 #include <linux/ethtool.h>
+#include <linux/phy.h>
 
 enum {
 	LINK_CAPA_10HD = 0,
@@ -32,6 +33,8 @@ enum {
 	__LINK_CAPA_MAX,
 };
 
+#define LINK_CAPA_ALL	GENMASK((__LINK_CAPA_MAX - 1), 0)
+
 struct link_capabilities {
 	int speed;
 	unsigned int duplex;
@@ -45,6 +48,7 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes);
+unsigned long phy_caps_from_interface(phy_interface_t interface);
 
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 0a64289a161b..555daaa41d52 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -253,3 +253,95 @@ void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
 		linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
 }
 EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
+
+/**
+ * phy_caps_from_interface() - Get the link capa from a given PHY interface
+ * @interface: The PHY interface we want to get the possible Speed/Duplex from
+ *
+ * Returns: A bitmask of LINK_CAPA_xxx values that can be achieved with the
+ *          provided interface.
+ */
+unsigned long phy_caps_from_interface(phy_interface_t interface)
+{
+	unsigned long link_caps = 0;
+
+	switch (interface) {
+	case PHY_INTERFACE_MODE_USXGMII:
+		link_caps |= BIT(LINK_CAPA_10000FD) | BIT(LINK_CAPA_5000FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_10G_QXGMII:
+		link_caps |= BIT(LINK_CAPA_2500FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+	case PHY_INTERFACE_MODE_QUSGMII:
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_GMII:
+		link_caps |= BIT(LINK_CAPA_1000HD) | BIT(LINK_CAPA_1000FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_REVRMII:
+	case PHY_INTERFACE_MODE_RMII:
+	case PHY_INTERFACE_MODE_SMII:
+	case PHY_INTERFACE_MODE_REVMII:
+	case PHY_INTERFACE_MODE_MII:
+		link_caps |= BIT(LINK_CAPA_10HD) | BIT(LINK_CAPA_10FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_100BASEX:
+		link_caps |= BIT(LINK_CAPA_100HD) | BIT(LINK_CAPA_100FD);
+		break;
+
+	case PHY_INTERFACE_MODE_TBI:
+	case PHY_INTERFACE_MODE_MOCA:
+	case PHY_INTERFACE_MODE_RTBI:
+	case PHY_INTERFACE_MODE_1000BASEX:
+		link_caps |= BIT(LINK_CAPA_1000HD);
+		fallthrough;
+	case PHY_INTERFACE_MODE_1000BASEKX:
+	case PHY_INTERFACE_MODE_TRGMII:
+		link_caps |= BIT(LINK_CAPA_1000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_2500BASEX:
+		link_caps |= BIT(LINK_CAPA_2500FD);
+		break;
+
+	case PHY_INTERFACE_MODE_5GBASER:
+		link_caps |= BIT(LINK_CAPA_5000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_XGMII:
+	case PHY_INTERFACE_MODE_RXAUI:
+	case PHY_INTERFACE_MODE_XAUI:
+	case PHY_INTERFACE_MODE_10GBASER:
+	case PHY_INTERFACE_MODE_10GKR:
+		link_caps |= BIT(LINK_CAPA_10000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_25GBASER:
+		link_caps |= BIT(LINK_CAPA_25000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_XLGMII:
+		link_caps |= BIT(LINK_CAPA_40000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_INTERNAL:
+		link_caps |= LINK_CAPA_ALL;
+		break;
+
+	case PHY_INTERFACE_MODE_NA:
+	case PHY_INTERFACE_MODE_MAX:
+		break;
+	}
+
+	return link_caps;
+}
+EXPORT_SYMBOL_GPL(phy_caps_from_interface);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 30f0ecb084ef..0162ce09f54d 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -335,6 +335,18 @@ static unsigned long phylink_caps_to_link_caps(unsigned long caps)
 	return link_caps;
 }
 
+static unsigned long phylink_link_caps_to_mac_caps(unsigned long link_caps)
+{
+	unsigned long caps = 0;
+	int i;
+
+	for (i = 0; i <  ARRAY_SIZE(phylink_caps_params); i++)
+		if (link_caps & phylink_caps_params[i].caps_bit)
+			caps |= phylink_caps_params[i].mask;
+
+	return caps;
+}
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -412,86 +424,12 @@ static unsigned long phylink_get_capabilities(phy_interface_t interface,
 					      unsigned long mac_capabilities,
 					      int rate_matching)
 {
+	unsigned long link_caps = phy_caps_from_interface(interface);
 	int max_speed = phylink_interface_max_speed(interface);
 	unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
 	unsigned long matched_caps = 0;
 
-	switch (interface) {
-	case PHY_INTERFACE_MODE_USXGMII:
-		caps |= MAC_10000FD | MAC_5000FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_10G_QXGMII:
-		caps |= MAC_2500FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_PSGMII:
-	case PHY_INTERFACE_MODE_QSGMII:
-	case PHY_INTERFACE_MODE_QUSGMII:
-	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_GMII:
-		caps |= MAC_1000HD | MAC_1000FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_REVRMII:
-	case PHY_INTERFACE_MODE_RMII:
-	case PHY_INTERFACE_MODE_SMII:
-	case PHY_INTERFACE_MODE_REVMII:
-	case PHY_INTERFACE_MODE_MII:
-		caps |= MAC_10HD | MAC_10FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_100BASEX:
-		caps |= MAC_100HD | MAC_100FD;
-		break;
-
-	case PHY_INTERFACE_MODE_TBI:
-	case PHY_INTERFACE_MODE_MOCA:
-	case PHY_INTERFACE_MODE_RTBI:
-	case PHY_INTERFACE_MODE_1000BASEX:
-		caps |= MAC_1000HD;
-		fallthrough;
-	case PHY_INTERFACE_MODE_1000BASEKX:
-	case PHY_INTERFACE_MODE_TRGMII:
-		caps |= MAC_1000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_2500BASEX:
-		caps |= MAC_2500FD;
-		break;
-
-	case PHY_INTERFACE_MODE_5GBASER:
-		caps |= MAC_5000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_XGMII:
-	case PHY_INTERFACE_MODE_RXAUI:
-	case PHY_INTERFACE_MODE_XAUI:
-	case PHY_INTERFACE_MODE_10GBASER:
-	case PHY_INTERFACE_MODE_10GKR:
-		caps |= MAC_10000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_25GBASER:
-		caps |= MAC_25000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_XLGMII:
-		caps |= MAC_40000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_INTERNAL:
-		caps |= ~0;
-		break;
-
-	case PHY_INTERFACE_MODE_NA:
-	case PHY_INTERFACE_MODE_MAX:
-		break;
-	}
+	caps |= phylink_link_caps_to_mac_caps(link_caps);
 
 	switch (rate_matching) {
 	case RATE_MATCH_OPEN_LOOP:
-- 
2.48.1



From peterz at infradead.org  Mon Mar  3 01:18:11 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 3 Mar 2025 10:18:11 +0100
Subject: [PATCH bpf-next v3 1/4] x86/ibt: factor out cfi and fineibt
 offset
In-Reply-To: <20250303065345.229298-2-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
 <20250303065345.229298-2-dongml2@chinatelecom.cn>
Message-ID: <20250303091811.GH5880@noisy.programming.kicks-ass.net>

On Mon, Mar 03, 2025 at 02:53:42PM +0800, Menglong Dong wrote:
> index c71b575bf229..ad050d09cb2b 100644
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -908,7 +908,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end, struct mod
>  
>  		poison_endbr(addr, wr_addr, true);
>  		if (IS_ENABLED(CONFIG_FINEIBT))
> -			poison_cfi(addr - 16, wr_addr - 16);
> +			poison_cfi(addr, wr_addr);
>  	}
>  }

If you're touching this code, please use tip/x86/core or tip/master.


From quentin.schulz at cherry.de  Mon Mar  3 01:27:31 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Mon, 3 Mar 2025 10:27:31 +0100
Subject: [PATCH v2 2/2] phy: rockchip: usbdp: re-init the phy on
 orientation-change
In-Reply-To: <dkjpudmzuuxvaotz4mx46yx7iacof7q6ck746j3rrqvlgbq3hk@6vtvy3gy3kff>
References: <20250226103810.3746018-1-heiko@sntech.de>
 <20250226103810.3746018-3-heiko@sntech.de>
 <02757b21-7599-4ee7-9f97-247b04ba646a@cherry.de>
 <dkjpudmzuuxvaotz4mx46yx7iacof7q6ck746j3rrqvlgbq3hk@6vtvy3gy3kff>
Message-ID: <2af85aa0-96dc-43ea-9542-88f91b21a028@cherry.de>

Hi Sebastian,

On 3/1/25 10:19 PM, Sebastian Reichel wrote:
> Hello Quentin,
> 
> On Wed, Feb 26, 2025 at 01:38:10PM +0100, Quentin Schulz wrote:
>> Unrelated to this patch (but may be triggered by this patch?), I'm wondering
>> how flip is really handled.
>>
>> It seems like we have flip store the orientation of the cable, but also if
>> rockchip,dp-lane-mux is set to <0 1>. But wouldn't that break if we ignore
>> that initial flipped lane-mux whenever a USB-C cable is inserted in reverse?
>> Basically, shouldn't a reserve orientation of the cable when
>> rockchip,dp-lane-mux is set to <0 1> mean "normal mux"?
> 
> If a USB-C connector is involved, the TypeC controller is supposed to
> setup the lane muxing based on the connector orientation. This
> happens via the typec API and in this hardware setup the PHY should
> not have the rockchip,dp-lane-mux DT property set.
> 

I could see some HW routing "mistake" where the USB-C connector in 
normal orientation has DP lanes routed to RX1/TX1? Or is this expected 
to just be faulty HW we shouldn't attempt at supporting?

> The rockchip,dp-lane-mux property is required if no USB-C connector
> is involved. For example if the lanes are routed to a Displayport
> connector. In that case the lane setup is fixed in hardware and
> there is no TypeC controller involved, which could do any setup ;)
> 

Yup I've seen that for the Rock 5 ITX and the evaluation board(s) do 
this. Quite interesting :)

Cheers,
Quentin


From quic_zhenhuah at quicinc.com  Mon Mar  3 01:29:55 2025
From: quic_zhenhuah at quicinc.com (Zhenhua Huang)
Date: Mon, 3 Mar 2025 17:29:55 +0800
Subject: [PATCH v7] arm64: mm: Populate vmemmap at the page level if not
 section aligned
In-Reply-To: <00c82c92-35a0-441c-b5b5-e4a6c8a4a9b7@redhat.com>
References: <20250217092907.3474806-1-quic_zhenhuah@quicinc.com>
 <8c1578ed-cfef-4fba-a334-ebf5eac26d60@redhat.com>
 <ce2bd045-3e3a-42bf-9a48-9ad806ff3765@quicinc.com>
 <871c0dae-c419-4ac2-9472-6901aab90dcf@redhat.com>
 <a5439884-551c-4104-9175-f95b0895a489@quicinc.com>
 <00c82c92-35a0-441c-b5b5-e4a6c8a4a9b7@redhat.com>
Message-ID: <45076e28-dd70-456f-83b2-7b4d532c455c@quicinc.com>



On 2025/2/27 1:13, David Hildenbrand wrote:
> Sorry, I somehow missed this mail.
> 

No problem. Thanks for your reply.

>>>> Hi David,
>>>>
>>>> I had the same doubt initially.
>>>> After going through the codes, I noticed for vmemmap_populate(), the
>>>> arguments "start" and "end" passed down should already be within one
>>>> section.
>>>> early path:
>>>> for_each_present_section_nr
>>>> ?????__populate_section_memmap
>>>> ???????? ..
>>>> ???????? vmemmap_populate()
>>>>
>>>> hotplug path:
>>>> __add_pages
>>>> ?????section_activate
>>>> ???????? vmemmap_populate()
>>>>
>>>> Therefore.. focusing only on the size seems OK to me, and fall back
>>>> solution below appears unnecessary?
>>>
>>> Ah, in that case it is fine. Might make sense to document/enforce that
>>> somehow for the time being ...
>>
>> Shall I document and WARN_ON if the size exceeds? like:
>> WARN_ON(end - start > PAGES_PER_SECTION * sizeof(struct page))
> 
> Probably WARN_ON_ONCE() along with a comment that we should never exceed 
> a single memory section.

Got it.

> 
>>
>> Since vmemmap_populate() is implemented per architecture, the change
>> should apply for other architectures as well. However I have no setup to
>> test it on...
>> Therefore, May I implement it only for arm64 now ?
> 
> Would work for me; better than no warning.

I made one patch several days ago, could you please help review once? 
https://lore.kernel.org/linux-mm/20250219084001.1272445-1-quic_zhenhuah at quicinc.com/T/
Is there anything else you would suggest besides preferring WARN_ON_ONCE() ?

> 
>> Additionally, from previous discussion, the change is worth
>> backporting(apologies for missing to CC stable kernel in this version).
>> Keeping it for arm64 should simplify for backporting. WDYT?
> 
> Jup. Of course, we could add a generic warning in a separate patch.
> 
>>
>>>
>>>
>>>>> +/*
>>>>> + * Try to populate PMDs, but fallback to populating base pages when
>>>>> ranges
>>>>> + * would only partially cover a PMD.
>>>>> + */
>>>>> ?? ?int __meminit vmemmap_populate_hugepages(unsigned long start,
>>>>> unsigned
>>>>> long end,
>>>>> ?? ???????????????????????????????????????? int node, struct 
>>>>> vmem_altmap
>>>>> *altmap)
>>>>> ?? ?{
>>>>> @@ -313,6 +317,9 @@ int __meminit vmemmap_populate_hugepages(unsigned
>>>>> long start, unsigned long end,
>>>>> ?? ??????? for (addr = start; addr < end; addr = next) {
>>>>
>>>> This for loop appears to be redundant for arm64 as well, as above
>>>> mentioned, a single call to pmd_addr_end() should suffice.
>>>
>>> Right, that was what was confusing me in the first place.
>>>
>>>>
>>>>> ?? ??????????????? next = pmd_addr_end(addr, end);
>>>>>
>>>>> +?????????????? if (!IS_ALIGNED(addr, PMD_SIZE) || !IS_ALIGNED(next,
>>>>> PMD_SIZE))
>>>>> +?????????????????????? goto fallback;
>>>>> +
>>>>> ?? ??????????????? pgd = vmemmap_pgd_populate(addr, node);
>>>>> ?? ??????????????? if (!pgd)
>>>>> ?? ??????????????????????? return -ENOMEM;
>>>>> @@ -346,6 +353,7 @@ int __meminit vmemmap_populate_hugepages(unsigned
>>>>> long start, unsigned long end,
>>>>> ?? ??????????????????????? }
>>>>> ?? ??????????????? } else if (vmemmap_check_pmd(pmd, node, addr, 
>>>>> next))
>>>>> ?? ??????????????????????? continue;
>>>>> +fallback:
>>>>> ?? ??????????????? if (vmemmap_populate_basepages(addr, next, node,
>>>>> altmap))
>>>>> ?? ??????????????????????? return -ENOMEM;
>>>>
>>>> It seems we have no chance to call populate_basepages here?
>>>
>>>
>>> Can you elaborate?
>>
>> It's invoked within vmemmap_populate_hugepages(), which is called by
>> vmemmap_populate(). This implies that we are always performing a whole
>> section hotplug?
> 
> Ah, you meant only in the context of this change, yes. I was confused, 
> because there are other reasons why we run into that fallback (failing 
> to allocate a PMD).

I observed that this logic was introduced in 
2045a3b8911b("mm/sparse-vmemmap: generalise 
vmemmap_populate_hugepages()") which moved from arch-dependent 
codes(such as vmemmap_set_pmd() in arch/loongarch/mm/init.c or 
arch/x86/mm/init_64.c) to common arch-independent code(function 
vmemmap_populate_hugepages).

I suspect it might be causing the confusion, as it may not be fully 
compatible with arm64. However, it does not seem to cause any bugs :)

> 



From eichest at gmail.com  Mon Mar  3 01:30:51 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Mon, 3 Mar 2025 10:30:51 +0100
Subject: [PATCH v1 1/2] phy: freescale: imx8m-pcie: cleanup reset logic
In-Reply-To: <c965906ea8797385399534e974cabdba5564ae0f.camel@pengutronix.de>
References: <20250228103959.47419-1-eichest@gmail.com>
 <20250228103959.47419-2-eichest@gmail.com>
 <c965906ea8797385399534e974cabdba5564ae0f.camel@pengutronix.de>
Message-ID: <Z8V2yzfYGirBFi1u@eichest-laptop>

Hi Philipp,

On Fri, Feb 28, 2025 at 01:38:11PM +0100, Philipp Zabel wrote:
> On Fr, 2025-02-28 at 11:38 +0100, Stefan Eichenberger wrote:
> > From: Stefan Eichenberger <stefan.eichenberger at toradex.com>
> > 
> > Remove the switch statement and base perst release on whether it is
> > found in the device tree. The probe function fails without the reset
> > property, making it mandatory. Therefore, always release reset
> > independent of the variant.
> > 
> > This does not change the behavior of the driver but reduces driver
> > complexity and allows for easier future modifications.
> > 
> > Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
> > ---
> >  drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 12 ++++--------
> >  1 file changed, 4 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> > index e98361dcdeadf..00f957a42d9dc 100644
> > --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> > +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> > @@ -141,15 +141,11 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
> >  			   IMX8MM_GPR_PCIE_REF_CLK_PLL);
> >  	usleep_range(100, 200);
> >  
> > -	switch (imx8_phy->drvdata->variant) {
> > -	case IMX8MP:
> > +	if (imx8_phy->perst)
> 
> This check is not necessary, reset_control_deassert(NULL) is a no-op:
> 

Thanks for the feedback, I will remove the check in the next version.

Regards,
Stefan


From leo.yan at arm.com  Mon Mar  3 01:38:53 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 3 Mar 2025 09:38:53 +0000
Subject: [PATCH v3 00/12] perf script: Refactor branch flags for Arm SPE
In-Reply-To: <20250217195908.176207-1-leo.yan@arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
Message-ID: <20250303093853.GG2157064@e132581.arm.com>

Hi Arnaldo, Namhyung,

On Mon, Feb 17, 2025 at 07:58:56PM +0000, Leo Yan wrote:
> This patch series refactors branch flags for support Arm SPE.  The patch
> set is divided into two parts, the first part is for refactoring common
> code and the second part is for enabling Arm SPE.

James has given review tags (including the new added patch 06).  Could
you kindly pick up this series?

Sorry for pushing a bit, as we have dependency on it.

Thanks,
Leo


From miko.lenczewski at arm.com  Mon Mar  3 01:40:34 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 09:40:34 +0000
Subject: [PATCH v2 1/4] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <223a817b-66dd-4182-838f-a186b059fe41@os.amperecomputing.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-3-miko.lenczewski@arm.com>
 <c572a93f-0899-4fc7-9764-d3e76e9fe6d1@os.amperecomputing.com>
 <223a817b-66dd-4182-838f-a186b059fe41@os.amperecomputing.com>
Message-ID: <20250303094022.GA13345@e133081.arm.com>

On Fri, Feb 28, 2025 at 06:45:38PM -0800, Yang Shi wrote:
> 
> 
> 
> On 2/28/25 5:29 PM, Yang Shi wrote:
> > 
> > 
> > 
> > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > > index 940343beb3d4..baae6d458996 100644
> > > --- a/arch/arm64/Kconfig
> > > +++ b/arch/arm64/Kconfig
> > > @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
> > > ??????? The feature introduces new assembly instructions, and they were
> > > ??????? support when binutils >= 2.30.
> > > ? +config ARM64_ENABLE_BBML2_NOABORT
> > > +??? bool "Enable support for Break-Before-Make Level 2 detection
> > > and usage"
> > > +??? default y
> > > +??? help
> > > +????? FEAT_BBM provides detection of support levels for
> > > break-before-make
> > > +????? sequences. If BBM level 2 is supported, some TLB maintenance
> > > requirements
> > > +????? can be relaxed to improve performance. We additonally require the
> > > +????? property that the implementation cannot ever raise TLB
> > > Conflict Aborts.
> > > +????? Selecting N causes the kernel to fallback to BBM level 0
> > > behaviour
> > > +????? even if the system supports BBM level 2.
> > > +
> > > ? endmenu # "ARMv8.4 architectural features"
> > > ? ? menu "ARMv8.5 architectural features"
> > > diff --git a/arch/arm64/include/asm/cpucaps.h
> > > b/arch/arm64/include/asm/cpucaps.h
> > > index 0b5ca6e0eb09..2d6db33d4e45 100644
> > > --- a/arch/arm64/include/asm/cpucaps.h
> > > +++ b/arch/arm64/include/asm/cpucaps.h
> > > @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
> > > ????????? return IS_ENABLED(CONFIG_ARM64_PAN);
> > > ????? case ARM64_HAS_EPAN:
> > > ????????? return IS_ENABLED(CONFIG_ARM64_EPAN);
> > > +??? case ARM64_HAS_BBML2_NOABORT:
> > > +??????? return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
> > > ????? case ARM64_SVE:
> > > ????????? return IS_ENABLED(CONFIG_ARM64_SVE);
> > > ????? case ARM64_SME:
> > > diff --git a/arch/arm64/include/asm/cpufeature.h
> > > b/arch/arm64/include/asm/cpufeature.h
> > > index e0e4478f5fb5..108ef3fbbc00 100644
> > > --- a/arch/arm64/include/asm/cpufeature.h
> > > +++ b/arch/arm64/include/asm/cpufeature.h
> > > @@ -866,6 +866,11 @@ static __always_inline bool
> > > system_supports_mpam_hcr(void)
> > > ????? return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
> > > ? }
> > > ? +static inline bool system_supports_bbml2_noabort(void)
> > > +{
> > > +??? return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
> > > +}
> > 
> > Hi Miko,
> > 
> > I added AmpereOne mdir on top of this patch. I can see BBML2 feature is
> > detected via dmesg. But system_supports_bbml2_noabort() returns false.
> > The warning in the below debug patch is triggered:
> > 
> > diff --git a/arch/arm64/kernel/cpufeature.c
> > b/arch/arm64/kernel/cpufeature.c
> > index faa9094d97dd..a70829ae2bd0 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -3814,6 +3814,9 @@ void __init setup_system_features(void)
> > ?{
> > ??????? setup_system_capabilities();
> > 
> > +?????? if (!system_supports_bbml2_noabort())
> > +?????????????? WARN_ON_ONCE(1);
> > +
> > ??????? kpti_install_ng_mappings();
> > 
> > ??????? sve_setup();
> > 
> > I thought it may be too early. But it seems other system features work
> > well, for example, MPAM. I didn't figure out why. It is weird.
> 
> I just figured out the problem It is because the wrong kconfig name is used
> in cpucaps.h. The code is:
> 
> +??? case ARM64_HAS_BBML2_NOABORT:
> +??????? return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
> 
> But the kconfig name actually is:
> 
> +config ARM64_ENABLE_BBML2_NOABORT
> 
> IMHO, the "ENABLE" in kconfig name sounds unnecessary.
> 
> Thanks,
> Yang
> 
> 

Hi Yang,

Thank you for the review, and apologies for the slight delay.

Thanks again for the spot, I agree that `ENABLE` is probably redundant
(and clearly, caused an issue here). Will remove this. Please let me
know if there are any other issues with rebasing your patches on top of
mine.

-- 
Kind regards,
Miko?aj Lenczewski


From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar  3 01:06:05 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 03 Mar 2025 17:06:05 +0800
Subject: [PATCH] pmdomain: amlogic: fix T7 ISP secpower
Message-ID: <20250303-fix-t7-pwrc-v1-1-b563612bcd86@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

ISP and MIPI_ISP, these two have a parent-child relationship,
ISP depends on MIPI_ISP.

Fixes: ca75e4b214c6 ("pmdomain: amlogic: Add support for T7 power domains controller")
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/pmdomain/amlogic/meson-secure-pwrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
index 42ce41a2fe3a..ff76ea36835e 100644
--- a/drivers/pmdomain/amlogic/meson-secure-pwrc.c
+++ b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
@@ -221,7 +221,7 @@ static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
 	SEC_PD(T7_VI_CLK2,	0),
 	/* ETH is for ethernet online wakeup, and should be always on */
 	SEC_PD(T7_ETH,		GENPD_FLAG_ALWAYS_ON),
-	SEC_PD(T7_ISP,		0),
+	TOP_PD(T7_ISP,		0, PWRC_T7_MIPI_ISP_ID),
 	SEC_PD(T7_MIPI_ISP,	0),
 	TOP_PD(T7_GDC,		0, PWRC_T7_NIC3_ID),
 	TOP_PD(T7_DEWARP,	0, PWRC_T7_NIC3_ID),

---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20250303-fix-t7-pwrc-f33650b190ef

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From krzysztof.kozlowski at linaro.org  Mon Mar  3 01:08:47 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon,  3 Mar 2025 10:08:47 +0100
Subject: [PATCH v3 0/3] Introduce pin controller support for Exynos7870
In-Reply-To: <20250301-exynos7870-pinctrl-v3-0-ba1da9d3cd2f@disroot.org>
References: <20250301-exynos7870-pinctrl-v3-0-ba1da9d3cd2f@disroot.org>
Message-ID: <174099291728.28792.4499836839323841404.b4-ty@linaro.org>


On Sat, 01 Mar 2025 01:05:16 +0530, Kaustabh Chakraborty wrote:
> Add support for exynos7870 in the pinctrl driver. Also, document the
> ALIVE pin controller's wakeup interrupt compatible.
> 
> This patch series is a part of Exynos7870 upstreaming.
> 
> 

Applied, thanks!

[1/3] dt-bindings: pinctrl: samsung: add exynos7870-pinctrl compatible
      https://git.kernel.org/pinctrl/samsung/c/129bdbd05650f4c11fb8995f8b6e63589ce4cb33
[2/3] dt-bindings: pinctrl: samsung: add exynos7870-wakeup-eint compatible
      https://git.kernel.org/pinctrl/samsung/c/c1ab2297bc746b07b96205dddc45979feac22f4d
[3/3] pinctrl: samsung: add support for exynos7870 pinctrl
      https://git.kernel.org/pinctrl/samsung/c/eb76dc973cef741f74ce17d3bba8a7c9f2cc6113

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


From vdonnefort at google.com  Mon Mar  3 01:08:50 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Mon, 3 Mar 2025 09:08:50 +0000
Subject: [PATCH 1/9] KVM: arm64: Handle huge mappings for np-guest CMOs
In-Reply-To: <Z8IGcA6h6hZx7ujh@google.com>
References: <20250228102530.1229089-1-vdonnefort@google.com>
 <20250228102530.1229089-2-vdonnefort@google.com>
 <Z8IGcA6h6hZx7ujh@google.com>
Message-ID: <Z8VxotNAW9CLogum@google.com>

On Fri, Feb 28, 2025 at 06:54:40PM +0000, Quentin Perret wrote:
> On Friday 28 Feb 2025 at 10:25:17 (+0000), Vincent Donnefort wrote:
> > diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > index 19c3c631708c..a796e257c41f 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > @@ -219,14 +219,24 @@ static void guest_s2_put_page(void *addr)
> >  
> >  static void clean_dcache_guest_page(void *va, size_t size)
> >  {
> > -	__clean_dcache_guest_page(hyp_fixmap_map(__hyp_pa(va)), size);
> > -	hyp_fixmap_unmap();
> > +	while (size) {
> 
> Nit: not a problem at the moment, but this makes me mildly worried if
> size ever became non-page-aligned, could we make the code robust to
> that?

The fixmap doesn't handle !ALIGNED adresses. (I have a patch in the tracing
series to cover that though). So wonder if that really makes sense to handle
unaligned size while it wouldn't work with unaligned va anyway?

Perhaps just a WARN_ON() then?

> 
> > +		__clean_dcache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
> > +					  PAGE_SIZE);
> > +		hyp_fixmap_unmap();
> > +		va += PAGE_SIZE;
> > +		size -= PAGE_SIZE;
> > +	}
> >  }
> >  
> >  static void invalidate_icache_guest_page(void *va, size_t size)
> >  {
> > -	__invalidate_icache_guest_page(hyp_fixmap_map(__hyp_pa(va)), size);
> > -	hyp_fixmap_unmap();
> > +	while (size) {
> > +		__invalidate_icache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
> > +					       PAGE_SIZE);
> > +		hyp_fixmap_unmap();
> > +		va += PAGE_SIZE;
> > +		size -= PAGE_SIZE;
> > +	}
> >  }
> >  
> >  int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
> > -- 
> > 2.48.1.711.g2feabab25a-goog
> > 


From david at redhat.com  Mon Mar  3 01:14:21 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 10:14:21 +0100
Subject: [PATCH v2 0/4] Initial BBML2 support for contpte_convert()
In-Reply-To: <20250228182403.6269-2-miko.lenczewski@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
Message-ID: <8609f693-0786-40bd-9136-3a8f9ee9304b@redhat.com>

On 28.02.25 19:24, Miko?aj Lenczewski wrote:
> Hi All,
> 
> This patch series adds adding initial support for eliding
> break-before-make requirements on systems that support BBML2 and
> additionally guarantee to never raise a conflict abort.
> 
> This support reorders and optionally elides a TLB invalidation in
> contpte_convert(). The elision of said invalidation leads to a 12%
> improvement when executing a microbenchmark designed to force the
> pathological path where contpte_convert() gets called. This
> represents an 80% reduction in the cost of calling contpte_convert().

Just a general comment: Nice! :)

-- 
Cheers,

David / dhildenb



From david at redhat.com  Mon Mar  3 01:17:12 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 10:17:12 +0100
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <20250228182403.6269-5-miko.lenczewski@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
Message-ID: <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>

On 28.02.25 19:24, Miko?aj Lenczewski wrote:
> If we support bbml2 without conflict aborts, we can avoid the final
> flush and have hardware manage the tlb entries for us. Avoiding flushes
> is a win.
> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
> ---
>   arch/arm64/mm/contpte.c | 3 ---
>   1 file changed, 3 deletions(-)
> 
> diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
> index 145530f706a9..77ed03b30b72 100644
> --- a/arch/arm64/mm/contpte.c
> +++ b/arch/arm64/mm/contpte.c
> @@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
>   		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>   
>   	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
> -
> -	if (system_supports_bbml2_noabort())
> -		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>   }
>   
>   void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,

What's the point of not squashing this into #2? :)

If this split was requested during earlier review, at least seeing patch 
#2 on its own confused me.

-- 
Cheers,

David / dhildenb



From u.kleine-koenig at baylibre.com  Mon Mar  3 01:43:07 2025
From: u.kleine-koenig at baylibre.com (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 3 Mar 2025 10:43:07 +0100
Subject: [PATCH] pwm: stmpe: Allow to compile as a module
In-Reply-To: <20250215143723.636591-2-u.kleine-koenig@baylibre.com>
References: <20250215143723.636591-2-u.kleine-koenig@baylibre.com>
Message-ID: <miozabyaeoagqrw7evl4c44augcfbrdtupf4ium62xz5kb77cm@vndlz2rcoyj4>

Hello,

On Sat, Feb 15, 2025 at 03:37:22PM +0100, Uwe Kleine-K?nig wrote:
> pwm-stmpe is the only driver that cannot be built as a module. Add the
> necessary boilerplate to also make this driver modular.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at baylibre.com>

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/for-next

.

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/0d9fe705/attachment.sig>

From miko.lenczewski at arm.com  Mon Mar  3 01:49:47 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 09:49:47 +0000
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
 <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
Message-ID: <20250303094947.GB13345@e133081.arm.com>

Hi David,

Thanks for taking the time to review.

On Mon, Mar 03, 2025 at 10:17:12AM +0100, David Hildenbrand wrote:
> On 28.02.25 19:24, Miko?aj Lenczewski wrote:
> > If we support bbml2 without conflict aborts, we can avoid the final
> > flush and have hardware manage the tlb entries for us. Avoiding flushes
> > is a win.
> > 
> > Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> > Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
> > ---
> >   arch/arm64/mm/contpte.c | 3 ---
> >   1 file changed, 3 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
> > index 145530f706a9..77ed03b30b72 100644
> > --- a/arch/arm64/mm/contpte.c
> > +++ b/arch/arm64/mm/contpte.c
> > @@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
> >   		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
> >   	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
> > -
> > -	if (system_supports_bbml2_noabort())
> > -		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
> >   }
> >   void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
> 
> What's the point of not squashing this into #2? :)
> 
> If this split was requested during earlier review, at least seeing patch #2
> on its own confused me.

This split is a holdover from an earlier patchset, where it was still
unknown whether the removal of the second flush was permitted with
BBML2. Partly this was due to us being worried about conflict aborts
after the removal, and partly this was because the "delay" is a separate
optimisation that we could apply even if it turned out the final patch
was not architecturally sound.

Now that we do not handle conflict aborts (preferring only systems that
handle BBML2 without ever raising aborts), the first issue is not a
problem. The reasoning behind the second patch is also a little bit
outdated, but I can see the logical split between a tlbi reorder, and
the removal of the tlbi. If this is truly redundant though, I would be
happy to squash the two into a single patch.

-- 
Kind regards,
Miko?aj Lenczewski


From vdonnefort at google.com  Mon Mar  3 01:47:48 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Mon, 3 Mar 2025 09:47:48 +0000
Subject: [PATCH 4/6] KVM: arm64: Move hyp state to hyp_vmemmap
In-Reply-To: <20250227003310.367350-5-qperret@google.com>
References: <20250227003310.367350-1-qperret@google.com>
 <20250227003310.367350-5-qperret@google.com>
Message-ID: <Z8V6xOVCPp7OOX6g@google.com>

[...]

> diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
> index 1a414288fe8c..955c431af5d0 100644
> --- a/arch/arm64/kvm/hyp/nvhe/setup.c
> +++ b/arch/arm64/kvm/hyp/nvhe/setup.c
> @@ -194,16 +194,20 @@ static int fix_host_ownership_walker(const struct kvm_pgtable_visit_ctx *ctx,
>  
>  	/*
>  	 * Adjust the host stage-2 mappings to match the ownership attributes
> -	 * configured in the hypervisor stage-1.
> +	 * configured in the hypervisor stage-1, and make sure to propagate them
> +	 * to the hyp_vmemmap state.
>  	 */
>  	state = pkvm_getstate(kvm_pgtable_hyp_pte_prot(ctx->old));
>  	switch (state) {
>  	case PKVM_PAGE_OWNED:
> +		set_hyp_state(phys, PKVM_PAGE_OWNED);
>  		return host_stage2_set_owner_locked(phys, PAGE_SIZE, PKVM_ID_HYP);
>  	case PKVM_PAGE_SHARED_OWNED:
> +		set_hyp_state(phys, PKVM_PAGE_SHARED_OWNED);
>  		set_host_state(phys, PKVM_PAGE_SHARED_BORROWED);
>  		break;
>  	case PKVM_PAGE_SHARED_BORROWED:
> +		set_hyp_state(phys, PKVM_PAGE_SHARED_BORROWED);
>  		set_host_state(phys, PKVM_PAGE_SHARED_OWNED);
>  		break;
>  	default:

Are the SHARED_OWNED/SHARED_BORROWED still relevant since the introduction of
"KVM: arm64: Don't map 'kvm_vgic_global_state' at EL2 with pKVM"? It doesn't
seem we have any !OWNED pages in the hyp anymore at setup, do we?

> -- 
> 2.48.1.658.g4767266eb4-goog
> 


From kw at linux.com  Mon Mar  3 01:52:00 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Mon, 3 Mar 2025 18:52:00 +0900
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250221131548.59616-5-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
Message-ID: <20250303095200.GB1065658@rocinante>

Hello,

[...]
> +		29) Generates duplicate TLPs - duplicate_dllp
> +		30) Generates Nullified TLPs - nullified_tlp

Would the above field called "duplicate_dllp" for duplicate TLPs be
a potential typo?  Perhaps this should be called "duplicate_tlp"?

I wanted to make sure we have the correct field name.

Thank you!

	Krzysztof


From pierre.gondois at arm.com  Mon Mar  3 01:56:12 2025
From: pierre.gondois at arm.com (Pierre Gondois)
Date: Mon, 3 Mar 2025 10:56:12 +0100
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <20250228190641.q23vd53aaw42tcdi@bogus>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com> <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
Message-ID: <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com>



On 2/28/25 20:06, Sudeep Holla wrote:
> On Fri, Feb 28, 2025 at 06:51:16PM +0100, Pierre Gondois wrote:
>>
>>
>> On 2/28/25 14:56, Sudeep Holla wrote:
>>> On Tue, Feb 18, 2025 at 10:10:17PM +0800, Yicong Yang wrote:
>>>> From: Yicong Yang <yangyicong at hisilicon.com>
>>>>
>>>> For ACPI we'll build the topology from PPTT and we cannot directly
>>>> get the SMT number of each core. Instead using a temporary xarray
>>>> to record the heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL)
>>>> and SMT information of the first core in its heterogeneous CPU cluster
>>>> when building the topology. Then we can know the largest SMT number
>>>> in the system. If a homogeneous system's using ACPI 6.2 or later,
>>>> all the CPUs should be under the root node of PPTT. There'll be
>>>> only one entry in the xarray and all the CPUs in the system will
>>>> be assumed identical.
>>>>
>>>> The core's SMT control provides two interface to the users [1]:
>>>> 1) enable/disable SMT by writing on/off
>>>> 2) enable/disable SMT by writing thread number 1/max_thread_number
>>>>
>>>> If a system have more than one SMT thread number the 2) may
>>>> not handle it well, since there're multiple thread numbers in the
>>>> system and 2) only accept 1/max_thread_number. So issue a warning
>>>> to notify the users if such system detected.
>>>>
>>>> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
>>>>
>>>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
>>>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>>>> ---
>>>>    arch/arm64/kernel/topology.c | 66 ++++++++++++++++++++++++++++++++++++
>>>>    1 file changed, 66 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
>>>> index 1a2c72f3e7f8..6eba1ac091ee 100644
>>>> --- a/arch/arm64/kernel/topology.c
>>>> +++ b/arch/arm64/kernel/topology.c
>>>> @@ -15,8 +15,10 @@
>>>>    #include <linux/arch_topology.h>
>>>>    #include <linux/cacheinfo.h>
>>>>    #include <linux/cpufreq.h>
>>>> +#include <linux/cpu_smt.h>
>>>>    #include <linux/init.h>
>>>>    #include <linux/percpu.h>
>>>> +#include <linux/xarray.h>
>>>>    #include <asm/cpu.h>
>>>>    #include <asm/cputype.h>
>>>> @@ -37,17 +39,28 @@ static bool __init acpi_cpu_is_threaded(int cpu)
>>>>    	return !!is_threaded;
>>>>    }
>>>> +struct cpu_smt_info {
>>>> +	unsigned int thread_num;
>>>> +	int core_id;
>>>> +};
>>>> +
>>>>    /*
>>>>     * Propagate the topology information of the processor_topology_node tree to the
>>>>     * cpu_topology array.
>>>>     */
>>>>    int __init parse_acpi_topology(void)
>>>>    {
>>>> +	unsigned int max_smt_thread_num = 0;
>>>> +	struct cpu_smt_info *entry;
>>>> +	struct xarray hetero_cpu;
>>>> +	unsigned long hetero_id;
>>>>    	int cpu, topology_id;
>>>>    	if (acpi_disabled)
>>>>    		return 0;
>>>> +	xa_init(&hetero_cpu);
>>>> +
>>>>    	for_each_possible_cpu(cpu) {
>>>>    		topology_id = find_acpi_cpu_topology(cpu, 0);
>>>>    		if (topology_id < 0)
>>>> @@ -57,6 +70,34 @@ int __init parse_acpi_topology(void)
>>>>    			cpu_topology[cpu].thread_id = topology_id;
>>>>    			topology_id = find_acpi_cpu_topology(cpu, 1);
>>>>    			cpu_topology[cpu].core_id   = topology_id;
>>>> +
>>>> +			/*
>>>> +			 * In the PPTT, CPUs below a node with the 'identical
>>>> +			 * implementation' flag have the same number of threads.
>>>> +			 * Count the number of threads for only one CPU (i.e.
>>>> +			 * one core_id) among those with the same hetero_id.
>>>> +			 * See the comment of find_acpi_cpu_topology_hetero_id()
>>>> +			 * for more details.
>>>> +			 *
>>>> +			 * One entry is created for each node having:
>>>> +			 * - the 'identical implementation' flag
>>>> +			 * - its parent not having the flag
>>>> +			 */
>>>> +			hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
>>>> +			entry = xa_load(&hetero_cpu, hetero_id);
>>>> +			if (!entry) {
>>>> +				entry = kzalloc(sizeof(*entry), GFP_KERNEL);
>>>> +				WARN_ON_ONCE(!entry);
>>>> +
>>>> +				if (entry) {
>>>> +					entry->core_id = topology_id;
>>>> +					entry->thread_num = 1;
>>>> +					xa_store(&hetero_cpu, hetero_id,
>>>> +						 entry, GFP_KERNEL);
>>>> +				}
>>>> +			} else if (entry->core_id == topology_id) {
>>>> +				entry->thread_num++;
>>>> +			}
>>>>    		} else {
>>>>    			cpu_topology[cpu].thread_id  = -1;
>>>>    			cpu_topology[cpu].core_id    = topology_id;
>>>> @@ -67,6 +108,31 @@ int __init parse_acpi_topology(void)
>>>>    		cpu_topology[cpu].package_id = topology_id;
>>>>    	}
>>>> +	/*
>>>> +	 * This should be a short loop depending on the number of heterogeneous
>>>> +	 * CPU clusters. Typically on a homogeneous system there's only one
>>>> +	 * entry in the XArray.
>>>> +	 */
>>>> +	xa_for_each(&hetero_cpu, hetero_id, entry) {
>>>> +		if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)
>>>> +			pr_warn_once("Heterogeneous SMT topology is partly supported by SMT control\n");
>>>
>>> Ditto as previous patch about handling no threaded cores with threaded cores
>>> in the system. I am not sure if that is required but just raising it here.
>>>
>>>> +
>>>> +		max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
>>>> +		xa_erase(&hetero_cpu, hetero_id);
>>>> +		kfree(entry);
>>>> +	}
>>>> +
>>>> +	/*
>>>> +	 * Notify the CPU framework of the SMT support. Initialize the
>>>> +	 * max_smt_thread_num to 1 if no SMT support detected. A thread
>>>> +	 * number of 1 can be handled by the framework so we don't need
>>>> +	 * to check max_smt_thread_num to see we support SMT or not.
>>>> +	 */
>>>> +	if (!max_smt_thread_num)
>>>> +		max_smt_thread_num = 1;
>>>> +
>>>
>>> Ditto as previous patch, can get rid if it is default 1.
>>>
>>
>> On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
>> cpu_smt_num_threads uninitialized to UINT_MAX:
>>
>> smt/active:0
>> smt/control:-1
>>
>> If cpu_smt_set_num_threads() is called:
>> active:0
>> control:notsupported
>>
>> So it might be slightly better to still initialize max_smt_thread_num.
>>
> 
> Sure, what I meant is to have max_smt_thread_num set to 1 by default is
> that is what needed anyways and the above code does that now.
> 
> Why not start with initialised to 1 instead ?
> Of course some current logic needs to change around testing it for zero.
> 

I think there would still be a way to check against the default value.
If we have:
unsigned int max_smt_thread_num = 1;

then on a platform with 2 threads, the detection condition would trigger:
xa_for_each(&hetero_cpu, hetero_id, entry) {
     if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
         pr_warn_once("Heterogeneous SMT topology is partly
                       supported by SMT control\n");

so we would need an additional variable:
bool is_initialized = false;


From david at redhat.com  Mon Mar  3 01:57:21 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 10:57:21 +0100
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <20250303094947.GB13345@e133081.arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
 <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
 <20250303094947.GB13345@e133081.arm.com>
Message-ID: <7e987f17-ffcb-45e0-8588-2d569d90f776@redhat.com>

On 03.03.25 10:49, Miko?aj Lenczewski wrote:
> Hi David,
> 
> Thanks for taking the time to review.
> 
> On Mon, Mar 03, 2025 at 10:17:12AM +0100, David Hildenbrand wrote:
>> On 28.02.25 19:24, Miko?aj Lenczewski wrote:
>>> If we support bbml2 without conflict aborts, we can avoid the final
>>> flush and have hardware manage the tlb entries for us. Avoiding flushes
>>> is a win.
>>>
>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
>>> ---
>>>    arch/arm64/mm/contpte.c | 3 ---
>>>    1 file changed, 3 deletions(-)
>>>
>>> diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
>>> index 145530f706a9..77ed03b30b72 100644
>>> --- a/arch/arm64/mm/contpte.c
>>> +++ b/arch/arm64/mm/contpte.c
>>> @@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
>>>    		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>>>    	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
>>> -
>>> -	if (system_supports_bbml2_noabort())
>>> -		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>>>    }
>>>    void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
>>
>> What's the point of not squashing this into #2? :)
>>
>> If this split was requested during earlier review, at least seeing patch #2
>> on its own confused me.
> 
> This split is a holdover from an earlier patchset, where it was still
> unknown whether the removal of the second flush was permitted with
> BBML2. Partly this was due to us being worried about conflict aborts
> after the removal, and partly this was because the "delay" is a separate
> optimisation that we could apply even if it turned out the final patch
> was not architecturally sound.
> 
> Now that we do not handle conflict aborts (preferring only systems that
> handle BBML2 without ever raising aborts), the first issue is not a
> problem. The reasoning behind the second patch is also a little bit
> outdated, but I can see the logical split between a tlbi reorder, and
> the removal of the tlbi. If this is truly redundant though, I would be
> happy to squash the two into a single patch.

Thanks for the information.

Does patch #2 (reordering the tlbi) have any benefit on its own? I read 
"other threads will not see an invalid pagetable entry", but I am not 
sure that is correct. A concurrent HW page table walker would still find 
the invalid PTE? It's just a matter of TLB state.

If there is no benefit in having patch #2 independently, I'd just squash 
them. Reordering to then remove is more complicated than just removing 
it IMHO.

-- 
Cheers,

David / dhildenb



From david at redhat.com  Mon Mar  3 02:01:24 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 11:01:24 +0100
Subject: [PATCH v8] arm64: mm: Populate vmemmap at the page level if not
 section aligned
In-Reply-To: <20250219084001.1272445-1-quic_zhenhuah@quicinc.com>
References: <20250219084001.1272445-1-quic_zhenhuah@quicinc.com>
Message-ID: <78d55e35-6cda-4f5e-8e52-0a54b1e64592@redhat.com>

On 19.02.25 09:40, Zhenhua Huang wrote:
> On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
> to 27, making one section 128M. The related page struct which vmemmap
> points to is 2M then.
> Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
> vmemmap to populate at the PMD section level which was suitable
> initially since hot plug granule is always one section(128M). However,
> commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
> existing arm64 assumptions.
> 
> The first problem is that if start or end is not aligned to a section
> boundary, such as when a subsection is hot added, populating the entire
> section is wasteful.
> 
> The next problem is if we hotplug something that spans part of 128 MiB
> section (subsections, let's call it memblock1), and then hotplug something
> that spans another part of a 128 MiB section(subsections, let's call it
> memblock2), and subsequently unplug memblock1, vmemmap_free() will clear
> the entire PMD entry which also supports memblock2 even though memblock2
> is still active.
> 
> Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the
> fix similar to x86-64: populate to pages levels if start/end is not aligned
> with section boundary.
> 
> Cc: <stable at vger.kernel.org> # v5.4+
> Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
> ---
> Hi Catalin and David,
> Following our latest discussion, I've updated the patch for your review.
> I also removed Catalin's review tag since I've made significant modifications.
>   arch/arm64/mm/mmu.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b4df5bc5b1b8..de05ccf47f21 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
>   		struct vmem_altmap *altmap)
>   {
>   	WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
> +	/* [start, end] should be within one section */
> +	WARN_ON(end - start > PAGES_PER_SECTION * sizeof(struct page));
>   
> -	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
> +	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
> +		(end - start < PAGES_PER_SECTION * sizeof(struct page)))

Indentation should be

	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
	    (end - start < PAGES_PER_SECTION * sizeof(struct page)))


Acked-by: David Hildenbrand <david at redhat.com>


Thanks!

-- 
Cheers,

David / dhildenb



From ryan.roberts at arm.com  Mon Mar  3 02:17:28 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 3 Mar 2025 10:17:28 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
Message-ID: <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>

On 01/03/2025 01:32, Yang Shi wrote:
> 
> 
> 
> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>> BBM level 2 is claimed.
>>
>> Add the feature and testing for it under arm_smmu_sva_supported().
>>
>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>> ---
>> ? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>> ? 4 files changed, 13 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 63f6d356dc77..1022c63f81b2 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>> arm64_cpu_capabilities *caps, int sco
>> ????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>> ????????????????? return false;
>> ????????? }
>> -
>> -??????? return true;
>> ????? } else if (scope & SCOPE_LOCAL_CPU) {
>> ????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>> ?????????? * If we have the correct MIDR, but the kernel booted on an
>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>> arm64_cpu_capabilities *caps, int sco
>> ?????????? * we have an incorrect MIDR, but the kernel booted on a
>> ?????????? * sufficient CPU, we will not bring up this CPU.
>> ?????????? */
>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>> +??????????? return false;
>> ????? }
>> ? -??? return false;
>> +??? return has_cpuid_feature(caps, scope);
> 
> Do we really need this? IIRC, it means the MIDR has to be in the allow list
> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register set.

Miko, I think this should have been squashed into patch #1? It doesn't belong in
this patch.

Yang, we discussed this internally and decided that we thought it was best to
still require BBML2 being advertised in the feature register. That way if trying
to use KVM to emulate a CPU that is in the allow list but doesn't really support
BBML2, we won't try to use it.

But we still end up with the same problem if running on a physical CPU that
supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So
given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
remove this check.

Thanks,
Ryan


> 
> Thanks,
> Yang
> 
>> ? }
>> ? ? #ifdef CONFIG_ARM64_PAN
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>> index 9ba596430e7c..6ba182572788 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>> ????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>> ????? }
>> ? +??? if (system_supports_bbml2_noabort())
>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>> +
>> ????? if ((smmu->features & feat_mask) != feat_mask)
>> ????????? return false;
>> ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>> arm/arm-smmu-v3/arm-smmu-v3.c
>> index 358072b4e293..dcee0bdec924 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>> arm_smmu_device *smmu)
>> ????? if (FIELD_GET(IDR3_RIL, reg))
>> ????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>> ? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>> +
>> ????? /* IDR5 */
>> ????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>> ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>> arm/arm-smmu-v3/arm-smmu-v3.h
>> index bd9d7c85576a..85eaf3ab88c2 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>> ? #define ARM_SMMU_IDR3??????????? 0xc
>> ? #define IDR3_FWB??????????? (1 << 8)
>> ? #define IDR3_RIL??????????? (1 << 10)
>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>> +#define IDR3_BBML1??????????? (1 << 11)
>> +#define IDR3_BBML2??????????? (2 << 11)
>> ? ? #define ARM_SMMU_IDR5??????????? 0x14
>> ? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>> ? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>> ? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>> ? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>> ????? u32??????????????? features;
>> ? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)
> 



From ryan.roberts at arm.com  Mon Mar  3 02:23:37 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 3 Mar 2025 10:23:37 +0000
Subject: [PATCH V2 0/8] arm64/mm: Drop PXD_TABLE_BIT
In-Reply-To: <a9600c92-bef0-4dd1-95d4-c696d686da18@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
 <aa71c6ed-8ff2-4b52-b8f7-49147c7769ba@arm.com>
 <a9600c92-bef0-4dd1-95d4-c696d686da18@arm.com>
Message-ID: <9dd8e02c-9abb-47e6-92df-cf7af6cda99c@arm.com>

On 03/03/2025 05:02, Anshuman Khandual wrote:
> 
> 
> On 2/28/25 21:02, Ryan Roberts wrote:
>> On 21/02/2025 04:42, Anshuman Khandual wrote:
>>> Remove the PXX_TABLE_BIT definitions and instead rely on PXX_TYPE_MASK,
>>> PXX_TYPE_SECT and PXX_TYPE_TABLE. The latter versions are more abstract
>>> and also include the PTE_VALID bit.
>>>
>>> This abstraction is valuable for the impending D128 page table support,
>>> which doesn't have a single page table bit to determine table vs block.
>>> Instead it has the skip level (SKL) field, where it will consider 0 to
>>> mean table and any other value to mean a block entry. So PXX_TABLE_BIT
>>> therefore doesn't fit into the D128 model well, but the type fields do.
>>
>> All the patches look logically correct to me and I agree with the intention of
>> removing PXX_TABLE_BIT. But personally I'd prefer to see a single patch that
>> just does everything that's required to remove PXX_TABLE_BIT. And then a second
>> patch for the pud_bad() fix/improvement (currently patch 6) which is orthogonal
>> to the removal of PXX_TABLE_BIT.
>>
>> That would make it much easier to review IMHO, and would also allow for writing
>> a single commit log which provides the justification for the change. I find the
>> current set of 7 commit logs to not be hugely helpful.
> 
> Dropping PXX_TABLE_BIT from individual functional components which stand on their
> own progressively leads to its complete removal from the tree. Even though goal
> is PXX_TABLE_BIT mask's complete removal, each patch here could be justified on
> its own improving consistent reasoning around various section mapping creation
> and identification while keeping the functionality unchanged and also improving
> code readability as well.
> 
>>
>> But I wrote the original patches and wrote them as I'm suggesting, so I would
>> say that :)
> 
> I can understand :) Although it also follows and expands on the previous attempt
> in removing this mask that formed a patch series instead.
> 
> https://lore.kernel.org/all/20241005123824.1366397-1-anshuman.khandual at arm.com/
> 
> TBH this is not a big deal. I can merge all but last one into a single patch as
> you have suggested if that's a general consensus. Although I would prefer the
> current logically progressive series based approach but that's just me.

I guess leave as is for now and see what others say.

> 
>>
>> I'm guessing I shouldn't provide a Reviewed-By here, given I wrote the code
>> originally...
>>
>> Thanks,
>> Ryan
>>
>>
>>>
>>> This series applies on v6.14-rc3.
>>>
>>> Changes in V2:
>>>
>>> - Changed pmd_mkhuge() and pud_mkhuge() implementation
>>> - Changed pud_bad() implementation with an additional patch
>>>
>>> Changes in V1:
>>>
>>> https://lore.kernel.org/all/20241005123824.1366397-1-anshuman.khandual at arm.com/
>>>
>>> Cc: Marc Zyngier <maz at kernel.org>
>>> Cc: Oliver Upton <oliver.upton at linux.dev>
>>> Cc: James Morse <james.morse at arm.com>
>>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>>> Cc: Will Deacon <will at kernel.org>
>>> Cc: Ard Biesheuvel <ardb at kernel.org>
>>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>>> Cc: Mark Rutland <mark.rutland at arm.com>
>>> Cc: kvmarm at lists.linux.dev
>>> Cc: linux-arm-kernel at lists.infradead.org
>>> Cc: linux-kernel at vger.kernel.org
>>>
>>> Anshuman Khandual (6):
>>>   KVM: arm64: ptdump: Test PMD_TYPE_MASK for block mapping
>>>   arm64/ptdump: Test PMD_TYPE_MASK for block mapping
>>>   arm64/mm: Clear PXX_TYPE_MASK in mk_[pmd|pud]_sect_prot()
>>>   arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT in [pmd|pud]_mkhuge()
>>>   arm64/mm: Check PXD_TYPE_TABLE in [p4d|pgd]_bad()
>>>   arm64/mm: Drop PXD_TABLE_BIT
>>>
>>> Ryan Roberts (2):
>>>   arm64/mm: Check PUD_TYPE_TABLE in pud_bad()
>>>   arm64/mm: Check pmd_table() in pmd_trans_huge()
>>>
>>>  arch/arm64/include/asm/pgtable-hwdef.h |  5 --
>>>  arch/arm64/include/asm/pgtable.h       | 65 ++++++++++++++++++--------
>>>  arch/arm64/kvm/ptdump.c                |  4 +-
>>>  arch/arm64/mm/ptdump.c                 |  4 +-
>>>  4 files changed, 50 insertions(+), 28 deletions(-)
>>>
>>



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:54 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:54 -0500
Subject: [PATCH iwl-next v7 5/9] igc: Add support for frame preemption verification
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-6-faizal.abdul.rahim@linux.intel.com>

This patch implements the "ethtool --set-mm" callback to trigger the
frame preemption verification handshake.

Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool
to perform the verification handshake for igc.
The structure fpe.mmsv is set by mmsv in ethtool and should remain
read-only for the driver.

Other mmsv callbacks:
a) configure_tx() -> not used yet at this point
   - igc lacks registers to configure FPE in the transmit direction, so
     this API is not utilized for now. A future patch will use it to
     control preemptible queue config.

b) configure_pmac() -> not used
   - this callback dynamically controls pmac_enabled at runtime. For
     example, mmsv calls configure_pmac() and disables pmac_enabled when
     the link partner goes down, even if the user previously enabled it.
     The intention is to save power but it is not feasible in igc
     because it causes an endless adapter reset loop:

   1) Board A and Board B complete the verification handshake. Tx mode
      register for both boards are in TSN mode.
   2) Board B link goes down.

   On Board A:
   3) mmsv calls configure_pmac() with pmac_enabled = false.
   4) configure_pmac() in igc updates a new field based on pmac_enabled.
      Driver uses this field in igc_tsn_new_flags() to indicate that the
      user enabled/disabled FPE.
   5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
      whether an adapter reset is needed. Calls existing logic in
      igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
   6) Since pmac_enabled is now disabled and no other TSN feature is
      active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
      mode will switch from TSN to Legacy.
   7) Driver resets the adapter.
   8) Registers are set, and Tx mode switches to Legacy.
   9) When link partner is up, steps 3?8 repeat, but this time with
      pmac_enabled = true, reactivating TSN.
      igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
      mode will switch from Legacy to TSN.
  10) Driver resets the adapter.
  11) Rest adapter completes, registers are set, and Tx mode switches to
      TSN.

  On Board B:
  12) Adapter reset on Board A at step 10 causes it to detect its link
      partner as down.
  13) Repeats steps 3?8.
  14) Once reset adapter on Board A is completed at step 11, it detects
      its link partner as up.
  15) Repeats steps 9?11.

   - this cycle repeats indefinitely. To avoid this issue, igc only uses
     mmsv.pmac_enabled to track whether FPE is enabled or disabled.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  12 +-
 drivers/net/ethernet/intel/igc/igc_base.h    |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |   8 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  21 +++
 drivers/net/ethernet/intel/igc/igc_main.c    |  53 ++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 146 ++++++++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  51 +++++++
 7 files changed, 287 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 22ecdac26cf4..d9ecb7cf80c9 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -40,6 +40,10 @@ void igc_ethtool_set_ops(struct net_device *);
 
 #define IGC_MAX_TX_TSTAMP_REGS		4
 
+struct igc_fpe_t {
+	struct ethtool_mmsv mmsv;
+};
+
 enum igc_mac_filter_type {
 	IGC_MAC_FILTER_TYPE_DST = 0,
 	IGC_MAC_FILTER_TYPE_SRC
@@ -332,6 +336,8 @@ struct igc_adapter {
 		struct timespec64 period;
 	} perout[IGC_N_PEROUT];
 
+	struct igc_fpe_t fpe;
+
 	/* LEDs */
 	struct mutex led_mutex;
 	struct igc_led_classdev *leds;
@@ -389,10 +395,11 @@ extern char igc_driver_name[];
 #define IGC_FLAG_TSN_QBV_ENABLED	BIT(17)
 #define IGC_FLAG_TSN_QAV_ENABLED	BIT(18)
 #define IGC_FLAG_TSN_LEGACY_ENABLED	BIT(19)
+#define IGC_FLAG_TSN_PREEMPT_ENABLED	BIT(20)
 
 #define IGC_FLAG_TSN_ANY_ENABLED				\
 	(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED |	\
-	 IGC_FLAG_TSN_LEGACY_ENABLED)
+	 IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)
 
 #define IGC_FLAG_RSS_FIELD_IPV4_UDP	BIT(6)
 #define IGC_FLAG_RSS_FIELD_IPV6_UDP	BIT(7)
@@ -736,7 +743,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter);
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter);
 struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
+void igc_flush_tx_descriptors(struct igc_ring *ring);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h
index bf8cdfbba9ff..6320eabb72fe 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.h
+++ b/drivers/net/ethernet/intel/igc/igc_base.h
@@ -49,6 +49,7 @@ struct igc_adv_tx_context_desc {
 #define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
 #define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
 #define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
+#define IGC_ADVTXD_PAYLEN_MASK	0XFFFFC000 /* Adv desc PAYLEN mask */
 #define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */
 
 #define IGC_RAR_ENTRIES		16
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b19ac6f30dac..22db1de02964 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -308,6 +308,8 @@
 #define IGC_TXD_DTYP_C		0x00000000 /* Context Descriptor */
 #define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
 #define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
+#define IGC_TXD_POPTS_SMD_MASK	0x3000     /* Indicates whether it's SMD-V or SMD-R */
+
 #define IGC_TXD_CMD_EOP		0x01000000 /* End of Packet */
 #define IGC_TXD_CMD_IC		0x04000000 /* Insert Checksum */
 #define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
@@ -363,6 +365,8 @@
 #define IGC_SRRCTL_TIMER0SEL(timer)	(((timer) & 0x3) << 17)
 
 /* Receive Descriptor bit definitions */
+#define IGC_RXD_STAT_SMD_TYPE_V	0x01	/* SMD-V Packet */
+#define IGC_RXD_STAT_SMD_TYPE_R	0x02	/* SMD-R Packet */
 #define IGC_RXD_STAT_EOP	0x02	/* End of Packet */
 #define IGC_RXD_STAT_IXSM	0x04	/* Ignore checksum */
 #define IGC_RXD_STAT_UDPCS	0x10	/* UDP xsum calculated */
@@ -372,7 +376,8 @@
 #define IGC_RXDEXT_STATERR_LB	0x00040000
 
 /* Advanced Receive Descriptor bit definitions */
-#define IGC_RXDADV_STAT_TSIP	0x08000 /* timestamp in packet */
+#define IGC_RXDADV_STAT_SMD_TYPE_MASK	0x06000
+#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */
 
 #define IGC_RXDEXT_STATERR_L4E		0x20000000
 #define IGC_RXDEXT_STATERR_IPE		0x40000000
@@ -543,6 +548,7 @@
 
 /* Transmit Scheduling */
 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
+#define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
 
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 817838677817..b64d5c6c1d20 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -8,6 +8,7 @@
 
 #include "igc.h"
 #include "igc_diag.h"
+#include "igc_tsn.h"
 
 /* forward declaration */
 struct igc_stats {
@@ -1781,6 +1782,25 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_set_mm(struct net_device *netdev,
+			      struct ethtool_mm_cfg *cmd,
+			      struct netlink_ext_ack *extack)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
+		if (cmd->pmac_enabled)
+			static_branch_inc(&igc_fpe_enabled);
+		else
+			static_branch_dec(&igc_fpe_enabled);
+	}
+
+	ethtool_mmsv_set_mm(&fpe->mmsv, cmd);
+
+	return igc_tsn_offload_apply(adapter);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2076,6 +2096,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.set_mm			= igc_ethtool_set_mm,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index db4a36afcec6..fc086919387c 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2528,7 +2528,7 @@ static int igc_xdp_run_prog(struct igc_adapter *adapter, struct xdp_buff *xdp)
 }
 
 /* This function assumes __netif_tx_lock is held by the caller. */
-static void igc_flush_tx_descriptors(struct igc_ring *ring)
+void igc_flush_tx_descriptors(struct igc_ring *ring)
 {
 	/* Once tail pointer is updated, hardware can fetch the descriptors
 	 * any time so we issue a write membar here to ensure all memory
@@ -2617,6 +2617,15 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
 			size -= IGC_TS_HDR_LEN;
 		}
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_is_verify_or_response(rx_desc, size)) {
+			igc_fpe_lp_event_status(rx_desc, &adapter->fpe.mmsv);
+			/* Advance the ring next-to-clean */
+			igc_is_non_eop(rx_ring, rx_desc);
+			cleaned_count++;
+			continue;
+		}
+
 		if (!skb) {
 			xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
 			xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
@@ -3064,6 +3073,11 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
 		if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD)))
 			break;
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_transmitted_smd_v(tx_desc))
+			ethtool_mmsv_event_handle(&adapter->fpe.mmsv,
+						  ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
+
 		/* Hold the completions while there's a pending tx hardware
 		 * timestamp request from XDP Tx metadata.
 		 */
@@ -3955,6 +3969,30 @@ static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr)
 	return 0;
 }
 
+/**
+ * igc_enable_empty_addr_recv - Enable Rx of packets with all-zeroes MAC address
+ * @adapter: Pointer to the igc_adapter structure.
+ *
+ * Frame preemption verification requires that packets with the all-zeroes
+ * MAC address are allowed to be received by the driver. This function adds the
+ * all-zeroes destination address to the list of acceptable addresses.
+ *
+ * Return: 0 on success, negative value otherwise.
+ */
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty, -1);
+}
+
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty);
+}
+
 /**
  * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
  * @netdev: network interface device structure
@@ -5230,6 +5268,9 @@ void igc_down(struct igc_adapter *adapter)
 	igc_disable_all_tx_rings_hw(adapter);
 	igc_clean_all_tx_rings(adapter);
 	igc_clean_all_rx_rings(adapter);
+
+	if (adapter->fpe.mmsv.pmac_enabled)
+		ethtool_mmsv_stop(&adapter->fpe.mmsv);
 }
 
 void igc_reinit_locked(struct igc_adapter *adapter)
@@ -5754,6 +5795,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			 */
 			igc_tsn_adjust_txtime_offset(adapter);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       true);
+
 			if (adapter->link_speed != SPEED_1000)
 				goto no_wait;
 
@@ -5789,6 +5834,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			netdev_info(netdev, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       false);
+
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGC_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
@@ -7109,6 +7158,8 @@ static int igc_probe(struct pci_dev *pdev,
 
 	igc_tsn_clear_schedule(adapter);
 
+	igc_fpe_init(adapter);
+
 	/* reset the hardware with the new settings */
 	igc_reset(adapter);
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index f0213cfce07d..0a2c747fde2d 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -2,9 +2,135 @@
 /* Copyright (c)  2019 Intel Corporation */
 
 #include "igc.h"
+#include "igc_base.h"
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+static int igc_fpe_init_smd_frame(struct igc_ring *ring,
+				  struct igc_tx_buffer *buffer,
+				  struct sk_buff *skb)
+{
+	dma_addr_t dma = dma_map_single(ring->dev, skb->data, skb->len,
+					DMA_TO_DEVICE);
+
+	if (dma_mapping_error(ring->dev, dma)) {
+		netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
+		return -ENOMEM;
+	}
+
+	buffer->skb = skb;
+	buffer->protocol = 0;
+	buffer->bytecount = skb->len;
+	buffer->gso_segs = 1;
+	buffer->time_stamp = jiffies;
+	dma_unmap_len_set(buffer, len, skb->len);
+	dma_unmap_addr_set(buffer, dma, dma);
+
+	return 0;
+}
+
+static int igc_fpe_init_tx_descriptor(struct igc_ring *ring,
+				      struct sk_buff *skb,
+				      enum igc_txd_popts_type type)
+{
+	u32 cmd_type, olinfo_status = 0;
+	struct igc_tx_buffer *buffer;
+	union igc_adv_tx_desc *desc;
+	int err;
+
+	if (!igc_desc_unused(ring))
+		return -EBUSY;
+
+	buffer = &ring->tx_buffer_info[ring->next_to_use];
+	err = igc_fpe_init_smd_frame(ring, buffer, skb);
+	if (err)
+		return err;
+
+	cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
+		   IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
+		   buffer->bytecount;
+
+	olinfo_status |= FIELD_PREP(IGC_ADVTXD_PAYLEN_MASK, buffer->bytecount);
+
+	switch (type) {
+	case SMD_V:
+	case SMD_R:
+		olinfo_status |= FIELD_PREP(IGC_TXD_POPTS_SMD_MASK, type);
+		break;
+	}
+
+	desc = IGC_TX_DESC(ring, ring->next_to_use);
+	desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+	desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+	desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
+
+	netdev_tx_sent_queue(txring_txq(ring), skb->len);
+
+	buffer->next_to_watch = desc;
+	ring->next_to_use = (ring->next_to_use + 1) % ring->count;
+
+	return 0;
+}
+
+static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
+				  enum igc_txd_popts_type type)
+{
+	int cpu = smp_processor_id();
+	struct netdev_queue *nq;
+	struct igc_ring *ring;
+	struct sk_buff *skb;
+	int err;
+
+	ring = igc_get_tx_ring(adapter, cpu);
+	nq = txring_txq(ring);
+
+	skb = alloc_skb(SMD_FRAME_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put_zero(skb, SMD_FRAME_SIZE);
+
+	__netif_tx_lock(nq, cpu);
+
+	err = igc_fpe_init_tx_descriptor(ring, skb, type);
+	igc_flush_tx_descriptors(ring);
+
+	__netif_tx_unlock(nq);
+
+	return err;
+}
+
+static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				 enum ethtool_mpacket type)
+{
+	struct igc_fpe_t *fpe = container_of(mmsv, struct igc_fpe_t, mmsv);
+	struct igc_adapter *adapter;
+	int err;
+
+	adapter = container_of(fpe, struct igc_adapter, fpe);
+
+	if (type == ETHTOOL_MPACKET_VERIFY) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_V);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-V\n");
+	} else if (type == ETHTOOL_MPACKET_RESPONSE) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_R);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-R frame\n");
+	}
+}
+
+static const struct ethtool_mmsv_ops igc_mmsv_ops = {
+	.send_mpacket = igc_fpe_send_mpacket,
+};
+
+void igc_fpe_init(struct igc_adapter *adapter)
+{
+	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
+}
+
 static bool is_any_launchtime(struct igc_adapter *adapter)
 {
 	int i;
@@ -49,6 +175,9 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
 	if (adapter->strict_priority_enable)
 		new_flags |= IGC_FLAG_TSN_LEGACY_ENABLED;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		new_flags |= IGC_FLAG_TSN_PREEMPT_ENABLED;
+
 	return new_flags;
 }
 
@@ -148,7 +277,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
-		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
+		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
+		      IGC_TQAVCTRL_PREEMPT_ENA);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -370,10 +500,14 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 		wr32(IGC_TXQCTL(i), txqctl);
 	}
 
-	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
+	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
+		   IGC_TQAVCTRL_PREEMPT_ENA);
 
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
@@ -434,6 +568,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)
 	unsigned int new_flags;
 	int err = 0;
 
+	if (adapter->fpe.mmsv.pmac_enabled) {
+		err = igc_enable_empty_addr_recv(adapter);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error adding empty address to MAC filter\n");
+	} else {
+		igc_disable_empty_addr_recv(adapter);
+	}
+
 	new_flags = igc_tsn_new_flags(adapter);
 
 	if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 98ec845a86bf..a1104326c904 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,9 +4,60 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define SMD_FRAME_SIZE			60
+
+enum igc_txd_popts_type {
+	SMD_V = 0x01,
+	SMD_R = 0x02,
+};
+
+DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+void igc_fpe_init(struct igc_adapter *adapter);
+u32 igc_fpe_get_supported_frag_size(u32 user_frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
 bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter);
 
+static inline bool igc_fpe_is_pmac_enabled(struct igc_adapter *adapter)
+{
+	return static_branch_unlikely(&igc_fpe_enabled) &&
+	       adapter->fpe.mmsv.pmac_enabled;
+}
+
+static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
+						 unsigned int size)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+
+	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
+		size == SMD_FRAME_SIZE;
+}
+
+static inline void igc_fpe_lp_event_status(union igc_adv_rx_desc *rx_desc,
+					   struct ethtool_mmsv *mmsv)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+
+	if (smd == IGC_RXD_STAT_SMD_TYPE_V)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
+	else if (smd == IGC_RXD_STAT_SMD_TYPE_R)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
+}
+
+static inline bool igc_fpe_transmitted_smd_v(union igc_adv_tx_desc *tx_desc)
+{
+	u32 olinfo_status = le32_to_cpu(tx_desc->read.olinfo_status);
+	u8 smd = FIELD_GET(IGC_TXD_POPTS_SMD_MASK, olinfo_status);
+
+	return smd == SMD_V;
+}
+
 #endif /* _IGC_BASE_H */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:55 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:55 -0500
Subject: [PATCH iwl-next v7 6/9] igc: Add support to set tx-min-frag-size
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-7-faizal.abdul.rahim@linux.intel.com>

Add support to set tx-min-frag-size via set_mm callback in igc.
Increase the max limit of tx-ming-frag-size in ethtool from 252 to 256
since i225/6 value range is 64, 128, 192 and 256.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |  1 +
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  5 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 37 ++++++++++++++++++--
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  2 +-
 net/ethtool/mm.c                             |  2 +-
 6 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index d9ecb7cf80c9..4dfd133b4d6f 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *);
 
 struct igc_fpe_t {
 	struct ethtool_mmsv mmsv;
+	u32 tx_min_frag_size;
 };
 
 enum igc_mac_filter_type {
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 22db1de02964..038ee89f1e08 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -551,6 +551,7 @@
 #define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
+#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000
 
 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
 #define IGC_TXQCTL_STRICT_CYCLE		0x00000002
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index b64d5c6c1d20..529654ccd83f 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_fpe_t *fpe = &adapter->fpe;
 
+	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
+	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");
+
 	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
 		if (cmd->pmac_enabled)
 			static_branch_inc(&igc_fpe_enabled);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 0a2c747fde2d..2ec5909bf8b0 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -6,6 +6,12 @@
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+#define MIN_MULTPLIER_TX_MIN_FRAG	0
+#define MAX_MULTPLIER_TX_MIN_FRAG	3
+/* Frag size is based on the Section 8.12.2 of the SW User Manual */
+#define TX_MIN_FRAG_SIZE		64
+#define TX_MAX_FRAG_SIZE	(TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1))
+
 DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 static int igc_fpe_init_smd_frame(struct igc_ring *ring,
@@ -128,6 +134,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = {
 
 void igc_fpe_init(struct igc_adapter *adapter)
 {
+	adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
 	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
 }
 
@@ -278,7 +285,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
 		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
-		      IGC_TQAVCTRL_PREEMPT_ENA);
+		      IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -324,12 +331,34 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
 	wr32(IGC_RETX_CTL, retxctl);
 }
 
+static u8 igc_fpe_get_frag_size_mult(const struct igc_fpe_t *fpe)
+{
+	u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1;
+
+	return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG,
+		       MAX_MULTPLIER_TX_MIN_FRAG);
+}
+
+u32 igc_fpe_get_supported_frag_size(u32 frag_size)
+{
+	const u32 supported_sizes[] = {64, 128, 192, 256};
+
+	/* Find the smallest supported size that is >= frag_size */
+	for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) {
+		if (frag_size <= supported_sizes[i])
+			return supported_sizes[i];
+	}
+
+	return TX_MAX_FRAG_SIZE; /* Should not happen, value > 256 is blocked by ethtool */
+}
+
 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
 	u32 sec, nsec, cycle, rxpbs;
 	ktime_t base_time, systim;
+	u32 frag_size_mult;
 	int i;
 
 	wr32(IGC_TSAUXC, 0);
@@ -501,13 +530,15 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	}
 
 	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
-		   IGC_TQAVCTRL_PREEMPT_ENA);
-
+		   IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
 	if (adapter->fpe.mmsv.pmac_enabled)
 		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
 
+	frag_size_mult = igc_fpe_get_frag_size_mult(&adapter->fpe);
+	tqavctrl |= FIELD_PREP(IGC_TQAVCTRL_MIN_FRAG_MASK, frag_size_mult);
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index a1104326c904..6b48e0ed4341 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -14,7 +14,7 @@ enum igc_txd_popts_type {
 DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 void igc_fpe_init(struct igc_adapter *adapter);
-u32 igc_fpe_get_supported_frag_size(u32 user_frag_size);
+u32 igc_fpe_get_supported_frag_size(u32 frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index ad9b40034003..4c395cd949ab 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -153,7 +153,7 @@ const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1] = {
 	[ETHTOOL_A_MM_VERIFY_TIME]	= NLA_POLICY_RANGE(NLA_U32, 1, 128),
 	[ETHTOOL_A_MM_TX_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
 	[ETHTOOL_A_MM_PMAC_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
-	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 252),
+	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 256),
 };
 
 static void mm_state_to_cfg(const struct ethtool_mm_state *state,
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:56 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:56 -0500
Subject: [PATCH iwl-next v7 7/9] igc: Block setting preemptible traffic class in taprio
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-8-faizal.abdul.rahim@linux.intel.com>

Since preemptible tc implementation is not ready yet, block it from being
set in taprio. The existing code already blocks it in mqprio.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index fc086919387c..319eeb5b0a54 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6407,6 +6407,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 	if (!validate_schedule(adapter, qopt))
 		return -EINVAL;
 
+	/* preemptible isn't supported yet */
+	if (qopt->mqprio.preemptible_tcs)
+		return -EOPNOTSUPP;
+
 	igc_ptp_read(adapter, &now);
 
 	if (igc_tsn_is_taprio_activated_by_user(adapter) &&
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:57 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:57 -0500
Subject: [PATCH iwl-next v7 8/9] igc: Add support to get MAC Merge data via ethtool
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-9-faizal.abdul.rahim@linux.intel.com>

Implement "ethtool --show-mm" callback for IGC.

Tested with command:
$ ethtool --show-mm enp1s0.
  MAC Merge layer state for enp1s0:
  pMAC enabled: on
  TX enabled: on
  TX active: on
  TX minimum fragment size: 64
  RX minimum fragment size: 60
  Verify enabled: on
  Verify time: 128
  Max verify time: 128
  Verification status: SUCCEEDED

Verified that the fields value are retrieved correctly.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 14 ++++++++++++++
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 529654ccd83f..fd4b4b332309 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1782,6 +1782,19 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_get_mm(struct net_device *netdev,
+			      struct ethtool_mm_state *cmd)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	ethtool_mmsv_get_mm(&fpe->mmsv, cmd);
+	cmd->tx_min_frag_size = fpe->tx_min_frag_size;
+	cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE;
+
+	return 0;
+}
+
 static int igc_ethtool_set_mm(struct net_device *netdev,
 			      struct ethtool_mm_cfg *cmd,
 			      struct netlink_ext_ack *extack)
@@ -2101,6 +2114,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 6b48e0ed4341..a00dc1d80e12 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,6 +4,7 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define IGC_RX_MIN_FRAG_SIZE		60
 #define SMD_FRAME_SIZE			60
 
 enum igc_txd_popts_type {
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:58 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:58 -0500
Subject: [PATCH iwl-next v7 9/9] igc: Add support to get frame preemption statistics via ethtool
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-10-faizal.abdul.rahim@linux.intel.com>

Implemented "ethtool --include-statistics --show-mm" callback for IGC.

Tested preemption scenario to check preemption statistics:
1) Trigger verification handshake on both boards:
    $ sudo ethtool --set-mm enp1s0 pmac-enabled on
    $ sudo ethtool --set-mm enp1s0 tx-enabled on
    $ sudo ethtool --set-mm enp1s0 verify-enabled on
2) Set preemptible or express queue in taprio for tx board:
    $ sudo tc qdisc replace dev enp1s0 parent root handle 100 taprio \
      num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
      queues 1 at 0 1 at 1 1 at 2 1 at 3 base-time 0 sched-entry S F 100000 \
      fp E E P P
3) Send large size packets on preemptible queue
4) Send small size packets on express queue to preempt packets in
   preemptible queue
5) Show preemption statistics on the receiving board:
   $ ethtool --include-statistics --show-mm enp1s0
     MAC Merge layer state for enp1s0:
     pMAC enabled: on
     TX enabled: on
     TX active: on
     TX minimum fragment size: 64
     RX minimum fragment size: 60
     Verify enabled: on
     Verify time: 128
     Max verify time: 128
     Verification status: SUCCEEDED
     Statistics:
      MACMergeFrameAssErrorCount: 0
      MACMergeFrameSmdErrorCount: 0
      MACMergeFrameAssOkCount: 511
      MACMergeFragCountRx: 764
      MACMergeFragCountTx: 0
      MACMergeHoldCount: 0

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 36 ++++++++++++++++++++
 drivers/net/ethernet/intel/igc/igc_regs.h    | 16 +++++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index fd4b4b332309..a5f7512a7806 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1819,6 +1819,41 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	return igc_tsn_offload_apply(adapter);
 }
 
+/**
+ * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
+ * @dev: Pointer to the net_device structure.
+ * Return: The count of frame assembly errors.
+ */
+static u64 igc_ethtool_get_frame_ass_error(struct net_device *dev)
+{
+	struct igc_adapter *adapter = netdev_priv(dev);
+	u32 ooo_smdc, ooo_frame_cnt, ooo_frag_cnt; /* Out of order statistics */
+	struct igc_hw *hw = &adapter->hw;
+	u32 miss_frame_frag_cnt;
+	u32 reg_value;
+
+	reg_value = rd32(IGC_PRMEXPRCNT);
+	ooo_smdc = FIELD_GET(IGC_PRMEXPRCNT_OOO_SMDC, reg_value);
+	ooo_frame_cnt = FIELD_GET(IGC_PRMEXPRCNT_OOO_FRAME_CNT, reg_value);
+	ooo_frag_cnt = FIELD_GET(IGC_PRMEXPRCNT_OOO_FRAG_CNT, reg_value);
+	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXPRCNT_MISS_FRAME_FRAG_CNT,
+					reg_value);
+
+	return ooo_smdc + ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
+}
+
+static void igc_ethtool_get_mm_stats(struct net_device *dev,
+				     struct ethtool_mm_stats *stats)
+{
+	struct igc_adapter *adapter = netdev_priv(dev);
+	struct igc_hw *hw = &adapter->hw;
+
+	stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(dev);
+	stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT);
+	stats->MACMergeFragCountRx =  rd32(IGC_PRMEVNTRCNT);
+	stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2116,6 +2151,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.self_test		= igc_ethtool_diag_test,
 	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
+	.get_mm_stats		= igc_ethtool_get_mm_stats,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index 12ddc5793651..41dbfb07eb2f 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -222,6 +222,22 @@
 
 #define IGC_FTQF(_n)	(0x059E0 + (4 * (_n)))  /* 5-tuple Queue Fltr */
 
+/* Time sync registers - preemption statistics */
+#define IGC_PRMPTDRCNT		0x04284	/* Good RX Preempted Packets */
+#define IGC_PRMEVNTTCNT		0x04298	/* TX Preemption event counter */
+#define IGC_PRMEVNTRCNT		0x0429C	/* RX Preemption event counter */
+
+ /* Preemption Exception Counter */
+#define IGC_PRMEXPRCNT					0x42A0
+/* Received out of order packets with SMD-C */
+#define IGC_PRMEXPRCNT_OOO_SMDC				0x000000FF
+/* Received out of order packets with SMD-C and wrong Frame CNT */
+#define IGC_PRMEXPRCNT_OOO_FRAME_CNT			0x0000FF00
+/* Received out of order packets with SMD-C and wrong Frag CNT */
+#define IGC_PRMEXPRCNT_OOO_FRAG_CNT			0x00FF0000
+/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
+#define IGC_PRMEXPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
+
 /* Transmit Scheduling Registers */
 #define IGC_TQAVCTRL		0x3570
 #define IGC_TXQCTL(_n)		(0x3344 + 0x4 * (_n))
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:49 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:49 -0500
Subject: [PATCH iwl-next v7 0/9] igc: Add support for Frame Preemption feature in IGC
Message-ID: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>

Introduces support for the FPE feature in the IGC driver.

The patches aligns with the upstream FPE API:
https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.oltean at nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.oltean at nxp.com/

It builds upon earlier work:
https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.1098888-1-vinicius.gomes at intel.com/

The patch series adds the following functionalities to the IGC driver:
a) Configure FPE using `ethtool --set-mm`.
b) Display FPE settings via `ethtool --show-mm`.
c) View FPE statistics using `ethtool --include-statistics --show-mm'.
e) Block setting preemptible tc in taprio since it is not supported yet.
   Existing code already blocks it in mqprio.

Tested:
Enabled CONFIG_PROVE_LOCKING, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_DMA_API_DEBUG, and CONFIG_KASAN
1) selftests
2) netdev down/up cycles
3) suspend/resume cycles
4) fpe verification

No bugs or unusual dmesg logs were observed.
Ran 1), 2) and 3) with and without the patch series, compared dmesg and selftest logs ? no differences found.

Change Log:
v6 -> v7:
- Squash the cpu param to the prev line (Przemek Kitszel)
- Use igc_ prefix for fpe_t (Przemek Kitszel)
- Move new ops to different line in igc_ethtool_ops (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): rx -> Rx (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): s/IGC/the driver/ (Przemek Kitszel)
- Change preferred style of init, from { }, to {} (Przemek Kitszel)
- Remove inclusion of umbrella header <linux/kernel.h> in igc_tsn.c (Przemek Kitszel)
- End enum with "," in igc_txd_popts_type (Przemek Kitszel)
- Remove unnecessary braces in igc_fpe_is_verify_or_response() (Przemek Kitszel)

v5 -> v6:
- Added Tested-by: Furong Xu for patch 1/9 (Vladimir, Furong Xu)
- Updated logic in ethtool_mmsv_link_state_handle() (Vladimir, Furong Xu)
- Swap sequence of function call in stmmac_set_mm() (Furong Xu)
- Log an error if igc_enable_empty_addr_recv() fails (Vladimir)
- Move the patch ".. Block setting preemptible traffic .." before ".. Add support to get MAC Merge data .." (Vladimir)
- Move mmsv function kernel-doc from .h to .c file (Vladimir)

v4 -> v5:
- Remove "igc: Add support for preemptible traffic class in taprio" patch (Vladimir)
- Add a new patch "igc: Block setting preemptible traffic classes in taprio" (Vladimir)
- Add kernel-doc for mmsv api (Vladimir)
- olininfo_status to use host byte order (Simon)
- status_error should host byte type (Simon)
- Some code was misplaced in the wrong patch (Vladimir)
- Mix of tabs and spaces in patch description (Vladimir)
- Created igc_is_pmac_enabled() to reduce code repetition (Vladimir)

v3 -> v4:
- Fix compilation warnings introduced by this patch series

v2 -> v3:
- Implement configure_tx() mmsv callback (Vladimir)
- Use static_branch_inc() and static_branch_dec() (Vladimir)
- Add adapter->fpe.mmsv.pmac_enabled as extra check (Vladimir)
- Remove unnecessary error check in igc_fpe_init_tx_descriptor() (Vladimir)
- Additional places to use FIELD_PREP() instead of manual bit manipulation (Vladimir)
- IGC_TXD_POPTS_SMD_V and IGC_TXD_POPTS_SMD_R type change to enum (Vladimir)
- Remove unnecessary netif_running() check in igc_fpe_xmit_frame (Vladimir)
- Rate limit print in igc_fpe_send_mpacket (Vladimir)

v1 -> v2:
- Extract the stmmac verification logic into a common library (Vladimir)
- igc to use common library for verification (Vladimir)
- Fix syntax for kernel-doc to use "Return:" (Vladimir)
- Use FIELD_GET instead of manual bit masking (Vladimir)
- Don't assign 0 to statistics counter in igc_ethtool_get_mm_stats() (Vladimir)
- Use pmac-enabled as a condition to allow MAC address value 0 (Vladimir)
- Define macro register value in increasing value order (Vladimir)
- Fix tx-min-frag-size handling for igc (Vladimir)
- Handle link state changes with verification in igc (Vladimir)
- Add static key for fast path code (Vladimir)
- rx_min_frag_size get from constant (Vladimir)

v1: https://patchwork.kernel.org/project/netdevbpf/cover/20241216064720.931522-1-faizal.abdul.rahim at linux.intel.com/
v2: https://patchwork.kernel.org/project/netdevbpf/cover/20250205100524.1138523-1-faizal.abdul.rahim at linux.intel.com/
v3: https://patchwork.kernel.org/project/netdevbpf/cover/20250207165649.2245320-1-faizal.abdul.rahim at linux.intel.com/
v4: https://patchwork.kernel.org/project/netdevbpf/cover/20250210070207.2615418-1-faizal.abdul.rahim at linux.intel.com/
v5: https://patchwork.kernel.org/project/netdevbpf/cover/20250220025349.3007793-1-faizal.abdul.rahim at linux.intel.com/
v6: https://patchwork.kernel.org/project/netdevbpf/cover/20250227140158.2129988-1-faizal.abdul.rahim at linux.intel.com/

Faizal Rahim (8):
  igc: Rename xdp_get_tx_ring() for non-xdp usage
  igc: Optimize the TX packet buffer utilization
  igc: Set the RX packet buffer size for TSN mode
  igc: Add support for frame preemption verification
  igc: Add support to set tx-min-frag-size
  igc: Block setting preemptible traffic class in taprio
  igc: Add support to get MAC Merge data via ethtool
  igc: Add support to get frame preemption statistics via ethtool

Vladimir Oltean (1):
  net: ethtool: mm: extract stmmac verification logic into common
    library

 drivers/net/ethernet/intel/igc/igc.h          |  15 +-
 drivers/net/ethernet/intel/igc/igc_base.h     |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h  |  15 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |  76 +++++
 drivers/net/ethernet/intel/igc/igc_main.c     |  66 +++-
 drivers/net/ethernet/intel/igc/igc_regs.h     |  16 +
 drivers/net/ethernet/intel/igc/igc_tsn.c      | 192 +++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h      |  52 ++++
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  41 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 281 +++++++++++++++++-
 15 files changed, 814 insertions(+), 217 deletions(-)

--
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:50 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:50 -0500
Subject: [PATCH iwl-next v7 1/9] net: ethtool: mm: extract stmmac verification logic into common library
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-2-faizal.abdul.rahim@linux.intel.com>

From: Vladimir Oltean <vladimir.oltean at nxp.com>

It appears that stmmac is not the only hardware which requires a
software-driven verification state machine for the MAC Merge layer.

While on the one hand it's good to encourage hardware implementations,
on the other hand it's quite difficult to tolerate multiple drivers
implementing independently fairly non-trivial logic.

Extract the hardware-independent logic from stmmac into library code and
put it in ethtool. Name the state structure "mmsv" for MAC Merge
Software Verification. Let this expose an operations structure for
executing the hardware stuff: sync hardware with the tx_active boolean
(result of verification process), enable/disable the pMAC, send mPackets,
notify library of external events (reception of mPackets), as well as
link state changes.

Note that it is assumed that the external events are received in hardirq
context. If they are not, it is probably a good idea to disable hardirqs
when calling ethtool_mmsv_event_handle(), because the library does not
do so.

Also, the MM software verification process has no business with the
tx_min_frag_size, that is all the driver's to handle.

Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Co-developed-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Tested-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Furong Xu <0x1207 at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  41 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 279 +++++++++++++++++-
 7 files changed, 395 insertions(+), 201 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index f05cae103d83..c9cc41af258a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -147,21 +147,9 @@ struct stmmac_channel {
 };
 
 struct stmmac_fpe_cfg {
-	/* Serialize access to MAC Merge state between ethtool requests
-	 * and link state updates.
-	 */
-	spinlock_t lock;
-
+	struct ethtool_mmsv mmsv;
 	const struct stmmac_fpe_reg *reg;
-	u32 fpe_csr;				/* MAC_FPE_CTRL_STS reg cache */
-
-	enum ethtool_mm_verify_status status;
-	struct timer_list verify_timer;
-	bool verify_enabled;
-	int verify_retries;
-	bool pmac_enabled;
-	u32 verify_time;
-	bool tx_enabled;
+	u32 fpe_csr;	/* MAC_FPE_CTRL_STS reg cache */
 };
 
 struct stmmac_tc_entry {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 918a32f8fda8..25533d6a3175 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1210,37 +1210,17 @@ static int stmmac_get_mm(struct net_device *ndev,
 			 struct ethtool_mm_state *state)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long flags;
 	u32 frag_size;
 
 	if (!stmmac_fpe_supported(priv))
 		return -EOPNOTSUPP;
 
-	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
+	ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
 
-	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	state->verify_enabled = priv->fpe_cfg.verify_enabled;
-	state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
-	state->verify_time = priv->fpe_cfg.verify_time;
-	state->tx_enabled = priv->fpe_cfg.tx_enabled;
-	state->verify_status = priv->fpe_cfg.status;
 	state->rx_min_frag_size = ETH_ZLEN;
-
-	/* FPE active if common tx_enabled and
-	 * (verification success or disabled(forced))
-	 */
-	if (state->tx_enabled &&
-	    (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
-	     state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
-		state->tx_active = true;
-	else
-		state->tx_active = false;
-
 	frag_size = stmmac_fpe_get_add_frag_size(priv);
 	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
 
-	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
-
 	return 0;
 }
 
@@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 			 struct netlink_ext_ack *extack)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
 	u32 frag_size;
 	int err;
 
@@ -1258,23 +1236,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (err)
 		return err;
 
-	/* Wait for the verification that's currently in progress to finish */
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	fpe_cfg->verify_enabled = cfg->verify_enabled;
-	fpe_cfg->pmac_enabled = cfg->pmac_enabled;
-	fpe_cfg->verify_time = cfg->verify_time;
-	fpe_cfg->tx_enabled = cfg->tx_enabled;
-
-	if (!cfg->verify_enabled)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-
 	stmmac_fpe_set_add_frag_size(priv, frag_size);
-	stmmac_fpe_apply(priv);
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+	ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index 3a4bee029c7f..75b470ee621a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -27,12 +27,6 @@
 #define STMMAC_MAC_FPE_CTRL_STS_SVER	BIT(1)
 #define STMMAC_MAC_FPE_CTRL_STS_EFPE	BIT(0)
 
-/* FPE link-partner hand-shaking mPacket type */
-enum stmmac_mpacket_type {
-	MPACKET_VERIFY = 0,
-	MPACKET_RESPONSE = 1,
-};
-
 struct stmmac_fpe_reg {
 	const u32 mac_fpe_reg;		/* offset of MAC_FPE_CTRL_STS */
 	const u32 mtl_fpe_reg;		/* offset of MTL_FPE_CTRL_STS */
@@ -48,10 +42,10 @@ bool stmmac_fpe_supported(struct stmmac_priv *priv)
 		priv->hw->mac->fpe_map_preemption_class;
 }
 
-static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
-				 bool pmac_enable)
+static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
 {
-	struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
 	const struct stmmac_fpe_reg *reg = cfg->reg;
 	u32 num_rxq = priv->plat->rx_queues_to_use;
 	void __iomem *ioaddr = priv->ioaddr;
@@ -68,6 +62,15 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 		cfg->fpe_csr = 0;
 	}
 	writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
+}
+
+static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
+{
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
+	void __iomem *ioaddr = priv->ioaddr;
+	u32 value;
 
 	value = readl(ioaddr + reg->int_en_reg);
 
@@ -85,47 +88,45 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 	writel(value, ioaddr + reg->int_en_reg);
 }
 
-static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
-				    enum stmmac_mpacket_type type)
+static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				    enum ethtool_mpacket type)
 {
-	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
 	void __iomem *ioaddr = priv->ioaddr;
-	u32 value = priv->fpe_cfg.fpe_csr;
+	u32 value = cfg->fpe_csr;
 
-	if (type == MPACKET_VERIFY)
+	if (type == ETHTOOL_MPACKET_VERIFY)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
-	else if (type == MPACKET_RESPONSE)
+	else if (type == ETHTOOL_MPACKET_RESPONSE)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
 
 	writel(value, ioaddr + reg->mac_fpe_reg);
 }
 
+static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
+	.configure_tx = stmmac_fpe_configure_tx,
+	.configure_pmac = stmmac_fpe_configure_pmac,
+	.send_mpacket = stmmac_fpe_send_mpacket,
+};
+
 static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
 {
 	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+	struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv;
 
-	/* This is interrupt context, just spin_lock() */
-	spin_lock(&fpe_cfg->lock);
-
-	if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
-		goto unlock_out;
+	if (status == FPE_EVENT_UNKNOWN)
+		return;
 
-	/* LP has sent verify mPacket */
 	if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
-		stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
 
-	/* Local has sent verify mPacket */
-	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
 
-	/* LP has sent response mPacket */
-	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
-	    fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
-
-unlock_out:
-	spin_unlock(&fpe_cfg->lock);
+	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
 }
 
 void stmmac_fpe_irq_status(struct stmmac_priv *priv)
@@ -164,119 +165,16 @@ void stmmac_fpe_irq_status(struct stmmac_priv *priv)
 	stmmac_fpe_event_status(priv, status);
 }
 
-/**
- * stmmac_fpe_verify_timer - Timer for MAC Merge verification
- * @t:  timer_list struct containing private info
- *
- * Verify the MAC Merge capability in the local TX direction, by
- * transmitting Verify mPackets up to 3 times. Wait until link
- * partner responds with a Response mPacket, otherwise fail.
- */
-static void stmmac_fpe_verify_timer(struct timer_list *t)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
-	struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
-						fpe_cfg);
-	unsigned long flags;
-	bool rearm = false;
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	switch (fpe_cfg->status) {
-	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
-	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
-		if (fpe_cfg->verify_retries != 0) {
-			stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
-			rearm = true;
-		} else {
-			fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
-		}
-
-		fpe_cfg->verify_retries--;
-		break;
-
-	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
-		stmmac_fpe_configure(priv, true, true);
-		break;
-
-	default:
-		break;
-	}
-
-	if (rearm) {
-		mod_timer(&fpe_cfg->verify_timer,
-			  jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
-static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
-{
-	if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
-	    fpe_cfg->verify_enabled &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
-		timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
-		mod_timer(&fpe_cfg->verify_timer, jiffies);
-	}
-}
-
 void stmmac_fpe_init(struct stmmac_priv *priv)
 {
-	priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-	priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-	timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
-	spin_lock_init(&priv->fpe_cfg.lock);
+	ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev,
+			  &stmmac_mmsv_ops);
 
 	if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
 	    priv->dma_cap.fpesel)
 		dev_info(priv->device, "FPE is not supported by driver.\n");
 }
 
-void stmmac_fpe_apply(struct stmmac_priv *priv)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
-	/* If verification is disabled, configure FPE right away.
-	 * Otherwise let the timer code do it.
-	 */
-	if (!fpe_cfg->verify_enabled) {
-		stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
-				     fpe_cfg->pmac_enabled);
-	} else {
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
-		fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-
-		if (netif_running(priv->dev))
-			stmmac_fpe_verify_timer_arm(fpe_cfg);
-	}
-}
-
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
-
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	if (is_up && fpe_cfg->pmac_enabled) {
-		/* VERIFY process requires pmac enabled when NIC comes up */
-		stmmac_fpe_configure(priv, false, true);
-
-		/* New link => maybe new partner => new verification process */
-		stmmac_fpe_apply(priv);
-	} else {
-		/* No link => turn off EFPE */
-		stmmac_fpe_configure(priv, false, false);
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
 {
 	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
index b884eac7142d..3fc46acf7001 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
@@ -9,15 +9,10 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 
-#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES	3
-#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS	128
-
 struct stmmac_priv;
 
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
 bool stmmac_fpe_supported(struct stmmac_priv *priv);
 void stmmac_fpe_init(struct stmmac_priv *priv);
-void stmmac_fpe_apply(struct stmmac_priv *priv);
 void stmmac_fpe_irq_status(struct stmmac_priv *priv);
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
 void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d04543e5697b..8f723f9e84ba 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -992,7 +992,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, false);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, false);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, false);
 }
 
 static void stmmac_mac_link_up(struct phylink_config *config,
@@ -1100,7 +1100,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, true);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, true);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, true);
 
 	if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
 		stmmac_hwtstamp_correct_latency(priv, priv);
@@ -4097,7 +4097,7 @@ static int stmmac_release(struct net_device *dev)
 	stmmac_release_ptp(priv);
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	pm_runtime_put(priv->device);
 
@@ -7822,7 +7822,7 @@ int stmmac_suspend(struct device *dev)
 	rtnl_unlock();
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	priv->speed = SPEED_UNKNOWN;
 	return 0;
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 870994cc3ef7..b4b8eaf1f256 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -17,9 +17,13 @@
 #include <linux/compat.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
+#include <linux/timer_types.h>
 #include <uapi/linux/ethtool.h>
 #include <uapi/linux/net_tstamp.h>
 
+#define ETHTOOL_MM_MAX_VERIFY_TIME_MS		128
+#define ETHTOOL_MM_MAX_VERIFY_RETRIES		3
+
 struct compat_ethtool_rx_flow_spec {
 	u32		flow_type;
 	union ethtool_flow_union h_u;
@@ -710,6 +714,75 @@ struct ethtool_mm_stats {
 	u64 MACMergeHoldCount;
 };
 
+enum ethtool_mmsv_event {
+	ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET,
+};
+
+/* MAC Merge verification mPacket type */
+enum ethtool_mpacket {
+	ETHTOOL_MPACKET_VERIFY,
+	ETHTOOL_MPACKET_RESPONSE,
+};
+
+struct ethtool_mmsv;
+
+/**
+ * struct ethtool_mmsv_ops - Operations for MAC Merge Software Verification
+ * @configure_tx: Driver callback for the event where the preemptible TX
+ *		  becomes active or inactive. Preemptible traffic
+ *		  classes must be committed to hardware only while
+ *		  preemptible TX is active.
+ * @configure_pmac: Driver callback for the event where the pMAC state
+ *		    changes as result of an administrative setting
+ *		    (ethtool) or a call to ethtool_mmsv_link_state_handle().
+ * @send_mpacket: Driver-provided method for sending a Verify or a Response
+ *		  mPacket.
+ */
+struct ethtool_mmsv_ops {
+	void (*configure_tx)(struct ethtool_mmsv *mmsv, bool tx_active);
+	void (*configure_pmac)(struct ethtool_mmsv *mmsv, bool pmac_enabled);
+	void (*send_mpacket)(struct ethtool_mmsv *mmsv, enum ethtool_mpacket mpacket);
+};
+
+/**
+ * struct ethtool_mmsv - MAC Merge Software Verification
+ * @ops: operations for MAC Merge Software Verification
+ * @dev: pointer to net_device structure
+ * @lock: serialize access to MAC Merge state between
+ *	  ethtool requests and link state updates.
+ * @status: current verification FSM state
+ * @verify_timer: timer for verification in local TX direction
+ * @verify_enabled: indicates if verification is enabled
+ * @verify_retries: number of retries for verification
+ * @pmac_enabled: indicates if the preemptible MAC is enabled
+ * @verify_time: time for verification in milliseconds
+ * @tx_enabled: indicates if transmission is enabled
+ */
+struct ethtool_mmsv {
+	const struct ethtool_mmsv_ops *ops;
+	struct net_device *dev;
+	spinlock_t lock;
+	enum ethtool_mm_verify_status status;
+	struct timer_list verify_timer;
+	bool verify_enabled;
+	int verify_retries;
+	bool pmac_enabled;
+	u32 verify_time;
+	bool tx_enabled;
+};
+
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv);
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up);
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event);
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state);
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg);
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops);
+
 /**
  * struct ethtool_rxfh_param - RXFH (RSS) parameters
  * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index 2816bb23c3ad..ad9b40034003 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright 2022-2023 NXP
+ * Copyright 2022-2025 NXP
+ * Copyright 2024 Furong Xu <0x1207 at gmail.com>
  */
 #include "common.h"
 #include "netlink.h"
@@ -282,3 +283,279 @@ bool ethtool_dev_mm_supported(struct net_device *dev)
 	return supported;
 }
 EXPORT_SYMBOL_GPL(ethtool_dev_mm_supported);
+
+static void ethtool_mmsv_configure_tx(struct ethtool_mmsv *mmsv,
+				      bool tx_active)
+{
+	if (mmsv->ops->configure_tx)
+		mmsv->ops->configure_tx(mmsv, tx_active);
+}
+
+static void ethtool_mmsv_configure_pmac(struct ethtool_mmsv *mmsv,
+					bool pmac_enabled)
+{
+	if (mmsv->ops->configure_pmac)
+		mmsv->ops->configure_pmac(mmsv, pmac_enabled);
+}
+
+static void ethtool_mmsv_send_mpacket(struct ethtool_mmsv *mmsv,
+				      enum ethtool_mpacket mpacket)
+{
+	if (mmsv->ops->send_mpacket)
+		mmsv->ops->send_mpacket(mmsv, mpacket);
+}
+
+/**
+ * ethtool_mmsv_verify_timer - Timer for MAC Merge verification
+ * @t: timer_list struct containing private info
+ *
+ * Verify the MAC Merge capability in the local TX direction, by
+ * transmitting Verify mPackets up to 3 times. Wait until link
+ * partner responds with a Response mPacket, otherwise fail.
+ */
+static void ethtool_mmsv_verify_timer(struct timer_list *t)
+{
+	struct ethtool_mmsv *mmsv = from_timer(mmsv, t, verify_timer);
+	unsigned long flags;
+	bool rearm = false;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	switch (mmsv->status) {
+	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+		if (mmsv->verify_retries != 0) {
+			ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_VERIFY);
+			rearm = true;
+		} else {
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+		}
+
+		mmsv->verify_retries--;
+		break;
+
+	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+		ethtool_mmsv_configure_tx(mmsv, true);
+		break;
+
+	default:
+		break;
+	}
+
+	if (rearm) {
+		mod_timer(&mmsv->verify_timer,
+			  jiffies + msecs_to_jiffies(mmsv->verify_time));
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+
+static void ethtool_mmsv_verify_timer_arm(struct ethtool_mmsv *mmsv)
+{
+	if (mmsv->pmac_enabled && mmsv->tx_enabled && mmsv->verify_enabled &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
+		timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+		mod_timer(&mmsv->verify_timer, jiffies);
+	}
+}
+
+static void ethtool_mmsv_apply(struct ethtool_mmsv *mmsv)
+{
+	/* If verification is disabled, configure FPE right away.
+	 * Otherwise let the timer code do it.
+	 */
+	if (!mmsv->verify_enabled) {
+		ethtool_mmsv_configure_pmac(mmsv, mmsv->pmac_enabled);
+		ethtool_mmsv_configure_tx(mmsv, mmsv->tx_enabled);
+	} else {
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+
+		if (netif_running(mmsv->dev))
+			ethtool_mmsv_verify_timer_arm(mmsv);
+	}
+}
+
+/**
+ * ethtool_mmsv_stop() - Stop MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ *
+ * Drivers should call this method in a state where the hardware is
+ * about to lose state, like ndo_stop() or suspend(), and turning off
+ * MAC Merge features would be superfluous. Otherwise, prefer
+ * ethtool_mmsv_link_state_handle() with up=false.
+ */
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv)
+{
+	timer_shutdown_sync(&mmsv->verify_timer);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_stop);
+
+/**
+ * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification
+ *				      of link state changes
+ * @mmsv: MAC Merge Software Verification state
+ * @up: True if device carrier is up and able to pass verification packets
+ *
+ * Calling context is expected to be from a task, interrupts enabled.
+ */
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
+{
+	unsigned long flags;
+
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	if (up && mmsv->pmac_enabled) {
+		/* VERIFY process requires pMAC enabled when NIC comes up */
+		ethtool_mmsv_configure_pmac(mmsv, true);
+
+		/* New link => maybe new partner => new verification process */
+		ethtool_mmsv_apply(mmsv);
+	} else {
+		/* Reset the reported verification state while the link is down */
+		if (mmsv->verify_enabled)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+
+		/* No link or pMAC not enabled */
+		ethtool_mmsv_configure_pmac(mmsv, false);
+		ethtool_mmsv_configure_tx(mmsv, false);
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle);
+
+/**
+ * ethtool_mmsv_event_handle() - Inform MAC Merge Software Verification
+ *				 of interrupt-based events
+ * @mmsv: MAC Merge Software Verification state
+ * @event: Event which took place (packet transmission or reception)
+ *
+ * Calling context expects to have interrupts disabled.
+ */
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event)
+{
+	/* This is interrupt context, just spin_lock() */
+	spin_lock(&mmsv->lock);
+
+	if (!mmsv->pmac_enabled)
+		goto unlock;
+
+	switch (event) {
+	case ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET:
+		/* Link partner has sent verify mPacket */
+		ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_RESPONSE);
+		break;
+	case ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET:
+		/* Local device has sent verify mPacket */
+		if (mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+		break;
+	case ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET:
+		/* Link partner has sent response mPacket */
+		if (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+		break;
+	}
+
+unlock:
+	spin_unlock(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_event_handle);
+
+static bool ethtool_mmsv_is_tx_active(struct ethtool_mmsv *mmsv)
+{
+	/* TX is active if administratively enabled, and verification either
+	 * succeeded, or was administratively disabled.
+	 */
+	return mmsv->tx_enabled &&
+	       (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
+	       mmsv->status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
+}
+
+/**
+ * ethtool_mmsv_get_mm() - get_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @state: see struct ethtool_mm_state
+ *
+ * Drivers are expected to call this from their ethtool_ops :: get_mm()
+ * method.
+ */
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	state->verify_enabled = mmsv->verify_enabled;
+	state->pmac_enabled = mmsv->pmac_enabled;
+	state->verify_time = mmsv->verify_time;
+	state->tx_enabled = mmsv->tx_enabled;
+	state->verify_status = mmsv->status;
+	state->tx_active = ethtool_mmsv_is_tx_active(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_get_mm);
+
+/**
+ * ethtool_mmsv_set_mm() - set_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @cfg: see struct ethtool_mm_cfg
+ *
+ * Drivers are expected to call this from their ethtool_ops :: set_mm()
+ * method.
+ */
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg)
+{
+	unsigned long flags;
+
+	/* Wait for the verification that's currently in progress to finish */
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	mmsv->verify_enabled = cfg->verify_enabled;
+	mmsv->pmac_enabled = cfg->pmac_enabled;
+	mmsv->verify_time = cfg->verify_time;
+	mmsv->tx_enabled = cfg->tx_enabled;
+
+	if (!cfg->verify_enabled)
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+
+	ethtool_mmsv_apply(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_set_mm);
+
+/**
+ * ethtool_mmsv_init() - Initialize MAC Merge Software Verification state
+ * @mmsv: MAC Merge Software Verification state
+ * @dev: Pointer to network interface
+ * @ops: Methods for implementing the generic functionality
+ *
+ * The MAC Merge Software Verification is a timer- and event-based state
+ * machine intended for network interfaces which lack a hardware-based
+ * TX verification process (as per IEEE 802.3 clause 99.4.3). The timer
+ * is managed by the core code, whereas events are supplied by the
+ * driver explicitly calling one of the other API functions.
+ */
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops)
+{
+	mmsv->ops = ops;
+	mmsv->dev = dev;
+	mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+	mmsv->verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+	timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+	spin_lock_init(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_init);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:51 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:51 -0500
Subject: [PATCH iwl-next v7 2/9] igc: Rename xdp_get_tx_ring() for non-xdp usage
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-3-faizal.abdul.rahim@linux.intel.com>

Renamed xdp_get_tx_ring() function to a more generic name for use in
upcoming frame preemption patches.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h      | 2 +-
 drivers/net/ethernet/intel/igc/igc_main.c | 9 ++++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index b8111ad9a9a8..22ecdac26cf4 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -736,7 +736,7 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
-
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 56a35d58e7a6..db4a36afcec6 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2444,8 +2444,7 @@ static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
 	return -ENOMEM;
 }
 
-static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
-					    int cpu)
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu)
 {
 	int index = cpu;
 
@@ -2469,7 +2468,7 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
 	if (unlikely(!xdpf))
 		return -EFAULT;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
@@ -2546,7 +2545,7 @@ static void igc_finalize_xdp(struct igc_adapter *adapter, int status)
 	struct igc_ring *ring;
 
 	if (status & IGC_XDP_TX) {
-		ring = igc_xdp_get_tx_ring(adapter, cpu);
+		ring = igc_get_tx_ring(adapter, cpu);
 		nq = txring_txq(ring);
 
 		__netif_tx_lock(nq, cpu);
@@ -6699,7 +6698,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
 	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
 		return -EINVAL;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:52 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:52 -0500
Subject: [PATCH iwl-next v7 3/9] igc: Optimize the TX packet buffer utilization
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-4-faizal.abdul.rahim@linux.intel.com>

Packet buffers (RX + TX) total 64KB. Neither RX or TX buffers can be
larger than 34KB. So divide the buffer equally, 32KB for each.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 8e449904aa7d..516ef70c98e9 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -400,7 +400,8 @@
 #define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
 #define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */
 
-#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
+ /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/
+#define IGC_TXPBSIZE_TSN	0x041c71c7
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar  3 02:26:53 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon,  3 Mar 2025 05:26:53 -0500
Subject: [PATCH iwl-next v7 4/9] igc: Set the RX packet buffer size for TSN mode
In-Reply-To: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250303102658.3580232-5-faizal.abdul.rahim@linux.intel.com>

In preparation for supporting frame preemption, when entering TSN mode
set the receive packet buffer to 16KB for the Express MAC, 16KB for
the Preemptible MAC and 2KB for the BMC, according to the datasheet
section 7.1.3.2.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h |  3 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 13 +++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 516ef70c98e9..b19ac6f30dac 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -402,6 +402,9 @@
 
  /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/
 #define IGC_TXPBSIZE_TSN	0x041c71c7
+/* 15KB for EXP + 15KB for BE + 2KB for BMC */
+#define IGC_RXPBSIZE_TSN	0x0000f08f
+#define IGC_RXPBSIZE_SIZE_MASK	0x0001FFFF
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 1e44374ca1ff..f0213cfce07d 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -132,13 +132,17 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 {
 	u16 queue_per_tc[4] = { 3, 2, 1, 0 };
 	struct igc_hw *hw = &adapter->hw;
-	u32 tqavctrl;
+	u32 tqavctrl, rxpbs;
 	int i;
 
 	wr32(IGC_GTXOFFSET, 0);
 	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
+	rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
+	rxpbs |= I225_RXPBSIZE_DEFAULT;
+	wr32(IGC_RXPBS, rxpbs);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_restore_retx_default(adapter);
 
@@ -194,7 +198,7 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
-	u32 sec, nsec, cycle;
+	u32 sec, nsec, cycle, rxpbs;
 	ktime_t base_time, systim;
 	int i;
 
@@ -202,6 +206,11 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
 
+	rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
+	rxpbs |= IGC_RXPBSIZE_TSN;
+
+	wr32(IGC_RXPBS, rxpbs);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_set_retx_qbvfullthreshold(adapter);
 
-- 
2.34.1



From miko.lenczewski at arm.com  Mon Mar  3 02:31:02 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 10:31:02 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <b23aa37f8e864dea82a6143bece912d6@huawei.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
Message-ID: <20250303103102.GC13345@e133081.arm.com>

Hi Both,

Thanks for review and for checking other implementations for this
discrepancy.

On Mon, Mar 03, 2025 at 08:49:02AM +0000, Shameerali Kolothum Thodi wrote:
> 
> 
> > -----Original Message-----
> > From: Jason Gunthorpe <jgg at ziepe.ca>
> > Sent: Friday, February 28, 2025 7:32 PM
> > To: Miko?aj Lenczewski <miko.lenczewski at arm.com>; Shameerali Kolothum
> > Thodi <shameerali.kolothum.thodi at huawei.com>
> > Cc: ryan.roberts at arm.com; suzuki.poulose at arm.com;
> > yang at os.amperecomputing.com; catalin.marinas at arm.com;
> > will at kernel.org; joro at 8bytes.org; jean-philippe at linaro.org;
> > mark.rutland at arm.com; joey.gouly at arm.com; oliver.upton at linux.dev;
> > james.morse at arm.com; broonie at kernel.org; maz at kernel.org;
> > david at redhat.com; akpm at linux-foundation.org; nicolinc at nvidia.com;
> > mshavit at google.com; jsnitsel at redhat.com; smostafa at google.com; linux-
> > arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > iommu at lists.linux.dev
> > Subject: Re: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
> > 
> > On Fri, Feb 28, 2025 at 06:24:04PM +0000, Miko?aj Lenczewski wrote:
> > > For supporting BBM Level 2 for userspace mappings, we want to ensure
> > > that the smmu also supports its own version of BBM Level 2. Luckily, the
> > > smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
> > > 0487K.a D8.16.2), so already guarantees that no aborts are raised when
> > > BBM level 2 is claimed.
> > >
> > > Add the feature and testing for it under arm_smmu_sva_supported().
> > >
> > > Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> > > ---
> > >  arch/arm64/kernel/cpufeature.c                  | 7 +++----
> > >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
> > >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
> > >  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
> > >  4 files changed, 13 insertions(+), 4 deletions(-)
> > 
> > This patch looks good, for what it does. However for bisection safety
> > it should be earlier, before the patches that change the page table
> > algorithms to be unsafe for the SMMU.

Right, I should have noticed this earlier. Will reorder the patch.

> > However, I've heard people talking about shipping chips that have CPUs
> > with BBML2 but SMMUs without.
> > 
> > On such a system it seems like your series would break previously
> > working SVA support because this patch will end up disabling it?

Perhaps my understanding is flawed here, but I was under the impression
that with SVA both the core and smmu MUST support BBML2 to use it safely
for core translations? Otherwise the smmu might experience page faults
when it touches pages from the core that use BBML2, if it does not
support BBML2 itself? Again, I could very well be wrong, will double
check with the reference manuals.

> > Though I see your MIDR_REV list is limited, so perhaps that worry
> > doesn't effect any real chips made with those families? I am trying to
> > check some NVIDIA products against this list..

Hopefully, as you say, the MIDR list restricts the breakage to a limited
(ideally, zero-size) set of implementations which advertise BBML2
without conflict aborts, but which do not support BBML2 on the smmu.

However, if my understanding of the BBML2 feature and how it interacts
with SVA is flawed, this will obviously be something for me to fix.

> We do have implementations that support CPUs with BBLM2 with TLB
> conflict aborts and SMMUv3 with BBML2.  So don't think those platforms
> be affected by this.  Will check with our hardware folks if there is
> anything that will be affected by this.
> 
> Also we  have plans to try to use SMMUv3 BBML2 during VM live migration
> to split block pages to 4K. I guess, in that case we can enable SMMU BBML2
> independent of CPU side.
> 
> Thanks,
> Shameer

On independently enabling BBML2 on the smmu but not the CPU, this should
be possible. My check was intended to catch the case where the CPU is on
the MIDR allowlist, but the smmu does not support the feature. Whilst
this might still be bad logic, if it is correct, then as long as the CPU
is not in the allowlist sva should not be affected. And bbml2 itself on
the smmu should be safe regardless, as it is stricted than the
corresponding cpu-side feature.

-- 
Kind regards,
Miko?aj Lenczewski


From miko.lenczewski at arm.com  Mon Mar  3 02:32:01 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 10:32:01 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
Message-ID: <20250303103201.GD13345@e133081.arm.com>

On Mon, Mar 03, 2025 at 10:17:28AM +0000, Ryan Roberts wrote:
> On 01/03/2025 01:32, Yang Shi wrote:
> > 
> > 
> > 
> > On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
> >> For supporting BBM Level 2 for userspace mappings, we want to ensure
> >> that the smmu also supports its own version of BBM Level 2. Luckily, the
> >> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
> >> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
> >> BBM level 2 is claimed.
> >>
> >> Add the feature and testing for it under arm_smmu_sva_supported().
> >>
> >> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> >> ---
> >> ? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
> >> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
> >> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
> >> ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
> >> ? 4 files changed, 13 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> >> index 63f6d356dc77..1022c63f81b2 100644
> >> --- a/arch/arm64/kernel/cpufeature.c
> >> +++ b/arch/arm64/kernel/cpufeature.c
> >> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
> >> arm64_cpu_capabilities *caps, int sco
> >> ????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
> >> ????????????????? return false;
> >> ????????? }
> >> -
> >> -??????? return true;
> >> ????? } else if (scope & SCOPE_LOCAL_CPU) {
> >> ????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
> >> ?????????? * If we have the correct MIDR, but the kernel booted on an
> >> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
> >> arm64_cpu_capabilities *caps, int sco
> >> ?????????? * we have an incorrect MIDR, but the kernel booted on a
> >> ?????????? * sufficient CPU, we will not bring up this CPU.
> >> ?????????? */
> >> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
> >> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
> >> +??????????? return false;
> >> ????? }
> >> ? -??? return false;
> >> +??? return has_cpuid_feature(caps, scope);
> > 
> > Do we really need this? IIRC, it means the MIDR has to be in the allow list
> > *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register set.
> 
> Miko, I think this should have been squashed into patch #1? It doesn't belong in
> this patch.

Yes, 100%. Missed this, will put into patch #1.


From adrian.hunter at intel.com  Mon Mar  3 02:44:33 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Mon, 3 Mar 2025 12:44:33 +0200
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <20250217195908.176207-2-leo.yan@arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
Message-ID: <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>

On 17/02/25 21:58, Leo Yan wrote:
> Add a check for the generated string of flags.  Print out the raw number
> if the string generation fails.

How does it fail?

> 
> In another case, if the string length is longer than the aligned size,
> allow the completed string to be printed.
> 
> Reviewed-by: Ian Rogers <irogers at google.com>
> Reviewed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>  tools/perf/builtin-script.c   | 10 ++++++++--
>  tools/perf/util/trace-event.h |  2 ++
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> index d797cec4f054..2c4b1fb7dc72 100644
> --- a/tools/perf/builtin-script.c
> +++ b/tools/perf/builtin-script.c
> @@ -1709,9 +1709,15 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
>  static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
>  {
>  	char str[SAMPLE_FLAGS_BUF_SIZE];
> +	int ret;
> +
> +	ret = perf_sample__sprintf_flags(flags, str, sizeof(str));
> +	if (ret < 0)

AFAICT ret is always >= 0

> +		return fprintf(fp, "  raw flags:0x%-*x ",
> +			       SAMPLE_FLAGS_STR_ALIGNED_SIZE - 12, flags);
>  
> -	perf_sample__sprintf_flags(flags, str, sizeof(str));
> -	return fprintf(fp, "  %-21s ", str);
> +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
> +	return fprintf(fp, "  %-*s ", ret, str);

-21 means the field width is 21 and left-justified.  It should not
truncate the string.

>  }
>  
>  struct printer_data {
> diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
> index ac9fde2f980c..71e680bc3d4b 100644
> --- a/tools/perf/util/trace-event.h
> +++ b/tools/perf/util/trace-event.h
> @@ -145,6 +145,8 @@ int common_flags(struct scripting_context *context);
>  int common_lock_depth(struct scripting_context *context);
>  
>  #define SAMPLE_FLAGS_BUF_SIZE 64
> +#define SAMPLE_FLAGS_STR_ALIGNED_SIZE	21
> +
>  int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz);
>  
>  #if defined(LIBTRACEEVENT_VERSION) &&  LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0)



From menglong8.dong at gmail.com  Mon Mar  3 02:51:41 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon, 3 Mar 2025 18:51:41 +0800
Subject: [PATCH bpf-next v3 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250303091811.GH5880@noisy.programming.kicks-ass.net>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
 <20250303065345.229298-2-dongml2@chinatelecom.cn> <20250303091811.GH5880@noisy.programming.kicks-ass.net>
Message-ID: <CADxym3as+KdeBMUigq4xq302g2U7UG-7Gm+vKiYGnSjHouq=bg@mail.gmail.com>

On Mon, Mar 3, 2025 at 5:18?PM Peter Zijlstra <peterz at infradead.org> wrote:
>
> On Mon, Mar 03, 2025 at 02:53:42PM +0800, Menglong Dong wrote:
> > index c71b575bf229..ad050d09cb2b 100644
> > --- a/arch/x86/kernel/alternative.c
> > +++ b/arch/x86/kernel/alternative.c
> > @@ -908,7 +908,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end, struct mod
> >
> >               poison_endbr(addr, wr_addr, true);
> >               if (IS_ENABLED(CONFIG_FINEIBT))
> > -                     poison_cfi(addr - 16, wr_addr - 16);
> > +                     poison_cfi(addr, wr_addr);
> >       }
> >  }
>
> If you're touching this code, please use tip/x86/core or tip/master.

Thank you for reminding me that, I were using the linux-next, and
I notice that you just did some optimization to the FINEIBT :/

I'll send a V4 later, based on the tip/x86/core.

Thanks!
Menglong Dong


From johan at kernel.org  Mon Mar  3 02:53:52 2025
From: johan at kernel.org (Johan Hovold)
Date: Mon, 3 Mar 2025 11:53:52 +0100
Subject: [RFC V6 2/2] firmware: arm_scmi: Add quirk to bypass SCP fw bug
In-Reply-To: <Z8AjhHsVT9ZQTtZX@pluto>
References: <20250226024338.3994701-1-quic_sibis@quicinc.com>
 <20250226024338.3994701-3-quic_sibis@quicinc.com>
 <Z77M5iXHQsdMptWm@hovoldconsulting.com>
 <Z77W-fKBUqAALZKJ@hovoldconsulting.com>
 <759226e1-05aa-4ca2-b2f5-7f1a84dc427f@stanley.mountain>
 <Z77l1NflYXTnRyg0@hovoldconsulting.com>
 <Z8AjhHsVT9ZQTtZX@pluto>
Message-ID: <Z8WKQJcPTQDIXaKD@hovoldconsulting.com>

Hi Cristian,

On Thu, Feb 27, 2025 at 08:34:44AM +0000, Cristian Marussi wrote:
> On Wed, Feb 26, 2025 at 10:58:44AM +0100, Johan Hovold wrote:

> > Something like that, yes. :) I didn't try to implement it, but it seems
> > like it should be possible implement this is a way that keeps the quirk
> > handling isolated.
> 
> I hope next week to have a better look at this, in tne meantime just a
> few considerations....
> 
> Sooner or later we should have introduced some sort of quirk framework
> in SCMI to deal systematically with potentially out-of-spec FW, but as
> in the name, it should be some sort of framework where you have a table of
> quirks, related activation conditions and a few very well isolated points
> where the quirks are placed and take action if enabled...this does not
> seem the case here where instead an ad-hoc param is added to the function
> that needs to be quirked...this does not scale and will make the codebase
> a mess IMHO...

Sounds good. At least we have a good understanding now of how this
particular firmware is broken so it would be great if you could use
this as a test case for the implementation.

In summary, we need to force the use of a fast channel for
PERF_LEVEL_GET on these machines, or possibly fall back to the current
behaviour of only using the domain attribute to determine whether the
fast channels should be initialised.

The latter may allow for a less intrusive implementation even if we'd
still see:

	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:0] - ret:-95. Using regular messaging.
	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:1] - ret:-95. Using regular messaging.
	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:2] - ret:-95. Using regular messaging.

when not supported for all messages (e.g. with the current firmware).

> Last but not least, these quirks 'activations' in the SCMI world should
> be driven mainly by the VENDOR/SUB-VENDOR/IMPLEMENTATION_VERS triple and
> only as a last resort by a platform compatible match...because the
> IMPLEMENTATION_VERSION, exposed by the FW and gathered via SCMI Base
> protocol, is completely under the vendor control so it can, and should, be
> used to identify broken FW-versions...indeed all the distinct SCMI protocols
> are anyway versioned elsewhere according to the spec, so there is no need to
> repeat SCMI protocol version here..I mean it is an IMPLEMENTATION version
> 
> As an example on a JUNO the SCP reference FW reports:
> 
> arm-scmi arm-scmi.1.auto: SCMI Protocol v2.0 'arm:arm' Firmware version 0x20f0000
> 
> where the FW version represent something like the FW release tag, I think...not
> really sure about the menaing our FW gys give to it, BUT definitely it is not
> a bare copy of the SCMI protocol version...
> 
> So...
> ...does the platfom-to-be-quirked at hand properly use the IMPLEMENTATION_VERSION
> flag in a sensible way ?
> IOW does that change between a bad and good (or less bad :D) version ?

I guess only Sibi and Qualcomm can answer that. Both machines I have
that suffer from this report:

	arm-scmi arm-scmi.0.auto: SCMI Protocol v2.0 'Qualcomm:' Firmware version 0x20000

and I'm not sure if any fixed firmware has made it out to the vendors
yet or if the version was bumped when this was fixed.

On the other hand, perhaps forcing fast channel initialisation for
PERF_LEVEL_GET on all 'Qualcomm' firmware would work (i.e. only based on
VENDOR).

> Because shooting with the platform 'compatible-gun' should be the last resort
> if all of the above does NOT happen in this beloved fw...
> 
> Anyway, after all of this babbling, I know, talk is cheap :D...so now I will shut
> up and see if I can prototype something generic to deal with quirks, possibly
> next week...

Much appreciated, thanks.

Johan


From miko.lenczewski at arm.com  Mon Mar  3 02:55:47 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 10:55:47 +0000
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <7e987f17-ffcb-45e0-8588-2d569d90f776@redhat.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
 <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
 <20250303094947.GB13345@e133081.arm.com>
 <7e987f17-ffcb-45e0-8588-2d569d90f776@redhat.com>
Message-ID: <20250303105539.GA74129@e133081.arm.com>

On Mon, Mar 03, 2025 at 10:57:21AM +0100, David Hildenbrand wrote:
> On 03.03.25 10:49, Miko?aj Lenczewski wrote:
> > Hi David,
> > 
> > Thanks for taking the time to review.
> > 
> > On Mon, Mar 03, 2025 at 10:17:12AM +0100, David Hildenbrand wrote:
> > > On 28.02.25 19:24, Miko?aj Lenczewski wrote:
> > > > If we support bbml2 without conflict aborts, we can avoid the final
> > > > flush and have hardware manage the tlb entries for us. Avoiding flushes
> > > > is a win.
> > > > 
> > > > Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> > > > Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
> > > > ---
> > > >    arch/arm64/mm/contpte.c | 3 ---
> > > >    1 file changed, 3 deletions(-)
> > > > 
> > > > diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
> > > > index 145530f706a9..77ed03b30b72 100644
> > > > --- a/arch/arm64/mm/contpte.c
> > > > +++ b/arch/arm64/mm/contpte.c
> > > > @@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
> > > >    		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
> > > >    	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
> > > > -
> > > > -	if (system_supports_bbml2_noabort())
> > > > -		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
> > > >    }
> > > >    void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
> > > 
> > > What's the point of not squashing this into #2? :)
> > > 
> > > If this split was requested during earlier review, at least seeing patch #2
> > > on its own confused me.
> > 
> > This split is a holdover from an earlier patchset, where it was still
> > unknown whether the removal of the second flush was permitted with
> > BBML2. Partly this was due to us being worried about conflict aborts
> > after the removal, and partly this was because the "delay" is a separate
> > optimisation that we could apply even if it turned out the final patch
> > was not architecturally sound.
> > 
> > Now that we do not handle conflict aborts (preferring only systems that
> > handle BBML2 without ever raising aborts), the first issue is not a
> > problem. The reasoning behind the second patch is also a little bit
> > outdated, but I can see the logical split between a tlbi reorder, and
> > the removal of the tlbi. If this is truly redundant though, I would be
> > happy to squash the two into a single patch.
> 
> Thanks for the information.
> 
> Does patch #2 (reordering the tlbi) have any benefit on its own? I read
> "other threads will not see an invalid pagetable entry", but I am not sure
> that is correct. A concurrent HW page table walker would still find the
> invalid PTE? It's just a matter of TLB state.

I think I understand what you mean. I agree that it is possible for a
concurrent walk to see an invalid TLBI state, if it is on the same TLB
that the repaint is happening on. For other TLBs, the flush has not yet
propagated our invalidated PTEs (from `__ptep_get_and_clear()`) though?
That invalidation will only be seen by other TLBs after the
`__flush_tlb_range()`, so we should save a few faults because only
"local" threads will ever see the invalid entry, as opposed to all
threads that try to read our modified range? Or it is the case that I
have misunderstood something basic here, or that I have misinterpreted
what you have written?

> If there is no benefit in having patch #2 independently, I'd just squash
> them. Reordering to then remove is more complicated than just removing it
> IMHO.
> 
> -- 
> Cheers,
> 
> David / dhildenb
> 

-- 
Kind regards,
Miko?aj Lenczewski


From suzuki.poulose at arm.com  Mon Mar  3 03:35:19 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 3 Mar 2025 11:35:19 +0000
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <20250227144150.1667735-1-suzuki.poulose@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
Message-ID: <2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>

Hi Marek,


On 27/02/2025 14:41, Suzuki K Poulose wrote:
> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> half and shared top half. In Linux we treat the "top" bit of the IPA space as
> an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> and are managed by RMM. The "top" bit as attribute is only a software construct.
> 
> At present any device passed through to a Realm is treated as untrusted and the
> Realm uses bounce buffering for any DMA, using the "decrypted" (shared) DMA
> buffers (i.e., IPA with top bit set). In Linux, we only send the "DMA" address
> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are managed by the
> non-secure Host and thus it can be confusing for the host/device when an unmasked
> address is provided. Given there could be other hypervisors than Linux/KVM
> running Arm CCA guests, the Realm Guest must adhere to a single convention for
> the DMA address. This gets further complicated when we add support for trusted
> devices, which can DMA into the full Realm memory space, once accepted. Thus,
> a DMA masked address (with "top" bit lost) will prevent a trusted device from
> accessing a shared buffer.
> 
> To resolve this Arm has decided to standardise the DMA address used by the Realm
> to include the full IPA address bits (including the "top" bit, which Linux uses
> as an attribute). This implies, any DMA to a shared buffer must have the top bit
> of the IPA space set.
> 
> There is already a provision to do this in phys_to_dma* and dma_to_phys(), but
> that is specific to AMD SME and is quite the opposite of what we need for Arm CCA.
> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and clear the bit
> for "encrypted".
> 
> This series converts the existing __sme_* helpers to a bit more generalised versions :
> dma_addr_decrypted() and dma_encrypted(). Also, while converting a DMA address back
> to CPU physical address requires clearing off any "encryption/decryption" bits.
> I have named this "dma_addr_canonical()". (The other options are :
>    * dma_addr_clear_encryption - Well, not just for encryption, but we clear decryption
>      too, so not ideal.
>    * dma_addr_normal
>    * dma_addr_clear
>    * dma_addr_default
> 
> This also implies that the VMMs must take care to :
> 
>   1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>   2. Always mask the "top" bit off any IPA it receives from the Realm for DMA.
>      KVM already does that today and no changes are required.
> 
> A kvmtool branch with the changes above is available here [1]. There are two
> patches [2] & [3], that are really required on top of the Arm CCA support.
> 
> Ideally it would be good to get this backported to v6.13 stable kernel releases
> to make sure that they are compliant with this change.
> 

Please could you take a look at this series and let us know your
thoughts ? If you are happy with the changes, are you happy to pull
this through the DMA MAP tree ? The relevant bits have been reviewed/
acked by people (arm64 and AMD bits).

Kind regards
Suzuki


> Changes since v2:
>   Link: https://lkml.kernel.org/r/20250219220751.1276854-1-suzuki.poulose at arm.com
>    - Collect Acks & Reviews for Patch 1
>    - Rename helpers
>    	dma_encrypted		=> dma_addr_encrypted
> 	dma_decrypted		=> dma_addr_unencrypted
> 	dma_clear_encryption	=> dma_addr_canonical
>    - For Arm CCA, use PROT_NS_SHARED, set/clear only the top IPA bit.
>    - Drop dma_addr_encrypted() helper for Arm CCA as it is a NOP
> 
> Changes since v1
>   Link: https://lkml.kernel.org/r/20250212171411.951874-1-suzuki.poulose at arm.com
>   - Follow Robin's suggestion to generalise the DMA address conversion helpers
>     to provide dma_{encrypte,decrypted,clear_encryption}. See PATCH 2 for more
>     details.
>   - Add a fix to the ordering of "__sme_clr" for dma_to_phys (PATCH 1)
> 
> [1] git at git.gitlab.arm.com:linux-arm/kvmtool-cca.git cca/guest-dma-alias/v1
> [2] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/ea37a6eb968abe4c75be4a8a90808714657c2ef7
> [3] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/8afd0d5e6a7ee444dd0c1565fe94ecd831054a29
> 
> Cc: Will Deacon <will at kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Robin Murphy <robin.murphy at arm.com>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Christoph Hellwig <hch at lst.de>
> Cc: Marek Szyprowski <m.szyprowski at samsung.com>
> Cc: Tom Lendacky <thomas.lendacky at amd.com>
> Cc: Gavin Shan <gshan at redhat.com>
> 
> Suzuki K Poulose (3):
>    dma: Fix encryption bit clearing for dma_to_phys
>    dma: Introduce generic dma_addr_*crypted helpers
>    arm64: realm: Use aliased addresses for device DMA to shared buffers
> 
>   arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
>   include/linux/dma-direct.h           | 13 +++++++++----
>   include/linux/mem_encrypt.h          | 23 +++++++++++++++++++++++
>   3 files changed, 43 insertions(+), 4 deletions(-)
> 



From m-malladi at ti.com  Mon Mar  3 03:36:48 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 17:06:48 +0530
Subject: [PATCH net-next v3 3/3] net: ti: icssg-prueth: Add XDP support
In-Reply-To: <8f93a9a0-5d0c-47d6-9db6-af93acebf008@kernel.org>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <8f93a9a0-5d0c-47d6-9db6-af93acebf008@kernel.org>
Message-ID: <12576ce1-9db0-4136-9f84-3c6a72a07127@ti.com>



On 2/27/2025 9:07 PM, Roger Quadros wrote:
> 
> 
> On 24/02/2025 13:01, Meghana Malladi wrote:
>> From: Roger Quadros <rogerq at kernel.org>
>>
>> Add native XDP support. We do not support zero copy yet.
>>
>> Signed-off-by: Roger Quadros <rogerq at kernel.org>
>> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi at ti.com>
>> ---
>> Changes since v2 (v3-v2):
>> - Use page_pool contained in the page instead of using passing page_pool
>> (rx_chn) as part of swdata
>> - dev_sw_netstats_tx_add() instead of incrementing the stats directly
>> - Add missing ndev->stats.tx_dropped++ wherever applicable
>> - Move k3_cppi_desc_pool_alloc() before the DMA mapping for easier cleanup
>> on failure
>> - Replace rxp->napi_id with emac->napi_rx.napi_id in prueth_create_xdp_rxqs()
>>
>> All the above changes have been suggested by Roger Quadros <rogerq at kernel.org>
>>
>>   drivers/net/ethernet/ti/icssg/icssg_common.c | 219 +++++++++++++++++--
>>   drivers/net/ethernet/ti/icssg/icssg_prueth.c | 125 ++++++++++-
>>   drivers/net/ethernet/ti/icssg/icssg_prueth.h |  17 ++
>>   3 files changed, 346 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> index 01eeabe83eff..4716e24ea05d 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> @@ -98,11 +98,19 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
>>   {
>>   	struct cppi5_host_desc_t *first_desc, *next_desc;
>>   	dma_addr_t buf_dma, next_desc_dma;
>> +	struct prueth_swdata *swdata;
>>   	u32 buf_dma_len;
>>   
>>   	first_desc = desc;
>>   	next_desc = first_desc;
>>   
>> +	swdata = cppi5_hdesc_get_swdata(desc);
>> +	if (swdata->type == PRUETH_SWDATA_PAGE) {
>> +		page_pool_recycle_direct(swdata->data.page->pp,
>> +					 swdata->data.page);
>> +		goto free_desc;
>> +	}
>> +
>>   	cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len);
>>   	k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma);
>>   
>> @@ -126,6 +134,7 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
>>   		k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
>>   	}
>>   
>> +free_desc:
>>   	k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc);
>>   }
>>   EXPORT_SYMBOL_GPL(prueth_xmit_free);
>> @@ -139,6 +148,7 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>   	struct prueth_swdata *swdata;
>>   	struct prueth_tx_chn *tx_chn;
>>   	unsigned int total_bytes = 0;
>> +	struct xdp_frame *xdpf;
>>   	struct sk_buff *skb;
>>   	dma_addr_t desc_dma;
>>   	int res, num_tx = 0;
>> @@ -168,21 +178,28 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>   			continue;
>>   		}
>>   
>> -		if (swdata->type != PRUETH_SWDATA_SKB) {
>> +		switch (swdata->type) {
>> +		case PRUETH_SWDATA_SKB:
>> +			skb = swdata->data.skb;
>> +			dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
>> +			total_bytes += skb->len;
>> +			napi_consume_skb(skb, budget);
>> +			break;
>> +		case PRUETH_SWDATA_XDPF:
>> +			xdpf = swdata->data.xdpf;
>> +			dev_sw_netstats_tx_add(ndev, 1, xdpf->len);
>> +			total_bytes += xdpf->len;
>> +			xdp_return_frame(xdpf);
>> +			break;
>> +		default:
>>   			netdev_err(ndev, "tx_complete: invalid swdata type %d\n", swdata->type);
>>   			prueth_xmit_free(tx_chn, desc_tx);
>> +			ndev->stats.tx_dropped++;
>>   			budget++;
>>   			continue;
>>   		}
>>   
>> -		skb = swdata->data.skb;
>>   		prueth_xmit_free(tx_chn, desc_tx);
>> -
>> -		ndev = skb->dev;
>> -		ndev->stats.tx_packets++;
>> -		ndev->stats.tx_bytes += skb->len;
>> -		total_bytes += skb->len;
>> -		napi_consume_skb(skb, budget);
>>   		num_tx++;
>>   	}
>>   
>> @@ -541,7 +558,153 @@ void emac_rx_timestamp(struct prueth_emac *emac,
>>   	ssh->hwtstamp = ns_to_ktime(ns);
>>   }
>>   
>> -static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>> +/**
>> + * emac_xmit_xdp_frame - transmits an XDP frame
>> + * @emac: emac device
>> + * @xdpf: data to transmit
>> + * @page: page from page pool if already DMA mapped
>> + * @q_idx: queue id
>> + *
>> + * Return: XDP state
>> + */
>> +int emac_xmit_xdp_frame(struct prueth_emac *emac,
>> +			struct xdp_frame *xdpf,
>> +			struct page *page,
>> +			unsigned int q_idx)
>> +{
>> +	struct cppi5_host_desc_t *first_desc;
>> +	struct net_device *ndev = emac->ndev;
>> +	struct prueth_tx_chn *tx_chn;
>> +	dma_addr_t desc_dma, buf_dma;
>> +	struct prueth_swdata *swdata;
>> +	u32 *epib;
>> +	int ret;
>> +
> drop new line and arrange below declarations in reverse xmas tree order.
> 

As suggested by Dan, will drop these variabled and directly use them.

>> +	void *data = xdpf->data;
>> +	u32 pkt_len = xdpf->len;
>> +
>> +	if (q_idx >= PRUETH_MAX_TX_QUEUES) {
>> +		netdev_err(ndev, "xdp tx: invalid q_id %d\n", q_idx);
>> +		return ICSSG_XDP_CONSUMED;	/* drop */
>> +	}
>> +
>> +	tx_chn = &emac->tx_chns[q_idx];
>> +
>> +	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
>> +	if (!first_desc) {
>> +		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
>> +		goto drop_free_descs;	/* drop */
>> +	}
>> +
>> +	if (page) { /* already DMA mapped by page_pool */
>> +		buf_dma = page_pool_get_dma_addr(page);
>> +		buf_dma += xdpf->headroom + sizeof(struct xdp_frame);
>> +	} else { /* Map the linear buffer */
>> +		buf_dma = dma_map_single(tx_chn->dma_dev, data, pkt_len, DMA_TO_DEVICE);
>> +		if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
>> +			netdev_err(ndev, "xdp tx: failed to map data buffer\n");
>> +			goto drop_free_descs;	/* drop */
>> +		}
>> +	}
>> +
>> +	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
>> +			 PRUETH_NAV_PS_DATA_SIZE);
>> +	cppi5_hdesc_set_pkttype(first_desc, 0);
>> +	epib = first_desc->epib;
>> +	epib[0] = 0;
>> +	epib[1] = 0;
>> +
>> +	/* set dst tag to indicate internal qid at the firmware which is at
>> +	 * bit8..bit15. bit0..bit7 indicates port num for directed
>> +	 * packets in case of switch mode operation
>> +	 */
>> +	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
>> +	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
>> +	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
>> +	swdata = cppi5_hdesc_get_swdata(first_desc);
>> +	if (page) {
>> +		swdata->type = PRUETH_SWDATA_PAGE;
>> +		swdata->data.page = page;
>> +	} else {
>> +		swdata->type = PRUETH_SWDATA_XDPF;
>> +		swdata->data.xdpf = xdpf;
>> +	}
>> +
>> +	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
>> +	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
>> +
>> +	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
>> +	if (ret) {
>> +		netdev_err(ndev, "xdp tx: push failed: %d\n", ret);
>> +		goto drop_free_descs;
>> +	}
>> +
>> +	return ICSSG_XDP_TX;
>> +
>> +drop_free_descs:
>> +	prueth_xmit_free(tx_chn, first_desc);
>> +	return ICSSG_XDP_CONSUMED;
>> +}
>> +EXPORT_SYMBOL_GPL(emac_xmit_xdp_frame);
>> +
>> +/**
>> + * emac_run_xdp - run an XDP program
>> + * @emac: emac device
>> + * @xdp: XDP buffer containing the frame
>> + * @page: page with RX data if already DMA mapped
>> + *
>> + * Return: XDP state
>> + */
>> +static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
>> +			struct page *page)
>> +{
>> +	struct net_device *ndev = emac->ndev;
>> +	int err, result = ICSSG_XDP_PASS;
> 
> you could avoid initialization of result. see below.
> 
>> +	struct bpf_prog *xdp_prog;
>> +	struct xdp_frame *xdpf;
>> +	int q_idx;
>> +	u32 act;
>> +
>> +	xdp_prog = READ_ONCE(emac->xdp_prog);
>> +	act = bpf_prog_run_xdp(xdp_prog, xdp);
>> +	switch (act) {
>> +	case XDP_PASS:
>> +		break;
> instead of break how about?
> 		return ICSSG_XDP_PASS;
> 

I looked into CPSW XDP implementation and its same as what you suggested 
here. Will update this functon with your suggestions.

>> +	case XDP_TX:
>> +		/* Send packet to TX ring for immediate transmission */
>> +		xdpf = xdp_convert_buff_to_frame(xdp);
>> +		if (unlikely(!xdpf))
> 
> TX is dropped so here you need to
> 			ndev->stats.tx_dropped++;

Yes added it.

>> +			goto drop;
>> +
>> +		q_idx = smp_processor_id() % emac->tx_ch_num;
>> +		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
>> +		if (result == ICSSG_XDP_CONSUMED)
>> +			goto drop;
> 
> need to increment rx stats as we received the packet successfully?
> 

Yes I will do that.

>> +		break;
> instead,
> 		return ICSSG_XDP_TX;
> 

returning result here as it depends on what emac_xmit_xdp_frame() returns

>> +	case XDP_REDIRECT:
>> +		err = xdp_do_redirect(emac->ndev, xdp, xdp_prog);
>> +		if (err)
>> +			goto drop;
>> +		result = ICSSG_XDP_REDIR;
>> +		break;
> 
> replace above 2 by
> 		return ICSSG_XDP_REDIR;

I suppose you meant "replace above to by?" I have updated it.

>> +	default:
>> +		bpf_warn_invalid_xdp_action(emac->ndev, xdp_prog, act);
>> +		fallthrough;
>> +	case XDP_ABORTED:
>> +drop:
>> +		trace_xdp_exception(emac->ndev, xdp_prog, act);
>> +		fallthrough; /* handle aborts by dropping packet */
>> +	case XDP_DROP:
>> +		ndev->stats.tx_dropped++;
> 
> shouldn't this be
> 		ndev->stats.rx_dropped++;
> 

Yes correct. Thanks for finding this. Fixed it.

>> +		result = ICSSG_XDP_CONSUMED;
> 
> not required if we directly return this value below.
> 
>> +		page_pool_recycle_direct(emac->rx_chns.pg_pool, page);
>> +		break;
> 		return ICSSG_XDP_CONSUMED;
>> +	}
>> +
>> +	return result;
> 
> drop this

Done.
> 
>> +}
>> +
>> +static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, int *xdp_state)
>>   {
>>   	struct prueth_rx_chn *rx_chn = &emac->rx_chns;
>>   	u32 buf_dma_len, pkt_len, port_id = 0;
>> @@ -552,10 +715,12 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   	struct page *page, *new_page;
>>   	struct page_pool *pool;
>>   	struct sk_buff *skb;
>> +	struct xdp_buff xdp;
>>   	u32 *psdata;
>>   	void *pa;
>>   	int ret;
>>   
>> +	*xdp_state = 0;
>>   	pool = rx_chn->pg_pool;
>>   	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
>>   	if (ret) {
>> @@ -596,9 +761,21 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   		goto requeue;
>>   	}
>>   
>> -	/* prepare skb and send to n/w stack */
>>   	pa = page_address(page);
>> -	skb = napi_build_skb(pa, PAGE_SIZE);
> 
> We are running the xdp program after allocating the new page.
> How about running the xdp program first? if the packet has to be dropped
> then it is pointless to allocate a new page. We could just reuse the old page
> and save CPU cycles.
> 

What if the packet need not be dropped (it has been processed by XDP) 
Then we go to requeue, where new page is needed to map it to the next 
upcoming packet descriptor. Hence running XDP needs new_page.

>> +	if (emac->xdp_prog) {
>> +		xdp_init_buff(&xdp, PAGE_SIZE, &rx_chn->xdp_rxq);
>> +		xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false);
>> +
>> +		*xdp_state = emac_run_xdp(emac, &xdp, page);
>> +		if (*xdp_state == ICSSG_XDP_PASS)
>> +			skb = xdp_build_skb_from_buff(&xdp);
>> +		else
>> +			goto requeue;
>> +	} else {
>> +		/* prepare skb and send to n/w stack */
>> +		skb = napi_build_skb(pa, PAGE_SIZE);
>> +	}
>> +
>>   	if (!skb) {
>>   		ndev->stats.rx_dropped++;
>>   		page_pool_recycle_direct(pool, page);
> 
> instead of recycling the old page just reuse it
> 		new_page = page;
> 

With the above explanation I think allocating new_page is inevitable.

>> 		goto requeue;
>> 	}
> 
> here you can allocate the new page cause now we're sure old page
> has to be sent to user space.
> 

likewise to the above comment.

>> @@ -861,13 +1038,23 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
>>   	struct prueth_tx_chn *tx_chn = data;
>>   	struct cppi5_host_desc_t *desc_tx;
>>   	struct prueth_swdata *swdata;
>> +	struct xdp_frame *xdpf;
>>   	struct sk_buff *skb;
>>   
>>   	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
>>   	swdata = cppi5_hdesc_get_swdata(desc_tx);
>> -	if (swdata->type == PRUETH_SWDATA_SKB) {
>> +
>> +	switch (swdata->type) {
>> +	case PRUETH_SWDATA_SKB:
>>   		skb = swdata->data.skb;
>>   		dev_kfree_skb_any(skb);
>> +		break;
>> +	case PRUETH_SWDATA_XDPF:
>> +		xdpf = swdata->data.xdpf;
>> +		xdp_return_frame(xdpf);
>> +		break;
>> +	default:
>> +		break;
>>   	}
>>   
>>   	prueth_xmit_free(tx_chn, desc_tx);
>> @@ -904,15 +1091,18 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
>>   		PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA;
>>   	int flow = emac->is_sr1 ?
>>   		PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
>> +	int xdp_state_or = 0;
>>   	int num_rx = 0;
>>   	int cur_budget;
>> +	int xdp_state;
>>   	int ret;
>>   
>>   	while (flow--) {
>>   		cur_budget = budget - num_rx;
>>   
>>   		while (cur_budget--) {
>> -			ret = emac_rx_packet(emac, flow);
>> +			ret = emac_rx_packet(emac, flow, &xdp_state);
>> +			xdp_state_or |= xdp_state;
>>   			if (ret)
>>   				break;
>>   			num_rx++;
>> @@ -922,6 +1112,9 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
>>   			break;
>>   	}
>>   
>> +	if (xdp_state_or & ICSSG_XDP_REDIR)
>> +		xdp_do_flush();
>> +
>>   	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
>>   		if (unlikely(emac->rx_pace_timeout_ns)) {
>>   			hrtimer_start(&emac->rx_hrtimer,
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> index 3ff8c322f9d9..1acbf9e1bade 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> @@ -559,6 +559,33 @@ const struct icss_iep_clockops prueth_iep_clockops = {
>>   	.perout_enable = prueth_perout_enable,
>>   };
>>   
>> +static int prueth_create_xdp_rxqs(struct prueth_emac *emac)
>> +{
>> +	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
>> +	struct page_pool *pool = emac->rx_chns.pg_pool;
>> +	int ret;
>> +
>> +	ret = xdp_rxq_info_reg(rxq, emac->ndev, 0, emac->napi_rx.napi_id);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = xdp_rxq_info_reg_mem_model(rxq, MEM_TYPE_PAGE_POOL, pool);
>> +	if (ret)
>> +		xdp_rxq_info_unreg(rxq);
>> +
>> +	return ret;
>> +}
>> +
>> +static void prueth_destroy_xdp_rxqs(struct prueth_emac *emac)
>> +{
>> +	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
>> +
>> +	if (!xdp_rxq_info_is_reg(rxq))
>> +		return;
>> +
>> +	xdp_rxq_info_unreg(rxq);
>> +}
>> +
>>   static int icssg_prueth_add_mcast(struct net_device *ndev, const u8 *addr)
>>   {
>>   	struct net_device *real_dev;
>> @@ -780,10 +807,14 @@ static int emac_ndo_open(struct net_device *ndev)
>>   	if (ret)
>>   		goto free_tx_ts_irq;
>>   
>> -	ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
>> +	ret = prueth_create_xdp_rxqs(emac);
>>   	if (ret)
>>   		goto reset_rx_chn;
>>   
>> +	ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
>> +	if (ret)
>> +		goto destroy_xdp_rxqs;
>> +
>>   	for (i = 0; i < emac->tx_ch_num; i++) {
>>   		ret = k3_udma_glue_enable_tx_chn(emac->tx_chns[i].tx_chn);
>>   		if (ret)
>> @@ -809,6 +840,8 @@ static int emac_ndo_open(struct net_device *ndev)
>>   	 * any SKB for completion. So set false to free_skb
>>   	 */
>>   	prueth_reset_tx_chan(emac, i, false);
>> +destroy_xdp_rxqs:
>> +	prueth_destroy_xdp_rxqs(emac);
>>   reset_rx_chn:
>>   	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false);
>>   free_tx_ts_irq:
>> @@ -879,7 +912,7 @@ static int emac_ndo_stop(struct net_device *ndev)
>>   	k3_udma_glue_tdown_rx_chn(emac->rx_chns.rx_chn, true);
>>   
>>   	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, true);
>> -
>> +	prueth_destroy_xdp_rxqs(emac);
>>   	napi_disable(&emac->napi_rx);
>>   	hrtimer_cancel(&emac->rx_hrtimer);
>>   
>> @@ -1024,6 +1057,90 @@ static int emac_ndo_vlan_rx_del_vid(struct net_device *ndev,
>>   	return 0;
>>   }
>>   
>> +/**
>> + * emac_xdp_xmit - Implements ndo_xdp_xmit
>> + * @dev: netdev
>> + * @n: number of frames
>> + * @frames: array of XDP buffer pointers
>> + * @flags: XDP extra info
>> + *
>> + * Return: number of frames successfully sent. Failed frames
>> + * will be free'ed by XDP core.
>> + *
>> + * For error cases, a negative errno code is returned and no-frames
>> + * are transmitted (caller must handle freeing frames).
>> + **/
>> +static int emac_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
>> +			 u32 flags)
>> +{
>> +	struct prueth_emac *emac = netdev_priv(dev);
>> +	unsigned int q_idx;
>> +	int nxmit = 0;
>> +	int i;
>> +
>> +	q_idx = smp_processor_id() % emac->tx_ch_num;
>> +
>> +	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
>> +		return -EINVAL;
>> +
>> +	for (i = 0; i < n; i++) {
>> +		struct xdp_frame *xdpf = frames[i];
>> +		int err;
>> +
>> +		err = emac_xmit_xdp_frame(emac, xdpf, NULL, q_idx);
>> +		if (err != ICSSG_XDP_TX)
>> +			break;
>> +		nxmit++;
>> +	}
>> +
>> +	return nxmit;
>> +}
>> +
>> +/**
>> + * emac_xdp_setup - add/remove an XDP program
>> + * @emac: emac device
>> + * @bpf: XDP program
>> + *
>> + * Return: Always 0 (Success)
>> + **/
>> +static int emac_xdp_setup(struct prueth_emac *emac, struct netdev_bpf *bpf)
>> +{
>> +	struct bpf_prog *prog = bpf->prog;
>> +	xdp_features_t val;
>> +
>> +	val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
>> +	      NETDEV_XDP_ACT_NDO_XMIT;
>> +	xdp_set_features_flag(emac->ndev, val);
>> +
>> +	if (!emac->xdpi.prog && !prog)
>> +		return 0;
>> +
>> +	WRITE_ONCE(emac->xdp_prog, prog);
>> +
>> +	xdp_attachment_setup(&emac->xdpi, bpf);
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * emac_ndo_bpf - implements ndo_bpf for icssg_prueth
>> + * @ndev: network adapter device
>> + * @bpf: XDP program
>> + *
>> + * Return: 0 on success, error code on failure.
>> + **/
>> +static int emac_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
>> +{
>> +	struct prueth_emac *emac = netdev_priv(ndev);
>> +
>> +	switch (bpf->command) {
>> +	case XDP_SETUP_PROG:
>> +		return emac_xdp_setup(emac, bpf);
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +}
>> +
>>   static const struct net_device_ops emac_netdev_ops = {
>>   	.ndo_open = emac_ndo_open,
>>   	.ndo_stop = emac_ndo_stop,
>> @@ -1038,6 +1155,8 @@ static const struct net_device_ops emac_netdev_ops = {
>>   	.ndo_fix_features = emac_ndo_fix_features,
>>   	.ndo_vlan_rx_add_vid = emac_ndo_vlan_rx_add_vid,
>>   	.ndo_vlan_rx_kill_vid = emac_ndo_vlan_rx_del_vid,
>> +	.ndo_bpf = emac_ndo_bpf,
>> +	.ndo_xdp_xmit = emac_xdp_xmit,
>>   };
>>   
>>   static int prueth_netdev_init(struct prueth *prueth,
>> @@ -1066,6 +1185,8 @@ static int prueth_netdev_init(struct prueth *prueth,
>>   	emac->prueth = prueth;
>>   	emac->ndev = ndev;
>>   	emac->port_id = port;
>> +	emac->xdp_prog = NULL;
>> +	emac->ndev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
>>   	emac->cmd_wq = create_singlethread_workqueue("icssg_cmd_wq");
>>   	if (!emac->cmd_wq) {
>>   		ret = -ENOMEM;
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> index 3bbabd007129..0675919beb94 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> @@ -8,6 +8,8 @@
>>   #ifndef __NET_TI_ICSSG_PRUETH_H
>>   #define __NET_TI_ICSSG_PRUETH_H
>>   
>> +#include <linux/bpf.h>
>> +#include <linux/bpf_trace.h>
>>   #include <linux/etherdevice.h>
>>   #include <linux/genalloc.h>
>>   #include <linux/if_vlan.h>
>> @@ -134,6 +136,7 @@ struct prueth_rx_chn {
>>   	unsigned int irq[ICSSG_MAX_RFLOWS];	/* separate irq per flow */
>>   	char name[32];
>>   	struct page_pool *pg_pool;
>> +	struct xdp_rxq_info xdp_rxq;
>>   };
>>   
>>   enum prueth_swdata_type {
>> @@ -141,6 +144,7 @@ enum prueth_swdata_type {
>>   	PRUETH_SWDATA_SKB,
>>   	PRUETH_SWDATA_PAGE,
>>   	PRUETH_SWDATA_CMD,
>> +	PRUETH_SWDATA_XDPF,
>>   };
>>   
>>   struct prueth_swdata {
>> @@ -149,6 +153,7 @@ struct prueth_swdata {
>>   		struct sk_buff *skb;
>>   		struct page *page;
>>   		u32 cmd;
>> +		struct xdp_frame *xdpf;
>>   	} data;
>>   };
>>   
>> @@ -159,6 +164,12 @@ struct prueth_swdata {
>>   
>>   #define PRUETH_MAX_TX_TS_REQUESTS	50 /* Max simultaneous TX_TS requests */
>>   
>> +/* XDP BPF state */
>> +#define ICSSG_XDP_PASS           0
>> +#define ICSSG_XDP_CONSUMED       BIT(0)
>> +#define ICSSG_XDP_TX             BIT(1)
>> +#define ICSSG_XDP_REDIR          BIT(2)
>> +
>>   /* Minimum coalesce time in usecs for both Tx and Rx */
>>   #define ICSSG_MIN_COALESCE_USECS 20
>>   
>> @@ -227,6 +238,8 @@ struct prueth_emac {
>>   	unsigned long rx_pace_timeout_ns;
>>   
>>   	struct netdev_hw_addr_list vlan_mcast_list[MAX_VLAN_ID];
>> +	struct bpf_prog *xdp_prog;
>> +	struct xdp_attachment_info xdpi;
>>   };
>>   
>>   /* The buf includes headroom compatible with both skb and xdpf */
>> @@ -465,5 +478,9 @@ void prueth_put_cores(struct prueth *prueth, int slice);
>>   
>>   /* Revision specific helper */
>>   u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns);
>> +int emac_xmit_xdp_frame(struct prueth_emac *emac,
>> +			struct xdp_frame *xdpf,
>> +			struct page *page,
>> +			unsigned int q_idx);
>>   
>>   #endif /* __NET_TI_ICSSG_PRUETH_H */
> 



From peter.chen at cixtech.com  Mon Mar  3 03:38:47 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 3 Mar 2025 19:38:47 +0800
Subject: [PATCH v3 6/6] arm64: dts: cix: add initial CIX P1(SKY1) dts
 support
In-Reply-To: <86r03ip0kf.wl-maz@kernel.org>
References: <20250227120619.1741431-1-peter.chen@cixtech.com>
 <20250227120619.1741431-7-peter.chen@cixtech.com>
 <86r03ip0kf.wl-maz@kernel.org>
Message-ID: <Z8WUxyJT1fdHKo67@nchen-desktop>

On 25-02-28 15:10:24, Marc Zyngier wrote:

Hi Marc,

Thanks for your detail review.

> > +
> > +             cpu10: cpu at a00 {
> > +                     compatible = "arm,cortex-a720";
> > +                     enable-method = "psci";
> > +                     reg = <0x0 0xa00>;
> > +                     device_type = "cpu";
> > +                     capacity-dmips-mhz = <1024>;
> > +             };
> > +
> > +             cpu11: cpu at b00 {
> > +                     compatible = "arm,cortex-a720";
> > +                     enable-method = "psci";
> > +                     reg = <0x0 0xb00>;
> > +                     device_type = "cpu";
> > +                     capacity-dmips-mhz = <1024>;
> > +             };
> 
> Given that half the A720s are advertised with lower clock speed, how
> comes they all have the same capacity?

According to Documentation/devicetree/bindings/cpu/cpu-capacity.txt
"capacity-dmips-mhz" is u32 value representing CPU capacity expressed
in normalized DMIPS/MHz, it means CPU capability per MHz. For sky1
SoC, both middle and big cores are A720, so their capability per MHz
are the same.

> > +
> > +     pmu-a520 {
> > +             compatible = "arm,cortex-a520-pmu";
> > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > +     };
> > +
> > +     pmu-a720 {
> > +             compatible = "arm,cortex-a720-pmu";
> > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > +     };
> 
> This is wrong. The default configuration for PPIs is to expose the
> *same* device on all CPUs. You must use PPI affinities for your PMUs.
> Please see the GICv3 binding for the details.

We have discussed internally, we have not seen the benefits routing
different PPI interrupt to dedicated CPUs. Any use cases?

I prefer changing pmu nodes as one generic Armv8 PMU node. Is it accepted?
Or must I keep both pmu for A520 and A720, and add PPI affinities to
describe hardware well?

> 
> > +
> > +     pmu-spe {
> > +             compatible = "arm,statistical-profiling-extension-v1";
> > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW>;
> > +     };
> > +
> > +     psci {
> > +             compatible = "arm,psci-1.0";
> > +             method = "smc";
> > +     };
> > +
> > +     soc at 0 {
> > +             compatible = "simple-bus";
> > +             ranges = <0 0 0 0 0x20 0>;
> > +             dma-ranges;
> > +             #address-cells = <2>;
> > +             #size-cells = <2>;
> > +
> > +             gic: interrupt-controller at e010000 {
> > +                     compatible = "arm,gic-v3";
> > +                     reg = <0x0 0x0e010000 0 0x10000>,       /* GICD */
> > +                           <0x0 0x0e090000 0 0x300000>;       /* GICR * 12 */
> > +                     interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
> > +                     #interrupt-cells = <3>;
> 
> This will need to be bumped up to 4, and all the interrupt specifiers adjusted.

Depends on if PPI affinities is must.

> 
> > +                     interrupt-controller;
> > +                     #redistributor-regions = <1>;
> 
> Drop this, this is useless. It is pretty obvious that there is a
> single RD region, and 1 is the default.
> 
> > +                     redistributor-stride = <0 0x40000>;
> 
> Drop this. This is a standard GIC700 that doesn't need any help
> computing the stride as it obeys the architecture.

Will drop above two properties.

> 
> > +                     #address-cells = <2>;
> > +                     #size-cells = <2>;
> 
> I don't understand why you repeat this on every sub-nodes.

Because there is a child node for gic_its below

> 
> > +                     ranges;
> > +
> > +                     gic_its: msi-controller at e050000 {
> > +                             compatible = "arm,gic-v3-its";
> > +                             reg = <0x0 0x0e050000 0x0 0x30000>;
> > +                             msi-controller;
> > +                             #msi-cells = <1>;
> > +                     };
> > +             };
> > +     };
> > +
> > +     timer {
> > +             compatible = "arm,armv8-timer";
> > +             interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
> > +             interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
> > +             clock-frequency = <1000000000>;
> 
> Drop this. The firmware already sets CNTFRQ_EL0 to the correct value,
> it seems. And if it doesn't, please fix the firmware.

Yes, you are right, firmware configures it, I will delete it at next
version.

> 
> > +             arm,no-tick-in-suspend;
> 
> Why do you need this? Is the HW so broken that you have implemented
> the global counter in a power domain that isn't always on?
> 

Not hardware broken, just arch timer will be powered off at cpu idle
and system suspend due to power consumption reason.

-- 

Best regards,
Peter


From mike.rudenko at gmail.com  Mon Mar  3 03:40:09 2025
From: mike.rudenko at gmail.com (Mikhail Rudenko)
Date: Mon, 03 Mar 2025 14:40:09 +0300
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in
 dma-contig
In-Reply-To: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
Message-ID: <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>

When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
commit 129134e5415d ("media: media/v4l2: remove
V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
no-ops, making cache maintenance for non-coherent dmabufs allocated by
dma-contig impossible.

Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
{flush,invalidate}_kernel_vmap_range calls to
vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
buffers.

Fixes: c0acf9cfeee0 ("media: videobuf2: handle V4L2_MEMORY_FLAG_NON_COHERENT flag")
Cc: stable at vger.kernel.org
Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
---
 .../media/common/videobuf2/videobuf2-dma-contig.c  | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7bc888a84a95d5 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -427,6 +427,17 @@ static int
 vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
 				   enum dma_data_direction direction)
 {
+	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (!buf->non_coherent_mem)
+		return 0;
+
+	if (buf->vaddr)
+		invalidate_kernel_vmap_range(buf->vaddr, buf->size);
+
+	dma_sync_sgtable_for_cpu(buf->dev, sgt, direction);
+
 	return 0;
 }
 
@@ -434,6 +445,17 @@ static int
 vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
 				 enum dma_data_direction direction)
 {
+	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (!buf->non_coherent_mem)
+		return 0;
+
+	if (buf->vaddr)
+		flush_kernel_vmap_range(buf->vaddr, buf->size);
+
+	dma_sync_sgtable_for_device(buf->dev, sgt, direction);
+
 	return 0;
 }
 

-- 
2.48.1



From mike.rudenko at gmail.com  Mon Mar  3 03:40:08 2025
From: mike.rudenko at gmail.com (Mikhail Rudenko)
Date: Mon, 03 Mar 2025 14:40:08 +0300
Subject: [PATCH v4 0/2] Allow non-coherent video capture buffers on
 Rockchip ISP V1
Message-ID: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>

This small series adds support for non-coherent video capture buffers
on Rockchip ISP V1. Patch 1 fixes cache management for dmabuf's
allocated by dma-contig allocator. Patch 2 allows non-coherent
allocations on the rkisp1 capture queue. Some timing measurements are
provided in the commit message of patch 2.

Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
---
Changes in v4:
- rebase to media/next
- use `direction` instead of `buf->dma_dir` in dma_sync_sgtable_*
- Link to v3: https://lore.kernel.org/r/20250128-b4-rkisp-noncoherent-v3-0-baf39c997d2a at gmail.com

Changes in v3:
- ignore skip_cache_sync_* flags in vb2_dc_dmabuf_ops_{begin,end}_cpu_access
- invalidate/flush kernel mappings as appropriate if they exist
- use dma_sync_sgtable_* instead of dma_sync_sg_*
- Link to v2: https://lore.kernel.org/r/20250115-b4-rkisp-noncoherent-v2-0-0853e1a24012 at gmail.com

Changes in v2:
- Fix vb2_dc_dmabuf_ops_{begin,end}_cpu_access() for non-coherent buffers.
- Add cache management timing information to patch 2 commit message.
- Link to v1: https://lore.kernel.org/r/20250102-b4-rkisp-noncoherent-v1-1-bba164f7132c at gmail.com

---
Mikhail Rudenko (2):
      media: videobuf2: Fix dmabuf cache sync/flush in dma-contig
      media: rkisp1: Allow non-coherent video capture buffers

 .../media/common/videobuf2/videobuf2-dma-contig.c  | 22 ++++++++++++++++++++++
 .../platform/rockchip/rkisp1/rkisp1-capture.c      |  1 +
 2 files changed, 23 insertions(+)
---
base-commit: b2c4bf0c102084e77ed1b12090d77a76469a6814
change-id: 20241231-b4-rkisp-noncoherent-ad6e7c7a68ba

Best regards,
-- 
Mikhail Rudenko <mike.rudenko at gmail.com>



From mike.rudenko at gmail.com  Mon Mar  3 03:40:10 2025
From: mike.rudenko at gmail.com (Mikhail Rudenko)
Date: Mon, 03 Mar 2025 14:40:10 +0300
Subject: [PATCH v4 2/2] media: rkisp1: Allow non-coherent video capture
 buffers
In-Reply-To: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
Message-ID: <20250303-b4-rkisp-noncoherent-v4-2-e32e843fb6ef@gmail.com>

Currently, the rkisp1 driver always uses coherent DMA allocations for
video capture buffers. However, on some platforms, using non-coherent
buffers can improve performance, especially when CPU processing of
MMAP'ed video buffers is required.

For example, on the Rockchip RK3399 running at maximum CPU frequency,
the time to memcpy a frame from a 1280x720 XRGB32 MMAP'ed buffer to a
malloc'ed userspace buffer decreases from 7.7 ms to 1.1 ms when using
non-coherent DMA allocation. When doing cache management with
DMA_BUF_IOCTL_SYNC, DMA_BUF_SYNC_START and DMA_BUF_SYNC_END operations
take around 270 us each.

This change allows userspace to request the allocation of non-coherent
buffers. Note that the behavior for existing users will remain unchanged
unless they explicitly set the V4L2_MEMORY_FLAG_NON_COHERENT flag when
allocating buffers.

Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
---
 drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
index 6dcefd144d5abe358323e37ac6133c6134ac636e..c94f7d1d73a92646457a27da20726ec6f92e7717 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
@@ -1563,6 +1563,7 @@ static int rkisp1_register_capture(struct rkisp1_capture *cap)
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	q->lock = &node->vlock;
 	q->dev = cap->rkisp1->dev;
+	q->allow_cache_hints = 1;
 	ret = vb2_queue_init(q);
 	if (ret) {
 		dev_err(cap->rkisp1->dev,

-- 
2.48.1



From david at redhat.com  Mon Mar  3 03:42:11 2025
From: david at redhat.com (David Hildenbrand)
Date: Mon, 3 Mar 2025 12:42:11 +0100
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <20250303105539.GA74129@e133081.arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
 <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
 <20250303094947.GB13345@e133081.arm.com>
 <7e987f17-ffcb-45e0-8588-2d569d90f776@redhat.com>
 <20250303105539.GA74129@e133081.arm.com>
Message-ID: <0ff27dbb-401b-4793-be70-1ff9c8010e4a@redhat.com>

On 03.03.25 11:55, Miko?aj Lenczewski wrote:
> On Mon, Mar 03, 2025 at 10:57:21AM +0100, David Hildenbrand wrote:
>> On 03.03.25 10:49, Miko?aj Lenczewski wrote:
>>> Hi David,
>>>
>>> Thanks for taking the time to review.
>>>
>>> On Mon, Mar 03, 2025 at 10:17:12AM +0100, David Hildenbrand wrote:
>>>> On 28.02.25 19:24, Miko?aj Lenczewski wrote:
>>>>> If we support bbml2 without conflict aborts, we can avoid the final
>>>>> flush and have hardware manage the tlb entries for us. Avoiding flushes
>>>>> is a win.
>>>>>
>>>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>>>> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
>>>>> ---
>>>>>     arch/arm64/mm/contpte.c | 3 ---
>>>>>     1 file changed, 3 deletions(-)
>>>>>
>>>>> diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
>>>>> index 145530f706a9..77ed03b30b72 100644
>>>>> --- a/arch/arm64/mm/contpte.c
>>>>> +++ b/arch/arm64/mm/contpte.c
>>>>> @@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
>>>>>     		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>>>>>     	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
>>>>> -
>>>>> -	if (system_supports_bbml2_noabort())
>>>>> -		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>>>>>     }
>>>>>     void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
>>>>
>>>> What's the point of not squashing this into #2? :)
>>>>
>>>> If this split was requested during earlier review, at least seeing patch #2
>>>> on its own confused me.
>>>
>>> This split is a holdover from an earlier patchset, where it was still
>>> unknown whether the removal of the second flush was permitted with
>>> BBML2. Partly this was due to us being worried about conflict aborts
>>> after the removal, and partly this was because the "delay" is a separate
>>> optimisation that we could apply even if it turned out the final patch
>>> was not architecturally sound.
>>>
>>> Now that we do not handle conflict aborts (preferring only systems that
>>> handle BBML2 without ever raising aborts), the first issue is not a
>>> problem. The reasoning behind the second patch is also a little bit
>>> outdated, but I can see the logical split between a tlbi reorder, and
>>> the removal of the tlbi. If this is truly redundant though, I would be
>>> happy to squash the two into a single patch.
>>
>> Thanks for the information.
>>
>> Does patch #2 (reordering the tlbi) have any benefit on its own? I read
>> "other threads will not see an invalid pagetable entry", but I am not sure
>> that is correct. A concurrent HW page table walker would still find the
>> invalid PTE? It's just a matter of TLB state.
> 
> I think I understand what you mean. I agree that it is possible for a
> concurrent walk to see an invalid TLBI state, if it is on the same TLB
> that the repaint is happening on. For other TLBs, the flush has not yet
> propagated our invalidated PTEs (from `__ptep_get_and_clear()`) though?

What I am saying is: if there is no TLB entry yet, HW will walk the page 
table to find no present PTE and trigger a fault.

> That invalidation will only be seen by other TLBs after the
> `__flush_tlb_range()`, so we should save a few faults because only
> "local" threads will ever see the invalid entry, as opposed to all
> threads that try to read our modified range?

So what you say is, that deferring the flush means that if there is 
already a TLB entry, flushing deferred reduces the likelihood that a 
page table walk is triggered that could find no present PTE: 
consequently, reducing the likelihood that a page fault is triggered.

(I use the word likelihood, because I assume other action could result 
in a TLB entry getting flushed in the meantime, such as TLB entry reuse)

Correct?

Or it is the case that I
> have misunderstood something basic here, or that I have misinterpreted
> what you have written?

No, that makes it clearer, thanks.

-- 
Cheers,

David / dhildenb



From Cloud.Zhang at mediatek.com  Mon Mar  3 03:45:07 2025
From: Cloud.Zhang at mediatek.com (mtk22730)
Date: Mon, 3 Mar 2025 19:45:07 +0800
Subject: [v2] spi: spi-mtk-nor: Modify the clock architecture of nor controller
Message-ID: <20250303114540.1617-1-Cloud.Zhang@mediatek.com>

The clocks used by different platforms are not same. So it is
necessary to modify the clock architecture to be adaptable to more
platforms.

Signed-off-by: Cloud Zhang <cloud.zhang at mediatek.com>
---
Changes in v2:
  -Use clk_bulk_xxx related functions to enable/disable clocks.

Changes in v1:
  -Add new function mtk_nor_parse_clk() to parse nor clock parameters.
---
---
 drivers/spi/spi-mtk-nor.c | 103 ++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 49 deletions(-)

diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index 85ab5ce96c4d..4863b9cb2706 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -99,6 +99,8 @@
 
 #define CLK_TO_US(sp, clkcnt)		DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)
 
+#define MAX_CLOCK_CNT		6
+
 struct mtk_nor_caps {
 	u8 dma_bits;
 
@@ -116,10 +118,8 @@ struct mtk_nor {
 	void __iomem *base;
 	u8 *buffer;
 	dma_addr_t buffer_dma;
-	struct clk *spi_clk;
-	struct clk *ctlr_clk;
-	struct clk *axi_clk;
-	struct clk *axi_s_clk;
+	struct clk_bulk_data clocks[MAX_CLOCK_CNT];
+	int clock_cnt;
 	unsigned int spi_freq;
 	bool wbuf_en;
 	bool has_irq;
@@ -703,44 +703,68 @@ static int mtk_nor_transfer_one_message(struct spi_controller *host,
 
 static void mtk_nor_disable_clk(struct mtk_nor *sp)
 {
-	clk_disable_unprepare(sp->spi_clk);
-	clk_disable_unprepare(sp->ctlr_clk);
-	clk_disable_unprepare(sp->axi_clk);
-	clk_disable_unprepare(sp->axi_s_clk);
+	clk_bulk_disable_unprepare(sp->clock_cnt, sp->clocks);
 }
 
 static int mtk_nor_enable_clk(struct mtk_nor *sp)
 {
 	int ret;
+	int i;
 
-	ret = clk_prepare_enable(sp->spi_clk);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare_enable(sp->ctlr_clk);
+	ret = clk_bulk_prepare_enable(sp->clock_cnt, sp->clocks);
 	if (ret) {
-		clk_disable_unprepare(sp->spi_clk);
+		dev_err(sp->dev, "enable clk failed\n");
 		return ret;
 	}
 
-	ret = clk_prepare_enable(sp->axi_clk);
-	if (ret) {
-		clk_disable_unprepare(sp->spi_clk);
-		clk_disable_unprepare(sp->ctlr_clk);
-		return ret;
-	}
+	for (i = 0; i < sp->clock_cnt; i++) {
+		if (IS_ERR(sp->clocks[i].clk)) {
+			dev_err(sp->dev, "get %s fail\n", sp->clocks[i].id);
+			return PTR_ERR(sp->clocks[i].clk);
+		}
 
-	ret = clk_prepare_enable(sp->axi_s_clk);
-	if (ret) {
-		clk_disable_unprepare(sp->spi_clk);
-		clk_disable_unprepare(sp->ctlr_clk);
-		clk_disable_unprepare(sp->axi_clk);
-		return ret;
+		if (!strcmp(sp->clocks[i].id, "spi"))
+			sp->spi_freq = clk_get_rate(sp->clocks[i].clk);
 	}
 
 	return 0;
 }
 
+static int mtk_nor_parse_clk(struct device *dev, struct mtk_nor *sp)
+{
+	struct device_node *np = dev->of_node;
+	int ret;
+	const char *name;
+	int cnt, i;
+
+	cnt = of_property_count_strings(np, "clock-names");
+	if (!cnt || (cnt == -EINVAL)) {
+		dev_err(dev, "Unable to find clocks\n");
+		ret = -EINVAL;
+		goto out;
+	} else if (cnt < 0) {
+		dev_err(dev, "Count clock strings failed, err %d\n", cnt);
+		ret = cnt;
+		goto out;
+	}
+
+	sp->clock_cnt = cnt;
+	for (i = 0; i < cnt; i++) {
+		ret = of_property_read_string_index(np, "clock-names", i, &name);
+		if (ret) {
+			dev_err(dev, "failed to get clock string\n");
+			return ret;
+		}
+
+		sp->clocks[i].id = name;
+	}
+
+	ret = devm_clk_bulk_get(dev, sp->clock_cnt, sp->clocks);
+
+out:
+	return ret;
+}
+
 static void mtk_nor_init(struct mtk_nor *sp)
 {
 	writel(0, sp->base + MTK_NOR_REG_IRQ_EN);
@@ -813,29 +837,12 @@ static int mtk_nor_probe(struct platform_device *pdev)
 	struct mtk_nor *sp;
 	struct mtk_nor_caps *caps;
 	void __iomem *base;
-	struct clk *spi_clk, *ctlr_clk, *axi_clk, *axi_s_clk;
 	int ret, irq;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	spi_clk = devm_clk_get(&pdev->dev, "spi");
-	if (IS_ERR(spi_clk))
-		return PTR_ERR(spi_clk);
-
-	ctlr_clk = devm_clk_get(&pdev->dev, "sf");
-	if (IS_ERR(ctlr_clk))
-		return PTR_ERR(ctlr_clk);
-
-	axi_clk = devm_clk_get_optional(&pdev->dev, "axi");
-	if (IS_ERR(axi_clk))
-		return PTR_ERR(axi_clk);
-
-	axi_s_clk = devm_clk_get_optional(&pdev->dev, "axi_s");
-	if (IS_ERR(axi_s_clk))
-		return PTR_ERR(axi_s_clk);
-
 	caps = (struct mtk_nor_caps *)of_device_get_match_data(&pdev->dev);
 
 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(caps->dma_bits));
@@ -868,10 +875,6 @@ static int mtk_nor_probe(struct platform_device *pdev)
 	sp->wbuf_en = false;
 	sp->ctlr = ctlr;
 	sp->dev = &pdev->dev;
-	sp->spi_clk = spi_clk;
-	sp->ctlr_clk = ctlr_clk;
-	sp->axi_clk = axi_clk;
-	sp->axi_s_clk = axi_s_clk;
 	sp->caps = caps;
 	sp->high_dma = caps->dma_bits > 32;
 	sp->buffer = dmam_alloc_coherent(&pdev->dev,
@@ -885,11 +888,13 @@ static int mtk_nor_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = mtk_nor_enable_clk(sp);
+	ret = mtk_nor_parse_clk(sp->dev, sp);
 	if (ret < 0)
 		return ret;
 
-	sp->spi_freq = clk_get_rate(sp->spi_clk);
+	ret = mtk_nor_enable_clk(sp);
+	if (ret < 0)
+		return ret;
 
 	mtk_nor_init(sp);
 
-- 
2.46.0



From sudeep.holla at arm.com  Mon Mar  3 03:48:45 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon,  3 Mar 2025 11:48:45 +0000
Subject: [PATCH] firmware: arm_ffa: Set dma_mask for ffa devices
In-Reply-To: <e3dd8042ac680bd74b6580c25df855d092079c18.1737107520.git.viresh.kumar@linaro.org>
References: <e3dd8042ac680bd74b6580c25df855d092079c18.1737107520.git.viresh.kumar@linaro.org>
Message-ID: <174100249569.1456.13505107409018325740.b4-ty@arm.com>

On Fri, 17 Jan 2025 15:35:52 +0530, Viresh Kumar wrote:
> Set dma_mask for FFA devices, otherwise DMA allocation using the device pointer
> lead to following warning:
>
> WARNING: CPU: 1 PID: 1 at kernel/dma/mapping.c:597 dma_alloc_attrs+0xe0/0x124
>
>
Applied to sudeep.holla/linux (for-next/ffa/updates), thanks!

[1/1] firmware: arm_ffa: Set dma_mask for ffa devices
      https://git.kernel.org/sudeep.holla/c/cc0aac7ca17e
--
Regards,
Sudeep



From m-malladi at ti.com  Mon Mar  3 03:49:28 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 17:19:28 +0530
Subject: [EXTERNAL] Re: [PATCH net-next v3 2/3] net: ti: icssg-prueth:
 introduce and use prueth_swdata struct for SWDATA
In-Reply-To: <41fbeb70-bf49-4751-b4ba-6b122a45233d@stanley.mountain>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-3-m-malladi@ti.com>
 <41fbeb70-bf49-4751-b4ba-6b122a45233d@stanley.mountain>
Message-ID: <06d2b616-9f11-46ae-91f7-e97f86f9f24c@ti.com>



On 2/26/2025 3:59 PM, Dan Carpenter wrote:
> On Mon, Feb 24, 2025 at 04:?31:?01PM +0530, Meghana Malladi wrote: > 
> From: Roger Quadros <rogerq@?kernel.?org> > > We have different cases 
> for SWDATA (skb, page, cmd, etc) > so it is better to have a dedicated 
> data structure for
> ZjQcmQRYFpfptBannerStart
> This message was sent from outside of Texas Instruments.
> Do not click links or open attachments unless you recognize the source 
> of this email and know the content is safe.
> Report?Suspicious
> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK! 
> uldqnT1FPMdbygXOdhMC_1iqujTzdK2ZTrOjiy9hZrrhggm_lCduTFVqMq5QnhhjXmDeSX6KQhxE9U6zpHeghHYcqYQiiHpSSbljHpY$>
> ZjQcmQRYFpfptBannerEnd
> 
> On Mon, Feb 24, 2025 at 04:31:01PM +0530, Meghana Malladi wrote:
>> From: Roger Quadros <rogerq at kernel.org>
>> 
>> We have different cases for SWDATA (skb, page, cmd, etc)
>> so it is better to have a dedicated data structure for that.
>> We can embed the type field inside the struct and use it
>> to interpret the data in completion handlers.
>> 
>> Increase SWDATA size to 48 so we have some room to add
>> more data if required.
> 
> What is the "SWDATA size"?  Where is that specified?  Is
> that a variable or a define or the size of a struct or
> what?
> 

Will be removing this line, since "increase SWDATA size" change is not 
applicable anymore. It is a macro PRUETH_NAV_SW_DATA_SIZE used to define 
the size held for swdata.

>> 
>> Signed-off-by: Roger Quadros <rogerq at kernel.org>
>> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi at ti.com>
>> ---
>> Changes since v2 (v3-v2):
>> - Fix leaking tx descriptor in emac_tx_complete_packets()
>> - Free rx descriptor if swdata type is not page in emac_rx_packet()
>> - Revert back the size of PRUETH_NAV_SW_DATA_SIZE
>> - Use build time check for prueth_swdata size
>> - re-write prueth_swdata to have enum type as first member in the struct
>> and prueth_data union embedded in the struct
>> 
>> All the above changes have been suggested by Roger Quadros <rogerq at kernel.org>
>> 
>>  drivers/net/ethernet/ti/icssg/icssg_common.c  | 52 +++++++++++++------
>>  drivers/net/ethernet/ti/icssg/icssg_prueth.c  |  3 ++
>>  drivers/net/ethernet/ti/icssg/icssg_prueth.h  | 16 ++++++
>>  .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  4 +-
>>  4 files changed, 57 insertions(+), 18 deletions(-)
>> 
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> index acbb79ad8b0c..01eeabe83eff 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> @@ -136,12 +136,12 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>  	struct net_device *ndev = emac->ndev;
>>  	struct cppi5_host_desc_t *desc_tx;
>>  	struct netdev_queue *netif_txq;
>> +	struct prueth_swdata *swdata;
>>  	struct prueth_tx_chn *tx_chn;
>>  	unsigned int total_bytes = 0;
>>  	struct sk_buff *skb;
>>  	dma_addr_t desc_dma;
>>  	int res, num_tx = 0;
>> -	void **swdata;
>>  
>>  	tx_chn = &emac->tx_chns[chn];
>>  
>> @@ -163,12 +163,19 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>  		swdata = cppi5_hdesc_get_swdata(desc_tx);
>>  
>>  		/* was this command's TX complete? */
>> -		if (emac->is_sr1 && *(swdata) == emac->cmd_data) {
>> +		if (emac->is_sr1 && (void *)(swdata) == emac->cmd_data) {
> 
> I don't think this conversion is correct.  You still need to say:
> 
> 		if (emac->is_sr1 && swdata->data.something == emac->cmd_data) {
> 
> Where something is probably "page".
> 

Yes you are right. This needs to be changes to:

if (emac->is_sr1 && swdata->data.cmd== emac->cmd_data) {

This issue can be addressed more cleanly with the fix Roger mentioned 
here: 
https://lore.kernel.org/all/3d3d180a-12b7-4bee-8172-700f0dae2439 at kernel.org/

> regards,
> dan carpenter
> 
>>  			prueth_xmit_free(tx_chn, desc_tx);
>>  			continue;
>>  		}
>>  
>> -		skb = *(swdata);
>> +		if (swdata->type != PRUETH_SWDATA_SKB) {
>> +			netdev_err(ndev, "tx_complete: invalid swdata type %d\n", swdata->type);
>> +			prueth_xmit_free(tx_chn, desc_tx);
>> +			budget++;
>> +			continue;
>> +		}
> 



From miko.lenczewski at arm.com  Mon Mar  3 03:52:44 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 11:52:44 +0000
Subject: [PATCH v2 3/4] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <0ff27dbb-401b-4793-be70-1ff9c8010e4a@redhat.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-5-miko.lenczewski@arm.com>
 <f270bb5d-aa54-45d3-89ed-2b757ab3a4b0@redhat.com>
 <20250303094947.GB13345@e133081.arm.com>
 <7e987f17-ffcb-45e0-8588-2d569d90f776@redhat.com>
 <20250303105539.GA74129@e133081.arm.com>
 <0ff27dbb-401b-4793-be70-1ff9c8010e4a@redhat.com>
Message-ID: <20250303115244.GB74129@e133081.arm.com>

> > I think I understand what you mean. I agree that it is possible for a
> > concurrent walk to see an invalid TLBI state, if it is on the same TLB
> > that the repaint is happening on. For other TLBs, the flush has not yet
> > propagated our invalidated PTEs (from `__ptep_get_and_clear()`) though?
> 
> What I am saying is: if there is no TLB entry yet, HW will walk the page
> table to find no present PTE and trigger a fault.

Yes, that is 100% correct. I believe that this is unavoidable.

> > That invalidation will only be seen by other TLBs after the
> > `__flush_tlb_range()`, so we should save a few faults because only
> > "local" threads will ever see the invalid entry, as opposed to all
> > threads that try to read our modified range?
> 
> So what you say is, that deferring the flush means that if there is already
> a TLB entry, flushing deferred reduces the likelihood that a page table walk
> is triggered that could find no present PTE: consequently, reducing the
> likelihood that a page fault is triggered.
> 
> (I use the word likelihood, because I assume other action could result in a
> TLB entry getting flushed in the meantime, such as TLB entry reuse)
> 
> Correct?

Yes, and your language here is clearer than the original commit message
(and cover letter). Will amend it to be closer to your wording.

-- 
Kind regards,
Miko?aj Lenczewski


From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:06:52 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:06:52 +0100
Subject: [PATCH v2 17/20] ASoC: mediatek: mt6359-accdet: Always set
 comp-vth to 1.6V
In-Reply-To: <20250302-mt6359-accdet-dts-v2-17-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-17-5bd633ee0d47@collabora.com>
Message-ID: <b1087fb6-99e6-4c54-b981-b8553bdecbe6@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The driver currently reads a mediatek,eint-comp-vth property from DT to
> determine the voltage threshold of the EINT comparator. Since there are
> no current users of the property and setting it to 1.6V is known to work
> across multiple boards, remove the code handling this property and
> instead always configure it to 1.6V. The property can be properly
> introduced in the binding in the future if it really turns out that
> different boards need different configurations.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>


Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:06:53 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:06:53 +0100
Subject: [PATCH v2 16/20] ASoC: mediatek: mt6359-accdet: Always configure
 hardware as mic-mode 2
In-Reply-To: <20250302-mt6359-accdet-dts-v2-16-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-16-5bd633ee0d47@collabora.com>
Message-ID: <925415fd-0415-491c-8e32-14dbd326f2a7@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The driver currently reads a mediatek,mic-mode property from DT to
> determine certain register configurations. Since there are no current
> users of the property, the property doesn't directly reflect the
> hardware  and the default value (2) is known to work on
> multiple boards, remove the code handling this property and instead
> always configure the hardware according to the known to work default.
> This property can be properly introduced in the binding in the future
> if it really turns out that different boards need different
> configurations.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:06:54 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:06:54 +0100
Subject: [PATCH v2 15/20] ASoC: mediatek: mt6359-accdet: Always set
 micbias1 to 2.8V
In-Reply-To: <20250302-mt6359-accdet-dts-v2-15-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-15-5bd633ee0d47@collabora.com>
Message-ID: <d9b64bb7-d4b1-4817-8d14-14ebabf40e88@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The driver currently reads a mediatek,mic-vol property from DT to
> determine the micbias1 setting to configure in hardware. Since there are
> no current users of the property and the default value (2.8V) is known
> to work on multiple boards, remove the code handling this property and
> instead always configure the micbias1 to 2.8V. The property can be
> properly introduced in the binding in the future if it really turns out
> that different boards need different configurations.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:06:59 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:06:59 +0100
Subject: [PATCH v2 12/20] ASoC: mediatek: mt6359-accdet: Always use
 internal resistor
In-Reply-To: <20250302-mt6359-accdet-dts-v2-12-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-12-5bd633ee0d47@collabora.com>
Message-ID: <8af68114-82cd-45b3-a0a9-baa46d64c936@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The code currently reads a property mediatek,eint-use-ext-res with
> values ranging between 0 and 4. Not only should this be a boolean
> property, but there's no need for it to even be a DT property, seeing as
> all current boards will use the internal resistor anyway. Since there's
> no current dt-binding or Devicetree user of this property, remove its
> handling and make the driver always configure the internal resistor.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Adding up to this - I even checked a few downstream smartphone devicetrees, and
not even those are ever using external resistor. This won't ever be needed.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:01 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:01 +0100
Subject: [PATCH v2 13/20] ASoC: mediatek: mt6359-accdet: Make PWM debounce
 settings internal
In-Reply-To: <20250302-mt6359-accdet-dts-v2-13-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-13-5bd633ee0d47@collabora.com>
Message-ID: <dac1dae7-55eb-45a5-903f-afb71320361b@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> Instead of reading a bunch of PWM debounce settings from the Devicetree,
> set reasonable values inside the driver that are known to work across
> multiple boards. There are no current users of these DT properties, so
> no backward compatibility needs to be maintained. The properties can be
> properly introduced in the binding in the future if different boards
> really need to override them.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:13 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:13 +0100
Subject: [PATCH v2 10/20] ASoC: mediatek: mt6359-accdet: Drop dead code
 for plugout-debounce
In-Reply-To: <20250302-mt6359-accdet-dts-v2-10-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-10-5bd633ee0d47@collabora.com>
Message-ID: <d6056fa3-ad3f-4eda-8479-4548eddbdaa6@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The mediatek,plugout-debounce property is undocumented in the binding
> and unhandled by the driver. Remove it.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:03 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:03 +0100
Subject: [PATCH v2 14/20] ASoC: mediatek: mt6359-accdet: Always use eint
 detect mode 4
In-Reply-To: <20250302-mt6359-accdet-dts-v2-14-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-14-5bd633ee0d47@collabora.com>
Message-ID: <ddd4b401-68ff-4b6b-8335-1feb29bfc243@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The driver currently reads a mediatek,eint-detect-mode property from DT,
> which determines certain register configurations. Since there are no
> users of the property, it doesn't directly describe the hardware, and
> the default value (4) is known to work across multiple boards, remove
> the handling for this property and always assume mode 4 is used. The
> property can be properly introduced in the binding in the future if
> different boards actually need different configurations.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Same as the internal resistor one, can't find usage of this property, not even
in downstream devicetrees for dimensity chips..... so it's safe to remove.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:19 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:19 +0100
Subject: [PATCH v2 11/20] ASoC: mediatek: mt6359-accdet: Drop unused
 moisture variables
In-Reply-To: <20250302-mt6359-accdet-dts-v2-11-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-11-5bd633ee0d47@collabora.com>
Message-ID: <e6d45582-6631-4f90-bc1f-8f70f974aebe@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The dts_data struct contains several variables for moisture
> configuration that are simply never used. Drop them.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:21 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:21 +0100
Subject: [PATCH v2 09/20] ASoC: mediatek: mt6359-accdet: Drop dead code
 for button detection
In-Reply-To: <20250302-mt6359-accdet-dts-v2-9-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-9-5bd633ee0d47@collabora.com>
Message-ID: <7bce0cec-3a44-48ce-af55-db20135f696d@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The button detection functionality depends on a calibration voltage
> value which is currently not updated anywhere in the driver code, and
> hence it doesn't actually do anything. Remove this unused code.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:24 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:24 +0100
Subject: [PATCH v2 07/20] ASoC: mediatek: mt6359-accdet: Drop dead code
 for EINT/GPIO IRQ handling
In-Reply-To: <20250302-mt6359-accdet-dts-v2-7-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-7-5bd633ee0d47@collabora.com>
Message-ID: <bea223a0-505e-473b-ac00-fc311f12a9a6@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The ACCDET supports two modes for IRQ generation: PMIC EINT or AP GPIO,
> which in principle could be configured through a DT property. However
> this DT property has no user nor is documented in a binding, and the
> driver only implements the PMIC EINT case, so drop the unused code
> intended to handle both cases.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>



From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:27 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:27 +0100
Subject: [PATCH v2 08/20] ASoC: mediatek: mt6359-accdet: Drop dead code
 for EINT trigger setting
In-Reply-To: <20250302-mt6359-accdet-dts-v2-8-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-8-5bd633ee0d47@collabora.com>
Message-ID: <40c421e1-efc4-492a-9e48-077a95509a18@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> None of the EINT trigger options are implemented and the DT property is
> not described in the binding. Remove the unused code.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>



From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:07:32 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:07:32 +0100
Subject: [PATCH v2 05/20] ASoC: mediatek: mt6359-accdet: Handle
 hp-eint-high property
In-Reply-To: <20250302-mt6359-accdet-dts-v2-5-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-5-5bd633ee0d47@collabora.com>
Message-ID: <3ab8b2a3-b9de-4c1e-b650-2892be8fc8c9@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> Now that the dt-binding was introduced, the property that governs the
> eint polarity is a boolean called mediatek,hp-eint-high, while the
> current code handles a u32 property called mediatek,eint-level-pol.
> Update the driver handling accordingly.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:08:49 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:08:49 +0100
Subject: [PATCH v2 18/20] ASoC: mediatek: mt6359-accdet: Always use EINT0
 IRQ
In-Reply-To: <20250302-mt6359-accdet-dts-v2-18-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-18-5bd633ee0d47@collabora.com>
Message-ID: <0a003d4c-6302-46f1-9f49-7ea8dc7cd049@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> The ACCDET block can generate two distinct EINT interrupts: EINT0 and
> EINT1, and which is enabled is currently determined by mediatek,eint-num
> property in DT. However, only EINT0 is used on the boards that are
> known to have working ACCDET. Since there are no current users of the
> property, remove its handling and instead always enable EINT0. The
> property can be properly introduced in the binding in the future if it
> really turns out that other boards require EINT1.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:09:16 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:09:16 +0100
Subject: [PATCH v2 19/20] arm64: dts: mt6359: Add accessory detect node
In-Reply-To: <20250302-mt6359-accdet-dts-v2-19-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-19-5bd633ee0d47@collabora.com>
Message-ID: <4c454ee5-6102-4fae-86de-1f562ab9d2b3@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> Add audio jack detection node. PMIC accessory detect driver will
> create an input device that will send key events on jack
> insertion/removal or accessory device key presses.
> 
> Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:09:23 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:09:23 +0100
Subject: [PATCH v2 20/20] arm64: defconfig: Enable MT6359 ACCDET
In-Reply-To: <20250302-mt6359-accdet-dts-v2-20-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-20-5bd633ee0d47@collabora.com>
Message-ID: <746eaa07-6682-4088-ab20-f1536e4cb106@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> Enable support for the ACCDET block in the MT6359 PMIC, which provides
> jack detection capabilities to MediaTek platforms.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:04 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:04 +0100
Subject: [PATCH 02/19] arm64: Make asm/cache.h compatible with vDSO
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-2-c1b5c69a166f@linutronix.de>

asm/cache.h can be used during the vDSO build through vdso/cache.h.
Not all definitions in it are compatible with the vDSO, especially the
compat vDSO.
Hide the more complex definitions from the vDSO build.

Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 arch/arm64/include/asm/cache.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
index 06a4670bdb0b9b7552d553cee3cc70a6e15b2b93..99cd6546e72e35cfbceec7ce0a0f64498dfadd38 100644
--- a/arch/arm64/include/asm/cache.h
+++ b/arch/arm64/include/asm/cache.h
@@ -35,7 +35,7 @@
 #define ARCH_DMA_MINALIGN	(128)
 #define ARCH_KMALLOC_MINALIGN	(8)
 
-#ifndef __ASSEMBLY__
+#if !defined(__ASSEMBLY__) && !defined(BUILD_VDSO)
 
 #include <linux/bitops.h>
 #include <linux/kasan-enabled.h>
@@ -118,6 +118,6 @@ static inline u32 __attribute_const__ read_cpuid_effective_cachetype(void)
 	return ctr;
 }
 
-#endif	/* __ASSEMBLY__ */
+#endif /* !defined(__ASSEMBLY__) && !defined(BUILD_VDSO) */
 
 #endif

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:02 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:02 +0100
Subject: [PATCH 00/19] vdso: Rework struct vdso_time_data and introduce
 struct vdso_clock
Message-ID: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be an array of it.

This series is based on and intended to be merged through tip/timers/vdso.

Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
Anna-Maria Behnsen (15):
      vdso: Make vdso_time_data cacheline aligned
      vdso/datapage: Define for vdso_data to make rework of vdso possible
      vdso/helpers: Prepare introduction of struct vdso_clock
      vdso/gettimeofday: Prepare introduction of struct vdso_clock
      vdso/gettimeofday: Prepare do_hres() for introduction of struct vdso_clock
      vdso/gettimeofday: Prepare do_hres_timens() for introduction of struct vdso_clock
      vdso/gettimeofday: Prepare do_coarse() for introduction of struct vdso_clock
      vdso/gettimeofday: Prepare do_coarse_timens() for introduction of struct vdso_clock
      vdso/gettimeofday: Prepare helper functions for introduction of struct vdso_clock
      vdso/vsyscall: Prepare introduction of struct vdso_clock
      vdso/namespace: Rename timens_setup_vdso_data() to reflect new vdso_clock struct
      time/namespace: Prepare introduction of struct vdso_clock
      x86/vdso: Prepare introduction of struct vdso_clock
      vdso: Move arch related data before basetime
      vdso: Rework struct vdso_time_data and introduce struct vdso_clock

Nam Cao (2):
      arm64/vdso: Prepare introduction of struct vdso_clock
      powerpc/vdso: Prepare introduction of struct vdso_clock

Thomas Wei?schuh (2):
      vdso: Introduce vdso/cache.h
      arm64: Make asm/cache.h compatible with vDSO

 arch/arm64/include/asm/cache.h                    |   4 +-
 arch/arm64/include/asm/vdso/compat_gettimeofday.h |   6 +-
 arch/arm64/include/asm/vdso/vsyscall.h            |   4 +-
 arch/powerpc/include/asm/vdso/gettimeofday.h      |   2 +-
 arch/s390/kernel/time.c                           |  11 +-
 arch/x86/include/asm/vdso/gettimeofday.h          |  16 +--
 include/asm-generic/vdso/vsyscall.h               |   2 +-
 include/linux/cache.h                             |   9 +-
 include/vdso/cache.h                              |  15 +++
 include/vdso/datapage.h                           |  48 ++++---
 include/vdso/helpers.h                            |  20 +--
 kernel/time/namespace.c                           |  20 +--
 kernel/time/vsyscall.c                            |  47 +++----
 lib/vdso/datastore.c                              |   6 +-
 lib/vdso/gettimeofday.c                           | 146 ++++++++++++----------
 15 files changed, 196 insertions(+), 160 deletions(-)
---
base-commit: ac1a42f4e4e296b5ba5fdb39444f65d6e5196240
change-id: 20250224-vdso-clock-f10f017c4b80

Best regards,
-- 
Thomas Wei?schuh <thomas.weissschuh at linutronix.de>



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:03 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:03 +0100
Subject: [PATCH 01/19] vdso: Introduce vdso/cache.h
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-1-c1b5c69a166f@linutronix.de>

The vDSO implementation can only include headers from the vdso/
namespace. To enable the usage of ____cacheline_aligned from
the vDSO, move it and its dependencies into a new header vdso/cache.h.
Keep compatibility by including vdso/cache.h from linux/cache.h.

Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 include/linux/cache.h |  9 +--------
 include/vdso/cache.h  | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/include/linux/cache.h b/include/linux/cache.h
index ca2a05682a54b51af991154a99f57a00c88fc5a8..e69768f50d5327b874ba4bd56609300526511a69 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -3,16 +3,13 @@
 #define __LINUX_CACHE_H
 
 #include <uapi/linux/kernel.h>
+#include <vdso/cache.h>
 #include <asm/cache.h>
 
 #ifndef L1_CACHE_ALIGN
 #define L1_CACHE_ALIGN(x) __ALIGN_KERNEL(x, L1_CACHE_BYTES)
 #endif
 
-#ifndef SMP_CACHE_BYTES
-#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#endif
-
 /**
  * SMP_CACHE_ALIGN - align a value to the L2 cacheline size
  * @x: value to align
@@ -63,10 +60,6 @@
 #define __ro_after_init __section(".data..ro_after_init")
 #endif
 
-#ifndef ____cacheline_aligned
-#define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
-#endif
-
 #ifndef ____cacheline_aligned_in_smp
 #ifdef CONFIG_SMP
 #define ____cacheline_aligned_in_smp ____cacheline_aligned
diff --git a/include/vdso/cache.h b/include/vdso/cache.h
new file mode 100644
index 0000000000000000000000000000000000000000..f89d48304bf8f101df581aee0e32a2efa9d2fb2d
--- /dev/null
+++ b/include/vdso/cache.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __VDSO_CACHE_H
+#define __VDSO_CACHE_H
+
+#include <asm/cache.h>
+
+#ifndef SMP_CACHE_BYTES
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
+#endif
+
+#ifndef ____cacheline_aligned
+#define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
+#endif
+
+#endif	/* __VDSO_ALIGN_H */

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:05 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:05 +0100
Subject: [PATCH 03/19] vdso: Make vdso_time_data cacheline aligned
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-3-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

vdso_time_data is not cacheline aligned at the moment. When instantiating
an array, the start of the second array member is not cache line aligned.
This increases the number of the required cache lines which needs to be
read when handling e.g. CLOCK_MONOTONIC_RAW, because the data spawns an
extra cache line if the previous data does not end at a cache line
boundary.

Therefore make struct vdso_time_data cacheline aligned.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 include/vdso/datapage.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h
index ed4fb4c06e3ee6423fe68ccb476565213f234863..dfd98f969f151eca3c551c3e90f69af9ee8f22bb 100644
--- a/include/vdso/datapage.h
+++ b/include/vdso/datapage.h
@@ -11,6 +11,7 @@
 
 #include <vdso/align.h>
 #include <vdso/bits.h>
+#include <vdso/cache.h>
 #include <vdso/clocksource.h>
 #include <vdso/ktime.h>
 #include <vdso/limits.h>
@@ -126,7 +127,7 @@ struct vdso_time_data {
 	u32			__unused;
 
 	struct arch_vdso_time_data arch_data;
-};
+} ____cacheline_aligned;
 
 /**
  * struct vdso_rng_data - vdso RNG state information

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:06 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:06 +0100
Subject: [PATCH 04/19] vdso/datapage: Define for vdso_data to make rework
 of vdso possible
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-4-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

PTP clocks could also be supported by the vdso to use the advantages of
this implementation. Therefore the struct must be reworked. For a
transition to the new structure of the vdso, add a define which maps
vdso_clock to vdso_data. This will be removed when all users are updated
step by step.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 include/vdso/datapage.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h
index dfd98f969f151eca3c551c3e90f69af9ee8f22bb..1df22e8bb9b31153546b72b1e8b8c8aeaed7d9e3 100644
--- a/include/vdso/datapage.h
+++ b/include/vdso/datapage.h
@@ -129,6 +129,8 @@ struct vdso_time_data {
 	struct arch_vdso_time_data arch_data;
 } ____cacheline_aligned;
 
+#define vdso_clock vdso_time_data
+
 /**
  * struct vdso_rng_data - vdso RNG state information
  * @generation:	counter representing the number of RNG reseeds

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:07 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:07 +0100
Subject: [PATCH 05/19] vdso/helpers: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-5-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

Prepare all functions which need the pointer to the vdso_clock array to
work well after the structures get reworked. Replace struct vdso_time_data
pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 include/vdso/helpers.h | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/include/vdso/helpers.h b/include/vdso/helpers.h
index 41c3087070c7ab21d7adec04e6cd30c4b32ea221..28f0707a46c62187ad7500543e169f5b99deee70 100644
--- a/include/vdso/helpers.h
+++ b/include/vdso/helpers.h
@@ -7,49 +7,53 @@
 #include <asm/barrier.h>
 #include <vdso/datapage.h>
 
-static __always_inline u32 vdso_read_begin(const struct vdso_time_data *vd)
+static __always_inline u32 vdso_read_begin(const struct vdso_clock *vc)
 {
 	u32 seq;
 
-	while (unlikely((seq = READ_ONCE(vd->seq)) & 1))
+	while (unlikely((seq = READ_ONCE(vc->seq)) & 1))
 		cpu_relax();
 
 	smp_rmb();
 	return seq;
 }
 
-static __always_inline u32 vdso_read_retry(const struct vdso_time_data *vd,
+static __always_inline u32 vdso_read_retry(const struct vdso_clock *vc,
 					   u32 start)
 {
 	u32 seq;
 
 	smp_rmb();
-	seq = READ_ONCE(vd->seq);
+	seq = READ_ONCE(vc->seq);
 	return seq != start;
 }
 
 static __always_inline void vdso_write_begin(struct vdso_time_data *vd)
 {
+	struct vdso_clock *vc = vd;
+
 	/*
 	 * WRITE_ONCE() is required otherwise the compiler can validly tear
 	 * updates to vd[x].seq and it is possible that the value seen by the
 	 * reader is inconsistent.
 	 */
-	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
-	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
+	WRITE_ONCE(vc[CS_HRES_COARSE].seq, vc[CS_HRES_COARSE].seq + 1);
+	WRITE_ONCE(vc[CS_RAW].seq, vc[CS_RAW].seq + 1);
 	smp_wmb();
 }
 
 static __always_inline void vdso_write_end(struct vdso_time_data *vd)
 {
+	struct vdso_clock *vc = vd;
+
 	smp_wmb();
 	/*
 	 * WRITE_ONCE() is required otherwise the compiler can validly tear
 	 * updates to vd[x].seq and it is possible that the value seen by the
 	 * reader is inconsistent.
 	 */
-	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
-	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
+	WRITE_ONCE(vc[CS_HRES_COARSE].seq, vc[CS_HRES_COARSE].seq + 1);
+	WRITE_ONCE(vc[CS_RAW].seq, vc[CS_RAW].seq + 1);
 }
 
 #endif /* !__ASSEMBLY__ */

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:09 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:09 +0100
Subject: [PATCH 07/19] vdso/gettimeofday: Prepare do_hres() for
 introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-7-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

Prepare for the rework of these structures by adding struct vdso_clock
pointer argument to do_hres(), and replace the struct vdso_time_data
pointer with the new pointer arugment whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 59369a4e9f25f937eb8d9aed3201ebd340097a9d..15611ab650232f2e847b7de80c7293c4fb7f84f2 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -139,10 +139,11 @@ static __always_inline int do_hres_timens(const struct vdso_time_data *vdns, clo
 }
 #endif
 
-static __always_inline int do_hres(const struct vdso_time_data *vd, clockid_t clk,
-				   struct __kernel_timespec *ts)
+static __always_inline
+int do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
+	    clockid_t clk, struct __kernel_timespec *ts)
 {
-	const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
+	const struct vdso_timestamp *vdso_ts = &vc->basetime[clk];
 	u64 cycles, sec, ns;
 	u32 seq;
 
@@ -154,31 +155,31 @@ static __always_inline int do_hres(const struct vdso_time_data *vd, clockid_t cl
 		/*
 		 * Open coded function vdso_read_begin() to handle
 		 * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a
-		 * special VVAR page installed which has vd->seq set to 1 and
-		 * vd->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time
+		 * special VVAR page installed which has vc->seq set to 1 and
+		 * vc->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time
 		 * namespace affected tasks this does not affect performance
-		 * because if vd->seq is odd, i.e. a concurrent update is in
-		 * progress the extra check for vd->clock_mode is just a few
-		 * extra instructions while spin waiting for vd->seq to become
+		 * because if vc->seq is odd, i.e. a concurrent update is in
+		 * progress the extra check for vc->clock_mode is just a few
+		 * extra instructions while spin waiting for vc->seq to become
 		 * even again.
 		 */
-		while (unlikely((seq = READ_ONCE(vd->seq)) & 1)) {
+		while (unlikely((seq = READ_ONCE(vc->seq)) & 1)) {
 			if (IS_ENABLED(CONFIG_TIME_NS) &&
-			    vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
+			    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
 				return do_hres_timens(vd, clk, ts);
 			cpu_relax();
 		}
 		smp_rmb();
 
-		if (unlikely(!vdso_clocksource_ok(vd)))
+		if (unlikely(!vdso_clocksource_ok(vc)))
 			return -1;
 
-		cycles = __arch_get_hw_counter(vd->clock_mode, vd);
+		cycles = __arch_get_hw_counter(vc->clock_mode, vd);
 		if (unlikely(!vdso_cycles_ok(cycles)))
 			return -1;
-		ns = vdso_calc_ns(vd, cycles, vdso_ts->nsec);
+		ns = vdso_calc_ns(vc, cycles, vdso_ts->nsec);
 		sec = vdso_ts->sec;
-	} while (unlikely(vdso_read_retry(vd, seq)));
+	} while (unlikely(vdso_read_retry(vc, seq)));
 
 	/*
 	 * Do this outside the loop: a race inside the loop could result
@@ -278,7 +279,7 @@ __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
 	else
 		return -1;
 
-	return do_hres(vc, clock, ts);
+	return do_hres(vd, vc, clock, ts);
 }
 
 static __maybe_unused int
@@ -334,7 +335,7 @@ __cvdso_gettimeofday_data(const struct vdso_time_data *vd,
 	if (likely(tv != NULL)) {
 		struct __kernel_timespec ts;
 
-		if (do_hres(&vc[CS_HRES_COARSE], CLOCK_REALTIME, &ts))
+		if (do_hres(vd, &vc[CS_HRES_COARSE], CLOCK_REALTIME, &ts))
 			return gettimeofday_fallback(tv, tz);
 
 		tv->tv_sec = ts.tv_sec;

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:08 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:08 +0100
Subject: [PATCH 06/19] vdso/gettimeofday: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-6-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. At the moment, vdso_clock
is simply a define which maps vdso_clock to vdso_time_data.

Prepare all functions which need the pointer to the vdso_clock array to
work well after introducing the new struct. Whenever applicable, struct
vdso_time_data pointer is replaced by struct vdso_clock pointer.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 299f027116ee0e50a69c5a8a17218004e4af0ea1..59369a4e9f25f937eb8d9aed3201ebd340097a9d 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -257,6 +257,7 @@ static __always_inline int
 __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
 			     struct __kernel_timespec *ts)
 {
+	const struct vdso_clock *vc = vd;
 	u32 msk;
 
 	/* Check for negative values or invalid clocks */
@@ -269,15 +270,15 @@ __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
 	 */
 	msk = 1U << clock;
 	if (likely(msk & VDSO_HRES))
-		vd = &vd[CS_HRES_COARSE];
+		vc = &vc[CS_HRES_COARSE];
 	else if (msk & VDSO_COARSE)
-		return do_coarse(&vd[CS_HRES_COARSE], clock, ts);
+		return do_coarse(&vc[CS_HRES_COARSE], clock, ts);
 	else if (msk & VDSO_RAW)
-		vd = &vd[CS_RAW];
+		vc = &vc[CS_RAW];
 	else
 		return -1;
 
-	return do_hres(vd, clock, ts);
+	return do_hres(vc, clock, ts);
 }
 
 static __maybe_unused int
@@ -328,11 +329,12 @@ static __maybe_unused int
 __cvdso_gettimeofday_data(const struct vdso_time_data *vd,
 			  struct __kernel_old_timeval *tv, struct timezone *tz)
 {
+	const struct vdso_clock *vc = vd;
 
 	if (likely(tv != NULL)) {
 		struct __kernel_timespec ts;
 
-		if (do_hres(&vd[CS_HRES_COARSE], CLOCK_REALTIME, &ts))
+		if (do_hres(&vc[CS_HRES_COARSE], CLOCK_REALTIME, &ts))
 			return gettimeofday_fallback(tv, tz);
 
 		tv->tv_sec = ts.tv_sec;
@@ -341,7 +343,7 @@ __cvdso_gettimeofday_data(const struct vdso_time_data *vd,
 
 	if (unlikely(tz != NULL)) {
 		if (IS_ENABLED(CONFIG_TIME_NS) &&
-		    vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
+		    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
 			vd = __arch_get_vdso_u_timens_data(vd);
 
 		tz->tz_minuteswest = vd[CS_HRES_COARSE].tz_minuteswest;
@@ -361,13 +363,16 @@ __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 static __maybe_unused __kernel_old_time_t
 __cvdso_time_data(const struct vdso_time_data *vd, __kernel_old_time_t *time)
 {
+	const struct vdso_clock *vc = vd;
 	__kernel_old_time_t t;
 
 	if (IS_ENABLED(CONFIG_TIME_NS) &&
-	    vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
+	    vc->clock_mode == VDSO_CLOCKMODE_TIMENS) {
 		vd = __arch_get_vdso_u_timens_data(vd);
+		vc = vd;
+	}
 
-	t = READ_ONCE(vd[CS_HRES_COARSE].basetime[CLOCK_REALTIME].sec);
+	t = READ_ONCE(vc[CS_HRES_COARSE].basetime[CLOCK_REALTIME].sec);
 
 	if (time)
 		*time = t;
@@ -386,6 +391,7 @@ static __maybe_unused
 int __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t clock,
 				struct __kernel_timespec *res)
 {
+	const struct vdso_clock *vc = vd;
 	u32 msk;
 	u64 ns;
 
@@ -394,7 +400,7 @@ int __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t clock
 		return -1;
 
 	if (IS_ENABLED(CONFIG_TIME_NS) &&
-	    vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
+	    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
 		vd = __arch_get_vdso_u_timens_data(vd);
 
 	/*

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:10 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:10 +0100
Subject: [PATCH 08/19] vdso/gettimeofday: Prepare do_hres_timens() for
 introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-8-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

Prepare for the rework of these structures by adding struct vdso_clock
pointer argument to do_hres_timens(), and replace the struct vdso_time_data
pointer with the new pointer arugment whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 15611ab650232f2e847b7de80c7293c4fb7f84f2..e8d4b02bcb616af19f1e794b14fb4419809408da 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -81,36 +81,36 @@ const struct vdso_time_data *__arch_get_vdso_u_timens_data(const struct vdso_tim
 }
 #endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
 
-static __always_inline int do_hres_timens(const struct vdso_time_data *vdns, clockid_t clk,
-					  struct __kernel_timespec *ts)
+static __always_inline
+int do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
+		   clockid_t clk, struct __kernel_timespec *ts)
 {
-	const struct timens_offset *offs = &vdns->offset[clk];
+	const struct vdso_time_data *vd = __arch_get_vdso_u_timens_data(vdns);
+	const struct timens_offset *offs = &vcns->offset[clk];
 	const struct vdso_timestamp *vdso_ts;
-	const struct vdso_time_data *vd;
+	const struct vdso_clock *vc = vd;
 	u64 cycles, ns;
 	u32 seq;
 	s64 sec;
 
-	vd = vdns - (clk == CLOCK_MONOTONIC_RAW ? CS_RAW : CS_HRES_COARSE);
-	vd = __arch_get_vdso_u_timens_data(vd);
 	if (clk != CLOCK_MONOTONIC_RAW)
-		vd = &vd[CS_HRES_COARSE];
+		vc = &vc[CS_HRES_COARSE];
 	else
-		vd = &vd[CS_RAW];
-	vdso_ts = &vd->basetime[clk];
+		vc = &vc[CS_RAW];
+	vdso_ts = &vc->basetime[clk];
 
 	do {
-		seq = vdso_read_begin(vd);
+		seq = vdso_read_begin(vc);
 
-		if (unlikely(!vdso_clocksource_ok(vd)))
+		if (unlikely(!vdso_clocksource_ok(vc)))
 			return -1;
 
-		cycles = __arch_get_hw_counter(vd->clock_mode, vd);
+		cycles = __arch_get_hw_counter(vc->clock_mode, vd);
 		if (unlikely(!vdso_cycles_ok(cycles)))
 			return -1;
-		ns = vdso_calc_ns(vd, cycles, vdso_ts->nsec);
+		ns = vdso_calc_ns(vc, cycles, vdso_ts->nsec);
 		sec = vdso_ts->sec;
-	} while (unlikely(vdso_read_retry(vd, seq)));
+	} while (unlikely(vdso_read_retry(vc, seq)));
 
 	/* Add the namespace offset */
 	sec += offs->sec;
@@ -132,8 +132,9 @@ const struct vdso_time_data *__arch_get_vdso_u_timens_data(const struct vdso_tim
 	return NULL;
 }
 
-static __always_inline int do_hres_timens(const struct vdso_time_data *vdns, clockid_t clk,
-					  struct __kernel_timespec *ts)
+static __always_inline
+int do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
+		   clockid_t clk, struct __kernel_timespec *ts)
 {
 	return -EINVAL;
 }
@@ -166,7 +167,7 @@ int do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
 		while (unlikely((seq = READ_ONCE(vc->seq)) & 1)) {
 			if (IS_ENABLED(CONFIG_TIME_NS) &&
 			    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
-				return do_hres_timens(vd, clk, ts);
+				return do_hres_timens(vd, vc, clk, ts);
 			cpu_relax();
 		}
 		smp_rmb();

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:12 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:12 +0100
Subject: [PATCH 10/19] vdso/gettimeofday: Prepare do_coarse_timens() for
 introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-10-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. At the moment, vdso_clock
is simply a define which maps vdso_clock to vdso_time_data.

Prepare for the rework of these structures by adding struct vdso_clock
pointer argument to do_coarse_timens(), and replace the struct
vdso_time_data pointer with the new pointer arugment whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 36ef7de097e6137832605928a155a0ff78123fb4..03fa0393645ac0f5ee465ddc19d84b330913da65 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -193,21 +193,25 @@ int do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
 }
 
 #ifdef CONFIG_TIME_NS
-static __always_inline int do_coarse_timens(const struct vdso_time_data *vdns, clockid_t clk,
-					    struct __kernel_timespec *ts)
+static __always_inline
+int do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
+		     clockid_t clk, struct __kernel_timespec *ts)
 {
 	const struct vdso_time_data *vd = __arch_get_vdso_u_timens_data(vdns);
-	const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
-	const struct timens_offset *offs = &vdns->offset[clk];
+	const struct timens_offset *offs = &vcns->offset[clk];
+	const struct vdso_timestamp *vdso_ts;
+	const struct vdso_clock *vc = vd;
 	u64 nsec;
 	s64 sec;
 	s32 seq;
 
+	vdso_ts = &vc->basetime[clk];
+
 	do {
-		seq = vdso_read_begin(vd);
+		seq = vdso_read_begin(vc);
 		sec = vdso_ts->sec;
 		nsec = vdso_ts->nsec;
-	} while (unlikely(vdso_read_retry(vd, seq)));
+	} while (unlikely(vdso_read_retry(vc, seq)));
 
 	/* Add the namespace offset */
 	sec += offs->sec;
@@ -222,8 +226,9 @@ static __always_inline int do_coarse_timens(const struct vdso_time_data *vdns, c
 	return 0;
 }
 #else
-static __always_inline int do_coarse_timens(const struct vdso_time_data *vdns, clockid_t clk,
-					    struct __kernel_timespec *ts)
+static __always_inline
+int do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
+		     clockid_t clk, struct __kernel_timespec *ts)
 {
 	return -1;
 }
@@ -244,7 +249,7 @@ int do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc,
 		while ((seq = READ_ONCE(vc->seq)) & 1) {
 			if (IS_ENABLED(CONFIG_TIME_NS) &&
 			    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
-				return do_coarse_timens(vc, clk, ts);
+				return do_coarse_timens(vd, vc, clk, ts);
 			cpu_relax();
 		}
 		smp_rmb();

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:13 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:13 +0100
Subject: [PATCH 11/19] vdso/gettimeofday: Prepare helper functions for
 introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-11-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer argument of the helper functions with struct
vdso_clock pointer if applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 03fa0393645ac0f5ee465ddc19d84b330913da65..c6ff6934558658f9e280d5b84cfb034f4828893d 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -17,12 +17,12 @@
 #endif
 
 #ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
-static __always_inline bool vdso_delta_ok(const struct vdso_time_data *vd, u64 delta)
+static __always_inline bool vdso_delta_ok(const struct vdso_clock *vc, u64 delta)
 {
-	return delta < vd->max_cycles;
+	return delta < vc->max_cycles;
 }
 #else
-static __always_inline bool vdso_delta_ok(const struct vdso_time_data *vd, u64 delta)
+static __always_inline bool vdso_delta_ok(const struct vdso_clock *vc, u64 delta)
 {
 	return true;
 }
@@ -39,14 +39,14 @@ static __always_inline u64 vdso_shift_ns(u64 ns, u32 shift)
  * Default implementation which works for all sane clocksources. That
  * obviously excludes x86/TSC.
  */
-static __always_inline u64 vdso_calc_ns(const struct vdso_time_data *vd, u64 cycles, u64 base)
+static __always_inline u64 vdso_calc_ns(const struct vdso_clock *vc, u64 cycles, u64 base)
 {
-	u64 delta = (cycles - vd->cycle_last) & VDSO_DELTA_MASK(vd);
+	u64 delta = (cycles - vc->cycle_last) & VDSO_DELTA_MASK(vc);
 
-	if (likely(vdso_delta_ok(vd, delta)))
-		return vdso_shift_ns((delta * vd->mult) + base, vd->shift);
+	if (likely(vdso_delta_ok(vc, delta)))
+		return vdso_shift_ns((delta * vc->mult) + base, vc->shift);
 
-	return mul_u64_u32_add_u64_shr(delta, vd->mult, base, vd->shift);
+	return mul_u64_u32_add_u64_shr(delta, vc->mult, base, vc->shift);
 }
 #endif /* vdso_calc_ns */
 
@@ -58,9 +58,9 @@ static inline bool __arch_vdso_hres_capable(void)
 #endif
 
 #ifndef vdso_clocksource_ok
-static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
+static inline bool vdso_clocksource_ok(const struct vdso_clock *vc)
 {
-	return vd->clock_mode != VDSO_CLOCKMODE_NONE;
+	return vc->clock_mode != VDSO_CLOCKMODE_NONE;
 }
 #endif
 

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:11 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:11 +0100
Subject: [PATCH 09/19] vdso/gettimeofday: Prepare do_coarse() for
 introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-9-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

Prepare for the rework of these structures by adding struct vdso_clock
pointer argument to do_coarse(), and replace the struct vdso_time_data
pointer with the new pointer arugment whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 lib/vdso/gettimeofday.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index e8d4b02bcb616af19f1e794b14fb4419809408da..36ef7de097e6137832605928a155a0ff78123fb4 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -229,10 +229,11 @@ static __always_inline int do_coarse_timens(const struct vdso_time_data *vdns, c
 }
 #endif
 
-static __always_inline int do_coarse(const struct vdso_time_data *vd, clockid_t clk,
-				     struct __kernel_timespec *ts)
+static __always_inline
+int do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc,
+	      clockid_t clk, struct __kernel_timespec *ts)
 {
-	const struct vdso_timestamp *vdso_ts = &vd->basetime[clk];
+	const struct vdso_timestamp *vdso_ts = &vc->basetime[clk];
 	u32 seq;
 
 	do {
@@ -240,17 +241,17 @@ static __always_inline int do_coarse(const struct vdso_time_data *vd, clockid_t
 		 * Open coded function vdso_read_begin() to handle
 		 * VDSO_CLOCK_TIMENS. See comment in do_hres().
 		 */
-		while ((seq = READ_ONCE(vd->seq)) & 1) {
+		while ((seq = READ_ONCE(vc->seq)) & 1) {
 			if (IS_ENABLED(CONFIG_TIME_NS) &&
-			    vd->clock_mode == VDSO_CLOCKMODE_TIMENS)
-				return do_coarse_timens(vd, clk, ts);
+			    vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
+				return do_coarse_timens(vc, clk, ts);
 			cpu_relax();
 		}
 		smp_rmb();
 
 		ts->tv_sec = vdso_ts->sec;
 		ts->tv_nsec = vdso_ts->nsec;
-	} while (unlikely(vdso_read_retry(vd, seq)));
+	} while (unlikely(vdso_read_retry(vc, seq)));
 
 	return 0;
 }
@@ -274,7 +275,7 @@ __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
 	if (likely(msk & VDSO_HRES))
 		vc = &vc[CS_HRES_COARSE];
 	else if (msk & VDSO_COARSE)
-		return do_coarse(&vc[CS_HRES_COARSE], clock, ts);
+		return do_coarse(vd, &vc[CS_HRES_COARSE], clock, ts);
 	else if (msk & VDSO_RAW)
 		vc = &vc[CS_RAW];
 	else

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:14 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:14 +0100
Subject: [PATCH 12/19] vdso/vsyscall: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-12-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 kernel/time/vsyscall.c | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/kernel/time/vsyscall.c b/kernel/time/vsyscall.c
index 418192296ef7dd3c1772d50f129e7838883cf00c..dd85b41a70bee7decbd943c35197c091916ee4c7 100644
--- a/kernel/time/vsyscall.c
+++ b/kernel/time/vsyscall.c
@@ -18,25 +18,26 @@
 static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct timekeeper *tk)
 {
 	struct vdso_timestamp *vdso_ts;
+	struct vdso_clock *vc = vdata;
 	u64 nsec, sec;
 
-	vdata[CS_HRES_COARSE].cycle_last	= tk->tkr_mono.cycle_last;
+	vc[CS_HRES_COARSE].cycle_last	= tk->tkr_mono.cycle_last;
 #ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
-	vdata[CS_HRES_COARSE].max_cycles	= tk->tkr_mono.clock->max_cycles;
+	vc[CS_HRES_COARSE].max_cycles	= tk->tkr_mono.clock->max_cycles;
 #endif
-	vdata[CS_HRES_COARSE].mask		= tk->tkr_mono.mask;
-	vdata[CS_HRES_COARSE].mult		= tk->tkr_mono.mult;
-	vdata[CS_HRES_COARSE].shift		= tk->tkr_mono.shift;
-	vdata[CS_RAW].cycle_last		= tk->tkr_raw.cycle_last;
+	vc[CS_HRES_COARSE].mask		= tk->tkr_mono.mask;
+	vc[CS_HRES_COARSE].mult		= tk->tkr_mono.mult;
+	vc[CS_HRES_COARSE].shift	= tk->tkr_mono.shift;
+	vc[CS_RAW].cycle_last		= tk->tkr_raw.cycle_last;
 #ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
-	vdata[CS_RAW].max_cycles		= tk->tkr_raw.clock->max_cycles;
+	vc[CS_RAW].max_cycles		= tk->tkr_raw.clock->max_cycles;
 #endif
-	vdata[CS_RAW].mask			= tk->tkr_raw.mask;
-	vdata[CS_RAW].mult			= tk->tkr_raw.mult;
-	vdata[CS_RAW].shift			= tk->tkr_raw.shift;
+	vc[CS_RAW].mask			= tk->tkr_raw.mask;
+	vc[CS_RAW].mult			= tk->tkr_raw.mult;
+	vc[CS_RAW].shift		= tk->tkr_raw.shift;
 
 	/* CLOCK_MONOTONIC */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
 	vdso_ts->sec	= tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
 
 	nsec = tk->tkr_mono.xtime_nsec;
@@ -54,7 +55,7 @@ static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct ti
 	nsec	+= (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
 
 	/* CLOCK_BOOTTIME */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
 	vdso_ts->sec	= sec;
 
 	while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
@@ -64,12 +65,12 @@ static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct ti
 	vdso_ts->nsec	= nsec;
 
 	/* CLOCK_MONOTONIC_RAW */
-	vdso_ts		= &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
+	vdso_ts		= &vc[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
 	vdso_ts->sec	= tk->raw_sec;
 	vdso_ts->nsec	= tk->tkr_raw.xtime_nsec;
 
 	/* CLOCK_TAI */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_TAI];
 	vdso_ts->sec	= tk->xtime_sec + (s64)tk->tai_offset;
 	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec;
 }
@@ -78,6 +79,7 @@ void update_vsyscall(struct timekeeper *tk)
 {
 	struct vdso_time_data *vdata = vdso_k_time_data;
 	struct vdso_timestamp *vdso_ts;
+	struct vdso_clock *vc = vdata;
 	s32 clock_mode;
 	u64 nsec;
 
@@ -85,21 +87,21 @@ void update_vsyscall(struct timekeeper *tk)
 	vdso_write_begin(vdata);
 
 	clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
-	vdata[CS_HRES_COARSE].clock_mode	= clock_mode;
-	vdata[CS_RAW].clock_mode		= clock_mode;
+	vc[CS_HRES_COARSE].clock_mode	= clock_mode;
+	vc[CS_RAW].clock_mode		= clock_mode;
 
 	/* CLOCK_REALTIME also required for time() */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
 	vdso_ts->sec	= tk->xtime_sec;
 	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec;
 
 	/* CLOCK_REALTIME_COARSE */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE];
 	vdso_ts->sec	= tk->xtime_sec;
 	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
 
 	/* CLOCK_MONOTONIC_COARSE */
-	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE];
+	vdso_ts		= &vc[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE];
 	vdso_ts->sec	= tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
 	nsec		= tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
 	nsec		= nsec + tk->wall_to_monotonic.tv_nsec;

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:15 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:15 +0100
Subject: [PATCH 13/19] vdso/namespace: Rename timens_setup_vdso_data() to
 reflect new vdso_clock struct
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-13-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it.

For time namespace, vdso_time_data needs to be set up. But this is only the
clock related part of the vdso_data thats requires this setup. To reflect
the future struct vdso_clock, rename timens_setup_vdso_data() to
timns_setup_vdso_clock_data().

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 kernel/time/namespace.c | 6 +++---
 lib/vdso/datastore.c    | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index 12f55aa539adbc11cce4055f519dbeca8a73320c..f02430a73be8f081618792c8968bf0c112c54505 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -176,8 +176,8 @@ static struct timens_offset offset_from_ts(struct timespec64 off)
  * Timens page has vdso_time_data->clock_mode set to VDSO_CLOCKMODE_TIMENS which
  * enforces the time namespace handling path.
  */
-static void timens_setup_vdso_data(struct vdso_time_data *vdata,
-				   struct time_namespace *ns)
+static void timens_setup_vdso_clock_data(struct vdso_time_data *vdata,
+					 struct time_namespace *ns)
 {
 	struct timens_offset *offset = vdata->offset;
 	struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
@@ -238,7 +238,7 @@ static void timens_set_vvar_page(struct task_struct *task,
 	vdata = page_address(ns->vvar_page);
 
 	for (i = 0; i < CS_BASES; i++)
-		timens_setup_vdso_data(&vdata[i], ns);
+		timens_setup_vdso_clock_data(&vdata[i], ns);
 
 out:
 	mutex_unlock(&offset_lock);
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index e227fbbcb79694f9a40606ac864f52cf1fdbfcf4..4e350f56ace335b7ebca8af7663b5731fae27334 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -109,7 +109,7 @@ struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned
  * non-root time namespace. Whenever a task changes its namespace, the VVAR
  * page tables are cleared and then they will be re-faulted with a
  * corresponding layout.
- * See also the comment near timens_setup_vdso_data() for details.
+ * See also the comment near timens_setup_vdso_clock_data() for details.
  */
 int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
 {

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:16 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:16 +0100
Subject: [PATCH 14/19] time/namespace: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-14-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 kernel/time/namespace.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index f02430a73be8f081618792c8968bf0c112c54505..09bc4fb39f24ccdaa1e6e7f7238660a4f2a63b54 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -165,26 +165,26 @@ static struct timens_offset offset_from_ts(struct timespec64 off)
  *     HVCLOCK
  *     VVAR
  *
- * The check for vdso_time_data->clock_mode is in the unlikely path of
+ * The check for vdso_clock->clock_mode is in the unlikely path of
  * the seq begin magic. So for the non-timens case most of the time
  * 'seq' is even, so the branch is not taken.
  *
  * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
- * for vdso_time_data->clock_mode is a non-issue. The task is spin waiting for the
+ * for vdso_clock->clock_mode is a non-issue. The task is spin waiting for the
  * update to finish and for 'seq' to become even anyway.
  *
- * Timens page has vdso_time_data->clock_mode set to VDSO_CLOCKMODE_TIMENS which
+ * Timens page has vdso_clock->clock_mode set to VDSO_CLOCKMODE_TIMENS which
  * enforces the time namespace handling path.
  */
-static void timens_setup_vdso_clock_data(struct vdso_time_data *vdata,
+static void timens_setup_vdso_clock_data(struct vdso_clock *vc,
 					 struct time_namespace *ns)
 {
-	struct timens_offset *offset = vdata->offset;
+	struct timens_offset *offset = vc->offset;
 	struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
 	struct timens_offset boottime = offset_from_ts(ns->offsets.boottime);
 
-	vdata->seq			= 1;
-	vdata->clock_mode		= VDSO_CLOCKMODE_TIMENS;
+	vc->seq				= 1;
+	vc->clock_mode			= VDSO_CLOCKMODE_TIMENS;
 	offset[CLOCK_MONOTONIC]		= monotonic;
 	offset[CLOCK_MONOTONIC_RAW]	= monotonic;
 	offset[CLOCK_MONOTONIC_COARSE]	= monotonic;
@@ -220,6 +220,7 @@ static void timens_set_vvar_page(struct task_struct *task,
 				struct time_namespace *ns)
 {
 	struct vdso_time_data *vdata;
+	struct vdso_clock *vc;
 	unsigned int i;
 
 	if (ns == &init_time_ns)
@@ -236,9 +237,10 @@ static void timens_set_vvar_page(struct task_struct *task,
 
 	ns->frozen_offsets = true;
 	vdata = page_address(ns->vvar_page);
+	vc = vdata;
 
 	for (i = 0; i < CS_BASES; i++)
-		timens_setup_vdso_clock_data(&vdata[i], ns);
+		timens_setup_vdso_clock_data(&vc[i], ns);
 
 out:
 	mutex_unlock(&offset_lock);

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:17 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:17 +0100
Subject: [PATCH 15/19] x86/vdso: Prepare introduction of struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-15-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 arch/x86/include/asm/vdso/gettimeofday.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index edec796832e08b73d6d58bda6408957048f4e80e..9e52cc46e1da99114312d85b34ae52e539dac9b6 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -261,7 +261,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode,
 	return U64_MAX;
 }
 
-static inline bool arch_vdso_clocksource_ok(const struct vdso_time_data *vd)
+static inline bool arch_vdso_clocksource_ok(const struct vdso_clock *vc)
 {
 	return true;
 }
@@ -300,34 +300,34 @@ static inline bool arch_vdso_cycles_ok(u64 cycles)
  * declares everything with the MSB/Sign-bit set as invalid. Therefore the
  * effective mask is S64_MAX.
  */
-static __always_inline u64 vdso_calc_ns(const struct vdso_time_data *vd, u64 cycles, u64 base)
+static __always_inline u64 vdso_calc_ns(const struct vdso_clock *vc, u64 cycles, u64 base)
 {
-	u64 delta = cycles - vd->cycle_last;
+	u64 delta = cycles - vc->cycle_last;
 
 	/*
 	 * Negative motion and deltas which can cause multiplication
 	 * overflow require special treatment. This check covers both as
-	 * negative motion is guaranteed to be greater than @vd::max_cycles
+	 * negative motion is guaranteed to be greater than @vc::max_cycles
 	 * due to unsigned comparison.
 	 *
 	 * Due to the MSB/Sign-bit being used as invalid marker (see
 	 * arch_vdso_cycles_ok() above), the effective mask is S64_MAX, but that
 	 * case is also unlikely and will also take the unlikely path here.
 	 */
-	if (unlikely(delta > vd->max_cycles)) {
+	if (unlikely(delta > vc->max_cycles)) {
 		/*
 		 * Due to the above mentioned TSC wobbles, filter out
 		 * negative motion.  Per the above masking, the effective
 		 * sign bit is now bit 62.
 		 */
 		if (delta & (1ULL << 62))
-			return base >> vd->shift;
+			return base >> vc->shift;
 
 		/* Handle multiplication overflow gracefully */
-		return mul_u64_u32_add_u64_shr(delta & S64_MAX, vd->mult, base, vd->shift);
+		return mul_u64_u32_add_u64_shr(delta & S64_MAX, vc->mult, base, vc->shift);
 	}
 
-	return ((delta * vd->mult) + base) >> vd->shift;
+	return ((delta * vc->mult) + base) >> vc->shift;
 }
 #define vdso_calc_ns vdso_calc_ns
 

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:18 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:18 +0100
Subject: [PATCH 16/19] arm64/vdso: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-16-c1b5c69a166f@linutronix.de>

From: Nam Cao <namcao at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 arch/arm64/include/asm/vdso/compat_gettimeofday.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index 957ee12fcc54bd7f978fbcd8945bce62327b037a..2c6b90d26bc8fd6d4be87bf6a4178472581f56d3 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -155,9 +155,9 @@ static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(
 }
 #define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data
 
-static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
+static inline bool vdso_clocksource_ok(const struct vdso_clock *vc)
 {
-	return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
+	return vc->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
 }
 #define vdso_clocksource_ok	vdso_clocksource_ok
 

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:20 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:20 +0100
Subject: [PATCH 18/19] vdso: Move arch related data before basetime
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-18-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

Architecture related vdso data is required in fastpath when acquiring
CLOCK_MONOTONIC or CLOCK_REALTIME. At the moment, this information is
located at the end of the vdso_time_data structure. The whole structure has
to be loaded into cache to be able to access this information.

To minimize the number of required cachelines, the architecture specific
vdso data struct is moved right before the basetime (basetime information
is required anyway). This change does not have an impact on architectures
with CONFIG_ARCH_HAS_VDSO_DATA=n. All other architectures could spare
reading unnecessary cachelines.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 include/vdso/datapage.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h
index 1df22e8bb9b31153546b72b1e8b8c8aeaed7d9e3..bcd19c223783be7c22f90120330e7dddd0496f1a 100644
--- a/include/vdso/datapage.h
+++ b/include/vdso/datapage.h
@@ -70,6 +70,8 @@ struct vdso_timestamp {
 
 /**
  * struct vdso_time_data - vdso datapage representation
+ * @arch_data:		architecture specific data (optional, defaults
+ *			to an empty struct)
  * @seq:		timebase sequence counter
  * @clock_mode:		clock mode
  * @cycle_last:		timebase at clocksource init
@@ -83,8 +85,6 @@ struct vdso_timestamp {
  * @tz_dsttime:		type of DST correction
  * @hrtimer_res:	hrtimer resolution
  * @__unused:		unused
- * @arch_data:		architecture specific data (optional, defaults
- *			to an empty struct)
  *
  * vdso_time_data will be accessed by 64 bit and compat code at the same time
  * so we should be careful before modifying this structure.
@@ -105,6 +105,8 @@ struct vdso_timestamp {
  * offset must be zero.
  */
 struct vdso_time_data {
+	struct arch_vdso_time_data arch_data;
+
 	u32			seq;
 
 	s32			clock_mode;
@@ -125,8 +127,6 @@ struct vdso_time_data {
 	s32			tz_dsttime;
 	u32			hrtimer_res;
 	u32			__unused;
-
-	struct arch_vdso_time_data arch_data;
 } ____cacheline_aligned;
 
 #define vdso_clock vdso_time_data

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:19 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:19 +0100
Subject: [PATCH 17/19] powerpc/vdso: Prepare introduction of struct
 vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-17-c1b5c69a166f@linutronix.de>

From: Nam Cao <namcao at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be array of it. By now, vdso_clock is
simply a define which maps vdso_clock to vdso_time_data.

To prepare for the rework of the data structures, replace the struct
vdso_time_data pointer with struct vdso_clock pointer whenever applicable.

No functional change.

Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 arch/powerpc/include/asm/vdso/gettimeofday.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h b/arch/powerpc/include/asm/vdso/gettimeofday.h
index dc955f2e0cc51f44d46f488a292aa0dbee3dc16c..99c9d6f43fde2efaf92d4777d3a5510677da7c92 100644
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
@@ -99,7 +99,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
 	return get_tb();
 }
 
-static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
+static inline bool vdso_clocksource_ok(const struct vdso_clock *vc)
 {
 	return true;
 }

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar  3 03:11:21 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 03 Mar 2025 12:11:21 +0100
Subject: [PATCH 19/19] vdso: Rework struct vdso_time_data and introduce
 struct vdso_clock
In-Reply-To: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
References: <20250303-vdso-clock-v1-0-c1b5c69a166f@linutronix.de>
Message-ID: <20250303-vdso-clock-v1-19-c1b5c69a166f@linutronix.de>

From: Anna-Maria Behnsen <anna-maria at linutronix.de>

To support multiple PTP clocks, the VDSO data structure needs to be
reworked. All clock specific data will end up in struct vdso_clock and in
struct vdso_time_data there will be an array of it.

Now all preparation is in place: Split the clock related struct members
into a separate struct vdso_clock. Make sure all users are aware, that
vdso_time_data is no longer initialized as an array and vdso_clock is now
the array inside vdso_data. Remove also the define of vdso_clock which made
preparation possible in smaller steps.

Signed-off-by: Anna-Maria Behnsen <anna-maria at linutronix.de>
Signed-off-by: Nam Cao <namcao at linutronix.de>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 arch/arm64/include/asm/vdso/compat_gettimeofday.h |  2 +-
 arch/arm64/include/asm/vdso/vsyscall.h            |  4 +-
 arch/s390/kernel/time.c                           | 11 ++----
 include/asm-generic/vdso/vsyscall.h               |  2 +-
 include/vdso/datapage.h                           | 47 ++++++++++++++---------
 include/vdso/helpers.h                            |  4 +-
 kernel/time/namespace.c                           |  2 +-
 kernel/time/vsyscall.c                            | 11 +++---
 lib/vdso/datastore.c                              |  4 +-
 lib/vdso/gettimeofday.c                           | 16 ++++----
 10 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index 2c6b90d26bc8fd6d4be87bf6a4178472581f56d3..d60ea7a72a9cb3457c412d0ece21ed76ae77782d 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -149,7 +149,7 @@ static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(
 	 * where __aarch64_get_vdso_u_time_data() is called, and then keep the
 	 * result in a register.
 	 */
-	asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_time_data));
+	asm volatile("mov %0, %1" : "=r"(ret) : "r"(&vdso_u_time_data));
 
 	return ret;
 }
diff --git a/arch/arm64/include/asm/vdso/vsyscall.h b/arch/arm64/include/asm/vdso/vsyscall.h
index 3f65cbd00635aab50a4e0c6058d38b39fd6d43a9..de58951b8df6a4bb9afd411878793c79c30adbf2 100644
--- a/arch/arm64/include/asm/vdso/vsyscall.h
+++ b/arch/arm64/include/asm/vdso/vsyscall.h
@@ -15,8 +15,8 @@
 static __always_inline
 void __arm64_update_vsyscall(struct vdso_time_data *vdata)
 {
-	vdata[CS_HRES_COARSE].mask	= VDSO_PRECISION_MASK;
-	vdata[CS_RAW].mask		= VDSO_PRECISION_MASK;
+	vdata->clock_data[CS_HRES_COARSE].mask	= VDSO_PRECISION_MASK;
+	vdata->clock_data[CS_RAW].mask		= VDSO_PRECISION_MASK;
 }
 #define __arch_update_vsyscall __arm64_update_vsyscall
 
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 41ca3586b19f6cac3753b52f0b99be62a33e1cb1..699a18f1c54eb7ec09f7f1cceecd1118aed37ab2 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -79,12 +79,10 @@ void __init time_early_init(void)
 {
 	struct ptff_qto qto;
 	struct ptff_qui qui;
-	int cs;
 
 	/* Initialize TOD steering parameters */
 	tod_steering_end = tod_clock_base.tod;
-	for (cs = 0; cs < CS_BASES; cs++)
-		vdso_k_time_data[cs].arch_data.tod_steering_end = tod_steering_end;
+	vdso_k_time_data->arch_data.tod_steering_end = tod_steering_end;
 
 	if (!test_facility(28))
 		return;
@@ -373,7 +371,6 @@ static void clock_sync_global(long delta)
 {
 	unsigned long now, adj;
 	struct ptff_qto qto;
-	int cs;
 
 	/* Fixup the monotonic sched clock. */
 	tod_clock_base.eitod += delta;
@@ -389,10 +386,8 @@ static void clock_sync_global(long delta)
 		panic("TOD clock sync offset %li is too large to drift\n",
 		      tod_steering_delta);
 	tod_steering_end = now + (abs(tod_steering_delta) << 15);
-	for (cs = 0; cs < CS_BASES; cs++) {
-		vdso_k_time_data[cs].arch_data.tod_steering_end = tod_steering_end;
-		vdso_k_time_data[cs].arch_data.tod_steering_delta = tod_steering_delta;
-	}
+	vdso_k_time_data->arch_data.tod_steering_end = tod_steering_end;
+	vdso_k_time_data->arch_data.tod_steering_delta = tod_steering_delta;
 
 	/* Update LPAR offset. */
 	if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0)
diff --git a/include/asm-generic/vdso/vsyscall.h b/include/asm-generic/vdso/vsyscall.h
index 1fb3000f50364feeaaa9348d438b3ab8091bb265..b550afa15ecd101d821f51ce9105903978dced40 100644
--- a/include/asm-generic/vdso/vsyscall.h
+++ b/include/asm-generic/vdso/vsyscall.h
@@ -9,7 +9,7 @@
 #ifndef __arch_get_vdso_u_time_data
 static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
 {
-	return vdso_u_time_data;
+	return &vdso_u_time_data;
 }
 #endif
 
diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h
index bcd19c223783be7c22f90120330e7dddd0496f1a..9e419394b32443c9e6af67afd9d97ef2b316d8be 100644
--- a/include/vdso/datapage.h
+++ b/include/vdso/datapage.h
@@ -69,9 +69,7 @@ struct vdso_timestamp {
 };
 
 /**
- * struct vdso_time_data - vdso datapage representation
- * @arch_data:		architecture specific data (optional, defaults
- *			to an empty struct)
+ * struct vdso_clock - vdso per clocksource datapage representation
  * @seq:		timebase sequence counter
  * @clock_mode:		clock mode
  * @cycle_last:		timebase at clocksource init
@@ -81,17 +79,9 @@ struct vdso_timestamp {
  * @shift:		clocksource shift
  * @basetime[clock_id]:	basetime per clock_id
  * @offset[clock_id]:	time namespace offset per clock_id
- * @tz_minuteswest:	minutes west of Greenwich
- * @tz_dsttime:		type of DST correction
- * @hrtimer_res:	hrtimer resolution
- * @__unused:		unused
- *
- * vdso_time_data will be accessed by 64 bit and compat code at the same time
- * so we should be careful before modifying this structure.
  *
- * The ordering of the struct members is optimized to have fast access to the
- * often required struct members which are related to CLOCK_REALTIME and
- * CLOCK_MONOTONIC. This information is stored in the first cache lines.
+ * See also struct vdso_time_data for basic access and ordering information as
+ * struct vdso_clock is used there.
  *
  * @basetime is used to store the base time for the system wide time getter
  * VVAR page.
@@ -104,9 +94,7 @@ struct vdso_timestamp {
  * For clocks which are not affected by time namespace adjustment the
  * offset must be zero.
  */
-struct vdso_time_data {
-	struct arch_vdso_time_data arch_data;
-
+struct vdso_clock {
 	u32			seq;
 
 	s32			clock_mode;
@@ -122,6 +110,29 @@ struct vdso_time_data {
 		struct vdso_timestamp	basetime[VDSO_BASES];
 		struct timens_offset	offset[VDSO_BASES];
 	};
+};
+
+/**
+ * struct vdso_time_data - vdso datapage representation
+ * @arch_data:		architecture specific data (optional, defaults
+ *			to an empty struct)
+ * @clock_data:		clocksource related data (array)
+ * @tz_minuteswest:	minutes west of Greenwich
+ * @tz_dsttime:		type of DST correction
+ * @hrtimer_res:	hrtimer resolution
+ * @__unused:		unused
+ *
+ * vdso_time_data will be accessed by 64 bit and compat code at the same time
+ * so we should be careful before modifying this structure.
+ *
+ * The ordering of the struct members is optimized to have fast acces to the
+ * often required struct members which are related to CLOCK_REALTIME and
+ * CLOCK_MONOTONIC. This information is stored in the first cache lines.
+ */
+struct vdso_time_data {
+	struct arch_vdso_time_data arch_data;
+
+	struct vdso_clock	clock_data[CS_BASES];
 
 	s32			tz_minuteswest;
 	s32			tz_dsttime;
@@ -129,8 +140,6 @@ struct vdso_time_data {
 	u32			__unused;
 } ____cacheline_aligned;
 
-#define vdso_clock vdso_time_data
-
 /**
  * struct vdso_rng_data - vdso RNG state information
  * @generation:	counter representing the number of RNG reseeds
@@ -151,7 +160,7 @@ struct vdso_rng_data {
  * relocation, and this is what we need.
  */
 #ifdef CONFIG_GENERIC_VDSO_DATA_STORE
-extern struct vdso_time_data vdso_u_time_data[CS_BASES] __attribute__((visibility("hidden")));
+extern struct vdso_time_data vdso_u_time_data __attribute__((visibility("hidden")));
 extern struct vdso_rng_data vdso_u_rng_data __attribute__((visibility("hidden")));
 extern struct vdso_arch_data vdso_u_arch_data __attribute__((visibility("hidden")));
 
diff --git a/include/vdso/helpers.h b/include/vdso/helpers.h
index 28f0707a46c62187ad7500543e169f5b99deee70..0a98fed550ba66a84a620fbbd6aee3e3029b4772 100644
--- a/include/vdso/helpers.h
+++ b/include/vdso/helpers.h
@@ -30,7 +30,7 @@ static __always_inline u32 vdso_read_retry(const struct vdso_clock *vc,
 
 static __always_inline void vdso_write_begin(struct vdso_time_data *vd)
 {
-	struct vdso_clock *vc = vd;
+	struct vdso_clock *vc = vd->clock_data;
 
 	/*
 	 * WRITE_ONCE() is required otherwise the compiler can validly tear
@@ -44,7 +44,7 @@ static __always_inline void vdso_write_begin(struct vdso_time_data *vd)
 
 static __always_inline void vdso_write_end(struct vdso_time_data *vd)
 {
-	struct vdso_clock *vc = vd;
+	struct vdso_clock *vc = vd->clock_data;
 
 	smp_wmb();
 	/*
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index 09bc4fb39f24ccdaa1e6e7f7238660a4f2a63b54..e3642278df433c41654ffb6a8043c3fcecc2994a 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -237,7 +237,7 @@ static void timens_set_vvar_page(struct task_struct *task,
 
 	ns->frozen_offsets = true;
 	vdata = page_address(ns->vvar_page);
-	vc = vdata;
+	vc = vdata->clock_data;
 
 	for (i = 0; i < CS_BASES; i++)
 		timens_setup_vdso_clock_data(&vc[i], ns);
diff --git a/kernel/time/vsyscall.c b/kernel/time/vsyscall.c
index dd85b41a70bee7decbd943c35197c091916ee4c7..01c2ab1e897193e12be9b981790147ad018e19f3 100644
--- a/kernel/time/vsyscall.c
+++ b/kernel/time/vsyscall.c
@@ -17,8 +17,8 @@
 
 static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct timekeeper *tk)
 {
+	struct vdso_clock *vc = vdata->clock_data;
 	struct vdso_timestamp *vdso_ts;
-	struct vdso_clock *vc = vdata;
 	u64 nsec, sec;
 
 	vc[CS_HRES_COARSE].cycle_last	= tk->tkr_mono.cycle_last;
@@ -78,8 +78,8 @@ static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct ti
 void update_vsyscall(struct timekeeper *tk)
 {
 	struct vdso_time_data *vdata = vdso_k_time_data;
+	struct vdso_clock *vc = vdata->clock_data;
 	struct vdso_timestamp *vdso_ts;
-	struct vdso_clock *vc = vdata;
 	s32 clock_mode;
 	u64 nsec;
 
@@ -109,9 +109,8 @@ void update_vsyscall(struct timekeeper *tk)
 
 	/*
 	 * Read without the seqlock held by clock_getres().
-	 * Note: No need to have a second copy.
 	 */
-	WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution);
+	WRITE_ONCE(vdata->hrtimer_res, hrtimer_resolution);
 
 	/*
 	 * If the current clocksource is not VDSO capable, then spare the
@@ -131,8 +130,8 @@ void update_vsyscall_tz(void)
 {
 	struct vdso_time_data *vdata = vdso_k_time_data;
 
-	vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
-	vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
+	vdata->tz_minuteswest = sys_tz.tz_minuteswest;
+	vdata->tz_dsttime = sys_tz.tz_dsttime;
 
 	__arch_sync_vdso_time_data(vdata);
 }
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index 4e350f56ace335b7ebca8af7663b5731fae27334..c715e217ec6576c34795ad76730faddf6b4c9f8b 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -13,10 +13,10 @@
  */
 #ifdef CONFIG_HAVE_GENERIC_VDSO
 static union {
-	struct vdso_time_data	data[CS_BASES];
+	struct vdso_time_data	data;
 	u8			page[PAGE_SIZE];
 } vdso_time_data_store __page_aligned_data;
-struct vdso_time_data *vdso_k_time_data = vdso_time_data_store.data;
+struct vdso_time_data *vdso_k_time_data = &vdso_time_data_store.data;
 static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE);
 #endif /* CONFIG_HAVE_GENERIC_VDSO */
 
diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index c6ff6934558658f9e280d5b84cfb034f4828893d..93ef801a97ef25f66195490d14e41bebcd41982b 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -87,8 +87,8 @@ int do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *v
 {
 	const struct vdso_time_data *vd = __arch_get_vdso_u_timens_data(vdns);
 	const struct timens_offset *offs = &vcns->offset[clk];
+	const struct vdso_clock *vc = vd->clock_data;
 	const struct vdso_timestamp *vdso_ts;
-	const struct vdso_clock *vc = vd;
 	u64 cycles, ns;
 	u32 seq;
 	s64 sec;
@@ -199,8 +199,8 @@ int do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock
 {
 	const struct vdso_time_data *vd = __arch_get_vdso_u_timens_data(vdns);
 	const struct timens_offset *offs = &vcns->offset[clk];
+	const struct vdso_clock *vc = vd->clock_data;
 	const struct vdso_timestamp *vdso_ts;
-	const struct vdso_clock *vc = vd;
 	u64 nsec;
 	s64 sec;
 	s32 seq;
@@ -265,7 +265,7 @@ static __always_inline int
 __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
 			     struct __kernel_timespec *ts)
 {
-	const struct vdso_clock *vc = vd;
+	const struct vdso_clock *vc = vd->clock_data;
 	u32 msk;
 
 	/* Check for negative values or invalid clocks */
@@ -337,7 +337,7 @@ static __maybe_unused int
 __cvdso_gettimeofday_data(const struct vdso_time_data *vd,
 			  struct __kernel_old_timeval *tv, struct timezone *tz)
 {
-	const struct vdso_clock *vc = vd;
+	const struct vdso_clock *vc = vd->clock_data;
 
 	if (likely(tv != NULL)) {
 		struct __kernel_timespec ts;
@@ -371,13 +371,13 @@ __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 static __maybe_unused __kernel_old_time_t
 __cvdso_time_data(const struct vdso_time_data *vd, __kernel_old_time_t *time)
 {
-	const struct vdso_clock *vc = vd;
+	const struct vdso_clock *vc = vd->clock_data;
 	__kernel_old_time_t t;
 
 	if (IS_ENABLED(CONFIG_TIME_NS) &&
 	    vc->clock_mode == VDSO_CLOCKMODE_TIMENS) {
 		vd = __arch_get_vdso_u_timens_data(vd);
-		vc = vd;
+		vc = vd->clock_data;
 	}
 
 	t = READ_ONCE(vc[CS_HRES_COARSE].basetime[CLOCK_REALTIME].sec);
@@ -399,7 +399,7 @@ static __maybe_unused
 int __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t clock,
 				struct __kernel_timespec *res)
 {
-	const struct vdso_clock *vc = vd;
+	const struct vdso_clock *vc = vd->clock_data;
 	u32 msk;
 	u64 ns;
 
@@ -420,7 +420,7 @@ int __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t clock
 		/*
 		 * Preserves the behaviour of posix_get_hrtimer_res().
 		 */
-		ns = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+		ns = READ_ONCE(vd->hrtimer_res);
 	} else if (msk & VDSO_COARSE) {
 		/*
 		 * Preserves the behaviour of posix_get_coarse_res().

-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:13:32 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:13:32 +0100
Subject: [PATCH v2 03/20] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <20250302-mt6359-accdet-dts-v2-3-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-3-5bd633ee0d47@collabora.com>
Message-ID: <32d41fc8-1855-4078-a5df-a0f3a7cbd423@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> From: Andrew Perepech <andrew.perepech at mediatek.com>
> 
> Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
> allow the mt6359-accdet driver to probe.
> 
> Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:14:51 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:14:51 +0100
Subject: [PATCH v2 01/20] ASoC: dt-bindings: Add document for
 mt6359-accdet
In-Reply-To: <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
Message-ID: <628a81c5-b9f1-4be9-84ec-90022a3526da@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> Add dt-binding for the MT6359 ACCDET hardware block.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>   .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
>   1 file changed, 42 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..d08a79301409374714c76135b061e20e8e8acfaf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> @@ -0,0 +1,42 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MT6359 Accessory Detection
> +
> +maintainers:
> +  - N?colas F. R. A. Prado <nfraprado at collabora.com>
> +
> +description: |
> +  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
> +  detecting audio jack insertion and removal, as well as identifying the type of
> +  events connected to the jack.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt6359-accdet
> +
> +  mediatek,hp-eint-high:
> +    type: boolean
> +    description:
> +      By default, the HP_EINT pin is assumed to be pulled high and connected to

Just to be clearer about this pin being an internal one and not externally sourced,
so, *not* a SoC GPIO, but somehing that is completely provided and handled by the
accdet IP...

"By default, the accdet IP's internal HP_EINT pin is assumed to be pulled ..."

After which:

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

> +      a normally open 3.5mm jack. Plug insertion is detected when the pin is
> +      brought low in that case. Add this property if the behavior should be
> +      inverted, for example if a normally closed 3.5mm jack is used, or if the
> +      line is pulled low on open.
> +
> +required:
> +  - compatible
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    accdet: accdet {
> +        compatible = "mediatek,mt6359-accdet";
> +        mediatek,hp-eint-high;
> +    };
> 




From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:15:24 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:15:24 +0100
Subject: [PATCH v2 06/20] ASoC: mediatek: mt6359-accdet: Implement HP_EINT
 polarity configuration
In-Reply-To: <20250302-mt6359-accdet-dts-v2-6-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-6-5bd633ee0d47@collabora.com>
Message-ID: <ea3cfb5c-bcba-4530-8bd4-6738acfaad90@collabora.com>

Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> From: Andrew Perepech <andrew.perepech at mediatek.com>
> 
> The driver currently reads the HP_EINT polarity from the Devicetree but
> never actually configures the hardware accordingly.
> 
> Implement the polarity configuration in hardware.
> 
> Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From sudeep.holla at arm.com  Mon Mar  3 03:16:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 3 Mar 2025 11:16:24 +0000
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com>
 <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com>
Message-ID: <Z8WPiOweOjFZqTwN@bogus>

On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
> On 2/28/25 20:06, Sudeep Holla wrote:
> > > >
> > > > Ditto as previous patch, can get rid if it is default 1.
> > > >
> > >
> > > On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
> > > cpu_smt_num_threads uninitialized to UINT_MAX:
> > >
> > > smt/active:0
> > > smt/control:-1
> > >
> > > If cpu_smt_set_num_threads() is called:
> > > active:0
> > > control:notsupported
> > >
> > > So it might be slightly better to still initialize max_smt_thread_num.
> > >
> >
> > Sure, what I meant is to have max_smt_thread_num set to 1 by default is
> > that is what needed anyways and the above code does that now.
> >
> > Why not start with initialised to 1 instead ?
> > Of course some current logic needs to change around testing it for zero.
> >
>
> I think there would still be a way to check against the default value.
> If we have:
> unsigned int max_smt_thread_num = 1;
>
> then on a platform with 2 threads, the detection condition would trigger:
> xa_for_each(&hetero_cpu, hetero_id, entry) {
>     if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
>         pr_warn_once("Heterogeneous SMT topology is partly
>                       supported by SMT control\n");
>
> so we would need an additional variable:
> bool is_initialized = false;

Sure, we could do that or skip the check if max_smt_thread_num == 1 ?

I mean
	if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)

I assume entry->thread_num must be set to 1 on single threaded cores
Won't that work ? Am I missing something still ?

--
Regards,
Sudeep


From m-malladi at ti.com  Mon Mar  3 03:16:31 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 16:46:31 +0530
Subject: [PATCH net-next v3 1/3] net: ti: icssg-prueth: Use page_pool API
 for RX buffer allocation
In-Reply-To: <4d57bf7f-fd6b-42bf-86c7-27a308a5bc2a@kernel.org>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-2-m-malladi@ti.com>
 <4d57bf7f-fd6b-42bf-86c7-27a308a5bc2a@kernel.org>
Message-ID: <ba2643d8-d312-4adf-9672-d4525bd9dc91@ti.com>

Hi Roger,

On 2/24/2025 7:50 PM, Roger Quadros wrote:
> 
> 
> On 24/02/2025 13:01, Meghana Malladi wrote:
>> From: Roger Quadros <rogerq at kernel.org>
>>
>> This is to prepare for native XDP support.
>>
>> The page pool API is more faster in allocating pages than
>> __alloc_skb(). Drawback is that it works at PAGE_SIZE granularity
>> so we are not efficient in memory usage.
>> i.e. we are using PAGE_SIZE (4KB) memory for 1.5KB max packet size.
>>
>> Signed-off-by: Roger Quadros <rogerq at kernel.org>
>> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi at ti.com>
>> ---
>> Changes since v2 (v3-v2):
>> - few cosmetic changes for all the patches as suggested by
>> Roger Quadros <rogerq at kernel.org>
>>
>>   drivers/net/ethernet/ti/Kconfig               |   1 +
>>   drivers/net/ethernet/ti/icssg/icssg_common.c  | 174 ++++++++++++------
>>   drivers/net/ethernet/ti/icssg/icssg_prueth.h  |  14 +-
>>   .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  21 ++-
>>   4 files changed, 139 insertions(+), 71 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
>> index 0d5a862cd78a..b461281d31b6 100644
>> --- a/drivers/net/ethernet/ti/Kconfig
>> +++ b/drivers/net/ethernet/ti/Kconfig
>> @@ -204,6 +204,7 @@ config TI_ICSSG_PRUETH_SR1
>>   	select PHYLIB
>>   	select TI_ICSS_IEP
>>   	select TI_K3_CPPI_DESC_POOL
>> +	select PAGE_POOL
>>   	depends on PRU_REMOTEPROC
>>   	depends on NET_SWITCHDEV
>>   	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> index 74f0f200a89d..acbb79ad8b0c 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> @@ -45,6 +45,11 @@ void prueth_cleanup_rx_chns(struct prueth_emac *emac,
>>   			    struct prueth_rx_chn *rx_chn,
>>   			    int max_rflows)
>>   {
>> +	if (rx_chn->pg_pool) {
>> +		page_pool_destroy(rx_chn->pg_pool);
>> +		rx_chn->pg_pool = NULL;
>> +	}
>> +
>>   	if (rx_chn->desc_pool)
>>   		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
>>   
>> @@ -461,17 +466,17 @@ int prueth_init_rx_chns(struct prueth_emac *emac,
>>   }
>>   EXPORT_SYMBOL_GPL(prueth_init_rx_chns);
>>   
>> -int prueth_dma_rx_push(struct prueth_emac *emac,
>> -		       struct sk_buff *skb,
>> -		       struct prueth_rx_chn *rx_chn)
>> +int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
>> +			      struct prueth_rx_chn *rx_chn,
>> +			      struct page *page, u32 buf_len)
>>   {
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>> -	u32 pkt_len = skb_tailroom(skb);
>>   	dma_addr_t desc_dma;
>>   	dma_addr_t buf_dma;
>>   	void **swdata;
>>   
>> +	buf_dma = page_pool_get_dma_addr(page) + PRUETH_HEADROOM;
>>   	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
>>   	if (!desc_rx) {
>>   		netdev_err(ndev, "rx push: failed to allocate descriptor\n");
>> @@ -479,25 +484,18 @@ int prueth_dma_rx_push(struct prueth_emac *emac,
>>   	}
>>   	desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx);
>>   
>> -	buf_dma = dma_map_single(rx_chn->dma_dev, skb->data, pkt_len, DMA_FROM_DEVICE);
>> -	if (unlikely(dma_mapping_error(rx_chn->dma_dev, buf_dma))) {
>> -		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>> -		netdev_err(ndev, "rx push: failed to map rx pkt buffer\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
>>   			 PRUETH_NAV_PS_DATA_SIZE);
>>   	k3_udma_glue_rx_dma_to_cppi5_addr(rx_chn->rx_chn, &buf_dma);
>> -	cppi5_hdesc_attach_buf(desc_rx, buf_dma, skb_tailroom(skb), buf_dma, skb_tailroom(skb));
>> +	cppi5_hdesc_attach_buf(desc_rx, buf_dma, buf_len, buf_dma, buf_len);
>>   
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	*swdata = skb;
>> +	*swdata = page;
>>   
>> -	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, 0,
>> +	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, PRUETH_RX_FLOW_DATA,
>>   					desc_rx, desc_dma);
>>   }
>> -EXPORT_SYMBOL_GPL(prueth_dma_rx_push);
>> +EXPORT_SYMBOL_GPL(prueth_dma_rx_push_mapped);
>>   
>>   u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns)
>>   {
>> @@ -541,12 +539,16 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   	u32 buf_dma_len, pkt_len, port_id = 0;
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>> -	struct sk_buff *skb, *new_skb;
>>   	dma_addr_t desc_dma, buf_dma;
>> +	struct page *page, *new_page;
>> +	struct page_pool *pool;
>> +	struct sk_buff *skb;
>>   	void **swdata;
>>   	u32 *psdata;
>> +	void *pa;
>>   	int ret;
>>   
>> +	pool = rx_chn->pg_pool;
>>   	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
>>   	if (ret) {
>>   		if (ret != -ENODATA)
>> @@ -558,15 +560,9 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   		return 0;
>>   
>>   	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
>> -
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	skb = *swdata;
>> -
>> -	psdata = cppi5_hdesc_get_psdata(desc_rx);
>> -	/* RX HW timestamp */
>> -	if (emac->rx_ts_enabled)
>> -		emac_rx_timestamp(emac, skb, psdata);
>> -
>> +	page = *swdata;
>> +	page_pool_dma_sync_for_cpu(pool, page, 0, PAGE_SIZE);
>>   	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
>>   	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
>>   	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
>> @@ -574,32 +570,51 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   	pkt_len -= 4;
>>   	cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
>>   
>> -	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
>>   	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>>   
>> -	skb->dev = ndev;
>> -	new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
>>   	/* if allocation fails we drop the packet but push the
>> -	 * descriptor back to the ring with old skb to prevent a stall
>> +	 * descriptor back to the ring with old page to prevent a stall
>>   	 */
>> -	if (!new_skb) {
>> +	new_page = page_pool_dev_alloc_pages(pool);
>> +	if (unlikely(!new_page)) {
>> +		new_page = page;
>>   		ndev->stats.rx_dropped++;
>> -		new_skb = skb;
>> -	} else {
>> -		/* send the filled skb up the n/w stack */
>> -		skb_put(skb, pkt_len);
>> -		if (emac->prueth->is_switch_mode)
>> -			skb->offload_fwd_mark = emac->offload_fwd_mark;
>> -		skb->protocol = eth_type_trans(skb, ndev);
>> -		napi_gro_receive(&emac->napi_rx, skb);
>> -		ndev->stats.rx_bytes += pkt_len;
>> -		ndev->stats.rx_packets++;
>> +		goto requeue;
>> +	}
>> +
>> +	/* prepare skb and send to n/w stack */
>> +	pa = page_address(page);
>> +	skb = napi_build_skb(pa, PAGE_SIZE);
>> +	if (!skb) {
>> +		ndev->stats.rx_dropped++;
>> +		page_pool_recycle_direct(pool, page);
>> +		goto requeue;
>>   	}
>>   
>> +	skb_reserve(skb, PRUETH_HEADROOM);
>> +	skb_put(skb, pkt_len);
>> +	skb->dev = ndev;
>> +
>> +	psdata = cppi5_hdesc_get_psdata(desc_rx);
>> +	/* RX HW timestamp */
>> +	if (emac->rx_ts_enabled)
>> +		emac_rx_timestamp(emac, skb, psdata);
>> +
>> +	if (emac->prueth->is_switch_mode)
>> +		skb->offload_fwd_mark = emac->offload_fwd_mark;
>> +	skb->protocol = eth_type_trans(skb, ndev);
>> +
>> +	skb_mark_for_recycle(skb);
>> +	napi_gro_receive(&emac->napi_rx, skb);
>> +	ndev->stats.rx_bytes += pkt_len;
>> +	ndev->stats.rx_packets++;
>> +
>> +requeue:
>>   	/* queue another RX DMA */
>> -	ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_chns);
>> +	ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page,
>> +					PRUETH_MAX_PKT_SIZE);
>>   	if (WARN_ON(ret < 0)) {
>> -		dev_kfree_skb_any(new_skb);
>> +		page_pool_recycle_direct(pool, new_page);
>>   		ndev->stats.rx_errors++;
>>   		ndev->stats.rx_dropped++;
>>   	}
>> @@ -611,22 +626,16 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma)
>>   {
>>   	struct prueth_rx_chn *rx_chn = data;
>>   	struct cppi5_host_desc_t *desc_rx;
>> -	struct sk_buff *skb;
>> -	dma_addr_t buf_dma;
>> -	u32 buf_dma_len;
>> +	struct page_pool *pool;
>> +	struct page *page;
>>   	void **swdata;
>>   
>> +	pool = rx_chn->pg_pool;
>>   	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	skb = *swdata;
>> -	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
>> -	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
>> -
>> -	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len,
>> -			 DMA_FROM_DEVICE);
>> +	page = *swdata;
>> +	page_pool_recycle_direct(pool, page);
>>   	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>> -
>> -	dev_kfree_skb_any(skb);
>>   }
>>   
>>   static int prueth_tx_ts_cookie_get(struct prueth_emac *emac)
>> @@ -907,29 +916,71 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
>>   }
>>   EXPORT_SYMBOL_GPL(icssg_napi_rx_poll);
>>   
>> +static struct page_pool *prueth_create_page_pool(struct prueth_emac *emac,
>> +						 struct device *dma_dev,
>> +						 int size)
>> +{
>> +	struct page_pool_params pp_params = { 0 };
>> +	struct page_pool *pool;
>> +
>> +	pp_params.order = 0;
>> +	pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
>> +	pp_params.pool_size = size;
>> +	pp_params.nid = dev_to_node(emac->prueth->dev);
>> +	pp_params.dma_dir = DMA_BIDIRECTIONAL;
>> +	pp_params.dev = dma_dev;
>> +	pp_params.napi = &emac->napi_rx;
>> +	pp_params.max_len = PAGE_SIZE;
>> +
>> +	pool = page_pool_create(&pp_params);
>> +	if (IS_ERR(pool))
>> +		netdev_err(emac->ndev, "cannot create rx page pool\n");
>> +
>> +	return pool;
>> +}
>> +
>>   int prueth_prepare_rx_chan(struct prueth_emac *emac,
>>   			   struct prueth_rx_chn *chn,
>>   			   int buf_size)
>>   {
>> -	struct sk_buff *skb;
>> +	struct page_pool *pool;
>> +	struct page *page;
>>   	int i, ret;
>>   
>> +	pool = prueth_create_page_pool(emac, chn->dma_dev, chn->descs_num);
>> +	if (IS_ERR(pool))
>> +		return PTR_ERR(pool);
>> +
>> +	chn->pg_pool = pool;
>> +
>>   	for (i = 0; i < chn->descs_num; i++) {
>> -		skb = __netdev_alloc_skb_ip_align(NULL, buf_size, GFP_KERNEL);
>> -		if (!skb)
>> -			return -ENOMEM;
>> +		/* NOTE: we're not using memory efficiently here.
>> +		 * 1 full page (4KB?) used here instead of
>> +		 * PRUETH_MAX_PKT_SIZE (~1.5KB?)
>> +		 */
>> +		page = page_pool_dev_alloc_pages(pool);
>> +		if (!page) {
>> +			netdev_err(emac->ndev, "couldn't allocate rx page\n");
>> +			ret = -ENOMEM;
>> +			goto recycle_alloc_pg;
>> +		}
>>   
>> -		ret = prueth_dma_rx_push(emac, skb, chn);
>> +		ret = prueth_dma_rx_push_mapped(emac, chn, page, buf_size);
>>   		if (ret < 0) {
>>   			netdev_err(emac->ndev,
>> -				   "cannot submit skb for rx chan %s ret %d\n",
>> +				   "cannot submit page for rx chan %s ret %d\n",
>>   				   chn->name, ret);
>> -			kfree_skb(skb);
>> -			return ret;
>> +			page_pool_recycle_direct(pool, page);
>> +			goto recycle_alloc_pg;
>>   		}
>>   	}
>>   
>>   	return 0;
>> +
>> +recycle_alloc_pg:
>> +	prueth_reset_rx_chan(&emac->rx_chns, PRUETH_MAX_RX_FLOWS, false);
>> +
>> +	return ret;
>>   }
>>   EXPORT_SYMBOL_GPL(prueth_prepare_rx_chan);
>>   
>> @@ -958,6 +1009,9 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
>>   					  prueth_rx_cleanup, !!i);
>>   	if (disable)
>>   		k3_udma_glue_disable_rx_chn(chn->rx_chn);
>> +
>> +	page_pool_destroy(chn->pg_pool);
>> +	chn->pg_pool = NULL;
>>   }
>>   EXPORT_SYMBOL_GPL(prueth_reset_rx_chan);
>>   
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> index 329b46e9ee53..c7b906de18af 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> @@ -33,6 +33,8 @@
>>   #include <linux/dma/k3-udma-glue.h>
>>   
>>   #include <net/devlink.h>
>> +#include <net/xdp.h>
>> +#include <net/page_pool/helpers.h>
>>   
>>   #include "icssg_config.h"
>>   #include "icss_iep.h"
>> @@ -131,6 +133,7 @@ struct prueth_rx_chn {
>>   	u32 descs_num;
>>   	unsigned int irq[ICSSG_MAX_RFLOWS];	/* separate irq per flow */
>>   	char name[32];
>> +	struct page_pool *pg_pool;
>>   };
>>   
>>   /* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3)
>> @@ -210,6 +213,10 @@ struct prueth_emac {
>>   	struct netdev_hw_addr_list vlan_mcast_list[MAX_VLAN_ID];
>>   };
>>   
>> +/* The buf includes headroom compatible with both skb and xdpf */
>> +#define PRUETH_HEADROOM_NA (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN)
>> +#define PRUETH_HEADROOM  ALIGN(PRUETH_HEADROOM_NA, sizeof(long))
>> +
>>   /**
>>    * struct prueth_pdata - PRUeth platform data
>>    * @fdqring_mode: Free desc queue mode
>> @@ -410,9 +417,10 @@ int prueth_init_rx_chns(struct prueth_emac *emac,
>>   			struct prueth_rx_chn *rx_chn,
>>   			char *name, u32 max_rflows,
>>   			u32 max_desc_num);
>> -int prueth_dma_rx_push(struct prueth_emac *emac,
>> -		       struct sk_buff *skb,
>> -		       struct prueth_rx_chn *rx_chn);
>> +int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
>> +			      struct prueth_rx_chn *rx_chn,
>> +			      struct page *page, u32 buf_len);
>> +unsigned int prueth_rxbuf_total_len(unsigned int len);
>>   void emac_rx_timestamp(struct prueth_emac *emac,
>>   		       struct sk_buff *skb, u32 *psdata);
>>   enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev);
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> index 64a19ff39562..aeeb8a50376b 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> @@ -274,10 +274,12 @@ static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
> 
> This is how we can get rid of skb from RX management code.
> 
> Change return type of this function and callers to struct page *
> 
>>   	struct prueth_rx_chn *rx_chn = &emac->rx_mgm_chn;
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>> -	struct sk_buff *skb, *new_skb;
>> +	struct page *page, *new_page;
>>   	dma_addr_t desc_dma, buf_dma;
>>   	u32 buf_dma_len, pkt_len;
>> +	struct sk_buff *skb;
> 
> drop skb
> 
>>   	void **swdata;
>> +	void *pa;
> 
> drop pa
> 
>>   	int ret;
>>   
>>   	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
>> @@ -299,32 +301,35 @@ static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
>>   	}
>>   
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	skb = *swdata;
>> +	page = *swdata;
>>   	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
>>   	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
>>   
>>   	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
>>   	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>>   
>> -	new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
>> +	new_page = page_pool_dev_alloc_pages(rx_chn->pg_pool);
>>   	/* if allocation fails we drop the packet but push the
>>   	 * descriptor back to the ring with old skb to prevent a stall
>>   	 */
>> -	if (!new_skb) {
>> +	if (!new_page) {
>>   		netdev_err(ndev,
>> -			   "skb alloc failed, dropped mgm pkt from flow %d\n",
>> +			   "page alloc failed, dropped mgm pkt from flow %d\n",
>>   			   flow_id);
>> -		new_skb = skb;
>> +		new_page = page;
>>   		skb = NULL;	/* return NULL */
> 
> page = NULL;
> 
>>   	} else {
>>   		/* return the filled skb */
>> +		pa = page_address(page);
>> +		skb = napi_build_skb(pa, PAGE_SIZE);
>>   		skb_put(skb, pkt_len);
>>   	}
> 
> drop entire else
> 
>>   
>>   	/* queue another DMA */
>> -	ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_mgm_chn);
>> +	ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page,
>> +					PRUETH_MAX_PKT_SIZE);
>>   	if (WARN_ON(ret < 0))
>> -		dev_kfree_skb_any(new_skb);
>> +		page_pool_recycle_direct(rx_chn->pg_pool, new_page);
>>   
>>   	return skb;
> 
> return page;
> 
>>   }
> 
> 
> In the callers to prueth_process_rx_mgm() use page_address(page) to get the virtual
> address i.e. in place of skb->data.
> Where you are freeing the SKB do a page_pool_recycle_direct(page->pg_pool, page);
> 

Ok thanks, I will incorporate these changes in v4 and send these patches 
to Diogo for testing.

Regards,
Meghana



From m-malladi at ti.com  Mon Mar  3 03:23:03 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 16:53:03 +0530
Subject: [PATCH net-next v3 2/3] net: ti: icssg-prueth: introduce and use
 prueth_swdata struct for SWDATA
In-Reply-To: <3d3d180a-12b7-4bee-8172-700f0dae2439@kernel.org>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-3-m-malladi@ti.com>
 <3d3d180a-12b7-4bee-8172-700f0dae2439@kernel.org>
Message-ID: <dbddfb0c-01f3-4a07-82b3-81929c3c4420@ti.com>



On 2/27/2025 5:57 PM, Roger Quadros wrote:
> 
> 
> On 24/02/2025 13:01, Meghana Malladi wrote:
>> From: Roger Quadros <rogerq at kernel.org>
>>
>> We have different cases for SWDATA (skb, page, cmd, etc)
>> so it is better to have a dedicated data structure for that.
>> We can embed the type field inside the struct and use it
>> to interpret the data in completion handlers.
>>
>> Increase SWDATA size to 48 so we have some room to add
>> more data if required.
>>
>> Signed-off-by: Roger Quadros <rogerq at kernel.org>
>> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi at ti.com>
>> ---
>> Changes since v2 (v3-v2):
>> - Fix leaking tx descriptor in emac_tx_complete_packets()
>> - Free rx descriptor if swdata type is not page in emac_rx_packet()
>> - Revert back the size of PRUETH_NAV_SW_DATA_SIZE
>> - Use build time check for prueth_swdata size
>> - re-write prueth_swdata to have enum type as first member in the struct
>> and prueth_data union embedded in the struct
>>
>> All the above changes have been suggested by Roger Quadros <rogerq at kernel.org>
>>
>>   drivers/net/ethernet/ti/icssg/icssg_common.c  | 52 +++++++++++++------
>>   drivers/net/ethernet/ti/icssg/icssg_prueth.c  |  3 ++
>>   drivers/net/ethernet/ti/icssg/icssg_prueth.h  | 16 ++++++
>>   .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  4 +-
>>   4 files changed, 57 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> index acbb79ad8b0c..01eeabe83eff 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> @@ -136,12 +136,12 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_tx;
>>   	struct netdev_queue *netif_txq;
>> +	struct prueth_swdata *swdata;
>>   	struct prueth_tx_chn *tx_chn;
>>   	unsigned int total_bytes = 0;
>>   	struct sk_buff *skb;
>>   	dma_addr_t desc_dma;
>>   	int res, num_tx = 0;
>> -	void **swdata;
>>   
>>   	tx_chn = &emac->tx_chns[chn];
>>   
>> @@ -163,12 +163,19 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
>>   		swdata = cppi5_hdesc_get_swdata(desc_tx);
>>   
>>   		/* was this command's TX complete? */
>> -		if (emac->is_sr1 && *(swdata) == emac->cmd_data) {
>> +		if (emac->is_sr1 && (void *)(swdata) == emac->cmd_data) {
>>   			prueth_xmit_free(tx_chn, desc_tx);
>>   			continue;
>>   		}
>>   
>> -		skb = *(swdata);
>> +		if (swdata->type != PRUETH_SWDATA_SKB) {
>> +			netdev_err(ndev, "tx_complete: invalid swdata type %d\n", swdata->type);
>> +			prueth_xmit_free(tx_chn, desc_tx);
>> +			budget++;
> 
> I don't recollect why we need to increase budget here.
> 

Probably because this packet hasn't been processed due to invalid swdata 
we are increasing the budget to compensate the loss -> but sounds 
counter intuitive to whole idea of using the budget. Will remove it.


>> +			continue;
>> +		}
>> +
>> +		skb = swdata->data.skb;
>>   		prueth_xmit_free(tx_chn, desc_tx);
> 
> if we set swdata->type to PRUETH_SWDATA_CMD in emac_send_command_sr1() then we could
> reduce all above code including both ifs to
> 
> 		swdata = cppi5_hdesc_get_swdata(desc_tx);
> 		prueth_xmit_free(tx_chn, desc_tx);
> 		if (swdata->type != PRUETH_SWDATA_SKB)
> 			continue;
> 
> 		skb = swdata->data.skb;

Yes this is a nice change. This also addresses the concern Dan pointed 
out regarding SR1's emac->cmd_data check. I was also wondering the same 
to use PRUETH_SWDATA_CMD for addressing Dan's comment. Thanks.

> 
>>   
>>   		ndev = skb->dev;
>> @@ -472,9 +479,9 @@ int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
>>   {
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>> +	struct prueth_swdata *swdata;
>>   	dma_addr_t desc_dma;
>>   	dma_addr_t buf_dma;
>> -	void **swdata;
>>   
>>   	buf_dma = page_pool_get_dma_addr(page) + PRUETH_HEADROOM;
>>   	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
>> @@ -490,7 +497,8 @@ int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
>>   	cppi5_hdesc_attach_buf(desc_rx, buf_dma, buf_len, buf_dma, buf_len);
>>   
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	*swdata = page;
>> +	swdata->type = PRUETH_SWDATA_PAGE;
>> +	swdata->data.page = page;
>>   
>>   	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, PRUETH_RX_FLOW_DATA,
>>   					desc_rx, desc_dma);
>> @@ -539,11 +547,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   	u32 buf_dma_len, pkt_len, port_id = 0;
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>> +	struct prueth_swdata *swdata;
>>   	dma_addr_t desc_dma, buf_dma;
>>   	struct page *page, *new_page;
>>   	struct page_pool *pool;
>>   	struct sk_buff *skb;
>> -	void **swdata;
>>   	u32 *psdata;
>>   	void *pa;
>>   	int ret;
>> @@ -561,7 +569,13 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>   
>>   	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	page = *swdata;
>> +	if (swdata->type != PRUETH_SWDATA_PAGE) {
>> +		netdev_err(ndev, "rx_pkt: invalid swdata->type %d\n", swdata->type);
>> +		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>> +		return 0;
>> +	}
>> +
>> +	page = swdata->data.page;
>>   	page_pool_dma_sync_for_cpu(pool, page, 0, PAGE_SIZE);
>>   	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
>>   	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
>> @@ -626,15 +640,18 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma)
>>   {
>>   	struct prueth_rx_chn *rx_chn = data;
>>   	struct cppi5_host_desc_t *desc_rx;
>> +	struct prueth_swdata *swdata;
>>   	struct page_pool *pool;
>>   	struct page *page;
>> -	void **swdata;
>>   
>>   	pool = rx_chn->pg_pool;
>>   	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	page = *swdata;
>> -	page_pool_recycle_direct(pool, page);
>> +	if (swdata->type == PRUETH_SWDATA_PAGE) {
>> +		page = swdata->data.page;
>> +		page_pool_recycle_direct(pool, page);
>> +	}
>> +
>>   	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
>>   }
>>   
>> @@ -671,13 +688,13 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
>>   	struct prueth_emac *emac = netdev_priv(ndev);
>>   	struct prueth *prueth = emac->prueth;
>>   	struct netdev_queue *netif_txq;
>> +	struct prueth_swdata *swdata;
>>   	struct prueth_tx_chn *tx_chn;
>>   	dma_addr_t desc_dma, buf_dma;
>>   	u32 pkt_len, dst_tag_id;
>>   	int i, ret = 0, q_idx;
>>   	bool in_tx_ts = 0;
>>   	int tx_ts_cookie;
>> -	void **swdata;
>>   	u32 *epib;
>>   
>>   	pkt_len = skb_headlen(skb);
>> @@ -739,7 +756,8 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
>>   	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
>>   	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
>>   	swdata = cppi5_hdesc_get_swdata(first_desc);
>> -	*swdata = skb;
>> +	swdata->type = PRUETH_SWDATA_SKB;
>> +	swdata->data.skb = skb;
>>   
>>   	/* Handle the case where skb is fragmented in pages */
>>   	cur_desc = first_desc;
>> @@ -842,15 +860,17 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
>>   {
>>   	struct prueth_tx_chn *tx_chn = data;
>>   	struct cppi5_host_desc_t *desc_tx;
>> +	struct prueth_swdata *swdata;
>>   	struct sk_buff *skb;
>> -	void **swdata;
>>   
>>   	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
>>   	swdata = cppi5_hdesc_get_swdata(desc_tx);
>> -	skb = *(swdata);
>> -	prueth_xmit_free(tx_chn, desc_tx);
>> +	if (swdata->type == PRUETH_SWDATA_SKB) {
>> +		skb = swdata->data.skb;
>> +		dev_kfree_skb_any(skb);
>> +	}
>>   
>> -	dev_kfree_skb_any(skb);
>> +	prueth_xmit_free(tx_chn, desc_tx);
>>   }
>>   
>>   irqreturn_t prueth_rx_irq(int irq, void *dev_id)
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> index 00ed97860547..3ff8c322f9d9 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> @@ -1522,6 +1522,9 @@ static int prueth_probe(struct platform_device *pdev)
>>   
>>   	np = dev->of_node;
>>   
>> +	BUILD_BUG_ON_MSG((sizeof(struct prueth_swdata) > PRUETH_NAV_SW_DATA_SIZE),
>> +			 "insufficient SW_DATA size");
>> +
>>   	prueth = devm_kzalloc(dev, sizeof(*prueth), GFP_KERNEL);
>>   	if (!prueth)
>>   		return -ENOMEM;
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> index c7b906de18af..3bbabd007129 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> @@ -136,6 +136,22 @@ struct prueth_rx_chn {
>>   	struct page_pool *pg_pool;
>>   };
>>   
>> +enum prueth_swdata_type {
>> +	PRUETH_SWDATA_INVALID = 0,
>> +	PRUETH_SWDATA_SKB,
>> +	PRUETH_SWDATA_PAGE,
>> +	PRUETH_SWDATA_CMD,
> 
> PRUETH_SWDATA_CMD is not beig used so let's use it in emac_send_command_sr1()
> 

Yes, will do that. This is actually a miss in my previous patches.

>> +};
>> +
>> +struct prueth_swdata {
>> +	enum prueth_swdata_type type;
>> +	union prueth_data {
>> +		struct sk_buff *skb;
>> +		struct page *page;
>> +		u32 cmd;
>> +	} data;
>> +};
>> +
>>   /* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3)
>>    * and lower three are lower priority channels or threads.
>>    */
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> index aeeb8a50376b..7bbe0808b3ec 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
>> @@ -275,10 +275,10 @@ static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
>>   	struct net_device *ndev = emac->ndev;
>>   	struct cppi5_host_desc_t *desc_rx;
>>   	struct page *page, *new_page;
>> +	struct prueth_swdata *swdata;
>>   	dma_addr_t desc_dma, buf_dma;
>>   	u32 buf_dma_len, pkt_len;
>>   	struct sk_buff *skb;
>> -	void **swdata;
>>   	void *pa;
>>   	int ret;
>>   
>> @@ -301,7 +301,7 @@ static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
>>   	}
>>   
>>   	swdata = cppi5_hdesc_get_swdata(desc_rx);
>> -	page = *swdata;
>> +	page = swdata->data.page;
>>   	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
>>   	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
>>   
> 



From peterz at infradead.org  Mon Mar  3 03:24:48 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 3 Mar 2025 12:24:48 +0100
Subject: [PATCH bpf-next v3 1/4] x86/ibt: factor out cfi and fineibt
 offset
In-Reply-To: <CADxym3as+KdeBMUigq4xq302g2U7UG-7Gm+vKiYGnSjHouq=bg@mail.gmail.com>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
 <20250303065345.229298-2-dongml2@chinatelecom.cn>
 <20250303091811.GH5880@noisy.programming.kicks-ass.net>
 <CADxym3as+KdeBMUigq4xq302g2U7UG-7Gm+vKiYGnSjHouq=bg@mail.gmail.com>
Message-ID: <20250303112448.GZ11590@noisy.programming.kicks-ass.net>

On Mon, Mar 03, 2025 at 06:51:41PM +0800, Menglong Dong wrote:
> On Mon, Mar 3, 2025 at 5:18?PM Peter Zijlstra <peterz at infradead.org> wrote:
> >
> > On Mon, Mar 03, 2025 at 02:53:42PM +0800, Menglong Dong wrote:
> > > index c71b575bf229..ad050d09cb2b 100644
> > > --- a/arch/x86/kernel/alternative.c
> > > +++ b/arch/x86/kernel/alternative.c
> > > @@ -908,7 +908,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end, struct mod
> > >
> > >               poison_endbr(addr, wr_addr, true);
> > >               if (IS_ENABLED(CONFIG_FINEIBT))
> > > -                     poison_cfi(addr - 16, wr_addr - 16);
> > > +                     poison_cfi(addr, wr_addr);
> > >       }
> > >  }
> >
> > If you're touching this code, please use tip/x86/core or tip/master.
> 
> Thank you for reminding me that, I were using the linux-next, and

That must've been an very old -next, because that wr_addr crap has been
gone a while now.

Anyway, thanks for moving to a newer tree!


From mazziesaccount at gmail.com  Mon Mar  3 03:30:59 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 3 Mar 2025 13:30:59 +0200
Subject: [PATCH v5 00/10] Support ROHM BD79124 ADC
Message-ID: <cover.1740993491.git.mazziesaccount@gmail.com>

Support ROHM BD79124 ADC.

This series adds also couple of IIO ADC helper functions for parsing the
channel information from the device tree. There are also two helpers
included for counting number of firmware child nodes with a specific name.

Series does also convert couple of drivers to use these helpers. The
rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.

The gianfar driver under net is added as an RFC patch to use the newly
added firmware child node counting function.

There has been some discussion about how useful these ADC helpers are,
and whether they should support also differential and single ended channel
configurations. This version does not include support for those - with the
benefit of reduced complexity and easier to use API.

patch 6/10 is small simplification for the ti-ads7924, and it can be
taken independently from the rest of the series.

NOTE: Patches 4...6 and the patch 10 are untested as I lack of relevant HW.
They have been compile tested only.

The ROHM BD79124 ADC itself is quite usual stuff. 12-bit, 8-channel ADC
with threshold monitoring.

Except that:
 - each ADC input pin can be configured as a general purpose output.
 - manually starting an ADC conversion and reading the result would
   require the I2C _master_ to do clock stretching(!) for the duration
   of the conversion... Let's just say this is not well supported.
 - IC supports 'autonomous measurement mode' and storing latest results
   to the result registers. This mode is used by the driver due to the
   "peculiar" I2C when doing manual reads.

Furthermore, the ADC uses this continuous autonomous measuring,
and the IC keeps producing new 'out of window' IRQs if measurements are
out of window - the driver disables the event for 1 seconds when sending
it to user. This prevents generating storm of events

Revision history:
v4 => v5: Fixes as per various review comments. Most notably:
 - Drop the patch making the TI's ADC driver to respect device tree.
 - Add (RFC) patch converting gianfar driver to use new name child-node
   counting API as suggested by Andy.
 - Add fwnode_get_child_node_count_named() as suggested by Rob.
 Changes which were not proposed by reviewers:
 - rebase to v6.14-rc5
 - Do not include all recipients to all of the patches.
 More accurate changelog in individual patches.
v3 => v4:
 - Drop the ADC helper support for differential channels
 - Drop the ADC helper for getting only channel IDs by fwnode.
 - "Promote" the function counting the number of child nodes with a
   specific name to the property.h (As suggested by Jonathan).
 - Add ADC helpers to a namespace.
 - Rebase on v6.14-rc3
 - More minor changes described in individual patches.
v2 => v3:
 - Restrict BD79124 channel numbers as suggested by Conor and add
   Conor's Reviewed-by tag.
 - Support differential and single-ended inputs
 - Convert couple of existing drivers to use the added ADC helpers
 - Minor fixes based on reviews
Link to v2:
https://lore.kernel.org/all/cover.1738761899.git.mazziesaccount at gmail.com/

RFC v1 => v2:
 - Drop MFD and pinmux.
 - Automatically re-enable events after 1 second.
 - Export fwnode parsing helpers for finding the ADC channels.

---

Matti Vaittinen (10):
  dt-bindings: ROHM BD79124 ADC/GPO
  property: Add functions to count named child nodes
  iio: adc: add helpers for parsing ADC nodes
  iio: adc: rzg2l_adc: Use adc-helpers
  iio: adc: sun20i-gpadc: Use adc-helpers
  iio: adc: ti-ads7924 Drop unnecessary function parameters
  iio: adc: Support ROHM BD79124 ADC
  MAINTAINERS: Add IIO ADC helpers
  MAINTAINERS: Add ROHM BD79124 ADC/GPO
  net: gianfar: Use device_get_child_node_count_named()

 .../bindings/iio/adc/rohm,bd79124.yaml        |  114 ++
 MAINTAINERS                                   |   12 +
 drivers/base/property.c                       |   57 +
 drivers/iio/adc/Kconfig                       |   17 +
 drivers/iio/adc/Makefile                      |    3 +
 drivers/iio/adc/industrialio-adc.c            |   82 ++
 drivers/iio/adc/rohm-bd79124.c                | 1108 +++++++++++++++++
 drivers/iio/adc/rzg2l_adc.c                   |   38 +-
 drivers/iio/adc/sun20i-gpadc-iio.c            |   38 +-
 drivers/iio/adc/ti-ads7924.c                  |    7 +-
 drivers/net/ethernet/freescale/gianfar.c      |   17 +-
 include/linux/iio/adc-helpers.h               |   27 +
 include/linux/property.h                      |    4 +
 13 files changed, 1462 insertions(+), 62 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 drivers/iio/adc/rohm-bd79124.c
 create mode 100644 include/linux/iio/adc-helpers.h


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/5dc62b39/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar  3 03:32:12 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 3 Mar 2025 13:32:12 +0200
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1740993491.git.mazziesaccount@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
Message-ID: <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v4 => v5:
- Inline iio_adc_device_num_channels()
- Fix Indenting function parameters
- Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 82 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 114 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..7bdae5330224
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use -1 if no checking
+ *			is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on succes. Negative value to indicate
+ *		failure.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan = 0, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 1)
+		return num_chan;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_child_node_scoped(dev, child) {
+		u32 ch;
+
+		if (!fwnode_name_eq(child, "channel"))
+			continue;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id != -1 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..403a70b109ec
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_child_node_count_named(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/6311d10e/attachment.sig>

From angelogioacchino.delregno at collabora.com  Mon Mar  3 03:32:29 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 12:32:29 +0100
Subject: [PATCH 1/2] arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI
 DSI port
In-Reply-To: <20250226-radxa-panel-overlay-v1-1-9e8938dfbead@collabora.com>
References: <20250226-radxa-panel-overlay-v1-0-9e8938dfbead@collabora.com>
 <20250226-radxa-panel-overlay-v1-1-9e8938dfbead@collabora.com>
Message-ID: <fc0a9471-da47-4f4f-a471-1b20f344ad22@collabora.com>

Il 26/02/25 15:35, Julien Massot ha scritto:
> This board can use a MIPI-DSI panel on the DSI0 connector: in
> preparation for adding an overlay for the Radxa Display 8HD,
> add a pipeline connecting VDOSYS0 components to DSI0.
> 
> Also add the backlight, and some pin definitions available
> through the DSI0 port.
> 
> Signed-off-by: Julien Massot <julien.massot at collabora.com>
> ---
>   .../boot/dts/mediatek/mt8395-radxa-nio-12l.dts     | 60 ++++++++++++++++++++++
>   1 file changed, 60 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> index 7184dc99296c7f5d749c7e6d378722677970b3b7..65c77e43d1cd4913b6741e25130febd746ff753c 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> +++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> @@ -48,6 +48,17 @@ memory at 40000000 {
>   		reg = <0 0x40000000 0x1 0x0>;
>   	};
>   
> +	backlight: backlight {
> +		compatible = "pwm-backlight";
> +		brightness-levels = <0 1023>;
> +		default-brightness-level = <576>;
> +		enable-gpios = <&pio 107 GPIO_ACTIVE_HIGH>;
> +		num-interpolated-steps = <1023>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&dsi0_backlight_pins>;
> +		pwms = <&disp_pwm0 0 500000>;

This should be disabled, unless there is a display connected to the DSI connector.

If there's no display, there's no point in enabling any backlight, as that pin
may be reused somehow (with hardware hacks, maybe, yes, but still configuring
the PWM IP and the pin as PWM while unused is at least a waste of energy).

> +	};
> +
>   	wifi_vreg: regulator-wifi-3v3-en {
>   		compatible = "regulator-fixed";
>   		regulator-name = "wifi_3v3_en";
> @@ -499,9 +510,20 @@ &mt6359_vsram_others_ldo_reg {
>   	regulator-max-microvolt = <750000>;
>   };
>   
> +&ovl0_in {
> +	remote-endpoint = <&vdosys0_ep_main>;
> +};
> +

This goes to the overlay that enables the DSI display.

> @@ -912,6 +960,18 @@ &ssusb2 {
>   	status = "okay";
>   };
>   
> +&vdosys0 {
> +	port {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		vdosys0_ep_main: endpoint at 0 {
> +			reg = <0>;
> +			remote-endpoint = <&ovl0_in>;
> +		};
> +	};
> +};

If you enable this path, in the event that the DSI display overlay is not added,
the mediatek-drm driver will fail probing: even if a second path is enabled and
that will succeed regardless of the first one failing, I don't see a reason why
whoever doesn't have a DSI display attached should see a miserable failure in the
kernel log :-)

Besides, mediatek-drm failing will also slow down boot for no reason.... etc etc.

Please move the display path setup to the DSI display overlay.

Thanks,
Angelo

> +
>   &xhci0 {
>   	vbus-supply = <&otg_vbus_regulator>;
>   	status = "okay";
> 



From mazziesaccount at gmail.com  Mon Mar  3 03:33:02 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 3 Mar 2025 13:33:02 +0200
Subject: [PATCH v5 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1740993491.git.mazziesaccount@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
Message-ID: <aabd8836dbe54ef54730d1cd112edb52a57cd353.1740993491.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-propereties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 38 ++++++++++++------------------
 2 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..bf1db2a3de9b 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,37 +150,27 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
+
 	if (num_channels == 0)
 		return dev_err_probe(dev, -ENODEV, "no channel children\n");
 
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
-
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
 
@@ -271,3 +262,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/081d548c/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar  3 03:34:06 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 3 Mar 2025 13:34:06 +0200
Subject: [PATCH v5 08/10] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1740993491.git.mazziesaccount@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
Message-ID: <78c18b224cd18b1bd83eea51c7e52dcea28e3d50.1740993491.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/c35b45c0/attachment.sig>

From m-malladi at ti.com  Mon Mar  3 04:06:41 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 17:36:41 +0530
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth: Add
 XDP support
In-Reply-To: <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
Message-ID: <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>



On 2/26/2025 4:19 PM, Dan Carpenter wrote:
> On Mon, Feb 24, 2025 at 04:?31:?02PM +0530, Meghana Malladi wrote: > @@ 
> -541,7 +558,153 @@ void emac_rx_timestamp(struct prueth_emac *emac, > 
> ssh->hwtstamp = ns_to_ktime(ns); > } > > -static int 
> emac_rx_packet(struct prueth_emac
> ZjQcmQRYFpfptBannerStart
> This message was sent from outside of Texas Instruments.
> Do not click links or open attachments unless you recognize the source 
> of this email and know the content is safe.
> Report?Suspicious
> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK! 
> uldgnXdPPE27auXFPdnpH8jx2nnu2fsVXLMVOyEVUH9IX54g6v7RJRENIKzAm7XCuLfioMeFBSH4bAdUdQTaEArV63odoRERqTN_5Pk$>
> ZjQcmQRYFpfptBannerEnd
> 
> On Mon, Feb 24, 2025 at 04:31:02PM +0530, Meghana Malladi wrote:
>> @@ -541,7 +558,153 @@ void emac_rx_timestamp(struct prueth_emac *emac,
>>  	ssh->hwtstamp = ns_to_ktime(ns);
>>  }
>>  
>> -static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>> +/**
>> + * emac_xmit_xdp_frame - transmits an XDP frame
>> + * @emac: emac device
>> + * @xdpf: data to transmit
>> + * @page: page from page pool if already DMA mapped
>> + * @q_idx: queue id
>> + *
>> + * Return: XDP state
>> + */
>> +int emac_xmit_xdp_frame(struct prueth_emac *emac,
>> +			struct xdp_frame *xdpf,
>> +			struct page *page,
>> +			unsigned int q_idx)
>> +{
>> +	struct cppi5_host_desc_t *first_desc;
>> +	struct net_device *ndev = emac->ndev;
>> +	struct prueth_tx_chn *tx_chn;
>> +	dma_addr_t desc_dma, buf_dma;
>> +	struct prueth_swdata *swdata;
>> +	u32 *epib;
>> +	int ret;
>> +
>> +	void *data = xdpf->data;
>> +	u32 pkt_len = xdpf->len;
> 
> Get rid of these variables?
> 

Yeah ok

>> +
>> +	if (q_idx >= PRUETH_MAX_TX_QUEUES) {
>> +		netdev_err(ndev, "xdp tx: invalid q_id %d\n", q_idx);
>> +		return ICSSG_XDP_CONSUMED;	/* drop */
>> +	}
>> +
>> +	tx_chn = &emac->tx_chns[q_idx];
>> +
>> +	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
>> +	if (!first_desc) {
>> +		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
>> +		goto drop_free_descs;	/* drop */
>> +	}
>> +
>> +	if (page) { /* already DMA mapped by page_pool */
>> +		buf_dma = page_pool_get_dma_addr(page);
>> +		buf_dma += xdpf->headroom + sizeof(struct xdp_frame);
>> +	} else { /* Map the linear buffer */
>> +		buf_dma = dma_map_single(tx_chn->dma_dev, data, pkt_len, DMA_TO_DEVICE);
>> +		if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
>> +			netdev_err(ndev, "xdp tx: failed to map data buffer\n");
>> +			goto drop_free_descs;	/* drop */
>> +		}
>> +	}
>> +
>> +	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
>> +			 PRUETH_NAV_PS_DATA_SIZE);
>> +	cppi5_hdesc_set_pkttype(first_desc, 0);
>> +	epib = first_desc->epib;
>> +	epib[0] = 0;
>> +	epib[1] = 0;
>> +
>> +	/* set dst tag to indicate internal qid at the firmware which is at
>> +	 * bit8..bit15. bit0..bit7 indicates port num for directed
>> +	 * packets in case of switch mode operation
>> +	 */
>> +	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
>> +	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
>> +	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
>> +	swdata = cppi5_hdesc_get_swdata(first_desc);
>> +	if (page) {
>> +		swdata->type = PRUETH_SWDATA_PAGE;
>> +		swdata->data.page = page;
>> +	} else {
>> +		swdata->type = PRUETH_SWDATA_XDPF;
>> +		swdata->data.xdpf = xdpf;
>> +	}
>> +
>> +	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
>> +	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
>> +
>> +	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
>> +	if (ret) {
>> +		netdev_err(ndev, "xdp tx: push failed: %d\n", ret);
>> +		goto drop_free_descs;
>> +	}
>> +
>> +	return ICSSG_XDP_TX;
>> +
>> +drop_free_descs:
>> +	prueth_xmit_free(tx_chn, first_desc);
>> +	return ICSSG_XDP_CONSUMED;
>> +}
>> +EXPORT_SYMBOL_GPL(emac_xmit_xdp_frame);
>> +
>> +/**
>> + * emac_run_xdp - run an XDP program
>> + * @emac: emac device
>> + * @xdp: XDP buffer containing the frame
>> + * @page: page with RX data if already DMA mapped
>> + *
>> + * Return: XDP state
>> + */
>> +static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
>> +			struct page *page)
>> +{
>> +	struct net_device *ndev = emac->ndev;
>> +	int err, result = ICSSG_XDP_PASS;
>> +	struct bpf_prog *xdp_prog;
>> +	struct xdp_frame *xdpf;
>> +	int q_idx;
>> +	u32 act;
>> +
>> +	xdp_prog = READ_ONCE(emac->xdp_prog);
>> +	act = bpf_prog_run_xdp(xdp_prog, xdp);
>> +	switch (act) {
>> +	case XDP_PASS:
>> +		break;
>> +	case XDP_TX:
>> +		/* Send packet to TX ring for immediate transmission */
>> +		xdpf = xdp_convert_buff_to_frame(xdp);
>> +		if (unlikely(!xdpf))
> 
> This is the second unlikely() macro which is added in this patchset.
> The rule with likely/unlikely() is that it should only be added if it
> likely makes a difference in benchmarking.  Quite often the compiler
> is able to predict that valid pointers are more likely than NULL
> pointers so often these types of annotations don't make any difference
> at all to the compiled code.  But it depends on the compiler and the -O2
> options.
> 

Do correct me if I am wrong, but from my understanding, XDP feature 
depends alot of performance and benchmarking and having unlikely does 
make a difference. Atleast in all the other drivers I see this being 
used for XDP.

>> +			goto drop;
>> +
>> +		q_idx = smp_processor_id() % emac->tx_ch_num;
>> +		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
>> +		if (result == ICSSG_XDP_CONSUMED)
>> +			goto drop;
>> +		break;
>> +	case XDP_REDIRECT:
>> +		err = xdp_do_redirect(emac->ndev, xdp, xdp_prog);
>> +		if (err)
>> +			goto drop;
>> +		result = ICSSG_XDP_REDIR;
>> +		break;
>> +	default:
>> +		bpf_warn_invalid_xdp_action(emac->ndev, xdp_prog, act);
>> +		fallthrough;
>> +	case XDP_ABORTED:
>> +drop:
>> +		trace_xdp_exception(emac->ndev, xdp_prog, act);
>> +		fallthrough; /* handle aborts by dropping packet */
>> +	case XDP_DROP:
>> +		ndev->stats.tx_dropped++;
>> +		result = ICSSG_XDP_CONSUMED;
>> +		page_pool_recycle_direct(emac->rx_chns.pg_pool, page);
>> +		break;
>> +	}
>> +
>> +	return result;
>> +}
>> +
>> +static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, int *xdp_state)
> 
> 
> xdp_state should be a u32 because it's a bitfield.  Bitfields are never
> signed.

Ok I will update it.

> 
>>  {
>>  	struct prueth_rx_chn *rx_chn = &emac->rx_chns;
>>  	u32 buf_dma_len, pkt_len, port_id = 0;
>> @@ -552,10 +715,12 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>  	struct page *page, *new_page;
>>  	struct page_pool *pool;
>>  	struct sk_buff *skb;
>> +	struct xdp_buff xdp;
>>  	u32 *psdata;
>>  	void *pa;
>>  	int ret;
>>  
>> +	*xdp_state = 0;
>>  	pool = rx_chn->pg_pool;
>>  	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
>>  	if (ret) {
>> @@ -596,9 +761,21 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
>>  		goto requeue;
>>  	}
>>  
>> -	/* prepare skb and send to n/w stack */
>>  	pa = page_address(page);
>> -	skb = napi_build_skb(pa, PAGE_SIZE);
>> +	if (emac->xdp_prog) {
>> +		xdp_init_buff(&xdp, PAGE_SIZE, &rx_chn->xdp_rxq);
>> +		xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false);
>> +
>> +		*xdp_state = emac_run_xdp(emac, &xdp, page);
>> +		if (*xdp_state == ICSSG_XDP_PASS)
>> +			skb = xdp_build_skb_from_buff(&xdp);
>> +		else
>> +			goto requeue;
>> +	} else {
>> +		/* prepare skb and send to n/w stack */
>> +		skb = napi_build_skb(pa, PAGE_SIZE);
>> +	}
>> +
>>  	if (!skb) {
>>  		ndev->stats.rx_dropped++;
>>  		page_pool_recycle_direct(pool, page);
>> @@ -861,13 +1038,23 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
>>  	struct prueth_tx_chn *tx_chn = data;
>>  	struct cppi5_host_desc_t *desc_tx;
>>  	struct prueth_swdata *swdata;
>> +	struct xdp_frame *xdpf;
>>  	struct sk_buff *skb;
>>  
>>  	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
>>  	swdata = cppi5_hdesc_get_swdata(desc_tx);
>> -	if (swdata->type == PRUETH_SWDATA_SKB) {
>> +
>> +	switch (swdata->type) {
>> +	case PRUETH_SWDATA_SKB:
>>  		skb = swdata->data.skb;
>>  		dev_kfree_skb_any(skb);
>> +		break;
>> +	case PRUETH_SWDATA_XDPF:
>> +		xdpf = swdata->data.xdpf;
>> +		xdp_return_frame(xdpf);
>> +		break;
>> +	default:
>> +		break;
>>  	}
>>  
>>  	prueth_xmit_free(tx_chn, desc_tx);
>> @@ -904,15 +1091,18 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
>>  		PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA;
>>  	int flow = emac->is_sr1 ?
>>  		PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
>> +	int xdp_state_or = 0;
>>  	int num_rx = 0;
>>  	int cur_budget;
>> +	int xdp_state;
> 
> Both xdp_state_or and xdp_state should be u32 because they are bitfields.
> 

Ok I will update it.

> regards,
> dan carpenter
> 
>>  	int ret;
>>  
>>  	while (flow--) {
>>  		cur_budget = budget - num_rx;
>>  
>>  		while (cur_budget--) {
>> -			ret = emac_rx_packet(emac, flow);
>> +			ret = emac_rx_packet(emac, flow, &xdp_state);
>> +			xdp_state_or |= xdp_state;
>>  			if (ret)
>>  				break;
>>  			num_rx++;
> 



From liviu.dudau at arm.com  Mon Mar  3 04:08:51 2025
From: liviu.dudau at arm.com (Liviu Dudau)
Date: Mon, 3 Mar 2025 12:08:51 +0000
Subject: [PATCH 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-7-marex@denx.de>
 <Z8GY0nWXOxCKF-XL@e110455-lin.cambridge.arm.com>
 <fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
Message-ID: <Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>

On Fri, Feb 28, 2025 at 06:05:36PM +0100, Marek Vasut wrote:
> On 2/28/25 12:06 PM, Liviu Dudau wrote:
> > Hi Marek,
> 
> Hi,
> 
> > On Thu, Feb 27, 2025 at 05:58:06PM +0100, Marek Vasut wrote:
> > > This seems necessary on Freescale i.MX95 Mali G310 to reliably resume
> > > from runtime PM suspend. Without this, if only the L2 is powered down
> > > on RPM entry, the GPU gets stuck and does not indicate the firmware is
> > > booted after RPM resume.
> > 
> > That doesn't sound right. Can you tell me what GPU firmware are you running
> > (we are now printing the git sha of the image at boot time).
> Please see below. It could be some sort of NXP firmware fork ?
> 
> It comes from the NXP firmware repo , mali-imx-r50.2-710cfb6 .
> 
> panthor 4d900000.gpu: [drm] clock rate = 1000000000
> panthor 4d900000.gpu: EM: created perf domain
> panthor 4d900000.gpu: [drm] mali-unknown id 0xac74 major 0x0 minor 0x0
> status 0x1
> panthor 4d900000.gpu: [drm] Features: L2:0x7110306 Tiler:0x809 Mem:0x1
> MMU:0x2830 AS:0xff
> panthor 4d900000.gpu: [drm] shader_present=0x1 l2_present=0x1
> tiler_present=0x1
> panthor 4d900000.gpu: [drm] Firmware protected mode entry not be supported,
> ignoring
> panthor 4d900000.gpu: [drm] Firmware git sha:
> 8e5cfcfec20cc8aff8509d37e72babc935d34a3b

This looks like it has been part of a R50 release of the DDK, which is recent
enough to consider it up-to-date. The issues you're seeing with fast resume are
probably due to some integration issues or other quirks.

Boris has the most recent experience with playing with fast resume, maybe
he can share some tips on where to add messages in Panthor to try to debug
your problem.

Best regards,
Liviu

> panthor 4d900000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0
> Instrumentation features 0x71
> [drm] Initialized panthor 1.3.0 for 4d900000.gpu on minor 0
> 
> $ sha256sum mali_csffw.bin
> befd23b9279b26010ebf35c835cc3aa7d0f50758930c7306ff4f5abbe5218624
> mali_csffw.bin
> 
> [...]

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From dan.carpenter at linaro.org  Mon Mar  3 04:31:05 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 3 Mar 2025 15:31:05 +0300
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth:
 Add XDP support
In-Reply-To: <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
 <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
Message-ID: <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>

On Mon, Mar 03, 2025 at 05:36:41PM +0530, Malladi, Meghana wrote:
> > > +static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
> > > +			struct page *page)
> > > +{
> > > +	struct net_device *ndev = emac->ndev;
> > > +	int err, result = ICSSG_XDP_PASS;
> > > +	struct bpf_prog *xdp_prog;
> > > +	struct xdp_frame *xdpf;
> > > +	int q_idx;
> > > +	u32 act;
> > > +
> > > +	xdp_prog = READ_ONCE(emac->xdp_prog);
> > > +	act = bpf_prog_run_xdp(xdp_prog, xdp);
> > > +	switch (act) {
> > > +	case XDP_PASS:
> > > +		break;
> > > +	case XDP_TX:
> > > +		/* Send packet to TX ring for immediate transmission */
> > > +		xdpf = xdp_convert_buff_to_frame(xdp);
> > > +		if (unlikely(!xdpf))
> > 
> > This is the second unlikely() macro which is added in this patchset.
> > The rule with likely/unlikely() is that it should only be added if it
> > likely makes a difference in benchmarking.  Quite often the compiler
> > is able to predict that valid pointers are more likely than NULL
> > pointers so often these types of annotations don't make any difference
> > at all to the compiled code.  But it depends on the compiler and the -O2
> > options.
> > 
> 
> Do correct me if I am wrong, but from my understanding, XDP feature depends
> alot of performance and benchmarking and having unlikely does make a
> difference. Atleast in all the other drivers I see this being used for XDP.
> 

Which compiler are you on when you say that "having unlikely does make a
difference"?

I'm on gcc version 14.2.0 (Debian 14.2.0-16) and it doesn't make a
difference to the compiled code.  This matches what one would expect from
a compiler.  Valid pointers are fast path and NULL pointers are slow path.

Adding an unlikely() is a micro optimization.  There are so many other
things you can do to speed up the code.  I wouldn't start with that.

regards,
dan



From angelogioacchino.delregno at collabora.com  Mon Mar  3 04:34:29 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 13:34:29 +0100
Subject: [v2] spi: spi-mtk-nor: Modify the clock architecture of nor
 controller
In-Reply-To: <20250303114540.1617-1-Cloud.Zhang@mediatek.com>
References: <20250303114540.1617-1-Cloud.Zhang@mediatek.com>
Message-ID: <12c5ba3e-a151-44a8-ace7-3d944a09ae5e@collabora.com>

Il 03/03/25 12:45, mtk22730 ha scritto:
> The clocks used by different platforms are not same. So it is
> necessary to modify the clock architecture to be adaptable to more
> platforms.
> 
> Signed-off-by: Cloud Zhang <cloud.zhang at mediatek.com>

You really shall fix your identity on outgoing emails: your name appears as
"mtk22730", that's not right.

Also, the title could be clarified a bit...

spi: spi-mtk-nor: Migrate to clk_bulk API

...and then: this should be a series, and the first commit shall be adjusting
the dt-binding for this driver accordigly, otherwise whatever you're doing here
will turn out to be unusable.

> ---
> Changes in v2:
>    -Use clk_bulk_xxx related functions to enable/disable clocks.
> 
> Changes in v1:
>    -Add new function mtk_nor_parse_clk() to parse nor clock parameters.
> ---
> ---
>   drivers/spi/spi-mtk-nor.c | 103 ++++++++++++++++++++------------------
>   1 file changed, 54 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
> index 85ab5ce96c4d..4863b9cb2706 100644
> --- a/drivers/spi/spi-mtk-nor.c
> +++ b/drivers/spi/spi-mtk-nor.c
> @@ -99,6 +99,8 @@
>   
>   #define CLK_TO_US(sp, clkcnt)		DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)
>   
> +#define MAX_CLOCK_CNT		6
> +
>   struct mtk_nor_caps {
>   	u8 dma_bits;
>   
> @@ -116,10 +118,8 @@ struct mtk_nor {
>   	void __iomem *base;
>   	u8 *buffer;
>   	dma_addr_t buffer_dma;
> -	struct clk *spi_clk;
> -	struct clk *ctlr_clk;
> -	struct clk *axi_clk;
> -	struct clk *axi_s_clk;
> +	struct clk_bulk_data clocks[MAX_CLOCK_CNT];

What about having this as a pointer?

	struct clk_bulk_data *clks;

...Then you count the clocks, and devm allocate the number of clks that you need.

> +	int clock_cnt;

u8 clock_cnt;

>   	unsigned int spi_freq;
>   	bool wbuf_en;
>   	bool has_irq;
> @@ -703,44 +703,68 @@ static int mtk_nor_transfer_one_message(struct spi_controller *host,
>   
>   static void mtk_nor_disable_clk(struct mtk_nor *sp)

A function with one call means that you don't need a function at all.

>   {
> -	clk_disable_unprepare(sp->spi_clk);
> -	clk_disable_unprepare(sp->ctlr_clk);
> -	clk_disable_unprepare(sp->axi_clk);
> -	clk_disable_unprepare(sp->axi_s_clk);
> +	clk_bulk_disable_unprepare(sp->clock_cnt, sp->clocks);
>   }
>   
>   static int mtk_nor_enable_clk(struct mtk_nor *sp)
>   {

You can also remove this function and transfer the contents into mtk_nor_probe():
it's just something like 6 lines and even called only once, so... :-)

>   	int ret;
> +	int i;
>   
> -	ret = clk_prepare_enable(sp->spi_clk);
> -	if (ret)
> -		return ret;
> -
> -	ret = clk_prepare_enable(sp->ctlr_clk);
> +	ret = clk_bulk_prepare_enable(sp->clock_cnt, sp->clocks);
>   	if (ret) {
> -		clk_disable_unprepare(sp->spi_clk);
> +		dev_err(sp->dev, "enable clk failed\n");
>   		return ret;
>   	}
>   
> -	ret = clk_prepare_enable(sp->axi_clk);
> -	if (ret) {
> -		clk_disable_unprepare(sp->spi_clk);
> -		clk_disable_unprepare(sp->ctlr_clk);
> -		return ret;
> -	}
> +	for (i = 0; i < sp->clock_cnt; i++) {
> +		if (IS_ERR(sp->clocks[i].clk)) {
> +			dev_err(sp->dev, "get %s fail\n", sp->clocks[i].id);
> +			return PTR_ERR(sp->clocks[i].clk);
> +		}
>   
> -	ret = clk_prepare_enable(sp->axi_s_clk);
> -	if (ret) {
> -		clk_disable_unprepare(sp->spi_clk);
> -		clk_disable_unprepare(sp->ctlr_clk);
> -		clk_disable_unprepare(sp->axi_clk);
> -		return ret;
> +		if (!strcmp(sp->clocks[i].id, "spi"))
> +			sp->spi_freq = clk_get_rate(sp->clocks[i].clk);
>   	}
>   
>   	return 0;
>   }
>   
> +static int mtk_nor_parse_clk(struct device *dev, struct mtk_nor *sp)
> +{
> +	struct device_node *np = dev->of_node;
> +	int ret;
> +	const char *name;
> +	int cnt, i;

	struct device_node *np = dev->of_node;
	const char *name;
	int cnt, i, ret;


> +
> +	cnt = of_property_count_strings(np, "clock-names");
> +	if (!cnt || (cnt == -EINVAL)) {
> +		dev_err(dev, "Unable to find clocks\n");

return -EINVAL;

> +		ret = -EINVAL;
> +		goto out;
> +	} else if (cnt < 0) {
> +		dev_err(dev, "Count clock strings failed, err %d\n", cnt);

return cnt;

> +		ret = cnt;
> +		goto out;
> +	}
> +
> +	sp->clock_cnt = cnt;
> +	for (i = 0; i < cnt; i++) {
> +		ret = of_property_read_string_index(np, "clock-names", i, &name);
> +		if (ret) {
> +			dev_err(dev, "failed to get clock string\n");
> +			return ret;
> +		}
> +
> +		sp->clocks[i].id = name;
> +	}
> +
> +	ret = devm_clk_bulk_get(dev, sp->clock_cnt, sp->clocks);

	if (ret)
		return ret;

	return 0;

> +
> +out:
> +	return ret;
> +}
> +

Cheers,
Angelo



From boris.brezillon at collabora.com  Mon Mar  3 04:35:23 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 3 Mar 2025 13:35:23 +0100
Subject: [PATCH 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>
References: <20250227170012.124768-1-marex@denx.de>
	<20250227170012.124768-7-marex@denx.de>
	<Z8GY0nWXOxCKF-XL@e110455-lin.cambridge.arm.com>
	<fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
	<Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>
Message-ID: <20250303133523.2c5153ed@collabora.com>

On Mon, 3 Mar 2025 12:08:51 +0000
Liviu Dudau <liviu.dudau at arm.com> wrote:

> On Fri, Feb 28, 2025 at 06:05:36PM +0100, Marek Vasut wrote:
> > On 2/28/25 12:06 PM, Liviu Dudau wrote:  
> > > Hi Marek,  
> > 
> > Hi,
> >   
> > > On Thu, Feb 27, 2025 at 05:58:06PM +0100, Marek Vasut wrote:  
> > > > This seems necessary on Freescale i.MX95 Mali G310 to reliably resume
> > > > from runtime PM suspend. Without this, if only the L2 is powered down
> > > > on RPM entry, the GPU gets stuck and does not indicate the firmware is
> > > > booted after RPM resume.  
> > > 
> > > That doesn't sound right. Can you tell me what GPU firmware are you running
> > > (we are now printing the git sha of the image at boot time).  
> > Please see below. It could be some sort of NXP firmware fork ?
> > 
> > It comes from the NXP firmware repo , mali-imx-r50.2-710cfb6 .
> > 
> > panthor 4d900000.gpu: [drm] clock rate = 1000000000
> > panthor 4d900000.gpu: EM: created perf domain
> > panthor 4d900000.gpu: [drm] mali-unknown id 0xac74 major 0x0 minor 0x0
> > status 0x1
> > panthor 4d900000.gpu: [drm] Features: L2:0x7110306 Tiler:0x809 Mem:0x1
> > MMU:0x2830 AS:0xff
> > panthor 4d900000.gpu: [drm] shader_present=0x1 l2_present=0x1
> > tiler_present=0x1
> > panthor 4d900000.gpu: [drm] Firmware protected mode entry not be supported,
> > ignoring
> > panthor 4d900000.gpu: [drm] Firmware git sha:
> > 8e5cfcfec20cc8aff8509d37e72babc935d34a3b  
> 
> This looks like it has been part of a R50 release of the DDK, which is recent
> enough to consider it up-to-date. The issues you're seeing with fast resume are
> probably due to some integration issues or other quirks.
> 
> Boris has the most recent experience with playing with fast resume, maybe
> he can share some tips on where to add messages in Panthor to try to debug
> your problem.

If you end up with fast_reset=true, that means the FW claims it entered
a suspend state from which is can resume quickly (fast-reset), and in
that case, we're only supposed to power on the L2 block at resume time
AFAIK. If there's a component that can tell us more, it's probably the
FW, unfortunately, it doesn't tell us much through the FW interface,
especially if it's not booting properly. Do you hit this error [1]
without this patch, and if you do, what's the status reported there?

[1]https://elixir.bootlin.com/linux/v6.14-rc4/source/drivers/gpu/drm/panthor/panthor_fw.c#L1051


From boris.brezillon at collabora.com  Mon Mar  3 04:42:50 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 3 Mar 2025 13:42:50 +0100
Subject: [PATCH 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <20250303133523.2c5153ed@collabora.com>
References: <20250227170012.124768-1-marex@denx.de>
	<20250227170012.124768-7-marex@denx.de>
	<Z8GY0nWXOxCKF-XL@e110455-lin.cambridge.arm.com>
	<fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
	<Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>
	<20250303133523.2c5153ed@collabora.com>
Message-ID: <20250303134250.5ba726fc@collabora.com>

On Mon, 3 Mar 2025 13:35:23 +0100
Boris Brezillon <boris.brezillon at collabora.com> wrote:

> On Mon, 3 Mar 2025 12:08:51 +0000
> Liviu Dudau <liviu.dudau at arm.com> wrote:
> 
> > On Fri, Feb 28, 2025 at 06:05:36PM +0100, Marek Vasut wrote:  
> > > On 2/28/25 12:06 PM, Liviu Dudau wrote:    
> > > > Hi Marek,    
> > > 
> > > Hi,
> > >     
> > > > On Thu, Feb 27, 2025 at 05:58:06PM +0100, Marek Vasut wrote:    
> > > > > This seems necessary on Freescale i.MX95 Mali G310 to reliably resume
> > > > > from runtime PM suspend. Without this, if only the L2 is powered down
> > > > > on RPM entry, the GPU gets stuck and does not indicate the firmware is
> > > > > booted after RPM resume.    
> > > > 
> > > > That doesn't sound right. Can you tell me what GPU firmware are you running
> > > > (we are now printing the git sha of the image at boot time).    
> > > Please see below. It could be some sort of NXP firmware fork ?
> > > 
> > > It comes from the NXP firmware repo , mali-imx-r50.2-710cfb6 .
> > > 
> > > panthor 4d900000.gpu: [drm] clock rate = 1000000000
> > > panthor 4d900000.gpu: EM: created perf domain
> > > panthor 4d900000.gpu: [drm] mali-unknown id 0xac74 major 0x0 minor 0x0
> > > status 0x1
> > > panthor 4d900000.gpu: [drm] Features: L2:0x7110306 Tiler:0x809 Mem:0x1
> > > MMU:0x2830 AS:0xff
> > > panthor 4d900000.gpu: [drm] shader_present=0x1 l2_present=0x1
> > > tiler_present=0x1
> > > panthor 4d900000.gpu: [drm] Firmware protected mode entry not be supported,
> > > ignoring
> > > panthor 4d900000.gpu: [drm] Firmware git sha:
> > > 8e5cfcfec20cc8aff8509d37e72babc935d34a3b    
> > 
> > This looks like it has been part of a R50 release of the DDK, which is recent
> > enough to consider it up-to-date. The issues you're seeing with fast resume are
> > probably due to some integration issues or other quirks.
> > 
> > Boris has the most recent experience with playing with fast resume, maybe
> > he can share some tips on where to add messages in Panthor to try to debug
> > your problem.  
> 
> If you end up with fast_reset=true, that means the FW claims it entered
> a suspend state from which is can resume quickly (fast-reset), and in
> that case, we're only supposed to power on the L2 block at resume time
> AFAIK.

Can you try deasserting the reset lines at probe time and keeping them
deasserted until the device is removed instead of re-asserting at
suspend time? If that doesn't work, try doing the same with power
domains.

> If there's a component that can tell us more, it's probably the
> FW, unfortunately, it doesn't tell us much through the FW interface,
> especially if it's not booting properly. Do you hit this error [1]
> without this patch, and if you do, what's the status reported there?
> 
> [1]https://elixir.bootlin.com/linux/v6.14-rc4/source/drivers/gpu/drm/panthor/panthor_fw.c#L1051



From chunkuang.hu at kernel.org  Mon Mar  3 04:57:29 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 20:57:29 +0800
Subject: [PATCH] drm/mediatek: Fix config_updating flag never false when
 no mbox channel
In-Reply-To: <20250224051301.3538484-1-jason-jh.lin@mediatek.com>
References: <20250224051301.3538484-1-jason-jh.lin@mediatek.com>
Message-ID: <CAAOTY_8cGVEYV2v6oAHHnVqfjk3jp_a1QtaYJRqDf1Hg4vY0UA@mail.gmail.com>

Hi, Jason:

Jason-JH Lin <jason-jh.lin at mediatek.com> ? 2025?2?24? ?? ??1:13???
>
> When CONFIG_MTK_CMDQ is enabled, if the display is controlled by the CPU
> while other hardware is controlled by the GCE, the display will encounter
> a mbox request channel failure.
> However, it will still enter the CONFIG_MTK_CMDQ statement, causing the
> config_updating flag to never be set to false. As a result, no page flip
> event is sent back to user space, and the screen does not update.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Fixes: da03801ad08f ("drm/mediatek: Move mtk_crtc_finish_page_flip() to ddp_cmdq_cb()")
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_crtc.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
> index 5674f5707cca..cfc4867296b8 100644
> --- a/drivers/gpu/drm/mediatek/mtk_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
> @@ -620,13 +620,14 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
>
>                 mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
>                 mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
> +               goto update_config_out;
>         }
> -#else
> +#endif
>         spin_lock_irqsave(&mtk_crtc->config_lock, flags);
>         mtk_crtc->config_updating = false;
>         spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
> -#endif
>
> +update_config_out:
>         mutex_unlock(&mtk_crtc->hw_lock);
>  }
>
> --
> 2.43.0
>


From dmitry.baryshkov at linaro.org  Mon Mar  3 04:57:42 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Mon, 3 Mar 2025 14:57:42 +0200
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <65706d63-18aa-41e0-81c4-4eab3d186250@rock-chips.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
 <65706d63-18aa-41e0-81c4-4eab3d186250@rock-chips.com>
Message-ID: <udunb6r3yvjc5i5cfk5xeaz6ezvyzbnor3gujjhcfoavdwtrsl@26yxnjan6yqb>

On Mon, Mar 03, 2025 at 04:59:50PM +0800, Yubing Zhang wrote:
> Hi Dmitry,
> 
> On 2025/3/2 2:14, Dmitry Baryshkov wrote:
> > On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
> > > From: Andy Yan <andy.yan at rock-chips.com>
> > > 
> > > The DW DP TX Controller is compliant with the DisplayPort Specification
> > > Version 1.4 with the following features:
> > > 
> > > * DisplayPort 1.4a
> > > * Main Link: 1/2/4 lanes
> > > * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
> > > * AUX channel 1Mbps
> > > * Single Stream Transport(SST)
> > > * Multistream Transport (MST)
> > > *?Type-C support (alternate mode)
> > > * HDCP 2.2, HDCP 1.3
> > > * Supports up to 8/10 bits per color component
> > > * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
> > > * Pixel clock up to 594MHz
> > > * I2S, SPDIF audio interface
> > > 
> > > Add library with common helpers to make it can be shared with
> > > other SoC.
> > > 
> > > Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> > > 
> > > drm/bridge: cleanup
> > 
> > Stray line?
> > 
> > > 
> > > ---
> > > 
> > >   drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
> > >   drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
> > >   drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
> > >   include/drm/bridge/dw_dp.h               |   19 +
> > >   4 files changed, 2182 insertions(+)
> > >   create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
> 
> ......
> 
> > > +
> > > +static u8 dw_dp_voltage_max(u8 preemph)
> > > +{
> > > +	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
> > > +	case DP_TRAIN_PRE_EMPH_LEVEL_0:
> > > +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
> > > +	case DP_TRAIN_PRE_EMPH_LEVEL_1:
> > > +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
> > > +	case DP_TRAIN_PRE_EMPH_LEVEL_2:
> > > +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
> > > +	case DP_TRAIN_PRE_EMPH_LEVEL_3:
> > > +	default:
> > > +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
> > > +	}
> > > +}
> > > +
> > > +static void dw_dp_link_get_adjustments(struct dw_dp_link *link,
> > > +				       u8 status[DP_LINK_STATUS_SIZE])
> > > +{
> > > +	struct dw_dp_link_train_set *adjust = &link->train.adjust;
> > > +	u8 v = 0;
> > > +	u8 p = 0;
> > > +	unsigned int i;
> > > +
> > > +	for (i = 0; i < link->lanes; i++) {
> > > +		v = drm_dp_get_adjust_request_voltage(status, i);
> > > +		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
> > > +		if (p >=  DP_TRAIN_PRE_EMPH_LEVEL_3) {
> > > +			adjust->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
> > > +						  DP_TRAIN_PRE_EMPHASIS_SHIFT;
> > > +			adjust->pre_max_reached[i] = true;
> > > +		} else {
> > > +			adjust->pre_emphasis[i] = p >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
> > > +			adjust->pre_max_reached[i] = false;
> > > +		}
> > > +		v = min(v, dw_dp_voltage_max(p));
> > > +		if (v >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) {
> > > +			adjust->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
> > > +						   DP_TRAIN_VOLTAGE_SWING_SHIFT;
> > > +			adjust->voltage_max_reached[i] = true;
> > > +		} else {
> > > +			adjust->voltage_swing[i] = v >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
> > > +			adjust->voltage_max_reached[i] = false;
> > > +		}
> > > +	}
> > > +}
> > > +
> > > +static void dw_dp_link_train_adjust(struct dw_dp_link_train *train)
> > > +{
> > > +	struct dw_dp_link_train_set *request = &train->request;
> > > +	struct dw_dp_link_train_set *adjust = &train->adjust;
> > > +	unsigned int i;
> > > +
> > > +	for (i = 0; i < 4; i++) {
> > 
> > Shouldn't it be a loop up to link->lanes?
> > 
> > > +		if (request->voltage_swing[i] != adjust->voltage_swing[i])
> > > +			request->voltage_swing[i] = adjust->voltage_swing[i];
> > > +		if (request->voltage_max_reached[i] != adjust->voltage_max_reached[i])
> > > +			request->voltage_max_reached[i] = adjust->voltage_max_reached[i];
> > > +	}
> > > +
> > > +	for (i = 0; i < 4; i++) {
> > > +		if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
> > > +			request->pre_emphasis[i] = adjust->pre_emphasis[i];
> > > +		if (request->pre_max_reached[i] != adjust->pre_max_reached[i])
> > > +			request->pre_max_reached[i] = adjust->pre_max_reached[i];
> > 
> > Why do you need separate request and adjustment structs?
> During link training cr sequence, if dprx keep the LANEx_CR_DONE bit(s)
> cleared, the request and adjustment structs are used to check the
> old and new valud of ADJUST_REQUEST_LANEx_y register(s) is changed or not.

This can be compared in dw_dp_link_get_adjustments(), before / while
updating the request data.

> 
> > 
> > > +	}
> > > +}
> > > +
> > > +static int dw_dp_link_clock_recovery(struct dw_dp *dp)
> > > +{
> > > +	struct dw_dp_link *link = &dp->link;
> > > +	u8 status[DP_LINK_STATUS_SIZE];
> > > +	unsigned int tries = 0;
> > > +	int ret;
> > > +
> > > +	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	for (;;) {
> > > +		ret = dw_dp_link_train_update_vs_emph(dp);
> > > +		if (ret)
> > > +			return ret;
> > > +
> > > +		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
> > > +
> > > +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> > > +		if (ret < 0) {
> > > +			dev_err(dp->dev, "failed to read link status: %d\n", ret);
> > > +			return ret;
> > > +		}
> > > +
> > > +		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
> > > +			link->train.clock_recovered = true;
> > > +			break;
> > > +		}
> > > +
> > > +		dw_dp_link_get_adjustments(link, status);
> > > +
> > > +		if (link->train.request.voltage_swing[0] ==
> > > +		    link->train.adjust.voltage_swing[0])
> > 
> > Should this take all lanes to account? I think it might be posssible to
> > drop the adjust / request split and adjust tries in
> > dw_dp_link_get_adjustments() instead.
> Yes, here shall compare both swing and pre-emphasis for all lanes. It's a
> good idea to drop the adjust / request split. The swing and pre-emphasis
> compare just need by cr sequence. But both cr and eq sequences use
> dw_dp_link_get_adjustments(). It will be better to delete
> dw_dp_link_train_adjust() and add a new function to adjust tries for cr
> sequence.

SGTM.

> > 
> > > +			tries++;
> > > +		else
> > > +			tries = 0;
> > > +
> > > +		if (tries == 5)
> > > +			break;
> > > +
> > > +		dw_dp_link_train_adjust(&link->train);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int dw_dp_link_channel_equalization(struct dw_dp *dp)
> > > +{
> > > +	struct dw_dp_link *link = &dp->link;
> > > +	u8 status[DP_LINK_STATUS_SIZE], pattern;
> > > +	unsigned int tries;
> > > +	int ret;
> > > +
> > > +	if (link->caps.tps4_supported)
> > > +		pattern = DP_TRAINING_PATTERN_4;
> > > +	else if (link->caps.tps3_supported)
> > > +		pattern = DP_TRAINING_PATTERN_3;
> > > +	else
> > > +		pattern = DP_TRAINING_PATTERN_2;
> > > +	ret = dw_dp_link_train_set_pattern(dp, pattern);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	for (tries = 1; tries < 5; tries++) {
> > > +		ret = dw_dp_link_train_update_vs_emph(dp);
> > > +		if (ret)
> > > +			return ret;
> > > +
> > > +		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
> > > +
> > > +		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
> > > +		if (ret < 0)
> > > +			return ret;
> > > +
> > > +		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
> > > +			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
> > > +			link->train.clock_recovered = false;
> > > +			break;
> > > +		}
> > > +
> > > +		if (drm_dp_channel_eq_ok(status, link->lanes)) {
> > > +			link->train.channel_equalized = true;
> > > +			break;
> > > +		}
> > > +
> > > +		dw_dp_link_get_adjustments(link, status);
> > > +		dw_dp_link_train_adjust(&link->train);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> ......
> > > +
> > > +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> > > +			 const struct dw_dp_plat_data *plat_data);
> > > +#endif /* __DW_DP__ */
> > > -- 
> > > 2.34.1
> > > 
> > 
> 

-- 
With best wishes
Dmitry


From chunkuang.hu at kernel.org  Mon Mar  3 05:05:40 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 21:05:40 +0800
Subject: [PATCH] drm/mediatek: dp: drm_err => dev_err in HPD path to avoid
 NULL ptr
In-Reply-To: <20250116094249.1.I29b0b621abb613ddc70ab4996426a3909e1aa75f@changeid>
References: <20250116094249.1.I29b0b621abb613ddc70ab4996426a3909e1aa75f@changeid>
Message-ID: <CAAOTY__Ka-RD1=XmaAuEjrhkQMQQ7Mg+rgXaNe8ka-VGeRZ4JQ@mail.gmail.com>

Hi, Douglas:

Douglas Anderson <dianders at chromium.org> ? 2025?1?17? ?? ??1:43???
>
> The function mtk_dp_wait_hpd_asserted() may be called before the
> `mtk_dp->drm_dev` pointer is assigned in mtk_dp_bridge_attach().
> Specifically it can be called via this callpath:
>  - mtk_edp_wait_hpd_asserted
>  - [panel probe]
>  - dp_aux_ep_probe
>
> Using "drm" level prints anywhere in this callpath causes a NULL
> pointer dereference. Change the error message directly in
> mtk_dp_wait_hpd_asserted() to dev_err() to avoid this. Also change the
> error messages in mtk_dp_parse_capabilities(), which is called by
> mtk_dp_wait_hpd_asserted().
>
> While touching these prints, also add the error code to them to make
> future debugging easier.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Fixes: 7eacba9a083b ("drm/mediatek: dp: Add .wait_hpd_asserted() for AUX bus")
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
> Unfortunately, I have only been able to compile-time test this code. I
> hit the NULL pointer dereference on a device that's nowhere near
> upstream and it was running (sigh) a heavily modified copy of this
> code where the eDP stuff has been forked out of DP. Specifically, you
> can see <https://crrev.com/c/6073744>. It's pretty easy to understand
> that the same problem affects both codebases though, so I'm posting
> this "blind" in the hopes to at least fix upstream.
>
> I'll also note that the fact that mtk_edp_wait_hpd_asserted() calls
> mtk_dp_parse_capabilities() feels weird/wrong to me based on other eDP
> code I've worked on, but I've only barely looked at the Mediatek
> driver and perhaps others have already debated this. In any case,
> that's not directly related to this patch.
>
>  drivers/gpu/drm/mediatek/mtk_dp.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
> index 0687672f0e52..ccd104d8851f 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dp.c
> @@ -1763,7 +1763,7 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp)
>
>         ret = drm_dp_dpcd_readb(&mtk_dp->aux, DP_MSTM_CAP, &val);
>         if (ret < 1) {
> -               drm_err(mtk_dp->drm_dev, "Read mstm cap failed\n");
> +               dev_err(mtk_dp->dev, "Read mstm cap failed: %zd\n", ret);
>                 return ret == 0 ? -EIO : ret;
>         }
>
> @@ -1773,7 +1773,7 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp)
>                                         DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0,
>                                         &val);
>                 if (ret < 1) {
> -                       drm_err(mtk_dp->drm_dev, "Read irq vector failed\n");
> +                       dev_err(mtk_dp->dev, "Read irq vector failed: %zd\n", ret);
>                         return ret == 0 ? -EIO : ret;
>                 }
>
> @@ -2056,7 +2056,7 @@ static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wa
>
>         ret = mtk_dp_parse_capabilities(mtk_dp);
>         if (ret) {
> -               drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
> +               dev_err(mtk_dp->dev, "Can't parse capabilities: %d\n", ret);
>                 return ret;
>         }
>
> --
> 2.48.0.rc2.279.g1de40edade-goog
>


From devnull+chester.a.unal.arinc9.com at kernel.org  Mon Mar  3 05:06:50 2025
From: devnull+chester.a.unal.arinc9.com at kernel.org (Chester A. Unal via B4 Relay)
Date: Mon, 03 Mar 2025 13:06:50 +0000
Subject: [PATCH] ARM: dts: BCM5301X: Fix switch port labels of ASUS
 RT-AC5300
Message-ID: <20250303-for-broadcom-fix-rt-ac5300-switch-ports-v1-1-e058856ef4d3@arinc9.com>

From: "Chester A. Unal" <chester.a.unal at arinc9.com>

After using the device for a while, Tom reports that he initially described
the switch port labels incorrectly. Correct them.

Reported-by: Tom Brautaset <tbrautaset at gmail.com>
Fixes: 961dedc6b4e4 ("ARM: dts: BCM5301X: Add DT for ASUS RT-AC5300")
Signed-off-by: Chester A. Unal <chester.a.unal at arinc9.com>
---
 arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts b/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts
index 6c666dc7ad23ef7c31ac22904c39789838caea2e..01ec8c03686a66dd1efa439333f83737fe572191 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts
@@ -126,11 +126,11 @@ &srab {
 
 	ports {
 		port at 0 {
-			label = "lan4";
+			label = "wan";
 		};
 
 		port at 1 {
-			label = "lan3";
+			label = "lan1";
 		};
 
 		port at 2 {
@@ -138,11 +138,11 @@ port at 2 {
 		};
 
 		port at 3 {
-			label = "lan1";
+			label = "lan3";
 		};
 
 		port at 4 {
-			label = "wan";
+			label = "lan4";
 		};
 	};
 };

---
base-commit: 768953614c1c13fdf771be5742f1be573eea8fa4
change-id: 20250303-for-broadcom-fix-rt-ac5300-switch-ports-776b704ed279

Best regards,
-- 
Chester A. Unal <chester.a.unal at arinc9.com>




From peter.griffin at linaro.org  Mon Mar  3 05:11:21 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Mon, 03 Mar 2025 13:11:21 +0000
Subject: [PATCH] clk: samsung: gs101: fix synchronous external abort in
 samsung_clk_save()
Message-ID: <20250303-clk-suspend-fix-v1-1-c2edaf66260f@linaro.org>

EARLY_WAKEUP_SW_TRIG_*_SET and EARLY_WAKEUP_SW_TRIG_*_CLEAR
registers are only writeable. Attempting to read these registers
during samsung_clk_save() causes a synchronous external abort.

Remove these 8 registers from cmu_top_clk_regs[] array so that
system suspend gets further.

Note: the code path can be exercised using the following command:
echo mem > /sys/power/state

Fixes: 2c597bb7d66a ("clk: samsung: clk-gs101: Add cmu_top, cmu_misc and cmu_apm support")
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Cc: stable at vger.kernel.org
---
Note: to hit this clock driver issue you also need the CPU hotplug
series otherwise system fails earlier offlining CPUs
Link: https://lore.kernel.org/linux-arm-kernel/20241213-contrib-pg-cpu-hotplug-suspend2ram-fixes-v1-v1-0-c72978f63713 at linaro.org/T/
---
 drivers/clk/samsung/clk-gs101.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 86b39edba122..08b867ae3ed9 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -382,17 +382,9 @@ static const unsigned long cmu_top_clk_regs[] __initconst = {
 	EARLY_WAKEUP_DPU_DEST,
 	EARLY_WAKEUP_CSIS_DEST,
 	EARLY_WAKEUP_SW_TRIG_APM,
-	EARLY_WAKEUP_SW_TRIG_APM_SET,
-	EARLY_WAKEUP_SW_TRIG_APM_CLEAR,
 	EARLY_WAKEUP_SW_TRIG_CLUSTER0,
-	EARLY_WAKEUP_SW_TRIG_CLUSTER0_SET,
-	EARLY_WAKEUP_SW_TRIG_CLUSTER0_CLEAR,
 	EARLY_WAKEUP_SW_TRIG_DPU,
-	EARLY_WAKEUP_SW_TRIG_DPU_SET,
-	EARLY_WAKEUP_SW_TRIG_DPU_CLEAR,
 	EARLY_WAKEUP_SW_TRIG_CSIS,
-	EARLY_WAKEUP_SW_TRIG_CSIS_SET,
-	EARLY_WAKEUP_SW_TRIG_CSIS_CLEAR,
 	CLK_CON_MUX_MUX_CLKCMU_BO_BUS,
 	CLK_CON_MUX_MUX_CLKCMU_BUS0_BUS,
 	CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS,

---
base-commit: 480112512bd6e770fa1902d01173731d02377705
change-id: 20250303-clk-suspend-fix-81c5d63827e3

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From brgl at bgdev.pl  Mon Mar  3 05:18:39 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:39 +0100
Subject: [PATCH 14/15] gpio: aspeed-sgpio: use lock guards
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-14-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reduce the code complexity by using automatic lock guards with the raw
spinlock.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-aspeed-sgpio.c | 76 +++++++++++++++-------------------------
 1 file changed, 29 insertions(+), 47 deletions(-)

diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 34eb26298e32..5ce86de22563 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/gpio/driver.h>
 #include <linux/hashtable.h>
@@ -170,17 +171,14 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	const struct aspeed_sgpio_bank *bank = to_bank(offset);
-	unsigned long flags;
 	enum aspeed_sgpio_reg reg;
 	int rc = 0;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
 	rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
 
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return rc;
 }
 
@@ -214,13 +212,10 @@ static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
 static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	sgpio_set_value(gc, offset, val);
-
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@@ -231,15 +226,14 @@ static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 	int rc;
 
 	/* No special action is required for setting the direction; we'll
 	 * error-out in sgpio_set_value if this isn't an output GPIO */
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
+
 	rc = sgpio_set_value(gc, offset, val);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return rc;
 }
@@ -269,7 +263,6 @@ static void aspeed_sgpio_irq_ack(struct irq_data *d)
 {
 	const struct aspeed_sgpio_bank *bank;
 	struct aspeed_sgpio *gpio;
-	unsigned long flags;
 	void __iomem *status_addr;
 	int offset;
 	u32 bit;
@@ -278,18 +271,15 @@ static void aspeed_sgpio_irq_ack(struct irq_data *d)
 
 	status_addr = bank_reg(gpio, bank, reg_irq_status);
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	iowrite32(bit, status_addr);
-
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
 {
 	const struct aspeed_sgpio_bank *bank;
 	struct aspeed_sgpio *gpio;
-	unsigned long flags;
 	u32 reg, bit;
 	void __iomem *addr;
 	int offset;
@@ -301,17 +291,15 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
 	if (set)
 		gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d));
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	scoped_guard(raw_spinlock_irqsave, &gpio->lock) {
+		reg = ioread32(addr);
+		if (set)
+			reg |= bit;
+		else
+			reg &= ~bit;
 
-	reg = ioread32(addr);
-	if (set)
-		reg |= bit;
-	else
-		reg &= ~bit;
-
-	iowrite32(reg, addr);
-
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
+		iowrite32(reg, addr);
+	}
 
 	/* Masking the IRQ */
 	if (!set)
@@ -339,7 +327,6 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
 	const struct aspeed_sgpio_bank *bank;
 	irq_flow_handler_t handler;
 	struct aspeed_sgpio *gpio;
-	unsigned long flags;
 	void __iomem *addr;
 	int offset;
 
@@ -366,24 +353,22 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	scoped_guard(raw_spinlock_irqsave, &gpio->lock) {
+		addr = bank_reg(gpio, bank, reg_irq_type0);
+		reg = ioread32(addr);
+		reg = (reg & ~bit) | type0;
+		iowrite32(reg, addr);
 
-	addr = bank_reg(gpio, bank, reg_irq_type0);
-	reg = ioread32(addr);
-	reg = (reg & ~bit) | type0;
-	iowrite32(reg, addr);
+		addr = bank_reg(gpio, bank, reg_irq_type1);
+		reg = ioread32(addr);
+		reg = (reg & ~bit) | type1;
+		iowrite32(reg, addr);
 
-	addr = bank_reg(gpio, bank, reg_irq_type1);
-	reg = ioread32(addr);
-	reg = (reg & ~bit) | type1;
-	iowrite32(reg, addr);
-
-	addr = bank_reg(gpio, bank, reg_irq_type2);
-	reg = ioread32(addr);
-	reg = (reg & ~bit) | type2;
-	iowrite32(reg, addr);
-
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
+		addr = bank_reg(gpio, bank, reg_irq_type2);
+		reg = ioread32(addr);
+		reg = (reg & ~bit) | type2;
+		iowrite32(reg, addr);
+	}
 
 	irq_set_handler_locked(d, handler);
 
@@ -487,13 +472,12 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
 					unsigned int offset, bool enable)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
-	unsigned long flags;
 	void __iomem *reg;
 	u32 val;
 
 	reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	val = readl(reg);
 
@@ -504,8 +488,6 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
 
 	writel(val, reg);
 
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return 0;
 }
 

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:40 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:40 +0100
Subject: [PATCH 15/15] gpio: aspeed-sgpio: use new line value setter
 callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-15-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-aspeed-sgpio.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 5ce86de22563..00b31497ecff 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -209,13 +209,13 @@ static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
 	return 0;
 }
 
-static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
+static int aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 
 	guard(raw_spinlock_irqsave)(&gpio->lock);
 
-	sgpio_set_value(gc, offset, val);
+	return sgpio_set_value(gc, offset, val);
 }
 
 static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@@ -596,7 +596,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
 	gpio->chip.request = NULL;
 	gpio->chip.free = NULL;
 	gpio->chip.get = aspeed_sgpio_get;
-	gpio->chip.set = aspeed_sgpio_set;
+	gpio->chip.set_rv = aspeed_sgpio_set;
 	gpio->chip.set_config = aspeed_sgpio_set_config;
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;

-- 
2.45.2



From chunkuang.hu at kernel.org  Mon Mar  3 05:22:55 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 21:22:55 +0800
Subject: [PATCH v7 1/6] dt-bindings: display: mediatek: dpi: add
 power-domains example
In-Reply-To: <20231023-display-support-v7-1-6703f3e26831@baylibre.com>
References: <20231023-display-support-v7-0-6703f3e26831@baylibre.com> <20231023-display-support-v7-1-6703f3e26831@baylibre.com>
Message-ID: <CAAOTY_8c4xeE=c4MTGopenORaP-PL66exLG+erKSV1fpoGJU+g@mail.gmail.com>

Hi, Amergnat:

<amergnat at baylibre.com> ? 2025?1?10? ?? ??9:31???
>
> From: Fabien Parent <fparent at baylibre.com>
>
> DPI is part of the display / multimedia block in MediaTek SoCs, and
> always have a power-domain (at least in the upstream device-trees).
> Add the power-domains property to the binding example.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Fixes: 9273cf7d3942 ("dt-bindings: display: mediatek: convert the dpi bindings to yaml")
> Signed-off-by: Fabien Parent <fparent at baylibre.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> Acked-by: Rob Herring (Arm) <robh at kernel.org>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
> ---
>  Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> index 0f1e556dc8ef..d5ee52ea479b 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> @@ -116,11 +116,13 @@ examples:
>    - |
>      #include <dt-bindings/interrupt-controller/arm-gic.h>
>      #include <dt-bindings/clock/mt8173-clk.h>
> +    #include <dt-bindings/power/mt8173-power.h>
>
>      dpi: dpi at 1401d000 {
>          compatible = "mediatek,mt8173-dpi";
>          reg = <0x1401d000 0x1000>;
>          interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
> +        power-domains = <&spm MT8173_POWER_DOMAIN_MM>;
>          clocks = <&mmsys CLK_MM_DPI_PIXEL>,
>               <&mmsys CLK_MM_DPI_ENGINE>,
>               <&apmixedsys CLK_APMIXED_TVDPLL>;
>
> --
> 2.25.1
>


From frieder at fris.de  Mon Mar  3 05:22:54 2025
From: frieder at fris.de (Frieder Schrempf)
Date: Mon,  3 Mar 2025 14:22:54 +0100
Subject: [RESEND PATCH v3] regulator: pca9450: Handle hardware with fixed SD_VSEL for LDO5
Message-ID: <20250303132258.50204-1-frieder@fris.de>

From: Frieder Schrempf <frieder.schrempf at kontron.de>

There are two ways to set the output voltage of the LD05
regulator. First by writing to the voltage selection registers
and second by toggling the SD_VSEL signal.

Usually board designers connect SD_VSEL to the VSELECT signal
controlled by the USDHC controller, but in some cases the
signal is hardwired to a fixed low level (therefore selecting
3.3V as initial value for allowing to boot from the SD card).

In these cases, the voltage is only determined by the value
of the LDO5CTRL_L register. Introduce a property
nxp,sd-vsel-fixed-low to let the driver know that SD_VSEL
is low and there is no GPIO to actually get that
information from dynamically.

Signed-off-by: Frieder Schrempf <frieder.schrempf at kontron.de>
---
This was originally part of the series here: [1]. The other patches
were already applied, but this one is missing in regulator/for-next
and linux-next, which is why I'm resending.

[1] https://patchwork.kernel.org/project/linux-arm-kernel/cover/20241218152842.97483-1-frieder at fris.de/
---
---
 drivers/regulator/pca9450-regulator.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index 8f81d813640d..a56f3ab754fa 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -36,6 +36,7 @@ struct pca9450 {
 	enum pca9450_chip_type type;
 	unsigned int rcnt;
 	int irq;
+	bool sd_vsel_fixed_low;
 };
 
 static const struct regmap_range pca9450_status_range = {
@@ -102,6 +103,9 @@ static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev)
 {
 	struct pca9450 *pca9450 = rdev_get_drvdata(rdev);
 
+	if (pca9450->sd_vsel_fixed_low)
+		return PCA9450_REG_LDO5CTRL_L;
+
 	if (pca9450->sd_vsel_gpio && !gpiod_get_value(pca9450->sd_vsel_gpio))
 		return PCA9450_REG_LDO5CTRL_L;
 
@@ -1100,6 +1104,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
 		return ret;
 	}
 
+	pca9450->sd_vsel_fixed_low =
+		of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low");
+
 	dev_info(&i2c->dev, "%s probed.\n",
 		type == PCA9450_TYPE_PCA9450A ? "pca9450a" :
 		(type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc"));
-- 
2.48.1


From chunkuang.hu at kernel.org  Mon Mar  3 05:29:43 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 21:29:43 +0800
Subject: [PATCH RESEND] drm/mediatek: dsi: fix error codes in mtk_dsi_host_transfer()
In-Reply-To: <b754a408-4f39-4e37-b52d-7706c132e27f@stanley.mountain>
References: <b754a408-4f39-4e37-b52d-7706c132e27f@stanley.mountain>
Message-ID: <CAAOTY__KF=9Pp=3PAnXG5WCPX4Hxkfd391eBu0dfhO-wz9dWqw@mail.gmail.com>

Hi, Dan:

Dan Carpenter <dan.carpenter at linaro.org> ? 2025?1?8? ?? ??5:36???
>
> There is a type bug because the return statement:
>
>         return ret < 0 ? ret : recv_cnt;
>
> The issue is that ret is an int, recv_cnt is a u32 and the function
> returns ssize_t, which is a signed long.  The way that the type promotion
> works is that the negative error codes are first cast to u32 and then
> to signed long.  The error codes end up being positive instead of
> negative and the callers treat them as success.

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

>
> Fixes: 81cc7e51c4f1 ("drm/mediatek: Allow commands to be sent during video mode")
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/r/202412210801.iADw0oIH-lkp at intel.com/
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> Reviewed-by: Mattijs Korpershoek <mkorpershoek at baylibre.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
> I sent this patch earlier:
> https://lore.kernel.org/all/Y%2FyBC4yxTs+Po0TG at kili/
> but it wasn't applied.  I've changed the commit message a bit and added
> new tags.
>
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index d871b1dba083..0acfda47f002 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -1015,12 +1015,12 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>                                      const struct mipi_dsi_msg *msg)
>  {
>         struct mtk_dsi *dsi = host_to_dsi(host);
> -       u32 recv_cnt, i;
> +       ssize_t recv_cnt;
>         u8 read_data[16];
>         void *src_addr;
>         u8 irq_flag = CMD_DONE_INT_FLAG;
>         u32 dsi_mode;
> -       int ret;
> +       int ret, i;
>
>         dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
>         if (dsi_mode & MODE) {
> @@ -1069,7 +1069,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>         if (recv_cnt)
>                 memcpy(msg->rx_buf, src_addr, recv_cnt);
>
> -       DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n",
> +       DRM_INFO("dsi get %zd byte data from the panel address(0x%x)\n",
>                  recv_cnt, *((u8 *)(msg->tx_buf)));
>
>  restore_dsi_mode:
> --
> 2.45.2
>


From menglong8.dong at gmail.com  Mon Mar  3 05:28:33 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 21:28:33 +0800
Subject: [PATCH v4 0/4] per-function storage support
Message-ID: <20250303132837.498938-1-dongml2@chinatelecom.cn>

For now, there isn't a way to set and get per-function metadata with
a low overhead, which is not convenient for some situations. Take
BPF trampoline for example, we need to create a trampoline for each
kernel function, as we have to store some information of the function
to the trampoline, such as BPF progs, function arg count, etc. The
performance overhead and memory consumption can be higher to create
these trampolines. With the supporting of per-function metadata storage,
we can store these information to the metadata, and create a global BPF
trampoline for all the kernel functions. In the global trampoline, we
get the information that we need from the function metadata through the
ip (function address) with almost no overhead.

Another beneficiary can be ftrace. For now, all the kernel functions that
are enabled by dynamic ftrace will be added to a filter hash if there are
more than one callbacks. And hash lookup will happen when the traced
functions are called, which has an impact on the performance, see
__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
metadata supporting, we can store the information that if the callback is
enabled on the kernel function to the metadata.

In the 1st patch, we factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET to
make fineibt works when the kernel function is 32-bytes aligned.

In the 2nd patch, we implement the per-function metadata storage by
storing the index of the metadata to the function padding space.

In the 3rd and 4th patch, we implement the per-function metadata storage
for x86 and arm64. And in the feature, we can support more arch.

Changes since V3:
- rebase to the newest tip/x86/core, the fineibt has some updating

Changes since V2:
- split the patch into a series.
- considering the effect to cfi and fineibt and introduce the 1st patch.

Changes since V1:
- add supporting for arm64
- split out arch relevant code
- refactor the commit log

Menglong Dong (4):
  x86/ibt: factor out cfi and fineibt offset
  add per-function metadata storage support
  x86: implement per-function metadata storage for x86
  arm64: implement per-function metadata storage for arm64

 arch/arm64/Kconfig              |  15 ++
 arch/arm64/Makefile             |  23 ++-
 arch/arm64/include/asm/ftrace.h |  34 +++++
 arch/arm64/kernel/ftrace.c      |  13 +-
 arch/x86/Kconfig                |  18 +++
 arch/x86/include/asm/cfi.h      |  13 +-
 arch/x86/include/asm/ftrace.h   |  54 ++++++++
 arch/x86/kernel/alternative.c   |  18 ++-
 arch/x86/net/bpf_jit_comp.c     |  22 +--
 include/linux/kfunc_md.h        |  25 ++++
 kernel/Makefile                 |   1 +
 kernel/trace/Makefile           |   1 +
 kernel/trace/kfunc_md.c         | 239 ++++++++++++++++++++++++++++++++
 13 files changed, 450 insertions(+), 26 deletions(-)
 create mode 100644 include/linux/kfunc_md.h
 create mode 100644 kernel/trace/kfunc_md.c

-- 
2.39.5



From menglong8.dong at gmail.com  Mon Mar  3 05:28:34 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 21:28:34 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250303132837.498938-1-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
Message-ID: <20250303132837.498938-2-dongml2@chinatelecom.cn>

For now, the layout of cfi and fineibt is hard coded, and the padding is
fixed on 16 bytes.

Factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET. CFI_INSN_OFFSET is
the offset of cfi, which is the same as FUNCTION_ALIGNMENT when
CALL_PADDING is enabled. And FINEIBT_INSN_OFFSET is the offset where we
put the fineibt preamble on, which is 16 for now.

When the FUNCTION_ALIGNMENT is bigger than 16, we place the fineibt
preamble on the last 16 bytes of the padding for better performance, which
means the fineibt preamble don't use the space that cfi uses.

The FINEIBT_INSN_OFFSET is not used in fineibt_caller_start and
fineibt_paranoid_start, as it is always "0x10". Note that we need to
update the offset in fineibt_caller_start and fineibt_paranoid_start if
FINEIBT_INSN_OFFSET changes.

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
v4:
- rebase to the newest tip/x86/core, the fineibt has some updating
---
 arch/x86/include/asm/cfi.h    | 13 +++++++++----
 arch/x86/kernel/alternative.c | 18 +++++++++++-------
 arch/x86/net/bpf_jit_comp.c   | 22 +++++++++++-----------
 3 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h
index 2f6a01f098b5..04525f2f6bf2 100644
--- a/arch/x86/include/asm/cfi.h
+++ b/arch/x86/include/asm/cfi.h
@@ -108,6 +108,14 @@ extern bhi_thunk __bhi_args_end[];
 
 struct pt_regs;
 
+#ifdef CONFIG_CALL_PADDING
+#define FINEIBT_INSN_OFFSET	16
+#define CFI_INSN_OFFSET		CONFIG_FUNCTION_ALIGNMENT
+#else
+#define FINEIBT_INSN_OFFSET	0
+#define CFI_INSN_OFFSET		5
+#endif
+
 #ifdef CONFIG_CFI_CLANG
 enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
 #define __bpfcall
@@ -118,11 +126,8 @@ static inline int cfi_get_offset(void)
 {
 	switch (cfi_mode) {
 	case CFI_FINEIBT:
-		return 16;
 	case CFI_KCFI:
-		if (IS_ENABLED(CONFIG_CALL_PADDING))
-			return 16;
-		return 5;
+		return CFI_INSN_OFFSET;
 	default:
 		return 0;
 	}
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 32e4b801db99..0088d2313f33 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -917,7 +917,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
 
 		poison_endbr(addr);
 		if (IS_ENABLED(CONFIG_FINEIBT))
-			poison_cfi(addr - 16);
+			poison_cfi(addr);
 	}
 }
 
@@ -980,12 +980,13 @@ u32 cfi_get_func_hash(void *func)
 {
 	u32 hash;
 
-	func -= cfi_get_offset();
 	switch (cfi_mode) {
 	case CFI_FINEIBT:
+		func -= FINEIBT_INSN_OFFSET;
 		func += 7;
 		break;
 	case CFI_KCFI:
+		func -= CFI_INSN_OFFSET;
 		func += 1;
 		break;
 	default:
@@ -1372,7 +1373,7 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
 		 * have determined there are no indirect calls to it and we
 		 * don't need no CFI either.
 		 */
-		if (!is_endbr(addr + 16))
+		if (!is_endbr(addr + CFI_INSN_OFFSET))
 			continue;
 
 		hash = decode_preamble_hash(addr, &arity);
@@ -1380,6 +1381,7 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
 			 addr, addr, 5, addr))
 			return -EINVAL;
 
+		addr += (CFI_INSN_OFFSET - FINEIBT_INSN_OFFSET);
 		text_poke_early(addr, fineibt_preamble_start, fineibt_preamble_size);
 		WARN_ON(*(u32 *)(addr + fineibt_preamble_hash) != 0x12345678);
 		text_poke_early(addr + fineibt_preamble_hash, &hash, 4);
@@ -1402,10 +1404,10 @@ static void cfi_rewrite_endbr(s32 *start, s32 *end)
 	for (s = start; s < end; s++) {
 		void *addr = (void *)s + *s;
 
-		if (!exact_endbr(addr + 16))
+		if (!exact_endbr(addr + CFI_INSN_OFFSET))
 			continue;
 
-		poison_endbr(addr + 16);
+		poison_endbr(addr + CFI_INSN_OFFSET);
 	}
 }
 
@@ -1543,12 +1545,12 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
 		return;
 
 	case CFI_FINEIBT:
-		/* place the FineIBT preamble at func()-16 */
+		/* place the FineIBT preamble at func()-FINEIBT_INSN_OFFSET */
 		ret = cfi_rewrite_preamble(start_cfi, end_cfi);
 		if (ret)
 			goto err;
 
-		/* rewrite the callers to target func()-16 */
+		/* rewrite the callers to target func()-FINEIBT_INSN_OFFSET */
 		ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
 		if (ret)
 			goto err;
@@ -1588,6 +1590,7 @@ static void poison_cfi(void *addr)
 	 */
 	switch (cfi_mode) {
 	case CFI_FINEIBT:
+		addr -= FINEIBT_INSN_OFFSET;
 		/*
 		 * FineIBT prefix should start with an ENDBR.
 		 */
@@ -1607,6 +1610,7 @@ static void poison_cfi(void *addr)
 		break;
 
 	case CFI_KCFI:
+		addr -= CFI_INSN_OFFSET;
 		/*
 		 * kCFI prefix should start with a valid hash.
 		 */
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 72776dcb75aa..ee86a5df5ffb 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -415,6 +415,12 @@ static int emit_call(u8 **prog, void *func, void *ip);
 static void emit_fineibt(u8 **pprog, u8 *ip, u32 hash, int arity)
 {
 	u8 *prog = *pprog;
+#ifdef CONFIG_CALL_PADDING
+	int i;
+
+	for (i = 0; i < CFI_INSN_OFFSET - 16; i++)
+		EMIT1(0x90);
+#endif
 
 	EMIT_ENDBR();
 	EMIT3_off32(0x41, 0x81, 0xea, hash);		/* subl $hash, %r10d	*/
@@ -432,20 +438,14 @@ static void emit_fineibt(u8 **pprog, u8 *ip, u32 hash, int arity)
 static void emit_kcfi(u8 **pprog, u32 hash)
 {
 	u8 *prog = *pprog;
+#ifdef CONFIG_CALL_PADDING
+	int i;
+#endif
 
 	EMIT1_off32(0xb8, hash);			/* movl $hash, %eax	*/
 #ifdef CONFIG_CALL_PADDING
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
-	EMIT1(0x90);
+	for (i = 0; i < CFI_INSN_OFFSET - 5; i++)
+		EMIT1(0x90);
 #endif
 	EMIT_ENDBR();
 
-- 
2.39.5



From menglong8.dong at gmail.com  Mon Mar  3 05:28:35 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 21:28:35 +0800
Subject: [PATCH v4 2/4] add per-function metadata storage support
In-Reply-To: <20250303132837.498938-1-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
Message-ID: <20250303132837.498938-3-dongml2@chinatelecom.cn>

For now, there isn't a way to set and get per-function metadata with
a low overhead, which is not convenient for some situations. Take
BPF trampoline for example, we need to create a trampoline for each
kernel function, as we have to store some information of the function
to the trampoline, such as BPF progs, function arg count, etc. The
performance overhead and memory consumption can be higher to create
these trampolines. With the supporting of per-function metadata storage,
we can store these information to the metadata, and create a global BPF
trampoline for all the kernel functions. In the global trampoline, we
get the information that we need from the function metadata through the
ip (function address) with almost no overhead.

Another beneficiary can be ftrace. For now, all the kernel functions that
are enabled by dynamic ftrace will be added to a filter hash if there are
more than one callbacks. And hash lookup will happen when the traced
functions are called, which has an impact on the performance, see
__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
metadata supporting, we can store the information that if the callback is
enabled on the kernel function to the metadata.

Support per-function metadata storage in the function padding, and
previous discussion can be found in [1]. Generally speaking, we have two
way to implement this feature:

1. Create a function metadata array, and prepend a insn which can hold
the index of the function metadata in the array. And store the insn to
the function padding.

2. Allocate the function metadata with kmalloc(), and prepend a insn which
hold the pointer of the metadata. And store the insn to the function
padding.

Compared with way 2, way 1 consume less space, but we need to do more work
on the global function metadata array. And we implement this function in
the way 1.

Link: https://lore.kernel.org/bpf/CADxym3anLzM6cAkn_z71GDd_VeKiqqk1ts=xuiP7pr4PO6USPA at mail.gmail.com/ [1]
Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
v2:
- add supporting for arm64
- split out arch relevant code
- refactor the commit log
---
 include/linux/kfunc_md.h |  25 ++++
 kernel/Makefile          |   1 +
 kernel/trace/Makefile    |   1 +
 kernel/trace/kfunc_md.c  | 239 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 266 insertions(+)
 create mode 100644 include/linux/kfunc_md.h
 create mode 100644 kernel/trace/kfunc_md.c

diff --git a/include/linux/kfunc_md.h b/include/linux/kfunc_md.h
new file mode 100644
index 000000000000..df616f0fcb36
--- /dev/null
+++ b/include/linux/kfunc_md.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KFUNC_MD_H
+#define _LINUX_KFUNC_MD_H
+
+#include <linux/kernel.h>
+
+struct kfunc_md {
+	int users;
+	/* we can use this field later, make sure it is 8-bytes aligned
+	 * for now.
+	 */
+	int pad0;
+	void *func;
+};
+
+extern struct kfunc_md *kfunc_mds;
+
+struct kfunc_md *kfunc_md_find(void *ip);
+struct kfunc_md *kfunc_md_get(void *ip);
+void kfunc_md_put(struct kfunc_md *meta);
+void kfunc_md_put_by_ip(void *ip);
+void kfunc_md_lock(void);
+void kfunc_md_unlock(void);
+
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index 87866b037fbe..7435674d5da3 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_TRACE_CLOCK) += trace/
 obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_TRACEPOINTS) += trace/
 obj-$(CONFIG_RETHOOK) += trace/
+obj-$(CONFIG_FUNCTION_METADATA) += trace/
 obj-$(CONFIG_IRQ_WORK) += irq_work.o
 obj-$(CONFIG_CPU_PM) += cpu_pm.o
 obj-$(CONFIG_BPF) += bpf/
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 057cd975d014..9780ee3f8d8d 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_FTRACE_RECORD_RECURSION) += trace_recursion_record.o
 obj-$(CONFIG_FPROBE) += fprobe.o
 obj-$(CONFIG_RETHOOK) += rethook.o
 obj-$(CONFIG_FPROBE_EVENTS) += trace_fprobe.o
+obj-$(CONFIG_FUNCTION_METADATA) += kfunc_md.o
 
 obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o
 obj-$(CONFIG_RV) += rv/
diff --git a/kernel/trace/kfunc_md.c b/kernel/trace/kfunc_md.c
new file mode 100644
index 000000000000..7ec25bcf778d
--- /dev/null
+++ b/kernel/trace/kfunc_md.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/slab.h>
+#include <linux/memory.h>
+#include <linux/rcupdate.h>
+#include <linux/ftrace.h>
+#include <linux/kfunc_md.h>
+
+#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct kfunc_md))
+
+static u32 kfunc_md_count = ENTRIES_PER_PAGE, kfunc_md_used;
+struct kfunc_md __rcu *kfunc_mds;
+EXPORT_SYMBOL_GPL(kfunc_mds);
+
+static DEFINE_MUTEX(kfunc_md_mutex);
+
+
+void kfunc_md_unlock(void)
+{
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_unlock);
+
+void kfunc_md_lock(void)
+{
+	mutex_lock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_lock);
+
+static u32 kfunc_md_get_index(void *ip)
+{
+	return *(u32 *)(ip - KFUNC_MD_DATA_OFFSET);
+}
+
+static void kfunc_md_init(struct kfunc_md *mds, u32 start, u32 end)
+{
+	u32 i;
+
+	for (i = start; i < end; i++)
+		mds[i].users = 0;
+}
+
+static int kfunc_md_page_order(void)
+{
+	return fls(DIV_ROUND_UP(kfunc_md_count, ENTRIES_PER_PAGE)) - 1;
+}
+
+/* Get next usable function metadata. On success, return the usable
+ * kfunc_md and store the index of it to *index. If no usable kfunc_md is
+ * found in kfunc_mds, a larger array will be allocated.
+ */
+static struct kfunc_md *kfunc_md_get_next(u32 *index)
+{
+	struct kfunc_md *new_mds, *mds;
+	u32 i, order;
+
+	mds = rcu_dereference(kfunc_mds);
+	if (mds == NULL) {
+		order = kfunc_md_page_order();
+		new_mds = (void *)__get_free_pages(GFP_KERNEL, order);
+		if (!new_mds)
+			return NULL;
+		kfunc_md_init(new_mds, 0, kfunc_md_count);
+		/* The first time to initialize kfunc_mds, so it is not
+		 * used anywhere yet, and we can update it directly.
+		 */
+		rcu_assign_pointer(kfunc_mds, new_mds);
+		mds = new_mds;
+	}
+
+	if (likely(kfunc_md_used < kfunc_md_count)) {
+		/* maybe we can manage the used function metadata entry
+		 * with a bit map ?
+		 */
+		for (i = 0; i < kfunc_md_count; i++) {
+			if (!mds[i].users) {
+				kfunc_md_used++;
+				*index = i;
+				mds[i].users++;
+				return mds + i;
+			}
+		}
+	}
+
+	order = kfunc_md_page_order();
+	/* no available function metadata, so allocate a bigger function
+	 * metadata array.
+	 */
+	new_mds = (void *)__get_free_pages(GFP_KERNEL, order + 1);
+	if (!new_mds)
+		return NULL;
+
+	memcpy(new_mds, mds, kfunc_md_count * sizeof(*new_mds));
+	kfunc_md_init(new_mds, kfunc_md_count, kfunc_md_count * 2);
+
+	rcu_assign_pointer(kfunc_mds, new_mds);
+	synchronize_rcu();
+	free_pages((u64)mds, order);
+
+	mds = new_mds + kfunc_md_count;
+	*index = kfunc_md_count;
+	kfunc_md_count <<= 1;
+	kfunc_md_used++;
+	mds->users++;
+
+	return mds;
+}
+
+static int kfunc_md_text_poke(void *ip, void *insn, void *nop)
+{
+	void *target;
+	int ret = 0;
+	u8 *prog;
+
+	target = ip - KFUNC_MD_INSN_OFFSET;
+	mutex_lock(&text_mutex);
+	if (insn) {
+		if (!memcmp(target, insn, KFUNC_MD_INSN_SIZE))
+			goto out;
+
+		if (memcmp(target, nop, KFUNC_MD_INSN_SIZE)) {
+			ret = -EBUSY;
+			goto out;
+		}
+		prog = insn;
+	} else {
+		if (!memcmp(target, nop, KFUNC_MD_INSN_SIZE))
+			goto out;
+		prog = nop;
+	}
+
+	ret = kfunc_md_arch_poke(target, prog);
+out:
+	mutex_unlock(&text_mutex);
+	return ret;
+}
+
+static bool __kfunc_md_put(struct kfunc_md *md)
+{
+	u8 nop_insn[KFUNC_MD_INSN_SIZE];
+
+	if (WARN_ON_ONCE(md->users <= 0))
+		return false;
+
+	md->users--;
+	if (md->users > 0)
+		return false;
+
+	if (!kfunc_md_arch_exist(md->func))
+		return false;
+
+	kfunc_md_arch_nops(nop_insn);
+	/* release the metadata by recovering the function padding to NOPS */
+	kfunc_md_text_poke(md->func, NULL, nop_insn);
+	/* TODO: we need a way to shrink the array "kfunc_mds" */
+	kfunc_md_used--;
+
+	return true;
+}
+
+/* Decrease the reference of the md, release it if "md->users <= 0" */
+void kfunc_md_put(struct kfunc_md *md)
+{
+	mutex_lock(&kfunc_md_mutex);
+	__kfunc_md_put(md);
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_put);
+
+/* Get a exist metadata by the function address, and NULL will be returned
+ * if not exist.
+ *
+ * NOTE: rcu lock should be held during reading the metadata, and
+ * kfunc_md_lock should be held if writing happens.
+ */
+struct kfunc_md *kfunc_md_find(void *ip)
+{
+	struct kfunc_md *md;
+	u32 index;
+
+	if (kfunc_md_arch_exist(ip)) {
+		index = kfunc_md_get_index(ip);
+		if (WARN_ON_ONCE(index >= kfunc_md_count))
+			return NULL;
+
+		md = rcu_dereference(kfunc_mds) + index;
+		return md;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(kfunc_md_find);
+
+void kfunc_md_put_by_ip(void *ip)
+{
+	struct kfunc_md *md;
+
+	mutex_lock(&kfunc_md_mutex);
+	md = kfunc_md_find(ip);
+	if (md)
+		__kfunc_md_put(md);
+	mutex_unlock(&kfunc_md_mutex);
+}
+EXPORT_SYMBOL_GPL(kfunc_md_put_by_ip);
+
+/* Get a exist metadata by the function address, and create one if not
+ * exist. Reference of the metadata will increase 1.
+ *
+ * NOTE: always call this function with kfunc_md_lock held, and all
+ * updating to metadata should also hold the kfunc_md_lock.
+ */
+struct kfunc_md *kfunc_md_get(void *ip)
+{
+	u8 nop_insn[KFUNC_MD_INSN_SIZE], insn[KFUNC_MD_INSN_SIZE];
+	struct kfunc_md *md;
+	u32 index;
+
+	md = kfunc_md_find(ip);
+	if (md) {
+		md->users++;
+		return md;
+	}
+
+	md = kfunc_md_get_next(&index);
+	if (!md)
+		return NULL;
+
+	kfunc_md_arch_pretend(insn, index);
+	kfunc_md_arch_nops(nop_insn);
+
+	if (kfunc_md_text_poke(ip, insn, nop_insn)) {
+		kfunc_md_used--;
+		md->users = 0;
+		return NULL;
+	}
+	md->func = ip;
+
+	return md;
+}
+EXPORT_SYMBOL_GPL(kfunc_md_get);
-- 
2.39.5



From menglong8.dong at gmail.com  Mon Mar  3 05:28:36 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 21:28:36 +0800
Subject: [PATCH v4 3/4] x86: implement per-function metadata storage for x86
In-Reply-To: <20250303132837.498938-1-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
Message-ID: <20250303132837.498938-4-dongml2@chinatelecom.cn>

With CONFIG_CALL_PADDING enabled, there will be 16-bytes padding space
before all the kernel functions. And some kernel features can use it,
such as MITIGATION_CALL_DEPTH_TRACKING, CFI_CLANG, FINEIBT, etc.

In my research, MITIGATION_CALL_DEPTH_TRACKING will consume the tail
9-bytes in the function padding, CFI_CLANG will consume the head 5-bytes,
and FINEIBT will consume all the 16 bytes if it is enabled. So there will
be no space for us if MITIGATION_CALL_DEPTH_TRACKING and CFI_CLANG are
both enabled, or FINEIBT is enabled.

In x86, we need 5-bytes to prepend a "mov %eax xxx" insn, which can hold
a 4-bytes index. So we have following logic:

1. use the head 5-bytes if CFI_CLANG is not enabled
2. use the tail 5-bytes if MITIGATION_CALL_DEPTH_TRACKING and FINEIBT are
   not enabled
3. compile the kernel with FUNCTION_ALIGNMENT_32B otherwise

In the third case, we make the kernel function 32 bytes aligned, and there
will be 32 bytes padding before the functions. According to my testing,
the text size didn't increase on this case, which is weird.

With 16-bytes padding:

-rwxr-xr-x 1 401190688  x86-dev/vmlinux*
-rw-r--r-- 1    251068  x86-dev/vmlinux.a
-rw-r--r-- 1 851892992  x86-dev/vmlinux.o
-rw-r--r-- 1  12395008  x86-dev/arch/x86/boot/bzImage

With 32-bytes padding:

-rwxr-xr-x 1 401318128 x86-dev/vmlinux*
-rw-r--r-- 1    251154 x86-dev/vmlinux.a
-rw-r--r-- 1 853636704 x86-dev/vmlinux.o
-rw-r--r-- 1  12509696 x86-dev/arch/x86/boot/bzImage

The way I tested should be right, and this is a good news for us. On the
third case, the layout of the padding space will be like this if fineibt
is enabled:

__cfi_func:
	mov	--	5	-- cfi, not used anymore
	nop
	nop
	nop
	mov	--	5	-- function metadata
	nop
	nop
	nop
	fineibt	--	16	-- fineibt
func:
	nopw	--	4
	......

I tested the fineibt with "cfi=fineibt" cmdline, and it works well
together with FUNCTION_METADATA enabled. And I also tested the
performance of this function by setting metadata for all the kernel
function, and it consumes 0.7s for 70k+ functions, not bad :/

I can't find a machine that support IBT, so I didn't test the IBT. I'd
appreciate it if someone can do this testing for me :/

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
v3:
- select FUNCTION_ALIGNMENT_32B on case3, instead of extra 5-bytes
---
 arch/x86/Kconfig              | 18 ++++++++++++
 arch/x86/include/asm/ftrace.h | 54 +++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5c277261507e..b0614188c80b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2518,6 +2518,24 @@ config PREFIX_SYMBOLS
 	def_bool y
 	depends on CALL_PADDING && !CFI_CLANG
 
+config FUNCTION_METADATA
+	bool "Per-function metadata storage support"
+	default y
+	depends on CC_HAS_ENTRY_PADDING && OBJTOOL
+	select CALL_PADDING
+	select FUNCTION_ALIGNMENT_32B if ((CFI_CLANG && CALL_THUNKS) || FINEIBT)
+	help
+	  Support per-function metadata storage for kernel functions, and
+	  get the metadata of the function by its address with almost no
+	  overhead.
+
+	  The index of the metadata will be stored in the function padding
+	  and consumes 5-bytes. FUNCTION_ALIGNMENT_32B will be selected if
+	  "(CFI_CLANG && CALL_THUNKS) || FINEIBT" to make sure there is
+	  enough available padding space for this function. However, it
+	  seems that the text size almost don't change, compare with
+	  FUNCTION_ALIGNMENT_16B.
+
 menuconfig CPU_MITIGATIONS
 	bool "Mitigations for CPU vulnerabilities"
 	default y
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index f2265246249a..700bb729e949 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -4,6 +4,28 @@
 
 #include <asm/ptrace.h>
 
+#ifdef CONFIG_FUNCTION_METADATA
+#if (defined(CONFIG_CFI_CLANG) && defined(CONFIG_CALL_THUNKS)) || (defined(CONFIG_FINEIBT))
+  /* the CONFIG_FUNCTION_PADDING_BYTES is 32 in this case, use the
+   * range: [align + 8, align + 13].
+   */
+  #define KFUNC_MD_INSN_OFFSET		(CONFIG_FUNCTION_PADDING_BYTES - 8)
+  #define KFUNC_MD_DATA_OFFSET		(CONFIG_FUNCTION_PADDING_BYTES - 9)
+#else
+  #ifdef CONFIG_CFI_CLANG
+    /* use the space that CALL_THUNKS suppose to use */
+    #define KFUNC_MD_INSN_OFFSET	(5)
+    #define KFUNC_MD_DATA_OFFSET	(4)
+  #else
+    /* use the space that CFI_CLANG suppose to use */
+    #define KFUNC_MD_INSN_OFFSET	(CONFIG_FUNCTION_PADDING_BYTES)
+    #define KFUNC_MD_DATA_OFFSET	(CONFIG_FUNCTION_PADDING_BYTES - 1)
+  #endif
+#endif
+
+#define KFUNC_MD_INSN_SIZE		(5)
+#endif
+
 #ifdef CONFIG_FUNCTION_TRACER
 #ifndef CC_USING_FENTRY
 # error Compiler does not support fentry?
@@ -156,4 +178,36 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
 #endif /* !COMPILE_OFFSETS */
 #endif /* !__ASSEMBLY__ */
 
+#if !defined(__ASSEMBLY__) && defined(CONFIG_FUNCTION_METADATA)
+#include <asm/text-patching.h>
+
+static inline bool kfunc_md_arch_exist(void *ip)
+{
+	return *(u8 *)(ip - KFUNC_MD_INSN_OFFSET) == 0xB8;
+}
+
+static inline void kfunc_md_arch_pretend(u8 *insn, u32 index)
+{
+	*insn = 0xB8;
+	*(u32 *)(insn + 1) = index;
+}
+
+static inline void kfunc_md_arch_nops(u8 *insn)
+{
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+	*(insn++) = BYTES_NOP1;
+}
+
+static inline int kfunc_md_arch_poke(void *ip, u8 *insn)
+{
+	text_poke(ip, insn, KFUNC_MD_INSN_SIZE);
+	text_poke_sync();
+	return 0;
+}
+
+#endif
+
 #endif /* _ASM_X86_FTRACE_H */
-- 
2.39.5



From menglong8.dong at gmail.com  Mon Mar  3 05:28:37 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Mon,  3 Mar 2025 21:28:37 +0800
Subject: [PATCH v4 4/4] arm64: implement per-function metadata storage for arm64
In-Reply-To: <20250303132837.498938-1-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
Message-ID: <20250303132837.498938-5-dongml2@chinatelecom.cn>

The per-function metadata storage is already used by ftrace if
CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS is enabled, and it store the pointer
of the callback directly to the function padding, which consume 8-bytes,
in the commit
baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS").
So we can directly store the index to the function padding too, without
a prepending. With CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS enabled, the
function is 8-bytes aligned, and we will compile the kernel with extra
8-bytes (2 NOPS) padding space. Otherwise, the function is 4-bytes
aligned, and only extra 4-bytes (1 NOPS) is needed.

However, we have the same problem with Mark in the commit above: we can't
use the function padding together with CFI_CLANG, which can make the clang
compiles a wrong offset to the pre-function type hash. He said that he was
working with others on this problem 2 years ago. Hi Mark, is there any
progress on this problem?

Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
---
 arch/arm64/Kconfig              | 15 +++++++++++++++
 arch/arm64/Makefile             | 23 ++++++++++++++++++++--
 arch/arm64/include/asm/ftrace.h | 34 +++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c      | 13 +++++++++++--
 4 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..7ed80f5eb267 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1536,6 +1536,21 @@ config NODES_SHIFT
 	  Specify the maximum number of NUMA Nodes available on the target
 	  system.  Increases memory reserved to accommodate various tables.
 
+config FUNCTION_METADATA
+	bool "Per-function metadata storage support"
+	default y
+	select HAVE_DYNAMIC_FTRACE_NO_PATCHABLE if !FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
+	depends on !CFI_CLANG
+	help
+	  Support per-function metadata storage for kernel functions, and
+	  get the metadata of the function by its address with almost no
+	  overhead.
+
+	  The index of the metadata will be stored in the function padding,
+	  which will consume 4-bytes. If FUNCTION_ALIGNMENT_8B is enabled,
+	  extra 8-bytes function padding will be reserved during compiling.
+	  Otherwise, only extra 4-bytes function padding is needed.
+
 source "kernel/Kconfig.hz"
 
 config ARCH_SPARSEMEM_ENABLE
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2b25d671365f..2df2b0f4dd90 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -144,12 +144,31 @@ endif
 
 CHECKFLAGS	+= -D__aarch64__
 
+ifeq ($(CONFIG_FUNCTION_METADATA),y)
+  ifeq ($(CONFIG_FUNCTION_ALIGNMENT_8B),y)
+  __padding_nops := 2
+  else
+  __padding_nops := 1
+  endif
+else
+  __padding_nops := 0
+endif
+
 ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS),y)
+  __padding_nops  := $(shell echo $(__padding_nops) + 2 | bc)
   KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
-  CC_FLAGS_FTRACE := -fpatchable-function-entry=4,2
+  CC_FLAGS_FTRACE := -fpatchable-function-entry=$(shell echo $(__padding_nops) + 2 | bc),$(__padding_nops)
 else ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y)
+  CC_FLAGS_FTRACE := -fpatchable-function-entry=$(shell echo $(__padding_nops) + 2 | bc),$(__padding_nops)
   KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
-  CC_FLAGS_FTRACE := -fpatchable-function-entry=2
+else ifeq ($(CONFIG_FUNCTION_METADATA),y)
+  CC_FLAGS_FTRACE += -fpatchable-function-entry=$(__padding_nops),$(__padding_nops)
+  ifneq ($(CONFIG_FUNCTION_TRACER),y)
+    KBUILD_CFLAGS += $(CC_FLAGS_FTRACE)
+    # some file need to remove this cflag when CONFIG_FUNCTION_TRACER
+    # is not enabled, so we need to export it here
+    export CC_FLAGS_FTRACE
+  endif
 endif
 
 ifeq ($(CONFIG_KASAN_SW_TAGS), y)
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index bfe3ce9df197..aa3eaa91bf82 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -24,6 +24,16 @@
 #define FTRACE_PLT_IDX		0
 #define NR_FTRACE_PLTS		1
 
+#ifdef CONFIG_FUNCTION_METADATA
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+#define KFUNC_MD_DATA_OFFSET	(AARCH64_INSN_SIZE * 3)
+#else
+#define KFUNC_MD_DATA_OFFSET	AARCH64_INSN_SIZE
+#endif
+#define KFUNC_MD_INSN_SIZE	AARCH64_INSN_SIZE
+#define KFUNC_MD_INSN_OFFSET	KFUNC_MD_DATA_OFFSET
+#endif
+
 /*
  * Currently, gcc tends to save the link register after the local variables
  * on the stack. This causes the max stack tracer to report the function
@@ -216,6 +226,30 @@ static inline bool arch_syscall_match_sym_name(const char *sym,
 	 */
 	return !strcmp(sym + 8, name);
 }
+
+#ifdef CONFIG_FUNCTION_METADATA
+#include <asm/text-patching.h>
+
+static inline bool kfunc_md_arch_exist(void *ip)
+{
+	return !aarch64_insn_is_nop(*(u32 *)(ip - KFUNC_MD_INSN_OFFSET));
+}
+
+static inline void kfunc_md_arch_pretend(u8 *insn, u32 index)
+{
+	*(u32 *)insn = index;
+}
+
+static inline void kfunc_md_arch_nops(u8 *insn)
+{
+	*(u32 *)insn = aarch64_insn_gen_nop();
+}
+
+static inline int kfunc_md_arch_poke(void *ip, u8 *insn)
+{
+	return aarch64_insn_patch_text_nosync(ip, *(u32 *)insn);
+}
+#endif
 #endif /* ifndef __ASSEMBLY__ */
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index d7c0d023dfe5..4191ff0037f5 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -88,8 +88,10 @@ unsigned long ftrace_call_adjust(unsigned long addr)
 	 * to `BL <caller>`, which is at `addr + 4` bytes in either case.
 	 *
 	 */
-	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
-		return addr + AARCH64_INSN_SIZE;
+	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS)) {
+		addr += AARCH64_INSN_SIZE;
+		goto out;
+	}
 
 	/*
 	 * When using patchable-function-entry with pre-function NOPs, addr is
@@ -139,6 +141,13 @@ unsigned long ftrace_call_adjust(unsigned long addr)
 
 	/* Skip the first NOP after function entry */
 	addr += AARCH64_INSN_SIZE;
+out:
+	if (IS_ENABLED(CONFIG_FUNCTION_METADATA)) {
+		if (IS_ENABLED(CONFIG_FUNCTION_ALIGNMENT_8B))
+			addr += 2 * AARCH64_INSN_SIZE;
+		else
+			addr += AARCH64_INSN_SIZE;
+	}
 
 	return addr;
 }
-- 
2.39.5



From rf at opensource.cirrus.com  Mon Mar  3 05:33:09 2025
From: rf at opensource.cirrus.com (Richard Fitzgerald)
Date: Mon, 3 Mar 2025 13:33:09 +0000
Subject: [PATCH 11/15] gpio: arizona: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-11-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
 <20250303-gpiochip-set-conversion-v1-11-1d5cceeebf8b@linaro.org>
Message-ID: <84b7c543-7e81-4a20-9f58-7ddf6b2001e5@opensource.cirrus.com>

On 03/03/2025 1:18 pm, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> struct gpio_chip now has callbacks for setting line values that return
> an integer, allowing to indicate failures. Convert the driver to using
> them.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> ---
>   drivers/gpio/gpio-arizona.c | 9 +++++----
>   1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
> index c15fda99120a..e530c94dcce8 100644
> --- a/drivers/gpio/gpio-arizona.c
> +++ b/drivers/gpio/gpio-arizona.c
> @@ -121,7 +121,8 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip,
>   				  ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value);
>   }
>   
> -static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> +static int arizona_gpio_set(struct gpio_chip *chip, unsigned int offset,
> +			    int value)
>   {
>   	struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
>   	struct arizona *arizona = arizona_gpio->arizona;
> @@ -129,8 +130,8 @@ static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
>   	if (value)
>   		value = ARIZONA_GPN_LVL;
>   
> -	regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
> -			   ARIZONA_GPN_LVL, value);
> +	return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
> +				  ARIZONA_GPN_LVL, value);
>   }
>   
>   static const struct gpio_chip template_chip = {
> @@ -139,7 +140,7 @@ static const struct gpio_chip template_chip = {
>   	.direction_input	= arizona_gpio_direction_in,
>   	.get			= arizona_gpio_get,
>   	.direction_output	= arizona_gpio_direction_out,
> -	.set			= arizona_gpio_set,
> +	.set_rv			= arizona_gpio_set,
>   	.can_sleep		= true,
>   };
>   
> 
Reviewed-by: Richard Fitzgerald <rf at opensource.cirrus.com>


From aliceryhl at google.com  Mon Mar  3 05:33:39 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Mon, 3 Mar 2025 14:33:39 +0100
Subject: [PATCH v3 5/5] rust: Add warn_on and warn_on_once
In-Reply-To: <20250213135759.190006-6-fujita.tomonori@gmail.com>
References: <20250213135759.190006-1-fujita.tomonori@gmail.com> <20250213135759.190006-6-fujita.tomonori@gmail.com>
Message-ID: <CAH5fLgjX9hh+QRrKggOKr+6p+UwqHSavzu4UXy9iGNL2wSJXtg@mail.gmail.com>

On Thu, Feb 13, 2025 at 3:01?PM FUJITA Tomonori
<fujita.tomonori at gmail.com> wrote:
>
> Add warn_on and warn_on_once macros. Wrapping the C's WARN_* and BUG_*
> macros doesn't work so this uses the assembly code exported by the C
> side via ARCH_WARN_ASM macro. Like the static branch code, this
> generates the assembly code for rust at compile time by using the C
> preprocessor.
>
> file()! macro doesn't work for the Rust inline assembly in the same
> way as __FILE__ for the C inline assembly. So the code to handle a
> file name is different from the C assembly code (similar to the
> arm64/loongarch assembly).
>
> Similarly, ARCH_WARN_REACHABLE is also used at compile time to
> generate the assembly code; objtool's reachable anotation code. Only
> architectures that use objtool (x86 and loongarch) need it.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori at gmail.com>
> ---
>  rust/Makefile                                 |   8 ++
>  rust/kernel/.gitignore                        |   2 +
>  rust/kernel/bug.rs                            | 100 ++++++++++++++++++
>  rust/kernel/generated_arch_reachable_asm.rs.S |   7 ++
>  rust/kernel/generated_arch_warn_asm.rs.S      |   7 ++
>  rust/kernel/lib.rs                            |   1 +
>  6 files changed, 125 insertions(+)
>  create mode 100644 rust/kernel/bug.rs
>  create mode 100644 rust/kernel/generated_arch_reachable_asm.rs.S
>  create mode 100644 rust/kernel/generated_arch_warn_asm.rs.S
>
> diff --git a/rust/Makefile b/rust/Makefile
> index 8fcfd60447bc..a295b65c43f3 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -34,6 +34,9 @@ obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o
>  obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
>
>  always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
> +ifndef CONFIG_UML
> +always-$(subst y,$(CONFIG_RUST),$(CONFIG_BUG)) += kernel/generated_arch_warn_asm.rs kernel/generated_arch_reachable_asm.rs
> +endif
>
>  # Avoids running `$(RUSTC)` when it may not be available.
>  ifdef CONFIG_RUST
> @@ -481,5 +484,10 @@ $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
>  ifdef CONFIG_JUMP_LABEL
>  $(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs
>  endif
> +ifndef CONFIG_UML
> +ifdef CONFIG_BUG
> +$(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generated_arch_reachable_asm.rs
> +endif
> +endif
>
>  endif # CONFIG_RUST
> diff --git a/rust/kernel/.gitignore b/rust/kernel/.gitignore
> index 6ba39a178f30..f1d7f4225332 100644
> --- a/rust/kernel/.gitignore
> +++ b/rust/kernel/.gitignore
> @@ -1,3 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
>
>  /generated_arch_static_branch_asm.rs
> +/generated_arch_warn_asm.rs
> +/generated_arch_reachable_asm.rs
> \ No newline at end of file
> diff --git a/rust/kernel/bug.rs b/rust/kernel/bug.rs
> new file mode 100644
> index 000000000000..7ffd9cb1ad75
> --- /dev/null
> +++ b/rust/kernel/bug.rs
> @@ -0,0 +1,100 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2024 FUJITA Tomonori
> +
> +//! Support for BUG_* and WARN_* functionality.
> +//!
> +//! C header: [`include/asm-generic/bug.h`](srctree/include/asm-generic/bug.h)
> +
> +#[macro_export]
> +#[doc(hidden)]
> +#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
> +macro_rules! warn_flags {
> +    ($flags:expr) => {
> +        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
> +        // SAFETY: Just an FFI call.
> +        #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
> +        unsafe {
> +            $crate::asm!(concat!(
> +                "/* {size} */",
> +                ".pushsection .rodata.str1.1, \"aMS\", at progbits, 1\n",
> +                "111:\t .string ", "\"", file!(), "\"\n",
> +                ".popsection\n",

It looks like you're doing this so that you can reference the filename
with "111b", but could you do this instead:

const _FILE: &[u8] = file!().as_bytes();
// Plus one for nul-terminator.
static FILE: [u8; 1 + _FILE.len()] = {
    let mut bytes = [0; 1 + _FILE.len()];
    let mut i = 0;
    while i < _FILE.len() {
        bytes[i] = _FILE[i];
        i += 1;
    }
    bytes
};

and then use

asm!(
    concat!(
        "/* {size} */",
        include!(concat!(env!("OBJTREE"),
"/rust/kernel/generated_arch_warn_asm.rs")),
        include!(concat!(env!("OBJTREE"),
"/rust/kernel/generated_arch_reachable_asm.rs")));
    file = sym FILE,
    line = const line!(),
    ...
);

with
::kernel::concat_literals!(ARCH_WARN_ASM("{file}", "{line}",
"{flags}", "{size}")),

That would be a lot simpler to understand than what you are doing.


Alice


From yangyicong at huawei.com  Mon Mar  3 05:35:35 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 21:35:35 +0800
Subject: [PATCH v11 1/4] cpu/SMT: Provide a default
 topology_is_primary_thread()
In-Reply-To: <e3607ed0-bdf5-4fef-8731-b81fae649312@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-2-yangyicong@huawei.com>
 <e3607ed0-bdf5-4fef-8731-b81fae649312@arm.com>
Message-ID: <af8d364e-a5e0-decb-4463-fd6b7c54a0d9@huawei.com>

On 2025/2/28 19:10, Dietmar Eggemann wrote:
> On 18/02/2025 15:10, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> [...]
> 
>> diff --git a/include/linux/topology.h b/include/linux/topology.h
>> index 52f5850730b3..b3aba443c4eb 100644
>> --- a/include/linux/topology.h
>> +++ b/include/linux/topology.h
>> @@ -240,6 +240,28 @@ static inline const struct cpumask *cpu_smt_mask(int cpu)
>>  }
>>  #endif
>>  
>> +#ifndef topology_is_primary_thread
>> +
>> +#define topology_is_primary_thread topology_is_primary_thread
>> +
>> +static inline bool topology_is_primary_thread(unsigned int cpu)
>> +{
>> +	/*
>> +	 * On SMT hotplug the primary thread of the SMT won't be disabled.
>> +	 * Architectures do have a special primary thread (e.g. x86) need
>> +	 * to override this function. Otherwise just make the first thread
>> +	 * in the SMT as the primary thread.
>> +	 *
>> +	 * The sibling cpumask of an offline CPU contains always the CPU
>> +	 * itself for architectures using CONFIG_GENERIC_ARCH_TOPOLOGY.
>> +	 * Other architectures should use this depend on their own
>> +	 * situation.
> 
> This sentence is hard to get. Do you want to say that other
> architectures (CONFIG_GENERIC_ARCH_TOPOLOGY or
> !CONFIG_GENERIC_ARCH_TOPOLOGY) have to check whether they can use this
> default implementation or have to override it?
> 

yes exactly, will improve the comments. thanks.



From m-malladi at ti.com  Mon Mar  3 05:36:07 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Mon, 3 Mar 2025 19:06:07 +0530
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth: Add
 XDP support
In-Reply-To: <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
 <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
 <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>
Message-ID: <40ce8ed3-b36c-4d5f-b75a-7e0409beb713@ti.com>



On 3/3/2025 6:01 PM, Dan Carpenter wrote:
> On Mon, Mar 03, 2025 at 05:?36:?41PM +0530, Malladi, Meghana wrote: > > 
>  > +static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff 
> *xdp, > > > + struct page *page) > > > +{ > > > + struct net_device
> ZjQcmQRYFpfptBannerStart
> This message was sent from outside of Texas Instruments.
> Do not click links or open attachments unless you recognize the source 
> of this email and know the content is safe.
> Report?Suspicious
> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK! 
> uldqV3eFFkc7oMXFHHkDX4AFLVsE3ldskf6bPMMFmxDOsNtMfZjUscGelUkBFpAeybNre38L_c2LiiUb7AZxLvAeqSk9ifgbPE1AYFU$>
> ZjQcmQRYFpfptBannerEnd
> 
> On Mon, Mar 03, 2025 at 05:36:41PM +0530, Malladi, Meghana wrote:
>> > > +static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
>> > > +			struct page *page)
>> > > +{
>> > > +	struct net_device *ndev = emac->ndev;
>> > > +	int err, result = ICSSG_XDP_PASS;
>> > > +	struct bpf_prog *xdp_prog;
>> > > +	struct xdp_frame *xdpf;
>> > > +	int q_idx;
>> > > +	u32 act;
>> > > +
>> > > +	xdp_prog = READ_ONCE(emac->xdp_prog);
>> > > +	act = bpf_prog_run_xdp(xdp_prog, xdp);
>> > > +	switch (act) {
>> > > +	case XDP_PASS:
>> > > +		break;
>> > > +	case XDP_TX:
>> > > +		/* Send packet to TX ring for immediate transmission */
>> > > +		xdpf = xdp_convert_buff_to_frame(xdp);
>> > > +		if (unlikely(!xdpf))
>> > 
>> > This is the second unlikely() macro which is added in this patchset.
>> > The rule with likely/unlikely() is that it should only be added if it
>> > likely makes a difference in benchmarking.  Quite often the compiler
>> > is able to predict that valid pointers are more likely than NULL
>> > pointers so often these types of annotations don't make any difference
>> > at all to the compiled code.  But it depends on the compiler and the -O2
>> > options.
>> > 
>> 
>> Do correct me if I am wrong, but from my understanding, XDP feature depends
>> alot of performance and benchmarking and having unlikely does make a
>> difference. Atleast in all the other drivers I see this being used for XDP.
>> 
> 
> Which compiler are you on when you say that "having unlikely does make a
> difference"?

I'm on gcc version 10.3.1.

> 
> I'm on gcc version 14.2.0 (Debian 14.2.0-16) and it doesn't make a
> difference to the compiled code.  This matches what one would expect from
> a compiler.  Valid pointers are fast path and NULL pointers are slow path.
> 

Can you tell me how did you verify this? I actually don't know what 
level of optimization to expect from a compiler. I said so, because I 
have checked with other drivers which implemented XDP and everywhere 
unlikely is used. But now I understand its not the driver but the 
compiler that plays the major role in defining the optimization.

> Adding an unlikely() is a micro optimization.  There are so many other
> things you can do to speed up the code.  I wouldn't start with that.
>

Ok, if you believe that unlikely is doing more harm than good, I am ok 
with dropping them off.

> regards,
> dan
> 



From yangyicong at huawei.com  Mon Mar  3 05:38:51 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 21:38:51 +0800
Subject: [PATCH v11 1/4] cpu/SMT: Provide a default
 topology_is_primary_thread()
In-Reply-To: <Z8G__C7n4zwje2MW@bogus>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-2-yangyicong@huawei.com> <Z8G__C7n4zwje2MW@bogus>
Message-ID: <d93e890c-739e-bd1d-8b28-b83d96ec55c0@huawei.com>

On 2025/2/28 21:54, Sudeep Holla wrote:
> On Tue, Feb 18, 2025 at 10:10:15PM +0800, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> Currently if architectures want to support HOTPLUG_SMT they need to
>> provide a topology_is_primary_thread() telling the framework which
>> thread in the SMT cannot offline. However arm64 doesn't have a
>> restriction on which thread in the SMT cannot offline, a simplest
>> choice is that just make 1st thread as the "primary" thread. So
>> just make this as the default implementation in the framework and
>> let architectures like x86 that have special primary thread to
>> override this function (which they've already done).
>>
>> There's no need to provide a stub function if !CONFIG_SMP or
>> !CONFIG_HOTPLUG_SMT. In such case the testing CPU is already
>> the 1st CPU in the SMT so it's always the primary thread.
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>> Pre questioned in v9 [1] whether this works on architectures not using
>> CONFIG_GENERIC_ARCH_TOPOLOGY, See [2] for demonstration hacking on LoongArch
>> VM and this also works. Architectures should use this on their own situation.
>> [1] https://lore.kernel.org/linux-arm-kernel/427bd639-33c3-47e4-9e83-68c428eb1a7d at arm.com/
>> [2] https://lore.kernel.org/linux-arm-kernel/a5690fee-3019-f26c-8bad-1d95e388e877 at huawei.com/
>>
>>  arch/powerpc/include/asm/topology.h |  1 +
>>  arch/x86/include/asm/topology.h     |  2 +-
>>  include/linux/topology.h            | 22 ++++++++++++++++++++++
>>  3 files changed, 24 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
>> index 16bacfe8c7a2..da15b5efe807 100644
>> --- a/arch/powerpc/include/asm/topology.h
>> +++ b/arch/powerpc/include/asm/topology.h
>> @@ -152,6 +152,7 @@ static inline bool topology_is_primary_thread(unsigned int cpu)
>>  {
>>  	return cpu == cpu_first_thread_sibling(cpu);
>>  }
>> +#define topology_is_primary_thread topology_is_primary_thread
>>  
>>  static inline bool topology_smt_thread_allowed(unsigned int cpu)
>>  {
>> diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
>> index ec134b719144..6c79ee7c0957 100644
>> --- a/arch/x86/include/asm/topology.h
>> +++ b/arch/x86/include/asm/topology.h
>> @@ -229,11 +229,11 @@ static inline bool topology_is_primary_thread(unsigned int cpu)
>>  {
>>  	return cpumask_test_cpu(cpu, cpu_primary_thread_mask);
>>  }
>> +#define topology_is_primary_thread topology_is_primary_thread
>>  
>>  #else /* CONFIG_SMP */
>>  static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
>>  static inline int topology_max_smt_threads(void) { return 1; }
>> -static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
>>  static inline unsigned int topology_amd_nodes_per_pkg(void) { return 1; }
>>  #endif /* !CONFIG_SMP */
>>  
>> diff --git a/include/linux/topology.h b/include/linux/topology.h
>> index 52f5850730b3..b3aba443c4eb 100644
>> --- a/include/linux/topology.h
>> +++ b/include/linux/topology.h
>> @@ -240,6 +240,28 @@ static inline const struct cpumask *cpu_smt_mask(int cpu)
>>  }
>>  #endif
>>  
>> +#ifndef topology_is_primary_thread
>> +
>> +#define topology_is_primary_thread topology_is_primary_thread
>> +
>> +static inline bool topology_is_primary_thread(unsigned int cpu)
>> +{
>> +	/*
>> +	 * On SMT hotplug the primary thread of the SMT won't be disabled.
> 
> I may be misunderstanding the term "SMT hotplug" above. For me it is
> comparable with logical CPU hotplug, so the above statement may be
> misleading. IIUC, what you mean above is if SMT is disabled, the
> primary thread will always remain enabled/active. Does that make sense
> or am I missing something ?
> 

I just the borrow the term from kconfig HOTPLUG_SMT here, but here the statement
only involves the disable part, so maybe it'll be more accurate to use "SMT
disable" rather than "SMT hotplug" here?

Thanks.



From horms at kernel.org  Mon Mar  3 05:42:09 2025
From: horms at kernel.org (Simon Horman)
Date: Mon, 3 Mar 2025 13:42:09 +0000
Subject: [PATCH net-next] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250227093712.2130561-1-danishanwar@ti.com>
References: <20250227093712.2130561-1-danishanwar@ti.com>
Message-ID: <20250303134209.GU1615191@kernel.org>

On Thu, Feb 27, 2025 at 03:07:12PM +0530, MD Danish Anwar wrote:
> The ICSSG firmware maintains set of stats called PA_STATS.
> Currently the driver only dumps 4 stats. Add support for dumping more
> stats.
> 
> The offset for different stats are defined as MACROs in icssg_switch_map.h
> file. All the offsets are for Slice0. Slice1 offsets are slice0 + 4.
> The offset calculation is taken care while reading the stats in
> emac_update_hardware_stats().
> 
> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>

Reviewed-by: Simon Horman <horms at kernel.org>



From Michael.Hennerich at analog.com  Mon Mar  3 05:46:51 2025
From: Michael.Hennerich at analog.com (Hennerich, Michael)
Date: Mon, 3 Mar 2025 13:46:51 +0000
Subject: [PATCH 06/15] gpio: adp5585: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-6-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
 <20250303-gpiochip-set-conversion-v1-6-1d5cceeebf8b@linaro.org>
Message-ID: <PH0PR03MB6512A48F698CE67687A274EA8EC92@PH0PR03MB6512.namprd03.prod.outlook.com>



> -----Original Message-----
> From: Bartosz Golaszewski <brgl at bgdev.pl>
> Sent: Monday, March 3, 2025 2:19 PM
> To: Linus Walleij <linus.walleij at linaro.org>; Bartosz Golaszewski
> <brgl at bgdev.pl>; Hennerich, Michael <Michael.Hennerich at analog.com>;
> Laurent Pinchart <laurent.pinchart at ideasonboard.com>; Mun Yew Tham
> <mun.yew.tham at intel.com>; Joel Stanley <joel at jms.id.au>; Andrew Jeffery
> <andrew at codeconstruct.com.au>
> Cc: linux-gpio at vger.kernel.org; linux-kernel at vger.kernel.org; linux-
> pwm at vger.kernel.org; patches at opensource.cirrus.com; linux-arm-
> kernel at lists.infradead.org; linux-aspeed at lists.ozlabs.org; Bartosz Golaszewski
> <bartosz.golaszewski at linaro.org>
> Subject: [PATCH 06/15] gpio: adp5585: use new line value setter callbacks
> 
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> struct gpio_chip now has callbacks for setting line values that return an
> integer, allowing to indicate failures. Convert the driver to using them.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Acked-by: Michael Hennerich <michael.hennerich at analog.com>

> ---
>  drivers/gpio/gpio-adp5585.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index
> 000d31f09671..d5c0f1b267c8 100644
> --- a/drivers/gpio/gpio-adp5585.c
> +++ b/drivers/gpio/gpio-adp5585.c
> @@ -86,14 +86,16 @@ static int adp5585_gpio_get_value(struct gpio_chip
> *chip, unsigned int off)
>  	return !!(val & bit);
>  }
> 
> -static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off,
> int val)
> +static int adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off,
> +				  int val)
>  {
>  	struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
>  	unsigned int bank = ADP5585_BANK(off);
>  	unsigned int bit = ADP5585_BIT(off);
> 
> -	regmap_update_bits(adp5585_gpio->regmap,
> ADP5585_GPO_DATA_OUT_A + bank,
> -			   bit, val ? bit : 0);
> +	return regmap_update_bits(adp5585_gpio->regmap,
> +				  ADP5585_GPO_DATA_OUT_A + bank,
> +				  bit, val ? bit : 0);
>  }
> 
>  static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,
> @@ -192,7 +194,7 @@ static int adp5585_gpio_probe(struct platform_device
> *pdev)
>  	gc->direction_input = adp5585_gpio_direction_input;
>  	gc->direction_output = adp5585_gpio_direction_output;
>  	gc->get = adp5585_gpio_get_value;
> -	gc->set = adp5585_gpio_set_value;
> +	gc->set_rv = adp5585_gpio_set_value;
>  	gc->set_config = adp5585_gpio_set_config;
>  	gc->can_sleep = true;
> 
> 
> --
> 2.45.2


From Michael.Hennerich at analog.com  Mon Mar  3 05:47:08 2025
From: Michael.Hennerich at analog.com (Hennerich, Michael)
Date: Mon, 3 Mar 2025 13:47:08 +0000
Subject: [PATCH 05/15] gpio: adp5520: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-5-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
 <20250303-gpiochip-set-conversion-v1-5-1d5cceeebf8b@linaro.org>
Message-ID: <PH0PR03MB651210C6D5480D215619C1648EC92@PH0PR03MB6512.namprd03.prod.outlook.com>



> -----Original Message-----
> From: Bartosz Golaszewski <brgl at bgdev.pl>
> Sent: Monday, March 3, 2025 2:19 PM
> To: Linus Walleij <linus.walleij at linaro.org>; Bartosz Golaszewski
> <brgl at bgdev.pl>; Hennerich, Michael <Michael.Hennerich at analog.com>;
> Laurent Pinchart <laurent.pinchart at ideasonboard.com>; Mun Yew Tham
> <mun.yew.tham at intel.com>; Joel Stanley <joel at jms.id.au>; Andrew Jeffery
> <andrew at codeconstruct.com.au>
> Cc: linux-gpio at vger.kernel.org; linux-kernel at vger.kernel.org; linux-
> pwm at vger.kernel.org; patches at opensource.cirrus.com; linux-arm-
> kernel at lists.infradead.org; linux-aspeed at lists.ozlabs.org; Bartosz Golaszewski
> <bartosz.golaszewski at linaro.org>
> Subject: [PATCH 05/15] gpio: adp5520: use new line value setter callbacks
> 
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> struct gpio_chip now has callbacks for setting line values that return an
> integer, allowing to indicate failures. Convert the driver to using them.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Acked-by: Michael Hennerich <michael.hennerich at analog.com>

> ---
>  drivers/gpio/gpio-adp5520.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index
> c55e821c63b6..57d12c10cbda 100644
> --- a/drivers/gpio/gpio-adp5520.c
> +++ b/drivers/gpio/gpio-adp5520.c
> @@ -40,16 +40,18 @@ static int adp5520_gpio_get_value(struct gpio_chip
> *chip, unsigned off)
>  	return !!(reg_val & dev->lut[off]);
>  }
> 
> -static void adp5520_gpio_set_value(struct gpio_chip *chip,
> -		unsigned off, int val)
> +static int adp5520_gpio_set_value(struct gpio_chip *chip,
> +				  unsigned int off, int val)
>  {
>  	struct adp5520_gpio *dev;
>  	dev = gpiochip_get_data(chip);
> 
>  	if (val)
> -		adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev-
> >lut[off]);
> +		return adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
> +					dev->lut[off]);
>  	else
> -		adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev-
> >lut[off]);
> +		return adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
> +					dev->lut[off]);
>  }
> 
>  static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
> @@ -120,7 +122,7 @@ static int adp5520_gpio_probe(struct platform_device
> *pdev)
>  	gc->direction_input  = adp5520_gpio_direction_input;
>  	gc->direction_output = adp5520_gpio_direction_output;
>  	gc->get = adp5520_gpio_get_value;
> -	gc->set = adp5520_gpio_set_value;
> +	gc->set_rv = adp5520_gpio_set_value;
>  	gc->can_sleep = true;
> 
>  	gc->base = pdata->gpio_start;
> 
> --
> 2.45.2


From m-malladi at ti.com  Mon Mar  3 05:51:23 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 3 Mar 2025 19:21:23 +0530
Subject: [PATCH net-next v3 1/2] net: ti: icss-iep: Add pwidth configuration for perout signal
In-Reply-To: <20250303135124.632845-1-m-malladi@ti.com>
References: <20250303135124.632845-1-m-malladi@ti.com>
Message-ID: <20250303135124.632845-2-m-malladi@ti.com>

icss_iep_perout_enable_hw() is a common function for generating
both pps and perout signals. When enabling pps, the application needs
to only pass enable/disable argument, whereas for perout it supports
different flags to configure the signal.

But icss_iep_perout_enable_hw() function is missing to hook the
configuration params passed by the app, causing perout to behave
same a pps (except being able to configure the period). As duty cycle
is also one feature which can configured for perout, incorporate this
in the function to get the expected signal.

Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
---
Changes from v2 (v3-v2):
- Posted patch to net-next as feature addition
- Collected RB tag from Jacob Keller <jacob.e.keller at intel.com>

 drivers/net/ethernet/ti/icssg/icss_iep.c | 49 ++++++++++++++++++++++--
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index d59c1744840a..0411438a3b5d 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -406,9 +406,16 @@ static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns)
 static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				     struct ptp_perout_request *req, int on)
 {
+	struct timespec64 ts;
+	u64 ns_width;
 	int ret;
 	u64 cmp;
 
+	/* Calculate width of the signal for PPS/PEROUT handling */
+	ts.tv_sec = req->on.sec;
+	ts.tv_nsec = req->on.nsec;
+	ns_width = timespec64_to_ns(&ts);
+
 	if (iep->ops && iep->ops->perout_enable) {
 		ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
 		if (ret)
@@ -419,8 +426,9 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
 			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
 				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
-			/* Configure SYNC, 1ms pulse width */
-			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000);
+			/* Configure SYNC, based on req on width */
+			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+				     div_u64(ns_width, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
 			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
@@ -447,6 +455,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				   + req->period.nsec;
 			icss_iep_update_to_next_boundary(iep, start_ns);
 
+			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+				     div_u64(ns_width, iep->def_inc));
 			/* Enable Sync in single shot mode  */
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
 				     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
@@ -474,7 +484,38 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 static int icss_iep_perout_enable(struct icss_iep *iep,
 				  struct ptp_perout_request *req, int on)
 {
-	return -EOPNOTSUPP;
+	int ret = 0;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	/* Reject requests with unsupported flags */
+	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) {
+		ret = -EOPNOTSUPP;
+		goto exit;
+	}
+
+	if (iep->pps_enabled) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	if (iep->perout_enabled == !!on)
+		goto exit;
+
+	/* Set default "on" time (1ms) for the signal if not passed by the app */
+	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
+		req->on.sec = 0;
+		req->on.nsec = NSEC_PER_MSEC;
+	}
+
+	ret = icss_iep_perout_enable_hw(iep, req, on);
+	if (!ret)
+		iep->perout_enabled = !!on;
+
+exit:
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return ret;
 }
 
 static void icss_iep_cap_cmp_work(struct work_struct *work)
@@ -553,6 +594,8 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
 		rq.perout.period.nsec = 0;
 		rq.perout.start.sec = ts.tv_sec + 2;
 		rq.perout.start.nsec = 0;
+		rq.perout.on.sec = 0;
+		rq.perout.on.nsec = NSEC_PER_MSEC;
 		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
 	} else {
 		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
-- 
2.43.0



From m-malladi at ti.com  Mon Mar  3 05:51:22 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 3 Mar 2025 19:21:22 +0530
Subject: [PATCH net-next v3 0/2] Add perout configuration support in IEP driver
Message-ID: <20250303135124.632845-1-m-malladi@ti.com>

IEP driver supported both perout and pps signal generation
but perout feature is faulty with half-cooked support
due to some missing configuration. Hence perout feature is
removed as a bug fix. This patch series adds back this feature
which configures perout signal based on the arguments passed
by the perout request.

This patch series is continuation to the bug fix: 
https://lore.kernel.org/all/20250227092441.1848419-1-m-malladi at ti.com/
as suggested by Jakub Kicinski and Jacob Keller:
https://lore.kernel.org/all/20250220172410.025b96d6 at kernel.org/

v2:https://lore.kernel.org/all/20250219062701.995955-1-m-malladi at ti.com/

Meghana Malladi (2):
  net: ti: icss-iep: Add pwidth configuration for perout signal
  net: ti: icss-iep: Add phase offset configuration for perout signal

 drivers/net/ethernet/ti/icssg/icss_iep.c | 65 ++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 4 deletions(-)


base-commit: f77f12010f67259bd0e1ad18877ed27c721b627a
-- 
2.43.0



From m-malladi at ti.com  Mon Mar  3 05:51:24 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 3 Mar 2025 19:21:24 +0530
Subject: [PATCH net-next v3 2/2] net: ti: icss-iep: Add phase offset configuration for perout signal
In-Reply-To: <20250303135124.632845-1-m-malladi@ti.com>
References: <20250303135124.632845-1-m-malladi@ti.com>
Message-ID: <20250303135124.632845-3-m-malladi@ti.com>

icss_iep_perout_enable_hw() is a common function for generating
both pps and perout signals. When enabling pps, the application needs
to only pass enable/disable argument, whereas for perout it supports
different flags to configure the signal.

In case the app passes a valid phase offset value, the signal should
start toggling after that phase offset, else start immediately or
as soon as possible. ICSS_IEP_SYNC_START_REG register take number of
clock cycles to wait before starting the signal after activation time.
Set appropriate value to this register to support phase offset.

Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
---
Changes from v2 (v3-v2):
- Posted patch to net-next as feature addition
- Collected RB tag from Jacob Keller <jacob.e.keller at intel.com>

 drivers/net/ethernet/ti/icssg/icss_iep.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index 0411438a3b5d..598dfb963db6 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -407,6 +407,7 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				     struct ptp_perout_request *req, int on)
 {
 	struct timespec64 ts;
+	u64 ns_start;
 	u64 ns_width;
 	int ret;
 	u64 cmp;
@@ -416,6 +417,14 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 	ts.tv_nsec = req->on.nsec;
 	ns_width = timespec64_to_ns(&ts);
 
+	if (req->flags & PTP_PEROUT_PHASE) {
+		ts.tv_sec = req->phase.sec;
+		ts.tv_nsec = req->phase.nsec;
+		ns_start = timespec64_to_ns(&ts);
+	} else {
+		ns_start = 0;
+	}
+
 	if (iep->ops && iep->ops->perout_enable) {
 		ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
 		if (ret)
@@ -430,7 +439,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
 				     div_u64(ns_width, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
-			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
+			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
+				     div_u64(ns_start, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
 			/* Enable CMP 1 */
 			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
@@ -457,6 +467,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 
 			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
 				     div_u64(ns_width, iep->def_inc));
+			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
+				     div_u64(ns_start, iep->def_inc));
 			/* Enable Sync in single shot mode  */
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
 				     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
@@ -489,7 +501,8 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
 	mutex_lock(&iep->ptp_clk_mutex);
 
 	/* Reject requests with unsupported flags */
-	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) {
+	if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
+			  PTP_PEROUT_PHASE)) {
 		ret = -EOPNOTSUPP;
 		goto exit;
 	}
@@ -590,6 +603,7 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
 	if (on) {
 		ns = icss_iep_gettime(iep, NULL);
 		ts = ns_to_timespec64(ns);
+		rq.perout.flags = 0;
 		rq.perout.period.sec = 1;
 		rq.perout.period.nsec = 0;
 		rq.perout.start.sec = ts.tv_sec + 2;
-- 
2.43.0



From florent.tomasin at arm.com  Mon Mar  3 05:55:49 2025
From: florent.tomasin at arm.com (Florent Tomasin)
Date: Mon, 3 Mar 2025 13:55:49 +0000
Subject: [PATCH 8/9] drm/panthor: Add i.MX95 support
In-Reply-To: <980075f9-5ad2-430e-b139-7e9477bf415c@denx.de>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-9-marex@denx.de> <4658624.cEBGB3zze1@steina-w>
 <887a6d8d-9eab-44ed-9fd0-9197598231f4@arm.com>
 <980075f9-5ad2-430e-b139-7e9477bf415c@denx.de>
Message-ID: <94f65cda-02bb-4165-ae6e-be19b7cee55f@arm.com>

Hi Marek,

On 28/02/2025 17:26, Marek Vasut wrote:
> On 2/28/25 12:23 PM, Florent Tomasin wrote:
> 
> Hi,
> 
>>>> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/
>>>> drm/panthor/panthor_drv.c
>>>> index 06fe46e320738..2504a456d45c4 100644
>>>> --- a/drivers/gpu/drm/panthor/panthor_drv.c
>>>> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
>>>> @@ -1591,6 +1591,7 @@ static struct attribute *panthor_attrs[] = {
>>>> ? ATTRIBUTE_GROUPS(panthor);
>>>> ? ? static const struct of_device_id dt_match[] = {
>>>> +??? { .compatible = "fsl,imx95-mali" },??? /* G310 */
>> No sure the comment about G310 is needed.
>>
>>>> ????? { .compatible = "rockchip,rk3588-mali" },
>>>> ????? { .compatible = "arm,mali-valhall-csf" },
>>>> ????? {}
>>>> diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/
>>>> drm/panthor/panthor_gpu.c
>>>> index 0f07ef7d9aea7..2371ab8e50627 100644
>>>> --- a/drivers/gpu/drm/panthor/panthor_gpu.c
>>>> +++ b/drivers/gpu/drm/panthor/panthor_gpu.c
>>>> @@ -67,6 +67,7 @@ struct panthor_model {
>>>> ? }
>>>> ? ? static const struct panthor_model gpu_models[] = {
>>>> +??? GPU_MODEL(g310, 0, 0),??? /* NXP i.MX95 */
>> We can remove the comment about the SoC. This GPU model could be found
>> in other vendor platforms.
> 
> Maybe it is a good idea to keep track of which GPU is in which SoC at
> least this way ?

I am worried the list gets bigger and bigger.
Maybe a comment in the DTB binding would be me more appropriate and
easier to search?

>>> Are you sure about 0, 0? With this I get
>>>> [drm] mali-unknown id 0xac74 major 0x0 minor 0x0 status 0x1
>>>
>>> Using GPU_MODEL(g310, 10, 4) I get:
>>>> [drm] mali-g310 id 0xac74 major 0x0 minor 0x0 status 0x1
>>
>> I'd agree it should be GPU_MODEL(g310, 10, 4). Unless the GPU
>> version has been changed by the vendor?
> With the fix suggested by Alexander, I get the following output on boot,
> so I think 10/4 is OK ?
> 
> panthor 4d900000.gpu: [drm] clock rate = 1000000000
> panthor 4d900000.gpu: EM: created perf domain
> panthor 4d900000.gpu: [drm] mali-g310 id 0xac74 major 0x0 minor 0x0
> status 0x1
> panthor 4d900000.gpu: [drm] Features: L2:0x7110306 Tiler:0x809 Mem:0x1
> MMU:0x2830 AS:0xff
> panthor 4d900000.gpu: [drm] shader_present=0x1 l2_present=0x1
> tiler_present=0x1
> panthor 4d900000.gpu: [drm] Firmware protected mode entry not be
> supported, ignoring
> panthor 4d900000.gpu: [drm] Firmware git sha:
> 8e5cfcfec20cc8aff8509d37e72babc935d34a3b
> panthor 4d900000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0
> Instrumentation features 0x71
> [drm] Initialized panthor 1.3.0 for 4d900000.gpu on minor 0

It looks about right

Regards,
Florent



From mordan at ispras.ru  Mon Mar  3 06:02:29 2025
From: mordan at ispras.ru (Vitalii Mordan)
Date: Mon,  3 Mar 2025 17:02:29 +0300
Subject: [PATCH] rtc: at91sam9: fix call balance of rtc->sclk handling routines
Message-ID: <20250303140229.642959-1-mordan@ispras.ru>

If rtc->sclk was enabled in at91_rtc_probe(), it must be disabled in
all error paths to ensure proper cleanup. However, if
devm_rtc_register_device() returns an error in at91_rtc_probe(), the
rtc->sclk clock will not be disabled.

Use the devm_clk_get_enabled() helper function to ensure proper call
balance for rtc->sclk.

Found by Linux Verification Center (linuxtesting.org) with Klever.

Fixes: a975f47f6e9a ("rtc: at91sam9: use clk API instead of relying on AT91_SLOW_CLOCK")
Signed-off-by: Vitalii Mordan <mordan at ispras.ru>
---
 drivers/rtc/rtc-at91sam9.c | 28 +++++++---------------------
 1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 38991cca5930..f4b7cf37397f 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -375,21 +375,16 @@ static int at91_rtc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(rtc->sclk))
+	rtc->sclk = devm_clk_get_enabled(&pdev->dev, NULL);
+	if (IS_ERR(rtc->sclk)) {
+		dev_err(&pdev->dev, "Could not get and enable slow clock\n");
 		return PTR_ERR(rtc->sclk);
-
-	ret = clk_prepare_enable(rtc->sclk);
-	if (ret) {
-		dev_err(&pdev->dev, "Could not enable slow clock\n");
-		return ret;
 	}
 
 	sclk_rate = clk_get_rate(rtc->sclk);
 	if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
 		dev_err(&pdev->dev, "Invalid slow clock rate\n");
-		ret = -EINVAL;
-		goto err_clk;
+		return -EINVAL;
 	}
 
 	mr = rtt_readl(rtc, MR);
@@ -405,10 +400,8 @@ static int at91_rtc_probe(struct platform_device *pdev)
 	rtt_writel(rtc, MR, mr);
 
 	rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(rtc->rtcdev)) {
-		ret = PTR_ERR(rtc->rtcdev);
-		goto err_clk;
-	}
+	if (IS_ERR(rtc->rtcdev))
+		return PTR_ERR(rtc->rtcdev);
 
 	rtc->rtcdev->ops = &at91_rtc_ops;
 	rtc->rtcdev->range_max = U32_MAX;
@@ -419,7 +412,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
 			       dev_name(&rtc->rtcdev->dev), rtc);
 	if (ret) {
 		dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
-		goto err_clk;
+		return ret;
 	}
 
 	/* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
@@ -433,11 +426,6 @@ static int at91_rtc_probe(struct platform_device *pdev)
 			 dev_name(&rtc->rtcdev->dev));
 
 	return devm_rtc_register_device(rtc->rtcdev);
-
-err_clk:
-	clk_disable_unprepare(rtc->sclk);
-
-	return ret;
 }
 
 /*
@@ -450,8 +438,6 @@ static void at91_rtc_remove(struct platform_device *pdev)
 
 	/* disable all interrupts */
 	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
-
-	clk_disable_unprepare(rtc->sclk);
 }
 
 static void at91_rtc_shutdown(struct platform_device *pdev)
-- 
2.25.1



From yangyicong at huawei.com  Mon Mar  3 06:03:04 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:03:04 +0800
Subject: [PATCH v11 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <8a9aedef-08d7-445f-9b67-85e74ec6bd50@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-3-yangyicong@huawei.com>
 <8a9aedef-08d7-445f-9b67-85e74ec6bd50@arm.com>
Message-ID: <21e74021-fb68-0003-f0f4-7f54dd674b9d@huawei.com>

On 2025/2/28 19:11, Dietmar Eggemann wrote:
> On 18/02/2025 15:10, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> On building the topology from the devicetree, we've already
>> gotten the SMT thread number of each core. Update the largest
>> SMT thread number and enable the SMT control by the end of
>> topology parsing.
>>
>> The core's SMT control provides two interface to the users [1]:
>> 1) enable/disable SMT by writing on/off
>> 2) enable/disable SMT by writing thread number 1/max_thread_number
> 
> 1/max_thread_number stands for '1 or max_thread_number', right ?
> 
> Aren't the two interfaces:
> 
> (a) /sys/devices/system/cpu/smt/active
> (b) /sys/devices/system/cpu/smt/control
> 
> and you write 1) or 2) (or 'forceoff') into (b)?

yes you're correct. "active" is a RO file for status only so not for this interface.
Let me explicitly mention the /sys/devices/system/cpu/smt/control here in the commit.

> 
>> If a system have more than one SMT thread number the 2) may
> 
> s/have/has
> 
>> not handle it well, since there're multiple thread numbers in the
> 
> multiple thread numbers other than 1, right?

according to the pr_warn_once() we implemented below it also includes the case
where the system have one type of SMT cores and non-SMT cores (the thread number is 1):
- 1 thread
- X (!= 1) threads

Discussion made in [1] and I thought we have agreement (hope I understood correctly)
that all the asymmetric cases need to notify. Do you and Sudeep think we should not
warn in such case?

[1] https://lore.kernel.org/linux-arm-kernel/10082e64-b00a-a30b-b9c5-1401a54f6717 at huawei.com/

> 
>> system and 2) only accept 1/max_thread_number. So issue a warning
>> to notify the users if such system detected.
> 
> This paragraph seems to be about heterogeneous systems. Maybe mention this?
> 
> Heterogeneous system with SMT only on a subset of cores (like Intel
> Hybrid): This one works (N threads per core with N=1 and N=2) just fine.
> 
> But on Arm64 (default) we would still see:
> 
> [0.075782] Heterogeneous SMT topology is partly supported by SMT control
> 

more clearer, will add it. Thanks.

>> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
>>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>>  drivers/base/arch_topology.c | 27 +++++++++++++++++++++++++++
>>  1 file changed, 27 insertions(+)
>>
>> diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
>> index 3ebe77566788..23f425a9d77a 100644
>> --- a/drivers/base/arch_topology.c
>> +++ b/drivers/base/arch_topology.c
>> @@ -11,6 +11,7 @@
>>  #include <linux/cleanup.h>
>>  #include <linux/cpu.h>
>>  #include <linux/cpufreq.h>
>> +#include <linux/cpu_smt.h>
>>  #include <linux/device.h>
>>  #include <linux/of.h>
>>  #include <linux/slab.h>
>> @@ -506,6 +507,10 @@ core_initcall(free_raw_capacity);
>>  #endif
>>  
>>  #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
>> +
>> +/* Maximum SMT thread number detected used to enable the SMT control */
> 
> maybe shorter ?
> 
> /* used to enable SMT control */
> 

sure.

>> +static unsigned int max_smt_thread_num;
>> +
>>  /*
>>   * This function returns the logic cpu number of the node.
>>   * There are basically three kinds of return values:
>> @@ -565,6 +570,16 @@ static int __init parse_core(struct device_node *core, int package_id,
>>  		i++;
>>  	} while (1);
>>  
>> +	/*
>> +	 * If max_smt_thread_num has been initialized and doesn't match
>> +	 * the thread number of this entry, then the system has
>> +	 * heterogeneous SMT topology.
>> +	 */
>> +	if (max_smt_thread_num && max_smt_thread_num != i)
>> +		pr_warn_once("Heterogeneous SMT topology is partly supported by SMT control\n");
>> +
>> +	max_smt_thread_num = max_t(unsigned int, max_smt_thread_num, i);
>> +
>>  	cpu = get_cpu_for_node(core);
>>  	if (cpu >= 0) {
>>  		if (!leaf) {
>> @@ -677,6 +692,18 @@ static int __init parse_socket(struct device_node *socket)
>>  	if (!has_socket)
>>  		ret = parse_cluster(socket, 0, -1, 0);
>>  
>> +	/*
>> +	 * Notify the CPU framework of the SMT support. Initialize the
>> +	 * max_smt_thread_num to 1 if no SMT support detected or failed
>> +	 * to parse the topology. A thread number of 1 can be handled by
>> +	 * the framework so we don't need to check max_smt_thread_num to
>> +	 * see we support SMT or not.
> 
> Not sure whether the last sentence is needed here?
> 

We always need to call cpu_smt_set_num_threads() to notify the framework
of the thread number even if SMT is not supported. In which case the
thread number is 1 but the framework can handle this well. I worry readers
may get confused for notifying a thread number of 1 so add this comment this.

Will get rid of this if thought redundant.

Thanks.




From u.kleine-koenig at baylibre.com  Mon Mar  3 06:03:29 2025
From: u.kleine-koenig at baylibre.com (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 3 Mar 2025 15:03:29 +0100
Subject: [PATCH v3 0/2] ARM: dts: socfpga: Add basic support for
 Terrasic's de10-nano
In-Reply-To: <cover.1738600838.git.u.kleine-koenig@baylibre.com>
References: <cover.1738600838.git.u.kleine-koenig@baylibre.com>
Message-ID: <xqe3grxdj62u6ixl5cdzcgzjo6swe64kegzjx4qabkfbkohlb5@rwu6rrh5lkzm>

Hello Dinh,

On Mon, Feb 03, 2025 at 05:46:35PM +0100, Uwe Kleine-K?nig wrote:
> The only change since v2
> (https://lore.kernel.org/linux-arm-kernel/20250130074553.92023-2-u.kleine-koenig at baylibre.com):
> is that I added patch 1/2 that is supposed to fix the warning that I
> failed to notice with the testing I did. Thanks to Krzysztof and Rob for
> their patience with me. I hope I got it right now.

I didn't hear anything from your side on this patch set and I don't see
it applied in next. Do you still have it on your radar?

If you prefer me dropping the reg property on the fpga node, please
tell me. Otherwise you dropping it on application is fine for me and
keeping it is fine for the dt people, too.

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/5989a6e9/attachment.sig>

From gomba007 at gmail.com  Mon Mar  3 06:04:09 2025
From: gomba007 at gmail.com (=?utf-8?B?VMOzdGggSsOhbm9z?=)
Date: Mon, 3 Mar 2025 15:04:09 +0100
Subject: [PATCH 13/18] rtc: sd2405al: drop needless struct sd2405al::rtc
 member
In-Reply-To: <20250228-rtc-cleanups-v1-13-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
 <20250228-rtc-cleanups-v1-13-b44cec078481@linaro.org>
Message-ID: <2gfjdazu2ohv4evd7iuk2dzexlydnd6yu3xmjk2lgsx3iws5sa@xdwf4df4ojck>

Hi!

> We can drop it from the structure and just use a local temporary
> variable, reducing runtime memory consumption by a few bytes.

It works on real hardware.

Tested-by: T?th J?nos <gomba007 at gmail.com>

Regards,
TJ



From mordan at ispras.ru  Mon Mar  3 06:08:05 2025
From: mordan at ispras.ru (Vitalii Mordan)
Date: Mon,  3 Mar 2025 17:08:05 +0300
Subject: [PATCH] i2c: cadence: fix call balance of id->clk handling routines
Message-ID: <20250303140805.644143-1-mordan@ispras.ru>

If the clock id->clk was not enabled in cdns_i2c_probe(), it should not be
disabled in any execution path. If the clock was not enabled, the probe
function should return an error code.

Use the devm_clk_get_enabled() helper function to ensure proper call
balance for id->clk.

Found by Linux Verification Center (linuxtesting.org) with Klever.

Fixes: df8eb5691c48 ("i2c: Add driver for Cadence I2C controller")
Signed-off-by: Vitalii Mordan <mordan at ispras.ru>
---
 drivers/i2c/busses/i2c-cadence.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index b64026fbca66..07564a962dcb 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -1541,7 +1541,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
 	snprintf(id->adap.name, sizeof(id->adap.name),
 		 "Cadence I2C at %08lx", (unsigned long)r_mem->start);
 
-	id->clk = devm_clk_get(&pdev->dev, NULL);
+	id->clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(id->clk))
 		return dev_err_probe(&pdev->dev, PTR_ERR(id->clk),
 				     "input clock not found.\n");
@@ -1551,10 +1551,6 @@ static int cdns_i2c_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, PTR_ERR(id->reset),
 				     "Failed to request reset.\n");
 
-	ret = clk_prepare_enable(id->clk);
-	if (ret)
-		dev_err(&pdev->dev, "Unable to enable clock.\n");
-
 	ret = reset_control_deassert(id->reset);
 	if (ret) {
 		dev_err_probe(&pdev->dev, ret,
@@ -1617,7 +1613,6 @@ static int cdns_i2c_probe(struct platform_device *pdev)
 	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
 	reset_control_assert(id->reset);
 err_clk_dis:
-	clk_disable_unprepare(id->clk);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	return ret;
@@ -1642,7 +1637,6 @@ static void cdns_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&id->adap);
 	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
 	reset_control_assert(id->reset);
-	clk_disable_unprepare(id->clk);
 }
 
 static struct platform_driver cdns_i2c_drv = {
-- 
2.25.1



From dan.carpenter at linaro.org  Mon Mar  3 06:08:24 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 3 Mar 2025 17:08:24 +0300
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth:
 Add XDP support
In-Reply-To: <40ce8ed3-b36c-4d5f-b75a-7e0409beb713@ti.com>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
 <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
 <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>
 <40ce8ed3-b36c-4d5f-b75a-7e0409beb713@ti.com>
Message-ID: <61117a07-35b5-48c0-93d9-f97db8e15503@stanley.mountain>

What I mean is just compile the .o file with and without the unlikely().

$ md5sum drivers/net/ethernet/ti/icssg/icssg_common.o*
2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.annotation
2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.no_anotation

Generally the rule is that you should leave likely/unlikely() annotations
out unless it's going to make a difference on a benchmark.  I'm not going
to jump down people's throat about this, and if you want to leave it,
it's fine.  But it just struct me as weird so that's why I commented on
it.

regards,
dan carpenter

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index 34d16e00c2ec..3db5bae44e61 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -672,7 +672,7 @@ static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
 	case XDP_TX:
 		/* Send packet to TX ring for immediate transmission */
 		xdpf = xdp_convert_buff_to_frame(xdp);
-		if (unlikely(!xdpf))
+		if (!xdpf)
 			goto drop;
 
 		q_idx = smp_processor_id() % emac->tx_ch_num;


From yangyicong at huawei.com  Mon Mar  3 06:11:48 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:11:48 +0800
Subject: [PATCH v11 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <Z8HAFftf7rAdc_MC@bogus>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-3-yangyicong@huawei.com> <Z8HAFftf7rAdc_MC@bogus>
Message-ID: <e6942ad5-e6dd-362a-a27e-ef722b8d30a7@huawei.com>

On 2025/2/28 21:54, Sudeep Holla wrote:
> On Tue, Feb 18, 2025 at 10:10:16PM +0800, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> On building the topology from the devicetree, we've already
>> gotten the SMT thread number of each core. Update the largest
>> SMT thread number and enable the SMT control by the end of
>> topology parsing.
>>
>> The core's SMT control provides two interface to the users [1]:
>> 1) enable/disable SMT by writing on/off
>> 2) enable/disable SMT by writing thread number 1/max_thread_number
>>
>> If a system have more than one SMT thread number the 2) may
>> not handle it well, since there're multiple thread numbers in the
>> system and 2) only accept 1/max_thread_number. So issue a warning
>> to notify the users if such system detected.
>>
>> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
>>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>>  drivers/base/arch_topology.c | 27 +++++++++++++++++++++++++++
>>  1 file changed, 27 insertions(+)
>>
>> diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
>> index 3ebe77566788..23f425a9d77a 100644
>> --- a/drivers/base/arch_topology.c
>> +++ b/drivers/base/arch_topology.c
>> @@ -11,6 +11,7 @@
>>  #include <linux/cleanup.h>
>>  #include <linux/cpu.h>
>>  #include <linux/cpufreq.h>
>> +#include <linux/cpu_smt.h>
>>  #include <linux/device.h>
>>  #include <linux/of.h>
>>  #include <linux/slab.h>
>> @@ -506,6 +507,10 @@ core_initcall(free_raw_capacity);
>>  #endif
>>  
>>  #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
>> +
>> +/* Maximum SMT thread number detected used to enable the SMT control */
>> +static unsigned int max_smt_thread_num;
>> +
>>  /*
>>   * This function returns the logic cpu number of the node.
>>   * There are basically three kinds of return values:
>> @@ -565,6 +570,16 @@ static int __init parse_core(struct device_node *core, int package_id,
>>  		i++;
>>  	} while (1);
>>  
>> +	/*
>> +	 * If max_smt_thread_num has been initialized and doesn't match
>> +	 * the thread number of this entry, then the system has
>> +	 * heterogeneous SMT topology.
>> +	 */
>> +	if (max_smt_thread_num && max_smt_thread_num != i)
>> +		pr_warn_once("Heterogeneous SMT topology is partly supported by SMT control\n");
>> +
> 
> May be we need to make it more conditional as we may have to support
> systems with few cores that are single threaded ? I think Dietmar's
> comment is about that.
> 

it thought of ignoring the cores with single thread in one previous discussion
as replied in Dietmar's thread.

>> +	max_smt_thread_num = max_t(unsigned int, max_smt_thread_num, i);
>> +
>>  	cpu = get_cpu_for_node(core);
>>  	if (cpu >= 0) {
>>  		if (!leaf) {
>> @@ -677,6 +692,18 @@ static int __init parse_socket(struct device_node *socket)
>>  	if (!has_socket)
>>  		ret = parse_cluster(socket, 0, -1, 0);
>>  
>> +	/*
>> +	 * Notify the CPU framework of the SMT support. Initialize the
>> +	 * max_smt_thread_num to 1 if no SMT support detected or failed
>> +	 * to parse the topology. A thread number of 1 can be handled by
>> +	 * the framework so we don't need to check max_smt_thread_num to
>> +	 * see we support SMT or not.
>> +	 */
>> +	if (!max_smt_thread_num || ret)
>> +		max_smt_thread_num = 1;
>> +
> 
> For the failed parsing of topology, reset_cpu_topology() gets called.
> I suggest resetting max_smt_thread_num to 1 belongs there.

this is only used by ARM64 || RISCV for using arch_topology to parse
the CPU topology, but the reset_cpu_topology() is also shared by arm/parisc.
Should we move it there and add some ARM64 || RISCV protection macro?

> 
> And if you start with max_smt_thread_num, we don't need to update it to
> 1 explicitly here. So I would like to get rid of above check completely.
> 
> --
> Regards,
> Sudeep
> 
> .
> 


From robh at kernel.org  Mon Mar  3 05:14:20 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 03 Mar 2025 07:14:20 -0600
Subject: [PATCH v4 0/7] Add support for the Exynos7870 SoC, along with
 three devices
In-Reply-To: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
References: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
Message-ID: <174100756283.1496281.12555971793250210333.robh@kernel.org>


On Sat, 01 Mar 2025 01:16:48 +0530, Kaustabh Chakraborty wrote:
> Samsung Exynos 7870 (codename: Joshua) is an ARM-v8 system-on-chip that was
> announced in 2016. The chipset was found in several popular mid-range to
> low-end Samsung phones, released within 2016 to 2019.
> 
> This patch series aims to add support for Exynos 7870, starting with the
> most basic yet essential components such as CPU, GPU, clock controllers,
> PMIC, pin controllers, etc.
> 
> Moreover, the series also adds support for three Exynos 7870 devices via
> devicetree. The devices are:
>  * Samsung Galaxy J7 Prime	- released 2016, codename on7xelte
>  * Samsung Galaxy J6		- released 2018, codename j6lte
>  * Samsung Galaxy A2 Core	- released 2019, codename a2corelte
> 
> Additional features implemented in this series include:
>  * I2C	- touchscreen, IIO sensors, etc.
>  * UART	- bluetooth and serial debugging
>  * MMC	- eMMC, Wi-Fi SDIO, SDCard
>  * USB	- micro-USB 2.0 interface
> 
> Build dependencies are in these sub-series:
>  * bootmode	  	- https://lore.kernel.org/all/20250204-exynos7870-bootmode-v1-1-0f17b3033c2d at disroot.org/
>  * pmu-clocks		- https://lore.kernel.org/all/20250301-exynos7870-pmu-clocks-v4-0-0f3e73b10db7 at disroot.org/
> 
> Other related sub-series:
>  * gpu			R https://lore.kernel.org/all/20250204-exynos7870-gpu-v1-1-0db4c163a030 at disroot.org/
>  * i2c	      		A https://lore.kernel.org/all/20250204-exynos7870-i2c-v1-0-63d67871ab7e at disroot.org/
>  * mmc			- https://lore.kernel.org/all/20250219-exynos7870-mmc-v2-0-b4255a3e39ed at disroot.org/
>  * pinctrl	  	- https://lore.kernel.org/all/20250301-exynos7870-pinctrl-v3-0-ba1da9d3cd2f at disroot.org/
>  * pmic-regulators	- https://lore.kernel.org/all/20250301-exynos7870-pmic-regulators-v3-0-808d0b47a564 at disroot.org/
>  * uart			R https://lore.kernel.org/all/20250219-exynos7870-uart-v2-1-c8c67f3a936c at disroot.org/
>  * usb			- https://lore.kernel.org/all/20250301-exynos7870-usb-v3-0-f01697165d19 at disroot.org/
>  * usbphy		- https://lore.kernel.org/all/20250219-exynos7870-usbphy-v2-0-b8ba4e7a72e9 at disroot.org/
> (Legend: [R]eviewed, [A]pplied)
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
> ---
> Changes in v4:
> - Drop merged [PATCH v3 1/7].
> - Explicitly mention sub-series having build dependencies.
> - Include the following patch from the pmu-clocks series:
>   - dt-bindings: soc: samsung: exynos-pmu: add exynos7870-pmu compatible
> - Adjust clock header file name to match changes in pmu-clocks.
> - Change regulator node names to match changes in pmic-regulators.
> - Remove non-removable flag for the SDCard's mmc node.
> - Link to v3: https://lore.kernel.org/r/20250219-exynos7870-v3-0-e384fb610cad at disroot.org
> 
> Changes in v3:
> - Added patches from https://lore.kernel.org/all/20250204-exynos7870-chipid-v1-0-0bf2db08e621 at disroot.org/
> - Fix devicetree formatting according to the devicetree style guide.
> - Take over ownership of patches by the co-author, upon their request.
> - Link to v2: https://lore.kernel.org/r/20250204-exynos7870-v2-0-56313165ef0c at disroot.org
> 
> Changes in v2:
> - Redo a few commit descriptions.
> - Split patchsets into multiple sub-series, subsystem-wise.
> - Link to v1: https://lore.kernel.org/r/20250203-exynos7870-v1-0-2b6df476a3f0 at disroot.org
> 
> ---
> Kaustabh Chakraborty (7):
>       dt-bindings: soc: samsung: exynos-pmu: add exynos7870-pmu compatible
>       dt-bindings: arm: samsung: add compatibles for exynos7870 devices
>       soc: samsung: exynos-chipid: add support for exynos7870
>       arm64: dts: exynos: add initial devicetree support for exynos7870
>       arm64: dts: exynos: add initial support for Samsung Galaxy J7 Prime
>       arm64: dts: exynos: add initial support for Samsung Galaxy A2 Core
>       arm64: dts: exynos: add initial support for Samsung Galaxy J6
> 
>  .../bindings/arm/samsung/samsung-boards.yaml       |    8 +
>  .../bindings/soc/samsung/exynos-pmu.yaml           |    1 +
>  arch/arm64/boot/dts/exynos/Makefile                |    3 +
>  .../arm64/boot/dts/exynos/exynos7870-a2corelte.dts |  628 ++++++++++++
>  arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts    |  616 ++++++++++++
>  arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts |  664 +++++++++++++
>  arch/arm64/boot/dts/exynos/exynos7870-pinctrl.dtsi | 1022 ++++++++++++++++++++
>  arch/arm64/boot/dts/exynos/exynos7870.dtsi         |  714 ++++++++++++++
>  drivers/soc/samsung/exynos-chipid.c                |    1 +
>  9 files changed, 3657 insertions(+)
> ---
> base-commit: be5c7bbb3a64baf884481a1ba0c2f8fb2f93f7c3
> change-id: 20250201-exynos7870-049587e4b7df
> 
> Best regards,
> --
> Kaustabh Chakraborty <kauschluss at disroot.org>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/exynos/' for 20250301-exynos7870-v4-0-2925537f9b2a at disroot.org:

In file included from arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts:10:
arch/arm64/boot/dts/exynos/exynos7870.dtsi:9:10: fatal error: dt-bindings/clock/samsung,exynos7870-cmu.h: No such file or directory
    9 | #include <dt-bindings/clock/samsung,exynos7870-cmu.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [scripts/Makefile.dtbs:131: arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dtb] Error 1
make[2]: *** [scripts/Makefile.build:461: arch/arm64/boot/dts/exynos] Error 2
make[2]: Target 'arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dtb' not remade because of errors.
make[1]: *** [/home/rob/proj/linux-dt-testing/Makefile:1462: exynos/exynos7870-on7xelte.dtb] Error 2
In file included from arch/arm64/boot/dts/exynos/exynos7870-a2corelte.dts:10:
arch/arm64/boot/dts/exynos/exynos7870.dtsi:9:10: fatal error: dt-bindings/clock/samsung,exynos7870-cmu.h: No such file or directory
    9 | #include <dt-bindings/clock/samsung,exynos7870-cmu.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [scripts/Makefile.dtbs:131: arch/arm64/boot/dts/exynos/exynos7870-a2corelte.dtb] Error 1
make[2]: *** [scripts/Makefile.build:461: arch/arm64/boot/dts/exynos] Error 2
make[2]: Target 'arch/arm64/boot/dts/exynos/exynos7870-a2corelte.dtb' not remade because of errors.
make[1]: *** [/home/rob/proj/linux-dt-testing/Makefile:1462: exynos/exynos7870-a2corelte.dtb] Error 2
In file included from arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts:10:
arch/arm64/boot/dts/exynos/exynos7870.dtsi:9:10: fatal error: dt-bindings/clock/samsung,exynos7870-cmu.h: No such file or directory
    9 | #include <dt-bindings/clock/samsung,exynos7870-cmu.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [scripts/Makefile.dtbs:131: arch/arm64/boot/dts/exynos/exynos7870-j6lte.dtb] Error 1
make[2]: *** [scripts/Makefile.build:461: arch/arm64/boot/dts/exynos] Error 2
make[2]: Target 'arch/arm64/boot/dts/exynos/exynos7870-j6lte.dtb' not remade because of errors.
make[1]: *** [/home/rob/proj/linux-dt-testing/Makefile:1462: exynos/exynos7870-j6lte.dtb] Error 2
make: *** [Makefile:251: __sub-make] Error 2
make: Target 'exynos/exynos8895-dreamlte.dtb' not remade because of errors.
make: Target 'exynos/exynos850-e850-96.dtb' not remade because of errors.
make: Target 'exynos/exynos7870-on7xelte.dtb' not remade because of errors.
make: Target 'exynos/exynos7885-jackpotlte.dtb' not remade because of errors.
make: Target 'exynos/exynos990-x1slte.dtb' not remade because of errors.
make: Target 'exynos/exynos5433-tm2.dtb' not remade because of errors.
make: Target 'exynos/exynos990-r8s.dtb' not remade because of errors.
make: Target 'exynos/exynos7-espresso.dtb' not remade because of errors.
make: Target 'exynos/google/gs101-oriole.dtb' not remade because of errors.
make: Target 'exynos/google/gs101-raven.dtb' not remade because of errors.
make: Target 'exynos/exynosautov920-sadk.dtb' not remade because of errors.
make: Target 'exynos/exynosautov9-sadk.dtb' not remade because of errors.
make: Target 'exynos/exynos990-c1s.dtb' not remade because of errors.
make: Target 'exynos/exynos9810-starlte.dtb' not remade because of errors.
make: Target 'exynos/exynos990-x1s.dtb' not remade because of errors.
make: Target 'exynos/exynos7870-a2corelte.dtb' not remade because of errors.
make: Target 'exynos/exynos5433-tm2e.dtb' not remade because of errors.
make: Target 'exynos/exynos7870-j6lte.dtb' not remade because of errors.







From robh at kernel.org  Mon Mar  3 05:14:22 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 03 Mar 2025 07:14:22 -0600
Subject: [PATCH v2 0/2] Describe the cameras in the PinePhone Pro dts
In-Reply-To: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
References: <20250302-camera-v2-0-312b44b4a89c@bootlin.com>
Message-ID: <174100756342.1496432.13525001046589650436.robh@kernel.org>


On Sun, 02 Mar 2025 16:41:01 +0100, Olivier Benjamin wrote:
> This series adds support for the Pine64 PinePhone Pro's rear and front
> cameras in Device Tree.
> This is based on some of Ondrej Jirman's patches hosted in his tree at
> https://codeberg.org/megi/linux, but I have also fully reviewed and
> re-written the code from the RK3399 datasheet, the PinePhone Pro
> schematic, and the IMX258-0AQH5 software reference manual.
> 
> I have tested these changes on my PinePhone Pro and am able to take
> photos from both cameras using libcamera's cam.
> 
> Signed-off-by: Olivier Benjamin <olivier.benjamin at bootlin.com>
> ---
> Changes in v2:
> - Rebase on mainline
> - Change patch subject to arm64: dts: rockchip
> - Rename new regulators to fit preferred form for fixed regulators
> - Link to v1: https://lore.kernel.org/r/20250228-camera-v1-0-c51869f94e97 at bootlin.com
> 
> ---
> Olivier Benjamin (2):
>       arm64: dts: rockchip: describe I2c Bus 1 and IMX258 world camera on PinePhone Pro
>       arm64: dts: rockchip: describe the OV8858 user camera on PinePhone Pro
> 
>  .../boot/dts/rockchip/rk3399-pinephone-pro.dts     | 138 +++++++++++++++++++++
>  1 file changed, 138 insertions(+)
> ---
> --
> Olivier Benjamin <olivier.benjamin at bootlin.com>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/rockchip/' for 20250302-camera-v2-0-312b44b4a89c at bootlin.com:

arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dtb: camera at 1a: port:endpoint: 'link-frequencies' is a required property
	from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx258.yaml#
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dtb: camera at 1a: 'clock-names', 'lens-focus', 'orientation', 'rotation' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx258.yaml#
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dtb: camera at 36: 'orientation', 'rotation' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/media/i2c/ovti,ov8858.yaml#







From robh at kernel.org  Mon Mar  3 05:14:24 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 03 Mar 2025 07:14:24 -0600
Subject: [PATCH v2 0/2] Add System Components for Microchip SAMA7D65
 SoC
In-Reply-To: <cover.1740675317.git.Ryan.Wanner@microchip.com>
References: <cover.1740675317.git.Ryan.Wanner@microchip.com>
Message-ID: <174100756391.1496568.10334189756404294750.robh@kernel.org>


On Fri, 28 Feb 2025 08:24:09 -0700, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> This patch set adds support for the following systems in the SAMA7D65
> SoC:
> - DMAs
> - Chip ID
> - Dual watchdog timer.
> 
> Changes v1 -> v2:
> - Removed pathes that have been accepted and applied from v1 [1].
> - Corrected missing newline in dt-binding.
> - Corrected mismatch in watchdog dt node.
> 
> 1) https://lore.kernel.org/linux-arm-kernel/09eafe54-c262-4db4-b11d-0644a1f90a14 at tuxon.dev/
> 
> Ryan Wanner (2):
>   dt-bindings: watchdog: sama5d4-wdt: Add sama7d65-wdt
>   ARM: dts: microchip: sama7d65: Add watchdog for sama7d65
> 
>  .../devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml    | 4 ++++
>  arch/arm/boot/dts/microchip/sama7d65.dtsi                  | 7 +++++++
>  2 files changed, 11 insertions(+)
> 
> --
> 2.43.0
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/microchip/' for cover.1740675317.git.Ryan.Wanner at microchip.com:

arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dtb: watchdog at e001d000: Unevaluated properties are not allowed ('clocks' was unexpected)
	from schema $id: http://devicetree.org/schemas/watchdog/atmel,sama5d4-wdt.yaml#
arch/arm/boot/dts/microchip/at91-dvk_som60.dtb: /ahb/apb/adc at f8018000: failed to match any schema with compatible: ['atmel,sama5d3-adc']
arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dtb: nand-controller: #address-cells: 1 was expected
	from schema $id: http://devicetree.org/schemas/mtd/nand-controller.yaml#







From chunkuang.hu at kernel.org  Mon Mar  3 05:15:50 2025
From: chunkuang.hu at kernel.org (Chun-Kuang Hu)
Date: Mon, 3 Mar 2025 21:15:50 +0800
Subject: [PATCH v7 3/6] drm/mediatek: add MT8365 SoC support
In-Reply-To: <20231023-display-support-v7-3-6703f3e26831@baylibre.com>
References: <20231023-display-support-v7-0-6703f3e26831@baylibre.com> <20231023-display-support-v7-3-6703f3e26831@baylibre.com>
Message-ID: <CAAOTY__qg1R4JQDssy1bDDJMea8Ud7OsPXjek20cHV8S=jfNbA@mail.gmail.com>

Hi, Amergnat:

<amergnat at baylibre.com> ? 2025?1?10? ?? ??9:31???
>
> From: Fabien Parent <fparent at baylibre.com>
>
> Add DRM support for MT8365 SoC.
>
> Signed-off-by: Fabien Parent <fparent at baylibre.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Applied to mediatek-drm-next [1], thanks.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next

Regards,
Chun-Kuang.

> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 0829ceb9967c..5471ef744cc1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -328,6 +328,10 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
>         .min_height = 1,
>  };
>
> +static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
> +       .mmsys_dev_num = 1,
> +};
> +
>  static const struct of_device_id mtk_drm_of_ids[] = {
>         { .compatible = "mediatek,mt2701-mmsys",
>           .data = &mt2701_mmsys_driver_data},
> @@ -355,6 +359,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
>           .data = &mt8195_vdosys0_driver_data},
>         { .compatible = "mediatek,mt8195-vdosys1",
>           .data = &mt8195_vdosys1_driver_data},
> +       { .compatible = "mediatek,mt8365-mmsys",
> +         .data = &mt8365_mmsys_driver_data},
>         { }
>  };
>  MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
> @@ -751,6 +757,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
>           .data = (void *)MTK_DISP_MUTEX },
>         { .compatible = "mediatek,mt8195-disp-mutex",
>           .data = (void *)MTK_DISP_MUTEX },
> +       { .compatible = "mediatek,mt8365-disp-mutex",
> +         .data = (void *)MTK_DISP_MUTEX },
>         { .compatible = "mediatek,mt8173-disp-od",
>           .data = (void *)MTK_DISP_OD },
>         { .compatible = "mediatek,mt2701-disp-ovl",
>
> --
> 2.25.1
>


From brgl at bgdev.pl  Mon Mar  3 05:18:25 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:25 +0100
Subject: [PATCH 00/15] gpio: convert more drivers to using the new value
 setters
Message-ID: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>

New variants of set() and set_multiple() callbacks allow drivers to
indicate failures back to callers. Convert more GPIO drivers to using
them as the old ones are now deprecated.

This series also contains some additional refactoring to the affected
drivers wherever it makes the conversion easier.

To: 

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
Bartosz Golaszewski (15):
      gpio: 74x164: use new line value setter callbacks
      gpio: adnp: use lock guards for the I2C lock
      gpio: adnp: use devm_mutex_init()
      gpio: adnp: use new line value setter callbacks
      gpio: adp5520: use new line value setter callbacks
      gpio: adp5585: use new line value setter callbacks
      gpio: altera-a10sr: use new line value setter callbacks
      gpio: altera: use new line value setter callbacks
      gpio: amd8111: use new line value setter callbacks
      gpio: amd-fch: use new line value setter callbacks
      gpio: arizona: use new line value setter callbacks
      gpio: aspeed: use lock guards
      gpio: aspeed: use new line value setter callbacks
      gpio: aspeed-sgpio: use lock guards
      gpio: aspeed-sgpio: use new line value setter callbacks

 drivers/gpio/gpio-74x164.c       |  16 ++---
 drivers/gpio/gpio-adnp.c         | 136 +++++++++++++++++----------------------
 drivers/gpio/gpio-adp5520.c      |  12 ++--
 drivers/gpio/gpio-adp5585.c      |  10 +--
 drivers/gpio/gpio-altera-a10sr.c |  14 ++--
 drivers/gpio/gpio-altera.c       |   6 +-
 drivers/gpio/gpio-amd-fch.c      |   7 +-
 drivers/gpio/gpio-amd8111.c      |   6 +-
 drivers/gpio/gpio-arizona.c      |   9 +--
 drivers/gpio/gpio-aspeed-sgpio.c |  82 +++++++++--------------
 drivers/gpio/gpio-aspeed.c       | 108 ++++++++++++-------------------
 11 files changed, 177 insertions(+), 229 deletions(-)
---
base-commit: 9778568dede2166c7bd124d473f9ec365f782935
change-id: 20250303-gpiochip-set-conversion-736fb6548975

Best regards,
-- 
Bartosz Golaszewski <bartosz.golaszewski at linaro.org>



From brgl at bgdev.pl  Mon Mar  3 05:18:26 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:26 +0100
Subject: [PATCH 01/15] gpio: 74x164: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-1-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-74x164.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 640ac24b72a2..4dd5c2c330bb 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -50,8 +50,8 @@ static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
 	return !!(chip->buffer[bank] & BIT(pin));
 }
 
-static void gen_74x164_set_value(struct gpio_chip *gc,
-		unsigned offset, int val)
+static int gen_74x164_set_value(struct gpio_chip *gc,
+				unsigned int offset, int val)
 {
 	struct gen_74x164_chip *chip = gpiochip_get_data(gc);
 	u8 bank = chip->registers - 1 - offset / 8;
@@ -64,11 +64,11 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
 	else
 		chip->buffer[bank] &= ~BIT(pin);
 
-	__gen_74x164_write_config(chip);
+	return __gen_74x164_write_config(chip);
 }
 
-static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask,
-				    unsigned long *bits)
+static int gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+				   unsigned long *bits)
 {
 	struct gen_74x164_chip *chip = gpiochip_get_data(gc);
 	unsigned long offset;
@@ -85,7 +85,7 @@ static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask,
 		chip->buffer[bank] &= ~bankmask;
 		chip->buffer[bank] |= bitmask;
 	}
-	__gen_74x164_write_config(chip);
+	return __gen_74x164_write_config(chip);
 }
 
 static int gen_74x164_direction_output(struct gpio_chip *gc,
@@ -141,8 +141,8 @@ static int gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.label = spi->modalias;
 	chip->gpio_chip.direction_output = gen_74x164_direction_output;
 	chip->gpio_chip.get = gen_74x164_get_value;
-	chip->gpio_chip.set = gen_74x164_set_value;
-	chip->gpio_chip.set_multiple = gen_74x164_set_multiple;
+	chip->gpio_chip.set_rv = gen_74x164_set_value;
+	chip->gpio_chip.set_multiple_rv = gen_74x164_set_multiple;
 	chip->gpio_chip.base = -1;
 	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
 	chip->gpio_chip.can_sleep = true;

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:27 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:27 +0100
Subject: [PATCH 02/15] gpio: adnp: use lock guards for the I2C lock
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-2-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reduce the code complexity by using automatic lock guards with the I2C
mutex.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-adnp.c | 118 +++++++++++++++++++----------------------------
 1 file changed, 47 insertions(+), 71 deletions(-)

diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 6dafab0cf964..dc87768276ec 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2011-2012 Avionic Design GmbH
  */
 
+#include <linux/cleanup.h>
 #include <linux/gpio/driver.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -101,9 +102,9 @@ static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct adnp *adnp = gpiochip_get_data(chip);
 
-	mutex_lock(&adnp->i2c_lock);
+	guard(mutex)(&adnp->i2c_lock);
+
 	__adnp_gpio_set(adnp, offset, value);
-	mutex_unlock(&adnp->i2c_lock);
 }
 
 static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -114,32 +115,26 @@ static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	u8 value;
 	int err;
 
-	mutex_lock(&adnp->i2c_lock);
+	guard(mutex)(&adnp->i2c_lock);
 
 	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
 	if (err < 0)
-		goto out;
+		return err;
 
 	value &= ~BIT(pos);
 
 	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value);
 	if (err < 0)
-		goto out;
+		return err;
 
 	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
 	if (err < 0)
-		goto out;
+		return err;
 
-	if (value & BIT(pos)) {
-		err = -EPERM;
-		goto out;
-	}
+	if (value & BIT(pos))
+		return -EPERM;
 
-	err = 0;
-
-out:
-	mutex_unlock(&adnp->i2c_lock);
-	return err;
+	return 0;
 }
 
 static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
@@ -151,33 +146,28 @@ static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 	int err;
 	u8 val;
 
-	mutex_lock(&adnp->i2c_lock);
+	guard(mutex)(&adnp->i2c_lock);
 
 	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
 	if (err < 0)
-		goto out;
+		return err;
 
 	val |= BIT(pos);
 
 	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val);
 	if (err < 0)
-		goto out;
+		return err;
 
 	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
 	if (err < 0)
-		goto out;
+		return err;
 
-	if (!(val & BIT(pos))) {
-		err = -EPERM;
-		goto out;
-	}
+	if (!(val & BIT(pos)))
+		return -EPERM;
 
 	__adnp_gpio_set(adnp, offset, value);
-	err = 0;
 
-out:
-	mutex_unlock(&adnp->i2c_lock);
-	return err;
+	return 0;
 }
 
 static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@@ -189,25 +179,24 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	for (i = 0; i < num_regs; i++) {
 		u8 ddr, plr, ier, isr;
 
-		mutex_lock(&adnp->i2c_lock);
+		scoped_guard(mutex, &adnp->i2c_lock) {
+			err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr);
+			if (err < 0)
+				return;
 
-		err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr);
-		if (err < 0)
-			goto unlock;
+			err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr);
+			if (err < 0)
+				return;
 
-		err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr);
-		if (err < 0)
-			goto unlock;
+			err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
+			if (err < 0)
+				return;
 
-		err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
-		if (err < 0)
-			goto unlock;
+			err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
+			if (err < 0)
+				return;
 
-		err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
-		if (err < 0)
-			goto unlock;
-
-		mutex_unlock(&adnp->i2c_lock);
+		}
 
 		for (j = 0; j < 8; j++) {
 			unsigned int bit = (i << adnp->reg_shift) + j;
@@ -232,11 +221,6 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 				   direction, level, interrupt, pending);
 		}
 	}
-
-	return;
-
-unlock:
-	mutex_unlock(&adnp->i2c_lock);
 }
 
 static irqreturn_t adnp_irq(int irq, void *data)
@@ -252,28 +236,20 @@ static irqreturn_t adnp_irq(int irq, void *data)
 		unsigned long pending;
 		int err;
 
-		mutex_lock(&adnp->i2c_lock);
+		scoped_guard(mutex, &adnp->i2c_lock) {
+			err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
+			if (err < 0)
+				continue;
 
-		err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
-		if (err < 0) {
-			mutex_unlock(&adnp->i2c_lock);
-			continue;
+			err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
+			if (err < 0)
+				continue;
+
+			err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
+			if (err < 0)
+				continue;
 		}
 
-		err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
-		if (err < 0) {
-			mutex_unlock(&adnp->i2c_lock);
-			continue;
-		}
-
-		err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
-		if (err < 0) {
-			mutex_unlock(&adnp->i2c_lock);
-			continue;
-		}
-
-		mutex_unlock(&adnp->i2c_lock);
-
 		/* determine pins that changed levels */
 		changed = level ^ adnp->irq_level[i];
 
@@ -365,12 +341,12 @@ static void adnp_irq_bus_unlock(struct irq_data *d)
 	struct adnp *adnp = gpiochip_get_data(gc);
 	unsigned int num_regs = 1 << adnp->reg_shift, i;
 
-	mutex_lock(&adnp->i2c_lock);
+	scoped_guard(mutex, &adnp->i2c_lock) {
+		for (i = 0; i < num_regs; i++)
+			adnp_write(adnp, GPIO_IER(adnp) + i,
+				   adnp->irq_enable[i]);
+	}
 
-	for (i = 0; i < num_regs; i++)
-		adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]);
-
-	mutex_unlock(&adnp->i2c_lock);
 	mutex_unlock(&adnp->irq_lock);
 }
 

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:28 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:28 +0100
Subject: [PATCH 03/15] gpio: adnp: use devm_mutex_init()
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-3-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

The mutex initialized in probe() is never cleaned up. Use
devm_mutex_init() to do it automatically.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-adnp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index dc87768276ec..d6ae9cf1eb54 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/property.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -482,7 +483,10 @@ static int adnp_i2c_probe(struct i2c_client *client)
 	if (!adnp)
 		return -ENOMEM;
 
-	mutex_init(&adnp->i2c_lock);
+	err = devm_mutex_init(&client->dev, &adnp->i2c_lock);
+	if (err)
+		return err;
+
 	adnp->client = client;
 
 	err = adnp_gpio_setup(adnp, num_gpios, device_property_read_bool(dev, "interrupt-controller"));

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:29 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:29 +0100
Subject: [PATCH 04/15] gpio: adnp: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-4-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-adnp.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index d6ae9cf1eb54..b31ce0e337ae 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -80,7 +80,7 @@ static int adnp_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return (value & BIT(pos)) ? 1 : 0;
 }
 
-static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value)
+static int __adnp_gpio_set(struct adnp *adnp, unsigned int offset, int value)
 {
 	unsigned int reg = offset >> adnp->reg_shift;
 	unsigned int pos = offset & 7;
@@ -89,23 +89,23 @@ static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value)
 
 	err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &val);
 	if (err < 0)
-		return;
+		return err;
 
 	if (value)
 		val |= BIT(pos);
 	else
 		val &= ~BIT(pos);
 
-	adnp_write(adnp, GPIO_PLR(adnp) + reg, val);
+	return adnp_write(adnp, GPIO_PLR(adnp) + reg, val);
 }
 
-static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int adnp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
 {
 	struct adnp *adnp = gpiochip_get_data(chip);
 
 	guard(mutex)(&adnp->i2c_lock);
 
-	__adnp_gpio_set(adnp, offset, value);
+	return __adnp_gpio_set(adnp, offset, value);
 }
 
 static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -430,7 +430,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios,
 	chip->direction_input = adnp_gpio_direction_input;
 	chip->direction_output = adnp_gpio_direction_output;
 	chip->get = adnp_gpio_get;
-	chip->set = adnp_gpio_set;
+	chip->set_rv = adnp_gpio_set;
 	chip->can_sleep = true;
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS))

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:30 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:30 +0100
Subject: [PATCH 05/15] gpio: adp5520: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-5-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-adp5520.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index c55e821c63b6..57d12c10cbda 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -40,16 +40,18 @@ static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
 	return !!(reg_val & dev->lut[off]);
 }
 
-static void adp5520_gpio_set_value(struct gpio_chip *chip,
-		unsigned off, int val)
+static int adp5520_gpio_set_value(struct gpio_chip *chip,
+				  unsigned int off, int val)
 {
 	struct adp5520_gpio *dev;
 	dev = gpiochip_get_data(chip);
 
 	if (val)
-		adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+		return adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
+					dev->lut[off]);
 	else
-		adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+		return adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
+					dev->lut[off]);
 }
 
 static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
@@ -120,7 +122,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
 	gc->direction_input  = adp5520_gpio_direction_input;
 	gc->direction_output = adp5520_gpio_direction_output;
 	gc->get = adp5520_gpio_get_value;
-	gc->set = adp5520_gpio_set_value;
+	gc->set_rv = adp5520_gpio_set_value;
 	gc->can_sleep = true;
 
 	gc->base = pdata->gpio_start;

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:31 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:31 +0100
Subject: [PATCH 06/15] gpio: adp5585: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-6-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-adp5585.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c
index 000d31f09671..d5c0f1b267c8 100644
--- a/drivers/gpio/gpio-adp5585.c
+++ b/drivers/gpio/gpio-adp5585.c
@@ -86,14 +86,16 @@ static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off)
 	return !!(val & bit);
 }
 
-static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val)
+static int adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off,
+				  int val)
 {
 	struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
 	unsigned int bank = ADP5585_BANK(off);
 	unsigned int bit = ADP5585_BIT(off);
 
-	regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank,
-			   bit, val ? bit : 0);
+	return regmap_update_bits(adp5585_gpio->regmap,
+				  ADP5585_GPO_DATA_OUT_A + bank,
+				  bit, val ? bit : 0);
 }
 
 static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,
@@ -192,7 +194,7 @@ static int adp5585_gpio_probe(struct platform_device *pdev)
 	gc->direction_input = adp5585_gpio_direction_input;
 	gc->direction_output = adp5585_gpio_direction_output;
 	gc->get = adp5585_gpio_get_value;
-	gc->set = adp5585_gpio_set_value;
+	gc->set_rv = adp5585_gpio_set_value;
 	gc->set_config = adp5585_gpio_set_config;
 	gc->can_sleep = true;
 

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:32 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:32 +0100
Subject: [PATCH 07/15] gpio: altera-a10sr: use new line value setter
 callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-7-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-altera-a10sr.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c
index 11edf1fe6c90..77a674cf99e4 100644
--- a/drivers/gpio/gpio-altera-a10sr.c
+++ b/drivers/gpio/gpio-altera-a10sr.c
@@ -35,15 +35,15 @@ static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT));
 }
 
-static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
-				int value)
+static int altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			       int value)
 {
 	struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
 
-	regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
-			   BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
-			   value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset)
-			   : 0);
+	return regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
+				  BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
+				  value ?
+				  BIT(ALTR_A10SR_LED_VALID_SHIFT + offset) : 0);
 }
 
 static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
@@ -69,7 +69,7 @@ static const struct gpio_chip altr_a10sr_gc = {
 	.label = "altr_a10sr_gpio",
 	.owner = THIS_MODULE,
 	.get = altr_a10sr_gpio_get,
-	.set = altr_a10sr_gpio_set,
+	.set_rv = altr_a10sr_gpio_set,
 	.direction_input = altr_a10sr_gpio_direction_input,
 	.direction_output = altr_a10sr_gpio_direction_output,
 	.can_sleep = true,

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:33 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:33 +0100
Subject: [PATCH 08/15] gpio: altera: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-8-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-altera.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 17ab039c7413..1b28525726d7 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -113,7 +113,7 @@ static int altera_gpio_get(struct gpio_chip *gc, unsigned offset)
 	return !!(readl(altera_gc->regs + ALTERA_GPIO_DATA) & BIT(offset));
 }
 
-static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+static int altera_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
 {
 	struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
 	unsigned long flags;
@@ -127,6 +127,8 @@ static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 		data_reg &= ~BIT(offset);
 	writel(data_reg, altera_gc->regs + ALTERA_GPIO_DATA);
 	raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
+
+	return 0;
 }
 
 static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
@@ -257,7 +259,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
 	altera_gc->gc.direction_input	= altera_gpio_direction_input;
 	altera_gc->gc.direction_output	= altera_gpio_direction_output;
 	altera_gc->gc.get		= altera_gpio_get;
-	altera_gc->gc.set		= altera_gpio_set;
+	altera_gc->gc.set_rv		= altera_gpio_set;
 	altera_gc->gc.owner		= THIS_MODULE;
 	altera_gc->gc.parent		= &pdev->dev;
 	altera_gc->gc.base		= -1;

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:34 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:34 +0100
Subject: [PATCH 09/15] gpio: amd8111: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-9-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-amd8111.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c
index 3377667a28de..425d8472f744 100644
--- a/drivers/gpio/gpio-amd8111.c
+++ b/drivers/gpio/gpio-amd8111.c
@@ -94,7 +94,7 @@ static void amd_gpio_free(struct gpio_chip *chip, unsigned offset)
 	iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset));
 }
 
-static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int amd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
 {
 	struct amd_gpio *agp = gpiochip_get_data(chip);
 	u8 temp;
@@ -107,6 +107,8 @@ static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	spin_unlock_irqrestore(&agp->lock, flags);
 
 	dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
+
+	return 0;
 }
 
 static int amd_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -163,7 +165,7 @@ static struct amd_gpio gp = {
 		.ngpio		= 32,
 		.request	= amd_gpio_request,
 		.free		= amd_gpio_free,
-		.set		= amd_gpio_set,
+		.set_rv		= amd_gpio_set,
 		.get		= amd_gpio_get,
 		.direction_output = amd_gpio_dirout,
 		.direction_input = amd_gpio_dirin,

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:35 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:35 +0100
Subject: [PATCH 10/15] gpio: amd-fch: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-10-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-amd-fch.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-amd-fch.c b/drivers/gpio/gpio-amd-fch.c
index 2a21354ed6a0..f8d0cea46049 100644
--- a/drivers/gpio/gpio-amd-fch.c
+++ b/drivers/gpio/gpio-amd-fch.c
@@ -95,8 +95,7 @@ static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
 	return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
 }
 
-static void amd_fch_gpio_set(struct gpio_chip *gc,
-			     unsigned int gpio, int value)
+static int amd_fch_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
 {
 	unsigned long flags;
 	struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
@@ -113,6 +112,8 @@ static void amd_fch_gpio_set(struct gpio_chip *gc,
 	writel_relaxed(mask, ptr);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
 }
 
 static int amd_fch_gpio_get(struct gpio_chip *gc,
@@ -164,7 +165,7 @@ static int amd_fch_gpio_probe(struct platform_device *pdev)
 	priv->gc.direction_output	= amd_fch_gpio_direction_output;
 	priv->gc.get_direction		= amd_fch_gpio_get_direction;
 	priv->gc.get			= amd_fch_gpio_get;
-	priv->gc.set			= amd_fch_gpio_set;
+	priv->gc.set_rv			= amd_fch_gpio_set;
 
 	spin_lock_init(&priv->lock);
 

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:36 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:36 +0100
Subject: [PATCH 11/15] gpio: arizona: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-11-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-arizona.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index c15fda99120a..e530c94dcce8 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -121,7 +121,8 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip,
 				  ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value);
 }
 
-static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int arizona_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			    int value)
 {
 	struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
 	struct arizona *arizona = arizona_gpio->arizona;
@@ -129,8 +130,8 @@ static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	if (value)
 		value = ARIZONA_GPN_LVL;
 
-	regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
-			   ARIZONA_GPN_LVL, value);
+	return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
+				  ARIZONA_GPN_LVL, value);
 }
 
 static const struct gpio_chip template_chip = {
@@ -139,7 +140,7 @@ static const struct gpio_chip template_chip = {
 	.direction_input	= arizona_gpio_direction_in,
 	.get			= arizona_gpio_get,
 	.direction_output	= arizona_gpio_direction_out,
-	.set			= arizona_gpio_set,
+	.set_rv			= arizona_gpio_set,
 	.can_sleep		= true,
 };
 

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:37 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:37 +0100
Subject: [PATCH 12/15] gpio: aspeed: use lock guards
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-12-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reduce the code complexity by using automatic lock guards with the raw
spinlock.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-aspeed.c | 101 +++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 63 deletions(-)

diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 40c1bd80f8b0..e2535aad1026 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -5,6 +5,7 @@
  * Joel Stanley <joel at jms.id.au>
  */
 
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/gpio/aspeed.h>
 #include <linux/gpio/driver.h>
@@ -427,37 +428,33 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
 			    int val)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 	bool copro = false;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
+
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	__aspeed_gpio_set(gc, offset, val);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 	bool copro = false;
 
 	if (!have_input(gpio, offset))
 		return -ENOTSUPP;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	copro = aspeed_gpio_copro_request(gpio, offset);
 	gpio->config->llops->reg_bit_set(gpio, offset, reg_dir, 0);
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
 
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return 0;
 }
 
@@ -465,13 +462,12 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
 			       unsigned int offset, int val)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 	bool copro = false;
 
 	if (!have_output(gpio, offset))
 		return -ENOTSUPP;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	copro = aspeed_gpio_copro_request(gpio, offset);
 	__aspeed_gpio_set(gc, offset, val);
@@ -479,7 +475,6 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
 }
@@ -487,7 +482,6 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
 static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
 	u32 val;
 
 	if (!have_input(gpio, offset))
@@ -496,12 +490,10 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 	if (!have_output(gpio, offset))
 		return GPIO_LINE_DIRECTION_IN;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	val = gpio->config->llops->reg_bit_get(gpio, offset, reg_dir);
 
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return val ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
 }
 
@@ -527,7 +519,6 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
 static void aspeed_gpio_irq_ack(struct irq_data *d)
 {
 	struct aspeed_gpio *gpio;
-	unsigned long flags;
 	int rc, offset;
 	bool copro = false;
 
@@ -535,20 +526,19 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)
 	if (rc)
 		return;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
+
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_status, 1);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
 {
 	struct aspeed_gpio *gpio;
-	unsigned long flags;
 	int rc, offset;
 	bool copro = false;
 
@@ -560,14 +550,14 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
 	if (set)
 		gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d));
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
+
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_enable, set);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	/* Masking the IRQ */
 	if (!set)
@@ -591,7 +581,6 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
 	u32 type2 = 0;
 	irq_flow_handler_t handler;
 	struct aspeed_gpio *gpio;
-	unsigned long flags;
 	int rc, offset;
 	bool copro = false;
 
@@ -620,16 +609,19 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
-	copro = aspeed_gpio_copro_request(gpio, offset);
+	scoped_guard(raw_spinlock_irqsave, &gpio->lock) {
+		copro = aspeed_gpio_copro_request(gpio, offset);
 
-	gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type0, type0);
-	gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type1, type1);
-	gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type2, type2);
+		gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type0,
+						 type0);
+		gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type1,
+						 type1);
+		gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type2,
+						 type2);
 
-	if (copro)
-		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
+		if (copro)
+			aspeed_gpio_copro_release(gpio, offset);
+	}
 
 	irq_set_handler_locked(d, handler);
 
@@ -686,17 +678,16 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
 					unsigned int offset, bool enable)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
-	unsigned long flags;
 	bool copro = false;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
+
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	gpio->config->llops->reg_bit_set(gpio, offset, reg_tolerance, enable);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
 }
@@ -798,7 +789,6 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
 	u32 requested_cycles;
-	unsigned long flags;
 	int rc;
 	int i;
 
@@ -812,12 +802,12 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
 		return rc;
 	}
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	if (timer_allocation_registered(gpio, offset)) {
 		rc = unregister_allocated_timer(gpio, offset);
 		if (rc < 0)
-			goto out;
+			return rc;
 	}
 
 	/* Try to find a timer already configured for the debounce period */
@@ -855,7 +845,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
 			 * consistency.
 			 */
 			configure_timer(gpio, offset, 0);
-			goto out;
+			return rc;
 		}
 
 		i = j;
@@ -863,34 +853,26 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
 		iowrite32(requested_cycles, gpio->base + gpio->config->debounce_timers_array[i]);
 	}
 
-	if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
-		rc = -EINVAL;
-		goto out;
-	}
+	if (WARN(i == 0, "Cannot register index of disabled timer\n"))
+		return -EINVAL;
 
 	register_allocated_timer(gpio, offset, i);
 	configure_timer(gpio, offset, i);
 
-out:
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return rc;
 }
 
 static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
-	unsigned long flags;
 	int rc;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	rc = unregister_allocated_timer(gpio, offset);
 	if (!rc)
 		configure_timer(gpio, offset, 0);
 
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-
 	return rc;
 }
 
@@ -961,7 +943,6 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
 	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
 	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
 	const struct aspeed_gpio_bank *bank = to_bank(offset);
-	unsigned long flags;
 
 	if (!aspeed_gpio_support_copro(gpio))
 		return -EOPNOTSUPP;
@@ -974,13 +955,12 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
 		return -EINVAL;
 	bindex = offset >> 3;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	/* Sanity check, this shouldn't happen */
-	if (gpio->cf_copro_bankmap[bindex] == 0xff) {
-		rc = -EIO;
-		goto bail;
-	}
+	if (gpio->cf_copro_bankmap[bindex] == 0xff)
+		return -EIO;
+
 	gpio->cf_copro_bankmap[bindex]++;
 
 	/* Switch command source */
@@ -994,8 +974,6 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
 		*dreg_offset = bank->rdata_reg;
 	if (bit)
 		*bit = GPIO_OFFSET(offset);
- bail:
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio);
@@ -1009,7 +987,6 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
 	struct gpio_chip *chip = gpiod_to_chip(desc);
 	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
 	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
-	unsigned long flags;
 
 	if (!aspeed_gpio_support_copro(gpio))
 		return -EOPNOTSUPP;
@@ -1021,21 +998,19 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
 		return -EINVAL;
 	bindex = offset >> 3;
 
-	raw_spin_lock_irqsave(&gpio->lock, flags);
+	guard(raw_spinlock_irqsave)(&gpio->lock);
 
 	/* Sanity check, this shouldn't happen */
-	if (gpio->cf_copro_bankmap[bindex] == 0) {
-		rc = -EIO;
-		goto bail;
-	}
+	if (gpio->cf_copro_bankmap[bindex] == 0)
+		return -EIO;
+
 	gpio->cf_copro_bankmap[bindex]--;
 
 	/* Switch command source */
 	if (gpio->cf_copro_bankmap[bindex] == 0)
 		aspeed_gpio_change_cmd_source(gpio, offset,
 					      GPIO_CMDSRC_ARM);
- bail:
-	raw_spin_unlock_irqrestore(&gpio->lock, flags);
+
 	return rc;
 }
 EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);

-- 
2.45.2



From brgl at bgdev.pl  Mon Mar  3 05:18:38 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Mon, 03 Mar 2025 14:18:38 +0100
Subject: [PATCH 13/15] gpio: aspeed: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
Message-ID: <20250303-gpiochip-set-conversion-v1-13-1d5cceeebf8b@linaro.org>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

struct gpio_chip now has callbacks for setting line values that return
an integer, allowing to indicate failures. Convert the driver to using
them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 drivers/gpio/gpio-aspeed.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index e2535aad1026..2d340a343a17 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -424,8 +424,7 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
 	gpio->config->llops->reg_bit_get(gpio, offset, reg_val);
 }
 
-static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
-			    int val)
+static int aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
 	bool copro = false;
@@ -438,6 +437,8 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
+
+	return 0;
 }
 
 static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@@ -1351,7 +1352,7 @@ static int aspeed_gpio_probe(struct platform_device *pdev)
 	gpio->chip.request = aspeed_gpio_request;
 	gpio->chip.free = aspeed_gpio_free;
 	gpio->chip.get = aspeed_gpio_get;
-	gpio->chip.set = aspeed_gpio_set;
+	gpio->chip.set_rv = aspeed_gpio_set;
 	gpio->chip.set_config = aspeed_gpio_set_config;
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;

-- 
2.45.2



From robin.murphy at arm.com  Mon Mar  3 06:16:15 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 3 Mar 2025 14:16:15 +0000
Subject: [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA
 to shared buffers
In-Reply-To: <20250227144150.1667735-4-suzuki.poulose@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
 <20250227144150.1667735-4-suzuki.poulose@arm.com>
Message-ID: <79b28d96-2a56-45b9-a5ae-5c120fe35a35@arm.com>

On 27/02/2025 2:41 pm, Suzuki K Poulose wrote:
> When a device performs DMA to a shared buffer using physical addresses,
> (without Stage1 translation), the device must use the "{I}PA address" with the
> top bit set in Realm. This is to make sure that a trusted device will be able
> to write to shared buffers as well as the protected buffers. Thus, a Realm must
> always program the full address including the "protection" bit, like AMD SME
> encryption bits.
> 
> Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
> helpers for Realms. Please note that the VMM needs to similarly make sure that
> the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
> unprotected alias.

FWIW,

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

> Cc: Will Deacon <will at kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Robin Murphy <robin.murphy at arm.com>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Christoph Hellwig <hch at lst.de>
> Cc: Marek Szyprowski <m.szyprowski at samsung.com>
> Cc: Tom Lendacky <thomas.lendacky at amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar at kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
> Changes since v2:
>   - Drop dma_addr_encrypted() helper, which is a NOP for CCA ( Aneesh )
>   - Only mask the "top" IPA bit and not all the bits beyond top bit. ( Robin )
>   - Use PROT_NS_SHARED, now that we only set/clear top bit. (Gavin)
> ---
>   arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h
> index f8f78f622dd2..a2a1eeb36d4b 100644
> --- a/arch/arm64/include/asm/mem_encrypt.h
> +++ b/arch/arm64/include/asm/mem_encrypt.h
> @@ -21,4 +21,15 @@ static inline bool force_dma_unencrypted(struct device *dev)
>   	return is_realm_world();
>   }
>   
> +/*
> + * For Arm CCA guests, canonical addresses are "encrypted", so no changes
> + * required for dma_addr_encrypted().
> + * The unencrypted DMA buffers must be accessed via the unprotected IPA,
> + * "top IPA bit" set.
> + */
> +#define dma_addr_unencrypted(x)		((x) | PROT_NS_SHARED)
> +
> +/* Clear the "top" IPA bit while converting back */
> +#define dma_addr_canonical(x)		((x) & ~PROT_NS_SHARED)
> +
>   #endif	/* __ASM_MEM_ENCRYPT_H */


From mark.rutland at arm.com  Mon Mar  3 06:18:05 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 3 Mar 2025 14:18:05 +0000
Subject: [PATCH v4] firmware: smccc: Support optional Arm SMC SOC_ID name
In-Reply-To: <20250219005932.3466-1-paul@os.amperecomputing.com>
References: <20241114030452.10149-1-paul@os.amperecomputing.com>
 <20250219005932.3466-1-paul@os.amperecomputing.com>
Message-ID: <Z8W6HXZy46K7ebWe@J2N7QTR9R3.cambridge.arm.com>

Hi Paul,

This looks generally good with a couple of minor nits.

On Tue, Feb 18, 2025 at 04:59:32PM -0800, Paul Benoit wrote:
> Issue Number 1.6 of the Arm SMC Calling Convention introduces an optional
> SOC_ID name string.  If implemented, point the 'machine' field of the SoC
> Device Attributes at this string so that it will appear under
> /sys/bus/soc/devices/soc0/machine.
> 
> On Arm SMC compliant SoCs, this will allow things like 'lscpu' to
> eventually get a SoC provider model name from there rather than each
> tool/utility needing to get a possibly inconsistent, obsolete, or incorrect
> model/machine name from its own hardcoded model/machine name table.
> 
> Signed-off-by: Paul Benoit <paul at os.amperecomputing.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Lorenzo Pieralisi <lpieralisi at kernel.org>
> Cc: Sudeep Holla <sudeep.holla at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> 
> v3->v4: Address code review identified issues of v3.
> v2->v3: Add conditionalization to exclude SOC_ID Name from 32-bit builds.
> v1->v2: Address code review identified issues.
> 
>  drivers/firmware/smccc/soc_id.c | 81 +++++++++++++++++++++++++++++++++
>  include/linux/arm-smccc.h       | 40 ++++++++++++++++
>  2 files changed, 121 insertions(+)
> 
> diff --git a/drivers/firmware/smccc/soc_id.c b/drivers/firmware/smccc/soc_id.c
> index 1990263fbba0..7b0688d78dab 100644
> --- a/drivers/firmware/smccc/soc_id.c
> +++ b/drivers/firmware/smccc/soc_id.c
> @@ -32,6 +32,86 @@
>  static struct soc_device *soc_dev;
>  static struct soc_device_attribute *soc_dev_attr;
>  
> +#ifdef CONFIG_ARM64
> +
> +static char __ro_after_init smccc_soc_id_name[136] = "";
> +
> +static inline void str_fragment_from_reg(char *dst, unsigned long reg)
> +{
> +	dst[0] = (reg >> 0)  & 0xff;
> +	dst[1] = (reg >> 8)  & 0xff;
> +	dst[2] = (reg >> 16) & 0xff;
> +	dst[3] = (reg >> 24) & 0xff;
> +	dst[4] = (reg >> 32) & 0xff;
> +	dst[5] = (reg >> 40) & 0xff;
> +	dst[6] = (reg >> 48) & 0xff;
> +	dst[7] = (reg >> 56) & 0xff;
> +}
> +
> +static char __init *smccc_soc_name_init(void)
> +{
> +	struct arm_smccc_1_2_regs args;
> +	struct arm_smccc_1_2_regs res;
> +	size_t len;
> +
> +	/*
> +	 * Issue Number 1.6 of the Arm SMC Calling Convention
> +	 * specification introduces an optional "name" string
> +	 * to the ARM_SMCCC_ARCH_SOC_ID function.  Fetch it if
> +	 * available.
> +	 */
> +	args.a0 = ARM_SMCCC_ARCH_SOC_ID;
> +	args.a1 = 2;    /* SOC_ID name */
> +	arm_smccc_1_2_invoke(&args, &res);
> +	if ((u32)res.a0 == 0) {
> +		const unsigned int regsize = sizeof(res.a1);
> +
> +		/*
> +		 * Copy res.a1..res.a17 to the smccc_soc_id_name string
> +		 * 8 bytes at a time.  As per Issue 1.6 of the Arm SMC
> +		 * Calling Convention, the string will be NUL terminated
> +		 * and padded, from the end of the string to the end of the
> +		 * 136 byte buffer, with NULs.
> +		 */
> +		str_fragment_from_reg(smccc_soc_id_name + 0*regsize, res.a1);
> +		str_fragment_from_reg(smccc_soc_id_name + 1*regsize, res.a2);
> +		str_fragment_from_reg(smccc_soc_id_name + 2*regsize, res.a3);
> +		str_fragment_from_reg(smccc_soc_id_name + 3*regsize, res.a4);
> +		str_fragment_from_reg(smccc_soc_id_name + 4*regsize, res.a5);
> +		str_fragment_from_reg(smccc_soc_id_name + 5*regsize, res.a6);
> +		str_fragment_from_reg(smccc_soc_id_name + 6*regsize, res.a7);
> +		str_fragment_from_reg(smccc_soc_id_name + 7*regsize, res.a8);
> +		str_fragment_from_reg(smccc_soc_id_name + 8*regsize, res.a9);
> +		str_fragment_from_reg(smccc_soc_id_name + 9*regsize, res.a10);
> +		str_fragment_from_reg(smccc_soc_id_name + 10*regsize, res.a11);
> +		str_fragment_from_reg(smccc_soc_id_name + 11*regsize, res.a12);
> +		str_fragment_from_reg(smccc_soc_id_name + 12*regsize, res.a13);
> +		str_fragment_from_reg(smccc_soc_id_name + 13*regsize, res.a14);
> +		str_fragment_from_reg(smccc_soc_id_name + 14*regsize, res.a15);
> +		str_fragment_from_reg(smccc_soc_id_name + 15*regsize, res.a16);
> +		str_fragment_from_reg(smccc_soc_id_name + 16*regsize, res.a17);

Please get rid of 'regsize' and use '8' directly. This only exists for
arm64, where the registeres are 8 bytes, and the comment immediately
above refers to "8 bytes" specifically anyway, so 'regsize' only serves
to make this harder to read.

It'd be a bit clearer as:

	str_fragment_from_reg(smccc_soc_id_name + 8 * 0,  res.a1);
	str_fragment_from_reg(smccc_soc_id_name + 8 * 1,  res.a2);
	...
	str_fragment_from_reg(smccc_soc_id_name + 8 * 15, res.a16);
	str_fragment_from_reg(smccc_soc_id_name + 8 * 16, res.a17);

Sudeep, are you happy to fix that up when applying?

> +
> +		len = strnlen(smccc_soc_id_name, sizeof(smccc_soc_id_name));
> +		if (len) {
> +			if (len == sizeof(smccc_soc_id_name))
> +				pr_warn(FW_BUG "Ignoring improperly formatted Name\n");

It's odd that 'Name' is capitalized here. Not a big deal, but it doesn't
look quite right.

> +			else
> +				return smccc_soc_id_name;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +#else
> +
> +static char __init *smccc_soc_name_init(void)
> +{
> +	return NULL;
> +}
> +
> +#endif
> +
>  static int __init smccc_soc_init(void)
>  {
>  	int soc_id_rev, soc_id_version;
> @@ -72,6 +152,7 @@ static int __init smccc_soc_init(void)
>  	soc_dev_attr->soc_id = soc_id_str;
>  	soc_dev_attr->revision = soc_id_rev_str;
>  	soc_dev_attr->family = soc_id_jep106_id_str;
> +	soc_dev_attr->machine = smccc_soc_name_init();
>  
>  	soc_dev = soc_device_register(soc_dev_attr);
>  	if (IS_ERR(soc_dev)) {
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 67f6fdf2e7cd..eb7eab04755a 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -639,5 +639,45 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>  		method;							\
>  	})
>  
> +#ifdef CONFIG_ARM64
> +
> +#define __fail_smccc_1_2(___res)					\
> +	do {								\
> +		if (___res)						\
> +			___res->a0 = SMCCC_RET_NOT_SUPPORTED;		\
> +	} while (0)
> +
> +/*
> + * arm_smccc_1_2_invoke() - make an SMCCC v1.2 compliant call
> + *
> + * @args: SMC args are in the a0..a17 fields of the arm_smcc_1_2_regs structure
> + * @res: result values from registers 0 to 17
> + *
> + * This macro will make either an HVC call or an SMC call depending on the
> + * current SMCCC conduit. If no valid conduit is available then -1
> + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
> + *
> + * The return value also provides the conduit that was used.
> + */
> +#define arm_smccc_1_2_invoke(args, res) ({				\
> +		struct arm_smccc_1_2_regs *__args = args;		\
> +		struct arm_smccc_1_2_regs *__res = res;			\
> +		int method = arm_smccc_1_1_get_conduit();		\
> +		switch (method) {					\
> +		case SMCCC_CONDUIT_HVC:					\
> +			arm_smccc_1_2_hvc(__args, __res);		\
> +			break;						\
> +		case SMCCC_CONDUIT_SMC:					\
> +			arm_smccc_1_2_smc(__args, __res);		\
> +			break;						\
> +		default:						\
> +			__fail_smccc_1_2(__res);			\
> +			method = SMCCC_CONDUIT_NONE;			\
> +			break;						\
> +		}							\
> +		method;							\
> +	})
> +#endif /*CONFIG_ARM64*/

At some point I intend to rework the existing helpers to not return the
conduit, but this is fine for now.

With the fixups above:

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> +
>  #endif /*__ASSEMBLY__*/
>  #endif /*__LINUX_ARM_SMCCC_H*/
> -- 
> 2.48.1
> 


From robh at kernel.org  Mon Mar  3 06:26:07 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 3 Mar 2025 08:26:07 -0600
Subject: [PATCH v3 4/6] dt-bindings: thermal: rockchip: document otp
 thermal trim
In-Reply-To: <20250228-rk3576-tsadc-upstream-v3-4-4bfbb3b699b9@collabora.com>
References: <20250228-rk3576-tsadc-upstream-v3-0-4bfbb3b699b9@collabora.com>
 <20250228-rk3576-tsadc-upstream-v3-4-4bfbb3b699b9@collabora.com>
Message-ID: <174101196712.1786336.17880487519994518563.robh@kernel.org>


On Fri, 28 Feb 2025 21:06:54 +0100, Nicolas Frattaroli wrote:
> Several Rockchip SoCs, such as the RK3576, can store calibration trim
> data for thermal sensors in OTP cells. This capability should be
> documented.
> 
> Such a rockchip thermal sensor may reference cell handles that store
> both a chip-wide trim for all the sensors, as well as cell handles
> for each individual sensor channel pointing to that specific sensor's
> trim value.
> 
> Additionally, the thermal sensor may optionally reference cells which
> store the base in terms of degrees celsius and decicelsius that the trim
> is relative to.
> 
> Each SoC that implements this appears to have a slightly different
> combination of chip-wide trim, base, base fractional part and
> per-channel trim, so which ones do which is documented in the bindings.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
>  .../bindings/thermal/rockchip-thermal.yaml         | 61 ++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From sudeep.holla at arm.com  Mon Mar  3 06:45:28 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 3 Mar 2025 14:45:28 +0000
Subject: [PATCH v4] firmware: smccc: Support optional Arm SMC SOC_ID name
In-Reply-To: <Z8W6HXZy46K7ebWe@J2N7QTR9R3.cambridge.arm.com>
References: <20241114030452.10149-1-paul@os.amperecomputing.com>
 <20250219005932.3466-1-paul@os.amperecomputing.com>
 <Z8W6HXZy46K7ebWe@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <Z8XAiMSoaOmR5JxY@bogus>

On Mon, Mar 03, 2025 at 02:18:05PM +0000, Mark Rutland wrote:
> Hi Paul,
>
> This looks generally good with a couple of minor nits.
>
> On Tue, Feb 18, 2025 at 04:59:32PM -0800, Paul Benoit wrote:
> > Issue Number 1.6 of the Arm SMC Calling Convention introduces an optional
> > SOC_ID name string.  If implemented, point the 'machine' field of the SoC
> > Device Attributes at this string so that it will appear under
> > /sys/bus/soc/devices/soc0/machine.
> >
> > On Arm SMC compliant SoCs, this will allow things like 'lscpu' to
> > eventually get a SoC provider model name from there rather than each
> > tool/utility needing to get a possibly inconsistent, obsolete, or incorrect
> > model/machine name from its own hardcoded model/machine name table.
> >
> > Signed-off-by: Paul Benoit <paul at os.amperecomputing.com>
> > Cc: Mark Rutland <mark.rutland at arm.com>
> > Cc: Lorenzo Pieralisi <lpieralisi at kernel.org>
> > Cc: Sudeep Holla <sudeep.holla at arm.com>
> > Cc: linux-arm-kernel at lists.infradead.org
> > ---

[...]

> > +static char __init *smccc_soc_name_init(void)
> > +{
> > +	struct arm_smccc_1_2_regs args;
> > +	struct arm_smccc_1_2_regs res;
> > +	size_t len;
> > +
> > +	/*
> > +	 * Issue Number 1.6 of the Arm SMC Calling Convention
> > +	 * specification introduces an optional "name" string
> > +	 * to the ARM_SMCCC_ARCH_SOC_ID function.  Fetch it if
> > +	 * available.
> > +	 */
> > +	args.a0 = ARM_SMCCC_ARCH_SOC_ID;
> > +	args.a1 = 2;    /* SOC_ID name */
> > +	arm_smccc_1_2_invoke(&args, &res);
> > +	if ((u32)res.a0 == 0) {
> > +		const unsigned int regsize = sizeof(res.a1);
> > +
> > +		/*
> > +		 * Copy res.a1..res.a17 to the smccc_soc_id_name string
> > +		 * 8 bytes at a time.  As per Issue 1.6 of the Arm SMC
> > +		 * Calling Convention, the string will be NUL terminated
> > +		 * and padded, from the end of the string to the end of the
> > +		 * 136 byte buffer, with NULs.
> > +		 */
> > +		str_fragment_from_reg(smccc_soc_id_name + 0*regsize, res.a1);
> > +		str_fragment_from_reg(smccc_soc_id_name + 1*regsize, res.a2);
> > +		str_fragment_from_reg(smccc_soc_id_name + 2*regsize, res.a3);
> > +		str_fragment_from_reg(smccc_soc_id_name + 3*regsize, res.a4);
> > +		str_fragment_from_reg(smccc_soc_id_name + 4*regsize, res.a5);
> > +		str_fragment_from_reg(smccc_soc_id_name + 5*regsize, res.a6);
> > +		str_fragment_from_reg(smccc_soc_id_name + 6*regsize, res.a7);
> > +		str_fragment_from_reg(smccc_soc_id_name + 7*regsize, res.a8);
> > +		str_fragment_from_reg(smccc_soc_id_name + 8*regsize, res.a9);
> > +		str_fragment_from_reg(smccc_soc_id_name + 9*regsize, res.a10);
> > +		str_fragment_from_reg(smccc_soc_id_name + 10*regsize, res.a11);
> > +		str_fragment_from_reg(smccc_soc_id_name + 11*regsize, res.a12);
> > +		str_fragment_from_reg(smccc_soc_id_name + 12*regsize, res.a13);
> > +		str_fragment_from_reg(smccc_soc_id_name + 13*regsize, res.a14);
> > +		str_fragment_from_reg(smccc_soc_id_name + 14*regsize, res.a15);
> > +		str_fragment_from_reg(smccc_soc_id_name + 15*regsize, res.a16);
> > +		str_fragment_from_reg(smccc_soc_id_name + 16*regsize, res.a17);
> 
> Please get rid of 'regsize' and use '8' directly. This only exists for
> arm64, where the registeres are 8 bytes, and the comment immediately
> above refers to "8 bytes" specifically anyway, so 'regsize' only serves
> to make this harder to read.
> 
> It'd be a bit clearer as:
> 
> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 0,  res.a1);
> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 1,  res.a2);
> 	...
> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 15, res.a16);
> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 16, res.a17);
> 
> Sudeep, are you happy to fix that up when applying?
> 
> > +
> > +		len = strnlen(smccc_soc_id_name, sizeof(smccc_soc_id_name));
> > +		if (len) {
> > +			if (len == sizeof(smccc_soc_id_name))
> > +				pr_warn(FW_BUG "Ignoring improperly formatted Name\n");
> 
> It's odd that 'Name' is capitalized here. Not a big deal, but it doesn't
> look quite right.
>

I can fix both of these and apply. No need to repost.

-- 
Regards,
Sudeep


From nfraprado at collabora.com  Mon Mar  3 06:45:47 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Mon, 3 Mar 2025 11:45:47 -0300
Subject: [PATCH v2 01/20] ASoC: dt-bindings: Add document for
 mt6359-accdet
In-Reply-To: <628a81c5-b9f1-4be9-84ec-90022a3526da@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
 <628a81c5-b9f1-4be9-84ec-90022a3526da@collabora.com>
Message-ID: <0120fe30-43c4-4fec-8b5e-fdb6b382fc2a@notapiano>

On Mon, Mar 03, 2025 at 12:14:51PM +0100, AngeloGioacchino Del Regno wrote:
> Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
> > Add dt-binding for the MT6359 ACCDET hardware block.
> > 
> > Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> > ---
> >   .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
> >   1 file changed, 42 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..d08a79301409374714c76135b061e20e8e8acfaf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> > @@ -0,0 +1,42 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: MT6359 Accessory Detection
> > +
> > +maintainers:
> > +  - N?colas F. R. A. Prado <nfraprado at collabora.com>
> > +
> > +description: |
> > +  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
> > +  detecting audio jack insertion and removal, as well as identifying the type of
> > +  events connected to the jack.
> > +
> > +properties:
> > +  compatible:
> > +    const: mediatek,mt6359-accdet
> > +
> > +  mediatek,hp-eint-high:
> > +    type: boolean
> > +    description:
> > +      By default, the HP_EINT pin is assumed to be pulled high and connected to
> 
> Just to be clearer about this pin being an internal one and not externally sourced,
> so, *not* a SoC GPIO, but somehing that is completely provided and handled by the
> accdet IP...
> 
> "By default, the accdet IP's internal HP_EINT pin is assumed to be pulled ..."

The HP_EINT is an external, not internal, pin of the MT6359 PMIC. It is an input
pin of the MT6359 IC that gets wired to the tip (left channel) of a 3.5mm audio
jack to allow for detecting when a plug is connected.

Since this dt-binding is about an IP in the MT6359 PMIC, I think when saying
"HP_EINT pin" it is already clear that the pin is on the MT6359 IC, but if you
think it's necessary I could make it "MT6359's HP_EINT pin".

Thanks,
N?colas


From yangyicong at huawei.com  Mon Mar  3 06:40:49 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:40:49 +0800
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <Z8WPiOweOjFZqTwN@bogus>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com> <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com> <Z8WPiOweOjFZqTwN@bogus>
Message-ID: <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>

On 2025/3/3 19:16, Sudeep Holla wrote:
> On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
>> On 2/28/25 20:06, Sudeep Holla wrote:
>>>>>
>>>>> Ditto as previous patch, can get rid if it is default 1.
>>>>>
>>>>
>>>> On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
>>>> cpu_smt_num_threads uninitialized to UINT_MAX:
>>>>
>>>> smt/active:0
>>>> smt/control:-1
>>>>
>>>> If cpu_smt_set_num_threads() is called:
>>>> active:0
>>>> control:notsupported
>>>>
>>>> So it might be slightly better to still initialize max_smt_thread_num.
>>>>
>>>
>>> Sure, what I meant is to have max_smt_thread_num set to 1 by default is
>>> that is what needed anyways and the above code does that now.
>>>
>>> Why not start with initialised to 1 instead ?
>>> Of course some current logic needs to change around testing it for zero.
>>>
>>
>> I think there would still be a way to check against the default value.
>> If we have:
>> unsigned int max_smt_thread_num = 1;
>>
>> then on a platform with 2 threads, the detection condition would trigger:
>> xa_for_each(&hetero_cpu, hetero_id, entry) {
>>     if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
>>         pr_warn_once("Heterogeneous SMT topology is partly
>>                       supported by SMT control\n");
>>
>> so we would need an additional variable:
>> bool is_initialized = false;
> 
> Sure, we could do that or skip the check if max_smt_thread_num == 1 ?
> 
> I mean
> 	if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)
> 

this will work for me. will launch some tests.

Thanks.




From yangyicong at huawei.com  Mon Mar  3 06:41:40 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:41:40 +0800
Subject: [PATCH v11 0/4] Support SMT control on arm64
In-Reply-To: <df9784c3-c2ea-4bac-839a-2b7de0a81aac@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <df9784c3-c2ea-4bac-839a-2b7de0a81aac@arm.com>
Message-ID: <6d83cc41-7759-c0a2-6695-01f98923ed5d@huawei.com>

On 2025/2/28 19:12, Dietmar Eggemann wrote:
> On 18/02/2025 15:10, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> The core CPU control framework supports runtime SMT control which
>> is not yet supported on arm64. Besides the general vulnerabilities
>> concerns we want this runtime control on our arm64 server for:
>>
>> - better single CPU performance in some cases
>> - saving overall power consumption
>>
>> This patchset implements it in the following aspects:
>>
>> - Provides a default topology_is_primary_thread()
>> - support retrieve SMT thread number on OF based system
>> - support retrieve SMT thread number on ACPI based system
>> - select HOTPLUG_SMT for arm64
>>
>> Tests has been done on our ACPI based arm64 server and on ACPI/OF
>> based QEMU VMs.
> 
> [...]
> 
>> Yicong Yang (4):
>>   cpu/SMT: Provide a default topology_is_primary_thread()
>>   arch_topology: Support SMT control for OF based system
>>   arm64: topology: Support SMT control on ACPI based system
>>   arm64: Kconfig: Enable HOTPLUG_SMT
>>
>>  arch/arm64/Kconfig                  |  1 +
>>  arch/arm64/kernel/topology.c        | 66 +++++++++++++++++++++++++++++
>>  arch/powerpc/include/asm/topology.h |  1 +
>>  arch/x86/include/asm/topology.h     |  2 +-
>>  drivers/base/arch_topology.c        | 27 ++++++++++++
>>  include/linux/topology.h            | 22 ++++++++++
>>  6 files changed, 118 insertions(+), 1 deletion(-)
> 
> With the review comments on the individual patches [0-3]/4:

will fix.

> 
> Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
> 

Thanks.



From yangyicong at huawei.com  Mon Mar  3 06:42:34 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:42:34 +0800
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <92193a09-271e-895e-f77f-d3952bdfdf49@huawei.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com>
 <92193a09-271e-895e-f77f-d3952bdfdf49@huawei.com>
Message-ID: <5f56d0fc-7ca8-cc52-9747-aec981e42bdc@huawei.com>

On 2025/2/25 14:08, Hanjun Guo wrote:
> On 2025/2/18 22:10, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> For ACPI we'll build the topology from PPTT and we cannot directly
>> get the SMT number of each core. Instead using a temporary xarray
>> to record the heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL)
>> and SMT information of the first core in its heterogeneous CPU cluster
>> when building the topology. Then we can know the largest SMT number
>> in the system. If a homogeneous system's using ACPI 6.2 or later,
>> all the CPUs should be under the root node of PPTT. There'll be
>> only one entry in the xarray and all the CPUs in the system will
>> be assumed identical.
>>
>> The core's SMT control provides two interface to the users [1]:
>> 1) enable/disable SMT by writing on/off
>> 2) enable/disable SMT by writing thread number 1/max_thread_number
>>
>> If a system have more than one SMT thread number the 2) may
>> not handle it well, since there're multiple thread numbers in the
>> system and 2) only accept 1/max_thread_number. So issue a warning
>> to notify the users if such system detected.
>>
>> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
>>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>> ? arch/arm64/kernel/topology.c | 66 ++++++++++++++++++++++++++++++++++++
>> ? 1 file changed, 66 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
>> index 1a2c72f3e7f8..6eba1ac091ee 100644
>> --- a/arch/arm64/kernel/topology.c
>> +++ b/arch/arm64/kernel/topology.c
>> @@ -15,8 +15,10 @@
>> ? #include <linux/arch_topology.h>
>> ? #include <linux/cacheinfo.h>
>> ? #include <linux/cpufreq.h>
>> +#include <linux/cpu_smt.h>
>> ? #include <linux/init.h>
>> ? #include <linux/percpu.h>
>> +#include <linux/xarray.h>
>> ? ? #include <asm/cpu.h>
>> ? #include <asm/cputype.h>
>> @@ -37,17 +39,28 @@ static bool __init acpi_cpu_is_threaded(int cpu)
>> ????? return !!is_threaded;
>> ? }
>> ? +struct cpu_smt_info {
>> +??? unsigned int thread_num;
>> +??? int core_id;
>> +};
>> +
>> ? /*
>> ?? * Propagate the topology information of the processor_topology_node tree to the
>> ?? * cpu_topology array.
>> ?? */
>> ? int __init parse_acpi_topology(void)
>> ? {
>> +??? unsigned int max_smt_thread_num = 0;
>> +??? struct cpu_smt_info *entry;
>> +??? struct xarray hetero_cpu;
>> +??? unsigned long hetero_id;
>> ????? int cpu, topology_id;
>> ? ????? if (acpi_disabled)
>> ????????? return 0;
>> ? +??? xa_init(&hetero_cpu);
>> +
>> ????? for_each_possible_cpu(cpu) {
>> ????????? topology_id = find_acpi_cpu_topology(cpu, 0);
>> ????????? if (topology_id < 0)
>> @@ -57,6 +70,34 @@ int __init parse_acpi_topology(void)
>> ????????????? cpu_topology[cpu].thread_id = topology_id;
>> ????????????? topology_id = find_acpi_cpu_topology(cpu, 1);
>> ????????????? cpu_topology[cpu].core_id?? = topology_id;
>> +
>> +??????????? /*
>> +???????????? * In the PPTT, CPUs below a node with the 'identical
>> +???????????? * implementation' flag have the same number of threads.
>> +???????????? * Count the number of threads for only one CPU (i.e.
>> +???????????? * one core_id) among those with the same hetero_id.
>> +???????????? * See the comment of find_acpi_cpu_topology_hetero_id()
>> +???????????? * for more details.
>> +???????????? *
>> +???????????? * One entry is created for each node having:
>> +???????????? * - the 'identical implementation' flag
>> +???????????? * - its parent not having the flag
>> +???????????? */
>> +??????????? hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
>> +??????????? entry = xa_load(&hetero_cpu, hetero_id);
>> +??????????? if (!entry) {
>> +??????????????? entry = kzalloc(sizeof(*entry), GFP_KERNEL);
>> +??????????????? WARN_ON_ONCE(!entry);
>> +
>> +??????????????? if (entry) {
>> +??????????????????? entry->core_id = topology_id;
>> +??????????????????? entry->thread_num = 1;
>> +??????????????????? xa_store(&hetero_cpu, hetero_id,
>> +???????????????????????? entry, GFP_KERNEL);
>> +??????????????? }
>> +??????????? } else if (entry->core_id == topology_id) {
>> +??????????????? entry->thread_num++;
>> +??????????? }
>> ????????? } else {
>> ????????????? cpu_topology[cpu].thread_id? = -1;
>> ????????????? cpu_topology[cpu].core_id??? = topology_id;
>> @@ -67,6 +108,31 @@ int __init parse_acpi_topology(void)
>> ????????? cpu_topology[cpu].package_id = topology_id;
>> ????? }
>> ? +??? /*
>> +???? * This should be a short loop depending on the number of heterogeneous
>> +???? * CPU clusters. Typically on a homogeneous system there's only one
>> +???? * entry in the XArray.
>> +???? */
>> +??? xa_for_each(&hetero_cpu, hetero_id, entry) {
>> +??????? if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)
>> +??????????? pr_warn_once("Heterogeneous SMT topology is partly supported by SMT control\n");
>> +
>> +??????? max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
>> +??????? xa_erase(&hetero_cpu, hetero_id);
>> +??????? kfree(entry);
>> +??? }
>> +
>> +??? /*
>> +???? * Notify the CPU framework of the SMT support. Initialize the
>> +???? * max_smt_thread_num to 1 if no SMT support detected. A thread
>> +???? * number of 1 can be handled by the framework so we don't need
>> +???? * to check max_smt_thread_num to see we support SMT or not.
>> +???? */
>> +??? if (!max_smt_thread_num)
>> +??????? max_smt_thread_num = 1;
>> +
>> +??? cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
>> +??? xa_destroy(&hetero_cpu);
>> ????? return 0;
>> ? }
>> ? #endif
> 
> Looks good to me,
> 
> Reviewed-by: Hanjun Guo <guohanjun at huawei.com>
> 

Thanks a lot for taking a look :)




From yangyicong at huawei.com  Mon Mar  3 06:43:35 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 3 Mar 2025 22:43:35 +0800
Subject: [PATCH 1/9] drivers/perf: hisi: Extend struct hisi_pmu_dev_info
In-Reply-To: <20250301062343.GA27700@willie-the-truck>
References: <20250218092000.41641-1-yangyicong@huawei.com>
 <20250218092000.41641-2-yangyicong@huawei.com>
 <20250301062343.GA27700@willie-the-truck>
Message-ID: <e6cfcfd0-5412-20bb-f4b5-cf266884c5d0@huawei.com>

On 2025/3/1 14:23, Will Deacon wrote:
> On Tue, Feb 18, 2025 at 05:19:52PM +0800, Yicong Yang wrote:
>> From: Junhao He <hejunhao3 at huawei.com>
>>
>> The counter bits and event range may differ from versions of a
>> certain uncore PMU. Make this device specific information into
>> struct hisi_pmu_dev_info. This will help to simplify the
>> initialization process by using a list of struct hisi_pmu_dev_info
>> rather than checking the version.
>>
>> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>>  drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> index f4fed2544877..777675838b80 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> @@ -72,6 +72,8 @@ struct hisi_uncore_ops {
>>  struct hisi_pmu_dev_info {
>>  	const char *name;
>>  	const struct attribute_group **attr_groups;
>> +	u32 counter_bits;
>> +	u32 check_event;
>>  	void *private;
>>  };
> 
> This doesn't really do anything on its own; please just fold it into the
> patch where the new fields are used.
> 

sure, will make this into the following patch.

Thanks.



From antonin.godard at bootlin.com  Mon Mar  3 06:46:52 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 03 Mar 2025 15:46:52 +0100
Subject: [PATCH v2 2/3] ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL
 SoM support
In-Reply-To: <Z7njGg4Hhc4wcZHU@dragon>
References: <20250127-varsom6ul-concerto-dts-v2-0-4dac29256989@bootlin.com>
 <20250127-varsom6ul-concerto-dts-v2-2-4dac29256989@bootlin.com>
 <Z7njGg4Hhc4wcZHU@dragon>
Message-ID: <D86POCANGF07.3HE2LVK396FGX@bootlin.com>

Hi Shawn,

On Sat Feb 22, 2025 at 3:45 PM CET, Shawn Guo wrote:
[...]
>> +	reg_gpio_dvfs: reg-gpio-dvfs {
>> +		compatible = "regulator-gpio";
>> +		regulator-min-microvolt = <1300000>;
>> +		regulator-max-microvolt = <1400000>;
>> +		regulator-name = "gpio_dvfs";
>> +		regulator-type = "voltage";
>> +		gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
>
> Don't we need 'enable-active-high'?

I am not specifying 'enable-gpios' but 'gpios' here so from my understanding of
gpio-regulator.yaml and examples from other device trees I don't think so.

>> +		states = <1300000 0x1 1400000 0x0>;
>> +	};
>> +
>> +	rmii_ref_clk: rmii-ref-clk-grp {
>
> What does "-grp" in node name mean?

A mistake on my side, I will rename the label to "rmii-ref-clk".

>> +		compatible = "fixed-clock";
>> +		clock-output-names = "rmii-ref";
>> +	};
>> +};
>> +
>> +&cpu0 {
>> +	dc-supply = <&reg_gpio_dvfs>;
>> +};
>> +
>> +&clks {
>> +	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
>> +	assigned-clock-rates = <786432000>;
>> +};
>> +
>> +&fec1 {
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_enet1>, <&pinctrl_enet1_gpio>, <&pinctrl_enet1_mdio>;
>> +	phy-mode = "rmii";
>> +	phy-reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
>> +	phy-reset-duration = <100>;
>> +	phy-handle = <&ethphy0>;
>> +	status = "okay";
>> +
>> +	mdio {
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		ethphy0: ethernet-phy at 1 {
>> +			compatible = "ethernet-phy-ieee802.3-c22";
>> +			micrel,rmii-reference-clock-select-25-mhz = <1>;
>> +			micrel,led-mode = <1>;
>> +			clocks = <&rmii_ref_clk>;
>> +			clock-names = "rmii-ref";
>> +			reg = <1>;
>
> We generally sort properties like:
>
>   - compatible
>   - reg
>   - generic ones
>   - vendor prefixed ones
>
> So in this case, we will get:
>
> 	compatible = "ethernet-phy-ieee802.3-c22";
> 	reg = <1>;
> 	clocks = <&rmii_ref_clk>;
> 	clock-names = "rmii-ref";
> 	micrel,rmii-reference-clock-select-25-mhz = <1>;
> 	micrel,led-mode = <1>;

Thanks for clarifying that! I will revise this for the next version.

Antonin

-- 
Antonin Godard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From hugo at hugovil.com  Mon Mar  3 06:57:17 2025
From: hugo at hugovil.com (Hugo Villeneuve)
Date: Mon, 3 Mar 2025 09:57:17 -0500
Subject: [PATCH v4 07/10] iio: adc: ti-ads7924: Respect device tree
 config
In-Reply-To: <7c79ce3a-0dc4-4aa4-941a-e05be9a34fb8@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<20dd0e4ea72fe39b90b611f9c08dbd4bc1d5217f.1740421248.git.mazziesaccount@gmail.com>
	<f0d0f114-3953-46b5-b9f6-9b35537e6f8e@baylibre.com>
	<d391b012-0a8e-40ca-af56-ca73b3fd853b@gmail.com>
	<20250302032713.1c834448@jic23-huawei>
	<7c79ce3a-0dc4-4aa4-941a-e05be9a34fb8@gmail.com>
Message-ID: <20250303095717.56ef5ac016b99911fc34e198@hugovil.com>

On Sun, 2 Mar 2025 15:10:12 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 02/03/2025 05:27, Jonathan Cameron wrote:
> > On Wed, 26 Feb 2025 08:39:11 +0200
> > Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> > 
> >> On 26/02/2025 02:09, David Lechner wrote:
> >>> On 2/24/25 12:34 PM, Matti Vaittinen wrote:
> >>>> The ti-ads7924 driver ignores the device-tree ADC channel specification
> >>>> and always exposes all 4 channels to users whether they are present in
> >>>> the device-tree or not. Additionally, the "reg" values in the channel
> >>>> nodes are ignored, although an error is printed if they are out of range.
> >>>>
> >>>> Register only the channels described in the device-tree, and use the reg
> >>>> property as a channel ID.
> >>>>
> >>>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>>>
> >>>> ---
> >>>> Revision history:
> >>>> v3 => v4:
> >>>>    - Adapt to 'drop diff-channel support' changes to ADC-helpers
> >>>>    - select ADC helpers in the Kconfig
> >>>> v2 => v3: New patch
> >>>>
> >>>> Please note that this is potentially breaking existing users if they
> >>>> have wrong values in the device-tree. I believe the device-tree should
> >>>> ideally be respected, and if it says device X has only one channel, then
> >>>> we should believe it and not register 4. Well, we don't live in the
> >>>> ideal world, so even though I believe this is TheRightThingToDo - it may
> >>>> cause havoc because correct device-tree has not been required from the
> >>>> day 1. So, please review and test and apply at your own risk :)
> >>>
> >>> The DT bindings on this one are a little weird. Usually, if we don't
> >>> use any extra properties from adc.yaml, we leave out the channels. In
> >>> this case it does seem kind of like the original intention was to work
> >>> like you are suggesting, but hard to say since the driver wasn't actually
> >>> implemented that way. I would be more inclined to actually not make the
> >>> breaking change here and instead relax the bindings to make channel nodes
> >>> optional and just have the driver ignore the channel nodes by dropping
> >>> the ads7924_get_channels_config() function completely. This would make
> >>> the driver simpler instead of more complex like this patch does.
> >>
> >> I have no strong opinion on this. I see this driver says 'Supported' in
> >> MAINTAINERS. Maybe Hugo is able to provide some insight?
> >>
> > This seems to be ABI breakage.  Never something we can take if there is
> > a significant chance of anyone noticing.  Here it looks like risk
> > is too high.
> 
> Ok. I'll just drop this patch then. Thanks David & Jonathan :)

Hi Matti,
I haven't really been able to follow all discussions, but as an
historic note I developped this driver for a prototype that never
materialized. So any changes would not have an impact, as far as I am
concerned.

Hugo.


From robh at kernel.org  Mon Mar  3 07:08:00 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 3 Mar 2025 09:08:00 -0600
Subject: [PATCH 2/8] dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
In-Reply-To: <20250301104250.36295-3-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104250.36295-3-ziyao@disroot.org>
Message-ID: <174101448016.1859733.11356021795380428935.robh@kernel.org>


On Sat, 01 Mar 2025 10:42:44 +0000, Yao Zi wrote:
> Add compatible string for VPU GRF found on RK3528 SoC.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar  3 07:08:15 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 3 Mar 2025 09:08:15 -0600
Subject: [PATCH 3/8] dt-bindings: mmc: rockchip-dw-mshc: Add compatible
 string for RK3528
In-Reply-To: <20250301104250.36295-4-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104250.36295-4-ziyao@disroot.org>
Message-ID: <174101449502.1860172.16789001197573661761.robh@kernel.org>


On Sat, 01 Mar 2025 10:42:45 +0000, Yao Zi wrote:
> Add RK3528 compatible string for SD/SDIO interface.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar  3 07:11:37 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 3 Mar 2025 09:11:37 -0600
Subject: [PATCH v2 01/20] ASoC: dt-bindings: Add document for
 mt6359-accdet
In-Reply-To: <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
Message-ID: <20250303151137.GA1862020-robh@kernel.org>

On Sun, Mar 02, 2025 at 01:30:40PM -0300, N?colas F. R. A. Prado wrote:
> Add dt-binding for the MT6359 ACCDET hardware block.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..d08a79301409374714c76135b061e20e8e8acfaf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> @@ -0,0 +1,42 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MT6359 Accessory Detection
> +
> +maintainers:
> +  - N?colas F. R. A. Prado <nfraprado at collabora.com>
> +
> +description: |

Don't need '|'.

> +  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
> +  detecting audio jack insertion and removal, as well as identifying the type of
> +  events connected to the jack.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt6359-accdet
> +
> +  mediatek,hp-eint-high:
> +    type: boolean
> +    description:
> +      By default, the HP_EINT pin is assumed to be pulled high and connected to
> +      a normally open 3.5mm jack. Plug insertion is detected when the pin is
> +      brought low in that case. Add this property if the behavior should be
> +      inverted, for example if a normally closed 3.5mm jack is used, or if the
> +      line is pulled low on open.
> +
> +required:
> +  - compatible
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    accdet: accdet {
> +        compatible = "mediatek,mt6359-accdet";
> +        mediatek,hp-eint-high;
> +    };
> 
> -- 
> 2.48.1
> 


From liviu.dudau at arm.com  Mon Mar  3 07:04:42 2025
From: liviu.dudau at arm.com (Liviu Dudau)
Date: Mon, 3 Mar 2025 15:04:42 +0000
Subject: [PATCH 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <4a27b6bf-aca8-4f29-9561-609a42eb81a0@denx.de>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-10-marex@denx.de>
 <2153305.bB369e8A3T@steina-w>
 <4a27b6bf-aca8-4f29-9561-609a42eb81a0@denx.de>
Message-ID: <Z8XFCv6ku6mG1_x5@e110455-lin.cambridge.arm.com>

On Fri, Feb 28, 2025 at 06:43:53PM +0100, Marek Vasut wrote:
> On 2/28/25 11:36 AM, Alexander Stein wrote:
> > Hi Marek,
> 
> Hi,
> 
> > > diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
> > > index 3af13173de4bd..36bad211e5558 100644
> > > --- a/arch/arm64/boot/dts/freescale/imx95.dtsi
> > > +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
> > > @@ -249,6 +249,37 @@ dummy: clock-dummy {
> > >   		clock-output-names = "dummy";
> > >   	};
> > > +	gpu_fixed_reg: fixed-gpu-reg {
> > > +		compatible = "regulator-fixed";
> > > +		regulator-min-microvolt = <920000>;
> > > +		regulator-max-microvolt = <920000>;
> > > +		regulator-name = "vdd_gpu";
> > > +		regulator-always-on;
> > > +		regulator-boot-on;
> > > +	};
> > 
> > Is this an internal voltage?
> 
> I think so.
> 
> > > +
> > > +	gpu_opp_table: opp_table {
> > 
> > Node-Names use dash instead of underscore.
> 
> Fixed, thanks.
> 
> [...]
> 
> > > @@ -1846,6 +1877,37 @@ netc_emdio: mdio at 0,0 {
> > >   			};
> > >   		};
> > > +		gpu_blk_ctrl: reset-controller at 4d810000 {
> > > +			compatible = "fsl,imx95-gpu-blk-ctrl";
> > > +			reg = <0x0 0x4d810000 0x0 0xc>;
> > 
> > Mh, GPU_BLK_CTRL is /just a bit) more than the GPU reset. Does it make sense
> > to make this an gpu-reset-only node, located at 0x4d810008?
> 
> The block controller itself is larger, it spans 3 or 4 registers, so this
> should describe the entire block controller here.
> 
> > > +			#reset-cells = <1>;
> > > +			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> > > +			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> > > +			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
> > > +			assigned-clock-rates = <133333333>;
> > > +			power-domains = <&scmi_devpd IMX95_PD_GPU>;
> > > +			status = "disabled";
> > > +		};
> > > +
> > > +		gpu: gpu at 4d900000 {
> > > +			compatible = "fsl,imx95-mali", "arm,mali-valhall-csf";
> > > +			reg = <0 0x4d900000 0 0x480000>;
> > > +			clocks = <&scmi_clk IMX95_CLK_GPU>;
> > 
> > There is also IMX95_CLK_GPUAPB. Is this only required for the rese control above?
> 
> I think I have to describe those clock here too, possibly as 'coregroup'
> clock ?

The 'coregroup' clock does indeed control the MMU and L2$ blocks as well as the AXI interface,
so if that is indeed a separate external clock source it should be defined. Could it be why
you're seeing issues with L2$ resume on the fast reset path?

Best regards,
Liviu

> 
> > > +			clock-names = "core";
> > > +			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
> > > +				     <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
> > > +				     <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
> > > +			interrupt-names = "gpu", "job", "mmu";
> > 
> > DT bindings say this order: job, mmu, gpu
> Yes, currently it is sorted by IRQ number, fixed.

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From steven.price at arm.com  Mon Mar  3 07:05:24 2025
From: steven.price at arm.com (Steven Price)
Date: Mon, 3 Mar 2025 15:05:24 +0000
Subject: [PATCH v7 01/45] KVM: Prepare for handling only shared mappings
 in mmu_notifier events
In-Reply-To: <8bf9ba6c-a8b2-42aa-9802-8e968bec1cd5@redhat.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-2-steven.price@arm.com>
 <8bf9ba6c-a8b2-42aa-9802-8e968bec1cd5@redhat.com>
Message-ID: <762524e0-d54f-4026-8a1d-732a7cfc6a1a@arm.com>

On 02/03/2025 23:36, Gavin Shan wrote:
> On 2/14/25 2:13 AM, Steven Price wrote:
>> From: Sean Christopherson <seanjc at google.com>
>>
>> Add flags to "struct kvm_gfn_range" to let notifier events target only
>> shared and only private mappings, and write up the existing mmu_notifier
>> events to be shared-only (private memory is never associated with a
>> userspace virtual address, i.e. can't be reached via mmu_notifiers).
>>
>> Add two flags so that KVM can handle the three possibilities (shared,
>> private, and shared+private) without needing something like a tri-state
>> enum.
>>
>> Link: https://lore.kernel.org/all/ZJX0hk+KpQP0KUyB at google.com
>> Signed-off-by: Sean Christopherson <seanjc at google.com>
>> Signed-off-by: Steven Price <steven.price at arm.com>
>> ---
>> ? include/linux/kvm_host.h | 2 ++
>> ? virt/kvm/kvm_main.c????? | 7 +++++++
>> ? 2 files changed, 9 insertions(+)
>>
>> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
>> index 3cb9a32a6330..0de1e485452c 100644
>> --- a/include/linux/kvm_host.h
>> +++ b/include/linux/kvm_host.h
>> @@ -266,6 +266,8 @@ struct kvm_gfn_range {
>> ????? gfn_t end;
>> ????? union kvm_mmu_notifier_arg arg;
>> ????? enum kvm_gfn_range_filter attr_filter;
>> +??? bool only_private;
>> +??? bool only_shared;
>> ????? bool may_block;
>> ? };
> 
> The added members (only_private and only_shared) looks duplicated to the
> member of attr_filter, which can be set to KVM_FILTER_SHARED,
> KVM_FILTER_PRIVATE,
> or both of them. More details can be found from the following commit where
> attr_filter was by dca6c88532322 ("KVM: Add member to struct kvm_gfn_range
> to indicate private/shared").
> 
> I'm guessing Sean's suggestion was given before dca6c88532322 showed up.

Thanks for pointing this out - you are absolutely right. I need to
switch the code in the following patches over to use attr_filter
instead. I hadn't realised when rebasing that attr_filter is the
replacement.

Thanks,
Steve

>> ? bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index faf10671eed2..4f0136094fac 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -593,6 +593,13 @@ static __always_inline kvm_mn_ret_t
>> __kvm_handle_hva_range(struct kvm *kvm,
>> ?????????????? * the second or later invocation of the handler).
>> ?????????????? */
>> ????????????? gfn_range.arg = range->arg;
>> +
>> +??????????? /*
>> +???????????? * HVA-based notifications aren't relevant to private
>> +???????????? * mappings as they don't have a userspace mapping.
>> +???????????? */
>> +??????????? gfn_range.only_private = false;
>> +??????????? gfn_range.only_shared = true;
>> ????????????? gfn_range.may_block = range->may_block;
>> ????????????? /*
>> ?????????????? * HVA-based notifications aren't relevant to private
> 
> Thanks,
> Gavin
> 



From steven.price at arm.com  Mon Mar  3 07:05:25 2025
From: steven.price at arm.com (Steven Price)
Date: Mon, 3 Mar 2025 15:05:25 +0000
Subject: [PATCH v7 05/45] arm64: RME: Add wrappers for RMI calls
In-Reply-To: <8f08b96b-8219-4d51-8f46-bc367bbf2031@redhat.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-6-steven.price@arm.com>
 <8f08b96b-8219-4d51-8f46-bc367bbf2031@redhat.com>
Message-ID: <59f84354-e890-48c8-ba06-87dda471f364@arm.com>

On 03/03/2025 03:42, Gavin Shan wrote:
> On 2/14/25 2:13 AM, Steven Price wrote:
>> The wrappers make the call sites easier to read and deal with the
>> boiler plate of handling the error codes from the RMM.
>>
>> Signed-off-by: Steven Price <steven.price at arm.com>
>> ---
>> Changes from v5:
>> ? * Further improve comments
>> Changes from v4:
>> ? * Improve comments
>> Changes from v2:
>> ? * Make output arguments optional.
>> ? * Mask RIPAS value rmi_rtt_read_entry()
>> ? * Drop unused rmi_rtt_get_phys()
>> ---
>> ? arch/arm64/include/asm/rmi_cmds.h | 508 ++++++++++++++++++++++++++++++
>> ? 1 file changed, 508 insertions(+)
>> ? create mode 100644 arch/arm64/include/asm/rmi_cmds.h
>>
> 
> With the following nitpicks addressed:
> 
> Reviewed-by: Gavin Shan <gshan at redhat.com>

Thanks, there were a couple of other pages and params_ptr references
that I've updated to granules and just 'params' too now. With hindsight
conflating pages and granules in the earlier versions of this series was
a big mistake ;)

Steve

>> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/
>> asm/rmi_cmds.h
>> new file mode 100644
>> index 000000000000..043b7ff278ee
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/rmi_cmds.h
>> @@ -0,0 +1,508 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (C) 2023 ARM Ltd.
>> + */
>> +
>> +#ifndef __ASM_RMI_CMDS_H
>> +#define __ASM_RMI_CMDS_H
>> +
> 
> [...]
> 
>> +
>> +/**
>> + * rmi_rec_aux_count() - Get number of auxiliary granules required
>> + * @rd: PA of the RD
>> + * @aux_count: Number of pages written to this pointer
> ????????????????? ^^^^^^^^^^^^^^^
> ????????????????? Number of granules
>> + *
>> + * A REC may require extra auxiliary pages to be delegated for the
>> RMM to
> ??????????????????????????????????????? ^^^^^
> ??????????????????????????????????????? granules
> 
>> + * store metadata (not visible to the normal world) in. This function
>> provides
>> + * the number of pages that are required.
> ??????????????????? ^^^^^
> ??????????????????? granules
>> + *
>> + * Return: RMI return code
>> + */
>> +static inline int rmi_rec_aux_count(unsigned long rd, unsigned long
>> *aux_count)
>> +{
>> +??? struct arm_smccc_res res;
>> +
>> +??? arm_smccc_1_1_invoke(SMC_RMI_REC_AUX_COUNT, rd, &res);
>> +
>> +??? if (aux_count)
>> +??????? *aux_count = res.a1;
>> +??? return res.a0;
>> +}
>> +
>> +/**
>> + * rmi_rec_create() - Create a REC
>> + * @rd: PA of the RD
>> + * @rec: PA of the target REC
>> + * @params_ptr: PA of REC parameters
>> + *
>> + * Create a REC using the parameters specified in the struct
>> rec_params pointed
>> + * to by @params_ptr.
>> + *
>> + * Return: RMI return code
>> + */
>> +static inline int rmi_rec_create(unsigned long rd, unsigned long rec,
>> +???????????????? unsigned long params_ptr)
>> +{
>> +??? struct arm_smccc_res res;
>> +
>> +??? arm_smccc_1_1_invoke(SMC_RMI_REC_CREATE, rd, rec, params_ptr, &res);
>> +
>> +??? return res.a0;
>> +}
>> +
> 
> 'params_ptr' may be renamed to 'params'.
> 
> 
> [...]
>> +#endif /* __ASM_RMI_CMDS_H */
> 
> Thanks,
> Gavin
> 



From robh at kernel.org  Mon Mar  3 07:07:39 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 3 Mar 2025 09:07:39 -0600
Subject: [PATCH 1/8] dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
In-Reply-To: <20250301104250.36295-2-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104250.36295-2-ziyao@disroot.org>
Message-ID: <174101445900.1859153.5372866255768427473.robh@kernel.org>


On Sat, 01 Mar 2025 10:42:43 +0000, Yao Zi wrote:
> Add compatible string for VO GRF found on RK3528 SoC.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar  3 07:13:41 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 3 Mar 2025 09:13:41 -0600
Subject: [PATCH v2 02/20] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250302-mt6359-accdet-dts-v2-2-5bd633ee0d47@collabora.com>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-2-5bd633ee0d47@collabora.com>
Message-ID: <20250303151341.GA1865196-robh@kernel.org>

On Sun, Mar 02, 2025 at 01:30:41PM -0300, N?colas F. R. A. Prado wrote:
> Describe the accdet as a possible subnode of the MT6359 PMIC.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..1a8c5748a28da6ad8aa091f8c0a74bc1dc709644 100644
> --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> @@ -224,6 +224,13 @@ properties:
>      description:
>        Pin controller
>  
> +  accdet:
> +    type: object
> +    $ref: /schemas/sound/mediatek,mt6359-accdet.yaml
> +    unevaluatedProperties: false

Don't need unevaluatedProperties here. The referenced schema already has 
the constraint.

> +    description:
> +      Accessory Detection
> +
>  required:
>    - compatible
>    - regulators
> 
> -- 
> 2.48.1
> 


From memxor at gmail.com  Mon Mar  3 07:22:53 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:53 -0800
Subject: [PATCH bpf-next v3 13/25] rqspinlock: Add a test-and-set fallback
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-14-memxor@gmail.com>

Include a test-and-set fallback when queued spinlock support is not
available. Introduce a rqspinlock type to act as a fallback when
qspinlock support is absent.

Include ifdef guards to ensure the slow path in this file is only
compiled when CONFIG_QUEUED_SPINLOCKS=y. Subsequent patches will add
further logic to ensure fallback to the test-and-set implementation
when queued spinlock support is unavailable on an architecture.

Unlike other waiting loops in rqspinlock code, the one for test-and-set
has no theoretical upper bound under contention, therefore we need a
longer timeout than usual. Bump it up to a second in this case.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 17 ++++++++++++
 kernel/locking/rqspinlock.c      | 45 ++++++++++++++++++++++++++++++--
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index b685f243cf96..b30a86abad7b 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -12,11 +12,28 @@
 #include <linux/types.h>
 #include <vdso/time64.h>
 #include <linux/percpu.h>
+#ifdef CONFIG_QUEUED_SPINLOCKS
+#include <asm/qspinlock.h>
+#endif
+
+struct rqspinlock {
+	union {
+		atomic_t val;
+		u32 locked;
+	};
+};
 
 struct qspinlock;
+#ifdef CONFIG_QUEUED_SPINLOCKS
 typedef struct qspinlock rqspinlock_t;
+#else
+typedef struct rqspinlock rqspinlock_t;
+#endif
 
+extern int resilient_tas_spin_lock(rqspinlock_t *lock);
+#ifdef CONFIG_QUEUED_SPINLOCKS
 extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+#endif
 
 /*
  * Default timeout for waiting loops is 0.25 seconds
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index ce2bc0a85a07..27ab4642f894 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -21,7 +21,9 @@
 #include <linux/mutex.h>
 #include <linux/prefetch.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_QUEUED_SPINLOCKS
 #include <asm/qspinlock.h>
+#endif
 #include <trace/events/lock.h>
 #include <asm/rqspinlock.h>
 #include <linux/timekeeping.h>
@@ -29,9 +31,12 @@
 /*
  * Include queued spinlock definitions and statistics code
  */
+#ifdef CONFIG_QUEUED_SPINLOCKS
 #include "qspinlock.h"
 #include "lock_events.h"
 #include "rqspinlock.h"
+#include "mcs_spinlock.h"
+#endif
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -70,8 +75,6 @@
  *
  */
 
-#include "mcs_spinlock.h"
-
 struct rqspinlock_timeout {
 	u64 timeout_end;
 	u64 duration;
@@ -262,6 +265,42 @@ static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
  */
 #define RES_RESET_TIMEOUT(ts, _duration) ({ (ts).timeout_end = 0; (ts).duration = _duration; })
 
+/*
+ * Provide a test-and-set fallback for cases when queued spin lock support is
+ * absent from the architecture.
+ */
+int __lockfunc resilient_tas_spin_lock(rqspinlock_t *lock)
+{
+	struct rqspinlock_timeout ts;
+	int val, ret = 0;
+
+	RES_INIT_TIMEOUT(ts);
+	grab_held_lock_entry(lock);
+
+	/*
+	 * Since the waiting loop's time is dependent on the amount of
+	 * contention, a short timeout unlike rqspinlock waiting loops
+	 * isn't enough. Choose a second as the timeout value.
+	 */
+	RES_RESET_TIMEOUT(ts, NSEC_PER_SEC);
+retry:
+	val = atomic_read(&lock->val);
+
+	if (val || !atomic_try_cmpxchg(&lock->val, &val, 1)) {
+		if (RES_CHECK_TIMEOUT(ts, ret, ~0u))
+			goto out;
+		cpu_relax();
+		goto retry;
+	}
+
+	return 0;
+out:
+	release_held_lock_entry();
+	return ret;
+}
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
  * contexts: task, softirq, hardirq, nmi.
@@ -610,3 +649,5 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	return ret;
 }
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
+
+#endif /* CONFIG_QUEUED_SPINLOCKS */
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:55 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:55 -0800
Subject: [PATCH bpf-next v3 15/25] rqspinlock: Add helper to print a splat on timeout or deadlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-16-memxor@gmail.com>

Whenever a timeout and a deadlock occurs, we would want to print a
message to the dmesg console, including the CPU where the event
occurred, the list of locks in the held locks table, and the stack trace
of the caller, which allows determining where exactly in the slow path
the waiter timed out or detected a deadlock.

Splats are limited to atmost one per-CPU during machine uptime, and a
lock is acquired to ensure that no interleaving occurs when a concurrent
set of CPUs conflict and enter a deadlock situation and start printing
data.

Later patches will use this to inspect return value of rqspinlock API
and then report a violation if necessary.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/rqspinlock.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index b06256bb16f4..3b4fdb183588 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -195,6 +195,35 @@ static noinline int check_deadlock_ABBA(rqspinlock_t *lock, u32 mask,
 	return 0;
 }
 
+static DEFINE_PER_CPU(int, report_nest_cnt);
+static DEFINE_PER_CPU(bool, report_flag);
+static arch_spinlock_t report_lock;
+
+static void rqspinlock_report_violation(const char *s, void *lock)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (this_cpu_inc_return(report_nest_cnt) != 1) {
+		this_cpu_dec(report_nest_cnt);
+		return;
+	}
+	if (this_cpu_read(report_flag))
+		goto end;
+	this_cpu_write(report_flag, true);
+	arch_spin_lock(&report_lock);
+
+	pr_err("CPU %d: %s", smp_processor_id(), s);
+	pr_info("Held locks: %d\n", rqh->cnt + 1);
+	pr_info("Held lock[%2d] = 0x%px\n", 0, lock);
+	for (int i = 0; i < min(RES_NR_HELD, rqh->cnt); i++)
+		pr_info("Held lock[%2d] = 0x%px\n", i + 1, rqh->locks[i]);
+	dump_stack();
+
+	arch_spin_unlock(&report_lock);
+end:
+	this_cpu_dec(report_nest_cnt);
+}
+
 static noinline int check_deadlock(rqspinlock_t *lock, u32 mask,
 				   struct rqspinlock_timeout *ts)
 {
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:56 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:56 -0800
Subject: [PATCH bpf-next v3 16/25] rqspinlock: Add macros for rqspinlock usage
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-17-memxor@gmail.com>

Introduce helper macros that wrap around the rqspinlock slow path and
provide an interface analogous to the raw_spin_lock API. Note that
in case of error conditions, preemption and IRQ disabling is
automatically unrolled before returning the error back to the caller.

Ensure that in absence of CONFIG_QUEUED_SPINLOCKS support, we fallback
to the test-and-set implementation.

Add some comments describing the subtle memory ordering logic during
unlock, and why it's safe.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 82 ++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index f8850f09d0d6..418b652e0249 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -153,4 +153,86 @@ static __always_inline void release_held_lock_entry(void)
 	this_cpu_dec(rqspinlock_held_locks.cnt);
 }
 
+#ifdef CONFIG_QUEUED_SPINLOCKS
+
+/**
+ * res_spin_lock - acquire a queued spinlock
+ * @lock: Pointer to queued spinlock structure
+ */
+static __always_inline int res_spin_lock(rqspinlock_t *lock)
+{
+	int val = 0;
+
+	if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL))) {
+		grab_held_lock_entry(lock);
+		return 0;
+	}
+	return resilient_queued_spin_lock_slowpath(lock, val);
+}
+
+#else
+
+#define res_spin_lock(lock) resilient_tas_spin_lock(lock)
+
+#endif /* CONFIG_QUEUED_SPINLOCKS */
+
+static __always_inline void res_spin_unlock(rqspinlock_t *lock)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (unlikely(rqh->cnt > RES_NR_HELD))
+		goto unlock;
+	WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL);
+unlock:
+	/*
+	 * Release barrier, ensures correct ordering. See release_held_lock_entry
+	 * for details.  Perform release store instead of queued_spin_unlock,
+	 * since we use this function for test-and-set fallback as well. When we
+	 * have CONFIG_QUEUED_SPINLOCKS=n, we clear the full 4-byte lockword.
+	 *
+	 * Like release_held_lock_entry, we can do the release before the dec.
+	 * We simply care about not seeing the 'lock' in our table from a remote
+	 * CPU once the lock has been released, which doesn't rely on the dec.
+	 *
+	 * Unlike smp_wmb(), release is not a two way fence, hence it is
+	 * possible for a inc to move up and reorder with our clearing of the
+	 * entry. This isn't a problem however, as for a misdiagnosis of ABBA,
+	 * the remote CPU needs to hold this lock, which won't be released until
+	 * the store below is done, which would ensure the entry is overwritten
+	 * to NULL, etc.
+	 */
+	smp_store_release(&lock->locked, 0);
+	this_cpu_dec(rqspinlock_held_locks.cnt);
+}
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+#define raw_res_spin_lock_init(lock) ({ *(lock) = (rqspinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; })
+#else
+#define raw_res_spin_lock_init(lock) ({ *(lock) = (rqspinlock_t){0}; })
+#endif
+
+#define raw_res_spin_lock(lock)                    \
+	({                                         \
+		int __ret;                         \
+		preempt_disable();                 \
+		__ret = res_spin_lock(lock);	   \
+		if (__ret)                         \
+			preempt_enable();          \
+		__ret;                             \
+	})
+
+#define raw_res_spin_unlock(lock) ({ res_spin_unlock(lock); preempt_enable(); })
+
+#define raw_res_spin_lock_irqsave(lock, flags)    \
+	({                                        \
+		int __ret;                        \
+		local_irq_save(flags);            \
+		__ret = raw_res_spin_lock(lock);  \
+		if (__ret)                        \
+			local_irq_restore(flags); \
+		__ret;                            \
+	})
+
+#define raw_res_spin_unlock_irqrestore(lock, flags) ({ raw_res_spin_unlock(lock); local_irq_restore(flags); })
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:54 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:54 -0800
Subject: [PATCH bpf-next v3 14/25] rqspinlock: Add basic support for CONFIG_PARAVIRT
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-15-memxor@gmail.com>

We ripped out PV and virtualization related bits from rqspinlock in an
earlier commit, however, a fair lock performs poorly within a virtual
machine when the lock holder is preempted. As such, retain the
virt_spin_lock fallback to test and set lock, but with timeout and
deadlock detection. We can do this by simply depending on the
resilient_tas_spin_lock implementation from the previous patch.

We don't integrate support for CONFIG_PARAVIRT_SPINLOCKS yet, as that
requires more involved algorithmic changes and introduces more
complexity. It can be done when the need arises in the future.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 arch/x86/include/asm/rqspinlock.h | 33 +++++++++++++++++++++++++++++++
 include/asm-generic/rqspinlock.h  | 14 +++++++++++++
 kernel/locking/rqspinlock.c       |  3 +++
 3 files changed, 50 insertions(+)
 create mode 100644 arch/x86/include/asm/rqspinlock.h

diff --git a/arch/x86/include/asm/rqspinlock.h b/arch/x86/include/asm/rqspinlock.h
new file mode 100644
index 000000000000..24a885449ee6
--- /dev/null
+++ b/arch/x86/include/asm/rqspinlock.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_RQSPINLOCK_H
+#define _ASM_X86_RQSPINLOCK_H
+
+#include <asm/paravirt.h>
+
+#ifdef CONFIG_PARAVIRT
+DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
+
+#define resilient_virt_spin_lock_enabled resilient_virt_spin_lock_enabled
+static __always_inline bool resilient_virt_spin_lock_enabled(void)
+{
+       return static_branch_likely(&virt_spin_lock_key);
+}
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+typedef struct qspinlock rqspinlock_t;
+#else
+typedef struct rqspinlock rqspinlock_t;
+#endif
+extern int resilient_tas_spin_lock(rqspinlock_t *lock);
+
+#define resilient_virt_spin_lock resilient_virt_spin_lock
+static inline int resilient_virt_spin_lock(rqspinlock_t *lock)
+{
+	return resilient_tas_spin_lock(lock);
+}
+
+#endif /* CONFIG_PARAVIRT */
+
+#include <asm-generic/rqspinlock.h>
+
+#endif /* _ASM_X86_RQSPINLOCK_H */
diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index b30a86abad7b..f8850f09d0d6 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -35,6 +35,20 @@ extern int resilient_tas_spin_lock(rqspinlock_t *lock);
 extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 #endif
 
+#ifndef resilient_virt_spin_lock_enabled
+static __always_inline bool resilient_virt_spin_lock_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef resilient_virt_spin_lock
+static __always_inline int resilient_virt_spin_lock(rqspinlock_t *lock)
+{
+	return 0;
+}
+#endif
+
 /*
  * Default timeout for waiting loops is 0.25 seconds
  */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 27ab4642f894..b06256bb16f4 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -345,6 +345,9 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
+	if (resilient_virt_spin_lock_enabled())
+		return resilient_virt_spin_lock(lock);
+
 	RES_INIT_TIMEOUT(ts);
 
 	/*
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:57 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:57 -0800
Subject: [PATCH bpf-next v3 17/25] rqspinlock: Add locktorture support
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-18-memxor@gmail.com>

Introduce locktorture support for rqspinlock using the newly added
macros as the first in-kernel user and consumer. Guard the code with
CONFIG_BPF_SYSCALL ifdef since rqspinlock is not available otherwise.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/locktorture.c | 57 ++++++++++++++++++++++++++++++++++++
 kernel/locking/rqspinlock.c  |  1 +
 2 files changed, 58 insertions(+)

diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index cc33470f4de9..ce0362f0a871 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -362,6 +362,60 @@ static struct lock_torture_ops raw_spin_lock_irq_ops = {
 	.name		= "raw_spin_lock_irq"
 };
 
+#ifdef CONFIG_BPF_SYSCALL
+
+#include <asm/rqspinlock.h>
+static rqspinlock_t rqspinlock;
+
+static int torture_raw_res_spin_write_lock(int tid __maybe_unused)
+{
+	raw_res_spin_lock(&rqspinlock);
+	return 0;
+}
+
+static void torture_raw_res_spin_write_unlock(int tid __maybe_unused)
+{
+	raw_res_spin_unlock(&rqspinlock);
+}
+
+static struct lock_torture_ops raw_res_spin_lock_ops = {
+	.writelock	= torture_raw_res_spin_write_lock,
+	.write_delay	= torture_spin_lock_write_delay,
+	.task_boost     = torture_rt_boost,
+	.writeunlock	= torture_raw_res_spin_write_unlock,
+	.readlock       = NULL,
+	.read_delay     = NULL,
+	.readunlock     = NULL,
+	.name		= "raw_res_spin_lock"
+};
+
+static int torture_raw_res_spin_write_lock_irq(int tid __maybe_unused)
+{
+	unsigned long flags;
+
+	raw_res_spin_lock_irqsave(&rqspinlock, flags);
+	cxt.cur_ops->flags = flags;
+	return 0;
+}
+
+static void torture_raw_res_spin_write_unlock_irq(int tid __maybe_unused)
+{
+	raw_res_spin_unlock_irqrestore(&rqspinlock, cxt.cur_ops->flags);
+}
+
+static struct lock_torture_ops raw_res_spin_lock_irq_ops = {
+	.writelock	= torture_raw_res_spin_write_lock_irq,
+	.write_delay	= torture_spin_lock_write_delay,
+	.task_boost     = torture_rt_boost,
+	.writeunlock	= torture_raw_res_spin_write_unlock_irq,
+	.readlock       = NULL,
+	.read_delay     = NULL,
+	.readunlock     = NULL,
+	.name		= "raw_res_spin_lock_irq"
+};
+
+#endif
+
 static DEFINE_RWLOCK(torture_rwlock);
 
 static int torture_rwlock_write_lock(int tid __maybe_unused)
@@ -1168,6 +1222,9 @@ static int __init lock_torture_init(void)
 		&lock_busted_ops,
 		&spin_lock_ops, &spin_lock_irq_ops,
 		&raw_spin_lock_ops, &raw_spin_lock_irq_ops,
+#ifdef CONFIG_BPF_SYSCALL
+		&raw_res_spin_lock_ops, &raw_res_spin_lock_irq_ops,
+#endif
 		&rw_lock_ops, &rw_lock_irq_ops,
 		&mutex_lock_ops,
 		&ww_mutex_lock_ops,
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 3b4fdb183588..0031a1bfbd4e 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -85,6 +85,7 @@ struct rqspinlock_timeout {
 #define RES_TIMEOUT_VAL	2
 
 DEFINE_PER_CPU_ALIGNED(struct rqspinlock_held, rqspinlock_held_locks);
+EXPORT_SYMBOL_GPL(rqspinlock_held_locks);
 
 static bool is_lock_released(rqspinlock_t *lock, u32 mask, struct rqspinlock_timeout *ts)
 {
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:59 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:59 -0800
Subject: [PATCH bpf-next v3 19/25] bpf: Convert hashtab.c to rqspinlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-20-memxor@gmail.com>

Convert hashtab.c from raw_spinlock to rqspinlock, and drop the hashed
per-cpu counter crud from the code base which is no longer necessary.

Closes: https://lore.kernel.org/bpf/675302fd.050a0220.2477f.0004.GAE at google.com
Closes: https://lore.kernel.org/bpf/000000000000b3e63e061eed3f6b at google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/hashtab.c | 102 ++++++++++++++-----------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)

diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index c308300fc72f..93d45812bb6a 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -16,6 +16,7 @@
 #include "bpf_lru_list.h"
 #include "map_in_map.h"
 #include <linux/bpf_mem_alloc.h>
+#include <asm/rqspinlock.h>
 
 #define HTAB_CREATE_FLAG_MASK						\
 	(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE |	\
@@ -78,7 +79,7 @@
  */
 struct bucket {
 	struct hlist_nulls_head head;
-	raw_spinlock_t raw_lock;
+	rqspinlock_t raw_lock;
 };
 
 #define HASHTAB_MAP_LOCK_COUNT 8
@@ -104,8 +105,6 @@ struct bpf_htab {
 	u32 n_buckets;	/* number of hash buckets */
 	u32 elem_size;	/* size of each element in bytes */
 	u32 hashrnd;
-	struct lock_class_key lockdep_key;
-	int __percpu *map_locked[HASHTAB_MAP_LOCK_COUNT];
 };
 
 /* each htab element is struct htab_elem + key + value */
@@ -140,45 +139,26 @@ static void htab_init_buckets(struct bpf_htab *htab)
 
 	for (i = 0; i < htab->n_buckets; i++) {
 		INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
-		raw_spin_lock_init(&htab->buckets[i].raw_lock);
-		lockdep_set_class(&htab->buckets[i].raw_lock,
-					  &htab->lockdep_key);
+		raw_res_spin_lock_init(&htab->buckets[i].raw_lock);
 		cond_resched();
 	}
 }
 
-static inline int htab_lock_bucket(const struct bpf_htab *htab,
-				   struct bucket *b, u32 hash,
-				   unsigned long *pflags)
+static inline int htab_lock_bucket(struct bucket *b, unsigned long *pflags)
 {
 	unsigned long flags;
+	int ret;
 
-	hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
-
-	preempt_disable();
-	local_irq_save(flags);
-	if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) {
-		__this_cpu_dec(*(htab->map_locked[hash]));
-		local_irq_restore(flags);
-		preempt_enable();
-		return -EBUSY;
-	}
-
-	raw_spin_lock(&b->raw_lock);
+	ret = raw_res_spin_lock_irqsave(&b->raw_lock, flags);
+	if (ret)
+		return ret;
 	*pflags = flags;
-
 	return 0;
 }
 
-static inline void htab_unlock_bucket(const struct bpf_htab *htab,
-				      struct bucket *b, u32 hash,
-				      unsigned long flags)
+static inline void htab_unlock_bucket(struct bucket *b, unsigned long flags)
 {
-	hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
-	raw_spin_unlock(&b->raw_lock);
-	__this_cpu_dec(*(htab->map_locked[hash]));
-	local_irq_restore(flags);
-	preempt_enable();
+	raw_res_spin_unlock_irqrestore(&b->raw_lock, flags);
 }
 
 static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node);
@@ -483,14 +463,12 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 	bool percpu_lru = (attr->map_flags & BPF_F_NO_COMMON_LRU);
 	bool prealloc = !(attr->map_flags & BPF_F_NO_PREALLOC);
 	struct bpf_htab *htab;
-	int err, i;
+	int err;
 
 	htab = bpf_map_area_alloc(sizeof(*htab), NUMA_NO_NODE);
 	if (!htab)
 		return ERR_PTR(-ENOMEM);
 
-	lockdep_register_key(&htab->lockdep_key);
-
 	bpf_map_init_from_attr(&htab->map, attr);
 
 	if (percpu_lru) {
@@ -536,15 +514,6 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 	if (!htab->buckets)
 		goto free_elem_count;
 
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++) {
-		htab->map_locked[i] = bpf_map_alloc_percpu(&htab->map,
-							   sizeof(int),
-							   sizeof(int),
-							   GFP_USER);
-		if (!htab->map_locked[i])
-			goto free_map_locked;
-	}
-
 	if (htab->map.map_flags & BPF_F_ZERO_SEED)
 		htab->hashrnd = 0;
 	else
@@ -607,15 +576,12 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 free_map_locked:
 	if (htab->use_percpu_counter)
 		percpu_counter_destroy(&htab->pcount);
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++)
-		free_percpu(htab->map_locked[i]);
 	bpf_map_area_free(htab->buckets);
 	bpf_mem_alloc_destroy(&htab->pcpu_ma);
 	bpf_mem_alloc_destroy(&htab->ma);
 free_elem_count:
 	bpf_map_free_elem_count(&htab->map);
 free_htab:
-	lockdep_unregister_key(&htab->lockdep_key);
 	bpf_map_area_free(htab);
 	return ERR_PTR(err);
 }
@@ -817,7 +783,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 	b = __select_bucket(htab, tgt_l->hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, tgt_l->hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return false;
 
@@ -828,7 +794,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 			break;
 		}
 
-	htab_unlock_bucket(htab, b, tgt_l->hash, flags);
+	htab_unlock_bucket(b, flags);
 
 	if (l == tgt_l)
 		check_and_free_fields(htab, l);
@@ -1147,7 +1113,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 		 */
 	}
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1198,7 +1164,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 			check_and_free_fields(htab, l_old);
 		}
 	}
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	if (l_old) {
 		if (old_map_ptr)
 			map->ops->map_fd_put_ptr(map, old_map_ptr, true);
@@ -1207,7 +1173,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 	}
 	return 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	return ret;
 }
 
@@ -1254,7 +1220,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 	copy_map_value(&htab->map,
 		       l_new->key + round_up(map->key_size, 8), value);
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		goto err_lock_bucket;
 
@@ -1275,7 +1241,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 	ret = 0;
 
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 
 err_lock_bucket:
 	if (ret)
@@ -1312,7 +1278,7 @@ static long __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1337,7 +1303,7 @@ static long __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
 	}
 	ret = 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	return ret;
 }
 
@@ -1378,7 +1344,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 			return -ENOMEM;
 	}
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		goto err_lock_bucket;
 
@@ -1402,7 +1368,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 	}
 	ret = 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 err_lock_bucket:
 	if (l_new) {
 		bpf_map_dec_elem_count(&htab->map);
@@ -1444,7 +1410,7 @@ static long htab_map_delete_elem(struct bpf_map *map, void *key)
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1454,7 +1420,7 @@ static long htab_map_delete_elem(struct bpf_map *map, void *key)
 	else
 		ret = -ENOENT;
 
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 
 	if (l)
 		free_htab_elem(htab, l);
@@ -1480,7 +1446,7 @@ static long htab_lru_map_delete_elem(struct bpf_map *map, void *key)
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1491,7 +1457,7 @@ static long htab_lru_map_delete_elem(struct bpf_map *map, void *key)
 	else
 		ret = -ENOENT;
 
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	if (l)
 		htab_lru_push_free(htab, l);
 	return ret;
@@ -1558,7 +1524,6 @@ static void htab_map_free_timers_and_wq(struct bpf_map *map)
 static void htab_map_free(struct bpf_map *map)
 {
 	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-	int i;
 
 	/* bpf_free_used_maps() or close(map_fd) will trigger this map_free callback.
 	 * bpf_free_used_maps() is called after bpf prog is no longer executing.
@@ -1583,9 +1548,6 @@ static void htab_map_free(struct bpf_map *map)
 	bpf_mem_alloc_destroy(&htab->ma);
 	if (htab->use_percpu_counter)
 		percpu_counter_destroy(&htab->pcount);
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++)
-		free_percpu(htab->map_locked[i]);
-	lockdep_unregister_key(&htab->lockdep_key);
 	bpf_map_area_free(htab);
 }
 
@@ -1628,7 +1590,7 @@ static int __htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key,
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &bflags);
+	ret = htab_lock_bucket(b, &bflags);
 	if (ret)
 		return ret;
 
@@ -1665,7 +1627,7 @@ static int __htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key,
 	hlist_nulls_del_rcu(&l->hash_node);
 
 out_unlock:
-	htab_unlock_bucket(htab, b, hash, bflags);
+	htab_unlock_bucket(b, bflags);
 
 	if (l) {
 		if (is_lru_map)
@@ -1787,7 +1749,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 	head = &b->head;
 	/* do not grab the lock unless need it (bucket_cnt > 0). */
 	if (locked) {
-		ret = htab_lock_bucket(htab, b, batch, &flags);
+		ret = htab_lock_bucket(b, &flags);
 		if (ret) {
 			rcu_read_unlock();
 			bpf_enable_instrumentation();
@@ -1810,7 +1772,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		/* Note that since bucket_cnt > 0 here, it is implicit
 		 * that the locked was grabbed, so release it.
 		 */
-		htab_unlock_bucket(htab, b, batch, flags);
+		htab_unlock_bucket(b, flags);
 		rcu_read_unlock();
 		bpf_enable_instrumentation();
 		goto after_loop;
@@ -1821,7 +1783,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		/* Note that since bucket_cnt > 0 here, it is implicit
 		 * that the locked was grabbed, so release it.
 		 */
-		htab_unlock_bucket(htab, b, batch, flags);
+		htab_unlock_bucket(b, flags);
 		rcu_read_unlock();
 		bpf_enable_instrumentation();
 		kvfree(keys);
@@ -1884,7 +1846,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		dst_val += value_size;
 	}
 
-	htab_unlock_bucket(htab, b, batch, flags);
+	htab_unlock_bucket(b, flags);
 	locked = false;
 
 	while (node_to_free) {
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:58 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:58 -0800
Subject: [PATCH bpf-next v3 18/25] rqspinlock: Add entry to Makefile, MAINTAINERS
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-19-memxor@gmail.com>

Ensure that rqspinlock is built when qspinlock support and BPF subsystem
is enabled. Also, add the file under the BPF MAINTAINERS entry so that
all patches changing code in the file end up Cc'ing bpf at vger and the
maintainers/reviewers.

Ensure that the rqspinlock code is only built when the BPF subsystem is
compiled in. Depending on queued spinlock support, we may or may not end
up building the queued spinlock slowpath, and instead fallback to the
test-and-set implementation.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 MAINTAINERS                | 3 +++
 include/asm-generic/Kbuild | 1 +
 kernel/locking/Makefile    | 1 +
 3 files changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3864d473f52f..b0179ef867eb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4297,6 +4297,9 @@ F:	include/uapi/linux/filter.h
 F:	kernel/bpf/
 F:	kernel/trace/bpf_trace.c
 F:	lib/buildid.c
+F:	arch/*/include/asm/rqspinlock.h
+F:	include/asm-generic/rqspinlock.h
+F:	kernel/locking/rqspinlock.c
 F:	lib/test_bpf.c
 F:	net/bpf/
 F:	net/core/filter.c
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index 1b43c3a77012..8675b7b4ad23 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -45,6 +45,7 @@ mandatory-y += pci.h
 mandatory-y += percpu.h
 mandatory-y += pgalloc.h
 mandatory-y += preempt.h
+mandatory-y += rqspinlock.h
 mandatory-y += runtime-const.h
 mandatory-y += rwonce.h
 mandatory-y += sections.h
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 0db4093d17b8..5645e9029bc0 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SMP) += spinlock.o
 obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o
 obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
 obj-$(CONFIG_QUEUED_SPINLOCKS) += qspinlock.o
+obj-$(CONFIG_BPF_SYSCALL) += rqspinlock.o
 obj-$(CONFIG_RT_MUTEXES) += rtmutex_api.o
 obj-$(CONFIG_PREEMPT_RT) += spinlock_rt.o ww_rt_mutex.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:00 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:00 -0800
Subject: [PATCH bpf-next v3 20/25] bpf: Convert percpu_freelist.c to rqspinlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-21-memxor@gmail.com>

Convert the percpu_freelist.c code to use rqspinlock, and remove the
extralist fallback and trylock-based acquisitions to avoid deadlocks.

Key thing to note is the retained while (true) loop to search through
other CPUs when failing to push a node due to locking errors. This
retains the behavior of the old code, where it would keep trying until
it would be able to successfully push the node back into the freelist of
a CPU.

Technically, we should start iteration for this loop from
raw_smp_processor_id() + 1, but to avoid hitting the edge of nr_cpus,
we skip execution in the loop body instead.

Closes: https://lore.kernel.org/bpf/CAPPBnEa1_pZ6W24+WwtcNFvTUHTHO7KUmzEbOcMqxp+m2o15qQ at mail.gmail.com
Closes: https://lore.kernel.org/bpf/CAPPBnEYm+9zduStsZaDnq93q1jPLqO-PiKX9jy0MuL8LCXmCrQ at mail.gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/percpu_freelist.c | 113 ++++++++---------------------------
 kernel/bpf/percpu_freelist.h |   4 +-
 2 files changed, 27 insertions(+), 90 deletions(-)

diff --git a/kernel/bpf/percpu_freelist.c b/kernel/bpf/percpu_freelist.c
index 034cf87b54e9..632762b57299 100644
--- a/kernel/bpf/percpu_freelist.c
+++ b/kernel/bpf/percpu_freelist.c
@@ -14,11 +14,9 @@ int pcpu_freelist_init(struct pcpu_freelist *s)
 	for_each_possible_cpu(cpu) {
 		struct pcpu_freelist_head *head = per_cpu_ptr(s->freelist, cpu);
 
-		raw_spin_lock_init(&head->lock);
+		raw_res_spin_lock_init(&head->lock);
 		head->first = NULL;
 	}
-	raw_spin_lock_init(&s->extralist.lock);
-	s->extralist.first = NULL;
 	return 0;
 }
 
@@ -34,58 +32,39 @@ static inline void pcpu_freelist_push_node(struct pcpu_freelist_head *head,
 	WRITE_ONCE(head->first, node);
 }
 
-static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
+static inline bool ___pcpu_freelist_push(struct pcpu_freelist_head *head,
 					 struct pcpu_freelist_node *node)
 {
-	raw_spin_lock(&head->lock);
-	pcpu_freelist_push_node(head, node);
-	raw_spin_unlock(&head->lock);
-}
-
-static inline bool pcpu_freelist_try_push_extra(struct pcpu_freelist *s,
-						struct pcpu_freelist_node *node)
-{
-	if (!raw_spin_trylock(&s->extralist.lock))
+	if (raw_res_spin_lock(&head->lock))
 		return false;
-
-	pcpu_freelist_push_node(&s->extralist, node);
-	raw_spin_unlock(&s->extralist.lock);
+	pcpu_freelist_push_node(head, node);
+	raw_res_spin_unlock(&head->lock);
 	return true;
 }
 
-static inline void ___pcpu_freelist_push_nmi(struct pcpu_freelist *s,
-					     struct pcpu_freelist_node *node)
+void __pcpu_freelist_push(struct pcpu_freelist *s,
+			struct pcpu_freelist_node *node)
 {
-	int cpu, orig_cpu;
+	struct pcpu_freelist_head *head;
+	int cpu;
 
-	orig_cpu = raw_smp_processor_id();
-	while (1) {
-		for_each_cpu_wrap(cpu, cpu_possible_mask, orig_cpu) {
-			struct pcpu_freelist_head *head;
+	if (___pcpu_freelist_push(this_cpu_ptr(s->freelist), node))
+		return;
 
+	while (true) {
+		for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
+			if (cpu == raw_smp_processor_id())
+				continue;
 			head = per_cpu_ptr(s->freelist, cpu);
-			if (raw_spin_trylock(&head->lock)) {
-				pcpu_freelist_push_node(head, node);
-				raw_spin_unlock(&head->lock);
-				return;
-			}
-		}
-
-		/* cannot lock any per cpu lock, try extralist */
-		if (pcpu_freelist_try_push_extra(s, node))
+			if (raw_res_spin_lock(&head->lock))
+				continue;
+			pcpu_freelist_push_node(head, node);
+			raw_res_spin_unlock(&head->lock);
 			return;
+		}
 	}
 }
 
-void __pcpu_freelist_push(struct pcpu_freelist *s,
-			struct pcpu_freelist_node *node)
-{
-	if (in_nmi())
-		___pcpu_freelist_push_nmi(s, node);
-	else
-		___pcpu_freelist_push(this_cpu_ptr(s->freelist), node);
-}
-
 void pcpu_freelist_push(struct pcpu_freelist *s,
 			struct pcpu_freelist_node *node)
 {
@@ -120,71 +99,29 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
 
 static struct pcpu_freelist_node *___pcpu_freelist_pop(struct pcpu_freelist *s)
 {
+	struct pcpu_freelist_node *node = NULL;
 	struct pcpu_freelist_head *head;
-	struct pcpu_freelist_node *node;
 	int cpu;
 
 	for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
 		head = per_cpu_ptr(s->freelist, cpu);
 		if (!READ_ONCE(head->first))
 			continue;
-		raw_spin_lock(&head->lock);
+		if (raw_res_spin_lock(&head->lock))
+			continue;
 		node = head->first;
 		if (node) {
 			WRITE_ONCE(head->first, node->next);
-			raw_spin_unlock(&head->lock);
+			raw_res_spin_unlock(&head->lock);
 			return node;
 		}
-		raw_spin_unlock(&head->lock);
+		raw_res_spin_unlock(&head->lock);
 	}
-
-	/* per cpu lists are all empty, try extralist */
-	if (!READ_ONCE(s->extralist.first))
-		return NULL;
-	raw_spin_lock(&s->extralist.lock);
-	node = s->extralist.first;
-	if (node)
-		WRITE_ONCE(s->extralist.first, node->next);
-	raw_spin_unlock(&s->extralist.lock);
-	return node;
-}
-
-static struct pcpu_freelist_node *
-___pcpu_freelist_pop_nmi(struct pcpu_freelist *s)
-{
-	struct pcpu_freelist_head *head;
-	struct pcpu_freelist_node *node;
-	int cpu;
-
-	for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
-		head = per_cpu_ptr(s->freelist, cpu);
-		if (!READ_ONCE(head->first))
-			continue;
-		if (raw_spin_trylock(&head->lock)) {
-			node = head->first;
-			if (node) {
-				WRITE_ONCE(head->first, node->next);
-				raw_spin_unlock(&head->lock);
-				return node;
-			}
-			raw_spin_unlock(&head->lock);
-		}
-	}
-
-	/* cannot pop from per cpu lists, try extralist */
-	if (!READ_ONCE(s->extralist.first) || !raw_spin_trylock(&s->extralist.lock))
-		return NULL;
-	node = s->extralist.first;
-	if (node)
-		WRITE_ONCE(s->extralist.first, node->next);
-	raw_spin_unlock(&s->extralist.lock);
 	return node;
 }
 
 struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
 {
-	if (in_nmi())
-		return ___pcpu_freelist_pop_nmi(s);
 	return ___pcpu_freelist_pop(s);
 }
 
diff --git a/kernel/bpf/percpu_freelist.h b/kernel/bpf/percpu_freelist.h
index 3c76553cfe57..914798b74967 100644
--- a/kernel/bpf/percpu_freelist.h
+++ b/kernel/bpf/percpu_freelist.h
@@ -5,15 +5,15 @@
 #define __PERCPU_FREELIST_H__
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
+#include <asm/rqspinlock.h>
 
 struct pcpu_freelist_head {
 	struct pcpu_freelist_node *first;
-	raw_spinlock_t lock;
+	rqspinlock_t lock;
 };
 
 struct pcpu_freelist {
 	struct pcpu_freelist_head __percpu *freelist;
-	struct pcpu_freelist_head extralist;
 };
 
 struct pcpu_freelist_node {
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:01 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:01 -0800
Subject: [PATCH bpf-next v3 21/25] bpf: Convert lpm_trie.c to rqspinlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-22-memxor@gmail.com>

Convert all LPM trie usage of raw_spinlock to rqspinlock.

Note that rcu_dereference_protected in trie_delete_elem is switched over
to plain rcu_dereference, the RCU read lock should be held from BPF
program side or eBPF syscall path, and the trie->lock is just acquired
before the dereference. It is not clear the reason the protected variant
was used from the commit history, but the above reasoning makes sense so
switch over.

Closes: https://lore.kernel.org/lkml/000000000000adb08b061413919e at google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/lpm_trie.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index e8a772e64324..be66d7e520e0 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -15,6 +15,7 @@
 #include <net/ipv6.h>
 #include <uapi/linux/btf.h>
 #include <linux/btf_ids.h>
+#include <asm/rqspinlock.h>
 #include <linux/bpf_mem_alloc.h>
 
 /* Intermediate node */
@@ -36,7 +37,7 @@ struct lpm_trie {
 	size_t				n_entries;
 	size_t				max_prefixlen;
 	size_t				data_size;
-	raw_spinlock_t			lock;
+	rqspinlock_t			lock;
 };
 
 /* This trie implements a longest prefix match algorithm that can be used to
@@ -342,7 +343,9 @@ static long trie_update_elem(struct bpf_map *map,
 	if (!new_node)
 		return -ENOMEM;
 
-	raw_spin_lock_irqsave(&trie->lock, irq_flags);
+	ret = raw_res_spin_lock_irqsave(&trie->lock, irq_flags);
+	if (ret)
+		goto out_free;
 
 	new_node->prefixlen = key->prefixlen;
 	RCU_INIT_POINTER(new_node->child[0], NULL);
@@ -356,8 +359,7 @@ static long trie_update_elem(struct bpf_map *map,
 	 */
 	slot = &trie->root;
 
-	while ((node = rcu_dereference_protected(*slot,
-					lockdep_is_held(&trie->lock)))) {
+	while ((node = rcu_dereference(*slot))) {
 		matchlen = longest_prefix_match(trie, node, key);
 
 		if (node->prefixlen != matchlen ||
@@ -442,8 +444,8 @@ static long trie_update_elem(struct bpf_map *map,
 	rcu_assign_pointer(*slot, im_node);
 
 out:
-	raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
-
+	raw_res_spin_unlock_irqrestore(&trie->lock, irq_flags);
+out_free:
 	if (ret)
 		bpf_mem_cache_free(&trie->ma, new_node);
 	bpf_mem_cache_free_rcu(&trie->ma, free_node);
@@ -467,7 +469,9 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	if (key->prefixlen > trie->max_prefixlen)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&trie->lock, irq_flags);
+	ret = raw_res_spin_lock_irqsave(&trie->lock, irq_flags);
+	if (ret)
+		return ret;
 
 	/* Walk the tree looking for an exact key/length match and keeping
 	 * track of the path we traverse.  We will need to know the node
@@ -478,8 +482,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	trim = &trie->root;
 	trim2 = trim;
 	parent = NULL;
-	while ((node = rcu_dereference_protected(
-		       *trim, lockdep_is_held(&trie->lock)))) {
+	while ((node = rcu_dereference(*trim))) {
 		matchlen = longest_prefix_match(trie, node, key);
 
 		if (node->prefixlen != matchlen ||
@@ -543,7 +546,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	free_node = node;
 
 out:
-	raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
+	raw_res_spin_unlock_irqrestore(&trie->lock, irq_flags);
 
 	bpf_mem_cache_free_rcu(&trie->ma, free_parent);
 	bpf_mem_cache_free_rcu(&trie->ma, free_node);
@@ -592,7 +595,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
 			  offsetof(struct bpf_lpm_trie_key_u8, data);
 	trie->max_prefixlen = trie->data_size * 8;
 
-	raw_spin_lock_init(&trie->lock);
+	raw_res_spin_lock_init(&trie->lock);
 
 	/* Allocate intermediate and leaf nodes from the same allocator */
 	leaf_size = sizeof(struct lpm_trie_node) + trie->data_size +
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:02 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:02 -0800
Subject: [PATCH bpf-next v3 22/25] bpf: Introduce rqspinlock kfuncs
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-23-memxor@gmail.com>

Introduce four new kfuncs, bpf_res_spin_lock, and bpf_res_spin_unlock,
and their irqsave/irqrestore variants, which wrap the rqspinlock APIs.
bpf_res_spin_lock returns a conditional result, depending on whether the
lock was acquired (NULL is returned when lock acquisition succeeds,
non-NULL upon failure). The memory pointed to by the returned pointer
upon failure can be dereferenced after the NULL check to obtain the
error code.

Instead of using the old bpf_spin_lock type, introduce a new type with
the same layout, and the same alignment, but a different name to avoid
type confusion.

Preemption is disabled upon successful lock acquisition, however IRQs
are not. Special kfuncs can be introduced later to allow disabling IRQs
when taking a spin lock. Resilient locks are safe against AA deadlocks,
hence not disabling IRQs currently does not allow violation of kernel
safety.

__irq_flag annotation is used to accept IRQ flags for the IRQ-variants,
with the same semantics as existing bpf_local_irq_{save, restore}.

These kfuncs will require additional verifier-side support in subsequent
commits, to allow programs to hold multiple locks at the same time.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h |  7 +++
 include/linux/bpf.h              |  1 +
 kernel/locking/rqspinlock.c      | 78 ++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 418b652e0249..06906489d9ba 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -23,6 +23,13 @@ struct rqspinlock {
 	};
 };
 
+/* Even though this is same as struct rqspinlock, we need to emit a distinct
+ * type in BTF for BPF programs.
+ */
+struct bpf_res_spin_lock {
+	u32 val;
+};
+
 struct qspinlock;
 #ifdef CONFIG_QUEUED_SPINLOCKS
 typedef struct qspinlock rqspinlock_t;
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 4c4028d865ee..aa47e11371b3 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -30,6 +30,7 @@
 #include <linux/static_call.h>
 #include <linux/memcontrol.h>
 #include <linux/cfi.h>
+#include <asm/rqspinlock.h>
 
 struct bpf_verifier_env;
 struct bpf_verifier_log;
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 0031a1bfbd4e..0c53d36e2f6c 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -15,6 +15,8 @@
 
 #include <linux/smp.h>
 #include <linux/bug.h>
+#include <linux/bpf.h>
+#include <linux/err.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
@@ -684,3 +686,79 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
 
 #endif /* CONFIG_QUEUED_SPINLOCKS */
+
+__bpf_kfunc_start_defs();
+
+#define REPORT_STR(ret) ({ ret == -ETIMEDOUT ? "Timeout detected" : "AA or ABBA deadlock detected"; })
+
+__bpf_kfunc int bpf_res_spin_lock(struct bpf_res_spin_lock *lock)
+{
+	int ret;
+
+	BUILD_BUG_ON(sizeof(rqspinlock_t) != sizeof(struct bpf_res_spin_lock));
+	BUILD_BUG_ON(__alignof__(rqspinlock_t) != __alignof__(struct bpf_res_spin_lock));
+
+	preempt_disable();
+	ret = res_spin_lock((rqspinlock_t *)lock);
+	if (unlikely(ret)) {
+		preempt_enable();
+		rqspinlock_report_violation(REPORT_STR(ret), lock);
+		return ret;
+	}
+	return 0;
+}
+
+__bpf_kfunc void bpf_res_spin_unlock(struct bpf_res_spin_lock *lock)
+{
+	res_spin_unlock((rqspinlock_t *)lock);
+	preempt_enable();
+}
+
+__bpf_kfunc int bpf_res_spin_lock_irqsave(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag)
+{
+	u64 *ptr = (u64 *)flags__irq_flag;
+	unsigned long flags;
+	int ret;
+
+	preempt_disable();
+	local_irq_save(flags);
+	ret = res_spin_lock((rqspinlock_t *)lock);
+	if (unlikely(ret)) {
+		local_irq_restore(flags);
+		preempt_enable();
+		rqspinlock_report_violation(REPORT_STR(ret), lock);
+		return ret;
+	}
+	*ptr = flags;
+	return 0;
+}
+
+__bpf_kfunc void bpf_res_spin_unlock_irqrestore(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag)
+{
+	u64 *ptr = (u64 *)flags__irq_flag;
+	unsigned long flags = *ptr;
+
+	res_spin_unlock((rqspinlock_t *)lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+
+__bpf_kfunc_end_defs();
+
+BTF_KFUNCS_START(rqspinlock_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_res_spin_lock, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_res_spin_unlock)
+BTF_ID_FLAGS(func, bpf_res_spin_lock_irqsave, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_res_spin_unlock_irqrestore)
+BTF_KFUNCS_END(rqspinlock_kfunc_ids)
+
+static const struct btf_kfunc_id_set rqspinlock_kfunc_set = {
+	.owner = THIS_MODULE,
+	.set = &rqspinlock_kfunc_ids,
+};
+
+static __init int rqspinlock_register_kfuncs(void)
+{
+	return register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, &rqspinlock_kfunc_set);
+}
+late_initcall(rqspinlock_register_kfuncs);
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:03 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:03 -0800
Subject: [PATCH bpf-next v3 23/25] bpf: Implement verifier support for rqspinlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-24-memxor@gmail.com>

Introduce verifier-side support for rqspinlock kfuncs. The first step is
allowing bpf_res_spin_lock type to be defined in map values and
allocated objects, so BTF-side is updated with a new BPF_RES_SPIN_LOCK
field to recognize and validate.

Any object cannot have both bpf_spin_lock and bpf_res_spin_lock, only
one of them (and at most one of them per-object, like before) must be
present. The bpf_res_spin_lock can also be used to protect objects that
require lock protection for their kfuncs, like BPF rbtree and linked
list.

The verifier plumbing to simulate success and failure cases when calling
the kfuncs is done by pushing a new verifier state to the verifier state
stack which will verify the failure case upon calling the kfunc. The
path where success is indicated creates all lock reference state and IRQ
state (if necessary for irqsave variants). In the case of failure, the
state clears the registers r0-r5, sets the return value, and skips kfunc
processing, proceeding to the next instruction.

When marking the return value for success case, the value is marked as
0, and for the failure case as [-MAX_ERRNO, -1]. Then, in the program,
whenever user checks the return value as 'if (ret)' or 'if (ret < 0)'
the verifier never traverses such branches for success cases, and would
be aware that the lock is not held in such cases.

We push the kfunc state in check_kfunc_call whenever rqspinlock kfuncs
are invoked. We introduce a kfunc_class state to avoid mixing lock
irqrestore kfuncs with IRQ state created by bpf_local_irq_save.

With all this infrastructure, these kfuncs become usable in programs
while satisfying all safety properties required by the kernel.

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/linux/bpf.h          |   9 ++
 include/linux/bpf_verifier.h |  16 ++-
 kernel/bpf/btf.c             |  26 ++++-
 kernel/bpf/syscall.c         |   6 +-
 kernel/bpf/verifier.c        | 219 ++++++++++++++++++++++++++++-------
 5 files changed, 231 insertions(+), 45 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index aa47e11371b3..ad4468422770 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -205,6 +205,7 @@ enum btf_field_type {
 	BPF_REFCOUNT   = (1 << 9),
 	BPF_WORKQUEUE  = (1 << 10),
 	BPF_UPTR       = (1 << 11),
+	BPF_RES_SPIN_LOCK = (1 << 12),
 };
 
 typedef void (*btf_dtor_kfunc_t)(void *);
@@ -240,6 +241,7 @@ struct btf_record {
 	u32 cnt;
 	u32 field_mask;
 	int spin_lock_off;
+	int res_spin_lock_off;
 	int timer_off;
 	int wq_off;
 	int refcount_off;
@@ -315,6 +317,8 @@ static inline const char *btf_field_type_name(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return "bpf_spin_lock";
+	case BPF_RES_SPIN_LOCK:
+		return "bpf_res_spin_lock";
 	case BPF_TIMER:
 		return "bpf_timer";
 	case BPF_WORKQUEUE:
@@ -347,6 +351,8 @@ static inline u32 btf_field_type_size(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return sizeof(struct bpf_spin_lock);
+	case BPF_RES_SPIN_LOCK:
+		return sizeof(struct bpf_res_spin_lock);
 	case BPF_TIMER:
 		return sizeof(struct bpf_timer);
 	case BPF_WORKQUEUE:
@@ -377,6 +383,8 @@ static inline u32 btf_field_type_align(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return __alignof__(struct bpf_spin_lock);
+	case BPF_RES_SPIN_LOCK:
+		return __alignof__(struct bpf_res_spin_lock);
 	case BPF_TIMER:
 		return __alignof__(struct bpf_timer);
 	case BPF_WORKQUEUE:
@@ -420,6 +428,7 @@ static inline void bpf_obj_init_field(const struct btf_field *field, void *addr)
 	case BPF_RB_ROOT:
 		/* RB_ROOT_CACHED 0-inits, no need to do anything after memset */
 	case BPF_SPIN_LOCK:
+	case BPF_RES_SPIN_LOCK:
 	case BPF_TIMER:
 	case BPF_WORKQUEUE:
 	case BPF_KPTR_UNREF:
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index d338f2a96bba..269449363f78 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -115,6 +115,14 @@ struct bpf_reg_state {
 			int depth:30;
 		} iter;
 
+		/* For irq stack slots */
+		struct {
+			enum {
+				IRQ_NATIVE_KFUNC,
+				IRQ_LOCK_KFUNC,
+			} kfunc_class;
+		} irq;
+
 		/* Max size from any of the above. */
 		struct {
 			unsigned long raw1;
@@ -255,9 +263,11 @@ struct bpf_reference_state {
 	 * default to pointer reference on zero initialization of a state.
 	 */
 	enum ref_state_type {
-		REF_TYPE_PTR	= 1,
-		REF_TYPE_IRQ	= 2,
-		REF_TYPE_LOCK	= 3,
+		REF_TYPE_PTR		= (1 << 1),
+		REF_TYPE_IRQ		= (1 << 2),
+		REF_TYPE_LOCK		= (1 << 3),
+		REF_TYPE_RES_LOCK 	= (1 << 4),
+		REF_TYPE_RES_LOCK_IRQ	= (1 << 5),
 	} type;
 	/* Track each reference created with a unique id, even if the same
 	 * instruction creates the reference multiple times (eg, via CALL).
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 519e3f5e9c10..f7a2bfb0c11a 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3481,6 +3481,15 @@ static int btf_get_field_type(const struct btf *btf, const struct btf_type *var_
 			goto end;
 		}
 	}
+	if (field_mask & BPF_RES_SPIN_LOCK) {
+		if (!strcmp(name, "bpf_res_spin_lock")) {
+			if (*seen_mask & BPF_RES_SPIN_LOCK)
+				return -E2BIG;
+			*seen_mask |= BPF_RES_SPIN_LOCK;
+			type = BPF_RES_SPIN_LOCK;
+			goto end;
+		}
+	}
 	if (field_mask & BPF_TIMER) {
 		if (!strcmp(name, "bpf_timer")) {
 			if (*seen_mask & BPF_TIMER)
@@ -3659,6 +3668,7 @@ static int btf_find_field_one(const struct btf *btf,
 
 	switch (field_type) {
 	case BPF_SPIN_LOCK:
+	case BPF_RES_SPIN_LOCK:
 	case BPF_TIMER:
 	case BPF_WORKQUEUE:
 	case BPF_LIST_NODE:
@@ -3952,6 +3962,7 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 		return ERR_PTR(-ENOMEM);
 
 	rec->spin_lock_off = -EINVAL;
+	rec->res_spin_lock_off = -EINVAL;
 	rec->timer_off = -EINVAL;
 	rec->wq_off = -EINVAL;
 	rec->refcount_off = -EINVAL;
@@ -3979,6 +3990,11 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 			/* Cache offset for faster lookup at runtime */
 			rec->spin_lock_off = rec->fields[i].offset;
 			break;
+		case BPF_RES_SPIN_LOCK:
+			WARN_ON_ONCE(rec->spin_lock_off >= 0);
+			/* Cache offset for faster lookup at runtime */
+			rec->res_spin_lock_off = rec->fields[i].offset;
+			break;
 		case BPF_TIMER:
 			WARN_ON_ONCE(rec->timer_off >= 0);
 			/* Cache offset for faster lookup at runtime */
@@ -4022,9 +4038,15 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 		rec->cnt++;
 	}
 
+	if (rec->spin_lock_off >= 0 && rec->res_spin_lock_off >= 0) {
+		ret = -EINVAL;
+		goto end;
+	}
+
 	/* bpf_{list_head, rb_node} require bpf_spin_lock */
 	if ((btf_record_has_field(rec, BPF_LIST_HEAD) ||
-	     btf_record_has_field(rec, BPF_RB_ROOT)) && rec->spin_lock_off < 0) {
+	     btf_record_has_field(rec, BPF_RB_ROOT)) &&
+		 (rec->spin_lock_off < 0 && rec->res_spin_lock_off < 0)) {
 		ret = -EINVAL;
 		goto end;
 	}
@@ -5637,7 +5659,7 @@ btf_parse_struct_metas(struct bpf_verifier_log *log, struct btf *btf)
 
 		type = &tab->types[tab->cnt];
 		type->btf_id = i;
-		record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE |
+		record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE |
 						  BPF_RB_ROOT | BPF_RB_NODE | BPF_REFCOUNT |
 						  BPF_KPTR, t->size);
 		/* The record cannot be unset, treat it as an error if so */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 57a438706215..5cf017e37d7d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -665,6 +665,7 @@ void btf_record_free(struct btf_record *rec)
 		case BPF_RB_ROOT:
 		case BPF_RB_NODE:
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 		case BPF_TIMER:
 		case BPF_REFCOUNT:
 		case BPF_WORKQUEUE:
@@ -717,6 +718,7 @@ struct btf_record *btf_record_dup(const struct btf_record *rec)
 		case BPF_RB_ROOT:
 		case BPF_RB_NODE:
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 		case BPF_TIMER:
 		case BPF_REFCOUNT:
 		case BPF_WORKQUEUE:
@@ -794,6 +796,7 @@ void bpf_obj_free_fields(const struct btf_record *rec, void *obj)
 
 		switch (fields[i].type) {
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 			break;
 		case BPF_TIMER:
 			bpf_timer_cancel_and_free(field_ptr);
@@ -1229,7 +1232,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
 		return -EINVAL;
 
 	map->record = btf_parse_fields(btf, value_type,
-				       BPF_SPIN_LOCK | BPF_TIMER | BPF_KPTR | BPF_LIST_HEAD |
+				       BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK | BPF_TIMER | BPF_KPTR | BPF_LIST_HEAD |
 				       BPF_RB_ROOT | BPF_REFCOUNT | BPF_WORKQUEUE | BPF_UPTR,
 				       map->value_size);
 	if (!IS_ERR_OR_NULL(map->record)) {
@@ -1248,6 +1251,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
 			case 0:
 				continue;
 			case BPF_SPIN_LOCK:
+			case BPF_RES_SPIN_LOCK:
 				if (map->map_type != BPF_MAP_TYPE_HASH &&
 				    map->map_type != BPF_MAP_TYPE_ARRAY &&
 				    map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index eb1624f6e743..6c8ef72ee6bc 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -456,7 +456,7 @@ static bool subprog_is_exc_cb(struct bpf_verifier_env *env, int subprog)
 
 static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
 {
-	return btf_record_has_field(reg_btf_record(reg), BPF_SPIN_LOCK);
+	return btf_record_has_field(reg_btf_record(reg), BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK);
 }
 
 static bool type_is_rdonly_mem(u32 type)
@@ -1148,7 +1148,8 @@ static int release_irq_state(struct bpf_verifier_state *state, int id);
 
 static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 				     struct bpf_kfunc_call_arg_meta *meta,
-				     struct bpf_reg_state *reg, int insn_idx)
+				     struct bpf_reg_state *reg, int insn_idx,
+				     int kfunc_class)
 {
 	struct bpf_func_state *state = func(env, reg);
 	struct bpf_stack_state *slot;
@@ -1170,6 +1171,7 @@ static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 	st->type = PTR_TO_STACK; /* we don't have dedicated reg type */
 	st->live |= REG_LIVE_WRITTEN;
 	st->ref_obj_id = id;
+	st->irq.kfunc_class = kfunc_class;
 
 	for (i = 0; i < BPF_REG_SIZE; i++)
 		slot->slot_type[i] = STACK_IRQ_FLAG;
@@ -1178,7 +1180,8 @@ static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 	return 0;
 }
 
-static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+				      int kfunc_class)
 {
 	struct bpf_func_state *state = func(env, reg);
 	struct bpf_stack_state *slot;
@@ -1192,6 +1195,15 @@ static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_r
 	slot = &state->stack[spi];
 	st = &slot->spilled_ptr;
 
+	if (st->irq.kfunc_class != kfunc_class) {
+		const char *flag_kfunc = st->irq.kfunc_class == IRQ_NATIVE_KFUNC ? "native" : "lock";
+		const char *used_kfunc = kfunc_class == IRQ_NATIVE_KFUNC ? "native" : "lock";
+
+		verbose(env, "irq flag acquired by %s kfuncs cannot be restored with %s kfuncs\n",
+			flag_kfunc, used_kfunc);
+		return -EINVAL;
+	}
+
 	err = release_irq_state(env->cur_state, st->ref_obj_id);
 	WARN_ON_ONCE(err && err != -EACCES);
 	if (err) {
@@ -1602,7 +1614,7 @@ static struct bpf_reference_state *find_lock_state(struct bpf_verifier_state *st
 	for (i = 0; i < state->acquired_refs; i++) {
 		struct bpf_reference_state *s = &state->refs[i];
 
-		if (s->type != type)
+		if (!(s->type & type))
 			continue;
 
 		if (s->id == id && s->ptr == ptr)
@@ -8063,6 +8075,12 @@ static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg
 	return err;
 }
 
+enum {
+	PROCESS_SPIN_LOCK = (1 << 0),
+	PROCESS_RES_LOCK  = (1 << 1),
+	PROCESS_LOCK_IRQ  = (1 << 2),
+};
+
 /* Implementation details:
  * bpf_map_lookup returns PTR_TO_MAP_VALUE_OR_NULL.
  * bpf_obj_new returns PTR_TO_BTF_ID | MEM_ALLOC | PTR_MAYBE_NULL.
@@ -8085,30 +8103,33 @@ static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg
  * env->cur_state->active_locks remembers which map value element or allocated
  * object got locked and clears it after bpf_spin_unlock.
  */
-static int process_spin_lock(struct bpf_verifier_env *env, int regno,
-			     bool is_lock)
+static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
 {
+	bool is_lock = flags & PROCESS_SPIN_LOCK, is_res_lock = flags & PROCESS_RES_LOCK;
+	const char *lock_str = is_res_lock ? "bpf_res_spin" : "bpf_spin";
 	struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
 	struct bpf_verifier_state *cur = env->cur_state;
 	bool is_const = tnum_is_const(reg->var_off);
+	bool is_irq = flags & PROCESS_LOCK_IRQ;
 	u64 val = reg->var_off.value;
 	struct bpf_map *map = NULL;
 	struct btf *btf = NULL;
 	struct btf_record *rec;
+	u32 spin_lock_off;
 	int err;
 
 	if (!is_const) {
 		verbose(env,
-			"R%d doesn't have constant offset. bpf_spin_lock has to be at the constant offset\n",
-			regno);
+			"R%d doesn't have constant offset. %s_lock has to be at the constant offset\n",
+			regno, lock_str);
 		return -EINVAL;
 	}
 	if (reg->type == PTR_TO_MAP_VALUE) {
 		map = reg->map_ptr;
 		if (!map->btf) {
 			verbose(env,
-				"map '%s' has to have BTF in order to use bpf_spin_lock\n",
-				map->name);
+				"map '%s' has to have BTF in order to use %s_lock\n",
+				map->name, lock_str);
 			return -EINVAL;
 		}
 	} else {
@@ -8116,36 +8137,53 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
 	}
 
 	rec = reg_btf_record(reg);
-	if (!btf_record_has_field(rec, BPF_SPIN_LOCK)) {
-		verbose(env, "%s '%s' has no valid bpf_spin_lock\n", map ? "map" : "local",
-			map ? map->name : "kptr");
+	if (!btf_record_has_field(rec, is_res_lock ? BPF_RES_SPIN_LOCK : BPF_SPIN_LOCK)) {
+		verbose(env, "%s '%s' has no valid %s_lock\n", map ? "map" : "local",
+			map ? map->name : "kptr", lock_str);
 		return -EINVAL;
 	}
-	if (rec->spin_lock_off != val + reg->off) {
-		verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock' that is at %d\n",
-			val + reg->off, rec->spin_lock_off);
+	spin_lock_off = is_res_lock ? rec->res_spin_lock_off : rec->spin_lock_off;
+	if (spin_lock_off != val + reg->off) {
+		verbose(env, "off %lld doesn't point to 'struct %s_lock' that is at %d\n",
+			val + reg->off, lock_str, spin_lock_off);
 		return -EINVAL;
 	}
 	if (is_lock) {
 		void *ptr;
+		int type;
 
 		if (map)
 			ptr = map;
 		else
 			ptr = btf;
 
-		if (cur->active_locks) {
-			verbose(env,
-				"Locking two bpf_spin_locks are not allowed\n");
-			return -EINVAL;
+		if (!is_res_lock && cur->active_locks) {
+			if (find_lock_state(env->cur_state, REF_TYPE_LOCK, 0, NULL)) {
+				verbose(env,
+					"Locking two bpf_spin_locks are not allowed\n");
+				return -EINVAL;
+			}
+		} else if (is_res_lock && cur->active_locks) {
+			if (find_lock_state(env->cur_state, REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ, reg->id, ptr)) {
+				verbose(env, "Acquiring the same lock again, AA deadlock detected\n");
+				return -EINVAL;
+			}
 		}
-		err = acquire_lock_state(env, env->insn_idx, REF_TYPE_LOCK, reg->id, ptr);
+
+		if (is_res_lock && is_irq)
+			type = REF_TYPE_RES_LOCK_IRQ;
+		else if (is_res_lock)
+			type = REF_TYPE_RES_LOCK;
+		else
+			type = REF_TYPE_LOCK;
+		err = acquire_lock_state(env, env->insn_idx, type, reg->id, ptr);
 		if (err < 0) {
 			verbose(env, "Failed to acquire lock state\n");
 			return err;
 		}
 	} else {
 		void *ptr;
+		int type;
 
 		if (map)
 			ptr = map;
@@ -8153,12 +8191,18 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
 			ptr = btf;
 
 		if (!cur->active_locks) {
-			verbose(env, "bpf_spin_unlock without taking a lock\n");
+			verbose(env, "%s_unlock without taking a lock\n", lock_str);
 			return -EINVAL;
 		}
 
-		if (release_lock_state(env->cur_state, REF_TYPE_LOCK, reg->id, ptr)) {
-			verbose(env, "bpf_spin_unlock of different lock\n");
+		if (is_res_lock && is_irq)
+			type = REF_TYPE_RES_LOCK_IRQ;
+		else if (is_res_lock)
+			type = REF_TYPE_RES_LOCK;
+		else
+			type = REF_TYPE_LOCK;
+		if (release_lock_state(cur, type, reg->id, ptr)) {
+			verbose(env, "%s_unlock of different lock\n", lock_str);
 			return -EINVAL;
 		}
 
@@ -9484,11 +9528,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 			return -EACCES;
 		}
 		if (meta->func_id == BPF_FUNC_spin_lock) {
-			err = process_spin_lock(env, regno, true);
+			err = process_spin_lock(env, regno, PROCESS_SPIN_LOCK);
 			if (err)
 				return err;
 		} else if (meta->func_id == BPF_FUNC_spin_unlock) {
-			err = process_spin_lock(env, regno, false);
+			err = process_spin_lock(env, regno, 0);
 			if (err)
 				return err;
 		} else {
@@ -11370,7 +11414,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 		regs[BPF_REG_0].map_uid = meta.map_uid;
 		regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag;
 		if (!type_may_be_null(ret_flag) &&
-		    btf_record_has_field(meta.map_ptr->record, BPF_SPIN_LOCK)) {
+		    btf_record_has_field(meta.map_ptr->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
 			regs[BPF_REG_0].id = ++env->id_gen;
 		}
 		break;
@@ -11542,10 +11586,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 /* mark_btf_func_reg_size() is used when the reg size is determined by
  * the BTF func_proto's return value size and argument.
  */
-static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
-				   size_t reg_size)
+static void __mark_btf_func_reg_size(struct bpf_verifier_env *env, struct bpf_reg_state *regs,
+				     u32 regno, size_t reg_size)
 {
-	struct bpf_reg_state *reg = &cur_regs(env)[regno];
+	struct bpf_reg_state *reg = &regs[regno];
 
 	if (regno == BPF_REG_0) {
 		/* Function return value */
@@ -11563,6 +11607,12 @@ static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
 	}
 }
 
+static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
+				   size_t reg_size)
+{
+	return __mark_btf_func_reg_size(env, cur_regs(env), regno, reg_size);
+}
+
 static bool is_kfunc_acquire(struct bpf_kfunc_call_arg_meta *meta)
 {
 	return meta->kfunc_flags & KF_ACQUIRE;
@@ -11700,6 +11750,7 @@ enum {
 	KF_ARG_RB_ROOT_ID,
 	KF_ARG_RB_NODE_ID,
 	KF_ARG_WORKQUEUE_ID,
+	KF_ARG_RES_SPIN_LOCK_ID,
 };
 
 BTF_ID_LIST(kf_arg_btf_ids)
@@ -11709,6 +11760,7 @@ BTF_ID(struct, bpf_list_node)
 BTF_ID(struct, bpf_rb_root)
 BTF_ID(struct, bpf_rb_node)
 BTF_ID(struct, bpf_wq)
+BTF_ID(struct, bpf_res_spin_lock)
 
 static bool __is_kfunc_ptr_arg_type(const struct btf *btf,
 				    const struct btf_param *arg, int type)
@@ -11757,6 +11809,11 @@ static bool is_kfunc_arg_wq(const struct btf *btf, const struct btf_param *arg)
 	return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_WORKQUEUE_ID);
 }
 
+static bool is_kfunc_arg_res_spin_lock(const struct btf *btf, const struct btf_param *arg)
+{
+	return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_RES_SPIN_LOCK_ID);
+}
+
 static bool is_kfunc_arg_callback(struct bpf_verifier_env *env, const struct btf *btf,
 				  const struct btf_param *arg)
 {
@@ -11828,6 +11885,7 @@ enum kfunc_ptr_arg_type {
 	KF_ARG_PTR_TO_MAP,
 	KF_ARG_PTR_TO_WORKQUEUE,
 	KF_ARG_PTR_TO_IRQ_FLAG,
+	KF_ARG_PTR_TO_RES_SPIN_LOCK,
 };
 
 enum special_kfunc_type {
@@ -11866,6 +11924,10 @@ enum special_kfunc_type {
 	KF_bpf_iter_num_destroy,
 	KF_bpf_set_dentry_xattr,
 	KF_bpf_remove_dentry_xattr,
+	KF_bpf_res_spin_lock,
+	KF_bpf_res_spin_unlock,
+	KF_bpf_res_spin_lock_irqsave,
+	KF_bpf_res_spin_unlock_irqrestore,
 };
 
 BTF_SET_START(special_kfunc_set)
@@ -11955,6 +12017,10 @@ BTF_ID(func, bpf_remove_dentry_xattr)
 BTF_ID_UNUSED
 BTF_ID_UNUSED
 #endif
+BTF_ID(func, bpf_res_spin_lock)
+BTF_ID(func, bpf_res_spin_unlock)
+BTF_ID(func, bpf_res_spin_lock_irqsave)
+BTF_ID(func, bpf_res_spin_unlock_irqrestore)
 
 static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
 {
@@ -12048,6 +12114,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
 	if (is_kfunc_arg_irq_flag(meta->btf, &args[argno]))
 		return KF_ARG_PTR_TO_IRQ_FLAG;
 
+	if (is_kfunc_arg_res_spin_lock(meta->btf, &args[argno]))
+		return KF_ARG_PTR_TO_RES_SPIN_LOCK;
+
 	if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) {
 		if (!btf_type_is_struct(ref_t)) {
 			verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n",
@@ -12155,13 +12224,19 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 			     struct bpf_kfunc_call_arg_meta *meta)
 {
 	struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
+	int err, kfunc_class = IRQ_NATIVE_KFUNC;
 	bool irq_save;
-	int err;
 
-	if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_save]) {
+	if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_save] ||
+	    meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave]) {
 		irq_save = true;
-	} else if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_restore]) {
+		if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])
+			kfunc_class = IRQ_LOCK_KFUNC;
+	} else if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_restore] ||
+		   meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore]) {
 		irq_save = false;
+		if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore])
+			kfunc_class = IRQ_LOCK_KFUNC;
 	} else {
 		verbose(env, "verifier internal error: unknown irq flags kfunc\n");
 		return -EFAULT;
@@ -12177,7 +12252,7 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 		if (err)
 			return err;
 
-		err = mark_stack_slot_irq_flag(env, meta, reg, env->insn_idx);
+		err = mark_stack_slot_irq_flag(env, meta, reg, env->insn_idx, kfunc_class);
 		if (err)
 			return err;
 	} else {
@@ -12191,7 +12266,7 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 		if (err)
 			return err;
 
-		err = unmark_stack_slot_irq_flag(env, reg);
+		err = unmark_stack_slot_irq_flag(env, reg, kfunc_class);
 		if (err)
 			return err;
 	}
@@ -12318,7 +12393,8 @@ static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_
 
 	if (!env->cur_state->active_locks)
 		return -EINVAL;
-	s = find_lock_state(env->cur_state, REF_TYPE_LOCK, id, ptr);
+	s = find_lock_state(env->cur_state, REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
+			    id, ptr);
 	if (!s) {
 		verbose(env, "held lock and object are not in the same allocation\n");
 		return -EINVAL;
@@ -12354,9 +12430,18 @@ static bool is_bpf_graph_api_kfunc(u32 btf_id)
 	       btf_id == special_kfunc_list[KF_bpf_refcount_acquire_impl];
 }
 
+static bool is_bpf_res_spin_lock_kfunc(u32 btf_id)
+{
+	return btf_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_unlock] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore];
+}
+
 static bool kfunc_spin_allowed(u32 btf_id)
 {
-	return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id);
+	return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id) ||
+	       is_bpf_res_spin_lock_kfunc(btf_id);
 }
 
 static bool is_sync_callback_calling_kfunc(u32 btf_id)
@@ -12788,6 +12873,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
 		case KF_ARG_PTR_TO_CONST_STR:
 		case KF_ARG_PTR_TO_WORKQUEUE:
 		case KF_ARG_PTR_TO_IRQ_FLAG:
+		case KF_ARG_PTR_TO_RES_SPIN_LOCK:
 			break;
 		default:
 			WARN_ON_ONCE(1);
@@ -13086,6 +13172,28 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
 			if (ret < 0)
 				return ret;
 			break;
+		case KF_ARG_PTR_TO_RES_SPIN_LOCK:
+		{
+			int flags = PROCESS_RES_LOCK;
+
+			if (reg->type != PTR_TO_MAP_VALUE && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
+				verbose(env, "arg#%d doesn't point to map value or allocated object\n", i);
+				return -EINVAL;
+			}
+
+			if (!is_bpf_res_spin_lock_kfunc(meta->func_id))
+				return -EFAULT;
+			if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+			    meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])
+				flags |= PROCESS_SPIN_LOCK;
+			if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave] ||
+			    meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore])
+				flags |= PROCESS_LOCK_IRQ;
+			ret = process_spin_lock(env, regno, flags);
+			if (ret < 0)
+				return ret;
+			break;
+		}
 		}
 	}
 
@@ -13171,6 +13279,33 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 
 	insn_aux->is_iter_next = is_iter_next_kfunc(&meta);
 
+	if (!insn->off &&
+	    (insn->imm == special_kfunc_list[KF_bpf_res_spin_lock] ||
+	     insn->imm == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])) {
+		struct bpf_verifier_state *branch;
+		struct bpf_reg_state *regs;
+
+		branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
+		if (!branch) {
+			verbose(env, "failed to push state for failed lock acquisition\n");
+			return -ENOMEM;
+		}
+
+		regs = branch->frame[branch->curframe]->regs;
+
+		/* Clear r0-r5 registers in forked state */
+		for (i = 0; i < CALLER_SAVED_REGS; i++)
+			mark_reg_not_init(env, regs, caller_saved[i]);
+
+		mark_reg_unknown(env, regs, BPF_REG_0);
+		err = __mark_reg_s32_range(env, regs, BPF_REG_0, -MAX_ERRNO, -1);
+		if (err) {
+			verbose(env, "failed to mark s32 range for retval in forked state for lock\n");
+			return err;
+		}
+		__mark_btf_func_reg_size(env, regs, BPF_REG_0, sizeof(u32));
+	}
+
 	if (is_kfunc_destructive(&meta) && !capable(CAP_SYS_BOOT)) {
 		verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capability\n");
 		return -EACCES;
@@ -13341,6 +13476,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 
 	if (btf_type_is_scalar(t)) {
 		mark_reg_unknown(env, regs, BPF_REG_0);
+		if (meta.btf == btf_vmlinux && (meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+		    meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave]))
+			__mark_reg_const_zero(env, &regs[BPF_REG_0]);
 		mark_btf_func_reg_size(env, BPF_REG_0, t->size);
 	} else if (btf_type_is_ptr(t)) {
 		ptr_type = btf_type_skip_modifiers(desc_btf, t->type, &ptr_type_id);
@@ -18275,7 +18413,8 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
 		case STACK_IRQ_FLAG:
 			old_reg = &old->stack[spi].spilled_ptr;
 			cur_reg = &cur->stack[spi].spilled_ptr;
-			if (!check_ids(old_reg->ref_obj_id, cur_reg->ref_obj_id, idmap))
+			if (!check_ids(old_reg->ref_obj_id, cur_reg->ref_obj_id, idmap) ||
+			    old_reg->irq.kfunc_class != cur_reg->irq.kfunc_class)
 				return false;
 			break;
 		case STACK_MISC:
@@ -18319,6 +18458,8 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
 		case REF_TYPE_IRQ:
 			break;
 		case REF_TYPE_LOCK:
+		case REF_TYPE_RES_LOCK:
+		case REF_TYPE_RES_LOCK_IRQ:
 			if (old->refs[i].ptr != cur->refs[i].ptr)
 				return false;
 			break;
@@ -19641,7 +19782,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 		}
 	}
 
-	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
+	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
 		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
 			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
 			return -EINVAL;
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:04 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:04 -0800
Subject: [PATCH bpf-next v3 24/25] bpf: Maintain FIFO property for rqspinlock unlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-25-memxor@gmail.com>

Since out-of-order unlocks are unsupported for rqspinlock, and irqsave
variants enforce strict FIFO ordering anyway, make the same change for
normal non-irqsave variants, such that FIFO ordering is enforced.

Two new verifier state fields (active_lock_id, active_lock_ptr) are used
to denote the top of the stack, and prev_id and prev_ptr are ascertained
whenever popping the topmost entry through an unlock.

Take special care to make these fields part of the state comparison in
refsafe.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/linux/bpf_verifier.h |  3 +++
 kernel/bpf/verifier.c        | 33 ++++++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 269449363f78..7348bd824e16 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -268,6 +268,7 @@ struct bpf_reference_state {
 		REF_TYPE_LOCK		= (1 << 3),
 		REF_TYPE_RES_LOCK 	= (1 << 4),
 		REF_TYPE_RES_LOCK_IRQ	= (1 << 5),
+		REF_TYPE_LOCK_MASK	= REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
 	} type;
 	/* Track each reference created with a unique id, even if the same
 	 * instruction creates the reference multiple times (eg, via CALL).
@@ -434,6 +435,8 @@ struct bpf_verifier_state {
 	u32 active_locks;
 	u32 active_preempt_locks;
 	u32 active_irq_id;
+	u32 active_lock_id;
+	void *active_lock_ptr;
 	bool active_rcu_lock;
 
 	bool speculative;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 6c8ef72ee6bc..d3be8932abe4 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1421,6 +1421,8 @@ static int copy_reference_state(struct bpf_verifier_state *dst, const struct bpf
 	dst->active_preempt_locks = src->active_preempt_locks;
 	dst->active_rcu_lock = src->active_rcu_lock;
 	dst->active_irq_id = src->active_irq_id;
+	dst->active_lock_id = src->active_lock_id;
+	dst->active_lock_ptr = src->active_lock_ptr;
 	return 0;
 }
 
@@ -1520,6 +1522,8 @@ static int acquire_lock_state(struct bpf_verifier_env *env, int insn_idx, enum r
 	s->ptr = ptr;
 
 	state->active_locks++;
+	state->active_lock_id = id;
+	state->active_lock_ptr = ptr;
 	return 0;
 }
 
@@ -1570,16 +1574,24 @@ static bool find_reference_state(struct bpf_verifier_state *state, int ptr_id)
 
 static int release_lock_state(struct bpf_verifier_state *state, int type, int id, void *ptr)
 {
+	void *prev_ptr = NULL;
+	u32 prev_id = 0;
 	int i;
 
 	for (i = 0; i < state->acquired_refs; i++) {
-		if (state->refs[i].type != type)
-			continue;
-		if (state->refs[i].id == id && state->refs[i].ptr == ptr) {
+		if (state->refs[i].type == type && state->refs[i].id == id &&
+		    state->refs[i].ptr == ptr) {
 			release_reference_state(state, i);
 			state->active_locks--;
+			/* Reassign active lock (id, ptr). */
+			state->active_lock_id = prev_id;
+			state->active_lock_ptr = prev_ptr;
 			return 0;
 		}
+		if (state->refs[i].type & REF_TYPE_LOCK_MASK) {
+			prev_id = state->refs[i].id;
+			prev_ptr = state->refs[i].ptr;
+		}
 	}
 	return -EINVAL;
 }
@@ -8201,6 +8213,14 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
 			type = REF_TYPE_RES_LOCK;
 		else
 			type = REF_TYPE_LOCK;
+		if (!find_lock_state(cur, type, reg->id, ptr)) {
+			verbose(env, "%s_unlock of different lock\n", lock_str);
+			return -EINVAL;
+		}
+		if (reg->id != cur->active_lock_id || ptr != cur->active_lock_ptr) {
+			verbose(env, "%s_unlock cannot be out of order\n", lock_str);
+			return -EINVAL;
+		}
 		if (release_lock_state(cur, type, reg->id, ptr)) {
 			verbose(env, "%s_unlock of different lock\n", lock_str);
 			return -EINVAL;
@@ -12393,8 +12413,7 @@ static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_
 
 	if (!env->cur_state->active_locks)
 		return -EINVAL;
-	s = find_lock_state(env->cur_state, REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
-			    id, ptr);
+	s = find_lock_state(env->cur_state, REF_TYPE_LOCK_MASK, id, ptr);
 	if (!s) {
 		verbose(env, "held lock and object are not in the same allocation\n");
 		return -EINVAL;
@@ -18449,6 +18468,10 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
 	if (!check_ids(old->active_irq_id, cur->active_irq_id, idmap))
 		return false;
 
+	if (!check_ids(old->active_lock_id, cur->active_lock_id, idmap) ||
+	    old->active_lock_ptr != cur->active_lock_ptr)
+		return false;
+
 	for (i = 0; i < old->acquired_refs; i++) {
 		if (!check_ids(old->refs[i].id, cur->refs[i].id, idmap) ||
 		    old->refs[i].type != cur->refs[i].type)
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:23:05 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:23:05 -0800
Subject: [PATCH bpf-next v3 25/25] selftests/bpf: Add tests for rqspinlock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-26-memxor@gmail.com>

Introduce selftests that trigger AA, ABBA deadlocks, and test the edge
case where the held locks table runs out of entries, since we then
fallback to the timeout as the final line of defense. Also exercise
verifier's AA detection where applicable.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 .../selftests/bpf/prog_tests/res_spin_lock.c  |  92 +++++++
 tools/testing/selftests/bpf/progs/irq.c       |  53 ++++
 .../selftests/bpf/progs/res_spin_lock.c       | 143 ++++++++++
 .../selftests/bpf/progs/res_spin_lock_fail.c  | 244 ++++++++++++++++++
 4 files changed, 532 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock_fail.c

diff --git a/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c b/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
new file mode 100644
index 000000000000..563d0d2801bb
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+#include <test_progs.h>
+#include <network_helpers.h>
+
+#include "res_spin_lock.skel.h"
+#include "res_spin_lock_fail.skel.h"
+
+void test_res_spin_lock_failure(void)
+{
+	RUN_TESTS(res_spin_lock_fail);
+}
+
+static volatile int skip;
+
+static void *spin_lock_thread(void *arg)
+{
+	int err, prog_fd = *(u32 *) arg;
+	LIBBPF_OPTS(bpf_test_run_opts, topts,
+		.data_in = &pkt_v4,
+		.data_size_in = sizeof(pkt_v4),
+		.repeat = 10000,
+	);
+
+	while (!READ_ONCE(skip)) {
+		err = bpf_prog_test_run_opts(prog_fd, &topts);
+		ASSERT_OK(err, "test_run");
+		ASSERT_OK(topts.retval, "test_run retval");
+	}
+	pthread_exit(arg);
+}
+
+void test_res_spin_lock_success(void)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts,
+		.data_in = &pkt_v4,
+		.data_size_in = sizeof(pkt_v4),
+		.repeat = 1,
+	);
+	struct res_spin_lock *skel;
+	pthread_t thread_id[16];
+	int prog_fd, i, err;
+	void *ret;
+
+	skel = res_spin_lock__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "res_spin_lock__open_and_load"))
+		return;
+	/* AA deadlock */
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	ASSERT_OK(err, "error");
+	ASSERT_OK(topts.retval, "retval");
+
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_held_lock_max);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	ASSERT_OK(err, "error");
+	ASSERT_OK(topts.retval, "retval");
+
+	/* Multi-threaded ABBA deadlock. */
+
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_AB);
+	for (i = 0; i < 16; i++) {
+		int err;
+
+		err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd);
+		if (!ASSERT_OK(err, "pthread_create"))
+			goto end;
+	}
+
+	topts.retval = 0;
+	topts.repeat = 1000;
+	int fd = bpf_program__fd(skel->progs.res_spin_lock_test_BA);
+	while (!topts.retval && !err && !READ_ONCE(skel->bss->err)) {
+		err = bpf_prog_test_run_opts(fd, &topts);
+	}
+
+	WRITE_ONCE(skip, true);
+
+	for (i = 0; i < 16; i++) {
+		if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join"))
+			goto end;
+		if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd"))
+			goto end;
+	}
+
+	ASSERT_EQ(READ_ONCE(skel->bss->err), -EDEADLK, "timeout err");
+	ASSERT_OK(err, "err");
+	ASSERT_EQ(topts.retval, -EDEADLK, "timeout");
+end:
+	res_spin_lock__destroy(skel);
+	return;
+}
diff --git a/tools/testing/selftests/bpf/progs/irq.c b/tools/testing/selftests/bpf/progs/irq.c
index 298d48d7886d..74d912b22de9 100644
--- a/tools/testing/selftests/bpf/progs/irq.c
+++ b/tools/testing/selftests/bpf/progs/irq.c
@@ -11,6 +11,9 @@ extern void bpf_local_irq_save(unsigned long *) __weak __ksym;
 extern void bpf_local_irq_restore(unsigned long *) __weak __ksym;
 extern int bpf_copy_from_user_str(void *dst, u32 dst__sz, const void *unsafe_ptr__ign, u64 flags) __weak __ksym;
 
+struct bpf_res_spin_lock lockA __hidden SEC(".data.A");
+struct bpf_res_spin_lock lockB __hidden SEC(".data.B");
+
 SEC("?tc")
 __failure __msg("arg#0 doesn't point to an irq flag on stack")
 int irq_save_bad_arg(struct __sk_buff *ctx)
@@ -510,4 +513,54 @@ int irq_sleepable_global_subprog_indirect(void *ctx)
 	return 0;
 }
 
+SEC("?tc")
+__failure __msg("cannot restore irq state out of order")
+int irq_ooo_lock_cond_inv(struct __sk_buff *ctx)
+{
+	unsigned long flags1, flags2;
+
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags1))
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&lockB, &flags2)) {
+		bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+		return 0;
+	}
+
+	bpf_res_spin_unlock_irqrestore(&lockB, &flags1);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags2);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("function calls are not allowed")
+int irq_wrong_kfunc_class_1(struct __sk_buff *ctx)
+{
+	unsigned long flags1;
+
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags1))
+		return 0;
+	/* For now, bpf_local_irq_restore is not allowed in critical section,
+	 * but this test ensures error will be caught with kfunc_class when it's
+	 * opened up. Tested by temporarily permitting this kfunc in critical
+	 * section.
+	 */
+	bpf_local_irq_restore(&flags1);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("function calls are not allowed")
+int irq_wrong_kfunc_class_2(struct __sk_buff *ctx)
+{
+	unsigned long flags1, flags2;
+
+	bpf_local_irq_save(&flags1);
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags2))
+		return 0;
+	bpf_local_irq_restore(&flags2);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/res_spin_lock.c b/tools/testing/selftests/bpf/progs/res_spin_lock.c
new file mode 100644
index 000000000000..40ac06c91779
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/res_spin_lock.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+#define EDEADLK 35
+#define ETIMEDOUT 110
+
+struct arr_elem {
+	struct bpf_res_spin_lock lock;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 64);
+	__type(key, int);
+	__type(value, struct arr_elem);
+} arrmap SEC(".maps");
+
+struct bpf_res_spin_lock lockA __hidden SEC(".data.A");
+struct bpf_res_spin_lock lockB __hidden SEC(".data.B");
+
+SEC("tc")
+int res_spin_lock_test(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem1, *elem2;
+	int r;
+
+	elem1 = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem1)
+		return -1;
+	elem2 = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem2)
+		return -1;
+
+	r = bpf_res_spin_lock(&elem1->lock);
+	if (r)
+		return r;
+	if (!bpf_res_spin_lock(&elem2->lock)) {
+		bpf_res_spin_unlock(&elem2->lock);
+		bpf_res_spin_unlock(&elem1->lock);
+		return -1;
+	}
+	bpf_res_spin_unlock(&elem1->lock);
+	return 0;
+}
+
+SEC("tc")
+int res_spin_lock_test_AB(struct __sk_buff *ctx)
+{
+	int r;
+
+	r = bpf_res_spin_lock(&lockA);
+	if (r)
+		return !r;
+	/* Only unlock if we took the lock. */
+	if (!bpf_res_spin_lock(&lockB))
+		bpf_res_spin_unlock(&lockB);
+	bpf_res_spin_unlock(&lockA);
+	return 0;
+}
+
+int err;
+
+SEC("tc")
+int res_spin_lock_test_BA(struct __sk_buff *ctx)
+{
+	int r;
+
+	r = bpf_res_spin_lock(&lockB);
+	if (r)
+		return !r;
+	if (!bpf_res_spin_lock(&lockA))
+		bpf_res_spin_unlock(&lockA);
+	else
+		err = -EDEADLK;
+	bpf_res_spin_unlock(&lockB);
+	return err ?: 0;
+}
+
+SEC("tc")
+int res_spin_lock_test_held_lock_max(struct __sk_buff *ctx)
+{
+	struct bpf_res_spin_lock *locks[48] = {};
+	struct arr_elem *e;
+	u64 time_beg, time;
+	int ret = 0, i;
+
+	_Static_assert(ARRAY_SIZE(((struct rqspinlock_held){}).locks) == 31,
+		       "RES_NR_HELD assumed to be 31");
+
+	for (i = 0; i < 34; i++) {
+		int key = i;
+
+		/* We cannot pass in i as it will get spilled/filled by the compiler and
+		 * loses bounds in verifier state.
+		 */
+		e = bpf_map_lookup_elem(&arrmap, &key);
+		if (!e)
+			return 1;
+		locks[i] = &e->lock;
+	}
+
+	for (; i < 48; i++) {
+		int key = i - 2;
+
+		/* We cannot pass in i as it will get spilled/filled by the compiler and
+		 * loses bounds in verifier state.
+		 */
+		e = bpf_map_lookup_elem(&arrmap, &key);
+		if (!e)
+			return 1;
+		locks[i] = &e->lock;
+	}
+
+	time_beg = bpf_ktime_get_ns();
+	for (i = 0; i < 34; i++) {
+		if (bpf_res_spin_lock(locks[i]))
+			goto end;
+	}
+
+	/* Trigger AA, after exhausting entries in the held lock table. This
+	 * time, only the timeout can save us, as AA detection won't succeed.
+	 */
+	if (!bpf_res_spin_lock(locks[34])) {
+		bpf_res_spin_unlock(locks[34]);
+		ret = 1;
+		goto end;
+	}
+
+end:
+	for (i = i - 1; i >= 0; i--)
+		bpf_res_spin_unlock(locks[i]);
+	time = bpf_ktime_get_ns() - time_beg;
+	/* Time spent should be easily above our limit (1/4 s), since AA
+	 * detection won't be expedited due to lack of held lock entry.
+	 */
+	return ret ?: (time > 1000000000 / 4 ? 0 : 1);
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c b/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c
new file mode 100644
index 000000000000..3222e9283c78
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
+#include "bpf_experimental.h"
+
+struct arr_elem {
+	struct bpf_res_spin_lock lock;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 1);
+	__type(key, int);
+	__type(value, struct arr_elem);
+} arrmap SEC(".maps");
+
+long value;
+
+struct bpf_spin_lock lock __hidden SEC(".data.A");
+struct bpf_res_spin_lock res_lock __hidden SEC(".data.B");
+
+SEC("?tc")
+__failure __msg("point to map value or allocated object")
+int res_spin_lock_arg(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock((struct bpf_res_spin_lock *)bpf_core_cast(&elem->lock, struct __sk_buff));
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("AA deadlock detected")
+int res_spin_lock_AA(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock(&elem->lock);
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("AA deadlock detected")
+int res_spin_lock_cond_AA(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock))
+		return 0;
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_mismatch_1(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock))
+		return 0;
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_mismatch_2(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	bpf_res_spin_unlock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_irq_mismatch_1(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_local_irq_save(&f1);
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_irq_mismatch_2(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&res_lock, &f1))
+		return 0;
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__success
+int res_spin_lock_ooo(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock)) {
+		bpf_res_spin_unlock(&res_lock);
+		return 0;
+	}
+	bpf_res_spin_unlock(&elem->lock);
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__success
+int res_spin_lock_ooo_irq(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1, f2;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&res_lock, &f1))
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&elem->lock, &f2)) {
+		bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+		/* We won't have a unreleased IRQ flag error here. */
+		return 0;
+	}
+	bpf_res_spin_unlock_irqrestore(&elem->lock, &f2);
+	bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+	return 0;
+}
+
+struct bpf_res_spin_lock lock1 __hidden SEC(".data.OO1");
+struct bpf_res_spin_lock lock2 __hidden SEC(".data.OO2");
+
+SEC("?tc")
+__failure __msg("bpf_res_spin_unlock cannot be out of order")
+int res_spin_lock_ooo_unlock(struct __sk_buff *ctx)
+{
+	if (bpf_res_spin_lock(&lock1))
+		return 0;
+	if (bpf_res_spin_lock(&lock2)) {
+		bpf_res_spin_unlock(&lock1);
+		return 0;
+	}
+	bpf_res_spin_unlock(&lock1);
+	bpf_res_spin_unlock(&lock2);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("off 1 doesn't point to 'struct bpf_res_spin_lock' that is at 0")
+int res_spin_lock_bad_off(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock((void *)&elem->lock + 1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("R1 doesn't have constant offset. bpf_res_spin_lock has to be at the constant offset")
+int res_spin_lock_var_off(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	u64 val = value;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem) {
+		// FIXME: Only inline assembly use in assert macro doesn't emit
+		//	  BTF definition.
+		bpf_throw(0);
+		return 0;
+	}
+	bpf_assert_range(val, 0, 40);
+	bpf_res_spin_lock((void *)&value + val);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("map 'res_spin.bss' has no valid bpf_res_spin_lock")
+int res_spin_lock_no_lock_map(struct __sk_buff *ctx)
+{
+	bpf_res_spin_lock((void *)&value + 1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("local 'kptr' has no valid bpf_res_spin_lock")
+int res_spin_lock_no_lock_kptr(struct __sk_buff *ctx)
+{
+	struct { int i; } *p = bpf_obj_new(typeof(*p));
+
+	if (!p)
+		return 0;
+	bpf_res_spin_lock((void *)p);
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.43.5



From nicolas at ndufresne.ca  Mon Mar  3 07:24:32 2025
From: nicolas at ndufresne.ca (Nicolas Dufresne)
Date: Mon, 03 Mar 2025 10:24:32 -0500
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in
 dma-contig
In-Reply-To: <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
	 <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>
Message-ID: <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>

Hi Mikhail,

Le lundi 03 mars 2025 ? 14:40 +0300, Mikhail Rudenko a ?crit?:
> When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
> commit 129134e5415d ("media: media/v4l2: remove
> V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
> no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
> introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
> V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
> no-ops, making cache maintenance for non-coherent dmabufs allocated
> by
> dma-contig impossible.
> 
> Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
> {flush,invalidate}_kernel_vmap_range calls to
> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
> buffers.
> 
> Fixes: c0acf9cfeee0 ("media: videobuf2: handle
> V4L2_MEMORY_FLAG_NON_COHERENT flag")
> Cc: stable at vger.kernel.org
> Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
> ---
> ?.../media/common/videobuf2/videobuf2-dma-contig.c? | 22
> ++++++++++++++++++++++
> ?1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> index
> a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7
> bc888a84a95d5 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> @@ -427,6 +427,17 @@ static int
> ?vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
> ?				?? enum dma_data_direction
> direction)
> ?{
> +	struct vb2_dc_buf *buf = dbuf->priv;
> +	struct sg_table *sgt = buf->dma_sgt;
> +
> +	if (!buf->non_coherent_mem)
> +		return 0;
> +
> +	if (buf->vaddr)
> +		invalidate_kernel_vmap_range(buf->vaddr, buf->size);

What would make me a lot more confortable with this change is if you
enable kernel mappings for one test. This will ensure you cover the
call to "invalidate" in your testing. I'd like to know about the
performance impact. With this implementation it should be identical to
the VB2 one.

What I was trying to say in previous comments, is that my impression is
that we can skip this for CPU read access, since we don't guaranty
concurrent access anyway. Both address space can keep their cache in
that case. Though, I see RKISP does not use kernel mapping plus I'm not
reporting a bug, but checking if we should leave a comment for possible
users of kernel mapping in the future ?

> +
> +	dma_sync_sgtable_for_cpu(buf->dev, sgt, direction);
> +
> ?	return 0;
> ?}
> ?
> @@ -434,6 +445,17 @@ static int
> ?vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
> ?				 enum dma_data_direction direction)
> ?{
> +	struct vb2_dc_buf *buf = dbuf->priv;
> +	struct sg_table *sgt = buf->dma_sgt;
> +
> +	if (!buf->non_coherent_mem)
> +		return 0;
> +
> +	if (buf->vaddr)
> +		flush_kernel_vmap_range(buf->vaddr, buf->size);
> +
> +	dma_sync_sgtable_for_device(buf->dev, sgt, direction);
> +
> ?	return 0;
> ?}
> ?
> 



From angelogioacchino.delregno at collabora.com  Mon Mar  3 07:33:49 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 3 Mar 2025 16:33:49 +0100
Subject: [PATCH v2 01/20] ASoC: dt-bindings: Add document for
 mt6359-accdet
In-Reply-To: <0120fe30-43c4-4fec-8b5e-fdb6b382fc2a@notapiano>
References: <20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47@collabora.com>
 <20250302-mt6359-accdet-dts-v2-1-5bd633ee0d47@collabora.com>
 <628a81c5-b9f1-4be9-84ec-90022a3526da@collabora.com>
 <0120fe30-43c4-4fec-8b5e-fdb6b382fc2a@notapiano>
Message-ID: <24d3713c-026a-4ef7-bb7f-19150e06f395@collabora.com>

Il 03/03/25 15:45, N?colas F. R. A. Prado ha scritto:
> On Mon, Mar 03, 2025 at 12:14:51PM +0100, AngeloGioacchino Del Regno wrote:
>> Il 02/03/25 17:30, N?colas F. R. A. Prado ha scritto:
>>> Add dt-binding for the MT6359 ACCDET hardware block.
>>>
>>> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
>>> ---
>>>    .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
>>>    1 file changed, 42 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
>>> new file mode 100644
>>> index 0000000000000000000000000000000000000000..d08a79301409374714c76135b061e20e8e8acfaf
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
>>> @@ -0,0 +1,42 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: MT6359 Accessory Detection
>>> +
>>> +maintainers:
>>> +  - N?colas F. R. A. Prado <nfraprado at collabora.com>
>>> +
>>> +description: |
>>> +  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
>>> +  detecting audio jack insertion and removal, as well as identifying the type of
>>> +  events connected to the jack.
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: mediatek,mt6359-accdet
>>> +
>>> +  mediatek,hp-eint-high:
>>> +    type: boolean
>>> +    description:
>>> +      By default, the HP_EINT pin is assumed to be pulled high and connected to
>>
>> Just to be clearer about this pin being an internal one and not externally sourced,
>> so, *not* a SoC GPIO, but somehing that is completely provided and handled by the
>> accdet IP...
>>
>> "By default, the accdet IP's internal HP_EINT pin is assumed to be pulled ..."
> 
> The HP_EINT is an external, not internal, pin of the MT6359 PMIC. It is an input
> pin of the MT6359 IC that gets wired to the tip (left channel) of a 3.5mm audio
> jack to allow for detecting when a plug is connected.
> 
> Since this dt-binding is about an IP in the MT6359 PMIC, I think when saying
> "HP_EINT pin" it is already clear that the pin is on the MT6359 IC, but if you
> think it's necessary I could make it "MT6359's HP_EINT pin".
> 

Eh I should've better clarified - I was meaning that the pin is managed internally,
so we're not managing an external SoC pin.

"MT6359's HP_EINT pin" looks good to me, btw.

Cheers!
Angelo




From hugues.kambampiana at arm.com  Mon Mar  3 07:37:44 2025
From: hugues.kambampiana at arm.com (Hugues KAMBA MPIANA)
Date: Mon,  3 Mar 2025 15:37:44 +0000
Subject: [PATCH] arm64: dts: corstone1000: Add definitions for secondary CPU cores
Message-ID: <20250303153744.376419-1-hugues.kambampiana@arm.com>

Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
enable support for secondary CPU cores.

This update facilitates symmetric multiprocessing (SMP) support on
the Corstone1000 Fixed Virtual Platform (FVP), allowing the
secondary cores to be properly initialised and utilised.

Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana at arm.com>
---
 arch/arm64/boot/dts/arm/corstone1000-fvp.dts | 24 ++++++++++++++++++++
 arch/arm64/boot/dts/arm/corstone1000.dtsi    |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
index abd013562995..df9700302b8d 100644
--- a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
+++ b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
@@ -49,3 +49,27 @@ sdmmc1: mmc at 50000000 {
 		clock-names = "smclk", "apb_pclk";
 	};
 };
+
+&cpus {
+	cpu1: cpu at 1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x1>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+	cpu2: cpu at 2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x2>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+	cpu3: cpu at 3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x3>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/arm/corstone1000.dtsi b/arch/arm64/boot/dts/arm/corstone1000.dtsi
index bb9b96fb5314..b4364c61901c 100644
--- a/arch/arm64/boot/dts/arm/corstone1000.dtsi
+++ b/arch/arm64/boot/dts/arm/corstone1000.dtsi
@@ -21,7 +21,7 @@ chosen {
 		stdout-path = "serial0:115200n8";
 	};
 
-	cpus {
+	cpus: cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
 


From neal at gompa.dev  Mon Mar  3 07:40:10 2025
From: neal at gompa.dev (Neal Gompa)
Date: Mon,  3 Mar 2025 10:40:10 -0500
Subject: [PATCH] MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support
Message-ID: <20250303154012.1417088-1-neal@gompa.dev>

As a member of the Asahi Linux project, I (Neal) have been involved in
reviewing the patches downstream as part of enabling the Fedora Asahi Remix
distribution for years and have recently been reviewing patches for upstream
submission as well.

This formalizes my role as a reviewer for ARM Apple system support patches.

Signed-off-by: Neal Gompa <neal at gompa.dev>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..052e6e997817 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2212,6 +2212,7 @@ ARM/APPLE MACHINE SUPPORT
 M:	Sven Peter <sven at svenpeter.dev>
 M:	Janne Grunau <j at jannau.net>
 R:	Alyssa Rosenzweig <alyssa at rosenzweig.io>
+R:	Neal Gompa <neal at gompa.dev>
 L:	asahi at lists.linux.dev
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-- 
2.48.1



From alyssa at rosenzweig.io  Mon Mar  3 07:43:17 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Mon, 3 Mar 2025 10:43:17 -0500
Subject: [PATCH] MAINTAINERS: Add myself (Neal Gompa) as a reviewer for
 ARM Apple support
In-Reply-To: <20250303154012.1417088-1-neal@gompa.dev>
References: <20250303154012.1417088-1-neal@gompa.dev>
Message-ID: <Z8XOFTclPeZwBKld@blossom>

Acked-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>

Le Mon , Mar 03, 2025 at 10:40:10AM -0500, Neal Gompa a ?crit :
> As a member of the Asahi Linux project, I (Neal) have been involved in
> reviewing the patches downstream as part of enabling the Fedora Asahi Remix
> distribution for years and have recently been reviewing patches for upstream
> submission as well.
> 
> This formalizes my role as a reviewer for ARM Apple system support patches.
> 
> Signed-off-by: Neal Gompa <neal at gompa.dev>
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8e0736dc2ee0..052e6e997817 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2212,6 +2212,7 @@ ARM/APPLE MACHINE SUPPORT
>  M:	Sven Peter <sven at svenpeter.dev>
>  M:	Janne Grunau <j at jannau.net>
>  R:	Alyssa Rosenzweig <alyssa at rosenzweig.io>
> +R:	Neal Gompa <neal at gompa.dev>
>  L:	asahi at lists.linux.dev
>  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
> -- 
> 2.48.1
> 


From sudeep.holla at arm.com  Mon Mar  3 08:00:35 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 3 Mar 2025 16:00:35 +0000
Subject: [PATCH] arm64: dts: corstone1000: Add definitions for secondary
 CPU cores
In-Reply-To: <20250303153744.376419-1-hugues.kambampiana@arm.com>
References: <20250303153744.376419-1-hugues.kambampiana@arm.com>
Message-ID: <Z8XSIx75B4mtcV48@bogus>

On Mon, Mar 03, 2025 at 03:37:44PM +0000, Hugues KAMBA MPIANA wrote:
> Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
> enable support for secondary CPU cores.
> 
> This update facilitates symmetric multiprocessing (SMP) support on
> the Corstone1000 Fixed Virtual Platform (FVP), allowing the
> secondary cores to be properly initialised and utilised.
> 
> Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana at arm.com>
> ---
>  arch/arm64/boot/dts/arm/corstone1000-fvp.dts | 24 ++++++++++++++++++++
>  arch/arm64/boot/dts/arm/corstone1000.dtsi    |  2 +-
>  2 files changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
> index abd013562995..df9700302b8d 100644
> --- a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
> +++ b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
> @@ -49,3 +49,27 @@ sdmmc1: mmc at 50000000 {
>  		clock-names = "smclk", "apb_pclk";
>  	};
>  };
> +
> +&cpus {
> +	cpu1: cpu at 1 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a35";
> +		reg = <0x1>;
> +		enable-method = "psci";
> +		next-level-cache = <&L2_0>;
> +	};
> +	cpu2: cpu at 2 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a35";
> +		reg = <0x2>;
> +		enable-method = "psci";
> +		next-level-cache = <&L2_0>;
> +	};
> +	cpu3: cpu at 3 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a35";
> +		reg = <0x3>;
> +		enable-method = "psci";
> +		next-level-cache = <&L2_0>;
> +	};

Why are these not part of /cpus node in corstone1000.dtsi ?
Also I see the original cpu at 0 node doesn't have enable-method set to
"psci" while these secondary cpus have. Please add the same and move all
these changes in corstone1000.dtsi unless you have strong reasons not to.

In that case, please clearly state the reason in the commit message.

P.S: I was about to send PR soon for v6.15. If you want this change for
v6.15, you need to be quicker.

-- 
Regards,
Sudeep


From memxor at gmail.com  Mon Mar  3 07:22:41 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:41 -0800
Subject: [PATCH bpf-next v3 01/25] locking: Move MCS struct definition to public header
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-2-memxor@gmail.com>

Move the definition of the struct mcs_spinlock from the private
mcs_spinlock.h header in kernel/locking to the mcs_spinlock.h
asm-generic header, since we will need to reference it from the
qspinlock.h header in subsequent commits.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/mcs_spinlock.h | 6 ++++++
 kernel/locking/mcs_spinlock.h      | 6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/asm-generic/mcs_spinlock.h b/include/asm-generic/mcs_spinlock.h
index 10cd4ffc6ba2..39c94012b88a 100644
--- a/include/asm-generic/mcs_spinlock.h
+++ b/include/asm-generic/mcs_spinlock.h
@@ -1,6 +1,12 @@
 #ifndef __ASM_MCS_SPINLOCK_H
 #define __ASM_MCS_SPINLOCK_H
 
+struct mcs_spinlock {
+	struct mcs_spinlock *next;
+	int locked; /* 1 if lock acquired */
+	int count;  /* nesting count, see qspinlock.c */
+};
+
 /*
  * Architectures can define their own:
  *
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
index 85251d8771d9..16160ca8907f 100644
--- a/kernel/locking/mcs_spinlock.h
+++ b/kernel/locking/mcs_spinlock.h
@@ -15,12 +15,6 @@
 
 #include <asm/mcs_spinlock.h>
 
-struct mcs_spinlock {
-	struct mcs_spinlock *next;
-	int locked; /* 1 if lock acquired */
-	int count;  /* nesting count, see qspinlock.c */
-};
-
 #ifndef arch_mcs_spin_lock_contended
 /*
  * Using smp_cond_load_acquire() provides the acquire semantics
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:40 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:40 -0800
Subject: [PATCH bpf-next v3 00/25] Resilient Queued Spin Lock
Message-ID: <20250303152305.3195648-1-memxor@gmail.com>

Changelog:
----------
v2 -> v3
v2: https://lore.kernel.org/bpf/20250206105435.2159977-1-memxor at gmail.com

 * Add ifdef's to fallback to Ankur's patch when it gets in, until then
   copy-paste the implementation.
 * Change the meaning of RES_DEF_TIMEOUT from two critical section
   lengths to one for clarity, and use RES_DEF_TIMEOUT * 2 where needed.
 * Use NSEC_PER_SEC as timeout for TAS fallback.
 * Add Closes: tags for known syzbot reports.
 * Change timeout for TAS fallback to 1 second.
 * Fix more kernel test robot errors.
 * More comments about smp_wmb in release_held_lock_entry interaction.
 * Change RES_NR_HELD to 31.
 * Address comments from Peter, Eduard, Alexei.

v1 -> v2
v1: https://lore.kernel.org/bpf/20250107140004.2732830-1-memxor at gmail.com

 * Address nits from Waiman and Peter
 * Fix arm64 WFE bug pointed out by Peter.
 * Fix incorrect memory ordering in release_held_lock_entry, and
   document subtleties. Explain why release is sufficient in unlock
   but not in release_held_lock_entry.
 * Remove dependence on CONFIG_QUEUED_SPINLOCKS and introduce a
   test-and-set fallback when queued spinlock support is missing on an
   architecture.
 * Enforce FIFO ordering for BPF program spin unlocks.
 * Address comments from Eduard on verifier plumbing.
 * Add comments as suggested by Waiman.
 * Refactor paravirt TAS lock to use the implemented TAS fallback.
 * Use rqspinlock_t as the type throughout so that it can be replaced
   with a non-qspinlock type in case of fallback.
 * Testing and benchmarking on arm64, added numbers to the cover letter.
 * Fix kernel test robot errors.
 * Fix a BPF selftest bug leading to spurious failures on arm64.

Introduction
------------

This patch set introduces Resilient Queued Spin Lock (or rqspinlock with
res_spin_lock() and res_spin_unlock() APIs).

This is a qspinlock variant which recovers the kernel from a stalled
state when the lock acquisition path cannot make forward progress. This
can occur when a lock acquisition attempt enters a deadlock situation
(e.g. AA, or ABBA), or more generally, when the owner of the lock (which
we?re trying to acquire) isn?t making forward progress.

The cover letter provides an overview of the motivation, design, and
alternative approaches. We then provide evaluation numbers showcasing
that while rqspinlock incurs overhead, the performance of rqspinlock
approaches that of the normal qspinlock used by the kernel.

The evaluations for rqspinlock were performed by replacing the default
qspinlock implementation with it and booting the kernel to run the
experiments. Support for locktorture is also included with numbers in
this series.

The cover letter's design section provides an overview of the
algorithmic approach. A technical document describing the implementation
in more detail is available here:
https://github.com/kkdwivedi/rqspinlock/blob/main/rqspinlock.pdf

We have a WIP TLA+ proof for liveness and mutual exclusion of rqspinlock
built on top of the qspinlock TLA+ proof from Catalin Marinas [3]. We
will share more details and the links in the near future.

Motivation
----------

In regular kernel code, usage of locks is assumed to be correct, so as
to avoid deadlocks and stalls by construction, however, the same is not
true for BPF programs. Users write normal C code and the in-kernel eBPF
runtime ensures the safety of the kernel by rejecting unsafe programs.
Users can upload programs that use locks in an improper fashion, and may
cause deadlocks when these programs run inside the kernel. The verifier
is responsible for rejecting such programs from being loaded into the
kernel.

Until now, the eBPF verifier ensured deadlock safety by only permitting
one lock acquisition at a time, and by preventing any functions to be
called from within the critical section. Additionally, only a few
restricted program types are allowed to call spin locks. As the usage of
eBPF grows (e.g. with sched_ext) beyond its conventional application in
networking, tracing, and security, the limitations on locking are
becoming a bottleneck for users.

The rqspinlock implementation allows us to permit more flexible locking
patterns in BPF programs, without limiting them to the subset that can
be proven safe statically (which is fairly small, and requires complex
static analysis), while ensuring that the kernel will recover in case we
encounter a locking violation at runtime. We make a tradeoff here by
accepting programs that may potentially have deadlocks, and recover the
kernel quickly at runtime to ensure availability.

Additionally, eBPF programs attached to different parts of the kernel
can introduce new control flow into the kernel, which increases the
likelihood of deadlocks in code not written to handle reentrancy. There
have been multiple syzbot reports surfacing deadlocks in internal kernel
code due to the diverse ways in which eBPF programs can be attached to
different parts of the kernel.  By switching the BPF subsystem?s lock
usage to rqspinlock, all of these issues can be mitigated at runtime.

This spin lock implementation allows BPF maps to become safer and remove
mechanisms that have fallen short in assuring safety when nesting
programs in arbitrary ways in the same context or across different
contexts. The red diffs due to patches 16-18 demonstrate this
simplification.

>  kernel/bpf/hashtab.c         | 102 ++++++++++++++++++++++++++++++++--------------------------...
>  kernel/bpf/lpm_trie.c        |  25 ++++++++++++++-----------
>  kernel/bpf/percpu_freelist.c | 113 +++++++++++++++++++++++++---------------------------------...
>  kernel/bpf/percpu_freelist.h |   4 ++--
>  4 files changed, 73 insertions(+), 171 deletions(-)

Design
------

Deadlocks mostly manifest as stalls in the waiting loops of the
qspinlock slow path. Thus, using stalls as a signal for deadlocks avoids
introducing cost to the normal fast path, and ensures bounded
termination of the waiting loop. Our recovery algorithm is focused on
terminating the waiting loops of the qspinlock algorithm when it gets
stuck, and implementing bespoke recovery procedures for each class of
waiter to restore the lock to a usable state. Deadlock detection is the
main mechanism used to provide faster recovery, with the timeout
mechanism acting as a final line of defense.

Deadlock Detection
~~~~~~~~~~~~~~~~~~
We handle two cases of deadlocks: AA deadlocks (attempts to acquire the
same lock again), and ABBA deadlocks (attempts to acquire two locks in
the opposite order from two distinct threads). Variants of ABBA
deadlocks may be encountered with more than two locks being held in the
incorrect order. These are not diagnosed explicitly, as they reduce to
ABBA deadlocks.

Deadlock detection is triggered immediately when beginning the waiting
loop of a lock slow path.

While timeouts ensure that any waiting loops in the locking slow path
terminate and return to the caller, it can be excessively long in some
situations. While the default timeout is short (0.5s), a stall for this
duration inside the kernel can set off alerts for latency-critical
services with strict SLOs.  Ideally, the kernel should recover from an
undesired state of the lock as soon as possible.

A multi-step strategy is used to recover the kernel from waiting loops
in the locking algorithm which may fail to terminate in a bounded amount
of time.

 * Each CPU maintains a table of held locks. Entries are inserted and
   removed upon entry into lock, and exit from unlock, respectively.
 * Deadlock detection for AA locks is thus simple: we have an AA
   deadlock if we find a held lock entry for the lock we?re attempting
   to acquire on the same CPU.
 * During deadlock detection for ABBA, we search through the tables of
   all other CPUs to find situations where we are holding a lock the
   remote CPU is attempting to acquire, and they are holding a lock we
   are attempting to acquire. Upon encountering such a condition, we
   report an ABBA deadlock.
 * We divide the duration between entry time point into the waiting loop
   and the timeout time point into intervals of 1 ms, and perform
   deadlock detection until timeout happens. Upon entry into the slow
   path, and then completion of each 1 ms interval, we perform detection
   of both AA and ABBA deadlocks. In the event that deadlock detection
   yields a positive result, the recovery happens sooner than the
   timeout.  Otherwise, it happens as a last resort upon completion of
   the timeout.

Timeouts
~~~~~~~~
Timeouts act as final line of defense against stalls for waiting loops.
The ?ktime_get_mono_fast_ns? function is used to poll for the current
time, and it is compared to the timestamp indicating the end time in the
waiter loop. Each waiting loop is instrumented to check an extra
condition using a macro. Internally, the macro implementation amortizes
the checking of the timeout to avoid sampling the clock in every
iteration.  Precisely, the timeout checks are invoked every 64k
iterations.

Recovery
~~~~~~~~
There is extensive literature in academia on designing locks that
support timeouts [0][1], as timeouts can be used as a proxy for
detecting the presence of deadlocks and recovering from them, without
maintaining explicit metadata to construct a waits-for relationship
between two threads at runtime.

In case of rqspinlock, the key simplification in our algorithm comes
from the fact that upon a timeout, waiters always leave the queue in
FIFO order.  As such, the timeout is only enforced by the head of the
wait queue, while other waiters rely on the head to signal them when a
timeout has occurred and when they need to exit. We don?t have to
implement complex algorithms and do not need extra synchronization for
waiters in the middle of the queue timing out before their predecessor
or successor, unlike previous approaches [0][1].

There are three forms of waiters in the original queued spin lock
algorithm.  The first is the waiter which acquires the pending bit and
spins on the lock word without forming a wait queue. The second is the
head waiter that is the first waiter heading the wait queue. The third
form is of all the non-head waiters queued behind the head, waiting to
be signalled through their MCS node to overtake the responsibility of
the head.

In rqspinlock's recovery algorithm, we are concerned with the second and
third kind. First, we augment the waiting loop of the head of the wait
queue with a timeout. When this timeout happens, all waiters part of the
wait queue will abort their lock acquisition attempts. This happens in
three steps.

 * First, the head breaks out of its loop waiting for pending and locked
   bits to turn to 0, and non-head waiters break out of their MCS node
   spin (more on that later).
 * Next, every waiter (head or non-head) attempts to check whether they
   are also the tail waiter, in such a case they attempt to zero out the
   tail word and allow a new queue to be built up for this lock. If they
   succeed, they have no one to signal next in the queue to stop
   spinning.
 * Otherwise, they signal the MCS node of the next waiter to break out
   of its spin and try resetting the tail word back to 0. This goes on
   until the tail waiter is found. In case of races, the new tail will
   be responsible for performing the same task, as the old tail will
   then fail to reset the tail word and wait for its next pointer to be
   updated before it signals the new tail to do the same.

Timeout Bound
~~~~~~~~~~~~~
The timeout is applied by two types of waiters: the pending bit waiter
and the wait queue head waiter. As such, for the pending waiter, only
the lock owner is ahead of it, and for the wait queue head waiter, only
the lock owner and the pending waiter take precedence in executing their
critical sections.

We define the timeout value to span at most 1 critical section length,
and then use the appropriate value (default, or default x 2) depending
on if we are the pending waiter or head of wait queue.

Therefore, the waiting loop wait can span at most 2 critical section
lengths, and thus, it is unaffected by the amount of contention or the
number of CPUs on the host. Non-head waiters simply wait for the wait
queue head to signal them on a timeout.

In Meta's production, we have noticed uncore PMU reads and SMIs
consuming tens of msecs. While these events are rare, a 0.25 second
timeout should absorb such tail events and not raise false alarms for
timeouts. We will continue monitoring this in production and adjust the
timeout if necessary in the future.

More details of the recovery algorithm is described in patch 9 and a
detailed description is available at [2].

Alternatives
------------

Lockdep: We do not rely on the lockdep facility for reporting violations
for primarily two reasons:

* Overhead: The lockdep infrastructure can add significant overhead to
  the lock acquisition path, and is not recommended for use in
  production due to this reason. While the report is more useful and
  exhaustive, the overhead can be prohibitive, especially as BPF
  programs run in hot paths of the kernel.  Moreover, it also increases
  the size of the lock word to store extra metadata, which is not
  feasible for BPF spin locks that are 4-bytes in size today (similar to
  qspinlock).

* Debug Tool: Lockdep is intended to be used as a debugging facility,
  providing extra context to the user about the locking violations
  occurring during runtime. It is always turned off on all production
  kernels, therefore isn?t available most of the time.

We require a mechanism for detecting common variants of deadlocks that
is always available in production kernels and never turned off. At the
same time, it must not introduce overhead in terms of time (for the slow
path) and memory (for the lock word size).

Evaluation
----------

We run benchmarks that stress locking scalability and perform comparison
against the baseline (qspinlock). For the rqspinlock case, we replace
the default qspinlock with it in the kernel, such that all spin locks in
the kernel use the rqspinlock slow path. As such, benchmarks that stress
kernel spin locks end up exercising rqspinlock.

Evaluation setup
~~~~~~~~~~~~~~~~

We set the CPU governor to performance for all experiments.

Note: Numbers for arm64 have been obtained without the no-WFE fallback
in this series, to perform a fair comparison with the WFE using
qspinlock baseline.

x86_64:

Intel Xeon Platinum 8468 (Sapphire Rapids)
96 cores (48 x 2 sockets)
2 threads per core, 0-95, siblings from 96-191
2 NUMA nodes (every 48 cores), 2 LLCs (every 48 cores), 1 LLC per NUMA node
Hyperthreading enabled

arm64:

Ampere Max Neoverse-N1 256-Core Processor
256 cores (128 cores x 2 sockets)
1 thread per core
2 NUMA nodes (every 128 cores), 1 L2 per core (256 instances), no shared L3
No hyperthreading available

The locktorture experiment is run for 30 seconds.
Average of 25 runs is used for will-it-scale, after an initial warm up.

More information on the locks contended in the will-it-scale experiments
is available in the evaluation section of the CNA paper, in table 1 [4].

Legend:
 QL - qspinlock (avg. throughput)
 RQL - rqspinlock (avg. throughput)

Results
~~~~~~~

locktorture - x86_64

Threads QL		RQL		Speedup
-----------------------------------------------
1	46910437	45057327	0.96
2	29871063	25085034	0.84
4	13876024	19242776	1.39
8	14638499	13346847	0.91
16	14380506	14104716	0.98
24	17278144	15293077	0.89
32	19494283	17826675	0.91
40	27760955	21002910	0.76
48	28638897	26432549	0.92
56	29336194	26512029	0.9
64	30040731	27421403	0.91
72	29523599	27010618	0.91
80	28846738	27885141	0.97
88	29277418	25963753	0.89
96	28472339	27423865	0.96
104	28093317	26634895	0.95
112	29914000	27872339	0.93
120	29199580	26682695	0.91
128	27755880	27314662	0.98
136	30349095	27092211	0.89
144	29193933	27805445	0.95
152	28956663	26071497	0.9
160	28950009	28183864	0.97
168	29383520	28135091	0.96
176	28475883	27549601	0.97
184	31958138	28602434	0.89
192	31342633	33394385	1.07

will-it-scale open1_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	1396323.92	7373.12		0.53	1366616.8	4152.08		0.3	0.98
2	1844403.8	3165.26		0.17	1700301.96	2396.58		0.14	0.92
4	2370590.6	24545.54	1.04	1655872.32	47938.71	2.9	0.7
8	2185227.04	9537.9		0.44	1691205.16	9783.25		0.58	0.77
16	2110672.36	10972.99	0.52	1781696.24	15021.43	0.84	0.84
24	1655042.72	18037.23	1.09	2165125.4	5422.54		0.25	1.31
32	1738928.24	7166.64		0.41	1829468.24	9081.59		0.5	1.05
40	1854430.52	6148.24		0.33	1731062.28	3311.95		0.19	0.93
48	1766529.96	5063.86		0.29	1749375.28	2311.27		0.13	0.99
56	1303016.28	6168.4		0.47	1452656		7695.29		0.53	1.11
64	1169557.96	4353.67		0.37	1287370.56	8477.2		0.66	1.1
72	1036023.4	7116.53		0.69	1135513.92	9542.55		0.84	1.1
80	1097913.64	11356		1.03	1176864.8	6771.41		0.58	1.07
88	1123907.36	12843.13	1.14	1072416.48	7412.25		0.69	0.95
96	1166981.52	9402.71		0.81	1129678.76	9499.14		0.84	0.97
104	1108954.04	8171.46		0.74	1032044.44	7840.17		0.76	0.93
112	1000777.76	8445.7		0.84	1078498.8	6551.47		0.61	1.08
120	1029448.4	6992.29		0.68	1093743		8378.94		0.77	1.06
128	1106670.36	10102.15	0.91	1241438.68	23212.66	1.87	1.12
136	1183776.88	6394.79		0.54	1116799.64	18111.38	1.62	0.94
144	1201122		25917.69	2.16	1301779.96	15792.6		1.21	1.08
152	1099737.08	13567.82	1.23	1053647.2	12704.29	1.21	0.96
160	1031186.32	9048.07		0.88	1069961.4	8293.18		0.78	1.04
168	1068817		16486.06	1.54	1096495.36	14021.93	1.28	1.03
176	966633.96	9623.27		1	1081129.84	9474.81		0.88	1.12
184	1004419.04	12111.11	1.21	1037771.24	12001.66	1.16	1.03
192	1088858.08	16522.93	1.52	1027943.12	14238.57	1.39	0.94

will-it-scale open2_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	1337797.76	4649.19		0.35	1332609.4	3813.14		0.29	1
2	1598300.2	1059.93		0.07	1771891.36	5667.12		0.32	1.11
4	1736573.76	13025.33	0.75	1396901.2	2682.46		0.19	0.8
8	1794367.84	4879.6		0.27	1917478.56	3751.98		0.2	1.07
16	1990998.44	8332.78		0.42	1864165.56	9648.59		0.52	0.94
24	1868148.56	4248.23		0.23	1710136.68	2760.58		0.16	0.92
32	1955180		6719		0.34	1936149.88	1980.87		0.1	0.99
40	1769646.4	4686.54		0.26	1729653.68	4551.22		0.26	0.98
48	1724861.16	4056.66		0.24	1764900		971.11		0.06	1.02
56	1318568		7758.86		0.59	1385660.84	7039.8		0.51	1.05
64	1143290.28	5351.43		0.47	1316686.6	5597.69		0.43	1.15
72	1196762.68	10655.67	0.89	1230173.24	9858.2		0.8	1.03
80	1126308.24	6901.55		0.61	1085391.16	7444.34		0.69	0.96
88	1035672.96	5452.95		0.53	1035541.52	8095.33		0.78	1
96	1030203.36	6735.71		0.65	1020113.48	8683.13		0.85	0.99
104	1039432.88	6583.59		0.63	1083902.48	5775.72		0.53	1.04
112	1113609.04	4380.62		0.39	1072010.36	8983.14		0.84	0.96
120	1109420.96	7183.5		0.65	1079424.12	10929.97	1.01	0.97
128	1095400.04	4274.6		0.39	1095475.2	12042.02	1.1	1
136	1071605.4	11103.73	1.04	1114757.2	10516.55	0.94	1.04
144	1104147.2	9714.75		0.88	1044954.16	7544.2		0.72	0.95
152	1164280.24	13386.15	1.15	1101213.92	11568.49	1.05	0.95
160	1084892.04	7941.25		0.73	1152273.76	9593.38		0.83	1.06
168	983654.76	11772.85	1.2	1111772.28	9806.83		0.88	1.13
176	1087544.24	11262.35	1.04	1077507.76	9442.02		0.88	0.99
184	1101682.4	24701.68	2.24	1095223.2	16707.29	1.53	0.99
192	983712.08	13453.59	1.37	1051244.2	15662.05	1.49	1.07

will-it-scale lock1_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	4307484.96	3959.31		0.09	4252908.56	10375.78	0.24	0.99
2	7701844.32	4169.88		0.05	7219233.52	6437.11		0.09	0.94
4	14781878.72	22854.85	0.15	15260565.12	37305.71	0.24	1.03
8	12949698.64	99270.42	0.77	9954660.4	142805.68	1.43	0.77
16	12947690.64	72977.27	0.56	10865245.12	49520.31	0.46	0.84
24	11142990.64	33200.39	0.3	11444391.68	37884.46	0.33	1.03
32	9652335.84	22369.48	0.23	9344086.72	21639.22	0.23	0.97
40	9185931.12	5508.96		0.06	8881506.32	5072.33		0.06	0.97
48	9084385.36	10871.05	0.12	8863579.12	4583.37		0.05	0.98
56	6595540.96	33100.59	0.5	6640389.76	46619.96	0.7	1.01
64	5946726.24	47160.5		0.79	6572155.84	91973.73	1.4	1.11
72	6744894.72	43166.65	0.64	5991363.36	80637.56	1.35	0.89
80	6234502.16	118983.16	1.91	5157894.32	73592.72	1.43	0.83
88	5053879.6	199713.75	3.95	4479758.08	36202.27	0.81	0.89
96	5184302.64	99199.89	1.91	5249210.16	122348.69	2.33	1.01
104	4612391.92	40803.05	0.88	4850209.6	26813.28	0.55	1.05
112	4809209.68	24070.68	0.5	4869477.84	27489.04	0.56	1.01
120	5130746.4	34265.5		0.67	4620047.12	44229.54	0.96	0.9
128	5376465.28	95028.05	1.77	4781179.6	43700.93	0.91	0.89
136	5453742.4	86718.87	1.59	5412457.12	40339.68	0.75	0.99
144	5805040.72	84669.31	1.46	5595382.48	68701.65	1.23	0.96
152	5842897.36	31120.33	0.53	5787587.12	43521.68	0.75	0.99
160	5837665.12	14179.44	0.24	5118808.72	45193.23	0.88	0.88
168	5660332.72	27467.09	0.49	5104959.04	40891.75	0.8	0.9
176	5180312.24	28656.39	0.55	4718407.6	58734.13	1.24	0.91
184	4706824.16	50469.31	1.07	4692962.64	92266.85	1.97	1
192	5126054.56	51082.02	1	4680866.8	58743.51	1.25	0.91

will-it-scale lock2_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	4316091.2	4933.28		0.11	4293104		30369.71	0.71	0.99
2	3500046.4	19852.62	0.57	4507627.76	23667.66	0.53	1.29
4	3639098.96	26370.65	0.72	3673166.32	30822.71	0.84	1.01
8	3714548.56	49953.44	1.34	4055818.56	71630.41	1.77	1.09
16	4188724.64	105414.49	2.52	4316077.12	68956.15	1.6	1.03
24	3737908.32	47391.46	1.27	3762254.56	55345.7		1.47	1.01
32	3820952.8	45207.66	1.18	3710368.96	52651.92	1.42	0.97
40	3791280.8	28630.55	0.76	3661933.52	37671.27	1.03	0.97
48	3765721.84	59553.83	1.58	3604738.64	50861.36	1.41	0.96
56	3175505.76	64336.17	2.03	2771022.48	66586.99	2.4	0.87
64	2620294.48	71651.34	2.73	2650171.68	44810.83	1.69	1.01
72	2861893.6	86542.61	3.02	2537437.2	84571.75	3.33	0.89
80	2976297.2	83566.43	2.81	2645132.8	85992.34	3.25	0.89
88	2547724.8	102014.36	4	2336852.16	80570.25	3.45	0.92
96	2945310.32	82673.25	2.81	2513316.96	45741.81	1.82	0.85
104	3028818.64	90643.36	2.99	2581787.52	52967.48	2.05	0.85
112	2546264.16	102605.82	4.03	2118812.64	62043.19	2.93	0.83
120	2917334.64	112220.01	3.85	2720418.64	64035.96	2.35	0.93
128	2906621.84	69428.1		2.39	2795310.32	56736.87	2.03	0.96
136	2841833.76	105541.11	3.71	3063404.48	62288.94	2.03	1.08
144	3032822.32	134796.56	4.44	3169985.6	149707.83	4.72	1.05
152	2557694.96	62218.15	2.43	2469887.6	68343.78	2.77	0.97
160	2810214.72	61468.79	2.19	2323768.48	54226.71	2.33	0.83
168	2651146.48	76573.27	2.89	2385936.64	52433.98	2.2	0.9
176	2720616.32	89026.19	3.27	2941400.08	59296.64	2.02	1.08
184	2696086		88541.24	3.28	2598225.2	76365.7		2.94	0.96
192	2908194.48	87023.91	2.99	2377677.68	53299.82	2.24	0.82

locktorture - arm64

Threads QL		RQL		Speedup
-----------------------------------------------
1	43320464	44718174	1.03
2	21056971	29255448	1.39
4	16040120	11563981	0.72
8	12786398	12838909	1
16	13646408	13436730	0.98
24	13597928	13669457	1.01
32	16456220	14600324	0.89
40	16667726	13883101	0.83
48	14347691	14608641	1.02
56	15624580	15180758	0.97
64	18105114	16009137	0.88
72	16606438	14772256	0.89
80	16550202	14124056	0.85
88	16716082	15930618	0.95
96	16489242	16817657	1.02
104	17915808	17165324	0.96
112	17217482	21343282	1.24
120	20449845	20576123	1.01
128	18700902	20286275	1.08
136	17913378	21142921	1.18
144	18225673	18971921	1.04
152	18374206	19229854	1.05
160	23136514	20129504	0.87
168	21096269	17167777	0.81
176	21376794	21594914	1.01
184	23542989	20638298	0.88
192	22793754	20655980	0.91
200	20933027	19628316	0.94
208	23105684	25572720	1.11
216	24158081	23173848	0.96
224	23388984	22485353	0.96
232	21916401	23899343	1.09
240	22292129	22831784	1.02
248	25812762	22636787	0.88
256	24294738	26127113	1.08

will-it-scale open1_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	844452.32	801		0.09	804936.92	900.25		0.11	0.95
2	1309419.08	9495.78		0.73	1265080.24	3171.13		0.25	0.97
4	2113074.24	5363.19		0.25	2041158.28	7883.65		0.39	0.97
8	1916650.96	15749.86	0.82	2039850.04	7562.87		0.37	1.06
16	1835540.72	12940.45	0.7	1937398.56	11461.15	0.59	1.06
24	1876760.48	12581.67	0.67	1966659.16	10012.69	0.51	1.05
32	1834525.6	5571.08		0.3	1929180.4	6221.96		0.32	1.05
40	1851592.76	7848.18		0.42	1937504.44	5991.55		0.31	1.05
48	1845067		4118.68		0.22	1773331.56	6068.23		0.34	0.96
56	1742709.36	6874.03		0.39	1716184.92	6713.16		0.39	0.98
64	1685339.72	6688.91		0.4	1676046.16	5844.06		0.35	0.99
72	1694838.84	2433.41		0.14	1821189.6	2906.89		0.16	1.07
80	1738778.68	2916.74		0.17	1729212.6	3714.41		0.21	0.99
88	1753131.76	2734.34		0.16	1713294.32	4652.82		0.27	0.98
96	1694112.52	4449.69		0.26	1714438.36	5621.66		0.33	1.01
104	1780279.76	2420.52		0.14	1767679.12	3067.66		0.17	0.99
112	1700284.72	9796.23		0.58	1796674.6	4066.06		0.23	1.06
120	1760466.72	3978.65		0.23	1704706.08	4080.04		0.24	0.97
128	1634067.96	5187.94		0.32	1764115.48	3545.02		0.2	1.08
136	1170303.84	7602.29		0.65	1227188.04	8090.84		0.66	1.05
144	953186.16	7859.02		0.82	964822.08	10536.61	1.09	1.01
152	818893.96	7238.86		0.88	853412.44	5932.25		0.7	1.04
160	707460.48	3868.26		0.55	746985.68	10363.03	1.39	1.06
168	658380.56	4938.77		0.75	672101.12	5442.95		0.81	1.02
176	614692.04	3137.74		0.51	615143.36	6197.19		1.01	1
184	574808.88	4741.61		0.82	592395.08	8840.92		1.49	1.03
192	548142.92	6116.31		1.12	571299.68	8388.56		1.47	1.04
200	511621.96	2182.33		0.43	532144.88	5467.04		1.03	1.04
208	506583.32	6834.39		1.35	521427.08	10318.65	1.98	1.03
216	480438.04	3608.96		0.75	510697.76	8086.47		1.58	1.06
224	470644.96	3451.35		0.73	467433.92	5008.59		1.07	0.99
232	466973.72	6599.97		1.41	444345.92	2144.96		0.48	0.95
240	442927.68	2351.56		0.53	440503.56	4289.01		0.97	0.99
248	432991.16	5829.92		1.35	445462.6	5944.03		1.33	1.03
256	409455.44	1430.5		0.35	422219.4	4007.04		0.95	1.03

will-it-scale open2_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	818645.4	1097.02		0.13	774110.24	1562.45		0.2	0.95
2	1281013.04	2188.78		0.17	1238346.24	2149.97		0.17	0.97
4	2058514.16	13105.36	0.64	1985375		3204.48		0.16	0.96
8	1920414.8	16154.63	0.84	1911667.92	8882.98		0.46	1
16	1943729.68	8714.38		0.45	1978946.72	7465.65		0.38	1.02
24	1915846.88	7749.9		0.4	1914442.72	9841.71		0.51	1
32	1964695.92	8854.83		0.45	1914650.28	9357.82		0.49	0.97
40	1845071.12	5103.26		0.28	1891685.44	4278.34		0.23	1.03
48	1838897.6	5123.61		0.28	1843498.2	5391.94		0.29	1
56	1823768.32	3214.14		0.18	1736477.48	5675.49		0.33	0.95
64	1627162.36	3528.1		0.22	1685727.16	6102.63		0.36	1.04
72	1725320.16	4709.83		0.27	1710174.4	6707.54		0.39	0.99
80	1692288.44	9110.89		0.54	1773676.24	4327.94		0.24	1.05
88	1725496.64	4249.71		0.25	1695173.84	5097.14		0.3	0.98
96	1766093.08	2280.09		0.13	1732782.64	3606.1		0.21	0.98
104	1647753		2926.83		0.18	1710876.4	4416.04		0.26	1.04
112	1763785.52	3838.26		0.22	1803813.76	1859.2		0.1	1.02
120	1684095.16	2385.31		0.14	1766903.08	3258.34		0.18	1.05
128	1733528.56	2800.62		0.16	1677446.32	3201.14		0.19	0.97
136	1179187.84	6804.86		0.58	1241839.52	10698.51	0.86	1.05
144	969456.36	6421.85		0.66	1018441.96	8732.19		0.86	1.05
152	839295.64	10422.66	1.24	817531.92	6778.37		0.83	0.97
160	743010.72	6957.98		0.94	749291.16	9388.47		1.25	1.01
168	666049.88	13159.73	1.98	689408.08	10192.66	1.48	1.04
176	609185.56	5685.18		0.93	653744.24	10847.35	1.66	1.07
184	602232.08	12089.72	2.01	597718.6	13856.45	2.32	0.99
192	563919.32	9870.46		1.75	560080.4	8388.47		1.5	0.99
200	522396.28	4155.61		0.8	539168.64	10456.64	1.94	1.03
208	520328.28	9353.14		1.8	510011.4	6061.19		1.19	0.98
216	479797.72	5824.58		1.21	486955.32	4547.05		0.93	1.01
224	467943.8	4484.86		0.96	473252.76	5608.58		1.19	1.01
232	456914.24	3129.5		0.68	457463.2	7474.83		1.63	1
240	450535		5149.78		1.14	437653.56	4604.92		1.05	0.97
248	435475.2	2350.87		0.54	435589.24	6176.01		1.42	1
256	416737.88	2592.76		0.62	424178.28	3932.2		0.93	1.02

will-it-scale lock1_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	2512077.52	3026.1		0.12	2085365.92	1612.44		0.08	0.83
2	4840180.4	3646.31		0.08	4326922.24	3802.17		0.09	0.89
4	9358779.44	6673.07		0.07	8467588.56	5577.05		0.07	0.9
8	9374436.88	18826.26	0.2	8635110.16	4217.66		0.05	0.92
16	9527184.08	14111.94	0.15	8561174.16	3258.6		0.04	0.9
24	8873099.76	17242.32	0.19	9286778.72	4124.51		0.04	1.05
32	8457640.4	10790.92	0.13	8700401.52	5110		0.06	1.03
40	8478771.76	13250.8		0.16	8746198.16	7606.42		0.09	1.03
48	8329097.76	7958.92		0.1	8774265.36	6082.08		0.07	1.05
56	8330143.04	11586.93	0.14	8472426.48	7402.13		0.09	1.02
64	8334684.08	10478.03	0.13	7979193.52	8436.63		0.11	0.96
72	7941815.52	16031.38	0.2	8016885.52	12640.56	0.16	1.01
80	8042221.68	10219.93	0.13	8072222.88	12479.54	0.15	1
88	8190336.8	10751.38	0.13	8432977.6	11865.67	0.14	1.03
96	8235010.08	7267.8		0.09	8022101.28	11910.63	0.15	0.97
104	8154434.08	7770.8		0.1	7987812		7647.42		0.1	0.98
112	7738464.56	11067.72	0.14	7968483.92	20632.93	0.26	1.03
120	8228919.36	10395.79	0.13	8304329.28	11913.76	0.14	1.01
128	7798646.64	8877.8		0.11	8197938.4	7527.81		0.09	1.05
136	5567293.68	66259.82	1.19	5642017.12	126584.59	2.24	1.01
144	4425655.52	55729.96	1.26	4519874.64	82996.01	1.84	1.02
152	3871300.8	77793.78	2.01	3850025.04	80167.3		2.08	0.99
160	3558041.68	55108.3		1.55	3495924.96	83626.42	2.39	0.98
168	3302042.72	45011.89	1.36	3298002.8	59393.64	1.8	1
176	3066165.2	34896.54	1.14	3063027.44	58219.26	1.9	1
184	2817899.6	43585.27	1.55	2859393.84	45258.03	1.58	1.01
192	2690403.76	42236.77	1.57	2630652.24	35953.13	1.37	0.98
200	2563141.44	28145.43	1.1	2539964.32	38556.52	1.52	0.99
208	2502968.8	27687.81	1.11	2477757.28	28240.81	1.14	0.99
216	2474917.76	24128.71	0.97	2483161.44	32198.37	1.3	1
224	2386874.72	32954.66	1.38	2398068.48	37667.29	1.57	1
232	2379248.24	27413.4		1.15	2327601.68	24565.28	1.06	0.98
240	2302146.64	19914.19	0.87	2236074.64	20968.17	0.94	0.97
248	2241798.32	21542.52	0.96	2173312.24	26498.36	1.22	0.97
256	2198765.12	20832.66	0.95	2136159.52	25027.96	1.17	0.97

will-it-scale lock2_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	2499414.32	1932.27		0.08	2075704.8	24589.71	1.18	0.83
2	3887820		34198.36	0.88	4057432.64	11896.04	0.29	1.04
4	3445307.6	7958.3		0.23	3869960.4	3788.5		0.1	1.12
8	4310597.2	14405.9		0.33	3931319.76	5845.33		0.15	0.91
16	3995159.84	22621.85	0.57	3953339.68	15668.9		0.4	0.99
24	4048456.88	22956.51	0.57	3887812.64	30584.77	0.79	0.96
32	3974808.64	20465.87	0.51	3718778.08	27407.24	0.74	0.94
40	3941154.88	15136.68	0.38	3551464.24	33378.67	0.94	0.9
48	3725436.32	17090.67	0.46	3714356.08	19035.26	0.51	1
56	3558449.44	10123.46	0.28	3449656.08	36476.87	1.06	0.97
64	3514616.08	16470.99	0.47	3493197.04	25639.82	0.73	0.99
72	3461700.88	16780.97	0.48	3376565.04	16930.19	0.5	0.98
80	3797008.64	17599.05	0.46	3505856.16	34320.34	0.98	0.92
88	3737459.44	10774.93	0.29	3631757.68	24231.29	0.67	0.97
96	3612816.16	21865.86	0.61	3545354.56	16391.15	0.46	0.98
104	3765167.36	17763.8		0.47	3466467.12	22235.45	0.64	0.92
112	3713386		15455.21	0.42	3402210		18349.66	0.54	0.92
120	3699986.08	15153.08	0.41	3580303.92	19823.01	0.55	0.97
128	3648694.56	11891.62	0.33	3426445.28	22993.32	0.67	0.94
136	800046.88	6039.73		0.75	784412.16	9062.03		1.16	0.98
144	769483.36	5231.74		0.68	714132.8	8953.57		1.25	0.93
152	821081.52	4249.12		0.52	743694.64	8155.18		1.1	0.91
160	789040.16	9187.4		1.16	834865.44	6159.29		0.74	1.06
168	867742.4	8967.66		1.03	734905.36	15582.75	2.12	0.85
176	838650.32	7949.72		0.95	846939.68	8959.8		1.06	1.01
184	854984.48	19475.51	2.28	794549.92	11924.54	1.5	0.93
192	846262.32	13795.86	1.63	899915.12	8639.82		0.96	1.06
200	942602.16	12665.42	1.34	900385.76	8592.23		0.95	0.96
208	954183.68	12853.22	1.35	1166186.96	13045.03	1.12	1.22
216	929319.76	10157.79	1.09	926773.76	10577.01	1.14	1
224	967896.56	9819.6		1.01	951144.32	12343.83	1.3	0.98
232	990621.12	7771.97		0.78	916361.2	17878.44	1.95	0.93
240	995285.04	20104.22	2.02	972119.6	12856.42	1.32	0.98
248	1029436		20404.97	1.98	965301.28	11102.95	1.15	0.94
256	1038724.8	19201.03	1.85	1029942.08	12563.07	1.22	0.99

Written By
----------
Alexei Starovoitov <ast at kernel.org>
Kumar Kartikeya Dwivedi <memxor at gmail.com>

  [0]: https://www.cs.rochester.edu/research/synchronization/pseudocode/timeout.html
  [1]: https://dl.acm.org/doi/10.1145/571825.571830
  [2]: https://github.com/kkdwivedi/rqspinlock/blob/main/rqspinlock.pdf
  [3]: https://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/kernel-tla.git/plain/qspinlock.tla
  [4]: https://arxiv.org/pdf/1810.05600

Kumar Kartikeya Dwivedi (25):
  locking: Move MCS struct definition to public header
  locking: Move common qspinlock helpers to a private header
  locking: Allow obtaining result of arch_mcs_spin_lock_contended
  locking: Copy out qspinlock.c to rqspinlock.c
  rqspinlock: Add rqspinlock.h header
  rqspinlock: Drop PV and virtualization support
  rqspinlock: Add support for timeouts
  rqspinlock: Hardcode cond_acquire loops for arm64
  rqspinlock: Protect pending bit owners from stalls
  rqspinlock: Protect waiters in queue from stalls
  rqspinlock: Protect waiters in trylock fallback from stalls
  rqspinlock: Add deadlock detection and recovery
  rqspinlock: Add a test-and-set fallback
  rqspinlock: Add basic support for CONFIG_PARAVIRT
  rqspinlock: Add helper to print a splat on timeout or deadlock
  rqspinlock: Add macros for rqspinlock usage
  rqspinlock: Add locktorture support
  rqspinlock: Add entry to Makefile, MAINTAINERS
  bpf: Convert hashtab.c to rqspinlock
  bpf: Convert percpu_freelist.c to rqspinlock
  bpf: Convert lpm_trie.c to rqspinlock
  bpf: Introduce rqspinlock kfuncs
  bpf: Implement verifier support for rqspinlock
  bpf: Maintain FIFO property for rqspinlock unlock
  selftests/bpf: Add tests for rqspinlock

 MAINTAINERS                                   |   3 +
 arch/arm64/include/asm/rqspinlock.h           |  93 +++
 arch/x86/include/asm/rqspinlock.h             |  33 +
 include/asm-generic/Kbuild                    |   1 +
 include/asm-generic/mcs_spinlock.h            |   6 +
 include/asm-generic/rqspinlock.h              | 245 ++++++
 include/linux/bpf.h                           |  10 +
 include/linux/bpf_verifier.h                  |  19 +-
 kernel/bpf/btf.c                              |  26 +-
 kernel/bpf/hashtab.c                          | 102 +--
 kernel/bpf/lpm_trie.c                         |  25 +-
 kernel/bpf/percpu_freelist.c                  | 113 +--
 kernel/bpf/percpu_freelist.h                  |   4 +-
 kernel/bpf/syscall.c                          |   6 +-
 kernel/bpf/verifier.c                         | 248 +++++-
 kernel/locking/Makefile                       |   1 +
 kernel/locking/lock_events_list.h             |   5 +
 kernel/locking/locktorture.c                  |  57 ++
 kernel/locking/mcs_spinlock.h                 |  10 +-
 kernel/locking/qspinlock.c                    | 193 +----
 kernel/locking/qspinlock.h                    | 200 +++++
 kernel/locking/rqspinlock.c                   | 764 ++++++++++++++++++
 kernel/locking/rqspinlock.h                   |  48 ++
 .../selftests/bpf/prog_tests/res_spin_lock.c  |  92 +++
 tools/testing/selftests/bpf/progs/irq.c       |  53 ++
 .../selftests/bpf/progs/res_spin_lock.c       | 143 ++++
 .../selftests/bpf/progs/res_spin_lock_fail.c  | 244 ++++++
 27 files changed, 2328 insertions(+), 416 deletions(-)
 create mode 100644 arch/arm64/include/asm/rqspinlock.h
 create mode 100644 arch/x86/include/asm/rqspinlock.h
 create mode 100644 include/asm-generic/rqspinlock.h
 create mode 100644 kernel/locking/qspinlock.h
 create mode 100644 kernel/locking/rqspinlock.c
 create mode 100644 kernel/locking/rqspinlock.h
 create mode 100644 tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock_fail.c


base-commit: 17a82ed98f62e0b3d2465e482ae5d0503e989a48
--
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:43 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:43 -0800
Subject: [PATCH bpf-next v3 03/25] locking: Allow obtaining result of arch_mcs_spin_lock_contended
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-4-memxor@gmail.com>

To support upcoming changes that require inspecting the return value
once the conditional waiting loop in arch_mcs_spin_lock_contended
terminates, modify the macro to preserve the result of
smp_cond_load_acquire. This enables checking the return value as needed,
which will help disambiguate the MCS node?s locked state in future
patches.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/mcs_spinlock.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
index 16160ca8907f..5c92ba199b90 100644
--- a/kernel/locking/mcs_spinlock.h
+++ b/kernel/locking/mcs_spinlock.h
@@ -24,9 +24,7 @@
  * spinning, and smp_cond_load_acquire() provides that behavior.
  */
 #define arch_mcs_spin_lock_contended(l)					\
-do {									\
-	smp_cond_load_acquire(l, VAL);					\
-} while (0)
+	smp_cond_load_acquire(l, VAL)
 #endif
 
 #ifndef arch_mcs_spin_unlock_contended
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:42 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:42 -0800
Subject: [PATCH bpf-next v3 02/25] locking: Move common qspinlock helpers to a private header
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-3-memxor@gmail.com>

Move qspinlock helper functions that encode, decode tail word, set and
clear the pending and locked bits, and other miscellaneous definitions
and macros to a private header. To this end, create a qspinlock.h header
file in kernel/locking. Subsequent commits will introduce a modified
qspinlock slow path function, thus moving shared code to a private
header will help minimize unnecessary code duplication.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/qspinlock.c | 193 +----------------------------------
 kernel/locking/qspinlock.h | 200 +++++++++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+), 188 deletions(-)
 create mode 100644 kernel/locking/qspinlock.h

diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 7d96bed718e4..af8d122bb649 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -25,8 +25,9 @@
 #include <trace/events/lock.h>
 
 /*
- * Include queued spinlock statistics code
+ * Include queued spinlock definitions and statistics code
  */
+#include "qspinlock.h"
 #include "qspinlock_stat.h"
 
 /*
@@ -67,36 +68,6 @@
  */
 
 #include "mcs_spinlock.h"
-#define MAX_NODES	4
-
-/*
- * On 64-bit architectures, the mcs_spinlock structure will be 16 bytes in
- * size and four of them will fit nicely in one 64-byte cacheline. For
- * pvqspinlock, however, we need more space for extra data. To accommodate
- * that, we insert two more long words to pad it up to 32 bytes. IOW, only
- * two of them can fit in a cacheline in this case. That is OK as it is rare
- * to have more than 2 levels of slowpath nesting in actual use. We don't
- * want to penalize pvqspinlocks to optimize for a rare case in native
- * qspinlocks.
- */
-struct qnode {
-	struct mcs_spinlock mcs;
-#ifdef CONFIG_PARAVIRT_SPINLOCKS
-	long reserved[2];
-#endif
-};
-
-/*
- * The pending bit spinning loop count.
- * This heuristic is used to limit the number of lockword accesses
- * made by atomic_cond_read_relaxed when waiting for the lock to
- * transition out of the "== _Q_PENDING_VAL" state. We don't spin
- * indefinitely because there's no guarantee that we'll make forward
- * progress.
- */
-#ifndef _Q_PENDING_LOOPS
-#define _Q_PENDING_LOOPS	1
-#endif
 
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
@@ -106,161 +77,7 @@ struct qnode {
  *
  * PV doubles the storage and uses the second cacheline for PV state.
  */
-static DEFINE_PER_CPU_ALIGNED(struct qnode, qnodes[MAX_NODES]);
-
-/*
- * We must be able to distinguish between no-tail and the tail at 0:0,
- * therefore increment the cpu number by one.
- */
-
-static inline __pure u32 encode_tail(int cpu, int idx)
-{
-	u32 tail;
-
-	tail  = (cpu + 1) << _Q_TAIL_CPU_OFFSET;
-	tail |= idx << _Q_TAIL_IDX_OFFSET; /* assume < 4 */
-
-	return tail;
-}
-
-static inline __pure struct mcs_spinlock *decode_tail(u32 tail)
-{
-	int cpu = (tail >> _Q_TAIL_CPU_OFFSET) - 1;
-	int idx = (tail &  _Q_TAIL_IDX_MASK) >> _Q_TAIL_IDX_OFFSET;
-
-	return per_cpu_ptr(&qnodes[idx].mcs, cpu);
-}
-
-static inline __pure
-struct mcs_spinlock *grab_mcs_node(struct mcs_spinlock *base, int idx)
-{
-	return &((struct qnode *)base + idx)->mcs;
-}
-
-#define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK)
-
-#if _Q_PENDING_BITS == 8
-/**
- * clear_pending - clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,* -> *,0,*
- */
-static __always_inline void clear_pending(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->pending, 0);
-}
-
-/**
- * clear_pending_set_locked - take ownership and clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,0 -> *,0,1
- *
- * Lock stealing is not allowed if this function is used.
- */
-static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->locked_pending, _Q_LOCKED_VAL);
-}
-
-/*
- * xchg_tail - Put in the new queue tail code word & retrieve previous one
- * @lock : Pointer to queued spinlock structure
- * @tail : The new queue tail code word
- * Return: The previous queue tail code word
- *
- * xchg(lock, tail), which heads an address dependency
- *
- * p,*,* -> n,*,* ; prev = xchg(lock, node)
- */
-static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
-{
-	/*
-	 * We can use relaxed semantics since the caller ensures that the
-	 * MCS node is properly initialized before updating the tail.
-	 */
-	return (u32)xchg_relaxed(&lock->tail,
-				 tail >> _Q_TAIL_OFFSET) << _Q_TAIL_OFFSET;
-}
-
-#else /* _Q_PENDING_BITS == 8 */
-
-/**
- * clear_pending - clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,* -> *,0,*
- */
-static __always_inline void clear_pending(struct qspinlock *lock)
-{
-	atomic_andnot(_Q_PENDING_VAL, &lock->val);
-}
-
-/**
- * clear_pending_set_locked - take ownership and clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,0 -> *,0,1
- */
-static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
-{
-	atomic_add(-_Q_PENDING_VAL + _Q_LOCKED_VAL, &lock->val);
-}
-
-/**
- * xchg_tail - Put in the new queue tail code word & retrieve previous one
- * @lock : Pointer to queued spinlock structure
- * @tail : The new queue tail code word
- * Return: The previous queue tail code word
- *
- * xchg(lock, tail)
- *
- * p,*,* -> n,*,* ; prev = xchg(lock, node)
- */
-static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
-{
-	u32 old, new;
-
-	old = atomic_read(&lock->val);
-	do {
-		new = (old & _Q_LOCKED_PENDING_MASK) | tail;
-		/*
-		 * We can use relaxed semantics since the caller ensures that
-		 * the MCS node is properly initialized before updating the
-		 * tail.
-		 */
-	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
-
-	return old;
-}
-#endif /* _Q_PENDING_BITS == 8 */
-
-/**
- * queued_fetch_set_pending_acquire - fetch the whole lock value and set pending
- * @lock : Pointer to queued spinlock structure
- * Return: The previous lock value
- *
- * *,*,* -> *,1,*
- */
-#ifndef queued_fetch_set_pending_acquire
-static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock)
-{
-	return atomic_fetch_or_acquire(_Q_PENDING_VAL, &lock->val);
-}
-#endif
-
-/**
- * set_locked - Set the lock bit and own the lock
- * @lock: Pointer to queued spinlock structure
- *
- * *,*,0 -> *,0,1
- */
-static __always_inline void set_locked(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->locked, _Q_LOCKED_VAL);
-}
-
+static DEFINE_PER_CPU_ALIGNED(struct qnode, qnodes[_Q_MAX_NODES]);
 
 /*
  * Generate the native code for queued_spin_unlock_slowpath(); provide NOPs for
@@ -410,7 +227,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
 	 * any MCS node. This is not the most elegant solution, but is
 	 * simple enough.
 	 */
-	if (unlikely(idx >= MAX_NODES)) {
+	if (unlikely(idx >= _Q_MAX_NODES)) {
 		lockevent_inc(lock_no_node);
 		while (!queued_spin_trylock(lock))
 			cpu_relax();
@@ -465,7 +282,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
 	 * head of the waitqueue.
 	 */
 	if (old & _Q_TAIL_MASK) {
-		prev = decode_tail(old);
+		prev = decode_tail(old, qnodes);
 
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
diff --git a/kernel/locking/qspinlock.h b/kernel/locking/qspinlock.h
new file mode 100644
index 000000000000..d4ceb9490365
--- /dev/null
+++ b/kernel/locking/qspinlock.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Queued spinlock defines
+ *
+ * This file contains macro definitions and functions shared between different
+ * qspinlock slow path implementations.
+ */
+#ifndef __LINUX_QSPINLOCK_H
+#define __LINUX_QSPINLOCK_H
+
+#include <asm-generic/percpu.h>
+#include <linux/percpu-defs.h>
+#include <asm-generic/qspinlock.h>
+#include <asm-generic/mcs_spinlock.h>
+
+#define _Q_MAX_NODES	4
+
+/*
+ * The pending bit spinning loop count.
+ * This heuristic is used to limit the number of lockword accesses
+ * made by atomic_cond_read_relaxed when waiting for the lock to
+ * transition out of the "== _Q_PENDING_VAL" state. We don't spin
+ * indefinitely because there's no guarantee that we'll make forward
+ * progress.
+ */
+#ifndef _Q_PENDING_LOOPS
+#define _Q_PENDING_LOOPS	1
+#endif
+
+/*
+ * On 64-bit architectures, the mcs_spinlock structure will be 16 bytes in
+ * size and four of them will fit nicely in one 64-byte cacheline. For
+ * pvqspinlock, however, we need more space for extra data. To accommodate
+ * that, we insert two more long words to pad it up to 32 bytes. IOW, only
+ * two of them can fit in a cacheline in this case. That is OK as it is rare
+ * to have more than 2 levels of slowpath nesting in actual use. We don't
+ * want to penalize pvqspinlocks to optimize for a rare case in native
+ * qspinlocks.
+ */
+struct qnode {
+	struct mcs_spinlock mcs;
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+	long reserved[2];
+#endif
+};
+
+/*
+ * We must be able to distinguish between no-tail and the tail at 0:0,
+ * therefore increment the cpu number by one.
+ */
+
+static inline __pure u32 encode_tail(int cpu, int idx)
+{
+	u32 tail;
+
+	tail  = (cpu + 1) << _Q_TAIL_CPU_OFFSET;
+	tail |= idx << _Q_TAIL_IDX_OFFSET; /* assume < 4 */
+
+	return tail;
+}
+
+static inline __pure struct mcs_spinlock *decode_tail(u32 tail, struct qnode *qnodes)
+{
+	int cpu = (tail >> _Q_TAIL_CPU_OFFSET) - 1;
+	int idx = (tail &  _Q_TAIL_IDX_MASK) >> _Q_TAIL_IDX_OFFSET;
+
+	return per_cpu_ptr(&qnodes[idx].mcs, cpu);
+}
+
+static inline __pure
+struct mcs_spinlock *grab_mcs_node(struct mcs_spinlock *base, int idx)
+{
+	return &((struct qnode *)base + idx)->mcs;
+}
+
+#define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK)
+
+#if _Q_PENDING_BITS == 8
+/**
+ * clear_pending - clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,* -> *,0,*
+ */
+static __always_inline void clear_pending(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->pending, 0);
+}
+
+/**
+ * clear_pending_set_locked - take ownership and clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,0 -> *,0,1
+ *
+ * Lock stealing is not allowed if this function is used.
+ */
+static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->locked_pending, _Q_LOCKED_VAL);
+}
+
+/*
+ * xchg_tail - Put in the new queue tail code word & retrieve previous one
+ * @lock : Pointer to queued spinlock structure
+ * @tail : The new queue tail code word
+ * Return: The previous queue tail code word
+ *
+ * xchg(lock, tail), which heads an address dependency
+ *
+ * p,*,* -> n,*,* ; prev = xchg(lock, node)
+ */
+static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
+{
+	/*
+	 * We can use relaxed semantics since the caller ensures that the
+	 * MCS node is properly initialized before updating the tail.
+	 */
+	return (u32)xchg_relaxed(&lock->tail,
+				 tail >> _Q_TAIL_OFFSET) << _Q_TAIL_OFFSET;
+}
+
+#else /* _Q_PENDING_BITS == 8 */
+
+/**
+ * clear_pending - clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,* -> *,0,*
+ */
+static __always_inline void clear_pending(struct qspinlock *lock)
+{
+	atomic_andnot(_Q_PENDING_VAL, &lock->val);
+}
+
+/**
+ * clear_pending_set_locked - take ownership and clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,0 -> *,0,1
+ */
+static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
+{
+	atomic_add(-_Q_PENDING_VAL + _Q_LOCKED_VAL, &lock->val);
+}
+
+/**
+ * xchg_tail - Put in the new queue tail code word & retrieve previous one
+ * @lock : Pointer to queued spinlock structure
+ * @tail : The new queue tail code word
+ * Return: The previous queue tail code word
+ *
+ * xchg(lock, tail)
+ *
+ * p,*,* -> n,*,* ; prev = xchg(lock, node)
+ */
+static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
+{
+	u32 old, new;
+
+	old = atomic_read(&lock->val);
+	do {
+		new = (old & _Q_LOCKED_PENDING_MASK) | tail;
+		/*
+		 * We can use relaxed semantics since the caller ensures that
+		 * the MCS node is properly initialized before updating the
+		 * tail.
+		 */
+	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
+
+	return old;
+}
+#endif /* _Q_PENDING_BITS == 8 */
+
+/**
+ * queued_fetch_set_pending_acquire - fetch the whole lock value and set pending
+ * @lock : Pointer to queued spinlock structure
+ * Return: The previous lock value
+ *
+ * *,*,* -> *,1,*
+ */
+#ifndef queued_fetch_set_pending_acquire
+static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock)
+{
+	return atomic_fetch_or_acquire(_Q_PENDING_VAL, &lock->val);
+}
+#endif
+
+/**
+ * set_locked - Set the lock bit and own the lock
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,*,0 -> *,0,1
+ */
+static __always_inline void set_locked(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->locked, _Q_LOCKED_VAL);
+}
+
+#endif /* __LINUX_QSPINLOCK_H */
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:45 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:45 -0800
Subject: [PATCH bpf-next v3 05/25] rqspinlock: Add rqspinlock.h header
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-6-memxor@gmail.com>

This header contains the public declarations usable in the rest of the
kernel for rqspinlock.

Let's also type alias qspinlock to rqspinlock_t to ensure consistent use
of the new lock type. We want to remove dependence on the qspinlock type
in later patches as we need to provide a test-and-set fallback, hence
begin abstracting away from now onwards.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 19 +++++++++++++++++++
 kernel/locking/rqspinlock.c      |  3 ++-
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 include/asm-generic/rqspinlock.h

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
new file mode 100644
index 000000000000..54860b519571
--- /dev/null
+++ b/include/asm-generic/rqspinlock.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Resilient Queued Spin Lock
+ *
+ * (C) Copyright 2024 Meta Platforms, Inc. and affiliates.
+ *
+ * Authors: Kumar Kartikeya Dwivedi <memxor at gmail.com>
+ */
+#ifndef __ASM_GENERIC_RQSPINLOCK_H
+#define __ASM_GENERIC_RQSPINLOCK_H
+
+#include <linux/types.h>
+
+struct qspinlock;
+typedef struct qspinlock rqspinlock_t;
+
+extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+
+#endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 143d9dda36f9..414a3ec8cf70 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -23,6 +23,7 @@
 #include <asm/byteorder.h>
 #include <asm/qspinlock.h>
 #include <trace/events/lock.h>
+#include <asm/rqspinlock.h>
 
 /*
  * Include queued spinlock definitions and statistics code
@@ -127,7 +128,7 @@ static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
  * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
  *   queue               :         ^--'                             :
  */
-void __lockfunc resilient_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
+void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
 	u32 old, tail;
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:44 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:44 -0800
Subject: [PATCH bpf-next v3 04/25] locking: Copy out qspinlock.c to rqspinlock.c
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-5-memxor@gmail.com>

In preparation for introducing a new lock implementation, Resilient
Queued Spin Lock, or rqspinlock, we first begin our modifications by
using the existing qspinlock.c code as the base. Simply copy the code to
a new file and rename functions and variables from 'queued' to
'resilient_queued'.

This helps each subsequent commit in clearly showing how and where the
code is being changed. The only change after a literal copy in this
commit is renaming the functions where necessary, and rename qnodes to
rqnodes.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/rqspinlock.c | 410 ++++++++++++++++++++++++++++++++++++
 1 file changed, 410 insertions(+)
 create mode 100644 kernel/locking/rqspinlock.c

diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
new file mode 100644
index 000000000000..143d9dda36f9
--- /dev/null
+++ b/kernel/locking/rqspinlock.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Resilient Queued Spin Lock
+ *
+ * (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ * (C) Copyright 2013-2014,2018 Red Hat, Inc.
+ * (C) Copyright 2015 Intel Corp.
+ * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP
+ *
+ * Authors: Waiman Long <longman at redhat.com>
+ *          Peter Zijlstra <peterz at infradead.org>
+ */
+
+#ifndef _GEN_PV_LOCK_SLOWPATH
+
+#include <linux/smp.h>
+#include <linux/bug.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/mutex.h>
+#include <linux/prefetch.h>
+#include <asm/byteorder.h>
+#include <asm/qspinlock.h>
+#include <trace/events/lock.h>
+
+/*
+ * Include queued spinlock definitions and statistics code
+ */
+#include "qspinlock.h"
+#include "qspinlock_stat.h"
+
+/*
+ * The basic principle of a queue-based spinlock can best be understood
+ * by studying a classic queue-based spinlock implementation called the
+ * MCS lock. A copy of the original MCS lock paper ("Algorithms for Scalable
+ * Synchronization on Shared-Memory Multiprocessors by Mellor-Crummey and
+ * Scott") is available at
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=206115
+ *
+ * This queued spinlock implementation is based on the MCS lock, however to
+ * make it fit the 4 bytes we assume spinlock_t to be, and preserve its
+ * existing API, we must modify it somehow.
+ *
+ * In particular; where the traditional MCS lock consists of a tail pointer
+ * (8 bytes) and needs the next pointer (another 8 bytes) of its own node to
+ * unlock the next pending (next->locked), we compress both these: {tail,
+ * next->locked} into a single u32 value.
+ *
+ * Since a spinlock disables recursion of its own context and there is a limit
+ * to the contexts that can nest; namely: task, softirq, hardirq, nmi. As there
+ * are at most 4 nesting levels, it can be encoded by a 2-bit number. Now
+ * we can encode the tail by combining the 2-bit nesting level with the cpu
+ * number. With one byte for the lock value and 3 bytes for the tail, only a
+ * 32-bit word is now needed. Even though we only need 1 bit for the lock,
+ * we extend it to a full byte to achieve better performance for architectures
+ * that support atomic byte write.
+ *
+ * We also change the first spinner to spin on the lock bit instead of its
+ * node; whereby avoiding the need to carry a node from lock to unlock, and
+ * preserving existing lock API. This also makes the unlock code simpler and
+ * faster.
+ *
+ * N.B. The current implementation only supports architectures that allow
+ *      atomic operations on smaller 8-bit and 16-bit data types.
+ *
+ */
+
+#include "mcs_spinlock.h"
+
+/*
+ * Per-CPU queue node structures; we can never have more than 4 nested
+ * contexts: task, softirq, hardirq, nmi.
+ *
+ * Exactly fits one 64-byte cacheline on a 64-bit architecture.
+ *
+ * PV doubles the storage and uses the second cacheline for PV state.
+ */
+static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
+
+/*
+ * Generate the native code for resilient_queued_spin_unlock_slowpath(); provide NOPs
+ * for all the PV callbacks.
+ */
+
+static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
+static __always_inline void __pv_wait_node(struct mcs_spinlock *node,
+					   struct mcs_spinlock *prev) { }
+static __always_inline void __pv_kick_node(struct qspinlock *lock,
+					   struct mcs_spinlock *node) { }
+static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
+						   struct mcs_spinlock *node)
+						   { return 0; }
+
+#define pv_enabled()		false
+
+#define pv_init_node		__pv_init_node
+#define pv_wait_node		__pv_wait_node
+#define pv_kick_node		__pv_kick_node
+#define pv_wait_head_or_lock	__pv_wait_head_or_lock
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+#define resilient_queued_spin_lock_slowpath	native_resilient_queued_spin_lock_slowpath
+#endif
+
+#endif /* _GEN_PV_LOCK_SLOWPATH */
+
+/**
+ * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
+ * @lock: Pointer to queued spinlock structure
+ * @val: Current value of the queued spinlock 32-bit word
+ *
+ * (queue tail, pending bit, lock value)
+ *
+ *              fast     :    slow                                  :    unlock
+ *                       :                                          :
+ * uncontended  (0,0,0) -:--> (0,0,1) ------------------------------:--> (*,*,0)
+ *                       :       | ^--------.------.             /  :
+ *                       :       v           \      \            |  :
+ * pending               :    (0,1,1) +--> (0,1,0)   \           |  :
+ *                       :       | ^--'              |           |  :
+ *                       :       v                   |           |  :
+ * uncontended           :    (n,x,y) +--> (n,0,0) --'           |  :
+ *   queue               :       | ^--'                          |  :
+ *                       :       v                               |  :
+ * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
+ *   queue               :         ^--'                             :
+ */
+void __lockfunc resilient_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
+{
+	struct mcs_spinlock *prev, *next, *node;
+	u32 old, tail;
+	int idx;
+
+	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
+
+	if (pv_enabled())
+		goto pv_queue;
+
+	if (virt_spin_lock(lock))
+		return;
+
+	/*
+	 * Wait for in-progress pending->locked hand-overs with a bounded
+	 * number of spins so that we guarantee forward progress.
+	 *
+	 * 0,1,0 -> 0,0,1
+	 */
+	if (val == _Q_PENDING_VAL) {
+		int cnt = _Q_PENDING_LOOPS;
+		val = atomic_cond_read_relaxed(&lock->val,
+					       (VAL != _Q_PENDING_VAL) || !cnt--);
+	}
+
+	/*
+	 * If we observe any contention; queue.
+	 */
+	if (val & ~_Q_LOCKED_MASK)
+		goto queue;
+
+	/*
+	 * trylock || pending
+	 *
+	 * 0,0,* -> 0,1,* -> 0,0,1 pending, trylock
+	 */
+	val = queued_fetch_set_pending_acquire(lock);
+
+	/*
+	 * If we observe contention, there is a concurrent locker.
+	 *
+	 * Undo and queue; our setting of PENDING might have made the
+	 * n,0,0 -> 0,0,0 transition fail and it will now be waiting
+	 * on @next to become !NULL.
+	 */
+	if (unlikely(val & ~_Q_LOCKED_MASK)) {
+
+		/* Undo PENDING if we set it. */
+		if (!(val & _Q_PENDING_MASK))
+			clear_pending(lock);
+
+		goto queue;
+	}
+
+	/*
+	 * We're pending, wait for the owner to go away.
+	 *
+	 * 0,1,1 -> *,1,0
+	 *
+	 * this wait loop must be a load-acquire such that we match the
+	 * store-release that clears the locked bit and create lock
+	 * sequentiality; this is because not all
+	 * clear_pending_set_locked() implementations imply full
+	 * barriers.
+	 */
+	if (val & _Q_LOCKED_MASK)
+		smp_cond_load_acquire(&lock->locked, !VAL);
+
+	/*
+	 * take ownership and clear the pending bit.
+	 *
+	 * 0,1,0 -> 0,0,1
+	 */
+	clear_pending_set_locked(lock);
+	lockevent_inc(lock_pending);
+	return;
+
+	/*
+	 * End of pending bit optimistic spinning and beginning of MCS
+	 * queuing.
+	 */
+queue:
+	lockevent_inc(lock_slowpath);
+pv_queue:
+	node = this_cpu_ptr(&rqnodes[0].mcs);
+	idx = node->count++;
+	tail = encode_tail(smp_processor_id(), idx);
+
+	trace_contention_begin(lock, LCB_F_SPIN);
+
+	/*
+	 * 4 nodes are allocated based on the assumption that there will
+	 * not be nested NMIs taking spinlocks. That may not be true in
+	 * some architectures even though the chance of needing more than
+	 * 4 nodes will still be extremely unlikely. When that happens,
+	 * we fall back to spinning on the lock directly without using
+	 * any MCS node. This is not the most elegant solution, but is
+	 * simple enough.
+	 */
+	if (unlikely(idx >= _Q_MAX_NODES)) {
+		lockevent_inc(lock_no_node);
+		while (!queued_spin_trylock(lock))
+			cpu_relax();
+		goto release;
+	}
+
+	node = grab_mcs_node(node, idx);
+
+	/*
+	 * Keep counts of non-zero index values:
+	 */
+	lockevent_cond_inc(lock_use_node2 + idx - 1, idx);
+
+	/*
+	 * Ensure that we increment the head node->count before initialising
+	 * the actual node. If the compiler is kind enough to reorder these
+	 * stores, then an IRQ could overwrite our assignments.
+	 */
+	barrier();
+
+	node->locked = 0;
+	node->next = NULL;
+	pv_init_node(node);
+
+	/*
+	 * We touched a (possibly) cold cacheline in the per-cpu queue node;
+	 * attempt the trylock once more in the hope someone let go while we
+	 * weren't watching.
+	 */
+	if (queued_spin_trylock(lock))
+		goto release;
+
+	/*
+	 * Ensure that the initialisation of @node is complete before we
+	 * publish the updated tail via xchg_tail() and potentially link
+	 * @node into the waitqueue via WRITE_ONCE(prev->next, node) below.
+	 */
+	smp_wmb();
+
+	/*
+	 * Publish the updated tail.
+	 * We have already touched the queueing cacheline; don't bother with
+	 * pending stuff.
+	 *
+	 * p,*,* -> n,*,*
+	 */
+	old = xchg_tail(lock, tail);
+	next = NULL;
+
+	/*
+	 * if there was a previous node; link it and wait until reaching the
+	 * head of the waitqueue.
+	 */
+	if (old & _Q_TAIL_MASK) {
+		prev = decode_tail(old, rqnodes);
+
+		/* Link @node into the waitqueue. */
+		WRITE_ONCE(prev->next, node);
+
+		pv_wait_node(node, prev);
+		arch_mcs_spin_lock_contended(&node->locked);
+
+		/*
+		 * While waiting for the MCS lock, the next pointer may have
+		 * been set by another lock waiter. We optimistically load
+		 * the next pointer & prefetch the cacheline for writing
+		 * to reduce latency in the upcoming MCS unlock operation.
+		 */
+		next = READ_ONCE(node->next);
+		if (next)
+			prefetchw(next);
+	}
+
+	/*
+	 * we're at the head of the waitqueue, wait for the owner & pending to
+	 * go away.
+	 *
+	 * *,x,y -> *,0,0
+	 *
+	 * this wait loop must use a load-acquire such that we match the
+	 * store-release that clears the locked bit and create lock
+	 * sequentiality; this is because the set_locked() function below
+	 * does not imply a full barrier.
+	 *
+	 * The PV pv_wait_head_or_lock function, if active, will acquire
+	 * the lock and return a non-zero value. So we have to skip the
+	 * atomic_cond_read_acquire() call. As the next PV queue head hasn't
+	 * been designated yet, there is no way for the locked value to become
+	 * _Q_SLOW_VAL. So both the set_locked() and the
+	 * atomic_cmpxchg_relaxed() calls will be safe.
+	 *
+	 * If PV isn't active, 0 will be returned instead.
+	 *
+	 */
+	if ((val = pv_wait_head_or_lock(lock, node)))
+		goto locked;
+
+	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
+
+locked:
+	/*
+	 * claim the lock:
+	 *
+	 * n,0,0 -> 0,0,1 : lock, uncontended
+	 * *,*,0 -> *,*,1 : lock, contended
+	 *
+	 * If the queue head is the only one in the queue (lock value == tail)
+	 * and nobody is pending, clear the tail code and grab the lock.
+	 * Otherwise, we only need to grab the lock.
+	 */
+
+	/*
+	 * In the PV case we might already have _Q_LOCKED_VAL set, because
+	 * of lock stealing; therefore we must also allow:
+	 *
+	 * n,0,1 -> 0,0,1
+	 *
+	 * Note: at this point: (val & _Q_PENDING_MASK) == 0, because of the
+	 *       above wait condition, therefore any concurrent setting of
+	 *       PENDING will make the uncontended transition fail.
+	 */
+	if ((val & _Q_TAIL_MASK) == tail) {
+		if (atomic_try_cmpxchg_relaxed(&lock->val, &val, _Q_LOCKED_VAL))
+			goto release; /* No contention */
+	}
+
+	/*
+	 * Either somebody is queued behind us or _Q_PENDING_VAL got set
+	 * which will then detect the remaining tail and queue behind us
+	 * ensuring we'll see a @next.
+	 */
+	set_locked(lock);
+
+	/*
+	 * contended path; wait for next if not observed yet, release.
+	 */
+	if (!next)
+		next = smp_cond_load_relaxed(&node->next, (VAL));
+
+	arch_mcs_spin_unlock_contended(&next->locked);
+	pv_kick_node(lock, next);
+
+release:
+	trace_contention_end(lock, 0);
+
+	/*
+	 * release the node
+	 */
+	__this_cpu_dec(rqnodes[0].mcs.count);
+}
+EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
+
+/*
+ * Generate the paravirt code for resilient_queued_spin_unlock_slowpath().
+ */
+#if !defined(_GEN_PV_LOCK_SLOWPATH) && defined(CONFIG_PARAVIRT_SPINLOCKS)
+#define _GEN_PV_LOCK_SLOWPATH
+
+#undef  pv_enabled
+#define pv_enabled()	true
+
+#undef pv_init_node
+#undef pv_wait_node
+#undef pv_kick_node
+#undef pv_wait_head_or_lock
+
+#undef  resilient_queued_spin_lock_slowpath
+#define resilient_queued_spin_lock_slowpath	__pv_resilient_queued_spin_lock_slowpath
+
+#include "qspinlock_paravirt.h"
+#include "rqspinlock.c"
+
+bool nopvspin;
+static __init int parse_nopvspin(char *arg)
+{
+	nopvspin = true;
+	return 0;
+}
+early_param("nopvspin", parse_nopvspin);
+#endif
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:47 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:47 -0800
Subject: [PATCH bpf-next v3 07/25] rqspinlock: Add support for timeouts
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-8-memxor@gmail.com>

Introduce policy macro RES_CHECK_TIMEOUT which can be used to detect
when the timeout has expired for the slow path to return an error. It
depends on being passed two variables initialized to 0: ts, ret. The
'ts' parameter is of type rqspinlock_timeout.

This macro resolves to the (ret) expression so that it can be used in
statements like smp_cond_load_acquire to break the waiting loop
condition.

The 'spin' member is used to amortize the cost of checking time by
dispatching to the implementation every 64k iterations. The
'timeout_end' member is used to keep track of the timestamp that denotes
the end of the waiting period. The 'ret' parameter denotes the status of
the timeout, and can be checked in the slow path to detect timeouts
after waiting loops.

The 'duration' member is used to store the timeout duration for each
waiting loop. The default timeout value defined in the header
(RES_DEF_TIMEOUT) is 0.25 seconds.

This macro will be used as a condition for waiting loops in the slow
path.  Since each waiting loop applies a fresh timeout using the same
rqspinlock_timeout, we add a new RES_RESET_TIMEOUT as well to ensure the
values can be easily reinitialized to the default state.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h |  6 +++++
 kernel/locking/rqspinlock.c      | 45 ++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 54860b519571..96cea871fdd2 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -10,10 +10,16 @@
 #define __ASM_GENERIC_RQSPINLOCK_H
 
 #include <linux/types.h>
+#include <vdso/time64.h>
 
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
 
 extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 
+/*
+ * Default timeout for waiting loops is 0.25 seconds
+ */
+#define RES_DEF_TIMEOUT (NSEC_PER_SEC / 4)
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 98cdcc5f1784..6b547f85fa95 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -6,9 +6,11 @@
  * (C) Copyright 2013-2014,2018 Red Hat, Inc.
  * (C) Copyright 2015 Intel Corp.
  * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP
+ * (C) Copyright 2024 Meta Platforms, Inc. and affiliates.
  *
  * Authors: Waiman Long <longman at redhat.com>
  *          Peter Zijlstra <peterz at infradead.org>
+ *          Kumar Kartikeya Dwivedi <memxor at gmail.com>
  */
 
 #include <linux/smp.h>
@@ -22,6 +24,7 @@
 #include <asm/qspinlock.h>
 #include <trace/events/lock.h>
 #include <asm/rqspinlock.h>
+#include <linux/timekeeping.h>
 
 /*
  * Include queued spinlock definitions and statistics code
@@ -68,6 +71,45 @@
 
 #include "mcs_spinlock.h"
 
+struct rqspinlock_timeout {
+	u64 timeout_end;
+	u64 duration;
+	u16 spin;
+};
+
+static noinline int check_timeout(struct rqspinlock_timeout *ts)
+{
+	u64 time = ktime_get_mono_fast_ns();
+
+	if (!ts->timeout_end) {
+		ts->timeout_end = time + ts->duration;
+		return 0;
+	}
+
+	if (time > ts->timeout_end)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+#define RES_CHECK_TIMEOUT(ts, ret)                    \
+	({                                            \
+		if (!(ts).spin++)                     \
+			(ret) = check_timeout(&(ts)); \
+		(ret);                                \
+	})
+
+/*
+ * Initialize the 'spin' member.
+ */
+#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 1; })
+
+/*
+ * We only need to reset 'timeout_end', 'spin' will just wrap around as necessary.
+ * Duration is defined for each spin attempt, so set it here.
+ */
+#define RES_RESET_TIMEOUT(ts, _duration) ({ (ts).timeout_end = 0; (ts).duration = _duration; })
+
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
  * contexts: task, softirq, hardirq, nmi.
@@ -100,11 +142,14 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
+	struct rqspinlock_timeout ts;
 	u32 old, tail;
 	int idx;
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
+	RES_INIT_TIMEOUT(ts);
+
 	/*
 	 * Wait for in-progress pending->locked hand-overs with a bounded
 	 * number of spins so that we guarantee forward progress.
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:48 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:48 -0800
Subject: [PATCH bpf-next v3 08/25] rqspinlock: Hardcode cond_acquire loops for arm64
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-9-memxor@gmail.com>

Currently, for rqspinlock usage, the implementation of
smp_cond_load_acquire (and thus, atomic_cond_read_acquire) are
susceptible to stalls on arm64, because they do not guarantee that the
conditional expression will be repeatedly invoked if the address being
loaded from is not written to by other CPUs. When support for
event-streams is absent (which unblocks stuck WFE-based loops every
~100us), we may end up being stuck forever.

This causes a problem for us, as we need to repeatedly invoke the
RES_CHECK_TIMEOUT in the spin loop to break out when the timeout
expires.

Let us import the smp_cond_load_acquire_timewait implementation Ankur is
proposing in [0], and then fallback to it once it is merged.

While we rely on the implementation to amortize the cost of sampling
check_timeout for us, it will not happen when event stream support is
unavailable. This is not the common case, and it would be difficult to
fit our logic in the time_expr_ns >= time_limit_ns comparison, hence
just let it be.

  [0]: https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora at oracle.com

Cc: Ankur Arora <ankur.a.arora at oracle.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 arch/arm64/include/asm/rqspinlock.h | 93 +++++++++++++++++++++++++++++
 kernel/locking/rqspinlock.c         | 15 +++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm64/include/asm/rqspinlock.h

diff --git a/arch/arm64/include/asm/rqspinlock.h b/arch/arm64/include/asm/rqspinlock.h
new file mode 100644
index 000000000000..5b80785324b6
--- /dev/null
+++ b/arch/arm64/include/asm/rqspinlock.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RQSPINLOCK_H
+#define _ASM_RQSPINLOCK_H
+
+#include <asm/barrier.h>
+
+/*
+ * Hardcode res_smp_cond_load_acquire implementations for arm64 to a custom
+ * version based on [0]. In rqspinlock code, our conditional expression involves
+ * checking the value _and_ additionally a timeout. However, on arm64, the
+ * WFE-based implementation may never spin again if no stores occur to the
+ * locked byte in the lock word. As such, we may be stuck forever if
+ * event-stream based unblocking is not available on the platform for WFE spin
+ * loops (arch_timer_evtstrm_available).
+ *
+ * Once support for smp_cond_load_acquire_timewait [0] lands, we can drop this
+ * copy-paste.
+ *
+ * While we rely on the implementation to amortize the cost of sampling
+ * cond_expr for us, it will not happen when event stream support is
+ * unavailable, time_expr check is amortized. This is not the common case, and
+ * it would be difficult to fit our logic in the time_expr_ns >= time_limit_ns
+ * comparison, hence just let it be. In case of event-stream, the loop is woken
+ * up at microsecond granularity.
+ *
+ * [0]: https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora at oracle.com
+ */
+
+#ifndef smp_cond_load_acquire_timewait
+
+#define smp_cond_time_check_count	200
+
+#define __smp_cond_load_relaxed_spinwait(ptr, cond_expr, time_expr_ns,	\
+					 time_limit_ns) ({		\
+	typeof(ptr) __PTR = (ptr);					\
+	__unqual_scalar_typeof(*ptr) VAL;				\
+	unsigned int __count = 0;					\
+	for (;;) {							\
+		VAL = READ_ONCE(*__PTR);				\
+		if (cond_expr)						\
+			break;						\
+		cpu_relax();						\
+		if (__count++ < smp_cond_time_check_count)		\
+			continue;					\
+		if ((time_expr_ns) >= (time_limit_ns))			\
+			break;						\
+		__count = 0;						\
+	}								\
+	(typeof(*ptr))VAL;						\
+})
+
+#define __smp_cond_load_acquire_timewait(ptr, cond_expr,		\
+					 time_expr_ns, time_limit_ns)	\
+({									\
+	typeof(ptr) __PTR = (ptr);					\
+	__unqual_scalar_typeof(*ptr) VAL;				\
+	for (;;) {							\
+		VAL = smp_load_acquire(__PTR);				\
+		if (cond_expr)						\
+			break;						\
+		__cmpwait_relaxed(__PTR, VAL);				\
+		if ((time_expr_ns) >= (time_limit_ns))			\
+			break;						\
+	}								\
+	(typeof(*ptr))VAL;						\
+})
+
+#define smp_cond_load_acquire_timewait(ptr, cond_expr,			\
+				      time_expr_ns, time_limit_ns)	\
+({									\
+	__unqual_scalar_typeof(*ptr) _val;				\
+	int __wfe = arch_timer_evtstrm_available();			\
+									\
+	if (likely(__wfe)) {						\
+		_val = __smp_cond_load_acquire_timewait(ptr, cond_expr,	\
+							time_expr_ns,	\
+							time_limit_ns);	\
+	} else {							\
+		_val = __smp_cond_load_relaxed_spinwait(ptr, cond_expr,	\
+							time_expr_ns,	\
+							time_limit_ns);	\
+		smp_acquire__after_ctrl_dep();				\
+	}								\
+	(typeof(*ptr))_val;						\
+})
+
+#endif
+
+#define res_smp_cond_load_acquire_timewait(v, c) smp_cond_load_acquire_timewait(v, c, 0, 1)
+
+#include <asm-generic/rqspinlock.h>
+
+#endif /* _ASM_RQSPINLOCK_H */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 6b547f85fa95..efa937ea80d9 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -92,12 +92,21 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
 	return 0;
 }
 
+/*
+ * Do not amortize with spins when res_smp_cond_load_acquire is defined,
+ * as the macro does internal amortization for us.
+ */
+#ifndef res_smp_cond_load_acquire
 #define RES_CHECK_TIMEOUT(ts, ret)                    \
 	({                                            \
 		if (!(ts).spin++)                     \
 			(ret) = check_timeout(&(ts)); \
 		(ret);                                \
 	})
+#else
+#define RES_CHECK_TIMEOUT(ts, ret, mask)	      \
+	({ (ret) = check_timeout(&(ts)); })
+#endif
 
 /*
  * Initialize the 'spin' member.
@@ -118,6 +127,12 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
  */
 static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 
+#ifndef res_smp_cond_load_acquire
+#define res_smp_cond_load_acquire(v, c) smp_cond_load_acquire(v, c)
+#endif
+
+#define res_atomic_cond_read_acquire(v, c) res_smp_cond_load_acquire(&(v)->counter, (c))
+
 /**
  * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
  * @lock: Pointer to queued spinlock structure
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:46 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:46 -0800
Subject: [PATCH bpf-next v3 06/25] rqspinlock: Drop PV and virtualization support
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-7-memxor@gmail.com>

Changes to rqspinlock in subsequent commits will be algorithmic
modifications, which won't remain in agreement with the implementations
of paravirt spin lock and virt_spin_lock support. These future changes
include measures for terminating waiting loops in slow path after a
certain point. While using a fair lock like qspinlock directly inside
virtual machines leads to suboptimal performance under certain
conditions, we cannot use the existing virtualization support before we
make it resilient as well.  Therefore, drop it for now.

Note that we need to drop qspinlock_stat.h, as it's only relevant in
case of CONFIG_PARAVIRT_SPINLOCKS=y, but we need to keep lock_events.h
in the includes, which was indirectly pulled in before.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/rqspinlock.c | 91 +------------------------------------
 1 file changed, 1 insertion(+), 90 deletions(-)

diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 414a3ec8cf70..98cdcc5f1784 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -11,8 +11,6 @@
  *          Peter Zijlstra <peterz at infradead.org>
  */
 
-#ifndef _GEN_PV_LOCK_SLOWPATH
-
 #include <linux/smp.h>
 #include <linux/bug.h>
 #include <linux/cpumask.h>
@@ -29,7 +27,7 @@
  * Include queued spinlock definitions and statistics code
  */
 #include "qspinlock.h"
-#include "qspinlock_stat.h"
+#include "lock_events.h"
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -75,38 +73,9 @@
  * contexts: task, softirq, hardirq, nmi.
  *
  * Exactly fits one 64-byte cacheline on a 64-bit architecture.
- *
- * PV doubles the storage and uses the second cacheline for PV state.
  */
 static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 
-/*
- * Generate the native code for resilient_queued_spin_unlock_slowpath(); provide NOPs
- * for all the PV callbacks.
- */
-
-static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
-static __always_inline void __pv_wait_node(struct mcs_spinlock *node,
-					   struct mcs_spinlock *prev) { }
-static __always_inline void __pv_kick_node(struct qspinlock *lock,
-					   struct mcs_spinlock *node) { }
-static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
-						   struct mcs_spinlock *node)
-						   { return 0; }
-
-#define pv_enabled()		false
-
-#define pv_init_node		__pv_init_node
-#define pv_wait_node		__pv_wait_node
-#define pv_kick_node		__pv_kick_node
-#define pv_wait_head_or_lock	__pv_wait_head_or_lock
-
-#ifdef CONFIG_PARAVIRT_SPINLOCKS
-#define resilient_queued_spin_lock_slowpath	native_resilient_queued_spin_lock_slowpath
-#endif
-
-#endif /* _GEN_PV_LOCK_SLOWPATH */
-
 /**
  * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
  * @lock: Pointer to queued spinlock structure
@@ -136,12 +105,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
-	if (pv_enabled())
-		goto pv_queue;
-
-	if (virt_spin_lock(lock))
-		return;
-
 	/*
 	 * Wait for in-progress pending->locked hand-overs with a bounded
 	 * number of spins so that we guarantee forward progress.
@@ -212,7 +175,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 queue:
 	lockevent_inc(lock_slowpath);
-pv_queue:
 	node = this_cpu_ptr(&rqnodes[0].mcs);
 	idx = node->count++;
 	tail = encode_tail(smp_processor_id(), idx);
@@ -251,7 +213,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	node->locked = 0;
 	node->next = NULL;
-	pv_init_node(node);
 
 	/*
 	 * We touched a (possibly) cold cacheline in the per-cpu queue node;
@@ -288,7 +249,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
 
-		pv_wait_node(node, prev);
 		arch_mcs_spin_lock_contended(&node->locked);
 
 		/*
@@ -312,23 +272,9 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * store-release that clears the locked bit and create lock
 	 * sequentiality; this is because the set_locked() function below
 	 * does not imply a full barrier.
-	 *
-	 * The PV pv_wait_head_or_lock function, if active, will acquire
-	 * the lock and return a non-zero value. So we have to skip the
-	 * atomic_cond_read_acquire() call. As the next PV queue head hasn't
-	 * been designated yet, there is no way for the locked value to become
-	 * _Q_SLOW_VAL. So both the set_locked() and the
-	 * atomic_cmpxchg_relaxed() calls will be safe.
-	 *
-	 * If PV isn't active, 0 will be returned instead.
-	 *
 	 */
-	if ((val = pv_wait_head_or_lock(lock, node)))
-		goto locked;
-
 	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
 
-locked:
 	/*
 	 * claim the lock:
 	 *
@@ -341,11 +287,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 
 	/*
-	 * In the PV case we might already have _Q_LOCKED_VAL set, because
-	 * of lock stealing; therefore we must also allow:
-	 *
-	 * n,0,1 -> 0,0,1
-	 *
 	 * Note: at this point: (val & _Q_PENDING_MASK) == 0, because of the
 	 *       above wait condition, therefore any concurrent setting of
 	 *       PENDING will make the uncontended transition fail.
@@ -369,7 +310,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		next = smp_cond_load_relaxed(&node->next, (VAL));
 
 	arch_mcs_spin_unlock_contended(&next->locked);
-	pv_kick_node(lock, next);
 
 release:
 	trace_contention_end(lock, 0);
@@ -380,32 +320,3 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	__this_cpu_dec(rqnodes[0].mcs.count);
 }
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
-
-/*
- * Generate the paravirt code for resilient_queued_spin_unlock_slowpath().
- */
-#if !defined(_GEN_PV_LOCK_SLOWPATH) && defined(CONFIG_PARAVIRT_SPINLOCKS)
-#define _GEN_PV_LOCK_SLOWPATH
-
-#undef  pv_enabled
-#define pv_enabled()	true
-
-#undef pv_init_node
-#undef pv_wait_node
-#undef pv_kick_node
-#undef pv_wait_head_or_lock
-
-#undef  resilient_queued_spin_lock_slowpath
-#define resilient_queued_spin_lock_slowpath	__pv_resilient_queued_spin_lock_slowpath
-
-#include "qspinlock_paravirt.h"
-#include "rqspinlock.c"
-
-bool nopvspin;
-static __init int parse_nopvspin(char *arg)
-{
-	nopvspin = true;
-	return 0;
-}
-early_param("nopvspin", parse_nopvspin);
-#endif
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:49 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:49 -0800
Subject: [PATCH bpf-next v3 09/25] rqspinlock: Protect pending bit owners from stalls
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-10-memxor@gmail.com>

The pending bit is used to avoid queueing in case the lock is
uncontended, and has demonstrated benefits for the 2 contender scenario,
esp. on x86. In case the pending bit is acquired and we wait for the
locked bit to disappear, we may get stuck due to the lock owner not
making progress. Hence, this waiting loop must be protected with a
timeout check.

To perform a graceful recovery once we decide to abort our lock
acquisition attempt in this case, we must unset the pending bit since we
own it. All waiters undoing their changes and exiting gracefully allows
the lock word to be restored to the unlocked state once all participants
(owner, waiters) have been recovered, and the lock remains usable.
Hence, set the pending bit back to zero before returning to the caller.

Introduce a lockevent (rqspinlock_lock_timeout) to capture timeout
event statistics.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h  |  2 +-
 kernel/locking/lock_events_list.h |  5 +++++
 kernel/locking/rqspinlock.c       | 28 +++++++++++++++++++++++-----
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 96cea871fdd2..d23793d8e64d 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -15,7 +15,7 @@
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
 
-extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 
 /*
  * Default timeout for waiting loops is 0.25 seconds
diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 97fb6f3f840a..c5286249994d 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -49,6 +49,11 @@ LOCK_EVENT(lock_use_node4)	/* # of locking ops that use 4th percpu node */
 LOCK_EVENT(lock_no_node)	/* # of locking ops w/o using percpu node    */
 #endif /* CONFIG_QUEUED_SPINLOCKS */
 
+/*
+ * Locking events for Resilient Queued Spin Lock
+ */
+LOCK_EVENT(rqspinlock_lock_timeout)	/* # of locking ops that timeout	*/
+
 /*
  * Locking events for rwsem
  */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index efa937ea80d9..6be36798ded9 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -154,12 +154,12 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
  * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
  *   queue               :         ^--'                             :
  */
-void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
+int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
 	struct rqspinlock_timeout ts;
+	int idx, ret = 0;
 	u32 old, tail;
-	int idx;
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
@@ -217,8 +217,25 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * clear_pending_set_locked() implementations imply full
 	 * barriers.
 	 */
-	if (val & _Q_LOCKED_MASK)
-		smp_cond_load_acquire(&lock->locked, !VAL);
+	if (val & _Q_LOCKED_MASK) {
+		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
+		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret));
+	}
+
+	if (ret) {
+		/*
+		 * We waited for the locked bit to go back to 0, as the pending
+		 * waiter, but timed out. We need to clear the pending bit since
+		 * we own it. Once a stuck owner has been recovered, the lock
+		 * must be restored to a valid state, hence removing the pending
+		 * bit is necessary.
+		 *
+		 * *,1,* -> *,0,*
+		 */
+		clear_pending(lock);
+		lockevent_inc(rqspinlock_lock_timeout);
+		return ret;
+	}
 
 	/*
 	 * take ownership and clear the pending bit.
@@ -227,7 +244,7 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	clear_pending_set_locked(lock);
 	lockevent_inc(lock_pending);
-	return;
+	return 0;
 
 	/*
 	 * End of pending bit optimistic spinning and beginning of MCS
@@ -378,5 +395,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * release the node
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
+	return 0;
 }
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:50 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:50 -0800
Subject: [PATCH bpf-next v3 10/25] rqspinlock: Protect waiters in queue from stalls
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-11-memxor@gmail.com>

Implement the wait queue cleanup algorithm for rqspinlock. There are
three forms of waiters in the original queued spin lock algorithm. The
first is the waiter which acquires the pending bit and spins on the lock
word without forming a wait queue. The second is the head waiter that is
the first waiter heading the wait queue. The third form is of all the
non-head waiters queued behind the head, waiting to be signalled through
their MCS node to overtake the responsibility of the head.

In this commit, we are concerned with the second and third kind. First,
we augment the waiting loop of the head of the wait queue with a
timeout. When this timeout happens, all waiters part of the wait queue
will abort their lock acquisition attempts. This happens in three steps.
First, the head breaks out of its loop waiting for pending and locked
bits to turn to 0, and non-head waiters break out of their MCS node spin
(more on that later). Next, every waiter (head or non-head) attempts to
check whether they are also the tail waiter, in such a case they attempt
to zero out the tail word and allow a new queue to be built up for this
lock. If they succeed, they have no one to signal next in the queue to
stop spinning. Otherwise, they signal the MCS node of the next waiter to
break out of its spin and try resetting the tail word back to 0. This
goes on until the tail waiter is found. In case of races, the new tail
will be responsible for performing the same task, as the old tail will
then fail to reset the tail word and wait for its next pointer to be
updated before it signals the new tail to do the same.

We terminate the whole wait queue because of two main reasons. Firstly,
we eschew per-waiter timeouts with one applied at the head of the wait
queue.  This allows everyone to break out faster once we've seen the
owner / pending waiter not responding for the timeout duration from the
head.  Secondly, it avoids complicated synchronization, because when not
leaving in FIFO order, prev's next pointer needs to be fixed up etc.

Lastly, all of these waiters release the rqnode and return to the
caller. This patch underscores the point that rqspinlock's timeout does
not apply to each waiter individually, and cannot be relied upon as an
upper bound. It is possible for the rqspinlock waiters to return early
from a failed lock acquisition attempt as soon as stalls are detected.

The head waiter cannot directly WRITE_ONCE the tail to zero, as it may
race with a concurrent xchg and a non-head waiter linking its MCS node
to the head's MCS node through 'prev->next' assignment.

One notable thing is that we must use RES_DEF_TIMEOUT * 2 as our maximum
duration for the waiting loop (for the wait queue head), since we may
have both the owner and pending bit waiter ahead of us, and in the worst
case, need to span their maximum permitted critical section lengths.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/rqspinlock.c | 55 +++++++++++++++++++++++++++++++++++--
 kernel/locking/rqspinlock.h | 48 ++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 3 deletions(-)
 create mode 100644 kernel/locking/rqspinlock.h

diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 6be36798ded9..9ad18b3c46f7 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -77,6 +77,8 @@ struct rqspinlock_timeout {
 	u16 spin;
 };
 
+#define RES_TIMEOUT_VAL	2
+
 static noinline int check_timeout(struct rqspinlock_timeout *ts)
 {
 	u64 time = ktime_get_mono_fast_ns();
@@ -321,12 +323,18 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * head of the waitqueue.
 	 */
 	if (old & _Q_TAIL_MASK) {
+		int val;
+
 		prev = decode_tail(old, rqnodes);
 
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
 
-		arch_mcs_spin_lock_contended(&node->locked);
+		val = arch_mcs_spin_lock_contended(&node->locked);
+		if (val == RES_TIMEOUT_VAL) {
+			ret = -EDEADLK;
+			goto waitq_timeout;
+		}
 
 		/*
 		 * While waiting for the MCS lock, the next pointer may have
@@ -349,8 +357,49 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * store-release that clears the locked bit and create lock
 	 * sequentiality; this is because the set_locked() function below
 	 * does not imply a full barrier.
+	 *
+	 * We use RES_DEF_TIMEOUT * 2 as the duration, as RES_DEF_TIMEOUT is
+	 * meant to span maximum allowed time per critical section, and we may
+	 * have both the owner of the lock and the pending bit waiter ahead of
+	 * us.
 	 */
-	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
+	RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT * 2);
+	val = res_atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK) ||
+					   RES_CHECK_TIMEOUT(ts, ret));
+
+waitq_timeout:
+	if (ret) {
+		/*
+		 * If the tail is still pointing to us, then we are the final waiter,
+		 * and are responsible for resetting the tail back to 0. Otherwise, if
+		 * the cmpxchg operation fails, we signal the next waiter to take exit
+		 * and try the same. For a waiter with tail node 'n':
+		 *
+		 * n,*,* -> 0,*,*
+		 *
+		 * When performing cmpxchg for the whole word (NR_CPUS > 16k), it is
+		 * possible locked/pending bits keep changing and we see failures even
+		 * when we remain the head of wait queue. However, eventually,
+		 * pending bit owner will unset the pending bit, and new waiters
+		 * will queue behind us. This will leave the lock owner in
+		 * charge, and it will eventually either set locked bit to 0, or
+		 * leave it as 1, allowing us to make progress.
+		 *
+		 * We terminate the whole wait queue for two reasons. Firstly,
+		 * we eschew per-waiter timeouts with one applied at the head of
+		 * the wait queue.  This allows everyone to break out faster
+		 * once we've seen the owner / pending waiter not responding for
+		 * the timeout duration from the head.  Secondly, it avoids
+		 * complicated synchronization, because when not leaving in FIFO
+		 * order, prev's next pointer needs to be fixed up etc.
+		 */
+		if (!try_cmpxchg_tail(lock, tail, 0)) {
+			next = smp_cond_load_relaxed(&node->next, VAL);
+			WRITE_ONCE(next->locked, RES_TIMEOUT_VAL);
+		}
+		lockevent_inc(rqspinlock_lock_timeout);
+		goto release;
+	}
 
 	/*
 	 * claim the lock:
@@ -395,6 +444,6 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * release the node
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
diff --git a/kernel/locking/rqspinlock.h b/kernel/locking/rqspinlock.h
new file mode 100644
index 000000000000..3cec3a0f2d7e
--- /dev/null
+++ b/kernel/locking/rqspinlock.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Resilient Queued Spin Lock defines
+ *
+ * (C) Copyright 2024 Meta Platforms, Inc. and affiliates.
+ *
+ * Authors: Kumar Kartikeya Dwivedi <memxor at gmail.com>
+ */
+#ifndef __LINUX_RQSPINLOCK_H
+#define __LINUX_RQSPINLOCK_H
+
+#include "qspinlock.h"
+
+/*
+ * try_cmpxchg_tail - Return result of cmpxchg of tail word with a new value
+ * @lock: Pointer to queued spinlock structure
+ * @tail: The tail to compare against
+ * @new_tail: The new queue tail code word
+ * Return: Bool to indicate whether the cmpxchg operation succeeded
+ *
+ * This is used by the head of the wait queue to clean up the queue.
+ * Provides relaxed ordering, since observers only rely on initialized
+ * state of the node which was made visible through the xchg_tail operation,
+ * i.e. through the smp_wmb preceding xchg_tail.
+ *
+ * We avoid using 16-bit cmpxchg, which is not available on all architectures.
+ */
+static __always_inline bool try_cmpxchg_tail(struct qspinlock *lock, u32 tail, u32 new_tail)
+{
+	u32 old, new;
+
+	old = atomic_read(&lock->val);
+	do {
+		/*
+		 * Is the tail part we compare to already stale? Fail.
+		 */
+		if ((old & _Q_TAIL_MASK) != tail)
+			return false;
+		/*
+		 * Encode latest locked/pending state for new tail.
+		 */
+		new = (old & _Q_LOCKED_PENDING_MASK) | new_tail;
+	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
+
+	return true;
+}
+
+#endif /* __LINUX_RQSPINLOCK_H */
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:51 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:51 -0800
Subject: [PATCH bpf-next v3 11/25] rqspinlock: Protect waiters in trylock fallback from stalls
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-12-memxor@gmail.com>

When we run out of maximum rqnodes, the original queued spin lock slow
path falls back to a try lock. In such a case, we are again susceptible
to stalls in case the lock owner fails to make progress. We use the
timeout as a fallback to break out of this loop and return to the
caller. This is a fallback for an extreme edge case, when on the same
CPU we run out of all 4 qnodes. When could this happen? We are in slow
path in task context, we get interrupted by an IRQ, which while in the
slow path gets interrupted by an NMI, whcih in the slow path gets
another nested NMI, which enters the slow path. All of the interruptions
happen after node->count++.

We use RES_DEF_TIMEOUT as our spinning duration, but in the case of this
fallback, no fairness is guaranteed, so the duration may be too small
for contended cases, as the waiting time is not bounded. Since this is
an extreme corner case, let's just prefer timing out instead of
attempting to spin for longer.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/rqspinlock.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 9ad18b3c46f7..16ec1b9eb005 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -271,8 +271,14 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	if (unlikely(idx >= _Q_MAX_NODES)) {
 		lockevent_inc(lock_no_node);
-		while (!queued_spin_trylock(lock))
+		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
+		while (!queued_spin_trylock(lock)) {
+			if (RES_CHECK_TIMEOUT(ts, ret)) {
+				lockevent_inc(rqspinlock_lock_timeout);
+				break;
+			}
 			cpu_relax();
+		}
 		goto release;
 	}
 
-- 
2.43.5



From memxor at gmail.com  Mon Mar  3 07:22:52 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Mon,  3 Mar 2025 07:22:52 -0800
Subject: [PATCH bpf-next v3 12/25] rqspinlock: Add deadlock detection and recovery
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <20250303152305.3195648-13-memxor@gmail.com>

While the timeout logic provides guarantees for the waiter's forward
progress, the time until a stalling waiter unblocks can still be long.
The default timeout of 1/2 sec can be excessively long for some use
cases.  Additionally, custom timeouts may exacerbate recovery time.

Introduce logic to detect common cases of deadlocks and perform quicker
recovery. This is done by dividing the time from entry into the locking
slow path until the timeout into intervals of 1 ms. Then, after each
interval elapses, deadlock detection is performed, while also polling
the lock word to ensure we can quickly break out of the detection logic
and proceed with lock acquisition.

A 'held_locks' table is maintained per-CPU where the entry at the bottom
denotes a lock being waited for or already taken. Entries coming before
it denote locks that are already held. The current CPU's table can thus
be looked at to detect AA deadlocks. The tables from other CPUs can be
looked at to discover ABBA situations. Finally, when a matching entry
for the lock being taken on the current CPU is found on some other CPU,
a deadlock situation is detected. This function can take a long time,
therefore the lock word is constantly polled in each loop iteration to
ensure we can preempt detection and proceed with lock acquisition, using
the is_lock_released check.

We set 'spin' member of rqspinlock_timeout struct to 0 to trigger
deadlock checks immediately to perform faster recovery.

Note: Extending lock word size by 4 bytes to record owner CPU can allow
faster detection for ABBA. It is typically the owner which participates
in a ABBA situation. However, to keep compatibility with existing lock
words in the kernel (struct qspinlock), and given deadlocks are a rare
event triggered by bugs, we choose to favor compatibility over faster
detection.

The release_held_lock_entry function requires an smp_wmb, while the
release store on unlock will provide the necessary ordering for us. Add
comments to document the subtleties of why this is correct. It is
possible for stores to be reordered still, but in the context of the
deadlock detection algorithm, a release barrier is sufficient and
needn't be stronger for unlock's case.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 100 +++++++++++++++++
 kernel/locking/rqspinlock.c      | 185 ++++++++++++++++++++++++++++---
 2 files changed, 271 insertions(+), 14 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index d23793d8e64d..b685f243cf96 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <vdso/time64.h>
+#include <linux/percpu.h>
 
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
@@ -22,4 +23,103 @@ extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
  */
 #define RES_DEF_TIMEOUT (NSEC_PER_SEC / 4)
 
+/*
+ * Choose 31 as it makes rqspinlock_held cacheline-aligned.
+ */
+#define RES_NR_HELD 31
+
+struct rqspinlock_held {
+	int cnt;
+	void *locks[RES_NR_HELD];
+};
+
+DECLARE_PER_CPU_ALIGNED(struct rqspinlock_held, rqspinlock_held_locks);
+
+static __always_inline void grab_held_lock_entry(void *lock)
+{
+	int cnt = this_cpu_inc_return(rqspinlock_held_locks.cnt);
+
+	if (unlikely(cnt > RES_NR_HELD)) {
+		/* Still keep the inc so we decrement later. */
+		return;
+	}
+
+	/*
+	 * Implied compiler barrier in per-CPU operations; otherwise we can have
+	 * the compiler reorder inc with write to table, allowing interrupts to
+	 * overwrite and erase our write to the table (as on interrupt exit it
+	 * will be reset to NULL).
+	 *
+	 * It is fine for cnt inc to be reordered wrt remote readers though,
+	 * they won't observe our entry until the cnt update is visible, that's
+	 * all.
+	 */
+	this_cpu_write(rqspinlock_held_locks.locks[cnt - 1], lock);
+}
+
+/*
+ * We simply don't support out-of-order unlocks, and keep the logic simple here.
+ * The verifier prevents BPF programs from unlocking out-of-order, and the same
+ * holds for in-kernel users.
+ *
+ * It is possible to run into misdetection scenarios of AA deadlocks on the same
+ * CPU, and missed ABBA deadlocks on remote CPUs if this function pops entries
+ * out of order (due to lock A, lock B, unlock A, unlock B) pattern. The correct
+ * logic to preserve right entries in the table would be to walk the array of
+ * held locks and swap and clear out-of-order entries, but that's too
+ * complicated and we don't have a compelling use case for out of order unlocking.
+ */
+static __always_inline void release_held_lock_entry(void)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (unlikely(rqh->cnt > RES_NR_HELD))
+		goto dec;
+	WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL);
+dec:
+	/*
+	 * Reordering of clearing above with inc and its write in
+	 * grab_held_lock_entry that came before us (in same acquisition
+	 * attempt) is ok, we either see a valid entry or NULL when it's
+	 * visible.
+	 *
+	 * But this helper is invoked when we unwind upon failing to acquire the
+	 * lock. Unlike the unlock path which constitutes a release store after
+	 * we clear the entry, we need to emit a write barrier here. Otherwise,
+	 * we may have a situation as follows:
+	 *
+	 * <error> for lock B
+	 * release_held_lock_entry
+	 *
+	 * try_cmpxchg_acquire for lock A
+	 * grab_held_lock_entry
+	 *
+	 * Lack of any ordering means reordering may occur such that dec, inc
+	 * are done before entry is overwritten. This permits a remote lock
+	 * holder of lock B (which this CPU failed to acquire) to now observe it
+	 * as being attempted on this CPU, and may lead to misdetection (if this
+	 * CPU holds a lock it is attempting to acquire, leading to false ABBA
+	 * diagnosis).
+	 *
+	 * In case of unlock, we will always do a release on the lock word after
+	 * releasing the entry, ensuring that other CPUs cannot hold the lock
+	 * (and make conclusions about deadlocks) until the entry has been
+	 * cleared on the local CPU, preventing any anomalies. Reordering is
+	 * still possible there, but a remote CPU cannot observe a lock in our
+	 * table which it is already holding, since visibility entails our
+	 * release store for the said lock has not retired.
+	 *
+	 * In theory we don't have a problem if the dec and WRITE_ONCE above get
+	 * reordered with each other, we either notice an empty NULL entry on
+	 * top (if dec succeeds WRITE_ONCE), or a potentially stale entry which
+	 * cannot be observed (if dec precedes WRITE_ONCE).
+	 *
+	 * Emit the write barrier _before_ the dec, this permits dec-inc
+	 * reordering but that is harmless as we'd have new entry set to NULL
+	 * already, i.e. they cannot precede the NULL store above.
+	 */
+	smp_wmb();
+	this_cpu_dec(rqspinlock_held_locks.cnt);
+}
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index 16ec1b9eb005..ce2bc0a85a07 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -31,6 +31,7 @@
  */
 #include "qspinlock.h"
 #include "lock_events.h"
+#include "rqspinlock.h"
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -74,16 +75,146 @@
 struct rqspinlock_timeout {
 	u64 timeout_end;
 	u64 duration;
+	u64 cur;
 	u16 spin;
 };
 
 #define RES_TIMEOUT_VAL	2
 
-static noinline int check_timeout(struct rqspinlock_timeout *ts)
+DEFINE_PER_CPU_ALIGNED(struct rqspinlock_held, rqspinlock_held_locks);
+
+static bool is_lock_released(rqspinlock_t *lock, u32 mask, struct rqspinlock_timeout *ts)
+{
+	if (!(atomic_read_acquire(&lock->val) & (mask)))
+		return true;
+	return false;
+}
+
+static noinline int check_deadlock_AA(rqspinlock_t *lock, u32 mask,
+				      struct rqspinlock_timeout *ts)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+	int cnt = min(RES_NR_HELD, rqh->cnt);
+
+	/*
+	 * Return an error if we hold the lock we are attempting to acquire.
+	 * We'll iterate over max 32 locks; no need to do is_lock_released.
+	 */
+	for (int i = 0; i < cnt - 1; i++) {
+		if (rqh->locks[i] == lock)
+			return -EDEADLK;
+	}
+	return 0;
+}
+
+/*
+ * This focuses on the most common case of ABBA deadlocks (or ABBA involving
+ * more locks, which reduce to ABBA). This is not exhaustive, and we rely on
+ * timeouts as the final line of defense.
+ */
+static noinline int check_deadlock_ABBA(rqspinlock_t *lock, u32 mask,
+					struct rqspinlock_timeout *ts)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+	int rqh_cnt = min(RES_NR_HELD, rqh->cnt);
+	void *remote_lock;
+	int cpu;
+
+	/*
+	 * Find the CPU holding the lock that we want to acquire. If there is a
+	 * deadlock scenario, we will read a stable set on the remote CPU and
+	 * find the target. This would be a constant time operation instead of
+	 * O(NR_CPUS) if we could determine the owning CPU from a lock value, but
+	 * that requires increasing the size of the lock word.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct rqspinlock_held *rqh_cpu = per_cpu_ptr(&rqspinlock_held_locks, cpu);
+		int real_cnt = READ_ONCE(rqh_cpu->cnt);
+		int cnt = min(RES_NR_HELD, real_cnt);
+
+		/*
+		 * Let's ensure to break out of this loop if the lock is available for
+		 * us to potentially acquire.
+		 */
+		if (is_lock_released(lock, mask, ts))
+			return 0;
+
+		/*
+		 * Skip ourselves, and CPUs whose count is less than 2, as they need at
+		 * least one held lock and one acquisition attempt (reflected as top
+		 * most entry) to participate in an ABBA deadlock.
+		 *
+		 * If cnt is more than RES_NR_HELD, it means the current lock being
+		 * acquired won't appear in the table, and other locks in the table are
+		 * already held, so we can't determine ABBA.
+		 */
+		if (cpu == smp_processor_id() || real_cnt < 2 || real_cnt > RES_NR_HELD)
+			continue;
+
+		/*
+		 * Obtain the entry at the top, this corresponds to the lock the
+		 * remote CPU is attempting to acquire in a deadlock situation,
+		 * and would be one of the locks we hold on the current CPU.
+		 */
+		remote_lock = READ_ONCE(rqh_cpu->locks[cnt - 1]);
+		/*
+		 * If it is NULL, we've raced and cannot determine a deadlock
+		 * conclusively, skip this CPU.
+		 */
+		if (!remote_lock)
+			continue;
+		/*
+		 * Find if the lock we're attempting to acquire is held by this CPU.
+		 * Don't consider the topmost entry, as that must be the latest lock
+		 * being held or acquired.  For a deadlock, the target CPU must also
+		 * attempt to acquire a lock we hold, so for this search only 'cnt - 1'
+		 * entries are important.
+		 */
+		for (int i = 0; i < cnt - 1; i++) {
+			if (READ_ONCE(rqh_cpu->locks[i]) != lock)
+				continue;
+			/*
+			 * We found our lock as held on the remote CPU.  Is the
+			 * acquisition attempt on the remote CPU for a lock held
+			 * by us?  If so, we have a deadlock situation, and need
+			 * to recover.
+			 */
+			for (int i = 0; i < rqh_cnt - 1; i++) {
+				if (rqh->locks[i] == remote_lock)
+					return -EDEADLK;
+			}
+			/*
+			 * Inconclusive; retry again later.
+			 */
+			return 0;
+		}
+	}
+	return 0;
+}
+
+static noinline int check_deadlock(rqspinlock_t *lock, u32 mask,
+				   struct rqspinlock_timeout *ts)
+{
+	int ret;
+
+	ret = check_deadlock_AA(lock, mask, ts);
+	if (ret)
+		return ret;
+	ret = check_deadlock_ABBA(lock, mask, ts);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
+				  struct rqspinlock_timeout *ts)
 {
 	u64 time = ktime_get_mono_fast_ns();
+	u64 prev = ts->cur;
 
 	if (!ts->timeout_end) {
+		ts->cur = time;
 		ts->timeout_end = time + ts->duration;
 		return 0;
 	}
@@ -91,6 +222,15 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
 	if (time > ts->timeout_end)
 		return -ETIMEDOUT;
 
+	/*
+	 * A millisecond interval passed from last time? Trigger deadlock
+	 * checks.
+	 */
+	if (prev + NSEC_PER_MSEC < time) {
+		ts->cur = time;
+		return check_deadlock(lock, mask, ts);
+	}
+
 	return 0;
 }
 
@@ -99,21 +239,22 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
  * as the macro does internal amortization for us.
  */
 #ifndef res_smp_cond_load_acquire
-#define RES_CHECK_TIMEOUT(ts, ret)                    \
-	({                                            \
-		if (!(ts).spin++)                     \
-			(ret) = check_timeout(&(ts)); \
-		(ret);                                \
+#define RES_CHECK_TIMEOUT(ts, ret, mask)                              \
+	({                                                            \
+		if (!(ts).spin++)                                     \
+			(ret) = check_timeout((lock), (mask), &(ts)); \
+		(ret);                                                \
 	})
 #else
-#define RES_CHECK_TIMEOUT(ts, ret, mask)	      \
+#define RES_CHECK_TIMEOUT(ts, ret, mask)			      \
 	({ (ret) = check_timeout(&(ts)); })
 #endif
 
 /*
  * Initialize the 'spin' member.
+ * Set spin member to 0 to trigger AA/ABBA checks immediately.
  */
-#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 1; })
+#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 0; })
 
 /*
  * We only need to reset 'timeout_end', 'spin' will just wrap around as necessary.
@@ -208,6 +349,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		goto queue;
 	}
 
+	/*
+	 * Grab an entry in the held locks array, to enable deadlock detection.
+	 */
+	grab_held_lock_entry(lock);
+
 	/*
 	 * We're pending, wait for the owner to go away.
 	 *
@@ -221,7 +367,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	if (val & _Q_LOCKED_MASK) {
 		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
-		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret));
+		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret, _Q_LOCKED_MASK));
 	}
 
 	if (ret) {
@@ -236,7 +382,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		 */
 		clear_pending(lock);
 		lockevent_inc(rqspinlock_lock_timeout);
-		return ret;
+		goto err_release_entry;
 	}
 
 	/*
@@ -254,6 +400,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 queue:
 	lockevent_inc(lock_slowpath);
+	/*
+	 * Grab deadlock detection entry for the queue path.
+	 */
+	grab_held_lock_entry(lock);
+
 	node = this_cpu_ptr(&rqnodes[0].mcs);
 	idx = node->count++;
 	tail = encode_tail(smp_processor_id(), idx);
@@ -273,9 +424,9 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		lockevent_inc(lock_no_node);
 		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
 		while (!queued_spin_trylock(lock)) {
-			if (RES_CHECK_TIMEOUT(ts, ret)) {
+			if (RES_CHECK_TIMEOUT(ts, ret, ~0u)) {
 				lockevent_inc(rqspinlock_lock_timeout);
-				break;
+				goto err_release_node;
 			}
 			cpu_relax();
 		}
@@ -371,7 +522,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT * 2);
 	val = res_atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK) ||
-					   RES_CHECK_TIMEOUT(ts, ret));
+					   RES_CHECK_TIMEOUT(ts, ret, _Q_LOCKED_PENDING_MASK));
 
 waitq_timeout:
 	if (ret) {
@@ -404,7 +555,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 			WRITE_ONCE(next->locked, RES_TIMEOUT_VAL);
 		}
 		lockevent_inc(rqspinlock_lock_timeout);
-		goto release;
+		goto err_release_node;
 	}
 
 	/*
@@ -451,5 +602,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
 	return ret;
+err_release_node:
+	trace_contention_end(lock, ret);
+	__this_cpu_dec(rqnodes[0].mcs.count);
+err_release_entry:
+	release_held_lock_entry();
+	return ret;
 }
 EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath);
-- 
2.43.5



From rostedt at goodmis.org  Mon Mar  3 08:05:59 2025
From: rostedt at goodmis.org (Steven Rostedt)
Date: Mon, 3 Mar 2025 11:05:59 -0500
Subject: [PATCH bpf-next v3 3/4] x86: implement per-function metadata
 storage for x86
In-Reply-To: <20250303065345.229298-4-dongml2@chinatelecom.cn>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
	<20250303065345.229298-4-dongml2@chinatelecom.cn>
Message-ID: <20250303110559.5a584602@gandalf.local.home>

On Mon,  3 Mar 2025 14:53:44 +0800
Menglong Dong <menglong8.dong at gmail.com> wrote:

> In the third case, we make the kernel function 32 bytes aligned, and there
> will be 32 bytes padding before the functions. According to my testing,
> the text size didn't increase on this case, which is weird.
> 
> With 16-bytes padding:
> 
> -rwxr-xr-x 1 401190688  x86-dev/vmlinux*
> -rw-r--r-- 1    251068  x86-dev/vmlinux.a
> -rw-r--r-- 1 851892992  x86-dev/vmlinux.o
> -rw-r--r-- 1  12395008  x86-dev/arch/x86/boot/bzImage
> 
> With 32-bytes padding:
> 
> -rwxr-xr-x 1 401318128 x86-dev/vmlinux*
> -rw-r--r-- 1    251154 x86-dev/vmlinux.a
> -rw-r--r-- 1 853636704 x86-dev/vmlinux.o
> -rw-r--r-- 1  12509696 x86-dev/arch/x86/boot/bzImage

Use the "size" command to see the differences in sizes and not the file size.

$ size vmlinux
   text    data     bss     dec     hex filename
36892658        9798658 16982016        63673332        3cb93f4 vmlinux

-- Steve


From sven at svenpeter.dev  Mon Mar  3 08:07:59 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Mon, 03 Mar 2025 17:07:59 +0100
Subject: [PATCH] MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple
 support
In-Reply-To: <20250303154012.1417088-1-neal@gompa.dev>
References: <20250303154012.1417088-1-neal@gompa.dev>
Message-ID: <634502ea-6389-43c8-8236-7f90f864f73a@app.fastmail.com>

On Mon, Mar 3, 2025, at 16:40, Neal Gompa wrote:
> As a member of the Asahi Linux project, I (Neal) have been involved in
> reviewing the patches downstream as part of enabling the Fedora Asahi Remix
> distribution for years and have recently been reviewing patches for upstream
> submission as well.
>
> This formalizes my role as a reviewer for ARM Apple system support patches.
>
> Signed-off-by: Neal Gompa <neal at gompa.dev>
> ---

Acked-by: Sven Peter <sven at svenpeter.dev>

Nothing much to add to that. You've been reviewing all of our downstream
patches when preparing Fedora Asahi Remix kernels for quite a while now
and provided good feedback so it makes sense to make this official.

I'll pick this up in a few days together with an update to MAINTAINERS
that includes our SPI driver files which I think we missed last year [1].



Best,


Sven


[1] https://lore.kernel.org/asahi/20241106-asahi-spi-v5-3-e81a4f3a8e19 at jannau.net/


From leo.yan at arm.com  Mon Mar  3 08:22:10 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 3 Mar 2025 16:22:10 +0000
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
 <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
Message-ID: <20250303162210.GH2157064@e132581.arm.com>

Hi Adrian,

On Mon, Mar 03, 2025 at 12:44:33PM +0200, Adrian Hunter wrote:
> On 17/02/25 21:58, Leo Yan wrote:
> > Add a check for the generated string of flags.  Print out the raw number
> > if the string generation fails.
> 
> How does it fail?

In practice, I agreed perf_sample__sprintf_flags() will not fail.  This
bases on a careful calculation for every invoking snprintf().

Please see comment below.

> > In another case, if the string length is longer than the aligned size,
> > allow the completed string to be printed.
> > 
> > Reviewed-by: Ian Rogers <irogers at google.com>
> > Reviewed-by: James Clark <james.clark at linaro.org>
> > Signed-off-by: Leo Yan <leo.yan at arm.com>
> > ---
> >  tools/perf/builtin-script.c   | 10 ++++++++--
> >  tools/perf/util/trace-event.h |  2 ++
> >  2 files changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> > index d797cec4f054..2c4b1fb7dc72 100644
> > --- a/tools/perf/builtin-script.c
> > +++ b/tools/perf/builtin-script.c
> > @@ -1709,9 +1709,15 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
> >  static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
> >  {
> >  	char str[SAMPLE_FLAGS_BUF_SIZE];
> > +	int ret;
> > +
> > +	ret = perf_sample__sprintf_flags(flags, str, sizeof(str));
> > +	if (ret < 0)
> 
> AFAICT ret is always >= 0

Since I refactored perf_sample__sprintf_flags() in the sequential
patches, for easier capturing and debugging, here checks the return
value to detect any potential issues.

Later when we review a perf log, a printed raw number for error cases
can remind there must be something wrong for printing flags.

> > +		return fprintf(fp, "  raw flags:0x%-*x ",
> > +			       SAMPLE_FLAGS_STR_ALIGNED_SIZE - 12, flags);
> >  
> > -	perf_sample__sprintf_flags(flags, str, sizeof(str));
> > -	return fprintf(fp, "  %-21s ", str);
> > +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
> > +	return fprintf(fp, "  %-*s ", ret, str);
> 
> -21 means the field width is 21 and left-justified.  It should not
> truncate the string.

No, it does not truncate the string.

It calculates a maximum value between the returned length and 21 (
defined in SAMPLE_FLAGS_STR_ALIGNED_SIZE).  It keeps left-justified and
can printing a complete string if the string length is bigger than 21.

Thanks,
Leo

> 
> >  }
> >  
> >  struct printer_data {
> > diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
> > index ac9fde2f980c..71e680bc3d4b 100644
> > --- a/tools/perf/util/trace-event.h
> > +++ b/tools/perf/util/trace-event.h
> > @@ -145,6 +145,8 @@ int common_flags(struct scripting_context *context);
> >  int common_lock_depth(struct scripting_context *context);
> >  
> >  #define SAMPLE_FLAGS_BUF_SIZE 64
> > +#define SAMPLE_FLAGS_STR_ALIGNED_SIZE	21
> > +
> >  int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz);
> >  
> >  #if defined(LIBTRACEEVENT_VERSION) &&  LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0)
> 


From Frank.li at nxp.com  Mon Mar  3 08:27:11 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 11:27:11 -0500
Subject: [PATCH v15 07/15] PCI: endpoint: pci-ep-msi: Add MSI
 address/data pair mutable check
In-Reply-To: <86mse5otzh.wl-maz@kernel.org>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
 <20250211-ep-msi-v15-7-bcacc1f2b1a9@nxp.com>
 <86mse5otzh.wl-maz@kernel.org>
Message-ID: <Z8XYX/D5c/+PuOg5@lizhi-Precision-Tower-5810>

On Sat, Mar 01, 2025 at 11:44:50AM +0000, Marc Zyngier wrote:
> On Tue, 11 Feb 2025 19:22:00 +0000,
> Frank Li <Frank.Li at nxp.com> wrote:
> >
> > Some MSI controller change address/data pair when irq_set_affinity().
> > Current PCI endpoint can't support this type MSI controller. So add flag
> > MSI_FLAG_MUTABLE in include/linux/msi.h and check it when allocate
> > doorbell.
> >
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> > change from v14 to v15
> > - none
> >
> > change from  v13 to v14
> > - bring v10 back
> >
> > Change from v9 to v10
> > - new patch
> > ---
> >  drivers/pci/endpoint/pci-ep-msi.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/drivers/pci/endpoint/pci-ep-msi.c b/drivers/pci/endpoint/pci-ep-msi.c
> > index 549b55b864d0e..c0e2d806ee658 100644
> > --- a/drivers/pci/endpoint/pci-ep-msi.c
> > +++ b/drivers/pci/endpoint/pci-ep-msi.c
> > @@ -44,6 +44,14 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)
> >
> >  	dev_set_msi_domain(dev, dom);
> >
> > +	if (!irq_domain_is_msi_parent(dom))
> > +		return -EINVAL;
> > +
> > +	if (!irq_domain_is_msi_immutable(dom)) {
> > +		dev_err(dev, "Can't support mutable address/data pair MSI controller\n");
> > +		return -EINVAL;
> > +	}
> > +
> >  	msg = kcalloc(num_db, sizeof(struct pci_epf_doorbell_msg), GFP_KERNEL);
> >  	if (!msg)
> >  		return -ENOMEM;
> >
>
> I really don't think this brings much to the table. These systems are
> not built by picking up random bits that can be put together by hand.
> They are integrated in an SoC, and I can't imagine that the MSI
> controller is picked randomly.
>
> So my conclusion is that this is either *designed* to work, or it
> doesn't exist, and that this code is just dead code.

I think Thomas answer this question. This code is actually safty check MSI
provider's capablity. If MSI provider can't address/pair is not immutable,
there are big risk when irq change affinity.

https://lore.kernel.org/imx/87senwd3mo.ffs at tglx/

"Yes and no. The problem is that the EP implementation is meant to be a
generic library and while GIC-ITS guarantees immutability of the
address/data pair after setup, there are architectures (x86, loongson,
riscv) where the base MSI controller does not and immutability is only
achieved when interrupt remapping is enabled. The latter can be disabled
at boot-time and then the EP implementation becomes a lottery across
affinity changes.

That was my concern about this library implementation and that's why I
asked for a mechanism to ensure that the underlying irqdomain provides a
immutable address/data pair.

So it does not matter for GIC-ITS, but in the larger picture it matters.
"

Let me know if I miss understand your means.

Frank


>
> Thanks,
>
> 	M.
>
> --
> Without deviation from the norm, progress is not possible.


From robh at kernel.org  Mon Mar  3 08:37:16 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 3 Mar 2025 10:37:16 -0600
Subject: (subset) [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <2d51cb9e-b8c5-4cf1-bd7a-751fb633275c@linaro.org>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com> <174047913824.2131221.6545389561298332217.b4-ty@linaro.org>
 <CAA8EJpqM8ZQ-ScEtEBXaUF2Nargtp_TBAyMYvbJ49PGbwPWjaQ@mail.gmail.com> <2d51cb9e-b8c5-4cf1-bd7a-751fb633275c@linaro.org>
Message-ID: <CAL_JsqKXguOAK2pge-TwH4M8JC3UnEi_ia_7QjrgE_6KZzGucg@mail.gmail.com>

On Tue, Feb 25, 2025 at 11:59?AM Neil Armstrong
<neil.armstrong at linaro.org> wrote:
>
> On 25/02/2025 12:37, Dmitry Baryshkov wrote:
> > On Tue, 25 Feb 2025 at 12:25, Neil Armstrong <neil.armstrong at linaro.org> wrote:
> >>
> >> Hi,
> >>
> >> On Mon, 17 Feb 2025 12:39:30 +0100, Sasha Finkelstein wrote:
> >>> This patch series adds support for a secondary display controller
> >>> present on Apple M1/M2 chips and used to drive the display of the
> >>> "touchbar" touch panel present on those.
> >>>
> >>>
> >>
> >> Thanks, Applied to https://gitlab.freedesktop.org/drm/misc/kernel.git (drm-misc-next)
> >>
> >> [3/5] drm: panel: Add a panel driver for the Summit display
> >>        https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/40115947b59f2ca361a47615304dff0a2b69a2b4
> >
> > Without the bindings?!
> >
>
> Bindings will be funneled with the rest of the ADP driver, the panel driver can be applied individually.

Uh, no. The bindings go with the user. Now 'make dt_compatible_check'
reports apple,summit is not documented.

Rob


From alyssa at rosenzweig.io  Mon Mar  3 08:43:11 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Mon, 3 Mar 2025 11:43:11 -0500
Subject: [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
 <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org>
Message-ID: <Z8XcH7xoDC7TA7ZC@blossom>

> > Sasha Finkelstein (5):
> >        dt-bindings: display: Add Apple pre-DCP display controller
> >        drm: adp: Add Apple Display Pipe driver
> >        drm: panel: Add a panel driver for the Summit display
> >        arm64: dts: apple: Add touchbar screen nodes
> >        MAINTAINERS: Add entries for touchbar display driver
> > 
> >   .../display/apple,h7-display-pipe-mipi.yaml        |  83 +++
> >   .../bindings/display/apple,h7-display-pipe.yaml    |  88 +++
> >   .../bindings/display/panel/apple,summit.yaml       |  58 ++
> >   MAINTAINERS                                        |  16 +
> >   arch/arm64/boot/dts/apple/t8103-j293.dts           |  31 ++
> >   arch/arm64/boot/dts/apple/t8103.dtsi               |  61 ++
> >   arch/arm64/boot/dts/apple/t8112-j493.dts           |  31 ++
> >   arch/arm64/boot/dts/apple/t8112.dtsi               |  61 ++
> >   drivers/gpu/drm/Kconfig                            |   2 +
> >   drivers/gpu/drm/Makefile                           |   1 +
> >   drivers/gpu/drm/adp/Kconfig                        |  17 +
> >   drivers/gpu/drm/adp/Makefile                       |   5 +
> >   drivers/gpu/drm/adp/adp-mipi.c                     | 276 +++++++++
> >   drivers/gpu/drm/adp/adp_drv.c                      | 617 +++++++++++++++++++++
> >   drivers/gpu/drm/panel/Kconfig                      |   9 +
> >   drivers/gpu/drm/panel/Makefile                     |   1 +
> >   drivers/gpu/drm/panel/panel-summit.c               | 132 +++++
> >   17 files changed, 1489 insertions(+)
> > ---
> > base-commit: b62cef9a5c673f1b8083159f5dc03c1c5daced2f
> > change-id: 20241124-adpdrm-25fce3dd8a71
> > 
> > 
> 
> All patches are reviewed, can we funnel patches 1, 2 & 5 via drm-misc-next now ?

I'm planning to do so today, just need to get dim setup first :)


From neil.armstrong at linaro.org  Mon Mar  3 08:42:22 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 3 Mar 2025 17:42:22 +0100
Subject: [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
Message-ID: <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org>

Hi,

On 17/02/2025 12:39, Sasha Finkelstein via B4 Relay wrote:
> Hi.
> 
> This patch series adds support for a secondary display controller
> present on Apple M1/M2 chips and used to drive the display of the
> "touchbar" touch panel present on those.
> 
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
> Changes in v7:
> - No changes aside from adding r-b trailers, effectively a resend.
> - Link to v6: https://lore.kernel.org/r/20250206-adpdrm-v6-0-c8ab9348b853 at gmail.com
> 
> Changes in v6:
> - Use the drm_connector_helper_get_modes_fixed helper.
> - Split out into a separate MAINTAINERS entry
> - Link to v5: https://lore.kernel.org/r/20250205-adpdrm-v5-0-4e4ec979bbf2 at gmail.com
> 
> Changes in v5:
> - Moved to using the component framework.
> - Other lifetime fixes
> - Link to v4: https://lore.kernel.org/r/20250114-adpdrm-v4-0-e9b5260a39f1 at gmail.com
> 
> Changes in v4:
> - Fixed dt bindings.
> - Link to v3: https://lore.kernel.org/r/20250112-adpdrm-v3-0-c674dc19fa7f at gmail.com
> 
> Changes in v3:
> - Fixed building as module after splitting out mipi block
> - Addressing the review feedback.
> - Link to v2: https://lore.kernel.org/r/20241126-adpdrm-v2-0-c90485336c09 at gmail.com
> 
> Changes in v2:
> - Addressing the review feedback.
> - Split out the mipi part of the display controller into a separate device
> - Link to v1: https://lore.kernel.org/r/20241124-adpdrm-v1-0-3191d8e6e49a at gmail.com
> 
> ---
> Sasha Finkelstein (5):
>        dt-bindings: display: Add Apple pre-DCP display controller
>        drm: adp: Add Apple Display Pipe driver
>        drm: panel: Add a panel driver for the Summit display
>        arm64: dts: apple: Add touchbar screen nodes
>        MAINTAINERS: Add entries for touchbar display driver
> 
>   .../display/apple,h7-display-pipe-mipi.yaml        |  83 +++
>   .../bindings/display/apple,h7-display-pipe.yaml    |  88 +++
>   .../bindings/display/panel/apple,summit.yaml       |  58 ++
>   MAINTAINERS                                        |  16 +
>   arch/arm64/boot/dts/apple/t8103-j293.dts           |  31 ++
>   arch/arm64/boot/dts/apple/t8103.dtsi               |  61 ++
>   arch/arm64/boot/dts/apple/t8112-j493.dts           |  31 ++
>   arch/arm64/boot/dts/apple/t8112.dtsi               |  61 ++
>   drivers/gpu/drm/Kconfig                            |   2 +
>   drivers/gpu/drm/Makefile                           |   1 +
>   drivers/gpu/drm/adp/Kconfig                        |  17 +
>   drivers/gpu/drm/adp/Makefile                       |   5 +
>   drivers/gpu/drm/adp/adp-mipi.c                     | 276 +++++++++
>   drivers/gpu/drm/adp/adp_drv.c                      | 617 +++++++++++++++++++++
>   drivers/gpu/drm/panel/Kconfig                      |   9 +
>   drivers/gpu/drm/panel/Makefile                     |   1 +
>   drivers/gpu/drm/panel/panel-summit.c               | 132 +++++
>   17 files changed, 1489 insertions(+)
> ---
> base-commit: b62cef9a5c673f1b8083159f5dc03c1c5daced2f
> change-id: 20241124-adpdrm-25fce3dd8a71
> 
> 

All patches are reviewed, can we funnel patches 1, 2 & 5 via drm-misc-next now ?

Neil



From robh at kernel.org  Mon Mar  3 08:44:21 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 3 Mar 2025 10:44:21 -0600
Subject: [PATCH v20 00/11] arm64/perf: Enable branch stack sampling
In-Reply-To: <174080569248.3208873.17639032755999041028.b4-ty@kernel.org>
References: <20250218-arm-brbe-v19-v20-0-4e9922fc2e8e@kernel.org> <174080569248.3208873.17639032755999041028.b4-ty@kernel.org>
Message-ID: <CAL_JsqLijFG1PFkqKk7hXzC=aj70OLQsXwC280QsCO=PnCVZYg@mail.gmail.com>

On Sat, Mar 1, 2025 at 1:05?AM Will Deacon <will at kernel.org> wrote:
>
> On Tue, 18 Feb 2025 14:39:55 -0600, Rob Herring (Arm) wrote:
> > This series enables perf branch stack sampling support on arm64 via a
> > v9.2 arch feature called Branch Record Buffer Extension (BRBE). Details
> > on BRBE can be found in the Arm ARM[1] chapter D18.
> >
> > I've picked up this series from Anshuman. v19 and v20 versions have been
> > reworked quite a bit by Mark and myself. The bulk of those changes are
> > in patch 11.
> >
> > [...]
>
> Applied cleanups to will (for-next/perf), thanks!
>
> [01/11] perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling counters
>         https://git.kernel.org/will/c/04bd15c4cbc3
> [02/11] perf: arm_pmu: Don't disable counter in armpmu_add()
>         https://git.kernel.org/will/c/dcca27bc1ecc
> [03/11] perf: arm_pmuv3: Don't disable counter in armv8pmu_enable_event()
>         https://git.kernel.org/will/c/4b0567ad0be5
> [04/11] perf: arm_v7_pmu: Drop obvious comments for enabling/disabling counters and interrupts
>         https://git.kernel.org/will/c/7a5387748215
> [05/11] perf: arm_v7_pmu: Don't disable counter in (armv7|krait_|scorpion_)pmu_enable_event()
>         https://git.kernel.org/will/c/7bf1001e0d91
> [06/11] perf: apple_m1: Don't disable counter in m1_pmu_enable_event()
>         https://git.kernel.org/will/c/c2e793da59fc
> [07/11] perf: arm_pmu: Move PMUv3-specific data
>         https://git.kernel.org/will/c/dc4d58a752ea

I don't know if you looked at the thread on patch 11 and said "long
discussion, I'll assume a new version is coming. Next!" because that's
what I would do. In this case though, there's not any changes.

Rob


From adrian.hunter at intel.com  Mon Mar  3 07:05:13 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Mon, 3 Mar 2025 17:05:13 +0200
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <20250303162210.GH2157064@e132581.arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
 <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
 <20250303162210.GH2157064@e132581.arm.com>
Message-ID: <447bcafc-4c47-4b95-bf21-7aee2cb6a629@intel.com>

On 3/03/25 18:22, Leo Yan wrote:
> Hi Adrian,
> 
> On Mon, Mar 03, 2025 at 12:44:33PM +0200, Adrian Hunter wrote:
>> On 17/02/25 21:58, Leo Yan wrote:
>>> Add a check for the generated string of flags.  Print out the raw number
>>> if the string generation fails.
>>
>> How does it fail?
> 
> In practice, I agreed perf_sample__sprintf_flags() will not fail.  This
> bases on a careful calculation for every invoking snprintf().
> 
> Please see comment below.
> 
>>> In another case, if the string length is longer than the aligned size,
>>> allow the completed string to be printed.
>>>
>>> Reviewed-by: Ian Rogers <irogers at google.com>
>>> Reviewed-by: James Clark <james.clark at linaro.org>
>>> Signed-off-by: Leo Yan <leo.yan at arm.com>
>>> ---
>>>  tools/perf/builtin-script.c   | 10 ++++++++--
>>>  tools/perf/util/trace-event.h |  2 ++
>>>  2 files changed, 10 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
>>> index d797cec4f054..2c4b1fb7dc72 100644
>>> --- a/tools/perf/builtin-script.c
>>> +++ b/tools/perf/builtin-script.c
>>> @@ -1709,9 +1709,15 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
>>>  static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
>>>  {
>>>  	char str[SAMPLE_FLAGS_BUF_SIZE];
>>> +	int ret;
>>> +
>>> +	ret = perf_sample__sprintf_flags(flags, str, sizeof(str));
>>> +	if (ret < 0)
>>
>> AFAICT ret is always >= 0
> 
> Since I refactored perf_sample__sprintf_flags() in the sequential
> patches, for easier capturing and debugging, here checks the return
> value to detect any potential issues.
> 
> Later when we review a perf log, a printed raw number for error cases
> can remind there must be something wrong for printing flags.
> 
>>> +		return fprintf(fp, "  raw flags:0x%-*x ",
>>> +			       SAMPLE_FLAGS_STR_ALIGNED_SIZE - 12, flags);
>>>  
>>> -	perf_sample__sprintf_flags(flags, str, sizeof(str));
>>> -	return fprintf(fp, "  %-21s ", str);
>>> +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
>>> +	return fprintf(fp, "  %-*s ", ret, str);
>>
>> -21 means the field width is 21 and left-justified.  It should not
>> truncate the string.
> 
> No, it does not truncate the string.
> 
> It calculates a maximum value between the returned length and 21 (
> defined in SAMPLE_FLAGS_STR_ALIGNED_SIZE).  It keeps left-justified and
> can printing a complete string if the string length is bigger than 21.

Maybe I am missing something, but that isn't that what

	return fprintf(fp, "  %-21s ", str);

does anyway?  Why change it to something more complicated.

> 
> 
>>
>>>  }
>>>  
>>>  struct printer_data {
>>> diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
>>> index ac9fde2f980c..71e680bc3d4b 100644
>>> --- a/tools/perf/util/trace-event.h
>>> +++ b/tools/perf/util/trace-event.h
>>> @@ -145,6 +145,8 @@ int common_flags(struct scripting_context *context);
>>>  int common_lock_depth(struct scripting_context *context);
>>>  
>>>  #define SAMPLE_FLAGS_BUF_SIZE 64
>>> +#define SAMPLE_FLAGS_STR_ALIGNED_SIZE	21
>>> +
>>>  int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz);
>>>  
>>>  #if defined(LIBTRACEEVENT_VERSION) &&  LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0)
>>



From neil.armstrong at linaro.org  Mon Mar  3 08:48:35 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 3 Mar 2025 17:48:35 +0100
Subject: [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <Z8XcH7xoDC7TA7ZC@blossom>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
 <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org> <Z8XcH7xoDC7TA7ZC@blossom>
Message-ID: <7a84f5fa-7128-4b51-8b05-e557e21663d8@linaro.org>

On 03/03/2025 17:43, Alyssa Rosenzweig wrote:
>>> Sasha Finkelstein (5):
>>>         dt-bindings: display: Add Apple pre-DCP display controller
>>>         drm: adp: Add Apple Display Pipe driver
>>>         drm: panel: Add a panel driver for the Summit display
>>>         arm64: dts: apple: Add touchbar screen nodes
>>>         MAINTAINERS: Add entries for touchbar display driver
>>>
>>>    .../display/apple,h7-display-pipe-mipi.yaml        |  83 +++
>>>    .../bindings/display/apple,h7-display-pipe.yaml    |  88 +++
>>>    .../bindings/display/panel/apple,summit.yaml       |  58 ++
>>>    MAINTAINERS                                        |  16 +
>>>    arch/arm64/boot/dts/apple/t8103-j293.dts           |  31 ++
>>>    arch/arm64/boot/dts/apple/t8103.dtsi               |  61 ++
>>>    arch/arm64/boot/dts/apple/t8112-j493.dts           |  31 ++
>>>    arch/arm64/boot/dts/apple/t8112.dtsi               |  61 ++
>>>    drivers/gpu/drm/Kconfig                            |   2 +
>>>    drivers/gpu/drm/Makefile                           |   1 +
>>>    drivers/gpu/drm/adp/Kconfig                        |  17 +
>>>    drivers/gpu/drm/adp/Makefile                       |   5 +
>>>    drivers/gpu/drm/adp/adp-mipi.c                     | 276 +++++++++
>>>    drivers/gpu/drm/adp/adp_drv.c                      | 617 +++++++++++++++++++++
>>>    drivers/gpu/drm/panel/Kconfig                      |   9 +
>>>    drivers/gpu/drm/panel/Makefile                     |   1 +
>>>    drivers/gpu/drm/panel/panel-summit.c               | 132 +++++
>>>    17 files changed, 1489 insertions(+)
>>> ---
>>> base-commit: b62cef9a5c673f1b8083159f5dc03c1c5daced2f
>>> change-id: 20241124-adpdrm-25fce3dd8a71
>>>
>>>
>>
>> All patches are reviewed, can we funnel patches 1, 2 & 5 via drm-misc-next now ?
> 
> I'm planning to do so today, just need to get dim setup first :)

Nice, go ahead then !

Neil


From Frank.li at nxp.com  Mon Mar  3 08:52:47 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 11:52:47 -0500
Subject: [PATCH v15 04/15] irqchip/gic-v3-its: Add support for device
 tree msi-map and msi-mask
In-Reply-To: <86o6ylouc5.wl-maz@kernel.org>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
 <20250211-ep-msi-v15-4-bcacc1f2b1a9@nxp.com>
 <86o6ylouc5.wl-maz@kernel.org>
Message-ID: <Z8XeXxg5WhDpcAoo@lizhi-Precision-Tower-5810>

On Sat, Mar 01, 2025 at 11:37:14AM +0000, Marc Zyngier wrote:
> On Tue, 11 Feb 2025 19:21:57 +0000,
> Frank Li <Frank.Li at nxp.com> wrote:
> >
> > Some platform devices create child devices dynamically and require the
> > parent device's msi-map to map device IDs to actual sideband information.
> >
> > A typical use case is using ITS as a PCIe Endpoint Controller(EPC)'s
> > doorbell function, where PCI hosts send TLP memory writes to the EP
> > controller. The EP controller converts these writes to AXI transactions
> > and appends platform-specific sideband information.  See below figure.
> >
> >                ??????????????????????????????????
> >                ?                                ?
> >                ?     PCI Endpoint Controller    ?
> >                ?                                ?
> >                ?  ???????   ???????     ??????? ?
> >     PCI Bus    ?  ?     ?   ?     ?     ?     ? ?
> >     ?????????? ?  ?Func1?   ?Func2? ... ?Func ? ?
> >     TLP Memory ?  ?     ?   ?     ?     ?<n>  ? ?
> >     Write Push ?  ?     ?   ?     ?     ?     ? ?
> >     DoorBell   ?  ???????   ???????     ??????? ?
> >                ?    ? ?        ?           ?    ?
> >                ??????????????????????????????????
> >         sideband    ? ? Address?           ?
> >         information ? ? /Data  ?           ?
> >                    ??????????????????????????
> >                    ?    MSI Controller      ?
> >                    ??????????????????????????
> >
>
> Please stop using these figures in commit messages. I don't think they
> help, and they are not in consistent with the way the commit messages
> are managed.

Okay

>
> > EPC's DTS will provide such information by msi-map and msi-mask. A
> > simplified dts as
> >
> > pcie-ep at 10000000 {
> > 	...
> > 	msi-map = <0 &its 0xc 8>;
> >                           ^^^ 0xc is implement defined sideband information,
> > 			      which append to AXI write transaction.
> > 	           ^ 0 is function index.
>
> What does this sideband field represent?

ARM ITS use term "streamid" for this sideband field, which indicate which
MSI consumer write to address/data pair on bus. Such as PCI1 or PCI2.

> How is the ITS driver
> supposed to use that data?

ITS use a as devid, or info->scratchpad[0].ul = dev_id;
msi-map actually given a start dev_id (it is 0xc in example) for fuction0.
function1 will use dev_id + 1 ...

> Is it the full devid as presented to the
> ITS?

Yes,

> Something combined with the "function index"? Is the "function
> index" a full RID, as defined in the documentation?

Not a full RID. RID is related with host PCIe's topology. The EP function's
RID may 1:00:01 at PC1, 3:00:01 at the another PC.

So Endpoint driver can't use RID directly. It should related function and
virtual function number only.

PCI define 8 physicla funciton, and 64000 virutal function. Define device
id as vfunc[31:3], pfunc[2:0] as msi-map's input. DTS provide information
how map it to real streamid.

>
> Also, msi-map is so far reserved to a PCIe RC, not this sort of wonky
> contraption. This needs to be documented.

Okay, I can update document.

Frank
>
> >
> > 	msi-mask = <0x7>
> > }
> >
> > Check msi-map if msi-parent missed to keep compatility with existed system.
> >
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> > change from v14 to v15
> > - none
> >
> > change from v13 to v14
> > new patch
> > ---
> >  drivers/irqchip/irq-gic-v3-its-msi-parent.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> > index e150365fbe892..6c7389bb84a4a 100644
> > --- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> > +++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
> > @@ -118,6 +118,14 @@ static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
> >  		index++;
> >  	} while (!ret);
> >
> > +	if (ret) {
> > +		struct device_node *np = NULL;
> > +
> > +		ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
> > +		if (np)
> > +			of_node_put(np);
> > +	}
> > +
> >  	return ret;
> >  }
> >
> >
>
> Thanks,
>
> 	M.
>
> --
> Without deviation from the norm, progress is not possible.


From jgg at ziepe.ca  Mon Mar  3 08:52:55 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Mon, 3 Mar 2025 12:52:55 -0400
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250303103102.GC13345@e133081.arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com>
Message-ID: <20250303165255.GS5011@ziepe.ca>

On Mon, Mar 03, 2025 at 10:31:02AM +0000, Miko?aj Lenczewski wrote:

> > > On such a system it seems like your series would break previously
> > > working SVA support because this patch will end up disabling it?
> 
> Perhaps my understanding is flawed here, but I was under the impression
> that with SVA both the core and smmu MUST support BBML2 to use it safely
> for core translations? 

Yes

But today's kernel does not use BBML2 in the CPU or the SMMU so it is
compatible with everything.

So it is an upgrade issue, going from today's kernel without any BBML2
support to tomorrow's kernel that does then you loose SVA on
previously working HW.

> Hopefully, as you say, the MIDR list restricts the breakage to a limited
> (ideally, zero-size) set of implementations which advertise BBML2
> without conflict aborts, but which do not support BBML2 on the smmu.
> 
> However, if my understanding of the BBML2 feature and how it interacts
> with SVA is flawed, this will obviously be something for me to fix.

Lets hope, I was not able to discover any NVIDIA platforms that have
an issue with this series as is.

But every addition to the MIDR list will require some consideration :\

> On independently enabling BBML2 on the smmu but not the CPU, this should
> be possible.

What about the reverse? Could we disable BBML2 on the CPU side on a
per-mm basis? Ie when an old SMMU attaches with disable the
incompatible feature? Not something for this series, but if we get
into trouble down the road

Jason


From peterz at infradead.org  Mon Mar  3 08:54:54 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 3 Mar 2025 17:54:54 +0100
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250303132837.498938-2-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn>
Message-ID: <20250303165454.GB11590@noisy.programming.kicks-ass.net>

On Mon, Mar 03, 2025 at 09:28:34PM +0800, Menglong Dong wrote:
> For now, the layout of cfi and fineibt is hard coded, and the padding is
> fixed on 16 bytes.
> 
> Factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET. CFI_INSN_OFFSET is
> the offset of cfi, which is the same as FUNCTION_ALIGNMENT when
> CALL_PADDING is enabled. And FINEIBT_INSN_OFFSET is the offset where we
> put the fineibt preamble on, which is 16 for now.
> 
> When the FUNCTION_ALIGNMENT is bigger than 16, we place the fineibt
> preamble on the last 16 bytes of the padding for better performance, which
> means the fineibt preamble don't use the space that cfi uses.
> 
> The FINEIBT_INSN_OFFSET is not used in fineibt_caller_start and
> fineibt_paranoid_start, as it is always "0x10". Note that we need to
> update the offset in fineibt_caller_start and fineibt_paranoid_start if
> FINEIBT_INSN_OFFSET changes.
> 
> Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>

I'm confused as to what exactly you mean.

Preamble will have __cfi symbol and some number of NOPs right before
actual symbol like:

__cfi_foo:
  mov $0x12345678, %reg
  nop
  nop
  nop
  ...
foo:

FineIBT must be at foo-16, has nothing to do with performance. This 16
can also be spelled: fineibt_preamble_size.

The total size of the preamble is FUNCTION_PADDING_BYTES + CFI_CLANG*5.

If you increase FUNCTION_PADDING_BYTES by another 5, which is what you
want I think, then we'll have total preamble of 21 bytes; 5 bytes kCFI,
16 bytes nop.

Then kCFI expects hash to be at -20, while FineIBT must be at -16.

This then means there is no unambiguous hole for you to stick your
meta-data thing (whatever that is).

There are two options: make meta data location depend on cfi_mode, or
have __apply_fineibt() rewrite kCFI to also be at -16, so that you can
have -21 for your 5 bytes.

I think I prefer latter.

In any case, I don't think we need *_INSN_OFFSET. At most we need
PREAMBLE_SIZE.

Hmm?


From hugues.kambampiana at arm.com  Mon Mar  3 09:00:12 2025
From: hugues.kambampiana at arm.com (Hugues KAMBA MPIANA)
Date: Mon,  3 Mar 2025 17:00:12 +0000
Subject: [PATCH v2] arm64: dts: corstone1000: Add definitions for secondary CPU cores
In-Reply-To: <Z8XSIx75B4mtcV48@bogus>
References: <Z8XSIx75B4mtcV48@bogus>
Message-ID: <20250303170012.469576-1-hugues.kambampiana@arm.com>

Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
enable support for secondary CPU cores.

This update facilitates symmetric multiprocessing (SMP) support on
the Corstone1000 Fixed Virtual Platform (FVP), allowing the
secondary cores to be properly initialised and utilised.

Only FVP platform will have SMP support and hence the secondary cpu definitions
are not added to corstone1000.dtsi.

Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana at arm.com>
---
 arch/arm64/boot/dts/arm/corstone1000-fvp.dts | 24 ++++++++++++++++++++
 arch/arm64/boot/dts/arm/corstone1000.dtsi    |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
index abd013562995..df9700302b8d 100644
--- a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
+++ b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
@@ -49,3 +49,27 @@ sdmmc1: mmc at 50000000 {
 		clock-names = "smclk", "apb_pclk";
 	};
 };
+
+&cpus {
+	cpu1: cpu at 1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x1>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+	cpu2: cpu at 2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x2>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+	cpu3: cpu at 3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a35";
+		reg = <0x3>;
+		enable-method = "psci";
+		next-level-cache = <&L2_0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/arm/corstone1000.dtsi b/arch/arm64/boot/dts/arm/corstone1000.dtsi
index bb9b96fb5314..b4364c61901c 100644
--- a/arch/arm64/boot/dts/arm/corstone1000.dtsi
+++ b/arch/arm64/boot/dts/arm/corstone1000.dtsi
@@ -21,7 +21,7 @@ chosen {
 		stdout-path = "serial0:115200n8";
 	};
 
-	cpus {
+	cpus: cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
 


From Frank.li at nxp.com  Mon Mar  3 09:01:56 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 12:01:56 -0500
Subject: [PATCH v15 02/15] irqdomain: Add IRQ_DOMAIN_FLAG_MSI_IMMUTABLE
 and irq_domain_is_msi_immutable()
In-Reply-To: <86plj1ovkk.wl-maz@kernel.org>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
 <20250211-ep-msi-v15-2-bcacc1f2b1a9@nxp.com>
 <86plj1ovkk.wl-maz@kernel.org>
Message-ID: <Z8XghE/VUrggdN7V@lizhi-Precision-Tower-5810>

On Sat, Mar 01, 2025 at 11:10:35AM +0000, Marc Zyngier wrote:
> On Tue, 11 Feb 2025 19:21:55 +0000,
> Frank Li <Frank.Li at nxp.com> wrote:
> >
> > Add the flag IRQ_DOMAIN_FLAG_MSI_IMMUTABLE and the API function
> > irq_domain_is_msi_immutable() to check if the MSI controller retains an
> > immutable address/data pair during irq_set_affinity().
> >
> > Ensure compatibility with MSI users like PCIe Endpoint Doorbell, which
> > require the address/data pair to remain unchanged after setup. Use this
> > function to verify if the MSI controller is immutable.
>
> Why is that a requirement? Why should a driver even care?

At v9, there were detail discussion about this
https://lore.kernel.org/all/87v7w0s9a8.ffs at tglx/

let me summary:

Host driver workflow like:

1. read address/data from shared memory (PC bar<n>)
2. write data to address to trigger doorbell.

1 and 2 is not atomic. So EP side may call set_affinity function during 1
and 2, address/data may be changed in some MSI provider, so 2 write to
previous address/data pair, which may not existed or map to other place and
cause write to unexpected place.

Frank

>
> 	M.
>
> --
> Without deviation from the norm, progress is not possible.


From kory.maincent at bootlin.com  Mon Mar  3 09:03:23 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 3 Mar 2025 18:03:23 +0100
Subject: [PATCH net-next v3 1/2] net: ti: icss-iep: Add pwidth
 configuration for perout signal
In-Reply-To: <20250303135124.632845-2-m-malladi@ti.com>
References: <20250303135124.632845-1-m-malladi@ti.com>
	<20250303135124.632845-2-m-malladi@ti.com>
Message-ID: <20250303180323.1d9b51de@kmaincent-XPS-13-7390>

On Mon, 3 Mar 2025 19:21:23 +0530
Meghana Malladi <m-malladi at ti.com> wrote:

> icss_iep_perout_enable_hw() is a common function for generating
> both pps and perout signals. When enabling pps, the application needs
> to only pass enable/disable argument, whereas for perout it supports
> different flags to configure the signal.
> 
> But icss_iep_perout_enable_hw() function is missing to hook the
> configuration params passed by the app, causing perout to behave
> same a pps (except being able to configure the period). As duty cycle
> is also one feature which can configured for perout, incorporate this
> in the function to get the expected signal.

...

> IEP_SYNC_CTRL_SYNC_EN); @@ -474,7 +484,38 @@ static int
> icss_iep_perout_enable_hw(struct icss_iep *iep, static int
> icss_iep_perout_enable(struct icss_iep *iep, struct ptp_perout_request *req,
> int on) {
> -	return -EOPNOTSUPP;
> +	int ret = 0;
> +
> +	mutex_lock(&iep->ptp_clk_mutex);
> +
> +	/* Reject requests with unsupported flags */
> +	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) {
> +		ret = -EOPNOTSUPP;
> +		goto exit;
> +	}

The flags check does not need to be in the mutex lock.
With this change:
Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>

> +	if (iep->pps_enabled) {
> +		ret = -EBUSY;
> +		goto exit;
> +	}
> +
> +	if (iep->perout_enabled == !!on)
> +		goto exit;
> +
> +	/* Set default "on" time (1ms) for the signal if not passed by the
> app */
> +	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
> +		req->on.sec = 0;
> +		req->on.nsec = NSEC_PER_MSEC;
> +	}
> +
> +	ret = icss_iep_perout_enable_hw(iep, req, on);
> +	if (!ret)
> +		iep->perout_enabled = !!on;
> +
> +exit:
> +	mutex_unlock(&iep->ptp_clk_mutex);
> +
> +	return ret;
>  }
>  
>  static void icss_iep_cap_cmp_work(struct work_struct *work)
> @@ -553,6 +594,8 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int
> on) rq.perout.period.nsec = 0;
>  		rq.perout.start.sec = ts.tv_sec + 2;
>  		rq.perout.start.nsec = 0;
> +		rq.perout.on.sec = 0;
> +		rq.perout.on.nsec = NSEC_PER_MSEC;
>  		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
>  	} else {
>  		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);



-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From paul at os.amperecomputing.com  Mon Mar  3 09:07:22 2025
From: paul at os.amperecomputing.com (Paul Benoit)
Date: Mon, 3 Mar 2025 12:07:22 -0500
Subject: [PATCH v4] firmware: smccc: Support optional Arm SMC SOC_ID name
In-Reply-To: <Z8XAiMSoaOmR5JxY@bogus>
References: <20241114030452.10149-1-paul@os.amperecomputing.com>
 <20250219005932.3466-1-paul@os.amperecomputing.com>
 <Z8W6HXZy46K7ebWe@J2N7QTR9R3.cambridge.arm.com> <Z8XAiMSoaOmR5JxY@bogus>
Message-ID: <7869d30c-283f-4015-98ae-1bfc7d1efbc0@os.amperecomputing.com>

Thank you Sudeep and Mark.

On 3/3/2025 9:45 AM, Sudeep Holla wrote:
> On Mon, Mar 03, 2025 at 02:18:05PM +0000, Mark Rutland wrote:
>> Hi Paul,
>>
>> This looks generally good with a couple of minor nits.
>>
>> On Tue, Feb 18, 2025 at 04:59:32PM -0800, Paul Benoit wrote:
>>> Issue Number 1.6 of the Arm SMC Calling Convention introduces an optional
>>> SOC_ID name string.  If implemented, point the 'machine' field of the SoC
>>> Device Attributes at this string so that it will appear under
>>> /sys/bus/soc/devices/soc0/machine.
>>>
>>> On Arm SMC compliant SoCs, this will allow things like 'lscpu' to
>>> eventually get a SoC provider model name from there rather than each
>>> tool/utility needing to get a possibly inconsistent, obsolete, or incorrect
>>> model/machine name from its own hardcoded model/machine name table.
>>>
>>> Signed-off-by: Paul Benoit <paul at os.amperecomputing.com>
>>> Cc: Mark Rutland <mark.rutland at arm.com>
>>> Cc: Lorenzo Pieralisi <lpieralisi at kernel.org>
>>> Cc: Sudeep Holla <sudeep.holla at arm.com>
>>> Cc: linux-arm-kernel at lists.infradead.org
>>> ---
> 
> [...]
> 
>>> +static char __init *smccc_soc_name_init(void)
>>> +{
>>> +	struct arm_smccc_1_2_regs args;
>>> +	struct arm_smccc_1_2_regs res;
>>> +	size_t len;
>>> +
>>> +	/*
>>> +	 * Issue Number 1.6 of the Arm SMC Calling Convention
>>> +	 * specification introduces an optional "name" string
>>> +	 * to the ARM_SMCCC_ARCH_SOC_ID function.  Fetch it if
>>> +	 * available.
>>> +	 */
>>> +	args.a0 = ARM_SMCCC_ARCH_SOC_ID;
>>> +	args.a1 = 2;    /* SOC_ID name */
>>> +	arm_smccc_1_2_invoke(&args, &res);
>>> +	if ((u32)res.a0 == 0) {
>>> +		const unsigned int regsize = sizeof(res.a1);
>>> +
>>> +		/*
>>> +		 * Copy res.a1..res.a17 to the smccc_soc_id_name string
>>> +		 * 8 bytes at a time.  As per Issue 1.6 of the Arm SMC
>>> +		 * Calling Convention, the string will be NUL terminated
>>> +		 * and padded, from the end of the string to the end of the
>>> +		 * 136 byte buffer, with NULs.
>>> +		 */
>>> +		str_fragment_from_reg(smccc_soc_id_name + 0*regsize, res.a1);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 1*regsize, res.a2);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 2*regsize, res.a3);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 3*regsize, res.a4);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 4*regsize, res.a5);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 5*regsize, res.a6);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 6*regsize, res.a7);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 7*regsize, res.a8);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 8*regsize, res.a9);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 9*regsize, res.a10);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 10*regsize, res.a11);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 11*regsize, res.a12);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 12*regsize, res.a13);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 13*regsize, res.a14);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 14*regsize, res.a15);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 15*regsize, res.a16);
>>> +		str_fragment_from_reg(smccc_soc_id_name + 16*regsize, res.a17);
>>
>> Please get rid of 'regsize' and use '8' directly. This only exists for
>> arm64, where the registeres are 8 bytes, and the comment immediately
>> above refers to "8 bytes" specifically anyway, so 'regsize' only serves
>> to make this harder to read.
>>
>> It'd be a bit clearer as:
>>
>> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 0,  res.a1);
>> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 1,  res.a2);
>> 	...
>> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 15, res.a16);
>> 	str_fragment_from_reg(smccc_soc_id_name + 8 * 16, res.a17);
>>
>> Sudeep, are you happy to fix that up when applying?
>>
>>> +
>>> +		len = strnlen(smccc_soc_id_name, sizeof(smccc_soc_id_name));
>>> +		if (len) {
>>> +			if (len == sizeof(smccc_soc_id_name))
>>> +				pr_warn(FW_BUG "Ignoring improperly formatted Name\n");
>>
>> It's odd that 'Name' is capitalized here. Not a big deal, but it doesn't
>> look quite right.
>>
> 
> I can fix both of these and apply. No need to repost.
> 



From krzk at kernel.org  Mon Mar  3 09:13:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 3 Mar 2025 18:13:20 +0100
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
Message-ID: <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org>

On 08/02/2025 23:51, Vikram Sharma wrote:
> The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
> camera sensor. Enable IMX577 on the vision mezzanine.
> 
> An example media-ctl pipeline for the imx577 is:
> 
> media-ctl --reset
> media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 field:none]'

AFAIU, camss does not support SRGGB10, but only SRGGB10P.

Based on tests reported on IRC I think this might not have been tested
correctly.

Best regards,
Krzysztof


From ivo.ivanov.ivanov1 at gmail.com  Mon Mar  3 09:18:09 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Mon, 3 Mar 2025 19:18:09 +0200
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
 <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
Message-ID: <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>

On 3/3/25 09:24, Krzysztof Kozlowski wrote:
> On 02/03/2025 10:16, Ivaylo Ivanov wrote:
>> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>>
>>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>> ---
>>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>>  1 file changed, 76 insertions(+)
>>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>> You have undocumented dependencies which prevent merging this file.
>>>>> First, dependencies have to be clearly expressed.
>>>> They are, in the cover letter.
>>> Where? I read it twice. Dependencies is the most important thing and
>>> should scream at beginning of the cover letter, so if you bury them
>>> somewhere deep it also would not matter - just like they were missing.
>>>
>>>>> Second, you should
>>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>>> be merged for current release (just use clocks with long names, without IDs).
>>>> Sure
>>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>> new file mode 100644
>>>>>> index 000000000..7d879ec8b
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>> @@ -0,0 +1,76 @@
>>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>>> +%YAML 1.2
>>>>>> +---
>>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>> +
>>>>>> +title: Exynos2200 USB controller PHY
>>>>>> +
>>>>>> +maintainers:
>>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>> +
>>>>>> +description:
>>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>>> It's not (I think). There's a few reasons I've decided to make this separate
>>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>>
>>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>>> at diagram - they call it phy controller.
>> Ughm. What? So in most exynos cases, there's a combination of multiple phys?
>
>>>> for them, and all that is needed from it is to disable HWACG, assert/
>>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>>> Does it mean there is no USB DRD phy controller as before?
>>>
>>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
>> So...
>>
>> DWC3 -> USBDRD (USBCON) -> PHYs?
> No, drop last phy. You just wrote the same as me - two phys, because
> usbdrd is the phy. In all existing designs there is no such controllable
> object from the point of view of operating system.

What? Per my understanding, the phy property should refer to whatever is
is connected to dwc3 UTMI. In this case it's the so-called USBDRD phy (called
usbcon in downstream). Considering that the eUSB2 IP definitely also has UTMI
that has to be connected to something, doesn't that mean we have clearly
separated hardware blocks? Now, I guess one could argue that this USBCON
hardware block could be classified as a syscon. But I don't see the problem
with the current binding description, nor the modelling, as it represents
how the hardware is (unless I've gotten it completely wrong).

Best regards,
Ivaylo

>
>> ...with usbdrd controller connecting and controlling the USB2 and USB3
>> phys, as well as dual role mode?
> Yes.
>
>> Well, where is the DRD part in the exynos5
>> driver?
> DRD? I believe it is part of DWC3, the same as in every other standard
> implementation of Synopsys DWC3.
>
>> I guess it does perfectly fit the job of a usbdrd controller then (if it
>> even deals with DRD). But then again,? this brings up two questions:
>> 1. Should this driver even be named exynos2200-usbcon and not, for
>> example, exynos2200-usbdrd?
> Are you sure we talk about the same thing? USBDRD is IP block in the
> Exynos and a device driver. Call your device as appropriate it is -
> based on datasheet or downstream sources.
>
>> 2. Are the exynos5-usbdrd phys really only USBDRD, or do they implement
>> USB speed functionality? What is the UTMI/PIPE3 setup for then?
> Dunno, I don't get what you mean by "exynos5-usbdrd phys really only
> USBDRD". USBDRD is just the name of the device.
>
> Best regards,
> Krzysztof



From nifan.cxl at gmail.com  Mon Mar  3 09:19:38 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 09:19:38 -0800
Subject: [PATCH v7 1/5] perf/dwc_pcie: Move common DWC struct definitions
 to 'pcie-dwc.h'
In-Reply-To: <20250221131548.59616-2-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132024epcas5p13d6e617805e4ef0c081227b08119871b@epcas5p1.samsung.com>
 <20250221131548.59616-2-shradha.t@samsung.com>
Message-ID: <Z8XkqnQir1CfilvM@debian>

On Fri, Feb 21, 2025 at 06:45:44PM +0530, Shradha Todi wrote:
> From: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> 
> Since these are common to all Desginware PCIe IPs, move them to a new
> header 'pcie-dwc.h', so that other drivers like debugfs, perf and sysfs
> could make use of them.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> Signed-off-by: Shradha Todi <shradha.t at samsung.com>

Reviewed-by: Fan Ni <fan.ni at samsung.com>

> ---
>  MAINTAINERS                 |  1 +
>  drivers/perf/dwc_pcie_pmu.c | 25 +++----------------------
>  include/linux/pcie-dwc.h    | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 38 insertions(+), 22 deletions(-)
>  create mode 100644 include/linux/pcie-dwc.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3864d473f52f..6474a2d83de4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18167,6 +18167,7 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
>  F:	Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
>  F:	drivers/pci/controller/dwc/*designware*
> +F:	include/linux/pcie-dwc.h
>  
>  PCI DRIVER FOR TI DRA7XX/J721E
>  M:	Vignesh Raghavendra <vigneshr at ti.com>
> diff --git a/drivers/perf/dwc_pcie_pmu.c b/drivers/perf/dwc_pcie_pmu.c
> index cccecae9823f..da30f2c2d674 100644
> --- a/drivers/perf/dwc_pcie_pmu.c
> +++ b/drivers/perf/dwc_pcie_pmu.c
> @@ -13,6 +13,7 @@
>  #include <linux/errno.h>
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> +#include <linux/pcie-dwc.h>
>  #include <linux/perf_event.h>
>  #include <linux/pci.h>
>  #include <linux/platform_device.h>
> @@ -99,26 +100,6 @@ struct dwc_pcie_dev_info {
>  	struct list_head dev_node;
>  };
>  
> -struct dwc_pcie_pmu_vsec_id {
> -	u16 vendor_id;
> -	u16 vsec_id;
> -	u8 vsec_rev;
> -};
> -
> -/*
> - * VSEC IDs are allocated by the vendor, so a given ID may mean different
> - * things to different vendors.  See PCIe r6.0, sec 7.9.5.2.
> - */
> -static const struct dwc_pcie_pmu_vsec_id dwc_pcie_pmu_vsec_ids[] = {
> -	{ .vendor_id = PCI_VENDOR_ID_ALIBABA,
> -	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> -	{ .vendor_id = PCI_VENDOR_ID_AMPERE,
> -	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> -	{ .vendor_id = PCI_VENDOR_ID_QCOM,
> -	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> -	{} /* terminator */
> -};
> -
>  static ssize_t cpumask_show(struct device *dev,
>  					 struct device_attribute *attr,
>  					 char *buf)
> @@ -529,14 +510,14 @@ static void dwc_pcie_unregister_pmu(void *data)
>  
>  static u16 dwc_pcie_des_cap(struct pci_dev *pdev)
>  {
> -	const struct dwc_pcie_pmu_vsec_id *vid;
> +	const struct dwc_pcie_vsec_id *vid;
>  	u16 vsec;
>  	u32 val;
>  
>  	if (!pci_is_pcie(pdev) || !(pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT))
>  		return 0;
>  
> -	for (vid = dwc_pcie_pmu_vsec_ids; vid->vendor_id; vid++) {
> +	for (vid = dwc_pcie_rasdes_vsec_ids; vid->vendor_id; vid++) {
>  		vsec = pci_find_vsec_capability(pdev, vid->vendor_id,
>  						vid->vsec_id);
>  		if (vsec) {
> diff --git a/include/linux/pcie-dwc.h b/include/linux/pcie-dwc.h
> new file mode 100644
> index 000000000000..40f3545731c8
> --- /dev/null
> +++ b/include/linux/pcie-dwc.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2021-2023 Alibaba Inc.
> + *
> + * Copyright 2025 Linaro Ltd.
> + * Author: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> + */
> +
> +#ifndef LINUX_PCIE_DWC_H
> +#define LINUX_PCIE_DWC_H
> +
> +#include <linux/pci_ids.h>
> +
> +struct dwc_pcie_vsec_id {
> +	u16 vendor_id;
> +	u16 vsec_id;
> +	u8 vsec_rev;
> +};
> +
> +/*
> + * VSEC IDs are allocated by the vendor, so a given ID may mean different
> + * things to different vendors.  See PCIe r6.0, sec 7.9.5.2.
> + */
> +static const struct dwc_pcie_vsec_id dwc_pcie_rasdes_vsec_ids[] = {
> +	{ .vendor_id = PCI_VENDOR_ID_ALIBABA,
> +	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> +	{ .vendor_id = PCI_VENDOR_ID_AMPERE,
> +	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> +	{ .vendor_id = PCI_VENDOR_ID_QCOM,
> +	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> +	{} /* terminator */
> +};
> +
> +#endif /* LINUX_PCIE_DWC_H */
> -- 
> 2.17.1
> 


From nifan.cxl at gmail.com  Mon Mar  3 09:22:50 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 09:22:50 -0800
Subject: [PATCH v7 2/5] PCI: dwc: Add helper to find the Vendor Specific
 Extended Capability (VSEC)
In-Reply-To: <20250221131548.59616-3-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132029epcas5p1e56dd355e7ac912ceb25325595de0d24@epcas5p1.samsung.com>
 <20250221131548.59616-3-shradha.t@samsung.com>
Message-ID: <Z8XlapjLRfz44hF7@debian>

On Fri, Feb 21, 2025 at 06:45:45PM +0530, Shradha Todi wrote:
> dw_pcie_find_vsec_capability() is used by upcoming DWC APIs to find the
How are about "Add dw_pcie_find_ext_capability(), which will be used by
..."

Other than that,


Reviewed-by: Fan Ni <fan.ni at samsung.com>

> VSEC capabilities like PTM, RAS etc.
> 
> Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> Signed-off-by: Shradha Todi <shradha.t at samsung.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware.c | 40 ++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 145e7f579072..a7c0671c6715 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -16,6 +16,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/ioport.h>
>  #include <linux/of.h>
> +#include <linux/pcie-dwc.h>
>  #include <linux/platform_device.h>
>  #include <linux/sizes.h>
>  #include <linux/types.h>
> @@ -283,6 +284,45 @@ u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
>  
> +static u16 __dw_pcie_find_vsec_capability(struct dw_pcie *pci, u16 vendor_id,
> +					  u16 vsec_id)
> +{
> +	u16 vsec = 0;
> +	u32 header;
> +
> +	if (vendor_id != dw_pcie_readw_dbi(pci, PCI_VENDOR_ID))
> +		return 0;
> +
> +	while ((vsec = dw_pcie_find_next_ext_capability(pci, vsec,
> +						       PCI_EXT_CAP_ID_VNDR))) {
> +		header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER);
> +		if (PCI_VNDR_HEADER_ID(header) == vsec_id)
> +			return vsec;
> +	}
> +
> +	return 0;
> +}
> +
> +static u16 dw_pcie_find_vsec_capability(struct dw_pcie *pci,
> +					const struct dwc_pcie_vsec_id *vsec_ids)
> +{
> +	const struct dwc_pcie_vsec_id *vid;
> +	u16 vsec;
> +	u32 header;
> +
> +	for (vid = vsec_ids; vid->vendor_id; vid++) {
> +		vsec = __dw_pcie_find_vsec_capability(pci, vid->vendor_id,
> +						      vid->vsec_id);
> +		if (vsec) {
> +			header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER);
> +			if (PCI_VNDR_HEADER_REV(header) == vid->vsec_rev)
> +				return vsec;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  int dw_pcie_read(void __iomem *addr, int size, u32 *val)
>  {
>  	if (!IS_ALIGNED((uintptr_t)addr, size)) {
> -- 
> 2.17.1
> 


From abel.vesa at linaro.org  Mon Mar  3 09:30:58 2025
From: abel.vesa at linaro.org (Abel Vesa)
Date: Mon, 03 Mar 2025 19:30:58 +0200
Subject: [PATCH v3 0/4] clk: imx8mp: fix parents of AUDIOMIX
 DSP/OCRAM_A
In-Reply-To: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
References: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
Message-ID: <174102305899.2928950.8837177294161174759.b4-ty@linaro.org>


On Wed, 26 Feb 2025 11:45:09 -0500, Laurentiu Mihalcea wrote:
> Correct the parent of the AUDIOMIX DSP and OCRAM_A clock gates by setting
> it to AUDIO_AXI_CLK_ROOT, instead of AUDIO_AHB_CLK_ROOT. Additionally, set
> the frequency of AUDIO_AXI_CLK_ROOT to 800MHz instead of the current
> 400MHz.
> 

Applied, thanks!

[1/4] dt-bindings: clock: imx8mp: add axi clock
      commit: 2471a101938b0d1835b1983df08daeb98eef1205
[2/4] clk: clk-imx8mp-audiomix: fix dsp/ocram_a clock parents
      commit: 91be7d27099dedf813b80702e4ca117d1fb38ce6
[3/4] arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to AUDIOMIX block
      (no commit info)
[4/4] arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT freq. to 800MHz
      (no commit info)

Best regards,
-- 
Abel Vesa <abel.vesa at linaro.org>



From abel.vesa at linaro.org  Mon Mar  3 09:31:02 2025
From: abel.vesa at linaro.org (Abel Vesa)
Date: Mon, 03 Mar 2025 19:31:02 +0200
Subject: [PATCH v4 0/6] arm64: dts: freescale: imx8mp-skov: switch to
 nominal drive mode
In-Reply-To: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
References: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
Message-ID: <174102306220.2928950.8878245519332562153.b4-ty@linaro.org>


On Tue, 18 Feb 2025 19:26:40 +0100, Ahmad Fatoum wrote:
> Unlike the i.MX8MM and i.MX8MN SoCs added earlier, the imx8mp.dtsi
> configures some clocks at frequencies that are only validated for
> overdrive mode, i.e., when VDD_SOC is 950 mV.
> 
> For the Skov i.MX8MP board, we want to run the SoC at the lower voltage of
> 850 mV though to reduce heat generation and power usage. For this to work,
> clock rates need to adhere to the limits of the nominal drive mode.
> 
> [...]

Applied, thanks!

[1/6] dt-bindings: clock: imx8m: document nominal/overdrive properties
      commit: d5992f1af1550a9e11e42cfa2ca1ad2a1b7fd7f3
[2/6] arm64: dts: imx8mp: Add optional nominal drive mode DTSI
      (no commit info)
[3/6] arm64: dts: imx8mp: add fsl,nominal-mode property into nominal.dtsi
      (no commit info)
[4/6] arm64: dts: freescale: imx8mp-skov: configure LDB clock automatically
      (no commit info)
[5/6] arm64: dts: freescale: imx8mp-skov: operate SoC in nominal mode
      (no commit info)
[6/6] clk: imx8mp: inform CCF of maximum frequency of clocks
      commit: 06a61b5cb6a8638fa8823cd09b17233b29696fa2

Best regards,
-- 
Abel Vesa <abel.vesa at linaro.org>



From abel.vesa at linaro.org  Mon Mar  3 09:32:40 2025
From: abel.vesa at linaro.org (Abel Vesa)
Date: Mon, 3 Mar 2025 19:32:40 +0200
Subject: [PATCH v4 0/6] arm64: dts: freescale: imx8mp-skov: switch to
 nominal drive mode
In-Reply-To: <174102306220.2928950.8878245519332562153.b4-ty@linaro.org>
References: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
 <174102306220.2928950.8878245519332562153.b4-ty@linaro.org>
Message-ID: <Z8XnuIIfDFykrKH8@linaro.org>

On 25-03-03 19:31:02, Abel Vesa wrote:
> 
> On Tue, 18 Feb 2025 19:26:40 +0100, Ahmad Fatoum wrote:
> > Unlike the i.MX8MM and i.MX8MN SoCs added earlier, the imx8mp.dtsi
> > configures some clocks at frequencies that are only validated for
> > overdrive mode, i.e., when VDD_SOC is 950 mV.
> > 
> > For the Skov i.MX8MP board, we want to run the SoC at the lower voltage of
> > 850 mV though to reduce heat generation and power usage. For this to work,
> > clock rates need to adhere to the limits of the nominal drive mode.
> > 
> > [...]
> 
> Applied, thanks!
> 
> [1/6] dt-bindings: clock: imx8m: document nominal/overdrive properties
>       commit: d5992f1af1550a9e11e42cfa2ca1ad2a1b7fd7f3
> [2/6] arm64: dts: imx8mp: Add optional nominal drive mode DTSI
>       (no commit info)
> [3/6] arm64: dts: imx8mp: add fsl,nominal-mode property into nominal.dtsi
>       (no commit info)
> [4/6] arm64: dts: freescale: imx8mp-skov: configure LDB clock automatically
>       (no commit info)
> [5/6] arm64: dts: freescale: imx8mp-skov: operate SoC in nominal mode
>       (no commit info)
> [6/6] clk: imx8mp: inform CCF of maximum frequency of clocks
>       commit: 06a61b5cb6a8638fa8823cd09b17233b29696fa2

Applied only patches 1 and 6.

My b4 setup messed up. Sorry.

> 
> Best regards,
> -- 
> Abel Vesa <abel.vesa at linaro.org>
> 


From abel.vesa at linaro.org  Mon Mar  3 09:33:33 2025
From: abel.vesa at linaro.org (Abel Vesa)
Date: Mon, 3 Mar 2025 19:33:33 +0200
Subject: [PATCH v3 0/4] clk: imx8mp: fix parents of AUDIOMIX DSP/OCRAM_A
In-Reply-To: <174102305899.2928950.8837177294161174759.b4-ty@linaro.org>
References: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
 <174102305899.2928950.8837177294161174759.b4-ty@linaro.org>
Message-ID: <Z8Xn7f6vXg0aM4zx@linaro.org>

On 25-03-03 19:30:58, Abel Vesa wrote:
> 
> On Wed, 26 Feb 2025 11:45:09 -0500, Laurentiu Mihalcea wrote:
> > Correct the parent of the AUDIOMIX DSP and OCRAM_A clock gates by setting
> > it to AUDIO_AXI_CLK_ROOT, instead of AUDIO_AHB_CLK_ROOT. Additionally, set
> > the frequency of AUDIO_AXI_CLK_ROOT to 800MHz instead of the current
> > 400MHz.
> > 
> 
> Applied, thanks!
> 
> [1/4] dt-bindings: clock: imx8mp: add axi clock
>       commit: 2471a101938b0d1835b1983df08daeb98eef1205
> [2/4] clk: clk-imx8mp-audiomix: fix dsp/ocram_a clock parents
>       commit: 91be7d27099dedf813b80702e4ca117d1fb38ce6
> [3/4] arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to AUDIOMIX block
>       (no commit info)
> [4/4] arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT freq. to 800MHz
>       (no commit info)

Applied only patches 1 and 2.

My b4 setup messed up. Sorry.

> 
> Best regards,
> -- 
> Abel Vesa <abel.vesa at linaro.org>
> 


From Frank.li at nxp.com  Mon Mar  3 09:40:13 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 12:40:13 -0500
Subject: [PATCH v3 00/12] media: imx8: add camera support
In-Reply-To: <20250210-8qxp_camera-v3-0-324f5105accc@nxp.com>
References: <20250210-8qxp_camera-v3-0-324f5105accc@nxp.com>
Message-ID: <Z8XpfW/TWg5rKpbm@lizhi-Precision-Tower-5810>

On Mon, Feb 10, 2025 at 03:59:19PM -0500, Frank Li wrote:
> Add SCU reset driver for i.MX8QM/i.MX8QXP.
> Update binding doc.
> Update driver for imx8qxp and imx8qm.
> Add dts files for it.

Laurent Pinchart:

	Do you have any comments about this version?

Frank

>
> To: Rob Herring <robh at kernel.org>
> To: Krzysztof Kozlowski <krzk+dt at kernel.org>
> To: Conor Dooley <conor+dt at kernel.org>
> To: Dong Aisheng <aisheng.dong at nxp.com>
> To: Philipp Zabel <p.zabel at pengutronix.de>
> To: Shawn Guo <shawnguo at kernel.org>
> To: Sascha Hauer <s.hauer at pengutronix.de>
> To: Pengutronix Kernel Team <kernel at pengutronix.de>
> To: Fabio Estevam <festevam at gmail.com>
> To: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> To: Mauro Carvalho Chehab <mchehab at kernel.org>
> To: Rui Miguel Silva <rmfrfs at gmail.com>
> To: Martin Kepplinger <martink at posteo.de>
> To: Purism Kernel Team <kernel at puri.sm>
> Cc: devicetree at vger.kernel.org
> Cc: linux-kernel at vger.kernel.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-media at vger.kernel.org
> Cc: Robert Chiras <robert.chiras at nxp.com>
> Cc: "Guoniu.zhou" <guoniu.zhou at nxp.com>
>
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
>
> Changes in v3:
> - Remove phy driver parts.
> - csr is dedicate for mipi csi2, so add it as second register space. csr is
> mixed with PHY and link control with csi2.
> - Link to v2: https://lore.kernel.org/r/20250205-8qxp_camera-v2-0-731a3edf2744 at nxp.com
>
> Changes in v2:
> - move scu reset binding doc to top scu doc.
> - isi use seperate binding doc for imx8qxp and imx8qm.
> - phy and csi2, compatible string 8qm fallback to qxp
> - remove internal review tags
> - Link to v1: https://lore.kernel.org/r/20250131-8qxp_camera-v1-0-319402ab606a at nxp.com
>
> ---
> Frank Li (9):
>       dt-bindings: firmware: imx: add property reset-controller
>       reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM
>       media: dt-bindings: Add binding doc for i.MX8QXP and i.MX8QM ISI
>       media: nxp: imx8-isi: Allow num_sources to be greater than num_sink
>       media: imx8mq-mipi-csi2: Add support for i.MX8QXP
>       arm64: dts: imx8: add capture controller for i.MX8's img subsystem
>       arm64: dts: imx8qm: add 24MHz clock-xtal24m
>       arm64: dts: imx8q: add linux,cma node for imx8qm-mek and imx8qxp-mek
>       arm64: dts: imx8q: add camera ov5640 support for imx8qm-mek and imx8qxp-mek
>
> Guoniu.zhou (1):
>       media: imx8mq-mipi-csi2: Add imx8mq_plat_data for different compatible strings
>
> Robert Chiras (2):
>       media: imx8-isi: Add support for i.MX8QM and i.MX8QXP
>       media: dt-bindings: nxp,imx8mq-mipi-csi2: Add i.MX8QM(QXP) compatible strings
>
>  .../devicetree/bindings/firmware/fsl,scu.yaml      |  12 +
>  .../devicetree/bindings/media/fsl,imx8qm-isi.yaml  | 117 +++++++
>  .../devicetree/bindings/media/fsl,imx8qxp-isi.yaml | 103 ++++++
>  .../bindings/media/nxp,imx8mq-mipi-csi2.yaml       |  38 ++-
>  MAINTAINERS                                        |   1 +
>  arch/arm64/boot/dts/freescale/Makefile             |  12 +
>  arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi     | 376 +++++++++++++++++++++
>  .../boot/dts/freescale/imx8qm-mek-ov5640-csi0.dtso |  90 +++++
>  .../boot/dts/freescale/imx8qm-mek-ov5640-csi1.dtso |  90 +++++
>  arch/arm64/boot/dts/freescale/imx8qm-mek.dts       |  60 ++++
>  arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi   |  45 +++
>  arch/arm64/boot/dts/freescale/imx8qm.dtsi          |  12 +
>  .../boot/dts/freescale/imx8qxp-mek-ov5640-csi.dtso |  89 +++++
>  arch/arm64/boot/dts/freescale/imx8qxp-mek.dts      |  44 +++
>  arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi  |  60 ++++
>  arch/arm64/boot/dts/freescale/imx8qxp.dtsi         |   5 +
>  .../media/platform/nxp/imx8-isi/imx8-isi-core.c    |  47 +++
>  .../media/platform/nxp/imx8-isi/imx8-isi-core.h    |   2 +
>  .../platform/nxp/imx8-isi/imx8-isi-crossbar.c      |   8 +-
>  drivers/media/platform/nxp/imx8mq-mipi-csi2.c      | 179 +++++++++-
>  drivers/reset/Kconfig                              |   7 +
>  drivers/reset/Makefile                             |   1 +
>  drivers/reset/reset-imx-scu.c                      | 101 ++++++
>  23 files changed, 1477 insertions(+), 22 deletions(-)
> ---
> base-commit: ce37eebeae8fa9e6c53f7f1ccd182ad5f27d66cd
> change-id: 20250114-8qxp_camera-c1af5749d304
>
> Best regards,
> ---
> Frank Li <Frank.Li at nxp.com>
>


From kory.maincent at bootlin.com  Mon Mar  3 09:45:43 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 3 Mar 2025 18:45:43 +0100
Subject: [PATCH net v2] net: ethtool: netlink: Allow NULL nlattrs when
 getting a phy_device
In-Reply-To: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
References: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303184543.33f74191@kmaincent-XPS-13-7390>

On Sat,  1 Mar 2025 15:11:13 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> ethnl_req_get_phydev() is used to lookup a phy_device, in the case an
> ethtool netlink command targets a specific phydev within a netdev's
> topology.
> 
> It takes as a parameter a const struct nlattr *header that's used for
> error handling :
> 
>        if (!phydev) {
>                NL_SET_ERR_MSG_ATTR(extack, header,
>                                    "no phy matching phyindex");
>                return ERR_PTR(-ENODEV);
>        }
> 
> In the notify path after a ->set operation however, there's no request
> attributes available.
> 
> The typical callsite for the above function looks like:
> 
> 	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_XXX_HEADER],
> 				      info->extack);
> 
> So, when tb is NULL (such as in the ethnl notify path), we have a nice
> crash.
> 
> It turns out that there's only the PLCA command that is in that case, as
> the other phydev-specific commands don't have a notification.
> 
> This commit fixes the crash by passing the cmd index and the nlattr
> array separately, allowing NULL-checking it directly inside the helper.
> 
> Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some
> commands") Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>

Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>

Thank you!

-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From nifan.cxl at gmail.com  Mon Mar  3 09:48:19 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 09:48:19 -0800
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250221131548.59616-4-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
Message-ID: <Z8XrYxP_pZr6tFU8@debian>

On Fri, Feb 21, 2025 at 06:45:46PM +0530, Shradha Todi wrote:
> Add support to provide silicon debug interface to userspace. This set
> of debug registers are part of the RASDES feature present in DesignWare
> PCIe controllers.
> 
> Signed-off-by: Shradha Todi <shradha.t at samsung.com>

One comment inline.
> ---
>  Documentation/ABI/testing/debugfs-dwc-pcie    |  13 ++
>  drivers/pci/controller/dwc/Kconfig            |  10 +
>  drivers/pci/controller/dwc/Makefile           |   1 +
>  .../controller/dwc/pcie-designware-debugfs.c  | 176 ++++++++++++++++++
>  .../pci/controller/dwc/pcie-designware-ep.c   |   5 +
>  .../pci/controller/dwc/pcie-designware-host.c |   6 +
>  drivers/pci/controller/dwc/pcie-designware.c  |   6 +
>  drivers/pci/controller/dwc/pcie-designware.h  |  21 +++
>  include/linux/pcie-dwc.h                      |   2 +
>  9 files changed, 240 insertions(+)
>  create mode 100644 Documentation/ABI/testing/debugfs-dwc-pcie
>  create mode 100644 drivers/pci/controller/dwc/pcie-designware-debugfs.c
> 

...

> +
> +static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
> +{
> +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> +
> +	mutex_destroy(&rinfo->reg_event_lock);
> +}
> +
> +static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
> +{
> +	struct dentry *rasdes_debug;
> +	struct dwc_pcie_rasdes_info *rasdes_info;
> +	struct device *dev = pci->dev;
> +	int ras_cap;
> +
> +	ras_cap = dw_pcie_find_rasdes_capability(pci);
> +	if (!ras_cap) {
> +		dev_dbg(dev, "no RASDES capability available\n");
> +		return -ENODEV;
> +	}
> +
> +	rasdes_info = devm_kzalloc(dev, sizeof(*rasdes_info), GFP_KERNEL);
> +	if (!rasdes_info)
> +		return -ENOMEM;
> +
> +	/* Create subdirectories for Debug, Error injection, Statistics */
> +	rasdes_debug = debugfs_create_dir("rasdes_debug", dir);
> +
> +	mutex_init(&rasdes_info->reg_event_lock);
> +	rasdes_info->ras_cap_offset = ras_cap;
> +	pci->debugfs->rasdes_info = rasdes_info;
> +
> +	/* Create debugfs files for Debug subdirectory */
> +	dwc_debugfs_create(lane_detect);
> +	dwc_debugfs_create(rx_valid);
> +
> +	return 0;
> +}
> +
> +void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
> +{
> +	dwc_pcie_rasdes_debugfs_deinit(pci);
> +	debugfs_remove_recursive(pci->debugfs->debug_dir);
> +}
> +
> +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> +{
> +	char dirname[DWC_DEBUGFS_BUF_MAX];
> +	struct device *dev = pci->dev;
> +	struct debugfs_info *debugfs;
> +	struct dentry *dir;
> +	int ret;
> +
> +	/* Create main directory for each platform driver */
> +	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> +	dir = debugfs_create_dir(dirname, NULL);
> +	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> +	if (!debugfs)
> +		return -ENOMEM;
> +
> +	debugfs->debug_dir = dir;
> +	pci->debugfs = debugfs;
> +	ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> +	if (ret)
> +		dev_dbg(dev, "RASDES debugfs init failed\n");

What will happen if ret != 0? still return 0? 

Fan
> +
> +	return 0;
> +}
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 72418160e658..f9d7f3f989ad 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -814,6 +814,7 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>  
> +	dwc_pcie_debugfs_deinit(pci);
>  	dw_pcie_edma_remove(pci);
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
> @@ -989,6 +990,10 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>  
>  	dw_pcie_ep_init_non_sticky_registers(pci);
>  
> +	ret = dwc_pcie_debugfs_init(pci);
> +	if (ret)
> +		goto err_remove_edma;
> +
>  	return 0;
>  
>  err_remove_edma:
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index ffaded8f2df7..2081e8c72d12 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -548,6 +548,10 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	if (pp->ops->post_init)
>  		pp->ops->post_init(pp);
>  
> +	ret = dwc_pcie_debugfs_init(pci);
> +	if (ret)
> +		goto err_stop_link;
> +
>  	return 0;
>  
>  err_stop_link:
> @@ -572,6 +576,8 @@ void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>  
> +	dwc_pcie_debugfs_deinit(pci);
> +
>  	pci_stop_root_bus(pp->bridge->bus);
>  	pci_remove_root_bus(pp->bridge->bus);
>  
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index a7c0671c6715..3d1d95d9e380 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -323,6 +323,12 @@ static u16 dw_pcie_find_vsec_capability(struct dw_pcie *pci,
>  	return 0;
>  }
>  
> +u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci)
> +{
> +	return dw_pcie_find_vsec_capability(pci, dwc_pcie_rasdes_vsec_ids);
> +}
> +EXPORT_SYMBOL_GPL(dw_pcie_find_rasdes_capability);
> +
>  int dw_pcie_read(void __iomem *addr, int size, u32 *val)
>  {
>  	if (!IS_ALIGNED((uintptr_t)addr, size)) {
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 501d9ddfea16..7f9807d4e5de 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -437,6 +437,11 @@ struct dw_pcie_ops {
>  	void	(*stop_link)(struct dw_pcie *pcie);
>  };
>  
> +struct debugfs_info {
> +	struct dentry		*debug_dir;
> +	void			*rasdes_info;
> +};
> +
>  struct dw_pcie {
>  	struct device		*dev;
>  	void __iomem		*dbi_base;
> @@ -465,6 +470,7 @@ struct dw_pcie {
>  	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
>  	struct gpio_desc		*pe_rst;
>  	bool			suspended;
> +	struct debugfs_info	*debugfs;
>  };
>  
>  #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
> @@ -478,6 +484,7 @@ void dw_pcie_version_detect(struct dw_pcie *pci);
>  
>  u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap);
>  u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap);
> +u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci);
>  
>  int dw_pcie_read(void __iomem *addr, int size, u32 *val);
>  int dw_pcie_write(void __iomem *addr, int size, u32 val);
> @@ -806,4 +813,18 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
>  	return NULL;
>  }
>  #endif
> +
> +#ifdef CONFIG_PCIE_DW_DEBUGFS
> +int dwc_pcie_debugfs_init(struct dw_pcie *pci);
> +void dwc_pcie_debugfs_deinit(struct dw_pcie *pci);
> +#else
> +static inline int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> +{
> +	return 0;
> +}
> +static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
> +{
> +}
> +#endif
> +
>  #endif /* _PCIE_DESIGNWARE_H */
> diff --git a/include/linux/pcie-dwc.h b/include/linux/pcie-dwc.h
> index 40f3545731c8..6436e7fadc75 100644
> --- a/include/linux/pcie-dwc.h
> +++ b/include/linux/pcie-dwc.h
> @@ -28,6 +28,8 @@ static const struct dwc_pcie_vsec_id dwc_pcie_rasdes_vsec_ids[] = {
>  	  .vsec_id = 0x02, .vsec_rev = 0x4 },
>  	{ .vendor_id = PCI_VENDOR_ID_QCOM,
>  	  .vsec_id = 0x02, .vsec_rev = 0x4 },
> +	{ .vendor_id = PCI_VENDOR_ID_SAMSUNG,
> +	  .vsec_id = 0x02, .vsec_rev = 0x4 },
>  	{} /* terminator */
>  };
>  
> -- 
> 2.17.1
> 


From nifan.cxl at gmail.com  Mon Mar  3 09:53:57 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 09:53:57 -0800
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250221131548.59616-5-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
Message-ID: <Z8XstSB-BE6JG5hk@debian>

On Fri, Feb 21, 2025 at 06:45:47PM +0530, Shradha Todi wrote:
> Add support to provide error injection interface to userspace. This set
> of debug registers are part of the RASDES feature present in DesignWare
> PCIe controllers.
> 
> Signed-off-by: Shradha Todi <shradha.t at samsung.com>
> ---

LGTM.

Reviewed-by: Fan Ni <fan.ni at samsung.com>

>  Documentation/ABI/testing/debugfs-dwc-pcie    |  70 ++++++++
>  .../controller/dwc/pcie-designware-debugfs.c  | 165 +++++++++++++++++-
>  2 files changed, 233 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/debugfs-dwc-pcie b/Documentation/ABI/testing/debugfs-dwc-pcie
> index e8ed34e988ef..6ee0897fe753 100644
> --- a/Documentation/ABI/testing/debugfs-dwc-pcie
> +++ b/Documentation/ABI/testing/debugfs-dwc-pcie
> @@ -11,3 +11,73 @@ Contact:	Shradha Todi <shradha.t at samsung.com>
>  Description:	(RW) Write the lane number to be checked as valid or invalid. Read
>  		will return the status of PIPE RXVALID signal of the selected lane.
>  		The default selected lane is Lane0.
> +
> +What:		/sys/kernel/debug/dwc_pcie_<dev>/rasdes_err_inj/<error>
> +Date:		Feburary 2025
> +Contact:	Shradha Todi <shradha.t at samsung.com>
> +Description:	rasdes_err_inj is the directory which can be used to inject errors in the
> +		system. The possible errors that can be injected are:
> +
> +		1) TLP LCRC error injection TX Path - tx_lcrc
> +		2) 16b CRC error injection of ACK/NAK DLLP - b16_crc_dllp
> +		3) 16b CRC error injection of Update-FC DLLP - b16_crc_upd_fc
> +		4) TLP ECRC error injection TX Path - tx_ecrc
> +		5) TLP's FCRC error injection TX Path - fcrc_tlp
> +		6) Parity error of TSOS - parity_tsos
> +		7) Parity error on SKPOS - parity_skpos
> +		8) LCRC error injection RX Path - rx_lcrc
> +		9) ECRC error injection RX Path - rx_ecrc
> +		10) TLPs SEQ# error - tlp_err_seq
> +		11) DLLPS ACK/NAK SEQ# error - ack_nak_dllp_seq
> +		12) ACK/NAK DLLPs transmission block - ack_nak_dllp
> +		13) UpdateFC DLLPs transmission block - upd_fc_dllp
> +		14) Always transmission for NAK DLLP - nak_dllp
> +		15) Invert SYNC header - inv_sync_hdr_sym
> +		16) COM/PAD TS1 order set - com_pad_ts1
> +		17) COM/PAD TS2 order set - com_pad_ts2
> +		18) COM/FTS FTS order set - com_fts
> +		19) COM/IDL E-idle order set - com_idl
> +		20) END/EDB symbol - end_edb
> +		21) STP/SDP symbol - stp_sdp
> +		22) COM/SKP SKP order set - com_skp
> +		23) Posted TLP Header credit value control - posted_tlp_hdr
> +		24) Non-Posted TLP Header credit value control - non_post_tlp_hdr
> +		25) Completion TLP Header credit value control - cmpl_tlp_hdr
> +		26) Posted TLP Data credit value control - posted_tlp_data
> +		27) Non-Posted TLP Data credit value control - non_post_tlp_data
> +		28) Completion TLP Data credit value control - cmpl_tlp_data
> +		29) Generates duplicate TLPs - duplicate_dllp
> +		30) Generates Nullified TLPs - nullified_tlp
> +
> +		(WO) Write to the attribute will prepare controller to inject the respective
> +		error in the next transmission of data. Parameter required to write will
> +		change in the following ways:
> +
> +		i) Errors 9) - 10) are sequence errors. The write command for these will be
> +
> +			echo <count> <diff> > /sys/kernel/debug/dwc_pcie_<dev>/rasdes_err_inj/<error>
> +
> +			<count>
> +				Number of errors to be injected
> +			<diff>
> +				The difference to add or subtract from natural sequence number to
> +				generate sequence error. Range (-4095 : 4095)
> +
> +		ii) Errors 23) - 28) are credit value error insertions. Write command:
> +
> +			echo <count> <diff> <vc> > /sys/kernel/debug/dwc_pcie_<dev>/rasdes_err_inj/<error>
> +
> +			<count>
> +				Number of errors to be injected
> +			<diff>
> +				The difference to add or subtract from UpdateFC credit value.
> +				Range (-4095 : 4095)
> +			<vc>
> +				Target VC number
> +
> +		iii) All other errors. Write command:
> +
> +			echo <count> > /sys/kernel/debug/dwc_pcie_<dev>/rasdes_err_inj/<error>
> +
> +			<count>
> +				Number of errors to be injected
> diff --git a/drivers/pci/controller/dwc/pcie-designware-debugfs.c b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> index 3887a6996706..b7260edd2336 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> @@ -17,6 +17,20 @@
>  #define PIPE_DETECT_LANE		BIT(17)
>  #define LANE_SELECT			GENMASK(3, 0)
>  
> +#define ERR_INJ0_OFF			0x34
> +#define EINJ_VAL_DIFF			GENMASK(28, 16)
> +#define EINJ_VC_NUM			GENMASK(14, 12)
> +#define EINJ_TYPE_SHIFT			8
> +#define EINJ0_TYPE			GENMASK(11, 8)
> +#define EINJ1_TYPE			BIT(8)
> +#define EINJ2_TYPE			GENMASK(9, 8)
> +#define EINJ3_TYPE			GENMASK(10, 8)
> +#define EINJ4_TYPE			GENMASK(10, 8)
> +#define EINJ5_TYPE			BIT(8)
> +#define EINJ_COUNT			GENMASK(7, 0)
> +
> +#define ERR_INJ_ENABLE_REG		0x30
> +
>  #define DWC_DEBUGFS_BUF_MAX		128
>  
>  /**
> @@ -33,6 +47,72 @@ struct dwc_pcie_rasdes_info {
>  	struct mutex reg_event_lock;
>  };
>  
> +/**
> + * struct dwc_pcie_rasdes_priv - Stores file specific private data information
> + * @pci: Reference to the dw_pcie structure
> + * @idx: Index to point to specific file related information in array of structs
> + *
> + * All debugfs files will have this struct as its private data.
> + */
> +struct dwc_pcie_rasdes_priv {
> +	struct dw_pcie *pci;
> +	int idx;
> +};
> +
> +/**
> + * struct dwc_pcie_err_inj - Store details about each error injection supported by DWC RASDES
> + * @name: Name of the error that can be injected
> + * @err_inj_group: Group number to which the error belongs to. Value can range from 0 - 5
> + * @err_inj_type: Each group can have multiple types of error
> + */
> +struct dwc_pcie_err_inj {
> +	const char *name;
> +	u32 err_inj_group;
> +	u32 err_inj_type;
> +};
> +
> +static const struct dwc_pcie_err_inj err_inj_list[] = {
> +	{"tx_lcrc", 0x0, 0x0},
> +	{"b16_crc_dllp", 0x0, 0x1},
> +	{"b16_crc_upd_fc", 0x0, 0x2},
> +	{"tx_ecrc", 0x0, 0x3},
> +	{"fcrc_tlp", 0x0, 0x4},
> +	{"parity_tsos", 0x0, 0x5},
> +	{"parity_skpos", 0x0, 0x6},
> +	{"rx_lcrc", 0x0, 0x8},
> +	{"rx_ecrc", 0x0, 0xb},
> +	{"tlp_err_seq", 0x1, 0x0},
> +	{"ack_nak_dllp_seq", 0x1, 0x1},
> +	{"ack_nak_dllp", 0x2, 0x0},
> +	{"upd_fc_dllp", 0x2, 0x1},
> +	{"nak_dllp", 0x2, 0x2},
> +	{"inv_sync_hdr_sym", 0x3, 0x0},
> +	{"com_pad_ts1", 0x3, 0x1},
> +	{"com_pad_ts2", 0x3, 0x2},
> +	{"com_fts", 0x3, 0x3},
> +	{"com_idl", 0x3, 0x4},
> +	{"end_edb", 0x3, 0x5},
> +	{"stp_sdp", 0x3, 0x6},
> +	{"com_skp", 0x3, 0x7},
> +	{"posted_tlp_hdr", 0x4, 0x0},
> +	{"non_post_tlp_hdr", 0x4, 0x1},
> +	{"cmpl_tlp_hdr", 0x4, 0x2},
> +	{"posted_tlp_data", 0x4, 0x4},
> +	{"non_post_tlp_data", 0x4, 0x5},
> +	{"cmpl_tlp_data", 0x4, 0x6},
> +	{"duplicate_dllp", 0x5, 0x0},
> +	{"nullified_tlp", 0x5, 0x1},
> +};
> +
> +static const u32 err_inj_type_mask[] = {
> +	EINJ0_TYPE,
> +	EINJ1_TYPE,
> +	EINJ2_TYPE,
> +	EINJ3_TYPE,
> +	EINJ4_TYPE,
> +	EINJ5_TYPE,
> +};
> +
>  static ssize_t lane_detect_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
>  {
>  	struct dw_pcie *pci = file->private_data;
> @@ -93,6 +173,63 @@ static ssize_t rx_valid_write(struct file *file, const char __user *buf, size_t
>  	return lane_detect_write(file, buf, count, ppos);
>  }
>  
> +static ssize_t err_inj_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
> +{
> +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> +	struct dw_pcie *pci = pdata->pci;
> +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> +	u32 val, counter, vc_num, err_group, type_mask;
> +	int val_diff = 0;
> +	char *kern_buf;
> +
> +	err_group = err_inj_list[pdata->idx].err_inj_group;
> +	type_mask = err_inj_type_mask[err_group];
> +
> +	kern_buf = memdup_user_nul(buf, count);
> +	if (IS_ERR(kern_buf))
> +		return PTR_ERR(kern_buf);
> +
> +	if (err_group == 4) {
> +		val = sscanf(kern_buf, "%u %d %u", &counter, &val_diff, &vc_num);
> +		if ((val != 3) || (val_diff < -4095 || val_diff > 4095)) {
> +			kfree(kern_buf);
> +			return -EINVAL;
> +		}
> +	} else if (err_group == 1) {
> +		val = sscanf(kern_buf, "%u %d", &counter, &val_diff);
> +		if ((val != 2) || (val_diff < -4095 || val_diff > 4095)) {
> +			kfree(kern_buf);
> +			return -EINVAL;
> +		}
> +	} else {
> +		val = kstrtou32(kern_buf, 0, &counter);
> +		if (val) {
> +			kfree(kern_buf);
> +			return val;
> +		}
> +	}
> +
> +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + ERR_INJ0_OFF + (0x4 * err_group));
> +	val &= ~(type_mask | EINJ_COUNT);
> +	val |= ((err_inj_list[pdata->idx].err_inj_type << EINJ_TYPE_SHIFT) & type_mask);
> +	val |= FIELD_PREP(EINJ_COUNT, counter);
> +
> +	if (err_group == 1 || err_group == 4) {
> +		val &= ~(EINJ_VAL_DIFF);
> +		val |= FIELD_PREP(EINJ_VAL_DIFF, val_diff);
> +	}
> +	if (err_group == 4) {
> +		val &= ~(EINJ_VC_NUM);
> +		val |= FIELD_PREP(EINJ_VC_NUM, vc_num);
> +	}
> +
> +	dw_pcie_writel_dbi(pci, rinfo->ras_cap_offset + ERR_INJ0_OFF + (0x4 * err_group), val);
> +	dw_pcie_writel_dbi(pci, rinfo->ras_cap_offset + ERR_INJ_ENABLE_REG, (0x1 << err_group));
> +
> +	kfree(kern_buf);
> +	return count;
> +}
> +
>  #define dwc_debugfs_create(name)			\
>  debugfs_create_file(#name, 0644, rasdes_debug, pci,	\
>  			&dbg_ ## name ## _fops)
> @@ -107,6 +244,11 @@ static const struct file_operations dbg_ ## name ## _fops = {	\
>  DWC_DEBUGFS_FOPS(lane_detect);
>  DWC_DEBUGFS_FOPS(rx_valid);
>  
> +static const struct file_operations dwc_pcie_err_inj_ops = {
> +	.open = simple_open,
> +	.write = err_inj_write,
> +};
> +
>  static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
>  {
>  	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> @@ -116,10 +258,11 @@ static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
>  
>  static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  {
> -	struct dentry *rasdes_debug;
> +	struct dentry *rasdes_debug, *rasdes_err_inj;
>  	struct dwc_pcie_rasdes_info *rasdes_info;
> +	struct dwc_pcie_rasdes_priv *priv_tmp;
>  	struct device *dev = pci->dev;
> -	int ras_cap;
> +	int ras_cap, i, ret;
>  
>  	ras_cap = dw_pcie_find_rasdes_capability(pci);
>  	if (!ras_cap) {
> @@ -133,6 +276,7 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  
>  	/* Create subdirectories for Debug, Error injection, Statistics */
>  	rasdes_debug = debugfs_create_dir("rasdes_debug", dir);
> +	rasdes_err_inj = debugfs_create_dir("rasdes_err_inj", dir);
>  
>  	mutex_init(&rasdes_info->reg_event_lock);
>  	rasdes_info->ras_cap_offset = ras_cap;
> @@ -142,7 +286,24 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  	dwc_debugfs_create(lane_detect);
>  	dwc_debugfs_create(rx_valid);
>  
> +	/* Create debugfs files for Error injection subdirectory */
> +	for (i = 0; i < ARRAY_SIZE(err_inj_list); i++) {
> +		priv_tmp = devm_kzalloc(dev, sizeof(*priv_tmp), GFP_KERNEL);
> +		if (!priv_tmp) {
> +			ret = -ENOMEM;
> +			goto err_deinit;
> +		}
> +
> +		priv_tmp->idx = i;
> +		priv_tmp->pci = pci;
> +		debugfs_create_file(err_inj_list[i].name, 0200, rasdes_err_inj, priv_tmp,
> +				    &dwc_pcie_err_inj_ops);
> +	}
>  	return 0;
> +
> +err_deinit:
> +	dwc_pcie_rasdes_debugfs_deinit(pci);
> +	return ret;
>  }
>  
>  void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
> -- 
> 2.17.1
> 


From nifan.cxl at gmail.com  Mon Mar  3 10:02:32 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 10:02:32 -0800
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <20250221131548.59616-6-shradha.t@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
 <20250221131548.59616-6-shradha.t@samsung.com>
Message-ID: <Z8XuuNb6TRevUlHH@debian>

On Fri, Feb 21, 2025 at 06:45:48PM +0530, Shradha Todi wrote:
> Add support to provide statistical counter interface to userspace. This set
> of debug registers are part of the RASDES feature present in DesignWare
> PCIe controllers.
> 
One comment inline.
> Signed-off-by: Shradha Todi <shradha.t at samsung.com>
> ---
>  Documentation/ABI/testing/debugfs-dwc-pcie    |  61 +++++
>  .../controller/dwc/pcie-designware-debugfs.c  | 229 +++++++++++++++++-
>  2 files changed, 289 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/ABI/testing/debugfs-dwc-pcie b/Documentation/ABI/testing/debugfs-dwc-pcie
> index 6ee0897fe753..650a89b0511e 100644
> --- a/Documentation/ABI/testing/debugfs-dwc-pcie
> +++ b/Documentation/ABI/testing/debugfs-dwc-pcie
> @@ -81,3 +81,64 @@ Description:	rasdes_err_inj is the directory which can be used to inject errors
>  
>  			<count>
>  				Number of errors to be injected

...

> +
> +static ssize_t counter_value_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
> +{
> +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> +	struct dw_pcie *pci = pdata->pci;
> +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> +	ssize_t pos;
> +	u32 val;
> +
> +	mutex_lock(&rinfo->reg_event_lock);
> +	set_event_number(pdata, pci, rinfo);
> +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> +	mutex_unlock(&rinfo->reg_event_lock);
> +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter value: %d\n", val);
> +
> +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf, pos);
> +}

Do we need to check whether the counter is enabled or not for the event
before retrieving the counter value?

Fan
> +
>  #define dwc_debugfs_create(name)			\
>  debugfs_create_file(#name, 0644, rasdes_debug, pci,	\
>  			&dbg_ ## name ## _fops)
> @@ -249,6 +436,23 @@ static const struct file_operations dwc_pcie_err_inj_ops = {
>  	.write = err_inj_write,
>  };
>  
> +static const struct file_operations dwc_pcie_counter_enable_ops = {
> +	.open = simple_open,
> +	.read = counter_enable_read,
> +	.write = counter_enable_write,
> +};
> +
> +static const struct file_operations dwc_pcie_counter_lane_ops = {
> +	.open = simple_open,
> +	.read = counter_lane_read,
> +	.write = counter_lane_write,
> +};
> +
> +static const struct file_operations dwc_pcie_counter_value_ops = {
> +	.open = simple_open,
> +	.read = counter_value_read,
> +};
> +
>  static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
>  {
>  	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> @@ -258,7 +462,7 @@ static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
>  
>  static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  {
> -	struct dentry *rasdes_debug, *rasdes_err_inj;
> +	struct dentry *rasdes_debug, *rasdes_err_inj, *rasdes_event_counter, *rasdes_events;
>  	struct dwc_pcie_rasdes_info *rasdes_info;
>  	struct dwc_pcie_rasdes_priv *priv_tmp;
>  	struct device *dev = pci->dev;
> @@ -277,6 +481,7 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  	/* Create subdirectories for Debug, Error injection, Statistics */
>  	rasdes_debug = debugfs_create_dir("rasdes_debug", dir);
>  	rasdes_err_inj = debugfs_create_dir("rasdes_err_inj", dir);
> +	rasdes_event_counter = debugfs_create_dir("rasdes_event_counter", dir);
>  
>  	mutex_init(&rasdes_info->reg_event_lock);
>  	rasdes_info->ras_cap_offset = ras_cap;
> @@ -299,6 +504,28 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
>  		debugfs_create_file(err_inj_list[i].name, 0200, rasdes_err_inj, priv_tmp,
>  				    &dwc_pcie_err_inj_ops);
>  	}
> +
> +	/* Create debugfs files for Statistical counter subdirectory */
> +	for (i = 0; i < ARRAY_SIZE(event_list); i++) {
> +		priv_tmp = devm_kzalloc(dev, sizeof(*priv_tmp), GFP_KERNEL);
> +		if (!priv_tmp) {
> +			ret = -ENOMEM;
> +			goto err_deinit;
> +		}
> +
> +		priv_tmp->idx = i;
> +		priv_tmp->pci = pci;
> +		rasdes_events = debugfs_create_dir(event_list[i].name, rasdes_event_counter);
> +		if (event_list[i].group_no == 0 || event_list[i].group_no == 4) {
> +			debugfs_create_file("lane_select", 0644, rasdes_events,
> +					    priv_tmp, &dwc_pcie_counter_lane_ops);
> +		}
> +		debugfs_create_file("counter_value", 0444, rasdes_events, priv_tmp,
> +				    &dwc_pcie_counter_value_ops);
> +		debugfs_create_file("counter_enable", 0644, rasdes_events, priv_tmp,
> +				    &dwc_pcie_counter_enable_ops);
> +	}
> +
>  	return 0;
>  
>  err_deinit:
> -- 
> 2.17.1
> 


From suzuki.poulose at arm.com  Mon Mar  3 10:02:56 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 3 Mar 2025 18:02:56 +0000
Subject: [PATCH v7 14/45] arm64: RME: Support for the VGIC in realms
In-Reply-To: <20250213161426.102987-15-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-15-steven.price@arm.com>
Message-ID: <6a7bf3ea-6f9b-4f8f-aa23-9a75a7c2e190@arm.com>

On 13/02/2025 16:13, Steven Price wrote:
> The RMM provides emulation of a VGIC to the realm guest but delegates
> much of the handling to the host. Implement support in KVM for
> saving/restoring state to/from the REC structure.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes from v5:
>   * Handle RMM providing fewer GIC LRs than the hardware supports.
> ---
>   arch/arm64/include/asm/kvm_rme.h |  1 +
>   arch/arm64/kvm/arm.c             | 16 +++++++++---
>   arch/arm64/kvm/rme.c             |  5 ++++
>   arch/arm64/kvm/vgic/vgic-init.c  |  2 +-
>   arch/arm64/kvm/vgic/vgic-v3.c    |  5 ++++
>   arch/arm64/kvm/vgic/vgic.c       | 43 ++++++++++++++++++++++++++++++--
>   6 files changed, 66 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_rme.h
> index 5db377943db4..2e319db9a05f 100644
> --- a/arch/arm64/include/asm/kvm_rme.h
> +++ b/arch/arm64/include/asm/kvm_rme.h
> @@ -83,6 +83,7 @@ struct realm_rec {
>   
>   void kvm_init_rme(void);
>   u32 kvm_realm_ipa_limit(void);
> +u32 kvm_realm_vgic_nr_lr(void);
>   
>   int kvm_realm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap);
>   int kvm_init_realm_vm(struct kvm *kvm);
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index a6a3034a2f50..a2bc86b3798f 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -672,19 +672,24 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
>   		kvm_call_hyp_nvhe(__pkvm_vcpu_put);
>   	}
>   
> +	kvm_timer_vcpu_put(vcpu);
> +	kvm_vgic_put(vcpu);
> +
> +	vcpu->cpu = -1;
> +
> +	if (vcpu_is_rec(vcpu))
> +		return;
> +
>   	kvm_vcpu_put_debug(vcpu);
>   	kvm_arch_vcpu_put_fp(vcpu);
>   	if (has_vhe())
>   		kvm_vcpu_put_vhe(vcpu);
> -	kvm_timer_vcpu_put(vcpu);
> -	kvm_vgic_put(vcpu);
>   	kvm_vcpu_pmu_restore_host(vcpu);
>   	if (vcpu_has_nv(vcpu))
>   		kvm_vcpu_put_hw_mmu(vcpu);
>   	kvm_arm_vmid_clear_active();
>   
>   	vcpu_clear_on_unsupported_cpu(vcpu);
> -	vcpu->cpu = -1;
>   }
>   
>   static void __kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
> @@ -889,6 +894,11 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
>   			return ret;
>   	}
>   
> +	if (!irqchip_in_kernel(kvm) && kvm_is_realm(vcpu->kvm)) {
> +		/* Userspace irqchip not yet supported with Realms */
> +		return -EOPNOTSUPP;
> +	}
> +
>   	mutex_lock(&kvm->arch.config_lock);
>   	set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
>   	mutex_unlock(&kvm->arch.config_lock);
> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> index 0aa1f29b0610..195390a66bc4 100644
> --- a/arch/arm64/kvm/rme.c
> +++ b/arch/arm64/kvm/rme.c
> @@ -77,6 +77,11 @@ u32 kvm_realm_ipa_limit(void)
>   	return u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_S2SZ);
>   }
>   
> +u32 kvm_realm_vgic_nr_lr(void)
> +{
> +	return u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS);
> +}
> +
>   static int get_start_level(struct realm *realm)
>   {
>   	return 4 - ((realm->ia_bits - 8) / (RMM_PAGE_SHIFT - 3));
> diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
> index bc7e22ab5d81..0ec9f6f62e86 100644
> --- a/arch/arm64/kvm/vgic/vgic-init.c
> +++ b/arch/arm64/kvm/vgic/vgic-init.c
> @@ -79,7 +79,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
>   	 * the proper checks already.
>   	 */
>   	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
> -		!kvm_vgic_global_state.can_emulate_gicv2)
> +	    (!kvm_vgic_global_state.can_emulate_gicv2 || kvm_is_realm(kvm)))
>   		return -ENODEV;
>   
>   	/* Must be held to avoid race with vCPU creation */
> diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
> index d7233ab982d0..41c3de063e72 100644
> --- a/arch/arm64/kvm/vgic/vgic-v3.c
> +++ b/arch/arm64/kvm/vgic/vgic-v3.c
> @@ -8,9 +8,11 @@
>   #include <linux/kvm_host.h>
>   #include <linux/string_choices.h>
>   #include <kvm/arm_vgic.h>
> +#include <asm/kvm_emulate.h>
>   #include <asm/kvm_hyp.h>
>   #include <asm/kvm_mmu.h>
>   #include <asm/kvm_asm.h>
> +#include <asm/rmi_smc.h>
>   
>   #include "vgic.h"
>   
> @@ -748,6 +750,9 @@ void vgic_v3_put(struct kvm_vcpu *vcpu)
>   {
>   	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
>   
> +	if (vcpu_is_rec(vcpu))
> +		cpu_if->vgic_vmcr = vcpu->arch.rec.run->exit.gicv3_vmcr;
> +


>   	if (likely(!is_protected_kvm_enabled()))

	else if (likely(...)) ?

>   		kvm_call_hyp(__vgic_v3_save_vmcr_aprs, cpu_if);

Otherwise, the VMCR could be rewritten from what we set above and 
pointless APR saves ?

Rest looks good to me.

Suzuki

>   	WARN_ON(vgic_v4_put(vcpu));
> diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
> index 1077fab2df4b..4218de3ea9da 100644
> --- a/arch/arm64/kvm/vgic/vgic.c
> +++ b/arch/arm64/kvm/vgic/vgic.c
> @@ -10,7 +10,9 @@
>   #include <linux/list_sort.h>
>   #include <linux/nospec.h>
>   
> +#include <asm/kvm_emulate.h>
>   #include <asm/kvm_hyp.h>
> +#include <asm/kvm_rme.h>
>   
>   #include "vgic.h"
>   
> @@ -23,6 +25,8 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
>   
>   static inline int kvm_vcpu_vgic_nr_lr(struct kvm_vcpu *vcpu)
>   {
> +	if (unlikely(vcpu_is_rec(vcpu)))
> +		return kvm_realm_vgic_nr_lr();
>   	return kvm_vgic_global_state.nr_lr;
>   }
>   
> @@ -864,10 +868,23 @@ static inline bool can_access_vgic_from_kernel(void)
>   	return !static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) || has_vhe();
>   }
>   
> +static inline void vgic_rmm_save_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
> +	int i;
> +
> +	for (i = 0; i < kvm_vcpu_vgic_nr_lr(vcpu); i++) {
> +		cpu_if->vgic_lr[i] = vcpu->arch.rec.run->exit.gicv3_lrs[i];
> +		vcpu->arch.rec.run->enter.gicv3_lrs[i] = 0;
> +	}
> +}
> +
>   static inline void vgic_save_state(struct kvm_vcpu *vcpu)
>   {
>   	if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>   		vgic_v2_save_state(vcpu);
> +	else if (vcpu_is_rec(vcpu))
> +		vgic_rmm_save_state(vcpu);
>   	else
>   		__vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3);
>   }
> @@ -894,10 +911,28 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
>   	vgic_prune_ap_list(vcpu);
>   }
>   
> +static inline void vgic_rmm_restore_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
> +	int i;
> +
> +	for (i = 0; i < kvm_vcpu_vgic_nr_lr(vcpu); i++) {
> +		vcpu->arch.rec.run->enter.gicv3_lrs[i] = cpu_if->vgic_lr[i];
> +		/*
> +		 * Also populate the rec.run->exit copies so that a late
> +		 * decision to back out from entering the realm doesn't cause
> +		 * the state to be lost
> +		 */
> +		vcpu->arch.rec.run->exit.gicv3_lrs[i] = cpu_if->vgic_lr[i];
> +	}
> +}
> +
>   static inline void vgic_restore_state(struct kvm_vcpu *vcpu)
>   {
>   	if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>   		vgic_v2_restore_state(vcpu);
> +	else if (vcpu_is_rec(vcpu))
> +		vgic_rmm_restore_state(vcpu);
>   	else
>   		__vgic_v3_restore_state(&vcpu->arch.vgic_cpu.vgic_v3);
>   }
> @@ -938,7 +973,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
>   
>   void kvm_vgic_load(struct kvm_vcpu *vcpu)
>   {
> -	if (unlikely(!irqchip_in_kernel(vcpu->kvm) || !vgic_initialized(vcpu->kvm))) {
> +	if (unlikely(!irqchip_in_kernel(vcpu->kvm) ||
> +		     !vgic_initialized(vcpu->kvm) ||
> +		     vcpu_is_rec(vcpu))) {
>   		if (has_vhe() && static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>   			__vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3);
>   		return;
> @@ -952,7 +989,9 @@ void kvm_vgic_load(struct kvm_vcpu *vcpu)
>   
>   void kvm_vgic_put(struct kvm_vcpu *vcpu)
>   {
> -	if (unlikely(!irqchip_in_kernel(vcpu->kvm) || !vgic_initialized(vcpu->kvm))) {
> +	if (unlikely(!irqchip_in_kernel(vcpu->kvm) ||
> +		     !vgic_initialized(vcpu->kvm) ||
> +		     vcpu_is_rec(vcpu))) {
>   		if (has_vhe() && static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>   			__vgic_v3_deactivate_traps(&vcpu->arch.vgic_cpu.vgic_v3);
>   		return;



From leo.yan at arm.com  Mon Mar  3 10:11:52 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 3 Mar 2025 18:11:52 +0000
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <447bcafc-4c47-4b95-bf21-7aee2cb6a629@intel.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
 <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
 <20250303162210.GH2157064@e132581.arm.com>
 <447bcafc-4c47-4b95-bf21-7aee2cb6a629@intel.com>
Message-ID: <20250303181152.GI2157064@e132581.arm.com>

On Mon, Mar 03, 2025 at 05:05:13PM +0200, Adrian Hunter wrote:

[...]

> >>> +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
> >>> +	return fprintf(fp, "  %-*s ", ret, str);
> >>
> >> -21 means the field width is 21 and left-justified.  It should not
> >> truncate the string.
> > 
> > No, it does not truncate the string.
> > 
> > It calculates a maximum value between the returned length and 21 (
> > defined in SAMPLE_FLAGS_STR_ALIGNED_SIZE).  It keeps left-justified and
> > can printing a complete string if the string length is bigger than 21.
> 
> Maybe I am missing something, but that isn't that what
> 
> 	return fprintf(fp, "  %-21s ", str);
> 
> does anyway?  Why change it to something more complicated.

You are right.  I should have done an experiment for this.

I will remove the max() sentence and update the last line:

        return fprintf(fp, "  %-*s ", SAMPLE_FLAGS_STR_ALIGNED_SIZE, str);

Another option is to drop this patch.  But I prefer to keep it, the
reason is except the benefit for the debugging log, an extra reason is
the SAMPLE_FLAGS_STR_ALIGNED_SIZE macro is used to replace the opened
value '21'.  The macro also will be used by a later patch for
right-alignment printing.  How about you think?

Thanks,
Leo


From florian.fainelli at broadcom.com  Mon Mar  3 10:18:03 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 3 Mar 2025 10:18:03 -0800
Subject: [PATCH] ARM: dts: bcm2711: Don't mark timer regs unconfigured
In-Reply-To: <20250222094113.48198-1-wahrenst@gmx.net>
References: <20250222094113.48198-1-wahrenst@gmx.net>
Message-ID: <3555a62e-b0aa-4564-827f-98508ceb77d1@broadcom.com>

On 2/22/25 01:41, Stefan Wahren wrote:
> From: Phil Elwell <phil at raspberrypi.com>
> 
> During upstream process of Raspberry Pi 4 back in 2019 the ARMv7 stubs
> didn't configured the ARM architectural timer. This firmware issue has
> been fixed in 2020, which gave users enough time to update their system.
> 
> So drop this property to allow the use of the vDSO version of
> clock_gettime.
> 
> Link: https://github.com/raspberrypi/tools/pull/113
> Fixes: 7dbe8c62ceeb ("ARM: dts: Add minimal Raspberry Pi 4 support")
> Signed-off-by: Phil Elwell <phil at raspberrypi.com>
> Signed-off-by: Stefan Wahren <wahrenst at gmx.net>

Applied to devicetree/fixes, thanks!
-- 
Florian


From heiko at sntech.de  Mon Mar  3 10:22:56 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon,  3 Mar 2025 19:22:56 +0100
Subject: [PATCH] drm/rockchip: vop2: add missing bitfield.h include
Message-ID: <20250303182256.1727178-1-heiko@sntech.de>

Commit 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
moved per soc configuration code to the other per-soc data into
rockchip_vop2_reg.c, but forgot to also include bitfield.h for the used
FIELD_PREP macro. Add this missing include.

Fixes: 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503040135.fgoyWdLB-lkp at intel.com/
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 0afef24db144..f86a30df94aa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -4,6 +4,7 @@
  * Author: Andy Yan <andy.yan at rock-chips.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/kernel.h>
 #include <linux/component.h>
 #include <linux/mod_devicetable.h>
-- 
2.47.2



From c-vankar at ti.com  Mon Mar  3 10:26:37 2025
From: c-vankar at ti.com (Vankar, Chintan)
Date: Mon, 3 Mar 2025 23:56:37 +0530
Subject: [PATCH v2 1/2] arm64: dts: ti: k3-am68-sk/k3-j721s2-mcu: Add
 bootph-all property to enable Ethernet boot
In-Reply-To: <6b5839b3-84cb-42ee-8336-81ebf9b2e40d@ti.com>
References: <20250302153502.181832-1-c-vankar@ti.com>
 <20250302153502.181832-2-c-vankar@ti.com>
 <6b5839b3-84cb-42ee-8336-81ebf9b2e40d@ti.com>
Message-ID: <13bd564d-84bc-4b97-9591-126eb51772fb@ti.com>

Hello Vignesh,

On 3/3/2025 1:44 PM, Vignesh Raghavendra wrote:
> 
> 
> On 02/03/25 21:05, Chintan Vankar wrote:
>> Ethernet boot requires CPSW nodes to be present starting from R5 SPL
>> stage. Add bootph-all property to required nodes to enable Ethernet boot
>> on AM68-SK and J721S2-EVM.
>>
>> Signed-off-by: Chintan Vankar <c-vankar at ti.com>
>> ---
>>
>> Link to v1:
>> https://lore.kernel.org/r/20250106123122.3531845-2-c-vankar at ti.com/
>>
>> Changes from v1 to v2:
>> - No changes.
>>
>>   arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 3 +++
>>   arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 4 ++++
>>   2 files changed, 7 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
>> index 11522b36e0ce..8e9101dd2152 100644
>> --- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
>> +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
>> @@ -333,6 +333,7 @@ J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
>>   			J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
>>   			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
>>   		>;
>> +		bootph-all;
>>   	};
>>   
>>   	mcu_mdio_pins_default: mcu-mdio-default-pins {
>> @@ -340,6 +341,7 @@ mcu_mdio_pins_default: mcu-mdio-default-pins {
>>   			J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
>>   			J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
>>   		>;
>> +		bootph-all;
>>   	};
>>   
>>   	mcu_mcan0_pins_default: mcu-mcan0-default-pins {
>> @@ -615,6 +617,7 @@ &mcu_cpsw {
>>   &davinci_mdio {
>>   	phy0: ethernet-phy at 0 {
>>   		reg = <0>;
>> +		bootph-all;
>>   		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
>>   		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
>>   		ti,min-output-impedance;
>> diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
>> index bc31266126d0..29cd4b1ffbbf 100644
>> --- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
>> +++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
>> @@ -154,12 +154,14 @@ mcu_conf: bus at 40f00000 {
>>   		cpsw_mac_syscon: ethernet-mac-syscon at 200 {
>>   			compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
>>   			reg = <0x200 0x8>;
>> +			bootph-all;
>>   		};
>>   
>>   		phy_gmii_sel: phy at 4040 {
>>   			compatible = "ti,am654-phy-gmii-sel";
>>   			reg = <0x4040 0x4>;
>>   			#phy-cells = <1>;
>> +			bootph-all;
>>   		};
>>   
>>   	};
>> @@ -538,6 +540,7 @@ mcu_cpsw: ethernet at 46000000 {
>>   		clocks = <&k3_clks 29 28>;
>>   		clock-names = "fck";
>>   		power-domains = <&k3_pds 29 TI_SCI_PD_EXCLUSIVE>;
>> +		bootph-all;
>>   
> 
> Since a child node has bootph-all, no need to put the same in the parent
> hierarchy.
> 

Thank you for pointing this out, I will remove it from the parent node
and post the next version.

Regards,
Chintan.

>>   		dmas = <&mcu_udmap 0xf000>,
>>   		       <&mcu_udmap 0xf001>,
>> @@ -562,6 +565,7 @@ cpsw_port1: port at 1 {
>>   				label = "port1";
>>   				ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
>>   				phys = <&phy_gmii_sel 1>;
>> +				bootph-all;
>>   			};
>>   		};
>>   
> 
> 


From adrian.hunter at intel.com  Mon Mar  3 08:56:42 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Mon, 3 Mar 2025 18:56:42 +0200
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <20250303181152.GI2157064@e132581.arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
 <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
 <20250303162210.GH2157064@e132581.arm.com>
 <447bcafc-4c47-4b95-bf21-7aee2cb6a629@intel.com>
 <20250303181152.GI2157064@e132581.arm.com>
Message-ID: <c227a1c2-13a4-4078-87ee-ed3fe0638060@intel.com>

On 3/03/25 20:11, Leo Yan wrote:
> On Mon, Mar 03, 2025 at 05:05:13PM +0200, Adrian Hunter wrote:
> 
> [...]
> 
>>>>> +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
>>>>> +	return fprintf(fp, "  %-*s ", ret, str);
>>>>
>>>> -21 means the field width is 21 and left-justified.  It should not
>>>> truncate the string.
>>>
>>> No, it does not truncate the string.
>>>
>>> It calculates a maximum value between the returned length and 21 (
>>> defined in SAMPLE_FLAGS_STR_ALIGNED_SIZE).  It keeps left-justified and
>>> can printing a complete string if the string length is bigger than 21.
>>
>> Maybe I am missing something, but that isn't that what
>>
>> 	return fprintf(fp, "  %-21s ", str);
>>
>> does anyway?  Why change it to something more complicated.
> 
> You are right.  I should have done an experiment for this.
> 
> I will remove the max() sentence and update the last line:
> 
>         return fprintf(fp, "  %-*s ", SAMPLE_FLAGS_STR_ALIGNED_SIZE, str);
> 
> Another option is to drop this patch.  But I prefer to keep it, the
> reason is except the benefit for the debugging log, an extra reason is
> the SAMPLE_FLAGS_STR_ALIGNED_SIZE macro is used to replace the opened
> value '21'.  The macro also will be used by a later patch for
> right-alignment printing.  How about you think?

Sure



From helgaas at kernel.org  Mon Mar  3 10:40:11 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 3 Mar 2025 12:40:11 -0600
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <20250214173944.47506-5-james.quinlan@broadcom.com>
Message-ID: <20250303184011.GA172021@bhelgaas>

On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> If regulator_bulk_get() returns an error, no regulators are created and we
> need to set their number to zero.  If we do not do this and the PCIe
> link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> 
> Also print out the error value, as we cannot return an error upwards as
> Linux will WARN on an error from add_bus().
> 
> Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> ---
>  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index e0b20f58c604..56b49d3cae19 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
>  
>  		ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
>  		if (ret) {
> -			dev_info(dev, "No regulators for downstream device\n");
> +			dev_info(dev, "Did not get regulators; err=%d\n", ret);
> +			pcie->sr = NULL;

Is alloc_subdev_regulators() buying us something useful?  It seems
like it would be simpler to have:

  struct brcm_pcie {
    ...
    struct regulator_bulk_data supplies[3];
    ...
  };

I think that's what most callers of devm_regulator_bulk_get() do.

>  			goto no_regulators;
>  		}
>  
> -- 
> 2.43.0
> 


From alexei.starovoitov at gmail.com  Mon Mar  3 10:43:07 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Mon, 3 Mar 2025 10:43:07 -0800
Subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <202503031631.OeUhVRHz-lkp@intel.com>
References: <2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin@google.com>
 <202503031631.OeUhVRHz-lkp@intel.com>
Message-ID: <CAADnVQLLhNRmpjwDYHB0-59TDrGcgXzqSkop+-5eHYsG-Ws08Q@mail.gmail.com>

On Mon, Mar 3, 2025 at 12:55?AM kernel test robot <lkp at intel.com> wrote:
>
> Hi Peilin,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on bpf-next/master]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Peilin-Ye/bpf-verifier-Factor-out-atomic_ptr_type_ok/20250303-134110
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
> patch link:    https://lore.kernel.org/r/2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin%40google.com
> patch subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and store-release instructions
> config: arc-randconfig-002-20250303 (https://download.01.org/0day-ci/archive/20250303/202503031631.OeUhVRHz-lkp at intel.com/config)
> compiler: arc-elf-gcc (GCC) 13.2.0

...

>    kernel/bpf/core.c:2228:25: note: in expansion of macro 'LOAD_ACQUIRE'
>     2228 |                         LOAD_ACQUIRE(DW, u64)
>          |                         ^~~~~~~~~~~~

Peilin,

how do you plan on fixing this?
So far I could only think of making compilation conditional for CONFIG_64BIT
and let the verifier reject these insns on 32-bit arches.
Other ideas?


From leo.yan at arm.com  Mon Mar  3 10:49:17 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 3 Mar 2025 18:49:17 +0000
Subject: [PATCH v3 01/12] perf script: Make printing flags reliable
In-Reply-To: <c227a1c2-13a4-4078-87ee-ed3fe0638060@intel.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250217195908.176207-2-leo.yan@arm.com>
 <34795c29-d256-49ce-9d01-435f8cd91611@intel.com>
 <20250303162210.GH2157064@e132581.arm.com>
 <447bcafc-4c47-4b95-bf21-7aee2cb6a629@intel.com>
 <20250303181152.GI2157064@e132581.arm.com>
 <c227a1c2-13a4-4078-87ee-ed3fe0638060@intel.com>
Message-ID: <20250303184917.GJ2157064@e132581.arm.com>

On Mon, Mar 03, 2025 at 06:56:42PM +0200, Adrian Hunter wrote:
> On 3/03/25 20:11, Leo Yan wrote:
> > On Mon, Mar 03, 2025 at 05:05:13PM +0200, Adrian Hunter wrote:
> > 
> > [...]
> > 
> >>>>> +	ret = max(ret, SAMPLE_FLAGS_STR_ALIGNED_SIZE);
> >>>>> +	return fprintf(fp, "  %-*s ", ret, str);
> >>>>
> >>>> -21 means the field width is 21 and left-justified.  It should not
> >>>> truncate the string.
> >>>
> >>> No, it does not truncate the string.
> >>>
> >>> It calculates a maximum value between the returned length and 21 (
> >>> defined in SAMPLE_FLAGS_STR_ALIGNED_SIZE).  It keeps left-justified and
> >>> can printing a complete string if the string length is bigger than 21.
> >>
> >> Maybe I am missing something, but that isn't that what
> >>
> >> 	return fprintf(fp, "  %-21s ", str);
> >>
> >> does anyway?  Why change it to something more complicated.
> > 
> > You are right.  I should have done an experiment for this.
> > 
> > I will remove the max() sentence and update the last line:
> > 
> >         return fprintf(fp, "  %-*s ", SAMPLE_FLAGS_STR_ALIGNED_SIZE, str);
> > 
> > Another option is to drop this patch.  But I prefer to keep it, the
> > reason is except the benefit for the debugging log, an extra reason is
> > the SAMPLE_FLAGS_STR_ALIGNED_SIZE macro is used to replace the opened
> > value '21'.  The macro also will be used by a later patch for
> > right-alignment printing.  How about you think?
> 
> Sure

Thanks a lot for confirmation and review!

I will send new version in my tomorrow.

Leo


From maz at kernel.org  Mon Mar  3 10:49:58 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 03 Mar 2025 18:49:58 +0000
Subject: [PATCH v3 6/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <Z8WUxyJT1fdHKo67@nchen-desktop>
References: <20250227120619.1741431-1-peter.chen@cixtech.com>
	<20250227120619.1741431-7-peter.chen@cixtech.com>
	<86r03ip0kf.wl-maz@kernel.org>
	<Z8WUxyJT1fdHKo67@nchen-desktop>
Message-ID: <86ikoqoso9.wl-maz@kernel.org>

On Mon, 03 Mar 2025 11:38:47 +0000,
Peter Chen <peter.chen at cixtech.com> wrote:
> 
> On 25-02-28 15:10:24, Marc Zyngier wrote:
> 
> Hi Marc,
> 
> Thanks for your detail review.
> 
> > > +
> > > +             cpu10: cpu at a00 {
> > > +                     compatible = "arm,cortex-a720";
> > > +                     enable-method = "psci";
> > > +                     reg = <0x0 0xa00>;
> > > +                     device_type = "cpu";
> > > +                     capacity-dmips-mhz = <1024>;
> > > +             };
> > > +
> > > +             cpu11: cpu at b00 {
> > > +                     compatible = "arm,cortex-a720";
> > > +                     enable-method = "psci";
> > > +                     reg = <0x0 0xb00>;
> > > +                     device_type = "cpu";
> > > +                     capacity-dmips-mhz = <1024>;
> > > +             };
> > 
> > Given that half the A720s are advertised with lower clock speed, how
> > comes they all have the same capacity?
> 
> According to Documentation/devicetree/bindings/cpu/cpu-capacity.txt
> "capacity-dmips-mhz" is u32 value representing CPU capacity expressed
> in normalized DMIPS/MHz, it means CPU capability per MHz. For sky1
> SoC, both middle and big cores are A720, so their capability per MHz
> are the same.

Ah, fair enough. I missed that detail.

> 
> > > +
> > > +     pmu-a520 {
> > > +             compatible = "arm,cortex-a520-pmu";
> > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > > +     };
> > > +
> > > +     pmu-a720 {
> > > +             compatible = "arm,cortex-a720-pmu";
> > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > > +     };
> > 
> > This is wrong. The default configuration for PPIs is to expose the
> > *same* device on all CPUs. You must use PPI affinities for your PMUs.
> > Please see the GICv3 binding for the details.
> 
> We have discussed internally, we have not seen the benefits routing
> different PPI interrupt to dedicated CPUs. Any use cases?

This isn't about changing the PPI. It is about matching CPUs with
their PMU. Here, you are saying "both PMU types are connected to all
the CPUs using PPI7".

That's obviously not the case.

> I prefer changing pmu nodes as one generic Armv8 PMU node. Is it accepted?

No, that's not acceptable.

> Or must I keep both pmu for A520 and A720, and add PPI affinities to
> describe hardware well?

This is an established practice on all big-little systems: each PMU
node has an affinity that indicates which CPUs they are connected
to. For GICv3+, this is carried by the interrupt specifier.

Please look at existing SoCs supported, such as rk3399, for example.

> 
> > 
> > > +
> > > +     pmu-spe {
> > > +             compatible = "arm,statistical-profiling-extension-v1";
> > > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW>;
> > > +     };
> > > +
> > > +     psci {
> > > +             compatible = "arm,psci-1.0";
> > > +             method = "smc";
> > > +     };
> > > +
> > > +     soc at 0 {
> > > +             compatible = "simple-bus";
> > > +             ranges = <0 0 0 0 0x20 0>;
> > > +             dma-ranges;
> > > +             #address-cells = <2>;
> > > +             #size-cells = <2>;
> > > +
> > > +             gic: interrupt-controller at e010000 {
> > > +                     compatible = "arm,gic-v3";
> > > +                     reg = <0x0 0x0e010000 0 0x10000>,       /* GICD */
> > > +                           <0x0 0x0e090000 0 0x300000>;       /* GICR * 12 */
> > > +                     interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
> > > +                     #interrupt-cells = <3>;
> > 
> > This will need to be bumped up to 4, and all the interrupt specifiers adjusted.
> 
> Depends on if PPI affinities is must.

Definitely a must, unless you want to completely remove all traces of
the PMU, which is of course silly, but a valid alternative.

[...]

> > > +             arm,no-tick-in-suspend;
> > 
> > Why do you need this? Is the HW so broken that you have implemented
> > the global counter in a power domain that isn't always on?
> > 
> 
> Not hardware broken, just arch timer will be powered off at cpu idle
> and system suspend due to power consumption reason.

This is not about the timer. This is about the global counter. If your
counter stops ticking when you're in idle or suspended, your system is
broken and you need this property. If the timer (or more precisely the
comparator) is turned off because the CPU is off, then that's the
expected behaviour and you don't need this property.


-- 
Without deviation from the norm, progress is not possible.


From alexei.starovoitov at gmail.com  Mon Mar  3 10:52:08 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Mon, 3 Mar 2025 10:52:08 -0800
Subject: [PATCH bpf-next v4 03/10] bpf/verifier: Factor out
 check_load_mem() and check_store_reg()
In-Reply-To: <8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com> <8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com>
Message-ID: <CAADnVQKyMx64_mP+u+rmnRGyzVoBs4rViTHeE4_0Rr+Kf3R5Tg@mail.gmail.com>

On Sun, Mar 2, 2025 at 9:37?PM Peilin Ye <yepeilin at google.com> wrote:
>
> Extract BPF_LDX and most non-ATOMIC BPF_STX instruction handling logic
> in do_check() into helper functions to be used later.  While we are
> here, make that comment about "reserved fields" more specific.
>
> Suggested-by: Eduard Zingerman <eddyz87 at gmail.com>
> Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
> Signed-off-by: Peilin Ye <yepeilin at google.com>

Applied the first 3 patches.


From claudiu.beznea at tuxon.dev  Mon Mar  3 10:56:47 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Mon, 3 Mar 2025 20:56:47 +0200
Subject: [PATCH v2 0/2] Add System Components for Microchip SAMA7D65 SoC
In-Reply-To: <cover.1740675317.git.Ryan.Wanner@microchip.com>
References: <cover.1740675317.git.Ryan.Wanner@microchip.com>
Message-ID: <39213e99-3041-4602-9dd2-536e9b09ad11@tuxon.dev>



On 28.02.2025 17:24, Ryan.Wanner at microchip.com wrote:
> Ryan Wanner (2):
>   ARM: dts: microchip: sama7d65: Add watchdog for sama7d65

Applied to at91-dt, thanks!


From patchwork-bot+netdevbpf at kernel.org  Mon Mar  3 11:00:30 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 03 Mar 2025 19:00:30 +0000
Subject: [PATCH bpf-next v4 00/10] Introduce load-acquire and store-release
 BPF instructions
In-Reply-To: <cover.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com>
Message-ID: <174102843076.3686766.17440507185363251083.git-patchwork-notify@kernel.org>

Hello:

This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast at kernel.org>:

On Mon,  3 Mar 2025 05:36:27 +0000 you wrote:
> Hi all!
> 
> This patchset adds kernel support for BPF load-acquire and store-release
> instructions (for background, please see [1]), including core/verifier,
> arm64/x86-64 JIT compiler and Documentation/ changes, as well as
> selftests.  riscv64 is also planned to be supported.  The corresponding
> LLVM changes can be found at:
> 
> [...]

Here is the summary with links:
  - [bpf-next,v4,01/10] bpf/verifier: Factor out atomic_ptr_type_ok()
    https://git.kernel.org/bpf/bpf-next/c/b2d9ef71d4c9
  - [bpf-next,v4,02/10] bpf/verifier: Factor out check_atomic_rmw()
    https://git.kernel.org/bpf/bpf-next/c/d430c46c7580
  - [bpf-next,v4,03/10] bpf/verifier: Factor out check_load_mem() and check_store_reg()
    https://git.kernel.org/bpf/bpf-next/c/d38ad248fb7a
  - [bpf-next,v4,04/10] bpf: Introduce load-acquire and store-release instructions
    (no matching commit)
  - [bpf-next,v4,05/10] arm64: insn: Add BIT(23) to {load,store}_ex's mask
    (no matching commit)
  - [bpf-next,v4,06/10] arm64: insn: Add load-acquire and store-release instructions
    (no matching commit)
  - [bpf-next,v4,07/10] bpf, arm64: Support load-acquire and store-release instructions
    (no matching commit)
  - [bpf-next,v4,08/10] bpf, x86: Support load-acquire and store-release instructions
    (no matching commit)
  - [bpf-next,v4,09/10] selftests/bpf: Add selftests for load-acquire and store-release instructions
    (no matching commit)
  - [bpf-next,v4,10/10] bpf, docs: Update instruction-set.rst for load-acquire and store-release instructions
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From miko.lenczewski at arm.com  Mon Mar  3 11:03:42 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Mon, 3 Mar 2025 19:03:42 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250303165255.GS5011@ziepe.ca>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com>
 <20250303165255.GS5011@ziepe.ca>
Message-ID: <20250303190330.GA426248@e133081.arm.com>

On Mon, Mar 03, 2025 at 12:52:55PM -0400, Jason Gunthorpe wrote:
> On Mon, Mar 03, 2025 at 10:31:02AM +0000, Miko?aj Lenczewski wrote:
> 
> > > > On such a system it seems like your series would break previously
> > > > working SVA support because this patch will end up disabling it?
> > 
> > Perhaps my understanding is flawed here, but I was under the impression
> > that with SVA both the core and smmu MUST support BBML2 to use it safely
> > for core translations? 
> 
> Yes
> 
> But today's kernel does not use BBML2 in the CPU or the SMMU so it is
> compatible with everything.
> 
> So it is an upgrade issue, going from today's kernel without any BBML2
> support to tomorrow's kernel that does then you loose SVA on
> previously working HW.

I see what you mean.

If you have hardware that supports cpu BBML2 but doesn't support smmu
BBML2, either by virtue of having a pre-SMMUv3.2 smmu, or by only
implementing BBML1, the simplest option I see is then to disable BBML2
globally in the kernel. A bad klude, but would at least leave current
SVA working.

> > Hopefully, as you say, the MIDR list restricts the breakage to a limited
> > (ideally, zero-size) set of implementations which advertise BBML2
> > without conflict aborts, but which do not support BBML2 on the smmu.
> > 
> > However, if my understanding of the BBML2 feature and how it interacts
> > with SVA is flawed, this will obviously be something for me to fix.
> 
> Lets hope, I was not able to discover any NVIDIA platforms that have
> an issue with this series as is.
> 
> But every addition to the MIDR list will require some consideration :\

Yes, I agree. I believe that for larger cores, this is a guarantee that
implementors will be able to make when adding themselves to the list.
They know what smmu their core uses, and that tends to be
performance-focused (hence more likely to use an smmu that support
BBML2).

For smaller cores, i.e. mobile cores, this becomes a larger issue as you
may have a higher likelyhood of pairing such a core with an
older/insufficient smmu version. So, careful consideration is required.

> > On independently enabling BBML2 on the smmu but not the CPU, this should
> > be possible.
> 
> What about the reverse? Could we disable BBML2 on the CPU side on a
> per-mm basis? Ie when an old SMMU attaches with disable the
> incompatible feature? Not something for this series, but if we get
> into trouble down the road

I agree in principle with having, as you point out, some mechanism
to disable BBML2 when an smmu without BBML2 is used. However, I think
that the complexity of such a mechanism depends on how the BBML2 feature
is used by future patches.

For example, if we use BBML2 for kernel mappings, does that require us
to repaint all kernel mappings when disabling BBML2 on smmu attach? I
am not sure, but definitely something to be worked out.

-- 
Kind regards,
Miko?aj Lenczewski


From kw at linux.com  Mon Mar  3 11:13:14 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 04:13:14 +0900
Subject: [PATCH v4 0/2] PCI: mediatek-gen3: Set PBUS_CSR regs for Airoha
 EN7581 SoC.
In-Reply-To: <20250225-en7581-pcie-pbus-csr-v4-0-24324382424a@kernel.org>
References: <20250225-en7581-pcie-pbus-csr-v4-0-24324382424a@kernel.org>
Message-ID: <20250303191314.GA1552306@rocinante>

Hello,

> Configure PBus base address and base address mask to allow the hw
> to detect if a given address is accessible on the PCIe controller.
> Introduce mediatek,pbus-csr phandle array property.

Applied to controller/mediatek, thank you!

	Krzysztof


From alexei.starovoitov at gmail.com  Mon Mar  3 11:14:47 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Mon, 3 Mar 2025 11:14:47 -0800
Subject: [PATCH bpf-next v4 10/10] bpf, docs: Update instruction-set.rst
 for load-acquire and store-release instructions
In-Reply-To: <c835515c35ec4ed59232adc3c02e1e90aa8ed8be.1740978603.git.yepeilin@google.com>
References: <cover.1740978603.git.yepeilin@google.com> <c835515c35ec4ed59232adc3c02e1e90aa8ed8be.1740978603.git.yepeilin@google.com>
Message-ID: <CAADnVQKGF-yD6UZ8Xha-wHu+7Jzn7Xa4Xu9Rju0hL2vFknqNEw@mail.gmail.com>

On Sun, Mar 2, 2025 at 9:38?PM Peilin Ye <yepeilin at google.com> wrote:
>
> Update documentation for the new load-acquire and store-release
> instructions.  Rename existing atomic operations as "atomic
> read-modify-write (RMW) operations".

rmw renaming looks like a churn. I don't think it adds clarity.

> Following RFC 9669, section 7.3. "Adding Instructions", create new
> conformance groups "atomic32v2" and "atomic64v2", where:
>
>   * atomic32v2: includes all instructions in "atomic32", plus the new
>                 8-bit, 16-bit and 32-bit atomic load-acquire and
>                 store-release instructions
>
>   * atomic64v2: includes all instructions in "atomic64" and
>                 "atomic32v2", plus the new 64-bit atomic load-acquire
>                 and store-release instructions

I think it's better for new groups to include only newly added insns.
Also we probably should add barriers to kernel/llvm and only
then update the doc with all insns together.
Otherwise we very quickly get to atomicv3 and v4 groups.
Naming wise I would call these two insns plus all barriers as
barrier32 and barrier64 groups.
cmpwait insn should probably be there as well.


From will at kernel.org  Mon Mar  3 11:18:13 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 3 Mar 2025 19:18:13 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
References: <20250226215520.1759218-1-tabba@google.com>
 <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com>
 <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
Message-ID: <20250303191811.GA30361@willie-the-truck>

On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> >
> > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > >  {
> > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > +     size_t pgd_sz, hyp_vm_sz;
> > >       struct kvm_vcpu *host_vcpu;
> > > -     pkvm_handle_t handle;
> > >       void *pgd, *hyp_vm;
> > >       unsigned long idx;
> > >       int ret;
> > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > >       if (ret < 0)
> > >               goto free_vm;
> > >
> > > -     handle = ret;
> > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> >
> > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > update the readers to be READ_ONCE()?
> 
> I don't remember the original reason, to be honest. In this case, it
> was to make it consistent with downstream code in Android. That said,
> I plan on revising all of these soon and fixing this (and related
> code) in light of Will's comment regarding potential specter gadgets:
> 
> https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/

I'm not sure the spectre stuff changes the concurrency aspects here, so
Quentin's question presumably still stands even after that.

Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
in pkvm_is_hyp_created() which is called without the config_lock held
by kvm_arch_prepare_memory_region(). However, given that
pkvm_is_hyp_created() is only testing against 0, I don't think the
_ONCE() accessors are doing anything useful in that case.

The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
directly without the 'config_lock' held. The MMU notifiers look like
they can do that, so I wonder if there's a theoretical race where they
can race with first run and issue TLB invalidation with the wrong handle?
That would apply equally to the upstream code, I think.

Will


From tabba at google.com  Mon Mar  3 11:21:33 2025
From: tabba at google.com (Fuad Tabba)
Date: Mon, 3 Mar 2025 19:21:33 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <20250303191811.GA30361@willie-the-truck>
References: <20250226215520.1759218-1-tabba@google.com> <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com> <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck>
Message-ID: <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>

Hi Will,

On Mon, 3 Mar 2025 at 19:18, Will Deacon <will at kernel.org> wrote:
>
> On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> > On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> > >
> > > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > >  {
> > > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > > +     size_t pgd_sz, hyp_vm_sz;
> > > >       struct kvm_vcpu *host_vcpu;
> > > > -     pkvm_handle_t handle;
> > > >       void *pgd, *hyp_vm;
> > > >       unsigned long idx;
> > > >       int ret;
> > > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > >       if (ret < 0)
> > > >               goto free_vm;
> > > >
> > > > -     handle = ret;
> > > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> > >
> > > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > > update the readers to be READ_ONCE()?
> >
> > I don't remember the original reason, to be honest. In this case, it
> > was to make it consistent with downstream code in Android. That said,
> > I plan on revising all of these soon and fixing this (and related
> > code) in light of Will's comment regarding potential specter gadgets:
> >
> > https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/
>
> I'm not sure the spectre stuff changes the concurrency aspects here, so
> Quentin's question presumably still stands even after that.
>
> Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
> in pkvm_is_hyp_created() which is called without the config_lock held
> by kvm_arch_prepare_memory_region(). However, given that
> pkvm_is_hyp_created() is only testing against 0, I don't think the
> _ONCE() accessors are doing anything useful in that case.
>
> The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
> directly without the 'config_lock' held. The MMU notifiers look like
> they can do that, so I wonder if there's a theoretical race where they
> can race with first run and issue TLB invalidation with the wrong handle?
> That would apply equally to the upstream code, I think.

Would using _ONCE accessors with the MMU notifiers be enough to avoid
the race, or do we need to reconsider the lock protecting the handle
and apply it to the notifiers?

Cheers,
/fuad

> Will


From oliver.upton at linux.dev  Mon Mar  3 11:26:08 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Mon, 3 Mar 2025 11:26:08 -0800
Subject: [PATCH] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250302-pmc-v1-1-caff989093dc@daynix.com>
References: <20250302-pmc-v1-1-caff989093dc@daynix.com>
Message-ID: <Z8YCUFkt8gdnWRSk@linux.dev>

Hi Akihiko,

On Sun, Mar 02, 2025 at 05:12:54PM +0900, Akihiko Odaki wrote:
> Reset the current perf event when setting the vPMU counter (vPMC)
> registers (PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change
> corresponding to commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
> for vPMC regs to return the current value") but for SET_ONE_REG.
> 
> Values of vPMC registers are saved in sysreg files on certain occasions.
> These saved values don't represent the current values of the vPMC
> registers if the perf events for the vPMCs count events after the save.
> The current values of those registers are the sum of the sysreg file
> value and the current perf event counter value.  But, when userspace
> writes those registers (using KVM_SET_ONE_REG), KVM only updates the
> sysreg file value and leaves the current perf event counter value as is.

Are you trying to change the PMCs after the VM has started?

> Fix this by calling kvm_pmu_set_counter_value(), which resests the
> current perf event as well.

I'm afraid this could introduce some oddities for save/restore of a VM.
The PMU configuration (e.g. type, event filter, nr event counters) is
subject to change before KVM_RUN.

For example, if the VM programmed an event that was filtered on the
source, KVM could erroneously allocate a perf event on the target if the
filter is restored after the vCPU sysregs.

A similar issue could happen with the PMU type not matching the final
selection as well. Attaching the perf event in KVM_REQ_RELOAD_PMU avoids
these sort of issues.

> Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
>  arch/arm64/kvm/sys_regs.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 42791971f75887796afab905cc12f49fead39e10..1de990edc6a3e9be2a05a711621bb1bcbeac236a 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
>  	return 0;
>  }
>  
> +static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> +			  u64 val)
> +{
> +	u64 idx;
> +
> +	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
> +		/* PMCCNTR_EL0 */
> +		idx = ARMV8_PMU_CYCLE_IDX;
> +	else
> +		/* PMEVCNTRn_EL0 */
> +		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);

nitpick: Let's get rid of the manual decode for both the getter and
setter. r->reg already provides the right info, we just need to
transform that into a counter index.

> +	kvm_pmu_set_counter_value(vcpu, idx, val);
> +	return 0;

WDYT about only calling kvm_pmu_set_counter_value() if the vCPU has
already run once, otherwise update the in-memory value of the register?
I think that would fix your issue while also guaranteeing that the perf
event matches the final configuration of the vPMU.

Thanks,
Oliver


From maz at kernel.org  Mon Mar  3 11:39:40 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 03 Mar 2025 19:39:40 +0000
Subject: writable ID_AA64MMFR0_EL1.TGRAN*_2 ?
In-Reply-To: <597411b1-ff60-edc3-d6f2-1b21ce2e34e9@redhat.com>
References: <597411b1-ff60-edc3-d6f2-1b21ce2e34e9@redhat.com>
Message-ID: <86h649q4xv.wl-maz@kernel.org>

On Fri, 28 Feb 2025 15:19:06 +0000,
Sebastian Ott <sebott at redhat.com> wrote:
> 
> Hi,
> 
> I'm looking into the possibility of migrating between 2 (Graviton) hosts
> and the only ID register diffs that are not yet writable are TGRAN*_2.
> Both hosts support the same sizes for S2 but express that differently
> (2==supported vs 0=="look at TGRAN*").
> 
> One idea would be to either set the guest view for these to NI (for the
> "normal" / not nested guest) or allow to convert between the 2 values
> (and maybe also allow to write NI for good measure).

I think we can allow any value to be written to any of the TGRAN*_2 in
a non-NV context. For NV, we must be fairly strict, by enforcing that
NI is the floor limit for the feature (we cannot let 0 be written for
any of them).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From kw at linux.com  Mon Mar  3 11:42:28 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 04:42:28 +0900
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <Z8XuuNb6TRevUlHH@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
 <20250221131548.59616-6-shradha.t@samsung.com>
 <Z8XuuNb6TRevUlHH@debian>
Message-ID: <20250303194228.GB1552306@rocinante>

Hello,

[...]
> > +static ssize_t counter_value_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
> > +{
> > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > +	struct dw_pcie *pci = pdata->pci;
> > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > +	ssize_t pos;
> > +	u32 val;
> > +
> > +	mutex_lock(&rinfo->reg_event_lock);
> > +	set_event_number(pdata, pci, rinfo);
> > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > +	mutex_unlock(&rinfo->reg_event_lock);
> > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter value: %d\n", val);
> > +
> > +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf, pos);
> > +}
> 
> Do we need to check whether the counter is enabled or not for the event
> before retrieving the counter value?

I believe, we have a patch that aims to address, have a look at:

  https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivannan.sadhasivam at linaro.org

Thank you!

	Krzysztof


From kw at linux.com  Mon Mar  3 11:46:47 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 04:46:47 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <Z8XrYxP_pZr6tFU8@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
Message-ID: <20250303194647.GC1552306@rocinante>

Hello,

[...]
> > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > +{
> > +	char dirname[DWC_DEBUGFS_BUF_MAX];
> > +	struct device *dev = pci->dev;
> > +	struct debugfs_info *debugfs;
> > +	struct dentry *dir;
> > +	int ret;
> > +
> > +	/* Create main directory for each platform driver */
> > +	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > +	dir = debugfs_create_dir(dirname, NULL);
> > +	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > +	if (!debugfs)
> > +		return -ENOMEM;
> > +
> > +	debugfs->debug_dir = dir;
> > +	pci->debugfs = debugfs;
> > +	ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > +	if (ret)
> > +		dev_dbg(dev, "RASDES debugfs init failed\n");
> 
> What will happen if ret != 0? still return 0? 

Given that callers of dwc_pcie_debugfs_init() check for errors,
this probably should correctly bubble up any failure coming from
dwc_pcie_rasdes_debugfs_init().

I made updates to the code directly on the current branch, have a look:

  https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=1ff54f4cbaed9ec6994844967c36cf7ada4cbe5e

Let me know if this is OK with you.

Good catch, thank you!

	Krzysztof


From kw at linux.com  Mon Mar  3 11:51:49 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 04:51:49 +0900
Subject: [PATCH v7 0/5] Add support for debugfs based RAS DES feature in
 PCIe DW
In-Reply-To: <20250225143001.GA1556729@rocinante>
References: <CGME20250221132011epcas5p4dea1e9ae5c09afaabcd1822f3a7d15c5@epcas5p4.samsung.com>
 <20250221131548.59616-1-shradha.t@samsung.com>
 <20250225143001.GA1556729@rocinante>
Message-ID: <20250303195149.GA1814481@rocinante>

Hello,

[...]
> Applied to controller/dwc, thank you!

Updated the current branch with a few missing "Reviewed-by" tags from Fan Ni.

Thank you!

	Krzysztof


From yang at os.amperecomputing.com  Mon Mar  3 11:55:28 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Mon, 3 Mar 2025 11:55:28 -0800
Subject: [PATCH v2 1/4] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250303094022.GA13345@e133081.arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-3-miko.lenczewski@arm.com>
 <c572a93f-0899-4fc7-9764-d3e76e9fe6d1@os.amperecomputing.com>
 <223a817b-66dd-4182-838f-a186b059fe41@os.amperecomputing.com>
 <20250303094022.GA13345@e133081.arm.com>
Message-ID: <a382e902-6887-4880-a312-cf52defccaf5@os.amperecomputing.com>



On 3/3/25 1:40 AM, Miko?aj Lenczewski wrote:
> On Fri, Feb 28, 2025 at 06:45:38PM -0800, Yang Shi wrote:
>>
>>
>> On 2/28/25 5:29 PM, Yang Shi wrote:
>>>
>>>
>>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>>> index 940343beb3d4..baae6d458996 100644
>>>> --- a/arch/arm64/Kconfig
>>>> +++ b/arch/arm64/Kconfig
>>>> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>>>>  ??????? The feature introduces new assembly instructions, and they were
>>>>  ??????? support when binutils >= 2.30.
>>>>  ? +config ARM64_ENABLE_BBML2_NOABORT
>>>> +??? bool "Enable support for Break-Before-Make Level 2 detection
>>>> and usage"
>>>> +??? default y
>>>> +??? help
>>>> +????? FEAT_BBM provides detection of support levels for
>>>> break-before-make
>>>> +????? sequences. If BBM level 2 is supported, some TLB maintenance
>>>> requirements
>>>> +????? can be relaxed to improve performance. We additonally require the
>>>> +????? property that the implementation cannot ever raise TLB
>>>> Conflict Aborts.
>>>> +????? Selecting N causes the kernel to fallback to BBM level 0
>>>> behaviour
>>>> +????? even if the system supports BBM level 2.
>>>> +
>>>>  ? endmenu # "ARMv8.4 architectural features"
>>>>  ? ? menu "ARMv8.5 architectural features"
>>>> diff --git a/arch/arm64/include/asm/cpucaps.h
>>>> b/arch/arm64/include/asm/cpucaps.h
>>>> index 0b5ca6e0eb09..2d6db33d4e45 100644
>>>> --- a/arch/arm64/include/asm/cpucaps.h
>>>> +++ b/arch/arm64/include/asm/cpucaps.h
>>>> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>>>>  ????????? return IS_ENABLED(CONFIG_ARM64_PAN);
>>>>  ????? case ARM64_HAS_EPAN:
>>>>  ????????? return IS_ENABLED(CONFIG_ARM64_EPAN);
>>>> +??? case ARM64_HAS_BBML2_NOABORT:
>>>> +??????? return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>>>>  ????? case ARM64_SVE:
>>>>  ????????? return IS_ENABLED(CONFIG_ARM64_SVE);
>>>>  ????? case ARM64_SME:
>>>> diff --git a/arch/arm64/include/asm/cpufeature.h
>>>> b/arch/arm64/include/asm/cpufeature.h
>>>> index e0e4478f5fb5..108ef3fbbc00 100644
>>>> --- a/arch/arm64/include/asm/cpufeature.h
>>>> +++ b/arch/arm64/include/asm/cpufeature.h
>>>> @@ -866,6 +866,11 @@ static __always_inline bool
>>>> system_supports_mpam_hcr(void)
>>>>  ????? return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>>>>  ? }
>>>>  ? +static inline bool system_supports_bbml2_noabort(void)
>>>> +{
>>>> +??? return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
>>>> +}
>>> Hi Miko,
>>>
>>> I added AmpereOne mdir on top of this patch. I can see BBML2 feature is
>>> detected via dmesg. But system_supports_bbml2_noabort() returns false.
>>> The warning in the below debug patch is triggered:
>>>
>>> diff --git a/arch/arm64/kernel/cpufeature.c
>>> b/arch/arm64/kernel/cpufeature.c
>>> index faa9094d97dd..a70829ae2bd0 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -3814,6 +3814,9 @@ void __init setup_system_features(void)
>>>  ?{
>>>  ??????? setup_system_capabilities();
>>>
>>> +?????? if (!system_supports_bbml2_noabort())
>>> +?????????????? WARN_ON_ONCE(1);
>>> +
>>>  ??????? kpti_install_ng_mappings();
>>>
>>>  ??????? sve_setup();
>>>
>>> I thought it may be too early. But it seems other system features work
>>> well, for example, MPAM. I didn't figure out why. It is weird.
>> I just figured out the problem It is because the wrong kconfig name is used
>> in cpucaps.h. The code is:
>>
>> +??? case ARM64_HAS_BBML2_NOABORT:
>> +??????? return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>>
>> But the kconfig name actually is:
>>
>> +config ARM64_ENABLE_BBML2_NOABORT
>>
>> IMHO, the "ENABLE" in kconfig name sounds unnecessary.
>>
>> Thanks,
>> Yang
>>
>>
> Hi Yang,
>
> Thank you for the review, and apologies for the slight delay.
>
> Thanks again for the spot, I agree that `ENABLE` is probably redundant
> (and clearly, caused an issue here). Will remove this. Please let me
> know if there are any other issues with rebasing your patches on top of
> mine.

Thank you. I didn't spot any other problem on our machines. With this 
addressed, you can have Tested-by: Yang Shi <yang at amperecomputing.com>, 
although I can't test on asymmetric system.

Yang


>



From yang at os.amperecomputing.com  Mon Mar  3 11:56:33 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Mon, 3 Mar 2025 11:56:33 -0800
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
Message-ID: <2f46a07a-20c3-4a7a-8174-99631cfbeade@os.amperecomputing.com>



On 3/3/25 2:17 AM, Ryan Roberts wrote:
> On 01/03/2025 01:32, Yang Shi wrote:
>>
>>
>> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>>> BBM level 2 is claimed.
>>>
>>> Add the feature and testing for it under arm_smmu_sva_supported().
>>>
>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>> ---
>>>  ? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>>>  ? 4 files changed, 13 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index 63f6d356dc77..1022c63f81b2 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>>> arm64_cpu_capabilities *caps, int sco
>>>  ????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>>>  ????????????????? return false;
>>>  ????????? }
>>> -
>>> -??????? return true;
>>>  ????? } else if (scope & SCOPE_LOCAL_CPU) {
>>>  ????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>>>  ?????????? * If we have the correct MIDR, but the kernel booted on an
>>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>>> arm64_cpu_capabilities *caps, int sco
>>>  ?????????? * we have an incorrect MIDR, but the kernel booted on a
>>>  ?????????? * sufficient CPU, we will not bring up this CPU.
>>>  ?????????? */
>>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>>> +??????????? return false;
>>>  ????? }
>>>  ? -??? return false;
>>> +??? return has_cpuid_feature(caps, scope);
>> Do we really need this? IIRC, it means the MIDR has to be in the allow list
>> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register set.
> Miko, I think this should have been squashed into patch #1? It doesn't belong in
> this patch.
>
> Yang, we discussed this internally and decided that we thought it was best to
> still require BBML2 being advertised in the feature register. That way if trying
> to use KVM to emulate a CPU that is in the allow list but doesn't really support
> BBML2, we won't try to use it.
>
> But we still end up with the same problem if running on a physical CPU that
> supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So
> given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
> remove this check.

Thank you.

Yang

>
> Thanks,
> Ryan
>
>
>> Thanks,
>> Yang
>>
>>>  ? }
>>>  ? ? #ifdef CONFIG_ARM64_PAN
>>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> index 9ba596430e7c..6ba182572788 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>>>  ????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>>>  ????? }
>>>  ? +??? if (system_supports_bbml2_noabort())
>>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>>> +
>>>  ????? if ((smmu->features & feat_mask) != feat_mask)
>>>  ????????? return false;
>>>  ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3.c
>>> index 358072b4e293..dcee0bdec924 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>>> arm_smmu_device *smmu)
>>>  ????? if (FIELD_GET(IDR3_RIL, reg))
>>>  ????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>>>  ? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>>> +
>>>  ????? /* IDR5 */
>>>  ????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>>>  ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3.h
>>> index bd9d7c85576a..85eaf3ab88c2 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>>>  ? #define ARM_SMMU_IDR3??????????? 0xc
>>>  ? #define IDR3_FWB??????????? (1 << 8)
>>>  ? #define IDR3_RIL??????????? (1 << 10)
>>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>>> +#define IDR3_BBML1??????????? (1 << 11)
>>> +#define IDR3_BBML2??????????? (2 << 11)
>>>  ? ? #define ARM_SMMU_IDR5??????????? 0x14
>>>  ? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>>>  ? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>>>  ? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>>>  ? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>>>  ????? u32??????????????? features;
>>>  ? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)



From kw at linux.com  Mon Mar  3 12:00:55 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 05:00:55 +0900
Subject: [PATCH v7 0/5] Add support for debugfs based RAS DES feature in
 PCIe DW
In-Reply-To: <20250228114301.31739-1-hrishikesh.d@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250228114813epcas5p32127b99d3a0adf6900a104468b48768d@epcas5p3.samsung.com>
 <20250228114301.31739-1-hrishikesh.d@samsung.com>
Message-ID: <20250303200055.GA1881771@rocinante>

Hello,

> Thanks for adding the support!
> 
> Tested the patch in one of our internal SoC with DesginWare PCIe controller. The patch works fine.

I assume this was for an entire series, not any specific patch.

> Tested-by: Hrishikesh Deleep <hrishikesh.d at samsung.com>

Thank you for testing!  I will add your tag to the current branch.

	Krzysztof


From sven at svenpeter.dev  Mon Mar  3 12:03:58 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Mon,  3 Mar 2025 21:03:58 +0100
Subject: (subset) [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
Message-ID: <174103187680.75921.8965235926191911132.b4-ty@svenpeter.dev>


On Mon, 17 Feb 2025 12:39:30 +0100, Sasha Finkelstein wrote:
> This patch series adds support for a secondary display controller
> present on Apple M1/M2 chips and used to drive the display of the
> "touchbar" touch panel present on those.
> 
> 

Since the dt-bindings are now part of drm-misc-next I've also applied
the dts change, thanks!

[4/5] arm64: dts: apple: Add touchbar screen nodes
      commit: 7275e795e520c7064af52ba67c74d7bac27eea4f

Best regards,
-- 
Sven Peter <sven at svenpeter.dev>


From hkallweit1 at gmail.com  Mon Mar  3 12:15:09 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:15:09 +0100
Subject: [PATCH net-next v3 2/8] net: phy: add getters for public members in
 struct phy_package_shared
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <c6da0b27-4479-4717-9e16-643821b76bd8@gmail.com>

Add getters for public members, this prepares for making struct
phy_package_shared private to phylib. Declare the getters in a new header
file phylib.h, which will be used by PHY drivers only.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
v2:
- rename getters
---
 drivers/net/phy/phy_package.c | 14 ++++++++++++++
 drivers/net/phy/phylib.h      | 15 +++++++++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 drivers/net/phy/phylib.h

diff --git a/drivers/net/phy/phy_package.c b/drivers/net/phy/phy_package.c
index 260469f02..873420e58 100644
--- a/drivers/net/phy/phy_package.c
+++ b/drivers/net/phy/phy_package.c
@@ -6,6 +6,20 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 
+#include "phylib.h"
+
+struct device_node *phy_package_get_node(struct phy_device *phydev)
+{
+	return phydev->shared->np;
+}
+EXPORT_SYMBOL_GPL(phy_package_get_node);
+
+void *phy_package_get_priv(struct phy_device *phydev)
+{
+	return phydev->shared->priv;
+}
+EXPORT_SYMBOL_GPL(phy_package_get_priv);
+
 /**
  * phy_package_join - join a common PHY group
  * @phydev: target phy_device struct
diff --git a/drivers/net/phy/phylib.h b/drivers/net/phy/phylib.h
new file mode 100644
index 000000000..a42e1fc07
--- /dev/null
+++ b/drivers/net/phy/phylib.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * phylib header
+ */
+
+#ifndef __PHYLIB_H
+#define __PHYLIB_H
+
+struct device_node;
+struct phy_device;
+
+struct device_node *phy_package_get_node(struct phy_device *phydev);
+void *phy_package_get_priv(struct phy_device *phydev);
+
+#endif /* __PHYLIB_H */
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:16:00 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:16:00 +0100
Subject: [PATCH net-next v3 3/8] net: phy: qca807x: use new phy_package_shared
 getters
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <b6402789-45d2-49d6-835f-ed584bce5b2f@gmail.com>

Use the new getters for members of struct phy_package_shared.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/qcom/qca807x.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/net/phy/qcom/qca807x.c b/drivers/net/phy/qcom/qca807x.c
index 2ad8c2586..1af6b5ead 100644
--- a/drivers/net/phy/qcom/qca807x.c
+++ b/drivers/net/phy/qcom/qca807x.c
@@ -15,6 +15,7 @@
 #include <linux/gpio/driver.h>
 #include <linux/sfp.h>
 
+#include "../phylib.h"
 #include "qcom.h"
 
 #define QCA807X_CHIP_CONFIGURATION				0x1f
@@ -486,13 +487,13 @@ static int qca807x_read_status(struct phy_device *phydev)
 
 static int qca807x_phy_package_probe_once(struct phy_device *phydev)
 {
-	struct phy_package_shared *shared = phydev->shared;
-	struct qca807x_shared_priv *priv = shared->priv;
+	struct qca807x_shared_priv *priv = phy_package_get_priv(phydev);
+	struct device_node *np = phy_package_get_node(phydev);
 	unsigned int tx_drive_strength;
 	const char *package_mode_name;
 
 	/* Default to 600mw if not defined */
-	if (of_property_read_u32(shared->np, "qcom,tx-drive-strength-milliwatt",
+	if (of_property_read_u32(np, "qcom,tx-drive-strength-milliwatt",
 				 &tx_drive_strength))
 		tx_drive_strength = 600;
 
@@ -541,7 +542,7 @@ static int qca807x_phy_package_probe_once(struct phy_device *phydev)
 	}
 
 	priv->package_mode = PHY_INTERFACE_MODE_NA;
-	if (!of_property_read_string(shared->np, "qcom,package-mode",
+	if (!of_property_read_string(np, "qcom,package-mode",
 				     &package_mode_name)) {
 		if (!strcasecmp(package_mode_name,
 				phy_modes(PHY_INTERFACE_MODE_PSGMII)))
@@ -558,8 +559,7 @@ static int qca807x_phy_package_probe_once(struct phy_device *phydev)
 
 static int qca807x_phy_package_config_init_once(struct phy_device *phydev)
 {
-	struct phy_package_shared *shared = phydev->shared;
-	struct qca807x_shared_priv *priv = shared->priv;
+	struct qca807x_shared_priv *priv = phy_package_get_priv(phydev);
 	int val, ret;
 
 	/* Make sure PHY follow PHY package mode if enforced */
@@ -708,7 +708,6 @@ static int qca807x_probe(struct phy_device *phydev)
 	struct device_node *node = phydev->mdio.dev.of_node;
 	struct qca807x_shared_priv *shared_priv;
 	struct device *dev = &phydev->mdio.dev;
-	struct phy_package_shared *shared;
 	struct qca807x_priv *priv;
 	int ret;
 
@@ -722,8 +721,7 @@ static int qca807x_probe(struct phy_device *phydev)
 			return ret;
 	}
 
-	shared = phydev->shared;
-	shared_priv = shared->priv;
+	shared_priv = phy_package_get_priv(phydev);
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:16:43 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:16:43 +0100
Subject: [PATCH net-next v3 4/8] net: phy: micrel: use new phy_package_shared
 getters
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <18e5d29e-fb96-4771-92e4-689e0c992177@gmail.com>

Use the new getters for members of struct phy_package_shared.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/micrel.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 9c0b1c229..289e1d56a 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -34,6 +34,8 @@
 #include <linux/net_tstamp.h>
 #include <linux/gpio/consumer.h>
 
+#include "phylib.h"
+
 /* Operation Mode Strap Override */
 #define MII_KSZPHY_OMSO				0x16
 #define KSZPHY_OMSO_FACTORY_TEST		BIT(15)
@@ -2631,8 +2633,7 @@ static void lan8814_ptp_tx_ts_get(struct phy_device *phydev,
 static int lan8814_ts_info(struct mii_timestamper *mii_ts, struct kernel_ethtool_ts_info *info)
 {
 	struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts);
-	struct phy_device *phydev = ptp_priv->phydev;
-	struct lan8814_shared_priv *shared = phydev->shared->priv;
+	struct lan8814_shared_priv *shared = phy_package_get_priv(ptp_priv->phydev);
 
 	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
 				SOF_TIMESTAMPING_RX_HARDWARE |
@@ -3653,7 +3654,7 @@ static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared)
 
 static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status)
 {
-	struct lan8814_shared_priv *shared = phydev->shared->priv;
+	struct lan8814_shared_priv *shared = phy_package_get_priv(phydev);
 	int ret;
 
 	mutex_lock(&shared->shared_lock);
@@ -3864,7 +3865,7 @@ static void lan8814_ptp_init(struct phy_device *phydev)
 
 static int lan8814_ptp_probe_once(struct phy_device *phydev)
 {
-	struct lan8814_shared_priv *shared = phydev->shared->priv;
+	struct lan8814_shared_priv *shared = phy_package_get_priv(phydev);
 
 	/* Initialise shared lock for clock*/
 	mutex_init(&shared->shared_lock);
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:17:18 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:17:18 +0100
Subject: [PATCH net-next v3 5/8] net: phy: mediatek: use new
 phy_package_shared getters
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <356a257f-68d0-47bc-a474-4dafaeaa149f@gmail.com>

Use the new getters for members of struct phy_package_shared.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/mediatek/mtk-ge-soc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/mediatek/mtk-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c
index 9de6fbb45..175cf5239 100644
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -8,6 +8,7 @@
 #include <linux/phy.h>
 #include <linux/regmap.h>
 
+#include "../phylib.h"
 #include "mtk.h"
 
 #define MTK_GPHY_ID_MT7981			0x03a29461
@@ -1278,7 +1279,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
 
 static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
 {
-	struct mtk_socphy_shared *priv = phydev->shared->priv;
+	struct mtk_socphy_shared *priv = phy_package_get_priv(phydev);
 	u32 polarities;
 
 	if (led_num == 0)
@@ -1317,7 +1318,7 @@ static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev)
 static int mt7988_phy_probe_shared(struct phy_device *phydev)
 {
 	struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
-	struct mtk_socphy_shared *shared = phydev->shared->priv;
+	struct mtk_socphy_shared *shared = phy_package_get_priv(phydev);
 	struct regmap *regmap;
 	u32 reg;
 	int ret;
@@ -1368,7 +1369,7 @@ static int mt7988_phy_probe(struct phy_device *phydev)
 			return err;
 	}
 
-	shared = phydev->shared->priv;
+	shared = phy_package_get_priv(phydev);
 	priv = &shared->priv[phydev->mdio.addr];
 
 	phydev->priv = priv;
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:17:54 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:17:54 +0100
Subject: [PATCH net-next v3 6/8] net: phy: mscc: use new phy_package_shared
 getters
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <61ee43ec-be20-4be1-bfad-d18d2a4fae2b@gmail.com>

Use the new getters for members of struct phy_package_shared.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/mscc/mscc_ptp.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c
index 738a8822f..ed8fb14a7 100644
--- a/drivers/net/phy/mscc/mscc_ptp.c
+++ b/drivers/net/phy/mscc/mscc_ptp.c
@@ -17,6 +17,7 @@
 #include <linux/udp.h>
 #include <linux/unaligned.h>
 
+#include "../phylib.h"
 #include "mscc.h"
 #include "mscc_ptp.h"
 
@@ -645,11 +646,12 @@ static int __vsc85xx_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
 {
 	struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps);
 	struct phy_device *phydev = ptp->phydev;
-	struct vsc85xx_shared_private *shared =
-		(struct vsc85xx_shared_private *)phydev->shared->priv;
 	struct vsc8531_private *priv = phydev->priv;
+	struct vsc85xx_shared_private *shared;
 	u32 val;
 
+	shared = phy_package_get_priv(phydev);
+
 	val = vsc85xx_ts_read_csr(phydev, PROCESSOR, MSCC_PHY_PTP_LTC_CTRL);
 	val |= PTP_LTC_CTRL_SAVE_ENA;
 	vsc85xx_ts_write_csr(phydev, PROCESSOR, MSCC_PHY_PTP_LTC_CTRL, val);
@@ -696,11 +698,12 @@ static int __vsc85xx_settime(struct ptp_clock_info *info,
 {
 	struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps);
 	struct phy_device *phydev = ptp->phydev;
-	struct vsc85xx_shared_private *shared =
-		(struct vsc85xx_shared_private *)phydev->shared->priv;
 	struct vsc8531_private *priv = phydev->priv;
+	struct vsc85xx_shared_private *shared;
 	u32 val;
 
+	shared = phy_package_get_priv(phydev);
+
 	vsc85xx_ts_write_csr(phydev, PROCESSOR, MSCC_PHY_PTP_LTC_LOAD_SEC_MSB,
 			     PTP_LTC_LOAD_SEC_MSB(ts->tv_sec));
 	vsc85xx_ts_write_csr(phydev, PROCESSOR, MSCC_PHY_PTP_LTC_LOAD_SEC_LSB,
@@ -1580,8 +1583,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
 
 int vsc8584_ptp_probe_once(struct phy_device *phydev)
 {
-	struct vsc85xx_shared_private *shared =
-		(struct vsc85xx_shared_private *)phydev->shared->priv;
+	struct vsc85xx_shared_private *shared = phy_package_get_priv(phydev);
 
 	/* Initialize shared GPIO lock */
 	mutex_init(&shared->gpio_lock);
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:18:46 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:18:46 +0100
Subject: [PATCH net-next v3 7/8] net: phy: move PHY package related code from
 phy.h to phy_package.c
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <a4518379-7a5d-45f3-831c-b7fde6512c65@gmail.com>

Move PHY package related inline functions from phy.h to phy_package.c.
While doing so remove locked versions phy_package_read() and
phy_package_write() which have no user.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/bcm54140.c        |  1 +
 drivers/net/phy/mscc/mscc_main.c  |  2 +
 drivers/net/phy/phy-core.c        |  1 +
 drivers/net/phy/phy_package.c     | 61 ++++++++++++++++++++++
 drivers/net/phy/phylib-internal.h |  2 +
 drivers/net/phy/phylib.h          |  6 +++
 include/linux/phy.h               | 86 -------------------------------
 7 files changed, 73 insertions(+), 86 deletions(-)

diff --git a/drivers/net/phy/bcm54140.c b/drivers/net/phy/bcm54140.c
index 7969345f6..a8edf45fd 100644
--- a/drivers/net/phy/bcm54140.c
+++ b/drivers/net/phy/bcm54140.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 
+#include "phylib.h"
 #include "bcm-phy-lib.h"
 
 /* RDB per-port registers
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 19cf12ee8..7ff975efd 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -17,6 +17,8 @@
 #include <linux/of.h>
 #include <linux/netdevice.h>
 #include <dt-bindings/net/mscc-phy-vsc8531.h>
+
+#include "../phylib.h"
 #include "mscc_serdes.h"
 #include "mscc.h"
 
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index b1c1670de..154d29be6 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -6,6 +6,7 @@
 #include <linux/phy.h>
 #include <linux/of.h>
 
+#include "phylib.h"
 #include "phylib-internal.h"
 
 /**
diff --git a/drivers/net/phy/phy_package.c b/drivers/net/phy/phy_package.c
index 873420e58..12c92d26e 100644
--- a/drivers/net/phy/phy_package.c
+++ b/drivers/net/phy/phy_package.c
@@ -7,6 +7,7 @@
 #include <linux/phy.h>
 
 #include "phylib.h"
+#include "phylib-internal.h"
 
 struct device_node *phy_package_get_node(struct phy_device *phydev)
 {
@@ -20,6 +21,66 @@ void *phy_package_get_priv(struct phy_device *phydev)
 }
 EXPORT_SYMBOL_GPL(phy_package_get_priv);
 
+int phy_package_address(struct phy_device *phydev, unsigned int addr_offset)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	u8 base_addr = shared->base_addr;
+
+	if (addr_offset >= PHY_MAX_ADDR - base_addr)
+		return -EIO;
+
+	/* we know that addr will be in the range 0..31 and thus the
+	 * implicit cast to a signed int is not a problem.
+	 */
+	return base_addr + addr_offset;
+}
+
+int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset,
+		       u32 regnum)
+{
+	int addr = phy_package_address(phydev, addr_offset);
+
+	if (addr < 0)
+		return addr;
+
+	return __mdiobus_read(phydev->mdio.bus, addr, regnum);
+}
+EXPORT_SYMBOL_GPL(__phy_package_read);
+
+int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset,
+			u32 regnum, u16 val)
+{
+	int addr = phy_package_address(phydev, addr_offset);
+
+	if (addr < 0)
+		return addr;
+
+	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
+}
+EXPORT_SYMBOL_GPL(__phy_package_write);
+
+static bool __phy_package_set_once(struct phy_device *phydev, unsigned int b)
+{
+	struct phy_package_shared *shared = phydev->shared;
+
+	if (!shared)
+		return false;
+
+	return !test_and_set_bit(b, &shared->flags);
+}
+
+bool phy_package_init_once(struct phy_device *phydev)
+{
+	return __phy_package_set_once(phydev, 0);
+}
+EXPORT_SYMBOL_GPL(phy_package_init_once);
+
+bool phy_package_probe_once(struct phy_device *phydev)
+{
+	return __phy_package_set_once(phydev, 1);
+}
+EXPORT_SYMBOL_GPL(phy_package_probe_once);
+
 /**
  * phy_package_join - join a common PHY group
  * @phydev: target phy_device struct
diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h
index dc9592c6b..afac2bd15 100644
--- a/drivers/net/phy/phylib-internal.h
+++ b/drivers/net/phy/phylib-internal.h
@@ -20,6 +20,8 @@ void of_set_phy_timing_role(struct phy_device *phydev);
 int phy_speed_down_core(struct phy_device *phydev);
 void phy_check_downshift(struct phy_device *phydev);
 
+int phy_package_address(struct phy_device *phydev, unsigned int addr_offset);
+
 int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv);
 
 #endif /* __PHYLIB_INTERNAL_H */
diff --git a/drivers/net/phy/phylib.h b/drivers/net/phy/phylib.h
index a42e1fc07..06c50d275 100644
--- a/drivers/net/phy/phylib.h
+++ b/drivers/net/phy/phylib.h
@@ -11,5 +11,11 @@ struct phy_device;
 
 struct device_node *phy_package_get_node(struct phy_device *phydev);
 void *phy_package_get_priv(struct phy_device *phydev);
+int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset,
+		       u32 regnum);
+int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset,
+			u32 regnum, u16 val);
+bool phy_package_init_once(struct phy_device *phydev);
+bool phy_package_probe_once(struct phy_device *phydev);
 
 #endif /* __PHYLIB_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7bfbae510..2b12d1bef 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -350,10 +350,6 @@ struct phy_package_shared {
 	void *priv;
 };
 
-/* used as bit number in atomic bitops */
-#define PHY_SHARED_F_INIT_DONE  0
-#define PHY_SHARED_F_PROBE_DONE 1
-
 /**
  * struct mii_bus - Represents an MDIO bus
  *
@@ -2149,67 +2145,6 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
 		       struct kernel_hwtstamp_config *config,
 		       struct netlink_ext_ack *extack);
 
-static inline int phy_package_address(struct phy_device *phydev,
-				      unsigned int addr_offset)
-{
-	struct phy_package_shared *shared = phydev->shared;
-	u8 base_addr = shared->base_addr;
-
-	if (addr_offset >= PHY_MAX_ADDR - base_addr)
-		return -EIO;
-
-	/* we know that addr will be in the range 0..31 and thus the
-	 * implicit cast to a signed int is not a problem.
-	 */
-	return base_addr + addr_offset;
-}
-
-static inline int phy_package_read(struct phy_device *phydev,
-				   unsigned int addr_offset, u32 regnum)
-{
-	int addr = phy_package_address(phydev, addr_offset);
-
-	if (addr < 0)
-		return addr;
-
-	return mdiobus_read(phydev->mdio.bus, addr, regnum);
-}
-
-static inline int __phy_package_read(struct phy_device *phydev,
-				     unsigned int addr_offset, u32 regnum)
-{
-	int addr = phy_package_address(phydev, addr_offset);
-
-	if (addr < 0)
-		return addr;
-
-	return __mdiobus_read(phydev->mdio.bus, addr, regnum);
-}
-
-static inline int phy_package_write(struct phy_device *phydev,
-				    unsigned int addr_offset, u32 regnum,
-				    u16 val)
-{
-	int addr = phy_package_address(phydev, addr_offset);
-
-	if (addr < 0)
-		return addr;
-
-	return mdiobus_write(phydev->mdio.bus, addr, regnum, val);
-}
-
-static inline int __phy_package_write(struct phy_device *phydev,
-				      unsigned int addr_offset, u32 regnum,
-				      u16 val)
-{
-	int addr = phy_package_address(phydev, addr_offset);
-
-	if (addr < 0)
-		return addr;
-
-	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
-}
-
 int __phy_package_read_mmd(struct phy_device *phydev,
 			   unsigned int addr_offset, int devad,
 			   u32 regnum);
@@ -2226,27 +2161,6 @@ int phy_package_write_mmd(struct phy_device *phydev,
 			  unsigned int addr_offset, int devad,
 			  u32 regnum, u16 val);
 
-static inline bool __phy_package_set_once(struct phy_device *phydev,
-					  unsigned int b)
-{
-	struct phy_package_shared *shared = phydev->shared;
-
-	if (!shared)
-		return false;
-
-	return !test_and_set_bit(b, &shared->flags);
-}
-
-static inline bool phy_package_init_once(struct phy_device *phydev)
-{
-	return __phy_package_set_once(phydev, PHY_SHARED_F_INIT_DONE);
-}
-
-static inline bool phy_package_probe_once(struct phy_device *phydev)
-{
-	return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE);
-}
-
 extern const struct bus_type mdio_bus_type;
 
 struct mdio_board_info {
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:13:05 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:13:05 +0100
Subject: [PATCH net-next v3 0/8] net: phy: move PHY package code to its own
 source file
Message-ID: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>

This series contributes to cleaning up phylib by moving PHY package
related code to its own source file.

v2:
- rename the getters
- add a new header file phylib.h, which is used by PHY drivers only
v3:
- include phylib.h in bcm54140.c

Heiner Kallweit (8):
  net: phy: move PHY package code from phy_device.c to own source file
  net: phy: add getters for public members in struct phy_package_shared
  net: phy: qca807x: use new phy_package_shared getters
  net: phy: micrel: use new phy_package_shared getters
  net: phy: mediatek: use new phy_package_shared getters
  net: phy: mscc: use new phy_package_shared getters
  net: phy: move PHY package related code from phy.h to phy_package.c
  net: phy: remove remaining PHY package related definitions from phy.h

 drivers/net/phy/Makefile              |   3 +-
 drivers/net/phy/bcm54140.c            |   1 +
 drivers/net/phy/mediatek/mtk-ge-soc.c |   7 +-
 drivers/net/phy/micrel.c              |   9 +-
 drivers/net/phy/mscc/mscc_main.c      |   2 +
 drivers/net/phy/mscc/mscc_ptp.c       |  14 +-
 drivers/net/phy/phy-core.c            |   1 +
 drivers/net/phy/phy_device.c          | 237 -----------------
 drivers/net/phy/phy_package.c         | 350 ++++++++++++++++++++++++++
 drivers/net/phy/phylib-internal.h     |   2 +
 drivers/net/phy/phylib.h              |  28 +++
 drivers/net/phy/qcom/qca807x.c        |  16 +-
 include/linux/phy.h                   | 124 ---------
 13 files changed, 410 insertions(+), 384 deletions(-)
 create mode 100644 drivers/net/phy/phy_package.c
 create mode 100644 drivers/net/phy/phylib.h

-- 
2.48.1



From hkallweit1 at gmail.com  Mon Mar  3 12:14:02 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:14:02 +0100
Subject: [PATCH net-next v3 1/8] net: phy: move PHY package code from
 phy_device.c to own source file
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <57df5c19-fbcd-45a7-9afd-cd4f74d7fa76@gmail.com>

This patch is the first step in moving the PHY package related code
to its own source file. No functional change intended.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/Makefile      |   3 +-
 drivers/net/phy/phy_device.c  | 237 ---------------------------------
 drivers/net/phy/phy_package.c | 244 ++++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+), 238 deletions(-)
 create mode 100644 drivers/net/phy/phy_package.c

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index c8dac6e92..8f9ba5e82 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -2,7 +2,8 @@
 # Makefile for Linux PHY drivers
 
 libphy-y			:= phy.o phy-c45.o phy-core.o phy_device.o \
-				   linkmode.o phy_link_topology.o
+				   linkmode.o phy_link_topology.o \
+				   phy_package.o
 mdio-bus-y			+= mdio_bus.o mdio_device.o
 
 ifdef CONFIG_MDIO_DEVICE
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a38d399f2..b2d32fbc8 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1686,243 +1686,6 @@ bool phy_driver_is_genphy_10g(struct phy_device *phydev)
 }
 EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
 
-/**
- * phy_package_join - join a common PHY group
- * @phydev: target phy_device struct
- * @base_addr: cookie and base PHY address of PHY package for offset
- *   calculation of global register access
- * @priv_size: if non-zero allocate this amount of bytes for private data
- *
- * This joins a PHY group and provides a shared storage for all phydevs in
- * this group. This is intended to be used for packages which contain
- * more than one PHY, for example a quad PHY transceiver.
- *
- * The base_addr parameter serves as cookie which has to have the same values
- * for all members of one group and as the base PHY address of the PHY package
- * for offset calculation to access generic registers of a PHY package.
- * Usually, one of the PHY addresses of the different PHYs in the package
- * provides access to these global registers.
- * The address which is given here, will be used in the phy_package_read()
- * and phy_package_write() convenience functions as base and added to the
- * passed offset in those functions.
- *
- * This will set the shared pointer of the phydev to the shared storage.
- * If this is the first call for a this cookie the shared storage will be
- * allocated. If priv_size is non-zero, the given amount of bytes are
- * allocated for the priv member.
- *
- * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
- * with the same cookie but a different priv_size is an error.
- */
-int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)
-{
-	struct mii_bus *bus = phydev->mdio.bus;
-	struct phy_package_shared *shared;
-	int ret;
-
-	if (base_addr < 0 || base_addr >= PHY_MAX_ADDR)
-		return -EINVAL;
-
-	mutex_lock(&bus->shared_lock);
-	shared = bus->shared[base_addr];
-	if (!shared) {
-		ret = -ENOMEM;
-		shared = kzalloc(sizeof(*shared), GFP_KERNEL);
-		if (!shared)
-			goto err_unlock;
-		if (priv_size) {
-			shared->priv = kzalloc(priv_size, GFP_KERNEL);
-			if (!shared->priv)
-				goto err_free;
-			shared->priv_size = priv_size;
-		}
-		shared->base_addr = base_addr;
-		shared->np = NULL;
-		refcount_set(&shared->refcnt, 1);
-		bus->shared[base_addr] = shared;
-	} else {
-		ret = -EINVAL;
-		if (priv_size && priv_size != shared->priv_size)
-			goto err_unlock;
-		refcount_inc(&shared->refcnt);
-	}
-	mutex_unlock(&bus->shared_lock);
-
-	phydev->shared = shared;
-
-	return 0;
-
-err_free:
-	kfree(shared);
-err_unlock:
-	mutex_unlock(&bus->shared_lock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(phy_package_join);
-
-/**
- * of_phy_package_join - join a common PHY group in PHY package
- * @phydev: target phy_device struct
- * @priv_size: if non-zero allocate this amount of bytes for private data
- *
- * This is a variant of phy_package_join for PHY package defined in DT.
- *
- * The parent node of the @phydev is checked as a valid PHY package node
- * structure (by matching the node name "ethernet-phy-package") and the
- * base_addr for the PHY package is passed to phy_package_join.
- *
- * With this configuration the shared struct will also have the np value
- * filled to use additional DT defined properties in PHY specific
- * probe_once and config_init_once PHY package OPs.
- *
- * Returns < 0 on error, 0 on success. Esp. calling phy_package_join()
- * with the same cookie but a different priv_size is an error. Or a parent
- * node is not detected or is not valid or doesn't match the expected node
- * name for PHY package.
- */
-int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
-{
-	struct device_node *node = phydev->mdio.dev.of_node;
-	struct device_node *package_node;
-	u32 base_addr;
-	int ret;
-
-	if (!node)
-		return -EINVAL;
-
-	package_node = of_get_parent(node);
-	if (!package_node)
-		return -EINVAL;
-
-	if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	if (of_property_read_u32(package_node, "reg", &base_addr)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	ret = phy_package_join(phydev, base_addr, priv_size);
-	if (ret)
-		goto exit;
-
-	phydev->shared->np = package_node;
-
-	return 0;
-exit:
-	of_node_put(package_node);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(of_phy_package_join);
-
-/**
- * phy_package_leave - leave a common PHY group
- * @phydev: target phy_device struct
- *
- * This leaves a PHY group created by phy_package_join(). If this phydev
- * was the last user of the shared data between the group, this data is
- * freed. Resets the phydev->shared pointer to NULL.
- */
-void phy_package_leave(struct phy_device *phydev)
-{
-	struct phy_package_shared *shared = phydev->shared;
-	struct mii_bus *bus = phydev->mdio.bus;
-
-	if (!shared)
-		return;
-
-	/* Decrease the node refcount on leave if present */
-	if (shared->np)
-		of_node_put(shared->np);
-
-	if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
-		bus->shared[shared->base_addr] = NULL;
-		mutex_unlock(&bus->shared_lock);
-		kfree(shared->priv);
-		kfree(shared);
-	}
-
-	phydev->shared = NULL;
-}
-EXPORT_SYMBOL_GPL(phy_package_leave);
-
-static void devm_phy_package_leave(struct device *dev, void *res)
-{
-	phy_package_leave(*(struct phy_device **)res);
-}
-
-/**
- * devm_phy_package_join - resource managed phy_package_join()
- * @dev: device that is registering this PHY package
- * @phydev: target phy_device struct
- * @base_addr: cookie and base PHY address of PHY package for offset
- *   calculation of global register access
- * @priv_size: if non-zero allocate this amount of bytes for private data
- *
- * Managed phy_package_join(). Shared storage fetched by this function,
- * phy_package_leave() is automatically called on driver detach. See
- * phy_package_join() for more information.
- */
-int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
-			  int base_addr, size_t priv_size)
-{
-	struct phy_device **ptr;
-	int ret;
-
-	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
-			   GFP_KERNEL);
-	if (!ptr)
-		return -ENOMEM;
-
-	ret = phy_package_join(phydev, base_addr, priv_size);
-
-	if (!ret) {
-		*ptr = phydev;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(devm_phy_package_join);
-
-/**
- * devm_of_phy_package_join - resource managed of_phy_package_join()
- * @dev: device that is registering this PHY package
- * @phydev: target phy_device struct
- * @priv_size: if non-zero allocate this amount of bytes for private data
- *
- * Managed of_phy_package_join(). Shared storage fetched by this function,
- * phy_package_leave() is automatically called on driver detach. See
- * of_phy_package_join() for more information.
- */
-int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
-			     size_t priv_size)
-{
-	struct phy_device **ptr;
-	int ret;
-
-	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
-			   GFP_KERNEL);
-	if (!ptr)
-		return -ENOMEM;
-
-	ret = of_phy_package_join(phydev, priv_size);
-
-	if (!ret) {
-		*ptr = phydev;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
-
 /**
  * phy_detach - detach a PHY device from its network device
  * @phydev: target phy_device struct
diff --git a/drivers/net/phy/phy_package.c b/drivers/net/phy/phy_package.c
new file mode 100644
index 000000000..260469f02
--- /dev/null
+++ b/drivers/net/phy/phy_package.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * PHY package support
+ */
+
+#include <linux/of.h>
+#include <linux/phy.h>
+
+/**
+ * phy_package_join - join a common PHY group
+ * @phydev: target phy_device struct
+ * @base_addr: cookie and base PHY address of PHY package for offset
+ *   calculation of global register access
+ * @priv_size: if non-zero allocate this amount of bytes for private data
+ *
+ * This joins a PHY group and provides a shared storage for all phydevs in
+ * this group. This is intended to be used for packages which contain
+ * more than one PHY, for example a quad PHY transceiver.
+ *
+ * The base_addr parameter serves as cookie which has to have the same values
+ * for all members of one group and as the base PHY address of the PHY package
+ * for offset calculation to access generic registers of a PHY package.
+ * Usually, one of the PHY addresses of the different PHYs in the package
+ * provides access to these global registers.
+ * The address which is given here, will be used in the phy_package_read()
+ * and phy_package_write() convenience functions as base and added to the
+ * passed offset in those functions.
+ *
+ * This will set the shared pointer of the phydev to the shared storage.
+ * If this is the first call for a this cookie the shared storage will be
+ * allocated. If priv_size is non-zero, the given amount of bytes are
+ * allocated for the priv member.
+ *
+ * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
+ * with the same cookie but a different priv_size is an error.
+ */
+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)
+{
+	struct mii_bus *bus = phydev->mdio.bus;
+	struct phy_package_shared *shared;
+	int ret;
+
+	if (base_addr < 0 || base_addr >= PHY_MAX_ADDR)
+		return -EINVAL;
+
+	mutex_lock(&bus->shared_lock);
+	shared = bus->shared[base_addr];
+	if (!shared) {
+		ret = -ENOMEM;
+		shared = kzalloc(sizeof(*shared), GFP_KERNEL);
+		if (!shared)
+			goto err_unlock;
+		if (priv_size) {
+			shared->priv = kzalloc(priv_size, GFP_KERNEL);
+			if (!shared->priv)
+				goto err_free;
+			shared->priv_size = priv_size;
+		}
+		shared->base_addr = base_addr;
+		shared->np = NULL;
+		refcount_set(&shared->refcnt, 1);
+		bus->shared[base_addr] = shared;
+	} else {
+		ret = -EINVAL;
+		if (priv_size && priv_size != shared->priv_size)
+			goto err_unlock;
+		refcount_inc(&shared->refcnt);
+	}
+	mutex_unlock(&bus->shared_lock);
+
+	phydev->shared = shared;
+
+	return 0;
+
+err_free:
+	kfree(shared);
+err_unlock:
+	mutex_unlock(&bus->shared_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_package_join);
+
+/**
+ * of_phy_package_join - join a common PHY group in PHY package
+ * @phydev: target phy_device struct
+ * @priv_size: if non-zero allocate this amount of bytes for private data
+ *
+ * This is a variant of phy_package_join for PHY package defined in DT.
+ *
+ * The parent node of the @phydev is checked as a valid PHY package node
+ * structure (by matching the node name "ethernet-phy-package") and the
+ * base_addr for the PHY package is passed to phy_package_join.
+ *
+ * With this configuration the shared struct will also have the np value
+ * filled to use additional DT defined properties in PHY specific
+ * probe_once and config_init_once PHY package OPs.
+ *
+ * Returns < 0 on error, 0 on success. Esp. calling phy_package_join()
+ * with the same cookie but a different priv_size is an error. Or a parent
+ * node is not detected or is not valid or doesn't match the expected node
+ * name for PHY package.
+ */
+int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
+{
+	struct device_node *node = phydev->mdio.dev.of_node;
+	struct device_node *package_node;
+	u32 base_addr;
+	int ret;
+
+	if (!node)
+		return -EINVAL;
+
+	package_node = of_get_parent(node);
+	if (!package_node)
+		return -EINVAL;
+
+	if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (of_property_read_u32(package_node, "reg", &base_addr)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	ret = phy_package_join(phydev, base_addr, priv_size);
+	if (ret)
+		goto exit;
+
+	phydev->shared->np = package_node;
+
+	return 0;
+exit:
+	of_node_put(package_node);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_phy_package_join);
+
+/**
+ * phy_package_leave - leave a common PHY group
+ * @phydev: target phy_device struct
+ *
+ * This leaves a PHY group created by phy_package_join(). If this phydev
+ * was the last user of the shared data between the group, this data is
+ * freed. Resets the phydev->shared pointer to NULL.
+ */
+void phy_package_leave(struct phy_device *phydev)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	struct mii_bus *bus = phydev->mdio.bus;
+
+	if (!shared)
+		return;
+
+	/* Decrease the node refcount on leave if present */
+	if (shared->np)
+		of_node_put(shared->np);
+
+	if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
+		bus->shared[shared->base_addr] = NULL;
+		mutex_unlock(&bus->shared_lock);
+		kfree(shared->priv);
+		kfree(shared);
+	}
+
+	phydev->shared = NULL;
+}
+EXPORT_SYMBOL_GPL(phy_package_leave);
+
+static void devm_phy_package_leave(struct device *dev, void *res)
+{
+	phy_package_leave(*(struct phy_device **)res);
+}
+
+/**
+ * devm_phy_package_join - resource managed phy_package_join()
+ * @dev: device that is registering this PHY package
+ * @phydev: target phy_device struct
+ * @base_addr: cookie and base PHY address of PHY package for offset
+ *   calculation of global register access
+ * @priv_size: if non-zero allocate this amount of bytes for private data
+ *
+ * Managed phy_package_join(). Shared storage fetched by this function,
+ * phy_package_leave() is automatically called on driver detach. See
+ * phy_package_join() for more information.
+ */
+int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
+			  int base_addr, size_t priv_size)
+{
+	struct phy_device **ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
+			   GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = phy_package_join(phydev, base_addr, priv_size);
+
+	if (!ret) {
+		*ptr = phydev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_phy_package_join);
+
+/**
+ * devm_of_phy_package_join - resource managed of_phy_package_join()
+ * @dev: device that is registering this PHY package
+ * @phydev: target phy_device struct
+ * @priv_size: if non-zero allocate this amount of bytes for private data
+ *
+ * Managed of_phy_package_join(). Shared storage fetched by this function,
+ * phy_package_leave() is automatically called on driver detach. See
+ * of_phy_package_join() for more information.
+ */
+int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
+			     size_t priv_size)
+{
+	struct phy_device **ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
+			   GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = of_phy_package_join(phydev, priv_size);
+
+	if (!ret) {
+		*ptr = phydev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
-- 
2.48.1




From hkallweit1 at gmail.com  Mon Mar  3 12:19:25 2025
From: hkallweit1 at gmail.com (Heiner Kallweit)
Date: Mon, 3 Mar 2025 21:19:25 +0100
Subject: [PATCH net-next v3 8/8] net: phy: remove remaining PHY package
 related definitions from phy.h
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <211e14b6-e2f8-43d7-b533-3628ec548456@gmail.com>

Move definition of struct phy_package_shared to phy_package.c, and
move remaining PHY package related declarations from phy.h to
phylib.h, thus making them accessible for PHY drivers only.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 drivers/net/phy/phy_package.c | 31 ++++++++++++++++++++++++++++
 drivers/net/phy/phylib.h      |  7 +++++++
 include/linux/phy.h           | 38 -----------------------------------
 3 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/net/phy/phy_package.c b/drivers/net/phy/phy_package.c
index 12c92d26e..c738f76e8 100644
--- a/drivers/net/phy/phy_package.c
+++ b/drivers/net/phy/phy_package.c
@@ -9,6 +9,37 @@
 #include "phylib.h"
 #include "phylib-internal.h"
 
+/**
+ * struct phy_package_shared - Shared information in PHY packages
+ * @base_addr: Base PHY address of PHY package used to combine PHYs
+ *   in one package and for offset calculation of phy_package_read/write
+ * @np: Pointer to the Device Node if PHY package defined in DT
+ * @refcnt: Number of PHYs connected to this shared data
+ * @flags: Initialization of PHY package
+ * @priv_size: Size of the shared private data @priv
+ * @priv: Driver private data shared across a PHY package
+ *
+ * Represents a shared structure between different phydev's in the same
+ * package, for example a quad PHY. See phy_package_join() and
+ * phy_package_leave().
+ */
+struct phy_package_shared {
+	u8 base_addr;
+	/* With PHY package defined in DT this points to the PHY package node */
+	struct device_node *np;
+	refcount_t refcnt;
+	unsigned long flags;
+	size_t priv_size;
+
+	/* private data pointer */
+	/* note that this pointer is shared between different phydevs and
+	 * the user has to take care of appropriate locking. It is allocated
+	 * and freed automatically by phy_package_join() and
+	 * phy_package_leave().
+	 */
+	void *priv;
+};
+
 struct device_node *phy_package_get_node(struct phy_device *phydev)
 {
 	return phydev->shared->np;
diff --git a/drivers/net/phy/phylib.h b/drivers/net/phy/phylib.h
index 06c50d275..f0e499fed 100644
--- a/drivers/net/phy/phylib.h
+++ b/drivers/net/phy/phylib.h
@@ -17,5 +17,12 @@ int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset,
 			u32 regnum, u16 val);
 bool phy_package_init_once(struct phy_device *phydev);
 bool phy_package_probe_once(struct phy_device *phydev);
+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
+int of_phy_package_join(struct phy_device *phydev, size_t priv_size);
+void phy_package_leave(struct phy_device *phydev);
+int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
+			  int base_addr, size_t priv_size);
+int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
+			     size_t priv_size);
 
 #endif /* __PHYLIB_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 2b12d1bef..c4a6385fa 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -319,37 +319,6 @@ struct mdio_bus_stats {
 	struct u64_stats_sync syncp;
 };
 
-/**
- * struct phy_package_shared - Shared information in PHY packages
- * @base_addr: Base PHY address of PHY package used to combine PHYs
- *   in one package and for offset calculation of phy_package_read/write
- * @np: Pointer to the Device Node if PHY package defined in DT
- * @refcnt: Number of PHYs connected to this shared data
- * @flags: Initialization of PHY package
- * @priv_size: Size of the shared private data @priv
- * @priv: Driver private data shared across a PHY package
- *
- * Represents a shared structure between different phydev's in the same
- * package, for example a quad PHY. See phy_package_join() and
- * phy_package_leave().
- */
-struct phy_package_shared {
-	u8 base_addr;
-	/* With PHY package defined in DT this points to the PHY package node */
-	struct device_node *np;
-	refcount_t refcnt;
-	unsigned long flags;
-	size_t priv_size;
-
-	/* private data pointer */
-	/* note that this pointer is shared between different phydevs and
-	 * the user has to take care of appropriate locking. It is allocated
-	 * and freed automatically by phy_package_join() and
-	 * phy_package_leave().
-	 */
-	void *priv;
-};
-
 /**
  * struct mii_bus - Represents an MDIO bus
  *
@@ -2109,13 +2078,6 @@ int phy_ethtool_get_link_ksettings(struct net_device *ndev,
 int phy_ethtool_set_link_ksettings(struct net_device *ndev,
 				   const struct ethtool_link_ksettings *cmd);
 int phy_ethtool_nway_reset(struct net_device *ndev);
-int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
-int of_phy_package_join(struct phy_device *phydev, size_t priv_size);
-void phy_package_leave(struct phy_device *phydev);
-int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
-			  int base_addr, size_t priv_size);
-int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
-			     size_t priv_size);
 
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
-- 
2.48.1




From nifan.cxl at gmail.com  Mon Mar  3 12:50:40 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 12:50:40 -0800
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250303194647.GC1552306@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
Message-ID: <Z8YWILtSbQnvVqbF@debian>

On Tue, Mar 04, 2025 at 04:46:47AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> [...]
> > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > +{
> > > +	char dirname[DWC_DEBUGFS_BUF_MAX];
> > > +	struct device *dev = pci->dev;
> > > +	struct debugfs_info *debugfs;
> > > +	struct dentry *dir;
> > > +	int ret;
> > > +
> > > +	/* Create main directory for each platform driver */
> > > +	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > +	dir = debugfs_create_dir(dirname, NULL);
> > > +	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > +	if (!debugfs)
> > > +		return -ENOMEM;
> > > +
> > > +	debugfs->debug_dir = dir;
> > > +	pci->debugfs = debugfs;
> > > +	ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > +	if (ret)
> > > +		dev_dbg(dev, "RASDES debugfs init failed\n");
> > 
> > What will happen if ret != 0? still return 0? 
> 
> Given that callers of dwc_pcie_debugfs_init() check for errors,
> this probably should correctly bubble up any failure coming from
> dwc_pcie_rasdes_debugfs_init().
> 
> I made updates to the code directly on the current branch, have a look:
> 
>   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=1ff54f4cbaed9ec6994844967c36cf7ada4cbe5e
> 
> Let me know if this is OK with you.

It looks good to me.

Feel free to add,
Reviewed-by: Fan Ni <fan.ni at samsung.com>

Fan
> 
> Good catch, thank you!
> 
> 	Krzysztof


From quic_eberman at quicinc.com  Mon Mar  3 13:08:34 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:34 -0800
Subject: [PATCH v9 5/5] arm64: dts: qcom: sa8775p-ride: Add PSCI
 SYSTEM_RESET2 types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-5-b2cf4a20feda@oss.qualcomm.com>

From: Elliot Berman <elliot.berman at oss.qualcomm.com>

sa8775p-ride firmware supports vendor-defined SYSTEM_RESET2 types.
Describe the reset types: "bootloader" will cause device to reboot and
stop in the bootloader's fastboot mode. "edl" will cause device to
reboot into "emergency download mode", which permits loading images via
the Firehose protocol.

Co-developed-by: Shivendra Pratap <quic_spratap at quicinc.com>
Signed-off-by: Shivendra Pratap <quic_spratap at quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi | 7 +++++++
 arch/arm64/boot/dts/qcom/sa8775p.dtsi      | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
index 3fc62e12368969e7cca246ddb55920db88eeb1e6..27cf3d35c48d2d79fdf054cadb00d6f4ca3b3c4b 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
@@ -589,6 +589,13 @@ &pmm8654au_3_gpios {
 			  "GNSS_BOOT_MODE";
 };
 
+&psci {
+	reset-types {
+		mode-bootloader = <0x10001 0x2>;
+		mode-edl = <0 0x1>;
+	};
+};
+
 &qupv3_id_1 {
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 9da62d7c4d27f4cae341242c799b61dd1b06f483..73c04e4f858a39b78f7f130f781a9a9ce1b0a0e7 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -392,7 +392,7 @@ pmu {
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
-	psci {
+	psci: psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
 

-- 
2.34.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:45 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:45 +0100
Subject: [PATCH v3 0/6] pinctrl: bcm281xx: Add support for BCM21664 pinmux
Message-ID: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>

BCM21664 is another chip from the Kona line of Broadcom SoCs, and
its pinmux shares a lot of similarities with the BCM281xx pinmux.

Add support for the BCM21664 pinmux controller to the BCM281xx driver.

This also enables pinmux support for the BCM23550, which has an
identical pinmux config to the BCM21664 (hence they can share a
single compatible, brcm,bcm21664-pinctrl).

While we're at it - fix a bug that affected higher registers in the
BCM281XX driver and replace bare "unsigned" with "unsigned int" to
comply with checkpatch requirements.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
By the way - while working on this patch, I noticed two things that
are not implemented in mainline, but seem to be present in the pin
controller regs according to the RDB[1][2]:

- On both BCM21664 and BCM281XX, TRACE* pins only have two bits for
  DRV_STR and no HYST bit. That seems like it deserves its own pin
  type; however, since I don't know how to translate the reduced
  DRV_STR value to a drive strength in mA, I did not implement it.
  For now, I kept the same type for BCM21664 as for BCM281XX for these
  pins (standard).

- On both BCM21664 and BCM281XX, two SIM-related pins (SIM and SIM2
  on BCM281XX, SIMDAT and SSPDO on BCM21664) have extra PUPM0 and PUPM1
  offsets (bits 11 and 12 respectively). Vendor kernel does not do
  anything with these bits, so I don't know what they do.

If any Broadcom engineers could shed some light on these, I'd be
grateful. Otherwise, neither of these are pressing issues, and this
patchset is complete without them (they can be fixed in another
patchset).

[1] https://github.com/knuxdroid/android_kernel_samsung_baffinlite/blob/cm-12.1/arch/arm/mach-hawaii/include/mach/rdb/brcm_rdb_padctrlreg.h
[2] https://github.com/s2plus/android_kernel_samsung_galaxys2plus/blob/cm-10.1_base-4.2/arch/arm/mach-capri/include/mach/rdb/brcm_rdb_padctrlreg.h

---
Changes in v3:
- Rebase on latest linux-pinctrl.git for-next branch
- Fix DT binding example for I2C pins
- Make DT binding more strict
- Link to v2: https://lore.kernel.org/r/20250221-bcm21664-pinctrl-v2-0-7d1f0279fe16 at gmail.com

Changes in v2:
- Rebase on linux-pinctrl.git for-next branch, drop patch 2 ("pinctrl:
  bcm281xx: Fix incorrect regmap max_registers value") as it has been
  applied separately
- Fix "initializer element is not a compile-time constant" warning
- Fix unused variable warning
- Simplify DT binding
- Link to v1: https://lore.kernel.org/r/20250207-bcm21664-pinctrl-v1-0-e7cfac9b2d3b at gmail.com

---
Artur Weber (6):
      dt-bindings: pinctrl: Add bindings for BCM21664 pin controller
      pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned"
      pinctrl: bcm281xx: Provide pinctrl device info as OF platform data
      pinctrl: bcm281xx: Add support for BCM21664 pinmux
      ARM: dts: bcm2166x-common: Add pinctrl node
      ARM: dts: bcm2166x: Add bcm2166x-pinctrl DTSI

 .../bindings/pinctrl/brcm,bcm21664-pinctrl.yaml    | 152 ++++
 arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi    |   7 +
 arch/arm/boot/dts/broadcom/bcm2166x-pinctrl.dtsi   | 297 +++++++
 drivers/pinctrl/bcm/pinctrl-bcm281xx.c             | 849 +++++++++++++++++++--
 4 files changed, 1242 insertions(+), 63 deletions(-)
---
base-commit: 920d1159328017ef0d57cb3172160ad7d33a9709
change-id: 20250206-bcm21664-pinctrl-13cd7d3f7866

Best regards,
-- 
Artur Weber <aweber.kernel at gmail.com>



From aweber.kernel at gmail.com  Mon Mar  3 12:54:46 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:46 +0100
Subject: [PATCH v3 1/6] dt-bindings: pinctrl: Add bindings for BCM21664 pin
 controller
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-1-5f8b80e4ab51@gmail.com>

Add device tree bindings for the pin controller included in the
BCM21664 chip. The bindings are based off brcm,bcm11351-pinctrl.yaml;
both chips use the same driver, but have different pins, and the
BCM21664 has 6 alt modes instead of 4.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v3:
- Fix example for I2C pins
- Specify bias-pull-up/bias-pull-down as a boolean
- Add gpio16/gpio17 to list of I2C pins in slew-rate description
- Use additionalProperties: false on pin group and specify valid
  properties for more strict checking

Changes in v2:
- Drop "property: true" declarations which had no effect with
  "unevaluatedProperties: false"
- Define property limits for I2C pins only instead of standard pins,
  making the pin-specific "if" condition significantly smaller
---
 .../bindings/pinctrl/brcm,bcm21664-pinctrl.yaml    | 152 +++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm21664-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm21664-pinctrl.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1283a588416d406e6ca5add012cbaa569ef355ef
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm21664-pinctrl.yaml
@@ -0,0 +1,152 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/brcm,bcm21664-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM21664 pin controller
+
+maintainers:
+  - Florian Fainelli <florian.fainelli at broadcom.com>
+  - Ray Jui <rjui at broadcom.com>
+  - Scott Branden <sbranden at broadcom.com>
+
+allOf:
+  - $ref: pinctrl.yaml#
+
+properties:
+  compatible:
+    const: brcm,bcm21664-pinctrl
+
+  reg:
+    maxItems: 1
+
+patternProperties:
+  '-pins$':
+    type: object
+    additionalProperties: false
+
+    patternProperties:
+      '-grp[0-9]$':
+        type: object
+
+        properties:
+          pins:
+            description:
+              Specifies the name(s) of one or more pins to be configured by
+              this node.
+            items:
+              enum: [ adcsyn, batrm, bsc1clk, bsc1dat, camcs0, camcs1, clk32k,
+                      clk_cx8, dclk1, dclk4, dclkreq1, dclkreq4, dmic0clk,
+                      dmic0dq, dsi0te, gpio00, gpio01, gpio02, gpio03, gpio04,
+                      gpio05, gpio06, gpio07, gpio08, gpio09, gpio10, gpio11,
+                      gpio12, gpio13, gpio14, gpio15, gpio16, gpio17, gpio18,
+                      gpio19, gpio20, gpio21, gpio22, gpio23, gpio24, gpio25,
+                      gpio26, gpio27, gpio28, gpio32, gpio33, gpio34, gpio93,
+                      gpio94, gps_calreq, gps_hostreq, gps_pablank, gps_tmark,
+                      icusbdm, icusbdp, lcdcs0, lcdres, lcdscl, lcdsda, lcdte,
+                      mdmgpio00, mdmgpio01, mdmgpio02, mdmgpio03, mdmgpio04,
+                      mdmgpio05, mdmgpio06, mdmgpio07, mdmgpio08, mmc0ck,
+                      mmc0cmd, mmc0dat0, mmc0dat1, mmc0dat2, mmc0dat3, mmc0dat4,
+                      mmc0dat5, mmc0dat6, mmc0dat7, mmc0rst, mmc1ck, mmc1cmd,
+                      mmc1dat0, mmc1dat1, mmc1dat2, mmc1dat3, mmc1dat4,
+                      mmc1dat5, mmc1dat6, mmc1dat7, mmc1rst, pc1, pc2, pmbscclk,
+                      pmbscdat, pmuint, resetn, rfst2g_mtsloten3g,
+                      rtxdata2g_txdata3g1, rtxen2g_txdata3g2, rxdata3g0,
+                      rxdata3g1, rxdata3g2, sdck, sdcmd, sddat0, sddat1, sddat2,
+                      sddat3, simclk, simdat, simdet, simrst, spi0clk, spi0fss,
+                      spi0rxd, spi0txd, sri_c, sri_d, sri_e, sspck, sspdi,
+                      sspdo, sspsyn, stat1, stat2, swclktck, swdiotms, sysclken,
+                      tdi, tdo, testmode, traceclk, tracedt00, tracedt01,
+                      tracedt02, tracedt03, tracedt04, tracedt05, tracedt06,
+                      tracedt07, tracedt08, tracedt09, tracedt10, tracedt11,
+                      tracedt12, tracedt13, tracedt14, tracedt15, trstb,
+                      txdata3g0, ubctsn, ubrtsn, ubrx, ubtx ]
+
+          function:
+            description:
+              Specifies the pin mux selection.
+            enum: [ alt1, alt2, alt3, alt4, alt5, alt6 ]
+
+          bias-disable: true
+
+          bias-pull-up:
+            type: boolean
+
+          bias-pull-down:
+            type: boolean
+
+          slew-rate:
+            description: |
+              Meaning depends on configured pin mux:
+                bsc*clk/pmbscclk or bsc*dat/pmbscdat or gpio16/gpio17:
+                  0: Standard (100 kbps) & Fast (400 kbps) mode
+                  1: Highspeed (3.4 Mbps) mode
+                Otherwise:
+                  0: fast slew rate
+                  1: normal slew rate
+
+          drive-strength:
+            enum: [ 2, 4, 6, 8, 10, 12, 14, 16 ]
+
+          input-enable: true
+          input-disable: true
+
+          input-schmitt-enable: true
+          input-schmitt-disable: true
+
+        required:
+          - pins
+
+        additionalProperties: false
+
+        allOf:
+          - $ref: pincfg-node.yaml#
+          # Limitations for I2C pins
+          - if:
+              properties:
+                pins:
+                  contains:
+                    enum: [ bsc1clk, bsc1dat, gpio16, gpio17, pmbscclk,
+                            pmbscdat ]
+            then:
+              properties:
+                drive-strength: false
+                bias-pull-down: false
+                input-schmitt-enable: false
+                input-schmitt-disable: false
+
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    pinctrl at 35004800 {
+      compatible = "brcm,bcm21664-pinctrl";
+      reg = <0x35004800 0x7f0>;
+
+      dev-a-active-pins {
+        /* group node defining 1 standard pin */
+        std-grp0 {
+          pins = "gpio00";
+          function = "alt1";
+          input-schmitt-enable;
+          bias-disable;
+          slew-rate = <1>;
+          drive-strength = <4>;
+        };
+
+        /* group node defining 2 I2C pins */
+        i2c-grp0 {
+          pins = "bsc1clk", "bsc1dat";
+          function = "alt2";
+          bias-pull-up;
+          input-enable;
+        };
+      };
+    };
+...

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:47 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:47 +0100
Subject: [PATCH v3 2/6] pinctrl: bcm281xx: Use "unsigned int" instead of
 bare "unsigned"
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-2-5f8b80e4ab51@gmail.com>

Replace uses of bare "unsigned" with "unsigned int" to fix checkpatch
warnings. No functional change.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
 drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 44 +++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
index cf6efa9c0364a1ad65885c982e7634f26d19c944..a039b490cdb8e6c41169bfd48abb371447c150a0 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -72,7 +72,7 @@ static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
 struct bcm281xx_pin_function {
 	const char *name;
 	const char * const *groups;
-	const unsigned ngroups;
+	const unsigned int ngroups;
 };
 
 /*
@@ -84,10 +84,10 @@ struct bcm281xx_pinctrl_data {
 
 	/* List of all pins */
 	const struct pinctrl_pin_desc *pins;
-	const unsigned npins;
+	const unsigned int npins;
 
 	const struct bcm281xx_pin_function *functions;
-	const unsigned nfunctions;
+	const unsigned int nfunctions;
 
 	struct regmap *regmap;
 };
@@ -941,7 +941,7 @@ static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
 };
 
 static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
-						  unsigned pin)
+						  unsigned int pin)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
@@ -985,7 +985,7 @@ static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
 }
 
 static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-						   unsigned group)
+						   unsigned int group)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
@@ -993,9 +993,9 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
 }
 
 static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
-					   unsigned group,
+					   unsigned int group,
 					   const unsigned **pins,
-					   unsigned *num_pins)
+					   unsigned int *num_pins)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
@@ -1007,7 +1007,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
 
 static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
 					  struct seq_file *s,
-					  unsigned offset)
+					  unsigned int offset)
 {
 	seq_printf(s, " %s", dev_name(pctldev->dev));
 }
@@ -1029,7 +1029,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
 }
 
 static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
-						 unsigned function)
+						 unsigned int function)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
@@ -1037,9 +1037,9 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
 }
 
 static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
-					   unsigned function,
+					   unsigned int function,
 					   const char * const **groups,
-					   unsigned * const num_groups)
+					   unsigned int * const num_groups)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
@@ -1050,8 +1050,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
 }
 
 static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
-			       unsigned function,
-			       unsigned group)
+			       unsigned int function,
+			       unsigned int group)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 	const struct bcm281xx_pin_function *f = &pdata->functions[function];
@@ -1082,7 +1082,7 @@ static const struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
 };
 
 static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
-					   unsigned pin,
+					   unsigned int pin,
 					   unsigned long *config)
 {
 	return -ENOTSUPP;
@@ -1091,9 +1091,9 @@ static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
 
 /* Goes through the configs and update register val/mask */
 static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
-				   unsigned pin,
+				   unsigned int pin,
 				   unsigned long *configs,
-				   unsigned num_configs,
+				   unsigned int num_configs,
 				   u32 *val,
 				   u32 *mask)
 {
@@ -1207,9 +1207,9 @@ static const u16 bcm281xx_pullup_map[] = {
 
 /* Goes through the configs and update register val/mask */
 static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
-				   unsigned pin,
+				   unsigned int pin,
 				   unsigned long *configs,
-				   unsigned num_configs,
+				   unsigned int num_configs,
 				   u32 *val,
 				   u32 *mask)
 {
@@ -1277,9 +1277,9 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
 
 /* Goes through the configs and update register val/mask */
 static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
-				    unsigned pin,
+				    unsigned int pin,
 				    unsigned long *configs,
-				    unsigned num_configs,
+				    unsigned int num_configs,
 				    u32 *val,
 				    u32 *mask)
 {
@@ -1321,9 +1321,9 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
 }
 
 static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
-					   unsigned pin,
+					   unsigned int pin,
 					   unsigned long *configs,
-					   unsigned num_configs)
+					   unsigned int num_configs)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 	enum bcm281xx_pin_type pin_type;

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:48 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:48 +0100
Subject: [PATCH v3 3/6] pinctrl: bcm281xx: Provide pinctrl device info as
 OF platform data
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-3-5f8b80e4ab51@gmail.com>

Introduce a new struct type, "bcm281xx_pinctrl_info", that holds
information about the pins, pin functions and regmap config for a pin
control chip. Create such a struct for the BCM218xx and pass it as
device data for the OF compatible match.

This is done in preparation for introducing additional chip types
to the driver.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v2:
- Make regmap_config pointer member of bcm281xx_pinctrl_info a pointer
  (fixes "initializer element is not a compile-time constant" error)
---
 drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 119 +++++++++++++++++++++------------
 1 file changed, 78 insertions(+), 41 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
index a039b490cdb8e6c41169bfd48abb371447c150a0..f5aeb8a56e6ffa1204423ddc22204a4f0f4e8f84 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -76,20 +76,40 @@ struct bcm281xx_pin_function {
 };
 
 /*
- * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
- * @reg_base - base of pinctrl registers
+ * Device types (used in bcm281xx_pinctrl_desc to differentiate
+ * the two device types from each other)
  */
-struct bcm281xx_pinctrl_data {
-	void __iomem *reg_base;
+enum bcm281xx_pinctrl_type {
+	BCM281XX_PINCTRL_TYPE,
+};
+
+/*
+ * bcm281xx_pinctrl_info - description of a pinctrl device supported
+ * by this driver, intended to be used as a provider of OF match data.
+ */
+struct bcm281xx_pinctrl_info {
+	enum bcm281xx_pinctrl_type device_type;
 
 	/* List of all pins */
 	const struct pinctrl_pin_desc *pins;
-	const unsigned int npins;
+	unsigned int npins;
 
 	const struct bcm281xx_pin_function *functions;
-	const unsigned int nfunctions;
+	unsigned int nfunctions;
+
+	const struct regmap_config *regmap_config;
+};
+
+/*
+ * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
+ * @reg_base - base of pinctrl registers
+ */
+struct bcm281xx_pinctrl_data {
+	struct device *dev;
+	void __iomem *reg_base;
 
 	struct regmap *regmap;
+	const struct bcm281xx_pinctrl_info *info;
 };
 
 /*
@@ -933,11 +953,22 @@ static const struct bcm281xx_pin_function bcm281xx_functions[] = {
 	BCM281XX_PIN_FUNCTION(alt4),
 };
 
-static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
+static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = BCM281XX_PIN_VC_CAM3_SDA * 4,
+};
+
+static const struct bcm281xx_pinctrl_info bcm281xx_pinctrl = {
+	.device_type = BCM281XX_PINCTRL_TYPE,
+
 	.pins = bcm281xx_pinctrl_pins,
 	.npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
 	.functions = bcm281xx_functions,
 	.nfunctions = ARRAY_SIZE(bcm281xx_functions),
+
+	.regmap_config = &bcm281xx_pinctrl_regmap_config,
 };
 
 static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
@@ -945,10 +976,10 @@ static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	if (pin >= pdata->npins)
+	if (pin >= pdata->info->npins)
 		return BCM281XX_PIN_TYPE_UNKNOWN;
 
-	return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
+	return *(enum bcm281xx_pin_type *)(pdata->info->pins[pin].drv_data);
 }
 
 #define BCM281XX_PIN_SHIFT(type, param) \
@@ -970,18 +1001,11 @@ static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
 	*reg_mask |= param_mask;
 }
 
-static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.max_register = BCM281XX_PIN_VC_CAM3_SDA * 4,
-};
-
 static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	return pdata->npins;
+	return pdata->info->npins;
 }
 
 static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
@@ -989,7 +1013,7 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	return pdata->pins[group].name;
+	return pdata->info->pins[group].name;
 }
 
 static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
@@ -999,7 +1023,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	*pins = &pdata->pins[group].number;
+	*pins = &pdata->info->pins[group].number;
 	*num_pins = 1;
 
 	return 0;
@@ -1025,7 +1049,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	return pdata->nfunctions;
+	return pdata->info->nfunctions;
 }
 
 static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
@@ -1033,7 +1057,7 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	return pdata->functions[function].name;
+	return pdata->info->functions[function].name;
 }
 
 static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
@@ -1043,8 +1067,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 
-	*groups = pdata->functions[function].groups;
-	*num_groups = pdata->functions[function].ngroups;
+	*groups = pdata->info->functions[function].groups;
+	*num_groups = pdata->info->functions[function].ngroups;
 
 	return 0;
 }
@@ -1054,14 +1078,15 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
 			       unsigned int group)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	const struct bcm281xx_pin_function *f = &pdata->functions[function];
-	u32 offset = 4 * pdata->pins[group].number;
+	const struct bcm281xx_pin_function *f = &pdata->info->functions[function];
+	unsigned int pin = pdata->info->pins[group].number;
+	u32 offset = 4 * pin;
 	int rc = 0;
 
 	dev_dbg(pctldev->dev,
 		"%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
-		__func__, f->name, function, pdata->pins[group].name,
-		pdata->pins[group].number, offset);
+		__func__, f->name, function, pdata->info->pins[group].name,
+		pin, offset);
 
 	rc = regmap_update_bits(pdata->regmap, offset,
 		BCM281XX_PIN_REG_F_SEL_MASK,
@@ -1069,7 +1094,7 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
 	if (rc)
 		dev_err(pctldev->dev,
 			"Error updating register for pin %s (%d).\n",
-			pdata->pins[group].name, pdata->pins[group].number);
+			pdata->info->pins[group].name, pin);
 
 	return rc;
 }
@@ -1168,7 +1193,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
 					"Invalid Drive Strength value (%d) for "
 					"pin %s (%d). Valid values are "
 					"(2..16) mA, even numbers only.\n",
-					arg, pdata->pins[pin].name, pin);
+					arg, pdata->info->pins[pin].name, pin);
 				return -EINVAL;
 			}
 			bcm281xx_pin_update(val, mask, (arg/2)-1,
@@ -1179,7 +1204,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
 		default:
 			dev_err(pctldev->dev,
 				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
+				param, pdata->info->pins[pin].name, pin);
 			return -EINVAL;
 
 		} /* switch config */
@@ -1233,7 +1258,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
 					"Invalid pull-up value (%d) for pin %s "
 					"(%d). Valid values are 568, 720, 831, "
 					"1080, 1200, 1800, 2700 Ohms.\n",
-					arg, pdata->pins[pin].name, pin);
+					arg, pdata->info->pins[pin].name, pin);
 				return -EINVAL;
 			}
 
@@ -1266,7 +1291,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
 		default:
 			dev_err(pctldev->dev,
 				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
+				param, pdata->info->pins[pin].name, pin);
 			return -EINVAL;
 
 		} /* switch config */
@@ -1311,7 +1336,7 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
 		default:
 			dev_err(pctldev->dev,
 				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
+				param, pdata->info->pins[pin].name, pin);
 			return -EINVAL;
 
 		} /* switch config */
@@ -1354,7 +1379,7 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 
 	default:
 		dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
-			pdata->pins[pin].name, pin);
+			pdata->info->pins[pin].name, pin);
 		return -EINVAL;
 
 	} /* switch pin type */
@@ -1364,13 +1389,13 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 
 	dev_dbg(pctldev->dev,
 		"%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
-		__func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
+		__func__, pdata->info->pins[pin].name, pin, cfg_val, cfg_mask);
 
 	rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
 	if (rc) {
 		dev_err(pctldev->dev,
 			"Error updating register for pin %s (%d).\n",
-			pdata->pins[pin].name, pin);
+			pdata->info->pins[pin].name, pin);
 		return rc;
 	}
 
@@ -1390,11 +1415,23 @@ static struct pinctrl_desc bcm281xx_pinctrl_desc = {
 	.owner = THIS_MODULE,
 };
 
+static struct bcm281xx_pinctrl_data bcm281xx_pinctrl_pdata;
+
 static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 {
-	struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
+	struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl_pdata;
 	struct pinctrl_dev *pctl;
 
+	/* Set device pointer in platform data */
+	pdata->dev = &pdev->dev;
+
+	/* Get the data to use from OF match */
+	pdata->info = of_device_get_match_data(&pdev->dev);
+	if (!pdata->info) {
+		dev_err(&pdev->dev, "Failed to get data from OF match\n");
+		return -ENODEV;
+	}
+
 	/* So far We can assume there is only 1 bank of registers */
 	pdata->reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(pdata->reg_base)) {
@@ -1404,15 +1441,15 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 
 	/* Initialize the dynamic part of pinctrl_desc */
 	pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
-		&bcm281xx_pinctrl_regmap_config);
+		pdata->info->regmap_config);
 	if (IS_ERR(pdata->regmap)) {
 		dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
 		return -ENODEV;
 	}
 
 	bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
-	bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
-	bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
+	bcm281xx_pinctrl_desc.pins = pdata->info->pins;
+	bcm281xx_pinctrl_desc.npins = pdata->info->npins;
 
 	pctl = devm_pinctrl_register(&pdev->dev, &bcm281xx_pinctrl_desc, pdata);
 	if (IS_ERR(pctl)) {
@@ -1426,7 +1463,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
-	{ .compatible = "brcm,bcm11351-pinctrl", },
+	{ .compatible = "brcm,bcm11351-pinctrl", .data = &bcm281xx_pinctrl },
 	{ },
 };
 

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:49 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:49 +0100
Subject: [PATCH v3 4/6] pinctrl: bcm281xx: Add support for BCM21664 pinmux
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-4-5f8b80e4ab51@gmail.com>

BCM21664 is another chip from the Kona line of Broadcom SoCs, and
its pinmux shares a lot of similarities with the BCM281xx pinmux.

Add support for the BCM21664 pinmux controller to the BCM281xx driver.

This also enables pinmux support for the BCM23550, which has an
identical pinmux config to the BCM21664 (hence they can share a
single compatible, brcm,bcm21664-pinctrl).

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v2:
- Adapt to regmap_config member of bcm281xx_pinctrl_info being a
  pointer now
---
 drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 690 ++++++++++++++++++++++++++++++++-
 1 file changed, 688 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
index f5aeb8a56e6ffa1204423ddc22204a4f0f4e8f84..7c8f8bd7da129daff1c1312fe74abf2986b83fb9 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -52,6 +52,12 @@
 #define BCM281XX_HDMI_PIN_REG_MODE_MASK		0x0010
 #define BCM281XX_HDMI_PIN_REG_MODE_SHIFT	4
 
+/* BCM21664 access lock registers */
+#define BCM21664_WR_ACCESS_OFFSET		0x07F0
+#define BCM21664_WR_ACCESS_PASSWORD		0xA5A501
+#define BCM21664_ACCESS_LOCK_OFFSET(lock)	(0x0780 + (lock * 4))
+#define BCM21664_ACCESS_LOCK_COUNT		5
+
 /*
  * bcm281xx_pin_type - types of pin register
  */
@@ -81,6 +87,7 @@ struct bcm281xx_pin_function {
  */
 enum bcm281xx_pinctrl_type {
 	BCM281XX_PINCTRL_TYPE,
+	BCM21664_PINCTRL_TYPE,
 };
 
 /*
@@ -971,6 +978,571 @@ static const struct bcm281xx_pinctrl_info bcm281xx_pinctrl = {
 	.regmap_config = &bcm281xx_pinctrl_regmap_config,
 };
 
+/* BCM21664 data */
+#define BCM21664_PIN_ADCSYN		0
+#define BCM21664_PIN_BATRM		1
+#define BCM21664_PIN_BSC1CLK		2
+#define BCM21664_PIN_BSC1DAT		3
+#define BCM21664_PIN_CAMCS0		4
+#define BCM21664_PIN_CAMCS1		5
+#define BCM21664_PIN_CLK32K		6
+#define BCM21664_PIN_CLK_CX8		7
+#define BCM21664_PIN_DCLK1		8
+#define BCM21664_PIN_DCLK4		9
+#define BCM21664_PIN_DCLKREQ1		10
+#define BCM21664_PIN_DCLKREQ4		11
+#define BCM21664_PIN_DMIC0CLK		12
+#define BCM21664_PIN_DMIC0DQ		13
+#define BCM21664_PIN_DSI0TE		14
+#define BCM21664_PIN_GPIO00		15
+#define BCM21664_PIN_GPIO01		16
+#define BCM21664_PIN_GPIO02		17
+#define BCM21664_PIN_GPIO03		18
+#define BCM21664_PIN_GPIO04		19
+#define BCM21664_PIN_GPIO05		20
+#define BCM21664_PIN_GPIO06		21
+#define BCM21664_PIN_GPIO07		22
+#define BCM21664_PIN_GPIO08		23
+#define BCM21664_PIN_GPIO09		24
+#define BCM21664_PIN_GPIO10		25
+#define BCM21664_PIN_GPIO11		26
+#define BCM21664_PIN_GPIO12		27
+#define BCM21664_PIN_GPIO13		28
+#define BCM21664_PIN_GPIO14		29
+#define BCM21664_PIN_GPIO15		30
+#define BCM21664_PIN_GPIO16		31
+#define BCM21664_PIN_GPIO17		32
+#define BCM21664_PIN_GPIO18		33
+#define BCM21664_PIN_GPIO19		34
+#define BCM21664_PIN_GPIO20		35
+#define BCM21664_PIN_GPIO21		36
+#define BCM21664_PIN_GPIO22		37
+#define BCM21664_PIN_GPIO23		38
+#define BCM21664_PIN_GPIO24		39
+#define BCM21664_PIN_GPIO25		40
+#define BCM21664_PIN_GPIO26		41
+#define BCM21664_PIN_GPIO27		42
+#define BCM21664_PIN_GPIO28		43
+#define BCM21664_PIN_GPIO32		44
+#define BCM21664_PIN_GPIO33		45
+#define BCM21664_PIN_GPIO34		46
+#define BCM21664_PIN_GPS_CALREQ		47
+#define BCM21664_PIN_GPS_HOSTREQ	48
+#define BCM21664_PIN_GPS_PABLANK	49
+#define BCM21664_PIN_GPS_TMARK		50
+#define BCM21664_PIN_ICUSBDM		51
+#define BCM21664_PIN_ICUSBDP		52
+#define BCM21664_PIN_LCDCS0		53
+#define BCM21664_PIN_LCDRES		54
+#define BCM21664_PIN_LCDSCL		55
+#define BCM21664_PIN_LCDSDA		56
+#define BCM21664_PIN_LCDTE		57
+#define BCM21664_PIN_MDMGPIO00		58
+#define BCM21664_PIN_MDMGPIO01		59
+#define BCM21664_PIN_MDMGPIO02		60
+#define BCM21664_PIN_MDMGPIO03		61
+#define BCM21664_PIN_MDMGPIO04		62
+#define BCM21664_PIN_MDMGPIO05		63
+#define BCM21664_PIN_MDMGPIO06		64
+#define BCM21664_PIN_MDMGPIO07		65
+#define BCM21664_PIN_MDMGPIO08		66
+#define BCM21664_PIN_MMC0CK		67
+#define BCM21664_PIN_MMC0CMD		68
+#define BCM21664_PIN_MMC0DAT0		69
+#define BCM21664_PIN_MMC0DAT1		70
+#define BCM21664_PIN_MMC0DAT2		71
+#define BCM21664_PIN_MMC0DAT3		72
+#define BCM21664_PIN_MMC0DAT4		73
+#define BCM21664_PIN_MMC0DAT5		74
+#define BCM21664_PIN_MMC0DAT6		75
+#define BCM21664_PIN_MMC0DAT7		76
+#define BCM21664_PIN_MMC0RST		77
+#define BCM21664_PIN_MMC1CK		78
+#define BCM21664_PIN_MMC1CMD		79
+#define BCM21664_PIN_MMC1DAT0		80
+#define BCM21664_PIN_MMC1DAT1		81
+#define BCM21664_PIN_MMC1DAT2		82
+#define BCM21664_PIN_MMC1DAT3		83
+#define BCM21664_PIN_MMC1DAT4		84
+#define BCM21664_PIN_MMC1DAT5		85
+#define BCM21664_PIN_MMC1DAT6		86
+#define BCM21664_PIN_MMC1DAT7		87
+#define BCM21664_PIN_MMC1RST		88
+#define BCM21664_PIN_PC1		89
+#define BCM21664_PIN_PC2		90
+#define BCM21664_PIN_PMBSCCLK		91
+#define BCM21664_PIN_PMBSCDAT		92
+#define BCM21664_PIN_PMUINT		93
+#define BCM21664_PIN_RESETN		94
+#define BCM21664_PIN_RFST2G_MTSLOTEN3G	95
+#define BCM21664_PIN_RTXDATA2G_TXDATA3G1	96
+#define BCM21664_PIN_RTXEN2G_TXDATA3G2	97
+#define BCM21664_PIN_RXDATA3G0		98
+#define BCM21664_PIN_RXDATA3G1		99
+#define BCM21664_PIN_RXDATA3G2		100
+#define BCM21664_PIN_SDCK		101
+#define BCM21664_PIN_SDCMD		102
+#define BCM21664_PIN_SDDAT0		103
+#define BCM21664_PIN_SDDAT1		104
+#define BCM21664_PIN_SDDAT2		105
+#define BCM21664_PIN_SDDAT3		106
+#define BCM21664_PIN_SIMCLK		107
+#define BCM21664_PIN_SIMDAT		108
+#define BCM21664_PIN_SIMDET		109
+#define BCM21664_PIN_SIMRST		110
+#define BCM21664_PIN_GPIO93		111
+#define BCM21664_PIN_GPIO94		112
+#define BCM21664_PIN_SPI0CLK		113
+#define BCM21664_PIN_SPI0FSS		114
+#define BCM21664_PIN_SPI0RXD		115
+#define BCM21664_PIN_SPI0TXD		116
+#define BCM21664_PIN_SRI_C		117
+#define BCM21664_PIN_SRI_D		118
+#define BCM21664_PIN_SRI_E		119
+#define BCM21664_PIN_SSPCK		120
+#define BCM21664_PIN_SSPDI		121
+#define BCM21664_PIN_SSPDO		122
+#define BCM21664_PIN_SSPSYN		123
+#define BCM21664_PIN_STAT1		124
+#define BCM21664_PIN_STAT2		125
+#define BCM21664_PIN_SWCLKTCK		126
+#define BCM21664_PIN_SWDIOTMS		127
+#define BCM21664_PIN_SYSCLKEN		128
+#define BCM21664_PIN_TDI		129
+#define BCM21664_PIN_TDO		130
+#define BCM21664_PIN_TESTMODE		131
+#define BCM21664_PIN_TRACECLK		132
+#define BCM21664_PIN_TRACEDT00		133
+#define BCM21664_PIN_TRACEDT01		134
+#define BCM21664_PIN_TRACEDT02		135
+#define BCM21664_PIN_TRACEDT03		136
+#define BCM21664_PIN_TRACEDT04		137
+#define BCM21664_PIN_TRACEDT05		138
+#define BCM21664_PIN_TRACEDT06		139
+#define BCM21664_PIN_TRACEDT07		140
+#define BCM21664_PIN_TRSTB		141
+#define BCM21664_PIN_TXDATA3G0		142
+#define BCM21664_PIN_UBCTSN		143
+#define BCM21664_PIN_UBRTSN		144
+#define BCM21664_PIN_UBRX		145
+#define BCM21664_PIN_UBTX		146
+#define BCM21664_PIN_TRACEDT08		147
+#define BCM21664_PIN_TRACEDT09		148
+#define BCM21664_PIN_TRACEDT10		149
+#define BCM21664_PIN_TRACEDT11		150
+#define BCM21664_PIN_TRACEDT12		151
+#define BCM21664_PIN_TRACEDT13		152
+#define BCM21664_PIN_TRACEDT14		153
+#define BCM21664_PIN_TRACEDT15		154
+
+static const struct pinctrl_pin_desc bcm21664_pinctrl_pins[] = {
+	BCM281XX_PIN_DESC(BCM21664_PIN_ADCSYN, "adcsyn", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_BATRM, "batrm", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_BSC1CLK, "bsc1clk", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_BSC1DAT, "bsc1dat", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_CAMCS0, "camcs0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_CAMCS1, "camcs1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_CLK32K, "clk32k", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_CLK_CX8, "clk_cx8", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DCLK1, "dclk1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DCLK4, "dclk4", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DCLKREQ1, "dclkreq1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DCLKREQ4, "dclkreq4", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DMIC0CLK, "dmic0clk", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DMIC0DQ, "dmic0dq", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_DSI0TE, "dsi0te", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO00, "gpio00", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO01, "gpio01", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO02, "gpio02", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO03, "gpio03", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO04, "gpio04", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO05, "gpio05", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO06, "gpio06", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO07, "gpio07", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO08, "gpio08", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO09, "gpio09", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO10, "gpio10", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO11, "gpio11", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO12, "gpio12", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO13, "gpio13", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO14, "gpio14", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO15, "gpio15", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO16, "gpio16", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO17, "gpio17", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO18, "gpio18", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO19, "gpio19", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO20, "gpio20", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO21, "gpio21", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO22, "gpio22", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO23, "gpio23", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO24, "gpio24", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO25, "gpio25", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO26, "gpio26", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO27, "gpio27", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO28, "gpio28", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO32, "gpio32", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO33, "gpio33", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO34, "gpio34", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPS_CALREQ, "gps_calreq", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPS_HOSTREQ, "gps_hostreq", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPS_PABLANK, "gps_pablank", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPS_TMARK, "gps_tmark", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_ICUSBDM, "icusbdm", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_ICUSBDP, "icusbdp", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_LCDCS0, "lcdcs0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_LCDRES, "lcdres", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_LCDSCL, "lcdscl", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_LCDSDA, "lcdsda", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_LCDTE, "lcdte", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO00, "mdmgpio00", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO01, "mdmgpio01", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO02, "mdmgpio02", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO03, "mdmgpio03", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO04, "mdmgpio04", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO05, "mdmgpio05", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO06, "mdmgpio06", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO07, "mdmgpio07", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MDMGPIO08, "mdmgpio08", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0CK, "mmc0ck", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0CMD, "mmc0cmd", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT0, "mmc0dat0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT1, "mmc0dat1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT2, "mmc0dat2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT3, "mmc0dat3", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT4, "mmc0dat4", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT5, "mmc0dat5", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT6, "mmc0dat6", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0DAT7, "mmc0dat7", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC0RST, "mmc0rst", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1CK, "mmc1ck", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1CMD, "mmc1cmd", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT0, "mmc1dat0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT1, "mmc1dat1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT2, "mmc1dat2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT3, "mmc1dat3", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT4, "mmc1dat4", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT5, "mmc1dat5", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT6, "mmc1dat6", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1DAT7, "mmc1dat7", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_MMC1RST, "mmc1rst", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_PC1, "pc1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_PC2, "pc2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_PMBSCCLK, "pmbscclk", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_PMBSCDAT, "pmbscdat", i2c),
+	BCM281XX_PIN_DESC(BCM21664_PIN_PMUINT, "pmuint", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RESETN, "resetn", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RTXDATA2G_TXDATA3G1, "rtxdata2g_txdata3g1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RXDATA3G0, "rxdata3g0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RXDATA3G1, "rxdata3g1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_RXDATA3G2, "rxdata3g2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDCK, "sdck", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDCMD, "sdcmd", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDDAT0, "sddat0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDDAT1, "sddat1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDDAT2, "sddat2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SDDAT3, "sddat3", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SIMCLK, "simclk", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SIMDAT, "simdat", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SIMDET, "simdet", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SIMRST, "simrst", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO93, "gpio93", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_GPIO94, "gpio94", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SPI0CLK, "spi0clk", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SPI0FSS, "spi0fss", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SPI0RXD, "spi0rxd", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SPI0TXD, "spi0txd", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SRI_C, "sri_c", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SRI_D, "sri_d", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SRI_E, "sri_e", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SSPCK, "sspck", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SSPDI, "sspdi", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SSPDO, "sspdo", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SSPSYN, "sspsyn", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_STAT1, "stat1", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_STAT2, "stat2", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SWCLKTCK, "swclktck", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SWDIOTMS, "swdiotms", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_SYSCLKEN, "sysclken", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TDI, "tdi", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TDO, "tdo", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TESTMODE, "testmode", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACECLK, "traceclk", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT00, "tracedt00", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT01, "tracedt01", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT02, "tracedt02", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT03, "tracedt03", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT04, "tracedt04", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT05, "tracedt05", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT06, "tracedt06", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT07, "tracedt07", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRSTB, "trstb", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TXDATA3G0, "txdata3g0", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_UBCTSN, "ubctsn", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_UBRTSN, "ubrtsn", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_UBRX, "ubrx", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_UBTX, "ubtx", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT08, "tracedt08", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT09, "tracedt09", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT10, "tracedt10", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT11, "tracedt11", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT12, "tracedt12", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT13, "tracedt13", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT14, "tracedt14", std),
+	BCM281XX_PIN_DESC(BCM21664_PIN_TRACEDT15, "tracedt15", std),
+};
+
+static const char * const bcm21664_alt_groups[] = {
+	"adcsyn",
+	"batrm",
+	"bsc1clk",
+	"bsc1dat",
+	"camcs0",
+	"camcs1",
+	"clk32k",
+	"clk_cx8",
+	"dclk1",
+	"dclk4",
+	"dclkreq1",
+	"dclkreq4",
+	"dmic0clk",
+	"dmic0dq",
+	"dsi0te",
+	"gpio00",
+	"gpio01",
+	"gpio02",
+	"gpio03",
+	"gpio04",
+	"gpio05",
+	"gpio06",
+	"gpio07",
+	"gpio08",
+	"gpio09",
+	"gpio10",
+	"gpio11",
+	"gpio12",
+	"gpio13",
+	"gpio14",
+	"gpio15",
+	"gpio16",
+	"gpio17",
+	"gpio18",
+	"gpio19",
+	"gpio20",
+	"gpio21",
+	"gpio22",
+	"gpio23",
+	"gpio24",
+	"gpio25",
+	"gpio26",
+	"gpio27",
+	"gpio28",
+	"gpio32",
+	"gpio33",
+	"gpio34",
+	"gps_calreq",
+	"gps_hostreq",
+	"gps_pablank",
+	"gps_tmark",
+	"icusbdm",
+	"icusbdp",
+	"lcdcs0",
+	"lcdres",
+	"lcdscl",
+	"lcdsda",
+	"lcdte",
+	"mdmgpio00",
+	"mdmgpio01",
+	"mdmgpio02",
+	"mdmgpio03",
+	"mdmgpio04",
+	"mdmgpio05",
+	"mdmgpio06",
+	"mdmgpio07",
+	"mdmgpio08",
+	"mmc0ck",
+	"mmc0cmd",
+	"mmc0dat0",
+	"mmc0dat1",
+	"mmc0dat2",
+	"mmc0dat3",
+	"mmc0dat4",
+	"mmc0dat5",
+	"mmc0dat6",
+	"mmc0dat7",
+	"mmc0rst",
+	"mmc1ck",
+	"mmc1cmd",
+	"mmc1dat0",
+	"mmc1dat1",
+	"mmc1dat2",
+	"mmc1dat3",
+	"mmc1dat4",
+	"mmc1dat5",
+	"mmc1dat6",
+	"mmc1dat7",
+	"mmc1rst",
+	"pc1",
+	"pc2",
+	"pmbscclk",
+	"pmbscdat",
+	"pmuint",
+	"resetn",
+	"rfst2g_mtsloten3g",
+	"rtxdata2g_txdata3g1",
+	"rtxen2g_txdata3g2",
+	"rxdata3g0",
+	"rxdata3g1",
+	"rxdata3g2",
+	"sdck",
+	"sdcmd",
+	"sddat0",
+	"sddat1",
+	"sddat2",
+	"sddat3",
+	"simclk",
+	"simdat",
+	"simdet",
+	"simrst",
+	"gpio93",
+	"gpio94",
+	"spi0clk",
+	"spi0fss",
+	"spi0rxd",
+	"spi0txd",
+	"sri_c",
+	"sri_d",
+	"sri_e",
+	"sspck",
+	"sspdi",
+	"sspdo",
+	"sspsyn",
+	"stat1",
+	"stat2",
+	"swclktck",
+	"swdiotms",
+	"sysclken",
+	"tdi",
+	"tdo",
+	"testmode",
+	"traceclk",
+	"tracedt00",
+	"tracedt01",
+	"tracedt02",
+	"tracedt03",
+	"tracedt04",
+	"tracedt05",
+	"tracedt06",
+	"tracedt07",
+	"trstb",
+	"txdata3g0",
+	"ubctsn",
+	"ubrtsn",
+	"ubrx",
+	"ubtx",
+	"tracedt08",
+	"tracedt09",
+	"tracedt10",
+	"tracedt11",
+	"tracedt12",
+	"tracedt13",
+	"tracedt14",
+	"tracedt15",
+};
+
+#define BCM21664_PIN_FUNCTION(fcn_name)			\
+{							\
+	.name = #fcn_name,				\
+	.groups = bcm21664_alt_groups,			\
+	.ngroups = ARRAY_SIZE(bcm21664_alt_groups),	\
+}
+
+static const struct bcm281xx_pin_function bcm21664_functions[] = {
+	BCM21664_PIN_FUNCTION(alt1),
+	BCM21664_PIN_FUNCTION(alt2),
+	BCM21664_PIN_FUNCTION(alt3),
+	BCM21664_PIN_FUNCTION(alt4),
+	BCM21664_PIN_FUNCTION(alt5),
+	BCM21664_PIN_FUNCTION(alt6),
+};
+
+static const struct regmap_config bcm21664_pinctrl_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = BCM21664_WR_ACCESS_OFFSET,
+};
+
+static const struct bcm281xx_pinctrl_info bcm21664_pinctrl = {
+	.device_type = BCM21664_PINCTRL_TYPE,
+
+	.pins = bcm21664_pinctrl_pins,
+	.npins = ARRAY_SIZE(bcm21664_pinctrl_pins),
+	.functions = bcm21664_functions,
+	.nfunctions = ARRAY_SIZE(bcm21664_functions),
+
+	.regmap_config = &bcm21664_pinctrl_regmap_config,
+};
+
+/* BCM21664 pinctrl access lock handlers */
+static int bcm21664_pinctrl_lock_all(struct bcm281xx_pinctrl_data *pdata)
+{
+	int i, rc;
+
+	for (i = 0; i < BCM21664_ACCESS_LOCK_COUNT; i++) {
+		rc = regmap_write(pdata->regmap, BCM21664_WR_ACCESS_OFFSET,
+				   BCM21664_WR_ACCESS_PASSWORD);
+		if (rc) {
+			dev_err(pdata->dev, "Failed to enable write access: %d\n",
+				rc);
+			return rc;
+		}
+		regmap_write(pdata->regmap, BCM21664_ACCESS_LOCK_OFFSET(i),
+			     0xffffffff);
+		if (rc) {
+			dev_err(pdata->dev, "Failed to write access lock: %d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int bcm21664_pinctrl_set_pin_lock(struct bcm281xx_pinctrl_data *pdata,
+					 unsigned int pin, bool lock)
+{
+	unsigned int access_lock = pin / 32;
+	int rc;
+
+	dev_dbg(pdata->dev,
+		"%s(): %s pin %s (%d)\n",
+		__func__, lock ? "Lock" : "Unlock", pdata->info->pins[pin].name,
+		pin);
+
+	rc = regmap_write(pdata->regmap, BCM21664_WR_ACCESS_OFFSET,
+			   BCM21664_WR_ACCESS_PASSWORD);
+	if (rc) {
+		dev_err(pdata->dev, "Failed to enable write access: %d\n",
+			rc);
+		return rc;
+	}
+
+	rc = regmap_update_bits(pdata->regmap,
+				BCM21664_ACCESS_LOCK_OFFSET(access_lock),
+				BIT(pin % 32),
+				(int)lock << (pin % 32));
+
+	if (rc) {
+		dev_err(pdata->dev, "Failed to %s pin: %d\n",
+			lock ? "lock" : "unlock", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
 						  unsigned int pin)
 {
@@ -1079,6 +1651,7 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
 	const struct bcm281xx_pin_function *f = &pdata->info->functions[function];
+	enum bcm281xx_pinctrl_type device_type = pdata->info->device_type;
 	unsigned int pin = pdata->info->pins[group].number;
 	u32 offset = 4 * pin;
 	int rc = 0;
@@ -1088,6 +1661,14 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
 		__func__, f->name, function, pdata->info->pins[group].name,
 		pin, offset);
 
+	if (device_type == BCM21664_PINCTRL_TYPE) {
+		rc = bcm21664_pinctrl_set_pin_lock(pdata, pin, false);
+		if (rc) {
+			/* Error is printed in bcm21664_pinctrl_set_pin_lock */
+			return rc;
+		}
+	}
+
 	rc = regmap_update_bits(pdata->regmap, offset,
 		BCM281XX_PIN_REG_F_SEL_MASK,
 		function << BCM281XX_PIN_REG_F_SEL_SHIFT);
@@ -1096,6 +1677,14 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
 			"Error updating register for pin %s (%d).\n",
 			pdata->info->pins[group].name, pin);
 
+	if (device_type == BCM21664_PINCTRL_TYPE) {
+		rc = bcm21664_pinctrl_set_pin_lock(pdata, pin, true);
+		if (rc) {
+			/* Error is printed in bcm21664_pinctrl_set_pin_lock */
+			return rc;
+		}
+	}
+
 	return rc;
 }
 
@@ -1300,6 +1889,68 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
+/* Goes through the configs and update register val/mask */
+static int bcm21664_i2c_pin_update(struct pinctrl_dev *pctldev,
+				   unsigned int pin,
+				   unsigned long *configs,
+				   unsigned int num_configs,
+				   u32 *val,
+				   u32 *mask)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int i;
+	enum pin_config_param param;
+	u32 arg;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		/*
+		 * BCM21664 I2C pins use the same config bits as standard pins,
+		 * but only pull up/none, slew rate and input enable/disable
+		 * options are supported.
+		 */
+		switch (param) {
+		case PIN_CONFIG_BIAS_PULL_UP:
+			bcm281xx_pin_update(val, mask, 1,
+				BCM281XX_PIN_SHIFT(STD, PULL_UP),
+				BCM281XX_PIN_MASK(STD, PULL_UP));
+		break;
+
+		case PIN_CONFIG_BIAS_DISABLE:
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(STD, PULL_UP),
+				BCM281XX_PIN_MASK(STD, PULL_UP));
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			arg = (arg >= 1 ? 1 : 0);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(STD, SLEW),
+				BCM281XX_PIN_MASK(STD, SLEW));
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			/* inversed since register is for input _disable_ */
+			arg = (arg >= 1 ? 0 : 1);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(STD, INPUT_DIS),
+				BCM281XX_PIN_MASK(STD, INPUT_DIS));
+			break;
+
+		default:
+			dev_err(pctldev->dev,
+				"Unrecognized pin config %d for pin %s (%d).\n",
+				param, pdata->info->pins[pin].name, pin);
+			return -EINVAL;
+
+		} /* switch config */
+	} /* for each config */
+
+	return 0;
+}
+
 /* Goes through the configs and update register val/mask */
 static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
 				    unsigned int pin,
@@ -1351,6 +2002,7 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 					   unsigned int num_configs)
 {
 	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	enum bcm281xx_pinctrl_type device_type = pdata->info->device_type;
 	enum bcm281xx_pin_type pin_type;
 	u32 offset = 4 * pin;
 	u32 cfg_val, cfg_mask;
@@ -1368,8 +2020,12 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 		break;
 
 	case BCM281XX_PIN_TYPE_I2C:
-		rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
-			num_configs, &cfg_val, &cfg_mask);
+		if (device_type == BCM21664_PINCTRL_TYPE)
+			rc = bcm21664_i2c_pin_update(pctldev, pin, configs,
+				num_configs, &cfg_val, &cfg_mask);
+		else
+			rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
+				num_configs, &cfg_val, &cfg_mask);
 		break;
 
 	case BCM281XX_PIN_TYPE_HDMI:
@@ -1391,6 +2047,14 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 		"%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
 		__func__, pdata->info->pins[pin].name, pin, cfg_val, cfg_mask);
 
+	if (device_type == BCM21664_PINCTRL_TYPE) {
+		rc = bcm21664_pinctrl_set_pin_lock(pdata, pin, false);
+		if (rc) {
+			/* Error is printed in bcm21664_pinctrl_set_pin_lock */
+			return rc;
+		}
+	}
+
 	rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
 	if (rc) {
 		dev_err(pctldev->dev,
@@ -1399,6 +2063,14 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
 		return rc;
 	}
 
+	if (device_type == BCM21664_PINCTRL_TYPE) {
+		rc = bcm21664_pinctrl_set_pin_lock(pdata, pin, true);
+		if (rc) {
+			/* Error is printed in bcm21664_pinctrl_set_pin_lock */
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -1421,6 +2093,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 {
 	struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl_pdata;
 	struct pinctrl_dev *pctl;
+	int rc;
 
 	/* Set device pointer in platform data */
 	pdata->dev = &pdev->dev;
@@ -1451,6 +2124,18 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 	bcm281xx_pinctrl_desc.pins = pdata->info->pins;
 	bcm281xx_pinctrl_desc.npins = pdata->info->npins;
 
+	/*
+	 * For BCM21664, lock all pins by default; they will be unlocked
+	 * as needed
+	 */
+	if (pdata->info->device_type == BCM21664_PINCTRL_TYPE) {
+		rc = bcm21664_pinctrl_lock_all(pdata);
+		if (rc) {
+			dev_err(&pdev->dev, "Failed to lock all pins\n");
+			return rc;
+		}
+	}
+
 	pctl = devm_pinctrl_register(&pdev->dev, &bcm281xx_pinctrl_desc, pdata);
 	if (IS_ERR(pctl)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
@@ -1464,6 +2149,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 
 static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
 	{ .compatible = "brcm,bcm11351-pinctrl", .data = &bcm281xx_pinctrl },
+	{ .compatible = "brcm,bcm21664-pinctrl", .data = &bcm21664_pinctrl },
 	{ },
 };
 

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:50 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:50 +0100
Subject: [PATCH v3 5/6] ARM: dts: bcm2166x-common: Add pinctrl node
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-5-5f8b80e4ab51@gmail.com>

Now that the pinctrl driver supports the BCM21664, add a node for
pinctrl in the DTS to allow for controlling pinmux pins.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
 arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
index 87180b7fd695e65b52c52743e6315cbcca385fba..d4b412ac8b0343bd3773f50c59a20fa00a3923f8 100644
--- a/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
@@ -46,6 +46,11 @@ gpio: gpio at 1003000 {
 			interrupt-controller;
 		};
 
+		pinctrl: pinctrl at 1004800 {
+			compatible = "brcm,bcm21664-pinctrl";
+			reg = <0x01004800 0x7f4>;
+		};
+
 		timer at 1006000 {
 			compatible = "brcm,kona-timer";
 			reg = <0x01006000 0x1c>;

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 12:54:51 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Mon, 03 Mar 2025 21:54:51 +0100
Subject: [PATCH v3 6/6] ARM: dts: bcm2166x: Add bcm2166x-pinctrl DTSI
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <20250303-bcm21664-pinctrl-v3-6-5f8b80e4ab51@gmail.com>

Add common DTSI with common pin control configs for BCM21664/BCM23550
and include it in bcm2166x-common.dtsi. The configs are kept in a
separate DTSI to keep things cleaner (pin config definitions take up
quite a lot of space).

Currently contains pins for BSC buses and SD/MMC; more pins can be
added in the future.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
 arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi  |   2 +
 arch/arm/boot/dts/broadcom/bcm2166x-pinctrl.dtsi | 297 +++++++++++++++++++++++
 2 files changed, 299 insertions(+)

diff --git a/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
index d4b412ac8b0343bd3773f50c59a20fa00a3923f8..f535212cb52fec0668abfc06e7268bead70d958a 100644
--- a/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi
@@ -337,3 +337,5 @@ master_ccu: master_ccu at 3f001000 {
 		};
 	};
 };
+
+#include "bcm2166x-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/broadcom/bcm2166x-pinctrl.dtsi b/arch/arm/boot/dts/broadcom/bcm2166x-pinctrl.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..51b8730c8feea501f2c5ca6a7bad8233ed708c82
--- /dev/null
+++ b/arch/arm/boot/dts/broadcom/bcm2166x-pinctrl.dtsi
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Common pinmux configrations for BCM2166x (BCM21664/BCM23550).
+ *
+ * Copyright (C) 2025 Artur Weber <aweber.kernel at gmail.com>
+ */
+
+&pinctrl {
+	/* BSC1 */
+	bsc1_pins: bsc1-pins {
+		bsc1clk-grp0 {
+			pins = "bsc1clk";
+			function = "alt1"; /* BSC1CLK */
+		};
+
+		bsc1dat-grp0 {
+			pins = "bsc1dat";
+			function = "alt1"; /* BSC1DAT */
+		};
+	};
+
+	/* BSC2 */
+	bsc2_pins: bsc2-pins {
+		bsc2clk-grp0 {
+			pins = "gpio16";
+			function = "alt2"; /* BSC2CLK */
+		};
+
+		bsc2dat-grp0 {
+			pins = "gpio17";
+			function = "alt2"; /* BSC2DAT */
+		};
+	};
+
+	/* BSC3 */
+	bsc3_pins: bsc3-pins {
+		bsc3clk-grp0 {
+			pins = "lcdscl";
+			function = "alt1"; /* BSC3_CLK */
+		};
+
+		bsc3dat-grp0 {
+			pins = "lcdsda";
+			function = "alt1"; /* BSC3_SDA */
+		};
+	};
+
+	/* BSC4 */
+	bsc4_pins: bsc4-pins {
+		bsc4clk-grp0 {
+			pins = "lcdres";
+			function = "alt1"; /* BSC4_CLK */
+		};
+
+		bsc4dat-grp0 {
+			pins = "lcdte";
+			function = "alt1"; /* BSC4_SDA */
+		};
+	};
+
+	/* PMBSC */
+	pmbsc_pins: pmbsc-pins {
+		pmbscclk-grp0 {
+			pins = "pmbscclk";
+			function = "alt1"; /* PMBSCCLK */
+		};
+
+		pmbscdat-grp0 {
+			pins = "pmbscdat";
+			function = "alt1"; /* PMBSCDAT */
+		};
+	};
+
+	/* SD */
+	sd_width1_pins: sd-width1-pins {
+		sdck-grp0 {
+			pins = "sdck";
+			function = "alt1"; /* SDCK */
+			bias-disable;
+		};
+
+		sdcmd-grp0 {
+			pins = "sdcmd";
+			function = "alt1"; /* SDCMD */
+			bias-pull-up;
+		};
+
+		sddat-grp0 {
+			pins = "sddat0";
+			function = "alt1"; /* SDDATx */
+			bias-pull-up;
+		};
+	};
+
+	sd_width4_pins: sd-width4-pins {
+		sdck-grp0 {
+			pins = "sdck";
+			function = "alt1"; /* SDCK */
+			bias-disable;
+		};
+
+		sdcmd-grp0 {
+			pins = "sdcmd";
+			function = "alt1"; /* SDCMD */
+			bias-pull-up;
+		};
+
+		sddat-grp0 {
+			pins = "sddat0", "sddat1", "sddat2", "sddat3";
+			function = "alt1"; /* SDDATx */
+			bias-pull-up;
+		};
+	};
+
+	/* SD1 */
+	sd1_width1_pins: sd1-width1-pins {
+		sd1ck-grp0 {
+			pins = "mmc1dat7";
+			function = "alt6"; /* SD1CK */
+			bias-disable;
+		};
+
+		sd1cmd-grp0 {
+			pins = "spi0txd";
+			function = "alt2"; /* SD1CMD */
+			bias-pull-up;
+		};
+
+		sd1dat0-grp0 {
+			pins = "mmc1dat5";
+			function = "alt6"; /* SD1DAT0 */
+			bias-pull-up;
+		};
+	};
+
+	sd1_width4_pins: sd1-width4-pins {
+		sd1ck-grp0 {
+			pins = "mmc1dat7";
+			function = "alt6"; /* SD1CK */
+			bias-disable;
+		};
+
+		sd1cmd-grp0 {
+			pins = "spi0txd";
+			function = "alt2"; /* SD1CMD */
+			bias-pull-up;
+		};
+
+		sd1dat0-grp0 {
+			pins = "mmc1dat5";
+			function = "alt6"; /* SD1DAT0 */
+			bias-pull-up;
+		};
+
+		sd1dat1-grp0 {
+			pins = "gpio93";
+			function = "alt1"; /* SD1DAT1 */
+			bias-pull-up;
+		};
+
+		sd1dat2-grp0 {
+			pins = "gpio94";
+			function = "alt1"; /* SD1DAT2 */
+			bias-pull-up;
+		};
+
+		sd1dat3-grp0 {
+			pins = "mmc1dat3";
+			function = "alt6"; /* SD1DAT3 */
+			bias-pull-up;
+		};
+	};
+
+	/* MMC0 */
+	mmc0_width1_pins: mmc0-width1-pins {
+		mmc0ck-grp0 {
+			pins = "mmc0ck";
+			function = "alt1"; /* MMC0CK */
+			bias-disable;
+		};
+
+		mmc0cmd-grp0 {
+			pins = "mmc0cmd";
+			function = "alt1"; /* MMC0CMD */
+			bias-pull-up;
+		};
+
+		mmc0dat-grp0 {
+			pins = "mmc0dat0";
+			function = "alt1"; /* MMC0DATx */
+			bias-pull-up;
+		};
+	};
+
+	mmc0_width4_pins: mmc0-width4-pins {
+		mmc0ck-grp0 {
+			pins = "mmc0ck";
+			function = "alt1"; /* MMC0CK */
+			bias-disable;
+		};
+
+		mmc0cmd-grp0 {
+			pins = "mmc0cmd";
+			function = "alt1"; /* MMC0CMD */
+			bias-pull-up;
+		};
+
+		mmc0dat-grp0 {
+			pins = "mmc0dat0", "mmc0dat1", "mmc0dat2", "mmc0dat3";
+			function = "alt1"; /* MMC0DATx */
+			bias-pull-up;
+		};
+	};
+
+	mmc0_width8_pins: mmc0-width8-pins {
+		mmc0ck-grp0 {
+			pins = "mmc0ck";
+			function = "alt1"; /* MMC0CK */
+			bias-disable;
+		};
+
+		mmc0cmd-grp0 {
+			pins = "mmc0cmd";
+			function = "alt1"; /* MMC0CMD */
+			bias-pull-up;
+		};
+
+		mmc0dat-grp0 {
+			pins = "mmc0dat0", "mmc0dat1", "mmc0dat2", "mmc0dat3",
+			       "mmc0dat4", "mmc0dat5", "mmc0dat6", "mmc0dat7";
+			function = "alt1"; /* MMC0DATx */
+			bias-pull-up;
+		};
+	};
+
+	/* MMC1 */
+	mmc1_width1_pins: mmc1-width1-pins {
+		mmc1ck-grp0 {
+			pins = "mmc1ck";
+			function = "alt1"; /* MMC1CK */
+			bias-disable;
+		};
+
+		mmc1cmd-grp0 {
+			pins = "mmc1cmd";
+			function = "alt1"; /* MMC1CMD */
+			bias-pull-up;
+		};
+
+		mmc1dat-grp0 {
+			pins = "mmc1dat0";
+			function = "alt1"; /* MMC1DATx */
+			bias-pull-up;
+		};
+	};
+
+	mmc1_width4_pins: mmc1-width4-pins {
+		mmc1ck-grp0 {
+			pins = "mmc1ck";
+			function = "alt1"; /* MMC1CK */
+			bias-disable;
+		};
+
+		mmc1cmd-grp0 {
+			pins = "mmc1cmd";
+			function = "alt1"; /* MMC1CMD */
+			bias-pull-up;
+		};
+
+		mmc1dat-grp0 {
+			pins = "mmc1dat0", "mmc1dat1", "mmc1dat2", "mmc1dat3";
+			function = "alt1"; /* MMC1DATx */
+			bias-pull-up;
+		};
+	};
+
+	mmc1_width8_pins: mmc1-width8-pins {
+		mmc1ck-grp0 {
+			pins = "mmc1ck";
+			function = "alt1"; /* MMC1CK */
+			bias-disable;
+		};
+
+		mmc1cmd-grp0 {
+			pins = "mmc1cmd";
+			function = "alt1"; /* MMC1CMD */
+			bias-pull-up;
+		};
+
+		mmc1dat-grp0 {
+			pins = "mmc1dat0", "mmc1dat1", "mmc1dat2", "mmc1dat3",
+			       "mmc1dat4", "mmc1dat5", "mmc1dat6", "mmc1dat7";
+			function = "alt1"; /* MMC1DATx */
+			bias-pull-up;
+		};
+	};
+};

-- 
2.48.1



From namhyung at kernel.org  Mon Mar  3 13:00:19 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 3 Mar 2025 13:00:19 -0800
Subject: [PATCH v3 00/12] perf script: Refactor branch flags for Arm SPE
In-Reply-To: <20250303093853.GG2157064@e132581.arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250303093853.GG2157064@e132581.arm.com>
Message-ID: <Z8YYY2Q_ZPIaZ74g@google.com>

On Mon, Mar 03, 2025 at 09:38:53AM +0000, Leo Yan wrote:
> Hi Arnaldo, Namhyung,
> 
> On Mon, Feb 17, 2025 at 07:58:56PM +0000, Leo Yan wrote:
> > This patch series refactors branch flags for support Arm SPE.  The patch
> > set is divided into two parts, the first part is for refactoring common
> > code and the second part is for enabling Arm SPE.
> 
> James has given review tags (including the new added patch 06).  Could
> you kindly pick up this series?
> 
> Sorry for pushing a bit, as we have dependency on it.

No problem, I'll add it to the tmp branch and run some tests.

Thanks,
Namhyung



From nifan.cxl at gmail.com  Mon Mar  3 13:03:12 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Mon, 3 Mar 2025 13:03:12 -0800
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <20250303194228.GB1552306@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
 <20250221131548.59616-6-shradha.t@samsung.com>
 <Z8XuuNb6TRevUlHH@debian>
 <20250303194228.GB1552306@rocinante>
Message-ID: <Z8YZEALV71PUkXpF@debian>

On Tue, Mar 04, 2025 at 04:42:28AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> [...]
> > > +static ssize_t counter_value_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
> > > +{
> > > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > > +	struct dw_pcie *pci = pdata->pci;
> > > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > > +	ssize_t pos;
> > > +	u32 val;
> > > +
> > > +	mutex_lock(&rinfo->reg_event_lock);
> > > +	set_event_number(pdata, pci, rinfo);
> > > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > > +	mutex_unlock(&rinfo->reg_event_lock);
> > > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter value: %d\n", val);
> > > +
> > > +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf, pos);
> > > +}
> > 
> > Do we need to check whether the counter is enabled or not for the event
> > before retrieving the counter value?
> 
> I believe, we have a patch that aims to address, have a look at:
> 
>   https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivannan.sadhasivam at linaro.org

Maybe I missed something, that seems to fix counter_enable_read(), but
here is to retrieve counter value. 
How dw_pcie_readl_dbi() can return something like "Counter Disabled"? 

Fan
> 
> Thank you!
> 
> 	Krzysztof


From didi.debian at cknow.org  Mon Mar  3 13:06:04 2025
From: didi.debian at cknow.org (Diederik de Haas)
Date: Mon, 03 Mar 2025 22:06:04 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add missing PCIe supplies
 to RockPro64 board dtsi
In-Reply-To: <b39cfd7490d8194f053bf3971f13a43472d1769e.1740941097.git.dsimic@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <b39cfd7490d8194f053bf3971f13a43472d1769e.1740941097.git.dsimic@manjaro.org>
Message-ID: <D86XQOCG7LJH.3NI330ETDBP5Z@cknow.org>

Hi Dragan,

On Sun Mar 2, 2025 at 7:48 PM CET, Dragan Simic wrote:
> Add missing "vpcie0v9-supply" and "vpcie1v8-supply" properties to the "pcie0"
> node in the Pine64 RockPro64 board dtsi file.  This eliminates the following
> warnings from the kernel log:
>
>   rockchip-pcie f8000000.pcie: supply vpcie1v8 not found, using dummy regulator
>   rockchip-pcie f8000000.pcie: supply vpcie0v9 not found, using dummy regulator
>
> These additions improve the accuracy of hardware description of the RockPro64
> and, in theory, they should result in no functional changes to the way board
> works after the changes, because the "vcca_0v9" and "vcca_1v8" regulators are
> always enabled. [1][2]  However, extended reliability testing, performed by
> Chris, [3] has proven that the age-old issues with some PCI Express cards,
> when used with a Pine64 RockPro64, are also resolved.

Thanks for this patch :-)

I 'reported' the issue based on the logs I saw from other people, but
now that I have a RockPro64 (version 2.1) myself, I can confirm that
without this patch I saw those warnings myself.

When booted up without a PCIe card in the slot, I also saw these errors:
[    5.106650] rockchip-pcie f8000000.pcie: PCIe link training gen1 timeout!
[    5.107373] rockchip-pcie f8000000.pcie: probe with driver rockchip-pcie failed with error -110

You indicated that that was due to there being no PCIe card inserted.

After applying this patch I booted up my RockPro64 and found that the
above mentioned warnings are indeed gone.

Then I inserted a Renesas Electronics Corp. uPD720201 USB 3.0 Host
Controller in the PCIe slot and booted up.
The above mentioned errors were indeed gone.
Furthermore ``lspci`` showed that card and when I plugged in an USB 3
drive in one of the ports, it was correctly detected and I could mount
the partition on my system. So feel free to include:

Tested-by: Diederik de Haas <didi.debian at cknow.org>

Cheers,
  Diederik

> Those issues were already mentioned in the commit 43853e843aa6 (arm64: dts:
> rockchip: Remove unsupported node from the Pinebook Pro dts, 2024-04-01),
> together with a brief description of the out-of-tree enumeration delay patch
> that reportedly resolves those issues.  In a nutshell, booting a RockPro64
> with some PCI Express cards attached to it caused a kernel oops. [4]
>
> Symptomatically enough, to the commit author's best knowledge, only the Pine64
> RockPro64, out of all RK3399-based boards and devices supported upstream, has
> been reported to suffer from those PCI Express issues, and only the RockPro64
> had some of the PCI Express supplies missing in its DT.  Thus, perhaps some
> weird timing issues exist that caused the "vcca_1v8" always-on regulator,
> which is part of the RK808 PMIC, to actually not be enabled before the PCI
> Express is initialized and enumerated on the RockPro64, causing oopses with
> some PCIe cards, and the aforementioned enumeration delay patch [4] probably
> acted as just a workaround for the underlying timing issue.
>
> Admittedly, the Pine64 RockPro64 is a bit specific board by having a standard
> PCI Express slot, allowing use of various standard cards, but pretty much
> standard PCI Express cards have been attached to other RK3399 boards as well,
> and the commit author is unaware ot such issues reported for them.
>
> It's quite hard to be sure that the PCI Express issues are fully resolved by
> these additions to the DT, without some really extensive and time-consuming
> testing.  However, these additions to the DT can result in good things and
> improvements anyway, making them perfectly safe from the standpoint of being
> unable to do any harm or cause some unforeseen regressions.
>
> Shuffle and reorder the "vpcie*-supply" properties a bit, so they're sorted
> alphanumerically, which is a bit more logical and more useful than having
> these properties listed in their strict alphabetical order.
>
> These changes apply to the both supported hardware revisions of the Pine64
> RockPro64, i.e. to the production-run revisions 2.0 and 2.1. [1][2]
>
> [1] https://files.pine64.org/doc/rockpro64/rockpro64_v21-SCH.pdf
> [2] https://files.pine64.org/doc/rockpro64/rockpro64_v20-SCH.pdf
> [3] https://z9.de/hedgedoc/s/nF4d5G7rg#reboot-tests-for-PCIe-improvements
> [4] https://lore.kernel.org/lkml/20230509153912.515218-1-vincenzopalazzodev at gmail.com/T/#u
>
> Fixes: bba821f5479e ("arm64: dts: rockchip: add PCIe nodes on rk3399-rockpro64")
> Cc: stable at vger.kernel.org
> Cc: Vincenzo Palazzo <vincenzopalazzodev at gmail.com>
> Cc: Peter Geis <pgwipeout at gmail.com>
> Cc: Bjorn Helgaas <helgaas at kernel.org>
> Reported-by: Diederik de Haas <didi.debian at cknow.org>
> Tested-by: Chris Vogel <chris at z9.de>
> Signed-off-by: Dragan Simic <dsimic at manjaro.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> index 47dc198706c8..41ee381ff81f 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> @@ -673,8 +673,10 @@ &pcie0 {
>  	num-lanes = <4>;
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&pcie_perst>;
> -	vpcie12v-supply = <&vcc12v_dcin>;
> +	vpcie0v9-supply = <&vcca_0v9>;
> +	vpcie1v8-supply = <&vcca_1v8>;
>  	vpcie3v3-supply = <&vcc3v3_pcie>;
> +	vpcie12v-supply = <&vcc12v_dcin>;
>  	status = "okay";
>  };
>  

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/f8c7d830/attachment.sig>

From quic_eberman at quicinc.com  Mon Mar  3 13:08:33 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:33 -0800
Subject: [PATCH v9 4/5] arm64: dts: qcom: qcs6490-rb3gen2: Add PSCI
 SYSTEM_RESET2 types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-4-b2cf4a20feda@oss.qualcomm.com>

From: Elliot Berman <elliot.berman at oss.qualcomm.com>

qcs6490-rb3gen2 firmware supports vendor-defined SYSTEM_RESET2 types.
Describe the reset types: "bootloader" will cause device to reboot and
stop in the bootloader's fastboot mode. "edl" will cause device to
reboot into "emergency download mode", which permits loading images via
the Firehose protocol.

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
index 27695bd5422055123e43b4081964b91bf252f274..c14a36a79db93766d8719e05434bf4aaac4deec2 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
@@ -758,6 +758,13 @@ &pon_resin {
 	status = "okay";
 };
 
+&psci {
+	reset-types {
+		mode-bootloader = <0x10001 0x2>;
+		mode-edl = <0 0x1>;
+	};
+};
+
 &qupv3_id_0 {
 	status = "okay";
 };

-- 
2.34.1



From quic_eberman at quicinc.com  Mon Mar  3 13:08:29 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:29 -0800
Subject: [PATCH v9 0/5] Implement vendor resets for PSCI SYSTEM_RESET2
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>

The PSCI SYSTEM_RESET2 call allows vendor firmware to define additional
reset types which could be mapped to the reboot argument.

Setting up reboot on Qualcomm devices can be inconsistent from chipset
to chipset. Generally, there is a PMIC register that gets written to
decide the reboot type. There is also sometimes a cookie that can be
written to indicate that the bootloader should behave differently than a
regular boot. These knobs evolve over product generations and require
more drivers. Qualcomm firmwares are beginning to expose vendor
SYSTEM_RESET2 types to simplify driver requirements from Linux.

Add support in PSCI to statically wire reboot mode commands from
userspace to a vendor reset and cookie value using the device tree. The
DT bindings are similar to reboot mode framework except that 2
integers are accepted (the type and cookie). Also, reboot mode framework
is intended to program the cookies, but not actually reboot the host.
PSCI SYSTEM_RESET2 does both. I've not added support for reading ACPI
tables since I don't have any device which provides them + firmware that
supports vendor SYSTEM_RESET2 types.

Previous discussions around SYSTEM_RESET2:
- https://lore.kernel.org/lkml/20230724223057.1208122-2-quic_eberman at quicinc.com/T/
- https://lore.kernel.org/all/4a679542-b48d-7e11-f33a-63535a5c68cb at quicinc.com/

Signed-off-by: Elliot Berman <quic_eberman at quicinc.com>

Changes in v9:
- Don't fallback to architecturally defined resets from Lorenzo.
- Link to v8: https://lore.kernel.org/r/20241107-arm-psci-system_reset2-vendor-reboots-v8-0-e8715fa65cb5 at quicinc.com

Changes in v8:
- Code style nits from Stephen
- Add rb3gen2
- Link to v7: https://lore.kernel.org/r/20241028-arm-psci-system_reset2-vendor-reboots-v7-0-a4c40b0ebc54 at quicinc.com

Changes in v7:
- Code style nits from Stephen
- Dropped unnecessary hunk from the sa8775p-ride patch
- Link to v6: https://lore.kernel.org/r/20241018-arm-psci-system_reset2-vendor-reboots-v6-0-50cbe88b0a24 at quicinc.com

Changes in v6:
- Rebase to v6.11 and fix trivial conflicts in qcm6490-idp
- Add sa8775p-ride support (same as qcm6490-idp)
- Link to v5: https://lore.kernel.org/r/20240617-arm-psci-system_reset2-vendor-reboots-v5-0-086950f650c8 at quicinc.com

Changes in v5:
- Drop the nested "items" in prep for future dtschema tools
- Link to v4: https://lore.kernel.org/r/20240611-arm-psci-system_reset2-vendor-reboots-v4-0-98f55aa74ae8 at quicinc.com

Changes in v4:
- Change mode- properties from uint32-matrix to uint32-array
- Restructure the reset-types node so only the restriction is in the
  if/then schemas and not the entire definition
- Link to v3: https://lore.kernel.org/r/20240515-arm-psci-system_reset2-vendor-reboots-v3-0-16dd4f9c0ab4 at quicinc.com

Changes in v3:
- Limit outer number of items to 1 for mode-* properties
- Move the reboot-mode for psci under a subnode "reset-types"
- Fix the DT node in qcm6490-idp so it doesn't overwrite the one from
  sc7820.dtsi
- Link to v2: https://lore.kernel.org/r/20240414-arm-psci-system_reset2-vendor-reboots-v2-0-da9a055a648f at quicinc.com

Changes in v2:
- Fixes to schema as suggested by Rob and Krzysztof
- Add qcm6490 idp as first Qualcomm device to support
- Link to v1: https://lore.kernel.org/r/20231117-arm-psci-system_reset2-vendor-reboots-v1-0-03c4612153e2 at quicinc.com

Changes in v1:
- Reference reboot-mode bindings as suggeted by Rob.
- Link to RFC: https://lore.kernel.org/r/20231030-arm-psci-system_reset2-vendor-reboots-v1-0-dcdd63352ad1 at quicinc.com

---
Elliot Berman (5):
      dt-bindings: arm: Document reboot mode magic
      firmware: psci: Read and use vendor reset types
      arm64: dts: qcom: qcm6490-idp: Add PSCI SYSTEM_RESET2 types
      arm64: dts: qcom: qcs6490-rb3gen2: Add PSCI SYSTEM_RESET2 types
      arm64: dts: qcom: sa8775p-ride: Add PSCI SYSTEM_RESET2 types

 Documentation/devicetree/bindings/arm/psci.yaml |  43 ++++++++++
 arch/arm64/boot/dts/qcom/qcm6490-idp.dts        |   7 ++
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts    |   7 ++
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi      |   7 ++
 arch/arm64/boot/dts/qcom/sa8775p.dtsi           |   2 +-
 arch/arm64/boot/dts/qcom/sc7280.dtsi            |   2 +-
 drivers/firmware/psci/psci.c                    | 105 ++++++++++++++++++++++++
 7 files changed, 171 insertions(+), 2 deletions(-)
---
base-commit: ffd294d346d185b70e28b1a28abe367bbfe53c04
change-id: 20231016-arm-psci-system_reset2-vendor-reboots-cc3ad456c070

Best regards,
-- 
Elliot Berman <elliot.berman at oss.qualcomm.com>



From quic_eberman at quicinc.com  Mon Mar  3 13:08:31 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:31 -0800
Subject: [PATCH v9 2/5] firmware: psci: Read and use vendor reset types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>

From: Elliot Berman <elliot.berman at oss.qualcomm.com>

SoC vendors have different types of resets and are controlled through
various registers. For instance, Qualcomm chipsets can reboot to a
"download mode" that allows a RAM dump to be collected. Another example
is they also support writing a cookie that can be read by bootloader
during next boot. PSCI offers a mechanism, SYSTEM_RESET2, for these
vendor reset types to be implemented without requiring drivers for every
register/cookie.

Add support in PSCI to statically map reboot mode commands from
userspace to a vendor reset and cookie value using the device tree.

A separate initcall is needed to parse the devicetree, instead of using
psci_dt_init because mm isn't sufficiently set up to allocate memory.

Reboot mode framework is close but doesn't quite fit with the
design and requirements for PSCI SYSTEM_RESET2. Some of these issues can
be solved but doesn't seem reasonable in sum:
 1. reboot mode registers against the reboot_notifier_list, which is too
    early to call SYSTEM_RESET2. PSCI would need to remember the reset
    type from the reboot-mode framework callback and use it
    psci_sys_reset.
 2. reboot mode assumes only one cookie/parameter is described in the
    device tree. SYSTEM_RESET2 uses 2: one for the type and one for
    cookie.
 3. psci cpuidle driver already registers a driver against the
    arm,psci-1.0 compatible. Refactoring would be needed to have both a
    cpuidle and reboot-mode driver.

Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
---
 drivers/firmware/psci/psci.c | 105 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index a1ebbe9b73b136218e9d9f9b8daa7756b3ab2fbe..6f8c47deaec0225f26704e1f3bcad52603127a85 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -80,6 +80,14 @@ static u32 psci_cpu_suspend_feature;
 static bool psci_system_reset2_supported;
 static bool psci_system_off2_hibernate_supported;
 
+struct psci_reset_param {
+	const char *mode;
+	u32 reset_type;
+	u32 cookie;
+};
+static struct psci_reset_param *psci_reset_params __ro_after_init;
+static size_t num_psci_reset_params __ro_after_init;
+
 static inline bool psci_has_ext_power_state(void)
 {
 	return psci_cpu_suspend_feature &
@@ -306,9 +314,39 @@ static int get_set_conduit_method(const struct device_node *np)
 	return 0;
 }
 
+static int psci_vendor_system_reset2(const char *cmd)
+{
+	unsigned long ret;
+	size_t i;
+
+	for (i = 0; i < num_psci_reset_params; i++) {
+		if (!strcmp(psci_reset_params[i].mode, cmd)) {
+			ret = invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2),
+					     psci_reset_params[i].reset_type,
+					     psci_reset_params[i].cookie, 0);
+			/*
+			 * if vendor reset fails, log it and fall back to
+			 * architecture reset types
+			 */
+			pr_err("failed to perform reset \"%s\": %ld\n", cmd,
+			       (long)ret);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
 static int psci_sys_reset(struct notifier_block *nb, unsigned long action,
 			  void *data)
 {
+	/*
+	 * try to do the vendor system_reset2
+	 * If there wasn't a matching command, fall back to architectural resets
+	 */
+	if (data && !psci_vendor_system_reset2(data))
+		return NOTIFY_DONE;
+
 	if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
 	    psci_system_reset2_supported) {
 		/*
@@ -795,6 +833,73 @@ static const struct of_device_id psci_of_match[] __initconst = {
 	{},
 };
 
+#define REBOOT_PREFIX "mode-"
+
+static int __init psci_init_system_reset2_modes(void)
+{
+	const size_t len = strlen(REBOOT_PREFIX);
+	struct psci_reset_param *param;
+	struct device_node *psci_np __free(device_node) = NULL;
+	struct device_node *np __free(device_node) = NULL;
+	struct property *prop;
+	size_t count = 0;
+	u32 magic[2];
+	int num;
+
+	if (!psci_system_reset2_supported)
+		return 0;
+
+	psci_np = of_find_matching_node(NULL, psci_of_match);
+	if (!psci_np)
+		return 0;
+
+	np = of_find_node_by_name(psci_np, "reset-types");
+	if (!np)
+		return 0;
+
+	for_each_property_of_node(np, prop) {
+		if (strncmp(prop->name, REBOOT_PREFIX, len))
+			continue;
+		num = of_property_count_u32_elems(np, prop->name);
+		if (num != 1 && num != 2)
+			continue;
+
+		count++;
+	}
+
+	param = psci_reset_params =
+		kcalloc(count, sizeof(*psci_reset_params), GFP_KERNEL);
+	if (!psci_reset_params)
+		return -ENOMEM;
+
+	for_each_property_of_node(np, prop) {
+		if (strncmp(prop->name, REBOOT_PREFIX, len))
+			continue;
+
+		num = of_property_read_variable_u32_array(np, prop->name, magic,
+							  1, ARRAY_SIZE(magic));
+		if (num < 0) {
+			pr_warn("Failed to parse vendor reboot mode %s\n",
+				param->mode);
+			kfree_const(param->mode);
+			continue;
+		}
+
+		param->mode = kstrdup_const(prop->name + len, GFP_KERNEL);
+		if (!param->mode)
+			continue;
+
+		/* Force reset type to be in vendor space */
+		param->reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic[0];
+		param->cookie = num > 1 ? magic[1] : 0;
+		param++;
+		num_psci_reset_params++;
+	}
+
+	return 0;
+}
+arch_initcall(psci_init_system_reset2_modes);
+
 int __init psci_dt_init(void)
 {
 	struct device_node *np;

-- 
2.34.1



From quic_eberman at quicinc.com  Mon Mar  3 13:08:30 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:30 -0800
Subject: [PATCH v9 1/5] dt-bindings: arm: Document reboot mode magic
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-1-b2cf4a20feda@oss.qualcomm.com>

From: Elliot Berman <elliot.berman at oss.qualcomm.com>

Add bindings to describe vendor-specific reboot modes. Values here
correspond to valid parameters to vendor-specific reset types in PSCI
SYSTEM_RESET2 call.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/arm/psci.yaml | 43 +++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml
index cbb012e217ab80c1ca88e611e7acc06c6d56fad0..5e07c62fe5d74a8d001f6b8a8c9e777f43f3113f 100644
--- a/Documentation/devicetree/bindings/arm/psci.yaml
+++ b/Documentation/devicetree/bindings/arm/psci.yaml
@@ -98,6 +98,27 @@ properties:
       [1] Kernel documentation - ARM idle states bindings
         Documentation/devicetree/bindings/cpu/idle-states.yaml
 
+  reset-types:
+    type: object
+    $ref: /schemas/power/reset/reboot-mode.yaml#
+    unevaluatedProperties: false
+    properties:
+      # "mode-normal" is just SYSTEM_RESET
+      mode-normal: false
+    patternProperties:
+      "^mode-.*$":
+        minItems: 1
+        maxItems: 2
+        description: |
+          Describes a vendor-specific reset type. The string after "mode-"
+          maps a reboot mode to the parameters in the PSCI SYSTEM_RESET2 call.
+
+          Parameters are named mode-xxx = <type[, cookie]>, where xxx
+          is the name of the magic reboot mode, type is the lower 31 bits
+          of the reset_type, and, optionally, the cookie value. If the cookie
+          is not provided, it is defaulted to zero.
+          The 31st bit (vendor-resets) will be implicitly set by the driver.
+
 patternProperties:
   "^power-domain-":
     $ref: /schemas/power/power-domain.yaml#
@@ -137,6 +158,15 @@ allOf:
       required:
         - cpu_off
         - cpu_on
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              const: arm,psci-1.0
+    then:
+      properties:
+        reset-types: false
 
 additionalProperties: false
 
@@ -261,4 +291,17 @@ examples:
         domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
       };
     };
+
+  - |+
+
+    // Case 5: SYSTEM_RESET2 vendor resets
+    psci {
+      compatible = "arm,psci-1.0";
+      method = "smc";
+
+      reset-types {
+        mode-edl = <0>;
+        mode-bootloader = <1 2>;
+      };
+    };
 ...

-- 
2.34.1



From quic_eberman at quicinc.com  Mon Mar  3 13:08:32 2025
From: quic_eberman at quicinc.com (Elliot Berman)
Date: Mon, 3 Mar 2025 13:08:32 -0800
Subject: [PATCH v9 3/5] arm64: dts: qcom: qcm6490-idp: Add PSCI
 SYSTEM_RESET2 types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <20250303-arm-psci-system_reset2-vendor-reboots-v9-3-b2cf4a20feda@oss.qualcomm.com>

From: Elliot Berman <elliot.berman at oss.qualcomm.com>

qcm6490-idp firmware supports vendor-defined SYSTEM_RESET2 types.
Describe the reset types: "bootloader" will cause device to reboot and
stop in the bootloader's fastboot mode. "edl" will cause device to
reboot into "emergency download mode", which permits loading images via
the Firehose protocol.

Co-developed-by: Shivendra Pratap <quic_spratap at quicinc.com>
Signed-off-by: Shivendra Pratap <quic_spratap at quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio at linaro.org>
Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 7 +++++++
 arch/arm64/boot/dts/qcom/sc7280.dtsi     | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
index c5fb153614e1f1d32a8d074d96829beb643c6919..471e71ab0db4db68d776e6b840d93e4e541ed5d7 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
@@ -625,6 +625,13 @@ &pon_resin {
 	status = "okay";
 };
 
+&psci {
+	reset-types {
+		mode-bootloader = <0x10001 0x2>;
+		mode-edl = <0 0x1>;
+	};
+};
+
 &qupv3_id_0 {
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 55db1c83ef5517f82504816baeee583695065225..07474bd2301edea0037da1194a941b8a3d2fa452 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -855,7 +855,7 @@ pmu-a78 {
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
 	};
 
-	psci {
+	psci: psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
 

-- 
2.34.1



From oliver.upton at linux.dev  Mon Mar  3 13:18:35 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Mon, 3 Mar 2025 13:18:35 -0800
Subject: [PATCH] KVM: arm64: Count pKVM stage-2 usage in secondary
 pagetable stats
In-Reply-To: <20250228121355.1377891-1-vdonnefort@google.com>
References: <20250228121355.1377891-1-vdonnefort@google.com>
Message-ID: <Z8Ycq3d7O8_3fozk@linux.dev>

On Fri, Feb 28, 2025 at 12:13:55PM +0000, Vincent Donnefort wrote:
> Count the pages used by pKVM for the guest stage-2 in memory stats under
> secondary pagetable stats, similarly to what the VHE mode does.
> 
> Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 1f55b0c7b11d..c2e022c41313 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1088,12 +1088,18 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
>  
>  static void hyp_mc_free_fn(void *addr, void *unused)
>  {
> +	kvm_account_pgtable_pages(addr, -1);
>  	free_page((unsigned long)addr);
>  }

Don't we drain more than just stage-2 page tables into the teardown_mc
(e.g. vcpu structs)?

Thanks,
Oliver


From ankur.a.arora at oracle.com  Mon Mar  3 13:28:06 2025
From: ankur.a.arora at oracle.com (Ankur Arora)
Date: Mon, 03 Mar 2025 13:28:06 -0800
Subject: [PATCH 0/4] barrier: Introduce smp_cond_load_*_timeout()
In-Reply-To: <20250203214911.898276-1-ankur.a.arora@oracle.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
Message-ID: <877c55249l.fsf@oracle.com>


Hi folks,

Gentle ping for reviews.

Next versions of users of this series:

Resilient Queued Spin Lock:
  https://lore.kernel.org/lkml/20250303152305.3195648-1-memxor at gmail.com/

poll_idle():
  https://lore.kernel.org/lkml/20250218213337.377987-1-ankur.a.arora at oracle.com/


Thanks
Ankur

Ankur Arora <ankur.a.arora at oracle.com> writes:

> Hi,
>
> This series adds waited variants of the smp_cond_load() primitives:
> smp_cond_load_relaxed_timewait(), and smp_cond_load_acquire_timewait().
>
> There are two known users for these interfaces:
>
>  - poll_idle() [1]
>  - resilient queued spinlocks [2]
>
> For both of these cases we want to wait on a condition but also want
> to terminate the wait at some point.
>
> Now, in theory, that can be worked around by making the time check a
> part of the conditional expression provided to smp_cond_load_*():
>
>    smp_cond_load_relaxed(&cvar, !VAL || time_check());
>
> That approach, however, runs into two problems:
>
>   - smp_cond_load_*() only allow waiting on a condition: this might
>     be okay when we are synchronously spin-waiting on the condition,
>     but not on architectures where are actually waiting for a store
>     to a cacheline.
>
>   - this semantic problem becomes a real problem on arm64 if the
>     event-stream is disabled. That means that there will be no
>     asynchronous event (the event-stream) that periodically wakes
>     the waiter, which might lead to an interminable wait if VAL is
>     never written to.
>
> This series extends the smp_cond_load_*() interfaces by adding two
> arguments: a time-check expression and its associated time limit.
> This is sufficient to allow for both a synchronously waited
> implementation (like the generic cpu_relax() based loop), or one
> where the CPU waits for a store to a cacheline with an out-of-band
> timer.
>
> Any comments appreciated!
>
>
> Ankur
>
> [1] https://lore.kernel.org/lkml/20241107190818.522639-3-ankur.a.arora at oracle.com/
> [2] https://lore.kernel.org/lkml/20250107140004.2732830-9-memxor at gmail.com/
>
> --
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Will Deacon <will at kernel.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Kumar Kartikeya Dwivedi <memxor at gmail.com>
> Cc: linux-arch at vger.kernel.org
>
> Ankur Arora (4):
>   asm-generic: barrier: Add smp_cond_load_relaxed_timewait()
>   asm-generic: barrier: Add smp_cond_load_acquire_timewait()
>   arm64: barrier: Add smp_cond_load_relaxed_timewait()
>   arm64: barrier: Add smp_cond_load_acquire_timewait()
>
>  arch/arm64/include/asm/barrier.h | 74 ++++++++++++++++++++++++++++++++
>  include/asm-generic/barrier.h    | 71 ++++++++++++++++++++++++++++++
>  2 files changed, 145 insertions(+)


From yepeilin at google.com  Mon Mar  3 13:31:01 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon, 3 Mar 2025 21:31:01 +0000
Subject: [PATCH bpf-next v4 10/10] bpf, docs: Update instruction-set.rst
 for load-acquire and store-release instructions
In-Reply-To: <CAADnVQKGF-yD6UZ8Xha-wHu+7Jzn7Xa4Xu9Rju0hL2vFknqNEw@mail.gmail.com>
References: <cover.1740978603.git.yepeilin@google.com>
 <c835515c35ec4ed59232adc3c02e1e90aa8ed8be.1740978603.git.yepeilin@google.com>
 <CAADnVQKGF-yD6UZ8Xha-wHu+7Jzn7Xa4Xu9Rju0hL2vFknqNEw@mail.gmail.com>
Message-ID: <Z8YflWUNESGh4pOt@google.com>

On Mon, Mar 03, 2025 at 11:14:47AM -0800, Alexei Starovoitov wrote:
> > Update documentation for the new load-acquire and store-release
> > instructions.  Rename existing atomic operations as "atomic
> > read-modify-write (RMW) operations".
> 
> rmw renaming looks like a churn. I don't think it adds clarity.
> 
> > Following RFC 9669, section 7.3. "Adding Instructions", create new
> > conformance groups "atomic32v2" and "atomic64v2", where:
> >
> >   * atomic32v2: includes all instructions in "atomic32", plus the new
> >                 8-bit, 16-bit and 32-bit atomic load-acquire and
> >                 store-release instructions
> >
> >   * atomic64v2: includes all instructions in "atomic64" and
> >                 "atomic32v2", plus the new 64-bit atomic load-acquire
> >                 and store-release instructions
> 
> I think it's better for new groups to include only newly added insns.
> Also we probably should add barriers to kernel/llvm and only
> then update the doc with all insns together.
> Otherwise we very quickly get to atomicv3 and v4 groups.
> Naming wise I would call these two insns plus all barriers as
> barrier32 and barrier64 groups.
> cmpwait insn should probably be there as well.

Got it, I'll drop this patch from the series for now.

Thanks,
Peilin Ye



From didi.debian at cknow.org  Mon Mar  3 13:36:23 2025
From: didi.debian at cknow.org (Diederik de Haas)
Date: Mon, 03 Mar 2025 22:36:23 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add avdd HDMI supplies to
 RockPro64 board dtsi
In-Reply-To: <df3d7e8fe74ed5e727e085b18c395260537bb5ac.1740941097.git.dsimic@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <df3d7e8fe74ed5e727e085b18c395260537bb5ac.1740941097.git.dsimic@manjaro.org>
Message-ID: <D86YDVZLWWA0.33WM5O2EZIAI6@cknow.org>

Hi Dragan,

On Sun Mar 2, 2025 at 7:48 PM CET, Dragan Simic wrote:
> Add missing "avdd-0v9-supply" and "avdd-1v8-supply" properties to the "hdmi"
> node in the Pine64 RockPro64 board dtsi file.  To achieve this, also add the
> associated "vcca_0v9" regulator that produces the 0.9 V supply, [1][2] which
> hasn't been defined previously in the board dtsi file.
>
> This also eliminates the following warnings from the kernel log:
>
>   dwhdmi-rockchip ff940000.hdmi: supply avdd-0v9 not found, using dummy regulator
>   dwhdmi-rockchip ff940000.hdmi: supply avdd-1v8 not found, using dummy regulator

Also thanks for this patch :-)

I've now also confirmed for myself that without this patch I see the
above warnings and I don't see them with this patch applied.

When booting up I saw an U-Boot logo (hadn't seen that one before) and
not longer after that I saw the various boot messages come by on the
monitor I had connected to the HDMI port. This is only a *very*
barebones install (yet), so I couldn't do 'deeper' tests, but HDMI
appears to work. So feel free to include:

Tested-by: Diederik de Haas <didi.debian at cknow.org>

Cheers,
  Diederik
>
> There are no functional changes to the way board works with these additions,
> because the "vcc1v8_dvp" and "vcca_0v9" regulators are always enabled, [1][2]
> but these additions improve the accuracy of hardware description.
>
> These changes apply to the both supported hardware revisions of the Pine64
> RockPro64, i.e. to the production-run revisions 2.0 and 2.1. [1][2]
>
> [1] https://files.pine64.org/doc/rockpro64/rockpro64_v21-SCH.pdf
> [2] https://files.pine64.org/doc/rockpro64/rockpro64_v20-SCH.pdf
>
> Fixes: e4f3fb490967 ("arm64: dts: rockchip: add initial dts support for Rockpro64")
> Cc: stable at vger.kernel.org
> Suggested-by: Diederik de Haas <didi.debian at cknow.org>
> Signed-off-by: Dragan Simic <dsimic at manjaro.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> index 69a9d6170649..47dc198706c8 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
> @@ -227,6 +227,16 @@ vcc5v0_usb: regulator-vcc5v0-usb {
>  		vin-supply = <&vcc12v_dcin>;
>  	};
>  
> +	vcca_0v9: regulator-vcca-0v9 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vcca_0v9";
> +		regulator-always-on;
> +		regulator-boot-on;
> +		regulator-min-microvolt = <900000>;
> +		regulator-max-microvolt = <900000>;
> +		vin-supply = <&vcc3v3_sys>;
> +	};
> +
>  	vdd_log: regulator-vdd-log {
>  		compatible = "pwm-regulator";
>  		pwms = <&pwm2 0 25000 1>;
> @@ -312,6 +322,8 @@ &gmac {
>  };
>  
>  &hdmi {
> +	avdd-0v9-supply = <&vcca_0v9>;
> +	avdd-1v8-supply = <&vcc1v8_dvp>;
>  	ddc-i2c-bus = <&i2c3>;
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&hdmi_cec>;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/c024e67f/attachment.sig>

From samitolvanen at google.com  Mon Mar  3 13:40:48 2025
From: samitolvanen at google.com (Sami Tolvanen)
Date: Mon, 3 Mar 2025 21:40:48 +0000
Subject: [PATCH v4 4/4] arm64: implement per-function metadata storage
 for arm64
In-Reply-To: <20250303132837.498938-5-dongml2@chinatelecom.cn>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-5-dongml2@chinatelecom.cn>
Message-ID: <20250303214048.GA570570@google.com>

On Mon, Mar 03, 2025 at 09:28:37PM +0800, Menglong Dong wrote:
> The per-function metadata storage is already used by ftrace if
> CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS is enabled, and it store the pointer
> of the callback directly to the function padding, which consume 8-bytes,
> in the commit
> baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS").
> So we can directly store the index to the function padding too, without
> a prepending. With CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS enabled, the
> function is 8-bytes aligned, and we will compile the kernel with extra
> 8-bytes (2 NOPS) padding space. Otherwise, the function is 4-bytes
> aligned, and only extra 4-bytes (1 NOPS) is needed.
> 
> However, we have the same problem with Mark in the commit above: we can't
> use the function padding together with CFI_CLANG, which can make the clang
> compiles a wrong offset to the pre-function type hash. He said that he was
> working with others on this problem 2 years ago. Hi Mark, is there any
> progress on this problem?

I don't think there's been much progress since the previous
discussion a couple of years ago. The conclusion seemed to be
that adding a section parameter to -fpatchable-function-entry
would allow us to identify notrace functions while keeping a
consistent layout for functions:

https://lore.kernel.org/lkml/Y1QEzk%2FA41PKLEPe at hirez.programming.kicks-ass.net/

Sami


From heiko at sntech.de  Mon Mar  3 13:47:47 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon,  3 Mar 2025 22:47:47 +0100
Subject: [PATCH v16 0/7] VOP Support for rk3576
In-Reply-To: <20250303034436.192400-1-andyshrk@163.com>
References: <20250303034436.192400-1-andyshrk@163.com>
Message-ID: <174103845739.1823374.12191535922821188431.b4-ty@sntech.de>


On Mon, 03 Mar 2025 11:44:14 +0800, Andy Yan wrote:
> Here is the v16
> Patches that have already been merged in drm-misc-next are dropped.
> 
> I test it with a 1080P/4K HDMI output with modetest and weston
> output.
> 
> If there are some one want to have a try, I have a tree based on
> Linux 6.14-rc1 here[0]
> 
> [...]

Applied, thanks!

[1/7] drm/rockchip: vop2: Register the primary plane and overlay plane separately
      commit: 6fd4f8a26a21dd2075cfcc7eae3b9d440d886571
[2/7] drm/rockchip: vop2: Set plane possible crtcs by possible vp mask
      commit: b90fa71a11600276c993e620abea8ca9f2045401
[3/7] drm/rockchip: vop2: Add uv swap for cluster window
      commit: e7aae9f6d762139f8d2b86db03793ae0ab3dd802
[4/7] dt-bindings: display: vop2: describe constraint SoC by SoC
      commit: 1803bfb59656d41c4f9f7e5f23188248b649e1a4
[5/7] dt-bindings: display: vop2: Add missing rockchip,grf property for rk3566/8
      commit: 47d31e6598e4fda1433e747ef031cb972c57c5ae
[6/7] dt-bindings: display: vop2: Add rk3576 support
      commit: c3b7c5a4d7c17afb158ba5a41222e95a32886ada
[7/7] drm/rockchip: vop2: Add support for rk3576
      commit: 944757a4cba62b1b50fb51933d0608117599db71

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From will at kernel.org  Mon Mar  3 13:49:50 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 3 Mar 2025 21:49:50 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
References: <20250226215520.1759218-1-tabba@google.com>
 <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com>
 <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck>
 <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
Message-ID: <20250303214947.GA30619@willie-the-truck>

On Mon, Mar 03, 2025 at 07:21:33PM +0000, Fuad Tabba wrote:
> On Mon, 3 Mar 2025 at 19:18, Will Deacon <will at kernel.org> wrote:
> > On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> > > On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> > > > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > > > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > >  {
> > > > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > > > +     size_t pgd_sz, hyp_vm_sz;
> > > > >       struct kvm_vcpu *host_vcpu;
> > > > > -     pkvm_handle_t handle;
> > > > >       void *pgd, *hyp_vm;
> > > > >       unsigned long idx;
> > > > >       int ret;
> > > > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > >       if (ret < 0)
> > > > >               goto free_vm;
> > > > >
> > > > > -     handle = ret;
> > > > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> > > >
> > > > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > > > update the readers to be READ_ONCE()?
> > >
> > > I don't remember the original reason, to be honest. In this case, it
> > > was to make it consistent with downstream code in Android. That said,
> > > I plan on revising all of these soon and fixing this (and related
> > > code) in light of Will's comment regarding potential specter gadgets:
> > >
> > > https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/
> >
> > I'm not sure the spectre stuff changes the concurrency aspects here, so
> > Quentin's question presumably still stands even after that.
> >
> > Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
> > in pkvm_is_hyp_created() which is called without the config_lock held
> > by kvm_arch_prepare_memory_region(). However, given that
> > pkvm_is_hyp_created() is only testing against 0, I don't think the
> > _ONCE() accessors are doing anything useful in that case.
> >
> > The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
> > directly without the 'config_lock' held. The MMU notifiers look like
> > they can do that, so I wonder if there's a theoretical race where they
> > can race with first run and issue TLB invalidation with the wrong handle?
> > That would apply equally to the upstream code, I think.
> 
> Would using _ONCE accessors with the MMU notifiers be enough to avoid
> the race, or do we need to reconsider the lock protecting the handle
> and apply it to the notifiers?

I'm not entirely sure... if we used _ONCE() then we'd get either the
correct handle or zero, but we presumably need to order that against the
page-table somehow. The 'mmu_lock' looks like it gives us that, but I
don't think the notifiers are expecting an uninitialised handle in the
case where the page-table is empty (i.e. if they fire before first run).

Given that the handle is necessary for TLB invalidation, I'd be inclined
to make sure that the handle is allocated and published _before_ the
kvm_pgtable pointer checked by the notifiers is set, but that means
moving the handle allocation into kvm_arch_init_vm(). Is that do-able?

Will


From alexandre.belloni at bootlin.com  Mon Mar  3 13:53:09 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 3 Mar 2025 22:53:09 +0100
Subject: [PATCH 0/7] rtc: Use devm_pm_set_wake_irq to simplify code
In-Reply-To: <20250205-rtc-cleanup-v1-0-66165678e089@nxp.com>
References: <20250205-rtc-cleanup-v1-0-66165678e089@nxp.com>
Message-ID: <174103876909.1106916.958645902819103595.b4-ty@bootlin.com>

On Wed, 05 Feb 2025 08:58:18 +0800, Peng Fan (OSS) wrote:
> This is a pick-up of patch 6-12 from patchset [1]
> 
> Since devm_pm_set_wake_irq is in 6.14, so resend the rtc parts.
> 
> R-b tags from Linus Walleij and Antonio Borneo are still kept.
> 
> [1] https://lore.kernel.org/all/CAJZ5v0jb=0c5m=FeA-W-aG30H4706Ay_xCHTsiC1S-7MuGxqTQ at mail.gmail.com/#r
> 
> [...]

Applied, thanks!

[1/7] rtc: stm32: Use resource managed API to simplify code
      https://git.kernel.org/abelloni/c/04572d18921d
[2/7] rtc: nxp-bbnsm: Use resource managed API to simplify code
      https://git.kernel.org/abelloni/c/6b296dee3eb7
[3/7] rtc: ds1343: Use devm_pm_set_wake_irq
      https://git.kernel.org/abelloni/c/5ad218f101e4
[4/7] rtc: pm8xxx: Use devm_pm_set_wake_irq
      https://git.kernel.org/abelloni/c/e8a0b6e62429
[5/7] rtc: ab8500: Use resource managed API to simplify code
      https://git.kernel.org/abelloni/c/ca36c9301117
[6/7] rtc: mpfs: Use devm_pm_set_wake_irq
      https://git.kernel.org/abelloni/c/d8690ce183bb
[7/7] rtc: pl031: Use resource managed API to simplify code
      https://git.kernel.org/abelloni/c/90e0bcc9392d

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From konrad.dybcio at oss.qualcomm.com  Mon Mar  3 13:56:33 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Mon, 3 Mar 2025 22:56:33 +0100
Subject: [PATCH v11 4/6] clk: qcom: Add NSS clock Controller driver for
 IPQ9574
In-Reply-To: <20250226075449.136544-5-quic_mmanikan@quicinc.com>
References: <20250226075449.136544-1-quic_mmanikan@quicinc.com>
 <20250226075449.136544-5-quic_mmanikan@quicinc.com>
Message-ID: <33bf565a-82af-46d3-920a-ed664aaef183@oss.qualcomm.com>

On 26.02.2025 8:54 AM, Manikanta Mylavarapu wrote:
> From: Devi Priya <quic_devipriy at quicinc.com>
> 
> Add Networking Sub System Clock Controller (NSSCC) driver for ipq9574 based
> devices.
> 
> Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
> Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>

Konrad



From Frank.li at nxp.com  Mon Mar  3 13:57:29 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 16:57:29 -0500
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <20250227002326.GA566507@bhelgaas>
References: <20250128-pci_fixup_addr-v9-3-3c4bb506f665@nxp.com>
 <20250227002326.GA566507@bhelgaas>
Message-ID: <Z8YlySM6Xtr0beo1@lizhi-Precision-Tower-5810>

On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > for PCI controllers with address translation units.
> >
> > Typical PCI data flow involves:
> >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> >   PCI Controller (PCI bus address) -> PCI Bus.
> >
> > While most bus fabrics preserve address consistency, some modify addresses
> > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > translate these intermediate addresses correctly to PCI bus addresses.
> >
> > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > PCI controller drivers.
> > ...
>
> > +++ b/drivers/pci/of.c
> > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> >  			res->flags &= ~IORESOURCE_MEM_64;
> >  		}
> >
> > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > +		/*
> > +		 * IORESOURCE_IO res->start is io space start address.
> > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > +		 * same as range.cpu_addr.
> > +		 *
> > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > +		 */
> > +
> > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > +						   range.cpu_addr - range.parent_bus_addr);
>
> I don't know exactly where it needs to go, but I think we can call
> .cpu_addr_fixup() once at startup on the base of the region.  This
> will tell us the offset that applies to the entire region, i.e.,
> parent_bus_offset.
>
> Then we can remove all the .cpu_addr_fixup() calls in
> cdns_pcie_host_init_address_translation(),
> cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
>
> Until we can get rid of all the .cpu_addr_fixup() implementations,
> We'll still have that single call at startup (I guess once for cadence
> and another for designware), but it should simplify the current
> callers quite a bit.

I don't think it can simple code. cdns_pcie_set_outbound_region() and
dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
"resource" to manage outbound windows. And there are IO/CFG/MEM space at
host side, It will involve more .cpu_addr_fixup() calls to setup these
range.

Frank
>
> >  	}
> >
> >  	/* Check for dma-ranges property */
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 47b31ad724fa5..0d7e67b47be47 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1510,6 +1510,8 @@ static inline void pci_release_config_region(struct pci_dev *pdev,
> >  void pci_add_resource(struct list_head *resources, struct resource *res);
> >  void pci_add_resource_offset(struct list_head *resources, struct resource *res,
> >  			     resource_size_t offset);
> > +void pci_add_resource_parent_bus_offset(struct list_head *resources, struct resource *res,
> > +					resource_size_t offset, resource_size_t parent_bus_offset);
> >  void pci_free_resource_list(struct list_head *resources);
> >  void pci_bus_add_resource(struct pci_bus *bus, struct resource *res);
> >  struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
> > diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h
> > index ff0339df56afc..b6ec6cc318203 100644
> > --- a/include/linux/resource_ext.h
> > +++ b/include/linux/resource_ext.h
> > @@ -24,6 +24,7 @@ struct resource_entry {
> >  	struct list_head	node;
> >  	struct resource		*res;	/* In master (CPU) address space */
> >  	resource_size_t		offset;	/* Translation offset for bridge */
> > +	resource_size_t		parent_bus_offset; /* Parent bus address offset for bridge */
> >  	struct resource		__res;	/* Default storage for res */
> >  };
> >
> >
> > --
> > 2.34.1
> >


From Frank.li at nxp.com  Mon Mar  3 13:58:56 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 16:58:56 -0500
Subject: [PATCH v9 4/7] PCI: dwc: Use devicetree 'ranges' property to get
 rid of cpu_addr_fixup() callback
In-Reply-To: <20250226233339.GA562682@bhelgaas>
References: <20250128-pci_fixup_addr-v9-4-3c4bb506f665@nxp.com>
 <20250226233339.GA562682@bhelgaas>
Message-ID: <Z8YmINgrQS7w0Myg@lizhi-Precision-Tower-5810>

On Wed, Feb 26, 2025 at 05:33:39PM -0600, Bjorn Helgaas wrote:
> On Tue, Jan 28, 2025 at 05:07:37PM -0500, Frank Li wrote:
> > parent_bus_offset in resource_entry can indicate address information just
> > ahead of PCIe controller. Most system's bus fabric use 1:1 map between
> > input and output address. but some hardware like i.MX8QXP doesn't use 1:1
> > map. See below diagram:
> > ...
>
> > @@ -448,6 +451,26 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> >  	if (IS_ERR(pp->va_cfg0_base))
> >  		return PTR_ERR(pp->va_cfg0_base);
> >
> > +	if (pci->use_parent_dt_ranges) {
> > +		if (pci->ops->cpu_addr_fixup) {
> > +			dev_err(dev, "Use parent bus DT ranges, cpu_addr_fixup() must be removed\n");
> > +			return -EINVAL;
> > +		}
> > +
> > +		index = of_property_match_string(np, "reg-names", "config");
> > +		if (index < 0)
> > +			return -EINVAL;
> > +
> > +		 /*
> > +		  * Retrieve the parent bus address of PCI config space.
> > +		  * If the parent bus ranges in the device tree provide
> > +		  * the correct address conversion information, set
> > +		  * 'use_parent_dt_ranges' to true, The
> > +		  * 'cpu_addr_fixup()' can be eliminated.
> > +		  */
> > +		of_property_read_reg(np, index, &pp->cfg0_base, NULL);
> > +	}
>
> I think all this code dealing with the "config" resource could go in a
> helper function.  It's kind of a lot of clutter in
> dw_pcie_host_init().
>
> It would be nice to assign pp->cfg0_base once, not assign res->start
> to it and then possibly overwrite it later.
>
> > @@ -841,6 +841,15 @@ void dw_pcie_iatu_detect(struct dw_pcie *pci)
> >  	pci->region_align = 1 << fls(min);
> >  	pci->region_limit = (max << 32) | (SZ_4G - 1);
> >
> > +	if (pci->ops && pci->ops->cpu_addr_fixup) {
> > +		/*
> > +		 * If the parent 'ranges' property in DT correctly describes
> > +		 * the address translation, cpu_addr_fixup() callback is not
> > +		 * needed.
> > +		 */
> > +		dev_warn_once(pci->dev, "cpu_addr_fixup() usage detected. Please fix DT!\n");
> > +	}
>
> Can you split the warnings out to a separate patch?  I think we should
> warn once in every initialization path where .cpu_addr_fixup() could
> be used, i.e.,
>
>   dw_pcie_host_init()
>   dw_pcie_ep_init()
>   cdns_pcie_host_setup()
>   cdns_pcie_ep_setup()
>
> IMO these should warn if .cpu_addr_fixup() is implemented, regardless
> of use_parent_dt_ranges.
>
> I'm still puzzling over some of the rest of this, so no need to post a
> revised series yet.

Do you have additional comments, so I can post a revised series?

Frank

>
> Bjorn


From florian.fainelli at broadcom.com  Mon Mar  3 14:08:16 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 3 Mar 2025 14:08:16 -0800
Subject: [PATCH v9 2/5] firmware: psci: Read and use vendor reset types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
 <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <cbc21738-2212-4124-9763-bb20fd927ba9@broadcom.com>

On 3/3/25 13:08, Elliot Berman wrote:
> From: Elliot Berman <elliot.berman at oss.qualcomm.com>
> 
> SoC vendors have different types of resets and are controlled through
> various registers. For instance, Qualcomm chipsets can reboot to a
> "download mode" that allows a RAM dump to be collected. Another example
> is they also support writing a cookie that can be read by bootloader
> during next boot. PSCI offers a mechanism, SYSTEM_RESET2, for these
> vendor reset types to be implemented without requiring drivers for every
> register/cookie.
> 
> Add support in PSCI to statically map reboot mode commands from
> userspace to a vendor reset and cookie value using the device tree.
> 
> A separate initcall is needed to parse the devicetree, instead of using
> psci_dt_init because mm isn't sufficiently set up to allocate memory.
> 
> Reboot mode framework is close but doesn't quite fit with the
> design and requirements for PSCI SYSTEM_RESET2. Some of these issues can
> be solved but doesn't seem reasonable in sum:
>   1. reboot mode registers against the reboot_notifier_list, which is too
>      early to call SYSTEM_RESET2. PSCI would need to remember the reset
>      type from the reboot-mode framework callback and use it
>      psci_sys_reset.
>   2. reboot mode assumes only one cookie/parameter is described in the
>      device tree. SYSTEM_RESET2 uses 2: one for the type and one for
>      cookie.
>   3. psci cpuidle driver already registers a driver against the
>      arm,psci-1.0 compatible. Refactoring would be needed to have both a
>      cpuidle and reboot-mode driver.
> 
> Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>

Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
Tested-by: Florian Fainelli <florian.fainelli at broadcom.com>
-- 
Florian


From yepeilin at google.com  Mon Mar  3 14:16:57 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon, 3 Mar 2025 22:16:57 +0000
Subject: [PATCH bpf-next v4 04/10] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <CAADnVQLLhNRmpjwDYHB0-59TDrGcgXzqSkop+-5eHYsG-Ws08Q@mail.gmail.com>
References: <2c82b29f3530b961b41f94a4942e490ab35a31c8.1740978603.git.yepeilin@google.com>
 <202503031631.OeUhVRHz-lkp@intel.com>
 <CAADnVQLLhNRmpjwDYHB0-59TDrGcgXzqSkop+-5eHYsG-Ws08Q@mail.gmail.com>
Message-ID: <Z8YqWQuyArxCQWeD@google.com>

On Mon, Mar 03, 2025 at 10:43:07AM -0800, Alexei Starovoitov wrote:
> > compiler: arc-elf-gcc (GCC) 13.2.0
> 
> ...
> 
> >    kernel/bpf/core.c:2228:25: note: in expansion of macro 'LOAD_ACQUIRE'
> >     2228 |                         LOAD_ACQUIRE(DW, u64)
> >          |                         ^~~~~~~~~~~~

*facepalm*

> Peilin,
> 
> how do you plan on fixing this?
> So far I could only think of making compilation conditional for CONFIG_64BIT
> and let the verifier reject these insns on 32-bit arches.

Agreed - after searching for "Need native word sized stores/loads for
atomicity." on lore, it appears that we can't have 64-bit
smp_{load_acquire,store_release}() on 32-bit arches.  My draft fix is:

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 323af18d7d49..6df1d3e379a4 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2225,7 +2225,9 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
                        LOAD_ACQUIRE(B,   u8)
                        LOAD_ACQUIRE(H,  u16)
                        LOAD_ACQUIRE(W,  u32)
+#ifdef CONFIG_64BIT
                        LOAD_ACQUIRE(DW, u64)
+#endif
 #undef LOAD_ACQUIRE
                        default:
                                goto default_label;
@@ -2241,7 +2243,9 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
                        STORE_RELEASE(B,   u8)
                        STORE_RELEASE(H,  u16)
                        STORE_RELEASE(W,  u32)
+#ifdef CONFIG_64BIT
                        STORE_RELEASE(DW, u64)
+#endif
 #undef STORE_RELEASE
                        default:
                                goto default_label;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index dac7af73ac8a..d0e4c6bab37d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7814,8 +7814,16 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
        case BPF_CMPXCHG:
                return check_atomic_rmw(env, insn);
        case BPF_LOAD_ACQ:
+               if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
+                       verbose(env, "64-bit load-acquire is only supported on 64-bit arches\n");
+                       return -ENOTSUPP;
+               }
                return check_atomic_load(env, insn);
        case BPF_STORE_REL:
+               if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
+                       verbose(env, "64-bit store-release is only supported on 64-bit arches\n");
+                       return -ENOTSUPP;
+               }
                return check_atomic_store(env, insn);
        default:
                verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",

Thanks,
Peilin Ye



From yepeilin at google.com  Mon Mar  3 14:20:55 2025
From: yepeilin at google.com (Peilin Ye)
Date: Mon, 3 Mar 2025 22:20:55 +0000
Subject: [PATCH bpf-next v4 03/10] bpf/verifier: Factor out
 check_load_mem() and check_store_reg()
In-Reply-To: <CAADnVQKyMx64_mP+u+rmnRGyzVoBs4rViTHeE4_0Rr+Kf3R5Tg@mail.gmail.com>
References: <cover.1740978603.git.yepeilin@google.com>
 <8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com>
 <CAADnVQKyMx64_mP+u+rmnRGyzVoBs4rViTHeE4_0Rr+Kf3R5Tg@mail.gmail.com>
Message-ID: <Z8YrR7p7ikaw0Kpr@google.com>

On Mon, Mar 03, 2025 at 10:52:08AM -0800, Alexei Starovoitov wrote:
> > Extract BPF_LDX and most non-ATOMIC BPF_STX instruction handling logic
> > in do_check() into helper functions to be used later.  While we are
> > here, make that comment about "reserved fields" more specific.
> >
> > Suggested-by: Eduard Zingerman <eddyz87 at gmail.com>
> > Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
> > Signed-off-by: Peilin Ye <yepeilin at google.com>
> 
> Applied the first 3 patches.

Thanks!

I'll fix that build issue for 32-bit arches, then send remaining patches
(except v4 10/10) as v5.

Cheers,
Peilin Ye



From heiko at sntech.de  Mon Mar  3 14:36:10 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon,  3 Mar 2025 23:36:10 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64 RockPro64
In-Reply-To: <cover.1740941097.git.dsimic@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
Message-ID: <174104113599.8946.16805724674396090918.b4-ty@sntech.de>


On Sun, 02 Mar 2025 19:48:02 +0100, Dragan Simic wrote:
> This is a small series that introduces small improvements to the way
> Pine64 RockPro64 [1] single-board-computer is described in the DT files.
> This applies to both production-run revisions of the RockPro64.
> 
> The introduced improvements boil down to eliminating some warnings from
> the kernel log, by adding a previously undefined regulator and by adding
> some previously missing references to the regulators.
> 
> [...]

Applied, thanks!

[1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board dtsi
      commit: bd1c959f37f384b477f51572331b0dc828bd009a
[2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 board dtsi
      commit: 64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b

I've moved the pcie12v supply up one line.
While in a mathematical sense it's true 12 > 3.3, we're sorting
alphabetical, so it's 1?? < 3?? .

And yes I sympathize with 3.3 < 12, but also have come to appreciate not
having overly many special cases :-)


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From sebastian.reichel at collabora.com  Mon Mar  3 14:34:42 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 3 Mar 2025 23:34:42 +0100
Subject: [PATCH] drm/rockchip: vop2: add missing bitfield.h include
In-Reply-To: <20250303182256.1727178-1-heiko@sntech.de>
References: <20250303182256.1727178-1-heiko@sntech.de>
Message-ID: <quj727pq3oc4xruatx7s5hob7jtcpw6zhe3wv6fhammxhejcem@eois3su6izj7>

Hi,

On Mon, Mar 03, 2025 at 07:22:56PM +0100, Heiko Stuebner wrote:
> Commit 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
> moved per soc configuration code to the other per-soc data into
> rockchip_vop2_reg.c, but forgot to also include bitfield.h for the used
> FIELD_PREP macro. Add this missing include.
> 
> Fixes: 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503040135.fgoyWdLB-lkp at intel.com/
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

Greetings,

-- Sebastian

>  drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
> index 0afef24db144..f86a30df94aa 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
> @@ -4,6 +4,7 @@
>   * Author: Andy Yan <andy.yan at rock-chips.com>
>   */
>  
> +#include <linux/bitfield.h>
>  #include <linux/kernel.h>
>  #include <linux/component.h>
>  #include <linux/mod_devicetable.h>
> -- 
> 2.47.2
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250303/b746f69c/attachment.sig>

From alexandre.belloni at bootlin.com  Mon Mar  3 14:36:37 2025
From: alexandre.belloni at bootlin.com (alexandre.belloni at bootlin.com)
Date: Mon,  3 Mar 2025 23:36:37 +0100
Subject: [PATCH] rtc: mt6397: drop unused defines
Message-ID: <20250303223637.1135362-1-alexandre.belloni@bootlin.com>

From: Alexandre Belloni <alexandre.belloni at bootlin.com>

RTC_NUM_YEARS has never been used, the other defines are not used since
commit 34bbdc12d04e ("rtc: mt6359: Add RTC hardware range and add support
for start-year")

Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
---
 include/linux/mfd/mt6397/rtc.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/include/linux/mfd/mt6397/rtc.h b/include/linux/mfd/mt6397/rtc.h
index 068ae1c0f0e8..27883af44f87 100644
--- a/include/linux/mfd/mt6397/rtc.h
+++ b/include/linux/mfd/mt6397/rtc.h
@@ -60,11 +60,6 @@
 #define RTC_PDN2               0x002e
 #define RTC_PDN2_PWRON_ALARM   BIT(4)
 
-#define RTC_MIN_YEAR           1968
-#define RTC_BASE_YEAR          1900
-#define RTC_NUM_YEARS          128
-#define RTC_MIN_YEAR_OFFSET    (RTC_MIN_YEAR - RTC_BASE_YEAR)
-
 #define MTK_RTC_POLL_DELAY_US  10
 #define MTK_RTC_POLL_TIMEOUT   (jiffies_to_usecs(HZ))
 
-- 
2.48.1



From heiko at sntech.de  Mon Mar  3 14:43:16 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon,  3 Mar 2025 23:43:16 +0100
Subject: [PATCH] drm/rockchip: vop2: add missing bitfield.h include
In-Reply-To: <20250303182256.1727178-1-heiko@sntech.de>
References: <20250303182256.1727178-1-heiko@sntech.de>
Message-ID: <174104179297.19992.1129192365556530821.b4-ty@sntech.de>


On Mon, 03 Mar 2025 19:22:56 +0100, Heiko Stuebner wrote:
> Commit 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
> moved per soc configuration code to the other per-soc data into
> rockchip_vop2_reg.c, but forgot to also include bitfield.h for the used
> FIELD_PREP macro. Add this missing include.
> 
> 

Applied, thanks!

[1/1] drm/rockchip: vop2: add missing bitfield.h include
      commit: 95a5c9d197bb22a506913acb330a926d4e51aa95

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From will at kernel.org  Mon Mar  3 15:43:03 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 3 Mar 2025 23:43:03 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <20250227181750.3606372-4-sebastianene@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
Message-ID: <20250303234259.GA30749@willie-the-truck>

On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> Map the hypervisor's buffers irrespective to the host and return
> a linux error code from the FF-A error code on failure. Remove
> the unmap ff-a buffers calls from the hypervisor as it will
> never be called.
> Prevent the host from using FF-A directly with Trustzone
> if the hypervisor could not map its own buffers.
> 
> Signed-off-by: Sebastian Ene <sebastianene at google.com>
> ---
>  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
>  1 file changed, 17 insertions(+), 29 deletions(-)

[...]

> @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
>  {
>  	struct arm_smccc_res res;
>  	void *tx, *rx;
> +	int ret;
>  
>  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
>  		return 0;
> @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
>  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
>  	};
>  
> +	/* Map our hypervisor buffers into the SPMD */
> +	ret = ffa_map_hyp_buffers();
> +	if (ret)
> +		return ret;

Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
the host to negotiate the version lazily?

Will


From will at kernel.org  Mon Mar  3 15:44:28 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 3 Mar 2025 23:44:28 +0000
Subject: [PATCH v2 2/4] KVM: arm64: Move the ffa_to_linux definition to
 the ffa header
In-Reply-To: <86wmdapei8.wl-maz@kernel.org>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-3-sebastianene@google.com>
 <20250227202557.d3fd6ylzbaho4pvx@bogus>
 <Z8DxZY-09R6lwEW3@google.com>
 <86wmdapei8.wl-maz@kernel.org>
Message-ID: <20250303234426.GB30749@willie-the-truck>

On Fri, Feb 28, 2025 at 10:09:19AM +0000, Marc Zyngier wrote:
> On Thu, 27 Feb 2025 23:12:37 +0000,
> Sebastian Ene <sebastianene at google.com> wrote:
> > 
> > On Thu, Feb 27, 2025 at 08:25:57PM +0000, Sudeep Holla wrote:
> > > On Thu, Feb 27, 2025 at 06:17:47PM +0000, Sebastian Ene wrote:
> > > > Keep the ffa_to_linux error map in the header and move it away
> > > > from the arm ffa driver to make it accessible for other components.
> > > 
> > > Do you plan to push/target these changes for v6.15 ? If not, I can take
> > > this patch with other FF-A changes in my tree for v6.15. Otherwise, it
> > > is must go along with other changes.
> > > 
> > 
> > Yes, feel free to pick them with your changes and we can push them
> > later.
> 
> So this series is not a 6.15 candidate?

I think this is 6.15 stuff once it's been reviewed. Sudeep's message is
a little confusing as it refers to 6.15 twice (I guess he meant 6.14 the
first time?).

Will


From dmitry.baryshkov at linaro.org  Mon Mar  3 16:01:07 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Tue, 4 Mar 2025 02:01:07 +0200
Subject: [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <Z8XcH7xoDC7TA7ZC@blossom>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
 <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org>
 <Z8XcH7xoDC7TA7ZC@blossom>
Message-ID: <dn7zskhxgdgr25nvbnsjyn5brc3yoc446dxz3vqgbiwoccvlcr@5l6f4byj53fo>

On Mon, Mar 03, 2025 at 11:43:11AM -0500, Alyssa Rosenzweig wrote:
> > > Sasha Finkelstein (5):
> > >        dt-bindings: display: Add Apple pre-DCP display controller
> > >        drm: adp: Add Apple Display Pipe driver
> > >        drm: panel: Add a panel driver for the Summit display
> > >        arm64: dts: apple: Add touchbar screen nodes
> > >        MAINTAINERS: Add entries for touchbar display driver
> > > 
> > >   .../display/apple,h7-display-pipe-mipi.yaml        |  83 +++
> > >   .../bindings/display/apple,h7-display-pipe.yaml    |  88 +++
> > >   .../bindings/display/panel/apple,summit.yaml       |  58 ++
> > >   MAINTAINERS                                        |  16 +
> > >   arch/arm64/boot/dts/apple/t8103-j293.dts           |  31 ++
> > >   arch/arm64/boot/dts/apple/t8103.dtsi               |  61 ++
> > >   arch/arm64/boot/dts/apple/t8112-j493.dts           |  31 ++
> > >   arch/arm64/boot/dts/apple/t8112.dtsi               |  61 ++
> > >   drivers/gpu/drm/Kconfig                            |   2 +
> > >   drivers/gpu/drm/Makefile                           |   1 +
> > >   drivers/gpu/drm/adp/Kconfig                        |  17 +
> > >   drivers/gpu/drm/adp/Makefile                       |   5 +
> > >   drivers/gpu/drm/adp/adp-mipi.c                     | 276 +++++++++
> > >   drivers/gpu/drm/adp/adp_drv.c                      | 617 +++++++++++++++++++++
> > >   drivers/gpu/drm/panel/Kconfig                      |   9 +
> > >   drivers/gpu/drm/panel/Makefile                     |   1 +
> > >   drivers/gpu/drm/panel/panel-summit.c               | 132 +++++
> > >   17 files changed, 1489 insertions(+)
> > > ---
> > > base-commit: b62cef9a5c673f1b8083159f5dc03c1c5daced2f
> > > change-id: 20241124-adpdrm-25fce3dd8a71
> > > 
> > > 
> > 
> > All patches are reviewed, can we funnel patches 1, 2 & 5 via drm-misc-next now ?
> 
> I'm planning to do so today, just need to get dim setup first :)

Nice! As a heads up, it would be really-really nice if you can send any
kind of 'applied' message. If you are using 'dim b4-shazam', then
'b4 ty -a' might do that for you. Otherwise just a simple 'hey, applied'
email is useful enough.

-- 
With best wishes
Dmitry


From kuba at kernel.org  Mon Mar  3 16:10:24 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Mon, 3 Mar 2025 16:10:24 -0800
Subject: [PATCH net v2] net: ethtool: netlink: Allow NULL nlattrs when
 getting a phy_device
In-Reply-To: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
References: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
Message-ID: <20250303161024.43969294@kernel.org>

On Sat,  1 Mar 2025 15:11:13 +0100 Maxime Chevallier wrote:
> ethnl_req_get_phydev() is used to lookup a phy_device, in the case an
> ethtool netlink command targets a specific phydev within a netdev's
> topology.
> 
> It takes as a parameter a const struct nlattr *header that's used for
> error handling :
> 
>        if (!phydev) {
>                NL_SET_ERR_MSG_ATTR(extack, header,
>                                    "no phy matching phyindex");
>                return ERR_PTR(-ENODEV);
>        }
> 
> In the notify path after a ->set operation however, there's no request
> attributes available.
> 
> The typical callsite for the above function looks like:
> 
> 	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_XXX_HEADER],
> 				      info->extack);
> 
> So, when tb is NULL (such as in the ethnl notify path), we have a nice
> crash.
> 
> It turns out that there's only the PLCA command that is in that case, as
> the other phydev-specific commands don't have a notification.
> 
> This commit fixes the crash by passing the cmd index and the nlattr
> array separately, allowing NULL-checking it directly inside the helper.
> 
> Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some commands")
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>

Well, this alone doesn't look too bad.. :) Hopefully we can address
adding more suitable handlers for phy ops in net-next.

Didn't someone report this, tho? I vaguely remember seeing an email,
unless they said they don't want to be credited maybe we should add
a Reported-by tag? You can post it in reply, no need to repost 
the patch.


From yepeilin at google.com  Mon Mar  3 16:14:16 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:14:16 +0000
Subject: [PATCH bpf-next v5 4/6] bpf, arm64: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <fb4784d569abe2ba66e33833e3e64c168a87465d.1741046028.git.yepeilin@google.com>

Support BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions in the arm64 JIT compiler.  For example
(assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))
  95 00 00 00 00 00 00 00  exit

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

The JIT compiler would emit an LDAR instruction for the above, e.g.:

  ldar  x7, [x0]

Similarly, consider the following 16-bit store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)
  95 00 00 00 00 00 00 00  exit

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

An STLRH instruction would be emitted, e.g.:

  stlrh  w1, [x0]

For a complete mapping:

  load-acquire     8-bit  LDARB
 (BPF_LOAD_ACQ)   16-bit  LDARH
                  32-bit  LDAR (32-bit)
                  64-bit  LDAR (64-bit)
  store-release    8-bit  STLRB
 (BPF_STORE_REL)  16-bit  STLRH
                  32-bit  STLR (32-bit)
                  64-bit  STLR (64-bit)

Arena accesses are supported.
bpf_jit_supports_insn(..., /*in_arena=*/true) always returns true for
BPF_LOAD_ACQ and BPF_STORE_REL instructions, as they don't depend on
ARM64_HAS_LSE_ATOMICS.

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit.h      | 20 ++++++++
 arch/arm64/net/bpf_jit_comp.c | 90 ++++++++++++++++++++++++++++++++---
 2 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index b22ab2f97a30..a3b0e693a125 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -119,6 +119,26 @@
 	aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \
 				       AARCH64_INSN_LDST_STORE_REL_EX)
 
+/* Load-acquire & store-release */
+#define A64_LDAR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_LOAD_ACQ)
+#define A64_STLR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_STORE_REL)
+
+/* Rt = [Rn] (load acquire) */
+#define A64_LDARB(Wt, Xn)	A64_LDAR(Wt, Xn, 8)
+#define A64_LDARH(Wt, Xn)	A64_LDAR(Wt, Xn, 16)
+#define A64_LDAR32(Wt, Xn)	A64_LDAR(Wt, Xn, 32)
+#define A64_LDAR64(Xt, Xn)	A64_LDAR(Xt, Xn, 64)
+
+/* [Rn] = Rt (store release) */
+#define A64_STLRB(Wt, Xn)	A64_STLR(Wt, Xn, 8)
+#define A64_STLRH(Wt, Xn)	A64_STLR(Wt, Xn, 16)
+#define A64_STLR32(Wt, Xn)	A64_STLR(Wt, Xn, 32)
+#define A64_STLR64(Xt, Xn)	A64_STLR(Xt, Xn, 64)
+
 /*
  * LSE atomics
  *
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index bdda5a77bb16..70d7c89d3ac9 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -647,6 +647,81 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
 	return 0;
 }
 
+static int emit_atomic_ld_st(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s32 imm = insn->imm;
+	const s16 off = insn->off;
+	const u8 code = insn->code;
+	const bool arena = BPF_MODE(code) == BPF_PROBE_ATOMIC;
+	const u8 arena_vm_base = bpf2a64[ARENA_VM_START];
+	const u8 dst = bpf2a64[insn->dst_reg];
+	const u8 src = bpf2a64[insn->src_reg];
+	const u8 tmp = bpf2a64[TMP_REG_1];
+	u8 reg;
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		reg = src;
+		break;
+	case BPF_STORE_REL:
+		reg = dst;
+		break;
+	default:
+		pr_err_once("unknown atomic load/store op code %02x\n", imm);
+		return -EINVAL;
+	}
+
+	if (off) {
+		emit_a64_add_i(1, tmp, reg, tmp, off, ctx);
+		reg = tmp;
+	}
+	if (arena) {
+		emit(A64_ADD(1, tmp, reg, arena_vm_base), ctx);
+		reg = tmp;
+	}
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_LDARB(dst, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_LDARH(dst, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_LDAR32(dst, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_LDAR64(dst, reg), ctx);
+			break;
+		}
+		break;
+	case BPF_STORE_REL:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_STLRB(src, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_STLRH(src, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_STLR32(src, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_STLR64(src, reg), ctx);
+			break;
+		}
+		break;
+	default:
+		pr_err_once("unexpected atomic load/store op code %02x\n",
+			    imm);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
 {
@@ -1641,11 +1716,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
 			return ret;
 		break;
 
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
-		if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (bpf_atomic_is_load_store(insn))
+			ret = emit_atomic_ld_st(insn, ctx);
+		else if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			ret = emit_lse_atomic(insn, ctx);
 		else
 			ret = emit_ll_sc_atomic(insn, ctx);
@@ -2667,13 +2748,10 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
-		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (!bpf_atomic_is_load_store(insn) &&
+		    !cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
 	return true;
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:14:22 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:14:22 +0000
Subject: [PATCH bpf-next v5 5/6] bpf, x86: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <c4b2b97086e214ee24aafeb5f57cb1275a4469ef.1741046028.git.yepeilin@google.com>

Recently we introduced BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions.  For x86-64, simply implement them as
regular BPF_LDX/BPF_STX loads and stores.  The verifier always rejects
misaligned load-acquires/store-releases (even if BPF_F_ANY_ALIGNMENT is
set), so emitted MOV* instructions are guaranteed to be atomic.

Arena accesses are supported.  8- and 16-bit load-acquires are
zero-extending (i.e., MOVZBQ, MOVZWQ).

Rename emit_atomic{,_index}() to emit_atomic_rmw{,_index}() to make it
clear that they only handle read-modify-write atomics, and extend their
@atomic_op parameter from u8 to u32, since we are starting to use more
than the lowest 8 bits of the 'imm' field.

Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/x86/net/bpf_jit_comp.c | 99 ++++++++++++++++++++++++++++++-------
 1 file changed, 82 insertions(+), 17 deletions(-)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index f0c31c940fb8..0263d98d92b0 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1242,8 +1242,8 @@ static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
 	emit_st_index(pprog, size, dst_reg, X86_REG_R12, off, imm);
 }
 
-static int emit_atomic(u8 **pprog, u8 atomic_op,
-		       u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
+static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
+			   u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
 {
 	u8 *prog = *pprog;
 
@@ -1283,8 +1283,9 @@ static int emit_atomic(u8 **pprog, u8 atomic_op,
 	return 0;
 }
 
-static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
-			     u32 dst_reg, u32 src_reg, u32 index_reg, int off)
+static int emit_atomic_rmw_index(u8 **pprog, u32 atomic_op, u32 size,
+				 u32 dst_reg, u32 src_reg, u32 index_reg,
+				 int off)
 {
 	u8 *prog = *pprog;
 
@@ -1297,7 +1298,7 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 		EMIT1(add_3mod(0x48, dst_reg, src_reg, index_reg));
 		break;
 	default:
-		pr_err("bpf_jit: 1 and 2 byte atomics are not supported\n");
+		pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
 		return -EFAULT;
 	}
 
@@ -1331,6 +1332,49 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 	return 0;
 }
 
+static int emit_atomic_ld_st(u8 **pprog, u32 atomic_op, u32 dst_reg,
+			     u32 src_reg, s16 off, u8 bpf_size)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + off16) */
+		emit_ldx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + off16, src_reg) */
+		emit_stx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int emit_atomic_ld_st_index(u8 **pprog, u32 atomic_op, u32 size,
+				   u32 dst_reg, u32 src_reg, u32 index_reg,
+				   int off)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + idx_reg + off16) */
+		emit_ldx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + idx_reg + off16, src_reg) */
+		emit_stx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
 #define DONT_CLEAR 1
 
 bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
@@ -2113,6 +2157,13 @@ st:			if (is_imm8(insn->off))
 			}
 			break;
 
+		case BPF_STX | BPF_ATOMIC | BPF_B:
+		case BPF_STX | BPF_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_ATOMIC | BPF_W:
 		case BPF_STX | BPF_ATOMIC | BPF_DW:
 			if (insn->imm == (BPF_AND | BPF_FETCH) ||
@@ -2148,10 +2199,10 @@ st:			if (is_imm8(insn->off))
 				EMIT2(simple_alu_opcodes[BPF_OP(insn->imm)],
 				      add_2reg(0xC0, AUX_REG, real_src_reg));
 				/* Attempt to swap in new value */
-				err = emit_atomic(&prog, BPF_CMPXCHG,
-						  real_dst_reg, AUX_REG,
-						  insn->off,
-						  BPF_SIZE(insn->code));
+				err = emit_atomic_rmw(&prog, BPF_CMPXCHG,
+						      real_dst_reg, AUX_REG,
+						      insn->off,
+						      BPF_SIZE(insn->code));
 				if (WARN_ON(err))
 					return err;
 				/*
@@ -2166,17 +2217,35 @@ st:			if (is_imm8(insn->off))
 				break;
 			}
 
-			err = emit_atomic(&prog, insn->imm, dst_reg, src_reg,
-					  insn->off, BPF_SIZE(insn->code));
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st(&prog, insn->imm, dst_reg, src_reg,
+							insn->off, BPF_SIZE(insn->code));
+			else
+				err = emit_atomic_rmw(&prog, insn->imm, dst_reg, src_reg,
+						      insn->off, BPF_SIZE(insn->code));
 			if (err)
 				return err;
 			break;
 
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
 			start_of_ldx = prog;
-			err = emit_atomic_index(&prog, insn->imm, BPF_SIZE(insn->code),
-						dst_reg, src_reg, X86_REG_R12, insn->off);
+
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st_index(&prog, insn->imm,
+							      BPF_SIZE(insn->code), dst_reg,
+							      src_reg, X86_REG_R12, insn->off);
+			else
+				err = emit_atomic_rmw_index(&prog, insn->imm, BPF_SIZE(insn->code),
+							    dst_reg, src_reg, X86_REG_R12,
+							    insn->off);
 			if (err)
 				return err;
 			goto populate_extable;
@@ -3771,12 +3840,8 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:14:31 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:14:31 +0000
Subject: [PATCH bpf-next v5 6/6] selftests/bpf: Add selftests for load-acquire
 and store-release instructions
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <cb63b671bb558eb2371bdf4d0c027d7d5ecd3999.1741046028.git.yepeilin@google.com>

Add several ./test_progs tests:

  - arena_atomics/load_acquire
  - arena_atomics/store_release
  - verifier_load_acquire/*
  - verifier_store_release/*
  - verifier_precision/bpf_load_acquire
  - verifier_precision/bpf_store_release

The last two tests are added to check if backtrack_insn() handles the
new instructions correctly.

Additionally, the last test also makes sure that the verifier
"remembers" the value (in src_reg) we store-release into e.g. a stack
slot.  For example, if we take a look at the test program:

    #0:  r1 = 8;
      /* store_release((u64 *)(r10 - 8), r1); */
    #1:  .8byte %[store_release];
    #2:  r1 = *(u64 *)(r10 - 8);
    #3:  r2 = r10;
    #4:  r2 += r1;
    #5:  r0 = 0;
    #6:  exit;

At #1, if the verifier doesn't remember that we wrote 8 to the stack,
then later at #4 we would be adding an unbounded scalar value to the
stack pointer, which would cause the program to be rejected:

  VERIFIER LOG:
  =============
...
  math between fp pointer and register with unbounded min value is not allowed

For easier CI integration, instead of using built-ins like
__atomic_{load,store}_n() which depend on the new
__BPF_FEATURE_LOAD_ACQ_STORE_REL pre-defined macro, manually craft
load-acquire/store-release instructions using __imm_insn(), as suggested
by Eduard.

All new tests depend on:

  (1) Clang major version >= 18, and
  (2) ENABLE_ATOMICS_TESTS is defined (currently implies -mcpu=v3 or
      v4), and
  (3) JIT supports load-acquire/store-release (currently arm64 and
      x86-64)

In .../progs/arena_atomics.c:

  /* 8-byte-aligned */
  __u8 __arena_global load_acquire8_value = 0x12;
  /* 1-byte hole */
  __u16 __arena_global load_acquire16_value = 0x1234;

That 1-byte hole in the .addr_space.1 ELF section caused clang-17 to
crash:

  fatal error: error in backend: unable to write nop sequence of 1 bytes

To work around such llvm-17 CI job failures, conditionally define
__arena_global variables as 64-bit if __clang_major__ < 18, to make sure
.addr_space.1 has no holes.  Ideally we should avoid compiling this file
using clang-17 at all (arena tests depend on
__BPF_FEATURE_ADDR_SPACE_CAST, and are skipped for llvm-17 anyway), but
that is a separate topic.

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 6 files changed, 698 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
index 26e7c06c6cb4..d98577a6babc 100644
--- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
+++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
@@ -162,6 +162,66 @@ static void test_uaf(struct arena_atomics *skel)
 	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
 }
 
+static void test_load_acquire(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support load-acquire\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.load_acquire);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->load_acquire8_result, 0x12,
+		  "load_acquire8_result");
+	ASSERT_EQ(skel->arena->load_acquire16_result, 0x1234,
+		  "load_acquire16_result");
+	ASSERT_EQ(skel->arena->load_acquire32_result, 0x12345678,
+		  "load_acquire32_result");
+	ASSERT_EQ(skel->arena->load_acquire64_result, 0x1234567890abcdef,
+		  "load_acquire64_result");
+}
+
+static void test_store_release(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support store-release\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.store_release);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->store_release8_result, 0x12,
+		  "store_release8_result");
+	ASSERT_EQ(skel->arena->store_release16_result, 0x1234,
+		  "store_release16_result");
+	ASSERT_EQ(skel->arena->store_release32_result, 0x12345678,
+		  "store_release32_result");
+	ASSERT_EQ(skel->arena->store_release64_result, 0x1234567890abcdef,
+		  "store_release64_result");
+}
+
 void test_arena_atomics(void)
 {
 	struct arena_atomics *skel;
@@ -171,7 +231,7 @@ void test_arena_atomics(void)
 	if (!ASSERT_OK_PTR(skel, "arena atomics skeleton open"))
 		return;
 
-	if (skel->data->skip_tests) {
+	if (skel->data->skip_all_tests) {
 		printf("%s:SKIP:no ENABLE_ATOMICS_TESTS or no addr_space_cast support in clang",
 		       __func__);
 		test__skip();
@@ -198,6 +258,10 @@ void test_arena_atomics(void)
 		test_xchg(skel);
 	if (test__start_subtest("uaf"))
 		test_uaf(skel);
+	if (test__start_subtest("load_acquire"))
+		test_load_acquire(skel);
+	if (test__start_subtest("store_release"))
+		test_store_release(skel);
 
 cleanup:
 	arena_atomics__destroy(skel);
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index 8a0e1ff8a2dc..cfe47b529e01 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -45,6 +45,7 @@
 #include "verifier_ldsx.skel.h"
 #include "verifier_leak_ptr.skel.h"
 #include "verifier_linked_scalars.skel.h"
+#include "verifier_load_acquire.skel.h"
 #include "verifier_loops1.skel.h"
 #include "verifier_lwt.skel.h"
 #include "verifier_map_in_map.skel.h"
@@ -80,6 +81,7 @@
 #include "verifier_spill_fill.skel.h"
 #include "verifier_spin_lock.skel.h"
 #include "verifier_stack_ptr.skel.h"
+#include "verifier_store_release.skel.h"
 #include "verifier_subprog_precision.skel.h"
 #include "verifier_subreg.skel.h"
 #include "verifier_tailcall_jit.skel.h"
@@ -173,6 +175,7 @@ void test_verifier_int_ptr(void)              { RUN(verifier_int_ptr); }
 void test_verifier_iterating_callbacks(void)  { RUN(verifier_iterating_callbacks); }
 void test_verifier_jeq_infer_not_null(void)   { RUN(verifier_jeq_infer_not_null); }
 void test_verifier_jit_convergence(void)      { RUN(verifier_jit_convergence); }
+void test_verifier_load_acquire(void)         { RUN(verifier_load_acquire); }
 void test_verifier_ld_ind(void)               { RUN(verifier_ld_ind); }
 void test_verifier_ldsx(void)                  { RUN(verifier_ldsx); }
 void test_verifier_leak_ptr(void)             { RUN(verifier_leak_ptr); }
@@ -211,6 +214,7 @@ void test_verifier_sockmap_mutate(void)       { RUN(verifier_sockmap_mutate); }
 void test_verifier_spill_fill(void)           { RUN(verifier_spill_fill); }
 void test_verifier_spin_lock(void)            { RUN(verifier_spin_lock); }
 void test_verifier_stack_ptr(void)            { RUN(verifier_stack_ptr); }
+void test_verifier_store_release(void)        { RUN(verifier_store_release); }
 void test_verifier_subprog_precision(void)    { RUN(verifier_subprog_precision); }
 void test_verifier_subreg(void)               { RUN(verifier_subreg); }
 void test_verifier_tailcall_jit(void)         { RUN(verifier_tailcall_jit); }
diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/testing/selftests/bpf/progs/arena_atomics.c
index 40dd57fca5cc..a52feff98112 100644
--- a/tools/testing/selftests/bpf/progs/arena_atomics.c
+++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
@@ -6,6 +6,8 @@
 #include <stdbool.h>
 #include <stdatomic.h>
 #include "bpf_arena_common.h"
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
 
 struct {
 	__uint(type, BPF_MAP_TYPE_ARENA);
@@ -19,9 +21,17 @@ struct {
 } arena SEC(".maps");
 
 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST)
-bool skip_tests __attribute((__section__(".data"))) = false;
+bool skip_all_tests __attribute((__section__(".data"))) = false;
 #else
-bool skip_tests = true;
+bool skip_all_tests = true;
+#endif
+
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+bool skip_lacq_srel_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_lacq_srel_tests = true;
 #endif
 
 __u32 pid = 0;
@@ -274,4 +284,111 @@ int uaf(const void *ctx)
 	return 0;
 }
 
+#if __clang_major__ >= 18
+__u8 __arena_global load_acquire8_value = 0x12;
+__u16 __arena_global load_acquire16_value = 0x1234;
+__u32 __arena_global load_acquire32_value = 0x12345678;
+__u64 __arena_global load_acquire64_value = 0x1234567890abcdef;
+
+__u8 __arena_global load_acquire8_result = 0;
+__u16 __arena_global load_acquire16_result = 0;
+__u32 __arena_global load_acquire32_result = 0;
+__u64 __arena_global load_acquire64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global load_acquire8_value;
+__u64 __arena_global load_acquire16_value;
+__u64 __arena_global load_acquire32_value;
+__u64 __arena_global load_acquire64_value;
+
+__u64 __arena_global load_acquire8_result;
+__u64 __arena_global load_acquire16_result;
+__u64 __arena_global load_acquire32_result;
+__u64 __arena_global load_acquire64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int load_acquire(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define LOAD_ACQUIRE_ARENA(SIZEOP, SIZE, SRC, DST)	\
+	{ asm volatile (				\
+	"r1 = %[" #SRC "] ll;"				\
+	"r1 = addr_space_cast(r1, 0x0, 0x1);"		\
+	".8byte %[load_acquire_insn];"			\
+	"r3 = %[" #DST "] ll;"				\
+	"r3 = addr_space_cast(r3, 0x0, 0x1);"		\
+	"*(" #SIZE " *)(r3 + 0) = r2;"			\
+	:						\
+	: __imm_addr(SRC),				\
+	  __imm_insn(load_acquire_insn,			\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_LOAD_ACQ,	\
+				   BPF_REG_2, BPF_REG_1, 0)),	\
+	  __imm_addr(DST)				\
+	: __clobber_all); }				\
+
+	LOAD_ACQUIRE_ARENA(B, u8, load_acquire8_value, load_acquire8_result)
+	LOAD_ACQUIRE_ARENA(H, u16, load_acquire16_value,
+			   load_acquire16_result)
+	LOAD_ACQUIRE_ARENA(W, u32, load_acquire32_value,
+			   load_acquire32_result)
+	LOAD_ACQUIRE_ARENA(DW, u64, load_acquire64_value,
+			   load_acquire64_result)
+#undef LOAD_ACQUIRE_ARENA
+
+#endif
+	return 0;
+}
+
+#if __clang_major__ >= 18
+__u8 __arena_global store_release8_result = 0;
+__u16 __arena_global store_release16_result = 0;
+__u32 __arena_global store_release32_result = 0;
+__u64 __arena_global store_release64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global store_release8_result;
+__u64 __arena_global store_release16_result;
+__u64 __arena_global store_release32_result;
+__u64 __arena_global store_release64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int store_release(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define STORE_RELEASE_ARENA(SIZEOP, DST, VAL)	\
+	{ asm volatile (			\
+	"r1 = " VAL ";"				\
+	"r2 = %[" #DST "] ll;"			\
+	"r2 = addr_space_cast(r2, 0x0, 0x1);"	\
+	".8byte %[store_release_insn];"		\
+	:					\
+	: __imm_addr(DST),			\
+	  __imm_insn(store_release_insn,	\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_STORE_REL,	\
+				   BPF_REG_2, BPF_REG_1, 0))	\
+	: __clobber_all); }			\
+
+	STORE_RELEASE_ARENA(B, store_release8_result, "0x12")
+	STORE_RELEASE_ARENA(H, store_release16_result, "0x1234")
+	STORE_RELEASE_ARENA(W, store_release32_result, "0x12345678")
+	STORE_RELEASE_ARENA(DW, store_release64_result,
+			    "0x1234567890abcdef ll")
+#undef STORE_RELEASE_ARENA
+
+#endif
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
new file mode 100644
index 000000000000..ff308f24d745
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("load-acquire, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void load_acquire_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	"*(u8 *)(r10 - 1) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r10 - 1));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void load_acquire_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	"*(u16 *)(r10 - 2) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u16 *)(r10 - 2));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void load_acquire_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	"*(u32 *)(r10 - 4) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 4));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void load_acquire_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r10 - 8));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void load_acquire_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with non-pointer src_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void load_acquire_with_non_pointer_src_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned load-acquire")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void load_acquire_misaligned(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 5));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire from ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC loads from R1 ctx is not allowed")
+__naked void load_acquire_from_ctx_pointer(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("load-acquire from pkt pointer")
+__failure __msg("BPF_ATOMIC loads from R2 pkt is not allowed")
+__naked void load_acquire_from_pkt_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("load-acquire from flow_keys pointer")
+__failure __msg("BPF_ATOMIC loads from R2 flow_keys is not allowed")
+__naked void load_acquire_from_flow_keys_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("load-acquire from sock pointer")
+__failure __msg("BPF_ATOMIC loads from R2 sock is not allowed")
+__naked void load_acquire_from_sock_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support load-acquire, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 6b564d4c0986..6662d4b39969 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -2,6 +2,7 @@
 /* Copyright (C) 2023 SUSE LLC */
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
 #include "bpf_misc.h"
 
 SEC("?raw_tp")
@@ -90,6 +91,54 @@ __naked int bpf_end_bswap(void)
 		::: __clobber_all);
 }
 
+#if defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r3 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (db) r2 = load_acquire((u64 *)(r10 -8))")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (7b) *(u64 *)(r10 -8) = r1")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_load_acquire(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" /* r2 = load_acquire((u64 *)(r10 - 8)); */
+	"r3 = r10;"
+	"r3 += r2;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r1 stack= before 3: (bf) r2 = r10")
+__msg("mark_precise: frame0: regs=r1 stack= before 2: (79) r1 = *(u64 *)(r10 -8)")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (db) store_release((u64 *)(r10 -8), r1)")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_store_release(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	".8byte %[store_release_insn];" /* store_release((u64 *)(r10 - 8), r1); */
+	"r1 = *(u64 *)(r10 - 8);"
+	"r2 = r10;"
+	"r2 += r1;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+#endif /* load-acquire, store-release */
 #endif /* v4 instruction */
 
 SEC("?raw_tp")
diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/tools/testing/selftests/bpf/progs/verifier_store_release.c
new file mode 100644
index 000000000000..f1c64c08f25f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("store-release, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void store_release_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1);
+	"w0 = *(u8 *)(r10 - 1);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void store_release_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1);
+	"w0 = *(u16 *)(r10 - 2);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void store_release_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1);
+	"w0 = *(u32 *)(r10 - 4);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void store_release_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = *(u64 *)(r10 - 8);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r2);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_2, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized dst_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r2 - 8), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with non-pointer dst_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void store_release_with_non_pointer_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r1 + 0), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_1, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned store-release")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void store_release_misaligned(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 5), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_0, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release to ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC stores into R1 ctx is not allowed")
+__naked void store_release_to_ctx_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r1 + 0), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_1, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("store-release to pkt pointer")
+__failure __msg("BPF_ATOMIC stores into R2 pkt is not allowed")
+__naked void store_release_to_pkt_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("store-release to flow_keys pointer")
+__failure __msg("BPF_ATOMIC stores into R2 flow_keys is not allowed")
+__naked void store_release_to_flow_keys_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("store-release to sock pointer")
+__failure __msg("BPF_ATOMIC stores into R2 sock is not allowed")
+__naked void store_release_to_sock_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, leak pointer to stack")
+__success __success_unpriv __retval(0)
+__naked void store_release_leak_pointer_to_stack(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 1);
+	__type(key, long long);
+	__type(value, long long);
+} map_hash_8b SEC(".maps");
+
+SEC("socket")
+__description("store-release, leak pointer to map")
+__success __retval(0)
+__failure_unpriv __msg_unpriv("R6 leaks addr into map")
+__naked void store_release_leak_pointer_to_map(void)
+{
+	asm volatile (
+	"r6 = r1;"
+	"r1 = %[map_hash_8b] ll;"
+	"r2 = 0;"
+	"*(u64 *)(r10 - 8) = r2;"
+	"r2 = r10;"
+	"r2 += -8;"
+	"call %[bpf_map_lookup_elem];"
+	"if r0 == 0 goto l0_%=;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r0 + 0), r6);
+"l0_%=:"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_addr(map_hash_8b),
+	  __imm(bpf_map_lookup_elem),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_0, BPF_REG_6, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support store-release, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:13:19 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:13:19 +0000
Subject: [PATCH bpf-next v5 0/6] Introduce load-acquire and store-release BPF instructions
Message-ID: <cover.1741046028.git.yepeilin@google.com>

Hi all!

This patchset adds kernel support for BPF load-acquire and store-release
instructions (for background, please see [1]), including core/verifier
and arm64/x86-64 JIT compiler changes, as well as selftests.  riscv64 is
also planned to be supported.  The corresponding LLVM changes can be
found at:

  https://github.com/llvm/llvm-project/pull/108636

The first 3 patches from v4 have already been applied:

  - [bpf-next,v4,01/10] bpf/verifier: Factor out atomic_ptr_type_ok()
    https://git.kernel.org/bpf/bpf-next/c/b2d9ef71d4c9
  - [bpf-next,v4,02/10] bpf/verifier: Factor out check_atomic_rmw()
    https://git.kernel.org/bpf/bpf-next/c/d430c46c7580
  - [bpf-next,v4,03/10] bpf/verifier: Factor out check_load_mem() and check_store_reg()
    https://git.kernel.org/bpf/bpf-next/c/d38ad248fb7a

Please refer to the LLVM PR and individual kernel patches for details.
Thanks!

v4: https://lore.kernel.org/bpf/cover.1740978603.git.yepeilin at google.com/
v4..v5 notable changes:

  o (kernel test robot) for 32-bit arches: make the verifier reject
                        64-bit load-acquires/store-releases, and fix
                        build error in interpreter changes
    * tested ARCH=arc build following instructions from kernel test
      robot
  o (Alexei) drop Documentation/ patch (v4 10/10) for now

v3: https://lore.kernel.org/bpf/cover.1740009184.git.yepeilin at google.com/
v3..v4 notable changes:

  o (Alexei) add x86-64 JIT support (including arena)
  o add Acked-by: tags from Xu

v2: https://lore.kernel.org/bpf/cover.1738888641.git.yepeilin at google.com/
v2..v3 notable changes:

  o (Alexei) change encoding to BPF_LOAD_ACQ=0x100, BPF_STORE_REL=0x110
  o add Acked-by: tags from Ilya and Eduard
  o make new selftests depend on:
    * __clang_major__ >= 18, and
    * ENABLE_ATOMICS_TESTS is defined (currently this means -mcpu=v3 or
      v4), and
    * JIT supports load_acq/store_rel (currenty only arm64)
  o work around llvm-17 CI job failure by conditionally define
    __arena_global variables as 64-bit if __clang_major__ < 18, to make
    sure .addr_space.1 has no holes
  o add Google copyright notice in new files

v1: https://lore.kernel.org/all/cover.1737763916.git.yepeilin at google.com/
v1..v2 notable changes:

  o (Eduard) for x86 and s390, make
             bpf_jit_supports_insn(..., /*in_arena=*/true) return false
	     for load_acq/store_rel
  o add Eduard's Acked-by: tag
  o (Eduard) extract LDX and non-ATOMIC STX handling into helpers, see
             PATCH v2 3/9
  o allow unpriv programs to store-release pointers to stack
  o (Alexei) make it clearer in the interpreter code (PATCH v2 4/9) that
             only W and DW are supported for atomic RMW
  o test misaligned load_acq/store_rel
  o (Eduard) other selftests/ changes:
    * test load_acq/store_rel with !atomic_ptr_type_ok() pointers:
      - PTR_TO_CTX, for is_ctx_reg()
      - PTR_TO_PACKET, for is_pkt_reg()
      - PTR_TO_FLOW_KEYS, for is_flow_key_reg()
      - PTR_TO_SOCKET, for is_sk_reg()
    * drop atomics/ tests
    * delete unnecessary 'pid' checks from arena_atomics/ tests
    * avoid depending on __BPF_FEATURE_LOAD_ACQ_STORE_REL, use
      __imm_insn() and inline asm macros instead

RFC v1: https://lore.kernel.org/all/cover.1734742802.git.yepeilin at google.com
RFC v1..v1 notable changes:

  o 1-2/8: minor verifier.c refactoring patches
  o   3/8: core/verifier changes
         * (Eduard) handle load-acquire properly in backtrack_insn()
         * (Eduard) avoid skipping checks (e.g.,
                    bpf_jit_supports_insn()) for load-acquires
         * track the value stored by store-releases, just like how
           non-atomic STX instructions are handled
         * (Eduard) add missing link in commit message
         * (Eduard) always print 'r' for disasm.c changes
  o   4/8: arm64/insn: avoid treating load_acq/store_rel as
           load_ex/store_ex
  o   5/8: arm64/insn: add load_acq/store_rel
         * (Xu) include Should-Be-One (SBO) bits in "mask" and "value",
                to avoid setting fixed bits during runtime (JIT-compile
                time)
  o   6/8: arm64 JIT compiler changes
         * (Xu) use emit_a64_add_i() for "pointer + offset" to optimize
                code emission
  o   7/8: selftests
         * (Eduard) avoid adding new tests to the 'test_verifier' runner
         * add more tests, e.g., checking mark_precise logic
  o   8/8: instruction-set.rst changes

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Thanks,
Peilin Ye (6):
  bpf: Introduce load-acquire and store-release instructions
  arm64: insn: Add BIT(23) to {load,store}_ex's mask
  arm64: insn: Add load-acquire and store-release instructions
  bpf, arm64: Support load-acquire and store-release instructions
  bpf, x86: Support load-acquire and store-release instructions
  selftests/bpf: Add selftests for load-acquire and store-release
    instructions

 arch/arm64/include/asm/insn.h                 |  12 +-
 arch/arm64/lib/insn.c                         |  29 ++
 arch/arm64/net/bpf_jit.h                      |  20 ++
 arch/arm64/net/bpf_jit_comp.c                 |  86 +++++-
 arch/s390/net/bpf_jit_comp.c                  |  14 +-
 arch/x86/net/bpf_jit_comp.c                   |  95 ++++++-
 include/linux/bpf.h                           |  15 +
 include/linux/filter.h                        |   2 +
 include/uapi/linux/bpf.h                      |   3 +
 kernel/bpf/core.c                             |  67 ++++-
 kernel/bpf/disasm.c                           |  12 +
 kernel/bpf/verifier.c                         |  59 +++-
 tools/include/uapi/linux/bpf.h                |   3 +
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 19 files changed, 1085 insertions(+), 33 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:13:42 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:13:42 +0000
Subject: [PATCH bpf-next v5 1/6] bpf: Introduce load-acquire and store-release instructions
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>

Introduce BPF instructions with load-acquire and store-release
semantics, as discussed in [1].  Define 2 new flags:

  #define BPF_LOAD_ACQ    0x100
  #define BPF_STORE_REL   0x110

A "load-acquire" is a BPF_STX | BPF_ATOMIC instruction with the 'imm'
field set to BPF_LOAD_ACQ (0x100).

Similarly, a "store-release" is a BPF_STX | BPF_ATOMIC instruction with
the 'imm' field set to BPF_STORE_REL (0x110).

Unlike existing atomic read-modify-write operations that only support
BPF_W (32-bit) and BPF_DW (64-bit) size modifiers, load-acquires and
store-releases also support BPF_B (8-bit) and BPF_H (16-bit).  As an
exception, however, 64-bit load-acquires/store-releases are not
supported on 32-bit architectures (to fix a build error reported by the
kernel test robot).

An 8- or 16-bit load-acquire zero-extends the value before writing it to
a 32-bit register, just like ARM64 instruction LDARH and friends.

Similar to existing atomic read-modify-write operations, misaligned
load-acquires/store-releases are not allowed (even if
BPF_F_ANY_ALIGNMENT is set).

As an example, consider the following 64-bit load-acquire BPF
instruction (assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

Similarly, a 16-bit BPF store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

In arch/{arm64,s390,x86}/net/bpf_jit_comp.c, have
bpf_jit_supports_insn(..., /*in_arena=*/true) return false for the new
instructions, until the corresponding JIT compiler supports them in
arena.

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Acked-by: Ilya Leoshkevich <iii at linux.ibm.com>
Cc: kernel test robot <lkp at intel.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit_comp.c  |  4 ++
 arch/s390/net/bpf_jit_comp.c   | 14 +++++--
 arch/x86/net/bpf_jit_comp.c    |  4 ++
 include/linux/bpf.h            | 15 ++++++++
 include/linux/filter.h         |  2 +
 include/uapi/linux/bpf.h       |  3 ++
 kernel/bpf/core.c              | 67 +++++++++++++++++++++++++++++++---
 kernel/bpf/disasm.c            | 12 ++++++
 kernel/bpf/verifier.c          | 59 ++++++++++++++++++++++++++++--
 tools/include/uapi/linux/bpf.h |  3 ++
 10 files changed, 170 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 7409c8acbde3..bdda5a77bb16 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -2667,8 +2667,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9d440a0b729e..0776dfde2dba 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -2919,10 +2919,16 @@ bool bpf_jit_supports_arena(void)
 
 bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 {
-	/*
-	 * Currently the verifier uses this function only to check which
-	 * atomic stores to arena are supported, and they all are.
-	 */
+	if (!in_arena)
+		return true;
+	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
+	case BPF_STX | BPF_ATOMIC | BPF_W:
+	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
+	}
 	return true;
 }
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a43fc5af973d..f0c31c940fb8 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3771,8 +3771,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 4c4028d865ee..b556a26d8150 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -991,6 +991,21 @@ static inline bool bpf_pseudo_func(const struct bpf_insn *insn)
 	return bpf_is_ldimm64(insn) && insn->src_reg == BPF_PSEUDO_FUNC;
 }
 
+/* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
+ * atomic load or store, and false if it is a read-modify-write instruction.
+ */
+static inline bool
+bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
+{
+	switch (atomic_insn->imm) {
+	case BPF_LOAD_ACQ:
+	case BPF_STORE_REL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 struct bpf_prog_ops {
 	int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
 			union bpf_attr __user *uattr);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3ed6eb9e7c73..24e94afb5622 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -364,6 +364,8 @@ static inline bool insn_is_cast_user(const struct bpf_insn *insn)
  *   BPF_XOR | BPF_FETCH      src_reg = atomic_fetch_xor(dst_reg + off16, src_reg);
  *   BPF_XCHG                 src_reg = atomic_xchg(dst_reg + off16, src_reg)
  *   BPF_CMPXCHG              r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg)
+ *   BPF_LOAD_ACQ             dst_reg = smp_load_acquire(src_reg + off16)
+ *   BPF_STORE_REL            smp_store_release(dst_reg + off16, src_reg)
  */
 
 #define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF)			\
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index a0200fbbace9..6df1d3e379a4 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1663,14 +1663,17 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
 	INSN_3(JMP, JSET, K),			\
 	INSN_2(JMP, JA),			\
 	INSN_2(JMP32, JA),			\
+	/* Atomic operations. */		\
+	INSN_3(STX, ATOMIC, B),			\
+	INSN_3(STX, ATOMIC, H),			\
+	INSN_3(STX, ATOMIC, W),			\
+	INSN_3(STX, ATOMIC, DW),		\
 	/* Store instructions. */		\
 	/*   Register based. */			\
 	INSN_3(STX, MEM,  B),			\
 	INSN_3(STX, MEM,  H),			\
 	INSN_3(STX, MEM,  W),			\
 	INSN_3(STX, MEM,  DW),			\
-	INSN_3(STX, ATOMIC, W),			\
-	INSN_3(STX, ATOMIC, DW),		\
 	/*   Immediate based. */		\
 	INSN_3(ST, MEM, B),			\
 	INSN_3(ST, MEM, H),			\
@@ -2152,24 +2155,33 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				atomic_##KOP((u32) SRC, (atomic_t *)(unsigned long) \
 					     (DST + insn->off));	\
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				atomic64_##KOP((u64) SRC, (atomic64_t *)(unsigned long) \
 					       (DST + insn->off));	\
+			else						\
+				goto default_label;			\
 			break;						\
 		case BOP | BPF_FETCH:					\
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				SRC = (u32) atomic_fetch_##KOP(		\
 					(u32) SRC,			\
 					(atomic_t *)(unsigned long) (DST + insn->off)); \
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				SRC = (u64) atomic64_fetch_##KOP(	\
 					(u64) SRC,			\
 					(atomic64_t *)(unsigned long) (DST + insn->off)); \
+			else						\
+				goto default_label;			\
 			break;
 
 	STX_ATOMIC_DW:
 	STX_ATOMIC_W:
+	STX_ATOMIC_H:
+	STX_ATOMIC_B:
 		switch (IMM) {
+		/* Atomic read-modify-write instructions support only W and DW
+		 * size modifiers.
+		 */
 		ATOMIC_ALU_OP(BPF_ADD, add)
 		ATOMIC_ALU_OP(BPF_AND, and)
 		ATOMIC_ALU_OP(BPF_OR, or)
@@ -2181,20 +2193,63 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 				SRC = (u32) atomic_xchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				SRC = (u64) atomic64_xchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) SRC);
+			else
+				goto default_label;
 			break;
 		case BPF_CMPXCHG:
 			if (BPF_SIZE(insn->code) == BPF_W)
 				BPF_R0 = (u32) atomic_cmpxchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) BPF_R0, (u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				BPF_R0 = (u64) atomic64_cmpxchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) BPF_R0, (u64) SRC);
+			else
+				goto default_label;
+			break;
+		/* Atomic load and store instructions support all size
+		 * modifiers.
+		 */
+		case BPF_LOAD_ACQ:
+			switch (BPF_SIZE(insn->code)) {
+#define LOAD_ACQUIRE(SIZEOP, SIZE)				\
+			case BPF_##SIZEOP:			\
+				DST = (SIZE)smp_load_acquire(	\
+					(SIZE *)(unsigned long)(SRC + insn->off));	\
+				break;
+			LOAD_ACQUIRE(B,   u8)
+			LOAD_ACQUIRE(H,  u16)
+			LOAD_ACQUIRE(W,  u32)
+#ifdef CONFIG_64BIT
+			LOAD_ACQUIRE(DW, u64)
+#endif
+#undef LOAD_ACQUIRE
+			default:
+				goto default_label;
+			}
+			break;
+		case BPF_STORE_REL:
+			switch (BPF_SIZE(insn->code)) {
+#define STORE_RELEASE(SIZEOP, SIZE)			\
+			case BPF_##SIZEOP:		\
+				smp_store_release(	\
+					(SIZE *)(unsigned long)(DST + insn->off), (SIZE)SRC);	\
+				break;
+			STORE_RELEASE(B,   u8)
+			STORE_RELEASE(H,  u16)
+			STORE_RELEASE(W,  u32)
+#ifdef CONFIG_64BIT
+			STORE_RELEASE(DW, u64)
+#endif
+#undef STORE_RELEASE
+			default:
+				goto default_label;
+			}
 			break;
 
 		default:
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c
index 309c4aa1b026..974d172d6735 100644
--- a/kernel/bpf/disasm.c
+++ b/kernel/bpf/disasm.c
@@ -267,6 +267,18 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
 				BPF_SIZE(insn->code) == BPF_DW ? "64" : "",
 				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
 				insn->dst_reg, insn->off, insn->src_reg);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_LOAD_ACQ) {
+			verbose(cbs->private_data, "(%02x) r%d = load_acquire((%s *)(r%d %+d))\n",
+				insn->code, insn->dst_reg,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->src_reg, insn->off);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_STORE_REL) {
+			verbose(cbs->private_data, "(%02x) store_release((%s *)(r%d %+d), r%d)\n",
+				insn->code,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->dst_reg, insn->off, insn->src_reg);
 		} else {
 			verbose(cbs->private_data, "BUG_%02x\n", insn->code);
 		}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 22c4edc8695c..a430540114da 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -579,6 +579,13 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
 	       insn->imm == BPF_CMPXCHG;
 }
 
+static bool is_atomic_load_insn(const struct bpf_insn *insn)
+{
+	return BPF_CLASS(insn->code) == BPF_STX &&
+	       BPF_MODE(insn->code) == BPF_ATOMIC &&
+	       insn->imm == BPF_LOAD_ACQ;
+}
+
 static int __get_spi(s32 off)
 {
 	return (-off - 1) / BPF_REG_SIZE;
@@ -3567,7 +3574,7 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
 	}
 
 	if (class == BPF_STX) {
-		/* BPF_STX (including atomic variants) has multiple source
+		/* BPF_STX (including atomic variants) has one or more source
 		 * operands, one of which is a ptr. Check whether the caller is
 		 * asking about it.
 		 */
@@ -4181,7 +4188,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
 			   * dreg still needs precision before this insn
 			   */
 		}
-	} else if (class == BPF_LDX) {
+	} else if (class == BPF_LDX || is_atomic_load_insn(insn)) {
 		if (!bt_is_reg_set(bt, dreg))
 			return 0;
 		bt_clear_reg(bt, dreg);
@@ -7766,6 +7773,32 @@ static int check_atomic_rmw(struct bpf_verifier_env *env,
 	return 0;
 }
 
+static int check_atomic_load(struct bpf_verifier_env *env,
+			     struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->src_reg, insn)) {
+		verbose(env, "BPF_ATOMIC loads from R%d %s is not allowed\n",
+			insn->src_reg,
+			reg_type_str(env, reg_state(env, insn->src_reg)->type));
+		return -EACCES;
+	}
+
+	return check_load_mem(env, insn, true, false, false, "atomic_load");
+}
+
+static int check_atomic_store(struct bpf_verifier_env *env,
+			      struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) {
+		verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n",
+			insn->dst_reg,
+			reg_type_str(env, reg_state(env, insn->dst_reg)->type));
+		return -EACCES;
+	}
+
+	return check_store_reg(env, insn, true);
+}
+
 static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
 	switch (insn->imm) {
@@ -7780,6 +7813,24 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 	case BPF_XCHG:
 	case BPF_CMPXCHG:
 		return check_atomic_rmw(env, insn);
+	case BPF_LOAD_ACQ:
+#ifndef CONFIG_64BIT
+		if (BPF_SIZE(insn->code) == BPF_DW) {
+			verbose(env,
+				"64-bit load-acquires are only supported on 64-bit arches\n");
+			return -EOPNOTSUPP;
+		}
+#endif
+		return check_atomic_load(env, insn);
+	case BPF_STORE_REL:
+#ifndef CONFIG_64BIT
+		if (BPF_SIZE(insn->code) == BPF_DW) {
+			verbose(env,
+				"64-bit store-releases are only supported on 64-bit arches\n");
+			return -EOPNOTSUPP;
+		}
+#endif
+		return check_atomic_store(env, insn);
 	default:
 		verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
 			insn->imm);
@@ -20605,7 +20656,9 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 			   insn->code == (BPF_ST | BPF_MEM | BPF_W) ||
 			   insn->code == (BPF_ST | BPF_MEM | BPF_DW)) {
 			type = BPF_WRITE;
-		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
+		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_B) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_H) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
 			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_DW)) &&
 			   env->insn_aux_data[i + delta].ptr_type == PTR_TO_ARENA) {
 			insn->code = BPF_STX | BPF_PROBE_ATOMIC | BPF_SIZE(insn->code);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:13:50 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:13:50 +0000
Subject: [PATCH bpf-next v5 2/6] arm64: insn: Add BIT(23) to {load,store}_ex's mask
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <e64f97503ec5b0e811ce7ed3534cd754ba81fbc3.1741046028.git.yepeilin@google.com>

We are planning to add load-acquire (LDAR{,B,H}) and store-release
(STLR{,B,H}) instructions to insn.{c,h}; add BIT(23) to mask of load_ex
and store_ex to prevent aarch64_insn_is_{load,store}_ex() from returning
false-positives for load-acquire and store-release instructions.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.228 LDXR
  * C6.2.165 LDAXR
  * C6.2.161 LDAR
  * C6.2.393 STXR
  * C6.2.360 STLXR
  * C6.2.353 STLR

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index e390c432f546..2d8316b3abaf 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -351,8 +351,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
-__AARCH64_INSN_FUNCS(load_ex,	0x3F400000, 0x08400000)
-__AARCH64_INSN_FUNCS(store_ex,	0x3F400000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
+__AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
 __AARCH64_INSN_FUNCS(stp,	0x7FC00000, 0x29000000)
 __AARCH64_INSN_FUNCS(ldp,	0x7FC00000, 0x29400000)
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 16:13:58 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 00:13:58 +0000
Subject: [PATCH bpf-next v5 3/6] arm64: insn: Add load-acquire and
 store-release instructions
In-Reply-To: <cover.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com>
Message-ID: <f2f998afa813534f94a6b36a6224e04df08f9871.1741046028.git.yepeilin@google.com>

Add load-acquire ("load_acq", LDAR{,B,H}) and store-release
("store_rel", STLR{,B,H}) instructions.  Breakdown of encoding:

                                size        L   (Rs)  o0 (Rt2) Rn    Rt
             mask (0x3fdffc00): 00 111111 1 1 0 11111 1  11111 00000 00000
  value, load_acq (0x08dffc00): 00 001000 1 1 0 11111 1  11111 00000 00000
 value, store_rel (0x089ffc00): 00 001000 1 0 0 11111 1  11111 00000 00000

As suggested by Xu [1], include all Should-Be-One (SBO) bits ("Rs" and
"Rt2" fields) in the "mask" and "value" numbers.

It is worth noting that we are adding the "no offset" variant of STLR
instead of the "pre-index" variant, which has a different encoding.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.161 LDAR
  * C6.2.353 STLR

[1] https://lore.kernel.org/bpf/4e6641ce-3f1e-4251-8daf-4dd4b77d08c4 at huaweicloud.com/

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h |  8 ++++++++
 arch/arm64/lib/insn.c         | 29 +++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 2d8316b3abaf..39577f1d079a 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -188,8 +188,10 @@ enum aarch64_insn_ldst_type {
 	AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX,
 	AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX,
 	AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX,
+	AARCH64_INSN_LDST_LOAD_ACQ,
 	AARCH64_INSN_LDST_LOAD_EX,
 	AARCH64_INSN_LDST_LOAD_ACQ_EX,
+	AARCH64_INSN_LDST_STORE_REL,
 	AARCH64_INSN_LDST_STORE_EX,
 	AARCH64_INSN_LDST_STORE_REL_EX,
 	AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET,
@@ -351,6 +353,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_acq,  0x3FDFFC00, 0x08DFFC00)
+__AARCH64_INSN_FUNCS(store_rel, 0x3FDFFC00, 0x089FFC00)
 __AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
 __AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
@@ -602,6 +606,10 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 				     int offset,
 				     enum aarch64_insn_variant variant,
 				     enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type);
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c
index b008a9b46a7f..9bef696e2230 100644
--- a/arch/arm64/lib/insn.c
+++ b/arch/arm64/lib/insn.c
@@ -540,6 +540,35 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 					     offset >> shift);
 }
 
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_ACQ:
+		insn = aarch64_insn_get_load_acq_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_REL:
+		insn = aarch64_insn_get_store_rel_value();
+		break;
+	default:
+		pr_err("%s: unknown load-acquire/store-release encoding %d\n",
+		       __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    reg);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+}
+
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
-- 
2.48.1.711.g2feabab25a-goog



From alexei.starovoitov at gmail.com  Mon Mar  3 16:24:12 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Mon, 3 Mar 2025 16:24:12 -0800
Subject: [PATCH bpf-next v5 1/6] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>
References: <cover.1741046028.git.yepeilin@google.com> <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>
Message-ID: <CAADnVQKX+PoSUqPBB2+eZrR7wdq-8EVaMxy_Wur7g8wyy3Dcmg@mail.gmail.com>

On Mon, Mar 3, 2025 at 4:13?PM Peilin Ye <yepeilin at google.com> wrote:
>
>         switch (insn->imm) {
> @@ -7780,6 +7813,24 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
>         case BPF_XCHG:
>         case BPF_CMPXCHG:
>                 return check_atomic_rmw(env, insn);
> +       case BPF_LOAD_ACQ:
> +#ifndef CONFIG_64BIT
> +               if (BPF_SIZE(insn->code) == BPF_DW) {
> +                       verbose(env,
> +                               "64-bit load-acquires are only supported on 64-bit arches\n");
> +                       return -EOPNOTSUPP;
> +               }
> +#endif

Your earlier proposal of:
if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {

was cleaner.
Why did you pick ifndef ?

> +               return check_atomic_load(env, insn);
> +       case BPF_STORE_REL:
> +#ifndef CONFIG_64BIT
> +               if (BPF_SIZE(insn->code) == BPF_DW) {
> +                       verbose(env,
> +                               "64-bit store-releases are only supported on 64-bit arches\n");
> +                       return -EOPNOTSUPP;
> +               }
> +#endif


From sebastianene at google.com  Mon Mar  3 16:38:15 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 4 Mar 2025 00:38:15 +0000
Subject: [PATCH v2 2/4] KVM: arm64: Move the ffa_to_linux definition to
 the ffa header
In-Reply-To: <20250303234426.GB30749@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-3-sebastianene@google.com>
 <20250227202557.d3fd6ylzbaho4pvx@bogus>
 <Z8DxZY-09R6lwEW3@google.com>
 <86wmdapei8.wl-maz@kernel.org>
 <20250303234426.GB30749@willie-the-truck>
Message-ID: <Z8ZLdwmFzS-lnssj@google.com>

On Mon, Mar 03, 2025 at 11:44:28PM +0000, Will Deacon wrote:
> On Fri, Feb 28, 2025 at 10:09:19AM +0000, Marc Zyngier wrote:
> > On Thu, 27 Feb 2025 23:12:37 +0000,
> > Sebastian Ene <sebastianene at google.com> wrote:
> > > 
> > > On Thu, Feb 27, 2025 at 08:25:57PM +0000, Sudeep Holla wrote:
> > > > On Thu, Feb 27, 2025 at 06:17:47PM +0000, Sebastian Ene wrote:
> > > > > Keep the ffa_to_linux error map in the header and move it away
> > > > > from the arm ffa driver to make it accessible for other components.
> > > > 
> > > > Do you plan to push/target these changes for v6.15 ? If not, I can take
> > > > this patch with other FF-A changes in my tree for v6.15. Otherwise, it
> > > > is must go along with other changes.
> > > > 
> > > 
> > > Yes, feel free to pick them with your changes and we can push them
> > > later.
> > 
> > So this series is not a 6.15 candidate?
> 
> I think this is 6.15 stuff once it's been reviewed. Sudeep's message is
> a little confusing as it refers to 6.15 twice (I guess he meant 6.14 the
> first time?).
> 

Right, I think it should be for 6.15 after it ticks the review boxes.

> Will

Thanks,
Seb


From yepeilin at google.com  Mon Mar  3 16:39:48 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue, 4 Mar 2025 00:39:48 +0000
Subject: [PATCH bpf-next v5 1/6] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <CAADnVQKX+PoSUqPBB2+eZrR7wdq-8EVaMxy_Wur7g8wyy3Dcmg@mail.gmail.com>
References: <cover.1741046028.git.yepeilin@google.com>
 <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>
 <CAADnVQKX+PoSUqPBB2+eZrR7wdq-8EVaMxy_Wur7g8wyy3Dcmg@mail.gmail.com>
Message-ID: <Z8ZL1L69z8XWm8vl@google.com>

Hi Alexei,

On Mon, Mar 03, 2025 at 04:24:12PM -0800, Alexei Starovoitov wrote:
> >         switch (insn->imm) {
> > @@ -7780,6 +7813,24 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
> >         case BPF_XCHG:
> >         case BPF_CMPXCHG:
> >                 return check_atomic_rmw(env, insn);
> > +       case BPF_LOAD_ACQ:
> > +#ifndef CONFIG_64BIT
> > +               if (BPF_SIZE(insn->code) == BPF_DW) {
> > +                       verbose(env,
> > +                               "64-bit load-acquires are only supported on 64-bit arches\n");
> > +                       return -EOPNOTSUPP;
> > +               }
> > +#endif
> 
> Your earlier proposal of:
> if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
> 
> was cleaner.
> Why did you pick ifndef ?

Likely overthinking, but I wanted to avoid this check at all for 64-bit
arches, so it's just a little bit faster.  Should I change it back to
checking BITS_PER_LONG ?

Thanks,
Peilin Ye



From gshan at redhat.com  Mon Mar  3 16:45:30 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 10:45:30 +1000
Subject: [PATCH v7 16/45] arm64: RME: Allow VMM to set RIPAS
In-Reply-To: <20250213161426.102987-17-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-17-steven.price@arm.com>
Message-ID: <329d28ce-3d12-47ed-9d88-fd779a65fe92@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> Each page within the protected region of the realm guest can be marked
> as either RAM or EMPTY. Allow the VMM to control this before the guest
> has started and provide the equivalent functions to change this (with
> the guest's approval) at runtime.
> 
> When transitioning from RIPAS RAM (1) to RIPAS EMPTY (0) the memory is
> unmapped from the guest and undelegated allowing the memory to be reused
> by the host. When transitioning to RIPAS RAM the actual population of
> the leaf RTTs is done later on stage 2 fault, however it may be
> necessary to allocate additional RTTs to allow the RMM track the RIPAS
> for the requested range.
> 
> When freeing a block mapping it is necessary to temporarily unfold the
> RTT which requires delegating an extra page to the RMM, this page can
> then be recovered once the contents of the block mapping have been
> freed.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes from v6:
>   * Split the code dealing with the guest triggering a RIPAS change into
>     a separate patch, so this patch is purely for the VMM setting up the
>     RIPAS before the guest first runs.
>   * Drop the useless flags argument from alloc_delegated_granule().
>   * Account RTTs allocated for a guest using kvm_account_pgtable_pages().
>   * Deal with the RMM granule size potentially being smaller than the
>     host's PAGE_SIZE. Although note alloc_delegated_granule() currently
>     still allocates an entire host page for every RMM granule (so wasting
>     memory when PAGE_SIZE>4k).
> Changes from v5:
>   * Adapt to rebasing.
>   * Introduce find_map_level()
>   * Rename some functions to be clearer.
>   * Drop the "spare page" functionality.
> Changes from v2:
>   * {alloc,free}_delegated_page() moved from previous patch to this one.
>   * alloc_delegated_page() now takes a gfp_t flags parameter.
>   * Fix the reference counting of guestmem pages to avoid leaking memory.
>   * Several misc code improvements and extra comments.
> ---
>   arch/arm64/include/asm/kvm_rme.h |   5 +
>   arch/arm64/kvm/mmu.c             |   8 +-
>   arch/arm64/kvm/rme.c             | 384 +++++++++++++++++++++++++++++++
>   3 files changed, 394 insertions(+), 3 deletions(-)
> 

It generally looks good to me, but there are some code level improvements
may be needed. Please only take those only sensible to you, Steven. With
those suggestions addressed (not all taken)

> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_rme.h
> index 2e319db9a05f..0bcde070b446 100644
> --- a/arch/arm64/include/asm/kvm_rme.h
> +++ b/arch/arm64/include/asm/kvm_rme.h
> @@ -92,6 +92,11 @@ void kvm_realm_destroy_rtts(struct kvm *kvm, u32 ia_bits);
>   int kvm_create_rec(struct kvm_vcpu *vcpu);
>   void kvm_destroy_rec(struct kvm_vcpu *vcpu);
>   
> +void kvm_realm_unmap_range(struct kvm *kvm,
> +			   unsigned long ipa,
> +			   u64 size,
> +			   bool unmap_private);
> +

The type of @ipa has been changed from phys_addr_t to unsigned long. It's
fine to have 'unsigned long size', to keep both of them consistent.

void kvm_realm_unmap_range(struct kvm *kvm, unsigned long ipa,
                            unsigned long size, bool unmap_private);

>   static inline bool kvm_realm_is_private_address(struct realm *realm,
>   						unsigned long addr)
>   {
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index b4506484913d..24eb60063573 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -323,6 +323,7 @@ static void invalidate_icache_guest_page(void *va, size_t size)
>    * @start: The intermediate physical base address of the range to unmap
>    * @size:  The size of the area to unmap
>    * @may_block: Whether or not we are permitted to block
> + * @only_shared: If true then protected mappings should not be unmapped
>    *
>    * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
>    * be called while holding mmu_lock (unless for freeing the stage2 pgd before
> @@ -330,7 +331,7 @@ static void invalidate_icache_guest_page(void *va, size_t size)
>    * with things behind our backs.
>    */
>   static void __unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size,
> -				 bool may_block)
> +				 bool may_block, bool only_shared)
>   {
>   	struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
>   	phys_addr_t end = start + size;
> @@ -344,7 +345,7 @@ static void __unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64
>   void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start,
>   			    u64 size, bool may_block)
>   {
> -	__unmap_stage2_range(mmu, start, size, may_block);
> +	__unmap_stage2_range(mmu, start, size, may_block, false);
>   }
>   
>   void kvm_stage2_flush_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end)
> @@ -1963,7 +1964,8 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
>   
>   	__unmap_stage2_range(&kvm->arch.mmu, range->start << PAGE_SHIFT,
>   			     (range->end - range->start) << PAGE_SHIFT,
> -			     range->may_block);
> +			     range->may_block,
> +			     range->only_shared);
>   
>   	kvm_nested_s2_unmap(kvm, range->may_block);
>   	return false;
> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> index 195390a66bc4..dc3fd66dd5bb 100644
> --- a/arch/arm64/kvm/rme.c
> +++ b/arch/arm64/kvm/rme.c
> @@ -87,6 +87,52 @@ static int get_start_level(struct realm *realm)
>   	return 4 - ((realm->ia_bits - 8) / (RMM_PAGE_SHIFT - 3));
>   }
>   
> +static int find_map_level(struct realm *realm,
> +			  unsigned long start,
> +			  unsigned long end)
> +{
> +	int level = RMM_RTT_MAX_LEVEL;
> +
> +	while (level > get_start_level(realm)) {
> +		unsigned long map_size = rme_rtt_level_mapsize(level - 1);
> +
> +		if (!IS_ALIGNED(start, map_size) ||
> +		    (start + map_size) > end)
> +			break;
> +
> +		level--;
> +	}
> +
> +	return level;
> +}
> +
> +static phys_addr_t alloc_delegated_granule(struct kvm_mmu_memory_cache *mc)
> +{
> +	phys_addr_t phys = PHYS_ADDR_MAX;
> +	void *virt;
> +
> +	if (mc)
> +		virt = kvm_mmu_memory_cache_alloc(mc);
> +	else
> +		virt = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
> +
> +	kvm_account_pgtable_pages(virt, 1);
> +
> +	if (!virt)
> +		goto out;
> +
> +	phys = virt_to_phys(virt);
> +
> +	if (rmi_granule_delegate(phys)) {
> +		free_page((unsigned long)virt);
> +
> +		phys = PHYS_ADDR_MAX;
> +	}
> +
> +out:
> +	return phys;
> +}
> +

The function name (alloc_delegated_rtt) since it's only to allocate page
and delegate it for RTT. Besides, kvm_account_pgtable_pages() needs to
executed after the check. Also, the 'out' tag is unnecessary.

static phys_addr_t alloc_delegated_rtt(struct kvm_mmu_memory_cache *mc)
{
	phys_addr_t phys;
	void *virt;

	if (mc)
		virt = kvm_mmu_memory_cache_alloc(mc);
	else
		virt = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);

	if (!virt)
		return PHYS_ADDR_MAX;

	phys = virt_to_phys(virt);
         if (rmi_granule_delegate(phys)) {
		free_page((unsigned long)virt);
		return PHYS_ADDR_MAX;
	}

	return phys;
}

>   static void free_delegated_granule(phys_addr_t phys)
>   {
>   	if (WARN_ON(rmi_granule_undelegate(phys))) {
> @@ -99,6 +145,154 @@ static void free_delegated_granule(phys_addr_t phys)
>   	free_page((unsigned long)phys_to_virt(phys));
>   }
>   
> +static int realm_rtt_create(struct realm *realm,
> +			    unsigned long addr,
> +			    int level,
> +			    phys_addr_t phys)
> +{
> +	addr = ALIGN_DOWN(addr, rme_rtt_level_mapsize(level - 1));
> +	return rmi_rtt_create(virt_to_phys(realm->rd), phys, addr, level);
> +}
> +
> +static int realm_rtt_fold(struct realm *realm,
> +			  unsigned long addr,
> +			  int level,
> +			  phys_addr_t *rtt_granule)
> +{
> +	unsigned long out_rtt;
> +	int ret;
> +
> +	ret = rmi_rtt_fold(virt_to_phys(realm->rd), addr, level, &out_rtt);
> +
> +	if (RMI_RETURN_STATUS(ret) == RMI_SUCCESS && rtt_granule)
> +		*rtt_granule = out_rtt;
> +
> +	return ret;
> +}
> +
> +static int realm_destroy_protected_granule(struct realm *realm,
> +					   unsigned long ipa,
> +					   unsigned long *next_addr,
> +					   phys_addr_t *out_addr)

It may be reasonable to rename it to realm_destroy_private_granule() to match with
its caller realm_unmap_private_page()

> +{
> +	unsigned long rd = virt_to_phys(realm->rd);
> +	unsigned long addr;
> +	phys_addr_t rtt;
> +	int ret;
> +

The variable name 'addr' confuses me a bit. Maybe we can rename it to 'rtt_addr'.
Similarly, 'out_addr' can be renamed to 'out_rtt'.

> +loop:

retry:

> +	ret = rmi_data_destroy(rd, ipa, &addr, next_addr);
> +	if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> +		if (*next_addr > ipa)
> +			return 0; /* UNASSIGNED */
> +		rtt = alloc_delegated_granule(NULL);
> +		if (WARN_ON(rtt == PHYS_ADDR_MAX))
> +			return -1;

			return -ENOMEM;

> +		/*
> +		 * ASSIGNED - ipa is mapped as a block, so split. The index
> +		 * from the return code should be 2 otherwise it appears
> +		 * there's a huge page bigger than KVM currently supports
> +		 */
> +		WARN_ON(RMI_RETURN_INDEX(ret) != 2);
> +		ret = realm_rtt_create(realm, ipa, 3, rtt);
> +		if (WARN_ON(ret)) {
> +			free_delegated_granule(rtt);
> +			return -1;

			return -ENXIO;		
> +		}
> +		/* retry */
> +		goto loop;

Drop '/* retry */'

		goto retry;

> +	} else if (WARN_ON(ret)) {
> +		return -1;

		return -ENXIO;
> +	}

A blank link is needed here.

> +	ret = rmi_granule_undelegate(addr);
> +	if (ret)
> +		return ret;
> +
> +	*out_addr = addr;
> +
> +	return 0;
> +}
> +
> +static int realm_unmap_private_page(struct realm *realm,
> +				    unsigned long ipa,
> +				    unsigned long *next_addr)
> +{
> +	unsigned long end = ALIGN(ipa + 1, PAGE_SIZE);
> +	unsigned long addr;
> +	phys_addr_t unmap_addr = PHYS_ADDR_MAX;
> +	int ret;
> +

s/unmap_addr/out_rtt

> +	for (addr = ipa; addr < end; addr = *next_addr) {
> +		ret = realm_destroy_protected_granule(realm, addr, next_addr,
> +						      &unmap_addr);
> +		if (WARN_ON(ret))
> +			return ret;

The WARN_ON() can be dropped since all errors has been guarded by WARN_ON()
in realm_destroy_protected_granule().

> +	}
> +
> +	if (unmap_addr != PHYS_ADDR_MAX)
> +		put_page(phys_to_page(unmap_addr));

s/put_page/free_page ?

> +
> +	return 0;
> +}
> +
> +static void realm_unmap_shared_range(struct kvm *kvm,
> +				     int level,
> +				     unsigned long start,
> +				     unsigned long end)
> +{
> +	struct realm *realm = &kvm->arch.realm;
> +	unsigned long rd = virt_to_phys(realm->rd);
> +	ssize_t map_size = rme_rtt_level_mapsize(level);
> +	unsigned long next_addr, addr;
> +	unsigned long shared_bit = BIT(realm->ia_bits - 1);
> +
> +	if (WARN_ON(level > RMM_RTT_MAX_LEVEL))
> +		return;
> +
> +	start |= shared_bit;
> +	end |= shared_bit;
> +
> +	for (addr = start; addr < end; addr = next_addr) {
> +		unsigned long align_addr = ALIGN(addr, map_size);
> +		int ret;
> +
> +		next_addr = ALIGN(addr + 1, map_size);
> +
> +		if (align_addr != addr || next_addr > end) {
> +			/* Need to recurse deeper */
> +			if (addr < align_addr)
> +				next_addr = align_addr;
> +			realm_unmap_shared_range(kvm, level + 1, addr,
> +						 min(next_addr, end));
> +			continue;
> +		}
> +
> +		ret = rmi_rtt_unmap_unprotected(rd, addr, level, &next_addr);
> +		switch (RMI_RETURN_STATUS(ret)) {
> +		case RMI_SUCCESS:
> +			break;
> +		case RMI_ERROR_RTT:
> +			if (next_addr == addr) {
> +				/*
> +				 * There's a mapping here, but it's not a block
> +				 * mapping, so reset next_addr to the next block
> +				 * boundary and recurse to clear out the pages
> +				 * one level deeper.
> +				 */
> +				next_addr = ALIGN(addr + 1, map_size);
> +				realm_unmap_shared_range(kvm, level + 1, addr,
> +							 next_addr);
> +			}
> +			break;
> +		default:
> +			WARN_ON(1);
> +			return;
> +		}
> +
> +		cond_resched_rwlock_write(&kvm->mmu_lock);
> +	}
> +}
> +
>   /* Calculate the number of s2 root rtts needed */
>   static int realm_num_root_rtts(struct realm *realm)
>   {
> @@ -209,6 +403,37 @@ static int realm_rtt_destroy(struct realm *realm, unsigned long addr,
>   	return ret;
>   }
>   
> +static int realm_create_rtt_levels(struct realm *realm,
> +				   unsigned long ipa,
> +				   int level,
> +				   int max_level,
> +				   struct kvm_mmu_memory_cache *mc)
> +{
> +	if (level == max_level)
> +		return 0;
> +
> +	while (level++ < max_level) {
> +		phys_addr_t rtt = alloc_delegated_granule(mc);
> +		int ret;
> +
> +		if (rtt == PHYS_ADDR_MAX)
> +			return -ENOMEM;
> +
> +		ret = realm_rtt_create(realm, ipa, level, rtt);
> +
> +		if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT &&
> +		    RMI_RETURN_INDEX(ret) == level) {
> +			/* The RTT already exists, continue */
> +			continue;
> +		} else if (ret) {
> +			free_delegated_granule(rtt);
> +			return -ENXIO;
> +		}

nit: the nested if statement is unnecessary.

		if (ret) {
			free_delegated_granule(rtt);
			return -ENXIO;
		}

> +	}
> +
> +	return 0;
> +}
> +
>   static int realm_tear_down_rtt_level(struct realm *realm, int level,
>   				     unsigned long start, unsigned long end)
>   {
> @@ -299,6 +524,61 @@ static int realm_tear_down_rtt_range(struct realm *realm,
>   					 start, end);
>   }
>   
> +/*
> + * Returns 0 on successful fold, a negative value on error, a positive value if
> + * we were not able to fold all tables at this level.
> + */
> +static int realm_fold_rtt_level(struct realm *realm, int level,
> +				unsigned long start, unsigned long end)
> +{
> +	int not_folded = 0;
> +	ssize_t map_size;
> +	unsigned long addr, next_addr;
> +
> +	if (WARN_ON(level > RMM_RTT_MAX_LEVEL))
> +		return -EINVAL;
> +
> +	map_size = rme_rtt_level_mapsize(level - 1);
> +
> +	for (addr = start; addr < end; addr = next_addr) {
> +		phys_addr_t rtt_granule;
> +		int ret;
> +		unsigned long align_addr = ALIGN(addr, map_size);
> +
> +		next_addr = ALIGN(addr + 1, map_size);
> +
> +		ret = realm_rtt_fold(realm, align_addr, level, &rtt_granule);
> +
> +		switch (RMI_RETURN_STATUS(ret)) {
> +		case RMI_SUCCESS:
> +			free_delegated_granule(rtt_granule);
> +			break;
> +		case RMI_ERROR_RTT:
> +			if (level == RMM_RTT_MAX_LEVEL ||
> +			    RMI_RETURN_INDEX(ret) < level) {
> +				not_folded++;
> +				break;
> +			}
> +			/* Recurse a level deeper */
> +			ret = realm_fold_rtt_level(realm,
> +						   level + 1,
> +						   addr,
> +						   next_addr);
> +			if (ret < 0)
> +				return ret;
> +			else if (ret == 0)
> +				/* Try again at this level */
> +				next_addr = addr;
> +			break;
> +		default:
> +			WARN_ON(1);
> +			return -ENXIO;
> +		}
> +	}
> +
> +	return not_folded;
> +}
> +
>   void kvm_realm_destroy_rtts(struct kvm *kvm, u32 ia_bits)
>   {
>   	struct realm *realm = &kvm->arch.realm;
> @@ -306,6 +586,98 @@ void kvm_realm_destroy_rtts(struct kvm *kvm, u32 ia_bits)
>   	WARN_ON(realm_tear_down_rtt_range(realm, 0, (1UL << ia_bits)));
>   }
>   
> +static void realm_unmap_private_range(struct kvm *kvm,
> +				      unsigned long start,
> +				      unsigned long end)
> +{
> +	struct realm *realm = &kvm->arch.realm;
> +	unsigned long next_addr, addr;
> +	int ret;
> +
> +	for (addr = start; addr < end; addr = next_addr) {
> +		ret = realm_unmap_private_page(realm, addr, &next_addr);
> +
> +		if (ret)
> +			break;
> +
> +		cond_resched_rwlock_write(&kvm->mmu_lock);
> +	}
> +
> +	realm_fold_rtt_level(realm, get_start_level(realm) + 1,
> +			     start, end);
> +}
> +
> +void kvm_realm_unmap_range(struct kvm *kvm, unsigned long start, u64 size,
> +			   bool unmap_private)
> +{
> +	unsigned long end = start + size;
> +	struct realm *realm = &kvm->arch.realm;
> +
> +	end = min(BIT(realm->ia_bits - 1), end);
> +
> +	if (realm->state == REALM_STATE_NONE)
> +		return;
> +
> +	realm_unmap_shared_range(kvm, find_map_level(realm, start, end),
> +				 start, end);
> +	if (unmap_private)
> +		realm_unmap_private_range(kvm, start, end);
> +}
> +
> +static int realm_init_ipa_state(struct realm *realm,
> +				unsigned long ipa,
> +				unsigned long end)
> +{
> +	phys_addr_t rd_phys = virt_to_phys(realm->rd);
> +	int ret;
> +
> +	while (ipa < end) {
> +		unsigned long next;
> +
> +		ret = rmi_rtt_init_ripas(rd_phys, ipa, end, &next);
> +
> +		if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> +			int err_level = RMI_RETURN_INDEX(ret);
> +			int level = find_map_level(realm, ipa, end);
> +
> +			if (WARN_ON(err_level >= level))
> +				return -ENXIO;
> +
> +			ret = realm_create_rtt_levels(realm, ipa,
> +						      err_level,
> +						      level, NULL);
> +			if (ret)
> +				return ret;
> +			/* Retry with the RTT levels in place */
> +			continue;
> +		} else if (WARN_ON(ret)) {
> +			return -ENXIO;
> +		}
> +
> +		ipa = next;
> +	}
> +
> +	return 0;
> +}
> +
> +static int kvm_init_ipa_range_realm(struct kvm *kvm,
> +				    struct arm_rme_init_ripas *args)
> +{
> +	gpa_t addr, end;
> +	struct realm *realm = &kvm->arch.realm;
> +
> +	addr = args->base;
> +	end = addr + args->size;
> +
> +	if (end < addr)
> +		return -EINVAL;
> +
> +	if (kvm_realm_state(kvm) != REALM_STATE_NEW)
> +		return -EINVAL;

		return -EPERM;
> +
> +	return realm_init_ipa_state(realm, addr, end);
> +}
> +
>   /* Protects access to rme_vmid_bitmap */
>   static DEFINE_SPINLOCK(rme_vmid_lock);
>   static unsigned long *rme_vmid_bitmap;
> @@ -431,6 +803,18 @@ int kvm_realm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
>   	case KVM_CAP_ARM_RME_CREATE_REALM:
>   		r = kvm_create_realm(kvm);
>   		break;
> +	case KVM_CAP_ARM_RME_INIT_RIPAS_REALM: {
> +		struct arm_rme_init_ripas args;
> +		void __user *argp = u64_to_user_ptr(cap->args[1]);
> +
> +		if (copy_from_user(&args, argp, sizeof(args))) {
> +			r = -EFAULT;
> +			break;
> +		}
> +
> +		r = kvm_init_ipa_range_realm(kvm, &args);
> +		break;
> +	}
>   	default:
>   		r = -EINVAL;
>   		break;

Thanks,
Gavin



From alexei.starovoitov at gmail.com  Mon Mar  3 16:45:45 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Mon, 3 Mar 2025 16:45:45 -0800
Subject: [PATCH bpf-next v5 1/6] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <Z8ZL1L69z8XWm8vl@google.com>
References: <cover.1741046028.git.yepeilin@google.com> <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>
 <CAADnVQKX+PoSUqPBB2+eZrR7wdq-8EVaMxy_Wur7g8wyy3Dcmg@mail.gmail.com> <Z8ZL1L69z8XWm8vl@google.com>
Message-ID: <CAADnVQKB-9q6fxcVPbd7Ee+QBH=_ySv2EyULkgFhv_n2i07L1A@mail.gmail.com>

On Mon, Mar 3, 2025 at 4:39?PM Peilin Ye <yepeilin at google.com> wrote:
>
> Hi Alexei,
>
> On Mon, Mar 03, 2025 at 04:24:12PM -0800, Alexei Starovoitov wrote:
> > >         switch (insn->imm) {
> > > @@ -7780,6 +7813,24 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
> > >         case BPF_XCHG:
> > >         case BPF_CMPXCHG:
> > >                 return check_atomic_rmw(env, insn);
> > > +       case BPF_LOAD_ACQ:
> > > +#ifndef CONFIG_64BIT
> > > +               if (BPF_SIZE(insn->code) == BPF_DW) {
> > > +                       verbose(env,
> > > +                               "64-bit load-acquires are only supported on 64-bit arches\n");
> > > +                       return -EOPNOTSUPP;
> > > +               }
> > > +#endif
> >
> > Your earlier proposal of:
> > if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
> >
> > was cleaner.
> > Why did you pick ifndef ?
>
> Likely overthinking, but I wanted to avoid this check at all for 64-bit
> arches, so it's just a little bit faster.  Should I change it back to
> checking BITS_PER_LONG ?

In general #ifdef in .c is the last resort.
We avoid it when possible.
In core.c we probably cannot, but here we can.
So yes. please respin.
I bet the compiler will produce the exact same code.


From yepeilin at google.com  Mon Mar  3 16:49:26 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue, 4 Mar 2025 00:49:26 +0000
Subject: [PATCH bpf-next v5 1/6] bpf: Introduce load-acquire and
 store-release instructions
In-Reply-To: <CAADnVQKB-9q6fxcVPbd7Ee+QBH=_ySv2EyULkgFhv_n2i07L1A@mail.gmail.com>
References: <cover.1741046028.git.yepeilin@google.com>
 <b0042990da762f5f6082cb6028c0af6b2b228c54.1741046028.git.yepeilin@google.com>
 <CAADnVQKX+PoSUqPBB2+eZrR7wdq-8EVaMxy_Wur7g8wyy3Dcmg@mail.gmail.com>
 <Z8ZL1L69z8XWm8vl@google.com>
 <CAADnVQKB-9q6fxcVPbd7Ee+QBH=_ySv2EyULkgFhv_n2i07L1A@mail.gmail.com>
Message-ID: <Z8ZOFuipuznnOD-7@google.com>

On Mon, Mar 03, 2025 at 04:45:45PM -0800, Alexei Starovoitov wrote:
> > > >         switch (insn->imm) {
> > > > @@ -7780,6 +7813,24 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
> > > >         case BPF_XCHG:
> > > >         case BPF_CMPXCHG:
> > > >                 return check_atomic_rmw(env, insn);
> > > > +       case BPF_LOAD_ACQ:
> > > > +#ifndef CONFIG_64BIT
> > > > +               if (BPF_SIZE(insn->code) == BPF_DW) {
> > > > +                       verbose(env,
> > > > +                               "64-bit load-acquires are only supported on 64-bit arches\n");
> > > > +                       return -EOPNOTSUPP;
> > > > +               }
> > > > +#endif
> > >
> > > Your earlier proposal of:
> > > if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
> > >
> > > was cleaner.
> > > Why did you pick ifndef ?
> >
> > Likely overthinking, but I wanted to avoid this check at all for 64-bit
> > arches, so it's just a little bit faster.  Should I change it back to
> > checking BITS_PER_LONG ?
> 
> In general #ifdef in .c is the last resort.
> We avoid it when possible.

Got it.

> In core.c we probably cannot, but here we can.
> So yes. please respin.

Sure!

> I bet the compiler will produce the exact same code.

Thanks,
Peilin Ye



From sebastianene at google.com  Mon Mar  3 16:53:25 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 4 Mar 2025 00:53:25 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <20250303234259.GA30749@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
Message-ID: <Z8ZPBZF7J-qKdb_i@google.com>

On Mon, Mar 03, 2025 at 11:43:03PM +0000, Will Deacon wrote:
> On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> > Map the hypervisor's buffers irrespective to the host and return
> > a linux error code from the FF-A error code on failure. Remove
> > the unmap ff-a buffers calls from the hypervisor as it will
> > never be called.
> > Prevent the host from using FF-A directly with Trustzone
> > if the hypervisor could not map its own buffers.
> > 
> > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > ---
> >  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
> >  1 file changed, 17 insertions(+), 29 deletions(-)
> 
> [...]
> 
> > @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
> >  {
> >  	struct arm_smccc_res res;
> >  	void *tx, *rx;
> > +	int ret;
> >  
> >  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
> >  		return 0;
> > @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
> >  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
> >  	};
> >  
> > +	/* Map our hypervisor buffers into the SPMD */
> > +	ret = ffa_map_hyp_buffers();
> > +	if (ret)
> > +		return ret;
> 
> Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
> arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
> the host to negotiate the version lazily?

We still have the same behaviour where we don't allow memory
sharing to happen until the version is negotiated but this
separates the hypervisor buffer mapping part from the host.

> 
> Will

Thanks,
Sebastian


From gshan at redhat.com  Mon Mar  3 17:03:21 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 11:03:21 +1000
Subject: [PATCH v7 17/45] arm64: RME: Handle realm enter/exit
In-Reply-To: <20250213161426.102987-18-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-18-steven.price@arm.com>
Message-ID: <80983793-5df7-4828-96e8-90540e7d9183@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> Entering a realm is done using a SMC call to the RMM. On exit the
> exit-codes need to be handled slightly differently to the normal KVM
> path so define our own functions for realm enter/exit and hook them
> in if the guest is a realm guest.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Use vcpu_err() rather than pr_err/kvm_err when there is an associated
>     vcpu to the error.
>   * Return -EFAULT for KVM_EXIT_MEMORY_FAULT as per the documentation for
>     this exit type.
>   * Split code handling a RIPAS change triggered by the guest to the
>     following patch.
> Changes since v5:
>   * For a RIPAS_CHANGE request from the guest perform the actual RIPAS
>     change on next entry rather than immediately on the exit. This allows
>     the VMM to 'reject' a RIPAS change by refusing to continue
>     scheduling.
> Changes since v4:
>   * Rename handle_rme_exit() to handle_rec_exit()
>   * Move the loop to copy registers into the REC enter structure from the
>     to rec_exit_handlers callbacks to kvm_rec_enter(). This fixes a bug
>     where the handler exits to user space and user space wants to modify
>     the GPRS.
>   * Some code rearrangement in rec_exit_ripas_change().
> Changes since v2:
>   * realm_set_ipa_state() now provides an output parameter for the
>     top_iap that was changed. Use this to signal the VMM with the correct
>     range that has been transitioned.
>   * Adapt to previous patch changes.
> ---
>   arch/arm64/include/asm/kvm_rme.h |   3 +
>   arch/arm64/kvm/Makefile          |   2 +-
>   arch/arm64/kvm/arm.c             |  19 +++-
>   arch/arm64/kvm/rme-exit.c        | 171 +++++++++++++++++++++++++++++++
>   arch/arm64/kvm/rme.c             |  19 ++++
>   5 files changed, 208 insertions(+), 6 deletions(-)
>   create mode 100644 arch/arm64/kvm/rme-exit.c
> 

With below nitpicks addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

[...]

> diff --git a/arch/arm64/kvm/rme-exit.c b/arch/arm64/kvm/rme-exit.c
> new file mode 100644
> index 000000000000..aae1adefe1a3
> --- /dev/null
> +++ b/arch/arm64/kvm/rme-exit.c
> @@ -0,0 +1,171 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#include <linux/kvm_host.h>
> +#include <kvm/arm_hypercalls.h>
> +#include <kvm/arm_psci.h>
> +
> +#include <asm/rmi_smc.h>
> +#include <asm/kvm_emulate.h>
> +#include <asm/kvm_rme.h>
> +#include <asm/kvm_mmu.h>
> +
> +typedef int (*exit_handler_fn)(struct kvm_vcpu *vcpu);
> +

Duplicated to exit_handler_fn, defined in handle_exit.c, need move the
definition to header file.

> +static int rec_exit_reason_notimpl(struct kvm_vcpu *vcpu)
> +{
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +
> +	vcpu_err(vcpu, "Unhandled exit reason from realm (ESR: %#llx)\n",
> +		 rec->run->exit.esr);
> +	return -ENXIO;
> +}
> +
> +static int rec_exit_sync_dabt(struct kvm_vcpu *vcpu)
> +{
> +	return kvm_handle_guest_abort(vcpu);
> +}
> +
> +static int rec_exit_sync_iabt(struct kvm_vcpu *vcpu)
> +{
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +
> +	vcpu_err(vcpu, "Unhandled instruction abort (ESR: %#llx).\n",
> +		 rec->run->exit.esr);
> +	return -ENXIO;
> +}
> +
> +static int rec_exit_sys_reg(struct kvm_vcpu *vcpu)
> +{
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +	unsigned long esr = kvm_vcpu_get_esr(vcpu);
> +	int rt = kvm_vcpu_sys_get_rt(vcpu);
> +	bool is_write = !(esr & 1);
> +	int ret;
> +
> +	if (is_write)
> +		vcpu_set_reg(vcpu, rt, rec->run->exit.gprs[0]);
> +
> +	ret = kvm_handle_sys_reg(vcpu);
> +
> +	if (ret >= 0 && !is_write)
> +		rec->run->enter.gprs[0] = vcpu_get_reg(vcpu, rt);
> +

Unncessary blank line and the conditon isn't completely correct: kvm_handle_sys_reg()
should return 0 if the requested emulation fails, even it always returns 1 for now.

	ret = kvm_handle_sys_reg(vcpu);
	if (ret > 0 && !is_write)
		rec->run->enter.gprs[0] = vcpu_get_reg(vcpu, rt);

> +	return ret;
> +}
> +

[...]

Thanks,
Gavin



From yepeilin at google.com  Mon Mar  3 17:06:33 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:33 +0000
Subject: [PATCH bpf-next v6 4/6] bpf, arm64: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <51664a1300710238ba2d4d95142b57a52c4f0cae.1741049567.git.yepeilin@google.com>

Support BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions in the arm64 JIT compiler.  For example
(assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))
  95 00 00 00 00 00 00 00  exit

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

The JIT compiler would emit an LDAR instruction for the above, e.g.:

  ldar  x7, [x0]

Similarly, consider the following 16-bit store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)
  95 00 00 00 00 00 00 00  exit

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

An STLRH instruction would be emitted, e.g.:

  stlrh  w1, [x0]

For a complete mapping:

  load-acquire     8-bit  LDARB
 (BPF_LOAD_ACQ)   16-bit  LDARH
                  32-bit  LDAR (32-bit)
                  64-bit  LDAR (64-bit)
  store-release    8-bit  STLRB
 (BPF_STORE_REL)  16-bit  STLRH
                  32-bit  STLR (32-bit)
                  64-bit  STLR (64-bit)

Arena accesses are supported.
bpf_jit_supports_insn(..., /*in_arena=*/true) always returns true for
BPF_LOAD_ACQ and BPF_STORE_REL instructions, as they don't depend on
ARM64_HAS_LSE_ATOMICS.

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit.h      | 20 ++++++++
 arch/arm64/net/bpf_jit_comp.c | 90 ++++++++++++++++++++++++++++++++---
 2 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index b22ab2f97a30..a3b0e693a125 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -119,6 +119,26 @@
 	aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \
 				       AARCH64_INSN_LDST_STORE_REL_EX)
 
+/* Load-acquire & store-release */
+#define A64_LDAR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_LOAD_ACQ)
+#define A64_STLR(Rt, Rn, size)  \
+	aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \
+					    AARCH64_INSN_LDST_STORE_REL)
+
+/* Rt = [Rn] (load acquire) */
+#define A64_LDARB(Wt, Xn)	A64_LDAR(Wt, Xn, 8)
+#define A64_LDARH(Wt, Xn)	A64_LDAR(Wt, Xn, 16)
+#define A64_LDAR32(Wt, Xn)	A64_LDAR(Wt, Xn, 32)
+#define A64_LDAR64(Xt, Xn)	A64_LDAR(Xt, Xn, 64)
+
+/* [Rn] = Rt (store release) */
+#define A64_STLRB(Wt, Xn)	A64_STLR(Wt, Xn, 8)
+#define A64_STLRH(Wt, Xn)	A64_STLR(Wt, Xn, 16)
+#define A64_STLR32(Wt, Xn)	A64_STLR(Wt, Xn, 32)
+#define A64_STLR64(Xt, Xn)	A64_STLR(Xt, Xn, 64)
+
 /*
  * LSE atomics
  *
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index bdda5a77bb16..70d7c89d3ac9 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -647,6 +647,81 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
 	return 0;
 }
 
+static int emit_atomic_ld_st(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s32 imm = insn->imm;
+	const s16 off = insn->off;
+	const u8 code = insn->code;
+	const bool arena = BPF_MODE(code) == BPF_PROBE_ATOMIC;
+	const u8 arena_vm_base = bpf2a64[ARENA_VM_START];
+	const u8 dst = bpf2a64[insn->dst_reg];
+	const u8 src = bpf2a64[insn->src_reg];
+	const u8 tmp = bpf2a64[TMP_REG_1];
+	u8 reg;
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		reg = src;
+		break;
+	case BPF_STORE_REL:
+		reg = dst;
+		break;
+	default:
+		pr_err_once("unknown atomic load/store op code %02x\n", imm);
+		return -EINVAL;
+	}
+
+	if (off) {
+		emit_a64_add_i(1, tmp, reg, tmp, off, ctx);
+		reg = tmp;
+	}
+	if (arena) {
+		emit(A64_ADD(1, tmp, reg, arena_vm_base), ctx);
+		reg = tmp;
+	}
+
+	switch (imm) {
+	case BPF_LOAD_ACQ:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_LDARB(dst, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_LDARH(dst, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_LDAR32(dst, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_LDAR64(dst, reg), ctx);
+			break;
+		}
+		break;
+	case BPF_STORE_REL:
+		switch (BPF_SIZE(code)) {
+		case BPF_B:
+			emit(A64_STLRB(src, reg), ctx);
+			break;
+		case BPF_H:
+			emit(A64_STLRH(src, reg), ctx);
+			break;
+		case BPF_W:
+			emit(A64_STLR32(src, reg), ctx);
+			break;
+		case BPF_DW:
+			emit(A64_STLR64(src, reg), ctx);
+			break;
+		}
+		break;
+	default:
+		pr_err_once("unexpected atomic load/store op code %02x\n",
+			    imm);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
 {
@@ -1641,11 +1716,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
 			return ret;
 		break;
 
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+	case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 	case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
-		if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (bpf_atomic_is_load_store(insn))
+			ret = emit_atomic_ld_st(insn, ctx);
+		else if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			ret = emit_lse_atomic(insn, ctx);
 		else
 			ret = emit_ll_sc_atomic(insn, ctx);
@@ -2667,13 +2748,10 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
-		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
+		if (!bpf_atomic_is_load_store(insn) &&
+		    !cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
 	return true;
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:06:40 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:40 +0000
Subject: [PATCH bpf-next v6 5/6] bpf, x86: Support load-acquire and
 store-release instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <d22bb3c69f126af1d962b7314f3489eff606a3b7.1741049567.git.yepeilin@google.com>

Recently we introduced BPF load-acquire (BPF_LOAD_ACQ) and store-release
(BPF_STORE_REL) instructions.  For x86-64, simply implement them as
regular BPF_LDX/BPF_STX loads and stores.  The verifier always rejects
misaligned load-acquires/store-releases (even if BPF_F_ANY_ALIGNMENT is
set), so emitted MOV* instructions are guaranteed to be atomic.

Arena accesses are supported.  8- and 16-bit load-acquires are
zero-extending (i.e., MOVZBQ, MOVZWQ).

Rename emit_atomic{,_index}() to emit_atomic_rmw{,_index}() to make it
clear that they only handle read-modify-write atomics, and extend their
@atomic_op parameter from u8 to u32, since we are starting to use more
than the lowest 8 bits of the 'imm' field.

Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/x86/net/bpf_jit_comp.c | 99 ++++++++++++++++++++++++++++++-------
 1 file changed, 82 insertions(+), 17 deletions(-)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index f0c31c940fb8..0263d98d92b0 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1242,8 +1242,8 @@ static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
 	emit_st_index(pprog, size, dst_reg, X86_REG_R12, off, imm);
 }
 
-static int emit_atomic(u8 **pprog, u8 atomic_op,
-		       u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
+static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
+			   u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
 {
 	u8 *prog = *pprog;
 
@@ -1283,8 +1283,9 @@ static int emit_atomic(u8 **pprog, u8 atomic_op,
 	return 0;
 }
 
-static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
-			     u32 dst_reg, u32 src_reg, u32 index_reg, int off)
+static int emit_atomic_rmw_index(u8 **pprog, u32 atomic_op, u32 size,
+				 u32 dst_reg, u32 src_reg, u32 index_reg,
+				 int off)
 {
 	u8 *prog = *pprog;
 
@@ -1297,7 +1298,7 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 		EMIT1(add_3mod(0x48, dst_reg, src_reg, index_reg));
 		break;
 	default:
-		pr_err("bpf_jit: 1 and 2 byte atomics are not supported\n");
+		pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
 		return -EFAULT;
 	}
 
@@ -1331,6 +1332,49 @@ static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
 	return 0;
 }
 
+static int emit_atomic_ld_st(u8 **pprog, u32 atomic_op, u32 dst_reg,
+			     u32 src_reg, s16 off, u8 bpf_size)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + off16) */
+		emit_ldx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + off16, src_reg) */
+		emit_stx(pprog, bpf_size, dst_reg, src_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int emit_atomic_ld_st_index(u8 **pprog, u32 atomic_op, u32 size,
+				   u32 dst_reg, u32 src_reg, u32 index_reg,
+				   int off)
+{
+	switch (atomic_op) {
+	case BPF_LOAD_ACQ:
+		/* dst_reg = smp_load_acquire(src_reg + idx_reg + off16) */
+		emit_ldx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	case BPF_STORE_REL:
+		/* smp_store_release(dst_reg + idx_reg + off16, src_reg) */
+		emit_stx_index(pprog, size, dst_reg, src_reg, index_reg, off);
+		break;
+	default:
+		pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
+		       atomic_op);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
 #define DONT_CLEAR 1
 
 bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
@@ -2113,6 +2157,13 @@ st:			if (is_imm8(insn->off))
 			}
 			break;
 
+		case BPF_STX | BPF_ATOMIC | BPF_B:
+		case BPF_STX | BPF_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_ATOMIC | BPF_W:
 		case BPF_STX | BPF_ATOMIC | BPF_DW:
 			if (insn->imm == (BPF_AND | BPF_FETCH) ||
@@ -2148,10 +2199,10 @@ st:			if (is_imm8(insn->off))
 				EMIT2(simple_alu_opcodes[BPF_OP(insn->imm)],
 				      add_2reg(0xC0, AUX_REG, real_src_reg));
 				/* Attempt to swap in new value */
-				err = emit_atomic(&prog, BPF_CMPXCHG,
-						  real_dst_reg, AUX_REG,
-						  insn->off,
-						  BPF_SIZE(insn->code));
+				err = emit_atomic_rmw(&prog, BPF_CMPXCHG,
+						      real_dst_reg, AUX_REG,
+						      insn->off,
+						      BPF_SIZE(insn->code));
 				if (WARN_ON(err))
 					return err;
 				/*
@@ -2166,17 +2217,35 @@ st:			if (is_imm8(insn->off))
 				break;
 			}
 
-			err = emit_atomic(&prog, insn->imm, dst_reg, src_reg,
-					  insn->off, BPF_SIZE(insn->code));
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st(&prog, insn->imm, dst_reg, src_reg,
+							insn->off, BPF_SIZE(insn->code));
+			else
+				err = emit_atomic_rmw(&prog, insn->imm, dst_reg, src_reg,
+						      insn->off, BPF_SIZE(insn->code));
 			if (err)
 				return err;
 			break;
 
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
+		case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
+			if (!bpf_atomic_is_load_store(insn)) {
+				pr_err("bpf_jit: 1- and 2-byte RMW atomics are not supported\n");
+				return -EFAULT;
+			}
+			fallthrough;
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
 		case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
 			start_of_ldx = prog;
-			err = emit_atomic_index(&prog, insn->imm, BPF_SIZE(insn->code),
-						dst_reg, src_reg, X86_REG_R12, insn->off);
+
+			if (bpf_atomic_is_load_store(insn))
+				err = emit_atomic_ld_st_index(&prog, insn->imm,
+							      BPF_SIZE(insn->code), dst_reg,
+							      src_reg, X86_REG_R12, insn->off);
+			else
+				err = emit_atomic_rmw_index(&prog, insn->imm, BPF_SIZE(insn->code),
+							    dst_reg, src_reg, X86_REG_R12,
+							    insn->off);
 			if (err)
 				return err;
 			goto populate_extable;
@@ -3771,12 +3840,8 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
-	case BPF_STX | BPF_ATOMIC | BPF_B:
-	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
-		if (bpf_atomic_is_load_store(insn))
-			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:06:46 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:46 +0000
Subject: [PATCH bpf-next v6 6/6] selftests/bpf: Add selftests for load-acquire
 and store-release instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <1b46c6feaf0f1b6984d9ec80e500cc7383e9da1a.1741049567.git.yepeilin@google.com>

Add several ./test_progs tests:

  - arena_atomics/load_acquire
  - arena_atomics/store_release
  - verifier_load_acquire/*
  - verifier_store_release/*
  - verifier_precision/bpf_load_acquire
  - verifier_precision/bpf_store_release

The last two tests are added to check if backtrack_insn() handles the
new instructions correctly.

Additionally, the last test also makes sure that the verifier
"remembers" the value (in src_reg) we store-release into e.g. a stack
slot.  For example, if we take a look at the test program:

    #0:  r1 = 8;
      /* store_release((u64 *)(r10 - 8), r1); */
    #1:  .8byte %[store_release];
    #2:  r1 = *(u64 *)(r10 - 8);
    #3:  r2 = r10;
    #4:  r2 += r1;
    #5:  r0 = 0;
    #6:  exit;

At #1, if the verifier doesn't remember that we wrote 8 to the stack,
then later at #4 we would be adding an unbounded scalar value to the
stack pointer, which would cause the program to be rejected:

  VERIFIER LOG:
  =============
...
  math between fp pointer and register with unbounded min value is not allowed

For easier CI integration, instead of using built-ins like
__atomic_{load,store}_n() which depend on the new
__BPF_FEATURE_LOAD_ACQ_STORE_REL pre-defined macro, manually craft
load-acquire/store-release instructions using __imm_insn(), as suggested
by Eduard.

All new tests depend on:

  (1) Clang major version >= 18, and
  (2) ENABLE_ATOMICS_TESTS is defined (currently implies -mcpu=v3 or
      v4), and
  (3) JIT supports load-acquire/store-release (currently arm64 and
      x86-64)

In .../progs/arena_atomics.c:

  /* 8-byte-aligned */
  __u8 __arena_global load_acquire8_value = 0x12;
  /* 1-byte hole */
  __u16 __arena_global load_acquire16_value = 0x1234;

That 1-byte hole in the .addr_space.1 ELF section caused clang-17 to
crash:

  fatal error: error in backend: unable to write nop sequence of 1 bytes

To work around such llvm-17 CI job failures, conditionally define
__arena_global variables as 64-bit if __clang_major__ < 18, to make sure
.addr_space.1 has no holes.  Ideally we should avoid compiling this file
using clang-17 at all (arena tests depend on
__BPF_FEATURE_ADDR_SPACE_CAST, and are skipped for llvm-17 anyway), but
that is a separate topic.

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 6 files changed, 698 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
index 26e7c06c6cb4..d98577a6babc 100644
--- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
+++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
@@ -162,6 +162,66 @@ static void test_uaf(struct arena_atomics *skel)
 	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
 }
 
+static void test_load_acquire(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support load-acquire\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.load_acquire);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->load_acquire8_result, 0x12,
+		  "load_acquire8_result");
+	ASSERT_EQ(skel->arena->load_acquire16_result, 0x1234,
+		  "load_acquire16_result");
+	ASSERT_EQ(skel->arena->load_acquire32_result, 0x12345678,
+		  "load_acquire32_result");
+	ASSERT_EQ(skel->arena->load_acquire64_result, 0x1234567890abcdef,
+		  "load_acquire64_result");
+}
+
+static void test_store_release(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	if (skel->data->skip_lacq_srel_tests) {
+		printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support addr_space_cast, and/or JIT doesn't support store-release\n",
+		       __func__);
+		test__skip();
+		return;
+	}
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.store_release);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->store_release8_result, 0x12,
+		  "store_release8_result");
+	ASSERT_EQ(skel->arena->store_release16_result, 0x1234,
+		  "store_release16_result");
+	ASSERT_EQ(skel->arena->store_release32_result, 0x12345678,
+		  "store_release32_result");
+	ASSERT_EQ(skel->arena->store_release64_result, 0x1234567890abcdef,
+		  "store_release64_result");
+}
+
 void test_arena_atomics(void)
 {
 	struct arena_atomics *skel;
@@ -171,7 +231,7 @@ void test_arena_atomics(void)
 	if (!ASSERT_OK_PTR(skel, "arena atomics skeleton open"))
 		return;
 
-	if (skel->data->skip_tests) {
+	if (skel->data->skip_all_tests) {
 		printf("%s:SKIP:no ENABLE_ATOMICS_TESTS or no addr_space_cast support in clang",
 		       __func__);
 		test__skip();
@@ -198,6 +258,10 @@ void test_arena_atomics(void)
 		test_xchg(skel);
 	if (test__start_subtest("uaf"))
 		test_uaf(skel);
+	if (test__start_subtest("load_acquire"))
+		test_load_acquire(skel);
+	if (test__start_subtest("store_release"))
+		test_store_release(skel);
 
 cleanup:
 	arena_atomics__destroy(skel);
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index 8a0e1ff8a2dc..cfe47b529e01 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -45,6 +45,7 @@
 #include "verifier_ldsx.skel.h"
 #include "verifier_leak_ptr.skel.h"
 #include "verifier_linked_scalars.skel.h"
+#include "verifier_load_acquire.skel.h"
 #include "verifier_loops1.skel.h"
 #include "verifier_lwt.skel.h"
 #include "verifier_map_in_map.skel.h"
@@ -80,6 +81,7 @@
 #include "verifier_spill_fill.skel.h"
 #include "verifier_spin_lock.skel.h"
 #include "verifier_stack_ptr.skel.h"
+#include "verifier_store_release.skel.h"
 #include "verifier_subprog_precision.skel.h"
 #include "verifier_subreg.skel.h"
 #include "verifier_tailcall_jit.skel.h"
@@ -173,6 +175,7 @@ void test_verifier_int_ptr(void)              { RUN(verifier_int_ptr); }
 void test_verifier_iterating_callbacks(void)  { RUN(verifier_iterating_callbacks); }
 void test_verifier_jeq_infer_not_null(void)   { RUN(verifier_jeq_infer_not_null); }
 void test_verifier_jit_convergence(void)      { RUN(verifier_jit_convergence); }
+void test_verifier_load_acquire(void)         { RUN(verifier_load_acquire); }
 void test_verifier_ld_ind(void)               { RUN(verifier_ld_ind); }
 void test_verifier_ldsx(void)                  { RUN(verifier_ldsx); }
 void test_verifier_leak_ptr(void)             { RUN(verifier_leak_ptr); }
@@ -211,6 +214,7 @@ void test_verifier_sockmap_mutate(void)       { RUN(verifier_sockmap_mutate); }
 void test_verifier_spill_fill(void)           { RUN(verifier_spill_fill); }
 void test_verifier_spin_lock(void)            { RUN(verifier_spin_lock); }
 void test_verifier_stack_ptr(void)            { RUN(verifier_stack_ptr); }
+void test_verifier_store_release(void)        { RUN(verifier_store_release); }
 void test_verifier_subprog_precision(void)    { RUN(verifier_subprog_precision); }
 void test_verifier_subreg(void)               { RUN(verifier_subreg); }
 void test_verifier_tailcall_jit(void)         { RUN(verifier_tailcall_jit); }
diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/testing/selftests/bpf/progs/arena_atomics.c
index 40dd57fca5cc..a52feff98112 100644
--- a/tools/testing/selftests/bpf/progs/arena_atomics.c
+++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
@@ -6,6 +6,8 @@
 #include <stdbool.h>
 #include <stdatomic.h>
 #include "bpf_arena_common.h"
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
 
 struct {
 	__uint(type, BPF_MAP_TYPE_ARENA);
@@ -19,9 +21,17 @@ struct {
 } arena SEC(".maps");
 
 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST)
-bool skip_tests __attribute((__section__(".data"))) = false;
+bool skip_all_tests __attribute((__section__(".data"))) = false;
 #else
-bool skip_tests = true;
+bool skip_all_tests = true;
+#endif
+
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+bool skip_lacq_srel_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_lacq_srel_tests = true;
 #endif
 
 __u32 pid = 0;
@@ -274,4 +284,111 @@ int uaf(const void *ctx)
 	return 0;
 }
 
+#if __clang_major__ >= 18
+__u8 __arena_global load_acquire8_value = 0x12;
+__u16 __arena_global load_acquire16_value = 0x1234;
+__u32 __arena_global load_acquire32_value = 0x12345678;
+__u64 __arena_global load_acquire64_value = 0x1234567890abcdef;
+
+__u8 __arena_global load_acquire8_result = 0;
+__u16 __arena_global load_acquire16_result = 0;
+__u32 __arena_global load_acquire32_result = 0;
+__u64 __arena_global load_acquire64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global load_acquire8_value;
+__u64 __arena_global load_acquire16_value;
+__u64 __arena_global load_acquire32_value;
+__u64 __arena_global load_acquire64_value;
+
+__u64 __arena_global load_acquire8_result;
+__u64 __arena_global load_acquire16_result;
+__u64 __arena_global load_acquire32_result;
+__u64 __arena_global load_acquire64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int load_acquire(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define LOAD_ACQUIRE_ARENA(SIZEOP, SIZE, SRC, DST)	\
+	{ asm volatile (				\
+	"r1 = %[" #SRC "] ll;"				\
+	"r1 = addr_space_cast(r1, 0x0, 0x1);"		\
+	".8byte %[load_acquire_insn];"			\
+	"r3 = %[" #DST "] ll;"				\
+	"r3 = addr_space_cast(r3, 0x0, 0x1);"		\
+	"*(" #SIZE " *)(r3 + 0) = r2;"			\
+	:						\
+	: __imm_addr(SRC),				\
+	  __imm_insn(load_acquire_insn,			\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_LOAD_ACQ,	\
+				   BPF_REG_2, BPF_REG_1, 0)),	\
+	  __imm_addr(DST)				\
+	: __clobber_all); }				\
+
+	LOAD_ACQUIRE_ARENA(B, u8, load_acquire8_value, load_acquire8_result)
+	LOAD_ACQUIRE_ARENA(H, u16, load_acquire16_value,
+			   load_acquire16_result)
+	LOAD_ACQUIRE_ARENA(W, u32, load_acquire32_value,
+			   load_acquire32_result)
+	LOAD_ACQUIRE_ARENA(DW, u64, load_acquire64_value,
+			   load_acquire64_result)
+#undef LOAD_ACQUIRE_ARENA
+
+#endif
+	return 0;
+}
+
+#if __clang_major__ >= 18
+__u8 __arena_global store_release8_result = 0;
+__u16 __arena_global store_release16_result = 0;
+__u32 __arena_global store_release32_result = 0;
+__u64 __arena_global store_release64_result = 0;
+#else
+/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around
+ * this issue by defining the below variables as 64-bit.
+ */
+__u64 __arena_global store_release8_result;
+__u64 __arena_global store_release16_result;
+__u64 __arena_global store_release32_result;
+__u64 __arena_global store_release64_result;
+#endif
+
+SEC("raw_tp/sys_enter")
+int store_release(const void *ctx)
+{
+#if defined(ENABLE_ATOMICS_TESTS) &&		  \
+	defined(__BPF_FEATURE_ADDR_SPACE_CAST) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+#define STORE_RELEASE_ARENA(SIZEOP, DST, VAL)	\
+	{ asm volatile (			\
+	"r1 = " VAL ";"				\
+	"r2 = %[" #DST "] ll;"			\
+	"r2 = addr_space_cast(r2, 0x0, 0x1);"	\
+	".8byte %[store_release_insn];"		\
+	:					\
+	: __imm_addr(DST),			\
+	  __imm_insn(store_release_insn,	\
+		     BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_STORE_REL,	\
+				   BPF_REG_2, BPF_REG_1, 0))	\
+	: __clobber_all); }			\
+
+	STORE_RELEASE_ARENA(B, store_release8_result, "0x12")
+	STORE_RELEASE_ARENA(H, store_release16_result, "0x1234")
+	STORE_RELEASE_ARENA(W, store_release32_result, "0x12345678")
+	STORE_RELEASE_ARENA(DW, store_release64_result,
+			    "0x1234567890abcdef ll")
+#undef STORE_RELEASE_ARENA
+
+#endif
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
new file mode 100644
index 000000000000..ff308f24d745
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("load-acquire, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void load_acquire_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	"*(u8 *)(r10 - 1) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r10 - 1));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void load_acquire_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	"*(u16 *)(r10 - 2) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u16 *)(r10 - 2));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void load_acquire_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	"*(u32 *)(r10 - 4) = w1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 4));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void load_acquire_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r10 - 8));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void load_acquire_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire with non-pointer src_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void load_acquire_with_non_pointer_src_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[load_acquire_insn];" // r0 = load_acquire((u64 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned load-acquire")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void load_acquire_misaligned(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u32 *)(r10 - 5));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("load-acquire from ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC loads from R1 ctx is not allowed")
+__naked void load_acquire_from_ctx_pointer(void)
+{
+	asm volatile (
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r1 + 0));
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("load-acquire from pkt pointer")
+__failure __msg("BPF_ATOMIC loads from R2 pkt is not allowed")
+__naked void load_acquire_from_pkt_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("load-acquire from flow_keys pointer")
+__failure __msg("BPF_ATOMIC loads from R2 flow_keys is not allowed")
+__naked void load_acquire_from_flow_keys_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("load-acquire from sock pointer")
+__failure __msg("BPF_ATOMIC loads from R2 sock is not allowed")
+__naked void load_acquire_from_sock_pointer(void)
+{
+	asm volatile (
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[load_acquire_insn];" // w0 = load_acquire((u8 *)(r2 + 0));
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support load-acquire, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 6b564d4c0986..6662d4b39969 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -2,6 +2,7 @@
 /* Copyright (C) 2023 SUSE LLC */
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
 #include "bpf_misc.h"
 
 SEC("?raw_tp")
@@ -90,6 +91,54 @@ __naked int bpf_end_bswap(void)
 		::: __clobber_all);
 }
 
+#if defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r3 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (db) r2 = load_acquire((u64 *)(r10 -8))")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (7b) *(u64 *)(r10 -8) = r1")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_load_acquire(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	"*(u64 *)(r10 - 8) = r1;"
+	".8byte %[load_acquire_insn];" /* r2 = load_acquire((u64 *)(r10 - 8)); */
+	"r3 = r10;"
+	"r3 += r2;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(load_acquire_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -8))
+	: __clobber_all);
+}
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r1 stack= before 3: (bf) r2 = r10")
+__msg("mark_precise: frame0: regs=r1 stack= before 2: (79) r1 = *(u64 *)(r10 -8)")
+__msg("mark_precise: frame0: regs= stack=-8 before 1: (db) store_release((u64 *)(r10 -8), r1)")
+__msg("mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8")
+__naked int bpf_store_release(void)
+{
+	asm volatile (
+	"r1 = 8;"
+	".8byte %[store_release_insn];" /* store_release((u64 *)(r10 - 8), r1); */
+	"r1 = *(u64 *)(r10 - 8);"
+	"r2 = r10;"
+	"r2 += r1;" /* mark_precise */
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+#endif /* load-acquire, store-release */
 #endif /* v4 instruction */
 
 SEC("?raw_tp")
diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/tools/testing/selftests/bpf/progs/verifier_store_release.c
new file mode 100644
index 000000000000..f1c64c08f25f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Google LLC. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "../../../include/linux/filter.h"
+#include "bpf_misc.h"
+
+#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
+	(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86))
+
+SEC("socket")
+__description("store-release, 8-bit")
+__success __success_unpriv __retval(0x12)
+__naked void store_release_8(void)
+{
+	asm volatile (
+	"w1 = 0x12;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1);
+	"w0 = *(u8 *)(r10 - 1);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -1))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 16-bit")
+__success __success_unpriv __retval(0x1234)
+__naked void store_release_16(void)
+{
+	asm volatile (
+	"w1 = 0x1234;"
+	".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1);
+	"w0 = *(u16 *)(r10 - 2);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_H, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -2))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 32-bit")
+__success __success_unpriv __retval(0x12345678)
+__naked void store_release_32(void)
+{
+	asm volatile (
+	"w1 = 0x12345678;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1);
+	"w0 = *(u32 *)(r10 - 4);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -4))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, 64-bit")
+__success __success_unpriv __retval(0x1234567890abcdef)
+__naked void store_release_64(void)
+{
+	asm volatile (
+	"r1 = 0x1234567890abcdef ll;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = *(u64 *)(r10 - 8);"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized src_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_src_reg(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r2);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_2, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with uninitialized dst_reg")
+__failure __failure_unpriv __msg("R2 !read_ok")
+__naked void store_release_with_uninitialized_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r2 - 8), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release with non-pointer dst_reg")
+__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'")
+__naked void store_release_with_non_pointer_dst_reg(void)
+{
+	asm volatile (
+	"r1 = 0;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r1 + 0), r1);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_1, BPF_REG_1, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("misaligned store-release")
+__failure __failure_unpriv __msg("misaligned stack access off")
+__flag(BPF_F_ANY_ALIGNMENT)
+__naked void store_release_misaligned(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 5), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_0, -5))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release to ctx pointer")
+__failure __failure_unpriv __msg("BPF_ATOMIC stores into R1 ctx is not allowed")
+__naked void store_release_to_ctx_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r1 + 0), w0);
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_1, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("xdp")
+__description("store-release to pkt pointer")
+__failure __msg("BPF_ATOMIC stores into R2 pkt is not allowed")
+__naked void store_release_to_pkt_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u32 *)(r1 + %[xdp_md_data]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("flow_dissector")
+__description("store-release to flow_keys pointer")
+__failure __msg("BPF_ATOMIC stores into R2 flow_keys is not allowed")
+__naked void store_release_to_flow_keys_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(__sk_buff_flow_keys,
+		      offsetof(struct __sk_buff, flow_keys)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("sk_reuseport")
+__description("store-release to sock pointer")
+__failure __msg("BPF_ATOMIC stores into R2 sock is not allowed")
+__naked void store_release_to_sock_pointer(void)
+{
+	asm volatile (
+	"w0 = 0;"
+	"r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);"
+	".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0);
+	"exit;"
+	:
+	: __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0))
+	: __clobber_all);
+}
+
+SEC("socket")
+__description("store-release, leak pointer to stack")
+__success __success_unpriv __retval(0)
+__naked void store_release_leak_pointer_to_stack(void)
+{
+	asm volatile (
+	".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1);
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8))
+	: __clobber_all);
+}
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 1);
+	__type(key, long long);
+	__type(value, long long);
+} map_hash_8b SEC(".maps");
+
+SEC("socket")
+__description("store-release, leak pointer to map")
+__success __retval(0)
+__failure_unpriv __msg_unpriv("R6 leaks addr into map")
+__naked void store_release_leak_pointer_to_map(void)
+{
+	asm volatile (
+	"r6 = r1;"
+	"r1 = %[map_hash_8b] ll;"
+	"r2 = 0;"
+	"*(u64 *)(r10 - 8) = r2;"
+	"r2 = r10;"
+	"r2 += -8;"
+	"call %[bpf_map_lookup_elem];"
+	"if r0 == 0 goto l0_%=;"
+	".8byte %[store_release_insn];" // store_release((u64 *)(r0 + 0), r6);
+"l0_%=:"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm_addr(map_hash_8b),
+	  __imm(bpf_map_lookup_elem),
+	  __imm_insn(store_release_insn,
+		     BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_0, BPF_REG_6, 0))
+	: __clobber_all);
+}
+
+#else
+
+SEC("socket")
+__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support store-release, use a dummy test")
+__success
+int dummy_test(void)
+{
+	return 0;
+}
+
+#endif
+
+char _license[] SEC("license") = "GPL";
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:05:41 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:05:41 +0000
Subject: [PATCH bpf-next v6 0/6] Introduce load-acquire and store-release BPF instructions
Message-ID: <cover.1741049567.git.yepeilin@google.com>

Hi all!

This patchset adds kernel support for BPF load-acquire and store-release
instructions (for background, please see [1]), including core/verifier
and arm64/x86-64 JIT compiler changes, as well as selftests.  riscv64 is
also planned to be supported.  The corresponding LLVM changes can be
found at:

  https://github.com/llvm/llvm-project/pull/108636

The first 3 patches from v4 have already been applied:

  - [bpf-next,v4,01/10] bpf/verifier: Factor out atomic_ptr_type_ok()
    https://git.kernel.org/bpf/bpf-next/c/b2d9ef71d4c9
  - [bpf-next,v4,02/10] bpf/verifier: Factor out check_atomic_rmw()
    https://git.kernel.org/bpf/bpf-next/c/d430c46c7580
  - [bpf-next,v4,03/10] bpf/verifier: Factor out check_load_mem() and check_store_reg()
    https://git.kernel.org/bpf/bpf-next/c/d38ad248fb7a

Please refer to the LLVM PR and individual kernel patches for details.
Thanks!

v5: https://lore.kernel.org/all/cover.1741046028.git.yepeilin at google.com/
v5..v6 change:

  o (Alexei) avoid using #ifndef in verifier.c

v4: https://lore.kernel.org/bpf/cover.1740978603.git.yepeilin at google.com/
v4..v5 notable changes:

  o (kernel test robot) for 32-bit arches: make the verifier reject
                        64-bit load-acquires/store-releases, and fix
                        build error in interpreter changes
    * tested ARCH=arc build following instructions from kernel test
      robot
  o (Alexei) drop Documentation/ patch (v4 10/10) for now

v3: https://lore.kernel.org/bpf/cover.1740009184.git.yepeilin at google.com/
v3..v4 notable changes:

  o (Alexei) add x86-64 JIT support (including arena)
  o add Acked-by: tags from Xu

v2: https://lore.kernel.org/bpf/cover.1738888641.git.yepeilin at google.com/
v2..v3 notable changes:

  o (Alexei) change encoding to BPF_LOAD_ACQ=0x100, BPF_STORE_REL=0x110
  o add Acked-by: tags from Ilya and Eduard
  o make new selftests depend on:
    * __clang_major__ >= 18, and
    * ENABLE_ATOMICS_TESTS is defined (currently this means -mcpu=v3 or
      v4), and
    * JIT supports load_acq/store_rel (currenty only arm64)
  o work around llvm-17 CI job failure by conditionally define
    __arena_global variables as 64-bit if __clang_major__ < 18, to make
    sure .addr_space.1 has no holes
  o add Google copyright notice in new files

v1: https://lore.kernel.org/all/cover.1737763916.git.yepeilin at google.com/
v1..v2 notable changes:

  o (Eduard) for x86 and s390, make
             bpf_jit_supports_insn(..., /*in_arena=*/true) return false
	     for load_acq/store_rel
  o add Eduard's Acked-by: tag
  o (Eduard) extract LDX and non-ATOMIC STX handling into helpers, see
             PATCH v2 3/9
  o allow unpriv programs to store-release pointers to stack
  o (Alexei) make it clearer in the interpreter code (PATCH v2 4/9) that
             only W and DW are supported for atomic RMW
  o test misaligned load_acq/store_rel
  o (Eduard) other selftests/ changes:
    * test load_acq/store_rel with !atomic_ptr_type_ok() pointers:
      - PTR_TO_CTX, for is_ctx_reg()
      - PTR_TO_PACKET, for is_pkt_reg()
      - PTR_TO_FLOW_KEYS, for is_flow_key_reg()
      - PTR_TO_SOCKET, for is_sk_reg()
    * drop atomics/ tests
    * delete unnecessary 'pid' checks from arena_atomics/ tests
    * avoid depending on __BPF_FEATURE_LOAD_ACQ_STORE_REL, use
      __imm_insn() and inline asm macros instead

RFC v1: https://lore.kernel.org/all/cover.1734742802.git.yepeilin at google.com
RFC v1..v1 notable changes:

  o 1-2/8: minor verifier.c refactoring patches
  o   3/8: core/verifier changes
         * (Eduard) handle load-acquire properly in backtrack_insn()
         * (Eduard) avoid skipping checks (e.g.,
                    bpf_jit_supports_insn()) for load-acquires
         * track the value stored by store-releases, just like how
           non-atomic STX instructions are handled
         * (Eduard) add missing link in commit message
         * (Eduard) always print 'r' for disasm.c changes
  o   4/8: arm64/insn: avoid treating load_acq/store_rel as
           load_ex/store_ex
  o   5/8: arm64/insn: add load_acq/store_rel
         * (Xu) include Should-Be-One (SBO) bits in "mask" and "value",
                to avoid setting fixed bits during runtime (JIT-compile
                time)
  o   6/8: arm64 JIT compiler changes
         * (Xu) use emit_a64_add_i() for "pointer + offset" to optimize
                code emission
  o   7/8: selftests
         * (Eduard) avoid adding new tests to the 'test_verifier' runner
         * add more tests, e.g., checking mark_precise logic
  o   8/8: instruction-set.rst changes

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Thanks,
Peilin Ye (6):
  bpf: Introduce load-acquire and store-release instructions
  arm64: insn: Add BIT(23) to {load,store}_ex's mask
  arm64: insn: Add load-acquire and store-release instructions
  bpf, arm64: Support load-acquire and store-release instructions
  bpf, x86: Support load-acquire and store-release instructions
  selftests/bpf: Add selftests for load-acquire and store-release
    instructions

 arch/arm64/include/asm/insn.h                 |  12 +-
 arch/arm64/lib/insn.c                         |  29 ++
 arch/arm64/net/bpf_jit.h                      |  20 ++
 arch/arm64/net/bpf_jit_comp.c                 |  86 +++++-
 arch/s390/net/bpf_jit_comp.c                  |  14 +-
 arch/x86/net/bpf_jit_comp.c                   |  95 ++++++-
 include/linux/bpf.h                           |  15 +
 include/linux/filter.h                        |   2 +
 include/uapi/linux/bpf.h                      |   3 +
 kernel/bpf/core.c                             |  67 ++++-
 kernel/bpf/disasm.c                           |  12 +
 kernel/bpf/verifier.c                         |  55 +++-
 tools/include/uapi/linux/bpf.h                |   3 +
 .../selftests/bpf/prog_tests/arena_atomics.c  |  66 ++++-
 .../selftests/bpf/prog_tests/verifier.c       |   4 +
 .../selftests/bpf/progs/arena_atomics.c       | 121 +++++++-
 .../bpf/progs/verifier_load_acquire.c         | 197 +++++++++++++
 .../selftests/bpf/progs/verifier_precision.c  |  49 ++++
 .../bpf/progs/verifier_store_release.c        | 264 ++++++++++++++++++
 19 files changed, 1081 insertions(+), 33 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire.c
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_release.c

-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:06:13 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:13 +0000
Subject: [PATCH bpf-next v6 1/6] bpf: Introduce load-acquire and store-release instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <a217f46f0e445fbd573a1a024be5c6bf1d5fe716.1741049567.git.yepeilin@google.com>

Introduce BPF instructions with load-acquire and store-release
semantics, as discussed in [1].  Define 2 new flags:

  #define BPF_LOAD_ACQ    0x100
  #define BPF_STORE_REL   0x110

A "load-acquire" is a BPF_STX | BPF_ATOMIC instruction with the 'imm'
field set to BPF_LOAD_ACQ (0x100).

Similarly, a "store-release" is a BPF_STX | BPF_ATOMIC instruction with
the 'imm' field set to BPF_STORE_REL (0x110).

Unlike existing atomic read-modify-write operations that only support
BPF_W (32-bit) and BPF_DW (64-bit) size modifiers, load-acquires and
store-releases also support BPF_B (8-bit) and BPF_H (16-bit).  As an
exception, however, 64-bit load-acquires/store-releases are not
supported on 32-bit architectures (to fix a build error reported by the
kernel test robot).

An 8- or 16-bit load-acquire zero-extends the value before writing it to
a 32-bit register, just like ARM64 instruction LDARH and friends.

Similar to existing atomic read-modify-write operations, misaligned
load-acquires/store-releases are not allowed (even if
BPF_F_ANY_ALIGNMENT is set).

As an example, consider the following 64-bit load-acquire BPF
instruction (assuming little-endian):

  db 10 00 00 00 01 00 00  r0 = load_acquire((u64 *)(r1 + 0x0))

  opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX
  imm (0x00000100): BPF_LOAD_ACQ

Similarly, a 16-bit BPF store-release:

  cb 21 00 00 10 01 00 00  store_release((u16 *)(r1 + 0x0), w2)

  opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX
  imm (0x00000110): BPF_STORE_REL

In arch/{arm64,s390,x86}/net/bpf_jit_comp.c, have
bpf_jit_supports_insn(..., /*in_arena=*/true) return false for the new
instructions, until the corresponding JIT compiler supports them in
arena.

[1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin at google.com/

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Acked-by: Ilya Leoshkevich <iii at linux.ibm.com>
Cc: kernel test robot <lkp at intel.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/net/bpf_jit_comp.c  |  4 ++
 arch/s390/net/bpf_jit_comp.c   | 14 +++++--
 arch/x86/net/bpf_jit_comp.c    |  4 ++
 include/linux/bpf.h            | 15 ++++++++
 include/linux/filter.h         |  2 +
 include/uapi/linux/bpf.h       |  3 ++
 kernel/bpf/core.c              | 67 +++++++++++++++++++++++++++++++---
 kernel/bpf/disasm.c            | 12 ++++++
 kernel/bpf/verifier.c          | 55 ++++++++++++++++++++++++++--
 tools/include/uapi/linux/bpf.h |  3 ++
 10 files changed, 166 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 7409c8acbde3..bdda5a77bb16 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -2667,8 +2667,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
 			return false;
 	}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9d440a0b729e..0776dfde2dba 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -2919,10 +2919,16 @@ bool bpf_jit_supports_arena(void)
 
 bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 {
-	/*
-	 * Currently the verifier uses this function only to check which
-	 * atomic stores to arena are supported, and they all are.
-	 */
+	if (!in_arena)
+		return true;
+	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
+	case BPF_STX | BPF_ATOMIC | BPF_W:
+	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
+	}
 	return true;
 }
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a43fc5af973d..f0c31c940fb8 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3771,8 +3771,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 	if (!in_arena)
 		return true;
 	switch (insn->code) {
+	case BPF_STX | BPF_ATOMIC | BPF_B:
+	case BPF_STX | BPF_ATOMIC | BPF_H:
 	case BPF_STX | BPF_ATOMIC | BPF_W:
 	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		if (bpf_atomic_is_load_store(insn))
+			return false;
 		if (insn->imm == (BPF_AND | BPF_FETCH) ||
 		    insn->imm == (BPF_OR | BPF_FETCH) ||
 		    insn->imm == (BPF_XOR | BPF_FETCH))
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 4c4028d865ee..b556a26d8150 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -991,6 +991,21 @@ static inline bool bpf_pseudo_func(const struct bpf_insn *insn)
 	return bpf_is_ldimm64(insn) && insn->src_reg == BPF_PSEUDO_FUNC;
 }
 
+/* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
+ * atomic load or store, and false if it is a read-modify-write instruction.
+ */
+static inline bool
+bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
+{
+	switch (atomic_insn->imm) {
+	case BPF_LOAD_ACQ:
+	case BPF_STORE_REL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 struct bpf_prog_ops {
 	int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
 			union bpf_attr __user *uattr);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3ed6eb9e7c73..24e94afb5622 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -364,6 +364,8 @@ static inline bool insn_is_cast_user(const struct bpf_insn *insn)
  *   BPF_XOR | BPF_FETCH      src_reg = atomic_fetch_xor(dst_reg + off16, src_reg);
  *   BPF_XCHG                 src_reg = atomic_xchg(dst_reg + off16, src_reg)
  *   BPF_CMPXCHG              r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg)
+ *   BPF_LOAD_ACQ             dst_reg = smp_load_acquire(src_reg + off16)
+ *   BPF_STORE_REL            smp_store_release(dst_reg + off16, src_reg)
  */
 
 #define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF)			\
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index a0200fbbace9..6df1d3e379a4 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1663,14 +1663,17 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
 	INSN_3(JMP, JSET, K),			\
 	INSN_2(JMP, JA),			\
 	INSN_2(JMP32, JA),			\
+	/* Atomic operations. */		\
+	INSN_3(STX, ATOMIC, B),			\
+	INSN_3(STX, ATOMIC, H),			\
+	INSN_3(STX, ATOMIC, W),			\
+	INSN_3(STX, ATOMIC, DW),		\
 	/* Store instructions. */		\
 	/*   Register based. */			\
 	INSN_3(STX, MEM,  B),			\
 	INSN_3(STX, MEM,  H),			\
 	INSN_3(STX, MEM,  W),			\
 	INSN_3(STX, MEM,  DW),			\
-	INSN_3(STX, ATOMIC, W),			\
-	INSN_3(STX, ATOMIC, DW),		\
 	/*   Immediate based. */		\
 	INSN_3(ST, MEM, B),			\
 	INSN_3(ST, MEM, H),			\
@@ -2152,24 +2155,33 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				atomic_##KOP((u32) SRC, (atomic_t *)(unsigned long) \
 					     (DST + insn->off));	\
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				atomic64_##KOP((u64) SRC, (atomic64_t *)(unsigned long) \
 					       (DST + insn->off));	\
+			else						\
+				goto default_label;			\
 			break;						\
 		case BOP | BPF_FETCH:					\
 			if (BPF_SIZE(insn->code) == BPF_W)		\
 				SRC = (u32) atomic_fetch_##KOP(		\
 					(u32) SRC,			\
 					(atomic_t *)(unsigned long) (DST + insn->off)); \
-			else						\
+			else if (BPF_SIZE(insn->code) == BPF_DW)	\
 				SRC = (u64) atomic64_fetch_##KOP(	\
 					(u64) SRC,			\
 					(atomic64_t *)(unsigned long) (DST + insn->off)); \
+			else						\
+				goto default_label;			\
 			break;
 
 	STX_ATOMIC_DW:
 	STX_ATOMIC_W:
+	STX_ATOMIC_H:
+	STX_ATOMIC_B:
 		switch (IMM) {
+		/* Atomic read-modify-write instructions support only W and DW
+		 * size modifiers.
+		 */
 		ATOMIC_ALU_OP(BPF_ADD, add)
 		ATOMIC_ALU_OP(BPF_AND, and)
 		ATOMIC_ALU_OP(BPF_OR, or)
@@ -2181,20 +2193,63 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 				SRC = (u32) atomic_xchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				SRC = (u64) atomic64_xchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) SRC);
+			else
+				goto default_label;
 			break;
 		case BPF_CMPXCHG:
 			if (BPF_SIZE(insn->code) == BPF_W)
 				BPF_R0 = (u32) atomic_cmpxchg(
 					(atomic_t *)(unsigned long) (DST + insn->off),
 					(u32) BPF_R0, (u32) SRC);
-			else
+			else if (BPF_SIZE(insn->code) == BPF_DW)
 				BPF_R0 = (u64) atomic64_cmpxchg(
 					(atomic64_t *)(unsigned long) (DST + insn->off),
 					(u64) BPF_R0, (u64) SRC);
+			else
+				goto default_label;
+			break;
+		/* Atomic load and store instructions support all size
+		 * modifiers.
+		 */
+		case BPF_LOAD_ACQ:
+			switch (BPF_SIZE(insn->code)) {
+#define LOAD_ACQUIRE(SIZEOP, SIZE)				\
+			case BPF_##SIZEOP:			\
+				DST = (SIZE)smp_load_acquire(	\
+					(SIZE *)(unsigned long)(SRC + insn->off));	\
+				break;
+			LOAD_ACQUIRE(B,   u8)
+			LOAD_ACQUIRE(H,  u16)
+			LOAD_ACQUIRE(W,  u32)
+#ifdef CONFIG_64BIT
+			LOAD_ACQUIRE(DW, u64)
+#endif
+#undef LOAD_ACQUIRE
+			default:
+				goto default_label;
+			}
+			break;
+		case BPF_STORE_REL:
+			switch (BPF_SIZE(insn->code)) {
+#define STORE_RELEASE(SIZEOP, SIZE)			\
+			case BPF_##SIZEOP:		\
+				smp_store_release(	\
+					(SIZE *)(unsigned long)(DST + insn->off), (SIZE)SRC);	\
+				break;
+			STORE_RELEASE(B,   u8)
+			STORE_RELEASE(H,  u16)
+			STORE_RELEASE(W,  u32)
+#ifdef CONFIG_64BIT
+			STORE_RELEASE(DW, u64)
+#endif
+#undef STORE_RELEASE
+			default:
+				goto default_label;
+			}
 			break;
 
 		default:
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c
index 309c4aa1b026..974d172d6735 100644
--- a/kernel/bpf/disasm.c
+++ b/kernel/bpf/disasm.c
@@ -267,6 +267,18 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
 				BPF_SIZE(insn->code) == BPF_DW ? "64" : "",
 				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
 				insn->dst_reg, insn->off, insn->src_reg);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_LOAD_ACQ) {
+			verbose(cbs->private_data, "(%02x) r%d = load_acquire((%s *)(r%d %+d))\n",
+				insn->code, insn->dst_reg,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->src_reg, insn->off);
+		} else if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+			   insn->imm == BPF_STORE_REL) {
+			verbose(cbs->private_data, "(%02x) store_release((%s *)(r%d %+d), r%d)\n",
+				insn->code,
+				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+				insn->dst_reg, insn->off, insn->src_reg);
 		} else {
 			verbose(cbs->private_data, "BUG_%02x\n", insn->code);
 		}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 22c4edc8695c..b9ffe2ef66fe 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -579,6 +579,13 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
 	       insn->imm == BPF_CMPXCHG;
 }
 
+static bool is_atomic_load_insn(const struct bpf_insn *insn)
+{
+	return BPF_CLASS(insn->code) == BPF_STX &&
+	       BPF_MODE(insn->code) == BPF_ATOMIC &&
+	       insn->imm == BPF_LOAD_ACQ;
+}
+
 static int __get_spi(s32 off)
 {
 	return (-off - 1) / BPF_REG_SIZE;
@@ -3567,7 +3574,7 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
 	}
 
 	if (class == BPF_STX) {
-		/* BPF_STX (including atomic variants) has multiple source
+		/* BPF_STX (including atomic variants) has one or more source
 		 * operands, one of which is a ptr. Check whether the caller is
 		 * asking about it.
 		 */
@@ -4181,7 +4188,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
 			   * dreg still needs precision before this insn
 			   */
 		}
-	} else if (class == BPF_LDX) {
+	} else if (class == BPF_LDX || is_atomic_load_insn(insn)) {
 		if (!bt_is_reg_set(bt, dreg))
 			return 0;
 		bt_clear_reg(bt, dreg);
@@ -7766,6 +7773,32 @@ static int check_atomic_rmw(struct bpf_verifier_env *env,
 	return 0;
 }
 
+static int check_atomic_load(struct bpf_verifier_env *env,
+			     struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->src_reg, insn)) {
+		verbose(env, "BPF_ATOMIC loads from R%d %s is not allowed\n",
+			insn->src_reg,
+			reg_type_str(env, reg_state(env, insn->src_reg)->type));
+		return -EACCES;
+	}
+
+	return check_load_mem(env, insn, true, false, false, "atomic_load");
+}
+
+static int check_atomic_store(struct bpf_verifier_env *env,
+			      struct bpf_insn *insn)
+{
+	if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) {
+		verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n",
+			insn->dst_reg,
+			reg_type_str(env, reg_state(env, insn->dst_reg)->type));
+		return -EACCES;
+	}
+
+	return check_store_reg(env, insn, true);
+}
+
 static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
 	switch (insn->imm) {
@@ -7780,6 +7813,20 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 	case BPF_XCHG:
 	case BPF_CMPXCHG:
 		return check_atomic_rmw(env, insn);
+	case BPF_LOAD_ACQ:
+		if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
+			verbose(env,
+				"64-bit load-acquires are only supported on 64-bit arches\n");
+			return -EOPNOTSUPP;
+		}
+		return check_atomic_load(env, insn);
+	case BPF_STORE_REL:
+		if (BPF_SIZE(insn->code) == BPF_DW && BITS_PER_LONG != 64) {
+			verbose(env,
+				"64-bit store-releases are only supported on 64-bit arches\n");
+			return -EOPNOTSUPP;
+		}
+		return check_atomic_store(env, insn);
 	default:
 		verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
 			insn->imm);
@@ -20605,7 +20652,9 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 			   insn->code == (BPF_ST | BPF_MEM | BPF_W) ||
 			   insn->code == (BPF_ST | BPF_MEM | BPF_DW)) {
 			type = BPF_WRITE;
-		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
+		} else if ((insn->code == (BPF_STX | BPF_ATOMIC | BPF_B) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_H) ||
+			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_W) ||
 			    insn->code == (BPF_STX | BPF_ATOMIC | BPF_DW)) &&
 			   env->insn_aux_data[i + delta].ptr_type == PTR_TO_ARENA) {
 			insn->code = BPF_STX | BPF_PROBE_ATOMIC | BPF_SIZE(insn->code);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index beac5cdf2d2c..bb37897c0393 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -51,6 +51,9 @@
 #define BPF_XCHG	(0xe0 | BPF_FETCH)	/* atomic exchange */
 #define BPF_CMPXCHG	(0xf0 | BPF_FETCH)	/* atomic compare-and-write */
 
+#define BPF_LOAD_ACQ	0x100	/* load-acquire */
+#define BPF_STORE_REL	0x110	/* store-release */
+
 enum bpf_cond_pseudo_jmp {
 	BPF_MAY_GOTO = 0,
 };
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:06:19 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:19 +0000
Subject: [PATCH bpf-next v6 2/6] arm64: insn: Add BIT(23) to {load,store}_ex's mask
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <5a4d2a52b2cc022bf86d0b572789f0b3bc3d5162.1741049567.git.yepeilin@google.com>

We are planning to add load-acquire (LDAR{,B,H}) and store-release
(STLR{,B,H}) instructions to insn.{c,h}; add BIT(23) to mask of load_ex
and store_ex to prevent aarch64_insn_is_{load,store}_ex() from returning
false-positives for load-acquire and store-release instructions.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.228 LDXR
  * C6.2.165 LDAXR
  * C6.2.161 LDAR
  * C6.2.393 STXR
  * C6.2.360 STLXR
  * C6.2.353 STLR

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index e390c432f546..2d8316b3abaf 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -351,8 +351,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
-__AARCH64_INSN_FUNCS(load_ex,	0x3F400000, 0x08400000)
-__AARCH64_INSN_FUNCS(store_ex,	0x3F400000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
+__AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
 __AARCH64_INSN_FUNCS(stp,	0x7FC00000, 0x29000000)
 __AARCH64_INSN_FUNCS(ldp,	0x7FC00000, 0x29400000)
-- 
2.48.1.711.g2feabab25a-goog



From yepeilin at google.com  Mon Mar  3 17:06:27 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue,  4 Mar 2025 01:06:27 +0000
Subject: [PATCH bpf-next v6 3/6] arm64: insn: Add load-acquire and
 store-release instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <ba92057b7502ce4c9c9b03b7d637abe5e178134e.1741049567.git.yepeilin@google.com>

Add load-acquire ("load_acq", LDAR{,B,H}) and store-release
("store_rel", STLR{,B,H}) instructions.  Breakdown of encoding:

                                size        L   (Rs)  o0 (Rt2) Rn    Rt
             mask (0x3fdffc00): 00 111111 1 1 0 11111 1  11111 00000 00000
  value, load_acq (0x08dffc00): 00 001000 1 1 0 11111 1  11111 00000 00000
 value, store_rel (0x089ffc00): 00 001000 1 0 0 11111 1  11111 00000 00000

As suggested by Xu [1], include all Should-Be-One (SBO) bits ("Rs" and
"Rt2" fields) in the "mask" and "value" numbers.

It is worth noting that we are adding the "no offset" variant of STLR
instead of the "pre-index" variant, which has a different encoding.

Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a,
           ID032224),

  * C6.2.161 LDAR
  * C6.2.353 STLR

[1] https://lore.kernel.org/bpf/4e6641ce-3f1e-4251-8daf-4dd4b77d08c4 at huaweicloud.com/

Acked-by: Xu Kuohai <xukuohai at huawei.com>
Signed-off-by: Peilin Ye <yepeilin at google.com>
---
 arch/arm64/include/asm/insn.h |  8 ++++++++
 arch/arm64/lib/insn.c         | 29 +++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 2d8316b3abaf..39577f1d079a 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -188,8 +188,10 @@ enum aarch64_insn_ldst_type {
 	AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX,
 	AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX,
 	AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX,
+	AARCH64_INSN_LDST_LOAD_ACQ,
 	AARCH64_INSN_LDST_LOAD_EX,
 	AARCH64_INSN_LDST_LOAD_ACQ_EX,
+	AARCH64_INSN_LDST_STORE_REL,
 	AARCH64_INSN_LDST_STORE_EX,
 	AARCH64_INSN_LDST_STORE_REL_EX,
 	AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET,
@@ -351,6 +353,8 @@ __AARCH64_INSN_FUNCS(ldr_imm,	0x3FC00000, 0x39400000)
 __AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
 __AARCH64_INSN_FUNCS(ldrsw_lit,	0xFF000000, 0x98000000)
 __AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
+__AARCH64_INSN_FUNCS(load_acq,  0x3FDFFC00, 0x08DFFC00)
+__AARCH64_INSN_FUNCS(store_rel, 0x3FDFFC00, 0x089FFC00)
 __AARCH64_INSN_FUNCS(load_ex,	0x3FC00000, 0x08400000)
 __AARCH64_INSN_FUNCS(store_ex,	0x3FC00000, 0x08000000)
 __AARCH64_INSN_FUNCS(mops,	0x3B200C00, 0x19000400)
@@ -602,6 +606,10 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 				     int offset,
 				     enum aarch64_insn_variant variant,
 				     enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type);
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c
index b008a9b46a7f..9bef696e2230 100644
--- a/arch/arm64/lib/insn.c
+++ b/arch/arm64/lib/insn.c
@@ -540,6 +540,35 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
 					     offset >> shift);
 }
 
+u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg,
+					enum aarch64_insn_register base,
+					enum aarch64_insn_size_type size,
+					enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_ACQ:
+		insn = aarch64_insn_get_load_acq_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_REL:
+		insn = aarch64_insn_get_store_rel_value();
+		break;
+	default:
+		pr_err("%s: unknown load-acquire/store-release encoding %d\n",
+		       __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    reg);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+}
+
 u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
 				   enum aarch64_insn_register base,
 				   enum aarch64_insn_register state,
-- 
2.48.1.711.g2feabab25a-goog



From menglong8.dong at gmail.com  Mon Mar  3 17:10:12 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 09:10:12 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250303165454.GB11590@noisy.programming.kicks-ass.net>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
Message-ID: <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>

On Tue, Mar 4, 2025 at 12:55?AM Peter Zijlstra <peterz at infradead.org> wrote:
>
> On Mon, Mar 03, 2025 at 09:28:34PM +0800, Menglong Dong wrote:
> > For now, the layout of cfi and fineibt is hard coded, and the padding is
> > fixed on 16 bytes.
> >
> > Factor out FINEIBT_INSN_OFFSET and CFI_INSN_OFFSET. CFI_INSN_OFFSET is
> > the offset of cfi, which is the same as FUNCTION_ALIGNMENT when
> > CALL_PADDING is enabled. And FINEIBT_INSN_OFFSET is the offset where we
> > put the fineibt preamble on, which is 16 for now.
> >
> > When the FUNCTION_ALIGNMENT is bigger than 16, we place the fineibt
> > preamble on the last 16 bytes of the padding for better performance, which
> > means the fineibt preamble don't use the space that cfi uses.
> >
> > The FINEIBT_INSN_OFFSET is not used in fineibt_caller_start and
> > fineibt_paranoid_start, as it is always "0x10". Note that we need to
> > update the offset in fineibt_caller_start and fineibt_paranoid_start if
> > FINEIBT_INSN_OFFSET changes.
> >
> > Signed-off-by: Menglong Dong <dongml2 at chinatelecom.cn>
>
> I'm confused as to what exactly you mean.
>
> Preamble will have __cfi symbol and some number of NOPs right before
> actual symbol like:
>
> __cfi_foo:
>   mov $0x12345678, %reg
>   nop
>   nop
>   nop
>   ...
> foo:
>
> FineIBT must be at foo-16, has nothing to do with performance. This 16
> can also be spelled: fineibt_preamble_size.
>
> The total size of the preamble is FUNCTION_PADDING_BYTES + CFI_CLANG*5.
>
> If you increase FUNCTION_PADDING_BYTES by another 5, which is what you
> want I think, then we'll have total preamble of 21 bytes; 5 bytes kCFI,
> 16 bytes nop.

Hello, sorry that I forgot to add something to the changelog. In fact,
I don't add extra 5-bytes anymore, which you can see in the 3rd patch.

The thing is that we can't add extra 5-bytes if CFI is enabled. Without
CFI, we can make the padding space any value, such as 5-bytes, and
the layout will be like this:

__align:
  nop
  nop
  nop
  nop
  nop
foo: -- __align +5

However, the CFI will always make the cfi insn 16-bytes aligned. When
we set the FUNCTION_PADDING_BYTES to (11 + 5), the layout will be
like this:

__cfi_foo:
  nop (11)
  mov $0x12345678, %reg
  nop (16)
foo:

and the padding space is 32-bytes actually. So, we can just select
FUNCTION_ALIGNMENT_32B instead, which makes the padding
space 32-bytes too, and have the following layout:

__cfi_foo:
  mov $0x12345678, %reg
  nop (27)
foo:

And the layout will be like this if fineibt and function metadata is both
used:

__cfi_foo:
        mov     --      5       -- cfi, not used anymore if fineibt is used
        nop
        nop
        nop
        mov     --      5       -- function metadata
        nop
        nop
        nop
        fineibt --      16      -- fineibt
foo:
        nopw    --      4
        ......

The things that I make in this commit is to make sure that
the code in arch/x86/kernel/alternative.c can find the location
of cfi hash and fineibt depends on the FUNCTION_ALIGNMENT.
the offset of cfi and fineibt is different now, so we need to do
some adjustment here.

In the beginning, I thought to make the layout like this to ensure
that the offset of cfi and fineibt the same:

__cfi_foo:
        fineibt  --   16  --  fineibt
        mov    --    5    -- function metadata
        nop(11)
foo:
        nopw    --      4
        ......

The adjustment will be easier in this mode. However, it may have
impact on the performance. That way I say it doesn't impact the
performance in this commit.

Sorry that I didn't describe it clearly in the commit log, and I'll
add the things above to the commit log too in the next version.

Thanks!
Menglong Dong

>
> Then kCFI expects hash to be at -20, while FineIBT must be at -16.
>
> This then means there is no unambiguous hole for you to stick your
> meta-data thing (whatever that is).
>
> There are two options: make meta data location depend on cfi_mode, or
> have __apply_fineibt() rewrite kCFI to also be at -16, so that you can
> have -21 for your 5 bytes.
>
> I think I prefer latter.
>
> In any case, I don't think we need *_INSN_OFFSET. At most we need
> PREAMBLE_SIZE.
>
> Hmm?


From menglong8.dong at gmail.com  Mon Mar  3 17:21:15 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 09:21:15 +0800
Subject: [PATCH v4 4/4] arm64: implement per-function metadata storage for arm64
In-Reply-To: <20250303214048.GA570570@google.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-5-dongml2@chinatelecom.cn> <20250303214048.GA570570@google.com>
Message-ID: <CADxym3Z76bm9wXPjX=9c95eZtWjODwz70xN1KUR92NuC6vzrwg@mail.gmail.com>

On Tue, Mar 4, 2025 at 5:40?AM Sami Tolvanen <samitolvanen at google.com> wrote:
>
> On Mon, Mar 03, 2025 at 09:28:37PM +0800, Menglong Dong wrote:
> > The per-function metadata storage is already used by ftrace if
> > CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS is enabled, and it store the pointer
> > of the callback directly to the function padding, which consume 8-bytes,
> > in the commit
> > baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS").
> > So we can directly store the index to the function padding too, without
> > a prepending. With CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS enabled, the
> > function is 8-bytes aligned, and we will compile the kernel with extra
> > 8-bytes (2 NOPS) padding space. Otherwise, the function is 4-bytes
> > aligned, and only extra 4-bytes (1 NOPS) is needed.
> >
> > However, we have the same problem with Mark in the commit above: we can't
> > use the function padding together with CFI_CLANG, which can make the clang
> > compiles a wrong offset to the pre-function type hash. He said that he was
> > working with others on this problem 2 years ago. Hi Mark, is there any
> > progress on this problem?
>
> I don't think there's been much progress since the previous
> discussion a couple of years ago. The conclusion seemed to be
> that adding a section parameter to -fpatchable-function-entry
> would allow us to identify notrace functions while keeping a
> consistent layout for functions:
>
> https://lore.kernel.org/lkml/Y1QEzk%2FA41PKLEPe at hirez.programming.kicks-ass.net/

Thank you for your information, which helps me a lot.
I'll dig deeper to find a way to keep CFI working together
with this function.

Thanks!
Menglong Dong

>
> Sami


From kuba at kernel.org  Mon Mar  3 17:25:43 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Mon, 3 Mar 2025 17:25:43 -0800
Subject: [PATCH net-next] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250227093712.2130561-1-danishanwar@ti.com>
References: <20250227093712.2130561-1-danishanwar@ti.com>
Message-ID: <20250303172543.249a4fc2@kernel.org>

On Thu, 27 Feb 2025 15:07:12 +0530 MD Danish Anwar wrote:
> +	ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),

I presume frame preemption is implemented in silicon? If yes -
what makes these "FW statistics"? Does the FW collect them from 
the device or the frames are for FW? 

> +	ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
> +	ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
> +	ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
> +	ICSSG_PA_STATS(FW_RX_EXP_FRAG_Q_DROP),
> +	ICSSG_PA_STATS(FW_RX_FIFO_OVERRUN),
> +	ICSSG_PA_STATS(FW_CUT_THR_PKT),
> +	ICSSG_PA_STATS(FW_HOST_RX_PKT_CNT),
> +	ICSSG_PA_STATS(FW_HOST_TX_PKT_CNT),
> +	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_PRE_OVERFLOW),
> +	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_EXP_OVERFLOW),
>  };
>  
>  #endif /* __NET_TI_ICSSG_STATS_H */
> diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
> index 424a7e945ea8..d30203a0978c 100644
> --- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
> +++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
> @@ -231,4 +231,109 @@
>  /* Start of 32 bits PA_STAT counters */
>  #define PA_STAT_32b_START_OFFSET                           0x0080
>  
> +/* Diagnostic error counter which increments when RTU drops a locally injected
> + * packet due to port disabled or rule violation.
> + */
> +#define FW_RTU_PKT_DROP		0x0088
> +
> +/* Tx Queue Overflow Counters */
> +#define FW_Q0_OVERFLOW		0x0090
> +#define FW_Q1_OVERFLOW		0x0098
> +#define FW_Q2_OVERFLOW		0x00A0
> +#define FW_Q3_OVERFLOW		0x00A8
> +#define FW_Q4_OVERFLOW		0x00B0
> +#define FW_Q5_OVERFLOW		0x00B8
> +#define FW_Q6_OVERFLOW		0x00C0
> +#define FW_Q7_OVERFLOW		0x00C8
> +
> +/* Incremented if a packet is dropped at PRU because of a rule violation */
> +#define FW_DROPPED_PKT		0x00F8

Instead of adding comments here please add a file under
Documentation/networking/device_drivers/ with the explanations.
That's far more likely to be discovered by users, no?
-- 
pw-bot: cr


From andre.przywara at arm.com  Mon Mar  3 17:27:58 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:58 +0000
Subject: [PATCH v3 08/15] clk: sunxi-ng: a523: add video mod clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-9-andre.przywara@arm.com>

Add the clocks driving the various video subsystems of the SoC: the "DE"
display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
clocks for the various video output drivers (HDMI, DP, LCDs).

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 238 +++++++++++++++++++++++++
 1 file changed, 238 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index c8a96b642bb1e..ba78a234d8b9d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -364,6 +364,208 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 24, 3,		/* mux */
 				 0);
 
+
+/**************************************************************************
+ *                          mod clocks                                    *
+ **************************************************************************/
+
+static const struct clk_hw *de_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_video3_3x_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *di_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *g2d_parents[] = {
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_hw *gpu_parents[] = {
+	&pll_gpu_clk.common.hw,
+	&pll_periph0_800M_clk.common.hw,
+	&pll_periph0_600M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_200M_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *ve_parents[] = {
+	&pll_ve_clk.common.hw,
+	&pll_periph0_480M_clk.common.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data iommu_parents[] = {
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+	{ .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
+					    0x7b0,
+					    0, 5,	/* M */
+					    0, 0,	/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    CLK_SET_RATE_PARENT,
+					    CCU_FEATURE_UPDATE_BIT27);
+
+static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
+
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
+				      pll_periph0_2x_hws,
+				      0xb10, BIT(30), 36621, 0);
+
+static const struct clk_parent_data hdmi_cec_parents[] = {
+	{ .fw_name = "losc" },
+	{ .hw = &hdmi_cec_32k_clk.common.hw },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
+				    0xb10,
+				    24, 1,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data mipi_dsi_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_200M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
+				      mipi_dsi_parents, 0xb24,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
+				      mipi_dsi_parents, 0xb28,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static const struct clk_hw *tcon_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+	&pll_video0_3x_clk.hw,
+	&pll_video1_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
+				    0xb60,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
+				    0xb64,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *tcon_tv_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd2_clk, "tcon-lcd2",
+				    tcon_tv_parents, 0xb68,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
+				    tcon_parents, 0xb6c,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
+				    tcon_parents, 0xb70,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_tv_parents,
+				    0xb80,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_tv_parents,
+				    0xb84,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *edp_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -394,6 +596,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ahb_clk.common,
 	&apb0_clk.common,
 	&apb1_clk.common,
+	&de_clk.common,
+	&di_clk.common,
+	&g2d_clk.common,
+	&gpu_clk.common,
+	&ve_clk.common,
+	&iommu_clk.common,
+	&hdmi_24M_clk.common,
+	&hdmi_cec_32k_clk.common,
+	&hdmi_cec_clk.common,
+	&mipi_dsi0_clk.common,
+	&mipi_dsi1_clk.common,
+	&tcon_lcd0_clk.common,
+	&tcon_lcd1_clk.common,
+	&tcon_lcd2_clk.common,
+	&tcon_tv0_clk.common,
+	&tcon_tv1_clk.common,
+	&edp_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -420,6 +639,7 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_PLL_PERIPH1_200M]	= &pll_periph1_200M_clk.hw,
 		[CLK_PLL_PERIPH1_160M]	= &pll_periph1_160M_clk.hw,
 		[CLK_PLL_PERIPH1_150M]	= &pll_periph1_150M_clk.hw,
+		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
 		[CLK_PLL_VIDEO0_8X]	= &pll_video0_8x_clk.common.hw,
 		[CLK_PLL_VIDEO0_4X]	= &pll_video0_4x_clk.common.hw,
 		[CLK_PLL_VIDEO0_3X]	= &pll_video0_3x_clk.hw,
@@ -442,6 +662,24 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_AHB]		= &ahb_clk.common.hw,
 		[CLK_APB0]		= &apb0_clk.common.hw,
 		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_DE]		= &de_clk.common.hw,
+		[CLK_DI]		= &di_clk.common.hw,
+		[CLK_G2D]		= &g2d_clk.common.hw,
+		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
+		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
+		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
+		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
+		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
+		[CLK_TCON_LCD0]		= &tcon_lcd0_clk.common.hw,
+		[CLK_TCON_LCD1]		= &tcon_lcd1_clk.common.hw,
+		[CLK_TCON_LCD2]		= &tcon_lcd2_clk.common.hw,
+		[CLK_COMBOPHY_DSI0]	= &combophy_dsi0_clk.common.hw,
+		[CLK_COMBOPHY_DSI1]	= &combophy_dsi1_clk.common.hw,
+		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
+		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
+		[CLK_EDP]		= &edp_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:59 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:59 +0000
Subject: [PATCH v3 09/15] clk: sunxi-ng: a523: add system mod clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-10-andre.przywara@arm.com>

Add the clocks driving some core system related subsystems of the SoC:
the "CE" crypto engine, the high speed timers, the DRAM and the associated
MBUS clock, and the PCIe clock.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 135 +++++++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index ba78a234d8b9d..cd227b4ed388d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -364,6 +364,21 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 24, 3,		/* mux */
 				 0);
 
+static const struct clk_parent_data mbus_parents[] = {
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph1_600M_clk.hw },
+	{ .hw = &pll_periph1_480M_clk.common.hw },
+	{ .hw = &pll_periph1_400M_clk.hw },
+	{ .hw = &pll_periph1_150M_clk.hw },
+	{ .fw_name = "hosc" },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
+					    0x540,
+					    0, 5,		/* M */
+					    0, 0,		/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    0, CCU_FEATURE_UPDATE_BIT27);
 
 /**************************************************************************
  *                          mod clocks                                    *
@@ -423,6 +438,18 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static const struct clk_parent_data ce_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_300M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+				       0, 5,	/* M */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
 static const struct clk_hw *ve_parents[] = {
 	&pll_ve_clk.common.hw,
 	&pll_periph0_480M_clk.common.hw,
@@ -435,6 +462,65 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static const struct clk_parent_data hstimer_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "iosc" },
+	{ .fw_name = "losc" },
+	{ .hw = &pll_periph0_200M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
+				       hstimer_parents, 0x730,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
+				       hstimer_parents,
+				       0x734,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
+				       hstimer_parents,
+				       0x738,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
+				       hstimer_parents,
+				       0x73c,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
+				       hstimer_parents,
+				       0x740,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
+				       hstimer_parents,
+				       0x744,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
 static const struct clk_parent_data iommu_parents[] = {
 	{ .hw = &pll_periph0_600M_clk.hw },
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -453,6 +539,34 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 					    CLK_SET_RATE_PARENT,
 					    CCU_FEATURE_UPDATE_BIT27);
 
+static const struct clk_parent_data dram_parents[] = {
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
+					    0x800,
+					    0, 5,	/* M */
+					    0, 0,	/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    CLK_IS_CRITICAL,
+					    CCU_FEATURE_UPDATE_BIT27);
+
+static const struct clk_parent_data losc_hosc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
+				      losc_hosc_parents, 0xaa0,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
 static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
@@ -596,12 +710,22 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ahb_clk.common,
 	&apb0_clk.common,
 	&apb1_clk.common,
+	&mbus_clk.common,
 	&de_clk.common,
 	&di_clk.common,
 	&g2d_clk.common,
 	&gpu_clk.common,
+	&ce_clk.common,
 	&ve_clk.common,
+	&hstimer0_clk.common,
+	&hstimer1_clk.common,
+	&hstimer2_clk.common,
+	&hstimer3_clk.common,
+	&hstimer4_clk.common,
+	&hstimer5_clk.common,
 	&iommu_clk.common,
+	&dram_clk.common,
+	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
 	&hdmi_cec_clk.common,
@@ -662,11 +786,22 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_AHB]		= &ahb_clk.common.hw,
 		[CLK_APB0]		= &apb0_clk.common.hw,
 		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_DE]		= &de_clk.common.hw,
 		[CLK_DI]		= &di_clk.common.hw,
 		[CLK_G2D]		= &g2d_clk.common.hw,
 		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_CE]		= &ce_clk.common.hw,
 		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_HSTIMER0]		= &hstimer0_clk.common.hw,
+		[CLK_HSTIMER1]		= &hstimer1_clk.common.hw,
+		[CLK_HSTIMER2]		= &hstimer2_clk.common.hw,
+		[CLK_HSTIMER3]		= &hstimer3_clk.common.hw,
+		[CLK_HSTIMER4]		= &hstimer4_clk.common.hw,
+		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
+		[CLK_IOMMU]		= &iommu_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
 		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:00 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:00 +0000
Subject: [PATCH v3 10/15] clk: sunxi-ng: a523: add interface mod clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-11-andre.przywara@arm.com>

Add the clocks driving what the user manual summarises under "interface"
devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
general purpose analogue/digital converter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 159 +++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index cd227b4ed388d..7aa38bb2e6ba6 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -113,6 +113,9 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
 			    pll_periph0_2x_hws, 8, 1, 0);
 static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
 			    pll_periph0_480M_hws, 3, 1, 0);
+static const struct clk_hw *pll_periph0_150M_hws[] = {
+	&pll_periph0_150M_clk.hw
+};
 
 #define SUN55I_A523_PLL_PERIPH1_REG	0x028
 static struct ccu_nm pll_periph1_4x_clk = {
@@ -555,6 +558,132 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 					    CLK_IS_CRITICAL,
 					    CCU_FEATURE_UPDATE_BIT27);
 
+static const struct clk_parent_data nand_mmc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_300M_clk.hw },
+	{ .hw = &pll_periph1_400M_clk.hw },
+	{ .hw = &pll_periph1_300M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
+				    0x810,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
+				    0x814,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc0_clk, "mmc0", nand_mmc_parents,
+					     0x830,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc1_clk, "mmc1", nand_mmc_parents,
+					     0x834,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static const struct clk_parent_data mmc2_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_800M_clk.common.hw },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph1_800M_clk.common.hw },
+	{ .hw = &pll_periph1_600M_clk.hw },
+};
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc2_clk, "mmc2", mmc2_parents,
+					     0x838,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static const struct clk_parent_data spi_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_300M_clk.hw },
+	{ .hw = &pll_periph0_200M_clk.hw },
+	{ .hw = &pll_periph1_300M_clk.hw },
+	{ .hw = &pll_periph1_200M_clk.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents, 0x950,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
+				      pll_periph0_150M_hws,
+				      0x970, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
+				      pll_periph0_150M_hws,
+				      0x974, BIT(31) | BIT(30), 6, 0);
+
+static const struct clk_parent_data ir_rx_parents[] = {
+	{ .fw_name = "losc" },
+	{ .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+static const struct clk_parent_data ir_tx_ledc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph1_600M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
+				      0x9c0,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
+				 0, 5,		/* M */
+				 BIT(31),	/* gate */
+				 0);
+static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
+				 0, 5,		/* M */
+				 BIT(31),	/* gate */
+				 0);
+
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "losc" },
@@ -725,6 +854,21 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&hstimer5_clk.common,
 	&iommu_clk.common,
 	&dram_clk.common,
+	&nand0_clk.common,
+	&nand1_clk.common,
+	&mmc0_clk.common,
+	&mmc1_clk.common,
+	&mmc2_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&spi2_clk.common,
+	&spifc_clk.common,
+	&emac0_25M_clk.common,
+	&emac1_25M_clk.common,
+	&ir_rx_clk.common,
+	&ir_tx_clk.common,
+	&gpadc0_clk.common,
+	&gpadc1_clk.common,
 	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
@@ -801,6 +945,21 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
 		[CLK_IOMMU]		= &iommu_clk.common.hw,
 		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_NAND0]		= &nand0_clk.common.hw,
+		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_SPI2]		= &spi2_clk.common.hw,
+		[CLK_SPIFC]		= &spifc_clk.common.hw,
+		[CLK_EMAC0_25M]		= &emac0_25M_clk.common.hw,
+		[CLK_EMAC1_25M]		= &emac1_25M_clk.common.hw,
+		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
+		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:01 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:01 +0000
Subject: [PATCH v3 11/15] clk: sunxi-ng: a523: add USB mod clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-12-andre.przywara@arm.com>

Add the clocks driving the USB subsystem: this just covers the two
clocks creating the 12 MHz rate for the OHCI (USB 1.x) device. The rest
of the USB clocks are either gate clocks (added later) or created
internal to the USB IP.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 57 ++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 7aa38bb2e6ba6..573c9885110a1 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -684,6 +684,59 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
 				 BIT(31),	/* gate */
 				 0);
 
+/*
+ * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
+ * a 2x multiplier from osc24M synchronized by pll-periph0, and is also used by
+ * the OHCI module.
+ */
+static const struct clk_parent_data usb_ohci_parents[] = {
+	{ .hw = &pll_periph0_4x_clk.common.hw },
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+};
+static const struct ccu_mux_fixed_prediv usb_ohci_predivs[] = {
+	{ .index = 0, .div = 50 },
+	{ .index = 1, .div = 2 },
+};
+
+static struct ccu_mux usb_ohci0_clk = {
+	.enable		= BIT(31),
+	.mux		= {
+		.shift		= 24,
+		.width		= 2,
+		.fixed_predivs	= usb_ohci_predivs,
+		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
+	},
+	.common		= {
+		.reg		= 0xa70,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci0",
+							   usb_ohci_parents,
+							   &ccu_mux_ops,
+							   0),
+	},
+};
+
+static struct ccu_mux usb_ohci1_clk = {
+	.enable		= BIT(31),
+	.mux		= {
+		.shift		= 24,
+		.width		= 2,
+		.fixed_predivs	= usb_ohci_predivs,
+		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
+	},
+	.common		= {
+		.reg		= 0xa74,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci1",
+							   usb_ohci_parents,
+							   &ccu_mux_ops,
+							   0),
+	},
+};
+
+
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "losc" },
@@ -869,6 +922,8 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ir_tx_clk.common,
 	&gpadc0_clk.common,
 	&gpadc1_clk.common,
+	&usb_ohci0_clk.common,
+	&usb_ohci1_clk.common,
 	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
@@ -960,6 +1015,8 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
 		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
 		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:56 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:56 +0000
Subject: [PATCH v3 06/15] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-7-andre.przywara@arm.com>

Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
The clocks were modelled after the A523 and T527 manual, and double
checked by writing all 1's into the respective register, to spot all
implemented bits.

The PLL and mod clocks for the two CPU clusters and the DSU are part of
a separate CCU, also most audio clocks are collected in a DSP CCU, so
both of these clock groups are missing from this driver.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/Kconfig           |   5 +
 drivers/clk/sunxi-ng/Makefile          |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 481 +++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523.h |  14 +
 4 files changed, 502 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index b547198a2c654..04efbda847cf9 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -52,6 +52,11 @@ config SUN50I_H6_R_CCU
 	default y
 	depends on ARM64 || COMPILE_TEST
 
+config SUN55I_A523_CCU
+	tristate "Support for the Allwinner A523/T527 CCU"
+	default y
+	depends on ARM64 || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	tristate "Support for the Allwinner A10/A20 CCU"
 	default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6b3ae2b620db6..01a887f7824bb 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= sun50i-a100-r-ccu.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= sun50i-h6-ccu.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= sun50i-h6-r-ccu.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= sun50i-h616-ccu.o
+obj-$(CONFIG_SUN55I_A523_CCU)	+= sun55i-a523-ccu.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= sun4i-a10-ccu.o
 obj-$(CONFIG_SUN5I_CCU)		+= sun5i-ccu.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= sun6i-a31-ccu.o
@@ -58,6 +59,7 @@ sun50i-a100-r-ccu-y		+= ccu-sun50i-a100-r.o
 sun50i-h6-ccu-y			+= ccu-sun50i-h6.o
 sun50i-h6-r-ccu-y		+= ccu-sun50i-h6-r.o
 sun50i-h616-ccu-y		+= ccu-sun50i-h616.o
+sun55i-a523-ccu-y		+= ccu-sun55i-a523.o
 sun4i-a10-ccu-y			+= ccu-sun4i-a10.o
 sun5i-ccu-y			+= ccu-sun5i.o
 sun6i-a31-ccu-y			+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
new file mode 100644
index 0000000000000..455bca0c344bc
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023-2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ *   Copyright (c) 2020 huangzhenwei at allwinnertech.com
+ *   Copyright (C) 2021 Samuel Holland <samuel at sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "../clk.h"
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun55i-a523.h"
+
+/*
+ * The 24 MHz oscillator, the root of most of the clock tree.
+ * .fw_name is the string used in the DT "clock-names" property, used to
+ * identify the corresponding clock in the "clocks" property.
+ */
+static const struct clk_parent_data osc24M[] = {
+	{ .fw_name = "hosc" }
+};
+
+/**************************************************************************
+ *                              PLLs                                      *
+ **************************************************************************/
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN55I_A523_PLL_DDR0_REG		0x010
+static struct ccu_nkmp pll_ddr_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x010,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE |
+							   CLK_IS_CRITICAL),
+	},
+};
+
+/*
+ * There is no actual clock output with that frequency (2.4 GHz), instead it
+ * has multiple outputs with adjustable dividers from that base frequency.
+ * Model them separately as divider clocks based on that parent here.
+ */
+#define SUN55I_A523_PLL_PERIPH0_REG	0x020
+static struct ccu_nm pll_periph0_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x020,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+/*
+ * Most clock-defining macros expect an *array* of parent clocks, even if
+ * they do not contain a muxer to select between different parents.
+ * The macros ending in just _HW take a simple clock pointer, but then create
+ * a single-entry array out of that. The macros using _HWS take such an
+ * array (even when it is a single entry one), this avoids having those
+ * helper arrays created inside *every* clock definition.
+ * This means for every clock that is referenced more than once it is
+ * useful to create such a dummy array and use _HWS.
+ */
+static const struct clk_hw *pll_periph0_4x_hws[] = {
+	&pll_periph0_4x_clk.common.hw
+};
+
+static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+		       pll_periph0_4x_hws, 0x020, 16, 3, 0);
+static const struct clk_hw *pll_periph0_2x_hws[] = {
+	&pll_periph0_2x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M",
+		       pll_periph0_4x_hws, 0x020, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph0_480M_clk, "pll-periph0-480M",
+		       pll_periph0_4x_hws, 0x020, 2, 3, 0);
+static const struct clk_hw *pll_periph0_480M_hws[] = {
+	&pll_periph0_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph0_600M_clk, "pll-periph0-600M",
+			    pll_periph0_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_400M_clk, "pll-periph0-400M",
+			    pll_periph0_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_300M_clk, "pll-periph0-300M",
+			    pll_periph0_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_200M_clk, "pll-periph0-200M",
+			    pll_periph0_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
+			    pll_periph0_2x_hws, 8, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
+			    pll_periph0_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_PERIPH1_REG	0x028
+static struct ccu_nm pll_periph1_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x028,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph1-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_periph1_4x_hws[] = {
+	&pll_periph1_4x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+		       pll_periph1_4x_hws, 0x028, 16, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_800M_clk, "pll-periph1-800M",
+		       pll_periph1_4x_hws, 0x028, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_480M_clk, "pll-periph1-480M",
+		       pll_periph1_4x_hws, 0x028, 2, 3, 0);
+
+static const struct clk_hw *pll_periph1_2x_hws[] = {
+	&pll_periph1_2x_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_600M_clk, "pll-periph1-600M",
+			    pll_periph1_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_400M_clk, "pll-periph1-400M",
+			    pll_periph1_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_300M_clk, "pll-periph1-300M",
+			    pll_periph1_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_200M_clk, "pll-periph1-200M",
+			    pll_periph1_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_150M_clk, "pll-periph1-150M",
+			    pll_periph1_2x_hws, 8, 1, 0);
+static const struct clk_hw *pll_periph1_480M_hws[] = {
+	&pll_periph1_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_160M_clk, "pll-periph1-160M",
+			    pll_periph1_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_GPU_REG		0x030
+static struct ccu_nkmp pll_gpu_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x030,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-gpu", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+#define SUN55I_A523_PLL_VIDEO0_REG	0x040
+static struct ccu_nm pll_video0_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x040,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video0-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video0_8x_hws[] = {
+	&pll_video0_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video0_4x_clk, "pll-video0-4x",
+		       pll_video0_8x_hws, 0x040, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video0_3x_clk, "pll-video0-3x",
+			    pll_video0_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO1_REG	0x048
+static struct ccu_nm pll_video1_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x048,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video1-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video1_8x_hws[] = {
+	&pll_video1_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video1_4x_clk, "pll-video1-4x",
+		       pll_video1_8x_hws, 0x048, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video1_3x_clk, "pll-video1-3x",
+			    pll_video1_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO2_REG	0x050
+static struct ccu_nm pll_video2_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x050,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video2-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video2_8x_hws[] = {
+	&pll_video2_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video2_4x_clk, "pll-video2-4x",
+		       pll_video2_8x_hws, 0x050, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video2_3x_clk, "pll-video2-3x",
+			    pll_video2_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VE_REG		0x058
+static struct ccu_nkmp pll_ve_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x058,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+#define SUN55I_A523_PLL_VIDEO3_REG	0x068
+static struct ccu_nm pll_video3_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x068,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video3-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video3_8x_hws[] = {
+	&pll_video3_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video3_4x_clk, "pll-video3-4x",
+		       pll_video3_8x_hws, 0x068, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video3_3x_clk, "pll-video3-3x",
+			    pll_video3_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+/*
+ * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors.
+ * Since we only need some fixed frequency from this PLL (22.5792MHz x 4 and
+ * 24.576MHz x 4), ignore those dividers and force both of them to 1 (encoded
+ * as 0), in the probe function below.
+ * The M factor must be an even number to produce a 50% duty cycle output.
+ */
+#define SUN55I_A523_PLL_AUDIO0_REG		0x078
+static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
+	{ .rate = 90316800, .pattern = 0xc000872b, .m = 20, .n = 75 },
+	{ .rate = 98304000, .pattern = 0xc0004dd3, .m = 12, .n = 49 },
+
+};
+
+static struct ccu_nm pll_audio0_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(16, 6),
+	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24),
+					 0x178, BIT(31)),
+	.min_rate	= 180000000U,
+	.max_rate	= 3000000000U,
+	.common		= {
+		.reg		= 0x078,
+		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static CLK_FIXED_FACTOR_HW(pll_audio0_2x_clk, "pll-audio0-2x",
+			   &pll_audio0_4x_clk.common.hw, 2, 1, 0);
+static CLK_FIXED_FACTOR_HW(pll_audio0_clk, "pll-audio0",
+			   &pll_audio0_4x_clk.common.hw, 4, 1, 0);
+
+#define SUN55I_A523_PLL_NPU_REG			0x080
+static struct ccu_nm pll_npu_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1),	/* input divider */
+	.common		= {
+		.reg		= 0x0080,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-npu-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
+			   &pll_npu_4x_clk.common.hw, 2, 1, CLK_SET_RATE_PARENT);
+
+static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
+			   &pll_npu_4x_clk.common.hw, 4, 1, 0);
+
+/*
+ * Contains all clocks that are controlled by a hardware register. They
+ * have a (sunxi) .common member, which needs to be initialised by the common
+ * sunxi CCU code, to be filled with the MMIO base address and the shared lock.
+ */
+static struct ccu_common *sun55i_a523_ccu_clks[] = {
+	&pll_ddr_clk.common,
+	&pll_periph0_4x_clk.common,
+	&pll_periph0_2x_clk.common,
+	&pll_periph0_800M_clk.common,
+	&pll_periph0_480M_clk.common,
+	&pll_periph1_4x_clk.common,
+	&pll_periph1_2x_clk.common,
+	&pll_periph1_800M_clk.common,
+	&pll_periph1_480M_clk.common,
+	&pll_gpu_clk.common,
+	&pll_video0_8x_clk.common,
+	&pll_video0_4x_clk.common,
+	&pll_video1_8x_clk.common,
+	&pll_video1_4x_clk.common,
+	&pll_video2_8x_clk.common,
+	&pll_video2_4x_clk.common,
+	&pll_video3_8x_clk.common,
+	&pll_video3_4x_clk.common,
+	&pll_ve_clk.common,
+	&pll_audio0_4x_clk.common,
+	&pll_npu_4x_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
+	.num	= CLK_NUMBER,
+	.hws	= {
+		[CLK_PLL_DDR0]		= &pll_ddr_clk.common.hw,
+		[CLK_PLL_PERIPH0_4X]	= &pll_periph0_4x_clk.common.hw,
+		[CLK_PLL_PERIPH0_2X]	= &pll_periph0_2x_clk.common.hw,
+		[CLK_PLL_PERIPH0_800M]	= &pll_periph0_800M_clk.common.hw,
+		[CLK_PLL_PERIPH0_480M]	= &pll_periph0_480M_clk.common.hw,
+		[CLK_PLL_PERIPH0_600M]	= &pll_periph0_600M_clk.hw,
+		[CLK_PLL_PERIPH0_400M]	= &pll_periph0_400M_clk.hw,
+		[CLK_PLL_PERIPH0_300M]	= &pll_periph0_300M_clk.hw,
+		[CLK_PLL_PERIPH0_200M]	= &pll_periph0_200M_clk.hw,
+		[CLK_PLL_PERIPH0_160M]	= &pll_periph0_160M_clk.hw,
+		[CLK_PLL_PERIPH0_150M]	= &pll_periph0_150M_clk.hw,
+		[CLK_PLL_PERIPH1_4X]	= &pll_periph1_4x_clk.common.hw,
+		[CLK_PLL_PERIPH1_2X]	= &pll_periph1_2x_clk.common.hw,
+		[CLK_PLL_PERIPH1_800M]	= &pll_periph1_800M_clk.common.hw,
+		[CLK_PLL_PERIPH1_480M]	= &pll_periph1_480M_clk.common.hw,
+		[CLK_PLL_PERIPH1_600M]	= &pll_periph1_600M_clk.hw,
+		[CLK_PLL_PERIPH1_400M]	= &pll_periph1_400M_clk.hw,
+		[CLK_PLL_PERIPH1_300M]	= &pll_periph1_300M_clk.hw,
+		[CLK_PLL_PERIPH1_200M]	= &pll_periph1_200M_clk.hw,
+		[CLK_PLL_PERIPH1_160M]	= &pll_periph1_160M_clk.hw,
+		[CLK_PLL_PERIPH1_150M]	= &pll_periph1_150M_clk.hw,
+		[CLK_PLL_VIDEO0_8X]	= &pll_video0_8x_clk.common.hw,
+		[CLK_PLL_VIDEO0_4X]	= &pll_video0_4x_clk.common.hw,
+		[CLK_PLL_VIDEO0_3X]	= &pll_video0_3x_clk.hw,
+		[CLK_PLL_VIDEO1_8X]	= &pll_video1_8x_clk.common.hw,
+		[CLK_PLL_VIDEO1_4X]	= &pll_video1_4x_clk.common.hw,
+		[CLK_PLL_VIDEO1_3X]	= &pll_video1_3x_clk.hw,
+		[CLK_PLL_VIDEO2_8X]	= &pll_video2_8x_clk.common.hw,
+		[CLK_PLL_VIDEO2_4X]	= &pll_video2_4x_clk.common.hw,
+		[CLK_PLL_VIDEO2_3X]	= &pll_video2_3x_clk.hw,
+		[CLK_PLL_VIDEO3_8X]	= &pll_video3_8x_clk.common.hw,
+		[CLK_PLL_VIDEO3_4X]	= &pll_video3_4x_clk.common.hw,
+		[CLK_PLL_VIDEO3_3X]	= &pll_video3_3x_clk.hw,
+		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
+		[CLK_PLL_AUDIO0_4X]	= &pll_audio0_4x_clk.common.hw,
+		[CLK_PLL_AUDIO0_2X]	= &pll_audio0_2x_clk.hw,
+		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.hw,
+		[CLK_PLL_NPU_4X]	= &pll_npu_4x_clk.common.hw,
+		[CLK_PLL_NPU_2X]	= &pll_npu_2x_clk.hw,
+		[CLK_PLL_NPU]		= &pll_npu_1x_clk.hw,
+	},
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
+	.ccu_clks	= sun55i_a523_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_ccu_clks),
+
+	.hw_clks	= &sun55i_a523_hw_clks,
+};
+
+static const u32 pll_regs[] = {
+	SUN55I_A523_PLL_DDR0_REG,
+	SUN55I_A523_PLL_PERIPH0_REG,
+	SUN55I_A523_PLL_PERIPH1_REG,
+	SUN55I_A523_PLL_GPU_REG,
+	SUN55I_A523_PLL_VIDEO0_REG,
+	SUN55I_A523_PLL_VIDEO1_REG,
+	SUN55I_A523_PLL_VIDEO2_REG,
+	SUN55I_A523_PLL_VE_REG,
+	SUN55I_A523_PLL_VIDEO3_REG,
+	SUN55I_A523_PLL_AUDIO0_REG,
+	SUN55I_A523_PLL_NPU_REG,
+};
+
+static int sun55i_a523_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+	u32 val;
+	int i, ret;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/*
+	 * The PLL clock code does not model all bits, for instance it does
+	 * not support a separate enable and gate bit. We present the
+	 * gate bit(27) as the enable bit, but then have to set the
+	 * PLL Enable, LDO Enable, and Lock Enable bits on all PLLs here.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		val = readl(reg + pll_regs[i]);
+		val |= BIT(31) | BIT(30) | BIT(29);
+		writel(val, reg + pll_regs[i]);
+	}
+
+	/* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
+	val = readl(reg + SUN55I_A523_PLL_AUDIO0_REG);
+	val &= ~(BIT(1) | BIT(0));
+	writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
+
+	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id sun55i_a523_ccu_ids[] = {
+	{ .compatible = "allwinner,sun55i-a523-ccu" },
+	{ }
+};
+
+static struct platform_driver sun55i_a523_ccu_driver = {
+	.probe	= sun55i_a523_ccu_probe,
+	.driver	= {
+		.name			= "sun55i-a523-ccu",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sun55i_a523_ccu_ids,
+	},
+};
+module_platform_driver(sun55i_a523_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
new file mode 100644
index 0000000000000..fc8dd42f1b47b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_H
+#define _CCU_SUN55I_A523_H
+
+#include <dt-bindings/clock/sun55i-a523-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-ccu.h>
+
+#define CLK_NUMBER	(CLK_FANOUT2 + 1)
+
+#endif /* _CCU_SUN55I_A523_H */
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:02 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:02 +0000
Subject: [PATCH v3 12/15] clk: sunxi-ng: a523: remaining mod clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-13-andre.przywara@arm.com>

Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
LED controller, the "CSI" camera interface, the "ISP" image processor,
the DSP clock, and the "fanout" clocks, which allow to put clock signals
on external pins.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 185 +++++++++++++++++++++++++
 1 file changed, 185 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 573c9885110a1..12cdd623a3851 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -862,6 +862,157 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
+				      0xbf0,
+				      0, 4,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static const struct clk_hw *csi_top_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_480M_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_video3_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
+				    0xc04,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data csi_mclk_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_video3_4x_clk.common.hw },
+	{ .hw = &pll_video0_4x_clk.common.hw },
+	{ .hw = &pll_video1_4x_clk.common.hw },
+	{ .hw = &pll_video2_4x_clk.common.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents,
+				  0xc08,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents,
+				  0xc0c,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents,
+				  0xc10,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk3_clk, "csi-mclk3", csi_mclk_parents,
+				  0xc14,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_hw *isp_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data dsp_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_2x_clk.common.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw, },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
+			   0xf30, BIT(0), 0);
+static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
+				       0xf30, BIT(1), 2, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
+				      pll_periph0_480M_hws,
+				      0xf30, BIT(2), 30, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
+				      pll_periph0_2x_hws,
+				      0xf30, BIT(3), 48, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
+				      pll_periph0_2x_hws,
+				      0xf30, BIT(4), 24, 0);
+
+static const struct clk_parent_data fanout_27M_parents[] = {
+	{ .hw = &pll_video0_4x_clk.common.hw },
+	{ .hw = &pll_video1_4x_clk.common.hw },
+	{ .hw = &pll_video2_4x_clk.common.hw },
+	{ .hw = &pll_video3_4x_clk.common.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_27M_clk, "fanout-27M",
+				  fanout_27M_parents, 0xf34,
+				  0, 5,		/* div0 */
+				  8, 5,		/* div1 */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_parent_data fanout_pclk_parents[] = {
+	{ .hw = &apb0_clk.common.hw }
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_pclk_clk, "fanout-pclk",
+				  fanout_pclk_parents,
+				  0xf38,
+				  0, 5,		/* div0 */
+				  5, 5,		/* div1 */
+				  0, 0,		/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_parent_data fanout_parents[] = {
+	{ .fw_name = "losc-fanout" },
+	{ .hw = &fanout_12M_clk.common.hw, },
+	{ .hw = &fanout_16M_clk.common.hw, },
+	{ .hw = &fanout_24M_clk.common.hw, },
+	{ .hw = &fanout_25M_clk.common.hw, },
+	{ .hw = &fanout_27M_clk.common.hw, },
+	{ .hw = &fanout_pclk_clk.common.hw, },
+	{ .hw = &fanout_50M_clk.common.hw, },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
+				    0xf3c,
+				    0, 3,	/* mux */
+				    BIT(21),	/* gate */
+				    0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
+				    0xf3c,
+				    3, 3,	/* mux */
+				    BIT(22),	/* gate */
+				    0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
+				    0xf3c,
+				    6, 3,	/* mux */
+				    BIT(23),	/* gate */
+				    0);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -936,6 +1087,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&tcon_tv0_clk.common,
 	&tcon_tv1_clk.common,
 	&edp_clk.common,
+	&ledc_clk.common,
+	&csi_top_clk.common,
+	&csi_mclk0_clk.common,
+	&csi_mclk1_clk.common,
+	&csi_mclk2_clk.common,
+	&csi_mclk3_clk.common,
+	&isp_clk.common,
+	&dsp_clk.common,
+	&fanout_24M_clk.common,
+	&fanout_12M_clk.common,
+	&fanout_16M_clk.common,
+	&fanout_25M_clk.common,
+	&fanout_27M_clk.common,
+	&fanout_pclk_clk.common,
+	&fanout0_clk.common,
+	&fanout1_clk.common,
+	&fanout2_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -1031,6 +1199,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
 		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
 		[CLK_EDP]		= &edp_clk.common.hw,
+		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_CSI_TOP]		= &csi_top_clk.common.hw,
+		[CLK_CSI_MCLK0]		= &csi_mclk0_clk.common.hw,
+		[CLK_CSI_MCLK1]		= &csi_mclk1_clk.common.hw,
+		[CLK_CSI_MCLK2]		= &csi_mclk2_clk.common.hw,
+		[CLK_CSI_MCLK3]		= &csi_mclk3_clk.common.hw,
+		[CLK_ISP]		= &isp_clk.common.hw,
+		[CLK_DSP]		= &dsp_clk.common.hw,
+		[CLK_FANOUT_24M]	= &fanout_24M_clk.common.hw,
+		[CLK_FANOUT_12M]	= &fanout_12M_clk.common.hw,
+		[CLK_FANOUT_16M]	= &fanout_16M_clk.common.hw,
+		[CLK_FANOUT_25M]	= &fanout_25M_clk.common.hw,
+		[CLK_FANOUT_27M]	= &fanout_27M_clk.common.hw,
+		[CLK_FANOUT_PCLK]	= &fanout_pclk_clk.common.hw,
+		[CLK_FANOUT0]		= &fanout0_clk.common.hw,
+		[CLK_FANOUT1]		= &fanout1_clk.common.hw,
+		[CLK_FANOUT2]		= &fanout2_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:03 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:03 +0000
Subject: [PATCH v3 13/15] clk: sunxi-ng: a523: add bus clock gates
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-14-andre.przywara@arm.com>

Add the various bus clock gates that control access to the devices'
register interface.
These clocks are each just one bit, typically the lower bits in some "BGR"
(Bus Gate / Reset) registers, for each device group: one for all UARTs,
one for all SPI interfaces, and so on.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 309 ++++++++++++++++++++++++-
 1 file changed, 308 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 12cdd623a3851..7d46a5ccbb051 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -350,10 +350,13 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
 				 0, 5,		/* M */
 				 24, 2,		/* mux */
 				 0);
+static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
+
 static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
 				 0, 5,		/* M */
 				 24, 2,	/* mux */
 				 0);
+static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
 
 static const struct clk_parent_data apb1_parents[] = {
 	{ .fw_name = "hosc" },
@@ -366,6 +369,7 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 0, 5,		/* M */
 				 24, 3,		/* mux */
 				 0);
+static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
 
 static const struct clk_parent_data mbus_parents[] = {
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -383,8 +387,10 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
 					    BIT(31),	/* gate */
 					    0, CCU_FEATURE_UPDATE_BIT27);
 
+static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw };
+
 /**************************************************************************
- *                          mod clocks                                    *
+ *                          mod clocks with gates                         *
  **************************************************************************/
 
 static const struct clk_hw *de_parents[] = {
@@ -400,6 +406,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
+
 static const struct clk_hw *di_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -413,6 +421,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
+
 static const struct clk_hw *g2d_parents[] = {
 	&pll_periph0_400M_clk.hw,
 	&pll_periph0_300M_clk.hw,
@@ -426,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
+
 static const struct clk_hw *gpu_parents[] = {
 	&pll_gpu_clk.common.hw,
 	&pll_periph0_800M_clk.common.hw,
@@ -441,6 +453,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
+
 static const struct clk_parent_data ce_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_480M_clk.common.hw },
@@ -453,6 +467,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
 				       BIT(31),	/* gate */
 				       0);
 
+static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
+			  BIT(1), 0);
+
 static const struct clk_hw *ve_parents[] = {
 	&pll_ve_clk.common.hw,
 	&pll_periph0_480M_clk.common.hw,
@@ -465,6 +483,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
+			  BIT(0), 0);
+
 static const struct clk_parent_data hstimer_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "iosc" },
@@ -524,6 +552,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
 				       BIT(31),	/* gate */
 				       0);
 
+static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
+
 static const struct clk_parent_data iommu_parents[] = {
 	{ .hw = &pll_periph0_600M_clk.hw },
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -542,6 +579,9 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 					    CLK_SET_RATE_PARENT,
 					    CCU_FEATURE_UPDATE_BIT27);
 
+static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
+			  BIT(0), 0);
+
 static const struct clk_parent_data dram_parents[] = {
 	{ .hw = &pll_ddr_clk.common.hw },
 	{ .hw = &pll_periph0_600M_clk.hw },
@@ -558,6 +598,26 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 					    CLK_IS_CRITICAL,
 					    CCU_FEATURE_UPDATE_BIT27);
 
+static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
+			  0x804, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
+			  0x804, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
+			  0x804, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(mbus_nand_clk, "mbus-nand", mbus_hws,
+			  0x804, BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(mbus_usb3_clk, "mbus-usb3", mbus_hws,
+			  0x804, BIT(6), 0);
+static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
+			  0x804, BIT(8), 0);
+static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
+			  0x804, BIT(9), 0);
+static SUNXI_CCU_GATE_HWS(mbus_gmac1_clk, "mbus-gmac1", mbus_hws,
+			  0x804, BIT(12), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
+			  BIT(0), CLK_IS_CRITICAL);
+
 static const struct clk_parent_data nand_mmc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_400M_clk.hw },
@@ -580,6 +640,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
+			  BIT(0), 0);
+
 static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc0_clk, "mmc0", nand_mmc_parents,
 					     0x830,
 					     0, 5,	/* M */
@@ -615,6 +678,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc2_clk, "mmc2", mmc2_parents,
 					     2,		/* post div */
 					     0);
 
+static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
+			  BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
+			  BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
+			  BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
+			  BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
+			  BIT(6), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
+			  BIT(7), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
+
 static const struct clk_parent_data spi_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_300M_clk.hw },
@@ -646,6 +742,11 @@ static SUNXI_CCU_DUALDIV_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents, 0x950,
 				  24, 3,	/* mux */
 				  BIT(31),	/* gate */
 				  0);
+static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
+			  BIT(3), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
 				      pll_periph0_150M_hws,
@@ -653,6 +754,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
 				      pll_periph0_150M_hws,
 				      0x974, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
+			  BIT(0), 0);
 
 static const struct clk_parent_data ir_rx_parents[] = {
 	{ .fw_name = "losc" },
@@ -664,6 +769,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
 				      24, 1,	/* mux */
 				      BIT(31),	/* gate */
 				      0);
+static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
+			  BIT(0), 0);
+
 static const struct clk_parent_data ir_tx_ledc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph1_600M_clk.hw },
@@ -674,6 +782,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
 				      24, 1,	/* mux */
 				      BIT(31),	/* gate */
 				      0);
+static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
+			  BIT(0), 0);
 
 static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
 				 0, 5,		/* M */
@@ -683,6 +793,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
 				 0, 5,		/* M */
 				 BIT(31),	/* gate */
 				 0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
+			  BIT(1), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
 
 /*
  * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
@@ -736,6 +852,18 @@ static struct ccu_mux usb_ohci1_clk = {
 	},
 };
 
+static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
+			  BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
+			  BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
+			  BIT(0), 0);
 
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
@@ -749,6 +877,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_display0_top_clk, "bus-display0-top", ahb_hws,
+			  0xabc, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_display1_top_clk, "bus-display1-top", ahb_hws,
+			  0xacc, BIT(0), 0);
+
 static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
@@ -765,6 +898,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
+
 static const struct clk_parent_data mipi_dsi_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_200M_clk.hw },
@@ -784,6 +919,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
+			  BIT(1), 0);
+
 static const struct clk_hw *tcon_parents[] = {
 	&pll_video0_4x_clk.common.hw,
 	&pll_video1_4x_clk.common.hw,
@@ -835,6 +976,13 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd2_clk, "bus-tcon-lcd2", ahb_hws, 0xb7c,
+			  BIT(2), 0);
+
 static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_tv_parents,
 				    0xb80,
 				    0, 4,	/* M */
@@ -849,6 +997,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_tv_parents,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
+			  BIT(1), 0);
+
 static const struct clk_hw *edp_parents[] = {
 	&pll_video0_4x_clk.common.hw,
 	&pll_video1_4x_clk.common.hw,
@@ -862,6 +1015,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
+
 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
 				      0xbf0,
 				      0, 4,	/* M */
@@ -869,6 +1024,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
+
 static const struct clk_hw *csi_top_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -922,6 +1079,8 @@ static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk3_clk, "csi-mclk3", csi_mclk_parents,
 				  BIT(31),	/* gate */
 				  0);
 
+static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
+
 static const struct clk_hw *isp_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -1045,54 +1204,130 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&apb1_clk.common,
 	&mbus_clk.common,
 	&de_clk.common,
+	&bus_de_clk.common,
 	&di_clk.common,
+	&bus_di_clk.common,
 	&g2d_clk.common,
+	&bus_g2d_clk.common,
 	&gpu_clk.common,
+	&bus_gpu_clk.common,
 	&ce_clk.common,
+	&bus_ce_clk.common,
+	&bus_ce_sys_clk.common,
 	&ve_clk.common,
+	&bus_ve_clk.common,
+	&bus_dma_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
 	&hstimer0_clk.common,
 	&hstimer1_clk.common,
 	&hstimer2_clk.common,
 	&hstimer3_clk.common,
 	&hstimer4_clk.common,
 	&hstimer5_clk.common,
+	&bus_hstimer_clk.common,
+	&bus_dbg_clk.common,
+	&bus_pwm0_clk.common,
+	&bus_pwm1_clk.common,
 	&iommu_clk.common,
+	&bus_iommu_clk.common,
 	&dram_clk.common,
+	&mbus_dma_clk.common,
+	&mbus_ve_clk.common,
+	&mbus_ce_clk.common,
+	&mbus_nand_clk.common,
+	&mbus_usb3_clk.common,
+	&mbus_csi_clk.common,
+	&mbus_isp_clk.common,
+	&mbus_gmac1_clk.common,
+	&bus_dram_clk.common,
 	&nand0_clk.common,
 	&nand1_clk.common,
+	&bus_nand_clk.common,
 	&mmc0_clk.common,
 	&mmc1_clk.common,
 	&mmc2_clk.common,
+	&bus_sysdap_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_mmc2_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_uart4_clk.common,
+	&bus_uart5_clk.common,
+	&bus_uart6_clk.common,
+	&bus_uart7_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_i2c2_clk.common,
+	&bus_i2c3_clk.common,
+	&bus_i2c4_clk.common,
+	&bus_i2c5_clk.common,
+	&bus_can_clk.common,
 	&spi0_clk.common,
 	&spi1_clk.common,
 	&spi2_clk.common,
 	&spifc_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&bus_spi2_clk.common,
+	&bus_spifc_clk.common,
 	&emac0_25M_clk.common,
 	&emac1_25M_clk.common,
+	&bus_emac0_clk.common,
+	&bus_emac1_clk.common,
 	&ir_rx_clk.common,
+	&bus_ir_rx_clk.common,
 	&ir_tx_clk.common,
+	&bus_ir_tx_clk.common,
 	&gpadc0_clk.common,
 	&gpadc1_clk.common,
+	&bus_gpadc0_clk.common,
+	&bus_gpadc1_clk.common,
+	&bus_ths_clk.common,
 	&usb_ohci0_clk.common,
 	&usb_ohci1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ohci1_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_ehci1_clk.common,
+	&bus_otg_clk.common,
+	&bus_lradc_clk.common,
 	&pcie_aux_clk.common,
+	&bus_display0_top_clk.common,
+	&bus_display1_top_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
 	&hdmi_cec_clk.common,
+	&bus_hdmi_clk.common,
 	&mipi_dsi0_clk.common,
 	&mipi_dsi1_clk.common,
+	&bus_mipi_dsi0_clk.common,
+	&bus_mipi_dsi1_clk.common,
 	&tcon_lcd0_clk.common,
 	&tcon_lcd1_clk.common,
 	&tcon_lcd2_clk.common,
+	&combophy_dsi0_clk.common,
+	&combophy_dsi1_clk.common,
+	&bus_tcon_lcd0_clk.common,
+	&bus_tcon_lcd1_clk.common,
+	&bus_tcon_lcd2_clk.common,
 	&tcon_tv0_clk.common,
 	&tcon_tv1_clk.common,
+	&bus_tcon_tv0_clk.common,
+	&bus_tcon_tv1_clk.common,
 	&edp_clk.common,
+	&bus_edp_clk.common,
 	&ledc_clk.common,
+	&bus_ledc_clk.common,
 	&csi_top_clk.common,
 	&csi_mclk0_clk.common,
 	&csi_mclk1_clk.common,
 	&csi_mclk2_clk.common,
 	&csi_mclk3_clk.common,
+	&bus_csi_clk.common,
 	&isp_clk.common,
 	&dsp_clk.common,
 	&fanout_24M_clk.common,
@@ -1155,56 +1390,128 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_APB1]		= &apb1_clk.common.hw,
 		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_DE]		= &de_clk.common.hw,
+		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
 		[CLK_DI]		= &di_clk.common.hw,
+		[CLK_BUS_DI]		= &bus_di_clk.common.hw,
 		[CLK_G2D]		= &g2d_clk.common.hw,
+		[CLK_BUS_G2D]		= &bus_g2d_clk.common.hw,
 		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
 		[CLK_CE]		= &ce_clk.common.hw,
+		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
+		[CLK_BUS_CE_SYS]	= &bus_ce_sys_clk.common.hw,
 		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
 		[CLK_HSTIMER0]		= &hstimer0_clk.common.hw,
 		[CLK_HSTIMER1]		= &hstimer1_clk.common.hw,
 		[CLK_HSTIMER2]		= &hstimer2_clk.common.hw,
 		[CLK_HSTIMER3]		= &hstimer3_clk.common.hw,
 		[CLK_HSTIMER4]		= &hstimer4_clk.common.hw,
 		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
+		[CLK_BUS_PWM0]		= &bus_pwm0_clk.common.hw,
+		[CLK_BUS_PWM1]		= &bus_pwm1_clk.common.hw,
 		[CLK_IOMMU]		= &iommu_clk.common.hw,
+		[CLK_BUS_IOMMU]		= &bus_iommu_clk.common.hw,
 		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
+		[CLK_MBUS_VE]		= &mbus_ve_clk.common.hw,
+		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
+		[CLK_MBUS_CSI]		= &mbus_csi_clk.common.hw,
+		[CLK_MBUS_ISP]		= &mbus_isp_clk.common.hw,
+		[CLK_MBUS_EMAC1]	= &mbus_gmac1_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
 		[CLK_NAND0]		= &nand0_clk.common.hw,
 		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
 		[CLK_MMC0]		= &mmc0_clk.common.hw,
 		[CLK_MMC1]		= &mmc1_clk.common.hw,
 		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_BUS_SYSDAP]	= &bus_sysdap_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
+		[CLK_BUS_UART5]		= &bus_uart5_clk.common.hw,
+		[CLK_BUS_UART6]		= &bus_uart6_clk.common.hw,
+		[CLK_BUS_UART7]		= &bus_uart7_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
+		[CLK_BUS_I2C3]		= &bus_i2c3_clk.common.hw,
+		[CLK_BUS_I2C4]		= &bus_i2c4_clk.common.hw,
+		[CLK_BUS_I2C5]		= &bus_i2c5_clk.common.hw,
+		[CLK_BUS_CAN]		= &bus_can_clk.common.hw,
 		[CLK_SPI0]		= &spi0_clk.common.hw,
 		[CLK_SPI1]		= &spi1_clk.common.hw,
 		[CLK_SPI2]		= &spi2_clk.common.hw,
 		[CLK_SPIFC]		= &spifc_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_BUS_SPI2]		= &bus_spi2_clk.common.hw,
+		[CLK_BUS_SPIFC]		= &bus_spifc_clk.common.hw,
 		[CLK_EMAC0_25M]		= &emac0_25M_clk.common.hw,
 		[CLK_EMAC1_25M]		= &emac1_25M_clk.common.hw,
+		[CLK_BUS_EMAC0]		= &bus_emac0_clk.common.hw,
+		[CLK_BUS_EMAC1]		= &bus_emac1_clk.common.hw,
 		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
 		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
 		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
 		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
+		[CLK_BUS_GPADC0]	= &bus_gpadc0_clk.common.hw,
+		[CLK_BUS_GPADC1]	= &bus_gpadc1_clk.common.hw,
+		[CLK_BUS_THS]		= &bus_ths_clk.common.hw,
 		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
 		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_BUS_LRADC]		= &bus_lradc_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
+		[CLK_BUS_DISPLAY0_TOP]	= &bus_display0_top_clk.common.hw,
+		[CLK_BUS_DISPLAY1_TOP]	= &bus_display1_top_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
 		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
+		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
 		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
 		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
+		[CLK_BUS_MIPI_DSI0]	= &bus_mipi_dsi0_clk.common.hw,
+		[CLK_BUS_MIPI_DSI1]	= &bus_mipi_dsi1_clk.common.hw,
 		[CLK_TCON_LCD0]		= &tcon_lcd0_clk.common.hw,
 		[CLK_TCON_LCD1]		= &tcon_lcd1_clk.common.hw,
 		[CLK_TCON_LCD2]		= &tcon_lcd2_clk.common.hw,
 		[CLK_COMBOPHY_DSI0]	= &combophy_dsi0_clk.common.hw,
 		[CLK_COMBOPHY_DSI1]	= &combophy_dsi1_clk.common.hw,
+		[CLK_BUS_TCON_LCD0]	= &bus_tcon_lcd0_clk.common.hw,
+		[CLK_BUS_TCON_LCD1]	= &bus_tcon_lcd1_clk.common.hw,
+		[CLK_BUS_TCON_LCD2]	= &bus_tcon_lcd2_clk.common.hw,
 		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
 		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
+		[CLK_BUS_TCON_TV0]	= &bus_tcon_tv0_clk.common.hw,
+		[CLK_BUS_TCON_TV1]	= &bus_tcon_tv1_clk.common.hw,
 		[CLK_EDP]		= &edp_clk.common.hw,
+		[CLK_BUS_EDP]		= &bus_edp_clk.common.hw,
 		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
 		[CLK_CSI_TOP]		= &csi_top_clk.common.hw,
 		[CLK_CSI_MCLK0]		= &csi_mclk0_clk.common.hw,
 		[CLK_CSI_MCLK1]		= &csi_mclk1_clk.common.hw,
 		[CLK_CSI_MCLK2]		= &csi_mclk2_clk.common.hw,
 		[CLK_CSI_MCLK3]		= &csi_mclk3_clk.common.hw,
+		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
 		[CLK_ISP]		= &isp_clk.common.hw,
 		[CLK_DSP]		= &dsp_clk.common.hw,
 		[CLK_FANOUT_24M]	= &fanout_24M_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:04 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:04 +0000
Subject: [PATCH v3 14/15] clk: sunxi-ng: a523: add reset lines
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-15-andre.przywara@arm.com>

Allwinner SoCs do not contain a separate reset controller, instead the
reset lines for the various devices are integrated into the "BGR" (Bus
Gate / Reset) registers, for each device group: one for all UARTs, one
for all SPI interfaces, and so on.
The Allwinner CCU driver also doubles as a reset provider, and since the
reset lines are indeed just single bits in those BGR register, we can
represent them easily in an array of structs, just containing the
register offset and the bit number.

Add the location of the reset bits for all devices in the A523/T527
SoCs, using the existing sunxi CCU infrastructure.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 84 ++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 7d46a5ccbb051..7b2ac2705773f 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -1526,11 +1526,95 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 	},
 };
 
+static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
+	[RST_MBUS]		= { 0x540, BIT(30) },
+	[RST_BUS_NSI]		= { 0x54c, BIT(16) },
+	[RST_BUS_DE]		= { 0x60c, BIT(16) },
+	[RST_BUS_DI]		= { 0x62c, BIT(16) },
+	[RST_BUS_G2D]		= { 0x63c, BIT(16) },
+	[RST_BUS_SYS]		= { 0x64c, BIT(16) },
+	[RST_BUS_GPU]		= { 0x67c, BIT(16) },
+	[RST_BUS_CE]		= { 0x68c, BIT(16) },
+	[RST_BUS_SYS_CE]	= { 0x68c, BIT(17) },
+	[RST_BUS_VE]		= { 0x69c, BIT(16) },
+	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
+	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
+	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
+	[RST_BUS_CPUXTIMER]	= { 0x74c, BIT(16) },
+	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
+	[RST_BUS_PWM0]		= { 0x7ac, BIT(16) },
+	[RST_BUS_PWM1]		= { 0x7ac, BIT(17) },
+	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
+	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
+	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
+	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
+	[RST_BUS_MMC2]		= { 0x84c, BIT(18) },
+	[RST_BUS_SYSDAP]	= { 0x88c, BIT(16) },
+	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
+	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
+	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
+	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
+	[RST_BUS_UART4]		= { 0x90c, BIT(20) },
+	[RST_BUS_UART5]		= { 0x90c, BIT(21) },
+	[RST_BUS_UART6]		= { 0x90c, BIT(22) },
+	[RST_BUS_UART7]		= { 0x90c, BIT(23) },
+	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
+	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
+	[RST_BUS_I2C2]		= { 0x91c, BIT(18) },
+	[RST_BUS_I2C3]		= { 0x91c, BIT(19) },
+	[RST_BUS_I2C4]		= { 0x91c, BIT(20) },
+	[RST_BUS_I2C5]		= { 0x91c, BIT(21) },
+	[RST_BUS_CAN]		= { 0x92c, BIT(16) },
+	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
+	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
+	[RST_BUS_SPI2]		= { 0x96c, BIT(18) },
+	[RST_BUS_SPIFC]		= { 0x96c, BIT(19) },
+	[RST_BUS_EMAC0]		= { 0x97c, BIT(16) },
+	[RST_BUS_EMAC1]		= { 0x98c, BIT(16) | BIT(17) },	/* GMAC1-AXI */
+	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
+	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
+	[RST_BUS_GPADC0]	= { 0x9ec, BIT(16) },
+	[RST_BUS_GPADC1]	= { 0x9ec, BIT(17) },
+	[RST_BUS_THS]		= { 0x9fc, BIT(16) },
+	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
+	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
+	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
+	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
+	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
+	[RST_BUS_EHCI1]		= { 0xa8c, BIT(21) },
+	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
+	[RST_BUS_3]		= { 0xa8c, BIT(25) },	/* BSP + register */
+	[RST_BUS_LRADC]		= { 0xa9c, BIT(16) },
+	[RST_BUS_PCIE_USB3]	= { 0xaac, BIT(16) },
+	[RST_BUS_DISPLAY0_TOP]	= { 0xabc, BIT(16) },
+	[RST_BUS_DISPLAY1_TOP]	= { 0xacc, BIT(16) },
+	[RST_BUS_HDMI_MAIN]	= { 0xb1c, BIT(16) },
+	[RST_BUS_HDMI_SUB]	= { 0xb1c, BIT(17) },
+	[RST_BUS_MIPI_DSI0]	= { 0xb4c, BIT(16) },
+	[RST_BUS_MIPI_DSI1]	= { 0xb4c, BIT(17) },
+	[RST_BUS_TCON_LCD0]	= { 0xb7c, BIT(16) },
+	[RST_BUS_TCON_LCD1]	= { 0xb7c, BIT(17) },
+	[RST_BUS_TCON_LCD2]	= { 0xb7c, BIT(18) },
+	[RST_BUS_TCON_TV0]	= { 0xb9c, BIT(16) },
+	[RST_BUS_TCON_TV1]	= { 0xb9c, BIT(17) },
+	[RST_BUS_LVDS0]		= { 0xbac, BIT(16) },
+	[RST_BUS_LVDS1]		= { 0xbac, BIT(17) },
+	[RST_BUS_EDP]		= { 0xbbc, BIT(16) },
+	[RST_BUS_VIDEO_OUT0]	= { 0xbcc, BIT(16) },
+	[RST_BUS_VIDEO_OUT1]	= { 0xbcc, BIT(17) },
+	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
+	[RST_BUS_CSI]		= { 0xc1c, BIT(16) },
+	[RST_BUS_ISP]		= { 0xc2c, BIT(16) },	/* BSP + register */
+};
+
 static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
 	.ccu_clks	= sun55i_a523_ccu_clks,
 	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_ccu_clks),
 
 	.hw_clks	= &sun55i_a523_hw_clks,
+
+	.resets		= sun55i_a523_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun55i_a523_ccu_resets),
 };
 
 static const u32 pll_regs[] = {
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:28:05 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:28:05 +0000
Subject: [PATCH v3 15/15] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-16-andre.przywara@arm.com>

The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
previous SoCs. For a change, the whole PRCM is documented in the A523
manual, including the system bus tree, so we can describe all those
clocks correctly based on that. There layout seems to be derived from
the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
have subtly changed.

Describe all the mod and gate clocks, including the three bus clocks
(R_AHB, R_APB0, and R_APB1).

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/Kconfig             |   5 +
 drivers/clk/sunxi-ng/Makefile            |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 248 +++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h |  14 ++
 4 files changed, 269 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 04efbda847cf9..5830a9d87bf25 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -57,6 +57,11 @@ config SUN55I_A523_CCU
 	default y
 	depends on ARM64 || COMPILE_TEST
 
+config SUN55I_A523_R_CCU
+	tristate "Support for the Allwinner A523/T527 PRCM CCU"
+	default y
+	depends on ARM64 || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	tristate "Support for the Allwinner A10/A20 CCU"
 	default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 01a887f7824bb..82e471036de69 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUN50I_H6_CCU)	+= sun50i-h6-ccu.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= sun50i-h6-r-ccu.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= sun50i-h616-ccu.o
 obj-$(CONFIG_SUN55I_A523_CCU)	+= sun55i-a523-ccu.o
+obj-$(CONFIG_SUN55I_A523_R_CCU)	+= sun55i-a523-r-ccu.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= sun4i-a10-ccu.o
 obj-$(CONFIG_SUN5I_CCU)		+= sun5i-ccu.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= sun6i-a31-ccu.o
@@ -60,6 +61,7 @@ sun50i-h6-ccu-y			+= ccu-sun50i-h6.o
 sun50i-h6-r-ccu-y		+= ccu-sun50i-h6-r.o
 sun50i-h616-ccu-y		+= ccu-sun50i-h616.o
 sun55i-a523-ccu-y		+= ccu-sun55i-a523.o
+sun55i-a523-r-ccu-y		+= ccu-sun55i-a523-r.o
 sun4i-a10-ccu-y			+= ccu-sun4i-a10.o
 sun5i-ccu-y			+= ccu-sun5i.o
 sun6i-a31-ccu-y			+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
new file mode 100644
index 0000000000000..b5464d8083c8a
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ *   Copyright (c) 2020 huangzhenwei at allwinnertech.com
+ *   Copyright (C) 2021 Samuel Holland <samuel at sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+
+#include "ccu-sun55i-a523-r.h"
+
+static const struct clk_parent_data r_ahb_apb_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .fw_name = "pll-periph" },
+	{ .fw_name = "pll-audio" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
+				 r_ahb_apb_parents, 0x000,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
+				 r_ahb_apb_parents, 0x00c,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
+				 r_ahb_apb_parents, 0x010,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
+				       r_ahb_apb_parents, 0x100,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				      0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
+				       r_ahb_apb_parents, 0x104,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				       0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
+				       r_ahb_apb_parents, 0x108,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				       0);
+
+static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
+			 0x11c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_twd_clk,	"bus-r-twd", &r_apb0_clk.common.hw,
+			 0x12c, BIT(0), 0);
+
+static const struct clk_parent_data r_pwmctrl_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
+				  r_pwmctrl_parents, 0x130,
+				  24, 2,	/* mux */
+				  BIT(31),
+				  0);
+static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
+			 &r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
+
+/* SPI clock is /M/N (same as new MMC?) */
+static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
+			 &r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
+			 &r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
+			 &r_ahb_clk.common.hw, 0x17c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart0_clk, "bus-r-uart0",
+			 &r_apb1_clk.common.hw, 0x18c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart1_clk, "bus-r-uart1",
+			 &r_apb1_clk.common.hw, 0x18c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c0_clk, "bus-r-i2c0",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c1_clk, "bus-r-i2c1",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c2_clk, "bus-r-i2c2",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(2), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu0_clk, "bus-r-ppu0",
+			 &r_apb0_clk.common.hw, 0x1ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu1_clk, "bus-r-ppu1",
+			 &r_apb0_clk.common.hw, 0x1ac, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpu_bist_clk, "bus-r-cpu-bist",
+			 &r_apb0_clk.common.hw, 0x1bc, BIT(0), 0);
+
+static const struct clk_parent_data r_ir_rx_parents[] = {
+	{ .fw_name = "losc" },
+	{ .fw_name = "hosc" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
+				      r_ir_rx_parents, 0x1c0,
+				      0, 5,	/* M */
+				      24, 2,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+static SUNXI_CCU_GATE_HW(bus_r_ir_rx_clk, "bus-r-ir-rx",
+			 &r_apb0_clk.common.hw, 0x1cc, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HW(bus_r_dma_clk, "bus-r-dma",
+			 &r_apb0_clk.common.hw, 0x1dc, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_rtc_clk, "bus-r-rtc",
+			 &r_apb0_clk.common.hw, 0x20c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpucfg_clk, "bus-r-cpucfg",
+			 &r_apb0_clk.common.hw, 0x22c, BIT(0), 0);
+
+static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
+	&r_ahb_clk.common,
+	&r_apb0_clk.common,
+	&r_apb1_clk.common,
+	&r_cpu_timer0.common,
+	&r_cpu_timer1.common,
+	&r_cpu_timer2.common,
+	&bus_r_timer_clk.common,
+	&bus_r_twd_clk.common,
+	&r_pwmctrl_clk.common,
+	&bus_r_pwmctrl_clk.common,
+	&bus_r_spi_clk.common,
+	&bus_r_spinlock_clk.common,
+	&bus_r_msgbox_clk.common,
+	&bus_r_uart0_clk.common,
+	&bus_r_uart1_clk.common,
+	&bus_r_i2c0_clk.common,
+	&bus_r_i2c1_clk.common,
+	&bus_r_i2c2_clk.common,
+	&bus_r_ppu0_clk.common,
+	&bus_r_ppu1_clk.common,
+	&bus_r_cpu_bist_clk.common,
+	&r_ir_rx_clk.common,
+	&bus_r_ir_rx_clk.common,
+	&bus_r_dma_clk.common,
+	&bus_r_rtc_clk.common,
+	&bus_r_cpucfg_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
+	.num	= CLK_NUMBER,
+	.hws	= {
+		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
+		[CLK_R_APB0]		= &r_apb0_clk.common.hw,
+		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
+		[CLK_R_TIMER0]		= &r_cpu_timer0.common.hw,
+		[CLK_R_TIMER1]		= &r_cpu_timer1.common.hw,
+		[CLK_R_TIMER2]		= &r_cpu_timer2.common.hw,
+		[CLK_BUS_R_TIMER]	= &bus_r_timer_clk.common.hw,
+		[CLK_BUS_R_TWD]		= &bus_r_twd_clk.common.hw,
+		[CLK_R_PWMCTRL]		= &r_pwmctrl_clk.common.hw,
+		[CLK_BUS_R_PWMCTRL]	= &bus_r_pwmctrl_clk.common.hw,
+		[CLK_BUS_R_SPI]		= &bus_r_spi_clk.common.hw,
+		[CLK_BUS_R_SPINLOCK]	= &bus_r_spinlock_clk.common.hw,
+		[CLK_BUS_R_MSGBOX]	= &bus_r_msgbox_clk.common.hw,
+		[CLK_BUS_R_UART0]	= &bus_r_uart0_clk.common.hw,
+		[CLK_BUS_R_UART1]	= &bus_r_uart1_clk.common.hw,
+		[CLK_BUS_R_I2C0]	= &bus_r_i2c0_clk.common.hw,
+		[CLK_BUS_R_I2C1]	= &bus_r_i2c1_clk.common.hw,
+		[CLK_BUS_R_I2C2]	= &bus_r_i2c2_clk.common.hw,
+		[CLK_BUS_R_PPU0]	= &bus_r_ppu0_clk.common.hw,
+		[CLK_BUS_R_PPU1]	= &bus_r_ppu1_clk.common.hw,
+		[CLK_BUS_R_CPU_BIST]	= &bus_r_cpu_bist_clk.common.hw,
+		[CLK_R_IR_RX]		= &r_ir_rx_clk.common.hw,
+		[CLK_BUS_R_IR_RX]	= &bus_r_ir_rx_clk.common.hw,
+		[CLK_BUS_R_DMA]		= &bus_r_dma_clk.common.hw,
+		[CLK_BUS_R_RTC]		= &bus_r_rtc_clk.common.hw,
+		[CLK_BUS_R_CPUCFG]	= &bus_r_cpucfg_clk.common.hw,
+	},
+};
+
+static struct ccu_reset_map sun55i_a523_r_ccu_resets[] = {
+	[RST_BUS_R_TIMER]	= { 0x11c, BIT(16) },
+	[RST_BUS_R_TWD]		= { 0x12c, BIT(16) },
+	[RST_BUS_R_PWMCTRL]	= { 0x13c, BIT(16) },
+	[RST_BUS_R_SPI]		= { 0x15c, BIT(16) },
+	[RST_BUS_R_SPINLOCK]	= { 0x16c, BIT(16) },
+	[RST_BUS_R_MSGBOX]	= { 0x17c, BIT(16) },
+	[RST_BUS_R_UART0]	= { 0x18c, BIT(16) },
+	[RST_BUS_R_UART1]	= { 0x18c, BIT(17) },
+	[RST_BUS_R_I2C0]	= { 0x19c, BIT(16) },
+	[RST_BUS_R_I2C1]	= { 0x19c, BIT(17) },
+	[RST_BUS_R_I2C2]	= { 0x19c, BIT(18) },
+	[RST_BUS_R_PPU1]	= { 0x1ac, BIT(17) },
+	[RST_BUS_R_IR_RX]	= { 0x1cc, BIT(16) },
+	[RST_BUS_R_RTC]		= { 0x20c, BIT(16) },
+	[RST_BUS_R_CPUCFG]	= { 0x22c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_r_ccu_desc = {
+	.ccu_clks	= sun55i_a523_r_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_r_ccu_clks),
+
+	.hw_clks	= &sun55i_a523_r_hw_clks,
+
+	.resets		= sun55i_a523_r_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun55i_a523_r_ccu_resets),
+};
+
+static int sun55i_a523_r_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_r_ccu_desc);
+}
+
+static const struct of_device_id sun55i_a523_r_ccu_ids[] = {
+	{ .compatible = "allwinner,sun55i-a523-r-ccu" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun55i_a523_r_ccu_ids);
+
+static struct platform_driver sun55i_a523_r_ccu_driver = {
+	.probe	= sun55i_a523_r_ccu_probe,
+	.driver	= {
+		.name			= "sun55i-a523-r-ccu",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sun55i_a523_r_ccu_ids,
+	},
+};
+module_platform_driver(sun55i_a523_r_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 PRCM CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
new file mode 100644
index 0000000000000..d50f46ac4f3fe
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_R_H
+#define _CCU_SUN55I_A523_R_H
+
+#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
+
+#define CLK_NUMBER	(CLK_BUS_R_CPUCFG + 1)
+
+#endif /* _CCU_SUN55I_A523_R_H */
-- 
2.46.3



From andy.yan at rock-chips.com  Mon Mar  3 17:31:04 2025
From: andy.yan at rock-chips.com (Andy Yan)
Date: Tue, 4 Mar 2025 09:31:04 +0800
Subject: [PATCH v2 2/2] drm/rockchip: lvds: Hide scary error messages on
 probe deferral
In-Reply-To: <20250301173547.710245-3-heiko@sntech.de>
References: <20250301173547.710245-1-heiko@sntech.de>
 <20250301173547.710245-3-heiko@sntech.de>
Message-ID: <61bf39de-3aae-46fb-b1d4-c9c7fd0df4a7@rock-chips.com>

Hi Heiko,


On 3/2/25 01:35, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner at cherry.de>
> 
> Commit 52d11c863ac9 ("drm/rockchip: lvds: do not print scary message when
> probing defer") already started hiding scary messages that are not relevant
> if the requested supply just returned EPROBE_DEFER, but there are more
> possible sources - like the phy.
> 
> So modernize the whole logging in the probe path by replacing the
> remaining deprecated DRM_DEV_ERROR with appropriate dev_err(_probe)
> and drm_err calls.
> 
> The distinction here is that all messages talking about mishaps of the
> lvds element use dev_err(_probe) while messages caused by interaction
> with the main Rockchip drm-device use drm_err.
> 
> Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>

   Reviewed-by: Andy Yan <andy.yan at rock-chips.com>

Thanks.
> ---
>   drivers/gpu/drm/rockchip/rockchip_lvds.c | 61 ++++++++++--------------
>   1 file changed, 26 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index ecfae8d5da89..d8b2007123fa 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -453,10 +453,9 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
>   		return PTR_ERR(lvds->regs);
>   
>   	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
> -	if (IS_ERR(lvds->pclk)) {
> -		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
> -		return PTR_ERR(lvds->pclk);
> -	}
> +	if (IS_ERR(lvds->pclk))
> +		return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk),
> +				     "could not get or prepare pclk_lvds\n");
>   
>   	lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
>   				  GFP_KERNEL);
> @@ -465,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
>   
>   	lvds->pins->p = devm_pinctrl_get(lvds->dev);
>   	if (IS_ERR(lvds->pins->p)) {
> -		DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
> +		dev_err(lvds->dev, "no pinctrl handle\n");
>   		devm_kfree(lvds->dev, lvds->pins);
>   		lvds->pins = NULL;
>   	} else {
>   		lvds->pins->default_state =
>   			pinctrl_lookup_state(lvds->pins->p, "lcdc");
>   		if (IS_ERR(lvds->pins->default_state)) {
> -			DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
> +			dev_err(lvds->dev, "no default pinctrl state\n");
>   			devm_kfree(lvds->dev, lvds->pins);
>   			lvds->pins = NULL;
>   		}
> @@ -547,11 +546,10 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	lvds->drm_dev = drm_dev;
>   	port = of_graph_get_port_by_id(dev->of_node, 1);
> -	if (!port) {
> -		DRM_DEV_ERROR(dev,
> -			      "can't found port point, please init lvds panel port!\n");
> -		return -EINVAL;
> -	}
> +	if (!port)
> +		return dev_err_probe(dev, -EINVAL,
> +				     "can't found port point, please init lvds panel port!\n");
> +
>   	for_each_child_of_node(port, endpoint) {
>   		child_count++;
>   		of_property_read_u32(endpoint, "reg", &endpoint_id);
> @@ -563,8 +561,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		}
>   	}
>   	if (!child_count) {
> -		DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
> -		ret = -EINVAL;
> +		ret = dev_err_probe(dev, -EINVAL, "lvds port does not have any children\n");
>   		goto err_put_port;
>   	} else if (ret) {
>   		dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
> @@ -581,8 +578,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		lvds->output = rockchip_lvds_name_to_output(name);
>   
>   	if (lvds->output < 0) {
> -		DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name);
> -		ret = lvds->output;
> +		ret = dev_err_probe(dev, lvds->output, "invalid output type [%s]\n", name);
>   		goto err_put_remote;
>   	}
>   
> @@ -593,7 +589,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		lvds->format = rockchip_lvds_name_to_format(name);
>   
>   	if (lvds->format < 0) {
> -		DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
> +		dev_err(dev, "invalid data-mapping format [%s]\n", name);
>   		ret = lvds->format;
>   		goto err_put_remote;
>   	}
> @@ -604,8 +600,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_LVDS);
>   	if (ret < 0) {
> -		DRM_DEV_ERROR(drm_dev->dev,
> -			      "failed to initialize encoder: %d\n", ret);
> +		drm_err(drm_dev,
> +			"failed to initialize encoder: %d\n", ret);
>   		goto err_put_remote;
>   	}
>   
> @@ -618,8 +614,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   					 &rockchip_lvds_connector_funcs,
>   					 DRM_MODE_CONNECTOR_LVDS);
>   		if (ret < 0) {
> -			DRM_DEV_ERROR(drm_dev->dev,
> -				      "failed to initialize connector: %d\n", ret);
> +			drm_err(drm_dev,
> +				"failed to initialize connector: %d\n", ret);
>   			goto err_free_encoder;
>   		}
>   
> @@ -633,9 +629,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   		connector = drm_bridge_connector_init(lvds->drm_dev, encoder);
>   		if (IS_ERR(connector)) {
> -			DRM_DEV_ERROR(drm_dev->dev,
> -				      "failed to initialize bridge connector: %pe\n",
> -				      connector);
> +			drm_err(drm_dev,
> +				"failed to initialize bridge connector: %pe\n",
> +				connector);
>   			ret = PTR_ERR(connector);
>   			goto err_free_encoder;
>   		}
> @@ -643,8 +639,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	ret = drm_connector_attach_encoder(connector, encoder);
>   	if (ret < 0) {
> -		DRM_DEV_ERROR(drm_dev->dev,
> -			      "failed to attach encoder: %d\n", ret);
> +		drm_err(drm_dev, "failed to attach encoder: %d\n", ret);
>   		goto err_free_connector;
>   	}
>   
> @@ -706,24 +701,20 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
>   
>   	lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>   						    "rockchip,grf");
> -	if (IS_ERR(lvds->grf)) {
> -		DRM_DEV_ERROR(dev, "missing rockchip,grf property\n");
> -		return PTR_ERR(lvds->grf);
> -	}
> +	if (IS_ERR(lvds->grf))
> +		return dev_err_probe(dev, PTR_ERR(lvds->grf), "missing rockchip,grf property\n");
>   
>   	ret = lvds->soc_data->probe(pdev, lvds);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Platform initialization failed\n");
> -		return ret;
> -	}
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Platform initialization failed\n");
>   
>   	dev_set_drvdata(dev, lvds);
>   
>   	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
>   	if (ret < 0)
> -		DRM_DEV_ERROR(dev, "failed to add component\n");
> +		return dev_err_probe(dev, ret, "failed to add component\n");
>   
> -	return ret;
> +	return 0;
>   }
>   
>   static void rockchip_lvds_remove(struct platform_device *pdev)


From do-not-reply-us at mybundlepay.com  Mon Mar  3 12:32:28 2025
From: do-not-reply-us at mybundlepay.com (Benjamin Elliot)
Date: 03 Mar 2025 20:32:28 +0000
Subject: INVESTMENT UPDATE
Message-ID: <20250303203228.9E3C83D367A87F76@mybundlepay.com>

Hello Dear,

I am  Benjamin Elliot. I am a Financial Consultant. My company 
represent the investment portfolio of a consortium of investors 
willing and readily available to fund any sustainable project 
that can yield a reasonable return on investment. What we do is 
that, we broker discreet financial services for high net 
individuals/Companies. We connect you to legitimate portfolio 
financiers that are willing and readily available to divert funds 
into sustainable and profitable project or business with a 
reasonable ROI. Do you have any ongoing project or a startup? 
Please contact me if you are looking for funds to invest in or 
expand your project or business. We would be happy to work with 
you.

Look forward to your response.

Best Regards,
Benjamin Elliot - MD
PAN Financial Consultant
Anna Blamansingel 72, Amsterdam 1102ST, Netherlands.


From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:01 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:01 +0200
Subject: [PATCH v4 02/12] phy: hdmi: Add color depth configuration
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-2-8657847c13f7@collabora.com>

Extend the HDMI configuration options to allow managing bits per color
channel.  This is required by some PHY drivers such as
rockchip-samsung-hdptx.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
index 6a696922bc7f29af63d88646701b2c0fcee5c885..f0ec963c6e84f1b7728acafc824dff191c6b873d 100644
--- a/include/linux/phy/phy-hdmi.h
+++ b/include/linux/phy/phy-hdmi.h
@@ -9,11 +9,13 @@
 /**
  * struct phy_configure_opts_hdmi - HDMI configuration set
  * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ * @bpc: Bits per color channel.
  *
  * This structure is used to represent the configuration state of a HDMI phy.
  */
 struct phy_configure_opts_hdmi {
 	unsigned long long tmds_char_rate;
+	unsigned int bpc;
 };
 
 #endif /* __PHY_HDMI_H_ */

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:43:59 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:43:59 +0200
Subject: [PATCH v4 00/12] phy: rockchip: samsung-hdptx: Support high color
 depth management
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>

This series relies on the new HDMI PHY configuration options [1] (patch
included here for convenience) to provide high color depth management
for rockchip-samsung-hdptx, and to introduce a proper solution to setup
the TMDS character rate on this PHY.

[1] https://lore.kernel.org/lkml/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com/

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
Changes in v4:
- Added patches to drop unnecessary phy_cfg & cfgs driver data
- Embedded struct phy_configure_opts_hdmi in driver data (Dmitry)
- Added new patch to provide config params validation support
- Provided a patch to restrict altering TMDS char rate via CCF (Dmitry)
- Made a bunch of small tweaks here and there
- Link to v3: https://lore.kernel.org/r/20250223-phy-sam-hdptx-bpc-v3-0-66a5c8e68327 at collabora.com

Changes in v3:
- Rebased series onto next-20250221 and fixed several conflicts due to
  the recently introduced eDP support
- Link to v2: https://lore.kernel.org/r/20241212-phy-sam-hdptx-bpc-v2-0-57e672c7c7c4 at collabora.com

Changes in v2:
- Added new patches providing a bug fix and several driver cleanups and
  improvements
- Link to v1: https://lore.kernel.org/r/20241207-phy-sam-hdptx-bpc-v1-0-03c2e4d6d797 at collabora.com

---
Cristian Ciocaltea (11):
      phy: hdmi: Add color depth configuration
      phy: rockchip: samsung-hdptx: Fix clock ratio setup
      phy: rockchip: samsung-hdptx: Drop unused struct lcpll_config
      phy: rockchip: samsung-hdptx: Drop unused phy_cfg driver data
      phy: rockchip: samsung-hdptx: Drop superfluous cfgs driver data
      phy: rockchip: samsung-hdptx: Setup TMDS char rate via phy_configure_opts_hdmi
      phy: rockchip: samsung-hdptx: Provide config params validation support
      phy: rockchip: samsung-hdptx: Restrict altering TMDS char rate via CCF
      phy: rockchip: samsung-hdptx: Add high color depth management
      phy: rockchip: samsung-hdptx: Optimize internal rate handling
      phy: rockchip: samsung-hdptx: Avoid Hz-hHz unit conversion overhead

Sandor Yu (1):
      phy: Add HDMI configuration options

 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 289 +++++++++++++---------
 include/linux/phy/phy-hdmi.h                      |  21 ++
 include/linux/phy/phy.h                           |   7 +-
 3 files changed, 200 insertions(+), 117 deletions(-)
---
base-commit: cd3215bbcb9d4321def93fea6cfad4d5b42b9d1d
change-id: 20241206-phy-sam-hdptx-bpc-3b05c6276fd7



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:00 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:00 +0200
Subject: [PATCH v4 01/12] phy: Add HDMI configuration options
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-1-8657847c13f7@collabora.com>

From: Sandor Yu <Sandor.yu at nxp.com>

Allow HDMI PHYs to be configured through the generic
functions through a custom structure added to the generic union.

The parameters added here are based on HDMI PHY
implementation practices.  The current set of parameters
should cover the potential users.

Signed-off-by: Sandor Yu <Sandor.yu at nxp.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Acked-by: Vinod Koul <vkoul at kernel.org>
Link: https://lore.kernel.org/r/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 19 +++++++++++++++++++
 include/linux/phy/phy.h      |  7 ++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a696922bc7f29af63d88646701b2c0fcee5c885
--- /dev/null
+++ b/include/linux/phy/phy-hdmi.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2022,2024 NXP
+ */
+
+#ifndef __PHY_HDMI_H_
+#define __PHY_HDMI_H_
+
+/**
+ * struct phy_configure_opts_hdmi - HDMI configuration set
+ * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ *
+ * This structure is used to represent the configuration state of a HDMI phy.
+ */
+struct phy_configure_opts_hdmi {
+	unsigned long long tmds_char_rate;
+};
+
+#endif /* __PHY_HDMI_H_ */
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 03cd5bae92d3f189d739c453fe4c160dd2a5063e..4ac486b101fe4023b8f2a84e907e65a0ff0a5ede 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <linux/phy/phy-dp.h>
+#include <linux/phy/phy-hdmi.h>
 #include <linux/phy/phy-lvds.h>
 #include <linux/phy/phy-mipi-dphy.h>
 
@@ -42,7 +43,8 @@ enum phy_mode {
 	PHY_MODE_MIPI_DPHY,
 	PHY_MODE_SATA,
 	PHY_MODE_LVDS,
-	PHY_MODE_DP
+	PHY_MODE_DP,
+	PHY_MODE_HDMI,
 };
 
 enum phy_media {
@@ -60,11 +62,14 @@ enum phy_media {
  *		the DisplayPort protocol.
  * @lvds:	Configuration set applicable for phys supporting
  *		the LVDS phy mode.
+ * @hdmi:	Configuration set applicable for phys supporting
+ *		the HDMI phy mode.
  */
 union phy_configure_opts {
 	struct phy_configure_opts_mipi_dphy	mipi_dphy;
 	struct phy_configure_opts_dp		dp;
 	struct phy_configure_opts_lvds		lvds;
+	struct phy_configure_opts_hdmi		hdmi;
 };
 
 /**

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:02 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:02 +0200
Subject: [PATCH v4 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>

The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
and not before.

While at it, introduce a define for this rate limit constant.

Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -320,6 +320,7 @@
 #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
 #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
 
+#define HDMI14_MAX_RATE			340000000
 #define HDMI20_MAX_RATE			600000000
 
 enum dp_link_rate {
@@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate >= 3400000) {
+	if (rate > HDMI14_MAX_RATE / 100) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:03 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:03 +0200
Subject: [PATCH v4 04/12] phy: rockchip: samsung-hdptx: Drop unused struct
 lcpll_config
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-4-8657847c13f7@collabora.com>

This is just a leftover from downstream support for HDMI 2.1.
Remove the unused struct for now.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -----------------------
 1 file changed, 31 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index cf2c3a46604cb9d8c26fe5ec8346904e0b62848f..f9b5c96d6c789e435657e224032d35b5a6950945 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -329,37 +329,6 @@ enum dp_link_rate {
 	DP_BW_HBR2,
 };
 
-struct lcpll_config {
-	u32 bit_rate;
-	u8 lcvco_mode_en;
-	u8 pi_en;
-	u8 clk_en_100m;
-	u8 pms_mdiv;
-	u8 pms_mdiv_afc;
-	u8 pms_pdiv;
-	u8 pms_refdiv;
-	u8 pms_sdiv;
-	u8 pi_cdiv_rstn;
-	u8 pi_cdiv_sel;
-	u8 sdm_en;
-	u8 sdm_rstn;
-	u8 sdc_frac_en;
-	u8 sdc_rstn;
-	u8 sdm_deno;
-	u8 sdm_num_sign;
-	u8 sdm_num;
-	u8 sdc_n;
-	u8 sdc_n2;
-	u8 sdc_num;
-	u8 sdc_deno;
-	u8 sdc_ndiv_rstn;
-	u8 ssc_en;
-	u8 ssc_fm_dev;
-	u8 ssc_fm_freq;
-	u8 ssc_clk_div_sel;
-	u8 cd_tx_ser_rate_sel;
-};
-
 struct ropll_config {
 	u32 bit_rate;
 	u8 pms_mdiv;

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:05 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:05 +0200
Subject: [PATCH v4 06/12] phy: rockchip: samsung-hdptx: Drop superfluous
 cfgs driver data
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-6-8657847c13f7@collabora.com>

The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
but it is only used during probe() in order to setup ->phy_id.

Use a probe() local variable to store device match data and remove the
now unnecessary member from struct rk_hdptx_phy.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 06644c3d98d3f8b697fc704704df5acdd3c85bad..2bf525514c1991a1299265d12e1e85f66333c604 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -392,10 +392,7 @@ struct rk_hdptx_phy {
 	struct regmap *regmap;
 	struct regmap *grf;
 
-	/* PHY const config */
-	const struct rk_hdptx_phy_cfg *cfgs;
 	int phy_id;
-
 	struct phy *phy;
 	struct clk_bulk_data *clks;
 	int nr_clks;
@@ -1892,6 +1889,7 @@ static int rk_hdptx_phy_runtime_resume(struct device *dev)
 
 static int rk_hdptx_phy_probe(struct platform_device *pdev)
 {
+	const struct rk_hdptx_phy_cfg *cfgs;
 	struct phy_provider *phy_provider;
 	struct device *dev = &pdev->dev;
 	struct rk_hdptx_phy *hdptx;
@@ -1910,14 +1908,14 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(regs),
 				     "Failed to ioremap resource\n");
 
-	hdptx->cfgs = device_get_match_data(dev);
-	if (!hdptx->cfgs)
+	cfgs = device_get_match_data(dev);
+	if (!cfgs)
 		return dev_err_probe(dev, -EINVAL, "missing match data\n");
 
 	/* find the phy-id from the io address */
 	hdptx->phy_id = -ENODEV;
-	for (id = 0; id < hdptx->cfgs->num_phys; id++) {
-		if (res->start == hdptx->cfgs->phy_ids[id]) {
+	for (id = 0; id < cfgs->num_phys; id++) {
+		if (res->start == cfgs->phy_ids[id]) {
 			hdptx->phy_id = id;
 			break;
 		}

-- 
2.48.1



From andy.yan at rock-chips.com  Mon Mar  3 17:29:33 2025
From: andy.yan at rock-chips.com (Andy Yan)
Date: Tue, 4 Mar 2025 09:29:33 +0800
Subject: [PATCH v2 1/2] drm/rockchip: lvds: move pclk preparation in with
 clk_get
In-Reply-To: <20250301173547.710245-2-heiko@sntech.de>
References: <20250301173547.710245-1-heiko@sntech.de>
 <20250301173547.710245-2-heiko@sntech.de>
Message-ID: <23e1ecc4-3386-426a-aa54-4d4c082cbf8a@rock-chips.com>

Hi Heiko,


On 3/2/25 01:35, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner at cherry.de>
> 
> The LVDS block needs a separate pclk only on some socs, so currently
> requests and prepares it in the soc-specific probe function, but common
> code is required to unprepare it in the error path or on driver remove.
> 
> While this works because clk_unprepare just does nothing if clk is NULL,
> this mismatch of who is responsible still is not very nice.
> The clock-framework already has a helper for clk-get-and-prepare even
> with devres support in devm_clk_get_prepared().
> 
> This will get and prepare the clock and also unprepare it on driver
> removal, saving the driver from having to handle it "manually".
> 
> Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>
> Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>

   Reviewed-by: Andy Yan <andy.yan at rock-chips.com>

> ---
>   drivers/gpu/drm/rockchip/rockchip_lvds.c | 19 +++----------------
>   1 file changed, 3 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index 385cf6881504..ecfae8d5da89 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -448,15 +448,13 @@ struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs = {
>   static int rk3288_lvds_probe(struct platform_device *pdev,
>   			     struct rockchip_lvds *lvds)
>   {
> -	int ret;
> -
>   	lvds->regs = devm_platform_ioremap_resource(pdev, 0);
>   	if (IS_ERR(lvds->regs))
>   		return PTR_ERR(lvds->regs);
>   
> -	lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
> +	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
>   	if (IS_ERR(lvds->pclk)) {
> -		DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
> +		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
>   		return PTR_ERR(lvds->pclk);
>   	}
>   
> @@ -480,12 +478,6 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
>   		}
>   	}
>   
> -	ret = clk_prepare(lvds->pclk);
> -	if (ret < 0) {
> -		DRM_DEV_ERROR(lvds->dev, "failed to prepare pclk_lvds\n");
> -		return ret;
> -	}
> -
>   	return 0;
>   }
>   
> @@ -728,20 +720,15 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
>   	dev_set_drvdata(dev, lvds);
>   
>   	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
> -	if (ret < 0) {
> +	if (ret < 0)
>   		DRM_DEV_ERROR(dev, "failed to add component\n");
> -		clk_unprepare(lvds->pclk);
> -	}
>   
>   	return ret;
>   }
>   
>   static void rockchip_lvds_remove(struct platform_device *pdev)
>   {
> -	struct rockchip_lvds *lvds = platform_get_drvdata(pdev);
> -
>   	component_del(&pdev->dev, &rockchip_lvds_component_ops);
> -	clk_unprepare(lvds->pclk);
>   }
>   
>   struct platform_driver rockchip_lvds_driver = {


From andre.przywara at arm.com  Mon Mar  3 17:27:51 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:51 +0000
Subject: [PATCH v3 01/15] clk: sunxi-ng: mp: introduce dual-divider clock
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-2-andre.przywara@arm.com>

The Allwinner A523 SoC introduces some new MP-style mod clock, where the
second "P" divider is an actual numerical divider value, and not the
numbers of bits to shift (1..32 instead of 1,2,4,8).
The rest of the clock is the same as the existing MP clock, so enhance the
existing code to accommodate for this.

Introduce the new CCU feature bit CCU_FEATURE_DUAL_DIV to mark an MP
clock as having two dividers, and change the dividing and encoding code
to differentiate the two cases.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/clk/sunxi-ng/ccu_common.h |  1 +
 drivers/clk/sunxi-ng/ccu_mp.c     | 51 +++++++++++++++++++++++++------
 2 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index dd330426a6e5f..50fd268329671 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -19,6 +19,7 @@
 #define CCU_FEATURE_SIGMA_DELTA_MOD	BIT(7)
 #define CCU_FEATURE_KEY_FIELD		BIT(8)
 #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
+#define CCU_FEATURE_DUAL_DIV		BIT(10)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 2bb8987ddcc20..354c981943b6f 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -10,15 +10,23 @@
 #include "ccu_gate.h"
 #include "ccu_mp.h"
 
+static unsigned int next_div(unsigned int div, bool shift)
+{
+	if (shift)
+		return div << 1;
+	return div + 1;
+}
+
 static unsigned long ccu_mp_find_best(unsigned long parent, unsigned long rate,
 				      unsigned int max_m, unsigned int max_p,
+				      bool shift,
 				      unsigned int *m, unsigned int *p)
 {
 	unsigned long best_rate = 0;
 	unsigned int best_m = 0, best_p = 0;
 	unsigned int _m, _p;
 
-	for (_p = 1; _p <= max_p; _p <<= 1) {
+	for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
 		for (_m = 1; _m <= max_m; _m++) {
 			unsigned long tmp_rate = parent / _p / _m;
 
@@ -43,7 +51,8 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
 						      unsigned long *parent,
 						      unsigned long rate,
 						      unsigned int max_m,
-						      unsigned int max_p)
+						      unsigned int max_p,
+						      bool shift)
 {
 	unsigned long parent_rate_saved;
 	unsigned long parent_rate, now;
@@ -60,7 +69,7 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
 	maxdiv = max_m * max_p;
 	maxdiv = min(ULONG_MAX / rate, maxdiv);
 
-	for (_p = 1; _p <= max_p; _p <<= 1) {
+	for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
 		for (_m = 1; _m <= max_m; _m++) {
 			div = _m * _p;
 
@@ -103,18 +112,26 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
 	struct ccu_mp *cmp = data;
 	unsigned int max_m, max_p;
 	unsigned int m, p;
+	bool shift = true;
 
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate *= cmp->fixed_post_div;
 
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		shift = false;
+
 	max_m = cmp->m.max ?: 1 << cmp->m.width;
-	max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	if (shift)
+		max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	else
+		max_p = cmp->p.max ?: 1 << cmp->p.width;
 
 	if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
-		rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
+		rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, shift,
+					&m, &p);
 	} else {
 		rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate,
-							max_m, max_p);
+							max_m, max_p, shift);
 	}
 
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
@@ -167,7 +184,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
 	p = reg >> cmp->p.shift;
 	p &= (1 << cmp->p.width) - 1;
 
-	rate = (parent_rate >> p) / m;
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		rate = (parent_rate / p) / m;
+	else
+		rate = (parent_rate >> p) / m;
+
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate /= cmp->fixed_post_div;
 
@@ -190,20 +211,27 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags;
 	unsigned int max_m, max_p;
 	unsigned int m, p;
+	bool shift = true;
 	u32 reg;
 
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		shift = false;
+
 	/* Adjust parent_rate according to pre-dividers */
 	parent_rate = ccu_mux_helper_apply_prediv(&cmp->common, &cmp->mux, -1,
 						  parent_rate);
 
 	max_m = cmp->m.max ?: 1 << cmp->m.width;
-	max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	if (shift)
+		max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	else
+		max_p = cmp->p.max ?: 1 << cmp->p.width;
 
 	/* Adjust target rate according to post-dividers */
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate = rate * cmp->fixed_post_div;
 
-	ccu_mp_find_best(parent_rate, rate, max_m, max_p, &m, &p);
+	ccu_mp_find_best(parent_rate, rate, max_m, max_p, shift, &m, &p);
 
 	spin_lock_irqsave(cmp->common.lock, flags);
 
@@ -211,7 +239,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
 	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
 	reg |= (m - cmp->m.offset) << cmp->m.shift;
-	reg |= ilog2(p) << cmp->p.shift;
+	if (shift)
+		reg |= ilog2(p) << cmp->p.shift;
+	else
+		reg |= (p - cmp->p.offset) << cmp->p.shift;
 
 	writel(reg, cmp->common.base + cmp->common.reg);
 
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:50 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:50 +0000
Subject: [PATCH v3 00/15] clk: sunxi-ng: add A523 clock support
Message-ID: <20250304012805.28594-1-andre.przywara@arm.com>

Hi,

this is the third drop of the series introducing basic clock support for
the Allwinner A523 family of SoCs, comprising A523, A527, T527, H728. [1]
This fixes the issues Jernej found in his extensive and gratefully
received review, many thanks for that, also to the other reviewers! 
Those changes affect only details, but the rework caused more changes:
the clock definition helper macros got reworked, and the binding turned
out to be wrong, as it ignored the change in the source clock names
(instead just accommodated their changed number). Shoehorning the
differing names into the existing binding document turned out to be
quite hard to follow, so I moved that into a separate yaml file.
For a more detailed changelog, see below.

*************
Please note that the clock numbers changed compared to v1 and v2, so DTs
from that era cannot be used anymore with this driver: you have to update
the DTB. Just copying the binding header and recompiling the DTB should do
the trick, since the symbols stayed mostly the same, at least as far they
are used in the basic DTs we use today.
*************

The SoCs contain *four* CCU components, aside from the usual main clock
device and the PRCM clock (in the always-on-domain), there is an MCU
clock and a CPU clock. This series just adds support for the first two,
the other two don't seem to be required for the basic functionality.

The clock tree of each SoC has always been individual, even though the
main clock *types* mostly remain the same. This time we see three slight
variations: There is an MP clock without the P (shift) part, there is one
with two dividers instead of one divider and one shift field, and certain
clocks require an "update" bit to be set to apply any changes.
The first three patches add support for these new clock types.

Patch 04 and 05 add the DT binding description for the two CCUs, along
with all the clock numbers already defined in the binding headers.
Since the main CCU is massive, and contains a lot of detail, I decided
to split this driver up into 9 patches, simply to help review. I tried
to group them somewhat logically, although this is rather arbitrary, and
just to make each individual patch smaller. I am happy to squash them
all back into one patch once they have been reviewed, for the final
merge. The PRCM CCU is comparably small, so I kept this in one patch.

Interestingly the Allwinner BSP has switched to using the existing sunxi
CCU framework for modelling the clocks (they had their own way before), so
we could theoretically use their code. However when I started working on
this more than a year ago, their files had a GPL-3.0-only license header,
which, according to my research, makes them incompatible for mainline
inclusion. I thus started from "scratch" (adjusting the D1 driver, really).
Meanwhile they seem to have changed the license, and a quick comparison
turned up some differences, some of which seem to be bugs on their, some
on my side, probably. I hope having such a "reference" helps the mainline
code quality, as people can help the review by comparing code.

Given the level of detail required in CCU drivers, I am certain there are
still some bugs in there, also many things that can be improved. But after
starring and editing this for weeks, I feel like it's time for the
community to have a look, so please help with the review, and also test.

Based on v6.14-rc1.

Cheers,
Andre

[1] https://linux-sunxi.org/A523#Family_of_sun55iw3

Changelog v2 .. v3:
- rename PLL_DDR0 to PLL_DDR
- move bogus macro definition from PLL patch to an earlier patch
- adding CLK_SET_RATE_PARENT flags where needed (GPU, eDP, ...)
- remove CLK_SET_RATE_PARENT from clocks with only fixed parents
- add support for clocks with the "update" bit (BIT(27))
- flags IOMMU, MBUS and DRAM clocks as needing "update" bit
- remove leftover comment about missing mux
- fix TCON_TV parent list
- add TCON_LCD2 clock
- export PLL_GPU
- describe MBUS clock properly (was copy&pasted wrongly from D1)
- change MMC clocks to use better macro
- mark SPI and CSI clocks as being dual-divider clocks
- fix wrong DSP parent clock (480 instead of 400 MHz)
- properly implement fanout clocks (describe both dividers)
- fix MBUS gate clocks and add two new ones
- rename dpss clock to display0 and add display1 clocks
- drop non-existing bus_dsp_cfg_clk
- mark r_timer clocks as having no divider
- fix r_pwm mux width
- move DT bindings into separate yaml file
- describe different source clock sets correctly
- add review tags
- remove Chen-Yu's and Conor's tags from changed patches

Changelog v1 .. v2:
- rebase onto v6.14-rc1
- split main CCU definition patch into 9 smaller patches
- rename RST_BUS_VO1_TCONLCD0 to RST_BUS_TCON_LCD2
- insert CLK_PLL_VIDEO3_xx clocks
- add clock for 2nd EMAC
- fix ISP clock definition
- remove BSP comments from clocks now documented in the T527 manual
- add Conor's binding ACKs (with thanks!)

Andre Przywara (15):
  clk: sunxi-ng: mp: introduce dual-divider clock
  clk: sunxi-ng: mp: provide wrappers for setting feature flags
  clk: sunxi-ng: Add support for update bit
  dt-bindings: clk: sunxi-ng: document Allwinner A523 CCU
  dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU
  clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
  clk: sunxi-ng: a523: Add support for bus clocks
  clk: sunxi-ng: a523: add video mod clocks
  clk: sunxi-ng: a523: add system mod clocks
  clk: sunxi-ng: a523: add interface mod clocks
  clk: sunxi-ng: a523: add USB mod clocks
  clk: sunxi-ng: a523: remaining mod clocks
  clk: sunxi-ng: a523: add bus clock gates
  clk: sunxi-ng: a523: add reset lines
  clk: sunxi-ng: add support for the A523/T527 PRCM CCU

 .../clock/allwinner,sun55i-a523-ccu.yaml      |   96 +
 drivers/clk/sunxi-ng/Kconfig                  |   10 +
 drivers/clk/sunxi-ng/Makefile                 |    4 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c      |  248 +++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h      |   14 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c        | 1685 +++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523.h        |   14 +
 drivers/clk/sunxi-ng/ccu_common.h             |    5 +
 drivers/clk/sunxi-ng/ccu_div.c                |    2 +
 drivers/clk/sunxi-ng/ccu_gate.c               |    4 +
 drivers/clk/sunxi-ng/ccu_mp.c                 |   51 +-
 drivers/clk/sunxi-ng/ccu_mp.h                 |   58 +-
 drivers/clk/sunxi-ng/ccu_mux.c                |    2 +
 include/dt-bindings/clock/sun55i-a523-ccu.h   |  189 ++
 include/dt-bindings/clock/sun55i-a523-r-ccu.h |   37 +
 include/dt-bindings/reset/sun55i-a523-ccu.h   |   88 +
 include/dt-bindings/reset/sun55i-a523-r-ccu.h |   25 +
 17 files changed, 2517 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h

-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:52 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:52 +0000
Subject: [PATCH v3 02/15] clk: sunxi-ng: mp: provide wrappers for setting feature flags
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-3-andre.przywara@arm.com>

So far our sunxi clock instantiation macros set the required clock
features depending on the clock type, but the new "dual divider MP
clock" requires us to pass that piece of information in by the user.

Add new wrapper macros that allow to specify a "features" field, to
allow marking those dual-divider clocks accordingly. Also add two
convenience macros that deal with the most common cases.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu_mp.h | 58 ++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index 6e50f3728fb5f..b35aeec70484d 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -82,11 +82,35 @@ struct ccu_mp {
 				   _muxshift, _muxwidth,		\
 				   0, _flags)
 
-#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
-					_mshift, _mwidth,		\
-					_pshift, _pwidth,		\
-					_muxshift, _muxwidth,		\
-					_gate, _flags)			\
+#define SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(_struct, _name, _parents, _reg, \
+					      _mshift, _mwidth,		\
+					      _pshift, _pwidth,		\
+					      _muxshift, _muxwidth,	\
+					      _gate, _postdiv,		\
+					      _flags)			\
+	struct ccu_mp _struct = {					\
+		.enable	= _gate,					\
+		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
+		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
+		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
+		.fixed_post_div = _postdiv,				\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_FIXED_POSTDIV |	\
+						CCU_FEATURE_DUAL_DIV,	\
+			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
+								   _parents, \
+								   &ccu_mp_ops, \
+								   _flags), \
+		}							\
+	}
+
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
+					     _mshift, _mwidth,		\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _features,		\
+					     _flags)			\
 	struct ccu_mp _struct = {					\
 		.enable	= _gate,					\
 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
@@ -94,6 +118,7 @@ struct ccu_mp {
 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
 		.common	= {						\
 			.reg		= _reg,				\
+			.features	= _features,			\
 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
 								   _parents, \
 								   &ccu_mp_ops, \
@@ -101,6 +126,29 @@ struct ccu_mp {
 		}							\
 	}
 
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+					_mshift, _mwidth,		\
+					_pshift, _pwidth,		\
+					_muxshift, _muxwidth,		\
+					_gate, _flags)			\
+	SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents,	\
+					     _reg, _mshift, _mwidth,	\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _flags, 0)
+
+#define SUNXI_CCU_DUALDIV_MUX_GATE(_struct, _name, _parents, _reg,	\
+				   _mshift, _mwidth,			\
+				   _pshift, _pwidth,			\
+				   _muxshift, _muxwidth,		\
+				   _gate, _flags)			\
+	SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents,	\
+					     _reg, _mshift, _mwidth,	\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _flags,		\
+					     CCU_FEATURE_DUAL_DIV)
+
 #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg,	\
 				   _mshift, _mwidth,			\
 				   _pshift, _pwidth,			\
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:54 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:54 +0000
Subject: [PATCH v3 04/15] dt-bindings: clk: sunxi-ng: document Allwinner A523 CCU
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-5-andre.przywara@arm.com>

The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
the main CCU.

The source clock list differs in some annoying details, and folding this
into the existing Allwinner CCU clock binding document gets quite
unwieldy, so create a new document for these CCUs.
Add the new compatible string, along with the required input clock
lists. This conditionally describes the input clock list, to make for
an easier patch adding the other CCUs.

Also add the DT binding headers, listing all the clocks with their ID
numbers.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../clock/allwinner,sun55i-a523-ccu.yaml      |  77 +++++++
 include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
 include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
 3 files changed, 354 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
 create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
new file mode 100644
index 0000000000000..2eacaeaeabac7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A523 Clock Control Unit
+
+maintainers:
+  - Andre Przywara <andre.przywara at arm.com>
+
+properties:
+  "#clock-cells":
+    const: 1
+
+  "#reset-cells":
+    const: 1
+
+  compatible:
+    enum:
+      - allwinner,sun55i-a523-ccu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 4
+    maxItems: 4
+
+  clock-names:
+    minItems: 4
+    maxItems: 4
+
+required:
+  - "#clock-cells"
+  - "#reset-cells"
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+
+if:
+  properties:
+    compatible:
+      enum:
+        - allwinner,sun55i-a523-ccu
+
+then:
+  properties:
+    clocks:
+      items:
+        - description: High Frequency Oscillator (usually at 24MHz)
+        - description: Low Frequency Oscillator (usually at 32kHz)
+        - description: Internal Oscillator
+        - description: Low Frequency Oscillator fanout
+
+    clock-names:
+      items:
+        - const: hosc
+        - const: losc
+        - const: iosc
+        - const: losc-fanout
+
+additionalProperties: false
+
+examples:
+  - |
+    ccu: clock at 2001000 {
+        compatible = "allwinner,sun55i-a523-ccu";
+        reg = <0x2001000 0x1000>;
+        clocks = <&osc24M>, <&osc32k>, <&iosc>, <&r_ccu 2>;
+        clock-names = "hosc", "losc", "iosc", "losc-fanout";
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+    };
+
+...
diff --git a/include/dt-bindings/clock/sun55i-a523-ccu.h b/include/dt-bindings/clock/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..c8259ac5ada7a
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-ccu.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+
+#define CLK_PLL_DDR0		0
+#define CLK_PLL_PERIPH0_4X	1
+#define CLK_PLL_PERIPH0_2X	2
+#define CLK_PLL_PERIPH0_800M	3
+#define CLK_PLL_PERIPH0_480M	4
+#define CLK_PLL_PERIPH0_600M	5
+#define CLK_PLL_PERIPH0_400M	6
+#define CLK_PLL_PERIPH0_300M	7
+#define CLK_PLL_PERIPH0_200M	8
+#define CLK_PLL_PERIPH0_160M	9
+#define CLK_PLL_PERIPH0_150M	10
+#define CLK_PLL_PERIPH1_4X	11
+#define CLK_PLL_PERIPH1_2X	12
+#define CLK_PLL_PERIPH1_800M	13
+#define CLK_PLL_PERIPH1_480M	14
+#define CLK_PLL_PERIPH1_600M	15
+#define CLK_PLL_PERIPH1_400M	16
+#define CLK_PLL_PERIPH1_300M	17
+#define CLK_PLL_PERIPH1_200M	18
+#define CLK_PLL_PERIPH1_160M	19
+#define CLK_PLL_PERIPH1_150M	20
+#define CLK_PLL_GPU		21
+#define CLK_PLL_VIDEO0_8X	22
+#define CLK_PLL_VIDEO0_4X	23
+#define CLK_PLL_VIDEO0_3X	24
+#define CLK_PLL_VIDEO1_8X	25
+#define CLK_PLL_VIDEO1_4X	26
+#define CLK_PLL_VIDEO1_3X	27
+#define CLK_PLL_VIDEO2_8X	28
+#define CLK_PLL_VIDEO2_4X	29
+#define CLK_PLL_VIDEO2_3X	30
+#define CLK_PLL_VIDEO3_8X	31
+#define CLK_PLL_VIDEO3_4X	32
+#define CLK_PLL_VIDEO3_3X	33
+#define CLK_PLL_VE		34
+#define CLK_PLL_AUDIO0_4X	35
+#define CLK_PLL_AUDIO0_2X	36
+#define CLK_PLL_AUDIO0		37
+#define CLK_PLL_NPU_4X		38
+#define CLK_PLL_NPU_2X		39
+#define CLK_PLL_NPU		40
+#define CLK_AHB			41
+#define CLK_APB0		42
+#define CLK_APB1		43
+#define CLK_MBUS		44
+#define CLK_DE			45
+#define CLK_BUS_DE		46
+#define CLK_DI			47
+#define CLK_BUS_DI		48
+#define CLK_G2D			49
+#define CLK_BUS_G2D		50
+#define CLK_GPU			51
+#define CLK_BUS_GPU		52
+#define CLK_CE			53
+#define CLK_BUS_CE		54
+#define CLK_BUS_CE_SYS		55
+#define CLK_VE			56
+#define CLK_BUS_VE		57
+#define CLK_BUS_DMA		58
+#define CLK_BUS_MSGBOX		59
+#define CLK_BUS_SPINLOCK	60
+#define CLK_HSTIMER0		61
+#define CLK_HSTIMER1		62
+#define CLK_HSTIMER2		63
+#define CLK_HSTIMER3		64
+#define CLK_HSTIMER4		65
+#define CLK_HSTIMER5		66
+#define CLK_BUS_HSTIMER		67
+#define CLK_BUS_DBG		68
+#define CLK_BUS_PWM0		69
+#define CLK_BUS_PWM1		70
+#define CLK_IOMMU		71
+#define CLK_BUS_IOMMU		72
+#define CLK_DRAM		73
+#define CLK_MBUS_DMA		74
+#define CLK_MBUS_VE		75
+#define CLK_MBUS_CE		76
+#define CLK_MBUS_CSI		77
+#define CLK_MBUS_ISP		78
+#define CLK_MBUS_EMAC1		79
+#define CLK_BUS_DRAM		80
+#define CLK_NAND0		81
+#define CLK_NAND1		82
+#define CLK_BUS_NAND		83
+#define CLK_MMC0		84
+#define CLK_MMC1		85
+#define CLK_MMC2		86
+#define CLK_BUS_SYSDAP		87
+#define CLK_BUS_MMC0		88
+#define CLK_BUS_MMC1		89
+#define CLK_BUS_MMC2		90
+#define CLK_BUS_UART0		91
+#define CLK_BUS_UART1		92
+#define CLK_BUS_UART2		93
+#define CLK_BUS_UART3		94
+#define CLK_BUS_UART4		95
+#define CLK_BUS_UART5		96
+#define CLK_BUS_UART6		97
+#define CLK_BUS_UART7		98
+#define CLK_BUS_I2C0		99
+#define CLK_BUS_I2C1		100
+#define CLK_BUS_I2C2		101
+#define CLK_BUS_I2C3		102
+#define CLK_BUS_I2C4		103
+#define CLK_BUS_I2C5		104
+#define CLK_BUS_CAN		105
+#define CLK_SPI0		106
+#define CLK_SPI1		107
+#define CLK_SPI2		108
+#define CLK_SPIFC		109
+#define CLK_BUS_SPI0		110
+#define CLK_BUS_SPI1		111
+#define CLK_BUS_SPI2		112
+#define CLK_BUS_SPIFC		113
+#define CLK_EMAC0_25M		114
+#define CLK_EMAC1_25M		115
+#define CLK_BUS_EMAC0		116
+#define CLK_BUS_EMAC1		117
+#define CLK_IR_RX		118
+#define CLK_BUS_IR_RX		119
+#define CLK_IR_TX		120
+#define CLK_BUS_IR_TX		121
+#define CLK_GPADC0		122
+#define CLK_GPADC1		123
+#define CLK_BUS_GPADC0		124
+#define CLK_BUS_GPADC1		125
+#define CLK_BUS_THS		126
+#define CLK_USB_OHCI0		127
+#define CLK_USB_OHCI1		128
+#define CLK_BUS_OHCI0		129
+#define CLK_BUS_OHCI1		130
+#define CLK_BUS_EHCI0		131
+#define CLK_BUS_EHCI1		132
+#define CLK_BUS_OTG		133
+#define CLK_BUS_LRADC		134
+#define CLK_PCIE_AUX		135
+#define CLK_BUS_DISPLAY0_TOP	136
+#define CLK_BUS_DISPLAY1_TOP	137
+#define CLK_HDMI_24M		138
+#define CLK_HDMI_CEC_32K	139
+#define CLK_HDMI_CEC		140
+#define CLK_BUS_HDMI		141
+#define CLK_MIPI_DSI0		142
+#define CLK_MIPI_DSI1		143
+#define CLK_BUS_MIPI_DSI0	144
+#define CLK_BUS_MIPI_DSI1	145
+#define CLK_TCON_LCD0		146
+#define CLK_TCON_LCD1		147
+#define CLK_TCON_LCD2		148
+#define CLK_COMBOPHY_DSI0	149
+#define CLK_COMBOPHY_DSI1	150
+#define CLK_BUS_TCON_LCD0	151
+#define CLK_BUS_TCON_LCD1	152
+#define CLK_BUS_TCON_LCD2	153
+#define CLK_TCON_TV0		154
+#define CLK_TCON_TV1		155
+#define CLK_BUS_TCON_TV0	156
+#define CLK_BUS_TCON_TV1	157
+#define CLK_EDP			158
+#define CLK_BUS_EDP		159
+#define CLK_LEDC		160
+#define CLK_BUS_LEDC		161
+#define CLK_CSI_TOP		162
+#define CLK_CSI_MCLK0		163
+#define CLK_CSI_MCLK1		164
+#define CLK_CSI_MCLK2		165
+#define CLK_CSI_MCLK3		166
+#define CLK_BUS_CSI		167
+#define CLK_ISP			168
+#define CLK_DSP			169
+#define CLK_FANOUT_24M		170
+#define CLK_FANOUT_12M		171
+#define CLK_FANOUT_16M		172
+#define CLK_FANOUT_25M		173
+#define CLK_FANOUT_27M		174
+#define CLK_FANOUT_PCLK		175
+#define CLK_FANOUT0		176
+#define CLK_FANOUT1		177
+#define CLK_FANOUT2		178
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-ccu.h b/include/dt-bindings/reset/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..e1e4c5f4cdd89
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-ccu.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_NSI		1
+#define RST_BUS_DE		2
+#define RST_BUS_DI		3
+#define RST_BUS_G2D		4
+#define RST_BUS_SYS		5
+#define RST_BUS_GPU		6
+#define RST_BUS_CE		7
+#define RST_BUS_SYS_CE		8
+#define RST_BUS_VE		9
+#define RST_BUS_DMA		10
+#define RST_BUS_MSGBOX		11
+#define RST_BUS_SPINLOCK	12
+#define RST_BUS_CPUXTIMER	13
+#define RST_BUS_DBG		14
+#define RST_BUS_PWM0		15
+#define RST_BUS_PWM1		16
+#define RST_BUS_DRAM		17
+#define RST_BUS_NAND		18
+#define RST_BUS_MMC0		19
+#define RST_BUS_MMC1		20
+#define RST_BUS_MMC2		21
+#define RST_BUS_SYSDAP		22
+#define RST_BUS_UART0		23
+#define RST_BUS_UART1		24
+#define RST_BUS_UART2		25
+#define RST_BUS_UART3		26
+#define RST_BUS_UART4		27
+#define RST_BUS_UART5		28
+#define RST_BUS_UART6		29
+#define RST_BUS_UART7		30
+#define RST_BUS_I2C0		31
+#define RST_BUS_I2C1		32
+#define RST_BUS_I2C2		33
+#define RST_BUS_I2C3		34
+#define RST_BUS_I2C4		35
+#define RST_BUS_I2C5		36
+#define RST_BUS_CAN		37
+#define RST_BUS_SPI0		38
+#define RST_BUS_SPI1		39
+#define RST_BUS_SPI2		40
+#define RST_BUS_SPIFC		41
+#define RST_BUS_EMAC0		42
+#define RST_BUS_EMAC1		43
+#define RST_BUS_IR_RX		44
+#define RST_BUS_IR_TX		45
+#define RST_BUS_GPADC0		46
+#define RST_BUS_GPADC1		47
+#define RST_BUS_THS		48
+#define RST_USB_PHY0		49
+#define RST_USB_PHY1		50
+#define RST_BUS_OHCI0		51
+#define RST_BUS_OHCI1		52
+#define RST_BUS_EHCI0		53
+#define RST_BUS_EHCI1		54
+#define RST_BUS_OTG		55
+#define RST_BUS_3		56
+#define RST_BUS_LRADC		57
+#define RST_BUS_PCIE_USB3	58
+#define RST_BUS_DISPLAY0_TOP	59
+#define RST_BUS_DISPLAY1_TOP	60
+#define RST_BUS_HDMI_MAIN	61
+#define RST_BUS_HDMI_SUB	62
+#define RST_BUS_MIPI_DSI0	63
+#define RST_BUS_MIPI_DSI1	64
+#define RST_BUS_TCON_LCD0	65
+#define RST_BUS_TCON_LCD1	66
+#define RST_BUS_TCON_LCD2	67
+#define RST_BUS_TCON_TV0	68
+#define RST_BUS_TCON_TV1	69
+#define RST_BUS_LVDS0		70
+#define RST_BUS_LVDS1		71
+#define RST_BUS_EDP		72
+#define RST_BUS_VIDEO_OUT0	73
+#define RST_BUS_VIDEO_OUT1	74
+#define RST_BUS_LEDC		75
+#define RST_BUS_CSI		76
+#define RST_BUS_ISP		77
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_CCU_H_ */
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:53 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:53 +0000
Subject: [PATCH v3 03/15] clk: sunxi-ng: Add support for update bit
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-4-andre.przywara@arm.com>

Some clocks in the Allwinner A523 SoC contain an "update bit" (bit 27),
which must be set to apply any register changes, namely the mux
selector, the divider and the gate bit.

Add a new CCU feature bit to mark those clocks, and set bit 27 whenever
we are applying any changes.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu_common.h | 4 ++++
 drivers/clk/sunxi-ng/ccu_div.c    | 2 ++
 drivers/clk/sunxi-ng/ccu_gate.c   | 4 ++++
 drivers/clk/sunxi-ng/ccu_mux.c    | 2 ++
 4 files changed, 12 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 50fd268329671..d41d33bdff470 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -20,10 +20,14 @@
 #define CCU_FEATURE_KEY_FIELD		BIT(8)
 #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
 #define CCU_FEATURE_DUAL_DIV		BIT(10)
+#define CCU_FEATURE_UPDATE_BIT27	BIT(11)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
 
+/* Some clocks need this bit to actually apply register changes */
+#define CCU_SUNXI_UPDATE_BIT		BIT(27)
+
 struct device_node;
 
 struct ccu_common {
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 7f4691f09e01f..2d8b98fe4b13a 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -106,6 +106,8 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	reg = readl(cd->common.base + cd->common.reg);
 	reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
+	if (cd->common.features & CCU_FEATURE_UPDATE_BIT27)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 
 	writel(reg | (val << cd->div.shift),
 	       cd->common.base + cd->common.reg);
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
index ac52fd6bff677..0490f95781361 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -20,6 +20,8 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
 	spin_lock_irqsave(common->lock, flags);
 
 	reg = readl(common->base + common->reg);
+	if (common->features & CCU_FEATURE_UPDATE_BIT27)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 	writel(reg & ~gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
@@ -44,6 +46,8 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
 	spin_lock_irqsave(common->lock, flags);
 
 	reg = readl(common->base + common->reg);
+	if (common->features & CCU_FEATURE_UPDATE_BIT27)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 	writel(reg | gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index d7ffbdeee9e04..82ee21e0d3a68 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -197,6 +197,8 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
 	/* The key field always reads as zero. */
 	if (common->features & CCU_FEATURE_KEY_FIELD)
 		reg |= CCU_MUX_KEY_VALUE;
+	if (common->features & CCU_FEATURE_UPDATE_BIT27)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 
 	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
 	writel(reg | (index << cm->shift), common->base + common->reg);
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:55 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:55 +0000
Subject: [PATCH v3 05/15] dt-bindings: clk: sunxi-ng: add compatible for the A523 PRCM-CCU
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-6-andre.przywara@arm.com>

The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
the PRCM R_CCU.

Add the new compatible string, along with the required input clock
lists. There is now an extra input clock (PLL_AUDIO), so add this to the
list of allowed clocks and required it for the A523 PRCM CCU.
Also add the DT binding headers, listing all the clocks with their ID
numbers.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../clock/allwinner,sun55i-a523-ccu.yaml      | 23 +++++++++++-
 include/dt-bindings/clock/sun55i-a523-r-ccu.h | 37 +++++++++++++++++++
 include/dt-bindings/reset/sun55i-a523-r-ccu.h | 25 +++++++++++++
 3 files changed, 83 insertions(+), 2 deletions(-)
 create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
index 2eacaeaeabac7..a64a35b423736 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
@@ -19,17 +19,18 @@ properties:
   compatible:
     enum:
       - allwinner,sun55i-a523-ccu
+      - allwinner,sun55i-a523-r-ccu
 
   reg:
     maxItems: 1
 
   clocks:
     minItems: 4
-    maxItems: 4
+    maxItems: 5
 
   clock-names:
     minItems: 4
-    maxItems: 4
+    maxItems: 5
 
 required:
   - "#clock-cells"
@@ -61,6 +62,24 @@ then:
         - const: iosc
         - const: losc-fanout
 
+else:
+  properties:
+    clocks:
+      items:
+        - description: High Frequency Oscillator (usually at 24MHz)
+        - description: Low Frequency Oscillator (usually at 32kHz)
+        - description: Internal Oscillator
+        - description: Peripherals PLL
+        - description: Audio PLL
+
+    clock-names:
+      items:
+        - const: hosc
+        - const: losc
+        - const: iosc
+        - const: pll-periph
+        - const: pll-audio
+
 additionalProperties: false
 
 examples:
diff --git a/include/dt-bindings/clock/sun55i-a523-r-ccu.h b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..365647499b9ab
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+
+#define CLK_R_AHB		0
+#define CLK_R_APB0		1
+#define CLK_R_APB1		2
+#define CLK_R_TIMER0		3
+#define CLK_R_TIMER1		4
+#define CLK_R_TIMER2		5
+#define CLK_BUS_R_TIMER		6
+#define CLK_BUS_R_TWD		7
+#define CLK_R_PWMCTRL		8
+#define CLK_BUS_R_PWMCTRL	9
+#define CLK_R_SPI		10
+#define CLK_BUS_R_SPI		11
+#define CLK_BUS_R_SPINLOCK	12
+#define CLK_BUS_R_MSGBOX	13
+#define CLK_BUS_R_UART0		14
+#define CLK_BUS_R_UART1		15
+#define CLK_BUS_R_I2C0		16
+#define CLK_BUS_R_I2C1		17
+#define CLK_BUS_R_I2C2		18
+#define CLK_BUS_R_PPU0		19
+#define CLK_BUS_R_PPU1		20
+#define CLK_BUS_R_CPU_BIST	21
+#define CLK_R_IR_RX		22
+#define CLK_BUS_R_IR_RX		23
+#define CLK_BUS_R_DMA		24
+#define CLK_BUS_R_RTC		25
+#define CLK_BUS_R_CPUCFG	26
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-r-ccu.h b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..dd6fbb372e190
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+
+#define RST_BUS_R_TIMER		0
+#define RST_BUS_R_TWD		1
+#define RST_BUS_R_PWMCTRL	2
+#define RST_BUS_R_SPI		3
+#define RST_BUS_R_SPINLOCK	4
+#define RST_BUS_R_MSGBOX	5
+#define RST_BUS_R_UART0		6
+#define RST_BUS_R_UART1		7
+#define RST_BUS_R_I2C0		8
+#define RST_BUS_R_I2C1		9
+#define RST_BUS_R_I2C2		10
+#define RST_BUS_R_PPU1		11
+#define RST_BUS_R_IR_RX		12
+#define RST_BUS_R_RTC		13
+#define RST_BUS_R_CPUCFG	14
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_ */
-- 
2.46.3



From andre.przywara at arm.com  Mon Mar  3 17:27:57 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 01:27:57 +0000
Subject: [PATCH v3 07/15] clk: sunxi-ng: a523: Add support for bus clocks
In-Reply-To: <20250304012805.28594-1-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
Message-ID: <20250304012805.28594-8-andre.przywara@arm.com>

Add the basic bus clocks for the Allwinner A523 and T527 SoCs.
This covers the AHB, APB0 and APB1 clocks. Linux is not supposed to
change those clocks, but they are needed as parents for many other mod
clocks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 39 ++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 455bca0c344bc..c8a96b642bb1e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -331,6 +331,39 @@ static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
 static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
 			   &pll_npu_4x_clk.common.hw, 4, 1, 0);
 
+
+/**************************************************************************
+ *                           bus clocks                                   *
+ **************************************************************************/
+
+static const struct clk_parent_data ahb_apb0_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_600M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
+				 0, 5,		/* M */
+				 24, 2,		/* mux */
+				 0);
+static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
+				 0, 5,		/* M */
+				 24, 2,	/* mux */
+				 0);
+
+static const struct clk_parent_data apb1_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
+				 0, 5,		/* M */
+				 24, 3,		/* mux */
+				 0);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -358,6 +391,9 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&pll_ve_clk.common,
 	&pll_audio0_4x_clk.common,
 	&pll_npu_4x_clk.common,
+	&ahb_clk.common,
+	&apb0_clk.common,
+	&apb1_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -403,6 +439,9 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_PLL_NPU_4X]	= &pll_npu_4x_clk.common.hw,
 		[CLK_PLL_NPU_2X]	= &pll_npu_2x_clk.hw,
 		[CLK_PLL_NPU]		= &pll_npu_1x_clk.hw,
+		[CLK_AHB]		= &ahb_clk.common.hw,
+		[CLK_APB0]		= &apb0_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:04 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:04 +0200
Subject: [PATCH v4 05/12] phy: rockchip: samsung-hdptx: Drop unused phy_cfg
 driver data
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-5-8657847c13f7@collabora.com>

There is no usage of phy_cfg in the upstream driver data, nor in the
downstream one, hence remove it.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index f9b5c96d6c789e435657e224032d35b5a6950945..06644c3d98d3f8b697fc704704df5acdd3c85bad 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -397,7 +397,6 @@ struct rk_hdptx_phy {
 	int phy_id;
 
 	struct phy *phy;
-	struct phy_config *phy_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];

-- 
2.48.1



From martin.petersen at oracle.com  Mon Mar  3 18:02:52 2025
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Mon, 03 Mar 2025 21:02:52 -0500
Subject: [PATCH][next] scsi: ufs: rockchip: Fix spelling mistake
 "susped" -> "suspend"
In-Reply-To: <20250225101142.161474-1-colin.i.king@gmail.com> (Colin Ian
	King's message of "Tue, 25 Feb 2025 10:11:42 +0000")
References: <20250225101142.161474-1-colin.i.king@gmail.com>
Message-ID: <yq11pvdwo1m.fsf@ca-mkp.ca.oracle.com>


Colin,

> There is a spelling mistake in a dev_err message. Fix it.

Applied to 6.15/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering


From menglong8.dong at gmail.com  Mon Mar  3 18:07:22 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 10:07:22 +0800
Subject: [PATCH bpf-next v3 3/4] x86: implement per-function metadata
 storage for x86
In-Reply-To: <20250303110559.5a584602@gandalf.local.home>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
 <20250303065345.229298-4-dongml2@chinatelecom.cn> <20250303110559.5a584602@gandalf.local.home>
Message-ID: <CADxym3ZJf3TEMwCy4JVT1gs9GP=U1n1qss3ycnuMZVyp9TfDdw@mail.gmail.com>

On Tue, Mar 4, 2025 at 12:05?AM Steven Rostedt <rostedt at goodmis.org> wrote:
>
> On Mon,  3 Mar 2025 14:53:44 +0800
> Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> > In the third case, we make the kernel function 32 bytes aligned, and there
> > will be 32 bytes padding before the functions. According to my testing,
> > the text size didn't increase on this case, which is weird.
> >
> > With 16-bytes padding:
> >
> > -rwxr-xr-x 1 401190688  x86-dev/vmlinux*
> > -rw-r--r-- 1    251068  x86-dev/vmlinux.a
> > -rw-r--r-- 1 851892992  x86-dev/vmlinux.o
> > -rw-r--r-- 1  12395008  x86-dev/arch/x86/boot/bzImage
> >
> > With 32-bytes padding:
> >
> > -rwxr-xr-x 1 401318128 x86-dev/vmlinux*
> > -rw-r--r-- 1    251154 x86-dev/vmlinux.a
> > -rw-r--r-- 1 853636704 x86-dev/vmlinux.o
> > -rw-r--r-- 1  12509696 x86-dev/arch/x86/boot/bzImage
>
> Use the "size" command to see the differences in sizes and not the file size.
>
> $ size vmlinux
>    text    data     bss     dec     hex filename
> 36892658        9798658 16982016        63673332        3cb93f4 vmlinux

Great! It seems that the way I tested has something wrong. I'll
compare the text size with "size" command later.

Thanks!
Menglong Dong

>
> -- Steve


From cristian.ciocaltea at collabora.com  Mon Mar  3 18:13:35 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 4 Mar 2025 04:13:35 +0200
Subject: [PATCH v3 5/8] phy: rockchip: samsung-hdptx: Setup TMDS char rate
 via phy_configure_opts_hdmi
In-Reply-To: <CAA8EJppjRFWXXYSp=SKPKBV-ceO7gu3n37k-5eUeYG_x6rOmsg@mail.gmail.com>
References: <20250223-phy-sam-hdptx-bpc-v3-0-66a5c8e68327@collabora.com>
 <20250223-phy-sam-hdptx-bpc-v3-5-66a5c8e68327@collabora.com>
 <CAA8EJppjRFWXXYSp=SKPKBV-ceO7gu3n37k-5eUeYG_x6rOmsg@mail.gmail.com>
Message-ID: <94ef8866-eccb-497e-8279-a242bbe098d6@collabora.com>

On 2/24/25 1:38 AM, Dmitry Baryshkov wrote:
> On Sun, 23 Feb 2025 at 13:02, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> The current workaround to setup the TMDS character rate relies on the
>> unconventional usage of phy_set_bus_width().
>>
>> Make use of the recently introduced HDMI PHY configuration API for this
>> purpose.  The workaround will be dropped as soon as the switch has been
>> completed on both ends.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 37 +++++++++++++++++------
>>  1 file changed, 27 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index f9b5c96d6c789e435657e224032d35b5a6950945..dd91a7272e246b2133112effdb080a847fd15abe 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -402,6 +402,9 @@ struct rk_hdptx_phy {
>>         int nr_clks;
>>         struct reset_control_bulk_data rsts[RST_MAX];
>>
>> +       /* PHY config opts */
>> +       unsigned long tmds_char_rate;
> 
> It's easier to embed struct phy_configure_opts_hdmi here, in the end
> you  add bpc here in one of the next patches.

Indeed, handled in [1], part of v4.
 
>> +
>>         /* clk provider */
>>         struct clk_hw hw;
>>         unsigned long rate;

[...]

>> @@ -1830,6 +1837,16 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
>>  {
>>         struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
>>
>> +       /*
>> +        * The TMDS char rate set via phy_configure(), if any, has
>> +        * precedence over the rate provided via clk_set_rate().
> 
> I think this is not so nice. It makes CCF desync from the actual rate
> programmed into the hardware. Maybe you can make the clock r/o?

Oh, you're right.  I should have added just a warning here, though I
haven't really noticed this in practice so far.

I ended up providing a new patch [2] to properly restrict altering 
the TMDS char rate.  As explained in the commit message, making the 
clock read-only is currently not feasible, but I'll revisit this as
soon as the switch to relying exclusively on the HDMI PHY config API 
for the rate setup gets completed on both ends.

Thanks for the review!

Regards,
Cristian
 
>> +        */
>> +       if (hdptx->tmds_char_rate && hdptx->tmds_char_rate != rate) {
>> +               dev_dbg(hdptx->dev, "Replaced clk_set_rate=%lu with tmds_char_rate=%lu\n",
>> +                       rate, hdptx->tmds_char_rate);
>> +               rate = hdptx->tmds_char_rate;
>> +       }
>> +
>>         return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
>>  }
>>
>>
>> --
>> 2.48.1

[1] https://lore.kernel.org/lkml/20250304-phy-sam-hdptx-bpc-v4-7-8657847c13f7 at collabora.com/
[2] https://lore.kernel.org/lkml/20250304-phy-sam-hdptx-bpc-v4-9-8657847c13f7 at collabora.com/


From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:07 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:07 +0200
Subject: [PATCH v4 08/12] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-8-8657847c13f7@collabora.com>

Implement the phy_ops.validate() callback to allow checking the PHY
configuration parameters without actually applying them.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 7e1d1c10758249aa5bbddbdaae0108bba04f30df..47db1395051f5d900197871694bab90ca4d6e38e 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1482,6 +1482,17 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
 		return -EINVAL;
 
+	u32 bit_rate = hdmi->tmds_char_rate / 100;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+			break;
+
+	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
+	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -1789,10 +1800,22 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	return 0;
 }
 
+static int rk_hdptx_phy_validate(struct phy *phy, enum phy_mode mode,
+				 int submode, union phy_configure_opts *opts)
+{
+	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+
+	if (mode != PHY_MODE_DP)
+		return rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+
+	return rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
+}
+
 static const struct phy_ops rk_hdptx_phy_ops = {
 	.power_on  = rk_hdptx_phy_power_on,
 	.power_off = rk_hdptx_phy_power_off,
 	.configure = rk_hdptx_phy_configure,
+	.validate  = rk_hdptx_phy_validate,
 	.owner	   = THIS_MODULE,
 };
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:08 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:08 +0200
Subject: [PATCH v4 09/12] phy: rockchip: samsung-hdptx: Restrict altering
 TMDS char rate via CCF
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-9-8657847c13f7@collabora.com>

Although, in theory, the clock provider functionality could be enabled
as a standalone driver feature, in practice it is unlikely that it would
be ever needed separately from the common PHY related features, i.e.
making use of the PHY PLL as an alternative and more accurate clock
source for display modes handling.  Which means the PLL will be always
programmed according to the TMDS char rate set via the HDMI PHY
configuration API.

Currently it's possible to freely adjust the rate via the clock API as
well, that is through clk_set_rate().  Making the clock read-only is not
feasible since we need to ensure any rate update done via the PHY
configuration API has been actually programmed into the hardware before
CCF accesses it.  This would be normally done during phy_ops.power_on()
or clk_ops.prepare() callbacks, but it might happen that the former gets
fired too late and the latter only once, hence we need to keep handle it
via clk_ops.set_rate() as a fallback approach.

Prevent changing the TMDS character rate via CCF by letting
rk_hdptx_phy_clk_round_rate() always return the value set via
phy_configure().  To avoid breaking existing users, i.e. RK DW HDMI QP
bridge driver, until the switch to the HDMI PHY config based approach is
completed, introduce a temporary exception to the rule, toggled via the
new ->restrict_rate_change flag, which indicates whether phy_configure()
has been called or not.

Additionally, revert any unlikely rate change that might have occurred
between the calls to ->round_rate() and ->set_rate().

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 53 +++++++++++++++++------
 1 file changed, 40 insertions(+), 13 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 47db1395051f5d900197871694bab90ca4d6e38e..b4d2f04842b5c5b425c5b73a8b27fabecbbbd6bb 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -402,6 +402,7 @@ struct rk_hdptx_phy {
 	/* clk provider */
 	struct clk_hw hw;
 	unsigned long rate;
+	bool restrict_rate_change;
 
 	atomic_t usage_count;
 
@@ -1759,10 +1760,12 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 
 	if (mode != PHY_MODE_DP) {
 		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
-		if (ret)
+		if (ret) {
 			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
-		else
+		} else {
 			hdptx->hdmi_cfg = opts->hdmi;
+			hdptx->restrict_rate_change = true;
+		}
 		return ret;
 	}
 
@@ -1849,21 +1852,31 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate)
 {
-	u32 bit_rate = rate / 100;
-	int i;
+	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	if (rate > HDMI20_MAX_RATE)
-		return rate;
+	/*
+	 * FIXME: Temporarily allow altering TMDS char rate via CCF.
+	 * To be dropped as soon as the RK DW HDMI QP bridge driver
+	 * switches to make use of phy_configure().
+	 */
+	if (!hdptx->restrict_rate_change && rate != hdptx->hdmi_cfg.tmds_char_rate) {
+		struct phy_configure_opts_hdmi hdmi = {
+			.tmds_char_rate = rate,
+		};
+		int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi);
 
-	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
-			break;
+		if (ret)
+			return ret;
 
-	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
-		return -EINVAL;
+		hdptx->hdmi_cfg = hdmi;
+	}
 
-	return rate;
+	/*
+	 * The TMDS char rate shall be adjusted via phy_configure() only,
+	 * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
+	 * a different rate argument.
+	 */
+	return hdptx->hdmi_cfg.tmds_char_rate;
 }
 
 static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1871,6 +1884,20 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
+	/* Revert any unlikely TMDS char rate change since round_rate() */
+	if (hdptx->hdmi_cfg.tmds_char_rate != rate) {
+		dev_warn(hdptx->dev, "Reverting unexpected rate change from %lu to %llu\n",
+			 rate, hdptx->hdmi_cfg.tmds_char_rate);
+		hdptx->hdmi_cfg.tmds_char_rate = rate;
+	}
+
+	/*
+	 * The TMDS char rate would be normally programmed in HW during
+	 * phy_ops.power_on() or clk_ops.prepare() callbacks, but it might
+	 * happen that the former gets fired too late, i.e. after this call,
+	 * while the latter being executed only once, i.e. when clock remains
+	 * in the prepared state during rate changes.
+	 */
 	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
 }
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:09 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:09 +0200
Subject: [PATCH v4 10/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-10-8657847c13f7@collabora.com>

Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 29 +++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index b4d2f04842b5c5b425c5b73a8b27fabecbbbd6bb..c2ad1cb94614711bea13b7259a6b66dbd72d663d 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1027,6 +1027,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
 			   FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
 
+	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+			   FIELD_PREP(PLL_PCG_CLK_SEL_MASK, (hdptx->hdmi_cfg.bpc - 8) >> 1));
+
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
@@ -1428,7 +1431,8 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		} else {
 			rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
 		}
-		dev_dbg(hdptx->dev, "%s rate=%u\n", __func__, rate);
+		dev_dbg(hdptx->dev, "%s rate=%u bpc=%u\n",
+			__func__, rate, hdptx->hdmi_cfg.bpc);
 	}
 
 	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
@@ -1480,12 +1484,12 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
 static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 					   struct phy_configure_opts_hdmi *hdmi)
 {
-	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
-		return -EINVAL;
-
 	u32 bit_rate = hdmi->tmds_char_rate / 100;
 	int i;
 
+	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
+		return -EINVAL;
+
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
 		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
 			break;
@@ -1494,6 +1498,19 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
 		return -EINVAL;
 
+	if (!hdmi->bpc)
+		hdmi->bpc = 8;
+
+	switch (hdmi->bpc) {
+	case 8:
+	case 10:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	};
+
 	return 0;
 }
 
@@ -1766,6 +1783,9 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 			hdptx->hdmi_cfg = opts->hdmi;
 			hdptx->restrict_rate_change = true;
 		}
+
+		dev_dbg(hdptx->dev, "%s tmds_rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 		return ret;
 	}
 
@@ -1974,6 +1994,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hdptx->dev = dev;
+	hdptx->hdmi_cfg.bpc = 8;
 
 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(regs))

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:10 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:10 +0200
Subject: [PATCH v4 11/12] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-11-8657847c13f7@collabora.com>

Drop the rate parameter from a bunch of internal helpers and, instead,
make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
data.

Additionally, rename the rather ambiguous ->rate member of struct
rk_hdptx_phy to ->hw_rate and ensure rk_hdptx_ropll_tmds_cmn_config()
updates it only after all the other operations have been successful.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 59 +++++++++++------------
 1 file changed, 29 insertions(+), 30 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index c2ad1cb94614711bea13b7259a6b66dbd72d663d..54210eaec0c0923b3e8eb8e207632983982bcd2f 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -401,9 +401,8 @@ struct rk_hdptx_phy {
 
 	/* clk provider */
 	struct clk_hw hw;
-	unsigned long rate;
+	unsigned long hw_rate;
 	bool restrict_rate_change;
-
 	atomic_t usage_count;
 
 	/* used for dp mode */
@@ -968,14 +967,15 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
 	return true;
 }
 
-static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
-					  unsigned int rate)
+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 {
+	unsigned int rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
-	int i;
+	int ret, i;
 
-	hdptx->rate = rate * 100;
+	if (!rate)
+		return 0;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
 		if (rate == ropll_tmds_cfg[i].bit_rate) {
@@ -987,7 +987,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 		if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
 			cfg = &rc;
 		} else {
-			dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+			dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%u\n",
+				__func__, rate);
 			return -EINVAL;
 		}
 	}
@@ -1033,17 +1034,20 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
-	return rk_hdptx_post_enable_pll(hdptx);
+	ret = rk_hdptx_post_enable_pll(hdptx);
+	if (!ret)
+		hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate;
+
+	return ret;
 }
 
-static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
-					   unsigned int rate)
+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx)
 {
 	rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate > HDMI14_MAX_RATE / 100) {
+	if (hdptx->hdmi_cfg.tmds_char_rate > HDMI14_MAX_RATE) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {
@@ -1095,8 +1099,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
 		     HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
 }
 
-static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
-				     unsigned int rate)
+static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
 {
 	enum phy_mode mode = phy_get_mode(hdptx->phy);
 	u32 status;
@@ -1115,11 +1118,9 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
 	if (mode == PHY_MODE_DP) {
 		rk_hdptx_dp_reset(hdptx);
 	} else {
-		if (rate) {
-			ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
-			if (ret)
-				goto dec_usage;
-		}
+		ret = rk_hdptx_ropll_tmds_cmn_config(hdptx);
+		if (ret)
+			goto dec_usage;
 	}
 
 	return 0;
@@ -1415,7 +1416,6 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
 	enum phy_mode mode = phy_get_mode(phy);
-	unsigned int rate = 0;
 	int ret, lane;
 
 	if (mode != PHY_MODE_DP) {
@@ -1426,16 +1426,15 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 			 * Will be removed as soon the switch to the HDMI PHY
 			 * configuration API has been completed on both ends.
 			 */
-			rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
-			hdptx->hdmi_cfg.tmds_char_rate = rate * 100;
-		} else {
-			rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
+			hdptx->hdmi_cfg.tmds_char_rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+			hdptx->hdmi_cfg.tmds_char_rate *= 100;
 		}
-		dev_dbg(hdptx->dev, "%s rate=%u bpc=%u\n",
-			__func__, rate, hdptx->hdmi_cfg.bpc);
+
+		dev_dbg(hdptx->dev, "%s tmds_rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 	}
 
-	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
+	ret = rk_hdptx_phy_consumer_get(hdptx);
 	if (ret)
 		return ret;
 
@@ -1466,7 +1465,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		regmap_write(hdptx->grf, GRF_HDPTX_CON0,
 			     HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
 
-		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+		ret = rk_hdptx_ropll_tmds_mode_config(hdptx);
 		if (ret)
 			rk_hdptx_phy_consumer_put(hdptx, true);
 	}
@@ -1851,7 +1850,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
+	return rk_hdptx_phy_consumer_get(hdptx);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1866,7 +1865,7 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return hdptx->rate;
+	return hdptx->hw_rate;
 }
 
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -1918,7 +1917,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	 * while the latter being executed only once, i.e. when clock remains
 	 * in the prepared state during rate changes.
 	 */
-	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+	return rk_hdptx_ropll_tmds_cmn_config(hdptx);
 }
 
 static const struct clk_ops hdptx_phy_clk_ops = {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:11 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:11 +0200
Subject: [PATCH v4 12/12] phy: rockchip: samsung-hdptx: Avoid Hz-hHz unit
 conversion overhead
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-12-8657847c13f7@collabora.com>

The ropll_tmds_cfg table used to identify the configuration params for
the supported rates expects the search keys - bit_rate field - to be
provided in hHz rather than Hz (1 hHz = 100 Hz).  This requires multiple
conversions between these units being performed at runtime.

Improve implementation clarity and efficiency by consistently using the
Hz unit throughout driver's internal data structures and functions.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 68 +++++++++++------------
 1 file changed, 33 insertions(+), 35 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 54210eaec0c0923b3e8eb8e207632983982bcd2f..8a835f8a5dc82a6d7ce5bdf79ed2773b9a7fa7c5 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -330,7 +330,7 @@ enum dp_link_rate {
 };
 
 struct ropll_config {
-	u32 bit_rate;
+	u32 rate;
 	u8 pms_mdiv;
 	u8 pms_mdiv_afc;
 	u8 pms_pdiv;
@@ -411,45 +411,45 @@ struct rk_hdptx_phy {
 };
 
 static const struct ropll_config ropll_tmds_cfg[] = {
-	{ 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 594000000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 371250000, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 297000000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
+	{ 162000000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 185625000, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
+	{ 154000000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
+	{ 148500000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
 	  0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
+	{ 146250000, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
+	{ 119000000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
+	{ 106500000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 108000000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
+	{ 85500000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
+	{ 83500000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 92812500, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 74250000, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
+	{ 65000000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
+	{ 33750000, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
 	  1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 40000000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 27000000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
+	{ 25175000, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
 };
 
@@ -895,10 +895,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
 	regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
 }
 
-static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
+static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,
 				      struct ropll_config *cfg)
 {
-	const unsigned int fout = data_rate / 2, fref = 24000;
+	const unsigned int fout = rate / 200, fref = 24000;
 	unsigned long k = 0, lc, k_sub, lc_sub;
 	unsigned int fvco, sdc;
 	u32 mdiv, sdiv, n = 8;
@@ -969,33 +969,32 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
 
 static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 {
-	unsigned int rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
 	int ret, i;
 
-	if (!rate)
+	if (!hdptx->hdmi_cfg.tmds_char_rate)
 		return 0;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].bit_rate) {
+		if (hdptx->hdmi_cfg.tmds_char_rate == ropll_tmds_cfg[i].rate) {
 			cfg = &ropll_tmds_cfg[i];
 			break;
 		}
 
 	if (!cfg) {
-		if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
+		if (rk_hdptx_phy_clk_pll_calc(hdptx->hdmi_cfg.tmds_char_rate, &rc)) {
 			cfg = &rc;
 		} else {
-			dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%u\n",
-				__func__, rate);
+			dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%llu\n",
+				__func__, hdptx->hdmi_cfg.tmds_char_rate);
 			return -EINVAL;
 		}
 	}
 
-	dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
-		cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
-		cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
+	dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
+		__func__, hdptx->hdmi_cfg.tmds_char_rate, cfg->pms_mdiv, cfg->pms_sdiv + 1,
+		cfg->sdm_en, cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
 
 	rk_hdptx_pre_power_up(hdptx);
 
@@ -1483,18 +1482,17 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
 static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 					   struct phy_configure_opts_hdmi *hdmi)
 {
-	u32 bit_rate = hdmi->tmds_char_rate / 100;
 	int i;
 
 	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
 		return -EINVAL;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+		if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
 			break;
 
 	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+	    !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
 		return -EINVAL;
 
 	if (!hdmi->bpc)

-- 
2.48.1



From will at kernel.org  Mon Mar  3 17:56:35 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 4 Mar 2025 01:56:35 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <Z8ZPBZF7J-qKdb_i@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
 <Z8ZPBZF7J-qKdb_i@google.com>
Message-ID: <20250304015633.GA30882@willie-the-truck>

On Tue, Mar 04, 2025 at 12:53:25AM +0000, Sebastian Ene wrote:
> On Mon, Mar 03, 2025 at 11:43:03PM +0000, Will Deacon wrote:
> > On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> > > Map the hypervisor's buffers irrespective to the host and return
> > > a linux error code from the FF-A error code on failure. Remove
> > > the unmap ff-a buffers calls from the hypervisor as it will
> > > never be called.
> > > Prevent the host from using FF-A directly with Trustzone
> > > if the hypervisor could not map its own buffers.
> > > 
> > > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > > ---
> > >  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
> > >  1 file changed, 17 insertions(+), 29 deletions(-)
> > 
> > [...]
> > 
> > > @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
> > >  {
> > >  	struct arm_smccc_res res;
> > >  	void *tx, *rx;
> > > +	int ret;
> > >  
> > >  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
> > >  		return 0;
> > > @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
> > >  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
> > >  	};
> > >  
> > > +	/* Map our hypervisor buffers into the SPMD */
> > > +	ret = ffa_map_hyp_buffers();
> > > +	if (ret)
> > > +		return ret;
> > 
> > Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
> > arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
> > the host to negotiate the version lazily?
> 
> We still have the same behaviour where we don't allow memory
> sharing to happen until the version is negotiated but this
> separates the hypervisor buffer mapping part from the host.

Sadly, the spec doesn't restrict this to the memory sharing calls:

  | [...] negotiation of the version must happen before an invocation of
  | any other FF-A ABI

We're also probing the minimum rxtx size in hyp_ffa_post_init() so doing
this here is doubly wrong.

So I think we should probably just drop this patch.

Will


From dingwei at marvell.com  Mon Mar  3 18:17:15 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Tue, 4 Mar 2025 02:17:15 +0000
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
Message-ID: <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Saturday, March 1, 2025 5:46 AM
> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
> Subject: Re: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
> reset controller node
> 
> On 28/02/2025 21:18, Wilson Ding wrote:
> >
> >
> >> -----Original Message-----
> >> From: Krzysztof Kozlowski <krzk at kernel.org>
> >> Sent: Thursday, February 27, 2025 10:57 PM
> >> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> >> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> >> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> >> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
> >> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
> >> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
> >> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
> reset
> >> controller node
> >>
> >> On 27/02/2025 20:?25, Wilson Ding wrote: > Add the reset controller node
> as
> >> a sub-node to the system controller > node. > > Signed-off-by: Wilson Ding
> >> <dingwei@?marvell.?com> > --- > arch/arm64/boot/dts/marvell/armada-
> >> cp11x.?dtsi
> >>
> >> On 27/02/2025 20:25, Wilson Ding wrote:
> >>> Add the reset controller node as a sub-node to the system controller
> >>> node.
> >>>
> >>> Signed-off-by: Wilson Ding <dingwei at marvell.com>
> >>> ---
> >>>  arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 8 ++++++++
> >>>  1 file changed, 8 insertions(+)
> >>>
> >>> diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >> b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>> index 161beec0b6b0..c27058d1534e 100644
> >>> --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>> +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>> @@ -226,6 +226,8 @@ CP11X_LABEL(rtc): rtc at 284000 {
> >>>  		CP11X_LABEL(syscon0): system-controller at 440000 {
> >>>  			compatible = "syscon", "simple-mfd";
> >>>  			reg = <0x440000 0x2000>;
> >>> +			#address-cells = <1>;
> >>> +			#size-cells = <1>;
> >>>
> >>>  			CP11X_LABEL(clk): clock {
> >>
> >> Wait, no unit address here.
> >
> > This subnode came from the existing code. I didn't touch this subnode
> > in my patch. As you can see, the system-controller has a wide address
> > range, which includes clock, GPIO registers as well as the unit-softreset
> > register.
> >
> >>
> >>>  				compatible = "marvell,cp110-clock";
> >>> @@ -273,6 +275,12 @@ CP11X_LABEL(gpio2): gpio at 140 {
> >>>  					 <&CP11X_LABEL(clk) 1 17>;
> >>>  				status = "disabled";
> >>>  			};
> >>> +
> >>> +			CP11X_LABEL(swrst): reset-controller at 268 {
> >>
> >>
> >> So why here it appeared? This is wrong and not even necessary. Entire
> >> child should be folded into parent, so finally you will fix the
> >> incomplete parent compatible.
> >
> > We do need the reset-controller as a subnode under system-controller node
> > for the following reasons:
> >
> > - We need to have 'reg' property in this subnode so that we can get the
> offset
> >   to system-controller register base defined in parent node. This is suggested
> >   by Rob in V2 comments.
> >   And we need to know the register size to calculate the number of reset
> lines.
> >   This is suggested by Philipp in V1 comments.
> 
> You do not need and you received that comment as well. It is implied by
> compatible.
> 
> >
> > - We also need to define the 'reset-cells' in this subnode. And the consumer
> of
> >   the reset controller uses the label of this subnode for the phandle and reset
> >   specifier pair.
> 
> reset-cells will be in the parent once you fold it.
> 
> >
> > As I mentioned in my reply to the first comment, the reset-controller is not
> the
> > only device within the system-controller register spaces. Do you still think I
> 
> You provided very little hardware description of the device. So based on
> hardware description you provided: yes.
> 
> > should fold it into the parent node. And what I proposed is exactly same as
> > that the armada_thermal driver did (See below). I wonder why what was
> accepted
> > in the past become not accepted now.
> 
> We did not discuss here drivers, but if you insist talking about
> "marvell,armada-cp110-thermal" then point me to review or ack from DT
> people. You claim it was accepted so how did we accept it?
> 

I didn't intend to extend discussion to the driver in this thread. The following
Is the review thread of the dt-binding for the thermal device (in 2018).
Indeed, there is no comments challenging why not fold the thermal sub-node
Into the parent 'syscon' node.

https://lore.kernel.org/linux-arm-kernel/20180703211335.GA8858 at rob-hp-laptop/

Digging further, I found some interesting history about the parent 'syscon' node
of the reset-controller. I'd appreciate if you can take a look into the following
patches/thread -

The syscon0 node was initially added along with Armada clock driver support.
It was the very beginning of the upstream for Armada SoCs support (2016).
And the clock driver is one of the earliest drivers to be mainlined. At that time,
the clock controller is the only supported device within sycon register range.
As you can see, the clock dt-binding was exactly aligned with what your suggested
(no sub-node, compatible and clock-cells just in syscon). 

https://lore.kernel.org/all/1460648013-31320-5-git-send-email-thomas.petazzoni at free-electrons.com/

Besides the clock controller, the system controller also includes the GPIO controller,
pinctl controller, reset controller and other miscellaneous configurations. Before
adding the pinctl dt-binding, it's decided to use the sub-nodes to present the multiple
function blocks of various devices.

https://lore.kernel.org/all/b27495e10fb4f4d8a7fd1a760d49402bbae83b58.1496328934.git-series.gregory.clement at free-electrons.com/

In the following patch, it was clearly addressed why sub-nodes was chosen
over one flat node.

https://lore.kernel.org/all/bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-series.gregory.clement at free-electrons.com/

"The initial intent when the binding of the cp110 system controller was to
have one flat node. The idea being that what is currently a clock-only
driver in drivers would become a MFD driver, exposing the clock, GPIO and
pinctrl functionality. However, after taking a step back, this would lead
to a messy binding. Indeed, a single node would be a GPIO controller,
clock controller, pinmux controller, and more.

This patch adopts a more classical solution of a top-level syscon node
with sub-nodes for the individual devices. The main benefit will be to
have each functional block associated to its own sub-node where we can
put its own properties."

Since then, the dt-binding of Armada's system controller became an
exception. But I think it's sensible. If we do put all these controllers into
one node, you can image the properties of different devices will be
messed up, e.g., not just #reset-cells, #clock-cells and #gpio-cells will
be gathered. There will be a long compatible list of all devices.

Going back to my current patch - if we fold the reset controller into the
parent node, the syscon node will become a hybrid, which GPIO and 
clock controller are still sub-nodes while reset controller is folded into
the syscon node. Isn't it very confusing?

> It was 2013 so that's another answer: many things done 12 years ago were
> done not according to best practices. Also best practices evolved.
> 
> Best regards,
> Krzysztof

From cristian.ciocaltea at collabora.com  Mon Mar  3 17:44:06 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 04 Mar 2025 03:44:06 +0200
Subject: [PATCH v4 07/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
Message-ID: <20250304-phy-sam-hdptx-bpc-v4-7-8657847c13f7@collabora.com>

The current workaround to setup the TMDS character rate relies on the
unconventional usage of phy_set_bus_width().

Make use of the recently introduced HDMI PHY configuration API to
properly handle the setup.  The workaround will be dropped as soon as
the switch has been completed on both ends.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 54 ++++++++++++++++-------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 2bf525514c1991a1299265d12e1e85f66333c604..7e1d1c10758249aa5bbddbdaae0108bba04f30df 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -394,6 +394,7 @@ struct rk_hdptx_phy {
 
 	int phy_id;
 	struct phy *phy;
+	struct phy_configure_opts_hdmi hdmi_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];
@@ -1409,19 +1410,25 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
 static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
-	int bus_width = phy_get_bus_width(hdptx->phy);
 	enum phy_mode mode = phy_get_mode(phy);
+	unsigned int rate = 0;
 	int ret, lane;
 
-	/*
-	 * FIXME: Temporary workaround to pass pixel_clk_rate
-	 * from the HDMI bridge driver until phy_configure_opts_hdmi
-	 * becomes available in the PHY API.
-	 */
-	unsigned int rate = bus_width & 0xfffffff;
-
-	dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
-		__func__, bus_width, rate);
+	if (mode != PHY_MODE_DP) {
+		if (!hdptx->hdmi_cfg.tmds_char_rate) {
+			/*
+			 * FIXME: Temporary workaround to setup TMDS char rate
+			 * from the RK DW HDMI QP bridge driver.
+			 * Will be removed as soon the switch to the HDMI PHY
+			 * configuration API has been completed on both ends.
+			 */
+			rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+			hdptx->hdmi_cfg.tmds_char_rate = rate * 100;
+		} else {
+			rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
+		}
+		dev_dbg(hdptx->dev, "%s rate=%u\n", __func__, rate);
+	}
 
 	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
 	if (ret)
@@ -1469,8 +1476,17 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
 	return rk_hdptx_phy_consumer_put(hdptx, false);
 }
 
-static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
-				      struct phy_configure_opts_dp *dp)
+static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
+					   struct phy_configure_opts_hdmi *hdmi)
+{
+	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rk_hdptx_phy_verify_dp_config(struct rk_hdptx_phy *hdptx,
+					 struct phy_configure_opts_dp *dp)
 {
 	int i;
 
@@ -1730,12 +1746,18 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	enum phy_mode mode = phy_get_mode(phy);
 	int ret;
 
-	if (mode != PHY_MODE_DP)
-		return 0;
+	if (mode != PHY_MODE_DP) {
+		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+		if (ret)
+			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
+		else
+			hdptx->hdmi_cfg = opts->hdmi;
+		return ret;
+	}
 
-	ret = rk_hdptx_phy_verify_config(hdptx, &opts->dp);
+	ret = rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
 	if (ret) {
-		dev_err(hdptx->dev, "invalid params for phy configure\n");
+		dev_err(hdptx->dev, "invalid dp params for phy configure\n");
 		return ret;
 	}
 

-- 
2.48.1



From martin.petersen at oracle.com  Mon Mar  3 18:26:02 2025
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Mon, 03 Mar 2025 21:26:02 -0500
Subject: [PATCH -next] scsi: ufs: rockchip: Simplify bool conversion
In-Reply-To: <20250226021157.77934-1-jiapeng.chong@linux.alibaba.com> (Jiapeng
	Chong's message of "Wed, 26 Feb 2025 10:11:57 +0800")
References: <20250226021157.77934-1-jiapeng.chong@linux.alibaba.com>
Message-ID: <yq1wmd5ttu3.fsf@ca-mkp.ca.oracle.com>


Jiapeng,

> ./drivers/ufs/host/ufs-rockchip.c:268:70-75: WARNING: conversion to bool not needed here.

Applied to 6.15/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering


From leilk.liu at mediatek.com  Mon Mar  3 18:37:15 2025
From: leilk.liu at mediatek.com (Leilk Liu)
Date: Tue, 4 Mar 2025 10:37:15 +0800
Subject: [PATCH v2] spi: mt65xx: add PM QoS support
Message-ID: <20250304024045.7788-1-leilk.liu@mediatek.com>

Enable Quality of Service(QoS) support to speed up interrupt service
routine handle. Sometimes, a gic interrupt will be generated after
SPI transmission, but at this time the CPU is in an idle state and the
processing handler will be very slow. It takes time to exit the idle state
and then become active. This will cause the SPI handler to execute slowly
and cause SPI transfer timeouts.

Signed-off-by: Leilk Liu <leilk.liu at mediatek.com>
---
v2: 
 1. add qos_request description in mtk_spi
---
 drivers/spi/spi-mt65xx.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 197bf2dbe5de..4b0a1c0db041 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -20,6 +20,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-mem.h>
 #include <linux/dma-mapping.h>
+#include <linux/pm_qos.h>
 
 #define SPI_CFG0_REG			0x0000
 #define SPI_CFG1_REG			0x0004
@@ -147,6 +148,7 @@ struct mtk_spi_compatible {
  * @tx_sgl_len:		Size of TX DMA transfer
  * @rx_sgl_len:		Size of RX DMA transfer
  * @dev_comp:		Device data structure
+ * @qos_request:	QoS request
  * @spi_clk_hz:		Current SPI clock in Hz
  * @spimem_done:	SPI-MEM operation completion
  * @use_spimem:		Enables SPI-MEM
@@ -166,6 +168,7 @@ struct mtk_spi {
 	struct scatterlist *tx_sgl, *rx_sgl;
 	u32 tx_sgl_len, rx_sgl_len;
 	const struct mtk_spi_compatible *dev_comp;
+	struct pm_qos_request qos_request;
 	u32 spi_clk_hz;
 	struct completion spimem_done;
 	bool use_spimem;
@@ -356,6 +359,7 @@ static int mtk_spi_hw_init(struct spi_controller *host,
 	struct mtk_chip_config *chip_config = spi->controller_data;
 	struct mtk_spi *mdata = spi_controller_get_devdata(host);
 
+	cpu_latency_qos_update_request(&mdata->qos_request, 500);
 	cpha = spi->mode & SPI_CPHA ? 1 : 0;
 	cpol = spi->mode & SPI_CPOL ? 1 : 0;
 
@@ -459,6 +463,15 @@ static int mtk_spi_prepare_message(struct spi_controller *host,
 	return mtk_spi_hw_init(host, msg->spi);
 }
 
+static int mtk_spi_unprepare_message(struct spi_controller *host,
+				     struct spi_message *message)
+{
+	struct mtk_spi *mdata = spi_controller_get_devdata(host);
+
+	cpu_latency_qos_update_request(&mdata->qos_request, PM_QOS_DEFAULT_VALUE);
+	return 0;
+}
+
 static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
 {
 	u32 reg_val;
@@ -1143,6 +1156,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
 
 	host->set_cs = mtk_spi_set_cs;
 	host->prepare_message = mtk_spi_prepare_message;
+	host->unprepare_message = mtk_spi_unprepare_message;
 	host->transfer_one = mtk_spi_transfer_one;
 	host->can_dma = mtk_spi_can_dma;
 	host->setup = mtk_spi_setup;
@@ -1249,6 +1263,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
 		clk_disable_unprepare(mdata->spi_hclk);
 	}
 
+	cpu_latency_qos_add_request(&mdata->qos_request, PM_QOS_DEFAULT_VALUE);
+
 	if (mdata->dev_comp->need_pad_sel) {
 		if (mdata->pad_num != host->num_chipselect)
 			return dev_err_probe(dev, -EINVAL,
@@ -1292,6 +1308,7 @@ static void mtk_spi_remove(struct platform_device *pdev)
 	struct mtk_spi *mdata = spi_controller_get_devdata(host);
 	int ret;
 
+	cpu_latency_qos_remove_request(&mdata->qos_request);
 	if (mdata->use_spimem && !completion_done(&mdata->spimem_done))
 		complete(&mdata->spimem_done);
 
-- 
2.46.0



From menglong8.dong at gmail.com  Mon Mar  3 19:06:55 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 11:06:55 +0800
Subject: [PATCH bpf-next v3 3/4] x86: implement per-function metadata
 storage for x86
In-Reply-To: <CADxym3ZJf3TEMwCy4JVT1gs9GP=U1n1qss3ycnuMZVyp9TfDdw@mail.gmail.com>
References: <20250303065345.229298-1-dongml2@chinatelecom.cn>
 <20250303065345.229298-4-dongml2@chinatelecom.cn> <20250303110559.5a584602@gandalf.local.home>
 <CADxym3ZJf3TEMwCy4JVT1gs9GP=U1n1qss3ycnuMZVyp9TfDdw@mail.gmail.com>
Message-ID: <CADxym3bNxGb-FPtkbjiLfEXBRnVT7HBM8nbQBWvcHoLhYrKKgw@mail.gmail.com>

On Tue, Mar 4, 2025 at 10:07?AM Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> On Tue, Mar 4, 2025 at 12:05?AM Steven Rostedt <rostedt at goodmis.org> wrote:
> >
> > On Mon,  3 Mar 2025 14:53:44 +0800
> > Menglong Dong <menglong8.dong at gmail.com> wrote:
> >
> > > In the third case, we make the kernel function 32 bytes aligned, and there
> > > will be 32 bytes padding before the functions. According to my testing,
> > > the text size didn't increase on this case, which is weird.
> > >
> > > With 16-bytes padding:
> > >
> > > -rwxr-xr-x 1 401190688  x86-dev/vmlinux*
> > > -rw-r--r-- 1    251068  x86-dev/vmlinux.a
> > > -rw-r--r-- 1 851892992  x86-dev/vmlinux.o
> > > -rw-r--r-- 1  12395008  x86-dev/arch/x86/boot/bzImage
> > >
> > > With 32-bytes padding:
> > >
> > > -rwxr-xr-x 1 401318128 x86-dev/vmlinux*
> > > -rw-r--r-- 1    251154 x86-dev/vmlinux.a
> > > -rw-r--r-- 1 853636704 x86-dev/vmlinux.o
> > > -rw-r--r-- 1  12509696 x86-dev/arch/x86/boot/bzImage
> >
> > Use the "size" command to see the differences in sizes and not the file size.
> >
> > $ size vmlinux
> >    text    data     bss     dec     hex filename
> > 36892658        9798658 16982016        63673332        3cb93f4 vmlinux
>
> Great! It seems that the way I tested has something wrong. I'll
> compare the text size with "size" command later.

With the size command, the text size with 32-bytes padding is:

  text    data     bss     dec     hex filename
48299471        14776173        18345936        81421580
4da650c x86-dev/vmlinux

And with 16-bytes padding is:

  text    data     bss     dec     hex filename
46620640        14772017        18458396        79851053
4c26e2d x86-dev/vmlinux

It increases about 3%, which I think is acceptable in this case.

I'll post the message in the commit log of the next version.

Thanks!
Menglong Dong

>
> Thanks!
> Menglong Dong
>
> >
> > -- Steve


From kpark3469 at gmail.com  Mon Mar  3 20:26:34 2025
From: kpark3469 at gmail.com (kpark3469 at gmail.com)
Date: Tue,  4 Mar 2025 08:26:34 +0400
Subject: [PATCH v2] arm64: kaslr: warning linear region randomization on failure
In-Reply-To: <CAMj1kXHyZ5_+ZrcRtdx4X8LA+mzCNcXUZM_3QcEudYGbuGBq0w@mail.gmail.com>
References: <CAMj1kXHyZ5_+ZrcRtdx4X8LA+mzCNcXUZM_3QcEudYGbuGBq0w@mail.gmail.com>
Message-ID: <20250304042634.591375-1-kpark3469@gmail.com>

From: Keuno Park <keun-o.park at katim.com>

On systems using 4KB pages and having 39 VA_BITS, linear_region_size
gets 256GiB space. It was observed that some SoCs such as Qualcomm
QCM8550 returns 40bits of PA range from MMFR0_EL1. This leads range
value to have minus as the variable range is s64, so that all the
calculations for randomizing linear address space are skipped.
As a result of this, the kernel's linear region is not randomized.
For hotplug memory users, kernel needs to inform that linear region
is not randomized. However, if CONFIG_MEMORY_HOTPLUG is turned off,
then kernel tries to fall back to the legacy way to randomize linear
region.

Change-Id: Ib29e45f44928937881d514fb87b4cac828b5a3f5
Fixes: 97d6786e0669 ("arm64: mm: account for hotplug memory when randomizing the linear region")
Signed-off-by: Keuno Park <keun-o.park at katim.com>
---
 arch/arm64/mm/init.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 9c0b8d9558fc..848790a9e75e 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -290,6 +290,17 @@ void __init arm64_memblock_init(void)
 		s64 range = linear_region_size -
 			    BIT(id_aa64mmfr0_parange_to_phys_shift(parange));
 
+		if (range < 0) {
+			if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) {
+				WARN(true, "linear region is not randomized due to bigger parange\n");
+			} else {
+				pr_warn("falling back to the range considering on-boot DRAM size\n");
+				range = linear_region_size -
+					(memblock_end_of_DRAM() -
+					 memblock_start_of_DRAM());
+			}
+		}
+
 		/*
 		 * If the size of the linear region exceeds, by a sufficient
 		 * margin, the size of the region that the physical memory can
-- 
2.34.1



From gshan at redhat.com  Mon Mar  3 20:35:08 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 14:35:08 +1000
Subject: [PATCH v7 18/45] arm64: RME: Handle RMI_EXIT_RIPAS_CHANGE
In-Reply-To: <20250213161426.102987-19-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-19-steven.price@arm.com>
Message-ID: <b89caaaf-3d26-4ca4-b395-08bf3f90dd1f@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> The guest can request that a region of it's protected address space is
> switched between RIPAS_RAM and RIPAS_EMPTY (and back) using
> RSI_IPA_STATE_SET. This causes a guest exit with the
> RMI_EXIT_RIPAS_CHANGE code. We treat this as a request to convert a
> protected region to unprotected (or back), exiting to the VMM to make
> the necessary changes to the guest_memfd and memslot mappings. On the
> next entry the RIPAS changes are committed by making RMI_RTT_SET_RIPAS
> calls.
> 
> The VMM may wish to reject the RIPAS change requested by the guest. For
> now it can only do with by no longer scheduling the VCPU as we don't
> currently have a usecase for returning that rejection to the guest, but
> by postponing the RMI_RTT_SET_RIPAS changes to entry we leave the door
> open for adding a new ioctl in the future for this purpose.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> New patch for v7: The code was previously split awkwardly between two
> other patches.
> ---
>   arch/arm64/kvm/rme.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 87 insertions(+)
> 

With the following comments addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> index 507eb4b71bb7..f965869e9ef7 100644
> --- a/arch/arm64/kvm/rme.c
> +++ b/arch/arm64/kvm/rme.c
> @@ -624,6 +624,64 @@ void kvm_realm_unmap_range(struct kvm *kvm, unsigned long start, u64 size,
>   		realm_unmap_private_range(kvm, start, end);
>   }
>   
> +static int realm_set_ipa_state(struct kvm_vcpu *vcpu,
> +			       unsigned long start,
> +			       unsigned long end,
> +			       unsigned long ripas,
> +			       unsigned long *top_ipa)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	struct realm *realm = &kvm->arch.realm;
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +	phys_addr_t rd_phys = virt_to_phys(realm->rd);
> +	phys_addr_t rec_phys = virt_to_phys(rec->rec_page);
> +	struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
> +	unsigned long ipa = start;
> +	int ret = 0;
> +
> +	while (ipa < end) {
> +		unsigned long next;
> +
> +		ret = rmi_rtt_set_ripas(rd_phys, rec_phys, ipa, end, &next);
> +

This doesn't look correct to me. Looking at RMM::smc_rtt_set_ripas(), it's possible
the SMC call is returned without updating 'next' to a valid address. In this case,
the garbage content resident in 'next' can be used to updated to 'ipa' in next
iternation. So we need to initialize it in advance, like below.

	unsigned long ipa = start;
	unsigned long next = start;

	while (ipa < end) {
		ret = rmi_rtt_set_ripas(rd_phys, rec_phys, ipa, end, &next);

> +		if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> +			int walk_level = RMI_RETURN_INDEX(ret);
> +			int level = find_map_level(realm, ipa, end);
> +
> +			/*
> +			 * If the RMM walk ended early then more tables are
> +			 * needed to reach the required depth to set the RIPAS.
> +			 */
> +			if (walk_level < level) {
> +				ret = realm_create_rtt_levels(realm, ipa,
> +							      walk_level,
> +							      level,
> +							      memcache);
> +				/* Retry with RTTs created */
> +				if (!ret)
> +					continue;
> +			} else {
> +				ret = -EINVAL;
> +			}
> +
> +			break;
> +		} else if (RMI_RETURN_STATUS(ret) != RMI_SUCCESS) {
> +			WARN(1, "Unexpected error in %s: %#x\n", __func__,
> +			     ret);
> +			ret = -EINVAL;

			ret = -ENXIO;

> +			break;
> +		}
> +		ipa = next;
> +	}
> +
> +	*top_ipa = ipa;
> +
> +	if (ripas == RMI_EMPTY && ipa != start)
> +		realm_unmap_private_range(kvm, start, ipa);
> +
> +	return ret;
> +}
> +
>   static int realm_init_ipa_state(struct realm *realm,
>   				unsigned long ipa,
>   				unsigned long end)
> @@ -863,6 +921,32 @@ void kvm_destroy_realm(struct kvm *kvm)
>   	kvm_free_stage2_pgd(&kvm->arch.mmu);
>   }
>   
> +static void kvm_complete_ripas_change(struct kvm_vcpu *vcpu)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +	unsigned long base = rec->run->exit.ripas_base;
> +	unsigned long top = rec->run->exit.ripas_top;
> +	unsigned long ripas = rec->run->exit.ripas_value;
> +	unsigned long top_ipa;
> +	int ret;
> +

Some checks are needed here to ensure the addresses (@base and @top) falls inside
the protected (private) space for two facts: (1) Those parameters originates from
the guest, which can be misbehaving. (2) RMM::smc_rtt_set_ripas() isn't limited to
the private space, meaning it also can change RIPAS for the ranges in the shared
space.

> +	do {
> +		kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_page_cache,
> +					   kvm_mmu_cache_min_pages(vcpu->arch.hw_mmu));
> +		write_lock(&kvm->mmu_lock);
> +		ret = realm_set_ipa_state(vcpu, base, top, ripas, &top_ipa);
> +		write_unlock(&kvm->mmu_lock);
> +
> +		if (WARN_RATELIMIT(ret && ret != -ENOMEM,
> +				   "Unable to satisfy RIPAS_CHANGE for %#lx - %#lx, ripas: %#lx\n",
> +				   base, top, ripas))
> +			break;
> +
> +		base = top_ipa;
> +	} while (top_ipa < top);
> +}
> +
>   int kvm_rec_enter(struct kvm_vcpu *vcpu)
>   {
>   	struct realm_rec *rec = &vcpu->arch.rec;
> @@ -873,6 +957,9 @@ int kvm_rec_enter(struct kvm_vcpu *vcpu)
>   		for (int i = 0; i < REC_RUN_GPRS; i++)
>   			rec->run->enter.gprs[i] = vcpu_get_reg(vcpu, i);
>   		break;
> +	case RMI_EXIT_RIPAS_CHANGE:
> +		kvm_complete_ripas_change(vcpu);
> +		break;
>   	}
>   
>   	if (kvm_realm_state(vcpu->kvm) != REALM_STATE_ACTIVE)

Thanks,
Gavin



From akpm at linux-foundation.org  Mon Mar  3 20:46:00 2025
From: akpm at linux-foundation.org (Andrew Morton)
Date: Mon, 3 Mar 2025 20:46:00 -0800
Subject: [PATCH v9 00/20] fs/dax: Fix ZONE_DEVICE page reference counts
In-Reply-To: <xhbru4aekyfl25552le5tvifwonyuwoyioxrqxy6zkm2xlyhc5@oqxnudb4bope>
References: <cover.8068ad144a7eea4a813670301f4d2a86a8e68ec4.1740713401.git-series.apopple@nvidia.com>
	<xhbru4aekyfl25552le5tvifwonyuwoyioxrqxy6zkm2xlyhc5@oqxnudb4bope>
Message-ID: <20250303204600.cb49d2d614efcded0b28f8c1@linux-foundation.org>

On Fri, 28 Feb 2025 14:42:40 +1100 Alistair Popple <apopple at nvidia.com> wrote:

> This is essentially the same as what's currently in mm-unstable aside from
> the two updates listed below. The main thing to note is it incorporates
> Balbir's fixup which is currently in mm-unstable as c98612955016
> ("mm-allow-compound-zone-device-pages-fix-fix")
> 

Thanks, I've updated mm.git to this v9 series.


From gshan at redhat.com  Mon Mar  3 20:52:51 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 14:52:51 +1000
Subject: [PATCH v7 19/45] KVM: arm64: Handle realm MMIO emulation
In-Reply-To: <20250213161426.102987-20-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-20-steven.price@arm.com>
Message-ID: <abec92a5-0158-4d97-bfdc-03e805a4c96b@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:
> MMIO emulation for a realm cannot be done directly with the VM's
> registers as they are protected from the host. However, for emulatable
> data aborts, the RMM uses GPRS[0] to provide the read/written value.
> We can transfer this from/to the equivalent VCPU's register entry and
> then depend on the generic MMIO handling code in KVM.
> 
> For a MMIO read, the value is placed in the shared RecExit structure
> during kvm_handle_mmio_return() rather than in the VCPU's register
> entry.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v5:
>   * Inject SEA to the guest is an emulatable MMIO access triggers a data
>     abort.
>   * kvm_handle_mmio_return() - disable kvm_incr_pc() for a REC (as the PC
>     isn't under the host's control) and move the REC_ENTER_EMULATED_MMIO
>     flag setting to this location (as that tells the RMM to skip the
>     instruction).
> ---
>   arch/arm64/kvm/inject_fault.c |  4 +++-
>   arch/arm64/kvm/mmio.c         | 16 ++++++++++++----
>   arch/arm64/kvm/rme-exit.c     |  6 ++++++
>   3 files changed, 21 insertions(+), 5 deletions(-)
> 

One nitpick below, with it addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index a640e839848e..2a9682b9834f 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -165,7 +165,9 @@ static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt, u32 addr)
>    */
>   void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
>   {
> -	if (vcpu_el1_is_32bit(vcpu))
> +	if (unlikely(vcpu_is_rec(vcpu)))
> +		vcpu->arch.rec.run->enter.flags |= REC_ENTER_FLAG_INJECT_SEA;
> +	else if (vcpu_el1_is_32bit(vcpu))
>   		inject_abt32(vcpu, false, addr);
>   	else
>   		inject_abt64(vcpu, false, addr);
> diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
> index ab365e839874..bff89d47a4d5 100644
> --- a/arch/arm64/kvm/mmio.c
> +++ b/arch/arm64/kvm/mmio.c
> @@ -6,6 +6,7 @@
>   
>   #include <linux/kvm_host.h>
>   #include <asm/kvm_emulate.h>
> +#include <asm/rmi_smc.h>
>   #include <trace/events/kvm.h>
>   
>   #include "trace.h"
> @@ -136,14 +137,21 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
>   		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
>   			       &data);
>   		data = vcpu_data_host_to_guest(vcpu, data, len);
> -		vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
> +
> +		if (vcpu_is_rec(vcpu))
> +			vcpu->arch.rec.run->enter.gprs[0] = data;
> +		else
> +			vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
>   	}
>   
>   	/*
>   	 * The MMIO instruction is emulated and should not be re-executed
>   	 * in the guest.
>   	 */
> -	kvm_incr_pc(vcpu);
> +	if (vcpu_is_rec(vcpu))
> +		vcpu->arch.rec.run->enter.flags |= REC_ENTER_FLAG_EMULATED_MMIO;
> +	else
> +		kvm_incr_pc(vcpu);
>   
>   	return 1;
>   }
> @@ -162,14 +170,14 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
>   	 * No valid syndrome? Ask userspace for help if it has
>   	 * volunteered to do so, and bail out otherwise.
>   	 *
> -	 * In the protected VM case, there isn't much userspace can do
> +	 * In the protected/realm VM case, there isn't much userspace can do
>   	 * though, so directly deliver an exception to the guest.
>   	 */
>   	if (!kvm_vcpu_dabt_isvalid(vcpu)) {
>   		trace_kvm_mmio_nisv(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu),
>   				    kvm_vcpu_get_hfar(vcpu), fault_ipa);
>   
> -		if (vcpu_is_protected(vcpu)) {
> +		if (vcpu_is_protected(vcpu) || vcpu_is_rec(vcpu)) {
>   			kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
>   			return 1;
>   		}
> diff --git a/arch/arm64/kvm/rme-exit.c b/arch/arm64/kvm/rme-exit.c
> index aae1adefe1a3..c785005f821f 100644
> --- a/arch/arm64/kvm/rme-exit.c
> +++ b/arch/arm64/kvm/rme-exit.c
> @@ -25,6 +25,12 @@ static int rec_exit_reason_notimpl(struct kvm_vcpu *vcpu)
>   
>   static int rec_exit_sync_dabt(struct kvm_vcpu *vcpu)
>   {
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +
> +	if (kvm_vcpu_dabt_iswrite(vcpu) && kvm_vcpu_dabt_isvalid(vcpu))
> +		vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu),
> +			     rec->run->exit.gprs[0]);
> +

A comment may be needed to explain why GPR[0] has to be copied over. The contexnt
in GPR[0] isn't needed by all cases, being handled by kvm_handle_guest_abort().
Something like below.

	/*
	 * Copy over GPR[0] to the target GPR, preparing to handle MMIO write
	 * fault. The content to be written has been saved to GPR[0] by RMM.
	 * It's overhead to other cases like fault due to MMIO read, shared
	 * or private space access.
	 */

>   	return kvm_handle_guest_abort(vcpu);
>   }
>   

Thanks,
Gavin



From irogers at google.com  Mon Mar  3 21:02:54 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:54 -0800
Subject: [PATCH v4 00/11] perf: Support multiple system call tables in the build
Message-ID: <20250304050305.901167-1-irogers@google.com>

This work builds on the clean up of system call tables and removal of
libaudit by Charlie Jenkins <charlie at rivosinc.com>.

The system call table in perf trace is used to map system call numbers
to names and vice versa. Prior to these changes, a single table
matching the perf binary's build was present. The table would be
incorrect if tracing say a 32-bit binary from a 64-bit version of
perf, the names and numbers wouldn't match.

Change the build so that a single system call file is built and the
potentially multiple tables are identifiable from the ELF machine type
of the process being examined. To determine the ELF machine type, the
executable's maps are searched and the associated DSOs ELF headers are
read. When this fails and when live, /proc/pid/exe's ELF header is
read. Fallback to using the perf's binary type when unknown.

Remove some runtime types used by the system call tables and make
equivalents generated at build time.

v4: Add reading the e_machine from the thread's maps dsos, only read
    from /proc/pid/exe on failure and when live as requested by
    Namhyung. Add patches to add dso comments and remove unused
    dso_data variables that are unused without libunwind.

v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
    Bergmann <arnd at arndb.de> on additional optional column and MIPS
    system call numbering. Rebase past Namhyung's global system call
    statistics and add comments that they don't yet support an
    e_machine other than EM_HOST.

v2: Change the 1 element cache for the last table as suggested by
    Howard Chu, add Howard's reviewed-by tags.
    Add a comment and apology to Charlie for not doing better in
    guiding:
    https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
    After discussion on v1 and he agreed this patch series would be
    the better direction.

Ian Rogers (11):
  perf dso: Move libunwind dso_data variables into ifdef
  perf dso: kernel-doc for enum dso_binary_type
  perf syscalltbl: Remove syscall_table.h
  perf trace: Reorganize syscalls
  perf syscalltbl: Remove struct syscalltbl
  perf dso: Add support for reading the e_machine type for a dso
  perf thread: Add support for reading the e_machine type for a thread
  perf trace beauty: Add syscalltbl.sh generating all system call tables
  perf syscalltbl: Use lookup table containing multiple architectures
  perf build: Remove Makefile.syscalls
  perf syscalltbl: Mask off ABI type for MIPS system calls

 tools/perf/Makefile.perf                      |  10 +-
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/alpha/include/syscall_table.h |   2 -
 tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
 tools/perf/arch/arc/include/syscall_table.h   |   2 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
 tools/perf/arch/arm/include/syscall_table.h   |   2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
 tools/perf/arch/arm64/include/syscall_table.h |   8 -
 tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
 .../csky/entry/syscalls/Makefile.syscalls     |   3 -
 tools/perf/arch/csky/include/syscall_table.h  |   2 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
 .../entry/syscalls/Makefile.syscalls          |   3 -
 .../arch/loongarch/include/syscall_table.h    |   2 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
 .../mips/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/mips/include/syscall_table.h  |   2 -
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
 .../perf/arch/parisc/include/syscall_table.h  |   8 -
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
 .../perf/arch/powerpc/include/syscall_table.h |   8 -
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
 tools/perf/arch/riscv/include/syscall_table.h |   8 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
 .../s390/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/s390/include/syscall_table.h  |   2 -
 tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
 tools/perf/arch/sh/include/syscall_table.h    |   2 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/sparc/include/syscall_table.h |   8 -
 tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
 tools/perf/arch/x86/include/syscall_table.h   |   8 -
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
 .../perf/arch/xtensa/include/syscall_table.h  |   2 -
 tools/perf/builtin-trace.c                    | 290 +++++++++++-------
 tools/perf/scripts/Makefile.syscalls          |  61 ----
 tools/perf/scripts/syscalltbl.sh              |  86 ------
 tools/perf/trace/beauty/syscalltbl.sh         | 274 +++++++++++++++++
 tools/perf/util/dso.c                         |  54 ++++
 tools/perf/util/dso.h                         |  56 ++++
 tools/perf/util/syscalltbl.c                  | 148 ++++-----
 tools/perf/util/syscalltbl.h                  |  22 +-
 tools/perf/util/thread.c                      |  80 +++++
 tools/perf/util/thread.h                      |  14 +-
 56 files changed, 756 insertions(+), 509 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:02:55 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:55 -0800
Subject: [PATCH v4 01/11] perf dso: Move libunwind dso_data variables into ifdef
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-2-irogers@google.com>

The variables elf_base_addr, debug_frame_offset, eh_frame_hdr_addr and
eh_frame_hdr_offset are only accessed in unwind-libunwind-local.c
which is conditionally built on having libunwind support. Make the
variables conditional on libunwind support too.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb8e8f444054..dfd763a0bd9d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -154,10 +154,12 @@ struct dso_data {
 	int		 status;
 	u32		 status_seen;
 	u64		 file_size;
+#ifdef HAVE_LIBUNWIND_SUPPORT
 	u64		 elf_base_addr;
 	u64		 debug_frame_offset;
 	u64		 eh_frame_hdr_addr;
 	u64		 eh_frame_hdr_offset;
+#endif
 };
 
 struct dso_bpf_prog {
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:02:56 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:56 -0800
Subject: [PATCH v4 02/11] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-3-irogers@google.com>

There are many and non-obvious meanings to the dso_binary_type enum
values. Add kernel-doc to speed interpretting their meanings.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 53 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index dfd763a0bd9d..f3ca2a5e7670 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -20,30 +20,83 @@ struct perf_env;
 #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
 #define DSO__NAME_KCORE		"[kernel.kcore]"
 
+/**
+ * enum dso_binary_type - The kind of DSO generally associated with a memory
+ *                        region (struct map).
+ */
 enum dso_binary_type {
+	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
 	DSO_BINARY_TYPE__KALLSYMS = 0,
+	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
 	DSO_BINARY_TYPE__GUEST_KALLSYMS,
+	/** @DSO_BINARY_TYPE__VMLINUX: Path to guest kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__VMLINUX,
+	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__GUEST_VMLINUX,
+	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
 	DSO_BINARY_TYPE__JAVA_JIT,
+	/**
+	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
+	 * in the .gnu_debuglink ELF section of the dso.
+	 */
 	DSO_BINARY_TYPE__DEBUGLINK,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
+	 * the buildid cache with an elf filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
+	 * located in the buildid cache with a debug filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
+	 * with .debug suffix.
+	 */
 	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
 	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
+	 * file in /usr/lib/debug/lib rather than the expected
+	 * /usr/lib/debug/usr/lib.
+	 */
 	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
+	 * in /usr/lib/debug/.build-id/.
+	 */
 	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
 	DSO_BINARY_TYPE__KCORE,
+	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
 	DSO_BINARY_TYPE__GUEST_KCORE,
+	/**
+	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
+	 * package debug info.
+	 */
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
 	DSO_BINARY_TYPE__BPF_PROG_INFO,
+	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
 	DSO_BINARY_TYPE__BPF_IMAGE,
+	/**
+	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
+	 * instructions or optimized kprobes or ftrace trampolines.
+	 */
 	DSO_BINARY_TYPE__OOL,
+	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:02:57 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:57 -0800
Subject: [PATCH v4 03/11] perf syscalltbl: Remove syscall_table.h
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-4-irogers@google.com>

The definition of "static const char *const syscalltbl[] = {" is done
in a generated syscalls_32.h or syscalls_64.h that is architecture
dependent. In order to include the appropriate file a syscall_table.h
is found via the perf include path and it includes the syscalls_32.h
or syscalls_64.h as appropriate.

To support having multiple syscall tables, one for 32-bit and one for
64-bit, or for different architectures, an include path cannot be
used. Remove syscall_table.h because of this and inline what it does
into syscalltbl.c.

For architectures without a syscall_table.h this will cause a failure
to include either syscalls_32.h or syscalls_64.h rather than a failure
to include syscall_table.h. For architectures that only included one
or other, the behavior matches BITS_PER_LONG as previously done on
architectures supporting both syscalls_32.h and syscalls_64.h.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/arch/alpha/include/syscall_table.h     | 2 --
 tools/perf/arch/arc/include/syscall_table.h       | 2 --
 tools/perf/arch/arm/include/syscall_table.h       | 2 --
 tools/perf/arch/arm64/include/syscall_table.h     | 8 --------
 tools/perf/arch/csky/include/syscall_table.h      | 2 --
 tools/perf/arch/loongarch/include/syscall_table.h | 2 --
 tools/perf/arch/mips/include/syscall_table.h      | 2 --
 tools/perf/arch/parisc/include/syscall_table.h    | 8 --------
 tools/perf/arch/powerpc/include/syscall_table.h   | 8 --------
 tools/perf/arch/riscv/include/syscall_table.h     | 8 --------
 tools/perf/arch/s390/include/syscall_table.h      | 2 --
 tools/perf/arch/sh/include/syscall_table.h        | 2 --
 tools/perf/arch/sparc/include/syscall_table.h     | 8 --------
 tools/perf/arch/x86/include/syscall_table.h       | 8 --------
 tools/perf/arch/xtensa/include/syscall_table.h    | 2 --
 tools/perf/util/syscalltbl.c                      | 8 +++++++-
 16 files changed, 7 insertions(+), 67 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h

diff --git a/tools/perf/arch/alpha/include/syscall_table.h b/tools/perf/arch/alpha/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/alpha/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/arc/include/syscall_table.h b/tools/perf/arch/arc/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arc/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm/include/syscall_table.h b/tools/perf/arch/arm/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arm/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm64/include/syscall_table.h b/tools/perf/arch/arm64/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/arm64/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/csky/include/syscall_table.h b/tools/perf/arch/csky/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/csky/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/loongarch/include/syscall_table.h b/tools/perf/arch/loongarch/include/syscall_table.h
deleted file mode 100644
index 9d0646d3455c..000000000000
--- a/tools/perf/arch/loongarch/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscall_table_64.h>
diff --git a/tools/perf/arch/mips/include/syscall_table.h b/tools/perf/arch/mips/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/mips/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/parisc/include/syscall_table.h b/tools/perf/arch/parisc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/parisc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/powerpc/include/syscall_table.h b/tools/perf/arch/powerpc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/powerpc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/riscv/include/syscall_table.h b/tools/perf/arch/riscv/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/riscv/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/s390/include/syscall_table.h b/tools/perf/arch/s390/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/s390/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/sh/include/syscall_table.h b/tools/perf/arch/sh/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/sh/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/sparc/include/syscall_table.h b/tools/perf/arch/sparc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/sparc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/x86/include/syscall_table.h b/tools/perf/arch/x86/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/x86/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/xtensa/include/syscall_table.h b/tools/perf/arch/xtensa/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/xtensa/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 928aca4cd6e9..2f76241494c8 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -7,13 +7,19 @@
 
 #include "syscalltbl.h"
 #include <stdlib.h>
+#include <asm/bitsperlong.h>
 #include <linux/compiler.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
 #include "string2.h"
 
-#include <syscall_table.h>
+#if __BITS_PER_LONG == 64
+  #include <asm/syscalls_64.h>
+#else
+  #include <asm/syscalls_32.h>
+#endif
+
 const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
 static const char *const *syscalltbl_native = syscalltbl;
 
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:02:58 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:58 -0800
Subject: [PATCH v4 04/11] perf trace: Reorganize syscalls
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-5-irogers@google.com>

Identify struct syscall information in the syscalls table by a machine
type and syscall number, not just system call number. Having the
machine type means that 32-bit system calls can be differentiated from
64-bit ones on a machine capable of both. Having a table for all
machine types and all system call numbers would be too large, so
maintain a sorted array of system calls as they are encountered.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c | 177 ++++++++++++++++++++++++-------------
 1 file changed, 118 insertions(+), 59 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 092c5f6404ba..f7d035dc0e00 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -66,6 +66,7 @@
 #include "syscalltbl.h"
 #include "../perf.h"
 #include "trace_augment.h"
+#include "dwarf-regs.h"
 
 #include <errno.h>
 #include <inttypes.h>
@@ -86,6 +87,7 @@
 
 #include <linux/ctype.h>
 #include <perf/mmap.h>
+#include <tools/libc_compat.h>
 
 #ifdef HAVE_LIBTRACEEVENT
 #include <event-parse.h>
@@ -149,7 +151,10 @@ struct trace {
 	struct perf_tool	tool;
 	struct syscalltbl	*sctbl;
 	struct {
+		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
+		/** Size of table. */
+		size_t		table_size;
 		struct {
 			struct evsel *sys_enter,
 				*sys_exit,
@@ -1454,22 +1459,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
 	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
 }
 
-/*
- * is_exit: is this "exit" or "exit_group"?
- * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
- * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
- * nonexistent: Just a hole in the syscall table, syscall id not allocated
+/**
+ * struct syscall
  */
 struct syscall {
+	/** @e_machine: The ELF machine associated with the entry. */
+	int e_machine;
+	/** @id: id value from the tracepoint, the system call number. */
+	int id;
 	struct tep_event    *tp_format;
 	int		    nr_args;
+	/**
+	 * @args_size: sum of the sizes of the syscall arguments, anything
+	 * after that is augmented stuff: pathname for openat, etc.
+	 */
+
 	int		    args_size;
 	struct {
 		struct bpf_program *sys_enter,
 				   *sys_exit;
 	}		    bpf_prog;
+	/** @is_exit: is this "exit" or "exit_group"? */
 	bool		    is_exit;
+	/**
+	 * @is_open: is this "open" or "openat"? To associate the fd returned in
+	 * sys_exit with the pathname in sys_enter.
+	 */
 	bool		    is_open;
+	/**
+	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
+	 * syscall id not allocated.
+	 */
 	bool		    nonexistent;
 	bool		    use_btf;
 	struct tep_format_field *args;
@@ -2107,22 +2127,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
 	return 0;
 }
 
-static int trace__read_syscall_info(struct trace *trace, int id)
+static int syscall__read_info(struct syscall *sc, struct trace *trace)
 {
 	char tp_name[128];
-	struct syscall *sc;
-	const char *name = syscalltbl__name(trace->sctbl, id);
+	const char *name;
 	int err;
 
-	if (trace->syscalls.table == NULL) {
-		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
-		if (trace->syscalls.table == NULL)
-			return -ENOMEM;
-	}
-	sc = trace->syscalls.table + id;
 	if (sc->nonexistent)
 		return -EEXIST;
 
+	if (sc->name) {
+		/* Info already read. */
+		return 0;
+	}
+
+	name = syscalltbl__name(trace->sctbl, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2145,15 +2164,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 	 */
 	if (IS_ERR(sc->tp_format)) {
 		sc->nonexistent = true;
-		return PTR_ERR(sc->tp_format);
+		err = PTR_ERR(sc->tp_format);
+		sc->tp_format = NULL;
+		return err;
 	}
 
 	/*
 	 * The tracepoint format contains __syscall_nr field, so it's one more
 	 * than the actual number of syscall arguments.
 	 */
-	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
-					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
+	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
 		return -ENOMEM;
 
 	sc->args = sc->tp_format->format.fields;
@@ -2442,13 +2462,67 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
+static void syscall__init(struct syscall *sc, int e_machine, int id)
+{
+	memset(sc, 0, sizeof(*sc));
+	sc->e_machine = e_machine;
+	sc->id = id;
+}
+
+static void syscall__exit(struct syscall *sc)
+{
+	if (!sc)
+		return;
+
+	zfree(&sc->arg_fmt);
+}
+
+static int syscall__cmp(const void *va, const void *vb)
+{
+	const struct syscall *a = va, *b = vb;
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
+}
+
+static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
+{
+	struct syscall key = {
+		.e_machine = e_machine,
+		.id = id,
+	};
+	struct syscall *sc, *tmp;
+
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	if (sc)
+		return sc;
+
+	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
+			   sizeof(struct syscall));
+	if (!tmp)
+		return NULL;
+
+	trace->syscalls.table = tmp;
+	sc = &trace->syscalls.table[trace->syscalls.table_size++];
+	syscall__init(sc, e_machine, id);
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	      syscall__cmp);
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	return sc;
+}
+
 typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
 				  union perf_event *event,
 				  struct perf_sample *sample);
 
-static struct syscall *trace__syscall_info(struct trace *trace,
-					   struct evsel *evsel, int id)
+static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
+					   int e_machine, int id)
 {
+	struct syscall *sc;
 	int err = 0;
 
 	if (id < 0) {
@@ -2473,28 +2547,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
 
 	err = -EINVAL;
 
-	if (id > trace->sctbl->syscalls.max_id) {
-		goto out_cant_read;
-	}
-
-	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
-	    (err = trace__read_syscall_info(trace, id)) != 0)
-		goto out_cant_read;
+	sc = trace__find_syscall(trace, e_machine, id);
+	if (sc)
+		err = syscall__read_info(sc, trace);
 
-	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
-		goto out_cant_read;
-
-	return &trace->syscalls.table[id];
-
-out_cant_read:
-	if (verbose > 0) {
+	if (err && verbose > 0) {
 		char sbuf[STRERR_BUFSIZE];
-		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
-		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
-			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
+
+		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
+			str_error_r(-err, sbuf, sizeof(sbuf)));
+		if (sc && sc->name)
+			fprintf(trace->output, "(%s)", sc->name);
 		fputs(" information\n", trace->output);
 	}
-	return NULL;
+	return err ? NULL : sc;
 }
 
 struct syscall_stats {
@@ -2643,14 +2709,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
 	return NULL;
 }
 
-static void syscall__exit(struct syscall *sc)
-{
-	if (!sc)
-		return;
-
-	zfree(&sc->arg_fmt);
-}
-
 static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 			    union perf_event *event __maybe_unused,
 			    struct perf_sample *sample)
@@ -2662,7 +2720,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -2736,7 +2794,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
 	int augmented_args_size;
@@ -2811,7 +2869,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -3164,7 +3222,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		struct syscall *sc = trace__syscall_info(trace, evsel, id);
+		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -3673,7 +3731,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 
 static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 
 	if (sc == NULL)
 		return;
@@ -3684,20 +3742,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 
 static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3795,7 +3853,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 try_to_find_pair:
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, id);
+		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
@@ -3945,7 +4003,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 */
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, key);
+		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4761,7 +4819,10 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = &trace->syscalls.table[entry->syscall];
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			if (!sc)
+				continue;
+
 			printed += fprintf(fp, "   %-15s", sc->name);
 			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
 					   n, stats->nr_failures, entry->msecs, min, avg);
@@ -5218,12 +5279,10 @@ static int trace__config(const char *var, const char *value, void *arg)
 
 static void trace__exit(struct trace *trace)
 {
-	int i;
-
 	strlist__delete(trace->ev_qualifier);
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
-		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
+		for (size_t i = 0; i < trace->syscalls.table_size; i++)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:02:59 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:02:59 -0800
Subject: [PATCH v4 05/11] perf syscalltbl: Remove struct syscalltbl
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-6-irogers@google.com>

The syscalltbl held entries of system call name and number pairs,
generated from a native syscalltbl at start up. As there are gaps in
the system call number there is a notion of index into the
table. Going forward we want the system call table to be identifiable
by a machine type, for example, i386 vs x86-64. Change the interface
to the syscalltbl so (1) a (currently unused machine type of EM_HOST)
is passed (2) the index to syscall number and system call name mapping
is computed at build time.

Two tables are used for this, an array of system call number to name,
an array of system call numbers sorted by the system call name. The
sorted array doesn't store strings in part to save memory and
relocations. The index notion is carried forward and is an index into
the sorted array of system call numbers, the data structures are
opaque (held only in syscalltbl.c), and so the number of indices for a
machine type is exposed as a new API.

The arrays are computed in the syscalltbl.sh script and so no start-up
time computation and storage is necessary.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c       | 106 +++++++++++++++++------------
 tools/perf/scripts/syscalltbl.sh |  36 ++++------
 tools/perf/util/syscalltbl.c     | 113 ++++++++++---------------------
 tools/perf/util/syscalltbl.h     |  22 ++----
 4 files changed, 117 insertions(+), 160 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index f7d035dc0e00..cfc8cb8cbef8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -149,7 +149,6 @@ enum summary_mode {
 
 struct trace {
 	struct perf_tool	tool;
-	struct syscalltbl	*sctbl;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
@@ -188,6 +187,14 @@ struct trace {
 		pid_t		*entries;
 		struct bpf_map  *map;
 	}			filter_pids;
+	/*
+	 * TODO: The map is from an ID (aka system call number) to struct
+	 * syscall_stats. If there is >1 e_machine, such as i386 and x86-64
+	 * processes, then the stats here will gather wrong the statistics for
+	 * the non EM_HOST system calls. A fix would be to add the e_machine
+	 * into the key, but this would make the code inconsistent with the
+	 * per-thread version.
+	 */
 	struct hashmap		*syscall_stats;
 	double			duration_filter;
 	double			runtime_ms;
@@ -2141,7 +2148,7 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace)
 		return 0;
 	}
 
-	name = syscalltbl__name(trace->sctbl, sc->id);
+	name = syscalltbl__name(sc->e_machine, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2241,10 +2248,14 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 
 	strlist__for_each_entry(pos, trace->ev_qualifier) {
 		const char *sc = pos->s;
-		int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
+		/*
+		 * TODO: Assume more than the validation/warnings are all for
+		 * the same binary type as perf.
+		 */
+		int id = syscalltbl__id(EM_HOST, sc), match_next = -1;
 
 		if (id < 0) {
-			id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_first(EM_HOST, sc, &match_next);
 			if (id >= 0)
 				goto matches;
 
@@ -2264,7 +2275,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 			continue;
 
 		while (1) {
-			id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_next(EM_HOST, sc, &match_next);
 			if (id < 0)
 				break;
 			if (nr_allocated == nr_used) {
@@ -2720,6 +2731,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -2794,6 +2806,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
@@ -2869,6 +2882,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -3222,6 +3236,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+		/* TODO: get e_machine from thread. */
 		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
@@ -3729,9 +3744,9 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 	return trace->skel->progs.syscall_unaugmented;
 }
 
-static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
+static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 
 	if (sc == NULL)
 		return;
@@ -3740,22 +3755,22 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 	sc->bpf_prog.sys_exit  = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit  : NULL,  "exit");
 }
 
-static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
+static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3851,9 +3866,9 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc->e_machine, i);
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
@@ -3937,7 +3952,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 }
 
-static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
 {
 	int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
 	int map_exit_fd  = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
@@ -3945,27 +3960,27 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	int err = 0;
 	unsigned int beauty_array[6];
 
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int prog_fd, key = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int prog_fd, key = syscalltbl__id_at_idx(e_machine, i);
 
 		if (!trace__syscall_enabled(trace, key))
 			continue;
 
-		trace__init_syscall_bpf_progs(trace, key);
+		trace__init_syscall_bpf_progs(trace, e_machine, key);
 
 		// It'll get at least the "!raw_syscalls:unaugmented"
-		prog_fd = trace__bpf_prog_sys_enter_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_enter_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
-		prog_fd = trace__bpf_prog_sys_exit_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_exit_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
 
 		/* use beauty_map to tell BPF how many bytes to collect, set beauty_map's value here */
 		memset(beauty_array, 0, sizeof(beauty_array));
-		err = trace__bpf_sys_enter_beauty_map(trace, key, (unsigned int *)beauty_array);
+		err = trace__bpf_sys_enter_beauty_map(trace, e_machine, key, (unsigned int *)beauty_array);
 		if (err)
 			continue;
 		err = bpf_map_update_elem(beauty_map_fd, &key, beauty_array, BPF_ANY);
@@ -4001,9 +4016,9 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 * first and second arg (this one on the raw_syscalls:sys_exit prog
 	 * array tail call, then that one will be used.
 	 */
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int key = syscalltbl__id_at_idx(e_machine, i);
+		struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4449,8 +4464,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 		goto out_error_mem;
 
 #ifdef HAVE_BPF_SKEL
-	if (trace->skel && trace->skel->progs.sys_enter)
-		trace__init_syscalls_bpf_prog_array_maps(trace);
+	if (trace->skel && trace->skel->progs.sys_enter) {
+		/*
+		 * TODO: Initialize for all host binary machine types, not just
+		 * those matching the perf binary.
+		 */
+		trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
+	}
 #endif
 
 	if (trace->ev_qualifier_ids.nr > 0) {
@@ -4475,7 +4495,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	 *  So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is
 	 *  not in use.
 	 */
-	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close"));
+	/* TODO: support for more than just perf binary machine type close. */
+	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(EM_HOST, "close"));
 
 	err = trace__expand_filters(trace, &evsel);
 	if (err)
@@ -4788,7 +4809,7 @@ static struct syscall_entry *syscall__sort_stats(struct hashmap *syscall_stats)
 	return entry;
 }
 
-static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
+static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
 				  struct hashmap *syscall_stats)
 {
 	size_t printed = 0;
@@ -4819,7 +4840,7 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, e_machine, entry->syscall);
 			if (!sc)
 				continue;
 
@@ -4846,14 +4867,14 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 }
 
 static size_t thread__dump_stats(struct thread_trace *ttrace,
-				 struct trace *trace, FILE *fp)
+				 struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, ttrace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, ttrace->syscall_stats);
 }
 
-static size_t system__dump_stats(struct trace *trace, FILE *fp)
+static size_t system__dump_stats(struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, trace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, trace->syscall_stats);
 }
 
 static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
@@ -4879,7 +4900,8 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += thread__dump_stats(ttrace, trace, fp);
+	/* TODO: get e_machine from thread. */
+	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -4940,7 +4962,8 @@ static size_t trace__fprintf_total_summary(struct trace *trace, FILE *fp)
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += system__dump_stats(trace, fp);
+	/* TODO: get all system e_machines. */
+	printed += system__dump_stats(trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -5132,8 +5155,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
 			*sep = '\0';
 
 		list = 0;
-		if (syscalltbl__id(trace->sctbl, s) >= 0 ||
-		    syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
+		/* TODO: support for more than just perf binary machine type syscalls. */
+		if (syscalltbl__id(EM_HOST, s) >= 0 ||
+		    syscalltbl__strglobmatch_first(EM_HOST, s, &idx) >= 0) {
 			list = 1;
 			goto do_concat;
 		}
@@ -5286,7 +5310,6 @@ static void trace__exit(struct trace *trace)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-	syscalltbl__delete(trace->sctbl);
 	zfree(&trace->perfconfig_events);
 }
 
@@ -5435,9 +5458,8 @@ int cmd_trace(int argc, const char **argv)
 	sigaction(SIGCHLD, &sigchld_act, NULL);
 
 	trace.evlist = evlist__new();
-	trace.sctbl = syscalltbl__new();
 
-	if (trace.evlist == NULL || trace.sctbl == NULL) {
+	if (trace.evlist == NULL) {
 		pr_err("Not enough memory to run!\n");
 		err = -ENOMEM;
 		goto out;
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
index 1ce0d5aa8b50..a39b3013b103 100755
--- a/tools/perf/scripts/syscalltbl.sh
+++ b/tools/perf/scripts/syscalltbl.sh
@@ -50,37 +50,27 @@ fi
 infile="$1"
 outfile="$2"
 
-nxt=0
-
-syscall_macro() {
-    nr="$1"
-    name="$2"
-
-    echo "	[$nr] = \"$name\","
-}
-
-emit() {
-    nr="$1"
-    entry="$2"
-
-    syscall_macro "$nr" "$entry"
-}
-
-echo "static const char *const syscalltbl[] = {" > $outfile
-
 sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
 grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
 
-max_nr=0
+echo "static const char *const syscall_num_to_name[] = {" > $outfile
 # the params are: nr abi name entry compat
 # use _ for intentionally unused variables according to SC2034
 while read nr _ name _ _; do
-    emit "$nr" "$name" >> $outfile
-    max_nr=$nr
+	echo "	[$nr] = \"$name\"," >> $outfile
 done < $sorted_table
+echo "};" >> $outfile
 
-rm -f $sorted_table
+echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
 
+# When sorting by name, add a suffix of 0s upto 20 characters so that system
+# calls that differ with a numerical suffix don't sort before those
+# without. This default behavior of sort differs from that of strcmp used at
+# runtime. Use sed to strip the trailing 0s suffix afterwards.
+grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
+while read name nr; do
+	echo "	$nr,	/* $name */" >> $outfile
+done < $sorted_table
 echo "};" >> $outfile
 
-echo "#define SYSCALLTBL_MAX_ID ${max_nr}" >> $outfile
+rm -f $sorted_table
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 2f76241494c8..760ac4d0869f 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <asm/bitsperlong.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
@@ -20,112 +21,66 @@
   #include <asm/syscalls_32.h>
 #endif
 
-const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
-static const char *const *syscalltbl_native = syscalltbl;
+const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+{
+	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
+		return syscall_num_to_name[id];
+	return NULL;
+}
 
-struct syscall {
-	int id;
+struct syscall_cmp_key {
 	const char *name;
+	const char *const *tbl;
 };
 
 static int syscallcmpname(const void *vkey, const void *ventry)
 {
-	const char *key = vkey;
-	const struct syscall *entry = ventry;
+	const struct syscall_cmp_key *key = vkey;
+	const uint16_t *entry = ventry;
 
-	return strcmp(key, entry->name);
+	return strcmp(key->name, key->tbl[*entry]);
 }
 
-static int syscallcmp(const void *va, const void *vb)
+int syscalltbl__id(int e_machine __maybe_unused, const char *name)
 {
-	const struct syscall *a = va, *b = vb;
-
-	return strcmp(a->name, b->name);
+	struct syscall_cmp_key key = {
+		.name = name,
+		.tbl = syscall_num_to_name,
+	};
+	const int *id = bsearch(&key, syscall_sorted_names,
+				ARRAY_SIZE(syscall_sorted_names),
+				sizeof(syscall_sorted_names[0]),
+				syscallcmpname);
+
+	return id ? *id : -1;
 }
 
-static int syscalltbl__init_native(struct syscalltbl *tbl)
+int syscalltbl__num_idx(int e_machine __maybe_unused)
 {
-	int nr_entries = 0, i, j;
-	struct syscall *entries;
-
-	for (i = 0; i <= syscalltbl_native_max_id; ++i)
-		if (syscalltbl_native[i])
-			++nr_entries;
-
-	entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
-	if (tbl->syscalls.entries == NULL)
-		return -1;
-
-	for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
-		if (syscalltbl_native[i]) {
-			entries[j].name = syscalltbl_native[i];
-			entries[j].id = i;
-			++j;
-		}
-	}
-
-	qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
-	tbl->syscalls.nr_entries = nr_entries;
-	tbl->syscalls.max_id	 = syscalltbl_native_max_id;
-	return 0;
+	return ARRAY_SIZE(syscall_sorted_names);
 }
 
-struct syscalltbl *syscalltbl__new(void)
+int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
 {
-	struct syscalltbl *tbl = malloc(sizeof(*tbl));
-	if (tbl) {
-		if (syscalltbl__init_native(tbl)) {
-			free(tbl);
-			return NULL;
-		}
-	}
-	return tbl;
-}
-
-void syscalltbl__delete(struct syscalltbl *tbl)
-{
-	zfree(&tbl->syscalls.entries);
-	free(tbl);
-}
-
-const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
-{
-	return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
-}
-
-int syscalltbl__id(struct syscalltbl *tbl, const char *name)
-{
-	struct syscall *sc = bsearch(name, tbl->syscalls.entries,
-				     tbl->syscalls.nr_entries, sizeof(*sc),
-				     syscallcmpname);
-
-	return sc ? sc->id : -1;
-}
-
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx)
-{
-	struct syscall *syscalls = tbl->syscalls.entries;
-
-	return idx < tbl->syscalls.nr_entries ? syscalls[idx].id : -1;
+	return syscall_sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
 {
-	int i;
-	struct syscall *syscalls = tbl->syscalls.entries;
+	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
+		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
 
-	for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
-		if (strglobmatch(syscalls[i].name, syscall_glob)) {
+		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscalls[i].id;
+			return syscall_sorted_names[i];
 		}
 	}
 
 	return -1;
 }
 
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx)
 {
 	*idx = -1;
-	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+	return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx);
 }
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index 362411a6d849..2bb628eff367 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -2,22 +2,12 @@
 #ifndef __PERF_SYSCALLTBL_H
 #define __PERF_SYSCALLTBL_H
 
-struct syscalltbl {
-	struct {
-		int max_id;
-		int nr_entries;
-		void *entries;
-	} syscalls;
-};
+const char *syscalltbl__name(int e_machine, int id);
+int syscalltbl__id(int e_machine, const char *name);
+int syscalltbl__num_idx(int e_machine);
+int syscalltbl__id_at_idx(int e_machine, int idx);
 
-struct syscalltbl *syscalltbl__new(void);
-void syscalltbl__delete(struct syscalltbl *tbl);
-
-const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
-int syscalltbl__id(struct syscalltbl *tbl, const char *name);
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx);
-
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx);
 
 #endif /* __PERF_SYSCALLTBL_H */
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:00 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:00 -0800
Subject: [PATCH v4 06/11] perf dso: Add support for reading the e_machine type
 for a dso
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-7-irogers@google.com>

For ELF file dsos read the e_machine from the ELF header. For kernel
types assume the e_machine matches the perf tool. In other cases
return EM_NONE.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.c | 54 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/dso.h |  1 +
 2 files changed, 55 insertions(+)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 5c6e85fdae0d..7f2f1af4f73b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1170,6 +1170,60 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 	return data_read_write_offset(dso, machine, offset, data, size, true);
 }
 
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
+{
+	uint16_t e_machine = EM_NONE;
+	int fd;
+
+	switch (dso__binary_type(dso)) {
+	case DSO_BINARY_TYPE__KALLSYMS:
+	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
+	case DSO_BINARY_TYPE__VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_KMODULE:
+	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
+	case DSO_BINARY_TYPE__KCORE:
+	case DSO_BINARY_TYPE__GUEST_KCORE:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
+	case DSO_BINARY_TYPE__BPF_IMAGE:
+	case DSO_BINARY_TYPE__OOL:
+	case DSO_BINARY_TYPE__JAVA_JIT:
+		return EM_HOST;
+	case DSO_BINARY_TYPE__DEBUGLINK:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
+	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
+	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+		break;
+	case DSO_BINARY_TYPE__NOT_FOUND:
+	default:
+		return EM_NONE;
+	}
+
+	pthread_mutex_lock(&dso__data_open_lock);
+
+	/*
+	 * dso__data(dso)->fd might be closed if other thread opened another
+	 * file (dso) due to open file limit (RLIMIT_NOFILE).
+	 */
+	try_to_open_dso(dso, machine);
+	fd = dso__data(dso)->fd;
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
+			e_machine = EM_NONE;
+	}
+	pthread_mutex_unlock(&dso__data_open_lock);
+	return e_machine;
+}
+
 /**
  * dso__data_read_addr - Read data from dso address
  * @dso: dso object
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index f3ca2a5e7670..ba9b83db061a 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -818,6 +818,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
 off_t dso__data_size(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 			      u64 offset, u8 *data, ssize_t size);
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
 			    struct machine *machine, u64 addr,
 			    u8 *data, ssize_t size);
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:01 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:01 -0800
Subject: [PATCH v4 07/11] perf thread: Add support for reading the e_machine
 type for a thread
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-8-irogers@google.com>

First try to read the e_machine from the dsos associated with the
thread's maps. If live use the executable from /proc/pid/exe and read
the e_machine from the ELF header. On failure use EM_HOST. Change
builtin-trace syscall functions to pass e_machine from the thread
rather than EM_HOST, so that in later patches when syscalltbl can use
the e_machine the system calls are specific to the architecture.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 43 ++++++++++----------
 tools/perf/util/thread.c   | 80 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/thread.h   | 14 ++++++-
 3 files changed, 115 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index cfc8cb8cbef8..49199d753b7c 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2729,16 +2729,16 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int printed = 0;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	int augmented_args_size = 0;
+	int augmented_args_size = 0, e_machine;
 	void *augmented_args = NULL;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -2806,17 +2806,18 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	char msg[1024];
 	void *args, *augmented_args = NULL;
-	int augmented_args_size;
+	int augmented_args_size, e_machine;
 	size_t printed = 0;
 
-	if (sc == NULL)
-		return -1;
 
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		return -1;
 	ttrace = thread__trace(thread, trace);
 	/*
 	 * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
@@ -2881,15 +2882,15 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	bool duration_calculated = false;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
-	int alignment = trace->args_alignment;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	int alignment = trace->args_alignment, e_machine;
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -3236,8 +3237,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		/* TODO: get e_machine from thread. */
-		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+		int e_machine = thread ? thread__e_machine(thread, trace->host) : EM_HOST;
+		struct syscall *sc = trace__syscall_info(trace, evsel, e_machine, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -4881,6 +4882,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 {
 	size_t printed = 0;
 	struct thread_trace *ttrace = thread__priv(thread);
+	int e_machine = thread__e_machine(thread, trace->host);
 	double ratio;
 
 	if (ttrace == NULL)
@@ -4900,8 +4902,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	/* TODO: get e_machine from thread. */
-	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
+	printed += thread__dump_stats(ttrace, trace, e_machine, fp);
 
 	return printed;
 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0ffdd52d86d7..89585f53c1d5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <elf.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,6 +18,7 @@
 #include "symbol.h"
 #include "unwind.h"
 #include "callchain.h"
+#include "dwarf-regs.h"
 
 #include <api/fs/fs.h>
 
@@ -51,6 +54,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		thread__set_ppid(thread, -1);
 		thread__set_cpu(thread, -1);
 		thread__set_guest_cpu(thread, -1);
+		thread__set_e_machine(thread, EM_NONE);
 		thread__set_lbr_stitch_enable(thread, false);
 		INIT_LIST_HEAD(thread__namespaces_list(thread));
 		INIT_LIST_HEAD(thread__comm_list(thread));
@@ -423,6 +427,82 @@ void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
 	}
 }
 
+static uint16_t read_proc_e_machine_for_pid(pid_t pid)
+{
+	char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */];
+	int fd;
+	uint16_t e_machine = EM_NONE;
+
+	snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+	fd = open(path, O_RDONLY);
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
+			e_machine = EM_NONE;
+		close(fd);
+	}
+	return e_machine;
+}
+
+static int thread__e_machine_callback(struct map *map, void *machine)
+{
+	struct dso *dso = map__dso(map);
+
+	_Static_assert(0 == EM_NONE, "Unexpected EM_NONE");
+	if (!dso)
+		return EM_NONE;
+
+	return dso__e_machine(dso, machine);
+}
+
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine)
+{
+	pid_t tid, pid;
+	uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine;
+
+	if (e_machine != EM_NONE)
+		return e_machine;
+
+	tid = thread__tid(thread);
+	pid = thread__pid(thread);
+	if (pid != tid) {
+		struct thread *parent = machine__findnew_thread(machine, pid, pid);
+
+		if (parent) {
+			e_machine = thread__e_machine(parent, machine);
+			thread__set_e_machine(thread, e_machine);
+			return e_machine;
+		}
+		/* Something went wrong, fallback. */
+	}
+	/* Reading on the PID thread. First try to find from the maps. */
+	e_machine = maps__for_each_map(thread__maps(thread),
+				       thread__e_machine_callback,
+				       machine);
+	if (e_machine == EM_NONE) {
+		/* Maps failed, perhaps we're live with map events disabled. */
+		bool is_live = machine->machines == NULL;
+
+		if (!is_live) {
+			/* Check if the session has a data file. */
+			struct perf_session *session = container_of(machine->machines,
+								    struct perf_session,
+								    machines);
+
+			is_live = !!session->data;
+		}
+		/* Read from /proc/pid/exe if live. */
+		if (is_live)
+			e_machine = read_proc_e_machine_for_pid(pid);
+	}
+	if (e_machine != EM_NONE)
+		thread__set_e_machine(thread, e_machine);
+	else
+		e_machine = EM_HOST;
+	return e_machine;
+}
+
 struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
 {
 	if (thread__pid(thread) == thread__tid(thread))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 6cbf6eb2812e..cd574a896418 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -60,7 +60,11 @@ DECLARE_RC_STRUCT(thread) {
 	struct srccode_state	srccode_state;
 	bool			filter;
 	int			filter_entry_depth;
-
+	/**
+	 * @e_machine: The ELF EM_* associated with the thread. EM_NONE if not
+	 * computed.
+	 */
+	uint16_t		e_machine;
 	/* LBR call stack stitch */
 	bool			lbr_stitch_enable;
 	struct lbr_stitch	*lbr_stitch;
@@ -302,6 +306,14 @@ static inline void thread__set_filter_entry_depth(struct thread *thread, int dep
 	RC_CHK_ACCESS(thread)->filter_entry_depth = depth;
 }
 
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine);
+
+static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine)
+{
+	RC_CHK_ACCESS(thread)->e_machine = e_machine;
+}
+
+
 static inline bool thread__lbr_stitch_enable(const struct thread *thread)
 {
 	return RC_CHK_ACCESS(thread)->lbr_stitch_enable;
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:02 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:02 -0800
Subject: [PATCH v4 08/11] perf trace beauty: Add syscalltbl.sh generating all
 system call tables
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-9-irogers@google.com>

Rather than generating individual syscall header files generate a
single trace/beauty/generated/syscalltbl.c. In a syscalltbls array
have references to each architectures tables along with the
corresponding e_machine. When the 32-bit or 64-bit table is ambiguous,
match the perf binary's type. For ARM32 don't use the arm64 32-bit
table which is smaller. EM_NONE is present for is no machine matches.

Conditionally compile the tables, only having the appropriate 32 and
64-bit table. If ALL_SYSCALLTBL is defined all tables can be
compiled.

Add comment for noreturn column suggested by Arnd Bergmann:
https://lore.kernel.org/lkml/d47c35dd-9c52-48e7-a00d-135572f11fbb at app.fastmail.com/
and added in commit 9142be9e6443 ("x86/syscall: Mark exit[_group]
syscall handlers __noreturn").

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf              |   9 +
 tools/perf/trace/beauty/syscalltbl.sh | 274 ++++++++++++++++++++++++++
 2 files changed, 283 insertions(+)
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d0b50ccc9d7b..f949ec72f3d2 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -559,6 +559,14 @@ beauty_ioctl_outdir := $(beauty_outdir)/ioctl
 # Create output directory if not already present
 $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
 
+syscall_array := $(beauty_outdir)/syscalltbl.c
+syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh
+syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \
+	$(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl)
+
+$(syscall_array): $(syscall_tbl) $(syscall_tbl_data)
+	$(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@
+
 fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c
 fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh
 
@@ -878,6 +886,7 @@ build-dir   = $(or $(__build-dir),.)
 
 prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders \
 	arm64-sysreg-defs \
+	$(syscall_array) \
 	$(fs_at_flags_array) \
 	$(clone_flags_array) \
 	$(drm_ioctl_array) \
diff --git a/tools/perf/trace/beauty/syscalltbl.sh b/tools/perf/trace/beauty/syscalltbl.sh
new file mode 100755
index 000000000000..1199618dc178
--- /dev/null
+++ b/tools/perf/trace/beauty/syscalltbl.sh
@@ -0,0 +1,274 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate all syscall tables.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT [noreturn]]
+#
+# NR       syscall number
+# ABI      ABI name
+# NAME     syscall name
+# NATIVE   native entry point (optional)
+# COMPAT   compat entry point (optional)
+# noreturn system call doesn't return (optional)
+set -e
+
+usage() {
+       cat >&2 <<EOF
+usage: $0 <TOOLS DIRECTORY> <OUTFILE>
+
+  <TOOLS DIRECTORY>    path to kernel tools directory
+  <OUTFILE>            output header file
+EOF
+       exit 1
+}
+
+if [ $# -ne 2 ]; then
+       usage
+fi
+tools_dir=$1
+outfile=$2
+
+build_tables() {
+	infile="$1"
+	outfile="$2"
+	abis=$(echo "($3)" | tr ',' '|')
+	e_machine="$4"
+
+	if [ ! -f "$infile" ]
+	then
+		echo "Missing file $infile"
+		exit 1
+	fi
+	sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > "$sorted_table"
+
+	echo "static const char *const syscall_num_to_name_${e_machine}[] = {" >> "$outfile"
+	# the params are: nr abi name entry compat
+	# use _ for intentionally unused variables according to SC2034
+	while read -r nr _ name _ _; do
+		echo "	[$nr] = \"$name\"," >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	echo "static const uint16_t syscall_sorted_names_${e_machine}[] = {" >> "$outfile"
+
+	# When sorting by name, add a suffix of 0s upto 20 characters so that
+	# system calls that differ with a numerical suffix don't sort before
+	# those without. This default behavior of sort differs from that of
+	# strcmp used at runtime. Use sed to strip the trailing 0s suffix
+	# afterwards.
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > "$sorted_table"
+	while read -r name nr; do
+		echo "	$nr,	/* $name */" >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	rm -f "$sorted_table"
+}
+
+rm -f "$outfile"
+cat >> "$outfile" <<EOF
+#include <elf.h>
+#include <stdint.h>
+#include <asm/bitsperlong.h>
+#include <linux/kernel.h>
+
+struct syscalltbl {
+       const char *const *num_to_name;
+       const uint16_t *sorted_names;
+       uint16_t e_machine;
+       uint16_t num_to_name_len;
+       uint16_t sorted_names_len;
+};
+
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_tables "$tools_dir/perf/arch/alpha/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_ALPHA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_tables "$tools_dir/perf/arch/arm/entry/syscalls/syscall.tbl" "$outfile" common,32,oabi EM_ARM
+build_tables "$tools_dir/perf/arch/arm64/entry/syscalls/syscall_64.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_AARCH64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,csky,time32,stat64,rlimit EM_CSKY
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_tables "$tools_dir/perf/arch/mips/entry/syscalls/syscall_n64.tbl" "$outfile" common,64,n64 EM_MIPS
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_PARISC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_PARISC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,32,nospu EM_PPC
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,64,nospu EM_PPC64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,riscv,memfd_secret EM_RISCV
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64,riscv,rlimit,memfd_secret EM_RISCV
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_tables "$tools_dir/perf/arch/s390/entry/syscalls/syscall.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_S390
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_tables "$tools_dir/perf/arch/sh/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SH
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SPARC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_SPARC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_32.tbl" "$outfile" common,32,i386 EM_386
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_64.tbl" "$outfile" common,64 EM_X86_64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_tables "$tools_dir/perf/arch/xtensa/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_XTENSA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32 EM_NONE
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64 EM_NONE
+echo "#endif //__BITS_PER_LONG != 64" >> "$outfile"
+
+build_outer_table() {
+       e_machine=$1
+       outfile="$2"
+       cat >> "$outfile" <<EOF
+       {
+	      .num_to_name = syscall_num_to_name_$e_machine,
+	      .sorted_names = syscall_sorted_names_$e_machine,
+	      .e_machine = $e_machine,
+	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_$e_machine),
+	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_$e_machine),
+       },
+EOF
+}
+
+cat >> "$outfile" <<EOF
+static const struct syscalltbl syscalltbls[] = {
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_outer_table EM_ALPHA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_outer_table EM_ARM "$outfile"
+build_outer_table EM_AARCH64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_outer_table EM_CSKY "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_outer_table EM_MIPS "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+EOF
+build_outer_table EM_PARISC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_outer_table EM_PPC "$outfile"
+build_outer_table EM_PPC64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+EOF
+build_outer_table EM_RISCV "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_outer_table EM_S390 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_outer_table EM_SH "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+EOF
+build_outer_table EM_SPARC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_outer_table EM_386 "$outfile"
+build_outer_table EM_X86_64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_XTENSA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_NONE "$outfile"
+cat >> "$outfile" <<EOF
+};
+EOF
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:03 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:03 -0800
Subject: [PATCH v4 09/11] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-10-irogers@google.com>

Switch to use the lookup table containing all architectures rather
than tables matching the perf binary.

This fixes perf trace when executed on a 32-bit i386 binary on an
x86-64 machine. Note in the following the system call names of the
32-bit i386 binary as seen by an x86-64 perf.

Before:
```
         ? (         ): a.out/447296  ... [continued]: munmap())                                           = 0
     0.024 ( 0.001 ms): a.out/447296 recvfrom(ubuf: 0x2, size: 4160585708, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|NOSIGNAL|WAITFORONE|BATCH|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f80000, addr: 0xe30, addr_len: 0xffce438c) = 1475198976
     0.042 ( 0.003 ms): a.out/447296 lgetxattr(name: "", value: 0x3, size: 34)                             = 4160344064
     0.054 ( 0.003 ms): a.out/447296 dup2(oldfd: -134422744, newfd: 4)                                     = -1 ENOENT (No such file or directory)
     0.060 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x2e646c2f6374652f,.iov_len = (__kernel_size_t)7307199665335594867,}, vlen: 557056, pos_h: 4160585708) = 3
     0.074 ( 0.004 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2)                              = 4160237568
     0.080 ( 0.001 ms): a.out/447296 lstat(filename: "", statbuf: 0x193f6)                                 = 0
     0.089 ( 0.007 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x3833692f62696c2f,.iov_len = (__kernel_size_t)3276497845987585334,}, vlen: 557056, pos_h: 4160585708) = 3
     0.097 ( 0.002 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 512
     0.103 ( 0.002 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2050)                           = 4157935616
     0.107 ( 0.007 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x5, size: 2066)             = 4158078976
     0.116 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x1, size: 2066)             = 4159639552
     0.121 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 2066)             = 4160184320
     0.129 ( 0.002 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 50)               = 4160196608
     0.138 ( 0.001 ms): a.out/447296 lstat(filename: "")                                                   = 0
     0.145 ( 0.002 ms): a.out/447296 mq_timedreceive(mqdes: 4291706800, u_msg_ptr: 0xf7f9ea48, msg_len: 134616640, u_msg_prio: 0xf7fd7fec, u_abs_timeout: (struct __kernel_timespec){.tv_sec = (__kernel_time64_t)-578174027777317696,.tv_nsec = (long long int)4160349376,}) = 0
     0.148 ( 0.001 ms): a.out/447296 mkdirat(dfd: -134617816, pathname: " ??? ???????????", mode: IFREG|ISUID|IRUSR|IWGRP|0xf7fd0000) = 447296
     0.150 ( 0.001 ms): a.out/447296 process_vm_writev(pid: -134617812, lvec: (struct iovec){.iov_base = (void *)0xf7f9e9c8f7f9e4c0,.iov_len = (__kernel_size_t)4160349376,}, liovcnt: 4160588048, rvec: (struct iovec){}, riovcnt: 4160585708, flags: 4291707352) = 0
     0.197 ( 0.004 ms): a.out/447296 capget(header: 4160184320, dataptr: 8192)                             = 0
     0.202 ( 0.002 ms): a.out/447296 capget(header: 1448669184, dataptr: 4096)                             = 0
     0.208 ( 0.002 ms): a.out/447296 capget(header: 4160577536, dataptr: 8192)                             = 0
     0.220 ( 0.001 ms): a.out/447296 getxattr(pathname: "", name: "c??????", value: 0xf7f77e34, size: 1)  = 0
     0.228 ( 0.005 ms): a.out/447296 fchmod(fd: -134729728, mode: IRUGO|IWUGO|IFREG|IFIFO|ISVTX|IXUSR|0x10000) = 0
     0.240 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: 0x5658e008, pos_h: 4160192052)            = 3
     0.250 ( 0.008 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 1436
     0.260 ( 0.018 ms): a.out/447296 stat(filename: "", statbuf: 0xffce32ac)                               = 1436
     0.288 (1000.213 ms): a.out/447296 readlinkat(buf: 0xffce31d4, bufsiz: 4291703244)                       = 0
```

After:
```
         ? (         ): a.out/442930  ... [continued]: execve())                                           = 0
     0.023 ( 0.002 ms): a.out/442930 brk()                                                                 = 0x57760000
     0.052 ( 0.003 ms): a.out/442930 access(filename: 0xf7f5af28, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.059 ( 0.009 ms): a.out/442930 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.078 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.087 ( 0.007 ms): a.out/442930 openat(dfd: CWD, filename: "/lib/i386-linux-", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.095 ( 0.002 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdbb70, count: 512)         = 512
     0.135 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.148 ( 0.001 ms): a.out/442930 set_tid_address(tidptr: 0xf7f2b528)                                   = 442930 (a.out)
     0.150 ( 0.001 ms): a.out/442930 set_robust_list(head: 0xf7f2b52c, len: 12)                            =
     0.196 ( 0.004 ms): a.out/442930 mprotect(start: 0xf7f03000, len: 8192, prot: READ)                    = 0
     0.202 ( 0.002 ms): a.out/442930 mprotect(start: 0x5658e000, len: 4096, prot: READ)                    = 0
     0.207 ( 0.002 ms): a.out/442930 mprotect(start: 0xf7f63000, len: 8192, prot: READ)                    = 0
     0.230 ( 0.005 ms): a.out/442930 munmap(addr: 0xf7f10000, len: 103414)                                 = 0
     0.244 ( 0.010 ms): a.out/442930 openat(dfd: CWD, filename: 0x5658d008)                                = 3
     0.255 ( 0.007 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdb67c, count: 4096)        = 1436
     0.264 ( 0.018 ms): a.out/442930 write(fd: 1</dev/pts/4>, buf: , count: 1436)                          = 1436
     0.292 (1000.173 ms): a.out/442930 clock_nanosleep(rqtp: { .tv_sec: 17866546940376776704, .tv_nsec: 4159878336 }, rmtp: 0xffbdb59c) = 0
  1000.478 (         ): a.out/442930 exit_group()                                                          = ?
```

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/util/syscalltbl.c | 89 ++++++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 760ac4d0869f..db0d2b81aed1 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,16 +15,39 @@
 #include <string.h>
 #include "string2.h"
 
-#if __BITS_PER_LONG == 64
-  #include <asm/syscalls_64.h>
-#else
-  #include <asm/syscalls_32.h>
-#endif
+#include "trace/beauty/generated/syscalltbl.c"
 
-const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+static const struct syscalltbl *find_table(int e_machine)
 {
-	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
-		return syscall_num_to_name[id];
+	static const struct syscalltbl *last_table;
+	static int last_table_machine = EM_NONE;
+
+	/* Tables only exist for EM_SPARC. */
+	if (e_machine == EM_SPARCV9)
+		e_machine = EM_SPARC;
+
+	if (last_table_machine == e_machine && last_table != NULL)
+		return last_table;
+
+	for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) {
+		const struct syscalltbl *entry = &syscalltbls[i];
+
+		if (entry->e_machine != e_machine && entry->e_machine != EM_NONE)
+			continue;
+
+		last_table = entry;
+		last_table_machine = e_machine;
+		return entry;
+	}
+	return NULL;
+}
+
+const char *syscalltbl__name(int e_machine, int id)
+{
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (table && id >= 0 && id < table->num_to_name_len)
+		return table->num_to_name[id];
 	return NULL;
 }
 
@@ -41,38 +64,54 @@ static int syscallcmpname(const void *vkey, const void *ventry)
 	return strcmp(key->name, key->tbl[*entry]);
 }
 
-int syscalltbl__id(int e_machine __maybe_unused, const char *name)
+int syscalltbl__id(int e_machine, const char *name)
 {
-	struct syscall_cmp_key key = {
-		.name = name,
-		.tbl = syscall_num_to_name,
-	};
-	const int *id = bsearch(&key, syscall_sorted_names,
-				ARRAY_SIZE(syscall_sorted_names),
-				sizeof(syscall_sorted_names[0]),
-				syscallcmpname);
+	const struct syscalltbl *table = find_table(e_machine);
+	struct syscall_cmp_key key;
+	const int *id;
+
+	if (!table)
+		return -1;
+
+	key.name = name;
+	key.tbl = table->num_to_name;
+	id = bsearch(&key, table->sorted_names, table->sorted_names_len,
+		     sizeof(table->sorted_names[0]), syscallcmpname);
 
 	return id ? *id : -1;
 }
 
-int syscalltbl__num_idx(int e_machine __maybe_unused)
+int syscalltbl__num_idx(int e_machine)
 {
-	return ARRAY_SIZE(syscall_sorted_names);
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return 0;
+
+	return table->sorted_names_len;
 }
 
-int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
+int syscalltbl__id_at_idx(int e_machine, int idx)
 {
-	return syscall_sorted_names[idx];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return -1;
+
+	assert(idx >= 0 && idx < table->sorted_names_len);
+	return table->sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx)
 {
-	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
-		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) {
+		const char *name = table->num_to_name[table->sorted_names[i]];
 
 		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscall_sorted_names[i];
+			return table->sorted_names[i];
 		}
 	}
 
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:04 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:04 -0800
Subject: [PATCH v4 10/11] perf build: Remove Makefile.syscalls
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-11-irogers@google.com>

Now a single beauty file is generated and used by all architectures,
remove the per-architecture Makefiles, Kbuild files and previous
generator script.

Note: there was conversation with Charlie Jenkins
<charlie at rivosinc.com> and they'd written an alternate approach to
support multiple architectures:
https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
It would have been better to have helped Charlie fix their series (my
apologies) but they agreed that the approach taken here was likely
best for longer term maintainability:
https://lore.kernel.org/lkml/Z6Jk_UN9i69QGqUj at ghost/

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf                      |  1 -
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |  2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/arc/entry/syscalls/Kbuild     |  2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |  3 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |  4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |  2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |  3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |  6 --
 tools/perf/arch/csky/entry/syscalls/Kbuild    |  2 -
 .../csky/entry/syscalls/Makefile.syscalls     |  3 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |  2 -
 .../entry/syscalls/Makefile.syscalls          |  3 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |  2 -
 .../mips/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |  3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |  6 --
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |  3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |  6 --
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |  2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |  4 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |  2 -
 .../s390/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/sh/entry/syscalls/Kbuild      |  2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |  4 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |  3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/x86/entry/syscalls/Kbuild     |  3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |  6 --
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |  2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |  4 -
 tools/perf/scripts/Makefile.syscalls          | 61 ---------------
 tools/perf/scripts/syscalltbl.sh              | 76 -------------------
 33 files changed, 242 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index f949ec72f3d2..f3cd8de15d1a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -339,7 +339,6 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
 FEATURE_TESTS := all
 endif
 endif
-include $(srctree)/tools/perf/scripts/Makefile.syscalls
 include Makefile.config
 endif
 
diff --git a/tools/perf/arch/alpha/entry/syscalls/Kbuild b/tools/perf/arch/alpha/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls b/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 690168aac34d..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/alpha/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arc/entry/syscalls/Kbuild b/tools/perf/arch/arc/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 391d30ab7a83..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += arc time32 renameat stat64 rlimit
diff --git a/tools/perf/arch/arm/entry/syscalls/Kbuild b/tools/perf/arch/arm/entry/syscalls/Kbuild
deleted file mode 100644
index 9d777540f089..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += oabi
-syscalltbl = $(srctree)/tools/perf/arch/arm/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Kbuild b/tools/perf/arch/arm64/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e7e78c2d1c02..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/arm64/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/csky/entry/syscalls/Kbuild b/tools/perf/arch/csky/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls b/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ea2dd10d0571..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += csky time32 stat64 rlimit
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Kbuild b/tools/perf/arch/loongarch/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls b/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 47d32da2aed8..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 +=
diff --git a/tools/perf/arch/mips/entry/syscalls/Kbuild b/tools/perf/arch/mips/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls b/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9ee914bdfb05..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += n64
-
-syscalltbl = $(srctree)/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
diff --git a/tools/perf/arch/parisc/entry/syscalls/Kbuild b/tools/perf/arch/parisc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ae326fecb83b..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/parisc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Kbuild b/tools/perf/arch/powerpc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e35afbc57c79..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += nospu
-syscall_abis_64 += nospu
-
-syscalltbl = $(srctree)/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/riscv/entry/syscalls/Kbuild b/tools/perf/arch/riscv/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls b/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9668fd1faf60..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += riscv memfd_secret
-syscall_abis_64 += riscv rlimit memfd_secret
diff --git a/tools/perf/arch/s390/entry/syscalls/Kbuild b/tools/perf/arch/s390/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls b/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9762d7abf17c..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/s390/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sh/entry/syscalls/Kbuild b/tools/perf/arch/sh/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 25080390e4ed..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscalltbl = $(srctree)/tools/perf/arch/sh/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sparc/entry/syscalls/Kbuild b/tools/perf/arch/sparc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 212c1800b644..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-syscalltbl = $(srctree)/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/x86/entry/syscalls/Kbuild b/tools/perf/arch/x86/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls b/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index db3d5d6d4e56..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += i386
-syscall_abis_64 +=
-
-syscalltbl = $(srctree)/tools/perf/arch/x86/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Kbuild b/tools/perf/arch/xtensa/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls b/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index d4aa2358460c..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscalltbl = $(srctree)/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
diff --git a/tools/perf/scripts/Makefile.syscalls b/tools/perf/scripts/Makefile.syscalls
deleted file mode 100644
index 8bf55333262e..000000000000
--- a/tools/perf/scripts/Makefile.syscalls
+++ /dev/null
@@ -1,61 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# This Makefile generates headers in
-# tools/perf/arch/$(SRCARCH)/include/generated/asm from the architecture's
-# syscall table. This will either be from the generic syscall table, or from a
-# table that is specific to that architecture.
-
-PHONY := all
-all:
-
-obj := $(OUTPUT)arch/$(SRCARCH)/include/generated/asm
-
-syscall_abis_32  := common,32
-syscall_abis_64  := common,64
-syscalltbl := $(srctree)/tools/scripts/syscall.tbl
-
-# let architectures override $(syscall_abis_%) and $(syscalltbl)
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Makefile.syscalls
-include $(srctree)/tools/build/Build.include
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Kbuild
-
-systbl := $(srctree)/tools/perf/scripts/syscalltbl.sh
-
-syscall-y   := $(addprefix $(obj)/, $(syscall-y))
-
-# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
-unwanted    := $(filter-out $(syscall-y),$(old-headers))
-
-quiet_cmd_remove = REMOVE  $(unwanted)
-      cmd_remove = rm -f $(unwanted)
-
-quiet_cmd_systbl = SYSTBL  $@
-      cmd_systbl = $(CONFIG_SHELL) $(systbl) \
-		   $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \
-		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
-		   $< $@
-
-all: $(syscall-y)
-	$(if $(unwanted),$(call cmd,remove))
-	@:
-
-$(obj)/syscalls_%.h: $(syscalltbl) $(systbl) FORCE
-	$(call if_changed,systbl)
-
-targets := $(syscall-y)
-
-# Create output directory. Skip it if at least one old header exists
-# since we know the output directory already exists.
-ifeq ($(old-headers),)
-$(shell mkdir -p $(obj))
-endif
-
-PHONY += FORCE
-
-FORCE:
-
-existing-targets := $(wildcard $(sort $(targets)))
-
--include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-
-.PHONY: $(PHONY)
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
deleted file mode 100755
index a39b3013b103..000000000000
--- a/tools/perf/scripts/syscalltbl.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Generate a syscall table header.
-#
-# Each line of the syscall table should have the following format:
-#
-# NR ABI NAME [NATIVE] [COMPAT]
-#
-# NR       syscall number
-# ABI      ABI name
-# NAME     syscall name
-# NATIVE   native entry point (optional)
-# COMPAT   compat entry point (optional)
-
-set -e
-
-usage() {
-	echo >&2 "usage: $0 [--abis ABIS] INFILE OUTFILE" >&2
-	echo >&2
-	echo >&2 "  INFILE    input syscall table"
-	echo >&2 "  OUTFILE   output header file"
-	echo >&2
-	echo >&2 "options:"
-	echo >&2 "  --abis ABIS        ABI(s) to handle (By default, all lines are handled)"
-	exit 1
-}
-
-# default unless specified by options
-abis=
-
-while [ $# -gt 0 ]
-do
-	case $1 in
-	--abis)
-		abis=$(echo "($2)" | tr ',' '|')
-		shift 2;;
-	-*)
-		echo "$1: unknown option" >&2
-		usage;;
-	*)
-		break;;
-	esac
-done
-
-if [ $# -ne 2 ]; then
-	usage
-fi
-
-infile="$1"
-outfile="$2"
-
-sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
-
-echo "static const char *const syscall_num_to_name[] = {" > $outfile
-# the params are: nr abi name entry compat
-# use _ for intentionally unused variables according to SC2034
-while read nr _ name _ _; do
-	echo "	[$nr] = \"$name\"," >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
-
-# When sorting by name, add a suffix of 0s upto 20 characters so that system
-# calls that differ with a numerical suffix don't sort before those
-# without. This default behavior of sort differs from that of strcmp used at
-# runtime. Use sed to strip the trailing 0s suffix afterwards.
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
-while read name nr; do
-	echo "	$nr,	/* $name */" >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-rm -f $sorted_table
-- 
2.48.1.711.g2feabab25a-goog



From irogers at google.com  Mon Mar  3 21:03:05 2025
From: irogers at google.com (Ian Rogers)
Date: Mon,  3 Mar 2025 21:03:05 -0800
Subject: [PATCH v4 11/11] perf syscalltbl: Mask off ABI type for MIPS system calls
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <20250304050305.901167-12-irogers@google.com>

Arnd Bergmann described that MIPS system calls don't necessarily start
from 0 as an ABI prefix is applied:
https://lore.kernel.org/lkml/8ed7dfb2-1e4d-4aa4-a04b-0397a89365d1 at app.fastmail.com/
When decoding the "id" (aka system call number) for MIPS ignore values
greater-than 1000.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/syscalltbl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index db0d2b81aed1..ace66e69c1bc 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -46,6 +46,14 @@ const char *syscalltbl__name(int e_machine, int id)
 {
 	const struct syscalltbl *table = find_table(e_machine);
 
+	if (e_machine == EM_MIPS && id > 1000) {
+		/*
+		 * MIPS may encode the N32/64/O32 type in the high part of
+		 * syscall number. Mask this off if present. See the values of
+		 * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux.
+		 */
+		id = id % 1000;
+	}
 	if (table && id >= 0 && id < table->num_to_name_len)
 		return table->num_to_name[id];
 	return NULL;
-- 
2.48.1.711.g2feabab25a-goog



From patchwork-bot+netdevbpf at kernel.org  Mon Mar  3 21:10:36 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 04 Mar 2025 05:10:36 +0000
Subject: [PATCH bpf-next v6 0/6] Introduce load-acquire and store-release BPF
 instructions
In-Reply-To: <cover.1741049567.git.yepeilin@google.com>
References: <cover.1741049567.git.yepeilin@google.com>
Message-ID: <174106503648.3866937.5658954004964289425.git-patchwork-notify@kernel.org>

Hello:

This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast at kernel.org>:

On Tue,  4 Mar 2025 01:05:41 +0000 you wrote:
> Hi all!
> 
> This patchset adds kernel support for BPF load-acquire and store-release
> instructions (for background, please see [1]), including core/verifier
> and arm64/x86-64 JIT compiler changes, as well as selftests.  riscv64 is
> also planned to be supported.  The corresponding LLVM changes can be
> found at:
> 
> [...]

Here is the summary with links:
  - [bpf-next,v6,1/6] bpf: Introduce load-acquire and store-release instructions
    https://git.kernel.org/bpf/bpf-next/c/e24bbad29a8d
  - [bpf-next,v6,2/6] arm64: insn: Add BIT(23) to {load,store}_ex's mask
    https://git.kernel.org/bpf/bpf-next/c/4170a60c473d
  - [bpf-next,v6,3/6] arm64: insn: Add load-acquire and store-release instructions
    https://git.kernel.org/bpf/bpf-next/c/248b1900dd95
  - [bpf-next,v6,4/6] bpf, arm64: Support load-acquire and store-release instructions
    https://git.kernel.org/bpf/bpf-next/c/1bfe7f657cf4
  - [bpf-next,v6,5/6] bpf, x86: Support load-acquire and store-release instructions
    https://git.kernel.org/bpf/bpf-next/c/14c0427b8a09
  - [bpf-next,v6,6/6] selftests/bpf: Add selftests for load-acquire and store-release instructions
    https://git.kernel.org/bpf/bpf-next/c/953df09aa42c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From gshan at redhat.com  Mon Mar  3 21:09:59 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:09:59 +1000
Subject: [PATCH v7 20/45] arm64: RME: Allow populating initial contents
In-Reply-To: <20250213161426.102987-21-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-21-steven.price@arm.com>
Message-ID: <8e852bc0-9a02-42d9-8d56-712c11508626@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> The VMM needs to populate the realm with some data before starting (e.g.
> a kernel and initrd). This is measured by the RMM and used as part of
> the attestation later on.
> 
> Co-developed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Handle host potentially having a larger page size than the RMM
>     granule.
>   * Drop historic "par" (protected address range) from
>     populate_par_region() - it doesn't exist within the current
>     architecture.
>   * Add a cond_resched() call in kvm_populate_realm().
> Changes since v5:
>   * Refactor to use PFNs rather than tracking struct page in
>     realm_create_protected_data_page().
>   * Pull changes from a later patch (in the v5 series) for accessing
>     pages from a guest memfd.
>   * Do the populate in chunks to avoid holding locks for too long and
>     triggering RCU stall warnings.
> ---
>   arch/arm64/kvm/rme.c | 234 +++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 234 insertions(+)
> 

With the following comments addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> index f965869e9ef7..7880894db722 100644
> --- a/arch/arm64/kvm/rme.c
> +++ b/arch/arm64/kvm/rme.c
> @@ -624,6 +624,228 @@ void kvm_realm_unmap_range(struct kvm *kvm, unsigned long start, u64 size,
>   		realm_unmap_private_range(kvm, start, end);
>   }
>   
> +static int realm_create_protected_data_granule(struct realm *realm,
> +					       unsigned long ipa,
> +					       phys_addr_t dst_phys,
> +					       phys_addr_t src_phys,
> +					       unsigned long flags)
> +{
> +	phys_addr_t rd = virt_to_phys(realm->rd);
> +	int ret;
> +
> +	if (rmi_granule_delegate(dst_phys))
> +		return -ENXIO;
> +
> +	ret = rmi_data_create(rd, dst_phys, ipa, src_phys, flags);
> +	if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> +		/* Create missing RTTs and retry */
> +		int level = RMI_RETURN_INDEX(ret);
> +
> +		WARN_ON(level == RMM_RTT_MAX_LEVEL);
> +
> +		ret = realm_create_rtt_levels(realm, ipa, level,
> +					      RMM_RTT_MAX_LEVEL, NULL);
> +		if (ret)
> +			return -EIO;
> +
> +		ret = rmi_data_create(rd, dst_phys, ipa, src_phys, flags);
> +	}
> +	if (ret)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static int realm_create_protected_data_page(struct realm *realm,
> +					    unsigned long ipa,
> +					    kvm_pfn_t dst_pfn,
> +					    kvm_pfn_t src_pfn,
> +					    unsigned long flags)
> +{
> +	unsigned long rd = virt_to_phys(realm->rd);
> +	phys_addr_t dst_phys, src_phys;
> +	bool undelegate_failed = false;
> +	int ret, offset;
> +
> +	dst_phys = __pfn_to_phys(dst_pfn);
> +	src_phys = __pfn_to_phys(src_pfn);
> +
> +	for (offset = 0; offset < PAGE_SIZE; offset += RMM_PAGE_SIZE) {
> +		ret = realm_create_protected_data_granule(realm,
> +							  ipa,
> +							  dst_phys,
> +							  src_phys,
> +							  flags);
> +		if (ret)
> +			goto err;
> +
> +		ipa += RMM_PAGE_SIZE;
> +		dst_phys += RMM_PAGE_SIZE;
> +		src_phys += RMM_PAGE_SIZE;
> +	}
> +
> +	return 0;
> +
> +err:
> +	if (ret == -EIO) {
> +		/* current offset needs undelegating */
> +		if (WARN_ON(rmi_granule_undelegate(dst_phys)))
> +			undelegate_failed = true;
> +	}
> +	while (offset > 0) {
> +		ipa -= RMM_PAGE_SIZE;
> +		offset -= RMM_PAGE_SIZE;
> +		dst_phys -= RMM_PAGE_SIZE;
> +
> +		rmi_data_destroy(rd, ipa, NULL, NULL);
> +
> +		if (WARN_ON(rmi_granule_undelegate(dst_phys)))
> +			undelegate_failed = true;
> +	}
> +
> +	if (undelegate_failed) {
> +		/*
> +		 * A granule could not be undelegated,
> +		 * so the page has to be leaked
> +		 */
> +		get_page(pfn_to_page(dst_pfn));
> +	}
> +
> +	return -ENXIO;
> +}
> +
> +static int populate_region(struct kvm *kvm,
> +			   phys_addr_t ipa_base,
> +			   phys_addr_t ipa_end,
> +			   unsigned long data_flags)
> +{
> +	struct realm *realm = &kvm->arch.realm;
> +	struct kvm_memory_slot *memslot;
> +	gfn_t base_gfn, end_gfn;
> +	int idx;
> +	phys_addr_t ipa;
> +	int ret = 0;
> +
> +	base_gfn = gpa_to_gfn(ipa_base);
> +	end_gfn = gpa_to_gfn(ipa_end);
> +
> +	idx = srcu_read_lock(&kvm->srcu);
> +	memslot = gfn_to_memslot(kvm, base_gfn);
> +	if (!memslot) {
> +		ret = -EFAULT;
> +		goto out;
> +	}
> +
> +	/* We require the region to be contained within a single memslot */
> +	if (memslot->base_gfn + memslot->npages < end_gfn) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (!kvm_slot_can_be_private(memslot)) {
> +		ret = -EINVAL;
		ret = -EPERM;

> +		goto out;
> +	}
> +
> +	write_lock(&kvm->mmu_lock);
> +
> +	ipa = ALIGN_DOWN(ipa_base, PAGE_SIZE);

The aignment operation is unnecessary since the base/size are ensured
to be aligned to PAGE_SIZE by its caller (kvm_populate_realm()).

> +	while (ipa < ipa_end) {
> +		struct vm_area_struct *vma;
> +		unsigned long hva;
> +		struct page *page;
> +		bool writeable;
> +		kvm_pfn_t pfn;
> +		kvm_pfn_t priv_pfn;
> +		struct page *gmem_page;
> +
> +		hva = gfn_to_hva_memslot(memslot, gpa_to_gfn(ipa));
> +		vma = vma_lookup(current->mm, hva);
> +		if (!vma) {
> +			ret = -EFAULT;
> +			break;
> +		}
> +
> +		pfn = __kvm_faultin_pfn(memslot, gpa_to_gfn(ipa), FOLL_WRITE,
> +					&writeable, &page);
> +
> +		if (is_error_pfn(pfn)) {
> +			ret = -EFAULT;
> +			break;
> +		}
> +
> +		ret = kvm_gmem_get_pfn(kvm, memslot,
> +				       ipa >> PAGE_SHIFT,
> +				       &priv_pfn, &gmem_page, NULL);
> +		if (ret)
> +			break;
> +
> +		ret = realm_create_protected_data_page(realm, ipa,
> +						       priv_pfn,
> +						       pfn,
> +						       data_flags);
> +
> +		kvm_release_faultin_page(kvm, page, false, false);
> +
> +		if (ret)
> +			break;
> +
> +		ipa += PAGE_SIZE;
> +	}
> +
> +	write_unlock(&kvm->mmu_lock);
> +
> +out:
> +	srcu_read_unlock(&kvm->srcu, idx);
> +	return ret;
> +}
> +
> +static int kvm_populate_realm(struct kvm *kvm,
> +			      struct arm_rme_populate_realm *args)
> +{
> +	phys_addr_t ipa_base, ipa_end;
> +	unsigned long data_flags = 0;
> +
> +	if (kvm_realm_state(kvm) != REALM_STATE_NEW)
> +		return -EINVAL;
		return -EPERM;

> +
> +	if (!IS_ALIGNED(args->base, PAGE_SIZE) ||
> +	    !IS_ALIGNED(args->size, PAGE_SIZE))
> +		return -EINVAL;
> +
> +	if (args->flags & ~RMI_MEASURE_CONTENT)
> +		return -EINVAL;

It's perfect to combine those checks:

	if (!IS_ALIGNED(...) ||
	    !IS_ALIGNED(...) ||
	    args->flags & ~RMI_MEASURE_CONTENT)
		return -EINVAL;

> +
> +	ipa_base = args->base;
> +	ipa_end = ipa_base + args->size;
> +
> +	if (ipa_end < ipa_base)
> +		return -EINVAL;
> +
> +	if (args->flags & RMI_MEASURE_CONTENT)
> +		data_flags |= RMI_MEASURE_CONTENT;
> +
> +	/*
> +	 * Perform the populate in parts to ensure locks are not held for too
> +	 * long
> +	 */
	
s/populate/population ?

> +	while (ipa_base < ipa_end) {
> +		phys_addr_t end = min(ipa_end, ipa_base + SZ_2M);
> +
> +		int ret = populate_region(kvm, ipa_base, end,
> +					  args->flags);
> +
> +		if (ret)
> +			return ret;
> +
> +		ipa_base = end;
> +
> +		cond_resched();
> +	}
> +
> +	return 0;
> +}
> +
>   static int realm_set_ipa_state(struct kvm_vcpu *vcpu,
>   			       unsigned long start,
>   			       unsigned long end,
> @@ -873,6 +1095,18 @@ int kvm_realm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
>   		r = kvm_init_ipa_range_realm(kvm, &args);
>   		break;
>   	}
> +	case KVM_CAP_ARM_RME_POPULATE_REALM: {
> +		struct arm_rme_populate_realm args;
> +		void __user *argp = u64_to_user_ptr(cap->args[1]);
> +
> +		if (copy_from_user(&args, argp, sizeof(args))) {
> +			r = -EFAULT;
> +			break;
> +		}
> +
> +		r = kvm_populate_realm(kvm, &args);
> +		break;
> +	}
>   	default:
>   		r = -EINVAL;
>   		break;

Thanks,
Gavin



From gshan at redhat.com  Mon Mar  3 21:15:31 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:15:31 +1000
Subject: [PATCH v7 22/45] KVM: arm64: Handle realm VCPU load
In-Reply-To: <20250213161426.102987-23-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-23-steven.price@arm.com>
Message-ID: <eb8ea5a0-fe6c-4b96-92da-f9ec0355b4dd@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> When loading a realm VCPU much of the work is handled by the RMM so only
> some of the actions are required. Rearrange kvm_arch_vcpu_load()
> slightly so we can bail out early for a realm guest.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/arm.c | 12 ++++++++----
>   1 file changed, 8 insertions(+), 4 deletions(-)
> 

One nitpick below:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 49ad633c5ca5..3e13e3d87ed9 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -633,10 +633,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>   	kvm_vgic_load(vcpu);
>   	kvm_timer_vcpu_load(vcpu);
>   	kvm_vcpu_load_debug(vcpu);
> -	if (has_vhe())
> -		kvm_vcpu_load_vhe(vcpu);
> -	kvm_arch_vcpu_load_fp(vcpu);
> -	kvm_vcpu_pmu_restore_guest(vcpu);
>   	if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
>   		kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
>   
> @@ -659,6 +655,14 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>   		kvm_call_hyp(__vgic_v3_restore_vmcr_aprs,
>   			     &vcpu->arch.vgic_cpu.vgic_v3);
>   	}

A spare line is needed here.

> +	/* No additional state needs to be loaded on Realmed VMs */
> +	if (vcpu_is_rec(vcpu))
> +		return;
> +
> +	if (has_vhe())
> +		kvm_vcpu_load_vhe(vcpu);
> +	kvm_arch_vcpu_load_fp(vcpu);
> +	kvm_vcpu_pmu_restore_guest(vcpu);
>   
>   	if (!cpumask_test_cpu(cpu, vcpu->kvm->arch.supported_cpus))
>   		vcpu_set_on_unsupported_cpu(vcpu);

Thanks,
Gavin



From y-abhilashchandra at ti.com  Mon Mar  3 21:24:19 2025
From: y-abhilashchandra at ti.com (Yemike Abhilash Chandra)
Date: Tue, 4 Mar 2025 10:54:19 +0530
Subject: [PATCH 0/5] Add J722S CSI support
In-Reply-To: <20250218185452.600797-1-vaishnav.a@ti.com>
References: <20250218185452.600797-1-vaishnav.a@ti.com>
Message-ID: <ed8ce158-89dd-4a81-aa70-679559d6f5b3@ti.com>


On 19/02/25 00:24, Vaishnav Achath wrote:
> This series adds support for CSI2RX capture on J722S EVM
> and enables IMX219 and OV5640 overlays to enables
> 4 sensors on EVM, this provides a reference for a user to
> enable a different sensor on any of the ports.
> 
> Test logs:
> IMX219: https://gist.github.com/vaishnavachath/60cc2ef257601f27f28a315f8cf669c4
> OV5640: https://gist.github.com/vaishnavachath/648202286d4d34d4d25f7c8c9db8b8bd
> 
> Vaishnav Achath (5):
>    arm64: dts: ti: k3-j722s-main: Add BCDMA CSI overrides
>    arm64: dts: ti: k3-j722s-main: Add CSI2RX nodes
>    arm64: dts: ti: k3-j722s-evm: Add camera peripherals
>    arm64: dts: ti: k3-j722s-evm: Add overlay for quad IMX219
>    arm64: dts: ti: k3-j722s-evm: Add overlay for TEVI OV5640
> 

For the series:
Reviewed-by: Yemike Abhilash Chandra <y-abhilashchandra at ti.com>

>   arch/arm64/boot/dts/ti/Makefile               |   9 +
>   ...k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtso | 304 +++++++++++++++++
>   .../k3-j722s-evm-csi2-quad-tevi-ov5640.dtso   | 319 ++++++++++++++++++
>   arch/arm64/boot/dts/ti/k3-j722s-evm.dts       |  28 ++
>   arch/arm64/boot/dts/ti/k3-j722s-main.dtsi     | 193 +++++++++++
>   5 files changed, 853 insertions(+)
>   create mode 100644 arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtso
>   create mode 100644 arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-tevi-ov5640.dtso
> 


From gshan at redhat.com  Mon Mar  3 21:29:38 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:29:38 +1000
Subject: [PATCH v7 23/45] KVM: arm64: Validate register access for a Realm
 VM
In-Reply-To: <20250213161426.102987-24-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-24-steven.price@arm.com>
Message-ID: <b4cc58db-b9d8-4cdb-8954-8697972a54ae@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> The RMM only allows setting the GPRS (x0-x30) and PC for a realm
> guest. Check this in kvm_arm_set_reg() so that the VMM can receive a
> suitable error return if other registers are accessed.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v5:
>   * Upper GPRS can be set as part of a HOST_CALL return, so fix up the
>     test to allow them.
> ---
>   arch/arm64/kvm/guest.c | 40 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 40 insertions(+)
> 

The subject isn't 100% matching with what has been done in this patch.
It's actually to limit the scope for the write operations. The question
is do we need similar limitation for the read operations? If not, it's
nice to explain in the change log :)

> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 2196979a24a3..ff0306650b39 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -73,6 +73,24 @@ static u64 core_reg_offset_from_id(u64 id)
>   	return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
>   }
>   
> +static bool kvm_realm_validate_core_reg(u64 off)
> +{
> +	/*
> +	 * Note that GPRs can only sometimes be controlled by the VMM.
> +	 * For PSCI only X0-X6 are used, higher registers are ignored (restored
> +	 * from the REC).
> +	 * For HOST_CALL all of X0-X30 are copied to the RsiHostCall structure.
> +	 * For emulated MMIO X0 is always used.
> +	 */
> +	switch (off) {
> +	case KVM_REG_ARM_CORE_REG(regs.regs[0]) ...
> +	     KVM_REG_ARM_CORE_REG(regs.regs[30]):
> +	case KVM_REG_ARM_CORE_REG(regs.pc):
> +		return true;
> +	}
> +	return false;
> +}
> +
>   static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off)
>   {
>   	int size;
> @@ -783,12 +801,34 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>   	return kvm_arm_sys_reg_get_reg(vcpu, reg);
>   }
>   
> +/*
> + * The RMI ABI only enables setting some GPRs and PC. The selection of GPRs
> + * that are available depends on the Realm state and the reason for the last
> + * exit.  All other registers are reset to architectural or otherwise defined
> + * reset values by the RMM, except for a few configuration fields that
> + * correspond to Realm parameters.
> + */
> +static bool validate_realm_set_reg(struct kvm_vcpu *vcpu,
> +				   const struct kvm_one_reg *reg)
> +{
> +	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) {
> +		u64 off = core_reg_offset_from_id(reg->id);
> +
> +		return kvm_realm_validate_core_reg(off);
> +	}
> +
> +	return false;
> +}
> +
>   int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>   {
>   	/* We currently use nothing arch-specific in upper 32 bits */
>   	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
>   		return -EINVAL;
>   
> +	if (kvm_is_realm(vcpu->kvm) && !validate_realm_set_reg(vcpu, reg))
> +		return -EINVAL;
> +
>   	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
>   	case KVM_REG_ARM_CORE:	return set_core_reg(vcpu, reg);
>   	case KVM_REG_ARM_FW:

Thanks,
Gavin



From peterz at infradead.org  Mon Mar  3 21:38:53 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 4 Mar 2025 06:38:53 +0100
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn>
 <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
Message-ID: <20250304053853.GA7099@noisy.programming.kicks-ass.net>

On Tue, Mar 04, 2025 at 09:10:12AM +0800, Menglong Dong wrote:
> Hello, sorry that I forgot to add something to the changelog. In fact,
> I don't add extra 5-bytes anymore, which you can see in the 3rd patch.
> 
> The thing is that we can't add extra 5-bytes if CFI is enabled. Without
> CFI, we can make the padding space any value, such as 5-bytes, and
> the layout will be like this:
> 
> __align:
>   nop
>   nop
>   nop
>   nop
>   nop
> foo: -- __align +5
> 
> However, the CFI will always make the cfi insn 16-bytes aligned. When
> we set the FUNCTION_PADDING_BYTES to (11 + 5), the layout will be
> like this:
> 
> __cfi_foo:
>   nop (11)
>   mov $0x12345678, %reg
>   nop (16)
> foo:
> 
> and the padding space is 32-bytes actually. So, we can just select
> FUNCTION_ALIGNMENT_32B instead, which makes the padding
> space 32-bytes too, and have the following layout:
> 
> __cfi_foo:
>   mov $0x12345678, %reg
>   nop (27)
> foo:

*blink*, wtf is clang smoking.

I mean, you're right, this is what it is doing, but that is somewhat
unexpected. Let me go look at clang source, this is insane.



From gshan at redhat.com  Mon Mar  3 21:39:51 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:39:51 +1000
Subject: [PATCH v7 25/45] KVM: arm64: WARN on injected undef exceptions
In-Reply-To: <20250213161426.102987-26-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-26-steven.price@arm.com>
Message-ID: <bf568862-5435-4c88-9364-0190f30a3d9a@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> The RMM doesn't allow injection of a undefined exception into a realm
> guest. Add a WARN to catch if this ever happens.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * if (x) WARN(1, ...) makes no sense, just WARN(x, ...)!
> ---
>   arch/arm64/kvm/inject_fault.c | 1 +
>   1 file changed, 1 insertion(+)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From gshan at redhat.com  Mon Mar  3 21:38:27 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:38:27 +1000
Subject: [PATCH v7 24/45] KVM: arm64: Handle Realm PSCI requests
In-Reply-To: <20250213161426.102987-25-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-25-steven.price@arm.com>
Message-ID: <5008db08-c153-48c0-90b3-39fa0297ba1e@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> The RMM needs to be informed of the target REC when a PSCI call is made
> with an MPIDR argument. Expose an ioctl to the userspace in case the PSCI
> is handled by it.
> 
> Co-developed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v6:
>   * Use vcpu_is_rec() rather than kvm_is_realm(vcpu->kvm).
>   * Minor renaming/formatting fixes.
> ---
>   arch/arm64/include/asm/kvm_rme.h |  3 +++
>   arch/arm64/kvm/arm.c             | 25 +++++++++++++++++++++++++
>   arch/arm64/kvm/psci.c            | 30 ++++++++++++++++++++++++++++++
>   arch/arm64/kvm/rme.c             | 14 ++++++++++++++
>   4 files changed, 72 insertions(+)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From gshan at redhat.com  Mon Mar  3 21:42:10 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:42:10 +1000
Subject: [PATCH v7 26/45] arm64: Don't expose stolen time for realm guests
In-Reply-To: <20250213161426.102987-27-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-27-steven.price@arm.com>
Message-ID: <ecf15da0-49ff-4cc3-9e4e-5c47f79acc06@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> It doesn't make much sense as a realm guest wouldn't want to trust the
> host. It will also need some extra work to ensure that KVM will only
> attempt to write into a shared memory region. So for now just disable
> it.
> 
> Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/arm.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 

With Documentation/virt/kvm/api.rst updated:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index a6718dec00c9..79d541c95bfb 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -403,7 +403,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   		r = system_supports_mte();
>   		break;
>   	case KVM_CAP_STEAL_TIME:
> -		r = kvm_arm_pvtime_supported();
> +		if (kvm_is_realm(kvm))
> +			r = 0;
> +		else
> +			r = kvm_arm_pvtime_supported();
>   		break;
>   	case KVM_CAP_ARM_EL1_32BIT:
>   		r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);



From gshan at redhat.com  Mon Mar  3 21:47:50 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 15:47:50 +1000
Subject: [PATCH v7 27/45] arm64: rme: allow userspace to inject aborts
In-Reply-To: <20250213161426.102987-28-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-28-steven.price@arm.com>
Message-ID: <2505ead3-64a6-4135-a96c-85c5dfef26d0@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> From: Joey Gouly <joey.gouly at arm.com>
> 
> Extend KVM_SET_VCPU_EVENTS to support realms, where KVM cannot set the
> system registers, and the RMM must perform it on next REC entry.
> 
> Signed-off-by: Joey Gouly <joey.gouly at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   Documentation/virt/kvm/api.rst |  2 ++
>   arch/arm64/kvm/guest.c         | 24 ++++++++++++++++++++++++
>   2 files changed, 26 insertions(+)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From gshan at redhat.com  Mon Mar  3 22:01:16 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 16:01:16 +1000
Subject: [PATCH v7 28/45] arm64: rme: support RSI_HOST_CALL
In-Reply-To: <20250213161426.102987-29-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-29-steven.price@arm.com>
Message-ID: <12b5ba41-4b1e-4876-9796-d1d6bb344015@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> From: Joey Gouly <joey.gouly at arm.com>
> 
> Forward RSI_HOST_CALLS to KVM's HVC handler.
> 
> Signed-off-by: Joey Gouly <joey.gouly at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v4:
>   * Setting GPRS is now done by kvm_rec_enter() rather than
>     rec_exit_host_call() (see previous patch - arm64: RME: Handle realm
>     enter/exit). This fixes a bug where the registers set by user space
>     were being ignored.
> ---
>   arch/arm64/kvm/rme-exit.c | 22 ++++++++++++++++++++++
>   1 file changed, 22 insertions(+)
> 
> diff --git a/arch/arm64/kvm/rme-exit.c b/arch/arm64/kvm/rme-exit.c
> index c785005f821f..4f7602aa3c6c 100644
> --- a/arch/arm64/kvm/rme-exit.c
> +++ b/arch/arm64/kvm/rme-exit.c
> @@ -107,6 +107,26 @@ static int rec_exit_ripas_change(struct kvm_vcpu *vcpu)
>   	return -EFAULT;
>   }
>   
> +static int rec_exit_host_call(struct kvm_vcpu *vcpu)
> +{
> +	int ret, i;
> +	struct realm_rec *rec = &vcpu->arch.rec;
> +
> +	vcpu->stat.hvc_exit_stat++;
> +
> +	for (i = 0; i < REC_RUN_GPRS; i++)
> +		vcpu_set_reg(vcpu, i, rec->run->exit.gprs[i]);
> +
> +	ret = kvm_smccc_call_handler(vcpu);
> +
> +	if (ret < 0) {
> +		vcpu_set_reg(vcpu, 0, ~0UL);
> +		ret = 1;
> +	}
> +
> +	return ret;
> +}
> +

I don't understand how a negative error can be returned from kvm_smccc_call_handler().
Besides, SMCCC_RET_NOT_SUPPORTED has been set to GPR[0 - 3] if the request can't be
supported. Why we need to set GPR[0] to ~0UL, which corresponds to SMCCC_RET_NOT_SUPPORTED
if I'm correct. I guess change log or a comment to explain the questions would be
nice.

>   static void update_arch_timer_irq_lines(struct kvm_vcpu *vcpu)
>   {
>   	struct realm_rec *rec = &vcpu->arch.rec;
> @@ -168,6 +188,8 @@ int handle_rec_exit(struct kvm_vcpu *vcpu, int rec_run_ret)
>   		return rec_exit_psci(vcpu);
>   	case RMI_EXIT_RIPAS_CHANGE:
>   		return rec_exit_ripas_change(vcpu);
> +	case RMI_EXIT_HOST_CALL:
> +		return rec_exit_host_call(vcpu);
>   	}
>   
>   	kvm_pr_unimpl("Unsupported exit reason: %u\n",

Thanks,
Gavin



From gshan at redhat.com  Mon Mar  3 22:02:45 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 16:02:45 +1000
Subject: [PATCH v7 29/45] arm64: rme: Allow checking SVE on VM instance
In-Reply-To: <20250213161426.102987-30-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-30-steven.price@arm.com>
Message-ID: <5587ca83-bb19-42ae-8297-676588502e5e@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> From: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Given we have different types of VMs supported, check the
> support for SVE for the given instance of the VM to accurately
> report the status.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/include/asm/kvm_rme.h | 2 ++
>   arch/arm64/kvm/arm.c             | 5 ++++-
>   arch/arm64/kvm/rme.c             | 5 +++++
>   3 files changed, 11 insertions(+), 1 deletion(-)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From yepeilin at google.com  Mon Mar  3 22:04:10 2025
From: yepeilin at google.com (Peilin Ye)
Date: Tue, 4 Mar 2025 06:04:10 +0000
Subject: [PATCH bpf-next v6 0/6] Introduce load-acquire and store-release
 BPF instructions
In-Reply-To: <174106503648.3866937.5658954004964289425.git-patchwork-notify@kernel.org>
References: <cover.1741049567.git.yepeilin@google.com>
 <174106503648.3866937.5658954004964289425.git-patchwork-notify@kernel.org>
Message-ID: <Z8aX2j2WYd4DlnCH@google.com>

On Tue, Mar 04, 2025 at 05:10:36AM +0000, patchwork-bot+netdevbpf at kernel.org wrote:
> Hello:
> 
> This series was applied to bpf/bpf-next.git (master)

Thanks again to everyone for reviewing this!

Cheers,
Peilin Ye



From m-malladi at ti.com  Mon Mar  3 22:17:35 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Tue, 4 Mar 2025 11:47:35 +0530
Subject: [EXTERNAL] Re: [PATCH net-next v3 1/2] net: ti: icss-iep: Add
 pwidth configuration for perout signal
In-Reply-To: <20250303180323.1d9b51de@kmaincent-XPS-13-7390>
References: <20250303135124.632845-1-m-malladi@ti.com>
 <20250303135124.632845-2-m-malladi@ti.com>
 <20250303180323.1d9b51de@kmaincent-XPS-13-7390>
Message-ID: <5cad21ef-a97b-4412-a399-7ace69b85356@ti.com>



On 3/3/2025 10:33 PM, Kory Maincent wrote:
> On Mon, 3 Mar 2025 19:?21:?23 +0530 Meghana Malladi <m-malladi@?ti.?com> 
> wrote: > icss_iep_perout_enable_hw() is a common function for generating 
>  > both pps and perout signals. When enabling pps, the application needs 
>  > to only pass
> ZjQcmQRYFpfptBannerStart
> This message was sent from outside of Texas Instruments.
> Do not click links or open attachments unless you recognize the source 
> of this email and know the content is safe.
> Report?Suspicious
> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK! 
> uVdqXRfP1m17KmZFPNPjnPB9kIuFmkbGwUjWeOt4PhpPuyUdhbWQXCWjPIg3CE7zH4vA7aR5lJOdoby6lh8SIqLqdFhb$>
> ZjQcmQRYFpfptBannerEnd
> 
> On Mon, 3 Mar 2025 19:21:23 +0530
> Meghana Malladi <m-malladi at ti.com> wrote:
> 
>> icss_iep_perout_enable_hw() is a common function for generating
>> both pps and perout signals. When enabling pps, the application needs
>> to only pass enable/disable argument, whereas for perout it supports
>> different flags to configure the signal.
>> 
>> But icss_iep_perout_enable_hw() function is missing to hook the
>> configuration params passed by the app, causing perout to behave
>> same a pps (except being able to configure the period). As duty cycle
>> is also one feature which can configured for perout, incorporate this
>> in the function to get the expected signal.
> 
> ...
> 
>> IEP_SYNC_CTRL_SYNC_EN); @@ -474,7 +484,38 @@ static int
>> icss_iep_perout_enable_hw(struct icss_iep *iep, static int
>> icss_iep_perout_enable(struct icss_iep *iep, struct ptp_perout_request *req,
>> int on) {
>> -	return -EOPNOTSUPP;
>> +	int ret = 0;
>> +
>> +	mutex_lock(&iep->ptp_clk_mutex);
>> +
>> +	/* Reject requests with unsupported flags */
>> +	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) {
>> +		ret = -EOPNOTSUPP;
>> +		goto exit;
>> +	}
> 
> The flags check does not need to be in the mutex lock.
> With this change:
> Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
> 

Yes agreed, will move it outside the mutex lock. Thanks.

>> +	if (iep->pps_enabled) {
>> +		ret = -EBUSY;
>> +		goto exit;
>> +	}
>> +
>> +	if (iep->perout_enabled == !!on)
>> +		goto exit;
>> +
>> +	/* Set default "on" time (1ms) for the signal if not passed by the
>> app */
>> +	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
>> +		req->on.sec = 0;
>> +		req->on.nsec = NSEC_PER_MSEC;
>> +	}
>> +
>> +	ret = icss_iep_perout_enable_hw(iep, req, on);
>> +	if (!ret)
>> +		iep->perout_enabled = !!on;
>> +
>> +exit:
>> +	mutex_unlock(&iep->ptp_clk_mutex);
>> +
>> +	return ret;
>>  }
>>  
>>  static void icss_iep_cap_cmp_work(struct work_struct *work)
>> @@ -553,6 +594,8 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int
>> on) rq.perout.period.nsec = 0;
>>  		rq.perout.start.sec = ts.tv_sec + 2;
>>  		rq.perout.start.nsec = 0;
>> +		rq.perout.on.sec = 0;
>> +		rq.perout.on.nsec = NSEC_PER_MSEC;
>>  		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
>>  	} else {
>>  		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
> 
> 
> 
> -- 
> K?ry Maincent, Bootlin
> Embedded Linux and kernel engineering
> https://urldefense.com/v3/__https://bootlin.com__;!!G3vK! 
> TJ19I0FAUivlehxg6fb4ka96Q2RiJDOZNyHXmEeRdYIPu4Cthp- 
> iiGCHOwcUnPvn8Ek_htiuIef9PMEWGUfBEA$ <https://urldefense.com/v3/__https://bootlin.com__;!!G3vK!TJ19I0FAUivlehxg6fb4ka96Q2RiJDOZNyHXmEeRdYIPu4Cthp-iiGCHOwcUnPvn8Ek_htiuIef9PMEWGUfBEA$>
> 



From aweber.kernel at gmail.com  Mon Mar  3 22:20:31 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:31 +0100
Subject: [PATCH v6 00/10] mfd: bcm590xx: Add support for BCM59054
Message-ID: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>

Add support for the BCM59054 MFD to the bcm590xx driver and fix a
couple of small bugs in it that also affected the already supported
BCM59056.

While we're at it - convert the devicetree bindings to YAML format
and drop the bcm59056 DTS in favor of describing the PMU in users'
DTS files, as is done for most other MFDs.

The BCM59054 is fairly similar to the BCM59056, with the primary
difference being the different number and layout of regulators.
It is primarily used in devices using the BCM21664 and BCM23550
chipsets.

This patchset has been tested on a Samsung Galaxy Grand Neo
(baffinlite rev02; DTS not in mainline yet) with a BCM59054 PMIC.
Testing on a BCM59056 would be appreciated.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Rename mfd/brcm,bcm590xx.yaml to mfd/brcm,bcm59056.yaml again
- Use PMU ID value as device type
- Rename rev_dig and rev_ana to rev_digital and rev_analog
- Link to v5: https://lore.kernel.org/r/20250221-bcm59054-v5-0-065f516a9042 at gmail.com

Changes in v5:
- Make regulator binding descriptions reference mfd/brcm,bcm590xx.yaml
  instead of mfd/brcm,bcm59056.yaml
- Move regmap type enum to common MFD header
- Link to v4: https://lore.kernel.org/r/20250215-bcm59054-v4-0-dbfb2d76a855 at gmail.com

Changes in v4:
- Fix yamllint warnings in DT bindings
- Address miscelaneous review comments related to DT bindings
  - Note that I did not end up moving the regulator refs from
    allOf compatible matches; I explained my reasoning in [1].
    [1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/
- Add PMU ID/revision parsing to MFD driver
- Fix instances of regulator data not matching vendor kernel for
  BCM59054
- Use different voltage table for BCM59054 VSR reg based on PMU
  revision
- Link to v3: https://lore.kernel.org/r/20250131-bcm59054-v3-0-bbac52a84787 at gmail.com

Changes in v3:
- Split out regulator DT bindings into separate YAML
- Use tables of regulator info instead of get_XXX_register, reg_is_XXX
  functions
- Drop "regulator: bcm590xx: Add proper handling for PMMODE registers";
  it adds unnecessary noise to the series and will be submitted separately
- Link to v2: https://lore.kernel.org/r/20231030-bcm59054-v2-0-5fa4011aa5ba at gmail.com

Changes in v2:
- Fixed BCM59054 ID being passed to BCM59056 function in the
  regulator driver
- Dropped linux-rpi-kernel from the CC list
- Link to v1: https://lore.kernel.org/r/20231030-bcm59054-v1-0-3517f980c1e3 at gmail.com

---
Artur Weber (10):
      dt-bindings: mfd: brcm,bcm59056: Convert to YAML
      dt-bindings: mfd: brcm,bcm59056: Add compatible for BCM59054
      ARM: dts: Drop DTS for BCM59056 PMU
      mfd: bcm590xx: Drop unused "id" member of bcm590xx MFD struct
      mfd: bcm590xx: Add support for multiple device types + BCM59054 compatible
      mfd: bcm590xx: Add PMU ID/revision parsing function
      regulator: bcm590xx: Use dev_err_probe for regulator register error
      regulator: bcm590xx: Store regulator descriptions in table
      regulator: bcm590xx: Rename BCM59056-specific data as such
      regulator: bcm590xx: Add support for BCM59054 regulators

 .../devicetree/bindings/mfd/brcm,bcm59056.txt      |   39 -
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     |   76 ++
 .../bindings/regulator/brcm,bcm59054.yaml          |   56 +
 .../bindings/regulator/brcm,bcm59056.yaml          |   51 +
 arch/arm/boot/dts/broadcom/bcm28155-ap.dts         |   68 +-
 arch/arm/boot/dts/broadcom/bcm59056.dtsi           |   91 --
 drivers/mfd/bcm590xx.c                             |   75 +-
 drivers/regulator/bcm590xx-regulator.c             | 1289 ++++++++++++++++----
 include/linux/mfd/bcm590xx.h                       |   28 +-
 9 files changed, 1366 insertions(+), 407 deletions(-)
---
base-commit: ffd294d346d185b70e28b1a28abe367bbfe53c04
change-id: 20240816-bcm59054-a880695e41e8

Best regards,
-- 
Artur Weber <aweber.kernel at gmail.com>



From aweber.kernel at gmail.com  Mon Mar  3 22:20:32 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:32 +0100
Subject: [PATCH v6 01/10] dt-bindings: mfd: brcm,bcm59056: Convert to YAML
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-1-ae8302358443@gmail.com>

Convert devicetree bindings for the Broadcom BCM59056 PMU MFD from
TXT to YAML format. This patch does not change any functionality;
the bindings remain the same.

The bindings have been split into two parts: the MFD binding and
a separate binding for the regulator node, to simplify the addition
of other models later (which have different regulators).

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml

Changes in v5:
- Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
  regulator binding description

Changes in v4:
- Made $ref use full schema path
- Cleaned up example
- Dropped regulator name list comment
- Changed description of regulator binding to mention BCM59056
  explicitly
- Changed "Power Management IC" to "Power Management Unit" to match
  official Broadcom naming
- Renamed mfd/brcm,bcm59056.yaml to mfd/brcm,bcm590xx.yaml

Changes in v3:
- Moved regulator node to separate binding
- Removed quotes around compatibles/vbus property
- Style fixes for example
---
 .../devicetree/bindings/mfd/brcm,bcm59056.txt      | 39 ----------------
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 54 ++++++++++++++++++++++
 .../bindings/regulator/brcm,bcm59056.yaml          | 51 ++++++++++++++++++++
 3 files changed, 105 insertions(+), 39 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt
deleted file mode 100644
index be51a15e05f926913b3a473648d977b25f1a2fbc..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt
+++ /dev/null
@@ -1,39 +0,0 @@
--------------------------------
-BCM590xx Power Management Units
--------------------------------
-
-Required properties:
-- compatible: "brcm,bcm59056"
-- reg: I2C slave address
-- interrupts: interrupt for the PMU. Generic interrupt client node bindings
-  are described in interrupt-controller/interrupts.txt
-
-------------------
-Voltage Regulators
-------------------
-
-Optional child nodes:
-- regulators: container node for regulators following the generic
-  regulator binding in regulator/regulator.txt
-
-  The valid regulator node names for BCM59056 are:
-  	rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
-	mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
-	csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr,
-	gpldo1, gpldo2, gpldo3, gpldo4, gpldo5, gpldo6,
-	vbus
-
-Example:
-	pmu: bcm59056 at 8 {
-		compatible = "brcm,bcm59056";
-		reg = <0x08>;
-		interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
-		regulators {
-			rfldo_reg: rfldo {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3300000>;
-			};
-
-			...
-		};
-	};
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b387ef9885c3ac524e0782545dbca9c0e81a556c
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/brcm,bcm59056.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM590xx Power Management Units
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+properties:
+  compatible:
+    const: brcm,bcm59056
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  regulators:
+    type: object
+    $ref: /schemas/regulator/brcm,bcm59056.yaml#
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic at 8 {
+            compatible = "brcm,bcm59056";
+            reg = <0x08>;
+            interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+
+            regulators {
+                rfldo {
+                    regulator-min-microvolt = <1200000>;
+                    regulator-max-microvolt = <3300000>;
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7a5e36394d216232e0a2070fb20d09dcc1ea8056
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/brcm,bcm59056.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM59056 Power Management Unit regulators
+
+description: |
+  This is a part of device tree bindings for the BCM59056 power
+  management unit.
+
+  See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
+  additional information and example.
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+patternProperties:
+  "^(cam|sim|mmc)ldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(rf|sd|sdx|aud|mic|usb|vib)ldo$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(c|m|v)sr$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(io|sd)sr[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^gpldo[1-6]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+properties:
+  vbus:
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+additionalProperties: false

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:33 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:33 +0100
Subject: [PATCH v6 02/10] dt-bindings: mfd: brcm,bcm59056: Add compatible
 for BCM59054
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-2-ae8302358443@gmail.com>

The BCM59054 MFD is fairly similar to the BCM59056, and will use
the same driver. Add compatible and specify the allowed regulator
nodes.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml

Changes in v5:
- Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
  regulator bindings description

Changes in v4:
- Fix yamllint errors (missing unevaluatedProperties)
- Drop comment with regulator name list
- Use full schema paths for $reg
- Change description of regulator binding to mention BCM59054
  explicitly
- Drop quotes around vbus reg name
- Change "Power Management IC" to "Power Management Unit" to match
  official Broadcom naming

Note that I did not end up moving the regulator refs from
allOf compatible matches; I explained my reasoning in [1].

[1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/

Changes in v3:
- Split regulator node into separate file
- Removed quotes around compatible
---
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 26 +++++++++-
 .../bindings/regulator/brcm,bcm59054.yaml          | 56 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
index b387ef9885c3ac524e0782545dbca9c0e81a556c..b67d7a723fc242869e5bdc6b3602785f62af45bd 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: brcm,bcm59056
+    enum:
+      - brcm,bcm59054
+      - brcm,bcm59056
 
   reg:
     maxItems: 1
@@ -21,7 +23,6 @@ properties:
 
   regulators:
     type: object
-    $ref: /schemas/regulator/brcm,bcm59056.yaml#
 
 required:
   - compatible
@@ -30,6 +31,27 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: brcm,bcm59054
+    then:
+      properties:
+        regulators:
+          $ref: /schemas/regulator/brcm,bcm59054.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: brcm,bcm59056
+    then:
+      properties:
+        regulators:
+          $ref: /schemas/regulator/brcm,bcm59056.yaml#
+
 examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
diff --git a/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml b/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5b46d7fca05e21aa1eae991b5f9f60b444f20c1c
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/brcm,bcm59054.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM59054 Power Management Unit regulators
+
+description: |
+  This is a part of device tree bindings for the BCM59054 power
+  management unit.
+
+  See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
+  additional information and example.
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+patternProperties:
+  "^(cam|sim|mmc)ldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(rf|sd|sdx|aud|mic|usb|vib|tcx)ldo$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(c|mm|v)sr$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(io|sd)sr[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^gpldo[1-3]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^lvldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+properties:
+  vbus:
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+additionalProperties: false

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:34 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:34 +0100
Subject: [PATCH v6 03/10] ARM: dts: Drop DTS for BCM59056 PMU
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-3-ae8302358443@gmail.com>

The BCM59056 PMU has its own separate DTSI, meant to be included
in a DTS file after defining the pmu node on some I2C bus.

This seems rather unintuitive; drop the DTS in favor of adding the
BCM59056 PMU node directly into the device DTS files.

If the amount of subdevices supported by the BCM590xx grows, and
a common device tree turns out to be beneficial, it can be reintroduced
in the future.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v4:
- PMIC -> PMU in commit message
---
 arch/arm/boot/dts/broadcom/bcm28155-ap.dts | 68 +++++++++++-----------
 arch/arm/boot/dts/broadcom/bcm59056.dtsi   | 91 ------------------------------
 2 files changed, 32 insertions(+), 127 deletions(-)

diff --git a/arch/arm/boot/dts/broadcom/bcm28155-ap.dts b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
index 2f3634545e64978888cd0b47fd5647a5e2eb8e07..cefaa9a3c45c9c90bffc08f739161d8ea21d98dd 100644
--- a/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
+++ b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
@@ -37,7 +37,39 @@ &pmu_bsc {
 	status = "okay";
 
 	pmu: pmu at 8 {
+		compatible = "brcm,bcm59056";
+		interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
 		reg = <0x08>;
+
+		regulators {
+			camldo1_reg: camldo1 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			sdldo_reg: sdldo {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			sdxldo_reg: sdxldo {
+				regulator-min-microvolt = <2700000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			usbldo_reg: usbldo {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			iosr1_reg: iosr1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
 	};
 };
 
@@ -74,39 +106,3 @@ &usbotg {
 &usbphy {
 	status = "okay";
 };
-
-#include "bcm59056.dtsi"
-
-&pmu {
-	compatible = "brcm,bcm59056";
-	interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
-	regulators {
-		camldo1_reg: camldo1 {
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		sdldo_reg: sdldo {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-		};
-
-		sdxldo_reg: sdxldo {
-			regulator-min-microvolt = <2700000>;
-			regulator-max-microvolt = <3300000>;
-		};
-
-		usbldo_reg: usbldo {
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		iosr1_reg: iosr1 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			regulator-always-on;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/broadcom/bcm59056.dtsi b/arch/arm/boot/dts/broadcom/bcm59056.dtsi
deleted file mode 100644
index a9bb7ad81378d88811c4473763c579d3d2c006a1..0000000000000000000000000000000000000000
--- a/arch/arm/boot/dts/broadcom/bcm59056.dtsi
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
-* Copyright 2014 Linaro Limited
-* Author: Matt Porter <mporter at linaro.org>
-*/
-
-&pmu {
-	compatible = "brcm,bcm59056";
-	regulators {
-		rfldo_reg: rfldo {
-		};
-
-		camldo1_reg: camldo1 {
-		};
-
-		camldo2_reg: camldo2 {
-		};
-
-		simldo1_reg: simldo1 {
-		};
-
-		simldo2_reg: simldo2 {
-		};
-
-		sdldo_reg: sdldo {
-		};
-
-		sdxldo_reg: sdxldo {
-		};
-
-		mmcldo1_reg: mmcldo1 {
-		};
-
-		mmcldo2_reg: mmcldo2 {
-		};
-
-		audldo_reg: audldo {
-		};
-
-		micldo_reg: micldo {
-		};
-
-		usbldo_reg: usbldo {
-		};
-
-		vibldo_reg: vibldo {
-		};
-
-		csr_reg: csr {
-		};
-
-		iosr1_reg: iosr1 {
-		};
-
-		iosr2_reg: iosr2 {
-		};
-
-		msr_reg: msr {
-		};
-
-		sdsr1_reg: sdsr1 {
-		};
-
-		sdsr2_reg: sdsr2 {
-		};
-
-		vsr_reg: vsr {
-		};
-
-		gpldo1_reg: gpldo1 {
-		};
-
-		gpldo2_reg: gpldo2 {
-		};
-
-		gpldo3_reg: gpldo3 {
-		};
-
-		gpldo4_reg: gpldo4 {
-		};
-
-		gpldo5_reg: gpldo5 {
-		};
-
-		gpldo6_reg: gpldo6 {
-		};
-
-		vbus_reg: vbus {
-		};
-	};
-};

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:35 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:35 +0100
Subject: [PATCH v6 04/10] mfd: bcm590xx: Drop unused "id" member of
 bcm590xx MFD struct
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-4-ae8302358443@gmail.com>

The "id" member of the bcm590xx struct is unused and will be confusing
once we add an actual PMU ID storage value. Drop it; a replacement
will be introduced in a future commit.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Add this commit
---
 include/linux/mfd/bcm590xx.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index 6b8791da6119b22514447bf1572238b71c8b0e97..c614d1b1d8a217ac2f212908a4c19ae71fa56f63 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -23,7 +23,6 @@ struct bcm590xx {
 	struct i2c_client *i2c_sec;
 	struct regmap *regmap_pri;
 	struct regmap *regmap_sec;
-	unsigned int id;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:36 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:36 +0100
Subject: [PATCH v6 05/10] mfd: bcm590xx: Add support for multiple device
 types + BCM59054 compatible
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-5-ae8302358443@gmail.com>

The BCM59054 is another chip from the BCM590xx line of PMUs, commonly
used on devices with the BCM21664/BCM23550 chipsets.

Prepare the BCM590xx driver for supporting other devices by adding the
PMUID register values for supported chip types and store them in the
MFD data struct as "pmu_id". (These will be checked against the actual
PMUID register values in a later commit.)

Then, add a DT compatible for the BCM59054, and provide the PMU ID as
OF match data.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Move PMUID value to MFD header
- Use PMUID value as OF data/device type value
- Add bcm59054 to I2C ID table

Changes in v4:
- Rewrite commit message description
- Rename "device_type" member to "dev_type"
- Drop awkward line break to fit function call
- Add PMU ID/revision parsing function

Changes in v3:
- Fix compilation warning about device_type pointer cast type
- Name the device types enum and use it as the type in the MFD struct
---
 drivers/mfd/bcm590xx.c       | 12 +++++++++++-
 include/linux/mfd/bcm590xx.h |  7 +++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 8b56786d85d0182acf91da203b5f943556c08422..4620eed0066fbf1dd691a2e392e967747b4d125b 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -50,6 +50,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 	bcm590xx->dev = &i2c_pri->dev;
 	bcm590xx->i2c_pri = i2c_pri;
 
+	bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);
+
 	bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,
 						 &bcm590xx_regmap_config_pri);
 	if (IS_ERR(bcm590xx->regmap_pri)) {
@@ -91,12 +93,20 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 }
 
 static const struct of_device_id bcm590xx_of_match[] = {
-	{ .compatible = "brcm,bcm59056" },
+	{
+		.compatible = "brcm,bcm59054",
+		.data = (void *)BCM590XX_PMUID_BCM59054,
+	},
+	{
+		.compatible = "brcm,bcm59056",
+		.data = (void *)BCM590XX_PMUID_BCM59056,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
 
 static const struct i2c_device_id bcm590xx_i2c_id[] = {
+	{ "bcm59054" },
 	{ "bcm59056" },
 	{ }
 };
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index c614d1b1d8a217ac2f212908a4c19ae71fa56f63..8d146e3b102a7dbce6f4dbab9f8ae5a9c4e68c0e 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -13,6 +13,10 @@
 #include <linux/i2c.h>
 #include <linux/regmap.h>
 
+/* PMU ID register values; also used as device type */
+#define BCM590XX_PMUID_BCM59054		0x54
+#define BCM590XX_PMUID_BCM59056		0x56
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0
@@ -23,6 +27,9 @@ struct bcm590xx {
 	struct i2c_client *i2c_sec;
 	struct regmap *regmap_pri;
 	struct regmap *regmap_sec;
+
+	/* PMU ID value; also used as device type */
+	u8 pmu_id;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:37 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:37 +0100
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-6-ae8302358443@gmail.com>

The BCM590xx PMUs have two I2C registers for reading the PMU ID
and revision. The revision is useful for subdevice drivers, since
different revisions may have slight differences in behavior (for
example - BCM59054 has different regulator configurations for
revision A0 and A1).

Check the PMU ID register and make sure it matches the DT compatible.
Fetch the digital and analog revision from the PMUREV register
so that it can be used in subdevice drivers.

Also add some known revision values to bcm590xx.h, for convenience
when writing subdevice drivers.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Adapt to PMUID being passed as device type value
- Rename rev_dig and rev_ana to rev_digital and rev_analog
- Rewrite commit message

Changes in v5:
- Add REG_ prefix to register offset constant names

Changes in v4:
- Added this commit
---
 drivers/mfd/bcm590xx.c       | 63 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/bcm590xx.h | 14 ++++++++++
 2 files changed, 77 insertions(+)

diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 4620eed0066fbf1dd691a2e392e967747b4d125b..74dc4ae5ecd5db7fadc56918f63110c1265d4a76 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -17,6 +17,15 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+/* Under primary I2C address: */
+#define BCM590XX_REG_PMUID		0x1e
+
+#define BCM590XX_REG_PMUREV		0x1f
+#define BCM590XX_PMUREV_DIG_MASK	0xF
+#define BCM590XX_PMUREV_DIG_SHIFT	0
+#define BCM590XX_PMUREV_ANA_MASK	0xF0
+#define BCM590XX_PMUREV_ANA_SHIFT	4
+
 static const struct mfd_cell bcm590xx_devs[] = {
 	{
 		.name = "bcm590xx-vregs",
@@ -37,6 +46,56 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+/* Map PMU ID value to model name string */
+static const char * const bcm590xx_names[] = {
+	[BCM590XX_PMUID_BCM59054] = "BCM59054",
+	[BCM590XX_PMUID_BCM59056] = "BCM59056",
+};
+
+/*
+ * Parse the version from version registers and make sure it matches
+ * the device type passed to the compatible.
+ */
+static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)
+{
+	unsigned int id, rev;
+	int ret;
+
+	/* Get PMU ID and verify that it matches compatible */
+	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);
+	if (ret) {
+		dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);
+		return ret;
+	}
+
+	if (id != bcm590xx->pmu_id) {
+		dev_err(bcm590xx->dev,
+			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",
+			bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);
+		return -EINVAL;
+	}
+
+	/* Get PMU revision and store it in the info struct */
+	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);
+	if (ret) {
+		dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n",
+			ret);
+		return ret;
+	}
+
+	bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK)
+				     >> BCM590XX_PMUREV_DIG_SHIFT;
+
+	bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK)
+				    >> BCM590XX_PMUREV_ANA_SHIFT;
+
+	dev_info(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",
+		 id, bcm590xx_names[id],
+		 bcm590xx->rev_digital, bcm590xx->rev_analog);
+
+	return 0;
+}
+
 static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 {
 	struct bcm590xx *bcm590xx;
@@ -78,6 +137,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 		goto err;
 	}
 
+	ret = bcm590xx_parse_version(bcm590xx);
+	if (ret)
+		goto err;
+
 	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
 				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
 	if (ret < 0) {
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index 8d146e3b102a7dbce6f4dbab9f8ae5a9c4e68c0e..fbc458e94bef923ca1b69afe2cac944adf6fedf8 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -17,6 +17,16 @@
 #define BCM590XX_PMUID_BCM59054		0x54
 #define BCM590XX_PMUID_BCM59056		0x56
 
+/* Known chip revision IDs */
+#define BCM59054_REV_DIGITAL_A1		1
+#define BCM59054_REV_ANALOG_A1		2
+
+#define BCM59056_REV_DIGITAL_A0		1
+#define BCM59056_REV_ANALOG_A0		1
+
+#define BCM59056_REV_DIGITAL_B0		2
+#define BCM59056_REV_ANALOG_B0		2
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0
@@ -30,6 +40,10 @@ struct bcm590xx {
 
 	/* PMU ID value; also used as device type */
 	u8 pmu_id;
+
+	/* Chip revision, read from PMUREV reg */
+	u8 rev_digital;
+	u8 rev_analog;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:38 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:38 +0100
Subject: [PATCH v6 07/10] regulator: bcm590xx: Use dev_err_probe for
 regulator register error
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-7-ae8302358443@gmail.com>

Instead of calling dev_err() and returning PTR_ERR(...) separately, use
a single "return dev_err_probe" statement.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v4:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 9f0cda46b01506080ae5fa709104a8df4d174a8d..a17311fa30e4d48c0a4925778d7bed486ac7a982 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -340,12 +340,10 @@ static int bcm590xx_probe(struct platform_device *pdev)
 
 		rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
 					       &config);
-		if (IS_ERR(rdev)) {
-			dev_err(bcm590xx->dev,
-				"failed to register %s regulator\n",
-				pdev->name);
-			return PTR_ERR(rdev);
-		}
+		if (IS_ERR(rdev))
+			return dev_err_probe(bcm590xx->dev, PTR_ERR(rdev),
+					     "failed to register %s regulator\n",
+					     pdev->name);
 	}
 
 	return 0;

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:39 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:39 +0100
Subject: [PATCH v6 08/10] regulator: bcm590xx: Store regulator descriptions
 in table
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-8-ae8302358443@gmail.com>

Instead of filling in the regulator description programatically,
store the data in a struct. This will make it a bit nicer to
introduce support for other BCM590xx chips besides the BCM59056.

To do this, add a new struct type, bcm590xx_reg_data, to store
all of the necessary information. Drop the old IS_LDO, IS_GPLDO...
macros in favor of the "type" field in this struct. Adapt the
old bcm590xx_reg struct to the new types.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Adapt to changes in MFD header

Changes in v5:
- Move the bcm590xx_regmap_type enum to the bcm590xx.h header
- Rename bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Replace incorrect return in regmap selection error handling
- Use switch statement for regmap selection

Changes in v3:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 473 ++++++++++++++++++++++-----------
 include/linux/mfd/bcm590xx.h           |   6 +
 2 files changed, 322 insertions(+), 157 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index a17311fa30e4d48c0a4925778d7bed486ac7a982..c2427ea166626bdc1eb7cfb99997d95e5125ed91 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -20,6 +20,18 @@
 
 /* I2C slave 0 registers */
 #define BCM590XX_RFLDOPMCTRL1	0x60
+#define BCM590XX_CAMLDO1PMCTRL1	0x62
+#define BCM590XX_CAMLDO2PMCTRL1	0x64
+#define BCM590XX_SIMLDO1PMCTRL1	0x66
+#define BCM590XX_SIMLDO2PMCTRL1	0x68
+#define BCM590XX_SDLDOPMCTRL1	0x6a
+#define BCM590XX_SDXLDOPMCTRL1	0x6c
+#define BCM590XX_MMCLDO1PMCTRL1	0x6e
+#define BCM590XX_MMCLDO2PMCTRL1	0x70
+#define BCM590XX_AUDLDOPMCTRL1	0x72
+#define BCM590XX_MICLDOPMCTRL1	0x74
+#define BCM590XX_USBLDOPMCTRL1	0x76
+#define BCM590XX_VIBLDOPMCTRL1	0x78
 #define BCM590XX_IOSR1PMCTRL1	0x7a
 #define BCM590XX_IOSR2PMCTRL1	0x7c
 #define BCM590XX_CSRPMCTRL1	0x7e
@@ -28,7 +40,25 @@
 #define BCM590XX_MSRPMCTRL1	0x8a
 #define BCM590XX_VSRPMCTRL1	0x8e
 #define BCM590XX_RFLDOCTRL	0x96
+#define BCM590XX_CAMLDO1CTRL	0x97
+#define BCM590XX_CAMLDO2CTRL	0x98
+#define BCM590XX_SIMLDO1CTRL	0x99
+#define BCM590XX_SIMLDO2CTRL	0x9a
+#define BCM590XX_SDLDOCTRL	0x9b
+#define BCM590XX_SDXLDOCTRL	0x9c
+#define BCM590XX_MMCLDO1CTRL	0x9d
+#define BCM590XX_MMCLDO2CTRL	0x9e
+#define BCM590XX_AUDLDOCTRL	0x9f
+#define BCM590XX_MICLDOCTRL	0xa0
+#define BCM590XX_USBLDOCTRL	0xa1
+#define BCM590XX_VIBLDOCTRL	0xa2
 #define BCM590XX_CSRVOUT1	0xc0
+#define BCM590XX_IOSR1VOUT1	0xc3
+#define BCM590XX_IOSR2VOUT1	0xc6
+#define BCM590XX_MSRVOUT1	0xc9
+#define BCM590XX_SDSR1VOUT1	0xcc
+#define BCM590XX_SDSR2VOUT1	0xcf
+#define BCM590XX_VSRVOUT1	0xd2
 
 /* I2C slave 1 registers */
 #define BCM590XX_GPLDO5PMCTRL1	0x16
@@ -94,11 +124,6 @@
 
 #define BCM590XX_NUM_REGS	27
 
-#define BCM590XX_REG_IS_LDO(n)	(n < BCM590XX_REG_CSR)
-#define BCM590XX_REG_IS_GPLDO(n) \
-	((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
-#define BCM590XX_REG_IS_VBUS(n)	(n == BCM590XX_REG_VBUS)
-
 /* LDO group A: supported voltages in microvolts */
 static const unsigned int ldo_a_table[] = {
 	1200000, 1800000, 2500000, 2700000, 2800000,
@@ -111,10 +136,6 @@ static const unsigned int ldo_c_table[] = {
 	2900000, 3000000, 3300000,
 };
 
-static const unsigned int ldo_vbus[] = {
-	5000000,
-};
-
 /* DCDC group CSR: supported voltages in microvolts */
 static const struct linear_range dcdc_csr_ranges[] = {
 	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
@@ -137,115 +158,25 @@ static const struct linear_range dcdc_sdsr1_ranges[] = {
 	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
 };
 
-struct bcm590xx_info {
-	const char *name;
-	const char *vin_name;
-	u8 n_voltages;
-	const unsigned int *volt_table;
-	u8 n_linear_ranges;
-	const struct linear_range *linear_ranges;
+enum bcm590xx_reg_type {
+	BCM590XX_REG_TYPE_LDO,
+	BCM590XX_REG_TYPE_GPLDO,
+	BCM590XX_REG_TYPE_SR,
+	BCM590XX_REG_TYPE_VBUS
 };
 
-#define BCM590XX_REG_TABLE(_name, _table) \
-	{ \
-		.name = #_name, \
-		.n_voltages = ARRAY_SIZE(_table), \
-		.volt_table = _table, \
-	}
-
-#define BCM590XX_REG_RANGES(_name, _ranges) \
-	{ \
-		.name = #_name, \
-		.n_voltages = 64, \
-		.n_linear_ranges = ARRAY_SIZE(_ranges), \
-		.linear_ranges = _ranges, \
-	}
-
-static struct bcm590xx_info bcm590xx_regs[] = {
-	BCM590XX_REG_TABLE(rfldo, ldo_a_table),
-	BCM590XX_REG_TABLE(camldo1, ldo_c_table),
-	BCM590XX_REG_TABLE(camldo2, ldo_c_table),
-	BCM590XX_REG_TABLE(simldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(simldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(sdldo, ldo_c_table),
-	BCM590XX_REG_TABLE(sdxldo, ldo_a_table),
-	BCM590XX_REG_TABLE(mmcldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(mmcldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(audldo, ldo_a_table),
-	BCM590XX_REG_TABLE(micldo, ldo_a_table),
-	BCM590XX_REG_TABLE(usbldo, ldo_a_table),
-	BCM590XX_REG_TABLE(vibldo, ldo_c_table),
-	BCM590XX_REG_RANGES(csr, dcdc_csr_ranges),
-	BCM590XX_REG_RANGES(iosr1, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(iosr2, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(msr, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
-	BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
-	BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
-	BCM590XX_REG_TABLE(vbus, ldo_vbus),
+struct bcm590xx_reg_data {
+	enum bcm590xx_reg_type type;
+	enum bcm590xx_regmap_type regmap;
+	const struct regulator_desc desc;
 };
 
 struct bcm590xx_reg {
-	struct regulator_desc *desc;
 	struct bcm590xx *mfd;
+	unsigned int n_regulators;
+	const struct bcm590xx_reg_data *regs;
 };
 
-static int bcm590xx_get_vsel_register(int id)
-{
-	if (BCM590XX_REG_IS_LDO(id))
-		return BCM590XX_RFLDOCTRL + id;
-	else if (BCM590XX_REG_IS_GPLDO(id))
-		return BCM590XX_GPLDO1CTRL + id;
-	else
-		return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
-}
-
-static int bcm590xx_get_enable_register(int id)
-{
-	int reg = 0;
-
-	if (BCM590XX_REG_IS_LDO(id))
-		reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
-	else if (BCM590XX_REG_IS_GPLDO(id))
-		reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
-	else
-		switch (id) {
-		case BCM590XX_REG_CSR:
-			reg = BCM590XX_CSRPMCTRL1;
-			break;
-		case BCM590XX_REG_IOSR1:
-			reg = BCM590XX_IOSR1PMCTRL1;
-			break;
-		case BCM590XX_REG_IOSR2:
-			reg = BCM590XX_IOSR2PMCTRL1;
-			break;
-		case BCM590XX_REG_MSR:
-			reg = BCM590XX_MSRPMCTRL1;
-			break;
-		case BCM590XX_REG_SDSR1:
-			reg = BCM590XX_SDSR1PMCTRL1;
-			break;
-		case BCM590XX_REG_SDSR2:
-			reg = BCM590XX_SDSR2PMCTRL1;
-			break;
-		case BCM590XX_REG_VSR:
-			reg = BCM590XX_VSRPMCTRL1;
-			break;
-		case BCM590XX_REG_VBUS:
-			reg = BCM590XX_OTG_CTRL;
-			break;
-		}
-
-
-	return reg;
-}
-
 static const struct regulator_ops bcm590xx_ops_ldo = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
@@ -272,73 +203,301 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 	.disable		= regulator_disable_regmap,
 };
 
+#define BCM590XX_REG_DESC(_name, _name_lower)				\
+	.id = BCM590XX_REG_##_name,					\
+	.name = #_name_lower,						\
+	.of_match = of_match_ptr(#_name_lower),				\
+	.regulators_node = of_match_ptr("regulators"),			\
+	.type = REGULATOR_VOLTAGE,					\
+	.owner = THIS_MODULE						\
+
+#define BCM590XX_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_REG_DESC(_name, _name_lower),				\
+	.ops = &bcm590xx_ops_ldo,					\
+	.n_voltages = ARRAY_SIZE(_table),				\
+	.volt_table = _table,						\
+	.vsel_reg = BCM590XX_##_name##CTRL,				\
+	.vsel_mask = BCM590XX_LDO_VSEL_MASK,				\
+	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_mask = BCM590XX_REG_ENABLE,				\
+	.enable_is_inverted = true
+
+#define BCM590XX_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_REG_DESC(_name, _name_lower),				\
+	.ops = &bcm590xx_ops_dcdc,					\
+	.n_voltages = 64,						\
+	.linear_ranges = _ranges,					\
+	.n_linear_ranges = ARRAY_SIZE(_ranges),				\
+	.vsel_reg = BCM590XX_##_name##VOUT1,				\
+	.vsel_mask = BCM590XX_SR_VSEL_MASK,				\
+	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_mask = BCM590XX_REG_ENABLE,				\
+	.enable_is_inverted = true
+
+static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(RFLDO, rfldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SDLDO, sdldo, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(AUDLDO, audldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MICLDO, micldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(USBLDO, usbldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM590XX_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
 static int bcm590xx_probe(struct platform_device *pdev)
 {
 	struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
 	struct bcm590xx_reg *pmu;
+	const struct bcm590xx_reg_data *info;
 	struct regulator_config config = { };
-	struct bcm590xx_info *info;
 	struct regulator_dev *rdev;
-	int i;
+	unsigned int i;
 
 	pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
 	if (!pmu)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
+	pmu->n_regulators = BCM590XX_NUM_REGS;
+	pmu->regs = bcm590xx_regs;
 
 	platform_set_drvdata(pdev, pmu);
 
-	pmu->desc = devm_kcalloc(&pdev->dev,
-				 BCM590XX_NUM_REGS,
-				 sizeof(struct regulator_desc),
-				 GFP_KERNEL);
-	if (!pmu->desc)
-		return -ENOMEM;
-
-	info = bcm590xx_regs;
-
-	for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) {
-		/* Register the regulators */
-		pmu->desc[i].name = info->name;
-		pmu->desc[i].of_match = of_match_ptr(info->name);
-		pmu->desc[i].regulators_node = of_match_ptr("regulators");
-		pmu->desc[i].supply_name = info->vin_name;
-		pmu->desc[i].id = i;
-		pmu->desc[i].volt_table = info->volt_table;
-		pmu->desc[i].n_voltages = info->n_voltages;
-		pmu->desc[i].linear_ranges = info->linear_ranges;
-		pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
-
-		if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
-			pmu->desc[i].ops = &bcm590xx_ops_ldo;
-			pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
-		} else if (BCM590XX_REG_IS_VBUS(i))
-			pmu->desc[i].ops = &bcm590xx_ops_vbus;
-		else {
-			pmu->desc[i].ops = &bcm590xx_ops_dcdc;
-			pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
-		}
-
-		if (BCM590XX_REG_IS_VBUS(i))
-			pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
-		else {
-			pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
-			pmu->desc[i].enable_is_inverted = true;
-			pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
-		}
-		pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
-		pmu->desc[i].type = REGULATOR_VOLTAGE;
-		pmu->desc[i].owner = THIS_MODULE;
+	/* Register the regulators */
+	for (i = 0; i < pmu->n_regulators; i++) {
+		info = &pmu->regs[i];
 
 		config.dev = bcm590xx->dev;
 		config.driver_data = pmu;
-		if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
-			config.regmap = bcm590xx->regmap_sec;
-		else
+
+		switch (info->regmap) {
+		case BCM590XX_REGMAP_PRI:
 			config.regmap = bcm590xx->regmap_pri;
+			break;
+		case BCM590XX_REGMAP_SEC:
+			config.regmap = bcm590xx->regmap_sec;
+			break;
+		default:
+			dev_err(bcm590xx->dev,
+				"invalid regmap for %s regulator; this is a driver bug\n",
+				pdev->name);
+			return -EINVAL;
+		}
 
-		rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
+		rdev = devm_regulator_register(&pdev->dev, &info->desc,
 					       &config);
 		if (IS_ERR(rdev))
 			return dev_err_probe(bcm590xx->dev, PTR_ERR(rdev),
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index fbc458e94bef923ca1b69afe2cac944adf6fedf8..5a5783abd47b9a6bb6f9bb3a8cafddbd01aa7fcc 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -27,6 +27,12 @@
 #define BCM59056_REV_DIGITAL_B0		2
 #define BCM59056_REV_ANALOG_B0		2
 
+/* regmap types */
+enum bcm590xx_regmap_type {
+	BCM590XX_REGMAP_PRI,
+	BCM590XX_REGMAP_SEC,
+};
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:40 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:40 +0100
Subject: [PATCH v6 09/10] regulator: bcm590xx: Rename BCM59056-specific
 data as such
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-9-ae8302358443@gmail.com>

Previously, the driver used the BCM590XX prefix for register data
specific to the BCM59056. As we will be introducing other regulators
to this driver as well, make the BCM59056-specific values use the
BCM59056 prefix.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v5:
- Adapt to rename of bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Drop unused BCM590XX_MAX_NUM_REGS constant

Changes in v3:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 369 +++++++++++++++++----------------
 1 file changed, 189 insertions(+), 180 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index c2427ea166626bdc1eb7cfb99997d95e5125ed91..f35b2b72e46f70496e16be5244529a5d95d0546d 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -18,146 +18,11 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
 
-/* I2C slave 0 registers */
-#define BCM590XX_RFLDOPMCTRL1	0x60
-#define BCM590XX_CAMLDO1PMCTRL1	0x62
-#define BCM590XX_CAMLDO2PMCTRL1	0x64
-#define BCM590XX_SIMLDO1PMCTRL1	0x66
-#define BCM590XX_SIMLDO2PMCTRL1	0x68
-#define BCM590XX_SDLDOPMCTRL1	0x6a
-#define BCM590XX_SDXLDOPMCTRL1	0x6c
-#define BCM590XX_MMCLDO1PMCTRL1	0x6e
-#define BCM590XX_MMCLDO2PMCTRL1	0x70
-#define BCM590XX_AUDLDOPMCTRL1	0x72
-#define BCM590XX_MICLDOPMCTRL1	0x74
-#define BCM590XX_USBLDOPMCTRL1	0x76
-#define BCM590XX_VIBLDOPMCTRL1	0x78
-#define BCM590XX_IOSR1PMCTRL1	0x7a
-#define BCM590XX_IOSR2PMCTRL1	0x7c
-#define BCM590XX_CSRPMCTRL1	0x7e
-#define BCM590XX_SDSR1PMCTRL1	0x82
-#define BCM590XX_SDSR2PMCTRL1	0x86
-#define BCM590XX_MSRPMCTRL1	0x8a
-#define BCM590XX_VSRPMCTRL1	0x8e
-#define BCM590XX_RFLDOCTRL	0x96
-#define BCM590XX_CAMLDO1CTRL	0x97
-#define BCM590XX_CAMLDO2CTRL	0x98
-#define BCM590XX_SIMLDO1CTRL	0x99
-#define BCM590XX_SIMLDO2CTRL	0x9a
-#define BCM590XX_SDLDOCTRL	0x9b
-#define BCM590XX_SDXLDOCTRL	0x9c
-#define BCM590XX_MMCLDO1CTRL	0x9d
-#define BCM590XX_MMCLDO2CTRL	0x9e
-#define BCM590XX_AUDLDOCTRL	0x9f
-#define BCM590XX_MICLDOCTRL	0xa0
-#define BCM590XX_USBLDOCTRL	0xa1
-#define BCM590XX_VIBLDOCTRL	0xa2
-#define BCM590XX_CSRVOUT1	0xc0
-#define BCM590XX_IOSR1VOUT1	0xc3
-#define BCM590XX_IOSR2VOUT1	0xc6
-#define BCM590XX_MSRVOUT1	0xc9
-#define BCM590XX_SDSR1VOUT1	0xcc
-#define BCM590XX_SDSR2VOUT1	0xcf
-#define BCM590XX_VSRVOUT1	0xd2
-
-/* I2C slave 1 registers */
-#define BCM590XX_GPLDO5PMCTRL1	0x16
-#define BCM590XX_GPLDO6PMCTRL1	0x18
-#define BCM590XX_GPLDO1CTRL	0x1a
-#define BCM590XX_GPLDO2CTRL	0x1b
-#define BCM590XX_GPLDO3CTRL	0x1c
-#define BCM590XX_GPLDO4CTRL	0x1d
-#define BCM590XX_GPLDO5CTRL	0x1e
-#define BCM590XX_GPLDO6CTRL	0x1f
-#define BCM590XX_OTG_CTRL	0x40
-#define BCM590XX_GPLDO1PMCTRL1	0x57
-#define BCM590XX_GPLDO2PMCTRL1	0x59
-#define BCM590XX_GPLDO3PMCTRL1	0x5b
-#define BCM590XX_GPLDO4PMCTRL1	0x5d
-
 #define BCM590XX_REG_ENABLE	BIT(7)
 #define BCM590XX_VBUS_ENABLE	BIT(2)
 #define BCM590XX_LDO_VSEL_MASK	GENMASK(5, 3)
 #define BCM590XX_SR_VSEL_MASK	GENMASK(5, 0)
 
-/*
- * RFLDO to VSR regulators are
- * accessed via I2C slave 0
- */
-
-/* LDO regulator IDs */
-#define BCM590XX_REG_RFLDO	0
-#define BCM590XX_REG_CAMLDO1	1
-#define BCM590XX_REG_CAMLDO2	2
-#define BCM590XX_REG_SIMLDO1	3
-#define BCM590XX_REG_SIMLDO2	4
-#define BCM590XX_REG_SDLDO	5
-#define BCM590XX_REG_SDXLDO	6
-#define BCM590XX_REG_MMCLDO1	7
-#define BCM590XX_REG_MMCLDO2	8
-#define BCM590XX_REG_AUDLDO	9
-#define BCM590XX_REG_MICLDO	10
-#define BCM590XX_REG_USBLDO	11
-#define BCM590XX_REG_VIBLDO	12
-
-/* DCDC regulator IDs */
-#define BCM590XX_REG_CSR	13
-#define BCM590XX_REG_IOSR1	14
-#define BCM590XX_REG_IOSR2	15
-#define BCM590XX_REG_MSR	16
-#define BCM590XX_REG_SDSR1	17
-#define BCM590XX_REG_SDSR2	18
-#define BCM590XX_REG_VSR	19
-
-/*
- * GPLDO1 to VBUS regulators are
- * accessed via I2C slave 1
- */
-
-#define BCM590XX_REG_GPLDO1	20
-#define BCM590XX_REG_GPLDO2	21
-#define BCM590XX_REG_GPLDO3	22
-#define BCM590XX_REG_GPLDO4	23
-#define BCM590XX_REG_GPLDO5	24
-#define BCM590XX_REG_GPLDO6	25
-#define BCM590XX_REG_VBUS	26
-
-#define BCM590XX_NUM_REGS	27
-
-/* LDO group A: supported voltages in microvolts */
-static const unsigned int ldo_a_table[] = {
-	1200000, 1800000, 2500000, 2700000, 2800000,
-	2900000, 3000000, 3300000,
-};
-
-/* LDO group C: supported voltages in microvolts */
-static const unsigned int ldo_c_table[] = {
-	3100000, 1800000, 2500000, 2700000, 2800000,
-	2900000, 3000000, 3300000,
-};
-
-/* DCDC group CSR: supported voltages in microvolts */
-static const struct linear_range dcdc_csr_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
-	REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
-	REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
-};
-
-/* DCDC group IOSR1: supported voltages in microvolts */
-static const struct linear_range dcdc_iosr1_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
-	REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
-	REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
-	REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
-};
-
-/* DCDC group SDSR1: supported voltages in microvolts */
-static const struct linear_range dcdc_sdsr1_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
-	REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
-	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
-};
-
 enum bcm590xx_reg_type {
 	BCM590XX_REG_TYPE_LDO,
 	BCM590XX_REG_TYPE_GPLDO,
@@ -203,43 +68,187 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 	.disable		= regulator_disable_regmap,
 };
 
-#define BCM590XX_REG_DESC(_name, _name_lower)				\
-	.id = BCM590XX_REG_##_name,					\
+#define BCM590XX_REG_DESC(_model, _name, _name_lower)			\
+	.id = _model##_REG_##_name,					\
 	.name = #_name_lower,						\
 	.of_match = of_match_ptr(#_name_lower),				\
 	.regulators_node = of_match_ptr("regulators"),			\
 	.type = REGULATOR_VOLTAGE,					\
 	.owner = THIS_MODULE						\
 
-#define BCM590XX_LDO_DESC(_name, _name_lower, _table)			\
-	BCM590XX_REG_DESC(_name, _name_lower),				\
+#define BCM590XX_LDO_DESC(_model, _model_lower, _name, _name_lower, _table) \
+	BCM590XX_REG_DESC(_model, _name, _name_lower),			\
 	.ops = &bcm590xx_ops_ldo,					\
-	.n_voltages = ARRAY_SIZE(_table),				\
-	.volt_table = _table,						\
-	.vsel_reg = BCM590XX_##_name##CTRL,				\
+	.n_voltages = ARRAY_SIZE(_model_lower##_##_table),		\
+	.volt_table = _model_lower##_##_table,				\
+	.vsel_reg = _model##_##_name##CTRL,				\
 	.vsel_mask = BCM590XX_LDO_VSEL_MASK,				\
-	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_reg = _model##_##_name##PMCTRL1,			\
 	.enable_mask = BCM590XX_REG_ENABLE,				\
 	.enable_is_inverted = true
 
-#define BCM590XX_SR_DESC(_name, _name_lower, _ranges)			\
-	BCM590XX_REG_DESC(_name, _name_lower),				\
+#define BCM590XX_SR_DESC(_model, _model_lower, _name, _name_lower, _ranges) \
+	BCM590XX_REG_DESC(_model, _name, _name_lower),			\
 	.ops = &bcm590xx_ops_dcdc,					\
 	.n_voltages = 64,						\
-	.linear_ranges = _ranges,					\
-	.n_linear_ranges = ARRAY_SIZE(_ranges),				\
-	.vsel_reg = BCM590XX_##_name##VOUT1,				\
+	.linear_ranges = _model_lower##_##_ranges,			\
+	.n_linear_ranges = ARRAY_SIZE(_model_lower##_##_ranges),	\
+	.vsel_reg = _model##_##_name##VOUT1,				\
 	.vsel_mask = BCM590XX_SR_VSEL_MASK,				\
-	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_reg = _model##_##_name##PMCTRL1,			\
 	.enable_mask = BCM590XX_REG_ENABLE,				\
 	.enable_is_inverted = true
 
-static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
+#define BCM59056_REG_DESC(_name, _name_lower)				\
+	BCM590XX_REG_DESC(BCM59056, _name, _name_lower)
+#define BCM59056_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_LDO_DESC(BCM59056, bcm59056, _name, _name_lower, _table)
+#define BCM59056_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_SR_DESC(BCM59056, bcm59056, _name, _name_lower, _ranges)
+
+/* BCM59056 data */
+
+/* I2C slave 0 registers */
+#define BCM59056_RFLDOPMCTRL1	0x60
+#define BCM59056_CAMLDO1PMCTRL1	0x62
+#define BCM59056_CAMLDO2PMCTRL1	0x64
+#define BCM59056_SIMLDO1PMCTRL1	0x66
+#define BCM59056_SIMLDO2PMCTRL1	0x68
+#define BCM59056_SDLDOPMCTRL1	0x6a
+#define BCM59056_SDXLDOPMCTRL1	0x6c
+#define BCM59056_MMCLDO1PMCTRL1	0x6e
+#define BCM59056_MMCLDO2PMCTRL1	0x70
+#define BCM59056_AUDLDOPMCTRL1	0x72
+#define BCM59056_MICLDOPMCTRL1	0x74
+#define BCM59056_USBLDOPMCTRL1	0x76
+#define BCM59056_VIBLDOPMCTRL1	0x78
+#define BCM59056_IOSR1PMCTRL1	0x7a
+#define BCM59056_IOSR2PMCTRL1	0x7c
+#define BCM59056_CSRPMCTRL1	0x7e
+#define BCM59056_SDSR1PMCTRL1	0x82
+#define BCM59056_SDSR2PMCTRL1	0x86
+#define BCM59056_MSRPMCTRL1	0x8a
+#define BCM59056_VSRPMCTRL1	0x8e
+#define BCM59056_RFLDOCTRL	0x96
+#define BCM59056_CAMLDO1CTRL	0x97
+#define BCM59056_CAMLDO2CTRL	0x98
+#define BCM59056_SIMLDO1CTRL	0x99
+#define BCM59056_SIMLDO2CTRL	0x9a
+#define BCM59056_SDLDOCTRL	0x9b
+#define BCM59056_SDXLDOCTRL	0x9c
+#define BCM59056_MMCLDO1CTRL	0x9d
+#define BCM59056_MMCLDO2CTRL	0x9e
+#define BCM59056_AUDLDOCTRL	0x9f
+#define BCM59056_MICLDOCTRL	0xa0
+#define BCM59056_USBLDOCTRL	0xa1
+#define BCM59056_VIBLDOCTRL	0xa2
+#define BCM59056_CSRVOUT1	0xc0
+#define BCM59056_IOSR1VOUT1	0xc3
+#define BCM59056_IOSR2VOUT1	0xc6
+#define BCM59056_MSRVOUT1	0xc9
+#define BCM59056_SDSR1VOUT1	0xcc
+#define BCM59056_SDSR2VOUT1	0xcf
+#define BCM59056_VSRVOUT1	0xd2
+
+/* I2C slave 1 registers */
+#define BCM59056_GPLDO5PMCTRL1	0x16
+#define BCM59056_GPLDO6PMCTRL1	0x18
+#define BCM59056_GPLDO1CTRL	0x1a
+#define BCM59056_GPLDO2CTRL	0x1b
+#define BCM59056_GPLDO3CTRL	0x1c
+#define BCM59056_GPLDO4CTRL	0x1d
+#define BCM59056_GPLDO5CTRL	0x1e
+#define BCM59056_GPLDO6CTRL	0x1f
+#define BCM59056_OTG_CTRL	0x40
+#define BCM59056_GPLDO1PMCTRL1	0x57
+#define BCM59056_GPLDO2PMCTRL1	0x59
+#define BCM59056_GPLDO3PMCTRL1	0x5b
+#define BCM59056_GPLDO4PMCTRL1	0x5d
+
+/*
+ * RFLDO to VSR regulators are
+ * accessed via I2C slave 0
+ */
+
+/* LDO regulator IDs */
+#define BCM59056_REG_RFLDO	0
+#define BCM59056_REG_CAMLDO1	1
+#define BCM59056_REG_CAMLDO2	2
+#define BCM59056_REG_SIMLDO1	3
+#define BCM59056_REG_SIMLDO2	4
+#define BCM59056_REG_SDLDO	5
+#define BCM59056_REG_SDXLDO	6
+#define BCM59056_REG_MMCLDO1	7
+#define BCM59056_REG_MMCLDO2	8
+#define BCM59056_REG_AUDLDO	9
+#define BCM59056_REG_MICLDO	10
+#define BCM59056_REG_USBLDO	11
+#define BCM59056_REG_VIBLDO	12
+
+/* DCDC regulator IDs */
+#define BCM59056_REG_CSR	13
+#define BCM59056_REG_IOSR1	14
+#define BCM59056_REG_IOSR2	15
+#define BCM59056_REG_MSR	16
+#define BCM59056_REG_SDSR1	17
+#define BCM59056_REG_SDSR2	18
+#define BCM59056_REG_VSR	19
+
+/*
+ * GPLDO1 to VBUS regulators are
+ * accessed via I2C slave 1
+ */
+
+#define BCM59056_REG_GPLDO1	20
+#define BCM59056_REG_GPLDO2	21
+#define BCM59056_REG_GPLDO3	22
+#define BCM59056_REG_GPLDO4	23
+#define BCM59056_REG_GPLDO5	24
+#define BCM59056_REG_GPLDO6	25
+#define BCM59056_REG_VBUS	26
+
+#define BCM59056_NUM_REGS	27
+
+/* LDO group A: supported voltages in microvolts */
+static const unsigned int bcm59056_ldo_a_table[] = {
+	1200000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group C: supported voltages in microvolts */
+static const unsigned int bcm59056_ldo_c_table[] = {
+	3100000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* DCDC group CSR: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_csr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
+	REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
+	REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
+};
+
+/* DCDC group IOSR1: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_iosr1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
+	REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
+};
+
+/* DCDC group SDSR1: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_sdsr1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
+	REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
+	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
+};
+
+static const struct bcm590xx_reg_data bcm59056_regs[BCM59056_NUM_REGS] = {
 	{
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(RFLDO, rfldo, ldo_a_table),
+			BCM59056_LDO_DESC(RFLDO, rfldo, ldo_a_table),
 		},
 	},
 
@@ -247,7 +256,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
+			BCM59056_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
 		},
 	},
 
@@ -255,7 +264,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
+			BCM59056_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
 		},
 	},
 
@@ -263,7 +272,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
+			BCM59056_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
 		},
 	},
 
@@ -271,7 +280,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
+			BCM59056_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
 		},
 	},
 
@@ -279,7 +288,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SDLDO, sdldo, ldo_c_table),
+			BCM59056_LDO_DESC(SDLDO, sdldo, ldo_c_table),
 		},
 	},
 
@@ -287,7 +296,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
+			BCM59056_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
 		},
 	},
 
@@ -295,7 +304,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
+			BCM59056_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
 		},
 	},
 
@@ -303,7 +312,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
+			BCM59056_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
 		},
 	},
 
@@ -311,7 +320,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(AUDLDO, audldo, ldo_a_table),
+			BCM59056_LDO_DESC(AUDLDO, audldo, ldo_a_table),
 		},
 	},
 
@@ -319,7 +328,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MICLDO, micldo, ldo_a_table),
+			BCM59056_LDO_DESC(MICLDO, micldo, ldo_a_table),
 		},
 	},
 
@@ -327,7 +336,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(USBLDO, usbldo, ldo_a_table),
+			BCM59056_LDO_DESC(USBLDO, usbldo, ldo_a_table),
 		},
 	},
 
@@ -335,7 +344,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
+			BCM59056_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
 		},
 	},
 
@@ -343,7 +352,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(CSR, csr, dcdc_csr_ranges),
+			BCM59056_SR_DESC(CSR, csr, dcdc_csr_ranges),
 		},
 	},
 
@@ -351,7 +360,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -359,7 +368,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -367,7 +376,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -375,7 +384,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
+			BCM59056_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
 		},
 	},
 
@@ -383,7 +392,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -391,7 +400,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -399,7 +408,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
 		},
 	},
 
@@ -407,7 +416,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
 		},
 	},
 
@@ -415,7 +424,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
 		},
 	},
 
@@ -423,7 +432,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
 		},
 	},
 
@@ -431,7 +440,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
 		},
 	},
 
@@ -439,7 +448,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
 		},
 	},
 
@@ -447,11 +456,11 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_VBUS,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_REG_DESC(VBUS, vbus),
+			BCM59056_REG_DESC(VBUS, vbus),
 			.ops = &bcm590xx_ops_vbus,
 			.n_voltages = 1,
 			.fixed_uV = 5000000,
-			.enable_reg = BCM590XX_OTG_CTRL,
+			.enable_reg = BCM59056_OTG_CTRL,
 			.enable_mask = BCM590XX_VBUS_ENABLE,
 		},
 	},
@@ -471,8 +480,8 @@ static int bcm590xx_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
-	pmu->n_regulators = BCM590XX_NUM_REGS;
-	pmu->regs = bcm590xx_regs;
+	pmu->n_regulators = BCM59056_NUM_REGS;
+	pmu->regs = bcm59056_regs;
 
 	platform_set_drvdata(pdev, pmu);
 

-- 
2.48.1



From aweber.kernel at gmail.com  Mon Mar  3 22:20:41 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 04 Mar 2025 07:20:41 +0100
Subject: [PATCH v6 10/10] regulator: bcm590xx: Add support for BCM59054
 regulators
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250304-bcm59054-v6-10-ae8302358443@gmail.com>

The BCM59056 and BCM59054 are very similar in terms of regulators. Add
the register definitions for the BCM59054 and enable support for it in
the driver.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- dev_type -> pmu_id conversion, rev_ana -> rev_analog rename

Changes in v5:
- Adapt to regmap type enum being moved/value names being renamed
- Adapt to rename of bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Lock MICLDO at 1.8v to match vendor kernel behavior
- Set different voltage table for VSR based on PMU revision
- Fix incorrect table being used for LVLDO1
- Add missing newline to "unknown device type" error message

Changes in v3:
- Adapt to regulator info being moved to tables
---
 drivers/regulator/bcm590xx-regulator.c | 649 ++++++++++++++++++++++++++++++++-
 1 file changed, 647 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index f35b2b72e46f70496e16be5244529a5d95d0546d..50414f4cb10958bb33a9fcfa5ed5aaecde9d0715 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -52,6 +52,17 @@ static const struct regulator_ops bcm590xx_ops_ldo = {
 	.map_voltage		= regulator_map_voltage_iterate,
 };
 
+/*
+ * LDO ops without voltage selection, used for MICLDO on BCM59054.
+ * (These are currently the same as VBUS ops, but will be different
+ * in the future once full PMMODE support is implemented.)
+ */
+static const struct regulator_ops bcm590xx_ops_ldo_novolt = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+};
+
 static const struct regulator_ops bcm590xx_ops_dcdc = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
@@ -106,6 +117,13 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 #define BCM59056_SR_DESC(_name, _name_lower, _ranges)			\
 	BCM590XX_SR_DESC(BCM59056, bcm59056, _name, _name_lower, _ranges)
 
+#define BCM59054_REG_DESC(_name, _name_lower)				\
+	BCM590XX_REG_DESC(BCM59054, _name, _name_lower)
+#define BCM59054_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_LDO_DESC(BCM59054, bcm59054, _name, _name_lower, _table)
+#define BCM59054_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_SR_DESC(BCM59054, bcm59054, _name, _name_lower, _ranges)
+
 /* BCM59056 data */
 
 /* I2C slave 0 registers */
@@ -466,6 +484,617 @@ static const struct bcm590xx_reg_data bcm59056_regs[BCM59056_NUM_REGS] = {
 	},
 };
 
+/* BCM59054 data */
+
+/* I2C slave 0 registers */
+#define BCM59054_RFLDOPMCTRL1	0x60
+#define BCM59054_CAMLDO1PMCTRL1	0x62
+#define BCM59054_CAMLDO2PMCTRL1	0x64
+#define BCM59054_SIMLDO1PMCTRL1	0x66
+#define BCM59054_SIMLDO2PMCTRL1	0x68
+#define BCM59054_SDLDOPMCTRL1	0x6a
+#define BCM59054_SDXLDOPMCTRL1	0x6c
+#define BCM59054_MMCLDO1PMCTRL1	0x6e
+#define BCM59054_MMCLDO2PMCTRL1	0x70
+#define BCM59054_AUDLDOPMCTRL1	0x72
+#define BCM59054_MICLDOPMCTRL1	0x74
+#define BCM59054_USBLDOPMCTRL1	0x76
+#define BCM59054_VIBLDOPMCTRL1	0x78
+#define BCM59054_IOSR1PMCTRL1	0x7a
+#define BCM59054_IOSR2PMCTRL1	0x7c
+#define BCM59054_CSRPMCTRL1	0x7e
+#define BCM59054_SDSR1PMCTRL1	0x82
+#define BCM59054_SDSR2PMCTRL1	0x86
+#define BCM59054_MMSRPMCTRL1	0x8a
+#define BCM59054_VSRPMCTRL1	0x8e
+#define BCM59054_RFLDOCTRL	0x96
+#define BCM59054_CAMLDO1CTRL	0x97
+#define BCM59054_CAMLDO2CTRL	0x98
+#define BCM59054_SIMLDO1CTRL	0x99
+#define BCM59054_SIMLDO2CTRL	0x9a
+#define BCM59054_SDLDOCTRL	0x9b
+#define BCM59054_SDXLDOCTRL	0x9c
+#define BCM59054_MMCLDO1CTRL	0x9d
+#define BCM59054_MMCLDO2CTRL	0x9e
+#define BCM59054_AUDLDOCTRL	0x9f
+#define BCM59054_MICLDOCTRL	0xa0
+#define BCM59054_USBLDOCTRL	0xa1
+#define BCM59054_VIBLDOCTRL	0xa2
+#define BCM59054_CSRVOUT1	0xc0
+#define BCM59054_IOSR1VOUT1	0xc3
+#define BCM59054_IOSR2VOUT1	0xc6
+#define BCM59054_MMSRVOUT1	0xc9
+#define BCM59054_SDSR1VOUT1	0xcc
+#define BCM59054_SDSR2VOUT1	0xcf
+#define BCM59054_VSRVOUT1	0xd2
+
+/* I2C slave 1 registers */
+#define BCM59054_LVLDO1PMCTRL1	0x16
+#define BCM59054_LVLDO2PMCTRL1	0x18
+#define BCM59054_GPLDO1CTRL	0x1a
+#define BCM59054_GPLDO2CTRL	0x1b
+#define BCM59054_GPLDO3CTRL	0x1c
+#define BCM59054_TCXLDOCTRL	0x1d
+#define BCM59054_LVLDO1CTRL	0x1e
+#define BCM59054_LVLDO2CTRL	0x1f
+#define BCM59054_OTG_CTRL	0x40
+#define BCM59054_GPLDO1PMCTRL1	0x57
+#define BCM59054_GPLDO2PMCTRL1	0x59
+#define BCM59054_GPLDO3PMCTRL1	0x5b
+#define BCM59054_TCXLDOPMCTRL1	0x5d
+
+/*
+ * RFLDO to VSR regulators are
+ * accessed via I2C slave 0
+ */
+
+/* LDO regulator IDs */
+#define BCM59054_REG_RFLDO	0
+#define BCM59054_REG_CAMLDO1	1
+#define BCM59054_REG_CAMLDO2	2
+#define BCM59054_REG_SIMLDO1	3
+#define BCM59054_REG_SIMLDO2	4
+#define BCM59054_REG_SDLDO	5
+#define BCM59054_REG_SDXLDO	6
+#define BCM59054_REG_MMCLDO1	7
+#define BCM59054_REG_MMCLDO2	8
+#define BCM59054_REG_AUDLDO	9
+#define BCM59054_REG_MICLDO	10
+#define BCM59054_REG_USBLDO	11
+#define BCM59054_REG_VIBLDO	12
+
+/* DCDC regulator IDs */
+#define BCM59054_REG_CSR	13
+#define BCM59054_REG_IOSR1	14
+#define BCM59054_REG_IOSR2	15
+#define BCM59054_REG_MMSR	16
+#define BCM59054_REG_SDSR1	17
+#define BCM59054_REG_SDSR2	18
+#define BCM59054_REG_VSR	19
+
+/*
+ * GPLDO1 to VBUS regulators are
+ * accessed via I2C slave 1
+ */
+
+#define BCM59054_REG_GPLDO1	20
+#define BCM59054_REG_GPLDO2	21
+#define BCM59054_REG_GPLDO3	22
+#define BCM59054_REG_TCXLDO	23
+#define BCM59054_REG_LVLDO1	24
+#define BCM59054_REG_LVLDO2	25
+#define BCM59054_REG_VBUS	26
+
+#define BCM59054_NUM_REGS	27
+
+/* LDO group 1: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_1_table[] = {
+	1200000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group 2: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_2_table[] = {
+	3100000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group 3: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_3_table[] = {
+	1000000, 1107000, 1143000, 1214000, 1250000,
+	1464000, 1500000, 1786000,
+};
+
+/* DCDC group SR: supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_sr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(0, 0, 1, 0),
+	REGULATOR_LINEAR_RANGE(860000, 2, 60, 10000),
+	REGULATOR_LINEAR_RANGE(1500000, 61, 61, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 62, 62, 0),
+	REGULATOR_LINEAR_RANGE(900000, 63, 63, 0),
+};
+
+/* DCDC group VSR (BCM59054A1): supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_vsr_a1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(0, 0, 1, 0),
+	REGULATOR_LINEAR_RANGE(860000, 2, 59, 10000),
+	REGULATOR_LINEAR_RANGE(1700000, 60, 60, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 61, 61, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 62, 62, 0),
+	REGULATOR_LINEAR_RANGE(1600000, 63, 63, 0),
+};
+
+/* DCDC group CSR: supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_csr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 1, 100000),
+	REGULATOR_LINEAR_RANGE(860000, 2, 60, 10000),
+	REGULATOR_LINEAR_RANGE(900000, 61, 63, 0),
+};
+
+static const struct bcm590xx_reg_data bcm59054_regs[BCM59054_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(RFLDO, rfldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO1, camldo1, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO2, camldo2, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO1, simldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO2, simldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDLDO, sdldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDXLDO, sdxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO1, mmcldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO2, mmcldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(AUDLDO, audldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_REG_DESC(MICLDO, micldo),
+			.ops = &bcm590xx_ops_ldo_novolt,
+			/* MICLDO is locked at 1.8V */
+			.n_voltages = 1,
+			.fixed_uV = 1800000,
+			.enable_reg = BCM59054_MICLDOPMCTRL1,
+			.enable_mask = BCM590XX_REG_ENABLE,
+			.enable_is_inverted = true,
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(USBLDO, usbldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(VIBLDO, vibldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR1, iosr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR2, iosr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(MMSR, mmsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR1, sdsr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR2, sdsr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(VSR, vsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO1, gpldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO2, gpldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO3, gpldo3, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(TCXLDO, tcxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO1, lvldo1, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO2, lvldo2, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM59054_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
+/*
+ * BCM59054A1 regulators; same as previous revision, but with different
+ * VSR voltage table.
+ */
+static const struct bcm590xx_reg_data bcm59054_a1_regs[BCM59054_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(RFLDO, rfldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO1, camldo1, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO2, camldo2, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO1, simldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO2, simldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDLDO, sdldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDXLDO, sdxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO1, mmcldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO2, mmcldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(AUDLDO, audldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_REG_DESC(MICLDO, micldo),
+			.ops = &bcm590xx_ops_ldo_novolt,
+			/* MICLDO is locked at 1.8V */
+			.n_voltages = 1,
+			.fixed_uV = 1800000,
+			.enable_reg = BCM59054_MICLDOPMCTRL1,
+			.enable_mask = BCM590XX_REG_ENABLE,
+			.enable_is_inverted = true,
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(USBLDO, usbldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(VIBLDO, vibldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR1, iosr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR2, iosr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(MMSR, mmsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR1, sdsr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR2, sdsr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(VSR, vsr, dcdc_vsr_a1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO1, gpldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO2, gpldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO3, gpldo3, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(TCXLDO, tcxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO1, lvldo1, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO2, lvldo2, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM59054_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
 static int bcm590xx_probe(struct platform_device *pdev)
 {
 	struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
@@ -480,8 +1109,24 @@ static int bcm590xx_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
-	pmu->n_regulators = BCM59056_NUM_REGS;
-	pmu->regs = bcm59056_regs;
+
+	switch (pmu->mfd->pmu_id) {
+	case BCM590XX_PMUID_BCM59054:
+		pmu->n_regulators = BCM59054_NUM_REGS;
+		if (pmu->mfd->rev_analog == BCM59054_REV_ANALOG_A1)
+			pmu->regs = bcm59054_a1_regs;
+		else
+			pmu->regs = bcm59054_regs;
+		break;
+	case BCM590XX_PMUID_BCM59056:
+		pmu->n_regulators = BCM59056_NUM_REGS;
+		pmu->regs = bcm59056_regs;
+		break;
+	default:
+		dev_err(bcm590xx->dev,
+			"unknown device type, could not initialize\n");
+		return -EINVAL;
+	}
 
 	platform_set_drvdata(pdev, pmu);
 

-- 
2.48.1



From gshan at redhat.com  Mon Mar  3 22:23:52 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 16:23:52 +1000
Subject: [PATCH v7 30/45] arm64: RME: Always use 4k pages for realms
In-Reply-To: <20250213161426.102987-31-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-31-steven.price@arm.com>
Message-ID: <9d32bfed-31f2-49ad-ae43-87e60957ad74@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> Always split up huge pages to avoid problems managing huge pages. There
> are two issues currently:
> 
> 1. The uABI for the VMM allows populating memory on 4k boundaries even
>     if the underlying allocator (e.g. hugetlbfs) is using a larger page
>     size. Using a memfd for private allocations will push this issue onto
>     the VMM as it will need to respect the granularity of the allocator.
> 
> 2. The guest is able to request arbitrary ranges to be remapped as
>     shared. Again with a memfd approach it will be up to the VMM to deal
>     with the complexity and either overmap (need the huge mapping and add
>     an additional 'overlapping' shared mapping) or reject the request as
>     invalid due to the use of a huge page allocator.
> 
> For now just break everything down to 4k pages in the RMM controlled
> stage 2.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/mmu.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 

The change log looks confusing to me. Currently, there are 3 classes of stage2 faults,
handled by their corresponding handlers like below.

stage2 fault in the private space: private_memslot_fault()
stage2 fault in the MMIO space:    io_mem_abort()
stage2 fault in the shared space:  user_mem_abort()

Only the stage2 fault in the private space needs to allocate a 4KB page from guest-memfd.
This patch is changing user_mem_abort(), which is all about the stage2 fault in the shared
space, where a guest-memfd isn't involved. The only intersection between the private/shared
space is the stage2 page table. I'm guessing we want to have enforced 4KB page is due to
the shared stage2 page table by the private/shared space, or I'm wrong.

What I'm understanding from the change log: it's something to be improved in future due to
only 4KB pages can be supported by guest-memfd. Please correct me if I'm wrong.

> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 994e71cfb358..8c656a0ef4e9 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1641,6 +1641,10 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>   	if (logging_active || is_protected_kvm_enabled()) {
>   		force_pte = true;
>   		vma_shift = PAGE_SHIFT;
> +	} else if (vcpu_is_rec(vcpu)) {
> +		// Force PTE level mappings for realms
> +		force_pte = true;
> +		vma_shift = PAGE_SHIFT;
>   	} else {
>   		vma_shift = get_vma_page_shift(vma, hva);
>   	}

Thanks,
Gavin



From oliver.sang at intel.com  Mon Mar  3 22:25:54 2025
From: oliver.sang at intel.com (kernel test robot)
Date: Tue, 4 Mar 2025 14:25:54 +0800
Subject: [PATCH bpf-next v2] add function metadata support
In-Reply-To: <20250226121537.752241-1-dongml2@chinatelecom.cn>
Message-ID: <202503041412.5cf70b18-lkp@intel.com>



Hello,

kernel test robot noticed "CFI_failure_at__seccomp_filter" on:

commit: 449ee82c2013c0e0ccfe716bc3f8fff1a3651cb8 ("[PATCH bpf-next v2] add function metadata support")
url: https://github.com/intel-lab-lkp/linux/commits/Menglong-Dong/add-function-metadata-support/20250226-202312
base: https://git.kernel.org/cgit/linux/kernel/git/bpf/bpf-next.git master
patch link: https://lore.kernel.org/all/20250226121537.752241-1-dongml2 at chinatelecom.cn/
patch subject: [PATCH bpf-next v2] add function metadata support

in testcase: boot

config: x86_64-randconfig-077-20250228
compiler: clang-19
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)


+--------------------------------------+------------+------------+
|                                      | 4e4136c644 | 449ee82c20 |
+--------------------------------------+------------+------------+
| boot_successes                       | 12         | 0          |
| boot_failures                        | 0          | 12         |
| CFI_failure_at__seccomp_filter       | 0          | 12         |
| WARNING:CPU:#PID:#at__seccomp_filter | 0          | 12         |
| RIP:__seccomp_filter                 | 0          | 12         |
+--------------------------------------+------------+------------+


If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang at intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202503041412.5cf70b18-lkp at intel.com


The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20250304/202503041412.5cf70b18-lkp at intel.com


[   47.224161][   T71] CFI failure at __seccomp_filter+0x419/0x1505 (target: 0xffffffffa0000d78; expected type: 0xd9421881)
[   47.225919][   T71] WARNING: CPU: 0 PID: 71 at __seccomp_filter+0x419/0x1505
[   47.227037][   T71] Modules linked in: font drm_panel_orientation_quirks autofs4
[   47.228206][   T71] CPU: 0 UID: 0 PID: 71 Comm: systemd-journal Not tainted 6.14.0-rc3-00256-g449ee82c2013 #1
[   47.229699][   T71] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   47.231293][   T71] RIP: 0010:__seccomp_filter+0x419/0x1505
[   47.232177][   T71] Code: ff df 80 3c 08 00 74 08 48 89 df e8 06 a5 3d 00 49 83 c7 48 48 8b 7d b0 4c 89 fe 4c 8b 1b 41 ba 7f e7 bd 26 45 03 53 c1 74 02 <0f> 0b 41 ff d3 89 c3 89 d8 44 21 e8 44 89 e1 44 21 e9 39 c8 48 8b
[   47.234992][   T71] RSP: 0000:ffffc90000d4fd18 EFLAGS: 00010296
[   47.235895][   T71] RAX: 1ffff9200000ea06 RBX: ffffc90000075030 RCX: dffffc0000000000
[   47.237038][   T71] RDX: 0000000000000000 RSI: ffffc90000075048 RDI: ffffc90000d4fd18
[   47.238193][   T71] RBP: ffffc90000d4fe98 R08: 0000000000000000 R09: 0000000000000000
[   47.240441][   T71] R10: 00000000f38ab44b R11: ffffffffa0000d78 R12: 000000007fff0000
[   47.241594][   T71] R13: 00000000ffff0000 R14: ffff888195158e00 R15: ffffc90000075048
[   47.242791][   T71] FS:  0000000000000000(0000) GS:ffffffff84443000(0000) knlGS:0000000000000000
[   47.244083][   T71] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
[   47.245000][   T71] CR2: 00000000f7f6a01c CR3: 0000000195c01000 CR4: 00000000000406f0
[   47.246154][   T71] Call Trace:
[   47.246736][   T71]  <TASK>
[   47.247169][   T71]  ? show_regs+0x5c/0x80
[   47.247812][   T71]  ? __warn+0xf7/0x200
[   47.248427][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.249202][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.249964][   T71]  ? report_cfi_failure+0x7a/0xc0
[   47.250833][   T71]  ? handle_cfi_failure+0x1d5/0x27b
[   47.251619][   T71]  ? handle_bug+0x62/0xc5
[   47.252263][   T71]  ? exc_invalid_op+0x1f/0xbb
[   47.252966][   T71]  ? asm_exc_invalid_op+0x1f/0x40
[   47.253716][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.254556][   T71]  ? __seccomp_filter+0x391/0x1505
[   47.255373][   T71]  ? putname+0xd5/0x140
[   47.256045][   T71]  ? __kasan_slab_free+0x46/0x80
[   47.256841][   T71]  ? kmem_cache_free+0x176/0x380
[   47.257629][   T71]  ? putname+0xd5/0x140
[   47.258338][   T71]  ? putname+0xd5/0x140
[   47.259100][   T71]  ? user_path_at+0x43/0x80
[   47.259875][   T71]  __secure_computing+0xdb/0x2fb
[   47.260669][   T71]  syscall_trace_enter+0xae/0x13b
[   47.261464][   T71]  do_int80_emulation+0x7d/0x140
[   47.262299][   T71]  asm_int80_emulation+0x1f/0x40
[   47.263153][   T71] RIP: 0023:0xf7f88cb0
[   47.263837][   T71] Code: 4c 24 34 89 44 24 0c 8b 44 24 44 8b 54 24 38 8b 74 24 3c 8b 7c 24 40 a9 ff 0f 00 00 75 1c c1 e8 0c 89 c5 b8 c0 00 00 00 cd 80 <3d> 00 f0 ff ff 77 21 83 c4 1c 5b 5e 5f 5d c3 90 83 c4 1c b8 ea ff
[   47.266925][   T71] RSP: 002b:00000000ffbbaac0 EFLAGS: 00000246 ORIG_RAX: 00000000000000c0
[   47.268242][   T71] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000002000
[   47.269513][   T71] RDX: 0000000000000003 RSI: 0000000000000022 RDI: 00000000ffffffff
[   47.270868][   T71] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[   47.272143][   T71] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[   47.273426][   T71] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[   47.274794][   T71]  </TASK>
[   47.275309][   T71] irq event stamp: 6683
[   47.275991][   T71] hardirqs last  enabled at (6691): [<ffffffff814f0bb0>] __console_unlock+0x75/0xc5
[   47.277474][   T71] hardirqs last disabled at (6698): [<ffffffff814f0b95>] __console_unlock+0x5a/0xc5
[   47.279025][   T71] softirqs last  enabled at (5774): [<ffffffff81317b30>] fpu_flush_thread+0x1b0/0x340
[   47.280534][   T71] softirqs last disabled at (5772): [<ffffffff81317b30>] fpu_flush_thread+0x1b0/0x340
[   47.282053][   T71] ---[ end trace 0000000000000000 ]---
[   47.283041][   T71] CFI failure at __seccomp_filter+0x419/0x1505 (target: 0xffffffffa0000cec; expected type: 0xd9421881)
[   47.284738][   T71] WARNING: CPU: 0 PID: 71 at __seccomp_filter+0x419/0x1505
[   47.285815][   T71] Modules linked in: font drm_panel_orientation_quirks autofs4
[   47.287080][   T71] CPU: 0 UID: 0 PID: 71 Comm: systemd-journal Tainted: P                   6.14.0-rc3-00256-g449ee82c2013 #1
[   47.288846][   T71] Tainted: [P]=PROPRIETARY_MODULE
[   47.289635][   T71] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   47.291262][   T71] RIP: 0010:__seccomp_filter+0x419/0x1505
[   47.292164][   T71] Code: ff df 80 3c 08 00 74 08 48 89 df e8 06 a5 3d 00 49 83 c7 48 48 8b 7d b0 4c 89 fe 4c 8b 1b 41 ba 7f e7 bd 26 45 03 53 c1 74 02 <0f> 0b 41 ff d3 89 c3 89 d8 44 21 e8 44 89 e1 44 21 e9 39 c8 48 8b
[   47.294996][   T71] RSP: 0000:ffffc90000d4fd18 EFLAGS: 00010296
[   47.295952][   T71] RAX: 1ffff9200000e606 RBX: ffffc90000073030 RCX: dffffc0000000000
[   47.297166][   T71] RDX: 0000000000000000 RSI: ffffc90000073048 RDI: ffffc90000d4fd18
[   47.298403][   T71] RBP: ffffc90000d4fe98 R08: 0000000000000000 R09: 0000000000000000
[   47.299660][   T71] R10: 00000000f38ab44b R11: ffffffffa0000cec R12: 000000007fff0000
[   47.300851][   T71] R13: 00000000ffff0000 R14: ffff888195158200 R15: ffffc90000073048
[   47.302042][   T71] FS:  0000000000000000(0000) GS:ffffffff84443000(0000) knlGS:0000000000000000
[   47.303293][   T71] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
[   47.304156][   T71] CR2: 00000000f7f6a01c CR3: 0000000195c01000 CR4: 00000000000406f0
[   47.305149][   T71] Call Trace:
[   47.305594][   T71]  <TASK>
[   47.306045][   T71]  ? show_regs+0x5c/0x80
[   47.306778][   T71]  ? __warn+0xf7/0x200
[   47.307428][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.308228][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.309008][   T71]  ? report_cfi_failure+0x7a/0xc0
[   47.309781][   T71]  ? handle_cfi_failure+0x1d5/0x27b
[   47.310662][   T71]  ? handle_bug+0x62/0xc5
[   47.311249][   T71]  ? exc_invalid_op+0x1f/0xbb
[   47.311851][   T71]  ? asm_exc_invalid_op+0x1f/0x40
[   47.312604][   T71]  ? __seccomp_filter+0x419/0x1505
[   47.313383][   T71]  ? __seccomp_filter+0x41e/0x1505
[   47.314172][   T71]  ? putname+0xd5/0x140
[   47.314893][   T71]  ? __kasan_slab_free+0x46/0x80
[   47.315651][   T71]  ? kmem_cache_free+0x176/0x380
[   47.316399][   T71]  ? putname+0xd5/0x140
[   47.317031][   T71]  ? putname+0xd5/0x140
[   47.317650][   T71]  ? user_path_at+0x43/0x80
[   47.318340][   T71]  __secure_computing+0xdb/0x2fb
[   47.319073][   T71]  syscall_trace_enter+0xae/0x13b
[   47.319752][   T71]  do_int80_emulation+0x7d/0x140
[   47.320440][   T71]  asm_int80_emulation+0x1f/0x40
[   47.321158][   T71] RIP: 0023:0xf7f88cb0
[   47.321762][   T71] Code: 4c 24 34 89 44 24 0c 8b 44 24 44 8b 54 24 38 8b 74 24 3c 8b 7c 24 40 a9 ff 0f 00 00 75 1c c1 e8 0c 89 c5 b8 c0 00 00 00 cd 80 <3d> 00 f0 ff ff 77 21 83 c4 1c 5b 5e 5f 5d c3 90 83 c4 1c b8 ea ff
[   47.324586][   T71] RSP: 002b:00000000ffbbaac0 EFLAGS: 00000246 ORIG_RAX: 00000000000000c0
[   47.325827][   T71] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000002000
[   47.327053][   T71] RDX: 0000000000000003 RSI: 0000000000000022 RDI: 00000000ffffffff
[   47.328188][   T71] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[   47.329334][   T71] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[   47.330527][   T71] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[   47.331478][   T71]  </TASK>
[   47.331880][   T71] irq event stamp: 7199
[   47.332440][   T71] hardirqs last  enabled at (7207): [<ffffffff814f0bb0>] __console_unlock+0x75/0xc5
[   47.333803][   T71] hardirqs last disabled at (7214): [<ffffffff814f0b95>] __console_unlock+0x5a/0xc5
[   47.335245][   T71] softirqs last  enabled at (7154): [<ffffffff813de303>] handle_softirqs+0x548/0x6c5
[   47.336680][   T71] softirqs last disabled at (7143): [<ffffffff813de763>] __irq_exit_rcu+0x68/0x145
[   47.337992][   T71] ---[ end trace 0000000000000000 ]---
[   47.338944][   T71] CFI failure at __seccomp_filter+0x419/0x1505 (target: 0xffffffffa0000c60; expected type: 0xd9421881)
[   47.340603][   T71] WARNING: CPU: 0 PID: 71 at __seccomp_filter+0x419/0x1505
[   47.341705][   T71] Modules linked in: font drm_panel_orientation_quirks autofs4
[   47.342944][   T71] CPU: 0 UID: 0 PID: 71 Comm: systemd-journal Tainted: P                   6.14.0-rc3-00256-g449ee82c2013 #1
[   47.344497][   T71] Tainted: [P]=PROPRIETARY_MODULE
[   47.345236][   T71] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   47.346778][   T71] RIP: 0010:__seccomp_filter+0x419/0x1505
[   47.347432][   T71] Code: ff df 80 3c 08 00 74 08 48 89 df e8 06 a5 3d 00 49 83 c7 48 48 8b 7d b0 4c 89 fe 4c 8b 1b 41 ba 7f e7 bd 26 45 03 53 c1 74 02 <0f> 0b 41 ff d3 89 c3 89 d8 44 21 e8 44 89 e1 44 21 e9 39 c8 48 8b
[   47.349980][   T71] RSP: 0000:ffffc90000d4fd18 EFLAGS: 00010292
[   47.350959][   T71] RAX: 1ffff9200000e206 RBX: ffffc90000071030 RCX: dffffc0000000000
[   47.352116][   T71] RDX: 0000000000000000 RSI: ffffc90000071048 RDI: ffffc90000d4fd18

...


-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki



From gshan at redhat.com  Mon Mar  3 22:27:48 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 16:27:48 +1000
Subject: [PATCH v7 31/45] arm64: rme: Prevent Device mappings for Realms
In-Reply-To: <20250213161426.102987-32-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-32-steven.price@arm.com>
Message-ID: <780f593c-81cd-495c-8ca6-38ecd64ddb35@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> Physical device assignment is not yet supported by the RMM, so it
> doesn't make much sense to allow device mappings within the realm.
> Prevent them when the guest is a realm.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes from v6:
>   * Fix the check in user_mem_abort() to prevent all pages that are not
>     guest_memfd() from being mapped into the protected half of the IPA.
> Changes from v5:
>   * Also prevent accesses in user_mem_abort()
> ---
>   arch/arm64/kvm/mmu.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From oliver.upton at linux.dev  Mon Mar  3 22:27:07 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Mon,  3 Mar 2025 22:27:07 -0800
Subject: [PATCH v4 00/16] KVM: arm64: Add NV GICv3 support
In-Reply-To: <20250225172930.1850838-1-maz@kernel.org>
References: <20250225172930.1850838-1-maz@kernel.org>
Message-ID: <174106961929.349492.6260089060201840223.b4-ty@linux.dev>

On Tue, 25 Feb 2025 17:29:14 +0000, Marc Zyngier wrote:
> Here's a respin of the NV support for GICv3. The integration branch
> containing this (and the rest of the NV stack) is still at [4].
> 
> At this stage, I think this is good to go.
> 
> * From v3 [3]:
> 
> [...]

Fixed up a few typos here but overall this is in great shape, thank you.

Applied to next, thanks!

[01/16] arm64: sysreg: Add layout for ICH_HCR_EL2
        https://git.kernel.org/kvmarm/kvmarm/c/22513c0d2ad8
[02/16] arm64: sysreg: Add layout for ICH_VTR_EL2
        https://git.kernel.org/kvmarm/kvmarm/c/5815fb82dc67
[03/16] arm64: sysreg: Add layout for ICH_MISR_EL2
        https://git.kernel.org/kvmarm/kvmarm/c/b7a252e881f3
[04/16] KVM: arm64: nv: Load timer before the GIC
        https://git.kernel.org/kvmarm/kvmarm/c/16abeb60be62
[05/16] KVM: arm64: nv: Add ICH_*_EL2 registers to vpcu_sysreg
        https://git.kernel.org/kvmarm/kvmarm/c/182f1596941e
[06/16] KVM: arm64: nv: Plumb handling of GICv3 EL2 accesses
        https://git.kernel.org/kvmarm/kvmarm/c/96c2f03311de
[07/16] KVM: arm64: nv: Sanitise ICH_HCR_EL2 accesses
        https://git.kernel.org/kvmarm/kvmarm/c/21d29cd814d7
[08/16] KVM: arm64: nv: Nested GICv3 emulation
        https://git.kernel.org/kvmarm/kvmarm/c/146a050f2d8c
[09/16] KVM: arm64: nv: Handle L2->L1 transition on interrupt injection
        https://git.kernel.org/kvmarm/kvmarm/c/4b1b97f0d7cf
[10/16] KVM: arm64: nv: Add Maintenance Interrupt emulation
        https://git.kernel.org/kvmarm/kvmarm/c/201c8d40dde9
[11/16] KVM: arm64: nv: Respect virtual HCR_EL2.TWx setting
        https://git.kernel.org/kvmarm/kvmarm/c/69c9176c3862
[12/16] KVM: arm64: nv: Request vPE doorbell upon nested ERET to L2
        https://git.kernel.org/kvmarm/kvmarm/c/93078ae63f20
[13/16] KVM: arm64: nv: Propagate used_lrs between L1 and L0 contexts
        https://git.kernel.org/kvmarm/kvmarm/c/7682c023212e
[14/16] KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup
        https://git.kernel.org/kvmarm/kvmarm/c/89896cc15911
[15/16] KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ
        https://git.kernel.org/kvmarm/kvmarm/c/faf7714a47a2
[16/16] KVM: arm64: nv: Fail KVM init if asking for NV without GICv3
        https://git.kernel.org/kvmarm/kvmarm/c/83c6cb20147b

--
Best,
Oliver


From kw at linux.com  Mon Mar  3 22:44:52 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 15:44:52 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <Z8YWILtSbQnvVqbF@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
 <Z8YWILtSbQnvVqbF@debian>
Message-ID: <20250304064452.GA2615015@rocinante>

Hello,

[...]
> > > What will happen if ret != 0? still return 0? 
> > 
> > Given that callers of dwc_pcie_debugfs_init() check for errors,
> > this probably should correctly bubble up any failure coming from
> > dwc_pcie_rasdes_debugfs_init().
> > 
> > I made updates to the code directly on the current branch, have a look:
> > 
> >   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=1ff54f4cbaed9ec6994844967c36cf7ada4cbe5e
> > 
> > Let me know if this is OK with you.
> 
> It looks good to me.
> 
> Feel free to add,
> Reviewed-by: Fan Ni <fan.ni at samsung.com>

Will do.  Thank you.

	Krzysztof


From ronak.jain at amd.com  Mon Mar  3 22:15:42 2025
From: ronak.jain at amd.com (Jain, Ronak)
Date: Tue, 4 Mar 2025 06:15:42 +0000
Subject: [PATCH 2/3] dt-bindings: firmware: xilinx: Add conditional
 pinctrl schema
In-Reply-To: <LV8PR12MB9206B51A38A82F5A1730DA3486C42@LV8PR12MB9206.namprd12.prod.outlook.com>
References: <20250206142244.2553237-1-ronak.jain@amd.com>
 <20250206142244.2553237-3-ronak.jain@amd.com>
 <20250211215354.GA1244436-robh@kernel.org>
 <LV8PR12MB9206BA2BC6BBBA184B3E2FCD86FF2@LV8PR12MB9206.namprd12.prod.outlook.com>
 <LV8PR12MB9206B51A38A82F5A1730DA3486C42@LV8PR12MB9206.namprd12.prod.outlook.com>
Message-ID: <LV8PR12MB9206C4FBC2C8675274FB1BCB86C82@LV8PR12MB9206.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

Hi @Rob Herring,

Did you get a moment to go through the queries I asked for?

Thanks,
Ronak

> -----Original Message-----
> From: Jain, Ronak
> Sent: Thursday, February 20, 2025 5:48 PM
> To: Rob Herring <robh at kernel.org>
> Cc: krzk+dt at kernel.org; conor+dt at kernel.org; Simek, Michal
> <michal.simek at amd.com>; Manne, Nava kishore
> <nava.kishore.manne at amd.com>; devicetree at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: RE: [PATCH 2/3] dt-bindings: firmware: xilinx: Add conditional pinctrl
> schema
>
> Hi Rob,
>
> > -----Original Message-----
> > From: Jain, Ronak
> > Sent: Thursday, February 13, 2025 4:46 PM
> > To: Rob Herring <robh at kernel.org>
> > Cc: krzk+dt at kernel.org; conor+dt at kernel.org; Simek, Michal
> > <michal.simek at amd.com>; Manne, Nava kishore
> > <nava.kishore.manne at amd.com>; devicetree at vger.kernel.org; linux-arm-
> > kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > Subject: RE: [PATCH 2/3] dt-bindings: firmware: xilinx: Add conditional
> pinctrl
> > schema
> >
> > Hi Rob,
> >
> > > -----Original Message-----
> > > From: Rob Herring <robh at kernel.org>
> > > Sent: Wednesday, February 12, 2025 3:24 AM
> > > To: Jain, Ronak <ronak.jain at amd.com>
> > > Cc: krzk+dt at kernel.org; conor+dt at kernel.org; Simek, Michal
> > > <michal.simek at amd.com>; Manne, Nava kishore
> > > <nava.kishore.manne at amd.com>; devicetree at vger.kernel.org; linux-
> arm-
> > > kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > Subject: Re: [PATCH 2/3] dt-bindings: firmware: xilinx: Add conditional
> pinctrl
> > > schema
> > >
> > > On Thu, Feb 06, 2025 at 06:22:43AM -0800, Ronak Jain wrote:
> > > > Updates the Device Tree bindings for Xilinx firmware by introducing
> > > > conditional schema references for the pinctrl node.
> > > >
> > > > Previously, the pinctrl node directly referenced
> > > > xlnx,zynqmp-pinctrl.yaml. However, this patch modifies the schema to
> > > > conditionally apply the correct pinctrl schema based on the compatible
> > > > property. Specifically:
> > > > - If compatible contains "xlnx,zynqmp-pinctrl", reference
> > > >   xlnx,zynqmp-pinctrl.yaml.
> > > > - If compatible contains "xlnx,versal-pinctrl", reference
> > > >   xlnx,versal-pinctrl.yaml.
> > > >
> > > > Additionally, an example entry for "xlnx,versal-pinctrl" has been
> > > > added under the examples section.
> > > >
> > > > Signed-off-by: Ronak Jain <ronak.jain at amd.com>
> > > > ---
> > > >  .../firmware/xilinx/xlnx,zynqmp-firmware.yaml | 20
> ++++++++++++++++++-
> > > >  1 file changed, 19 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git
> a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-
> > > firmware.yaml
> b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-
> > > firmware.yaml
> > > > index 2b72fb9d3c22..d50438b0fca8 100644
> > > > --- a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-
> > > firmware.yaml
> > > > +++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-
> > > firmware.yaml
> > > > @@ -76,7 +76,6 @@ properties:
> > > >      type: object
> > > >
> > > >    pinctrl:
> > > > -    $ref: /schemas/pinctrl/xlnx,zynqmp-pinctrl.yaml#
> > > >      description: The pinctrl node provides access to pinconfig and
> pincontrol
> > > >        functionality available in firmware.
> > > >      type: object
> > > > @@ -106,6 +105,21 @@ properties:
> > > >      type: object
> > > >      deprecated: true
> > > >
> > > > +allOf:
> > > > +  - if:
> > > > +      properties:
> > > > +        compatible:
> > > > +          contains:
> > > > +            const: xlnx,zynqmp-firmware
> > > > +    then:
> > > > +      properties:
> > > > +        pinctrl:
> > > > +          $ref: /schemas/pinctrl/xlnx,zynqmp-pinctrl.yaml#
> > > > +    else:
> > > > +      properties:
> > > > +        pinctrl:
> > > > +          $ref: /schemas/pinctrl/xlnx,versal-pinctrl.yaml#
> > >
> > > The somewhat preferred way to do this would be to do this in the top
> > > level:
> > >
> > > pinctrl:
> > >   type: object
> > >   additionalProperties: true
> > >   properties:
> > >     compatible:
> > >       contains:
> > >         enum:
> > >           - xlnx,zynqmp-pinctrl
> > >           - xlnx,versal-pinctrl
> > >   required:
> > >     - compatible
> > >
> > > Otherwise, the pinctrl schema ends up being applied twice.
> >
> > Thanks for the patch review and inputs. I'll update and send the next
> version.
> >
>
> In your suggested code, the schema allows either xlnx,zynqmp-pinctrl or
> xlnx,versal-pinctrl on any platform, which is incorrect. This means that if a
> user mistakenly assigns xlnx,versal-pinctrl to a ZynqMP platform or
> xlnx,zynqmp-pinctrl to a Versal platform, the wrong reference will be used,
> but no error is reported. The dt-binding check still passes instead of flagging
> this as an issue.
>
> By using a conditional schema, we can enforce platform-specific compatibility,
> ensuring that the correct compatible string is used for the corresponding
> platform. This would also generate an error if an incorrect compatible string is
> provided, preventing misconfigurations.
>
> Please let me know your thoughts.
>
> Thanks,
> Ronak
>
> > Thanks,
> > Ronak
> > >
> > > > +
> > > >  required:
> > > >    - compatible
> > > >
> > > > @@ -164,6 +178,10 @@ examples:
> > > >          compatible = "xlnx,versal-fpga";
> > > >        };
> > > >
> > > > +      pinctrl {
> > > > +        compatible = "xlnx,versal-pinctrl";
> > > > +      };
> > > > +
> > > >        xlnx_aes: zynqmp-aes {
> > > >          compatible = "xlnx,zynqmp-aes";
> > > >        };
> > > > --
> > > > 2.34.1
> > > >


From devnull+nayabbasha.sayed.microchip.com at kernel.org  Mon Mar  3 22:15:40 2025
From: devnull+nayabbasha.sayed.microchip.com at kernel.org (Nayab Sayed via B4 Relay)
Date: Tue, 04 Mar 2025 11:45:40 +0530
Subject: [PATCH] ARM: dts: microchip: sama7g5: add ADC hw trigger edge type
Message-ID: <20250304-sama7g5-hw-trigger-enable-v1-1-61b5618285f0@microchip.com>

From: Nayab Sayed <nayabbasha.sayed at microchip.com>

Set ADC trigger edge type property as interrupt edge rising value.

Signed-off-by: Nayab Sayed <nayabbasha.sayed at microchip.com>
---
 arch/arm/boot/dts/microchip/at91-sama7g5ek.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
index 0f5e6ad438dd..2543599013b1 100644
--- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
@@ -137,6 +137,7 @@ &adc {
 	vref-supply = <&vddout25>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_mikrobus1_an_default &pinctrl_mikrobus2_an_default>;
+	atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
 	status = "okay";
 };
 

---
base-commit: 99fa936e8e4f117d62f229003c9799686f74cebc
change-id: 20250303-sama7g5-hw-trigger-enable-82b0b3d4042a

Best regards,
-- 
Nayab Sayed <nayabbasha.sayed at microchip.com>




From peterz at infradead.org  Mon Mar  3 22:16:35 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 4 Mar 2025 07:16:35 +0100
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250304053853.GA7099@noisy.programming.kicks-ass.net>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn>
 <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net>
Message-ID: <20250304061635.GA29480@noisy.programming.kicks-ass.net>

On Tue, Mar 04, 2025 at 06:38:53AM +0100, Peter Zijlstra wrote:
> On Tue, Mar 04, 2025 at 09:10:12AM +0800, Menglong Dong wrote:
> > Hello, sorry that I forgot to add something to the changelog. In fact,
> > I don't add extra 5-bytes anymore, which you can see in the 3rd patch.
> > 
> > The thing is that we can't add extra 5-bytes if CFI is enabled. Without
> > CFI, we can make the padding space any value, such as 5-bytes, and
> > the layout will be like this:
> > 
> > __align:
> >   nop
> >   nop
> >   nop
> >   nop
> >   nop
> > foo: -- __align +5
> > 
> > However, the CFI will always make the cfi insn 16-bytes aligned. When
> > we set the FUNCTION_PADDING_BYTES to (11 + 5), the layout will be
> > like this:
> > 
> > __cfi_foo:
> >   nop (11)
> >   mov $0x12345678, %reg
> >   nop (16)
> > foo:
> > 
> > and the padding space is 32-bytes actually. So, we can just select
> > FUNCTION_ALIGNMENT_32B instead, which makes the padding
> > space 32-bytes too, and have the following layout:
> > 
> > __cfi_foo:
> >   mov $0x12345678, %reg
> >   nop (27)
> > foo:
> 
> *blink*, wtf is clang smoking.
> 
> I mean, you're right, this is what it is doing, but that is somewhat
> unexpected. Let me go look at clang source, this is insane.

Bah, this is because assemblers are stupid :/

There is no way to tell them to have foo aligned such that there are at
least N bytes free before it.

So what kCFI ends up having to do is align the __cfi symbol to the
function alignment, and then stuff enough nops in to make the real
symbol meet alignment.

And the end result is utter insanity.

I mean, look at this:

      50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
      56:       66 2e 0f 1f 84 00 00 00 00 00   cs nopw 0x0(%rax,%rax,1)

0000000000000060 <__cfi___probestub_initcall_level>:
      60:       90                      nop
      61:       90                      nop
      62:       90                      nop
      63:       90                      nop
      64:       90                      nop
      65:       90                      nop
      66:       90                      nop
      67:       90                      nop
      68:       90                      nop
      69:       90                      nop
      6a:       90                      nop
      6b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax

0000000000000070 <__probestub_initcall_level>:
      70:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4


That's 21 bytes wasted, for no reason other than that asm doesn't have a
directive to say: get me a place that is M before N alignment.

Because ideally the whole above thing would look like:

      50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
      56:       66 2e 0f 1f 84 		cs nopw (%rax,%rax,1)

000000000000005b <__cfi___probestub_initcall_level>:
      5b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax

0000000000000060 <__probestub_initcall_level>:
      60:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4





From dsimic at manjaro.org  Mon Mar  3 22:44:59 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Tue, 04 Mar 2025 07:44:59 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64
 RockPro64
In-Reply-To: <174104113599.8946.16805724674396090918.b4-ty@sntech.de>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <174104113599.8946.16805724674396090918.b4-ty@sntech.de>
Message-ID: <757afa87255212dfa5abf4c0e31deb08@manjaro.org>

Hello Heiko,

On 2025-03-03 23:36, Heiko Stuebner wrote:
> On Sun, 02 Mar 2025 19:48:02 +0100, Dragan Simic wrote:
>> This is a small series that introduces small improvements to the way
>> Pine64 RockPro64 [1] single-board-computer is described in the DT 
>> files.
>> This applies to both production-run revisions of the RockPro64.
>> 
>> The introduced improvements boil down to eliminating some warnings 
>> from
>> the kernel log, by adding a previously undefined regulator and by 
>> adding
>> some previously missing references to the regulators.
>> 
>> [...]
> 
> Applied, thanks!
> 
> [1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board 
> dtsi
>       commit: bd1c959f37f384b477f51572331b0dc828bd009a
> [2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 
> board dtsi
>       commit: 64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
> 
> I've moved the pcie12v supply up one line.
> While in a mathematical sense it's true 12 > 3.3, we're sorting
> alphabetical, so it's 1?? < 3?? .
> 
> And yes I sympathize with 3.3 < 12, but also have come to appreciate 
> not
> having overly many special cases :-)

Great, thanks! :)

I'm fine with the alphabetical ordering, albeit with some caveats
described below, but the following part of the patch description
should also be removed, if possible, so the patch description fully
matches the introduced changes:

   Shuffle and reorder the "vpcie*-supply" properties a bit, so they're 
sorted
   alphanumerically, which is a bit more logical and more useful than 
having
   these properties listed in their strict alphabetical order.

Admittedly, the patch itself indeed looks nicer [1] with the
alphabetical ordering, :) (which is quasi-alphabetical, actually,
please see below) but it might be better to have the DT guidelines
adjusted to specify alphanumerical ordering as well.  Even ls(1)
can sort filenames alphanumerically, with its "-v" option that
performs "natural sort of (version) numbers within text". [2]

The real trouble is that, if we were to apply the alphabetical
ordering strictly, we'd end up with the following order of node
properties in which 12 is before 1.8 and 3.3, which IMHO doesn't
make much sense:

   vpcie0v9-supply = <&vcca_0v9>;
   vpcie12v-supply = <&vcc12v_dcin>;
   vpcie1v8-supply = <&vcca_1v8>;
   vpcie3v3-supply = <&vcc3v3_pcie>;

I'm hoping you'll agree that specifying alphanumerical ordering
for the properties in the DTS coding style is the way to go, just
like it's already specified for the ordering of the nodes.  I'll
go ahead and submit an appropriate patch for the DT guidelines.

[1] 
https://web.git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/commit/?id=64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
[2] https://man.archlinux.org/man/ls.1.en#v


From kw at linux.com  Mon Mar  3 22:50:00 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 4 Mar 2025 15:50:00 +0900
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250303095200.GB1065658@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
 <20250303095200.GB1065658@rocinante>
Message-ID: <20250304065000.GB2615015@rocinante>

Hello,

[...]
> > +		29) Generates duplicate TLPs - duplicate_dllp
> > +		30) Generates Nullified TLPs - nullified_tlp
> 
> Would the above field called "duplicate_dllp" for duplicate TLPs be
> a potential typo?  Perhaps this should be called "duplicate_tlp"?
> 
> I wanted to make sure we have the correct field name.

Fan or Shradha, any thoughts on this?

Would the problem be with the name of the property of the description?

Thank you!

	Krzysztof


From dsimic at manjaro.org  Mon Mar  3 22:57:34 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Tue, 04 Mar 2025 07:57:34 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64
 RockPro64
In-Reply-To: <757afa87255212dfa5abf4c0e31deb08@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <174104113599.8946.16805724674396090918.b4-ty@sntech.de>
 <757afa87255212dfa5abf4c0e31deb08@manjaro.org>
Message-ID: <dff9509bcbe9be10b2df454c2dabc289@manjaro.org>

On 2025-03-04 07:44, Dragan Simic wrote:
> On 2025-03-03 23:36, Heiko Stuebner wrote:
>> On Sun, 02 Mar 2025 19:48:02 +0100, Dragan Simic wrote:
>>> This is a small series that introduces small improvements to the way
>>> Pine64 RockPro64 [1] single-board-computer is described in the DT 
>>> files.
>>> This applies to both production-run revisions of the RockPro64.
>>> 
>>> The introduced improvements boil down to eliminating some warnings 
>>> from
>>> the kernel log, by adding a previously undefined regulator and by 
>>> adding
>>> some previously missing references to the regulators.
>>> 
>>> [...]
>> 
>> Applied, thanks!
>> 
>> [1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board 
>> dtsi
>>       commit: bd1c959f37f384b477f51572331b0dc828bd009a
>> [2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 
>> board dtsi
>>       commit: 64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
>> 
>> I've moved the pcie12v supply up one line.
>> While in a mathematical sense it's true 12 > 3.3, we're sorting
>> alphabetical, so it's 1?? < 3?? .
>> 
>> And yes I sympathize with 3.3 < 12, but also have come to appreciate 
>> not
>> having overly many special cases :-)
> 
> Great, thanks! :)
> 
> I'm fine with the alphabetical ordering, albeit with some caveats
> described below, but the following part of the patch description
> should also be removed, if possible, so the patch description fully
> matches the introduced changes:
> 
>   Shuffle and reorder the "vpcie*-supply" properties a bit, so they're 
> sorted
>   alphanumerically, which is a bit more logical and more useful than 
> having
>   these properties listed in their strict alphabetical order.
> 
> Admittedly, the patch itself indeed looks nicer [1] with the
> alphabetical ordering, :) (which is quasi-alphabetical, actually,
> please see below) but it might be better to have the DT guidelines
> adjusted to specify alphanumerical ordering as well.  Even ls(1)
> can sort filenames alphanumerically, with its "-v" option that
> performs "natural sort of (version) numbers within text". [2]
> 
> The real trouble is that, if we were to apply the alphabetical
> ordering strictly, we'd end up with the following order of node
> properties in which 12 is before 1.8 and 3.3, which IMHO doesn't
> make much sense:
> 
>   vpcie0v9-supply = <&vcca_0v9>;
>   vpcie12v-supply = <&vcc12v_dcin>;
>   vpcie1v8-supply = <&vcca_1v8>;
>   vpcie3v3-supply = <&vcc3v3_pcie>;
> 
> I'm hoping you'll agree that specifying alphanumerical ordering
> for the properties in the DTS coding style is the way to go, just
> like it's already specified for the ordering of the nodes.  I'll
> go ahead and submit an appropriate patch for the DT guidelines.
> 
> [1] 
> https://web.git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/commit/?id=64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
> [2] https://man.archlinux.org/man/ls.1.en#v

For future reference and for anyone interested, here's a link to
the above-mentioned DTS coding style patch:

https://lore.kernel.org/linux-kernel/09d6f2fc111b3d6e58987336944f93ec36b65118.1741071107.git.dsimic at manjaro.org/T/#u


From wbg at kernel.org  Mon Mar  3 23:02:00 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 16:02:00 +0900
Subject: [PATCH v6 2/3] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <20250227144023.64530-3-csokas.bence@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-3-csokas.bence@prolan.hu>
Message-ID: <Z8alaOTjZeRuXnUI@ishi>

On Thu, Feb 27, 2025 at 03:40:19PM +0100, Bence Cs?k?s wrote:
> Add interrupt servicing to allow userspace to wait for the following events:

Hi Bence,

This is a nitpick but keep the commit description with a maximum of 75
characters per line so we don't have formatting issues with how they
wrap.

> @@ -378,6 +444,15 @@ static int mchp_tc_probe(struct platform_device *pdev)
>  	counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals);
>  	counter->signals = mchp_tc_count_signals;
>  
> +	priv->irq = of_irq_get(np->parent, 0);
> +	if (priv->irq == -EPROBE_DEFER)
> +		return -EPROBE_DEFER;

In theory, the error code could be something else if of_irq_get() failed
for any other reason. Handle all those error cases at once by checking
IS_ERR(priv->irq) rather than just -EPROBE_DEFER. Then you can just
return dev_err_probe() with priv->irq for the error code.

> diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
> index 7bda5fdef19b..ee72f1463594 100644
> --- a/include/uapi/linux/counter/microchip-tcb-capture.h
> +++ b/include/uapi/linux/counter/microchip-tcb-capture.h
> @@ -12,6 +12,17 @@
>   * Count 0
>   * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
>   * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
> + *
> + * It also supports the following events:
> + *
> + * Channel 0:
> + * - CV register changed
> + * - CV overflowed
> + * - RA captured
> + * Channel 1:
> + * - RB captured
> + * Channel 2:
> + * - RC compare triggered
>   */
>  
>  enum counter_mchp_signals {
> @@ -19,4 +30,11 @@ enum counter_mchp_signals {
>  	COUNTER_MCHP_SIG_TIOB,
>  };
>  
> +enum counter_mchp_event_channels {
> +	COUNTER_MCHP_EVCHN_CV = 0,
> +	COUNTER_MCHP_EVCHN_RA = 0,
> +	COUNTER_MCHP_EVCHN_RB,
> +	COUNTER_MCHP_EVCHN_RC,
> +};

These would be better as preprocessor defines in case we need to
introduce new events to channel 1 or 2 in the future. That would allow
us to insert new events easily to existing channels without having to
worry about its actual position in an enum list.

One additional benefit is if we do end up introducing more Counts for
the module. In that situation we would have multiple CV and RA/RB/RC per
Counter device, but we can easily define a preprocessor macro to
calculate the channel offset given the Count index. However, with enum
structure we would have to manually add and maintain redundant defines
for each Count, which is far less ideal.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/c30800c0/attachment.sig>

From irogers at google.com  Mon Mar  3 23:04:59 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 3 Mar 2025 23:04:59 -0800
Subject: [PATCH v4 00/11] perf: Support multiple system call tables in the build
In-Reply-To: <20250304050305.901167-1-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
Message-ID: <CAP-5=fXFoawZnRD22iSev5FQnx3oyFOhrPf=gZbk84qGtr9NFA@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:04?PM Ian Rogers <irogers at google.com> wrote:
>
> This work builds on the clean up of system call tables and removal of
> libaudit by Charlie Jenkins <charlie at rivosinc.com>.
>
> The system call table in perf trace is used to map system call numbers
> to names and vice versa. Prior to these changes, a single table
> matching the perf binary's build was present. The table would be
> incorrect if tracing say a 32-bit binary from a 64-bit version of
> perf, the names and numbers wouldn't match.
>
> Change the build so that a single system call file is built and the
> potentially multiple tables are identifiable from the ELF machine type
> of the process being examined. To determine the ELF machine type, the
> executable's maps are searched and the associated DSOs ELF headers are
> read. When this fails and when live, /proc/pid/exe's ELF header is
> read. Fallback to using the perf's binary type when unknown.
>
> Remove some runtime types used by the system call tables and make
> equivalents generated at build time.
>
> v4: Add reading the e_machine from the thread's maps dsos, only read
>     from /proc/pid/exe on failure and when live as requested by
>     Namhyung. Add patches to add dso comments and remove unused
>     dso_data variables that are unused without libunwind.

This has allowed `perf trace record` (not just perf trace) to work
with binaries with an e_machine that doesn't match that of the perf
binary. An example:

Before:
```
$ file ./a.out
a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux.so.2
, BuildID[sha1]=3fcd28f85a27a3108941661a91dbc675c06868f9, for
GNU/Linux 3.2.0, not stripped
$ perf trace record -- ./a.out
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.059 MB perf.data (60 samples) ]
$ perf trace -i perf.data
         ? (         ): a.out/914959  ... [continued]: munmap())
                                    = 0
    0.019 ( 0.001 ms): a.out/914959 recvfrom(ubuf: 0x2, size:
4160602092, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|>
    0.034 ( 0.002 ms): a.out/914959 lgetxattr(name: 0x2000, value:
0x3, size: 34)                         = 4160352256
    0.043 ( 0.002 ms): a.out/914959 dup2(oldfd: -134405940, newfd: 4)
                                   = -1 ENOENT>
    0.047 ( 0.009 ms): a.out/914959 preadv(fd: 4294967196, vec:
0xf7fce47f, vlen: 557056, pos_h: 4160602092) = 3
    0.058 ( 0.004 ms): a.out/914959 lgetxattr(name: 0x1b5c2, value:
0x1, size: 2)                         = 4160237568
    0.063 ( 0.000 ms): a.out/914959 lstat(filename: 0x3, statbuf:
0x1b5c2)                                = 0
    0.071 ( 0.006 ms): a.out/914959 preadv(fd: 4294967196, vec:
0xf7f9f3e0, vlen: 557056, pos_h: 4160602092) = 3
    0.078 ( 0.001 ms): a.out/914959 close(fd: 3)
                                   = 512
    0.082 ( 0.002 ms): a.out/914959 lgetxattr(name: 0x23f8d0, value:
0x1, size: 2050)                     = 4157878272
    0.084 ( 0.006 ms): a.out/914959 lgetxattr(pathname: 0xf7d66000,
name: 0x18b000, value: 0x5, size: 2066) = 4158021>
    0.091 ( 0.002 ms): a.out/914959 lgetxattr(pathname: 0xf7ef1000,
name: 0x85000, value: 0x1, size: 2066) = 41596395>
    0.093 ( 0.003 ms): a.out/914959 lgetxattr(pathname: 0xf7f76000,
name: 0x3000, value: 0x3, size: 2066) = 4160184320
    0.099 ( 0.002 ms): a.out/914959 lgetxattr(pathname: 0xf7f79000,
name: 0x98d0, value: 0x3, size: 50)   = 4160196608
    0.106 ( 0.000 ms): a.out/914959 lstat(filename: 0x3)
                                   = 0
    0.112 ( 0.001 ms): a.out/914959 mq_timedreceive(mqdes: 4287979520,
u_msg_ptr: 0xf7f9fbb0, u_msg_prio: 0xf7fdbfec,>
    0.113 ( 0.000 ms): a.out/914959 mkdirat(dfd: -134609624, pathname:
0xf7fdc910, mode: IFSOCK|ISUID|IRUSR|IWGRP|0xf>
    0.114 ( 0.000 ms): a.out/914959 process_vm_writev(pid: -134609620,
lvec: 0xc, liovcnt: 4160604432, rvec: 0xf7fa04>
    0.154 ( 0.003 ms): a.out/914959 capget(header: 4160184320,
dataptr: 8192)                             = 0
    0.158 ( 0.002 ms): a.out/914959 capget(header: 1448792064,
dataptr: 4096)                             = 0
    0.163 ( 0.002 ms): a.out/914959 capget(header: 4160593920,
dataptr: 8192)                             = 0
    0.171 ( 0.001 ms): a.out/914959 getxattr(pathname: 0x3, name:
0xff955fe4, value: 0xf7f77e14, size: 1) = 0
    0.179 ( 0.005 ms): a.out/914959 fchmod(fd: -134729728, mode:
IFLNK|IFIFO|ISGID|IRWXU|IWOTH|0x10000)   = 0
    0.193 ( 0.008 ms): a.out/914959 preadv(fd: 4294967196, vec:
0x565ac008, pos_h: 4160192020)            = 3
    0.202 ( 0.007 ms): a.out/914959 close(fd: 3)
                                   = 1436
    0.209 ( 0.017 ms): a.out/914959 stat(filename: 0x1, statbuf:
0xff9552fc)                              = 1436
    0.234 (1000.083 ms): a.out/914959 readlinkat(buf: 0xff955224,
bufsiz: 4287975964)                       = 0
```

After:
```
$ file ./a.out
a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux.so.2
, BuildID[sha1]=3fcd28f85a27a3108941661a91dbc675c06868f9, for
GNU/Linux 3.2.0, not stripped
$ perf trace record -- ./a.out
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.059 MB perf.data (60 samples) ]
$ perf trace -i perf.data
        ? (         ): a.out/908002  ... [continued]: execve())
                                   = 0
    0.019 ( 0.001 ms): a.out/908002 brk()
                                   = 0x57680000
    0.041 ( 0.003 ms): a.out/908002 access(filename: 0xf7f0b0cc, mode:
R)                                 = -1 ENOENT>
    0.046 ( 0.008 ms): a.out/908002 openat(dfd: CWD, filename:
0xf7f0747f, flags: RDONLY|CLOEXEC|LARGEFILE) = 3
    0.055 ( 0.001 ms): a.out/908002 statx(dfd: 3, filename:
0xf7f080f6, flags: NO_AUTOMOUNT|EMPTY_PATH, mask: TYPE|MO>
    0.061 ( 0.000 ms): a.out/908002 close(fd: 3)
                                   = 0
    0.070 ( 0.006 ms): a.out/908002 openat(dfd: CWD, filename:
0xf7ed83e0, flags: RDONLY|CLOEXEC|LARGEFILE) = 3
    0.077 ( 0.001 ms): a.out/908002 read(fd: 3, buf: 0xff80ea50,
count: 512)                              = 512
    0.079 ( 0.001 ms): a.out/908002 statx(dfd: 3, filename:
0xf7f080f6, flags: NO_AUTOMOUNT|EMPTY_PATH, mask: TYPE|MO>
    0.104 ( 0.000 ms): a.out/908002 close(fd: 3)
                                   = 0
    0.112 ( 0.000 ms): a.out/908002 set_tid_address(tidptr:
0xf7ed9528)                                   = 908002 (a>
    0.113 ( 0.000 ms): a.out/908002 set_robust_list(head: 0xf7ed952c,
len: 12)                            = 0 (swappe>
    0.114 ( 0.001 ms): a.out/908002 rseq(rseq: 0xf7ed9960, rseq_len:
32, sig: 1392848979)                 = 0 (swappe>
    0.153 ( 0.003 ms): a.out/908002 mprotect(start: 0xf7eaf000, len:
8192, prot: READ)                    = 0
    0.158 ( 0.002 ms): a.out/908002 mprotect(start: 0x565ef000, len:
4096, prot: READ)                    = 0
    0.163 ( 0.002 ms): a.out/908002 mprotect(start: 0xf7f13000, len:
8192, prot: READ)                    = 0
    0.177 ( 0.005 ms): a.out/908002 munmap(addr: 0xf7ebc000, len:
112066)                                 = 0
    0.189 ( 0.009 ms): a.out/908002 openat(dfd: CWD, filename:
0x565ee008)                                = 3
    0.198 ( 0.006 ms): a.out/908002 read(fd: 3, buf: 0xff80e56c,
count: 4096)                             = 1436
    0.205 ( 0.017 ms): a.out/908002 write(fd: 1, buf: , count: 1436)
                                   = 1436
    0.229 (1000.201 ms): a.out/908002 clock_nanosleep(rqtp:
0xff80e494, rmtp: 0xff80e48c)                   = 0
 1000.486 (         ): a.out/908002 exit_group()
```

Thanks,
Ian

> v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
>     Bergmann <arnd at arndb.de> on additional optional column and MIPS
>     system call numbering. Rebase past Namhyung's global system call
>     statistics and add comments that they don't yet support an
>     e_machine other than EM_HOST.
>
> v2: Change the 1 element cache for the last table as suggested by
>     Howard Chu, add Howard's reviewed-by tags.
>     Add a comment and apology to Charlie for not doing better in
>     guiding:
>     https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
>     After discussion on v1 and he agreed this patch series would be
>     the better direction.
>
> Ian Rogers (11):
>   perf dso: Move libunwind dso_data variables into ifdef
>   perf dso: kernel-doc for enum dso_binary_type
>   perf syscalltbl: Remove syscall_table.h
>   perf trace: Reorganize syscalls
>   perf syscalltbl: Remove struct syscalltbl
>   perf dso: Add support for reading the e_machine type for a dso
>   perf thread: Add support for reading the e_machine type for a thread
>   perf trace beauty: Add syscalltbl.sh generating all system call tables
>   perf syscalltbl: Use lookup table containing multiple architectures
>   perf build: Remove Makefile.syscalls
>   perf syscalltbl: Mask off ABI type for MIPS system calls
>
>  tools/perf/Makefile.perf                      |  10 +-
>  tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
>  .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/alpha/include/syscall_table.h |   2 -
>  tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
>  .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
>  tools/perf/arch/arc/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
>  .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
>  tools/perf/arch/arm/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
>  .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
>  tools/perf/arch/arm64/include/syscall_table.h |   8 -
>  tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
>  .../csky/entry/syscalls/Makefile.syscalls     |   3 -
>  tools/perf/arch/csky/include/syscall_table.h  |   2 -
>  .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
>  .../entry/syscalls/Makefile.syscalls          |   3 -
>  .../arch/loongarch/include/syscall_table.h    |   2 -
>  tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
>  .../mips/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/mips/include/syscall_table.h  |   2 -
>  tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
>  .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
>  .../perf/arch/parisc/include/syscall_table.h  |   8 -
>  tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
>  .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
>  .../perf/arch/powerpc/include/syscall_table.h |   8 -
>  tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
>  .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
>  tools/perf/arch/riscv/include/syscall_table.h |   8 -
>  tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
>  .../s390/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/s390/include/syscall_table.h  |   2 -
>  tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
>  .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
>  tools/perf/arch/sh/include/syscall_table.h    |   2 -
>  tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
>  .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/sparc/include/syscall_table.h |   8 -
>  tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
>  .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
>  tools/perf/arch/x86/include/syscall_table.h   |   8 -
>  tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
>  .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
>  .../perf/arch/xtensa/include/syscall_table.h  |   2 -
>  tools/perf/builtin-trace.c                    | 290 +++++++++++-------
>  tools/perf/scripts/Makefile.syscalls          |  61 ----
>  tools/perf/scripts/syscalltbl.sh              |  86 ------
>  tools/perf/trace/beauty/syscalltbl.sh         | 274 +++++++++++++++++
>  tools/perf/util/dso.c                         |  54 ++++
>  tools/perf/util/dso.h                         |  56 ++++
>  tools/perf/util/syscalltbl.c                  | 148 ++++-----
>  tools/perf/util/syscalltbl.h                  |  22 +-
>  tools/perf/util/thread.c                      |  80 +++++
>  tools/perf/util/thread.h                      |  14 +-
>  56 files changed, 756 insertions(+), 509 deletions(-)
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
>  delete mode 100644 tools/perf/scripts/Makefile.syscalls
>  delete mode 100755 tools/perf/scripts/syscalltbl.sh
>  create mode 100755 tools/perf/trace/beauty/syscalltbl.sh
>
> --
> 2.48.1.711.g2feabab25a-goog
>


From krzk at kernel.org  Mon Mar  3 23:13:30 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 08:13:30 +0100
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
Message-ID: <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>

On 04/03/2025 03:17, Wilson Ding wrote:
> 
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: Saturday, March 1, 2025 5:46 AM
>> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
>> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
>> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
>> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
>> Subject: Re: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
>> reset controller node
>>
>> On 28/02/2025 21:18, Wilson Ding wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: Krzysztof Kozlowski <krzk at kernel.org>
>>>> Sent: Thursday, February 27, 2025 10:57 PM
>>>> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
>>>> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>>>> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
>>>> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
>>>> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
>>>> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
>>>> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
>> reset
>>>> controller node
>>>>
>>>> On 27/02/2025 20:?25, Wilson Ding wrote: > Add the reset controller node
>> as
>>>> a sub-node to the system controller > node. > > Signed-off-by: Wilson Ding
>>>> <dingwei@?marvell.?com> > --- > arch/arm64/boot/dts/marvell/armada-
>>>> cp11x.?dtsi
>>>>
>>>> On 27/02/2025 20:25, Wilson Ding wrote:
>>>>> Add the reset controller node as a sub-node to the system controller
>>>>> node.
>>>>>
>>>>> Signed-off-by: Wilson Ding <dingwei at marvell.com>
>>>>> ---
>>>>>  arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 8 ++++++++
>>>>>  1 file changed, 8 insertions(+)
>>>>>
>>>>> diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>> b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>>> index 161beec0b6b0..c27058d1534e 100644
>>>>> --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>>> +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
>>>>> @@ -226,6 +226,8 @@ CP11X_LABEL(rtc): rtc at 284000 {
>>>>>  		CP11X_LABEL(syscon0): system-controller at 440000 {
>>>>>  			compatible = "syscon", "simple-mfd";
>>>>>  			reg = <0x440000 0x2000>;
>>>>> +			#address-cells = <1>;
>>>>> +			#size-cells = <1>;
>>>>>
>>>>>  			CP11X_LABEL(clk): clock {
>>>>
>>>> Wait, no unit address here.
>>>
>>> This subnode came from the existing code. I didn't touch this subnode
>>> in my patch. As you can see, the system-controller has a wide address
>>> range, which includes clock, GPIO registers as well as the unit-softreset
>>> register.
>>>
>>>>
>>>>>  				compatible = "marvell,cp110-clock";
>>>>> @@ -273,6 +275,12 @@ CP11X_LABEL(gpio2): gpio at 140 {
>>>>>  					 <&CP11X_LABEL(clk) 1 17>;
>>>>>  				status = "disabled";
>>>>>  			};
>>>>> +
>>>>> +			CP11X_LABEL(swrst): reset-controller at 268 {
>>>>
>>>>
>>>> So why here it appeared? This is wrong and not even necessary. Entire
>>>> child should be folded into parent, so finally you will fix the
>>>> incomplete parent compatible.
>>>
>>> We do need the reset-controller as a subnode under system-controller node
>>> for the following reasons:
>>>
>>> - We need to have 'reg' property in this subnode so that we can get the
>> offset
>>>   to system-controller register base defined in parent node. This is suggested
>>>   by Rob in V2 comments.
>>>   And we need to know the register size to calculate the number of reset
>> lines.
>>>   This is suggested by Philipp in V1 comments.
>>
>> You do not need and you received that comment as well. It is implied by
>> compatible.
>>
>>>
>>> - We also need to define the 'reset-cells' in this subnode. And the consumer
>> of
>>>   the reset controller uses the label of this subnode for the phandle and reset
>>>   specifier pair.
>>
>> reset-cells will be in the parent once you fold it.
>>
>>>
>>> As I mentioned in my reply to the first comment, the reset-controller is not
>> the
>>> only device within the system-controller register spaces. Do you still think I
>>
>> You provided very little hardware description of the device. So based on
>> hardware description you provided: yes.
>>
>>> should fold it into the parent node. And what I proposed is exactly same as
>>> that the armada_thermal driver did (See below). I wonder why what was
>> accepted
>>> in the past become not accepted now.
>>
>> We did not discuss here drivers, but if you insist talking about
>> "marvell,armada-cp110-thermal" then point me to review or ack from DT
>> people. You claim it was accepted so how did we accept it?
>>
> 
> I didn't intend to extend discussion to the driver in this thread. The following
> Is the review thread of the dt-binding for the thermal device (in 2018).
> Indeed, there is no comments challenging why not fold the thermal sub-node
> Into the parent 'syscon' node.
> 
> https://lore.kernel.org/linux-arm-kernel/20180703211335.GA8858 at rob-hp-laptop/

Indeed, this one got review. I was checking armada-thermal and it never
got any, when it was merged back in the 2013.

> 
> Digging further, I found some interesting history about the parent 'syscon' node
> of the reset-controller. I'd appreciate if you can take a look into the following
> patches/thread -
> 
> The syscon0 node was initially added along with Armada clock driver support.
> It was the very beginning of the upstream for Armada SoCs support (2016).
> And the clock driver is one of the earliest drivers to be mainlined. At that time,
> the clock controller is the only supported device within sycon register range.
> As you can see, the clock dt-binding was exactly aligned with what your suggested
> (no sub-node, compatible and clock-cells just in syscon). 
> 
> https://lore.kernel.org/all/1460648013-31320-5-git-send-email-thomas.petazzoni at free-electrons.com/
> 
> Besides the clock controller, the system controller also includes the GPIO controller,
> pinctl controller, reset controller and other miscellaneous configurations. Before
> adding the pinctl dt-binding, it's decided to use the sub-nodes to present the multiple
> function blocks of various devices.
> 
> https://lore.kernel.org/all/b27495e10fb4f4d8a7fd1a760d49402bbae83b58.1496328934.git-series.gregory.clement at free-electrons.com/

So this is the source here. I see.

Commit comes with a rationale that it will grow significantly.

> 
> In the following patch, it was clearly addressed why sub-nodes was chosen
> over one flat node.
> 
> https://lore.kernel.org/all/bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-series.gregory.clement at free-electrons.com/
> 
> "The initial intent when the binding of the cp110 system controller was to
> have one flat node. The idea being that what is currently a clock-only
> driver in drivers would become a MFD driver, exposing the clock, GPIO and
> pinctrl functionality. However, after taking a step back, this would lead
> to a messy binding. Indeed, a single node would be a GPIO controller,
> clock controller, pinmux controller, and more.
> 
> This patch adopts a more classical solution of a top-level syscon node
> with sub-nodes for the individual devices. The main benefit will be to
> have each functional block associated to its own sub-node where we can
> put its own properties."
> 
> Since then, the dt-binding of Armada's system controller became an
> exception. But I think it's sensible. If we do put all these controllers into
> one node, you can image the properties of different devices will be
> messed up, e.g., not just #reset-cells, #clock-cells and #gpio-cells will
> be gathered. There will be a long compatible list of all devices.
> 
> Going back to my current patch - if we fold the reset controller into the
> parent node, the syscon node will become a hybrid, which GPIO and 
> clock controller are still sub-nodes while reset controller is folded into
> the syscon node. Isn't it very confusing?

Yes, it will be. But more confusing is existing pattern of mixing MMIO
nodes with non-MMIO which you grow. So okay, keep them as separate
child, but drop offset in your patch or unify everything into 'reg'.


Best regards,
Krzysztof


From andyshrk at 163.com  Mon Mar  3 23:16:16 2025
From: andyshrk at 163.com (Andy Yan)
Date: Tue, 4 Mar 2025 15:16:16 +0800 (CST)
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
 <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>
 <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>
Message-ID: <7c4a1e3e.6be8.1956003303a.Coremail.andyshrk@163.com>


Hi Dmitry,

? 2025-03-03 00:21:06?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
>On Sun, Mar 02, 2025 at 06:34:22PM +0800, Andy Yan wrote:
>> 
>> 
>> Hi Dmitry?
>>    Thank you for your review?
>>    Please also review my inline reply.
>>       
>> ? 2025-03-02 02:14:19?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
>> >On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
>> >> From: Andy Yan <andy.yan at rock-chips.com>
>> >> 
>> >> The DW DP TX Controller is compliant with the DisplayPort Specification
>> >> Version 1.4 with the following features:
>> >> 
>> >> * DisplayPort 1.4a
>> >> * Main Link: 1/2/4 lanes
>> >> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> >> * AUX channel 1Mbps
>> >> * Single Stream Transport(SST)
>> >> * Multistream Transport (MST)
>> >> *?Type-C support (alternate mode)
>> >> * HDCP 2.2, HDCP 1.3
>> >> * Supports up to 8/10 bits per color component
>> >> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> >> * Pixel clock up to 594MHz
>> >> * I2S, SPDIF audio interface
>> >> 
>> >> Add library with common helpers to make it can be shared with
>> >> other SoC.
>> >> 
>> >> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> >> 
>> >> drm/bridge: cleanup
>> >
>> >Stray line?
>> 
>> Sorry, will be removed.
>> 
>> >
>> >> 
>> >> ---

........

>> >> +static int dw_dp_link_power_up(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	int ret;
>> >> +	u8 value;
>> >> +
>> >> +	if (link->revision < DP_DPCD_REV_11)
>> >> +		return 0;
>> >> +
>> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
>> >> +	if (ret < 0)
>> >> +		return ret;
>> >> +
>> >> +	value &= ~DP_SET_POWER_MASK;
>> >> +	value |= DP_SET_POWER_D0;
>> >> +
>> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
>> >> +	if (ret < 0)
>> >> +		return ret;
>> >> +
>> >> +	usleep_range(1000, 2000);
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static int dw_dp_link_power_down(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	int ret;
>> >> +	u8 value;
>> >> +
>> >> +	if (link->revision < DP_DPCD_REV_11)
>> >> +		return 0;
>> >> +
>> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
>> >> +	if (ret < 0)
>> >> +		return ret;
>> >> +
>> >> +	value &= ~DP_SET_POWER_MASK;
>> >> +	value |= DP_SET_POWER_D3;
>> >> +
>> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
>> >> +	if (ret < 0)
>> >> +		return ret;
>> >> +
>> >
>> >Would you please mind pulling these two functions to DRM DP helpers?
>> >There are enough users to make this into a common code.
>> 
>> Yes, when developing this patch, I had the same realization. 
>> The processing logic for MSM/Cadence/ANX6345/tegra follows
>> a similar approach.
>> I had originally planned to defer this refactoring until the series of patches is accepted. 
>> Additionally, I have other pending tasks in my TODO list, such as fully decoupling the 
>> bridge driver and encoder/connector components across all Rockchip platforms?
>> But I prioritize completing these foundational features before go to next steps,
>> Is this acceptable ?
>
>You can add necessary helpers as one of the first patches in the
>series. Convert one or several platforms that use drm-misc (i.e. not
>MSM, AMD, i915, nouveau) and send conversion of the rest of the
>platforms as followups.

If  pull these two functions to DRM DP helpers, I think they should be
named as drm_dp_link_power_up/down ?.
I found that tegra/dp.c already use this name, so I need to do a symbols rename
for tegra first to avoid build error like[2].

Can the patch for Tegra be merged  through  drm-misc branch?


[2]https://lore.kernel.org/oe-kbuild-all/202410250305.UHKDhtxy-lkp at intel.com/
>
>> 
>> >
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>> >> +				 const struct drm_dp_desc *desc)
>> >> +{
>> >> +	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
>> >> +	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
>> >> +	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);
>> >
>> >
>> >isn't it drm_dp_read_sink_count_cap() ?
>> 
>> I will have a try, since this drm_dp_read_sink_count_cap requires a connector parameter, 
>> I need to figure out how to get the connector here.
>
>Maybe Maxime's series will you here, see [1].
>
>[1] https://lore.kernel.org/dri-devel/20250225-bridge-connector-v4-4-7ecb07b09cad at kernel.org/
>
>> 
>> >
>> >> +}
>> >> +
>> >> +static int dw_dp_link_parse(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	u8 dpcd;
>> >> +	int ret;

......

>> >> +		break;
>> >> +	}
>> >> +
>> >> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
>> >> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
>> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
>> >> +	} else {
>> >> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
>> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>> >> +	}
>> >> +
>> >> +	vsc.bpc = video->bpc;
>> >> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
>> >> +
>> >> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
>> >> +
>> >> +	return dw_dp_send_sdp(dp, &sdp);
>> >> +}
>> >> +
>> >> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
>> >> +{
>> >> +	switch (pixel_mode) {
>> >> +	case DW_DP_MP_SINGLE_PIXEL:
>> >> +	case DW_DP_MP_DUAL_PIXEL:
>> >> +	case DW_DP_MP_QUAD_PIXEL:
>> >> +		break;
>> >> +	default:
>> >> +		return -EINVAL;
>> >
>> >Is it possible?
>> 
>> This IP is configurable for single/dual/quad pixel modes?
>> It's  quad pixel mode on rk3588 and dual pixel mode on rk3576,
>> so we add this check here.
>
>My question was slightly different: is it possible to end up here in the
>'default' branch?

Sorry, I think I didn't get your key point here.
If someone give a invalid pixe mode(not any of SINGLE/DUAL/QUAD_PIXEL ), 
then we go to default branch return -ENVIAL,  then the dp_bridge enable stop.
This is what we want here.




>
>> 
>> 
>> >
>> >> +	}
>> >> +
>> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
>> >> +			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	struct dw_dp_video *video = &dp->video;
>> >> +
>> >> +	if (!link->vsc_sdp_supported)
>> >> +		return false;
>> >> +
>> >> +	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
>> >> +		return true;
>> >> +
>> >> +	return false;
>> >> +}
>> >> +
>> >> +static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
>> >> +			       u16 vstart, u16 hstart)
>> >> +{
>> >> +	u16 misc = 0;
>> >> +
>> >> +	if (dw_dp_video_need_vsc_sdp(dp))
>> >> +		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
>> >> +
>> >> +	switch (color_format) {
>> >> +	case DRM_COLOR_FORMAT_RGB444:
>> >> +		misc |= DP_MSA_MISC_COLOR_RGB;
>> >> +		break;
>> >> +	case DRM_COLOR_FORMAT_YCBCR444:
>> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
>> >> +		break;
>> >> +	case DRM_COLOR_FORMAT_YCBCR422:
>> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
>> >> +		break;
>> >> +	case DRM_COLOR_FORMAT_YCBCR420:
>> >> +		break;
>> >> +	default:
>> >> +		return -EINVAL;
>> >> +	}
>> >> +
>> >> +	switch (bpc) {
>> >> +	case 6:
>> >> +		misc |= DP_MSA_MISC_6_BPC;
>> >> +		break;
>> >> +	case 8:
>> >> +		misc |= DP_MSA_MISC_8_BPC;
>> >> +		break;
>> >> +	case 10:
>> >> +		misc |= DP_MSA_MISC_10_BPC;
>> >> +		break;
>> >> +	case 12:
>> >> +		misc |= DP_MSA_MISC_12_BPC;
>> >> +		break;
>> >> +	case 16:
>> >> +		misc |= DP_MSA_MISC_16_BPC;
>> >> +		break;
>> >> +	default:
>> >> +		return -EINVAL;
>> >> +	}
>> >> +
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
>> >> +		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static void dw_dp_video_disable(struct dw_dp *dp)
>> >> +{
>> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
>> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
>> >> +}
>> >> +
>> >> +static int dw_dp_video_enable(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_video *video = &dp->video;
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	struct drm_display_mode *mode = &video->mode;
>> >> +	u8 color_format = video->color_format;
>> >> +	u8 bpc = video->bpc;
>> >> +	u8 pixel_mode = video->pixel_mode;
>> >> +	u8 bpp = video->bpp, init_threshold, vic;
>> >> +	u32 hactive, hblank, h_sync_width, h_front_porch;
>> >> +	u32 vactive, vblank, v_sync_width, v_front_porch;
>> >> +	u32 vstart = mode->vtotal - mode->vsync_start;
>> >> +	u32 hstart = mode->htotal - mode->hsync_start;
>> >> +	u32 peak_stream_bandwidth, link_bandwidth;
>> >> +	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
>> >> +	u32 ts, hblank_interval;
>> >> +	u32 value;
>> >> +	int ret;
>> >> +
>> >> +	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
>> >> +	if (ret)
>> >> +		return ret;
>> >> +
>> >> +	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
>> >> +	if (ret)
>> >> +		return ret;
>> >> +
>> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
>> >> +			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
>> >> +
>> >> +	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
>> >> +	value = 0;
>> >> +	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
>> >> +		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
>> >> +	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
>> >> +		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
>> >> +	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_CONFIG1 register */
>> >> +	hactive = mode->hdisplay;
>> >> +	hblank = mode->htotal - mode->hdisplay;
>> >> +	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
>> >> +	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>> >> +		value |= FIELD_PREP(I_P, 1);
>> >> +	vic = drm_match_cea_mode(mode);
>> >> +	if (vic == 5 || vic == 6 || vic == 7 ||
>> >> +	    vic == 10 || vic == 11 || vic == 20 ||
>> >> +	    vic == 21 || vic == 22 || vic == 39 ||
>> >> +	    vic == 25 || vic == 26 || vic == 40 ||
>> >> +	    vic == 44 || vic == 45 || vic == 46 ||
>> >> +	    vic == 50 || vic == 51 || vic == 54 ||
>> >> +	    vic == 55 || vic == 58 || vic  == 59)
>> >> +		value |= R_V_BLANK_IN_OSC;
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_CONFIG2 register */
>> >> +	vblank = mode->vtotal - mode->vdisplay;
>> >> +	vactive = mode->vdisplay;
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
>> >> +		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_CONFIG3 register */
>> >> +	h_sync_width = mode->hsync_end - mode->hsync_start;
>> >> +	h_front_porch = mode->hsync_start - mode->hdisplay;
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
>> >> +		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
>> >> +		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_CONFIG4 register */
>> >> +	v_sync_width = mode->vsync_end - mode->vsync_start;
>> >> +	v_front_porch = mode->vsync_start - mode->vdisplay;
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
>> >> +		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
>> >> +		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_CONFIG5 register */
>> >> +	peak_stream_bandwidth = mode->clock * bpp / 8;
>> >> +	link_bandwidth = (link->rate / 1000) * link->lanes;
>> >> +	ts = peak_stream_bandwidth * 64 / link_bandwidth;
>> >> +	average_bytes_per_tu = ts / 1000;
>> >> +	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
>> >> +	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
>> >> +		if (average_bytes_per_tu < 6)
>> >> +			init_threshold = 32;
>> >> +		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
>> >> +			init_threshold = 12;
>> >> +		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
>> >> +			init_threshold = 3;
>> >> +		else
>> >> +			init_threshold = 16;
>> >> +	} else {
>> >> +		u32 t1 = 0, t2 = 0, t3 = 0;
>> >> +
>> >> +		switch (bpc) {
>> >> +		case 6:
>> >> +			t1 = (4 * 1000 / 9) * link->lanes;
>> >> +			break;
>> >> +		case 8:
>> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
>> >> +				t1 = (1000 / 2) * link->lanes;
>> >> +			} else {
>> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> >> +					t1 = (1000 / 3) * link->lanes;
>> >> +				else
>> >> +					t1 = (3000 / 16) * link->lanes;
>> >> +			}
>> >> +			break;
>> >> +		case 10:
>> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
>> >> +				t1 = (2000 / 5) * link->lanes;
>> >> +			else
>> >> +				t1 = (4000 / 15) * link->lanes;
>> >> +			break;
>> >> +		case 12:
>> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
>> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> >> +					t1 = (1000 / 6) * link->lanes;
>> >> +				else
>> >> +					t1 = (1000 / 3) * link->lanes;
>> >> +			} else {
>> >> +				t1 = (2000 / 9) * link->lanes;
>> >> +			}
>> >> +			break;
>> >> +		case 16:
>> >> +			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
>> >> +			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
>> >> +				t1 = (1000 / 6) * link->lanes;
>> >> +			else
>> >> +				t1 = (1000 / 4) * link->lanes;
>> >> +			break;
>> >> +		default:
>> >> +			return -EINVAL;
>> >> +		}
>> >> +
>> >> +		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
>> >> +			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
>> >> +		else
>> >> +			t2 = (link->rate / 4) * 1000 / mode->clock;
>> >> +
>> >> +		if (average_bytes_per_tu_frac)
>> >> +			t3 = average_bytes_per_tu + 1;
>> >> +		else
>> >> +			t3 = average_bytes_per_tu;
>> >> +		init_threshold = t1 * t2 * t3 / (1000 * 1000);
>> >> +		if (init_threshold <= 16 || average_bytes_per_tu < 10)
>> >> +			init_threshold = 40;
>> >> +	}
>> >> +
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
>> >> +		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
>> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
>> >> +		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
>> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
>> >> +
>> >> +	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
>> >> +	hblank_interval = hblank * (link->rate / 4) / mode->clock;
>> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
>> >> +		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
>> >> +		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
>> >> +
>> >> +	/* Video stream enable */
>> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
>> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
>> >> +
>> >> +	if (dw_dp_video_need_vsc_sdp(dp))
>> >> +		dw_dp_send_vsc_sdp(dp);
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +static void dw_dp_hpd_init(struct dw_dp *dp)
>> >> +{
>> >> +	/* Enable all HPD interrupts */
>> >> +	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
>> >> +			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
>> >> +			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
>> >> +			   FIELD_PREP(HPD_PLUG_EN, 1) |
>> >> +			   FIELD_PREP(HPD_IRQ_EN, 1));
>> >> +
>> >> +	/* Enable all top-level interrupts */
>> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
>> >> +			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
>> >> +}
>> >> +
>> >> +static void dw_dp_aux_init(struct dw_dp *dp)
>> >> +{
>> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
>> >> +			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
>> >> +}
>> >> +
>> >> +static void dw_dp_init_hw(struct dw_dp *dp)
>> >> +{
>> >> +	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
>> >> +			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
>> >> +
>> >> +	dw_dp_hpd_init(dp);
>> >> +	dw_dp_aux_init(dp);
>> >> +}
>> >> +
>> >> +static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
>> >> +{
>> >> +	size_t i, j;
>> >> +
>> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
>> >> +		size_t num = min_t(size_t, size - i * 4, 4);
>> >> +		u32 value = 0;
>> >> +
>> >> +		for (j = 0; j < num; j++)
>> >> +			value |= buffer[i * 4 + j] << (j * 8);
>> >> +
>> >> +		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
>> >> +	}
>> >> +
>> >> +	return size;
>> >> +}
>> >> +
>> >> +static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
>> >> +{
>> >> +	size_t i, j;
>> >> +
>> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
>> >> +		size_t num = min_t(size_t, size - i * 4, 4);
>> >> +		u32 value;
>> >> +
>> >> +		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
>> >> +
>> >> +		for (j = 0; j < num; j++)
>> >> +			buffer[i * 4 + j] = value >> (j * 8);
>> >> +	}
>> >> +
>> >> +	return size;
>> >> +}
>> >> +
>> >> +static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
>> >> +				  struct drm_dp_aux_msg *msg)
>> >> +{
>> >> +	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
>> >> +	unsigned long timeout = msecs_to_jiffies(10);
>> >> +	u32 status, value;
>> >> +	ssize_t ret = 0;
>> >> +
>> >> +	if (WARN_ON(msg->size > 16))
>> >> +		return -E2BIG;
>> >> +
>> >> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
>> >> +	case DP_AUX_NATIVE_WRITE:
>> >> +	case DP_AUX_I2C_WRITE:
>> >> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
>> >> +		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
>> >> +		if (ret < 0)
>> >> +			return ret;
>> >> +		break;
>> >> +	case DP_AUX_NATIVE_READ:
>> >> +	case DP_AUX_I2C_READ:
>> >> +		break;
>> >> +	default:
>> >> +		return -EINVAL;
>> >> +	}
>> >> +
>> >> +	if (msg->size > 0)
>> >> +		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
>> >> +	else
>> >> +		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
>> >> +	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
>> >> +	value |= FIELD_PREP(AUX_ADDR, msg->address);
>> >> +	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
>> >> +
>> >> +	status = wait_for_completion_timeout(&dp->complete, timeout);
>> >> +	if (!status) {
>> >> +		dev_err(dp->dev, "timeout waiting for AUX reply\n");
>> >> +		return -ETIMEDOUT;
>> >> +	}
>> >> +
>> >> +	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
>> >> +	if (value & AUX_TIMEOUT)
>> >> +		return -ETIMEDOUT;
>> >> +
>> >> +	msg->reply = FIELD_GET(AUX_STATUS, value);
>> >> +
>> >> +	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
>> >> +		if (msg->request & DP_AUX_I2C_READ) {
>> >> +			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
>> >> +
>> >> +			if (count != msg->size)
>> >> +				return -EBUSY;
>> >> +
>> >> +			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
>> >> +			if (ret < 0)
>> >> +				return ret;
>> >> +		}
>> >> +	}
>> >> +
>> >> +	return ret;
>> >> +}
>> >> +
>> >> +/*
>> >> + * Limits for the video timing output by DP:
>> >> + * 1. the hfp should be 2 pixels aligned;
>> >> + * 2. the minimum hsync should be 9 pixel;
>> >> + * 3. the minimum hbp should be 16 pixel;
>> >> + */
>> >> +static bool dw_dp_bridge_mode_fixup(struct drm_bridge *bridge,
>> >> +				    const struct drm_display_mode *mode,
>> >> +				    struct drm_display_mode *adjusted_mode)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	int min_hbp = 16;
>> >> +	int min_hsync = 9;
>> >> +
>> >> +	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
>> >> +		adjusted_mode->hsync_start += 1;
>> >> +		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
>> >> +	}
>> >> +	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
>> >> +		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
>> >> +		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
>> >> +	}
>> >> +	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
>> >> +		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
>> >> +		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
>> >> +	}
>> >> +
>> >> +	return true;
>> >> +}
>> >> +
>> >> +static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
>> >> +						    const struct drm_display_info *info,
>> >> +						    const struct drm_display_mode *mode)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	u32 min_bpp;
>> >> +
>> >> +	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
>> >> +	    link->vsc_sdp_supported &&
>> >> +	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
>> >> +		min_bpp = 12;
>> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
>> >> +		min_bpp = 16;
>> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
>> >> +		min_bpp = 18;
>> >> +	else
>> >> +		min_bpp = 24;
>> >> +
>> >> +	if (!link->vsc_sdp_supported &&
>> >> +	    drm_mode_is_420_only(info, mode))
>> >> +		return MODE_NO_420;
>> >> +
>> >> +	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
>> >> +		return MODE_CLOCK_HIGH;
>> >> +
>> >> +	return MODE_OK;
>> >> +}
>> >> +
>> >> +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
>> >> +					   struct drm_bridge_state *old_bridge_state)
>> >> +{
>> >> +	struct drm_atomic_state *state = old_bridge_state->base.state;
>> >> +	struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	struct dw_dp_video *video = &dp->video;
>> >> +	struct drm_display_mode *m = &video->mode;
>> >> +	struct drm_bridge_state *bridge_state;
>> >> +	const struct dw_dp_output_format *fmt;
>> >> +
>> >> +	drm_mode_copy(m, &crtc_state->adjusted_mode);
>> >> +
>> >> +	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
>> >> +	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);
>> >
>> >Should it be a part of the atomic_check() instead?
>> 
>> Since we have modef_fixup in this driver, which is mutually exclusive with atomic_check.
>
>You can convet .mode_fixup into .atomic_check. The latter can change the
>crtc_state->adjusted_mode. It is better to reject the invalid
>combinations from the .atomic_check rather than having to handled them
>later.
>
>> 
>> 
>> 
>> >
>> >> +
>> >> +	video->video_mapping = fmt->video_mapping;
>> >> +	video->color_format = fmt->color_format;
>> >> +	video->bpc = fmt->bpc;
>> >> +	video->bpp = fmt->bpp;
>> >> +}
>> >> +
>> >> +static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	u8 link_status[DP_LINK_STATUS_SIZE];
>> >> +
>> >> +	if (!dw_dp_link_train_valid(&link->train))
>> >> +		return false;
>> >> +
>> >> +	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
>> >> +		return false;
>> >> +
>> >> +	/* Retrain if Channel EQ or CR not ok */
>> >> +	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
>> >> +}
>> >> +
>> >> +static void dw_dp_link_disable(struct dw_dp *dp)
>> >> +{
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +
>> >> +	if (dw_dp_hpd_detect(dp))
>> >> +		dw_dp_link_power_down(dp);
>> >> +
>> >> +	dw_dp_phy_xmit_enable(dp, 0);
>> >> +
>> >> +	phy_power_off(dp->phy);
>> >> +
>> >> +	link->train.clock_recovered = false;
>> >> +	link->train.channel_equalized = false;
>> >> +}
>> >> +
>> >> +static int dw_dp_link_enable(struct dw_dp *dp)
>> >> +{
>> >> +	int ret;
>> >> +
>> >> +	ret = phy_power_on(dp->phy);
>> >> +	if (ret)
>> >> +		return ret;
>> >> +
>> >> +	ret = dw_dp_link_power_up(dp);
>> >> +	if (ret < 0)
>> >> +		return ret;
>> >> +
>> >> +	ret = dw_dp_link_train(dp);
>> >> +
>> >> +	return ret;
>> >> +}
>> >> +
>> >> +static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
>> >> +				       struct drm_bridge_state *old_state)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	struct drm_atomic_state *state = old_state->base.state;
>> >> +	struct drm_connector *connector;
>> >> +	struct drm_connector_state *conn_state;
>> >> +	int ret;
>> >> +
>> >> +	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
>> >> +	if (!connector) {
>> >> +		dev_err(dp->dev, "failed to get connector\n");
>> >> +		return;
>> >> +	}
>> >> +
>> >> +	conn_state = drm_atomic_get_new_connector_state(state, connector);
>> >> +	if (!conn_state) {
>> >> +		dev_err(dp->dev, "failed to get connector state\n");
>> >> +		return;
>> >> +	}
>> >> +
>> >> +	set_bit(0, dp->sdp_reg_bank);
>> >> +
>> >> +	ret = dw_dp_link_enable(dp);
>> >> +	if (ret < 0) {
>> >> +		dev_err(dp->dev, "failed to enable link: %d\n", ret);
>> >> +		return;
>> >> +	}
>> >> +
>> >> +	ret = dw_dp_video_enable(dp);
>> >> +	if (ret < 0) {
>> >> +		dev_err(dp->dev, "failed to enable video: %d\n", ret);
>> >> +		return;
>> >> +	}
>> >> +}
>> >> +
>> >> +static void dw_dp_reset(struct dw_dp *dp)
>> >> +{
>> >> +	int val;
>> >> +
>> >> +	disable_irq(dp->irq);
>> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
>> >> +			   FIELD_PREP(CONTROLLER_RESET, 1));
>> >> +	udelay(10);
>> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
>> >> +			   FIELD_PREP(CONTROLLER_RESET, 0));
>> >> +
>> >> +	dw_dp_init_hw(dp);
>> >> +	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
>> >> +				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
>> >> +	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
>> >> +	enable_irq(dp->irq);
>> >> +}
>> >> +
>> >> +static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
>> >> +					struct drm_bridge_state *old_bridge_state)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +
>> >> +	dw_dp_video_disable(dp);
>> >> +	dw_dp_link_disable(dp);
>> >> +	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
>> >> +	dw_dp_reset(dp);
>> >> +}
>> >> +
>> >> +static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
>> >> +{
>> >> +	int ret;
>> >> +
>> >> +	ret = phy_power_on(dp->phy);
>> >> +	if (ret < 0)
>> >> +		return false;
>> >> +	ret = dw_dp_link_parse(dp);
>> >> +	phy_power_off(dp->phy);
>> >> +
>> >> +	return !ret;
>> >> +}
>> >> +
>> >> +static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +
>> >> +	if (!dw_dp_hpd_detect(dp))
>> >> +		return connector_status_disconnected;
>> >> +
>> >> +	if (!dw_dp_hpd_detect_link(dp))
>> >> +		return connector_status_disconnected;
>> >> +
>> >> +	return connector_status_connected;
>> >> +}
>> >> +
>> >> +static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
>> >> +						     struct drm_connector *connector)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	const struct drm_edid *edid;
>> >> +	int ret;
>> >> +
>> >> +	ret = phy_power_on(dp->phy);
>> >> +	if (ret)
>> >> +		return NULL;
>> >> +
>> >> +	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
>> >> +
>> >> +	phy_power_off(dp->phy);
>> >> +
>> >> +	return edid;
>> >> +}
>> >> +
>> >> +static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
>> >> +						    struct drm_bridge_state *bridge_state,
>> >> +						    struct drm_crtc_state *crtc_state,
>> >> +						    struct drm_connector_state *conn_state,
>> >> +						    unsigned int *num_output_fmts)
>> >> +{
>> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
>> >> +	struct dw_dp_link *link = &dp->link;
>> >> +	struct drm_display_info *di = &conn_state->connector->display_info;
>> >> +	struct drm_display_mode mode = crtc_state->mode;
>> >> +	const struct dw_dp_output_format *fmt;
>> >> +	u32 i, j = 0;
>> >> +	u32 *output_fmts;
>> >> +
>> >> +	*num_output_fmts = 0;
>> >> +
>> >> +	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
>> >> +	if (!output_fmts)
>> >> +		return NULL;
>> >> +
>> >> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
>> >> +		fmt = &dw_dp_output_formats[i];
>> >> +
>> >> +		if (fmt->bpc > conn_state->max_bpc)
>> >> +			continue;
>> >> +
>> >> +		if (!(fmt->color_format & di->color_formats))
>> >> +			continue;
>> >> +
>> >> +		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
>> >> +		    !link->vsc_sdp_supported)
>> >> +			continue;
>> >> +
>> >> +		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
>> >> +		    drm_mode_is_420_only(di, &mode))
>> >> +			continue;
>> >> +
>> >> +		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
>> >> +			continue;
>> >> +
>> >> +		output_fmts[j++] = fmt->bus_format;
>> >> +	}
>> >> +
>> >> +	*num_output_fmts = j;
>> >> +
>> >> +	return output_fmts;
>> >> +}
>> >> +
>> >> +static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
>> >> +	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>> >> +	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>> >> +	.atomic_reset = drm_atomic_helper_bridge_reset,
>> >> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
>> >> +	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
>> >> +	.mode_fixup = dw_dp_bridge_mode_fixup,
>> >> +	.mode_valid = dw_dp_bridge_mode_valid,
>> >> +	.atomic_pre_enable = dw_dp_bridge_atomic_pre_enable,
>> >> +	.atomic_enable = dw_dp_bridge_atomic_enable,
>> >> +	.atomic_disable = dw_dp_bridge_atomic_disable,
>> >> +	.detect = dw_dp_bridge_detect,
>> >> +	.edid_read = dw_dp_bridge_edid_read,
>> >> +};
>> >> +
>> >> +static int dw_dp_link_retrain(struct dw_dp *dp)
>> >> +{
>> >> +	struct drm_device *dev = dp->bridge.dev;
>> >> +	struct drm_modeset_acquire_ctx ctx;
>> >> +	int ret;
>> >> +
>> >> +	if (!dw_dp_needs_link_retrain(dp))
>> >> +		return 0;
>> >> +
>> >> +	dev_dbg(dp->dev, "Retraining link\n");
>> >> +
>> >> +	drm_modeset_acquire_init(&ctx, 0);
>> >> +	for (;;) {
>> >> +		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
>> >> +		if (ret != -EDEADLK)
>> >> +			break;
>> >
>> >I think it's an error to continue in such a case. There should be a
>> >return after the loop if ret is not 0.
>> 
>> Thank you for catching this? I will add a check fater the loop.
>> 
>> 
>> >
>> >> +
>> >> +		drm_modeset_backoff(&ctx);
>> >> +	}
>> >> +
>> >> +	ret = dw_dp_link_train(dp);
>> >> +	drm_modeset_drop_locks(&ctx);
>> >> +	drm_modeset_acquire_fini(&ctx);
>> >> +
>> >> +	return ret;
>> >> +}
>> >> +
>> >> +static void dw_dp_hpd_work(struct work_struct *work)
>> >> +{
>> >> +	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
>> >> +	bool long_hpd;
>> >> +	int ret;
>> >> +
>> >> +	mutex_lock(&dp->irq_lock);
>> >> +	long_hpd = dp->hotplug.long_hpd;
>> >> +	mutex_unlock(&dp->irq_lock);
>> >> +
>> >> +	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
>> >> +
>> >> +	if (!long_hpd) {
>> >> +		if (dw_dp_needs_link_retrain(dp)) {
>> >> +			ret = dw_dp_link_retrain(dp);
>> >> +			if (ret)
>> >> +				dev_warn(dp->dev, "Retrain link failed\n");
>> >> +		}
>> >> +	} else {
>> >> +		drm_helper_hpd_irq_event(dp->bridge.dev);
>> >> +	}
>> >> +}
>> >> +
>> >> +static void dw_dp_handle_hpd_event(struct dw_dp *dp)
>> >> +{
>> >> +	u32 value;
>> >> +
>> >> +	mutex_lock(&dp->irq_lock);
>> >> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
>> >> +
>> >> +	if (value & HPD_IRQ) {
>> >> +		dev_dbg(dp->dev, "IRQ from the HPD\n");
>> >> +		dp->hotplug.long_hpd = false;
>> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
>> >> +	}
>> >> +
>> >> +	if (value & HPD_HOT_PLUG) {
>> >> +		dev_dbg(dp->dev, "Hot plug detected\n");
>> >> +		dp->hotplug.long_hpd = true;
>> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
>> >> +	}
>> >> +
>> >> +	if (value & HPD_HOT_UNPLUG) {
>> >> +		dev_dbg(dp->dev, "Unplug detected\n");
>> >> +		dp->hotplug.long_hpd = true;
>> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
>> >> +	}
>> >> +	mutex_unlock(&dp->irq_lock);
>> >> +
>> >> +	schedule_work(&dp->hpd_work);
>> >> +}
>> >> +
>> >> +static irqreturn_t dw_dp_irq(int irq, void *data)
>> >> +{
>> >> +	struct dw_dp *dp = data;
>> >> +	u32 value;
>> >> +
>> >> +	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
>> >> +	if (!value)
>> >> +		return IRQ_NONE;
>> >> +
>> >> +	if (value & HPD_EVENT)
>> >> +		dw_dp_handle_hpd_event(dp);
>> >> +
>> >> +	if (value & AUX_REPLY_EVENT) {
>> >> +		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
>> >> +		complete(&dp->complete);
>> >> +	}
>> >> +
>> >> +	return IRQ_HANDLED;
>> >> +}
>> >> +
>> >> +static const struct regmap_range dw_dp_readable_ranges[] = {
>> >> +	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
>> >> +	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
>> >> +	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
>> >> +	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
>> >> +	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
>> >> +	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
>> >> +	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
>> >> +	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
>> >> +	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
>> >> +};
>> >> +
>> >> +static const struct regmap_access_table dw_dp_readable_table = {
>> >> +	.yes_ranges     = dw_dp_readable_ranges,
>> >> +	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
>> >> +};
>> >> +
>> >> +static const struct regmap_config dw_dp_regmap_config = {
>> >> +	.reg_bits = 32,
>> >> +	.reg_stride = 4,
>> >> +	.val_bits = 32,
>> >> +	.fast_io = true,
>> >> +	.max_register = DW_DP_MAX_REGISTER,
>> >> +	.rd_table = &dw_dp_readable_table,
>> >> +};
>> >> +
>> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>> >> +			 const struct dw_dp_plat_data *plat_data)
>> >> +{
>> >> +	struct platform_device *pdev = to_platform_device(dev);
>> >> +	struct dw_dp *dp;
>> >> +	struct drm_bridge *bridge;
>> >> +	void __iomem *res;
>> >> +	int ret;
>> >> +
>> >> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
>> >> +	if (!dp)
>> >> +		return ERR_PTR(-ENOMEM);
>> >> +
>> >> +	dp->dev = dev;
>> >> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
>> >> +
>> >> +	dp->plat_data = plat_data;
>> >> +	bridge = &dp->bridge;
>> >> +	mutex_init(&dp->irq_lock);
>> >> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
>> >> +	init_completion(&dp->complete);
>> >> +
>> >> +	res = devm_platform_ioremap_resource(pdev, 0);
>> >> +	if (IS_ERR(res))
>> >> +		return ERR_CAST(res);
>> >> +
>> >> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
>> >> +	if (IS_ERR(dp->regmap)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
>> >> +		return ERR_CAST(dp->regmap);
>> >> +	}
>> >> +
>> >> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
>> >> +	if (IS_ERR(dp->phy)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
>> >> +		return ERR_CAST(dp->phy);
>> >> +	}
>> >> +
>> >> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
>> >> +	if (IS_ERR(dp->apb_clk)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
>> >> +		return ERR_CAST(dp->apb_clk);
>> >> +	}
>> >> +
>> >> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
>> >> +	if (IS_ERR(dp->aux_clk)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
>> >> +		return ERR_CAST(dp->aux_clk);
>> >> +	}
>> >> +
>> >> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
>> >> +	if (IS_ERR(dp->i2s_clk)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
>> >> +		return ERR_CAST(dp->i2s_clk);
>> >> +	}
>> >> +
>> >> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
>> >> +	if (IS_ERR(dp->spdif_clk)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
>> >> +		return ERR_CAST(dp->spdif_clk);
>> >> +	}
>> >> +
>> >> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
>> >> +	if (IS_ERR(dp->hdcp_clk)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
>> >> +		return ERR_CAST(dp->hdcp_clk);
>> >> +	}
>> >> +
>> >> +	dp->rstc = devm_reset_control_get(dev, NULL);
>> >> +	if (IS_ERR(dp->rstc)) {
>> >> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
>> >> +		return ERR_CAST(dp->rstc);
>> >> +	}
>> >> +
>> >> +	dp->irq = platform_get_irq(pdev, 0);
>> >> +	if (dp->irq < 0)
>> >> +		return ERR_PTR(ret);
>> >> +
>> >> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
>> >> +					IRQF_ONESHOT, dev_name(dev), dp);
>> >
>> >Are you ready to handle the IRQ here, before the bridge is filled?
>> 
>> I will move to  devm_request_threaded_irq after dw_dp_init_hw.
>> 
>> 
>> >
>> >> +	if (ret) {
>> >> +		dev_err_probe(dev, ret, "failed to request irq\n");
>> >> +		return ERR_PTR(ret);
>> >> +	}
>> >> +
>> >> +	bridge->of_node = dev->of_node;
>> >> +	bridge->funcs = &dw_dp_bridge_funcs;
>> >> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
>> >> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
>> >> +	bridge->ycbcr_420_allowed = true;
>> >> +	bridge->vendor = "Synopsys";
>> >> +	bridge->product = "DW DP TX";
>> >
>> >These two are unused
>> >
>> >> +
>> >> +	platform_set_drvdata(pdev, dp);
>> >
>> >Unused
>> 
>> I will remove them.
>> 
>> Thanks again.
>> 
>> 
>> >
>> >> +
>> >> +	dp->aux.dev = dev;
>> >> +	dp->aux.drm_dev = encoder->dev;
>> >> +	dp->aux.name = dev_name(dev);
>> >> +	dp->aux.transfer = dw_dp_aux_transfer;
>> >> +	ret = drm_dp_aux_register(&dp->aux);
>> >> +	if (ret) {
>> >> +		dev_err_probe(dev, ret, "Aux register failed\n");
>> >> +		return ERR_PTR(ret);
>> >> +	}
>> >> +
>> >> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>> >> +	if (ret)
>> >> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
>> >> +
>> >> +	dw_dp_init_hw(dp);
>> >> +
>> >> +	return dp;
>> >> +}
>> >> +MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
>> >> +MODULE_DESCRIPTION("DW DP Core Library");
>> >> +MODULE_LICENSE("GPL");
>> >> diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
>> >> new file mode 100644
>> >> index 000000000000..07845f609eca
>> >> --- /dev/null
>> >> +++ b/include/drm/bridge/dw_dp.h
>> >> @@ -0,0 +1,19 @@
>> >> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> >> +/*
>> >> + * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
>> >> + */
>> >> +
>> >> +#ifndef __DW_DP__
>> >> +#define __DW_DP__
>> >> +
>> >> +struct device;
>> >> +struct drm_encoder;
>> >> +struct dw_dp;
>> >> +
>> >> +struct dw_dp_plat_data {
>> >> +	u32 max_link_rate;
>> >> +};
>> >> +
>> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>> >> +			 const struct dw_dp_plat_data *plat_data);
>> >> +#endif /* __DW_DP__ */
>> >> -- 
>> >> 2.34.1
>> >> 
>> >
>> >-- 
>> >With best wishes
>> >Dmitry
>
>-- 
>With best wishes
>Dmitry

From jens.wiklander at linaro.org  Mon Mar  3 23:17:23 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Tue, 4 Mar 2025 08:17:23 +0100
Subject: [PATCH v4 0/6] TEE subsystem for restricted dma-buf allocations
In-Reply-To: <CAPj87rN7J6u9NsviAdw8=OenEYc8t719Lds6u6-BhFKrtkLZ-A@mail.gmail.com>
References: <20241217100809.3962439-1-jens.wiklander@linaro.org>
 <20250212205613.4400a888@collabora.com> <CAFA6WYOaGEPj0xNEDBCoEmjJreEHChjQ2hyXRJ_CYoGhiBonfw@mail.gmail.com>
 <20250213093557.278f5d19@collabora.com> <CAFA6WYOJkSRsH-15QdqXNMd08Q=Dg4NkRd1Cr9LXA+5nozTF6g@mail.gmail.com>
 <20250213134008.4cbef142@collabora.com> <CAPj87rM5Y=-Jgf4mwukicF6Yb-vccn2fpG2X1jNq0upH2+cAEQ@mail.gmail.com>
 <CAHUa44G9hw-z6wzxg=HkVAxPKEW1yES5JTEqRWMvJUJAtcUDkQ@mail.gmail.com>
 <CAPj87rPHnME5Osgnf5-FSAu22mDpLj=dzvhi_NqEcOwr1ThgGw@mail.gmail.com>
 <CAHUa44Gs0D1fBD0=+EDgcQUMeDv4knci9trUkYEc1J98qFV7HQ@mail.gmail.com>
 <CAFA6WYOuTwRPEh3L7+hMyARB_E73xmp+OwhKyS-r4+ryS7=9sw@mail.gmail.com>
 <20250214164856.0d2ead8a@collabora.com> <CAFA6WYPc6EHQwcPuMZRm4C1P6SoDrCzEPUmju_meupB6NXQ1sg@mail.gmail.com>
 <CAPj87rN-OYTzh5=Gdv619UQD5=x=U6Yt=uV4N1kCs4Zao4RVAg@mail.gmail.com>
 <CAFA6WYMLLLSuz3y5J+DuRFAGrmwpZoWax5sasfAUhXoQXmrNNA@mail.gmail.com> <CAPj87rN7J6u9NsviAdw8=OenEYc8t719Lds6u6-BhFKrtkLZ-A@mail.gmail.com>
Message-ID: <CAHUa44FkG1NAWpoW8UVBywv44XW_mjAJa32PcC9mcmiOLdiRqw@mail.gmail.com>

Hi Daniel,

On Fri, Feb 21, 2025 at 3:12?PM Daniel Stone <daniel at fooishbar.org> wrote:
>
> Hi Sumit,
>
> On Fri, 21 Feb 2025 at 11:24, Sumit Garg <sumit.garg at linaro.org> wrote:
> > On Tue, 18 Feb 2025 at 21:52, Daniel Stone <daniel at fooishbar.org> wrote:
> > > dma-heaps was created to solve the problem of having too many
> > > 'allocate $n bytes from $specialplace' uAPIs. The proliferation was
> > > painful and making it difficult for userspace to do what it needed to
> > > do. Userspace doesn't _yet_ make full use of it, but the solution is
> > > to make userspace make full use of it, not to go create entirely
> > > separate allocation paths for unclear reasons.
> > >
> > > Besides, I'm writing this from a platform that implements SVP not via
> > > TEE. I've worked on platforms which implement SVP without any TEE,
> > > where the TEE implementation would be at best a no-op stub, and at
> > > worst flat-out impossible.
> >
> > Can you elaborate the non-TEE use-case for Secure Video Path (SVP) a
> > bit more? As to how the protected/encrypted media content pipeline
> > works? Which architecture support does your use-case require? Is there
> > any higher privileged level firmware interaction required to perform
> > media content decryption into restricted memory? Do you plan to
> > upstream corresponding support in near future?
>
> You can see the MTK SVP patches on list which use the MTK SMC to mediate it.
>
> There are TI Jacinto platforms which implement a 'secure' area
> configured statically by (IIRC) BL2, with static permissions defined
> for each AXI endpoint, e.g. CPU write + codec RW + dispc read. I've
> heard of another SoC vendor doing the same, but I don't think I can
> share those details. There is no TEE interaction.
>
> I'm writing this message from an AMD laptop which implements
> restricted content paths outside of TEE. I don't have the full picture
> of how SVP is implemented on AMD systems, but I do know that I don't
> have any TEE devices exposed.
>
> > Let me try to elaborate on the Secure Video Path (SVP) flow requiring
> > a TEE implementation (in general terms a higher privileged firmware
> > managing the pipeline as the kernel/user-space has no access
> > permissions to the plain text media content):
> >
> > - [...]
>
> Yeah, I totally understand the TEE usecase. I think that TEE is a good
> design to implement this. I think that TEE should be used for SVP
> where it makes sense.
>
> Please understand that I am _not_ arguing that no-one should use TEE for SVP!
>
> > > So, again, let's
> > > please turn this around: _why_ TEE? Who benefits from exposing this as
> > > completely separate to the more generic uAPI that we specifically
> > > designed to handle things like this?
> >
> > The bridging between DMA heaps and TEE would still require user-space
> > to perform an IOCTL into TEE to register the DMA-bufs as you can see
> > here [1]. Then it will rather be two handles for user-space to manage.
>
> Yes, the decoder would need to do this. That's common though: if you
> want to share a buffer between V4L2 and DRM, you have three handles:
> the V4L2 buffer handle, the DRM GEM handle, and the dmabuf you use to
> bridge the two.
>
> > Similarly during restricted memory allocation/free we need another
> > glue layer under DMA heaps to TEE subsystem.
>
> Yep.
>
> > The reason is simply which has been iterated over many times in the
> > past threads that:
> >
> >     "If user-space has to interact with a TEE device for SVP use-case
> > then why it's not better to ask TEE to allocate restricted DMA-bufs
> > too"
>
> The first word in your proposition is load-bearing.
>
> Build out the usecase a little more here. You have a DRMed video
> stream coming in, which you need to decode (involving TEE for this
> usecase). You get a dmabuf handle to the decoded frame. You need to
> pass the dmabuf across to the Wayland compositor. The compositor needs
> to pass it to EGL/Vulkan to import and do composition, which in turn
> passes it to the GPU DRM driver. The output of the composition is in
> turn shared between the GPU DRM driver and the separate KMS DRM
> driver, with the involvement of GBM.
>
> For the platforms I'm interested in, the GPU DRM driver needs to
> switch into protected mode, which has no involvement at all with TEE -
> it's architecturally impossible to have TEE involved without moving
> most of the GPU driver into TEE and destroying performance. The
> display hardware also needs to engage protected mode, which again has
> no involvement with TEE and again would need to have half the driver
> moved into TEE for no benefit in order to do so. The Wayland
> compositor also has no interest in TEE: it tells the GPU DRM driver
> about the protected status of its buffers, and that's it.
>
> What these components _are_ opinionated about, is the way buffers are
> allocated and managed. We built out dmabuf modifiers for this usecase,
> and we have a good negotiation protocol around that. We also really
> care about buffer placement in some usecases - e.g. some display/codec
> hardware requires buffers to be sourced from contiguous memory, other
> hardware needs to know that when it shares buffers with another
> device, it needs to place the buffers outside of inaccessible/slow
> local RAM. So we built out dma-heaps, so every part of the component
> in the stack can communicate their buffer-placement needs in the same
> way as we do modifiers, and negotiate an acceptable allocation.
>
> That's my starting point for this discussion. We have a mechanism to
> deal with the fact that buffers need to be shared between different IP
> blocks which have their own constraints on buffer placement, avoiding
> the current problem of having every subsystem reinvent their own
> allocation uAPI which was burying us in impedance mismatch and
> confusion. That mechanism is dma-heaps. It seems like your starting
> point from this discussion is that you've implemented a TEE-centric
> design for SVP, and so all of userspace should bypass our existing
> cross-subsystem special-purpose allocation mechanism, and write
> specifically to one implementation. I believe that is a massive step
> backwards and an immediate introduction of technical debt.
>
> Again, having an implementation of SVP via TEE makes a huge amount of
> sense. Having _most_ SVP implementations via TEE still makes a lot of
> sense. Having _all_ SVP implementations eventually be via TEE would
> still make sense. But even if we were at that point - which we aren't
> - it still doesn't justify telling userspace 'use the generic dma-heap
> uAPI for every device-specific allocation constraint, apart from SVP
> which has a completely different way to allocate some bytes'.

I must admit that I don't see how this makes a significant difference,
but then I haven't hacked much in the stacks you're talking about, so
I'm going to take your word for it.

I've experimented with providing a dma-heap replacing the TEE API. The
implementation is more complex than I first anticipated, adding about
400 lines to the patch set. From user space, it looks like another
dma-heap. I'm using the names you gave earlier,
protected,secure-video, protected,trusted-ui, and
protected,secure-video-record. However, I wonder if we shouldn't use
"restricted" instead of "protected" since we had agreed to call it
restricted memory earlier.

I'll soon post this in a v6 and an updated demo.

Cheers,
Jens


From krzk at kernel.org  Mon Mar  3 23:21:39 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 08:21:39 +0100
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
 <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
 <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>
Message-ID: <027decb4-3fa9-40a5-9cf4-65f9a69b4566@kernel.org>

On 03/03/2025 18:18, Ivaylo Ivanov wrote:
> On 3/3/25 09:24, Krzysztof Kozlowski wrote:
>> On 02/03/2025 10:16, Ivaylo Ivanov wrote:
>>> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>>>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>>>
>>>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>> ---
>>>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>>>  1 file changed, 76 insertions(+)
>>>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>> You have undocumented dependencies which prevent merging this file.
>>>>>> First, dependencies have to be clearly expressed.
>>>>> They are, in the cover letter.
>>>> Where? I read it twice. Dependencies is the most important thing and
>>>> should scream at beginning of the cover letter, so if you bury them
>>>> somewhere deep it also would not matter - just like they were missing.
>>>>
>>>>>> Second, you should
>>>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>>>> be merged for current release (just use clocks with long names, without IDs).
>>>>> Sure
>>>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>> new file mode 100644
>>>>>>> index 000000000..7d879ec8b
>>>>>>> --- /dev/null
>>>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>> @@ -0,0 +1,76 @@
>>>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>>>> +%YAML 1.2
>>>>>>> +---
>>>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>> +
>>>>>>> +title: Exynos2200 USB controller PHY
>>>>>>> +
>>>>>>> +maintainers:
>>>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>> +
>>>>>>> +description:
>>>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>>>> It's not (I think). There's a few reasons I've decided to make this separate
>>>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>>>
>>>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>>>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>>>> at diagram - they call it phy controller.
>>> Ughm. What? So in most exynos cases, there's a combination of multiple phys?
>>
>>>>> for them, and all that is needed from it is to disable HWACG, assert/
>>>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>>>> Does it mean there is no USB DRD phy controller as before?
>>>>
>>>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
>>> So...
>>>
>>> DWC3 -> USBDRD (USBCON) -> PHYs?
>> No, drop last phy. You just wrote the same as me - two phys, because
>> usbdrd is the phy. In all existing designs there is no such controllable
>> object from the point of view of operating system.
> 
> What? Per my understanding, the phy property should refer to whatever is
> is connected to dwc3 UTMI. In this case it's the so-called USBDRD phy (called
> usbcon in downstream). Considering that the eUSB2 IP definitely also has UTMI
> that has to be connected to something, doesn't that mean we have clearly

The entire point is that eUSB2 is connected to DWC3, no? That's exactly
how it is done for example on Qualcomm SoC. Otherwise you claim that
DWC3 controls one phy, which controls another phy which controls UTMI...

> separated hardware blocks? Now, I guess one could argue that this USBCON
> hardware block could be classified as a syscon. But I don't see the problem
> with the current binding description, nor the modelling, as it represents
> how the hardware is (unless I've gotten it completely wrong).

It is the first time you use argument that it represents how the
hardware is and this is what we actually disagree. It is not like that.
You do not have chain of phys. Just look at any USB 3.0 DRD DWC diagram
from any Samsung SoC: where would you squeeze these two phys in relation
to what is called there "USB 3.0 PHY" which would be the third phy (!!!).

Best regards,
Krzysztof


From quic_zhenhuah at quicinc.com  Mon Mar  3 23:25:55 2025
From: quic_zhenhuah at quicinc.com (Zhenhua Huang)
Date: Tue, 4 Mar 2025 15:25:55 +0800
Subject: [PATCH v8] arm64: mm: Populate vmemmap at the page level if not
 section aligned
In-Reply-To: <78d55e35-6cda-4f5e-8e52-0a54b1e64592@redhat.com>
References: <20250219084001.1272445-1-quic_zhenhuah@quicinc.com>
 <78d55e35-6cda-4f5e-8e52-0a54b1e64592@redhat.com>
Message-ID: <b68799da-7290-418a-b7db-4cfad7b12e0f@quicinc.com>



On 2025/3/3 18:01, David Hildenbrand wrote:
> On 19.02.25 09:40, Zhenhua Huang wrote:
>> On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
>> to 27, making one section 128M. The related page struct which vmemmap
>> points to is 2M then.
>> Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
>> vmemmap to populate at the PMD section level which was suitable
>> initially since hot plug granule is always one section(128M). However,
>> commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
>> introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
>> existing arm64 assumptions.
>>
>> The first problem is that if start or end is not aligned to a section
>> boundary, such as when a subsection is hot added, populating the entire
>> section is wasteful.
>>
>> The next problem is if we hotplug something that spans part of 128 MiB
>> section (subsections, let's call it memblock1), and then hotplug 
>> something
>> that spans another part of a 128 MiB section(subsections, let's call it
>> memblock2), and subsequently unplug memblock1, vmemmap_free() will clear
>> the entire PMD entry which also supports memblock2 even though memblock2
>> is still active.
>>
>> Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the
>> fix similar to x86-64: populate to pages levels if start/end is not 
>> aligned
>> with section boundary.
>>
>> Cc: <stable at vger.kernel.org> # v5.4+
>> Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
>> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
>> ---
>> Hi Catalin and David,
>> Following our latest discussion, I've updated the patch for your review.
>> I also removed Catalin's review tag since I've made significant 
>> modifications.
>> ? arch/arm64/mm/mmu.c | 5 ++++-
>> ? 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index b4df5bc5b1b8..de05ccf47f21 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long 
>> start, unsigned long end, int node,
>> ????????? struct vmem_altmap *altmap)
>> ? {
>> ????? WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
>> +??? /* [start, end] should be within one section */
>> +??? WARN_ON(end - start > PAGES_PER_SECTION * sizeof(struct page));
>> -??? if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
>> +??? if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
>> +??????? (end - start < PAGES_PER_SECTION * sizeof(struct page)))
> 
> Indentation should be
> 
>  ????if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
>  ??????? (end - start < PAGES_PER_SECTION * sizeof(struct page)))
> 

Thanks, I will repost with the above fix and WARN_ON_ONCE as you 
preferred in v7.

> 
> Acked-by: David Hildenbrand <david at redhat.com>
> 
> 
> Thanks!
> 



From quic_zhenhuah at quicinc.com  Mon Mar  3 23:27:00 2025
From: quic_zhenhuah at quicinc.com (Zhenhua Huang)
Date: Tue, 4 Mar 2025 15:27:00 +0800
Subject: [PATCH v9] arm64: mm: Populate vmemmap at the page level if not section aligned
Message-ID: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>

On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
to 27, making one section 128M. The related page struct which vmemmap
points to is 2M then.
Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
vmemmap to populate at the PMD section level which was suitable
initially since hot plug granule is always one section(128M). However,
commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
existing arm64 assumptions.

The first problem is that if start or end is not aligned to a section
boundary, such as when a subsection is hot added, populating the entire
section is wasteful.

The next problem is if we hotplug something that spans part of 128 MiB
section (subsections, let's call it memblock1), and then hotplug something
that spans another part of a 128 MiB section(subsections, let's call it
memblock2), and subsequently unplug memblock1, vmemmap_free() will clear
the entire PMD entry which also supports memblock2 even though memblock2
is still active.

Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the
fix similar to x86-64: populate to pages levels if start/end is not aligned
with section boundary.

Cc: <stable at vger.kernel.org> # v5.4+
Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
Acked-by: David Hildenbrand <david at redhat.com>
Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
---
 arch/arm64/mm/mmu.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index b4df5bc5b1b8..1dfe1a8efdbe 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
 		struct vmem_altmap *altmap)
 {
 	WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
+	/* [start, end] should be within one section */
+	WARN_ON_ONCE(end - start > PAGES_PER_SECTION * sizeof(struct page));
 
-	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
+	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
+	    (end - start < PAGES_PER_SECTION * sizeof(struct page)))
 		return vmemmap_populate_basepages(start, end, node, altmap);
 	else
 		return vmemmap_populate_hugepages(start, end, node, altmap);
-- 
2.25.1



From wei.fang at nxp.com  Mon Mar  3 23:21:59 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:59 +0800
Subject: [PATCH v3 net-next 11/13] net: enetc: add VLAN filtering support for i.MX95 ENETC PF
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-12-wei.fang@nxp.com>

Add VLAN hash filter support for i.MX95 ENETC PF. If VLAN filtering is
disabled, then VLAN promiscuous mode will be enabled, which means that
PF qualifies for reception of all VLAN tags.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 ++++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +++++++++++++++++++
 .../freescale/enetc/enetc_pf_common.c         |  2 +-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)		((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)		((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a)		((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a)		((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR			0x4004
 #define  PMCAPR_HD			BIT(8)
 #define  PMCAPR_FP			GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index adaf28fdf0aa..e08d06e22898 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -101,6 +101,13 @@ static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
 	}
 }
 
+static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
+					      int si, u64 hash)
+{
+	enetc_port_wr(hw, ENETC4_PSIVHFR0(si), lower_32_bits(hash));
+	enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
+}
+
 static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
 {
 	struct enetc_mac_list_entry *entry;
@@ -403,6 +410,7 @@ static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
 static const struct enetc_pf_ops enetc4_pf_ops = {
 	.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
 	.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
+	.set_si_vlan_hash_filter = enetc4_pf_set_si_vlan_hash_filter,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -692,6 +700,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
 				  netdev_features_t features)
 {
+	netdev_features_t changed = ndev->features ^ features;
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_hw *hw = &priv->si->hw;
+
+	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+		bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+		enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+	}
+
 	enetc_set_features(ndev, features);
 
 	return 0;
@@ -705,6 +723,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
 	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
 	.ndo_set_features	= enetc4_pf_set_features,
+	.ndo_vlan_rx_add_vid	= enetc_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 9f812c1af7a3..3f7ccc482301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
-		ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
+		ndev->hw_features &= ~NETIF_F_LOOPBACK;
 		goto end;
 	}
 
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:22:00 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:22:00 +0800
Subject: [PATCH v3 net-next 12/13] net: enetc: add loopback support for i.MX95 ENETC PF
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-13-wei.fang@nxp.com>

Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++++++++++++++++++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index e08d06e22898..ea859792ccfa 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -108,6 +108,21 @@ static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
 	enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_si *si = priv->si;
+	u32 val;
+
+	val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+	val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+	/* Default to select MAC level loopback mode if loopback is enabled. */
+	val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+			       PM_CMD_CFG_LPBK_MODE);
+
+	enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
 {
 	struct enetc_mac_list_entry *entry;
@@ -710,6 +725,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
 		enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
 	}
 
+	if (changed & NETIF_F_LOOPBACK)
+		enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
 	enetc_set_features(ndev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3f7ccc482301..0a2b8769a175 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	}
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
-	if (!is_enetc_rev1(si)) {
-		ndev->hw_features &= ~NETIF_F_LOOPBACK;
+	if (!is_enetc_rev1(si))
 		goto end;
-	}
 
 	ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 			     NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:22:01 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:22:01 +0800
Subject: [PATCH v3 net-next 13/13] MAINTAINERS: add new file ntmp.h to ENETC driver
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-14-wei.fang@nxp.com>

Add new file ntmp.h. to ENETC driver.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7078199fcebf..e259b659eadb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9174,6 +9174,7 @@ F:	Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F:	drivers/net/ethernet/freescale/enetc/
 F:	include/linux/fsl/enetc_mdio.h
 F:	include/linux/fsl/netc_global.h
+F:	include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M:	Claudiu Manoil <claudiu.manoil at nxp.com>
-- 
2.34.1



From sumit.garg at kernel.org  Mon Mar  3 23:45:54 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 4 Mar 2025 13:15:54 +0530
Subject: [PATCH v4 0/6] TEE subsystem for restricted dma-buf allocations
In-Reply-To: <CAHUa44FkG1NAWpoW8UVBywv44XW_mjAJa32PcC9mcmiOLdiRqw@mail.gmail.com>
References: <CAHUa44G9hw-z6wzxg=HkVAxPKEW1yES5JTEqRWMvJUJAtcUDkQ@mail.gmail.com>
 <CAPj87rPHnME5Osgnf5-FSAu22mDpLj=dzvhi_NqEcOwr1ThgGw@mail.gmail.com>
 <CAHUa44Gs0D1fBD0=+EDgcQUMeDv4knci9trUkYEc1J98qFV7HQ@mail.gmail.com>
 <CAFA6WYOuTwRPEh3L7+hMyARB_E73xmp+OwhKyS-r4+ryS7=9sw@mail.gmail.com>
 <20250214164856.0d2ead8a@collabora.com>
 <CAFA6WYPc6EHQwcPuMZRm4C1P6SoDrCzEPUmju_meupB6NXQ1sg@mail.gmail.com>
 <CAPj87rN-OYTzh5=Gdv619UQD5=x=U6Yt=uV4N1kCs4Zao4RVAg@mail.gmail.com>
 <CAFA6WYMLLLSuz3y5J+DuRFAGrmwpZoWax5sasfAUhXoQXmrNNA@mail.gmail.com>
 <CAPj87rN7J6u9NsviAdw8=OenEYc8t719Lds6u6-BhFKrtkLZ-A@mail.gmail.com>
 <CAHUa44FkG1NAWpoW8UVBywv44XW_mjAJa32PcC9mcmiOLdiRqw@mail.gmail.com>
Message-ID: <Z8avsigZJ4vqmiA4@sumit-X1>

On Tue, Mar 04, 2025 at 08:17:23AM +0100, Jens Wiklander wrote:
> Hi Daniel,
> 
> On Fri, Feb 21, 2025 at 3:12?PM Daniel Stone <daniel at fooishbar.org> wrote:
> >
> > Hi Sumit,
> >
> > On Fri, 21 Feb 2025 at 11:24, Sumit Garg <sumit.garg at linaro.org> wrote:
> > > On Tue, 18 Feb 2025 at 21:52, Daniel Stone <daniel at fooishbar.org> wrote:
> > > > dma-heaps was created to solve the problem of having too many
> > > > 'allocate $n bytes from $specialplace' uAPIs. The proliferation was
> > > > painful and making it difficult for userspace to do what it needed to
> > > > do. Userspace doesn't _yet_ make full use of it, but the solution is
> > > > to make userspace make full use of it, not to go create entirely
> > > > separate allocation paths for unclear reasons.
> > > >
> > > > Besides, I'm writing this from a platform that implements SVP not via
> > > > TEE. I've worked on platforms which implement SVP without any TEE,
> > > > where the TEE implementation would be at best a no-op stub, and at
> > > > worst flat-out impossible.
> > >
> > > Can you elaborate the non-TEE use-case for Secure Video Path (SVP) a
> > > bit more? As to how the protected/encrypted media content pipeline
> > > works? Which architecture support does your use-case require? Is there
> > > any higher privileged level firmware interaction required to perform
> > > media content decryption into restricted memory? Do you plan to
> > > upstream corresponding support in near future?
> >
> > You can see the MTK SVP patches on list which use the MTK SMC to mediate it.
> >
> > There are TI Jacinto platforms which implement a 'secure' area
> > configured statically by (IIRC) BL2, with static permissions defined
> > for each AXI endpoint, e.g. CPU write + codec RW + dispc read. I've
> > heard of another SoC vendor doing the same, but I don't think I can
> > share those details. There is no TEE interaction.
> >
> > I'm writing this message from an AMD laptop which implements
> > restricted content paths outside of TEE. I don't have the full picture
> > of how SVP is implemented on AMD systems, but I do know that I don't
> > have any TEE devices exposed.
> >
> > > Let me try to elaborate on the Secure Video Path (SVP) flow requiring
> > > a TEE implementation (in general terms a higher privileged firmware
> > > managing the pipeline as the kernel/user-space has no access
> > > permissions to the plain text media content):
> > >
> > > - [...]
> >
> > Yeah, I totally understand the TEE usecase. I think that TEE is a good
> > design to implement this. I think that TEE should be used for SVP
> > where it makes sense.
> >
> > Please understand that I am _not_ arguing that no-one should use TEE for SVP!
> >
> > > > So, again, let's
> > > > please turn this around: _why_ TEE? Who benefits from exposing this as
> > > > completely separate to the more generic uAPI that we specifically
> > > > designed to handle things like this?
> > >
> > > The bridging between DMA heaps and TEE would still require user-space
> > > to perform an IOCTL into TEE to register the DMA-bufs as you can see
> > > here [1]. Then it will rather be two handles for user-space to manage.
> >
> > Yes, the decoder would need to do this. That's common though: if you
> > want to share a buffer between V4L2 and DRM, you have three handles:
> > the V4L2 buffer handle, the DRM GEM handle, and the dmabuf you use to
> > bridge the two.
> >
> > > Similarly during restricted memory allocation/free we need another
> > > glue layer under DMA heaps to TEE subsystem.
> >
> > Yep.
> >
> > > The reason is simply which has been iterated over many times in the
> > > past threads that:
> > >
> > >     "If user-space has to interact with a TEE device for SVP use-case
> > > then why it's not better to ask TEE to allocate restricted DMA-bufs
> > > too"
> >
> > The first word in your proposition is load-bearing.
> >
> > Build out the usecase a little more here. You have a DRMed video
> > stream coming in, which you need to decode (involving TEE for this
> > usecase). You get a dmabuf handle to the decoded frame. You need to
> > pass the dmabuf across to the Wayland compositor. The compositor needs
> > to pass it to EGL/Vulkan to import and do composition, which in turn
> > passes it to the GPU DRM driver. The output of the composition is in
> > turn shared between the GPU DRM driver and the separate KMS DRM
> > driver, with the involvement of GBM.
> >
> > For the platforms I'm interested in, the GPU DRM driver needs to
> > switch into protected mode, which has no involvement at all with TEE -
> > it's architecturally impossible to have TEE involved without moving
> > most of the GPU driver into TEE and destroying performance. The
> > display hardware also needs to engage protected mode, which again has
> > no involvement with TEE and again would need to have half the driver
> > moved into TEE for no benefit in order to do so. The Wayland
> > compositor also has no interest in TEE: it tells the GPU DRM driver
> > about the protected status of its buffers, and that's it.
> >
> > What these components _are_ opinionated about, is the way buffers are
> > allocated and managed. We built out dmabuf modifiers for this usecase,
> > and we have a good negotiation protocol around that. We also really
> > care about buffer placement in some usecases - e.g. some display/codec
> > hardware requires buffers to be sourced from contiguous memory, other
> > hardware needs to know that when it shares buffers with another
> > device, it needs to place the buffers outside of inaccessible/slow
> > local RAM. So we built out dma-heaps, so every part of the component
> > in the stack can communicate their buffer-placement needs in the same
> > way as we do modifiers, and negotiate an acceptable allocation.
> >
> > That's my starting point for this discussion. We have a mechanism to
> > deal with the fact that buffers need to be shared between different IP
> > blocks which have their own constraints on buffer placement, avoiding
> > the current problem of having every subsystem reinvent their own
> > allocation uAPI which was burying us in impedance mismatch and
> > confusion. That mechanism is dma-heaps. It seems like your starting
> > point from this discussion is that you've implemented a TEE-centric
> > design for SVP, and so all of userspace should bypass our existing
> > cross-subsystem special-purpose allocation mechanism, and write
> > specifically to one implementation. I believe that is a massive step
> > backwards and an immediate introduction of technical debt.
> >
> > Again, having an implementation of SVP via TEE makes a huge amount of
> > sense. Having _most_ SVP implementations via TEE still makes a lot of
> > sense. Having _all_ SVP implementations eventually be via TEE would
> > still make sense. But even if we were at that point - which we aren't
> > - it still doesn't justify telling userspace 'use the generic dma-heap
> > uAPI for every device-specific allocation constraint, apart from SVP
> > which has a completely different way to allocate some bytes'.
> 
> I must admit that I don't see how this makes a significant difference,
> but then I haven't hacked much in the stacks you're talking about, so
> I'm going to take your word for it.
> 
> I've experimented with providing a dma-heap replacing the TEE API. The
> implementation is more complex than I first anticipated, adding about
> 400 lines to the patch set.

I did anticipated this but let's give it a try and see if DMA heaps
really adds any value from user-space point of view. If it does then it
will be worth the maintenence overhead.

> From user space, it looks like another
> dma-heap. I'm using the names you gave earlier,
> protected,secure-video, protected,trusted-ui, and
> protected,secure-video-record. However, I wonder if we shouldn't use
> "restricted" instead of "protected" since we had agreed to call it
> restricted memory earlier.

Let's stick with "restricted" memory buffer references only.

-Sumit


From wbg at kernel.org  Mon Mar  3 23:47:36 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 16:47:36 +0900
Subject: [PATCH v6 3/3] counter: microchip-tcb-capture: Add capture
 extensions for registers RA/RB
In-Reply-To: <20250227144023.64530-4-csokas.bence@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-4-csokas.bence@prolan.hu>
Message-ID: <Z8awGBW8obpG1QPN@ishi>

On Thu, Feb 27, 2025 at 03:40:20PM +0100, Bence Cs?k?s wrote:
> +static int mchp_tc_count_cap_read(struct counter_device *counter,
> +				  struct counter_count *count, size_t idx, u64 *val)
> +{
> +	struct mchp_tc_data *const priv = counter_priv(counter);
> +	u32 cnt;
> +	int ret;
> +
> +	switch (idx) {
> +	case COUNTER_MCHP_EXCAP_RA:
> +		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), &cnt);
> +		break;
> +	case COUNTER_MCHP_EXCAP_RB:
> +		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), &cnt);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (!ret)
> +		*val = cnt;
> +
> +	return ret;
> +}

It's cleaner to exit early on an error than to carry it to the end.
Instead of if (!ret), perform an if (ret) return ret to exit early on an
error, then simply return 0 at the end of the funtion.

> diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
> index ee72f1463594..5c015fafe42c 100644
> --- a/include/uapi/linux/counter/microchip-tcb-capture.h
> +++ b/include/uapi/linux/counter/microchip-tcb-capture.h
> @@ -12,6 +12,9 @@
>   * Count 0
>   * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
>   * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
> + * \__  Extension capture0    (RA register)
> + * \__  Extension capture1    (RB register)
> + * \__  Extension capture2    (RC register)

The capture2 extension doesn't exist in this patch so remove this
comment line.

> @@ -30,6 +33,12 @@ enum counter_mchp_signals {
>  	COUNTER_MCHP_SIG_TIOB,
>  };
>  
> +enum counter_mchp_capture_extensions {
> +	COUNTER_MCHP_EXCAP_RA,
> +	COUNTER_MCHP_EXCAP_RB,
> +	COUNTER_MCHP_EXCAP_RC,
> +};

Remove COUNTER_MCHP_EXCAP_RC for the same reason as above.

Also, I would argue for these to be preprocessor defines rather than
enum for the same reasons as in my other review[^1].

One final comment: is RA/RB the best way to differentiate these? One of
the benefits of abstraction layers is that users won't need to be
concerned about the hardware details, and naming the capture values
after their respective general register hardware names feels somewhat
antithetic to that end.

I imagine there are better ways to refer to these that would communicate
their relationship better, such as "primary capture" and "secondary
capture". However at that point capture0 and capture1 would seem
obvious enough, in which case you might not even need to expose these to
userspace at all.

William Breathitt Gray

[^1] https://lore.kernel.org/all/Z8alaOTjZeRuXnUI at ishi/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/873faf8a/attachment.sig>

From menglong8.dong at gmail.com  Mon Mar  3 23:47:45 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 15:47:45 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250304061635.GA29480@noisy.programming.kicks-ass.net>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
Message-ID: <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>

On Tue, Mar 4, 2025 at 2:16?PM Peter Zijlstra <peterz at infradead.org> wrote:
>
> On Tue, Mar 04, 2025 at 06:38:53AM +0100, Peter Zijlstra wrote:
> > On Tue, Mar 04, 2025 at 09:10:12AM +0800, Menglong Dong wrote:
> > > Hello, sorry that I forgot to add something to the changelog. In fact,
> > > I don't add extra 5-bytes anymore, which you can see in the 3rd patch.
> > >
> > > The thing is that we can't add extra 5-bytes if CFI is enabled. Without
> > > CFI, we can make the padding space any value, such as 5-bytes, and
> > > the layout will be like this:
> > >
> > > __align:
> > >   nop
> > >   nop
> > >   nop
> > >   nop
> > >   nop
> > > foo: -- __align +5
> > >
> > > However, the CFI will always make the cfi insn 16-bytes aligned. When
> > > we set the FUNCTION_PADDING_BYTES to (11 + 5), the layout will be
> > > like this:
> > >
> > > __cfi_foo:
> > >   nop (11)
> > >   mov $0x12345678, %reg
> > >   nop (16)
> > > foo:
> > >
> > > and the padding space is 32-bytes actually. So, we can just select
> > > FUNCTION_ALIGNMENT_32B instead, which makes the padding
> > > space 32-bytes too, and have the following layout:
> > >
> > > __cfi_foo:
> > >   mov $0x12345678, %reg
> > >   nop (27)
> > > foo:
> >
> > *blink*, wtf is clang smoking.
> >
> > I mean, you're right, this is what it is doing, but that is somewhat
> > unexpected. Let me go look at clang source, this is insane.
>
> Bah, this is because assemblers are stupid :/
>
> There is no way to tell them to have foo aligned such that there are at
> least N bytes free before it.
>
> So what kCFI ends up having to do is align the __cfi symbol to the
> function alignment, and then stuff enough nops in to make the real
> symbol meet alignment.
>
> And the end result is utter insanity.
>
> I mean, look at this:
>
>       50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
>       56:       66 2e 0f 1f 84 00 00 00 00 00   cs nopw 0x0(%rax,%rax,1)
>
> 0000000000000060 <__cfi___probestub_initcall_level>:
>       60:       90                      nop
>       61:       90                      nop
>       62:       90                      nop
>       63:       90                      nop
>       64:       90                      nop
>       65:       90                      nop
>       66:       90                      nop
>       67:       90                      nop
>       68:       90                      nop
>       69:       90                      nop
>       6a:       90                      nop
>       6b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax
>
> 0000000000000070 <__probestub_initcall_level>:
>       70:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4
>
>
> That's 21 bytes wasted, for no reason other than that asm doesn't have a
> directive to say: get me a place that is M before N alignment.
>
> Because ideally the whole above thing would look like:
>
>       50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
>       56:       66 2e 0f 1f 84          cs nopw (%rax,%rax,1)
>
> 000000000000005b <__cfi___probestub_initcall_level>:
>       5b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax
>
> 0000000000000060 <__probestub_initcall_level>:
>       60:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4

Hi, peter. Thank you for the testing, which is quite helpful
to understand the whole thing.

I was surprised at this too. Without CALL_PADDING, the cfi is
nop(11) + mov; with CALL_PADDING, the cfi is mov + nop(11),
which is weird, as it seems that we can select CALL_PADDING if
CFI_CLANG to make things consistent. And I  thought that it is
designed to be this for some reasons :/

Hmm......so what should we do now? Accept and bear it,
or do something different?

I'm good at clang, so the solution that I can think of is how to
bear it :/

According to my testing, the text size will increase:

~2.2% if we make FUNCTION_PADDING_BYTES 27 and select
FUNCTION_ALIGNMENT_16B.

~3.5% if we make FUNCTION_PADDING_BYTES 27 and select
FUNCTION_ALIGNMENT_32B.

We don't have to select FUNCTION_ALIGNMENT_32B, so the
worst case is to increase ~2.2%.

What do you think?

Thanks!
Menglong Dong

>
>
>


From linus.walleij at linaro.org  Mon Mar  3 23:51:32 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 4 Mar 2025 08:51:32 +0100
Subject: [PATCH 0/7] rockchip: Add support for leds and user button on
 Radxa E20C
In-Reply-To: <20250228064024.3200000-1-jonas@kwiboo.se>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
Message-ID: <CACRpkdaELuU6XDKacOLsWAF8ncbudJ9Tp0jykAyf-NXRLjoSdw@mail.gmail.com>

Hi Jonas,

On Fri, Feb 28, 2025 at 7:40?AM Jonas Karlman <jonas at kwiboo.se> wrote:

>   dt-bindings: pinctrl: Add pinctrl support for RK3528
>   pinctrl: rockchip: Add support for RK3528

These two patches applied to the pinctrl tree.

Please funnel the rest through the SoC tree, it seems
it should all be able to go in orthogonally.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon Mar  3 23:53:03 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 4 Mar 2025 08:53:03 +0100
Subject: [RFC/RFT PATCH] pinctrl: bcm2835: don't -EINVAL on alternate
 funcs from get_direction()
In-Reply-To: <20250219102750.38519-1-brgl@bgdev.pl>
References: <20250219102750.38519-1-brgl@bgdev.pl>
Message-ID: <CACRpkdYeBM6V+61-cbX1g_wLAVHvQQrtPb=5qjTdUw--+J+E4g@mail.gmail.com>

On Wed, Feb 19, 2025 at 11:27?AM Bartosz Golaszewski <brgl at bgdev.pl> wrote:

> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
>
> Since commit 9d846b1aebbe ("gpiolib: check the return value of
> gpio_chip::get_direction()") we check the return value of the
> get_direction() callback as per its API contract. This driver returns
> -EINVAL if the pin in question is set to one of the alternative
> (non-GPIO) functions. This isn't really an error that should be
> communicated to GPIOLIB so default to returning the "safe" value of
> INPUT in this case. The GPIO subsystem does not have the notion of
> "unknown" direction.
>
> Fixes: 9d846b1aebbe ("gpiolib: check the return value of gpio_chip::get_direction()")
> Reported-by: Mark Brown <broonie at kernel.org>
> Closes: https://lore.kernel.org/all/Z7VFB1nST6lbmBIo at finisterre.sirena.org.uk/
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Patch applied!

Yours,
Linus Walleij


From wei.fang at nxp.com  Mon Mar  3 23:21:48 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:48 +0800
Subject: [PATCH v3 net-next 00/13] Add more feautues for ENETC v4 - round 2
Message-ID: <20250304072201.1332603-1-wei.fang@nxp.com>

This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.fang at nxp.com/
v2 changes
1. Change NTMP_FILL_CRD() and NTMP_FILL_CRD_EID to functions
2. Fix the compile warning in enetc4_pf.c
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.fang at nxp.com/
v3 changes
1. Rename ntmp_formats.h to ntmp_private.h, becuase in addition to
   defining some table formats, some macros and function declarations
   will be added to this header file in the future
2. Add struct ntmp_dma_buf, so refactor ntmp_alloc_data_mem() and
   ntmp_free_data_mem() accordingly
3. Add the setting for cache attributes of command BD Ring in
   enetc4_setup_cbdr()
4. Remove __free() and scoped_guard() from patch "net: enetc: add MAC
   filter for i.MX95 ENETC PF", as these cleanup APIs are discouraged
   within networking drivers.
5. Remove patch "net: enetc: make enetc_set_rxfh() and enetc_get_rxfh()
   reusable" in v2, and add enetc_set_rss_key() and enetc_get_rss_key()
   instead of adding .set_rss_key() and .get_rss_key() to enetc_pf_ops
6. Separate patch " net: enetc: check if the RSS hfunc is toeplitz" from
   patch "net: enetc: add RSS support for i.MX95 ENETC PF"
---

Wei Fang (13):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filterng interfaces to enetc-core
  net: enetc: add MAC filter for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: check if the RSS hfunc is toeplitz
  net: enetc: enable RSS feature by default
  net: enetc: move generic VLAN filter interfaces to enetc-core
  net: enetc: move generic VLAN hash filter functions to
    enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF
  MAINTAINERS: add new file ntmp.h to ENETC driver

 MAINTAINERS                                   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  | 103 +++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  59 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 529 +++++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  69 ++-
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  76 ++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 124 +---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  30 +-
 .../freescale/enetc/enetc_pf_common.c         |  46 +-
 .../freescale/enetc/enetc_pf_common.h         |   2 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  19 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 458 +++++++++++++++
 .../ethernet/freescale/enetc/ntmp_private.h   |  67 +++
 include/linux/fsl/ntmp.h                      | 178 ++++++
 20 files changed, 1716 insertions(+), 191 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:49 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:49 +0800
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib driver to support NTMP
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-2-wei.fang@nxp.com>

Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 458 ++++++++++++++++++
 .../ethernet/freescale/enetc/ntmp_private.h   |  67 +++
 include/linux/fsl/ntmp.h                      | 178 +++++++
 5 files changed, 717 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..94db8e8d0eb3 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,16 @@ config NXP_ENETC_PF_COMMON
 
 	  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+	tristate "NETC Library"
+	help
+	  This module provides common functionalities for both ENETC and NETC
+	  Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+	  flower and debugfs interfaces and so on.
+
+	  If compiled as module (M), the module name is nxp-netc-lib.
+
+
 config FSL_ENETC
 	tristate "ENETC PF driver"
 	depends on PCI_MSI
@@ -40,6 +50,7 @@ config NXP_ENETC4
 	select FSL_ENETC_CORE
 	select FSL_ENETC_MDIO
 	select NXP_ENETC_PF_COMMON
+	select NXP_NETC_LIB
 	select PHYLINK
 	select DIMLIB
 	help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index 000000000000..df10f2f310c1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fsl/netc_global.h>
+#include <linux/iopoll.h>
+
+#include "ntmp_private.h"
+
+#define NETC_CBDR_TIMEOUT		1000 /* us */
+#define NETC_CBDR_MR_EN			BIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN		128
+#define NTMP_DATA_ADDR_ALIGN		32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID			1
+#define NTMP_RSST_ID			3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU		BIT(0)
+#define NTMP_GEN_UA_STSEU		BIT(1)
+
+#define NTMP_ENTRY_ID_SIZE		4
+#define RSST_ENTRY_NUM			64
+#define RSST_STSE_DATA_SIZE(n)		((n) * 8)
+#define RSST_CFGE_DATA_SIZE(n)		(n)
+
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+		    struct netc_cbdr_regs *regs,
+		    struct netc_cbdr *cbdr)
+{
+	size_t size;
+
+	size = cbd_num * sizeof(union netc_cbd) + NTMP_BASE_ADDR_ALIGN;
+	cbdr->addr_base = dma_alloc_coherent(dev, size, &cbdr->dma_base,
+					     GFP_KERNEL);
+	if (!cbdr->addr_base)
+		return -ENOMEM;
+
+	cbdr->dma_size = size;
+	cbdr->bd_num = cbd_num;
+	cbdr->regs = *regs;
+
+	/* The base address of the Control BD Ring must be 128 bytes aligned */
+	cbdr->dma_base_align =  ALIGN(cbdr->dma_base,  NTMP_BASE_ADDR_ALIGN);
+	cbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,
+					  NTMP_BASE_ADDR_ALIGN);
+
+	cbdr->next_to_clean = 0;
+	cbdr->next_to_use = 0;
+	spin_lock_init(&cbdr->ring_lock);
+
+	/* Step 1: Configure the base address of the Control BD Ring */
+	netc_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
+	netc_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
+
+	/* Step 2: Configure the producer index register */
+	netc_write(cbdr->regs.pir, cbdr->next_to_clean);
+
+	/* Step 3: Configure the consumer index register */
+	netc_write(cbdr->regs.cir, cbdr->next_to_use);
+
+	/* Step4: Configure the number of BDs of the Control BD Ring */
+	netc_write(cbdr->regs.lenr, cbdr->bd_num);
+
+	/* Step 5: Enable the Control BD Ring */
+	netc_write(cbdr->regs.mr, NETC_CBDR_MR_EN);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(netc_setup_cbdr);
+
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr)
+{
+	/* Disable the Control BD Ring */
+	netc_write(cbdr->regs.mr, 0);
+	dma_free_coherent(dev, cbdr->dma_size, cbdr->addr_base,
+			  cbdr->dma_base);
+	memset(cbdr, 0, sizeof(*cbdr));
+}
+EXPORT_SYMBOL_GPL(netc_teardown_cbdr);
+
+static int netc_get_free_cbd_num(struct netc_cbdr *cbdr)
+{
+	return (cbdr->next_to_clean - cbdr->next_to_use - 1 +
+		cbdr->bd_num) % cbdr->bd_num;
+}
+
+static union netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
+{
+	return &((union netc_cbd *)(cbdr->addr_base_align))[index];
+}
+
+static void netc_clean_cbdr(struct netc_cbdr *cbdr)
+{
+	union netc_cbd *cbd;
+	int i;
+
+	i = cbdr->next_to_clean;
+	while (netc_read(cbdr->regs.cir) != i) {
+		cbd = netc_get_cbd(cbdr, i);
+		memset(cbd, 0, sizeof(*cbd));
+		i = (i + 1) % cbdr->bd_num;
+	}
+
+	cbdr->next_to_clean = i;
+}
+
+static struct netc_cbdr *netc_select_cbdr(struct netc_cbdrs *cbdrs)
+{
+	int i;
+
+	for (i = 0; i < cbdrs->cbdr_num; i++) {
+		if (spin_is_locked(&cbdrs->ring[i].ring_lock))
+			continue;
+
+		return &cbdrs->ring[i];
+	}
+
+	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];
+}
+
+static int netc_xmit_ntmp_cmd(struct netc_cbdrs *cbdrs, union netc_cbd *cbd)
+{
+	union netc_cbd *cur_cbd;
+	struct netc_cbdr *cbdr;
+	int i, err;
+	u16 status;
+	u32 val;
+
+	if (cbdrs->cbdr_num == 1)
+		cbdr = &cbdrs->ring[0];
+	else
+		cbdr = netc_select_cbdr(cbdrs);
+
+	spin_lock_bh(&cbdr->ring_lock);
+
+	if (unlikely(!netc_get_free_cbd_num(cbdr)))
+		netc_clean_cbdr(cbdr);
+
+	i = cbdr->next_to_use;
+	cur_cbd = netc_get_cbd(cbdr, i);
+	*cur_cbd = *cbd;
+
+	/* Update producer index of both software and hardware */
+	i = (i + 1) % cbdr->bd_num;
+	cbdr->next_to_use = i;
+	dma_wmb();
+	netc_write(cbdr->regs.pir, i);
+
+	err = read_poll_timeout_atomic(netc_read, val, val == i,
+				       10, NETC_CBDR_TIMEOUT, true,
+				       cbdr->regs.cir);
+	if (unlikely(err))
+		goto cbdr_unlock;
+
+	dma_rmb();
+	/* Get the writeback command BD, because the caller may need
+	 * to check some other fields of the response header.
+	 */
+	*cbd = *cur_cbd;
+
+	/* Check the writeback error status */
+	status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
+	if (unlikely(status)) {
+		err = -EIO;
+		dev_err(cbdrs->dma_dev, "Command BD error: 0x%04x\n", status);
+	}
+
+	netc_clean_cbdr(cbdr);
+	dma_wmb();
+
+cbdr_unlock:
+	spin_unlock_bh(&cbdr->ring_lock);
+
+	return err;
+}
+
+static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
+{
+	void *buf;
+
+	buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+				 &data->dma, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	data->buf = buf;
+	*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
+
+	return 0;
+}
+
+static void ntmp_free_data_mem(struct ntmp_dma_buf *data)
+{
+	dma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+			  data->buf, data->dma);
+}
+
+static void ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
+				    int len, int table_id, int cmd,
+				    int access_method)
+{
+	dma_addr_t dma_align;
+
+	memset(cbd, 0, sizeof(*cbd));
+	dma_align = ALIGN(dma, NTMP_DATA_ADDR_ALIGN);
+	cbd->req_hdr.addr = cpu_to_le64(dma_align);
+	cbd->req_hdr.len = cpu_to_le32(len);
+	cbd->req_hdr.cmd = cmd;
+	cbd->req_hdr.access_method = FIELD_PREP(NTMP_ACCESS_METHOD,
+						access_method);
+	cbd->req_hdr.table_id = table_id;
+	cbd->req_hdr.ver_cci_rr = FIELD_PREP(NTMP_HDR_VERSION,
+					     NTMP_HDR_VER2);
+	/* For NTMP version 2.0 or later version */
+	cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
+}
+
+static void ntmp_fill_crd(struct common_req_data *crd,
+			  u8 tblv, u8 qa, u16 ua)
+{
+	crd->update_act = cpu_to_le16(ua);
+	crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
+}
+
+static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
+			      u8 qa, u16 ua, u32 entry_id)
+{
+	ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
+	rbe->entry_id = cpu_to_le32(entry_id);
+}
+
+static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
+				   u8 tbl_ver, u32 entry_id, u32 req_len,
+				   u32 resp_len)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct ntmp_req_by_eid *req;
+	union netc_cbd cbd;
+	u32 len;
+	int err;
+
+	if (entry_id == NTMP_NULL_ENTRY_ID)
+		return 0;
+
+	/* If the req_len is 0, indicates the requested length is the
+	 * standard length.
+	 */
+	if (!req_len)
+		req_len = sizeof(*req);
+
+	data.size = req_len >= resp_len ? req_len : resp_len;
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
+	len = NTMP_LEN(req_len, resp_len);
+	ntmp_fill_request_headr(&cbd, data.dma, len, tbl_id,
+				NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err)
+		dev_err(cbdrs->dma_dev, "Delete table (id: %d) entry failed: %d",
+			tbl_id, err);
+
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+
+static int ntmp_query_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
+				  u32 len, struct ntmp_req_by_eid *req,
+				  dma_addr_t dma, bool compare_eid)
+{
+	struct device *dev = cbdrs->dma_dev;
+	struct common_resp_query *resp;
+	int cmd = NTMP_CMD_QUERY;
+	union netc_cbd cbd;
+	u32 entry_id;
+	int err;
+
+	entry_id = le32_to_cpu(req->entry_id);
+	if (le16_to_cpu(req->crd.update_act))
+		cmd = NTMP_CMD_QU;
+
+	/* Request header */
+	ntmp_fill_request_headr(&cbd, dma, len, tbl_id,
+				cmd, NTMP_AM_ENTRY_ID);
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err) {
+		dev_err(dev, "Query table (id: %d) entry failed: %d\n",
+			tbl_id, err);
+		return err;
+	}
+
+	/* For a few tables, the first field of its response data is not
+	 * entry_id, so directly return success.
+	 */
+	if (!compare_eid)
+		return 0;
+
+	resp = (struct common_resp_query *)req;
+	if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
+		dev_err(dev, "Table (id: %d) query EID:0x%0x, response EID:0x%x\n",
+			tbl_id, entry_id, le32_to_cpu(resp->entry_id));
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			struct maft_entry_data *maft)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct maft_req_add *req;
+	union netc_cbd cbd;
+	int err;
+
+	data.size = sizeof(*req);
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	/* Set mac address filter table request data buffer */
+	ntmp_fill_crd_eid(&req->rbe, cbdrs->tbl.maft_ver, 0, 0, entry_id);
+	req->keye = maft->keye;
+	req->cfge = maft->cfge;
+
+	ntmp_fill_request_headr(&cbd, data.dma, NTMP_LEN(data.size, 0),
+				NTMP_MAFT_ID, NTMP_CMD_ADD,
+				NTMP_AM_ENTRY_ID);
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err)
+		dev_err(cbdrs->dma_dev, "Add MAFT entry failed (%d)", err);
+
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
+
+int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			  struct maft_entry_data *maft)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct maft_resp_query *resp;
+	struct ntmp_req_by_eid *req;
+	u32 req_len = sizeof(*req);
+	int err;
+
+	if (entry_id == NTMP_NULL_ENTRY_ID)
+		return -EINVAL;
+
+	data.size = sizeof(*resp);
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	ntmp_fill_crd_eid(req, cbdrs->tbl.maft_ver, 0, 0, entry_id);
+	err = ntmp_query_entry_by_id(cbdrs, NTMP_MAFT_ID,
+				     NTMP_LEN(req_len, data.size),
+				     req, data.dma, true);
+	if (err)
+		goto end;
+
+	resp = (struct maft_resp_query *)req;
+	maft->keye = resp->keye;
+	maft->cfge = resp->cfge;
+
+end:
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
+
+int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
+{
+	return ntmp_delete_entry_by_id(cbdrs, NTMP_MAFT_ID,
+				       cbdrs->tbl.maft_ver,
+				       entry_id, 0, 0);
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);
+
+int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs, u32 *table,
+				    int count, bool query)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct rsst_req_update *requ;
+	struct ntmp_req_by_eid *req;
+	union netc_cbd cbd;
+	int err, i;
+	u32 len;
+
+	if (count != RSST_ENTRY_NUM)
+		/* HW only takes in a full 64 entry table */
+		return -EINVAL;
+
+	if (query)
+		data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
+			    RSST_CFGE_DATA_SIZE(count);
+	else
+		data.size = struct_size(requ, groups, count);
+
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	/* Set the request data buffer */
+	if (query) {
+		ntmp_fill_crd_eid(req, cbdrs->tbl.rsst_ver, 0, 0, 0);
+		len = NTMP_LEN(sizeof(*req), data.size);
+		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
+					NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
+	} else {
+		requ = (struct rsst_req_update *)req;
+		ntmp_fill_crd_eid(&requ->rbe, cbdrs->tbl.rsst_ver, 0,
+				  NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
+		for (i = 0; i < count; i++)
+			requ->groups[i] = (u8)(table[i]);
+
+		len = NTMP_LEN(data.size, 0);
+		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
+					NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
+	}
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err) {
+		dev_err(cbdrs->dma_dev, "%s RSS table entry failed (%d)",
+			query ? "Query" : "Update", err);
+		goto end;
+	}
+
+	if (query) {
+		u8 *group = (u8 *)req;
+
+		group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
+		for (i = 0; i < count; i++)
+			table[i] = group[i];
+	}
+
+end:
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_rsst_query_or_update_entry);
+
+MODULE_DESCRIPTION("NXP NETC Library");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
new file mode 100644
index 000000000000..6f2ffbae27d6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * NTMP table request and response data buffer formats
+ * Copyright 2025 NXP
+ */
+
+#ifndef __NTMP_PRIVATE_H
+#define __NTMP_PRIVATE_H
+
+#include <linux/fsl/ntmp.h>
+
+struct ntmp_dma_buf {
+	struct device *dev;
+	size_t size;
+	void *buf;
+	dma_addr_t dma;
+};
+
+#pragma pack(1)
+
+struct common_req_data {
+	__le16 update_act;
+	u8 dbg_opt;
+	u8 tblv_qact;
+#define NTMP_QUERY_ACT		GENMASK(3, 0)
+#define NTMP_TBL_VER		GENMASK(7, 0)
+#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
+				 ((a) & NTMP_QUERY_ACT))
+};
+
+struct common_resp_query {
+	__le32 entry_id;
+};
+
+struct common_resp_nq {
+	__le32 status;
+};
+
+/* Generic structure for request data by entry ID  */
+struct ntmp_req_by_eid {
+	struct common_req_data crd;
+	__le32 entry_id;
+};
+
+/* MAC Address Filter Table Request Data Buffer Format of Add action */
+struct maft_req_add {
+	struct ntmp_req_by_eid rbe;
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+/* MAC Address Filter Table Response Data Buffer Format of Query action */
+struct maft_resp_query {
+	__le32 entry_id;
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+/* RSS Table Request Data Buffer Format of Update action */
+struct rsst_req_update {
+	struct ntmp_req_by_eid rbe;
+	u8 groups[];
+};
+
+#pragma pack()
+
+#endif
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
new file mode 100644
index 000000000000..7259a9277550
--- /dev/null
+++ b/include/linux/fsl/ntmp.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+#ifndef __NETC_NTMP_H
+#define __NETC_NTMP_H
+
+#include <linux/bitops.h>
+#include <linux/if_ether.h>
+
+#define NTMP_NULL_ENTRY_ID		0xffffffffU
+#define NETC_CBDR_BD_NUM		256
+
+#pragma pack(1)
+
+union netc_cbd {
+	struct {
+		__le64 addr;
+		__le32 len;
+#define NTMP_RESP_LEN		GENMASK(19, 0)
+#define NTMP_REQ_LEN		GENMASK(31, 20)
+#define NTMP_LEN(req, resp)	(FIELD_PREP(NTMP_REQ_LEN, (req)) | \
+				((resp) & NTMP_RESP_LEN))
+		u8 cmd;
+#define NTMP_CMD_DELETE		BIT(0)
+#define NTMP_CMD_UPDATE		BIT(1)
+#define NTMP_CMD_QUERY		BIT(2)
+#define NTMP_CMD_ADD		BIT(3)
+#define NTMP_CMD_QD		(NTMP_CMD_QUERY | NTMP_CMD_DELETE)
+#define NTMP_CMD_QU		(NTMP_CMD_QUERY | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AU		(NTMP_CMD_ADD | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AQ		(NTMP_CMD_ADD | NTMP_CMD_QUERY)
+#define NTMP_CMD_AQU		(NTMP_CMD_AQ | NTMP_CMD_UPDATE)
+		u8 access_method;
+#define NTMP_ACCESS_METHOD	GENMASK(7, 4)
+#define NTMP_AM_ENTRY_ID	0
+#define NTMP_AM_EXACT_KEY	1
+#define NTMP_AM_SEARCH		2
+#define NTMP_AM_TERNARY_KEY	3
+		u8 table_id;
+		u8 ver_cci_rr;
+#define NTMP_HDR_VERSION	GENMASK(5, 0)
+#define NTMP_HDR_VER2		2
+#define NTMP_CCI		BIT(6)
+#define NTMP_RR			BIT(7)
+		__le32 resv[3];
+		__le32 npf;
+#define NTMP_NPF		BIT(15)
+	} req_hdr;	/* NTMP Request Message Header Format */
+
+	struct {
+		__le32 resv0[3];
+		__le16 num_matched;
+		__le16 error_rr;
+#define NTMP_RESP_ERROR		GENMASK(11, 0)
+#define NTMP_RESP_RR		BIT(15)
+		__le32 resv1[4];
+	} resp_hdr; /* NTMP Response Message Header Format */
+};
+
+struct maft_keye_data {
+	u8 mac_addr[ETH_ALEN];
+	__le16 resv;
+};
+
+struct maft_cfge_data {
+	__le16 si_bitmap;
+	__le16 resv;
+};
+
+#pragma pack()
+
+struct netc_cbdr_regs {
+	void __iomem *pir;
+	void __iomem *cir;
+	void __iomem *mr;
+
+	void __iomem *bar0;
+	void __iomem *bar1;
+	void __iomem *lenr;
+};
+
+struct netc_tbl_vers {
+	u8 maft_ver;
+	u8 rsst_ver;
+};
+
+struct netc_cbdr {
+	struct netc_cbdr_regs regs;
+
+	int bd_num;
+	int next_to_use;
+	int next_to_clean;
+
+	int dma_size;
+	void *addr_base;
+	void *addr_base_align;
+	dma_addr_t dma_base;
+	dma_addr_t dma_base_align;
+
+	spinlock_t ring_lock; /* Avoid race condition */
+};
+
+struct netc_cbdrs {
+	int cbdr_num;	/* number of control BD ring */
+	int cbdr_size;	/* number of BDs per control BD ring */
+	struct device *dma_dev;
+	struct netc_cbdr *ring;
+	struct netc_tbl_vers tbl;
+};
+
+enum netc_dev_type {
+	NETC_DEV_ENETC,
+	NETC_DEV_SWITCH
+};
+
+struct ntmp_priv {
+	enum netc_dev_type dev_type;
+	struct netc_cbdrs cbdrs;
+};
+
+struct maft_entry_data {
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+#if IS_ENABLED(CONFIG_NXP_NETC_LIB)
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+		    struct netc_cbdr_regs *regs,
+		    struct netc_cbdr *cbdr);
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr);
+
+/* NTMP APIs */
+int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			struct maft_entry_data *maft);
+int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			  struct maft_entry_data *maft);
+int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id);
+int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs,
+				    u32 *table, int count, bool query);
+#else
+static inline int netc_setup_cbdr(struct device *dev, int cbd_num,
+				  struct netc_cbdr_regs *regs,
+				  struct netc_cbdr *cbdr)
+{
+	return 0;
+}
+
+static inline void netc_teardown_cbdr(struct device *dev,
+				      struct netc_cbdr *cbdr)
+{
+}
+
+static inline int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+				      struct maft_entry_data *maft)
+{
+	return 0;
+}
+
+static inline int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+					struct maft_entry_data *maft)
+{
+	return 0;
+}
+
+static inline int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
+{
+	return 0;
+}
+
+static inline int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs,
+						  u32 *table, int count,
+						  bool query)
+{
+	return 0;
+}
+
+#endif
+
+#endif
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:50 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:50 +0800
Subject: [PATCH v3 net-next 02/13] net: enetc: add command BD ring support for i.MX95 ENETC
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-3-wei.fang@nxp.com>

The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. In order to
ensure driver compatibility, struct enetc_si_ops is introduced. This
structure defines some hooks shared by VSI and PSI. Different hardware
driver will register different hooks, For example, setup_cbdr() is used
to initialize the command BD ring, and teardown_cbdr() is used to free
the command BD ring.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  | 27 +++++++--
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 +++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 55 +++++++++++++++++--
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
 .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
 5 files changed, 136 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..4ff0957e69be 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/fsl/ntmp.h>
 #include <linux/if_vlan.h>
 #include <linux/phylink.h>
 #include <linux/dim.h>
@@ -266,6 +267,19 @@ struct enetc_platform_info {
 	const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+	int (*setup_cbdr)(struct enetc_si *si);
+	void (*teardown_cbdr)(struct enetc_si *si);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
 	struct pci_dev *pdev;
@@ -274,7 +288,10 @@ struct enetc_si {
 
 	struct net_device *ndev; /* back ref. */
 
-	struct enetc_cbdr cbd_ring;
+	union {
+		struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+		struct ntmp_priv ntmp; /* ENETC 4.1 and later */
+	};
 
 	int num_rx_rings; /* how many rings are available in the SI */
 	int num_tx_rings;
@@ -284,6 +301,7 @@ struct enetc_si {
 	u16 revision;
 	int hw_features;
 	const struct enetc_drvdata *drvdata;
+	const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN	32
@@ -490,9 +508,10 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
 void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
 
 /* control buffer descriptor ring (CBDR) */
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-		     struct enetc_cbdr *cbdr);
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc_setup_cbdr(struct enetc_si *si);
+void enetc_teardown_cbdr(struct enetc_si *si);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 			    char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..63001379f0a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,23 @@ static void enetc4_configure_port(struct enetc_pf *pf)
 	enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_priv(struct enetc_si *si)
+{
+	struct ntmp_priv *ntmp = &si->ntmp;
+
+	ntmp->dev_type = NETC_DEV_ENETC;
+
+	/* For ENETC 4.1, all table versions are 0 */
+	memset(&ntmp->cbdrs.tbl, 0, sizeof(ntmp->cbdrs.tbl));
+
+	return si->ops->setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_priv(struct enetc_si *si)
+{
+	si->ops->teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
 	struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +289,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
 		return err;
 	}
 
+	err = enetc4_init_ntmp_priv(pf->si);
+	if (err) {
+		dev_err(dev, "Failed to init CBDR\n");
+		return err;
+	}
+
 	enetc4_configure_port(pf);
 
 	return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+	enetc4_free_ntmp_priv(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
@@ -688,6 +716,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
 	free_netdev(ndev);
 }
 
+static const struct enetc_si_ops enetc4_psi_ops = {
+	.setup_cbdr = enetc4_setup_cbdr,
+	.teardown_cbdr = enetc4_teardown_cbdr,
+};
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
@@ -712,6 +745,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 				     "Couldn't map PF only space\n");
 
 	si->revision = enetc_get_ip_revision(&si->hw);
+	si->ops = &enetc4_psi_ops;
 	err = enetc_get_driver_data(si);
 	if (err)
 		return dev_err_probe(dev, err,
@@ -728,14 +762,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
 	enetc_get_si_caps(si);
 
-	return enetc4_pf_netdev_create(si);
+	err = enetc4_pf_netdev_create(si);
+	if (err)
+		goto err_netdev_create;
+
+	return 0;
+
+err_netdev_create:
+	enetc4_pf_free(pf);
+
+	return err;
 }
 
 static void enetc4_pf_remove(struct pci_dev *pdev)
 {
 	struct enetc_si *si = pci_get_drvdata(pdev);
+	struct enetc_pf *pf = enetc_si_priv(si);
 
 	enetc4_pf_netdev_destroy(si);
+	enetc4_pf_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..4e5125331d7b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -3,10 +3,12 @@
 
 #include "enetc.h"
 
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-		     struct enetc_cbdr *cbdr)
+int enetc_setup_cbdr(struct enetc_si *si)
 {
-	int size = bd_count * sizeof(struct enetc_cbd);
+	int size = ENETC_CBDR_DEFAULT_SIZE * sizeof(struct enetc_cbd);
+	struct enetc_cbdr *cbdr = &si->cbd_ring;
+	struct device *dev = &si->pdev->dev;
+	struct enetc_hw *hw = &si->hw;
 
 	cbdr->bd_base = dma_alloc_coherent(dev, size, &cbdr->bd_dma_base,
 					   GFP_KERNEL);
@@ -23,7 +25,7 @@ int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 	cbdr->next_to_clean = 0;
 	cbdr->next_to_use = 0;
 	cbdr->dma_dev = dev;
-	cbdr->bd_count = bd_count;
+	cbdr->bd_count = ENETC_CBDR_DEFAULT_SIZE;
 
 	cbdr->pir = hw->reg + ENETC_SICBDRPIR;
 	cbdr->cir = hw->reg + ENETC_SICBDRCIR;
@@ -46,13 +48,45 @@ int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 }
 EXPORT_SYMBOL_GPL(enetc_setup_cbdr);
 
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
+int enetc4_setup_cbdr(struct enetc_si *si)
 {
-	int size = cbdr->bd_count * sizeof(struct enetc_cbd);
+	struct netc_cbdrs *cbdrs = &si->ntmp.cbdrs;
+	struct device *dev = &si->pdev->dev;
+	struct enetc_hw *hw = &si->hw;
+	struct netc_cbdr_regs regs;
+
+	cbdrs->cbdr_num = 1;
+	cbdrs->cbdr_size = NETC_CBDR_BD_NUM;
+	cbdrs->dma_dev = dev;
+	cbdrs->ring = devm_kcalloc(dev, cbdrs->cbdr_num,
+				   sizeof(struct netc_cbdr), GFP_KERNEL);
+	if (!cbdrs->ring)
+		return -ENOMEM;
+
+	/* set CBDR cache attributes */
+	enetc_wr(hw, ENETC_SICAR2,
+		 ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+
+	regs.pir = hw->reg + ENETC_SICBDRPIR;
+	regs.cir = hw->reg + ENETC_SICBDRCIR;
+	regs.mr = hw->reg + ENETC_SICBDRMR;
+	regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
+	regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
+	regs.lenr = hw->reg + ENETC_SICBDRLENR;
+
+	return netc_setup_cbdr(dev, cbdrs->cbdr_size, &regs, cbdrs->ring);
+}
+EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
+
+void enetc_teardown_cbdr(struct enetc_si *si)
+{
+	struct enetc_cbdr *cbdr = &si->cbd_ring;
+	int size;
 
 	/* disable ring */
 	enetc_wr_reg(cbdr->mr, 0);
 
+	size = cbdr->bd_count * sizeof(struct enetc_cbd);
 	dma_free_coherent(cbdr->dma_dev, size, cbdr->bd_base,
 			  cbdr->bd_dma_base);
 	cbdr->bd_base = NULL;
@@ -60,6 +94,15 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
 }
 EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
 
+void enetc4_teardown_cbdr(struct enetc_si *si)
+{
+	struct netc_cbdrs *cbdrs = &si->ntmp.cbdrs;
+
+	netc_teardown_cbdr(cbdrs->dma_dev, cbdrs->ring);
+	cbdrs->dma_dev = NULL;
+}
+EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
+
 static void enetc_clean_cbdr(struct enetc_cbdr *ring)
 {
 	struct enetc_cbd *dest_cbd;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..a214749a4af6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -939,6 +939,11 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
 	return enetc_ierb_register_pf(ierb_pdev, pdev);
 }
 
+static const struct enetc_si_ops enetc_psi_ops = {
+	.setup_cbdr = enetc_setup_cbdr,
+	.teardown_cbdr = enetc_teardown_cbdr,
+};
+
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 {
 	struct enetc_si *si;
@@ -957,6 +962,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 		goto out_pci_remove;
 	}
 
+	si->ops = &enetc_psi_ops;
 	si->revision = enetc_get_ip_revision(&si->hw);
 	err = enetc_get_driver_data(si);
 	if (err) {
@@ -964,8 +970,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 		goto out_pci_remove;
 	}
 
-	err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
-			       &si->cbd_ring);
+	err = si->ops->setup_cbdr(si);
 	if (err)
 		goto out_pci_remove;
 
@@ -984,7 +989,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 	return si;
 
 out_teardown_cbdr:
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 out_pci_remove:
 	enetc_pci_remove(pdev);
 out:
@@ -995,7 +1000,7 @@ static void enetc_psi_destroy(struct pci_dev *pdev)
 {
 	struct enetc_si *si = pci_get_drvdata(pdev);
 
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 	enetc_pci_remove(pdev);
 }
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 3768752b6008..d7d9a720069b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -162,6 +162,11 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	enetc_load_primary_mac_addr(&si->hw, ndev);
 }
 
+static const struct enetc_si_ops enetc_vsi_ops = {
+	.setup_cbdr = enetc_setup_cbdr,
+	.teardown_cbdr = enetc_teardown_cbdr,
+};
+
 static int enetc_vf_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *ent)
 {
@@ -176,6 +181,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 	si = pci_get_drvdata(pdev);
 	si->revision = ENETC_REV_1_0;
+	si->ops = &enetc_vsi_ops;
 	err = enetc_get_driver_data(si);
 	if (err) {
 		dev_err_probe(&pdev->dev, err,
@@ -198,8 +204,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 	enetc_init_si_rings_params(priv);
 
-	err = enetc_setup_cbdr(priv->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
-			       &si->cbd_ring);
+	err = si->ops->setup_cbdr(si);
 	if (err)
 		goto err_setup_cbdr;
 
@@ -235,7 +240,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 err_alloc_msix:
 	enetc_free_si_resources(priv);
 err_alloc_si_res:
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 err_setup_cbdr:
 	si->ndev = NULL;
 	free_netdev(ndev);
@@ -256,7 +261,7 @@ static void enetc_vf_remove(struct pci_dev *pdev)
 	enetc_free_msix(priv);
 
 	enetc_free_si_resources(priv);
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 
 	free_netdev(si->ndev);
 
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:51 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:51 +0800
Subject: [PATCH v3 net-next 03/13] net: enetc: move generic MAC filterng interfaces to enetc-core
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-4-wei.fang@nxp.com>

Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. At the same time, the struct enetc_mac_filter is
moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
MAC address filtering.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 ++++++++++++++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 17 +++++++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 49 +++----------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 14 ------
 4 files changed, 60 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2106861463e4..3832d2cd91ba 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
 	enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+	u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+	u64 mask = 0;
+	int res = 0;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		mask |= BIT_ULL(i * 6);
+
+	for (i = 0; i < 6; i++)
+		res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+	return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+				  const unsigned char *addr)
+{
+	int idx = enetc_mac_addr_hash_idx(addr);
+
+	/* add hash table entry */
+	__set_bit(idx, filter->mac_hash_table);
+	filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+	filter->mac_addr_cnt = 0;
+
+	bitmap_zero(filter->mac_hash_table,
+		    ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
 	int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ff0957e69be..9380d3e8ca01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ	64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+	union {
+		char mac_addr[ETH_ALEN];
+		DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+	};
+	int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
 	union {
 		struct sk_buff *skb;
@@ -302,6 +314,8 @@ struct enetc_si {
 	int hw_features;
 	const struct enetc_drvdata *drvdata;
 	const struct enetc_si_ops *ops;
+
+	struct enetc_mac_filter mac_filter[MADDR_TYPE];
 };
 
 #define ENETC_SI_ALIGN	32
@@ -484,6 +498,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+				  const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index a214749a4af6..cc3e52bd3096 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
 	enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-	u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-	u64 mask = 0;
-	int res = 0;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		mask |= BIT_ULL(i * 6);
-
-	for (i = 0; i < 6; i++)
-		res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-	return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-	filter->mac_addr_cnt = 0;
-
-	bitmap_zero(filter->mac_hash_table,
-		    ENETC_MADDR_HASH_TBL_SZ);
-}
-
 static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 					 const unsigned char *addr)
 {
@@ -104,16 +80,6 @@ static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 	filter->mac_addr_cnt++;
 }
 
-static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
-					 const unsigned char *addr)
-{
-	int idx = enetc_mac_addr_hash_idx(addr);
-
-	/* add hash table entry */
-	__set_bit(idx, filter->mac_hash_table);
-	filter->mac_addr_cnt++;
-}
-
 static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)
 {
 	bool err = si->errata & ENETC_ERR_UCMCSWP;
@@ -145,10 +111,9 @@ static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,
 	}
 }
 
-static void enetc_sync_mac_filters(struct enetc_pf *pf)
+static void enetc_sync_mac_filters(struct enetc_si *si)
 {
-	struct enetc_mac_filter *f = pf->mac_filter;
-	struct enetc_si *si = pf->si;
+	struct enetc_mac_filter *f = si->mac_filter;
 	int i, pos;
 
 	pos = EMETC_MAC_ADDR_FILT_RES;
@@ -192,10 +157,10 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)
 static void enetc_pf_set_rx_mode(struct net_device *ndev)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
-	struct enetc_hw *hw = &priv->si->hw;
 	bool uprom = false, mprom = false;
 	struct enetc_mac_filter *filter;
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	struct netdev_hw_addr *ha;
 	u32 psipmr = 0;
 	bool em;
@@ -214,7 +179,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 	/* first 2 filter entries belong to PF */
 	if (!uprom) {
 		/* Update unicast filters */
-		filter = &pf->mac_filter[UC];
+		filter = &si->mac_filter[UC];
 		enetc_reset_mac_addr_filter(filter);
 
 		em = (netdev_uc_count(ndev) == 1);
@@ -230,7 +195,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 
 	if (!mprom) {
 		/* Update multicast filters */
-		filter = &pf->mac_filter[MC];
+		filter = &si->mac_filter[MC];
 		enetc_reset_mac_addr_filter(filter);
 
 		netdev_for_each_mc_addr(ha, ndev) {
@@ -243,7 +208,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 
 	if (!uprom || !mprom)
 		/* update PF entries */
-		enetc_sync_mac_filters(pf);
+		enetc_sync_mac_filters(si);
 
 	psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) &
 		  ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index a26a12863855..2b9d0f625f01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -6,18 +6,6 @@
 
 #define ENETC_PF_NUM_RINGS	8
 
-enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
-#define ENETC_MAX_NUM_MAC_FLT	((ENETC_MAX_NUM_VFS + 1) * MADDR_TYPE)
-
-#define ENETC_MADDR_HASH_TBL_SZ	64
-struct enetc_mac_filter {
-	union {
-		char mac_addr[ETH_ALEN];
-		DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
-	};
-	int mac_addr_cnt;
-};
-
 #define ENETC_VLAN_HT_SIZE	64
 
 enum enetc_vf_flags {
@@ -52,8 +40,6 @@ struct enetc_pf {
 	int total_vfs; /* max number of VFs, set for PF at probe */
 	struct enetc_vf_state *vf_state;
 
-	struct enetc_mac_filter mac_filter[ENETC_MAX_NUM_MAC_FLT];
-
 	struct enetc_msg_swbd rxmsg[ENETC_MAX_NUM_VFS];
 	struct work_struct msg_task;
 	char msg_int_name[ENETC_INT_NAME_MAX];
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:52 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:52 +0800
Subject: [PATCH v3 net-next 04/13] net: enetc: add MAC filter for i.MX95 ENETC PF
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-5-wei.fang@nxp.com>

The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bits hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 418 +++++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  11 +
 5 files changed, 444 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 9380d3e8ca01..4dba91408e3d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -316,6 +316,8 @@ struct enetc_si {
 	const struct enetc_si_ops *ops;
 
 	struct enetc_mac_filter mac_filter[MADDR_TYPE];
+	struct workqueue_struct *workqueue;
+	struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN	32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a)		((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX		GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)		((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)		((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)		((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)		((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR			0x4004
 #define  PMCAPR_HD			BIT(8)
 #define  PMCAPR_FP			GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 63001379f0a0..305781ccefd0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM	8
 
+#define ENETC_MAC_FILTER_TYPE_UC	BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC	BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL	(ENETC_MAC_FILTER_TYPE_UC | \
+					 ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+	u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
 	struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
 	val = enetc_port_rd(hw, ENETC4_PMCAPR);
 	pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+	val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+	pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,337 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
 	put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
+					 int type, bool en)
+{
+	u32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+
+	if (type == UC) {
+		if (en)
+			val |= PSIPMMR_SI_MAC_UP(si);
+		else
+			val &= ~PSIPMMR_SI_MAC_UP(si);
+	} else { /* Multicast promiscuous mode. */
+		if (en)
+			val |= PSIPMMR_SI_MAC_MP(si);
+		else
+			val &= ~PSIPMMR_SI_MAC_MP(si);
+	}
+
+	enetc_port_wr(hw, ENETC4_PSIPMMR, val);
+}
+
+static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
+					     int type, u64 hash)
+{
+	if (type == UC) {
+		enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
+		enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
+	} else { /* MC */
+		enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
+		enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
+	}
+}
+
+static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
+{
+	struct enetc_mac_list_entry *entry;
+	struct hlist_node *tmp;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+		hlist_del(&entry->node);
+		kfree(entry);
+	}
+
+	pf->num_mfe = 0;
+
+	mutex_unlock(&pf->mac_list_lock);
+}
+
+static bool enetc_mac_filter_type_check(int type, const u8 *addr)
+{
+	if (type == ENETC_MAC_FILTER_TYPE_UC)
+		return !is_multicast_ether_addr(addr);
+	else if (type == ENETC_MAC_FILTER_TYPE_MC)
+		return is_multicast_ether_addr(addr);
+	else
+		return true;
+}
+
+static struct enetc_mac_list_entry *
+enetc_mac_list_lookup_entry(struct enetc_pf *pf, const unsigned char *addr)
+{
+	struct enetc_mac_list_entry *entry;
+
+	hlist_for_each_entry(entry, &pf->mac_list, node)
+		if (ether_addr_equal(entry->mac, addr))
+			return entry;
+
+	return NULL;
+}
+
+static void enetc_mac_list_add_entry(struct enetc_pf *pf,
+				     struct enetc_mac_list_entry *entry)
+{
+	hlist_add_head(&entry->node, &pf->mac_list);
+}
+
+static void enetc_mac_list_del_entry(struct enetc_mac_list_entry *entry)
+{
+	hlist_del(&entry->node);
+	kfree(entry);
+}
+
+static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16 si_bit,
+					       struct enetc_mac_addr *mac,
+					       int mac_cnt)
+{
+	struct enetc_mac_list_entry *entry;
+	int i;
+
+	for (i = 0; i < mac_cnt; i++) {
+		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
+		if (entry) {
+			entry->si_bitmap &= ~si_bit;
+			if (!entry->si_bitmap) {
+				enetc_mac_list_del_entry(entry);
+				pf->num_mfe--;
+			}
+		}
+	}
+}
+
+static bool enetc_mac_list_is_available(struct enetc_pf *pf,
+					struct enetc_mac_addr *mac,
+					int mac_cnt)
+{
+	int max_num_mfe = pf->caps.mac_filter_num;
+	struct enetc_mac_list_entry *entry;
+	int cur_num_mfe = pf->num_mfe;
+	int i, new_mac_cnt = 0;
+
+	if (mac_cnt > max_num_mfe)
+		return false;
+
+	/* Check MAC filter table whether has enough available entries */
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		for (i = 0; i < mac_cnt; i++) {
+			if (ether_addr_equal(entry->mac, mac[i].addr))
+				break;
+		}
+
+		if (i == mac_cnt)
+			new_mac_cnt++;
+
+		if ((cur_num_mfe + new_mac_cnt) > max_num_mfe)
+			return false;
+	}
+
+	return true;
+}
+
+static int enetc4_pf_add_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
+					     struct enetc_mac_addr *mac,
+					     int mac_cnt)
+{
+	struct enetc_mac_list_entry *entry;
+	struct maft_entry_data data = {0};
+	struct enetc_si *si = pf->si;
+	u16 si_bit = BIT(si_id);
+	int i, num_mfe, err = 0;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	if (!enetc_mac_list_is_available(pf, mac, mac_cnt)) {
+		err = -ENOSPC;
+		goto mac_list_unlock;
+	}
+
+	num_mfe = pf->num_mfe;
+	/* Update mac_list */
+	for (i = 0; i < mac_cnt; i++) {
+		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
+		if (!entry) {
+			entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+			if (unlikely(!entry)) {
+				/* Restore MAC list to the state before the update
+				 * if an error occurs.
+				 */
+				enetc_mac_list_del_matched_entries(pf, si_bit,
+								   mac, i + 1);
+				err = -ENOMEM;
+				goto mac_list_unlock;
+			}
+
+			ether_addr_copy(entry->mac, mac[i].addr);
+			entry->si_bitmap = si_bit;
+			enetc_mac_list_add_entry(pf, entry);
+			pf->num_mfe++;
+		} else {
+			entry->si_bitmap |= si_bit;
+		}
+	}
+
+	/* Clear MAC filter table */
+	for (i = 0; i < num_mfe; i++)
+		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
+
+	i = 0;
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
+		ether_addr_copy(data.keye.mac_addr, entry->mac);
+		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
+	}
+
+mac_list_unlock:
+	mutex_unlock(&pf->mac_list_lock);
+
+	return err;
+}
+
+static void enetc4_pf_flush_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
+						int mac_type)
+{
+	struct enetc_mac_list_entry *entry;
+	struct maft_entry_data data = {0};
+	struct enetc_si *si = pf->si;
+	u16 si_bit = BIT(si_id);
+	struct hlist_node *tmp;
+	int i, num_mfe;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	num_mfe = pf->num_mfe;
+	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+		if (enetc_mac_filter_type_check(mac_type, entry->mac) &&
+		    entry->si_bitmap & si_bit) {
+			entry->si_bitmap ^= si_bit;
+			if (!entry->si_bitmap) {
+				enetc_mac_list_del_entry(entry);
+				pf->num_mfe--;
+			}
+		}
+	}
+
+	for (i = 0; i < num_mfe; i++)
+		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
+
+	i = 0;
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
+		ether_addr_copy(data.keye.mac_addr, entry->mac);
+		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
+	}
+
+	mutex_unlock(&pf->mac_list_lock);
+}
+
+static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
+{
+	int max_num_mfe = pf->caps.mac_filter_num;
+	struct net_device *ndev = pf->si->ndev;
+	struct enetc_mac_addr *mac_tbl;
+	struct netdev_hw_addr *ha;
+	u8 si_mac[ETH_ALEN];
+	int mac_cnt = 0;
+	int err;
+
+	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
+	if (!mac_tbl)
+		return -ENOMEM;
+
+	enetc_get_primary_mac_addr(&pf->si->hw, si_mac);
+
+	netif_addr_lock_bh(ndev);
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		netdev_for_each_uc_addr(ha, ndev) {
+			if (!is_valid_ether_addr(ha->addr) ||
+			    ether_addr_equal(ha->addr, si_mac))
+				continue;
+
+			if (mac_cnt >= max_num_mfe)
+				goto err_nospace_out;
+
+			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
+		}
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC) {
+		netdev_for_each_mc_addr(ha, ndev) {
+			if (!is_multicast_ether_addr(ha->addr))
+				continue;
+
+			if (mac_cnt >= max_num_mfe)
+				goto err_nospace_out;
+
+			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
+		}
+	}
+	netif_addr_unlock_bh(ndev);
+
+	err = enetc4_pf_add_si_mac_exact_filter(pf, 0, mac_tbl, mac_cnt);
+	kfree(mac_tbl);
+
+	return err;
+
+err_nospace_out:
+	netif_addr_unlock_bh(ndev);
+	kfree(mac_tbl);
+
+	return -ENOSPC;
+}
+
+static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)
+{
+	struct net_device *ndev = pf->si->ndev;
+	struct enetc_mac_filter *mac_filter;
+	struct enetc_hw *hw = &pf->si->hw;
+	struct enetc_si *si = pf->si;
+	struct netdev_hw_addr *ha;
+
+	netif_addr_lock_bh(ndev);
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		mac_filter = &si->mac_filter[UC];
+		enetc_reset_mac_addr_filter(mac_filter);
+		netdev_for_each_uc_addr(ha, ndev)
+			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
+
+		enetc4_pf_set_si_mac_hash_filter(hw, 0, UC,
+						 *mac_filter->mac_hash_table);
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC) {
+		mac_filter = &si->mac_filter[MC];
+		enetc_reset_mac_addr_filter(mac_filter);
+		netdev_for_each_mc_addr(ha, ndev)
+			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
+
+		enetc4_pf_set_si_mac_hash_filter(hw, 0, MC,
+						 *mac_filter->mac_hash_table);
+	}
+	netif_addr_unlock_bh(ndev);
+}
+
+static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
+{
+	/* Currently, the MAC address filter table only has 4 entries, and the
+	 * table is shared by PF and VFs. In the default network configuration,
+	 * the MAC filter will be configured with multiple multicast addresses,
+	 * so it is only suitable for unicast filtering. If the number of unicast
+	 * addresses exceeds the table capacity, the MAC hash filter will be used.
+	 */
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		if (enetc4_pf_set_mac_exact_filter(pf, ENETC_MAC_FILTER_TYPE_UC))
+			/* Fall back to the MAC hash filter */
+			enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC)
+		enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
 	.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
 	.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
@@ -71,9 +414,18 @@ static int enetc4_pf_struct_init(struct enetc_si *si)
 
 	enetc4_get_port_caps(pf);
 
+	INIT_HLIST_HEAD(&pf->mac_list);
+	mutex_init(&pf->mac_list_lock);
+
 	return 0;
 }
 
+static void enetc4_pf_struct_free(struct enetc_pf *pf)
+{
+	enetc4_pf_destroy_mac_list(pf);
+	mutex_destroy(&pf->mac_list_lock);
+}
+
 static u32 enetc4_psicfgr0_val_construct(bool is_vf, u32 num_tx_bdr, u32 num_rx_bdr)
 {
 	u32 val;
@@ -305,12 +657,53 @@ static void enetc4_pf_free(struct enetc_pf *pf)
 	enetc4_free_ntmp_priv(pf->si);
 }
 
+static void enetc4_pf_do_set_rx_mode(struct work_struct *work)
+{
+	struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
+	struct enetc_pf *pf = enetc_si_priv(si);
+	struct net_device *ndev = si->ndev;
+	struct enetc_hw *hw = &si->hw;
+	bool uc_promisc = false;
+	bool mc_promisc = false;
+	int type = 0;
+
+	if (ndev->flags & IFF_PROMISC) {
+		uc_promisc = true;
+		mc_promisc = true;
+	} else if (ndev->flags & IFF_ALLMULTI) {
+		mc_promisc = true;
+		type = ENETC_MAC_FILTER_TYPE_UC;
+	} else {
+		type = ENETC_MAC_FILTER_TYPE_ALL;
+	}
+
+	enetc4_pf_set_si_mac_promisc(hw, 0, UC, uc_promisc);
+	enetc4_pf_set_si_mac_promisc(hw, 0, MC, mc_promisc);
+
+	/* Clear Old MAC filter */
+	enetc4_pf_flush_si_mac_exact_filter(pf, 0, ENETC_MAC_FILTER_TYPE_ALL);
+	enetc4_pf_set_si_mac_hash_filter(hw, 0, UC, 0);
+	enetc4_pf_set_si_mac_hash_filter(hw, 0, MC, 0);
+
+	/* Set new MAC filter */
+	enetc4_pf_set_mac_filter(pf, type);
+}
+
+static void enetc4_pf_set_rx_mode(struct net_device *ndev)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_si *si = priv->si;
+
+	queue_work(si->workqueue, &si->rx_mode_task);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
 	.ndo_start_xmit		= enetc_xmit,
 	.ndo_get_stats		= enetc_get_stats,
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
+	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
 };
 
 static struct phylink_pcs *
@@ -721,6 +1114,19 @@ static const struct enetc_si_ops enetc4_psi_ops = {
 	.teardown_cbdr = enetc4_teardown_cbdr,
 };
 
+static int enetc4_pf_wq_task_init(struct enetc_si *si)
+{
+	char wq_name[24];
+
+	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
+	snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
+	si->workqueue = create_singlethread_workqueue(wq_name);
+	if (!si->workqueue)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
@@ -756,9 +1162,13 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 		return err;
 
 	pf = enetc_si_priv(si);
+	err = enetc4_pf_wq_task_init(si);
+	if (err)
+		goto err_wq_task_init;
+
 	err = enetc4_pf_init(pf);
 	if (err)
-		return err;
+		goto err_pf_init;
 
 	enetc_get_si_caps(si);
 
@@ -770,6 +1180,10 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
 err_netdev_create:
 	enetc4_pf_free(pf);
+err_pf_init:
+	destroy_workqueue(si->workqueue);
+err_wq_task_init:
+	enetc4_pf_struct_free(pf);
 
 	return err;
 }
@@ -781,6 +1195,8 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
 
 	enetc4_pf_netdev_destroy(si);
 	enetc4_pf_free(pf);
+	destroy_workqueue(si->workqueue);
+	enetc4_pf_struct_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 4098f01479bc..2e676212d230 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -712,6 +712,12 @@ static inline void enetc_load_primary_mac_addr(struct enetc_hw *hw,
 	eth_hw_addr_set(ndev, addr);
 }
 
+static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr)
+{
+	*(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0);
+	*(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1);
+}
+
 #define ENETC_SI_INT_IDX	0
 /* base index for Rx/Tx interrupts */
 #define ENETC_BDR_INT_BASE_IDX	1
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 2b9d0f625f01..3b0cb0d8bf48 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -22,6 +22,13 @@ struct enetc_port_caps {
 	int num_msix;
 	int num_rx_bdr;
 	int num_tx_bdr;
+	int mac_filter_num;
+};
+
+struct enetc_mac_list_entry {
+	u8 mac[ETH_ALEN];
+	u16 si_bitmap;
+	struct hlist_node node;
 };
 
 struct enetc_pf;
@@ -57,6 +64,10 @@ struct enetc_pf {
 
 	struct enetc_port_caps caps;
 	const struct enetc_pf_ops *ops;
+
+	struct hlist_head mac_list; /* MAC address filter table */
+	struct mutex mac_list_lock; /* mac_list lock */
+	int num_mfe;	/* number of mac address filter table entries */
 };
 
 #define phylink_to_enetc_pf(config) \
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:53 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:53 +0800
Subject: [PATCH v3 net-next 05/13] net: enetc: add debugfs interface to dump MAC filter
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-6-wei.fang@nxp.com>

ENETC's MAC filter consists of hash MAC filter and exact MAC filter. Hash
MAC filter is a 64-entry hash table consisting of two 32-bit registers.
Exact MAC filter is implemented by configuring MAC address filter table
through command BD ring. The table is stored in ENETC's internal memory
and needs to be read through command BD ring. In order to facilitate
debugging, added a debugfs interface to get the relevant information
about MAC filter.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 93 +++++++++++++++++++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 ++++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 119 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4dba91408e3d..ca1bc85c0ac9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -318,6 +318,7 @@ struct enetc_si {
 	struct enetc_mac_filter mac_filter[MADDR_TYPE];
 	struct workqueue_struct *workqueue;
 	struct work_struct rx_mode_task;
+	struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN	32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index 000000000000..3a660c80344a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+#define is_en(x)	(x) ? "Enabled" : "Disabled"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+	struct enetc_si *si = s->private;
+	struct enetc_hw *hw = &si->hw;
+	u32 hash_h, hash_l;
+
+	hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+	hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+	seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+		   i, hash_h, hash_l);
+
+	hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+	hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+	seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+		   i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+	struct maft_entry_data maft_data;
+	struct enetc_si *si = s->private;
+	struct enetc_hw *hw = &si->hw;
+	struct maft_keye_data *keye;
+	struct enetc_pf *pf;
+	int i, err, num_si;
+	u32 val;
+
+	pf = enetc_si_priv(si);
+	num_si = pf->caps.num_vsi + 1;
+
+	val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+	for (i = 0; i < num_si; i++) {
+		seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
+			   i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
+		seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
+			   i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
+	}
+
+	/* MAC hash filter table */
+	for (i = 0; i < num_si; i++)
+		enetc_show_si_mac_hash_filter(s, i);
+
+	if (!pf->num_mfe)
+		return 0;
+
+	/* MAC address filter table */
+	seq_puts(s, "Show MAC address filter table\n");
+	for (i = 0; i < pf->num_mfe; i++) {
+		memset(&maft_data, 0, sizeof(maft_data));
+		err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
+		if (err)
+			return err;
+
+		keye = &maft_data.keye;
+		seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+			   keye->mac_addr, le16_to_cpu(maft_data.cfge.si_bitmap));
+	}
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+	struct net_device *ndev = si->ndev;
+	struct dentry *root;
+
+	root = debugfs_create_dir(netdev_name(ndev), NULL);
+	if (IS_ERR(root))
+		return;
+
+	si->debugfs_root = root;
+
+	debugfs_create_file("mac_filter", 0444, root, si, &enetc_mac_filter_fops);
+}
+
+void enetc_remove_debugfs(struct enetc_si *si)
+{
+	debugfs_remove_recursive(si->debugfs_root);
+	si->debugfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
new file mode 100644
index 000000000000..96caca35f79d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+
+#ifndef __ENETC4_DEBUGFS_H
+#define __ENETC4_DEBUGFS_H
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+void enetc_create_debugfs(struct enetc_si *si);
+void enetc_remove_debugfs(struct enetc_si *si);
+#else
+static inline void enetc_create_debugfs(struct enetc_si *si)
+{
+}
+
+static inline void enetc_remove_debugfs(struct enetc_si *si)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 305781ccefd0..c696eb4f0488 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -8,6 +8,7 @@
 #include <linux/unaligned.h>
 
 #include "enetc_pf_common.h"
+#include "enetc4_debugfs.h"
 
 #define ENETC_SI_MAX_RING_NUM	8
 
@@ -1176,6 +1177,8 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_netdev_create;
 
+	enetc_create_debugfs(si);
+
 	return 0;
 
 err_netdev_create:
@@ -1193,6 +1196,7 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
 	struct enetc_si *si = pci_get_drvdata(pdev);
 	struct enetc_pf *pf = enetc_si_priv(si);
 
+	enetc_remove_debugfs(si);
 	enetc4_pf_netdev_destroy(si);
 	enetc4_pf_free(pf);
 	destroy_workqueue(si->workqueue);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:54 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:54 +0800
Subject: [PATCH v3 net-next 06/13] net: enetc: add RSS support for i.MX95 ENETC PF
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-7-wei.fang@nxp.com>

Add Receive side scaling (RSS) support for i.MX95 ENETC PF to improve
the network performance and balance the CPU loading. The main changes
are as follows.

1. Since i.MX95 ENETC (v4) use NTMP 2.0 to manage the RSS table, which
is different from LS1028A ENETC (v1). In order to reuse some functions
related to the RSS table, so add .get_rss_table() and .set_rss_table()
hooks to enetc_si_ops.

2. Since the offset of the RSS key registers of i.MX95 ENETC is also
different from that of LS1028A, so add enetc_get_rss_key_base() to get
the base offset for the different chips, so that enetc_set_rss_key()
and enetc_get_rss_key() can be reused for this trivial.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  7 +-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  6 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 22 +++---
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 14 ++++
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 69 +++++++++++++++----
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  4 +-
 .../freescale/enetc/enetc_pf_common.c         |  6 +-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  2 +
 8 files changed, 95 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3832d2cd91ba..5b5e65ac8fab 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2405,7 +2405,7 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
 	for (i = 0; i < si->num_rss; i++)
 		rss_table[i] = i % num_groups;
 
-	enetc_set_rss_table(si, rss_table, si->num_rss);
+	si->ops->set_rss_table(si, rss_table, si->num_rss);
 
 	kfree(rss_table);
 
@@ -2436,10 +2436,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
 	if (si->hw_features & ENETC_SI_F_LSO)
 		enetc_set_lso_flags_mask(hw);
 
-	/* TODO: RSS support for i.MX95 will be supported later, and the
-	 * is_enetc_rev1() condition will be removed
-	 */
-	if (si->num_rss && is_enetc_rev1(si)) {
+	if (si->num_rss) {
 		err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
 		if (err)
 			return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index ca1bc85c0ac9..ecf79338cd79 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -290,6 +290,8 @@ struct enetc_si;
 struct enetc_si_ops {
 	int (*setup_cbdr)(struct enetc_si *si);
 	void (*teardown_cbdr)(struct enetc_si *si);
+	int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+	int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
 };
 
 /* PCI IEP device data */
@@ -537,10 +539,12 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
 		       int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 					     struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index c696eb4f0488..adaf28fdf0aa 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -579,22 +579,13 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
 	enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-	int i;
-
-	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-		enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
 static void enetc4_set_default_rss_key(struct enetc_pf *pf)
 {
 	u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
-	struct enetc_hw *hw = &pf->si->hw;
 
 	/* set up hash key */
 	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-	enetc4_set_rss_key(hw, hash_key);
+	enetc_set_rss_key(pf->si, hash_key);
 }
 
 static void enetc4_enable_trx(struct enetc_pf *pf)
@@ -698,6 +689,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 	queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device *ndev,
+				  netdev_features_t features)
+{
+	enetc_set_features(ndev, features);
+
+	return 0;
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
@@ -705,6 +704,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_get_stats		= enetc_get_stats,
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
 	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
+	.ndo_set_features	= enetc4_pf_set_features,
 };
 
 static struct phylink_pcs *
@@ -1113,6 +1113,8 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
 static const struct enetc_si_ops enetc4_psi_ops = {
 	.setup_cbdr = enetc4_setup_cbdr,
 	.teardown_cbdr = enetc4_teardown_cbdr,
+	.get_rss_table = enetc4_get_rss_table,
+	.set_rss_table = enetc4_set_rss_table,
 };
 
 static int enetc4_pf_wq_task_init(struct enetc_si *si)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 4e5125331d7b..1a74b93f1fd3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -299,3 +299,17 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count)
 	return enetc_cmd_rss_table(si, (u32 *)table, count, false);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
+					       table, count, true);
+}
+EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
+
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
+{
+	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
+					       (u32 *)table, count, false);
+}
+EXPORT_SYMBOL_GPL(enetc4_set_rss_table);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index ece3ae28ba82..bc65135925b8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -625,6 +625,24 @@ static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
 	return 0;
 }
 
+static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
+			    u32 *rule_locs)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_GRXRINGS:
+		rxnfc->data = priv->num_rx_rings;
+		break;
+	case ETHTOOL_GRXFH:
+		return enetc_get_rsshash(rxnfc);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -677,36 +695,53 @@ static u32 enetc_get_rxfh_indir_size(struct net_device *ndev)
 	return priv->si->num_rss;
 }
 
+static int enetc_get_rss_key_base(struct enetc_si *si)
+{
+	if (is_enetc_rev1(si))
+		return ENETC_PRSSK(0);
+
+	return ENETC4_PRSSKR(0);
+}
+
+static void enetc_get_rss_key(struct enetc_si *si, const u8 *key)
+{
+	int base = enetc_get_rss_key_base(si);
+	struct enetc_hw *hw = &si->hw;
+	int i;
+
+	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+		((u32 *)key)[i] = enetc_port_rd(hw, base + i * 4);
+}
+
 static int enetc_get_rxfh(struct net_device *ndev,
 			  struct ethtool_rxfh_param *rxfh)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
-	int err = 0, i;
+	struct enetc_si *si = priv->si;
+	int err = 0;
 
 	/* return hash function */
 	rxfh->hfunc = ETH_RSS_HASH_TOP;
 
 	/* return hash key */
-	if (rxfh->key && hw->port)
-		for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-			((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
-							      ENETC_PRSSK(i));
+	if (rxfh->key && enetc_si_is_pf(si))
+		enetc_get_rss_key(si, rxfh->key);
 
 	/* return RSS table */
 	if (rxfh->indir)
-		err = enetc_get_rss_table(priv->si, rxfh->indir,
-					  priv->si->num_rss);
+		err = si->ops->get_rss_table(si, rxfh->indir, si->num_rss);
 
 	return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes)
 {
+	int base = enetc_get_rss_key_base(si);
+	struct enetc_hw *hw = &si->hw;
 	int i;
 
 	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-		enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+		enetc_port_wr(hw, base + i * 4, ((u32 *)bytes)[i]);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_key);
 
@@ -715,17 +750,16 @@ static int enetc_set_rxfh(struct net_device *ndev,
 			  struct netlink_ext_ack *extack)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
+	struct enetc_si *si = priv->si;
 	int err = 0;
 
 	/* set hash key, if PF */
-	if (rxfh->key && hw->port)
-		enetc_set_rss_key(hw, rxfh->key);
+	if (rxfh->key && enetc_si_is_pf(si))
+		enetc_set_rss_key(si, rxfh->key);
 
 	/* set RSS table */
 	if (rxfh->indir)
-		err = enetc_set_rss_table(priv->si, rxfh->indir,
-					  priv->si->num_rss);
+		err = si->ops->set_rss_table(si, rxfh->indir, si->num_rss);
 
 	return err;
 }
@@ -1240,6 +1274,11 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
 	.set_wol = enetc_set_wol,
 	.get_pauseparam = enetc_get_pauseparam,
 	.set_pauseparam = enetc_set_pauseparam,
+	.get_rxnfc = enetc4_get_rxnfc,
+	.get_rxfh_key_size = enetc_get_rxfh_key_size,
+	.get_rxfh_indir_size = enetc_get_rxfh_indir_size,
+	.get_rxfh = enetc_get_rxfh,
+	.set_rxfh = enetc_set_rxfh,
 };
 
 void enetc_set_ethtool_ops(struct net_device *ndev)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index cc3e52bd3096..38ec7657b9aa 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -523,7 +523,7 @@ static void enetc_configure_port(struct enetc_pf *pf)
 
 	/* set up hash key */
 	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-	enetc_set_rss_key(hw, hash_key);
+	enetc_set_rss_key(pf->si, hash_key);
 
 	/* split up RFS entries */
 	enetc_port_assign_rfs_entries(pf->si);
@@ -907,6 +907,8 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
 static const struct enetc_si_ops enetc_psi_ops = {
 	.setup_cbdr = enetc_setup_cbdr,
 	.teardown_cbdr = enetc_teardown_cbdr,
+	.get_rss_table = enetc_get_rss_table,
+	.set_rss_table = enetc_set_rss_table,
 };
 
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3fd9b0727875..c346e0e3ad37 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,15 +128,15 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	if (si->hw_features & ENETC_SI_F_LSO)
 		priv->active_offloads |= ENETC_F_LSO;
 
+	if (si->num_rss)
+		ndev->hw_features |= NETIF_F_RXHASH;
+
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
 		ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
 		goto end;
 	}
 
-	if (si->num_rss)
-		ndev->hw_features |= NETIF_F_RXHASH;
-
 	ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 			     NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
 			     NETDEV_XDP_ACT_NDO_XMIT_SG;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index d7d9a720069b..072e5b40a199 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -165,6 +165,8 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 static const struct enetc_si_ops enetc_vsi_ops = {
 	.setup_cbdr = enetc_setup_cbdr,
 	.teardown_cbdr = enetc_teardown_cbdr,
+	.get_rss_table = enetc_get_rss_table,
+	.set_rss_table = enetc_set_rss_table,
 };
 
 static int enetc_vf_probe(struct pci_dev *pdev,
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:55 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:55 +0800
Subject: [PATCH v3 net-next 07/13] net: enetc: check if the RSS hfunc is toeplitz
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-8-wei.fang@nxp.com>

Both ENETC v1 and ENETC v4 only support the toeplitz algorithm for RSS,
so add a check for RSS hfunc.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index bc65135925b8..6a47e2bd1d4f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -753,6 +753,13 @@ static int enetc_set_rxfh(struct net_device *ndev,
 	struct enetc_si *si = priv->si;
 	int err = 0;
 
+	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+	    rxfh->hfunc != ETH_RSS_HASH_TOP) {
+		netdev_err(ndev, "Only toeplitz hash function is supported\n");
+
+		return -EOPNOTSUPP;
+	}
+
 	/* set hash key, if PF */
 	if (rxfh->key && enetc_si_is_pf(si))
 		enetc_set_rss_key(si, rxfh->key);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:56 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:56 +0800
Subject: [PATCH v3 net-next 08/13] net: enetc: enable RSS feature by default
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-9-wei.fang@nxp.com>

Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++++++++++---------
 .../freescale/enetc/enetc_pf_common.c         |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5b5e65ac8fab..8583ac9f7b9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2420,6 +2420,22 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
 	enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static int enetc_set_rss(struct net_device *ndev, int en)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_hw *hw = &priv->si->hw;
+	u32 reg;
+
+	enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+	reg = enetc_rd(hw, ENETC_SIMR);
+	reg &= ~ENETC_SIMR_RSSE;
+	reg |= (en) ? ENETC_SIMR_RSSE : 0;
+	enetc_wr(hw, ENETC_SIMR, reg);
+
+	return 0;
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
 	struct enetc_si *si = priv->si;
@@ -2440,6 +2456,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
 		err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
 		if (err)
 			return err;
+
+		if (priv->ndev->features & NETIF_F_RXHASH)
+			enetc_set_rss(priv->ndev, true);
 	}
 
 	return 0;
@@ -3232,22 +3251,6 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
-	u32 reg;
-
-	enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-	reg = enetc_rd(hw, ENETC_SIMR);
-	reg &= ~ENETC_SIMR_RSSE;
-	reg |= (en) ? ENETC_SIMR_RSSE : 0;
-	enetc_wr(hw, ENETC_SIMR, reg);
-
-	return 0;
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index c346e0e3ad37..a737a7f8c79e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	if (si->hw_features & ENETC_SI_F_LSO)
 		priv->active_offloads |= ENETC_F_LSO;
 
-	if (si->num_rss)
+	if (si->num_rss) {
 		ndev->hw_features |= NETIF_F_RXHASH;
+		ndev->features |= NETIF_F_RXHASH;
+	}
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 072e5b40a199..3372a9a779a6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
 			      NETIF_F_TSO | NETIF_F_TSO6;
 
-	if (si->num_rss)
+	if (si->num_rss) {
 		ndev->hw_features |= NETIF_F_RXHASH;
+		ndev->features |= NETIF_F_RXHASH;
+	}
 
 	/* pick up primary MAC address from SI */
 	enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:57 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:57 +0800
Subject: [PATCH v3 net-next 09/13] net: enetc: move generic VLAN filter interfaces to enetc-core
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-10-wei.fang@nxp.com>

For ENETC, each SI has a corresponding VLAN hash table. That is to say,
both PF and VFs can support VLAN filter. However, currently only ENETC v1
PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
VF drivers also support VLAN filter, some related macros are moved from
enetc_pf.h to enetc.h, and the related structure variables are moved from
enetc_pf to enetc_si.

Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
so that it can be shared by PF and VF drivers. This will make it easier
to add VLAN filter support for i.MX95 ENETC later.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 25 ++++++++++
 drivers/net/ethernet/freescale/enetc/enetc.h  |  6 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 46 +++++--------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  4 --
 4 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 8583ac9f7b9e..248dbc874eec 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -72,6 +72,31 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
 }
 EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
 
+int enetc_vid_hash_idx(unsigned int vid)
+{
+	int res = 0;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(enetc_vid_hash_idx);
+
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si)
+{
+	int i;
+
+	bitmap_zero(si->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+	for_each_set_bit(i, si->active_vlans, VLAN_N_VID) {
+		int hidx = enetc_vid_hash_idx(i);
+
+		__set_bit(hidx, si->vlan_ht_filter);
+	}
+}
+EXPORT_SYMBOL_GPL(enetc_refresh_vlan_ht_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
 	int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index ecf79338cd79..c60741dfe358 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -24,6 +24,7 @@
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
 #define ENETC_MADDR_HASH_TBL_SZ	64
+#define ENETC_VLAN_HT_SIZE	64
 
 enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
 
@@ -321,6 +322,9 @@ struct enetc_si {
 	struct workqueue_struct *workqueue;
 	struct work_struct rx_mode_task;
 	struct dentry *debugfs_root;
+
+	DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 };
 
 #define ENETC_SI_ALIGN	32
@@ -506,6 +510,8 @@ int enetc_get_driver_data(struct enetc_si *si);
 void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
 				  const unsigned char *addr);
 void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+int enetc_vid_hash_idx(unsigned int vid);
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 38ec7657b9aa..f9b179ed6d8b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -222,45 +222,18 @@ static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
 	enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-	int res = 0;
-	int i;
-
-	for (i = 0; i < 6; i++)
-		res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-	return res;
-}
-
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
-{
-	int i;
-
-	if (rehash) {
-		bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-
-		for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-			int hidx = enetc_vid_hash_idx(i);
-
-			__set_bit(hidx, pf->vlan_ht_filter);
-		}
-	}
-
-	enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-}
-
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	int idx;
 
-	__set_bit(vid, pf->active_vlans);
+	__set_bit(vid, si->active_vlans);
 
 	idx = enetc_vid_hash_idx(vid);
-	if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-		enetc_sync_vlan_ht_filter(pf, false);
+	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
 
 	return 0;
 }
@@ -268,10 +241,13 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 
-	__clear_bit(vid, pf->active_vlans);
-	enetc_sync_vlan_ht_filter(pf, true);
+	if (__test_and_clear_bit(vid, si->active_vlans)) {
+		enetc_refresh_vlan_ht_filter(si);
+		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
+	}
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 3b0cb0d8bf48..90137fbb8f48 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -6,8 +6,6 @@
 
 #define ENETC_PF_NUM_RINGS	8
 
-#define ENETC_VLAN_HT_SIZE	64
-
 enum enetc_vf_flags {
 	ENETC_VF_FLAG_PF_SET_MAC	= BIT(0),
 };
@@ -52,8 +50,6 @@ struct enetc_pf {
 	char msg_int_name[ENETC_INT_NAME_MAX];
 
 	char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */
-	DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 
 	struct mii_bus *mdio; /* saved for cleanup */
 	struct mii_bus *imdio;
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar  3 23:21:58 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue,  4 Mar 2025 15:21:58 +0800
Subject: [PATCH v3 net-next 10/13] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c
In-Reply-To: <20250304072201.1332603-1-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
Message-ID: <20250304072201.1332603-11-wei.fang@nxp.com>

Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
only difference is the offset of the VLAN hash filter registers. So, the
.set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
the registers of the corresponding platform. In addition, the common VLAN
hash filter functions enetc_vlan_rx_add_vid() and enetc_vlan_rx_del_vid()
are moved to enetc_pf_common.c.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 ++-----------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 +
 .../freescale/enetc/enetc_pf_common.c         | 34 +++++++++++++++++++
 .../freescale/enetc/enetc_pf_common.h         |  2 ++
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index f9b179ed6d8b..d3ca9e33893f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -215,43 +215,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 	enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-				     unsigned long hash)
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, u64 hash)
 {
 	enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
 	enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
-	int idx;
-
-	__set_bit(vid, si->active_vlans);
-
-	idx = enetc_vid_hash_idx(vid);
-	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
-		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-
-	return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
-
-	if (__test_and_clear_bit(vid, si->active_vlans)) {
-		enetc_refresh_vlan_ht_filter(si);
-		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-	}
-
-	return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -953,6 +922,7 @@ static const struct enetc_pf_ops enetc_pf_ops = {
 	.create_pcs = enetc_pf_create_pcs,
 	.destroy_pcs = enetc_pf_destroy_pcs,
 	.enable_psfp = enetc_psfp_enable,
+	.set_si_vlan_hash_filter = enetc_set_vlan_ht_filter,
 };
 
 static int enetc_pf_probe(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 90137fbb8f48..704c4ee42f61 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -37,6 +37,7 @@ struct enetc_pf_ops {
 	struct phylink_pcs *(*create_pcs)(struct enetc_pf *pf, struct mii_bus *bus);
 	void (*destroy_pcs)(struct phylink_pcs *pcs);
 	int (*enable_psfp)(struct enetc_ndev_priv *priv);
+	void (*set_si_vlan_hash_filter)(struct enetc_hw *hw, int si, u64 hash);
 };
 
 struct enetc_pf {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a737a7f8c79e..9f812c1af7a3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -343,5 +343,39 @@ void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
 }
 EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
 
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
+	int idx;
+
+	__set_bit(vid, si->active_vlans);
+
+	idx = enetc_vid_hash_idx(vid);
+	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+		pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
+
+	if (__test_and_clear_bit(vid, si->active_vlans)) {
+		enetc_refresh_vlan_ht_filter(si);
+		pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_del_vid);
+
 MODULE_DESCRIPTION("NXP ENETC PF common functionality driver");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index 48f55ee743ad..253310859ca1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -12,6 +12,8 @@ void enetc_mdiobus_destroy(struct enetc_pf *pf);
 int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
 			 const struct phylink_mac_ops *ops);
 void enetc_phylink_destroy(struct enetc_ndev_priv *priv);
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid);
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid);
 
 static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
 {
-- 
2.34.1



From a.fatoum at pengutronix.de  Mon Mar  3 23:56:23 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 4 Mar 2025 08:56:23 +0100
Subject: [PATCH v4 0/6] arm64: dts: freescale: imx8mp-skov: switch to
 nominal drive mode
In-Reply-To: <Z8XnuIIfDFykrKH8@linaro.org>
References: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
 <174102306220.2928950.8878245519332562153.b4-ty@linaro.org>
 <Z8XnuIIfDFykrKH8@linaro.org>
Message-ID: <4175faf6-1d41-4409-89db-dd902c966dd5@pengutronix.de>

Hello Abel,
Hello Shawn,

On 03.03.25 18:32, Abel Vesa wrote:
> On 25-03-03 19:31:02, Abel Vesa wrote:
>>
>> On Tue, 18 Feb 2025 19:26:40 +0100, Ahmad Fatoum wrote:
>>> Unlike the i.MX8MM and i.MX8MN SoCs added earlier, the imx8mp.dtsi
>>> configures some clocks at frequencies that are only validated for
>>> overdrive mode, i.e., when VDD_SOC is 950 mV.
>>>
>>> For the Skov i.MX8MP board, we want to run the SoC at the lower voltage of
>>> 850 mV though to reduce heat generation and power usage. For this to work,
>>> clock rates need to adhere to the limits of the nominal drive mode.
>>>
>>> [...]
>>
>> Applied, thanks!
>>
>> [1/6] dt-bindings: clock: imx8m: document nominal/overdrive properties
>>       commit: d5992f1af1550a9e11e42cfa2ca1ad2a1b7fd7f3
>> [2/6] arm64: dts: imx8mp: Add optional nominal drive mode DTSI
>>       (no commit info)
>> [3/6] arm64: dts: imx8mp: add fsl,nominal-mode property into nominal.dtsi
>>       (no commit info)
>> [4/6] arm64: dts: freescale: imx8mp-skov: configure LDB clock automatically
>>       (no commit info)
>> [5/6] arm64: dts: freescale: imx8mp-skov: operate SoC in nominal mode
>>       (no commit info)
>> [6/6] clk: imx8mp: inform CCF of maximum frequency of clocks
>>       commit: 06a61b5cb6a8638fa8823cd09b17233b29696fa2
> 
> Applied only patches 1 and 6.
> 
> My b4 setup messed up. Sorry.

Thanks for applying, Abel!

@Shawn, could the remainder of the patches go through your tree?

Thanks!
Ahmad

> 
>>
>> Best regards,
>> -- 
>> Abel Vesa <abel.vesa at linaro.org>
>>
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From krzk at kernel.org  Tue Mar  4 00:05:03 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 09:05:03 +0100
Subject: [PATCH v3 1/7] dt-bindings: arm: Add support for Coresight TGU
 trace
In-Reply-To: <20250227092640.2666894-2-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com>
 <20250227092640.2666894-2-quic_songchai@quicinc.com>
Message-ID: <20250304-certain-aboriginal-magpie-cade86@krzk-bin>

On Thu, Feb 27, 2025 at 05:26:34PM +0800, songchai wrote:
> From: Songwei Chai <quic_songchai at quicinc.com>
> 
> The Trigger Generation Unit (TGU) is designed to detect patterns or
> sequences within a specific region of the System on Chip (SoC). Once
> configured and activated, it monitors sense inputs and can detect a
> pre-programmed state or sequence across clock cycles, subsequently
> producing a trigger.
> 
>    TGU configuration space
>         offset table
>  x-------------------------x
>  |                         |
>  |                         |
>  |                         |                           Step configuration
>  |                         |                             space layout
>  |   coresight management  |                           x-------------x
>  |        registers        |                     |---> |             |
>  |                         |                     |     |  reserve    |
>  |                         |                     |     |             |
>  |-------------------------|                     |     |-------------|
>  |                         |                     |     | priority[3] |
>  |         step[7]         |<--                  |     |-------------|
>  |-------------------------|   |                 |     | priority[2] |
>  |                         |   |                 |     |-------------|
>  |           ...           |   |Steps region     |     | priority[1] |
>  |                         |   |                 |     |-------------|
>  |-------------------------|   |                 |     | priority[0] |
>  |                         |<--                  |     |-------------|
>  |         step[0]         |-------------------->      |             |
>  |-------------------------|                           |  condition  |
>  |                         |                           |             |
>  |     control and status  |                           x-------------x
>  |           space         |                           |             |
>  x-------------------------x                           |Timer/Counter|
>                                                        |             |
> 						       x-------------x
> TGU Configuration in Hardware
> 
> The TGU provides a step region for user configuration, similar
> to a flow chart. Each step region consists of three register clusters:
> 
> 1.Priority Region: Sets the required signals with priority.
> 2.Condition Region: Defines specific requirements (e.g., signal A
> reaches three times) and the subsequent action once the requirement is
> met.
> 3.Timer/Counter (Optional): Provides timing or counting functionality.
> 
> Add a new coresight-tgu.yaml file to describe the bindings required to
> define the TGU in the device trees.
> 
> Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> Signed-off-by: songchai <quic_songchai at quicinc.com>

Don't duplicate yourself.

Anyway, this is marked as v3, I cannot find previous versions, no
changelog, no references.

What happened here in this binding?

> ---
>  .../bindings/arm/qcom,coresight-tgu.yaml      | 135 ++++++++++++++++++
>  1 file changed, 135 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> 
> diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> new file mode 100644
> index 000000000000..a41ac68a4fe7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> @@ -0,0 +1,135 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +# Copyright (c) 2023-2025 Qualcomm Innovation Center, Inc. All rights reserved.

2023 and 2024? Where was it published in these years?

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/qcom,coresight-tgu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Trigger Generation Unit - TGU
> +
> +description: |
> +  The Trigger Generation Unit (TGU) is a Data Engine which can be utilized
> +  to sense a plurality of signals and create a trigger into the CTI or
> +  generate interrupts to processors. The TGU is like the trigger circuit
> +  of a Logic Analyzer. The corresponding trigger logic can be realized by
> +  configuring the conditions for each step after sensing the signal.
> +  Once setup and enabled, it will observe sense inputs and based upon
> +  the activity of those inputs, even over clock cycles, may detect a
> +  preprogrammed state/sequence and then produce a trigger or interrupt.
> +
> +  The primary use case of the TGU is to detect patterns or sequences on a
> +  given set of signals within some region of the SoC.
> +
> +maintainers:
> +  - Mao Jinlong <quic_jinlmao at quicinc.com>
> +  - Sam Chai <quic_songchai at quicinc.com>
> +
> +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - qcom,coresight-tgu
> +  required:
> +    - compatible
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: qcom,coresight-tgu
> +      - const: arm,primecell
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  clock-names:
> +    items:
> +      - const: apb_pclk
> +
> +  qcom,tgu-steps:
> +    description:
> +      The trigger logic is realized by configuring each step after sensing
> +      the signal. The parameter here is used to describe the maximum of steps
> +      that could be configured in the current TGU.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 1
> +    maximum: 8
> +
> +  qcom,tgu-regs:
> +    description:
> +      There are some "groups" register clusters in each step, which are used to
> +      configure the signal that we want to detect. Meanwhile, each group has its
> +      own priority, and the priority increases with number of groups. For example,
> +      group3 has a higher priority than group2, the signal configured in group3
> +      will be sensed more preferentially than the signal which is configured in group2.
> +      The parameter here is used to describe the signal number that each group
> +      could be configured.

And all groups are indexed by number? Or do they have names?

> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 1
> +    maximum: 18
> +
> +  qcom,tgu-conditions:
> +    description:
> +      A condition sets a specific requirement for a step and defines the subsequent
> +      action once the requirement is met. For example, in step two, if signal A is
> +      detected three times, the process jumps back to step one. The parameter describes
> +      the register number for each functionality, whether it is setting a specific
> +      requirement or defining a subsequent action.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 1
> +    maximum: 4
> +
> +  qcom,tgu-timer-counters:
> +    description:
> +      TGU has timer and counter which are used to set some requirement on each step.

Wrap according to Linux coding style, so at 80.

> +      For example, we could use counter to create a trigger into CTI once TGU senses
> +      the target signal three times.This parameter is used to describe the number of
> +      Timers/Counters in TGU.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0

Drop

> +    maximum: 2
> +
> +  in-ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +    additionalProperties: false
> +
> +    properties:
> +      port:
> +        description: AXI Slave connected to another Coresight component

So this TGU can be connected to anything in coresight graph, no
restrictions?

> +        $ref: /schemas/graph.yaml#/properties/port
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names

Most likely you miss also: in-ports


Best regards,
Krzysztof



From mripard at kernel.org  Tue Mar  4 00:13:20 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Tue, 4 Mar 2025 09:13:20 +0100
Subject: [PATCH v4 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>
Message-ID: <20250304-small-mindful-mongrel-bd6f8b@houat>

Hi,

On Tue, Mar 04, 2025 at 03:44:02AM +0200, Cristian Ciocaltea wrote:
> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
> and not before.
> 
> While at it, introduce a define for this rate limit constant.
> 
> Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -320,6 +320,7 @@
>  #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
>  #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
>  
> +#define HDMI14_MAX_RATE			340000000
>  #define HDMI20_MAX_RATE			600000000
>  
>  enum dp_link_rate {
> @@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
>  
>  	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
>  
> -	if (rate >= 3400000) {
> +	if (rate > HDMI14_MAX_RATE / 100) {

The rate seems to come from rk_hdptx_phy_power_on and eventually from
tmds_char_rate in the PHY config options, so its rate is in Hertz.
HDMI14_MAX_RATE and HDMI20_MAX_RATE are both defined in Hertz as well.
It seems super odd to mee that you then convert HDMI14_MAX_RATE to hHz?

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/83be1d7e/attachment.sig>

From mripard at kernel.org  Tue Mar  4 00:15:21 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Tue, 4 Mar 2025 09:15:21 +0100
Subject: [PATCH v4 07/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-7-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-7-8657847c13f7@collabora.com>
Message-ID: <20250304-turtle-of-serious-aurora-2b0bae@houat>

On Tue, Mar 04, 2025 at 03:44:06AM +0200, Cristian Ciocaltea wrote:
> The current workaround to setup the TMDS character rate relies on the
> unconventional usage of phy_set_bus_width().
> 
> Make use of the recently introduced HDMI PHY configuration API to
> properly handle the setup.  The workaround will be dropped as soon as
> the switch has been completed on both ends.
> 
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 54 ++++++++++++++++-------
>  1 file changed, 38 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 2bf525514c1991a1299265d12e1e85f66333c604..7e1d1c10758249aa5bbddbdaae0108bba04f30df 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -394,6 +394,7 @@ struct rk_hdptx_phy {
>  
>  	int phy_id;
>  	struct phy *phy;
> +	struct phy_configure_opts_hdmi hdmi_cfg;
>  	struct clk_bulk_data *clks;
>  	int nr_clks;
>  	struct reset_control_bulk_data rsts[RST_MAX];
> @@ -1409,19 +1410,25 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
>  static int rk_hdptx_phy_power_on(struct phy *phy)
>  {
>  	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
> -	int bus_width = phy_get_bus_width(hdptx->phy);
>  	enum phy_mode mode = phy_get_mode(phy);
> +	unsigned int rate = 0;
>  	int ret, lane;
>  
> -	/*
> -	 * FIXME: Temporary workaround to pass pixel_clk_rate
> -	 * from the HDMI bridge driver until phy_configure_opts_hdmi
> -	 * becomes available in the PHY API.
> -	 */
> -	unsigned int rate = bus_width & 0xfffffff;
> -
> -	dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
> -		__func__, bus_width, rate);
> +	if (mode != PHY_MODE_DP) {
> +		if (!hdptx->hdmi_cfg.tmds_char_rate) {
> +			/*
> +			 * FIXME: Temporary workaround to setup TMDS char rate
> +			 * from the RK DW HDMI QP bridge driver.
> +			 * Will be removed as soon the switch to the HDMI PHY
> +			 * configuration API has been completed on both ends.
> +			 */
> +			rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
> +			hdptx->hdmi_cfg.tmds_char_rate = rate * 100;
> +		} else {
> +			rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
> +		}
> +		dev_dbg(hdptx->dev, "%s rate=%u\n", __func__, rate);
> +	}

Some story here, I can't make sense of a variable in hHz. If it's
actually needed and not a bug, this should be very explictly documented.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/87160d2b/attachment.sig>

From danishanwar at ti.com  Tue Mar  4 00:16:39 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Tue, 4 Mar 2025 13:46:39 +0530
Subject: [PATCH net-next] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250303172543.249a4fc2@kernel.org>
References: <20250227093712.2130561-1-danishanwar@ti.com>
 <20250303172543.249a4fc2@kernel.org>
Message-ID: <33c38844-4fbe-469c-bb5f-06bdb7721114@ti.com>



On 04/03/25 6:55 am, Jakub Kicinski wrote:
> On Thu, 27 Feb 2025 15:07:12 +0530 MD Danish Anwar wrote:
>> +	ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
>> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
>> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
>> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
>> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),
> 
> I presume frame preemption is implemented in silicon? If yes -
> what makes these "FW statistics"? Does the FW collect them from 

The statistics are maintained / updated by firmware and thus the name.

Preemption is implemented partially in both the hardware and firmware.
The STATE MACHINE for preemption is in the firmware. The decision to
when to PREEMEPT / ASSEMBLE a packet is made in firmware.

These preemption statistics are updated by the firmware based on the
action performed by the firmware. Driver can read these to know the
statistics of preemption. These stats will be able used by
ethtool_mm_stats once the support for Preemption is added in the driver.

> the device or the frames are for FW? 
> 
>> +	ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
>> +	ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
>> +	ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
>> +	ICSSG_PA_STATS(FW_RX_EXP_FRAG_Q_DROP),
>> +	ICSSG_PA_STATS(FW_RX_FIFO_OVERRUN),
>> +	ICSSG_PA_STATS(FW_CUT_THR_PKT),
>> +	ICSSG_PA_STATS(FW_HOST_RX_PKT_CNT),
>> +	ICSSG_PA_STATS(FW_HOST_TX_PKT_CNT),
>> +	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_PRE_OVERFLOW),
>> +	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_EXP_OVERFLOW),
>>  };
>>  
>>  #endif /* __NET_TI_ICSSG_STATS_H */
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> index 424a7e945ea8..d30203a0978c 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> @@ -231,4 +231,109 @@
>>  /* Start of 32 bits PA_STAT counters */
>>  #define PA_STAT_32b_START_OFFSET                           0x0080
>>  
>> +/* Diagnostic error counter which increments when RTU drops a locally injected
>> + * packet due to port disabled or rule violation.
>> + */
>> +#define FW_RTU_PKT_DROP		0x0088
>> +
>> +/* Tx Queue Overflow Counters */
>> +#define FW_Q0_OVERFLOW		0x0090
>> +#define FW_Q1_OVERFLOW		0x0098
>> +#define FW_Q2_OVERFLOW		0x00A0
>> +#define FW_Q3_OVERFLOW		0x00A8
>> +#define FW_Q4_OVERFLOW		0x00B0
>> +#define FW_Q5_OVERFLOW		0x00B8
>> +#define FW_Q6_OVERFLOW		0x00C0
>> +#define FW_Q7_OVERFLOW		0x00C8
>> +
>> +/* Incremented if a packet is dropped at PRU because of a rule violation */
>> +#define FW_DROPPED_PKT		0x00F8
> 
> Instead of adding comments here please add a file under
> Documentation/networking/device_drivers/ with the explanations.
> That's far more likely to be discovered by users, no?

Sure I will drop these MACRO comments and create a .rst file in
Documentation/networking/device_drivers/

One question though, should I create a table for the stats and it's
description or should I create a section for each stats?

Something like this,

FW_RTU_PKT_DROP
---------------
Diagnostic error counter which increments when RTU drops a locally
injected packet due to port being disabled or rule violation.

Please let me know what do you think.

-- 
Thanks and Regards,
Danish


From mripard at kernel.org  Tue Mar  4 00:18:23 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Tue, 4 Mar 2025 09:18:23 +0100
Subject: [PATCH v4 08/12] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-8-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-8-8657847c13f7@collabora.com>
Message-ID: <20250304-romantic-truthful-sambar-deaab1@houat>

On Tue, Mar 04, 2025 at 03:44:07AM +0200, Cristian Ciocaltea wrote:
> Implement the phy_ops.validate() callback to allow checking the PHY
> configuration parameters without actually applying them.
> 
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 7e1d1c10758249aa5bbddbdaae0108bba04f30df..47db1395051f5d900197871694bab90ca4d6e38e 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -1482,6 +1482,17 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>  	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>  		return -EINVAL;
>  
> +	u32 bit_rate = hdmi->tmds_char_rate / 100;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
> +		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
> +			break;
> +
> +	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
> +	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
> +		return -EINVAL;

What are you calling bit_rate here? If anything, I'd expect the bit_rate
to be a multiple of the char rate, not a divisor.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/81abaadb/attachment.sig>

From osalvador at suse.de  Tue Mar  4 00:22:09 2025
From: osalvador at suse.de (Oscar Salvador)
Date: Tue, 4 Mar 2025 09:22:09 +0100
Subject: [PATCH v9] arm64: mm: Populate vmemmap at the page level if not
 section aligned
In-Reply-To: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
References: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
Message-ID: <Z8a4MWPpTKm2FAce@localhost.localdomain>

On Tue, Mar 04, 2025 at 03:27:00PM +0800, Zhenhua Huang wrote:
> On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
> to 27, making one section 128M. The related page struct which vmemmap
> points to is 2M then.
> Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
> vmemmap to populate at the PMD section level which was suitable
> initially since hot plug granule is always one section(128M). However,
> commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
> existing arm64 assumptions.
> 
> The first problem is that if start or end is not aligned to a section
> boundary, such as when a subsection is hot added, populating the entire
> section is wasteful.
> 
> The next problem is if we hotplug something that spans part of 128 MiB
> section (subsections, let's call it memblock1), and then hotplug something
> that spans another part of a 128 MiB section(subsections, let's call it
> memblock2), and subsequently unplug memblock1, vmemmap_free() will clear
> the entire PMD entry which also supports memblock2 even though memblock2
> is still active.
> 
> Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the
> fix similar to x86-64: populate to pages levels if start/end is not aligned
> with section boundary.
> 
> Cc: <stable at vger.kernel.org> # v5.4+
> Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> Acked-by: David Hildenbrand <david at redhat.com>
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>

Reviewed-by: Oscar Salvador <osalvador at suse.de>


-- 
Oscar Salvador
SUSE Labs


From victor.liu at nxp.com  Tue Mar  4 00:24:32 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Tue,  4 Mar 2025 16:24:32 +0800
Subject: [PATCH v5 0/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support
Message-ID: <20250304082434.834031-1-victor.liu@nxp.com>

Hi,

This patch set aims to add NXP i.MX93 parallel display format configuration
DRM bridge driver support. i.MX93 mediamix blk-ctrl contains one
DISPLAY_MUX register which configures parallel display format by using
the "PARALLEL_DISP_FORMAT" field. i.MX93 LCDIF display controller's
parallel output connects with this piece of small logic to configure
parallel display format.

Patch 1/2 adds NXP i.MX93 parallel display format configuration subnode
in i.MX93 mediamix blk-ctrl dt-binding.

Patch 2/2 adds NXP i.MX93 parallel display format configuration DRM bridge
driver support.

v4->v5:
* Rebase the patch set upon next-20250303.  This causes the drop of .remove_new
  from patch 2/2 by using devm_drm_bridge_add().  Also, this causes API change
  for imx93_pdfc_bridge_atomic_enable() in patch 2/2.
* Update year of copyright in patch 2/2.

v3->v4:
* Use dev_err_probe() in imx93_pdfc_bridge_probe() in patch 2/2. (Krzysztof)
* Drop MODULE_ALIAS() in patch 2/2. (Krzysztof)
* Update year of Copyright in patch 2/2.

v2->v3:
* Define i.MX93 parallel display format configuration subnode in
  i.MX93 mediamix blk-ctrl dt-binding. (Rob)
* Resend with Conor's R-b tag on patch 1/2 and with the patch set rebased
  upon v6.11-rc1.

v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL in patch 2/2.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver in patch 2/2.

Liu Ying (2):
  dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and
    example
  drm/bridge: imx: Add i.MX93 parallel display format configuration
    support

 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     |  68 +++++++
 drivers/gpu/drm/bridge/imx/Kconfig            |   8 +
 drivers/gpu/drm/bridge/imx/Makefile           |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c       | 186 ++++++++++++++++++
 4 files changed, 263 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

-- 
2.34.1



From victor.liu at nxp.com  Tue Mar  4 00:24:33 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Tue,  4 Mar 2025 16:24:33 +0800
Subject: [PATCH v5 1/2] dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and example
In-Reply-To: <20250304082434.834031-1-victor.liu@nxp.com>
References: <20250304082434.834031-1-victor.liu@nxp.com>
Message-ID: <20250304082434.834031-2-victor.liu@nxp.com>

i.MX93 SoC mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Document the Parallel Display Format Configuration(PDFC) subnode
and add the subnode to example.

Signed-off-by: Liu Ying <victor.liu at nxp.com>
Reviewed-by: Conor Dooley <conor.dooley at microchip.com>
---
v3->v5:
* No change.

v2->v3:
* Newly introduced to replace the standalone dt-binding in v1 and v2. (Rob)
* Resend with Conor's R-b tag and with the patch rebased upon v6.11-rc1.

 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 68 +++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
index b3554e7f9e76..3f550c30d93d 100644
--- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
+++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
@@ -24,6 +24,12 @@ properties:
   reg:
     maxItems: 1
 
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 1
+
   '#power-domain-cells':
     const: 1
 
@@ -46,9 +52,43 @@ properties:
       - const: csi
       - const: dsi
 
+  bridge at 60:
+    type: object
+    additionalProperties: false
+
+    properties:
+      compatible:
+        const: nxp,imx93-pdfc
+
+      reg:
+        maxItems: 1
+
+      ports:
+        $ref: /schemas/graph.yaml#/properties/ports
+
+        properties:
+          port at 0:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: Input port node to receive pixel data.
+
+          port at 1:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: Output port node to downstream pixel data receivers.
+
+        required:
+          - port at 0
+          - port at 1
+
+    required:
+      - compatible
+      - reg
+      - ports
+
 required:
   - compatible
   - reg
+  - '#address-cells'
+  - '#size-cells'
   - power-domains
   - clocks
   - clock-names
@@ -76,5 +116,33 @@ examples:
                <&clk IMX93_CLK_MIPI_DSI_GATE>;
                clock-names = "apb", "axi", "nic", "disp", "cam",
                              "pxp", "lcdif", "isi", "csi", "dsi";
+      #address-cells = <1>;
+      #size-cells = <1>;
       #power-domain-cells = <1>;
+
+      bridge at 60 {
+        compatible = "nxp,imx93-pdfc";
+        reg = <0x60 0x4>;
+
+        ports {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          port at 0 {
+            reg = <0>;
+
+            pdfc_from_lcdif: endpoint {
+              remote-endpoint = <&lcdif_to_pdfc>;
+            };
+          };
+
+          port at 1 {
+            reg = <1>;
+
+            pdfc_to_panel: endpoint {
+              remote-endpoint = <&panel_from_pdfc>;
+            };
+          };
+        };
+      };
     };
-- 
2.34.1



From victor.liu at nxp.com  Tue Mar  4 00:24:34 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Tue,  4 Mar 2025 16:24:34 +0800
Subject: [PATCH v5 2/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support
In-Reply-To: <20250304082434.834031-1-victor.liu@nxp.com>
References: <20250304082434.834031-1-victor.liu@nxp.com>
Message-ID: <20250304082434.834031-3-victor.liu@nxp.com>

NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Add a DRM bridge driver to support the display format configuration.

Signed-off-by: Liu Ying <victor.liu at nxp.com>
---
v4->v5:
* Rebase upon next-20250303.  This causes the drop of .remove_new by using
  devm_drm_bridge_add().  Also, this causes API change for
  imx93_pdfc_bridge_atomic_enable().
* Update year of copyright.

v3->v4:
* Use dev_err_probe() in imx93_pdfc_bridge_probe(). (Krzysztof)
* Drop MODULE_ALIAS(). (Krzysztof)
* Update year of Copyright.

v2->v3:
* No change.
* Resend with the patch rebased upon v6.11-rc1.

v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver.

 drivers/gpu/drm/bridge/imx/Kconfig      |   8 +
 drivers/gpu/drm/bridge/imx/Makefile     |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c | 186 ++++++++++++++++++++++++
 3 files changed, 195 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig
index 9a480c6abb85..51138d74ddfb 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -88,4 +88,12 @@ config DRM_IMX93_MIPI_DSI
 	  Choose this to enable MIPI DSI controller found in Freescale i.MX93
 	  processor.
 
+config DRM_IMX93_PARALLEL_DISP_FMT_CONFIG
+	tristate "NXP i.MX93 parallel display format configuration"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Choose this to enable parallel display format configuration
+	  found in NXP i.MX93 processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile b/drivers/gpu/drm/bridge/imx/Makefile
index dd5d48584806..f4ccc5cbef72 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
 obj-$(CONFIG_DRM_IMX93_MIPI_DSI) += imx93-mipi-dsi.o
+obj-$(CONFIG_DRM_IMX93_PARALLEL_DISP_FMT_CONFIG) += imx93-pdfc.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-pdfc.c b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
new file mode 100644
index 000000000000..7dfb87e64197
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022-2025 NXP
+ */
+
+#include <linux/media-bus-format.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_print.h>
+
+#define DISPLAY_MUX		0x60
+#define  PARALLEL_DISP_FORMAT	0x700
+
+enum imx93_pdfc_format {
+	RGB888_TO_RGB888 = 0x0,
+	RGB888_TO_RGB666 = 0x1 << 8,
+	RGB565_TO_RGB565 = 0x2 << 8,
+};
+
+struct imx93_pdfc {
+	struct drm_bridge bridge;
+	struct drm_bridge *next_bridge;
+	struct device *dev;
+	struct regmap *regmap;
+	u32 format;
+};
+
+static int imx93_pdfc_bridge_attach(struct drm_bridge *bridge,
+				    enum drm_bridge_attach_flags flags)
+{
+	struct imx93_pdfc *pdfc = bridge->driver_private;
+
+	return drm_bridge_attach(bridge->encoder, pdfc->next_bridge, bridge, flags);
+}
+
+static void imx93_pdfc_bridge_atomic_enable(struct drm_bridge *bridge,
+					    struct drm_atomic_state *state)
+{
+	struct imx93_pdfc *pdfc = bridge->driver_private;
+
+	regmap_update_bits(pdfc->regmap, DISPLAY_MUX, PARALLEL_DISP_FORMAT,
+			   pdfc->format);
+}
+
+static const u32 imx93_pdfc_bus_output_fmts[] = {
+	MEDIA_BUS_FMT_RGB888_1X24,
+	MEDIA_BUS_FMT_RGB666_1X18,
+	MEDIA_BUS_FMT_RGB565_1X16,
+	MEDIA_BUS_FMT_FIXED
+};
+
+static bool imx93_pdfc_bus_output_fmt_supported(u32 fmt)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx93_pdfc_bus_output_fmts); i++) {
+		if (imx93_pdfc_bus_output_fmts[i] == fmt)
+			return true;
+	}
+
+	return false;
+}
+
+static u32 *
+imx93_pdfc_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+					    struct drm_bridge_state *bridge_state,
+					    struct drm_crtc_state *crtc_state,
+					    struct drm_connector_state *conn_state,
+					    u32 output_fmt,
+					    unsigned int *num_input_fmts)
+{
+	u32 *input_fmts;
+
+	*num_input_fmts = 0;
+
+	if (!imx93_pdfc_bus_output_fmt_supported(output_fmt))
+		return NULL;
+
+	input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+	if (!input_fmts)
+		return NULL;
+
+	switch (output_fmt) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		input_fmts[0] = output_fmt;
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+	case MEDIA_BUS_FMT_FIXED:
+		input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+		break;
+	}
+
+	*num_input_fmts = 1;
+
+	return input_fmts;
+}
+
+static int imx93_pdfc_bridge_atomic_check(struct drm_bridge *bridge,
+					  struct drm_bridge_state *bridge_state,
+					  struct drm_crtc_state *crtc_state,
+					  struct drm_connector_state *conn_state)
+{
+	struct imx93_pdfc *pdfc = bridge->driver_private;
+
+	switch (bridge_state->output_bus_cfg.format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		pdfc->format = RGB888_TO_RGB888;
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+		pdfc->format = RGB888_TO_RGB666;
+		break;
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		pdfc->format = RGB565_TO_RGB565;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(pdfc->dev, "Unsupported output bus format: 0x%x\n",
+				     bridge_state->output_bus_cfg.format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct drm_bridge_funcs imx93_pdfc_bridge_funcs = {
+	.attach			= imx93_pdfc_bridge_attach,
+	.atomic_enable		= imx93_pdfc_bridge_atomic_enable,
+	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
+	.atomic_get_input_bus_fmts	= imx93_pdfc_bridge_atomic_get_input_bus_fmts,
+	.atomic_check		= imx93_pdfc_bridge_atomic_check,
+	.atomic_reset		= drm_atomic_helper_bridge_reset,
+};
+
+static int imx93_pdfc_bridge_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct imx93_pdfc *pdfc;
+
+	pdfc = devm_kzalloc(dev, sizeof(*pdfc), GFP_KERNEL);
+	if (!pdfc)
+		return -ENOMEM;
+
+	pdfc->regmap = syscon_node_to_regmap(dev->of_node->parent);
+	if (IS_ERR(pdfc->regmap))
+		return dev_err_probe(dev, PTR_ERR(pdfc->regmap),
+				     "failed to get regmap\n");
+
+	pdfc->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
+	if (IS_ERR(pdfc->next_bridge))
+		return dev_err_probe(dev, PTR_ERR(pdfc->next_bridge),
+				     "failed to get next bridge\n");
+
+	pdfc->dev = dev;
+	pdfc->bridge.driver_private = pdfc;
+	pdfc->bridge.funcs = &imx93_pdfc_bridge_funcs;
+	pdfc->bridge.of_node = dev->of_node;
+
+	return devm_drm_bridge_add(dev, &pdfc->bridge);
+}
+
+static const struct of_device_id imx93_pdfc_dt_ids[] = {
+	{ .compatible = "nxp,imx93-pdfc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx93_pdfc_dt_ids);
+
+static struct platform_driver imx93_pdfc_bridge_driver = {
+	.probe	= imx93_pdfc_bridge_probe,
+	.driver	= {
+		.of_match_table = imx93_pdfc_dt_ids,
+		.name = "imx93_pdfc",
+	},
+};
+module_platform_driver(imx93_pdfc_bridge_driver);
+
+MODULE_DESCRIPTION("NXP i.MX93 parallel display format configuration driver");
+MODULE_AUTHOR("Liu Ying <victor.liu at nxp.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.34.1



From krzk at kernel.org  Tue Mar  4 00:24:41 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 09:24:41 +0100
Subject: [PATCH v3 05/15] dt-bindings: clk: sunxi-ng: add compatible for
 the A523 PRCM-CCU
In-Reply-To: <20250304012805.28594-6-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
 <20250304012805.28594-6-andre.przywara@arm.com>
Message-ID: <20250304-rare-hyrax-of-criticism-1c7b12@krzk-bin>

On Tue, Mar 04, 2025 at 01:27:55AM +0000, Andre Przywara wrote:
> The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> the PRCM R_CCU.
> 
> Add the new compatible string, along with the required input clock
> lists. There is now an extra input clock (PLL_AUDIO), so add this to the
> list of allowed clocks and required it for the A523 PRCM CCU.
> Also add the DT binding headers, listing all the clocks with their ID
> numbers.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../clock/allwinner,sun55i-a523-ccu.yaml      | 23 +++++++++++-
>  include/dt-bindings/clock/sun55i-a523-r-ccu.h | 37 +++++++++++++++++++
>  include/dt-bindings/reset/sun55i-a523-r-ccu.h | 25 +++++++++++++
>  3 files changed, 83 insertions(+), 2 deletions(-)
>  create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> index 2eacaeaeabac7..a64a35b423736 100644
> --- a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> @@ -19,17 +19,18 @@ properties:
>    compatible:
>      enum:
>        - allwinner,sun55i-a523-ccu
> +      - allwinner,sun55i-a523-r-ccu
>  
>    reg:
>      maxItems: 1
>  
>    clocks:
>      minItems: 4
> -    maxItems: 4
> +    maxItems: 5

You just added these lines in previous patch, so squash these and make a
complete binding in one patch.

Otherwise you will get comment like:

>  
>    clock-names:
>      minItems: 4

This is not supposed to be here in previous patch...

> -    maxItems: 4
> +    maxItems: 5

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar  4 00:25:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 09:25:24 +0100
Subject: [PATCH v3 04/15] dt-bindings: clk: sunxi-ng: document Allwinner
 A523 CCU
In-Reply-To: <20250304012805.28594-5-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
 <20250304012805.28594-5-andre.przywara@arm.com>
Message-ID: <20250304-resilient-spiritual-crane-30d4e1@krzk-bin>

On Tue, Mar 04, 2025 at 01:27:54AM +0000, Andre Przywara wrote:
> The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> the main CCU.
> 
> The source clock list differs in some annoying details, and folding this
> into the existing Allwinner CCU clock binding document gets quite
> unwieldy, so create a new document for these CCUs.
> Add the new compatible string, along with the required input clock
> lists. This conditionally describes the input clock list, to make for
> an easier patch adding the other CCUs.
> 
> Also add the DT binding headers, listing all the clocks with their ID
> numbers.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../clock/allwinner,sun55i-a523-ccu.yaml      |  77 +++++++
>  include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
>  include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
>  3 files changed, 354 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
>  create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> new file mode 100644
> index 0000000000000..2eacaeaeabac7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> @@ -0,0 +1,77 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner A523 Clock Control Unit
> +
> +maintainers:
> +  - Andre Przywara <andre.przywara at arm.com>
> +
> +properties:
> +  "#clock-cells":
> +    const: 1
> +
> +  "#reset-cells":
> +    const: 1
> +
> +  compatible:
> +    enum:
> +      - allwinner,sun55i-a523-ccu
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    minItems: 4

Drop, redundant.

> +    maxItems: 4
> +
> +  clock-names:
> +    minItems: 4
> +    maxItems: 4

Drop both and instead you need to list the items.

> +
> +required:
> +  - "#clock-cells"
> +  - "#reset-cells"
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +
> +if:

Drop, you have here only one device, no need for if:then.

Best regards,
Krzysztof



From pierre.gondois at arm.com  Tue Mar  4 00:25:02 2025
From: pierre.gondois at arm.com (Pierre Gondois)
Date: Tue, 4 Mar 2025 09:25:02 +0100
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com> <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com> <Z8WPiOweOjFZqTwN@bogus>
 <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>
Message-ID: <2fdea4f6-db98-4dc7-947f-e19ee54d2c3c@arm.com>



On 3/3/25 15:40, Yicong Yang wrote:
> On 2025/3/3 19:16, Sudeep Holla wrote:
>> On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
>>> On 2/28/25 20:06, Sudeep Holla wrote:
>>>>>>
>>>>>> Ditto as previous patch, can get rid if it is default 1.
>>>>>>
>>>>>
>>>>> On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
>>>>> cpu_smt_num_threads uninitialized to UINT_MAX:
>>>>>
>>>>> smt/active:0
>>>>> smt/control:-1
>>>>>
>>>>> If cpu_smt_set_num_threads() is called:
>>>>> active:0
>>>>> control:notsupported
>>>>>
>>>>> So it might be slightly better to still initialize max_smt_thread_num.
>>>>>
>>>>
>>>> Sure, what I meant is to have max_smt_thread_num set to 1 by default is
>>>> that is what needed anyways and the above code does that now.
>>>>
>>>> Why not start with initialised to 1 instead ?
>>>> Of course some current logic needs to change around testing it for zero.
>>>>
>>>
>>> I think there would still be a way to check against the default value.
>>> If we have:
>>> unsigned int max_smt_thread_num = 1;
>>>
>>> then on a platform with 2 threads, the detection condition would trigger:
>>> xa_for_each(&hetero_cpu, hetero_id, entry) {
>>>      if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
>>>          pr_warn_once("Heterogeneous SMT topology is partly
>>>                        supported by SMT control\n");
>>>
>>> so we would need an additional variable:
>>> bool is_initialized = false;
>>
>> Sure, we could do that or skip the check if max_smt_thread_num == 1 ?
>>
>> I mean
>> 	if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)
>>

I think it will be problematic if we parse:
- first a CPU with 1 thread
- then a CPU with 2 threads

in that case we should detect the 'Heterogeneous SMT topology',
but we cannot because we don't know whether max_smt_thread_num=1
because 1 is the default value or we found a CPU with one thread.


From angelogioacchino.delregno at collabora.com  Tue Mar  4 00:33:30 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 09:33:30 +0100
Subject: [PATCH] rtc: mt6397: drop unused defines
In-Reply-To: <20250303223637.1135362-1-alexandre.belloni@bootlin.com>
References: <20250303223637.1135362-1-alexandre.belloni@bootlin.com>
Message-ID: <7aa89f17-c2d4-4143-a84d-4e736fdc6c27@collabora.com>

Il 03/03/25 23:36, alexandre.belloni at bootlin.com ha scritto:
> From: Alexandre Belloni <alexandre.belloni at bootlin.com>
> 
> RTC_NUM_YEARS has never been used, the other defines are not used since
> commit 34bbdc12d04e ("rtc: mt6359: Add RTC hardware range and add support
> for start-year")
> 
> Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From jorge.ramirez at oss.qualcomm.com  Tue Mar  4 00:36:00 2025
From: jorge.ramirez at oss.qualcomm.com (Jorge Ramirez)
Date: Tue, 4 Mar 2025 09:36:00 +0100
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
 <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org>
Message-ID: <Z8a7cMmxJuHIhgjo@trex>

On 03/03/25 18:13:20, Krzysztof Kozlowski wrote:
> On 08/02/2025 23:51, Vikram Sharma wrote:
> > The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
> > camera sensor. Enable IMX577 on the vision mezzanine.
> > 
> > An example media-ctl pipeline for the imx577 is:
> > 
> > media-ctl --reset
> > media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
> 
> AFAIU, camss does not support SRGGB10, but only SRGGB10P.
> 
> Based on tests reported on IRC I think this might not have been tested
> correctly.

I acquired SRGGB10P (10 bit packed) frames from the camera despite the
pipeline being set to SRGGB10 (16 bit) samples.

so something does not add up.

> 
> Best regards,
> Krzysztof


From Zoie.Lin at mediatek.com  Tue Mar  4 00:37:27 2025
From: Zoie.Lin at mediatek.com (=?utf-8?B?Wm9pZSBMaW4gKOael+emueWmoSk=?=)
Date: Tue, 4 Mar 2025 08:37:27 +0000
Subject: [PATCH v4 0/1] i2c: mediatek: add runtime PM operations and bus
 regulator control
In-Reply-To: <46621db1-6096-46af-b021-c919c1cae7ef@collabora.com>
References: <20250211144016.488001-1-zoie.lin@mediatek.com>
	 <46621db1-6096-46af-b021-c919c1cae7ef@collabora.com>
Message-ID: <ec77bb9478cd86a6737b92135170064970925b3c.camel@mediatek.com>


Hi Angelo,

Thank you for your suggestions regarding the autosuspend delay.

We understand the importance of balancing power efficiency and
responsiveness. Given the diversity of I2C devices connected
under each platform, it is indeed challenging to estimate an
appropriate delay time for testing.

Therefore, we would like to proceed with your initial suggestion
and set the autosuspend delay to 250ms. Based on our preliminary
tests, this adjustment appears to be a practical solution across 
our existing platforms.

Thank you.

Best regards,
Zoie


On Thu, 2025-02-13 at 12:57 +0100, AngeloGioacchino Del Regno wrote:
> 
> 
> Turning on and off regulators at start of transfer and end of
> transfer respectively
> is very expensive and, while it makes sense for power efficiency of
> the controller,
> it doesn't make sense for:
> 
> ? 1. Responsiveness (latency); and
> ? 2. Platform power efficiency at a whole.
> 
> As a start, just set the autosuspend delay to 250ms; this gives you
> at least time
> to bring up clocks and regulators and usually finish a transfer at
> 400KHz, giving
> you the chance to also get some more requests before autosuspend
> decides to, well,
> auto..suspend the device.
> 
> The right way of choosing an autosuspend delay a bit more precisely,
> though, for
> this device, would be to check the bus speed and calculate the
> autosuspend time
> accordingly.
> 
> Cheers,
> Angelo
> 
> 
> 


From linus.walleij at linaro.org  Tue Mar  4 00:38:44 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 4 Mar 2025 09:38:44 +0100
Subject: [PATCH] pinctrl: meson: fix pin input property for a4
In-Reply-To: <20250303-fix-a4-pinctl-v1-1-6579888b4272@amlogic.com>
References: <20250303-fix-a4-pinctl-v1-1-6579888b4272@amlogic.com>
Message-ID: <CACRpkdbbD6wLp1-m8WMnW68stz6U5GhxbJxcKAThYXWnH00u1Q@mail.gmail.com>

On Mon, Mar 3, 2025 at 8:53?AM Xianwei Zhao via B4 Relay
<devnull+xianwei.zhao.amlogic.com at kernel.org> wrote:

> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>
> The register of pin input attribute means the opposite.
> value of reigster meaning is 1 for input and 0 for output.
> So fix it.
>
> Fixes: 6e9be3abb78c ("pinctrl: Add driver support for Amlogic SoCs")
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>

Patch applied!

Yours,
Linus Walleij


From mripard at kernel.org  Tue Mar  4 00:21:43 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Tue, 4 Mar 2025 09:21:43 +0100
Subject: [PATCH v4 10/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250304-phy-sam-hdptx-bpc-v4-10-8657847c13f7@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-10-8657847c13f7@collabora.com>
Message-ID: <20250304-delicate-crazy-tuatara-5ea4d3@houat>

On Tue, Mar 04, 2025 at 03:44:09AM +0200, Cristian Ciocaltea wrote:
> @@ -1480,12 +1484,12 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
>  static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>  					   struct phy_configure_opts_hdmi *hdmi)
>  {
> -	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
> -		return -EINVAL;
> -
>  	u32 bit_rate = hdmi->tmds_char_rate / 100;
>  	int i;
>  
> +	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
> +		return -EINVAL;
> +
>  	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
>  		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
>  			break;

Why is that change needed?

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/e3350d17/attachment.sig>

From krzk at kernel.org  Tue Mar  4 00:40:21 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 09:40:21 +0100
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <Z8a7cMmxJuHIhgjo@trex>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
 <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org> <Z8a7cMmxJuHIhgjo@trex>
Message-ID: <baae2a56-5299-486f-acf1-14fe13fd2f81@kernel.org>

On 04/03/2025 09:36, Jorge Ramirez wrote:
> On 03/03/25 18:13:20, Krzysztof Kozlowski wrote:
>> On 08/02/2025 23:51, Vikram Sharma wrote:
>>> The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
>>> camera sensor. Enable IMX577 on the vision mezzanine.
>>>
>>> An example media-ctl pipeline for the imx577 is:
>>>
>>> media-ctl --reset
>>> media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
>>
>> AFAIU, camss does not support SRGGB10, but only SRGGB10P.
>>
>> Based on tests reported on IRC I think this might not have been tested
>> correctly.
> 
> I acquired SRGGB10P (10 bit packed) frames from the camera despite the
> pipeline being set to SRGGB10 (16 bit) samples.
> 
> so something does not add up.

Then the commands are actually correct, just the camss or media behave
here a bit unexpected?

Best regards,
Krzysztof


From menglong8.dong at gmail.com  Tue Mar  4 00:41:29 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Tue, 4 Mar 2025 16:41:29 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
Message-ID: <CADxym3bS6XdGFhKeEm5TKD-_ubEQB+yTrd=7_L_CDn4xthe-Vg@mail.gmail.com>

On Tue, Mar 4, 2025 at 3:47?PM Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> On Tue, Mar 4, 2025 at 2:16?PM Peter Zijlstra <peterz at infradead.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 06:38:53AM +0100, Peter Zijlstra wrote:
> > > On Tue, Mar 04, 2025 at 09:10:12AM +0800, Menglong Dong wrote:
> > > > Hello, sorry that I forgot to add something to the changelog. In fact,
> > > > I don't add extra 5-bytes anymore, which you can see in the 3rd patch.
> > > >
> > > > The thing is that we can't add extra 5-bytes if CFI is enabled. Without
> > > > CFI, we can make the padding space any value, such as 5-bytes, and
> > > > the layout will be like this:
> > > >
> > > > __align:
> > > >   nop
> > > >   nop
> > > >   nop
> > > >   nop
> > > >   nop
> > > > foo: -- __align +5
> > > >
> > > > However, the CFI will always make the cfi insn 16-bytes aligned. When
> > > > we set the FUNCTION_PADDING_BYTES to (11 + 5), the layout will be
> > > > like this:
> > > >
> > > > __cfi_foo:
> > > >   nop (11)
> > > >   mov $0x12345678, %reg
> > > >   nop (16)
> > > > foo:
> > > >
> > > > and the padding space is 32-bytes actually. So, we can just select
> > > > FUNCTION_ALIGNMENT_32B instead, which makes the padding
> > > > space 32-bytes too, and have the following layout:
> > > >
> > > > __cfi_foo:
> > > >   mov $0x12345678, %reg
> > > >   nop (27)
> > > > foo:
> > >
> > > *blink*, wtf is clang smoking.
> > >
> > > I mean, you're right, this is what it is doing, but that is somewhat
> > > unexpected. Let me go look at clang source, this is insane.
> >
> > Bah, this is because assemblers are stupid :/
> >
> > There is no way to tell them to have foo aligned such that there are at
> > least N bytes free before it.
> >
> > So what kCFI ends up having to do is align the __cfi symbol to the
> > function alignment, and then stuff enough nops in to make the real
> > symbol meet alignment.
> >
> > And the end result is utter insanity.
> >
> > I mean, look at this:
> >
> >       50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
> >       56:       66 2e 0f 1f 84 00 00 00 00 00   cs nopw 0x0(%rax,%rax,1)
> >
> > 0000000000000060 <__cfi___probestub_initcall_level>:
> >       60:       90                      nop
> >       61:       90                      nop
> >       62:       90                      nop
> >       63:       90                      nop
> >       64:       90                      nop
> >       65:       90                      nop
> >       66:       90                      nop
> >       67:       90                      nop
> >       68:       90                      nop
> >       69:       90                      nop
> >       6a:       90                      nop
> >       6b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax
> >
> > 0000000000000070 <__probestub_initcall_level>:
> >       70:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4
> >
> >
> > That's 21 bytes wasted, for no reason other than that asm doesn't have a
> > directive to say: get me a place that is M before N alignment.
> >
> > Because ideally the whole above thing would look like:
> >
> >       50:       2e e9 00 00 00 00       cs jmp 56 <__traceiter_initcall_level+0x46>     52: R_X86_64_PLT32      __x86_return_thunk-0x4
> >       56:       66 2e 0f 1f 84          cs nopw (%rax,%rax,1)
> >
> > 000000000000005b <__cfi___probestub_initcall_level>:
> >       5b:       b8 b1 fd 66 f9          mov    $0xf966fdb1,%eax
> >
> > 0000000000000060 <__probestub_initcall_level>:
> >       60:       2e e9 00 00 00 00       cs jmp 76 <__probestub_initcall_level+0x6>      72: R_X86_64_PLT32      __x86_return_thunk-0x4
>
> Hi, peter. Thank you for the testing, which is quite helpful
> to understand the whole thing.
>
> I was surprised at this too. Without CALL_PADDING, the cfi is
> nop(11) + mov; with CALL_PADDING, the cfi is mov + nop(11),
> which is weird, as it seems that we can select CALL_PADDING if
> CFI_CLANG to make things consistent. And I  thought that it is
> designed to be this for some reasons :/
>
> Hmm......so what should we do now? Accept and bear it,
> or do something different?
>
> I'm good at clang, so the solution that I can think of is how to

*not good at*

> bear it :/
>
> According to my testing, the text size will increase:
>
> ~2.2% if we make FUNCTION_PADDING_BYTES 27 and select
> FUNCTION_ALIGNMENT_16B.
>
> ~3.5% if we make FUNCTION_PADDING_BYTES 27 and select
> FUNCTION_ALIGNMENT_32B.
>
> We don't have to select FUNCTION_ALIGNMENT_32B, so the
> worst case is to increase ~2.2%.
>
> What do you think?
>
> Thanks!
> Menglong Dong
>
> >
> >
> >


From pjaroszynski at nvidia.com  Tue Mar  4 00:51:27 2025
From: pjaroszynski at nvidia.com (Piotr Jaroszynski)
Date: Tue,  4 Mar 2025 00:51:27 -0800
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
Message-ID: <20250304085127.2238030-1-pjaroszynski@nvidia.com>

Update the __flush_tlb_range_op macro not to modify its parameters as
these are unexepcted semantics. In practice, this fixes the call to
mmu_notifier_arch_invalidate_secondary_tlbs() in
__flush_tlb_range_nosync() to use the correct range instead of an empty
range with start=end. The empty range was (un)lucky as it results in
taking the invalidate-all path that doesn't cause correctness issues,
but can certainly result in suboptimal perf.

This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
invalidate_range() when invalidating TLBs") when the call to the
notifiers was added to __flush_tlb_range(). It predates the addition of
the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") that made the
bug hard to spot.

Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Alistair Popple <apopple at nvidia.com>
Cc: Raghavendra Rao Ananta <rananta at google.com>
Cc: SeongJae Park <sj at kernel.org>
Cc: Jason Gunthorpe <jgg at nvidia.com>
Cc: John Hubbard <jhubbard at nvidia.com>
Cc: Nicolin Chen <nicolinc at nvidia.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: linux-mm at kvack.org
Cc: linux-kernel at vger.kernel.org
Cc: stable at vger.kernel.org
---
 arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index bc94e036a26b..8104aee4f9a0 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
 #define __flush_tlb_range_op(op, start, pages, stride,			\
 				asid, tlb_level, tlbi_user, lpa2)	\
 do {									\
+	typeof(start) __flush_start = start;				\
+	typeof(pages) __flush_pages = pages;				\
 	int num = 0;							\
 	int scale = 3;							\
 	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 	unsigned long addr;						\
 									\
-	while (pages > 0) {						\
+	while (__flush_pages > 0) {					\
 		if (!system_supports_tlb_range() ||			\
-		    pages == 1 ||					\
-		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
-			addr = __TLBI_VADDR(start, asid);		\
+		    __flush_pages == 1 ||				\
+		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
+			addr = __TLBI_VADDR(__flush_start, asid);	\
 			__tlbi_level(op, addr, tlb_level);		\
 			if (tlbi_user)					\
 				__tlbi_user_level(op, addr, tlb_level);	\
-			start += stride;				\
-			pages -= stride >> PAGE_SHIFT;			\
+			__flush_start += stride;			\
+			__flush_pages -= stride >> PAGE_SHIFT;		\
 			continue;					\
 		}							\
 									\
-		num = __TLBI_RANGE_NUM(pages, scale);			\
+		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
+			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 						scale, num, tlb_level);	\
 			__tlbi(r##op, addr);				\
 			if (tlbi_user)					\
 				__tlbi_user(r##op, addr);		\
-			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			pages -= __TLBI_RANGE_PAGES(num, scale);	\
+			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 		}							\
 		scale--;						\
 	}								\

base-commit: 99fa936e8e4f117d62f229003c9799686f74cebc
-- 
2.22.1.7.gac84d6e93c.dirty



From lorenzo at kernel.org  Tue Mar  4 00:50:23 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 04 Mar 2025 09:50:23 +0100
Subject: [PATCH net] net: dsa: mt7530: Fix traffic flooding for MMIO
 devices
Message-ID: <20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org>

On MMIO devices (e.g. MT7988 or EN7581) unicast traffic received on lanX
port is flooded on all other user ports if the DSA switch is configured
without VLAN support since PORT_MATRIX in PCR regs contains all user
ports. Similar to MDIO devices (e.g. MT7530 and MT7531) fix the issue
defining default VLAN-ID 0 for MT7530 MMIO devices.

Fixes: 110c18bfed414 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch")
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/dsa/mt7530.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 1c83af805209cae40c56138fa8f72261e396f58c..5883eb93efb11423bec260a11ff8b60cfff1fd2c 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2591,7 +2591,8 @@ mt7531_setup_common(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	return 0;
+	/* Setup VLAN ID 0 for VLAN-unaware bridges */
+	return mt7530_setup_vlan0(priv);
 }
 
 static int
@@ -2687,11 +2688,6 @@ mt7531_setup(struct dsa_switch *ds)
 	if (ret)
 		return ret;
 
-	/* Setup VLAN ID 0 for VLAN-unaware bridges */
-	ret = mt7530_setup_vlan0(priv);
-	if (ret)
-		return ret;
-
 	ds->assisted_learning_on_cpu_port = true;
 	ds->mtu_enforcement_ingress = true;
 

---
base-commit: 64e6a754d33d31aa844b3ee66fb93ac84ca1565e
change-id: 20250304-mt7988-flooding-fix-cdfec66a0640

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From jorge.ramirez at oss.qualcomm.com  Tue Mar  4 00:51:26 2025
From: jorge.ramirez at oss.qualcomm.com (Jorge Ramirez)
Date: Tue, 4 Mar 2025 09:51:26 +0100
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <baae2a56-5299-486f-acf1-14fe13fd2f81@kernel.org>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
 <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org>
 <Z8a7cMmxJuHIhgjo@trex>
 <baae2a56-5299-486f-acf1-14fe13fd2f81@kernel.org>
Message-ID: <Z8a/Dk7zjZ7RQT2/@trex>

On 04/03/25 09:40:21, Krzysztof Kozlowski wrote:
> On 04/03/2025 09:36, Jorge Ramirez wrote:
> > On 03/03/25 18:13:20, Krzysztof Kozlowski wrote:
> >> On 08/02/2025 23:51, Vikram Sharma wrote:
> >>> The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
> >>> camera sensor. Enable IMX577 on the vision mezzanine.
> >>>
> >>> An example media-ctl pipeline for the imx577 is:
> >>>
> >>> media-ctl --reset
> >>> media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
> >>
> >> AFAIU, camss does not support SRGGB10, but only SRGGB10P.
> >>
> >> Based on tests reported on IRC I think this might not have been tested
> >> correctly.
> > 
> > I acquired SRGGB10P (10 bit packed) frames from the camera despite the
> > pipeline being set to SRGGB10 (16 bit) samples.
> > 
> > so something does not add up.
> 
> Then the commands are actually correct, just the camss or media behave
> here a bit unexpected?
>

setting the pipeline (CSI) as SRGGB10 (16 bit samples) as per below

media-ctl --reset
media-ctl -v -V '"imx577 '19-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
media-ctl -V '"msm_csiphy3":0[fmt:SRGGB10/4056x3040]'
media-ctl -V '"msm_csid0":0[fmt:SRGGB10/4056x3040]'
media-ctl -V '"msm_vfe0_rdi0":0[fmt:SRGGB10/4056x3040]'
media-ctl -l '"msm_csiphy3":1->"msm_csid0":0[1]'
media-ctl -l '"msm_csid0":1->"msm_vfe0_rdi0":0[1]'

allows to capture SRGGB10P samples (frames-xxxx.bin files contain 10 bit samples for the size)

 ==> yavta -B capture-mplane -c -I -n 5 -f SRGGB10P -s 4056x3040 -F /dev/video0


shouldnt the CSI need to be set to SRGGB10P instead?


> Best regards,
> Krzysztof



From maxime.chevallier at bootlin.com  Tue Mar  4 01:52:39 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Tue, 4 Mar 2025 10:52:39 +0100
Subject: [PATCH net v2] net: ethtool: netlink: Allow NULL nlattrs when
 getting a phy_device
In-Reply-To: <20250303161024.43969294@kernel.org>
References: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
	<20250303161024.43969294@kernel.org>
Message-ID: <20250304105239.747500be@fedora.home>

On Mon, 3 Mar 2025 16:10:24 -0800
Jakub Kicinski <kuba at kernel.org> wrote:

> On Sat,  1 Mar 2025 15:11:13 +0100 Maxime Chevallier wrote:
> > ethnl_req_get_phydev() is used to lookup a phy_device, in the case an
> > ethtool netlink command targets a specific phydev within a netdev's
> > topology.
> > 
> > It takes as a parameter a const struct nlattr *header that's used for
> > error handling :
> > 
> >        if (!phydev) {
> >                NL_SET_ERR_MSG_ATTR(extack, header,
> >                                    "no phy matching phyindex");
> >                return ERR_PTR(-ENODEV);
> >        }
> > 
> > In the notify path after a ->set operation however, there's no request
> > attributes available.
> > 
> > The typical callsite for the above function looks like:
> > 
> > 	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_XXX_HEADER],
> > 				      info->extack);
> > 
> > So, when tb is NULL (such as in the ethnl notify path), we have a nice
> > crash.
> > 
> > It turns out that there's only the PLCA command that is in that case, as
> > the other phydev-specific commands don't have a notification.
> > 
> > This commit fixes the crash by passing the cmd index and the nlattr
> > array separately, allowing NULL-checking it directly inside the helper.
> > 
> > Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some commands")
> > Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>  
> 
> Well, this alone doesn't look too bad.. :) Hopefully we can address
> adding more suitable handlers for phy ops in net-next.

Yeah I'm cooking something to improve on that, and I have also dusted
off a netdevsim patch I had written back when working on the
phy_link_topology that adds very very basic PHY support so that we can
start covering all these commands with proper tests. I'll hopefully send
something in the coming week or so.

> Didn't someone report this, tho? I vaguely remember seeing an email,
> unless they said they don't want to be credited maybe we should add
> a Reported-by tag? You can post it in reply, no need to repost 
> the patch.

Parthiban reported this without CC: netdev, but I think it's fair to
add :

Reported-by: Parthiban Veerasooran <parthiban.veerasooran at microchip.com>

I didn't include it in the first place because checkpatch complained
about a reported-by tag without a "Closes:", which we don't have
because of the private reporting :)

Thanks Jakub,

Maxime


From vincenc.turek at commetrax.com  Tue Mar  4 00:56:19 2025
From: vincenc.turek at commetrax.com (Vincenc Turek)
Date: Tue,  4 Mar 2025 08:56:19 GMT
Subject: Message from production
Message-ID: <20250304084500-0.1.87.ney5.0.36epr14hoy@commetrax.com>

Hello,

We specialize in manufacturing packaging for the food industry, such as those for ketchup, mustard, and sauces.

We also offer solutions for household and construction chemicals ? packaging in various sizes and shapes to meet your requirements.

Our products are durable and resistant to damage, ensuring faster and hassle-free transportation of your goods.

How about a short presentation of our offer?


Best regards
Vincenc Turek


From vdonnefort at google.com  Tue Mar  4 01:03:26 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Tue, 4 Mar 2025 09:03:26 +0000
Subject: [PATCH] KVM: arm64: Count pKVM stage-2 usage in secondary
 pagetable stats
In-Reply-To: <Z8Ycq3d7O8_3fozk@linux.dev>
References: <20250228121355.1377891-1-vdonnefort@google.com>
 <Z8Ycq3d7O8_3fozk@linux.dev>
Message-ID: <Z8bB3sr7X4RRV0CN@google.com>

On Mon, Mar 03, 2025 at 01:18:35PM -0800, Oliver Upton wrote:
> On Fri, Feb 28, 2025 at 12:13:55PM +0000, Vincent Donnefort wrote:
> > Count the pages used by pKVM for the guest stage-2 in memory stats under
> > secondary pagetable stats, similarly to what the VHE mode does.
> > 
> > Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> > 
> > diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> > index 1f55b0c7b11d..c2e022c41313 100644
> > --- a/arch/arm64/kvm/mmu.c
> > +++ b/arch/arm64/kvm/mmu.c
> > @@ -1088,12 +1088,18 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
> >  
> >  static void hyp_mc_free_fn(void *addr, void *unused)
> >  {
> > +	kvm_account_pgtable_pages(addr, -1);
> >  	free_page((unsigned long)addr);
> >  }
> 
> Don't we drain more than just stage-2 page tables into the teardown_mc
> (e.g. vcpu structs)?

Sigh, yes we do. I've left behind some changes we have in our Android branches.
Let me respin a proper version :-\ 

> 
> Thanks,
> Oliver


From lkp at intel.com  Tue Mar  4 01:07:44 2025
From: lkp at intel.com (kernel test robot)
Date: Tue, 4 Mar 2025 17:07:44 +0800
Subject: [PATCH 02/15] gpio: adnp: use lock guards for the I2C lock
In-Reply-To: <20250303-gpiochip-set-conversion-v1-2-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-2-1d5cceeebf8b@linaro.org>
Message-ID: <202503041612.G8O0Bdrg-lkp@intel.com>

Hi Bartosz,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 9778568dede2166c7bd124d473f9ec365f782935]

url:    https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/gpio-74x164-use-new-line-value-setter-callbacks/20250303-212738
base:   9778568dede2166c7bd124d473f9ec365f782935
patch link:    https://lore.kernel.org/r/20250303-gpiochip-set-conversion-v1-2-1d5cceeebf8b%40linaro.org
patch subject: [PATCH 02/15] gpio: adnp: use lock guards for the I2C lock
config: x86_64-buildonly-randconfig-001-20250304 (https://download.01.org/0day-ci/archive/20250304/202503041612.G8O0Bdrg-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250304/202503041612.G8O0Bdrg-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503041612.G8O0Bdrg-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-adnp.c:241:8: warning: variable 'isr' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
     241 |                         if (err < 0)
         |                             ^~~~~~~
   drivers/gpio/gpio-adnp.c:265:14: note: uninitialized use occurs here
     265 |                 pending &= isr & ier;
         |                            ^~~
   drivers/gpio/gpio-adnp.c:241:4: note: remove the 'if' if its condition is always false
     241 |                         if (err < 0)
         |                         ^~~~~~~~~~~~
     242 |                                 continue;
         |                                 ~~~~~~~~
   drivers/gpio/gpio-adnp.c:235:25: note: initialize the variable 'isr' to silence this warning
     235 |                 u8 changed, level, isr, ier;
         |                                       ^
         |                                        = '\0'
>> drivers/gpio/gpio-adnp.c:245:8: warning: variable 'ier' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
     245 |                         if (err < 0)
         |                             ^~~~~~~
   drivers/gpio/gpio-adnp.c:265:20: note: uninitialized use occurs here
     265 |                 pending &= isr & ier;
         |                                  ^~~
   drivers/gpio/gpio-adnp.c:245:4: note: remove the 'if' if its condition is always false
     245 |                         if (err < 0)
         |                         ^~~~~~~~~~~~
     246 |                                 continue;
         |                                 ~~~~~~~~
   drivers/gpio/gpio-adnp.c:241:8: warning: variable 'ier' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
     241 |                         if (err < 0)
         |                             ^~~~~~~
   drivers/gpio/gpio-adnp.c:265:20: note: uninitialized use occurs here
     265 |                 pending &= isr & ier;
         |                                  ^~~
   drivers/gpio/gpio-adnp.c:241:4: note: remove the 'if' if its condition is always false
     241 |                         if (err < 0)
         |                         ^~~~~~~~~~~~
     242 |                                 continue;
         |                                 ~~~~~~~~
   drivers/gpio/gpio-adnp.c:235:30: note: initialize the variable 'ier' to silence this warning
     235 |                 u8 changed, level, isr, ier;
         |                                            ^
         |                                             = '\0'
   3 warnings generated.


vim +241 drivers/gpio/gpio-adnp.c

   225	
   226	static irqreturn_t adnp_irq(int irq, void *data)
   227	{
   228		struct adnp *adnp = data;
   229		unsigned int num_regs, i;
   230	
   231		num_regs = 1 << adnp->reg_shift;
   232	
   233		for (i = 0; i < num_regs; i++) {
   234			unsigned int base = i << adnp->reg_shift, bit;
   235			u8 changed, level, isr, ier;
   236			unsigned long pending;
   237			int err;
   238	
   239			scoped_guard(mutex, &adnp->i2c_lock) {
   240				err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
 > 241				if (err < 0)
   242					continue;
   243	
   244				err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
 > 245				if (err < 0)
   246					continue;
   247	
   248				err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
   249				if (err < 0)
   250					continue;
   251			}
   252	
   253			/* determine pins that changed levels */
   254			changed = level ^ adnp->irq_level[i];
   255	
   256			/* compute edge-triggered interrupts */
   257			pending = changed & ((adnp->irq_fall[i] & ~level) |
   258					     (adnp->irq_rise[i] & level));
   259	
   260			/* add in level-triggered interrupts */
   261			pending |= (adnp->irq_high[i] & level) |
   262				   (adnp->irq_low[i] & ~level);
   263	
   264			/* mask out non-pending and disabled interrupts */
   265			pending &= isr & ier;
   266	
   267			for_each_set_bit(bit, &pending, 8) {
   268				unsigned int child_irq;
   269				child_irq = irq_find_mapping(adnp->gpio.irq.domain,
   270							     base + bit);
   271				handle_nested_irq(child_irq);
   272			}
   273		}
   274	
   275		return IRQ_HANDLED;
   276	}
   277	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From ivo.ivanov.ivanov1 at gmail.com  Tue Mar  4 01:09:31 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Tue, 4 Mar 2025 11:09:31 +0200
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <027decb4-3fa9-40a5-9cf4-65f9a69b4566@kernel.org>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
 <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
 <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>
 <027decb4-3fa9-40a5-9cf4-65f9a69b4566@kernel.org>
Message-ID: <21460de5-76a0-4576-a7e6-f4873e40de48@gmail.com>

On 3/4/25 09:21, Krzysztof Kozlowski wrote:
> On 03/03/2025 18:18, Ivaylo Ivanov wrote:
>> On 3/3/25 09:24, Krzysztof Kozlowski wrote:
>>> On 02/03/2025 10:16, Ivaylo Ivanov wrote:
>>>> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>>>>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>>>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>>>>
>>>>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>> ---
>>>>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>>>>  1 file changed, 76 insertions(+)
>>>>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>> You have undocumented dependencies which prevent merging this file.
>>>>>>> First, dependencies have to be clearly expressed.
>>>>>> They are, in the cover letter.
>>>>> Where? I read it twice. Dependencies is the most important thing and
>>>>> should scream at beginning of the cover letter, so if you bury them
>>>>> somewhere deep it also would not matter - just like they were missing.
>>>>>
>>>>>>> Second, you should
>>>>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>>>>> be merged for current release (just use clocks with long names, without IDs).
>>>>>> Sure
>>>>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>> new file mode 100644
>>>>>>>> index 000000000..7d879ec8b
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>> @@ -0,0 +1,76 @@
>>>>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>>>>> +%YAML 1.2
>>>>>>>> +---
>>>>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>>> +
>>>>>>>> +title: Exynos2200 USB controller PHY
>>>>>>>> +
>>>>>>>> +maintainers:
>>>>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>> +
>>>>>>>> +description:
>>>>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>>>>> It's not (I think). There's a few reasons I've decided to make this separate
>>>>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>>>>
>>>>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>>>>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>>>>> at diagram - they call it phy controller.
>>>> Ughm. What? So in most exynos cases, there's a combination of multiple phys?
>>>>>> for them, and all that is needed from it is to disable HWACG, assert/
>>>>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>>>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>>>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>>>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>>>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>>>>> Does it mean there is no USB DRD phy controller as before?
>>>>>
>>>>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
>>>> So...
>>>>
>>>> DWC3 -> USBDRD (USBCON) -> PHYs?
>>> No, drop last phy. You just wrote the same as me - two phys, because
>>> usbdrd is the phy. In all existing designs there is no such controllable
>>> object from the point of view of operating system.
>> What? Per my understanding, the phy property should refer to whatever is
>> is connected to dwc3 UTMI. In this case it's the so-called USBDRD phy (called
>> usbcon in downstream). Considering that the eUSB2 IP definitely also has UTMI
>> that has to be connected to something, doesn't that mean we have clearly
> The entire point is that eUSB2 is connected to DWC3, no? That's exactly
> how it is done for example on Qualcomm SoC. Otherwise you claim that
> DWC3 controls one phy, which controls another phy which controls UTMI...

But where does the USBCON fit? Is it just a side controller? Why's it needed
in the first place? This is what I don't understand.

>
>> separated hardware blocks? Now, I guess one could argue that this USBCON
>> hardware block could be classified as a syscon. But I don't see the problem
>> with the current binding description, nor the modelling, as it represents
>> how the hardware is (unless I've gotten it completely wrong).
> It is the first time you use argument that it represents how the
> hardware is and this is what we actually disagree. It is not like that.
> You do not have chain of phys. Just look at any USB 3.0 DRD DWC diagram
> from any Samsung SoC: where would you squeeze these two phys in relation
> to what is called there "USB 3.0 PHY" which would be the third phy (!!!).

Yeah, my point was that it was different from any previous design. Now,
I don't know if it's actually theoretically possible to design it like so. It's
hard to just guess how the hardware is designed without having access
to die shots, documentations or even just schematics.

Let's make it clear now, the changes your request are to document USBCON
in the existing exynos binding, as well as to correct all explanations of how
this block functions, right?

Best regards,
Ivaylo

>
> Best regards,
> Krzysztof



From dmitry.baryshkov at linaro.org  Tue Mar  4 01:18:47 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Tue, 4 Mar 2025 11:18:47 +0200
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <7c4a1e3e.6be8.1956003303a.Coremail.andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
 <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>
 <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>
 <7c4a1e3e.6be8.1956003303a.Coremail.andyshrk@163.com>
Message-ID: <g3d2wjkr2igmnreu7eujl32s4lofupxl7i2w4ub4djztlni3td@g35vrcyr5bis>

On Tue, Mar 04, 2025 at 03:16:16PM +0800, Andy Yan wrote:
> 
> Hi Dmitry,
> 
> ? 2025-03-03 00:21:06?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
> >On Sun, Mar 02, 2025 at 06:34:22PM +0800, Andy Yan wrote:
> >> 
> >> 
> >> Hi Dmitry?
> >>    Thank you for your review?
> >>    Please also review my inline reply.
> >>       
> >> ? 2025-03-02 02:14:19?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
> >> >On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
> >> >> From: Andy Yan <andy.yan at rock-chips.com>
> >> >> 
> >> >> The DW DP TX Controller is compliant with the DisplayPort Specification
> >> >> Version 1.4 with the following features:
> >> >> 
> >> >> * DisplayPort 1.4a
> >> >> * Main Link: 1/2/4 lanes
> >> >> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
> >> >> * AUX channel 1Mbps
> >> >> * Single Stream Transport(SST)
> >> >> * Multistream Transport (MST)
> >> >> *?Type-C support (alternate mode)
> >> >> * HDCP 2.2, HDCP 1.3
> >> >> * Supports up to 8/10 bits per color component
> >> >> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
> >> >> * Pixel clock up to 594MHz
> >> >> * I2S, SPDIF audio interface
> >> >> 
> >> >> Add library with common helpers to make it can be shared with
> >> >> other SoC.
> >> >> 
> >> >> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> >> >> 
> >> >> drm/bridge: cleanup
> >> >
> >> >Stray line?
> >> 
> >> Sorry, will be removed.
> >> 
> >> >
> >> >> 
> >> >> ---
> 
> ........
> 
> >> >> +static int dw_dp_link_power_up(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	int ret;
> >> >> +	u8 value;
> >> >> +
> >> >> +	if (link->revision < DP_DPCD_REV_11)
> >> >> +		return 0;
> >> >> +
> >> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> >> >> +	if (ret < 0)
> >> >> +		return ret;
> >> >> +
> >> >> +	value &= ~DP_SET_POWER_MASK;
> >> >> +	value |= DP_SET_POWER_D0;
> >> >> +
> >> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> >> >> +	if (ret < 0)
> >> >> +		return ret;
> >> >> +
> >> >> +	usleep_range(1000, 2000);
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_link_power_down(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	int ret;
> >> >> +	u8 value;
> >> >> +
> >> >> +	if (link->revision < DP_DPCD_REV_11)
> >> >> +		return 0;
> >> >> +
> >> >> +	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
> >> >> +	if (ret < 0)
> >> >> +		return ret;
> >> >> +
> >> >> +	value &= ~DP_SET_POWER_MASK;
> >> >> +	value |= DP_SET_POWER_D3;
> >> >> +
> >> >> +	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
> >> >> +	if (ret < 0)
> >> >> +		return ret;
> >> >> +
> >> >
> >> >Would you please mind pulling these two functions to DRM DP helpers?
> >> >There are enough users to make this into a common code.
> >> 
> >> Yes, when developing this patch, I had the same realization. 
> >> The processing logic for MSM/Cadence/ANX6345/tegra follows
> >> a similar approach.
> >> I had originally planned to defer this refactoring until the series of patches is accepted. 
> >> Additionally, I have other pending tasks in my TODO list, such as fully decoupling the 
> >> bridge driver and encoder/connector components across all Rockchip platforms?
> >> But I prioritize completing these foundational features before go to next steps,
> >> Is this acceptable ?
> >
> >You can add necessary helpers as one of the first patches in the
> >series. Convert one or several platforms that use drm-misc (i.e. not
> >MSM, AMD, i915, nouveau) and send conversion of the rest of the
> >platforms as followups.
> 
> If  pull these two functions to DRM DP helpers, I think they should be
> named as drm_dp_link_power_up/down ?.

I think so.

> I found that tegra/dp.c already use this name, so I need to do a symbols rename
> for tegra first to avoid build error like[2].
> 
> Can the patch for Tegra be merged  through  drm-misc branch?

Yes, when drm_dp_link code was moved to the Tegra driver, nobody renamed
those symboles. Maybe in the hope of moving them back. Please rename
those symbols.

> 
> 
> [2]https://lore.kernel.org/oe-kbuild-all/202410250305.UHKDhtxy-lkp at intel.com/
> >
> >> 
> >> >
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >> >> +				 const struct drm_dp_desc *desc)
> >> >> +{
> >> >> +	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
> >> >> +	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
> >> >> +	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);
> >> >
> >> >
> >> >isn't it drm_dp_read_sink_count_cap() ?
> >> 
> >> I will have a try, since this drm_dp_read_sink_count_cap requires a connector parameter, 
> >> I need to figure out how to get the connector here.
> >
> >Maybe Maxime's series will you here, see [1].
> >
> >[1] https://lore.kernel.org/dri-devel/20250225-bridge-connector-v4-4-7ecb07b09cad at kernel.org/
> >
> >> 
> >> >
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_link_parse(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	u8 dpcd;
> >> >> +	int ret;
> 
> ......
> 
> >> >> +		break;
> >> >> +	}
> >> >> +
> >> >> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
> >> >> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
> >> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
> >> >> +	} else {
> >> >> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
> >> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> >> >> +	}
> >> >> +
> >> >> +	vsc.bpc = video->bpc;
> >> >> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
> >> >> +
> >> >> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
> >> >> +
> >> >> +	return dw_dp_send_sdp(dp, &sdp);
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
> >> >> +{
> >> >> +	switch (pixel_mode) {
> >> >> +	case DW_DP_MP_SINGLE_PIXEL:
> >> >> +	case DW_DP_MP_DUAL_PIXEL:
> >> >> +	case DW_DP_MP_QUAD_PIXEL:
> >> >> +		break;
> >> >> +	default:
> >> >> +		return -EINVAL;
> >> >
> >> >Is it possible?
> >> 
> >> This IP is configurable for single/dual/quad pixel modes?
> >> It's  quad pixel mode on rk3588 and dual pixel mode on rk3576,
> >> so we add this check here.
> >
> >My question was slightly different: is it possible to end up here in the
> >'default' branch?
> 
> Sorry, I think I didn't get your key point here.
> If someone give a invalid pixe mode(not any of SINGLE/DUAL/QUAD_PIXEL ), 
> then we go to default branch return -ENVIAL,  then the dp_bridge enable stop.
> This is what we want here.
> 
> 
> 
> 
> >
> >> 
> >> 
> >> >
> >> >> +	}
> >> >> +
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
> >> >> +			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	struct dw_dp_video *video = &dp->video;
> >> >> +
> >> >> +	if (!link->vsc_sdp_supported)
> >> >> +		return false;
> >> >> +
> >> >> +	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> >> +		return true;
> >> >> +
> >> >> +	return false;
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
> >> >> +			       u16 vstart, u16 hstart)
> >> >> +{
> >> >> +	u16 misc = 0;
> >> >> +
> >> >> +	if (dw_dp_video_need_vsc_sdp(dp))
> >> >> +		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
> >> >> +
> >> >> +	switch (color_format) {
> >> >> +	case DRM_COLOR_FORMAT_RGB444:
> >> >> +		misc |= DP_MSA_MISC_COLOR_RGB;
> >> >> +		break;
> >> >> +	case DRM_COLOR_FORMAT_YCBCR444:
> >> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
> >> >> +		break;
> >> >> +	case DRM_COLOR_FORMAT_YCBCR422:
> >> >> +		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
> >> >> +		break;
> >> >> +	case DRM_COLOR_FORMAT_YCBCR420:
> >> >> +		break;
> >> >> +	default:
> >> >> +		return -EINVAL;
> >> >> +	}
> >> >> +
> >> >> +	switch (bpc) {
> >> >> +	case 6:
> >> >> +		misc |= DP_MSA_MISC_6_BPC;
> >> >> +		break;
> >> >> +	case 8:
> >> >> +		misc |= DP_MSA_MISC_8_BPC;
> >> >> +		break;
> >> >> +	case 10:
> >> >> +		misc |= DP_MSA_MISC_10_BPC;
> >> >> +		break;
> >> >> +	case 12:
> >> >> +		misc |= DP_MSA_MISC_12_BPC;
> >> >> +		break;
> >> >> +	case 16:
> >> >> +		misc |= DP_MSA_MISC_16_BPC;
> >> >> +		break;
> >> >> +	default:
> >> >> +		return -EINVAL;
> >> >> +	}
> >> >> +
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
> >> >> +		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_video_disable(struct dw_dp *dp)
> >> >> +{
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> >> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_video_enable(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_video *video = &dp->video;
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	struct drm_display_mode *mode = &video->mode;
> >> >> +	u8 color_format = video->color_format;
> >> >> +	u8 bpc = video->bpc;
> >> >> +	u8 pixel_mode = video->pixel_mode;
> >> >> +	u8 bpp = video->bpp, init_threshold, vic;
> >> >> +	u32 hactive, hblank, h_sync_width, h_front_porch;
> >> >> +	u32 vactive, vblank, v_sync_width, v_front_porch;
> >> >> +	u32 vstart = mode->vtotal - mode->vsync_start;
> >> >> +	u32 hstart = mode->htotal - mode->hsync_start;
> >> >> +	u32 peak_stream_bandwidth, link_bandwidth;
> >> >> +	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
> >> >> +	u32 ts, hblank_interval;
> >> >> +	u32 value;
> >> >> +	int ret;
> >> >> +
> >> >> +	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
> >> >> +	if (ret)
> >> >> +		return ret;
> >> >> +
> >> >> +	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
> >> >> +	if (ret)
> >> >> +		return ret;
> >> >> +
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
> >> >> +			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
> >> >> +
> >> >> +	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
> >> >> +	value = 0;
> >> >> +	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
> >> >> +		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
> >> >> +	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
> >> >> +		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
> >> >> +	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_CONFIG1 register */
> >> >> +	hactive = mode->hdisplay;
> >> >> +	hblank = mode->htotal - mode->hdisplay;
> >> >> +	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
> >> >> +	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> >> >> +		value |= FIELD_PREP(I_P, 1);
> >> >> +	vic = drm_match_cea_mode(mode);
> >> >> +	if (vic == 5 || vic == 6 || vic == 7 ||
> >> >> +	    vic == 10 || vic == 11 || vic == 20 ||
> >> >> +	    vic == 21 || vic == 22 || vic == 39 ||
> >> >> +	    vic == 25 || vic == 26 || vic == 40 ||
> >> >> +	    vic == 44 || vic == 45 || vic == 46 ||
> >> >> +	    vic == 50 || vic == 51 || vic == 54 ||
> >> >> +	    vic == 55 || vic == 58 || vic  == 59)
> >> >> +		value |= R_V_BLANK_IN_OSC;
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_CONFIG2 register */
> >> >> +	vblank = mode->vtotal - mode->vdisplay;
> >> >> +	vactive = mode->vdisplay;
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
> >> >> +		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_CONFIG3 register */
> >> >> +	h_sync_width = mode->hsync_end - mode->hsync_start;
> >> >> +	h_front_porch = mode->hsync_start - mode->hdisplay;
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
> >> >> +		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
> >> >> +		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_CONFIG4 register */
> >> >> +	v_sync_width = mode->vsync_end - mode->vsync_start;
> >> >> +	v_front_porch = mode->vsync_start - mode->vdisplay;
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
> >> >> +		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
> >> >> +		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_CONFIG5 register */
> >> >> +	peak_stream_bandwidth = mode->clock * bpp / 8;
> >> >> +	link_bandwidth = (link->rate / 1000) * link->lanes;
> >> >> +	ts = peak_stream_bandwidth * 64 / link_bandwidth;
> >> >> +	average_bytes_per_tu = ts / 1000;
> >> >> +	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
> >> >> +	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
> >> >> +		if (average_bytes_per_tu < 6)
> >> >> +			init_threshold = 32;
> >> >> +		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
> >> >> +			init_threshold = 12;
> >> >> +		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> >> +			init_threshold = 3;
> >> >> +		else
> >> >> +			init_threshold = 16;
> >> >> +	} else {
> >> >> +		u32 t1 = 0, t2 = 0, t3 = 0;
> >> >> +
> >> >> +		switch (bpc) {
> >> >> +		case 6:
> >> >> +			t1 = (4 * 1000 / 9) * link->lanes;
> >> >> +			break;
> >> >> +		case 8:
> >> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> >> >> +				t1 = (1000 / 2) * link->lanes;
> >> >> +			} else {
> >> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> >> +					t1 = (1000 / 3) * link->lanes;
> >> >> +				else
> >> >> +					t1 = (3000 / 16) * link->lanes;
> >> >> +			}
> >> >> +			break;
> >> >> +		case 10:
> >> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
> >> >> +				t1 = (2000 / 5) * link->lanes;
> >> >> +			else
> >> >> +				t1 = (4000 / 15) * link->lanes;
> >> >> +			break;
> >> >> +		case 12:
> >> >> +			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
> >> >> +				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> >> +					t1 = (1000 / 6) * link->lanes;
> >> >> +				else
> >> >> +					t1 = (1000 / 3) * link->lanes;
> >> >> +			} else {
> >> >> +				t1 = (2000 / 9) * link->lanes;
> >> >> +			}
> >> >> +			break;
> >> >> +		case 16:
> >> >> +			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
> >> >> +			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
> >> >> +				t1 = (1000 / 6) * link->lanes;
> >> >> +			else
> >> >> +				t1 = (1000 / 4) * link->lanes;
> >> >> +			break;
> >> >> +		default:
> >> >> +			return -EINVAL;
> >> >> +		}
> >> >> +
> >> >> +		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
> >> >> +			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
> >> >> +		else
> >> >> +			t2 = (link->rate / 4) * 1000 / mode->clock;
> >> >> +
> >> >> +		if (average_bytes_per_tu_frac)
> >> >> +			t3 = average_bytes_per_tu + 1;
> >> >> +		else
> >> >> +			t3 = average_bytes_per_tu;
> >> >> +		init_threshold = t1 * t2 * t3 / (1000 * 1000);
> >> >> +		if (init_threshold <= 16 || average_bytes_per_tu < 10)
> >> >> +			init_threshold = 40;
> >> >> +	}
> >> >> +
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
> >> >> +		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
> >> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
> >> >> +		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
> >> >> +		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
> >> >> +
> >> >> +	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
> >> >> +	hblank_interval = hblank * (link->rate / 4) / mode->clock;
> >> >> +	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
> >> >> +		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
> >> >> +		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
> >> >> +
> >> >> +	/* Video stream enable */
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
> >> >> +			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
> >> >> +
> >> >> +	if (dw_dp_video_need_vsc_sdp(dp))
> >> >> +		dw_dp_send_vsc_sdp(dp);
> >> >> +
> >> >> +	return 0;
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_hpd_init(struct dw_dp *dp)
> >> >> +{
> >> >> +	/* Enable all HPD interrupts */
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
> >> >> +			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
> >> >> +			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
> >> >> +			   FIELD_PREP(HPD_PLUG_EN, 1) |
> >> >> +			   FIELD_PREP(HPD_IRQ_EN, 1));
> >> >> +
> >> >> +	/* Enable all top-level interrupts */
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> >> >> +			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_aux_init(struct dw_dp *dp)
> >> >> +{
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
> >> >> +			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_init_hw(struct dw_dp *dp)
> >> >> +{
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
> >> >> +			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
> >> >> +
> >> >> +	dw_dp_hpd_init(dp);
> >> >> +	dw_dp_aux_init(dp);
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
> >> >> +{
> >> >> +	size_t i, j;
> >> >> +
> >> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> >> >> +		size_t num = min_t(size_t, size - i * 4, 4);
> >> >> +		u32 value = 0;
> >> >> +
> >> >> +		for (j = 0; j < num; j++)
> >> >> +			value |= buffer[i * 4 + j] << (j * 8);
> >> >> +
> >> >> +		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
> >> >> +	}
> >> >> +
> >> >> +	return size;
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
> >> >> +{
> >> >> +	size_t i, j;
> >> >> +
> >> >> +	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
> >> >> +		size_t num = min_t(size_t, size - i * 4, 4);
> >> >> +		u32 value;
> >> >> +
> >> >> +		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
> >> >> +
> >> >> +		for (j = 0; j < num; j++)
> >> >> +			buffer[i * 4 + j] = value >> (j * 8);
> >> >> +	}
> >> >> +
> >> >> +	return size;
> >> >> +}
> >> >> +
> >> >> +static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
> >> >> +				  struct drm_dp_aux_msg *msg)
> >> >> +{
> >> >> +	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
> >> >> +	unsigned long timeout = msecs_to_jiffies(10);
> >> >> +	u32 status, value;
> >> >> +	ssize_t ret = 0;
> >> >> +
> >> >> +	if (WARN_ON(msg->size > 16))
> >> >> +		return -E2BIG;
> >> >> +
> >> >> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
> >> >> +	case DP_AUX_NATIVE_WRITE:
> >> >> +	case DP_AUX_I2C_WRITE:
> >> >> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
> >> >> +		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
> >> >> +		if (ret < 0)
> >> >> +			return ret;
> >> >> +		break;
> >> >> +	case DP_AUX_NATIVE_READ:
> >> >> +	case DP_AUX_I2C_READ:
> >> >> +		break;
> >> >> +	default:
> >> >> +		return -EINVAL;
> >> >> +	}
> >> >> +
> >> >> +	if (msg->size > 0)
> >> >> +		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
> >> >> +	else
> >> >> +		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
> >> >> +	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
> >> >> +	value |= FIELD_PREP(AUX_ADDR, msg->address);
> >> >> +	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
> >> >> +
> >> >> +	status = wait_for_completion_timeout(&dp->complete, timeout);
> >> >> +	if (!status) {
> >> >> +		dev_err(dp->dev, "timeout waiting for AUX reply\n");
> >> >> +		return -ETIMEDOUT;
> >> >> +	}
> >> >> +
> >> >> +	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
> >> >> +	if (value & AUX_TIMEOUT)
> >> >> +		return -ETIMEDOUT;
> >> >> +
> >> >> +	msg->reply = FIELD_GET(AUX_STATUS, value);
> >> >> +
> >> >> +	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
> >> >> +		if (msg->request & DP_AUX_I2C_READ) {
> >> >> +			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
> >> >> +
> >> >> +			if (count != msg->size)
> >> >> +				return -EBUSY;
> >> >> +
> >> >> +			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
> >> >> +			if (ret < 0)
> >> >> +				return ret;
> >> >> +		}
> >> >> +	}
> >> >> +
> >> >> +	return ret;
> >> >> +}
> >> >> +
> >> >> +/*
> >> >> + * Limits for the video timing output by DP:
> >> >> + * 1. the hfp should be 2 pixels aligned;
> >> >> + * 2. the minimum hsync should be 9 pixel;
> >> >> + * 3. the minimum hbp should be 16 pixel;
> >> >> + */
> >> >> +static bool dw_dp_bridge_mode_fixup(struct drm_bridge *bridge,
> >> >> +				    const struct drm_display_mode *mode,
> >> >> +				    struct drm_display_mode *adjusted_mode)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	int min_hbp = 16;
> >> >> +	int min_hsync = 9;
> >> >> +
> >> >> +	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
> >> >> +		adjusted_mode->hsync_start += 1;
> >> >> +		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
> >> >> +	}
> >> >> +	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
> >> >> +		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
> >> >> +		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
> >> >> +	}
> >> >> +	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
> >> >> +		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
> >> >> +		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
> >> >> +	}
> >> >> +
> >> >> +	return true;
> >> >> +}
> >> >> +
> >> >> +static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
> >> >> +						    const struct drm_display_info *info,
> >> >> +						    const struct drm_display_mode *mode)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	u32 min_bpp;
> >> >> +
> >> >> +	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
> >> >> +	    link->vsc_sdp_supported &&
> >> >> +	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
> >> >> +		min_bpp = 12;
> >> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
> >> >> +		min_bpp = 16;
> >> >> +	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
> >> >> +		min_bpp = 18;
> >> >> +	else
> >> >> +		min_bpp = 24;
> >> >> +
> >> >> +	if (!link->vsc_sdp_supported &&
> >> >> +	    drm_mode_is_420_only(info, mode))
> >> >> +		return MODE_NO_420;
> >> >> +
> >> >> +	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
> >> >> +		return MODE_CLOCK_HIGH;
> >> >> +
> >> >> +	return MODE_OK;
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> >> >> +					   struct drm_bridge_state *old_bridge_state)
> >> >> +{
> >> >> +	struct drm_atomic_state *state = old_bridge_state->base.state;
> >> >> +	struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	struct dw_dp_video *video = &dp->video;
> >> >> +	struct drm_display_mode *m = &video->mode;
> >> >> +	struct drm_bridge_state *bridge_state;
> >> >> +	const struct dw_dp_output_format *fmt;
> >> >> +
> >> >> +	drm_mode_copy(m, &crtc_state->adjusted_mode);
> >> >> +
> >> >> +	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> >> >> +	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);
> >> >
> >> >Should it be a part of the atomic_check() instead?
> >> 
> >> Since we have modef_fixup in this driver, which is mutually exclusive with atomic_check.
> >
> >You can convet .mode_fixup into .atomic_check. The latter can change the
> >crtc_state->adjusted_mode. It is better to reject the invalid
> >combinations from the .atomic_check rather than having to handled them
> >later.
> >
> >> 
> >> 
> >> 
> >> >
> >> >> +
> >> >> +	video->video_mapping = fmt->video_mapping;
> >> >> +	video->color_format = fmt->color_format;
> >> >> +	video->bpc = fmt->bpc;
> >> >> +	video->bpp = fmt->bpp;
> >> >> +}
> >> >> +
> >> >> +static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	u8 link_status[DP_LINK_STATUS_SIZE];
> >> >> +
> >> >> +	if (!dw_dp_link_train_valid(&link->train))
> >> >> +		return false;
> >> >> +
> >> >> +	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
> >> >> +		return false;
> >> >> +
> >> >> +	/* Retrain if Channel EQ or CR not ok */
> >> >> +	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_link_disable(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +
> >> >> +	if (dw_dp_hpd_detect(dp))
> >> >> +		dw_dp_link_power_down(dp);
> >> >> +
> >> >> +	dw_dp_phy_xmit_enable(dp, 0);
> >> >> +
> >> >> +	phy_power_off(dp->phy);
> >> >> +
> >> >> +	link->train.clock_recovered = false;
> >> >> +	link->train.channel_equalized = false;
> >> >> +}
> >> >> +
> >> >> +static int dw_dp_link_enable(struct dw_dp *dp)
> >> >> +{
> >> >> +	int ret;
> >> >> +
> >> >> +	ret = phy_power_on(dp->phy);
> >> >> +	if (ret)
> >> >> +		return ret;
> >> >> +
> >> >> +	ret = dw_dp_link_power_up(dp);
> >> >> +	if (ret < 0)
> >> >> +		return ret;
> >> >> +
> >> >> +	ret = dw_dp_link_train(dp);
> >> >> +
> >> >> +	return ret;
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
> >> >> +				       struct drm_bridge_state *old_state)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	struct drm_atomic_state *state = old_state->base.state;
> >> >> +	struct drm_connector *connector;
> >> >> +	struct drm_connector_state *conn_state;
> >> >> +	int ret;
> >> >> +
> >> >> +	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
> >> >> +	if (!connector) {
> >> >> +		dev_err(dp->dev, "failed to get connector\n");
> >> >> +		return;
> >> >> +	}
> >> >> +
> >> >> +	conn_state = drm_atomic_get_new_connector_state(state, connector);
> >> >> +	if (!conn_state) {
> >> >> +		dev_err(dp->dev, "failed to get connector state\n");
> >> >> +		return;
> >> >> +	}
> >> >> +
> >> >> +	set_bit(0, dp->sdp_reg_bank);
> >> >> +
> >> >> +	ret = dw_dp_link_enable(dp);
> >> >> +	if (ret < 0) {
> >> >> +		dev_err(dp->dev, "failed to enable link: %d\n", ret);
> >> >> +		return;
> >> >> +	}
> >> >> +
> >> >> +	ret = dw_dp_video_enable(dp);
> >> >> +	if (ret < 0) {
> >> >> +		dev_err(dp->dev, "failed to enable video: %d\n", ret);
> >> >> +		return;
> >> >> +	}
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_reset(struct dw_dp *dp)
> >> >> +{
> >> >> +	int val;
> >> >> +
> >> >> +	disable_irq(dp->irq);
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> >> >> +			   FIELD_PREP(CONTROLLER_RESET, 1));
> >> >> +	udelay(10);
> >> >> +	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
> >> >> +			   FIELD_PREP(CONTROLLER_RESET, 0));
> >> >> +
> >> >> +	dw_dp_init_hw(dp);
> >> >> +	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
> >> >> +				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
> >> >> +	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> >> >> +	enable_irq(dp->irq);
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
> >> >> +					struct drm_bridge_state *old_bridge_state)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +
> >> >> +	dw_dp_video_disable(dp);
> >> >> +	dw_dp_link_disable(dp);
> >> >> +	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
> >> >> +	dw_dp_reset(dp);
> >> >> +}
> >> >> +
> >> >> +static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
> >> >> +{
> >> >> +	int ret;
> >> >> +
> >> >> +	ret = phy_power_on(dp->phy);
> >> >> +	if (ret < 0)
> >> >> +		return false;
> >> >> +	ret = dw_dp_link_parse(dp);
> >> >> +	phy_power_off(dp->phy);
> >> >> +
> >> >> +	return !ret;
> >> >> +}
> >> >> +
> >> >> +static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +
> >> >> +	if (!dw_dp_hpd_detect(dp))
> >> >> +		return connector_status_disconnected;
> >> >> +
> >> >> +	if (!dw_dp_hpd_detect_link(dp))
> >> >> +		return connector_status_disconnected;
> >> >> +
> >> >> +	return connector_status_connected;
> >> >> +}
> >> >> +
> >> >> +static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
> >> >> +						     struct drm_connector *connector)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	const struct drm_edid *edid;
> >> >> +	int ret;
> >> >> +
> >> >> +	ret = phy_power_on(dp->phy);
> >> >> +	if (ret)
> >> >> +		return NULL;
> >> >> +
> >> >> +	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
> >> >> +
> >> >> +	phy_power_off(dp->phy);
> >> >> +
> >> >> +	return edid;
> >> >> +}
> >> >> +
> >> >> +static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> >> >> +						    struct drm_bridge_state *bridge_state,
> >> >> +						    struct drm_crtc_state *crtc_state,
> >> >> +						    struct drm_connector_state *conn_state,
> >> >> +						    unsigned int *num_output_fmts)
> >> >> +{
> >> >> +	struct dw_dp *dp = bridge_to_dp(bridge);
> >> >> +	struct dw_dp_link *link = &dp->link;
> >> >> +	struct drm_display_info *di = &conn_state->connector->display_info;
> >> >> +	struct drm_display_mode mode = crtc_state->mode;
> >> >> +	const struct dw_dp_output_format *fmt;
> >> >> +	u32 i, j = 0;
> >> >> +	u32 *output_fmts;
> >> >> +
> >> >> +	*num_output_fmts = 0;
> >> >> +
> >> >> +	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
> >> >> +	if (!output_fmts)
> >> >> +		return NULL;
> >> >> +
> >> >> +	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
> >> >> +		fmt = &dw_dp_output_formats[i];
> >> >> +
> >> >> +		if (fmt->bpc > conn_state->max_bpc)
> >> >> +			continue;
> >> >> +
> >> >> +		if (!(fmt->color_format & di->color_formats))
> >> >> +			continue;
> >> >> +
> >> >> +		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
> >> >> +		    !link->vsc_sdp_supported)
> >> >> +			continue;
> >> >> +
> >> >> +		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
> >> >> +		    drm_mode_is_420_only(di, &mode))
> >> >> +			continue;
> >> >> +
> >> >> +		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
> >> >> +			continue;
> >> >> +
> >> >> +		output_fmts[j++] = fmt->bus_format;
> >> >> +	}
> >> >> +
> >> >> +	*num_output_fmts = j;
> >> >> +
> >> >> +	return output_fmts;
> >> >> +}
> >> >> +
> >> >> +static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
> >> >> +	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
> >> >> +	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> >> >> +	.atomic_reset = drm_atomic_helper_bridge_reset,
> >> >> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
> >> >> +	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
> >> >> +	.mode_fixup = dw_dp_bridge_mode_fixup,
> >> >> +	.mode_valid = dw_dp_bridge_mode_valid,
> >> >> +	.atomic_pre_enable = dw_dp_bridge_atomic_pre_enable,
> >> >> +	.atomic_enable = dw_dp_bridge_atomic_enable,
> >> >> +	.atomic_disable = dw_dp_bridge_atomic_disable,
> >> >> +	.detect = dw_dp_bridge_detect,
> >> >> +	.edid_read = dw_dp_bridge_edid_read,
> >> >> +};
> >> >> +
> >> >> +static int dw_dp_link_retrain(struct dw_dp *dp)
> >> >> +{
> >> >> +	struct drm_device *dev = dp->bridge.dev;
> >> >> +	struct drm_modeset_acquire_ctx ctx;
> >> >> +	int ret;
> >> >> +
> >> >> +	if (!dw_dp_needs_link_retrain(dp))
> >> >> +		return 0;
> >> >> +
> >> >> +	dev_dbg(dp->dev, "Retraining link\n");
> >> >> +
> >> >> +	drm_modeset_acquire_init(&ctx, 0);
> >> >> +	for (;;) {
> >> >> +		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
> >> >> +		if (ret != -EDEADLK)
> >> >> +			break;
> >> >
> >> >I think it's an error to continue in such a case. There should be a
> >> >return after the loop if ret is not 0.
> >> 
> >> Thank you for catching this? I will add a check fater the loop.
> >> 
> >> 
> >> >
> >> >> +
> >> >> +		drm_modeset_backoff(&ctx);
> >> >> +	}
> >> >> +
> >> >> +	ret = dw_dp_link_train(dp);
> >> >> +	drm_modeset_drop_locks(&ctx);
> >> >> +	drm_modeset_acquire_fini(&ctx);
> >> >> +
> >> >> +	return ret;
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_hpd_work(struct work_struct *work)
> >> >> +{
> >> >> +	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
> >> >> +	bool long_hpd;
> >> >> +	int ret;
> >> >> +
> >> >> +	mutex_lock(&dp->irq_lock);
> >> >> +	long_hpd = dp->hotplug.long_hpd;
> >> >> +	mutex_unlock(&dp->irq_lock);
> >> >> +
> >> >> +	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
> >> >> +
> >> >> +	if (!long_hpd) {
> >> >> +		if (dw_dp_needs_link_retrain(dp)) {
> >> >> +			ret = dw_dp_link_retrain(dp);
> >> >> +			if (ret)
> >> >> +				dev_warn(dp->dev, "Retrain link failed\n");
> >> >> +		}
> >> >> +	} else {
> >> >> +		drm_helper_hpd_irq_event(dp->bridge.dev);
> >> >> +	}
> >> >> +}
> >> >> +
> >> >> +static void dw_dp_handle_hpd_event(struct dw_dp *dp)
> >> >> +{
> >> >> +	u32 value;
> >> >> +
> >> >> +	mutex_lock(&dp->irq_lock);
> >> >> +	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >> >> +
> >> >> +	if (value & HPD_IRQ) {
> >> >> +		dev_dbg(dp->dev, "IRQ from the HPD\n");
> >> >> +		dp->hotplug.long_hpd = false;
> >> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
> >> >> +	}
> >> >> +
> >> >> +	if (value & HPD_HOT_PLUG) {
> >> >> +		dev_dbg(dp->dev, "Hot plug detected\n");
> >> >> +		dp->hotplug.long_hpd = true;
> >> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
> >> >> +	}
> >> >> +
> >> >> +	if (value & HPD_HOT_UNPLUG) {
> >> >> +		dev_dbg(dp->dev, "Unplug detected\n");
> >> >> +		dp->hotplug.long_hpd = true;
> >> >> +		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
> >> >> +	}
> >> >> +	mutex_unlock(&dp->irq_lock);
> >> >> +
> >> >> +	schedule_work(&dp->hpd_work);
> >> >> +}
> >> >> +
> >> >> +static irqreturn_t dw_dp_irq(int irq, void *data)
> >> >> +{
> >> >> +	struct dw_dp *dp = data;
> >> >> +	u32 value;
> >> >> +
> >> >> +	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
> >> >> +	if (!value)
> >> >> +		return IRQ_NONE;
> >> >> +
> >> >> +	if (value & HPD_EVENT)
> >> >> +		dw_dp_handle_hpd_event(dp);
> >> >> +
> >> >> +	if (value & AUX_REPLY_EVENT) {
> >> >> +		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
> >> >> +		complete(&dp->complete);
> >> >> +	}
> >> >> +
> >> >> +	return IRQ_HANDLED;
> >> >> +}
> >> >> +
> >> >> +static const struct regmap_range dw_dp_readable_ranges[] = {
> >> >> +	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
> >> >> +	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
> >> >> +	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
> >> >> +	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
> >> >> +	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
> >> >> +	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
> >> >> +	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
> >> >> +	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
> >> >> +	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
> >> >> +};
> >> >> +
> >> >> +static const struct regmap_access_table dw_dp_readable_table = {
> >> >> +	.yes_ranges     = dw_dp_readable_ranges,
> >> >> +	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
> >> >> +};
> >> >> +
> >> >> +static const struct regmap_config dw_dp_regmap_config = {
> >> >> +	.reg_bits = 32,
> >> >> +	.reg_stride = 4,
> >> >> +	.val_bits = 32,
> >> >> +	.fast_io = true,
> >> >> +	.max_register = DW_DP_MAX_REGISTER,
> >> >> +	.rd_table = &dw_dp_readable_table,
> >> >> +};
> >> >> +
> >> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> >> >> +			 const struct dw_dp_plat_data *plat_data)
> >> >> +{
> >> >> +	struct platform_device *pdev = to_platform_device(dev);
> >> >> +	struct dw_dp *dp;
> >> >> +	struct drm_bridge *bridge;
> >> >> +	void __iomem *res;
> >> >> +	int ret;
> >> >> +
> >> >> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
> >> >> +	if (!dp)
> >> >> +		return ERR_PTR(-ENOMEM);
> >> >> +
> >> >> +	dp->dev = dev;
> >> >> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
> >> >> +
> >> >> +	dp->plat_data = plat_data;
> >> >> +	bridge = &dp->bridge;
> >> >> +	mutex_init(&dp->irq_lock);
> >> >> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
> >> >> +	init_completion(&dp->complete);
> >> >> +
> >> >> +	res = devm_platform_ioremap_resource(pdev, 0);
> >> >> +	if (IS_ERR(res))
> >> >> +		return ERR_CAST(res);
> >> >> +
> >> >> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
> >> >> +	if (IS_ERR(dp->regmap)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
> >> >> +		return ERR_CAST(dp->regmap);
> >> >> +	}
> >> >> +
> >> >> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
> >> >> +	if (IS_ERR(dp->phy)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
> >> >> +		return ERR_CAST(dp->phy);
> >> >> +	}
> >> >> +
> >> >> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
> >> >> +	if (IS_ERR(dp->apb_clk)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
> >> >> +		return ERR_CAST(dp->apb_clk);
> >> >> +	}
> >> >> +
> >> >> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
> >> >> +	if (IS_ERR(dp->aux_clk)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
> >> >> +		return ERR_CAST(dp->aux_clk);
> >> >> +	}
> >> >> +
> >> >> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
> >> >> +	if (IS_ERR(dp->i2s_clk)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
> >> >> +		return ERR_CAST(dp->i2s_clk);
> >> >> +	}
> >> >> +
> >> >> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
> >> >> +	if (IS_ERR(dp->spdif_clk)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
> >> >> +		return ERR_CAST(dp->spdif_clk);
> >> >> +	}
> >> >> +
> >> >> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
> >> >> +	if (IS_ERR(dp->hdcp_clk)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
> >> >> +		return ERR_CAST(dp->hdcp_clk);
> >> >> +	}
> >> >> +
> >> >> +	dp->rstc = devm_reset_control_get(dev, NULL);
> >> >> +	if (IS_ERR(dp->rstc)) {
> >> >> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
> >> >> +		return ERR_CAST(dp->rstc);
> >> >> +	}
> >> >> +
> >> >> +	dp->irq = platform_get_irq(pdev, 0);
> >> >> +	if (dp->irq < 0)
> >> >> +		return ERR_PTR(ret);
> >> >> +
> >> >> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
> >> >> +					IRQF_ONESHOT, dev_name(dev), dp);
> >> >
> >> >Are you ready to handle the IRQ here, before the bridge is filled?
> >> 
> >> I will move to  devm_request_threaded_irq after dw_dp_init_hw.
> >> 
> >> 
> >> >
> >> >> +	if (ret) {
> >> >> +		dev_err_probe(dev, ret, "failed to request irq\n");
> >> >> +		return ERR_PTR(ret);
> >> >> +	}
> >> >> +
> >> >> +	bridge->of_node = dev->of_node;
> >> >> +	bridge->funcs = &dw_dp_bridge_funcs;
> >> >> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> >> >> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
> >> >> +	bridge->ycbcr_420_allowed = true;
> >> >> +	bridge->vendor = "Synopsys";
> >> >> +	bridge->product = "DW DP TX";
> >> >
> >> >These two are unused
> >> >
> >> >> +
> >> >> +	platform_set_drvdata(pdev, dp);
> >> >
> >> >Unused
> >> 
> >> I will remove them.
> >> 
> >> Thanks again.
> >> 
> >> 
> >> >
> >> >> +
> >> >> +	dp->aux.dev = dev;
> >> >> +	dp->aux.drm_dev = encoder->dev;
> >> >> +	dp->aux.name = dev_name(dev);
> >> >> +	dp->aux.transfer = dw_dp_aux_transfer;
> >> >> +	ret = drm_dp_aux_register(&dp->aux);
> >> >> +	if (ret) {
> >> >> +		dev_err_probe(dev, ret, "Aux register failed\n");
> >> >> +		return ERR_PTR(ret);
> >> >> +	}
> >> >> +
> >> >> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >> >> +	if (ret)
> >> >> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
> >> >> +
> >> >> +	dw_dp_init_hw(dp);
> >> >> +
> >> >> +	return dp;
> >> >> +}
> >> >> +MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
> >> >> +MODULE_DESCRIPTION("DW DP Core Library");
> >> >> +MODULE_LICENSE("GPL");
> >> >> diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
> >> >> new file mode 100644
> >> >> index 000000000000..07845f609eca
> >> >> --- /dev/null
> >> >> +++ b/include/drm/bridge/dw_dp.h
> >> >> @@ -0,0 +1,19 @@
> >> >> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> >> >> +/*
> >> >> + * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
> >> >> + */
> >> >> +
> >> >> +#ifndef __DW_DP__
> >> >> +#define __DW_DP__
> >> >> +
> >> >> +struct device;
> >> >> +struct drm_encoder;
> >> >> +struct dw_dp;
> >> >> +
> >> >> +struct dw_dp_plat_data {
> >> >> +	u32 max_link_rate;
> >> >> +};
> >> >> +
> >> >> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> >> >> +			 const struct dw_dp_plat_data *plat_data);
> >> >> +#endif /* __DW_DP__ */
> >> >> -- 
> >> >> 2.34.1
> >> >> 
> >> >
> >> >-- 
> >> >With best wishes
> >> >Dmitry
> >
> >-- 
> >With best wishes
> >Dmitry

-- 
With best wishes
Dmitry


From Jonathan.Cameron at huawei.com  Tue Mar  4 01:21:02 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 17:21:02 +0800
Subject: [PATCH 1/9] drivers/perf: hisi: Extend struct hisi_pmu_dev_info
In-Reply-To: <e6cfcfd0-5412-20bb-f4b5-cf266884c5d0@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-2-yangyicong@huawei.com>
	<20250301062343.GA27700@willie-the-truck>
	<e6cfcfd0-5412-20bb-f4b5-cf266884c5d0@huawei.com>
Message-ID: <20250304172102.00006e54@huawei.com>

On Mon, 3 Mar 2025 22:43:35 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> On 2025/3/1 14:23, Will Deacon wrote:
> > On Tue, Feb 18, 2025 at 05:19:52PM +0800, Yicong Yang wrote:  
> >> From: Junhao He <hejunhao3 at huawei.com>
> >>
> >> The counter bits and event range may differ from versions of a
> >> certain uncore PMU. Make this device specific information into
> >> struct hisi_pmu_dev_info. This will help to simplify the
> >> initialization process by using a list of struct hisi_pmu_dev_info
> >> rather than checking the version.
> >>
> >> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> >> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> >> ---
> >>  drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 ++
> >>  1 file changed, 2 insertions(+)
> >>
> >> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> >> index f4fed2544877..777675838b80 100644
> >> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
> >> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> >> @@ -72,6 +72,8 @@ struct hisi_uncore_ops {
> >>  struct hisi_pmu_dev_info {
> >>  	const char *name;
> >>  	const struct attribute_group **attr_groups;
> >> +	u32 counter_bits;
> >> +	u32 check_event;
This name is a little confusing.  Maybe nr_events or similar?


> >>  	void *private;
> >>  };  
> > 
> > This doesn't really do anything on its own; please just fold it into the
> > patch where the new fields are used.
> >   
> 
> sure, will make this into the following patch.
> 
> Thanks.
> 



From angelogioacchino.delregno at collabora.com  Tue Mar  4 01:41:43 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 10:41:43 +0100
Subject: [PATCH v4 6/8] soc: mediatek: Add programming flow for
 unsupported subsys ID hardware
In-Reply-To: <20250218054405.2017918-7-jason-jh.lin@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-7-jason-jh.lin@mediatek.com>
Message-ID: <c52b132b-fc08-4d1c-8276-1771f7457014@collabora.com>

Il 18/02/25 06:41, Jason-JH Lin ha scritto:
> To support hardware without subsys IDs on new SoCs, add a programming
> flow that checks whether the subsys ID is valid. If the subsys ID is
> invalid, the flow will call 2 alternative CMDQ APIs:
> cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the same
> functionality.
> 
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> ---
>   drivers/soc/mediatek/mtk-mmsys.c | 14 +++++++++++---
>   drivers/soc/mediatek/mtk-mutex.c | 11 +++++++++--
>   2 files changed, 20 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
> index bb4639ca0b8c..ce949b863b05 100644
> --- a/drivers/soc/mediatek/mtk-mmsys.c
> +++ b/drivers/soc/mediatek/mtk-mmsys.c
> @@ -167,9 +167,17 @@ static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask,
>   	u32 tmp;
>   
>   	if (mmsys->cmdq_base.size && cmdq_pkt) {
> -		ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
> -					  mmsys->cmdq_base.offset + offset, val,
> -					  mask);
> +		offset += mmsys->cmdq_base.offset;
> +		if (mmsys->cmdq_base.subsys != CMDQ_SUBSYS_INVALID) {

You're still anyway passing the subsys to cmdq_pkt_write_mask(), right?!
Why don't you just handle this in cmdq_pkt_write_mask() then? ;-)

I can see this pattern being repeated over and over in both drm/mediatek and MDP3
drivers, and it's not necessary to duplicate this many times when you can write it
just once.

Would've also been faster for you to implement... :-D

Cheers,
Angelo

> +			ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
> +						  offset, val, mask);
> +		} else {
> +			/* only MMIO access, no need to check mminfro_offset */
> +			ret = cmdq_pkt_assign(cmdq_pkt, CMDQ_THR_SPR_IDX0,
> +					      CMDQ_ADDR_HIGH(mmsys->cmdq_base.pa_base));
> +			ret |= cmdq_pkt_write_s_mask_value(cmdq_pkt, CMDQ_THR_SPR_IDX0,
> +							   CMDQ_ADDR_LOW(offset), val, mask);
> +		}
>   		if (ret)
>   			pr_debug("CMDQ unavailable: using CPU write\n");
>   		else
> diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
> index 5250c1d702eb..3788b16efbf4 100644
> --- a/drivers/soc/mediatek/mtk-mutex.c
> +++ b/drivers/soc/mediatek/mtk-mutex.c
> @@ -963,6 +963,7 @@ int mtk_mutex_enable_by_cmdq(struct mtk_mutex *mutex, void *pkt)
>   	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
>   						 mutex[mutex->id]);
>   	struct cmdq_pkt *cmdq_pkt = (struct cmdq_pkt *)pkt;
> +	dma_addr_t en_addr = mtx->addr + DISP_REG_MUTEX_EN(mutex->id);
>   
>   	WARN_ON(&mtx->mutex[mutex->id] != mutex);
>   
> @@ -971,8 +972,14 @@ int mtk_mutex_enable_by_cmdq(struct mtk_mutex *mutex, void *pkt)
>   		return -ENODEV;
>   	}
>   
> -	cmdq_pkt_write(cmdq_pkt, mtx->cmdq_reg.subsys,
> -		       mtx->addr + DISP_REG_MUTEX_EN(mutex->id), 1);
> +	if (mtx->cmdq_reg.subsys != CMDQ_SUBSYS_INVALID) {
> +		cmdq_pkt_write(cmdq_pkt, mtx->cmdq_reg.subsys, en_addr, 1);
> +	} else {
> +		/* only MMIO access, no need to check mminfro_offset */
> +		cmdq_pkt_assign(cmdq_pkt, CMDQ_THR_SPR_IDX0, CMDQ_ADDR_HIGH(en_addr));
> +		cmdq_pkt_write_s_value(cmdq_pkt, CMDQ_THR_SPR_IDX0, CMDQ_ADDR_LOW(en_addr), 1);
> +	}
> +
>   	return 0;
>   }
>   EXPORT_SYMBOL_GPL(mtk_mutex_enable_by_cmdq);




From peterz at infradead.org  Tue Mar  4 01:42:20 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 4 Mar 2025 10:42:20 +0100
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn>
 <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net>
 <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
Message-ID: <20250304094220.GC11590@noisy.programming.kicks-ass.net>

On Tue, Mar 04, 2025 at 03:47:45PM +0800, Menglong Dong wrote:
> We don't have to select FUNCTION_ALIGNMENT_32B, so the
> worst case is to increase ~2.2%.
> 
> What do you think?

Well, since I don't understand what you need this for at all, I'm firmly
on the side of not doing this.

What actual problem is being solved with this meta data nonsense? Why is
it worth blowing up our I$ footprint over.

Also note, that if you're going to be explaining this, start from
scratch, as I have absolutely 0 clues about BPF and such.


From ping.bai at nxp.com  Tue Mar  4 01:45:13 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue,  4 Mar 2025 17:45:13 +0800
Subject: [PATCH] irq: imx-irqsteer: irq_count can larger than registered irq
Message-ID: <20250304094513.1964356-1-ping.bai@nxp.com>

From: Shengjiu Wang <shengjiu.wang at nxp.com>

The irqsteer IP itself can support up to 5 channels and each
channel can support max 960 IRQs per. The actual number of
channels and IRQ per channel implemented in HW is SoC related.

For previous i.MX SoCs, normally only one channel and max 512
IRQ is implemented, But for i.MX94, the irqsteer HW is implemented
for 960 IRQs, even it only has 384 IRQs connected.

That means on i.MX94, the 'irq_number' is 6 but the 'irq_count' is
15, so we need to increase the CHAN_MAX_OUTPUT_INT to 0xF(960 / 64)
to make sure the irqsteer can work correctly on i.MX94.

Signed-off-by: Shengjiu Wang <shengjiu.wang at nxp.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
Reviewed-by: Ye Li <ye.li at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/irqchip/irq-imx-irqsteer.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index b0e9788c0045..afbfcce3b1e3 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -24,7 +24,7 @@
 #define CHAN_MINTDIS(t)		(CTRL_STRIDE_OFF(t, 3) + 0x4)
 #define CHAN_MASTRSTAT(t)	(CTRL_STRIDE_OFF(t, 3) + 0x8)
 
-#define CHAN_MAX_OUTPUT_INT	0x8
+#define CHAN_MAX_OUTPUT_INT	0xF
 
 struct irqsteer_data {
 	void __iomem		*regs;
@@ -228,10 +228,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 
 	for (i = 0; i < data->irq_count; i++) {
 		data->irq[i] = irq_of_parse_and_map(np, i);
-		if (!data->irq[i]) {
-			ret = -EINVAL;
-			goto out;
-		}
+		if (!data->irq[i])
+			break;
 
 		irq_set_chained_handler_and_data(data->irq[i],
 						 imx_irqsteer_irq_handler,
@@ -254,9 +252,13 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 	struct irqsteer_data *irqsteer_data = platform_get_drvdata(pdev);
 	int i;
 
-	for (i = 0; i < irqsteer_data->irq_count; i++)
+	for (i = 0; i < irqsteer_data->irq_count; i++) {
+		if (!irqsteer_data->irq[i])
+			break;
+
 		irq_set_chained_handler_and_data(irqsteer_data->irq[i],
 						 NULL, NULL);
+	}
 
 	irq_domain_remove(irqsteer_data->domain);
 
-- 
2.34.1



From chester.a.unal at arinc9.com  Tue Mar  4 01:46:28 2025
From: chester.a.unal at arinc9.com (Chester A. Unal)
Date: Tue, 04 Mar 2025 09:46:28 +0000 (UTC)
Subject: [PATCH net] net: dsa: mt7530: Fix traffic flooding for MMIO
 devices
In-Reply-To: <20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org>
References: <20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org>
Message-ID: <b63fcbaa-ef27-48a9-885c-7962bd92a8b9@arinc9.com>

On 04/03/2025 08:50, Lorenzo Bianconi wrote:
> On MMIO devices (e.g. MT7988 or EN7581) unicast traffic received on lanX
> port is flooded on all other user ports if the DSA switch is configured
> without VLAN support since PORT_MATRIX in PCR regs contains all user
> ports. Similar to MDIO devices (e.g. MT7530 and MT7531) fix the issue
> defining default VLAN-ID 0 for MT7530 MMIO devices.
> 
> Fixes: 110c18bfed414 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch")
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>

I was suspecting of this for a while. Thanks for addressing it.

Reviewed-by: Chester A. Unal <chester.a.unal at arinc9.com>

Chester A.


From bryan.odonoghue at linaro.org  Tue Mar  4 01:47:44 2025
From: bryan.odonoghue at linaro.org (Bryan O'Donoghue)
Date: Tue, 4 Mar 2025 09:47:44 +0000
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <Z8a/Dk7zjZ7RQT2/@trex>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
 <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org> <Z8a7cMmxJuHIhgjo@trex>
 <baae2a56-5299-486f-acf1-14fe13fd2f81@kernel.org> <Z8a/Dk7zjZ7RQT2/@trex>
Message-ID: <f5c2044e-e78e-4839-9c29-63610ff406e2@linaro.org>

On 04/03/2025 08:51, Jorge Ramirez wrote:
> On 04/03/25 09:40:21, Krzysztof Kozlowski wrote:
>> On 04/03/2025 09:36, Jorge Ramirez wrote:
>>> On 03/03/25 18:13:20, Krzysztof Kozlowski wrote:
>>>> On 08/02/2025 23:51, Vikram Sharma wrote:
>>>>> The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
>>>>> camera sensor. Enable IMX577 on the vision mezzanine.
>>>>>
>>>>> An example media-ctl pipeline for the imx577 is:
>>>>>
>>>>> media-ctl --reset
>>>>> media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
>>>>
>>>> AFAIU, camss does not support SRGGB10, but only SRGGB10P.
>>>>
>>>> Based on tests reported on IRC I think this might not have been tested
>>>> correctly.
>>>
>>> I acquired SRGGB10P (10 bit packed) frames from the camera despite the
>>> pipeline being set to SRGGB10 (16 bit) samples.
>>>
>>> so something does not add up.
>>
>> Then the commands are actually correct, just the camss or media behave
>> here a bit unexpected?
>>
> 
> setting the pipeline (CSI) as SRGGB10 (16 bit samples) as per below
> 
> media-ctl --reset
> media-ctl -v -V '"imx577 '19-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
> media-ctl -V '"msm_csiphy3":0[fmt:SRGGB10/4056x3040]'
> media-ctl -V '"msm_csid0":0[fmt:SRGGB10/4056x3040]'
> media-ctl -V '"msm_vfe0_rdi0":0[fmt:SRGGB10/4056x3040]'
> media-ctl -l '"msm_csiphy3":1->"msm_csid0":0[1]'
> media-ctl -l '"msm_csid0":1->"msm_vfe0_rdi0":0[1]'
> 
> allows to capture SRGGB10P samples (frames-xxxx.bin files contain 10 bit samples for the size)
> 
>   ==> yavta -B capture-mplane -c -I -n 5 -f SRGGB10P -s 4056x3040 -F /dev/video0
> 
> 
> shouldnt the CSI need to be set to SRGGB10P instead?
> 
> 
>> Best regards,
>> Krzysztof
> 

No an internal media bus format MEDIA_BUS_FMT_THING is used

See

87889f1b7ea40d2544b49c62092e6ef2792dced7
5480b0c67f120a6c293cc5eff72fa1d6a74de504
3c1dfb5a69cf836f513a2a49113ee946a4b9d95d

Yavta is specifying a v4l2 pixel format SRGGB10P which then gets 
translated into a media bus format MEDIA_BUS_FMT_SRGGB10_1X10.

I'm not sure what the historical reasons for that are, probably good ones.

---
bod


From Jonathan.Cameron at huawei.com  Tue Mar  4 01:49:19 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 17:49:19 +0800
Subject: [PATCH 4/9] drivers/perf: hisi: Use ACPI driver_data to
 retrieve SLLC PMU information
In-Reply-To: <20250301064347.GB27700@willie-the-truck>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-5-yangyicong@huawei.com>
	<20250301064347.GB27700@willie-the-truck>
Message-ID: <20250304174919.00001e24@huawei.com>

On Sat, 1 Mar 2025 06:43:49 +0000
Will Deacon <will at kernel.org> wrote:

> On Tue, Feb 18, 2025 at 05:19:55PM +0800, Yicong Yang wrote:
> > From: Junhao He <hejunhao3 at huawei.com>
> > 
> > Make use of struct acpi_device_id::driver_data for version specific
> > information rather than judge the version register. This will help
> > to simplify the probe process and also a bit easier for extension.
> > 
> > Factor out SLLC register definition to struct hisi_sllc_pmu_regs.
> > No functional changes intended.
> > 
> > Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> > Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> > ---
> >  drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 191 ++++++++++++------
> >  1 file changed, 125 insertions(+), 66 deletions(-)
> > 
> > diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> > index dbd079016fc4..c1fd60d397c3 100644
> > --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> > +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> > @@ -36,11 +36,14 @@
> >  #define SLLC_SRCID_NONE			0x0
> >  #define SLLC_TGTID_EN			BIT(5)
> >  #define SLLC_TGTID_NONE			0x0
> > -#define SLLC_TGTID_MIN_SHIFT		1
> > -#define SLLC_TGTID_MAX_SHIFT		12
> > -#define SLLC_SRCID_CMD_SHIFT		1
> > -#define SLLC_SRCID_MSK_SHIFT		12
> > +#define SLLC_TGTID_MIN_MSK		GENMASK(11, 1)
> > +#define SLLC_TGTID_MAX_MSK		GENMASK(22, 12)
> > +#define SLLC_SRCID_CMD_MSK		GENMASK(11, 1)
> > +#define SLLC_SRCID_MSK_MSK		GENMASK(22, 12)
> >  #define SLLC_NR_EVENTS			0x80
> > +#define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
> > +#define SLLC_FIRST_BIT(_mask)		(find_first_bit((const unsigned long *)&(_mask), 32))
> > +#define SLLC_FIELD_PREP(_mask, _val)	(_mask & (_val << SLLC_FIRST_BIT(_mask)))  
> 
> It's a bit of a shame to have to compute this dynamically given that th
> input mask is constant for a given device. Is it not possible to use the
> generic FIELD_PREP macro in per-device code and then just dispatch to
> that, instead of funneling everything through hisi_sllc_pmu_regs?
There is yet another ongoing discussion of handling non const
field cases:
https://lore.kernel.org/all/cover.1739540679.git.geert+renesas at glider.be/

Maybe that will resolve with a nicer solution but I doubt it.

Alternatively best plan may be a shift (and length) instead
of the neat solution of FIELD_PREP().

Jonathan

> 
> Will



From frank-w at public-files.de  Tue Mar  4 01:23:59 2025
From: frank-w at public-files.de (Frank Wunderlich)
Date: Tue, 4 Mar 2025 09:23:59 +0000
Subject: Aw: Re: [RESEND][PATCH] arm64: dts: mediatek: mt7986: fix pwn fan
 settings for sinovoip bpi-r3 board
In-Reply-To: <618b3cdb-0fef-4194-aeb0-4111c011904d@collabora.com>
References: <20250226050132.547353-1-mikhail.kshevetskiy@iopsys.eu>
 <618b3cdb-0fef-4194-aeb0-4111c011904d@collabora.com>
Message-ID: <trinity-a81b2adf-df25-4888-9490-cc33257061b2-1741080239272@trinity-msg-rest-gmx-gmx-live-5779db864f-7hl68>

> Gesendet: Mittwoch, 26. Februar 2025 um 10:46
> Von: "AngeloGioacchino Del Regno" <angelogioacchino.delregno at collabora.com>
> Betreff: Re: [RESEND][PATCH] arm64: dts: mediatek: mt7986: fix pwn fan settings for sinovoip bpi-r3 board

> I get that the cheapest fans you can get are not working correctly with the current
> mid pwm setting, but you can't break things.
>
> This devicetree should, at this point, hold default values that would generally
> make the vast majority of fans to actually spin, because it's impossible to have
> something perfectly (or vaguely, sometimes) optimized for each fan on the market.
>
> Of course this means that you need to properly configure your fans in userspace
> if you want to reach the sweet spot.
>
> I added Frank and Daniel to this thread, as they are the ones who originally did
> upstream this device.
>
> Frank, Daniel, any suggestion regarding the PWM values here?

Hi,

sorry for delay

i have the fan from sinovoip and that was working for me, but if your fan only works with new values, i have no point against this change.

btw. angelo, how is state for my r4-dtsi change?

regards Frank


From dlechner at baylibre.com  Tue Mar  4 01:25:03 2025
From: dlechner at baylibre.com (David Lechner)
Date: Tue, 4 Mar 2025 10:25:03 +0100
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com> <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
Message-ID: <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>

On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
<mazziesaccount at gmail.com> wrote:
>
> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
>
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
>
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.
>
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
>
> ---
> Revision history:
> v4 => v5:
> - Inline iio_adc_device_num_channels()
> - Fix Indenting function parameters
> - Combine the max channel ID checks.
> v3 => v4:
>  - Drop diff-channel support
>  - Drop iio_adc_device_channels_by_property()
>  - Add IIO_DEVICE namespace
>  - Move industrialio-adc.o to top of the Makefile
>  - Some styling as suggested by Andy
>  - Re-consider included headers
> v2 => v3: Mostly based on review comments by Jonathan
>  - Support differential and single-ended channels
>  - Rename iio_adc_device_get_channels() as
>    iio_adc_device_channels_by_property()
>  - Improve spelling
>  - Drop support for cases where DT comes from parent device's node
>  - Decrease loop indent by reverting node name check conditions
>  - Don't set 'chan->indexed' by number of channels to keep the
>    interface consistent no matter how many channels are connected.
>  - Fix ID range check and related comment
> RFC v1 => v2:
>  - New patch
> ---
>  drivers/iio/adc/Kconfig            |  3 ++
>  drivers/iio/adc/Makefile           |  2 +
>  drivers/iio/adc/industrialio-adc.c | 82 ++++++++++++++++++++++++++++++
>  include/linux/iio/adc-helpers.h    | 27 ++++++++++
>  4 files changed, 114 insertions(+)
>  create mode 100644 drivers/iio/adc/industrialio-adc.c
>  create mode 100644 include/linux/iio/adc-helpers.h
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 849c90203071..37b70a65da6f 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -6,6 +6,9 @@
>
>  menu "Analog to digital converters"
>
> +config IIO_ADC_HELPER
> +       tristate
> +
>  config AB8500_GPADC
>         bool "ST-Ericsson AB8500 GPADC driver"
>         depends on AB8500_CORE && REGULATOR_AB8500
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index ee19afba62b7..1c410f483029 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -3,6 +3,8 @@
>  # Makefile for IIO ADC drivers
>  #
>
> +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
> +
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
>  obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
> new file mode 100644
> index 000000000000..7bdae5330224
> --- /dev/null
> +++ b/drivers/iio/adc/industrialio-adc.c
> @@ -0,0 +1,82 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Helpers for parsing common ADC information from a firmware node.
> + *
> + * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include <linux/types.h>
> +
> +#include <linux/iio/adc-helpers.h>
> +#include <linux/iio/iio.h>
> +
> +/**
> + * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
> + *
> + * Scan the device node for single-ended ADC channel information. Channel ID is
> + * expected to be found from the "reg" property. Allocate and populate the
> + * iio_chan_spec structure corresponding to channels that are found. The memory
> + * for iio_chan_spec structure will be freed upon device detach.
> + *
> + * @dev:               Pointer to the ADC device.
> + * @template:          Template iio_chan_spec from which the fields of all
> + *                     found and allocated channels are initialized.
> + * @max_chan_id:       Maximum value of a channel ID. Use -1 if no checking
> + *                     is required.
> + * @cs:                        Location where pointer to allocated iio_chan_spec
> + *                     should be stored.
> + *
> + * Return:     Number of found channels on succes. Negative value to indicate

s/succes/success/

> + *             failure.
> + */
> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> +                                         const struct iio_chan_spec *template,
> +                                         int max_chan_id,
> +                                         struct iio_chan_spec **cs)
> +{
> +       struct iio_chan_spec *chan_array, *chan;
> +       int num_chan = 0, ret;
> +
> +       num_chan = iio_adc_device_num_channels(dev);
> +       if (num_chan < 1)
> +               return num_chan;
> +
> +       chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
> +                                 GFP_KERNEL);
> +       if (!chan_array)
> +               return -ENOMEM;
> +
> +       chan = &chan_array[0];
> +
> +       device_for_each_child_node_scoped(dev, child) {
> +               u32 ch;
> +
> +               if (!fwnode_name_eq(child, "channel"))
> +                       continue;
> +
> +               ret = fwnode_property_read_u32(child, "reg", &ch);
> +               if (ret)
> +                       return ret;
> +
> +               if (max_chan_id != -1 && ch > max_chan_id)
> +                       return -ERANGE;
> +

Should we use return dev_err_probe() on these to help with debugging a bad dtb?

> +               *chan = *template;
> +               chan->channel = ch;
> +               chan++;
> +       }
> +
> +       *cs = chan_array;
> +
> +       return num_chan;
> +}
> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");

We can make this less verbose by setting #define
DEFAULT_SYMBOL_NAMESPACE at the start of the file. Then we can just do
EXPORT_SYMBOL_GPL() throughout the rest of the file.

Also, I would prefer if the namespace matched config name (IIO_ADC_HELPER).

> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
> +MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
> diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
> new file mode 100644
> index 000000000000..403a70b109ec
> --- /dev/null
> +++ b/include/linux/iio/adc-helpers.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +/*
> + * The industrial I/O ADC firmware property parsing helpers
> + *
> + * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
> + */
> +
> +#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
> +#define _INDUSTRIAL_IO_ADC_HELPERS_H_
> +
> +#include <linux/property.h>
> +
> +struct device;
> +struct iio_chan_spec;
> +
> +static inline int iio_adc_device_num_channels(struct device *dev)
> +{
> +       return device_get_child_node_count_named(dev, "channel");
> +}
> +
> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> +                                         const struct iio_chan_spec *template,
> +                                         int max_chan_id,
> +                                         struct iio_chan_spec **cs);
> +

There are some different opinions on this, but on the last patch I did
introducing a new namespace, the consensus seems to be that putting
the MODULE_IMPORT_NS() in the header file was convenient so that users
of the API don't have to remember to both include the header and add
the import macro.

> +#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
> --
> 2.48.1
>


From Jonathan.Cameron at huawei.com  Tue Mar  4 01:26:49 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 17:26:49 +0800
Subject: [PATCH 2/9] drivers/perf: hisi: Simplify the probe process for
 each DDRC version
In-Reply-To: <20250218092000.41641-3-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-3-yangyicong@huawei.com>
Message-ID: <20250304172649.0000189c@huawei.com>

On Tue, 18 Feb 2025 17:19:53 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> Version 1 and 2 of DDRC PMU also use different HID. Make use of
> struct acpi_device_id::driver_data for version specific information
> rather than judge the version register. This will help to
> simplify the probe process and also a bit easier for extension.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Looks good to me. Looking at this I can see the check_reg naming
is an existing thing so maybe leave that alone for now and consider
renaming as a future improvement in readability.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>


From Jonathan.Cameron at huawei.com  Tue Mar  4 01:27:43 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 17:27:43 +0800
Subject: [PATCH 3/9] drivers/perf: hisi: Add support for HiSilicon DDRC
 v3 PMU driver
In-Reply-To: <20250218092000.41641-4-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-4-yangyicong@huawei.com>
Message-ID: <20250304172743.0000211e@huawei.com>

On Tue, 18 Feb 2025 17:19:54 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> HiSilicon DDRC v3 PMU has the different interrupt register offset
> compared to the v2. Add device information of v3 PMU with ACPI
> HID HISI0235.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>



From ping.bai at nxp.com  Tue Mar  4 01:31:23 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue,  4 Mar 2025 17:31:23 +0800
Subject: [PATCH v2 0/4] Add i.MX943 basic dts support
Message-ID: <20250304093127.1954549-1-ping.bai@nxp.com>

i.MX943 is the first SoC of the i.MX94 family, all the SoCs
of this family are pin to pin compatible with only several
peripherals differance.

For i.MX943 device tree support, we split the dtsi into two
part, one for the common dtsi that shared for the i.MX94 family,
and an i.MX943 specific part.

Jacky Bai (4):
  dt-bindings: dma: fsl-edma: add interrupts-extended property
  dt-bindings: arm: fsl: add i.MX943 EVK board
  arm64: dts: freescale: Add basic dtsi for imx943
  arm64: dts: freescale: Add minimal dts support for imx943 evk

 .../devicetree/bindings/arm/fsl.yaml          |    6 +
 .../devicetree/bindings/dma/fsl,edma.yaml     |   11 +-
 arch/arm64/boot/dts/freescale/Makefile        |    1 +
 arch/arm64/boot/dts/freescale/imx94-clock.h   |  195 +++
 arch/arm64/boot/dts/freescale/imx94-pinfunc.h | 1542 +++++++++++++++++
 arch/arm64/boot/dts/freescale/imx94-power.h   |   41 +
 arch/arm64/boot/dts/freescale/imx94.dtsi      | 1141 ++++++++++++
 arch/arm64/boot/dts/freescale/imx943-evk.dts  |  196 +++
 arch/arm64/boot/dts/freescale/imx943.dtsi     |  148 ++
 9 files changed, 3280 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-clock.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-pinfunc.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-power.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94.dtsi
 create mode 100644 arch/arm64/boot/dts/freescale/imx943-evk.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx943.dtsi

-- 
2.34.1



From ping.bai at nxp.com  Tue Mar  4 01:31:24 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue,  4 Mar 2025 17:31:24 +0800
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add interrupts-extended property
In-Reply-To: <20250304093127.1954549-1-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
Message-ID: <20250304093127.1954549-2-ping.bai@nxp.com>

Add interrupts-extended property for edma that has multiple interrupt
controllers used.

Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v2 changes:
  - newly added entry
---
 Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
index d54140f18d34..549afb8611a9 100644
--- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
+++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
@@ -38,6 +38,10 @@ properties:
     minItems: 1
     maxItems: 64
 
+  interrupts-extended:
+    minItems: 1
+    maxItems: 65
+
   interrupt-names:
     minItems: 1
     maxItems: 64
@@ -87,9 +91,14 @@ required:
   - "#dma-cells"
   - compatible
   - reg
-  - interrupts
   - dma-channels
 
+oneOf:
+  - required:
+    - interrupts
+  - required:
+    - interrupts-extended
+
 allOf:
   - $ref: dma-controller.yaml#
   - if:
-- 
2.34.1



From ping.bai at nxp.com  Tue Mar  4 01:31:25 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue,  4 Mar 2025 17:31:25 +0800
Subject: [PATCH v2 2/4] dt-bindings: arm: fsl: add i.MX943 EVK board
In-Reply-To: <20250304093127.1954549-1-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
Message-ID: <20250304093127.1954549-3-ping.bai@nxp.com>

Add DT compatible string for NXP i.MX943 EVK board.

Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v2 changes:
  - newly added
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 371317554863..31c1d5e643d2 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1349,6 +1349,12 @@ properties:
               - fsl,imx93-14x14-evk       # i.MX93 14x14 EVK Board
           - const: fsl,imx93
 
+      - description: i.MX94 based Boards
+        items:
+          - enum:
+              - fsl,imx943-evk            # i.MX943 EVK Board
+          - const: fsl,imx94
+
       - description: i.MX95 based Boards
         items:
           - enum:
-- 
2.34.1



From ping.bai at nxp.com  Tue Mar  4 01:31:27 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue,  4 Mar 2025 17:31:27 +0800
Subject: [PATCH v2 4/4] arm64: dts: freescale: Add minimal dts support for imx943 evk
In-Reply-To: <20250304093127.1954549-1-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
Message-ID: <20250304093127.1954549-5-ping.bai@nxp.com>

Add the minimal board dts support for i.MX943 EVK. Only the
console uart, SD & eMMC are enabled for linux basic boot.

Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v2 changes:
  - newly added for board dts
---
 arch/arm64/boot/dts/freescale/Makefile       |   1 +
 arch/arm64/boot/dts/freescale/imx943-evk.dts | 196 +++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx943-evk.dts

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 839432153cc7..02863c09bb8b 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -282,6 +282,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx943-evk.dtb
 
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
 
diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts
new file mode 100644
index 000000000000..d4a204eaf5e5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024-2025 NXP
+ */
+
+/dts-v1/;
+
+#include "imx943.dtsi"
+
+/ {
+	compatible = "fsl,imx943-evk", "fsl,imx94";
+	model = "NXP i.MX943 EVK board";
+
+	aliases {
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		serial0 = &lpuart1;
+	};
+
+	chosen {
+		stdout-path = &lpuart1;
+	};
+
+	reg_usdhc2_vmmc: regulator-usdhc2 {
+		compatible = "regulator-fixed";
+		off-on-delay-us = <12000>;
+		pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-name = "VDD_SD2_3V3";
+		gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reserved-memory {
+		ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x80000000 0 0x7f000000>;
+			reusable;
+			size = <0 0x10000000>;
+			linux,cma-default;
+		};
+	};
+
+	memory at 80000000 {
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+		device_type = "memory";
+	};
+};
+
+&lpuart1 {
+	pinctrl-0 = <&pinctrl_uart1>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&scmi_iomuxc {
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			IMX94_PAD_UART1_TXD__LPUART1_TX		0x31e
+			IMX94_PAD_UART1_RXD__LPUART1_RX		0x31e
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x15fe
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x13fe
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x13fe
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x13fe
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x13fe
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x13fe
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x13fe
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x13fe
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x13fe
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x13fe
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x15fe
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x15fe
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x13fe
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x13fe
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x13fe
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x13fe
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x13fe
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CD_B__GPIO4_IO20		0x31e
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_reg_usdhc2_vmmc: usdhc2regvmmcgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_RESET_B__GPIO4_IO27	0x31e
+		>;
+	};
+};
+
+&usdhc1 {
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	pinctrl-3 = <&pinctrl_usdhc1>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	bus-width = <8>;
+	non-removable;
+	no-sdio;
+	no-sd;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	bus-width = <4>;
+	cd-gpios = <&gpio4 20 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_usdhc2_vmmc>;
+	fsl,cd-gpio-wakeup-disable;
+	status = "okay";
+};
+
+&wdog3 {
+	fsl,ext-reset-output;
+	status = "okay";
+};
-- 
2.34.1



From dietmar.eggemann at arm.com  Tue Mar  4 01:32:13 2025
From: dietmar.eggemann at arm.com (Dietmar Eggemann)
Date: Tue, 4 Mar 2025 10:32:13 +0100
Subject: [PATCH v11 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <21e74021-fb68-0003-f0f4-7f54dd674b9d@huawei.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-3-yangyicong@huawei.com>
 <8a9aedef-08d7-445f-9b67-85e74ec6bd50@arm.com>
 <21e74021-fb68-0003-f0f4-7f54dd674b9d@huawei.com>
Message-ID: <5435fd87-6209-4896-84cc-27a35ef3cea4@arm.com>

On 03/03/2025 15:03, Yicong Yang wrote:
> On 2025/2/28 19:11, Dietmar Eggemann wrote:
>> On 18/02/2025 15:10, Yicong Yang wrote:
>>> From: Yicong Yang <yangyicong at hisilicon.com>

[...]

>>> If a system have more than one SMT thread number the 2) may
>>
>> s/have/has
>>
>>> not handle it well, since there're multiple thread numbers in the
>>
>> multiple thread numbers other than 1, right?
> 
> according to the pr_warn_once() we implemented below it also includes the case
> where the system have one type of SMT cores and non-SMT cores (the thread number is 1):
> - 1 thread
> - X (!= 1) threads
> 
> Discussion made in [1] and I thought we have agreement (hope I understood correctly)
> that all the asymmetric cases need to notify. Do you and Sudeep think we should not
> warn in such case?

Systems with non-SMT and SMT-2 cores are IMHO a special case since for
them the '/sys/devices/system/cpu/smt' interface still works correctly.
And on X86 those systems do exist today.

IMHO, it would be awkward to see the message 'Heterogeneous SMT topology
is partly supported by SMT control' on arm64 but not on x86 on such a
system.

I do understand that this message is more tailored to theoretically
possible 'multiple SMT-X (X>1) core' systems (e.g. 1,2,4).

And here we cannot issue a '2 > ./control' since
cpu_smt_num_threads_valid() only returns true for 1 or 4.

IMHO, I would remove the warning and state clearly in the patch that for
systems with multiple SMT-X (X>1) cores, this interface only support SMT
completely on or off.

Example Arm64 DT:

cpu-map {
        cluster0 {
                core0 {
                        thread0 {
                                cpu = <&A53_0>;
                        };
                };
                core1 {
                        thread0 {
                                cpu = <&A53_1>;
                        };
                };
                core2 {
                        thread0 {
                                cpu = <&A53_2>;
                        };
                        thread1 {
                                cpu = <&A53_3>;
                        };
                };
                core3 {
                        thread0 {
                                cpu = <&A53_4>;
                        };
                        thread1 {
                                cpu = <&A53_5>;
                        };
                        thread2 {
                                cpu = <&A53_6>;
                        };
                        thread3 {
                                cpu = <&A53_7>;
                        };
                };
        };
};

# cat /proc/cpuinfo | grep ^processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3
processor	: 4
processor	: 5
processor	: 6
processor	: 7

/sys/devices/system/cpu/smt# echo 1 >control

# cat /proc/cpuinfo | grep ^processor
processor	: 0
processor	: 1
processor	: 2
processor	: 4

/sys/devices/system/cpu/smt# echo 2 >control
-bash: echo: write error: Invalid argument

[...]


From angelogioacchino.delregno at collabora.com  Tue Mar  4 01:32:58 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 10:32:58 +0100
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
Message-ID: <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>

Il 18/02/25 06:41, Jason-JH Lin ha scritto:
> MT8196 has 3 new hardware configuration compared with the previous SoC,
> which correspond to the 3 new driver data:
> 
> 1. mminfra_offset: For GCE data plane control
>     Since GCE has been moved into mminfra, GCE needs to append the
>     mminfra offset to the DRAM address when accessing the DRAM.
> 
> 2. gce_vm: For GCE hardware virtualization
>     Currently, the first version of the mt8196 mailbox controller only
>     requires setting the VM-related registers to enable the permissions
>     of a host VM.

I think that the GCE VM changes should go to a different commit, as that
looks like being something not critical for basic functionality of the
MMINFRA GCE.

I really like seeing support for that, but please split the basic stuff
from the extra functionality :-)

> 
> 3. dma_mask_bit: For dma address bit control
>     In order to avoid the hardware limitations of MT8196 accessing DRAM,
>     GCE needs to configure the DMA address to be less than 35 bits.
> 
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> ---
>   drivers/mailbox/mtk-cmdq-mailbox.c       | 90 +++++++++++++++++++++---
>   include/linux/mailbox/mtk-cmdq-mailbox.h |  2 +
>   2 files changed, 84 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
> index d186865b8dce..0abe10a7fef9 100644
> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> @@ -43,6 +43,17 @@
>   #define GCE_CTRL_BY_SW				GENMASK(2, 0)
>   #define GCE_DDR_EN				GENMASK(18, 16)
>   
> +#define GCE_VM_ID_MAP0			0x5018
> +#define GCE_VM_MAP0_ALL_HOST			GENMASK(29, 0)
> +#define GCE_VM_ID_MAP1			0x501c
> +#define GCE_VM_MAP1_ALL_HOST			GENMASK(29, 0)
> +#define GCE_VM_ID_MAP2			0x5020
> +#define GCE_VM_MAP2_ALL_HOST			GENMASK(29, 0)
> +#define GCE_VM_ID_MAP3			0x5024
> +#define GCE_VM_MAP3_ALL_HOST			GENMASK(5, 0)
> +#define GCE_VM_CPR_GSIZE		0x50c4
> +#define GCE_VM_CPR_GSIZE_HSOT			GENMASK(3, 0)

typo: GSIZE_HOST....

...but also, if you could add some brief description of what the VMIDs are used for
and what the GSIZE is... that'd be very much appreciated from whoever is reading
this.

The GCE stuff isn't even properly described in datasheets - I do (probably!)
understand what those are for, but asking people to get years of experience on
MediaTek to understand what's going on would be a bit rude, wouldn't it? :-D

> +
>   #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
>   #define CMDQ_THR_ENABLED		0x1
>   #define CMDQ_THR_DISABLED		0x0
> @@ -87,11 +98,24 @@ struct cmdq {
>   struct gce_plat {
>   	u32 thread_nr;
>   	u8 shift;
> +	dma_addr_t mminfra_offset;

It looks like this is exactly the DRAM's iostart... at least, I can see that in the
downstream devicetree that's where it starts.

	memory: memory at 80000000 {
		device_type = "memory";
		reg = <0 0x80000000 0 0x40000000>;
	};

It doesn't really look like being a coincidence, but, for the sake of asking:
is this just a coincidence? :-)

>   	bool control_by_sw;
>   	bool sw_ddr_en;
> +	bool gce_vm;
> +	u32 dma_mask_bit;
>   	u32 gce_num;
>   };
>   
> +static inline u32 cmdq_reg_shift_addr(dma_addr_t addr, const struct gce_plat *pdata)
> +{
> +	return ((addr + pdata->mminfra_offset) >> pdata->shift);
> +}
> +
> +static inline u32 cmdq_reg_revert_addr(dma_addr_t addr, const struct gce_plat *pdata)
> +{
> +	return ((addr << pdata->shift) - pdata->mminfra_offset);
> +}

I'm not sure that you really need those two functions... probably it's simply
cleaner and easier to just write that single line every time... and I'm
saying that especially for how you're using those functions, with some readl()
passed directly as param, decreasing human readability by "a whole lot" :-)

> +
>   static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
>   {
>   	WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
> @@ -112,6 +136,30 @@ u8 cmdq_get_shift_pa(struct mbox_chan *chan)
>   }
>   EXPORT_SYMBOL(cmdq_get_shift_pa);
>   
> +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan)
> +{
> +	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
> +
> +	return cmdq->pdata->mminfra_offset;
> +}
> +EXPORT_SYMBOL(cmdq_get_offset_pa);

I think I remember this get_offset_pa from the old times, then CK removed it (and I
was really happy about that disappearing), or am I confusing this with something
else?

(of course, this wasn't used for mminfra, but for something else!)

> +
> +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t addr)
> +{
> +	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
> +
> +	if (cmdq->pdata->mminfra_offset == 0)
> +		return false;
> +
> +	/*
> +	 * mminfra will recognize the addr that greater than the mminfra_offset
> +	 * as a transaction to DRAM.
> +	 * So the caller needs to append mminfra_offset for the true case.
> +	 */
> +	return (addr >= cmdq->pdata->mminfra_offset);


/**
  * cmdq_is_mminfra_gce() - Brief description
  * @args.....
  *
  * The MMINFRA GCE will recognize an address greater than DRAM iostart as a
  * DRAM transaction instead of ....xyz
  *
  * In order for callers to perform (xyz) transactions through the CMDQ, those
  * need to know if they are using a GCE located in MMINFRA.
  */
bool cmdq_is_mminfra_gce(...)
{
	return cmdq->pdata->mminfra_offset &&
	       (addr >= cmdq->pdata->mminfra_offset)

> +}
> +EXPORT_SYMBOL(cmdq_addr_need_offset);
> +

...but then, is there really no way of just handling the GCE being in MMINFRA
transparently from the callers? Do the callers really *need* to know that they're
using a new GCE?!

Another way of saying: can't we just handle the address translation in here instead
of instructing each and every driver about how to communicate with the new GCE?!


Cheers,
Angelo

>   static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
>   {
>   	u32 status;
> @@ -143,6 +191,17 @@ static void cmdq_init(struct cmdq *cmdq)
>   	u32 gctl_regval = 0;
>   
>   	WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
> +
> +	if (cmdq->pdata->gce_vm) {
> +		/* config cpr size for host vm */
> +		writel(GCE_VM_CPR_GSIZE_HSOT, cmdq->base + GCE_VM_CPR_GSIZE);
> +		/* config CPR_GSIZE before setting VM_ID_MAP to avoid data leakage */
> +		writel(GCE_VM_MAP0_ALL_HOST, cmdq->base + GCE_VM_ID_MAP0);
> +		writel(GCE_VM_MAP1_ALL_HOST, cmdq->base + GCE_VM_ID_MAP1);
> +		writel(GCE_VM_MAP2_ALL_HOST, cmdq->base + GCE_VM_ID_MAP2);
> +		writel(GCE_VM_MAP3_ALL_HOST, cmdq->base + GCE_VM_ID_MAP3);
> +	}
> +
>   	if (cmdq->pdata->control_by_sw)
>   		gctl_regval = GCE_CTRL_BY_SW;
>   	if (cmdq->pdata->sw_ddr_en)
> @@ -199,7 +258,7 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task)
>   				prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
>   	prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] =
>   		(u64)CMDQ_JUMP_BY_PA << 32 |
> -		(task->pa_base >> task->cmdq->pdata->shift);
> +		cmdq_reg_shift_addr(task->pa_base, task->cmdq->pdata);
>   	dma_sync_single_for_device(dev, prev_task->pa_base,
>   				   prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
>   
> @@ -264,7 +323,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
>   	else
>   		return;
>   
> -	curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift;
> +	curr_pa = cmdq_reg_shift_addr(readl(thread->base + CMDQ_THR_CURR_ADDR), cmdq->pdata);
>   
>   	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
>   				 list_entry) {
> @@ -416,9 +475,9 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
>   		 */
>   		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
>   
> -		writel(task->pa_base >> cmdq->pdata->shift,
> +		writel(cmdq_reg_shift_addr(task->pa_base, cmdq->pdata),
>   		       thread->base + CMDQ_THR_CURR_ADDR);
> -		writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift,
> +		writel(cmdq_reg_shift_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata),
>   		       thread->base + CMDQ_THR_END_ADDR);
>   
>   		writel(thread->priority, thread->base + CMDQ_THR_PRIORITY);
> @@ -426,10 +485,10 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
>   		writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK);
>   	} else {
>   		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> -		curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) <<
> -			cmdq->pdata->shift;
> -		end_pa = readl(thread->base + CMDQ_THR_END_ADDR) <<
> -			cmdq->pdata->shift;
> +		curr_pa = cmdq_reg_revert_addr(readl(thread->base + CMDQ_THR_CURR_ADDR),
> +					       cmdq->pdata);
> +		end_pa = cmdq_reg_revert_addr(readl(thread->base + CMDQ_THR_END_ADDR),
> +					      cmdq->pdata);
>   		/* check boundary */
>   		if (curr_pa == end_pa - CMDQ_INST_SIZE ||
>   		    curr_pa == end_pa) {
> @@ -663,6 +722,9 @@ static int cmdq_probe(struct platform_device *pdev)
>   	if (err)
>   		return err;
>   
> +	if (cmdq->pdata->dma_mask_bit)
> +		dma_set_coherent_mask(dev, DMA_BIT_MASK(cmdq->pdata->dma_mask_bit));
> +
>   	cmdq->mbox.dev = dev;
>   	cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr,
>   					sizeof(*cmdq->mbox.chans), GFP_KERNEL);
> @@ -782,6 +844,17 @@ static const struct gce_plat gce_plat_mt8195 = {
>   	.gce_num = 2
>   };
>   
> +static const struct gce_plat gce_plat_mt8196 = {
> +	.thread_nr = 32,
> +	.shift = 3,
> +	.mminfra_offset = 0x80000000, /* 2GB */
> +	.control_by_sw = true,
> +	.sw_ddr_en = true,
> +	.gce_vm = true,
> +	.dma_mask_bit = 35,
> +	.gce_num = 2
> +};
> +
>   static const struct of_device_id cmdq_of_ids[] = {
>   	{.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_mt6779},
>   	{.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_mt8173},
> @@ -790,6 +863,7 @@ static const struct of_device_id cmdq_of_ids[] = {
>   	{.compatible = "mediatek,mt8188-gce", .data = (void *)&gce_plat_mt8188},
>   	{.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_mt8192},
>   	{.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_mt8195},
> +	{.compatible = "mediatek,mt8196-gce", .data = (void *)&gce_plat_mt8196},
>   	{}
>   };
>   MODULE_DEVICE_TABLE(of, cmdq_of_ids);
> diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h
> index a8f0070c7aa9..79398bf95f8d 100644
> --- a/include/linux/mailbox/mtk-cmdq-mailbox.h
> +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
> @@ -79,5 +79,7 @@ struct cmdq_pkt {
>   };
>   
>   u8 cmdq_get_shift_pa(struct mbox_chan *chan);
> +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan);
> +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t addr);
>   
>   #endif /* __MTK_CMDQ_MAILBOX_H__ */



From angelogioacchino.delregno at collabora.com  Tue Mar  4 01:35:31 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 10:35:31 +0100
Subject: [PATCH v4 4/8] soc: mediatek: mtk-cmdq: Add pa_base parsing for
 unsupported subsys ID hardware
In-Reply-To: <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
Message-ID: <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>

Il 18/02/25 06:41, Jason-JH Lin ha scritto:
> When GCE executes instructions, the corresponding hardware register
> can be found through the subsys ID. For hardware that does not support
> subsys ID, its subsys ID will be set to invalid value and its physical
> address needs to be used to generate GCE instructions.
> 
> This commit adds a pa_base parsing flow to the cmdq_client_reg structure
> for these unsupported subsys ID hardware.
> 

Does this work only for the MMINFRA located GCEs, or does this work also for
the legacy ones in MT8173/83/88/92/95 // MT6795/6893/etc?

In order to actually review and decide, I do need to know :-)

Thanks,
Angelo




From angelogioacchino.delregno at collabora.com  Tue Mar  4 01:37:19 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 10:37:19 +0100
Subject: [PATCH v4 5/8] soc: mediatek: mtk-cmdq: Add mminfra_offset
 compatibility for DRAM address
In-Reply-To: <20250218054405.2017918-6-jason-jh.lin@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-6-jason-jh.lin@mediatek.com>
Message-ID: <c1395546-9cfe-4da9-b87a-e5cc392910f6@collabora.com>

Il 18/02/25 06:41, Jason-JH Lin ha scritto:
> Since GCE has been moved to mminfra in MT8196, all transactions from
> mminfra to DRAM will have their addresses adjusted by subtracting a
> mminfra offset.
> This information should be handled inside the CMDQ driver, allowing
> CMDQ users to call CMDQ APIs as usual.
> 
> Therefore, CMDQ driver needs to use the mbox API to get the
> mminfra_offset value of the SoC, and then add it to the DRAM address
> when generating instructions to ensure GCE accesses the correct DRAM
> address.
> 
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> ---
>   drivers/soc/mediatek/mtk-cmdq-helper.c | 35 ++++++++++++++++++++++++--
>   1 file changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
> index aa9853100d78..f2853a74af01 100644
> --- a/drivers/soc/mediatek/mtk-cmdq-helper.c
> +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
> @@ -314,10 +314,22 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value);
>   
>   int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr)
>   {
> +	struct cmdq_client *cl = (struct cmdq_client *)pkt->cl;
>   	const u16 high_addr_reg_idx  = CMDQ_THR_SPR_IDX0;
>   	const u16 value_reg_idx = CMDQ_THR_SPR_IDX1;
>   	int ret;
>   
> +	if (!cl) {
> +		pr_err("%s %d: pkt->cl is NULL!\n", __func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	if (cmdq_addr_need_offset(cl->chan, src_addr))
> +		src_addr += cmdq_get_offset_pa(cl->chan);

If the offset is just DRAM IOSTART, you could manage that differently in the cmdq
helper as well as the cmdq mailbox... :-)

> +
> +	if (cmdq_addr_need_offset(cl->chan, dst_addr))
> +		dst_addr += cmdq_get_offset_pa(cl->chan);
> +
Cheers,
Angelo


From wbg at kernel.org  Tue Mar  4 01:51:18 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 18:51:18 +0900
Subject: [PATCH v6 1/3] include: uapi: counter: Add
 microchip-tcb-capture.h
In-Reply-To: <20250227144023.64530-2-csokas.bence@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-2-csokas.bence@prolan.hu>
Message-ID: <Z8bNFjh85p2jqK9C@ishi>

On Thu, Feb 27, 2025 at 03:40:18PM +0100, Bence Cs?k?s wrote:
> Add UAPI header for the microchip-tcb-capture.c driver.
> This header will hold the various event channels, component numbers etc.
> used by this driver.
> 
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>

Oops, I almost missed this one! Make sure I'm included in the To field
for the next revision. ;-)

By the way, b4 is a nifty tool that can save you some work and help you
prep patch series for submission.[^1]

> +/*
> + * The driver defines the following components:
> + *
> + * Count 0
> + * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
> + * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
> + */
> +
> +enum counter_mchp_signals {
> +	COUNTER_MCHP_SIG_TIOA,
> +	COUNTER_MCHP_SIG_TIOB,
> +};

Are these meant to be used to identify the Signals in the
microchip-tcb-capture.c file. You should set the the counter_signal id
members to these enum constants then. However, this enum doesn't need to
be exposed to userspace in that case.

Or is the purpose of this to match the parent ID of the Signal when
you create Counter watches? That won't work safely the way you intend
because the Counter subsystem creates the userspace parent IDs
independent of the kernelspace counter_signal struct id member.

Right now the Counter subsystem just happens to create these parent IDs
sequentially from 0 because it was a simple way to implement it at the
time we introduced the feature. However, there is nothing that ensures
this will stay that way in the future, and in fact the design intention
was exactly to allow the possibility of a future change to this area of
code.

In other words, there's no gurantee the parent ID in userspace will
remain the same even between driver reloads. The intended way for
userspace to behave is to first identify the desired Signals at startup
based on their "name" sysfs attribute and then set Counter watches and
such accordingly thereafter as desired.

If that is the only purpose of enum counter_mchp_signals, then we can
omit this patch from the series and you won't need to send it in the
next revision.

William Breathitt Gray

[^1] https://b4.docs.kernel.org/en/latest/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/bd125560/attachment.sig>

From alexander.stein at ew.tq-group.com  Tue Mar  4 01:52:05 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue, 04 Mar 2025 10:52:05 +0100
Subject: [PATCH v5 1/2] dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode
 to schema and example
In-Reply-To: <20250304082434.834031-2-victor.liu@nxp.com>
References: <20250304082434.834031-1-victor.liu@nxp.com>
 <20250304082434.834031-2-victor.liu@nxp.com>
Message-ID: <3348463.44csPzL39Z@steina-w>

Hi,

thanks for the update.

Am Dienstag, 4. M?rz 2025, 09:24:33 CET schrieb Liu Ying:
> i.MX93 SoC mediamix blk-ctrl contains one DISPLAY_MUX register which
> configures parallel display format by using the "PARALLEL_DISP_FORMAT"
> field. Document the Parallel Display Format Configuration(PDFC) subnode
> and add the subnode to example.
> 
> Signed-off-by: Liu Ying <victor.liu at nxp.com>
> Reviewed-by: Conor Dooley <conor.dooley at microchip.com>
> ---
> v3->v5:
> * No change.
> 
> v2->v3:
> * Newly introduced to replace the standalone dt-binding in v1 and v2. (Rob)
> * Resend with Conor's R-b tag and with the patch rebased upon v6.11-rc1.
> 
>  .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> index b3554e7f9e76..3f550c30d93d 100644
> --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> @@ -24,6 +24,12 @@ properties:
>    reg:
>      maxItems: 1
>  
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 1
> +
>    '#power-domain-cells':
>      const: 1
>  
> @@ -46,9 +52,43 @@ properties:
>        - const: csi
>        - const: dsi
>  
> +  bridge at 60:
> +    type: object
> +    additionalProperties: false
> +
> +    properties:
> +      compatible:
> +        const: nxp,imx93-pdfc
> +
> +      reg:
> +        maxItems: 1
> +
> +      ports:
> +        $ref: /schemas/graph.yaml#/properties/ports
> +
> +        properties:
> +          port at 0:
> +            $ref: /schemas/graph.yaml#/properties/port
> +            description: Input port node to receive pixel data.
> +
> +          port at 1:
> +            $ref: /schemas/graph.yaml#/properties/port
> +            description: Output port node to downstream pixel data receivers.
> +
> +        required:
> +          - port at 0
> +          - port at 1
> +
> +    required:
> +      - compatible
> +      - reg
> +      - ports
> +
>  required:
>    - compatible
>    - reg
> +  - '#address-cells'
> +  - '#size-cells'
>    - power-domains
>    - clocks
>    - clock-names
> @@ -76,5 +116,33 @@ examples:
>                 <&clk IMX93_CLK_MIPI_DSI_GATE>;
>                 clock-names = "apb", "axi", "nic", "disp", "cam",
>                               "pxp", "lcdif", "isi", "csi", "dsi";
> +      #address-cells = <1>;
> +      #size-cells = <1>;
>        #power-domain-cells = <1>;
> +
> +      bridge at 60 {

Given that you add a subnode, I would assume Rob's comment from [1]
also applies to you here.

Despite that, looks good to me. With that fixed:
Reviewed-by: Alexander Stein <alexander.stein at ew.tq-group.com>

[1] https://lore.kernel.org/all/20250225145833.GB2361434-robh at kernel.org/

> +        compatible = "nxp,imx93-pdfc";
> +        reg = <0x60 0x4>;
> +
> +        ports {
> +          #address-cells = <1>;
> +          #size-cells = <0>;
> +
> +          port at 0 {
> +            reg = <0>;
> +
> +            pdfc_from_lcdif: endpoint {
> +              remote-endpoint = <&lcdif_to_pdfc>;
> +            };
> +          };
> +
> +          port at 1 {
> +            reg = <1>;
> +
> +            pdfc_to_panel: endpoint {
> +              remote-endpoint = <&panel_from_pdfc>;
> +            };
> +          };
> +        };
> +      };
>      };
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From alexander.stein at ew.tq-group.com  Tue Mar  4 01:52:21 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue, 04 Mar 2025 10:52:21 +0100
Subject: [PATCH v5 2/2] drm/bridge: imx: Add i.MX93 parallel display format
 configuration support
In-Reply-To: <20250304082434.834031-3-victor.liu@nxp.com>
References: <20250304082434.834031-1-victor.liu@nxp.com>
 <20250304082434.834031-3-victor.liu@nxp.com>
Message-ID: <8499738.T7Z3S40VBb@steina-w>

Hi,

thanks for the update.

Am Dienstag, 4. M?rz 2025, 09:24:34 CET schrieb Liu Ying:
> NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
> configures parallel display format by using the "PARALLEL_DISP_FORMAT"
> field. Add a DRM bridge driver to support the display format configuration.
> 
> Signed-off-by: Liu Ying <victor.liu at nxp.com>
> ---
> v4->v5:
> * Rebase upon next-20250303.  This causes the drop of .remove_new by using
>   devm_drm_bridge_add().  Also, this causes API change for
>   imx93_pdfc_bridge_atomic_enable().
> * Update year of copyright.
> 
> v3->v4:
> * Use dev_err_probe() in imx93_pdfc_bridge_probe(). (Krzysztof)
> * Drop MODULE_ALIAS(). (Krzysztof)
> * Update year of Copyright.
> 
> v2->v3:
> * No change.
> * Resend with the patch rebased upon v6.11-rc1.
> 
> v1->v2:
> * Set *num_input_fmts to zero in case
>   imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL.
> * Replace .remove callback with .remove_new callback in
>   imx93_pdfc_bridge_driver.
> 
>  drivers/gpu/drm/bridge/imx/Kconfig      |   8 +
>  drivers/gpu/drm/bridge/imx/Makefile     |   1 +
>  drivers/gpu/drm/bridge/imx/imx93-pdfc.c | 186 ++++++++++++++++++++++++
>  3 files changed, 195 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c
> 
> diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig
> index 9a480c6abb85..51138d74ddfb 100644
> --- a/drivers/gpu/drm/bridge/imx/Kconfig
> +++ b/drivers/gpu/drm/bridge/imx/Kconfig
> @@ -88,4 +88,12 @@ config DRM_IMX93_MIPI_DSI
>  	  Choose this to enable MIPI DSI controller found in Freescale i.MX93
>  	  processor.
>  
> +config DRM_IMX93_PARALLEL_DISP_FMT_CONFIG
> +	tristate "NXP i.MX93 parallel display format configuration"
> +	depends on OF
> +	select DRM_KMS_HELPER
> +	help
> +	  Choose this to enable parallel display format configuration
> +	  found in NXP i.MX93 processor.
> +
>  endif # ARCH_MXC || COMPILE_TEST
> diff --git a/drivers/gpu/drm/bridge/imx/Makefile b/drivers/gpu/drm/bridge/imx/Makefile
> index dd5d48584806..f4ccc5cbef72 100644
> --- a/drivers/gpu/drm/bridge/imx/Makefile
> +++ b/drivers/gpu/drm/bridge/imx/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
>  obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
>  obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
>  obj-$(CONFIG_DRM_IMX93_MIPI_DSI) += imx93-mipi-dsi.o
> +obj-$(CONFIG_DRM_IMX93_PARALLEL_DISP_FMT_CONFIG) += imx93-pdfc.o
> diff --git a/drivers/gpu/drm/bridge/imx/imx93-pdfc.c b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
> new file mode 100644
> index 000000000000..7dfb87e64197
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
> @@ -0,0 +1,186 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +/*
> + * Copyright 2022-2025 NXP
> + */
> +
> +#include <linux/media-bus-format.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drm_atomic_state_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_print.h>
> +
> +#define DISPLAY_MUX		0x60
> +#define  PARALLEL_DISP_FORMAT	0x700
> +
> +enum imx93_pdfc_format {
> +	RGB888_TO_RGB888 = 0x0,
> +	RGB888_TO_RGB666 = 0x1 << 8,
> +	RGB565_TO_RGB565 = 0x2 << 8,
> +};

How about?
#define  PARALLEL_DISP_FORMAT          GENMASK(10, 8)
#define  FORMAT_RGB888_TO_RGB888       FIELD_PREP(PARALLEL_DISP_FORMAT, 0)
#define  FORMAT_RGB888_TO_RGB666       FIELD_PREP(PARALLEL_DISP_FORMAT, 1)
#define  FORMAT_RGB565_TO_RGB565       FIELD_PREP(PARALLEL_DISP_FORMAT, 2)
#define  FORMAT_RGB555_TO_RGB555       FIELD_PREP(PARALLEL_DISP_FORMAT, 3)
#define  FORMAT_YUV_TO_YCBCR24         FIELD_PREP(PARALLEL_DISP_FORMAT, 4)
#define  FORMAT_YUV_TO_YUV444          FIELD_PREP(PARALLEL_DISP_FORMAT, 5)

> +
> +struct imx93_pdfc {
> +	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
> +	struct device *dev;
> +	struct regmap *regmap;
> +	u32 format;
> +};
> +
> +static int imx93_pdfc_bridge_attach(struct drm_bridge *bridge,
> +				    enum drm_bridge_attach_flags flags)
> +{
> +	struct imx93_pdfc *pdfc = bridge->driver_private;
> +
> +	return drm_bridge_attach(bridge->encoder, pdfc->next_bridge, bridge, flags);
> +}
> +
> +static void imx93_pdfc_bridge_atomic_enable(struct drm_bridge *bridge,
> +					    struct drm_atomic_state *state)
> +{
> +	struct imx93_pdfc *pdfc = bridge->driver_private;
> +
> +	regmap_update_bits(pdfc->regmap, DISPLAY_MUX, PARALLEL_DISP_FORMAT,
> +			   pdfc->format);
> +}
> +
> +static const u32 imx93_pdfc_bus_output_fmts[] = {
> +	MEDIA_BUS_FMT_RGB888_1X24,
> +	MEDIA_BUS_FMT_RGB666_1X18,
> +	MEDIA_BUS_FMT_RGB565_1X16,
> +	MEDIA_BUS_FMT_FIXED
> +};
> +
> +static bool imx93_pdfc_bus_output_fmt_supported(u32 fmt)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(imx93_pdfc_bus_output_fmts); i++) {
> +		if (imx93_pdfc_bus_output_fmts[i] == fmt)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static u32 *
> +imx93_pdfc_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> +					    struct drm_bridge_state *bridge_state,
> +					    struct drm_crtc_state *crtc_state,
> +					    struct drm_connector_state *conn_state,
> +					    u32 output_fmt,
> +					    unsigned int *num_input_fmts)
> +{
> +	u32 *input_fmts;
> +
> +	*num_input_fmts = 0;
> +
> +	if (!imx93_pdfc_bus_output_fmt_supported(output_fmt))
> +		return NULL;
> +
> +	input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
> +	if (!input_fmts)
> +		return NULL;
> +
> +	switch (output_fmt) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +	case MEDIA_BUS_FMT_RGB565_1X16:
> +		input_fmts[0] = output_fmt;
> +		break;
> +	case MEDIA_BUS_FMT_RGB666_1X18:
> +	case MEDIA_BUS_FMT_FIXED:
> +		input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
> +		break;
> +	}
> +
> +	*num_input_fmts = 1;
> +
> +	return input_fmts;
> +}
> +
> +static int imx93_pdfc_bridge_atomic_check(struct drm_bridge *bridge,
> +					  struct drm_bridge_state *bridge_state,
> +					  struct drm_crtc_state *crtc_state,
> +					  struct drm_connector_state *conn_state)
> +{
> +	struct imx93_pdfc *pdfc = bridge->driver_private;
> +
> +	switch (bridge_state->output_bus_cfg.format) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		pdfc->format = RGB888_TO_RGB888;
> +		break;
> +	case MEDIA_BUS_FMT_RGB666_1X18:
> +		pdfc->format = RGB888_TO_RGB666;
> +		break;
> +	case MEDIA_BUS_FMT_RGB565_1X16:
> +		pdfc->format = RGB565_TO_RGB565;

Do really need to store the bus format in device struct?
It's possible to access the bridge state in atomic_enable using
drm_atomic_get_bridge_state, no? TBH I don't know what are the best
practices though.
> +		break;
> +	default:
> +		DRM_DEV_DEBUG_DRIVER(pdfc->dev, "Unsupported output bus format: 0x%x\n",
> +				     bridge_state->output_bus_cfg.format);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct drm_bridge_funcs imx93_pdfc_bridge_funcs = {
> +	.attach			= imx93_pdfc_bridge_attach,
> +	.atomic_enable		= imx93_pdfc_bridge_atomic_enable,
> +	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
> +	.atomic_get_input_bus_fmts	= imx93_pdfc_bridge_atomic_get_input_bus_fmts,
> +	.atomic_check		= imx93_pdfc_bridge_atomic_check,
> +	.atomic_reset		= drm_atomic_helper_bridge_reset,
> +};
> +
> +static int imx93_pdfc_bridge_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct imx93_pdfc *pdfc;
> +
> +	pdfc = devm_kzalloc(dev, sizeof(*pdfc), GFP_KERNEL);
> +	if (!pdfc)
> +		return -ENOMEM;
> +
> +	pdfc->regmap = syscon_node_to_regmap(dev->of_node->parent);
> +	if (IS_ERR(pdfc->regmap))
> +		return dev_err_probe(dev, PTR_ERR(pdfc->regmap),
> +				     "failed to get regmap\n");
> +
> +	pdfc->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
> +	if (IS_ERR(pdfc->next_bridge))
> +		return dev_err_probe(dev, PTR_ERR(pdfc->next_bridge),
> +				     "failed to get next bridge\n");
> +
> +	pdfc->dev = dev;
> +	pdfc->bridge.driver_private = pdfc;
> +	pdfc->bridge.funcs = &imx93_pdfc_bridge_funcs;
> +	pdfc->bridge.of_node = dev->of_node;

pdfc->bridge.type = DRM_MODE_CONNECTOR_DPI;

Despite that looks god to me.

Best regards
Alexander

> +
> +	return devm_drm_bridge_add(dev, &pdfc->bridge);
> +}
> +
> +static const struct of_device_id imx93_pdfc_dt_ids[] = {
> +	{ .compatible = "nxp,imx93-pdfc", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, imx93_pdfc_dt_ids);
> +
> +static struct platform_driver imx93_pdfc_bridge_driver = {
> +	.probe	= imx93_pdfc_bridge_probe,
> +	.driver	= {
> +		.of_match_table = imx93_pdfc_dt_ids,
> +		.name = "imx93_pdfc",
> +	},
> +};
> +module_platform_driver(imx93_pdfc_bridge_driver);
> +
> +MODULE_DESCRIPTION("NXP i.MX93 parallel display format configuration driver");
> +MODULE_AUTHOR("Liu Ying <victor.liu at nxp.com>");
> +MODULE_LICENSE("GPL v2");
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From sudeep.holla at arm.com  Tue Mar  4 01:54:32 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 4 Mar 2025 09:54:32 +0000
Subject: [PATCH v2 2/4] KVM: arm64: Move the ffa_to_linux definition to
 the ffa header
In-Reply-To: <20250303234426.GB30749@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-3-sebastianene@google.com>
 <20250227202557.d3fd6ylzbaho4pvx@bogus>
 <Z8DxZY-09R6lwEW3@google.com>
 <86wmdapei8.wl-maz@kernel.org>
 <20250303234426.GB30749@willie-the-truck>
Message-ID: <Z8bN2MI5GYdVtGyE@bogus>

On Mon, Mar 03, 2025 at 11:44:28PM +0000, Will Deacon wrote:
> On Fri, Feb 28, 2025 at 10:09:19AM +0000, Marc Zyngier wrote:
> > On Thu, 27 Feb 2025 23:12:37 +0000,
> > Sebastian Ene <sebastianene at google.com> wrote:
> > >
> > > On Thu, Feb 27, 2025 at 08:25:57PM +0000, Sudeep Holla wrote:
> > > > On Thu, Feb 27, 2025 at 06:17:47PM +0000, Sebastian Ene wrote:
> > > > > Keep the ffa_to_linux error map in the header and move it away
> > > > > from the arm ffa driver to make it accessible for other components.
> > > >
> > > > Do you plan to push/target these changes for v6.15 ? If not, I can take
> > > > this patch with other FF-A changes in my tree for v6.15. Otherwise, it
> > > > is must go along with other changes.
> > > >
> > >
> > > Yes, feel free to pick them with your changes and we can push them
> > > later.
> >
> > So this series is not a 6.15 candidate?
>
> I think this is 6.15 stuff once it's been reviewed. Sudeep's message is
> a little confusing as it refers to 6.15 twice (I guess he meant 6.14 the
> first time?).
>

No I meant v6.15 both times ?. Since not much time before v6.15, I was
thinking if this is not v6.15 material, I can just take the driver change
for v6.15 itself via my tree. Now that, you have clarified, I will leave
it to you. I think it doesn't conflict with any of driver changes in -next.

In short, just to avoid any further confusion, please take it via arm64/kvm
tree.

--
Regards,
Sudeep


From pabeni at redhat.com  Tue Mar  4 01:54:34 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Tue, 4 Mar 2025 10:54:34 +0100
Subject: [PATCH net-next v9 3/6] arch: x86: add IPC mailbox accessor
 function and add SoC register access
In-Reply-To: <20250227121522.1802832-4-yong.liang.choong@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-4-yong.liang.choong@linux.intel.com>
Message-ID: <48885074-b590-41e6-9794-49ec12713cce@redhat.com>

On 2/27/25 1:15 PM, Choong Yong Liang wrote:
> From: "David E. Box" <david.e.box at linux.intel.com>
> 
> - Exports intel_pmc_ipc() for host access to the PMC IPC mailbox
> - Enables the host to access specific SoC registers through the PMC
> firmware using IPC commands. This access method is necessary for
> registers that are not available through direct Memory-Mapped I/O (MMIO),
> which is used for other accessible parts of the PMC.
> 
> Signed-off-by: David E. Box <david.e.box at linux.intel.com>
> Signed-off-by: Chao Qin <chao.qin at intel.com>
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>

Hans, Ilpo, are you ok with this patch going through the netdev/net-next
tree?

Thanks,

Paolo



From csokas.bence at prolan.hu  Tue Mar  4 01:57:05 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Tue, 4 Mar 2025 10:57:05 +0100
Subject: [PATCH v6 2/3] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <Z8alaOTjZeRuXnUI@ishi>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-3-csokas.bence@prolan.hu> <Z8alaOTjZeRuXnUI@ishi>
Message-ID: <9fcf9cf4-ba02-4583-9e14-bd650dbe32ee@prolan.hu>

Hi,

On 2025. 03. 04. 8:02, William Breathitt Gray wrote:
> In theory, the error code could be something else if of_irq_get() failed
> for any other reason. Handle all those error cases at once by checking
> IS_ERR(priv->irq) rather than just -EPROBE_DEFER. Then you can just
> return dev_err_probe() with priv->irq for the error code.

Yes, `of_irq_get()` can return an error, for example if the IRQ is not 
defined in the DT. In these cases, we just don't do IRQ, but still allow 
the device to probe. -EPROBE_DEFER is special in this case, because it 
signifies that there *is* an IRQ to set up, just not now.

>> +enum counter_mchp_event_channels {
>> +	COUNTER_MCHP_EVCHN_CV = 0,
>> +	COUNTER_MCHP_EVCHN_RA = 0,
>> +	COUNTER_MCHP_EVCHN_RB,
>> +	COUNTER_MCHP_EVCHN_RC,
>> +};
> 
> These would be better as preprocessor defines in case we need to
> introduce new events to channel 1 or 2 in the future. That would allow
> us to insert new events easily to existing channels without having to
> worry about its actual position in an enum list.

Okay. I personally like the enum interface more, as it is much cleaner, 
but if there's a good reason to use #define's, then so be it.

> One additional benefit is if we do end up introducing more Counts for
> the module. In that situation we would have multiple CV and RA/RB/RC per
> Counter device, but we can easily define a preprocessor macro to
> calculate the channel offset given the Count index. However, with enum
> structure we would have to manually add and maintain redundant defines
> for each Count, which is far less ideal.
> 
> William Breathitt Gray

Bence



From sudeep.holla at arm.com  Tue Mar  4 01:57:21 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 4 Mar 2025 09:57:21 +0000
Subject: [PATCH v2 2/4] KVM: arm64: Move the ffa_to_linux definition to
 the ffa header
In-Reply-To: <20250227181750.3606372-3-sebastianene@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-3-sebastianene@google.com>
Message-ID: <Z8bOgetwikZQnUqy@bogus>

On Thu, Feb 27, 2025 at 06:17:47PM +0000, Sebastian Ene wrote:
> Keep the ffa_to_linux error map in the header and move it away
> from the arm ffa driver to make it accessible for other components.
>

If you are reposting the series(which seems to be the case), please

s/KVM: arm64:/firmware: arm_ffa:/

 as it is not strictly KVM specific. With that, you can add

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

-- 
Regards,
Sudeep


From Jonathan.Cameron at huawei.com  Tue Mar  4 02:00:54 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:00:54 +0800
Subject: [PATCH 4/9] drivers/perf: hisi: Use ACPI driver_data to
 retrieve SLLC PMU information
In-Reply-To: <20250218092000.41641-5-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-5-yangyicong@huawei.com>
Message-ID: <20250304180054.00001ffc@huawei.com>

On Tue, 18 Feb 2025 17:19:55 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> Make use of struct acpi_device_id::driver_data for version specific
> information rather than judge the version register. This will help
> to simplify the probe process and also a bit easier for extension.
> 
> Factor out SLLC register definition to struct hisi_sllc_pmu_regs.
> No functional changes intended.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> ---
>  drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 191 ++++++++++++------
>  1 file changed, 125 insertions(+), 66 deletions(-)
> 
> diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> index dbd079016fc4..c1fd60d397c3 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> @@ -36,11 +36,14 @@
>  #define SLLC_SRCID_NONE			0x0
>  #define SLLC_TGTID_EN			BIT(5)
>  #define SLLC_TGTID_NONE			0x0
> -#define SLLC_TGTID_MIN_SHIFT		1
> -#define SLLC_TGTID_MAX_SHIFT		12
> -#define SLLC_SRCID_CMD_SHIFT		1
> -#define SLLC_SRCID_MSK_SHIFT		12
> +#define SLLC_TGTID_MIN_MSK		GENMASK(11, 1)
> +#define SLLC_TGTID_MAX_MSK		GENMASK(22, 12)
> +#define SLLC_SRCID_CMD_MSK		GENMASK(11, 1)
> +#define SLLC_SRCID_MSK_MSK		GENMASK(22, 12)
>  #define SLLC_NR_EVENTS			0x80
> +#define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
> +#define SLLC_FIRST_BIT(_mask)		(find_first_bit((const unsigned long *)&(_mask), 32))

If you do end up keeping this, I think there should be no need for outer brackets here.

> +#define SLLC_FIELD_PREP(_mask, _val)	(_mask & (_val << SLLC_FIRST_BIT(_mask)))



From sudeep.holla at arm.com  Tue Mar  4 02:02:30 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 4 Mar 2025 10:02:30 +0000
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <2fdea4f6-db98-4dc7-947f-e19ee54d2c3c@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com>
 <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com>
 <Z8WPiOweOjFZqTwN@bogus>
 <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>
 <2fdea4f6-db98-4dc7-947f-e19ee54d2c3c@arm.com>
Message-ID: <Z8bPtsO7dEV0lq2M@bogus>

On Tue, Mar 04, 2025 at 09:25:02AM +0100, Pierre Gondois wrote:
>
>
> On 3/3/25 15:40, Yicong Yang wrote:
> > On 2025/3/3 19:16, Sudeep Holla wrote:
> > > On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
> > > > On 2/28/25 20:06, Sudeep Holla wrote:
> > > > > > >
> > > > > > > Ditto as previous patch, can get rid if it is default 1.
> > > > > > >
> > > > > >
> > > > > > On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
> > > > > > cpu_smt_num_threads uninitialized to UINT_MAX:
> > > > > >
> > > > > > smt/active:0
> > > > > > smt/control:-1
> > > > > >
> > > > > > If cpu_smt_set_num_threads() is called:
> > > > > > active:0
> > > > > > control:notsupported
> > > > > >
> > > > > > So it might be slightly better to still initialize max_smt_thread_num.
> > > > > >
> > > > >
> > > > > Sure, what I meant is to have max_smt_thread_num set to 1 by default is
> > > > > that is what needed anyways and the above code does that now.
> > > > >
> > > > > Why not start with initialised to 1 instead ?
> > > > > Of course some current logic needs to change around testing it for zero.
> > > > >
> > > >
> > > > I think there would still be a way to check against the default value.
> > > > If we have:
> > > > unsigned int max_smt_thread_num = 1;
> > > >
> > > > then on a platform with 2 threads, the detection condition would trigger:
> > > > xa_for_each(&hetero_cpu, hetero_id, entry) {
> > > >      if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
> > > >          pr_warn_once("Heterogeneous SMT topology is partly
> > > >                        supported by SMT control\n");
> > > >
> > > > so we would need an additional variable:
> > > > bool is_initialized = false;
> > >
> > > Sure, we could do that or skip the check if max_smt_thread_num == 1 ?
> > >
> > > I mean
> > > 	if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)
> > >
>
> I think it will be problematic if we parse:
> - first a CPU with 1 thread
> - then a CPU with 2 threads
>
> in that case we should detect the 'Heterogeneous SMT topology',
> but we cannot because we don't know whether max_smt_thread_num=1
> because 1 is the default value or we found a CPU with one thread.

Right, but as per Dietmar's and my previous response, it may be a valid
case. See latest response from Dietmar which is explicitly requesting
support for this. It may need some special handling if we decide to support
that.

--
Regards,
Sudeep


From Jonathan.Cameron at huawei.com  Tue Mar  4 02:02:35 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:02:35 +0800
Subject: [PATCH 5/9] drivers/perf: hisi: Add support for HiSilicon SLLC
 v3 PMU driver
In-Reply-To: <20250218092000.41641-6-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-6-yangyicong@huawei.com>
Message-ID: <20250304180235.00005eb3@huawei.com>

On Tue, 18 Feb 2025 17:19:56 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> SLLC v3 PMU has the following changes compared to previous version:
> a) update the register layout
> b) update the definition of SRCID_CTRL and TGTID_CTRL registers.
>    To be compatible with v2, we use maximum width (11 bits)
>    and mask the extra length for themselves.
> c) remove latency events (driver does not need to be adapted).
> 
> SLLC v3 PMU is identified with HID HISI0264.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>




From csokas.bence at prolan.hu  Tue Mar  4 02:03:17 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Tue, 4 Mar 2025 11:03:17 +0100
Subject: [PATCH v6 3/3] counter: microchip-tcb-capture: Add capture
 extensions for registers RA/RB
In-Reply-To: <Z8awGBW8obpG1QPN@ishi>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-4-csokas.bence@prolan.hu> <Z8awGBW8obpG1QPN@ishi>
Message-ID: <1604dce5-7be6-4a95-a51c-0c760a6c9a76@prolan.hu>

Hi,

On 2025. 03. 04. 8:47, William Breathitt Gray wrote:
> It's cleaner to exit early on an error than to carry it to the end.
> Instead of if (!ret), perform an if (ret) return ret to exit early on an
> error, then simply return 0 at the end of the funtion.

Ok.

> The capture2 extension doesn't exist in this patch so remove this
> comment line.
> 
>> @@ -30,6 +33,12 @@ enum counter_mchp_signals {
>>   	COUNTER_MCHP_SIG_TIOB,
>>   };
>>   
>> +enum counter_mchp_capture_extensions {
>> +	COUNTER_MCHP_EXCAP_RA,
>> +	COUNTER_MCHP_EXCAP_RB,
>> +	COUNTER_MCHP_EXCAP_RC,
>> +};
> 
> Remove COUNTER_MCHP_EXCAP_RC for the same reason as above.
> 
> Also, I would argue for these to be preprocessor defines rather than
> enum for the same reasons as in my other review[^1].

Ok.

> One final comment: is RA/RB the best way to differentiate these? One of
> the benefits of abstraction layers is that users won't need to be
> concerned about the hardware details, and naming the capture values
> after their respective general register hardware names feels somewhat
> antithetic to that end.
> 
> I imagine there are better ways to refer to these that would communicate
> their relationship better, such as "primary capture" and "secondary
> capture". However at that point capture0 and capture1 would seem
> obvious enough, in which case you might not even need to expose these to
> userspace at all.

Hmm. Well, RA and RB is what it says in the datasheet, and since we 
don't do much processing on their value, I'd say we're still closely 
coupled to the hardware. So, if one wants to understand what they do, 
they will have to read the datasheet anyways in which case I think it's 
best to be consistent with it naming-wise.

> William Breathitt Gray
> 
> [^1] https://lore.kernel.org/all/Z8alaOTjZeRuXnUI at ishi/

Bence



From krzk at kernel.org  Tue Mar  4 02:03:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 11:03:47 +0100
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <21460de5-76a0-4576-a7e6-f4873e40de48@gmail.com>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
 <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
 <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>
 <027decb4-3fa9-40a5-9cf4-65f9a69b4566@kernel.org>
 <21460de5-76a0-4576-a7e6-f4873e40de48@gmail.com>
Message-ID: <9ec6c2c6-cf99-4c6e-8fc2-871716987c54@kernel.org>

On 04/03/2025 10:09, Ivaylo Ivanov wrote:
> On 3/4/25 09:21, Krzysztof Kozlowski wrote:
>> On 03/03/2025 18:18, Ivaylo Ivanov wrote:
>>> On 3/3/25 09:24, Krzysztof Kozlowski wrote:
>>>> On 02/03/2025 10:16, Ivaylo Ivanov wrote:
>>>>> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>>>>>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>>>>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>>>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>>> ---
>>>>>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>>>>>  1 file changed, 76 insertions(+)
>>>>>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>> You have undocumented dependencies which prevent merging this file.
>>>>>>>> First, dependencies have to be clearly expressed.
>>>>>>> They are, in the cover letter.
>>>>>> Where? I read it twice. Dependencies is the most important thing and
>>>>>> should scream at beginning of the cover letter, so if you bury them
>>>>>> somewhere deep it also would not matter - just like they were missing.
>>>>>>
>>>>>>>> Second, you should
>>>>>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>>>>>> be merged for current release (just use clocks with long names, without IDs).
>>>>>>> Sure
>>>>>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>>> new file mode 100644
>>>>>>>>> index 000000000..7d879ec8b
>>>>>>>>> --- /dev/null
>>>>>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>>> @@ -0,0 +1,76 @@
>>>>>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>>>>>> +%YAML 1.2
>>>>>>>>> +---
>>>>>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>>>> +
>>>>>>>>> +title: Exynos2200 USB controller PHY
>>>>>>>>> +
>>>>>>>>> +maintainers:
>>>>>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>>> +
>>>>>>>>> +description:
>>>>>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>>>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>>>>>> It's not (I think). There's a few reasons I've decided to make this separate
>>>>>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>>>>>
>>>>>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>>>>>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>>>>>> at diagram - they call it phy controller.
>>>>> Ughm. What? So in most exynos cases, there's a combination of multiple phys?
>>>>>>> for them, and all that is needed from it is to disable HWACG, assert/
>>>>>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>>>>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>>>>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>>>>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>>>>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>>>>>> Does it mean there is no USB DRD phy controller as before?
>>>>>>
>>>>>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
>>>>> So...
>>>>>
>>>>> DWC3 -> USBDRD (USBCON) -> PHYs?
>>>> No, drop last phy. You just wrote the same as me - two phys, because
>>>> usbdrd is the phy. In all existing designs there is no such controllable
>>>> object from the point of view of operating system.
>>> What? Per my understanding, the phy property should refer to whatever is
>>> is connected to dwc3 UTMI. In this case it's the so-called USBDRD phy (called
>>> usbcon in downstream). Considering that the eUSB2 IP definitely also has UTMI
>>> that has to be connected to something, doesn't that mean we have clearly
>> The entire point is that eUSB2 is connected to DWC3, no? That's exactly
>> how it is done for example on Qualcomm SoC. Otherwise you claim that
>> DWC3 controls one phy, which controls another phy which controls UTMI...
> 
> But where does the USBCON fit? Is it just a side controller? Why's it needed
> in the first place? This is what I don't understand.

I assume usbcon, so old usbdrd, is the second DWC3's phy, just like qcom
qmpphy.

> 
>>
>>> separated hardware blocks? Now, I guess one could argue that this USBCON
>>> hardware block could be classified as a syscon. But I don't see the problem
>>> with the current binding description, nor the modelling, as it represents
>>> how the hardware is (unless I've gotten it completely wrong).
>> It is the first time you use argument that it represents how the
>> hardware is and this is what we actually disagree. It is not like that.
>> You do not have chain of phys. Just look at any USB 3.0 DRD DWC diagram
>> from any Samsung SoC: where would you squeeze these two phys in relation
>> to what is called there "USB 3.0 PHY" which would be the third phy (!!!).
> 
> Yeah, my point was that it was different from any previous design. Now,
> I don't know if it's actually theoretically possible to design it like so. It's
> hard to just guess how the hardware is designed without having access
> to die shots, documentations or even just schematics.
> 
> Let's make it clear now, the changes your request are to document USBCON
> in the existing exynos binding, as well as to correct all explanations of how
> this block functions, right?

No, not necessarily. If USBCON is entirely different device than USBDRD
(different register layout, different features), then go ahead with a
new binding.

I was questioning your chain of PHYs and this should be investigated.


Best regards,
Krzysztof


From sudeep.holla at arm.com  Tue Mar  4 02:08:47 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:08:47 +0000
Subject: [PATCH v2] arm64: dts: corstone1000: Add definitions for secondary CPU cores
In-Reply-To: <20250303170012.469576-1-hugues.kambampiana@arm.com>
References: <Z8XSIx75B4mtcV48@bogus> <20250303170012.469576-1-hugues.kambampiana@arm.com>
Message-ID: <174108287362.420865.6246087705407586774.b4-ty@arm.com>

On Mon, 03 Mar 2025 17:00:12 +0000, Hugues KAMBA MPIANA wrote:
> Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
> enable support for secondary CPU cores.
>
> This update facilitates symmetric multiprocessing (SMP) support on
> the Corstone1000 Fixed Virtual Platform (FVP), allowing the
> secondary cores to be properly initialised and utilised.
>
> [...]

Applied to sudeep.holla/linux (for-next/juno/updates), thanks!

[1/1] arm64: dts: corstone1000: Add definitions for secondary CPU cores
      https://git.kernel.org/sudeep.holla/c/21b9f56cec8f
--
Regards,
Sudeep



From tglx at linutronix.de  Tue Mar  4 02:09:53 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Tue, 04 Mar 2025 11:09:53 +0100
Subject: [PATCH] irq: imx-irqsteer: irq_count can larger than registered
 irq
In-Reply-To: <20250304094513.1964356-1-ping.bai@nxp.com>
References: <20250304094513.1964356-1-ping.bai@nxp.com>
Message-ID: <87bjuh6r9q.ffs@tglx>

On Tue, Mar 04 2025 at 17:45, Jacky Bai wrote:
> From: Shengjiu Wang <shengjiu.wang at nxp.com>

Please use the proper subsystem prefix as documented:

  https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#patch-submission-notes

Also 'irq_count can larger than registered irq' is not a sentence and
tells absolutely nothing what this patch is about.

> The irqsteer IP itself can support up to 5 channels and each
> channel can support max 960 IRQs per. The actual number of

Can you please write out words, i.e. interrupts, hardware etc.. This is
a changelog and not twatter.

Aside of that: 'per.' does not make any sense. 'per' wants to be
followed by a noun: '...per $WHAT.'

> channels and IRQ per channel implemented in HW is SoC related.

> For previous i.MX SoCs, normally only one channel and max 512
> IRQ is implemented, But for i.MX94, the irqsteer HW is implemented
> for 960 IRQs, even it only has 384 IRQs connected.
>
> That means on i.MX94, the 'irq_number' is 6 but the 'irq_count' is

What means irq_number and irq_count here? 

> 15, so we need to increase the CHAN_MAX_OUTPUT_INT to 0xF(960 / 64)

What kind of math is 0xF(960 / 64) ? And what has this to do with
irq_number=6 ad irq_count=15?

Thanks,

        tglx



From Jonathan.Cameron at huawei.com  Tue Mar  4 02:11:46 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:11:46 +0800
Subject: [PATCH 6/9] drivers/perf: hisi: Relax the event number check of
 v2 PMUs
In-Reply-To: <20250218092000.41641-7-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-7-yangyicong@huawei.com>
Message-ID: <20250304181146.000042b3@huawei.com>

On Tue, 18 Feb 2025 17:19:57 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> The supported event number range of each Uncore PMUs is provided by
> each driver in hisi_pmu::check_event and out of range events
> will be rejected. A later version with expanded event number range
> needs to register the PMU with updated hisi_pmu::check_event
> even if it's the only update, which means the expanded events
> cannot be used unless the driver's updated. However the unsupported
> events won't be counted by the hardware so we can relax the event
> number check to allow the use the expanded events.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> ---
>  drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +-
>  drivers/perf/hisilicon/hisi_uncore_hha_pmu.c  | 7 +++----
>  drivers/perf/hisilicon/hisi_uncore_pa_pmu.c   | 2 +-
>  drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 3 +--
>  4 files changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> index 26eaa6d20c00..21c494881ca0 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> @@ -53,7 +53,7 @@
>  #define DDRC_V1_PERF_CTRL_EN	0x2
>  #define DDRC_V2_PERF_CTRL_EN	0x1
>  #define DDRC_V1_NR_EVENTS	0x7
> -#define DDRC_V2_NR_EVENTS	0x90
> +#define DDRC_V2_NR_EVENTS	0xFF
>  
>  #define DDRC_EVENT_CNTn(base, n)	((base) + (n) * 8)
>  #define DDRC_EVENT_TYPEn(base, n)	((base) + (n) * 4)
> diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> index ca609db86046..78cd6d67f209 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> @@ -47,9 +47,8 @@
>  #define HHA_SRCID_CMD		GENMASK(16, 6)
>  #define HHA_SRCID_MSK		GENMASK(30, 20)
>  #define HHA_DATSRC_SKT_EN	BIT(23)
> -#define HHA_EVTYPE_NONE		0xff
> +#define HHA_EVTYPE_MASK		GENMASK(7, 0)
Using something called mask in places where we previously
had something called nr_events seems a little odd.

renaming EVTYPE_NONE to EVTYPE_MASK seems valid given the
useage but I'd have a different define for the number
of events and not make both changes in one patch.

>  #define HHA_V1_NR_EVENT		0x65
> -#define HHA_V2_NR_EVENT		0xCE
>  
>  HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 10, 0);
>  HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 21, 11);
> @@ -197,7 +196,7 @@ static void hisi_hha_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
>  
>  	/* Write event code to HHA_EVENT_TYPEx register */
>  	val = readl(hha_pmu->base + reg);
> -	val &= ~(HHA_EVTYPE_NONE << shift);
> +	val &= ~(HHA_EVTYPE_MASK << shift);
>  	val |= (type << shift);
>  	writel(val, hha_pmu->base + reg);
>  }
> @@ -453,7 +452,7 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
>  
>  	if (hha_pmu->identifier >= HISI_PMU_V2) {
>  		hha_pmu->counter_bits = 64;
> -		hha_pmu->check_event = HHA_V2_NR_EVENT;
> +		hha_pmu->check_event = HHA_EVTYPE_MASK;
To me this makes little sense.  Should be HHA_MAX_NR_EVENT
or something like that.

>  		hha_pmu->pmu_events.attr_groups = hisi_hha_pmu_v2_attr_groups;
>  		hha_pmu->num_counters = HHA_V2_NR_COUNTERS;
>  	} else {

Jonathan


From krzk at kernel.org  Tue Mar  4 02:12:57 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 11:12:57 +0100
Subject: [PATCH v2] arm64: dts: corstone1000: Add definitions for
 secondary CPU cores
In-Reply-To: <174108287362.420865.6246087705407586774.b4-ty@arm.com>
References: <Z8XSIx75B4mtcV48@bogus>
 <20250303170012.469576-1-hugues.kambampiana@arm.com>
 <174108287362.420865.6246087705407586774.b4-ty@arm.com>
Message-ID: <f6c7feb3-e003-4bbc-8179-3a3df533d2d5@kernel.org>

On 04/03/2025 11:08, Sudeep Holla wrote:
> On Mon, 03 Mar 2025 17:00:12 +0000, Hugues KAMBA MPIANA wrote:
>> Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
>> enable support for secondary CPU cores.
>>
>> This update facilitates symmetric multiprocessing (SMP) support on
>> the Corstone1000 Fixed Virtual Platform (FVP), allowing the
>> secondary cores to be properly initialised and utilised.
>>
>> [...]
> 
> Applied to sudeep.holla/linux (for-next/juno/updates), thanks!
> 
> [1/1] arm64: dts: corstone1000: Add definitions for secondary CPU cores
>       https://git.kernel.org/sudeep.holla/c/21b9f56cec8f

Why? Nothing improved here comparing to v1.

Your comment are still valid and the patch is still not correct.

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar  4 02:13:29 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 11:13:29 +0100
Subject: [PATCH v2] arm64: dts: corstone1000: Add definitions for
 secondary CPU cores
In-Reply-To: <20250303170012.469576-1-hugues.kambampiana@arm.com>
References: <Z8XSIx75B4mtcV48@bogus>
 <20250303170012.469576-1-hugues.kambampiana@arm.com>
Message-ID: <eb423b6e-6142-4b78-b724-49a526a49d4d@kernel.org>

On 03/03/2025 18:00, Hugues KAMBA MPIANA wrote:
> Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
> enable support for secondary CPU cores.
> 
> This update facilitates symmetric multiprocessing (SMP) support on
> the Corstone1000 Fixed Virtual Platform (FVP), allowing the
> secondary cores to be properly initialised and utilised.
> 
> Only FVP platform will have SMP support and hence the secondary cpu definitions
> are not added to corstone1000.dtsi.
> 
> Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana at arm.com>
> ---
>  arch/arm64/boot/dts/arm/corstone1000-fvp.dts | 24 ++++++++++++++++++++
>  arch/arm64/boot/dts/arm/corstone1000.dtsi    |  2 +-
>  2 files changed, 25 insertions(+), 1 deletion(-)
> 
No, nothing improved.

Provide detailed changelog after the ---.

Do not attach (thread) your patchsets to some other threads (unrelated
or older versions). This buries them deep in the mailbox and might
interfere with applying entire sets.

Best regards,
Krzysztof


From neil.armstrong at linaro.org  Tue Mar  4 02:15:46 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 4 Mar 2025 11:15:46 +0100
Subject: [PATCH] pmdomain: amlogic: fix T7 ISP secpower
In-Reply-To: <20250303-fix-t7-pwrc-v1-1-b563612bcd86@amlogic.com>
References: <20250303-fix-t7-pwrc-v1-1-b563612bcd86@amlogic.com>
Message-ID: <2b5c44c8-4eca-45d2-9599-a4d00bf44f5e@linaro.org>

On 03/03/2025 10:06, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> 
> ISP and MIPI_ISP, these two have a parent-child relationship,
> ISP depends on MIPI_ISP.
> 
> Fixes: ca75e4b214c6 ("pmdomain: amlogic: Add support for T7 power domains controller")
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>   drivers/pmdomain/amlogic/meson-secure-pwrc.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> index 42ce41a2fe3a..ff76ea36835e 100644
> --- a/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> +++ b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> @@ -221,7 +221,7 @@ static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
>   	SEC_PD(T7_VI_CLK2,	0),
>   	/* ETH is for ethernet online wakeup, and should be always on */
>   	SEC_PD(T7_ETH,		GENPD_FLAG_ALWAYS_ON),
> -	SEC_PD(T7_ISP,		0),
> +	TOP_PD(T7_ISP,		0, PWRC_T7_MIPI_ISP_ID),
>   	SEC_PD(T7_MIPI_ISP,	0),
>   	TOP_PD(T7_GDC,		0, PWRC_T7_NIC3_ID),
>   	TOP_PD(T7_DEWARP,	0, PWRC_T7_NIC3_ID),
> 
> ---
> base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
> change-id: 20250303-fix-t7-pwrc-f33650b190ef
> 
> Best regards,

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From Jonathan.Cameron at huawei.com  Tue Mar  4 02:16:06 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:16:06 +0800
Subject: [PATCH 7/9] drivers/perf: hisi: Support PMUs with no interrupt
In-Reply-To: <20250218092000.41641-8-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-8-yangyicong@huawei.com>
Message-ID: <20250304181606.00000748@huawei.com>

On Tue, 18 Feb 2025 17:19:58 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> We'll have PMUs don't have an interrupt to indicate the counter
> overflow, but the Uncore PMU core assume all the PMUs have
> interrupt. So handle this case in the core. The existing PMUs
> won't be affected.
> 
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>


From andyshrk at 163.com  Tue Mar  4 02:16:19 2025
From: andyshrk at 163.com (Andy Yan)
Date: Tue, 4 Mar 2025 18:16:19 +0800 (CST)
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
 <563i7xcbbsxfezkgs4txsa6lar5tb5folp7zk7dc7sbvf54n6y@vqbtuwvj3fcw>
 <6046d805.2173.195566bd4cf.Coremail.andyshrk@163.com>
 <5g6qv47ufjfy4yvzpw3rw7xopyuikzi7k4n2habxoexor4kyb2@f7pwawo75kqu>
Message-ID: <17a6bdcc.a22e.19560a80576.Coremail.andyshrk@163.com>

Hi Dmitry,

? 2025-03-03 00:21:06?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
>On Sun, Mar 02, 2025 at 06:34:22PM +0800, Andy Yan wrote:
>> 
>> 
>> Hi Dmitry?
>>    Thank you for your review?
>>    Please also review my inline reply.
>>       
>> ? 2025-03-02 02:14:19?"Dmitry Baryshkov" <dmitry.baryshkov at linaro.org> ???
>> >On Sun, Feb 23, 2025 at 07:30:25PM +0800, Andy Yan wrote:
>> >> From: Andy Yan <andy.yan at rock-chips.com>
>> >> 
>> >> The DW DP TX Controller is compliant with the DisplayPort Specification
>> >> Version 1.4 with the following features:
>> >> 
>> >> * DisplayPort 1.4a
>> >> * Main Link: 1/2/4 lanes
>> >> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> >> * AUX channel 1Mbps
>> >> * Single Stream Transport(SST)
>> >> * Multistream Transport (MST)
>> >> *?Type-C support (alternate mode)
>> >> * HDCP 2.2, HDCP 1.3
>> >> * Supports up to 8/10 bits per color component
>> >> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> >> * Pixel clock up to 594MHz
>> >> * I2S, SPDIF audio interface
>> >> 
>> >> Add library with common helpers to make it can be shared with
>> >> other SoC.
>> >> 
>> >> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> >> 
>> >> drm/bridge: cleanup
>> >
>> >Stray line?
>> 
>> Sorry, will be removed.
>> 
>> >
>> >> 
>> >> ---
>> >> 
>> >>  drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
>> >>  drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
>> >>  drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2155 ++++++++++++++++++++++
>> >>  include/drm/bridge/dw_dp.h               |   19 +
>> >>  4 files changed, 2182 insertions(+)
>> >>  create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
>> >>  create mode 100644 include/drm/bridge/dw_dp.h
>> >> 
>> >> diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
>> >> index f3ab2f985f8c..2c5e532410de 100644
>> >> --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
>> >> +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
>> >> @@ -1,4 +1,11 @@
>> >>  # SPDX-License-Identifier: GPL-2.0-only
>> >> +config DRM_DW_DP
>> >> +	tristate
>> >> +	select DRM_DISPLAY_HELPER
>> >> +	select DRM_DISPLAY_DP_HELPER
>> >> +	select DRM_KMS_HELPER
>> >> +	select REGMAP_MMIO
>> >> +
>> >>  config DRM_DW_HDMI


..............

>> >> +		vsc.pixelformat = DP_PIXELFORMAT_RGB;
>> >> +		break;
>> >> +	}
>> >> +
>> >> +	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
>> >> +		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
>> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
>> >> +	} else {
>> >> +		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
>> >> +		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>> >> +	}
>> >> +
>> >> +	vsc.bpc = video->bpc;
>> >> +	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
>> >> +
>> >> +	dw_dp_vsc_sdp_pack(&vsc, &sdp);
>> >> +
>> >> +	return dw_dp_send_sdp(dp, &sdp);
>> >> +}
>> >> +
>> >> +static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
>> >> +{
>> >> +	switch (pixel_mode) {
>> >> +	case DW_DP_MP_SINGLE_PIXEL:
>> >> +	case DW_DP_MP_DUAL_PIXEL:
>> >> +	case DW_DP_MP_QUAD_PIXEL:
>> >> +		break;
>> >> +	default:
>> >> +		return -EINVAL;
>> >
>> >Is it possible?
>> 
>> This IP is configurable for single/dual/quad pixel modes?
>> It's  quad pixel mode on rk3588 and dual pixel mode on rk3576,
>> so we add this check here.
>
>My question was slightly different: is it possible to end up here in the
>'default' branch?

Sorry, I think I didn't get your key point here.
If someone gives an invalid pixel mode(not any of SINGLE/DUAL/QUAD_PIXEL ), 
then we go to the default branch return -ENVIAL,  then the dp_bridge_enable  call stop.
This is what we want here.

>
>> 
>> 
>> >
>> >> +	}

>> >> +#endif /* __DW_DP__ */
>> >> -- 
>> >> 2.34.1
>> >> 
>> >
>> >-- 
>> >With best wishes
>> >Dmitry
>
>-- 
>With best wishes
>Dmitry

From wbg at kernel.org  Tue Mar  4 02:18:49 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 19:18:49 +0900
Subject: [PATCH v6 2/3] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <9fcf9cf4-ba02-4583-9e14-bd650dbe32ee@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-3-csokas.bence@prolan.hu>
 <Z8alaOTjZeRuXnUI@ishi>
 <9fcf9cf4-ba02-4583-9e14-bd650dbe32ee@prolan.hu>
Message-ID: <Z8bTiTWa11iqxUnH@ishi>

On Tue, Mar 04, 2025 at 10:57:05AM +0100, Cs?k?s Bence wrote:
> On 2025. 03. 04. 8:02, William Breathitt Gray wrote:
> > In theory, the error code could be something else if of_irq_get() failed
> > for any other reason. Handle all those error cases at once by checking
> > IS_ERR(priv->irq) rather than just -EPROBE_DEFER. Then you can just
> > return dev_err_probe() with priv->irq for the error code.
> 
> Yes, `of_irq_get()` can return an error, for example if the IRQ is not
> defined in the DT. In these cases, we just don't do IRQ, but still allow the
> device to probe. -EPROBE_DEFER is special in this case, because it signifies
> that there *is* an IRQ to set up, just not now.

You're right, that makes sense. Thank you for explaining.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/b78d13f1/attachment.sig>

From wbg at kernel.org  Tue Mar  4 02:21:35 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 19:21:35 +0900
Subject: [PATCH v6 3/3] counter: microchip-tcb-capture: Add capture
 extensions for registers RA/RB
In-Reply-To: <1604dce5-7be6-4a95-a51c-0c760a6c9a76@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-4-csokas.bence@prolan.hu>
 <Z8awGBW8obpG1QPN@ishi>
 <1604dce5-7be6-4a95-a51c-0c760a6c9a76@prolan.hu>
Message-ID: <Z8bULwq70CAAQRSe@ishi>

On Tue, Mar 04, 2025 at 11:03:17AM +0100, Cs?k?s Bence wrote:
> On 2025. 03. 04. 8:47, William Breathitt Gray wrote:
> > One final comment: is RA/RB the best way to differentiate these? One of
> > the benefits of abstraction layers is that users won't need to be
> > concerned about the hardware details, and naming the capture values
> > after their respective general register hardware names feels somewhat
> > antithetic to that end.
> > 
> > I imagine there are better ways to refer to these that would communicate
> > their relationship better, such as "primary capture" and "secondary
> > capture". However at that point capture0 and capture1 would seem
> > obvious enough, in which case you might not even need to expose these to
> > userspace at all.
> 
> Hmm. Well, RA and RB is what it says in the datasheet, and since we don't do
> much processing on their value, I'd say we're still closely coupled to the
> hardware. So, if one wants to understand what they do, they will have to
> read the datasheet anyways in which case I think it's best to be consistent
> with it naming-wise.

All right, let's keep it as RA and RA then.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/6903fe45/attachment.sig>

From Jonathan.Cameron at huawei.com  Tue Mar  4 02:22:22 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:22:22 +0800
Subject: [PATCH 8/9] drivers/perf: hisi: Add support for HiSilicon NoC
 PMU
In-Reply-To: <20250218092000.41641-9-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-9-yangyicong@huawei.com>
Message-ID: <20250304182222.00006e5a@huawei.com>

On Tue, 18 Feb 2025 17:19:59 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> Adds the support for HiSilicon NoC (Network on Chip) PMU which
> will be used to monitor the events on the system bus. The PMU
> device will be named after the SCL ID (either Super CPU cluster
> or Super IO cluster) and the index ID, just similar to other
> HiSilicon Uncore PMUs. Below PMU formats are provided besides
> the event:
> 
> - ch: the transaction channel (data, request, response, etc) which
>   can be used to filter the counting.
> - tt_en: tracetag filtering enable. Just as other HiSilicon Uncore
>   PMUs the NoC PMU supports only counting the transactions with
>   tracetag.
> 
> The NoC PMU doesn't have an interrupt to indicate the overflow.
> However we have a 64 bit counter which is large enough and it's
> nearly impossible to overflow.
> 
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
A few minor comments inline.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
> ---
>  Documentation/admin-guide/perf/hisi-pmu.rst  |  11 +
>  drivers/perf/hisilicon/Makefile              |   3 +-
>  drivers/perf/hisilicon/hisi_uncore_noc_pmu.c | 391 +++++++++++++++++++
>  3 files changed, 404 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> 
> diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
> index 48992a0b8e94..d858bd3a8802 100644
> --- a/Documentation/admin-guide/perf/hisi-pmu.rst
> +++ b/Documentation/admin-guide/perf/hisi-pmu.rst
> @@ -112,6 +112,17 @@ uring channel. It is 2 bits. Some important codes are as follows:
>  - 2'b00: default value, count the events which sent to the both uring and
>    uring_ext channel;
>  
> +6. ch: NoC PMU supports to filter the event counts of certain transaction
supports filtering the event counts...
> +channel with this option. The current supported channels are as follows:
> +
> +- 3'b010: Request channel
> +- 3'b100: Snoop channel
> +- 3'b110: Response channel
> +- 3'b111: Data channel
> +
> +7. tt_en: NoC PMU supports to only count the transactions with tracetag by

supports counting only transactions that have tracetag set if this option is
set.

> +this option. See the 2nd list for more information about tracetag.
> +


> +static int hisi_noc_pmu_probe(struct platform_device *pdev)
> +{
> +	struct hisi_pmu *noc_pmu;
> +	char *name;
> +	int ret;
> +
> +	noc_pmu = devm_kzalloc(&pdev->dev, sizeof(*noc_pmu), GFP_KERNEL);
Quite a bit of use of &pdev->dev, maybe worth
struct device *dev = &pdev->dev; to shorten all these lines.

> +	if (!noc_pmu)
> +		return -ENOMEM;
> +
> +	/*
> +	 * HiSilicon Uncore PMU framework needs to get common hisi_pmu device
> +	 * by device's drvdata.

from device's drvdata



From Jonathan.Cameron at huawei.com  Tue Mar  4 02:24:27 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 4 Mar 2025 18:24:27 +0800
Subject: [PATCH 9/9] drivers/perf: hisi: Add support for HiSilicon MN
 PMU driver
In-Reply-To: <20250218092000.41641-10-yangyicong@huawei.com>
References: <20250218092000.41641-1-yangyicong@huawei.com>
	<20250218092000.41641-10-yangyicong@huawei.com>
Message-ID: <20250304182427.000076d9@huawei.com>

On Tue, 18 Feb 2025 17:20:00 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> MN (Miscellaneous Node) is a hybrid node in ARM CHI. It broadcasts the
> following two types of requests: DVM operations and PCIe configuration.
> MN PMU devices exist on both SCCL and SICL, so we named the MN pmu
> driver after SCL (Super cluster) ID.
> The MN PMU driver using the HiSilicon uncore PMU framework. And only
> the event parameter is supported.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Short and sweet

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>



From wbg at kernel.org  Tue Mar  4 02:28:42 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue,  4 Mar 2025 19:28:42 +0900
Subject: [PATCH] counter: stm32-lptimer-cnt: fix error handling when enabling
In-Reply-To: <20250224170657.3368236-1-fabrice.gasnier@foss.st.com>
References: <20250224170657.3368236-1-fabrice.gasnier@foss.st.com>
Message-ID: <174108402893.227977.9200776572329997415.b4-ty@kernel.org>


On Mon, 24 Feb 2025 18:06:57 +0100, Fabrice Gasnier wrote:
> In case the stm32_lptim_set_enable_state() fails to update CMP and ARR,
> a timeout error is raised, by regmap_read_poll_timeout. It may happen,
> when the lptimer runs on a slow clock, and the clock is gated only
> few times during the polling.
> 
> Badly, when this happen, STM32_LPTIM_ENABLE in CR register has been set.
> So the 'enable' state in sysfs wrongly lies on the counter being
> correctly enabled, due to CR is read as one in stm32_lptim_is_enabled().
> 
> [...]

Applied, thanks!

[1/1] counter: stm32-lptimer-cnt: fix error handling when enabling
      commit: 8744dcd4fc7800de2eb9369410470bb2930d4c14

Best regards,
-- 
William Breathitt Gray <wbg at kernel.org>


From sudeep.holla at arm.com  Tue Mar  4 02:30:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 4 Mar 2025 10:30:24 +0000
Subject: [PATCH v2] arm64: dts: corstone1000: Add definitions for
 secondary CPU cores
In-Reply-To: <f6c7feb3-e003-4bbc-8179-3a3df533d2d5@kernel.org>
References: <Z8XSIx75B4mtcV48@bogus>
 <20250303170012.469576-1-hugues.kambampiana@arm.com>
 <174108287362.420865.6246087705407586774.b4-ty@arm.com>
 <f6c7feb3-e003-4bbc-8179-3a3df533d2d5@kernel.org>
Message-ID: <Z8bWQDVebIehuftS@bogus>

On Tue, Mar 04, 2025 at 11:12:57AM +0100, Krzysztof Kozlowski wrote:
> On 04/03/2025 11:08, Sudeep Holla wrote:
> > On Mon, 03 Mar 2025 17:00:12 +0000, Hugues KAMBA MPIANA wrote:
> >> Add `cpu1`, `cpu2` and `cpu3` nodes to the Corstone1000 device tree to
> >> enable support for secondary CPU cores.
> >>
> >> This update facilitates symmetric multiprocessing (SMP) support on
> >> the Corstone1000 Fixed Virtual Platform (FVP), allowing the
> >> secondary cores to be properly initialised and utilised.
> >>
> >> [...]
> > 
> > Applied to sudeep.holla/linux (for-next/juno/updates), thanks!
> > 
> > [1/1] arm64: dts: corstone1000: Add definitions for secondary CPU cores
> >       https://git.kernel.org/sudeep.holla/c/21b9f56cec8f
> 
> Why? Nothing improved here comparing to v1.
> 
> Your comment are still valid and the patch is still not correct.
> 

It was not marked clearly or noted as change. I agree that is confusing.

However the following was added:

"Only FVP platform will have SMP support and hence the secondary cpu
definitions are not added to corstone1000.dtsi"

Hugues pinged me in private to explain why it is done in that way and I
asked him to add the reasoning in the commit message which he did but
failed to capture in the v1->v2 changelog. I mentioned it in private
again as he is new contributor to the kernel, I was less strict on him ?.

--
Regards,
Sudeep


From andre.przywara at arm.com  Tue Mar  4 02:36:50 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 4 Mar 2025 10:36:50 +0000
Subject: [PATCH v3 04/15] dt-bindings: clk: sunxi-ng: document Allwinner
 A523 CCU
In-Reply-To: <20250304-resilient-spiritual-crane-30d4e1@krzk-bin>
References: <20250304012805.28594-1-andre.przywara@arm.com>
	<20250304012805.28594-5-andre.przywara@arm.com>
	<20250304-resilient-spiritual-crane-30d4e1@krzk-bin>
Message-ID: <20250304103650.704fd28b@donnerap.manchester.arm.com>

On Tue, 4 Mar 2025 09:25:24 +0100
Krzysztof Kozlowski <krzk at kernel.org> wrote:

Hi,

> On Tue, Mar 04, 2025 at 01:27:54AM +0000, Andre Przywara wrote:
> > The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> > the main CCU.
> > 
> > The source clock list differs in some annoying details, and folding this
> > into the existing Allwinner CCU clock binding document gets quite
> > unwieldy, so create a new document for these CCUs.
> > Add the new compatible string, along with the required input clock
> > lists. This conditionally describes the input clock list, to make for
> > an easier patch adding the other CCUs.
> > 
> > Also add the DT binding headers, listing all the clocks with their ID
> > numbers.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> >  .../clock/allwinner,sun55i-a523-ccu.yaml      |  77 +++++++
> >  include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
> >  include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
> >  3 files changed, 354 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> >  create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
> >  create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
> > 
> > diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> > new file mode 100644
> > index 0000000000000..2eacaeaeabac7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> > @@ -0,0 +1,77 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Allwinner A523 Clock Control Unit
> > +
> > +maintainers:
> > +  - Andre Przywara <andre.przywara at arm.com>
> > +
> > +properties:
> > +  "#clock-cells":
> > +    const: 1
> > +
> > +  "#reset-cells":
> > +    const: 1
> > +
> > +  compatible:
> > +    enum:
> > +      - allwinner,sun55i-a523-ccu
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    minItems: 4  
> 
> Drop, redundant.
> 
> > +    maxItems: 4
> > +
> > +  clock-names:
> > +    minItems: 4
> > +    maxItems: 4  
> 
> Drop both and instead you need to list the items.

> 
> > +
> > +required:
> > +  - "#clock-cells"
> > +  - "#reset-cells"
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +
> > +if:  
> 
> Drop, you have here only one device, no need for if:then.

I know, and I do understand the redundancy of the minItems/maxItems above,
but as I wrote in the commit message, this paves the way for the follow up
patch and makes both more readable.
Apart from helping with the review, I didn't want to conflate both devices
into one patch, I think I saw people complaining about that in the past.

If you are fine with having them both added all in one go, I am happy to
just squash the patches.

Cheers,
Andre

> 
> Best regards,
> Krzysztof
> 



From ivo.ivanov.ivanov1 at gmail.com  Tue Mar  4 02:37:27 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Tue, 4 Mar 2025 12:37:27 +0200
Subject: [PATCH v2 3/8] dt-bindings: phy: add
 samsung,exynos2200-usbcon-phy schema file
In-Reply-To: <9ec6c2c6-cf99-4c6e-8fc2-871716987c54@kernel.org>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-4-ivo.ivanov.ivanov1@gmail.com>
 <20250224-curly-cyber-spaniel-efdc39@krzk-bin>
 <a4f63721-d094-4eda-b68a-6ef62ff54680@gmail.com>
 <c8184542-5dab-4403-bee4-867810397ae4@kernel.org>
 <4502b578-96e6-49e0-8f3b-54f6e5640c55@gmail.com>
 <354d6100-311f-44d7-b8a5-1fd671b651e3@kernel.org>
 <9fb63a04-5b3d-40cc-b96f-eb4f297f307e@gmail.com>
 <027decb4-3fa9-40a5-9cf4-65f9a69b4566@kernel.org>
 <21460de5-76a0-4576-a7e6-f4873e40de48@gmail.com>
 <9ec6c2c6-cf99-4c6e-8fc2-871716987c54@kernel.org>
Message-ID: <0b8f71cf-03ee-4b5f-94ba-92811fccb541@gmail.com>

On 3/4/25 12:03, Krzysztof Kozlowski wrote:
> On 04/03/2025 10:09, Ivaylo Ivanov wrote:
>> On 3/4/25 09:21, Krzysztof Kozlowski wrote:
>>> On 03/03/2025 18:18, Ivaylo Ivanov wrote:
>>>> On 3/3/25 09:24, Krzysztof Kozlowski wrote:
>>>>> On 02/03/2025 10:16, Ivaylo Ivanov wrote:
>>>>>> On 2/25/25 10:11, Krzysztof Kozlowski wrote:
>>>>>>> On 24/02/2025 11:48, Ivaylo Ivanov wrote:
>>>>>>>> On 2/24/25 10:56, Krzysztof Kozlowski wrote:
>>>>>>>>> On Sun, Feb 23, 2025 at 02:22:22PM +0200, Ivaylo Ivanov wrote:
>>>>>>>>>> The Exynos2200 SoC has a USB controller PHY, which acts as an
>>>>>>>>>> intermediary between a USB controller (typically DWC3) and other PHYs
>>>>>>>>>> (UTMI, PIPE3). Add a dt-binding schema for it.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>>>> ---
>>>>>>>>>>  .../phy/samsung,exynos2200-usbcon-phy.yaml    | 76 +++++++++++++++++++
>>>>>>>>>>  1 file changed, 76 insertions(+)
>>>>>>>>>>  create mode 100644 Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>>> You have undocumented dependencies which prevent merging this file.
>>>>>>>>> First, dependencies have to be clearly expressed.
>>>>>>>> They are, in the cover letter.
>>>>>>> Where? I read it twice. Dependencies is the most important thing and
>>>>>>> should scream at beginning of the cover letter, so if you bury them
>>>>>>> somewhere deep it also would not matter - just like they were missing.
>>>>>>>
>>>>>>>>> Second, you should
>>>>>>>>> rather decouple the code from header dependencies, otherwise this cannot
>>>>>>>>> be merged for current release (just use clocks with long names, without IDs).
>>>>>>>> Sure
>>>>>>>>>> diff --git a/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>>>> new file mode 100644
>>>>>>>>>> index 000000000..7d879ec8b
>>>>>>>>>> --- /dev/null
>>>>>>>>>> +++ b/Documentation/devicetree/bindings/phy/samsung,exynos2200-usbcon-phy.yaml
>>>>>>>>>> @@ -0,0 +1,76 @@
>>>>>>>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>>>>>>>> +%YAML 1.2
>>>>>>>>>> +---
>>>>>>>>>> +$id: http://devicetree.org/schemas/phy/samsung,exynos2200-usbcon-phy.yaml#
>>>>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>>>>> +
>>>>>>>>>> +title: Exynos2200 USB controller PHY
>>>>>>>>>> +
>>>>>>>>>> +maintainers:
>>>>>>>>>> +  - Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>>>>>>>>>> +
>>>>>>>>>> +description:
>>>>>>>>>> +  Exynos2200 USB controller PHY is an intermediary between a USB controller
>>>>>>>>>> +  (typically DWC3) and other PHYs (UTMI, PIPE3).
>>>>>>>>> Isn't this the same as usbdrd phy? see: samsung,usb3-drd-phy.yaml
>>>>>>>> It's not (I think). There's a few reasons I've decided to make this separate
>>>>>>>> from the usb3-drd-phy bindings and exynos5-usbdrd driver:
>>>>>>>>
>>>>>>>> 1. This PHY does not provide UTMI and PIPE3 on its own. There's no tuning
>>>>>>> USBDRD phy does not provide UTMI and PIPE on its own either if you look
>>>>>>> at diagram - they call it phy controller.
>>>>>> Ughm. What? So in most exynos cases, there's a combination of multiple phys?
>>>>>>>> for them, and all that is needed from it is to disable HWACG, assert/
>>>>>>>> deassert reset and force bvalid/vbusvalid. After that SNPS eUSB2
>>>>>>>> initialization can be done and USB2 works. If the USBCON phy is not set
>>>>>>>> up before the eUSB2 one, the device hangs, so there is definitely a
>>>>>>>> dependancy between them. For PIPE3 we'd need to control the pipe3
>>>>>>>> attaching/deattaching and then initialize the synopsys USBDP combophy.
>>>>>>> Does it mean there is no USB DRD phy controller as before?
>>>>>>>
>>>>>>> Anyway the problem is you have DWC3 -> PHY -> PHY. Looks one phy too many.
>>>>>> So...
>>>>>>
>>>>>> DWC3 -> USBDRD (USBCON) -> PHYs?
>>>>> No, drop last phy. You just wrote the same as me - two phys, because
>>>>> usbdrd is the phy. In all existing designs there is no such controllable
>>>>> object from the point of view of operating system.
>>>> What? Per my understanding, the phy property should refer to whatever is
>>>> is connected to dwc3 UTMI. In this case it's the so-called USBDRD phy (called
>>>> usbcon in downstream). Considering that the eUSB2 IP definitely also has UTMI
>>>> that has to be connected to something, doesn't that mean we have clearly
>>> The entire point is that eUSB2 is connected to DWC3, no? That's exactly
>>> how it is done for example on Qualcomm SoC. Otherwise you claim that
>>> DWC3 controls one phy, which controls another phy which controls UTMI...
>> But where does the USBCON fit? Is it just a side controller? Why's it needed
>> in the first place? This is what I don't understand.
> I assume usbcon, so old usbdrd, is the second DWC3's phy, just like qcom
> qmpphy.

Ugh. For qcoms, does the first phy depend on qmpphy? If we pass it as the second phy,
I don't know how the linkreset will happen. We also have a usbdp phy, which I
suspect is used for SS as well since it's a combophy by Synopsys.

https://gitlab.com/Mis012/sm-s908b-linux-source-code/-/blob/s22_restored_history/drivers/phy/samsung/phy-exynos-usbdrd-eusb.c#L1579

Best regards,
Ivaylo

>
>>>> separated hardware blocks? Now, I guess one could argue that this USBCON
>>>> hardware block could be classified as a syscon. But I don't see the problem
>>>> with the current binding description, nor the modelling, as it represents
>>>> how the hardware is (unless I've gotten it completely wrong).
>>> It is the first time you use argument that it represents how the
>>> hardware is and this is what we actually disagree. It is not like that.
>>> You do not have chain of phys. Just look at any USB 3.0 DRD DWC diagram
>>> from any Samsung SoC: where would you squeeze these two phys in relation
>>> to what is called there "USB 3.0 PHY" which would be the third phy (!!!).
>> Yeah, my point was that it was different from any previous design. Now,
>> I don't know if it's actually theoretically possible to design it like so. It's
>> hard to just guess how the hardware is designed without having access
>> to die shots, documentations or even just schematics.
>>
>> Let's make it clear now, the changes your request are to document USBCON
>> in the existing exynos binding, as well as to correct all explanations of how
>> this block functions, right?
> No, not necessarily. If USBCON is entirely different device than USBDRD
> (different register layout, different features), then go ahead with a
> new binding.
>
> I was questioning your chain of PHYs and this should be investigated.
>
>
> Best regards,
> Krzysztof



From sudeep.holla at arm.com  Tue Mar  4 02:59:28 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:59:28 +0000
Subject: [GIT PULL] firmware: arm_ffa: Updates for v6.15
Message-ID: <20250304105928.432997-1-sudeep.holla@arm.com>

Hi ARM SoC Team,

Please pull !

Regards,
Sudeep

-->8

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git tags/ffa-updates-6.15

for you to fetch changes up to cc0aac7ca17e0ea3ca84b552fc79f3e86fd07f53:

  firmware: arm_ffa: Set dma_mask for ffa devices (2025-02-28 11:20:06 +0000)

----------------------------------------------------------------
Arm FF-A updates for v6.15

This update primarily focuses on FF-A framework notification support
along with other improvements, including UUID handling enhancements
and various fixes.

1. FF-A framework notification upport

    - Adds support for multiple UUIDs per partition to register individual
      SRI callbacks.
    - Handles Rx buffer full framework notifications and provides a general
      interface for future extensions.

2. Improved multiple UUID/services per-partition handling

    - Adds support for UUID passing in FFA_MSG_SEND2, improving multiple
      UUID/service support in the driver.
    - Introduces a helper function to check whether a partition can
      receive REQUEST2 messages.

3. Partition handling generic improvements

    - Implements device unregistration for better partition cleanup.
    - Improves handling of the host partition presence in partition info.

4. FF-A version updates

    - Upgrades the driver version to FF-A v1.2.
    - Rejects major versions higher than the driver version as incompatible.

5. Big-Endian support fixes

    - Fixes big-endian issues in:
        __ffa_partition_info_regs_get()
        __ffa_partition_info_get()
    - Big-endian support is still incomplete, and only these changes can
      be verified without additional application/testing updates at the
      moment. We can discover all the partitions correctly with big-endian
      kernel now.

6. Miscellaneous fixes

    - Fixes function prototype misalignments in: sync_send_receive{,2}
    - Adds explicit type casting for return values from: FFA_VERSION
      and NOTIFICATION_INFO_GET
    - Corrects vCPU list parsing in ffa_notification_info_get().

7. UUID management in the driver and DMA mask updates

    - Replaces UUID buffer with the standard UUID format in ffa_partition_info
      structure.
    - Fixes a typo in some FF-A bus macros.
    - Sets dma_mask for FF-A devices.

In short, this update enhances notification handling, UUID support, and
overall robustness of the FF-A driver while addressing multiple fixes
and cleanups.

----------------------------------------------------------------
Sudeep Holla (21):
      firmware: arm_ffa: Replace SCMI by FF-A in the macro
      firmware: arm_ffa: Replace UUID buffer to standard UUID format
      firmware: arm_ffa: Align sync_send_receive{,2} function prototypes
      firmware: arm_ffa: Fix big-endian support in __ffa_partition_info_get()
      firmware: arm_ffa: Fix big-endian support in __ffa_partition_info_regs_get()
      firmware: arm_ffa: Handle the presence of host partition in the partition info
      firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions
      firmware: arm_ffa: Helper to check if a partition can receive REQUEST2 messages
      firmware: arm_ffa: Add support for passing UUID in FFA_MSG_SEND2
      firmware: arm_ffa: Upgrade FF-A version to v1.2 in the driver
      firmware: arm_ffa: Reject higher major version as incompatible
      firmware: arm_ffa: Remove unnecessary declaration of ffa_partitions_cleanup()
      firmware: arm_ffa: Refactoring to prepare for framework notification support
      firmware: arm_ffa: Stash ffa_device instead of notify_type in notifier_cb_info
      firmware: arm_ffa: Add support for {un,}registration of framework notifications
      firmware: arm_ffa: Add support for handling framework notifications
      firmware: arm_ffa: Allow multiple UUIDs per partition to register SRI callback
      firmware: arm_ffa: Handle ffa_notification_get correctly at virtual FF-A instance
      firmware: arm_ffa: Explicitly cast return value from FFA_VERSION before comparison
      firmware: arm_ffa: Explicitly cast return value from NOTIFICATION_INFO_GET
      firmware: arm_ffa: Skip the first/partition ID when parsing vCPU list

Viresh Kumar (2):
      firmware: arm_ffa: Refactor addition of partition information into XArray
      firmware: arm_ffa: Set dma_mask for ffa devices

 drivers/firmware/arm_ffa/bus.c    |  14 +-
 drivers/firmware/arm_ffa/driver.c | 532 ++++++++++++++++++++++++++++----------
 include/linux/arm_ffa.h           |  22 +-
 3 files changed, 422 insertions(+), 146 deletions(-)


From krzk at kernel.org  Tue Mar  4 02:59:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 11:59:53 +0100
Subject: [PATCH v2 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <20250304104434.481429-3-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-3-kevin_chen@aspeedtech.com>
Message-ID: <142a2edc-a668-4a6a-a4e8-eff3e8bf9e91@kernel.org>

On 04/03/2025 11:44, Kevin Chen wrote:
> The AST2600 has PCC controller in LPC, placed in LPC node.
> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> ---
>  arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> index 8ed715bd53aa..87dcacb78692 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> @@ -626,6 +626,13 @@ lpc_snoop: lpc-snoop at 80 {
>  					status = "disabled";
>  				};
>  
> +				lpc_pcc: lpc-pcc at 0 {
> +					compatible = "aspeed,ast2600-lpc-pcc";
> +					reg = <0x0 0x140>;
> +					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> +					status = "disabled";

Incomplete. Your driver clearly bails on missing ports...

Best regards,
Krzysztof


From iivanov at suse.de  Tue Mar  4 03:09:04 2025
From: iivanov at suse.de (Ivan T. Ivanov)
Date: Tue, 4 Mar 2025 13:09:04 +0200
Subject: [PATCH v12 1/5] Documentation/firmware: add imx/se to
 other_interfaces
In-Reply-To: <20250120-imx-se-if-v12-1-c5ec9754570c@nxp.com>
References: <20250120-imx-se-if-v12-0-c5ec9754570c@nxp.com>
 <20250120-imx-se-if-v12-1-c5ec9754570c@nxp.com>
Message-ID: <20250304110904.qr5rtsvkqa3l64t4@localhost.localdomain>

Hi,

On 01-20 22:22, Pankaj Gupta wrote:
> 
> Documents i.MX SoC's Service layer and C_DEV driver for selected SoC(s)
> that contains the NXP hardware IP(s) for Secure Enclaves(se) like:
> - NXP EdgeLock Enclave on i.MX93 & i.MX8ULP
> 
> Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
> ---
>  .../driver-api/firmware/other_interfaces.rst       | 121 +++++++++++++++++++++
>  1 file changed, 121 insertions(+)
> 

<snip>

> +
> +- c_dev:
> +  This layer offers character device contexts, created as '/dev/<se>_mux_chx'.
> +  Using these multiple device contexts that are getting multiplexed over a single MU,
> +  userspace application(s) can call fops like write/read to send the command message,
> +  and read back the command response message to/from Firmware.
> +  fops like read & write use the above defined service layer API(s) to communicate with
> +  Firmware.
> +
> +  Misc-device(/dev/<se>_mux_chn) synchronization protocol:
> +
> +                                Non-Secure               +   Secure
> +                                                         |
> +                                                         |
> +                  +---------+      +-------------+       |
> +                  | se_fw.c +<---->+imx-mailbox.c|       |
> +                  |         |      |  mailbox.c  +<-->+------+    +------+
> +                  +---+-----+      +-------------+    | MU X +<-->+ ELE |
> +                      |                               +------+    +------+
> +                      +----------------+                 |
> +                      |                |                 |
> +                      v                v                 |
> +                  logical           logical              |
> +                  receiver          waiter               |
> +                     +                 +                 |
> +                     |                 |                 |
> +                     |                 |                 |
> +                     |            +----+------+          |
> +                     |            |           |          |
> +                     |            |           |          |
> +              device_ctx     device_ctx     device_ctx   |
> +                                                         |
> +                User 0        User 1       User Y        |
> +                +------+      +------+     +------+      |
> +                |misc.c|      |misc.c|     |misc.c|      |
> + kernel space   +------+      +------+     +------+      |
> +                                                         |
> + +------------------------------------------------------ |
> +                    |             |           |          |
> + userspace     /dev/ele_muXch0    |           |          |
> +                          /dev/ele_muXch1     |          |
> +                                        /dev/ele_muXchY  |
> +                                                         |

I tried these patches on FRDM i.MX 93 board using this
devicetree excerpt:

	ele_if0: secure-enclave {
		compatible = "fsl,imx93-se";
		mbox-names = "tx", "rx";
		mboxes = <&s4muap 0 0>,
			<&s4muap 1 0>;
		memory-region = <&ele_reserved>;
	};

	ele_reserved: ele-reserved at a4120000 {
		compatible = "shared-dma-pool";
		reg = <0 0xa4120000 0 0x100000>;
		no-map;
	};

Unfortunately I do not see these device nodes, but only /dev/hsm0_ch0.

...
fsl-se secure-enclave: i.MX secure-enclave: hsm0 interface to firmware, configured.
...

This matches SE_TYPE_STR_HSM, so perhaps documentation needs updating.

Then I build imx-secure-enclave user space tools. I have to update device
nodes ELE_MU_HSM_PATH_xxx to match what c_dev exports, hopefully I
patched it in the right place :-)

Unfortunately just starting  nvm_daemon gives me following kernel
crash [1].

Please could you point me to the proper instruction how to test this?

Thank you,
Ivan

---
# ./usr/bin/nvm_daemon  ./etc/file ./etc/ 0

[  597.387002][    C0] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
[  597.396866][    C0] Mem abort info:
[  597.400347][    C0]   ESR = 0x0000000096000006
[  597.404775][    C0]   EC = 0x25: DABT (current EL), IL = 32 bits
[  597.410764][    C0]   SET = 0, FnV = 0
[  597.414499][    C0]   EA = 0, S1PTW = 0
[  597.418321][    C0]   FSC = 0x06: level 2 translation fault
[  597.423877][    C0] Data abort info:
[  597.427438][    C0]   ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000
[  597.433600][    C0]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[  597.439329][    C0]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[  597.445318][    C0] user pgtable: 4k pages, 48-bit VAs, pgdp=00000000a04ac000
[  597.452433][    C0] [0000000000000010] pgd=08000000a04b0003, p4d=08000000a04b0003, pud=08000000a04b3003, pmd=0000000000000000
[  597.463728][    C0] Internal error: Oops: 0000000096000006 [#1] SMP
[  597.469985][    C0] Modules linked in: af_packet trusted caam_jr caamhash_desc caamalg_desc caam error crypto_engine asn1_encoder authenc libdes btnxpuart snd_soc_fsl_asoc_card snd_soc_imx_audmux snd_soc_simple_card_utils snd_ac97_codec snd_soc_fsl_sai bluetooth fsl_imx9_ddr_perf imx_pcm_dma snd_soc_fsl_utils qoriq_thermal ecdh_generic rfkill snd_soc_fsl_mqs flexcan snd_soc_core snd_compress can_dev optee sec_enclave(OE) imx_rproc ac97_bus ffa_core snd_pcm_dmaengine tee snd_pcm snd_timer snd soundcore nls_iso8859_1 nls_cp437 vfat fat uio_pdrv_genirq fuse dmi_sysfs ip_tables x_tables spidev mmc_block rpmb_core tcpci tcpm typec rtc_pcf2127 crct10dif_ce pca9450_regulator ci_hdrc_imx 8021q ci_hdrc ghash_ce usb_otg_fsm garp gf128mul ulpi mrp sm4 sha2_ce udc_core sha256_arm64 pwrseq_simple roles ehci_hcd sha1_ce dwmac_imx usbcore phy_generic gpio_keys usb_common nvmem_imx_ocotp_ele usbmisc_imx sdhci_esdhc_imx stmmac_platform sdhci_pltfm stmmac cqhci sdhci pwm_imx_tpm mmc_core pcs_xpcs i2c_imx_lpi2c phylink spi_fsl_lpspi imx7ulp_wdt
[  597.470224][    C0]  fsl_edma fixed overlay btrfs blake2b_generic xor xor_neon raid6_pq libcrc32c sunrpc dm_mirror dm_region_hash dm_log dm_mod be2iscsi bnx2i cnic uio cxgb4i cxgb4 tls libcxgbi libcxgb qla4xxx iscsi_boot_sysfs iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi sd_mod sg scsi_mod scsi_common br_netfilter bridge stp llc efivarfs aes_neon_bs aes_neon_blk aes_ce_blk aes_ce_cipher
[  597.595841][    C0] Supported: No, Unreleased kernel
[  597.600794][    C0] CPU: 0 UID: 0 PID: 1912 Comm: nvm_daemon Tainted: G           OE        6.12.0-g6dd51d0 #1  (unreleased) 1bbfa4b46f0796a1c0b0abee639edd3b3230f00f
[  597.617891][    C0] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[  597.623877][    C0] Hardware name: fsl NXP i.MX93 11X11 FRDM board/NXP i.MX93 11X11 FRDM board, BIOS 2024.04-00004-g27baba14a58-dirty 04/01/2024
[  597.636801][    C0] pstate: 804000c9 (Nzcv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  597.644443][    C0] pc : se_if_rx_callback+0xa8/0x1f0 [sec_enclave]
[  597.650709][    C0] lr : mbox_chan_received_data+0x24/0x40
[  597.656187][    C0] sp : ffff800080003e20
[  597.660182][    C0] x29: ffff800080003e20 x28: ffff000085e60080 x27: 000000000000001b
[  597.667999][    C0] x26: ffff0000e89f388c x25: 0000000000000004 x24: ffff0000996a4ac8
[  597.675816][    C0] x23: ffff0000a43e3810 x22: ffff0000996a4ac8 x21: ffff0000996a4a80
[  597.683634][    C0] x20: 000000000000000c x19: ffff0000e89f3880 x18: 0000000000000000
[  597.691451][    C0] x17: ffff80007d89b000 x16: ffff800080000000 x15: 0000000000000000
[  597.699268][    C0] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[  597.707086][    C0] x11: 0000000000000040 x10: ffff0000801fab30 x9 : ffff800080cbfbfc
[  597.714903][    C0] x8 : ffff000080400948 x7 : 0000000000000000 x6 : 0000000000000000
[  597.722720][    C0] x5 : 0000000000000008 x4 : 000000000000000c x3 : 00000000e1100307
[  597.730538][    C0] x2 : 0000000000000000 x1 : ffff80007bb5fb98 x0 : ffff0000a43e3810
[  597.738356][    C0] Call trace:
[  597.741485][    C0]  se_if_rx_callback+0xa8/0x1f0 [sec_enclave eaa590c7f5850e16202e831d5a0ef9bbd976ab91]
[  597.750957][    C0]  mbox_chan_received_data+0x24/0x40
[  597.756087][    C0]  imx_mu_specific_rx+0x1ec/0x280
[  597.760958][    C0]  imx_mu_isr+0x314/0x340
[  597.765135][    C0]  __handle_irq_event_percpu+0x58/0x240
[  597.770526][    C0]  handle_irq_event+0x54/0xd0
[  597.775041][    C0]  handle_fasteoi_irq+0xac/0x1e0
[  597.779825][    C0]  handle_irq_desc+0x48/0x70
[  597.784254][    C0]  generic_handle_domain_irq+0x24/0x40
[  597.789549][    C0]  gic_handle_irq+0x11c/0x260
[  597.794073][    C0]  call_on_irq_stack+0x24/0x30
[  597.798684][    C0]  do_interrupt_handler+0x88/0xa0
[  597.803554][    C0]  el1_interrupt+0x44/0xd0
[  597.807818][    C0]  el1h_64_irq_handler+0x18/0x30
[  597.812602][    C0]  el1h_64_irq+0x7c/0x80
[  597.816684][    C0]  _raw_spin_unlock_irq+0x14/0x70
[  597.821555][    C0]  wait_for_completion_interruptible+0x28/0x50
[  597.827544][    C0]  ele_msg_rcv+0xa0/0x100 [sec_enclave eaa590c7f5850e16202e831d5a0ef9bbd976ab91]
[  597.836488][    C0]  se_if_fops_read+0xc8/0x1f0 [sec_enclave eaa590c7f5850e16202e831d5a0ef9bbd976ab91]
[  597.845779][    C0]  vfs_read+0xcc/0x320
[  597.849696][    C0]  ksys_read+0x78/0x120
[  597.853691][    C0]  __arm64_sys_read+0x24/0x40
[  597.858207][    C0]  invoke_syscall+0x70/0x100
[  597.862644][    C0]  el0_svc_common.constprop.0+0x48/0xf0
[  597.868034][    C0]  do_el0_svc+0x24/0x40
[  597.872038][    C0]  el0_svc+0x3c/0x170
[  597.875869][    C0]  el0t_64_sync_handler+0x120/0x130
[  597.880913][    C0]  el0t_64_sync+0x1a8/0x1b0
[  597.885258][    C0] Code: b9400263 2a1403e4 f0fffe61 912e6021 (f9400842)
[  597.892035][    C0] ---[ end trace 0000000000000000 ]---
[  597.897330][    C0] Kernel panic - not syncing: Oops: Fatal exception in interrupt
[  597.904878][    C0] SMP: stopping secondary CPUs
[  597.909521][    C0] Kernel Offset: disabled
[  597.913691][    C0] CPU features: 0x0,0000000c,00000004,00280928,4201721b
[  597.920468][    C0] Memory Limit: none
[  597.924205][    C0] Rebooting in 90 seconds..



From peter.griffin at linaro.org  Tue Mar  4 03:10:06 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Tue, 4 Mar 2025 11:10:06 +0000
Subject: [PATCH 5/6] scsi: ufs: exynos: Move phy calls to .exit() callback
In-Reply-To: <51ec6f40-c62a-418b-a538-082e3ad887cb@acm.org>
References: <20250226220414.343659-1-peter.griffin@linaro.org>
 <20250226220414.343659-6-peter.griffin@linaro.org> <51ec6f40-c62a-418b-a538-082e3ad887cb@acm.org>
Message-ID: <CADrjBPqw-kt+4fLfJCziAJrtcV4gVM9Gubtq=7Xb8sgxq-i8uQ@mail.gmail.com>

Hi Bart,

Thanks for your review feedback!

On Fri, 28 Feb 2025 at 19:20, Bart Van Assche <bvanassche at acm.org> wrote:
>
> On 2/26/25 2:04 PM, Peter Griffin wrote:
> > +static void exynos_ufs_exit(struct ufs_hba *hba)
> > +{
> > +     struct exynos_ufs *ufs = ufshcd_get_variant(hba);
> > +
> > +     phy_power_off(ufs->phy);
> > +     phy_exit(ufs->phy);
> > +}
> > +
> > +
>
> For future patches, please follow the convention that is used elsewhere
> in the kernel and separate functions with a single blank line instead of
> two.

That was an oversight on my part, will fix.

Thanks,

Peter


From leo.yan at arm.com  Tue Mar  4 03:12:28 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:28 +0000
Subject: [PATCH v4 00/12] perf script: Refactor branch flags for Arm SPE
Message-ID: <20250304111240.3378214-1-leo.yan@arm.com>

This patch series refactors branch flags for support Arm SPE.  The patch
set is divided into two parts, the first part is for refactoring common
code and the second part is for enabling Arm SPE.

For refactoring branch flags, the sample flaghs are classified as branch
types and events.  A program branch type can be conditional branch,
function call, return or expection taken.  A branch event happens when
taking a branch.  This series combines branch types and the associated
events to present a sample flag.

The second part is to enable Arm SPE's sample flags for expressing
branch types and events, and support branch stack.

Patches 01 - 03 are to refactor branch types and branch events.
Patches 04, 05 extend to support not-taken event.

Patch 06 is to fix a bug for parsing ldst operations.  Without this fix,
the seqential changes will cause breaking for memory samples.

Patches 07 - 10 enables branch flags in Arm SPE.  This allows to print
out sample flags for samples.

Patch 11 supports branch stack for Arm SPE.  Patch 12 is an enhancement
for PBT feature.

Changes from v3:
- Deleted unnecessary change for left-justified printing in patch 01
  (Adrian).

Changes from v2:
- Added a new patch 06 for fixing the ldst operation bug (James).
- Added James' review tags (except the new added patch 06).
- Removed a wrong output result in the last patch's commit log.

Changes from v1:
- For patch 05, changed to append the 'not_taken' bit in the branch_flags.
  This can avoid altering bit layout and cause breakage.
- Added Ian's review tags.


Leo Yan (12):
  perf script: Make printing flags reliable
  perf script: Refactor sample_flags_to_name() function
  perf script: Separate events from branch types
  perf script: Add not taken event for branches
  perf script: Add not taken event for branch stack
  perf arm-spe: Fix load-store operation checking
  perf arm-spe: Extend branch operations
  perf arm-spe: Decode transactional event
  perf arm-spe: Fill branch operations and events to record
  perf arm-spe: Set sample flags with supplement info
  perf arm-spe: Add branch stack
  perf arm-spe: Support previous branch target (PBT) address

 tools/perf/builtin-script.c                   |  29 ++--
 .../util/arm-spe-decoder/arm-spe-decoder.c    |  23 ++-
 .../util/arm-spe-decoder/arm-spe-decoder.h    |  11 +-
 .../arm-spe-decoder/arm-spe-pkt-decoder.c     |  14 +-
 .../arm-spe-decoder/arm-spe-pkt-decoder.h     |  12 +-
 tools/perf/util/arm-spe.c                     | 143 +++++++++++++++++-
 tools/perf/util/branch.h                      |   3 +-
 tools/perf/util/event.h                       |  12 +-
 tools/perf/util/trace-event-scripting.c       | 116 ++++++++++----
 tools/perf/util/trace-event.h                 |   2 +
 10 files changed, 313 insertions(+), 52 deletions(-)

-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:29 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:29 +0000
Subject: [PATCH v4 01/12] perf script: Make printing flags reliable
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-2-leo.yan@arm.com>

Add a check for the generated string of flags.  Print out the raw number
if the string generation fails.

Use the SAMPLE_FLAGS_STR_ALIGNED_SIZE macro to replace the value '21'.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/builtin-script.c   | 9 +++++++--
 tools/perf/util/trace-event.h | 2 ++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d797cec4f054..8ca04293d335 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1709,9 +1709,14 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
 static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
 {
 	char str[SAMPLE_FLAGS_BUF_SIZE];
+	int ret;
+
+	ret = perf_sample__sprintf_flags(flags, str, sizeof(str));
+	if (ret < 0)
+		return fprintf(fp, "  raw flags:0x%-*x ",
+			       SAMPLE_FLAGS_STR_ALIGNED_SIZE - 12, flags);
 
-	perf_sample__sprintf_flags(flags, str, sizeof(str));
-	return fprintf(fp, "  %-21s ", str);
+	return fprintf(fp, "  %-*s ", SAMPLE_FLAGS_STR_ALIGNED_SIZE, str);
 }
 
 struct printer_data {
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index ac9fde2f980c..71e680bc3d4b 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -145,6 +145,8 @@ int common_flags(struct scripting_context *context);
 int common_lock_depth(struct scripting_context *context);
 
 #define SAMPLE_FLAGS_BUF_SIZE 64
+#define SAMPLE_FLAGS_STR_ALIGNED_SIZE	21
+
 int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz);
 
 #if defined(LIBTRACEEVENT_VERSION) &&  LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0)
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:30 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:30 +0000
Subject: [PATCH v4 02/12] perf script: Refactor sample_flags_to_name() function
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-3-leo.yan@arm.com>

When generating a string for sample flags, the sample_flags_to_name()
function lacks the ability to parse the trace start bit or trace end bit.
Therefore, the function is invoked multiple times after clearing its
unsupported bits.

This commit improves the sample_flags_to_name() function to parse sample
flags in one go for three kinds of information:
- The prefix info for trace start, trace end, etc.
- Branch types.
- Extra info for transaction and interrupt related info.

As a result, the code is simplified to call the sample_flags_to_name()
only once.  No expectation for any changes in the perf script output.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/event.h                 |  5 ++
 tools/perf/util/trace-event-scripting.c | 85 ++++++++++++++++---------
 2 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 2744c54f404e..cd75efc09834 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -71,6 +71,11 @@ enum {
 
 #define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"
 
+#define PERF_ADDITIONAL_STATE_MASK	\
+	(PERF_IP_FLAG_IN_TX |		\
+	 PERF_IP_FLAG_INTR_DISABLE |	\
+	 PERF_IP_FLAG_INTR_TOGGLE)
+
 #define PERF_BRANCH_MASK		(\
 	PERF_IP_FLAG_BRANCH		|\
 	PERF_IP_FLAG_CALL		|\
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 4e81e02a4f18..712ba3a51bbe 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -313,49 +313,72 @@ static const struct {
 	{0, NULL}
 };
 
-static const char *sample_flags_to_name(u32 flags)
+static int sample_flags_to_name(u32 flags, char *str, size_t size)
 {
 	int i;
-
-	for (i = 0; sample_flags[i].name ; i++) {
-		if (sample_flags[i].flags == flags)
-			return sample_flags[i].name;
+	const char *prefix;
+	int pos = 0, ret;
+	u32 xf = flags & PERF_ADDITIONAL_STATE_MASK;
+	char xs[16] = { 0 };
+
+	/* Clear additional state bits */
+	flags &= ~PERF_ADDITIONAL_STATE_MASK;
+
+	if (flags & PERF_IP_FLAG_TRACE_BEGIN)
+		prefix = "tr strt ";
+	else if (flags & PERF_IP_FLAG_TRACE_END)
+		prefix = "tr end  ";
+	else
+		prefix = "";
+
+	ret = snprintf(str + pos, size - pos, "%s", prefix);
+	if (ret < 0)
+		return ret;
+	pos += ret;
+
+	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);
+
+	for (i = 0; sample_flags[i].name; i++) {
+		if (sample_flags[i].flags != flags)
+			continue;
+
+		ret = snprintf(str + pos, size - pos, "%s", sample_flags[i].name);
+		if (ret < 0)
+			return ret;
+		pos += ret;
+		break;
 	}
 
-	return NULL;
+	if (!xf)
+		return pos;
+
+	snprintf(xs, sizeof(xs), "(%s%s%s)",
+		 flags & PERF_IP_FLAG_IN_TX ? "x" : "",
+		 flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "",
+		 flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : "");
+
+	/* Right align the string if its length is less than the limit */
+	if ((pos + strlen(xs)) < SAMPLE_FLAGS_STR_ALIGNED_SIZE)
+		ret = snprintf(str + pos, size - pos, "%*s",
+			       (int)(SAMPLE_FLAGS_STR_ALIGNED_SIZE - ret), xs);
+	else
+		ret = snprintf(str + pos, size - pos, " %s", xs);
+	if (ret < 0)
+		return ret;
+
+	return pos + ret;
 }
 
 int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz)
 {
-	u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE |
-		 PERF_IP_FLAG_INTR_TOGGLE;
 	const char *chars = PERF_IP_FLAG_CHARS;
 	const size_t n = strlen(PERF_IP_FLAG_CHARS);
-	const char *name = NULL;
 	size_t i, pos = 0;
-	char xs[16] = {0};
-
-	if (flags & xf)
-		snprintf(xs, sizeof(xs), "(%s%s%s)",
-			 flags & PERF_IP_FLAG_IN_TX ? "x" : "",
-			 flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "",
-			 flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : "");
-
-	name = sample_flags_to_name(flags & ~xf);
-	if (name)
-		return snprintf(str, sz, "%-15s%6s", name, xs);
-
-	if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
-		name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN));
-		if (name)
-			return snprintf(str, sz, "tr strt %-7s%6s", name, xs);
-	}
+	int ret;
 
-	if (flags & PERF_IP_FLAG_TRACE_END) {
-		name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END));
-		if (name)
-			return snprintf(str, sz, "tr end  %-7s%6s", name, xs);
-	}
+	ret = sample_flags_to_name(flags, str, sz);
+	if (ret > 0)
+		return ret;
 
 	for (i = 0; i < n; i++, flags >>= 1) {
 		if ((flags & 1) && pos < sz)
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:31 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:31 +0000
Subject: [PATCH v4 03/12] perf script: Separate events from branch types
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-4-leo.yan@arm.com>

Branch types and events are two different things.  A branch type can be
a conditional branch, an indirect branch, a procedure call, a return, or
an exception taken, etc.  The extra event information is provided for
what happens during a branch, e.g. if a branch is mispredicted or not
taken (specific to conditional branches).

To deliver information about branches, this commit separates events from
branch types.  It parses branch types first, then appends event strings
embraced by the '/' character.  If multiple events occur, the events is
separated with a comma (,).

Also add a minor improvement by adding char 'm' in char array for branch
mispredict event.

Below are extracted sample flags.

Before:
        branch:   br miss
  instructions:   br miss

After:
        branch:   jmp/miss/
  instructions:   jmp/miss/

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/event.h                 |  5 +++-
 tools/perf/util/trace-event-scripting.c | 36 ++++++++++++++++++++++---
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index cd75efc09834..962fbc1714cf 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -69,7 +69,7 @@ enum {
 	PERF_IP_FLAG_BRANCH_MISS	= 1ULL << 15,
 };
 
-#define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"
+#define PERF_IP_FLAG_CHARS "bcrosyiABExghDtm"
 
 #define PERF_ADDITIONAL_STATE_MASK	\
 	(PERF_IP_FLAG_IN_TX |		\
@@ -90,6 +90,9 @@ enum {
 	PERF_IP_FLAG_VMENTRY		|\
 	PERF_IP_FLAG_VMEXIT)
 
+#define PERF_IP_FLAG_BRACH_EVENT_MASK	\
+	PERF_IP_FLAG_BRANCH_MISS
+
 #define PERF_MEM_DATA_SRC_NONE \
 	(PERF_MEM_S(OP, NA) |\
 	 PERF_MEM_S(LVL, NA) |\
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 712ba3a51bbe..55d7e4e612d5 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -309,7 +309,14 @@ static const struct {
 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"},
 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"},
-	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"},
+	{0, NULL}
+};
+
+static const struct {
+	u32 flags;
+	const char *name;
+} branch_events[] = {
+	{PERF_IP_FLAG_BRANCH_MISS, "miss"},
 	{0, NULL}
 };
 
@@ -317,8 +324,9 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
 {
 	int i;
 	const char *prefix;
-	int pos = 0, ret;
+	int pos = 0, ret, ev_idx = 0;
 	u32 xf = flags & PERF_ADDITIONAL_STATE_MASK;
+	u32 types, events;
 	char xs[16] = { 0 };
 
 	/* Clear additional state bits */
@@ -338,8 +346,9 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
 
 	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);
 
+	types = flags & ~PERF_IP_FLAG_BRACH_EVENT_MASK;
 	for (i = 0; sample_flags[i].name; i++) {
-		if (sample_flags[i].flags != flags)
+		if (sample_flags[i].flags != types)
 			continue;
 
 		ret = snprintf(str + pos, size - pos, "%s", sample_flags[i].name);
@@ -349,6 +358,27 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
 		break;
 	}
 
+	events = flags & PERF_IP_FLAG_BRACH_EVENT_MASK;
+	for (i = 0; branch_events[i].name; i++) {
+		if (!(branch_events[i].flags & events))
+			continue;
+
+		ret = snprintf(str + pos, size - pos, !ev_idx ? "/%s" : ",%s",
+			       branch_events[i].name);
+		if (ret < 0)
+			return ret;
+		pos += ret;
+		ev_idx++;
+	}
+
+	/* Add an end character '/' for events */
+	if (ev_idx) {
+		ret = snprintf(str + pos, size - pos, "/");
+		if (ret < 0)
+			return ret;
+		pos += ret;
+	}
+
 	if (!xf)
 		return pos;
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:32 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:32 +0000
Subject: [PATCH v4 04/12] perf script: Add not taken event for branches
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-5-leo.yan@arm.com>

Some hardware (e.g., Arm SPE) can trace the not taken event for
branches.  Add a flag for this event and support printing it.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/event.h                 | 6 ++++--
 tools/perf/util/trace-event-scripting.c | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 962fbc1714cf..c7f4b4b841ca 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -67,9 +67,10 @@ enum {
 	PERF_IP_FLAG_INTR_DISABLE	= 1ULL << 13,
 	PERF_IP_FLAG_INTR_TOGGLE	= 1ULL << 14,
 	PERF_IP_FLAG_BRANCH_MISS	= 1ULL << 15,
+	PERF_IP_FLAG_NOT_TAKEN		= 1ULL << 16,
 };
 
-#define PERF_IP_FLAG_CHARS "bcrosyiABExghDtm"
+#define PERF_IP_FLAG_CHARS "bcrosyiABExghDtmn"
 
 #define PERF_ADDITIONAL_STATE_MASK	\
 	(PERF_IP_FLAG_IN_TX |		\
@@ -91,7 +92,8 @@ enum {
 	PERF_IP_FLAG_VMEXIT)
 
 #define PERF_IP_FLAG_BRACH_EVENT_MASK	\
-	PERF_IP_FLAG_BRANCH_MISS
+	(PERF_IP_FLAG_BRANCH_MISS |	\
+	 PERF_IP_FLAG_NOT_TAKEN)
 
 #define PERF_MEM_DATA_SRC_NONE \
 	(PERF_MEM_S(OP, NA) |\
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 55d7e4e612d5..29cc467be14a 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -317,6 +317,7 @@ static const struct {
 	const char *name;
 } branch_events[] = {
 	{PERF_IP_FLAG_BRANCH_MISS, "miss"},
+	{PERF_IP_FLAG_NOT_TAKEN, "not_taken"},
 	{0, NULL}
 };
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:33 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:33 +0000
Subject: [PATCH v4 05/12] perf script: Add not taken event for branch stack
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-6-leo.yan@arm.com>

The branch stack has an existed field for printing mispredict, extend
the field for printing events and add support not-taken event.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/builtin-script.c | 20 +++++++++++++-------
 tools/perf/util/branch.h    |  3 ++-
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 8ca04293d335..d931c971a100 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -935,19 +935,25 @@ static int perf_sample__fprintf_start(struct perf_script *script,
 	return printed;
 }
 
-static inline char
-mispred_str(struct branch_entry *br)
+static inline size_t
+bstack_event_str(struct branch_entry *br, char *buf, size_t sz)
 {
-	if (!(br->flags.mispred  || br->flags.predicted))
-		return '-';
+	if (!(br->flags.mispred || br->flags.predicted || br->flags.not_taken))
+		return snprintf(buf, sz, "-");
 
-	return br->flags.predicted ? 'P' : 'M';
+	return snprintf(buf, sz, "%s%s",
+			br->flags.predicted ? "P" : "M",
+			br->flags.not_taken ? "N" : "");
 }
 
 static int print_bstack_flags(FILE *fp, struct branch_entry *br)
 {
-	return fprintf(fp, "/%c/%c/%c/%d/%s/%s ",
-		       mispred_str(br),
+	char events[16] = { 0 };
+	size_t pos;
+
+	pos = bstack_event_str(br, events, sizeof(events));
+	return fprintf(fp, "/%s/%c/%c/%d/%s/%s ",
+		       pos < 0 ? "-" : events,
 		       br->flags.in_tx ? 'X' : '-',
 		       br->flags.abort ? 'A' : '-',
 		       br->flags.cycles,
diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h
index b80c12c74bbb..7429530fa774 100644
--- a/tools/perf/util/branch.h
+++ b/tools/perf/util/branch.h
@@ -25,7 +25,8 @@ struct branch_flags {
 			u64 spec:2;
 			u64 new_type:4;
 			u64 priv:3;
-			u64 reserved:31;
+			u64 not_taken:1;
+			u64 reserved:30;
 		};
 	};
 };
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:34 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:34 +0000
Subject: [PATCH v4 06/12] perf arm-spe: Fix load-store operation checking
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-7-leo.yan@arm.com>

The ARM_SPE_OP_LD and ARM_SPE_OP_ST operations are secondary operation
type, they are overlapping with other second level's operation types
belonging to SVE and branch operations.  As a result, a non load-store
operation can be parsed for data source and memory sample.

To fix the issue, this commit introduces a is_ldst_op() macro for
checking LDST operation, and apply the checking when synthesize data
source and memory samples.

Fixes: a89dbc9b988f ("perf arm-spe: Set sample's data source field")
Signed-off-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
---
 tools/perf/util/arm-spe.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 251d214adf7f..0e8e05c87fd7 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -37,6 +37,8 @@
 #include "../../arch/arm64/include/asm/cputype.h"
 #define MAX_TIMESTAMP (~0ULL)
 
+#define is_ldst_op(op)		(!!((op) & ARM_SPE_OP_LDST))
+
 struct arm_spe {
 	struct auxtrace			auxtrace;
 	struct auxtrace_queues		queues;
@@ -681,6 +683,10 @@ static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq,
 {
 	union perf_mem_data_src	data_src = { .mem_op = PERF_MEM_OP_NA };
 
+	/* Only synthesize data source for LDST operations */
+	if (!is_ldst_op(record->op))
+		return 0;
+
 	if (record->op & ARM_SPE_OP_LD)
 		data_src.mem_op = PERF_MEM_OP_LOAD;
 	else if (record->op & ARM_SPE_OP_ST)
@@ -779,7 +785,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
 	 * When data_src is zero it means the record is not a memory operation,
 	 * skip to synthesize memory sample for this case.
 	 */
-	if (spe->sample_memory && data_src) {
+	if (spe->sample_memory && is_ldst_op(record->op)) {
 		err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src);
 		if (err)
 			return err;
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:35 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:35 +0000
Subject: [PATCH v4 07/12] perf arm-spe: Extend branch operations
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-8-leo.yan@arm.com>

In Arm ARM (ARM DDI 0487, L.a), the section "D18.2.7 Operation Type
packet", the branch subclass is extended for Call Return (CR), Guarded
control stack data access (GCS).

This commit adds support CR and GCS operations.  The IND (indirect)
operation is defined only in bit [1], its macro is updated accordingly.

Move the COND (Conditional) macro into the same group with other
operations for better maintenance.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c  | 12 +++++++++---
 .../perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h  | 11 ++++++++---
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
index 4cef10a83962..625834da7e20 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
@@ -397,10 +397,16 @@ static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet,
 
 		if (payload & SPE_OP_PKT_COND)
 			arm_spe_pkt_out_string(&err, &buf, &buf_len, " COND");
-
-		if (SPE_OP_PKT_IS_INDIRECT_BRANCH(payload))
+		if (payload & SPE_OP_PKT_INDIRECT_BRANCH)
 			arm_spe_pkt_out_string(&err, &buf, &buf_len, " IND");
-
+		if (payload & SPE_OP_PKT_GCS)
+			arm_spe_pkt_out_string(&err, &buf, &buf_len, " GCS");
+		if (SPE_OP_PKT_CR_BL(payload))
+			arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-BL");
+		if (SPE_OP_PKT_CR_RET(payload))
+			arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-RET");
+		if (SPE_OP_PKT_CR_NON_BL_RET(payload))
+			arm_spe_pkt_out_string(&err, &buf, &buf_len, " CR-NON-BL-RET");
 		break;
 	default:
 		/* Unknown index */
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
index 464a912b221c..32d760ede701 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
@@ -7,6 +7,7 @@
 #ifndef INCLUDE__ARM_SPE_PKT_DECODER_H__
 #define INCLUDE__ARM_SPE_PKT_DECODER_H__
 
+#include <linux/bitfield.h>
 #include <stddef.h>
 #include <stdint.h>
 
@@ -116,8 +117,6 @@ enum arm_spe_events {
 
 #define SPE_OP_PKT_IS_OTHER_SVE_OP(v)		(((v) & (BIT(7) | BIT(3) | BIT(0))) == 0x8)
 
-#define SPE_OP_PKT_COND				BIT(0)
-
 #define SPE_OP_PKT_LDST_SUBCLASS_GET(v)		((v) & GENMASK_ULL(7, 1))
 #define SPE_OP_PKT_LDST_SUBCLASS_GP_REG		0x0
 #define SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP	0x4
@@ -148,7 +147,13 @@ enum arm_spe_events {
 #define SPE_OP_PKT_SVE_PRED			BIT(2)
 #define SPE_OP_PKT_SVE_FP			BIT(1)
 
-#define SPE_OP_PKT_IS_INDIRECT_BRANCH(v)	(((v) & GENMASK_ULL(7, 1)) == 0x2)
+#define SPE_OP_PKT_CR_MASK			GENMASK_ULL(4, 3)
+#define SPE_OP_PKT_CR_BL(v)			(FIELD_GET(SPE_OP_PKT_CR_MASK, (v)) == 1)
+#define SPE_OP_PKT_CR_RET(v)			(FIELD_GET(SPE_OP_PKT_CR_MASK, (v)) == 2)
+#define SPE_OP_PKT_CR_NON_BL_RET(v)		(FIELD_GET(SPE_OP_PKT_CR_MASK, (v)) == 3)
+#define SPE_OP_PKT_GCS				BIT(2)
+#define SPE_OP_PKT_INDIRECT_BRANCH		BIT(1)
+#define SPE_OP_PKT_COND				BIT(0)
 
 const char *arm_spe_pkt_name(enum arm_spe_pkt_type);
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:36 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:36 +0000
Subject: [PATCH v4 08/12] perf arm-spe: Decode transactional event
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-9-leo.yan@arm.com>

The bit[16] in an event payload indicates an operation is in
transactional state.  Decode the bit.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 2 ++
 tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
index 625834da7e20..13cadb2f1cea 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
@@ -308,6 +308,8 @@ static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
 		arm_spe_pkt_out_string(&err, &buf, &buf_len, " REMOTE-ACCESS");
 	if (payload & BIT(EV_ALIGNMENT))
 		arm_spe_pkt_out_string(&err, &buf, &buf_len, " ALIGNMENT");
+	if (payload & BIT(EV_TRANSACTIONAL))
+		arm_spe_pkt_out_string(&err, &buf, &buf_len, " TXN");
 	if (payload & BIT(EV_PARTIAL_PREDICATE))
 		arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-PARTIAL-PRED");
 	if (payload & BIT(EV_EMPTY_PREDICATE))
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
index 32d760ede701..2cdf9f6da268 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
@@ -105,6 +105,7 @@ enum arm_spe_events {
 	EV_LLC_MISS		= 9,
 	EV_REMOTE_ACCESS	= 10,
 	EV_ALIGNMENT		= 11,
+	EV_TRANSACTIONAL	= 16,
 	EV_PARTIAL_PREDICATE	= 17,
 	EV_EMPTY_PREDICATE	= 18,
 };
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:37 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:37 +0000
Subject: [PATCH v4 09/12] perf arm-spe: Fill branch operations and events to record
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-10-leo.yan@arm.com>

The new added branch operations and events are filled into record, the
information will be consumed when synthesizing samples.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../util/arm-spe-decoder/arm-spe-decoder.c     | 18 ++++++++++++++++++
 .../util/arm-spe-decoder/arm-spe-decoder.h     | 10 ++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
index ba807071d3c1..52bd0a4ea96d 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
@@ -207,6 +207,18 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
 				break;
 			case SPE_OP_PKT_HDR_CLASS_BR_ERET:
 				decoder->record.op |= ARM_SPE_OP_BRANCH_ERET;
+				if (payload & SPE_OP_PKT_COND)
+					decoder->record.op |= ARM_SPE_OP_BR_COND;
+				if (payload & SPE_OP_PKT_INDIRECT_BRANCH)
+					decoder->record.op |= ARM_SPE_OP_BR_INDIRECT;
+				if (payload & SPE_OP_PKT_GCS)
+					decoder->record.op |= ARM_SPE_OP_BR_GCS;
+				if (SPE_OP_PKT_CR_BL(payload))
+					decoder->record.op |= ARM_SPE_OP_BR_CR_BL;
+				if (SPE_OP_PKT_CR_RET(payload))
+					decoder->record.op |= ARM_SPE_OP_BR_CR_RET;
+				if (SPE_OP_PKT_CR_NON_BL_RET(payload))
+					decoder->record.op |= ARM_SPE_OP_BR_CR_NON_BL_RET;
 				break;
 			default:
 				pr_err("Get packet error!\n");
@@ -238,6 +250,12 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
 			if (payload & BIT(EV_MISPRED))
 				decoder->record.type |= ARM_SPE_BRANCH_MISS;
 
+			if (payload & BIT(EV_NOT_TAKEN))
+				decoder->record.type |= ARM_SPE_BRANCH_NOT_TAKEN;
+
+			if (payload & BIT(EV_TRANSACTIONAL))
+				decoder->record.type |= ARM_SPE_IN_TXN;
+
 			if (payload & BIT(EV_PARTIAL_PREDICATE))
 				decoder->record.type |= ARM_SPE_SVE_PARTIAL_PRED;
 
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
index 4bcd627e859f..85b688a97436 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
@@ -24,6 +24,8 @@ enum arm_spe_sample_type {
 	ARM_SPE_REMOTE_ACCESS		= 1 << 7,
 	ARM_SPE_SVE_PARTIAL_PRED	= 1 << 8,
 	ARM_SPE_SVE_EMPTY_PRED		= 1 << 9,
+	ARM_SPE_BRANCH_NOT_TAKEN	= 1 << 10,
+	ARM_SPE_IN_TXN			= 1 << 11,
 };
 
 enum arm_spe_op_type {
@@ -52,8 +54,12 @@ enum arm_spe_op_type {
 	ARM_SPE_OP_SVE_SG		= 1 << 27,
 
 	/* Second level operation type for BRANCH_ERET */
-	ARM_SPE_OP_BR_COND	= 1 << 16,
-	ARM_SPE_OP_BR_INDIRECT	= 1 << 17,
+	ARM_SPE_OP_BR_COND		= 1 << 16,
+	ARM_SPE_OP_BR_INDIRECT		= 1 << 17,
+	ARM_SPE_OP_BR_GCS		= 1 << 18,
+	ARM_SPE_OP_BR_CR_BL		= 1 << 19,
+	ARM_SPE_OP_BR_CR_RET		= 1 << 20,
+	ARM_SPE_OP_BR_CR_NON_BL_RET	= 1 << 21,
 };
 
 enum arm_spe_common_data_source {
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:38 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:38 +0000
Subject: [PATCH v4 10/12] perf arm-spe: Set sample flags with supplement info
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-11-leo.yan@arm.com>

Based on the supplement information in the record, this commit sets the
sample flags for conditional branch, function call, return.  It also
sets events in flags, such as mispredict, not taken, and in transaction.

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/arm-spe.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 0e8e05c87fd7..daecf9e1017a 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -484,6 +484,26 @@ static void arm_spe__sample_flags(struct arm_spe_queue *speq)
 
 		if (record->type & ARM_SPE_BRANCH_MISS)
 			speq->flags |= PERF_IP_FLAG_BRANCH_MISS;
+
+		if (record->type & ARM_SPE_BRANCH_NOT_TAKEN)
+			speq->flags |= PERF_IP_FLAG_NOT_TAKEN;
+
+		if (record->type & ARM_SPE_IN_TXN)
+			speq->flags |= PERF_IP_FLAG_IN_TX;
+
+		if (record->op & ARM_SPE_OP_BR_COND)
+			speq->flags |= PERF_IP_FLAG_CONDITIONAL;
+
+		if (record->op & ARM_SPE_OP_BR_CR_BL)
+			speq->flags |= PERF_IP_FLAG_CALL;
+		else if (record->op & ARM_SPE_OP_BR_CR_RET)
+			speq->flags |= PERF_IP_FLAG_RETURN;
+		/*
+		 * Indirect branch instruction without link (e.g. BR),
+		 * take it as a function return.
+		 */
+		else if (record->op & ARM_SPE_OP_BR_INDIRECT)
+			speq->flags |= PERF_IP_FLAG_RETURN;
 	}
 }
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:39 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:39 +0000
Subject: [PATCH v4 11/12] perf arm-spe: Add branch stack
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-12-leo.yan@arm.com>

Although Arm SPE cannot generate continuous branch records, this commit
creates a branch stack with only one branch entry.  A single branch info
can be used for performance optimization.

A branch stack structure is dynamically allocated in the decode queue.
The branch stack and stack flags are synthesized based on branch types
and associated events.

After:

  # perf script --itrace=bl1 -F flags,addr,brstack

  jcc                   ffffc0fad9c6b214 0xffffc0fad9c6b234/0xffffc0fad9c6b214/P/-/-/7/COND/-
  jcc/miss,not_taken/   ffffc0fadaaebb30 0xffffc0fadaaebb2c/0xffffc0fadaaebb30/MN/-/-/7/COND/-
  jmp                   ffffc0fadaaea358 0xffffc0fadaaea5ec/0xffffc0fadaaea358/P/-/-/5//-
  jcc/not_taken/        ffffc0fadaae6494 0xffffc0fadaae6490/0xffffc0fadaae6494/PN/-/-/11/COND/-
  jcc/not_taken/            ffff7f83ab54 0xffff7f83ab50/0xffff7f83ab54/PN/-/-/13/COND/-
  jcc/not_taken/            ffff7f83ab08 0xffff7f83ab04/0xffff7f83ab08/PN/-/-/8/COND/-
  jcc                       ffff7f83aa80 0xffff7f83aa58/0xffff7f83aa80/P/-/-/10/COND/-
  jcc                       ffff7f9a45d0 0xffff7f9a43f0/0xffff7f9a45d0/P/-/-/29/COND/-
  jcc/not_taken/        ffffc0fad9ba6db4 0xffffc0fad9ba6db0/0xffffc0fad9ba6db4/PN/-/-/44/COND/-
  jcc                   ffffc0fadaac2964 0xffffc0fadaac2970/0xffffc0fadaac2964/P/-/-/6/COND/-
  jcc                   ffffc0fad99ddc10 0xffffc0fad99ddc04/0xffffc0fad99ddc10/P/-/-/72/COND/-
  jcc/not_taken/        ffffc0fad9b3f21c 0xffffc0fad9b3f218/0xffffc0fad9b3f21c/PN/-/-/64/COND/-
  jcc                   ffffc0fad9c3b604 0xffffc0fad9c3b5f8/0xffffc0fad9c3b604/P/-/-/13/COND/-
  jcc                   ffffc0fadaad6048 0xffffc0fadaad5f8c/0xffffc0fadaad6048/P/-/-/5/COND/-
  return/miss/              ffff7f84e614 0xffffc0fad98a2274/0xffff7f84e614/M/-/-/13/RET/-
  jcc/not_taken/        ffffc0fadaac4eb4 0xffffc0fadaac4eb0/0xffffc0fadaac4eb4/PN/-/-/5/COND/-
  jmp                       ffff7f8e3130 0xffff7f87555c/0xffff7f8e3130/P/-/-/5//-
  jcc/not_taken/        ffffc0fad9b3d9b0 0xffffc0fad9b3d9ac/0xffffc0fad9b3d9b0/PN/-/-/14/COND/-
  return                ffffc0fad9b91950 0xffffc0fad98c3e28/0xffffc0fad9b91950/P/-/-/12/RET/-

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/perf/util/arm-spe.c | 99 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index daecf9e1017a..ed89b7dbc244 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -103,6 +103,7 @@ struct arm_spe_queue {
 	struct thread			*thread;
 	u64				period_instructions;
 	u32				flags;
+	struct branch_stack		*last_branch;
 };
 
 struct data_source_handle {
@@ -233,6 +234,16 @@ static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
 	params.get_trace = arm_spe_get_trace;
 	params.data = speq;
 
+	if (spe->synth_opts.last_branch) {
+		size_t sz = sizeof(struct branch_stack);
+
+		/* Allocate one entry for TGT */
+		sz += sizeof(struct branch_entry);
+		speq->last_branch = zalloc(sz);
+		if (!speq->last_branch)
+			goto out_free;
+	}
+
 	/* create new decoder */
 	speq->decoder = arm_spe_decoder_new(&params);
 	if (!speq->decoder)
@@ -242,6 +253,7 @@ static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
 
 out_free:
 	zfree(&speq->event_buf);
+	zfree(&speq->last_branch);
 	free(speq);
 
 	return NULL;
@@ -348,6 +360,73 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
 	event->sample.header.size = sizeof(struct perf_event_header);
 }
 
+static void arm_spe__prep_branch_stack(struct arm_spe_queue *speq)
+{
+	struct arm_spe_record *record = &speq->decoder->record;
+	struct branch_stack *bstack = speq->last_branch;
+	struct branch_flags *bs_flags;
+	size_t sz = sizeof(struct branch_stack) +
+		    sizeof(struct branch_entry) /* TGT */;
+
+	/* Clean up branch stack */
+	memset(bstack, 0x0, sz);
+
+	if (!(speq->flags & PERF_IP_FLAG_BRANCH))
+		return;
+
+	bstack->entries[0].from = record->from_ip;
+	bstack->entries[0].to = record->to_ip;
+
+	bs_flags = &bstack->entries[0].flags;
+	bs_flags->value = 0;
+
+	if (record->op & ARM_SPE_OP_BR_CR_BL) {
+		if (record->op & ARM_SPE_OP_BR_COND)
+			bs_flags->type |= PERF_BR_COND_CALL;
+		else
+			bs_flags->type |= PERF_BR_CALL;
+	/*
+	 * Indirect branch instruction without link (e.g. BR),
+	 * take this case as function return.
+	 */
+	} else if (record->op & ARM_SPE_OP_BR_CR_RET ||
+		   record->op & ARM_SPE_OP_BR_INDIRECT) {
+		if (record->op & ARM_SPE_OP_BR_COND)
+			bs_flags->type |= PERF_BR_COND_RET;
+		else
+			bs_flags->type |= PERF_BR_RET;
+	} else if (record->op & ARM_SPE_OP_BR_CR_NON_BL_RET) {
+		if (record->op & ARM_SPE_OP_BR_COND)
+			bs_flags->type |= PERF_BR_COND;
+		else
+			bs_flags->type |= PERF_BR_UNCOND;
+	} else {
+		if (record->op & ARM_SPE_OP_BR_COND)
+			bs_flags->type |= PERF_BR_COND;
+		else
+			bs_flags->type |= PERF_BR_UNKNOWN;
+	}
+
+	if (record->type & ARM_SPE_BRANCH_MISS) {
+		bs_flags->mispred = 1;
+		bs_flags->predicted = 0;
+	} else {
+		bs_flags->mispred = 0;
+		bs_flags->predicted = 1;
+	}
+
+	if (record->type & ARM_SPE_BRANCH_NOT_TAKEN)
+		bs_flags->not_taken = 1;
+
+	if (record->type & ARM_SPE_IN_TXN)
+		bs_flags->in_tx = 1;
+
+	bs_flags->cycles = min(record->latency, 0xFFFFU);
+
+	bstack->nr = 1;
+	bstack->hw_idx = -1ULL;
+}
+
 static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
 {
 	event->header.size = perf_event__sample_event_size(sample, type, 0);
@@ -416,6 +495,7 @@ static int arm_spe__synth_branch_sample(struct arm_spe_queue *speq,
 	sample.addr = record->to_ip;
 	sample.weight = record->latency;
 	sample.flags = speq->flags;
+	sample.branch_stack = speq->last_branch;
 
 	ret = arm_spe_deliver_synth_event(spe, speq, event, &sample);
 	perf_sample__exit(&sample);
@@ -450,6 +530,7 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq,
 	sample.period = spe->instructions_sample_period;
 	sample.weight = record->latency;
 	sample.flags = speq->flags;
+	sample.branch_stack = speq->last_branch;
 
 	ret = arm_spe_deliver_synth_event(spe, speq, event, &sample);
 	perf_sample__exit(&sample);
@@ -787,6 +868,10 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
 		}
 	}
 
+	if (spe->synth_opts.last_branch &&
+	    (spe->sample_branch || spe->sample_instructions))
+		arm_spe__prep_branch_stack(speq);
+
 	if (spe->sample_branch && (record->op & ARM_SPE_OP_BRANCH_ERET)) {
 		err = arm_spe__synth_branch_sample(speq, spe->branch_id);
 		if (err)
@@ -1278,6 +1363,7 @@ static void arm_spe_free_queue(void *priv)
 	thread__zput(speq->thread);
 	arm_spe_decoder_free(speq->decoder);
 	zfree(&speq->event_buf);
+	zfree(&speq->last_branch);
 	free(speq);
 }
 
@@ -1497,6 +1583,19 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
 		id += 1;
 	}
 
+	if (spe->synth_opts.last_branch) {
+		if (spe->synth_opts.last_branch_sz > 1)
+			pr_debug("Arm SPE supports only one bstack entry (TGT).\n");
+
+		attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
+		/*
+		 * We don't use the hardware index, but the sample generation
+		 * code uses the new format branch_stack with this field,
+		 * so the event attributes must indicate that it's present.
+		 */
+		attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
+	}
+
 	if (spe->synth_opts.branches) {
 		spe->sample_branch = true;
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar  4 03:12:40 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue,  4 Mar 2025 11:12:40 +0000
Subject: [PATCH v4 12/12] perf arm-spe: Support previous branch target (PBT) address
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <20250304111240.3378214-13-leo.yan@arm.com>

When FEAT_SPE_PBT is implemented, the previous branch target address
(named as PBT) before the sampled operation, will be recorded.

This commit first introduces a 'prev_br_tgt' field in the record for
saving the PBT address in the decoder.

If the current operation is a branch instruction, by combining with PBT,
it can create a chain with two consecutive branches.  As the branch
stack stores branches in descending order, meaning a newer branch is
stored in a lower entry in the stack.  Arm SPE stores the latest branch
in the first entry of branch stack, and the previous branch coming from
PBT is stored into the second entry.

Otherwise, if current operation is not a branch, the last branch will be
saved for PBT only.  PBT lacks associated information such as branch
source address, branch type, and events.  The branch entry fills zeros
for the corresponding fields and only set its target address.

After:

  perf script -f --itrace=bl -F flags,addr,brstack
  jcc                   ffff800080187914 0xffff8000801878fc/0xffff800080187914/P/-/-/1/COND/-  0x0/0xffff8000801878f8/-/-/-/0//-
  jcc                   ffff8000802d12d8 0xffff8000802d12f8/0xffff8000802d12d8/P/-/-/1/COND/-  0x0/0xffff8000802d12ec/-/-/-/0//-
  jcc                   ffff8000813fe200 0xffff8000813fe20c/0xffff8000813fe200/P/-/-/1/COND/-  0x0/0xffff8000813fe200/-/-/-/0//-
  jcc                   ffff8000813fe200 0xffff8000813fe20c/0xffff8000813fe200/P/-/-/1/COND/-  0x0/0xffff8000813fe200/-/-/-/0//-
  jmp                   ffff800081410980 0xffff800081419108/0xffff800081410980/P/-/-/1//-  0x0/0xffff800081419104/-/-/-/0//-
  return                ffff80008036e064 0xffff80008141ba84/0xffff80008036e064/P/-/-/1/RET/-  0x0/0xffff80008141ba60/-/-/-/0//-
  jcc                   ffff8000803d54f0 0xffff8000803d54e8/0xffff8000803d54f0/P/-/-/1/COND/-  0x0/0xffff8000803d54e0/-/-/-/0//-
  jmp                   ffff80008015e468 0xffff8000803d46dc/0xffff80008015e468/P/-/-/1//-  0x0/0xffff8000803d46c8/-/-/-/0//-
  jmp                   ffff8000806e2d50 0xffff80008040f710/0xffff8000806e2d50/P/-/-/1//-  0x0/0xffff80008040f6e8/-/-/-/0//-
  jcc                   ffff800080721704 0xffff8000807216b4/0xffff800080721704/P/-/-/1/COND/-  0x0/0xffff8000807216ac/-/-/-/0//-

Reviewed-by: Ian Rogers <irogers at google.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../util/arm-spe-decoder/arm-spe-decoder.c    |   5 +-
 .../util/arm-spe-decoder/arm-spe-decoder.h    |   1 +
 tools/perf/util/arm-spe.c                     | 114 ++++++++++--------
 3 files changed, 70 insertions(+), 50 deletions(-)

diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
index 52bd0a4ea96d..688fe6d75244 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
@@ -28,7 +28,8 @@ static u64 arm_spe_calc_ip(int index, u64 payload)
 
 	/* Instruction virtual address or Branch target address */
 	if (index == SPE_ADDR_PKT_HDR_INDEX_INS ||
-	    index == SPE_ADDR_PKT_HDR_INDEX_BRANCH) {
+	    index == SPE_ADDR_PKT_HDR_INDEX_BRANCH ||
+	    index == SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH) {
 		ns = SPE_ADDR_PKT_GET_NS(payload);
 		el = SPE_ADDR_PKT_GET_EL(payload);
 
@@ -181,6 +182,8 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
 				decoder->record.virt_addr = ip;
 			else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS)
 				decoder->record.phys_addr = ip;
+			else if (idx == SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH)
+				decoder->record.prev_br_tgt = ip;
 			break;
 		case ARM_SPE_COUNTER:
 			if (idx == SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT)
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
index 85b688a97436..5d232188643b 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
@@ -89,6 +89,7 @@ struct arm_spe_record {
 	u32 latency;
 	u64 from_ip;
 	u64 to_ip;
+	u64 prev_br_tgt;
 	u64 timestamp;
 	u64 virt_addr;
 	u64 phys_addr;
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index ed89b7dbc244..2a9775649cc2 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -237,8 +237,9 @@ static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
 	if (spe->synth_opts.last_branch) {
 		size_t sz = sizeof(struct branch_stack);
 
-		/* Allocate one entry for TGT */
-		sz += sizeof(struct branch_entry);
+		/* Allocate up to two entries for PBT + TGT */
+		sz += sizeof(struct branch_entry) *
+			min(spe->synth_opts.last_branch_sz, 2U);
 		speq->last_branch = zalloc(sz);
 		if (!speq->last_branch)
 			goto out_free;
@@ -362,68 +363,83 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
 
 static void arm_spe__prep_branch_stack(struct arm_spe_queue *speq)
 {
+	struct arm_spe *spe = speq->spe;
 	struct arm_spe_record *record = &speq->decoder->record;
 	struct branch_stack *bstack = speq->last_branch;
 	struct branch_flags *bs_flags;
+	unsigned int last_branch_sz = spe->synth_opts.last_branch_sz;
+	bool have_tgt = !!(speq->flags & PERF_IP_FLAG_BRANCH);
+	bool have_pbt = last_branch_sz >= (have_tgt + 1U) && record->prev_br_tgt;
 	size_t sz = sizeof(struct branch_stack) +
-		    sizeof(struct branch_entry) /* TGT */;
+		    sizeof(struct branch_entry) * min(last_branch_sz, 2U) /* PBT + TGT */;
+	int i = 0;
 
 	/* Clean up branch stack */
 	memset(bstack, 0x0, sz);
 
-	if (!(speq->flags & PERF_IP_FLAG_BRANCH))
+	if (!have_tgt && !have_pbt)
 		return;
 
-	bstack->entries[0].from = record->from_ip;
-	bstack->entries[0].to = record->to_ip;
+	if (have_tgt) {
+		bstack->entries[i].from = record->from_ip;
+		bstack->entries[i].to = record->to_ip;
 
-	bs_flags = &bstack->entries[0].flags;
-	bs_flags->value = 0;
+		bs_flags = &bstack->entries[i].flags;
+		bs_flags->value = 0;
 
-	if (record->op & ARM_SPE_OP_BR_CR_BL) {
-		if (record->op & ARM_SPE_OP_BR_COND)
-			bs_flags->type |= PERF_BR_COND_CALL;
-		else
-			bs_flags->type |= PERF_BR_CALL;
-	/*
-	 * Indirect branch instruction without link (e.g. BR),
-	 * take this case as function return.
-	 */
-	} else if (record->op & ARM_SPE_OP_BR_CR_RET ||
-		   record->op & ARM_SPE_OP_BR_INDIRECT) {
-		if (record->op & ARM_SPE_OP_BR_COND)
-			bs_flags->type |= PERF_BR_COND_RET;
-		else
-			bs_flags->type |= PERF_BR_RET;
-	} else if (record->op & ARM_SPE_OP_BR_CR_NON_BL_RET) {
-		if (record->op & ARM_SPE_OP_BR_COND)
-			bs_flags->type |= PERF_BR_COND;
-		else
-			bs_flags->type |= PERF_BR_UNCOND;
-	} else {
-		if (record->op & ARM_SPE_OP_BR_COND)
-			bs_flags->type |= PERF_BR_COND;
-		else
-			bs_flags->type |= PERF_BR_UNKNOWN;
-	}
+		if (record->op & ARM_SPE_OP_BR_CR_BL) {
+			if (record->op & ARM_SPE_OP_BR_COND)
+				bs_flags->type |= PERF_BR_COND_CALL;
+			else
+				bs_flags->type |= PERF_BR_CALL;
+		/*
+		 * Indirect branch instruction without link (e.g. BR),
+		 * take this case as function return.
+		 */
+		} else if (record->op & ARM_SPE_OP_BR_CR_RET ||
+			   record->op & ARM_SPE_OP_BR_INDIRECT) {
+			if (record->op & ARM_SPE_OP_BR_COND)
+				bs_flags->type |= PERF_BR_COND_RET;
+			else
+				bs_flags->type |= PERF_BR_RET;
+		} else if (record->op & ARM_SPE_OP_BR_CR_NON_BL_RET) {
+			if (record->op & ARM_SPE_OP_BR_COND)
+				bs_flags->type |= PERF_BR_COND;
+			else
+				bs_flags->type |= PERF_BR_UNCOND;
+		} else {
+			if (record->op & ARM_SPE_OP_BR_COND)
+				bs_flags->type |= PERF_BR_COND;
+			else
+				bs_flags->type |= PERF_BR_UNKNOWN;
+		}
 
-	if (record->type & ARM_SPE_BRANCH_MISS) {
-		bs_flags->mispred = 1;
-		bs_flags->predicted = 0;
-	} else {
-		bs_flags->mispred = 0;
-		bs_flags->predicted = 1;
-	}
+		if (record->type & ARM_SPE_BRANCH_MISS) {
+			bs_flags->mispred = 1;
+			bs_flags->predicted = 0;
+		} else {
+			bs_flags->mispred = 0;
+			bs_flags->predicted = 1;
+		}
+
+		if (record->type & ARM_SPE_BRANCH_NOT_TAKEN)
+			bs_flags->not_taken = 1;
 
-	if (record->type & ARM_SPE_BRANCH_NOT_TAKEN)
-		bs_flags->not_taken = 1;
+		if (record->type & ARM_SPE_IN_TXN)
+			bs_flags->in_tx = 1;
 
-	if (record->type & ARM_SPE_IN_TXN)
-		bs_flags->in_tx = 1;
+		bs_flags->cycles = min(record->latency, 0xFFFFU);
+		i++;
+	}
 
-	bs_flags->cycles = min(record->latency, 0xFFFFU);
+	if (have_pbt) {
+		bs_flags = &bstack->entries[i].flags;
+		bs_flags->type |= PERF_BR_UNKNOWN;
+		bstack->entries[i].to = record->prev_br_tgt;
+		i++;
+	}
 
-	bstack->nr = 1;
+	bstack->nr = i;
 	bstack->hw_idx = -1ULL;
 }
 
@@ -1584,8 +1600,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
 	}
 
 	if (spe->synth_opts.last_branch) {
-		if (spe->synth_opts.last_branch_sz > 1)
-			pr_debug("Arm SPE supports only one bstack entry (TGT).\n");
+		if (spe->synth_opts.last_branch_sz > 2)
+			pr_debug("Arm SPE supports only two bstack entries (PBT+TGT).\n");
 
 		attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
 		/*
-- 
2.34.1



From csokas.bence at prolan.hu  Tue Mar  4 03:14:04 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Tue, 4 Mar 2025 12:14:04 +0100
Subject: [PATCH v6 1/3] include: uapi: counter: Add
 microchip-tcb-capture.h
In-Reply-To: <Z8bNFjh85p2jqK9C@ishi>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-2-csokas.bence@prolan.hu> <Z8bNFjh85p2jqK9C@ishi>
Message-ID: <8cf056d7-22d0-4bf2-8dd6-79a45977bfc1@prolan.hu>

Hi,

On 2025. 03. 04. 10:51, William Breathitt Gray wrote:
> On Thu, Feb 27, 2025 at 03:40:18PM +0100, Bence Cs?k?s wrote:
>> Add UAPI header for the microchip-tcb-capture.c driver.
>> This header will hold the various event channels, component numbers etc.
>> used by this driver.
>>
>> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
> 
> Oops, I almost missed this one! Make sure I'm included in the To field
> for the next revision. ;-)
> 
> By the way, b4 is a nifty tool that can save you some work and help you
> prep patch series for submission.[^1]

Yes, I have considered it, but unfortunately it still has quite a few 
bugs, for example [1], which has mangled my tags before, when a 
maintainer using it tried to apply one of my patches with it.

[1] https://github.com/mricon/b4/issues/52

>> +/*
>> + * The driver defines the following components:
>> + *
>> + * Count 0
>> + * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
>> + * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
>> + */
>> +
>> +enum counter_mchp_signals {
>> +	COUNTER_MCHP_SIG_TIOA,
>> +	COUNTER_MCHP_SIG_TIOB,
>> +};
> 
> Are these meant to be used to identify the Signals in the
> microchip-tcb-capture.c file. You should set the the counter_signal id
> members to these enum constants then. However, this enum doesn't need to
> be exposed to userspace in that case.

The thought was to let userspace figure out which 
`signal%d_action_component_id` to read, but now I see that this is not 
the way to go.

> If that is the only purpose of enum counter_mchp_signals, then we can
> omit this patch from the series and you won't need to send it in the
> next revision.

Alright, I'll drop this enum. Then this header will be empty at the 
start, save for the block comment. I hope that will be alright.

> William Breathitt Gray
> 
> [^1] https://b4.docs.kernel.org/en/latest/

Bence



From rmk+kernel at armlinux.org.uk  Tue Mar  4 03:21:27 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 04 Mar 2025 11:21:27 +0000
Subject: [PATCH net-next] net: stmmac: simplify phylink_suspend() and
 phylink_resume() calls
Message-ID: <E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk>

Currently, the calls to phylink's suspend and resume functions are
inside overly complex tests, and boil down to:

	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
		call phylink
	} else {
		call phylink and
		if (device_may_wakeup(priv->device))
			do something else
	}

This results in phylink always being called, possibly with differing
arguments for phylink_suspend().

Simplify this code, noting that each site is slightly different due to
the order in which phylink is called and the "something else".

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +++++++------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index aec230353ac4..fbcba6c71f12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7831,13 +7831,11 @@ int stmmac_suspend(struct device *dev)
 	mutex_unlock(&priv->lock);
 
 	rtnl_lock();
-	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
-		phylink_suspend(priv->phylink, true);
-	} else {
-		if (device_may_wakeup(priv->device))
-			phylink_speed_down(priv->phylink, false);
-		phylink_suspend(priv->phylink, false);
-	}
+	if (device_may_wakeup(priv->device) && !priv->plat->pmt)
+		phylink_speed_down(priv->phylink, false);
+
+	phylink_suspend(priv->phylink,
+			device_may_wakeup(priv->device) && priv->plat->pmt);
 	rtnl_unlock();
 
 	if (stmmac_fpe_supported(priv))
@@ -7927,13 +7925,9 @@ int stmmac_resume(struct device *dev)
 	}
 
 	rtnl_lock();
-	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
-		phylink_resume(priv->phylink);
-	} else {
-		phylink_resume(priv->phylink);
-		if (device_may_wakeup(priv->device))
-			phylink_speed_up(priv->phylink);
-	}
+	phylink_resume(priv->phylink);
+	if (device_may_wakeup(priv->device) && !priv->plat->pmt)
+		phylink_speed_up(priv->phylink);
 	rtnl_unlock();
 
 	rtnl_lock();
-- 
2.30.2



From catalin.marinas at arm.com  Tue Mar  4 03:25:06 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 4 Mar 2025 11:25:06 +0000
Subject: [PATCH v20 00/11] arm64/perf: Enable branch stack sampling
In-Reply-To: <CAL_JsqLijFG1PFkqKk7hXzC=aj70OLQsXwC280QsCO=PnCVZYg@mail.gmail.com>
References: <20250218-arm-brbe-v19-v20-0-4e9922fc2e8e@kernel.org>
 <174080569248.3208873.17639032755999041028.b4-ty@kernel.org>
 <CAL_JsqLijFG1PFkqKk7hXzC=aj70OLQsXwC280QsCO=PnCVZYg@mail.gmail.com>
Message-ID: <Z8bjEm_neWdMBNYv@arm.com>

On Mon, Mar 03, 2025 at 10:44:21AM -0600, Rob Herring wrote:
> On Sat, Mar 1, 2025 at 1:05?AM Will Deacon <will at kernel.org> wrote:
> > On Tue, 18 Feb 2025 14:39:55 -0600, Rob Herring (Arm) wrote:
> > > This series enables perf branch stack sampling support on arm64 via a
> > > v9.2 arch feature called Branch Record Buffer Extension (BRBE). Details
> > > on BRBE can be found in the Arm ARM[1] chapter D18.
> > >
> > > I've picked up this series from Anshuman. v19 and v20 versions have been
> > > reworked quite a bit by Mark and myself. The bulk of those changes are
> > > in patch 11.
> > >
> > > [...]
> >
> > Applied cleanups to will (for-next/perf), thanks!
> >
> > [01/11] perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling counters
> >         https://git.kernel.org/will/c/04bd15c4cbc3
> > [02/11] perf: arm_pmu: Don't disable counter in armpmu_add()
> >         https://git.kernel.org/will/c/dcca27bc1ecc
> > [03/11] perf: arm_pmuv3: Don't disable counter in armv8pmu_enable_event()
> >         https://git.kernel.org/will/c/4b0567ad0be5
> > [04/11] perf: arm_v7_pmu: Drop obvious comments for enabling/disabling counters and interrupts
> >         https://git.kernel.org/will/c/7a5387748215
> > [05/11] perf: arm_v7_pmu: Don't disable counter in (armv7|krait_|scorpion_)pmu_enable_event()
> >         https://git.kernel.org/will/c/7bf1001e0d91
> > [06/11] perf: apple_m1: Don't disable counter in m1_pmu_enable_event()
> >         https://git.kernel.org/will/c/c2e793da59fc
> > [07/11] perf: arm_pmu: Move PMUv3-specific data
> >         https://git.kernel.org/will/c/dc4d58a752ea
> 
> I don't know if you looked at the thread on patch 11 and said "long
> discussion, I'll assume a new version is coming. Next!" because that's
> what I would do. In this case though, there's not any changes.

I do this as well ;). But I think Will is waiting for Mark R to look at
the rest of the series.

-- 
Catalin


From leo.yan at arm.com  Tue Mar  4 03:33:50 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 4 Mar 2025 11:33:50 +0000
Subject: [PATCH v3 00/12] perf script: Refactor branch flags for Arm SPE
In-Reply-To: <Z8YYY2Q_ZPIaZ74g@google.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250303093853.GG2157064@e132581.arm.com>
 <Z8YYY2Q_ZPIaZ74g@google.com>
Message-ID: <20250304113350.GK2157064@e132581.arm.com>

On Mon, Mar 03, 2025 at 01:00:19PM -0800, Namhyung Kim wrote:
> On Mon, Mar 03, 2025 at 09:38:53AM +0000, Leo Yan wrote:
> > Hi Arnaldo, Namhyung,
> > 
> > On Mon, Feb 17, 2025 at 07:58:56PM +0000, Leo Yan wrote:
> > > This patch series refactors branch flags for support Arm SPE.  The patch
> > > set is divided into two parts, the first part is for refactoring common
> > > code and the second part is for enabling Arm SPE.
> > 
> > James has given review tags (including the new added patch 06).  Could
> > you kindly pick up this series?
> > 
> > Sorry for pushing a bit, as we have dependency on it.
> 
> No problem, I'll add it to the tmp branch and run some tests.

Thanks a lot, Namhyung!

I saw you have picked patch series v3 in the tmp.perf-tools-next branch.
On the other hand, to follow up on Adrian's comment, I have sent out
v4 to remove an unnecessary change in patch 01, and the rest of the
patches are exactly the same as v3.

Please consider picking the latest change (either the whole v4 series or
just the updated patch 01 would be fine).

Thanks,
Leo


From peter.griffin at linaro.org  Tue Mar  4 03:37:56 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Tue, 4 Mar 2025 11:37:56 +0000
Subject: [PATCH 6/6] scsi: ufs: exynos: put ufs device in reset on .exit()
 and .suspend()
In-Reply-To: <015ce85d-c62b-472c-8527-33217ad815eb@acm.org>
References: <20250226220414.343659-1-peter.griffin@linaro.org>
 <20250226220414.343659-7-peter.griffin@linaro.org> <015ce85d-c62b-472c-8527-33217ad815eb@acm.org>
Message-ID: <CADrjBPrOTMPh2BfROdMnCrPWBaKw+uQ=jH3yYNZ-HEKEjNahSA@mail.gmail.com>

Hi Bart,

Thanks for the review feedback.

On Fri, 28 Feb 2025 at 19:21, Bart Van Assche <bvanassche at acm.org> wrote:
>
> On 2/26/25 2:04 PM, Peter Griffin wrote:
> > GPIO_OUT[0] is connected to the reset pin of embedded UFS device.
> > Before powering off the phy assert the reset signal.
> Does the above apply to the GS implementation only or does it apply to
> all SoC's with an Exynos UFS host controller?

The reason I went with a generic approach (rather than adding another
SoC specific hook) was that exynos_ufs_dev_hw_reset() is already
called by all users of this driver. From that I concluded it is a
common register shared by all exynos implementations.

It is hard to be 100% sure though as I don't personally have any of
the other Exynos platforms supported by this driver to test on.
Another approach would be to add some more gs101 SoC specific hooks
for suspend() and exit() to exynos_ufs_drv_data() or another
EXYNOS_UFS_OPT_.

Thanks,

Peter


From heiko at sntech.de  Tue Mar  4 03:41:56 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 12:41:56 +0100
Subject: [PATCH 1/4] dt-bindings: iio: adc: Add rockchip,rk3528-saradc variant
In-Reply-To: <20250227184058.2964204-2-jonas@kwiboo.se>
References: <20250227184058.2964204-1-jonas@kwiboo.se>
 <20250227184058.2964204-2-jonas@kwiboo.se>
Message-ID: <3748393.44csPzL39Z@diego>

Am Donnerstag, 27. Februar 2025, 19:40:50 MEZ schrieb Jonas Karlman:
> The Successive Approximation ADC (SARADC) in RK3528 uses the v2
> controller and support:
> - 10-bit resolution
> - Up to 1MS/s sampling rate
> - 4 single-ended input channels
> - Current consumption: 0.5mA @ 1MS/s
> 
> Add a rockchip,rk3562-saradc compatible string for the 4 channels of
> 10-bit resolution supported by SARADC in RK3528.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>




From quentin.schulz at cherry.de  Tue Mar  4 03:46:59 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Tue, 4 Mar 2025 12:46:59 +0100
Subject: [PATCH v2 2/2] drm/rockchip: lvds: Hide scary error messages on
 probe deferral
In-Reply-To: <20250301173547.710245-3-heiko@sntech.de>
References: <20250301173547.710245-1-heiko@sntech.de>
 <20250301173547.710245-3-heiko@sntech.de>
Message-ID: <0e54f70a-0b07-4ead-96fb-add2bbdaf787@cherry.de>

Hi Heiko,

On 3/1/25 6:35 PM, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner at cherry.de>
> 
> Commit 52d11c863ac9 ("drm/rockchip: lvds: do not print scary message when
> probing defer") already started hiding scary messages that are not relevant
> if the requested supply just returned EPROBE_DEFER, but there are more
> possible sources - like the phy.
> 
> So modernize the whole logging in the probe path by replacing the
> remaining deprecated DRM_DEV_ERROR with appropriate dev_err(_probe)
> and drm_err calls.
> 
> The distinction here is that all messages talking about mishaps of the
> lvds element use dev_err(_probe) while messages caused by interaction
> with the main Rockchip drm-device use drm_err.
> 
> Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
> ---
>   drivers/gpu/drm/rockchip/rockchip_lvds.c | 61 ++++++++++--------------
>   1 file changed, 26 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index ecfae8d5da89..d8b2007123fa 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -453,10 +453,9 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
>   		return PTR_ERR(lvds->regs);
>   
>   	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
> -	if (IS_ERR(lvds->pclk)) {
> -		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
> -		return PTR_ERR(lvds->pclk);
> -	}
> +	if (IS_ERR(lvds->pclk))
> +		return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk),
> +				     "could not get or prepare pclk_lvds\n");
>   
>   	lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
>   				  GFP_KERNEL);
> @@ -465,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
>   
>   	lvds->pins->p = devm_pinctrl_get(lvds->dev);
>   	if (IS_ERR(lvds->pins->p)) {
> -		DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
> +		dev_err(lvds->dev, "no pinctrl handle\n");
>   		devm_kfree(lvds->dev, lvds->pins);
>   		lvds->pins = NULL;
>   	} else {
>   		lvds->pins->default_state =
>   			pinctrl_lookup_state(lvds->pins->p, "lcdc");
>   		if (IS_ERR(lvds->pins->default_state)) {
> -			DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
> +			dev_err(lvds->dev, "no default pinctrl state\n");
>   			devm_kfree(lvds->dev, lvds->pins);
>   			lvds->pins = NULL;

Should those be dev_err if they are not breaking anything? After all, 
the device will actually probe? Maybe dev_warn would be more appropriate?

Maybe a separate patch since we had DRM_DEV_ERROR already, so switching 
to dev_err in one and then lowering the log level in a second would make 
"more" sense?

>   		}
> @@ -547,11 +546,10 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	lvds->drm_dev = drm_dev;
>   	port = of_graph_get_port_by_id(dev->of_node, 1);
> -	if (!port) {
> -		DRM_DEV_ERROR(dev,
> -			      "can't found port point, please init lvds panel port!\n");
> -		return -EINVAL;
> -	}
> +	if (!port)
> +		return dev_err_probe(dev, -EINVAL,
> +				     "can't found port point, please init lvds panel port!\n");
> +
>   	for_each_child_of_node(port, endpoint) {
>   		child_count++;
>   		of_property_read_u32(endpoint, "reg", &endpoint_id);
> @@ -563,8 +561,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		}
>   	}
>   	if (!child_count) {
> -		DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
> -		ret = -EINVAL;
> +		ret = dev_err_probe(dev, -EINVAL, "lvds port does not have any children\n");
>   		goto err_put_port;
>   	} else if (ret) {
>   		dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
> @@ -581,8 +578,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		lvds->output = rockchip_lvds_name_to_output(name);
>   
>   	if (lvds->output < 0) {
> -		DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name);
> -		ret = lvds->output;
> +		ret = dev_err_probe(dev, lvds->output, "invalid output type [%s]\n", name);
>   		goto err_put_remote;
>   	}
>   
> @@ -593,7 +589,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   		lvds->format = rockchip_lvds_name_to_format(name);
>   
>   	if (lvds->format < 0) {
> -		DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
> +		dev_err(dev, "invalid data-mapping format [%s]\n", name);
>   		ret = lvds->format;

nipitck:

ret = dev_err_probe(dev, lvds->format, "invalid data-mapping format 
[%s]\n", name);

>   		goto err_put_remote;
>   	}
> @@ -604,8 +600,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_LVDS);
>   	if (ret < 0) {
> -		DRM_DEV_ERROR(drm_dev->dev,
> -			      "failed to initialize encoder: %d\n", ret);
> +		drm_err(drm_dev,
> +			"failed to initialize encoder: %d\n", ret);
>   		goto err_put_remote;
>   	}
>   
> @@ -618,8 +614,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   					 &rockchip_lvds_connector_funcs,
>   					 DRM_MODE_CONNECTOR_LVDS);
>   		if (ret < 0) {
> -			DRM_DEV_ERROR(drm_dev->dev,
> -				      "failed to initialize connector: %d\n", ret);
> +			drm_err(drm_dev,
> +				"failed to initialize connector: %d\n", ret);
>   			goto err_free_encoder;
>   		}
>   
> @@ -633,9 +629,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   		connector = drm_bridge_connector_init(lvds->drm_dev, encoder);
>   		if (IS_ERR(connector)) {
> -			DRM_DEV_ERROR(drm_dev->dev,
> -				      "failed to initialize bridge connector: %pe\n",
> -				      connector);
> +			drm_err(drm_dev,
> +				"failed to initialize bridge connector: %pe\n",
> +				connector);
>   			ret = PTR_ERR(connector);
>   			goto err_free_encoder;
>   		}
> @@ -643,8 +639,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>   
>   	ret = drm_connector_attach_encoder(connector, encoder);
>   	if (ret < 0) {
> -		DRM_DEV_ERROR(drm_dev->dev,
> -			      "failed to attach encoder: %d\n", ret);
> +		drm_err(drm_dev, "failed to attach encoder: %d\n", ret);
>   		goto err_free_connector;
>   	}
>   
> @@ -706,24 +701,20 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
>   
>   	lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>   						    "rockchip,grf");
> -	if (IS_ERR(lvds->grf)) {
> -		DRM_DEV_ERROR(dev, "missing rockchip,grf property\n");
> -		return PTR_ERR(lvds->grf);
> -	}
> +	if (IS_ERR(lvds->grf))
> +		return dev_err_probe(dev, PTR_ERR(lvds->grf), "missing rockchip,grf property\n");
>   
>   	ret = lvds->soc_data->probe(pdev, lvds);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Platform initialization failed\n");
> -		return ret;
> -	}
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Platform initialization failed\n");
>   
>   	dev_set_drvdata(dev, lvds);
>   
>   	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
>   	if (ret < 0)
> -		DRM_DEV_ERROR(dev, "failed to add component\n");
> +		return dev_err_probe(dev, ret, "failed to add component\n");
>   

Should this rather be drm_error? I believe this is related to the 
Rockchip DRM main device?

Otherwise looks good to me,

Cheers,
Quentin


From peter.griffin at linaro.org  Tue Mar  4 03:49:29 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Tue, 4 Mar 2025 11:49:29 +0000
Subject: [PATCH 4/6] scsi: ufs: exynos: Enable PRDT pre-fetching with UFSHCD_CAP_CRYPTO
In-Reply-To: <bb595629-f975-4417-af28-8f4924a5ca5c@acm.org>
References: <20250226220414.343659-1-peter.griffin@linaro.org>
 <20250226220414.343659-5-peter.griffin@linaro.org> <bb595629-f975-4417-af28-8f4924a5ca5c@acm.org>
Message-ID: <CADrjBPrpXH1E2Wt34KXgfdOTNE1v7JCwU3AN7dqoAPYS7j=8YQ@mail.gmail.com>

Hi Bart,

Thanks for the review feedback.

On Fri, 28 Feb 2025 at 19:18, Bart Van Assche <bvanassche at acm.org> wrote:
>
> On 2/26/25 2:04 PM, Peter Griffin wrote:
> > -     hci_writel(ufs, ilog2(DATA_UNIT_SIZE), HCI_TXPRDT_ENTRY_SIZE);
> > +
> > +     if (hba->caps & UFSHCD_CAP_CRYPTO)
> > +             val |= PRDT_PREFECT_EN;
>
> In a future patch series, please consider renaming PRDT_PREFECT_EN into
> PRDT_PREFECTH_EN.

I was just checking the datasheet naming (it is listed as
PRDT_PREFETCH_ENABLE). As well as the typo in my patch I think your
reply also has a typo :) I'm assuming you would like it renamed to
PRDT_PREFETCH_EN?

Thanks,

Peter


From gshan at redhat.com  Tue Mar  4 03:51:26 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 4 Mar 2025 21:51:26 +1000
Subject: [PATCH v7 34/45] kvm: rme: Hide KVM_CAP_READONLY_MEM for realm
 guests
In-Reply-To: <20250213161426.102987-35-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-35-steven.price@arm.com>
Message-ID: <32a09a27-f131-44dd-8959-abb63b2089a8@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> For protected memory read only isn't supported. While it may be possible
> to support read only for unprotected memory, this isn't supported at the
> present time.
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/arm.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 

It's worthy to explain why KVM_CAP_READONLY_MEM isn't supported and its
negative impact. It's something to be done in the future if I'm correct.

 From QEMU's perspective, all ROM data, which is populated by it, can
be written. It conflicts to the natural limit: all ROM data should be
read-only.

QEMU
====
rom_add_blob
   rom_set_mr
     memory_region_set_readonly
       memory_region_transaction_commit
         kvm_region_commit
           kvm_set_phys_mem
             kvm_mem_flags                                    // flag KVM_MEM_READONLY is missed
             kvm_set_user_memory_region
               kvm_vm_ioctl(KVM_SET_USER_MEMORY_REGION2)

non-secure host
===============
rec_exit_sync_dabt
   kvm_handle_guest_abort
     user_mem_abort
       __kvm_faultin_pfn					   // writable == true
         realm_map_ipa
           WARN_ON(!(prot & KVM_PGTABLE_PROT_W)

non-secure host
===============
kvm_realm_enable_cap(KVM_CAP_ARM_RME_POPULATE_REALM)
   kvm_populate_realm
     __kvm_faultin_pfn					  // writable == true
       realm_create_protected_data_page

> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 1f3674e95f03..0f1d65f87e2b 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -348,7 +348,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   	case KVM_CAP_ONE_REG:
>   	case KVM_CAP_ARM_PSCI:
>   	case KVM_CAP_ARM_PSCI_0_2:
> -	case KVM_CAP_READONLY_MEM:
>   	case KVM_CAP_MP_STATE:
>   	case KVM_CAP_IMMEDIATE_EXIT:
>   	case KVM_CAP_VCPU_EVENTS:
> @@ -362,6 +361,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>   	case KVM_CAP_COUNTER_OFFSET:
>   		r = 1;
>   		break;
> +	case KVM_CAP_READONLY_MEM:
>   	case KVM_CAP_SET_GUEST_DEBUG:
>   		r = !kvm_is_realm(kvm);
>   		break;

Thanks,
Gavin



From heiko at sntech.de  Tue Mar  4 03:51:47 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 12:51:47 +0100
Subject: [PATCH 2/4] iio: adc: rockchip_saradc: Add support for RK3528
In-Reply-To: <20250227184058.2964204-3-jonas@kwiboo.se>
References: <20250227184058.2964204-1-jonas@kwiboo.se>
 <20250227184058.2964204-3-jonas@kwiboo.se>
Message-ID: <11022969.nUPlyArG6x@diego>

Am Donnerstag, 27. Februar 2025, 19:40:51 MEZ schrieb Jonas Karlman:
> The Successive Approximation ADC (SARADC) in RK3528 uses the v2
> controller and support:
> - 10-bit resolution
> - Up to 1MS/s sampling rate
> - 4 single-ended input channels
> - Current consumption: 0.5mA @ 1MS/s
> 
> Add support for the 4 channels of 10-bit resolution supported by SARADC
> in RK3528.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>





From wbg at kernel.org  Tue Mar  4 03:54:37 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Tue, 4 Mar 2025 20:54:37 +0900
Subject: [PATCH v6 1/3] include: uapi: counter: Add
 microchip-tcb-capture.h
In-Reply-To: <8cf056d7-22d0-4bf2-8dd6-79a45977bfc1@prolan.hu>
References: <20250227144023.64530-1-csokas.bence@prolan.hu>
 <20250227144023.64530-2-csokas.bence@prolan.hu>
 <Z8bNFjh85p2jqK9C@ishi>
 <8cf056d7-22d0-4bf2-8dd6-79a45977bfc1@prolan.hu>
Message-ID: <Z8bp_RJSPSXOLV5C@ishi>

On Tue, Mar 04, 2025 at 12:14:04PM +0100, Cs?k?s Bence wrote:
> Hi,
> 
> On 2025. 03. 04. 10:51, William Breathitt Gray wrote:
> > On Thu, Feb 27, 2025 at 03:40:18PM +0100, Bence Cs?k?s wrote:
> > > Add UAPI header for the microchip-tcb-capture.c driver.
> > > This header will hold the various event channels, component numbers etc.
> > > used by this driver.
> > > 
> > > Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
> > 
> > Oops, I almost missed this one! Make sure I'm included in the To field
> > for the next revision. ;-)
> > 
> > By the way, b4 is a nifty tool that can save you some work and help you
> > prep patch series for submission.[^1]
> 
> Yes, I have considered it, but unfortunately it still has quite a few bugs,
> for example [1], which has mangled my tags before, when a maintainer using
> it tried to apply one of my patches with it.
> 
> [1] https://github.com/mricon/b4/issues/52

Oh that is unfortunate, you'll have to continue submitting manually for
now until those bugs are fixed. :-(

> > > +/*
> > > + * The driver defines the following components:
> > > + *
> > > + * Count 0
> > > + * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
> > > + * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
> > > + */
> > > +
> > > +enum counter_mchp_signals {
> > > +	COUNTER_MCHP_SIG_TIOA,
> > > +	COUNTER_MCHP_SIG_TIOB,
> > > +};
> > 
> > Are these meant to be used to identify the Signals in the
> > microchip-tcb-capture.c file. You should set the the counter_signal id
> > members to these enum constants then. However, this enum doesn't need to
> > be exposed to userspace in that case.
> 
> The thought was to let userspace figure out which
> `signal%d_action_component_id` to read, but now I see that this is not the
> way to go.
> 
> > If that is the only purpose of enum counter_mchp_signals, then we can
> > omit this patch from the series and you won't need to send it in the
> > next revision.
> 
> Alright, I'll drop this enum. Then this header will be empty at the start,
> save for the block comment. I hope that will be alright.

No, it'll better to drop this patch and introduce the header in the IRQ
handling patch. You can merge the MAINTAINERS change there as well.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/c8ef4a4f/attachment.sig>

From rmk+kernel at armlinux.org.uk  Tue Mar  4 02:53:26 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 04 Mar 2025 10:53:26 +0000
Subject: [PATCH RFC net-next 2/3] net: phylink: add functions to block/unblock
 rx clock stop
In-Reply-To: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
References: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
Message-ID: <E1tpPtu-005Soa-Ac@rmk-PC.armlinux.org.uk>

Some MACs require the PHY receive clock to be running to complete setup
actions. This may fail if the PHY has negotiated EEE, the MAC supports
receive clock stop, and the link has entered LPI state. Provide a pair
of APIs that MAC drivers can use to temporarily block the PHY disabling
the receive clock.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 62 +++++++++++++++++++++++++++++++--------
 include/linux/phylink.h   |  3 ++
 2 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0aae0bb2a254..9a62808cf935 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -88,6 +88,7 @@ struct phylink {
 	bool mac_enable_tx_lpi;
 	bool mac_tx_clk_stop;
 	u32 mac_tx_lpi_timer;
+	u8 mac_rx_clk_stop_blocked;
 
 	struct sfp_bus *sfp_bus;
 	bool sfp_may_have_phy;
@@ -2592,6 +2593,55 @@ void phylink_stop(struct phylink *pl)
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
+
+void phylink_rx_clk_stop_block(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Disable PHY receive clock stop if this is the first time this
+	 * function has been called and clock-stop was previously enabled.
+	 */
+	if (pl->mac_rx_clk_stop_blocked++ == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev)
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, false);
+}
+
+/**
+ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * All calls to phylink_rx_clk_stop_block() must be balanced with a
+ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
+ * clock stop ability.
+ */
+void phylink_rx_clk_stop_unblock(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == 0) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Re-enable PHY receive clock stop if the number of unblocks matches
+	 * the number of calls to the block function above.
+	 */
+	if (--pl->mac_rx_clk_stop_blocked == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, true);
+}
+
 /**
  * phylink_suspend() - handle a network device suspend event
  * @pl: a pointer to a &struct phylink returned from phylink_create()
@@ -2649,18 +2699,6 @@ void phylink_resume(struct phylink *pl)
 
 	ASSERT_RTNL();
 
-	if (pl->mac_supports_eee_ops && pl->phydev) {
-		/* Explicitly configure whether the PHY is allowed to stop its
-		 * receive clock on resume to ensure that it is correctly
-		 * configured.
-		 */
-		ret = phy_eee_rx_clock_stop(pl->phydev,
-					    pl->config->eee_rx_clk_stop_enable);
-		if (ret == -EOPNOTSUPP)
-			phylink_warn(pl, "failed to set rx clock stop: %pe\n",
-				     ERR_PTR(ret));
-	}
-
 	if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
 		/* Wake-on-Lan enabled, MAC handling */
 
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 08df65f6867a..249c437d6b7b 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -698,6 +698,9 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
 void phylink_start(struct phylink *);
 void phylink_stop(struct phylink *);
 
+void phylink_rx_clk_stop_block(struct phylink *);
+void phylink_rx_clk_stop_unblock(struct phylink *);
+
 void phylink_suspend(struct phylink *pl, bool mac_wol);
 void phylink_resume(struct phylink *pl);
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Tue Mar  4 02:53:31 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 04 Mar 2025 10:53:31 +0000
Subject: [PATCH RFC net-next 3/3] net: stmmac: block PHY rx clock-stop over
 reset
In-Reply-To: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
References: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
Message-ID: <E1tpPtz-005Soh-EG@rmk-PC.armlinux.org.uk>

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index aec230353ac4..21026ea7541c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3097,7 +3097,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
 		priv->plat->dma_cfg->atds = 1;
 
+	/* Note that the PHY clock must be running for reset to complete. */
+	phylink_rx_clk_stop_block(priv->phylink);
 	ret = stmmac_reset(priv, priv->ioaddr);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 	if (ret) {
 		netdev_err(priv->dev, "Failed to reset the dma\n");
 		return ret;
-- 
2.30.2



From linux at armlinux.org.uk  Tue Mar  4 02:53:17 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 4 Mar 2025 10:53:17 +0000
Subject: [PATCH RFC net-next 0/3] net: stmmac: approach 2 to solve EEE LPI
 reset issues
Message-ID: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>

Hi,

This is a second approach to solving the STMMAC reset issues caused by
the lack of receive clock from the PHY where the media is in low power
mode with a PHY that supports receive clock-stop.

The first approach centred around only addressing the issue in the
resume path, but it seems to also happen when the platform glue module
is removed and re-inserted (Jon - can you check whether that's also
the case for you please?)

As this is more targetted, I've dropped the patches from this series
which move the call to phylink_resume(), so the link may still come
up too early on resume - but that's something I also intend to fix.

This is experimental - so I value test reports for this change.

As mentioned recently, the reset timeout will only occur if the PHY
receive clock is actually stopped at the moment that stmmac_reset()
is called and remains stopped for the duration of the timeout.
Network activity can wake up the link, causing the PHY to restart
its receive clock and allow reset to complete. So, careful testing
with and without these patches is necessary.

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |  3 ++
 drivers/net/phy/phylink.c                         | 54 ++++++++++++++++++++++-
 include/linux/phylink.h                           |  3 ++
 3 files changed, 59 insertions(+), 1 deletion(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Tue Mar  4 02:53:21 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 04 Mar 2025 10:53:21 +0000
Subject: [PATCH RFC net-next 1/3] net: phylink: add config of PHY receive
 clock-stop in phylink_resume()
In-Reply-To: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
References: <Z8bbnSG67rqTj0pH@shell.armlinux.org.uk>
Message-ID: <E1tpPtp-005SoU-7N@rmk-PC.armlinux.org.uk>

Add configuration of the receive clock-stop in phylink_resume() to
ensure that the clock-stop is correctly configured.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3b186ab3854..0aae0bb2a254 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -2264,7 +2264,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
 	pl->mac_tx_clk_stop = phy_eee_tx_clock_stop_capable(phy) > 0;
 
 	if (pl->mac_supports_eee_ops) {
-		/* Explicitly configure whether the PHY is allowed to stop it's
+		/* Explicitly configure whether the PHY is allowed to stop its
 		 * receive clock.
 		 */
 		ret = phy_eee_rx_clock_stop(phy,
@@ -2645,8 +2645,22 @@ EXPORT_SYMBOL_GPL(phylink_suspend);
  */
 void phylink_resume(struct phylink *pl)
 {
+	int ret;
+
 	ASSERT_RTNL();
 
+	if (pl->mac_supports_eee_ops && pl->phydev) {
+		/* Explicitly configure whether the PHY is allowed to stop its
+		 * receive clock on resume to ensure that it is correctly
+		 * configured.
+		 */
+		ret = phy_eee_rx_clock_stop(pl->phydev,
+					    pl->config->eee_rx_clk_stop_enable);
+		if (ret == -EOPNOTSUPP)
+			phylink_warn(pl, "failed to set rx clock stop: %pe\n",
+				     ERR_PTR(ret));
+	}
+
 	if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
 		/* Wake-on-Lan enabled, MAC handling */
 
-- 
2.30.2



From robh at kernel.org  Tue Mar  4 02:57:10 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 04 Mar 2025 04:57:10 -0600
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <20250304093127.1954549-2-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
Message-ID: <174108583009.1693369.10518412306267353272.robh@kernel.org>


On Tue, 04 Mar 2025 17:31:24 +0800, Jacky Bai wrote:
> Add interrupts-extended property for edma that has multiple interrupt
> controllers used.
> 
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - newly added entry
> ---
>  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/dma/fsl,edma.yaml:102:5: [warning] wrong indentation: expected 6 but found 4 (indentation)
./Documentation/devicetree/bindings/dma/fsl,edma.yaml:104:5: [warning] wrong indentation: expected 6 but found 4 (indentation)

dtschema/dtc warnings/errors:

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250304093127.1954549-2-ping.bai at nxp.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From m-malladi at ti.com  Tue Mar  4 02:57:51 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Tue, 4 Mar 2025 16:27:51 +0530
Subject: [PATCH net-next v4 0/2] Add perout configuration support in IEP driver
Message-ID: <20250304105753.1552159-1-m-malladi@ti.com>

IEP driver supported both perout and pps signal generation
but perout feature is faulty with half-cooked support
due to some missing configuration. Hence perout feature is
removed as a bug fix. This patch series adds back this feature
which configures perout signal based on the arguments passed
by the perout request.

This patch series is continuation to the bug fix: 
https://lore.kernel.org/all/20250227092441.1848419-1-m-malladi at ti.com/
as suggested by Jakub Kicinski and Jacob Keller:
https://lore.kernel.org/all/20250220172410.025b96d6 at kernel.org/

v3:https://lore.kernel.org/all/20250303135124.632845-1-m-malladi at ti.com/

Meghana Malladi (2):
  net: ti: icss-iep: Add pwidth configuration for perout signal
  net: ti: icss-iep: Add phase offset configuration for perout signal

 drivers/net/ethernet/ti/icssg/icss_iep.c | 63 ++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 4 deletions(-)


base-commit: f77f12010f67259bd0e1ad18877ed27c721b627a
-- 
2.43.0



From m-malladi at ti.com  Tue Mar  4 02:57:52 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Tue, 4 Mar 2025 16:27:52 +0530
Subject: [PATCH net-next v4 1/2] net: ti: icss-iep: Add pwidth configuration for perout signal
In-Reply-To: <20250304105753.1552159-1-m-malladi@ti.com>
References: <20250304105753.1552159-1-m-malladi@ti.com>
Message-ID: <20250304105753.1552159-2-m-malladi@ti.com>

icss_iep_perout_enable_hw() is a common function for generating
both pps and perout signals. When enabling pps, the application needs
to only pass enable/disable argument, whereas for perout it supports
different flags to configure the signal.

But icss_iep_perout_enable_hw() function is missing to hook the
configuration params passed by the app, causing perout to behave
same a pps (except being able to configure the period). As duty cycle
is also one feature which can configured for perout, incorporate this
in the function to get the expected signal.

Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
---
Changes from v3 (v4-v3):
- Move flag checks out of mutex lock as suggested by Kory Maincent <kory.maincent at bootlin.com>
- Collected RB tag from Kory Maincent <kory.maincent at bootlin.com>

 drivers/net/ethernet/ti/icssg/icss_iep.c | 47 ++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index d59c1744840a..2981c19c48b1 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -406,9 +406,16 @@ static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns)
 static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				     struct ptp_perout_request *req, int on)
 {
+	struct timespec64 ts;
+	u64 ns_width;
 	int ret;
 	u64 cmp;
 
+	/* Calculate width of the signal for PPS/PEROUT handling */
+	ts.tv_sec = req->on.sec;
+	ts.tv_nsec = req->on.nsec;
+	ns_width = timespec64_to_ns(&ts);
+
 	if (iep->ops && iep->ops->perout_enable) {
 		ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
 		if (ret)
@@ -419,8 +426,9 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
 			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
 				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
-			/* Configure SYNC, 1ms pulse width */
-			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000);
+			/* Configure SYNC, based on req on width */
+			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+				     div_u64(ns_width, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
 			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
@@ -447,6 +455,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				   + req->period.nsec;
 			icss_iep_update_to_next_boundary(iep, start_ns);
 
+			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+				     div_u64(ns_width, iep->def_inc));
 			/* Enable Sync in single shot mode  */
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
 				     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
@@ -474,7 +484,36 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 static int icss_iep_perout_enable(struct icss_iep *iep,
 				  struct ptp_perout_request *req, int on)
 {
-	return -EOPNOTSUPP;
+	int ret = 0;
+
+	/* Reject requests with unsupported flags */
+	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	if (iep->pps_enabled) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	if (iep->perout_enabled == !!on)
+		goto exit;
+
+	/* Set default "on" time (1ms) for the signal if not passed by the app */
+	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
+		req->on.sec = 0;
+		req->on.nsec = NSEC_PER_MSEC;
+	}
+
+	ret = icss_iep_perout_enable_hw(iep, req, on);
+	if (!ret)
+		iep->perout_enabled = !!on;
+
+exit:
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return ret;
 }
 
 static void icss_iep_cap_cmp_work(struct work_struct *work)
@@ -553,6 +592,8 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
 		rq.perout.period.nsec = 0;
 		rq.perout.start.sec = ts.tv_sec + 2;
 		rq.perout.start.nsec = 0;
+		rq.perout.on.sec = 0;
+		rq.perout.on.nsec = NSEC_PER_MSEC;
 		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
 	} else {
 		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
-- 
2.43.0



From sudeep.holla at arm.com  Tue Mar  4 02:58:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:58:24 +0000
Subject: [PATCH v4] firmware: smccc: Support optional Arm SMC SOC_ID name
In-Reply-To: <20250219005932.3466-1-paul@os.amperecomputing.com>
References: <20241114030452.10149-1-paul@os.amperecomputing.com> <20250219005932.3466-1-paul@os.amperecomputing.com>
Message-ID: <174108587625.432485.15057756163207597336.b4-ty@arm.com>

On Tue, 18 Feb 2025 16:59:32 -0800, Paul Benoit wrote:
> Issue Number 1.6 of the Arm SMC Calling Convention introduces an optional
> SOC_ID name string.  If implemented, point the 'machine' field of the SoC
> Device Attributes at this string so that it will appear under
> /sys/bus/soc/devices/soc0/machine.
>
> On Arm SMC compliant SoCs, this will allow things like 'lscpu' to
> eventually get a SoC provider model name from there rather than each
> tool/utility needing to get a possibly inconsistent, obsolete, or incorrect
> model/machine name from its own hardcoded model/machine name table.
>
> [...]

Applied to sudeep.holla/linux (for-linux-next), thanks!

[1/1] firmware: smccc: Support optional Arm SMC SOC_ID name
      https://git.kernel.org/sudeep.holla/c/5f9c23abc477
--
Regards,
Sudeep



From m-malladi at ti.com  Tue Mar  4 02:57:53 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Tue, 4 Mar 2025 16:27:53 +0530
Subject: [PATCH net-next v4 2/2] net: ti: icss-iep: Add phase offset configuration for perout signal
In-Reply-To: <20250304105753.1552159-1-m-malladi@ti.com>
References: <20250304105753.1552159-1-m-malladi@ti.com>
Message-ID: <20250304105753.1552159-3-m-malladi@ti.com>

icss_iep_perout_enable_hw() is a common function for generating
both pps and perout signals. When enabling pps, the application needs
to only pass enable/disable argument, whereas for perout it supports
different flags to configure the signal.

In case the app passes a valid phase offset value, the signal should
start toggling after that phase offset, else start immediately or
as soon as possible. ICSS_IEP_SYNC_START_REG register take number of
clock cycles to wait before starting the signal after activation time.
Set appropriate value to this register to support phase offset.

Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
---
Changes from v3 (v4-v3):
- Move flag checks out of mutex lock as suggested by Kory Maincent <kory.maincent at bootlin.com>
- Collected RB tag from Kory Maincent <kory.maincent at bootlin.com>

 drivers/net/ethernet/ti/icssg/icss_iep.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index 2981c19c48b1..b4a34c57b7b4 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -407,6 +407,7 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 				     struct ptp_perout_request *req, int on)
 {
 	struct timespec64 ts;
+	u64 ns_start;
 	u64 ns_width;
 	int ret;
 	u64 cmp;
@@ -416,6 +417,14 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 	ts.tv_nsec = req->on.nsec;
 	ns_width = timespec64_to_ns(&ts);
 
+	if (req->flags & PTP_PEROUT_PHASE) {
+		ts.tv_sec = req->phase.sec;
+		ts.tv_nsec = req->phase.nsec;
+		ns_start = timespec64_to_ns(&ts);
+	} else {
+		ns_start = 0;
+	}
+
 	if (iep->ops && iep->ops->perout_enable) {
 		ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
 		if (ret)
@@ -430,7 +439,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
 				     div_u64(ns_width, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
-			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
+			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
+				     div_u64(ns_start, iep->def_inc));
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
 			/* Enable CMP 1 */
 			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
@@ -457,6 +467,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
 
 			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
 				     div_u64(ns_width, iep->def_inc));
+			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
+				     div_u64(ns_start, iep->def_inc));
 			/* Enable Sync in single shot mode  */
 			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
 				     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
@@ -487,7 +499,8 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
 	int ret = 0;
 
 	/* Reject requests with unsupported flags */
-	if (req->flags & ~PTP_PEROUT_DUTY_CYCLE)
+	if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
+			  PTP_PEROUT_PHASE))
 		return -EOPNOTSUPP;
 
 	mutex_lock(&iep->ptp_clk_mutex);
@@ -588,6 +601,7 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
 	if (on) {
 		ns = icss_iep_gettime(iep, NULL);
 		ts = ns_to_timespec64(ns);
+		rq.perout.flags = 0;
 		rq.perout.period.sec = 1;
 		rq.perout.period.nsec = 0;
 		rq.perout.start.sec = ts.tv_sec + 2;
-- 
2.43.0



From sudeep.holla at arm.com  Tue Mar  4 02:58:45 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:58:45 +0000
Subject: [GIT PULL] firmware: smccc: Update for v6.15
Message-ID: <20250304105845.432813-1-sudeep.holla@arm.com>

Hi ARM SoC Team,

Please pull !

Regards,
Sudeep

-->8

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git tags/smccc-update-6.15

for you to fetch changes up to 5f9c23abc47744f2578af4a362655c31254c93b5:

  firmware: smccc: Support optional Arm SMCCC SOC_ID name (2025-03-03 14:53:46 +0000)

----------------------------------------------------------------
Arm SMCCC update for v6.15

Just a single update introducing the support for the optional SOC_ID
name string from the Arm SMCCC v1.6 specification.

If the SOC_ID name string is implemented, the machine field of the SoC
Device Attributes will reflect it.

The original intent of SOC_ID was to provide a JEP-106 code for the SiP
and the SoC revision to uniquely identify the SoC. However, there has
been a request to add this optional name so that SoC firmware can
directly provide the SoC name to the OS.

This change avoids the need for frequent updates to various tools that
would otherwise require maintaining hardcoded model/machine name tables
for new SoCs.

----------------------------------------------------------------
Paul Benoit (1):
      firmware: smccc: Support optional Arm SMCCC SOC_ID name

 drivers/firmware/smccc/soc_id.c | 80 +++++++++++++++++++++++++++++++++++++++++
 include/linux/arm-smccc.h       | 40 +++++++++++++++++++++
 2 files changed, 120 insertions(+)


From sudeep.holla at arm.com  Tue Mar  4 02:58:56 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:58:56 +0000
Subject: [GIT PULL] arm64: dts: juno/vexpress: Updates for v6.15
Message-ID: <20250304105856.432848-1-sudeep.holla@arm.com>

Hi ARM SoC Team,

Please pull !

Regards,
Sudeep

-->8

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git tags/juno-updates-6.15

for you to fetch changes up to 21b9f56cec8f8918b5bbb900d6d86eaf06d54537:

  arm64: dts: corstone1000: Add definitions for secondary CPU cores (2025-03-03 17:07:15 +0000)

----------------------------------------------------------------
Armv8 FVP/Vexpress/Juno updates for v6.15

The main and bulk of the addition this time is the support for the Arm
reference Morello System Development Platform (SDP).

The Morello architecture is an experimental extension to Armv8.2-A,
enhancing the AArch64 execution state with capabilities for fine-grained
memory protection and scalable software compartmentalization. However
these changes doesn't add any of the support for security enhancements.
This is mainly adding device tree support for Morello SDP.

The platform iteslf is shipped with ACPI firmware. However, since the
ACPI bindings for GPU, DPU, I2C, I2S,..etc are not well defined or not
provided in the shipped ACPI firmware, there is a need for the device
tree as alternative for the developers focusing on those features.

The CPU is called rainier, the architecture is Morello and the platform
is Morello SDP board. There is FVP equivalent of the same though they
are not completely in feature parity with the real hardware.

These changes provide the initial support for Morello SDP and FVP
platforms.

Apart from this, we have an update to add support for secondary cores
on Corstone1000 FVP platform.

----------------------------------------------------------------
Hugues KAMBA MPIANA (1):
      arm64: dts: corstone1000: Add definitions for secondary CPU cores

Vincenzo Frascino (9):
      arm64: Kconfig: Update description for CONFIG_ARCH_VEXPRESS
      dt-bindings: arm: Add Morello compatibility
      dt-bindings: arm: Add Morello fvp compatibility
      dt-bindings: arm: Add Rainier compatibility
      dt-bindings: arm-pmu: Add support for ARM Rainier PMU
      arm64: dts: morello: Add support for common functionalities
      arm64: dts: morello: Add support for soc dts
      arm64: dts: morello: Add support for fvp dts
      MAINTAINERS: Add Vincenzo Frascino as Arm Morello Maintainer

 .../devicetree/bindings/arm/arm,morello.yaml       |  35 +++
 Documentation/devicetree/bindings/arm/cpus.yaml    |   1 +
 Documentation/devicetree/bindings/arm/pmu.yaml     |   1 +
 MAINTAINERS                                        |   7 +
 arch/arm64/Kconfig.platforms                       |   5 +-
 arch/arm64/boot/dts/arm/Makefile                   |   1 +
 arch/arm64/boot/dts/arm/corstone1000-fvp.dts       |  26 ++
 arch/arm64/boot/dts/arm/corstone1000.dtsi          |   3 +-
 arch/arm64/boot/dts/arm/morello-fvp.dts            |  77 +++++
 arch/arm64/boot/dts/arm/morello-sdp.dts            | 157 ++++++++++
 arch/arm64/boot/dts/arm/morello.dtsi               | 323 +++++++++++++++++++++
 11 files changed, 632 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,morello.yaml
 create mode 100644 arch/arm64/boot/dts/arm/morello-fvp.dts
 create mode 100644 arch/arm64/boot/dts/arm/morello-sdp.dts
 create mode 100644 arch/arm64/boot/dts/arm/morello.dtsi


From krzk at kernel.org  Tue Mar  4 02:59:08 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 11:59:08 +0100
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
Message-ID: <2fd83d68-7104-4755-a0f0-8ce4a2601e09@kernel.org>

On 04/03/2025 11:44, Kevin Chen wrote:
> +
> +static int aspeed_pcc_probe(struct platform_device *pdev)
> +{
> +	int rc;
> +	struct aspeed_pcc_ctrl *pcc;
> +	struct device *dev;
> +	uint32_t fifo_size = PAGE_SIZE;
> +
> +	dev = &pdev->dev;

This goes to declaration.

> +
> +	pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL);

Maybe my previous comment was not clear, but you agreed with it. Anyway
nothing improved here.

If you have 'dev' variable, use it.

> +	if (!pcc)
> +		return -ENOMEM;
> +
> +	pcc->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);

same here and everywhere else.

> +	if (IS_ERR(pcc->regmap)) {
> +		dev_err(dev, "Couldn't get regmap\n");
> +		return -ENODEV;
> +	}
> +
> +	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
> +	if (rc) {
> +		dev_err(dev, "no pcc ports configured\n");
> +		return -ENODEV;
> +	}
> +
> +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> +	if (rc) {
> +		dev_err(dev, "cannot set 64-bits DMA mask\n");
> +		return rc;
> +	}
> +
> +	pcc->dma.size = PCC_DMA_BUFSZ;
> +	pcc->dma.virt = dmam_alloc_coherent(dev,
> +					    pcc->dma.size,
> +					    &pcc->dma.addr,
> +					    GFP_KERNEL);
> +	if (!pcc->dma.virt) {
> +		dev_err(dev, "cannot allocate DMA buffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
> +	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
> +	if (rc) {
> +		dev_err(dev, "cannot allocate kFIFO\n");

Drop

> +		return -ENOMEM;
> +	}
> +
> +	/* Disable PCC to clean up DMA buffer before request IRQ. */
> +	rc = aspeed_pcc_disable(pcc);
> +	if (rc) {
> +		dev_err(dev, "Couldn't disable PCC\n");
> +		goto err_free_kfifo;
> +	}
> +
> +	pcc->irq = platform_get_irq(pdev, 0);
> +	if (pcc->irq < 0) {
> +		dev_err(dev, "Couldn't get IRQ\n");

Drop, core already prints this. Do not duplicate messages.

> +		rc = -ENODEV;

Why not using pcc->irq as rc?

> +		goto err_free_kfifo;
> +	}
> +
Best regards,
Krzysztof


From sudeep.holla at arm.com  Tue Mar  4 02:59:15 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue,  4 Mar 2025 10:59:15 +0000
Subject: [GIT PULL] firmware: arm_scmi: Updates for v6.15
Message-ID: <20250304105915.432967-1-sudeep.holla@arm.com>

Hi ARM SoC Team,

Please pull !

Regards,
Sudeep

-->8

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git tags/scmi-updates-6.15

for you to fetch changes up to d069c33f5ce2fe8f13489ba396080fcf28c10f60:

  firmware: arm_scmi: Emit modalias for SCMI devices (2025-02-03 10:50:11 +0000)

----------------------------------------------------------------
Arm SCMI updates for v6.15

Couple of updates around the flexibility in SCMI device names and
addition of name, protocol id attributes and modalias for SCMI
devices in the sysfs.

Currently, in the scmi_protocol_device_request() function, SCMI device
names ust be unique across all protocols. However, this constraint is
being relaxed, allowing devices in different protocols to share the
same name. The change aims to provide more flexibility in naming devices
across various protocols.

Two attributes: name and protocol ID is being added to the SCMI device
in the sysfs along with the support for the modalias. These attributes
aim to enhance device identification and management.

----------------------------------------------------------------
Sudeep Holla (3):
      firmware: arm_scmi: Relax duplicate name constraint across protocol ids
      firmware: arm_scmi: Add name and protocol id attributes
      firmware: arm_scmi: Emit modalias for SCMI devices

 drivers/firmware/arm_scmi/bus.c | 69 +++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 13 deletions(-)


From ping.bai at nxp.com  Tue Mar  4 04:02:00 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue, 4 Mar 2025 12:02:00 +0000
Subject: [PATCH] irq: imx-irqsteer: irq_count can larger than registered
 irq
In-Reply-To: <87bjuh6r9q.ffs@tglx>
References: <20250304094513.1964356-1-ping.bai@nxp.com> <87bjuh6r9q.ffs@tglx>
Message-ID: <AS8PR04MB8642733D81F0A37FBB70902E87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH] irq: imx-irqsteer: irq_count can larger than registered irq
> 
> On Tue, Mar 04 2025 at 17:45, Jacky Bai wrote:
> > From: Shengjiu Wang <shengjiu.wang at nxp.com>
Hi Thomas,

> 
> Please use the proper subsystem prefix as documented:
> 
> 
...

> 
> Also 'irq_count can larger than registered irq' is not a sentence and tells
> absolutely nothing what this patch is about.
> 

My fault, will fix it.

> > The irqsteer IP itself can support up to 5 channels and each channel
> > can support max 960 IRQs per. The actual number of
> 
> Can you please write out words, i.e. interrupts, hardware etc.. This is a
> changelog and not twatter.
> 
> Aside of that: 'per.' does not make any sense. 'per' wants to be followed by a
> noun: '...per $WHAT.'
> 

Thx, will improve and fix in v2.

> > channels and IRQ per channel implemented in HW is SoC related.
> 
> > For previous i.MX SoCs, normally only one channel and max 512 IRQ is
> > implemented, But for i.MX94, the irqsteer HW is implemented for 960
> > IRQs, even it only has 384 IRQs connected.
> >
> > That means on i.MX94, the 'irq_number' is 6 but the 'irq_count' is
> 
> What means irq_number and irq_count here?

For irqsteer, the interrupt inputs are divided into groups, each group has 64 interrupt
Inputs and use one irqsteer's interrupt output line to raise interrupt to parent interrupt controller.

The irq_number means how many interrupt output lines from irqsteer are really
connected to the parent interrupt controller, while the irq_count means the max
interrupt input line groups in the irqsteer instance.

If the irq_count is 15, as each group has 64 interrupts, it means the irqsteer
can support up to 960 interrupt inputs.

> 
> > 15, so we need to increase the CHAN_MAX_OUTPUT_INT to 0xF(960 / 64)
> 
> What kind of math is 0xF(960 / 64) ? And what has this to do with
> irq_number=6 ad irq_count=15?

As mentioned above, if the irqsteer is designed in HW with max 960 interrupt inputs,
It needs 15 interrupt outputs: 960 / 16 = 15. Even if we only 384, 512, or any number of
interrupt inputs less than 960 are actually connected to valid peripheral interrupt.

For i.MX94, In the SoC design, the irqsteer is designed with max 960 interrupt inputs, the
irq_count is 15. But only 384 inputs are really connected in HW. For these 384 interrupts,
it need 6 irqsteer interrupt output(384 / 64 = 6), the irq_number is 6.

In other world, the irq_number means the number of used interrupt outputs, while irq_count
means the max interrupt outputs that can be supported by an irqsteer instance.

I will refine the changelog to make it more clear. Sorry for the confusion,^_^

BR
Jacky
> 
> Thanks,
> 
>         tglx



From heiko at sntech.de  Tue Mar  4 04:02:45 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 13:02:45 +0100
Subject: (subset) [PATCH 0/7] rockchip: Add support for leds and user button on Radxa E20C
In-Reply-To: <20250228064024.3200000-1-jonas@kwiboo.se>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
Message-ID: <174108970986.65436.4272591414898454986.b4-ty@sntech.de>


On Fri, 28 Feb 2025 06:40:06 +0000, Jonas Karlman wrote:
> The Radxa E20C has three gpio leds and one gpio button.
> 
> This series adds dt-binding, driver support, DT node in SoC .dtsi and
> gpio-keys and gpio-leds nodes in board DT to support the leds and user
> button.
> 
> This series builds on top of the "rockchip: Add support for maskrom
> button on Radxa E20C" series [1].
> 
> [...]

Applied, thanks!

[1/7] dt-bindings: soc: rockchip: Add RK3528 ioc grf syscon
      commit: ac32ad07a97648eb8330b2c4cb840b0ef46903ae
[4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
      commit: a31fad19ae39ea27b5068e3b02bcbf30a905339b
[5/7] arm64: dts: rockchip: Add uart0 pinctrl to Radxa E20C
      commit: 0d2312f0d3e4ce74af0977c1519a07dfc71a82ac

Patches 6+7 depend on the parallel saradc support series and thus
do not apply - and need too much rework to safely apply.


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From h-salunke at ti.com  Tue Mar  4 04:03:20 2025
From: h-salunke at ti.com (Hrushikesh Salunke)
Date: Tue, 4 Mar 2025 17:33:20 +0530
Subject: [PATCH] arm64: defconfig: Enable config for PL2303 USB to serial adapter
Message-ID: <20250304120320.874617-1-h-salunke@ti.com>

Enable support for Prolific PL2303 USB Serial single port adapter.

Signed-off-by: Hrushikesh Salunke <h-salunke at ti.com>
---
This patch is based on commit
20d5c66e1810  Add linux-next specific files for 20250304

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db2982..8b233b7ea857 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1113,6 +1113,7 @@ CONFIG_USB_ISP1760=y
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_CP210X=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_SERIAL_OPTION=m
 CONFIG_USB_QCOM_EUD=m
 CONFIG_USB_HSIC_USB3503=y
-- 
2.34.1



From cristian.ciocaltea at collabora.com  Tue Mar  4 04:04:18 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 4 Mar 2025 14:04:18 +0200
Subject: [PATCH v4 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250304-small-mindful-mongrel-bd6f8b@houat>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>
 <20250304-small-mindful-mongrel-bd6f8b@houat>
Message-ID: <155f609f-994f-4140-8453-7e38a5e6deef@collabora.com>

Hi Maxime,

On 3/4/25 10:13 AM, Maxime Ripard wrote:
> Hi,
> 
> On Tue, Mar 04, 2025 at 03:44:02AM +0200, Cristian Ciocaltea wrote:
>> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
>> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
>> and not before.
>>
>> While at it, introduce a define for this rate limit constant.
>>
>> Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -320,6 +320,7 @@
>>  #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
>>  #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
>>  
>> +#define HDMI14_MAX_RATE			340000000
>>  #define HDMI20_MAX_RATE			600000000
>>  
>>  enum dp_link_rate {
>> @@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
>>  
>>  	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
>>  
>> -	if (rate >= 3400000) {
>> +	if (rate > HDMI14_MAX_RATE / 100) {
> 
> The rate seems to come from rk_hdptx_phy_power_on and eventually from
> tmds_char_rate in the PHY config options, so its rate is in Hertz.

The rate coming from rk_hdptx_phy_power_on() is in hHz, since it passed
via dw_hdmi_qp_rockchip_encoder_enable() as

  phy_set_bus_width(hdmi->phy, div_u64(rate, 100));

> HDMI14_MAX_RATE and HDMI20_MAX_RATE are both defined in Hertz as well.
> It seems super odd to mee that you then convert HDMI14_MAX_RATE to hHz?

This stems from the ropll_tmds_cfg table containing the configuration
params for the supported rates which requires the search keys to be
provided in hHz rather than Hz.

I agree this is nothing but confusing, that's why I fixed this up in
"phy: rockchip: samsung-hdptx: Avoid Hz-hHz unit conversion overhead"

Thanks for reviewing!

Regards,
Cristian


From andriy.shevchenko at linux.intel.com  Tue Mar  4 04:07:43 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 4 Mar 2025 14:07:43 +0200
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
 <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
 <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
Message-ID: <Z8btDzggD29xtaAo@smile.fi.intel.com>

On Tue, Mar 04, 2025 at 10:25:03AM +0100, David Lechner wrote:
> On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
> <mazziesaccount at gmail.com> wrote:

...

> There are some different opinions on this, but on the last patch I did
> introducing a new namespace,

> the consensus

Hmm... I may not call that "the consensus"...

> seems to be that putting
> the MODULE_IMPORT_NS() in the header file was convenient so that users
> of the API don't have to remember to both include the header and add
> the import macro.

Which I am against because it will diminish the point of prevention of
the APIs abuse along with a potential to have the stale headers in
the file when the code is moved somewhere else..

So, please do not do that. We have only two abusers currently:
the PWM and SPI OFFLOAD.

-- 
With Best Regards,
Andy Shevchenko




From cristian.ciocaltea at collabora.com  Tue Mar  4 04:12:19 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 4 Mar 2025 14:12:19 +0200
Subject: [PATCH v4 07/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250304-turtle-of-serious-aurora-2b0bae@houat>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-7-8657847c13f7@collabora.com>
 <20250304-turtle-of-serious-aurora-2b0bae@houat>
Message-ID: <ddf4c3c9-849c-4d96-a073-966bb19a6047@collabora.com>

On 3/4/25 10:15 AM, Maxime Ripard wrote:
> On Tue, Mar 04, 2025 at 03:44:06AM +0200, Cristian Ciocaltea wrote:
>> The current workaround to setup the TMDS character rate relies on the
>> unconventional usage of phy_set_bus_width().
>>
>> Make use of the recently introduced HDMI PHY configuration API to
>> properly handle the setup.  The workaround will be dropped as soon as
>> the switch has been completed on both ends.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 54 ++++++++++++++++-------
>>  1 file changed, 38 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 2bf525514c1991a1299265d12e1e85f66333c604..7e1d1c10758249aa5bbddbdaae0108bba04f30df 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -394,6 +394,7 @@ struct rk_hdptx_phy {
>>  
>>  	int phy_id;
>>  	struct phy *phy;
>> +	struct phy_configure_opts_hdmi hdmi_cfg;
>>  	struct clk_bulk_data *clks;
>>  	int nr_clks;
>>  	struct reset_control_bulk_data rsts[RST_MAX];
>> @@ -1409,19 +1410,25 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
>>  static int rk_hdptx_phy_power_on(struct phy *phy)
>>  {
>>  	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
>> -	int bus_width = phy_get_bus_width(hdptx->phy);
>>  	enum phy_mode mode = phy_get_mode(phy);
>> +	unsigned int rate = 0;
>>  	int ret, lane;
>>  
>> -	/*
>> -	 * FIXME: Temporary workaround to pass pixel_clk_rate
>> -	 * from the HDMI bridge driver until phy_configure_opts_hdmi
>> -	 * becomes available in the PHY API.
>> -	 */
>> -	unsigned int rate = bus_width & 0xfffffff;
>> -
>> -	dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
>> -		__func__, bus_width, rate);
>> +	if (mode != PHY_MODE_DP) {
>> +		if (!hdptx->hdmi_cfg.tmds_char_rate) {
>> +			/*
>> +			 * FIXME: Temporary workaround to setup TMDS char rate
>> +			 * from the RK DW HDMI QP bridge driver.
>> +			 * Will be removed as soon the switch to the HDMI PHY
>> +			 * configuration API has been completed on both ends.
>> +			 */
>> +			rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
>> +			hdptx->hdmi_cfg.tmds_char_rate = rate * 100;
>> +		} else {
>> +			rate = hdptx->hdmi_cfg.tmds_char_rate / 100;
>> +		}
>> +		dev_dbg(hdptx->dev, "%s rate=%u\n", __func__, rate);
>> +	}
> 
> Some story here, I can't make sense of a variable in hHz. If it's
> actually needed and not a bug, this should be very explictly documented.

Not a bug - as explained earlier, phy_set_bus_width() on the other end
passes this in hHz.  I agree it should have been properly documented,
but eventually we got this cleaned up in the last patch of the series.

Thanks,
Cristian


From amadeus at jmu.edu.cn  Tue Mar  4 04:10:36 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue,  4 Mar 2025 20:10:36 +0800
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <20250301104835.36439-1-ziyao@disroot.org>
References: <20250301104835.36439-1-ziyao@disroot.org>
Message-ID: <20250304121036.1453284-1-amadeus@jmu.edu.cn>

Hi,

> +	aliases {
> +		mmc0 = &sdmmc;

s/mmc0/mmc1

> +&sdmmc {
> +	bus-width = <4>;
> +	cap-mmc-highspeed;
> +	cap-sd-highspeed;

I think for sdcard, only cap-sd-highspeed
is needed, not cap-mmc-highspeed?

> +	disable-wp;

Missing pinctrl.

> +	rockchip,default-sample-phase = <90>;

It seems that all rk3528 devices need to set this
default phase, so maybe this can be placed in dtsi?

> +	sd-uhs-sdr104;

The rk3528 devices uses gpio to switch IO voltage, maybe
more modes should be added here like vendor kernel?
And these devices use 3.3V IO voltage by default.

	sd-uhs-sdr12;
	sd-uhs-sdr25;
	sd-uhs-sdr50;
	sd-uhs-sdr104;

Thanks,
Chukun

-- 
2.25.1



From brgl at bgdev.pl  Tue Mar  4 02:41:40 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:41:40 +0100
Subject: [PATCH 1/6] ASoC: samsung: bells: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-1-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-1-56a2299dd928@linaro.org>
Message-ID: <CAMRc=MevrFnw4BGRgwKrg+wj+saEmVmk+diGj=+sveE2P_hwYw@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> This file does not use the symbols from the legacy
> <linux/gpio.h> header, so let's drop it.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/bells.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
> index 365b1aca4855c885e0b59a1101475d8edb86374f..b4c0857ae35134b58a125b0746af07a5fff040fa 100644
> --- a/sound/soc/samsung/bells.c
> +++ b/sound/soc/samsung/bells.c
> @@ -7,7 +7,6 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/jack.h>
> -#include <linux/gpio.h>
>  #include <linux/module.h>
>
>  #include "../codecs/wm5102.h"
>
> --
> 2.48.1
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From krzysztof.kozlowski at linaro.org  Tue Mar  4 02:41:59 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue,  4 Mar 2025 11:41:59 +0100
Subject: [PATCH 1/2] arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3399 ROC PC PLUS
Message-ID: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>

Devicetree bindings for ES8388 audio codec expect the device to be
marked as compatible with ES8328.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Changeset depends on bindings patch being accepted to ASoC:
https://lore.kernel.org/all/20250304103808.75236-1-krzysztof.kozlowski at linaro.org/

Please take it to the same or next merge cycle as above ASoC binding.
---
 arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
index e2e9279fa267..8e3858cf988c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
@@ -112,7 +112,7 @@ hym8563: rtc at 51 {
 
 &i2c1 {
 	es8388: es8388 at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		clocks = <&cru SCLK_I2S_8CH_OUT>;
 		#sound-dai-cells = <0>;
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Tue Mar  4 02:42:00 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue,  4 Mar 2025 11:42:00 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3588 boards
In-Reply-To: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
References: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250304104200.76178-2-krzysztof.kozlowski@linaro.org>

Devicetree bindings for ES8388 audio codec expect the device to be
marked as compatible with ES8328.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Changeset depends on bindings patch being accepted to ASoC:
https://lore.kernel.org/all/20250304103808.75236-1-krzysztof.kozlowski at linaro.org/

Please take it to the same or next merge cycle as above ASoC binding.
---
 arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts         | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi      | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts      | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts        | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts   | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi     | 2 +-
 7 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 27a7895595ee..e77a38d726e0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -472,7 +472,7 @@ &i2c7 {
 	status = "okay";
 
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		clocks = <&cru I2S0_8CH_MCLKOUT>;
 		assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi
index a98e804a0949..81031b99c9b9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi
@@ -276,7 +276,7 @@ &i2c7 {
 
 	/* PLDO2 vcca 1.8V, BUCK8 gated by PLDO2 being enabled */
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		clocks = <&cru I2S0_8CH_MCLKOUT>;
 		AVDD-supply = <&vcc_3v3_s0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
index 088cfade6f6f..e07888c9948f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
@@ -311,7 +311,7 @@ &i2c7 {
 	status = "okay";
 
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
 		assigned-clock-rates = <12288000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
index bc4077575beb..7c948b2653da 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
@@ -242,7 +242,7 @@ &i2c3 {
 	status = "okay";
 
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		clocks = <&cru I2S0_8CH_MCLKOUT>;
 		assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
index 812bba0aef1a..b79ce3ec1186 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
@@ -611,7 +611,7 @@ &i2c7 {
 	status = "okay";
 
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		assigned-clock-rates = <12288000>;
 		assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
index 74a4f03e05e3..73042e7416bc 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
@@ -412,7 +412,7 @@ &i2c7 {
 	status = "okay";
 
 	es8388: audio-codec at 11 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x11>;
 		assigned-clock-rates = <12288000>;
 		assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
index 9e16960b8705..a48bcb6b6a91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
@@ -268,7 +268,7 @@ &i2c6 {
 	status = "okay";
 
 	es8388: audio-codec at 10 {
-		compatible = "everest,es8388";
+		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x10>;
 		clocks = <&cru I2S1_8CH_MCLKOUT>;
 		AVDD-supply = <&vcc_3v3_s0>;
-- 
2.43.0



From brgl at bgdev.pl  Tue Mar  4 02:41:52 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:41:52 +0100
Subject: [PATCH 2/6] ASoC: samsung: littlemill: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-2-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-2-56a2299dd928@linaro.org>
Message-ID: <CAMRc=Me7kcLvYPgRF38ahNtq4J0e8yHPRyd9yMnsjN4dB7Y8Ag@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> This file does not use the symbols from the legacy
> <linux/gpio.h> header, so let's drop it.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/littlemill.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
> index c5260e101c2a136001c6273200fa35740e618829..9fa5e3ff9215164491839d6ffdf499a3eeadfbaa 100644
> --- a/sound/soc/samsung/littlemill.c
> +++ b/sound/soc/samsung/littlemill.c
> @@ -7,7 +7,6 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/jack.h>
> -#include <linux/gpio.h>
>  #include <linux/module.h>
>
>  #include "../codecs/wm8994.h"
>
> --
> 2.48.1
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From brgl at bgdev.pl  Tue Mar  4 02:42:03 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:42:03 +0100
Subject: [PATCH 3/6] ASoC: samsung: lowland: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-3-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-3-56a2299dd928@linaro.org>
Message-ID: <CAMRc=MdqV7bm+zbi=mrBhS0506CTXOn09=rJj+pR7RMYmhn-MA@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> This file does not use the symbols from the legacy
> <linux/gpio.h> header, so let's drop it.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/lowland.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
> index 702cb4cc1ce9f07e55ddf9435b19c4691e0236e5..d4088b72d43c2295102d850197f8b9eac50d7120 100644
> --- a/sound/soc/samsung/lowland.c
> +++ b/sound/soc/samsung/lowland.c
> @@ -7,7 +7,6 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/jack.h>
> -#include <linux/gpio.h>
>  #include <linux/module.h>
>
>  #include "../codecs/wm5100.h"
>
> --
> 2.48.1
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From kevin_chen at aspeedtech.com  Tue Mar  4 02:44:31 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 4 Mar 2025 18:44:31 +0800
Subject: Add AST2600 LPC PCC support
Message-ID: <20250304104434.481429-1-kevin_chen@aspeedtech.com>

 The AST2600 has PCC controller in LPC, placed in LPC node. As a result,
 add LPC PCC controller driver to support POST code capture.

--
v2:
  -- Change driver path to drivers/misc

Kevin Chen (3):
  dt-binding: aspeed: Add LPC PCC controller
  ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
  soc: aspeed: lpc-pcc: Add PCC controller support

 .../devicetree/bindings/mfd/aspeed-lpc.yaml   |  36 ++
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi       |   7 +
 drivers/misc/Kconfig                          |  10 +
 drivers/misc/Makefile                         |   1 +
 drivers/misc/aspeed-lpc-pcc.c                 | 441 ++++++++++++++++++
 5 files changed, 495 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

-- 
2.34.1



From kevin_chen at aspeedtech.com  Tue Mar  4 02:44:32 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 4 Mar 2025 18:44:32 +0800
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
Message-ID: <20250304104434.481429-2-kevin_chen@aspeedtech.com>

Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 36 +++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
index 5dfe77aca167..367847bd7e75 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
@@ -149,6 +149,35 @@ patternProperties:
       - interrupts
       - snoop-ports
 
+  "^lpc-pcc@[0-9a-f]+$":
+    type: object
+    additionalProperties: false
+
+    description:
+      The LPC pcc interface allows the BMC to listen on and record the data
+      bytes written by the Host to the targeted LPC I/O pots.
+
+    properties:
+      compatible:
+        items:
+          - enum:
+              - aspeed,ast2600-lpc-pcc
+
+      reg:
+        maxItems: 1
+
+      interrupts:
+        maxItems: 1
+
+      pcc-ports:
+        $ref: /schemas/types.yaml#/definitions/uint32-array
+        description: The LPC I/O ports to pcc
+
+    required:
+      - compatible
+      - interrupts
+      - pcc-ports
+
   "^uart-routing@[0-9a-f]+$":
     $ref: /schemas/soc/aspeed/uart-routing.yaml#
     description: The UART routing control under LPC register space
@@ -176,6 +205,13 @@ examples:
         #size-cells = <1>;
         ranges = <0x0 0x1e789000 0x1000>;
 
+        lpc_pcc: lpc-pcc at 0 {
+            compatible = "aspeed,ast2600-lpc-pcc";
+            reg = <0x0 0x140>;
+            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+            pcc-ports = <0x80>;
+        };
+
         lpc_ctrl: lpc-ctrl at 80 {
             compatible = "aspeed,ast2600-lpc-ctrl";
             reg = <0x80 0x80>;
-- 
2.34.1



From kevin_chen at aspeedtech.com  Tue Mar  4 02:44:33 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 4 Mar 2025 18:44:33 +0800
Subject: [PATCH v2 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
Message-ID: <20250304104434.481429-3-kevin_chen@aspeedtech.com>

The AST2600 has PCC controller in LPC, placed in LPC node.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 8ed715bd53aa..87dcacb78692 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -626,6 +626,13 @@ lpc_snoop: lpc-snoop at 80 {
 					status = "disabled";
 				};
 
+				lpc_pcc: lpc-pcc at 0 {
+					compatible = "aspeed,ast2600-lpc-pcc";
+					reg = <0x0 0x140>;
+					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+					status = "disabled";
+				};
+
 				lhc: lhc at a0 {
 					compatible = "aspeed,ast2600-lhc";
 					reg = <0xa0 0x24 0xc8 0x8>;
-- 
2.34.1



From kevin_chen at aspeedtech.com  Tue Mar  4 02:44:34 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 4 Mar 2025 18:44:34 +0800
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
Message-ID: <20250304104434.481429-4-kevin_chen@aspeedtech.com>

Add LPC PCC controller driver to support POST code capture.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 drivers/misc/Kconfig          |  10 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/aspeed-lpc-pcc.c | 441 ++++++++++++++++++++++++++++++++++
 3 files changed, 452 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 56bc72c7ce4a..d8e2d6c1fe40 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -50,6 +50,16 @@ config AD525X_DPOT_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
+config ASPEED_LPC_PCC
+	tristate "Aspeed Post Code Capture support"
+	select REGMAP
+	select MFD_SYSCON
+	default ARCH_ASPEED
+	help
+	  Provides a driver to control the LPC PCC interface,
+	  allowing the BMC to snoop data bytes written by the
+	  the host to an arbitrary LPC I/O port.
+
 config DUMMY_IRQ
 	tristate "Dummy IRQ handler"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 545aad06d088..4762da7804bf 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_IBMVMC)		+= ibmvmc.o
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
+obj-$(CONFIG_ASPEED_LPC_PCC)	+= aspeed-lpc-pcc.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
diff --git a/drivers/misc/aspeed-lpc-pcc.c b/drivers/misc/aspeed-lpc-pcc.c
new file mode 100644
index 000000000000..f3cbf375d61f
--- /dev/null
+++ b/drivers/misc/aspeed-lpc-pcc.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/kfifo.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regmap.h>
+#include <linux/dma-mapping.h>
+#include <linux/sizes.h>
+
+#define DEVICE_NAME "aspeed-lpc-pcc"
+
+static DEFINE_IDA(aspeed_pcc_ida);
+
+#define HICR5	0x80
+#define HICR5_EN_SNP0W			BIT(0)
+#define HICR5_EN_SNP1W			BIT(2)
+#define HICR6	0x084
+#define   HICR6_EN2BMODE		BIT(19)
+#define SNPWADR	0x090
+#define PCCR6	0x0c4
+#define   PCCR6_DMA_CUR_ADDR		GENMASK(27, 0)
+#define PCCR4	0x0d0
+#define   PCCR4_DMA_ADDRL_MASK		GENMASK(31, 0)
+#define   PCCR4_DMA_ADDRL_SHIFT		0
+#define PCCR5	0x0d4
+#define   PCCR5_DMA_ADDRH_MASK		GENMASK(27, 24)
+#define   PCCR5_DMA_ADDRH_SHIFT		24
+#define   PCCR5_DMA_LEN_MASK		GENMASK(23, 0)
+#define   PCCR5_DMA_LEN_SHIFT		0
+#define HICRB	0x100
+#define   HICRB_ENSNP0D			BIT(14)
+#define   HICRB_ENSNP1D			BIT(15)
+#define PCCR0	0x130
+#define   PCCR0_EN_DMA_INT		BIT(31)
+#define   PCCR0_EN_DMA_MODE		BIT(14)
+#define   PCCR0_ADDR_SEL_MASK		GENMASK(13, 12)
+#define   PCCR0_ADDR_SEL_SHIFT		12
+#define   PCCR0_RX_TRIG_LVL_MASK	GENMASK(10, 8)
+#define   PCCR0_RX_TRIG_LVL_SHIFT	8
+#define   PCCR0_CLR_RX_FIFO		BIT(7)
+#define   PCCR0_MODE_SEL_MASK		GENMASK(5, 4)
+#define   PCCR0_MODE_SEL_SHIFT		4
+#define   PCCR0_EN_RX_TMOUT_INT		BIT(2)
+#define   PCCR0_EN_RX_AVAIL_INT		BIT(1)
+#define   PCCR0_EN			BIT(0)
+#define PCCR1	0x134
+#define   PCCR1_BASE_ADDR_MASK		GENMASK(15, 0)
+#define   PCCR1_BASE_ADDR_SHIFT		0
+#define   PCCR1_DONT_CARE_BITS_MASK	GENMASK(21, 16)
+#define   PCCR1_DONT_CARE_BITS_SHIFT	16
+#define PCCR2	0x138
+#define   PCCR2_INT_STATUS_PATTERN_B	BIT(16)
+#define   PCCR2_INT_STATUS_PATTERN_A	BIT(8)
+#define   PCCR2_INT_STATUS_DMA_DONE	BIT(4)
+#define   PCCR2_INT_STATUS_DATA_RDY	PCCR2_INT_STATUS_DMA_DONE
+#define   PCCR2_INT_STATUS_RX_OVER	BIT(3)
+#define   PCCR2_INT_STATUS_RX_TMOUT	BIT(2)
+#define   PCCR2_INT_STATUS_RX_AVAIL	BIT(1)
+#define PCCR3	0x13c
+#define   PCCR3_FIFO_DATA_MASK		GENMASK(7, 0)
+
+#define PCC_DMA_BUFSZ	(256 * SZ_1K)
+
+enum pcc_fifo_threshold {
+	PCC_FIFO_THR_1_BYTE,
+	PCC_FIFO_THR_1_EIGHTH,
+	PCC_FIFO_THR_2_EIGHTH,
+	PCC_FIFO_THR_3_EIGHTH,
+	PCC_FIFO_THR_4_EIGHTH,
+	PCC_FIFO_THR_5_EIGHTH,
+	PCC_FIFO_THR_6_EIGHTH,
+	PCC_FIFO_THR_7_EIGHTH,
+	PCC_FIFO_THR_8_EIGHTH,
+};
+
+enum pcc_record_mode {
+	PCC_REC_1B,
+	PCC_REC_2B,
+	PCC_REC_4B,
+	PCC_REC_FULL,
+};
+
+enum pcc_port_hbits_select {
+	PCC_PORT_HBITS_SEL_NONE,
+	PCC_PORT_HBITS_SEL_45,
+	PCC_PORT_HBITS_SEL_67,
+	PCC_PORT_HBITS_SEL_89,
+};
+
+struct aspeed_pcc_dma {
+	uint32_t rptr;
+	uint8_t *virt;
+	dma_addr_t addr;
+	uint32_t size;
+};
+
+struct aspeed_pcc_ctrl {
+	struct device *dev;
+	struct regmap *regmap;
+	int irq;
+	uint32_t port;
+	struct aspeed_pcc_dma dma;
+	struct kfifo fifo;
+	wait_queue_head_t wq;
+	struct miscdevice mdev;
+	int mdev_id;
+};
+
+static inline bool is_valid_rec_mode(uint32_t mode)
+{
+	return (mode > PCC_REC_FULL) ? false : true;
+}
+
+static inline bool is_valid_high_bits_select(uint32_t sel)
+{
+	return (sel > PCC_PORT_HBITS_SEL_89) ? false : true;
+}
+
+static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	int rc;
+	unsigned int copied;
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	if (kfifo_is_empty(&pcc->fifo)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		rc = wait_event_interruptible(pcc->wq,
+					      !kfifo_is_empty(&pcc->fifo));
+		if (rc == -ERESTARTSYS)
+			return -EINTR;
+	}
+
+	rc = kfifo_to_user(&pcc->fifo, buffer, count, &copied);
+
+	return rc ? rc : copied;
+}
+
+static __poll_t aspeed_pcc_file_poll(struct file *file,
+				     struct poll_table_struct *pt)
+{
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	poll_wait(file, &pcc->wq, pt);
+
+	return !kfifo_is_empty(&pcc->fifo) ? POLLIN : 0;
+}
+
+static const struct file_operations pcc_fops = {
+	.owner = THIS_MODULE,
+	.read = aspeed_pcc_file_read,
+	.poll = aspeed_pcc_file_poll,
+};
+
+static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg)
+{
+	uint32_t reg, rptr, wptr;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+	struct kfifo *fifo = &pcc->fifo;
+
+	regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_INT_STATUS_DMA_DONE);
+
+	regmap_read(pcc->regmap, PCCR6, &reg);
+	wptr = (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR);
+	rptr = pcc->dma.rptr;
+
+	do {
+		if (kfifo_is_full(fifo))
+			kfifo_skip(fifo);
+
+		kfifo_put(fifo, pcc->dma.virt[rptr]);
+
+		rptr = (rptr + 1) % pcc->dma.size;
+	} while (rptr != wptr);
+
+	pcc->dma.rptr = rptr;
+
+	wake_up_interruptible(&pcc->wq);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t aspeed_pcc_isr(int irq, void *arg)
+{
+	uint32_t sts;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+
+	regmap_read(pcc->regmap, PCCR2, &sts);
+
+	if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT |
+		     PCCR2_INT_STATUS_RX_AVAIL |
+		     PCCR2_INT_STATUS_DMA_DONE)))
+		return IRQ_NONE;
+
+	return aspeed_pcc_dma_isr(irq, arg);
+}
+
+/*
+ * A2600-15 AP note
+ *
+ * SW workaround to prevent generating Non-Fatal-Error (NFE)
+ * eSPI response when PCC is used for port I/O byte snooping
+ * over eSPI.
+ */
+static int aspeed_a2600_15(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	u32 hicr5_en, hicrb_en;
+
+	/* abort if snoop is enabled */
+	regmap_read(pcc->regmap, HICR5, &hicr5_en);
+	if (hicr5_en & (HICR5_EN_SNP0W | HICR5_EN_SNP1W)) {
+		dev_err(dev, "A2600-15 should be applied with snoop disabled\n");
+		return -EPERM;
+	}
+
+	/* set SNPWADR of snoop device */
+	regmap_write(pcc->regmap, SNPWADR, pcc->port | ((pcc->port + 2) << 16));
+
+	/* set HICRB[15:14]=11b to enable ACCEPT response for SNPWADR */
+	hicrb_en = HICRB_ENSNP0D | HICRB_ENSNP1D;
+	regmap_update_bits(pcc->regmap, HICRB, hicrb_en, hicrb_en);
+
+	/* set HICR6[19] to extend SNPWADR to 2x range */
+	regmap_update_bits(pcc->regmap, HICR6, HICR6_EN2BMODE, HICR6_EN2BMODE);
+
+	return 0;
+}
+
+static int aspeed_pcc_enable(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	int rc;
+
+	rc = aspeed_a2600_15(pcc, dev);
+	if (rc)
+		return rc;
+
+	/* record mode: Set 2-Byte mode. */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_MODE_SEL_MASK,
+			   PCC_REC_2B << PCCR0_MODE_SEL_SHIFT);
+
+	/* port address */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_BASE_ADDR_MASK,
+			   pcc->port << PCCR1_BASE_ADDR_SHIFT);
+
+	/* Set address high bits selection to 0b01 for address bit[5:4] */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_ADDR_SEL_MASK,
+			   PCC_PORT_HBITS_SEL_45 << PCCR0_ADDR_SEL_SHIFT);
+
+	/* Set LPC don't care address to 0x3 for port 80~83h */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_DONT_CARE_BITS_MASK,
+			   0x3 << PCCR1_DONT_CARE_BITS_SHIFT);
+
+	/* set DMA ring buffer size and enable interrupts */
+	regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff);
+#ifdef CONFIG_ARM64
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK,
+			   (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT);
+#endif
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK,
+			   (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT);
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE);
+
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN, PCCR0_EN);
+
+	return 0;
+}
+
+static int aspeed_pcc_disable(struct aspeed_pcc_ctrl *pcc)
+{
+	/* Disable PCC and DMA Mode for safety */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN |  PCCR0_EN_DMA_MODE, 0);
+
+	/* Clear Rx FIFO. */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1);
+
+	/* Clear All interrupts status. */
+	regmap_write(pcc->regmap, PCCR2,
+		     PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE |
+		     PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B);
+
+	return 0;
+}
+
+static int aspeed_pcc_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct aspeed_pcc_ctrl *pcc;
+	struct device *dev;
+	uint32_t fifo_size = PAGE_SIZE;
+
+	dev = &pdev->dev;
+
+	pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL);
+	if (!pcc)
+		return -ENOMEM;
+
+	pcc->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
+	if (IS_ERR(pcc->regmap)) {
+		dev_err(dev, "Couldn't get regmap\n");
+		return -ENODEV;
+	}
+
+	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
+	if (rc) {
+		dev_err(dev, "no pcc ports configured\n");
+		return -ENODEV;
+	}
+
+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+	if (rc) {
+		dev_err(dev, "cannot set 64-bits DMA mask\n");
+		return rc;
+	}
+
+	pcc->dma.size = PCC_DMA_BUFSZ;
+	pcc->dma.virt = dmam_alloc_coherent(dev,
+					    pcc->dma.size,
+					    &pcc->dma.addr,
+					    GFP_KERNEL);
+	if (!pcc->dma.virt) {
+		dev_err(dev, "cannot allocate DMA buffer\n");
+		return -ENOMEM;
+	}
+
+	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
+	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
+	if (rc) {
+		dev_err(dev, "cannot allocate kFIFO\n");
+		return -ENOMEM;
+	}
+
+	/* Disable PCC to clean up DMA buffer before request IRQ. */
+	rc = aspeed_pcc_disable(pcc);
+	if (rc) {
+		dev_err(dev, "Couldn't disable PCC\n");
+		goto err_free_kfifo;
+	}
+
+	pcc->irq = platform_get_irq(pdev, 0);
+	if (pcc->irq < 0) {
+		dev_err(dev, "Couldn't get IRQ\n");
+		rc = -ENODEV;
+		goto err_free_kfifo;
+	}
+
+	rc = devm_request_irq(dev, pcc->irq, aspeed_pcc_isr, 0, DEVICE_NAME, pcc);
+	if (rc < 0) {
+		dev_err(dev, "Couldn't request IRQ %d\n", pcc->irq);
+		goto err_free_kfifo;
+	}
+
+	init_waitqueue_head(&pcc->wq);
+
+	pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL);
+	if (pcc->mdev_id < 0) {
+		dev_err(dev, "Couldn't allocate ID\n");
+		return pcc->mdev_id;
+	}
+
+	pcc->mdev.parent = dev;
+	pcc->mdev.minor = MISC_DYNAMIC_MINOR;
+	pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME,
+					pcc->mdev_id);
+	pcc->mdev.fops = &pcc_fops;
+	rc = misc_register(&pcc->mdev);
+	if (rc) {
+		dev_err(dev, "Couldn't register misc device\n");
+		goto err_free_kfifo;
+	}
+
+	rc = aspeed_pcc_enable(pcc, dev);
+	if (rc) {
+		dev_err(dev, "Couldn't enable PCC\n");
+		goto err_dereg_mdev;
+	}
+
+	dev_set_drvdata(&pdev->dev, pcc);
+
+	return 0;
+
+err_dereg_mdev:
+	misc_deregister(&pcc->mdev);
+
+err_free_kfifo:
+	kfifo_free(&pcc->fifo);
+
+	return rc;
+}
+
+static void aspeed_pcc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev);
+
+	kfifo_free(&pcc->fifo);
+	misc_deregister(&pcc->mdev);
+}
+
+static const struct of_device_id aspeed_pcc_table[] = {
+	{ .compatible = "aspeed,ast2600-lpc-pcc" },
+	{ },
+};
+
+static struct platform_driver aspeed_pcc_driver = {
+	.driver = {
+		.name = "aspeed-pcc",
+		.of_match_table = aspeed_pcc_table,
+	},
+	.probe = aspeed_pcc_probe,
+	.remove = aspeed_pcc_remove,
+};
+
+module_platform_driver(aspeed_pcc_driver);
+
+MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang at aspeedtech.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Aspeed Post Code Capture");
-- 
2.34.1



From brgl at bgdev.pl  Tue Mar  4 02:44:57 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:44:57 +0100
Subject: [PATCH 4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
In-Reply-To: <20250303-samsung-codecs-v1-4-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-4-56a2299dd928@linaro.org>
Message-ID: <CAMRc=Mc3GkM1aoDnNgGLBH7rzOxyCZcu23MspdCC0gMm9f=_=w@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> The Speyside ASoC uses a single GPIO from the WM8996
> that we can provide from the local offset on that chip
> rather than from the global GPIO numberspace as is being
> done currently.
>
> The offset 2 was done by calculating the base offset
> for the CODEC (i.e. wm8996) GPIOs to 212, by reading
> arch/arm/mach-s3c/gpio-samsung-s3c64xx.h and
> arch/arm/mach-s3c/crag6410.h and adding up all the
> offsets that were occasionally adding a +1 blank GPIO
> between each GPIO provider.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/speyside.c | 37 ++++++++++++++++++++++++++++++-------
>  1 file changed, 30 insertions(+), 7 deletions(-)
>
> diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
> index 79476e8eb680984434a1198ff691ddd4b9fe07c1..947b85ff83f036a0814fd477f5f6f69253a2a2d8 100644
> --- a/sound/soc/samsung/speyside.c
> +++ b/sound/soc/samsung/speyside.c
> @@ -7,13 +7,13 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/jack.h>
> -#include <linux/gpio.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/gpio/consumer.h>
>  #include <linux/module.h>
>
>  #include "../codecs/wm8996.h"
>  #include "../codecs/wm9081.h"
>
> -#define WM8996_HPSEL_GPIO 214
>  #define MCLK_AUDIO_RATE (512 * 48000)
>
>  static int speyside_set_bias_level(struct snd_soc_card *card,
> @@ -105,6 +105,7 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = {
>         },
>  };
>
> +static struct gpio_desc *speyside_hpsel_gpio;
>  /* Default the headphone selection to active high */
>  static int speyside_jack_polarity;
>
> @@ -123,7 +124,7 @@ static void speyside_set_polarity(struct snd_soc_component *component,
>                                   int polarity)
>  {
>         speyside_jack_polarity = !polarity;
> -       gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
> +       gpiod_direction_output(speyside_hpsel_gpio, speyside_jack_polarity);
>
>         /* Re-run DAPM to make sure we're using the correct mic bias */
>         snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
> @@ -145,16 +146,22 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
>  {
>         struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
>         struct snd_soc_component *component = dai->component;
> +       enum gpiod_flags flags;
>         int ret;
>
>         ret = snd_soc_dai_set_sysclk(dai, WM8996_SYSCLK_MCLK2, 32768, 0);
>         if (ret < 0)
>                 return ret;
>
> -       ret = gpio_request(WM8996_HPSEL_GPIO, "HP_SEL");
> -       if (ret != 0)
> -               pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
> -       gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
> +       if (speyside_jack_polarity)
> +               flags = GPIOD_OUT_HIGH;
> +       else
> +               flags = GPIOD_OUT_LOW;
> +       speyside_hpsel_gpio = devm_gpiod_get(rtd->card->dev,
> +                                            "hp-sel",
> +                                            flags);
> +       if (IS_ERR(speyside_hpsel_gpio))
> +               return PTR_ERR(speyside_hpsel_gpio);
>
>         ret = snd_soc_card_jack_new_pins(rtd->card, "Headset",
>                                          SND_JACK_LINEOUT | SND_JACK_HEADSET |
> @@ -325,6 +332,21 @@ static struct snd_soc_card speyside = {
>         .late_probe = speyside_late_probe,
>  };
>
> +static struct gpiod_lookup_table wm8996_gpiod_table = {
> +       /* Hardcoded device name in board file mach-crag6410.c */
> +       .dev_id = "speyside",
> +       .table = {
> +               /*
> +                * This line was hardcoded to 214 in the global GPIO
> +                * number space, S3C GPIO macros seems top set the
> +                * wm8996 codec GPIO start offset to 212, so this will
> +                * be GPIO 214 - 212 = 2 on the wm8996.
> +                */
> +               GPIO_LOOKUP("wm8996", 2, "hp-sel", GPIO_ACTIVE_HIGH),
> +               { },
> +       },
> +};
> +
>  static int speyside_probe(struct platform_device *pdev)
>  {
>         struct snd_soc_card *card = &speyside;
> @@ -332,6 +354,7 @@ static int speyside_probe(struct platform_device *pdev)
>
>         card->dev = &pdev->dev;
>
> +       gpiod_add_lookup_table(&wm8996_gpiod_table);

This looks good but you never remove the lookup table. We should
typically undo everything on driver detach, that we did in probe().
I'd suggest either scheduling a devm action to remove the lookup table
or adding it statically in module's init.

Bart

>         ret = devm_snd_soc_register_card(&pdev->dev, card);
>         if (ret)
>                 dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n");
>
> --
> 2.48.1
>


From brgl at bgdev.pl  Tue Mar  4 02:45:14 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:45:14 +0100
Subject: [PATCH 5/6] ASoC: samsung: tobermory: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-5-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-5-56a2299dd928@linaro.org>
Message-ID: <CAMRc=MeWNT9k6o55UjsLypuNzpwDKRmNs7Mh6TgTchxq-9+QPg@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> This file does not use the symbols from the legacy
> <linux/gpio.h> header, so let's drop it.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/tobermory.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
> index 2bdd81bf821a5b9bdc56479bb2cd5d0089fab339..bc2608dbaddc4feeb9af77639699fed89540b44b 100644
> --- a/sound/soc/samsung/tobermory.c
> +++ b/sound/soc/samsung/tobermory.c
> @@ -7,7 +7,6 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/jack.h>
> -#include <linux/gpio.h>
>  #include <linux/module.h>
>
>  #include "../codecs/wm8962.h"
>
> --
> 2.48.1
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From brgl at bgdev.pl  Tue Mar  4 02:45:28 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 11:45:28 +0100
Subject: [PATCH 6/6] ASoC: samsung: tm2_wm5110: Drop unused include
In-Reply-To: <20250303-samsung-codecs-v1-6-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <20250303-samsung-codecs-v1-6-56a2299dd928@linaro.org>
Message-ID: <CAMRc=Mfr0Bwy_OWRheY8U5c2-0nB+_JxZHLNjbHFzvCEQb3OrA@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:41?AM Linus Walleij <linus.walleij at linaro.org> wrote:
>
> This file does not use the symbols from the legacy
> <linux/gpio.h> header, so let's drop it.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  sound/soc/samsung/tm2_wm5110.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
> index 2417b91a328f083f991af8505c5586d3b27d9bbd..cc76963105d9fa37fe0bc45acf9a28720fdde158 100644
> --- a/sound/soc/samsung/tm2_wm5110.c
> +++ b/sound/soc/samsung/tm2_wm5110.c
> @@ -6,7 +6,6 @@
>  //          Sylwester Nawrocki <s.nawrocki at samsung.com>
>
>  #include <linux/clk.h>
> -#include <linux/gpio.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>
> --
> 2.48.1
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From peterz at infradead.org  Tue Mar  4 02:46:48 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 4 Mar 2025 11:46:48 +0100
Subject: [PATCH bpf-next v2 00/26] Resilient Queued Spin Lock
In-Reply-To: <CAADnVQJJbi-52mP6BivyAudWSk95f1mgGQXWnjD-H37b7_AtLw@mail.gmail.com>
References: <20250206105435.2159977-1-memxor@gmail.com>
 <20250210093840.GE10324@noisy.programming.kicks-ass.net>
 <20250210104931.GE31462@noisy.programming.kicks-ass.net>
 <CAADnVQ+3wu0WB2pXs4cccxfkbTb3TK8Z+act5egytiON+qN9tA@mail.gmail.com>
 <20250211104352.GC29593@noisy.programming.kicks-ass.net>
 <CAADnVQJ=81PE19JWeNjq6aNOy+GM-wo6n7WU9StX1b6kevqCUw@mail.gmail.com>
 <20250213095918.GB28068@noisy.programming.kicks-ass.net>
 <CAADnVQJJbi-52mP6BivyAudWSk95f1mgGQXWnjD-H37b7_AtLw@mail.gmail.com>
Message-ID: <20250304104648.GD11590@noisy.programming.kicks-ass.net>


new posting reminded me we had this thread...

On Thu, Feb 13, 2025 at 06:37:05PM -0800, Alexei Starovoitov wrote:

> > > When bpf prog does bpf_rcu_read_lock() the verifier makes sure
> > > that all execution paths from there on have bpf_rcu_read_unlock()
> > > before program reaches the exit.
> > > Same thing with locks.
> >
> > Ah, okay, this wasn't stated anywhere. This is rather crucial
> > information.
> 
> This is kinda verifier 101. I don't think it needs to be in the log.

Right, but I didn't take that class. I'm BPF n00b. Meanwhile you're
asking me to review this :-/

> > OK; how is the user supposed to handle locking two hash buckets? Does
> > the BPF prog create some global lock to serialize the multi bucket case?
> 
> Not following.
> Are you talking about patch 19 where we convert per-bucket
> raw_spinlock_t in bpf hashmap to rqspinlock_t ?

I'm not sure -- see the BPF n00b thing, I don't know how this is
supposed to be used.

Like really; I have absolutely 0 clues.

Anyway; the situation I was thinking of was something along the lines
of: you need data from 2 buckets, so you need to lock 2 buckets, but
since hash-table, there is no sane order, so you need a 3rd lock to
impose order.

But also, see below, you've illustrated this exact case with q1,q2.

> Only one bucket lock is held at a time by map update code,
> but due to reentrance and crazy kprobes in the wrong places
> two bucket locks of a single map can be held on the same cpu.
> 
> bpf_prog_A -> bpf_map_update -> res_spin_lock(bucket_A)
>   -> kprobe or tracepoint
>     -> bpf_prob_B -> bpf_map_update -> res_spin_lock(bucket_B)
> 
> and that's why we currently have:
> if (__this_cpu_inc_return(*(htab->map_locked[hash])) ...
>     return -EBUSY;
> 
> .. workaround to prevent the most obvious AA deadlock,
> but it's not enough.
> People were able to hit ABBA.

Right, you can create arbitrary lock chain with this; chain length is
limited by nesting-depth*nr-cpus or somesuch.

> > Anyway, I wonder. Since the verifier tracks all this, it can determine
> > lock order for the prog. Can't it do what lockdep does and maintain lock
> > order graph of all loaded BPF programs?
> >
> > This is load-time overhead, rather than runtime.
> 
> I wish it was possible. Locks are dynamic. They protect
> dynamically allocated objects, so the order cannot be statically
> verified. We pushed the limit of static analysis a lot.
> Maybe too much.
> For example,
> the verifier can statically validate the following code:
>         struct node_data *n, *m, *o;
>         struct bpf_rb_node *res, *res2;
> 
>         // here we allocate an object of type known to the verifier
>         n = bpf_obj_new(typeof(*n));
>         if (!n)
>                 return 1;
>         n->key = 41;
>         n->data = 42;
> 
>         // here the verifier knows that glock spin_lock
>         // protect rbtree groot
>         bpf_spin_lock(&glock);
> 
>         // here it checks that the lock is held and type of
>         // objects in rbtree matches the type of 'n'
>         bpf_rbtree_add(&groot, &n->node, less);
>         bpf_spin_unlock(&glock);
> 
> and all kinds of other more complex stuff,
> but it is not enough to cover necessary algorithms.
> 
> Here is an example from real code that shows
> why we cannot verify two held locks:
> 
> struct bpf_vqueue {
>         struct bpf_spin_lock lock;
>         int credit;
>         unsigned long long lasttime;
>         unsigned int rate;
> };
> 
> struct {
>         __uint(type, BPF_MAP_TYPE_HASH);
>         __uint(max_entries, ...);
>         __type(key, int);
>         __type(value, struct bpf_vqueue);
> } vqueue SEC(".maps");
> 
>         q = bpf_map_lookup_elem(&vqueue, &key);
>         if (!q)
>                 goto err;
>         curtime = bpf_ktime_get_ns();
>         bpf_spin_lock(&q->lock);
>         q->lasttime = curtime;
>         q->credit -= ...;
>         credit = q->credit;
>         bpf_spin_unlock(&q->lock);
> 
> the above is safe, but if there are two lookups:
> 
> q1 = bpf_map_lookup_elem(&vqueue, &key1);
> q2 = bpf_map_lookup_elem(&vqueue, &key2);
> 
> both will point to two different locks,
> and since the key is dynamic there is no way to know
> the order of q1->lock vs q2->lock.

I still feel like I'm missing things, but while they are two dynamic
locks, they are both locks of vqueue object. What lockdep does is
classify locks by initialization site (by default). Same can be done
here, classify per dynamic object.

So verifier can know the above is invalid. Both locks are same class, so
treat as A-A order (trivial case is where q1 and q2 are in fact the same
object since the keys hash the same).

Now, going back to 3rd lock, if instead you write it like:

  bpf_spin_lock(&glock);
  q1 = bpf_map_lookup_elem(&vqueue, &key1);
  q2 = bpf_map_lookup_elem(&vqueue, &key2);
  ...
  bpf_spin_unlock(&glock);

then (assuming q1 != q2) things are fine, since glock will serialize
everybody taking two vqueue locks.

And the above program snippet seems to imply maps are global state, so
you can keep lock graph of maps, such that:

  bpf_map_lookup_elem(&map-A, &key-A);
  bpf_map_lookup_elem(&map-B, &key-B);

vs

  bpf_map_lookup_elem(&map-B, &key-B);
  bpf_map_lookup_elem(&map-A, &key-A);

trips AB-BA

> So we allow only one lock at a time with
> bare minimal operations while holding the lock,
> but it's not enough to do any meaningful work.

Yes, I can see that being a problem.

> The top feature request is to allow calls
> while holding locks (currently they're disallowed,
> like above bpf_ktime_get_ns() cannot be done
> while holding the lock)

So bpf_ktime_get_ns() is a trivial example; it it always safe to call,
you can simply whitelist it.

> and allow grabbing more than one lock.
> That's what res_spin_lock() is achieving.

I am not at all sure how res_spin_lock is helping with the q1,q2 thing.
That will trivially result in lock cycles.

And you said any program that would trigger deadlock is invalid.
Therefore the q1,q2 example from above is still invalid and
res_spin_lock has not helped.

> Having said all that I think the discussion is diverging into
> all-thing-bpf instead of focusing on res_spin_lock.

I disagree, all of this is needed to understand res_spin_lock.

>From the above, I'm not yet convinced you cannot extend the verifier
with something lockdep like.

> Just to make it clear... there is a patch 18:
> 
>  F: kernel/bpf/
>  F: kernel/trace/bpf_trace.c
>  F: lib/buildid.c
> +F: arch/*/include/asm/rqspinlock.h
> +F: include/asm-generic/rqspinlock.h
> +F: kernel/locking/rqspinlock.c
>  F: lib/test_bpf.c
>  F: net/bpf/
> 
> that adds maintainer entries to BPF scope.
> 
> We're not asking locking experts to maintain this new res_spin_lock.
> It's not a generic kernel infra.
> It will only be used by bpf infra and by bpf progs.
> We will maintain it and we will fix whatever bugs
> we introduce.

While that is appreciated, the whole kernel is subject to the worst case
behaviour of this thing. As such, I feel I need to care.



From linux.amoon at gmail.com  Tue Mar  4 04:20:01 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Tue, 4 Mar 2025 17:50:01 +0530
Subject: [PATCH v3 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <CANAwSgTpV_kGFEU-ND0N+OEtT6+j4ceq37xAoLyC7iHPWAuLjg@mail.gmail.com>
References: <20250216195850.5352-1-linux.amoon@gmail.com> <20250216195850.5352-5-linux.amoon@gmail.com>
 <f44efd1a-1f6e-456d-9395-de2a55ef2279@arm.com> <CANAwSgTpV_kGFEU-ND0N+OEtT6+j4ceq37xAoLyC7iHPWAuLjg@mail.gmail.com>
Message-ID: <CANAwSgSWf_YxSi-pzWPaRoiJx7RLrWUz+HTWx5hf+E2x1ZGmoQ@mail.gmail.com>

Hi Lukasz,

On Sat, 1 Mar 2025 at 00:06, Anand Moon <linux.amoon at gmail.com> wrote:
>
> Hi Lukasz,
>
> On Fri, 28 Feb 2025 at 22:58, Lukasz Luba <lukasz.luba at arm.com> wrote:
> >
> >
> >
> > On 2/16/25 19:58, Anand Moon wrote:
> > > Using guard notation makes the code more compact and error handling
> > > more robust by ensuring that mutexes are released in all code paths
> > > when control leaves critical section.
> > >
> > > Signed-off-by: Anand Moon <linux.amoon at gmail.com>
> > > ---
> > > v3: new patch
> > > ---
> > >   drivers/thermal/samsung/exynos_tmu.c | 21 +++++++--------------
> > >   1 file changed, 7 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> > > index fe090c1a93ab..a34ba3858d64 100644
> > > --- a/drivers/thermal/samsung/exynos_tmu.c
> > > +++ b/drivers/thermal/samsung/exynos_tmu.c
> > > @@ -256,7 +256,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> > >       unsigned int status;
> > >       int ret = 0;
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >       clk_enable(data->clk_sec);
> > >
> > > @@ -270,7 +270,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> > >
> > >       clk_disable(data->clk_sec);
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >
> > >       return ret;
> > >   }
> > > @@ -292,13 +291,12 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
> > >               return ret;
> > >       }
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >
> > >       data->tmu_set_crit_temp(data, temp / MCELSIUS);
> > >
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >
> > >       return 0;
> > >   }
> > > @@ -325,12 +323,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
> > >   {
> > >       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >       data->tmu_control(pdev, on);
> > >       data->enabled = on;
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >   }
> > >
> > >   static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
> > > @@ -645,7 +642,7 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
> > >                */
> > >               return -EAGAIN;
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >
> > >       value = data->tmu_read(data);
> > > @@ -655,7 +652,6 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
> > >               *temp = code_to_temp(data, value) * MCELSIUS;
> > >
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >
> > >       return ret;
> > >   }
> > > @@ -720,11 +716,10 @@ static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
> > >       if (temp && temp < MCELSIUS)
> > >               goto out;
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >       data->tmu_set_emulation(data, temp);
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >       return 0;
> > >   out:
> > >       return ret;
> > > @@ -760,14 +755,13 @@ static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id)
> > >
> > >       thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >
> > >       /* TODO: take action based on particular interrupt */
> > >       data->tmu_clear_irqs(data);
> > >
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >
> > >       return IRQ_HANDLED;
> > >   }
> > > @@ -987,7 +981,7 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
> > >   {
> > >       struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
> > >
> > > -     mutex_lock(&data->lock);
> > > +     guard(mutex)(&data->lock);
> > >       clk_enable(data->clk);
> > >
> > >       if (low > INT_MIN)
> > > @@ -1000,7 +994,6 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
> > >               data->tmu_disable_high(data);
> > >
> > >       clk_disable(data->clk);
> > > -     mutex_unlock(&data->lock);
> > >
> > >       return 0;
> > >   }
>
> Thanks for your review comments.
> >
> > IMO you should be able to even use something like we have
> > core framework:
> >
> > guard(thermal_zone)(tz);
> >
> > Your mutex name is simply 'lock' in the struct exynos_tmu_data
> > so you should be able to leverage this by:
> >
> > guard(exynos_tmu_data)(data);
> >

If I introduce the guard it creates a compilation error

amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ vi
drivers/thermal/samsung/exynos_tmu.c +306
amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ make -j$(nproc)
ARCH=arm CROSS_COMPILE=arm-none-eabi- LOCALVERSION=-u3ml dtbs zImage
modules
  CALL    scripts/checksyscalls.sh
  CHK     kernel/kheaders_data.tar.xz
  CC      drivers/thermal/samsung/exynos_tmu.o
  CC [M]  drivers/md/raid10.o
In file included from ./include/linux/irqflags.h:17,
                 from ./arch/arm/include/asm/bitops.h:28,
                 from ./include/linux/bitops.h:68,
                 from ./include/linux/kernel.h:23,
                 from ./include/linux/clk.h:13,
                 from drivers/thermal/samsung/exynos_tmu.c:14:
drivers/thermal/samsung/exynos_tmu.c: In function 'exynos_tmu_update_bit':
./include/linux/cleanup.h:258:9: error: unknown type name
'class_exynos_tmu_data_t'
  258 |         class_##_name##_t var
__cleanup(class_##_name##_destructor) =   \
      |         ^~~~~~
./include/linux/cleanup.h:309:9: note: in expansion of macro 'CLASS'
  309 |         CLASS(_name, __UNIQUE_ID(guard))
      |         ^~~~~
drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
  338 |         guard(exynos_tmu_data)(data);
      |         ^~~~~
drivers/thermal/samsung/exynos_tmu.c:338:9: error: cleanup argument
not a function
  CC [M]  drivers/md/raid5.o
./include/linux/cleanup.h:259:17: error: implicit declaration of
function 'class_exynos_tmu_data_constructor'
[-Wimplicit-function-declaration]
  259 |                 class_##_name##_constructor
      |                 ^~~~~~
./include/linux/cleanup.h:309:9: note: in expansion of macro 'CLASS'
  309 |         CLASS(_name, __UNIQUE_ID(guard))
      |         ^~~~~
drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
  338 |         guard(exynos_tmu_data)(data);
      |         ^~~~~
./include/linux/compiler.h:166:45: warning: unused variable
'__UNIQUE_ID_guard572' [-Wunused-variable]
  166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_,
prefix), __COUNTER__)
      |                                             ^~~~~~~~~~~~
./include/linux/cleanup.h:258:27: note: in definition of macro 'CLASS'
  258 |         class_##_name##_t var
__cleanup(class_##_name##_destructor) =   \
      |                           ^~~
././include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE'
   84 | #define __PASTE(a,b) ___PASTE(a,b)
      |                      ^~~~~~~~
./include/linux/compiler.h:166:29: note: in expansion of macro '__PASTE'
  166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_,
prefix), __COUNTER__)
      |                             ^~~~~~~
././include/linux/compiler_types.h:84:22: note: in expansion of macro '___PASTE'
   84 | #define __PASTE(a,b) ___PASTE(a,b)
      |                      ^~~~~~~~
./include/linux/compiler.h:166:37: note: in expansion of macro '__PASTE'
  166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_,
prefix), __COUNTER__)
      |                                     ^~~~~~~
./include/linux/cleanup.h:309:22: note: in expansion of macro '__UNIQUE_ID'
  309 |         CLASS(_name, __UNIQUE_ID(guard))
      |                      ^~~~~~~~~~~
drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
  338 |         guard(exynos_tmu_data)(data);

Thanks
-Anand


From cristian.ciocaltea at collabora.com  Tue Mar  4 04:20:20 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 4 Mar 2025 14:20:20 +0200
Subject: [PATCH v4 08/12] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250304-romantic-truthful-sambar-deaab1@houat>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-8-8657847c13f7@collabora.com>
 <20250304-romantic-truthful-sambar-deaab1@houat>
Message-ID: <bee17643-e0b4-467b-a632-06f91ac7fc3a@collabora.com>

On 3/4/25 10:18 AM, Maxime Ripard wrote:
> On Tue, Mar 04, 2025 at 03:44:07AM +0200, Cristian Ciocaltea wrote:
>> Implement the phy_ops.validate() callback to allow checking the PHY
>> configuration parameters without actually applying them.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 +++++++++++++++++++++++
>>  1 file changed, 23 insertions(+)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 7e1d1c10758249aa5bbddbdaae0108bba04f30df..47db1395051f5d900197871694bab90ca4d6e38e 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -1482,6 +1482,17 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>>  	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>>  		return -EINVAL;
>>  
>> +	u32 bit_rate = hdmi->tmds_char_rate / 100;
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
>> +		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
>> +			break;
>> +
>> +	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
>> +	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
>> +		return -EINVAL;
> 
> What are you calling bit_rate here? If anything, I'd expect the bit_rate
> to be a multiple of the char rate, not a divisor.

This is just an unfortunate naming of the search key in struct
ropll_config, inherited from downstream, given in hHz rather than Hz.
I've already renamed it in the last patch, while getting rid of those
annoying unit conversions.


From cristian.ciocaltea at collabora.com  Tue Mar  4 04:28:36 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 4 Mar 2025 14:28:36 +0200
Subject: [PATCH v4 10/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250304-delicate-crazy-tuatara-5ea4d3@houat>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-10-8657847c13f7@collabora.com>
 <20250304-delicate-crazy-tuatara-5ea4d3@houat>
Message-ID: <71817739-7ecd-478d-ae57-d764e21c8dd9@collabora.com>



On 3/4/25 10:21 AM, Maxime Ripard wrote:
> On Tue, Mar 04, 2025 at 03:44:09AM +0200, Cristian Ciocaltea wrote:
>> @@ -1480,12 +1484,12 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
>>  static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>>  					   struct phy_configure_opts_hdmi *hdmi)
>>  {
>> -	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>> -		return -EINVAL;
>> -
>>  	u32 bit_rate = hdmi->tmds_char_rate / 100;
>>  	int i;
>>  
>> +	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>> +		return -EINVAL;
>> +
>>  	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
>>  		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
>>  			break;
> 
> Why is that change needed?

Oh, that was supposed to be a fixup for "phy: rockchip: samsung-hdptx:
Provide config params validation support" to keep variable declaration
section on top.  Not sure how I missed it, probably I chose the wrong
commit hash while focusing on some other changes during the rebase.

Will sort this out in v5.

Thanks for spotting it,
Cristian


From suzuki.poulose at arm.com  Tue Mar  4 04:28:23 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 4 Mar 2025 12:28:23 +0000
Subject: [PATCH v15 10/10] arm64: dts: qcom: sa8775p: Add CTCU and ETR
 nodes
In-Reply-To: <20250303032931.2500935-11-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-11-quic_jiegan@quicinc.com>
Message-ID: <0be31ecd-4386-4eb6-ad6f-a4409a3fc6ad@arm.com>

On 03/03/2025 03:29, Jie Gan wrote:
> Add CTCU and ETR nodes in DT to enable related functionalities.
> 
> Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>

Assuming this goes via the soc tree,

Acked-by: Suzuki K Poulose <suzuki.poulose at arm.com>


> ---
>   arch/arm64/boot/dts/qcom/sa8775p.dtsi | 153 ++++++++++++++++++++++++++
>   1 file changed, 153 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> index 3394ae2d1300..31aa94d2a043 100644
> --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> @@ -2429,6 +2429,35 @@ crypto: crypto at 1dfa000 {
>   			interconnect-names = "memory";
>   		};
>   
> +		ctcu at 4001000 {
> +			compatible = "qcom,sa8775p-ctcu";
> +			reg = <0x0 0x04001000 0x0 0x1000>;
> +
> +			clocks = <&aoss_qmp>;
> +			clock-names = "apb";
> +
> +			in-ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				port at 0 {
> +					reg = <0>;
> +
> +					ctcu_in0: endpoint {
> +						remote-endpoint = <&etr0_out>;
> +					};
> +				};
> +
> +				port at 1 {
> +					reg = <1>;
> +
> +					ctcu_in1: endpoint {
> +						remote-endpoint = <&etr1_out>;
> +					};
> +				};
> +			};
> +		};
> +
>   		stm: stm at 4002000 {
>   			compatible = "arm,coresight-stm", "arm,primecell";
>   			reg = <0x0 0x4002000 0x0 0x1000>,
> @@ -2633,6 +2662,122 @@ qdss_funnel_in1: endpoint {
>   			};
>   		};
>   
> +		replicator at 4046000 {
> +			compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
> +			reg = <0x0 0x04046000 0x0 0x1000>;
> +
> +			clocks = <&aoss_qmp>;
> +			clock-names = "apb_pclk";
> +
> +			in-ports {
> +				port {
> +					qdss_rep_in: endpoint {
> +						remote-endpoint = <&swao_rep_out0>;
> +					};
> +				};
> +			};
> +
> +			out-ports {
> +				port {
> +					qdss_rep_out0: endpoint {
> +						remote-endpoint = <&etr_rep_in>;
> +					};
> +				};
> +			};
> +		};
> +
> +		tmc_etr: tmc at 4048000 {
> +			compatible = "arm,coresight-tmc", "arm,primecell";
> +			reg = <0x0 0x04048000 0x0 0x1000>;
> +
> +			clocks = <&aoss_qmp>;
> +			clock-names = "apb_pclk";
> +			iommus = <&apps_smmu 0x04c0 0x00>;
> +
> +			arm,scatter-gather;
> +
> +			in-ports {
> +				port {
> +					etr0_in: endpoint {
> +						remote-endpoint = <&etr_rep_out0>;
> +					};
> +				};
> +			};
> +
> +			out-ports {
> +				port {
> +					etr0_out: endpoint {
> +						remote-endpoint = <&ctcu_in0>;
> +					};
> +				};
> +			};
> +		};
> +
> +		replicator at 404e000 {
> +			compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
> +			reg = <0x0 0x0404e000 0x0 0x1000>;
> +
> +			clocks = <&aoss_qmp>;
> +			clock-names = "apb_pclk";
> +
> +			in-ports {
> +				port {
> +					etr_rep_in: endpoint {
> +						remote-endpoint = <&qdss_rep_out0>;
> +					};
> +				};
> +			};
> +
> +			out-ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				port at 0 {
> +					reg = <0>;
> +
> +					etr_rep_out0: endpoint {
> +						remote-endpoint = <&etr0_in>;
> +					};
> +				};
> +
> +				port at 1 {
> +					reg = <1>;
> +
> +					etr_rep_out1: endpoint {
> +						remote-endpoint = <&etr1_in>;
> +					};
> +				};
> +			};
> +		};
> +
> +		tmc_etr1: tmc at 404f000 {
> +			compatible = "arm,coresight-tmc", "arm,primecell";
> +			reg = <0x0 0x0404f000 0x0 0x1000>;
> +
> +			clocks = <&aoss_qmp>;
> +			clock-names = "apb_pclk";
> +			iommus = <&apps_smmu 0x04a0 0x40>;
> +
> +			arm,scatter-gather;
> +			arm,buffer-size = <0x400000>;
> +
> +			in-ports {
> +				port {
> +					etr1_in: endpoint {
> +						remote-endpoint = <&etr_rep_out1>;
> +					};
> +				};
> +			};
> +
> +			out-ports {
> +				port {
> +					etr1_out: endpoint {
> +						remote-endpoint = <&ctcu_in1>;
> +					};
> +				};
> +			};
> +		};
> +
>   		funnel at 4b04000 {
>   			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
>   			reg = <0x0 0x4b04000 0x0 0x1000>;
> @@ -2708,6 +2853,14 @@ out-ports {
>   				#address-cells = <1>;
>   				#size-cells = <0>;
>   
> +				port at 0 {
> +					reg = <0>;
> +
> +					swao_rep_out0: endpoint {
> +						remote-endpoint = <&qdss_rep_in>;
> +					};
> +				};
> +
>   				port at 1 {
>   					reg = <1>;
>   					swao_rep_out1: endpoint {



From patchwork-bot+netdevbpf at kernel.org  Tue Mar  4 04:30:34 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 04 Mar 2025 12:30:34 +0000
Subject: [PATCH net-next v8 00/15] Introduce flowtable hw offloading in
 airoha_eth driver
In-Reply-To: <20250228-airoha-en7581-flowtable-offload-v8-0-01dc1653f46e@kernel.org>
References: <20250228-airoha-en7581-flowtable-offload-v8-0-01dc1653f46e@kernel.org>
Message-ID: <174109143450.124302.2708662777154071510.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri, 28 Feb 2025 11:54:08 +0100 you wrote:
> Introduce netfilter flowtable integration in airoha_eth driver to
> offload 5-tuple flower rules learned by the PPE module if the user
> accelerates them using a nft configuration similar to the one reported
> below:
> 
> table inet filter {
> 	flowtable ft {
> 		hook ingress priority filter
> 		devices = { lan1, lan2, lan3, lan4, eth1 }
> 		flags offload;
> 	}
> 	chain forward {
> 		type filter hook forward priority filter; policy accept;
> 		meta l4proto { tcp, udp } flow add @ft
> 	}
> }
> 
> [...]

Here is the summary with links:
  - [net-next,v8,01/15] net: airoha: Move airoha_eth driver in a dedicated folder
    https://git.kernel.org/netdev/net-next/c/fb3dda82fd38
  - [net-next,v8,02/15] net: airoha: Move definitions in airoha_eth.h
    https://git.kernel.org/netdev/net-next/c/b38f4ff0ceac
  - [net-next,v8,03/15] net: airoha: Move reg/write utility routines in airoha_eth.h
    https://git.kernel.org/netdev/net-next/c/e0758a8694fb
  - [net-next,v8,04/15] net: airoha: Move register definitions in airoha_regs.h
    https://git.kernel.org/netdev/net-next/c/ec663d9a82bf
  - [net-next,v8,05/15] net: airoha: Move DSA tag in DMA descriptor
    https://git.kernel.org/netdev/net-next/c/af3cf757d5c9
  - [net-next,v8,06/15] net: dsa: mt7530: Enable Rx sptag for EN7581 SoC
    https://git.kernel.org/netdev/net-next/c/ab667db1e601
  - [net-next,v8,07/15] net: airoha: Enable support for multiple net_devices
    https://git.kernel.org/netdev/net-next/c/80369686737f
  - [net-next,v8,08/15] net: airoha: Move REG_GDM_FWD_CFG() initialization in airoha_dev_init()
    https://git.kernel.org/netdev/net-next/c/67fde5d58cd4
  - [net-next,v8,09/15] net: airoha: Rename airoha_set_gdm_port_fwd_cfg() in airoha_set_vip_for_gdm_port()
    https://git.kernel.org/netdev/net-next/c/c28b8375f6d0
  - [net-next,v8,10/15] dt-bindings: net: airoha: Add the NPU node for EN7581 SoC
    https://git.kernel.org/netdev/net-next/c/266f7a0f81c0
  - [net-next,v8,11/15] dt-bindings: net: airoha: Add airoha,npu phandle property
    https://git.kernel.org/netdev/net-next/c/9b1a0b72264c
  - [net-next,v8,12/15] net: airoha: Introduce Airoha NPU support
    https://git.kernel.org/netdev/net-next/c/23290c7bc190
  - [net-next,v8,13/15] net: airoha: Introduce flowtable offload support
    https://git.kernel.org/netdev/net-next/c/00a7678310fe
  - [net-next,v8,14/15] net: airoha: Add loopback support for GDM2
    https://git.kernel.org/netdev/net-next/c/9cd451d414f6
  - [net-next,v8,15/15] net: airoha: Introduce PPE debugfs support
    https://git.kernel.org/netdev/net-next/c/3fe15c640f38

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From broonie at kernel.org  Tue Mar  4 04:33:59 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 04 Mar 2025 12:33:59 +0000
Subject: [RESEND PATCH v3] regulator: pca9450: Handle hardware with
 fixed SD_VSEL for LDO5
In-Reply-To: <20250303132258.50204-1-frieder@fris.de>
References: <20250303132258.50204-1-frieder@fris.de>
Message-ID: <174109163933.26710.17795041039558652228.b4-ty@kernel.org>

On Mon, 03 Mar 2025 14:22:54 +0100, Frieder Schrempf wrote:
> There are two ways to set the output voltage of the LD05
> regulator. First by writing to the voltage selection registers
> and second by toggling the SD_VSEL signal.
> 
> Usually board designers connect SD_VSEL to the VSELECT signal
> controlled by the USDHC controller, but in some cases the
> signal is hardwired to a fixed low level (therefore selecting
> 3.3V as initial value for allowing to boot from the SD card).
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next

Thanks!

[1/1] regulator: pca9450: Handle hardware with fixed SD_VSEL for LDO5
      commit: c8c1ab2c5cb797fe455aa18b4ab7bf39897627f6

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From tabba at google.com  Tue Mar  4 04:33:27 2025
From: tabba at google.com (Fuad Tabba)
Date: Tue, 4 Mar 2025 12:33:27 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <20250303214947.GA30619@willie-the-truck>
References: <20250226215520.1759218-1-tabba@google.com> <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com> <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck> <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
 <20250303214947.GA30619@willie-the-truck>
Message-ID: <CA+EHjTzZQ6UnOdaqpZ86JNiY=Gr_UoBAjZxk4CS3Q6nMJYdV2w@mail.gmail.com>

Hi Will,

On Mon, 3 Mar 2025 at 21:49, Will Deacon <will at kernel.org> wrote:
>
> On Mon, Mar 03, 2025 at 07:21:33PM +0000, Fuad Tabba wrote:
> > On Mon, 3 Mar 2025 at 19:18, Will Deacon <will at kernel.org> wrote:
> > > On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> > > > On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> > > > > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > > > > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > >  {
> > > > > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > > > > +     size_t pgd_sz, hyp_vm_sz;
> > > > > >       struct kvm_vcpu *host_vcpu;
> > > > > > -     pkvm_handle_t handle;
> > > > > >       void *pgd, *hyp_vm;
> > > > > >       unsigned long idx;
> > > > > >       int ret;
> > > > > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > >       if (ret < 0)
> > > > > >               goto free_vm;
> > > > > >
> > > > > > -     handle = ret;
> > > > > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> > > > >
> > > > > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > > > > update the readers to be READ_ONCE()?
> > > >
> > > > I don't remember the original reason, to be honest. In this case, it
> > > > was to make it consistent with downstream code in Android. That said,
> > > > I plan on revising all of these soon and fixing this (and related
> > > > code) in light of Will's comment regarding potential specter gadgets:
> > > >
> > > > https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/
> > >
> > > I'm not sure the spectre stuff changes the concurrency aspects here, so
> > > Quentin's question presumably still stands even after that.
> > >
> > > Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
> > > in pkvm_is_hyp_created() which is called without the config_lock held
> > > by kvm_arch_prepare_memory_region(). However, given that
> > > pkvm_is_hyp_created() is only testing against 0, I don't think the
> > > _ONCE() accessors are doing anything useful in that case.
> > >
> > > The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
> > > directly without the 'config_lock' held. The MMU notifiers look like
> > > they can do that, so I wonder if there's a theoretical race where they
> > > can race with first run and issue TLB invalidation with the wrong handle?
> > > That would apply equally to the upstream code, I think.
> >
> > Would using _ONCE accessors with the MMU notifiers be enough to avoid
> > the race, or do we need to reconsider the lock protecting the handle
> > and apply it to the notifiers?
>
> I'm not entirely sure... if we used _ONCE() then we'd get either the
> correct handle or zero, but we presumably need to order that against the
> page-table somehow. The 'mmu_lock' looks like it gives us that, but I
> don't think the notifiers are expecting an uninitialised handle in the
> case where the page-table is empty (i.e. if they fire before first run).
>
> Given that the handle is necessary for TLB invalidation, I'd be inclined
> to make sure that the handle is allocated and published _before_ the
> kvm_pgtable pointer checked by the notifiers is set, but that means
> moving the handle allocation into kvm_arch_init_vm(). Is that do-able?

It is doable, but it won't be a simple patch. Up until now, the
creation of the hyp view of a vm is associated with the first run of
the vm, rather than its allocation at the host. Part of the reason for
that is that much of the vm state (mainly the vcpu state) isn't
finalized until then.

This patch series fixes this in part, by decoupling the initialization
of the individual vcpus from the vm. Because of that, it would be
doable, but it might be better as another patch series that we could
test and analyze separately.

If you agree, I could whip up something and send it soon.

Cheers,
/fuad
> Will


From heiko at sntech.de  Tue Mar  4 04:38:02 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 13:38:02 +0100
Subject: [PATCH v2 2/2] drm/rockchip: lvds: Hide scary error messages on probe
 deferral
In-Reply-To: <0e54f70a-0b07-4ead-96fb-add2bbdaf787@cherry.de>
References: <20250301173547.710245-1-heiko@sntech.de>
 <20250301173547.710245-3-heiko@sntech.de>
 <0e54f70a-0b07-4ead-96fb-add2bbdaf787@cherry.de>
Message-ID: <9817880.CDJkKcVGEf@diego>

Am Dienstag, 4. M?rz 2025, 12:46:59 MEZ schrieb Quentin Schulz:
> > @@ -465,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
> >   
> >   	lvds->pins->p = devm_pinctrl_get(lvds->dev);
> >   	if (IS_ERR(lvds->pins->p)) {
> > -		DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
> > +		dev_err(lvds->dev, "no pinctrl handle\n");
> >   		devm_kfree(lvds->dev, lvds->pins);
> >   		lvds->pins = NULL;
> >   	} else {
> >   		lvds->pins->default_state =
> >   			pinctrl_lookup_state(lvds->pins->p, "lcdc");
> >   		if (IS_ERR(lvds->pins->default_state)) {
> > -			DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
> > +			dev_err(lvds->dev, "no default pinctrl state\n");
> >   			devm_kfree(lvds->dev, lvds->pins);
> >   			lvds->pins = NULL;
> 
> Should those be dev_err if they are not breaking anything? After all, 
> the device will actually probe? Maybe dev_warn would be more appropriate?
> 
> Maybe a separate patch since we had DRM_DEV_ERROR already, so switching 
> to dev_err in one and then lowering the log level in a second would make 
> "more" sense?

I did debate a bit whether to ignore here and go directly to dev_warn,
but opted for DRM_DEV_ERROR -> dev_err -> dev_warn, to keep the commit
description intact. Otherwise people looking at this patch alone might ask
if this part was forgotten, when the commit message indicates "all".

So expect an additional patch in v3 :-) .


> > @@ -593,7 +589,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
> >   		lvds->format = rockchip_lvds_name_to_format(name);
> >   
> >   	if (lvds->format < 0) {
> > -		DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
> > +		dev_err(dev, "invalid data-mapping format [%s]\n", name);
> >   		ret = lvds->format;
> 
> nipitck:
> 
> ret = dev_err_probe(dev, lvds->format, "invalid data-mapping format 
> [%s]\n", name);

you're right of course

...

> >   	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
> >   	if (ret < 0)
> > -		DRM_DEV_ERROR(dev, "failed to add component\n");
> > +		return dev_err_probe(dev, ret, "failed to add component\n");
> >   
> 
> Should this rather be drm_error? I believe this is related to the 
> Rockchip DRM main device?

I would group this more to general device error.
Component_add happens way before the component master binds anything.

drm_err is supposed to also point to the main drm_device as its parameter,
which does not even exist at this point.


Heiko




From Chum-Nam.Aubry at competitiveness.precisionfactorysolutions.com  Tue Mar  4 04:19:55 2025
From: Chum-Nam.Aubry at competitiveness.precisionfactorysolutions.com (Chum-Nam.Aubry)
Date: Tue, 4 Mar 2025 20:19:55 +0800
Subject: Combine efforts with us for unparalleled quality, service, and forward-thinking innovation.
Message-ID: <mailman.0.1741092099.2020513.linux-arm-kernel@lists.infradead.org>

Good evening linux-arm-kernel,
CNM Shenzhen, which was founded in 2006, enjoys a strategic geographical location and easy transportation access. We excel in designing and manufacturing precision mechanical parts, mold components, precision components, jigs, fixtures, and hardware parts.

In addition to our mold manufacturing services, we also offer a wide range of complementary services to cater to all your manufacturing needs. Our services include:
 1.3D Printing: We utilize advanced 3D printing technologies to quickly and accurately produce prototypes and functional parts, allowing for rapid product development and testing.
 2.CNC Machining: Our state-of-the-art CNC machines enable precise and efficient machining of various materials, ensuring high-quality components and molds.
 3.Surface Treatment: We offer a comprehensive range of surface treatment options, including painting, coating, anodizing, and more, to enhance the appearance and durability of your products.
 4.Film Coating: Our film coating services provide an additional layer of protection to your molds, improving their performance and extending their lifespan.
 5.Prototyping: We offer rapid prototyping services to help you visualize and test your designs before moving forward with mass production, saving time and reducing costs.
 6.Product Design and Development: Our experienced design and development team can assist you in bringing your ideas to life, ensuring that your products meet your specifications and market demands.
 7.Assembly Services: We provide convenient and efficient assembly services, offering fully assembled products ready for distribution.

With access to cutting-edge manufacturing equipment and processing technologies from Switzerland, Japan, and other top-tier nations, CNM caters predominantly to European and American markets, including the USA, Germany, UK, France, as well as Asian regions like Japan, Singapore, Thailand, and Vietnam. We conform to international standards like GB, JIS, DIN, and AISI, offering tailored manufacturing solutions to meet customer requirements. Our products achieve precision with geometric tolerances as low as 0.001mm, while finishes reach within Ra0.2.

I am eager to explore how we can assist with your upcoming projects and contribute to your success. Thank you for considering CNM Casting as your valued partner. I am thrilled about the opportunity to collaborate with you.

May each day be better than the last!
Tel : +86 18565792083
ATTN: Bill Liu

From heiko at sntech.de  Tue Mar  4 04:44:15 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 13:44:15 +0100
Subject: [PATCH v3 0/3] drm/rockchip: lvds: probe logging improvements
Message-ID: <20250304124418.111061-1-heiko@sntech.de>

Getting the panel already uses dev_err_probe to stay silent, when
the panel just probes later, and the lvds defers.

But the phy needed on px30, also has the capability to probe after
the lvds. So make the rest of the lvds probe/bind logic also use
more modern logging than DRM_DEV_ERR, that is deprecated anyway.

changes in v3:
- add patch to lower warning level on missing pinctrl (Quentin)
- one more dev_err_probe (Quentin)

changes in v2:
- reword the messages about getting (and preparing) pclk (Quentin)
- use a ret = dev_err_probe(dev, -EINVAL, ...) pattern
  in some (additional) places (Quentin)

Heiko Stuebner (3):
  drm/rockchip: lvds: move pclk preparation in with clk_get
  drm/rockchip: lvds: Hide scary error messages on probe deferral
  drm/rockchip: lvds: lower log severity for missing pinctrl settings

 drivers/gpu/drm/rockchip/rockchip_lvds.c | 80 +++++++++---------------
 1 file changed, 29 insertions(+), 51 deletions(-)

-- 
2.47.2



From heiko at sntech.de  Tue Mar  4 04:44:16 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 13:44:16 +0100
Subject: [PATCH v3 1/3] drm/rockchip: lvds: move pclk preparation in with clk_get
In-Reply-To: <20250304124418.111061-1-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
Message-ID: <20250304124418.111061-2-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

The LVDS block needs a separate pclk only on some socs, so currently
requests and prepares it in the soc-specific probe function, but common
code is required to unprepare it in the error path or on driver remove.

While this works because clk_unprepare just does nothing if clk is NULL,
this mismatch of who is responsible still is not very nice.
The clock-framework already has a helper for clk-get-and-prepare even
with devres support in devm_clk_get_prepared().

This will get and prepare the clock and also unprepare it on driver
removal, saving the driver from having to handle it "manually".

Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>
Reviewed-by: Andy Yan <andy.yan at rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 385cf6881504..ecfae8d5da89 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -448,15 +448,13 @@ struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs = {
 static int rk3288_lvds_probe(struct platform_device *pdev,
 			     struct rockchip_lvds *lvds)
 {
-	int ret;
-
 	lvds->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(lvds->regs))
 		return PTR_ERR(lvds->regs);
 
-	lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
+	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
 	if (IS_ERR(lvds->pclk)) {
-		DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
+		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
 		return PTR_ERR(lvds->pclk);
 	}
 
@@ -480,12 +478,6 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 		}
 	}
 
-	ret = clk_prepare(lvds->pclk);
-	if (ret < 0) {
-		DRM_DEV_ERROR(lvds->dev, "failed to prepare pclk_lvds\n");
-		return ret;
-	}
-
 	return 0;
 }
 
@@ -728,20 +720,15 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
 	dev_set_drvdata(dev, lvds);
 
 	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
-	if (ret < 0) {
+	if (ret < 0)
 		DRM_DEV_ERROR(dev, "failed to add component\n");
-		clk_unprepare(lvds->pclk);
-	}
 
 	return ret;
 }
 
 static void rockchip_lvds_remove(struct platform_device *pdev)
 {
-	struct rockchip_lvds *lvds = platform_get_drvdata(pdev);
-
 	component_del(&pdev->dev, &rockchip_lvds_component_ops);
-	clk_unprepare(lvds->pclk);
 }
 
 struct platform_driver rockchip_lvds_driver = {
-- 
2.47.2



From heiko at sntech.de  Tue Mar  4 04:44:18 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 13:44:18 +0100
Subject: [PATCH v3 3/3] drm/rockchip: lvds: lower log severity for missing pinctrl settings
In-Reply-To: <20250304124418.111061-1-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
Message-ID: <20250304124418.111061-4-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

While missing lvds pinctrl is unexpected and is reported, we nevertheless
don't fail setting up the device and instead continue without explicit
pinctrl handling. So lower the log-level from error to warning to reflect
that.

Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index bfebe42a0331..a673779de3d2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -464,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 
 	lvds->pins->p = devm_pinctrl_get(lvds->dev);
 	if (IS_ERR(lvds->pins->p)) {
-		dev_err(lvds->dev, "no pinctrl handle\n");
+		dev_warn(lvds->dev, "no pinctrl handle\n");
 		devm_kfree(lvds->dev, lvds->pins);
 		lvds->pins = NULL;
 	} else {
 		lvds->pins->default_state =
 			pinctrl_lookup_state(lvds->pins->p, "lcdc");
 		if (IS_ERR(lvds->pins->default_state)) {
-			dev_err(lvds->dev, "no default pinctrl state\n");
+			dev_warn(lvds->dev, "no default pinctrl state\n");
 			devm_kfree(lvds->dev, lvds->pins);
 			lvds->pins = NULL;
 		}
-- 
2.47.2



From heiko at sntech.de  Tue Mar  4 04:44:17 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 13:44:17 +0100
Subject: [PATCH v3 2/3] drm/rockchip: lvds: Hide scary error messages on probe deferral
In-Reply-To: <20250304124418.111061-1-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
Message-ID: <20250304124418.111061-3-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

Commit 52d11c863ac9 ("drm/rockchip: lvds: do not print scary message when
probing defer") already started hiding scary messages that are not relevant
if the requested supply just returned EPROBE_DEFER, but there are more
possible sources - like the phy.

So modernize the whole logging in the probe path by replacing the
remaining deprecated DRM_DEV_ERROR with appropriate dev_err(_probe)
and drm_err calls.

The distinction here is that all messages talking about mishaps of the
lvds element use dev_err(_probe) while messages caused by interaction
with the main Rockchip drm-device use drm_err.

Reviewed-by: Andy Yan <andy.yan at rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 63 ++++++++++--------------
 1 file changed, 27 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index ecfae8d5da89..bfebe42a0331 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -453,10 +453,9 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 		return PTR_ERR(lvds->regs);
 
 	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
-	if (IS_ERR(lvds->pclk)) {
-		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
-		return PTR_ERR(lvds->pclk);
-	}
+	if (IS_ERR(lvds->pclk))
+		return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk),
+				     "could not get or prepare pclk_lvds\n");
 
 	lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
 				  GFP_KERNEL);
@@ -465,14 +464,14 @@ static int rk3288_lvds_probe(struct platform_device *pdev,
 
 	lvds->pins->p = devm_pinctrl_get(lvds->dev);
 	if (IS_ERR(lvds->pins->p)) {
-		DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
+		dev_err(lvds->dev, "no pinctrl handle\n");
 		devm_kfree(lvds->dev, lvds->pins);
 		lvds->pins = NULL;
 	} else {
 		lvds->pins->default_state =
 			pinctrl_lookup_state(lvds->pins->p, "lcdc");
 		if (IS_ERR(lvds->pins->default_state)) {
-			DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
+			dev_err(lvds->dev, "no default pinctrl state\n");
 			devm_kfree(lvds->dev, lvds->pins);
 			lvds->pins = NULL;
 		}
@@ -547,11 +546,10 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	lvds->drm_dev = drm_dev;
 	port = of_graph_get_port_by_id(dev->of_node, 1);
-	if (!port) {
-		DRM_DEV_ERROR(dev,
-			      "can't found port point, please init lvds panel port!\n");
-		return -EINVAL;
-	}
+	if (!port)
+		return dev_err_probe(dev, -EINVAL,
+				     "can't found port point, please init lvds panel port!\n");
+
 	for_each_child_of_node(port, endpoint) {
 		child_count++;
 		of_property_read_u32(endpoint, "reg", &endpoint_id);
@@ -563,8 +561,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		}
 	}
 	if (!child_count) {
-		DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
-		ret = -EINVAL;
+		ret = dev_err_probe(dev, -EINVAL, "lvds port does not have any children\n");
 		goto err_put_port;
 	} else if (ret) {
 		dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
@@ -581,8 +578,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		lvds->output = rockchip_lvds_name_to_output(name);
 
 	if (lvds->output < 0) {
-		DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name);
-		ret = lvds->output;
+		ret = dev_err_probe(dev, lvds->output, "invalid output type [%s]\n", name);
 		goto err_put_remote;
 	}
 
@@ -593,8 +589,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 		lvds->format = rockchip_lvds_name_to_format(name);
 
 	if (lvds->format < 0) {
-		DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
-		ret = lvds->format;
+		ret = dev_err_probe(dev, lvds->format,
+				    "invalid data-mapping format [%s]\n", name);
 		goto err_put_remote;
 	}
 
@@ -604,8 +600,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_LVDS);
 	if (ret < 0) {
-		DRM_DEV_ERROR(drm_dev->dev,
-			      "failed to initialize encoder: %d\n", ret);
+		drm_err(drm_dev,
+			"failed to initialize encoder: %d\n", ret);
 		goto err_put_remote;
 	}
 
@@ -618,8 +614,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 					 &rockchip_lvds_connector_funcs,
 					 DRM_MODE_CONNECTOR_LVDS);
 		if (ret < 0) {
-			DRM_DEV_ERROR(drm_dev->dev,
-				      "failed to initialize connector: %d\n", ret);
+			drm_err(drm_dev,
+				"failed to initialize connector: %d\n", ret);
 			goto err_free_encoder;
 		}
 
@@ -633,9 +629,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 		connector = drm_bridge_connector_init(lvds->drm_dev, encoder);
 		if (IS_ERR(connector)) {
-			DRM_DEV_ERROR(drm_dev->dev,
-				      "failed to initialize bridge connector: %pe\n",
-				      connector);
+			drm_err(drm_dev,
+				"failed to initialize bridge connector: %pe\n",
+				connector);
 			ret = PTR_ERR(connector);
 			goto err_free_encoder;
 		}
@@ -643,8 +639,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 
 	ret = drm_connector_attach_encoder(connector, encoder);
 	if (ret < 0) {
-		DRM_DEV_ERROR(drm_dev->dev,
-			      "failed to attach encoder: %d\n", ret);
+		drm_err(drm_dev, "failed to attach encoder: %d\n", ret);
 		goto err_free_connector;
 	}
 
@@ -706,24 +701,20 @@ static int rockchip_lvds_probe(struct platform_device *pdev)
 
 	lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
 						    "rockchip,grf");
-	if (IS_ERR(lvds->grf)) {
-		DRM_DEV_ERROR(dev, "missing rockchip,grf property\n");
-		return PTR_ERR(lvds->grf);
-	}
+	if (IS_ERR(lvds->grf))
+		return dev_err_probe(dev, PTR_ERR(lvds->grf), "missing rockchip,grf property\n");
 
 	ret = lvds->soc_data->probe(pdev, lvds);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Platform initialization failed\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Platform initialization failed\n");
 
 	dev_set_drvdata(dev, lvds);
 
 	ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
 	if (ret < 0)
-		DRM_DEV_ERROR(dev, "failed to add component\n");
+		return dev_err_probe(dev, ret, "failed to add component\n");
 
-	return ret;
+	return 0;
 }
 
 static void rockchip_lvds_remove(struct platform_device *pdev)
-- 
2.47.2



From dinguyen at kernel.org  Tue Mar  4 04:46:18 2025
From: dinguyen at kernel.org (Dinh Nguyen)
Date: Tue, 4 Mar 2025 06:46:18 -0600
Subject: [PATCH v3 0/2] ARM: dts: socfpga: Add basic support for
 Terrasic's de10-nano
In-Reply-To: <cover.1738600838.git.u.kleine-koenig@baylibre.com>
References: <cover.1738600838.git.u.kleine-koenig@baylibre.com>
Message-ID: <6ae42224-74cf-4d2e-88fb-f766279d3525@kernel.org>

On 2/3/25 10:46, Uwe Kleine-K?nig wrote:
> Hello,
> 
> The only change since v2
> (https://lore.kernel.org/linux-arm-kernel/20250130074553.92023-2-u.kleine-koenig at baylibre.com):
> is that I added patch 1/2 that is supposed to fix the warning that I
> failed to notice with the testing I did. Thanks to Krzysztof and Rob for
> their patience with me. I hope I got it right now.
> 
> Best regards
> Uwe
> 
> Uwe Kleine-K?nig (2):
>    dt-bindings: altera: Add compatible for Terasic's DE10-nano
>    ARM: dts: socfpga: Add basic support for Terrasic's de10-nano
> 
>   .../devicetree/bindings/arm/altera.yaml       |  1 +
>   arch/arm/boot/dts/intel/socfpga/Makefile      |  1 +
>   .../socfpga/socfpga_cyclone5_de10nano.dts     | 95 +++++++++++++++++++
>   3 files changed, 97 insertions(+)
>   create mode 100644 arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10nano.dts
> 
> base-commit: 00f3246adeeacbda0bd0b303604e46eb59c32e6e

Applied!

Thanks,
Dinh


From ilpo.jarvinen at linux.intel.com  Tue Mar  4 05:05:24 2025
From: ilpo.jarvinen at linux.intel.com (=?UTF-8?q?Ilpo=20J=C3=A4rvinen?=)
Date: Tue, 4 Mar 2025 15:05:24 +0200 (EET)
Subject: [PATCH net-next v9 3/6] arch: x86: add IPC mailbox accessor
 function and add SoC register access
In-Reply-To: <48885074-b590-41e6-9794-49ec12713cce@redhat.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com> <20250227121522.1802832-4-yong.liang.choong@linux.intel.com> <48885074-b590-41e6-9794-49ec12713cce@redhat.com>
Message-ID: <d8e04cf2-afb9-dead-f7c2-297c66969081@linux.intel.com>

On Tue, 4 Mar 2025, Paolo Abeni wrote:

> On 2/27/25 1:15 PM, Choong Yong Liang wrote:
> > From: "David E. Box" <david.e.box at linux.intel.com>
> > 
> > - Exports intel_pmc_ipc() for host access to the PMC IPC mailbox
> > - Enables the host to access specific SoC registers through the PMC
> > firmware using IPC commands. This access method is necessary for
> > registers that are not available through direct Memory-Mapped I/O (MMIO),
> > which is used for other accessible parts of the PMC.
> > 
> > Signed-off-by: David E. Box <david.e.box at linux.intel.com>
> > Signed-off-by: Chao Qin <chao.qin at intel.com>
> > Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> 
> Hans, Ilpo, are you ok with this patch going through the netdev/net-next
> tree?

Yes, it you can merge it through netdev trees.

The function added into the header is a bit large on footprint front but 
there are not that many callers so I guess it's okay.

Acked-by: Ilpo J?rvinen <ilpo.jarvinen at linux.intel.com>


-- 
 i.

From peter.chen at cixtech.com  Tue Mar  4 05:05:33 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Tue, 4 Mar 2025 21:05:33 +0800
Subject: [PATCH v3 6/6] arm64: dts: cix: add initial CIX P1(SKY1) dts
 support
In-Reply-To: <86ikoqoso9.wl-maz@kernel.org>
References: <20250227120619.1741431-1-peter.chen@cixtech.com>
 <20250227120619.1741431-7-peter.chen@cixtech.com>
 <86r03ip0kf.wl-maz@kernel.org>
 <Z8WUxyJT1fdHKo67@nchen-desktop>
 <86ikoqoso9.wl-maz@kernel.org>
Message-ID: <Z8b6na8RjtF5FXi7@nchen-desktop>

On 25-03-03 18:49:58, Marc Zyngier wrote:
> > > > +
> > > > +     pmu-a520 {
> > > > +             compatible = "arm,cortex-a520-pmu";
> > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > > > +     };
> > > > +
> > > > +     pmu-a720 {
> > > > +             compatible = "arm,cortex-a720-pmu";
> > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > > > +     };
> > >
> > > This is wrong. The default configuration for PPIs is to expose the
> > > *same* device on all CPUs. You must use PPI affinities for your PMUs.
> > > Please see the GICv3 binding for the details.
> >
> > We have discussed internally, we have not seen the benefits routing
> > different PPI interrupt to dedicated CPUs. Any use cases?
> 
> This isn't about changing the PPI. It is about matching CPUs with
> their PMU. Here, you are saying "both PMU types are connected to all
> the CPUs using PPI7".
> 
> That's obviously not the case.
> 
> > I prefer changing pmu nodes as one generic Armv8 PMU node. Is it accepted?
> 
> No, that's not acceptable.
> 
> > Or must I keep both pmu for A520 and A720, and add PPI affinities to
> > describe hardware well?
> 
> This is an established practice on all big-little systems: each PMU
> node has an affinity that indicates which CPUs they are connected
> to. For GICv3+, this is carried by the interrupt specifier.
> 
> Please look at existing SoCs supported, such as rk3399, for example.

I see. I will add ppi-partitions for gic-v3 node.

> > >
> > > This will need to be bumped up to 4, and all the interrupt specifiers adjusted.
> >
> > Depends on if PPI affinities is must.
> 
> Definitely a must, unless you want to completely remove all traces of
> the PMU, which is of course silly, but a valid alternative.

I will change #interrupt-cells to 4, and applies to all interrupt
specifiers.

> 
> > > > +             arm,no-tick-in-suspend;
> > >
> > > Why do you need this? Is the HW so broken that you have implemented
> > > the global counter in a power domain that isn't always on?
> > >
> >
> > Not hardware broken, just arch timer will be powered off at cpu idle
> > and system suspend due to power consumption reason.
> 
> This is not about the timer. This is about the global counter. If your
> counter stops ticking when you're in idle or suspended, your system is
> broken and you need this property. If the timer (or more precisely the
> comparator) is turned off because the CPU is off, then that's the
> expected behaviour and you don't need this property.
> 

I will delete this property.

-- 

Best regards,
Peter


From piotr.oniszczuk at gmail.com  Tue Mar  4 05:12:50 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Tue, 4 Mar 2025 14:12:50 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <7b8767fc.3607.19551aa5f74.Coremail.andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <AC3DE87B-64B1-4C34-8E1B-3900E2C53AA3@gmail.com>
 <7b8767fc.3607.19551aa5f74.Coremail.andyshrk@163.com>
Message-ID: <047EECFC-7E55-44EC-896F-13FE04333E4D@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 1 mar 2025, o godz. 13:24:
> 
> 
> Hi Piotr,
> 
>> 
>> is it worth to play with this or it is too early?
> 
> I think you could give it a try if it using the Standard DP?non-ALT mode? port for output. 
> Since I don't currently have a development board with DP1 output available, I haven't been
> able to test it yet. As for the Type-C Alternate Mode output, some patches are still required 
> I'll  send it with V2 tomorrow or next week.
> Feel free to let me know if If you encounter any issues?
> 

Andy,
I added dp1 enablement in rock5 itx like this: https://gist.github.com/warpme/bddf75912193f57724c49216d5d85d4a
Unfortunately it not works.
For /sys/kernel/debug/dri/0/state - pls see above link?
I?m not sure: do i missed something in dt or rather issue issue  is in dp code...

FYI: schematic: https://dl.radxa.com/rock5/5itx/v1110/radxa_rock_5itx_v1110_schematic.pdf





From robh at kernel.org  Tue Mar  4 05:13:14 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 07:13:14 -0600
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <20250304093127.1954549-2-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
Message-ID: <20250304131314.GA2441686-robh@kernel.org>

On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> Add interrupts-extended property for edma that has multiple interrupt
> controllers used.

Did you try using interrupts-extended? No. Because either is supported 
by the tools already.

> 
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - newly added entry
> ---
>  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> index d54140f18d34..549afb8611a9 100644
> --- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> @@ -38,6 +38,10 @@ properties:
>      minItems: 1
>      maxItems: 64
>  
> +  interrupts-extended:
> +    minItems: 1
> +    maxItems: 65

Doesn't match the size for interrupt-names:

> +
>    interrupt-names:
>      minItems: 1
>      maxItems: 64


From brgl at bgdev.pl  Tue Mar  4 05:18:14 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue,  4 Mar 2025 14:18:14 +0100
Subject: [PATCH] irqchip: davinci-cp-intc: remove public header
Message-ID: <20250304131815.86549-1-brgl@bgdev.pl>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

There are no more users of irq-davinci-cp-intc.h (da830.c doesn't use
any of its symbols). Remove the header and make the driver stop using the
config structure.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 arch/arm/mach-davinci/da830.c               |  1 -
 drivers/irqchip/irq-davinci-cp-intc.c       | 31 ++++++++-------------
 include/linux/irqchip/irq-davinci-cp-intc.h | 25 -----------------
 3 files changed, 12 insertions(+), 45 deletions(-)
 delete mode 100644 include/linux/irqchip/irq-davinci-cp-intc.h

diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 2e497745b624..a044ea5cb4f1 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -11,7 +11,6 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/irqchip/irq-davinci-cp-intc.h>
 
 #include <clocksource/timer-davinci.h>
 
diff --git a/drivers/irqchip/irq-davinci-cp-intc.c b/drivers/irqchip/irq-davinci-cp-intc.c
index f4f8e9fadbbf..42224ca43d5e 100644
--- a/drivers/irqchip/irq-davinci-cp-intc.c
+++ b/drivers/irqchip/irq-davinci-cp-intc.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
-#include <linux/irqchip/irq-davinci-cp-intc.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -155,23 +154,21 @@ static const struct irq_domain_ops davinci_cp_intc_irq_domain_ops = {
 };
 
 static int __init
-davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
+davinci_cp_intc_do_init(struct resource *res, unsigned int num_irqs,
 			struct device_node *node)
 {
-	unsigned int num_regs = BITS_TO_LONGS(config->num_irqs);
+	unsigned int num_regs = BITS_TO_LONGS(num_irqs);
 	int offset, irq_base;
 	void __iomem *req;
 
-	req = request_mem_region(config->reg.start,
-				 resource_size(&config->reg),
+	req = request_mem_region(res->start, resource_size(res),
 				 "davinci-cp-intc");
 	if (!req) {
 		pr_err("%s: register range busy\n", __func__);
 		return -EBUSY;
 	}
 
-	davinci_cp_intc_base = ioremap(config->reg.start,
-				       resource_size(&config->reg));
+	davinci_cp_intc_base = ioremap(res->start, resource_size(res));
 	if (!davinci_cp_intc_base) {
 		pr_err("%s: unable to ioremap register range\n", __func__);
 		return -EINVAL;
@@ -200,12 +197,12 @@ davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
 	davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET);
 
 	/* Default all priorities to channel 7. */
-	num_regs = (config->num_irqs + 3) >> 2;	/* 4 channels per register */
+	num_regs = (num_irqs + 3) >> 2; /* 4 channels per register */
 	for (offset = 0; offset < num_regs; offset++)
 		davinci_cp_intc_write(0x07070707,
 			DAVINCI_CP_INTC_CHAN_MAP(offset));
 
-	irq_base = irq_alloc_descs(-1, 0, config->num_irqs, 0);
+	irq_base = irq_alloc_descs(-1, 0, num_irqs, 0);
 	if (irq_base < 0) {
 		pr_err("%s: unable to allocate interrupt descriptors: %d\n",
 		       __func__, irq_base);
@@ -213,7 +210,7 @@ davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
 	}
 
 	davinci_cp_intc_irq_domain = irq_domain_add_legacy(
-					node, config->num_irqs, irq_base, 0,
+					node, num_irqs, irq_base, 0,
 					&davinci_cp_intc_irq_domain_ops, NULL);
 
 	if (!davinci_cp_intc_irq_domain) {
@@ -229,31 +226,27 @@ davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
 	return 0;
 }
 
-int __init davinci_cp_intc_init(const struct davinci_cp_intc_config *config)
-{
-	return davinci_cp_intc_do_init(config, NULL);
-}
-
 static int __init davinci_cp_intc_of_init(struct device_node *node,
 					  struct device_node *parent)
 {
-	struct davinci_cp_intc_config config = { };
+	unsigned int num_irqs;
+	struct resource res;
 	int ret;
 
-	ret = of_address_to_resource(node, 0, &config.reg);
+	ret = of_address_to_resource(node, 0, &res);
 	if (ret) {
 		pr_err("%s: unable to get the register range from device-tree\n",
 		       __func__);
 		return ret;
 	}
 
-	ret = of_property_read_u32(node, "ti,intc-size", &config.num_irqs);
+	ret = of_property_read_u32(node, "ti,intc-size", &num_irqs);
 	if (ret) {
 		pr_err("%s: unable to read the 'ti,intc-size' property\n",
 		       __func__);
 		return ret;
 	}
 
-	return davinci_cp_intc_do_init(&config, node);
+	return davinci_cp_intc_do_init(&res, num_irqs, node);
 }
 IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", davinci_cp_intc_of_init);
diff --git a/include/linux/irqchip/irq-davinci-cp-intc.h b/include/linux/irqchip/irq-davinci-cp-intc.h
deleted file mode 100644
index 8d71ed5b5a61..000000000000
--- a/include/linux/irqchip/irq-davinci-cp-intc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Texas Instruments
- */
-
-#ifndef _LINUX_IRQ_DAVINCI_CP_INTC_
-#define _LINUX_IRQ_DAVINCI_CP_INTC_
-
-#include <linux/ioport.h>
-
-/**
- * struct davinci_cp_intc_config - configuration data for davinci-cp-intc
- *                                 driver.
- *
- * @reg: register range to map
- * @num_irqs: number of HW interrupts supported by the controller
- */
-struct davinci_cp_intc_config {
-	struct resource reg;
-	unsigned int num_irqs;
-};
-
-int davinci_cp_intc_init(const struct davinci_cp_intc_config *config);
-
-#endif /* _LINUX_IRQ_DAVINCI_CP_INTC_ */
-- 
2.45.2



From broonie at kernel.org  Tue Mar  4 05:39:09 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 04 Mar 2025 13:39:09 +0000
Subject: (subset) [PATCH v5 0/8] Add STM32MP25 SPI NOR support
In-Reply-To: <20250219080059.367045-1-patrice.chotard@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
Message-ID: <174109554967.53872.7193131885074327926.b4-ty@kernel.org>

On Wed, 19 Feb 2025 09:00:51 +0100, patrice.chotard at foss.st.com wrote:
> This series adds SPI NOR support for STM32MP25 SoCs from STMicroelectronics.
> 
> On STM32MP25 SoCs family, an Octo Memory Manager block manages the muxing,
> the memory area split, the chip select override and the time constraint
> between its 2 Octo SPI children.
> 
> Due to these depedencies, this series adds support for:
>   - Octo Memory Manager driver.
>   - Octo SPI driver.
>   - yaml schema for Octo Memory Manager and Octo SPI drivers.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/8] dt-bindings: spi: Add STM32 OSPI controller
      commit: bed97e35786a7d0141d1ecaaace03c46b5435d75
[2/8] spi: stm32: Add OSPI driver
      commit: 79b8a705e26c08f8f09dd55f1dd56f2375973d2d

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From m.szyprowski at samsung.com  Tue Mar  4 05:40:49 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Tue, 4 Mar 2025 14:40:49 +0100
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
	<CGME20250303113525eucas1p1099e087e2c11b9021603a6f13f8135c4@eucas1p1.samsung.com>
	<2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>
Message-ID: <7b5c90cf-00e4-4684-8719-f380badab064@samsung.com>

Hi,

On 03.03.2025 12:35, Suzuki K Poulose wrote:
> On 27/02/2025 14:41, Suzuki K Poulose wrote:
>> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. 
>> The address
>> space (GPA or IPA) of a Realm VM is split into two halves, with 
>> private bottom
>> half and shared top half. In Linux we treat the "top" bit of the IPA 
>> space as
>> an attribute, to indicate whether it is shared or not (MSB == 1 
>> implies shared).
>> Stage2 (GPA to PA) translations used by the CPU accesses, cover the 
>> full IPA space,
>> and are managed by RMM. The "top" bit as attribute is only a software 
>> construct.
>>
>> At present any device passed through to a Realm is treated as 
>> untrusted and the
>> Realm uses bounce buffering for any DMA, using the "decrypted" 
>> (shared) DMA
>> buffers (i.e., IPA with top bit set). In Linux, we only send the 
>> "DMA" address
>> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are 
>> managed by the
>> non-secure Host and thus it can be confusing for the host/device when 
>> an unmasked
>> address is provided. Given there could be other hypervisors than 
>> Linux/KVM
>> running Arm CCA guests, the Realm Guest must adhere to a single 
>> convention for
>> the DMA address. This gets further complicated when we add support 
>> for trusted
>> devices, which can DMA into the full Realm memory space, once 
>> accepted. Thus,
>> a DMA masked address (with "top" bit lost) will prevent a trusted 
>> device from
>> accessing a shared buffer.
>>
>> To resolve this Arm has decided to standardise the DMA address used 
>> by the Realm
>> to include the full IPA address bits (including the "top" bit, which 
>> Linux uses
>> as an attribute). This implies, any DMA to a shared buffer must have 
>> the top bit
>> of the IPA space set.
>>
>> There is already a provision to do this in phys_to_dma* and 
>> dma_to_phys(), but
>> that is specific to AMD SME and is quite the opposite of what we need 
>> for Arm CCA.
>> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and 
>> clear the bit
>> for "encrypted".
>>
>> This series converts the existing __sme_* helpers to a bit more 
>> generalised versions :
>> dma_addr_decrypted() and dma_encrypted(). Also, while converting a 
>> DMA address back
>> to CPU physical address requires clearing off any 
>> "encryption/decryption" bits.
>> I have named this "dma_addr_canonical()". (The other options are :
>> ?? * dma_addr_clear_encryption - Well, not just for encryption, but 
>> we clear decryption
>> ???? too, so not ideal.
>> ?? * dma_addr_normal
>> ?? * dma_addr_clear
>> ?? * dma_addr_default
>>
>> This also implies that the VMMs must take care to :
>>
>> ? 1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>> ? 2. Always mask the "top" bit off any IPA it receives from the Realm 
>> for DMA.
>> ???? KVM already does that today and no changes are required.
>>
>> A kvmtool branch with the changes above is available here [1]. There 
>> are two
>> patches [2] & [3], that are really required on top of the Arm CCA 
>> support.
>>
>> Ideally it would be good to get this backported to v6.13 stable 
>> kernel releases
>> to make sure that they are compliant with this change.
>>
>
> Please could you take a look at this series and let us know your
> thoughts ? If you are happy with the changes, are you happy to pull
> this through the DMA MAP tree ? The relevant bits have been reviewed/
> acked by people (arm64 and AMD bits).

The changes look fine. However I won't be able to setup new dma-mapping 
git tree this week because I got really sick has to stay in bed. :/ If 
You don't want such delay, please merge it via ARM64 tree. Here is my:

Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>


Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From vdonnefort at google.com  Tue Mar  4 05:43:44 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Tue,  4 Mar 2025 13:43:44 +0000
Subject: [PATCH v2 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <20250304134347.369854-1-vdonnefort@google.com>
References: <20250304134347.369854-1-vdonnefort@google.com>
Message-ID: <20250304134347.369854-2-vdonnefort@google.com>

Add flags to kvm_hyp_memcache and propagate them up to the allocation
and free callbacks. This will later allow to account for memory, based
on the memcache configuration.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3a7ec98ef123..12691ae23d4c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,7 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+	unsigned long flags;
 };
 
 static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..68d99baa76c2 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1086,12 +1086,12 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 	}
 }
 
-static void hyp_mc_free_fn(void *addr, void *unused)
+static void hyp_mc_free_fn(void *addr, void *flags)
 {
 	free_page((unsigned long)addr);
 }
 
-static void *hyp_mc_alloc_fn(void *unused)
+static void *hyp_mc_alloc_fn(void *flags)
 {
 	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
 }
@@ -1102,7 +1102,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
 		return;
 
 	kfree(mc->mapping);
-	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
+	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, (void *)mc->flags);
 }
 
 int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
@@ -1117,7 +1117,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
 	}
 
 	return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
-				    kvm_host_pa, NULL);
+				    kvm_host_pa, (void *)mc->flags);
 }
 
 /**
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Tue Mar  4 05:43:45 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Tue,  4 Mar 2025 13:43:45 +0000
Subject: [PATCH v2 2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
In-Reply-To: <20250304134347.369854-1-vdonnefort@google.com>
References: <20250304134347.369854-1-vdonnefort@google.com>
Message-ID: <20250304134347.369854-3-vdonnefort@google.com>

In order to account for memory dedicated to the stage-2 page-tables, use
a separated memcache when tearing down the VM.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 12691ae23d4c..ace3969e8106 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
 struct kvm_protected_vm {
 	pkvm_handle_t handle;
 	struct kvm_hyp_memcache teardown_mc;
+	struct kvm_hyp_memcache stage2_teardown_mc;
 	bool enabled;
 };
 
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 3927fe52a3dd..15f8d5315959 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
 
 int __pkvm_teardown_vm(pkvm_handle_t handle)
 {
-	struct kvm_hyp_memcache *mc;
+	struct kvm_hyp_memcache *mc, *stage2_mc;
 	struct pkvm_hyp_vm *hyp_vm;
 	struct kvm *host_kvm;
 	unsigned int idx;
@@ -706,7 +706,8 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 
 	/* Reclaim guest pages (including page-table pages) */
 	mc = &host_kvm->arch.pkvm.teardown_mc;
-	reclaim_guest_pages(hyp_vm, mc);
+	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
+	reclaim_guest_pages(hyp_vm, stage2_mc);
 	unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->nr_vcpus);
 
 	/* Push the metadata pages to the teardown memcache */
@@ -717,7 +718,7 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 		while (vcpu_mc->nr_pages) {
 			void *addr = pop_hyp_memcache(vcpu_mc, hyp_phys_to_virt);
 
-			push_hyp_memcache(mc, addr, hyp_virt_to_phys);
+			push_hyp_memcache(stage2_mc, addr, hyp_virt_to_phys);
 			unmap_donated_memory_noclear(addr, PAGE_SIZE);
 		}
 
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..19921ca407c6 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -111,6 +111,7 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 
 	host_kvm->arch.pkvm.handle = 0;
 	free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
+	free_hyp_memcache(&host_kvm->arch.pkvm.stage2_teardown_mc);
 }
 
 /*
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Tue Mar  4 05:43:43 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Tue,  4 Mar 2025 13:43:43 +0000
Subject: [PATCH v2 0/3] Count pKVM stage-2 usage in secondary pagetable stat
Message-ID: <20250304134347.369854-1-vdonnefort@google.com>

This series allows to count stage-2 related memory when using pKVM. The
value can be found in the /proc/meminfo field SecPageTables.

Changes since v1: https://lore.kernel.org/all/20250228121355.1377891-1-vdonnefort at google.com/
  - Flags to kvm_hyp_memcache
  - Separate stage-2 memcache
  - Account for PGD

Vincent Donnefort (3):
  KVM: arm64: Add flags to kvm_hyp_memcache
  KVM: arm64: Distinct pKVM teardown memcache for stage-2
  KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats

 arch/arm64/include/asm/kvm_host.h |  4 ++++
 arch/arm64/kvm/hyp/nvhe/pkvm.c    |  7 ++++---
 arch/arm64/kvm/mmu.c              | 18 +++++++++++++-----
 arch/arm64/kvm/pkvm.c             |  5 +++++
 4 files changed, 26 insertions(+), 8 deletions(-)


base-commit: d082ecbc71e9e0bf49883ee4afd435a77a5101b6
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Tue Mar  4 05:43:46 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Tue,  4 Mar 2025 13:43:46 +0000
Subject: [PATCH v2 3/3] KVM: arm64: Count pKVM stage-2 usage in secondary
 pagetable stats
In-Reply-To: <20250304134347.369854-1-vdonnefort@google.com>
References: <20250304134347.369854-1-vdonnefort@google.com>
Message-ID: <20250304134347.369854-4-vdonnefort@google.com>

Count the pages used by pKVM for the guest stage-2 in memory stats under
secondary pagetable stats, similarly to what the VHE mode does.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ace3969e8106..51754a354b7a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,8 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+
+#define	HYP_MEMCACHE_ACCOUNT_STAGE2	BIT(1)
 	unsigned long flags;
 };
 
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 68d99baa76c2..85d739fbddb8 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1088,12 +1088,20 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 
 static void hyp_mc_free_fn(void *addr, void *flags)
 {
+	if ((unsigned long)flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, -1);
+
 	free_page((unsigned long)addr);
 }
 
 static void *hyp_mc_alloc_fn(void *flags)
 {
-	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+	void *addr = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+
+	if (addr && (unsigned long)flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, 1);
+
+	return addr;
 }
 
 void free_hyp_memcache(struct kvm_hyp_memcache *mc)
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 19921ca407c6..7e6e3b0518f8 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -165,12 +165,16 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 	handle = ret;
 
 	host_kvm->arch.pkvm.handle = handle;
+	host_kvm->arch.pkvm.stage2_teardown_mc.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+	kvm_account_pgtable_pages(pgd, PAGE_ALIGN(pgd_sz) >> PAGE_SHIFT);
 
 	/* Donate memory for the vcpus at hyp and initialize it. */
 	hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
 	kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
 		void *hyp_vcpu;
 
+		host_vcpu->arch.pkvm_memcache.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+
 		/* Indexing of the vcpus to be sequential starting at 0. */
 		if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
 			ret = -EINVAL;
-- 
2.48.1.711.g2feabab25a-goog



From julien.massot at collabora.com  Tue Mar  4 05:56:23 2025
From: julien.massot at collabora.com (Julien Massot)
Date: Tue, 04 Mar 2025 14:56:23 +0100
Subject: [PATCH 1/2] arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI
 DSI port
In-Reply-To: <fc0a9471-da47-4f4f-a471-1b20f344ad22@collabora.com>
References: <20250226-radxa-panel-overlay-v1-0-9e8938dfbead@collabora.com>
	 <20250226-radxa-panel-overlay-v1-1-9e8938dfbead@collabora.com>
	 <fc0a9471-da47-4f4f-a471-1b20f344ad22@collabora.com>
Message-ID: <3ee575154a95627b7ecaf33b2f52b6fa0ce4a352.camel@collabora.com>

Hi Angelo,

On Mon, 2025-03-03 at 12:32 +0100, AngeloGioacchino Del Regno wrote:
> Il 26/02/25 15:35, Julien Massot ha scritto:
> > This board can use a MIPI-DSI panel on the DSI0 connector: in
> > preparation for adding an overlay for the Radxa Display 8HD,
> > add a pipeline connecting VDOSYS0 components to DSI0.
> > 
> > Also add the backlight, and some pin definitions available
> > through the DSI0 port.
> > 
> > Signed-off-by: Julien Massot <julien.massot at collabora.com>
> > ---
> > ? .../boot/dts/mediatek/mt8395-radxa-nio-12l.dts???? | 60 ++++++++++++++++++++++
> > ? 1 file changed, 60 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> > b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> > index 7184dc99296c7f5d749c7e6d378722677970b3b7..65c77e43d1cd4913b6741e25130febd746ff753c 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> > +++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
> > @@ -48,6 +48,17 @@ memory at 40000000 {
> > ??		reg = <0 0x40000000 0x1 0x0>;
> > ??	};
> > ? 
> > +	backlight: backlight {
> > +		compatible = "pwm-backlight";
> > +		brightness-levels = <0 1023>;
> > +		default-brightness-level = <576>;
> > +		enable-gpios = <&pio 107 GPIO_ACTIVE_HIGH>;
> > +		num-interpolated-steps = <1023>;
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&dsi0_backlight_pins>;
> > +		pwms = <&disp_pwm0 0 500000>;
> 
> This should be disabled, unless there is a display connected to the DSI connector.
> 
> If there's no display, there's no point in enabling any backlight, as that pin
> may be reused somehow (with hardware hacks, maybe, yes, but still configuring
> the PWM IP and the pin as PWM while unused is at least a waste of energy).
> 
Yes, I will keep it disabled in the board dts.

> > +	};
> > +
> > ??	wifi_vreg: regulator-wifi-3v3-en {
> > ??		compatible = "regulator-fixed";
> > ??		regulator-name = "wifi_3v3_en";
> > @@ -499,9 +510,20 @@ &mt6359_vsram_others_ldo_reg {
> > ??	regulator-max-microvolt = <750000>;
> > ? };
> > ? 
> > +&ovl0_in {
> > +	remote-endpoint = <&vdosys0_ep_main>;
> > +};
> > +
> 
> This goes to the overlay that enables the DSI display.
Ok

> 
> > @@ -912,6 +960,18 @@ &ssusb2 {
> > ??	status = "okay";
> > ? };
> > ? 
> > +&vdosys0 {
> > +	port {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		vdosys0_ep_main: endpoint at 0 {
> > +			reg = <0>;
> > +			remote-endpoint = <&ovl0_in>;
> > +		};
> > +	};
> > +};
> 
> If you enable this path, in the event that the DSI display overlay is not added,
> the mediatek-drm driver will fail probing: even if a second path is enabled and
> that will succeed regardless of the first one failing, I don't see a reason why
> whoever doesn't have a DSI display attached should see a miserable failure in the
> kernel log :-)
> 
> Besides, mediatek-drm failing will also slow down boot for no reason.... etc etc.
> 
> Please move the display path setup to the DSI display overlay.
Sure will move the display path setup to the display overlay.

Thank you,
Julien


From julien.massot at collabora.com  Tue Mar  4 06:01:54 2025
From: julien.massot at collabora.com (Julien Massot)
Date: Tue, 04 Mar 2025 15:01:54 +0100
Subject: [PATCH v2 0/2] mt8395-radxa-nio-12l: Add overlay for Radxa 8HD
 panel
Message-ID: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>

Hi,
small series to enable a DSI panel on Radxa NIO 12L.

The first patch adds missing dts nodes to expose some
feature of the DSI0 port.

The second patch adds the Radxa 8 HD panel as an overlay.

Tested on top of linux-next tag:next-20250303

Signed-off-by: Julien Massot <julien.massot at collabora.com>
---
Changes in v2:
- Moved video pipeline enablement to the overlay (ovl0, vdosys0)
- Keep backlight disabled in the board dts, enabled in the panel overlay
- Test again on Linux next-20250303
- Link to v1: https://lore.kernel.org/r/20250226-radxa-panel-overlay-v1-0-9e8938dfbead at collabora.com

---
Julien Massot (2):
      arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI DSI port
      arm64: dts: mediatek: mt8395-radxa-nio-12l: Add Radxa 8 HD panel

 arch/arm64/boot/dts/mediatek/Makefile              |  2 +
 .../mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso  | 84 ++++++++++++++++++++++
 .../boot/dts/mediatek/mt8395-radxa-nio-12l.dts     | 45 ++++++++++++
 3 files changed, 131 insertions(+)
---
base-commit: cd3215bbcb9d4321def93fea6cfad4d5b42b9d1d
change-id: 20250226-radxa-panel-overlay-5424db95995c

Best regards,
-- 
Julien Massot <julien.massot at collabora.com>



From julien.massot at collabora.com  Tue Mar  4 06:01:55 2025
From: julien.massot at collabora.com (Julien Massot)
Date: Tue, 04 Mar 2025 15:01:55 +0100
Subject: [PATCH v2 1/2] arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI
 DSI port
In-Reply-To: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
References: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
Message-ID: <20250304-radxa-panel-overlay-v2-1-3ee6797d3f86@collabora.com>

This board can use a MIPI-DSI panel on the DSI0 connector: in
preparation for adding an overlay for the Radxa Display 8HD,
add the backlight, and some definitions for pins available
through the DSI0 port.

Signed-off-by: Julien Massot <julien.massot at collabora.com>
---
 .../boot/dts/mediatek/mt8395-radxa-nio-12l.dts     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
index 7184dc99296c7f5d749c7e6d378722677970b3b7..1c922e98441a1aadf0aa3cdd76583a70401a1fa3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
@@ -48,6 +48,18 @@ memory at 40000000 {
 		reg = <0 0x40000000 0x1 0x0>;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <0 1023>;
+		default-brightness-level = <576>;
+		enable-gpios = <&pio 107 GPIO_ACTIVE_HIGH>;
+		num-interpolated-steps = <1023>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&dsi0_backlight_pins>;
+		pwms = <&disp_pwm0 0 500000>;
+		status = "disabled";
+	};
+
 	wifi_vreg: regulator-wifi-3v3-en {
 		compatible = "regulator-fixed";
 		regulator-name = "wifi_3v3_en";
@@ -502,6 +514,13 @@ &mt6359_vsram_others_ldo_reg {
 &pio {
 	mediatek,rsel-resistance-in-si-unit;
 
+	dsi0_backlight_pins: dsi0-backlight-pins {
+		pins-backlight-en {
+			pinmux = <PINMUX_GPIO107__FUNC_GPIO107>;
+			output-high;
+		};
+	};
+
 	eth_default_pins: eth-default-pins {
 		pins-cc {
 			pinmux = <PINMUX_GPIO85__FUNC_GBE_TXC>,
@@ -699,6 +718,13 @@ pins-irq {
 		};
 	};
 
+	panel_default_pins: panel-pins {
+		pins-rst {
+			pinmux = <PINMUX_GPIO108__FUNC_GPIO108>;
+			bias-pull-up;
+		};
+	};
+
 	pcie0_default_pins: pcie0-default-pins {
 		pins-bus {
 			pinmux = <PINMUX_GPIO19__FUNC_WAKEN>,
@@ -717,6 +743,12 @@ pins-bus {
 		};
 	};
 
+	pwm0_default_pins: pwm0-pins {
+		pins-disp-pwm {
+			pinmux = <PINMUX_GPIO97__FUNC_DISP_PWM0>;
+		};
+	};
+
 	spi1_pins: spi1-default-pins {
 		pins-bus {
 			pinmux = <PINMUX_GPIO136__FUNC_SPIM1_CSB>,
@@ -737,6 +769,19 @@ pins-bus {
 		};
 	};
 
+	touch_pins: touch-pins {
+		pins-touch-int {
+			pinmux = <PINMUX_GPIO132__FUNC_GPIO132>;
+			input-enable;
+			bias-disable;
+		};
+
+		pins-touch-rst {
+			pinmux = <PINMUX_GPIO133__FUNC_GPIO133>;
+			output-high;
+		};
+	};
+
 	uart0_pins: uart0-pins {
 		pins-bus {
 			pinmux = <PINMUX_GPIO98__FUNC_UTXD0>,

-- 
2.48.1



From julien.massot at collabora.com  Tue Mar  4 06:01:56 2025
From: julien.massot at collabora.com (Julien Massot)
Date: Tue, 04 Mar 2025 15:01:56 +0100
Subject: [PATCH v2 2/2] arm64: dts: mediatek: mt8395-radxa-nio-12l: Add
 Radxa 8 HD panel
In-Reply-To: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
References: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
Message-ID: <20250304-radxa-panel-overlay-v2-2-3ee6797d3f86@collabora.com>

The Radxa 8 HD touchscreen can be used with various Radxa board
and is sold appart from the Radxa NIO 12L development kit.

Add a DTS overlay for this panel.

Signed-off-by: Julien Massot <julien.massot at collabora.com>
---
 arch/arm64/boot/dts/mediatek/Makefile              |  2 +
 .../mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso  | 84 ++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index ae1147eca9a915f117487101e2ad4acead97adfe..58484e8300632edbdef24bbda33ccf00db9df937 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -100,9 +100,11 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-genio-1200-evk.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8390-genio-700-evk.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-kontron-3-5-sbc-i1200.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l-8-hd-panel.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb
 
 # Device tree overlays support
 DTC_FLAGS_mt7986a-bananapi-bpi-r3 := -@
 DTC_FLAGS_mt7986a-bananapi-bpi-r3-mini := -@
 DTC_FLAGS_mt7988a-bananapi-bpi-r4 := -@
+DTC_FLAGS_mt8395-radxa-nio-12l := -@
diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso
new file mode 100644
index 0000000000000000000000000000000000000000..0389c9cb8581c0bb50bb38fd35d1190de13feb6e
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Radxa Display 8 HD touchscreen module
+ * Copyright (C) 2025 Collabora Ltd.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&backlight {
+	status = "okay";
+};
+
+&disp_pwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_default_pins>;
+	status = "okay";
+};
+
+&dsi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	panel at 0 {
+		compatible = "radxa,display-8hd-ad002", "jadard,jd9365da-h3";
+		reg = <0>;
+		backlight = <&backlight>;
+		vdd-supply = <&mt6359_vcn33_2_bt_ldo_reg>;
+		vccio-supply = <&mt6360_ldo2>;
+		reset-gpios = <&pio 108 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&panel_default_pins>;
+
+		port {
+			dsi_panel_in: endpoint {
+				remote-endpoint = <&dsi0_out>;
+			};
+		};
+	};
+};
+
+&dsi0_out {
+	remote-endpoint = <&dsi_panel_in>;
+};
+
+&i2c4 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen at 14 {
+		compatible = "goodix,gt911";
+		reg = <0x14>;
+		interrupts-extended = <&pio 132 IRQ_TYPE_EDGE_RISING>;
+		irq-gpios = <&pio 132 GPIO_ACTIVE_HIGH>;
+		reset-gpios = <&pio 133 GPIO_ACTIVE_HIGH>;
+		VDDIO-supply = <&mt6359_vcn33_2_bt_ldo_reg>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touch_pins>;
+	};
+};
+
+&mipi_tx0 {
+	status = "okay";
+};
+
+&ovl0_in {
+	remote-endpoint = <&vdosys0_ep_main>;
+};
+
+&vdosys0 {
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdosys0_ep_main: endpoint at 0 {
+			reg = <0>;
+			remote-endpoint = <&ovl0_in>;
+		};
+	};
+};

-- 
2.48.1



From robh at kernel.org  Tue Mar  4 06:02:25 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 4 Mar 2025 08:02:25 -0600
Subject: [PATCH v3 1/6] dt-bindings: pinctrl: Add bindings for BCM21664
 pin controller
In-Reply-To: <20250303-bcm21664-pinctrl-v3-1-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
 <20250303-bcm21664-pinctrl-v3-1-5f8b80e4ab51@gmail.com>
Message-ID: <174109694544.2517876.17977367715126492989.robh@kernel.org>


On Mon, 03 Mar 2025 21:54:46 +0100, Artur Weber wrote:
> Add device tree bindings for the pin controller included in the
> BCM21664 chip. The bindings are based off brcm,bcm11351-pinctrl.yaml;
> both chips use the same driver, but have different pins, and the
> BCM21664 has 6 alt modes instead of 4.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---
> Changes in v3:
> - Fix example for I2C pins
> - Specify bias-pull-up/bias-pull-down as a boolean
> - Add gpio16/gpio17 to list of I2C pins in slew-rate description
> - Use additionalProperties: false on pin group and specify valid
>   properties for more strict checking
> 
> Changes in v2:
> - Drop "property: true" declarations which had no effect with
>   "unevaluatedProperties: false"
> - Define property limits for I2C pins only instead of standard pins,
>   making the pin-specific "if" condition significantly smaller
> ---
>  .../bindings/pinctrl/brcm,bcm21664-pinctrl.yaml    | 152 +++++++++++++++++++++
>  1 file changed, 152 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From angelogioacchino.delregno at collabora.com  Tue Mar  4 06:07:31 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 15:07:31 +0100
Subject: [PATCH v2 2/2] arm64: dts: mediatek: mt8395-radxa-nio-12l: Add
 Radxa 8 HD panel
In-Reply-To: <20250304-radxa-panel-overlay-v2-2-3ee6797d3f86@collabora.com>
References: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
 <20250304-radxa-panel-overlay-v2-2-3ee6797d3f86@collabora.com>
Message-ID: <287cff19-a95f-47c0-8e06-9d12b9e7a093@collabora.com>

Il 04/03/25 15:01, Julien Massot ha scritto:
> The Radxa 8 HD touchscreen can be used with various Radxa board
> and is sold appart from the Radxa NIO 12L development kit.
> 
> Add a DTS overlay for this panel.
> 
> Signed-off-by: Julien Massot <julien.massot at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Tue Mar  4 06:07:32 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 15:07:32 +0100
Subject: [PATCH v2 1/2] arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI
 DSI port
In-Reply-To: <20250304-radxa-panel-overlay-v2-1-3ee6797d3f86@collabora.com>
References: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
 <20250304-radxa-panel-overlay-v2-1-3ee6797d3f86@collabora.com>
Message-ID: <c2580ca2-2999-43cd-a1bd-ab660bbc8953@collabora.com>

Il 04/03/25 15:01, Julien Massot ha scritto:
> This board can use a MIPI-DSI panel on the DSI0 connector: in
> preparation for adding an overlay for the Radxa Display 8HD,
> add the backlight, and some definitions for pins available
> through the DSI0 port.
> 
> Signed-off-by: Julien Massot <julien.massot at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From tongtiangen at huawei.com  Tue Mar  4 06:10:47 2025
From: tongtiangen at huawei.com (Tong Tiangen)
Date: Tue, 4 Mar 2025 22:10:47 +0800
Subject: [PATCH v13 4/5] arm64: support copy_mc_[user]_highpage()
In-Reply-To: <Z7TisqB5qCIF5nYI@arm.com>
References: <20241209024257.3618492-1-tongtiangen@huawei.com>
 <20241209024257.3618492-5-tongtiangen@huawei.com> <Z6zWSXzKctkpyH7-@arm.com>
 <69955002-c3b1-459d-9b42-8d07475c3fd3@huawei.com> <Z698SFVqHjpGeGC0@arm.com>
 <e1d2affb-5c6b-00b5-8209-34bbca36f96b@huawei.com> <Z7NN5Pa-c5PtIbcF@arm.com>
 <3b181285-2ff3-b77a-867b-725f38ea86d3@huawei.com> <Z7TisqB5qCIF5nYI@arm.com>
Message-ID: <2c1fa758-c292-aefb-f6e2-cab41f592568@huawei.com>

Hi,Catalin:

Kindly ping ...

Thanks.:)

? 2025/2/19 3:42, Catalin Marinas ??:
> On Tue, Feb 18, 2025 at 07:51:10PM +0800, Tong Tiangen wrote:
>>>>>> ? 2025/2/13 1:11, Catalin Marinas ??:
>>>>>>> On Mon, Dec 09, 2024 at 10:42:56AM +0800, Tong Tiangen wrote:
>>>>>>>> Currently, many scenarios that can tolerate memory errors when copying page
>>>>>>>> have been supported in the kernel[1~5], all of which are implemented by
>>>>>>>> copy_mc_[user]_highpage(). arm64 should also support this mechanism.
>>>>>>>>
>>>>>>>> Due to mte, arm64 needs to have its own copy_mc_[user]_highpage()
>>>>>>>> architecture implementation, macros __HAVE_ARCH_COPY_MC_HIGHPAGE and
>>>>>>>> __HAVE_ARCH_COPY_MC_USER_HIGHPAGE have been added to control it.
>>>>>>>>
>>>>>>>> Add new helper copy_mc_page() which provide a page copy implementation with
>>>>>>>> hardware memory error safe. The code logic of copy_mc_page() is the same as
>>>>>>>> copy_page(), the main difference is that the ldp insn of copy_mc_page()
>>>>>>>> contains the fixup type EX_TYPE_KACCESS_ERR_ZERO_MEM_ERR, therefore, the
>>>>>>>> main logic is extracted to copy_page_template.S. In addition, the fixup of
>>>>>>>> MOPS insn is not considered at present.
>>>>>>>
>>>>>>> Could we not add the exception table entry permanently but ignore the
>>>>>>> exception table entry if it's not on the do_sea() path? That would save
>>>>>>> some code duplication.
> [...]
>> So we need another way to distinguish the different processing of the
>> same exception type on SEA and non-SEA path.
> 
> Distinguishing whether the fault is SEA or non-SEA is already done by
> the exception handling you are adding. What we don't have though is
> information about whether the caller invoked copy_highpage() or
> copy_mc_highpage(). That's where the code duplication comes in handy.
> 
> It's a shame we need to duplicate identical functions just to have
> different addresses to look up in the exception table. We are also short
> of caller saved registers to track this information (e.g. an extra
> argument to those functions that the exception handler interprets).
> 
> I need to think a bit more, we could in theory get the arm64 memcpy_mc()
> to return an error code depending on what type of fault it got (e.g.
> -EHWPOISON for SEA, -EFAULT for non-SEA). copy_mc_highpage() would
> interpret this one and panic if -EFAULT. But we lose some fault details
> we normally get on a faulty access like some of the registers.
> 
> Well, maybe the simples is still to keep the function duplication. I'll
> have another look at the series tomorrow.
> 


From robh at kernel.org  Tue Mar  4 06:11:25 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 08:11:25 -0600
Subject: [PATCH v3 04/15] dt-bindings: clk: sunxi-ng: document Allwinner
 A523 CCU
In-Reply-To: <20250304012805.28594-5-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
 <20250304012805.28594-5-andre.przywara@arm.com>
Message-ID: <20250304141125.GA2518548-robh@kernel.org>

On Tue, Mar 04, 2025 at 01:27:54AM +0000, Andre Przywara wrote:
> The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> the main CCU.
> 
> The source clock list differs in some annoying details, and folding this
> into the existing Allwinner CCU clock binding document gets quite
> unwieldy, so create a new document for these CCUs.
> Add the new compatible string, along with the required input clock
> lists. This conditionally describes the input clock list, to make for
> an easier patch adding the other CCUs.
> 
> Also add the DT binding headers, listing all the clocks with their ID
> numbers.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../clock/allwinner,sun55i-a523-ccu.yaml      |  77 +++++++
>  include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
>  include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
>  3 files changed, 354 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
>  create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> new file mode 100644
> index 0000000000000..2eacaeaeabac7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> @@ -0,0 +1,77 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner A523 Clock Control Unit
> +
> +maintainers:
> +  - Andre Przywara <andre.przywara at arm.com>
> +
> +properties:
> +  "#clock-cells":
> +    const: 1
> +
> +  "#reset-cells":
> +    const: 1
> +
> +  compatible:
> +    enum:
> +      - allwinner,sun55i-a523-ccu
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    minItems: 4
> +    maxItems: 4
> +
> +  clock-names:
> +    minItems: 4
> +    maxItems: 4
> +
> +required:
> +  - "#clock-cells"
> +  - "#reset-cells"
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +
> +if:

Put this under an allOf and use another 'if' instead of the 'else' 
clause in the 2nd patch.

> +  properties:
> +    compatible:
> +      enum:
> +        - allwinner,sun55i-a523-ccu
> +
> +then:
> +  properties:
> +    clocks:
> +      items:
> +        - description: High Frequency Oscillator (usually at 24MHz)
> +        - description: Low Frequency Oscillator (usually at 32kHz)
> +        - description: Internal Oscillator
> +        - description: Low Frequency Oscillator fanout
> +
> +    clock-names:
> +      items:
> +        - const: hosc
> +        - const: losc
> +        - const: iosc
> +        - const: losc-fanout
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    ccu: clock at 2001000 {

Drop ccu and it's 'clock-controller' not 'clock'.

> +        compatible = "allwinner,sun55i-a523-ccu";
> +        reg = <0x2001000 0x1000>;
> +        clocks = <&osc24M>, <&osc32k>, <&iosc>, <&r_ccu 2>;
> +        clock-names = "hosc", "losc", "iosc", "losc-fanout";
> +        #clock-cells = <1>;
> +        #reset-cells = <1>;
> +    };
> +
> +...


From robh at kernel.org  Tue Mar  4 06:16:17 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 4 Mar 2025 08:16:17 -0600
Subject: [PATCH v6 01/10] dt-bindings: mfd: brcm,bcm59056: Convert to YAML
In-Reply-To: <20250304-bcm59054-v6-1-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-1-ae8302358443@gmail.com>
Message-ID: <174109777678.2543384.14004490230937287192.robh@kernel.org>


On Tue, 04 Mar 2025 07:20:32 +0100, Artur Weber wrote:
> Convert devicetree bindings for the Broadcom BCM59056 PMU MFD from
> TXT to YAML format. This patch does not change any functionality;
> the bindings remain the same.
> 
> The bindings have been split into two parts: the MFD binding and
> a separate binding for the regulator node, to simplify the addition
> of other models later (which have different regulators).
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---
> Changes in v6:
> - Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml
> 
> Changes in v5:
> - Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
>   regulator binding description
> 
> Changes in v4:
> - Made $ref use full schema path
> - Cleaned up example
> - Dropped regulator name list comment
> - Changed description of regulator binding to mention BCM59056
>   explicitly
> - Changed "Power Management IC" to "Power Management Unit" to match
>   official Broadcom naming
> - Renamed mfd/brcm,bcm59056.yaml to mfd/brcm,bcm590xx.yaml
> 
> Changes in v3:
> - Moved regulator node to separate binding
> - Removed quotes around compatibles/vbus property
> - Style fixes for example
> ---
>  .../devicetree/bindings/mfd/brcm,bcm59056.txt      | 39 ----------------
>  .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 54 ++++++++++++++++++++++
>  .../bindings/regulator/brcm,bcm59056.yaml          | 51 ++++++++++++++++++++
>  3 files changed, 105 insertions(+), 39 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar  4 06:19:33 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 08:19:33 -0600
Subject: [PATCH v6 02/10] dt-bindings: mfd: brcm,bcm59056: Add compatible
 for BCM59054
In-Reply-To: <20250304-bcm59054-v6-2-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-2-ae8302358443@gmail.com>
Message-ID: <20250304141933.GA2543583-robh@kernel.org>

On Tue, Mar 04, 2025 at 07:20:33AM +0100, Artur Weber wrote:
> The BCM59054 MFD is fairly similar to the BCM59056, and will use
> the same driver. Add compatible and specify the allowed regulator
> nodes.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---
> Changes in v6:
> - Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml
> 
> Changes in v5:
> - Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
>   regulator bindings description
> 
> Changes in v4:
> - Fix yamllint errors (missing unevaluatedProperties)
> - Drop comment with regulator name list
> - Use full schema paths for $reg
> - Change description of regulator binding to mention BCM59054
>   explicitly
> - Drop quotes around vbus reg name
> - Change "Power Management IC" to "Power Management Unit" to match
>   official Broadcom naming
> 
> Note that I did not end up moving the regulator refs from
> allOf compatible matches; I explained my reasoning in [1].
> 
> [1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/
> 
> Changes in v3:
> - Split regulator node into separate file
> - Removed quotes around compatible
> ---
>  .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 26 +++++++++-
>  .../bindings/regulator/brcm,bcm59054.yaml          | 56 ++++++++++++++++++++++
>  2 files changed, 80 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
> index b387ef9885c3ac524e0782545dbca9c0e81a556c..b67d7a723fc242869e5bdc6b3602785f62af45bd 100644
> --- a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
> +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
> @@ -11,7 +11,9 @@ maintainers:
>  
>  properties:
>    compatible:
> -    const: brcm,bcm59056
> +    enum:
> +      - brcm,bcm59054
> +      - brcm,bcm59056
>  
>    reg:
>      maxItems: 1
> @@ -21,7 +23,6 @@ properties:
>  
>    regulators:
>      type: object
> -    $ref: /schemas/regulator/brcm,bcm59056.yaml#

Just do:

additionalProperties: true
properties:
  compatible:
    contains:
      enum:
        - brcm,bcm59056
        - brcm,bcm59054

(This patch should just add the last line)

And drop the allOf below.

>  
>  required:
>    - compatible
> @@ -30,6 +31,27 @@ required:
>  
>  additionalProperties: false
>  
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: brcm,bcm59054
> +    then:
> +      properties:
> +        regulators:
> +          $ref: /schemas/regulator/brcm,bcm59054.yaml#
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: brcm,bcm59056
> +    then:
> +      properties:
> +        regulators:
> +          $ref: /schemas/regulator/brcm,bcm59056.yaml#
> +
>  examples:
>    - |
>      #include <dt-bindings/interrupt-controller/arm-gic.h>


From broonie at kernel.org  Tue Mar  4 06:20:46 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 04 Mar 2025 14:20:46 +0000
Subject: [PATCH] ASoC: mediatek: mt6359: Fix DT parse error due to
 wrong child node name
In-Reply-To: <20250228-mt6359-fix-probe-failed-v1-1-64941d387b2c@collabora.com>
References: <20250228-mt6359-fix-probe-failed-v1-1-64941d387b2c@collabora.com>
Message-ID: <174109804670.69310.9373110369182366922.b4-ty@kernel.org>

On Fri, 28 Feb 2025 11:32:19 +0100, Louis-Alexis Eyraud wrote:
> A recent dtbs_check error fix in mt6359.dtsi file changed a node name
> (from "mt6359codec" to "audio-codec") without modifying the mt6539
> codec code that uses it.
> It leads to a probe failure after devicetree parsing returns in error:
> ```
> [    1.354025] mt6359-sound mt6359-sound: mt6359_platform_driver_probe() failed to parse dts
> [    1.355066] mt6359-sound mt6359-sound: probe with driver mt6359-sound failed with error -22
> ```
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: mediatek: mt6359: Fix DT parse error due to wrong child node name
      commit: 79c080c75cdd0a5ba38be039f6f9bb66ec53b0c4

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From krzysztof.kozlowski at linaro.org  Tue Mar  4 06:25:25 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 15:25:25 +0100
Subject: [PATCH 1/2] arm64: dts: rockchip: Add ES8388 audio codec fallback
 on RK3399 ROC PC PLUS
In-Reply-To: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
References: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
Message-ID: <2b8f2c5c-eb06-462a-8fbc-9eb28866f49c@linaro.org>

On 04/03/2025 11:41, Krzysztof Kozlowski wrote:
> Devicetree bindings for ES8388 audio codec expect the device to be
> marked as compatible with ES8328.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> ---
> 
> Changeset depends on bindings patch being accepted to ASoC:
> https://lore.kernel.org/all/20250304103808.75236-1-krzysztof.kozlowski at linaro.org/
> 
> Please take it to the same or next merge cycle as above ASoC binding.

Binding was accepted by Mark to ASoC, so this can go for this cycle as well.

Best regards,
Krzysztof


From jgg at ziepe.ca  Tue Mar  4 06:26:34 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Tue, 4 Mar 2025 10:26:34 -0400
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250303190330.GA426248@e133081.arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com>
 <20250303165255.GS5011@ziepe.ca>
 <20250303190330.GA426248@e133081.arm.com>
Message-ID: <20250304142634.GC5011@ziepe.ca>

On Mon, Mar 03, 2025 at 07:03:42PM +0000, Miko?aj Lenczewski wrote:

> For example, if we use BBML2 for kernel mappings, does that require us
> to repaint all kernel mappings when disabling BBML2 on smmu attach? I
> am not sure, but definitely something to be worked out.

No, it would be a per-mm_struct basis only if we did something like
that

When the SMMU driver puts a SVA on top of the mm_struct it would
disable BBML2 usage only for that mm_struct and it's contained VMAs.

Kernel mappings are never made into a SVA so are not effected.
Userspace only.

Jason


From arnd at kernel.org  Tue Mar  4 06:27:59 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Tue,  4 Mar 2025 15:27:59 +0100
Subject: [PATCH] pmdomain: rockchip: add regulator dependency
Message-ID: <20250304142803.689201-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

When CONFIG_REGULATOR is disabled, this pmdomain driver fails to build:

drivers/pmdomain/rockchip/pm-domains.c:653:30: error: implicit declaration of function 'devm_of_regulator_get'; did you mean 'devm_regulator_get'? [-Wimplicit-function-declaration]
  653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
      |                              ^~~~~~~~~~~~~~~~~~~~~
      |                              devm_regulator_get
drivers/pmdomain/rockchip/pm-domains.c:653:28: error: assignment to 'struct regulator *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
  653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
      |                            ^

Add a Kconfig dependency.

Fixes: db6df2e3fc16 ("pmdomain: rockchip: add regulator support")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/pmdomain/rockchip/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pmdomain/rockchip/Kconfig b/drivers/pmdomain/rockchip/Kconfig
index 7e4f9b628f0b..218d43186e5b 100644
--- a/drivers/pmdomain/rockchip/Kconfig
+++ b/drivers/pmdomain/rockchip/Kconfig
@@ -5,6 +5,7 @@ config ROCKCHIP_PM_DOMAINS
 	bool "Rockchip generic power domain"
 	depends on PM
 	depends on HAVE_ARM_SMCCC_DISCOVERY
+	depends on REGULATOR
 	select PM_GENERIC_DOMAINS
 	help
 	  Say y here to enable power domain support.
-- 
2.39.5



From sebastian.reichel at collabora.com  Tue Mar  4 06:31:37 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Tue, 4 Mar 2025 15:31:37 +0100
Subject: [PATCH] pmdomain: rockchip: add regulator dependency
In-Reply-To: <20250304142803.689201-1-arnd@kernel.org>
References: <20250304142803.689201-1-arnd@kernel.org>
Message-ID: <2g5p6ucwp55zuisupqx6dglikmbm5rqy3yl34mqobs3giucfqe@um6uhmglxhex>

Hi,

On Tue, Mar 04, 2025 at 03:27:59PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> When CONFIG_REGULATOR is disabled, this pmdomain driver fails to build:
> 
> drivers/pmdomain/rockchip/pm-domains.c:653:30: error: implicit declaration of function 'devm_of_regulator_get'; did you mean 'devm_regulator_get'? [-Wimplicit-function-declaration]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                              ^~~~~~~~~~~~~~~~~~~~~
>       |                              devm_regulator_get
> drivers/pmdomain/rockchip/pm-domains.c:653:28: error: assignment to 'struct regulator *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                            ^
> 
> Add a Kconfig dependency.
> 
> Fixes: db6df2e3fc16 ("pmdomain: rockchip: add regulator support")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

-- Sebastian

>  drivers/pmdomain/rockchip/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pmdomain/rockchip/Kconfig b/drivers/pmdomain/rockchip/Kconfig
> index 7e4f9b628f0b..218d43186e5b 100644
> --- a/drivers/pmdomain/rockchip/Kconfig
> +++ b/drivers/pmdomain/rockchip/Kconfig
> @@ -5,6 +5,7 @@ config ROCKCHIP_PM_DOMAINS
>  	bool "Rockchip generic power domain"
>  	depends on PM
>  	depends on HAVE_ARM_SMCCC_DISCOVERY
> +	depends on REGULATOR
>  	select PM_GENERIC_DOMAINS
>  	help
>  	  Say y here to enable power domain support.
> -- 
> 2.39.5
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/85b4353a/attachment.sig>

From heiko at sntech.de  Tue Mar  4 06:34:40 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 15:34:40 +0100
Subject: [PATCH 1/2] arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3399 ROC PC PLUS
In-Reply-To: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
References: <20250304104200.76178-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174109881585.132749.2987468837584062976.b4-ty@sntech.de>


On Tue, 04 Mar 2025 11:41:59 +0100, Krzysztof Kozlowski wrote:
> Devicetree bindings for ES8388 audio codec expect the device to be
> marked as compatible with ES8328.
> 
> 

Applied, thanks!

[1/2] arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3399 ROC PC PLUS
      commit: d83f6c32d70f96037cb187e63785e7a58f9e751b
[2/2] arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3588 boards
      commit: ced36c336d241eafbc812fed27e6a52908d249bb

Thanks for the heads up Krzysztof, about the asoc patches getting accepted
for 6.15.


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From tabba at google.com  Tue Mar  4 06:36:19 2025
From: tabba at google.com (Fuad Tabba)
Date: Tue, 4 Mar 2025 14:36:19 +0000
Subject: [PATCH 03/18] KVM: arm64: Handle trapping of FEAT_LS64* instructions
In-Reply-To: <20250210184150.2145093-4-maz@kernel.org>
References: <20250210184150.2145093-1-maz@kernel.org> <20250210184150.2145093-4-maz@kernel.org>
Message-ID: <CA+EHjTwkX+sy1wuS8LvGM+=m_S-h-=xUUXOyMapnoLiHt0XpOw@mail.gmail.com>

Hi Marc,

On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
>
> We generally don't expect FEAT_LS64* instructions to trap, unless
> they are trapped by a guest hypervisor.
>
> Otherwise, this is just the guest playing tricks on us by using
> an instruction that isn't advertised, which we handle with a well
> deserved UNDEF.
>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  arch/arm64/kvm/handle_exit.c | 64 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 512d152233ff2..4f8354bf7dc5f 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -294,6 +294,69 @@ static int handle_svc(struct kvm_vcpu *vcpu)
>         return 1;
>  }
>
> +static int handle_ls64b(struct kvm_vcpu *vcpu)
> +{
> +       struct kvm *kvm = vcpu->kvm;
> +       u64 esr = kvm_vcpu_get_esr(vcpu);
> +       u64 iss = ESR_ELx_ISS(esr);
> +       bool allowed;
> +
> +       switch (iss) {
> +       case ESR_ELx_ISS_ST64BV:
> +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
> +               break;
> +       case ESR_ELx_ISS_ST64BV0:
> +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
> +               break;
> +       case ESR_ELx_ISS_LDST64B:
> +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
> +               break;
> +       default:
> +               /* Clearly, we're missing something. */
> +               goto unknown_trap;
> +       }
> +
> +       if (!allowed)
> +               goto undef;
> +
> +       if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
> +               u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
> +               bool fwd;
> +
> +               switch (iss) {
> +               case ESR_ELx_ISS_ST64BV:
> +                       fwd = !(hcrx & HCRX_EL2_EnASR);
> +                       break;
> +               case ESR_ELx_ISS_ST64BV0:
> +                       fwd = !(hcrx & HCRX_EL2_EnAS0);
> +                       break;
> +               case ESR_ELx_ISS_LDST64B:
> +                       fwd = !(hcrx & HCRX_EL2_EnALS);
> +                       break;
> +               default:
> +                       /* We don't expect to be here */
> +                       fwd = false;
> +               }
> +
> +               if (fwd) {
> +                       kvm_inject_nested_sync(vcpu, esr);
> +                       return 1;
> +               }
> +       }
> +
> +unknown_trap:
> +       /*
> +        * If we land here, something must be very wrong, because we
> +        * have no idea why we trapped at all. Warn and undef as a
> +        * fallback.
> +        */
> +       WARN_ON(1);

nit: should this be WARN_ONCE() instead?

> +
> +undef:
> +       kvm_inject_undefined(vcpu);
> +       return 1;
> +}

I'm wondering if this can be simplified by having one switch()
statement that toggles both allowed and fwd (or maybe even only fwd),
and then inject depending on that, e.g.,

+static int handle_ls64b(struct kvm_vcpu *vcpu)
+{
+    struct kvm *kvm = vcpu->kvm;
+    bool is_nv = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
+    u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
+    u64 esr = kvm_vcpu_get_esr(vcpu);
+    u64 iss = ESR_ELx_ISS(esr);
+    bool fwd = false;
+
+    switch (iss) {
+    case ESR_ELx_ISS_ST64BV:
+         fwd = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V) &&
+                   !(hcrx & HCRX_EL2_EnASR)
+         break;
...
+    default:
+        WARN_ONCE(1);
+ }
+
+    if (is_nv && fwd) {
+        kvm_inject_nested_sync(vcpu, esr);
+    else
+        kvm_inject_undefined(vcpu);
+
+    return 1;
+}

I think this has the same effect as the code above.

Cheers,
/fuad



> +
>  static exit_handle_fn arm_exit_handlers[] = {
>         [0 ... ESR_ELx_EC_MAX]  = kvm_handle_unknown_ec,
>         [ESR_ELx_EC_WFx]        = kvm_handle_wfx,
> @@ -303,6 +366,7 @@ static exit_handle_fn arm_exit_handlers[] = {
>         [ESR_ELx_EC_CP14_LS]    = kvm_handle_cp14_load_store,
>         [ESR_ELx_EC_CP10_ID]    = kvm_handle_cp10_id,
>         [ESR_ELx_EC_CP14_64]    = kvm_handle_cp14_64,
> +       [ESR_ELx_EC_LS64B]      = handle_ls64b,
>         [ESR_ELx_EC_HVC32]      = handle_hvc,
>         [ESR_ELx_EC_SMC32]      = handle_smc,
>         [ESR_ELx_EC_HVC64]      = handle_hvc,
> --
> 2.39.2
>


From ping.bai at nxp.com  Tue Mar  4 06:40:31 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue, 4 Mar 2025 14:40:31 +0000
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <20250304131314.GA2441686-robh@kernel.org>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
 <20250304131314.GA2441686-robh@kernel.org>
Message-ID: <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>

Hi Rob,

> Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
> interrupts-extended property
> 
> On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> > Add interrupts-extended property for edma that has multiple interrupt
> > controllers used.
> 
> Did you try using interrupts-extended? No. Because either is supported by the
> tools already.
> 

We need to use interrupts-extended property for i.MX94 because for the edma's
interrupts, some are connected to irqsteer interrupt controller and some are connected
to the GIC. make dtbs_check report error, so I add this dt binding changes.

Sorry, Which tools are you referring?

> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - newly added entry
> > ---
> >  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11
> ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > index d54140f18d34..549afb8611a9 100644
> > --- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > @@ -38,6 +38,10 @@ properties:
> >      minItems: 1
> >      maxItems: 64
> >
> > +  interrupts-extended:
> > +    minItems: 1
> > +    maxItems: 65
> 
> Doesn't match the size for interrupt-names:
> 

The interrupt-names are only true for vf610, maxItems is
enough for such case. do we still need to update it? 

> > +
> >    interrupt-names:
> >      minItems: 1
> >      maxItems: 64


From maxime.chevallier at bootlin.com  Tue Mar  4 06:43:30 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Tue, 4 Mar 2025 15:43:30 +0100
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <20250303090321.805785-10-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
	<20250303090321.805785-10-maxime.chevallier@bootlin.com>
Message-ID: <20250304154330.6e00961b@fedora.home>

Hi,

On Mon,  3 Mar 2025 10:03:15 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> When phylink creates a fixed-link configuration, it finds a matching
> linkmode to set as the advertised, lp_advertising and supported modes
> based on the speed and duplex of the fixed link.
> 
> Use the newly introduced phy_caps_lookup to get these modes instead of
> phy_lookup_settings(). This has the side effect that the matched
> settings and configured linkmodes may now contain several linkmodes (the
> intersection of supported linkmodes from the phylink settings and the
> linkmodes that match speed/duplex) instead of the one from
> phy_lookup_settings().
> 
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---

Maybe before anything goes further with this patch, I'd like to get
some feedback from it on a particular point. This changes the linkmodes
that are reported on fixed-link interfaces. Instead of reporting one
single mode, we report all modes supported by the fixed-link' speed and
duplex settings.

The following example is a before/after of the "ethtool ethX" output on
a 1G fixed link :

Before this patch :

	Settings for eth0:
	Supported ports: [ MII ]
	Supported link modes:   1000baseT/Full 
	Supported pause frame use: Symmetric
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  Not reported
	Advertised pause frame use: No
	Advertised auto-negotiation: No
	Advertised FEC modes: Not reported
	Speed: Unknown!
	Duplex: Half
	Port: MII
	PHYAD: 0
	Transceiver: internal
	Auto-negotiation: off
	Supports Wake-on: d
	Wake-on: d
	Link detected: no

After :

	Supported ports: [ MII ]
	Supported link modes:   1000baseT/Full 
	                        1000baseKX/Full 
	                        1000baseX/Full 
	                        1000baseT1/Full 
	Supported pause frame use: Symmetric
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  Not reported
	Advertised pause frame use: No
	Advertised auto-negotiation: No
	Advertised FEC modes: Not reported
	Speed: Unknown!
	Duplex: Half
	Port: MII
	PHYAD: 0
	Transceiver: internal
	Auto-negotiation: off
	Supports Wake-on: d
	Wake-on: d
	Link detected: no

The fixed-link in question is for the CPU port of a DSA switch.

In my opinion, this is OK as the linkmodes expressed here don't match
physical linkmodes on an actual wire, but as this is a user visible
change, I'd like to make sure this is OK. Any comment here is more than
welcome.

Maxime

> V4: Remove unnecessary linklmode_zero in phylink_set_fixed_link(),
> follwing Russell's comment
> 
>  drivers/net/phy/phylink.c | 27 +++++++++++++++------------
>  1 file changed, 15 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 6c67d5c9b787..0b9585cb508e 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -805,9 +805,10 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
>  static int phylink_parse_fixedlink(struct phylink *pl,
>  				   const struct fwnode_handle *fwnode)
>  {
> +	__ETHTOOL_DECLARE_LINK_MODE_MASK(match) = { 0, };
>  	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
> +	const struct link_capabilities *c;
>  	struct fwnode_handle *fixed_node;
> -	const struct phy_setting *s;
>  	struct gpio_desc *desc;
>  	u32 speed;
>  	int ret;
> @@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
>  	linkmode_copy(pl->link_config.advertising, pl->supported);
>  	phylink_validate(pl, pl->supported, &pl->link_config);
>  
> -	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
> -			       pl->supported, true);
> +	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
> +			    pl->supported, true);
> +	if (c)
> +		linkmode_and(match, pl->supported, c->linkmodes);
>  
>  	linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask);
>  	linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask);
> @@ -889,9 +892,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
>  
>  	phylink_set(pl->supported, MII);
>  
> -	if (s) {
> -		__set_bit(s->bit, pl->supported);
> -		__set_bit(s->bit, pl->link_config.lp_advertising);
> +	if (c) {
> +		linkmode_or(pl->supported, pl->supported, match);
> +		linkmode_or(pl->link_config.lp_advertising,
> +			    pl->link_config.lp_advertising, match);
>  	} else {
>  		phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n",
>  			     pl->link_config.duplex == DUPLEX_FULL ? "full" : "half",
> @@ -1879,21 +1883,20 @@ static int phylink_register_sfp(struct phylink *pl,
>  int phylink_set_fixed_link(struct phylink *pl,
>  			   const struct phylink_link_state *state)
>  {
> -	const struct phy_setting *s;
> +	const struct link_capabilities *c;
>  	unsigned long *adv;
>  
>  	if (pl->cfg_link_an_mode != MLO_AN_PHY || !state ||
>  	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
>  		return -EINVAL;
>  
> -	s = phy_lookup_setting(state->speed, state->duplex,
> -			       pl->supported, true);
> -	if (!s)
> +	c = phy_caps_lookup(state->speed, state->duplex,
> +			    pl->supported, true);
> +	if (!c)
>  		return -EINVAL;
>  
>  	adv = pl->link_config.advertising;
> -	linkmode_zero(adv);
> -	linkmode_set_bit(s->bit, adv);
> +	linkmode_and(adv, pl->supported, c->linkmodes);
>  	linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv);
>  
>  	pl->link_config.speed = state->speed;



From arnd at kernel.org  Tue Mar  4 06:43:34 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Tue,  4 Mar 2025 15:43:34 +0100
Subject: [PATCH] firmware: arm_scmi: use ioread64() instead of ioread64_hi_lo()
Message-ID: <20250304144346.1025658-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

The scmi_common_fastchannel_db_ring() function calls either ioread64()
or ioread64_hi_lo() depending on whether it is compiler for 32-bit
or 64-bit architectures.

The same logic is used to define ioread64() itself in the
linux/io-64-nonatomic-hi-lo.h header file, so the special case
is not really needed.

The behavior here should not change at all.

Fixes: 6f9ea4dabd2d ("firmware: arm_scmi: Generalize the fast channel support")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/firmware/arm_scmi/driver.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 60050da54bf2..1c75a4c9c371 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1997,17 +1997,7 @@ static void scmi_common_fastchannel_db_ring(struct scmi_fc_db_info *db)
 	else if (db->width == 4)
 		SCMI_PROTO_FC_RING_DB(32);
 	else /* db->width == 8 */
-#ifdef CONFIG_64BIT
 		SCMI_PROTO_FC_RING_DB(64);
-#else
-	{
-		u64 val = 0;
-
-		if (db->mask)
-			val = ioread64_hi_lo(db->addr) & db->mask;
-		iowrite64_hi_lo(db->set | val, db->addr);
-	}
-#endif
 }
 
 /**
-- 
2.39.5



From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:04:48 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:34:48 +0530
Subject: [PATCH v2 5/8] PCI: brcmstb: Fix potential premature regulator
 disabling
In-Reply-To: <20250214173944.47506-6-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-6-james.quinlan@broadcom.com>
Message-ID: <20250304150448.r42maovz4xggbqdx@thinkpad>

On Fri, Feb 14, 2025 at 12:39:33PM -0500, Jim Quinlan wrote:
> Our system for enabling and disabling regulators is designed to work only

'system'? Perhaps 'logic'?

> on the port driver below the root complex.  The conditions to discriminate
> for this case should be the same when we are adding or removing the bus.
> Without this change the regulators may be disabled prematurely when a bus
> further down the tree is removed.
> 
> Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 56b49d3cae19..e1059e3365bd 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -1440,7 +1440,7 @@ static void brcm_pcie_remove_bus(struct pci_bus *bus)
>  	struct subdev_regulators *sr = pcie->sr;
>  	struct device *dev = &bus->dev;
>  
> -	if (!sr)
> +	if (!sr || !bus->parent || !pci_is_root_bus(bus->parent))
>  		return;
>  
>  	if (regulator_bulk_disable(sr->num_supplies, sr->supplies))
> -- 
> 2.43.0
> 

-- 
????????? ????????


From ryan.roberts at arm.com  Tue Mar  4 07:04:32 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:32 +0000
Subject: [PATCH v3 02/11] arm64: hugetlb: Refine tlb maintenance scope
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-3-ryan.roberts@arm.com>

When operating on contiguous blocks of ptes (or pmds) for some hugetlb
sizes, we must honour break-before-make requirements and clear down the
block to invalid state in the pgtable then invalidate the relevant tlb
entries before making the pgtable entries valid again.

However, the tlb maintenance is currently always done assuming the worst
case stride (PAGE_SIZE), last_level (false) and tlb_level
(TLBI_TTL_UNKNOWN). We can do much better with the hinting; In reality,
we know the stride from the huge_pte pgsize, we are always operating
only on the last level, and we always know the tlb_level, again based on
pgsize. So let's start providing these hints.

Additionally, avoid tlb maintenace in set_huge_pte_at().
Break-before-make is only required if we are transitioning the
contiguous pte block from valid -> valid. So let's elide the
clear-and-flush ("break") if the pte range was previously invalid.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/include/asm/hugetlb.h | 29 +++++++++++++++++++----------
 arch/arm64/mm/hugetlbpage.c      |  9 ++++++---
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 07fbf5bf85a7..2a8155c4a882 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -69,29 +69,38 @@ extern void huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
 
 #include <asm-generic/hugetlb.h>
 
-#define __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
-static inline void flush_hugetlb_tlb_range(struct vm_area_struct *vma,
-					   unsigned long start,
-					   unsigned long end)
+static inline void __flush_hugetlb_tlb_range(struct vm_area_struct *vma,
+					     unsigned long start,
+					     unsigned long end,
+					     unsigned long stride,
+					     bool last_level)
 {
-	unsigned long stride = huge_page_size(hstate_vma(vma));
-
 	switch (stride) {
 #ifndef __PAGETABLE_PMD_FOLDED
 	case PUD_SIZE:
-		__flush_tlb_range(vma, start, end, PUD_SIZE, false, 1);
+		__flush_tlb_range(vma, start, end, PUD_SIZE, last_level, 1);
 		break;
 #endif
 	case CONT_PMD_SIZE:
 	case PMD_SIZE:
-		__flush_tlb_range(vma, start, end, PMD_SIZE, false, 2);
+		__flush_tlb_range(vma, start, end, PMD_SIZE, last_level, 2);
 		break;
 	case CONT_PTE_SIZE:
-		__flush_tlb_range(vma, start, end, PAGE_SIZE, false, 3);
+		__flush_tlb_range(vma, start, end, PAGE_SIZE, last_level, 3);
 		break;
 	default:
-		__flush_tlb_range(vma, start, end, PAGE_SIZE, false, TLBI_TTL_UNKNOWN);
+		__flush_tlb_range(vma, start, end, PAGE_SIZE, last_level, TLBI_TTL_UNKNOWN);
 	}
 }
 
+#define __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
+static inline void flush_hugetlb_tlb_range(struct vm_area_struct *vma,
+					   unsigned long start,
+					   unsigned long end)
+{
+	unsigned long stride = huge_page_size(hstate_vma(vma));
+
+	__flush_hugetlb_tlb_range(vma, start, end, stride, false);
+}
+
 #endif /* __ASM_HUGETLB_H */
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 6a2af9fb2566..065be8650aa5 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -183,8 +183,9 @@ static pte_t get_clear_contig_flush(struct mm_struct *mm,
 {
 	pte_t orig_pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
 	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+	unsigned long end = addr + (pgsize * ncontig);
 
-	flush_tlb_range(&vma, addr, addr + (pgsize * ncontig));
+	__flush_hugetlb_tlb_range(&vma, addr, end, pgsize, true);
 	return orig_pte;
 }
 
@@ -209,7 +210,7 @@ static void clear_flush(struct mm_struct *mm,
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
 		__ptep_get_and_clear(mm, addr, ptep);
 
-	flush_tlb_range(&vma, saddr, addr);
+	__flush_hugetlb_tlb_range(&vma, saddr, addr, pgsize, true);
 }
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -238,7 +239,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	dpfn = pgsize >> PAGE_SHIFT;
 	hugeprot = pte_pgprot(pte);
 
-	clear_flush(mm, addr, ptep, pgsize, ncontig);
+	/* Only need to "break" if transitioning valid -> valid. */
+	if (pte_valid(__ptep_get(ptep)))
+		clear_flush(mm, addr, ptep, pgsize, ncontig);
 
 	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
 		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:34 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:34 +0000
Subject: [PATCH v3 04/11] arm64/mm: Refactor __set_ptes() and __ptep_get_and_clear()
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-5-ryan.roberts@arm.com>

Refactor __set_ptes(), set_pmd_at() and set_pud_at() so that they are
all a thin wrapper around a new common set_ptes_anysz(), which takes
pgsize parameter. Additionally, refactor __ptep_get_and_clear() and
pmdp_huge_get_and_clear() to use a new common ptep_get_and_clear_anysz()
which also takes a pgsize parameter.

These changes will permit the huge_pte API to efficiently batch-set
pgtable entries and take advantage of the future barrier optimizations.
Additionally since the new *_anysz() helpers call the correct
page_table_check_*_set() API based on pgsize, this means that huge_ptes
will be able to get proper coverage. Currently the huge_pte API always
uses the pte API which assumes an entry only covers a single page.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 108 +++++++++++++++++++------------
 1 file changed, 67 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 0b2a2ad1b9e8..e255a36380dc 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -420,23 +420,6 @@ static inline pte_t pte_advance_pfn(pte_t pte, unsigned long nr)
 	return pfn_pte(pte_pfn(pte) + nr, pte_pgprot(pte));
 }
 
-static inline void __set_ptes(struct mm_struct *mm,
-			      unsigned long __always_unused addr,
-			      pte_t *ptep, pte_t pte, unsigned int nr)
-{
-	page_table_check_ptes_set(mm, ptep, pte, nr);
-	__sync_cache_and_tags(pte, nr);
-
-	for (;;) {
-		__check_safe_pte_update(mm, ptep, pte);
-		__set_pte(ptep, pte);
-		if (--nr == 0)
-			break;
-		ptep++;
-		pte = pte_advance_pfn(pte, 1);
-	}
-}
-
 /*
  * Hugetlb definitions.
  */
@@ -641,30 +624,59 @@ static inline pgprot_t pud_pgprot(pud_t pud)
 	return __pgprot(pud_val(pfn_pud(pfn, __pgprot(0))) ^ pud_val(pud));
 }
 
-static inline void __set_pte_at(struct mm_struct *mm,
-				unsigned long __always_unused addr,
-				pte_t *ptep, pte_t pte, unsigned int nr)
+static inline void set_ptes_anysz(struct mm_struct *mm, pte_t *ptep, pte_t pte,
+				  unsigned int nr, unsigned long pgsize)
 {
-	__sync_cache_and_tags(pte, nr);
-	__check_safe_pte_update(mm, ptep, pte);
-	__set_pte(ptep, pte);
+	unsigned long stride = pgsize >> PAGE_SHIFT;
+
+	switch (pgsize) {
+	case PAGE_SIZE:
+		page_table_check_ptes_set(mm, ptep, pte, nr);
+		break;
+	case PMD_SIZE:
+		page_table_check_pmds_set(mm, (pmd_t *)ptep, pte_pmd(pte), nr);
+		break;
+	case PUD_SIZE:
+		page_table_check_puds_set(mm, (pud_t *)ptep, pte_pud(pte), nr);
+		break;
+	default:
+		VM_WARN_ON(1);
+	}
+
+	__sync_cache_and_tags(pte, nr * stride);
+
+	for (;;) {
+		__check_safe_pte_update(mm, ptep, pte);
+		__set_pte(ptep, pte);
+		if (--nr == 0)
+			break;
+		ptep++;
+		pte = pte_advance_pfn(pte, stride);
+	}
 }
 
-static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
-			      pmd_t *pmdp, pmd_t pmd)
+static inline void __set_ptes(struct mm_struct *mm,
+			      unsigned long __always_unused addr,
+			      pte_t *ptep, pte_t pte, unsigned int nr)
 {
-	page_table_check_pmd_set(mm, pmdp, pmd);
-	return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd),
-						PMD_SIZE >> PAGE_SHIFT);
+	set_ptes_anysz(mm, ptep, pte, nr, PAGE_SIZE);
 }
 
-static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
-			      pud_t *pudp, pud_t pud)
+static inline void __set_pmds(struct mm_struct *mm,
+			      unsigned long __always_unused addr,
+			      pmd_t *pmdp, pmd_t pmd, unsigned int nr)
+{
+	set_ptes_anysz(mm, (pte_t *)pmdp, pmd_pte(pmd), nr, PMD_SIZE);
+}
+#define set_pmd_at(mm, addr, pmdp, pmd) __set_pmds(mm, addr, pmdp, pmd, 1)
+
+static inline void __set_puds(struct mm_struct *mm,
+			      unsigned long __always_unused addr,
+			      pud_t *pudp, pud_t pud, unsigned int nr)
 {
-	page_table_check_pud_set(mm, pudp, pud);
-	return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud),
-						PUD_SIZE >> PAGE_SHIFT);
+	set_ptes_anysz(mm, (pte_t *)pudp, pud_pte(pud), nr, PUD_SIZE);
 }
+#define set_pud_at(mm, addr, pudp, pud) __set_puds(mm, addr, pudp, pud, 1)
 
 #define __p4d_to_phys(p4d)	__pte_to_phys(p4d_pte(p4d))
 #define __phys_to_p4d_val(phys)	__phys_to_pte_val(phys)
@@ -1276,16 +1288,34 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */
 
-static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pte_t *ptep)
+static inline pte_t ptep_get_and_clear_anysz(struct mm_struct *mm, pte_t *ptep,
+					     unsigned long pgsize)
 {
 	pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0));
 
-	page_table_check_pte_clear(mm, pte);
+	switch (pgsize) {
+	case PAGE_SIZE:
+		page_table_check_pte_clear(mm, pte);
+		break;
+	case PMD_SIZE:
+		page_table_check_pmd_clear(mm, pte_pmd(pte));
+		break;
+	case PUD_SIZE:
+		page_table_check_pud_clear(mm, pte_pud(pte));
+		break;
+	default:
+		VM_WARN_ON(1);
+	}
 
 	return pte;
 }
 
+static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
+				       unsigned long address, pte_t *ptep)
+{
+	return ptep_get_and_clear_anysz(mm, ptep, PAGE_SIZE);
+}
+
 static inline void __clear_full_ptes(struct mm_struct *mm, unsigned long addr,
 				pte_t *ptep, unsigned int nr, int full)
 {
@@ -1322,11 +1352,7 @@ static inline pte_t __get_and_clear_full_ptes(struct mm_struct *mm,
 static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
 					    unsigned long address, pmd_t *pmdp)
 {
-	pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0));
-
-	page_table_check_pmd_clear(mm, pmd);
-
-	return pmd;
+	return pte_pmd(ptep_get_and_clear_anysz(mm, (pte_t *)pmdp, PMD_SIZE));
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:35 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:35 +0000
Subject: [PATCH v3 05/11] arm64: hugetlb: Use set_ptes_anysz() and ptep_get_and_clear_anysz()
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-6-ryan.roberts@arm.com>

Refactor the huge_pte helpers to use the new common set_ptes_anysz() and
ptep_get_and_clear_anysz() APIs.

This provides 2 benefits; First, when page_table_check=on, hugetlb is
now properly/fully checked. Previously only the first page of a hugetlb
folio was checked. Second, instead of having to call __set_ptes(nr=1)
for each pte in a loop, the whole contiguous batch can now be set in one
go, which enables some efficiencies and cleans up the code.

One detail to note is that huge_ptep_clear_flush() was previously
calling ptep_clear_flush() for a non-contiguous pte (i.e. a pud or pmd
block mapping). This has a couple of disadvantages; first
ptep_clear_flush() calls ptep_get_and_clear() which transparently
handles contpte. Given we only call for non-contiguous ptes, it would be
safe, but a waste of effort. It's preferable to go straight to the layer
below. However, more problematic is that ptep_get_and_clear() is for
PAGE_SIZE entries so it calls page_table_check_pte_clear() and would not
clear the whole hugetlb folio. So let's stop special-casing the non-cont
case and just rely on get_clear_contig_flush() to do the right thing for
non-cont entries.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/mm/hugetlbpage.c | 52 +++++++------------------------------
 1 file changed, 10 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 065be8650aa5..efd18bd1eae3 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -159,12 +159,12 @@ static pte_t get_clear_contig(struct mm_struct *mm,
 	pte_t pte, tmp_pte;
 	bool present;
 
-	pte = __ptep_get_and_clear(mm, addr, ptep);
+	pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
 	present = pte_present(pte);
 	while (--ncontig) {
 		ptep++;
 		addr += pgsize;
-		tmp_pte = __ptep_get_and_clear(mm, addr, ptep);
+		tmp_pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
 		if (present) {
 			if (pte_dirty(tmp_pte))
 				pte = pte_mkdirty(pte);
@@ -208,7 +208,7 @@ static void clear_flush(struct mm_struct *mm,
 	unsigned long i, saddr = addr;
 
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
-		__ptep_get_and_clear(mm, addr, ptep);
+		ptep_get_and_clear_anysz(mm, ptep, pgsize);
 
 	__flush_hugetlb_tlb_range(&vma, saddr, addr, pgsize, true);
 }
@@ -219,32 +219,20 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	size_t pgsize;
 	int i;
 	int ncontig;
-	unsigned long pfn, dpfn;
-	pgprot_t hugeprot;
 
 	ncontig = num_contig_ptes(sz, &pgsize);
 
 	if (!pte_present(pte)) {
 		for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
-			__set_ptes(mm, addr, ptep, pte, 1);
+			set_ptes_anysz(mm, ptep, pte, 1, pgsize);
 		return;
 	}
 
-	if (!pte_cont(pte)) {
-		__set_ptes(mm, addr, ptep, pte, 1);
-		return;
-	}
-
-	pfn = pte_pfn(pte);
-	dpfn = pgsize >> PAGE_SHIFT;
-	hugeprot = pte_pgprot(pte);
-
 	/* Only need to "break" if transitioning valid -> valid. */
-	if (pte_valid(__ptep_get(ptep)))
+	if (pte_cont(pte) && pte_valid(__ptep_get(ptep)))
 		clear_flush(mm, addr, ptep, pgsize, ncontig);
 
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
+	set_ptes_anysz(mm, ptep, pte, ncontig, pgsize);
 }
 
 pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -434,11 +422,9 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 			       unsigned long addr, pte_t *ptep,
 			       pte_t pte, int dirty)
 {
-	int ncontig, i;
+	int ncontig;
 	size_t pgsize = 0;
-	unsigned long pfn = pte_pfn(pte), dpfn;
 	struct mm_struct *mm = vma->vm_mm;
-	pgprot_t hugeprot;
 	pte_t orig_pte;
 
 	VM_WARN_ON(!pte_present(pte));
@@ -447,7 +433,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 		return __ptep_set_access_flags(vma, addr, ptep, pte, dirty);
 
 	ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
-	dpfn = pgsize >> PAGE_SHIFT;
 
 	if (!__cont_access_flags_changed(ptep, pte, ncontig))
 		return 0;
@@ -462,19 +447,14 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 	if (pte_young(orig_pte))
 		pte = pte_mkyoung(pte);
 
-	hugeprot = pte_pgprot(pte);
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
-
+	set_ptes_anysz(mm, ptep, pte, ncontig, pgsize);
 	return 1;
 }
 
 void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     unsigned long addr, pte_t *ptep)
 {
-	unsigned long pfn, dpfn;
-	pgprot_t hugeprot;
-	int ncontig, i;
+	int ncontig;
 	size_t pgsize;
 	pte_t pte;
 
@@ -487,16 +467,11 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 	}
 
 	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
-	dpfn = pgsize >> PAGE_SHIFT;
 
 	pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 	pte = pte_wrprotect(pte);
 
-	hugeprot = pte_pgprot(pte);
-	pfn = pte_pfn(pte);
-
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
+	set_ptes_anysz(mm, ptep, pte, ncontig, pgsize);
 }
 
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -505,13 +480,6 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 	size_t pgsize;
 	int ncontig;
-	pte_t pte;
-
-	pte = __ptep_get(ptep);
-	VM_WARN_ON(!pte_present(pte));
-
-	if (!pte_cont(pte))
-		return ptep_clear_flush(vma, addr, ptep);
 
 	ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
 	return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:33 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:33 +0000
Subject: [PATCH v3 03/11] mm/page_table_check: Batch-check pmds/puds just like ptes
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-4-ryan.roberts@arm.com>

Convert page_table_check_p[mu]d_set(...) to
page_table_check_p[mu]ds_set(..., nr) to allow checking a contiguous set
of pmds/puds in single batch. We retain page_table_check_p[mu]d_set(...)
as macros that call new batch functions with nr=1 for compatibility.

arm64 is about to reorganise its pte/pmd/pud helpers to reuse more code
and to allow the implementation for huge_pte to more efficiently set
ptes/pmds/puds in batches. We need these batch-helpers to make the
refactoring possible.

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 include/linux/page_table_check.h | 30 +++++++++++++++++-----------
 mm/page_table_check.c            | 34 +++++++++++++++++++-------------
 2 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/include/linux/page_table_check.h b/include/linux/page_table_check.h
index 6722941c7cb8..289620d4aad3 100644
--- a/include/linux/page_table_check.h
+++ b/include/linux/page_table_check.h
@@ -19,8 +19,10 @@ void __page_table_check_pmd_clear(struct mm_struct *mm, pmd_t pmd);
 void __page_table_check_pud_clear(struct mm_struct *mm, pud_t pud);
 void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte,
 		unsigned int nr);
-void __page_table_check_pmd_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd);
-void __page_table_check_pud_set(struct mm_struct *mm, pud_t *pudp, pud_t pud);
+void __page_table_check_pmds_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd,
+		unsigned int nr);
+void __page_table_check_puds_set(struct mm_struct *mm, pud_t *pudp, pud_t pud,
+		unsigned int nr);
 void __page_table_check_pte_clear_range(struct mm_struct *mm,
 					unsigned long addr,
 					pmd_t pmd);
@@ -74,22 +76,22 @@ static inline void page_table_check_ptes_set(struct mm_struct *mm,
 	__page_table_check_ptes_set(mm, ptep, pte, nr);
 }
 
-static inline void page_table_check_pmd_set(struct mm_struct *mm, pmd_t *pmdp,
-					    pmd_t pmd)
+static inline void page_table_check_pmds_set(struct mm_struct *mm,
+		pmd_t *pmdp, pmd_t pmd, unsigned int nr)
 {
 	if (static_branch_likely(&page_table_check_disabled))
 		return;
 
-	__page_table_check_pmd_set(mm, pmdp, pmd);
+	__page_table_check_pmds_set(mm, pmdp, pmd, nr);
 }
 
-static inline void page_table_check_pud_set(struct mm_struct *mm, pud_t *pudp,
-					    pud_t pud)
+static inline void page_table_check_puds_set(struct mm_struct *mm,
+		pud_t *pudp, pud_t pud, unsigned int nr)
 {
 	if (static_branch_likely(&page_table_check_disabled))
 		return;
 
-	__page_table_check_pud_set(mm, pudp, pud);
+	__page_table_check_puds_set(mm, pudp, pud, nr);
 }
 
 static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
@@ -129,13 +131,13 @@ static inline void page_table_check_ptes_set(struct mm_struct *mm,
 {
 }
 
-static inline void page_table_check_pmd_set(struct mm_struct *mm, pmd_t *pmdp,
-					    pmd_t pmd)
+static inline void page_table_check_pmds_set(struct mm_struct *mm,
+		pmd_t *pmdp, pmd_t pmd, unsigned int nr)
 {
 }
 
-static inline void page_table_check_pud_set(struct mm_struct *mm, pud_t *pudp,
-					    pud_t pud)
+static inline void page_table_check_puds_set(struct mm_struct *mm,
+		pud_t *pudp, pud_t pud, unsigned int nr)
 {
 }
 
@@ -146,4 +148,8 @@ static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
 }
 
 #endif /* CONFIG_PAGE_TABLE_CHECK */
+
+#define page_table_check_pmd_set(mm, pmdp, pmd)	page_table_check_pmds_set(mm, pmdp, pmd, 1)
+#define page_table_check_pud_set(mm, pudp, pud)	page_table_check_puds_set(mm, pudp, pud, 1)
+
 #endif /* __LINUX_PAGE_TABLE_CHECK_H */
diff --git a/mm/page_table_check.c b/mm/page_table_check.c
index 509c6ef8de40..dae4a7d776b3 100644
--- a/mm/page_table_check.c
+++ b/mm/page_table_check.c
@@ -234,33 +234,39 @@ static inline void page_table_check_pmd_flags(pmd_t pmd)
 		WARN_ON_ONCE(swap_cached_writable(pmd_to_swp_entry(pmd)));
 }
 
-void __page_table_check_pmd_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd)
+void __page_table_check_pmds_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd,
+		unsigned int nr)
 {
+	unsigned int i;
+	unsigned long stride = PMD_SIZE >> PAGE_SHIFT;
+
 	if (&init_mm == mm)
 		return;
 
 	page_table_check_pmd_flags(pmd);
 
-	__page_table_check_pmd_clear(mm, *pmdp);
-	if (pmd_user_accessible_page(pmd)) {
-		page_table_check_set(pmd_pfn(pmd), PMD_SIZE >> PAGE_SHIFT,
-				     pmd_write(pmd));
-	}
+	for (i = 0; i < nr; i++)
+		__page_table_check_pmd_clear(mm, *(pmdp + i));
+	if (pmd_user_accessible_page(pmd))
+		page_table_check_set(pmd_pfn(pmd), stride * nr, pmd_write(pmd));
 }
-EXPORT_SYMBOL(__page_table_check_pmd_set);
+EXPORT_SYMBOL(__page_table_check_pmds_set);
 
-void __page_table_check_pud_set(struct mm_struct *mm, pud_t *pudp, pud_t pud)
+void __page_table_check_puds_set(struct mm_struct *mm, pud_t *pudp, pud_t pud,
+		unsigned int nr)
 {
+	unsigned int i;
+	unsigned long stride = PUD_SIZE >> PAGE_SHIFT;
+
 	if (&init_mm == mm)
 		return;
 
-	__page_table_check_pud_clear(mm, *pudp);
-	if (pud_user_accessible_page(pud)) {
-		page_table_check_set(pud_pfn(pud), PUD_SIZE >> PAGE_SHIFT,
-				     pud_write(pud));
-	}
+	for (i = 0; i < nr; i++)
+		__page_table_check_pud_clear(mm, *(pudp + i));
+	if (pud_user_accessible_page(pud))
+		page_table_check_set(pud_pfn(pud), stride * nr, pud_write(pud));
 }
-EXPORT_SYMBOL(__page_table_check_pud_set);
+EXPORT_SYMBOL(__page_table_check_puds_set);
 
 void __page_table_check_pte_clear_range(struct mm_struct *mm,
 					unsigned long addr,
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:36 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:36 +0000
Subject: [PATCH v3 06/11] arm64/mm: Hoist barriers out of set_ptes_anysz() loop
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-7-ryan.roberts@arm.com>

set_ptes_anysz() previously called __set_pte() for each PTE in the
range, which would conditionally issue a DSB and ISB to make the new PTE
value immediately visible to the table walker if the new PTE was valid
and for kernel space.

We can do better than this; let's hoist those barriers out of the loop
so that they are only issued once at the end of the loop. We then reduce
the cost by the number of PTEs in the range.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e255a36380dc..1898c3069c43 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -317,13 +317,11 @@ static inline void __set_pte_nosync(pte_t *ptep, pte_t pte)
 	WRITE_ONCE(*ptep, pte);
 }
 
-static inline void __set_pte(pte_t *ptep, pte_t pte)
+static inline void __set_pte_complete(pte_t pte)
 {
-	__set_pte_nosync(ptep, pte);
-
 	/*
 	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
-	 * or update_mmu_cache() have the necessary barriers.
+	 * has the necessary barriers.
 	 */
 	if (pte_valid_not_user(pte)) {
 		dsb(ishst);
@@ -331,6 +329,12 @@ static inline void __set_pte(pte_t *ptep, pte_t pte)
 	}
 }
 
+static inline void __set_pte(pte_t *ptep, pte_t pte)
+{
+	__set_pte_nosync(ptep, pte);
+	__set_pte_complete(pte);
+}
+
 static inline pte_t __ptep_get(pte_t *ptep)
 {
 	return READ_ONCE(*ptep);
@@ -647,12 +651,14 @@ static inline void set_ptes_anysz(struct mm_struct *mm, pte_t *ptep, pte_t pte,
 
 	for (;;) {
 		__check_safe_pte_update(mm, ptep, pte);
-		__set_pte(ptep, pte);
+		__set_pte_nosync(ptep, pte);
 		if (--nr == 0)
 			break;
 		ptep++;
 		pte = pte_advance_pfn(pte, stride);
 	}
+
+	__set_pte_complete(pte);
 }
 
 static inline void __set_ptes(struct mm_struct *mm,
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:37 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:37 +0000
Subject: [PATCH v3 07/11] mm/vmalloc: Warn on improper use of vunmap_range()
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-8-ryan.roberts@arm.com>

A call to vmalloc_huge() may cause memory blocks to be mapped at pmd or
pud level. But it is possible to subsequently call vunmap_range() on a
sub-range of the mapped memory, which partially overlaps a pmd or pud.
In this case, vmalloc unmaps the entire pmd or pud so that the
no-overlapping portion is also unmapped. Clearly that would have a bad
outcome, but it's not something that any callers do today as far as I
can tell. So I guess it's just expected that callers will not do this.

However, it would be useful to know if this happened in future; let's
add a warning to cover the eventuality.

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 mm/vmalloc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a6e7acebe9ad..fcdf67d5177a 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -374,8 +374,10 @@ static void vunmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 		if (cleared || pmd_bad(*pmd))
 			*mask |= PGTBL_PMD_MODIFIED;
 
-		if (cleared)
+		if (cleared) {
+			WARN_ON(next - addr < PMD_SIZE);
 			continue;
+		}
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
 		vunmap_pte_range(pmd, addr, next, mask);
@@ -399,8 +401,10 @@ static void vunmap_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
 		if (cleared || pud_bad(*pud))
 			*mask |= PGTBL_PUD_MODIFIED;
 
-		if (cleared)
+		if (cleared) {
+			WARN_ON(next - addr < PUD_SIZE);
 			continue;
+		}
 		if (pud_none_or_clear_bad(pud))
 			continue;
 		vunmap_pmd_range(pud, addr, next, mask);
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:38 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:38 +0000
Subject: [PATCH v3 08/11] mm/vmalloc: Gracefully unmap huge ptes
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-9-ryan.roberts@arm.com>

Commit f7ee1f13d606 ("mm/vmalloc: enable mapping of huge pages at pte
level in vmap") added its support by reusing the set_huge_pte_at() API,
which is otherwise only used for user mappings. But when unmapping those
huge ptes, it continued to call ptep_get_and_clear(), which is a
layering violation. To date, the only arch to implement this support is
powerpc and it all happens to work ok for it.

But arm64's implementation of ptep_get_and_clear() can not be safely
used to clear a previous set_huge_pte_at(). So let's introduce a new
arch opt-in function, arch_vmap_pte_range_unmap_size(), which can
provide the size of a (present) pte. Then we can call
huge_ptep_get_and_clear() to tear it down properly.

Note that if vunmap_range() is called with a range that starts in the
middle of a huge pte-mapped page, we must unmap the entire huge page so
the behaviour is consistent with pmd and pud block mappings. In this
case emit a warning just like we do for pmd/pud mappings.

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>
Reviewed-by: Uladzislau Rezki (Sony) <urezki at gmail.com>
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 include/linux/vmalloc.h |  8 ++++++++
 mm/vmalloc.c            | 18 ++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 31e9ffd936e3..16dd4cba64f2 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -113,6 +113,14 @@ static inline unsigned long arch_vmap_pte_range_map_size(unsigned long addr, uns
 }
 #endif
 
+#ifndef arch_vmap_pte_range_unmap_size
+static inline unsigned long arch_vmap_pte_range_unmap_size(unsigned long addr,
+							   pte_t *ptep)
+{
+	return PAGE_SIZE;
+}
+#endif
+
 #ifndef arch_vmap_pte_supported_shift
 static inline int arch_vmap_pte_supported_shift(unsigned long size)
 {
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index fcdf67d5177a..6111ce900ec4 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -350,12 +350,26 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 			     pgtbl_mod_mask *mask)
 {
 	pte_t *pte;
+	pte_t ptent;
+	unsigned long size = PAGE_SIZE;
 
 	pte = pte_offset_kernel(pmd, addr);
 	do {
-		pte_t ptent = ptep_get_and_clear(&init_mm, addr, pte);
+#ifdef CONFIG_HUGETLB_PAGE
+		size = arch_vmap_pte_range_unmap_size(addr, pte);
+		if (size != PAGE_SIZE) {
+			if (WARN_ON(!IS_ALIGNED(addr, size))) {
+				addr = ALIGN_DOWN(addr, size);
+				pte = PTR_ALIGN_DOWN(pte, sizeof(*pte) * (size >> PAGE_SHIFT));
+			}
+			ptent = huge_ptep_get_and_clear(&init_mm, addr, pte, size);
+			if (WARN_ON(end - addr < size))
+				size = end - addr;
+		} else
+#endif
+			ptent = ptep_get_and_clear(&init_mm, addr, pte);
 		WARN_ON(!pte_none(ptent) && !pte_present(ptent));
-	} while (pte++, addr += PAGE_SIZE, addr != end);
+	} while (pte += (size >> PAGE_SHIFT), addr += size, addr != end);
 	*mask |= PGTBL_PTE_MODIFIED;
 }
 
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:39 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:39 +0000
Subject: [PATCH v3 09/11] arm64/mm: Support huge pte-mapped pages in vmap
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-10-ryan.roberts@arm.com>

Implement the required arch functions to enable use of contpte in the
vmap when VM_ALLOW_HUGE_VMAP is specified. This speeds up vmap
operations due to only having to issue a DSB and ISB per contpte block
instead of per pte. But it also means that the TLB pressure reduces due
to only needing a single TLB entry for the whole contpte block.

Since vmap uses set_huge_pte_at() to set the contpte, that API is now
used for kernel mappings for the first time. Although in the vmap case
we never expect it to be called to modify a valid mapping so
clear_flush() should never be called, it's still wise to make it robust
for the kernel case, so amend the tlb flush function if the mm is for
kernel space.

Tested with vmalloc performance selftests:

  # kself/mm/test_vmalloc.sh \
	run_test_mask=1
	test_repeat_count=5
	nr_pages=256
	test_loop_count=100000
	use_huge=1

Duration reduced from 1274243 usec to 1083553 usec on Apple M2 for 15%
reduction in time taken.

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/include/asm/vmalloc.h | 45 ++++++++++++++++++++++++++++++++
 arch/arm64/mm/hugetlbpage.c      |  5 +++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/vmalloc.h b/arch/arm64/include/asm/vmalloc.h
index 38fafffe699f..12f534e8f3ed 100644
--- a/arch/arm64/include/asm/vmalloc.h
+++ b/arch/arm64/include/asm/vmalloc.h
@@ -23,6 +23,51 @@ static inline bool arch_vmap_pmd_supported(pgprot_t prot)
 	return !IS_ENABLED(CONFIG_PTDUMP_DEBUGFS);
 }
 
+#define arch_vmap_pte_range_map_size arch_vmap_pte_range_map_size
+static inline unsigned long arch_vmap_pte_range_map_size(unsigned long addr,
+						unsigned long end, u64 pfn,
+						unsigned int max_page_shift)
+{
+	/*
+	 * If the block is at least CONT_PTE_SIZE in size, and is naturally
+	 * aligned in both virtual and physical space, then we can pte-map the
+	 * block using the PTE_CONT bit for more efficient use of the TLB.
+	 */
+	if (max_page_shift < CONT_PTE_SHIFT)
+		return PAGE_SIZE;
+
+	if (end - addr < CONT_PTE_SIZE)
+		return PAGE_SIZE;
+
+	if (!IS_ALIGNED(addr, CONT_PTE_SIZE))
+		return PAGE_SIZE;
+
+	if (!IS_ALIGNED(PFN_PHYS(pfn), CONT_PTE_SIZE))
+		return PAGE_SIZE;
+
+	return CONT_PTE_SIZE;
+}
+
+#define arch_vmap_pte_range_unmap_size arch_vmap_pte_range_unmap_size
+static inline unsigned long arch_vmap_pte_range_unmap_size(unsigned long addr,
+							   pte_t *ptep)
+{
+	/*
+	 * The caller handles alignment so it's sufficient just to check
+	 * PTE_CONT.
+	 */
+	return pte_valid_cont(__ptep_get(ptep)) ? CONT_PTE_SIZE : PAGE_SIZE;
+}
+
+#define arch_vmap_pte_supported_shift arch_vmap_pte_supported_shift
+static inline int arch_vmap_pte_supported_shift(unsigned long size)
+{
+	if (size >= CONT_PTE_SIZE)
+		return CONT_PTE_SHIFT;
+
+	return PAGE_SHIFT;
+}
+
 #endif
 
 #define arch_vmap_pgprot_tagged arch_vmap_pgprot_tagged
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index efd18bd1eae3..c1cb13dd5e84 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -210,7 +210,10 @@ static void clear_flush(struct mm_struct *mm,
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
 		ptep_get_and_clear_anysz(mm, ptep, pgsize);
 
-	__flush_hugetlb_tlb_range(&vma, saddr, addr, pgsize, true);
+	if (mm == &init_mm)
+		flush_tlb_kernel_range(saddr, addr);
+	else
+		__flush_hugetlb_tlb_range(&vma, saddr, addr, pgsize, true);
 }
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-- 
2.43.0



From jic23 at kernel.org  Tue Mar  4 06:46:48 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Tue, 4 Mar 2025 14:46:48 +0000
Subject: [PATCH 2/4] iio: adc: rockchip_saradc: Add support for RK3528
In-Reply-To: <11022969.nUPlyArG6x@diego>
References: <20250227184058.2964204-1-jonas@kwiboo.se>
	<20250227184058.2964204-3-jonas@kwiboo.se>
	<11022969.nUPlyArG6x@diego>
Message-ID: <20250304144648.29f376f9@jic23-huawei>

On Tue, 04 Mar 2025 12:51:47 +0100
Heiko St?bner <heiko at sntech.de> wrote:

> Am Donnerstag, 27. Februar 2025, 19:40:51 MEZ schrieb Jonas Karlman:
> > The Successive Approximation ADC (SARADC) in RK3528 uses the v2
> > controller and support:
> > - 10-bit resolution
> > - Up to 1MS/s sampling rate
> > - 4 single-ended input channels
> > - Current consumption: 0.5mA @ 1MS/s
> > 
> > Add support for the 4 channels of 10-bit resolution supported by SARADC
> > in RK3528.
> > 
> > Signed-off-by: Jonas Karlman <jonas at kwiboo.se>  
> 
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> 
> 
Not sure why but I can't reply to cover letter.  Anyhow, replying here
instead.  Applied patches 1-2 to iio.git / togreg which I'll push out
a testing for 0-day to poke at it.

Thanks,

Jonathan

> 



From sebastian.reichel at collabora.com  Tue Mar  4 06:47:28 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Tue, 4 Mar 2025 15:47:28 +0100
Subject: [PATCH v3 0/3] Add display subsystem dt node on rk3576
In-Reply-To: <173564980410.21979.2947276365464229762.robh@kernel.org>
References: <20241231095728.253943-1-andyshrk@163.com>
 <173564980410.21979.2947276365464229762.robh@kernel.org>
Message-ID: <lfmhqurnpjmfy6pfjxd5aczxujislv2p5bsurcbl7capyt7zv3@hy2twvjj53uz>

Hello,

On Tue, Dec 31, 2024 at 06:57:21AM -0600, Rob Herring (Arm) wrote:
> On Tue, 31 Dec 2024 17:57:17 +0800, Andy Yan wrote:
> > As the VOP[0] and HDMI[1] driver have already been submitted for review.
> > This series enable hdmi display on sige5 board.
> > 
> > [0] https://lore.kernel.org/linux-rockchip/20241231090802.251787-1-andyshrk at 163.com/T/#t
> > [1] https://lore.kernel.org/linux-rockchip/20241231094425.253398-1-andyshrk at 163.com/T/#t
> > 
> > Changes in v3:
> > - Split from https://lore.kernel.org/linux-rockchip/3330586.aeNJFYEL58 at diego/T/#t
> > 
> > Andy Yan (3):
> >   arm64: dts: rockchip: Add vop for rk3576
> >   arm64: dts: rockchip: Add hdmi for rk3576
> >   arm64: dts: rockchip: Enable hdmi display on sige5
> > 
> >  .../boot/dts/rockchip/rk3576-armsom-sige5.dts |  47 +++++++
> >  arch/arm64/boot/dts/rockchip/rk3576.dtsi      | 126 ++++++++++++++++++
> >  2 files changed, 173 insertions(+)
>
> [...] (a bunch of warnings due to dependency patch series not yet
> being in linux-next)

I think all dependencies have landed now. But it might be sensible
to do a quick resend considering how old this is.

Would be nice to have initial RK3576 HDMI support in 6.15 :)

Greetings,

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/f6c96bec/attachment.sig>

From james.quinlan at broadcom.com  Tue Mar  4 06:49:36 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Tue, 4 Mar 2025 09:49:36 -0500
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of regulator_bulk_get()
In-Reply-To: <20250303184011.GA172021@bhelgaas>
References: <20250214173944.47506-5-james.quinlan@broadcom.com> <20250303184011.GA172021@bhelgaas>
Message-ID: <CA+-6iNwsCzf30a0vbgStqA+DCyBnk3bGwoXNv0UNYOThE1Us6Q@mail.gmail.com>

On Mon, Mar 3, 2025 at 1:40?PM Bjorn Helgaas <helgaas at kernel.org> wrote:
>
> On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > If regulator_bulk_get() returns an error, no regulators are created and we
> > need to set their number to zero.  If we do not do this and the PCIe
> > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> >
> > Also print out the error value, as we cannot return an error upwards as
> > Linux will WARN on an error from add_bus().
> >
> > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > ---
> >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > index e0b20f58c604..56b49d3cae19 100644
> > --- a/drivers/pci/controller/pcie-brcmstb.c
> > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> >
> >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> >               if (ret) {
> > -                     dev_info(dev, "No regulators for downstream device\n");
> > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > +                     pcie->sr = NULL;
>
> Is alloc_subdev_regulators() buying us something useful?  It seems
> like it would be simpler to have:
>
>   struct brcm_pcie {
>     ...
>     struct regulator_bulk_data supplies[3];
>     ...
>   };
>
> I think that's what most callers of devm_regulator_bulk_get() do.

Ack.

Jim Quinlan
Broadcom STB/CM
>
> >                       goto no_regulators;
> >               }
> >
> > --
> > 2.43.0
> >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4210 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/6b48b2a5/attachment.p7s>

From krzk at kernel.org  Tue Mar  4 06:50:16 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 15:50:16 +0100
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
 <20250304131314.GA2441686-robh@kernel.org>
 <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>
Message-ID: <cdcfdbfe-7186-4a29-a39b-7253070d889c@kernel.org>

On 04/03/2025 15:40, Jacky Bai wrote:
> Hi Rob,
> 
>> Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
>> interrupts-extended property
>>
>> On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
>>> Add interrupts-extended property for edma that has multiple interrupt
>>> controllers used.
>>
>> Did you try using interrupts-extended? No. Because either is supported by the
>> tools already.
>>
> 
> We need to use interrupts-extended property for i.MX94 because for the edma's
> interrupts, some are connected to irqsteer interrupt controller and some are connected
> to the GIC. make dtbs_check report error, so I add this dt binding changes.
> 
> Sorry, Which tools are you referring?

Linux, dtschema, everything.

> 
>>>
>>> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
>>> ---
>>>  - v2 changes:
>>>   - newly added entry
>>> ---
>>>  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11
>> ++++++++++-
>>>  1 file changed, 10 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
>>> b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
>>> index d54140f18d34..549afb8611a9 100644
>>> --- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
>>> +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
>>> @@ -38,6 +38,10 @@ properties:
>>>      minItems: 1
>>>      maxItems: 64
>>>
>>> +  interrupts-extended:
>>> +    minItems: 1
>>> +    maxItems: 65
>>
>> Doesn't match the size for interrupt-names:
>>
> 
> The interrupt-names are only true for vf610, maxItems is
> enough for such case. do we still need to update it? 

They always go in sync.

Anyway, you did not get the point of Rob's comments: this patch is
neither needed nor correct. Just drop it and test again your DTS.



Best regards,
Krzysztof


From manivannan.sadhasivam at linaro.org  Tue Mar  4 06:51:20 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:21:20 +0530
Subject: [PATCH v2 1/8] PCI: brcmstb: Set gen limitation before link, not
 after
In-Reply-To: <20250214173944.47506-2-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-2-james.quinlan@broadcom.com>
Message-ID: <20250304145120.jrcxrvnuhj2cweyp@thinkpad>

On Fri, Feb 14, 2025 at 12:39:29PM -0500, Jim Quinlan wrote:
> When the user elects to limit the PCIe generation via the appropriate DT
> property, apply the settings before the PCIe link-up, not after.
> 
> Fixes: c0452137034bda8f686dd9a2e167949bfffd6776 ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver")
> 

Common practice is to use the 12 chars SHA for Fixes tag and not the entire 40
chars. Like,

Fixes: c0452137034b ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver")

And no need of extra newline here.

> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 546056f7f0d3..64a7511e66a8 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -1324,6 +1324,10 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie)
>  	bool ssc_good = false;
>  	int ret, i;
>  
> +	/* Limit the generation if specified */
> +	if (pcie->gen)
> +		brcm_pcie_set_gen(pcie, pcie->gen);
> +
>  	/* Unassert the fundamental reset */
>  	ret = pcie->cfg->perst_set(pcie, 0);
>  	if (ret)
> @@ -1350,9 +1354,6 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie)
>  
>  	brcm_config_clkreq(pcie);
>  
> -	if (pcie->gen)
> -		brcm_pcie_set_gen(pcie, pcie->gen);
> -
>  	if (pcie->ssc) {
>  		ret = brcm_pcie_set_ssc(pcie);
>  		if (ret == 0)
> -- 
> 2.43.0
> 

-- 
????????? ????????


From robh at kernel.org  Tue Mar  4 06:53:41 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 08:53:41 -0600
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com> <20250304093127.1954549-2-ping.bai@nxp.com>
 <20250304131314.GA2441686-robh@kernel.org> <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>
Message-ID: <CAL_JsqJd06AOJKXFiDq=rihFa7qWnLciBeHKCKwkRUfF7AJTMA@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:40?AM Jacky Bai <ping.bai at nxp.com> wrote:
>
> Hi Rob,
>
> > Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
> > interrupts-extended property
> >
> > On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> > > Add interrupts-extended property for edma that has multiple interrupt
> > > controllers used.
> >
> > Did you try using interrupts-extended? No. Because either is supported by the
> > tools already.
> >
>
> We need to use interrupts-extended property for i.MX94 because for the edma's
> interrupts, some are connected to irqsteer interrupt controller and some are connected
> to the GIC. make dtbs_check report error, so I add this dt binding changes.
>
> Sorry, Which tools are you referring?

dtschema

The schemas specify 'interrupts' only. The dts files can use either
interrupts or interrupts-extended. If that doesn't work for you, it is
a bug in dtschema.

Rob


From krzk at kernel.org  Tue Mar  4 06:54:10 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 15:54:10 +0100
Subject: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <20250304093127.1954549-4-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-4-ping.bai@nxp.com>
Message-ID: <9581e376-19b2-4d4e-ad81-cc24e39e9d33@kernel.org>

On 04/03/2025 10:31, Jacky Bai wrote:
> Add the minimal dtsi support for i.MX943. i.MX943 is the
> first SoC of i.MX94 Family, create a common dtsi for the
> whole i.MX94 family, and the specific dtsi part for i.MX943.
> 
> The clock, power domain and perf index need to be used by
> the device nodes for resource reference, add them along
> with the dtsi support.
> 
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - remove the unnecessary macro define in clock header as suggested by Krzysztof
>   - split the dtsi into imx94.dtsi and imx943.dtsi
>   - use low case in the pinfunc header as Frank suggested
>   - reorder the device nodes and properties
>   - resolve Krzysztof's other comments

Which ones? Be specific.

Based on last issue, I don't think you implemented comments.


> +
> +			a55_irqsteer: interrupt-controller at 446a0000 {
> +				compatible = "fsl,imx-irqsteer";
> +				reg = <0x446a0000 0x1000>;
> +				#interrupt-cells = <1>;
> +				interrupt-controller;
> +				interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "ipg";
> +				fsl,channel = <0>;
> +				fsl,num-irqs = <960>;
> +			};
> +		};
> +
> +		aips4: bus at 49000000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0x0 0x49000000 0x0 0x800000>;
> +			ranges = <0x49000000 0x0 0x49000000 0x800000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			wdog3: watchdog at 49220000 {
> +				compatible = "fsl,imx93-wdt";

imx93 or imx95, like in other places? And the commit msg says imx943.

I already asked for that.

> +				reg = <0x49220000 0x10000>;
> +				interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				timeout-sec = <40>;
> +				fsl,ext-reset-output;
> +				status = "disabled";
> +			};
> +		};
Best regards,
Krzysztof


From hpa at zytor.com  Tue Mar  4 06:52:53 2025
From: hpa at zytor.com (H. Peter Anvin)
Date: Tue, 04 Mar 2025 06:52:53 -0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250304094220.GC11590@noisy.programming.kicks-ass.net>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn> <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net> <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com> <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net> <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com> <20250304094220.GC11590@noisy.programming.kicks-ass.net>
Message-ID: <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>

On March 4, 2025 1:42:20 AM PST, Peter Zijlstra <peterz at infradead.org> wrote:
>On Tue, Mar 04, 2025 at 03:47:45PM +0800, Menglong Dong wrote:
>> We don't have to select FUNCTION_ALIGNMENT_32B, so the
>> worst case is to increase ~2.2%.
>> 
>> What do you think?
>
>Well, since I don't understand what you need this for at all, I'm firmly
>on the side of not doing this.
>
>What actual problem is being solved with this meta data nonsense? Why is
>it worth blowing up our I$ footprint over.
>
>Also note, that if you're going to be explaining this, start from
>scratch, as I have absolutely 0 clues about BPF and such.

I would appreciate such information as well. The idea seems dubious on the surface.


From geert at linux-m68k.org  Tue Mar  4 06:54:16 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 4 Mar 2025 15:54:16 +0100
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250303194647.GC1552306@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com> <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com> <Z8XrYxP_pZr6tFU8@debian> <20250303194647.GC1552306@rocinante>
Message-ID: <CAMuHMdWuCJAd-mCpCoseThureCKnnep4T-Z0h1_WJ1BOf2ZeDg@mail.gmail.com>

Hi Krzysztof,

This patch is now commit 1ff54f4cbaed9ec6 ("PCI: dwc: Add debugfs
based Silicon Debug support for DWC") in pci/next (next-20250304).

On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> [...]
> > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > +{
> > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > +   struct device *dev = pci->dev;
> > > +   struct debugfs_info *debugfs;
> > > +   struct dentry *dir;
> > > +   int ret;
> > > +
> > > +   /* Create main directory for each platform driver */
> > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > +   dir = debugfs_create_dir(dirname, NULL);
> > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > +   if (!debugfs)
> > > +           return -ENOMEM;
> > > +
> > > +   debugfs->debug_dir = dir;
> > > +   pci->debugfs = debugfs;
> > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > +   if (ret)
> > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> >
> > What will happen if ret != 0? still return 0?

And that is exactly what happens on Gray Hawk Single with R-Car
V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
dwc_pcie_rasdes_debugfs_init() to return -ENODEV.

> Given that callers of dwc_pcie_debugfs_init() check for errors,

Debugfs issues should never be propagated upstream!

> this probably should correctly bubble up any failure coming from
> dwc_pcie_rasdes_debugfs_init().
>
> I made updates to the code directly on the current branch, have a look:

So while applying, you changed this like:

            ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
    -       if (ret)
    -               dev_dbg(dev, "RASDES debugfs init failed\n");
    +       if (ret) {
    +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
    +               return ret;
    +       }

            return 0;

Hence this is now a fatal error, causing the probe to fail.
Unfortunately something fails during cleanup:

    pcie-rcar-gen4 e65d0000.pcie: failed to initialize RAS DES debugfs
    ------------[ cut here ]------------
    WARNING: CPU: 3 PID: 36 at kernel/irq/irqdomain.c:393
irq_domain_remove+0xa8/0xb0
    CPU: 3 UID: 0 PID: 36 Comm: kworker/u16:1 Not tainted
6.14.0-rc1-arm64-renesas-00134-g12c8c1363538 #2884
    Hardware name: Renesas Gray Hawk Single board based on r8a779h0 (DT)
    Workqueue: async async_run_entry_fn
    pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : irq_domain_remove+0xa8/0xb0
    lr : irq_domain_remove+0x2c/0xb0
    sp : ffff8000819b3b10
    x29: ffff8000819b3b10 x28: 0000000000000000 x27: 0000000000000000
    x26: ffff00044011d800 x25: ffff80008053294c x24: ffff000441740400
    x23: ffff0004413a30f0 x22: ffff0004413a3130 x21: ffff0004413a3130
    x20: ffff8000815c0ec8 x19: ffff0004415f8240 x18: 00000000ffffffff
    x17: 6775626564205345 x16: 0000000000000020 x15: ffff8000819b37b0
    x14: 0000000000000004 x13: ffff8000813e9dd8 x12: 0000000000000000
    x11: ffff0004404b6448 x10: ffff800080e85400 x9 : 1fffe00088334301
    x8 : 0000000000000001 x7 : ffff0004419a1800 x6 : ffff0004419a1808
    x5 : ffff000441349030 x4 : fffffffffffffdc1 x3 : 0000000000000000
    x2 : ffff0004403e0000 x1 : 0000000000000000 x0 : ffff00044134f630
    Call trace:
     irq_domain_remove+0xa8/0xb0 (P)
     dw_pcie_host_init+0x394/0x710
     rcar_gen4_pcie_probe+0x104/0x2f8
     platform_probe+0x64/0xbc
     really_probe+0xb8/0x294
     __driver_probe_device+0x74/0x124
     driver_probe_device+0x3c/0x158
     __device_attach_driver+0xd4/0x154
     bus_for_each_drv+0x84/0xe0
     __device_attach_async_helper+0xac/0xd0
     async_run_entry_fn+0x30/0xd8
     process_one_work+0x144/0x280
     worker_thread+0x2c4/0x3cc
     kthread+0x128/0x1e0
     ret_from_fork+0x10/0x20
    ---[ end trace 0000000000000000 ]---

Worse, the PCI bus is still registered, so running "lspci" causes an Oops:

    Unable to handle kernel NULL pointer dereference at virtual
address 0000000000000004
    Mem abort info:
      ESR = 0x0000000096000004
      EC = 0x25: DABT (current EL), IL = 32 bits
      SET = 0, FnV = 0
      EA = 0, S1PTW = 0
      FSC = 0x04: level 0 translation fault
    Data abort info:
      ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
      CM = 0, WnR = 0, TnD = 0, TagAccess = 0
      GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
    user pgtable: 4k pages, 48-bit VAs, pgdp=0000000483b53000
    [0000000000000004] pgd=0000000000000000, p4d=0000000000000000
    Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
    CPU: 3 UID: 0 PID: 707 Comm: lspci Tainted: G        W
6.14.0-rc1-arm64-renesas-00134-g12c8c1363538 #2884
    Tainted: [W]=WARN
    Hardware name: Renesas Gray Hawk Single board based on r8a779h0 (DT)
    pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : pci_generic_config_read+0x34/0xac
    lr : pci_generic_config_read+0x20/0xac
    sp : ffff8000825cbbf0
    x29: ffff8000825cbbf0 x28: ffff0004491c4b84 x27: 0000000000000004
    x26: 000000000000000f x25: ffff0004491c4b80 x24: 0000000000000040
    x23: 0000000000000040 x22: ffff8000825cbc64 x21: ffff8000816fb4f8
    x20: ffff8000825cbc14 x19: 0000000000000004 x18: 0000000000000000
    x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
    x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
    x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000
    x8 : 0000000000000000 x7 : ffff000442c653c0 x6 : ffff8000805163d0
    x5 : ffff8000804f3334 x4 : ffff8000825cbc14 x3 : ffff800080531990
    x2 : 0000000000000004 x1 : 0000000000000000 x0 : 0000000000000004
    Call trace:
     pci_generic_config_read+0x34/0xac (P)
     pci_user_read_config_dword+0x78/0x118
     pci_read_config+0xe4/0x29c
     sysfs_kf_bin_read+0x8c/0x9c
     kernfs_fop_read_iter+0x9c/0x19c
     vfs_read+0x24c/0x330
     __arm64_sys_pread64+0xac/0xc8
     invoke_syscall+0x44/0x100
     el0_svc_common.constprop.0+0x3c/0xd4
     do_el0_svc+0x18/0x20
     el0_svc+0x24/0xa8
     el0t_64_sync_handler+0x104/0x130
     el0t_64_sync+0x154/0x158
    Code: 7100067f 540002a0 71000a7f 54000160 (b9400000)
    ---[ end trace 0000000000000000 ]---
    note: lspci[707] exited with irqs disabled
    note: lspci[707] exited with preempt_count 1

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From manivannan.sadhasivam at linaro.org  Tue Mar  4 06:54:25 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:24:25 +0530
Subject: [PATCH v2 2/8] PCI: brcmstb: Write to internal register to
 change link cap
In-Reply-To: <20250214173944.47506-3-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-3-james.quinlan@broadcom.com>
Message-ID: <20250304145425.rayj5zowyxp7s4se@thinkpad>

On Fri, Feb 14, 2025 at 12:39:30PM -0500, Jim Quinlan wrote:
> The driver was mistakenly writing to a RO config-space register
> (PCI_EXP_LNKCAP).  Although harmless in this case, the proper destination
> is an internal RW register that is reflected by PCI_EXP_LNKCAP.
> 

You mean to say that writing to RO register doesn't cause any issue, but what
about the link capability not getting updated? It is a bug nevertheless.

> Fixes: c0452137034bda8f686dd9a2e167949bfffd6776 ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver")
> 

Same comment as previous patch.

> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 64a7511e66a8..98542e74aa16 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -413,10 +413,10 @@ static int brcm_pcie_set_ssc(struct brcm_pcie *pcie)
>  static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen)
>  {
>  	u16 lnkctl2 = readw(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
> -	u32 lnkcap = readl(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
> +	u32 lnkcap = readl(pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
>  
>  	lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
> -	writel(lnkcap, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
> +	writel(lnkcap, pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
>  
>  	lnkctl2 = (lnkctl2 & ~0xf) | gen;
>  	writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
> -- 
> 2.43.0
> 

-- 
????????? ????????


From krzk at kernel.org  Tue Mar  4 06:55:22 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 15:55:22 +0100
Subject: [PATCH v2 2/4] dt-bindings: arm: fsl: add i.MX943 EVK board
In-Reply-To: <20250304093127.1954549-3-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-3-ping.bai@nxp.com>
Message-ID: <487093b6-d9fc-4c85-95b8-174fe76e04c5@kernel.org>

On 04/03/2025 10:31, Jacky Bai wrote:
> Add DT compatible string for NXP i.MX943 EVK board.
> 
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


---

<form letter>
This is an automated instruction, just in case, because many review tags
are being ignored. If you know the process, you can skip it (please do
not feel offended by me posting it here - no bad intentions intended).
If you do not know the process, here is a short explanation:

Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Full context and explanation:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
</form letter>

Best regards,
Krzysztof


From geert at linux-m68k.org  Tue Mar  4 06:57:01 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 4 Mar 2025 15:57:01 +0100
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250303194647.GC1552306@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com> <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com> <Z8XrYxP_pZr6tFU8@debian> <20250303194647.GC1552306@rocinante>
Message-ID: <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>

Hi Krzysztof,

(CC corrected)

This patch is now commit 1ff54f4cbaed9ec6 ("PCI: dwc: Add debugfs
based Silicon Debug support for DWC") in pci/next (next-20250304).

On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> [...]
> > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > +{
> > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > +   struct device *dev = pci->dev;
> > > +   struct debugfs_info *debugfs;
> > > +   struct dentry *dir;
> > > +   int ret;
> > > +
> > > +   /* Create main directory for each platform driver */
> > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > +   dir = debugfs_create_dir(dirname, NULL);
> > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > +   if (!debugfs)
> > > +           return -ENOMEM;
> > > +
> > > +   debugfs->debug_dir = dir;
> > > +   pci->debugfs = debugfs;
> > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > +   if (ret)
> > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> >
> > What will happen if ret != 0? still return 0?

And that is exactly what happens on Gray Hawk Single with R-Car
V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
dwc_pcie_rasdes_debugfs_init() to return -ENODEV.

> Given that callers of dwc_pcie_debugfs_init() check for errors,

Debugfs issues should never be propagated upstream!

> this probably should correctly bubble up any failure coming from
> dwc_pcie_rasdes_debugfs_init().
>
> I made updates to the code directly on the current branch, have a look:

So while applying, you changed this like:

            ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
    -       if (ret)
    -               dev_dbg(dev, "RASDES debugfs init failed\n");
    +       if (ret) {
    +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
    +               return ret;
    +       }

            return 0;

Hence this is now a fatal error, causing the probe to fail.
Unfortunately something fails during cleanup:

    pcie-rcar-gen4 e65d0000.pcie: failed to initialize RAS DES debugfs
    ------------[ cut here ]------------
    WARNING: CPU: 3 PID: 36 at kernel/irq/irqdomain.c:393
irq_domain_remove+0xa8/0xb0
    CPU: 3 UID: 0 PID: 36 Comm: kworker/u16:1 Not tainted
6.14.0-rc1-arm64-renesas-00134-g12c8c1363538 #2884
    Hardware name: Renesas Gray Hawk Single board based on r8a779h0 (DT)
    Workqueue: async async_run_entry_fn
    pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : irq_domain_remove+0xa8/0xb0
    lr : irq_domain_remove+0x2c/0xb0
    sp : ffff8000819b3b10
    x29: ffff8000819b3b10 x28: 0000000000000000 x27: 0000000000000000
    x26: ffff00044011d800 x25: ffff80008053294c x24: ffff000441740400
    x23: ffff0004413a30f0 x22: ffff0004413a3130 x21: ffff0004413a3130
    x20: ffff8000815c0ec8 x19: ffff0004415f8240 x18: 00000000ffffffff
    x17: 6775626564205345 x16: 0000000000000020 x15: ffff8000819b37b0
    x14: 0000000000000004 x13: ffff8000813e9dd8 x12: 0000000000000000
    x11: ffff0004404b6448 x10: ffff800080e85400 x9 : 1fffe00088334301
    x8 : 0000000000000001 x7 : ffff0004419a1800 x6 : ffff0004419a1808
    x5 : ffff000441349030 x4 : fffffffffffffdc1 x3 : 0000000000000000
    x2 : ffff0004403e0000 x1 : 0000000000000000 x0 : ffff00044134f630
    Call trace:
     irq_domain_remove+0xa8/0xb0 (P)
     dw_pcie_host_init+0x394/0x710
     rcar_gen4_pcie_probe+0x104/0x2f8
     platform_probe+0x64/0xbc
     really_probe+0xb8/0x294
     __driver_probe_device+0x74/0x124
     driver_probe_device+0x3c/0x158
     __device_attach_driver+0xd4/0x154
     bus_for_each_drv+0x84/0xe0
     __device_attach_async_helper+0xac/0xd0
     async_run_entry_fn+0x30/0xd8
     process_one_work+0x144/0x280
     worker_thread+0x2c4/0x3cc
     kthread+0x128/0x1e0
     ret_from_fork+0x10/0x20
    ---[ end trace 0000000000000000 ]---

Worse, the PCI bus is still registered, so running "lspci" causes an Oops:

    Unable to handle kernel NULL pointer dereference at virtual
address 0000000000000004
    Mem abort info:
      ESR = 0x0000000096000004
      EC = 0x25: DABT (current EL), IL = 32 bits
      SET = 0, FnV = 0
      EA = 0, S1PTW = 0
      FSC = 0x04: level 0 translation fault
    Data abort info:
      ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
      CM = 0, WnR = 0, TnD = 0, TagAccess = 0
      GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
    user pgtable: 4k pages, 48-bit VAs, pgdp=0000000483b53000
    [0000000000000004] pgd=0000000000000000, p4d=0000000000000000
    Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
    CPU: 3 UID: 0 PID: 707 Comm: lspci Tainted: G
W6.14.0-rc1-arm64-renesas-00134-g12c8c1363538 #2884
    Tainted: [W]=WARN
    Hardware name: Renesas Gray Hawk Single board based on r8a779h0 (DT)
    pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : pci_generic_config_read+0x34/0xac
    lr : pci_generic_config_read+0x20/0xac
    sp : ffff8000825cbbf0
    x29: ffff8000825cbbf0 x28: ffff0004491c4b84 x27: 0000000000000004
    x26: 000000000000000f x25: ffff0004491c4b80 x24: 0000000000000040
    x23: 0000000000000040 x22: ffff8000825cbc64 x21: ffff8000816fb4f8
    x20: ffff8000825cbc14 x19: 0000000000000004 x18: 0000000000000000
    x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
    x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
    x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000
    x8 : 0000000000000000 x7 : ffff000442c653c0 x6 : ffff8000805163d0
    x5 : ffff8000804f3334 x4 : ffff8000825cbc14 x3 : ffff800080531990
    x2 : 0000000000000004 x1 : 0000000000000000 x0 : 0000000000000004
    Call trace:
     pci_generic_config_read+0x34/0xac (P)
     pci_user_read_config_dword+0x78/0x118
     pci_read_config+0xe4/0x29c
     sysfs_kf_bin_read+0x8c/0x9c
     kernfs_fop_read_iter+0x9c/0x19c
     vfs_read+0x24c/0x330
     __arm64_sys_pread64+0xac/0xc8
     invoke_syscall+0x44/0x100
     el0_svc_common.constprop.0+0x3c/0xd4
     do_el0_svc+0x18/0x20
     el0_svc+0x24/0xa8
     el0t_64_sync_handler+0x104/0x130
     el0t_64_sync+0x154/0x158
    Code: 7100067f 540002a0 71000a7f 54000160 (b9400000)
    ---[ end trace 0000000000000000 ]---
    note: lspci[707] exited with irqs disabled
    note: lspci[707] exited with preempt_count 1

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From manivannan.sadhasivam at linaro.org  Tue Mar  4 06:57:24 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:27:24 +0530
Subject: [PATCH v2 3/8] PCI: brcmstb: Do not assume that reg field starts
 at LSB
In-Reply-To: <20250214173944.47506-4-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-4-james.quinlan@broadcom.com>
Message-ID: <20250304145724.itrzj6wnflxxf3up@thinkpad>

On Fri, Feb 14, 2025 at 12:39:31PM -0500, Jim Quinlan wrote:
> When setting a register field it was assumed that the field started at the

s/a register field/LNKCAP and LNKCTL2 register fields,

> lsb of the register.  Although the masks do indeed start at the lsb, and
> this will probably not change, it is prudent to use a method that makes no
> assumption about the mask's placement in the register.
> 
> The uXXp_replace_bits() calls are used since they are already prevalent
> in this driver.
> 
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 98542e74aa16..e0b20f58c604 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -415,10 +415,10 @@ static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen)
>  	u16 lnkctl2 = readw(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
>  	u32 lnkcap = readl(pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
>  
> -	lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
> +	u32p_replace_bits(&lnkcap, gen, PCI_EXP_LNKCAP_SLS);
>  	writel(lnkcap, pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
>  
> -	lnkctl2 = (lnkctl2 & ~0xf) | gen;
> +	u16p_replace_bits(&lnkctl2, gen, PCI_EXP_LNKCTL2_TLS);
>  	writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
>  }
>  
> -- 
> 2.43.0
> 

-- 
????????? ????????


From suzuki.poulose at arm.com  Tue Mar  4 06:58:01 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 4 Mar 2025 14:58:01 +0000
Subject: [PATCH v15 05/10] Coresight: Allocate trace ID after building the
 path
In-Reply-To: <20250303032931.2500935-6-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-6-quic_jiegan@quicinc.com>
Message-ID: <8efe6176-44a2-4b3d-b9b5-855b26f00187@arm.com>

On 03/03/2025 03:29, Jie Gan wrote:
> The trace_id will be stored in coresight_path instead of being declared
> everywhere and allocated after building the path.
> 
> Co-developed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c  | 44 +++++++++++++++++++
>   .../hwtracing/coresight/coresight-etm-perf.c  |  5 +--
>   drivers/hwtracing/coresight/coresight-priv.h  |  2 +
>   drivers/hwtracing/coresight/coresight-sysfs.c |  4 ++
>   4 files changed, 52 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index ed0e9368324d..6adc06995d76 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -655,6 +655,50 @@ static void coresight_drop_device(struct coresight_device *csdev)
>   	}
>   }
>   
> +/*
> + * coresight device will read their existing or alloc a trace ID, if their trace_id
> + * callback is set.
> + *
> + * Return 0 if the trace_id callback is not set.
> + * Return the result of the trace_id callback if it is set. The return value
> + * will be the trace_id if successful, and an error number if it fails.
> + */
> +static int coresight_get_trace_id(struct coresight_device *csdev,
> +				  enum cs_mode mode,
> +				  struct coresight_device *sink)
> +{
> +	if (coresight_ops(csdev)->trace_id)
> +		return coresight_ops(csdev)->trace_id(csdev, mode, sink);
> +
> +	return 0;
> +}
> +
> +/*
> + * Call this after creating the path and before enabling it. This leaves
> + * the trace ID set on the path, or it remains 0 if it couldn't be assigned.
> + */
> +void coresight_path_assign_trace_id(struct coresight_path *path,
> +				    enum cs_mode mode)
> +{
> +	struct coresight_device *sink = coresight_get_sink(&path->path_list);
> +	struct coresight_node *nd;
> +	int trace_id;
> +
> +	list_for_each_entry(nd, &path->path_list, link) {
> +		/* Assign a trace ID to the path for the first device that wants to do it */
> +		trace_id = coresight_get_trace_id(nd->csdev, mode, sink);
> +
> +		/*
> +		 * 0 in this context is that it didn't want to assign so keep searching.
> +		 * Non 0 is either success or fail.
> +		*/

checkpatch complains:

WARNING: Block comments should align the * on each line 

#65: FILE: drivers/hwtracing/coresight/coresight-core.c:694: 

+                * Non 0 is either success or fail.
+               */


Please make sure to run the checkpatch on individual patches before 
submitting in the future. I will fix this up locally for now.

Kind regards
Suzuki



> +		if (trace_id != 0) {
> +			path->trace_id = trace_id;
> +			return;
> +		}
> +	}
> +}
> +
>   /**
>    * _coresight_build_path - recursively build a path from a @csdev to a sink.
>    * @csdev:	The device to start from.
> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> index b0426792f08a..134290ab622e 100644
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> @@ -319,7 +319,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
>   {
>   	u32 id, cfg_hash;
>   	int cpu = event->cpu;
> -	int trace_id;
>   	cpumask_t *mask;
>   	struct coresight_device *sink = NULL;
>   	struct coresight_device *user_sink = NULL, *last_sink = NULL;
> @@ -409,8 +408,8 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
>   		}
>   
>   		/* ensure we can allocate a trace ID for this CPU */
> -		trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
> -		if (!IS_VALID_CS_TRACE_ID(trace_id)) {
> +		coresight_path_assign_trace_id(path, CS_MODE_PERF);
> +		if (!IS_VALID_CS_TRACE_ID(path->trace_id)) {
>   			cpumask_clear_cpu(cpu, mask);
>   			coresight_release_path(path);
>   			continue;
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 27b7dc348d4a..2bea35bae0d4 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -152,6 +152,8 @@ int coresight_make_links(struct coresight_device *orig,
>   void coresight_remove_links(struct coresight_device *orig,
>   			    struct coresight_connection *conn);
>   u32 coresight_get_sink_id(struct coresight_device *csdev);
> +void coresight_path_assign_trace_id(struct coresight_path *path,
> +				   enum cs_mode mode);
>   
>   #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
>   extern int etm_readl_cp14(u32 off, unsigned int *val);
> diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
> index cb4c39732d26..d03751bf3d8a 100644
> --- a/drivers/hwtracing/coresight/coresight-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-sysfs.c
> @@ -209,6 +209,10 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
>   		goto out;
>   	}
>   
> +	coresight_path_assign_trace_id(path, CS_MODE_SYSFS);
> +	if (!IS_VALID_CS_TRACE_ID(path->trace_id))
> +		goto err_path;
> +
>   	ret = coresight_enable_path(&path->path_list, CS_MODE_SYSFS, NULL);
>   	if (ret)
>   		goto err_path;



From quentin.schulz at cherry.de  Tue Mar  4 06:59:09 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Tue, 4 Mar 2025 15:59:09 +0100
Subject: [PATCH v3 2/3] drm/rockchip: lvds: Hide scary error messages on
 probe deferral
In-Reply-To: <20250304124418.111061-3-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
 <20250304124418.111061-3-heiko@sntech.de>
Message-ID: <cd001ccb-41a8-4204-8945-8ea00006ef0c@cherry.de>

Hi Heiko,

On 3/4/25 1:44 PM, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner at cherry.de>
> 
> Commit 52d11c863ac9 ("drm/rockchip: lvds: do not print scary message when
> probing defer") already started hiding scary messages that are not relevant
> if the requested supply just returned EPROBE_DEFER, but there are more
> possible sources - like the phy.
> 
> So modernize the whole logging in the probe path by replacing the
> remaining deprecated DRM_DEV_ERROR with appropriate dev_err(_probe)
> and drm_err calls.
> 
> The distinction here is that all messages talking about mishaps of the
> lvds element use dev_err(_probe) while messages caused by interaction
> with the main Rockchip drm-device use drm_err.
> 
> Reviewed-by: Andy Yan <andy.yan at rock-chips.com>

Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>

Thanks!
Quentin


From angelogioacchino.delregno at collabora.com  Tue Mar  4 06:59:30 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 15:59:30 +0100
Subject: [v2,1/2] memory/mediatek: Add an interface to get current DDR
 data rate
In-Reply-To: <20250207014437.17920-2-crystal.guo@mediatek.com>
References: <20250207014437.17920-1-crystal.guo@mediatek.com>
 <20250207014437.17920-2-crystal.guo@mediatek.com>
Message-ID: <10163a0b-5865-4088-b38b-6c5680548fc4@collabora.com>

Il 07/02/25 02:42, Crystal Guo ha scritto:
> Add MediaTek DRAMC driver to provide an interface that can
> obtain current DDR data rate.
> 
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202412210955.FvO0Pee3-lkp at intel.
> com/
> Signed-off-by: Crystal Guo <crystal.guo at mediatek.com>
> ---
>   drivers/memory/Kconfig              |   1 +
>   drivers/memory/Makefile             |   1 +
>   drivers/memory/mediatek/Kconfig     |  21 +++
>   drivers/memory/mediatek/Makefile    |   2 +
>   drivers/memory/mediatek/mtk-dramc.c | 196 ++++++++++++++++++++++++++++
>   5 files changed, 221 insertions(+)
>   create mode 100644 drivers/memory/mediatek/Kconfig
>   create mode 100644 drivers/memory/mediatek/Makefile
>   create mode 100644 drivers/memory/mediatek/mtk-dramc.c
> 
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index c82d8d8a16ea..b1698549ff81 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -227,5 +227,6 @@ config STM32_FMC2_EBI
>   
>   source "drivers/memory/samsung/Kconfig"
>   source "drivers/memory/tegra/Kconfig"
> +source "drivers/memory/mediatek/Kconfig"
>   
>   endif
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index d2e6ca9abbe0..c0facf529803 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -27,6 +27,7 @@ obj-$(CONFIG_STM32_FMC2_EBI)	+= stm32-fmc2-ebi.o
>   
>   obj-$(CONFIG_SAMSUNG_MC)	+= samsung/
>   obj-$(CONFIG_TEGRA_MC)		+= tegra/
> +obj-$(CONFIG_MEDIATEK_MC)	+= mediatek/
>   obj-$(CONFIG_TI_EMIF_SRAM)	+= ti-emif-sram.o
>   obj-$(CONFIG_FPGA_DFL_EMIF)	+= dfl-emif.o
>   
> diff --git a/drivers/memory/mediatek/Kconfig b/drivers/memory/mediatek/Kconfig
> new file mode 100644
> index 000000000000..3f238e0d9647
> --- /dev/null
> +++ b/drivers/memory/mediatek/Kconfig
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config MEDIATEK_MC
> +	bool "MediaTek Memory Controller support"
> +	help
> +	  This option allows to enable MediaTek memory controller drivers,
> +	  which may include controllers for DRAM or others.
> +	  Select Y here if you need support for MediaTek memory controller.
> +	  If you don't need, select N.
> +
> +if MEDIATEK_MC
> +
> +config MTK_DRAMC
> +	tristate "MediaTek DRAMC driver"
> +	default y
> +	help
> +	  This option selects the MediaTek DRAMC driver, which provides
> +	  an interface for reporting the current data rate of DRAM.
> +	  Select Y here if you need support for the MediaTek DRAMC driver.
> +	  If you don't need, select N.
> +
> +endif
> diff --git a/drivers/memory/mediatek/Makefile b/drivers/memory/mediatek/Makefile
> new file mode 100644
> index 000000000000..a1395fc55b41
> --- /dev/null
> +++ b/drivers/memory/mediatek/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_MTK_DRAMC)		+= mtk-dramc.o
> diff --git a/drivers/memory/mediatek/mtk-dramc.c b/drivers/memory/mediatek/mtk-dramc.c
> new file mode 100644
> index 000000000000..d452483a98ce
> --- /dev/null
> +++ b/drivers/memory/mediatek/mtk-dramc.c
> @@ -0,0 +1,196 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +#include <linux/bitops.h>
> +#include <linux/bitfield.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/printk.h>
> +
> +#define POSDIV_PURIFY	BIT(2)
> +#define PREDIV		7
> +#define REF_FREQUENCY	26

REF_FREQUENCY should be platform data, not a definition, as this is
different in other SoCs.

> +#define SHUFFLE_OFFSET	0x700
> +
> +/*--------------------------------------------------------------------------*/
> +/* Register Offset                                                          */
> +/*--------------------------------------------------------------------------*/
> +#define DPHY_DVFS_STA		0x0e98
> +#define APHY_PHYPLL2		0x0908
> +#define APHY_CLRPLL2		0x0928
> +#define APHY_PHYPLL3		0x090c
> +#define APHY_CLRPLL3		0x092c
> +#define APHY_PHYPLL4		0x0910
> +#define APHY_ARPI0		0x0d94
> +#define APHY_CA_ARDLL1		0x0d08
> +#define APHY_B0_TX0		0x0dc4

Aren't those also SoC-dependant?

enum mtk_dramc_reg_index {
	DRAMC_DPHY_DVFS_STA,
	DRAMC_APHY_SHU_PHYPLL2,
	....etc
}

static const u16 mtk_dramc_regs_mt8195[] = {
	[DRAMC_DPHY_DVFS_STA] = 0x50c, /* ddrphy_config_NAO */
	[DRAMC_APHY_SHU_PHYPLL2] = 0x704,
	[DRAMC_APHY_SHU_CLRPLL2] = 0x724,
	[DRAMC_APHY_SHU_PHYPLL3] = 0x708,
	[DRAMC_APHY_SHU_CLRPLL3] = 0x728,
	[DRAMC_APHY_SHU_PHYPLL4] = 0x70c,
	...etc
}

static const u16 mtk_dramc_regs_mt8196[] = {
	[DRAMC_DPHY_DVFS_STA] = 0xe98, /* ddrphy_config_misc */
	[DRAMC_APHY_SHU_PHYPLL2] = 0x908,
	[DRAMC_APHY_SHU_CLRPLL2] = 0x928,
	.... etc
}

> +
> +/*--------------------------------------------------------------------------*/
> +/* Register Mask                                                            */
> +/*--------------------------------------------------------------------------*/
> +#define DPHY_DVFS_SHU_LV	GENMASK(15, 14)
> +#define DPHY_DVFS_PLL_SEL	GENMASK(25, 25)
> +#define APHY_PLL2_SDMPCW	GENMASK(18, 3)
> +#define APHY_PLL3_POSDIV	GENMASK(13, 11)
> +#define APHY_PLL4_FBKSEL	GENMASK(6, 6)
> +#define APHY_ARPI0_SOPEN	GENMASK(26, 26)
> +#define APHY_ARDLL1_CK_EN	GENMASK(0, 0)
> +#define APHY_B0_TX0_SER_MODE	GENMASK(4, 3)

And those masks should also be platform data, as those are also different
in other SoCs.

> +
> +static unsigned int read_reg_field(void __iomem *base, unsigned int offset, unsigned int mask)
> +{
> +	unsigned int val = readl(base + offset);
> +	unsigned int shift = __ffs(mask);
> +
> +	return (val & mask) >> shift;
> +}
> +
> +struct mtk_dramc_pdata {
> +	unsigned int fmeter_version;

u8 fmeter_version;
u8 ref_freq_mhz;
const u16 *regs;

...etc etc


> +};
> +
> +struct mtk_dramc_dev_t {
> +	void __iomem *anaphy_base;
> +	void __iomem *ddrphy_base;
> +	const struct mtk_dramc_pdata *pdata;
> +};
> +
> +static int mtk_dramc_probe(struct platform_device *pdev)
> +{
> +	struct mtk_dramc_dev_t *dramc;
> +	const struct mtk_dramc_pdata *pdata;
> +	int ret;
> +
> +	dramc = devm_kzalloc(&pdev->dev, sizeof(struct mtk_dramc_dev_t), GFP_KERNEL);
> +	if (!dramc)
> +		return dev_err_probe(&pdev->dev, -ENOMEM, "Failed to allocate memory\n");
> +
> +	pdata = of_device_get_match_data(&pdev->dev);
> +	if (!pdata)
> +		return dev_err_probe(&pdev->dev, -EINVAL, "No platform data available\n");
> +
> +	dramc->pdata = pdata;
> +
> +	dramc->anaphy_base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(dramc->anaphy_base)) {
> +		ret = PTR_ERR(dramc->anaphy_base);
> +		return dev_err_probe(&pdev->dev, ret, "Unable to map DDRPHY NAO base\n");
> +	}
> +
> +	dramc->ddrphy_base = devm_platform_ioremap_resource(pdev, 1);
> +	if (IS_ERR(dramc->ddrphy_base)) {
> +		ret = PTR_ERR(dramc->ddrphy_base);
> +		return dev_err_probe(&pdev->dev, ret, "Unable to map DDRPHY AO base\n");
> +	}
> +
> +	platform_set_drvdata(pdev, dramc);
> +	return 0;
> +}
> +
> +static unsigned int mtk_fmeter_v1(struct mtk_dramc_dev_t *dramc)
> +{
> +	unsigned int shu_level, pll_sel, offset;
> +	unsigned int sdmpcw, posdiv, ckdiv4, fbksel, sopen, async_ca, ser_mode;
> +	unsigned int perdiv_freq, posdiv_freq, vco_freq;
> +	unsigned int final_rate;
> +
> +	shu_level = read_reg_field(dramc->ddrphy_base, DPHY_DVFS_STA, DPHY_DVFS_SHU_LV);
> +	pll_sel = read_reg_field(dramc->ddrphy_base, DPHY_DVFS_STA, DPHY_DVFS_PLL_SEL);
> +	offset = SHUFFLE_OFFSET * shu_level;
> +
> +	sdmpcw = read_reg_field(dramc->anaphy_base,
> +				((pll_sel == 0) ? APHY_PHYPLL2 : APHY_CLRPLL2) + offset,
> +				APHY_PLL2_SDMPCW);
> +	posdiv = read_reg_field(dramc->anaphy_base,
> +				((pll_sel == 0) ? APHY_PHYPLL3 : APHY_CLRPLL3) + offset,
> +				APHY_PLL3_POSDIV);
> +	fbksel = read_reg_field(dramc->anaphy_base, APHY_PHYPLL4 + offset, APHY_PLL4_FBKSEL);
> +	sopen = read_reg_field(dramc->anaphy_base, APHY_ARPI0 + offset, APHY_ARPI0_SOPEN);
> +	async_ca = read_reg_field(dramc->anaphy_base, APHY_CA_ARDLL1 + offset, APHY_ARDLL1_CK_EN);
> +	ser_mode = read_reg_field(dramc->anaphy_base, APHY_B0_TX0 + offset, APHY_B0_TX0_SER_MODE);
> +
> +	ckdiv4 = (ser_mode == 1) ? 1 : 0;
> +	posdiv &= ~(POSDIV_PURIFY);
> +
> +	perdiv_freq = REF_FREQUENCY * (sdmpcw >> PREDIV);

s/perdiv/prediv/g

> +	posdiv_freq = (perdiv_freq >> posdiv) >> 1;
> +	vco_freq = posdiv_freq << fbksel;
> +	final_rate = vco_freq >> ckdiv4;
> +

there's also one case in which `final_rate >>= 2`... please check if it is
applicable to this driver (it should).

Cheers,
Angelo

> +	if (sopen == 1 && async_ca == 1)
> +		final_rate >>= 1;
> +
> +	return final_rate;
> +}
> +
> +/*
> + * mtk_dramc_get_data_rate - calculate DRAM data rate
> + *
> + * Returns DRAM data rate (MB/s)
> + */
> +static unsigned int mtk_dramc_get_data_rate(struct device *dev)
> +{
> +	struct mtk_dramc_dev_t *dramc_dev = dev_get_drvdata(dev);
> +
> +	if (!dramc_dev) {
> +		dev_err(dev, "DRAMC device data not found\n");
> +		return -EINVAL;
> +	}
> +
> +	if (dramc_dev->pdata) {
> +		if (dramc_dev->pdata->fmeter_version == 1)
> +			return mtk_fmeter_v1(dramc_dev);
> +
> +		dev_err(dev, "Unsupported fmeter version\n");
> +		return -EINVAL;
> +	}
> +	dev_err(dev, "DRAMC platform data not found\n");
> +	return -EINVAL;
> +}
> +
> +static ssize_t dram_data_rate_show(struct device *dev,
> +				   struct device_attribute *attr, char *buf)
> +{
> +	return snprintf(buf, PAGE_SIZE, "DRAM data rate = %u\n",
> +			mtk_dramc_get_data_rate(dev));
> +}
> +
> +static DEVICE_ATTR_RO(dram_data_rate);
> +
> +static struct attribute *mtk_dramc_attrs[] = {
> +	&dev_attr_dram_data_rate.attr,
> +	NULL
> +};
> +ATTRIBUTE_GROUPS(mtk_dramc);
> +
> +static const struct mtk_dramc_pdata dramc_pdata_mt8196 = {
> +	.fmeter_version = 1
> +};
> +
> +static const struct of_device_id mtk_dramc_of_ids[] = {
> +	{ .compatible = "mediatek,mt8196-dramc", .data = &dramc_pdata_mt8196 },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, mtk_dramc_of_ids);
> +
> +static struct platform_driver mtk_dramc_driver = {
> +	.probe = mtk_dramc_probe,
> +	.driver = {
> +		.name = "mtk_dramc_drv",
> +		.of_match_table = mtk_dramc_of_ids,
> +		.dev_groups = mtk_dramc_groups,
> +	},
> +};
> +
> +module_platform_driver(mtk_dramc_driver);
> +
> +MODULE_AUTHOR("Crystal Guo <crystal.guo at mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek DRAM Controller Driver");
> +MODULE_LICENSE("GPL");



From suzuki.poulose at arm.com  Tue Mar  4 06:59:56 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 4 Mar 2025 14:59:56 +0000
Subject: [PATCH v15 09/10] Coresight: Add Coresight TMC Control Unit
 driver
In-Reply-To: <20250303032931.2500935-10-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-10-quic_jiegan@quicinc.com>
Message-ID: <1b05e832-6d41-463a-a52a-6ff340d0d6f8@arm.com>

On 03/03/2025 03:29, Jie Gan wrote:
> The Coresight TMC Control Unit hosts miscellaneous configuration registers
> which control various features related to TMC ETR sink.
> 
> Based on the trace ID, which is programmed in the related CTCU ATID
> register of a specific ETR, trace data with that trace ID gets into
> the ETR buffer, while other trace data gets dropped.
> 
> Enabling source device sets one bit of the ATID register based on
> source device's trace ID.
> Disabling source device resets the bit according to the source
> device's trace ID.
> 
> Reviewed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>

...

> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _CORESIGHT_CTCU_H
> +#define _CORESIGHT_CTCU_H
> +#include "coresight-trace-id.h"
> +
> +/* Maximum number of supported ETR devices for a single CTCU. */
> +#define ETR_MAX_NUM 	2
> +

WARNING: please, no space before tabs
#413: FILE: drivers/hwtracing/coresight/coresight-ctcu.h:11:
+#define ETR_MAX_NUM ^I2$

total: 0 errors, 2 warnings, 397 lines checked

Another checkpatch warning. Please take care in the future.

Suzuki




From quentin.schulz at cherry.de  Tue Mar  4 07:00:00 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Tue, 4 Mar 2025 16:00:00 +0100
Subject: [PATCH v3 3/3] drm/rockchip: lvds: lower log severity for missing
 pinctrl settings
In-Reply-To: <20250304124418.111061-4-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
 <20250304124418.111061-4-heiko@sntech.de>
Message-ID: <23b59af6-da87-44c2-8916-65f7df146306@cherry.de>

Hi Heiko,

On 3/4/25 1:44 PM, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner at cherry.de>
> 
> While missing lvds pinctrl is unexpected and is reported, we nevertheless
> don't fail setting up the device and instead continue without explicit
> pinctrl handling. So lower the log-level from error to warning to reflect
> that.
> 

Suggested-by: Quentin Schulz <quentin.schulz at cherry.de>
Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>

Thanks!
Quentin


From jic23 at kernel.org  Tue Mar  4 07:01:35 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Tue, 4 Mar 2025 15:01:35 +0000
Subject: [PATCH v2 1/2] dt-bindings: iio: adc: Add
 rockchip,rk3562-saradc string
In-Reply-To: <174077321955.3490993.13046330315407577605.robh@kernel.org>
References: <20250227110343.2342017-1-kever.yang@rock-chips.com>
	<174077321955.3490993.13046330315407577605.robh@kernel.org>
Message-ID: <20250304150135.5ac5bb1c@jic23-huawei>

On Fri, 28 Feb 2025 14:06:59 -0600
"Rob Herring (Arm)" <robh at kernel.org> wrote:

> On Thu, 27 Feb 2025 19:03:42 +0800, Kever Yang wrote:
> > Add rockchip,rk3562-saradc compatible string.
> > The saradc on rk3562 is v2 controller, with 10bit width which is different
> > with rk3588.
> > 
> > Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> > ---
> > 
> > Changes in v2:
> > - fix dtb check error
> > 
> >  Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml | 1 +
> >  1 file changed, 1 insertion(+)
> >   
> 
> Acked-by: Rob Herring (Arm) <robh at kernel.org>
> 

Hi Kever,
I'm applying patches in a fairly random order today and in this
case I'd already picked up support for the rk3528 so there was a bit
of noise on this. Please check the result in the testing branch of iio.git
on kernel.org.

Thanks,

Jonathan



From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:03:13 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:33:13 +0530
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <20250214173944.47506-5-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com>
Message-ID: <20250304150313.ey4fky35bu6dbtxd@thinkpad>

On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> If regulator_bulk_get() returns an error, no regulators are created and we
> need to set their number to zero.  If we do not do this and the PCIe
> link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> 
> Also print out the error value, as we cannot return an error upwards as
> Linux will WARN on an error from add_bus().
> 
> Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> ---
>  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index e0b20f58c604..56b49d3cae19 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
>  
>  		ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
>  		if (ret) {
> -			dev_info(dev, "No regulators for downstream device\n");
> +			dev_info(dev, "Did not get regulators; err=%d\n", ret);

Why is this dev_info() instead of dev_err()?

> +			pcie->sr = NULL;

Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?

- Mani

-- 
????????? ????????


From jic23 at kernel.org  Tue Mar  4 07:04:08 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Tue, 4 Mar 2025 15:04:08 +0000
Subject: [PATCH v2 2/2] iio: adc: rockchip_saradc: add rk3562
In-Reply-To: <20250227110343.2342017-2-kever.yang@rock-chips.com>
References: <20250227110343.2342017-1-kever.yang@rock-chips.com>
	<20250227110343.2342017-2-kever.yang@rock-chips.com>
Message-ID: <20250304150408.60864bbd@jic23-huawei>

On Thu, 27 Feb 2025 19:03:43 +0800
Kever Yang <kever.yang at rock-chips.com> wrote:

> From: Simon Xue <xxm at rock-chips.com>
> 
> rk3562 is using v2 saradc with 8 channels.
> 
> Signed-off-by: Simon Xue <xxm at rock-chips.com>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  drivers/iio/adc/rockchip_saradc.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
> index a29e54754c8f..9995f95bafe0 100644
> --- a/drivers/iio/adc/rockchip_saradc.c
> +++ b/drivers/iio/adc/rockchip_saradc.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Rockchip Successive Approximation Register (SAR) A/D Converter
> - * Copyright (C) 2014 ROCKCHIP, Inc.
> + * Copyright (C) 2014 Rockchip Electronics Co., Ltd.
This 'fixup' should have been mentioned in the patch description.
Not that important though so I'll leave it this time.


From ryan.roberts at arm.com  Tue Mar  4 07:04:31 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:31 +0000
Subject: [PATCH v3 01/11] arm64: hugetlb: Cleanup huge_pte size discovery mechanisms
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-2-ryan.roberts@arm.com>

Not all huge_pte helper APIs explicitly provide the size of the
huge_pte. So the helpers have to depend on various methods to determine
the size of the huge_pte. Some of these methods are dubious.

Let's clean up the code to use preferred methods and retire the dubious
ones. The options in order of preference:

 - If size is provided as parameter, use it together with
   num_contig_ptes(). This is explicit and works for both present and
   non-present ptes.

 - If vma is provided as a parameter, retrieve size via
   huge_page_size(hstate_vma(vma)) and use it together with
   num_contig_ptes(). This is explicit and works for both present and
   non-present ptes.

 - If the pte is present and contiguous, use find_num_contig() to walk
   the pgtable to find the level and infer the number of ptes from
   level. Only works for *present* ptes.

 - If the pte is present and not contiguous and you can infer from this
   that only 1 pte needs to be operated on. This is ok if you don't care
   about the absolute size, and just want to know the number of ptes.

 - NEVER rely on resolving the PFN of a present pte to a folio and
   getting the folio's size. This is fragile at best, because there is
   nothing to stop the core-mm from allocating a folio twice as big as
   the huge_pte then mapping it across 2 consecutive huge_ptes. Or just
   partially mapping it.

Where we require that the pte is present, add warnings if not-present.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/mm/hugetlbpage.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index b3a7fafe8892..6a2af9fb2566 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -129,7 +129,7 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 	if (!pte_present(orig_pte) || !pte_cont(orig_pte))
 		return orig_pte;
 
-	ncontig = num_contig_ptes(page_size(pte_page(orig_pte)), &pgsize);
+	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
 	for (i = 0; i < ncontig; i++, ptep++) {
 		pte_t pte = __ptep_get(ptep);
 
@@ -438,16 +438,19 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 	pgprot_t hugeprot;
 	pte_t orig_pte;
 
+	VM_WARN_ON(!pte_present(pte));
+
 	if (!pte_cont(pte))
 		return __ptep_set_access_flags(vma, addr, ptep, pte, dirty);
 
-	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
+	ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
 	dpfn = pgsize >> PAGE_SHIFT;
 
 	if (!__cont_access_flags_changed(ptep, pte, ncontig))
 		return 0;
 
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
+	VM_WARN_ON(!pte_present(orig_pte));
 
 	/* Make sure we don't lose the dirty or young state */
 	if (pte_dirty(orig_pte))
@@ -472,7 +475,10 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 	size_t pgsize;
 	pte_t pte;
 
-	if (!pte_cont(__ptep_get(ptep))) {
+	pte = __ptep_get(ptep);
+	VM_WARN_ON(!pte_present(pte));
+
+	if (!pte_cont(pte)) {
 		__ptep_set_wrprotect(mm, addr, ptep);
 		return;
 	}
@@ -496,11 +502,15 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 	size_t pgsize;
 	int ncontig;
+	pte_t pte;
+
+	pte = __ptep_get(ptep);
+	VM_WARN_ON(!pte_present(pte));
 
-	if (!pte_cont(__ptep_get(ptep)))
+	if (!pte_cont(pte))
 		return ptep_clear_flush(vma, addr, ptep);
 
-	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
+	ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
 	return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 }
 
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:30 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:30 +0000
Subject: [PATCH v3 00/11] Perf improvements for hugetlb and vmalloc on arm64
Message-ID: <20250304150444.3788920-1-ryan.roberts@arm.com>

Hi All,

This is v3 of a series to improve performance for hugetlb and vmalloc on arm64.
Although some of these patches are core-mm, advice from Andrew was to go via the
arm64 tree. Hopefully I can get some ACKs from mm folks.

The 2 key performance improvements are 1) enabling the use of contpte-mapped
blocks in the vmalloc space when appropriate (which reduces TLB pressure). There
were already hooks for this (used by powerpc) but they required some tidying and
extending for arm64. And 2) batching up barriers when modifying the vmalloc
address space for upto 30% reduction in time taken in vmalloc().

vmalloc() performance was measured using the test_vmalloc.ko module. Tested on
Apple M2 and Ampere Altra. Each test had loop count set to 500000 and the whole
test was repeated 10 times.

legend:
  - p: nr_pages (pages to allocate)
  - h: use_huge (vmalloc() vs vmalloc_huge())
  - (I): statistically significant improvement (95% CI does not overlap)
  - (R): statistically significant regression (95% CI does not overlap)
  - measurements are times; smaller is better

+--------------------------------------------------+-------------+-------------+
| Benchmark                                        |             |             |
|   Result Class                                   |    Apple M2 | Ampere Alta |
+==================================================+=============+=============+
| micromm/vmalloc                                  |             |             |
|   fix_align_alloc_test: p:1, h:0 (usec)          | (I) -11.53% |      -2.57% |
|   fix_size_alloc_test: p:1, h:0 (usec)           |       2.14% |       1.79% |
|   fix_size_alloc_test: p:4, h:0 (usec)           |  (I) -9.93% |  (I) -4.80% |
|   fix_size_alloc_test: p:16, h:0 (usec)          | (I) -25.07% | (I) -14.24% |
|   fix_size_alloc_test: p:16, h:1 (usec)          | (I) -14.07% |   (R) 7.93% |
|   fix_size_alloc_test: p:64, h:0 (usec)          | (I) -29.43% | (I) -19.30% |
|   fix_size_alloc_test: p:64, h:1 (usec)          | (I) -16.39% |   (R) 6.71% |
|   fix_size_alloc_test: p:256, h:0 (usec)         | (I) -31.46% | (I) -20.60% |
|   fix_size_alloc_test: p:256, h:1 (usec)         | (I) -16.58% |   (R) 6.70% |
|   fix_size_alloc_test: p:512, h:0 (usec)         | (I) -31.96% | (I) -20.04% |
|   fix_size_alloc_test: p:512, h:1 (usec)         |       2.30% |       0.71% |
|   full_fit_alloc_test: p:1, h:0 (usec)           |      -2.94% |       1.77% |
|   kvfree_rcu_1_arg_vmalloc_test: p:1, h:0 (usec) |      -7.75% |       1.71% |
|   kvfree_rcu_2_arg_vmalloc_test: p:1, h:0 (usec) |      -9.07% |   (R) 2.34% |
|   long_busy_list_alloc_test: p:1, h:0 (usec)     | (I) -29.18% | (I) -17.91% |
|   pcpu_alloc_test: p:1, h:0 (usec)               |     -14.71% |      -3.14% |
|   random_size_align_alloc_test: p:1, h:0 (usec)  | (I) -11.08% |  (I) -4.62% |
|   random_size_alloc_test: p:1, h:0 (usec)        | (I) -30.25% | (I) -17.95% |
|   vm_map_ram_test: p:1, h:0 (usec)               |       5.06% |   (R) 6.63% |
+--------------------------------------------------+-------------+-------------+

So there are some nice improvements but also some regressions to explain:

fix_size_alloc_test with h:1 and p:16,64,256 regress by ~6% on Altra. The
regression is actually introduced by enabling contpte-mapped 64K blocks in these
tests, and that regression is reduced (from about 8% if memory serves) by doing
the barrier batching. I don't have a definite conclusion on the root cause, but
I've ruled out the differences in the mapping paths in vmalloc. I strongly
believe this is likely due to the difference in the allocation path; 64K blocks
are not cached per-cpu so we have to go all the way to the buddy. I'm not sure
why this doesn't show up on M2 though. Regardless, I'm going to assert that it's
better to choose 16x reduction in TLB pressure vs 6% on the vmalloc allocation
call duration.

Changes since v2 [2]
====================
- Removed the new arch_update_kernel_mappings_[begin|end]() API
- Switches to arch_[enter|leave]_lazy_mmu_mode() instead for barrier batching
- Removed clean up to avoid barriers for invalid or user mappings

Changes since v1 [1]
====================
- Split out the fixes into their own series
- Added Rbs from Anshuman - Thanks!
- Added patch to clean up the methods by which huge_pte size is determined
- Added "#ifndef __PAGETABLE_PMD_FOLDED" around PUD_SIZE in
  flush_hugetlb_tlb_range()
- Renamed ___set_ptes() -> set_ptes_anysz()
- Renamed ___ptep_get_and_clear() -> ptep_get_and_clear_anysz()
- Fixed typos in commit logs
- Refactored pXd_valid_not_user() for better reuse
- Removed TIF_KMAP_UPDATE_PENDING after concluding that single flag is sufficent
- Concluded the extra isb() in __switch_to() is not required
- Only call arch_update_kernel_mappings_[begin|end]() for kernel mappings

Applies on top of v6.14-rc5, which already contains the fixes from [3]. All
mm selftests run and pass.

NOTE: Its possible that the changes in patch #10 may cause bugs I found in other
archs' lazy mmu implementations to become more likely to trigger. I've fixed all
those bugs in the series at [4], which is now in mm-unstable. But some
coordination when merging this may be required.

[1] https://lore.kernel.org/all/20250205151003.88959-1-ryan.roberts at arm.com/
[2] https://lore.kernel.org/all/20250217140809.1702789-1-ryan.roberts at arm.com/
[3] https://lore.kernel.org/all/20250217140419.1702389-1-ryan.roberts at arm.com/
[4] https://lore.kernel.org/all/20250303141542.3371656-1-ryan.roberts at arm.com/

Thanks,
Ryan

Ryan Roberts (11):
  arm64: hugetlb: Cleanup huge_pte size discovery mechanisms
  arm64: hugetlb: Refine tlb maintenance scope
  mm/page_table_check: Batch-check pmds/puds just like ptes
  arm64/mm: Refactor __set_ptes() and __ptep_get_and_clear()
  arm64: hugetlb: Use set_ptes_anysz() and ptep_get_and_clear_anysz()
  arm64/mm: Hoist barriers out of set_ptes_anysz() loop
  mm/vmalloc: Warn on improper use of vunmap_range()
  mm/vmalloc: Gracefully unmap huge ptes
  arm64/mm: Support huge pte-mapped pages in vmap
  mm/vmalloc: Enter lazy mmu mode while manipulating vmalloc ptes
  arm64/mm: Batch barriers when updating kernel mappings

 arch/arm64/include/asm/hugetlb.h     |  29 ++--
 arch/arm64/include/asm/pgtable.h     | 195 ++++++++++++++++++---------
 arch/arm64/include/asm/thread_info.h |   2 +
 arch/arm64/include/asm/vmalloc.h     |  45 +++++++
 arch/arm64/kernel/process.c          |   9 +-
 arch/arm64/mm/hugetlbpage.c          |  72 ++++------
 include/linux/page_table_check.h     |  30 +++--
 include/linux/vmalloc.h              |   8 ++
 mm/page_table_check.c                |  34 +++--
 mm/vmalloc.c                         |  40 +++++-
 10 files changed, 315 insertions(+), 149 deletions(-)

--
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:40 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:40 +0000
Subject: [PATCH v3 10/11] mm/vmalloc: Enter lazy mmu mode while manipulating vmalloc ptes
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-11-ryan.roberts@arm.com>

Wrap vmalloc's pte table manipulation loops with
arch_enter_lazy_mmu_mode() / arch_leave_lazy_mmu_mode(). This provides
the arch code with the opportunity to optimize the pte manipulations.

Note that vmap_pfn() already uses lazy mmu mode since it delegates to
apply_to_page_range() which enters lazy mmu mode for both user and
kernel mappings.

These hooks will shortly be used by arm64 to improve vmalloc
performance.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 mm/vmalloc.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 6111ce900ec4..b63ca0b7dd40 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -104,6 +104,9 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	pte = pte_alloc_kernel_track(pmd, addr, mask);
 	if (!pte)
 		return -ENOMEM;
+
+	arch_enter_lazy_mmu_mode();
+
 	do {
 		if (unlikely(!pte_none(ptep_get(pte)))) {
 			if (pfn_valid(pfn)) {
@@ -127,6 +130,8 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 		set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
 		pfn++;
 	} while (pte += PFN_DOWN(size), addr += size, addr != end);
+
+	arch_leave_lazy_mmu_mode();
 	*mask |= PGTBL_PTE_MODIFIED;
 	return 0;
 }
@@ -354,6 +359,8 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	unsigned long size = PAGE_SIZE;
 
 	pte = pte_offset_kernel(pmd, addr);
+	arch_enter_lazy_mmu_mode();
+
 	do {
 #ifdef CONFIG_HUGETLB_PAGE
 		size = arch_vmap_pte_range_unmap_size(addr, pte);
@@ -370,6 +377,8 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 			ptent = ptep_get_and_clear(&init_mm, addr, pte);
 		WARN_ON(!pte_none(ptent) && !pte_present(ptent));
 	} while (pte += (size >> PAGE_SHIFT), addr += size, addr != end);
+
+	arch_leave_lazy_mmu_mode();
 	*mask |= PGTBL_PTE_MODIFIED;
 }
 
@@ -515,6 +524,9 @@ static int vmap_pages_pte_range(pmd_t *pmd, unsigned long addr,
 	pte = pte_alloc_kernel_track(pmd, addr, mask);
 	if (!pte)
 		return -ENOMEM;
+
+	arch_enter_lazy_mmu_mode();
+
 	do {
 		struct page *page = pages[*nr];
 
@@ -528,6 +540,8 @@ static int vmap_pages_pte_range(pmd_t *pmd, unsigned long addr,
 		set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
 		(*nr)++;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
+
+	arch_leave_lazy_mmu_mode();
 	*mask |= PGTBL_PTE_MODIFIED;
 	return 0;
 }
-- 
2.43.0



From ryan.roberts at arm.com  Tue Mar  4 07:04:41 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue,  4 Mar 2025 15:04:41 +0000
Subject: [PATCH v3 11/11] arm64/mm: Batch barriers when updating kernel mappings
In-Reply-To: <20250304150444.3788920-1-ryan.roberts@arm.com>
References: <20250304150444.3788920-1-ryan.roberts@arm.com>
Message-ID: <20250304150444.3788920-12-ryan.roberts@arm.com>

Because the kernel can't tolerate page faults for kernel mappings, when
setting a valid, kernel space pte (or pmd/pud/p4d/pgd), it emits a
dsb(ishst) to ensure that the store to the pgtable is observed by the
table walker immediately. Additionally it emits an isb() to ensure that
any already speculatively determined invalid mapping fault gets
canceled.

We can improve the performance of vmalloc operations by batching these
barriers until the end of a set of entry updates.
arch_enter_lazy_mmu_mode() and arch_leave_lazy_mmu_mode() provide the
required hooks.

vmalloc improves by up to 30% as a result.

Two new TIF_ flags are created; TIF_LAZY_MMU tells us if the task is in
the lazy mode and can therefore defer any barriers until exit from the
lazy mode. TIF_LAZY_MMU_PENDING is used to remember if any pte operation
was performed while in the lazy mode that required barriers. Then when
leaving lazy mode, if that flag is set, we emit the barriers.

Since arch_enter_lazy_mmu_mode() and arch_leave_lazy_mmu_mode() are used
for both user and kernel mappings, we need the second flag to avoid
emitting barriers unnecessarily if only user mappings were updated.

Signed-off-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/include/asm/pgtable.h     | 73 ++++++++++++++++++++++------
 arch/arm64/include/asm/thread_info.h |  2 +
 arch/arm64/kernel/process.c          |  9 ++--
 3 files changed, 64 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 1898c3069c43..149df945c1ab 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -40,6 +40,55 @@
 #include <linux/sched.h>
 #include <linux/page_table_check.h>
 
+static inline void emit_pte_barriers(void)
+{
+	/*
+	 * These barriers are emitted under certain conditions after a pte entry
+	 * was modified (see e.g. __set_pte_complete()). The dsb makes the store
+	 * visible to the table walker. The isb ensures that any previous
+	 * speculative "invalid translation" marker that is in the CPU's
+	 * pipeline gets cleared, so that any access to that address after
+	 * setting the pte to valid won't cause a spurious fault. If the thread
+	 * gets preempted after storing to the pgtable but before emitting these
+	 * barriers, __switch_to() emits a dsb which ensure the walker gets to
+	 * see the store. There is no guarrantee of an isb being issued though.
+	 * This is safe because it will still get issued (albeit on a
+	 * potentially different CPU) when the thread starts running again,
+	 * before any access to the address.
+	 */
+	dsb(ishst);
+	isb();
+}
+
+static inline void queue_pte_barriers(void)
+{
+	if (test_thread_flag(TIF_LAZY_MMU))
+		set_thread_flag(TIF_LAZY_MMU_PENDING);
+	else
+		emit_pte_barriers();
+}
+
+#define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+static inline void arch_enter_lazy_mmu_mode(void)
+{
+	VM_WARN_ON(in_interrupt());
+	VM_WARN_ON(test_thread_flag(TIF_LAZY_MMU));
+
+	set_thread_flag(TIF_LAZY_MMU);
+}
+
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+	if (test_and_clear_thread_flag(TIF_LAZY_MMU_PENDING))
+		emit_pte_barriers();
+}
+
+static inline void arch_leave_lazy_mmu_mode(void)
+{
+	arch_flush_lazy_mmu_mode();
+	clear_thread_flag(TIF_LAZY_MMU);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
 
@@ -323,10 +372,8 @@ static inline void __set_pte_complete(pte_t pte)
 	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
 	 * has the necessary barriers.
 	 */
-	if (pte_valid_not_user(pte)) {
-		dsb(ishst);
-		isb();
-	}
+	if (pte_valid_not_user(pte))
+		queue_pte_barriers();
 }
 
 static inline void __set_pte(pte_t *ptep, pte_t pte)
@@ -778,10 +825,8 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 
 	WRITE_ONCE(*pmdp, pmd);
 
-	if (pmd_valid(pmd)) {
-		dsb(ishst);
-		isb();
-	}
+	if (pmd_valid(pmd))
+		queue_pte_barriers();
 }
 
 static inline void pmd_clear(pmd_t *pmdp)
@@ -845,10 +890,8 @@ static inline void set_pud(pud_t *pudp, pud_t pud)
 
 	WRITE_ONCE(*pudp, pud);
 
-	if (pud_valid(pud)) {
-		dsb(ishst);
-		isb();
-	}
+	if (pud_valid(pud))
+		queue_pte_barriers();
 }
 
 static inline void pud_clear(pud_t *pudp)
@@ -925,8 +968,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
 	}
 
 	WRITE_ONCE(*p4dp, p4d);
-	dsb(ishst);
-	isb();
+	queue_pte_barriers();
 }
 
 static inline void p4d_clear(p4d_t *p4dp)
@@ -1052,8 +1094,7 @@ static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
 	}
 
 	WRITE_ONCE(*pgdp, pgd);
-	dsb(ishst);
-	isb();
+	queue_pte_barriers();
 }
 
 static inline void pgd_clear(pgd_t *pgdp)
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 1114c1c3300a..1fdd74b7b831 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -82,6 +82,8 @@ void arch_setup_new_exec(void);
 #define TIF_SME_VL_INHERIT	28	/* Inherit SME vl_onexec across exec */
 #define TIF_KERNEL_FPSTATE	29	/* Task is in a kernel mode FPSIMD section */
 #define TIF_TSC_SIGSEGV		30	/* SIGSEGV on counter-timer access */
+#define TIF_LAZY_MMU		31	/* Task in lazy mmu mode */
+#define TIF_LAZY_MMU_PENDING	32	/* Ops pending for lazy mmu mode exit */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 42faebb7b712..45a55fe81788 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -680,10 +680,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	gcs_thread_switch(next);
 
 	/*
-	 * Complete any pending TLB or cache maintenance on this CPU in case
-	 * the thread migrates to a different CPU.
-	 * This full barrier is also required by the membarrier system
-	 * call.
+	 * Complete any pending TLB or cache maintenance on this CPU in case the
+	 * thread migrates to a different CPU. This full barrier is also
+	 * required by the membarrier system call. Additionally it makes any
+	 * in-progress pgtable writes visible to the table walker; See
+	 * emit_pte_barriers().
 	 */
 	dsb(ish);
 
-- 
2.43.0



From pierre.gondois at arm.com  Tue Mar  4 07:07:35 2025
From: pierre.gondois at arm.com (Pierre Gondois)
Date: Tue, 4 Mar 2025 16:07:35 +0100
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <Z8bPtsO7dEV0lq2M@bogus>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com> <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com> <Z8WPiOweOjFZqTwN@bogus>
 <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>
 <2fdea4f6-db98-4dc7-947f-e19ee54d2c3c@arm.com> <Z8bPtsO7dEV0lq2M@bogus>
Message-ID: <153df413-9989-42fe-b574-598ff0fa9716@arm.com>



On 3/4/25 11:02, Sudeep Holla wrote:
> On Tue, Mar 04, 2025 at 09:25:02AM +0100, Pierre Gondois wrote:
>>
>>
>> On 3/3/25 15:40, Yicong Yang wrote:
>>> On 2025/3/3 19:16, Sudeep Holla wrote:
>>>> On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
>>>>> On 2/28/25 20:06, Sudeep Holla wrote:
>>>>>>>>
>>>>>>>> Ditto as previous patch, can get rid if it is default 1.
>>>>>>>>
>>>>>>>
>>>>>>> On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
>>>>>>> cpu_smt_num_threads uninitialized to UINT_MAX:
>>>>>>>
>>>>>>> smt/active:0
>>>>>>> smt/control:-1
>>>>>>>
>>>>>>> If cpu_smt_set_num_threads() is called:
>>>>>>> active:0
>>>>>>> control:notsupported
>>>>>>>
>>>>>>> So it might be slightly better to still initialize max_smt_thread_num.
>>>>>>>
>>>>>>
>>>>>> Sure, what I meant is to have max_smt_thread_num set to 1 by default is
>>>>>> that is what needed anyways and the above code does that now.
>>>>>>
>>>>>> Why not start with initialised to 1 instead ?
>>>>>> Of course some current logic needs to change around testing it for zero.
>>>>>>
>>>>>
>>>>> I think there would still be a way to check against the default value.
>>>>> If we have:
>>>>> unsigned int max_smt_thread_num = 1;
>>>>>
>>>>> then on a platform with 2 threads, the detection condition would trigger:
>>>>> xa_for_each(&hetero_cpu, hetero_id, entry) {
>>>>>       if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)     <---- (entry->thread_num=2) and (max_smt_thread_num=1)
>>>>>           pr_warn_once("Heterogeneous SMT topology is partly
>>>>>                         supported by SMT control\n");
>>>>>
>>>>> so we would need an additional variable:
>>>>> bool is_initialized = false;
>>>>
>>>> Sure, we could do that or skip the check if max_smt_thread_num == 1 ?
>>>>
>>>> I mean
>>>> 	if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)
>>>>
>>
>> I think it will be problematic if we parse:
>> - first a CPU with 1 thread
>> - then a CPU with 2 threads
>>
>> in that case we should detect the 'Heterogeneous SMT topology',
>> but we cannot because we don't know whether max_smt_thread_num=1
>> because 1 is the default value or we found a CPU with one thread.
> 
> Right, but as per Dietmar's and my previous response, it may be a valid
> case. See latest response from Dietmar which is explicitly requesting
> support for this. It may need some special handling if we decide to support
> that.

Ah ok, right indeed.
For heterogeneous SMT platforms, the 'smt/control' file is able to accept
on/off/forceoff strings. But providing the max #count of threads as an integer would
be wrong if the CPU doesn't have this #count of threads.

Initially the idea was to just warn that support might be needed for heterogeneous
SMT platforms, and let whoever would have such platform solve this case, but just
disabling the integer interface in this case would solve the issue generically.


From angelogioacchino.delregno at collabora.com  Tue Mar  4 07:39:30 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 16:39:30 +0100
Subject: [PATCH 2/3] ASoC: mediatek: common: Handle mediatek,accdet
 property
In-Reply-To: <20250214-mt8188-accdet-v1-2-6bbd5483855b@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-2-6bbd5483855b@collabora.com>
Message-ID: <a955f2cc-16a8-48dd-958f-2f2f2a3cc58e@collabora.com>

Il 14/02/25 16:14, N?colas F. R. A. Prado ha scritto:
> Handle the optional mediatek,accdet property. When present, retrieve the
> sound component from its phandle, so the machine sound driver can use it
> to register the audio jack and initialize the MT6359 ACCDET for jack
> detection.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Tue Mar  4 07:39:33 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 16:39:33 +0100
Subject: [PATCH 3/3] ASoC: mediatek: mt8188-mt6359: Add headset jack
 detect support
In-Reply-To: <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
Message-ID: <d976b28d-f44f-4d51-8b61-4c046c571412@collabora.com>

Il 14/02/25 16:14, N?colas F. R. A. Prado ha scritto:
> Enable headset jack detection for MT8188 platforms using the MT6359
> ACCDET block for it.
> 
> Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
> Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>   sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
>   1 file changed, 43 insertions(+)
> 
> diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> index 2d0d04e0232da07ba43a030b14853322427d55e7..4e19e6cfad1e1f42863b2e2f27131f880c5883bf 100644
> --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> @@ -17,6 +17,7 @@
>   #include "mt8188-afe-common.h"
>   #include "../../codecs/nau8825.h"
>   #include "../../codecs/mt6359.h"
> +#include "../../codecs/mt6359-accdet.h"
>   #include "../../codecs/rt5682.h"
>   #include "../common/mtk-afe-platform-driver.h"
>   #include "../common/mtk-soundcard-driver.h"
> @@ -266,6 +267,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
>   	},
>   };
>   
> +static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = {

This is the same as nau8825_jack_pins... perhaps we could reuse that?

> +	{
> +		.pin    = "Headphone",
> +		.mask   = SND_JACK_HEADPHONE,
> +	},
> +	{
> +		.pin    = "Headset Mic",
> +		.mask   = SND_JACK_MICROPHONE,
> +	},
> +};
> +
>   static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
>   	SOC_DAPM_PIN_SWITCH("Ext Spk"),
>   };
> @@ -500,6 +512,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
>   	return 0;
>   }
>   
> +static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd)
> +{
> +	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
> +	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
> +	int ret;
> +
> +	if (!soc_card_data->accdet)
> +		return 0;

I'm not sure... if we have mediatek,accdet (so accdet is present here), but we also
have a NAU8825, or RT5682S, or ES8326 codec, this function will create a headset
jack for MT6359, but then mt8188_headset_codec_init() will do the same again!

I think we should find a way to avoid that situation, as I'm mostly sure that this
will give issues in the long run.

Even if it wouldn't, having two headset jacks exposed, of which one doesn't work
because it doesn't exist on the physical board... would be confusing for the user.

I guess that the best option here would be:
  - Let the `for_each_card_prelinks()` loop finish
  - Check if any of the external codecs are providing 3.5mm jack
    - External codec providing jack means that the detection should be performed
      by the external codec, as the jack should not be physically routed to the
      MediaTek ACCDET related PMIC pins (right?)
    - No external codec means that the accessory detection can only be performed
      by the MediaTek ACCDET IP
  - If external codec manages 3.5mm jack: do nothing
  - If no external codec managing 3.5mm jack: check if accdet provided in DT and
    initialize it

....unless I'm wrong - and if I am, please explain why (and also add explanation
to the commit description).

Cheers,
Angelo

> +
> +	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
> +				   SND_JACK_HEADSET | SND_JACK_BTN_0 |
> +				   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
> +				   SND_JACK_BTN_3,
> +				   jack, mt8188_headset_jack_pins,
> +				   ARRAY_SIZE(mt8188_headset_jack_pins));
> +	if (ret) {
> +		dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack);
> +	if (ret) {
> +		dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>   static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
>   {
>   	struct snd_soc_component *cmpnt_codec =
> @@ -512,6 +553,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
>   	/* mtkaif calibration */
>   	mt8188_mt6359_mtkaif_calibration(rtd);
>   
> +	mt8188_mt6359_accdet_init(rtd);
> +
>   	return 0;
>   }
>   
> 


From angelogioacchino.delregno at collabora.com  Tue Mar  4 07:41:28 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 16:41:28 +0100
Subject: [PATCH v3 02/20] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250304-mt6359-accdet-dts-v3-2-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
 <20250304-mt6359-accdet-dts-v3-2-5b0eafc29f5b@collabora.com>
Message-ID: <f9fad64b-963f-4059-9b80-7d1c877525a8@collabora.com>

Il 04/03/25 16:15, N?colas F. R. A. Prado ha scritto:
> Describe the accdet as a possible subnode of the MT6359 PMIC.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From vladimir.oltean at nxp.com  Tue Mar  4 07:26:44 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 4 Mar 2025 17:26:44 +0200
Subject: [PATCH iwl-next v7 5/9] igc: Add support for frame preemption
 verification
In-Reply-To: <20250303102658.3580232-6-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
 <20250303102658.3580232-6-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250304152644.y7j7eshr4qxhmxq2@skbuf>

On Mon, Mar 03, 2025 at 05:26:54AM -0500, Faizal Rahim wrote:
> +static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
> +						 unsigned int size)
> +{
> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
> +	int smd;
> +
> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
> +
> +	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
> +		size == SMD_FRAME_SIZE;
> +}

The NIC should explicitly not respond to frames which have an SMD-V but
are not "verify" mPackets (7 octets of 0x55 + 1 octet SMD-V + 60 octets
of 0x00 + mCRC - as per 802.3 definitions). Similarly, it should only
treat SMD-R frames which contain 7 octets of 0x55 + 1 octet SMD-R + 60
octets of 0x00 + mCRC as "respond" mPackets, and only advance its
verification state machine based on those.

Specifically, it doesn't look like you are ensuring the packet payload
contains 60 octets of zeroes. Is this something that the hardware
already does for you, or is it something that needs further validation
and differentiation in software?


From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:08:38 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:38:38 +0530
Subject: [PATCH v2 6/8] PCI: brcmstb: Use same constant table for config
 space access
In-Reply-To: <20250214173944.47506-7-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-7-james.quinlan@broadcom.com>
Message-ID: <20250304150838.23ca5qbhm4yrpa3h@thinkpad>

On Fri, Feb 14, 2025 at 12:39:34PM -0500, Jim Quinlan wrote:
> The constants EXT_CFG_DATA and EXT_CFG_INDEX vary by SOC. One of the
> map_bus methods used these constants, the other used different constants.
> Fortunately there was no problem because the SoCs that used the latter
> map_bus method all had the same register constants.
> 
> Remove the redundant constants and adjust the code to use them.  In
> addition, update EXT_CFG_DATA to use the 4k-page based config space access
> system, which is what the second map_bus method was already using.
> 

What is the effect of this change? Why is it required? Sounds like it got
sneaked in.

> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> ---
>  drivers/pci/controller/pcie-brcmstb.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index e1059e3365bd..923ac1a03f85 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -150,9 +150,6 @@
>  #define  MSI_INT_MASK_SET		0x10
>  #define  MSI_INT_MASK_CLR		0x14
>  
> -#define PCIE_EXT_CFG_DATA				0x8000
> -#define PCIE_EXT_CFG_INDEX				0x9000
> -
>  #define  PCIE_RGR1_SW_INIT_1_PERST_MASK			0x1
>  #define  PCIE_RGR1_SW_INIT_1_PERST_SHIFT		0x0
>  
> @@ -727,8 +724,8 @@ static void __iomem *brcm_pcie_map_bus(struct pci_bus *bus,
>  
>  	/* For devices, write to the config space index register */
>  	idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0);
> -	writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
> -	return base + PCIE_EXT_CFG_DATA + PCIE_ECAM_REG(where);
> +	writel(idx, base + IDX_ADDR(pcie));
> +	return base + DATA_ADDR(pcie) + PCIE_ECAM_REG(where);
>  }
>  
>  static void __iomem *brcm7425_pcie_map_bus(struct pci_bus *bus,
> @@ -1711,7 +1708,7 @@ static void brcm_pcie_remove(struct platform_device *pdev)
>  static const int pcie_offsets[] = {
>  	[RGR1_SW_INIT_1]	= 0x9210,
>  	[EXT_CFG_INDEX]		= 0x9000,
> -	[EXT_CFG_DATA]		= 0x9004,
> +	[EXT_CFG_DATA]		= 0x8000,
>  	[PCIE_HARD_DEBUG]	= 0x4204,
>  	[PCIE_INTR2_CPU_BASE]	= 0x4300,
>  };
> @@ -1719,7 +1716,7 @@ static const int pcie_offsets[] = {
>  static const int pcie_offsets_bcm7278[] = {
>  	[RGR1_SW_INIT_1]	= 0xc010,
>  	[EXT_CFG_INDEX]		= 0x9000,
> -	[EXT_CFG_DATA]		= 0x9004,
> +	[EXT_CFG_DATA]		= 0x8000,
>  	[PCIE_HARD_DEBUG]	= 0x4204,
>  	[PCIE_INTR2_CPU_BASE]	= 0x4300,
>  };
> @@ -1733,8 +1730,9 @@ static const int pcie_offsets_bcm7425[] = {
>  };
>  
>  static const int pcie_offsets_bcm7712[] = {
> +	[RGR1_SW_INIT_1]	= 0x9210,
>  	[EXT_CFG_INDEX]		= 0x9000,
> -	[EXT_CFG_DATA]		= 0x9004,
> +	[EXT_CFG_DATA]		= 0x8000,
>  	[PCIE_HARD_DEBUG]	= 0x4304,
>  	[PCIE_INTR2_CPU_BASE]	= 0x4400,
>  };
> -- 
> 2.43.0
> 

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:09:24 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:39:24 +0530
Subject: [PATCH v2 7/8] PCI: brcmstb: Make two changes in MDIO register
 fields
In-Reply-To: <20250214173944.47506-8-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-8-james.quinlan@broadcom.com>
Message-ID: <20250304150924.a6ygwzca3lwgpt7h@thinkpad>

On Fri, Feb 14, 2025 at 12:39:35PM -0500, Jim Quinlan wrote:
> The HW team has decided to "tighten" some field definitions in the MDIO
> packet format.  Fortunately these two changes may be made in a backwards
> compatible manner.
> 
> The CMD field used to be 12 bits and now is one.  This change is backwards
> compatible because the field's starting bit position is unchanged and the
> only commands we've used have values 0 and 1.
> 
> The PORT field's width has been changed from four to five bits.  When
> written, the new bit is not contiguous with the other four.  Fortunately,
> this change is backwards compatible because we have never used anything
> other than 0 for the port field's value.
> 
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 923ac1a03f85..cb897d4b2579 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -175,8 +175,9 @@
>  #define MDIO_PORT0			0x0
>  #define MDIO_DATA_MASK			0x7fffffff
>  #define MDIO_PORT_MASK			0xf0000
> +#define MDIO_PORT_EXT_MASK		0x200000
>  #define MDIO_REGAD_MASK			0xffff
> -#define MDIO_CMD_MASK			0xfff00000
> +#define MDIO_CMD_MASK			0x00100000
>  #define MDIO_CMD_READ			0x1
>  #define MDIO_CMD_WRITE			0x0
>  #define MDIO_DATA_DONE_MASK		0x80000000
> @@ -327,6 +328,7 @@ static u32 brcm_pcie_mdio_form_pkt(int port, int regad, int cmd)
>  {
>  	u32 pkt = 0;
>  
> +	pkt |= FIELD_PREP(MDIO_PORT_EXT_MASK, port >> 4);
>  	pkt |= FIELD_PREP(MDIO_PORT_MASK, port);
>  	pkt |= FIELD_PREP(MDIO_REGAD_MASK, regad);
>  	pkt |= FIELD_PREP(MDIO_CMD_MASK, cmd);
> -- 
> 2.43.0
> 

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:10:40 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:40:40 +0530
Subject: [PATCH v2 8/8] PCI: brcmstb: Clarify conversion of
 irq_domain_set_info() param
In-Reply-To: <20250214173944.47506-9-james.quinlan@broadcom.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-9-james.quinlan@broadcom.com>
Message-ID: <20250304151022.qgp253hv5sxvxzdc@thinkpad>

On Fri, Feb 14, 2025 at 12:39:36PM -0500, Jim Quinlan wrote:
> Just make it clear to the reader that there is a conversion happening, in
> this case from an int type to an irq_hw_number_t, an unsigned long int.
> 
> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  drivers/pci/controller/pcie-brcmstb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index cb897d4b2579..f790d5252e9f 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -559,7 +559,7 @@ static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>  		return hwirq;
>  
>  	for (i = 0; i < nr_irqs; i++)
> -		irq_domain_set_info(domain, virq + i, hwirq + i,
> +		irq_domain_set_info(domain, virq + i, (irq_hw_number_t)hwirq + i,
>  				    &brcm_msi_bottom_irq_chip, domain->host_data,
>  				    handle_edge_irq, NULL, NULL);
>  	return 0;
> -- 
> 2.43.0
> 

-- 
????????? ????????


From ping.bai at nxp.com  Tue Mar  4 07:16:00 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue, 4 Mar 2025 15:16:00 +0000
Subject: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <9581e376-19b2-4d4e-ad81-cc24e39e9d33@kernel.org>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-4-ping.bai@nxp.com>
 <9581e376-19b2-4d4e-ad81-cc24e39e9d33@kernel.org>
Message-ID: <AS8PR04MB86420E1D079341F806EC685087C82@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
> 
> On 04/03/2025 10:31, Jacky Bai wrote:
> > Add the minimal dtsi support for i.MX943. i.MX943 is the first SoC of
> > i.MX94 Family, create a common dtsi for the whole i.MX94 family, and
> > the specific dtsi part for i.MX943.
> >
> > The clock, power domain and perf index need to be used by the device
> > nodes for resource reference, add them along with the dtsi support.
> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - remove the unnecessary macro define in clock header as suggested by
> Krzysztof
> >   - split the dtsi into imx94.dtsi and imx943.dtsi
> >   - use low case in the pinfunc header as Frank suggested
> >   - reorder the device nodes and properties
> >   - resolve Krzysztof's other comments
> 
> Which ones? Be specific.
> 
> Based on last issue, I don't think you implemented comments.
> 
> 
> > +
> > +			a55_irqsteer: interrupt-controller at 446a0000 {
> > +				compatible = "fsl,imx-irqsteer";
> > +				reg = <0x446a0000 0x1000>;
> > +				#interrupt-cells = <1>;
> > +				interrupt-controller;
> > +				interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "ipg";
> > +				fsl,channel = <0>;
> > +				fsl,num-irqs = <960>;
> > +			};
> > +		};
> > +
> > +		aips4: bus at 49000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x49000000 0x0 0x800000>;
> > +			ranges = <0x49000000 0x0 0x49000000 0x800000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			wdog3: watchdog at 49220000 {
> > +				compatible = "fsl,imx93-wdt";
> 
> imx93 or imx95, like in other places? And the commit msg says imx943.
> 
> I already asked for that.

Yes, I know. I asked for your suggestion in v1 mail thread.
https://lore.kernel.org/linux-arm-kernel/3c9fe85a-5f86-4df6-92fb-e4ceb033f161 at kernel.org/T/#m0a180c57e5d79e368b5eae924afbab8706f95546

BR
Jacky Bai

> 
> > +				reg = <0x49220000 0x10000>;
> > +				interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				timeout-sec = <40>;
> > +				fsl,ext-reset-output;
> > +				status = "disabled";
> > +			};
> > +		};
> Best regards,
> Krzysztof

From nfraprado at collabora.com  Tue Mar  4 07:15:41 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:41 -0300
Subject: [PATCH v3 00/20] Get mt6359-accdet ready for usage in Devicetree
Message-ID: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>

This series prepares the MT6359 ACCDET for actual usage in the
Devicetree. Patches 1 and 2 add the required DT bindings, patches 3 and
4 get the mt6359-accdet driver probing, patches 5-18 clean up code
related to DT property parsing, patch 19 adds the node in the
Devicetree and patch 20 enables the kconfig for the driver.

Together with the series "Allow retrieving accessory detection reference
on MT8188" [1], and one extra patch on top enabling it on the
genio-700-evk DT, this series was tested on the Genio 700 EVK to get
audio jack detection working on it.

[1] https://lore.kernel.org/all/20250214-mt8188-accdet-v1-0-6bbd5483855b at collabora.com

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
Changes in v3:
- Removed unneeded '|' in mt6359-accdet's dt-binding description
- Removed unneeded unevaluatedProperties for accdet node in mt6397's
  dt-binding
- Clarified HP_EINT pin is on the MT6359 PMIC in mediatek,hp-eint-high's
  description in the mt6359-accdet dt-binding
- Link to v2: https://lore.kernel.org/r/20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47 at collabora.com

Changes in v2:
- Removed all DT-binding properties except for EINT polarity one
  (mediatek,eint-level-pol / mediatek,hp-eint-high)
  - Added patches 12-18 to make those settings internal to driver
- Renamed mediatek,eint-level-pol to mediatek,hp-eint-high and made it
  bool
- Added patch 20 to enable the MT6359 ACCDET Kconfig in the defconfig
- Removed unused btn_type variable as part of "Drop dead code for button
  detection" patch.
- Link to v1: https://lore.kernel.org/r/20250214-mt6359-accdet-dts-v1-0-677a151b9b4c at collabora.com

---
Andrew Perepech (2):
      mfd: mt6397-core: Add mfd_cell for mt6359-accdet
      ASoC: mediatek: mt6359-accdet: Implement HP_EINT polarity configuration

N?colas F. R. A. Prado (18):
      ASoC: dt-bindings: Add document for mt6359-accdet
      dt-bindings: mfd: mediatek: mt6397: Add accdet subnode
      ASoC: mediatek: mt6359-accdet: Add compatible property
      ASoC: mediatek: mt6359-accdet: Handle hp-eint-high property
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT/GPIO IRQ handling
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT trigger setting
      ASoC: mediatek: mt6359-accdet: Drop dead code for button detection
      ASoC: mediatek: mt6359-accdet: Drop dead code for plugout-debounce
      ASoC: mediatek: mt6359-accdet: Drop unused moisture variables
      ASoC: mediatek: mt6359-accdet: Always use internal resistor
      ASoC: mediatek: mt6359-accdet: Make PWM debounce settings internal
      ASoC: mediatek: mt6359-accdet: Always use eint detect mode 4
      ASoC: mediatek: mt6359-accdet: Always set micbias1 to 2.8V
      ASoC: mediatek: mt6359-accdet: Always configure hardware as mic-mode 2
      ASoC: mediatek: mt6359-accdet: Always set comp-vth to 1.6V
      ASoC: mediatek: mt6359-accdet: Always use EINT0 IRQ
      arm64: dts: mt6359: Add accessory detect node
      arm64: defconfig: Enable MT6359 ACCDET

 .../devicetree/bindings/mfd/mediatek,mt6397.yaml   |   6 +
 .../bindings/sound/mediatek,mt6359-accdet.yaml     |  42 ++
 arch/arm64/boot/dts/mediatek/mt6359.dtsi           |   4 +
 arch/arm64/configs/defconfig                       |   1 +
 drivers/mfd/mt6397-core.c                          |  12 +
 sound/soc/codecs/mt6359-accdet.c                   | 599 +++++----------------
 sound/soc/codecs/mt6359-accdet.h                   |  55 +-
 7 files changed, 195 insertions(+), 524 deletions(-)
---
base-commit: 20d5c66e1810e6e8805ec0d01373afb2dba9f51a
change-id: 20250214-mt6359-accdet-dts-00b189847f3c

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Tue Mar  4 07:15:42 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:42 -0300
Subject: [PATCH v3 01/20] ASoC: dt-bindings: Add document for mt6359-accdet
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-1-5b0eafc29f5b@collabora.com>

Add dt-binding for the MT6359 ACCDET hardware block.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1d27148ed7bffee3f73015c8af88bfffa8701843
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MT6359 Accessory Detection
+
+maintainers:
+  - N?colas F. R. A. Prado <nfraprado at collabora.com>
+
+description:
+  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
+  detecting audio jack insertion and removal, as well as identifying the type of
+  events connected to the jack.
+
+properties:
+  compatible:
+    const: mediatek,mt6359-accdet
+
+  mediatek,hp-eint-high:
+    type: boolean
+    description:
+      By default, MT6359's HP_EINT pin is assumed to be pulled high and
+      connected to a normally open 3.5mm jack. Plug insertion is detected when
+      the pin is brought low in that case. Add this property if the behavior
+      should be inverted, for example if a normally closed 3.5mm jack is used,
+      or if the line is pulled low on open.
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    accdet: accdet {
+        compatible = "mediatek,mt6359-accdet";
+        mediatek,hp-eint-high;
+    };

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:43 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:43 -0300
Subject: [PATCH v3 02/20] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-2-5b0eafc29f5b@collabora.com>

Describe the accdet as a possible subnode of the MT6359 PMIC.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..b2a50f754d00fd8e9577b9d8269868bdfc2e425f 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -224,6 +224,12 @@ properties:
     description:
       Pin controller
 
+  accdet:
+    type: object
+    $ref: /schemas/sound/mediatek,mt6359-accdet.yaml
+    description:
+      Accessory Detection
+
 required:
   - compatible
   - regulators

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:44 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:44 -0300
Subject: [PATCH v3 03/20] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-3-5b0eafc29f5b@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
allow the mt6359-accdet driver to probe.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 drivers/mfd/mt6397-core.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 0e5d59ae064a696ae2111e2b558b316667c14773..5f8ed898890783c0ce4e34c7eae0d8f678e7d7bc 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -84,6 +84,12 @@ static const struct resource mt6359_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
 };
 
+static const struct resource mt6359_accdet_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET, "accdet_irq"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT0, "accdet_eint0"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT1, "accdet_eint1"),
+};
+
 static const struct resource mt6323_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
@@ -239,6 +245,12 @@ static const struct mfd_cell mt6359_devs[] = {
 		.resources = mt6359_keys_resources,
 		.of_compatible = "mediatek,mt6359-keys"
 	},
+	{
+		.name = "mt6359-accdet",
+		.of_compatible = "mediatek,mt6359-accdet",
+		.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
+		.resources = mt6359_accdet_resources,
+	},
 };
 
 static const struct mfd_cell mt6397_devs[] = {

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:45 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:45 -0300
Subject: [PATCH v3 04/20] ASoC: mediatek: mt6359-accdet: Add compatible
 property
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-4-5b0eafc29f5b@collabora.com>

Add a compatible property and add it to the module device table for the
mt6359-accdet platform driver to allow automatic module loading and
probing when the compatible is present in DT.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ed34cc15b80e856356c07fd53af22207124e0d19..9bbd4497e8d481ee125693be2fc576b439574b39 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -1047,9 +1047,16 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	return ret;
 }
 
+const struct of_device_id accdet_of_match[] = {
+	{ .compatible = "mediatek,mt6359-accdet", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, accdet_of_match);
+
 static struct platform_driver mt6359_accdet_driver = {
 	.driver = {
 		.name = "pmic-codec-accdet",
+		.of_match_table = accdet_of_match,
 	},
 	.probe = mt6359_accdet_probe,
 };

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:46 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:46 -0300
Subject: [PATCH v3 05/20] ASoC: mediatek: mt6359-accdet: Handle
 hp-eint-high property
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-5-5b0eafc29f5b@collabora.com>

Now that the dt-binding was introduced, the property that governs the
eint polarity is a boolean called mediatek,hp-eint-high, while the
current code handles a u32 property called mediatek,eint-level-pol.
Update the driver handling accordingly.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 +----
 sound/soc/codecs/mt6359-accdet.h | 2 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 9bbd4497e8d481ee125693be2fc576b439574b39..ca3be59d2d0ecaadccd9ba399649ba93f20490c4 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -578,10 +578,7 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!ret)
 		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
 
-	ret = of_property_read_u32(node, "mediatek,eint-level-pol",
-				   &priv->data->eint_pol);
-	if (ret)
-		priv->data->eint_pol = 8;
+	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index c234f2f4276a12853a6fe0b13c4198dfc551b6b4..a54a328bdf3797ce642da446c0cc6792f72ec939 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -86,7 +86,7 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	unsigned int plugout_deb;
-	unsigned int eint_pol;
+	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	struct three_key_threshold three_key;
 	struct four_key_threshold four_key;

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:47 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:47 -0300
Subject: [PATCH v3 06/20] ASoC: mediatek: mt6359-accdet: Implement HP_EINT
 polarity configuration
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-6-5b0eafc29f5b@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

The driver currently reads the HP_EINT polarity from the Devicetree but
never actually configures the hardware accordingly.

Implement the polarity configuration in hardware.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ca3be59d2d0ecaadccd9ba399649ba93f20490c4..1d4481109f6e4f473610e0797c9d3c636bdf12cf 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -730,6 +730,17 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 		}
 	}
+
+	if (priv->data->hp_eint_high) {
+		/* EINT polarity inverse */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT,
+				   BIT(ACCDET_EINT_IN_INVERSE_SFT));
+	} else {
+		/* EINT polarity normal */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT, 0);
+	}
 }
 
 static void config_eint_init_by_mode(struct mt6359_accdet *priv)

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:49 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:49 -0300
Subject: [PATCH v3 08/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT trigger setting
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-8-5b0eafc29f5b@collabora.com>

None of the EINT trigger options are implemented and the DT property is
not described in the binding. Remove the unused code.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0..a21c6544174517e3eebc8cf25d1ea3029ba014f6 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -35,8 +35,6 @@
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
 
-#define ACCDET_PMIC_GPIO_TRIG_EINT	BIT(5)
-#define ACCDET_PMIC_INVERTER_TRIG_EINT	BIT(6)
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_THREE_KEY		BIT(8)
@@ -593,15 +591,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-trig-mode",
-				   &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
 				   &priv->data->eint_use_ext_res);
 	if (ret) {

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:48 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:48 -0300
Subject: [PATCH v3 07/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT/GPIO IRQ handling
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-7-5b0eafc29f5b@collabora.com>

The ACCDET supports two modes for IRQ generation: PMIC EINT or AP GPIO,
which in principle could be configured through a DT property. However
this DT property has no user nor is documented in a binding, and the
driver only implements the PMIC EINT case, so drop the unused code
intended to handle both cases.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 1d4481109f6e4f473610e0797c9d3c636bdf12cf..ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,9 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT_IRQ		BIT(0)
-#define ACCDET_AP_GPIO_EINT		BIT(1)
-
 #define ACCDET_PMIC_EINT0		BIT(2)
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
@@ -448,8 +445,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		mt6359_accdet_recover_jd_setting(priv);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ)
-		recover_eint_setting(priv);
+	recover_eint_setting(priv);
 	mutex_unlock(&priv->res_lock);
 }
 
@@ -580,14 +576,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT_IRQ;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_AP_GPIO_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
 				   &priv->data->eint_detect_mode);
 	if (ret) {
@@ -902,10 +890,8 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 				   0x3 << RG_ANALOGFDEN_SFT);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ) {
-		config_eint_init_by_mode(priv);
-		config_digital_init_by_mode(priv);
-	}
+	config_eint_init_by_mode(priv);
+	config_digital_init_by_mode(priv);
 }
 
 int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:50 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:50 -0300
Subject: [PATCH v3 09/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 button detection
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-9-5b0eafc29f5b@collabora.com>

The button detection functionality depends on a calibration voltage
value which is currently not updated anywhere in the driver code, and
hence it doesn't actually do anything. Remove this unused code.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 92 ++--------------------------------------
 sound/soc/codecs/mt6359-accdet.h | 17 --------
 2 files changed, 3 insertions(+), 106 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a21c6544174517e3eebc8cf25d1ea3029ba014f6..6b0178976d91e37c32540991693ebfd8e29c11f5 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -37,9 +37,6 @@
 
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
-#define ACCDET_THREE_KEY		BIT(8)
-#define ACCDET_FOUR_KEY			BIT(9)
-#define ACCDET_TRI_KEY_CDD		BIT(10)
 #define ACCDET_RSV_KEY			BIT(11)
 
 #define ACCDET_ANALOG_FASTDISCHARGE	BIT(12)
@@ -255,7 +252,6 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 			    priv->data->pwm_deb->debounce3);
 
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_jack_report(priv);
 }
@@ -318,45 +314,10 @@ static void mt6359_accdet_jack_report(struct mt6359_accdet *priv)
 	if (!priv->jack)
 		return;
 
-	report = priv->jack_type | priv->btn_type;
+	report = priv->jack_type;
 	snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK);
 }
 
-static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v)
-{
-	if (priv->caps & ACCDET_FOUR_KEY) {
-		if (v < priv->data->four_key.down &&
-		    v >= priv->data->four_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->four_key.up &&
-		    v >= priv->data->four_key.voice)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->four_key.voice &&
-		    v >= priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_3;
-		if (v < priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	} else {
-		if (v < priv->data->three_key.down &&
-		    v >= priv->data->three_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->three_key.up &&
-		    v >= priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	}
-	return 0;
-}
-
-static void is_key_pressed(struct mt6359_accdet *priv, bool pressed)
-{
-	priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK;
-
-	if (pressed)
-		check_button(priv, priv->cali_voltage);
-}
-
 static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
@@ -368,15 +329,11 @@ static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 
 	switch (priv->accdet_status) {
 	case 0:
-		if (priv->jack_type == SND_JACK_HEADSET)
-			is_key_pressed(priv, true);
-		else
+		if (priv->jack_type != SND_JACK_HEADSET)
 			priv->jack_type = SND_JACK_HEADPHONE;
 		break;
 	case 1:
-		if (priv->jack_type == SND_JACK_HEADSET) {
-			is_key_pressed(priv, false);
-		} else {
+		if (priv->jack_type != SND_JACK_HEADSET) {
 			priv->jack_type = SND_JACK_HEADSET;
 			accdet_set_debounce(priv, eint_state011, 0x1);
 		}
@@ -603,48 +560,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->eint_comp_vth = 0x0;
 
-	ret = of_property_read_u32(node, "mediatek,key-mode", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_THREE_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,three-key-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	} else if (tmp == 1) {
-		int four_key[5];
-
-		priv->caps |= ACCDET_FOUR_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,four-key-thr",
-						 four_key,
-						 ARRAY_SIZE(four_key));
-		if (!ret) {
-			memcpy(&priv->data->four_key, four_key + 1,
-			       sizeof(struct four_key_threshold));
-		} else {
-			dev_warn(priv->dev,
-				 "accdet no 4-key-thrsh dts, use efuse\n");
-		}
-	} else if (tmp == 2) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_TRI_KEY_CDD;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,tri-key-cdd-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	}
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -1015,7 +930,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 
 	priv->jd_sts = M_PLUG_OUT;
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_init(priv);
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index a54a328bdf3797ce642da446c0cc6792f72ec939..09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,19 +50,6 @@ enum {
 	eint_inverter_state000,
 };
 
-struct three_key_threshold {
-	unsigned int mid;
-	unsigned int up;
-	unsigned int down;
-};
-
-struct four_key_threshold {
-	unsigned int mid;
-	unsigned int voice;
-	unsigned int up;
-	unsigned int down;
-};
-
 struct pwm_deb_settings {
 	unsigned int pwm_width;
 	unsigned int pwm_thresh;
@@ -88,8 +75,6 @@ struct dts_data {
 	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	struct three_key_threshold three_key;
-	struct four_key_threshold four_key;
 	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
@@ -112,10 +97,8 @@ struct mt6359_accdet {
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;
-	unsigned int btn_type;
 	unsigned int accdet_status;
 	unsigned int pre_accdet_status;
-	unsigned int cali_voltage;
 	unsigned int jd_sts;
 	struct work_struct accdet_work;
 	struct workqueue_struct *accdet_workqueue;

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:51 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:51 -0300
Subject: [PATCH v3 10/20] ASoC: mediatek: mt6359-accdet: Drop dead code for
 plugout-debounce
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-10-5b0eafc29f5b@collabora.com>

The mediatek,plugout-debounce property is undocumented in the binding
and unhandled by the driver. Remove it.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 -----
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 6 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6b0178976d91e37c32540991693ebfd8e29c11f5..d78d7516342a5c2273b1c2962c0346646aa6390f 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -513,11 +513,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_vol = 8;
 
-	ret = of_property_read_u32(node, "mediatek,plugout-debounce",
-				   &priv->data->plugout_deb);
-	if (ret)
-		priv->data->plugout_deb = 1;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a..54a33a0f0e084f80df33386b3df9bba9525fa880 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -72,7 +72,6 @@ struct pwm_deb_settings {
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
-	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int moisture_detect_enable;

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:52 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:52 -0300
Subject: [PATCH v3 11/20] ASoC: mediatek: mt6359-accdet: Drop unused
 moisture variables
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-11-5b0eafc29f5b@collabora.com>

The dts_data struct contains several variables for moisture
configuration that are simply never used. Drop them.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 54a33a0f0e084f80df33386b3df9bba9525fa880..38c36d59b9cc68bd90e16137a05a62b521b75ac1 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -74,14 +74,9 @@ struct dts_data {
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
-	unsigned int moisture_detect_mode;
-	unsigned int moisture_comp_vth;
-	unsigned int moisture_comp_vref2;
-	unsigned int moisture_use_ext_res;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:53 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:53 -0300
Subject: [PATCH v3 12/20] ASoC: mediatek: mt6359-accdet: Always use
 internal resistor
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-12-5b0eafc29f5b@collabora.com>

The code currently reads a property mediatek,eint-use-ext-res with
values ranging between 0 and 4. Not only should this be a boolean
property, but there's no need for it to even be a DT property, seeing as
all current boards will use the internal resistor anyway. Since there's
no current dt-binding or Devicetree user of this property, remove its
handling and make the driver always configure the internal resistor.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 53 +++++++++++-----------------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 14 insertions(+), 40 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index d78d7516342a5c2273b1c2962c0346646aa6390f..e04cfb9a607aa5d38d46329eb1387545fda37ccc 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -82,14 +82,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 					   RG_EINT1CONFIGACCDET_MASK_SFT,
 					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
-		if (priv->data->eint_use_ext_res == 0x3 ||
-		    priv->data->eint_use_ext_res == 0x4) {
-			/*select 500k, use internal resistor */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0HIRENB_ADDR,
-					   RG_EINT0HIRENB_MASK_SFT,
-					   BIT(RG_EINT0HIRENB_SFT));
-		}
+		/*select 500k, use internal resistor */
+		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+				   RG_EINT0HIRENB_MASK_SFT,
+				   BIT(RG_EINT0HIRENB_SFT));
 	}
 	return 0;
 }
@@ -543,13 +539,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
-				   &priv->data->eint_use_ext_res);
-	if (ret) {
-		/* eint use internal resister */
-		priv->data->eint_use_ext_res = 0x0;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
 				   &priv->data->eint_comp_vth);
 	if (ret)
@@ -651,30 +640,16 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	if (priv->data->eint_detect_mode == 0x1 ||
 	    priv->data->eint_detect_mode == 0x2 ||
 	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->data->eint_use_ext_res == 0x1) {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   0);
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   0);
-			}
-		} else {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT0CONFIGACCDET_SFT));
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT1CONFIGACCDET_SFT));
-			}
+		if (priv->caps & ACCDET_PMIC_EINT0) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT0CONFIGACCDET_ADDR,
+					   RG_EINT0CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT0CONFIGACCDET_SFT));
+		} else if (priv->caps & ACCDET_PMIC_EINT1) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT1CONFIGACCDET_ADDR,
+					   RG_EINT1CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 38c36d59b9cc68bd90e16137a05a62b521b75ac1..99de5037a2294b62cb8535fc45dbf4c6fafb5c7f 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -75,7 +75,6 @@ struct dts_data {
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
-	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:54 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:54 -0300
Subject: [PATCH v3 13/20] ASoC: mediatek: mt6359-accdet: Make PWM debounce
 settings internal
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-13-5b0eafc29f5b@collabora.com>

Instead of reading a bunch of PWM debounce settings from the Devicetree,
set reasonable values inside the driver that are known to work across
multiple boards. There are no current users of these DT properties, so
no backward compatibility needs to be maintained. The properties can be
properly introduced in the binding in the future if different boards
really need to override them.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 70 ++++++++++++++++++++++------------------
 sound/soc/codecs/mt6359-accdet.h | 20 ------------
 2 files changed, 38 insertions(+), 52 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index e04cfb9a607aa5d38d46329eb1387545fda37ccc..6728f1018c992fc9d4e4133dbaf091d256567683 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -43,6 +43,25 @@
 #define ACCDET_DIGITAL_FASTDISCHARGE	BIT(13)
 #define ACCDET_AD_FASTDISCHRAGE		BIT(14)
 
+/* Debounce time = (DEBOUNCE/32768) sec */
+#define ACCDET_DEBOUNCE0_625MS 0x800
+#define ACCDET_DEBOUNCE1_625MS 0x800
+#define ACCDET_DEBOUNCE3_976US 0x20
+#define ACCDET_DEBOUNCE_AUXADC_2MS 0x44
+/* PWM frequency = 32768/(PWM_WIDTH + 1) Hz */
+#define ACCDET_PWM_WIDTH_25_580HZ 0x500
+/* Duty cycle = (PWM_THRESH + 1) / (PWM_WIDTH + 1) */
+#define ACCDET_PWM_THRESH_100PERCENT ACCDET_PWM_WIDTH_25_580HZ
+#define ACCDET_RISE_DELAY 0x1f0
+#define ACCDET_FALL_DELAY 1
+#define ACCDET_EINT_DEBOUNCE0_1MS 5
+#define ACCDET_EINT_DEBOUNCE1_900US 3
+#define ACCDET_EINT_DEBOUNCE2_900US 3
+#define ACCDET_EINT_DEBOUNCE3_1MS 5
+#define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
+#define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
+#define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
 
@@ -130,7 +149,7 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 	} else if (priv->jd_sts == M_PLUG_OUT) {
 		/* set debounce to 1ms */
 		accdet_set_debounce(priv, eint_state000,
-				    priv->data->pwm_deb->eint_debounce0);
+				    ACCDET_EINT_DEBOUNCE0_1MS);
 	} else {
 		dev_dbg(priv->dev, "should not be here %s()\n", __func__);
 	}
@@ -241,11 +260,11 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 
 	/* recover accdet debounce0,3 */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 
 	priv->jack_type = 0;
 	priv->accdet_status = 0x3;
@@ -390,7 +409,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		priv->jack_plugged = false;
 
 		accdet_set_debounce(priv, accdet_state011,
-				    priv->data->pwm_deb->debounce3);
+				    ACCDET_DEBOUNCE3_976US);
 		regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,
 				   ACCDET_SW_EN_MASK_SFT, 0);
 		mt6359_accdet_recover_jd_setting(priv);
@@ -497,7 +516,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	int pwm_deb[15] = {0};
 	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
@@ -514,12 +532,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_mode = 2;
 
-	ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting",
-					 pwm_deb, ARRAY_SIZE(pwm_deb));
-	/* debounce8(auxadc debounce) is default, needn't get from dts */
-	if (!ret)
-		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
@@ -554,8 +566,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 {
 	/* enable eint cmpmem pwm */
 	regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR,
-		     (priv->data->pwm_deb->eint_pwm_width << 4 |
-		     priv->data->pwm_deb->eint_pwm_thresh));
+		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
+		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
 	if (priv->caps & ACCDET_PMIC_EINT0) {
 		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
@@ -675,22 +687,22 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 	mdelay(1);
 	/* init the debounce time (debounce/32768)sec */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 	accdet_set_debounce(priv, accdet_auxadc,
-			    priv->data->pwm_deb->debounce4);
+			    ACCDET_DEBOUNCE_AUXADC_2MS);
 
 	accdet_set_debounce(priv, eint_state000,
-			    priv->data->pwm_deb->eint_debounce0);
+			    ACCDET_EINT_DEBOUNCE0_1MS);
 	accdet_set_debounce(priv, eint_state001,
-			    priv->data->pwm_deb->eint_debounce1);
+			    ACCDET_EINT_DEBOUNCE1_900US);
 	accdet_set_debounce(priv, eint_state011,
-			    priv->data->pwm_deb->eint_debounce3);
+			    ACCDET_EINT_DEBOUNCE3_1MS);
 	accdet_set_debounce(priv, eint_inverter_state000,
-			    priv->data->pwm_deb->eint_inverter_debounce);
+			    ACCDET_EINT_INVERTER_DEBOUNCE_256MS);
 
 	regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,
 			   RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT));
@@ -705,12 +717,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 
 	/* init pwm frequency, duty & rise/falling delay */
 	regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_width));
+		     REGISTER_VAL(ACCDET_PWM_WIDTH_25_580HZ));
 	regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_thresh));
+		     REGISTER_VAL(ACCDET_PWM_THRESH_100PERCENT));
 	regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR,
-		     (priv->data->pwm_deb->fall_delay << 15 |
-		      priv->data->pwm_deb->rise_delay));
+		     (ACCDET_FALL_DELAY << 15 |
+		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
 	if (priv->data->mic_vol <= 7) {
@@ -806,12 +818,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	if (!priv->data)
 		return -ENOMEM;
 
-	priv->data->pwm_deb = devm_kzalloc(&pdev->dev,
-					   sizeof(struct pwm_deb_settings),
-					   GFP_KERNEL);
-	if (!priv->data->pwm_deb)
-		return -ENOMEM;
-
 	priv->regmap = mt6397->regmap;
 	if (IS_ERR(priv->regmap)) {
 		ret = PTR_ERR(priv->regmap);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 99de5037a2294b62cb8535fc45dbf4c6fafb5c7f..287201eebe0330fa170093fd6192bf5694c30469 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,30 +50,10 @@ enum {
 	eint_inverter_state000,
 };
 
-struct pwm_deb_settings {
-	unsigned int pwm_width;
-	unsigned int pwm_thresh;
-	unsigned int fall_delay;
-	unsigned int rise_delay;
-	unsigned int debounce0;
-	unsigned int debounce1;
-	unsigned int debounce3;
-	unsigned int debounce4;
-	unsigned int eint_pwm_width;
-	unsigned int eint_pwm_thresh;
-	unsigned int eint_debounce0;
-	unsigned int eint_debounce1;
-	unsigned int eint_debounce2;
-	unsigned int eint_debounce3;
-	unsigned int eint_inverter_debounce;
-
-};
-
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:55 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:55 -0300
Subject: [PATCH v3 14/20] ASoC: mediatek: mt6359-accdet: Always use eint
 detect mode 4
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-14-5b0eafc29f5b@collabora.com>

The driver currently reads a mediatek,eint-detect-mode property from DT,
which determines certain register configurations. Since there are no
users of the property, it doesn't directly describe the hardware, and
the default value (4) is known to work across multiple boards, remove
the handling for this property and always assume mode 4 is used. The
property can be properly introduced in the binding in the future if
different boards actually need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 208 +++++++++++++--------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 70 insertions(+), 139 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6728f1018c992fc9d4e4133dbaf091d256567683..83e65b6d5845dea00a8a77d68df4b7df1f62a87c 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -81,31 +81,22 @@ static void recover_eint_setting(struct mt6359_accdet *priv);
 
 static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches off */
-		regmap_update_bits(priv->regmap,
-				   RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-		/*select 500k, use internal resistor */
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT,
-				   BIT(RG_EINT0HIRENB_SFT));
+	/* ESD switches off */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT0CONFIGACCDET_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT1CONFIGACCDET_SFT));
 	}
+	/*select 500k, use internal resistor */
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
 	return 0;
 }
 
@@ -123,18 +114,14 @@ static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
 	}
 
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
 	}
 	return 0;
 }
@@ -159,27 +146,19 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 
 static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches on */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   1 << 8, 1 << 8);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* disable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* disable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-		}
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT, 0);
+	/* ESD switches on */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* disable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* disable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
 	}
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
@@ -193,37 +172,30 @@ static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_M_SW_EN_ADDR,
 				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
 	}
-	if (priv->data->eint_detect_mode == 0x4) {
+	if (priv->caps & ACCDET_PMIC_EINT0) {
 		/* enable eint0cen */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable eint0cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable eint1cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-		}
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable eint1cen */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
 	}
 
-	if (priv->data->eint_detect_mode != 0x1) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 }
 
@@ -534,13 +506,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
-				   &priv->data->eint_detect_mode);
-	if (ret) {
-		/* eint detection mode equals to EINT HW Mode */
-		priv->data->eint_detect_mode = 0x4;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
 	if (ret)
 		tmp = 0;
@@ -592,31 +557,16 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->data->eint_detect_mode == 0x1) {
-		/* disable inverter detection */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		}
-	} else {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 
 	if (priv->data->hp_eint_high) {
@@ -649,28 +599,10 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR,
 			   RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT));
 
-	if (priv->data->eint_detect_mode == 0x1 ||
-	    priv->data->eint_detect_mode == 0x2 ||
-	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-	}
-
-	if (priv->data->eint_detect_mode != 0x1) {
-		/* current detect set 0.25uA */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << RG_ACCDETSPARE_SFT,
-				   0x3 << RG_ACCDETSPARE_SFT);
-	}
+	/* current detect set 0.25uA */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
+			   0x3 << RG_ACCDETSPARE_SFT,
+			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
 		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
 }
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 287201eebe0330fa170093fd6192bf5694c30469..ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -54,7 +54,6 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:56 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:56 -0300
Subject: [PATCH v3 15/20] ASoC: mediatek: mt6359-accdet: Always set
 micbias1 to 2.8V
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-15-5b0eafc29f5b@collabora.com>

The driver currently reads a mediatek,mic-vol property from DT to
determine the micbias1 setting to configure in hardware. Since there are
no current users of the property and the default value (2.8V) is known
to work on multiple boards, remove the code handling this property and
instead always configure the micbias1 to 2.8V. The property can be
properly introduced in the binding in the future if it really turns out
that different boards need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 23 +++--------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 83e65b6d5845dea00a8a77d68df4b7df1f62a87c..a31e084560c7643b14fb71871699e3167075d9d9 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-vol",
-				   &priv->data->mic_vol);
-	if (ret)
-		priv->data->mic_vol = 8;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
@@ -657,22 +652,10 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
-	if (priv->data->mic_vol <= 7) {
-		/* micbias1 <= 2.7V */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 8) {
-		/* micbias1 = 2.8v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
+	/* micbias1 = 2.8v */
+	regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
+		     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 9) {
-		/* micbias1 = 2.85v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (1 << RG_AUDMICBIAS1HVEN_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	}
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
 	if (priv->data->mic_mode == HEADSET_MODE_1) {
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92..46dcd4759230a5190434b9b7c785e8b9ed12fd3d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -51,7 +51,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:57 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:57 -0300
Subject: [PATCH v3 16/20] ASoC: mediatek: mt6359-accdet: Always configure
 hardware as mic-mode 2
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-16-5b0eafc29f5b@collabora.com>

The driver currently reads a mediatek,mic-mode property from DT to
determine certain register configurations. Since there are no current
users of the property, the property doesn't directly reflect the
hardware  and the default value (2) is known to work on
multiple boards, remove the code handling this property and instead
always configure the hardware according to the known to work default.
This property can be properly introduced in the binding in the future
if it really turns out that different boards need different
configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 43 ++++++----------------------------------
 sound/soc/codecs/mt6359-accdet.h |  5 -----
 2 files changed, 6 insertions(+), 42 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a31e084560c7643b14fb71871699e3167075d9d9..12697b02faff1be39317116cd7d8ffa359f2cd4e 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-mode",
-				   &priv->data->mic_mode);
-	if (ret)
-		priv->data->mic_mode = 2;
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
@@ -658,38 +653,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
-	if (priv->data->mic_mode == HEADSET_MODE_1) {
-		/* ACC mode*/
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE1);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   RG_ANALOGFDEN_MASK_SFT,
-				   BIT(RG_ANALOGFDEN_SFT));
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << 11, 0x3 << 11);
-	} else if (priv->data->mic_mode == HEADSET_MODE_2) {
-		/* DCC mode Low cost mode without internal bias */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE2);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	} else if (priv->data->mic_mode == HEADSET_MODE_6) {
-		/* DCC mode Low cost mode with internal bias,
-		 * bit8 = 1 to use internal bias
-		 */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE6);
-		regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-				   RG_AUDMICBIAS1DCSW1PEN_MASK_SFT,
-				   BIT(RG_AUDMICBIAS1DCSW1PEN_SFT));
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	}
+	/* DCC mode Low cost mode without internal bias */
+	regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
+		     reg | RG_ACCDET_MODE_ANA11_MODE2);
+	/* enable analog fast discharge */
+	regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
+			   0x3 << RG_ANALOGFDEN_SFT, 0x3 << RG_ANALOGFDEN_SFT);
 
 	config_eint_init_by_mode(priv);
 	config_digital_init_by_mode(priv);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 46dcd4759230a5190434b9b7c785e8b9ed12fd3d..579373807c414130b2a7384db4978e01cf1d046c 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -12,10 +12,6 @@
 
 #define ACCDET_DEVNAME "accdet"
 
-#define HEADSET_MODE_1		(1)
-#define HEADSET_MODE_2		(2)
-#define HEADSET_MODE_6		(6)
-
 #define MT6359_ACCDET_NUM_BUTTONS 4
 #define MT6359_ACCDET_JACK_MASK (SND_JACK_HEADPHONE | \
 				SND_JACK_HEADSET | \
@@ -51,7 +47,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:58 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:58 -0300
Subject: [PATCH v3 17/20] ASoC: mediatek: mt6359-accdet: Always set
 comp-vth to 1.6V
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-17-5b0eafc29f5b@collabora.com>

The driver currently reads a mediatek,eint-comp-vth property from DT to
determine the voltage threshold of the EINT comparator. Since there are
no current users of the property and setting it to 1.6V is known to work
across multiple boards, remove the code handling this property and
instead always configure it to 1.6V. The property can be properly
introduced in the binding in the future if it really turns out that
different boards need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 8 ++------
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 12697b02faff1be39317116cd7d8ffa359f2cd4e..3f6a97e8de8d174e59e512d53135fadc5765b5c1 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -61,6 +61,7 @@
 #define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
 #define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
 #define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+#define ACCDET_EINT_COMP_VTH_1600MV 2
 
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
@@ -506,11 +507,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
-				   &priv->data->eint_comp_vth);
-	if (ret)
-		priv->data->eint_comp_vth = 0x0;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -594,7 +590,7 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 			   0x3 << RG_ACCDETSPARE_SFT,
 			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
-		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
+		     val | ACCDET_EINT_COMP_VTH_1600MV << RG_EINTCOMPVTH_SFT);
 }
 
 static void mt6359_accdet_init(struct mt6359_accdet *priv)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 579373807c414130b2a7384db4978e01cf1d046c..288b8fbf7c5efaee6520a2c0a5845e156f3b805d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -48,7 +48,6 @@ enum {
 
 struct dts_data {
 	bool hp_eint_high;
-	unsigned int eint_comp_vth;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:15:59 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:15:59 -0300
Subject: [PATCH v3 18/20] ASoC: mediatek: mt6359-accdet: Always use EINT0
 IRQ
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-18-5b0eafc29f5b@collabora.com>

The ACCDET block can generate two distinct EINT interrupts: EINT0 and
EINT1, and which is enabled is currently determined by mediatek,eint-num
property in DT. However, only EINT0 is used on the boards that are
known to have working ACCDET. Since there are no current users of the
property, remove its handling and instead always enable EINT0. The
property can be properly introduced in the binding in the future if it
really turns out that other boards require EINT1.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 187 +++++++++------------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 43 insertions(+), 145 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 3f6a97e8de8d174e59e512d53135fadc5765b5c1..b1e63f3f7fa44687b1cac47c0e33f68a28e15a47 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,10 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT0		BIT(2)
-#define ACCDET_PMIC_EINT1		BIT(3)
-#define ACCDET_PMIC_BI_EINT		BIT(4)
-
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_RSV_KEY			BIT(11)
@@ -84,17 +80,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches off */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT0CONFIGACCDET_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT1CONFIGACCDET_SFT));
-	}
+	/* enable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT,
+			   BIT(RG_EINT0CONFIGACCDET_SFT));
 	/*select 500k, use internal resistor */
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
@@ -103,27 +92,13 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 
 static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
-	}
+	/* disable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-	}
+	/* set DA stable signal */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
 	return 0;
 }
 
@@ -149,55 +124,26 @@ static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-	}
+	/* disable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_M_SW_EN_ADDR,
-				   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_M_SW_EN_ADDR,
-				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
-	}
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable eint0cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable eint1cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-	}
-
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_M_SW_EN_ADDR,
+			   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
+	/* enable eint0cen */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+			   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+
+	/* enable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 }
 
 static void recover_eint_setting(struct mt6359_accdet *priv)
@@ -486,10 +432,8 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
 
 static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 {
-	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
 	if (!node)
@@ -497,16 +441,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT0;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_EINT1;
-	else if (tmp == 2)
-		priv->caps |= ACCDET_PMIC_BI_EINT;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -520,13 +454,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
 		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT0_STABLE_VAL);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT1_STABLE_VAL);
-	}
+	regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
+		     ACCDET_EINT0_STABLE_VAL);
 	/* after receive n+1 number, interrupt issued. */
 	regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR,
 			   ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT,
@@ -543,17 +472,9 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 
 	if (priv->data->hp_eint_high) {
 		/* EINT polarity inverse */
@@ -571,13 +492,8 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR,
-				   RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR,
-				   RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR, RG_EINT0EN_MASK_SFT,
+			   BIT(RG_EINT0EN_SFT));
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
 			   1 << 8, 1 << 8);
@@ -727,35 +643,18 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		priv->accdet_eint0 = platform_get_irq(pdev, 1);
-		if (priv->accdet_eint0 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint0,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT0", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint0 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
-		}
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		priv->accdet_eint1 = platform_get_irq(pdev, 2);
-		if (priv->accdet_eint1 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint1,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT1", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint1 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
+	priv->accdet_eint0 = platform_get_irq(pdev, 1);
+	if (priv->accdet_eint0 >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+						priv->accdet_eint0,
+						NULL, mt6359_accdet_irq,
+						IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+						"ACCDET_EINT0", priv);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request eint0 IRQ (%d)\n",
+				ret);
+			return ret;
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 288b8fbf7c5efaee6520a2c0a5845e156f3b805d..4156cbc7f0a1744226d5f28746bd13fec6c615b4 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -58,7 +58,6 @@ struct mt6359_accdet {
 	unsigned int caps;
 	int accdet_irq;
 	int accdet_eint0;
-	int accdet_eint1;
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:16:00 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:16:00 -0300
Subject: [PATCH v3 19/20] arm64: dts: mt6359: Add accessory detect node
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-19-5b0eafc29f5b@collabora.com>

Add audio jack detection node. PMIC accessory detect driver will
create an input device that will send key events on jack
insertion/removal or accessory device key presses.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Macpaul Lin <macpaul.lin at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/boot/dts/mediatek/mt6359.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
index 7b10f9c59819a9ad02319f00938f35c931091f9f..e24e4aeb3b9cafa2af56c62bc4c549df27d0ec73 100644
--- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
@@ -15,6 +15,10 @@ pmic_adc: adc {
 			#io-channel-cells = <1>;
 		};
 
+		accdet: accdet {
+			compatible = "mediatek,mt6359-accdet";
+		};
+
 		mt6359codec: audio-codec {
 			compatible = "mediatek,mt6359-codec";
 		};

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 07:16:01 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 12:16:01 -0300
Subject: [PATCH v3 20/20] arm64: defconfig: Enable MT6359 ACCDET
In-Reply-To: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
Message-ID: <20250304-mt6359-accdet-dts-v3-20-5b0eafc29f5b@collabora.com>

Enable support for the ACCDET block in the MT6359 PMIC, which provides
jack detection capabilities to MediaTek platforms.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db29822036d25a7228f8936e2ad613b208..d4a6eeec8ba0db110dd831e146716a0e50cc294f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1066,6 +1066,7 @@ CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_SOC_WSA881X=m
 CONFIG_SND_SOC_WSA883X=m
 CONFIG_SND_SOC_WSA884X=m
+CONFIG_SND_SOC_MT6359_ACCDET=m
 CONFIG_SND_SOC_NAU8822=m
 CONFIG_SND_SOC_LPASS_WSA_MACRO=m
 CONFIG_SND_SOC_LPASS_VA_MACRO=m

-- 
2.48.1



From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:18:14 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:48:14 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250303194647.GC1552306@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
Message-ID: <20250304151814.6xu7cbpwpqrvcad5@thinkpad>

+ Geert (who reported the regression in -next)

On Tue, Mar 04, 2025 at 04:46:47AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> [...]
> > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > +{
> > > +	char dirname[DWC_DEBUGFS_BUF_MAX];
> > > +	struct device *dev = pci->dev;
> > > +	struct debugfs_info *debugfs;
> > > +	struct dentry *dir;
> > > +	int ret;
> > > +
> > > +	/* Create main directory for each platform driver */
> > > +	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > +	dir = debugfs_create_dir(dirname, NULL);
> > > +	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > +	if (!debugfs)
> > > +		return -ENOMEM;
> > > +
> > > +	debugfs->debug_dir = dir;
> > > +	pci->debugfs = debugfs;
> > > +	ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > +	if (ret)
> > > +		dev_dbg(dev, "RASDES debugfs init failed\n");
> > 
> > What will happen if ret != 0? still return 0? 
> 
> Given that callers of dwc_pcie_debugfs_init() check for errors,
> this probably should correctly bubble up any failure coming from
> dwc_pcie_rasdes_debugfs_init().
> 
> I made updates to the code directly on the current branch, have a look:
> 
>   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=1ff54f4cbaed9ec6994844967c36cf7ada4cbe5e
> 
> Let me know if this is OK with you.
> 

If the SoC has no RASDES capability, then this call is bound to fail (which will
break existing platforms). I'd propose to return 0 if
dw_pcie_find_rasdes_capability() fails in addition to this change:

diff --git a/drivers/pci/controller/dwc/pcie-designware-debugfs.c b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
index dca1e9999113..7277a21e30d5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c
+++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
@@ -471,7 +471,7 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
        ras_cap = dw_pcie_find_rasdes_capability(pci);
        if (!ras_cap) {
                dev_dbg(dev, "no RASDES capability available\n");
-               return -ENODEV;
+               return 0;
        }
 
        rasdes_info = devm_kzalloc(dev, sizeof(*rasdes_info), GFP_KERNEL);

This will fix the regressions like the one reported by Geert:

https://lore.kernel.org/linux-pci/CAMuHMdWuCJAd-mCpCoseThureCKnnep4T-Z0h1_WJ1BOf2ZeDg at mail.gmail.com/

- Mani

-- 
????????? ????????


From adrian.hunter at intel.com  Tue Mar  4 07:21:11 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 4 Mar 2025 17:21:11 +0200
Subject: [PATCH v4 01/12] perf script: Make printing flags reliable
In-Reply-To: <20250304111240.3378214-2-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
 <20250304111240.3378214-2-leo.yan@arm.com>
Message-ID: <21ad7f1c-eb08-45fc-9a2c-3d55787f15d7@intel.com>

On 4/03/25 13:12, Leo Yan wrote:
> Add a check for the generated string of flags.  Print out the raw number
> if the string generation fails.
> 
> Use the SAMPLE_FLAGS_STR_ALIGNED_SIZE macro to replace the value '21'.
> 
> Reviewed-by: Ian Rogers <irogers at google.com>
> Reviewed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Leo Yan <leo.yan at arm.com>

Reviewed-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  tools/perf/builtin-script.c   | 9 +++++++--
>  tools/perf/util/trace-event.h | 2 ++
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> index d797cec4f054..8ca04293d335 100644
> --- a/tools/perf/builtin-script.c
> +++ b/tools/perf/builtin-script.c
> @@ -1709,9 +1709,14 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
>  static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
>  {
>  	char str[SAMPLE_FLAGS_BUF_SIZE];
> +	int ret;
> +
> +	ret = perf_sample__sprintf_flags(flags, str, sizeof(str));
> +	if (ret < 0)
> +		return fprintf(fp, "  raw flags:0x%-*x ",
> +			       SAMPLE_FLAGS_STR_ALIGNED_SIZE - 12, flags);
>  
> -	perf_sample__sprintf_flags(flags, str, sizeof(str));
> -	return fprintf(fp, "  %-21s ", str);
> +	return fprintf(fp, "  %-*s ", SAMPLE_FLAGS_STR_ALIGNED_SIZE, str);
>  }
>  
>  struct printer_data {
> diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
> index ac9fde2f980c..71e680bc3d4b 100644
> --- a/tools/perf/util/trace-event.h
> +++ b/tools/perf/util/trace-event.h
> @@ -145,6 +145,8 @@ int common_flags(struct scripting_context *context);
>  int common_lock_depth(struct scripting_context *context);
>  
>  #define SAMPLE_FLAGS_BUF_SIZE 64
> +#define SAMPLE_FLAGS_STR_ALIGNED_SIZE	21
> +
>  int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz);
>  
>  #if defined(LIBTRACEEVENT_VERSION) &&  LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0)



From maz at kernel.org  Tue Mar  4 07:25:28 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 04 Mar 2025 15:25:28 +0000
Subject: [PATCH 03/18] KVM: arm64: Handle trapping of FEAT_LS64* instructions
In-Reply-To: <CA+EHjTwkX+sy1wuS8LvGM+=m_S-h-=xUUXOyMapnoLiHt0XpOw@mail.gmail.com>
References: <20250210184150.2145093-1-maz@kernel.org>
	<20250210184150.2145093-4-maz@kernel.org>
	<CA+EHjTwkX+sy1wuS8LvGM+=m_S-h-=xUUXOyMapnoLiHt0XpOw@mail.gmail.com>
Message-ID: <86frjsq0lz.wl-maz@kernel.org>

Hi Fuad,

On Tue, 04 Mar 2025 14:36:19 +0000,
Fuad Tabba <tabba at google.com> wrote:
> 
> Hi Marc,
> 
> On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
> >
> > We generally don't expect FEAT_LS64* instructions to trap, unless
> > they are trapped by a guest hypervisor.
> >
> > Otherwise, this is just the guest playing tricks on us by using
> > an instruction that isn't advertised, which we handle with a well
> > deserved UNDEF.
> >
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > ---
> >  arch/arm64/kvm/handle_exit.c | 64 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 64 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> > index 512d152233ff2..4f8354bf7dc5f 100644
> > --- a/arch/arm64/kvm/handle_exit.c
> > +++ b/arch/arm64/kvm/handle_exit.c
> > @@ -294,6 +294,69 @@ static int handle_svc(struct kvm_vcpu *vcpu)
> >         return 1;
> >  }
> >
> > +static int handle_ls64b(struct kvm_vcpu *vcpu)
> > +{
> > +       struct kvm *kvm = vcpu->kvm;
> > +       u64 esr = kvm_vcpu_get_esr(vcpu);
> > +       u64 iss = ESR_ELx_ISS(esr);
> > +       bool allowed;
> > +
> > +       switch (iss) {
> > +       case ESR_ELx_ISS_ST64BV:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
> > +               break;
> > +       case ESR_ELx_ISS_ST64BV0:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
> > +               break;
> > +       case ESR_ELx_ISS_LDST64B:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
> > +               break;
> > +       default:
> > +               /* Clearly, we're missing something. */
> > +               goto unknown_trap;
> > +       }
> > +
> > +       if (!allowed)
> > +               goto undef;
> > +
> > +       if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
> > +               u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
> > +               bool fwd;
> > +
> > +               switch (iss) {
> > +               case ESR_ELx_ISS_ST64BV:
> > +                       fwd = !(hcrx & HCRX_EL2_EnASR);
> > +                       break;
> > +               case ESR_ELx_ISS_ST64BV0:
> > +                       fwd = !(hcrx & HCRX_EL2_EnAS0);
> > +                       break;
> > +               case ESR_ELx_ISS_LDST64B:
> > +                       fwd = !(hcrx & HCRX_EL2_EnALS);
> > +                       break;
> > +               default:
> > +                       /* We don't expect to be here */
> > +                       fwd = false;
> > +               }
> > +
> > +               if (fwd) {
> > +                       kvm_inject_nested_sync(vcpu, esr);
> > +                       return 1;
> > +               }
> > +       }
> > +
> > +unknown_trap:
> > +       /*
> > +        * If we land here, something must be very wrong, because we
> > +        * have no idea why we trapped at all. Warn and undef as a
> > +        * fallback.
> > +        */
> > +       WARN_ON(1);
> 
> nit: should this be WARN_ONCE() instead?
> 
> > +
> > +undef:
> > +       kvm_inject_undefined(vcpu);
> > +       return 1;
> > +}
> 
> I'm wondering if this can be simplified by having one switch()
> statement that toggles both allowed and fwd (or maybe even only fwd),
> and then inject depending on that, e.g.,
> 
> +static int handle_ls64b(struct kvm_vcpu *vcpu)
> +{
> +    struct kvm *kvm = vcpu->kvm;
> +    bool is_nv = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
> +    u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
> +    u64 esr = kvm_vcpu_get_esr(vcpu);
> +    u64 iss = ESR_ELx_ISS(esr);
> +    bool fwd = false;
> +
> +    switch (iss) {
> +    case ESR_ELx_ISS_ST64BV:
> +         fwd = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V) &&
> +                   !(hcrx & HCRX_EL2_EnASR)
> +         break;
> ...
> +    default:
> +        WARN_ONCE(1);
> + }
> +
> +    if (is_nv && fwd) {
> +        kvm_inject_nested_sync(vcpu, esr);
> +    else
> +        kvm_inject_undefined(vcpu);
> +
> +    return 1;
> +}
> 
> I think this has the same effect as the code above.

Yeah, I think something like that could work. I initially was trying
to handle all 4 states (allowed, fwd), but obviously some states do
not exist (you don't forward something that isn't allowed).

My only concern here is that we don't have clear rules on the init of
EL2 guest registers such as HCRX_EL2 when !NV, but that's something
that can be easily done (or even worked around locally).

Maybe we should introduce the dreaded notion of "effective value" for
EL2 registers when NV is not enabled...

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From Frank.li at nxp.com  Tue Mar  4 07:26:25 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 10:26:25 -0500
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <20250304093127.1954549-2-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
Message-ID: <Z8cboXGsy1uyJwgf@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> Add interrupts-extended property for edma that has multiple interrupt
> controllers used.
>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - newly added entry
> ---
>  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> index d54140f18d34..549afb8611a9 100644
> --- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> @@ -38,6 +38,10 @@ properties:
>      minItems: 1
>      maxItems: 64
>
> +  interrupts-extended:
> +    minItems: 1
> +    maxItems: 65
> +

I suggest add error irq later because optional err-irq patch under review.
https://lore.kernel.org/imx/20250228-edma_err-v1-0-d1869fe4163e at nxp.com/T/#t

Frank

>    interrupt-names:
>      minItems: 1
>      maxItems: 64
> @@ -87,9 +91,14 @@ required:
>    - "#dma-cells"
>    - compatible
>    - reg
> -  - interrupts
>    - dma-channels
>
> +oneOf:
> +  - required:
> +    - interrupts
> +  - required:
> +    - interrupts-extended
> +
>  allOf:
>    - $ref: dma-controller.yaml#
>    - if:
> --
> 2.34.1
>


From Frank.li at nxp.com  Tue Mar  4 07:27:36 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 10:27:36 -0500
Subject: [PATCH v2 4/4] arm64: dts: freescale: Add minimal dts support
 for imx943 evk
In-Reply-To: <20250304093127.1954549-5-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-5-ping.bai@nxp.com>
Message-ID: <Z8cb6MhDrbJvBI3h@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 05:31:27PM +0800, Jacky Bai wrote:
> Add the minimal board dts support for i.MX943 EVK. Only the
> console uart, SD & eMMC are enabled for linux basic boot.
>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  - v2 changes:
>   - newly added for board dts
> ---
>  arch/arm64/boot/dts/freescale/Makefile       |   1 +
>  arch/arm64/boot/dts/freescale/imx943-evk.dts | 196 +++++++++++++++++++
>  2 files changed, 197 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/freescale/imx943-evk.dts
>
> diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
> index 839432153cc7..02863c09bb8b 100644
> --- a/arch/arm64/boot/dts/freescale/Makefile
> +++ b/arch/arm64/boot/dts/freescale/Makefile
> @@ -282,6 +282,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
> +dtb-$(CONFIG_ARCH_MXC) += imx943-evk.dtb
>
>  imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
>
> diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts
> new file mode 100644
> index 000000000000..d4a204eaf5e5
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts
> @@ -0,0 +1,196 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright 2024-2025 NXP
> + */
> +
> +/dts-v1/;
> +
> +#include "imx943.dtsi"
> +
> +/ {
> +	compatible = "fsl,imx943-evk", "fsl,imx94";
> +	model = "NXP i.MX943 EVK board";
> +
> +	aliases {
> +		mmc0 = &usdhc1;
> +		mmc1 = &usdhc2;
> +		serial0 = &lpuart1;
> +	};
> +
> +	chosen {
> +		stdout-path = &lpuart1;
> +	};
> +
> +	reg_usdhc2_vmmc: regulator-usdhc2 {
> +		compatible = "regulator-fixed";
> +		off-on-delay-us = <12000>;
> +		pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
> +		pinctrl-names = "default";
> +		regulator-max-microvolt = <3300000>;
> +		regulator-min-microvolt = <3300000>;
> +		regulator-name = "VDD_SD2_3V3";
> +		gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +	};
> +
> +	reserved-memory {
> +		ranges;
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +
> +		linux,cma {
> +			compatible = "shared-dma-pool";
> +			alloc-ranges = <0 0x80000000 0 0x7f000000>;
> +			reusable;
> +			size = <0 0x10000000>;
> +			linux,cma-default;
> +		};
> +	};
> +
> +	memory at 80000000 {
> +		reg = <0x0 0x80000000 0x0 0x80000000>;
> +		device_type = "memory";
> +	};
> +};
> +
> +&lpuart1 {
> +	pinctrl-0 = <&pinctrl_uart1>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&scmi_iomuxc {
> +	pinctrl_uart1: uart1grp {
> +		fsl,pins = <
> +			IMX94_PAD_UART1_TXD__LPUART1_TX		0x31e
> +			IMX94_PAD_UART1_RXD__LPUART1_RX		0x31e
> +		>;
> +	};
> +
> +	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
> +			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
> +			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
> +			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
> +			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
> +			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
> +			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
> +			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
> +			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
> +			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
> +			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
> +		>;
> +	};
> +
> +	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x15fe
> +			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x13fe
> +			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x13fe
> +			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x13fe
> +			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x13fe
> +			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x13fe
> +			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x13fe
> +			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x13fe
> +			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x13fe
> +			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x13fe
> +			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x15fe
> +		>;
> +	};
> +
> +	pinctrl_usdhc1: usdhc1grp {
> +		fsl,pins = <
> +			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
> +			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
> +			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
> +			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
> +			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
> +			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
> +			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
> +			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
> +			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
> +			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
> +			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
> +		>;
> +	};
> +
> +	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
> +			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
> +			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
> +			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
> +			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
> +			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
> +			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
> +		>;
> +	};
> +
> +	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x15fe
> +			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x13fe
> +			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x13fe
> +			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x13fe
> +			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x13fe
> +			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x13fe
> +			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
> +		>;
> +	};
> +
> +	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD2_CD_B__GPIO4_IO20		0x31e
> +		>;
> +	};
> +
> +	pinctrl_usdhc2: usdhc2grp {
> +		fsl,pins = <
> +			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
> +			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
> +			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
> +			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
> +			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
> +			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
> +			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
> +		>;
> +	};
> +
> +	pinctrl_reg_usdhc2_vmmc: usdhc2regvmmcgrp {
> +		fsl,pins = <
> +			IMX94_PAD_SD2_RESET_B__GPIO4_IO27	0x31e
> +		>;
> +	};
> +};
> +
> +&usdhc1 {
> +	pinctrl-0 = <&pinctrl_usdhc1>;
> +	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
> +	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
> +	pinctrl-3 = <&pinctrl_usdhc1>;
> +	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
> +	bus-width = <8>;
> +	non-removable;
> +	no-sdio;
> +	no-sd;
> +	status = "okay";
> +};
> +
> +&usdhc2 {
> +	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
> +	bus-width = <4>;
> +	cd-gpios = <&gpio4 20 GPIO_ACTIVE_LOW>;
> +	vmmc-supply = <&reg_usdhc2_vmmc>;
> +	fsl,cd-gpio-wakeup-disable;
> +	status = "okay";
> +};
> +
> +&wdog3 {
> +	fsl,ext-reset-output;
> +	status = "okay";
> +};
> --
> 2.34.1
>


From sudeep.holla at arm.com  Tue Mar  4 07:28:32 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 4 Mar 2025 15:28:32 +0000
Subject: [PATCH] firmware: arm_scmi: use ioread64() instead of
 ioread64_hi_lo()
In-Reply-To: <20250304144346.1025658-1-arnd@kernel.org>
References: <20250304144346.1025658-1-arnd@kernel.org>
Message-ID: <Z8ccIBTgn6n7CYXh@bogus>

Hi Arnd,

On Tue, Mar 04, 2025 at 03:43:34PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> The scmi_common_fastchannel_db_ring() function calls either ioread64()
> or ioread64_hi_lo() depending on whether it is compiler for 32-bit
> or 64-bit architectures.
> 
> The same logic is used to define ioread64() itself in the
> linux/io-64-nonatomic-hi-lo.h header file, so the special case
> is not really needed.
> 
> The behavior here should not change at all.

LGTM. I just sent PR for v6.15 this morning. Either I can redo PR with
this included or you can just apply this directly. I am fine either way.
If you go for the latter approach,

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

If you prefer me to send updated PR, let me know. I don't want to create
confusion by recalling by PR and sending an updated one without consulting
you.

--
Regards,
Sudeep


From jernej.skrabec at gmail.com  Tue Mar  4 07:28:48 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Tue, 04 Mar 2025 16:28:48 +0100
Subject: [PATCH v3 03/15] clk: sunxi-ng: Add support for update bit
In-Reply-To: <20250304012805.28594-4-andre.przywara@arm.com>
References: <20250304012805.28594-1-andre.przywara@arm.com>
 <20250304012805.28594-4-andre.przywara@arm.com>
Message-ID: <3616088.iIbC2pHGDl@jernej-laptop>

Dne torek, 4. marec 2025 ob 02:27:53 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Some clocks in the Allwinner A523 SoC contain an "update bit" (bit 27),
> which must be set to apply any register changes, namely the mux
> selector, the divider and the gate bit.
> 
> Add a new CCU feature bit to mark those clocks, and set bit 27 whenever
> we are applying any changes.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  drivers/clk/sunxi-ng/ccu_common.h | 4 ++++
>  drivers/clk/sunxi-ng/ccu_div.c    | 2 ++
>  drivers/clk/sunxi-ng/ccu_gate.c   | 4 ++++
>  drivers/clk/sunxi-ng/ccu_mux.c    | 2 ++
>  4 files changed, 12 insertions(+)
> 
> diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
> index 50fd268329671..d41d33bdff470 100644
> --- a/drivers/clk/sunxi-ng/ccu_common.h
> +++ b/drivers/clk/sunxi-ng/ccu_common.h
> @@ -20,10 +20,14 @@
>  #define CCU_FEATURE_KEY_FIELD		BIT(8)
>  #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
>  #define CCU_FEATURE_DUAL_DIV		BIT(10)
> +#define CCU_FEATURE_UPDATE_BIT27	BIT(11)

There is no reason to have "BIT27" in the name of the macro. This is similar
to KEY_FIELD, which is generic name and doesn't specify either key or position
of this key field. Maybe just CCU_FEATURE_UPDATE_BIT or something equaly
generic.

With that fixed:
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej

>  
>  /* MMC timing mode switch bit */
>  #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
>  
> +/* Some clocks need this bit to actually apply register changes */
> +#define CCU_SUNXI_UPDATE_BIT		BIT(27)
> +
>  struct device_node;
>  
>  struct ccu_common {
> diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
> index 7f4691f09e01f..2d8b98fe4b13a 100644
> --- a/drivers/clk/sunxi-ng/ccu_div.c
> +++ b/drivers/clk/sunxi-ng/ccu_div.c
> @@ -106,6 +106,8 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	reg = readl(cd->common.base + cd->common.reg);
>  	reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
> +	if (cd->common.features & CCU_FEATURE_UPDATE_BIT27)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>  
>  	writel(reg | (val << cd->div.shift),
>  	       cd->common.base + cd->common.reg);
> diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
> index ac52fd6bff677..0490f95781361 100644
> --- a/drivers/clk/sunxi-ng/ccu_gate.c
> +++ b/drivers/clk/sunxi-ng/ccu_gate.c
> @@ -20,6 +20,8 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
>  	spin_lock_irqsave(common->lock, flags);
>  
>  	reg = readl(common->base + common->reg);
> +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>  	writel(reg & ~gate, common->base + common->reg);
>  
>  	spin_unlock_irqrestore(common->lock, flags);
> @@ -44,6 +46,8 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
>  	spin_lock_irqsave(common->lock, flags);
>  
>  	reg = readl(common->base + common->reg);
> +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>  	writel(reg | gate, common->base + common->reg);
>  
>  	spin_unlock_irqrestore(common->lock, flags);
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> index d7ffbdeee9e04..82ee21e0d3a68 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.c
> +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> @@ -197,6 +197,8 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
>  	/* The key field always reads as zero. */
>  	if (common->features & CCU_FEATURE_KEY_FIELD)
>  		reg |= CCU_MUX_KEY_VALUE;
> +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>  
>  	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
>  	writel(reg | (index << cm->shift), common->base + common->reg);
> 






From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:29:52 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 20:59:52 +0530
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250303095200.GB1065658@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
 <20250303095200.GB1065658@rocinante>
Message-ID: <20250304152952.pal66goo2dwegevh@thinkpad>

On Mon, Mar 03, 2025 at 06:52:00PM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> [...]
> > +		29) Generates duplicate TLPs - duplicate_dllp
> > +		30) Generates Nullified TLPs - nullified_tlp
> 
> Would the above field called "duplicate_dllp" for duplicate TLPs be
> a potential typo?  Perhaps this should be called "duplicate_tlp"?
> 

Looks like a typo. As per Synopsys documentation, there is only 'duplicate TLP'
field.

Good catch!

- Mani

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Tue Mar  4 07:32:06 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 21:02:06 +0530
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <Z8YZEALV71PUkXpF@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
 <20250221131548.59616-6-shradha.t@samsung.com>
 <Z8XuuNb6TRevUlHH@debian>
 <20250303194228.GB1552306@rocinante>
 <Z8YZEALV71PUkXpF@debian>
Message-ID: <20250304153206.gr7footrqrpc5uxf@thinkpad>

On Mon, Mar 03, 2025 at 01:03:12PM -0800, Fan Ni wrote:
> On Tue, Mar 04, 2025 at 04:42:28AM +0900, Krzysztof Wilczy?ski wrote:
> > Hello,
> > 
> > [...]
> > > > +static ssize_t counter_value_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
> > > > +{
> > > > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > > > +	struct dw_pcie *pci = pdata->pci;
> > > > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > > > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > > > +	ssize_t pos;
> > > > +	u32 val;
> > > > +
> > > > +	mutex_lock(&rinfo->reg_event_lock);
> > > > +	set_event_number(pdata, pci, rinfo);
> > > > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > > > +	mutex_unlock(&rinfo->reg_event_lock);
> > > > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter value: %d\n", val);
> > > > +
> > > > +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf, pos);
> > > > +}
> > > 
> > > Do we need to check whether the counter is enabled or not for the event
> > > before retrieving the counter value?
> > 
> > I believe, we have a patch that aims to address, have a look at:
> > 
> >   https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivannan.sadhasivam at linaro.org
> 
> Maybe I missed something, that seems to fix counter_enable_read(), but
> here is to retrieve counter value. 
> How dw_pcie_readl_dbi() can return something like "Counter Disabled"? 
> 

Only way to know if a counter is enabled by reading back the status. And that is
what the patch is doing.

- Mani

-- 
????????? ????????


From laurentiumihalcea111 at gmail.com  Tue Mar  4 07:34:57 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 4 Mar 2025 17:34:57 +0200
Subject: [PATCH v3 0/4] clk: imx8mp: fix parents of AUDIOMIX DSP/OCRAM_A
In-Reply-To: <Z8Xn7f6vXg0aM4zx@linaro.org>
References: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
 <174102305899.2928950.8837177294161174759.b4-ty@linaro.org>
 <Z8Xn7f6vXg0aM4zx@linaro.org>
Message-ID: <09aba9f8-354d-4987-9026-37eb3ca26d6f@gmail.com>



On 3/3/2025 7:33 PM, Abel Vesa wrote:
> On 25-03-03 19:30:58, Abel Vesa wrote:
>> On Wed, 26 Feb 2025 11:45:09 -0500, Laurentiu Mihalcea wrote:
>>> Correct the parent of the AUDIOMIX DSP and OCRAM_A clock gates by setting
>>> it to AUDIO_AXI_CLK_ROOT, instead of AUDIO_AHB_CLK_ROOT. Additionally, set
>>> the frequency of AUDIO_AXI_CLK_ROOT to 800MHz instead of the current
>>> 400MHz.
>>>
>> Applied, thanks!
>>
>> [1/4] dt-bindings: clock: imx8mp: add axi clock
>>       commit: 2471a101938b0d1835b1983df08daeb98eef1205
>> [2/4] clk: clk-imx8mp-audiomix: fix dsp/ocram_a clock parents
>>       commit: 91be7d27099dedf813b80702e4ca117d1fb38ce6
>> [3/4] arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to AUDIOMIX block
>>       (no commit info)
>> [4/4] arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT freq. to 800MHz
>>       (no commit info)
> Applied only patches 1 and 2.
>
> My b4 setup messed up. Sorry.
would it be possible to also have patch no. 3 merged via the IMX CLK tree? I'd like to at least keep the first 3 patches together as they all fix the issue of OCRAM_A/DSP clocks having the wrong parent. if not, Shawn would you mind picking up patches 3 and 4? Thanks!


From kw at linux.com  Tue Mar  4 07:35:09 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 00:35:09 +0900
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250304152952.pal66goo2dwegevh@thinkpad>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
 <20250303095200.GB1065658@rocinante>
 <20250304152952.pal66goo2dwegevh@thinkpad>
Message-ID: <20250304153509.GA2310180@rocinante>

Hello,

[....]
> > > +		29) Generates duplicate TLPs - duplicate_dllp
> > > +		30) Generates Nullified TLPs - nullified_tlp
> > 
> > Would the above field called "duplicate_dllp" for duplicate TLPs be
> > a potential typo?  Perhaps this should be called "duplicate_tlp"?
> > 
> 
> Looks like a typo. As per Synopsys documentation, there is only 'duplicate TLP'
> field.
> 
> Good catch!

Updated.  Thank you!

	Krzysztof


From broonie at kernel.org  Tue Mar  4 07:35:59 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 04 Mar 2025 15:35:59 +0000
Subject: [PATCH 0/6] ASoC: samsung: GPIO descriptor conversion
In-Reply-To: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
Message-ID: <174110255924.87345.17067818310965896666.b4-ty@kernel.org>

On Mon, 03 Mar 2025 09:41:40 +0100, Linus Walleij wrote:
> This drops unused includes and converts one Samsung
> codec to use GPIO descriptors.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/6] ASoC: samsung: bells: Drop unused include
      commit: b19d340d5d08c5940ce612c2a1b5fe3a8a401f9d
[2/6] ASoC: samsung: littlemill: Drop unused include
      commit: c4b2d9643a06a5326a778c4d77d6fa60e0f3d6b1
[3/6] ASoC: samsung: lowland: Drop unused include
      commit: 5c06f7f3d8374df1cec3b353306a4d1032a60f44
[4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
      commit: da9146c19b1774926148ff271c4a3dc8d7891b18
[5/6] ASoC: samsung: tobermory: Drop unused include
      commit: c095b7a27529d1d18b3b36a47f77a1419f0de939
[6/6] ASoC: samsung: tm2_wm5110: Drop unused include
      commit: 0a22454ab2eca530702b2689858909b608953703

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From Frank.li at nxp.com  Tue Mar  4 07:35:59 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 10:35:59 -0500
Subject: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <20250304093127.1954549-4-ping.bai@nxp.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-4-ping.bai@nxp.com>
Message-ID: <Z8cd33Aw3tpPBism@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 05:31:26PM +0800, Jacky Bai wrote:
> Add the minimal dtsi support for i.MX943. i.MX943 is the
> first SoC of i.MX94 Family, create a common dtsi for the
> whole i.MX94 family, and the specific dtsi part for i.MX943.
>
> The clock, power domain and perf index need to be used by
> the device nodes for resource reference, add them along
> with the dtsi support.
>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - remove the unnecessary macro define in clock header as suggested by Krzysztof
>   - split the dtsi into imx94.dtsi and imx943.dtsi
>   - use low case in the pinfunc header as Frank suggested
>   - reorder the device nodes and properties
>   - resolve Krzysztof's other comments
> ---
...
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc_24m";
> +	};
> +
> +	dummy: clock-dummy {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <0>;
> +		clock-output-names = "dummy";
> +	};
> +
> +	clk_ext1: clock-ext1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <133000000>;
> +		clock-output-names = "clk_ext1";
> +	};
> +
> +	sai1_mclk: clock-sai1-mclk1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <0>;
> +		clock-output-names = "sai1_mclk";
> +	};
> +
> +	sai2_mclk: clock-sai2-mclk1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <0>;
> +		clock-output-names = "sai2_mclk";
> +	};
> +
> +	sai3_mclk: clock-sai3-mclk1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <0>;
> +		clock-output-names = "sai3_mclk";
> +	};
> +
> +	sai4_mclk: clock-sai4-mclk1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <0>;
> +		clock-output-names = "sai4_mclk";
> +	};
> +
> +	firmware {
> +

Remove empty line here.

Frank
> +		scmi {
> +			compatible = "arm,scmi";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>, <&mu2 5 1>;
> +			shmem = <&scmi_buf0>, <&scmi_buf1>;
> +			arm,max-rx-timeout-ms = <5000>;
> +
> +			scmi_devpd: protocol at 11 {
> +				reg = <0x11>;
> +				#power-domain-cells = <1>;
> +			};
> +
> +			scmi_sys_power: protocol at 12 {
> +				reg = <0x12>;
> +			};
> +
> +			scmi_perf: protocol at 13 {
> +				reg = <0x13>;
> +				#power-domain-cells = <1>;
> +			};
> +
> +			scmi_clk: protocol at 14 {
> +				reg = <0x14>;
> +				#clock-cells = <1>;
> +			};
> +
> +			scmi_iomuxc: protocol at 19 {
> +				reg = <0x19>;
> +			};
> +
> +			scmi_bbm: protocol at 81 {
> +				reg = <0x81>;
> +			};
> +
> +			scmi_misc: protocol at 84 {
> +				reg = <0x84>;
> +			};
> +		};
> +	};
> +
> +	pmu {
> +		compatible = "arm,cortex-a55-pmu";
> +		interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-1.0";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
> +			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
> +			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
> +			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
> +		clock-frequency = <24000000>;
> +		interrupt-parent = <&gic>;
> +		arm,no-tick-in-suspend;
> +	};
> +
> +	gic: interrupt-controller at 48000000 {
> +		compatible = "arm,gic-v3";
> +		reg = <0 0x48000000 0 0x10000>,
> +		      <0 0x48060000 0 0xc0000>;
> +		ranges;
> +		#interrupt-cells = <3>;
> +		interrupt-controller;
> +		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		dma-noncoherent;
> +		interrupt-parent = <&gic>;
> +
> +		its: msi-controller at 48040000 {
> +			compatible = "arm,gic-v3-its";
> +			reg = <0 0x48040000 0 0x20000>;
> +			#msi-cells = <1>;
> +			dma-noncoherent;
> +			msi-controller;
> +		};
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		ranges;
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +
> +		aips2: bus at 42000000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0x0 0x42000000 0x0 0x800000>;
> +			ranges = <0x42000000 0x0 0x42000000 0x8000000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			edma2: dma-controller at 42000000 {
> +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> +				reg = <0x42000000 0x210000>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "dma";
> +				#dma-cells = <3>;
> +				dma-channels = <64>;
> +				interrupts-extended = <&a55_irqsteer 0>, <&a55_irqsteer 1>, <&a55_irqsteer 2>,
> +					<&a55_irqsteer 3>, <&a55_irqsteer 4>, <&a55_irqsteer 5>,
> +					<&a55_irqsteer 6>, <&a55_irqsteer 7>, <&a55_irqsteer 8>,
> +					<&a55_irqsteer 9>, <&a55_irqsteer 10>, <&a55_irqsteer 11>,
> +					<&a55_irqsteer 12>, <&a55_irqsteer 13>, <&a55_irqsteer 14>,
> +					<&a55_irqsteer 15>, <&a55_irqsteer 16>, <&a55_irqsteer 17>,
> +					<&a55_irqsteer 18>, <&a55_irqsteer 19>, <&a55_irqsteer 20>,
> +					<&a55_irqsteer 21>, <&a55_irqsteer 22>, <&a55_irqsteer 23>,
> +					<&a55_irqsteer 24>, <&a55_irqsteer 25>, <&a55_irqsteer 26>,
> +					<&a55_irqsteer 27>, <&a55_irqsteer 28>, <&a55_irqsteer 29>,
> +					<&a55_irqsteer 30>, <&a55_irqsteer 31>, <&a55_irqsteer 64>,
> +					<&a55_irqsteer 65>, <&a55_irqsteer 66>, <&a55_irqsteer 67>,
> +					<&a55_irqsteer 68>, <&a55_irqsteer 69>, <&a55_irqsteer 70>,
> +					<&a55_irqsteer 71>, <&a55_irqsteer 72>, <&a55_irqsteer 73>,
> +					<&a55_irqsteer 74>, <&a55_irqsteer 75>, <&a55_irqsteer 76>,
> +					<&a55_irqsteer 77>, <&a55_irqsteer 78>, <&a55_irqsteer 79>,
> +					<&a55_irqsteer 80>, <&a55_irqsteer 81>, <&a55_irqsteer 82>,
> +					<&a55_irqsteer 83>, <&a55_irqsteer 84>, <&a55_irqsteer 85>,
> +					<&a55_irqsteer 86>, <&a55_irqsteer 87>, <&a55_irqsteer 88>,
> +					<&a55_irqsteer 89>, <&a55_irqsteer 90>, <&a55_irqsteer 91>,
> +					<&a55_irqsteer 92>, <&a55_irqsteer 93>, <&a55_irqsteer 94>,
> +					<&a55_irqsteer 95>, <&gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
> +			};
> +
> +			mu10: mailbox at 42430000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42430000 0x10000>;
> +				interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			i3c2: i3c at 42520000 {
> +				compatible = "silvaco,i3c-master-v1";
> +				reg = <0x42520000 0x10000>;
> +				interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <3>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_I3C2SLOW>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&dummy>;
> +				clock-names = "pclk", "fast_clk", "slow_clk";
> +				status = "disabled";
> +			};
> +
> +			lpi2c3: i2c at 42530000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x42530000 0x10000>;
> +				interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C3>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 5 0 0>, <&edma2 6 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c4: i2c at 42540000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x42540000 0x10000>;
> +				interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C4>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 4 0 0>, <&edma4 5 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi3: spi at 42550000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x42550000 0x10000>;
> +				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI3>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 7 0 0>, <&edma2 8 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi4: spi at 42560000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x42560000 0x10000>;
> +				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI4>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 6 0 0>, <&edma4 7 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpuart3: serial at 42570000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42570000 0x1000>;
> +				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART3>;
> +				clock-names = "ipg";
> +				dmas = <&edma2 10 0 FSL_EDMA_RX>, <&edma2 9 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart4: serial at 42580000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42580000 0x1000>;
> +				interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART4>;
> +				clock-names = "ipg";
> +				dmas = <&edma4 10 0 FSL_EDMA_RX>, <&edma4 9 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart5: serial at 42590000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42590000 0x1000>;
> +				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART5>;
> +				clock-names = "ipg";
> +				dmas = <&edma2 12 0 FSL_EDMA_RX>, <&edma2 11 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart6: serial at 425a0000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x425a0000 0x1000>;
> +				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART6>;
> +				clock-names = "ipg";
> +				dmas = <&edma4 12 0 FSL_EDMA_RX>, <&edma4 11 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			flexcan2: can at 425b0000 {
> +				compatible = "fsl,imx95-flexcan";
> +				reg = <0x425b0000 0x10000>;
> +				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_CAN2>;
> +				clock-names = "ipg", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN2>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> +				assigned-clock-rates = <80000000>;
> +				fsl,clk-source = /bits/ 8 <0>;
> +				status = "disabled";
> +			};
> +
> +			flexcan3: can at 425e0000 {
> +				compatible = "fsl,imx95-flexcan";
> +				reg = <0x425e0000 0x10000>;
> +				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_CAN3>;
> +				clock-names = "ipg", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN3>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> +				assigned-clock-rates = <80000000>;
> +				fsl,clk-source = /bits/ 8 <0>;
> +				status = "disabled";
> +			};
> +
> +			flexcan4: can at 425f0000 {
> +				compatible = "fsl,imx95-flexcan";
> +				reg = <0x425f0000 0x10000>;
> +				interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_CAN4>;
> +				clock-names = "ipg", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN4>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> +				assigned-clock-rates = <80000000>;
> +				fsl,clk-source = /bits/ 8 <0>;
> +				status = "disabled";
> +			};
> +
> +			flexcan5: can at 42600000 {
> +				compatible = "fsl,imx95-flexcan";
> +				reg = <0x42600000 0x10000>;
> +				interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_CAN5>;
> +				clock-names = "ipg", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN5>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> +				assigned-clock-rates = <80000000>;
> +				fsl,clk-source = /bits/ 8 <0>;
> +				status = "disabled";
> +			};
> +
> +			sai2: sai at 42650000 {
> +				compatible = "fsl,imx95-sai";
> +				reg = <0x42650000 0x10000>;
> +				interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>, <&dummy>,
> +					<&scmi_clk IMX94_CLK_SAI2>, <&dummy>, <&dummy>;
> +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> +				dmas = <&edma2 30 0 FSL_EDMA_RX>, <&edma2 29 0 0>;
> +				dma-names = "rx", "tx";
> +				#sound-dai-cells = <0>;
> +				status = "disabled";
> +			};
> +
> +			sai3: sai at 42660000 {
> +				compatible = "fsl,imx95-sai";
> +				reg = <0x42660000 0x10000>;
> +				interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>, <&dummy>,
> +					<&scmi_clk IMX94_CLK_SAI3>, <&dummy>, <&dummy>;
> +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> +				dmas = <&edma2 32 0 FSL_EDMA_RX>, <&edma2 31 0 0>;
> +				dma-names = "rx", "tx";
> +				#sound-dai-cells = <0>;
> +				status = "disabled";
> +			};
> +
> +			sai4: sai at 42670000 {
> +				compatible = "fsl,imx95-sai";
> +				reg = <0x42670000 0x10000>;
> +				interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>, <&dummy>,
> +					<&scmi_clk IMX94_CLK_SAI4>, <&dummy>, <&dummy>;
> +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> +				dmas = <&edma2 36 0 FSL_EDMA_RX>, <&edma2 35 0 0>;
> +				dma-names = "rx", "tx";
> +				#sound-dai-cells = <0>;
> +				status = "disabled";
> +			};
> +
> +			lpuart7: serial at 42690000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42690000 0x1000>;
> +				interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART7>;
> +				clock-names = "ipg";
> +				dmas = <&edma2 46 0 FSL_EDMA_RX>, <&edma2 45 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart8: serial at 426a0000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x426a0000 0x1000>;
> +				interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART8>;
> +				clock-names = "ipg";
> +				dmas = <&edma4 39 0 FSL_EDMA_RX>, <&edma4 38 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c5: i2c at 426b0000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x426b0000 0x10000>;
> +				interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C5>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 37 0 0>, <&edma2 38 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c6: i2c at 426c0000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x426c0000 0x10000>;
> +				interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C6>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 30 0 0>, <&edma4 31 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c7: i2c at 426d0000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x426d0000 0x10000>;
> +				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C7>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 39 0 0>, <&edma2 40 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c8: i2c at 426e0000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x426e0000 0x10000>;
> +				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C8>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 32 0 0>, <&edma4 33 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi5: spi at 426f0000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x426f0000 0x10000>;
> +				interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI5>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 41 0 0>, <&edma2 42 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi6: spi at 42700000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x42700000 0x10000>;
> +				interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI6>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 34 0 0>, <&edma4 35 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi7: spi at 42710000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x42710000 0x10000>;
> +				interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI7>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma2 43 0 0>, <&edma2 44 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi8: spi at 42720000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x42720000 0x10000>;
> +				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI8>,
> +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma4 36 0 0>, <&edma4 37 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			mu11: mailbox at 42730000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42730000 0x10000>;
> +				interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			edma4: dma-controller at 42df0000 {
> +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> +				reg = <0x42df0000 0x210000>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "dma";
> +				#dma-cells = <3>;
> +				dma-channels = <64>;
> +				interrupts-extended = <&a55_irqsteer 128>, <&a55_irqsteer 129>,
> +					<&a55_irqsteer 130>, <&a55_irqsteer 131>,
> +					<&a55_irqsteer 132>, <&a55_irqsteer 133>,
> +					<&a55_irqsteer 134>, <&a55_irqsteer 135>,
> +					<&a55_irqsteer 136>, <&a55_irqsteer 137>,
> +					<&a55_irqsteer 138>, <&a55_irqsteer 139>,
> +					<&a55_irqsteer 140>, <&a55_irqsteer 141>,
> +					<&a55_irqsteer 142>, <&a55_irqsteer 143>,
> +					<&a55_irqsteer 144>, <&a55_irqsteer 145>,
> +					<&a55_irqsteer 146>, <&a55_irqsteer 147>,
> +					<&a55_irqsteer 148>, <&a55_irqsteer 149>,
> +					<&a55_irqsteer 150>, <&a55_irqsteer 151>,
> +					<&a55_irqsteer 152>, <&a55_irqsteer 153>,
> +					<&a55_irqsteer 154>, <&a55_irqsteer 155>,
> +					<&a55_irqsteer 156>, <&a55_irqsteer 157>,
> +					<&a55_irqsteer 158>, <&a55_irqsteer 159>,
> +					<&a55_irqsteer 192>, <&a55_irqsteer 193>,
> +					<&a55_irqsteer 194>, <&a55_irqsteer 195>,
> +					<&a55_irqsteer 196>, <&a55_irqsteer 197>,
> +					<&a55_irqsteer 198>, <&a55_irqsteer 199>,
> +					<&a55_irqsteer 200>, <&a55_irqsteer 201>,
> +					<&a55_irqsteer 202>, <&a55_irqsteer 203>,
> +					<&a55_irqsteer 204>, <&a55_irqsteer 205>,
> +					<&a55_irqsteer 206>, <&a55_irqsteer 207>,
> +					<&a55_irqsteer 208>, <&a55_irqsteer 209>,
> +					<&a55_irqsteer 210>, <&a55_irqsteer 211>,
> +					<&a55_irqsteer 212>, <&a55_irqsteer 213>,
> +					<&a55_irqsteer 214>, <&a55_irqsteer 215>,
> +					<&a55_irqsteer 216>, <&a55_irqsteer 217>,
> +					<&a55_irqsteer 218>, <&a55_irqsteer 219>,
> +					<&a55_irqsteer 220>, <&a55_irqsteer 221>,
> +					<&a55_irqsteer 222>, <&a55_irqsteer 223>,
> +					<&gic GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
> +			};
> +		};
> +
> +		aips3: bus at 42800000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0 0x42800000 0 0x800000>;
> +			ranges = <0x42800000 0x0 0x42800000 0x800000>,
> +				 <0x28000000 0x0 0x28000000 0x1000000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			usdhc1: mmc at 42850000 {
> +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> +				reg = <0x42850000 0x10000>;
> +				interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> +					 <&scmi_clk IMX94_CLK_USDHC1>;
> +				clock-names = "ipg", "ahb", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC1>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1>;
> +				assigned-clock-rates = <400000000>;
> +				bus-width = <8>;
> +				fsl,tuning-start-tap = <1>;
> +				fsl,tuning-step = <2>;
> +				status = "disabled";
> +			};
> +
> +			usdhc2: mmc at 42860000 {
> +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> +				reg = <0x42860000 0x10000>;
> +				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> +					 <&scmi_clk IMX94_CLK_USDHC2>;
> +				clock-names = "ipg", "ahb", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC2>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1>;
> +				assigned-clock-rates = <200000000>;
> +				bus-width = <4>;
> +				fsl,tuning-start-tap = <1>;
> +				fsl,tuning-step = <2>;
> +				status = "disabled";
> +			};
> +
> +			usdhc3: mmc at 42880000 {
> +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> +				reg = <0x42880000 0x10000>;
> +				interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> +					 <&scmi_clk IMX94_CLK_USDHC3>;
> +				clock-names = "ipg", "ahb", "per";
> +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC3>;
> +				assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD1>;
> +				assigned-clock-rates = <200000000>;
> +				bus-width = <4>;
> +				fsl,tuning-start-tap = <1>;
> +				fsl,tuning-step = <2>;
> +				status = "disabled";
> +			};
> +
> +			lpuart9: serial at 42a50000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42a50000 0x1000>;
> +				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART10>;
> +				clock-names = "ipg";
> +				dmas = <&edma2 51 0 FSL_EDMA_RX>, <&edma2 50 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart10: serial at 42a60000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42a60000 0x1000>;
> +				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART10>;
> +				clock-names = "ipg";
> +				dmas = <&edma4 47 0 FSL_EDMA_RX>, <&edma4 46 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart11: serial at 42a70000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42a70000 0x1000>;
> +				interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART11>;
> +				clock-names = "ipg";
> +				dmas = <&edma2 53 0 FSL_EDMA_RX>, <&edma2 52 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart12: serial at 42a80000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x42a80000 0x1000>;
> +				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART12>;
> +				clock-names = "ipg";
> +				dmas = <&edma4 49 0 FSL_EDMA_RX>, <&edma4 48 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			mu12: mailbox at 42ac0000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42ac0000 0x10000>;
> +				interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu13: mailbox at 42ae0000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42ae0000 0x10000>;
> +				interrupts = <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu14: mailbox at 42b00000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42b00000 0x10000>;
> +				interrupts = <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu15: mailbox at 42b20000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42b20000 0x10000>;
> +				interrupts = <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu16: mailbox at 42b40000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42b40000 0x10000>;
> +				interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu17: mailbox at 42b60000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x42b60000 0x10000>;
> +				interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +		};
> +
> +		gpio2: gpio at 43810000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43810000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 4 32>;
> +		};
> +
> +		gpio3: gpio at 43820000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43820000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 36 26>;
> +		};
> +
> +		gpio4: gpio at 43840000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43840000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 62 4>, <&scmi_iomuxc 4 0 4>,
> +				      <&scmi_iomuxc 8 140 12>, <&scmi_iomuxc 20 164 12>;
> +		};
> +
> +		gpio5: gpio at 43850000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43850000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 108 32>;
> +		};
> +
> +		gpio6: gpio at 43860000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43860000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 66 32>;
> +		};
> +
> +		gpio7: gpio at 43870000 {
> +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> +			reg = <0x0 0x43870000 0x0 0x1000>;
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
> +			#gpio-cells = <2>;
> +			gpio-controller;
> +			gpio-ranges = <&scmi_iomuxc 0 98 10>, <&scmi_iomuxc 16 152 12>;
> +		};
> +
> +		aips1: bus at 44000000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0x0 0x44000000 0x0 0x800000>;
> +			ranges = <0x44000000 0x0 0x44000000 0x800000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			edma1: dma-controller at 44000000 {
> +				compatible = "fsl,imx94-edma3", "fsl,imx93-edma3";
> +				reg = <0x44000000 0x210000>;
> +				interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "dma";
> +				#dma-cells = <3>;
> +				dma-channels = <32>;
> +				status = "okay";
> +			};
> +
> +			mu1: mailbox at 44220000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x44220000 0x10000>;
> +				interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			system_counter: timer at 44290000 {
> +				compatible = "nxp,imx95-sysctr-timer";
> +				reg = <0x44290000 0x30000>;
> +				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&osc_24m>;
> +				clock-names = "per";
> +				nxp,no-divider;
> +			};
> +
> +			tpm1: pwm at 44310000 {
> +				compatible = "fsl,imx7ulp-pwm";
> +				reg = <0x44310000 0x1000>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> +				#pwm-cells = <3>;
> +				status = "disabled";
> +			};
> +
> +			tpm2: pwm at 44320000 {
> +				compatible = "fsl,imx7ulp-pwm";
> +				reg = <0x44320000 0x1000>;
> +				clocks = <&scmi_clk IMX94_CLK_TPM2>;
> +				#pwm-cells = <3>;
> +				status = "disabled";
> +			};
> +
> +			i3c1: i3c at 44330000 {
> +				compatible = "silvaco,i3c-master-v1";
> +				reg = <0x44330000 0x10000>;
> +				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <3>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_I3C1SLOW>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>,
> +					 <&dummy>;
> +				clock-names = "pclk", "fast_clk", "slow_clk";
> +				status = "disabled";
> +			};
> +
> +			lpi2c1: i2c at 44340000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x44340000 0x10000>;
> +				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C1>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpi2c2: i2c at 44350000 {
> +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> +				reg = <0x44350000 0x10000>;
> +				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPI2C2>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi1: spi at 44360000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x44360000 0x10000>;
> +				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI2>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma1 16 0 0>, <&edma1 17 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpspi2: spi at 44370000 {
> +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> +				reg = <0x44370000 0x10000>;
> +				interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				clocks = <&scmi_clk IMX94_CLK_LPSPI2>,
> +					 <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "per", "ipg";
> +				dmas = <&edma1 18 0 0>, <&edma1 19 0 FSL_EDMA_RX>;
> +				dma-names = "tx", "rx";
> +				status = "disabled";
> +			};
> +
> +			lpuart1: serial at 44380000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x44380000 0x1000>;
> +				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART1>;
> +				clock-names = "ipg";
> +				dmas = <&edma1 21 0 FSL_EDMA_RX>, <&edma1 20 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			lpuart2: serial at 44390000 {
> +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> +					     "fsl,imx7ulp-lpuart";
> +				reg = <0x44390000 0x1000>;
> +				interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_LPUART2>;
> +				clock-names = "ipg";
> +				dmas = <&edma1 23 0 FSL_EDMA_RX>, <&edma1 22 0 0>;
> +				dma-names = "rx", "tx";
> +				status = "disabled";
> +			};
> +
> +			flexcan1: can at 443a0000 {
> +				compatible = "fsl,imx95-flexcan";
> +				reg = <0x443a0000 0x10000>;
> +				interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
> +				status = "disabled";
> +			};
> +
> +			sai1: sai at 443b0000 {
> +				compatible = "fsl,imx95-sai";
> +				reg = <0x443b0000 0x10000>;
> +				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>, <&dummy>,
> +					<&scmi_clk IMX94_CLK_SAI1>, <&dummy>,
> +					<&dummy>, <&dummy>;
> +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> +				dmas = <&edma1 25 0 FSL_EDMA_RX>, <&edma1 24 0 0>;
> +				dma-names = "rx", "tx";
> +				#sound-dai-cells = <0>;
> +				status = "disabled";
> +			};
> +
> +			adc1: adc at 44530000 {
> +				compatible = "nxp,imx93-adc";
> +				reg = <0x44530000 0x10000>;
> +				interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_ADC>;
> +				clock-names = "ipg";
> +				#io-channel-cells = <1>;
> +				status = "disabled";
> +			};
> +
> +			mu2: mailbox at 445b0000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x445b0000 0x1000>;
> +				ranges;
> +				interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				#mbox-cells = <2>;
> +
> +				sram0: sram at 445b1000 {
> +					compatible = "mmio-sram";
> +					reg = <0x445b1000 0x400>;
> +					ranges = <0x0 0x445b1000 0x400>;
> +					#address-cells = <1>;
> +					#size-cells = <1>;
> +
> +					scmi_buf0: scmi-sram-section at 0 {
> +						compatible = "arm,scmi-shmem";
> +						reg = <0x0 0x80>;
> +					};
> +
> +					scmi_buf1: scmi-sram-section at 80 {
> +						compatible = "arm,scmi-shmem";
> +						reg = <0x80 0x80>;
> +					};
> +				};
> +			};
> +
> +			mu3: mailbox at 445d0000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x445d0000 0x10000>;
> +				interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu4: mailbox at 445f0000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x445f0000 0x10000>;
> +				interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			mu6: mailbox at 44630000 {
> +				compatible = "fsl,imx95-mu";
> +				reg = <0x44630000 0x10000>;
> +				interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
> +				#mbox-cells = <2>;
> +				status = "disabled";
> +			};
> +
> +			a55_irqsteer: interrupt-controller at 446a0000 {
> +				compatible = "fsl,imx-irqsteer";
> +				reg = <0x446a0000 0x1000>;
> +				#interrupt-cells = <1>;
> +				interrupt-controller;
> +				interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> +				clock-names = "ipg";
> +				fsl,channel = <0>;
> +				fsl,num-irqs = <960>;
> +			};
> +		};
> +
> +		aips4: bus at 49000000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0x0 0x49000000 0x0 0x800000>;
> +			ranges = <0x49000000 0x0 0x49000000 0x800000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			wdog3: watchdog at 49220000 {
> +				compatible = "fsl,imx93-wdt";
> +				reg = <0x49220000 0x10000>;
> +				interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				timeout-sec = <40>;
> +				fsl,ext-reset-output;
> +				status = "disabled";
> +			};
> +		};
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/freescale/imx943.dtsi b/arch/arm64/boot/dts/freescale/imx943.dtsi
> new file mode 100644
> index 000000000000..a9877fcfd896
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx943.dtsi
> @@ -0,0 +1,148 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include "imx94.dtsi"
> +
> +/ {
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		idle-states {
> +			entry-method = "psci";
> +
> +			cpu_pd_wait: cpu-pd-wait {
> +				compatible = "arm,idle-state";
> +				arm,psci-suspend-param = <0x0010033>;
> +				local-timer-stop;
> +				entry-latency-us = <1000>;
> +				exit-latency-us = <700>;
> +				min-residency-us = <2700>;
> +				wakeup-latency-us = <1500>;
> +			};
> +		};
> +
> +		cpu0: cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x0>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l0>;
> +		};
> +
> +		cpu1: cpu at 100 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x100>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l1>;
> +		};
> +
> +		cpu2: cpu at 200 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x200>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l2>;
> +		};
> +
> +		cpu3: cpu at 300 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x300>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l3>;
> +		};
> +
> +		l2_cache_l0: l2-cache-l0 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l1: l2-cache-l1 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l2: l2-cache-l2 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l3: l2-cache-l3 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l3_cache: l3-cache {
> +			compatible = "cache";
> +			cache-size = <1048576>;
> +			cache-line-size = <64>;
> +			cache-sets = <1024>;
> +			cache-level = <3>;
> +			cache-unified;
> +		};
> +	};
> +};
> --
> 2.34.1
>


From ping.bai at nxp.com  Tue Mar  4 07:38:27 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue, 4 Mar 2025 15:38:27 +0000
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <CAL_JsqJd06AOJKXFiDq=rihFa7qWnLciBeHKCKwkRUfF7AJTMA@mail.gmail.com>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
 <20250304131314.GA2441686-robh@kernel.org>
 <AS8PR04MB8642D20F0F5A7E8622A7685F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>
 <CAL_JsqJd06AOJKXFiDq=rihFa7qWnLciBeHKCKwkRUfF7AJTMA@mail.gmail.com>
Message-ID: <AS8PR04MB8642EFC83C65A92B75B6A83F87C82@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
> interrupts-extended property
> 
> On Tue, Mar 4, 2025 at 8:40?AM Jacky Bai <ping.bai at nxp.com> wrote:
> >
> > Hi Rob,
> >
> > > Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
> > > interrupts-extended property
> > >
> > > On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> > > > Add interrupts-extended property for edma that has multiple
> > > > interrupt controllers used.
> > >
> > > Did you try using interrupts-extended? No. Because either is
> > > supported by the tools already.
> > >
> >
> > We need to use interrupts-extended property for i.MX94 because for the
> > edma's interrupts, some are connected to irqsteer interrupt controller
> > and some are connected to the GIC. make dtbs_check report error, so I add
> this dt binding changes.
> >
> > Sorry, Which tools are you referring?
> 
> dtschema
> 
> The schemas specify 'interrupts' only. The dts files can use either interrupts or
> interrupts-extended. If that doesn't work for you, it is a bug in dtschema.
> 

Clear for now, caused by maxItems.

Thx for your review.

BR
> Rob

From angelogioacchino.delregno at collabora.com  Tue Mar  4 07:39:14 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 4 Mar 2025 16:39:14 +0100
Subject: [PATCH 1/3] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add
 mediatek,accdet
In-Reply-To: <20250214-mt8188-accdet-v1-1-6bbd5483855b@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-1-6bbd5483855b@collabora.com>
Message-ID: <58528744-4afc-46e8-81a1-ff0704751b41@collabora.com>

Il 14/02/25 16:14, N?colas F. R. A. Prado ha scritto:
> Add a mediatek,accdet phandle property to allow getting a reference to
> the MT6359 ACCDET block, which is responsible for detecting jack
> insertion/removal.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From ping.bai at nxp.com  Tue Mar  4 07:41:32 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Tue, 4 Mar 2025 15:41:32 +0000
Subject: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
 interrupts-extended property
In-Reply-To: <Z8cboXGsy1uyJwgf@lizhi-Precision-Tower-5810>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-2-ping.bai@nxp.com>
 <Z8cboXGsy1uyJwgf@lizhi-Precision-Tower-5810>
Message-ID: <AS8PR04MB8642F46C61B544D4CC98F2F887C82@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2 1/4] dt-bindings: dma: fsl-edma: add
> interrupts-extended property
> 
> On Tue, Mar 04, 2025 at 05:31:24PM +0800, Jacky Bai wrote:
> > Add interrupts-extended property for edma that has multiple interrupt
> > controllers used.
> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - newly added entry
> > ---
> >  Documentation/devicetree/bindings/dma/fsl,edma.yaml | 11
> ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > index d54140f18d34..549afb8611a9 100644
> > --- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
> > @@ -38,6 +38,10 @@ properties:
> >      minItems: 1
> >      maxItems: 64
> >
> > +  interrupts-extended:
> > +    minItems: 1
> > +    maxItems: 65
> > +
> 
> I suggest add error irq later because optional err-irq patch under review.
> https://lore.kernel.org/imx/20250228-edma_err-v1-0-d1869fe4163e at nxp.c
> om/T/#t
> 
> Frank

Ok, need the above patch ready first, then this patch can be dropped, I think.

BR
> 
> >    interrupt-names:
> >      minItems: 1
> >      maxItems: 64
> > @@ -87,9 +91,14 @@ required:
> >    - "#dma-cells"
> >    - compatible
> >    - reg
> > -  - interrupts
> >    - dma-channels
> >
> > +oneOf:
> > +  - required:
> > +    - interrupts
> > +  - required:
> > +    - interrupts-extended
> > +
> >  allOf:
> >    - $ref: dma-controller.yaml#
> >    - if:
> > --
> > 2.34.1
> >


From kw at linux.com  Tue Mar  4 07:46:38 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 00:46:38 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
 <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
Message-ID: <20250304154638.GB2310180@rocinante>

Hello,

> This patch is now commit 1ff54f4cbaed9ec6 ("PCI: dwc: Add debugfs
> based Silicon Debug support for DWC") in pci/next (next-20250304).
> 
> On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> > [...]
> > > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > > +{
> > > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > > +   struct device *dev = pci->dev;
> > > > +   struct debugfs_info *debugfs;
> > > > +   struct dentry *dir;
> > > > +   int ret;
> > > > +
> > > > +   /* Create main directory for each platform driver */
> > > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > > +   dir = debugfs_create_dir(dirname, NULL);
> > > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > > +   if (!debugfs)
> > > > +           return -ENOMEM;
> > > > +
> > > > +   debugfs->debug_dir = dir;
> > > > +   pci->debugfs = debugfs;
> > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > +   if (ret)
> > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > >
> > > What will happen if ret != 0? still return 0?
> 
> And that is exactly what happens on Gray Hawk Single with R-Car
> V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> dwc_pcie_rasdes_debugfs_init() to return -ENODEV.

Thank you for testing and for catching this issue.  Much appreciated.

> > Given that callers of dwc_pcie_debugfs_init() check for errors,
> 
> Debugfs issues should never be propagated upstream!

Makes complete sense.  Sorry for breaking things here!

> > this probably should correctly bubble up any failure coming from
> > dwc_pcie_rasdes_debugfs_init().
> >
> > I made updates to the code directly on the current branch, have a look:
> 
> So while applying, you changed this like:
> 
>             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
>     -       if (ret)
>     -               dev_dbg(dev, "RASDES debugfs init failed\n");
>     +       if (ret) {
>     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
>     +               return ret;
>     +       }
> 
>             return 0;
> 
> Hence this is now a fatal error, causing the probe to fail.

I removed the changed, and also move the log level to be a warning, per:

  https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=c6759a967e69aba16aef0d92f43e527b112e98a5

Would this be acceptable here?

Mani, would this be acceptable to you, too?  Given that you posted the
following recently:

  https://lore.kernel.org/linux-pci/20250303200055.GA1881771 at rocinante/T/#mab9cbd5834390d259afea056eee9a73d8c3b435f

That said, perhaps moving the log level to a debug would be better served here.

	Krzysztof


From maz at kernel.org  Tue Mar  4 07:47:11 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 04 Mar 2025 15:47:11 +0000
Subject: [PATCH 03/18] KVM: arm64: Handle trapping of FEAT_LS64* instructions
In-Reply-To: <CA+EHjTwkX+sy1wuS8LvGM+=m_S-h-=xUUXOyMapnoLiHt0XpOw@mail.gmail.com>
References: <20250210184150.2145093-1-maz@kernel.org>
	<20250210184150.2145093-4-maz@kernel.org>
	<CA+EHjTwkX+sy1wuS8LvGM+=m_S-h-=xUUXOyMapnoLiHt0XpOw@mail.gmail.com>
Message-ID: <86eczcpzls.wl-maz@kernel.org>

On Tue, 04 Mar 2025 14:36:19 +0000,
Fuad Tabba <tabba at google.com> wrote:
> 
> Hi Marc,
> 
> On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
> >
> > We generally don't expect FEAT_LS64* instructions to trap, unless
> > they are trapped by a guest hypervisor.
> >
> > Otherwise, this is just the guest playing tricks on us by using
> > an instruction that isn't advertised, which we handle with a well
> > deserved UNDEF.
> >
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > ---
> >  arch/arm64/kvm/handle_exit.c | 64 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 64 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> > index 512d152233ff2..4f8354bf7dc5f 100644
> > --- a/arch/arm64/kvm/handle_exit.c
> > +++ b/arch/arm64/kvm/handle_exit.c
> > @@ -294,6 +294,69 @@ static int handle_svc(struct kvm_vcpu *vcpu)
> >         return 1;
> >  }
> >
> > +static int handle_ls64b(struct kvm_vcpu *vcpu)
> > +{
> > +       struct kvm *kvm = vcpu->kvm;
> > +       u64 esr = kvm_vcpu_get_esr(vcpu);
> > +       u64 iss = ESR_ELx_ISS(esr);
> > +       bool allowed;
> > +
> > +       switch (iss) {
> > +       case ESR_ELx_ISS_ST64BV:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
> > +               break;
> > +       case ESR_ELx_ISS_ST64BV0:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
> > +               break;
> > +       case ESR_ELx_ISS_LDST64B:
> > +               allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
> > +               break;
> > +       default:
> > +               /* Clearly, we're missing something. */
> > +               goto unknown_trap;
> > +       }
> > +
> > +       if (!allowed)
> > +               goto undef;
> > +
> > +       if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
> > +               u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
> > +               bool fwd;
> > +
> > +               switch (iss) {
> > +               case ESR_ELx_ISS_ST64BV:
> > +                       fwd = !(hcrx & HCRX_EL2_EnASR);
> > +                       break;
> > +               case ESR_ELx_ISS_ST64BV0:
> > +                       fwd = !(hcrx & HCRX_EL2_EnAS0);
> > +                       break;
> > +               case ESR_ELx_ISS_LDST64B:
> > +                       fwd = !(hcrx & HCRX_EL2_EnALS);
> > +                       break;
> > +               default:
> > +                       /* We don't expect to be here */
> > +                       fwd = false;
> > +               }
> > +
> > +               if (fwd) {
> > +                       kvm_inject_nested_sync(vcpu, esr);
> > +                       return 1;
> > +               }
> > +       }
> > +
> > +unknown_trap:
> > +       /*
> > +        * If we land here, something must be very wrong, because we
> > +        * have no idea why we trapped at all. Warn and undef as a
> > +        * fallback.
> > +        */
> > +       WARN_ON(1);
> 
> nit: should this be WARN_ONCE() instead?
> 
> > +
> > +undef:
> > +       kvm_inject_undefined(vcpu);
> > +       return 1;
> > +}
> 
> I'm wondering if this can be simplified by having one switch()
> statement that toggles both allowed and fwd (or maybe even only fwd),
> and then inject depending on that, e.g.,
> 
> +static int handle_ls64b(struct kvm_vcpu *vcpu)
> +{
> +    struct kvm *kvm = vcpu->kvm;
> +    bool is_nv = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
> +    u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
> +    u64 esr = kvm_vcpu_get_esr(vcpu);
> +    u64 iss = ESR_ELx_ISS(esr);
> +    bool fwd = false;
> +
> +    switch (iss) {
> +    case ESR_ELx_ISS_ST64BV:
> +         fwd = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V) &&
> +                   !(hcrx & HCRX_EL2_EnASR)

Ah, I know what I dislike about this approach: If your L1 guest runs
at EL2, HCRX_EL2 doesn't apply (it is only for an L2 guest). Yet we
evaluate it.

I think this still works because you shouldn't have HCRX_EL2.EnASR
clear on the host if LS64V is advertised to the guest, but it feels a
bit fragile.

I'll have another think at refactoring that code.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From david at redhat.com  Tue Mar  4 07:48:44 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue,  4 Mar 2025 16:48:44 +0100
Subject: [PATCH -next v1 1/3] kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
In-Reply-To: <20250304154846.1937958-1-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
Message-ID: <20250304154846.1937958-2-david@redhat.com>

... and remove the "MM" argument from install_breakpoint(), because it
can easily be derived from the VMA.

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8fc53813779a4..991aacc80d0e0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1134,10 +1134,10 @@ static bool filter_chain(struct uprobe *uprobe, struct mm_struct *mm)
 	return ret;
 }
 
-static int
-install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
-			struct vm_area_struct *vma, unsigned long vaddr)
+static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	bool first_uprobe;
 	int ret;
 
@@ -1162,9 +1162,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
-static int
-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
+static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
+
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
 	return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
@@ -1296,10 +1298,10 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 		if (is_register) {
 			/* consult only the "caller", new consumer. */
 			if (consumer_filter(new, mm))
-				err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+				err = install_breakpoint(uprobe, vma, info->vaddr);
 		} else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
 			if (!filter_chain(uprobe, mm))
-				err |= remove_breakpoint(uprobe, mm, info->vaddr);
+				err |= remove_breakpoint(uprobe, vma, info->vaddr);
 		}
 
  unlock:
@@ -1472,7 +1474,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
 			continue;
 
 		vaddr = offset_to_vaddr(vma, uprobe->offset);
-		err |= remove_breakpoint(uprobe, mm, vaddr);
+		err |= remove_breakpoint(uprobe, vma, vaddr);
 	}
 	mmap_read_unlock(mm);
 
@@ -1610,7 +1612,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 		if (!fatal_signal_pending(current) &&
 		    filter_chain(uprobe, vma->vm_mm)) {
 			unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
-			install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
+			install_breakpoint(uprobe, vma, vaddr);
 		}
 		put_uprobe(uprobe);
 	}
-- 
2.48.1



From david at redhat.com  Tue Mar  4 07:48:43 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue,  4 Mar 2025 16:48:43 +0100
Subject: [PATCH -next v1 0/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
Message-ID: <20250304154846.1937958-1-david@redhat.com>

Based on -next, because a related fix [1] is not in mm.git. This is
the follow-up to [2] (later than I wanted to send it out), now that
Willy also stumbled over this [3].

Since the RFC, I rewrote it once again, now using a folio_walk instead of
our old pagewalk infrastructure.


Currently, uprobe_write_opcode() implements COW-breaking manually, which is
really far from ideal. Further, there is interest in supporting uprobes on
hugetlb pages [1], and leaving at least the COW-breaking to the core will
make this much easier.

Also, I think the current code doesn't really handle some things
properly (see patch #3) when replacing/zapping pages.

Let's rewrite it, to leave COW-breaking to the fault handler, and handle
registration/unregistration by temporarily unmapping the anonymous page,
modifying it, and mapping it again. We still have to implement
zapping of anonymous pages ourselves, unfortunately.

We could look into not performing the temporary unmapping if we can
perform the write atomically, which would likely also make adding hugetlb
support a lot easier. But, limited (e.g., only PMD/PUD) hugetlb support
could be added on top of this with some tweaking.

Note that we now won't have to allocate another anonymous folio when
unregistering (which will be beneficial for hugetlb as well), we can simply
modify the already-mapped one from the registration (if any). When
registering a uprobe, we'll first trigger a ptrace-like write fault to
break COW, to then modify the already-mapped page.

Briefly sanity tested with perf:
  [root at localhost ~]# perf probe -x /usr/bin/bash -a main
  ...
  [root at localhost ~]# perf record -e probe_bash:main -aR sleep 10 &
  [1] 2196
  [root at localhost ~]# bash
  [root at localhost ~]# exit
  exit
  [root at localhost ~]# bash
  [root at localhost ~]# exit
  exit
  [root at localhost ~]# [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.287 MB perf.data (8 samples) ]
  ...
  [root at localhost ~]# perf report --stdio
  # To display the perf.data header info, please use --header/--header-only optio>
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 8  of event 'probe_bash:main'
  # Event count (approx.): 8
  #
  # Overhead  Command      Shared Object  Symbol
  # ........  ...........  .............  ........
  #
      75.00%  grepconf.sh  bash           [.] main
      25.00%  bash         bash           [.] main
  ...

Are there any uprobe tests / benchmarks that are worth running?

RFC -> v1:
* Use folio_walk and simplify the logic

Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Matthew Wilcox <willy at infradead.org>
Cc: Russell King <linux at armlinux.org.uk>
Cc: Masami Hiramatsu <mhiramat at kernel.org>
Cc: Oleg Nesterov <oleg at redhat.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Arnaldo Carvalho de Melo <acme at kernel.org>
Cc: Namhyung Kim <namhyung at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
Cc: Jiri Olsa <jolsa at kernel.org>
Cc: Ian Rogers <irogers at google.com>
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: "Liang, Kan" <kan.liang at linux.intel.com>
Cc: Tong Tiangen <tongtiangen at huawei.com>

[1] https://lkml.kernel.org/r/20250224031149.1598949-1-tongtiangen at huawei.com
[2] https://lore.kernel.org/linux-mm/20240604122548.359952-2-david at redhat.com/T/
[3] https://lore.kernel.org/all/d7971673-19ed-448a-9e54-8ffbde5059dc at redhat.com/T/
[4] https://lkml.kernel.org/r/ZiK50qob9yl5e0Xz at bender.morinfr.org

David Hildenbrand (3):
  kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
  kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and
    uprobe_write_opcode()
  kernel/events/uprobes: uprobe_write_opcode() rewrite

 arch/arm/probes/uprobes/core.c |   4 +-
 include/linux/uprobes.h        |   6 +-
 kernel/events/uprobes.c        | 363 +++++++++++++++++----------------
 3 files changed, 190 insertions(+), 183 deletions(-)


base-commit: cd3215bbcb9d4321def93fea6cfad4d5b42b9d1d
-- 
2.48.1



From kory.maincent at bootlin.com  Tue Mar  4 08:00:51 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Tue, 4 Mar 2025 17:00:51 +0100
Subject: [PATCH net] net: ethtool: Set the req_info->dev on DUMP
 requests for each dev
In-Reply-To: <20250302162137.698092-1-maxime.chevallier@bootlin.com>
References: <20250302162137.698092-1-maxime.chevallier@bootlin.com>
Message-ID: <20250304170051.607097e9@kmaincent-XPS-13-7390>

On Sun,  2 Mar 2025 17:21:36 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> There are a few netlink commands that rely on the req_info->dev field
> being populated by ethnl in their ->prepare_data() and ->fill_reply().
> 
> For a regular GET request, this will be set by ethnl_default_parse(),
> which calls ethnl_parse_header_dev_get().
> 
> In the case of a DUMP request, the ->prepare_data() and ->fill_reply()
> callbacks will be called with the req_info->dev being NULL, which can
> cause discrepancies in the behaviour between GET and DUMP results.
> 
> The main impact is that ethnl_req_get_phydev() will not find any
> phy_device, impacting :
>  - plca
>  - pse-pd
>  - stats
> 
> Some other commands rely on req_info->dev, namely :
>  - coalesce in ->fill_reply to look for an irq_moder
> 
> Although cable_test and tunnels also rely on req_info->dev being set,
> that's not a problem for these commands as :
>  - cable_test doesn't support DUMP
>  - tunnels rolls its own ->dumpit (and sets dev in the req_info).
>  - phy also has its own ->dumpit
> 
> All other commands use reply_data->dev (probably the correct way of
> doing things) and aren't facing this issue.
> 
> Simply set the dev in the req_info context when iterating to dump each
> dev.
> 
> Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some
> commands") Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---
> 
> Fixes tag targets the phy-index commit, as it introduced a change in
> behaviour for PLCA. From what I can tell, coalesce never correctly
> detected irq_moder in DUMP requests.
> 
> We could also consider fixing all individual commands that use
> req_info->dev, however I'm not actually sure it's incorrect to do so,
> feel free to correct me though.
> 
> Maxime
> 
>  net/ethtool/netlink.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index b4c45207fa32..de967961d8fe 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -582,6 +582,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
>  		dev_hold(dev);
>  		rcu_read_unlock();
>  
> +		ctx->req_info->dev = dev;

I would rather put it in ethnl_default_dump_one() before
ethnl_init_reply_data() call.

With this change:
Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
Tested-by: Kory Maincent <kory.maincent at bootlin.com>

Thank you!

>  		ret = ethnl_default_dump_one(skb, dev, ctx,
> genl_info_dump(cb)); 
>  		rcu_read_lock();



-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From ryan.roberts at arm.com  Tue Mar  4 08:02:20 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue, 4 Mar 2025 16:02:20 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250304142634.GC5011@ziepe.ca>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com> <20250303165255.GS5011@ziepe.ca>
 <20250303190330.GA426248@e133081.arm.com> <20250304142634.GC5011@ziepe.ca>
Message-ID: <67fbe3f4-4fb6-4753-b34c-320b7897fd16@arm.com>

On 04/03/2025 14:26, Jason Gunthorpe wrote:
> On Mon, Mar 03, 2025 at 07:03:42PM +0000, Miko?aj Lenczewski wrote:
> 
>> For example, if we use BBML2 for kernel mappings, does that require us
>> to repaint all kernel mappings when disabling BBML2 on smmu attach? I
>> am not sure, but definitely something to be worked out.
> 
> No, it would be a per-mm_struct basis only if we did something like
> that
> 
> When the SMMU driver puts a SVA on top of the mm_struct it would
> disable BBML2 usage only for that mm_struct and it's contained VMAs.

I guess we would need to figure out some synchonization mechanism if disabling
BBML2 dynaically per-mm. If there was already a BBML2 operation in flight would
want to wait for it to end. But that's a problem to solve if/when it's shown to
be needed, I think.

> 
> Kernel mappings are never made into a SVA so are not effected.
> Userspace only.
> 
> Jason



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:19 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:19 +0100
Subject: [PATCH v3 0/6] TQMa93xx on MBa93xxLA/CA LVDS support
Message-ID: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>

Hi,

this is v3 for the LVDS support on TQMa93xx module series.

It consists of three parts:
1. New PLL configuration for 477.4 MHz
2. LVDS support for imx93
3. LVDS platform support for tqma9352-mba93xxla & tqma9352-mba93xxca

Patch 1 adds a video PLL configuration for 477.4MHz
Patch 2 is the imx93 equivalent of commit 1cb0c87d27dc ("dt-bindings:
  soc: imx8mp-media-blk-ctrl: Add LDB subnode into schema and example")
Patch 3 is the imx93 equivalent of commit 9cb6d1b39a8f ("soc: imx:
  imx8m-blk-ctrl: Scan subnodes and bind drivers to them")
Patch 4 is the imx93 equivalent of commit 94e6197dadc9 ("arm64: dts:
  imx8mp: Add LCDIF2 & LDB nodes")
Patch 5 adds LVDS DT overlay for tqma9352-mba93xxla platform
Patch 6 adds LVDS DT overlay for tqma9352-mba93xxca platform

Changes in v3:
* Collected Peng's R-b
* Fixed subject prefix in patch 3/6
* Fix 'ranges' property both in bindings example and .dtsi

Changes in v2:
* Rebased to next-20250221
* Reordered patches
* Added 'ranges' to bindings
* Use subnode constraint styles as suggested by Rob Herring
* Use IMX93_CLK_SYS_PLL_PFD0 as parent for IMX93_CLK_MEDIA_AXI
* Use 333MHz for IMX93_CLK_MEDIA_AXI
* Do not set board compatible in orverlays
* Add MBa93xxCA platform as well

I skipped the support for dynamic PLL configuration for now. This is a
separate task, see [2].

Best regards,
Alexander

v2:
* https://lore.kernel.org/all/20250224142831.485159-1-alexander.stein at ew.tq-group.com/
v1:
* https://lore.kernel.org/all/20231020130019.665853-1-alexander.stein at ew.tq-group.com/

Alexander Stein (6):
  clk: imx: clk-fracn-gppll: Add 477.4MHz config for video pll
  dt-bindings: soc: imx93-media-blk-ctrl: Add LDB subnode into schema
    and example
  pmdomain: imx93-blk-ctrl: Scan subnodes and bind drivers to them
  arm64: dts: imx93: Add LCDIF & LDB nodes
  arm64: dts: tqma9352-mba93xxla: Add LVDS overlay
  arm64: dts: tqma9352-mba93xxca: Add LVDS overlay

 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 ++++++++++++
 arch/arm64/boot/dts/freescale/Makefile        |  5 ++
 ...3-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso | 40 ++++++++++
 .../freescale/imx93-tqma9352-mba93xxca.dts    | 27 +++++++
 ...3-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso | 40 ++++++++++
 .../freescale/imx93-tqma9352-mba93xxla.dts    | 27 +++++++
 arch/arm64/boot/dts/freescale/imx93.dtsi      | 77 +++++++++++++++++++
 drivers/clk/imx/clk-fracn-gppll.c             |  1 +
 drivers/pmdomain/imx/imx93-blk-ctrl.c         |  7 ++
 9 files changed, 275 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso

-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:20 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:20 +0100
Subject: [PATCH v3 1/6] clk: imx: clk-fracn-gppll: Add 477.4MHz config for video pll
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-2-alexander.stein@ew.tq-group.com>

Add the 477.4MHz frequency support that will be used by video subsystem
on imx93.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 drivers/clk/imx/clk-fracn-gppll.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
index 85771afd4698a..f0c34a02acac3 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -85,6 +85,7 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
 	PLL_FRACN_GP(519750000U, 173, 25, 100, 1, 8),
 	PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8),
 	PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
+	PLL_FRACN_GP(477400000U, 119, 35, 100, 0, 6),
 	PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
 	PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12),
 	PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10),
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:21 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:21 +0100
Subject: [PATCH v3 2/6] dt-bindings: soc: imx93-media-blk-ctrl: Add LDB subnode into schema and example
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>

Document the LDB bridge subnode and add the subnode into the example.
For the subnode to work, the block control must scan its subnodes and
bind drivers to them, do not misuse either simple-bus or simple-mfd
here.

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 +++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
index b3554e7f9e76d..cd785111928bf 100644
--- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
+++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
@@ -24,6 +24,14 @@ properties:
   reg:
     maxItems: 1
 
+  ranges: true
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 1
+
   '#power-domain-cells':
     const: 1
 
@@ -46,9 +54,20 @@ properties:
       - const: csi
       - const: dsi
 
+  bridge at 20:
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        contains:
+          const: fsl,imx93-ldb
+
 required:
   - compatible
   - reg
+  - ranges
+  - '#address-cells'
+  - '#size-cells'
   - power-domains
   - clocks
   - clock-names
@@ -77,4 +96,36 @@ examples:
                clock-names = "apb", "axi", "nic", "disp", "cam",
                              "pxp", "lcdif", "isi", "csi", "dsi";
       #power-domain-cells = <1>;
+      #address-cells = <1>;
+      #size-cells = <1>;
+      ranges = <0x0 0x4ac10000 0x10000>;
+
+      bridge at 20 {
+          compatible = "fsl,imx93-ldb";
+          reg = <0x20 0x4>, <0x24 0x4>;
+          reg-names = "ldb", "lvds";
+          clocks = <&clk IMX93_CLK_LVDS_GATE>;
+          clock-names = "ldb";
+
+          ports {
+              #address-cells = <1>;
+              #size-cells = <0>;
+
+              port at 0 {
+                  reg = <0>;
+
+                  ldb_from_lcdif2: endpoint {
+                      remote-endpoint = <&lcdif2_to_ldb>;
+                  };
+              };
+
+              port at 1 {
+                  reg = <1>;
+
+                  ldb_lvds: endpoint {
+                      remote-endpoint = <&ldb_to_panel>;
+                  };
+              };
+          };
+        };
     };
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:22 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:22 +0100
Subject: [PATCH v3 3/6] pmdomain: imx93-blk-ctrl: Scan subnodes and bind drivers to them
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>

This particular block can have DT subnodes describing the LVDS LDB
bridge. Instead of misusing simple-bus to scan for those nodes, do
the scan within the driver.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 drivers/pmdomain/imx/imx93-blk-ctrl.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/pmdomain/imx/imx93-blk-ctrl.c b/drivers/pmdomain/imx/imx93-blk-ctrl.c
index 0e2ba8ec55d75..fe2ff7a457502 100644
--- a/drivers/pmdomain/imx/imx93-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx93-blk-ctrl.c
@@ -7,6 +7,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -297,8 +298,14 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, bc);
 
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		goto cleanup_provider;
+
 	return 0;
 
+cleanup_provider:
+	of_genpd_del_provider(dev->of_node);
 cleanup_pds:
 	for (i--; i >= 0; i--)
 		pm_genpd_remove(&bc->domains[i].genpd);
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:23 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:23 +0100
Subject: [PATCH v3 4/6] arm64: dts: imx93: Add LCDIF & LDB nodes
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-5-alexander.stein@ew.tq-group.com>

LCDIF port 1 is directly attached to the LVDS Display Bridge (LDB).
Both need the same clock source (VIDEO_PLL1).

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 arch/arm64/boot/dts/freescale/imx93.dtsi | 77 ++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index 56766fdb0b1e5..69a639a8c833f 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -1273,6 +1273,9 @@ s4muap: mailbox at 47520000 {
 		media_blk_ctrl: system-controller at 4ac10000 {
 			compatible = "fsl,imx93-media-blk-ctrl", "syscon";
 			reg = <0x4ac10000 0x10000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x4ac10000 0x10000>;
 			power-domains = <&mediamix>;
 			clocks = <&clk IMX93_CLK_MEDIA_APB>,
 				 <&clk IMX93_CLK_MEDIA_AXI>,
@@ -1286,8 +1289,82 @@ media_blk_ctrl: system-controller at 4ac10000 {
 				 <&clk IMX93_CLK_MIPI_DSI_GATE>;
 			clock-names = "apb", "axi", "nic", "disp", "cam",
 				      "pxp", "lcdif", "isi", "csi", "dsi";
+			assigned-clocks = <&clk IMX93_CLK_MEDIA_AXI>,
+					  <&clk IMX93_CLK_MEDIA_APB>,
+					  <&clk IMX93_CLK_VIDEO_PLL>,
+					  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
+			assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD0>,
+						 <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>,
+						 <&clk IMX93_CLK_24M>,
+						 <&clk IMX93_CLK_VIDEO_PLL>;
+			assigned-clock-rates = <333333333>, <133333333>, <0>, <200000000>;
 			#power-domain-cells = <1>;
 			status = "disabled";
+
+			lvds_bridge: bridge at 20 {
+				compatible = "fsl,imx93-ldb";
+				reg = <0x20 0x4>, <0x24 0x4>;
+				reg-names = "ldb", "lvds";
+				clocks = <&clk IMX93_CLK_LVDS_GATE>;
+				clock-names = "ldb";
+				assigned-clocks = <&clk IMX93_CLK_MEDIA_LDB>;
+				assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						ldb_from_lcdif: endpoint {
+							remote-endpoint = <&lcdif_to_ldb>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						ldb_lvds: endpoint {
+						};
+					};
+				};
+			};
+		};
+
+		lcdif: display-controller at 4ae30000 {
+			compatible = "fsl,imx93-lcdif";
+			reg = <0x4ae30000 0x23c>;
+			interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk IMX93_CLK_MEDIA_DISP_PIX>,
+				 <&clk IMX93_CLK_LCDIF_GATE>,
+				 <&clk IMX93_CLK_MEDIA_AXI>;
+			clock-names = "pix", "axi", "disp_axi";
+			assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
+					  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
+			assigned-clock-parents = <&clk IMX93_CLK_24M>,
+						 <&clk IMX93_CLK_VIDEO_PLL>;
+			power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_LCDIF>;
+			status = "disabled";
+
+			port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				lcdif_to_dsi: endpoint at 0 {
+					reg = <0>;
+				};
+
+				lcdif_to_ldb: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&ldb_from_lcdif>;
+				};
+
+				lcdif_to_dpi: endpoint at 2 {
+					reg = <2>;
+				};
+			};
 		};
 
 		usbotg1: usb at 4c100000 {
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:24 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:24 +0100
Subject: [PATCH v3 5/6] arm64: dts: tqma9352-mba93xxla: Add LVDS overlay
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-6-alexander.stein@ew.tq-group.com>

This adds the overlay for the Tianma TM070JVHG33 LVDS display.

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 arch/arm64/boot/dts/freescale/Makefile        |  3 ++
 ...3-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso | 40 +++++++++++++++++++
 .../freescale/imx93-tqma9352-mba93xxla.dts    | 27 +++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index be6ef4c56fbf4..ac4f14c69cdd8 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -300,6 +300,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
 
+imx93-tqma9352-mba93xxla-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxla.dtb imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtb
+
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
 
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-dl.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso
new file mode 100644
index 0000000000000..c723a19f03d63
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2023 TQ-Systems GmbH <linux at ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+
+#include <dt-bindings/clock/imx93-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/dts-v1/;
+/plugin/;
+
+&backlight_lvds {
+	status = "okay";
+};
+
+&display {
+	compatible = "tianma,tm070jvhg33";
+	status = "okay";
+};
+
+&lcdif {
+	assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
+			  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
+	assigned-clock-rates = <477400000>;
+	status = "okay";
+};
+
+&lvds_bridge {
+	status = "okay";
+};
+
+&media_blk_ctrl {
+	status = "okay";
+};
+
+&tpm5 {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
index 9e88c42c3d170..4618f836345fc 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
@@ -48,6 +48,23 @@ clk_dp: clk-dp {
 		clock-frequency = <26000000>;
 	};
 
+	display: display {
+		/*
+		 * Display is not fixed, so compatible has to be added from
+		 * DT overlay
+		 */
+		power-supply = <&reg_3v3>;
+		enable-gpios = <&expander2 1 GPIO_ACTIVE_HIGH>;
+		backlight = <&backlight_lvds>;
+		status = "disabled";
+
+		port {
+			panel_in_lvds0: endpoint {
+				remote-endpoint = <&ldb_lvds>;
+			};
+		};
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		autorepeat;
@@ -509,6 +526,16 @@ &lpuart8 {
 	status = "okay";
 };
 
+&lvds_bridge {
+	ports {
+		port at 1 {
+			ldb_lvds: endpoint {
+				remote-endpoint = <&panel_in_lvds0>;
+			};
+		};
+	};
+};
+
 &pcf85063 {
 	/* RTC_EVENT# from SoM is connected on mainboard */
 	pinctrl-names = "default";
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Tue Mar  4 07:49:25 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue,  4 Mar 2025 16:49:25 +0100
Subject: [PATCH v3 6/6] arm64: dts: tqma9352-mba93xxca: Add LVDS overlay
In-Reply-To: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250304154929.1785200-7-alexander.stein@ew.tq-group.com>

This adds the overlay for the Tianma TM070JVHG33 LVDS display.

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 arch/arm64/boot/dts/freescale/Makefile        |  2 +
 ...3-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso | 40 +++++++++++++++++++
 .../freescale/imx93-tqma9352-mba93xxca.dts    | 27 +++++++++++++
 3 files changed, 69 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index ac4f14c69cdd8..48991e9a9c076 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -300,7 +300,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
 
+imx93-tqma9352-mba93xxca-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxca.dtb imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtbo
 imx93-tqma9352-mba93xxla-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxla.dtb imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtb
 
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
new file mode 100644
index 0000000000000..d21e5ccca2e93
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2025 TQ-Systems GmbH <linux at ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+
+#include <dt-bindings/clock/imx93-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/dts-v1/;
+/plugin/;
+
+&backlight_lvds {
+	status = "okay";
+};
+
+&display {
+	compatible = "tianma,tm070jvhg33";
+	status = "okay";
+};
+
+&lcdif {
+	assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
+			  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
+	assigned-clock-rates = <477400000>;
+	status = "okay";
+};
+
+&lvds_bridge {
+	status = "okay";
+};
+
+&media_blk_ctrl {
+	status = "okay";
+};
+
+&tpm5 {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
index ebbac5f8d2b2d..e70c3995e89da 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
@@ -42,6 +42,23 @@ backlight_lvds: backlight {
 		status = "disabled";
 	};
 
+	display: display {
+		/*
+		 * Display is not fixed, so compatible has to be added from
+		 * DT overlay
+		 */
+		power-supply = <&reg_3v3>;
+		enable-gpios = <&expander2 1 GPIO_ACTIVE_HIGH>;
+		backlight = <&backlight_lvds>;
+		status = "disabled";
+
+		port {
+			panel_in_lvds0: endpoint {
+				remote-endpoint = <&ldb_lvds>;
+			};
+		};
+	};
+
 	fan0: pwm-fan {
 		compatible = "pwm-fan";
 		pinctrl-names = "default";
@@ -546,6 +563,16 @@ &lpuart8 {
 	status = "okay";
 };
 
+&lvds_bridge {
+	ports {
+		port at 1 {
+			ldb_lvds: endpoint {
+				remote-endpoint = <&panel_in_lvds0>;
+			};
+		};
+	};
+};
+
 &pcf85063 {
 	/* RTC_EVENT# from SoM is connected on mainboard */
 	pinctrl-names = "default";
-- 
2.43.0



From csokas.bence at prolan.hu  Tue Mar  4 07:51:50 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Tue, 4 Mar 2025 16:51:50 +0100
Subject: [PATCH v7 0/2] microchip-tcb-capture: Add Capture, Compare, Overflow etc. events
Message-ID: <20250304155156.374150-1-csokas.bence@prolan.hu>

The TCB has three R/W-able "general purpose" hardware registers:
RA, RB and RC. The hardware is capable of:
* sampling Counter Value Register (CV) to RA/RB on a trigger edge
* sending an interrupt of this change
* sending an interrupt on CV change due to trigger
* triggering an interrupt on CV compare to RC
* stop counting after sampling to RB

To enable using these features in user-space, an interrupt handler
was added, generating the necessary counter events. On top, RA/RB
registers are added as Count Extensions. To aid interoperation, a
uapi header was also added, containing the various numeral IDs of
the Extensions, Event channels etc.

Bence Cs?k?s (2):
  counter: microchip-tcb-capture: Add IRQ handling
  counter: microchip-tcb-capture: Add capture extensions for registers
    RA/RB

 MAINTAINERS                                   |   1 +
 drivers/counter/microchip-tcb-capture.c       | 133 ++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     |  40 ++++++
 3 files changed, 174 insertions(+)
 create mode 100644 include/uapi/linux/counter/microchip-tcb-capture.h

-- 
2.48.1




From csokas.bence at prolan.hu  Tue Mar  4 07:51:51 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Tue, 4 Mar 2025 16:51:51 +0100
Subject: [PATCH v7 1/2] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <20250304155156.374150-1-csokas.bence@prolan.hu>
References: <20250304155156.374150-1-csokas.bence@prolan.hu>
Message-ID: <20250304155156.374150-2-csokas.bence@prolan.hu>

Add interrupt servicing to allow userspace to wait for the following:
* Change-of-state caused by external trigger
* Capture of timer value into RA/RB
* Compare to RC register
* Overflow

Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    New in v2
    Changes in v3:
    * Add IRQs for Capture events (from next patch)
    * Add IRQ for RC Compare
    * Add events as bullet points to commit msg
    Changes in v4:
    * Add uapi header, names for the event channels
    * Add check for -EPROBE_DEFER from `of_irq_get()`
    Changes in v5:
    * Split out UAPI header introduction
    Changes in v7:
    * Revert split-out
    * Drop `enum counter_mchp_signals` from UAPI
    * Change enums to #define's in UAPI header

 MAINTAINERS                                   |  1 +
 drivers/counter/microchip-tcb-capture.c       | 75 +++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     | 34 +++++++++
 3 files changed, 110 insertions(+)
 create mode 100644 include/uapi/linux/counter/microchip-tcb-capture.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e047e20fbd8..d1d264210690 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15579,6 +15579,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-iio at vger.kernel.org
 S:	Maintained
 F:	drivers/counter/microchip-tcb-capture.c
+F:	include/uapi/linux/counter/microchip-tcb-capture.h
 
 MICROCHIP USB251XB DRIVER
 M:	Richard Leitner <richard.leitner at skidata.com>
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 2f096a5b973d..cc12c2e2113a 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -6,18 +6,24 @@
  */
 #include <linux/clk.h>
 #include <linux/counter.h>
+#include <linux/interrupt.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <uapi/linux/counter/microchip-tcb-capture.h>
 #include <soc/at91/atmel_tcb.h>
 
 #define ATMEL_TC_CMR_MASK	(ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
 				 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
 				 ATMEL_TC_LDBSTOP)
 
+#define ATMEL_TC_DEF_IRQS	(ATMEL_TC_ETRGS | ATMEL_TC_COVFS | \
+				 ATMEL_TC_LDRAS | ATMEL_TC_LDRBS | ATMEL_TC_CPCS)
+
 #define ATMEL_TC_QDEN			BIT(8)
 #define ATMEL_TC_POSEN			BIT(9)
 
@@ -27,6 +33,7 @@ struct mchp_tc_data {
 	int qdec_mode;
 	int num_channels;
 	int channel[2];
+	int irq;
 };
 
 static const enum counter_function mchp_tc_count_functions[] = {
@@ -294,6 +301,65 @@ static const struct of_device_id atmel_tc_of_match[] = {
 	{ /* sentinel */ }
 };
 
+static irqreturn_t mchp_tc_isr(int irq, void *dev_id)
+{
+	struct counter_device *const counter = dev_id;
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	u32 sr, mask;
+
+	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
+	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], IMR), &mask);
+
+	sr &= mask;
+	if (!(sr & ATMEL_TC_ALL_IRQ))
+		return IRQ_NONE;
+
+	if (sr & ATMEL_TC_ETRGS)
+		counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE,
+				   COUNTER_MCHP_EVCHN_CV);
+	if (sr & ATMEL_TC_LDRAS)
+		counter_push_event(counter, COUNTER_EVENT_CAPTURE,
+				   COUNTER_MCHP_EVCHN_RA);
+	if (sr & ATMEL_TC_LDRBS)
+		counter_push_event(counter, COUNTER_EVENT_CAPTURE,
+				   COUNTER_MCHP_EVCHN_RB);
+	if (sr & ATMEL_TC_CPCS)
+		counter_push_event(counter, COUNTER_EVENT_THRESHOLD,
+				   COUNTER_MCHP_EVCHN_RC);
+	if (sr & ATMEL_TC_COVFS)
+		counter_push_event(counter, COUNTER_EVENT_OVERFLOW,
+				   COUNTER_MCHP_EVCHN_CV);
+
+	return IRQ_HANDLED;
+}
+
+static void mchp_tc_irq_remove(void *ptr)
+{
+	struct mchp_tc_data *priv = ptr;
+
+	regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IDR), ATMEL_TC_DEF_IRQS);
+}
+
+static int mchp_tc_irq_enable(struct counter_device *const counter)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	int ret = devm_request_irq(counter->parent, priv->irq, mchp_tc_isr, 0,
+				   dev_name(counter->parent), counter);
+
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IER), ATMEL_TC_DEF_IRQS);
+	if (ret < 0)
+		return ret;
+
+	ret = devm_add_action_or_reset(counter->parent, mchp_tc_irq_remove, priv);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static void mchp_tc_clk_remove(void *ptr)
 {
 	clk_disable_unprepare((struct clk *)ptr);
@@ -378,6 +444,15 @@ static int mchp_tc_probe(struct platform_device *pdev)
 	counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals);
 	counter->signals = mchp_tc_count_signals;
 
+	priv->irq = of_irq_get(np->parent, 0);
+	if (priv->irq == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (priv->irq > 0) {
+		ret = mchp_tc_irq_enable(counter);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret, "Failed to set up IRQ");
+	}
+
 	ret = devm_counter_add(&pdev->dev, counter);
 	if (ret < 0)
 		return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n");
diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
new file mode 100644
index 000000000000..f3ef315fe9f6
--- /dev/null
+++ b/include/uapi/linux/counter/microchip-tcb-capture.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Channel numbers used by the microchip-tcb-capture driver
+ * Copyright (C) 2025 Bence Cs?k?s
+ */
+#ifndef _UAPI_COUNTER_MCHP_TCB_H_
+#define _UAPI_COUNTER_MCHP_TCB_H_
+
+/*
+ * The driver defines the following components:
+ *
+ * Count 0
+ * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
+ * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
+ *
+ * It also supports the following events:
+ *
+ * Channel 0:
+ * - CV register changed
+ * - CV overflowed
+ * - RA captured
+ * Channel 1:
+ * - RB captured
+ * Channel 2:
+ * - RC compare triggered
+ */
+
+/* Event channels */
+#define COUNTER_MCHP_EVCHN_CV 0
+#define COUNTER_MCHP_EVCHN_RA 0
+#define COUNTER_MCHP_EVCHN_RB 1
+#define COUNTER_MCHP_EVCHN_RC 2
+
+#endif /* _UAPI_COUNTER_MCHP_TCB_H_ */
-- 
2.48.1




From csokas.bence at prolan.hu  Tue Mar  4 07:51:52 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Tue, 4 Mar 2025 16:51:52 +0100
Subject: [PATCH v7 2/2] counter: microchip-tcb-capture: Add capture extensions for registers RA/RB
In-Reply-To: <20250304155156.374150-1-csokas.bence@prolan.hu>
References: <20250304155156.374150-1-csokas.bence@prolan.hu>
Message-ID: <20250304155156.374150-3-csokas.bence@prolan.hu>

TCB hardware is capable of capturing the timer value to registers RA and
RB. Add these registers as capture extensions.

Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    Changes in v2:
    * Add IRQs
    Changes in v3:
    * Move IRQs to previous patch
    Changes in v4:
    * Return the status of the regmap_*() operations
    * Add names for the extension numbers
    Changes in v6:
    * Remove RC, as it is not a capture register
    Changes in v7:
    * Change enums to #define's in UAPI header
    * Return early on error in `mchp_tc_count_cap_read()`

 drivers/counter/microchip-tcb-capture.c       | 58 +++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     |  6 ++
 2 files changed, 64 insertions(+)

diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index cc12c2e2113a..52493f7e8b57 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -254,6 +254,62 @@ static int mchp_tc_count_read(struct counter_device *counter,
 	return 0;
 }
 
+static int mchp_tc_count_cap_read(struct counter_device *counter,
+				  struct counter_count *count, size_t idx, u64 *val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	u32 cnt;
+	int ret;
+
+	switch (idx) {
+	case COUNTER_MCHP_EXCAP_RA:
+		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), &cnt);
+		break;
+	case COUNTER_MCHP_EXCAP_RB:
+		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), &cnt);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	*val = cnt;
+
+	return 0;
+}
+
+static int mchp_tc_count_cap_write(struct counter_device *counter,
+				   struct counter_count *count, size_t idx, u64 val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	int ret;
+
+	if (val > U32_MAX)
+		return -ERANGE;
+
+	switch (idx) {
+	case COUNTER_MCHP_EXCAP_RA:
+		ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), val);
+		break;
+	case COUNTER_MCHP_EXCAP_RB:
+		ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static DEFINE_COUNTER_ARRAY_CAPTURE(mchp_tc_cnt_cap_array, 2);
+
+static struct counter_comp mchp_tc_count_ext[] = {
+	COUNTER_COMP_ARRAY_CAPTURE(mchp_tc_count_cap_read, mchp_tc_count_cap_write,
+				   mchp_tc_cnt_cap_array),
+};
+
 static struct counter_count mchp_tc_counts[] = {
 	{
 		.id = 0,
@@ -262,6 +318,8 @@ static struct counter_count mchp_tc_counts[] = {
 		.num_functions = ARRAY_SIZE(mchp_tc_count_functions),
 		.synapses = mchp_tc_count_synapses,
 		.num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
+		.ext = mchp_tc_count_ext,
+		.num_ext = ARRAY_SIZE(mchp_tc_count_ext),
 	},
 };
 
diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
index f3ef315fe9f6..136e2faa7730 100644
--- a/include/uapi/linux/counter/microchip-tcb-capture.h
+++ b/include/uapi/linux/counter/microchip-tcb-capture.h
@@ -12,6 +12,8 @@
  * Count 0
  * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
  * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
+ * \__  Extension capture0    (RA register)
+ * \__  Extension capture1    (RB register)
  *
  * It also supports the following events:
  *
@@ -25,6 +27,10 @@
  * - RC compare triggered
  */
 
+/* Capture extensions */
+#define COUNTER_MCHP_EXCAP_RA 0
+#define COUNTER_MCHP_EXCAP_RB 1
+
 /* Event channels */
 #define COUNTER_MCHP_EVCHN_CV 0
 #define COUNTER_MCHP_EVCHN_RA 0
-- 
2.48.1




From devnull+chester.a.unal.arinc9.com at kernel.org  Tue Mar  4 07:55:36 2025
From: devnull+chester.a.unal.arinc9.com at kernel.org (Chester A. Unal via B4 Relay)
Date: Tue, 04 Mar 2025 15:55:36 +0000
Subject: [PATCH] ARM: dts: BCM5301X: Fix switch port labels of ASUS
 RT-AC3200
Message-ID: <20250304-for-broadcom-fix-rt-ac3200-switch-ports-v1-1-7e249a19a13e@arinc9.com>

From: "Chester A. Unal" <chester.a.unal at arinc9.com>

After using the device for a while, Tom reports that he initially described
the switch port labels incorrectly. Apparently, ASUS's own firmware also
describes them incorrectly. Correct them to what is seen on the chassis.

Reported-by: Tom Brautaset <tbrautaset at gmail.com>
Fixes: b116239094d8 ("ARM: dts: BCM5301X: Add DT for ASUS RT-AC3200")
Signed-off-by: Chester A. Unal <chester.a.unal at arinc9.com>
---
 arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts
index 53cb0c58f6d0574f4f13c6aeb1d1bc5961d80379..3da2daee0c849d536df94c868849af7610cc1ded 100644
--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts
@@ -124,19 +124,19 @@ port at 0 {
 		};
 
 		port at 1 {
-			label = "lan1";
+			label = "lan4";
 		};
 
 		port at 2 {
-			label = "lan2";
+			label = "lan3";
 		};
 
 		port at 3 {
-			label = "lan3";
+			label = "lan2";
 		};
 
 		port at 4 {
-			label = "lan4";
+			label = "lan1";
 		};
 	};
 };

---
base-commit: 768953614c1c13fdf771be5742f1be573eea8fa4
change-id: 20250304-for-broadcom-fix-rt-ac3200-switch-ports-def10a03bb89

Best regards,
-- 
Chester A. Unal <chester.a.unal at arinc9.com>




From Frank.li at nxp.com  Tue Mar  4 08:06:33 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:06:33 -0500
Subject: [PATCH v3 2/6] dt-bindings: soc: imx93-media-blk-ctrl: Add LDB
 subnode into schema and example
In-Reply-To: <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
Message-ID: <Z8clCaPHIVFl1WX1@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 04:49:21PM +0100, Alexander Stein wrote:
> Document the LDB bridge subnode and add the subnode into the example.
> For the subnode to work, the block control must scan its subnodes and
> bind drivers to them, do not misuse either simple-bus or simple-mfd
> here.
>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
Reviewed-by: Frank Li <Frank.Li at nxp.com>

>  .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 +++++++++++++++++++
>  1 file changed, 51 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> index b3554e7f9e76d..cd785111928bf 100644
> --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> @@ -24,6 +24,14 @@ properties:
>    reg:
>      maxItems: 1
>
> +  ranges: true
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 1
> +
>    '#power-domain-cells':
>      const: 1
>
> @@ -46,9 +54,20 @@ properties:
>        - const: csi
>        - const: dsi
>
> +  bridge at 20:
> +    type: object
> +    additionalProperties: true
> +    properties:
> +      compatible:
> +        contains:
> +          const: fsl,imx93-ldb
> +
>  required:
>    - compatible
>    - reg
> +  - ranges
> +  - '#address-cells'
> +  - '#size-cells'
>    - power-domains
>    - clocks
>    - clock-names
> @@ -77,4 +96,36 @@ examples:
>                 clock-names = "apb", "axi", "nic", "disp", "cam",
>                               "pxp", "lcdif", "isi", "csi", "dsi";
>        #power-domain-cells = <1>;
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      ranges = <0x0 0x4ac10000 0x10000>;
> +
> +      bridge at 20 {
> +          compatible = "fsl,imx93-ldb";
> +          reg = <0x20 0x4>, <0x24 0x4>;
> +          reg-names = "ldb", "lvds";
> +          clocks = <&clk IMX93_CLK_LVDS_GATE>;
> +          clock-names = "ldb";
> +
> +          ports {
> +              #address-cells = <1>;
> +              #size-cells = <0>;
> +
> +              port at 0 {
> +                  reg = <0>;
> +
> +                  ldb_from_lcdif2: endpoint {
> +                      remote-endpoint = <&lcdif2_to_ldb>;
> +                  };
> +              };
> +
> +              port at 1 {
> +                  reg = <1>;
> +
> +                  ldb_lvds: endpoint {
> +                      remote-endpoint = <&ldb_to_panel>;
> +                  };
> +              };
> +          };
> +        };
>      };
> --
> 2.43.0
>


From Frank.li at nxp.com  Tue Mar  4 08:07:21 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:07:21 -0500
Subject: [PATCH v3 3/6] pmdomain: imx93-blk-ctrl: Scan subnodes and bind
 drivers to them
In-Reply-To: <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>
Message-ID: <Z8clOYhu/ja9/RqK@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 04:49:22PM +0100, Alexander Stein wrote:
> This particular block can have DT subnodes describing the LVDS LDB
> bridge. Instead of misusing simple-bus to scan for those nodes, do
> the scan within the driver.
>
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/pmdomain/imx/imx93-blk-ctrl.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/pmdomain/imx/imx93-blk-ctrl.c b/drivers/pmdomain/imx/imx93-blk-ctrl.c
> index 0e2ba8ec55d75..fe2ff7a457502 100644
> --- a/drivers/pmdomain/imx/imx93-blk-ctrl.c
> +++ b/drivers/pmdomain/imx/imx93-blk-ctrl.c
> @@ -7,6 +7,7 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/of_platform.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> @@ -297,8 +298,14 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
>
>  	dev_set_drvdata(dev, bc);
>
> +	ret = devm_of_platform_populate(dev);
> +	if (ret)
> +		goto cleanup_provider;
> +
>  	return 0;
>
> +cleanup_provider:
> +	of_genpd_del_provider(dev->of_node);
>  cleanup_pds:
>  	for (i--; i >= 0; i--)
>  		pm_genpd_remove(&bc->domains[i].genpd);
> --
> 2.43.0
>


From david at redhat.com  Tue Mar  4 07:48:46 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue,  4 Mar 2025 16:48:46 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
In-Reply-To: <20250304154846.1937958-1-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
Message-ID: <20250304154846.1937958-4-david@redhat.com>

uprobe_write_opcode() does some pretty low-level things that really, it
shouldn't be doing: for example, manually breaking COW by allocating
anonymous folios and replacing mapped pages.

Further, it does seem to do some shaky things: for example, writing to
possible COW-shared anonymous pages or zapping anonymous pages that might
be pinned. We're also not taking care of uffd, uffd-wp, softdirty ...
although rather corner cases here. Let's just get it right like ordinary
ptrace writes would.

Let's rewrite the code, leaving COW-breaking to core-MM, triggered by
FOLL_FORCE|FOLL_WRITE (note that the code was already using FOLL_FORCE).

We'll use GUP to lookup/faultin the page and break COW if required. Then,
we'll walk the page tables using a folio_walk to perform our page
modification atomically by temporarily unmap the PTE + flushing the TLB.

Likely, we could avoid the temporary unmap in case we can just
atomically write the instruction, but that will be a separate project.

Unfortunately, we still have to implement the zapping logic manually,
because we only want to zap in specific circumstances (e.g., page
content identical).

Note that we can now handle large folios (compound pages) and the shared
zeropage just fine, so drop these checks.

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 316 ++++++++++++++++++++--------------------
 1 file changed, 160 insertions(+), 156 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 0276defd6fbfa..4e39280f8f424 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -29,6 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/srcu.h>
 #include <linux/oom.h>          /* check_stable_address_space */
+#include <linux/pagewalk.h>
 
 #include <linux/uprobes.h>
 
@@ -151,91 +152,6 @@ static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
 	return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
 }
 
-/**
- * __replace_page - replace page in vma by new page.
- * based on replace_page in mm/ksm.c
- *
- * @vma:      vma that holds the pte pointing to page
- * @addr:     address the old @page is mapped at
- * @old_page: the page we are replacing by new_page
- * @new_page: the modified page we replace page by
- *
- * If @new_page is NULL, only unmap @old_page.
- *
- * Returns 0 on success, negative error code otherwise.
- */
-static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
-				struct page *old_page, struct page *new_page)
-{
-	struct folio *old_folio = page_folio(old_page);
-	struct folio *new_folio;
-	struct mm_struct *mm = vma->vm_mm;
-	DEFINE_FOLIO_VMA_WALK(pvmw, old_folio, vma, addr, 0);
-	int err;
-	struct mmu_notifier_range range;
-	pte_t pte;
-
-	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, addr,
-				addr + PAGE_SIZE);
-
-	if (new_page) {
-		new_folio = page_folio(new_page);
-		err = mem_cgroup_charge(new_folio, vma->vm_mm, GFP_KERNEL);
-		if (err)
-			return err;
-	}
-
-	/* For folio_free_swap() below */
-	folio_lock(old_folio);
-
-	mmu_notifier_invalidate_range_start(&range);
-	err = -EAGAIN;
-	if (!page_vma_mapped_walk(&pvmw))
-		goto unlock;
-	VM_BUG_ON_PAGE(addr != pvmw.address, old_page);
-	pte = ptep_get(pvmw.pte);
-
-	/*
-	 * Handle PFN swap PTES, such as device-exclusive ones, that actually
-	 * map pages: simply trigger GUP again to fix it up.
-	 */
-	if (unlikely(!pte_present(pte))) {
-		page_vma_mapped_walk_done(&pvmw);
-		goto unlock;
-	}
-
-	if (new_page) {
-		folio_get(new_folio);
-		folio_add_new_anon_rmap(new_folio, vma, addr, RMAP_EXCLUSIVE);
-		folio_add_lru_vma(new_folio, vma);
-	} else
-		/* no new page, just dec_mm_counter for old_page */
-		dec_mm_counter(mm, MM_ANONPAGES);
-
-	if (!folio_test_anon(old_folio)) {
-		dec_mm_counter(mm, mm_counter_file(old_folio));
-		inc_mm_counter(mm, MM_ANONPAGES);
-	}
-
-	flush_cache_page(vma, addr, pte_pfn(pte));
-	ptep_clear_flush(vma, addr, pvmw.pte);
-	if (new_page)
-		set_pte_at(mm, addr, pvmw.pte,
-			   mk_pte(new_page, vma->vm_page_prot));
-
-	folio_remove_rmap_pte(old_folio, old_page, vma);
-	if (!folio_mapped(old_folio))
-		folio_free_swap(old_folio);
-	page_vma_mapped_walk_done(&pvmw);
-	folio_put(old_folio);
-
-	err = 0;
- unlock:
-	mmu_notifier_invalidate_range_end(&range);
-	folio_unlock(old_folio);
-	return err;
-}
-
 /**
  * is_swbp_insn - check if instruction is breakpoint instruction.
  * @insn: instruction to be checked.
@@ -463,6 +379,105 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
+static bool orig_page_is_identical(struct vm_area_struct *vma,
+		unsigned long vaddr, struct page *page, bool *pmd_mappable)
+{
+	const pgoff_t index = vaddr_to_offset(vma, vaddr) >> PAGE_SHIFT;
+	struct page *orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
+					       index);
+	struct folio *orig_folio;
+	bool identical;
+
+	if (!orig_page)
+		return false;
+	orig_folio = page_folio(orig_page);
+
+	*pmd_mappable = folio_test_pmd_mappable(orig_folio);
+	identical = folio_test_uptodate(orig_folio) &&
+		    pages_identical(page, orig_page);
+	folio_put(orig_folio);
+	return identical;
+}
+
+static int __uprobe_write_opcode(struct vm_area_struct *vma,
+		struct folio_walk *fw, struct folio *folio,
+		unsigned long opcode_vaddr, uprobe_opcode_t opcode)
+{
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
+	const bool is_register = !!is_swbp_insn(&opcode);
+	bool pmd_mappable;
+
+	/* We're done if we don't find an anonymous folio when unregistering. */
+	if (!folio_test_anon(folio))
+		return is_register ? -EFAULT : 0;
+
+	/* For now, we'll only handle PTE-mapped folios. */
+	if (fw->level != FW_LEVEL_PTE)
+		return -EFAULT;
+
+	/*
+	 * See can_follow_write_pte(): we'd actually prefer a writable PTE here,
+	 * but the VMA might not be writable.
+	 */
+	if (!pte_write(fw->pte)) {
+		if (!PageAnonExclusive(fw->page))
+			return -EFAULT;
+		if (unlikely(userfaultfd_pte_wp(vma, fw->pte)))
+			return -EFAULT;
+		/* SOFTDIRTY is handled via pte_mkdirty() below. */
+	}
+
+	/*
+	 * We'll temporarily unmap the page and flush the TLB, such that we can
+	 * modify the page atomically.
+	 */
+	flush_cache_page(vma, vaddr, pte_pfn(fw->pte));
+	fw->pte = ptep_clear_flush(vma, vaddr, fw->ptep);
+
+	/* Verify that the page content is still as expected. */
+	if (verify_opcode(fw->page, opcode_vaddr, &opcode) <= 0) {
+		set_pte_at(vma->vm_mm, vaddr, fw->ptep, fw->pte);
+		return -EAGAIN;
+	}
+	copy_to_page(fw->page, opcode_vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+
+	/*
+	 * When unregistering, we may only zap a PTE if uffd is disabled and
+	 * there are no unexpected folio references ...
+	 */
+	if (is_register || userfaultfd_missing(vma) ||
+	    (folio_ref_count(folio) != folio_mapcount(folio) +
+	     folio_test_swapcache(folio) * folio_nr_pages(folio)))
+		goto remap;
+
+	/*
+	 * ... and the mapped page is identical to the original page that
+	 * would get faulted in on next access.
+	 */
+	if (!orig_page_is_identical(vma, vaddr, fw->page, &pmd_mappable))
+		goto remap;
+
+	dec_mm_counter(vma->vm_mm, MM_ANONPAGES);
+	folio_remove_rmap_pte(folio, fw->page, vma);
+	if (!folio_mapped(folio) && folio_test_swapcache(folio) &&
+	     folio_trylock(folio)) {
+		folio_free_swap(folio);
+		folio_unlock(folio);
+	}
+	folio_put(folio);
+
+	return pmd_mappable;
+remap:
+	/*
+	 * Make sure that our copy_to_page() changes become visible before the
+	 * set_pte_at() write.
+	 */
+	smp_wmb();
+	/* We modified the page. Make sure to mark the PTE dirty. */
+	set_pte_at(vma->vm_mm, vaddr, fw->ptep, pte_mkdirty(fw->pte));
+	return 0;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
@@ -475,116 +490,105 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
  * @vma: the probed virtual memory area.
- * @vaddr: the virtual address to store the opcode.
- * @opcode: opcode to be written at @vaddr.
+ * @opcode_vaddr: the virtual address to store the opcode.
+ * @opcode: opcode to be written at @opcode_vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
 int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
-		unsigned long vaddr, uprobe_opcode_t opcode)
+		const unsigned long opcode_vaddr, uprobe_opcode_t opcode)
 {
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
 	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
-	struct page *old_page, *new_page;
 	int ret, is_register, ref_ctr_updated = 0;
-	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
+	struct mmu_notifier_range range;
+	struct folio_walk fw;
+	struct folio *folio;
+	struct page *page;
 
 	is_register = is_swbp_insn(&opcode);
 	uprobe = container_of(auprobe, struct uprobe, arch);
 
-retry:
+	if (WARN_ON_ONCE(!is_cow_mapping(vma->vm_flags)))
+		return -EINVAL;
+
+	/*
+	 * When registering, we have to break COW to get an exclusive anonymous
+	 * page that we can safely modify. Use FOLL_WRITE to trigger a write
+	 * fault if required. When unregistering, we might be lucky and the
+	 * anon page is already gone. So defer write faults until really
+	 * required. Use FOLL_SPLIT_PMD, because __uprobe_write_opcode()
+	 * cannot deal with PMDs yet.
+	 */
 	if (is_register)
-		gup_flags |= FOLL_SPLIT_PMD;
-	/* Read the page with vaddr into memory */
-	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
+
+retry:
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &page, NULL);
 	if (ret != 1)
-		return ret;
+		goto out;
 
-	ret = verify_opcode(old_page, vaddr, &opcode);
+	ret = verify_opcode(page, opcode_vaddr, &opcode);
+	put_page(page);
 	if (ret <= 0)
-		goto put_old;
-
-	if (is_zero_page(old_page)) {
-		ret = -EINVAL;
-		goto put_old;
-	}
-
-	if (WARN(!is_register && PageCompound(old_page),
-		 "uprobe unregister should never work on compound page\n")) {
-		ret = -EINVAL;
-		goto put_old;
-	}
+		goto out;
 
 	/* We are going to replace instruction, update ref_ctr. */
 	if (!ref_ctr_updated && uprobe->ref_ctr_offset) {
 		ret = update_ref_ctr(uprobe, mm, is_register ? 1 : -1);
 		if (ret)
-			goto put_old;
+			goto out;
 
 		ref_ctr_updated = 1;
 	}
 
-	ret = 0;
-	if (!is_register && !PageAnon(old_page))
-		goto put_old;
-
-	ret = anon_vma_prepare(vma);
-	if (ret)
-		goto put_old;
-
-	ret = -ENOMEM;
-	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
-	if (!new_page)
-		goto put_old;
-
-	__SetPageUptodate(new_page);
-	copy_highpage(new_page, old_page);
-	copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
-
 	if (!is_register) {
-		struct page *orig_page;
-		pgoff_t index;
-
-		VM_BUG_ON_PAGE(!PageAnon(old_page), old_page);
-
-		index = vaddr_to_offset(vma, vaddr & PAGE_MASK) >> PAGE_SHIFT;
-		orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
-					  index);
-
-		if (orig_page) {
-			if (PageUptodate(orig_page) &&
-			    pages_identical(new_page, orig_page)) {
-				/* let go new_page */
-				put_page(new_page);
-				new_page = NULL;
-
-				if (PageCompound(orig_page))
-					orig_page_huge = true;
-			}
-			put_page(orig_page);
-		}
+		/*
+		 * In the common case, we'll be able to zap the page when
+		 * unregistering. So trigger MMU notifiers now, as we won't
+		 * be able to do it under PTL.
+		 */
+		mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
+					vaddr, vaddr + PAGE_SIZE);
+		mmu_notifier_invalidate_range_start(&range);
+	}
+
+	/* Walk the page tables again, to perform the actual update. */
+	folio = folio_walk_start(&fw, vma, vaddr, 0);
+	if (folio) {
+		ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr,
+					    opcode);
+		folio_walk_end(&fw, vma);
+	} else {
+		ret = -EAGAIN;
 	}
 
-	ret = __replace_page(vma, vaddr & PAGE_MASK, old_page, new_page);
-	if (new_page)
-		put_page(new_page);
-put_old:
-	put_page(old_page);
+	if (!is_register)
+		mmu_notifier_invalidate_range_end(&range);
 
-	if (unlikely(ret == -EAGAIN))
+	switch (ret) {
+	case -EFAULT:
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
+		fallthrough;
+	case -EAGAIN:
 		goto retry;
+	default:
+		break;
+	}
 
+out:
 	/* Revert back reference counter if instruction update failed. */
-	if (ret && is_register && ref_ctr_updated)
+	if (ret < 0 && is_register && ref_ctr_updated)
 		update_ref_ctr(uprobe, mm, -1);
 
 	/* try collapse pmd for compound page */
-	if (!ret && orig_page_huge)
+	if (ret > 0)
 		collapse_pte_mapped_thp(mm, vaddr, false);
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 /**
-- 
2.48.1



From brgl at bgdev.pl  Tue Mar  4 07:48:54 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 4 Mar 2025 16:48:54 +0100
Subject: [PATCH 0/6] ASoC: samsung: GPIO descriptor conversion
In-Reply-To: <174110255924.87345.17067818310965896666.b4-ty@kernel.org>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org> <174110255924.87345.17067818310965896666.b4-ty@kernel.org>
Message-ID: <CAMRc=MfqNSZeQxBuEfM1nAo0F3NmEkyG-Les3dyxxuun=4XpuQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 4:36?PM Mark Brown <broonie at kernel.org> wrote:
>
> On Mon, 03 Mar 2025 09:41:40 +0100, Linus Walleij wrote:
> > This drops unused includes and converts one Samsung
> > codec to use GPIO descriptors.
> >
> >
>
> Applied to
>
>    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
>
> Thanks!
>
> [1/6] ASoC: samsung: bells: Drop unused include
>       commit: b19d340d5d08c5940ce612c2a1b5fe3a8a401f9d
> [2/6] ASoC: samsung: littlemill: Drop unused include
>       commit: c4b2d9643a06a5326a778c4d77d6fa60e0f3d6b1
> [3/6] ASoC: samsung: lowland: Drop unused include
>       commit: 5c06f7f3d8374df1cec3b353306a4d1032a60f44
> [4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
>       commit: da9146c19b1774926148ff271c4a3dc8d7891b18

I pointed out an issue with patch 4. :(

Bart

> [5/6] ASoC: samsung: tobermory: Drop unused include
>       commit: c095b7a27529d1d18b3b36a47f77a1419f0de939
> [6/6] ASoC: samsung: tm2_wm5110: Drop unused include
>       commit: 0a22454ab2eca530702b2689858909b608953703
>


From kw at linux.com  Tue Mar  4 08:10:06 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 01:10:06 +0900
Subject: [PATCH v2 0/8] PCI: brcmstb: Misc small tweaks and fixes
In-Reply-To: <20250301144831.GA846783@rocinante>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250301144831.GA846783@rocinante>
Message-ID: <20250304161006.GC2310180@rocinante>

Hello,

> >   Six small fixes and improvements for the driver.  This may be applied
> >   before or after Stan's V5 [1] on pci-next (they should not conflict).
> 
> Applied to controller/brcmstb, thank you!

Updated with missing "Reviewed-by" tags that Mani recently offered.

Thank you!

	Krzysztof


From Frank.li at nxp.com  Tue Mar  4 08:12:12 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:12:12 -0500
Subject: [PATCH v3 5/6] arm64: dts: tqma9352-mba93xxla: Add LVDS overlay
In-Reply-To: <20250304154929.1785200-6-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-6-alexander.stein@ew.tq-group.com>
Message-ID: <Z8cmXP22SXtXjNw3@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 04:49:24PM +0100, Alexander Stein wrote:
> This adds the overlay for the Tianma TM070JVHG33 LVDS display.
>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  arch/arm64/boot/dts/freescale/Makefile        |  3 ++
>  ...3-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso | 40 +++++++++++++++++++
>  .../freescale/imx93-tqma9352-mba93xxla.dts    | 27 +++++++++++++
>  3 files changed, 70 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso
>
> diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
> index be6ef4c56fbf4..ac4f14c69cdd8 100644
> --- a/arch/arm64/boot/dts/freescale/Makefile
> +++ b/arch/arm64/boot/dts/freescale/Makefile
> @@ -300,6 +300,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
>
> +imx93-tqma9352-mba93xxla-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxla.dtb imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtbo
> +dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtb
> +
>  imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
>
>  dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-dl.dtb
> diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso
> new file mode 100644
> index 0000000000000..c723a19f03d63
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtso
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
> +/*
> + * Copyright (c) 2023 TQ-Systems GmbH <linux at ew.tq-group.com>,
> + * D-82229 Seefeld, Germany.
> + * Author: Alexander Stein
> + */
> +
> +#include <dt-bindings/clock/imx93-clock.h>
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/dts-v1/;
> +/plugin/;
> +
> +&backlight_lvds {
> +	status = "okay";
> +};
> +
> +&display {
> +	compatible = "tianma,tm070jvhg33";
> +	status = "okay";
> +};
> +
> +&lcdif {
> +	assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
> +			  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
> +	assigned-clock-rates = <477400000>;
> +	status = "okay";
> +};
> +
> +&lvds_bridge {
> +	status = "okay";
> +};
> +
> +&media_blk_ctrl {
> +	status = "okay";
> +};
> +
> +&tpm5 {
> +	status = "okay";
> +};
> diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
> index 9e88c42c3d170..4618f836345fc 100644
> --- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
> +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
> @@ -48,6 +48,23 @@ clk_dp: clk-dp {
>  		clock-frequency = <26000000>;
>  	};
>
> +	display: display {
> +		/*
> +		 * Display is not fixed, so compatible has to be added from
> +		 * DT overlay
> +		 */
> +		power-supply = <&reg_3v3>;
> +		enable-gpios = <&expander2 1 GPIO_ACTIVE_HIGH>;
> +		backlight = <&backlight_lvds>;
> +		status = "disabled";
> +
> +		port {
> +			panel_in_lvds0: endpoint {
> +				remote-endpoint = <&ldb_lvds>;
> +			};
> +		};
> +	};
> +
>  	gpio-keys {
>  		compatible = "gpio-keys";
>  		autorepeat;
> @@ -509,6 +526,16 @@ &lpuart8 {
>  	status = "okay";
>  };
>
> +&lvds_bridge {
> +	ports {
> +		port at 1 {
> +			ldb_lvds: endpoint {
> +				remote-endpoint = <&panel_in_lvds0>;
> +			};
> +		};
> +	};
> +};
> +
>  &pcf85063 {
>  	/* RTC_EVENT# from SoM is connected on mainboard */
>  	pinctrl-names = "default";
> --
> 2.43.0
>


From Frank.li at nxp.com  Tue Mar  4 08:13:24 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:13:24 -0500
Subject: [PATCH v3 6/6] arm64: dts: tqma9352-mba93xxca: Add LVDS overlay
In-Reply-To: <20250304154929.1785200-7-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-7-alexander.stein@ew.tq-group.com>
Message-ID: <Z8cmpPy40ztL/hA/@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 04:49:25PM +0100, Alexander Stein wrote:
> This adds the overlay for the Tianma TM070JVHG33 LVDS display.

Nit: Add the overlay ...

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
>  arch/arm64/boot/dts/freescale/Makefile        |  2 +
>  ...3-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso | 40 +++++++++++++++++++
>  .../freescale/imx93-tqma9352-mba93xxca.dts    | 27 +++++++++++++
>  3 files changed, 69 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
>
> diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
> index ac4f14c69cdd8..48991e9a9c076 100644
> --- a/arch/arm64/boot/dts/freescale/Makefile
> +++ b/arch/arm64/boot/dts/freescale/Makefile
> @@ -300,7 +300,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
>
> +imx93-tqma9352-mba93xxca-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxca.dtb imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtbo
>  imx93-tqma9352-mba93xxla-lvds-tm070jvhg33-dtbs += imx93-tqma9352-mba93xxla.dtb imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtbo
> +dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla-lvds-tm070jvhg33.dtb
>
>  imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
> diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
> new file mode 100644
> index 0000000000000..d21e5ccca2e93
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca-lvds-tm070jvhg33.dtso
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
> +/*
> + * Copyright (c) 2025 TQ-Systems GmbH <linux at ew.tq-group.com>,
> + * D-82229 Seefeld, Germany.
> + * Author: Alexander Stein
> + */
> +
> +#include <dt-bindings/clock/imx93-clock.h>
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/dts-v1/;
> +/plugin/;
> +
> +&backlight_lvds {
> +	status = "okay";
> +};
> +
> +&display {
> +	compatible = "tianma,tm070jvhg33";
> +	status = "okay";
> +};
> +
> +&lcdif {
> +	assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
> +			  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
> +	assigned-clock-rates = <477400000>;
> +	status = "okay";
> +};
> +
> +&lvds_bridge {
> +	status = "okay";
> +};
> +
> +&media_blk_ctrl {
> +	status = "okay";
> +};
> +
> +&tpm5 {
> +	status = "okay";
> +};
> diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
> index ebbac5f8d2b2d..e70c3995e89da 100644
> --- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
> +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
> @@ -42,6 +42,23 @@ backlight_lvds: backlight {
>  		status = "disabled";
>  	};
>
> +	display: display {
> +		/*
> +		 * Display is not fixed, so compatible has to be added from
> +		 * DT overlay
> +		 */
> +		power-supply = <&reg_3v3>;
> +		enable-gpios = <&expander2 1 GPIO_ACTIVE_HIGH>;
> +		backlight = <&backlight_lvds>;
> +		status = "disabled";
> +
> +		port {
> +			panel_in_lvds0: endpoint {
> +				remote-endpoint = <&ldb_lvds>;
> +			};
> +		};
> +	};
> +
>  	fan0: pwm-fan {
>  		compatible = "pwm-fan";
>  		pinctrl-names = "default";
> @@ -546,6 +563,16 @@ &lpuart8 {
>  	status = "okay";
>  };
>
> +&lvds_bridge {
> +	ports {
> +		port at 1 {
> +			ldb_lvds: endpoint {
> +				remote-endpoint = <&panel_in_lvds0>;
> +			};
> +		};
> +	};
> +};
> +
>  &pcf85063 {
>  	/* RTC_EVENT# from SoM is connected on mainboard */
>  	pinctrl-names = "default";
> --
> 2.43.0
>


From florin.leotescu at oss.nxp.com  Tue Mar  4 08:21:33 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue,  4 Mar 2025 18:21:33 +0200
Subject: [PATCH v3 0/3] Add OF support for Microchip emc2305 fan controller
Message-ID: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

This patch series add initial OF support for Microchip emc2305 fan controller.

Changes since v2:
- Removed the introduction of new properties for now and we only 
  enable basic OF support.
- Link to previous version: 
  https://lore.kernel.org/linux-arm-kernel/20250219133221.2641041-3-florin.leotescu at oss.nxp.com/T/

Florin Leotescu (3):
  dt-bindings: hwmon: Add Microchip emc2305 yaml schema
  hwmon: emc2305: Add OF support
  hwmon: emc2305: Use devm_thermal_of_cooling_device_register

 .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
 drivers/hwmon/emc2305.c                       | 36 ++++++----------
 2 files changed, 55 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar  4 08:21:34 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue,  4 Mar 2025 18:21:34 +0200
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml schema
In-Reply-To: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce yaml schema for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
---
 .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
new file mode 100644
index 000000000000..cac0075a65bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip EMC2305 SMBus compliant PWM fan controller
+
+maintainers:
+  - Michael Shych <michaelsh at nvidia.com>
+
+description: |
+  Microchip EMC2301/2/3/5 pwm controller which supports up
+  to five programmable fan control circuits
+
+properties:
+  compatible:
+    enum:
+      - microchip,emc2301
+      - microchip,emc2302
+      - microchip,emc2303
+      - microchip,emc2305
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        emc2301: pwm at 2f {
+            compatible = "microchip,emc2301";
+            reg = <0x2f>;
+        };
+    };
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar  4 08:21:35 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue,  4 Mar 2025 18:21:35 +0200
Subject: [PATCH v3 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250304162136.1963384-3-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce OF support for Microchip emc2301/2/3/5 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
---
 drivers/hwmon/emc2305.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 4d39fbd83769..a236f27c75bc 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -607,9 +607,19 @@ static void emc2305_remove(struct i2c_client *client)
 		emc2305_unset_tz(dev);
 }
 
+static const struct of_device_id of_emc2305_match_table[] = {
+	{ .compatible = "microchip,emc2301", },
+	{ .compatible = "microchip,emc2302", },
+	{ .compatible = "microchip,emc2303", },
+	{ .compatible = "microchip,emc2305", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
+
 static struct i2c_driver emc2305_driver = {
 	.driver = {
 		.name = "emc2305",
+		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
 	.remove	  = emc2305_remove,
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar  4 08:21:36 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue,  4 Mar 2025 18:21:36 +0200
Subject: [PATCH v3 3/3] hwmon: emc2305: Use devm_thermal_of_cooling_device_register
In-Reply-To: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250304162136.1963384-4-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

This prepares emc2305 driver to use configuration from Device Tree nodes.
Using devm_thermal_of_cooling_device_register also simplifies cleanup
procedure, so we are able to remove the emc2305_unset_tz and emc2305_remove
functions which are no longer used.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
---
 drivers/hwmon/emc2305.c | 28 +++-------------------------
 1 file changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index a236f27c75bc..5f3f06308826 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
 	"emc2305_fan5",
 };
 
-static void emc2305_unset_tz(struct device *dev);
-
 static int emc2305_get_max_channel(const struct emc2305_data *data)
 {
 	return data->pwm_num;
@@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
 	pwm = data->pwm_min[cdev_idx];
 
 	data->cdev_data[cdev_idx].cdev =
-		thermal_cooling_device_register(emc2305_fan_name[idx], data,
-						&emc2305_cooling_ops);
+		devm_thermal_of_cooling_device_register(dev, dev->of_node,
+							emc2305_fan_name[idx], data,
+							&emc2305_cooling_ops);
 
 	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
 		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
@@ -337,21 +336,9 @@ static int emc2305_set_tz(struct device *dev)
 	return 0;
 
 thermal_cooling_device_register_fail:
-	emc2305_unset_tz(dev);
 	return ret;
 }
 
-static void emc2305_unset_tz(struct device *dev)
-{
-	struct emc2305_data *data = dev_get_drvdata(dev);
-	int i;
-
-	/* Unregister cooling device. */
-	for (i = 0; i < EMC2305_PWM_MAX; i++)
-		if (data->cdev_data[i].cdev)
-			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
-}
-
 static umode_t
 emc2305_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
 {
@@ -599,14 +586,6 @@ static int emc2305_probe(struct i2c_client *client)
 	return 0;
 }
 
-static void emc2305_remove(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-
-	if (IS_REACHABLE(CONFIG_THERMAL))
-		emc2305_unset_tz(dev);
-}
-
 static const struct of_device_id of_emc2305_match_table[] = {
 	{ .compatible = "microchip,emc2301", },
 	{ .compatible = "microchip,emc2302", },
@@ -622,7 +601,6 @@ static struct i2c_driver emc2305_driver = {
 		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
-	.remove	  = emc2305_remove,
 	.id_table = emc2305_ids,
 };
 
-- 
2.34.1



From maxime.chevallier at bootlin.com  Tue Mar  4 08:15:15 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Tue, 4 Mar 2025 17:15:15 +0100
Subject: [PATCH net] net: ethtool: Set the req_info->dev on DUMP
 requests for each dev
In-Reply-To: <20250304170051.607097e9@kmaincent-XPS-13-7390>
References: <20250302162137.698092-1-maxime.chevallier@bootlin.com>
	<20250304170051.607097e9@kmaincent-XPS-13-7390>
Message-ID: <20250304171515.297d15df@fedora.home>

Hi K?ry,

On Tue, 4 Mar 2025 17:00:51 +0100
Kory Maincent <kory.maincent at bootlin.com> wrote:

> On Sun,  2 Mar 2025 17:21:36 +0100
> Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:
> 
> > There are a few netlink commands that rely on the req_info->dev field
> > being populated by ethnl in their ->prepare_data() and ->fill_reply().
> > 
> > For a regular GET request, this will be set by ethnl_default_parse(),
> > which calls ethnl_parse_header_dev_get().
> > 
> > In the case of a DUMP request, the ->prepare_data() and ->fill_reply()
> > callbacks will be called with the req_info->dev being NULL, which can
> > cause discrepancies in the behaviour between GET and DUMP results.
> > 
> > The main impact is that ethnl_req_get_phydev() will not find any
> > phy_device, impacting :
> >  - plca
> >  - pse-pd
> >  - stats
> > 
> > Some other commands rely on req_info->dev, namely :
> >  - coalesce in ->fill_reply to look for an irq_moder
> > 
> > Although cable_test and tunnels also rely on req_info->dev being set,
> > that's not a problem for these commands as :
> >  - cable_test doesn't support DUMP
> >  - tunnels rolls its own ->dumpit (and sets dev in the req_info).
> >  - phy also has its own ->dumpit
> > 
> > All other commands use reply_data->dev (probably the correct way of
> > doing things) and aren't facing this issue.
> > 
> > Simply set the dev in the req_info context when iterating to dump each
> > dev.
> > 
> > Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some
> > commands") Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> > ---
> > 
> > Fixes tag targets the phy-index commit, as it introduced a change in
> > behaviour for PLCA. From what I can tell, coalesce never correctly
> > detected irq_moder in DUMP requests.
> > 
> > We could also consider fixing all individual commands that use
> > req_info->dev, however I'm not actually sure it's incorrect to do so,
> > feel free to correct me though.
> > 
> > Maxime
> > 
> >  net/ethtool/netlink.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> > index b4c45207fa32..de967961d8fe 100644
> > --- a/net/ethtool/netlink.c
> > +++ b/net/ethtool/netlink.c
> > @@ -582,6 +582,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
> >  		dev_hold(dev);
> >  		rcu_read_unlock();
> >  
> > +		ctx->req_info->dev = dev;  
> 
> I would rather put it in ethnl_default_dump_one() before
> ethnl_init_reply_data() call.

Ah yes true, that'll be more consistent with the other callpaths.

> With this change:
> Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
> Tested-by: Kory Maincent <kory.maincent at bootlin.com>

Thank you for testing, I'll respin.

Maxime

> 



From broonie at kernel.org  Tue Mar  4 08:18:20 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 4 Mar 2025 16:18:20 +0000
Subject: [PATCH 0/6] ASoC: samsung: GPIO descriptor conversion
In-Reply-To: <CAMRc=MfqNSZeQxBuEfM1nAo0F3NmEkyG-Les3dyxxuun=4XpuQ@mail.gmail.com>
References: <20250303-samsung-codecs-v1-0-56a2299dd928@linaro.org>
 <174110255924.87345.17067818310965896666.b4-ty@kernel.org>
 <CAMRc=MfqNSZeQxBuEfM1nAo0F3NmEkyG-Les3dyxxuun=4XpuQ@mail.gmail.com>
Message-ID: <7da76b50-67fd-4273-83a3-300f734f7922@sirena.org.uk>

On Tue, Mar 04, 2025 at 04:48:54PM +0100, Bartosz Golaszewski wrote:
> On Tue, Mar 4, 2025 at 4:36?PM Mark Brown <broonie at kernel.org> wrote:

> > [4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
> >       commit: da9146c19b1774926148ff271c4a3dc8d7891b18

> I pointed out an issue with patch 4. :(

Oh, sorry - you didn't cut any context so I think it just flashed by
while paging through the entire message as I was scanning for responses.
One of the reasons for cutting uneeded context is it makes it easier to
spot the new content in your message.  It's an issue which can be easily
addressed incrementally in any case.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/99dde9d3/attachment.sig>

From jgg at ziepe.ca  Tue Mar  4 08:19:43 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Tue, 4 Mar 2025 12:19:43 -0400
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <67fbe3f4-4fb6-4753-b34c-320b7897fd16@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com>
 <20250303165255.GS5011@ziepe.ca>
 <20250303190330.GA426248@e133081.arm.com>
 <20250304142634.GC5011@ziepe.ca>
 <67fbe3f4-4fb6-4753-b34c-320b7897fd16@arm.com>
Message-ID: <20250304161943.GD5011@ziepe.ca>

On Tue, Mar 04, 2025 at 04:02:20PM +0000, Ryan Roberts wrote:
> On 04/03/2025 14:26, Jason Gunthorpe wrote:
> > On Mon, Mar 03, 2025 at 07:03:42PM +0000, Miko?aj Lenczewski wrote:
> > 
> >> For example, if we use BBML2 for kernel mappings, does that require us
> >> to repaint all kernel mappings when disabling BBML2 on smmu attach? I
> >> am not sure, but definitely something to be worked out.
> > 
> > No, it would be a per-mm_struct basis only if we did something like
> > that
> > 
> > When the SMMU driver puts a SVA on top of the mm_struct it would
> > disable BBML2 usage only for that mm_struct and it's contained VMAs.
> 
> I guess we would need to figure out some synchonization mechanism if disabling
> BBML2 dynaically per-mm. If there was already a BBML2 operation in flight would
> want to wait for it to end. But that's a problem to solve if/when it's shown to
> be needed, I think.

I have a feeling we can piggyback on the mmu notifiers to achieve this
as all the changes to the PTEs should be bracketed by notifier
callbacks..

Let's hope it isn't needed.

Jasob


From ryan.roberts at arm.com  Tue Mar  4 08:21:14 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue, 4 Mar 2025 16:21:14 +0000
Subject: [PATCH] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <20250303041834.2796751-1-anshuman.khandual@arm.com>
References: <20250303041834.2796751-1-anshuman.khandual@arm.com>
Message-ID: <0fe6f3b2-1011-4418-bc19-612a3b98c78d@arm.com>

On 03/03/2025 04:18, Anshuman Khandual wrote:
> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
> section mapping at all page table levels except the last level. This works
> fine as the section mapping masks are exactly the same (0x1UL) for all page
> table levels.
> 
> This will change in the future with D128 page tables that have unique skip
> level values (SKL) required for creating section mapping at different page
> table levels. Hence use page table level specific section mapping macros
> instead of the common PMD_TYPE_SECT.
> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: linux-kernel at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
> This patch applies on 6.14-rc5
> 
> PGD_TYPE_SECT for level -1 section map handling has been added for 4K
> base pages with 52 bit VA configuration that has 5 page table levels.
> In such cases (CONFIG_PGTABLE_LEVELS = 5) early_map_kernel() can call
> map_range() eventually with -1 (i.e 4 - CONFIG_PGTABLE_LEVELS) as the
> root_level.

Table Table D8-16 on page D8-6459 of ARM DDI 0487 L.a says that block mappings
at level -1 are not permitted for 4K pages; only levels 0-3 support leaf
mappings. Similarly for 16K, table D8-26 says only levels 1-3 permit leaf
mappings. And for 64K, table D8-35 says only levels 1-3 permit leaf mappings.

So I don't think PGD_TYPE_SECT is the right solution. Perhaps we need to
explicitly force the unsupported levels to be table entries even if the
alignment is correct?

Thanks,
Ryan

> 
>  arch/arm64/include/asm/pgtable-hwdef.h |  1 +
>  arch/arm64/kernel/pi/map_range.c       | 23 +++++++++++++++++++++--
>  2 files changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index a9136cc551cc..fd0a82e8878c 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -99,6 +99,7 @@
>  #define PGD_TYPE_TABLE		(_AT(pgdval_t, 3) << 0)
>  #define PGD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
>  #define PGD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
> +#define PGD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
>  #define PGD_TABLE_AF		(_AT(pgdval_t, 1) << 10)	/* Ignored if no FEAT_HAFT */
>  #define PGD_TABLE_PXN		(_AT(pgdval_t, 1) << 59)
>  #define PGD_TABLE_UXN		(_AT(pgdval_t, 1) << 60)
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..9ea869f5745f 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -44,8 +44,27 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	 * Set the right block/page bits for this level unless we are
>  	 * clearing the mapping
>  	 */
> -	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> +	if (protval) {
> +		switch (level) {
> +		case 3:
> +			protval |= PTE_TYPE_PAGE;
> +			break;
> +		case 2:
> +			protval |= PMD_TYPE_SECT;
> +			break;
> +		case 1:
> +			protval |= PUD_TYPE_SECT;
> +			break;
> +		case 0:
> +			protval |= P4D_TYPE_SECT;
> +			break;
> +		case -1:
> +			protval |= PGD_TYPE_SECT;
> +			break;
> +		default:
> +			break;
> +		}
> +	}
>  
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));



From broonie at kernel.org  Tue Mar  4 08:22:39 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 4 Mar 2025 16:22:39 +0000
Subject: [PATCH v3 03/20] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <20250304-mt6359-accdet-dts-v3-3-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
 <20250304-mt6359-accdet-dts-v3-3-5b0eafc29f5b@collabora.com>
Message-ID: <a8fbb536-a246-4650-8085-d576652b0301@sirena.org.uk>

On Tue, Mar 04, 2025 at 12:15:44PM -0300, N?colas F. R. A. Prado wrote:
> From: Andrew Perepech <andrew.perepech at mediatek.com>
> 
> Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
> allow the mt6359-accdet driver to probe.

Lee, is this OK to merge via ASoC?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/4f85eaac/attachment.sig>

From mark.rutland at arm.com  Tue Mar  4 08:25:38 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 4 Mar 2025 16:25:38 +0000
Subject: [PATCH v20 00/11] arm64/perf: Enable branch stack sampling
In-Reply-To: <Z8bjEm_neWdMBNYv@arm.com>
References: <20250218-arm-brbe-v19-v20-0-4e9922fc2e8e@kernel.org>
 <174080569248.3208873.17639032755999041028.b4-ty@kernel.org>
 <CAL_JsqLijFG1PFkqKk7hXzC=aj70OLQsXwC280QsCO=PnCVZYg@mail.gmail.com>
 <Z8bjEm_neWdMBNYv@arm.com>
Message-ID: <Z8cpgsxG4RrDoTKR@J2N7QTR9R3.cambridge.arm.com>

On Tue, Mar 04, 2025 at 11:25:06AM +0000, Catalin Marinas wrote:
> On Mon, Mar 03, 2025 at 10:44:21AM -0600, Rob Herring wrote:
> > On Sat, Mar 1, 2025 at 1:05?AM Will Deacon <will at kernel.org> wrote:
> > > On Tue, 18 Feb 2025 14:39:55 -0600, Rob Herring (Arm) wrote:
> > > > This series enables perf branch stack sampling support on arm64 via a
> > > > v9.2 arch feature called Branch Record Buffer Extension (BRBE). Details
> > > > on BRBE can be found in the Arm ARM[1] chapter D18.
> > > >
> > > > I've picked up this series from Anshuman. v19 and v20 versions have been
> > > > reworked quite a bit by Mark and myself. The bulk of those changes are
> > > > in patch 11.
> > > >
> > > > [...]
> > >
> > > Applied cleanups to will (for-next/perf), thanks!
> > >
> > > [01/11] perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling counters
> > >         https://git.kernel.org/will/c/04bd15c4cbc3
> > > [02/11] perf: arm_pmu: Don't disable counter in armpmu_add()
> > >         https://git.kernel.org/will/c/dcca27bc1ecc
> > > [03/11] perf: arm_pmuv3: Don't disable counter in armv8pmu_enable_event()
> > >         https://git.kernel.org/will/c/4b0567ad0be5
> > > [04/11] perf: arm_v7_pmu: Drop obvious comments for enabling/disabling counters and interrupts
> > >         https://git.kernel.org/will/c/7a5387748215
> > > [05/11] perf: arm_v7_pmu: Don't disable counter in (armv7|krait_|scorpion_)pmu_enable_event()
> > >         https://git.kernel.org/will/c/7bf1001e0d91
> > > [06/11] perf: apple_m1: Don't disable counter in m1_pmu_enable_event()
> > >         https://git.kernel.org/will/c/c2e793da59fc
> > > [07/11] perf: arm_pmu: Move PMUv3-specific data
> > >         https://git.kernel.org/will/c/dc4d58a752ea
> > 
> > I don't know if you looked at the thread on patch 11 and said "long
> > discussion, I'll assume a new version is coming. Next!" because that's
> > what I would do. In this case though, there's not any changes.
> 
> I do this as well ;). But I think Will is waiting for Mark R to look at
> the rest of the series.

Sorry for the delay there.

I'm happy with the structure of this; my only remaining concern is the
filtering logic, as it is surprisingly subtle, and when I was last
working on that it wasn't clear to me whether we could alwways filter
appropriately (or whether it'd be better to reject scheduling of events
with mismatched filters).

I'll try to page that in and properly attack that soon, but aside from
that concern the series as a whole looks good to me.

Thanks,
Mark.


From Frank.li at nxp.com  Tue Mar  4 08:27:03 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:27:03 -0500
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
Message-ID: <Z8cp1xoIXT8lgD8T@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 06:21:34PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
>
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
>
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
>  1 file changed, 43 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..cac0075a65bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,43 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>

who is it? look like not Microchip and hwmon maintainer.

> +
> +description: |

Needn't |

> +  Microchip EMC2301/2/3/5 pwm controller which supports up
> +  to five programmable fan control circuits
> +
> +properties:
> +  compatible:
> +    enum:
> +      - microchip,emc2301
> +      - microchip,emc2302
> +      - microchip,emc2303
> +      - microchip,emc2305

According to your driver code look like all compatible with microchip,emc2301

oneOf:
  - enum:
      - microchip,emc2301
  - items:
      - enum:
          - microchip,emc2302
          - microchip,emc2303
          - microchip,emc2305
      - const: microchip,emc2301

So your driver just need one "microchip,emc2301" compatible string.

> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        emc2301: pwm at 2f {
> +            compatible = "microchip,emc2301";
> +            reg = <0x2f>;

If only one reg:
You can go through trivial-devices.yaml

Frank

> +        };
> +    };
> --
> 2.34.1
>


From Frank.li at nxp.com  Tue Mar  4 08:27:50 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:27:50 -0500
Subject: [PATCH v3 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250304162136.1963384-3-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-3-florin.leotescu@oss.nxp.com>
Message-ID: <Z8cqBtDCtylWkmWJ@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 06:21:35PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
>
> Introduce OF support for Microchip emc2301/2/3/5 pwm fan controller.
>
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/hwmon/emc2305.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
> index 4d39fbd83769..a236f27c75bc 100644
> --- a/drivers/hwmon/emc2305.c
> +++ b/drivers/hwmon/emc2305.c
> @@ -607,9 +607,19 @@ static void emc2305_remove(struct i2c_client *client)
>  		emc2305_unset_tz(dev);
>  }
>
> +static const struct of_device_id of_emc2305_match_table[] = {
> +	{ .compatible = "microchip,emc2301", },
> +	{ .compatible = "microchip,emc2302", },
> +	{ .compatible = "microchip,emc2303", },
> +	{ .compatible = "microchip,emc2305", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
> +
>  static struct i2c_driver emc2305_driver = {
>  	.driver = {
>  		.name = "emc2305",
> +		.of_match_table = of_emc2305_match_table,
>  	},
>  	.probe = emc2305_probe,
>  	.remove	  = emc2305_remove,
> --
> 2.34.1
>


From conor at kernel.org  Tue Mar  4 08:29:53 2025
From: conor at kernel.org (Conor Dooley)
Date: Tue, 4 Mar 2025 16:29:53 +0000
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
Message-ID: <20250304-serving-stem-e059361db2b8@spud>

On Tue, Mar 04, 2025 at 06:21:34PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
>  1 file changed, 43 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..cac0075a65bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,43 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>
> +
> +description: |
> +  Microchip EMC2301/2/3/5 pwm controller which supports up
> +  to five programmable fan control circuits
> +
> +properties:
> +  compatible:
> +    enum:
> +      - microchip,emc2301
> +      - microchip,emc2302
> +      - microchip,emc2303
> +      - microchip,emc2305

Driver has no match data etc, suggesting all of these are compatible.
Please pick one as a fallback compatible.

> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg

Missing descriptions of the fans, no?
See max6639 for an example.

> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        emc2301: pwm at 2f {

The emc2301 label here can be dropped, it is not used.
The nodename should be "fan-controller", not pwm here I guess.

Cheers,
Conor.

> +            compatible = "microchip,emc2301";
> +            reg = <0x2f>;
> +        };
> +    };
> -- 
> 2.34.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/65dad026/attachment.sig>

From krzk at kernel.org  Tue Mar  4 08:32:50 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 17:32:50 +0100
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <880bac84-c593-44fa-a9dc-63462e1cee9d@kernel.org>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
 <20250304-serving-stem-e059361db2b8@spud>
 <880bac84-c593-44fa-a9dc-63462e1cee9d@kernel.org>
Message-ID: <fda24b29-3a86-484f-b674-e933d2fa3704@kernel.org>

On 04/03/2025 17:31, Krzysztof Kozlowski wrote:
> On 04/03/2025 17:29, Conor Dooley wrote:
>>> +properties:
>>> +  compatible:
>>> +    enum:
>>> +      - microchip,emc2301
>>> +      - microchip,emc2302
>>> +      - microchip,emc2303
>>> +      - microchip,emc2305
>>
>> Driver has no match data etc, suggesting all of these are compatible.
>> Please pick one as a fallback compatible.
>>
>>> +
>>> +  reg:
>>> +    maxItems: 1
>>> +
>>> +required:
>>> +  - compatible
>>> +  - reg
>>
>> Missing descriptions of the fans, no?
>> See max6639 for an example.
> 
> Yes and missing $ref to fan-controller schema.
About which I asked at v2...

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar  4 08:33:16 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 17:33:16 +0100
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
Message-ID: <d4282923-63e4-4f14-b5ee-5e8bf1973893@kernel.org>

On 04/03/2025 17:21, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++

I do not see improvements in the subject nor in missing $ref to common
schema for fans.

<form letter>
This is a friendly reminder during the review process.

It looks like you received a tag and forgot to add it.

If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Please read:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577

If a tag was not added on purpose, please state why and what changed.
</form letter>

Best regards,
Krzysztof


From Frank.li at nxp.com  Tue Mar  4 08:33:07 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:33:07 -0500
Subject: [PATCH v3 3/3] hwmon: emc2305: Use
 devm_thermal_of_cooling_device_register
In-Reply-To: <20250304162136.1963384-4-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-4-florin.leotescu@oss.nxp.com>
Message-ID: <Z8crKuVIF07oxsl+@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 06:21:36PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
>
> This prepares emc2305 driver to use configuration from Device Tree nodes.
> Using devm_thermal_of_cooling_device_register also simplifies cleanup
> procedure, so we are able to remove the emc2305_unset_tz and emc2305_remove
> functions which are no longer used.

Kernel doc suggest use imperative mode:

Prepare the emc2305 driver to use configuration from Device Tree nodes.
Switch to devm_thermal_of_cooling_device_register to simplify the cleanup
procedure, allowing the removal of emc2305_unset_tz and emc2305_remove, which
are no longer needed.

nice cleanup

Reviewed-by: Frank Li <Frank.Li at nxp.com>
>
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>  drivers/hwmon/emc2305.c | 28 +++-------------------------
>  1 file changed, 3 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
> index a236f27c75bc..5f3f06308826 100644
> --- a/drivers/hwmon/emc2305.c
> +++ b/drivers/hwmon/emc2305.c
> @@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
>  	"emc2305_fan5",
>  };
>
> -static void emc2305_unset_tz(struct device *dev);
> -
>  static int emc2305_get_max_channel(const struct emc2305_data *data)
>  {
>  	return data->pwm_num;
> @@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
>  	pwm = data->pwm_min[cdev_idx];
>
>  	data->cdev_data[cdev_idx].cdev =
> -		thermal_cooling_device_register(emc2305_fan_name[idx], data,
> -						&emc2305_cooling_ops);
> +		devm_thermal_of_cooling_device_register(dev, dev->of_node,
> +							emc2305_fan_name[idx], data,
> +							&emc2305_cooling_ops);
>
>  	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
>  		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
> @@ -337,21 +336,9 @@ static int emc2305_set_tz(struct device *dev)
>  	return 0;
>
>  thermal_cooling_device_register_fail:
> -	emc2305_unset_tz(dev);
>  	return ret;
>  }
>
> -static void emc2305_unset_tz(struct device *dev)
> -{
> -	struct emc2305_data *data = dev_get_drvdata(dev);
> -	int i;
> -
> -	/* Unregister cooling device. */
> -	for (i = 0; i < EMC2305_PWM_MAX; i++)
> -		if (data->cdev_data[i].cdev)
> -			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
> -}
> -
>  static umode_t
>  emc2305_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
>  {
> @@ -599,14 +586,6 @@ static int emc2305_probe(struct i2c_client *client)
>  	return 0;
>  }
>
> -static void emc2305_remove(struct i2c_client *client)
> -{
> -	struct device *dev = &client->dev;
> -
> -	if (IS_REACHABLE(CONFIG_THERMAL))
> -		emc2305_unset_tz(dev);
> -}
> -
>  static const struct of_device_id of_emc2305_match_table[] = {
>  	{ .compatible = "microchip,emc2301", },
>  	{ .compatible = "microchip,emc2302", },
> @@ -622,7 +601,6 @@ static struct i2c_driver emc2305_driver = {
>  		.of_match_table = of_emc2305_match_table,
>  	},
>  	.probe = emc2305_probe,
> -	.remove	  = emc2305_remove,
>  	.id_table = emc2305_ids,
>  };
>
> --
> 2.34.1
>


From james.quinlan at broadcom.com  Tue Mar  4 08:37:14 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Tue, 4 Mar 2025 11:37:14 -0500
Subject: [PATCH v2 6/8] PCI: brcmstb: Use same constant table for config
 space access
In-Reply-To: <20250304150838.23ca5qbhm4yrpa3h@thinkpad>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-7-james.quinlan@broadcom.com> <20250304150838.23ca5qbhm4yrpa3h@thinkpad>
Message-ID: <CA+-6iNzOWU1qLfmSiThdYXX0v5RkbUYtf52yk6KXm6yDDNRUnw@mail.gmail.com>

On Tue, Mar 4, 2025 at 10:08?AM Manivannan Sadhasivam
<manivannan.sadhasivam at linaro.org> wrote:
>
> On Fri, Feb 14, 2025 at 12:39:34PM -0500, Jim Quinlan wrote:
> > The constants EXT_CFG_DATA and EXT_CFG_INDEX vary by SOC. One of the
> > map_bus methods used these constants, the other used different constants.
> > Fortunately there was no problem because the SoCs that used the latter
> > map_bus method all had the same register constants.
> >
> > Remove the redundant constants and adjust the code to use them.  In
> > addition, update EXT_CFG_DATA to use the 4k-page based config space access
> > system, which is what the second map_bus method was already using.
> >
>
> What is the effect of this change? Why is it required? Sounds like it got
> sneaked in.

Hello,
There is no functional difference with this commit -- the code will
behave the same.  A previous commit set up the "EXT_CFG_DATA" and
"EXT_CFG_INDEX" constants in the offset table but one of the map_bus()
methods did not use them, instead it relied on old generic #define
constants.  This commit uses them and gets rid of the old #defines.

I didn't add a "Fixes" line because there is no functional change but
I can if you want.

Regards,
Jim Quinlan
Broadcom STB/CM

>
> > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > ---
> >  drivers/pci/controller/pcie-brcmstb.c | 14 ++++++--------
> >  1 file changed, 6 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > index e1059e3365bd..923ac1a03f85 100644
> > --- a/drivers/pci/controller/pcie-brcmstb.c
> > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > @@ -150,9 +150,6 @@
> >  #define  MSI_INT_MASK_SET            0x10
> >  #define  MSI_INT_MASK_CLR            0x14
> >
> > -#define PCIE_EXT_CFG_DATA                            0x8000
> > -#define PCIE_EXT_CFG_INDEX                           0x9000
> > -
> >  #define  PCIE_RGR1_SW_INIT_1_PERST_MASK                      0x1
> >  #define  PCIE_RGR1_SW_INIT_1_PERST_SHIFT             0x0
> >
> > @@ -727,8 +724,8 @@ static void __iomem *brcm_pcie_map_bus(struct pci_bus *bus,
> >
> >       /* For devices, write to the config space index register */
> >       idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0);
> > -     writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
> > -     return base + PCIE_EXT_CFG_DATA + PCIE_ECAM_REG(where);
> > +     writel(idx, base + IDX_ADDR(pcie));
> > +     return base + DATA_ADDR(pcie) + PCIE_ECAM_REG(where);
> >  }
> >
> >  static void __iomem *brcm7425_pcie_map_bus(struct pci_bus *bus,
> > @@ -1711,7 +1708,7 @@ static void brcm_pcie_remove(struct platform_device *pdev)
> >  static const int pcie_offsets[] = {
> >       [RGR1_SW_INIT_1]        = 0x9210,
> >       [EXT_CFG_INDEX]         = 0x9000,
> > -     [EXT_CFG_DATA]          = 0x9004,
> > +     [EXT_CFG_DATA]          = 0x8000,
> >       [PCIE_HARD_DEBUG]       = 0x4204,
> >       [PCIE_INTR2_CPU_BASE]   = 0x4300,
> >  };
> > @@ -1719,7 +1716,7 @@ static const int pcie_offsets[] = {
> >  static const int pcie_offsets_bcm7278[] = {
> >       [RGR1_SW_INIT_1]        = 0xc010,
> >       [EXT_CFG_INDEX]         = 0x9000,
> > -     [EXT_CFG_DATA]          = 0x9004,
> > +     [EXT_CFG_DATA]          = 0x8000,
> >       [PCIE_HARD_DEBUG]       = 0x4204,
> >       [PCIE_INTR2_CPU_BASE]   = 0x4300,
> >  };
> > @@ -1733,8 +1730,9 @@ static const int pcie_offsets_bcm7425[] = {
> >  };
> >
> >  static const int pcie_offsets_bcm7712[] = {
> > +     [RGR1_SW_INIT_1]        = 0x9210,
> >       [EXT_CFG_INDEX]         = 0x9000,
> > -     [EXT_CFG_DATA]          = 0x9004,
> > +     [EXT_CFG_DATA]          = 0x8000,
> >       [PCIE_HARD_DEBUG]       = 0x4304,
> >       [PCIE_INTR2_CPU_BASE]   = 0x4400,
> >  };
> > --
> > 2.43.0
> >
>
> --
> ????????? ????????
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4210 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/e855d16a/attachment.p7s>

From krzk at kernel.org  Tue Mar  4 08:31:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 4 Mar 2025 17:31:47 +0100
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <20250304-serving-stem-e059361db2b8@spud>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
 <20250304-serving-stem-e059361db2b8@spud>
Message-ID: <880bac84-c593-44fa-a9dc-63462e1cee9d@kernel.org>

On 04/03/2025 17:29, Conor Dooley wrote:
>> +properties:
>> +  compatible:
>> +    enum:
>> +      - microchip,emc2301
>> +      - microchip,emc2302
>> +      - microchip,emc2303
>> +      - microchip,emc2305
> 
> Driver has no match data etc, suggesting all of these are compatible.
> Please pick one as a fallback compatible.
> 
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +required:
>> +  - compatible
>> +  - reg
> 
> Missing descriptions of the fans, no?
> See max6639 for an example.

Yes and missing $ref to fan-controller schema.

Best regards,
Krzysztof


From james.quinlan at broadcom.com  Tue Mar  4 08:55:05 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Tue, 4 Mar 2025 11:55:05 -0500
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of regulator_bulk_get()
In-Reply-To: <20250304150313.ey4fky35bu6dbtxd@thinkpad>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com> <20250304150313.ey4fky35bu6dbtxd@thinkpad>
Message-ID: <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 10:03?AM Manivannan Sadhasivam
<manivannan.sadhasivam at linaro.org> wrote:
>
> On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > If regulator_bulk_get() returns an error, no regulators are created and we
> > need to set their number to zero.  If we do not do this and the PCIe
> > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> >
> > Also print out the error value, as we cannot return an error upwards as
> > Linux will WARN on an error from add_bus().
> >
> > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > ---
> >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > index e0b20f58c604..56b49d3cae19 100644
> > --- a/drivers/pci/controller/pcie-brcmstb.c
> > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> >
> >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> >               if (ret) {
> > -                     dev_info(dev, "No regulators for downstream device\n");
> > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
>
> Why is this dev_info() instead of dev_err()?

I will change this.
>
> > +                     pcie->sr = NULL;
>
> Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?

Not sure I understand -- it is already set before a  successful
regulator_bulk_get() call.
I set it to NULL after an unsuccessful result so the structure will
not be passed to subsequent calls.

Regards,
Jim Quinlan
Broadcom STB/CM

>
> - Mani
>
> --
> ????????? ????????
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4210 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/b77d2f53/attachment.p7s>

From tabba at google.com  Tue Mar  4 08:55:50 2025
From: tabba at google.com (Fuad Tabba)
Date: Tue, 4 Mar 2025 16:55:50 +0000
Subject: [PATCH 07/18] KVM: arm64: Compute FGT masks from KVM's own FGT tables
In-Reply-To: <20250210184150.2145093-8-maz@kernel.org>
References: <20250210184150.2145093-1-maz@kernel.org> <20250210184150.2145093-8-maz@kernel.org>
Message-ID: <CA+EHjTwm4CosWDGcaH_tnLU7zMNCq8twDyEcKd7-V0Lu7b-LcA@mail.gmail.com>

Hi Marc,

On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
>
> In the process of decoupling KVM's view of the FGT bits from the
> wider architectural state, use KVM's own FGT tables to build
> a synthitic view of what is actually known.

synthitic -> synthetic


> This allows for some checking along the way.
>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  arch/arm64/include/asm/kvm_arm.h  |   4 ++
>  arch/arm64/include/asm/kvm_host.h |  14 ++++
>  arch/arm64/kvm/emulate-nested.c   | 102 ++++++++++++++++++++++++++++++
>  3 files changed, 120 insertions(+)
>
> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> index 8d94a6c0ed5c4..e424085f2aaca 100644
> --- a/arch/arm64/include/asm/kvm_arm.h
> +++ b/arch/arm64/include/asm/kvm_arm.h
> @@ -359,6 +359,10 @@
>  #define __HAFGRTR_EL2_MASK     (GENMASK(49, 17) | GENMASK(4, 0))
>  #define __HAFGRTR_EL2_nMASK    ~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
>
> +/* Because the sysreg file mixes R and W... */
> +#define HFGRTR_EL2_RES0                HFGxTR_EL2_RES0 (0)
> +#define HFGWTR_EL2_RES0                (HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)

__HFGRTR_ONLY_MASK is a hand-crafted bitmask. The only bit remaining
in HFGxTR_EL2 that is RES0 is bit 51. If that were to be used as an
HFGRTR-only bit without __HFGRTR_ONLY_MASK getting updated, then
aggregate_fgt() below would set its bit in hfgwtr_masks. Could this be
a problem if this happens and the polarity of this bit ends up being
negative, thereby setting the corresponding nmask bit?

Cheers,
/fuad

> +
>  /* Similar definitions for HCRX_EL2 */
>  #define __HCRX_EL2_RES0         HCRX_EL2_RES0
>  #define __HCRX_EL2_MASK                (BIT(6))
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 7cfa024de4e34..4e67d4064f409 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -569,6 +569,20 @@ struct kvm_sysreg_masks {
>         } mask[NR_SYS_REGS - __SANITISED_REG_START__];
>  };
>
> +struct fgt_masks {
> +       const char      *str;
> +       u64             mask;
> +       u64             nmask;
> +       u64             res0;
> +};
> +
> +extern struct fgt_masks hfgrtr_masks;
> +extern struct fgt_masks hfgwtr_masks;
> +extern struct fgt_masks hfgitr_masks;
> +extern struct fgt_masks hdfgrtr_masks;
> +extern struct fgt_masks hdfgwtr_masks;
> +extern struct fgt_masks hafgrtr_masks;
> +
>  struct kvm_cpu_context {
>         struct user_pt_regs regs;       /* sp = sp_el0 */
>
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> index 607d37bab70b4..bbfe89c37a86e 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -2033,6 +2033,101 @@ static u32 encoding_next(u32 encoding)
>         return sys_reg(op0 + 1, 0, 0, 0, 0);
>  }
>
> +#define FGT_MASKS(__n, __m)                                            \
> +       struct fgt_masks __n = { .str = #__m, .res0 = __m, }
> +
> +FGT_MASKS(hfgrtr_masks, HFGRTR_EL2_RES0);
> +FGT_MASKS(hfgwtr_masks, HFGWTR_EL2_RES0);
> +FGT_MASKS(hfgitr_masks, HFGITR_EL2_RES0);
> +FGT_MASKS(hdfgrtr_masks, HDFGRTR_EL2_RES0);
> +FGT_MASKS(hdfgwtr_masks, HDFGWTR_EL2_RES0);
> +FGT_MASKS(hafgrtr_masks, HAFGRTR_EL2_RES0);
> +
> +static __init bool aggregate_fgt(union trap_config tc)
> +{
> +       struct fgt_masks *rmasks, *wmasks;
> +
> +       switch (tc.fgt) {
> +       case HFGxTR_GROUP:
> +               rmasks = &hfgrtr_masks;
> +               wmasks = &hfgwtr_masks;
> +               break;
> +       case HDFGRTR_GROUP:
> +               rmasks = &hdfgrtr_masks;
> +               wmasks = &hdfgwtr_masks;
> +               break;
> +       case HAFGRTR_GROUP:
> +               rmasks = &hafgrtr_masks;
> +               wmasks = NULL;
> +               break;
> +       case HFGITR_GROUP:
> +               rmasks = &hfgitr_masks;
> +               wmasks = NULL;
> +               break;
> +       }
> +
> +       /*
> +        * A bit can be reserved in either the R or W register, but
> +        * not both.
> +        */
> +       if ((BIT(tc.bit) & rmasks->res0) &&
> +           (!wmasks || (BIT(tc.bit) & wmasks->res0)))
> +               return false;
> +
> +       if (tc.pol)
> +               rmasks->mask |= BIT(tc.bit) & ~rmasks->res0;
> +       else
> +               rmasks->nmask |= BIT(tc.bit) & ~rmasks->res0;
> +
> +       if (wmasks) {
> +               if (tc.pol)
> +                       wmasks->mask |= BIT(tc.bit) & ~wmasks->res0;
> +               else
> +                       wmasks->nmask |= BIT(tc.bit) & ~wmasks->res0;
> +       }
> +
> +       return true;
> +}
> +
> +static __init int check_fgt_masks(struct fgt_masks *masks)
> +{
> +       unsigned long duplicate = masks->mask & masks->nmask;
> +       u64 res0 = masks->res0;
> +       int ret = 0;
> +
> +       if (duplicate) {
> +               int i;
> +
> +               for_each_set_bit(i, &duplicate, 64) {
> +                       kvm_err("%s[%d] bit has both polarities\n",
> +                               masks->str, i);
> +               }
> +
> +               ret = -EINVAL;
> +       }
> +
> +       masks->res0 = ~(masks->mask | masks->nmask);
> +       if (masks->res0 != res0)
> +               kvm_info("Implicit %s = %016llx, expecting %016llx\n",
> +                        masks->str, masks->res0, res0);
> +
> +       return ret;
> +}
> +
> +static __init int check_all_fgt_masks(int ret)
> +{
> +       int err = 0;
> +
> +       err |= check_fgt_masks(&hfgrtr_masks);
> +       err |= check_fgt_masks(&hfgwtr_masks);
> +       err |= check_fgt_masks(&hfgitr_masks);
> +       err |= check_fgt_masks(&hdfgrtr_masks);
> +       err |= check_fgt_masks(&hdfgwtr_masks);
> +       err |= check_fgt_masks(&hafgrtr_masks);
> +
> +       return ret ?: err;
> +}
> +
>  int __init populate_nv_trap_config(void)
>  {
>         int ret = 0;
> @@ -2097,8 +2192,15 @@ int __init populate_nv_trap_config(void)
>                         ret = xa_err(prev);
>                         print_nv_trap_error(fgt, "Failed FGT insertion", ret);
>                 }
> +
> +               if (!aggregate_fgt(tc)) {
> +                       ret = -EINVAL;
> +                       print_nv_trap_error(fgt, "FGT bit is reserved", ret);
> +               }
>         }
>
> +       ret = check_all_fgt_masks(ret);
> +
>         kvm_info("nv: %ld fine grained trap handlers\n",
>                  ARRAY_SIZE(encoding_to_fgt));
>
> --
> 2.39.2
>


From cwabbott0 at gmail.com  Tue Mar  4 08:56:48 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:48 -0500
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers
 directly
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>

In some cases drm/msm has to resume a stalled transaction directly in
its fault handler. Experimentally this doesn't work on SMMU500 if the
fault hasn't already been acknowledged by clearing FSR. Rather than
trying to clear FSR in msm's fault handler and implementing a
tricky handshake to avoid accidentally clearing FSR twice, we want to
clear FSR before calling the fault handlers, but this means that the
contents of registers can change underneath us in the fault handler and
msm currently uses a private function to read the register contents for
its own purposes in its fault handler, such as using the
implementation-defined FSYNR1 to determine which block caused the fault.
Fix this by making msm use the register values already read by arm-smmu
itself before clearing FSR rather than messing around with reading
registers directly.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
 drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
 drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
 3 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 6372f3e25c4bc24cb52f9233095170e8aa510a53..186d6ad4fd1c990398df4dec53f4d58ada9e658c 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -62,16 +62,15 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie,
 		struct adreno_smmu_fault_info *info)
 {
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
-	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-
-	info->fsr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSR);
-	info->fsynr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR0);
-	info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1);
-	info->far = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_FAR);
-	info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
-	info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0);
-	info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR);
+	struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
+
+	info->fsr = cfi->fsr;
+	info->fsynr0 = cfi->fsynr0;
+	info->fsynr1 = cfi->fsynr1;
+	info->far = cfi->iova;
+	info->cbfrsynra = cfi->cbfrsynra;
+	info->ttbr0 = cfi->ttbr0;
+	info->contextidr = cfi->contextidr;
 }
 
 static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index a9213e0f1579d1e3be0bfba75eea1d5de23117de..498b96e95cb4fdb67c246ef13de1eb8f40d68f7d 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -453,26 +453,26 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 {
-	struct arm_smmu_context_fault_info cfi;
 	struct arm_smmu_domain *smmu_domain = dev;
+	struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
 				      DEFAULT_RATELIMIT_BURST);
 	int idx = smmu_domain->cfg.cbndx;
 	int ret;
 
-	arm_smmu_read_context_fault_info(smmu, idx, &cfi);
+	arm_smmu_read_context_fault_info(smmu, idx, cfi);
 
-	if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
+	if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
-	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-		cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
+		cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
-		arm_smmu_print_context_fault_info(smmu, idx, &cfi);
+		arm_smmu_print_context_fault_info(smmu, idx, cfi);
 
-	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
+	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
 	ARM_SMMU_DOMAIN_NESTED,
 };
 
+struct arm_smmu_context_fault_info {
+	unsigned long iova;
+	u64 ttbr0;
+	u32 fsr;
+	u32 fsynr0;
+	u32 fsynr1;
+	u32 cbfrsynra;
+	u32 contextidr;
+};
+
 struct arm_smmu_domain {
 	struct arm_smmu_device		*smmu;
 	struct io_pgtable_ops		*pgtbl_ops;
@@ -380,6 +390,7 @@ struct arm_smmu_domain {
 	const struct iommu_flush_ops	*flush_ops;
 	struct arm_smmu_cfg		cfg;
 	enum arm_smmu_domain_stage	stage;
+	struct arm_smmu_context_fault_info cfi;
 	struct mutex			init_mutex; /* Protects smmu pointer */
 	spinlock_t			cb_lock; /* Serialises ATS1* ops and TLB syncs */
 	struct iommu_domain		domain;
@@ -541,16 +552,6 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
 void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
 int arm_mmu500_reset(struct arm_smmu_device *smmu);
 
-struct arm_smmu_context_fault_info {
-	unsigned long iova;
-	u64 ttbr0;
-	u32 fsr;
-	u32 fsynr0;
-	u32 fsynr1;
-	u32 cbfrsynra;
-	u32 contextidr;
-};
-
 void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
 				      struct arm_smmu_context_fault_info *cfi);
 

-- 
2.47.1



From cwabbott0 at gmail.com  Tue Mar  4 08:56:47 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:47 -0500
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>

This will be used by drm/msm for GPU page faults, replacing the manual
register reading it does.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
 drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
 drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
@@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
 
 	if (list_empty(&tbu_list)) {
 		ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-					 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+					 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 		if (ret == -ENOSYS)
 			arm_smmu_print_context_fault_info(smmu, idx, &cfi);
@@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
 	phys_soft = ops->iova_to_phys(ops, cfi.iova);
 
 	tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-				 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+				 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 	if (!tmp || tmp == -EBUSY) {
 		ret = IRQ_HANDLED;
 		resume = ARM_SMMU_RESUME_TERMINATE;
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
 				      struct arm_smmu_context_fault_info *cfi)
 {
 	cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
+	cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
 	cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
-	cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
+	cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
+	cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
 	cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
+	cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
 }
 
 void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
@@ -419,7 +422,7 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 {
 	dev_err(smmu->dev,
 		"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
-		cfi->fsr, cfi->iova, cfi->fsynr, cfi->cbfrsynra, idx);
+		cfi->fsr, cfi->iova, cfi->fsynr0, cfi->cbfrsynra, idx);
 
 	dev_err(smmu->dev, "FSR    = %08x [%s%sFormat=%u%s%s%s%s%s%s%s%s], SID=0x%x\n",
 		cfi->fsr,
@@ -437,15 +440,15 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 		cfi->cbfrsynra);
 
 	dev_err(smmu->dev, "FSYNR0 = %08x [S1CBNDX=%u%s%s%s%s%s%s PLVL=%u]\n",
-		cfi->fsynr,
-		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr),
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
-		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr));
+		cfi->fsynr0,
+		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr0),
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
+		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr0));
 }
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
@@ -464,7 +467,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 		return IRQ_NONE;
 
 	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-		cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+		cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
 		arm_smmu_print_context_fault_info(smmu, idx, &cfi);
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index e2aeb511ae903302e3c15d2cf5f22e2a26ac2346..d3bc77dcd4d40f25bc70f3289616fb866649b022 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -543,9 +543,12 @@ int arm_mmu500_reset(struct arm_smmu_device *smmu);
 
 struct arm_smmu_context_fault_info {
 	unsigned long iova;
+	u64 ttbr0;
 	u32 fsr;
-	u32 fsynr;
+	u32 fsynr0;
+	u32 fsynr1;
 	u32 cbfrsynra;
+	u32 contextidr;
 };
 
 void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,

-- 
2.47.1



From cwabbott0 at gmail.com  Tue Mar  4 08:56:51 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:51 -0500
Subject: [PATCH v4 5/5] drm/msm: Temporarily disable stall-on-fault after a
 page fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-5-be14be37f4c3@gmail.com>

When things go wrong, the GPU is capable of quickly generating millions
of faulting translation requests per second. When that happens, in the
stall-on-fault model each access will stall until it wins the race to
signal the fault and then the RESUME register is written. This slows
processing page faults to a crawl as the GPU can generate faults much
faster than the CPU can acknowledge them. It also means that all
available resources in the SMMU are saturated waiting for the stalled
transactions, so that other transactions such as transactions generated
by the GMU, which shares a context bank with the GPU, cannot proceed.
This causes a GMU watchdog timeout, which leads to a failed reset
because GX cannot collapse when there is a transaction pending and a
permanently hung GPU.

On older platforms with qcom,smmu-v2, it seems that when one transaction
is stalled subsequent faulting transactions are terminated, which avoids
this problem, but the MMU-500 follows the spec here.

To work around these problem, disable stall-on-fault as soon as we get a
page fault until a cooldown period after pagefaults stop. This allows
the GMU some guaranteed time to continue working. We only use
stall-on-fault to halt the GPU while we collect a devcoredump and we
always terminate the transaction afterward, so it's fine to miss some
subsequent page faults. We also keep it disabled so long as the current
devcoredump hasn't been deleted, because in that case we likely won't
capture another one if there's a fault.

After this commit HFI messages still occasionally time out, because the
crashdump handler doesn't run fast enough to let the GMU resume, but the
driver seems to recover from it. This will probably go away after the
HFI timeout is increased.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  4 ++++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 42 ++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h | 24 +++++++++++++++++++
 drivers/gpu/drm/msm/msm_iommu.c         |  9 +++++++
 drivers/gpu/drm/msm/msm_mmu.h           |  1 +
 6 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 71dca78cd7a5324e9ff5b14f173e2209fa42e196..670141531112c9d29cef8ef1fd51b74759fdd6d2 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
 		ring->cur_ctx_seqno = 0;
 		a5xx_submit_in_rb(gpu, submit);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 0ae29a7c8a4d3f74236a35cc919f69d5c0a384a0..5a34cd2109a2d74c92841448a61ccb0d4f34e264 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -212,6 +212,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	a6xx_set_pagetable(a6xx_gpu, ring, submit);
 
 	get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
@@ -335,6 +337,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	/*
 	 * Toggle concurrent binning for pagetable switch and set the thread to
 	 * BR since only it can execute the pagetable switch packets.
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 1238f326597808eb28b4c6822cbd41a26e555eb9..bac586101dc0494f46b069a8440a45825dfe9b5e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -246,16 +246,53 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
 	return SZ_4G;
 }
 
+void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
+{
+	struct msm_gpu *gpu = &adreno_gpu->base;
+	unsigned long flags;
+
+	/*
+	 * Wait until the cooldown period has passed and we would actually
+	 * collect a crashdump to re-enable stall-on-fault.
+	 */
+	spin_lock_irqsave(&adreno_gpu->fault_stall_lock, flags);
+	if (!adreno_gpu->stall_enabled &&
+			ktime_after(ktime_get(), adreno_gpu->stall_reenable_time) &&
+			!READ_ONCE(gpu->crashstate)) {
+		adreno_gpu->stall_enabled = true;
+
+		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
+	}
+	spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, flags);
+}
+
 #define ARM_SMMU_FSR_TF                 BIT(1)
 #define ARM_SMMU_FSR_PF			BIT(3)
 #define ARM_SMMU_FSR_EF			BIT(4)
+#define ARM_SMMU_FSR_SS			BIT(30)
 
 int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
 			 struct adreno_smmu_fault_info *info, const char *block,
 			 u32 scratch[4])
 {
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
 	const char *type = "UNKNOWN";
-	bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
+	bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
+		!READ_ONCE(gpu->crashstate);
+	unsigned long irq_flags;
+
+	/*
+	 * In case there is a subsequent storm of pagefaults, disable
+	 * stall-on-fault for at least half a second.
+	 */
+	spin_lock_irqsave(&adreno_gpu->fault_stall_lock, irq_flags);
+	if (adreno_gpu->stall_enabled) {
+		adreno_gpu->stall_enabled = false;
+
+		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
+	}
+	adreno_gpu->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
+	spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, irq_flags);
 
 	/*
 	 * If we aren't going to be resuming later from fault_worker, then do
@@ -1143,6 +1180,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 		adreno_gpu->info->inactive_period);
 	pm_runtime_use_autosuspend(dev);
 
+	spin_lock_init(&adreno_gpu->fault_stall_lock);
+	adreno_gpu->stall_enabled = true;
+
 	return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
 			gpu_name, &adreno_gpu_config);
 }
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index dcf454629ce037b2a8274a6699674ad754ce1f07..a528036b46216bd898f6d48c5fb0555c4c4b053b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -205,6 +205,28 @@ struct adreno_gpu {
 	/* firmware: */
 	const struct firmware *fw[ADRENO_FW_MAX];
 
+	/**
+	 * fault_stall_lock:
+	 *
+	 * Serialize changes to stall-on-fault state.
+	 */
+	spinlock_t fault_stall_lock;
+
+	/**
+	 * fault_stall_reenable_time:
+	 *
+	 * if stall_enabled is false, when to reenable stall-on-fault.
+	 */
+	ktime_t stall_reenable_time;
+
+	/**
+	 * stall_enabled:
+	 *
+	 * Whether stall-on-fault is currently enabled.
+	 */
+	bool stall_enabled;
+
+
 	struct {
 		/**
 		 * @rgb565_predicator: Unknown, introduced with A650 family,
@@ -629,6 +651,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
 			 struct adreno_smmu_fault_info *info, const char *block,
 			 u32 scratch[4]);
 
+void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
+
 int adreno_read_speedbin(struct device *dev, u32 *speedbin);
 
 /*
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 2a94e82316f95c5f9dcc37ef0a4664a29e3492b2..8d5380e6dcc217c7c209b51527bf15748b3ada71 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -351,6 +351,14 @@ static void msm_iommu_resume_translation(struct msm_mmu *mmu)
 		adreno_smmu->resume_translation(adreno_smmu->cookie, true);
 }
 
+static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
+{
+	struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
+
+	if (adreno_smmu->set_stall)
+		adreno_smmu->set_stall(adreno_smmu->cookie, enable);
+}
+
 static void msm_iommu_detach(struct msm_mmu *mmu)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
@@ -399,6 +407,7 @@ static const struct msm_mmu_funcs funcs = {
 		.unmap = msm_iommu_unmap,
 		.destroy = msm_iommu_destroy,
 		.resume_translation = msm_iommu_resume_translation,
+		.set_stall = msm_iommu_set_stall,
 };
 
 struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 88af4f490881f2a6789ae2d03e1c02d10046331a..2694a356a17904e7572b767b16ed0cee806406cf 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -16,6 +16,7 @@ struct msm_mmu_funcs {
 	int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
 	void (*destroy)(struct msm_mmu *mmu);
 	void (*resume_translation)(struct msm_mmu *mmu);
+	void (*set_stall)(struct msm_mmu *mmu, bool enable);
 };
 
 enum msm_mmu_type {

-- 
2.47.1



From cwabbott0 at gmail.com  Tue Mar  4 08:56:50 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:50 -0500
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>

Up until now we have only called the set_stall callback during
initialization when the device is off. But we will soon start calling it
to temporarily disable stall-on-fault when the device is on, so handle
that by checking if the device is on and writing SCTLR.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
 {
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
 	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
+	u32 mask = BIT(cfg->cbndx);
+	bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
+	unsigned long flags;
 
 	if (enabled)
-		qsmmu->stall_enabled |= BIT(cfg->cbndx);
+		qsmmu->stall_enabled |= mask;
 	else
-		qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
+		qsmmu->stall_enabled &= ~mask;
+
+	/*
+	 * If the device is on and we changed the setting, update the register.
+	 */
+	if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
+		spin_lock_irqsave(&smmu_domain->cb_lock, flags);
+
+		u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
+
+		if (enabled)
+			reg |= ARM_SMMU_SCTLR_CFCFG;
+		else
+			reg &= ~ARM_SMMU_SCTLR_CFCFG;
+
+		arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
+
+		spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
+
+		pm_runtime_put_autosuspend(smmu->dev);
+	}
 }
 
 static void qcom_adreno_smmu_resume_translation(const void *cookie, bool terminate)

-- 
2.47.1



From cwabbott0 at gmail.com  Tue Mar  4 08:56:49 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:49 -0500
Subject: [PATCH v4 3/5] iommu/arm-smmu: Fix spurious interrupts with
 stall-on-fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-3-be14be37f4c3@gmail.com>

On some SMMUv2 implementations, including MMU-500, SMMU_CBn_FSR.SS
asserts an interrupt. The only way to clear that bit is to resume the
transaction by writing SMMU_CBn_RESUME, but typically resuming the
transaction requires complex operations (copying in pages, etc.) that
can't be done in IRQ context. drm/msm already has a problem, because
its fault handler sometimes schedules a job to dump the GPU state and
doesn't resume translation until this is complete.

Work around this by disabling context fault interrupts until after the
transaction is resumed. Because other context banks can share an IRQ
line, we may still get an interrupt intended for another context bank,
but in this case only SMMU_CBn_FSR.SS will be asserted and we can skip
it assuming that interrupts are disabled which is accomplished by
removing the bit from ARM_SMMU_CB_FSR_FAULT. SMMU_CBn_FSR.SS won't be
asserted unless an external user enabled stall-on-fault, and they are
expected to resume the translation and re-enable interrupts.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 15 ++++++++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.c      | 41 +++++++++++++++++++++++++++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.h      |  1 -
 3 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 186d6ad4fd1c990398df4dec53f4d58ada9e658c..a428e53add08d451fb2152e3ab80e0fba936e214 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -90,12 +90,25 @@ static void qcom_adreno_smmu_resume_translation(const void *cookie, bool termina
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
 	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	u32 reg = 0;
+	u32 reg = 0, sctlr;
+	unsigned long flags;
 
 	if (terminate)
 		reg |= ARM_SMMU_RESUME_TERMINATE;
 
+	spin_lock_irqsave(&smmu_domain->cb_lock, flags);
+
 	arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg);
+
+	/*
+	 * Re-enable interrupts after they were disabled by
+	 * arm_smmu_context_fault().
+	 */
+	sctlr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
+	sctlr |= ARM_SMMU_SCTLR_CFIE;
+	arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, sctlr);
+
+	spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
 }
 
 #define QCOM_ADRENO_SMMU_GPU_SID 0
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 498b96e95cb4fdb67c246ef13de1eb8f40d68f7d..284079ef95cd2deeb71816a284850523897badd8 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -466,13 +466,52 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 	if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
+	/*
+	 * On some implementations FSR.SS asserts a context fault
+	 * interrupt. We do not want this behavior, because resolving the
+	 * original context fault typically requires operations that cannot be
+	 * performed in IRQ context but leaving the stall unacknowledged will
+	 * immediately lead to another spurious interrupt as FSR.SS is still
+	 * set. Work around this by disabling interrupts for this context bank.
+	 * It's expected that interrupts are re-enabled after resuming the
+	 * translation.
+	 *
+	 * We have to do this before report_iommu_fault() so that we don't
+	 * leave interrupts disabled in case the downstream user decides the
+	 * fault can be resolved inside its fault handler.
+	 *
+	 * There is a possible race if there are multiple context banks sharing
+	 * the same interrupt and both signal an interrupt in between writing
+	 * RESUME and SCTLR. We could disable interrupts here before we
+	 * re-enable them in the resume handler, leaving interrupts enabled.
+	 * Lock the write to serialize it with the resume handler.
+	 */
+	if (cfi->fsr & ARM_SMMU_CB_FSR_SS) {
+		u32 val;
+
+		spin_lock(&smmu_domain->cb_lock);
+		val = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_SCTLR);
+		val &= ~ARM_SMMU_SCTLR_CFIE;
+		arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, val);
+		spin_unlock(&smmu_domain->cb_lock);
+	}
+
+	/*
+	 * The SMMUv2 architecture specification says that if stall-on-fault is
+	 * enabled the correct sequence is to write to SMMU_CBn_FSR to clear
+	 * the fault and then write to SMMU_CBn_RESUME. Clear the interrupt
+	 * first before running the user's fault handler to make sure we follow
+	 * this sequence. It should be ok if there is another fault in the
+	 * meantime because we have already read the fault info.
+	 */
+	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
+
 	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
 		cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
 		arm_smmu_print_context_fault_info(smmu, idx, cfi);
 
-	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index 411d807e0a7033833716635efb3968a0bd3ff237..4235b772c2cb032778816578c9e6644512543a5e 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -214,7 +214,6 @@ enum arm_smmu_cbar_type {
 					 ARM_SMMU_CB_FSR_TLBLKF)
 
 #define ARM_SMMU_CB_FSR_FAULT		(ARM_SMMU_CB_FSR_MULTI |	\
-					 ARM_SMMU_CB_FSR_SS |		\
 					 ARM_SMMU_CB_FSR_UUT |		\
 					 ARM_SMMU_CB_FSR_EF |		\
 					 ARM_SMMU_CB_FSR_PF |		\

-- 
2.47.1



From cwabbott0 at gmail.com  Tue Mar  4 08:56:46 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 04 Mar 2025 11:56:46 -0500
Subject: [PATCH v4 0/5] iommu/arm-smmu, drm/msm: Fixes for stall-on-fault
Message-ID: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>

drm/msm uses the stall-on-fault model to record the GPU state on the
first GPU page fault to help debugging. On systems where the GPU is
paired with a MMU-500, there were two problems:

1. The MMU-500 doesn't de-assert its interrupt line until the fault is
   resumed, which led to a storm of interrupts until the fault handler
   was called. If we got unlucky and the fault handler was on the same
   CPU as the interrupt, there was a deadlock.
2. The GPU is capable of generating page faults much faster than we can
   resume them. GMU (GPU Management Unit) shares the same context bank
   as the GPU, so if there was a sudden spurt of page faults it would be
   effectively starved and would trigger a watchdog reset, made even
   worse because the GPU cannot be reset while there's a pending
   transaction leaving the GPU permanently wedged.

Patches 1-3 fixes the first problem and is independent of the rest of the
series. Patch 5 fixes the second problem and is dependent on patch 4, so
there will have to be some cross-tree coordination.

I've rebased this series on the latest linux-next to avoid rebase
troubles.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
Changes in v4:
- Add patches 1-2, which fix reading registers in drm/msm when
  acknowledging the fault early. This was Robin's preferred solution
  compared to making drm/msm's fault handler tell arm-smmu to resume the
  fault.
- Link to v3: https://lore.kernel.org/r/20250122-msm-gpu-fault-fixes-next-v3-0-0afa00158521 at gmail.com

Changes in v3:
- Acknowledge the fault before resuming the transaction in patch 1.
- Add suggested extra context to commit messages.
- Link to v2: https://lore.kernel.org/r/20250120-msm-gpu-fault-fixes-next-v2-0-d636c4027042 at gmail.com

Changes in v2:
- Remove unnecessary _irqsave when locking in IRQ handler (Robin)
- Reuse existing spinlock for CFIE manipulation (Robin)
- Lock CFCFG manipulation against concurrent CFIE manipulation
- Don't use timer to re-enable stall-on-fault. (Rob)
- Use more descriptive name for the function that re-enables
  stall-on-fault if the cooldown period has ended. (Rob)
- Link to v1: https://lore.kernel.org/r/20250117-msm-gpu-fault-fixes-next-v1-0-bc9b332b5d0b at gmail.com

---
Connor Abbott (5):
      iommu/arm-smmu: Save additional information on context fault
      iommu/arm-smmu-qcom: Don't read fault registers directly
      iommu/arm-smmu: Fix spurious interrupts with stall-on-fault
      iommu/arm-smmu-qcom: Make set_stall work when the device is on
      drm/msm: Temporarily disable stall-on-fault after a page fault

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c            |  2 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c            |  4 ++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c          | 42 ++++++++++++-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h          | 24 ++++++++
 drivers/gpu/drm/msm/msm_iommu.c                  |  9 +++
 drivers/gpu/drm/msm/msm_mmu.h                    |  1 +
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c       | 64 ++++++++++++++-----
 drivers/iommu/arm/arm-smmu/arm-smmu.c            | 78 ++++++++++++++++++------
 drivers/iommu/arm/arm-smmu/arm-smmu.h            | 19 +++---
 10 files changed, 204 insertions(+), 43 deletions(-)
---
base-commit: 866e43b945bf98f8e807dfa45eca92f931f3a032
change-id: 20250117-msm-gpu-fault-fixes-next-96e3098023e1

Best regards,
-- 
Connor Abbott <cwabbott0 at gmail.com>



From manivannan.sadhasivam at linaro.org  Tue Mar  4 08:58:08 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 22:28:08 +0530
Subject: [PATCH v2 6/8] PCI: brcmstb: Use same constant table for config
 space access
In-Reply-To: <CA+-6iNzOWU1qLfmSiThdYXX0v5RkbUYtf52yk6KXm6yDDNRUnw@mail.gmail.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-7-james.quinlan@broadcom.com>
 <20250304150838.23ca5qbhm4yrpa3h@thinkpad>
 <CA+-6iNzOWU1qLfmSiThdYXX0v5RkbUYtf52yk6KXm6yDDNRUnw@mail.gmail.com>
Message-ID: <20250304165808.t46fh6fwpardheup@thinkpad>

On Tue, Mar 04, 2025 at 11:37:14AM -0500, Jim Quinlan wrote:
> On Tue, Mar 4, 2025 at 10:08?AM Manivannan Sadhasivam
> <manivannan.sadhasivam at linaro.org> wrote:
> >
> > On Fri, Feb 14, 2025 at 12:39:34PM -0500, Jim Quinlan wrote:
> > > The constants EXT_CFG_DATA and EXT_CFG_INDEX vary by SOC. One of the
> > > map_bus methods used these constants, the other used different constants.
> > > Fortunately there was no problem because the SoCs that used the latter
> > > map_bus method all had the same register constants.
> > >
> > > Remove the redundant constants and adjust the code to use them.  In
> > > addition, update EXT_CFG_DATA to use the 4k-page based config space access
> > > system, which is what the second map_bus method was already using.
> > >
> >
> > What is the effect of this change? Why is it required? Sounds like it got
> > sneaked in.
> 
> Hello,
> There is no functional difference with this commit -- the code will
> behave the same.  A previous commit set up the "EXT_CFG_DATA" and
> "EXT_CFG_INDEX" constants in the offset table but one of the map_bus()
> methods did not use them, instead it relied on old generic #define
> constants.  This commit uses them and gets rid of the old #defines.
> 

My comment was about the change that modified the offset of EXT_CFG_DATA. This
was not justified properly.

- Mani

-- 
????????? ????????


From Frank.li at nxp.com  Tue Mar  4 08:10:01 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 11:10:01 -0500
Subject: [PATCH v3 4/6] arm64: dts: imx93: Add LCDIF & LDB nodes
In-Reply-To: <20250304154929.1785200-5-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-5-alexander.stein@ew.tq-group.com>
Message-ID: <Z8cl2bwpYFiS2lnr@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 04:49:23PM +0100, Alexander Stein wrote:
> LCDIF port 1 is directly attached to the LVDS Display Bridge (LDB).
> Both need the same clock source (VIDEO_PLL1).
>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
>  arch/arm64/boot/dts/freescale/imx93.dtsi | 77 ++++++++++++++++++++++++
>  1 file changed, 77 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
> index 56766fdb0b1e5..69a639a8c833f 100644
> --- a/arch/arm64/boot/dts/freescale/imx93.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
> @@ -1273,6 +1273,9 @@ s4muap: mailbox at 47520000 {
>  		media_blk_ctrl: system-controller at 4ac10000 {
>  			compatible = "fsl,imx93-media-blk-ctrl", "syscon";
>  			reg = <0x4ac10000 0x10000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			ranges = <0x0 0x4ac10000 0x10000>;

I remember ranges should be after reg.

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>  			power-domains = <&mediamix>;
>  			clocks = <&clk IMX93_CLK_MEDIA_APB>,
>  				 <&clk IMX93_CLK_MEDIA_AXI>,
> @@ -1286,8 +1289,82 @@ media_blk_ctrl: system-controller at 4ac10000 {
>  				 <&clk IMX93_CLK_MIPI_DSI_GATE>;
>  			clock-names = "apb", "axi", "nic", "disp", "cam",
>  				      "pxp", "lcdif", "isi", "csi", "dsi";
> +			assigned-clocks = <&clk IMX93_CLK_MEDIA_AXI>,
> +					  <&clk IMX93_CLK_MEDIA_APB>,
> +					  <&clk IMX93_CLK_VIDEO_PLL>,
> +					  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
> +			assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD0>,
> +						 <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>,
> +						 <&clk IMX93_CLK_24M>,
> +						 <&clk IMX93_CLK_VIDEO_PLL>;
> +			assigned-clock-rates = <333333333>, <133333333>, <0>, <200000000>;
>  			#power-domain-cells = <1>;
>  			status = "disabled";
> +
> +			lvds_bridge: bridge at 20 {
> +				compatible = "fsl,imx93-ldb";
> +				reg = <0x20 0x4>, <0x24 0x4>;
> +				reg-names = "ldb", "lvds";
> +				clocks = <&clk IMX93_CLK_LVDS_GATE>;
> +				clock-names = "ldb";
> +				assigned-clocks = <&clk IMX93_CLK_MEDIA_LDB>;
> +				assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
> +				status = "disabled";
> +
> +				ports {
> +					#address-cells = <1>;
> +					#size-cells = <0>;
> +
> +					port at 0 {
> +						reg = <0>;
> +
> +						ldb_from_lcdif: endpoint {
> +							remote-endpoint = <&lcdif_to_ldb>;
> +						};
> +					};
> +
> +					port at 1 {
> +						reg = <1>;
> +
> +						ldb_lvds: endpoint {
> +						};
> +					};
> +				};
> +			};
> +		};
> +
> +		lcdif: display-controller at 4ae30000 {
> +			compatible = "fsl,imx93-lcdif";
> +			reg = <0x4ae30000 0x23c>;
> +			interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&clk IMX93_CLK_MEDIA_DISP_PIX>,
> +				 <&clk IMX93_CLK_LCDIF_GATE>,
> +				 <&clk IMX93_CLK_MEDIA_AXI>;
> +			clock-names = "pix", "axi", "disp_axi";
> +			assigned-clocks = <&clk IMX93_CLK_VIDEO_PLL>,
> +					  <&clk IMX93_CLK_MEDIA_DISP_PIX>;
> +			assigned-clock-parents = <&clk IMX93_CLK_24M>,
> +						 <&clk IMX93_CLK_VIDEO_PLL>;
> +			power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_LCDIF>;
> +			status = "disabled";
> +
> +			port {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				lcdif_to_dsi: endpoint at 0 {
> +					reg = <0>;
> +				};
> +
> +				lcdif_to_ldb: endpoint at 1 {
> +					reg = <1>;
> +					remote-endpoint = <&ldb_from_lcdif>;
> +				};
> +
> +				lcdif_to_dpi: endpoint at 2 {
> +					reg = <2>;
> +				};
> +			};
>  		};
>
>  		usbotg1: usb at 4c100000 {
> --
> 2.43.0
>


From suzuki.poulose at arm.com  Tue Mar  4 08:10:58 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 4 Mar 2025 16:10:58 +0000
Subject: [PATCH v15 04/10] Coresight: Introduce a new struct
 coresight_path
In-Reply-To: <20250303032931.2500935-5-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-5-quic_jiegan@quicinc.com>
Message-ID: <4e0959e7-cb66-41f1-b686-a274b6cbfd2e@arm.com>

On 03/03/2025 03:29, Jie Gan wrote:
> Introduce a new strcuture, 'struct coresight_path', to store the data that
> utilized by the devices in the path. The coresight_path will be built/released
> by coresight_build_path/coresight_release_path functions.
> 
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c  | 16 +++++-----
>   .../hwtracing/coresight/coresight-etm-perf.c  | 30 ++++++++++---------
>   .../hwtracing/coresight/coresight-etm-perf.h  |  2 +-
>   drivers/hwtracing/coresight/coresight-priv.h  |  6 ++--
>   drivers/hwtracing/coresight/coresight-sysfs.c | 12 ++++----
>   include/linux/coresight.h                     | 10 +++++++
>   6 files changed, 44 insertions(+), 32 deletions(-)
> 

...

> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index ce9a5e71b261..67cf8bdbe5c0 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -329,6 +329,16 @@ static struct coresight_dev_list (var) = {				\
>   
>   #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
>   
> +/**
> + * struct coresight_path - data needed by enable/disable path
> + * @path:              path from source to sink.

This doesn't match the actual variable below.

> + * @trace_id:          trace_id of the whole path.
> + */
> +struct coresight_path {
> +	struct list_head	path_list;
> +	u8			trace_id;
> +};
> +
>   enum cs_mode {
>   	CS_MODE_DISABLED,
>   	CS_MODE_SYSFS,

Suzuki


From laurentiumihalcea111 at gmail.com  Tue Mar  4 08:11:55 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 4 Mar 2025 18:11:55 +0200
Subject: [PATCH 4/5] arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
In-Reply-To: <20250228101952.g6tae3ni5xrhjk3y@pengutronix.de>
References: <20250221191909.31874-1-laurentiumihalcea111@gmail.com>
 <20250221191909.31874-5-laurentiumihalcea111@gmail.com>
 <Z7jahtO3bxjkMfnc@lizhi-Precision-Tower-5810>
 <cd6a84cd-ff17-45df-becc-9bfc74522f73@gmail.com>
 <20250227-monumental-whale-of-security-b1c84e-mkl@pengutronix.de>
 <Z8CWsI/DKZtDBkzE@lizhi-Precision-Tower-5810>
 <20250228101952.g6tae3ni5xrhjk3y@pengutronix.de>
Message-ID: <bfe3c719-f1c5-4ae5-9a40-45ad75cd5855@gmail.com>



On 2/28/2025 12:19 PM, Marco Felsch wrote:
> Hi,
>
> On 25-02-27, Frank Li wrote:
>> On Thu, Feb 27, 2025 at 11:57:54AM +0100, Marc Kleine-Budde wrote:
>>> On 25.02.2025 16:14:34, Mihalcea Laurentiu wrote:
>>>> On 21.02.2025 21:56, Frank Li wrote:
>>>>> On Fri, Feb 21, 2025 at 02:19:08PM -0500, Laurentiu Mihalcea wrote:
>>>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>>>>
>>>>>> AIPS5 is actually AIPSTZ5 as it offers some security-related
>>>>>> configurations. Since these configurations need to be applied before
>>>>>> accessing any of the peripherals on the bus, it's better to make AIPSTZ5
>>>>>> be their parent instead of keeping AIPS5 and adding a child node for
>>>>>> AIPSTZ5. Also, because of the security configurations, the address space
>>>>>> of the bus has to be changed to that of the configuration registers.
>>>>> The orginal 0x30c0_0000..0x31200000 include 0x30df0000, why not map only
>>>>> config address part in your drivers.
>>>>>
>>>>> Frank
>>>> Any concerns/anything wrong with current approach?
>>>>
>>>>
>>>> I find it a bit awkward to have the whole bus address space
>>>> in the DT given that we're only interested in using the access
>>>> controller register space.
>>>>
>>>>
>>>> I'm fine with the approach you suggested but I don't see a
>>>> reason for using it?
>>> Looking at the "AIPS5 Memory Map" (page 34/35 in i.MX 8M Plus
>>> Applications Processor Reference Manual, Rev. 3, 08/2024), the
>>> AIPS5_Configuration is part of the AIPS5 bus. IMHO the bus is something
>>> different than the bus configuration. Why not model it as part of the
>>> bus?
>>>
>>>>>> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>> index e0d3b8cba221..a1d9b834d2da 100644
>>>>>> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>> @@ -1399,11 +1399,13 @@ eqos: ethernet at 30bf0000 {
>>>>>>  			};
>>>>>>  		};
>>>>>>
>>>>>> -		aips5: bus at 30c00000 {
>>>>>> -			compatible = "fsl,aips-bus", "simple-bus";
>>>>>> -			reg = <0x30c00000 0x400000>;
>>>>>> +		aips5: bus at 30df0000 {
>>>                        ^^^^^^^^^^^^
>>>>>> +			compatible = "fsl,imx8mp-aipstz", "simple-bus";
>>>>>> +			reg = <0x30df0000 0x10000>;
>>>>>> +			power-domains = <&pgc_audio>;
>>>>>>  			#address-cells = <1>;
>>>>>>  			#size-cells = <1>;
>>>>>> +			#access-controller-cells = <0>;
>>>>>>  			ranges;
>>>>>>
>>>>>>  			spba-bus at 30c00000 {
>>>                         ^^^^^^^^^^^^^^^^^
>>>
>>> This looks very strange: The aips5 bus starts at 0x30df0000 and has a
>>> child bus starting at 0x30c00000?
>> @30df0000 should match controller reg's address.
>>
>> subnode address 0x30c00000,  should be descript in "ranges", which 1:1 map.
>>
>> So it should be reasonable. another example:
>> i2c at 1000 {
>>
>> 	device at 1c <- which use difference address space.
>> }
>>
>> The similar case also happen at pcie.
> I'm not really convinced that pcie and i2c are good examples here. I2C
> does have an other addressing scheme by nature and the hotplug-able pcie
> is dependeds on the pcie device memory map of course.
>
> Here we're talking about an access control IP core on a bus which is
> static.
>
> But.. it looks like from DT abstraction it's fine because STM did
> something similiar with their st,stm32mp25-rifsc or st,stm32-etzpc
> albeit it does look strange and I don't know why we have to limit the
> address space since it was already mapped but used by the fsl,aips-bus
> driver.
>
> Regards,
>   Marco

The address space of the bridge was changed to that of the bridge's configuration
space because I think it's very awkward from the software's point of view to have
to hardcode the offset and size of the configuration space inside the driver. I also
looked at what STM did with "st,stm32-etzpc" so I thought this would be acceptable
from the DT's POV.

Regarding why I chose not to model the access controller part as a subnode of the
bus:

??? 1) The access controller is part of the bridge itself (not a separate module accessible
? ? via the bridge like it's the case for its children) so I think the current approach
??? should also make sense if we take the hardware into consideration.

??? 2) The access controller configuration also impacts the AP. As such, we needed a way to
??? enforce a dependency between the children of the aips5 bus and the access controller
??? (we could have used the 'access-controllers' property like we did with the DSP but having
??? to do that for all children of the bus is not ideal I'd say.

Of course, argument no. 2 is somewhat brittle in the context of i.MX8MP as the reset
values of the AC's registers already allow the AP to access said peripherals. Despite this,
I think the current approach would be more scalable given that the IP offers some more
configuration bits which we might want to toggle. For that to work, we need to make sure
the bits are toggled before the AP accesses the peripherals on the bridge.


Note that we don't do this for aips1-aips4 because it's really not needed. If I'm not mistaken,
they're not really attached to a PD so we don't need to re-configure them each time the domain
is power cycled (which is why we can just do it once from ATF during the boot process)
??


From robh at kernel.org  Tue Mar  4 09:03:13 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 11:03:13 -0600
Subject: [PATCH v2 1/3] arm64: dts: ti: k3-j721e-evm: Add overlay for PCIe
 NTB functionality
In-Reply-To: <20250226124245.9856-2-s-vadapalli@ti.com>
References: <20250226124245.9856-1-s-vadapalli@ti.com> <20250226124245.9856-2-s-vadapalli@ti.com>
Message-ID: <CAL_JsqKDMecB3dD2oU2MJo-_8G66K-mVTfNKWUBuL-=_tWpjtw@mail.gmail.com>

On Wed, Feb 26, 2025 at 6:43?AM Siddharth Vadapalli <s-vadapalli at ti.com> wrote:
>
> PCIe NTB (Non-Transparent-Bridge) allows connecting the memory of
> multiple PCIe Hosts (Root-Complex). The number of such hosts is
> determined by the number of PCIe instances configured for NTB operation
> on the device which intends to enable NTB functionality. Add a device-tree
> overlay to configure PCIE0 and PCIE1 instances of PCIe on J721E EVM for NTB
> operation. This shall allow connecting the memory of two PCIe Hosts via
> PCIE0 and PCIE1 on J721E EVM.
>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> ---
>
> v1:
> https://patchwork.kernel.org/project/linux-arm-kernel/patch/20250202093636.2699064-2-s-vadapalli at ti.com/
> Changes since v1:
> - s/epf_bus/epf-bus since node names shouldn't contain underscores.
>
> Regards,
> Siddharth.
>
>  arch/arm64/boot/dts/ti/Makefile               |  4 +
>  .../boot/dts/ti/k3-j721e-evm-pcie-ntb.dtso    | 91 +++++++++++++++++++
>  2 files changed, 95 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/ti/k3-j721e-evm-pcie-ntb.dtso
>
> diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
> index 8a4bdf87e2d4..1097ab30f5a9 100644
> --- a/arch/arm64/boot/dts/ti/Makefile
> +++ b/arch/arm64/boot/dts/ti/Makefile
> @@ -102,6 +102,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64.dtb
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-common-proc-board-infotainment.dtbo
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm.dtb
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-gesi-exp-board.dtbo
> +dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-pcie-ntb.dtbo
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-pcie0-ep.dtbo
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-pcie1-ep.dtbo
>  dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk.dtb
> @@ -201,6 +202,8 @@ k3-j7200-evm-pcie1-ep-dtbs := k3-j7200-common-proc-board.dtb \
>         k3-j7200-evm-pcie1-ep.dtbo
>  k3-j721e-common-proc-board-infotainment-dtbs := k3-j721e-common-proc-board.dtb \
>         k3-j721e-common-proc-board-infotainment.dtbo
> +k3-j721e-evm-pcie-ntb-dtbs := k3-j721e-common-proc-board.dtb \
> +       k3-j721e-evm-pcie-ntb.dtbo
>  k3-j721e-evm-pcie0-ep-dtbs := k3-j721e-common-proc-board.dtb \
>         k3-j721e-evm-pcie0-ep.dtbo
>  k3-j721e-evm-pcie1-ep-dtbs := k3-j721e-common-proc-board.dtb \
> @@ -239,6 +242,7 @@ dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
>         k3-am69-sk-pcie0-ep.dtb \
>         k3-j7200-evm-pcie1-ep.dtb \
>         k3-j721e-common-proc-board-infotainment.dtb \
> +       k3-j721e-evm-pcie-ntb.dtb \
>         k3-j721e-evm-pcie0-ep.dtb \
>         k3-j721e-evm-pcie1-ep.dtb \
>         k3-j721e-sk-csi2-dual-imx219.dtb \
> diff --git a/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie-ntb.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie-ntb.dtso
> new file mode 100644
> index 000000000000..9b6b3e153e91
> --- /dev/null
> +++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie-ntb.dtso
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/**
> + * DT Overlay for enabling NTB functionality using PCIE0 and PCIE1 instances of
> + * PCIe on the J7 common processor board.
> + *
> + * J7 Common Processor Board Product Link: https://www.ti.com/tool/J721EXCPXEVM
> + *
> + * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/soc/ti,sci_pm_domain.h>
> +
> +#include "k3-pinctrl.h"
> +
> +&{/} {
> +       epf-bus {
> +               compatible = "pci-epf-bus";

There is no such binding upstream nor one pending. This needs to be dropped.

Rob


From andre.draszik at linaro.org  Tue Mar  4 09:05:28 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:28 +0000
Subject: [PATCH v2 00/16] a few rtc driver cleanups
Message-ID: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>

Hi,

While looking at RTC, I noticed that various drivers are keeping
pointers to data that they're not using themselves throughout their
lifetime.

So I took the liberty to drop these pointers and this series is the
result.

The last two patches also convert two drivers to using dev_err_probe(),
as I looked slightly closer into those two. They don't exactly fit the
general subject of removal of unneeded pointers, but I wanted to share
them anyway, since they're ready.

Drivers other than s5m were compile-tested only.

Cheers,
Andre'

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Changes in v2:
- s5m: fix arguments to devm_i2c_new_dummy_device()
- merge two rx8581 & sd3078 patches into one each (Alexandre)
- Link to v1: https://lore.kernel.org/r/20250228-rtc-cleanups-v1-0-b44cec078481 at linaro.org

---
Andr? Draszik (16):
      rtc: max77686: drop needless struct max77686_rtc_info::rtc member
      rtc: s5m: drop needless struct s5m_rtc_info::i2c member
      rtc: aspeed: drop needless struct aspeed_rtc::rtc_dev member
      rtc: ds2404: drop needless struct ds2404::rtc member
      rtc: ep93xx: drop needless struct ep93xx_rtc::rtc member
      rtc: ftrtc010: drop needless struct ftrtc010_rtc::rtc_dev member
      rtc: m48t86: drop needless struct m48t86_rtc_info::rtc member
      rtc: meson: drop needless struct meson_rtc::rtc member
      rtc: meson-vrtc: drop needless struct meson_vrtc_data::rtc member
      rtc: pl030: drop needless struct pl030_rtc::rtc member
      rtc: rx8581: drop needless struct rx8581
      rtc: s35390a: drop needless struct s35390a::rtc member
      rtc: sd2405al: drop needless struct sd2405al::rtc member
      rtc: sd3078: drop needless struct sd3078
      rtc: max77686: use dev_err_probe() where appropriate
      rtc: s5m: convert to dev_err_probe() where appropriate

 drivers/rtc/rtc-aspeed.c     | 16 ++++-----
 drivers/rtc/rtc-ds2404.c     | 14 ++++----
 drivers/rtc/rtc-ep93xx.c     | 16 ++++-----
 drivers/rtc/rtc-ftrtc010.c   | 17 +++++----
 drivers/rtc/rtc-m48t86.c     | 14 ++++----
 drivers/rtc/rtc-max77686.c   | 37 +++++++++----------
 drivers/rtc/rtc-meson-vrtc.c | 12 +++----
 drivers/rtc/rtc-meson.c      | 16 ++++-----
 drivers/rtc/rtc-pl030.c      | 14 ++++----
 drivers/rtc/rtc-rx8581.c     | 85 +++++++++++++++++++-------------------------
 drivers/rtc/rtc-s35390a.c    | 22 ++++++------
 drivers/rtc/rtc-s5m.c        | 58 +++++++++++++-----------------
 drivers/rtc/rtc-sd2405al.c   | 16 ++++-----
 drivers/rtc/rtc-sd3078.c     | 71 +++++++++++++++---------------------
 14 files changed, 183 insertions(+), 225 deletions(-)
---
base-commit: 0226d0ce98a477937ed295fb7df4cc30b46fc304
change-id: 20250228-rtc-cleanups-12c0b5123ea4

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Tue Mar  4 09:05:29 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:29 +0000
Subject: [PATCH v2 01/16] rtc: max77686: drop needless struct
 max77686_rtc_info::rtc member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-1-d4689a71668c@linaro.org>

When this driver was converted to using the devres managed i2c device
in commit 59a7f24fceb3 ("rtc: max77686: convert to
devm_i2c_new_dummy_device()"), struct max77686_rtc_info::rtc became
essentially unused.

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-max77686.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 7bb044d2ac25aeaaf2404b47b7e7bd485ae3d39e..6b0d02b44c8097453f704cbec9f02580fb869ca3 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -85,7 +85,6 @@ struct max77686_rtc_driver_data {
 
 struct max77686_rtc_info {
 	struct device		*dev;
-	struct i2c_client	*rtc;
 	struct rtc_device	*rtc_dev;
 	struct mutex		lock;
 
@@ -691,6 +690,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 {
 	struct device *parent = info->dev->parent;
 	struct i2c_client *parent_i2c = to_i2c_client(parent);
+	struct i2c_client *client;
 	int ret;
 
 	if (info->drv_data->rtc_irq_from_platform) {
@@ -714,14 +714,14 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 		goto add_rtc_irq;
 	}
 
-	info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
-					      info->drv_data->rtc_i2c_addr);
-	if (IS_ERR(info->rtc)) {
+	client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
+					   info->drv_data->rtc_i2c_addr);
+	if (IS_ERR(client)) {
 		dev_err(info->dev, "Failed to allocate I2C device for RTC\n");
-		return PTR_ERR(info->rtc);
+		return PTR_ERR(client);
 	}
 
-	info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
+	info->rtc_regmap = devm_regmap_init_i2c(client,
 						info->drv_data->regmap_config);
 	if (IS_ERR(info->rtc_regmap)) {
 		ret = PTR_ERR(info->rtc_regmap);

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:35 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:35 +0000
Subject: [PATCH v2 07/16] rtc: m48t86: drop needless struct
 m48t86_rtc_info::rtc member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-7-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-m48t86.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index dd4a62e2d39c73b1c8c3f50a59fd4fffc0b45105..10cd054fe86f9e6be74eb282222b2751dd91cc7e 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -41,7 +41,6 @@
 struct m48t86_rtc_info {
 	void __iomem *index_reg;
 	void __iomem *data_reg;
-	struct rtc_device *rtc;
 };
 
 static unsigned char m48t86_readb(struct device *dev, unsigned long addr)
@@ -219,6 +218,7 @@ static bool m48t86_verify_chip(struct platform_device *pdev)
 static int m48t86_rtc_probe(struct platform_device *pdev)
 {
 	struct m48t86_rtc_info *info;
+	struct rtc_device *rtc;
 	unsigned char reg;
 	int err;
 	struct nvmem_config m48t86_nvmem_cfg = {
@@ -250,17 +250,17 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(info->rtc))
-		return PTR_ERR(info->rtc);
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	info->rtc->ops = &m48t86_rtc_ops;
+	rtc->ops = &m48t86_rtc_ops;
 
-	err = devm_rtc_register_device(info->rtc);
+	err = devm_rtc_register_device(rtc);
 	if (err)
 		return err;
 
-	devm_rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg);
+	devm_rtc_nvmem_register(rtc, &m48t86_nvmem_cfg);
 
 	/* read battery status */
 	reg = m48t86_readb(&pdev->dev, M48T86_D);

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:30 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:30 +0000
Subject: [PATCH v2 02/16] rtc: s5m: drop needless struct s5m_rtc_info::i2c
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-2-d4689a71668c@linaro.org>

When this driver was converted to using the devres managed i2c device
in commit 7db7ad0817fe ("rtc: s5m: use devm_i2c_new_dummy_device()"),
struct s5m_rtc_info::i2c became essentially unused.

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
v2:
* fix arguments to devm_i2c_new_dummy_device() - too eager sed //, and
  gcc didn't notice, only clang :-(
---
 drivers/rtc/rtc-s5m.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 36acca5b2639e272dd9baed06ea5582f635702b0..88aed27660348a05886f080a2848fcabbf9666d0 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -146,7 +146,6 @@ static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
 
 struct s5m_rtc_info {
 	struct device *dev;
-	struct i2c_client *i2c;
 	struct sec_pmic_dev *s5m87xx;
 	struct regmap *regmap;
 	struct rtc_device *rtc_dev;
@@ -640,6 +639,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
 	struct s5m_rtc_info *info;
+	struct i2c_client *i2c;
 	const struct regmap_config *regmap_cfg;
 	int ret, alarm_irq;
 
@@ -675,14 +675,14 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info->i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
-					      RTC_I2C_ADDR);
-	if (IS_ERR(info->i2c)) {
+	i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
+					RTC_I2C_ADDR);
+	if (IS_ERR(i2c)) {
 		dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
-		return PTR_ERR(info->i2c);
+		return PTR_ERR(i2c);
 	}
 
-	info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg);
+	info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
 	if (IS_ERR(info->regmap)) {
 		ret = PTR_ERR(info->regmap);
 		dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:36 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:36 +0000
Subject: [PATCH v2 08/16] rtc: meson: drop needless struct meson_rtc::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-8-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-meson.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
index db1d626edca5fbb590f26c1cdd0774d350244a99..47e9ebf58ffc2f2b6c65932f8ec3773a213a62ef 100644
--- a/drivers/rtc/rtc-meson.c
+++ b/drivers/rtc/rtc-meson.c
@@ -59,7 +59,6 @@
 #define MESON_STATIC_DEFAULT    (MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE)
 
 struct meson_rtc {
-	struct rtc_device	*rtc;		/* rtc device we created */
 	struct device		*dev;		/* device we bound from */
 	struct reset_control	*reset;		/* reset source */
 	struct regulator	*vdd;		/* voltage input */
@@ -292,6 +291,7 @@ static int meson_rtc_probe(struct platform_device *pdev)
 	};
 	struct device *dev = &pdev->dev;
 	struct meson_rtc *rtc;
+	struct rtc_device *rtc_dev;
 	void __iomem *base;
 	int ret;
 	u32 tm;
@@ -300,16 +300,16 @@ static int meson_rtc_probe(struct platform_device *pdev)
 	if (!rtc)
 		return -ENOMEM;
 
-	rtc->rtc = devm_rtc_allocate_device(dev);
-	if (IS_ERR(rtc->rtc))
-		return PTR_ERR(rtc->rtc);
+	rtc_dev = devm_rtc_allocate_device(dev);
+	if (IS_ERR(rtc_dev))
+		return PTR_ERR(rtc_dev);
 
 	platform_set_drvdata(pdev, rtc);
 
 	rtc->dev = dev;
 
-	rtc->rtc->ops = &meson_rtc_ops;
-	rtc->rtc->range_max = U32_MAX;
+	rtc_dev->ops = &meson_rtc_ops;
+	rtc_dev->range_max = U32_MAX;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
@@ -365,11 +365,11 @@ static int meson_rtc_probe(struct platform_device *pdev)
 	}
 
 	meson_rtc_nvmem_config.priv = rtc;
-	ret = devm_rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config);
+	ret = devm_rtc_nvmem_register(rtc_dev, &meson_rtc_nvmem_config);
 	if (ret)
 		goto out_disable_vdd;
 
-	ret = devm_rtc_register_device(rtc->rtc);
+	ret = devm_rtc_register_device(rtc_dev);
 	if (ret)
 		goto out_disable_vdd;
 

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:40 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:40 +0000
Subject: [PATCH v2 12/16] rtc: s35390a: drop needless struct s35390a::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-12-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s35390a.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index e3dc18882f41445c41fbea56edbd5c869514880c..3408d2ab274194e39cde38a83567d37bd53f6632 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -63,7 +63,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match);
 
 struct s35390a {
 	struct i2c_client *client[8];
-	struct rtc_device *rtc;
 	int twentyfourhour;
 };
 
@@ -422,6 +421,7 @@ static int s35390a_probe(struct i2c_client *client)
 	int err, err_read;
 	unsigned int i;
 	struct s35390a *s35390a;
+	struct rtc_device *rtc;
 	char buf, status1;
 	struct device *dev = &client->dev;
 
@@ -447,9 +447,9 @@ static int s35390a_probe(struct i2c_client *client)
 		}
 	}
 
-	s35390a->rtc = devm_rtc_allocate_device(dev);
-	if (IS_ERR(s35390a->rtc))
-		return PTR_ERR(s35390a->rtc);
+	rtc = devm_rtc_allocate_device(dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
 	err_read = s35390a_read_status(s35390a, &status1);
 	if (err_read < 0) {
@@ -480,17 +480,17 @@ static int s35390a_probe(struct i2c_client *client)
 
 	device_set_wakeup_capable(dev, 1);
 
-	s35390a->rtc->ops = &s35390a_rtc_ops;
-	s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099;
+	rtc->ops = &s35390a_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
 
-	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features);
-	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features );
+	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
+	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
 
 	if (status1 & S35390A_FLAG_INT2)
-		rtc_update_irq(s35390a->rtc, 1, RTC_AF);
+		rtc_update_irq(rtc, 1, RTC_AF);
 
-	return devm_rtc_register_device(s35390a->rtc);
+	return devm_rtc_register_device(rtc);
 }
 
 static struct i2c_driver s35390a_driver = {

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:41 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:41 +0000
Subject: [PATCH v2 13/16] rtc: sd2405al: drop needless struct sd2405al::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-13-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Tested-by: T?th J?nos <gomba007 at gmail.com>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-sd2405al.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-sd2405al.c b/drivers/rtc/rtc-sd2405al.c
index d2568c3e387659dfea598cd2ef6bddc5c076cbb9..00c3033e8079b5f10aaabcc7a1d3f19771263a02 100644
--- a/drivers/rtc/rtc-sd2405al.c
+++ b/drivers/rtc/rtc-sd2405al.c
@@ -42,7 +42,6 @@
 
 struct sd2405al {
 	struct device		*dev;
-	struct rtc_device	*rtc;
 	struct regmap		*regmap;
 };
 
@@ -167,6 +166,7 @@ static const struct regmap_config sd2405al_regmap_conf = {
 static int sd2405al_probe(struct i2c_client *client)
 {
 	struct sd2405al *sd2405al;
+	struct rtc_device *rtc;
 	int ret;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@@ -182,17 +182,17 @@ static int sd2405al_probe(struct i2c_client *client)
 	if (IS_ERR(sd2405al->regmap))
 		return PTR_ERR(sd2405al->regmap);
 
-	sd2405al->rtc = devm_rtc_allocate_device(&client->dev);
-	if (IS_ERR(sd2405al->rtc))
-		return PTR_ERR(sd2405al->rtc);
+	rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	sd2405al->rtc->ops = &sd2405al_rtc_ops;
-	sd2405al->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	sd2405al->rtc->range_max = RTC_TIMESTAMP_END_2099;
+	rtc->ops = &sd2405al_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
 
 	dev_set_drvdata(&client->dev, sd2405al);
 
-	ret = devm_rtc_register_device(sd2405al->rtc);
+	ret = devm_rtc_register_device(rtc);
 	if (ret < 0)
 		return ret;
 

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:39 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:39 +0000
Subject: [PATCH v2 11/16] rtc: rx8581: drop needless struct rx8581
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-11-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Since this now means that the structure has just one member only left,
there  is no need anymore to allocate data for it and pass that around
via the various callbacks, just to extract that one member.

Instead, we can just pass that one member and avoid the extra memory
allocation for the containing struct, reducing runtime memory
consumption.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-rx8581.c | 85 ++++++++++++++++++++----------------------------
 1 file changed, 36 insertions(+), 49 deletions(-)

diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index b18c12887bdc3705ea4cee9b8d75086a05b24e71..20c2dff01bae833ae4e100cc38cd5f030017be75 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -52,11 +52,6 @@
 #define RX8571_USER_RAM		0x10
 #define RX8571_NVRAM_SIZE	0x10
 
-struct rx8581 {
-	struct regmap		*regmap;
-	struct rtc_device	*rtc;
-};
-
 struct rx85x1_config {
 	struct regmap_config regmap;
 	unsigned int num_nvram;
@@ -72,14 +67,14 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	unsigned char date[7];
 	unsigned int data;
 	int err;
-	struct rx8581 *rx8581 = i2c_get_clientdata(client);
+	struct regmap *regmap = i2c_get_clientdata(client);
 
 	/* First we ensure that the "update flag" is not set, we read the
 	 * time and date then re-read the "update flag". If the update flag
 	 * has been set, we know that the time has changed during the read so
 	 * we repeat the whole process again.
 	 */
-	err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
+	err = regmap_read(regmap, RX8581_REG_FLAG, &data);
 	if (err < 0)
 		return err;
 
@@ -92,20 +87,20 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	do {
 		/* If update flag set, clear it */
 		if (data & RX8581_FLAG_UF) {
-			err = regmap_write(rx8581->regmap, RX8581_REG_FLAG,
-					  data & ~RX8581_FLAG_UF);
+			err = regmap_write(regmap, RX8581_REG_FLAG,
+					   data & ~RX8581_FLAG_UF);
 			if (err < 0)
 				return err;
 		}
 
 		/* Now read time and date */
-		err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date,
+		err = regmap_bulk_read(regmap, RX8581_REG_SC, date,
 				       sizeof(date));
 		if (err < 0)
 			return err;
 
 		/* Check flag register */
-		err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
+		err = regmap_read(regmap, RX8581_REG_FLAG, &data);
 		if (err < 0)
 			return err;
 	} while (data & RX8581_FLAG_UF);
@@ -137,7 +132,7 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	struct i2c_client *client = to_i2c_client(dev);
 	int err;
 	unsigned char buf[7];
-	struct rx8581 *rx8581 = i2c_get_clientdata(client);
+	struct regmap *regmap = i2c_get_clientdata(client);
 
 	dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -160,25 +155,23 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	buf[RX8581_REG_DW] = (0x1 << tm->tm_wday);
 
 	/* Stop the clock */
-	err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
+	err = regmap_update_bits(regmap, RX8581_REG_CTRL,
 				 RX8581_CTRL_STOP, RX8581_CTRL_STOP);
 	if (err < 0)
 		return err;
 
 	/* write register's data */
-	err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC,
-				buf, sizeof(buf));
+	err = regmap_bulk_write(regmap, RX8581_REG_SC, buf, sizeof(buf));
 	if (err < 0)
 		return err;
 
 	/* get VLF and clear it */
-	err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG,
-				 RX8581_FLAG_VLF, 0);
+	err = regmap_update_bits(regmap, RX8581_REG_FLAG, RX8581_FLAG_VLF, 0);
 	if (err < 0)
 		return err;
 
 	/* Restart the clock */
-	return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
+	return regmap_update_bits(regmap, RX8581_REG_CTRL,
 				 RX8581_CTRL_STOP, 0);
 }
 
@@ -190,29 +183,27 @@ static const struct rtc_class_ops rx8581_rtc_ops = {
 static int rx8571_nvram_read(void *priv, unsigned int offset, void *val,
 			     size_t bytes)
 {
-	struct rx8581 *rx8581 = priv;
+	struct regmap *regmap = priv;
 
-	return regmap_bulk_read(rx8581->regmap, RX8571_USER_RAM + offset,
-				val, bytes);
+	return regmap_bulk_read(regmap, RX8571_USER_RAM + offset, val, bytes);
 }
 
 static int rx8571_nvram_write(void *priv, unsigned int offset, void *val,
 			      size_t bytes)
 {
-	struct rx8581 *rx8581 = priv;
+	struct regmap *regmap = priv;
 
-	return regmap_bulk_write(rx8581->regmap, RX8571_USER_RAM + offset,
-				 val, bytes);
+	return regmap_bulk_write(regmap, RX8571_USER_RAM + offset, val, bytes);
 }
 
 static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val,
 			     size_t bytes)
 {
-	struct rx8581 *rx8581 = priv;
+	struct regmap *regmap = priv;
 	unsigned int tmp_val;
 	int ret;
 
-	ret = regmap_read(rx8581->regmap, RX8581_REG_RAM, &tmp_val);
+	ret = regmap_read(regmap, RX8581_REG_RAM, &tmp_val);
 	(*(unsigned char *)val) = (unsigned char) tmp_val;
 
 	return ret;
@@ -221,12 +212,11 @@ static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val,
 static int rx85x1_nvram_write(void *priv, unsigned int offset, void *val,
 			      size_t bytes)
 {
-	struct rx8581 *rx8581 = priv;
+	struct regmap *regmap = priv;
 	unsigned char tmp_val;
 
 	tmp_val = *((unsigned char *)val);
-	return regmap_write(rx8581->regmap, RX8581_REG_RAM,
-				(unsigned int)tmp_val);
+	return regmap_write(regmap, RX8581_REG_RAM, (unsigned int)tmp_val);
 }
 
 static const struct rx85x1_config rx8581_config = {
@@ -249,9 +239,10 @@ static const struct rx85x1_config rx8571_config = {
 
 static int rx8581_probe(struct i2c_client *client)
 {
-	struct rx8581 *rx8581;
+	struct regmap *regmap;
 	const struct rx85x1_config *config = &rx8581_config;
 	const void *data = of_device_get_match_data(&client->dev);
+	struct rtc_device *rtc;
 	static struct nvmem_config nvmem_cfg[] = {
 		{
 			.name = "rx85x1-",
@@ -276,31 +267,27 @@ static int rx8581_probe(struct i2c_client *client)
 	if (data)
 		config = data;
 
-	rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL);
-	if (!rx8581)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, rx8581);
+	regmap = devm_regmap_init_i2c(client, &config->regmap);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
 
-	rx8581->regmap = devm_regmap_init_i2c(client, &config->regmap);
-	if (IS_ERR(rx8581->regmap))
-		return PTR_ERR(rx8581->regmap);
+	i2c_set_clientdata(client, regmap);
 
-	rx8581->rtc = devm_rtc_allocate_device(&client->dev);
-	if (IS_ERR(rx8581->rtc))
-		return PTR_ERR(rx8581->rtc);
+	rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	rx8581->rtc->ops = &rx8581_rtc_ops;
-	rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099;
-	rx8581->rtc->start_secs = 0;
-	rx8581->rtc->set_start_time = true;
+	rtc->ops = &rx8581_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
+	rtc->start_secs = 0;
+	rtc->set_start_time = true;
 
-	ret = devm_rtc_register_device(rx8581->rtc);
+	ret = devm_rtc_register_device(rtc);
 
 	for (i = 0; i < config->num_nvram; i++) {
-		nvmem_cfg[i].priv = rx8581;
-		devm_rtc_nvmem_register(rx8581->rtc, &nvmem_cfg[i]);
+		nvmem_cfg[i].priv = regmap;
+		devm_rtc_nvmem_register(rtc, &nvmem_cfg[i]);
 	}
 
 	return ret;

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:43 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:43 +0000
Subject: [PATCH v2 15/16] rtc: max77686: use dev_err_probe() where
 appropriate
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-15-d4689a71668c@linaro.org>

dev_err_probe() exists to simplify code and harmonise error messages,
there's no reason not to use it here.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-max77686.c | 29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 6b0d02b44c8097453f704cbec9f02580fb869ca3..69ea3ce75b5a5426d4a56b979773be71c4ee7562 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -704,10 +704,9 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 	}
 
 	info->regmap = dev_get_regmap(parent, NULL);
-	if (!info->regmap) {
-		dev_err(info->dev, "Failed to get rtc regmap\n");
-		return -ENODEV;
-	}
+	if (!info->regmap)
+		return dev_err_probe(info->dev, -ENODEV,
+				     "Failed to get rtc regmap\n");
 
 	if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) {
 		info->rtc_regmap = info->regmap;
@@ -716,28 +715,24 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
 
 	client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
 					   info->drv_data->rtc_i2c_addr);
-	if (IS_ERR(client)) {
-		dev_err(info->dev, "Failed to allocate I2C device for RTC\n");
-		return PTR_ERR(client);
-	}
+	if (IS_ERR(client))
+		return dev_err_probe(info->dev, PTR_ERR(client),
+				     "Failed to allocate I2C device for RTC\n");
 
 	info->rtc_regmap = devm_regmap_init_i2c(client,
 						info->drv_data->regmap_config);
-	if (IS_ERR(info->rtc_regmap)) {
-		ret = PTR_ERR(info->rtc_regmap);
-		dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
-		return ret;
-	}
+	if (IS_ERR(info->rtc_regmap))
+		return dev_err_probe(info->dev, PTR_ERR(info->rtc_regmap),
+				     "Failed to allocate RTC regmap\n");
 
 add_rtc_irq:
 	ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
 				  IRQF_ONESHOT | IRQF_SHARED,
 				  0, info->drv_data->rtc_irq_chip,
 				  &info->rtc_irq_data);
-	if (ret < 0) {
-		dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
-		return ret;
-	}
+	if (ret < 0)
+		return dev_err_probe(info->dev, ret,
+				     "Failed to add RTC irq chip\n");
 
 	return 0;
 }

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:32 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:32 +0000
Subject: [PATCH v2 04/16] rtc: ds2404: drop needless struct ds2404::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-4-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-ds2404.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c
index 3231fd9f61da49bdaf00e46486fc34836094ee78..217694eca36c3432a8db3b874374e347eeb802d9 100644
--- a/drivers/rtc/rtc-ds2404.c
+++ b/drivers/rtc/rtc-ds2404.c
@@ -31,7 +31,6 @@ struct ds2404 {
 	struct gpio_desc *rst_gpiod;
 	struct gpio_desc *clk_gpiod;
 	struct gpio_desc *dq_gpiod;
-	struct rtc_device *rtc;
 };
 
 static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev)
@@ -182,6 +181,7 @@ static const struct rtc_class_ops ds2404_rtc_ops = {
 static int rtc_probe(struct platform_device *pdev)
 {
 	struct ds2404 *chip;
+	struct rtc_device *rtc;
 	int retval = -EBUSY;
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(struct ds2404), GFP_KERNEL);
@@ -190,9 +190,9 @@ static int rtc_probe(struct platform_device *pdev)
 
 	chip->dev = &pdev->dev;
 
-	chip->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(chip->rtc))
-		return PTR_ERR(chip->rtc);
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
 	retval = ds2404_gpio_map(chip, pdev);
 	if (retval)
@@ -200,10 +200,10 @@ static int rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, chip);
 
-	chip->rtc->ops = &ds2404_rtc_ops;
-	chip->rtc->range_max = U32_MAX;
+	rtc->ops = &ds2404_rtc_ops;
+	rtc->range_max = U32_MAX;
 
-	retval = devm_rtc_register_device(chip->rtc);
+	retval = devm_rtc_register_device(rtc);
 	if (retval)
 		return retval;
 

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:33 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:33 +0000
Subject: [PATCH v2 05/16] rtc: ep93xx: drop needless struct ep93xx_rtc::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-5-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-ep93xx.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 1fdd20d01560ef4fae2b996cf366b4f812329225..dcdcdd06f30d1ff6d0939f6bcad2c17c03c5a65e 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -28,7 +28,6 @@
 
 struct ep93xx_rtc {
 	void __iomem	*mmio_base;
-	struct rtc_device *rtc;
 };
 
 static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
@@ -123,6 +122,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {
 static int ep93xx_rtc_probe(struct platform_device *pdev)
 {
 	struct ep93xx_rtc *ep93xx_rtc;
+	struct rtc_device *rtc;
 	int err;
 
 	ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
@@ -135,18 +135,18 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ep93xx_rtc);
 
-	ep93xx_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(ep93xx_rtc->rtc))
-		return PTR_ERR(ep93xx_rtc->rtc);
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	ep93xx_rtc->rtc->ops = &ep93xx_rtc_ops;
-	ep93xx_rtc->rtc->range_max = U32_MAX;
+	rtc->ops = &ep93xx_rtc_ops;
+	rtc->range_max = U32_MAX;
 
-	err = rtc_add_group(ep93xx_rtc->rtc, &ep93xx_rtc_sysfs_files);
+	err = rtc_add_group(rtc, &ep93xx_rtc_sysfs_files);
 	if (err)
 		return err;
 
-	return devm_rtc_register_device(ep93xx_rtc->rtc);
+	return devm_rtc_register_device(rtc);
 }
 
 static const struct of_device_id ep93xx_rtc_of_ids[] = {

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:31 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:31 +0000
Subject: [PATCH v2 03/16] rtc: aspeed: drop needless struct
 aspeed_rtc::rtc_dev member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-3-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc_dev member is managed via devres,
and no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-aspeed.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c
index 880b015eebaf796f68ed82c29998f345e1fd418b..0d0053b52f9b90a61725bf29435bfc8071977f9e 100644
--- a/drivers/rtc/rtc-aspeed.c
+++ b/drivers/rtc/rtc-aspeed.c
@@ -8,7 +8,6 @@
 #include <linux/io.h>
 
 struct aspeed_rtc {
-	struct rtc_device *rtc_dev;
 	void __iomem *base;
 };
 
@@ -85,6 +84,7 @@ static const struct rtc_class_ops aspeed_rtc_ops = {
 static int aspeed_rtc_probe(struct platform_device *pdev)
 {
 	struct aspeed_rtc *rtc;
+	struct rtc_device *rtc_dev;
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
 	if (!rtc)
@@ -94,17 +94,17 @@ static int aspeed_rtc_probe(struct platform_device *pdev)
 	if (IS_ERR(rtc->base))
 		return PTR_ERR(rtc->base);
 
-	rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(rtc->rtc_dev))
-		return PTR_ERR(rtc->rtc_dev);
+	rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc_dev))
+		return PTR_ERR(rtc_dev);
 
 	platform_set_drvdata(pdev, rtc);
 
-	rtc->rtc_dev->ops = &aspeed_rtc_ops;
-	rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
-	rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */
+	rtc_dev->ops = &aspeed_rtc_ops;
+	rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
+	rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */
 
-	return devm_rtc_register_device(rtc->rtc_dev);
+	return devm_rtc_register_device(rtc_dev);
 }
 
 static const struct of_device_id aspeed_rtc_match[] = {

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:44 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:44 +0000
Subject: [PATCH v2 16/16] rtc: s5m: convert to dev_err_probe() where
 appropriate
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-16-d4689a71668c@linaro.org>

dev_err_probe() exists to simplify code and harmonise error messages,
there's no reason not to use it here.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 50 +++++++++++++++++++++-----------------------------
 1 file changed, 21 insertions(+), 29 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 88aed27660348a05886f080a2848fcabbf9666d0..db5c9b641277213aa1371776c63e2eda3f223465 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -626,11 +626,10 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
 	}
 
 	info->rtc_24hr_mode = 1;
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
-			__func__, ret);
-		return ret;
-	}
+	if (ret < 0)
+		return dev_err_probe(info->dev, ret,
+				     "%s: fail to write controlm reg\n",
+				     __func__);
 
 	return ret;
 }
@@ -669,26 +668,21 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 		alarm_irq = S5M8767_IRQ_RTCA1;
 		break;
 	default:
-		dev_err(&pdev->dev,
-				"Device type %lu is not supported by RTC driver\n",
-				platform_get_device_id(pdev)->driver_data);
-		return -ENODEV;
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Device type %lu is not supported by RTC driver\n",
+				     platform_get_device_id(pdev)->driver_data);
 	}
 
 	i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
 					RTC_I2C_ADDR);
-	if (IS_ERR(i2c)) {
-		dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
-		return PTR_ERR(i2c);
-	}
+	if (IS_ERR(i2c))
+		return dev_err_probe(&pdev->dev, PTR_ERR(i2c),
+				     "Failed to allocate I2C for RTC\n");
 
 	info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
-	if (IS_ERR(info->regmap)) {
-		ret = PTR_ERR(info->regmap);
-		dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
-				ret);
-		return ret;
-	}
+	if (IS_ERR(info->regmap))
+		return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
+				     "Failed to allocate RTC register map\n");
 
 	info->dev = &pdev->dev;
 	info->s5m87xx = s5m87xx;
@@ -696,11 +690,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
 	if (s5m87xx->irq_data) {
 		info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
-		if (info->irq <= 0) {
-			dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
-				alarm_irq);
-			return -EINVAL;
-		}
+		if (info->irq <= 0)
+			return dev_err_probe(&pdev->dev, -EINVAL,
+					     "Failed to get virtual IRQ %d\n",
+					     alarm_irq);
 	}
 
 	platform_set_drvdata(pdev, info);
@@ -724,11 +717,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 		ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
 						s5m_rtc_alarm_irq, 0, "rtc-alarm0",
 						info);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
-				info->irq, ret);
-			return ret;
-		}
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret,
+					     "Failed to request alarm IRQ %d\n",
+					     info->irq);
 		device_init_wakeup(&pdev->dev, true);
 	}
 

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:37 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:37 +0000
Subject: [PATCH v2 09/16] rtc: meson-vrtc: drop needless struct
 meson_vrtc_data::rtc member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-9-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-meson-vrtc.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c
index 5849729f7d01d7ec7868ff3bbdc5ed599aaa8238..7d38258cbe376e5a1b2af6250cb6d04c313175fb 100644
--- a/drivers/rtc/rtc-meson-vrtc.c
+++ b/drivers/rtc/rtc-meson-vrtc.c
@@ -13,7 +13,6 @@
 
 struct meson_vrtc_data {
 	void __iomem *io_alarm;
-	struct rtc_device *rtc;
 	unsigned long alarm_time;
 	bool enabled;
 };
@@ -65,6 +64,7 @@ static const struct rtc_class_ops meson_vrtc_ops = {
 static int meson_vrtc_probe(struct platform_device *pdev)
 {
 	struct meson_vrtc_data *vrtc;
+	struct rtc_device *rtc;
 
 	vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL);
 	if (!vrtc)
@@ -78,12 +78,12 @@ static int meson_vrtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, vrtc);
 
-	vrtc->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(vrtc->rtc))
-		return PTR_ERR(vrtc->rtc);
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	vrtc->rtc->ops = &meson_vrtc_ops;
-	return devm_rtc_register_device(vrtc->rtc);
+	rtc->ops = &meson_vrtc_ops;
+	return devm_rtc_register_device(rtc);
 }
 
 static int __maybe_unused meson_vrtc_suspend(struct device *dev)

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:34 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:34 +0000
Subject: [PATCH v2 06/16] rtc: ftrtc010: drop needless struct
 ftrtc010_rtc::rtc_dev member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-6-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc_dev member is managed via devres,
and no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-ftrtc010.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index cb4a5d101f537e20a685bb022e6f6516b0df8271..02608d3784958e69ec0ecbdb9fcc8b333b19e7cc 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -28,7 +28,6 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
 
 struct ftrtc010_rtc {
-	struct rtc_device	*rtc_dev;
 	void __iomem		*rtc_base;
 	int			rtc_irq;
 	struct clk		*pclk;
@@ -113,6 +112,7 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
 	struct ftrtc010_rtc *rtc;
 	struct device *dev = &pdev->dev;
 	struct resource *res;
+	struct rtc_device *rtc_dev;
 	int ret;
 
 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -160,29 +160,28 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
 		goto err_disable_extclk;
 	}
 
-	rtc->rtc_dev = devm_rtc_allocate_device(dev);
-	if (IS_ERR(rtc->rtc_dev)) {
-		ret = PTR_ERR(rtc->rtc_dev);
+	rtc_dev = devm_rtc_allocate_device(dev);
+	if (IS_ERR(rtc_dev)) {
+		ret = PTR_ERR(rtc_dev);
 		goto err_disable_extclk;
 	}
 
-	rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
+	rtc_dev->ops = &ftrtc010_rtc_ops;
 
 	sec  = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
 	min  = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
 	hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
 	days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
 
-	rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 +
-				  min * 60 + sec;
-	rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min;
+	rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + min * 60 + sec;
+	rtc_dev->range_max = U32_MAX + rtc_dev->range_min;
 
 	ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
 			       IRQF_SHARED, pdev->name, dev);
 	if (unlikely(ret))
 		goto err_disable_extclk;
 
-	return devm_rtc_register_device(rtc->rtc_dev);
+	return devm_rtc_register_device(rtc_dev);
 
 err_disable_extclk:
 	clk_disable_unprepare(rtc->extclk);

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:42 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:42 +0000
Subject: [PATCH v2 14/16] rtc: sd3078: drop needless struct sd3078
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-14-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Since this now means that the structure has just one member only left,
there  is no need anymore to allocate data for it and pass that around
via the various callbacks, just to extract that one member.

Instead, we can just pass that one member and avoid the extra memory
allocation for the containing struct, reducing runtime memory
consumption.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-sd3078.c | 71 +++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 43 deletions(-)

diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c
index fe27b54beaad1c06b70bf7f22e44c3f6da087267..10cc1dcfc7748144f51ef674939506feee1fb471 100644
--- a/drivers/rtc/rtc-sd3078.c
+++ b/drivers/rtc/rtc-sd3078.c
@@ -36,11 +36,6 @@
  */
 #define WRITE_PROTECT_EN	0
 
-struct sd3078 {
-	struct rtc_device	*rtc;
-	struct regmap		*regmap;
-};
-
 /*
  * In order to prevent arbitrary modification of the time register,
  * when modification of the register,
@@ -49,14 +44,11 @@ struct sd3078 {
  * 2. set WRITE2 bit
  * 3. set WRITE3 bit
  */
-static void sd3078_enable_reg_write(struct sd3078 *sd3078)
+static void sd3078_enable_reg_write(struct regmap *regmap)
 {
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
-			   KEY_WRITE1, KEY_WRITE1);
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
-			   KEY_WRITE2, KEY_WRITE2);
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
-			   KEY_WRITE3, KEY_WRITE3);
+	regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, KEY_WRITE1);
+	regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, KEY_WRITE2);
+	regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, KEY_WRITE3);
 }
 
 #if WRITE_PROTECT_EN
@@ -69,14 +61,11 @@ static void sd3078_enable_reg_write(struct sd3078 *sd3078)
  * 2. clear WRITE3 bit
  * 3. clear WRITE1 bit
  */
-static void sd3078_disable_reg_write(struct sd3078 *sd3078)
+static void sd3078_disable_reg_write(struct regmap *regmap)
 {
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
-			   KEY_WRITE2, 0);
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
-			   KEY_WRITE3, 0);
-	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
-			   KEY_WRITE1, 0);
+	regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, 0);
+	regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, 0);
+	regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, 0);
 }
 #endif
 
@@ -85,11 +74,10 @@ static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	unsigned char hour;
 	unsigned char rtc_data[NUM_TIME_REGS] = {0};
 	struct i2c_client *client = to_i2c_client(dev);
-	struct sd3078 *sd3078 = i2c_get_clientdata(client);
+	struct regmap *regmap = i2c_get_clientdata(client);
 	int ret;
 
-	ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data,
-			       NUM_TIME_REGS);
+	ret = regmap_bulk_read(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS);
 	if (ret < 0) {
 		dev_err(dev, "reading from RTC failed with err:%d\n", ret);
 		return ret;
@@ -123,7 +111,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	unsigned char rtc_data[NUM_TIME_REGS];
 	struct i2c_client *client = to_i2c_client(dev);
-	struct sd3078 *sd3078 = i2c_get_clientdata(client);
+	struct regmap *regmap = i2c_get_clientdata(client);
 	int ret;
 
 	rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec);
@@ -135,10 +123,10 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100);
 
 #if WRITE_PROTECT_EN
-	sd3078_enable_reg_write(sd3078);
+	sd3078_enable_reg_write(regmap);
 #endif
 
-	ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data,
+	ret = regmap_bulk_write(regmap, SD3078_REG_SC, rtc_data,
 				NUM_TIME_REGS);
 	if (ret < 0) {
 		dev_err(dev, "writing to RTC failed with err:%d\n", ret);
@@ -146,7 +134,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	}
 
 #if WRITE_PROTECT_EN
-	sd3078_disable_reg_write(sd3078);
+	sd3078_disable_reg_write(regmap);
 #endif
 
 	return 0;
@@ -166,36 +154,33 @@ static const struct regmap_config regmap_config = {
 static int sd3078_probe(struct i2c_client *client)
 {
 	int ret;
-	struct sd3078 *sd3078;
+	struct regmap *regmap;
+	struct rtc_device *rtc;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
 
-	sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL);
-	if (!sd3078)
-		return -ENOMEM;
-
-	sd3078->regmap = devm_regmap_init_i2c(client, &regmap_config);
-	if (IS_ERR(sd3078->regmap)) {
+	regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(regmap)) {
 		dev_err(&client->dev, "regmap allocation failed\n");
-		return PTR_ERR(sd3078->regmap);
+		return PTR_ERR(regmap);
 	}
 
-	i2c_set_clientdata(client, sd3078);
+	i2c_set_clientdata(client, regmap);
 
-	sd3078->rtc = devm_rtc_allocate_device(&client->dev);
-	if (IS_ERR(sd3078->rtc))
-		return PTR_ERR(sd3078->rtc);
+	rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
-	sd3078->rtc->ops = &sd3078_rtc_ops;
-	sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099;
+	rtc->ops = &sd3078_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
 
-	ret = devm_rtc_register_device(sd3078->rtc);
+	ret = devm_rtc_register_device(rtc);
 	if (ret)
 		return ret;
 
-	sd3078_enable_reg_write(sd3078);
+	sd3078_enable_reg_write(regmap);
 
 	return 0;
 }

-- 
2.48.1.711.g2feabab25a-goog



From andre.draszik at linaro.org  Tue Mar  4 09:05:38 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 04 Mar 2025 17:05:38 +0000
Subject: [PATCH v2 10/16] rtc: pl030: drop needless struct pl030_rtc::rtc
 member
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <20250304-rtc-cleanups-v2-10-d4689a71668c@linaro.org>

The memory pointed to by the ::rtc member is managed via devres, and
no code in this driver uses it past _probe().

We can drop it from the structure and just use a local temporary
variable, reducing runtime memory consumption by a few bytes.

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-pl030.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c
index 39038c0754ee55a952e5986afe711cffff35840b..e7c81740061bb60c4d8447d6522819685bea9180 100644
--- a/drivers/rtc/rtc-pl030.c
+++ b/drivers/rtc/rtc-pl030.c
@@ -21,7 +21,6 @@
 #define RTC_CR_MIE	(1 << 0)
 
 struct pl030_rtc {
-	struct rtc_device	*rtc;
 	void __iomem		*base;
 };
 
@@ -86,6 +85,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct pl030_rtc *rtc;
 	int ret;
+	struct rtc_device *rtc_dev;
 
 	ret = amba_request_regions(dev, NULL);
 	if (ret)
@@ -97,14 +97,14 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
 		goto err_rtc;
 	}
 
-	rtc->rtc = devm_rtc_allocate_device(&dev->dev);
-	if (IS_ERR(rtc->rtc)) {
-		ret = PTR_ERR(rtc->rtc);
+	rtc_dev = devm_rtc_allocate_device(&dev->dev);
+	if (IS_ERR(rtc_dev)) {
+		ret = PTR_ERR(rtc_dev);
 		goto err_rtc;
 	}
 
-	rtc->rtc->ops = &pl030_ops;
-	rtc->rtc->range_max = U32_MAX;
+	rtc_dev->ops = &pl030_ops;
+	rtc_dev->range_max = U32_MAX;
 	rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!rtc->base) {
 		ret = -ENOMEM;
@@ -121,7 +121,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
 	if (ret)
 		goto err_irq;
 
-	ret = devm_rtc_register_device(rtc->rtc);
+	ret = devm_rtc_register_device(rtc_dev);
 	if (ret)
 		goto err_reg;
 

-- 
2.48.1.711.g2feabab25a-goog



From manivannan.sadhasivam at linaro.org  Tue Mar  4 09:07:35 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 22:37:35 +0530
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com>
 <20250304150313.ey4fky35bu6dbtxd@thinkpad>
 <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com>
Message-ID: <20250304170735.x25c65azfpd7xmwv@thinkpad>

On Tue, Mar 04, 2025 at 11:55:05AM -0500, Jim Quinlan wrote:
> On Tue, Mar 4, 2025 at 10:03?AM Manivannan Sadhasivam
> <manivannan.sadhasivam at linaro.org> wrote:
> >
> > On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > > If regulator_bulk_get() returns an error, no regulators are created and we
> > > need to set their number to zero.  If we do not do this and the PCIe
> > > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> > >
> > > Also print out the error value, as we cannot return an error upwards as
> > > Linux will WARN on an error from add_bus().
> > >
> > > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > > ---
> > >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > index e0b20f58c604..56b49d3cae19 100644
> > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> > >
> > >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> > >               if (ret) {
> > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> >
> > Why is this dev_info() instead of dev_err()?
> 
> I will change this.
> >
> > > +                     pcie->sr = NULL;
> >
> > Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?
> 
> Not sure I understand -- it is already set before a  successful
> regulator_bulk_get() call.

Didn't I say 'after'?

> I set it to NULL after an unsuccessful result so the structure will
> not be passed to subsequent calls.
> 

If you set the pointer after a successful regulator_bulk_get(), you do not need
to set it to NULL for a failure.

- Mani

-- 
????????? ????????


From robh at kernel.org  Tue Mar  4 09:10:54 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 4 Mar 2025 11:10:54 -0600
Subject: [PATCH 1/1] arm64: dts: im8mq: move dwc3 usb port under ports
In-Reply-To: <20250224193308.407606-1-Frank.Li@nxp.com>
References: <20250224193308.407606-1-Frank.Li@nxp.com>
Message-ID: <CAL_JsqLJciDgc2cPy7QApH4ia=Rx3MnoVMS3pha3u9PVy_EfPg@mail.gmail.com>

On Mon, Feb 24, 2025 at 1:33?PM Frank Li <Frank.Li at nxp.com> wrote:
>
> Move port at 0 and port at 1 under ports to fix below DTB_CHECK warnings.
>
> arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dtb: usb at 38100000: port at 0:reg:0:0: 0 is less than the minimum of 1
>         from schema $id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
> arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dtb: usb at 38100000: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'dr_mode', 'phy-names', 'phys', 'port at 0', 'port at 1', 'snps,parkmode-disable-ss-quirk' were unexpected)
>         from schema $id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
>
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  .../dts/freescale/imx8mq-librem5-devkit.dts   | 25 +++++++++++--------
>  .../boot/dts/freescale/imx8mq-librem5.dtsi    | 25 +++++++++++--------
>  2 files changed, 28 insertions(+), 22 deletions(-)

Acked-by: Rob Herring (Arm) <robh at kernel.org>


From manivannan.sadhasivam at linaro.org  Tue Mar  4 09:11:54 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 22:41:54 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250304154638.GB2310180@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
 <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
 <20250304154638.GB2310180@rocinante>
Message-ID: <20250304171154.njoygsvfd567pb66@thinkpad>

On Wed, Mar 05, 2025 at 12:46:38AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> > This patch is now commit 1ff54f4cbaed9ec6 ("PCI: dwc: Add debugfs
> > based Silicon Debug support for DWC") in pci/next (next-20250304).
> > 
> > On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> > > [...]
> > > > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > > > +{
> > > > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > > > +   struct device *dev = pci->dev;
> > > > > +   struct debugfs_info *debugfs;
> > > > > +   struct dentry *dir;
> > > > > +   int ret;
> > > > > +
> > > > > +   /* Create main directory for each platform driver */
> > > > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > > > +   dir = debugfs_create_dir(dirname, NULL);
> > > > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > > > +   if (!debugfs)
> > > > > +           return -ENOMEM;
> > > > > +
> > > > > +   debugfs->debug_dir = dir;
> > > > > +   pci->debugfs = debugfs;
> > > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > > +   if (ret)
> > > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > > >
> > > > What will happen if ret != 0? still return 0?
> > 
> > And that is exactly what happens on Gray Hawk Single with R-Car
> > V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> > dwc_pcie_rasdes_debugfs_init() to return -ENODEV.
> 
> Thank you for testing and for catching this issue.  Much appreciated.
> 
> > > Given that callers of dwc_pcie_debugfs_init() check for errors,
> > 
> > Debugfs issues should never be propagated upstream!
> 
> Makes complete sense.  Sorry for breaking things here!
> 
> > > this probably should correctly bubble up any failure coming from
> > > dwc_pcie_rasdes_debugfs_init().
> > >
> > > I made updates to the code directly on the current branch, have a look:
> > 
> > So while applying, you changed this like:
> > 
> >             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> >     -       if (ret)
> >     -               dev_dbg(dev, "RASDES debugfs init failed\n");
> >     +       if (ret) {
> >     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
> >     +               return ret;
> >     +       }
> > 
> >             return 0;
> > 
> > Hence this is now a fatal error, causing the probe to fail.
> 
> I removed the changed, and also move the log level to be a warning, per:
> 
>   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=c6759a967e69aba16aef0d92f43e527b112e98a5
> 
> Would this be acceptable here?
> 
> Mani, would this be acceptable to you, too?  Given that you posted the
> following recently:
> 
>   https://lore.kernel.org/linux-pci/20250303200055.GA1881771 at rocinante/T/#mab9cbd5834390d259afea056eee9a73d8c3b435f
> 
> That said, perhaps moving the log level to a debug would be better served here.
> 

Even though debugfs_init() failure is not supposed to fail the probe(),
dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
failure would be canolically correct IMO.

So I would still opt to have my version + your previous one.

- Mani

-- 
????????? ????????


From detlev.casanova at collabora.com  Tue Mar  4 09:15:41 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Tue, 04 Mar 2025 12:15:41 -0500
Subject: [PATCH v3 1/3] arm64: dts: rockchip: Add vop for rk3576
In-Reply-To: <20241231095728.253943-2-andyshrk@163.com>
References: <20241231095728.253943-1-andyshrk@163.com>
 <20241231095728.253943-2-andyshrk@163.com>
Message-ID: <12619358.O9o76ZdvQC@earth>

Hi andy,

On Tuesday, 31 December 2024 04:57:18 EST Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Add VOP and VOP_MMU found on rk3576.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> 
> ---
> 
> Changes in v3:
> - Split from
> https://lore.kernel.org/linux-rockchip/3330586.aeNJFYEL58 at diego/T/#t
> 
>  arch/arm64/boot/dts/rockchip/rk3576.dtsi | 68 ++++++++++++++++++++++++
>  1 file changed, 68 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index 436232ffe4d1..130d11a2cc89
> 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> @@ -393,6 +393,11 @@ opp-950000000 {
>  		};
>  	};
> 
> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vop_out>;
> +	};
> +
>  	firmware {
>  		scmi: scmi {
>  			compatible = "arm,scmi-smc";
> @@ -826,6 +831,69 @@ gpu: gpu at 27800000 {
>  			status = "disabled";
>  		};
> 
> +		vop: vop at 27d00000 {
> +			compatible = "rockchip,rk3576-vop";
> +			reg = <0x0 0x27d00000 0x0 0x3000>, <0x0 0x27d05000 
0x0 0x1000>;
> +			reg-names = "vop", "gamma-lut";
> +			interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 380 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "vop-sys",
> +					  "vop-vp0",
> +					  "vop-vp1",
> +					  "vop-vp2";

These need to be renamed without the 'vop-' prefix.

> +			clocks = <&cru ACLK_VOP>,
> +				 <&cru HCLK_VOP>,
> +				 <&cru DCLK_VP0>,
> +				 <&cru DCLK_VP1>,
> +				 <&cru DCLK_VP2>;
> +			clock-names = "aclk",
> +				      "hclk",
> +				      "dclk_vp0",
> +				      "dclk_vp1",
> +				      "dclk_vp2";
> +			iommus = <&vop_mmu>;
> +			power-domains = <&power RK3576_PD_VOP>;
> +			rockchip,grf = <&sys_grf>;
> +			rockchip,pmu = <&pmu>;
> +			status = "disabled";
> +
> +			vop_out: ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				vp0: port at 0 {
> +					#address-cells = <1>;
> +					#size-cells = <0>;
> +					reg = <0>;
> +				};
> +
> +				vp1: port at 1 {
> +					#address-cells = <1>;
> +					#size-cells = <0>;
> +					reg = <1>;
> +				};
> +
> +				vp2: port at 2 {
> +					#address-cells = <1>;
> +					#size-cells = <0>;
> +					reg = <2>;
> +				};
> +			};
> +		};
> +
> +		vop_mmu: iommu at 27d07e00 {
> +			compatible = "rockchip,rk3576-iommu", 
"rockchip,rk3568-iommu";
> +			reg = <0x0 0x27d07e00 0x0 0x100>, <0x0 0x27d07f00 
0x0 0x100>;
> +			interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
> +			clock-names = "aclk", "iface";
> +			#iommu-cells = <0>;
> +			power-domains = <&power RK3576_PD_VOP>;
> +			status = "disabled";
> +		};
> +
>  		qos_hdcp1: qos at 27f02000 {
>  			compatible = "rockchip,rk3576-qos", "syscon";
>  			reg = <0x0 0x27f02000 0x0 0x20>;

Regards,
Detlev




From broonie at kernel.org  Tue Mar  4 09:17:27 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 4 Mar 2025 17:17:27 +0000
Subject: [PATCH 3/3] ASoC: mediatek: mt8188-mt6359: Add headset jack
 detect support
In-Reply-To: <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
Message-ID: <e544340c-af89-4ba5-b22c-a1fbe1bc18c9@sirena.org.uk>

On Fri, Feb 14, 2025 at 12:14:31PM -0300, N?colas F. R. A. Prado wrote:
> Enable headset jack detection for MT8188 platforms using the MT6359
> ACCDET block for it.

This breaks an arm64 defconfig build:

ERROR: modpost: "mt6359_accdet_enable_jack_detect" [sound/soc/mediatek/mt8188/mt8188-mt6359.ko] undefined!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/d1294dbb/attachment.sig>

From detlev.casanova at collabora.com  Tue Mar  4 09:17:30 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Tue, 04 Mar 2025 12:17:30 -0500
Subject: [PATCH v3 2/3] arm64: dts: rockchip: Add hdmi for rk3576
In-Reply-To: <20241231095728.253943-3-andyshrk@163.com>
References: <20241231095728.253943-1-andyshrk@163.com>
 <20241231095728.253943-3-andyshrk@163.com>
Message-ID: <6133294.lOV4Wx5bFT@earth>

Hi Andy,

On Tuesday, 31 December 2024 04:57:19 EST Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Add hdmi and it's phy dt node for rk3576.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
> (no changes since v1)
> 
>  arch/arm64/boot/dts/rockchip/rk3576.dtsi | 58 ++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index 130d11a2cc89..b83f421dc11d
> 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
> @@ -450,6 +450,11 @@ soc {
>  		#size-cells = <2>;
>  		ranges;
> 
> +		hdptxphy_grf: syscon at 26032000 {
> +			compatible = "rockchip,rk3576-hdptxphy-grf", 
"syscon";
> +			reg = <0x0 0x26032000 0x0 0x100>;
> +		};
> +
>  		sys_grf: syscon at 2600a000 {
>  			compatible = "rockchip,rk3576-sys-grf", "syscon";
>  			reg = <0x0 0x2600a000 0x0 0x2000>;
> @@ -894,6 +899,46 @@ vop_mmu: iommu at 27d07e00 {
>  			status = "disabled";
>  		};
> 
> +		hdmi: hdmi at 27da0000 {
> +			compatible = "rockchip,rk3576-dw-hdmi-qp";
> +			reg = <0x0 0x27da0000 0x0 0x20000>;
> +			clocks = <&cru PCLK_HDMITX0>,
> +				 <&cru CLK_HDMITX0_EARC>,
> +				 <&cru CLK_HDMITX0_REF>,
> +				 <&cru MCLK_SAI6_8CH>,
> +				 <&cru CLK_HDMITXHDP>,
> +				 <&cru HCLK_VO0_ROOT>;
> +			clock-names = "pclk", "earc", "ref", "aud", "hdp", 
"hclk_vo1";
> +			interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "avp", "cec", "earc", "main", 
"hpd";
> +			phys = <&hdptxphy>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&hdmi_txm0_pins &hdmi_tx_scl 
&hdmi_tx_sda>;
> +			power-domains = <&power RK3576_PD_VO0>;
> +			resets = <&cru SRST_HDMITX0_REF>, <&cru 
SRST_HDMITXHDP>;
> +			reset-names = "ref", "hdp";
> +			rockchip,grf = <&ioc_grf>;
> +			rockchip,vo-grf = <&vo0_grf>;
> +			status = "disabled";
> +
> +			ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				hdmi_in: port at 0 {
> +					reg = <0>;
> +				};
> +
> +				hdmi_out: port at 1 {
> +					reg = <1>;
> +				};
> +			};
> +		};
> +
>  		qos_hdcp1: qos at 27f02000 {
>  			compatible = "rockchip,rk3576-qos", "syscon";
>  			reg = <0x0 0x27f02000 0x0 0x20>;
> @@ -1655,6 +1700,19 @@ uart11: serial at 2afd0000 {
>  			status = "disabled";
>  		};
> 
> +		hdptxphy: hdmiphy at 2b000000 {
> +			compatible = "rockchip,rk3576-hdptx-phy", 
"rockchip,rk3588-hdptx-phy";
> +			reg = <0x0 0x2b000000 0x0 0x2000>;
> +			clocks = <&cru CLK_PHY_REF_SRC>, <&cru 
PCLK_HDPTX_APB>;
> +			clock-names = "ref", "apb";
> +			resets = <&cru SRST_P_HDPTX_APB>, <&cru 
SRST_HDPTX_INIT>,
> +				 <&cru SRST_HDPTX_CMN>, <&cru 
SRST_HDPTX_LANE>;
> +			reset-names = "apb", "init", "cmn", "lane";
> +			rockchip,grf = <&hdptxphy_grf>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
> +
>  		sram: sram at 3ff88000 {
>  			compatible = "mmio-sram";
>  			reg = <0x0 0x3ff88000 0x0 0x78000>;

This patch needs rebasing over the USB support patches.

Regards,
Detlev.




From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:24 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:24 +0100
Subject: [PATCH v2 3/8] iio: trigger: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-4-fabrice.gasnier@foss.st.com>

From: Olivier Moysan <olivier.moysan at foss.st.com>

Add support for STM32MP25 SoC. Use newly introduced compatible to handle
this new HW variant. Add new trigger definitions that can be used by the
stm32 analog-to-digital converter. Use compatible data to identify them.

Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 drivers/iio/trigger/stm32-lptimer-trigger.c   | 109 +++++++++++++++---
 include/linux/iio/timer/stm32-lptim-trigger.h |   9 ++
 2 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c
index f1e18913236a..995234c1e7d5 100644
--- a/drivers/iio/trigger/stm32-lptimer-trigger.c
+++ b/drivers/iio/trigger/stm32-lptimer-trigger.c
@@ -16,16 +16,44 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 
-/* List Low-Power Timer triggers */
-static const char * const stm32_lptim_triggers[] = {
-	LPTIM1_OUT,
-	LPTIM2_OUT,
-	LPTIM3_OUT,
+/* Maximum triggers + one trailing null entry to indicate the end of array */
+#define MAX_TRIGGERS 3
+
+struct stm32_lptim_cfg {
+	const char * const (*triggers)[MAX_TRIGGERS];
+	unsigned int nb_triggers;
+};
+
+/* List Low-Power Timer triggers for H7, MP13, MP15 */
+static const char * const stm32_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_OUT,},
+	{ LPTIM2_OUT,},
+	{ LPTIM3_OUT,},
+};
+
+/* List Low-Power Timer triggers for STM32MP25 */
+static const char * const stm32mp25_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_CH1, LPTIM1_CH2, },
+	{ LPTIM2_CH1, LPTIM2_CH2, },
+	{ LPTIM3_CH1,},
+	{ LPTIM4_CH1,},
+	{ LPTIM5_OUT,},
+};
+
+static const struct stm32_lptim_cfg stm32mp15_lptim_cfg = {
+	.triggers = stm32_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32_lptim_triggers),
+};
+
+static const struct stm32_lptim_cfg stm32mp25_lptim_cfg = {
+	.triggers = stm32mp25_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32mp25_lptim_triggers),
 };
 
 struct stm32_lptim_trigger {
 	struct device *dev;
-	const char *trg;
+	const char * const *triggers;
+	struct list_head tr_list;
 };
 
 static int stm32_lptim_validate_device(struct iio_trigger *trig,
@@ -54,25 +82,49 @@ bool is_stm32_lptim_trigger(struct iio_trigger *trig)
 }
 EXPORT_SYMBOL(is_stm32_lptim_trigger);
 
-static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv)
+static void stm32_lptim_unregister_triggers(struct stm32_lptim_trigger *priv)
 {
-	struct iio_trigger *trig;
+	struct iio_trigger *tr;
 
-	trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg);
-	if  (!trig)
-		return -ENOMEM;
+	list_for_each_entry(tr, &priv->tr_list, alloc_list)
+		iio_trigger_unregister(tr);
+}
+
+static int stm32_lptim_register_triggers(struct stm32_lptim_trigger *priv)
+{
+	const char * const *cur = priv->triggers;
+	int ret;
 
-	trig->dev.parent = priv->dev->parent;
-	trig->ops = &stm32_lptim_trigger_ops;
-	iio_trigger_set_drvdata(trig, priv);
+	INIT_LIST_HEAD(&priv->tr_list);
 
-	return devm_iio_trigger_register(priv->dev, trig);
+	while (cur && *cur) {
+		struct iio_trigger *trig;
+
+		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
+		if  (!trig)
+			return -ENOMEM;
+
+		trig->dev.parent = priv->dev->parent;
+		trig->ops = &stm32_lptim_trigger_ops;
+		iio_trigger_set_drvdata(trig, priv);
+
+		ret = iio_trigger_register(trig);
+		if (ret)
+			return ret;
+
+		list_add_tail(&trig->alloc_list, &priv->tr_list);
+		cur++;
+	}
+
+	return 0;
 }
 
 static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 {
 	struct stm32_lptim_trigger *priv;
+	struct stm32_lptim_cfg const *lptim_cfg;
 	u32 index;
+	int ret;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -81,23 +133,42 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 	if (device_property_read_u32(&pdev->dev, "reg", &index))
 		return -EINVAL;
 
-	if (index >= ARRAY_SIZE(stm32_lptim_triggers))
+	lptim_cfg = device_get_match_data(&pdev->dev);
+
+	if (index >= lptim_cfg->nb_triggers)
 		return -EINVAL;
 
 	priv->dev = &pdev->dev;
-	priv->trg = stm32_lptim_triggers[index];
+	priv->triggers = lptim_cfg->triggers[index];
+
+	ret = stm32_lptim_register_triggers(priv);
+	if (ret) {
+		stm32_lptim_unregister_triggers(priv);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static void stm32_lptim_trigger_remove(struct platform_device *pdev)
+{
+	struct stm32_lptim_trigger *priv = platform_get_drvdata(pdev);
 
-	return stm32_lptim_setup_trig(priv);
+	stm32_lptim_unregister_triggers(priv);
 }
 
 static const struct of_device_id stm32_lptim_trig_of_match[] = {
-	{ .compatible = "st,stm32-lptimer-trigger", },
+	{ .compatible = "st,stm32-lptimer-trigger", .data = (void *)&stm32mp15_lptim_cfg },
+	{ .compatible = "st,stm32mp25-lptimer-trigger", .data = (void *)&stm32mp25_lptim_cfg},
 	{},
 };
 MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match);
 
 static struct platform_driver stm32_lptim_trigger_driver = {
 	.probe = stm32_lptim_trigger_probe,
+	.remove = stm32_lptim_trigger_remove,
 	.driver = {
 		.name = "stm32-lptimer-trigger",
 		.of_match_table = stm32_lptim_trig_of_match,
diff --git a/include/linux/iio/timer/stm32-lptim-trigger.h b/include/linux/iio/timer/stm32-lptim-trigger.h
index a34dcf6a6001..ce3cf0addb2e 100644
--- a/include/linux/iio/timer/stm32-lptim-trigger.h
+++ b/include/linux/iio/timer/stm32-lptim-trigger.h
@@ -14,6 +14,15 @@
 #define LPTIM1_OUT	"lptim1_out"
 #define LPTIM2_OUT	"lptim2_out"
 #define LPTIM3_OUT	"lptim3_out"
+#define LPTIM4_OUT	"lptim4_out"
+#define LPTIM5_OUT	"lptim5_out"
+
+#define LPTIM1_CH1	"lptim1_ch1"
+#define LPTIM1_CH2	"lptim1_ch2"
+#define LPTIM2_CH1	"lptim2_ch1"
+#define LPTIM2_CH2	"lptim2_ch2"
+#define LPTIM3_CH1	"lptim3_ch1"
+#define LPTIM4_CH1	"lptim4_ch1"
 
 #if IS_REACHABLE(CONFIG_IIO_STM32_LPTIMER_TRIGGER)
 bool is_stm32_lptim_trigger(struct iio_trigger *trig);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:21 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:21 +0100
Subject: [PATCH v2 0/8] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
Message-ID: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>

This series adds support for STM32MP25 to MFD PWM, IIO, counter and
clocksource low-power timer (LPTIM) drivers.
This new variant is managed by using a new DT compatible string, hardware
configuration and version registers.
It comes with a slightly updated register set, some new features and new
interconnect signals inside the SoC.
Same feature list as on STM32MP1x is supported currently.
The device tree files add all instances in stm32mp251 dtsi file.

Changes in V2
---
- Review comments from Krzysztof
  - Adopt compatible fallback in dt-bindings and driver
  - drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
  - counter driver: no update (patch dropped)
  - defconfig: only enable the necessary config for upstream board
  - add lptimer DT node in stm32mp257f-ev1 board
- Add missing management of IER access for stm32mp25

Fabrice Gasnier (7):
  dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
  mfd: stm32-lptimer: add support for stm32mp25
  clocksource: stm32-lptimer: add support for stm32mp25
  pwm: stm32-lp: add support for stm32mp25
  arm64: defconfig: enable STM32 LP timer clockevent driver
  arm64: dts: st: add low-power timer nodes on stm32mp251
  arm64: dts: st: use lptimer3 as tick broadcast source on
    stm32mp257f-ev1

Olivier Moysan (1):
  iio: trigger: stm32-lptimer: add support for stm32mp25

 .../bindings/mfd/st,stm32-lptimer.yaml        |  40 +++-
 arch/arm64/boot/dts/st/stm32mp251.dtsi        | 177 ++++++++++++++
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts    |   8 +
 arch/arm64/configs/defconfig                  |   2 +
 drivers/clocksource/timer-stm32-lp.c          |  26 ++-
 drivers/iio/trigger/stm32-lptimer-trigger.c   | 109 +++++++--
 drivers/mfd/stm32-lptimer.c                   |  33 ++-
 drivers/pwm/pwm-stm32-lp.c                    | 219 +++++++++++++++---
 include/linux/iio/timer/stm32-lptim-trigger.h |   9 +
 include/linux/mfd/stm32-lptimer.h             |  35 ++-
 10 files changed, 599 insertions(+), 59 deletions(-)

-- 
2.25.1



From david at redhat.com  Tue Mar  4 07:48:45 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue,  4 Mar 2025 16:48:45 +0100
Subject: [PATCH -next v1 2/3] kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and uprobe_write_opcode()
In-Reply-To: <20250304154846.1937958-1-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
Message-ID: <20250304154846.1937958-3-david@redhat.com>

We already have the VMA, no need to look it up using
get_user_page_vma_remote(). We can now switch to
get_user_pages_remote().

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 arch/arm/probes/uprobes/core.c |  4 ++--
 include/linux/uprobes.h        |  6 +++---
 kernel/events/uprobes.c        | 33 +++++++++++++++++----------------
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c
index f5f790c6e5f89..885e0c5e8c20d 100644
--- a/arch/arm/probes/uprobes/core.c
+++ b/arch/arm/probes/uprobes/core.c
@@ -26,10 +26,10 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
 		(UPROBE_SWBP_ARM_INSN & 0x0fffffff);
 }
 
-int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+int set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
 	     unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 		   __opcode_to_mem_arm(auprobe->bpinsn));
 }
 
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index a40efdda9052b..4da3bce5e062d 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -186,13 +186,13 @@ struct uprobes_state {
 };
 
 extern void __init uprobes_init(void);
-extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
-extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+extern int set_swbp(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
+extern int set_orig_insn(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
 extern bool is_swbp_insn(uprobe_opcode_t *insn);
 extern bool is_trap_insn(uprobe_opcode_t *insn);
 extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
 extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
-extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
+extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t);
 extern struct uprobe *uprobe_register(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister_nosync(struct uprobe *uprobe, struct uprobe_consumer *uc);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 991aacc80d0e0..0276defd6fbfa 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -474,19 +474,19 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  *
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
-int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-			unsigned long vaddr, uprobe_opcode_t opcode)
+int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr, uprobe_opcode_t opcode)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
 	struct page *old_page, *new_page;
-	struct vm_area_struct *vma;
 	int ret, is_register, ref_ctr_updated = 0;
 	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
@@ -498,9 +498,9 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 	if (is_register)
 		gup_flags |= FOLL_SPLIT_PMD;
 	/* Read the page with vaddr into memory */
-	old_page = get_user_page_vma_remote(mm, vaddr, gup_flags, &vma);
-	if (IS_ERR(old_page))
-		return PTR_ERR(old_page);
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
+	if (ret != 1)
+		return ret;
 
 	ret = verify_opcode(old_page, vaddr, &opcode);
 	if (ret <= 0)
@@ -590,30 +590,31 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, store the breakpoint instruction at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+	return uprobe_write_opcode(auprobe, vma, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
  * set_orig_insn - Restore the original instruction.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @auprobe: arch specific probepoint information.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, restore the original opcode (opcode) at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak
-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_orig_insn(struct arch_uprobe *auprobe,
+		struct vm_area_struct *vma, unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 			*(uprobe_opcode_t *)&auprobe->insn);
 }
 
@@ -1153,7 +1154,7 @@ static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	if (first_uprobe)
 		set_bit(MMF_HAS_UPROBES, &mm->flags);
 
-	ret = set_swbp(&uprobe->arch, mm, vaddr);
+	ret = set_swbp(&uprobe->arch, vma, vaddr);
 	if (!ret)
 		clear_bit(MMF_RECALC_UPROBES, &mm->flags);
 	else if (first_uprobe)
@@ -1168,7 +1169,7 @@ static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
-	return set_orig_insn(&uprobe->arch, mm, vaddr);
+	return set_orig_insn(&uprobe->arch, vma, vaddr);
 }
 
 struct map_info {
-- 
2.48.1



From james.quinlan at broadcom.com  Tue Mar  4 09:24:56 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Tue, 4 Mar 2025 12:24:56 -0500
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of regulator_bulk_get()
In-Reply-To: <20250304170735.x25c65azfpd7xmwv@thinkpad>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com> <20250304150313.ey4fky35bu6dbtxd@thinkpad>
 <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com> <20250304170735.x25c65azfpd7xmwv@thinkpad>
Message-ID: <CA+-6iNzvqnZB=7kRqUm5ie6245AM5ObeVmMNQ_S4AtMLD0jKQw@mail.gmail.com>

On Tue, Mar 4, 2025 at 12:07?PM Manivannan Sadhasivam
<manivannan.sadhasivam at linaro.org> wrote:
>
> On Tue, Mar 04, 2025 at 11:55:05AM -0500, Jim Quinlan wrote:
> > On Tue, Mar 4, 2025 at 10:03?AM Manivannan Sadhasivam
> > <manivannan.sadhasivam at linaro.org> wrote:
> > >
> > > On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > > > If regulator_bulk_get() returns an error, no regulators are created and we
> > > > need to set their number to zero.  If we do not do this and the PCIe
> > > > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> > > >
> > > > Also print out the error value, as we cannot return an error upwards as
> > > > Linux will WARN on an error from add_bus().
> > > >
> > > > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > > > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > > > ---
> > > >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > > index e0b20f58c604..56b49d3cae19 100644
> > > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> > > >
> > > >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> > > >               if (ret) {
> > > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > >
> > > Why is this dev_info() instead of dev_err()?
> >
> > I will change this.
> > >
> > > > +                     pcie->sr = NULL;
> > >
> > > Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?
> >
> > Not sure I understand -- it is already set before a  successful
> > regulator_bulk_get() call.
>
> Didn't I say 'after'?

Sorry, I misinterpreted your question.  I can change it but it would
just be churn because a new commit is going to refactor this function.
However,
I can set  pcie->num_regulators "after" in the new commit.

Regards,
Jim Quinlan
Broadcom STB/CM

>
> > I set it to NULL after an unsuccessful result so the structure will
> > not be passed to subsequent calls.
> >
>
> If you set the pointer after a successful regulator_bulk_get(), you do not need
> to set it to NULL for a failure.
>
> - Mani
>
> --
> ????????? ????????
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4210 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/b7fe1de0/attachment.p7s>

From manivannan.sadhasivam at linaro.org  Tue Mar  4 09:32:09 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 4 Mar 2025 23:02:09 +0530
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <CA+-6iNzvqnZB=7kRqUm5ie6245AM5ObeVmMNQ_S4AtMLD0jKQw@mail.gmail.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com>
 <20250304150313.ey4fky35bu6dbtxd@thinkpad>
 <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com>
 <20250304170735.x25c65azfpd7xmwv@thinkpad>
 <CA+-6iNzvqnZB=7kRqUm5ie6245AM5ObeVmMNQ_S4AtMLD0jKQw@mail.gmail.com>
Message-ID: <20250304173209.bq2lpijsea7aufpu@thinkpad>

On Tue, Mar 04, 2025 at 12:24:56PM -0500, Jim Quinlan wrote:
> On Tue, Mar 4, 2025 at 12:07?PM Manivannan Sadhasivam
> <manivannan.sadhasivam at linaro.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 11:55:05AM -0500, Jim Quinlan wrote:
> > > On Tue, Mar 4, 2025 at 10:03?AM Manivannan Sadhasivam
> > > <manivannan.sadhasivam at linaro.org> wrote:
> > > >
> > > > On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > > > > If regulator_bulk_get() returns an error, no regulators are created and we
> > > > > need to set their number to zero.  If we do not do this and the PCIe
> > > > > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> > > > >
> > > > > Also print out the error value, as we cannot return an error upwards as
> > > > > Linux will WARN on an error from add_bus().
> > > > >
> > > > > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > > > > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > > > > ---
> > > > >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > > > index e0b20f58c604..56b49d3cae19 100644
> > > > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > > > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> > > > >
> > > > >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> > > > >               if (ret) {
> > > > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > > >
> > > > Why is this dev_info() instead of dev_err()?
> > >
> > > I will change this.
> > > >
> > > > > +                     pcie->sr = NULL;
> > > >
> > > > Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?
> > >
> > > Not sure I understand -- it is already set before a  successful
> > > regulator_bulk_get() call.
> >
> > Didn't I say 'after'?
> 
> Sorry, I misinterpreted your question.  I can change it but it would
> just be churn because a new commit is going to refactor this function.
> However,
> I can set  pcie->num_regulators "after" in the new commit.
> 

If a new patch is going to change the beahvior, then I'm fine with it for now.
After all, this series is already merged.

- Mani

-- 
????????? ????????


From james.quinlan at broadcom.com  Tue Mar  4 09:37:26 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Tue, 4 Mar 2025 12:37:26 -0500
Subject: [PATCH v2 6/8] PCI: brcmstb: Use same constant table for config
 space access
In-Reply-To: <20250304165808.t46fh6fwpardheup@thinkpad>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-7-james.quinlan@broadcom.com> <20250304150838.23ca5qbhm4yrpa3h@thinkpad>
 <CA+-6iNzOWU1qLfmSiThdYXX0v5RkbUYtf52yk6KXm6yDDNRUnw@mail.gmail.com> <20250304165808.t46fh6fwpardheup@thinkpad>
Message-ID: <CA+-6iNw2i=4KVr+VYOxacWpP7Pw0E5mDwKY1i9_6V_hjxu9neQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 11:58?AM Manivannan Sadhasivam
<manivannan.sadhasivam at linaro.org> wrote:
>
> On Tue, Mar 04, 2025 at 11:37:14AM -0500, Jim Quinlan wrote:
> > On Tue, Mar 4, 2025 at 10:08?AM Manivannan Sadhasivam
> > <manivannan.sadhasivam at linaro.org> wrote:
> > >
> > > On Fri, Feb 14, 2025 at 12:39:34PM -0500, Jim Quinlan wrote:
> > > > The constants EXT_CFG_DATA and EXT_CFG_INDEX vary by SOC. One of the
> > > > map_bus methods used these constants, the other used different constants.
> > > > Fortunately there was no problem because the SoCs that used the latter
> > > > map_bus method all had the same register constants.
> > > >
> > > > Remove the redundant constants and adjust the code to use them.  In
> > > > addition, update EXT_CFG_DATA to use the 4k-page based config space access
> > > > system, which is what the second map_bus method was already using.
> > > >
> > >
> > > What is the effect of this change? Why is it required? Sounds like it got
> > > sneaked in.
> >
> > Hello,
> > There is no functional difference with this commit -- the code will
> > behave the same.  A previous commit set up the "EXT_CFG_DATA" and
> > "EXT_CFG_INDEX" constants in the offset table but one of the map_bus()
> > methods did not use them, instead it relied on old generic #define
> > constants.  This commit uses them and gets rid of the old #defines.
> >
>
> My comment was about the change that modified the offset of EXT_CFG_DATA. This
> was not justified properly.

Okay, got it.  You are referring to (for example)
-      [EXT_CFG_DATA]          = 0x9004,
+       [EXT_CFG_DATA]          = 0x8000,

We have two ways of accessing the config space: (1) by writing a full
index and reading a  designated register (0x9004) and (2) by writing
the index and then reading from a 4k register region (0x8000 +
offset).  We previously used (1).  An update was made to use (2) but
instead of updating EXT_CFG_DATA from 0x9004 to 0x8000,
PCIE_EXT_CFG_DATA (0x8000) was used by the code of one of the map_bus
methods.

This commit changes the code in the offending map_bus method to use
the offset table for (2) and updates the offset table EXT_CFG_DATA to
its proper value.

If you want me to expand the commit message with the above text I can do that.

Regards,
Jim Quiinlan
Broadcom STB/CM

>
> - Mani
>
> --
> ????????? ????????
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4197 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250304/a391bb14/attachment.p7s>

From sebastianene at google.com  Tue Mar  4 09:38:02 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 4 Mar 2025 17:38:02 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <20250304015633.GA30882@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
 <Z8ZPBZF7J-qKdb_i@google.com>
 <20250304015633.GA30882@willie-the-truck>
Message-ID: <Z8c6enoolJe7Zeqk@google.com>

On Tue, Mar 04, 2025 at 01:56:35AM +0000, Will Deacon wrote:
> On Tue, Mar 04, 2025 at 12:53:25AM +0000, Sebastian Ene wrote:
> > On Mon, Mar 03, 2025 at 11:43:03PM +0000, Will Deacon wrote:
> > > On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> > > > Map the hypervisor's buffers irrespective to the host and return
> > > > a linux error code from the FF-A error code on failure. Remove
> > > > the unmap ff-a buffers calls from the hypervisor as it will
> > > > never be called.
> > > > Prevent the host from using FF-A directly with Trustzone
> > > > if the hypervisor could not map its own buffers.
> > > > 
> > > > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > > > ---
> > > >  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
> > > >  1 file changed, 17 insertions(+), 29 deletions(-)
> > > 
> > > [...]
> > > 
> > > > @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
> > > >  {
> > > >  	struct arm_smccc_res res;
> > > >  	void *tx, *rx;
> > > > +	int ret;
> > > >  
> > > >  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
> > > >  		return 0;
> > > > @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
> > > >  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
> > > >  	};
> > > >  
> > > > +	/* Map our hypervisor buffers into the SPMD */
> > > > +	ret = ffa_map_hyp_buffers();
> > > > +	if (ret)
> > > > +		return ret;
> > > 
> > > Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
> > > arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
> > > the host to negotiate the version lazily?
> > 
> > We still have the same behaviour where we don't allow memory
> > sharing to happen until the version is negotiated but this
> > separates the hypervisor buffer mapping part from the host.
> 
> Sadly, the spec doesn't restrict this to the memory sharing calls:
> 
>   | [...] negotiation of the version must happen before an invocation of
>   | any other FF-A ABI
> 

We do that, as the hypervisor negotiates its own version in
hyp_ffa_init. I think the host shouldn't be allowed to overwrite the
hyp_ffa_version obtained from _init, this feels wrong as you
can have a driver that forcefully downgrades the hypervisor to an old
version.

We need to do three things, Sudeep & Will please correct me if I am
wrong, but this is how I see it:

- the hypervisor should act as a separate entity (it has a different ID and
in the current implementation we don't do a distinction between host/hyp) and
it should be able to lock its own version from init.
- keep a separate version negotiated for the host
- trap FFA_ID_GET from the host and return ID=1 because
  currently we forward the call to the TZ and it returns the same ID
  as the (hypervisor == 0).

> We're also probing the minimum rxtx size in hyp_ffa_post_init() so doing
> this here is doubly wrong.
> 

Those operations should happen before the current ffa_map_hyp_buffers()
call, I agree.

Thanks,
Sebastian

> So I think we should probably just drop this patch.
> 
> Will


From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:25 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:25 +0100
Subject: [PATCH v2 4/8] clocksource: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-5-fabrice.gasnier@foss.st.com>

On stm32mp25, DIER (former IER) must only be modified when the lptimer
is enabled. On earlier SoCs, it must be only be modified when it is
disabled. Read the LPTIM_VERR register to properly manage the enable
state, before accessing IER.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Use version data from MFD core.
- Added interrupt enable register access update in (missed in V1)
---
 drivers/clocksource/timer-stm32-lp.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index a4c95161cb22..96d975adf7a4 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -25,6 +25,7 @@ struct stm32_lp_private {
 	struct clock_event_device clkevt;
 	unsigned long period;
 	struct device *dev;
+	bool ier_wr_enabled;	/* Enables LPTIMER before writing into IER register */
 };
 
 static struct stm32_lp_private*
@@ -37,8 +38,15 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
 {
 	struct stm32_lp_private *priv = to_priv(clkevt);
 
-	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	/* Disable LPTIMER either before or after writing IER register (else, keep it enabled) */
+	if (!priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+
 	regmap_write(priv->reg, STM32_LPTIM_IER, 0);
+
+	if (priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+
 	/* clear pending flags */
 	regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
 
@@ -51,12 +59,21 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
 {
 	struct stm32_lp_private *priv = to_priv(clkevt);
 
-	/* disable LPTIMER to be able to write into IER register*/
-	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	if (!priv->ier_wr_enabled) {
+		/* Disable LPTIMER to be able to write into IER register */
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	} else {
+		/* Enable LPTIMER to be able to write into IER register */
+		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+	}
+
 	/* enable ARR interrupt */
 	regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
+
 	/* enable LPTIMER to be able to write into ARR register */
-	regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+	if (!priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+
 	/* set next event counter */
 	regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
 
@@ -151,6 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	priv->reg = ddata->regmap;
+	priv->ier_wr_enabled = ddata->version == STM32_LPTIM_VERR_23;
 	ret = clk_prepare_enable(ddata->clk);
 	if (ret)
 		return -EINVAL;
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:27 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:27 +0100
Subject: [PATCH v2 6/8] arm64: defconfig: enable STM32 LP timer clockevent driver
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-7-fabrice.gasnier@foss.st.com>

Enable the STM32 LP timer MFD core and clockevent drivers used on
STM32MP257F-EV1 board, for PSCI OSI.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in v2:
- dropped unused IIO trigger, PWM and counter driver unused on upstream
board currently, as advised by Krzysztof
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1f25423de383..b29b2350ae27 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -775,6 +775,7 @@ CONFIG_MFD_TI_LP873X=m
 CONFIG_MFD_TPS65219=y
 CONFIG_MFD_TPS6594_I2C=m
 CONFIG_MFD_ROHM_BD718XX=y
+CONFIG_MFD_STM32_LPTIMER=m
 CONFIG_MFD_WCD934X=m
 CONFIG_MFD_KHADAS_MCU=m
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -1401,6 +1402,7 @@ CONFIG_CLK_RENESAS_VBATTB=m
 CONFIG_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_TEGRA186_TIMER=y
+CONFIG_CLKSRC_STM32_LP=y
 CONFIG_RENESAS_OSTM=y
 CONFIG_ARM_MHU=y
 CONFIG_IMX_MBOX=y
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:23 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:23 +0100
Subject: [PATCH v2 2/8] mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-3-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC.
A new hardware configuration register (HWCFGR2) has been added, to gather
number of capture/compare channels, autonomous mode and input capture
capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
supports a smaller set of features. This can now be read from HWCFGR
registers.

Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
Update the stm32_lptimer data struct so signal the number of
capture/compare channels to the child devices.
Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Compatibility is added by reading hardware configuration
  registers.
- read version register, to be used by clockevent child driver
- rename register/bits definitions
---
 drivers/mfd/stm32-lptimer.c       | 33 ++++++++++++++++++++++++++++-
 include/linux/mfd/stm32-lptimer.h | 35 ++++++++++++++++++++++++++++---
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c
index b2704a9809c7..09073dbc9c80 100644
--- a/drivers/mfd/stm32-lptimer.c
+++ b/drivers/mfd/stm32-lptimer.c
@@ -6,6 +6,7 @@
  * Inspired by Benjamin Gaignard's stm32-timers driver
  */
 
+#include <linux/bitfield.h>
 #include <linux/mfd/stm32-lptimer.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
@@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
 	return 0;
 }
 
+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
+{
+	u32 val;
+	int ret;
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
+	if (ret)
+		return ret;
+
+	/* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
+	if (ret)
+		return ret;
+
+	/* Fallback to legacy init if HWCFGR isn't present */
+	if (!val)
+		return stm32_lptimer_detect_encoder(ddata);
+
+	ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
+	if (ret)
+		return ret;
+
+	/* Number of capture/compare channels */
+	ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
+
+	return 0;
+}
+
 static int stm32_lptimer_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
 	if (IS_ERR(ddata->clk))
 		return PTR_ERR(ddata->clk);
 
-	ret = stm32_lptimer_detect_encoder(ddata);
+	ret = stm32_lptimer_detect_hwcfgr(ddata);
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h
index 06d3f11dc3c9..30ebd3152e1a 100644
--- a/include/linux/mfd/stm32-lptimer.h
+++ b/include/linux/mfd/stm32-lptimer.h
@@ -17,20 +17,28 @@
 #define STM32_LPTIM_IER		0x08	/* Interrupt Enable Reg      */
 #define STM32_LPTIM_CFGR	0x0C	/* Configuration Reg         */
 #define STM32_LPTIM_CR		0x10	/* Control Reg               */
-#define STM32_LPTIM_CMP		0x14	/* Compare Reg               */
+#define STM32_LPTIM_CMP		0x14	/* Compare Reg (MP25 CCR1)   */
 #define STM32_LPTIM_ARR		0x18	/* Autoreload Reg            */
 #define STM32_LPTIM_CNT		0x1C	/* Counter Reg               */
+#define STM32_LPTIM_CCMR1	0x2C	/* Capture/Compare Mode MP25 */
+#define STM32_LPTIM_CCR2	0x34	/* Compare Reg2 MP25         */
+
+#define STM32_LPTIM_HWCFGR2	0x3EC	/* Hardware configuration register 2 - MP25 */
+#define STM32_LPTIM_HWCFGR1	0x3F0	/* Hardware configuration register 1 - MP15 */
+#define STM32_LPTIM_VERR	0x3F4	/* Version identification register - MP15 */
 
 /* STM32_LPTIM_ISR - bit fields */
+#define STM32_LPTIM_CMP2_ARROK		(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOK_ARROK		GENMASK(4, 3)
 #define STM32_LPTIM_ARROK		BIT(4)
 #define STM32_LPTIM_CMPOK		BIT(3)
 
 /* STM32_LPTIM_ICR - bit fields */
-#define STM32_LPTIM_ARRMCF		BIT(1)
+#define STM32_LPTIM_CMP2OKCF_ARROKCF	(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOKCF_ARROKCF	GENMASK(4, 3)
+#define STM32_LPTIM_ARRMCF		BIT(1)
 
-/* STM32_LPTIM_IER - bit flieds */
+/* STM32_LPTIM_IER - bit fields */
 #define STM32_LPTIM_ARRMIE	BIT(1)
 
 /* STM32_LPTIM_CR - bit fields */
@@ -53,16 +61,37 @@
 /* STM32_LPTIM_ARR */
 #define STM32_LPTIM_MAX_ARR	0xFFFF
 
+/* STM32_LPTIM_CCMR1 */
+#define STM32_LPTIM_CC2P	GENMASK(19, 18)
+#define STM32_LPTIM_CC2E	BIT(17)
+#define STM32_LPTIM_CC2SEL	BIT(16)
+#define STM32_LPTIM_CC1P	GENMASK(3, 2)
+#define STM32_LPTIM_CC1E	BIT(1)
+#define STM32_LPTIM_CC1SEL	BIT(0)
+
+/* STM32_LPTIM_HWCFGR1 */
+#define STM32_LPTIM_HWCFGR1_ENCODER	BIT(16)
+
+/* STM32_LPTIM_HWCFGR2 */
+#define STM32_LPTIM_HWCFGR2_CHAN_NUM	GENMASK(3, 0)
+
+/* STM32_LPTIM_VERR */
+#define STM32_LPTIM_VERR_23	0x23	/* STM32MP25 */
+
 /**
  * struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
  * @clk: clock reference for this instance
  * @regmap: register map reference for this instance
  * @has_encoder: indicates this Low-Power Timer supports encoder mode
+ * @num_cc_chans: indicates the number of capture/compare channels
+ * @version: indicates the major and minor revision of the controller
  */
 struct stm32_lptimer {
 	struct clk *clk;
 	struct regmap *regmap;
 	bool has_encoder;
+	unsigned int num_cc_chans;
+	u32 version;
 };
 
 #endif
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:22 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:22 +0100
Subject: [PATCH v2 1/8] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-2-fabrice.gasnier@foss.st.com>

Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
STM32MP25 SoC. Some features has been updated or added to the low-power
timer:
- new capture compare channels
- up to two PWM channels
- PWM input capture
- peripheral interconnect in stm32mp25 has been updated (new triggers).
- registers/bits has been added or revisited (IER access).
So introduce a new compatible to handle this diversity.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- Use fallback compatibles, along with stm32mp25 specific compatible
- trigger identifier can be up to 4 (e.g. from LPTIM1..5)
---
 .../bindings/mfd/st,stm32-lptimer.yaml        | 40 ++++++++++++++++---
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index d41308856408..ca251994cda2 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -21,7 +21,12 @@ maintainers:
 
 properties:
   compatible:
-    const: st,stm32-lptimer
+    oneOf:
+      - items:
+        - const: st,stm32mp25-lptimer
+        - const: st,stm32-lptimer
+      - items:
+        - const: st,stm32-lptimer
 
   reg:
     maxItems: 1
@@ -48,13 +53,21 @@ properties:
     minItems: 1
     maxItems: 2
 
+  power-domains:
+    maxItems: 1
+
   pwm:
     type: object
     additionalProperties: false
 
     properties:
       compatible:
-        const: st,stm32-pwm-lp
+        oneOf:
+          - items:
+            - const: st,stm32mp25-pwm-lp
+            - const: st,stm32-pwm-lp
+          - items:
+            - const: st,stm32-pwm-lp
 
       "#pwm-cells":
         const: 3
@@ -69,7 +82,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-counter
+        oneOf:
+          - items:
+            - const: st,stm32mp25-lptimer-counter
+            - const: st,stm32-lptimer-counter
+          - items:
+            - const: st,stm32-lptimer-counter
 
     required:
       - compatible
@@ -80,7 +98,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-timer
+        oneOf:
+          - items:
+            - const: st,stm32mp25-lptimer-timer
+            - const: st,stm32-lptimer-timer
+          - items:
+            - const: st,stm32-lptimer-timer
 
     required:
       - compatible
@@ -92,13 +115,18 @@ patternProperties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-trigger
+        oneOf:
+          - items:
+            - const: st,stm32mp25-lptimer-trigger
+            - const: st,stm32-lptimer-trigger
+          - items:
+            - const: st,stm32-lptimer-trigger
 
       reg:
         description: Identify trigger hardware block.
         items:
           minimum: 0
-          maximum: 2
+          maximum: 4
 
     required:
       - compatible
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:26 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:26 +0100
Subject: [PATCH v2 5/8] pwm: stm32-lp: add support for stm32mp25
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-6-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC. A new compatible has been added to the
dt-bindings. It represents handle new features, registers and bits
diversity.
It isn't used currently in the driver, as matching is done by retrieving
MFD parent data.

New dedicated capture/compare channels has been added: e.g. a new compare
register for channel 2. Some controls (polarity / cc channel enable) are
handled in CCMR register on this new variant (instead of wavepol bit).

So, Low-power timer can now have up to two PWM outputs. Use device data
from the MFD parent to configure the number of PWM channels e.g. 'npwm'.

Update current get_state() and apply() ops to support either:
- one PWM channel (as on older revision, or LPTIM5 on STM32MP25)
- two PWM channels (e.g. LPTIM1/2/3/4 on STM32MP25 that has the full
  feature set)
Introduce new routines to manage common prescaler, reload register and
global enable bit.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Matching is achieved by using MFD parent data.
- renamed registers/bits defintions
---
 drivers/pwm/pwm-stm32-lp.c | 219 ++++++++++++++++++++++++++++++++-----
 1 file changed, 193 insertions(+), 26 deletions(-)

diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 5832dce8ed9d..4789eafb8bac 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -20,6 +20,7 @@
 struct stm32_pwm_lp {
 	struct clk *clk;
 	struct regmap *regmap;
+	unsigned int num_cc_chans;
 };
 
 static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
@@ -30,13 +31,101 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
 /* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
 #define STM32_LPTIM_MAX_PRESCALER	128
 
+static int stm32_pwm_lp_update_allowed(struct stm32_pwm_lp *priv, int channel)
+{
+	int ret;
+	u32 ccmr1;
+	unsigned long ccmr;
+
+	/* Only one PWM on this LPTIMER: enable, prescaler and reload value can be changed */
+	if (!priv->num_cc_chans)
+		return true;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+	ccmr = ccmr1 & (STM32_LPTIM_CC1E | STM32_LPTIM_CC2E);
+
+	/* More than one channel enabled: enable, prescaler or ARR value can't be changed */
+	if (bitmap_weight(&ccmr, sizeof(u32) * BITS_PER_BYTE) > 1)
+		return false;
+
+	/*
+	 * Only one channel is enabled (or none): check status on the other channel, to
+	 * report if enable, prescaler or ARR value can be changed.
+	 */
+	if (channel)
+		return !(ccmr1 & STM32_LPTIM_CC1E);
+	else
+		return !(ccmr1 & STM32_LPTIM_CC2E);
+}
+
+static int stm32_pwm_lp_compare_channel_apply(struct stm32_pwm_lp *priv, int channel,
+					      bool enable, enum pwm_polarity polarity)
+{
+	u32 ccmr1, val, mask;
+	bool reenable;
+	int ret;
+
+	/* No dedicated CC channel: nothing to do */
+	if (!priv->num_cc_chans)
+		return 0;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+
+	if (channel) {
+		/* Must disable CC channel (CCxE) to modify polarity (CCxP), then re-enable */
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC2E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC2P, ccmr1));
+
+		mask = STM32_LPTIM_CC2SEL | STM32_LPTIM_CC2E | STM32_LPTIM_CC2P;
+		val = FIELD_PREP(STM32_LPTIM_CC2P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC2E, enable);
+	} else {
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC1E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC1P, ccmr1));
+
+		mask = STM32_LPTIM_CC1SEL | STM32_LPTIM_CC1E | STM32_LPTIM_CC1P;
+		val = FIELD_PREP(STM32_LPTIM_CC1P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC1E, enable);
+	}
+
+	if (reenable) {
+		u32 cfgr, presc;
+		unsigned long rate;
+		unsigned int delay_us;
+
+		ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1,
+					 channel ? STM32_LPTIM_CC2E : STM32_LPTIM_CC1E, 0);
+		if (ret)
+			return ret;
+		/*
+		 * After a write to the LPTIM_CCMRx register, a new write operation can only be
+		 * performed after a delay of at least (PRESC ? 3) clock cycles
+		 */
+		ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+		if (ret)
+			return ret;
+		presc = FIELD_GET(STM32_LPTIM_PRESC, cfgr);
+		rate = clk_get_rate(priv->clk) >> presc;
+		if (!rate)
+			return -EINVAL;
+		delay_us = 3 * DIV_ROUND_UP(USEC_PER_SEC, rate);
+		usleep_range(delay_us, delay_us * 2);
+	}
+
+	return regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1, mask, val);
+}
+
 static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			      const struct pwm_state *state)
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long long prd, div, dty;
 	struct pwm_state cstate;
-	u32 val, mask, cfgr, presc = 0;
+	u32 arr, val, mask, cfgr, presc = 0;
 	bool reenable;
 	int ret;
 
@@ -45,10 +134,28 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	if (!state->enabled) {
 		if (cstate.enabled) {
-			/* Disable LP timer */
-			ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+			/* Disable CC channel if any */
+			ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, false,
+								 state->polarity);
 			if (ret)
 				return ret;
+			ret = regmap_write(priv->regmap, pwm->hwpwm ?
+					   STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, 0);
+			if (ret)
+				return ret;
+
+			/* Check if the timer can be disabled */
+			ret = stm32_pwm_lp_update_allowed(priv, pwm->hwpwm);
+			if (ret < 0)
+				return ret;
+
+			if (ret) {
+				/* Disable LP timer */
+				ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+				if (ret)
+					return ret;
+			}
+
 			/* disable clock to PWM counter */
 			clk_disable(priv->clk);
 		}
@@ -79,6 +186,23 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	dty = prd * state->duty_cycle;
 	do_div(dty, state->period);
 
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+	if (ret)
+		return ret;
+
+	/*
+	 * When there are several channels, they share the same prescaler and reload value.
+	 * Check if this can be changed, or the values are the same for all channels.
+	 */
+	if (!stm32_pwm_lp_update_allowed(priv, pwm->hwpwm)) {
+		ret = regmap_read(priv->regmap, STM32_LPTIM_ARR, &arr);
+		if (ret)
+			return ret;
+
+		if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || (arr != prd - 1))
+			return -EBUSY;
+	}
+
 	if (!cstate.enabled) {
 		/* enable clock to drive PWM counter */
 		ret = clk_enable(priv->clk);
@@ -86,15 +210,20 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			return ret;
 	}
 
-	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
-	if (ret)
-		goto err;
-
 	if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||
-	    (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {
+	    ((FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity) && !priv->num_cc_chans)) {
 		val = FIELD_PREP(STM32_LPTIM_PRESC, presc);
-		val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
-		mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;
+		mask = STM32_LPTIM_PRESC;
+
+		if (!priv->num_cc_chans) {
+			/*
+			 * WAVPOL bit is only available when no capature compare channel is used,
+			 * e.g. on LPTIMER instances that have only one output channel. CCMR1 is
+			 * used otherwise.
+			 */
+			val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
+			mask |= STM32_LPTIM_WAVPOL;
+		}
 
 		/* Must disable LP timer to modify CFGR */
 		reenable = true;
@@ -120,20 +249,27 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (ret)
 		goto err;
 
-	ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));
+	/* Write CMP/CCRx register and ensure it's been properly written */
+	ret = regmap_write(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP,
+			   prd - (1 + dty));
 	if (ret)
 		goto err;
 
-	/* ensure CMP & ARR registers are properly written */
-	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
+	/* ensure ARR and CMP/CCRx registers are properly written */
+	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, pwm->hwpwm ?
+				       (val & STM32_LPTIM_CMP2_ARROK) == STM32_LPTIM_CMP2_ARROK :
 				       (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
 				       100, 1000);
 	if (ret) {
 		dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
 		goto err;
 	}
-	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
-			   STM32_LPTIM_CMPOKCF_ARROKCF);
+	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, pwm->hwpwm ?
+			   STM32_LPTIM_CMP2OKCF_ARROKCF : STM32_LPTIM_CMPOKCF_ARROKCF);
+	if (ret)
+		goto err;
+
+	ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, true, state->polarity);
 	if (ret)
 		goto err;
 
@@ -161,11 +297,22 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long rate = clk_get_rate(priv->clk);
-	u32 val, presc, prd;
+	u32 val, presc, prd, ccmr1;
+	bool enabled;
 	u64 tmp;
 
 	regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
-	state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	if (priv->num_cc_chans) {
+		/* There's a CC chan, need to also check if it's enabled */
+		regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+		if (pwm->hwpwm)
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC2E, ccmr1);
+		else
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC1E, ccmr1);
+	}
+	state->enabled = enabled;
+
 	/* Keep PWM counter clock refcount in sync with PWM initial state */
 	if (state->enabled) {
 		int ret = clk_enable(priv->clk);
@@ -176,14 +323,21 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 
 	regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);
 	presc = FIELD_GET(STM32_LPTIM_PRESC, val);
-	state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	if (priv->num_cc_chans) {
+		if (pwm->hwpwm)
+			state->polarity = FIELD_GET(STM32_LPTIM_CC2P, ccmr1);
+		else
+			state->polarity = FIELD_GET(STM32_LPTIM_CC1P, ccmr1);
+	} else {
+		state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	}
 
 	regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);
 	tmp = prd + 1;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
 
-	regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);
+	regmap_read(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, &val);
 	tmp = prd - val;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
@@ -201,15 +355,25 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
 	struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
 	struct stm32_pwm_lp *priv;
 	struct pwm_chip *chip;
+	unsigned int npwm;
 	int ret;
 
-	chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+	if (!ddata->num_cc_chans) {
+		/* No dedicated CC channel, so there's only one PWM channel */
+		npwm = 1;
+	} else {
+		/* There are dedicated CC channels, each with one PWM output */
+		npwm = ddata->num_cc_chans;
+	}
+
+	chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*priv));
 	if (IS_ERR(chip))
 		return PTR_ERR(chip);
 	priv = to_stm32_pwm_lp(chip);
 
 	priv->regmap = ddata->regmap;
 	priv->clk = ddata->clk;
+	priv->num_cc_chans = ddata->num_cc_chans;
 	chip->ops = &stm32_pwm_lp_ops;
 
 	ret = devm_pwmchip_add(&pdev->dev, chip);
@@ -225,12 +389,15 @@ static int stm32_pwm_lp_suspend(struct device *dev)
 {
 	struct pwm_chip *chip = dev_get_drvdata(dev);
 	struct pwm_state state;
-
-	pwm_get_state(&chip->pwms[0], &state);
-	if (state.enabled) {
-		dev_err(dev, "The consumer didn't stop us (%s)\n",
-			chip->pwms[0].label);
-		return -EBUSY;
+	unsigned int i;
+
+	for (i = 0; i < chip->npwm; i++) {
+		pwm_get_state(&chip->pwms[i], &state);
+		if (state.enabled) {
+			dev_err(dev, "The consumer didn't stop us (%s)\n",
+				chip->pwms[i].label);
+			return -EBUSY;
+		}
 	}
 
 	return pinctrl_pm_select_sleep_state(dev);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:29 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:29 +0100
Subject: [PATCH v2 8/8] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-9-fabrice.gasnier@foss.st.com>

During the low power modes the generic ARM timer is deactivated, so the
the tick broadcast is used, based on LPTIMER3 which is clocked by LSE on
STMicroelectronics boards.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1..242115863ab4 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -190,6 +190,14 @@ &i2c8 {
 	status = "disabled";
 };
 
+/* use LPTIMER with tick broadcast for suspend mode */
+&lptimer3 {
+	status = "okay";
+	timer {
+		status = "okay";
+	};
+};
+
 &rtc {
 	status = "okay";
 };
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Tue Mar  4 09:32:28 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Tue, 4 Mar 2025 18:32:28 +0100
Subject: [PATCH v2 7/8] arm64: dts: st: add low-power timer nodes on stm32mp251
In-Reply-To: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250304173229.3215445-8-fabrice.gasnier@foss.st.com>

Add low-power timer (LPTimer) support on STM32MP25 SoC.
The full feature set is implemented in LPTIM1/2/3/4. LPTIM5 supports a
smaller set of features (no capture/compare) channel. Still, LPTIM5 can
be used as single PWM, counter, trigger or timer.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- Adopt two compatibles: newly introduced "st,stm32mp25-..." compatible,
  and fallback "st,stm32-...".
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 +++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008..505176276e72 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -238,6 +238,78 @@ rifsc: bus at 42080000 {
 			#access-controller-cells = <1>;
 			ranges;
 
+			lptimer1: timer at 40090000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x40090000 0x400>;
+				interrupts-extended = <&exti1 47 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM1>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 17>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 0 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <0>;
+					status = "disabled";
+				};
+			};
+
+			lptimer2: timer at 400a0000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x400a0000 0x400>;
+				interrupts-extended = <&exti1 48 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM2>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 18>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 1 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <1>;
+					status = "disabled";
+				};
+			};
+
 			i2s2: audio-controller at 400b0000 {
 				compatible = "st,stm32mp25-i2s";
 				reg = <0x400b0000 0x400>;
@@ -799,6 +871,111 @@ i2c8: i2c at 46040000 {
 				status = "disabled";
 			};
 
+			lptimer3: timer at 46050000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46050000 0x400>;
+				interrupts-extended = <&exti2 29 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM3>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 19>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 2 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <2>;
+					status = "disabled";
+				};
+			};
+
+			lptimer4: timer at 46060000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46060000 0x400>;
+				interrupts-extended = <&exti2 30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM4>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 20>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 3 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <3>;
+					status = "disabled";
+				};
+			};
+
+			lptimer5: timer at 46070000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46070000 0x400>;
+				interrupts-extended = <&exti2 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM5>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 21>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 4 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+
 			csi: csi at 48020000 {
 				compatible = "st,stm32mp25-csi";
 				reg = <0x48020000 0x2000>;
-- 
2.25.1



From helgaas at kernel.org  Tue Mar  4 09:50:10 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 4 Mar 2025 11:50:10 -0600
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <Z8YlySM6Xtr0beo1@lizhi-Precision-Tower-5810>
Message-ID: <20250304175010.GA207565@bhelgaas>

On Mon, Mar 03, 2025 at 04:57:29PM -0500, Frank Li wrote:
> On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> > On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > > for PCI controllers with address translation units.
> > >
> > > Typical PCI data flow involves:
> > >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> > >   PCI Controller (PCI bus address) -> PCI Bus.
> > >
> > > While most bus fabrics preserve address consistency, some modify addresses
> > > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > > translate these intermediate addresses correctly to PCI bus addresses.
> > >
> > > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > > PCI controller drivers.
> > > ...
> >
> > > +++ b/drivers/pci/of.c
> > > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> > >  			res->flags &= ~IORESOURCE_MEM_64;
> > >  		}
> > >
> > > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > > +		/*
> > > +		 * IORESOURCE_IO res->start is io space start address.
> > > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > > +		 * same as range.cpu_addr.
> > > +		 *
> > > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > > +		 */
> > > +
> > > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > > +						   range.cpu_addr - range.parent_bus_addr);
> >
> > I don't know exactly where it needs to go, but I think we can call
> > .cpu_addr_fixup() once at startup on the base of the region.  This
> > will tell us the offset that applies to the entire region, i.e.,
> > parent_bus_offset.
> >
> > Then we can remove all the .cpu_addr_fixup() calls in
> > cdns_pcie_host_init_address_translation(),
> > cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
> >
> > Until we can get rid of all the .cpu_addr_fixup() implementations,
> > We'll still have that single call at startup (I guess once for cadence
> > and another for designware), but it should simplify the current
> > callers quite a bit.
> 
> I don't think it can simple code. cdns_pcie_set_outbound_region() and
> dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
> "resource" to manage outbound windows. 

Let's ignore cadence for now.  I don't think we need to solve that
until later.

dw_pcie_prog_outbound_atu() is called by:

  - dw_pcie_other_conf_map_bus(): atu.parent_bus_addr = pp->cfg0_base

    I think dw_pcie_host_init() can set pp->cfg0_base with the correct
    intermediate address, either via the the of_property_read_reg() or
    .cpu_addr_fixup().

    If dw_pcie_host_init() does this, then we don't need
    .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().

  - dw_pcie_rd_other_conf(): atu.parent_bus_addr = pp->io_base

    Similarly, dw_pcie_host_init() should be able to set pp->io_base
    to the intermediate address, so we don't need .cpu_addr_fixup() in
    dw_pcie_prog_outbound_atu().

  - dw_pcie_iatu_setup(): atu.parent_bus_addr = entry->res->start

    Here "entry" iterates through bridge->windows, and we should be
    able to set entry->parent_bus_offset at init-time, using
    .cpu_addr_fixup() if necessary, so we can apply that offset
    unconditionally, regardless of use_parent_dt_ranges, and we won't
    need .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().

  - dw_pcie_pme_turn_off:
    atu.parent_bus_addr = pci->pp.msg_res->start - pci->pp.msg_parent_bus_offset

    This should be the same as dw_pcie_iatu_setup() since
    msg_parent_bus_offset comes from the window iteration in
    dw_pcie_host_request_msg_tlp_res().  As long as the windows have
    the correct parent_bus_offset at init-time, we should be all set.


From namhyung at kernel.org  Tue Mar  4 10:43:31 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Tue, 4 Mar 2025 10:43:31 -0800
Subject: [PATCH v3 00/12] perf script: Refactor branch flags for Arm SPE
In-Reply-To: <20250304113350.GK2157064@e132581.arm.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250303093853.GG2157064@e132581.arm.com>
 <Z8YYY2Q_ZPIaZ74g@google.com>
 <20250304113350.GK2157064@e132581.arm.com>
Message-ID: <Z8dJ00nIeVqMMncD@google.com>

On Tue, Mar 04, 2025 at 11:33:50AM +0000, Leo Yan wrote:
> On Mon, Mar 03, 2025 at 01:00:19PM -0800, Namhyung Kim wrote:
> > On Mon, Mar 03, 2025 at 09:38:53AM +0000, Leo Yan wrote:
> > > Hi Arnaldo, Namhyung,
> > > 
> > > On Mon, Feb 17, 2025 at 07:58:56PM +0000, Leo Yan wrote:
> > > > This patch series refactors branch flags for support Arm SPE.  The patch
> > > > set is divided into two parts, the first part is for refactoring common
> > > > code and the second part is for enabling Arm SPE.
> > > 
> > > James has given review tags (including the new added patch 06).  Could
> > > you kindly pick up this series?
> > > 
> > > Sorry for pushing a bit, as we have dependency on it.
> > 
> > No problem, I'll add it to the tmp branch and run some tests.
> 
> Thanks a lot, Namhyung!
> 
> I saw you have picked patch series v3 in the tmp.perf-tools-next branch.
> On the other hand, to follow up on Adrian's comment, I have sent out
> v4 to remove an unnecessary change in patch 01, and the rest of the
> patches are exactly the same as v3.
> 
> Please consider picking the latest change (either the whole v4 series or
> just the updated patch 01 would be fine).

Sure, I'll add v4 to the tmp branch soon.

Thanks,
Namhyung



From krzysztof.kozlowski at linaro.org  Tue Mar  4 10:45:30 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 04 Mar 2025 19:45:30 +0100
Subject: [PATCH 0/2] clk: samsung: Two header cleanups
Message-ID: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>

Just two cleanups, no dependencies.

Best regards,
Krzysztof

---
Krzysztof Kozlowski (2):
      clk: samsung: Add missing mod_devicetable.h header
      clk: samsung: Drop unused clk.h and of.h headers

 drivers/clk/samsung/clk-exynos-audss.c   | 1 +
 drivers/clk/samsung/clk-exynos-clkout.c  | 1 +
 drivers/clk/samsung/clk-exynos3250.c     | 4 +---
 drivers/clk/samsung/clk-exynos4.c        | 1 -
 drivers/clk/samsung/clk-exynos4412-isp.c | 2 +-
 drivers/clk/samsung/clk-exynos5250.c     | 1 +
 drivers/clk/samsung/clk-exynos5260.c     | 3 ---
 drivers/clk/samsung/clk-exynos5410.c     | 2 --
 drivers/clk/samsung/clk-exynos5420.c     | 1 +
 drivers/clk/samsung/clk-exynos5433.c     | 4 +---
 drivers/clk/samsung/clk-exynos7.c        | 1 -
 drivers/clk/samsung/clk-exynos7885.c     | 2 +-
 drivers/clk/samsung/clk-exynos850.c      | 2 +-
 drivers/clk/samsung/clk-exynos8895.c     | 2 +-
 drivers/clk/samsung/clk-exynos990.c      | 2 +-
 drivers/clk/samsung/clk-exynosautov9.c   | 2 +-
 drivers/clk/samsung/clk-exynosautov920.c | 2 +-
 drivers/clk/samsung/clk-fsd.c            | 2 +-
 drivers/clk/samsung/clk-gs101.c          | 2 +-
 drivers/clk/samsung/clk-s3c64xx.c        | 1 -
 drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +
 drivers/clk/samsung/clk-s5pv210.c        | 1 -
 drivers/clk/samsung/clk.c                | 1 -
 23 files changed, 16 insertions(+), 25 deletions(-)
---
base-commit: c0eb65494e59d9834af7cbad983629e9017b25a1
change-id: 20250304-clk-samsung-headers-cleanup-c07b8dd50360

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Tue Mar  4 10:45:31 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 04 Mar 2025 19:45:31 +0100
Subject: [PATCH 1/2] clk: samsung: Add missing mod_devicetable.h header
In-Reply-To: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
References: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
Message-ID: <20250304-clk-samsung-headers-cleanup-v1-1-81718e38246e@linaro.org>

Add an include for <mod_devicetable.h> in the drivers which use
of_device_id table to bring its declaration directly, not through some
other headers.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos-audss.c   | 1 +
 drivers/clk/samsung/clk-exynos-clkout.c  | 1 +
 drivers/clk/samsung/clk-exynos3250.c     | 2 +-
 drivers/clk/samsung/clk-exynos4412-isp.c | 1 +
 drivers/clk/samsung/clk-exynos5250.c     | 1 +
 drivers/clk/samsung/clk-exynos5420.c     | 1 +
 drivers/clk/samsung/clk-exynos5433.c     | 1 +
 drivers/clk/samsung/clk-exynos7885.c     | 1 +
 drivers/clk/samsung/clk-exynos850.c      | 1 +
 drivers/clk/samsung/clk-exynos8895.c     | 1 +
 drivers/clk/samsung/clk-exynos990.c      | 1 +
 drivers/clk/samsung/clk-exynosautov9.c   | 1 +
 drivers/clk/samsung/clk-exynosautov920.c | 1 +
 drivers/clk/samsung/clk-fsd.c            | 1 +
 drivers/clk/samsung/clk-gs101.c          | 1 +
 drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +
 16 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index e11ac67819ef26f04edfd4d1a26a5d9fde361aae..0f5ae3e8d000f9edddba4beb3c9a2e10d604c8a3 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index 2ef5748c139b37ca5429b9071ee0e06f44fcf28e..5f1a4f5e2e594f8e858dd92634de2019bbcf1ee3 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -10,6 +10,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index aec4d18c1f9ef93b62b718c85d731a6afd3e6b92..62ae5d845853e6fed2498cecb1151c8cf99bcae4 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -7,10 +7,10 @@
 
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
-
 #include <dt-bindings/clock/exynos3250.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index 29c5644f059379f8a0770ce2214c32b9df7d76e3..a6595b8d918b972208ba0b61d4c0d7f13bccaa3d 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 47e9ac2275ee356481f242ce59772f66daa32f14..e90d3a0848cbc24b2709c10795f6affcda404567 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/exynos5250.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 333c52fda17f69797d2defc36ad6293225d25e8a..a9df4e6db82fa7831d4e5c7210b0163d7d301ec1 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/exynos5420.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk.h>
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 609d31a7aa5247e6318884609d1e651001616b73..61e7e7ce1f60aba005018054aa2155455dece6bb 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
diff --git a/drivers/clk/samsung/clk-exynos7885.c b/drivers/clk/samsung/clk-exynos7885.c
index fc42251731edb6f8368d38638179056f8bc58335..79613affe8ab99d78cc677e688dbb03a2dc7cbb0 100644
--- a/drivers/clk/samsung/clk-exynos7885.c
+++ b/drivers/clk/samsung/clk-exynos7885.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index e00e213b1201c82ac0c70cfe23d5ccc9c04f2aa3..dfbb00312b03eea362f90149bfe36129a0d29285 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
index 29ec0c4a863524fe3fc5c223d762da87e5f13013..66f9b735e3818cc993f1f61acaef4c38bf2a3285 100644
--- a/drivers/clk/samsung/clk-exynos8895.c
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos990.c b/drivers/clk/samsung/clk-exynos990.c
index 76f22a4a4631fadf400420b977f3f59f40f840c7..2cb77a7c3e7830163e8337fd035b5fa426480be5 100644
--- a/drivers/clk/samsung/clk-exynos990.c
+++ b/drivers/clk/samsung/clk-exynos990.c
@@ -7,6 +7,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
index 5971e680e566336ecdf55bdccacc3cea09a33201..1834751650df82a4a89a1a50de4c68d985a0cb60 100644
--- a/drivers/clk/samsung/clk-exynosautov9.c
+++ b/drivers/clk/samsung/clk-exynosautov9.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index 2a8bfd5d9abc8acced4e5a3eaacefe5fa724cbd2..f9b4e9f09bcd0e77ecf99e72273776454b302f31 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 9a6006c298c2a80da0e29aeca3b09cc827caac0c..079d3f4eda3f7acec84cc866b0ea7623104fa257 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 86b39edba12276745a124df6a2ea9c22d74b915a..97a4ccc103f62199cfd7d0d8d4b38bd2e127bfc3 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
index d19a3d9fd45239500c0f811aa27df86f832ea5c0..b1fd8fac3a4c0549f1143d02d11eeb95ee8967d3 100644
--- a/drivers/clk/samsung/clk-s5pv210-audss.c
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 #include <linux/init.h>

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Tue Mar  4 10:45:32 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 04 Mar 2025 19:45:32 +0100
Subject: [PATCH 2/2] clk: samsung: Drop unused clk.h and of.h headers
In-Reply-To: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
References: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
Message-ID: <20250304-clk-samsung-headers-cleanup-v1-2-81718e38246e@linaro.org>

<clk.h> header is for clock consumers, so drop its include from the
Samsung clock controller drivers which do not use the consumer API
(there are few which do, so leave it there).

Drop including of <of.h> and <of_address.h> headers for all drivers
which do not use anything from generic OF API or of_iomap().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos3250.c     | 2 --
 drivers/clk/samsung/clk-exynos4.c        | 1 -
 drivers/clk/samsung/clk-exynos4412-isp.c | 1 -
 drivers/clk/samsung/clk-exynos5260.c     | 3 ---
 drivers/clk/samsung/clk-exynos5410.c     | 2 --
 drivers/clk/samsung/clk-exynos5433.c     | 3 ---
 drivers/clk/samsung/clk-exynos7.c        | 1 -
 drivers/clk/samsung/clk-exynos7885.c     | 1 -
 drivers/clk/samsung/clk-exynos850.c      | 1 -
 drivers/clk/samsung/clk-exynos8895.c     | 1 -
 drivers/clk/samsung/clk-exynos990.c      | 1 -
 drivers/clk/samsung/clk-exynosautov9.c   | 1 -
 drivers/clk/samsung/clk-exynosautov920.c | 1 -
 drivers/clk/samsung/clk-fsd.c            | 1 -
 drivers/clk/samsung/clk-gs101.c          | 1 -
 drivers/clk/samsung/clk-s3c64xx.c        | 1 -
 drivers/clk/samsung/clk-s5pv210.c        | 1 -
 drivers/clk/samsung/clk.c                | 1 -
 18 files changed, 24 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 62ae5d845853e6fed2498cecb1151c8cf99bcae4..84564ec4c8ecfa012743d3fa9826daeab4bb0f75 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -8,8 +8,6 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <dt-bindings/clock/exynos3250.h>
 
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 16be0c53903cf43537d6f5496c106a41eae62838..252cd02bc486837eb1d065e443d6304469e4957c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -9,7 +9,6 @@
 
 #include <dt-bindings/clock/exynos4.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index a6595b8d918b972208ba0b61d4c0d7f13bccaa3d..fa915057e109e0008ebe0b1b5d1652fd5804e82b 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -8,7 +8,6 @@
 
 #include <dt-bindings/clock/exynos4.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index fd0520d204dc7e993b443fa1811c81f0a2e16a3f..0a59598233704b201ea97e907286f761152f54aa 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -6,9 +6,6 @@
  * Common Clock Framework support for Exynos5260 SoC.
  */
 
-#include <linux/of.h>
-#include <linux/of_address.h>
-
 #include "clk-exynos5260.h"
 #include "clk.h"
 #include "clk-pll.h"
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 99b1bb4539fd0f08da61814887af7a40da06b002..baa9988c7bb717cd87fa3c340062afa784985090 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -9,8 +9,6 @@
 #include <dt-bindings/clock/exynos5410.h>
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/clk.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 61e7e7ce1f60aba005018054aa2155455dece6bb..4b2a861e7d573213e92666033893c44ae286b78a 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -6,11 +6,8 @@
  * Common Clock Framework support for Exynos5433 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index e6c938effa29bc067fa4cf864fe721cce37d9fda..fe0fa5bdbd4bca6921d07403637f93ba5c92208d 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -5,7 +5,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
 
 #include "clk.h"
 #include <dt-bindings/clock/exynos7-clk.h>
diff --git a/drivers/clk/samsung/clk-exynos7885.c b/drivers/clk/samsung/clk-exynos7885.c
index 79613affe8ab99d78cc677e688dbb03a2dc7cbb0..ba7cf79bc300112d01cc0f81e1d74f65309707eb 100644
--- a/drivers/clk/samsung/clk-exynos7885.c
+++ b/drivers/clk/samsung/clk-exynos7885.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos7885 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index dfbb00312b03eea362f90149bfe36129a0d29285..cf7e08cca78e04e496703b565881bf64dcf979c8 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos850 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
index 66f9b735e3818cc993f1f61acaef4c38bf2a3285..e6980a8f026fc33645e72a3bdfd3b5eb3a64fa84 100644
--- a/drivers/clk/samsung/clk-exynos8895.c
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos8895 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos990.c b/drivers/clk/samsung/clk-exynos990.c
index 2cb77a7c3e7830163e8337fd035b5fa426480be5..8d3f193d2b4d4c2146d9b8b57d76605b88dc9bbb 100644
--- a/drivers/clk/samsung/clk-exynos990.c
+++ b/drivers/clk/samsung/clk-exynos990.c
@@ -5,7 +5,6 @@
  * Common Clock Framework support for Exynos990.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
index 1834751650df82a4a89a1a50de4c68d985a0cb60..e4d7c7b96aa89be3677890102dd68f514a28aa08 100644
--- a/drivers/clk/samsung/clk-exynosautov9.c
+++ b/drivers/clk/samsung/clk-exynosautov9.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for ExynosAuto V9 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index f9b4e9f09bcd0e77ecf99e72273776454b302f31..dc8d4240f6defc623cc2e075923556747c98a59d 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for ExynosAuto v920 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 079d3f4eda3f7acec84cc866b0ea7623104fa257..594931334574eba949af92095d2408f7a8f56933 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -8,7 +8,6 @@
  * Common Clock Framework support for FSD SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 97a4ccc103f62199cfd7d0d8d4b38bd2e127bfc3..b58b8e1c272d594c2855a043cedcce5a3f293b84 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for GS101.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index e2ec8fe32e392844a85c63d837f10d3331d646f4..397a057af5d1e704e7ead7ba04b477fdc28c45bf 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -8,7 +8,6 @@
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/samsung.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
 
 #include <dt-bindings/clock/samsung,s3c64xx-clock.h>
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index cd85342e4ddbe28538d9f30e88c490089adc5e2c..9a4217cc1908aa60ebbe51b2b5c841138cc46ef3 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 8d440cf56bd45970929bd556b739194ed7b80ce3..80a98461184cb25b8d37df89f646239950623f3f 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -10,7 +10,6 @@
 
 #include <linux/slab.h>
 #include <linux/clkdev.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of_address.h>

-- 
2.43.0



From lkp at intel.com  Tue Mar  4 10:49:38 2025
From: lkp at intel.com (kernel test robot)
Date: Wed, 5 Mar 2025 02:49:38 +0800
Subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker
 script
In-Reply-To: <20250224125414.2184-1-ceggers@arri.de>
References: <20250224125414.2184-1-ceggers@arri.de>
Message-ID: <202503050230.820w99b6-lkp@intel.com>

Hi Christian,

kernel test robot noticed the following build errors:

[auto build test ERROR on soc/for-next]
[also build test ERROR on linus/master v6.14-rc5 next-20250304]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Eggers/ARM-avoid-that-vectors-are-removed-during-linker-garbage-collection/20250224-210146
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
patch link:    https://lore.kernel.org/r/20250224125414.2184-1-ceggers%40arri.de
patch subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker script
config: arm-milbeaut_m10v_defconfig (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503050230.820w99b6-lkp at intel.com/

All errors (new ones prefixed by >>):

>> ld.lld: error: section .vectors.bhb.bpiall virtual address range overlaps with .vectors.bhb.loop8
   >>> .vectors.bhb.bpiall range is [0xFFFF0000, 0xFFFF001F]
   >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
--
>> ld.lld: error: section .vectors.bhb.loop8 virtual address range overlaps with .vectors
   >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
   >>> .vectors range is [0xFFFF0000, 0xFFFF001F]

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From dingwei at marvell.com  Tue Mar  4 11:08:08 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Tue, 4 Mar 2025 19:08:08 +0000
Subject: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset controller
 node
In-Reply-To: <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
Message-ID: <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Monday, March 3, 2025 11:14 PM
> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> robh at kernel.org
> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> sebastian.hesselbarth at gmail.com; krzk+dt at kernel.org; conor+dt at kernel.org;
> p.zabel at pengutronix.de; Sanghoon Lee <salee at marvell.com>;
> Geethasowjanya Akula <gakula at marvell.com>
> Subject: Re: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
> reset controller node
> 
> On 04/03/2025 03:17, Wilson Ding wrote:
> >
> >
> >> -----Original Message-----
> >> From: Krzysztof Kozlowski <krzk at kernel.org>
> >> Sent: Saturday, March 1, 2025 5:46 AM
> >> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> >> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> >> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> >> sebastian.hesselbarth at gmail.com; robh at kernel.org; krzk+dt at kernel.org;
> >> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
> >> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
> >> Subject: Re: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell:
> >> cp11x: Add reset controller node
> >>
> >> On 28/02/2025 21:18, Wilson Ding wrote:
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: Krzysztof Kozlowski <krzk at kernel.org>
> >>>> Sent: Thursday, February 27, 2025 10:57 PM
> >>>> To: Wilson Ding <dingwei at marvell.com>;
> >>>> linux-kernel at vger.kernel.org; devicetree at vger.kernel.org;
> >>>> linux-arm-kernel at lists.infradead.org
> >>>> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> >>>> sebastian.hesselbarth at gmail.com; robh at kernel.org;
> >>>> krzk+dt at kernel.org;
> >>>> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
> >>>> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
> >>>> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x:
> >>>> Add
> >> reset
> >>>> controller node
> >>>>
> >>>> On 27/02/2025 20:?25, Wilson Ding wrote: > Add the reset controller
> >>>> node
> >> as
> >>>> a sub-node to the system controller > node. > > Signed-off-by:
> >>>> Wilson Ding <dingwei@?marvell.?com> > --- >
> >>>> arch/arm64/boot/dts/marvell/armada-
> >>>> cp11x.?dtsi
> >>>>
> >>>> On 27/02/2025 20:25, Wilson Ding wrote:
> >>>>> Add the reset controller node as a sub-node to the system
> >>>>> controller node.
> >>>>>
> >>>>> Signed-off-by: Wilson Ding <dingwei at marvell.com>
> >>>>> ---
> >>>>>  arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 8 ++++++++
> >>>>>  1 file changed, 8 insertions(+)
> >>>>>
> >>>>> diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>>> b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>>>> index 161beec0b6b0..c27058d1534e 100644
> >>>>> --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>>>> +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
> >>>>> @@ -226,6 +226,8 @@ CP11X_LABEL(rtc): rtc at 284000 {
> >>>>>  		CP11X_LABEL(syscon0): system-controller at 440000 {
> >>>>>  			compatible = "syscon", "simple-mfd";
> >>>>>  			reg = <0x440000 0x2000>;
> >>>>> +			#address-cells = <1>;
> >>>>> +			#size-cells = <1>;
> >>>>>
> >>>>>  			CP11X_LABEL(clk): clock {
> >>>>
> >>>> Wait, no unit address here.
> >>>
> >>> This subnode came from the existing code. I didn't touch this
> >>> subnode in my patch. As you can see, the system-controller has a
> >>> wide address range, which includes clock, GPIO registers as well as
> >>> the unit-softreset register.
> >>>
> >>>>
> >>>>>  				compatible = "marvell,cp110-clock"; @@ -
> 273,6 +275,12 @@
> >>>>> CP11X_LABEL(gpio2): gpio at 140 {
> >>>>>  					 <&CP11X_LABEL(clk) 1 17>;
> >>>>>  				status = "disabled";
> >>>>>  			};
> >>>>> +
> >>>>> +			CP11X_LABEL(swrst): reset-controller at 268 {
> >>>>
> >>>>
> >>>> So why here it appeared? This is wrong and not even necessary.
> >>>> Entire child should be folded into parent, so finally you will fix
> >>>> the incomplete parent compatible.
> >>>
> >>> We do need the reset-controller as a subnode under system-controller
> >>> node for the following reasons:
> >>>
> >>> - We need to have 'reg' property in this subnode so that we can get
> >>> the
> >> offset
> >>>   to system-controller register base defined in parent node. This is
> suggested
> >>>   by Rob in V2 comments.
> >>>   And we need to know the register size to calculate the number of
> >>> reset
> >> lines.
> >>>   This is suggested by Philipp in V1 comments.
> >>
> >> You do not need and you received that comment as well. It is implied
> >> by compatible.
> >>
> >>>
> >>> - We also need to define the 'reset-cells' in this subnode. And the
> >>> consumer
> >> of
> >>>   the reset controller uses the label of this subnode for the phandle and
> reset
> >>>   specifier pair.
> >>
> >> reset-cells will be in the parent once you fold it.
> >>
> >>>
> >>> As I mentioned in my reply to the first comment, the
> >>> reset-controller is not
> >> the
> >>> only device within the system-controller register spaces. Do you
> >>> still think I
> >>
> >> You provided very little hardware description of the device. So based
> >> on hardware description you provided: yes.
> >>
> >>> should fold it into the parent node. And what I proposed is exactly
> >>> same as that the armada_thermal driver did (See below). I wonder why
> >>> what was
> >> accepted
> >>> in the past become not accepted now.
> >>
> >> We did not discuss here drivers, but if you insist talking about
> >> "marvell,armada-cp110-thermal" then point me to review or ack from DT
> >> people. You claim it was accepted so how did we accept it?
> >>
> >
> > I didn't intend to extend discussion to the driver in this thread. The
> > following Is the review thread of the dt-binding for the thermal device (in
> 2018).
> > Indeed, there is no comments challenging why not fold the thermal
> > sub-node Into the parent 'syscon' node.
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_l
> > inux-2Darm-2Dkernel_20180703211335.GA8858-40rob-2Dhp-
> 2Dlaptop_&d=DwIDa
> >
> Q&c=nKjWec2b6R0mOyPaz7xtfQ&r=sXDQZu4GyqNVDlFUXakSGJl0Dh81ZIPl
> U26YS4KHG
> >
> IA&m=38vmzSKDh1f33oyqXyKxLMelJiyurSZl38hR43cMNb1JmGrdorIuj2bCEn
> HRs37W&
> > s=MsDwvAhgZcRztTZgawJ_imU4Ld5aZebUxhtCaXUgY5A&e=
> 
> Indeed, this one got review. I was checking armada-thermal and it never got
> any, when it was merged back in the 2013.
> 
> >
> > Digging further, I found some interesting history about the parent
> > 'syscon' node of the reset-controller. I'd appreciate if you can take
> > a look into the following patches/thread -
> >
> > The syscon0 node was initially added along with Armada clock driver
> support.
> > It was the very beginning of the upstream for Armada SoCs support (2016).
> > And the clock driver is one of the earliest drivers to be mainlined.
> > At that time, the clock controller is the only supported device within sycon
> register range.
> > As you can see, the clock dt-binding was exactly aligned with what
> > your suggested (no sub-node, compatible and clock-cells just in syscon).
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_a
> > ll_1460648013-2D31320-2D5-2Dgit-2Dsend-2Demail-
> 2Dthomas.petazzoni-40fr
> > ee-
> 2Delectrons.com_&d=DwIDaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=sXDQZu4Gy
> qNVDl
> >
> FUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=38vmzSKDh1f33oyqXyKxLMelJiyurSZl
> 38hR43
> > cMNb1JmGrdorIuj2bCEnHRs37W&s=pvsI6D-
> tAm32RQzrFFUl7pAclLGStG4bBgQ_iHs2R
> > _Q&e=
> >
> > Besides the clock controller, the system controller also includes the
> > GPIO controller, pinctl controller, reset controller and other
> > miscellaneous configurations. Before adding the pinctl dt-binding,
> > it's decided to use the sub-nodes to present the multiple function blocks of
> various devices.
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_a
> > ll_b27495e10fb4f4d8a7fd1a760d49402bbae83b58.1496328934.git-
> 2Dseries.gr
> > egory.clement-40free-
> 2Delectrons.com_&d=DwIDaQ&c=nKjWec2b6R0mOyPaz7xtf
> >
> Q&r=sXDQZu4GyqNVDlFUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=38vmzSKDh1
> f33oyqXyKx
> >
> LMelJiyurSZl38hR43cMNb1JmGrdorIuj2bCEnHRs37W&s=R58U_4PGdQrcLB
> Wh1gfNnZe
> > voNQfbABbW5QlvgOrAGY&e=
> 
> So this is the source here. I see.
> 
> Commit comes with a rationale that it will grow significantly.
> 
> >
> > In the following patch, it was clearly addressed why sub-nodes was
> > chosen over one flat node.
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_a
> > ll_bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-
> 2Dseries.gr
> > egory.clement-40free-
> 2Delectrons.com_&d=DwIDaQ&c=nKjWec2b6R0mOyPaz7xtf
> >
> Q&r=sXDQZu4GyqNVDlFUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=38vmzSKDh1
> f33oyqXyKx
> >
> LMelJiyurSZl38hR43cMNb1JmGrdorIuj2bCEnHRs37W&s=8U7S14wRqQiL6eO
> C6G2GPpY
> > tlvgFIbmNmEjljAKDdCA&e=
> >
> > "The initial intent when the binding of the cp110 system controller
> > was to have one flat node. The idea being that what is currently a
> > clock-only driver in drivers would become a MFD driver, exposing the
> > clock, GPIO and pinctrl functionality. However, after taking a step
> > back, this would lead to a messy binding. Indeed, a single node would
> > be a GPIO controller, clock controller, pinmux controller, and more.
> >
> > This patch adopts a more classical solution of a top-level syscon node
> > with sub-nodes for the individual devices. The main benefit will be to
> > have each functional block associated to its own sub-node where we can
> > put its own properties."
> >
> > Since then, the dt-binding of Armada's system controller became an
> > exception. But I think it's sensible. If we do put all these
> > controllers into one node, you can image the properties of different
> > devices will be messed up, e.g., not just #reset-cells, #clock-cells
> > and #gpio-cells will be gathered. There will be a long compatible list of all
> devices.
> >
> > Going back to my current patch - if we fold the reset controller into
> > the parent node, the syscon node will become a hybrid, which GPIO and
> > clock controller are still sub-nodes while reset controller is folded
> > into the syscon node. Isn't it very confusing?
> 
> Yes, it will be. But more confusing is existing pattern of mixing MMIO nodes
> with non-MMIO which you grow.So okay, keep them as separate child, but

I did consider shrinking the syscon's register address range to
make the reset-controller node to be independent from the
syscon node. However, I found the syscon node is also referred
by some devices for miscellaneous configurations . The reset
configuration register happens to be located in between these
registers and clock/GPIO registers.

> drop offset in your patch or unify everything into 'reg'.
> 

This is exactly what I proposed in v3 patch. Do I misunderstand
you?

CP11X_LABEL(swrst): reset-controller at 268 {
	compatible = "marvell,armada8k-reset";
	reg = <0x268 0x4>;
	#reset-cells = <1>;
};

> 
> Best regards,
> Krzysztof

From robh at kernel.org  Tue Mar  4 11:15:15 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 04 Mar 2025 13:15:15 -0600
Subject: [PATCH v2 1/8] dt-bindings: mfd: stm32-lptimer: add support
 for stm32mp25
In-Reply-To: <20250304173229.3215445-2-fabrice.gasnier@foss.st.com>
References: <20250304173229.3215445-1-fabrice.gasnier@foss.st.com>
 <20250304173229.3215445-2-fabrice.gasnier@foss.st.com>
Message-ID: <174111571576.3307031.12348647271786435979.robh@kernel.org>


On Tue, 04 Mar 2025 18:32:22 +0100, Fabrice Gasnier wrote:
> Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
> STM32MP25 SoC. Some features has been updated or added to the low-power
> timer:
> - new capture compare channels
> - up to two PWM channels
> - PWM input capture
> - peripheral interconnect in stm32mp25 has been updated (new triggers).
> - registers/bits has been added or revisited (IER access).
> So introduce a new compatible to handle this diversity.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
> Changes in V2:
> - Use fallback compatibles, along with stm32mp25 specific compatible
> - trigger identifier can be up to 4 (e.g. from LPTIM1..5)
> ---
>  .../bindings/mfd/st,stm32-lptimer.yaml        | 40 ++++++++++++++++---
>  1 file changed, 34 insertions(+), 6 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:26:9: [warning] wrong indentation: expected 10 but found 8 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:29:9: [warning] wrong indentation: expected 10 but found 8 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:67:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:70:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:87:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:90:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:103:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:106:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:120:13: [warning] wrong indentation: expected 14 but found 12 (indentation)
./Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml:123:13: [warning] wrong indentation: expected 14 but found 12 (indentation)

dtschema/dtc warnings/errors:

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250304173229.3215445-2-fabrice.gasnier at foss.st.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From catalin.marinas at arm.com  Tue Mar  4 11:15:54 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 4 Mar 2025 19:15:54 +0000
Subject: [PATCH 1/4] asm-generic: barrier: Add
 smp_cond_load_relaxed_timewait()
In-Reply-To: <20250203214911.898276-2-ankur.a.arora@oracle.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-2-ankur.a.arora@oracle.com>
Message-ID: <Z8dRalfxYcJIcLGj@arm.com>

On Mon, Feb 03, 2025 at 01:49:08PM -0800, Ankur Arora wrote:
> Add smp_cond_load_relaxed_timewait(), a timed variant of
> smp_cond_load_relaxed(). This is useful for cases where we want to
> wait on a conditional variable but don't want to wait indefinitely.

Bikeshedding: why not "timeout" rather than "timewait"?

> diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
> index d4f581c1e21d..31de8ed2a05e 100644
> --- a/include/asm-generic/barrier.h
> +++ b/include/asm-generic/barrier.h
> @@ -273,6 +273,54 @@ do {									\
>  })
>  #endif
>  
> +#ifndef smp_cond_time_check_count
> +/*
> + * Limit how often smp_cond_load_relaxed_timewait() evaluates time_expr_ns.
> + * This helps reduce the number of instructions executed while spin-waiting.
> + */
> +#define smp_cond_time_check_count	200
> +#endif

While this was indeed added to the poll_idle() loop, it feels completely
random in a generic implementation. It's highly dependent on the
time_expr_ns passed. Can the caller not move the loop in time_expr_ns
before invoking this macro?

> +
> +/**
> + * smp_cond_load_relaxed_timewait() - (Spin) wait for cond with no ordering
> + * guarantees until a timeout expires.
> + * @ptr: pointer to the variable to wait on
> + * @cond: boolean expression to wait for
> + * @time_expr_ns: evaluates to the current time
> + * @time_limit_ns: compared against time_expr_ns
> + *
> + * Equivalent to using READ_ONCE() on the condition variable.
> + *
> + * Note that the time check in time_expr_ns can be synchronous or
> + * asynchronous.
> + * In the generic version the check is synchronous but kept coarse
> + * to minimize instructions executed while spin-waiting.
> + */

Not sure exactly what synchronous vs asynchronous here mean. I see the
latter more like an interrupt. I guess what you have in mind is the WFE
wakeup events on arm64, though they don't interrupt the instruction
flow. I'd not bother specifying this at all.

> +#ifndef __smp_cond_load_relaxed_spinwait
> +#define __smp_cond_load_relaxed_spinwait(ptr, cond_expr, time_expr_ns,	\
> +					 time_limit_ns) ({		\
> +	typeof(ptr) __PTR = (ptr);					\
> +	__unqual_scalar_typeof(*ptr) VAL;				\
> +	unsigned int __count = 0;					\
> +	for (;;) {							\
> +		VAL = READ_ONCE(*__PTR);				\
> +		if (cond_expr)						\
> +			break;						\
> +		cpu_relax();						\
> +		if (__count++ < smp_cond_time_check_count)		\
> +			continue;					\
> +		if ((time_expr_ns) >= (time_limit_ns))			\
> +			break;						\
> +		__count = 0;						\
> +	}								\
> +	(typeof(*ptr))VAL;						\
> +})
> +#endif
> +
> +#ifndef smp_cond_load_relaxed_timewait
> +#define smp_cond_load_relaxed_timewait  __smp_cond_load_relaxed_spinwait
> +#endif

What I don't particularly like about this interface is (1) no idea of
what time granularity it offers, how much it can slip past the deadline,
even though there's some nanoseconds implied and (2) time_expr_ns leaves
the caller to figure out why time function to use for tracking the time.
Well, I can be ok with (2) if we make it a bit more generic.

The way it is written, I guess the type of the time expression and limit
no longer matters as long as you can compare them. The naming implies
nanoseconds but we don't have such precision, especially with the WFE
implementation for arm64. We could add a slack range argument like the
delta_ns for some of the hrtimer API and let the arch code decide
whether to honour it.

What about we drop the time_limit_ns and build it into the time_expr_ns
as a 'time_cond' argument? The latter would return the result of some
comparison and the loop bails out if true. An additional argument would
be the minimum granularity for checking the time_cond and the arch code
may decide to fall back to busy loops if the granularity is larger than
what the caller required.

-- 
Catalin


From catalin.marinas at arm.com  Tue Mar  4 11:29:07 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 4 Mar 2025 19:29:07 +0000
Subject: [PATCH 3/4] arm64: barrier: Add smp_cond_load_relaxed_timewait()
In-Reply-To: <20250203214911.898276-4-ankur.a.arora@oracle.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-4-ankur.a.arora@oracle.com>
Message-ID: <Z8dUg5zzclvDpPtZ@arm.com>

On Mon, Feb 03, 2025 at 01:49:10PM -0800, Ankur Arora wrote:
> diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
> index 1ca947d5c939..25721275a5a2 100644
> --- a/arch/arm64/include/asm/barrier.h
> +++ b/arch/arm64/include/asm/barrier.h
> @@ -216,6 +216,44 @@ do {									\
>  	(typeof(*ptr))VAL;						\
>  })
>  
> +#define __smp_cond_load_relaxed_timewait(ptr, cond_expr,		\
> +					 time_expr_ns, time_limit_ns)	\
> +({									\
> +	typeof(ptr) __PTR = (ptr);					\
> +	__unqual_scalar_typeof(*ptr) VAL;				\
> +	for (;;) {							\
> +		VAL = READ_ONCE(*__PTR);				\
> +		if (cond_expr)						\
> +			break;						\
> +		__cmpwait_relaxed(__PTR, VAL);				\
> +		if ((time_expr_ns) >= (time_limit_ns))			\
> +			break;						\
> +	}								\
> +	(typeof(*ptr))VAL;						\
> +})

Rename this to something like *_evstrm as this doesn't really work
unless we have the event stream. Another one would be *_wfet.

> +
> +/*
> + * For the unlikely case that the event-stream is unavailable,
> + * ward off the possibility of waiting forever by falling back
> + * to the generic spin-wait.
> + */
> +#define smp_cond_load_relaxed_timewait(ptr, cond_expr,			\
> +				       time_expr_ns, time_limit_ns)	\
> +({									\
> +	__unqual_scalar_typeof(*ptr) _val;				\
> +	int __wfe = arch_timer_evtstrm_available();			\

This should be a bool.

> +									\
> +	if (likely(__wfe))						\
> +		_val = __smp_cond_load_relaxed_timewait(ptr, cond_expr,	\
> +							time_expr_ns,	\
> +							time_limit_ns);	\
> +	else								\
> +		_val = __smp_cond_load_relaxed_spinwait(ptr, cond_expr,	\
> +							time_expr_ns,	\
> +							time_limit_ns);	\
> +	(typeof(*ptr))_val;						\
> +})

Not sure there's much to say here, this depends on the actual interface
introduced by patch 1. If we make some statements about granularity of
some time_cond_expr check, we'll have to take that into account.

-- 
Catalin


From mehdi.djait at linux.intel.com  Tue Mar  4 11:41:14 2025
From: mehdi.djait at linux.intel.com (Mehdi Djait)
Date: Tue, 4 Mar 2025 20:41:14 +0100
Subject: [PATCH v4 06/11] media: rockchip: rkcif: add driver for mipi
 csi-2 host
In-Reply-To: <20250219-v6-8-topic-rk3568-vicap-v4-6-e906600ae3b0@wolfvision.net>
References: <20250219-v6-8-topic-rk3568-vicap-v4-0-e906600ae3b0@wolfvision.net>
 <20250219-v6-8-topic-rk3568-vicap-v4-6-e906600ae3b0@wolfvision.net>
Message-ID: <3fztpczfxlfzt3bdll4alzllrrqvvr3akhkiqtmtam2v2sbw2y@6hb3aok7h62x>

Hi Michael,

thank you for the patches.

Sorry for the big delay!

On Wed, Feb 19, 2025 at 11:16:37AM +0100, Michael Riesch wrote:
> The Rockchip RK3568 MIPI CSI-2 Host is a CSI-2 bridge with one input port
> and one output port. It receives the data with the help of an external
> MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip RK3568 Video
> Capture (VICAP) block. Add a V4L2 subdevice driver for this unit.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  drivers/media/platform/rockchip/rkcif/Makefile     |   1 +
>  .../platform/rockchip/rkcif/rkcif-mipi-csi-host.c  | 731 +++++++++++++++++++++
>  2 files changed, 732 insertions(+)
> 
> diff --git a/drivers/media/platform/rockchip/rkcif/Makefile b/drivers/media/platform/rockchip/rkcif/Makefile
> index 818424972c7b..0c18efd1f1b4 100644
> --- a/drivers/media/platform/rockchip/rkcif/Makefile
> +++ b/drivers/media/platform/rockchip/rkcif/Makefile
> @@ -4,4 +4,5 @@ rockchip-cif-objs += rkcif-dev.o \
>  	rkcif-capture-dvp.o \
>  	rkcif-capture-mipi.o \
>  	rkcif-interface.o \
> +	rkcif-mipi-csi-host.o \

[..]

>  	rkcif-stream.o
> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
> new file mode 100644
> index 000000000000..fa3f42b2dc55

SNIP

> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
> +
> +static struct platform_driver rkcif_csi_drv = {
> +	.driver = {
> +		   .name = "rockchip-mipi-csi",
> +		   .of_match_table = rkcif_csi_of_match,
> +		   .pm = &rkcif_csi_pm_ops,
> +	},
> +	.probe = rkcif_csi_probe,
> +	.remove = rkcif_csi_remove,
> +};
> +module_platform_driver(rkcif_csi_drv);

[..]

When adding the driver for this CSI-2 Host bridge, you added another
call to  module_platform_driver()

but in the definition of this macro:

"Each module may only use this macro once, and
calling it replaces module_init() and module_exit()"

and as you can see in the diff of the Makefile,
rkcif-mipi-csi-host.0 is part of the same module as rkcif-dev.o, where
you already call module_platform_driver()

I think the solution here is to call
platform_register_drivers(drivers, ARRAY_SIZE(drivers)) in rkcif-dev.c

with

static struct platform_driver * const drivers[] = {
	&rkcif_csi_drv,
	&rkcif_plat_drv,
};

then define module_init() and module_exit()

Btw. MODULE_DEVICE_TABLE() is missing both here and in rkcif-dev.c

> +
> +MODULE_DESCRIPTION("Rockchip MIPI CSI-2 Host platform driver");
> +MODULE_LICENSE("GPL");
> 
> -- 
> 2.34.1
> 

--
Kind Regards
Mehdi Djait


From ziyao at disroot.org  Tue Mar  4 11:49:45 2025
From: ziyao at disroot.org (Yao Zi)
Date: Tue, 4 Mar 2025 19:49:45 +0000
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <20250304121036.1453284-1-amadeus@jmu.edu.cn>
References: <20250301104835.36439-1-ziyao@disroot.org>
 <20250304121036.1453284-1-amadeus@jmu.edu.cn>
Message-ID: <Z8dZWYpABghRHHge@pie.lan>

On Tue, Mar 04, 2025 at 08:10:36PM +0800, Chukun Pan wrote:
> Hi,
> 
> > +	aliases {
> > +		mmc0 = &sdmmc;
> 
> s/mmc0/mmc1

Will take it and add the missing pinctrl, as Jonas already pointed out.

> > +&sdmmc {
> > +	bus-width = <4>;
> > +	cap-mmc-highspeed;
> > +	cap-sd-highspeed;
> 
> I think for sdcard, only cap-sd-highspeed
> is needed, not cap-mmc-highspeed?

This makes sense, will remove it in the next version.

> > +	disable-wp;
> 
> Missing pinctrl.
>
> > +	rockchip,default-sample-phase = <90>;
> 
> It seems that all rk3528 devices need to set this
> default phase, so maybe this can be placed in dtsi?

Yes, since the tuned phase offset is a SoC-specific value, as pointed
out by comment in the driver,

	this is _not_ a value that is dynamically tuned and is also
	_not_ a value that will vary from board to board.  It is a value
	that could vary between different SoC models.

Will take it in the next version, thanks for finding it!

> > +	sd-uhs-sdr104;
> 
> The rk3528 devices uses gpio to switch IO voltage, maybe
> more modes should be added here like vendor kernel?

I cannot get the relationship between things you mentioned. For the
regulator, yes, here vqmmc-supply is missing, as already pointed out by
Jonas.

> And these devices use 3.3V IO voltage by default.
> 
> 	sd-uhs-sdr12;
> 	sd-uhs-sdr25;
> 	sd-uhs-sdr50;
> 	sd-uhs-sdr104;

But I don't think it's necessary to lay out these slower modes
explicitly, since SDR104 seems to imply them, see
sd_update_bus_speed_mode() in drivers/mmc/core/sd.c[1],

        if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
            (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
                        card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
        } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
                   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
                        card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
                    SD_MODE_UHS_SDR50)) {
                        card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
                   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
                        card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
                    MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
                    SD_MODE_UHS_SDR12)) {
                        card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
        }

> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Regards,
Yao Zi

[1]: https://elixir.bootlin.com/linux/v6.13.5/source/drivers/mmc/core/sd.c#L448-L479


From sboyd at kernel.org  Tue Mar  4 11:50:35 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 04 Mar 2025 11:50:35 -0800
Subject: [PATCH] clk: stm32f4: fix an uninitialized variable
In-Reply-To: <20250124111711.1051436-1-dario.binacchi@amarulasolutions.com>
References: <20250124111711.1051436-1-dario.binacchi@amarulasolutions.com>
Message-ID: <2e9b95d5ac648daf07101cc0da77d20a.sboyd@kernel.org>

Quoting Dario Binacchi (2025-01-24 03:16:54)
> The variable s, used by pr_debug() to print the mnemonic of the modulation
> depth in use, was not initialized. Fix the output by addressing the correct
> mnemonic.
> 
> Fixes: 65b3516dbe50 ("clk: stm32f4: support spread spectrum clock generation")
> Reported-by: Dan Carpenter <dan.carpenter at linaro.org>
> Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> 
> ---

Applied to clk-next


From jonas at kwiboo.se  Tue Mar  4 11:55:36 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue, 4 Mar 2025 20:55:36 +0100
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <Z8dZWYpABghRHHge@pie.lan>
References: <20250301104835.36439-1-ziyao@disroot.org>
 <20250304121036.1453284-1-amadeus@jmu.edu.cn> <Z8dZWYpABghRHHge@pie.lan>
Message-ID: <5c429552-bdbb-43d9-8e07-bacda57c0fcf@kwiboo.se>

Hi Yao Zi,

On 2025-03-04 20:49, Yao Zi wrote:
> On Tue, Mar 04, 2025 at 08:10:36PM +0800, Chukun Pan wrote:
>> Hi,
>>
>>> +	aliases {
>>> +		mmc0 = &sdmmc;
>>
>> s/mmc0/mmc1
> 
> Will take it and add the missing pinctrl, as Jonas already pointed out.
> 
>>> +&sdmmc {
>>> +	bus-width = <4>;
>>> +	cap-mmc-highspeed;
>>> +	cap-sd-highspeed;
>>
>> I think for sdcard, only cap-sd-highspeed
>> is needed, not cap-mmc-highspeed?
> 
> This makes sense, will remove it in the next version.

Please do not remove the cap-mmc-highspeed prop, I tested the controller
with a microSD to eMMC adapter and MMC HS speed is supported:

  mmc1: card 59b4 removed
  mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
  mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 52000000Hz, actual 49800000HZ div = 0)
  mmc1: new high speed MMC card at address 0001
  mmcblk1: mmc1:0001 DG4008 7.28 GiB
   mmcblk1: p1 p2
  mmcblk1boot0: mmc1:0001 DG4008 4.00 MiB
  mmcblk1boot1: mmc1:0001 DG4008 4.00 MiB
  mmcblk1rpmb: mmc1:0001 DG4008 4.00 MiB, chardev (499:0)

  ~ # cat /sys/kernel/debug/mmc1/ios
  clock:          52000000 Hz
  vdd:            21 (3.3 ~ 3.4 V)
  bus mode:       2 (push-pull)
  chip select:    0 (don't care)
  power mode:     2 (on)
  bus width:      2 (4 bits)
  timing spec:    1 (mmc high-speed)
  signal voltage: 0 (3.30 V)
  driver type:    0 (driver type B)

Regards,
Jonas

> 
>>> +	disable-wp;
>>
>> Missing pinctrl.
>>
>>> +	rockchip,default-sample-phase = <90>;
>>
>> It seems that all rk3528 devices need to set this
>> default phase, so maybe this can be placed in dtsi?
> 
> Yes, since the tuned phase offset is a SoC-specific value, as pointed
> out by comment in the driver,
> 
> 	this is _not_ a value that is dynamically tuned and is also
> 	_not_ a value that will vary from board to board.  It is a value
> 	that could vary between different SoC models.
> 
> Will take it in the next version, thanks for finding it!
> 
>>> +	sd-uhs-sdr104;
>>
>> The rk3528 devices uses gpio to switch IO voltage, maybe
>> more modes should be added here like vendor kernel?
> 
> I cannot get the relationship between things you mentioned. For the
> regulator, yes, here vqmmc-supply is missing, as already pointed out by
> Jonas.
> 
>> And these devices use 3.3V IO voltage by default.
>>
>> 	sd-uhs-sdr12;
>> 	sd-uhs-sdr25;
>> 	sd-uhs-sdr50;
>> 	sd-uhs-sdr104;
> 
> But I don't think it's necessary to lay out these slower modes
> explicitly, since SDR104 seems to imply them, see
> sd_update_bus_speed_mode() in drivers/mmc/core/sd.c[1],
> 
>         if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
>             (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
>                         card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
>         } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
>                    (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
>                         card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
>         } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
>                     MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
>                     SD_MODE_UHS_SDR50)) {
>                         card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
>         } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
>                     MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
>                    (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
>                         card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
>         } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
>                     MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
>                     MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
>                     SD_MODE_UHS_SDR12)) {
>                         card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
>         }
> 
>> Thanks,
>> Chukun
>>
>> -- 
>> 2.25.1
>>
> 
> Regards,
> Yao Zi
> 
> [1]: https://elixir.bootlin.com/linux/v6.13.5/source/drivers/mmc/core/sd.c#L448-L479



From kw at linux.com  Tue Mar  4 09:54:56 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 02:54:56 +0900
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <20250304173209.bq2lpijsea7aufpu@thinkpad>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-5-james.quinlan@broadcom.com>
 <20250304150313.ey4fky35bu6dbtxd@thinkpad>
 <CA+-6iNyuQskVNjAuX1QcLTPetbfhogGYUTOA01QwNw9YcwAdNQ@mail.gmail.com>
 <20250304170735.x25c65azfpd7xmwv@thinkpad>
 <CA+-6iNzvqnZB=7kRqUm5ie6245AM5ObeVmMNQ_S4AtMLD0jKQw@mail.gmail.com>
 <20250304173209.bq2lpijsea7aufpu@thinkpad>
Message-ID: <20250304175456.GE2310180@rocinante>

Hello,

[...]
> > > > > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > > > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > > > >
> > > > > Why is this dev_info() instead of dev_err()?
> > > >
> > > > I will change this.

I can update this directly on the branch if you want.

> > > > >
> > > > > > +                     pcie->sr = NULL;
> > > > >
> > > > > Why can't you set 'pcie->sr' after successfull regulator_bulk_get()?
> > > >
> > > > Not sure I understand -- it is already set before a  successful
> > > > regulator_bulk_get() call.
> > >
> > > Didn't I say 'after'?
> > 
> > Sorry, I misinterpreted your question.  I can change it but it would
> > just be churn because a new commit is going to refactor this function.
> > However,
> > I can set  pcie->num_regulators "after" in the new commit.
> > 
> 
> If a new patch is going to change the beahvior, then I'm fine with it for now.
> After all, this series is already merged.

There is still time if a follow-up patch would be of benefit there.

Same goes for

	Krzysztof


From chester.a.unal at arinc9.com  Tue Mar  4 09:57:24 2025
From: chester.a.unal at arinc9.com (Chester A. Unal)
Date: Tue, 04 Mar 2025 17:57:24 +0000 (UTC)
Subject: [PATCH net-next v2] dsa: mt7530: Utilize REGMAP_IRQ for interrupt
 handling
In-Reply-To: <221013c3530b61504599e285c341a993f6188f00.1740792674.git.daniel@makrotopia.org>
References: <221013c3530b61504599e285c341a993f6188f00.1740792674.git.daniel@makrotopia.org>
Message-ID: <411daae4-0cf6-4e47-9a38-0fe46cf2825c@arinc9.com>

On 01/03/2025 01:41, Daniel Golle wrote:
> Replace the custom IRQ chip handler and mask/unmask functions with
> REGMAP_IRQ. This significantly simplifies the code and allows for the
> removal of almost all interrupt-related functions from mt7530.c.
> 
> Tested on MT7988A built-in switch (MMIO) as well as MT7531AE IC (MDIO).
> 
> Signed-off-by: Daniel Golle <daniel at makrotopia.org>

Acked-by: Chester A. Unal <chester.a.unal at arinc9.com>

Chester A.


From kw at linux.com  Tue Mar  4 09:58:41 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 02:58:41 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250304171154.njoygsvfd567pb66@thinkpad>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
 <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
 <20250304154638.GB2310180@rocinante>
 <20250304171154.njoygsvfd567pb66@thinkpad>
Message-ID: <20250304175841.GF2310180@rocinante>

Hello,

[...]
> > > > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > > > +   if (ret)
> > > > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > > > >
> > > > > What will happen if ret != 0? still return 0?
> > > 
> > > And that is exactly what happens on Gray Hawk Single with R-Car
> > > V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> > > dwc_pcie_rasdes_debugfs_init() to return -ENODEV.
> > 
> > Thank you for testing and for catching this issue.  Much appreciated.
> > 
> > > > Given that callers of dwc_pcie_debugfs_init() check for errors,
> > > 
> > > Debugfs issues should never be propagated upstream!
> > 
> > Makes complete sense.  Sorry for breaking things here!
> > 
> > > > this probably should correctly bubble up any failure coming from
> > > > dwc_pcie_rasdes_debugfs_init().
> > > >
> > > > I made updates to the code directly on the current branch, have a look:
> > > 
> > > So while applying, you changed this like:
> > > 
> > >             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > >     -       if (ret)
> > >     -               dev_dbg(dev, "RASDES debugfs init failed\n");
> > >     +       if (ret) {
> > >     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
> > >     +               return ret;
> > >     +       }
> > > 
> > >             return 0;
> > > 
> > > Hence this is now a fatal error, causing the probe to fail.
> > 
> > I removed the changed, and also move the log level to be a warning, per:
> > 
> >   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=c6759a967e69aba16aef0d92f43e527b112e98a5
> > 
> > Would this be acceptable here?
> > 
> > Mani, would this be acceptable to you, too?  Given that you posted the
> > following recently:
> > 
> >   https://lore.kernel.org/linux-pci/20250303200055.GA1881771 at rocinante/T/#mab9cbd5834390d259afea056eee9a73d8c3b435f
> > 
> > That said, perhaps moving the log level to a debug would be better served here.
> > 
> 
> Even though debugfs_init() failure is not supposed to fail the probe(),
> dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> failure would be canolically correct IMO.
> 
> So I would still opt to have my version + your previous one.

Sounds good!

I combined both changes (squashed your fix for the RAS DES capability
detection) together directly on the branch.

Thank you!

	Krzysztof


From suzuki.poulose at arm.com  Tue Mar  4 09:59:19 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 4 Mar 2025 17:59:19 +0000
Subject: [PATCH v7 15/45] KVM: arm64: Support timers in realm RECs
In-Reply-To: <20250213161426.102987-16-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-16-steven.price@arm.com>
Message-ID: <d3181dde-1070-4101-a5f7-7e42d0ec2f99@arm.com>

On 13/02/2025 16:13, Steven Price wrote:
> The RMM keeps track of the timer while the realm REC is running, but on
> exit to the normal world KVM is responsible for handling the timers.
> 
> A later patch adds the support for propagating the timer values from the
> exit data structure and calling kvm_realm_timers_update().
> 
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/arch_timer.c  | 45 ++++++++++++++++++++++++++++++++----
>   include/kvm/arm_arch_timer.h |  2 ++
>   2 files changed, 43 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
> index d3d243366536..06b68bcd244f 100644
> --- a/arch/arm64/kvm/arch_timer.c
> +++ b/arch/arm64/kvm/arch_timer.c
> @@ -148,6 +148,13 @@ static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval)
>   
>   static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset)
>   {
> +	struct kvm_vcpu *vcpu = ctxt->vcpu;
> +
> +	if (kvm_is_realm(vcpu->kvm)) {
> +		WARN_ON(offset);
> +		return;
> +	}
> +
>   	if (!ctxt->offset.vm_offset) {
>   		WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt));
>   		return;
> @@ -464,6 +471,21 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
>   	}
>   }
>   
> +void kvm_realm_timers_update(struct kvm_vcpu *vcpu)
> +{
> +	struct arch_timer_cpu *arch_timer = &vcpu->arch.timer_cpu;
> +	int i;
> +
> +	for (i = 0; i < NR_KVM_EL0_TIMERS; i++) {
> +		struct arch_timer_context *timer = &arch_timer->timers[i];
> +		bool status = timer_get_ctl(timer) & ARCH_TIMER_CTRL_IT_STAT;
> +		bool level = kvm_timer_irq_can_fire(timer) && status;
> +
> +		if (level != timer->irq.level)
> +			kvm_timer_update_irq(vcpu, level, timer);
> +	}
> +}
> +
>   /* Only called for a fully emulated timer */
>   static void timer_emulate(struct arch_timer_context *ctx)
>   {
> @@ -889,6 +911,8 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
>   	if (unlikely(!timer->enabled))
>   		return;
>   
> +	kvm_timer_unblocking(vcpu);
> +
>   	get_timer_map(vcpu, &map);
>   
>   	if (static_branch_likely(&has_gic_active_state)) {
> @@ -902,8 +926,6 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
>   		kvm_timer_vcpu_load_nogic(vcpu);
>   	}
>   
> -	kvm_timer_unblocking(vcpu);
> -
>   	timer_restore_state(map.direct_vtimer);
>   	if (map.direct_ptimer)
>   		timer_restore_state(map.direct_ptimer);
> @@ -1094,7 +1116,9 @@ static void timer_context_init(struct kvm_vcpu *vcpu, int timerid)
>   
>   	ctxt->vcpu = vcpu;
>   
> -	if (timerid == TIMER_VTIMER)
> +	if (kvm_is_realm(vcpu->kvm))
> +		ctxt->offset.vm_offset = NULL;
> +	else if (timerid == TIMER_VTIMER)
>   		ctxt->offset.vm_offset = &kvm->arch.timer_data.voffset;

I think we need to disable the KVM_CAP_COUNTER_OFFSET for Realms and
also deny KVM_ARM_SET_COUNTER_OFFSET vm_ioctl.

Suzuki




From jonas at kwiboo.se  Tue Mar  4 10:13:10 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue, 4 Mar 2025 19:13:10 +0100
Subject: (subset) [PATCH 0/7] rockchip: Add support for leds and user
 button on Radxa E20C
In-Reply-To: <174108970986.65436.4272591414898454986.b4-ty@sntech.de>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
 <174108970986.65436.4272591414898454986.b4-ty@sntech.de>
Message-ID: <03c34bdf-d470-4c99-bb06-0eb7496465a3@kwiboo.se>

Hi Heiko,

On 2025-03-04 13:02, Heiko Stuebner wrote:
> 
> On Fri, 28 Feb 2025 06:40:06 +0000, Jonas Karlman wrote:
>> The Radxa E20C has three gpio leds and one gpio button.
>>
>> This series adds dt-binding, driver support, DT node in SoC .dtsi and
>> gpio-keys and gpio-leds nodes in board DT to support the leds and user
>> button.
>>
>> This series builds on top of the "rockchip: Add support for maskrom
>> button on Radxa E20C" series [1].
>>
>> [...]
> 
> Applied, thanks!
> 
> [1/7] dt-bindings: soc: rockchip: Add RK3528 ioc grf syscon
>       commit: ac32ad07a97648eb8330b2c4cb840b0ef46903ae
> [4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
>       commit: a31fad19ae39ea27b5068e3b02bcbf30a905339b
> [5/7] arm64: dts: rockchip: Add uart0 pinctrl to Radxa E20C
>       commit: 0d2312f0d3e4ce74af0977c1519a07dfc71a82ac
> 
> Patches 6+7 depend on the parallel saradc support series and thus
> do not apply - and need too much rework to safely apply.

Do you want me to rebase/reorder and send an updated version with
remaining patches? Look like the iio saradc patches [2] is pending apply
so maybe not needed?

[2] https://lore.kernel.org/all/20250304144648.29f376f9 at jic23-huawei/

Regards,
Jonas

> 
> 
> Best regards,



From sboyd at kernel.org  Tue Mar  4 10:16:03 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 04 Mar 2025 10:16:03 -0800
Subject: [PATCH v5 2/2] clk: samsung: add initial exynos7870 clock driver
In-Reply-To: <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org> <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
Message-ID: <b4fb36bc3970293ebdf1ac793bb3d752.sboyd@kernel.org>

Quoting Kaustabh Chakraborty (2025-02-28 19:57:13)
> diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..2ec4a4e489be30bd1cd2e6deac006bb8ac5bdc57
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos7870.c
> @@ -0,0 +1,1830 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2015 Samsung Electronics Co., Ltd.
> + * Author: Kaustabh Chakraborty <kauschluss at disroot.org>
> + *
> + * Common Clock Framework support for Exynos7870.
> + */
> +
> +#include <linux/clk.h>

Please remove this include as this is a clk provider and not a clk
consumer.

> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/samsung,exynos7870-cmu.h>
> +
> +#include "clk.h"
> +#include "clk-exynos-arm64.h"
> +
> +/*
> + * Register offsets for CMU_MIF (0x10460000)
> + */
[...]
> +
> +static const struct samsung_cmu_info peri_cmu_info __initconst = {
> +       .gate_clks              = peri_gate_clks,
> +       .nr_gate_clks           = ARRAY_SIZE(peri_gate_clks),
> +       .clk_regs               = peri_clk_regs,
> +       .nr_clk_regs            = ARRAY_SIZE(peri_clk_regs),
> +       .nr_clk_ids             = PERI_NR_CLK,
> +};
> +
> +static int __init exynos7870_cmu_probe(struct platform_device *pdev)
> +{
> +       const struct samsung_cmu_info *info;
> +       struct device *dev = &pdev->dev;
> +
> +       info = of_device_get_match_data(dev);

Use device APIs please: device_get_match_data()

> +       exynos_arm64_register_cmu(dev, dev->of_node, info);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id exynos7870_cmu_of_match[] = {
> +       {
> +               .compatible = "samsung,exynos7870-cmu-mif",
> +               .data = &mif_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-dispaud",
> +               .data = &dispaud_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-fsys",
> +               .data = &fsys_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-g3d",
> +               .data = &g3d_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-isp",
> +               .data = &isp_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-mfcmscl",
> +               .data = &mfcmscl_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos7870-cmu-peri",
> +               .data = &peri_cmu_info,
> +       }, {
> +       },
> +};
> +
> +static struct platform_driver exynos7870_cmu_driver __refdata = {

Having __refdata here looks wrong.

> +       .driver = {
> +               .name = "exynos7870-cmu",
> +               .of_match_table = exynos7870_cmu_of_match,
> +               .suppress_bind_attrs = true,
> +       },
> +       .probe = exynos7870_cmu_probe,
> +};
> +
> +static int __init exynos7870_cmu_init(void)
> +{
> +       return platform_driver_register(&exynos7870_cmu_driver);

Is this supposed to be platform_driver_probe()? All the __init markings
in the samsung clk driver look like potential problems if anything
defers or is made into a module.


From sboyd at kernel.org  Tue Mar  4 10:19:00 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 04 Mar 2025 10:19:00 -0800
Subject: [PATCH v2 3/3] clk: samsung: introduce Exynos2200 clock driver
In-Reply-To: <20250223115601.723886-4-ivo.ivanov.ivanov1@gmail.com>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com> <20250223115601.723886-4-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <7b182615f1439dd39a17b8e74cf740bf.sboyd@kernel.org>

Quoting Ivaylo Ivanov (2025-02-23 03:56:00)
> diff --git a/drivers/clk/samsung/clk-exynos2200.c b/drivers/clk/samsung/clk-exynos2200.c
> new file mode 100644
> index 000000000..151bdb35a
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos2200.c
> @@ -0,0 +1,3928 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2025 Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> + * Author: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> + *
> + * Common Clock Framework support for Exynos2200 SoC.
> + */
> +
> +#include <linux/clk.h>

Remove this include because this is a clk provider and not a clk
consumer.

> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/samsung,exynos2200-cmu.h>
> +
> +#include "clk.h"
> +#include "clk-exynos-arm64.h"
> +
> +/* NOTE: Must be equal to the last clock ID increased by one */
> +#define CLKS_NR_TOP                    (CLK_DOUT_TCXO_DIV4 + 1)
> +#define CLKS_NR_ALIVE                  (CLK_DOUT_ALIVE_DSP_NOC + 1)
> +#define CLKS_NR_PERIS                  (CLK_DOUT_PERIS_DDD_CTRL + 1)
> +#define CLKS_NR_CMGP                   (CLK_DOUT_CMGP_USI6 + 1)
> +#define CLKS_NR_HSI0                   (CLK_DOUT_DIV_CLK_HSI0_EUSB + 1)
[...]
> +
> +static int __init exynos2200_cmu_probe(struct platform_device *pdev)
> +{
> +       const struct samsung_cmu_info *info;
> +       struct device *dev = &pdev->dev;
> +
> +       info = of_device_get_match_data(dev);

Use device APIs to be firmware agnostic: device_get_match_data() 

> +       exynos_arm64_register_cmu(dev, dev->of_node, info);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id exynos2200_cmu_of_match[] = {
> +       {
> +               .compatible = "samsung,exynos2200-cmu-cmgp",
> +               .data = &cmgp_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-hsi0",
> +               .data = &hsi0_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-peric0",
> +               .data = &peric0_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-peric1",
> +               .data = &peric1_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-peric2",
> +               .data = &peric2_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-ufs",
> +               .data = &ufs_cmu_info,
> +       }, {
> +               .compatible = "samsung,exynos2200-cmu-vts",
> +               .data = &vts_cmu_info,
> +       }, { }
> +};
> +
> +static struct platform_driver exynos2200_cmu_driver __refdata = {
> +       .driver = {
> +               .name = "exynos2200-cmu",
> +               .of_match_table = exynos2200_cmu_of_match,
> +               .suppress_bind_attrs = true,
> +       },
> +       .probe = exynos2200_cmu_probe,
> +};
> +
> +static int __init exynos2200_cmu_init(void)
> +{
> +       return platform_driver_register(&exynos2200_cmu_driver);

Was this supposed to be platform_driver_probe()? The __refdata usage
suggests that but all of the __init markings and stuff in the samsung
clk driver worry me.


From heiko at sntech.de  Tue Mar  4 10:27:18 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 19:27:18 +0100
Subject: (subset) [PATCH 0/7] rockchip: Add support for leds and user button on
 Radxa E20C
In-Reply-To: <03c34bdf-d470-4c99-bb06-0eb7496465a3@kwiboo.se>
References: <20250228064024.3200000-1-jonas@kwiboo.se>
 <174108970986.65436.4272591414898454986.b4-ty@sntech.de>
 <03c34bdf-d470-4c99-bb06-0eb7496465a3@kwiboo.se>
Message-ID: <8941439.NyiUUSuA9g@diego>

Am Dienstag, 4. M?rz 2025, 19:13:10 MEZ schrieb Jonas Karlman:
> Hi Heiko,
> 
> On 2025-03-04 13:02, Heiko Stuebner wrote:
> > 
> > On Fri, 28 Feb 2025 06:40:06 +0000, Jonas Karlman wrote:
> >> The Radxa E20C has three gpio leds and one gpio button.
> >>
> >> This series adds dt-binding, driver support, DT node in SoC .dtsi and
> >> gpio-keys and gpio-leds nodes in board DT to support the leds and user
> >> button.
> >>
> >> This series builds on top of the "rockchip: Add support for maskrom
> >> button on Radxa E20C" series [1].
> >>
> >> [...]
> > 
> > Applied, thanks!
> > 
> > [1/7] dt-bindings: soc: rockchip: Add RK3528 ioc grf syscon
> >       commit: ac32ad07a97648eb8330b2c4cb840b0ef46903ae
> > [4/7] arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
> >       commit: a31fad19ae39ea27b5068e3b02bcbf30a905339b
> > [5/7] arm64: dts: rockchip: Add uart0 pinctrl to Radxa E20C
> >       commit: 0d2312f0d3e4ce74af0977c1519a07dfc71a82ac
> > 
> > Patches 6+7 depend on the parallel saradc support series and thus
> > do not apply - and need too much rework to safely apply.
> 
> Do you want me to rebase/reorder and send an updated version with
> remaining patches? Look like the iio saradc patches [2] is pending apply
> so maybe not needed?

Not sure how long the that test run will be taking ...
and where after -rc5. But in theory things should be fine though.

So essentially up to you - and if you actually have spare minutes.

Heiko






From laurentiumihalcea111 at gmail.com  Tue Mar  4 10:38:37 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 4 Mar 2025 20:38:37 +0200
Subject: [PATCH v4 3/3] arm64: dts: imx: add imx95 dts for sof
In-Reply-To: <Z7zNymSs5qeHp9wL@lizhi-Precision-Tower-5810>
References: <20250211225808.3050-1-laurentiumihalcea111@gmail.com>
 <20250211225808.3050-4-laurentiumihalcea111@gmail.com>
 <Z6vcBvs4xGQ+pGCJ@lizhi-Precision-Tower-5810>
 <36ca7549-aee7-4f14-9311-77978a42362a@gmail.com>
 <Z7zNymSs5qeHp9wL@lizhi-Precision-Tower-5810>
Message-ID: <31451d28-d179-49b7-81fb-0f8914cc9c1a@gmail.com>



On 2/24/2025 9:51 PM, Frank Li wrote:
> On Mon, Feb 24, 2025 at 09:17:03PM +0200, Mihalcea Laurentiu wrote:
>> On 12.02.2025 01:23, Frank Li wrote:
>>> On Tue, Feb 11, 2025 at 05:58:08PM -0500, Laurentiu Mihalcea wrote:
>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>>
>>>> Add imx95 DTS for SOF usage.
>>>>
>>>> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>> ---
>>>>  arch/arm64/boot/dts/freescale/Makefile        |  1 +
>>>>  .../dts/freescale/imx95-19x19-evk-sof.dts     | 85 +++++++++++++++++++
>>>>  2 files changed, 86 insertions(+)
>>>>  create mode 100644 arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts
>>>>
>>>> diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
>>>> index 839432153cc7..27f64e333e4b 100644
>>>> --- a/arch/arm64/boot/dts/freescale/Makefile
>>>> +++ b/arch/arm64/boot/dts/freescale/Makefile
>>>> @@ -282,6 +282,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
>>>>  dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
>>>>  dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
>>>>  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
>>>> +dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb
>>> look like should use dt overlay ?
>>
>> can you pls explain why you'd see this as an overlay?
> It is addtional option, which base on imx95-19x19-evk.dtb. Default wm8962
> is used for built-in dai, this provide option to move it dsp.
>
> Ideally this option should work for all boards, which use wm8962.
>
> We try to move MxN problem to M + N. otherwise, there are huge numbers of
> dtb files.
>
> Frank

Yeah but these are not cameras/sensors (for which there's a lot of possible combinations)
we're dealing with. Unless your board has the same codec, same GPIO for headphone
detection, and uses the same SAI instance this overlay will not work. For instance,
this wouldn't work for the imx95 15x15 EVK board as that uses a different GPIO for
headphone detection. As such, you'll most likely end up with a different DT overlay for
each board instead of a DTB.

Also, from the experience with the IMX8 series, we really don't have many DTBs. Usually,
it's been 1 for the base board and 1 for the audio board if applicable (which can probably
be turned into DT overlays. It would certainly make more sense this way).


Given all this, I'm still not convinced that DT overlays are the way to go.


From ziyao at disroot.org  Tue Mar  4 12:02:14 2025
From: ziyao at disroot.org (Yao Zi)
Date: Tue, 4 Mar 2025 20:02:14 +0000
Subject: [PATCH 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <5c429552-bdbb-43d9-8e07-bacda57c0fcf@kwiboo.se>
References: <20250301104835.36439-1-ziyao@disroot.org>
 <20250304121036.1453284-1-amadeus@jmu.edu.cn>
 <Z8dZWYpABghRHHge@pie.lan>
 <5c429552-bdbb-43d9-8e07-bacda57c0fcf@kwiboo.se>
Message-ID: <Z8dcRjPcbKqEyKdT@pie.lan>

On Tue, Mar 04, 2025 at 08:55:36PM +0100, Jonas Karlman wrote:
> Hi Yao Zi,
> 
> On 2025-03-04 20:49, Yao Zi wrote:
> > On Tue, Mar 04, 2025 at 08:10:36PM +0800, Chukun Pan wrote:
> >> Hi,
> >>
> >>> +	aliases {
> >>> +		mmc0 = &sdmmc;
> >>
> >> s/mmc0/mmc1
> > 
> > Will take it and add the missing pinctrl, as Jonas already pointed out.
> > 
> >>> +&sdmmc {
> >>> +	bus-width = <4>;
> >>> +	cap-mmc-highspeed;
> >>> +	cap-sd-highspeed;
> >>
> >> I think for sdcard, only cap-sd-highspeed
> >> is needed, not cap-mmc-highspeed?
> > 
> > This makes sense, will remove it in the next version.
> 
> Please do not remove the cap-mmc-highspeed prop, I tested the controller
> with a microSD to eMMC adapter and MMC HS speed is supported:
> 
>   mmc1: card 59b4 removed
>   mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
>   mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 52000000Hz, actual 49800000HZ div = 0)
>   mmc1: new high speed MMC card at address 0001
>   mmcblk1: mmc1:0001 DG4008 7.28 GiB
>    mmcblk1: p1 p2
>   mmcblk1boot0: mmc1:0001 DG4008 4.00 MiB
>   mmcblk1boot1: mmc1:0001 DG4008 4.00 MiB
>   mmcblk1rpmb: mmc1:0001 DG4008 4.00 MiB, chardev (499:0)
> 
>   ~ # cat /sys/kernel/debug/mmc1/ios
>   clock:          52000000 Hz
>   vdd:            21 (3.3 ~ 3.4 V)
>   bus mode:       2 (push-pull)
>   chip select:    0 (don't care)
>   power mode:     2 (on)
>   bus width:      2 (4 bits)
>   timing spec:    1 (mmc high-speed)
>   signal voltage: 0 (3.30 V)
>   driver type:    0 (driver type B)

Oops, indeed, I didn't expect the adapted usecase and thought only
sdcards could be connected through the interface.

> Regards,
> Jonas

Thanks for the correction,
Yao Zi


From jonas at kwiboo.se  Tue Mar  4 12:16:33 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue,  4 Mar 2025 20:16:33 +0000
Subject: [PATCH v2 0/4] rockchip: Add support for leds and buttons on Radxa E20C
Message-ID: <20250304201642.831218-1-jonas@kwiboo.se>

The Radxa E20C has three GPIO leds, one SARADC maskrom button and one
GPIO user button.

This series add leds, gpio-keys and adc-keys nodes to board DT to
describe the leds and buttons found on Radxa E20C.

Changes in v2:
- Change gpio-leds node name to leds
- Drop patches already applied
- Merge saradc and gpio button series
- Reorder patches

Board schematics for Radxa E20C can be found at [1].

[1] https://dl.radxa.com/e/e20c/v1.10/radxa_e20c_v1100_schematic.pdf

Jonas Karlman (4):
  arm64: dts: rockchip: Add leds node to Radxa E20C
  arm64: dts: rockchip: Add user button to Radxa E20C
  arm64: dts: rockchip: Add SARADC node for RK3528
  arm64: dts: rockchip: Add maskrom button to Radxa E20C

 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 116 ++++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      |  13 ++
 2 files changed, 129 insertions(+)

-- 
2.48.1



From jonas at kwiboo.se  Tue Mar  4 12:16:35 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue,  4 Mar 2025 20:16:35 +0000
Subject: [PATCH v2 2/4] arm64: dts: rockchip: Add user button to Radxa E20C
In-Reply-To: <20250304201642.831218-1-jonas@kwiboo.se>
References: <20250304201642.831218-1-jonas@kwiboo.se>
Message-ID: <20250304201642.831218-3-jonas@kwiboo.se>

Radxa E20C has two buttons, one SARADC maskrom button and one GPIO user
button.

Add support for the user button using a gpio-keys node.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
v2: No change
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 7f0237206405..b378774d2a4e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -7,6 +7,7 @@
 
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include "rk3528.dtsi"
 
@@ -18,6 +19,19 @@ chosen {
 		stdout-path = "serial0:1500000n8";
 	};
 
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_key>;
+
+		button-user {
+			gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
+			label = "USER";
+			linux,code = <BTN_1>;
+			wakeup-source;
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -50,6 +64,12 @@ led-wan {
 };
 
 &pinctrl {
+	gpio-keys {
+		user_key: user-key {
+			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
 	leds {
 		lan_led_g: lan-led-g {
 			rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
-- 
2.48.1



From dsimic at manjaro.org  Tue Mar  4 12:23:21 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Tue, 04 Mar 2025 21:23:21 +0100
Subject: [PATCH] pmdomain: rockchip: add regulator dependency
In-Reply-To: <20250304142803.689201-1-arnd@kernel.org>
References: <20250304142803.689201-1-arnd@kernel.org>
Message-ID: <57dc1e1b8a3f1134c5eed050a81de1b7@manjaro.org>

Hello Arnd,

On 2025-03-04 15:27, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> When CONFIG_REGULATOR is disabled, this pmdomain driver fails to build:
> 
> drivers/pmdomain/rockchip/pm-domains.c:653:30: error: implicit
> declaration of function 'devm_of_regulator_get'; did you mean
> 'devm_regulator_get'? [-Wimplicit-function-declaration]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev,
> pd->node, "domain");
>       |                              ^~~~~~~~~~~~~~~~~~~~~
>       |                              devm_regulator_get
> drivers/pmdomain/rockchip/pm-domains.c:653:28: error: assignment to
> 'struct regulator *' from 'int' makes pointer from integer without a
> cast [-Wint-conversion]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev,
> pd->node, "domain");
>       |                            ^
> 
> Add a Kconfig dependency.
> 
> Fixes: db6df2e3fc16 ("pmdomain: rockchip: add regulator support")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  drivers/pmdomain/rockchip/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pmdomain/rockchip/Kconfig
> b/drivers/pmdomain/rockchip/Kconfig
> index 7e4f9b628f0b..218d43186e5b 100644
> --- a/drivers/pmdomain/rockchip/Kconfig
> +++ b/drivers/pmdomain/rockchip/Kconfig
> @@ -5,6 +5,7 @@ config ROCKCHIP_PM_DOMAINS
>  	bool "Rockchip generic power domain"
>  	depends on PM
>  	depends on HAVE_ARM_SMCCC_DISCOVERY
> +	depends on REGULATOR
>  	select PM_GENERIC_DOMAINS
>  	help
>  	  Say y here to enable power domain support.

Looking good to me, thanks for this patch.

Reviewed-by: Dragan Simic <dsimic at manjaro.org>


From nfraprado at collabora.com  Tue Mar  4 12:16:45 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Tue, 4 Mar 2025 17:16:45 -0300
Subject: [PATCH 3/3] ASoC: mediatek: mt8188-mt6359: Add headset jack
 detect support
In-Reply-To: <d976b28d-f44f-4d51-8b61-4c046c571412@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
 <d976b28d-f44f-4d51-8b61-4c046c571412@collabora.com>
Message-ID: <fc9863ef-8781-46a0-ba8c-6dabd9fb6cdf@notapiano>

On Tue, Mar 04, 2025 at 04:39:33PM +0100, AngeloGioacchino Del Regno wrote:
> Il 14/02/25 16:14, N?colas F. R. A. Prado ha scritto:
> > Enable headset jack detection for MT8188 platforms using the MT6359
> > ACCDET block for it.
> > 
> > Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
> > Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
> > Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> > ---
> >   sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
> >   1 file changed, 43 insertions(+)
> > 
> > diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> > index 2d0d04e0232da07ba43a030b14853322427d55e7..4e19e6cfad1e1f42863b2e2f27131f880c5883bf 100644
> > --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> > +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
> > @@ -17,6 +17,7 @@
> >   #include "mt8188-afe-common.h"
> >   #include "../../codecs/nau8825.h"
> >   #include "../../codecs/mt6359.h"
> > +#include "../../codecs/mt6359-accdet.h"
> >   #include "../../codecs/rt5682.h"
> >   #include "../common/mtk-afe-platform-driver.h"
> >   #include "../common/mtk-soundcard-driver.h"
> > @@ -266,6 +267,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
> >   	},
> >   };
> > +static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = {
> 
> This is the same as nau8825_jack_pins... perhaps we could reuse that?

The difference is the pin name: "Headphone Jack", which results in a difference
in the widget's name. I remember you wanted to not have the "Jack" in the
widget's name to standardize it among other MTK platforms, and we could do that
here by dropping it from the nau8825_jack_pins. But since that name is also used
on the audio routes in a few DTs, those would need updating as well:

arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku0.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku1.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku3.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku2.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku5.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku7.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku4.dts
arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku6.dts

The name is not used in upstream alsa-ucm-conf though, so it should be safe to
update.

In any case, I didn't want to expand the scope of this series to that unrelated
change, so that's why I introduced this separate struct, thinking we could
commonize as a later step.

> 
> > +	{
> > +		.pin    = "Headphone",
> > +		.mask   = SND_JACK_HEADPHONE,
> > +	},
> > +	{
> > +		.pin    = "Headset Mic",
> > +		.mask   = SND_JACK_MICROPHONE,
> > +	},
> > +};
> > +
> >   static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
> >   	SOC_DAPM_PIN_SWITCH("Ext Spk"),
> >   };
> > @@ -500,6 +512,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
> >   	return 0;
> >   }
> > +static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd)
> > +{
> > +	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
> > +	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
> > +	int ret;
> > +
> > +	if (!soc_card_data->accdet)
> > +		return 0;
> 
> I'm not sure... if we have mediatek,accdet (so accdet is present here), but we also
> have a NAU8825, or RT5682S, or ES8326 codec, this function will create a headset
> jack for MT6359, but then mt8188_headset_codec_init() will do the same again!
> 
> I think we should find a way to avoid that situation, as I'm mostly sure that this
> will give issues in the long run.
> 
> Even if it wouldn't, having two headset jacks exposed, of which one doesn't work
> because it doesn't exist on the physical board... would be confusing for the user.

IMO that situation happening would mean the DT is wrong. If the board has the
headset jack pins wired to a headset codec, and that's responsible for jack
detection, then those pins won't be wired to the ACCDET block, and therefore the
board DT shouldn't have the mediatek,accdet property.

I think you're imagining having the mediatek,accdet property always present, and
the logic you propose would allow specifying a headset codec to essentially
override it (making the mediatek,accdet property useless in this case). But
there can also be boards with no jacks at all, and in those cases we don't want
jack widgets exposed to userspace, so the mediatek,accdet property should be
omitted for those boards, and only present on boards where the ACCDET is
actually wired to.

> 
> I guess that the best option here would be:
>  - Let the `for_each_card_prelinks()` loop finish
>  - Check if any of the external codecs are providing 3.5mm jack
>    - External codec providing jack means that the detection should be performed
>      by the external codec, as the jack should not be physically routed to the
>      MediaTek ACCDET related PMIC pins (right?)
>    - No external codec means that the accessory detection can only be performed
>      by the MediaTek ACCDET IP
>  - If external codec manages 3.5mm jack: do nothing
>  - If no external codec managing 3.5mm jack: check if accdet provided in DT and
>    initialize it
> 
> ....unless I'm wrong - and if I am, please explain why (and also add explanation
> to the commit description).

I can add to the commit message:

Only boards that have jack detection managed by the MT6359 ACCDET block will
have the mediatek,accdet property present.

Thanks,
N?colas

> 
> Cheers,
> Angelo
> 
> > +
> > +	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
> > +				   SND_JACK_HEADSET | SND_JACK_BTN_0 |
> > +				   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
> > +				   SND_JACK_BTN_3,
> > +				   jack, mt8188_headset_jack_pins,
> > +				   ARRAY_SIZE(mt8188_headset_jack_pins));
> > +	if (ret) {
> > +		dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack);
> > +	if (ret) {
> > +		dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >   static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
> >   {
> >   	struct snd_soc_component *cmpnt_codec =
> > @@ -512,6 +553,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
> >   	/* mtkaif calibration */
> >   	mt8188_mt6359_mtkaif_calibration(rtd);
> > +	mt8188_mt6359_accdet_init(rtd);
> > +
> >   	return 0;
> >   }
> > 


From dsimic at manjaro.org  Tue Mar  4 12:30:22 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Tue, 04 Mar 2025 21:30:22 +0100
Subject: [PATCH v3 1/3] drm/rockchip: lvds: move pclk preparation in with
 clk_get
In-Reply-To: <20250304124418.111061-2-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
 <20250304124418.111061-2-heiko@sntech.de>
Message-ID: <041c5f0e2371817a27577bd0989b9dca@manjaro.org>

Hello Heiko,

On 2025-03-04 13:44, Heiko Stuebner wrote:
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index 385cf6881504..ecfae8d5da89 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -448,15 +448,13 @@ struct drm_encoder_helper_funcs
> px30_lvds_encoder_helper_funcs = {
>  static int rk3288_lvds_probe(struct platform_device *pdev,
>  			     struct rockchip_lvds *lvds)
>  {
> -	int ret;
> -
>  	lvds->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(lvds->regs))
>  		return PTR_ERR(lvds->regs);
> 
> -	lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
> +	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
>  	if (IS_ERR(lvds->pclk)) {
> -		DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
> +		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");

I'm wondering why this patch isn't replacing deprecated DRM
logging macros with their preferred successors in a couple of
places, just like what the patch 2/3 from this series does?


From heiko at sntech.de  Tue Mar  4 12:44:37 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 21:44:37 +0100
Subject: [PATCH] pmdomain: rockchip: add regulator dependency
In-Reply-To: <20250304142803.689201-1-arnd@kernel.org>
References: <20250304142803.689201-1-arnd@kernel.org>
Message-ID: <3938258.QJadu78ljV@diego>

Am Dienstag, 4. M?rz 2025, 15:27:59 MEZ schrieb Arnd Bergmann:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> When CONFIG_REGULATOR is disabled, this pmdomain driver fails to build:
> 
> drivers/pmdomain/rockchip/pm-domains.c:653:30: error: implicit declaration of function 'devm_of_regulator_get'; did you mean 'devm_regulator_get'? [-Wimplicit-function-declaration]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                              ^~~~~~~~~~~~~~~~~~~~~
>       |                              devm_regulator_get
> drivers/pmdomain/rockchip/pm-domains.c:653:28: error: assignment to 'struct regulator *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                            ^
> 
> Add a Kconfig dependency.
> 
> Fixes: db6df2e3fc16 ("pmdomain: rockchip: add regulator support")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>




From daniel.lezcano at linaro.org  Tue Mar  4 12:46:22 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 4 Mar 2025 21:46:22 +0100
Subject: [PATCH] clocksource: stm32-lptimer: add support for PM
In-Reply-To: <20250224172101.3448398-1-fabrice.gasnier@foss.st.com>
References: <20250224172101.3448398-1-fabrice.gasnier@foss.st.com>
Message-ID: <e4dc9c1a-bdf2-45c9-950a-69f647f6283f@linaro.org>

On 24/02/2025 18:21, Fabrice Gasnier wrote:
> Add support for power management on STM32 LPTIMER clocksource driver:
> - Upon clockevents_suspend(), shutdown the LPTIMER, and balance the
> clk_prepare_enable() from the probe routine.
> - Upon clockevents_resume(), restore the prescaler that may have been lost
> during low power mode, and restore the clock.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---

Applied, thanks



-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From jonas at kwiboo.se  Tue Mar  4 12:16:36 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue,  4 Mar 2025 20:16:36 +0000
Subject: [PATCH v2 3/4] arm64: dts: rockchip: Add SARADC node for RK3528
In-Reply-To: <20250304201642.831218-1-jonas@kwiboo.se>
References: <20250304201642.831218-1-jonas@kwiboo.se>
Message-ID: <20250304201642.831218-4-jonas@kwiboo.se>

Add a device tree node for the SARADC controller used by RK3528.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
v2: No change
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index b1713ed4d7e2..d3e2a64ff2d5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -9,6 +9,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/clock/rockchip,rk3528-cru.h>
+#include <dt-bindings/reset/rockchip,rk3528-cru.h>
 
 / {
 	compatible = "rockchip,rk3528";
@@ -264,6 +265,18 @@ uart7: serial at ffa28000 {
 			status = "disabled";
 		};
 
+		saradc: adc at ffae0000 {
+			compatible = "rockchip,rk3528-saradc";
+			reg = <0x0 0xffae0000 0x0 0x10000>;
+			clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
+			clock-names = "saradc", "apb_pclk";
+			interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&cru SRST_P_SARADC>;
+			reset-names = "saradc-apb";
+			#io-channel-cells = <1>;
+			status = "disabled";
+		};
+
 		pinctrl: pinctrl {
 			compatible = "rockchip,rk3528-pinctrl";
 			rockchip,grf = <&ioc_grf>;
-- 
2.48.1



From jonas at kwiboo.se  Tue Mar  4 12:16:34 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue,  4 Mar 2025 20:16:34 +0000
Subject: [PATCH v2 1/4] arm64: dts: rockchip: Add leds node to Radxa E20C
In-Reply-To: <20250304201642.831218-1-jonas@kwiboo.se>
References: <20250304201642.831218-1-jonas@kwiboo.se>
Message-ID: <20250304201642.831218-2-jonas@kwiboo.se>

Radxa E20C has three gpio controlled leds (sys, wan and lan).

Add led nodes and set default trigger to heartbeat for the sys led and
netdev for the lan and wan leds.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
v2: Rename gpio-leds node to leds
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 5161d22330ab..7f0237206405 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -6,6 +6,8 @@
  */
 
 /dts-v1/;
+
+#include <dt-bindings/leds/common.h>
 #include "rk3528.dtsi"
 
 / {
@@ -15,6 +17,52 @@ / {
 	chosen {
 		stdout-path = "serial0:1500000n8";
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lan_led_g>, <&sys_led_g>, <&wan_led_g>;
+
+		led-lan {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "netdev";
+		};
+
+		led-sys {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "on";
+			function = LED_FUNCTION_HEARTBEAT;
+			gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-wan {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_WAN;
+			gpios = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "netdev";
+		};
+	};
+};
+
+&pinctrl {
+	leds {
+		lan_led_g: lan-led-g {
+			rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		sys_led_g: sys-led-g {
+			rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		wan_led_g: wan-led-g {
+			rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
 };
 
 &uart0 {
-- 
2.48.1



From jonas at kwiboo.se  Tue Mar  4 12:16:37 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Tue,  4 Mar 2025 20:16:37 +0000
Subject: [PATCH v2 4/4] arm64: dts: rockchip: Add maskrom button to Radxa E20C
In-Reply-To: <20250304201642.831218-1-jonas@kwiboo.se>
References: <20250304201642.831218-1-jonas@kwiboo.se>
Message-ID: <20250304201642.831218-5-jonas@kwiboo.se>

Radxa E20C has two buttons, one SARADC maskrom button and one GPIO user
button.

Add support for the maskrom button using a adc-keys node, also add the
regulators used by SARADC controller.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
v2: No change
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index b378774d2a4e..5346ef457c2a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -19,6 +19,20 @@ chosen {
 		stdout-path = "serial0:1500000n8";
 	};
 
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 0>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1800000>;
+		poll-interval = <100>;
+
+		button-maskrom {
+			label = "MASKROM";
+			linux,code = <KEY_SETUP>;
+			press-threshold-microvolt = <0>;
+		};
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		pinctrl-names = "default";
@@ -61,6 +75,35 @@ led-wan {
 			linux,default-trigger = "netdev";
 		};
 	};
+
+	vcc_1v8: regulator-1v8-vcc {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_1v8";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_3v3>;
+	};
+
+	vcc_3v3: regulator-3v3-vcc {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_3v3";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc5v0_sys: regulator-5v0-vcc-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc5v0_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
 };
 
 &pinctrl {
@@ -85,6 +128,11 @@ wan_led_g: wan-led-g {
 	};
 };
 
+&saradc {
+	vref-supply = <&vcc_1v8>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0m0_xfer>;
-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:35 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:35 -0500
Subject: [PATCH v5 5/7] drm/sti: move to devm_platform_ioremap_resource()
 usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-5-fb3dab8d901f@redhat.com>

Replace platform_get_resource/_byname + devm_ioremap
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:

@rule@
identifier res;
expression ioremap;
identifier pdev;
constant mem;
expression name;
@@
-struct resource *res;
...
-res = platform_get_resource_byname(pdev,mem,name);
<...
-if (!res) {
-...
-}
...>
-ioremap = devm_ioremap(...);
+ioremap = devm_platform_ioremap_resource_byname(pdev,name);

and
@rule_2@
identifier res;
expression ioremap;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
<...
-if (!res) {
-...
-}
...>
-ioremap = devm_ioremap(...);
+ioremap = devm_platform_ioremap_resource(pdev,0);

v2: Fix compilation error.
v3: Handle returns properly since the new API return error pointers
and not NULL

Cc: Raphael Gallais-Pou <raphael.gallais-pou at foss.st.com>
Cc: Alain Volmat <alain.volmat at foss.st.com>
Reviewed-by: Maxime Ripard <mripard at kernel.org>(v2)
Acked-by: Raphael Gallais-Pou <rgallaispou at gmail.com>(v2)
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
 drivers/gpu/drm/sti/sti_compositor.c | 14 +++-----------
 drivers/gpu/drm/sti/sti_dvo.c        | 14 +++-----------
 drivers/gpu/drm/sti/sti_hda.c        | 13 +++----------
 drivers/gpu/drm/sti/sti_hdmi.c       | 15 +++------------
 drivers/gpu/drm/sti/sti_hqvdp.c      | 14 +++-----------
 drivers/gpu/drm/sti/sti_tvout.c      | 14 +++-----------
 drivers/gpu/drm/sti/sti_vtg.c        | 14 +++-----------
 7 files changed, 21 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 063f82d23d80c4ba83624a0066a18416a2b37351..8c529b0cca8b48fca532cd15e1f36fbe5bcbc71e 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -177,7 +177,6 @@ static int sti_compositor_probe(struct platform_device *pdev)
 	struct device_node *np = dev->of_node;
 	struct device_node *vtg_np;
 	struct sti_compositor *compo;
-	struct resource *res;
 	unsigned int i;
 
 	compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
@@ -194,17 +193,10 @@ static int sti_compositor_probe(struct platform_device *pdev)
 
 	memcpy(&compo->data, of_match_node(compositor_of_match, np)->data,
 	       sizeof(struct sti_compositor_data));
-
-	/* Get Memory ressources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		DRM_ERROR("Get memory resource failed\n");
-		return -ENXIO;
-	}
-	compo->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (compo->regs == NULL) {
+	compo->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(compo->regs)) {
 		DRM_ERROR("Register mapping failed\n");
-		return -ENXIO;
+		return PTR_ERR(compo->regs);
 	}
 
 	/* Get clock resources */
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 4dcddd02629b6a1052be8fb8333bd3aa17c083c5..74a1eef4674eeabc445b53b380e325f785242024 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -511,7 +511,6 @@ static int sti_dvo_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct sti_dvo *dvo;
-	struct resource *res;
 	struct device_node *np = dev->of_node;
 
 	DRM_INFO("%s\n", __func__);
@@ -523,16 +522,9 @@ static int sti_dvo_probe(struct platform_device *pdev)
 	}
 
 	dvo->dev = pdev->dev;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvo-reg");
-	if (!res) {
-		DRM_ERROR("Invalid dvo resource\n");
-		return -ENOMEM;
-	}
-	dvo->regs = devm_ioremap(dev, res->start,
-			resource_size(res));
-	if (!dvo->regs)
-		return -ENOMEM;
+	dvo->regs = devm_platform_ioremap_resource_byname(pdev, "dvo-reg");
+	if (IS_ERR(dvo->regs))
+		return PTR_ERR(dvo->regs);
 
 	dvo->clk_pix = devm_clk_get(dev, "dvo_pix");
 	if (IS_ERR(dvo->clk_pix)) {
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 14fdc00d2ba03d4f96ba407ac8e576decb6f32c0..eedccdf70833145d8cc316588915db2c766bb31a 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -750,16 +750,9 @@ static int sti_hda_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hda->dev = pdev->dev;
-
-	/* Get resources */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hda-reg");
-	if (!res) {
-		DRM_ERROR("Invalid hda resource\n");
-		return -ENOMEM;
-	}
-	hda->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (!hda->regs)
-		return -ENOMEM;
+	hda->regs = devm_platform_ioremap_resource_byname(pdev, "hda-reg");
+	if (IS_ERR(hda->regs))
+		return PTR_ERR(hda->regs);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 			"video-dacs-ctrl");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 164a34d793d86f114394048667ae3189e1c39242..37b8d619066ef14a2def26e2e4f90a9c2194238d 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -1380,7 +1380,6 @@ static int sti_hdmi_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct sti_hdmi *hdmi;
 	struct device_node *np = dev->of_node;
-	struct resource *res;
 	struct device_node *ddc;
 	int ret;
 
@@ -1399,17 +1398,9 @@ static int sti_hdmi_probe(struct platform_device *pdev)
 	}
 
 	hdmi->dev = pdev->dev;
-
-	/* Get resources */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
-	if (!res) {
-		DRM_ERROR("Invalid hdmi resource\n");
-		ret = -ENOMEM;
-		goto release_adapter;
-	}
-	hdmi->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (!hdmi->regs) {
-		ret = -ENOMEM;
+	hdmi->regs = devm_platform_ioremap_resource_byname(pdev, "hdmi-reg");
+	if (IS_ERR(hdmi->regs)) {
+		ret = PTR_ERR(hdmi->regs);
 		goto release_adapter;
 	}
 
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 0f658709c9d0d398c4eed65202443db9d0b41f8c..03684062309bbb9915d47fa6e6475cbb6c7beaaa 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1356,7 +1356,6 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *vtg_np;
 	struct sti_hqvdp *hqvdp;
-	struct resource *res;
 
 	DRM_DEBUG_DRIVER("\n");
 
@@ -1367,17 +1366,10 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
 	}
 
 	hqvdp->dev = dev;
-
-	/* Get Memory resources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		DRM_ERROR("Get memory resource failed\n");
-		return -ENXIO;
-	}
-	hqvdp->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (!hqvdp->regs) {
+	hqvdp->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(hqvdp->regs)) {
 		DRM_ERROR("Register mapping failed\n");
-		return -ENXIO;
+		return PTR_ERR(hqvdp->regs);
 	}
 
 	/* Get clock resources */
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index af6c06f448c4819def8cc0d0836e30f991529690..6a464b035de800509fb6dc7c8780b5e1128643c1 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -838,7 +838,6 @@ static int sti_tvout_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct sti_tvout *tvout;
-	struct resource *res;
 
 	DRM_INFO("%s\n", __func__);
 
@@ -850,16 +849,9 @@ static int sti_tvout_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	tvout->dev = dev;
-
-	/* get memory resources */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg");
-	if (!res) {
-		DRM_ERROR("Invalid glue resource\n");
-		return -ENOMEM;
-	}
-	tvout->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (!tvout->regs)
-		return -ENOMEM;
+	tvout->regs = devm_platform_ioremap_resource_byname(pdev, "tvout-reg");
+	if (IS_ERR(tvout->regs))
+		return PTR_ERR(tvout->regs);
 
 	/* get reset resources */
 	tvout->reset = devm_reset_control_get(dev, "tvout");
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c
index 5ba469b711b5318e9e9e6d8df127fb8933d1fac1..ee81691b32036d209020498511841f6da053e17d 100644
--- a/drivers/gpu/drm/sti/sti_vtg.c
+++ b/drivers/gpu/drm/sti/sti_vtg.c
@@ -380,23 +380,15 @@ static int vtg_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct sti_vtg *vtg;
-	struct resource *res;
 	int ret;
 
 	vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL);
 	if (!vtg)
 		return -ENOMEM;
-
-	/* Get Memory ressources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		DRM_ERROR("Get memory resource failed\n");
-		return -ENOMEM;
-	}
-	vtg->regs = devm_ioremap(dev, res->start, resource_size(res));
-	if (!vtg->regs) {
+	vtg->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(vtg->regs)) {
 		DRM_ERROR("failed to remap I/O memory\n");
-		return -ENOMEM;
+		return PTR_ERR(vtg->regs);
 	}
 
 	vtg->irq = platform_get_irq(pdev, 0);

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:30 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:30 -0500
Subject: [PATCH v5 0/7] drm: Move to using devm_platform_ioremap_resource
Message-ID: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>

Start replacing the below occurences with the newer API:
- (devm_)platform_get_resource + devm_ioremap_resource
- (devm_)platform_get_resource + (devm_)ioremap
- platform_get_resource_byname + devm_ioremap
Move all these occurences to uses devm_platform_ioremap_resource
instead.

This is v5 of the series.

Changes in v5:
- Some patches already merged, leave them out.
- Handle return properly. The new API returns a error pointers
and not NULL. While this is taken care of in most drivers in
the series, the sprd and sti needed changes. Thanks to Dan
for pointing this out with his fix:
https://lore.kernel.org/dri-devel/a952e2b4-d4b8-49ac-abd9-9967c50f4a80 at stanley.mountain/

Changes in v4:
- Address vc4 driver compilation error

Changes in v3:
- Keep the old snippet of documentation and add further
clarification (Thomas)
- change in vc4 driver for the a resource is not needed.
Add a comment to clarify why that is left behind (Maxime)

Changes in v2:
- Fix compilation errors

Used Coccinelle to make the code changes.Semantic patch:

//First Case
//rule s/platform_get_resource + devm_ioremap_resource/devm_platform_ioremap_resource
@rule_1@
identifier res;
expression ioremap_res;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
-ioremap_res = devm_ioremap_resource(...);
+ioremap_res = devm_platform_ioremap_resource(pdev,0);

//Second case
//rule s/(devm_)platform_get_resource + (devm_)ioremap/devm_platform_ioremap_resource.
@rule_2@
identifier res;
expression ioremap;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
<...
-if (!res) {
-...
-}
...>
-ioremap = devm_ioremap(...);
+ioremap = devm_platform_ioremap_resource(pdev,0);

//Third case
//rule s/(devm_)platform_get_resource_byname + (devm_)ioremap/devm_platform_ioremap_resource_byname.
@rule_3@
identifier res;
expression ioremap;
identifier pdev;
constant mem;
expression name;
@@
-struct resource *res;
<+...
-res = platform_get_resource_byname(pdev,mem,name);
<...
-if (!res) {
-...
-}
...>
-ioremap = devm_ioremap(...);
+ioremap = devm_platform_ioremap_resource_byname(pdev,name);
...+>

Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
Anusha Srivatsa (7):
      drm/fsl-dcu: move to devm_platform_ioremap_resource() usage
      drm/hisilicon: move to devm_platform_ioremap_resource() usage
      drm/mxsfb: move to devm_platform_ioremap_resource() usage
      drm/sprd: move to devm_platform_ioremap_resource() usage
      drm/sti: move to devm_platform_ioremap_resource() usage
      drm/tegra: move to devm_platform_ioremap_resource() usage
      Documentation: Update the todo

 Documentation/gpu/todo.rst                      | 13 +++++++------
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c       |  4 +---
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    |  4 +---
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c |  4 +---
 drivers/gpu/drm/mxsfb/lcdif_drv.c               |  4 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c               |  4 +---
 drivers/gpu/drm/sprd/sprd_dpu.c                 | 13 +++----------
 drivers/gpu/drm/sprd/sprd_dsi.c                 | 13 +++----------
 drivers/gpu/drm/sti/sti_compositor.c            | 14 +++-----------
 drivers/gpu/drm/sti/sti_dvo.c                   | 14 +++-----------
 drivers/gpu/drm/sti/sti_hda.c                   | 13 +++----------
 drivers/gpu/drm/sti/sti_hdmi.c                  | 15 +++------------
 drivers/gpu/drm/sti/sti_hqvdp.c                 | 14 +++-----------
 drivers/gpu/drm/sti/sti_tvout.c                 | 14 +++-----------
 drivers/gpu/drm/sti/sti_vtg.c                   | 14 +++-----------
 drivers/gpu/drm/tegra/dsi.c                     |  4 +---
 16 files changed, 40 insertions(+), 121 deletions(-)
---
base-commit: 0670c2f56e45b3f4541985a9ebe06d04308e43b0
change-id: 20250304-mem-fixes-34df71d18b98

Best regards,
-- 
Anusha Srivatsa <asrivats at redhat.com>



From asrivats at redhat.com  Tue Mar  4 13:05:33 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:33 -0500
Subject: [PATCH v5 3/7] drm/mxsfb: move to devm_platform_ioremap_resource()
 usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-3-fb3dab8d901f@redhat.com>

Replace platform_get_resource + devm_ioremap_resource
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:
@rule_1@
identifier res;
expression ioremap_res;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
-ioremap_res = devm_ioremap_resource(...);
+ioremap_res = devm_platform_ioremap_resource(pdev,0);

Cc: Marek Vasut <marex at denx.de>
Cc: Stefan Agner <stefan at agner.ch>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
 drivers/gpu/drm/mxsfb/lcdif_drv.c | 4 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 8ee00f59ca821cea8e823e7100fb4d7534283994..fcb2a7517377e9a5bbd2997c578c579b1b079f92 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -134,7 +134,6 @@ static int lcdif_load(struct drm_device *drm)
 {
 	struct platform_device *pdev = to_platform_device(drm->dev);
 	struct lcdif_drm_private *lcdif;
-	struct resource *res;
 	int ret;
 
 	lcdif = devm_kzalloc(&pdev->dev, sizeof(*lcdif), GFP_KERNEL);
@@ -144,8 +143,7 @@ static int lcdif_load(struct drm_device *drm)
 	lcdif->drm = drm;
 	drm->dev_private = lcdif;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	lcdif->base = devm_ioremap_resource(drm->dev, res);
+	lcdif->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(lcdif->base))
 		return PTR_ERR(lcdif->base);
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 59020862cf65e5cc488903f1263ed16dfbce06f9..377d4c4c9979ad9538cfec5464827a82936f811b 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -215,7 +215,6 @@ static int mxsfb_load(struct drm_device *drm,
 {
 	struct platform_device *pdev = to_platform_device(drm->dev);
 	struct mxsfb_drm_private *mxsfb;
-	struct resource *res;
 	int ret;
 
 	mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
@@ -226,8 +225,7 @@ static int mxsfb_load(struct drm_device *drm,
 	drm->dev_private = mxsfb;
 	mxsfb->devdata = devdata;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mxsfb->base = devm_ioremap_resource(drm->dev, res);
+	mxsfb->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(mxsfb->base))
 		return PTR_ERR(mxsfb->base);
 

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:32 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:32 -0500
Subject: [PATCH v5 2/7] drm/hisilicon: move to
 devm_platform_ioremap_resource() usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-2-fb3dab8d901f@redhat.com>

Replace platform_get_resource + devm_ioremap_resource
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:
@rule_1@
identifier res;
expression ioremap_res;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
-ioremap_res = devm_ioremap_resource(...);
+ioremap_res = devm_platform_ioremap_resource(pdev,0);

Cc: Xinliang Liu <xinliang.liu at linaro.org>
Cc: Tian Tao <tiantao6 at hisilicon.com>
Cc: Xinwei Kong <kong.kongxinwei at hisilicon.com>
Cc: Sumit Semwal <sumit.semwal at linaro.org>
Cc: Yongqin Liu <yongqin.liu at linaro.org>
Cc: John Stultz <jstultz at google.com>

Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 4 +---
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 2eea9fb0e76bf3ead8f5914e6ebb65b5b3603b9a..e80debdc41763357cb2cf321205c0dfac80a911e 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -825,7 +825,6 @@ static const struct component_ops dsi_ops = {
 static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 {
 	struct dsi_hw_ctx *ctx = dsi->ctx;
-	struct resource *res;
 
 	ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(ctx->pclk)) {
@@ -833,8 +832,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 		return PTR_ERR(ctx->pclk);
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ctx->base = devm_ioremap_resource(&pdev->dev, res);
+	ctx->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(ctx->base)) {
 		DRM_ERROR("failed to remap dsi io region\n");
 		return PTR_ERR(ctx->base);
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index 2eb49177ac42bc6dba692328cca5c99d5925041c..45c4eb008ad5d639340f769ad022d186ec454722 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -844,7 +844,6 @@ static struct drm_plane_funcs ade_plane_funcs = {
 static void *ade_hw_ctx_alloc(struct platform_device *pdev,
 			      struct drm_crtc *crtc)
 {
-	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = pdev->dev.of_node;
 	struct ade_hw_ctx *ctx = NULL;
@@ -856,8 +855,7 @@ static void *ade_hw_ctx_alloc(struct platform_device *pdev,
 		return ERR_PTR(-ENOMEM);
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ctx->base = devm_ioremap_resource(dev, res);
+	ctx->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(ctx->base)) {
 		DRM_ERROR("failed to remap ade io base\n");
 		return ERR_PTR(-EIO);

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:34 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:34 -0500
Subject: [PATCH v5 4/7] drm/sprd: move to devm_platform_ioremap_resource()
 usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-4-fb3dab8d901f@redhat.com>

Replace platform_get_resource + devm_ioremap
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:
@rule_2@
identifier res;
expression ioremap;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
<...
-if (!res) {
-...
-}
...>
-ioremap = devm_ioremap(...);
+ioremap = devm_platform_ioremap_resource(pdev,0);

v2: Address the return handling properly since
the new API returns error pointers and not NULL.

Cc: Chunyan Zhang <zhang.lyra at gmail.com>
Cc: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
Reviewed-by: Chunyan Zhang <zhang.lyra at gmail.com>(v1)
Reviewed-by: Maxime Ripard <mripard at kernel.org>(v1)
---
 drivers/gpu/drm/sprd/sprd_dpu.c | 13 +++----------
 drivers/gpu/drm/sprd/sprd_dsi.c | 13 +++----------
 2 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index cb2816985305fd19eac27413c214681a5a1e9ffa..a3447622a33cd612e34be038e833222567bdcd2c 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -784,19 +784,12 @@ static int sprd_dpu_context_init(struct sprd_dpu *dpu,
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dpu_context *ctx = &dpu->ctx;
-	struct resource *res;
 	int ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "failed to get I/O resource\n");
-		return -EINVAL;
-	}
-
-	ctx->base = devm_ioremap(dev, res->start, resource_size(res));
-	if (!ctx->base) {
+	ctx->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(ctx->base)) {
 		dev_err(dev, "failed to map dpu registers\n");
-		return -EFAULT;
+		return PTR_ERR(ctx->base);
 	}
 
 	ctx->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index 8fc26479bb6bce0aa94914f49d0986a7e19326c1..23b0e1dc547a5023ee6ad7d5e1c49e2cec986bf0 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -901,18 +901,11 @@ static int sprd_dsi_context_init(struct sprd_dsi *dsi,
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dsi_context *ctx = &dsi->ctx;
-	struct resource *res;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "failed to get I/O resource\n");
-		return -EINVAL;
-	}
-
-	ctx->base = devm_ioremap(dev, res->start, resource_size(res));
-	if (!ctx->base) {
+	ctx->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(ctx->base)) {
 		drm_err(dsi->drm, "failed to map dsi host registers\n");
-		return -ENXIO;
+		return PTR_ERR(ctx->base);
 	}
 
 	ctx->regmap = devm_regmap_init(dev, &regmap_tst_io, dsi, &byte_config);

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:37 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:37 -0500
Subject: [PATCH v5 7/7] Documentation: Update the todo
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-7-fb3dab8d901f@redhat.com>

Update the Documentation to be more precise.

v2: Update for clarity
v3: Further details in Todo

Cc: Thomas Zimmermann <tzimmermann at suse.de>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
Acked-by: Thomas Zimmermann <tzimmermann at suse.de>
---
 Documentation/gpu/todo.rst | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 256d0d1cb2164bd94f9b610a751b907834d96a21..c57777a24e03d91b1ffe04365f7356f2d938befd 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -441,14 +441,15 @@ Contact: Thomas Zimmermann <tzimmermann at suse.de>
 
 Level: Intermediate
 
-Request memory regions in all drivers
--------------------------------------
+Request memory regions in all fbdev drivers
+--------------------------------------------
 
-Go through all drivers and add code to request the memory regions that the
-driver uses. This requires adding calls to request_mem_region(),
+Old/ancient fbdev drivers do not request their memory properly.
+Go through these drivers and add code to request the memory regions
+that the driver uses. This requires adding calls to request_mem_region(),
 pci_request_region() or similar functions. Use helpers for managed cleanup
-where possible.
-
+where possible. Problematic areas include hardware that has exclusive ranges
+like VGA. VGA16fb does not request the range as it is expected.
 Drivers are pretty bad at doing this and there used to be conflicts among
 DRM and fbdev drivers. Still, it's the correct thing to do.
 

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:31 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:31 -0500
Subject: [PATCH v5 1/7] drm/fsl-dcu: move to
 devm_platform_ioremap_resource() usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-1-fb3dab8d901f@redhat.com>

Replace platform_get_resource + devm_ioremap_resource
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:
@rule_1@
identifier res;
expression ioremap_res;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
-ioremap_res = devm_ioremap_resource(...);
+ioremap_res = devm_platform_ioremap_resource(pdev,0);

Cc: Stefan Agner <stefan at agner.ch>
Cc: Alison Wang <alison.wang at nxp.com>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 03b076db9381a5db0bff6576cda2772495a61fed..3bbfc1b56a6557e2f54d2b7ed099531053871341 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -260,7 +260,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
 	struct fsl_dcu_drm_device *fsl_dev;
 	struct drm_device *drm;
 	struct device *dev = &pdev->dev;
-	struct resource *res;
 	void __iomem *base;
 	struct clk *pix_clk_in;
 	char pix_clk_name[32];
@@ -278,8 +277,7 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
 		return -ENODEV;
 	fsl_dev->soc = id->data;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
+	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base)) {
 		ret = PTR_ERR(base);
 		return ret;

-- 
2.48.1



From asrivats at redhat.com  Tue Mar  4 13:05:36 2025
From: asrivats at redhat.com (Anusha Srivatsa)
Date: Tue, 04 Mar 2025 16:05:36 -0500
Subject: [PATCH v5 6/7] drm/tegra: move to devm_platform_ioremap_resource()
 usage
In-Reply-To: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
References: <20250304-mem-fixes-v1-0-fb3dab8d901f@redhat.com>
Message-ID: <20250304-mem-fixes-v1-6-fb3dab8d901f@redhat.com>

Replace platform_get_resource + devm_ioremap_resource
with just devm_platform_ioremap_resource()

Used Coccinelle to do this change. SmPl patch:
@rule_1@
identifier res;
expression ioremap_res;
identifier pdev;
@@
-struct resource *res;
...
-res = platform_get_resource(pdev,...);
-ioremap_res = devm_ioremap_resource(...);
+ioremap_res = devm_platform_ioremap_resource(pdev,0);

Cc: Thierry Reding <thierry.reding at gmail.com>
Cc: Mikko Perttunen <mperttunen at nvidia.com>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Anusha Srivatsa <asrivats at redhat.com>
---
 drivers/gpu/drm/tegra/dsi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 9bb077558167293c8e47ca9578cef13172b0b22f..b5089b7722676cfaee5d28216af4ae706a47f895 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1564,7 +1564,6 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
 static int tegra_dsi_probe(struct platform_device *pdev)
 {
 	struct tegra_dsi *dsi;
-	struct resource *regs;
 	int err;
 
 	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
@@ -1636,8 +1635,7 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 		goto remove;
 	}
 
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
+	dsi->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(dsi->regs)) {
 		err = PTR_ERR(dsi->regs);
 		goto remove;

-- 
2.48.1



From christophe.jaillet at wanadoo.fr  Tue Mar  4 13:20:59 2025
From: christophe.jaillet at wanadoo.fr (Christophe JAILLET)
Date: Tue, 4 Mar 2025 22:20:59 +0100
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
Message-ID: <7ef88ec2-24a5-4aa7-a601-d605a12768ba@wanadoo.fr>

Le 04/03/2025 ? 11:44, Kevin Chen a ?crit?:
> Add LPC PCC controller driver to support POST code capture.
> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>

Hi,

> +	init_waitqueue_head(&pcc->wq);
> +
> +	pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL);

Missing ida_free() in therror handling path and in the rmove function?

> +	if (pcc->mdev_id < 0) {
> +		dev_err(dev, "Couldn't allocate ID\n");
> +		return pcc->mdev_id;
> +	}
> +
> +	pcc->mdev.parent = dev;
> +	pcc->mdev.minor = MISC_DYNAMIC_MINOR;
> +	pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME,
> +					pcc->mdev_id);
> +	pcc->mdev.fops = &pcc_fops;
> +	rc = misc_register(&pcc->mdev);
> +	if (rc) {
> +		dev_err(dev, "Couldn't register misc device\n");
> +		goto err_free_kfifo;
> +	}
> +
> +	rc = aspeed_pcc_enable(pcc, dev);
> +	if (rc) {
> +		dev_err(dev, "Couldn't enable PCC\n");
> +		goto err_dereg_mdev;
> +	}
> +
> +	dev_set_drvdata(&pdev->dev, pcc);
> +
> +	return 0;
> +
> +err_dereg_mdev:
> +	misc_deregister(&pcc->mdev);
> +
> +err_free_kfifo:
> +	kfifo_free(&pcc->fifo);
> +
> +	return rc;
> +}
> +
> +static void aspeed_pcc_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev);
> +
> +	kfifo_free(&pcc->fifo);
> +	misc_deregister(&pcc->mdev);
> +}
> +
> +static const struct of_device_id aspeed_pcc_table[] = {
> +	{ .compatible = "aspeed,ast2600-lpc-pcc" },
> +	{ },

Unneeded trailing comma after a terminator.

> +};
> +
> +static struct platform_driver aspeed_pcc_driver = {
> +	.driver = {
> +		.name = "aspeed-pcc",
> +		.of_match_table = aspeed_pcc_table,
> +	},
> +	.probe = aspeed_pcc_probe,
> +	.remove = aspeed_pcc_remove,
> +};

...

CJ


From nfraprado at collabora.com  Tue Mar  4 13:35:37 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 18:35:37 -0300
Subject: [PATCH v2 2/3] ASoC: mediatek: common: Handle mediatek,accdet
 property
In-Reply-To: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
Message-ID: <20250304-mt8188-accdet-v2-2-27f496c4aede@collabora.com>

Handle the optional mediatek,accdet property. When present, retrieve the
sound component from its phandle, so the machine sound driver can use it
to register the audio jack and initialize the MT6359 ACCDET for jack
detection.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/mediatek/common/mtk-soc-card.h         |  1 +
 sound/soc/mediatek/common/mtk-soundcard-driver.c | 15 ++++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h
index 3f6e24dd22df13ddb3aef1625a77d2e29e46fccf..a1d2794ac1f717997fb47023d5951a9ac4897788 100644
--- a/sound/soc/mediatek/common/mtk-soc-card.h
+++ b/sound/soc/mediatek/common/mtk-soc-card.h
@@ -16,6 +16,7 @@ struct mtk_soc_card_data {
 	const struct mtk_sof_priv *sof_priv;
 	struct list_head sof_dai_link_list;
 	struct mtk_platform_card_data *card_data;
+	struct snd_soc_component *accdet;
 	void *mach_priv;
 };
 
diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c
index f4314dddc46075d554b4e3f3aae8bcb5498f8ab5..4e1c546a994f5e6b7068f70ac8dc2af7e87d141a 100644
--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c
+++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <sound/soc.h>
 
 #include "mtk-dsp-sof-common.h"
@@ -192,7 +193,9 @@ EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops);
 
 int mtk_soundcard_common_probe(struct platform_device *pdev)
 {
-	struct device_node *platform_node, *adsp_node;
+	struct device_node *platform_node, *adsp_node, *accdet_node;
+	struct snd_soc_component *accdet_comp;
+	struct platform_device *accdet_pdev;
 	const struct mtk_soundcard_pdata *pdata;
 	struct mtk_soc_card_data *soc_card_data;
 	struct snd_soc_dai_link *orig_dai_link, *dai_link;
@@ -250,6 +253,16 @@ int mtk_soundcard_common_probe(struct platform_device *pdev)
 
 	soc_card_data->card_data->jacks = jacks;
 
+	accdet_node = of_parse_phandle(pdev->dev.of_node, "mediatek,accdet", 0);
+	if (!IS_ERR(accdet_node)) {
+		accdet_pdev = of_find_device_by_node(accdet_node);
+		if (!IS_ERR(accdet_pdev)) {
+			accdet_comp = snd_soc_lookup_component(&accdet_pdev->dev, NULL);
+			if (!IS_ERR(accdet_comp))
+				soc_card_data->accdet = accdet_comp;
+		}
+	}
+
 	platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
 	if (!platform_node)
 		return dev_err_probe(&pdev->dev, -EINVAL,

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 13:35:35 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 18:35:35 -0300
Subject: [PATCH v2 0/3] Allow retrieving accessory detection reference on
 MT8188
Message-ID: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>

This series enables the MT8188-MT6359 sound driver to retrieve the
MT6359 ACCDET sound component from a mediatek,accdet DT property, which
allows detecting jack insertion/removal.

Patch 1 describes the new property in the binding. Patch 2 implements
the sound component retrieval in the common MTK soundcard driver. Patch
3 updates the MT8188-MT6359 sound driver to register the audio jack and
initialize the ACCDET driver for detection, if the property is present.

Tested on the Genio 700 EVK board.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
Changes in v2:
- Added CONFIG_SND_SOC_MT6359_ACCDET select in
  CONFIG_SND_SOC_MT8188_MT6359 to avoid build failure
- Clarified in mediatek,accdet dt-binding and commit description that
  the property should only be present if the accdet is actually used
- Link to v1: https://lore.kernel.org/r/20250214-mt8188-accdet-v1-0-6bbd5483855b at collabora.com

---
N?colas F. R. A. Prado (3):
      ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet
      ASoC: mediatek: common: Handle mediatek,accdet property
      ASoC: mediatek: mt8188-mt6359: Add accdet headset jack detect support

 .../bindings/sound/mediatek,mt8188-mt6359.yaml     |  8 ++++
 sound/soc/mediatek/Kconfig                         |  1 +
 sound/soc/mediatek/common/mtk-soc-card.h           |  1 +
 sound/soc/mediatek/common/mtk-soundcard-driver.c   | 15 +++++++-
 sound/soc/mediatek/mt8188/mt8188-mt6359.c          | 43 ++++++++++++++++++++++
 5 files changed, 67 insertions(+), 1 deletion(-)
---
base-commit: 20d5c66e1810e6e8805ec0d01373afb2dba9f51a
change-id: 20250214-mt8188-accdet-4deabb85534d

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Tue Mar  4 13:35:36 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 18:35:36 -0300
Subject: [PATCH v2 1/3] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add
 mediatek,accdet
In-Reply-To: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
Message-ID: <20250304-mt8188-accdet-v2-1-27f496c4aede@collabora.com>

Add a mediatek,accdet phandle property to allow getting a reference to
the MT6359 ACCDET block, which is responsible for detecting jack
insertion/removal.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml         | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
index 8c77e7f68ad7b6f5b88b53cedccb291139a2eeea..76d5a437dc8f4ad1f31c21f84304bad326b0facd 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
@@ -40,6 +40,14 @@ properties:
       hardware that provides additional audio functionalities if present.
       The AFE will link to ADSP when the phandle is provided.
 
+  mediatek,accdet:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      The phandle to the MT6359 accessory detection block, which detects audio
+      jack insertion and removal. This property should only be present if the
+      accdet block is actually wired to the audio jack pins and to be used for
+      jack detection.
+
 patternProperties:
   "^dai-link-[0-9]+$":
     type: object

-- 
2.48.1



From laurentiumihalcea111 at gmail.com  Tue Mar  4 13:35:58 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 4 Mar 2025 23:35:58 +0200
Subject: [PATCH v4 1/3] ASoC: dt-bindings: support imx95's CM7 core
In-Reply-To: <20250213064724.kbmxsk5szpxwclj6@pengutronix.de>
References: <20250211225808.3050-1-laurentiumihalcea111@gmail.com>
 <20250211225808.3050-2-laurentiumihalcea111@gmail.com>
 <20250212093610.x4ixrackmn3u2xrf@pengutronix.de>
 <CAEnQRZBeQdnC+K92+Udb5awTmom10YHHNt7Ld-pYK4A1i8sr3Q@mail.gmail.com>
 <d66996eb-f49b-448b-9743-d19a3c3eba52@sirena.org.uk>
 <e45411df-1b8b-4f21-878d-d52e1112e62d@gmail.com>
 <20250213064724.kbmxsk5szpxwclj6@pengutronix.de>
Message-ID: <88584d8f-e1cd-4b56-8906-461e1e6d9cc9@gmail.com>



On 2/13/2025 8:47 AM, Marco Felsch wrote:
> Hi Laurentiu, Daniel,
>
> On 25-02-12, Laurentiu Mihalcea wrote:
>> On 2/12/2025 2:38 PM, Mark Brown wrote:
>>> On Wed, Feb 12, 2025 at 12:11:49PM +0200, Daniel Baluta wrote:
>>>> On Wed, Feb 12, 2025 at 11:38?AM Marco Felsch <m.felsch at pengutronix.de> wrote:
>>>>> On 25-02-11, Laurentiu Mihalcea wrote:
>>>>>> +    const: fsl,imx95-cm7-sof
>>>>> Albeit Krzysztof already add his Reviewed-by, can I ask why we need to
>>>>> add the -sof suffix instead of -audio or so? SOF is a software project
>>>>> but you can clearly run different software on the audio-copro as well.
>>>> Sure you can run a different software project on the audio DSP but
>>>> you will need a way to distinguish between the different projects.
>>>> There might be different mailbox, memory configurations. So you will  need
>>>> to invent another suffix specific to the new project.
>>>> We can make  const: fsl,imx95-cm7-audio as the one used with SOF
>>>> and think about a different name later for when another project will
>>>> want to use the DSP.
>>> I think the point here was that the DT should stay the same even if the
>>> DSP firwmare changes, just as how changing the main OS shouldn't affect
>>> the DT.
>> It's rather unfortunate but based on the experience from the 8 series
>> (imx8qm, imx8qxp, imx8mp), the programming model can differ quite
>> a bit (e.g: remoteproc vs SOF) even if the core is the same (i.e: DSP core).
>>
>> The different programming models also required different DT configurations
>> (e.g: dif. mboxes as Daniel mentioned, some extra properties (i.e: reg-names), etc...)
>>
>> The "-sof" suffix was chosen here instead of the more generic "-audio" (or whatever else
>> alternative) because the DT configuration is specific to SOF's programming model. Other
>> audio applications running on the same core may have dif. configurations (e.g: use
>> DTCM/ITCM for memory instead of DDR, dif. mbox count, etc...). I suppose this kind of thing
>> is bound to happen to some degree since the DT node doesn't just describe the CM7 core
>> (but, rather, it also encompasses information on the memory, mboxes, etc. used)
>> but perhaps I'm wrong?
> Time will tell if there will be any other user except for SOF for the
> DSP but and this is what I wanted to point out: the DTS should abstract
> the HW. IMHO The CM7-Audio node should contain all properties required
> to turn power and reset the core (e.g. clocks, reset, pm-domains). I get
> your point regarding different configs but please have a look at
> mt8183-kukui.dtsi. Here the rpmsg config is a subnode of the actual
> system-control-proc. This makes much more sense to me since the HW part
> is part of the generic core-node and all the software config goes into a
> separate subnode.
>
> Regards,
>   Marco

I understand your point but we're dealing with 2 different programming
models here: SOF and remoteproc as opposed to just remoteproc as it's
the case for Mediatek.

Going for a similar approach would also mean quite a bit of software
changes as we'd need to factor out the common bits (most importantly here:
core operations like start/stop) and placing them in a common driver. This is not
trivial and I'm not sure it's worth the effort right now given that:

??? 1) The current way we model the hardware inside the DT is not exactly inaccurate.
??? The core does physically use those memory regions, mailboxes, etc.

??? 2) Whatever we do, the information in the DT will still depend on the programming model.
??? It's just that you're placing it in a child node, instead of the parent, which is arguably not that
??? big of an improvement?


From nfraprado at collabora.com  Tue Mar  4 13:35:38 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 18:35:38 -0300
Subject: [PATCH v2 3/3] ASoC: mediatek: mt8188-mt6359: Add accdet headset
 jack detect support
In-Reply-To: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
Message-ID: <20250304-mt8188-accdet-v2-3-27f496c4aede@collabora.com>

Enable headset jack detection for MT8188 platforms that use the MT6359
ACCDET block for it, indicated by the mediatek,accdet property in DT.
For those platforms, register a jack and initialize the ACCDET block to
report jack events through it.

Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/mediatek/Kconfig                |  1 +
 sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 3033e2d3fe16840631a465dd967da77f7a6ff43c..64155ea7965a1cc50593fef442ce90761836f328 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -237,6 +237,7 @@ config SND_SOC_MT8188_MT6359
 	select SND_SOC_NAU8825
 	select SND_SOC_RT5682S
 	select SND_SOC_ES8326
+	select SND_SOC_MT6359_ACCDET
 	help
 	  This adds support for ASoC machine driver for MediaTek MT8188
 	  boards with the MT6359 and other I2S audio codecs.
diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
index 420b1427b71dc1424a52f7ab6140c14659036733..20dc9470ba76b2a750e79a5ae3dafabd7c597f40 100644
--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
+++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
@@ -17,6 +17,7 @@
 #include "mt8188-afe-common.h"
 #include "../../codecs/nau8825.h"
 #include "../../codecs/mt6359.h"
+#include "../../codecs/mt6359-accdet.h"
 #include "../../codecs/rt5682.h"
 #include "../common/mtk-afe-platform-driver.h"
 #include "../common/mtk-soundcard-driver.h"
@@ -271,6 +272,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
 	},
 };
 
+static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = {
+	{
+		.pin    = "Headphone",
+		.mask   = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin    = "Headset Mic",
+		.mask   = SND_JACK_MICROPHONE,
+	},
+};
+
 static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Ext Spk"),
 };
@@ -506,6 +518,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
+	int ret;
+
+	if (!soc_card_data->accdet)
+		return 0;
+
+	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+				   SND_JACK_HEADSET | SND_JACK_BTN_0 |
+				   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+				   SND_JACK_BTN_3,
+				   jack, mt8188_headset_jack_pins,
+				   ARRAY_SIZE(mt8188_headset_jack_pins));
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_component *cmpnt_codec =
@@ -518,6 +559,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
 	/* mtkaif calibration */
 	mt8188_mt6359_mtkaif_calibration(rtd);
 
+	mt8188_mt6359_accdet_init(rtd);
+
 	return 0;
 }
 

-- 
2.48.1



From nfraprado at collabora.com  Tue Mar  4 13:43:49 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 04 Mar 2025 18:43:49 -0300
Subject: [PATCH] arm64: dts: mediatek: mt8390-genio-common: Add jack
 detection with accdet
Message-ID: <20250304-genio700-accdet-dts-v1-1-86d77c5cc745@collabora.com>

Enable audio jack detection for the Genio 700 and 510 EVK boards. This
is handled by the MT6359 ACCDET block, which on these boards has the
HP_EINT pin pulled high and connected to a normally open 3.5mm jack.

Add a phandle to the accdet in the sound card node so the machine sound
driver can initialize the accdet.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
This patch depends on both "Allow retrieving accessory detection
reference on MT8188" [1] and "Get mt6359-accdet ready for usage in
Devicetree" [2].

[1] https://lore.kernel.org/all/20250304-mt8188-accdet-v2-0-27f496c4aede at collabora.com
[2] https://lore.kernel.org/all/20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b at collabora.com
---
 arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
index 992bf60c097ae3b1fd6d4e62ef1a327b146496ef..e53c6b0b5a53a616a1684e6efc3758f449294bb9 100644
--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
@@ -1189,6 +1189,7 @@ &sound {
 		"AP DMIC", "AUDGLB",
 		"AP DMIC", "MIC_BIAS_0",
 		"AP DMIC", "MIC_BIAS_2";
+	mediatek,accdet = <&accdet>;
 	mediatek,adsp = <&adsp>;
 	status = "okay";
 

---
base-commit: 20d5c66e1810e6e8805ec0d01373afb2dba9f51a
change-id: 20250304-genio700-accdet-dts-4a4767fef27d

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From heiko at sntech.de  Tue Mar  4 13:11:18 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 22:11:18 +0100
Subject: [PATCH v3 1/3] drm/rockchip: lvds: move pclk preparation in with clk_get
In-Reply-To: <041c5f0e2371817a27577bd0989b9dca@manjaro.org>
References: <20250304124418.111061-1-heiko@sntech.de>
 <20250304124418.111061-2-heiko@sntech.de>
 <041c5f0e2371817a27577bd0989b9dca@manjaro.org>
Message-ID: <3048640.Lt9SDvczpP@diego>

Am Dienstag, 4. M?rz 2025, 21:30:22 MEZ schrieb Dragan Simic:
> Hello Heiko,
> 
> On 2025-03-04 13:44, Heiko Stuebner wrote:
> > diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> > b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> > index 385cf6881504..ecfae8d5da89 100644
> > --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> > +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> > @@ -448,15 +448,13 @@ struct drm_encoder_helper_funcs
> > px30_lvds_encoder_helper_funcs = {
> >  static int rk3288_lvds_probe(struct platform_device *pdev,
> >  			     struct rockchip_lvds *lvds)
> >  {
> > -	int ret;
> > -
> >  	lvds->regs = devm_platform_ioremap_resource(pdev, 0);
> >  	if (IS_ERR(lvds->regs))
> >  		return PTR_ERR(lvds->regs);
> > 
> > -	lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
> > +	lvds->pclk = devm_clk_get_prepared(lvds->dev, "pclk_lvds");
> >  	if (IS_ERR(lvds->pclk)) {
> > -		DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
> > +		DRM_DEV_ERROR(lvds->dev, "could not get or prepare pclk_lvds\n");
> 
> I'm wondering why this patch isn't replacing deprecated DRM
> logging macros with their preferred successors in a couple of
> places, just like what the patch 2/3 from this series does?

because this patch is about reorganizing the clock handling :-)

Changing the logging functions is a different topic and so has no place
in _this_ patch.

And of course drm-logging is a separate beast to tame altogether.
drm_err vs. dev_err; lvds->dev vs. drm_dev (there was an argument over
what belongs where recently) .

And I had neither the capacity nor time to delve into all that, so limited
myself to stuff I understood :-)

Heiko





From heiko at sntech.de  Tue Mar  4 13:16:49 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 22:16:49 +0100
Subject: [PATCH v3 0/3] Add display subsystem dt node on rk3576
In-Reply-To: <lfmhqurnpjmfy6pfjxd5aczxujislv2p5bsurcbl7capyt7zv3@hy2twvjj53uz>
References: <20241231095728.253943-1-andyshrk@163.com>
 <173564980410.21979.2947276365464229762.robh@kernel.org>
 <lfmhqurnpjmfy6pfjxd5aczxujislv2p5bsurcbl7capyt7zv3@hy2twvjj53uz>
Message-ID: <2627393.Mh6RI2rZIc@diego>

Am Dienstag, 4. M?rz 2025, 15:47:28 MEZ schrieb Sebastian Reichel:
> Hello,
> 
> On Tue, Dec 31, 2024 at 06:57:21AM -0600, Rob Herring (Arm) wrote:
> > On Tue, 31 Dec 2024 17:57:17 +0800, Andy Yan wrote:
> > > As the VOP[0] and HDMI[1] driver have already been submitted for review.
> > > This series enable hdmi display on sige5 board.
> > > 
> > > [0] https://lore.kernel.org/linux-rockchip/20241231090802.251787-1-andyshrk at 163.com/T/#t
> > > [1] https://lore.kernel.org/linux-rockchip/20241231094425.253398-1-andyshrk at 163.com/T/#t
> > > 
> > > Changes in v3:
> > > - Split from https://lore.kernel.org/linux-rockchip/3330586.aeNJFYEL58 at diego/T/#t
> > > 
> > > Andy Yan (3):
> > >   arm64: dts: rockchip: Add vop for rk3576
> > >   arm64: dts: rockchip: Add hdmi for rk3576
> > >   arm64: dts: rockchip: Enable hdmi display on sige5
> > > 
> > >  .../boot/dts/rockchip/rk3576-armsom-sige5.dts |  47 +++++++
> > >  arch/arm64/boot/dts/rockchip/rk3576.dtsi      | 126 ++++++++++++++++++
> > >  2 files changed, 173 insertions(+)
> >
> > [...] (a bunch of warnings due to dependency patch series not yet
> > being in linux-next)
> 
> I think all dependencies have landed now. But it might be sensible
> to do a quick resend considering how old this is.
> 
> Would be nice to have initial RK3576 HDMI support in 6.15 :)

now we can :-)

The update was not that difficult, so did it myself when applying.


Heiko




From heiko at sntech.de  Tue Mar  4 13:14:34 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 22:14:34 +0100
Subject: [PATCH v3 0/3] Add display subsystem dt node on rk3576
In-Reply-To: <20241231095728.253943-1-andyshrk@163.com>
References: <20241231095728.253943-1-andyshrk@163.com>
Message-ID: <174112278794.341367.445088781126200714.b4-ty@sntech.de>


On Tue, 31 Dec 2024 17:57:17 +0800, Andy Yan wrote:
> As the VOP[0] and HDMI[1] driver have already been submitted for review.
> This series enable hdmi display on sige5 board.
> 
> [0] https://lore.kernel.org/linux-rockchip/20241231090802.251787-1-andyshrk at 163.com/T/#t
> [1] https://lore.kernel.org/linux-rockchip/20241231094425.253398-1-andyshrk at 163.com/T/#t
> 
> Changes in v3:
> - Split from https://lore.kernel.org/linux-rockchip/3330586.aeNJFYEL58 at diego/T/#t
> 
> [...]

Applied, thanks!

[1/3] arm64: dts: rockchip: Add vop for rk3576
      commit: d74b842cab0860e41a45df0dac41e4e56202c766
[2/3] arm64: dts: rockchip: Add hdmi for rk3576
      commit: ad0ea230ab2a3535b186f7fb863b4bca7050e06f
[3/3] arm64: dts: rockchip: Enable hdmi display on sige5
      commit: 2062b91b9f3c6afe9c2a7d1ddf0f3e6af5f3fa31

I've adapted the patches where needed.
- Moved the grf to it's address-related position
- updated the irq names

With all the driver patches in place, dtbscheck for the sige5 is happy.


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Tue Mar  4 13:12:41 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue,  4 Mar 2025 22:12:41 +0100
Subject: [PATCH v3 0/3] drm/rockchip: lvds: probe logging improvements
In-Reply-To: <20250304124418.111061-1-heiko@sntech.de>
References: <20250304124418.111061-1-heiko@sntech.de>
Message-ID: <174112269652.340957.10714067153847883727.b4-ty@sntech.de>


On Tue, 04 Mar 2025 13:44:15 +0100, Heiko Stuebner wrote:
> Getting the panel already uses dev_err_probe to stay silent, when
> the panel just probes later, and the lvds defers.
> 
> But the phy needed on px30, also has the capability to probe after
> the lvds. So make the rest of the lvds probe/bind logic also use
> more modern logging than DRM_DEV_ERR, that is deprecated anyway.
> 
> [...]

Applied, thanks!

[1/3] drm/rockchip: lvds: move pclk preparation in with clk_get
      commit: d4f5efb9139cad34823f265053c57baf6af3c70c
[2/3] drm/rockchip: lvds: Hide scary error messages on probe deferral
      commit: 37c18639504aacbd31371f562fabafdb890bcd2e
[3/3] drm/rockchip: lvds: lower log severity for missing pinctrl settings
      commit: 4006be2f77cd26d065133b338dc51f59857d20f0


With some freedesktop.org hickup, I forgot to send the "patch applied"
mail, when I applied the series this afternoon, done now.


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From quic_molvera at quicinc.com  Tue Mar  4 13:56:42 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:42 -0800
Subject: [PATCH v2 9/9] arm64: defconfig: Add M31 eUSB2 PHY config
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-9-a698a2e68e06@quicinc.com>

Add configs for the M31 eUSB2 PHY for SM8750 USB.

Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db29822036d25a7228f8936e2ad613b208..7a7187475a11206e708a5a2c6dd51736e16932e9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1587,6 +1587,7 @@ CONFIG_PHY_QCOM_QUSB2=m
 CONFIG_PHY_QCOM_SNPS_EUSB2=m
 CONFIG_PHY_QCOM_EUSB2_REPEATER=m
 CONFIG_PHY_QCOM_M31_USB=m
+CONFIG_PHY_QCOM_M31_EUSB=m
 CONFIG_PHY_QCOM_USB_HS=m
 CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
 CONFIG_PHY_QCOM_USB_HS_28NM=m

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:35 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:35 -0800
Subject: [PATCH v2 2/9] dt-bindings: phy: Add the M31 based eUSB2 PHY
 bindings
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-2-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

On SM8750, the M31 eUSB2 PHY is being used to support USB2. Add the
binding definition for the PHY driver.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 .../bindings/phy/qcom,m31-eusb2-phy.yaml           | 79 ++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c1b2b7c898f44949769e6027b47dd13812a1bf5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/qcom,m31-eusb2-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm M31 eUSB2 phy
+
+maintainers:
+  - Wesley Cheng <quic_wcheng at quicinc.com>
+
+description:
+  M31 based eUSB2 controller, which supports LS/FS/HS usb connectivity
+  on Qualcomm chipsets.  It is paired with a eUSB2 repeater.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - qcom,sm8750-m31-eusb2-phy
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 0
+
+  clocks:
+    items:
+      - description: reference clock
+
+  clock-names:
+    items:
+      - const: ref
+
+  resets:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+    description:
+      Phandle to eUSB2 repeater
+
+  vdd-supply:
+    description:
+      Phandle to 0.88V regulator supply to PHY digital circuit.
+
+  vdda12-supply:
+    description:
+      Phandle to 1.2V regulator supply to PHY refclk pll block.
+
+required:
+  - compatible
+  - reg
+  - "#phy-cells"
+  - clocks
+  - clock-names
+  - vdd-supply
+  - vdda12-supply
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    usb_1_hsphy: phy at 88e3000 {
+        compatible = "qcom,sm8750-m31-eusb2-phy";
+        reg = <0x88e3000 0x29c>;
+
+        clocks = <&tcsrcc_usb2_clkref_en>;
+        clock-names = "ref";
+
+        resets = <&gcc_qusb2phy_prim_bcr>;
+
+        #phy-cells = <0>;
+
+        vdd-supply = <&vreg_l2d_0p88>;
+        vdda12-supply = <&vreg_l3g_1p2>;
+    };

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:41 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:41 -0800
Subject: [PATCH v2 8/9] arm64: dts: qcom: sm8750: Add USB support for
 SM8750 MTP and QRD platforms
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-8-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Enable USB support on SM8750 MTP and QRD variants.  The current definition
will start the USB controller in peripheral mode by default until
dependencies are added, such as USB role detection.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 24 ++++++++++++++++++++++++
 arch/arm64/boot/dts/qcom/sm8750-qrd.dts | 24 ++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
index 9e3aacad7bdab6848e86f8e45e04907e1c752a07..059eccbbc3fb05fc8806e36d35dc469d44443a26 100644
--- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
@@ -792,3 +792,27 @@ &tlmm {
 &uart7 {
 	status = "okay";
 };
+
+&usb_1 {
+	status = "okay";
+};
+
+&usb_1_dwc3 {
+	dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+	vdd-supply = <&vreg_l2d_0p88>;
+	vdda12-supply = <&vreg_l3g_1p2>;
+
+	phys = <&pmih0108_eusb2_repeater>;
+
+	status = "okay";
+};
+
+&usb_dp_qmpphy {
+	vdda-phy-supply = <&vreg_l3g_1p2>;
+	vdda-pll-supply = <&vreg_l2d_0p88>;
+
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
index f77efab0aef9bab751a947173bcdcc27df7295a8..01c0af643626917614fbd68cf8962ef947ca6548 100644
--- a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
@@ -790,3 +790,27 @@ &tlmm {
 &uart7 {
 	status = "okay";
 };
+
+&usb_1 {
+	status = "okay";
+};
+
+&usb_1_dwc3 {
+	dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+	vdd-supply = <&vreg_l2d_0p88>;
+	vdda12-supply = <&vreg_l3g_1p2>;
+
+	phys = <&pmih0108_eusb2_repeater>;
+
+	status = "okay";
+};
+
+&usb_dp_qmpphy {
+	vdda-phy-supply = <&vreg_l3g_1p2>;
+	vdda-pll-supply = <&vreg_l2d_0p88>;
+
+	status = "okay";
+};

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:34 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:34 -0800
Subject: [PATCH v2 1/9] dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy:
 Add SM8750 to QMP PHY
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-1-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add an entry to the compatible field for SM8750 for the QMP combo PHY.
This handles the USB3 path for SM8750.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 .../devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml          | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
index 358a6736a951ca5db7cff7385b3657976a667358..38ce04c35d945d0d8d319191c241920810ee9005 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
@@ -29,6 +29,7 @@ properties:
       - qcom,sm8450-qmp-usb3-dp-phy
       - qcom,sm8550-qmp-usb3-dp-phy
       - qcom,sm8650-qmp-usb3-dp-phy
+      - qcom,sm8750-qmp-usb3-dp-phy
       - qcom,x1e80100-qmp-usb3-dp-phy
 
   reg:
@@ -133,6 +134,7 @@ allOf:
             - qcom,sm6350-qmp-usb3-dp-phy
             - qcom,sm8550-qmp-usb3-dp-phy
             - qcom,sm8650-qmp-usb3-dp-phy
+            - qcom,sm8750-qmp-usb3-dp-phy
             - qcom,x1e80100-qmp-usb3-dp-phy
     then:
       required:

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:36 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:36 -0800
Subject: [PATCH v2 3/9] dt-bindings: usb: qcom,dwc3: Add SM8750 compatible
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-3-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

SM8750 uses the Synopsys DWC3 controller. Add this to the compatibles list
to utilize the DWC3 QCOM and DWC3 core framework.  Other than a revision
bump to DWC3 controller rev2.00a, the controller on SM8750 does not add any
additional vendor specific features compared to previous chipsets.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index a2b3cf625e5b3962f3acfe93de02f3cae2b6123d..916024b7bd95a11d5cc5495de0fffd3fbdca8318 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -55,6 +55,7 @@ properties:
           - qcom,sm8450-dwc3
           - qcom,sm8550-dwc3
           - qcom,sm8650-dwc3
+          - qcom,sm8750-dwc3
           - qcom,x1e80100-dwc3
           - qcom,x1e80100-dwc3-mp
       - const: qcom,dwc3
@@ -354,6 +355,7 @@ allOf:
               - qcom,sm8450-dwc3
               - qcom,sm8550-dwc3
               - qcom,sm8650-dwc3
+              - qcom,sm8750-dwc3
     then:
       properties:
         clocks:
@@ -495,6 +497,7 @@ allOf:
               - qcom,sm8450-dwc3
               - qcom,sm8550-dwc3
               - qcom,sm8650-dwc3
+              - qcom,sm8750-dwc3
     then:
       properties:
         interrupts:

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:37 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:37 -0800
Subject: [PATCH v2 4/9] phy: qcom: qmp-combo: Add new PHY sequences for
 SM8750
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-4-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add new register offsets and PHY values for SM8750. Some of the previous
definitions can be leveraged from older PHY versions as offsets within
registers have not changed. This also updates the PHY sequence that is
recommended after running hardware characterization.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c          | 221 +++++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h     |  38 ++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h         |  32 +++
 drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h |  64 ++++++
 .../phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h    |  68 +++++++
 drivers/phy/qualcomm/phy-qcom-qmp.h                |   5 +
 6 files changed, 428 insertions(+)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index b09fa00e9fe7db8d97b7179ee15d3f07fe578b0c..8b9710a9654ab1acf8419e7f87188cbc98f8714a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -32,6 +32,7 @@
 #include "phy-qcom-qmp-pcs-usb-v4.h"
 #include "phy-qcom-qmp-pcs-usb-v5.h"
 #include "phy-qcom-qmp-pcs-usb-v6.h"
+#include "phy-qcom-qmp-pcs-usb-v8.h"
 
 #include "phy-qcom-qmp-dp-com-v3.h"
 
@@ -212,6 +213,28 @@ static const unsigned int qmp_v6_n4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
 	[QPHY_TX_TRANSCEIVER_BIAS_EN]	= QSERDES_V6_N4_TX_TRANSCEIVER_BIAS_EN,
 };
 
+static const unsigned int qmp_v8_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+	[QPHY_SW_RESET]			= QPHY_V8_PCS_SW_RESET,
+	[QPHY_START_CTRL]		= QPHY_V8_PCS_START_CONTROL,
+	[QPHY_PCS_STATUS]		= QPHY_V8_PCS_PCS_STATUS1,
+	[QPHY_PCS_POWER_DOWN_CONTROL]	= QPHY_V8_PCS_POWER_DOWN_CONTROL,
+
+	/* In PCS_USB */
+	[QPHY_PCS_AUTONOMOUS_MODE_CTRL]	= QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL,
+	[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_CLEAR,
+
+	[QPHY_COM_RESETSM_CNTRL]	= QSERDES_V8_COM_RESETSM_CNTRL,
+	[QPHY_COM_C_READY_STATUS]	= QSERDES_V8_COM_C_READY_STATUS,
+	[QPHY_COM_CMN_STATUS]		= QSERDES_V8_COM_CMN_STATUS,
+	[QPHY_COM_BIAS_EN_CLKBUFLR_EN]	= QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN,
+
+	[QPHY_TX_TX_POL_INV]		= QSERDES_V8_TX_TX_POL_INV,
+	[QPHY_TX_TX_DRV_LVL]		= QSERDES_V8_TX_TX_DRV_LVL,
+	[QPHY_TX_TX_EMP_POST1_LVL]	= QSERDES_V8_TX_TX_EMP_POST1_LVL,
+	[QPHY_TX_HIGHZ_DRVR_EN]		= QSERDES_V8_TX_HIGHZ_DRVR_EN,
+	[QPHY_TX_TRANSCEIVER_BIAS_EN]	= QSERDES_V8_TX_TRANSCEIVER_BIAS_EN,
+};
+
 static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
 	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
@@ -1471,6 +1494,139 @@ static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_EQ_CONFIG5, 0x10),
 };
 
+static const struct qmp_phy_init_tbl sm8750_usb3_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1, 0xc0),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORECLK_DIV_MODE1, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE1, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE1, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE1, 0x55),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE1, 0x75),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_SEL_1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE1, 0x25),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x5c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x5c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0, 0xc0),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE0, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE0, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE0, 0x1a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE0, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE0, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE0, 0x55),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE0, 0x75),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE0, 0x25),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE0, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BG_TIMER, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_EN_CENTER, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER1, 0x62),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER2, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_BUF_ENABLE, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_EN_SEL, 0x1a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_CFG, 0x14),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_MAP, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORE_CLK_EN, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_CONFIG_1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1, 0xb6),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2, 0x4a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_ADDITIONAL_MISC, 0x0c),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_TX, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_RX, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_TX, 0x1f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_1, 0xf5),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_3, 0x11),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_4, 0x31),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_5, 0x5f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RCV_DETECT_LVL_2, 0x12),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V8_TX_PI_QEC_CTRL, 0x21, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V8_TX_PI_QEC_CTRL, 0x05, 2),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FO_GAIN, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_GAIN, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_PI_CONTROLS, 0x99),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH1, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH2, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN2, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_AUX_DATA_TCOARSE_TFINE, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL1, 0x54),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL2, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_GM_CAL, 0x13),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_LOW, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
+
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_ENABLES, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CNTRL, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_LOW, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH, 0xbf),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH2, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH3, 0xdf),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH4, 0xed),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_LOW, 0x19),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH, 0x09),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH2, 0x91),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH3, 0xb7),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH4, 0xaa),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_EN_TIMER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DCC_CTRL1, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VTH_CODE, 0x10),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_CTRL1, 0x14),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_TRIM, 0x08),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG1, 0xc4),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG2, 0x89),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG3, 0x20),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG6, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_REFGEN_REQ_CONFIG1, 0x21),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RX_SIGDET_LVL, 0x55),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_CDR_RESET_TIME, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG1, 0x88),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG2, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_PCS_TX_RX_CONFIG, 0x0c),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG1, 0x4b),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG5, 0x10),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_pcs_usb_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2, 0x07),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_L, 0x40),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_H, 0x00),
+};
+
 static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_usb_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
@@ -1781,6 +1937,22 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v5 = {
 	.dp_dp_phy	= 0x2200,
 };
 
+static const struct qmp_combo_offsets qmp_combo_offsets_v8 = {
+	.com		= 0x0000,
+	.txa		= 0x1400,
+	.rxa		= 0x1600,
+	.txb		= 0x1800,
+	.rxb		= 0x1a00,
+	.usb3_serdes	= 0x1000,
+	.usb3_pcs_misc	= 0x1c00,
+	.usb3_pcs	= 0x1e00,
+	.usb3_pcs_usb	= 0x2100,
+	.dp_serdes	= 0x3000,
+	.dp_txa		= 0x3400,
+	.dp_txb		= 0x3800,
+	.dp_dp_phy	= 0x3c00,
+};
+
 static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
 	.offsets		= &qmp_combo_offsets_v3,
 
@@ -2280,6 +2452,51 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 };
 
+static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
+	.offsets		= &qmp_combo_offsets_v8,
+
+	.serdes_tbl		= sm8750_usb3_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sm8750_usb3_serdes_tbl),
+	.tx_tbl			= sm8750_usb3_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sm8750_usb3_tx_tbl),
+	.rx_tbl			= sm8750_usb3_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sm8750_usb3_rx_tbl),
+	.pcs_tbl		= sm8750_usb3_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sm8750_usb3_pcs_tbl),
+	.pcs_usb_tbl		= sm8750_usb3_pcs_usb_tbl,
+	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8750_usb3_pcs_usb_tbl),
+
+	.dp_serdes_tbl		= qmp_v6_dp_serdes_tbl,
+	.dp_serdes_tbl_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
+	.dp_tx_tbl		= qmp_v6_dp_tx_tbl,
+	.dp_tx_tbl_num		= ARRAY_SIZE(qmp_v6_dp_tx_tbl),
+
+	.serdes_tbl_rbr		= qmp_v6_dp_serdes_tbl_rbr,
+	.serdes_tbl_rbr_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
+	.serdes_tbl_hbr		= qmp_v6_dp_serdes_tbl_hbr,
+	.serdes_tbl_hbr_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
+	.serdes_tbl_hbr2	= qmp_v6_dp_serdes_tbl_hbr2,
+	.serdes_tbl_hbr2_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
+	.serdes_tbl_hbr3	= qmp_v6_dp_serdes_tbl_hbr3,
+	.serdes_tbl_hbr3_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
+
+	.swing_hbr_rbr		= &qmp_dp_v6_voltage_swing_hbr_rbr,
+	.pre_emphasis_hbr_rbr	= &qmp_dp_v6_pre_emphasis_hbr_rbr,
+	.swing_hbr3_hbr2	= &qmp_dp_v5_voltage_swing_hbr3_hbr2,
+	.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
+
+	.dp_aux_init		= qmp_v4_dp_aux_init,
+	.configure_dp_tx	= qmp_v4_configure_dp_tx,
+	.configure_dp_phy	= qmp_v4_configure_dp_phy,
+	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
+
+	.regs			= qmp_v8_usb3phy_regs_layout,
+	.reset_list		= msm8996_usb3phy_reset_l,
+	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+};
+
 static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
 {
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -3915,6 +4132,10 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
 		.compatible = "qcom,sm8650-qmp-usb3-dp-phy",
 		.data = &sm8650_usb3dpphy_cfg,
 	},
+	{
+		.compatible = "qcom,sm8750-qmp-usb3-dp-phy",
+		.data = &sm8750_usb3dpphy_cfg,
+	},
 	{
 		.compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
 		.data = &x1e80100_usb3dpphy_cfg,
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..89ace8024bc0bde55b5a590f67d906b893c197a1
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_USB_V8_H_
+#define QCOM_PHY_QMP_PCS_USB_V8_H_
+
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG1		0x00
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_STATUS		0x04
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL		0x08
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL2		0x0c
+#define QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x10
+#define QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_CLEAR		0x14
+#define QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL		0x18
+#define QPHY_V8_PCS_USB_LFPS_TX_ECSTART			0x1c
+#define QPHY_V8_PCS_USB_LFPS_PER_TIMER_VAL		0x20
+#define QPHY_V8_PCS_USB_LFPS_TX_END_CNT_U3_START	0x24
+#define QPHY_V8_PCS_USB_LFPS_CONFIG1			0x28
+#define QPHY_V8_PCS_USB_RXEQTRAINING_LOCK_TIME		0x2c
+#define QPHY_V8_PCS_USB_RXEQTRAINING_WAIT_TIME		0x30
+#define QPHY_V8_PCS_USB_RXEQTRAINING_CTLE_TIME		0x34
+#define QPHY_V8_PCS_USB_RXEQTRAINING_WAIT_TIME_S2	0x38
+#define QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2	0x3c
+#define QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_L		0x40
+#define QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_H		0x44
+#define QPHY_V8_PCS_USB_ARCVR_DTCT_EN_PERIOD		0x48
+#define QPHY_V8_PCS_USB_ARCVR_DTCT_CM_DLY		0x4c
+#define QPHY_V8_PCS_USB_TXONESZEROS_RUN_LENGTH		0x50
+#define QPHY_V8_PCS_USB_ALFPS_DEGLITCH_VAL		0x54
+#define QPHY_V8_PCS_USB_SIGDET_STARTUP_TIMER_VAL	0x58
+#define QPHY_V8_PCS_USB_TEST_CONTROL			0x5c
+#define QPHY_V8_PCS_USB_RXTERMINATION_DLY_SEL		0x60
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG2		0x64
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG3		0x68
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG4		0x6c
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..169fd5de74747c8c9a833a629d8000875168a6ff
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V8_H_
+#define QCOM_PHY_QMP_PCS_V8_H_
+
+/* Only for QMP V8 PHY - USB/PCIe PCS registers */
+#define QPHY_V8_PCS_SW_RESET			0x000
+#define QPHY_V8_PCS_PCS_STATUS1			0x014
+#define QPHY_V8_PCS_POWER_DOWN_CONTROL		0x040
+#define QPHY_V8_PCS_START_CONTROL		0x044
+#define QPHY_V8_PCS_POWER_STATE_CONFIG1		0x090
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG1		0x0c4
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG2		0x0c8
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG3		0x0cc
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG6		0x0d8
+#define QPHY_V8_PCS_REFGEN_REQ_CONFIG1		0x0dc
+#define QPHY_V8_PCS_RX_SIGDET_LVL		0x188
+#define QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_L	0x190
+#define QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_H	0x194
+#define QPHY_V8_PCS_RATE_SLEW_CNTRL1		0x198
+#define QPHY_V8_PCS_CDR_RESET_TIME		0x1b0
+#define QPHY_V8_PCS_ALIGN_DETECT_CONFIG1	0x1c0
+#define QPHY_V8_PCS_ALIGN_DETECT_CONFIG2	0x1c4
+#define QPHY_V8_PCS_PCS_TX_RX_CONFIG		0x1d0
+#define QPHY_V8_PCS_EQ_CONFIG1			0x1dc
+#define QPHY_V8_PCS_EQ_CONFIG2			0x1e0
+#define QPHY_V8_PCS_EQ_CONFIG5			0x1ec
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3b2292257bc521cb66562a5b6bfae8dc8c92cc1
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_QSERDES_COM_V8_H_
+#define QCOM_PHY_QMP_QSERDES_COM_V8_H_
+
+/* Only for QMP V8 PHY - QSERDES COM registers */
+#define QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1		0x000
+#define QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1		0x004
+#define QSERDES_V8_COM_SSC_STEP_SIZE3_MODE1		0x008
+#define QSERDES_V8_COM_CP_CTRL_MODE1			0x010
+#define QSERDES_V8_COM_PLL_RCTRL_MODE1			0x014
+#define QSERDES_V8_COM_PLL_CCTRL_MODE1			0x018
+#define QSERDES_V8_COM_CORECLK_DIV_MODE1		0x01c
+#define QSERDES_V8_COM_LOCK_CMP1_MODE1			0x020
+#define QSERDES_V8_COM_LOCK_CMP2_MODE1			0x024
+#define QSERDES_V8_COM_DEC_START_MODE1			0x028
+#define QSERDES_V8_COM_DEC_START_MSB_MODE1		0x02c
+#define QSERDES_V8_COM_DIV_FRAC_START1_MODE1		0x030
+#define QSERDES_V8_COM_DIV_FRAC_START2_MODE1		0x034
+#define QSERDES_V8_COM_DIV_FRAC_START3_MODE1		0x038
+#define QSERDES_V8_COM_HSCLK_SEL_1			0x03c
+#define QSERDES_V8_COM_VCO_TUNE1_MODE1			0x048
+#define QSERDES_V8_COM_VCO_TUNE2_MODE1			0x04c
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1	0x050
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1	0x054
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0	0x058
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0	0x05c
+#define QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0		0x060
+#define QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0		0x064
+#define QSERDES_V8_COM_CP_CTRL_MODE0			0x070
+#define QSERDES_V8_COM_PLL_RCTRL_MODE0			0x074
+#define QSERDES_V8_COM_PLL_CCTRL_MODE0			0x078
+#define QSERDES_V8_COM_LOCK_CMP1_MODE0			0x080
+#define QSERDES_V8_COM_LOCK_CMP2_MODE0			0x084
+#define QSERDES_V8_COM_DEC_START_MODE0			0x088
+#define QSERDES_V8_COM_DEC_START_MSB_MODE0		0x08c
+#define QSERDES_V8_COM_DIV_FRAC_START1_MODE0		0x090
+#define QSERDES_V8_COM_DIV_FRAC_START2_MODE0		0x094
+#define QSERDES_V8_COM_DIV_FRAC_START3_MODE0		0x098
+#define QSERDES_V8_COM_VCO_TUNE1_MODE0			0x0a8
+#define QSERDES_V8_COM_VCO_TUNE2_MODE0			0x0ac
+#define QSERDES_V8_COM_BG_TIMER				0x0bc
+#define QSERDES_V8_COM_SSC_EN_CENTER			0x0c0
+#define QSERDES_V8_COM_SSC_PER1				0x0cc
+#define QSERDES_V8_COM_SSC_PER2				0x0d0
+#define QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN		0x0dc
+#define QSERDES_V8_COM_SYSCLK_BUF_ENABLE		0x0e8
+#define QSERDES_V8_COM_SYSCLK_EN_SEL			0x110
+#define QSERDES_V8_COM_RESETSM_CNTRL			0x118
+#define QSERDES_V8_COM_LOCK_CMP_CFG			0x124
+#define QSERDES_V8_COM_VCO_TUNE_MAP			0x140
+#define QSERDES_V8_COM_CORE_CLK_EN			0x170
+#define QSERDES_V8_COM_CMN_CONFIG_1			0x174
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1		0x1a4
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2		0x1a8
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3		0x1ac
+#define QSERDES_V8_COM_ADDITIONAL_MISC			0x1b4
+#define QSERDES_V8_COM_CMN_STATUS			0x2c8
+#define QSERDES_V8_COM_C_READY_STATUS			0x2f0
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cb8b1708607ab35760fb15f3e524872334d9b40
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V8_H_
+#define QCOM_PHY_QMP_QSERDES_TXRX_V8_H_
+
+#define QSERDES_V8_TX_TX_EMP_POST1_LVL			0x00c
+#define QSERDES_V8_TX_TX_DRV_LVL			0x014
+#define QSERDES_V8_TX_RES_CODE_LANE_TX			0x034
+#define QSERDES_V8_TX_RES_CODE_LANE_RX			0x038
+#define QSERDES_V8_TX_RES_CODE_LANE_OFFSET_TX		0x03c
+#define QSERDES_V8_TX_RES_CODE_LANE_OFFSET_RX		0x040
+#define QSERDES_V8_TX_TRANSCEIVER_BIAS_EN		0x054
+#define QSERDES_V8_TX_HIGHZ_DRVR_EN			0x058
+#define QSERDES_V8_TX_TX_POL_INV			0x05c
+#define QSERDES_V8_TX_LANE_MODE_1			0x084
+#define QSERDES_V8_TX_LANE_MODE_2			0x088
+#define QSERDES_V8_TX_LANE_MODE_3			0x08c
+#define QSERDES_V8_TX_LANE_MODE_4			0x090
+#define QSERDES_V8_TX_LANE_MODE_5			0x094
+#define QSERDES_V8_TX_RCV_DETECT_LVL_2			0x0a4
+#define QSERDES_V8_TX_PI_QEC_CTRL			0x0e4
+
+#define QSERDES_V8_RX_UCDR_FO_GAIN			0x008
+#define QSERDES_V8_RX_UCDR_SO_GAIN			0x014
+#define QSERDES_V8_RX_UCDR_SVS_FO_GAIN			0x020
+#define QSERDES_V8_RX_UCDR_FASTLOCK_FO_GAIN		0x030
+#define QSERDES_V8_RX_UCDR_SO_SATURATION_AND_ENABLE	0x034
+#define QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_LOW		0x03c
+#define QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_HIGH		0x040
+#define QSERDES_V8_RX_UCDR_PI_CONTROLS			0x044
+#define QSERDES_V8_RX_UCDR_SB2_THRESH1			0x04c
+#define QSERDES_V8_RX_UCDR_SB2_THRESH2			0x050
+#define QSERDES_V8_RX_UCDR_SB2_GAIN1			0x054
+#define QSERDES_V8_RX_UCDR_SB2_GAIN2			0x058
+#define QSERDES_V8_RX_AUX_DATA_TCOARSE_TFINE		0x060
+#define QSERDES_V8_RX_VGA_CAL_CNTRL1			0x0d4
+#define QSERDES_V8_RX_VGA_CAL_CNTRL2			0x0d8
+#define QSERDES_V8_RX_GM_CAL				0x0dc
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL2		0x0ec
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL3		0x0f0
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL4		0x0f4
+#define QSERDES_V8_RX_RX_IDAC_TSETTLE_LOW		0x0f8
+#define QSERDES_V8_RX_RX_IDAC_TSETTLE_HIGH		0x0fc
+#define QSERDES_V8_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1	0x110
+#define QSERDES_V8_RX_SIGDET_ENABLES			0x118
+#define QSERDES_V8_RX_SIGDET_CNTRL			0x11c
+#define QSERDES_V8_RX_SIGDET_DEGLITCH_CNTRL		0x124
+#define QSERDES_V8_RX_RX_MODE_00_LOW			0x15c
+#define QSERDES_V8_RX_RX_MODE_00_HIGH			0x160
+#define QSERDES_V8_RX_RX_MODE_00_HIGH2			0x164
+#define QSERDES_V8_RX_RX_MODE_00_HIGH3			0x168
+#define QSERDES_V8_RX_RX_MODE_00_HIGH4			0x16c
+#define QSERDES_V8_RX_RX_MODE_01_LOW			0x170
+#define QSERDES_V8_RX_RX_MODE_01_HIGH			0x174
+#define QSERDES_V8_RX_RX_MODE_01_HIGH2			0x178
+#define QSERDES_V8_RX_RX_MODE_01_HIGH3			0x17c
+#define QSERDES_V8_RX_RX_MODE_01_HIGH4			0x180
+#define QSERDES_V8_RX_DFE_EN_TIMER			0x1a0
+#define QSERDES_V8_RX_DFE_CTLE_POST_CAL_OFFSET		0x1a4
+#define QSERDES_V8_RX_DCC_CTRL1				0x1a8
+#define QSERDES_V8_RX_VTH_CODE				0x1b0
+#define QSERDES_V8_RX_SIGDET_CAL_CTRL1			0x1e4
+#define QSERDES_V8_RX_SIGDET_CAL_TRIM			0x1f8
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index d0f41e4aaa855fc3ee088afc833b214277b7e2b0..8148853ff275b0526cb47a158d332af1d74e0abf 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -30,6 +30,9 @@
 #include "phy-qcom-qmp-qserdes-com-v7.h"
 #include "phy-qcom-qmp-qserdes-txrx-v7.h"
 
+#include "phy-qcom-qmp-qserdes-com-v8.h"
+#include "phy-qcom-qmp-qserdes-txrx-v8.h"
+
 #include "phy-qcom-qmp-qserdes-pll.h"
 
 #include "phy-qcom-qmp-pcs-v2.h"
@@ -52,6 +55,8 @@
 
 #include "phy-qcom-qmp-pcs-v7.h"
 
+#include "phy-qcom-qmp-pcs-v8.h"
+
 /* QPHY_SW_RESET bit */
 #define SW_RESET				BIT(0)
 /* QPHY_POWER_DOWN_CONTROL */

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:33 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:33 -0800
Subject: [PATCH v2 0/9] phy: qcom: Introduce USB support for SM8750
Message-ID: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>

Add support for the PHYs and controllers used for USB on SM8750 SoCs.

---
Changes in v2:
- Added new QMP PHY register definitions for v8 based QMP phys.
- Made changes to clean up some code in the M31 eUSB2 PHY driver based
on feedback received.
- Added bulk regulator operations in M31 eUSB2 PHY, to ensure that
both the vdd and vdda12 regulators are properly voted for.
- Removed external references to other dt bindings in M31 example for
the DT bindings change.
- Split DT patches between SoC and plaform changes, as well as the
PHY subsystem Kconfig changes when introducing the M31 eUSB2 PHY.
- Added orientation switch and port definitions in the DT changes.EDITME: describe what is new in this series revision.
- Link to v1: https://lore.kernel.org/r/20250113-sm8750_usb_master-v1-0-09afe1dc2524 at quicinc.com

---
Melody Olvera (1):
      arm64: defconfig: Add M31 eUSB2 PHY config

Wesley Cheng (8):
      dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Add SM8750 to QMP PHY
      dt-bindings: phy: Add the M31 based eUSB2 PHY bindings
      dt-bindings: usb: qcom,dwc3: Add SM8750 compatible
      phy: qcom: qmp-combo: Add new PHY sequences for SM8750
      phy: qcom: Update description for QCOM based eUSB2 repeater
      phy: qcom: Add M31 based eUSB2 PHY driver
      arm64: dts: qcom: sm8750: Add USB support to SM8750 SoCs
      arm64: dts: qcom: sm8750: Add USB support for SM8750 MTP and QRD platforms

 .../bindings/phy/qcom,m31-eusb2-phy.yaml           |  79 ++++++
 .../phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml         |   2 +
 .../devicetree/bindings/usb/qcom,dwc3.yaml         |   3 +
 arch/arm64/boot/dts/qcom/sm8750-mtp.dts            |  24 ++
 arch/arm64/boot/dts/qcom/sm8750-qrd.dts            |  24 ++
 arch/arm64/boot/dts/qcom/sm8750.dtsi               | 163 ++++++++++++
 arch/arm64/configs/defconfig                       |   1 +
 drivers/phy/qualcomm/Kconfig                       |  16 +-
 drivers/phy/qualcomm/Makefile                      |   1 +
 drivers/phy/qualcomm/phy-qcom-m31-eusb2.c          | 296 +++++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c          | 221 +++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h     |  38 +++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h         |  32 +++
 drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h |  64 +++++
 .../phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h    |  68 +++++
 drivers/phy/qualcomm/phy-qcom-qmp.h                |   5 +
 16 files changed, 1034 insertions(+), 3 deletions(-)
---
base-commit: 20d5c66e1810e6e8805ec0d01373afb2dba9f51a
change-id: 20241223-sm8750_usb_master-f27aed7f6d40

Best regards,
-- 
Melody Olvera <quic_molvera at quicinc.com>



From quic_molvera at quicinc.com  Tue Mar  4 13:56:40 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:40 -0800
Subject: [PATCH v2 7/9] arm64: dts: qcom: sm8750: Add USB support to SM8750
 SoCs
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-7-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add the base USB devicetree definitions for SM8750 platforms.  The overall
chipset contains a single DWC3 USB3 controller (rev. 200a), SS QMP PHY
(rev. v8) and M31 eUSB2 PHY.  The major difference for SM8750 is the
transition to using the M31 eUSB2 PHY compared to previous SoCs.

Enable USB support on SM8750 MTP and QRD variants. SM8750 has a QMP combo
PHY for the SSUSB path, and a M31 eUSB2 PHY for the HSUSB path.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8750.dtsi | 163 +++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi
index 3bbd7d18598ee0a3a0d5130c03a3166e1fc14d82..e543e65c7aba3213ca0b8a8f6dbaf1371ed8317e 100644
--- a/arch/arm64/boot/dts/qcom/sm8750.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/interconnect/qcom,icc.h>
 #include <dt-bindings/interconnect/qcom,sm8750-rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
 #include <dt-bindings/power/qcom,rpmhpd.h>
 #include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
@@ -1966,6 +1967,168 @@ lpass_lpicx_noc: interconnect at 7420000 {
 			#interconnect-cells = <2>;
 		};
 
+		usb_1_hsphy: phy at 88e3000 {
+			compatible = "qcom,sm8750-m31-eusb2-phy";
+			reg = <0x0 0x88e3000 0x0 0x29c>;
+
+			clocks = <&tcsrcc TCSR_USB2_CLKREF_EN>;
+			clock-names = "ref";
+
+			resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+			#phy-cells = <0>;
+
+			status = "disabled";
+		};
+
+		usb_dp_qmpphy: phy at 88e8000 {
+			compatible = "qcom,sm8750-qmp-usb3-dp-phy";
+			reg = <0x0 0x088e8000 0x0 0x4000>;
+
+			clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+				 <&rpmhcc RPMH_CXO_CLK>,
+				 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+				 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+			clock-names = "aux",
+				      "ref",
+				      "com_aux",
+				      "usb3_pipe";
+
+			resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+				 <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+			reset-names = "phy",
+				      "common";
+
+			power-domains = <&gcc GCC_USB3_PHY_GDSC>;
+
+			#clock-cells = <1>;
+			#phy-cells = <1>;
+
+			orientation-switch;
+
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+
+					usb_dp_qmpphy_out: endpoint {
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+
+					usb_dp_qmpphy_usb_ss_in: endpoint {
+						remote-endpoint = <&usb_1_dwc3_ss>;
+					};
+				};
+
+				port at 2 {
+					reg = <2>;
+
+					usb_dp_qmpphy_dp_in: endpoint {
+					};
+				};
+			};
+		};
+
+		usb_1: usb at a6f8800 {
+			compatible = "qcom,sm8750-dwc3", "qcom,dwc3";
+			reg = <0x0 0x0a6f8800 0x0 0x400>;
+			status = "disabled";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+				 <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+				 <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+				 <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+				 <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+				 <&tcsrcc TCSR_USB3_CLKREF_EN>;
+			clock-names = "cfg_noc",
+				      "core",
+				      "iface",
+				      "sleep",
+				      "mock_utmi",
+				      "xo";
+
+			assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+					  <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+			assigned-clock-rates = <19200000>, <200000000>;
+
+			interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+						  <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+					      <&pdc 14 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc 15 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "pwr_event",
+					  "hs_phy_irq",
+					  "dp_hs_phy_irq",
+					  "dm_hs_phy_irq",
+					  "ss_phy_irq";
+
+			power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+			required-opps = <&rpmhpd_opp_nom>;
+
+			resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+			interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>,
+					<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;
+			interconnect-names = "usb-ddr", "apps-usb";
+
+			usb_1_dwc3: usb at a600000 {
+				compatible = "snps,dwc3";
+				reg = <0x0 0x0a600000 0x0 0xe000>;
+
+				interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+
+				iommus = <&apps_smmu 0x40 0x0>;
+
+				phys = <&usb_1_hsphy>, <&usb_dp_qmpphy QMP_USB43DP_USB3_PHY>;
+				phy-names = "usb2-phy", "usb3-phy";
+
+				snps,hird-threshold = /bits/ 8 <0x0>;
+				snps,usb2-gadget-lpm-disable;
+				snps,dis_u2_susphy_quirk;
+				snps,dis_enblslpm_quirk;
+				snps,dis-u1-entry-quirk;
+				snps,dis-u2-entry-quirk;
+				snps,is-utmi-l1-suspend;
+				snps,usb3_lpm_capable;
+				snps,usb2-lpm-disable;
+				snps,has-lpm-erratum;
+				tx-fifo-resize;
+
+				dma-coherent;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						usb_1_dwc3_hs: endpoint {
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						usb_1_dwc3_ss: endpoint {
+							remote-endpoint =
+								<&usb_dp_qmpphy_usb_ss_in>;
+						};
+					};
+				};
+			};
+		};
+
 		pdc: interrupt-controller at b220000 {
 			compatible = "qcom,sm8750-pdc", "qcom,pdc";
 			reg = <0x0 0x0b220000 0x0 0x10000>, <0x0 0x164400f0 0x0 0x64>;

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:39 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:39 -0800
Subject: [PATCH v2 6/9] phy: qcom: Add M31 based eUSB2 PHY driver
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

SM8750 utilizes an eUSB2 PHY from M31.  Add the initialization
sequences to bring it out of reset and into an operational state.  This
differs to the M31 USB driver, in that the M31 eUSB2 driver will
require a connection to an eUSB2 repeater.  This PHY driver will handle
the initialization of the associated eUSB2 repeater when required.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 drivers/phy/qualcomm/Kconfig              |  10 +
 drivers/phy/qualcomm/Makefile             |   1 +
 drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 296 ++++++++++++++++++++++++++++++
 3 files changed, 307 insertions(+)

diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index f281e3b7f3f20b4a4bb1602be94b8a1b041a876f..0dcdbef67d7e023a88c6f513825925e306e7579b 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -154,6 +154,16 @@ config PHY_QCOM_M31_USB
 	  management. This driver is required even for peripheral only or
 	  host only mode configurations.
 
+config PHY_QCOM_M31_EUSB
+	tristate "Qualcomm M31 eUSB2 PHY driver support"
+	depends on USB && (ARCH_QCOM || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable this to support M31 EUSB2 PHY transceivers on Qualcomm
+	  chips with DWC3 USB core. It supports initializing and cleaning
+	  up of the associated USB repeater that is paired with the eUSB2
+	  PHY.
+
 config PHY_QCOM_USB_HS
 	tristate "Qualcomm USB HS PHY module"
 	depends on USB_ULPI_BUS
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index eb60e950ad53334a3ada3db618aa584afb33fb93..f88ba0f71a73cd6935184c8831d6cd6488d6551f 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_PHY_QCOM_EDP)		+= phy-qcom-edp.o
 obj-$(CONFIG_PHY_QCOM_IPQ4019_USB)	+= phy-qcom-ipq4019-usb.o
 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
 obj-$(CONFIG_PHY_QCOM_M31_USB)		+= phy-qcom-m31.o
+obj-$(CONFIG_PHY_QCOM_M31_EUSB)		+= phy-qcom-m31-eusb2.o
 obj-$(CONFIG_PHY_QCOM_PCIE2)		+= phy-qcom-pcie2.o
 
 obj-$(CONFIG_PHY_QCOM_QMP_COMBO)	+= phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
diff --git a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c
new file mode 100644
index 0000000000000000000000000000000000000000..d14be08ce7c98eb183181d17f3ab9c92713e3785
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#define USB_PHY_UTMI_CTRL0		(0x3c)
+
+#define USB_PHY_UTMI_CTRL5		(0x50)
+
+#define USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
+#define FSEL				GENMASK(6, 4)
+#define FSEL_38_4_MHZ_VAL		(0x6)
+
+#define USB_PHY_HS_PHY_CTRL2		(0x64)
+
+#define USB_PHY_CFG0			(0x94)
+#define USB_PHY_CFG1			(0x154)
+
+#define USB_PHY_FSEL_SEL		(0xb8)
+
+#define USB_PHY_XCFGI_39_32		(0x16c)
+#define USB_PHY_XCFGI_71_64		(0x17c)
+#define USB_PHY_XCFGI_31_24		(0x168)
+#define USB_PHY_XCFGI_7_0		(0x15c)
+
+#define M31_EUSB_PHY_INIT_CFG(o, b, v)	\
+{				\
+	.off = o,		\
+	.mask = b,		\
+	.val = v,		\
+}
+
+struct m31_phy_tbl_entry {
+	u32 off;
+	u32 mask;
+	u32 val;
+};
+
+struct m31_eusb2_priv_data {
+	const struct m31_phy_tbl_entry	*setup_seq;
+	unsigned int			setup_seq_nregs;
+	const struct m31_phy_tbl_entry	*override_seq;
+	unsigned int			override_seq_nregs;
+	const struct m31_phy_tbl_entry	*reset_seq;
+	unsigned int			reset_seq_nregs;
+	unsigned int			fsel;
+};
+
+static const struct m31_phy_tbl_entry m31_eusb2_setup_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG1, BIT(0), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_FSEL_SEL, BIT(0), 1),
+};
+
+static const struct m31_phy_tbl_entry m31_eusb_phy_override_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_39_32, GENMASK(3, 2), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_71_64, GENMASK(3, 0), 7),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_31_24, GENMASK(2, 0), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_7_0, GENMASK(1, 0), 0),
+};
+
+static const struct m31_phy_tbl_entry m31_eusb_phy_reset_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(3), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(2), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL0, BIT(0), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, BIT(2), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, BIT(1), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(3), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, BIT(1), 0),
+};
+
+static const char * const m31_eusb_phy_vreg_names[] = {
+	"vdd", "vdda12",
+};
+
+#define M31_EUSB_NUM_VREGS		ARRAY_SIZE(m31_eusb_phy_vreg_names)
+
+struct m31eusb2_phy {
+	struct phy			 *phy;
+	void __iomem			 *base;
+	const struct m31_eusb2_priv_data *data;
+
+	struct regulator_bulk_data	 vregs[M31_EUSB_NUM_VREGS];
+	struct clk			 *clk;
+	struct reset_control		 *reset;
+
+	struct phy			 *repeater;
+};
+
+static int msm_m31_eusb2_write_readback(void __iomem *base, u32 offset,
+					const u32 mask, u32 val)
+{
+	u32 write_val;
+	u32 tmp;
+
+	tmp = readl_relaxed(base + offset);
+	tmp &= ~mask;
+	write_val = tmp | val;
+
+	writel_relaxed(write_val, base + offset);
+
+	tmp = readl_relaxed(base + offset);
+	tmp &= mask;
+
+	if (tmp != val) {
+		pr_err("write: %x to offset: %x FAILED\n", val, offset);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int m31eusb2_phy_write_sequence(struct m31eusb2_phy *phy,
+				       const struct m31_phy_tbl_entry *tbl,
+				       int num)
+{
+	int i;
+	int ret;
+
+	for (i = 0 ; i < num; i++, tbl++) {
+		dev_dbg(&phy->phy->dev, "Offset:%x BitMask:%x Value:%x",
+			tbl->off, tbl->mask, tbl->val);
+
+		ret = msm_m31_eusb2_write_readback(phy->base,
+						   tbl->off, tbl->mask,
+						   tbl->val << __ffs(tbl->mask));
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int m31eusb2_phy_init(struct phy *uphy)
+{
+	struct m31eusb2_phy *phy = phy_get_drvdata(uphy);
+	const struct m31_eusb2_priv_data *data = phy->data;
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs);
+	if (ret) {
+		dev_err(&uphy->dev, "failed to enable regulator, %d\n", ret);
+		return ret;
+	}
+
+	ret = phy_init(phy->repeater);
+	if (ret) {
+		dev_err(&uphy->dev, "repeater init failed. %d\n", ret);
+		goto disable_vreg;
+	}
+
+	ret = clk_prepare_enable(phy->clk);
+	if (ret) {
+		dev_err(&uphy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+		goto disable_repeater;
+	}
+
+	/* Perform phy reset */
+	reset_control_assert(phy->reset);
+	udelay(5);
+	reset_control_deassert(phy->reset);
+
+	m31eusb2_phy_write_sequence(phy, data->setup_seq, data->setup_seq_nregs);
+	msm_m31_eusb2_write_readback(phy->base,
+				     USB_PHY_HS_PHY_CTRL_COMMON0, FSEL,
+				     FIELD_PREP(FSEL, data->fsel));
+	m31eusb2_phy_write_sequence(phy, data->override_seq, data->override_seq_nregs);
+	m31eusb2_phy_write_sequence(phy, data->reset_seq, data->reset_seq_nregs);
+
+	return 0;
+
+disable_repeater:
+	phy_exit(phy->repeater);
+disable_vreg:
+	regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs);
+
+	return 0;
+}
+
+static int m31eusb2_phy_exit(struct phy *uphy)
+{
+	struct m31eusb2_phy *phy = phy_get_drvdata(uphy);
+
+	clk_disable_unprepare(phy->clk);
+	regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs);
+	phy_exit(phy->repeater);
+
+	return 0;
+}
+
+static const struct phy_ops m31eusb2_phy_gen_ops = {
+	.init	= m31eusb2_phy_init,
+	.exit	= m31eusb2_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int m31eusb2_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	const struct m31_eusb2_priv_data *data;
+	struct device *dev = &pdev->dev;
+	struct m31eusb2_phy *phy;
+	int ret;
+	int i;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	data = of_device_get_match_data(dev);
+	if (IS_ERR(data))
+		return -EINVAL;
+	phy->data = data;
+
+	phy->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(phy->base))
+		return PTR_ERR(phy->base);
+
+	phy->reset = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(phy->reset))
+		return PTR_ERR(phy->reset);
+
+	phy->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(phy->clk))
+		return dev_err_probe(dev, PTR_ERR(phy->clk),
+				     "failed to get clk\n");
+
+	phy->phy = devm_phy_create(dev, NULL, &m31eusb2_phy_gen_ops);
+	if (IS_ERR(phy->phy))
+		return dev_err_probe(dev, PTR_ERR(phy->phy),
+				     "failed to create phy\n");
+
+	for (i = 0; i < M31_EUSB_NUM_VREGS; i++)
+		phy->vregs[i].supply = m31_eusb_phy_vreg_names[i];
+
+	ret = devm_regulator_bulk_get(dev, M31_EUSB_NUM_VREGS, phy->vregs);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				"failed to get regulator supplies\n");
+
+	phy_set_drvdata(phy->phy, phy);
+
+	phy->repeater = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+	if (IS_ERR(phy->repeater))
+		return dev_err_probe(dev, PTR_ERR(phy->repeater),
+				     "failed to get repeater\n");
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (!IS_ERR(phy_provider))
+		dev_info(dev, "Registered M31 USB phy\n");
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct m31_eusb2_priv_data m31_eusb_v1_data = {
+	.setup_seq = m31_eusb2_setup_tbl,
+	.setup_seq_nregs = ARRAY_SIZE(m31_eusb2_setup_tbl),
+	.override_seq = m31_eusb_phy_override_tbl,
+	.override_seq_nregs = ARRAY_SIZE(m31_eusb_phy_override_tbl),
+	.reset_seq = m31_eusb_phy_reset_tbl,
+	.reset_seq_nregs = ARRAY_SIZE(m31_eusb_phy_reset_tbl),
+	.fsel = FSEL_38_4_MHZ_VAL,
+};
+
+static const struct of_device_id m31eusb2_phy_id_table[] = {
+	{ .compatible = "qcom,sm8750-m31-eusb2-phy", .data = &m31_eusb_v1_data },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, m31eusb2_phy_id_table);
+
+static struct platform_driver m31eusb2_phy_driver = {
+	.probe = m31eusb2_phy_probe,
+	.driver = {
+		.name = "qcom-m31eusb2-phy",
+		.of_match_table = m31eusb2_phy_id_table,
+	},
+};
+
+module_platform_driver(m31eusb2_phy_driver);
+
+MODULE_DESCRIPTION("eUSB2 Qualcomm M31 HSPHY driver");
+MODULE_LICENSE("GPL");

-- 
2.46.1



From quic_molvera at quicinc.com  Tue Mar  4 13:56:38 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Tue, 4 Mar 2025 13:56:38 -0800
Subject: [PATCH v2 5/9] phy: qcom: Update description for QCOM based eUSB2
 repeater
In-Reply-To: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
Message-ID: <20250304-sm8750_usb_master-v2-5-a698a2e68e06@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

The eUSB2 repeater that exists in the QCOM PMICs are utilized for several
different eUSB2 PHY vendors, such as M31 or Synopsys.  Hence, the wording
needs to be updated to remove associations to a specific vendor.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 drivers/phy/qualcomm/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 846f8c99547fd5132feaa1e41093b8eab51714f9..f281e3b7f3f20b4a4bb1602be94b8a1b041a876f 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -135,12 +135,12 @@ config PHY_QCOM_SNPS_EUSB2
 	  on Qualcomm SOCs.
 
 config PHY_QCOM_EUSB2_REPEATER
-	tristate "Qualcomm SNPS eUSB2 Repeater Driver"
+	tristate "Qualcomm PMIC eUSB2 Repeater Driver"
 	depends on OF && (ARCH_QCOM || COMPILE_TEST)
 	select GENERIC_PHY
 	help
-	  Enable support for the USB high-speed SNPS eUSB2 repeater on Qualcomm
-	  PMICs. The repeater is paired with a Synopsys eUSB2 Phy
+	  Enable support for the USB high-speed eUSB2 repeater on Qualcomm
+	  PMICs. The repeater can be paired with a Synopsys or M31 eUSB2 Phy
 	  on Qualcomm SOCs.
 
 config PHY_QCOM_M31_USB

-- 
2.46.1



From heiko at sntech.de  Tue Mar  4 13:52:22 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 04 Mar 2025 22:52:22 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64 RockPro64
In-Reply-To: <757afa87255212dfa5abf4c0e31deb08@manjaro.org>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <174104113599.8946.16805724674396090918.b4-ty@sntech.de>
 <757afa87255212dfa5abf4c0e31deb08@manjaro.org>
Message-ID: <2630232.Icojqenx9y@diego>

Am Dienstag, 4. M?rz 2025, 07:44:59 MEZ schrieb Dragan Simic:
> Hello Heiko,
> 
> On 2025-03-03 23:36, Heiko Stuebner wrote:
> > On Sun, 02 Mar 2025 19:48:02 +0100, Dragan Simic wrote:
> >> This is a small series that introduces small improvements to the way
> >> Pine64 RockPro64 [1] single-board-computer is described in the DT 
> >> files.
> >> This applies to both production-run revisions of the RockPro64.
> >> 
> >> The introduced improvements boil down to eliminating some warnings 
> >> from
> >> the kernel log, by adding a previously undefined regulator and by 
> >> adding
> >> some previously missing references to the regulators.
> >> 
> >> [...]
> > 
> > Applied, thanks!
> > 
> > [1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board 
> > dtsi
> >       commit: bd1c959f37f384b477f51572331b0dc828bd009a
> > [2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 
> > board dtsi
> >       commit: 64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
> > 
> > I've moved the pcie12v supply up one line.
> > While in a mathematical sense it's true 12 > 3.3, we're sorting
> > alphabetical, so it's 1?? < 3?? .
> > 
> > And yes I sympathize with 3.3 < 12, but also have come to appreciate 
> > not
> > having overly many special cases :-)
> 
> Great, thanks! :)
> 
> I'm fine with the alphabetical ordering, albeit with some caveats
> described below, but the following part of the patch description
> should also be removed, if possible, so the patch description fully
> matches the introduced changes:
> 
>    Shuffle and reorder the "vpcie*-supply" properties a bit, so they're 
> sorted
>    alphanumerically, which is a bit more logical and more useful than 
> having
>    these properties listed in their strict alphabetical order.

I've amended the commit, dropping this block

> I'm hoping you'll agree that specifying alphanumerical ordering
> for the properties in the DTS coding style is the way to go, just
> like it's already specified for the ordering of the nodes.  I'll
> go ahead and submit an appropriate patch for the DT guidelines.

vpcie0v9-supply = <&vcca_0v9>;
vpcie1v8-supply = <&vcca_1v8>;
vpcie3v3-supply = <&vcc3v3_pcie>;
vpcie12v-supply = <&vcc12v_dcin>;

In the end I don't care _that_ much, but personally I find that
alphanumerical ordering harder to read ;-) .

Because in the example above, my mind now constantly shouts
"why is vpcie1... after vpcie3... ..... ooooh right, it's alpha-numerical"

But I can live with it I guess ;-) .
As 3.3 is smaller than 12 afterall.


Heiko




From andre.przywara at arm.com  Tue Mar  4 14:23:06 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:06 +0000
Subject: [PATCH v2 12/15] arm64: dts: allwinner: a523: add X96Q-Pro+ support
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-13-andre.przywara@arm.com>

The X96QPro+ is a TV box using the Allwinner H728 SoC. That SoC seems to
be a package variant of the A523 family, at least it uses the same SoC
ID and is compatible as far as we can assess.

It comes with the following specs:
  - Allwinner H728 SoC: 8 Arm Cortex-A55 cores, Mali-G57 MC1 GPU
  - 2 or 4GiB DDR3L DRAM
  - 32, 64, or 128 GiB eMMC flash
  - AXP717 + AXP323 PMICs
  - Gigabit Ethernet (using MAXIO PHY)
  - HDMI port
  - 2 * USB 2.0 ports
  - 1 * USB 3.0 port
  - microSD card slot
  - TOSLINK digital audio output
  - 3.5mm A/V port
  - infrared sensor
  - 7-segment display
  - 5V barrel plug power supply
  - power button

The PCB provides holes for soldering a UART header or cable, this is
connected to the debug UART0. There is another set of UART pins
available. The board also features a FEL button (accessible through the
3.5mm socket) and a reset button (only accessible when case is open).

This .dts just describes the basic peripherals as far as we support them
at the moment. The PMIC rail assignments are reverse engineered as far
as possible, by dumping them from a running Android system, and correlating
them to other boards using the same SoC.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-h728-x96qpro+.dts    | 287 ++++++++++++++++++
 2 files changed, 288 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 0d678a7499e3c..983be49ea6ef8 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,4 +52,5 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-h728-x96qpro+.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
new file mode 100644
index 0000000000000..c0bce3f4fa925
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2024 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "X96Q Pro+";
+	compatible = "amediatech,x96q-pro-plus", "allwinner,sun55i-h728";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the barrel plug */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_vcc3v3: vcc3v3 {
+		/* 3.3V dummy supply for the SD card */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&reg_vcc5v>;
+		regulator-always-on;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_vcc3v3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	disable-wp;
+	status = "okay";
+};
+
+&mmc2 {
+	vmmc-supply = <&reg_cldo3>;
+	vqmmc-supply = <&reg_cldo1>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_dcdc4>;
+	vcc-pe-supply = <&reg_dcdc4>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_dcdc4>;
+	vcc-pj-supply = <&reg_dcdc4>;
+	vcc-pk-supply = <&reg_bldo3>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 34 {
+		compatible = "x-powers,axp717";
+		reg = <0x34>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.0(?) GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1360000>;
+				regulator-max-microvolt = <1360000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd-dcdc4";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				/* not connected */
+			};
+
+			reg_aldo3: aldo3 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-aldo3";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-wifi-lvds";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-dram-1v8";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-name = "vcc-bldo3";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-codec-sd";
+			};
+
+			reg_cldo2: cldo2 {
+			};
+
+			reg_cldo3: cldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-codec-eth-sd";
+			};
+
+			reg_cldo4: cldo4 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-eth-phy";
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				/* not connected */
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1050000>;
+				regulator-name = "vdd-dcdc3";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/* USB0 is a USB-A receptacle, always powered, so force host mode. */
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:07 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:07 +0000
Subject: [PATCH v2 13/15] arm64: dts: allwinner: a523: add Radxa A5E support
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-14-andre.przywara@arm.com>

The Radxa A5E is a development board using the Allwinner A527 SoC, which
is using the same die as the A523 SoC, just exposing the pins of more
peripherals (like HDMI or the 2nd MAC). The board features:

  - Allwinner A527/T527 SoC: 8 ARM Cortex-A55 cores, Mali-G57 MC1 GPU
  - 1GiB/2GiB/4GiB LPDDR4 DRAM
  - AXP717 + AXP323 PMICs
  - Raspberry-Pi-2 compatible 40pin GPIO header
  - 1 USB 2.0 type C port (OTG), also power supply
  - 1 USB 3.0 type A host port (multiplexed with M.2 slot)
  - 1 M.2 M-key 2230 slot, with 1 PCIe2.1 lane connected (multiplexed
    with USB 3.0 port)
  - MicroSD slot
  - optional eMMC, 8, 16 or 32GB available
  - optional on-board 16MiB bootable SPI NOR flash
  - two 1Gbps Ethernet ports (via MAXIO MAE0621A PHYs)
  - PoE header for optional supply circuit on one Ethernet port
  - WiFi 802.11 a/b/g/n/ac/ax (LB-Link BL-M8800DS2 module using AIC8800)
  - HDMI port
  - camera and LCD connectors
  - power supply via USB-C connector (but no PD) or GPIO header pins

This .dts describes the devices as far as we support them at the moment.
The PMIC rails have been assigned as per the schematics.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-a527-radxa-a5e.dts   | 299 ++++++++++++++++++
 2 files changed, 300 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 983be49ea6ef8..9d5e14695af0b 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,5 +52,6 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-a527-radxa-a5e.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-h728-x96qpro+.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
new file mode 100644
index 0000000000000..912e1bda974ce
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2025 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Radxa A5E";
+	compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the USB-C connector */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_vbus: vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc5v>;
+		gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>;	/* PL8 */
+		enable-active-high;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_cldo3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_cldo3>;
+	vcc-pe-supply = <&reg_aldo2>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_cldo3>;
+	vcc-pj-supply = <&reg_cldo4>;
+	vcc-pk-supply = <&reg_cldo1>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 34 {
+		compatible = "x-powers,axp717";
+		reg = <0x34>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.4 GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pe";
+			};
+
+			reg_aldo3: aldo3 {
+				/* supplies the I2C pins for this PMIC */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pl-usb";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-iowifi";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pm-lpddr4";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-mipi-cam";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pc-and-their-dog";
+			};
+
+			reg_cldo2: cldo2 {
+				/* not connected */
+			};
+
+			reg_cldo3: cldo3 {
+				/* IO, USB-2, 3V3, card, NAND, sensor, PI */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-io-mmc-spi-ana";
+			};
+
+			reg_cldo4: cldo4 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pj-phy";
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-mipi-dsi";
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			/* RISC-V management core supply */
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-dnr";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * The USB-C port is the primary power supply, so in this configuration
+	 * relies on the other end of the USB cable to supply the VBUS power.
+	 * So use this port in peripheral mode.
+	 * It is possible to supply the board with the 5V pins on the GPIO
+	 * header, and since the DCIN_5V line is hardwired to the USB-C VBUS
+	 * pins, the port turns into a host port, unconditionally supplying
+	 * power. The dr_mode property should be changed to "host" here, if
+	 * users choose this setup.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+/*
+ * The schematic describes USB0_ID (PL10), measuring VBUS_5V, which looks to
+ * be always on. Also there is USB-VBUSDET (PL2), which is measuring the same
+ * VBUS_5V. There is also DCIN_DET, which measures DCIN_5V, so the power
+ * input rail.
+ * None of them seem to make any sense in relation to detecting USB devices
+ * or whether there is power provided via any USB pins: they would always
+ * report high, otherwise the system wouldn't be running.
+ * The AXP717C provides proper USB-C CC pin functionality, but the PMIC is
+ * not connected to those pins of the USB-C connector.
+ */
+&usbphy {
+	usb0_vbus-supply = <&reg_vcc5v>;
+	usb1_vbus-supply = <&reg_usb_vbus>;
+	status = "okay";
+};
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:08 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:08 +0000
Subject: [PATCH v2 14/15] dt-bindings: arm: sunxi: Add YuzukiHD Chameleon board name
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-15-andre.przywara@arm.com>

The Chameleon is an Open Source hardware board designed by YuzkuiHD,
using the Allwinner H618 SoC: https://github.com/YuzukiHD/YuzukiChameleon

Add its compatible name to the list of valid board name.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 80096819fda91..cce31492b0f11 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -1091,4 +1091,9 @@ properties:
           - const: yuzukihd,avaota-a1
           - const: allwinner,sun55i-t527
 
+      - description: YuzukiHD Chameleon
+        items:
+          - const: yuzukihd,chameleon
+          - const: allwinner,sun50i-h618
+
 additionalProperties: true
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:09 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:09 +0000
Subject: [PATCH v2 15/15] arm64: dts: allwinner: h616: add YuzukiHD Chameleon support
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-16-andre.przywara@arm.com>

The Chameleon board is an OpenHardware devboard made by YuzukiTsuru.
The form factor resembles the Raspberry Pi Model A boards, though it
differs significantly in its features:

  - Allwinner H618 SoC (4 * Arm Cortex-A53 cores, 1MB L2 cache, 1.4 GHz)
  - between 512MiB and 2GiB DDR3 DRAM
  - up to 128 GiB eMMC flash
  - AXP313a PMIC
  - 100 Mbit/s Ethernet pins on a header
  - XR829 WIFI+Bluetooth chip
  - 4 * USB 2.0 USB-C ports
  - microSD card slot
  - 3.5mm A/V port

Add the devicetree describing the board's peripherals and their
connections.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../sun50i-h618-yuzukihd-chameleon.dts        | 222 ++++++++++++++++++
 2 files changed, 223 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 9d5e14695af0b..c15f6a0d8d55a 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-longanpi-3h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero2w.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero3.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-transpeed-8k618-t.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-yuzukihd-chameleon.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
new file mode 100644
index 0000000000000..eae56908b9b4e
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Yuzuki Chameleon";
+	compatible = "yuzukihd,chameleon", "allwinner,sun50i-h618";
+
+	aliases {
+		ethernet1 = &sdio_wifi;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply directly from the USB-C socket */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	wifi_pwrseq: pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&rtc CLK_OSC32K_FANOUT>;
+		clock-names = "ext_clock";
+		pinctrl-0 = <&x32clk_fanout_pin>;
+		pinctrl-names = "default";
+		reset-gpios = <&pio 6 11 GPIO_ACTIVE_LOW>; /* PG11 */
+	};
+};
+
+&codec {
+	allwinner,audio-routing = "Line Out", "LINEOUT";
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;	/* PF6 */
+	disable-wp;
+	vmmc-supply = <&reg_dldo1>;
+	status = "okay";
+};
+
+&mmc1 {
+	bus-width = <4>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	non-removable;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
+	status = "okay";
+
+	sdio_wifi: wifi at 1 {
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <6 12 IRQ_TYPE_LEVEL_LOW>;  /* PG12 */
+		interrupt-names = "host-wake";
+	};
+};
+
+&mmc2 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	mmc-ddr-3_3v;
+	non-removable;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pc-supply = <&reg_dldo1>;
+	vcc-pf-supply = <&reg_dldo1>;	/* via VCC_IO */
+	vcc-pg-supply = <&reg_dldo1>;
+	vcc-ph-supply = <&reg_dldo1>;	/* via VCC_IO */
+	vcc-pi-supply = <&reg_dldo1>;
+};
+
+&r_i2c {
+	status = "okay";
+
+	axp313: pmic at 36 {
+		compatible = "x-powers,axp313a";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&pio>;
+		interrupts = <2 2 IRQ_TYPE_LEVEL_LOW>;	/* PC2 */
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies VCC-PLL, so needs to be always on. */
+			reg_aldo1: aldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc1v8";
+			};
+
+			/* Supplies VCC-IO, so needs to be always on. */
+			reg_dldo1: dldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc3v3";
+			};
+
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <990000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpu";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd-dram";
+			};
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_ph_pins>;
+	status = "okay";
+};
+
+/* Connected to the Bluetooth UART pins of the XR829 Wifi/BT chip. */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg {
+	/*
+	 * PHY0 pins are connected to a USB-C socket, but a role switch
+	 * is not implemented: both CC pins are pulled to GND.
+	 * The VBUS pins power the device, so a fixed peripheral mode
+	 * is the best choice.
+	 * The board can be powered via GPIOs, in this case port0 *can*
+	 * act as a host (with a cable/adapter ignoring CC), as VBUS is
+	 * then provided by the GPIOs. Any user of this setup would
+	 * need to adjust the DT accordingly: dr_mode set to "host",
+	 * enabling OHCI0 and EHCI0.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb0_id_det-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18 */
+	usb0_vbus-supply = <&reg_vcc5v>;
+	usb1_vbus-supply = <&reg_vcc5v>;
+	usb2_vbus-supply = <&reg_vcc5v>;
+	usb3_vbus-supply = <&reg_vcc5v>;
+	status = "okay";
+};
-- 
2.46.3



From yang at os.amperecomputing.com  Tue Mar  4 14:19:25 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:25 -0800
Subject: [v3 PATCH 0/6] arm64: support FEAT_BBM level 2 and large block mapping when rodata=full
Message-ID: <20250304222018.615808-1-yang@os.amperecomputing.com>


Changelog
=========
v3:
  * Rebased to v6.14-rc4.
  * Based on Miko's BBML2 cpufeature patch (https://lore.kernel.org/linux-arm-kernel/20250228182403.6269-3-miko.lenczewski at arm.com/).
    Also included in this series in order to have the complete patchset.
  * Enhanced __create_pgd_mapping() to handle split as well per Ryan.
  * Supported CONT mappings per Ryan.
  * Supported asymmetric system by splitting kernel linear mapping if such
    system is detected per Ryan. I don't have such system to test, so the
    testing is done by hacking kernel to call linear mapping repainting
    unconditionally. The linear mapping doesn't have any block and cont
    mappings after booting.

RFC v2:
  * Used allowlist to advertise BBM lv2 on the CPUs which can handle TLB
    conflict gracefully per Will Deacon
  * Rebased onto v6.13-rc5
  * https://lore.kernel.org/linux-arm-kernel/20250103011822.1257189-1-yang at os.amperecomputing.com/

RFC v1: https://lore.kernel.org/lkml/20241118181711.962576-1-yang at os.amperecomputing.com/

Description
===========
When rodata=full kernel linear mapping is mapped by PTE due to arm's
break-before-make rule.

A number of performance issues arise when the kernel linear map is using
PTE entries due to arm's break-before-make rule:
  - performance degradation
  - more TLB pressure
  - memory waste for kernel page table

These issues can be avoided by specifying rodata=on the kernel command
line but this disables the alias checks on page table permissions and
therefore compromises security somewhat.

With FEAT_BBM level 2 support it is no longer necessary to invalidate the
page table entry when changing page sizes.  This allows the kernel to
split large mappings after boot is complete.

This patch adds support for splitting large mappings when FEAT_BBM level 2
is available and rodata=full is used. This functionality will be used
when modifying page permissions for individual page frames.

Without FEAT_BBM level 2 we will keep the kernel linear map using PTEs
only.

If the system is asymmetric, the kernel linear mapping may be repainted once
the BBML2 capability is finalized on all CPUs.  See patch #6 for more details.

We saw significant performance increases in some benchmarks with
rodata=full without compromising the security features of the kernel.

Testing
=======
The test was done on AmpereOne machine (192 cores, 1P) with 256GB memory and
4K page size + 48 bit VA.

Function test (4K/16K/64K page size)
  - Kernel boot.  Kernel needs change kernel linear mapping permission at
    boot stage, if the patch didn't work, kernel typically didn't boot.
  - Module stress from stress-ng. Kernel module load change permission for
    linear mapping.
  - A test kernel module which allocates 80% of total memory via vmalloc(),
    then change the vmalloc area permission to RO, this also change linear
    mapping permission to RO, then change it back before vfree(). Then launch
    a VM which consumes almost all physical memory.
  - VM with the patchset applied in guest kernel too.
  - Kernel build in VM with guest kernel which has this series applied.
  - rodata=on. Make sure other rodata mode is not broken.
  - Boot on the machine which doesn't support BBML2.

Performance
===========
Memory consumption
Before:
MemTotal:       258988984 kB
MemFree:        254821700 kB

After:
MemTotal:       259505132 kB
MemFree:        255410264 kB

Around 500MB more memory are free to use.  The larger the machine, the
more memory saved.

Performance benchmarking
* Memcached
We saw performance degradation when running Memcached benchmark with
rodata=full vs rodata=on.  Our profiling pointed to kernel TLB pressure.
With this patchset we saw ops/sec is increased by around 3.5%, P99
latency is reduced by around 9.6%.
The gain mainly came from reduced kernel TLB misses.  The kernel TLB
MPKI is reduced by 28.5%.

The benchmark data is now on par with rodata=on too.

* Disk encryption (dm-crypt) benchmark
Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
encryption (by dm-crypt).
fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
    --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
    --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
    --name=iops-test-job --eta-newline=1 --size 100G

The IOPS is increased by 90% - 150% (the variance is high, but the worst
number of good case is around 90% more than the best number of bad case).
The bandwidth is increased and the avg clat is reduced proportionally.

* Sequential file read
Read 100G file sequentially on XFS (xfs_io read with page cache populated).
The bandwidth is increased by 150%.


Miko?aj Lenczewski (1):
      arm64: Add BBM Level 2 cpu feature

Yang Shi (5):
      arm64: cpufeature: add AmpereOne to BBML2 allow list
      arm64: mm: make __create_pgd_mapping() and helpers non-void
      arm64: mm: support large block mapping when rodata=full
      arm64: mm: support split CONT mappings
      arm64: mm: split linear mapping if BBML2 is not supported on secondary CPUs

 arch/arm64/Kconfig                  |  11 +++++
 arch/arm64/include/asm/cpucaps.h    |   2 +
 arch/arm64/include/asm/cpufeature.h |  15 ++++++
 arch/arm64/include/asm/mmu.h        |   4 ++
 arch/arm64/include/asm/pgtable.h    |  12 ++++-
 arch/arm64/kernel/cpufeature.c      |  95 +++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/mmu.c                 | 397 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
 arch/arm64/mm/pageattr.c            |  37 ++++++++++++---
 arch/arm64/tools/cpucaps            |   1 +
 9 files changed, 518 insertions(+), 56 deletions(-)



From yang at os.amperecomputing.com  Tue Mar  4 14:19:26 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:26 -0800
Subject: [v3 PATCH 1/6] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-2-yang@os.amperecomputing.com>

From: Miko?aj Lenczewski <miko.lenczewski at arm.com>

The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
and this commit adds a dedicated BBML2 cpufeature to test against
support for.

This is a system feature as we might have a big.LITTLE architecture
where some cores support BBML2 and some don't, but we want all cores to
be available and BBM to default to level 0 (as opposed to having cores
without BBML2 not coming online).

To support BBML2 in as wide a range of contexts as we can, we want not
only the architectural guarantees that BBML2 makes, but additionally
want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
us having to prove that no recursive faults can be induced in any path
that uses BBML2, allowing its use for arbitrary kernel mappings.
Support detection of such CPUs.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 arch/arm64/Kconfig                  | 11 +++++
 arch/arm64/include/asm/cpucaps.h    |  2 +
 arch/arm64/include/asm/cpufeature.h |  5 +++
 arch/arm64/kernel/cpufeature.c      | 69 +++++++++++++++++++++++++++++
 arch/arm64/tools/cpucaps            |  1 +
 5 files changed, 88 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..49deda2b22ae 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
 	  The feature introduces new assembly instructions, and they were
 	  support when binutils >= 2.30.
 
+config ARM64_BBML2_NOABORT
+	bool "Enable support for Break-Before-Make Level 2 detection and usage"
+	default y
+	help
+	  FEAT_BBM provides detection of support levels for break-before-make
+	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
+	  can be relaxed to improve performance. We additonally require the
+	  property that the implementation cannot ever raise TLB Conflict Aborts.
+	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
+	  even if the system supports BBM level 2.
+
 endmenu # "ARMv8.4 architectural features"
 
 menu "ARMv8.5 architectural features"
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 0b5ca6e0eb09..2d6db33d4e45 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
 		return IS_ENABLED(CONFIG_ARM64_PAN);
 	case ARM64_HAS_EPAN:
 		return IS_ENABLED(CONFIG_ARM64_EPAN);
+	case ARM64_HAS_BBML2_NOABORT:
+		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
 	case ARM64_SVE:
 		return IS_ENABLED(CONFIG_ARM64_SVE);
 	case ARM64_SME:
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..108ef3fbbc00 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
 	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
 }
 
+static inline bool system_supports_bbml2_noabort(void)
+{
+	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d561cf3b8ac7..7934c6dd493e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2176,6 +2176,68 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
 	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
 }
 
+static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
+{
+	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
+	 * as possible. This list is therefore an allow-list of known-good
+	 * implementations that both support bbml2 and additionally, fulfill the
+	 * extra constraint of never generating TLB conflict aborts when using
+	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
+	 * kernel contexts difficult to prove safe against recursive aborts).
+	 *
+	 * Note that implementations can only be considered "known-good" if their
+	 * implementors attest to the fact that the implementation never raises
+	 * TLBI conflict aborts for bbml2 mapping granularity changes.
+	 */
+	static const struct midr_range supports_bbml2_noabort_list[] = {
+		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
+		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
+		{}
+	};
+
+	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
+}
+
+static inline unsigned int __cpu_read_midr(int cpu)
+{
+	WARN_ON_ONCE(!cpu_online(cpu));
+
+	return per_cpu(cpu_data, cpu).reg_midr;
+}
+
+static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
+		return false;
+
+	if (scope & SCOPE_SYSTEM) {
+		int cpu;
+
+		/* We are a boot CPU, and must verify that all enumerated boot
+		 * CPUs have MIDR values within our allowlist. Otherwise, we do
+		 * not allow the BBML2 feature to avoid potential faults when
+		 * the insufficient CPUs access memory regions using BBML2
+		 * semantics.
+		 */
+		for_each_online_cpu(cpu) {
+			if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
+				return false;
+		}
+
+		return true;
+	} else if (scope & SCOPE_LOCAL_CPU) {
+		/* We are a hot-plugged CPU, so only need to check our MIDR.
+		 * If we have the correct MIDR, but the kernel booted on an
+		 * insufficient CPU, we will not use BBML2 (this is safe). If
+		 * we have an incorrect MIDR, but the kernel booted on a
+		 * sufficient CPU, we will not bring up this CPU.
+		 */
+		return cpu_has_bbml2_noabort(read_cpuid_id());
+	}
+
+	return false;
+}
+
 #ifdef CONFIG_ARM64_PAN
 static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
@@ -2926,6 +2988,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.matches = has_cpuid_feature,
 		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
 	},
+	{
+		.desc = "BBM Level 2 without conflict abort",
+		.capability = ARM64_HAS_BBML2_NOABORT,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_bbml2_noabort,
+		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
+	},
 	{
 		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
 		.capability = ARM64_HAS_LPA2,
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1e65f2fb45bd..b03a375e5507 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
 HAS_ADDRESS_AUTH_IMP_DEF
 HAS_AMU_EXTN
 HAS_ARMv8_4_TTL
+HAS_BBML2_NOABORT
 HAS_CACHE_DIC
 HAS_CACHE_IDC
 HAS_CNP
-- 
2.47.1



From yang at os.amperecomputing.com  Tue Mar  4 14:19:27 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:27 -0800
Subject: [v3 PATCH 2/6] arm64: cpufeature: add AmpereOne to BBML2 allow list
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-3-yang@os.amperecomputing.com>

AmpereOne supports BBML2 without conflict abort, add to the allow list.

Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
 arch/arm64/kernel/cpufeature.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 7934c6dd493e..bf3df8407ca3 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2192,6 +2192,8 @@ static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
 	static const struct midr_range supports_bbml2_noabort_list[] = {
 		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
 		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
+		MIDR_ALL_VERSIONS(MIDR_AMPERE1),
+		MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
 		{}
 	};
 
-- 
2.47.1



From yang at os.amperecomputing.com  Tue Mar  4 14:19:28 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:28 -0800
Subject: [v3 PATCH 3/6] arm64: mm: make __create_pgd_mapping() and helpers non-void
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-4-yang@os.amperecomputing.com>

The later patch will enhance __create_pgd_mapping() and related helpers
to split kernel linear mapping, it requires have return value.  So make
__create_pgd_mapping() and helpers non-void functions.

And move the BUG_ON() out of page table alloc helper since failing
splitting kernel linear mapping is not fatal and can be handled by the
callers in the later patch.  Have BUG_ON() after
__create_pgd_mapping_locked() returns to keep the current callers behavior
intact.

Suggested-by: Ryan Roberts <ryan.roberts at arm.com>
Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
 arch/arm64/mm/mmu.c | 127 ++++++++++++++++++++++++++++++--------------
 1 file changed, 86 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index b4df5bc5b1b8..dccf0877285b 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -189,11 +189,11 @@ static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
 	} while (ptep++, addr += PAGE_SIZE, addr != end);
 }
 
-static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
-				unsigned long end, phys_addr_t phys,
-				pgprot_t prot,
-				phys_addr_t (*pgtable_alloc)(int),
-				int flags)
+static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
+			       unsigned long end, phys_addr_t phys,
+			       pgprot_t prot,
+			       phys_addr_t (*pgtable_alloc)(int),
+			       int flags)
 {
 	unsigned long next;
 	pmd_t pmd = READ_ONCE(*pmdp);
@@ -208,6 +208,8 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 			pmdval |= PMD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
 		pte_phys = pgtable_alloc(PAGE_SHIFT);
+		if (!pte_phys)
+			return -ENOMEM;
 		ptep = pte_set_fixmap(pte_phys);
 		init_clear_pgtable(ptep);
 		ptep += pte_index(addr);
@@ -239,13 +241,16 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 	 * walker.
 	 */
 	pte_clear_fixmap();
+
+	return 0;
 }
 
-static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
-		     phys_addr_t phys, pgprot_t prot,
-		     phys_addr_t (*pgtable_alloc)(int), int flags)
+static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
+		    phys_addr_t phys, pgprot_t prot,
+		    phys_addr_t (*pgtable_alloc)(int), int flags)
 {
 	unsigned long next;
+	int ret = 0;
 
 	do {
 		pmd_t old_pmd = READ_ONCE(*pmdp);
@@ -264,22 +269,27 @@ static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
 			BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd),
 						      READ_ONCE(pmd_val(*pmdp))));
 		} else {
-			alloc_init_cont_pte(pmdp, addr, next, phys, prot,
+			ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot,
 					    pgtable_alloc, flags);
+			if (ret)
+				break;
 
 			BUG_ON(pmd_val(old_pmd) != 0 &&
 			       pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp)));
 		}
 		phys += next - addr;
 	} while (pmdp++, addr = next, addr != end);
+
+	return ret;
 }
 
-static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
-				unsigned long end, phys_addr_t phys,
-				pgprot_t prot,
-				phys_addr_t (*pgtable_alloc)(int), int flags)
+static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
+			       unsigned long end, phys_addr_t phys,
+			       pgprot_t prot,
+			       phys_addr_t (*pgtable_alloc)(int), int flags)
 {
 	unsigned long next;
+	int ret = 0;
 	pud_t pud = READ_ONCE(*pudp);
 	pmd_t *pmdp;
 
@@ -295,6 +305,8 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 			pudval |= PUD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
 		pmd_phys = pgtable_alloc(PMD_SHIFT);
+		if (!pmd_phys)
+			return -ENOMEM;
 		pmdp = pmd_set_fixmap(pmd_phys);
 		init_clear_pgtable(pmdp);
 		pmdp += pmd_index(addr);
@@ -314,21 +326,26 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 		    (flags & NO_CONT_MAPPINGS) == 0)
 			__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
 
-		init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
+		ret = init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
+		if (ret)
+			break;
 
 		pmdp += pmd_index(next) - pmd_index(addr);
 		phys += next - addr;
 	} while (addr = next, addr != end);
 
 	pmd_clear_fixmap();
+
+	return ret;
 }
 
-static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
-			   phys_addr_t phys, pgprot_t prot,
-			   phys_addr_t (*pgtable_alloc)(int),
-			   int flags)
+static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
+			  phys_addr_t phys, pgprot_t prot,
+			  phys_addr_t (*pgtable_alloc)(int),
+			  int flags)
 {
 	unsigned long next;
+	int ret = 0;
 	p4d_t p4d = READ_ONCE(*p4dp);
 	pud_t *pudp;
 
@@ -340,6 +357,8 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 			p4dval |= P4D_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
 		pud_phys = pgtable_alloc(PUD_SHIFT);
+		if (!pud_phys)
+			return -ENOMEM;
 		pudp = pud_set_fixmap(pud_phys);
 		init_clear_pgtable(pudp);
 		pudp += pud_index(addr);
@@ -369,8 +388,10 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 			BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
 						      READ_ONCE(pud_val(*pudp))));
 		} else {
-			alloc_init_cont_pmd(pudp, addr, next, phys, prot,
+			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
 					    pgtable_alloc, flags);
+			if (ret)
+				break;
 
 			BUG_ON(pud_val(old_pud) != 0 &&
 			       pud_val(old_pud) != READ_ONCE(pud_val(*pudp)));
@@ -379,14 +400,17 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 	} while (pudp++, addr = next, addr != end);
 
 	pud_clear_fixmap();
+
+	return ret;
 }
 
-static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
-			   phys_addr_t phys, pgprot_t prot,
-			   phys_addr_t (*pgtable_alloc)(int),
-			   int flags)
+static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
+			  phys_addr_t phys, pgprot_t prot,
+			  phys_addr_t (*pgtable_alloc)(int),
+			  int flags)
 {
 	unsigned long next;
+	int ret = 0;
 	pgd_t pgd = READ_ONCE(*pgdp);
 	p4d_t *p4dp;
 
@@ -398,6 +422,8 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 			pgdval |= PGD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
 		p4d_phys = pgtable_alloc(P4D_SHIFT);
+		if (!p4d_phys)
+			return -ENOMEM;
 		p4dp = p4d_set_fixmap(p4d_phys);
 		init_clear_pgtable(p4dp);
 		p4dp += p4d_index(addr);
@@ -412,8 +438,10 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 
 		next = p4d_addr_end(addr, end);
 
-		alloc_init_pud(p4dp, addr, next, phys, prot,
+		ret = alloc_init_pud(p4dp, addr, next, phys, prot,
 			       pgtable_alloc, flags);
+		if (ret)
+			break;
 
 		BUG_ON(p4d_val(old_p4d) != 0 &&
 		       p4d_val(old_p4d) != READ_ONCE(p4d_val(*p4dp)));
@@ -422,23 +450,26 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 	} while (p4dp++, addr = next, addr != end);
 
 	p4d_clear_fixmap();
+
+	return ret;
 }
 
-static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
-					unsigned long virt, phys_addr_t size,
-					pgprot_t prot,
-					phys_addr_t (*pgtable_alloc)(int),
-					int flags)
+static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
+				       unsigned long virt, phys_addr_t size,
+				       pgprot_t prot,
+				       phys_addr_t (*pgtable_alloc)(int),
+				       int flags)
 {
 	unsigned long addr, end, next;
 	pgd_t *pgdp = pgd_offset_pgd(pgdir, virt);
+	int ret = 0;
 
 	/*
 	 * If the virtual and physical address don't have the same offset
 	 * within a page, we cannot map the region as the caller expects.
 	 */
 	if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
-		return;
+		return -EINVAL;
 
 	phys &= PAGE_MASK;
 	addr = virt & PAGE_MASK;
@@ -446,29 +477,38 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
 
 	do {
 		next = pgd_addr_end(addr, end);
-		alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
+		ret = alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
 			       flags);
+		if (ret)
+			break;
 		phys += next - addr;
 	} while (pgdp++, addr = next, addr != end);
+
+	return ret;
 }
 
-static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
-				 unsigned long virt, phys_addr_t size,
-				 pgprot_t prot,
-				 phys_addr_t (*pgtable_alloc)(int),
-				 int flags)
+static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
+				unsigned long virt, phys_addr_t size,
+				pgprot_t prot,
+				phys_addr_t (*pgtable_alloc)(int),
+				int flags)
 {
+	int ret;
+
 	mutex_lock(&fixmap_lock);
-	__create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
+	ret = __create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
 				    pgtable_alloc, flags);
+	BUG_ON(ret);
 	mutex_unlock(&fixmap_lock);
+
+	return ret;
 }
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 extern __alias(__create_pgd_mapping_locked)
-void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
-			     phys_addr_t size, pgprot_t prot,
-			     phys_addr_t (*pgtable_alloc)(int), int flags);
+int create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
+			    phys_addr_t size, pgprot_t prot,
+			    phys_addr_t (*pgtable_alloc)(int), int flags);
 #endif
 
 static phys_addr_t __pgd_pgtable_alloc(int shift)
@@ -476,13 +516,17 @@ static phys_addr_t __pgd_pgtable_alloc(int shift)
 	/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
 	void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL & ~__GFP_ZERO);
 
-	BUG_ON(!ptr);
+	if (!ptr)
+		return 0;
+
 	return __pa(ptr);
 }
 
 static phys_addr_t pgd_pgtable_alloc(int shift)
 {
 	phys_addr_t pa = __pgd_pgtable_alloc(shift);
+	if (!pa)
+		goto out;
 	struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa));
 
 	/*
@@ -498,6 +542,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
 	else if (shift == PMD_SHIFT)
 		BUG_ON(!pagetable_pmd_ctor(ptdesc));
 
+out:
 	return pa;
 }
 
-- 
2.47.1



From yang at os.amperecomputing.com  Tue Mar  4 14:19:29 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:29 -0800
Subject: [v3 PATCH 4/6] arm64: mm: support large block mapping when rodata=full
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-5-yang@os.amperecomputing.com>

When rodata=full is specified, kernel linear mapping has to be mapped at
PTE level since large page table can't be split due to break-before-make
rule on ARM64.

This resulted in a couple of problems:
  - performance degradation
  - more TLB pressure
  - memory waste for kernel page table

With FEAT_BBM level 2 support, splitting large block page table to
smaller ones doesn't need to make the page table entry invalid anymore.
This allows kernel split large block mapping on the fly.

Add kernel page table split support and use large block mapping by
default when FEAT_BBM level 2 is supported for rodata=full.  When
changing permissions for kernel linear mapping, the page table will be
split to PTE level.

The machine without FEAT_BBM level 2 will fallback to have kernel linear
mapping PTE-mapped when rodata=full.

With this we saw significant performance boost with some benchmarks and
much less memory consumption on my AmpereOne machine (192 cores, 1P) with
256GB memory.

* Memory use after boot
Before:
MemTotal:       258988984 kB
MemFree:        254821700 kB

After:
MemTotal:       259505132 kB
MemFree:        255410264 kB

Around 500MB more memory are free to use.  The larger the machine, the
more memory saved.

* Memcached
We saw performance degradation when running Memcached benchmark with
rodata=full vs rodata=on.  Our profiling pointed to kernel TLB pressure.
With this patchset we saw ops/sec is increased by around 3.5%, P99
latency is reduced by around 9.6%.
The gain mainly came from reduced kernel TLB misses.  The kernel TLB
MPKI is reduced by 28.5%.

The benchmark data is now on par with rodata=on too.

* Disk encryption (dm-crypt) benchmark
Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
encryption (by dm-crypt).
fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
    --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
    --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
    --name=iops-test-job --eta-newline=1 --size 100G

The IOPS is increased by 90% - 150% (the variance is high, but the worst
number of good case is around 90% more than the best number of bad case).
The bandwidth is increased and the avg clat is reduced proportionally.

* Sequential file read
Read 100G file sequentially on XFS (xfs_io read with page cache populated).
The bandwidth is increased by 150%.

Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
 arch/arm64/include/asm/cpufeature.h |  10 ++
 arch/arm64/include/asm/mmu.h        |   1 +
 arch/arm64/include/asm/pgtable.h    |   7 +-
 arch/arm64/kernel/cpufeature.c      |   2 +-
 arch/arm64/mm/mmu.c                 | 169 +++++++++++++++++++++++++++-
 arch/arm64/mm/pageattr.c            |  35 +++++-
 6 files changed, 211 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 108ef3fbbc00..e24edc32b0bd 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -871,6 +871,16 @@ static inline bool system_supports_bbml2_noabort(void)
 	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
 }
 
+bool cpu_has_bbml2_noabort(unsigned int cpu_midr);
+/*
+ * Called at early boot stage on boot CPU before cpu info and cpu feature
+ * are ready.
+ */
+static inline bool bbml2_noabort_available(void)
+{
+	return cpu_has_bbml2_noabort(read_cpuid_id());
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 662471cfc536..d658a33df266 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -71,6 +71,7 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 			       pgprot_t prot, bool page_mappings_only);
 extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
 extern void mark_linear_text_alias_ro(void);
+extern int split_linear_mapping(unsigned long start, unsigned long end);
 
 /*
  * This check is triggered during the early boot before the cpufeature
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 0b2a2ad1b9e8..ed2fc1dcf7ae 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -749,7 +749,7 @@ static inline bool in_swapper_pgdir(void *addr)
 	        ((unsigned long)swapper_pg_dir & PAGE_MASK);
 }
 
-static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
+static inline void __set_pmd_nosync(pmd_t *pmdp, pmd_t pmd)
 {
 #ifdef __PAGETABLE_PMD_FOLDED
 	if (in_swapper_pgdir(pmdp)) {
@@ -759,6 +759,11 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 #endif /* __PAGETABLE_PMD_FOLDED */
 
 	WRITE_ONCE(*pmdp, pmd);
+}
+
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+	__set_pmd_nosync(pmdp, pmd);
 
 	if (pmd_valid(pmd)) {
 		dsb(ishst);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index bf3df8407ca3..d39637d5aeab 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2176,7 +2176,7 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
 	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
 }
 
-static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
+bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
 {
 	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
 	 * as possible. This list is therefore an allow-list of known-good
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index dccf0877285b..ad0f1cc55e3a 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -45,6 +45,7 @@
 #define NO_BLOCK_MAPPINGS	BIT(0)
 #define NO_CONT_MAPPINGS	BIT(1)
 #define NO_EXEC_MAPPINGS	BIT(2)	/* assumes FEAT_HPDS is not used */
+#define SPLIT_MAPPINGS		BIT(3)
 
 u64 kimage_voffset __ro_after_init;
 EXPORT_SYMBOL(kimage_voffset);
@@ -166,6 +167,73 @@ static void init_clear_pgtable(void *table)
 	dsb(ishst);
 }
 
+static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
+		     phys_addr_t (*pgtable_alloc)(int))
+{
+	unsigned long pfn;
+	pgprot_t prot;
+	phys_addr_t pte_phys;
+	pte_t *ptep;
+
+	if (!pmd_leaf(pmdval))
+		return 0;
+
+	pfn = pmd_pfn(pmdval);
+	prot = pmd_pgprot(pmdval);
+
+	pte_phys = pgtable_alloc(PAGE_SHIFT);
+	if (!pte_phys)
+		return -ENOMEM;
+
+	ptep = (pte_t *)phys_to_virt(pte_phys);
+	init_clear_pgtable(ptep);
+	prot = __pgprot(pgprot_val(prot) | PTE_TYPE_PAGE);
+	for (int i = 0; i < PTRS_PER_PTE; i++, ptep++)
+		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));
+
+	dsb(ishst);
+
+	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(pte_phys),
+		__pgprot(PMD_TYPE_TABLE)));
+
+	return 0;
+}
+
+static int split_pud(pud_t *pudp, pud_t pudval,
+		     phys_addr_t (*pgtable_alloc)(int))
+{
+	unsigned long pfn;
+	pgprot_t prot;
+	pmd_t *pmdp;
+	phys_addr_t pmd_phys;
+	unsigned int step;
+
+	if (!pud_leaf(pudval))
+		return 0;
+
+	pfn = pud_pfn(pudval);
+	prot = pud_pgprot(pudval);
+	step = PMD_SIZE >> PAGE_SHIFT;
+
+	pmd_phys = pgtable_alloc(PMD_SHIFT);
+	if (!pmd_phys)
+		return -ENOMEM;
+
+	pmdp = (pmd_t *)phys_to_virt(pmd_phys);
+	init_clear_pgtable(pmdp);
+	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
+		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
+		pfn += step;
+	}
+
+	dsb(ishst);
+
+	set_pud(pudp, pfn_pud(__phys_to_pfn(pmd_phys),
+		__pgprot(PUD_TYPE_TABLE)));
+
+	return 0;
+}
+
 static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
 		     phys_addr_t phys, pgprot_t prot)
 {
@@ -251,12 +319,21 @@ static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
 {
 	unsigned long next;
 	int ret = 0;
+	bool split = flags & SPLIT_MAPPINGS;
 
 	do {
 		pmd_t old_pmd = READ_ONCE(*pmdp);
 
 		next = pmd_addr_end(addr, end);
 
+		if (split) {
+			ret = split_pmd(pmdp, old_pmd, pgtable_alloc);
+			if (ret)
+				break;
+
+			continue;
+		}
+
 		/* try section mapping first */
 		if (((addr | next | phys) & ~PMD_MASK) == 0 &&
 		    (flags & NO_BLOCK_MAPPINGS) == 0) {
@@ -292,11 +369,19 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 	int ret = 0;
 	pud_t pud = READ_ONCE(*pudp);
 	pmd_t *pmdp;
+	bool split = flags & SPLIT_MAPPINGS;
 
 	/*
 	 * Check for initial section mappings in the pgd/pud.
 	 */
 	BUG_ON(pud_sect(pud));
+
+	if (split) {
+		BUG_ON(pud_none(pud));
+		pmdp = pmd_offset(pudp, addr);
+		goto split_pgtable;
+	}
+
 	if (pud_none(pud)) {
 		pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
 		phys_addr_t pmd_phys;
@@ -316,6 +401,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 		pmdp = pmd_set_fixmap_offset(pudp, addr);
 	}
 
+split_pgtable:
 	do {
 		pgprot_t __prot = prot;
 
@@ -334,7 +420,8 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 		phys += next - addr;
 	} while (addr = next, addr != end);
 
-	pmd_clear_fixmap();
+	if (!split)
+		pmd_clear_fixmap();
 
 	return ret;
 }
@@ -348,6 +435,13 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 	int ret = 0;
 	p4d_t p4d = READ_ONCE(*p4dp);
 	pud_t *pudp;
+	bool split = flags & SPLIT_MAPPINGS;
+
+	if (split) {
+		BUG_ON(p4d_none(p4d));
+		pudp = pud_offset(p4dp, addr);
+		goto split_pgtable;
+	}
 
 	if (p4d_none(p4d)) {
 		p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
@@ -368,11 +462,25 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 		pudp = pud_set_fixmap_offset(p4dp, addr);
 	}
 
+split_pgtable:
 	do {
 		pud_t old_pud = READ_ONCE(*pudp);
 
 		next = pud_addr_end(addr, end);
 
+		if (split) {
+			ret = split_pud(pudp, old_pud, pgtable_alloc);
+			if (ret)
+				break;
+
+			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
+						  pgtable_alloc, flags);
+			if (ret)
+				break;
+
+			continue;
+		}
+
 		/*
 		 * For 4K granule only, attempt to put down a 1GB block
 		 */
@@ -399,7 +507,8 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 		phys += next - addr;
 	} while (pudp++, addr = next, addr != end);
 
-	pud_clear_fixmap();
+	if (!split)
+		pud_clear_fixmap();
 
 	return ret;
 }
@@ -413,6 +522,13 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 	int ret = 0;
 	pgd_t pgd = READ_ONCE(*pgdp);
 	p4d_t *p4dp;
+	bool split = flags & SPLIT_MAPPINGS;
+
+	if (split) {
+		BUG_ON(pgd_none(pgd));
+		p4dp = p4d_offset(pgdp, addr);
+		goto split_pgtable;
+	}
 
 	if (pgd_none(pgd)) {
 		pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF;
@@ -433,6 +549,7 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 		p4dp = p4d_set_fixmap_offset(pgdp, addr);
 	}
 
+split_pgtable:
 	do {
 		p4d_t old_p4d = READ_ONCE(*p4dp);
 
@@ -449,7 +566,8 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 		phys += next - addr;
 	} while (p4dp++, addr = next, addr != end);
 
-	p4d_clear_fixmap();
+	if (!split)
+		p4d_clear_fixmap();
 
 	return ret;
 }
@@ -546,6 +664,23 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
 	return pa;
 }
 
+int split_linear_mapping(unsigned long start, unsigned long end)
+{
+	int ret = 0;
+
+	if (!system_supports_bbml2_noabort())
+		return 0;
+
+	mmap_write_lock(&init_mm);
+	ret = __create_pgd_mapping_locked(init_mm.pgd, virt_to_phys((void *)start),
+					  start, (end - start), __pgprot(0),
+					  __pgd_pgtable_alloc, SPLIT_MAPPINGS);
+	mmap_write_unlock(&init_mm);
+	flush_tlb_kernel_range(start, end);
+
+	return ret;
+}
+
 /*
  * This function can only be used to modify existing table entries,
  * without allocating new levels of table. Note that this permits the
@@ -665,6 +800,24 @@ static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) {
 
 #endif /* CONFIG_KFENCE */
 
+static inline bool force_pte_mapping(void)
+{
+	/*
+	 * Can't use cpufeature API to determine whether BBML2 supported
+	 * or not since cpufeature have not been finalized yet.
+	 *
+	 * Checking the boot CPU only for now.  If the boot CPU has
+	 * BBML2, paint linear mapping with block mapping.  If it turns
+	 * out the secondary CPUs don't support BBML2 once cpufeature is
+	 * fininalized, the linear mapping will be repainted with PTE
+	 * mapping.
+	 */
+	return (rodata_full && !bbml2_noabort_available()) ||
+		debug_pagealloc_enabled() ||
+		arm64_kfence_can_set_direct_map() ||
+		is_realm_world();
+}
+
 static void __init map_mem(pgd_t *pgdp)
 {
 	static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN);
@@ -690,9 +843,12 @@ static void __init map_mem(pgd_t *pgdp)
 
 	early_kfence_pool = arm64_kfence_alloc_pool();
 
-	if (can_set_direct_map())
+	if (force_pte_mapping())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
+	if (rodata_full)
+		flags |= NO_CONT_MAPPINGS;
+
 	/*
 	 * Take care not to create a writable alias for the
 	 * read-only text and rodata sections of the kernel image.
@@ -1388,9 +1544,12 @@ int arch_add_memory(int nid, u64 start, u64 size,
 
 	VM_BUG_ON(!mhp_range_allowed(start, size, true));
 
-	if (can_set_direct_map())
+	if (force_pte_mapping())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
+	if (rodata_full)
+		flags |= NO_CONT_MAPPINGS;
+
 	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
 			     size, params->pgprot, __pgd_pgtable_alloc,
 			     flags);
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 39fd1f7ff02a..5d42d87ea7e1 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -10,6 +10,7 @@
 #include <linux/vmalloc.h>
 
 #include <asm/cacheflush.h>
+#include <asm/mmu.h>
 #include <asm/pgtable-prot.h>
 #include <asm/set_memory.h>
 #include <asm/tlbflush.h>
@@ -80,8 +81,9 @@ static int change_memory_common(unsigned long addr, int numpages,
 	unsigned long start = addr;
 	unsigned long size = PAGE_SIZE * numpages;
 	unsigned long end = start + size;
+	unsigned long l_start;
 	struct vm_struct *area;
-	int i;
+	int i, ret;
 
 	if (!PAGE_ALIGNED(addr)) {
 		start &= PAGE_MASK;
@@ -118,7 +120,12 @@ static int change_memory_common(unsigned long addr, int numpages,
 	if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
 			    pgprot_val(clear_mask) == PTE_RDONLY)) {
 		for (i = 0; i < area->nr_pages; i++) {
-			__change_memory_common((u64)page_address(area->pages[i]),
+			l_start = (u64)page_address(area->pages[i]);
+			ret = split_linear_mapping(l_start, l_start + PAGE_SIZE);
+			if (WARN_ON_ONCE(ret))
+				return ret;
+
+			__change_memory_common(l_start,
 					       PAGE_SIZE, set_mask, clear_mask);
 		}
 	}
@@ -174,6 +181,9 @@ int set_memory_valid(unsigned long addr, int numpages, int enable)
 
 int set_direct_map_invalid_noflush(struct page *page)
 {
+	unsigned long l_start;
+	int ret;
+
 	struct page_change_data data = {
 		.set_mask = __pgprot(0),
 		.clear_mask = __pgprot(PTE_VALID),
@@ -182,13 +192,21 @@ int set_direct_map_invalid_noflush(struct page *page)
 	if (!can_set_direct_map())
 		return 0;
 
+	l_start = (unsigned long)page_address(page);
+	ret = split_linear_mapping(l_start, l_start + PAGE_SIZE);
+	if (WARN_ON_ONCE(ret))
+		return ret;
+
 	return apply_to_page_range(&init_mm,
-				   (unsigned long)page_address(page),
-				   PAGE_SIZE, change_page_range, &data);
+				   l_start, PAGE_SIZE, change_page_range,
+				   &data);
 }
 
 int set_direct_map_default_noflush(struct page *page)
 {
+	unsigned long l_start;
+	int ret;
+
 	struct page_change_data data = {
 		.set_mask = __pgprot(PTE_VALID | PTE_WRITE),
 		.clear_mask = __pgprot(PTE_RDONLY),
@@ -197,9 +215,14 @@ int set_direct_map_default_noflush(struct page *page)
 	if (!can_set_direct_map())
 		return 0;
 
+	l_start = (unsigned long)page_address(page);
+	ret = split_linear_mapping(l_start, l_start + PAGE_SIZE);
+	if (WARN_ON_ONCE(ret))
+		return ret;
+
 	return apply_to_page_range(&init_mm,
-				   (unsigned long)page_address(page),
-				   PAGE_SIZE, change_page_range, &data);
+				   l_start, PAGE_SIZE, change_page_range,
+				   &data);
 }
 
 static int __set_memory_enc_dec(unsigned long addr,
-- 
2.47.1



From yang at os.amperecomputing.com  Tue Mar  4 14:19:30 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:30 -0800
Subject: [v3 PATCH 5/6] arm64: mm: support split CONT mappings
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-6-yang@os.amperecomputing.com>

Add split CONT mappings support in order to support CONT mappings for
direct map.  This should help reduce TLB pressure further.

When splitting PUD, all PMDs will have CONT bit set since the leaf PUD
must be naturally aligned.  When splitting PMD, all PTEs will have CONT
bit set since the leaf PMD must be naturally aligned too, but the PMDs
in the cont range of split PMD will have CONT bit cleared.  Splitting
CONT PTEs by clearing CONT bit for all PTEs in the range.

Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
 arch/arm64/include/asm/pgtable.h |  5 ++
 arch/arm64/mm/mmu.c              | 82 ++++++++++++++++++++++++++------
 arch/arm64/mm/pageattr.c         |  2 +
 3 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index ed2fc1dcf7ae..3c6ef47f5813 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -290,6 +290,11 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
 	return __pmd(pmd_val(pmd) | PMD_SECT_CONT);
 }
 
+static inline pmd_t pmd_mknoncont(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) & ~PMD_SECT_CONT);
+}
+
 static inline pte_t pte_mkdevmap(pte_t pte)
 {
 	return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index ad0f1cc55e3a..d4dfeabc80e9 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -167,19 +167,36 @@ static void init_clear_pgtable(void *table)
 	dsb(ishst);
 }
 
+static void split_cont_pte(pte_t *ptep)
+{
+	pte_t *_ptep = PTR_ALIGN_DOWN(ptep, sizeof(*ptep) * CONT_PTES);
+	pte_t _pte;
+	for (int i = 0; i < CONT_PTES; i++, _ptep++) {
+		_pte = READ_ONCE(*_ptep);
+		_pte = pte_mknoncont(_pte);
+		__set_pte_nosync(_ptep, _pte);
+	}
+
+	dsb(ishst);
+	isb();
+}
+
 static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
-		     phys_addr_t (*pgtable_alloc)(int))
+		     phys_addr_t (*pgtable_alloc)(int), int flags)
 {
 	unsigned long pfn;
 	pgprot_t prot;
 	phys_addr_t pte_phys;
 	pte_t *ptep;
+	bool cont;
+	int i;
 
 	if (!pmd_leaf(pmdval))
 		return 0;
 
 	pfn = pmd_pfn(pmdval);
 	prot = pmd_pgprot(pmdval);
+	cont = pgprot_val(prot) & PTE_CONT;
 
 	pte_phys = pgtable_alloc(PAGE_SHIFT);
 	if (!pte_phys)
@@ -188,11 +205,27 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
 	ptep = (pte_t *)phys_to_virt(pte_phys);
 	init_clear_pgtable(ptep);
 	prot = __pgprot(pgprot_val(prot) | PTE_TYPE_PAGE);
-	for (int i = 0; i < PTRS_PER_PTE; i++, ptep++)
+
+	/* It must be naturally aligned if PMD is leaf */
+	if ((flags & NO_CONT_MAPPINGS) == 0)
+		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+
+	for (i = 0; i < PTRS_PER_PTE; i++, ptep++)
 		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));
 
 	dsb(ishst);
 
+	/* Clear CONT bit for the PMDs in the range */
+	if (cont) {
+		pmd_t *_pmdp, _pmd;
+		_pmdp = PTR_ALIGN_DOWN(pmdp, sizeof(*pmdp) * CONT_PMDS);
+		for (i = 0; i < CONT_PMDS; i++, _pmdp++) {
+			_pmd = READ_ONCE(*_pmdp);
+			_pmd = pmd_mknoncont(_pmd);
+			set_pmd(_pmdp, _pmd);
+		}
+	}
+
 	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(pte_phys),
 		__pgprot(PMD_TYPE_TABLE)));
 
@@ -200,7 +233,7 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
 }
 
 static int split_pud(pud_t *pudp, pud_t pudval,
-		     phys_addr_t (*pgtable_alloc)(int))
+		     phys_addr_t (*pgtable_alloc)(int), int flags)
 {
 	unsigned long pfn;
 	pgprot_t prot;
@@ -221,6 +254,11 @@ static int split_pud(pud_t *pudp, pud_t pudval,
 
 	pmdp = (pmd_t *)phys_to_virt(pmd_phys);
 	init_clear_pgtable(pmdp);
+
+	/* It must be naturally aligned if PUD is leaf */
+	if ((flags & NO_CONT_MAPPINGS) == 0)
+		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+
 	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
 		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
 		pfn += step;
@@ -235,11 +273,18 @@ static int split_pud(pud_t *pudp, pud_t pudval,
 }
 
 static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
-		     phys_addr_t phys, pgprot_t prot)
+		     phys_addr_t phys, pgprot_t prot, int flags)
 {
 	do {
 		pte_t old_pte = __ptep_get(ptep);
 
+		if (flags & SPLIT_MAPPINGS) {
+			if (pte_cont(old_pte))
+				split_cont_pte(ptep);
+
+			continue;
+		}
+
 		/*
 		 * Required barriers to make this visible to the table walker
 		 * are deferred to the end of alloc_init_cont_pte().
@@ -266,8 +311,16 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 	unsigned long next;
 	pmd_t pmd = READ_ONCE(*pmdp);
 	pte_t *ptep;
+	bool split = flags & SPLIT_MAPPINGS;
 
 	BUG_ON(pmd_sect(pmd));
+
+	if (split) {
+		BUG_ON(pmd_none(pmd));
+		ptep = pte_offset_kernel(pmdp, addr);
+		goto split_pgtable;
+	}
+
 	if (pmd_none(pmd)) {
 		pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
 		phys_addr_t pte_phys;
@@ -287,6 +340,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 		ptep = pte_set_fixmap_offset(pmdp, addr);
 	}
 
+split_pgtable:
 	do {
 		pgprot_t __prot = prot;
 
@@ -297,7 +351,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 		    (flags & NO_CONT_MAPPINGS) == 0)
 			__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
 
-		init_pte(ptep, addr, next, phys, __prot);
+		init_pte(ptep, addr, next, phys, __prot, flags);
 
 		ptep += pte_index(next) - pte_index(addr);
 		phys += next - addr;
@@ -308,7 +362,8 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 	 * ensure that all previous pgtable writes are visible to the table
 	 * walker.
 	 */
-	pte_clear_fixmap();
+	if (!split)
+		pte_clear_fixmap();
 
 	return 0;
 }
@@ -327,7 +382,12 @@ static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
 		next = pmd_addr_end(addr, end);
 
 		if (split) {
-			ret = split_pmd(pmdp, old_pmd, pgtable_alloc);
+			ret = split_pmd(pmdp, old_pmd, pgtable_alloc, flags);
+			if (ret)
+				break;
+
+			ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot,
+						  pgtable_alloc, flags);
 			if (ret)
 				break;
 
@@ -469,7 +529,7 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 		next = pud_addr_end(addr, end);
 
 		if (split) {
-			ret = split_pud(pudp, old_pud, pgtable_alloc);
+			ret = split_pud(pudp, old_pud, pgtable_alloc, flags);
 			if (ret)
 				break;
 
@@ -846,9 +906,6 @@ static void __init map_mem(pgd_t *pgdp)
 	if (force_pte_mapping())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
-	if (rodata_full)
-		flags |= NO_CONT_MAPPINGS;
-
 	/*
 	 * Take care not to create a writable alias for the
 	 * read-only text and rodata sections of the kernel image.
@@ -1547,9 +1604,6 @@ int arch_add_memory(int nid, u64 start, u64 size,
 	if (force_pte_mapping())
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
-	if (rodata_full)
-		flags |= NO_CONT_MAPPINGS;
-
 	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
 			     size, params->pgprot, __pgd_pgtable_alloc,
 			     flags);
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 5d42d87ea7e1..25c068712cb5 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -43,6 +43,8 @@ static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
 	struct page_change_data *cdata = data;
 	pte_t pte = __ptep_get(ptep);
 
+	BUG_ON(pte_cont(pte));
+
 	pte = clear_pte_bit(pte, cdata->clear_mask);
 	pte = set_pte_bit(pte, cdata->set_mask);
 
-- 
2.47.1



From yang at os.amperecomputing.com  Tue Mar  4 14:19:31 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Tue,  4 Mar 2025 14:19:31 -0800
Subject: [v3 PATCH 6/6] arm64: mm: split linear mapping if BBML2 is not supported on secondary CPUs
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <20250304222018.615808-7-yang@os.amperecomputing.com>

The kernel linear mapping is painted in very early stage of system boot.
The cpufeature has not been finalized yet at this point.  So the linear
mapping is determined by the capability of boot CPU.  If the boot CPU
supports BBML2, large block mapping will be used for linear mapping.

But the secondary CPUs may not support BBML2, so repaint the linear mapping
if large block mapping is used and the secondary CPUs don't support BBML2
once cpufeature is finalized on all CPUs.

If the boot CPU doesn't support BBML2 or the secondary CPUs have the
same BBML2 capability with the boot CPU, repainting the linear mapping
is not needed.

Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
 arch/arm64/include/asm/mmu.h   |  3 +++
 arch/arm64/kernel/cpufeature.c | 24 +++++++++++++++++++
 arch/arm64/mm/mmu.c            | 43 +++++++++++++++++++++++++++++++++-
 3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index d658a33df266..181649424317 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -56,6 +56,8 @@ typedef struct {
  */
 #define ASID(mm)	(atomic64_read(&(mm)->context.id) & 0xffff)
 
+extern bool block_mapping;
+
 static inline bool arm64_kernel_unmapped_at_el0(void)
 {
 	return alternative_has_cap_unlikely(ARM64_UNMAP_KERNEL_AT_EL0);
@@ -72,6 +74,7 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
 extern void mark_linear_text_alias_ro(void);
 extern int split_linear_mapping(unsigned long start, unsigned long end);
+extern int __repaint_linear_mappings(void *__unused);
 
 /*
  * This check is triggered during the early boot before the cpufeature
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d39637d5aeab..ffb797bc2dba 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -85,6 +85,7 @@
 #include <asm/insn.h>
 #include <asm/kvm_host.h>
 #include <asm/mmu_context.h>
+#include <asm/mmu.h>
 #include <asm/mte.h>
 #include <asm/processor.h>
 #include <asm/smp.h>
@@ -1972,6 +1973,28 @@ static int __init __kpti_install_ng_mappings(void *__unused)
 	return 0;
 }
 
+static void __init repaint_linear_mappings(void)
+{
+	struct cpumask bbml2_cpus;
+
+	if (!block_mapping)
+		return;
+
+	if (!rodata_full)
+		return;
+
+	if (system_supports_bbml2_noabort())
+		return;
+
+	/*
+	 * Need to guarantee repainting linear mapping is called on the
+	 * boot CPU since boot CPU supports BBML2.
+	 */
+	cpumask_clear(&bbml2_cpus);
+	cpumask_set_cpu(smp_processor_id(), &bbml2_cpus);
+	stop_machine(__repaint_linear_mappings, NULL, &bbml2_cpus);
+}
+
 static void __init kpti_install_ng_mappings(void)
 {
 	/* Check whether KPTI is going to be used */
@@ -3814,6 +3837,7 @@ void __init setup_system_features(void)
 {
 	setup_system_capabilities();
 
+	repaint_linear_mappings();
 	kpti_install_ng_mappings();
 
 	sve_setup();
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index d4dfeabc80e9..015b30567ad1 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -209,6 +209,8 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
 	/* It must be naturally aligned if PMD is leaf */
 	if ((flags & NO_CONT_MAPPINGS) == 0)
 		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+	else
+		prot = __pgprot(pgprot_val(prot) & ~PTE_CONT);
 
 	for (i = 0; i < PTRS_PER_PTE; i++, ptep++)
 		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));
@@ -258,6 +260,8 @@ static int split_pud(pud_t *pudp, pud_t pudval,
 	/* It must be naturally aligned if PUD is leaf */
 	if ((flags & NO_CONT_MAPPINGS) == 0)
 		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+	else
+		prot = __pgprot(pgprot_val(prot) & ~PTE_CONT);
 
 	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
 		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
@@ -806,6 +810,37 @@ void __init mark_linear_text_alias_ro(void)
 			    PAGE_KERNEL_RO);
 }
 
+int __init __repaint_linear_mappings(void *__unused)
+{
+	phys_addr_t kernel_start = __pa_symbol(_stext);
+	phys_addr_t kernel_end = __pa_symbol(__init_begin);
+	phys_addr_t start, end;
+	unsigned long vstart, vend;
+	u64 i;
+	int ret;
+
+	memblock_mark_nomap(kernel_start, kernel_end - kernel_start);
+	/* Split the whole linear mapping */
+	for_each_mem_range(i, &start, &end) {
+		if (start >= end)
+			return -EINVAL;
+
+		vstart = __phys_to_virt(start);
+		vend = __phys_to_virt(end);
+		ret = __create_pgd_mapping_locked(init_mm.pgd, start,
+					vstart, (end - start), __pgprot(0),
+					__pgd_pgtable_alloc,
+					NO_CONT_MAPPINGS | SPLIT_MAPPINGS);
+		if (ret)
+			panic("Failed to split linear mappings\n");
+
+		flush_tlb_kernel_range(vstart, vend);
+	}
+	memblock_clear_nomap(kernel_start, kernel_end - kernel_start);
+
+	return 0;
+}
+
 #ifdef CONFIG_KFENCE
 
 bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
@@ -860,6 +895,8 @@ static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) {
 
 #endif /* CONFIG_KFENCE */
 
+bool block_mapping;
+
 static inline bool force_pte_mapping(void)
 {
 	/*
@@ -888,6 +925,8 @@ static void __init map_mem(pgd_t *pgdp)
 	int flags = NO_EXEC_MAPPINGS;
 	u64 i;
 
+	block_mapping = true;
+
 	/*
 	 * Setting hierarchical PXNTable attributes on table entries covering
 	 * the linear region is only possible if it is guaranteed that no table
@@ -903,8 +942,10 @@ static void __init map_mem(pgd_t *pgdp)
 
 	early_kfence_pool = arm64_kfence_alloc_pool();
 
-	if (force_pte_mapping())
+	if (force_pte_mapping()) {
+		block_mapping = false;
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
+	}
 
 	/*
 	 * Take care not to create a writable alias for the
-- 
2.47.1



From vladimir.oltean at nxp.com  Tue Mar  4 14:21:22 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 5 Mar 2025 00:21:22 +0200
Subject: [PATCH iwl-next v7 1/9] net: ethtool: mm: extract stmmac
 verification logic into common library
In-Reply-To: <20250303102658.3580232-2-faizal.abdul.rahim@linux.intel.com>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
 <20250303102658.3580232-2-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250304222122.67bjes6jzbiveqfk@skbuf>

On Mon, Mar 03, 2025 at 05:26:50AM -0500, Faizal Rahim wrote:
> +/**
> + * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification
> + *				      of link state changes
> + * @mmsv: MAC Merge Software Verification state
> + * @up: True if device carrier is up and able to pass verification packets
> + *
> + * Calling context is expected to be from a task, interrupts enabled.
> + */
> +void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
> +{
> +	unsigned long flags;
> +
> +	ethtool_mmsv_stop(mmsv);
> +
> +	spin_lock_irqsave(&mmsv->lock, flags);
> +
> +	if (up && mmsv->pmac_enabled) {
> +		/* VERIFY process requires pMAC enabled when NIC comes up */
> +		ethtool_mmsv_configure_pmac(mmsv, true);
> +
> +		/* New link => maybe new partner => new verification process */
> +		ethtool_mmsv_apply(mmsv);
> +	} else {
> +		/* Reset the reported verification state while the link is down */
> +		if (mmsv->verify_enabled)
> +			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;

As requested in v5, please make this a separate patch. It represents a
functional change for stmmac, and I don't want somebody who bisects it
to find a code movement commit and search for a needle through a haystack.

> +
> +		/* No link or pMAC not enabled */
> +		ethtool_mmsv_configure_pmac(mmsv, false);
> +		ethtool_mmsv_configure_tx(mmsv, false);
> +	}
> +
> +	spin_unlock_irqrestore(&mmsv->lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index 918a32f8fda8..25533d6a3175 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -1210,37 +1210,17 @@ static int stmmac_get_mm(struct net_device *ndev,
>  			 struct ethtool_mm_state *state)
>  {
>  	struct stmmac_priv *priv = netdev_priv(ndev);
> -	unsigned long flags;
>  	u32 frag_size;
>  
>  	if (!stmmac_fpe_supported(priv))
>  		return -EOPNOTSUPP;
>  
> -	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
> +	ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
>  
> -	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
> -	state->verify_enabled = priv->fpe_cfg.verify_enabled;
> -	state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
> -	state->verify_time = priv->fpe_cfg.verify_time;
> -	state->tx_enabled = priv->fpe_cfg.tx_enabled;
> -	state->verify_status = priv->fpe_cfg.status;
>  	state->rx_min_frag_size = ETH_ZLEN;
> -
> -	/* FPE active if common tx_enabled and
> -	 * (verification success or disabled(forced))
> -	 */
> -	if (state->tx_enabled &&
> -	    (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
> -	     state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
> -		state->tx_active = true;
> -	else
> -		state->tx_active = false;
> -
>  	frag_size = stmmac_fpe_get_add_frag_size(priv);
>  	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
>  
> -	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
> -
>  	return 0;
>  }
>  
> @@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
>  			 struct netlink_ext_ack *extack)
>  {
>  	struct stmmac_priv *priv = netdev_priv(ndev);
> -	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
> -	unsigned long flags;
>  	u32 frag_size;
>  	int err;
>  
> @@ -1258,23 +1236,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
>  	if (err)
>  		return err;
>  
> -	/* Wait for the verification that's currently in progress to finish */
> -	timer_shutdown_sync(&fpe_cfg->verify_timer);
> -
> -	spin_lock_irqsave(&fpe_cfg->lock, flags);
> -
> -	fpe_cfg->verify_enabled = cfg->verify_enabled;
> -	fpe_cfg->pmac_enabled = cfg->pmac_enabled;
> -	fpe_cfg->verify_time = cfg->verify_time;
> -	fpe_cfg->tx_enabled = cfg->tx_enabled;
> -
> -	if (!cfg->verify_enabled)
> -		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
> -
>  	stmmac_fpe_set_add_frag_size(priv, frag_size);

This is another change in behavior which unfortunately I am noticing
only now: stmmac_fpe_set_add_frag_size() and stmmac_fpe_get_add_frag_size()
used to execute under &fpe_cfg->lock, and now run outside of what
eventually became the mmsv->lock (but still under rtnl_lock() protection).

I am not seeing a need for the additional fragment size to be covered
by the mmsv->lock (the mmsv has no business with this parameter), and
rtnl_lock() should be sufficient to serialize stmmac_get_mm() with
stmmac_set_mm(). So I guess I am ok with the code structure, but again,
please move stmmac_fpe_set_add_frag_size() and stmmac_fpe_get_add_frag_size()
outside of the spin_lock_irqsave(&fpe_cfg->lock) context (essentially to
their current positions) as a preliminary separate patch. Again, it is
best for a "git blame" caused by a behavior change here to not point to
a commit that moves code from one file to another.

> -	stmmac_fpe_apply(priv);
> -
> -	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
> +	ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
>  
>  	return 0;
>  }


From andre.przywara at arm.com  Tue Mar  4 14:22:55 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:55 +0000
Subject: [PATCH v2 01/15] dt-bindings: mmc: sunxi: Simplify compatible string listing
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-2-andre.przywara@arm.com>

New Allwinner SoCs only occasionally update their MMC IP, leading to many
pairs of compatible strings, though there are sometimes a number of them
being compatible with one particular SoC.

Collate the compatible string listing in the binding, to group those
being compatible together. This makes the list more readable, and allows
for easier addition of new SoC's MMC devices.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 36 ++++++++-----------
 1 file changed, 14 insertions(+), 22 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 0ccd632d56200..8e4c77b7e4ab9 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -30,38 +30,30 @@ properties:
       - const: allwinner,sun50i-a100-emmc
       - const: allwinner,sun50i-a100-mmc
       - items:
-          - const: allwinner,sun8i-a83t-mmc
+          - enum:
+              - allwinner,sun8i-a83t-mmc
+              - allwinner,suniv-f1c100s-mmc
           - const: allwinner,sun7i-a20-mmc
       - items:
-          - const: allwinner,sun8i-r40-emmc
+          - enum:
+              - allwinner,sun8i-r40-emmc
+              - allwinner,sun50i-h5-emmc
+              - allwinner,sun50i-h6-emmc
           - const: allwinner,sun50i-a64-emmc
       - items:
-          - const: allwinner,sun8i-r40-mmc
+          - enum:
+              - allwinner,sun8i-r40-mmc
+              - allwinner,sun50i-h5-mmc
+              - allwinner,sun50i-h6-mmc
           - const: allwinner,sun50i-a64-mmc
       - items:
-          - const: allwinner,sun50i-h5-emmc
-          - const: allwinner,sun50i-a64-emmc
-      - items:
-          - const: allwinner,sun50i-h5-mmc
-          - const: allwinner,sun50i-a64-mmc
-      - items:
-          - const: allwinner,sun50i-h6-emmc
-          - const: allwinner,sun50i-a64-emmc
-      - items:
-          - const: allwinner,sun50i-h6-mmc
-          - const: allwinner,sun50i-a64-mmc
-      - items:
-          - const: allwinner,sun20i-d1-emmc
-          - const: allwinner,sun50i-a100-emmc
-      - items:
-          - const: allwinner,sun50i-h616-emmc
+          - enum:
+              - allwinner,sun20i-d1-emmc
+              - allwinner,sun50i-h616-emmc
           - const: allwinner,sun50i-a100-emmc
       - items:
           - const: allwinner,sun50i-h616-mmc
           - const: allwinner,sun50i-a100-mmc
-      - items:
-          - const: allwinner,suniv-f1c100s-mmc
-          - const: allwinner,sun7i-a20-mmc
 
   reg:
     maxItems: 1
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:22:54 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:54 +0000
Subject: [PATCH v2 00/15] arm64: dts: allwinner: Add basic Allwinner A523 support
Message-ID: <20250304222309.29385-1-andre.przywara@arm.com>

Hi,

this in an update to the series introducing the basic DT support for the
Allwinner A523 SoC. It now comes with DTs for three boards, using
slightly different packages of that SoC.[1]
Functionality-wise it relies on the pinctrl[2] and clock[3] support
series, though there are no direct code dependency series between the
series. Three binding patches from there are required to pass dtbs_check,
git put their patch IDs in the footer below.
Compared to v1 this drops the patches that have already been merged
(I2C, USB, RTC), changes the proposed NMI controller binding, extends 
the SoC .dtsi to include more device instances, also the secondary cores,
and adds DTs for two new boards. On top of this I added v2 of the DT patch
for an H616 board, since it shares the newly introduced YuzukiHD vendor
name patch. Also it adds the tags from the diligent reviewers, many thanks
for that! More detailed changelog below.

The first patches add DT binding documentation for the most basic
peripherals, most of them actually being already supported, courtesy of
identical IP being used. This includes MMC and USB 2.0, so with the above
mentioned clock and pinctrl support this gives an already somewhat usable
mainline support for this new SoC family.
The watchdog is not completely compatible, but is an easy addition, so
this bit is included in here as well, the same is true for the NMI
controller, required for delivering PMIC interrupts.

The A523 features 8 Arm Cortex-A55 cores, organised in two clusters,
clocked separately, with different OPP limits, in some kind of
little/LITTLE configuration. The GPU is a Arm Mali G57 MC01, and the chip
also features a single PCIe 2.1 lane, sharing a PHY with some USB 3.1
controller - which means only one of the two can be used.
The rest of the SoC is the usual soup of multimedia SoC IP, with eDP
support and two Gigabit Ethernet MACs among the highlights.

The main feature is patch 08/15, which adds the SoC .dtsi. This for now
is limited to the parts that are supported and could be tested. Compared
to v1 we now have some basic TF-A support, so the PSCI nodes are in now.

The final patches add basic support for the Avaota-A1 router board, the
X96QPro+ TV box, and the Radxa A5E development board.

The mainline firmware side in general is coming together now: we have
basic U-Boot support working (including MMC and USB), most importantly
with proper DRAM support, so no more binary blobs, and some basic TF-A
support.

Please have a look at those DT bits here, ideally compare them to the
available user manual, and test them if you have access to hardware.

Based on v6.14-rc1.
I pushed a branch with all the three series combined here:
https://github.com/apritzel/linux/commits/a523-v2/

Cheers,
Andre

Changelog v1 .. v2:
- drop USB, I2C, RTC binding patches: already merged
- add tags from reviewers (with thanks!)
- drop unrelated deprecation comment from MMC binding patch
- drop fallback compatible for NMI controller, stands on its own now
- adjust PHY binding to merged A100 binding (dropping tag)
- .dtsi: add secondary cores
- .dtsi: enable PSCI
- .dtsi: move 32K oscillator to board .dts files
- .dtsi: adjust CCU source clocks
- .dtsi: add MMC1 node (typcially for SDIO WiFi)
- .dtsi: add remaining UARTs
- .dtsi: add remaing I2C devices
- add two new board .dts files
- add DT bindings for those two new board names
- avaota.dts: drop reserved memory from (TF-A now in SRAM)
- avaota.dts: drop SD card dummy supply node
- avaota.dts: add eMMC node (shipped on most boards)
- avaota.dts: fix OTG mode, explain situation
- add Chameleon .dts file (depends on YuzukiHD vendor name patch)

[1] https://linux-sunxi.org/A523#Family_of_sun55iw3
[2] https://lore.kernel.org/linux-sunxi/20250227231447.20161-1-andre.przywara at arm.com/T/#u
[3] https://lore.kernel.org/linux-sunxi/20250304012805.28594-1-andre.przywara at arm.com/T/#u

Andre Przywara (15):
  dt-bindings: mmc: sunxi: Simplify compatible string listing
  dt-bindings: mmc: sunxi: add compatible strings for Allwinner A523
  dt-bindings: watchdog: sunxi: add Allwinner A523 compatible string
  watchdog: sunxi_wdt: Add support for Allwinner A523
  dt-bindings: irq: sun7i-nmi: document the Allwinner A523 NMI
    controller
  irqchip/sunxi-nmi: Support Allwinner A523 NMI controller
  dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
  arm64: dts: allwinner: Add Allwinner A523 .dtsi file
  dt-bindings: vendor-prefixes: Add YuzukiHD name
  dt-bindings: arm: sunxi: Add new board names for A523 generation
  arm64: dts: allwinner: a523: add Avaota-A1 router support
  arm64: dts: allwinner: a523: add X96Q-Pro+ support
  arm64: dts: allwinner: a523: add Radxa A5E support
  dt-bindings: arm: sunxi: Add YuzukiHD Chameleon board name
  arm64: dts: allwinner: h616: add YuzukiHD Chameleon support

 .../devicetree/bindings/arm/sunxi.yaml        |  20 +
 .../allwinner,sun7i-a20-sc-nmi.yaml           |   1 +
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml |  38 +-
 .../phy/allwinner,sun50i-a64-usb-phy.yaml     |   4 +-
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 .../watchdog/allwinner,sun4i-a10-wdt.yaml     |   2 +
 arch/arm64/boot/dts/allwinner/Makefile        |   4 +
 .../sun50i-h618-yuzukihd-chameleon.dts        | 222 +++++++
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
 .../dts/allwinner/sun55i-a527-radxa-a5e.dts   | 299 +++++++++
 .../dts/allwinner/sun55i-h728-x96qpro+.dts    | 287 +++++++++
 .../dts/allwinner/sun55i-t527-avaota-a1.dts   | 308 +++++++++
 drivers/irqchip/irq-sunxi-nmi.c               |  50 +-
 drivers/watchdog/sunxi_wdt.c                  |  11 +
 14 files changed, 1807 insertions(+), 39 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts


base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
prerequisite-patch-id: 5b8a883819d2f3dfc975735a855291cb8b02dd39
prerequisite-patch-id: ff4d42c2dcb0c3b4be45a4b0b8e22027207979ee
prerequisite-patch-id: 4596fa402b501a9406821a9535f8329d30bf1ca4
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:22:56 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:56 +0000
Subject: [PATCH v2 02/15] dt-bindings: mmc: sunxi: add compatible strings for Allwinner A523
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-3-andre.przywara@arm.com>

The Allwinner A523 uses the same MMC IP as the D1.

Introduce the new specific compatible strings, and use them with
fallbacks to the D1 strings.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml      | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 8e4c77b7e4ab9..9f3b1edacaa02 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -50,10 +50,14 @@ properties:
           - enum:
               - allwinner,sun20i-d1-emmc
               - allwinner,sun50i-h616-emmc
+              - allwinner,sun55i-a523-emmc
           - const: allwinner,sun50i-a100-emmc
       - items:
           - const: allwinner,sun50i-h616-mmc
           - const: allwinner,sun50i-a100-mmc
+      - items:
+          - const: allwinner,sun55i-a523-mmc
+          - const: allwinner,sun20i-d1-mmc
 
   reg:
     maxItems: 1
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:22:58 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:58 +0000
Subject: [PATCH v2 04/15] watchdog: sunxi_wdt: Add support for Allwinner A523
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-5-andre.przywara@arm.com>

The Allwinner A523 SoC comes with a watchdog very similar to the ones in
the previous Allwinner SoCs, but oddly enough moves the first half of its
registers up by one word. Since we have different offsets for these
registers across the other SoCs as well, this can simply be modelled by
just stating the new offsets in our per-SoC struct.
The rest of the IP is the same as in the D1, although the A523 moves its
watchdog to a separate MMIO frame, so it's not embedded in the timer
anymore. The driver can be ignorant of this, because the DT will take
care of this.

Add a new struct for the A523, specifying the SoC-specific details, and
tie the new DT compatible string to it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/watchdog/sunxi_wdt.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
index b85354a995826..b6c761acc3de6 100644
--- a/drivers/watchdog/sunxi_wdt.c
+++ b/drivers/watchdog/sunxi_wdt.c
@@ -236,10 +236,21 @@ static const struct sunxi_wdt_reg sun20i_wdt_reg = {
 	.wdt_key_val = 0x16aa0000,
 };
 
+static const struct sunxi_wdt_reg sun55i_wdt_reg = {
+	.wdt_ctrl = 0x0c,
+	.wdt_cfg = 0x10,
+	.wdt_mode = 0x14,
+	.wdt_timeout_shift = 4,
+	.wdt_reset_mask = 0x03,
+	.wdt_reset_val = 0x01,
+	.wdt_key_val = 0x16aa0000,
+};
+
 static const struct of_device_id sunxi_wdt_dt_ids[] = {
 	{ .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg },
 	{ .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg },
 	{ .compatible = "allwinner,sun20i-d1-wdt", .data = &sun20i_wdt_reg },
+	{ .compatible = "allwinner,sun55i-a523-wdt", .data = &sun55i_wdt_reg },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:22:57 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:57 +0000
Subject: [PATCH v2 03/15] dt-bindings: watchdog: sunxi: add Allwinner A523 compatible string
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-4-andre.przywara@arm.com>

The Allwinner A523 SoC features a watchdog similar to the one used in
previous SoCs, but moves some registers around (by just one word), making
it incompatible to existing IPs.

Add the new name to the list of compatible string, and also to the list
of IP requiring two clock inputs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml   | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index 64c8f73938099..b35ac03d51727 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -32,6 +32,7 @@ properties:
       - items:
           - const: allwinner,sun20i-d1-wdt-reset
           - const: allwinner,sun20i-d1-wdt
+      - const: allwinner,sun55i-a523-wdt
 
   reg:
     maxItems: 1
@@ -60,6 +61,7 @@ if:
           - allwinner,sun20i-d1-wdt-reset
           - allwinner,sun50i-r329-wdt
           - allwinner,sun50i-r329-wdt-reset
+          - allwinner,sun55i-a523-wdt
 
 then:
   properties:
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:22:59 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:22:59 +0000
Subject: [PATCH v2 05/15] dt-bindings: irq: sun7i-nmi: document the Allwinner A523 NMI controller
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-6-andre.przywara@arm.com>

The Allwinner A523 SoC contains an NMI controller very close to the one
used in the recent Allwinner SoCs, but it adds another bit that needs to
be toggled to actually deliver the IRQs. Sigh.

Add the A523 specific name to the list of allowed compatible strings.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
index f49b43f45f3d9..06e3621a8c06c 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
@@ -26,6 +26,7 @@ properties:
         deprecated: true
       - const: allwinner,sun7i-a20-sc-nmi
       - const: allwinner,sun9i-a80-nmi
+      - const: allwinner,sun55i-a523-nmi
       - items:
           - enum:
               - allwinner,sun8i-v3s-nmi
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:00 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:00 +0000
Subject: [PATCH v2 06/15] irqchip/sunxi-nmi: Support Allwinner A523 NMI controller
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-7-andre.przywara@arm.com>

The NMI controller in the Allwinner A523 is almost compatible to the
previous versions of this IP, but requires the extra bit 31 to be set in
the enable register to actually report the NMI.

Add a mask to allow such an enable bit to be specified, and add this to
the per-SoC data structure. As this struct was just for different register
offsets so far, it was consequently named "reg_offs", which is now no
longer applicable, so rename this to the more generic "data" on the way.

Also add the respective Allwinner A523 compatible string, and set bit 31
in its enable mask, to add support for this SoC.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/irqchip/irq-sunxi-nmi.c | 50 ++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 0b43121520243..9380c3cafeeb5 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -48,30 +48,38 @@ enum {
 	SUNXI_SRC_TYPE_EDGE_RISING,
 };
 
-struct sunxi_sc_nmi_reg_offs {
+struct sunxi_sc_nmi_data {
 	u32 ctrl;
 	u32 pend;
 	u32 enable;
+	u32 enable_val;
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = {
+static const struct sunxi_sc_nmi_data sun6i_data __initconst = {
 	.ctrl	= SUN6I_NMI_CTRL,
 	.pend	= SUN6I_NMI_PENDING,
 	.enable	= SUN6I_NMI_ENABLE,
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun7i_reg_offs __initconst = {
+static const struct sunxi_sc_nmi_data sun7i_data __initconst = {
 	.ctrl	= SUN7I_NMI_CTRL,
 	.pend	= SUN7I_NMI_PENDING,
 	.enable	= SUN7I_NMI_ENABLE,
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun9i_reg_offs __initconst = {
+static const struct sunxi_sc_nmi_data sun9i_data __initconst = {
 	.ctrl	= SUN9I_NMI_CTRL,
 	.pend	= SUN9I_NMI_PENDING,
 	.enable	= SUN9I_NMI_ENABLE,
 };
 
+static const struct sunxi_sc_nmi_data sun55i_a523_data __initconst = {
+	.ctrl	= SUN9I_NMI_CTRL,
+	.pend	= SUN9I_NMI_PENDING,
+	.enable	= SUN9I_NMI_ENABLE,
+	.enable_val = BIT(31),
+};
+
 static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
 				      u32 val)
 {
@@ -143,7 +151,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
 }
 
 static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
-					const struct sunxi_sc_nmi_reg_offs *reg_offs)
+					const struct sunxi_sc_nmi_data *data)
 {
 	struct irq_domain *domain;
 	struct irq_chip_generic *gc;
@@ -186,27 +194,28 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
 	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit;
 	gc->chip_types[0].chip.irq_eoi		= irq_gc_ack_set_bit;
 	gc->chip_types[0].chip.irq_set_type	= sunxi_sc_nmi_set_type;
-	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
+	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED |
+						  IRQCHIP_EOI_IF_HANDLED |
 						  IRQCHIP_SKIP_SET_WAKE;
-	gc->chip_types[0].regs.ack		= reg_offs->pend;
-	gc->chip_types[0].regs.mask		= reg_offs->enable;
-	gc->chip_types[0].regs.type		= reg_offs->ctrl;
+	gc->chip_types[0].regs.ack		= data->pend;
+	gc->chip_types[0].regs.mask		= data->enable;
+	gc->chip_types[0].regs.type		= data->ctrl;
 
 	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;
 	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_set_bit;
 	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
 	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit;
 	gc->chip_types[1].chip.irq_set_type	= sunxi_sc_nmi_set_type;
-	gc->chip_types[1].regs.ack		= reg_offs->pend;
-	gc->chip_types[1].regs.mask		= reg_offs->enable;
-	gc->chip_types[1].regs.type		= reg_offs->ctrl;
+	gc->chip_types[1].regs.ack		= data->pend;
+	gc->chip_types[1].regs.mask		= data->enable;
+	gc->chip_types[1].regs.type		= data->ctrl;
 	gc->chip_types[1].handler		= handle_edge_irq;
 
 	/* Disable any active interrupts */
-	sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
+	sunxi_sc_nmi_write(gc, data->enable, data->enable_val);
 
 	/* Clear any pending NMI interrupts */
-	sunxi_sc_nmi_write(gc, reg_offs->pend, SUNXI_NMI_IRQ_BIT);
+	sunxi_sc_nmi_write(gc, data->pend, SUNXI_NMI_IRQ_BIT);
 
 	irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain);
 
@@ -221,20 +230,27 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
 static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
 					struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun6i_data);
 }
 IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init);
 
 static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
 					struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun7i_data);
 }
 IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
 
 static int __init sun9i_nmi_irq_init(struct device_node *node,
 				     struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun9i_data);
 }
 IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);
+
+static int __init sun55i_nmi_irq_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	return sunxi_sc_nmi_irq_init(node, &sun55i_a523_data);
+}
+IRQCHIP_DECLARE(sun55i_nmi, "allwinner,sun55i-a523-nmi", sun55i_nmi_irq_init);
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:01 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:01 +0000
Subject: [PATCH v2 07/15] dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-8-andre.przywara@arm.com>

The Allwinner A523 SoC contains a USB-2.0 PHY fully compatible to the
one used in the D1/T113s SoCs. This PHY controls the two USB-2.0 ports,
there is a separate and quite different PHY for the USB-3.0 port.

Add the new compatible string, with a fallback to the D1 version.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
index 21209126ed008..580c3296a18d7 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
@@ -20,7 +20,9 @@ properties:
           - allwinner,sun20i-d1-usb-phy
           - allwinner,sun50i-a64-usb-phy
       - items:
-          - const: allwinner,sun50i-a100-usb-phy
+          - enum:
+              - allwinner,sun50i-a100-usb-phy
+              - allwinner,sun55i-a523-usb-phy
           - const: allwinner,sun20i-d1-usb-phy
 
   reg:
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:02 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:02 +0000
Subject: [PATCH v2 08/15] arm64: dts: allwinner: Add Allwinner A523 .dtsi file
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-9-andre.przywara@arm.com>

The Allwinner A523, and its siblings A527 and T527, which share the same
die, are a new family of SoCs introduced in 2023. They features eight
Arm Cortex-A55 cores, and, among the other usual peripherals, a PCIe and
USB 3.0 controller.

Add the basic SoC devicetree .dtsi for the chip, describing the
fundamental peripherals: the cores, GIC, timer, RTC, CCU and pinctrl.
Also some other peripherals are fully compatible with previous IP, so
add the USB and MMC nodes as well.
The other peripherals will be added in the future, once we understand
their compatibility and DT requirements.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
 1 file changed, 598 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
new file mode 100644
index 0000000000000..01e662bdf5521
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2023-2024 Arm Ltd.
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun55i-a523-ccu.h>
+#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x000>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 100 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x100>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 200 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x200>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 300 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x300>;
+			enable-method = "psci";
+		};
+
+		cpu4: cpu at 400 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x400>;
+			enable-method = "psci";
+		};
+
+		cpu5: cpu at 500 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x500>;
+			enable-method = "psci";
+		};
+
+		cpu6: cpu at 600 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x600>;
+			enable-method = "psci";
+		};
+
+		cpu7: cpu at 700 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x700>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	pmu {
+		compatible = "arm,cortex-a55-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		arm,no-tick-in-suspend;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x0 0x40000000>;
+
+		pio: pinctrl at 2000000 {
+			compatible = "allwinner,sun55i-a523-pinctrl";
+			reg = <0x2000000 0x800>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc CLK_OSC32K>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			mmc0_pins: mmc0-pins {
+				pins = "PF0" ,"PF1", "PF2", "PF3", "PF4", "PF5";
+				allwinner,pinmux = <2>;
+				function = "mmc0";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			/omit-if-no-ref/
+			mmc1_pins: mmc1-pins {
+				pins = "PG0" ,"PG1", "PG2", "PG3", "PG4", "PG5";
+				allwinner,pinmux = <2>;
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			mmc2_pins: mmc2-pins {
+				pins = "PC1" ,"PC5", "PC6", "PC8", "PC9",
+				       "PC10", "PC11", "PC13", "PC14", "PC15",
+				       "PC16";
+				allwinner,pinmux = <3>;
+				function = "mmc2";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			uart0_pb_pins: uart0-pb-pins {
+				pins = "PB9", "PB10";
+				allwinner,pinmux = <2>;
+				function = "uart0";
+			};
+		};
+
+		ccu: clock at 2001000 {
+			compatible = "allwinner,sun55i-a523-ccu";
+			reg = <0x02001000 0x1000>;
+			clocks = <&osc24M>, <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>, <&rtc CLK_OSC32K_FANOUT>;
+			clock-names = "hosc", "losc",
+				      "iosc", "losc-fanout";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mmc0: mmc at 4020000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04020000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc at 4021000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04021000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc1_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc2: mmc at 4022000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04022000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC2>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc2_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		wdt: watchdog at 2050000 {
+			compatible = "allwinner,sun55i-a523-wdt";
+			reg = <0x2050000 0x20>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+			clock-names = "hosc", "losc";
+			status = "okay";
+		};
+
+		uart0: serial at 2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500000 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial at 2500400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500400 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial at 2500800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500800 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial at 2500c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500c00 0x400>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			status = "disabled";
+		};
+
+		uart4: serial at 2501000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501000 0x400>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART4>;
+			resets = <&ccu RST_BUS_UART4>;
+			status = "disabled";
+		};
+
+		uart5: serial at 2501400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501400 0x400>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART5>;
+			resets = <&ccu RST_BUS_UART5>;
+			status = "disabled";
+		};
+
+		uart6: serial at 2501800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501800 0x400>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART6>;
+			resets = <&ccu RST_BUS_UART6>;
+			status = "disabled";
+		};
+
+		uart7: serial at 2501c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501c00 0x400>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART7>;
+			resets = <&ccu RST_BUS_UART7>;
+			status = "disabled";
+		};
+
+		i2c0: i2c at 2502000 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502000 0x400>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C0>;
+			resets = <&ccu RST_BUS_I2C0>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: i2c at 2502400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502400 0x400>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C1>;
+			resets = <&ccu RST_BUS_I2C1>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c2: i2c at 2502800 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502800 0x400>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C2>;
+			resets = <&ccu RST_BUS_I2C2>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c3: i2c at 2502c00 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502c00 0x400>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C3>;
+			resets = <&ccu RST_BUS_I2C3>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c4: i2c at 2503000 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2503000 0x400>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C4>;
+			resets = <&ccu RST_BUS_I2C4>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c5: i2c at 2503400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2503400 0x400>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C5>;
+			resets = <&ccu RST_BUS_I2C5>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		gic: interrupt-controller at 3400000 {
+			compatible = "arm,gic-v3";
+			#address-cells = <1>;
+			#interrupt-cells = <3>;
+			#size-cells = <1>;
+			ranges;
+			interrupt-controller;
+			reg = <0x3400000 0x10000>,
+			      <0x3460000 0x100000>;
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			dma-noncoherent;
+
+			its: msi-controller at 3440000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x3440000 0x20000>;
+				msi-controller;
+				#msi-cells = <1>;
+				dma-noncoherent;
+			};
+		};
+
+		usb_otg: usb at 4100000 {
+			compatible = "allwinner,sun55i-a523-musb",
+				     "allwinner,sun8i-a33-musb";
+			reg = <0x4100000 0x400>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "mc";
+			clocks = <&ccu CLK_BUS_OTG>;
+			resets = <&ccu RST_BUS_OTG>;
+			extcon = <&usbphy 0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		usbphy: phy at 4100400 {
+			compatible = "allwinner,sun55i-a523-usb-phy",
+				     "allwinner,sun20i-d1-usb-phy";
+			reg = <0x4100400 0x100>,
+			      <0x4101800 0x100>,
+			      <0x4200800 0x100>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1";
+			clocks = <&osc24M>,
+				 <&osc24M>;
+			clock-names = "usb0_phy",
+				      "usb1_phy";
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>;
+			reset-names = "usb0_reset",
+				      "usb1_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
+		ehci0: usb at 4101000 {
+			compatible = "allwinner,sun55i-a523-ehci",
+				     "generic-ehci";
+			reg = <0x4101000 0x100>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_BUS_EHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>,
+				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci0: usb at 4101400 {
+			compatible = "allwinner,sun55i-a523-ohci",
+				     "generic-ohci";
+			reg = <0x4101400 0x100>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci1: usb at 4200000 {
+			compatible = "allwinner,sun55i-a523-ehci",
+				     "generic-ehci";
+			reg = <0x4200000 0x100>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_BUS_EHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>,
+				 <&ccu RST_BUS_EHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb at 4200400 {
+			compatible = "allwinner,sun55i-a523-ohci",
+				     "generic-ohci";
+			reg = <0x4200400 0x100>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		r_ccu: clock-controller at 7010000 {
+			compatible = "allwinner,sun55i-a523-r-ccu";
+			reg = <0x7010000 0x250>;
+			clocks = <&osc24M>,
+				 <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>,
+				 <&ccu CLK_PLL_PERIPH0_200M>,
+				 <&ccu CLK_PLL_AUDIO0_4X>;
+			clock-names = "hosc",
+				      "losc",
+				      "iosc",
+				      "pll-periph",
+				      "pll-audio";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		nmi_intc: interrupt-controller at 7010320 {
+			compatible = "allwinner,sun55i-a523-nmi";
+			reg = <0x07010320 0xc>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		r_pio: pinctrl at 7022000 {
+			compatible = "allwinner,sun55i-a523-r-pinctrl";
+			reg = <0x7022000 0x800>;
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB0>,
+				 <&osc24M>,
+				 <&rtc CLK_OSC32K>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			r_i2c_pins: r-i2c-pins {
+				pins = "PL0" ,"PL1";
+				allwinner,pinmux = <2>;
+				function = "r_i2c0";
+			};
+		};
+
+		r_i2c0: i2c at 7081400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x07081400 0x400>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_BUS_R_I2C0>;
+			resets = <&r_ccu RST_BUS_R_I2C0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&r_i2c_pins>;
+			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		rtc: rtc at 7090000 {
+			compatible = "allwinner,sun55i-a523-rtc",
+				     "allwinner,sun50i-r329-rtc";
+			reg = <0x7090000 0x400>;
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_BUS_R_RTC>,
+				 <&osc24M>,
+				 <&r_ccu CLK_R_AHB>;
+			clock-names = "bus", "hosc", "ahb";
+			#clock-cells = <1>;
+		};
+	};
+};
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:03 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:03 +0000
Subject: [PATCH v2 09/15] dt-bindings: vendor-prefixes: Add YuzukiHD name
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-10-andre.przywara@arm.com>

YuzukiHD provides Open Source Hardware designs, and also offers
ready-made builds of them: https://github.com/YuzukiHD

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 5079ca6ce1d1e..8c0991e002ee8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1737,6 +1737,8 @@ patternProperties:
     description: Shenzhen Yashi Changhua Intelligent Technology Co., Ltd.
   "^ysoft,.*":
     description: Y Soft Corporation a.s.
+  "^yuzukihd,.*":
+    description: YuzukiHD Open Source Hardware
   "^zarlink,.*":
     description: Zarlink Semiconductor
   "^zealz,.*":
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:04 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:04 +0000
Subject: [PATCH v2 10/15] dt-bindings: arm: sunxi: Add new board names for A523 generation
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-11-andre.przywara@arm.com>

The new Allwinner A523 SoC family comes in different packages, though
they all share the same die, and so the devicetree bindings.

Add three board names that use a version from this SoC family:
- The Avaota A1: an Open Source hardware router board.
- The Radxa Cubie A5E: a typical development board
- The X96QPro+: a TV box

Add their compatible name to the list.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 046536d02706f..80096819fda91 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -840,6 +840,11 @@ properties:
           - const: allwinner,r7-tv-dongle
           - const: allwinner,sun5i-a10s
 
+      - description: Radxa Cubie A5E
+        items:
+          - const: radxa,cubie-a5e
+          - const: allwinner,sun55i-a527
+
       - description: Remix Mini PC
         items:
           - const: jide,remix-mini-pc
@@ -961,6 +966,11 @@ properties:
           - const: hechuang,x96-mate
           - const: allwinner,sun50i-h616
 
+      - description: X96Q Pro+
+        items:
+          - const: amediatech,x96q-pro-plus
+          - const: allwinner,sun55i-h728
+
       - description: Xunlong OrangePi
         items:
           - const: xunlong,orangepi
@@ -1076,4 +1086,9 @@ properties:
           - const: xunlong,orangepi-zero3
           - const: allwinner,sun50i-h618
 
+      - description: YuzukiHD Avaota A1
+        items:
+          - const: yuzukihd,avaota-a1
+          - const: allwinner,sun55i-t527
+
 additionalProperties: true
-- 
2.46.3



From andre.przywara at arm.com  Tue Mar  4 14:23:05 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  4 Mar 2025 22:23:05 +0000
Subject: [PATCH v2 11/15] arm64: dts: allwinner: a523: add Avaota-A1 router support
In-Reply-To: <20250304222309.29385-1-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
Message-ID: <20250304222309.29385-12-andre.przywara@arm.com>

The Avaota A1 router board is an Open Source hardware board, designed
by YuzukiHD. Pine64 produces some boards and sells them. It uses the
Allwinner A527 or T527 SoC, and comes with the following features:
  - Eight ARM Cortex-A55 cores, Mali-G57 MC1 GPU
  - 1GiB/2GiB/4GiB LPDDR4 DRAM
  - AXP717 + AXP323 PMIC
  - Raspberry-Pi-2 compatible GPIO header
  - 1 USB 2.0 type A host port, 1 USB 3.0 type A host post
  - 1 USB 2.0 type C port (OTG + serial debug)
  - MicroSD slot
  - eMMC between 16 and 128 GiB
  - on-board 16MiB bootable SPI NOR flash
  - two 1Gbps Ethernet ports (via RTL8211F PHYs)
  - HDMI port
  - DP port
  - camera and LCD connectors
  - 3.5mm headphone jack
  - (yet) unsupported WiFi/BT chip
  - 1.3" LC display, connected via SPI
  - 12 V barrel plug for power supply

Add the devicetree file describing the currently supported features.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-t527-avaota-a1.dts   | 308 ++++++++++++++++++
 2 files changed, 309 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 00bed412ee31c..0d678a7499e3c 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,3 +52,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts
new file mode 100644
index 0000000000000..85a546aecdbe1
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2024 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Avaota A1";
+	compatible = "yuzukihd,avaota-a1", "allwinner,sun55i-t527";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc12v: vcc12v {
+		/* DC input jack */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-12v";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the 12V->5V regulator */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc12v>;
+		regulator-always-on;
+	};
+
+	reg_usb_vbus: vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc5v>;
+		gpio = <&pio 8 12 GPIO_ACTIVE_HIGH>;	/* PI12 */
+		enable-active-high;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_cldo3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	status = "okay";
+};
+
+&mmc2 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	non-removable;
+	vmmc-supply = <&reg_cldo3>;
+	vqmmc-supply = <&reg_cldo1>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_dcdc4>;
+	vcc-pe-supply = <&reg_dcdc4>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_dcdc4>;
+	vcc-pj-supply = <&reg_dcdc4>;
+	vcc-pk-supply = <&reg_bldo3>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 35 {
+		compatible = "x-powers,axp717";
+		reg = <0x35>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.4 GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1160000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vdd-io";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				/* not connected */
+			};
+
+			reg_aldo3: aldo3 {
+				/* supplies the I2C pins for this PMIC */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pl-pm";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-wifi-lvds";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-dram-1v8";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-cvp-pk-vid1v8";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pc";
+			};
+
+			reg_cldo2: cldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-efuse";
+			};
+
+			reg_cldo3: cldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-io-mmc-spi-ana";
+			};
+
+			reg_cldo4: cldo4 {
+				/* not connected */
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				/* not connected */
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			/* Some RISC-V management core related voltage */
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-dnr";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	 /*
+	  * The CC pins of the USB-C port have two pull-down resistors
+	  * connected to GND, which fixes this port to a peripheral role.
+	  * There is a regulator, controlled by a GPIO, to provide VBUS power
+	  * to the port, and a VBUSDET GPIO, to detect externally provided
+	  * power, but without the CC pins there is no real way to do a
+	  * runtime role detection.
+	  */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb0_vbus-supply = <&reg_usb_vbus>;
+	usb0_vbus_det-gpios = <&pio 8 13 GPIO_ACTIVE_HIGH>; /* PI13 */
+	status = "okay";
+};
-- 
2.46.3



From Frank.li at nxp.com  Tue Mar  4 14:25:45 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 17:25:45 -0500
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <Z8d6qpNaL4eJRQI1@lizhi-Precision-Tower-5810>
References: <Z8YlySM6Xtr0beo1@lizhi-Precision-Tower-5810>
 <20250304175010.GA207565@bhelgaas>
 <Z8d6qpNaL4eJRQI1@lizhi-Precision-Tower-5810>
Message-ID: <Z8d96Qbggv117LlO@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 05:11:54PM -0500, Frank Li wrote:
> On Tue, Mar 04, 2025 at 11:50:10AM -0600, Bjorn Helgaas wrote:
> > On Mon, Mar 03, 2025 at 04:57:29PM -0500, Frank Li wrote:
> > > On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> > > > On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > > > > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > > > > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > > > > for PCI controllers with address translation units.
> > > > >
> > > > > Typical PCI data flow involves:
> > > > >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> > > > >   PCI Controller (PCI bus address) -> PCI Bus.
> > > > >
> > > > > While most bus fabrics preserve address consistency, some modify addresses
> > > > > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > > > > translate these intermediate addresses correctly to PCI bus addresses.
> > > > >
> > > > > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > > > > PCI controller drivers.
> > > > > ...
> > > >
> > > > > +++ b/drivers/pci/of.c
> > > > > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> > > > >  			res->flags &= ~IORESOURCE_MEM_64;
> > > > >  		}
> > > > >
> > > > > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > > > > +		/*
> > > > > +		 * IORESOURCE_IO res->start is io space start address.
> > > > > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > > > > +		 * same as range.cpu_addr.
> > > > > +		 *
> > > > > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > > > > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > > > > +		 */
> > > > > +
> > > > > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > > > > +						   range.cpu_addr - range.parent_bus_addr);
> > > >
> > > > I don't know exactly where it needs to go, but I think we can call
> > > > .cpu_addr_fixup() once at startup on the base of the region.  This
> > > > will tell us the offset that applies to the entire region, i.e.,
> > > > parent_bus_offset.
> > > >
> > > > Then we can remove all the .cpu_addr_fixup() calls in
> > > > cdns_pcie_host_init_address_translation(),
> > > > cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
> > > >
> > > > Until we can get rid of all the .cpu_addr_fixup() implementations,
> > > > We'll still have that single call at startup (I guess once for cadence
> > > > and another for designware), but it should simplify the current
> > > > callers quite a bit.
> > >
> > > I don't think it can simple code. cdns_pcie_set_outbound_region() and
> > > dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
> > > "resource" to manage outbound windows.
> >
> > Let's ignore cadence for now.  I don't think we need to solve that
> > until later.
> >
> > dw_pcie_prog_outbound_atu() is called by:
> >
> >   - dw_pcie_other_conf_map_bus(): atu.parent_bus_addr = pp->cfg0_base
> >
> >     I think dw_pcie_host_init() can set pp->cfg0_base with the correct
> >     intermediate address, either via the the of_property_read_reg() or
> >     .cpu_addr_fixup().

And chicken and egg problem here for artpec6_pcie_cpu_addr_fixup(), which
need cfg0_base. But try to use .cpu_addr_fixup() to get cfg0_base's
intermediate address.

Frank

> >
> >     If dw_pcie_host_init() does this, then we don't need
> >     .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
> >
> >   - dw_pcie_rd_other_conf(): atu.parent_bus_addr = pp->io_base
> >
> >     Similarly, dw_pcie_host_init() should be able to set pp->io_base
> >     to the intermediate address, so we don't need .cpu_addr_fixup() in
> >     dw_pcie_prog_outbound_atu().
>
> I found some driver's cpu_addr_fixup()'s implement depend on the
> initilize sequence.
>
> for example:
> 	pcie-artpec6.c
>
> static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
> {
>         struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
>         struct dw_pcie_rp *pp = &pci->pp;
>         struct dw_pcie_ep *ep = &pci->ep;
>
>         switch (artpec6_pcie->mode) {
>         case DW_PCIE_RC_TYPE:
>                 return cpu_addr - pp->cfg0_base;
>         case DW_PCIE_EP_TYPE:
>                 return cpu_addr - ep->phys_base;
>         default:
>                 dev_err(pci->dev, "UNKNOWN device type\n");
>         }
>         return cpu_addr;
> }
>
> This implement require *cfg0_base* and *phys_base*, pp/ep, need set before
> call artpec6_pcie_cpu_addr_fixup().
>
> static u64 visconti_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
> {
>         struct dw_pcie_rp *pp = &pci->pp;
>
>         return cpu_addr & ~pp->io_base;
> }
>
> this one require *io_base* and *pp* need be set before call
> visconti_pcie_cpu_addr_fixup()
>
> Because I have not such hardware platform, it is not trivial change and
> it is hard to involve bugs.
>
> If move .cpu_addr_fixup() too early, it will cause kernel dump.
>
> I suggest keep current overall sequent and try to clean up these driver's
> cpu_addr_fixup() firstly.
>
> Frank
>
> >
> >   - dw_pcie_iatu_setup(): atu.parent_bus_addr = entry->res->start
> >
> >     Here "entry" iterates through bridge->windows, and we should be
> >     able to set entry->parent_bus_offset at init-time, using
> >     .cpu_addr_fixup() if necessary, so we can apply that offset
> >     unconditionally, regardless of use_parent_dt_ranges, and we won't
> >     need .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
> >
> >   - dw_pcie_pme_turn_off:
> >     atu.parent_bus_addr = pci->pp.msg_res->start - pci->pp.msg_parent_bus_offset
> >
> >     This should be the same as dw_pcie_iatu_setup() since
> >     msg_parent_bus_offset comes from the window iteration in
> >     dw_pcie_host_request_msg_tlp_res().  As long as the windows have
> >     the correct parent_bus_offset at init-time, we should be all set.


From Frank.li at nxp.com  Tue Mar  4 14:11:54 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 4 Mar 2025 17:11:54 -0500
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <20250304175010.GA207565@bhelgaas>
References: <Z8YlySM6Xtr0beo1@lizhi-Precision-Tower-5810>
 <20250304175010.GA207565@bhelgaas>
Message-ID: <Z8d6qpNaL4eJRQI1@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 11:50:10AM -0600, Bjorn Helgaas wrote:
> On Mon, Mar 03, 2025 at 04:57:29PM -0500, Frank Li wrote:
> > On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> > > On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > > > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > > > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > > > for PCI controllers with address translation units.
> > > >
> > > > Typical PCI data flow involves:
> > > >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> > > >   PCI Controller (PCI bus address) -> PCI Bus.
> > > >
> > > > While most bus fabrics preserve address consistency, some modify addresses
> > > > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > > > translate these intermediate addresses correctly to PCI bus addresses.
> > > >
> > > > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > > > PCI controller drivers.
> > > > ...
> > >
> > > > +++ b/drivers/pci/of.c
> > > > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> > > >  			res->flags &= ~IORESOURCE_MEM_64;
> > > >  		}
> > > >
> > > > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > > > +		/*
> > > > +		 * IORESOURCE_IO res->start is io space start address.
> > > > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > > > +		 * same as range.cpu_addr.
> > > > +		 *
> > > > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > > > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > > > +		 */
> > > > +
> > > > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > > > +						   range.cpu_addr - range.parent_bus_addr);
> > >
> > > I don't know exactly where it needs to go, but I think we can call
> > > .cpu_addr_fixup() once at startup on the base of the region.  This
> > > will tell us the offset that applies to the entire region, i.e.,
> > > parent_bus_offset.
> > >
> > > Then we can remove all the .cpu_addr_fixup() calls in
> > > cdns_pcie_host_init_address_translation(),
> > > cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
> > >
> > > Until we can get rid of all the .cpu_addr_fixup() implementations,
> > > We'll still have that single call at startup (I guess once for cadence
> > > and another for designware), but it should simplify the current
> > > callers quite a bit.
> >
> > I don't think it can simple code. cdns_pcie_set_outbound_region() and
> > dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
> > "resource" to manage outbound windows.
>
> Let's ignore cadence for now.  I don't think we need to solve that
> until later.
>
> dw_pcie_prog_outbound_atu() is called by:
>
>   - dw_pcie_other_conf_map_bus(): atu.parent_bus_addr = pp->cfg0_base
>
>     I think dw_pcie_host_init() can set pp->cfg0_base with the correct
>     intermediate address, either via the the of_property_read_reg() or
>     .cpu_addr_fixup().
>
>     If dw_pcie_host_init() does this, then we don't need
>     .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
>
>   - dw_pcie_rd_other_conf(): atu.parent_bus_addr = pp->io_base
>
>     Similarly, dw_pcie_host_init() should be able to set pp->io_base
>     to the intermediate address, so we don't need .cpu_addr_fixup() in
>     dw_pcie_prog_outbound_atu().

I found some driver's cpu_addr_fixup()'s implement depend on the
initilize sequence.

for example:
	pcie-artpec6.c

static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
{
        struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
        struct dw_pcie_rp *pp = &pci->pp;
        struct dw_pcie_ep *ep = &pci->ep;

        switch (artpec6_pcie->mode) {
        case DW_PCIE_RC_TYPE:
                return cpu_addr - pp->cfg0_base;
        case DW_PCIE_EP_TYPE:
                return cpu_addr - ep->phys_base;
        default:
                dev_err(pci->dev, "UNKNOWN device type\n");
        }
        return cpu_addr;
}

This implement require *cfg0_base* and *phys_base*, pp/ep, need set before
call artpec6_pcie_cpu_addr_fixup().

static u64 visconti_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
{
        struct dw_pcie_rp *pp = &pci->pp;

        return cpu_addr & ~pp->io_base;
}

this one require *io_base* and *pp* need be set before call
visconti_pcie_cpu_addr_fixup()

Because I have not such hardware platform, it is not trivial change and
it is hard to involve bugs.

If move .cpu_addr_fixup() too early, it will cause kernel dump.

I suggest keep current overall sequent and try to clean up these driver's
cpu_addr_fixup() firstly.

Frank

>
>   - dw_pcie_iatu_setup(): atu.parent_bus_addr = entry->res->start
>
>     Here "entry" iterates through bridge->windows, and we should be
>     able to set entry->parent_bus_offset at init-time, using
>     .cpu_addr_fixup() if necessary, so we can apply that offset
>     unconditionally, regardless of use_parent_dt_ranges, and we won't
>     need .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
>
>   - dw_pcie_pme_turn_off:
>     atu.parent_bus_addr = pci->pp.msg_res->start - pci->pp.msg_parent_bus_offset
>
>     This should be the same as dw_pcie_iatu_setup() since
>     msg_parent_bus_offset comes from the window iteration in
>     dw_pcie_host_request_msg_tlp_res().  As long as the windows have
>     the correct parent_bus_offset at init-time, we should be all set.


From laurentiumihalcea111 at gmail.com  Tue Mar  4 14:58:47 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Wed, 5 Mar 2025 00:58:47 +0200
Subject: [PATCH v2 0/5] imx8mp: add support for the IMX AIPSTZ bridge
In-Reply-To: <20250227112856.aylsurbt3uqm4ivw@pengutronix.de>
References: <20250226165314.34205-1-laurentiumihalcea111@gmail.com>
 <20250226212219.lthoofw7nrs3gtg6@pengutronix.de>
 <20250227112856.aylsurbt3uqm4ivw@pengutronix.de>
Message-ID: <541539db-0015-41de-837f-aabbea68486a@gmail.com>



On 2/27/2025 1:28 PM, Marco Felsch wrote:
> Hi Laurentiu,
>
> On 25-02-26, Marco Felsch wrote:
>> Hi,
>>
>> On 25-02-26, Laurentiu Mihalcea wrote:
>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>
>>> The AIPSTZ bridge offers some security-related configurations which can
>>> be used to restrict master access to certain peripherals on the bridge.
>>>
>>> Normally, this could be done from a secure environment such as ATF before
>>> Linux boots but the configuration of AIPSTZ5 is lost each time the power
>>> domain is powered off and then powered on. Because of this, it has to be
>>> configured each time the power domain is turned on and before any master
>>> tries to access the peripherals (e.g: AP, CM7, DSP, on i.MX8MP).
>> My question still stands:
>>
>> Setting these bits requires very often that the core is running at EL3
>> (e.g. secure-monitor) which is not the case for Linux. Can you please
>> provide more information how Linux can set these bits?
> Sorry I didn't noticed your response:
>
> https://lore.kernel.org/all/a62ab860-5e0e-4ebc-af1f-6fb7ac621e2b at gmail.com/
>
> If EL1 is allowed to set the security access configuration of the IP
> cores doesn't this mean that a backdoor can be opened? E.g. your
> secure-boot system configures one I2C IP core to be accessible only from
> secure-world S-EL1 (OP-TEE) and after the power-domain was power-cycled
> it's accessible from EL1 again. This doesn't seem right. Why should a
> user be able to limit the access permissions to an IP core to only be
> accessible from secure-world if the IP core is accessible from
> normal-world after the power-domain was power-cycled.
>
> Regards,
>   Marco

I'm no security expert so please feel free to correct me if I get something wrong.

This isn't about S/NS world. The bridge AC doesn't offer any configurations for
denying access to peripherals based on S/NS world. AFAIK that's the job of the CSU
(central security unit), which is a different IP.

Perhaps I shouldn't have used the term "trusted" as it might have ended up creating
more confusion? If so, please do let me know so I can maybe add a comment about
it in one of the commit messages. In this context, "master X is trusted for read/writes"
means "master X is allowed to perform read/write transactions".

Even if the bridge is configured to allow read/write transactions from a master
(i.e: master is marked as trusted for read/writes) that wouldn't be very helpful.
You'd still have to bypass the CSU configuration which as far as I understand is also
used by the bridge to deny access to peripherals (e.g: if transaction is secure+privileged
then forward to peripheral, otherwise abort it). See the "4.7.6.1 Security Block"
and "4.7.4? Access Protections" chapters from the IMX8MP RM.

Given all of this, I think the purpose of this IP's AC is to add some extra,
light, security features on top of the CSU.


From florian.fainelli at broadcom.com  Tue Mar  4 15:01:53 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Tue, 4 Mar 2025 15:01:53 -0800
Subject: [PATCH] ARM: dts: BCM5301X: Fix switch port labels of ASUS
 RT-AC3200
In-Reply-To: <20250304-for-broadcom-fix-rt-ac3200-switch-ports-v1-1-7e249a19a13e@arinc9.com>
References: <20250304-for-broadcom-fix-rt-ac3200-switch-ports-v1-1-7e249a19a13e@arinc9.com>
Message-ID: <934529bf-d859-4eed-ade1-2917afb4e793@broadcom.com>

On 3/4/25 07:55, Chester A. Unal via B4 Relay wrote:
> From: "Chester A. Unal" <chester.a.unal at arinc9.com>
> 
> After using the device for a while, Tom reports that he initially described
> the switch port labels incorrectly. Apparently, ASUS's own firmware also
> describes them incorrectly. Correct them to what is seen on the chassis.
> 
> Reported-by: Tom Brautaset <tbrautaset at gmail.com>
> Fixes: b116239094d8 ("ARM: dts: BCM5301X: Add DT for ASUS RT-AC3200")
> Signed-off-by: Chester A. Unal <chester.a.unal at arinc9.com>

Applied to devicetree/fixes, thanks!
-- 
Florian


From florian.fainelli at broadcom.com  Tue Mar  4 15:01:42 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Tue, 4 Mar 2025 15:01:42 -0800
Subject: [PATCH] ARM: dts: BCM5301X: Fix switch port labels of ASUS
 RT-AC5300
In-Reply-To: <20250303-for-broadcom-fix-rt-ac5300-switch-ports-v1-1-e058856ef4d3@arinc9.com>
References: <20250303-for-broadcom-fix-rt-ac5300-switch-ports-v1-1-e058856ef4d3@arinc9.com>
Message-ID: <cb5e3a1e-39a5-4502-b99b-b7183dfaea02@broadcom.com>

On 3/3/25 05:06, Chester A. Unal via B4 Relay wrote:
> From: "Chester A. Unal" <chester.a.unal at arinc9.com>
> 
> After using the device for a while, Tom reports that he initially described
> the switch port labels incorrectly. Correct them.
> 
> Reported-by: Tom Brautaset <tbrautaset at gmail.com>
> Fixes: 961dedc6b4e4 ("ARM: dts: BCM5301X: Add DT for ASUS RT-AC5300")
> Signed-off-by: Chester A. Unal <chester.a.unal at arinc9.com>

Applied to devicetree/fixes, thanks!
-- 
Florian


From gshan at redhat.com  Tue Mar  4 15:45:41 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 5 Mar 2025 09:45:41 +1000
Subject: [PATCH v7 35/45] arm64: RME: Propagate number of breakpoints and
 watchpoints to userspace
In-Reply-To: <20250213161426.102987-36-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-36-steven.price@arm.com>
Message-ID: <c8af8a7f-5ee4-460b-aec4-959f688db628@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> From: Jean-Philippe Brucker <jean-philippe at linaro.org>
> 
> The RMM describes the maximum number of BPs/WPs available to the guest
> in the Feature Register 0. Propagate those numbers into ID_AA64DFR0_EL1,
> which is visible to userspace. A VMM needs this information in order to
> set up realm parameters.
> 
> Signed-off-by: Jean-Philippe Brucker <jean-philippe at linaro.org>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/include/asm/kvm_rme.h |  2 ++
>   arch/arm64/kvm/rme.c             | 22 ++++++++++++++++++++++
>   arch/arm64/kvm/sys_regs.c        |  2 +-
>   3 files changed, 25 insertions(+), 1 deletion(-)
> 

With the following one nitpick addressed:

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_rme.h
> index d684b30493f5..67ee38541a82 100644
> --- a/arch/arm64/include/asm/kvm_rme.h
> +++ b/arch/arm64/include/asm/kvm_rme.h
> @@ -85,6 +85,8 @@ void kvm_init_rme(void);
>   u32 kvm_realm_ipa_limit(void);
>   u32 kvm_realm_vgic_nr_lr(void);
>   
> +u64 kvm_realm_reset_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val);
> +
>   bool kvm_rme_supports_sve(void);
>   
>   int kvm_realm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap);
> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
> index f83f34358832..8c426f575728 100644
> --- a/arch/arm64/kvm/rme.c
> +++ b/arch/arm64/kvm/rme.c
> @@ -87,6 +87,28 @@ u32 kvm_realm_vgic_nr_lr(void)
>   	return u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS);
>   }
>   
> +u64 kvm_realm_reset_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
> +{
> +	u32 bps = u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_NUM_BPS);
> +	u32 wps = u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_NUM_WPS);
> +	u32 ctx_cmps;
> +
> +	if (!kvm_is_realm(vcpu->kvm))
> +		return val;
> +
> +	/* Ensure CTX_CMPs is still valid */
> +	ctx_cmps = FIELD_GET(ID_AA64DFR0_EL1_CTX_CMPs, val);
> +	ctx_cmps = min(bps, ctx_cmps);
> +
> +	val &= ~(ID_AA64DFR0_EL1_BRPs_MASK | ID_AA64DFR0_EL1_WRPs_MASK |
> +		 ID_AA64DFR0_EL1_CTX_CMPs);
> +	val |= FIELD_PREP(ID_AA64DFR0_EL1_BRPs_MASK, bps) |
> +	       FIELD_PREP(ID_AA64DFR0_EL1_WRPs_MASK, wps) |
> +	       FIELD_PREP(ID_AA64DFR0_EL1_CTX_CMPs, ctx_cmps);
> +
> +	return val;
> +}
> +

The chunk of code can be squeezed to sys_reg.c::sanitise_id_aa64dfr0_el1() since
sys_reg.c has been plumbed for realm, no reason to keep a separate helper in rme.c
because it's only called by sys_reg.c::sanitise_id_aa64dfr0_el1()

>   static int get_start_level(struct realm *realm)
>   {
>   	return 4 - ((realm->ia_bits - 8) / (RMM_PAGE_SHIFT - 3));
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index ed881725eb64..5618eff33155 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1820,7 +1820,7 @@ static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
>   	/* Hide BRBE from guests */
>   	val &= ~ID_AA64DFR0_EL1_BRBE_MASK;
>   
> -	return val;
> +	return kvm_realm_reset_id_aa64dfr0_el1(vcpu, val);
>   }
>   
>   static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,

Thanks,
Gavin



From gshan at redhat.com  Tue Mar  4 15:46:31 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 5 Mar 2025 09:46:31 +1000
Subject: [PATCH v7 36/45] arm64: RME: Set breakpoint parameters through
 SET_ONE_REG
In-Reply-To: <20250213161426.102987-37-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-37-steven.price@arm.com>
Message-ID: <f331382f-5747-4837-ae60-42e9cb37ecd4@redhat.com>

On 2/14/25 2:14 AM, Steven Price wrote:
> From: Jean-Philippe Brucker <jean-philippe at linaro.org>
> 
> Allow userspace to configure the number of breakpoints and watchpoints
> of a Realm VM through KVM_SET_ONE_REG ID_AA64DFR0_EL1.
> 
> The KVM sys_reg handler checks the user value against the maximum value
> given by RMM (arm64_check_features() gets it from the
> read_sanitised_id_aa64dfr0_el1() reset handler).
> 
> Userspace discovers that it can write these fields by issuing a
> KVM_ARM_GET_REG_WRITABLE_MASKS ioctl.
> 
> Signed-off-by: Jean-Philippe Brucker <jean-philippe at linaro.org>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
>   arch/arm64/kvm/guest.c    |  2 ++
>   arch/arm64/kvm/rme.c      |  3 +++
>   arch/arm64/kvm/sys_regs.c | 17 +++++++++++------
>   3 files changed, 16 insertions(+), 6 deletions(-)
> 

Reviewed-by: Gavin Shan <gshan at redhat.com>



From jic23 at kernel.org  Tue Mar  4 15:59:29 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Tue, 4 Mar 2025 23:59:29 +0000
Subject: [PATCH v4 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <eaede287-658d-4c23-b217-5bc8053e64ed@gmail.com>
References: <cover.1740421248.git.mazziesaccount@gmail.com>
	<23f5ee3e3bf7179930d66c720d5c4c33cdbe8366.1740421248.git.mazziesaccount@gmail.com>
	<0de7b0ac-eca5-49ba-b1b3-f249655f3646@baylibre.com>
	<1b308a10-9622-47f9-b489-bd969fbdfc34@gmail.com>
	<6f6e6550-5246-476f-9168-5e24151ab165@baylibre.com>
	<9180ff11-888b-453d-9617-4b3a0fb38d91@gmail.com>
	<20250302032054.1fb8a011@jic23-huawei>
	<eaede287-658d-4c23-b217-5bc8053e64ed@gmail.com>
Message-ID: <20250304235929.1a8f23f8@jic23-huawei>

On Sun, 2 Mar 2025 14:54:16 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 02/03/2025 05:20, Jonathan Cameron wrote:
> > On Thu, 27 Feb 2025 09:46:06 +0200
> > Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> >   
> >> On 26/02/2025 18:10, David Lechner wrote:  
> >>> On 2/26/25 12:28 AM, Matti Vaittinen wrote:  
> 
> ...
> 
> > So today the situation is we have all the options in tree and we aren't
> > really in a position to drop any of them:  
> 
> Sure. I am only really interested whether we want to prefer some 
> approach for (majority of) new drivers. Furthermore, I believe there 
> will always be corner cases and oddities which won't fit to the 'de 
> facto' model. That doesn't mean we shouldn't help those which don't have 
> such 'oddities' to work with some generic code.
Absolutely but we also can't apply this to existing drivers that don't
work quite that way.  So if we want to make more use of it we end up
providing variants long term.

> 
> > Hindsight is a wonderful thing.  I'm not sure on what policy we should have
> > gone for, but now we are kind of stuck with this slightly messy situation.  
> 
> Sorry if my comments came out as criticism. 

No problem - that was just me being wistful about wanting a crystal ball :)

> It was not intention, I just 
> try to justify the helpers by trying to think what new drivers should 
> prefer.
> 
> > Helper wise if it expands usefulness we may want a bool parameter to say
> > if we skip the missing or not + make sure a max expected channel is provided
> > (might already be - I didn't check!)  
> 
> This far it only had (optional) maximum channel ID for sanity checking 
> (useful for callers which use the ID to index an array). The bool 
> parameter would also require a parameter specifying the number of 
> expected channels. That'd make 3 parameters which may be used or unused.
> 
> I don't think I saw existing code which would have used these 
> parameters. It might be cleaner to add new APIs when we get such 
> use-cases. That should simplify the use for current cases.
That's fair enough.   Ultimately my guess is we'll end up with a complex
internal function and a bunch of wrappers that elide the majority of
the parameters.  We can get there once it's needed though!

Jonathan

> 
> Thank You for the long explanation of current system + the history :) I 
> appreciate your guidance!
> 
> Yours,
> 	-- Matti
> 



From gshan at redhat.com  Tue Mar  4 16:15:54 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 5 Mar 2025 10:15:54 +1000
Subject: [PATCH v7 05/45] arm64: RME: Add wrappers for RMI calls
In-Reply-To: <59f84354-e890-48c8-ba06-87dda471f364@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-6-steven.price@arm.com>
 <8f08b96b-8219-4d51-8f46-bc367bbf2031@redhat.com>
 <59f84354-e890-48c8-ba06-87dda471f364@arm.com>
Message-ID: <1e1aa766-c358-4a4f-918e-f0044fe499fe@redhat.com>

On 3/4/25 1:05 AM, Steven Price wrote:
> On 03/03/2025 03:42, Gavin Shan wrote:
>> On 2/14/25 2:13 AM, Steven Price wrote:
>>> The wrappers make the call sites easier to read and deal with the
>>> boiler plate of handling the error codes from the RMM.
>>>
>>> Signed-off-by: Steven Price <steven.price at arm.com>
>>> ---
>>> Changes from v5:
>>>  ? * Further improve comments
>>> Changes from v4:
>>>  ? * Improve comments
>>> Changes from v2:
>>>  ? * Make output arguments optional.
>>>  ? * Mask RIPAS value rmi_rtt_read_entry()
>>>  ? * Drop unused rmi_rtt_get_phys()
>>> ---
>>>  ? arch/arm64/include/asm/rmi_cmds.h | 508 ++++++++++++++++++++++++++++++
>>>  ? 1 file changed, 508 insertions(+)
>>>  ? create mode 100644 arch/arm64/include/asm/rmi_cmds.h
>>>
>>
>> With the following nitpicks addressed:
>>
>> Reviewed-by: Gavin Shan <gshan at redhat.com>
> 
> Thanks, there were a couple of other pages and params_ptr references
> that I've updated to granules and just 'params' too now. With hindsight
> conflating pages and granules in the earlier versions of this series was
> a big mistake ;)
> 

Yeah, that was because the assumption was the page size and granule size are
equal(4KB), but they're still different things. With the intention to support
ARM CCA on host with non-aligned page sizes (16KB/64KB), we have to differentiate
granule/page.

Ideally, the granule is only visible to RMI calls and their helpers. An new memory
allocator seems inevitable so that the allocated pages can be distributed on requests
by various RMI helpers in granule. It means the allocator is the line to separate page
and granule :)

Thanks,
Gavin

> Steve
> 
>>> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/
>>> asm/rmi_cmds.h
>>> new file mode 100644
>>> index 000000000000..043b7ff278ee
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/rmi_cmds.h
>>> @@ -0,0 +1,508 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/*
>>> + * Copyright (C) 2023 ARM Ltd.
>>> + */
>>> +
>>> +#ifndef __ASM_RMI_CMDS_H
>>> +#define __ASM_RMI_CMDS_H
>>> +
>>
>> [...]
>>
>>> +
>>> +/**
>>> + * rmi_rec_aux_count() - Get number of auxiliary granules required
>>> + * @rd: PA of the RD
>>> + * @aux_count: Number of pages written to this pointer
>>  ????????????????? ^^^^^^^^^^^^^^^
>>  ????????????????? Number of granules
>>> + *
>>> + * A REC may require extra auxiliary pages to be delegated for the
>>> RMM to
>>  ??????????????????????????????????????? ^^^^^
>>  ??????????????????????????????????????? granules
>>
>>> + * store metadata (not visible to the normal world) in. This function
>>> provides
>>> + * the number of pages that are required.
>>  ??????????????????? ^^^^^
>>  ??????????????????? granules
>>> + *
>>> + * Return: RMI return code
>>> + */
>>> +static inline int rmi_rec_aux_count(unsigned long rd, unsigned long
>>> *aux_count)
>>> +{
>>> +??? struct arm_smccc_res res;
>>> +
>>> +??? arm_smccc_1_1_invoke(SMC_RMI_REC_AUX_COUNT, rd, &res);
>>> +
>>> +??? if (aux_count)
>>> +??????? *aux_count = res.a1;
>>> +??? return res.a0;
>>> +}
>>> +
>>> +/**
>>> + * rmi_rec_create() - Create a REC
>>> + * @rd: PA of the RD
>>> + * @rec: PA of the target REC
>>> + * @params_ptr: PA of REC parameters
>>> + *
>>> + * Create a REC using the parameters specified in the struct
>>> rec_params pointed
>>> + * to by @params_ptr.
>>> + *
>>> + * Return: RMI return code
>>> + */
>>> +static inline int rmi_rec_create(unsigned long rd, unsigned long rec,
>>> +???????????????? unsigned long params_ptr)
>>> +{
>>> +??? struct arm_smccc_res res;
>>> +
>>> +??? arm_smccc_1_1_invoke(SMC_RMI_REC_CREATE, rd, rec, params_ptr, &res);
>>> +
>>> +??? return res.a0;
>>> +}
>>> +
>>
>> 'params_ptr' may be renamed to 'params'.
>>
>>
>> [...]
>>> +#endif /* __ASM_RMI_CMDS_H */
>>
>> Thanks,
>> Gavin
>>
> 



From matt at traverse.com.au  Tue Mar  4 16:19:01 2025
From: matt at traverse.com.au (Mathew McBride)
Date: Wed,  5 Mar 2025 11:19:01 +1100
Subject: [PATCH v2] arm64: dts: freescale: ten64: add usb hub definition
In-Reply-To: <20250129045352.10728-1-matt@traverse.com.au>
References: <20250129045352.10728-1-matt@traverse.com.au>
Message-ID: <20250305001901.31594-1-matt@traverse.com.au>

A device tree binding for the Microchip USB5744 hub controller
was added in commit 02be19e914b8 ("dt-bindings: usb: Add support
for Microchip usb5744 hub controller").

U-Boot will consume this binding in order to perform the
necessary actions to enable the USB hub ports over I2C.
(We previously used our own out-of-tree driver for
this task)

The Ten64 board does not have any switchable supplies
for the voltage rails utilized by the USB5744, so a
pair of dummy supplies have been added to facilitate
operation with U-Boot's hub driver.

Signed-off-by: Mathew McBride <matt at traverse.com.au>
---
Changes in v2:
 - provide unique node names for the two regulators
 - remove unnecessary newline under &usb1
---
 .../boot/dts/freescale/fsl-ls1088a-ten64.dts  | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
index bc0d89427fbe5..3a11068f2212f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
@@ -87,6 +87,22 @@ sfp_xg1: dpmac1-sfp {
 		los-gpios = <&sfpgpio 7 GPIO_ACTIVE_HIGH>;
 		maximum-power-milliwatt = <2000>;
 	};
+
+	usb1v2_supply: regulator-usbhub-1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "usbhub_1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+	};
+
+	system3v3_supply: regulator-system-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "system_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
 };
 
 /* XG1 - Upper SFP */
@@ -231,6 +247,12 @@ at97sc: tpm at 29 {
 		compatible = "atmel,at97sc3204t";
 		reg = <0x29>;
 	};
+
+	usbhub: usb-hub at 2d {
+		compatible = "microchip,usb5744";
+		reg = <0x2d>;
+	};
+
 };
 
 &i2c2 {
@@ -378,10 +400,32 @@ partition at 9400000 {
 	};
 };
 
+/* LS1088A USB Port 0 - direct to bottom USB-A port */
 &usb0 {
 	status = "okay";
 };
 
+/* LS1088A USB Port 1 - to Microchip USB5744 USB Hub */
 &usb1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
+
+	hub_2_0: hub at 1 {
+		compatible = "usb424,2744";
+		reg = <1>;
+		peer-hub = <&hub_3_0>;
+		i2c-bus = <&usbhub>;
+		vdd-supply = <&system3v3_supply>;
+		vdd2-supply = <&usb1v2_supply>;
+	};
+
+	hub_3_0: hub at 2 {
+		compatible = "usb424,5744";
+		reg = <2>;
+		peer-hub = <&hub_2_0>;
+		i2c-bus = <&usbhub>;
+		vdd-supply = <&system3v3_supply>;
+		vdd2-supply = <&usb1v2_supply>;
+	};
 };
-- 
2.45.1



From kuba at kernel.org  Tue Mar  4 16:24:37 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Tue, 4 Mar 2025 16:24:37 -0800
Subject: [PATCH net-next] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <33c38844-4fbe-469c-bb5f-06bdb7721114@ti.com>
References: <20250227093712.2130561-1-danishanwar@ti.com>
	<20250303172543.249a4fc2@kernel.org>
	<33c38844-4fbe-469c-bb5f-06bdb7721114@ti.com>
Message-ID: <20250304162437.0160f687@kernel.org>

On Tue, 4 Mar 2025 13:46:39 +0530 MD Danish Anwar wrote:
> On 04/03/25 6:55 am, Jakub Kicinski wrote:
> > On Thu, 27 Feb 2025 15:07:12 +0530 MD Danish Anwar wrote:  
> >> +	ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
> >> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
> >> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
> >> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
> >> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),  
> > 
> > I presume frame preemption is implemented in silicon? If yes -
> > what makes these "FW statistics"? Does the FW collect them from   
> 
> The statistics are maintained / updated by firmware and thus the name.
> 
> Preemption is implemented partially in both the hardware and firmware.
> The STATE MACHINE for preemption is in the firmware. The decision to
> when to PREEMEPT / ASSEMBLE a packet is made in firmware.
> 
> These preemption statistics are updated by the firmware based on the
> action performed by the firmware. Driver can read these to know the
> statistics of preemption. These stats will be able used by
> ethtool_mm_stats once the support for Preemption is added in the driver.

That was going to be my next question. If the statistic is suitable 
for a standard interface it should not be reported via ethtool -S.

Please leave the stats for unimplemented features out.

> >> +/* Incremented if a packet is dropped at PRU because of a rule violation */
> >> +#define FW_DROPPED_PKT		0x00F8  
> > 
> > Instead of adding comments here please add a file under
> > Documentation/networking/device_drivers/ with the explanations.
> > That's far more likely to be discovered by users, no?  
> 
> Sure I will drop these MACRO comments and create a .rst file in
> Documentation/networking/device_drivers/
> 
> One question though, should I create a table for the stats and it's
> description or should I create a section for each stats?
> 
> Something like this,
> 
> FW_RTU_PKT_DROP
> ---------------

Let's document the user-visible names! The strings from ethtool -S

> Diagnostic error counter which increments when RTU drops a locally
> injected packet due to port being disabled or rule violation.
> 
> Please let me know what do you think.

Taking inspiration from:
  Documentation/networking/device_drivers/ethernet/meta/fbnic.rst
should be a safe choice, I hope.


From ping.bai at nxp.com  Tue Mar  4 16:34:16 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Wed, 5 Mar 2025 00:34:16 +0000
Subject: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <Z8cd33Aw3tpPBism@lizhi-Precision-Tower-5810>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-4-ping.bai@nxp.com>
 <Z8cd33Aw3tpPBism@lizhi-Precision-Tower-5810>
Message-ID: <PAXPR04MB865500783C2518B63456B97687CB2@PAXPR04MB8655.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
> 
> On Tue, Mar 04, 2025 at 05:31:26PM +0800, Jacky Bai wrote:
> > Add the minimal dtsi support for i.MX943. i.MX943 is the first SoC of
> > i.MX94 Family, create a common dtsi for the whole i.MX94 family, and
> > the specific dtsi part for i.MX943.
> >
> > The clock, power domain and perf index need to be used by the device
> > nodes for resource reference, add them along with the dtsi support.
> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - remove the unnecessary macro define in clock header as suggested by
> Krzysztof
> >   - split the dtsi into imx94.dtsi and imx943.dtsi
> >   - use low case in the pinfunc header as Frank suggested
> >   - reorder the device nodes and properties
> >   - resolve Krzysztof's other comments
> > ---
> ...
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <24000000>;
> > +		clock-output-names = "osc_24m";
> > +	};
> > +
> > +	dummy: clock-dummy {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <0>;
> > +		clock-output-names = "dummy";
> > +	};
> > +
> > +	clk_ext1: clock-ext1 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <133000000>;
> > +		clock-output-names = "clk_ext1";
> > +	};
> > +
> > +	sai1_mclk: clock-sai1-mclk1 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <0>;
> > +		clock-output-names = "sai1_mclk";
> > +	};
> > +
> > +	sai2_mclk: clock-sai2-mclk1 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <0>;
> > +		clock-output-names = "sai2_mclk";
> > +	};
> > +
> > +	sai3_mclk: clock-sai3-mclk1 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <0>;
> > +		clock-output-names = "sai3_mclk";
> > +	};
> > +
> > +	sai4_mclk: clock-sai4-mclk1 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <0>;
> > +		clock-output-names = "sai4_mclk";
> > +	};
> > +
> > +	firmware {
> > +
> 
> Remove empty line here.
> 

Thx, will fix it in v3. 

BR
> Frank
> > +		scmi {
> > +			compatible = "arm,scmi";
> > +			#address-cells = <1>;
> > +			#size-cells = <0>;
> > +			mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>, <&mu2 5 1>;
> > +			shmem = <&scmi_buf0>, <&scmi_buf1>;
> > +			arm,max-rx-timeout-ms = <5000>;
> > +
> > +			scmi_devpd: protocol at 11 {
> > +				reg = <0x11>;
> > +				#power-domain-cells = <1>;
> > +			};
> > +
> > +			scmi_sys_power: protocol at 12 {
> > +				reg = <0x12>;
> > +			};
> > +
> > +			scmi_perf: protocol at 13 {
> > +				reg = <0x13>;
> > +				#power-domain-cells = <1>;
> > +			};
> > +
> > +			scmi_clk: protocol at 14 {
> > +				reg = <0x14>;
> > +				#clock-cells = <1>;
> > +			};
> > +
> > +			scmi_iomuxc: protocol at 19 {
> > +				reg = <0x19>;
> > +			};
> > +
> > +			scmi_bbm: protocol at 81 {
> > +				reg = <0x81>;
> > +			};
> > +
> > +			scmi_misc: protocol at 84 {
> > +				reg = <0x84>;
> > +			};
> > +		};
> > +	};
> > +
> > +	pmu {
> > +		compatible = "arm,cortex-a55-pmu";
> > +		interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) |
> IRQ_TYPE_LEVEL_HIGH)>;
> > +	};
> > +
> > +	psci {
> > +		compatible = "arm,psci-1.0";
> > +		method = "smc";
> > +	};
> > +
> > +	timer {
> > +		compatible = "arm,armv8-timer";
> > +		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) |
> IRQ_TYPE_LEVEL_LOW)>,
> > +			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) |
> IRQ_TYPE_LEVEL_LOW)>,
> > +			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) |
> IRQ_TYPE_LEVEL_LOW)>,
> > +			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) |
> IRQ_TYPE_LEVEL_LOW)>;
> > +		clock-frequency = <24000000>;
> > +		interrupt-parent = <&gic>;
> > +		arm,no-tick-in-suspend;
> > +	};
> > +
> > +	gic: interrupt-controller at 48000000 {
> > +		compatible = "arm,gic-v3";
> > +		reg = <0 0x48000000 0 0x10000>,
> > +		      <0 0x48060000 0 0xc0000>;
> > +		ranges;
> > +		#interrupt-cells = <3>;
> > +		interrupt-controller;
> > +		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> > +		#address-cells = <2>;
> > +		#size-cells = <2>;
> > +		dma-noncoherent;
> > +		interrupt-parent = <&gic>;
> > +
> > +		its: msi-controller at 48040000 {
> > +			compatible = "arm,gic-v3-its";
> > +			reg = <0 0x48040000 0 0x20000>;
> > +			#msi-cells = <1>;
> > +			dma-noncoherent;
> > +			msi-controller;
> > +		};
> > +	};
> > +
> > +	soc {
> > +		compatible = "simple-bus";
> > +		ranges;
> > +		#address-cells = <2>;
> > +		#size-cells = <2>;
> > +
> > +		aips2: bus at 42000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x42000000 0x0 0x800000>;
> > +			ranges = <0x42000000 0x0 0x42000000 0x8000000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			edma2: dma-controller at 42000000 {
> > +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> > +				reg = <0x42000000 0x210000>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "dma";
> > +				#dma-cells = <3>;
> > +				dma-channels = <64>;
> > +				interrupts-extended = <&a55_irqsteer 0>, <&a55_irqsteer
> 1>, <&a55_irqsteer 2>,
> > +					<&a55_irqsteer 3>, <&a55_irqsteer 4>,
> <&a55_irqsteer 5>,
> > +					<&a55_irqsteer 6>, <&a55_irqsteer 7>,
> <&a55_irqsteer 8>,
> > +					<&a55_irqsteer 9>, <&a55_irqsteer 10>,
> <&a55_irqsteer 11>,
> > +					<&a55_irqsteer 12>, <&a55_irqsteer 13>,
> <&a55_irqsteer 14>,
> > +					<&a55_irqsteer 15>, <&a55_irqsteer 16>,
> <&a55_irqsteer 17>,
> > +					<&a55_irqsteer 18>, <&a55_irqsteer 19>,
> <&a55_irqsteer 20>,
> > +					<&a55_irqsteer 21>, <&a55_irqsteer 22>,
> <&a55_irqsteer 23>,
> > +					<&a55_irqsteer 24>, <&a55_irqsteer 25>,
> <&a55_irqsteer 26>,
> > +					<&a55_irqsteer 27>, <&a55_irqsteer 28>,
> <&a55_irqsteer 29>,
> > +					<&a55_irqsteer 30>, <&a55_irqsteer 31>,
> <&a55_irqsteer 64>,
> > +					<&a55_irqsteer 65>, <&a55_irqsteer 66>,
> <&a55_irqsteer 67>,
> > +					<&a55_irqsteer 68>, <&a55_irqsteer 69>,
> <&a55_irqsteer 70>,
> > +					<&a55_irqsteer 71>, <&a55_irqsteer 72>,
> <&a55_irqsteer 73>,
> > +					<&a55_irqsteer 74>, <&a55_irqsteer 75>,
> <&a55_irqsteer 76>,
> > +					<&a55_irqsteer 77>, <&a55_irqsteer 78>,
> <&a55_irqsteer 79>,
> > +					<&a55_irqsteer 80>, <&a55_irqsteer 81>,
> <&a55_irqsteer 82>,
> > +					<&a55_irqsteer 83>, <&a55_irqsteer 84>,
> <&a55_irqsteer 85>,
> > +					<&a55_irqsteer 86>, <&a55_irqsteer 87>,
> <&a55_irqsteer 88>,
> > +					<&a55_irqsteer 89>, <&a55_irqsteer 90>,
> <&a55_irqsteer 91>,
> > +					<&a55_irqsteer 92>, <&a55_irqsteer 93>,
> <&a55_irqsteer 94>,
> > +					<&a55_irqsteer 95>, <&gic GIC_SPI 98
> IRQ_TYPE_LEVEL_HIGH>;
> > +			};
> > +
> > +			mu10: mailbox at 42430000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42430000 0x10000>;
> > +				interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			i3c2: i3c at 42520000 {
> > +				compatible = "silvaco,i3c-master-v1";
> > +				reg = <0x42520000 0x10000>;
> > +				interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <3>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_I3C2SLOW>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&dummy>;
> > +				clock-names = "pclk", "fast_clk", "slow_clk";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c3: i2c at 42530000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x42530000 0x10000>;
> > +				interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C3>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 5 0 0>, <&edma2 6 0 FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c4: i2c at 42540000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x42540000 0x10000>;
> > +				interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C4>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 4 0 0>, <&edma4 5 0 FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi3: spi at 42550000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x42550000 0x10000>;
> > +				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI3>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 7 0 0>, <&edma2 8 0 FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi4: spi at 42560000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x42560000 0x10000>;
> > +				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI4>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 6 0 0>, <&edma4 7 0 FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart3: serial at 42570000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42570000 0x1000>;
> > +				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART3>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma2 10 0 FSL_EDMA_RX>, <&edma2 9 0 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart4: serial at 42580000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42580000 0x1000>;
> > +				interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART4>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma4 10 0 FSL_EDMA_RX>, <&edma4 9 0 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart5: serial at 42590000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42590000 0x1000>;
> > +				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART5>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma2 12 0 FSL_EDMA_RX>, <&edma2 11 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart6: serial at 425a0000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x425a0000 0x1000>;
> > +				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART6>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma4 12 0 FSL_EDMA_RX>, <&edma4 11 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			flexcan2: can at 425b0000 {
> > +				compatible = "fsl,imx95-flexcan";
> > +				reg = <0x425b0000 0x10000>;
> > +				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_CAN2>;
> > +				clock-names = "ipg", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN2>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> > +				assigned-clock-rates = <80000000>;
> > +				fsl,clk-source = /bits/ 8 <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			flexcan3: can at 425e0000 {
> > +				compatible = "fsl,imx95-flexcan";
> > +				reg = <0x425e0000 0x10000>;
> > +				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_CAN3>;
> > +				clock-names = "ipg", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN3>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> > +				assigned-clock-rates = <80000000>;
> > +				fsl,clk-source = /bits/ 8 <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			flexcan4: can at 425f0000 {
> > +				compatible = "fsl,imx95-flexcan";
> > +				reg = <0x425f0000 0x10000>;
> > +				interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_CAN4>;
> > +				clock-names = "ipg", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN4>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> > +				assigned-clock-rates = <80000000>;
> > +				fsl,clk-source = /bits/ 8 <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			flexcan5: can at 42600000 {
> > +				compatible = "fsl,imx95-flexcan";
> > +				reg = <0x42600000 0x10000>;
> > +				interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_CAN5>;
> > +				clock-names = "ipg", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_CAN5>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1_DIV2>;
> > +				assigned-clock-rates = <80000000>;
> > +				fsl,clk-source = /bits/ 8 <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			sai2: sai at 42650000 {
> > +				compatible = "fsl,imx95-sai";
> > +				reg = <0x42650000 0x10000>;
> > +				interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> <&dummy>,
> > +					<&scmi_clk IMX94_CLK_SAI2>, <&dummy>,
> <&dummy>;
> > +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> > +				dmas = <&edma2 30 0 FSL_EDMA_RX>, <&edma2 29 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				#sound-dai-cells = <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			sai3: sai at 42660000 {
> > +				compatible = "fsl,imx95-sai";
> > +				reg = <0x42660000 0x10000>;
> > +				interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> <&dummy>,
> > +					<&scmi_clk IMX94_CLK_SAI3>, <&dummy>,
> <&dummy>;
> > +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> > +				dmas = <&edma2 32 0 FSL_EDMA_RX>, <&edma2 31 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				#sound-dai-cells = <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			sai4: sai at 42670000 {
> > +				compatible = "fsl,imx95-sai";
> > +				reg = <0x42670000 0x10000>;
> > +				interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> <&dummy>,
> > +					<&scmi_clk IMX94_CLK_SAI4>, <&dummy>,
> <&dummy>;
> > +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> > +				dmas = <&edma2 36 0 FSL_EDMA_RX>, <&edma2 35 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				#sound-dai-cells = <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart7: serial at 42690000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42690000 0x1000>;
> > +				interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART7>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma2 46 0 FSL_EDMA_RX>, <&edma2 45 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart8: serial at 426a0000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x426a0000 0x1000>;
> > +				interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART8>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma4 39 0 FSL_EDMA_RX>, <&edma4 38 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c5: i2c at 426b0000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x426b0000 0x10000>;
> > +				interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C5>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 37 0 0>, <&edma2 38 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c6: i2c at 426c0000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x426c0000 0x10000>;
> > +				interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C6>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 30 0 0>, <&edma4 31 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c7: i2c at 426d0000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x426d0000 0x10000>;
> > +				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C7>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 39 0 0>, <&edma2 40 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c8: i2c at 426e0000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x426e0000 0x10000>;
> > +				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C8>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 32 0 0>, <&edma4 33 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi5: spi at 426f0000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x426f0000 0x10000>;
> > +				interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI5>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 41 0 0>, <&edma2 42 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi6: spi at 42700000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x42700000 0x10000>;
> > +				interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI6>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 34 0 0>, <&edma4 35 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi7: spi at 42710000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x42710000 0x10000>;
> > +				interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI7>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma2 43 0 0>, <&edma2 44 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi8: spi at 42720000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x42720000 0x10000>;
> > +				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI8>,
> > +					 <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma4 36 0 0>, <&edma4 37 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			mu11: mailbox at 42730000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42730000 0x10000>;
> > +				interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			edma4: dma-controller at 42df0000 {
> > +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> > +				reg = <0x42df0000 0x210000>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "dma";
> > +				#dma-cells = <3>;
> > +				dma-channels = <64>;
> > +				interrupts-extended = <&a55_irqsteer 128>,
> <&a55_irqsteer 129>,
> > +					<&a55_irqsteer 130>, <&a55_irqsteer 131>,
> > +					<&a55_irqsteer 132>, <&a55_irqsteer 133>,
> > +					<&a55_irqsteer 134>, <&a55_irqsteer 135>,
> > +					<&a55_irqsteer 136>, <&a55_irqsteer 137>,
> > +					<&a55_irqsteer 138>, <&a55_irqsteer 139>,
> > +					<&a55_irqsteer 140>, <&a55_irqsteer 141>,
> > +					<&a55_irqsteer 142>, <&a55_irqsteer 143>,
> > +					<&a55_irqsteer 144>, <&a55_irqsteer 145>,
> > +					<&a55_irqsteer 146>, <&a55_irqsteer 147>,
> > +					<&a55_irqsteer 148>, <&a55_irqsteer 149>,
> > +					<&a55_irqsteer 150>, <&a55_irqsteer 151>,
> > +					<&a55_irqsteer 152>, <&a55_irqsteer 153>,
> > +					<&a55_irqsteer 154>, <&a55_irqsteer 155>,
> > +					<&a55_irqsteer 156>, <&a55_irqsteer 157>,
> > +					<&a55_irqsteer 158>, <&a55_irqsteer 159>,
> > +					<&a55_irqsteer 192>, <&a55_irqsteer 193>,
> > +					<&a55_irqsteer 194>, <&a55_irqsteer 195>,
> > +					<&a55_irqsteer 196>, <&a55_irqsteer 197>,
> > +					<&a55_irqsteer 198>, <&a55_irqsteer 199>,
> > +					<&a55_irqsteer 200>, <&a55_irqsteer 201>,
> > +					<&a55_irqsteer 202>, <&a55_irqsteer 203>,
> > +					<&a55_irqsteer 204>, <&a55_irqsteer 205>,
> > +					<&a55_irqsteer 206>, <&a55_irqsteer 207>,
> > +					<&a55_irqsteer 208>, <&a55_irqsteer 209>,
> > +					<&a55_irqsteer 210>, <&a55_irqsteer 211>,
> > +					<&a55_irqsteer 212>, <&a55_irqsteer 213>,
> > +					<&a55_irqsteer 214>, <&a55_irqsteer 215>,
> > +					<&a55_irqsteer 216>, <&a55_irqsteer 217>,
> > +					<&a55_irqsteer 218>, <&a55_irqsteer 219>,
> > +					<&a55_irqsteer 220>, <&a55_irqsteer 221>,
> > +					<&a55_irqsteer 222>, <&a55_irqsteer 223>,
> > +					<&gic GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
> > +			};
> > +		};
> > +
> > +		aips3: bus at 42800000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0 0x42800000 0 0x800000>;
> > +			ranges = <0x42800000 0x0 0x42800000 0x800000>,
> > +				 <0x28000000 0x0 0x28000000 0x1000000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			usdhc1: mmc at 42850000 {
> > +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> > +				reg = <0x42850000 0x10000>;
> > +				interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> > +					 <&scmi_clk IMX94_CLK_USDHC1>;
> > +				clock-names = "ipg", "ahb", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC1>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1>;
> > +				assigned-clock-rates = <400000000>;
> > +				bus-width = <8>;
> > +				fsl,tuning-start-tap = <1>;
> > +				fsl,tuning-step = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			usdhc2: mmc at 42860000 {
> > +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> > +				reg = <0x42860000 0x10000>;
> > +				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> > +					 <&scmi_clk IMX94_CLK_USDHC2>;
> > +				clock-names = "ipg", "ahb", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC2>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1>;
> > +				assigned-clock-rates = <200000000>;
> > +				bus-width = <4>;
> > +				fsl,tuning-start-tap = <1>;
> > +				fsl,tuning-step = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			usdhc3: mmc at 42880000 {
> > +				compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
> > +				reg = <0x42880000 0x10000>;
> > +				interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>,
> > +					 <&scmi_clk IMX94_CLK_WAKEUPAXI>,
> > +					 <&scmi_clk IMX94_CLK_USDHC3>;
> > +				clock-names = "ipg", "ahb", "per";
> > +				assigned-clocks = <&scmi_clk IMX94_CLK_USDHC3>;
> > +				assigned-clock-parents = <&scmi_clk
> IMX94_CLK_SYSPLL1_PFD1>;
> > +				assigned-clock-rates = <200000000>;
> > +				bus-width = <4>;
> > +				fsl,tuning-start-tap = <1>;
> > +				fsl,tuning-step = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart9: serial at 42a50000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42a50000 0x1000>;
> > +				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART10>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma2 51 0 FSL_EDMA_RX>, <&edma2 50 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart10: serial at 42a60000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42a60000 0x1000>;
> > +				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART10>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma4 47 0 FSL_EDMA_RX>, <&edma4 46 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart11: serial at 42a70000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42a70000 0x1000>;
> > +				interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART11>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma2 53 0 FSL_EDMA_RX>, <&edma2 52 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart12: serial at 42a80000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x42a80000 0x1000>;
> > +				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART12>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma4 49 0 FSL_EDMA_RX>, <&edma4 48 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			mu12: mailbox at 42ac0000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42ac0000 0x10000>;
> > +				interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu13: mailbox at 42ae0000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42ae0000 0x10000>;
> > +				interrupts = <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu14: mailbox at 42b00000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42b00000 0x10000>;
> > +				interrupts = <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu15: mailbox at 42b20000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42b20000 0x10000>;
> > +				interrupts = <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu16: mailbox at 42b40000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42b40000 0x10000>;
> > +				interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu17: mailbox at 42b60000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x42b60000 0x10000>;
> > +				interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +		};
> > +
> > +		gpio2: gpio at 43810000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43810000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 4 32>;
> > +		};
> > +
> > +		gpio3: gpio at 43820000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43820000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 36 26>;
> > +		};
> > +
> > +		gpio4: gpio at 43840000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43840000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 62 4>, <&scmi_iomuxc 4 0 4>,
> > +				      <&scmi_iomuxc 8 140 12>, <&scmi_iomuxc 20 164
> 12>;
> > +		};
> > +
> > +		gpio5: gpio at 43850000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43850000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 108 32>;
> > +		};
> > +
> > +		gpio6: gpio at 43860000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43860000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 66 32>;
> > +		};
> > +
> > +		gpio7: gpio at 43870000 {
> > +			compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
> > +			reg = <0x0 0x43870000 0x0 0x1000>;
> > +			#interrupt-cells = <2>;
> > +			interrupt-controller;
> > +			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
> > +				     <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
> > +			#gpio-cells = <2>;
> > +			gpio-controller;
> > +			gpio-ranges = <&scmi_iomuxc 0 98 10>, <&scmi_iomuxc 16 152
> 12>;
> > +		};
> > +
> > +		aips1: bus at 44000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x44000000 0x0 0x800000>;
> > +			ranges = <0x44000000 0x0 0x44000000 0x800000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			edma1: dma-controller at 44000000 {
> > +				compatible = "fsl,imx94-edma3", "fsl,imx93-edma3";
> > +				reg = <0x44000000 0x210000>;
> > +				interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "dma";
> > +				#dma-cells = <3>;
> > +				dma-channels = <32>;
> > +				status = "okay";
> > +			};
> > +
> > +			mu1: mailbox at 44220000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x44220000 0x10000>;
> > +				interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			system_counter: timer at 44290000 {
> > +				compatible = "nxp,imx95-sysctr-timer";
> > +				reg = <0x44290000 0x30000>;
> > +				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&osc_24m>;
> > +				clock-names = "per";
> > +				nxp,no-divider;
> > +			};
> > +
> > +			tpm1: pwm at 44310000 {
> > +				compatible = "fsl,imx7ulp-pwm";
> > +				reg = <0x44310000 0x1000>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				#pwm-cells = <3>;
> > +				status = "disabled";
> > +			};
> > +
> > +			tpm2: pwm at 44320000 {
> > +				compatible = "fsl,imx7ulp-pwm";
> > +				reg = <0x44320000 0x1000>;
> > +				clocks = <&scmi_clk IMX94_CLK_TPM2>;
> > +				#pwm-cells = <3>;
> > +				status = "disabled";
> > +			};
> > +
> > +			i3c1: i3c at 44330000 {
> > +				compatible = "silvaco,i3c-master-v1";
> > +				reg = <0x44330000 0x10000>;
> > +				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <3>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_I3C1SLOW>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>,
> > +					 <&dummy>;
> > +				clock-names = "pclk", "fast_clk", "slow_clk";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c1: i2c at 44340000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x44340000 0x10000>;
> > +				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C1>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma1 12 0 0>, <&edma1 13 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpi2c2: i2c at 44350000 {
> > +				compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
> > +				reg = <0x44350000 0x10000>;
> > +				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPI2C2>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma1 14 0 0>, <&edma1 15 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi1: spi at 44360000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x44360000 0x10000>;
> > +				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI2>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma1 16 0 0>, <&edma1 17 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpspi2: spi at 44370000 {
> > +				compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
> > +				reg = <0x44370000 0x10000>;
> > +				interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPSPI2>,
> > +					 <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "per", "ipg";
> > +				dmas = <&edma1 18 0 0>, <&edma1 19 0
> FSL_EDMA_RX>;
> > +				dma-names = "tx", "rx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart1: serial at 44380000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x44380000 0x1000>;
> > +				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART1>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma1 21 0 FSL_EDMA_RX>, <&edma1 20 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			lpuart2: serial at 44390000 {
> > +				compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
> > +					     "fsl,imx7ulp-lpuart";
> > +				reg = <0x44390000 0x1000>;
> > +				interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_LPUART2>;
> > +				clock-names = "ipg";
> > +				dmas = <&edma1 23 0 FSL_EDMA_RX>, <&edma1 22 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				status = "disabled";
> > +			};
> > +
> > +			flexcan1: can at 443a0000 {
> > +				compatible = "fsl,imx95-flexcan";
> > +				reg = <0x443a0000 0x10000>;
> > +				interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
> > +				status = "disabled";
> > +			};
> > +
> > +			sai1: sai at 443b0000 {
> > +				compatible = "fsl,imx95-sai";
> > +				reg = <0x443b0000 0x10000>;
> > +				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>, <&dummy>,
> > +					<&scmi_clk IMX94_CLK_SAI1>, <&dummy>,
> > +					<&dummy>, <&dummy>;
> > +				clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
> > +				dmas = <&edma1 25 0 FSL_EDMA_RX>, <&edma1 24 0
> 0>;
> > +				dma-names = "rx", "tx";
> > +				#sound-dai-cells = <0>;
> > +				status = "disabled";
> > +			};
> > +
> > +			adc1: adc at 44530000 {
> > +				compatible = "nxp,imx93-adc";
> > +				reg = <0x44530000 0x10000>;
> > +				interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_ADC>;
> > +				clock-names = "ipg";
> > +				#io-channel-cells = <1>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu2: mailbox at 445b0000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x445b0000 0x1000>;
> > +				ranges;
> > +				interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
> > +				#address-cells = <1>;
> > +				#size-cells = <1>;
> > +				#mbox-cells = <2>;
> > +
> > +				sram0: sram at 445b1000 {
> > +					compatible = "mmio-sram";
> > +					reg = <0x445b1000 0x400>;
> > +					ranges = <0x0 0x445b1000 0x400>;
> > +					#address-cells = <1>;
> > +					#size-cells = <1>;
> > +
> > +					scmi_buf0: scmi-sram-section at 0 {
> > +						compatible = "arm,scmi-shmem";
> > +						reg = <0x0 0x80>;
> > +					};
> > +
> > +					scmi_buf1: scmi-sram-section at 80 {
> > +						compatible = "arm,scmi-shmem";
> > +						reg = <0x80 0x80>;
> > +					};
> > +				};
> > +			};
> > +
> > +			mu3: mailbox at 445d0000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x445d0000 0x10000>;
> > +				interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu4: mailbox at 445f0000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x445f0000 0x10000>;
> > +				interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			mu6: mailbox at 44630000 {
> > +				compatible = "fsl,imx95-mu";
> > +				reg = <0x44630000 0x10000>;
> > +				interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
> > +				#mbox-cells = <2>;
> > +				status = "disabled";
> > +			};
> > +
> > +			a55_irqsteer: interrupt-controller at 446a0000 {
> > +				compatible = "fsl,imx-irqsteer";
> > +				reg = <0x446a0000 0x1000>;
> > +				#interrupt-cells = <1>;
> > +				interrupt-controller;
> > +				interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "ipg";
> > +				fsl,channel = <0>;
> > +				fsl,num-irqs = <960>;
> > +			};
> > +		};
> > +
> > +		aips4: bus at 49000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x49000000 0x0 0x800000>;
> > +			ranges = <0x49000000 0x0 0x49000000 0x800000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			wdog3: watchdog at 49220000 {
> > +				compatible = "fsl,imx93-wdt";
> > +				reg = <0x49220000 0x10000>;
> > +				interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				timeout-sec = <40>;
> > +				fsl,ext-reset-output;
> > +				status = "disabled";
> > +			};
> > +		};
> > +	};
> > +};
> > diff --git a/arch/arm64/boot/dts/freescale/imx943.dtsi
> > b/arch/arm64/boot/dts/freescale/imx943.dtsi
> > new file mode 100644
> > index 000000000000..a9877fcfd896
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/freescale/imx943.dtsi
> > @@ -0,0 +1,148 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#include "imx94.dtsi"
> > +
> > +/ {
> > +	cpus {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		idle-states {
> > +			entry-method = "psci";
> > +
> > +			cpu_pd_wait: cpu-pd-wait {
> > +				compatible = "arm,idle-state";
> > +				arm,psci-suspend-param = <0x0010033>;
> > +				local-timer-stop;
> > +				entry-latency-us = <1000>;
> > +				exit-latency-us = <700>;
> > +				min-residency-us = <2700>;
> > +				wakeup-latency-us = <1500>;
> > +			};
> > +		};
> > +
> > +		cpu0: cpu at 0 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x0>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l0>;
> > +		};
> > +
> > +		cpu1: cpu at 100 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x100>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l1>;
> > +		};
> > +
> > +		cpu2: cpu at 200 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x200>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l2>;
> > +		};
> > +
> > +		cpu3: cpu at 300 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x300>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l3>;
> > +		};
> > +
> > +		l2_cache_l0: l2-cache-l0 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l1: l2-cache-l1 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l2: l2-cache-l2 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l3: l2-cache-l3 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l3_cache: l3-cache {
> > +			compatible = "cache";
> > +			cache-size = <1048576>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <1024>;
> > +			cache-level = <3>;
> > +			cache-unified;
> > +		};
> > +	};
> > +};
> > --
> > 2.34.1
> >


From will at kernel.org  Tue Mar  4 16:38:08 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 5 Mar 2025 00:38:08 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <Z8c6enoolJe7Zeqk@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
 <Z8ZPBZF7J-qKdb_i@google.com>
 <20250304015633.GA30882@willie-the-truck>
 <Z8c6enoolJe7Zeqk@google.com>
Message-ID: <20250305003808.GA31667@willie-the-truck>

On Tue, Mar 04, 2025 at 05:38:02PM +0000, Sebastian Ene wrote:
> On Tue, Mar 04, 2025 at 01:56:35AM +0000, Will Deacon wrote:
> > On Tue, Mar 04, 2025 at 12:53:25AM +0000, Sebastian Ene wrote:
> > > On Mon, Mar 03, 2025 at 11:43:03PM +0000, Will Deacon wrote:
> > > > On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> > > > > Map the hypervisor's buffers irrespective to the host and return
> > > > > a linux error code from the FF-A error code on failure. Remove
> > > > > the unmap ff-a buffers calls from the hypervisor as it will
> > > > > never be called.
> > > > > Prevent the host from using FF-A directly with Trustzone
> > > > > if the hypervisor could not map its own buffers.
> > > > > 
> > > > > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > > > > ---
> > > > >  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
> > > > >  1 file changed, 17 insertions(+), 29 deletions(-)
> > > > 
> > > > [...]
> > > > 
> > > > > @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
> > > > >  {
> > > > >  	struct arm_smccc_res res;
> > > > >  	void *tx, *rx;
> > > > > +	int ret;
> > > > >  
> > > > >  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
> > > > >  		return 0;
> > > > > @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
> > > > >  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
> > > > >  	};
> > > > >  
> > > > > +	/* Map our hypervisor buffers into the SPMD */
> > > > > +	ret = ffa_map_hyp_buffers();
> > > > > +	if (ret)
> > > > > +		return ret;
> > > > 
> > > > Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
> > > > arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
> > > > the host to negotiate the version lazily?
> > > 
> > > We still have the same behaviour where we don't allow memory
> > > sharing to happen until the version is negotiated but this
> > > separates the hypervisor buffer mapping part from the host.
> > 
> > Sadly, the spec doesn't restrict this to the memory sharing calls:
> > 
> >   | [...] negotiation of the version must happen before an invocation of
> >   | any other FF-A ABI
> > 
> 
> We do that, as the hypervisor negotiates its own version in
> hyp_ffa_init.

hyp_ffa_init() only issues FFA_VERSION afaict, which is the one call
that you're allowed to make during negotiation. So the existing code is
fine.

> I think the host shouldn't be allowed to overwrite the
> hyp_ffa_version obtained from _init, this feels wrong as you
> can have a driver that forcefully downgrades the hypervisor to an old
> version.

I think that's also fine. The FFA code in the hypervisor exists solely
to proxy requests from the host; it's not used for anything else and so,
from the host's persective, FFA should behave identically to the case in
which the proxy is not present (e.g. if we were just using VHE). That
means that we're doing the right thing by deferring to the host for
version negotation.

Are you saying there's a bug in the current code if the host negotiates
the downgrade?

> We need to do three things, Sudeep & Will please correct me if I am
> wrong, but this is how I see it:
> 
> - the hypervisor should act as a separate entity (it has a different ID and
> in the current implementation we don't do a distinction between host/hyp) and
> it should be able to lock its own version from init.

I strongly disagree with that. The hypervisor isn't using FFA for
anything other than proxying the host and so we don't need to negotiate
a separate version.

What would we gain by doing this? Is there a bug with what we're doing
at the moment?

> - keep a separate version negotiated for the host
> - trap FFA_ID_GET from the host and return ID=1 because
>   currently we forward the call to the TZ and it returns the same ID
>   as the (hypervisor == 0).

Why is this beneficial? It just looks like complexity at EL2 for no gain
to me, but maybe I'm missing something.

Will


From will at kernel.org  Tue Mar  4 16:39:31 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 5 Mar 2025 00:39:31 +0000
Subject: [PATCH v2 1/4] KVM: arm64: Use the static initializer for the
 vesion lock
In-Reply-To: <20250227181750.3606372-2-sebastianene@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-2-sebastianene@google.com>
Message-ID: <20250305003931.GB31667@willie-the-truck>

On Thu, Feb 27, 2025 at 06:17:46PM +0000, Sebastian Ene wrote:
> Replace the definition of the hypervisor version lock
> with a static initializer.
> 
> Signed-off-by: Sebastian Ene <sebastianene at google.com>
> ---
>  arch/arm64/kvm/hyp/nvhe/ffa.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index e433dfab882a..6df6131f1107 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -69,7 +69,7 @@ static struct kvm_ffa_buffers hyp_buffers;
>  static struct kvm_ffa_buffers host_buffers;
>  static u32 hyp_ffa_version;
>  static bool has_version_negotiated;
> -static hyp_spinlock_t version_lock;
> +static DEFINE_HYP_SPINLOCK(version_lock);
>  
>  static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
>  {
> @@ -911,6 +911,5 @@ int hyp_ffa_init(void *pages)
>  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
>  	};
>  
> -	version_lock = __HYP_SPIN_LOCK_UNLOCKED;
>  	return 0;

nit: typo in the subject (s/vesion/version/).

With that fixed:

Acked-by: Will Deacon <will at kernel.org>

Will


From will at kernel.org  Tue Mar  4 16:45:23 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 5 Mar 2025 00:45:23 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <20250227181750.3606372-5-sebastianene@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
Message-ID: <20250305004522.GC31667@willie-the-truck>

On Thu, Feb 27, 2025 at 06:17:49PM +0000, Sebastian Ene wrote:
> Introduce the release FF-A call to notify Trustzone that the hypervisor
> has finished copying the data from the buffer shared with Trustzone to
> the non-secure partition.
> 
> Reported-by: Andrei Homescu <ahomescu at google.com>
> Signed-off-by: Sebastian Ene <sebastianene at google.com>
> ---
>  arch/arm64/kvm/hyp/nvhe/ffa.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 861f24de97cb..7da0203f1ee9 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -725,6 +725,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
>  	DECLARE_REG(u32, uuid3, ctxt, 4);
>  	DECLARE_REG(u32, flags, ctxt, 5);
>  	u32 count, partition_sz, copy_sz;
> +	struct arm_smccc_res _res;
>  
>  	hyp_spin_lock(&host_buffers.lock);
>  	if (!host_buffers.rx) {
> @@ -741,7 +742,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
>  
>  	count = res->a2;
>  	if (!count)
> -		goto out_unlock;
> +		goto release_rx;
>  
>  	if (hyp_ffa_version > FFA_VERSION_1_0) {
>  		/* Get the number of partitions deployed in the system */
> @@ -757,10 +758,12 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
>  	copy_sz = partition_sz * count;
>  	if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
>  		ffa_to_smccc_res(res, FFA_RET_ABORTED);
> -		goto out_unlock;
> +		goto release_rx;
>  	}
>  
>  	memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
> +release_rx:
> +	ffa_rx_release(&_res);

Hmm, the FFA spec is characteristically unclear as to whether or not we
need to release the rx buffer in the case that the flags indicate use of
the rx buffer but the returned partition count is 0.

Sudeep -- do you know what we should be doing in that case?

Will


From patchwork-bot+netdevbpf at kernel.org  Tue Mar  4 17:20:32 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Wed, 05 Mar 2025 01:20:32 +0000
Subject: [PATCH net v2] net: ethtool: netlink: Allow NULL nlattrs when getting
 a phy_device
In-Reply-To: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
References: <20250301141114.97204-1-maxime.chevallier@bootlin.com>
Message-ID: <174113763227.356990.18423879063180957214.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Sat,  1 Mar 2025 15:11:13 +0100 you wrote:
> ethnl_req_get_phydev() is used to lookup a phy_device, in the case an
> ethtool netlink command targets a specific phydev within a netdev's
> topology.
> 
> It takes as a parameter a const struct nlattr *header that's used for
> error handling :
> 
> [...]

Here is the summary with links:
  - [net,v2] net: ethtool: netlink: Allow NULL nlattrs when getting a phy_device
    https://git.kernel.org/netdev/net/c/637399bf7e77

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Tue Mar  4 17:20:39 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Wed, 05 Mar 2025 01:20:39 +0000
Subject: [PATCH net-next v2] dsa: mt7530: Utilize REGMAP_IRQ for interrupt
 handling
In-Reply-To: <221013c3530b61504599e285c341a993f6188f00.1740792674.git.daniel@makrotopia.org>
References: <221013c3530b61504599e285c341a993f6188f00.1740792674.git.daniel@makrotopia.org>
Message-ID: <174113763901.356990.6788752081470910551.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Sat, 1 Mar 2025 01:41:18 +0000 you wrote:
> Replace the custom IRQ chip handler and mask/unmask functions with
> REGMAP_IRQ. This significantly simplifies the code and allows for the
> removal of almost all interrupt-related functions from mt7530.c.
> 
> Tested on MT7988A built-in switch (MMIO) as well as MT7531AE IC (MDIO).
> 
> Signed-off-by: Daniel Golle <daniel at makrotopia.org>
> 
> [...]

Here is the summary with links:
  - [net-next,v2] dsa: mt7530: Utilize REGMAP_IRQ for interrupt handling
    https://git.kernel.org/netdev/net-next/c/254f6b272e3b

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From menglong8.dong at gmail.com  Tue Mar  4 17:19:09 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Wed, 5 Mar 2025 09:19:09 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
Message-ID: <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>

On Tue, Mar 4, 2025 at 10:53?PM H. Peter Anvin <hpa at zytor.com> wrote:
>
> On March 4, 2025 1:42:20 AM PST, Peter Zijlstra <peterz at infradead.org> wrote:
> >On Tue, Mar 04, 2025 at 03:47:45PM +0800, Menglong Dong wrote:
> >> We don't have to select FUNCTION_ALIGNMENT_32B, so the
> >> worst case is to increase ~2.2%.
> >>
> >> What do you think?
> >
> >Well, since I don't understand what you need this for at all, I'm firmly
> >on the side of not doing this.
> >
> >What actual problem is being solved with this meta data nonsense? Why is
> >it worth blowing up our I$ footprint over.
> >
> >Also note, that if you're going to be explaining this, start from
> >scratch, as I have absolutely 0 clues about BPF and such.
>
> I would appreciate such information as well. The idea seems dubious on the surface.

Ok, let me explain it from the beginning. (My English is not good,
but I'll try to describe it as clear as possible :/)

Many BPF program types need to depend on the BPF trampoline,
such as BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_EXT,
BPF_PROG_TYPE_LSM, etc. BPF trampoline is a bridge between
the kernel (or bpf) function and BPF program, and it acts just like the
trampoline that ftrace uses.

Generally speaking, it is used to hook a function, just like what ftrace
do:

foo:
    endbr
    nop5  -->  call trampoline_foo
    xxxx

In short, the trampoline_foo can be this:

trampoline_foo:
    prepare a array and store the args of foo to the array
    call fentry_bpf1
    call fentry_bpf2
    ......
    call foo+4 (origin call)
    save the return value of foo
    call fexit_bpf1 (this bpf can get the return value of foo)
    call fexit_bpf2
    .......
    return to the caller of foo

We can see that the trampoline_foo can be only used for
the function foo, as different kernel function can be attached
different BPF programs, and have different argument count,
etc. Therefore, we have to create 1000 BPF trampolines if
we want to attach a BPF program to 1000 kernel functions.

The creation of the BPF trampoline is expensive. According to
my testing, It will spend more than 1 second to create 100 bpf
trampoline. What's more, it consumes more memory.

If we have the per-function metadata supporting, then we can
create a global BPF trampoline, like this:

trampoline_global:
    prepare a array and store the args of foo to the array
    get the metadata by the ip
    call metadata.fentry_bpf1
    call metadata.fentry_bpf2
    ....
    call foo+4 (origin call)
    save the return value of foo
    call metadata.fexit_bpf1 (this bpf can get the return value of foo)
    call metadata.fexit_bpf2
    .......
    return to the caller of foo

(The metadata holds more information for the global trampoline than
I described.)

Then, we don't need to create a trampoline for every kernel function
anymore.

Another beneficiary can be ftrace. For now, all the kernel functions that
are enabled by dynamic ftrace will be added to a filter hash if there are
more than one callbacks. And hash lookup will happen when the traced
functions are called, which has an impact on the performance, see
__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
metadata supporting, we can store the information that if the callback is
enabled on the kernel function to the metadata, which can make the performance
much better.

The per-function metadata storage is a basic function, and I think there
may be other functions that can use it for better performance in the feature
too.

(Hope that I'm describing it clearly :/)

Thanks!
Menglong Dong


From ping.bai at nxp.com  Tue Mar  4 17:22:07 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Wed, 5 Mar 2025 01:22:07 +0000
Subject: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <9581e376-19b2-4d4e-ad81-cc24e39e9d33@kernel.org>
References: <20250304093127.1954549-1-ping.bai@nxp.com>
 <20250304093127.1954549-4-ping.bai@nxp.com>
 <9581e376-19b2-4d4e-ad81-cc24e39e9d33@kernel.org>
Message-ID: <AS8PR04MB8642F0234301B23206E78A0287CB2@AS8PR04MB8642.eurprd04.prod.outlook.com>

Hi Krzysztof,

> Subject: Re: [PATCH v2 3/4] arm64: dts: freescale: Add basic dtsi for imx943
> 
> On 04/03/2025 10:31, Jacky Bai wrote:
> > Add the minimal dtsi support for i.MX943. i.MX943 is the first SoC of
> > i.MX94 Family, create a common dtsi for the whole i.MX94 family, and
> > the specific dtsi part for i.MX943.
> >
> > The clock, power domain and perf index need to be used by the device
> > nodes for resource reference, add them along with the dtsi support.
> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - remove the unnecessary macro define in clock header as suggested by
> Krzysztof
> >   - split the dtsi into imx94.dtsi and imx943.dtsi
> >   - use low case in the pinfunc header as Frank suggested
> >   - reorder the device nodes and properties
> >   - resolve Krzysztof's other comments
> 
> Which ones? Be specific.
> 

Thank you for review, Will improve this in v3. 

> Based on last issue, I don't think you implemented comments.
> 

For the compatible string, really need your suggestions :)
Is it a hard requirement that each time when we add a new soc, we must
add new compatible for the reused IPs even if the new compatible may
not be used?

BR
> 
> > +
> > +			a55_irqsteer: interrupt-controller at 446a0000 {
> > +				compatible = "fsl,imx-irqsteer";
> > +				reg = <0x446a0000 0x1000>;
> > +				#interrupt-cells = <1>;
> > +				interrupt-controller;
> > +				interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
> > +					     <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSAON>;
> > +				clock-names = "ipg";
> > +				fsl,channel = <0>;
> > +				fsl,num-irqs = <960>;
> > +			};
> > +		};
> > +
> > +		aips4: bus at 49000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x49000000 0x0 0x800000>;
> > +			ranges = <0x49000000 0x0 0x49000000 0x800000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			wdog3: watchdog at 49220000 {
> > +				compatible = "fsl,imx93-wdt";
> 
> imx93 or imx95, like in other places? And the commit msg says imx943.
> 
> I already asked for that.
> 
> > +				reg = <0x49220000 0x10000>;
> > +				interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				timeout-sec = <40>;
> > +				fsl,ext-reset-output;
> > +				status = "disabled";
> > +			};
> > +		};
> Best regards,
> Krzysztof

From quic_jiegan at quicinc.com  Tue Mar  4 17:34:56 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 5 Mar 2025 09:34:56 +0800
Subject: [PATCH v15 04/10] Coresight: Introduce a new struct
 coresight_path
In-Reply-To: <4e0959e7-cb66-41f1-b686-a274b6cbfd2e@arm.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-5-quic_jiegan@quicinc.com>
 <4e0959e7-cb66-41f1-b686-a274b6cbfd2e@arm.com>
Message-ID: <bb2f4a5d-1a93-4637-908d-316516213061@quicinc.com>



On 3/5/2025 12:10 AM, Suzuki K Poulose wrote:
> On 03/03/2025 03:29, Jie Gan wrote:
>> Introduce a new strcuture, 'struct coresight_path', to store the data 
>> that
>> utilized by the devices in the path. The coresight_path will be built/ 
>> released
>> by coresight_build_path/coresight_release_path functions.
>>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>> ? drivers/hwtracing/coresight/coresight-core.c? | 16 +++++-----
>> ? .../hwtracing/coresight/coresight-etm-perf.c? | 30 ++++++++++---------
>> ? .../hwtracing/coresight/coresight-etm-perf.h? |? 2 +-
>> ? drivers/hwtracing/coresight/coresight-priv.h? |? 6 ++--
>> ? drivers/hwtracing/coresight/coresight-sysfs.c | 12 ++++----
>> ? include/linux/coresight.h???????????????????? | 10 +++++++
>> ? 6 files changed, 44 insertions(+), 32 deletions(-)
>>
> 
> ...
> 
>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>> index ce9a5e71b261..67cf8bdbe5c0 100644
>> --- a/include/linux/coresight.h
>> +++ b/include/linux/coresight.h
>> @@ -329,6 +329,16 @@ static struct coresight_dev_list (var) = 
>> {??????????????? \
>> ? #define to_coresight_device(d) container_of(d, struct 
>> coresight_device, dev)
>> +/**
>> + * struct coresight_path - data needed by enable/disable path
>> + * @path:????????????? path from source to sink.
> 
> This doesn't match the actual variable below.

Hi Suzuki,

Very sorry for the mistake. I should spot it in advance. I will take 
care and enhance the self-checking process in the future.

Jie

> 
>> + * @trace_id:????????? trace_id of the whole path.
>> + */
>> +struct coresight_path {
>> +??? struct list_head??? path_list;
>> +??? u8??????????? trace_id;
>> +};
>> +
>> ? enum cs_mode {
>> ????? CS_MODE_DISABLED,
>> ????? CS_MODE_SYSFS,
> 
> Suzuki



From quic_jiegan at quicinc.com  Tue Mar  4 17:37:12 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 5 Mar 2025 09:37:12 +0800
Subject: [PATCH v15 05/10] Coresight: Allocate trace ID after building the
 path
In-Reply-To: <8efe6176-44a2-4b3d-b9b5-855b26f00187@arm.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-6-quic_jiegan@quicinc.com>
 <8efe6176-44a2-4b3d-b9b5-855b26f00187@arm.com>
Message-ID: <25fadd59-e728-4fc0-9441-e9630c8c64cb@quicinc.com>



On 3/4/2025 10:58 PM, Suzuki K Poulose wrote:
> On 03/03/2025 03:29, Jie Gan wrote:
>> The trace_id will be stored in coresight_path instead of being declared
>> everywhere and allocated after building the path.
>>
>> Co-developed-by: James Clark <james.clark at linaro.org>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>> ? drivers/hwtracing/coresight/coresight-core.c? | 44 +++++++++++++++++++
>> ? .../hwtracing/coresight/coresight-etm-perf.c? |? 5 +--
>> ? drivers/hwtracing/coresight/coresight-priv.h? |? 2 +
>> ? drivers/hwtracing/coresight/coresight-sysfs.c |? 4 ++
>> ? 4 files changed, 52 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index ed0e9368324d..6adc06995d76 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -655,6 +655,50 @@ static void coresight_drop_device(struct 
>> coresight_device *csdev)
>> ????? }
>> ? }
>> +/*
>> + * coresight device will read their existing or alloc a trace ID, if 
>> their trace_id
>> + * callback is set.
>> + *
>> + * Return 0 if the trace_id callback is not set.
>> + * Return the result of the trace_id callback if it is set. The 
>> return value
>> + * will be the trace_id if successful, and an error number if it fails.
>> + */
>> +static int coresight_get_trace_id(struct coresight_device *csdev,
>> +????????????????? enum cs_mode mode,
>> +????????????????? struct coresight_device *sink)
>> +{
>> +??? if (coresight_ops(csdev)->trace_id)
>> +??????? return coresight_ops(csdev)->trace_id(csdev, mode, sink);
>> +
>> +??? return 0;
>> +}
>> +
>> +/*
>> + * Call this after creating the path and before enabling it. This leaves
>> + * the trace ID set on the path, or it remains 0 if it couldn't be 
>> assigned.
>> + */
>> +void coresight_path_assign_trace_id(struct coresight_path *path,
>> +??????????????????? enum cs_mode mode)
>> +{
>> +??? struct coresight_device *sink = coresight_get_sink(&path- 
>> >path_list);
>> +??? struct coresight_node *nd;
>> +??? int trace_id;
>> +
>> +??? list_for_each_entry(nd, &path->path_list, link) {
>> +??????? /* Assign a trace ID to the path for the first device that 
>> wants to do it */
>> +??????? trace_id = coresight_get_trace_id(nd->csdev, mode, sink);
>> +
>> +??????? /*
>> +???????? * 0 in this context is that it didn't want to assign so keep 
>> searching.
>> +???????? * Non 0 is either success or fail.
>> +??????? */
> 
> checkpatch complains:
> 
> WARNING: Block comments should align the * on each line
> #65: FILE: drivers/hwtracing/coresight/coresight-core.c:694:
> +??????????????? * Non 0 is either success or fail.
> +?????????????? */
> 
> 
> Please make sure to run the checkpatch on individual patches before 
> submitting in the future. I will fix this up locally for now.
> 
> Kind regards
> Suzuki
> 

Hi Suzuki,

Sure. Thanks for help to deal with the error this time. I will take care 
in future.

Jie

> 
> 
>> +??????? if (trace_id != 0) {
>> +??????????? path->trace_id = trace_id;
>> +??????????? return;
>> +??????? }
>> +??? }
>> +}
>> +
>> ? /**
>> ?? * _coresight_build_path - recursively build a path from a @csdev to 
>> a sink.
>> ?? * @csdev:??? The device to start from.
>> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/ 
>> drivers/hwtracing/coresight/coresight-etm-perf.c
>> index b0426792f08a..134290ab622e 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
>> @@ -319,7 +319,6 @@ static void *etm_setup_aux(struct perf_event 
>> *event, void **pages,
>> ? {
>> ????? u32 id, cfg_hash;
>> ????? int cpu = event->cpu;
>> -??? int trace_id;
>> ????? cpumask_t *mask;
>> ????? struct coresight_device *sink = NULL;
>> ????? struct coresight_device *user_sink = NULL, *last_sink = NULL;
>> @@ -409,8 +408,8 @@ static void *etm_setup_aux(struct perf_event 
>> *event, void **pages,
>> ????????? }
>> ????????? /* ensure we can allocate a trace ID for this CPU */
>> -??????? trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink- 
>> >perf_sink_id_map);
>> -??????? if (!IS_VALID_CS_TRACE_ID(trace_id)) {
>> +??????? coresight_path_assign_trace_id(path, CS_MODE_PERF);
>> +??????? if (!IS_VALID_CS_TRACE_ID(path->trace_id)) {
>> ????????????? cpumask_clear_cpu(cpu, mask);
>> ????????????? coresight_release_path(path);
>> ????????????? continue;
>> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/ 
>> hwtracing/coresight/coresight-priv.h
>> index 27b7dc348d4a..2bea35bae0d4 100644
>> --- a/drivers/hwtracing/coresight/coresight-priv.h
>> +++ b/drivers/hwtracing/coresight/coresight-priv.h
>> @@ -152,6 +152,8 @@ int coresight_make_links(struct coresight_device 
>> *orig,
>> ? void coresight_remove_links(struct coresight_device *orig,
>> ????????????????? struct coresight_connection *conn);
>> ? u32 coresight_get_sink_id(struct coresight_device *csdev);
>> +void coresight_path_assign_trace_id(struct coresight_path *path,
>> +?????????????????? enum cs_mode mode);
>> ? #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
>> ? extern int etm_readl_cp14(u32 off, unsigned int *val);
>> diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/ 
>> hwtracing/coresight/coresight-sysfs.c
>> index cb4c39732d26..d03751bf3d8a 100644
>> --- a/drivers/hwtracing/coresight/coresight-sysfs.c
>> +++ b/drivers/hwtracing/coresight/coresight-sysfs.c
>> @@ -209,6 +209,10 @@ int coresight_enable_sysfs(struct 
>> coresight_device *csdev)
>> ????????? goto out;
>> ????? }
>> +??? coresight_path_assign_trace_id(path, CS_MODE_SYSFS);
>> +??? if (!IS_VALID_CS_TRACE_ID(path->trace_id))
>> +??????? goto err_path;
>> +
>> ????? ret = coresight_enable_path(&path->path_list, CS_MODE_SYSFS, NULL);
>> ????? if (ret)
>> ????????? goto err_path;
> 



From quic_jiegan at quicinc.com  Tue Mar  4 17:39:45 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 5 Mar 2025 09:39:45 +0800
Subject: [PATCH v15 09/10] Coresight: Add Coresight TMC Control Unit
 driver
In-Reply-To: <1b05e832-6d41-463a-a52a-6ff340d0d6f8@arm.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-10-quic_jiegan@quicinc.com>
 <1b05e832-6d41-463a-a52a-6ff340d0d6f8@arm.com>
Message-ID: <2ab83252-fe17-489c-b103-28ce769123a3@quicinc.com>



On 3/4/2025 10:59 PM, Suzuki K Poulose wrote:
> On 03/03/2025 03:29, Jie Gan wrote:
>> The Coresight TMC Control Unit hosts miscellaneous configuration 
>> registers
>> which control various features related to TMC ETR sink.
>>
>> Based on the trace ID, which is programmed in the related CTCU ATID
>> register of a specific ETR, trace data with that trace ID gets into
>> the ETR buffer, while other trace data gets dropped.
>>
>> Enabling source device sets one bit of the ATID register based on
>> source device's trace ID.
>> Disabling source device resets the bit according to the source
>> device's trace ID.
>>
>> Reviewed-by: James Clark <james.clark at linaro.org>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> 
> ...
> 
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
>> @@ -0,0 +1,39 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All 
>> rights reserved.
>> + */
>> +
>> +#ifndef _CORESIGHT_CTCU_H
>> +#define _CORESIGHT_CTCU_H
>> +#include "coresight-trace-id.h"
>> +
>> +/* Maximum number of supported ETR devices for a single CTCU. */
>> +#define ETR_MAX_NUM???? 2
>> +
> 
> WARNING: please, no space before tabs
> #413: FILE: drivers/hwtracing/coresight/coresight-ctcu.h:11:
> +#define ETR_MAX_NUM ^I2$
> 
> total: 0 errors, 2 warnings, 397 lines checked
> 
> Another checkpatch warning. Please take care in the future.
> 
> Suzuki

Hi Suzuki,

Got it. Will take care in the future. Thanks for help to deal with them 
this time.

Jie

> 
> 



From kuba at kernel.org  Tue Mar  4 17:58:34 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Tue, 4 Mar 2025 17:58:34 -0800
Subject: [PATCH v8 net-next 00/15] bridge-fastpath and related
 improvements
In-Reply-To: <20250228201533.23836-1-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
Message-ID: <20250304175834.4306c670@kernel.org>

On Fri, 28 Feb 2025 21:15:18 +0100 Eric Woudstra wrote:
> This patchset makes it possible to set up a software fastpath between
> bridged interfaces. One patch adds the flow rule for the hardware
> fastpath. This creates the possibility to have a hardware offloaded
> fastpath between bridged interfaces. More patches are added to solve
> issues found with the existing code.

For some reason this series didn't get ingested by patchwork correctly.
Instead of reposting for net-next maybe lets use this opportunity to
resend to netfilter instead? Looks like we have some acks from Nik but
none from Pablo.
-- 
pw-bot: cr


From ming.qian at oss.nxp.com  Tue Mar  4 18:25:13 2025
From: ming.qian at oss.nxp.com (ming.qian at oss.nxp.com)
Date: Wed,  5 Mar 2025 10:25:13 +0800
Subject: [PATCH] media: imx-jpeg: Drop the first error frames
Message-ID: <20250305022513.2312731-1-ming.qian@oss.nxp.com>

From: Ming Qian <ming.qian at oss.nxp.com>

When an output buffer contains error frame header,
v4l2_jpeg_parse_header() will return error, then driver will mark this
buffer and a capture buffer done with error flag in device_run().

But if the error occurs in the first frames, before setup the capture
queue, there is no chance to schedule device_run(), and there may be no
capture to mark error.

So we need to drop this buffer with error flag, and make the decoding
can continue.

Signed-off-by: Ming Qian <ming.qian at oss.nxp.com>
---
 drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 1221b309a916..0e6ee997284b 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1921,6 +1921,15 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
 	if (ret)
 		jpeg_src_buf->jpeg_parse_error = true;
 
+	/*
+	 * if the capture queue is not setup, the device_run() won't be scheduled,
+	 * need to drop the error buffer, so that the decoding can continue
+	 */
+	if (jpeg_src_buf->jpeg_parse_error &&
+	    !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx))) {
+		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		return;
+	}
 end:
 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 }
-- 
2.43.0-rc1



From dmitry.baryshkov at linaro.org  Tue Mar  4 18:37:38 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:37:38 +0200
Subject: [PATCH v2 4/9] phy: qcom: qmp-combo: Add new PHY sequences for
 SM8750
In-Reply-To: <20250304-sm8750_usb_master-v2-4-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-4-a698a2e68e06@quicinc.com>
Message-ID: <jr4lvgumvnjhybvwuo7crpjhaogjvet2d7llt65qzstjnoekuj@zx6z3npa37xg>

On Tue, Mar 04, 2025 at 01:56:37PM -0800, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> Add new register offsets and PHY values for SM8750. Some of the previous
> definitions can be leveraged from older PHY versions as offsets within
> registers have not changed. This also updates the PHY sequence that is
> recommended after running hardware characterization.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-qmp-combo.c          | 221 +++++++++++++++++++++
>  drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h     |  38 ++++
>  drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h         |  32 +++
>  drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h |  64 ++++++
>  .../phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h    |  68 +++++++
>  drivers/phy/qualcomm/phy-qcom-qmp.h                |   5 +
>  6 files changed, 428 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Tue Mar  4 18:38:55 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:38:55 +0200
Subject: [PATCH v2 5/9] phy: qcom: Update description for QCOM based
 eUSB2 repeater
In-Reply-To: <20250304-sm8750_usb_master-v2-5-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-5-a698a2e68e06@quicinc.com>
Message-ID: <6e742b2dke3pcqq3v6nzs3gfvwau4sk4gtadzgca2zk5merzvi@ubc6l3hsafok>

On Tue, Mar 04, 2025 at 01:56:38PM -0800, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> The eUSB2 repeater that exists in the QCOM PMICs are utilized for several
> different eUSB2 PHY vendors, such as M31 or Synopsys.  Hence, the wording
> needs to be updated to remove associations to a specific vendor.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  drivers/phy/qualcomm/Kconfig | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From ebiggers at kernel.org  Tue Mar  4 18:40:20 2025
From: ebiggers at kernel.org (Eric Biggers)
Date: Tue, 4 Mar 2025 18:40:20 -0800
Subject: [PATCH 4/6] scsi: ufs: exynos: Enable PRDT pre-fetching with
 UFSHCD_CAP_CRYPTO
In-Reply-To: <20250226220414.343659-5-peter.griffin@linaro.org>
References: <20250226220414.343659-1-peter.griffin@linaro.org>
 <20250226220414.343659-5-peter.griffin@linaro.org>
Message-ID: <20250305024020.GC20133@sol.localdomain>

On Wed, Feb 26, 2025 at 10:04:12PM +0000, Peter Griffin wrote:
> PRDT_PREFETCH_ENABLE[31] bit should be set when desctype field of
> fmpsecurity0 register is type2 (double file encryption) or type3
> (file and disk excryption). Setting this bit enables PRDT
> pre-fetching on both TXPRDT and RXPRDT.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>

I assume you mean that desctype 3 provides "support for file and disk
encryption"?  The driver does use desctype 3, but it only uses the "file
encryption".  So this confused me a bit.  (BTW, in FMP terminology, "file
encryption" seems to mean "use the key provided in the I/O request", and "disk
encryption" seems to mean "use some key the firmware provided somehow".  They
can be cascaded, and the intended use cases are clearly file and disk encryption
respectively, but they don't necessarily have to be used that way.)

- Eric


From dmitry.baryshkov at linaro.org  Tue Mar  4 18:45:42 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:45:42 +0200
Subject: [PATCH v2 6/9] phy: qcom: Add M31 based eUSB2 PHY driver
In-Reply-To: <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>
Message-ID: <dfpqg6u7kdvurgajufaldvpdxhe2pawmgum6ngtbbstdxrngwx@i2masto6nnwk>

On Tue, Mar 04, 2025 at 01:56:39PM -0800, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> SM8750 utilizes an eUSB2 PHY from M31.  Add the initialization
> sequences to bring it out of reset and into an operational state.  This
> differs to the M31 USB driver, in that the M31 eUSB2 driver will
> require a connection to an eUSB2 repeater.  This PHY driver will handle
> the initialization of the associated eUSB2 repeater when required.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  drivers/phy/qualcomm/Kconfig              |  10 +
>  drivers/phy/qualcomm/Makefile             |   1 +
>  drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 296 ++++++++++++++++++++++++++++++
>  3 files changed, 307 insertions(+)
> 

[...]

> +
> +static int msm_m31_eusb2_write_readback(void __iomem *base, u32 offset,

m31eusb2_phy_write_readback()

> +					const u32 mask, u32 val)
> +{
> +	u32 write_val;
> +	u32 tmp;
> +

[..]

> +
> +static const struct phy_ops m31eusb2_phy_gen_ops = {
> +	.init	= m31eusb2_phy_init,
> +	.exit	= m31eusb2_phy_exit,
> +	.owner		= THIS_MODULE,

Strange alignment

> +};
> +

[...]

> +
> +	phy->phy = devm_phy_create(dev, NULL, &m31eusb2_phy_gen_ops);
> +	if (IS_ERR(phy->phy))
> +		return dev_err_probe(dev, PTR_ERR(phy->phy),
> +				     "failed to create phy\n");
> +
> +	for (i = 0; i < M31_EUSB_NUM_VREGS; i++)
> +		phy->vregs[i].supply = m31_eusb_phy_vreg_names[i];
> +
> +	ret = devm_regulator_bulk_get(dev, M31_EUSB_NUM_VREGS, phy->vregs);

devm_regulator_bulk_get_const()

> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				"failed to get regulator supplies\n");
> +
> +

[..]

> +MODULE_DESCRIPTION("eUSB2 Qualcomm M31 HSPHY driver");
> +MODULE_LICENSE("GPL");

MODULE_AUTHOR()?

> 
> -- 
> 2.46.1
> 

-- 
With best wishes
Dmitry


From andyshrk at 163.com  Tue Mar  4 18:55:17 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 5 Mar 2025 10:55:17 +0800 (CST)
Subject: [PATCH v3 0/3] Add display subsystem dt node on rk3576
In-Reply-To: <2627393.Mh6RI2rZIc@diego>
References: <20241231095728.253943-1-andyshrk@163.com>
 <173564980410.21979.2947276365464229762.robh@kernel.org>
 <lfmhqurnpjmfy6pfjxd5aczxujislv2p5bsurcbl7capyt7zv3@hy2twvjj53uz>
 <2627393.Mh6RI2rZIc@diego>
Message-ID: <c9c0a4a.3247.195643a9a86.Coremail.andyshrk@163.com>


Hello,

? 2025-03-05 05:16:49?"Heiko St?bner" <heiko at sntech.de> ???
>Am Dienstag, 4. M?rz 2025, 15:47:28 MEZ schrieb Sebastian Reichel:
>> Hello,
>> 
>> On Tue, Dec 31, 2024 at 06:57:21AM -0600, Rob Herring (Arm) wrote:
>> > On Tue, 31 Dec 2024 17:57:17 +0800, Andy Yan wrote:
>> > > As the VOP[0] and HDMI[1] driver have already been submitted for review.
>> > > This series enable hdmi display on sige5 board.
>> > > 
>> > > [0] https://lore.kernel.org/linux-rockchip/20241231090802.251787-1-andyshrk at 163.com/T/#t
>> > > [1] https://lore.kernel.org/linux-rockchip/20241231094425.253398-1-andyshrk at 163.com/T/#t
>> > > 
>> > > Changes in v3:
>> > > - Split from https://lore.kernel.org/linux-rockchip/3330586.aeNJFYEL58 at diego/T/#t
>> > > 
>> > > Andy Yan (3):
>> > >   arm64: dts: rockchip: Add vop for rk3576
>> > >   arm64: dts: rockchip: Add hdmi for rk3576
>> > >   arm64: dts: rockchip: Enable hdmi display on sige5
>> > > 
>> > >  .../boot/dts/rockchip/rk3576-armsom-sige5.dts |  47 +++++++
>> > >  arch/arm64/boot/dts/rockchip/rk3576.dtsi      | 126 ++++++++++++++++++
>> > >  2 files changed, 173 insertions(+)
>> >
>> > [...] (a bunch of warnings due to dependency patch series not yet
>> > being in linux-next)
>> 
>> I think all dependencies have landed now. But it might be sensible
>> to do a quick resend considering how old this is.
>> 
>> Would be nice to have initial RK3576 HDMI support in 6.15 :)
>
>now we can :-)
>
>The update was not that difficult, so did it myself when applying.

Thanks for you all, many thanks.
I also sent out a patch for eanble hdmi on rk3576 evb1.


>
>
>Heiko
>
>

From dmitry.baryshkov at linaro.org  Tue Mar  4 18:57:50 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:57:50 +0200
Subject: [PATCH v2 7/9] arm64: dts: qcom: sm8750: Add USB support to
 SM8750 SoCs
In-Reply-To: <20250304-sm8750_usb_master-v2-7-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-7-a698a2e68e06@quicinc.com>
Message-ID: <qr5vsq5b4pf5po3uq4esrozfjkmzq5q55tqlxxc74fh2pcygzi@vb7txcm5wpst>

On Tue, Mar 04, 2025 at 01:56:40PM -0800, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> Add the base USB devicetree definitions for SM8750 platforms.  The overall
> chipset contains a single DWC3 USB3 controller (rev. 200a), SS QMP PHY
> (rev. v8) and M31 eUSB2 PHY.  The major difference for SM8750 is the
> transition to using the M31 eUSB2 PHY compared to previous SoCs.
> 
> Enable USB support on SM8750 MTP and QRD variants. SM8750 has a QMP combo
> PHY for the SSUSB path, and a M31 eUSB2 PHY for the HSUSB path.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/sm8750.dtsi | 163 +++++++++++++++++++++++++++++++++++
>  1 file changed, 163 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi
> index 3bbd7d18598ee0a3a0d5130c03a3166e1fc14d82..e543e65c7aba3213ca0b8a8f6dbaf1371ed8317e 100644
> --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi
> @@ -10,6 +10,7 @@
>  #include <dt-bindings/interconnect/qcom,icc.h>
>  #include <dt-bindings/interconnect/qcom,sm8750-rpmh.h>
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/phy/phy-qcom-qmp.h>
>  #include <dt-bindings/power/qcom,rpmhpd.h>
>  #include <dt-bindings/power/qcom-rpmpd.h>
>  #include <dt-bindings/soc/qcom,rpmh-rsc.h>
> @@ -1966,6 +1967,168 @@ lpass_lpicx_noc: interconnect at 7420000 {
>  			#interconnect-cells = <2>;
>  		};
>  
> +		usb_1_hsphy: phy at 88e3000 {
> +			compatible = "qcom,sm8750-m31-eusb2-phy";
> +			reg = <0x0 0x88e3000 0x0 0x29c>;
> +
> +			clocks = <&tcsrcc TCSR_USB2_CLKREF_EN>;
> +			clock-names = "ref";
> +
> +			resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
> +
> +			#phy-cells = <0>;
> +
> +			status = "disabled";
> +		};
> +
> +		usb_dp_qmpphy: phy at 88e8000 {
> +			compatible = "qcom,sm8750-qmp-usb3-dp-phy";
> +			reg = <0x0 0x088e8000 0x0 0x4000>;
> +
> +			clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
> +				 <&rpmhcc RPMH_CXO_CLK>,
> +				 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
> +				 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
> +			clock-names = "aux",
> +				      "ref",
> +				      "com_aux",
> +				      "usb3_pipe";
> +
> +			resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
> +				 <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
> +			reset-names = "phy",
> +				      "common";
> +
> +			power-domains = <&gcc GCC_USB3_PHY_GDSC>;
> +
> +			#clock-cells = <1>;
> +			#phy-cells = <1>;
> +
> +			orientation-switch;
> +
> +			status = "disabled";
> +
> +			ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				port at 0 {
> +					reg = <0>;
> +
> +					usb_dp_qmpphy_out: endpoint {
> +					};
> +				};
> +
> +				port at 1 {
> +					reg = <1>;
> +
> +					usb_dp_qmpphy_usb_ss_in: endpoint {
> +						remote-endpoint = <&usb_1_dwc3_ss>;
> +					};
> +				};
> +
> +				port at 2 {
> +					reg = <2>;
> +
> +					usb_dp_qmpphy_dp_in: endpoint {
> +					};
> +				};
> +			};
> +		};
> +
> +		usb_1: usb at a6f8800 {
> +			compatible = "qcom,sm8750-dwc3", "qcom,dwc3";
> +			reg = <0x0 0x0a6f8800 0x0 0x400>;
> +			status = "disabled";

Status should be the last property

> +			#address-cells = <2>;
> +			#size-cells = <2>;
> +			ranges;
> +
> +			clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
> +				 <&gcc GCC_USB30_PRIM_MASTER_CLK>,
> +				 <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
> +				 <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
> +				 <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
> +				 <&tcsrcc TCSR_USB3_CLKREF_EN>;
> +			clock-names = "cfg_noc",
> +				      "core",
> +				      "iface",
> +				      "sleep",
> +				      "mock_utmi",
> +				      "xo";
> +
> +			assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
> +					  <&gcc GCC_USB30_PRIM_MASTER_CLK>;
> +			assigned-clock-rates = <19200000>, <200000000>;
> +
> +			interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
> +						  <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,

Misaligned

> +					      <&pdc 14 IRQ_TYPE_EDGE_BOTH>,
> +					      <&pdc 15 IRQ_TYPE_EDGE_BOTH>,
> +					      <&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "pwr_event",
> +					  "hs_phy_irq",
> +					  "dp_hs_phy_irq",
> +					  "dm_hs_phy_irq",
> +					  "ss_phy_irq";
> +
> +			power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
> +			required-opps = <&rpmhpd_opp_nom>;
> +
> +			resets = <&gcc GCC_USB30_PRIM_BCR>;
> +
> +			interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>,

QCOM_ICC_TAG_ALWAYS

> +					<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;
> +			interconnect-names = "usb-ddr", "apps-usb";
> +

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Tue Mar  4 18:58:29 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:58:29 +0200
Subject: [PATCH v2 8/9] arm64: dts: qcom: sm8750: Add USB support for
 SM8750 MTP and QRD platforms
In-Reply-To: <20250304-sm8750_usb_master-v2-8-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-8-a698a2e68e06@quicinc.com>
Message-ID: <6msx5eontkkunldl45npigj756b5sst7xjhmomlnummbsmncif@ca3hkdvtdo44>

On Tue, Mar 04, 2025 at 01:56:41PM -0800, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> Enable USB support on SM8750 MTP and QRD variants.  The current definition
> will start the USB controller in peripheral mode by default until
> dependencies are added, such as USB role detection.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 24 ++++++++++++++++++++++++
>  arch/arm64/boot/dts/qcom/sm8750-qrd.dts | 24 ++++++++++++++++++++++++

Nit: two separate commits please.


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

>  2 files changed, 48 insertions(+)
> 

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Tue Mar  4 18:59:49 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Wed, 5 Mar 2025 04:59:49 +0200
Subject: [PATCH v2 9/9] arm64: defconfig: Add M31 eUSB2 PHY config
In-Reply-To: <20250304-sm8750_usb_master-v2-9-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-9-a698a2e68e06@quicinc.com>
Message-ID: <xgryihmtcbvhimm4fr2pcrhjcwdp6djfrgtwj4a5kl4tukeavb@de5irgx54w5p>

On Tue, Mar 04, 2025 at 01:56:42PM -0800, Melody Olvera wrote:
> Add configs for the M31 eUSB2 PHY for SM8750 USB.

Please use git log on the defconfig to check what is usually required
from the commit messages. The defconfig is not Qcom-specific so you can
not expect somebody to know what is SM8750 or why does it require a PHY.

> 
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  arch/arm64/configs/defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 3a3706db29822036d25a7228f8936e2ad613b208..7a7187475a11206e708a5a2c6dd51736e16932e9 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -1587,6 +1587,7 @@ CONFIG_PHY_QCOM_QUSB2=m
>  CONFIG_PHY_QCOM_SNPS_EUSB2=m
>  CONFIG_PHY_QCOM_EUSB2_REPEATER=m
>  CONFIG_PHY_QCOM_M31_USB=m
> +CONFIG_PHY_QCOM_M31_EUSB=m
>  CONFIG_PHY_QCOM_USB_HS=m
>  CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
>  CONFIG_PHY_QCOM_USB_HS_28NM=m
> 
> -- 
> 2.46.1
> 

-- 
With best wishes
Dmitry


From andyshrk at 163.com  Tue Mar  4 18:51:11 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed,  5 Mar 2025 10:51:11 +0800
Subject: [PATCH] arm64: dts: rockchip: Enable hdmi out display for rk3576-evb-v10
Message-ID: <20250305025128.479245-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Enable vop and hdmi on rk3576 evb1, so we can get a display output
on this board now.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 .../boot/dts/rockchip/rk3576-evb1-v10.dts     | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
index 318e13d2ea55..52ea6917b7de 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
@@ -10,6 +10,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
 #include "rk3576.dtsi"
 
 / {
@@ -58,6 +59,17 @@ button-vol-up {
 		};
 	};
 
+	hdmi-con {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
 	leds: leds {
 		compatible = "gpio-leds";
 
@@ -271,6 +283,26 @@ &eth1m0_rgmii_bus
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_in {
+	hdmi_in_vp0: endpoint {
+		remote-endpoint = <&vp0_out_hdmi>;
+	};
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&hdptxphy {
+	status = "okay";
+};
+
 &i2c1 {
 	status = "okay";
 
@@ -734,3 +766,18 @@ &usb_drd1_dwc3 {
 	dr_mode = "host";
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0 {
+	vp0_out_hdmi: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+		remote-endpoint = <&hdmi_in_vp0>;
+	};
+};
-- 
2.34.1



From shradha.t at samsung.com  Tue Mar  4 08:52:36 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Tue, 4 Mar 2025 22:22:36 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250304154638.GB2310180@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
	<CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
	<20250221131548.59616-4-shradha.t@samsung.com> <Z8XrYxP_pZr6tFU8@debian>
	<20250303194647.GC1552306@rocinante>
	<CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
	<20250304154638.GB2310180@rocinante>
Message-ID: <061201db8d25$dd1e2bd0$975a8370$@samsung.com>



> -----Original Message-----
> From: Krzysztof Wilczy?ski <kw at linux.com>
> Sent: 04 March 2025 21:17
> To: Geert Uytterhoeven <geert at linux-m68k.org>
> Cc: Fan Ni <nifan.cxl at gmail.com>; Shradha Todi <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org;
> lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com; jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com;
> a.manzanares at samsung.com; pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com;
> xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com; Yoshihiro Shimoda
> <yoshihiro.shimoda.uh at renesas.com>; Linux-Renesas <linux-renesas-soc at vger.kernel.org>
> Subject: Re: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
> 
> Hello,
> 
> > This patch is now commit 1ff54f4cbaed9ec6 ("PCI: dwc: Add debugfs
> > based Silicon Debug support for DWC") in pci/next (next-20250304).
> >
> > On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> > > [...]
> > > > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci) {
> > > > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > > > +   struct device *dev = pci->dev;
> > > > > +   struct debugfs_info *debugfs;
> > > > > +   struct dentry *dir;
> > > > > +   int ret;
> > > > > +
> > > > > +   /* Create main directory for each platform driver */
> > > > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > > > +   dir = debugfs_create_dir(dirname, NULL);
> > > > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > > > +   if (!debugfs)
> > > > > +           return -ENOMEM;
> > > > > +
> > > > > +   debugfs->debug_dir = dir;
> > > > > +   pci->debugfs = debugfs;
> > > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > > +   if (ret)
> > > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > > >
> > > > What will happen if ret != 0? still return 0?
> >
> > And that is exactly what happens on Gray Hawk Single with R-Car
> > V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> > dwc_pcie_rasdes_debugfs_init() to return -ENODEV.
> 
> Thank you for testing and for catching this issue.  Much appreciated.
> 
> > > Given that callers of dwc_pcie_debugfs_init() check for errors,
> >
> > Debugfs issues should never be propagated upstream!
> 
> Makes complete sense.  Sorry for breaking things here!
> 
> > > this probably should correctly bubble up any failure coming from
> > > dwc_pcie_rasdes_debugfs_init().
> > >
> > > I made updates to the code directly on the current branch, have a look:
> >
> > So while applying, you changed this like:
> >
> >             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> >     -       if (ret)
> >     -               dev_dbg(dev, "RASDES debugfs init failed\n");
> >     +       if (ret) {
> >     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
> >     +               return ret;
> >     +       }
> >
> >             return 0;
> >
> > Hence this is now a fatal error, causing the probe to fail.
> 
> I removed the changed, and also move the log level to be a warning, per:
> 

Hey Krzysztof,
I think we shouldn't move the log level to be a WARN. I believe many controllers might not support
RAS DES feature in their design and giving a warn dump would draw unnecessary attention.
My opinion is to silently let it fail unless the user is actually interested in getting the RAS DES feature up.
We can wait for Mani's response though. But good catch to also add the error type, that's definitely a more
informative error log.

> 
> https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/dwc&id=c6759a967e69aba16aef0d92f43e527b
> 112e98a5
> 
> Would this be acceptable here?
> 
> Mani, would this be acceptable to you, too?  Given that you posted the following recently:
> 
>   https://lore.kernel.org/linux-pci/20250303200055.GA1881771 at rocinante/T/#mab9cbd5834390d259afea056eee9a73d8c3b435f
> 
> That said, perhaps moving the log level to a debug would be better served here.
> 
> 	Krzysztof




From shradha.t at samsung.com  Tue Mar  4 09:10:43 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Tue, 4 Mar 2025 22:40:43 +0530
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <Z8YZEALV71PUkXpF@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
	<CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
	<20250221131548.59616-6-shradha.t@samsung.com> <Z8XuuNb6TRevUlHH@debian>
	<20250303194228.GB1552306@rocinante> <Z8YZEALV71PUkXpF@debian>
Message-ID: <061401db8d28$5f0a4b40$1d1ee1c0$@samsung.com>



> -----Original Message-----
> From: Fan Ni <nifan.cxl at gmail.com>
> Sent: 04 March 2025 02:33
> To: Krzysztof Wilczy?ski <kw at linux.com>
> Cc: Fan Ni <nifan.cxl at gmail.com>; Shradha Todi <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org;
> lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com; jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com;
> a.manzanares at samsung.com; pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com;
> xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com
> Subject: Re: [PATCH v7 5/5] Add debugfs based statistical counter support in DWC
> 
> On Tue, Mar 04, 2025 at 04:42:28AM +0900, Krzysztof Wilczy?ski wrote:
> > Hello,
> >
> > [...]
> > > > +static ssize_t counter_value_read(struct file *file, char __user
> > > > +*buf, size_t count, loff_t *ppos) {
> > > > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > > > +	struct dw_pcie *pci = pdata->pci;
> > > > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > > > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > > > +	ssize_t pos;
> > > > +	u32 val;
> > > > +
> > > > +	mutex_lock(&rinfo->reg_event_lock);
> > > > +	set_event_number(pdata, pci, rinfo);
> > > > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > > > +	mutex_unlock(&rinfo->reg_event_lock);
> > > > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter
> > > > +value: %d\n", val);
> > > > +
> > > > +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf,
> > > > +pos); }
> > >
> > > Do we need to check whether the counter is enabled or not for the
> > > event before retrieving the counter value?
> >
> > I believe, we have a patch that aims to address, have a look at:
> >
> >
> > https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivannan.sa
> > dhasivam at linaro.org
> 
> Maybe I missed something, that seems to fix counter_enable_read(), but here is to retrieve counter value.
> How dw_pcie_readl_dbi() can return something like "Counter Disabled"?
> 
> Fan

Hey Fan,
So the counter value will show 0 in case it is disabled so there will not be any issues as per say. We could add the
check here but I feel I have already exposed the functionality to check if a counter is enabled or disabled, (by reading the
counter_enable debugfs entry) so this could be handled in user space to only read the counter if it's enabled.

> >
> > Thank you!
> >
> > 	Krzysztof




From shradha.t at samsung.com  Tue Mar  4 09:00:58 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Tue, 4 Mar 2025 22:30:58 +0530
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <20250304153509.GA2310180@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
	<CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
	<20250221131548.59616-5-shradha.t@samsung.com>
	<20250303095200.GB1065658@rocinante>
	<20250304152952.pal66goo2dwegevh@thinkpad>
	<20250304153509.GA2310180@rocinante>
Message-ID: <061301db8d27$02e0ced0$08a26c70$@samsung.com>



> -----Original Message-----
> From: Krzysztof Wilczy?ski <kw at linux.com>
> Sent: 04 March 2025 21:05
> To: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> Cc: Shradha Todi <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-pci at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com;
> jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com; fan.ni at samsung.com; nifan.cxl at gmail.com;
> a.manzanares at samsung.com; pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com;
> xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com
> Subject: Re: [PATCH v7 4/5] Add debugfs based error injection support in DWC
> 
> Hello,
> 
> [....]
> > > > +		29) Generates duplicate TLPs - duplicate_dllp
> > > > +		30) Generates Nullified TLPs - nullified_tlp
> > >
> > > Would the above field called "duplicate_dllp" for duplicate TLPs be
> > > a potential typo?  Perhaps this should be called "duplicate_tlp"?
> > >
> >
> > Looks like a typo. As per Synopsys documentation, there is only 'duplicate TLP'
> > field.
> >
> > Good catch!
> 
> Updated.  Thank you!
> 

Sorry, this was a typo. Krzysztof, we need another change for this typo.

diff --git a/drivers/pci/controller/dwc/pcie-designware-debugfs.c b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
index 729ac14ff700..4d77db3ca6ae 100644
--- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c
+++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
@@ -113,7 +113,7 @@ static const struct dwc_pcie_err_inj err_inj_list[] = {
        {"posted_tlp_data", 0x4, 0x4},
        {"non_post_tlp_data", 0x4, 0x5},
        {"cmpl_tlp_data", 0x4, 0x6},
-       {"duplicate_dllp", 0x5, 0x0},
+       {"duplicate_tlp", 0x5, 0x0},
        {"nullified_tlp", 0x5, 0x1},
 };

So sorry for the inconvenience! Should I post a patch for this?

> 	Krzysztof




From alexei.starovoitov at gmail.com  Tue Mar  4 19:26:12 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Tue, 4 Mar 2025 19:26:12 -0800
Subject: [PATCH bpf-next v2 00/26] Resilient Queued Spin Lock
In-Reply-To: <20250304104648.GD11590@noisy.programming.kicks-ass.net>
References: <20250206105435.2159977-1-memxor@gmail.com> <20250210093840.GE10324@noisy.programming.kicks-ass.net>
 <20250210104931.GE31462@noisy.programming.kicks-ass.net> <CAADnVQ+3wu0WB2pXs4cccxfkbTb3TK8Z+act5egytiON+qN9tA@mail.gmail.com>
 <20250211104352.GC29593@noisy.programming.kicks-ass.net> <CAADnVQJ=81PE19JWeNjq6aNOy+GM-wo6n7WU9StX1b6kevqCUw@mail.gmail.com>
 <20250213095918.GB28068@noisy.programming.kicks-ass.net> <CAADnVQJJbi-52mP6BivyAudWSk95f1mgGQXWnjD-H37b7_AtLw@mail.gmail.com>
 <20250304104648.GD11590@noisy.programming.kicks-ass.net>
Message-ID: <CAADnVQ+hR6WB9=WVP73uxhetAZMTugcT2z_N=89qhjFJPoWT=Q@mail.gmail.com>

On Tue, Mar 4, 2025 at 2:46?AM Peter Zijlstra <peterz at infradead.org> wrote:
>
>
> Anyway; the situation I was thinking of was something along the lines
> of: you need data from 2 buckets, so you need to lock 2 buckets, but
> since hash-table, there is no sane order, so you need a 3rd lock to
> impose order.

Not quite. This is a typical request to allow locking two buckets
and solution to that is run-time lock address check.

> > q1 = bpf_map_lookup_elem(&vqueue, &key1);
> > q2 = bpf_map_lookup_elem(&vqueue, &key2);
> >
> > both will point to two different locks,
> > and since the key is dynamic there is no way to know
> > the order of q1->lock vs q2->lock.
>
> I still feel like I'm missing things, but while they are two dynamic
> locks, they are both locks of vqueue object. What lockdep does is
> classify locks by initialization site (by default). Same can be done
> here, classify per dynamic object.
>
> So verifier can know the above is invalid. Both locks are same class, so
> treat as A-A order (trivial case is where q1 and q2 are in fact the same
> object since the keys hash the same).

Sounds like you're saying that the verifier should reject
the case when two locks of the same class like q1->lock and q2->lock
need to be taken ?
But that is one of the use cases where people requested to allow
multiple locks.
The typical solution to this is to order locks by addresses at runtime.
And nf_conntrack_double_lock() in net/netfilter/nf_conntrack_core.c
does exactly that.

if (lock1 < lock2) {
  spin_lock(lock1);spin_lock(lock2);
} else {
  spin_lock(lock2);spin_lock(lock1);
}

> Now, going back to 3rd lock, if instead you write it like:
>
>   bpf_spin_lock(&glock);
>   q1 = bpf_map_lookup_elem(&vqueue, &key1);
>   q2 = bpf_map_lookup_elem(&vqueue, &key2);
>   ...
>   bpf_spin_unlock(&glock);
>
> then (assuming q1 != q2) things are fine, since glock will serialize
> everybody taking two vqueue locks.
>
> And the above program snippet seems to imply maps are global state, so

Not quite. Some maps are global, but there are dynamic maps too.
That's what map-in-map is for.

> you can keep lock graph of maps, such that:
>
>   bpf_map_lookup_elem(&map-A, &key-A);
>   bpf_map_lookup_elem(&map-B, &key-B);
>
> vs
>
>   bpf_map_lookup_elem(&map-B, &key-B);
>   bpf_map_lookup_elem(&map-A, &key-A);
>
> trips AB-BA

If everything was static and _keys_ known statically too, then yes,
such analysis by the verifier would be possible.
But both maps and keys are dynamic.

Note, to make sure that the above example doesn't confuse people,
bpf_map_lookup_elem() lookup itself is completely lockless.
So nothing wrong with the above sequence as written.
Only when:
q1 = bpf_map_lookup_elem(&map-A, &key-A);
q2 = bpf_map_lookup_elem(&map-B, &key-B);
if (bpf_res_spin_lock(&q1->lock))
if (bpf_res_spin_lock(&q2->lock))

the deadlocks become a possibility.
Both maps and keys are only known at run-time.
So locking logic has to do run-time checks too.

> I am not at all sure how res_spin_lock is helping with the q1,q2 thing.
> That will trivially result in lock cycles.

Right and AA or ABBA will be instantly detected at run-time.

> And you said any program that would trigger deadlock is invalid.
> Therefore the q1,q2 example from above is still invalid and
> res_spin_lock has not helped.

res_spin_lock will do its job and will prevent a deadlock.
As we explained earlier such a program will be marked as broken
and will be detached/stopped by the bpf infra.
Also we're talking root privileges.
None of this is allowed in unpriv.

> > Just to make it clear... there is a patch 18:
> >
> >  F: kernel/bpf/
> >  F: kernel/trace/bpf_trace.c
> >  F: lib/buildid.c
> > +F: arch/*/include/asm/rqspinlock.h
> > +F: include/asm-generic/rqspinlock.h
> > +F: kernel/locking/rqspinlock.c
> >  F: lib/test_bpf.c
> >  F: net/bpf/
> >
> > that adds maintainer entries to BPF scope.
> >
> > We're not asking locking experts to maintain this new res_spin_lock.
> > It's not a generic kernel infra.
> > It will only be used by bpf infra and by bpf progs.
> > We will maintain it and we will fix whatever bugs
> > we introduce.
>
> While that is appreciated, the whole kernel is subject to the worst case
> behaviour of this thing. As such, I feel I need to care.

Not sure why you're trying to relitigate the years worth of
discussions around locks in the bpf community.
Static analysis of 2+ locks by the verifier is impossible.
Full lock graph cycle detection lockdep-style is too slow in run-time.
Hence res_spin_lock with AA, ABBA, and timeout as a last resort
is our solution to real reported bugs.

This res_spin_lock patchset fixes the following syzbot reports:

https://lore.kernel.org/bpf/675302fd.050a0220.2477f.0004.GAE at google.com
https://lore.kernel.org/bpf/000000000000b3e63e061eed3f6b at google.com
https://lore.kernel.org/bpf/CAPPBnEa1_pZ6W24+WwtcNFvTUHTHO7KUmzEbOcMqxp+m2o15qQ at mail.gmail.com
https://lore.kernel.org/bpf/CAPPBnEYm+9zduStsZaDnq93q1jPLqO-PiKX9jy0MuL8LCXmCrQ at mail.gmail.com
https://lore.kernel.org/lkml/000000000000adb08b061413919e at google.com

It fixes the real issues.
Some of them have hacky workarounds, some are not fixed yet.

More syzbot reports will be fixed in follow ups when we
adopt res_spin_lock in other parts of bpf infra.

Note, all of the above syzbot reports are _not_ using direct
locks inside the bpf programs. All of them hit proper kernel
spin_locks inside bpf infra (like inside map implementations and such).
The verifier cannot do anything. syzbot generated programs
are trivial. They do one bpf_map_update_elem() call or similar.
It's a combination of attaching to tricky tracepoints
like trace_contention_begin or deep inside bpf infra.
We already have these workarounds:
CFLAGS_REMOVE_percpu_freelist.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_bpf_lru_list.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_queue_stack_maps.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_lpm_trie.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_ringbuf.o = $(CC_FLAGS_FTRACE)
to prevent recursion anywhere in these files,
but it's helping only so much.

So please take a look at patches 1-18 and help us make
sure we implemented AA, ABBA, timeout logic without obvious bugs.
I think we did, but extra review would be great.

Thanks!


From gshan at redhat.com  Tue Mar  4 19:53:06 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 5 Mar 2025 13:53:06 +1000
Subject: [PATCH v7 00/45] arm64: Support for Arm CCA in KVM
In-Reply-To: <20250213161426.102987-1-steven.price@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
Message-ID: <af65c1ea-202a-4a60-ab13-0c325385b7ec@redhat.com>

On 2/14/25 2:13 AM, Steven Price wrote:

[...]

> 
> The ABI to the RMM (the RMI) is based on RMM v1.0-rel0 specification[1].
> 
> This series is based on v6.14-rc1. It is also available as a git
> repository:
> 
> https://gitlab.arm.com/linux-arm/linux-cca cca-host/v7
> 
> Work in progress changes for kvmtool are available from the git
> repository below:
> 
> https://gitlab.arm.com/linux-arm/kvmtool-cca cca/v5
> 
> [1] https://developer.arm.com/documentation/den0137/1-0rel0/
> [2] https://lore.kernel.org/r/a7011738-a084-46fa-947f-395d90b37f8b%40arm.com
> 

I had a chance to test it by following Jean's instructions [1-2]. The guest can
boot up and kvmtool also can boot the guest. I'm listing the repositories I used
in case some body else want to give it a try.

[1] Jean's guide to build software components needed by ARM CCA stack
     https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/Building+an+RME+stack+for+QEMU
[2] Jean's guide to build firmware needed by the emulated host

host
====
tf-rmm    https://git.codelinaro.org/linaro/dcap/rmm.git                       (cca/v4)
edk2:     git at github.com:tianocore/edk2.git                                    (edk2-stable202411)
tf-a:     https://git.codelinaro.org/linaro/dcap/tf-a/trusted-firmware-a.git   (cca/v4)
qemu      https://git.qemu.org/git/qemu.git                                    (stable-9.2)
linux     https://git.gitlab.arm.com/linux-arm/linux-cca.git                   (cca-host/v7)
buildroot https://github.com/buildroot/buildroot                               (master)

guest
=====
qemu      https://git.codelinaro.org/linaro/dcap/qemu.git                      (cca/latest)
kvmtool   https://gitlab.arm.com/linux-arm/kvmtool-cca                         (cca/latest)
linux     https://git.gitlab.arm.com/linux-arm/linux-cca.git                   (cca-guest/v7)

Command lines to start the host
================================
[gshan at virtlab723 host]$ cat start.sh
#!/bin/sh
HOST_PATH=/home/gshan/sandbox/qemu/host
GUEST_PATH=/home/gshan/sandbox/qemu/guest

sudo ${HOST_PATH}/qemu/build/qemu-system-aarch64                      \
-M virt,virtualization=on,secure=on,gic-version=3,acpi=off            \
-cpu max,x-rme=on -m 4G -smp 8                                        \
-serial mon:stdio -monitor none -nographic -nodefaults                \
-bios ${HOST_PATH}/tf-a/flash.bin                                     \
-kernel ${HOST_PATH}/linux/arch/arm64/boot/Image                      \
-initrd ${HOST_PATH}/buildroot/output/images/rootfs.cpio.xz           \
-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1                 \
-device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2                 \
-device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3                 \
-device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4                 \
-device virtio-9p-device,fsdev=shr0,mount_tag=shr0                    \
-fsdev local,security_model=none,path=${GUEST_PATH},id=shr0           \
-netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \
-device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=78:ac:44:2b:43:f0

Command lines to start the guest
================================
[gshan at virtlab723 guest]$ cat start_guest.sh
#!/bin/sh
key="VGhlIHJlYWxtIGd1ZXN0IHBlcnNvbmFsaXphdGlvbiBrZXkga"
key+="W4gZm9ybWF0IG9mIGJhc2U2NCAgICAgICAgIA=="

qemu-system-aarch64 -enable-kvm                                                     \
-object rme-guest,id=rme0,measurement-algorithm=sha512,personalization-value=${key} \
-M virt,gic-version=3,its=on,confidential-guest-support=rme0 ? ? ? ? ? ?            \
-cpu host -smp 2 -m 1024M ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?           \
-serial mon:stdio -monitor none -nographic -nodefaults ? ? ? ? ? ? ? ? ?            \
-kernel /mnt/linux/arch/arm64/boot/Image ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?            \
-initrd /mnt/buildroot/output/images/rootfs.cpio.xz ? ? ? ? ? ? ? ? ? ? ?           \
-append earlycon=pl011,mmio,0x10009000000

Thanks,
Gavin



From dsimic at manjaro.org  Tue Mar  4 20:06:41 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Wed, 05 Mar 2025 05:06:41 +0100
Subject: [PATCH v2 0/2] Slightly improve hardware description of Pine64
 RockPro64
In-Reply-To: <2630232.Icojqenx9y@diego>
References: <cover.1740941097.git.dsimic@manjaro.org>
 <174104113599.8946.16805724674396090918.b4-ty@sntech.de>
 <757afa87255212dfa5abf4c0e31deb08@manjaro.org> <2630232.Icojqenx9y@diego>
Message-ID: <40aed1a2c3d4015881694e847beca683@manjaro.org>

Hello Heiko,

On 2025-03-04 22:52, Heiko St?bner wrote:
> Am Dienstag, 4. M?rz 2025, 07:44:59 MEZ schrieb Dragan Simic:
>> On 2025-03-03 23:36, Heiko Stuebner wrote:
>> > On Sun, 02 Mar 2025 19:48:02 +0100, Dragan Simic wrote:
>> >> This is a small series that introduces small improvements to the way
>> >> Pine64 RockPro64 [1] single-board-computer is described in the DT
>> >> files.
>> >> This applies to both production-run revisions of the RockPro64.
>> >>
>> >> The introduced improvements boil down to eliminating some warnings
>> >> from
>> >> the kernel log, by adding a previously undefined regulator and by
>> >> adding
>> >> some previously missing references to the regulators.
>> >>
>> >> [...]
>> >
>> > Applied, thanks!
>> >
>> > [1/2] arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board
>> > dtsi
>> >       commit: bd1c959f37f384b477f51572331b0dc828bd009a
>> > [2/2] arm64: dts: rockchip: Add missing PCIe supplies to RockPro64
>> > board dtsi
>> >       commit: 64ef4a4320e7aa3f0f267e01f170f52b90bf0b1b
>> >
>> > I've moved the pcie12v supply up one line.
>> > While in a mathematical sense it's true 12 > 3.3, we're sorting
>> > alphabetical, so it's 1?? < 3?? .
>> >
>> > And yes I sympathize with 3.3 < 12, but also have come to appreciate
>> > not
>> > having overly many special cases :-)
>> 
>> Great, thanks! :)
>> 
>> I'm fine with the alphabetical ordering, albeit with some caveats
>> described below, but the following part of the patch description
>> should also be removed, if possible, so the patch description fully
>> matches the introduced changes:
>> 
>>    Shuffle and reorder the "vpcie*-supply" properties a bit, so 
>> they're
>> sorted
>>    alphanumerically, which is a bit more logical and more useful than
>> having
>>    these properties listed in their strict alphabetical order.
> 
> I've amended the commit, dropping this block

Thanks!

>> I'm hoping you'll agree that specifying alphanumerical ordering
>> for the properties in the DTS coding style is the way to go, just
>> like it's already specified for the ordering of the nodes.  I'll
>> go ahead and submit an appropriate patch for the DT guidelines.
> 
> vpcie0v9-supply = <&vcca_0v9>;
> vpcie1v8-supply = <&vcca_1v8>;
> vpcie3v3-supply = <&vcc3v3_pcie>;
> vpcie12v-supply = <&vcc12v_dcin>;
> 
> In the end I don't care _that_ much, but personally I find that
> alphanumerical ordering harder to read ;-) .
> 
> Because in the example above, my mind now constantly shouts
> "why is vpcie1... after vpcie3... ..... ooooh right, it's 
> alpha-numerical"
> 
> But I can live with it I guess ;-) .
> As 3.3 is smaller than 12 afterall.

Oh, I know very well first-hand how alphanumerical ordering may
look and feel strange at first... :)

I used ls(1) without the "-v" option for many, many years, and the
things looked a bit strange after I decided to add "-v" to its set
of options at some point, but after a short period of getting used
to it, alphanumerical sorting became so logical and useful to me that
alphabetical ordering is actually now harder to read and is looking
a bit strange to me. :)


From shawn.lin at rock-chips.com  Tue Mar  4 20:10:58 2025
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed,  5 Mar 2025 12:10:58 +0800
Subject: [PATCH] arm64: defconfig: Enable Rockchip UFS host driver
Message-ID: <1741147858-136859-1-git-send-email-shawn.lin@rock-chips.com>

Enable Rockchip UFS host driver.

This driver is first introduced on RK3576 SoC, and will be
used for more SoCs in near future, so add it to defconfig
will make these platforms work better.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
---

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706d..907e92d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1191,6 +1191,7 @@ CONFIG_SCSI_UFS_HISI=y
 CONFIG_SCSI_UFS_RENESAS=m
 CONFIG_SCSI_UFS_TI_J721E=m
 CONFIG_SCSI_UFS_EXYNOS=y
+CONFIG_SCSI_UFS_ROCKCHIP=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS_MULTICOLOR=m
-- 
2.7.4



From shawn.lin at rock-chips.com  Tue Mar  4 20:18:27 2025
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed,  5 Mar 2025 12:18:27 +0800
Subject: [PATCH] arm64: dts: rockchip: Enable ufshc on RK3576 evb1 board
Message-ID: <1741148307-137177-1-git-send-email-shawn.lin@rock-chips.com>

RK3576 evb1 board supports UFS, so enable it.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
---

 arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
index 782ca00..5412c60 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
@@ -711,6 +711,10 @@
 	status = "okay";
 };
 
+&ufshc {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
-- 
2.7.4



From nifan.cxl at gmail.com  Tue Mar  4 20:26:01 2025
From: nifan.cxl at gmail.com (Fan Ni)
Date: Tue, 4 Mar 2025 20:26:01 -0800
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <061401db8d28$5f0a4b40$1d1ee1c0$@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
 <20250221131548.59616-6-shradha.t@samsung.com>
 <Z8XuuNb6TRevUlHH@debian>
 <20250303194228.GB1552306@rocinante>
 <Z8YZEALV71PUkXpF@debian>
 <061401db8d28$5f0a4b40$1d1ee1c0$@samsung.com>
Message-ID: <Z8fSWcR_aXyxmFEZ@debian>

On Tue, Mar 04, 2025 at 10:40:43PM +0530, Shradha Todi wrote:
> 
> 
> > -----Original Message-----
> > From: Fan Ni <nifan.cxl at gmail.com>
> > Sent: 04 March 2025 02:33
> > To: Krzysztof Wilczy?ski <kw at linux.com>
> > Cc: Fan Ni <nifan.cxl at gmail.com>; Shradha Todi <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-
> > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org;
> > lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com; jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com;
> > a.manzanares at samsung.com; pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com;
> > xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com
> > Subject: Re: [PATCH v7 5/5] Add debugfs based statistical counter support in DWC
> > 
> > On Tue, Mar 04, 2025 at 04:42:28AM +0900, Krzysztof Wilczy?ski wrote:
> > > Hello,
> > >
> > > [...]
> > > > > +static ssize_t counter_value_read(struct file *file, char __user
> > > > > +*buf, size_t count, loff_t *ppos) {
> > > > > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > > > > +	struct dw_pcie *pci = pdata->pci;
> > > > > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > > > > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > > > > +	ssize_t pos;
> > > > > +	u32 val;
> > > > > +
> > > > > +	mutex_lock(&rinfo->reg_event_lock);
> > > > > +	set_event_number(pdata, pci, rinfo);
> > > > > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > > > > +	mutex_unlock(&rinfo->reg_event_lock);
> > > > > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter
> > > > > +value: %d\n", val);
> > > > > +
> > > > > +	return simple_read_from_buffer(buf, count, ppos, debugfs_buf,
> > > > > +pos); }
> > > >
> > > > Do we need to check whether the counter is enabled or not for the
> > > > event before retrieving the counter value?
> > >
> > > I believe, we have a patch that aims to address, have a look at:
> > >
> > >
> > > https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivannan.sa
> > > dhasivam at linaro.org
> > 
> > Maybe I missed something, that seems to fix counter_enable_read(), but here is to retrieve counter value.
> > How dw_pcie_readl_dbi() can return something like "Counter Disabled"?
> > 
> > Fan
> 
> Hey Fan,
> So the counter value will show 0 in case it is disabled so there will not be any issues as per say. We could add the
> check here but I feel I have already exposed the functionality to check if a counter is enabled or disabled, (by reading the
> counter_enable debugfs entry) so this could be handled in user space to only read the counter if it's enabled.
Ok. 
Returning 0 when the counter is disabled makes sense to me.

Just some thought.

It seems natural to me if we make "counter_value" only visiable to
users when the counter is enabled. 

Fan
> 
> > >
> > > Thank you!
> > >
> > > 	Krzysztof
> 
> 


From nicolinc at nvidia.com  Tue Mar  4 21:04:02 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 4 Mar 2025 21:04:02 -0800
Subject: [PATCH v1 3/4] iommu/arm-smmu-v3: Decouple vmid from S2 nest_parent domain
In-Reply-To: <cover.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
Message-ID: <0429d554fb0f54f6d79bdacacb3fb3e7877ca8f7.1741150594.git.nicolinc@nvidia.com>

An S2 nest_parent domain can be shared across vSMMUs in the same VM, since
the S2 domain is basically the IPA mappings for the entire RAM of the VM.

Meanwhile, each vSMMU can have its own VMID, so the VMID allocation should
be done per vSMMU instance v.s. per S2 nest_parent domain.

However, an S2 domain can be also allocated when a physical SMMU instance
doesn't support S1. So, the structure has to retain the s2_cfg and vmid.

Allocate a vmid for a vSMMU instance in arm_vsmmu_alloc() and add a proper
arm_vsmmu_destroy() to clean it up.

Add a per-domain "vsmmus" list pairing with a spinlock, maintaining a list
on the S2 parent domain, to iterate S2 invalidations over the vmids across
the vSMMU instances created for the same VM.

Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 10 +++-
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 35 ++++++++++++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 47 +++++++++++++++----
 3 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 3336d196062c..1f6696bc4f6c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -849,8 +849,12 @@ struct arm_smmu_domain {
 
 	enum arm_smmu_domain_stage	stage;
 	union {
-		struct arm_smmu_ctx_desc	cd;
-		struct arm_smmu_s2_cfg		s2_cfg;
+		struct arm_smmu_ctx_desc cd;	/* S1 */
+		struct arm_smmu_s2_cfg s2_cfg;	/* S2 && !nest_parent */
+		struct {			/* S2 && nest_parent */
+			struct list_head list;
+			spinlock_t lock;
+		} vsmmus;
 	};
 
 	struct iommu_domain		domain;
@@ -1049,6 +1053,8 @@ struct arm_vsmmu {
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_domain *s2_parent;
 	u16 vmid;
+
+	struct list_head vsmmus_elm; /* arm_smmu_domain::vsmmus::list */
 };
 
 #if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index ff8b550159f2..2c5a9d0abed5 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -30,6 +30,23 @@ void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type)
 	return info;
 }
 
+static void arm_vsmmu_destroy(struct iommufd_viommu *viommu)
+{
+	struct arm_vsmmu *vsmmu = container_of(viommu, struct arm_vsmmu, core);
+	struct arm_smmu_device *smmu = vsmmu->smmu;
+	struct arm_smmu_cmdq_ent cmd = {
+		.opcode = CMDQ_OP_TLBI_S12_VMALL,
+		.tlbi.vmid = vsmmu->vmid,
+	};
+	unsigned long flags;
+
+	spin_lock_irqsave(&vsmmu->s2_parent->vsmmus.lock, flags);
+	list_del(&vsmmu->vsmmus_elm);
+	spin_unlock_irqrestore(&vsmmu->s2_parent->vsmmus.lock, flags);
+	arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
+	ida_free(&smmu->vmid_map, vsmmu->vmid);
+}
+
 static void arm_smmu_make_nested_cd_table_ste(
 	struct arm_smmu_ste *target, struct arm_smmu_master *master,
 	struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
@@ -337,6 +354,7 @@ static int arm_vsmmu_cache_invalidate(struct iommufd_viommu *viommu,
 }
 
 static const struct iommufd_viommu_ops arm_vsmmu_ops = {
+	.destroy = arm_vsmmu_destroy,
 	.alloc_domain_nested = arm_vsmmu_alloc_domain_nested,
 	.cache_invalidate = arm_vsmmu_cache_invalidate,
 };
@@ -351,6 +369,8 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
 	struct arm_smmu_domain *s2_parent = to_smmu_domain(parent);
 	struct arm_vsmmu *vsmmu;
+	unsigned long flags;
+	int vmid;
 
 	if (viommu_type != IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
 		return ERR_PTR(-EOPNOTSUPP);
@@ -381,15 +401,24 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 	    !(smmu->features & ARM_SMMU_FEAT_S2FWB))
 		return ERR_PTR(-EOPNOTSUPP);
 
+	vmid = ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1,
+			       GFP_KERNEL);
+	if (vmid < 0)
+		return ERR_PTR(vmid);
+
 	vsmmu = iommufd_viommu_alloc(ictx, struct arm_vsmmu, core,
 				     &arm_vsmmu_ops);
-	if (IS_ERR(vsmmu))
+	if (IS_ERR(vsmmu)) {
+		ida_free(&smmu->vmid_map, vmid);
 		return ERR_CAST(vsmmu);
+	}
 
 	vsmmu->smmu = smmu;
+	vsmmu->vmid = (u16)vmid;
 	vsmmu->s2_parent = s2_parent;
-	/* FIXME Move VMID allocation from the S2 domain allocation to here */
-	vsmmu->vmid = s2_parent->s2_cfg.vmid;
+	spin_lock_irqsave(&s2_parent->vsmmus.lock, flags);
+	list_add_tail(&vsmmu->vsmmus_elm, &s2_parent->vsmmus.list);
+	spin_unlock_irqrestore(&s2_parent->vsmmus.lock, flags);
 
 	return &vsmmu->core;
 }
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 0462eb1b2912..addc6308742b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2249,10 +2249,22 @@ static void arm_smmu_tlb_inv_context(void *cookie)
 	 */
 	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
 		arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
-	} else {
+	} else if (!smmu_domain->nest_parent) {
 		cmd.opcode	= CMDQ_OP_TLBI_S12_VMALL;
 		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
 		arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
+	} else {
+		struct arm_vsmmu *vsmmu, *next;
+		unsigned long flags;
+
+		cmd.opcode = CMDQ_OP_TLBI_S12_VMALL;
+		spin_lock_irqsave(&smmu_domain->vsmmus.lock, flags);
+		list_for_each_entry_safe(vsmmu, next, &smmu_domain->vsmmus.list,
+					 vsmmus_elm) {
+			cmd.tlbi.vmid = vsmmu->vmid;
+			arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
+		}
+		spin_unlock_irqrestore(&smmu_domain->vsmmus.lock, flags);
 	}
 	arm_smmu_atc_inv_domain(smmu_domain, 0, 0);
 }
@@ -2342,19 +2354,33 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
 		cmd.opcode	= smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ?
 				  CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA;
 		cmd.tlbi.asid	= smmu_domain->cd.asid;
-	} else {
+		__arm_smmu_tlb_inv_range(&cmd, iova, size, granule,
+					 smmu_domain);
+	} else if (!smmu_domain->nest_parent) {
 		cmd.opcode	= CMDQ_OP_TLBI_S2_IPA;
 		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
-	}
-	__arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain);
+		__arm_smmu_tlb_inv_range(&cmd, iova, size, granule,
+					 smmu_domain);
+	} else {
+		struct arm_vsmmu *vsmmu, *next;
+		unsigned long flags;
 
-	if (smmu_domain->nest_parent) {
 		/*
 		 * When the S2 domain changes all the nested S1 ASIDs have to be
 		 * flushed too.
 		 */
 		cmd.opcode = CMDQ_OP_TLBI_NH_ALL;
 		arm_smmu_cmdq_issue_cmd_with_sync(smmu_domain->smmu, &cmd);
+
+		cmd.opcode = CMDQ_OP_TLBI_S2_IPA;
+		spin_lock_irqsave(&smmu_domain->vsmmus.lock, flags);
+		list_for_each_entry_safe(vsmmu, next, &smmu_domain->vsmmus.list,
+					 vsmmus_elm) {
+			cmd.tlbi.vmid = vsmmu->vmid;
+			__arm_smmu_tlb_inv_range(&cmd, iova, size, granule,
+						 smmu_domain);
+		}
+		spin_unlock_irqrestore(&smmu_domain->vsmmus.lock, flags);
 	}
 
 	/*
@@ -2477,7 +2503,7 @@ static void arm_smmu_domain_free_paging(struct iommu_domain *domain)
 		mutex_lock(&arm_smmu_asid_lock);
 		xa_erase(&arm_smmu_asid_xa, smmu_domain->cd.asid);
 		mutex_unlock(&arm_smmu_asid_lock);
-	} else {
+	} else if (!smmu_domain->nest_parent) {
 		struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
 		if (cfg->vmid)
 			ida_free(&smmu->vmid_map, cfg->vmid);
@@ -2506,7 +2532,10 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_device *smmu,
 				       struct arm_smmu_domain *smmu_domain)
 {
 	int vmid;
-	struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
+
+	/* nest_parent stores vmid in vSMMU instead of a shared S2 domain */
+	if (smmu_domain->nest_parent)
+		return 0;
 
 	/* Reserve VMID 0 for stage-2 bypass STEs */
 	vmid = ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1,
@@ -2514,7 +2543,7 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_device *smmu,
 	if (vmid < 0)
 		return vmid;
 
-	cfg->vmid	= (u16)vmid;
+	smmu_domain->s2_cfg.vmid = (u16)vmid;
 	return 0;
 }
 
@@ -3233,6 +3262,8 @@ arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
 		}
 		smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
 		smmu_domain->nest_parent = true;
+		INIT_LIST_HEAD(&smmu_domain->vsmmus.list);
+		spin_lock_init(&smmu_domain->vsmmus.lock);
 		break;
 	case IOMMU_HWPT_ALLOC_DIRTY_TRACKING:
 	case IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID:
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar  4 21:04:03 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 4 Mar 2025 21:04:03 -0800
Subject: [PATCH v1 4/4] iommu/arm-smmu-v3-iommufd: Allow a shared s2_parent to allocate vSMMU
In-Reply-To: <cover.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
Message-ID: <564eda8dee4bbf4c6e1d1dd9ed6bd40cc1a2df26.1741150594.git.nicolinc@nvidia.com>

Now, vmids are stored in vSMMU objects. So all vSMMUs assigned to the same
VM can share a s2_parent domain. This means a vIOMMU allocation per device
behind one SMMU can be given with a s2_parent domain that's allocated per
another device behind another SMMU, i.e. s2_parent->smmu != master->smmu.

Remove the validation line to allow this use case.

Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 2c5a9d0abed5..9bfa5fa5bafa 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -378,9 +378,6 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 	if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
 		return ERR_PTR(-EOPNOTSUPP);
 
-	if (s2_parent->smmu != master->smmu)
-		return ERR_PTR(-EINVAL);
-
 	/*
 	 * FORCE_SYNC is not set with FEAT_NESTING. Some study of the exact HW
 	 * defect is needed to determine if arm_vsmmu_cache_invalidate() needs
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar  4 21:04:00 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 4 Mar 2025 21:04:00 -0800
Subject: [PATCH v1 1/4] iommu/arm-smmu-v3: Pass in vmid to arm_smmu_make_s2_domain_ste()
In-Reply-To: <cover.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
Message-ID: <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>

An stage-2 STE requires a vmid that has been so far allocated per domain,
so arm_smmu_make_s2_domain_ste() has been extracting the vmid from the S2
domain.

To share an S2 parent domain across vSMMUs in the same VM, a vmid will be
no longer allocated for nor stored in the S2 domain, but per vSMMU, which
means the arm_smmu_make_s2_domain_ste() can get a vmid either from an S2
domain (non nesting parent) or a vSMMU.

Allow to pass in vmid explicitly to arm_smmu_make_s2_domain_ste(), giving
its callers a chance to pick the vmid between a domain or a vSMMU.

Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 2 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 6 ++++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c    | 3 ++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c         | 6 +++---
 4 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index bd9d7c85576a..e08c4ede4b2d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -887,7 +887,7 @@ struct arm_smmu_entry_writer_ops {
 void arm_smmu_make_abort_ste(struct arm_smmu_ste *target);
 void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
 				 struct arm_smmu_master *master,
-				 struct arm_smmu_domain *smmu_domain,
+				 struct arm_smmu_domain *smmu_domain, u16 vmid,
 				 bool ats_enabled);
 
 #if IS_ENABLED(CONFIG_KUNIT)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 5aa2e7af58b4..ff8b550159f2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -34,8 +34,9 @@ static void arm_smmu_make_nested_cd_table_ste(
 	struct arm_smmu_ste *target, struct arm_smmu_master *master,
 	struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
 {
-	arm_smmu_make_s2_domain_ste(
-		target, master, nested_domain->vsmmu->s2_parent, ats_enabled);
+	arm_smmu_make_s2_domain_ste(target, master,
+				    nested_domain->vsmmu->s2_parent,
+				    nested_domain->vsmmu->vmid, ats_enabled);
 
 	target->data[0] = cpu_to_le64(STRTAB_STE_0_V |
 				      FIELD_PREP(STRTAB_STE_0_CFG,
@@ -76,6 +77,7 @@ static void arm_smmu_make_nested_domain_ste(
 	case STRTAB_STE_0_CFG_BYPASS:
 		arm_smmu_make_s2_domain_ste(target, master,
 					    nested_domain->vsmmu->s2_parent,
+					    nested_domain->vsmmu->vmid,
 					    ats_enabled);
 		break;
 	case STRTAB_STE_0_CFG_ABORT:
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
index d2671bfd3798..7fac5a112c5c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
@@ -316,7 +316,8 @@ static void arm_smmu_test_make_s2_ste(struct arm_smmu_ste *ste,
 	io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.sl = 3;
 	io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.tsz = 4;
 
-	arm_smmu_make_s2_domain_ste(ste, &master, &smmu_domain, ats_enabled);
+	arm_smmu_make_s2_domain_ste(ste, &master, &smmu_domain,
+				    smmu_domain.s2_cfg.vmid, ats_enabled);
 }
 
 static void arm_smmu_v3_write_ste_test_s2_to_abort(struct kunit *test)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 358072b4e293..310bb4109ec9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1656,10 +1656,9 @@ EXPORT_SYMBOL_IF_KUNIT(arm_smmu_make_cdtable_ste);
 
 void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
 				 struct arm_smmu_master *master,
-				 struct arm_smmu_domain *smmu_domain,
+				 struct arm_smmu_domain *smmu_domain, u16 vmid,
 				 bool ats_enabled)
 {
-	struct arm_smmu_s2_cfg *s2_cfg = &smmu_domain->s2_cfg;
 	const struct io_pgtable_cfg *pgtbl_cfg =
 		&io_pgtable_ops_to_pgtable(smmu_domain->pgtbl_ops)->cfg;
 	typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr =
@@ -1690,7 +1689,7 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
 		   FIELD_PREP(STRTAB_STE_2_VTCR_S2TG, vtcr->tg) |
 		   FIELD_PREP(STRTAB_STE_2_VTCR_S2PS, vtcr->ps);
 	target->data[2] = cpu_to_le64(
-		FIELD_PREP(STRTAB_STE_2_S2VMID, s2_cfg->vmid) |
+		FIELD_PREP(STRTAB_STE_2_S2VMID, vmid) |
 		FIELD_PREP(STRTAB_STE_2_VTCR, vtcr_val) |
 		STRTAB_STE_2_S2AA64 |
 #ifdef __BIG_ENDIAN
@@ -2969,6 +2968,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	}
 	case ARM_SMMU_DOMAIN_S2:
 		arm_smmu_make_s2_domain_ste(&target, master, smmu_domain,
+					    smmu_domain->s2_cfg.vmid,
 					    state.ats_enabled);
 		arm_smmu_install_ste_for_dev(master, &target);
 		arm_smmu_clear_cd(master, IOMMU_NO_PASID);
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar  4 21:03:59 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 4 Mar 2025 21:03:59 -0800
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu instead of s2_parent
Message-ID: <cover.1741150594.git.nicolinc@nvidia.com>

With a system having multiple SMMU physical instances, multiple vSMMUs can
be allocated for a VM that deivces behind different SMMUs are assigned to.
In such a use case, the IPA->PA mappings (i.e. the stage-2 I/O page table)
can be shared across the vSMMU instances.

With a shareable S2 parent domain, it is more natural to store a vmid per
vSMMU instance v.s. a shared S2 domain, since each physical SMMU instance
maintains its own vmid bitmap.

Have a pair of patches getting the functions ready for the vmid migration.
Decouple the vmid from S2 parent domains and move its allocation to vSMMU
instances. Note that a regular S2 domain (!nest_parent) has to retain the
s2_cfg and vmid for non-nesting use cases, if the SMMU HW doesn't support
stage 1. Then, an S2 invalidation has to be iterated for all the vmids in
the vSMMU list introduced in the S2 parent domain.

This is on Github:
https://github.com/nicolinc/iommufd/commits/smmuv3_vmid-v1

To test it with RMR:
https://github.com/nicolinc/iommufd/commits/smmuv3_vmid-v1-with-rmr
Pairing QEMU branch:
https://github.com/nicolinc/qemu/commits/wip/for_smmuv3_vmid-v1

Thanks
Nicolin

Nicolin Chen (4):
  iommu/arm-smmu-v3: Pass in vmid to arm_smmu_make_s2_domain_ste()
  iommu/arm-smmu-v3: Share arm_smmu_cmdq_issue_cmd_with_sync() with
    vsmmu
  iommu/arm-smmu-v3: Decouple vmid from S2 nest_parent domain
  iommu/arm-smmu-v3-iommufd: Allow a shared s2_parent to allocate vSMMU

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 14 ++++-
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 44 +++++++++++---
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c  |  3 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 57 ++++++++++++++-----
 4 files changed, 93 insertions(+), 25 deletions(-)


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar  4 21:04:01 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 4 Mar 2025 21:04:01 -0800
Subject: [PATCH v1 2/4] iommu/arm-smmu-v3: Share arm_smmu_cmdq_issue_cmd_with_sync() with vsmmu
In-Reply-To: <cover.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
Message-ID: <e9e8df0b9dadfb8c716b8b9072657327ab14898c.1741150594.git.nicolinc@nvidia.com>

Allow arm-smmu-v3-iommufd to call it for S2 cache invalidations.

Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 ++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index e08c4ede4b2d..3336d196062c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -984,6 +984,8 @@ void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master,
 int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
 				struct arm_smmu_cmdq *cmdq, u64 *cmds, int n,
 				bool sync);
+int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+				      struct arm_smmu_cmdq_ent *ent);
 
 #ifdef CONFIG_ARM_SMMU_V3_SVA
 bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 310bb4109ec9..0462eb1b2912 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -929,8 +929,8 @@ static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
 	return __arm_smmu_cmdq_issue_cmd(smmu, ent, false);
 }
 
-static int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
-					     struct arm_smmu_cmdq_ent *ent)
+int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+				      struct arm_smmu_cmdq_ent *ent)
 {
 	return __arm_smmu_cmdq_issue_cmd(smmu, ent, true);
 }
-- 
2.43.0



From fujita.tomonori at gmail.com  Tue Mar  4 21:13:07 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed, 05 Mar 2025 14:13:07 +0900 (JST)
Subject: [PATCH v3 5/5] rust: Add warn_on and warn_on_once
In-Reply-To: <CAH5fLgjX9hh+QRrKggOKr+6p+UwqHSavzu4UXy9iGNL2wSJXtg@mail.gmail.com>
References: <20250213135759.190006-1-fujita.tomonori@gmail.com>
	<20250213135759.190006-6-fujita.tomonori@gmail.com>
	<CAH5fLgjX9hh+QRrKggOKr+6p+UwqHSavzu4UXy9iGNL2wSJXtg@mail.gmail.com>
Message-ID: <20250305.141307.586794213367343251.fujita.tomonori@gmail.com>

On Mon, 3 Mar 2025 14:33:39 +0100
Alice Ryhl <aliceryhl at google.com> wrote:

>> +#[macro_export]
>> +#[doc(hidden)]
>> +#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
>> +macro_rules! warn_flags {
>> +    ($flags:expr) => {
>> +        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
>> +        // SAFETY: Just an FFI call.
>> +        #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
>> +        unsafe {
>> +            $crate::asm!(concat!(
>> +                "/* {size} */",
>> +                ".pushsection .rodata.str1.1, \"aMS\", at progbits, 1\n",
>> +                "111:\t .string ", "\"", file!(), "\"\n",
>> +                ".popsection\n",
> 
> It looks like you're doing this so that you can reference the filename
> with "111b", but could you do this instead:
> 
> const _FILE: &[u8] = file!().as_bytes();
> // Plus one for nul-terminator.
> static FILE: [u8; 1 + _FILE.len()] = {
>     let mut bytes = [0; 1 + _FILE.len()];
>     let mut i = 0;
>     while i < _FILE.len() {
>         bytes[i] = _FILE[i];
>         i += 1;
>     }
>     bytes
> };

Neat! I will use this in the next version.

> and then use
> 
> asm!(
>     concat!(
>         "/* {size} */",
>         include!(concat!(env!("OBJTREE"),
> "/rust/kernel/generated_arch_warn_asm.rs")),
>         include!(concat!(env!("OBJTREE"),
> "/rust/kernel/generated_arch_reachable_asm.rs")));
>     file = sym FILE,
>     line = const line!(),
>     ...
> );
> 
> with
> ::kernel::concat_literals!(ARCH_WARN_ASM("{file}", "{line}",
> "{flags}", "{size}")),
> 
> That would be a lot simpler to understand than what you are doing.

Indeed.

Thanks a lot!


From danishanwar at ti.com  Tue Mar  4 21:20:47 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Wed, 5 Mar 2025 10:50:47 +0530
Subject: [PATCH net-next] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250304162437.0160f687@kernel.org>
References: <20250227093712.2130561-1-danishanwar@ti.com>
 <20250303172543.249a4fc2@kernel.org>
 <33c38844-4fbe-469c-bb5f-06bdb7721114@ti.com>
 <20250304162437.0160f687@kernel.org>
Message-ID: <cf468c08-6808-49a2-b6d9-5c2b00d654de@ti.com>

Hi Jakub,

On 05/03/25 5:54 am, Jakub Kicinski wrote:
> On Tue, 4 Mar 2025 13:46:39 +0530 MD Danish Anwar wrote:
>> On 04/03/25 6:55 am, Jakub Kicinski wrote:
>>> On Thu, 27 Feb 2025 15:07:12 +0530 MD Danish Anwar wrote:  
>>>> +	ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
>>>> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
>>>> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
>>>> +	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
>>>> +	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),  
>>>
>>> I presume frame preemption is implemented in silicon? If yes -
>>> what makes these "FW statistics"? Does the FW collect them from   
>>
>> The statistics are maintained / updated by firmware and thus the name.
>>
>> Preemption is implemented partially in both the hardware and firmware.
>> The STATE MACHINE for preemption is in the firmware. The decision to
>> when to PREEMEPT / ASSEMBLE a packet is made in firmware.
>>
>> These preemption statistics are updated by the firmware based on the
>> action performed by the firmware. Driver can read these to know the
>> statistics of preemption. These stats will be able used by
>> ethtool_mm_stats once the support for Preemption is added in the driver.
> 
> That was going to be my next question. If the statistic is suitable 
> for a standard interface it should not be reported via ethtool -S.
> 

Sure. I will not report it via `ethtool -S`. This will only be reported
via ethtool_get_mm_stats. I will do something similar to
`icssg_miig_stats`. Have a boolean to indicate whether the stat is
getting reported by some standard interface or not.

> Please leave the stats for unimplemented features out.
> 

Sure. For now I will remove the FW_PREEMPT stats since the feature is
not implemented yet. Once the implementation is done, I will add the
stats to icssg_all_pa_stats() and read it via
emac_update_hardware_stats() and report it via ethtool_get_mm_stats.

>>>> +/* Incremented if a packet is dropped at PRU because of a rule violation */
>>>> +#define FW_DROPPED_PKT		0x00F8  
>>>
>>> Instead of adding comments here please add a file under
>>> Documentation/networking/device_drivers/ with the explanations.
>>> That's far more likely to be discovered by users, no?  
>>
>> Sure I will drop these MACRO comments and create a .rst file in
>> Documentation/networking/device_drivers/
>>
>> One question though, should I create a table for the stats and it's
>> description or should I create a section for each stats?
>>
>> Something like this,
>>
>> FW_RTU_PKT_DROP
>> ---------------
> 
> Let's document the user-visible names! The strings from ethtool -S
> 
>> Diagnostic error counter which increments when RTU drops a locally
>> injected packet due to port being disabled or rule violation.
>>
>> Please let me know what do you think.
> 
> Taking inspiration from:
>   Documentation/networking/device_drivers/ethernet/meta/fbnic.rst
> should be a safe choice, I hope.

This looks to be a good choice. I will do the changes and send out a v2.
Thanks for the review.

-- 
Thanks and Regards,
Danish


From peter.chen at cixtech.com  Tue Mar  4 21:38:20 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:20 +0800
Subject: [PATCH v4 3/6] arm64: Kconfig: add ARCH_CIX for cix silicons
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-4-peter.chen@cixtech.com>

From: Fugang Duan <fugang.duan at cixtech.com>

Add ARCH_CIX for CIX SoC series support.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v4:
- Add Krzysztof Kozlowski's Reviewed-by Tag

 arch/arm64/Kconfig.platforms | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 02f9248f7c84..abe41db9b9b3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -106,6 +106,12 @@ config ARCH_BLAIZE
 	help
 	  This enables support for the Blaize SoC family
 
+config ARCH_CIX
+	bool "Cixtech SoC family"
+	help
+	  This enables support for the Cixtech SoC family,
+	  like P1(sky1).
+
 config ARCH_EXYNOS
 	bool "Samsung Exynos SoC family"
 	select COMMON_CLK_SAMSUNG
-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:19 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:19 +0800
Subject: [PATCH v4 2/6] dt-bindings: arm: add CIX P1 (SKY1) SoC
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-3-peter.chen@cixtech.com>

Add device tree bindings for CIX P1 (Internal name sky1) Arm SoC,
it consists several SoC models like CP8180, CD8180, etc.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 .../devicetree/bindings/arm/cix.yaml          | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml

diff --git a/Documentation/devicetree/bindings/arm/cix.yaml b/Documentation/devicetree/bindings/arm/cix.yaml
new file mode 100644
index 000000000000..114dab4bc4d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cix.yaml
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/cix.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CIX platforms
+
+maintainers:
+  - Peter Chen <peter.chen at cixtech.com>
+  - Fugang Duan <fugang.duan at cixtech.com>
+
+properties:
+  $nodename:
+    const: '/'
+  compatible:
+    oneOf:
+
+      - description: Radxa Orion O6
+        items:
+          - const: radxa,orion-o6
+          - const: cix,sky1
+
+additionalProperties: true
+
+...
-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:23 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:23 +0800
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-7-peter.chen@cixtech.com>

Using this entry as the maintainers information for CIX SKY series SoCs.

Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v4
- Add two dts files as maintained files

 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index efee40ea589f..edf26cf11ee2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2354,6 +2354,16 @@ F:	arch/arm/boot/compressed/misc-ep93xx.h
 F:	arch/arm/mach-ep93xx/
 F:	drivers/iio/adc/ep93xx_adc.c
 
+ARM/CIX SKY ARM ARCHITECTURE
+M:	Peter Chen <peter.chen at cixtech.com>
+M:	Fugang Duan <fugang.duan at cixtech.com>
+R:	CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/arm/cix.yaml
+F:	arch/arm64/boot/dts/cix/sky1-orion-o6.dts
+F:	arch/arm64/boot/dts/cix/sky1.dtsi
+
 ARM/CLKDEV SUPPORT
 M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:17 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:17 +0800
Subject: [PATCH v4 0/6] arm64: Introduce CIX P1 (SKY1) SoC
Message-ID: <20250305053823.2048217-1-peter.chen@cixtech.com>

Cixtech P1 (internal name sky1) is high performance generic Armv9 SoC.
Orion O6 is the world's first open source Arm V9 Motherboard built by
Radxa. You could find brief introduction for SoC and related boards at:
https://radxa.com/products/orion/o6#overview

In this series, we add initial SoC and board support for Kernel building.
Patch 1-2: Add dt-binding doc for CIX and its sky1 SoC
Patch 3: add related maintainers entry
Patch 4-5: add Arm64 build support
Patch 6: add initial dts support for SoC and Orion O6 board

To run upstream kernel at Orion O6 board, you need to use BIOS
released by Radxa:
https://docs.radxa.com/en/orion/o6/bios/install-bios

Changes for v4:
- Move add MAINTAINERS entry patch to the last, and add two dts files entry in it. 
- Add three Krzysztof Kozlowski's Reviewed-by Tags
- For sky1.dtsi, makes below changes:
	- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
	get its handle
	- Remove gic-v3's #redistributor-regions and redistributor-stride properties
	- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
	- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
	- Remove timer's clock frequency due to firmware has already set it

Changes for v3:
- Patch 1: Add Krzysztof Kozlowski's Acked-by Tag
- Patch 2: Add Krzysztof Kozlowski's Reviewed-by Tag
- Patch 6: Fix two dts coding sytle issues

Changes for v2:
- Pass dts build check with below commands:
make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=vendor-prefixes.yaml
make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=arm/cix.yaml
make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
- Re-order the patch set, and move vendor-perfixes to the 1st patch.
- Patch 4: Ordered Kconfig config entry by alpha-numerically
- Patch 5: Corrects the Ack tag's name
- Patch 6: see below.
1) Corrects the SoF tag's name
2) Fix several coding sytle issues
3) move linux,cma node to dts file
4) delete memory node, memory size is passed by firmware
5) delete uart2 node which will be added in future patches
6) Improve for pmu and cpu node to stands for more specific cpu model
7) Improve the timer node and add hypervisor virtual timer irq

Fugang Duan (1):
  arm64: Kconfig: add ARCH_CIX for cix silicons

Peter Chen (5):
  dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
  dt-bindings: arm: add CIX P1 (SKY1) SoC
  arm64: defconfig: Enable CIX SoC
  arm64: dts: cix: add initial CIX P1(SKY1) dts support
  MAINTAINERS: Add CIX SoC maintainer entry

 .../devicetree/bindings/arm/cix.yaml          |  26 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |  10 +
 arch/arm64/Kconfig.platforms                  |   6 +
 arch/arm64/boot/dts/Makefile                  |   1 +
 arch/arm64/boot/dts/cix/Makefile              |   2 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |  26 ++
 arch/arm64/boot/dts/cix/sky1.dtsi             | 222 ++++++++++++++++++
 arch/arm64/configs/defconfig                  |   1 +
 9 files changed, 296 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml
 create mode 100644 arch/arm64/boot/dts/cix/Makefile
 create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
 create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi

-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:22 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:22 +0800
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-6-peter.chen@cixtech.com>

CIX SKY1 SoC is high performance Armv9 SoC designed by Cixtech,
and Orion O6 is open source motherboard launched by Radxa.
See below for detail:
https://docs.radxa.com/en/orion/o6/getting-started/introduction

In this commit, it only adds limited components for running initramfs
at Orion O6.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v4:
- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
get its handle
- Remove gic-v3's #redistributor-regions and redistributor-stride properties
- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
- Remove timer's clock frequency due to firmware has already set it
- Add Krzysztof Kozlowski's reviewed-by
Changes for v3:
- Fix two dts coding sytle issues 
Changes for v2:
- Corrects the SoF tag's name
- Fix several coding sytle issues
- move linux,cma node to dts file
- delete memory node, memory size is passed by firmware
- delete uart2 node which will be added in future patches
- Improve for pmu and cpu node to stands for more specific cpu model
- Improve the timer node and add hypervisor virtual timer irq
- Pass "make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb"

 arch/arm64/boot/dts/Makefile              |   1 +
 arch/arm64/boot/dts/cix/Makefile          |   2 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts |  26 +++
 arch/arm64/boot/dts/cix/sky1.dtsi         | 222 ++++++++++++++++++++++
 4 files changed, 251 insertions(+)
 create mode 100644 arch/arm64/boot/dts/cix/Makefile
 create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
 create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 79b73a21ddc2..8e7ccd0027bd 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -13,6 +13,7 @@ subdir-y += bitmain
 subdir-y += blaize
 subdir-y += broadcom
 subdir-y += cavium
+subdir-y += cix
 subdir-y += exynos
 subdir-y += freescale
 subdir-y += hisilicon
diff --git a/arch/arm64/boot/dts/cix/Makefile b/arch/arm64/boot/dts/cix/Makefile
new file mode 100644
index 000000000000..ed3713982012
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_CIX) += sky1-orion-o6.dtb
diff --git a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
new file mode 100644
index 000000000000..78f4fcd87216
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2025 Cix Technology Group Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "sky1.dtsi"
+/ {
+	model = "Radxa Orion O6";
+	compatible = "radxa,orion-o6", "cix,sky1";
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x0 0x28000000>;
+			linux,cma-default;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
new file mode 100644
index 000000000000..5c5a2d1144c1
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/sky1.dtsi
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2025 Cix Technology Group Co., Ltd.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu1: cpu at 100 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu2: cpu at 200 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x200>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu3: cpu at 300 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x300>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu4: cpu at 400 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x400>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu5: cpu at 500 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x500>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu6: cpu at 600 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x600>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu7: cpu at 700 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x700>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu8: cpu at 800 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x800>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu9: cpu at 900 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x900>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu10: cpu at a00 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0xa00>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu11: cpu at b00 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0xb00>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+				core4 {
+					cpu = <&cpu4>;
+				};
+				core5 {
+					cpu = <&cpu5>;
+				};
+				core6 {
+					cpu = <&cpu6>;
+				};
+				core7 {
+					cpu = <&cpu7>;
+				};
+				core8 {
+					cpu = <&cpu8>;
+				};
+				core9 {
+					cpu = <&cpu9>;
+				};
+				core10 {
+					cpu = <&cpu10>;
+				};
+				core11 {
+					cpu = <&cpu11>;
+				};
+			};
+		};
+	};
+
+	pmu-a520 {
+		compatible = "arm,cortex-a520-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
+	};
+
+	pmu-a720 {
+		compatible = "arm,cortex-a720-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
+	};
+
+	pmu-spe {
+		compatible = "arm,statistical-profiling-extension-v1";
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	soc at 0 {
+		compatible = "simple-bus";
+		ranges = <0 0 0 0 0x20 0>;
+		dma-ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		gic: interrupt-controller at e010000 {
+			compatible = "arm,gic-v3";
+			reg = <0x0 0x0e010000 0 0x10000>,	/* GICD */
+			      <0x0 0x0e090000 0 0x300000>;       /* GICR * 12 */
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW 0>;
+			#interrupt-cells = <4>;
+			interrupt-controller;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			gic_its: msi-controller at e050000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x0e050000 0x0 0x30000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+
+			ppi-partitions {
+				ppi_partition0: interrupt-partition-0 {
+					affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
+				};
+
+				ppi_partition1: interrupt-partition-1 {
+					affinity = <&cpu4 &cpu5 &cpu6 &cpu7 &cpu8 &cpu9 &cpu10 &cpu11>;
+				};
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 12 IRQ_TYPE_LEVEL_LOW 0>;
+	};
+};
-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:21 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:21 +0800
Subject: [PATCH v4 4/6] arm64: defconfig: Enable CIX SoC
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-5-peter.chen@cixtech.com>

Enable CIX SoC support at ARM64 defconfig

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v4:
- Add Krzysztof Kozlowski's Reviewed-by Tag

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..1dd46d200401 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -45,6 +45,7 @@ CONFIG_ARCH_BCMBCA=y
 CONFIG_ARCH_BRCMSTB=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_ARCH_BLAIZE=y
+CONFIG_ARCH_CIX=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_ARCH_SPARX5=y
 CONFIG_ARCH_K3=y
-- 
2.25.1



From peter.chen at cixtech.com  Tue Mar  4 21:38:18 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed,  5 Mar 2025 13:38:18 +0800
Subject: [PATCH v4 1/6] dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <20250305053823.2048217-2-peter.chen@cixtech.com>

CIX Technology Group Co., Ltd. is a high performance Arm SoC design
company. Link: https://www.cixtech.com/.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 5079ca6ce1d1..5e76223e4570 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -302,6 +302,8 @@ patternProperties:
     description: Cirrus Logic, Inc.
   "^cisco,.*":
     description: Cisco Systems, Inc.
+  "^cix,.*":
+    description: CIX Technology Group Co., Ltd.
   "^clockwork,.*":
     description: Clockwork Tech LLC
   "^cloos,.*":
-- 
2.25.1



From manivannan.sadhasivam at linaro.org  Tue Mar  4 21:47:29 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Wed, 5 Mar 2025 11:17:29 +0530
Subject: [PATCH v2 6/8] PCI: brcmstb: Use same constant table for config
 space access
In-Reply-To: <CA+-6iNw2i=4KVr+VYOxacWpP7Pw0E5mDwKY1i9_6V_hjxu9neQ@mail.gmail.com>
References: <20250214173944.47506-1-james.quinlan@broadcom.com>
 <20250214173944.47506-7-james.quinlan@broadcom.com>
 <20250304150838.23ca5qbhm4yrpa3h@thinkpad>
 <CA+-6iNzOWU1qLfmSiThdYXX0v5RkbUYtf52yk6KXm6yDDNRUnw@mail.gmail.com>
 <20250304165808.t46fh6fwpardheup@thinkpad>
 <CA+-6iNw2i=4KVr+VYOxacWpP7Pw0E5mDwKY1i9_6V_hjxu9neQ@mail.gmail.com>
Message-ID: <20250305054729.5jkxen5vahoxvlrr@thinkpad>

On Tue, Mar 04, 2025 at 12:37:26PM -0500, Jim Quinlan wrote:
> On Tue, Mar 4, 2025 at 11:58?AM Manivannan Sadhasivam
> <manivannan.sadhasivam at linaro.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 11:37:14AM -0500, Jim Quinlan wrote:
> > > On Tue, Mar 4, 2025 at 10:08?AM Manivannan Sadhasivam
> > > <manivannan.sadhasivam at linaro.org> wrote:
> > > >
> > > > On Fri, Feb 14, 2025 at 12:39:34PM -0500, Jim Quinlan wrote:
> > > > > The constants EXT_CFG_DATA and EXT_CFG_INDEX vary by SOC. One of the
> > > > > map_bus methods used these constants, the other used different constants.
> > > > > Fortunately there was no problem because the SoCs that used the latter
> > > > > map_bus method all had the same register constants.
> > > > >
> > > > > Remove the redundant constants and adjust the code to use them.  In
> > > > > addition, update EXT_CFG_DATA to use the 4k-page based config space access
> > > > > system, which is what the second map_bus method was already using.
> > > > >
> > > >
> > > > What is the effect of this change? Why is it required? Sounds like it got
> > > > sneaked in.
> > >
> > > Hello,
> > > There is no functional difference with this commit -- the code will
> > > behave the same.  A previous commit set up the "EXT_CFG_DATA" and
> > > "EXT_CFG_INDEX" constants in the offset table but one of the map_bus()
> > > methods did not use them, instead it relied on old generic #define
> > > constants.  This commit uses them and gets rid of the old #defines.
> > >
> >
> > My comment was about the change that modified the offset of EXT_CFG_DATA. This
> > was not justified properly.
> 
> Okay, got it.  You are referring to (for example)
> -      [EXT_CFG_DATA]          = 0x9004,
> +       [EXT_CFG_DATA]          = 0x8000,
> 
> We have two ways of accessing the config space: (1) by writing a full
> index and reading a  designated register (0x9004) and (2) by writing
> the index and then reading from a 4k register region (0x8000 +
> offset).  We previously used (1).  An update was made to use (2) but
> instead of updating EXT_CFG_DATA from 0x9004 to 0x8000,
> PCIE_EXT_CFG_DATA (0x8000) was used by the code of one of the map_bus
> methods.
> 
> This commit changes the code in the offending map_bus method to use
> the offset table for (2) and updates the offset table EXT_CFG_DATA to
> its proper value.
> 

Ok, this clarifies.

> If you want me to expand the commit message with the above text I can do that.
> 

No need. Krzysztof should be able to ammend the commit message for you.

- Mani

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Tue Mar  4 22:06:07 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Wed, 5 Mar 2025 11:36:07 +0530
Subject: [PATCH] PCI: controller: Restore PCI_REASSIGN_ALL_BUS when
 PCI_PROBE_ONLY is enabled
In-Reply-To: <55a33534-bff0-488c-a2a2-2898d54bd62f@windriver.com>
References: <20250117082428.129353-1-Bo.Sun.CN@windriver.com>
 <20250210103707.c5ubeaowk7xwt6p5@thinkpad>
 <df5d3c54-d436-43bb-8b40-665c020d6bb5@windriver.com>
 <20250214170057.o3ffoiuxn4hxqqqe@thinkpad>
 <55a33534-bff0-488c-a2a2-2898d54bd62f@windriver.com>
Message-ID: <20250305060607.ygsafql53h2ujwjp@thinkpad>

On Fri, Feb 28, 2025 at 07:58:10PM +0800, Bo Sun wrote:
> On 2/15/25 1:00 AM, Manivannan Sadhasivam wrote:
> > CAUTION: This email comes from a non Wind River email account!
> > Do not click links or open attachments unless you recognize the sender and know the content is safe.
> > 
> > On Wed, Feb 12, 2025 at 03:07:56PM +0800, Bo Sun wrote:
> > > On 2/10/25 18:37, Manivannan Sadhasivam wrote:
> > > > CAUTION: This email comes from a non Wind River email account!
> > > > Do not click links or open attachments unless you recognize the sender and know the content is safe.
> > > > 
> > > > On Fri, Jan 17, 2025 at 04:24:14PM +0800, Bo Sun wrote:
> > > > > On our Marvell OCTEON CN96XX board, we observed the following panic on
> > > > > the latest kernel:
> > > > > Unable to handle kernel NULL pointer dereference at virtual address 0000000000000080
> > > > > Mem abort info:
> > > > >     ESR = 0x0000000096000005
> > > > >     EC = 0x25: DABT (current EL), IL = 32 bits
> > > > >     SET = 0, FnV = 0
> > > > >     EA = 0, S1PTW = 0
> > > > >     FSC = 0x05: level 1 translation fault
> > > > > Data abort info:
> > > > >     ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
> > > > >     CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> > > > >     GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > > > > [0000000000000080] user address but active_mm is swapper
> > > > > Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
> > > > > Modules linked in:
> > > > > CPU: 9 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.13.0-rc7-00149-g9bffa1ad25b8 #1
> > > > > Hardware name: Marvell OcteonTX CN96XX board (DT)
> > > > > pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > > > > pc : of_pci_add_properties+0x278/0x4c8
> > > > > lr : of_pci_add_properties+0x258/0x4c8
> > > > > sp : ffff8000822ef9b0
> > > > > x29: ffff8000822ef9b0 x28: ffff000106dd8000 x27: ffff800081bc3b30
> > > > > x26: ffff800081540118 x25: ffff8000813d2be0 x24: 0000000000000000
> > > > > x23: ffff00010528a800 x22: ffff000107c50000 x21: ffff0001039c2630
> > > > > x20: ffff0001039c2630 x19: 0000000000000000 x18: ffffffffffffffff
> > > > > x17: 00000000a49c1b85 x16: 0000000084c07b58 x15: ffff000103a10f98
> > > > > x14: ffffffffffffffff x13: ffff000103a10f96 x12: 0000000000000003
> > > > > x11: 0101010101010101 x10: 000000000000002c x9 : ffff800080ca7acc
> > > > > x8 : ffff0001038fd900 x7 : 0000000000000000 x6 : 0000000000696370
> > > > > x5 : 0000000000000000 x4 : 0000000000000002 x3 : ffff8000822efa40
> > > > > x2 : ffff800081341000 x1 : ffff000107c50000 x0 : 0000000000000000
> > > > > Call trace:
> > > > >    of_pci_add_properties+0x278/0x4c8 (P)
> > > > >    of_pci_make_dev_node+0xe0/0x158
> > > > >    pci_bus_add_device+0x158/0x210
> > > > >    pci_bus_add_devices+0x40/0x98
> > > > >    pci_host_probe+0x94/0x118
> > > > >    pci_host_common_probe+0x120/0x1a0
> > > > >    platform_probe+0x70/0xf0
> > > > >    really_probe+0xb4/0x2a8
> > > > >    __driver_probe_device+0x80/0x140
> > > > >    driver_probe_device+0x48/0x170
> > > > >    __driver_attach+0x9c/0x1b0
> > > > >    bus_for_each_dev+0x7c/0xe8
> > > > >    driver_attach+0x2c/0x40
> > > > >    bus_add_driver+0xec/0x218
> > > > >    driver_register+0x68/0x138
> > > > >    __platform_driver_register+0x2c/0x40
> > > > >    gen_pci_driver_init+0x24/0x38
> > > > >    do_one_initcall+0x4c/0x278
> > > > >    kernel_init_freeable+0x1f4/0x3d0
> > > > >    kernel_init+0x28/0x1f0
> > > > >    ret_from_fork+0x10/0x20
> > > > > Code: aa1603e1 f0005522 d2800044 91000042 (f94040a0)
> > > > > 
> > > > > This regression was introduced by commit 7246a4520b4b ("PCI: Use
> > > > > preserve_config in place of pci_flags"). On our board, the 002:00:07.0
> > > > > bridge is misconfigured by the bootloader. Both its secondary and
> > > > > subordinate bus numbers are initialized to 0, while its fixed secondary
> > > > > bus number is set to 8.
> > > > 
> > > > What do you mean by 'fixed secondary bus number'?
> > > > 
> > > 
> > > The 'fixed secondary bus number' refers to the value returned by the
> > > function pci_ea_fixed_busnrs(), which reads the fixed Secondary and
> > > Subordinate bus numbers from the EA (Extended Attributes) capability, if
> > > present.
> > 
> > Thanks! It'd be good to mention the EA capability.
> > 
> > > In the code at drivers/pci/probe.c, line 1439, we have the
> > > following:
> > > 
> > >                /* Read bus numbers from EA Capability (if present) */
> > >                fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
> > >                if (fixed_buses)
> > >                        next_busnr = fixed_sec;
> > >                else
> > >                        next_busnr = max + 1;
> > > 
> > > > > However, bus number 8 is also assigned to another
> > > > > bridge (0002:00:0f.0). Although this is a bootloader issue, before the
> > > > > change in commit 7246a4520b4b, the PCI_REASSIGN_ALL_BUS flag was
> > > > > set by default when PCI_PROBE_ONLY was enabled, ensuing that all the
> > > > > bus number for these bridges were reassigned, avoiding any conflicts.
> > > > > 
> > > > 
> > > > Isn't the opposite? PCI_REASSIGN_ALL_BUS was only added if the PCI_PROBE_ONLY
> > > > flag was not set:
> > > > 
> > > >           /* Do not reassign resources if probe only */
> > > >           if (!pci_has_flag(PCI_PROBE_ONLY))
> > > >                   pci_add_flags(PCI_REASSIGN_ALL_BUS);
> > > > 
> > > 
> > > Yes, you are correct. It?s a typo; it should be "when PCI_PROBE_ONLY was not
> > > enabled." I will fix this in v2.
> > > 
> > > > 
> > > > > After the change introduced in commit 7246a4520b4b, the bus numbers
> > > > > assigned by the bootloader are reused by all other bridges, except
> > > > > the misconfigured 002:00:07.0 bridge. The kernel attempt to reconfigure
> > > > > 002:00:07.0 by reusing the fixed secondary bus number 8 assigned by
> > > > > bootloader. However, since a pci_bus has already been allocated for
> > > > > bus 8 due to the probe of 0002:00:0f.0, no new pci_bus allocated for
> > > > > 002:00:07.0.
> > > > 
> > > > How come 0002:00:0f.0 is enumerated before 0002:00:07.0 in a depth first manner?
> > > > 
> > > 
> > > The device 0002:00:07.0 is actually enumerated before 0002:00:0f.0, but it
> > > appears misconfigured. The kernel attempts to reconfigure it during
> > > initialization, which is where the issue arises.
> > > 
> > 
> > Ok, thanks for the clarification. I think the bug is in this part of the code:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/probe.c#n1451
> > 
> > It just reuses the fixed bus number even if the bus already exists, which is
> > wrong. I think this should be fixed by evaluating the bus number read from EA
> > capability as below:
> > 
> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> > index b6536ed599c3..097e2a01faae 100644
> > --- a/drivers/pci/probe.c
> > +++ b/drivers/pci/probe.c
> > @@ -1438,10 +1438,21 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
> > 
> >                  /* Read bus numbers from EA Capability (if present) */
> >                  fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
> > -               if (fixed_buses)
> > -                       next_busnr = fixed_sec;
> > -               else
> > +               if (fixed_buses) {
> > +                       /*
> > +                        * If the fixed bus number is already taken, use the
> > +                        * next available bus number. This can happen if the
> > +                        * bootloader has assigned a wrong bus number in EA
> > +                        * capability of the bridge.
> > +                        */
> > +                       child = pci_find_bus(pci_domain_nr(bus), fixed_sec);
> > +                       if (child)
> > +                               next_busnr = max + 1;
> > +                       else
> > +                               next_busnr = fixed_sec;
> > +               } else {
> >                          next_busnr = max + 1;
> > +               }
> > 
> >                  /*
> >                   * Prevent assigning a bus number that already exists.
> 
> You proposed solution doesn't work on our Marvell OCTEON CN96XX board.
> 
> When probing the bus 0002:00, the bus number preset by the bootloader for
> the bridges under this bus start with 0xf9. Before configure of
> 0002:00:07.0, the 'max' bus number has already reached 0xff. With your
> proposed fix, the next_busnr is set to (0xff + 1), which evaluate to 0x100.
> This results in a 0 being assigned to the secondary bus number of
> 0002:00:07.0 bridge, causing a recursive bus probe.
> 

Oops. This is turning out to be too much of a problem.

> For reference, you can take a look at the code in probe.c and the
> corresponding log.
> 
>     pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
> 
>     primary = buses & 0xFF;
> 
>     secondary = (buses >> 8) & 0xFF;
> 
>     subordinate = (buses >> 16) & 0xFF;
> 
> 
>     pci_dbg(dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
> 
>         secondary, subordinate, pass);
> 
> pci_bus 0002:00: fixups for bus
> pci 0002:00:00.0: scanning [bus f9-f9] behind bridge, pass 0
> pci_bus 0002:f9: scanning bus
> pci_bus 0002:f9: fixups for bus
> pci_bus 0002:f9: bus scan returning with max=f9
> ...
> pci 0002:00:06.0: scanning [bus ff-ff] behind bridge, pass 0
> pci_bus 0002:ff: scanning bus
> pci_bus 0002:ff: fixups for bus
> pci_bus 0002:ff: bus scan returning with max=ff
> pci 0002:00:07.0: scanning [bus 00-00] behind bridge, pass 0
> pci 0002:00:07.0: bridge configuration invalid ([bus 00-00]), reconfiguring
> ...
> Kernel panic - not syncing: kernel stack overflow
> CPU: 12 UID: 0 PID: 1 Comm: swapper/0 Not tainted
> 6.14.0-rc4-00091-ga58485af8826 #16
> Hardware name: Marvell OcteonTX CN96XX board (DT)
> Call trace:
>  show_stack+0x20/0x38 (C)
>  dump_stack_lvl+0x38/0x90
>  dump_stack+0x18/0x28
>  panic+0x3ac/0x3c8
>  nmi_panic+0x48/0xa0
>  panic_bad_stack+0x118/0x140
>  handle_bad_stack+0x34/0x38
>  __bad_stack+0x80/0x88
>  format_decode+0x4/0x2e8 (P)
>  va_format.constprop.0+0x74/0x130
>  pointer+0x204/0x4f8
>  vsnprintf+0x2c4/0x5a0
>  vscnprintf+0x34/0x58
>  printk_sprint+0x48/0x170
>  vprintk_store+0x2d0/0x478
>  vprintk_emit+0xb0/0x2b0
>  dev_vprintk_emit+0xe0/0x1b0
>  dev_printk_emit+0x60/0x90
>  __dev_printk+0x44/0x98
>  _dev_printk+0x5c/0x90
>  pci_scan_child_bus_extend+0x5c/0x2c0
>  pci_scan_bridge_extend+0x16c/0x630
>  pci_scan_child_bus_extend+0xfc/0x2c0
>  pci_scan_bridge_extend+0x320/0x630
>  pci_scan_child_bus_extend+0x1b0/0x2c0
>  pci_scan_bridge_extend+0x320/0x630
> 
> So, I propose the following solution as a workaround to handle these edge
> cases.
> 
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 82b21e34c545..af8efebc7e7d 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -6181,6 +6181,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1536,
> rom_bar_overlap_defect);
>  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1537,
> rom_bar_overlap_defect);
>  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1538,
> rom_bar_overlap_defect);
> 
> +static void quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr(struct pci_dev
> *dev)
> +{
> +       if (!pci_has_flag(PCI_PROBE_ONLY))
> +               pci_add_flags(PCI_REASSIGN_ALL_BUS);
> +}
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CAVIUM, 0xa002,
> quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr);
> +

LGTM. Please add a comment about this quirk too.

- Mani

-- 
????????? ????????


From ming.qian at oss.nxp.com  Tue Mar  4 22:26:29 2025
From: ming.qian at oss.nxp.com (ming.qian at oss.nxp.com)
Date: Wed,  5 Mar 2025 14:26:29 +0800
Subject: [PATCH v3 1/2] media: amphion: Reduce decoding latency for HEVC decoder
Message-ID: <20250305062630.2329032-1-ming.qian@oss.nxp.com>

From: Ming Qian <ming.qian at oss.nxp.com>

The amphion decoder firmware supports a low latency flush mode for the
HEVC format since v1.9.0. This feature, which is enabled when the
display delay is set to 0, can help to reduce the decoding latency by
appending some padding data to every frame.

Signed-off-by: Ming Qian <ming.qian at oss.nxp.com>
---
v3
- Improve commit message as recommended
v2
- Improve commit message
- Add firmware version check

 drivers/media/platform/amphion/vpu_malone.c | 22 ++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c
index 5c6b2a841b6f..1d9e10d9bec1 100644
--- a/drivers/media/platform/amphion/vpu_malone.c
+++ b/drivers/media/platform/amphion/vpu_malone.c
@@ -68,6 +68,9 @@
 
 #define MALONE_DEC_FMT_RV_MASK			BIT(21)
 
+#define MALONE_VERSION_MASK			0xFFFFF
+#define MALONE_MIN_VERSION_HEVC_BUFFLUSH	(((1 << 16) | (9 << 8) | 0) & MALONE_VERSION_MASK)
+
 enum vpu_malone_stream_input_mode {
 	INVALID_MODE = 0,
 	FRAME_LVL,
@@ -332,6 +335,8 @@ struct vpu_dec_ctrl {
 	u32 buf_addr[VID_API_NUM_STREAMS];
 };
 
+static const struct malone_padding_scode *get_padding_scode(u32 type, u32 fmt);
+
 u32 vpu_malone_get_data_size(void)
 {
 	return sizeof(struct vpu_dec_ctrl);
@@ -654,9 +659,16 @@ static int vpu_malone_set_params(struct vpu_shared_addr *shared,
 		hc->jpg[instance].jpg_mjpeg_interlaced = 0;
 	}
 
-	hc->codec_param[instance].disp_imm = params->display_delay_enable ? 1 : 0;
-	if (malone_format != MALONE_FMT_AVC)
+	if (params->display_delay_enable &&
+	    get_padding_scode(SCODE_PADDING_BUFFLUSH, params->codec_format))
+		hc->codec_param[instance].disp_imm = 1;
+	else
 		hc->codec_param[instance].disp_imm = 0;
+
+	if (params->codec_format == V4L2_PIX_FMT_HEVC &&
+	    (iface->fw_version & MALONE_VERSION_MASK) < MALONE_MIN_VERSION_HEVC_BUFFLUSH)
+		hc->codec_param[instance].disp_imm = 0;
+
 	hc->codec_param[instance].dbglog_enable = 0;
 	iface->dbglog_desc.level = 0;
 
@@ -1024,6 +1036,7 @@ static const struct malone_padding_scode padding_scodes[] = {
 	{SCODE_PADDING_EOS,      V4L2_PIX_FMT_JPEG,        {0x0, 0x0}},
 	{SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264,        {0x15010000, 0x0}},
 	{SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264_MVC,    {0x15010000, 0x0}},
+	{SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_HEVC,        {0x3e010000, 0x20}},
 };
 
 static const struct malone_padding_scode padding_scode_dft = {0x0, 0x0};
@@ -1058,8 +1071,11 @@ static int vpu_malone_add_padding_scode(struct vpu_buffer *stream_buffer,
 	int ret;
 
 	ps = get_padding_scode(scode_type, pixelformat);
-	if (!ps)
+	if (!ps) {
+		if (scode_type == SCODE_PADDING_BUFFLUSH)
+			return 0;
 		return -EINVAL;
+	}
 
 	wptr = readl(&str_buf->wptr);
 	if (wptr < stream_buffer->phys || wptr > stream_buffer->phys + stream_buffer->length)
-- 
2.43.0-rc1



From ming.qian at oss.nxp.com  Tue Mar  4 22:26:30 2025
From: ming.qian at oss.nxp.com (ming.qian at oss.nxp.com)
Date: Wed,  5 Mar 2025 14:26:30 +0800
Subject: [PATCH v3 2/2] media: amphion: Add a frame flush mode for decoder
In-Reply-To: <20250305062630.2329032-1-ming.qian@oss.nxp.com>
References: <20250305062630.2329032-1-ming.qian@oss.nxp.com>
Message-ID: <20250305062630.2329032-2-ming.qian@oss.nxp.com>

From: Ming Qian <ming.qian at oss.nxp.com>

By default the amphion decoder will pre-parse 3 frames before starting
to decode the first frame. Alternatively, a block of flush padding data
can be appended to the frame, which will ensure that the decoder can
start decoding immediately after parsing the flush padding data, thus
potentially reducing decoding latency.

This mode was previously only enabled, when the display delay was set to
0. Allow the user to manually toggle the use of that mode via a module
parameter called frame_flush_mode, which enables the mode without
changing the display order.

Signed-off-by: Ming Qian <ming.qian at oss.nxp.com>
---
v3
- Improve commit message as recommended
- Add some comments to avoid code looks cryptic

 drivers/media/platform/amphion/vpu_malone.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c
index 1d9e10d9bec1..4ef9810d8142 100644
--- a/drivers/media/platform/amphion/vpu_malone.c
+++ b/drivers/media/platform/amphion/vpu_malone.c
@@ -25,6 +25,10 @@
 #include "vpu_imx8q.h"
 #include "vpu_malone.h"
 
+static bool frame_flush_mode;
+module_param(frame_flush_mode, bool, 0644);
+MODULE_PARM_DESC(frame_flush_mode, "Set low latency flush mode: 0 (disable) or 1 (enable)");
+
 #define CMD_SIZE			25600
 #define MSG_SIZE			25600
 #define CODEC_SIZE			0x1000
@@ -1579,7 +1583,15 @@ static int vpu_malone_input_frame_data(struct vpu_malone_str_buffer __iomem *str
 
 	vpu_malone_update_wptr(str_buf, wptr);
 
-	if (disp_imm && !vpu_vb_is_codecconfig(vbuf)) {
+	/*
+	 * Enable the low latency flush mode if display delay is set to 0
+	 * or parameter frame_flush_mode is set to 1.
+	 * The low latency flush mode requires some padding data to be appended after each frame,
+	 * but don't put it in between the sequence header and frame.
+	 * Only H264 and HEVC decoder support this module yet,
+	 * for other formats, vpu_malone_add_scode() will return 0.
+	 */
+	if ((disp_imm || frame_flush_mode) && !vpu_vb_is_codecconfig(vbuf)) {
 		ret = vpu_malone_add_scode(inst->core->iface,
 					   inst->id,
 					   &inst->stream_buffer,
-- 
2.43.0-rc1



From aakarsh.jain at samsung.com  Tue Mar  4 21:53:07 2025
From: aakarsh.jain at samsung.com (Aakarsh Jain)
Date: Wed,  5 Mar 2025 11:23:07 +0530
Subject: [Patch v3] media: s5p-mfc: Corrected NV12M/NV21M plane-sizes
References: <CGME20250305055904epcas5p45828c732019a847a0852c26d9ef9f2db@epcas5p4.samsung.com>
Message-ID: <20250305055308.111300-1-aakarsh.jain@samsung.com>

There is a possibility of getting page fault if the overall
buffer size is not aligned to 256bytes. Since MFC does read
operation only and it won't corrupt the data values even if
it reads the extra bytes.
Corrected luma and chroma plane sizes for V4L2_PIX_FMT_NV12M
and V4L2_PIX_FMT_NV21M pixel format.

Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
Suggested-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
Signed-off-by: Aakarsh Jain <aakarsh.jain at samsung.com>
---
changelog:
v2->v3
Patch link:https://patchwork.kernel.org/project/linux-media/patch/20250226102251.9040-1-aakarsh.jain at samsung.com/
Fixed checkpatch warning.

v1->v2
Patch link: https://patchwork.kernel.org/project/linux-media/patch/20240806115714.29828-1-aakarsh.jain at samsung.com/
Removed duplicate code and aligned luma and chroma size
to multiple of 256bytes as suggested by Hans.
 drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
index 73f7af674c01..4cf12f33d706 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
@@ -549,8 +549,9 @@ static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
 		case V4L2_PIX_FMT_NV21M:
 			ctx->stride[0] = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
 			ctx->stride[1] = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
-			ctx->luma_size = ctx->stride[0] * ALIGN(ctx->img_height, 16);
-			ctx->chroma_size =  ctx->stride[0] * ALIGN(ctx->img_height / 2, 16);
+			ctx->luma_size = ALIGN(ctx->stride[0] * ALIGN(ctx->img_height, 16), 256);
+			ctx->chroma_size = ALIGN(ctx->stride[0] *
+						ALIGN(ctx->img_height / 2, 16), 256);
 			break;
 		case V4L2_PIX_FMT_YUV420M:
 		case V4L2_PIX_FMT_YVU420M:
-- 
2.17.1



From aakarsh.jain at samsung.com  Tue Mar  4 21:53:08 2025
From: aakarsh.jain at samsung.com (Aakarsh Jain)
Date: Wed,  5 Mar 2025 11:23:08 +0530
Subject: [Patch v2] media: s5p-mfc: Support for handling RET_ENC_BUFFER_FULL
 interrupt
In-Reply-To: <20250305055308.111300-1-aakarsh.jain@samsung.com>
References: <20250305055308.111300-1-aakarsh.jain@samsung.com>
	<CGME20250305055908epcas5p222e192cc21512ac178543445184a2519@epcas5p2.samsung.com>
Message-ID: <20250305055308.111300-2-aakarsh.jain@samsung.com>

When output encoded buffer size provided by userspace
is insufficient with current encoding parameters, it
leads to RET_ENC_BUFFER_FULL interrupt which was not
handled in IRQ handler.

On handling of RET_ENC_BUFFER_FULL interrupt leads to
NAL_ABORT command from host to risc which in turn leads
to RET_NAL_ABORT interrupt. On receiving RET_NAL_ABORT
driver clears workbit and VB2 queues for cleaner closing
of MFC instance.

When user encounters "Call on DQBUF after unrecoverable
error", userspace should close fd and restart with larger
output encoder buffer size.

Signed-off-by: Aakarsh Jain <aakarsh.jain at samsung.com>
---
changelog:
v1->v2
Patch link: https://patchwork.kernel.org/project/linux-media/patch/20250228065952.14375-1-aakarsh.jain at samsung.com/
Fixed build errors reported by Media CI robot.
 .../media/platform/samsung/s5p-mfc/regs-mfc-v6.h   |  1 +
 drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c   | 14 ++++++++++++++
 .../platform/samsung/s5p-mfc/s5p_mfc_common.h      |  1 +
 .../platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c      |  5 +++++
 4 files changed, 21 insertions(+)

diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
index fa49fe580e1a..075a58b50b8c 100644
--- a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
@@ -45,6 +45,7 @@
 #define S5P_FIMV_H2R_CMD_WAKEUP_V6		8
 #define S5P_FIMV_CH_LAST_FRAME_V6		9
 #define S5P_FIMV_H2R_CMD_FLUSH_V6		10
+#define S5P_FIMV_H2R_CMD_NAL_ABORT_V6		11
 /* RMVME: REALLOC used? */
 #define S5P_FIMV_CH_FRAME_START_REALLOC_V6	5
 
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
index 5f80931f056d..e764cab2485c 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
@@ -739,6 +739,20 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
 		ctx->state = MFCINST_RUNNING;
 		goto irq_cleanup_hw;
 
+	case S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET:
+		ctx->state = MFCINST_NAL_ABORT;
+		s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+		set_work_bit(ctx);
+		WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+		s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+		break;
+
+	case S5P_MFC_R2H_CMD_NAL_ABORT_RET:
+		ctx->state = MFCINST_ERROR;
+		s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+		s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+		goto irq_cleanup_hw;
+
 	default:
 		mfc_debug(2, "Unknown int reason\n");
 		s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
index 3cc2a4f5c40a..86c316c1ff8f 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
@@ -141,6 +141,7 @@ enum s5p_mfc_inst_state {
 	MFCINST_RES_CHANGE_INIT,
 	MFCINST_RES_CHANGE_FLUSH,
 	MFCINST_RES_CHANGE_END,
+	MFCINST_NAL_ABORT,
 };
 
 /*
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
index 4cf12f33d706..356adfddcfcf 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
@@ -2229,6 +2229,11 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
 		case MFCINST_HEAD_PRODUCED:
 			ret = s5p_mfc_run_init_enc_buffers(ctx);
 			break;
+		case MFCINST_NAL_ABORT:
+			mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+			s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc,
+					dev, S5P_FIMV_H2R_CMD_NAL_ABORT_V6, NULL);
+			break;
 		default:
 			ret = -EAGAIN;
 		}
-- 
2.17.1



From inbaraj.e at samsung.com  Tue Mar  4 21:56:55 2025
From: inbaraj.e at samsung.com (Inbaraj E)
Date: Wed,  5 Mar 2025 11:26:55 +0530
Subject: [PATCH] media: imx-mipi-csis: Fix v4l2 mbus frame descriptor type
References: <CGME20250305060259epcas5p20c02f4c4b4ff84b0f790b4ea446056e6@epcas5p2.samsung.com>
Message-ID: <20250305055655.6622-1-inbaraj.e@samsung.com>

For MIPI CSI2 v4l2 mbus frame descriptor type should be set to
V4L2_MBUS_FRAME_DESC_TYPE_CSI2. Now frame descriptor type is set to
V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL. So changing the frame descriptor
type to V4L2_MBUS_FRAME_DESC_TYPE_CSI2.

Fixes: d200de90de2a0 ("media: imx: imx-mipi-csis: Implement the .get_frame_desc() operation")
Signed-off-by: Inbaraj E <inbaraj.e at samsung.com>
---
 drivers/media/platform/nxp/imx-mipi-csis.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
index 29523bb84d95..bb6550bed230 100644
--- a/drivers/media/platform/nxp/imx-mipi-csis.c
+++ b/drivers/media/platform/nxp/imx-mipi-csis.c
@@ -1137,7 +1137,7 @@ static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 	if (!csis_fmt)
 		return -EPIPE;
 
-	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
 	fd->num_entries = 1;
 
 	entry->flags = 0;
-- 
2.17.1



From quic_yuanjiey at quicinc.com  Tue Mar  4 22:31:57 2025
From: quic_yuanjiey at quicinc.com (Yuanjie Yang)
Date: Wed, 5 Mar 2025 14:31:57 +0800
Subject: [PATCH v2] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <20241120103749.1450017-1-ping.bai@nxp.com>
References: <20241120103749.1450017-1-ping.bai@nxp.com>
Message-ID: <Z8fv3X0Pivh8zbMg@cse-cd02-lnx.ap.qualcomm.com>

On Wed, Nov 20, 2024 at 06:37:49PM +0800, Jacky Bai wrote:
> With 'nosmp' or 'maxcpus=0' boot command line parameters,
> the 'cpu_present_mask' may not be the same as 'cpu_possible_mask'.
> 
> In current psci cpuidle driver init, for_each_possible_cpu()
> is used to init the cpuidle for each possible CPU. but in
> drivers/base/cpu.c ->cpu_dev_register_generic(),
> for_each_present_cpu() is used to register cpu device for
> present CPUs.
> 
> When boot system with 'nosmp' or 'maxcpus=0', the cpuidle driver
> init failed due to no valid CPU device sysfs node for non-boot CPUs.
> 
> [ 0.182993] Failed to register cpuidle device for cpu1
> 
> Use for_each_present_cpu() to register cpuidle only for present
> CPUs.
> 
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> Reviewed-by: Dhruva Gole <d-gole at ti.com>
> ---
>  drivers/cpuidle/cpuidle-psci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 2562dc001fc1..00117e9b33e8 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -410,7 +410,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
>  	struct cpuidle_driver *drv;
>  	struct cpuidle_device *dev;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		ret = psci_idle_init_cpu(&pdev->dev, cpu);
>  		if (ret)
>  			goto out_fail;
> -- 
> 2.34.1
> 

Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>

I meet the same problem, and I test your patch, it is good to me.

Thanks,
Yuanjie


From krzk at kernel.org  Tue Mar  4 22:35:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 07:35:24 +0100
Subject: [PATCH] arm64: defconfig: Enable Rockchip UFS host driver
In-Reply-To: <1741147858-136859-1-git-send-email-shawn.lin@rock-chips.com>
References: <1741147858-136859-1-git-send-email-shawn.lin@rock-chips.com>
Message-ID: <0d4d1cea-350e-4ca4-954c-fdbe1b0acf93@kernel.org>

On 05/03/2025 05:10, Shawn Lin wrote:
> Enable Rockchip UFS host driver.
> 
> This driver is first introduced on RK3576 SoC, and will be

...on Rockchip RK3576 SoC...


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


Best regards,
Krzysztof


From inochiama at gmail.com  Tue Mar  4 22:39:16 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed,  5 Mar 2025 14:39:16 +0800
Subject: [PATCH net-next v6 4/4] net: stmmac: Add glue layer for Sophgo SG2044 SoC
In-Reply-To: <20250305063920.803601-1-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
Message-ID: <20250305063920.803601-5-inochiama@gmail.com>

Adds Sophgo dwmac driver support on the Sophgo SG2044 SoC.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   | 11 +++
 drivers/net/ethernet/stmicro/stmmac/Makefile  |  1 +
 .../ethernet/stmicro/stmmac/dwmac-sophgo.c    | 75 +++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 4cc85a36a1ab..b6ff51e1ebce 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -181,6 +181,17 @@ config DWMAC_SOCFPGA
 	  for the stmmac device driver. This driver is used for
 	  arria5 and cyclone5 FPGA SoCs.
 
+config DWMAC_SOPHGO
+	tristate "Sophgo dwmac support"
+	depends on OF && (ARCH_SOPHGO || COMPILE_TEST)
+	default m if ARCH_SOPHGO
+	help
+	  Support for ethernet controllers on Sophgo RISC-V SoCs
+
+	  This selects the Sophgo SoC specific glue layer support
+	  for the stmmac device driver. This driver is used for the
+	  ethernet controllers on various Sophgo SoCs.
+
 config DWMAC_STARFIVE
 	tristate "StarFive dwmac support"
 	depends on OF && (ARCH_STARFIVE || COMPILE_TEST)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index b26f0e79c2b3..594883fb4164 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_RZN1)	+= dwmac-rzn1.o
 obj-$(CONFIG_DWMAC_S32)		+= dwmac-s32.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
+obj-$(CONFIG_DWMAC_SOPHGO)	+= dwmac-sophgo.o
 obj-$(CONFIG_DWMAC_STARFIVE)	+= dwmac-starfive.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
 obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c
new file mode 100644
index 000000000000..3303784cbbf8
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sophgo DWMAC platform driver
+ *
+ * Copyright (C) 2024 Inochi Amaoto <inochiama at gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+
+#include "stmmac_platform.h"
+
+static int sophgo_sg2044_dwmac_init(struct platform_device *pdev,
+				    struct plat_stmmacenet_data *plat_dat,
+				    struct stmmac_resources *stmmac_res)
+{
+	plat_dat->clk_tx_i = devm_clk_get_enabled(&pdev->dev, "tx");
+	if (IS_ERR(plat_dat->clk_tx_i))
+		return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat->clk_tx_i),
+				     "failed to get tx clock\n");
+
+	plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE;
+	plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
+	plat_dat->multicast_filter_bins = 0;
+	plat_dat->unicast_filter_entries = 1;
+
+	return 0;
+}
+
+static int sophgo_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to get platform resources\n");
+
+	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return dev_err_probe(dev, PTR_ERR(plat_dat),
+				     "failed to parse DT parameters\n");
+
+	ret = sophgo_sg2044_dwmac_init(pdev, plat_dat, &stmmac_res);
+	if (ret)
+		return ret;
+
+	return stmmac_dvr_probe(dev, plat_dat, &stmmac_res);
+}
+
+static const struct of_device_id sophgo_dwmac_match[] = {
+	{ .compatible = "sophgo,sg2044-dwmac" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sophgo_dwmac_match);
+
+static struct platform_driver sophgo_dwmac_driver = {
+	.probe  = sophgo_dwmac_probe,
+	.remove = stmmac_pltfr_remove,
+	.driver = {
+		.name = "sophgo-dwmac",
+		.pm = &stmmac_pltfr_pm_ops,
+		.of_match_table = sophgo_dwmac_match,
+	},
+};
+module_platform_driver(sophgo_dwmac_driver);
+
+MODULE_AUTHOR("Inochi Amaoto <inochiama at gmail.com>");
+MODULE_DESCRIPTION("Sophgo DWMAC platform driver");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From inochiama at gmail.com  Tue Mar  4 22:39:14 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed,  5 Mar 2025 14:39:14 +0800
Subject: [PATCH net-next v6 2/4] net: stmmac: platform: Group GMAC4 compatible check
In-Reply-To: <20250305063920.803601-1-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
Message-ID: <20250305063920.803601-3-inochiama@gmail.com>

Use of_device_compatible_match to group existing compatible
check of GMAC4 device.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
---
 .../ethernet/stmicro/stmmac/stmmac_platform.c    | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index d0e61aa1a495..4a3fe44b780d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -405,6 +405,16 @@ static int stmmac_of_get_mac_mode(struct device_node *np)
 	return -ENODEV;
 }
 
+/* Compatible string array for all gmac4 devices */
+static const char * const stmmac_gmac4_compats[] = {
+	"snps,dwmac-4.00",
+	"snps,dwmac-4.10a",
+	"snps,dwmac-4.20a",
+	"snps,dwmac-5.10a",
+	"snps,dwmac-5.20",
+	NULL
+};
+
 /**
  * stmmac_probe_config_dt - parse device-tree driver parameters
  * @pdev: platform_device structure
@@ -538,11 +548,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
 		plat->pmt = 1;
 	}
 
-	if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
-	    of_device_is_compatible(np, "snps,dwmac-4.10a") ||
-	    of_device_is_compatible(np, "snps,dwmac-4.20a") ||
-	    of_device_is_compatible(np, "snps,dwmac-5.10a") ||
-	    of_device_is_compatible(np, "snps,dwmac-5.20")) {
+	if (of_device_compatible_match(np, stmmac_gmac4_compats)) {
 		plat->has_gmac4 = 1;
 		plat->has_gmac = 0;
 		plat->pmt = 1;
-- 
2.48.1



From fj5100bi at fujitsu.com  Tue Mar  4 22:40:28 2025
From: fj5100bi at fujitsu.com (Yoshihiro Furudera (Fujitsu))
Date: Wed, 5 Mar 2025 06:40:28 +0000
Subject: [PATCH] Remove some PMU events for FUJITSU-MONAKA
In-Reply-To: <OSZPR01MB6908AA7CEB24ED38F9289D6DD4CC2@OSZPR01MB6908.jpnprd01.prod.outlook.com>
References: <20250227054045.1340090-1-fj5100bi@fujitsu.com>
 <96b323eb-15b2-4b60-8522-83bf2f57694b@linaro.org>
 <OSZPR01MB6908AA7CEB24ED38F9289D6DD4CC2@OSZPR01MB6908.jpnprd01.prod.outlook.com>
Message-ID: <OS3PR01MB6903726FDA70250F72A73410D4CB2@OS3PR01MB6903.jpnprd01.prod.outlook.com>

Hi, James

> 
> Hi, James
> Thank you for your comment.
> 
> > On 27/02/2025 5:40 am, Yoshihiro Furudera wrote:
> > > The following events are not counted properly:
> > >
> > > 0x0037 LL_CACHE_MISS_RD
> > > 0x400B L3D_CACHE_LMISS_RD
> >
> > These two are discoverable so will still appear in
> > /sys/bus/event_source/devices/armv8_pmuv3_0/events/ if the hardware
> > says they exist. It might be better to change the json strings of
> > these two to warn that they don't work if that's the case, otherwise
> > Perf will still list them and you'll be worse off.
> 
> I will leave these 2 events and
> add a warning message to the description in the JSON file.
> I will handle other events in the same way as these 2 events.

I'm thinking of adding one of the following warnings
to the description of events where inaccurate counts 
occur on FUJITSU-MONAKA. 
Is this okay?

1.Simple version
"Note: This event does not count accurately."

2.Detailed version
"Note: This event does not count accurately because it counts as a miss regardless of whether the L3 prefetch is a hit or miss."

I think "2.Detailed version" is better.

example:
{
    "EventCode": "0x0396",
    "EventName": "L2D_CACHE_REFILL_L3D_MISS",
    "BriefDescription": "This event counts operations that cause a miss of the L3 cache. Note: This event does not count accurately because it counts as a miss regardless of whether the L3 prefetch is a hit or miss."
}

Best Regards,
Yoshihiro Furudera

From krzk at kernel.org  Tue Mar  4 22:38:49 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 07:38:49 +0100
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250304104434.481429-2-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
Message-ID: <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>

On 04/03/2025 11:44, Kevin Chen wrote:
> Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.

Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

Missing 's'.

> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> ---
>  .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 36 +++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> index 5dfe77aca167..367847bd7e75 100644
> --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> @@ -149,6 +149,35 @@ patternProperties:
>        - interrupts
>        - snoop-ports
>  
> +  "^lpc-pcc@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: false
> +
> +    description:
> +      The LPC pcc interface allows the BMC to listen on and record the data
> +      bytes written by the Host to the targeted LPC I/O pots.
> +
> +    properties:
> +      compatible:
> +        items:
> +          - enum:
> +              - aspeed,ast2600-lpc-pcc
> +
> +      reg:
> +        maxItems: 1
> +
> +      interrupts:
> +        maxItems: 1
> +
> +      pcc-ports:

Missing vendor prefix

> +        $ref: /schemas/types.yaml#/definitions/uint32-array
> +        description: The LPC I/O ports to pcc

Description is too vague. Why would we encode I/O ports as some numbers
instead of GPIOs for example? If these are ports, why this is not a graph?

Missing constraints - min/maxItems, defaults, minimum/maximum etc.

> +
> +    required:
> +      - compatible
> +      - interrupts
> +      - pcc-ports
> +
>    "^uart-routing@[0-9a-f]+$":
>      $ref: /schemas/soc/aspeed/uart-routing.yaml#
>      description: The UART routing control under LPC register space
> @@ -176,6 +205,13 @@ examples:
>          #size-cells = <1>;
>          ranges = <0x0 0x1e789000 0x1000>;
>  
> +        lpc_pcc: lpc-pcc at 0 {
> +            compatible = "aspeed,ast2600-lpc-pcc";
> +            reg = <0x0 0x140>;
> +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> +            pcc-ports = <0x80>;

So what 0x80 stands for?


Best regards,
Krzysztof


From inochiama at gmail.com  Tue Mar  4 22:39:12 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed,  5 Mar 2025 14:39:12 +0800
Subject: [PATCH net-next v6 0/4] riscv: sophgo: Add ethernet support for SG2044
Message-ID: <20250305063920.803601-1-inochiama@gmail.com>

The ethernet controller of SG2044 is Synopsys DesignWare IP with
custom clock. Add glue layer for it.

Changed from v5:
- https://lore.kernel.org/netdev/20250216123953.1252523-1-inochiama at gmail.com/
1. apply Andrew's tag for patch 2,3
3. patch 1: add dma-noncoherent property.
2. patch 2,3: separate original patch into 2 part
4. patch 4: adopt new stmmac_set_clk_tx_rate helper function

Changed from v4:
- https://lore.kernel.org/netdev/20250209013054.816580-1-inochiama at gmail.com/
1. apply Romain's tag
2. patch 3: use device variable to replace &pdev->dev.
3. patch 3: remove unused include.
4. patch 3: make error message more useful.

Changed from v3:
- https://lore.kernel.org/netdev/20241223005843.483805-1-inochiama at gmail.com/
1. rebase for 6.14.rc1
2. remove the dependency requirement as it was already merged
   into master.

Changed from RFC:
- https://lore.kernel.org/netdev/20241101014327.513732-1-inochiama at gmail.com/
1. patch 1: apply Krzysztof' tag

Changed from v2:
- https://lore.kernel.org/netdev/20241025011000.244350-1-inochiama at gmail.com/
1. patch 1: merge the first and the second bindings patch to show the all
            compatible change.
2. patch 2: use of_device_compatible_match helper function to perform check.
2. patch 3: remove unused include and sort the left.
3. patch 3: fix wrong variable usage in sophgo_dwmac_fix_mac_speed
4. patch 3: drop unused variable in the patch.

Changed from v1:
- https://lore.kernel.org/netdev/20241021103617.653386-1-inochiama at gmail.com/
1. patch 2: remove sophgo,syscon as this mac delay is resolved.
2. patch 2: apply all the properties unconditionally.
3. patch 4: remove sophgo,syscon code as this mac delay is resolved.
4. patch 4: use the helper function to compute rgmii clock.
5. patch 4: use remove instead of remove_new for the platform driver.

Inochi Amaoto (4):
  dt-bindings: net: Add support for Sophgo SG2044 dwmac
  net: stmmac: platform: Group GMAC4 compatible check
  net: stmmac: platform: Add snps,dwmac-5.30a IP compatible string
  net: stmmac: Add glue layer for Sophgo SG2044 SoC

 .../devicetree/bindings/net/snps,dwmac.yaml   |   4 +
 .../bindings/net/sophgo,sg2044-dwmac.yaml     | 126 ++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 ++
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-sophgo.c    |  75 +++++++++++
 .../ethernet/stmicro/stmmac/stmmac_platform.c |  17 ++-
 6 files changed, 229 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c

--
2.48.1



From inochiama at gmail.com  Tue Mar  4 22:39:13 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed,  5 Mar 2025 14:39:13 +0800
Subject: [PATCH net-next v6 1/4] dt-bindings: net: Add support for Sophgo SG2044 dwmac
In-Reply-To: <20250305063920.803601-1-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
Message-ID: <20250305063920.803601-2-inochiama@gmail.com>

The GMAC IP on SG2044 is almost a standard Synopsys DesignWare
MAC (version 5.30a) with some extra clock.

Add necessary compatible string for this device.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../devicetree/bindings/net/snps,dwmac.yaml   |   4 +
 .../bindings/net/sophgo,sg2044-dwmac.yaml     | 126 ++++++++++++++++++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml

diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 91e75eb3f329..02ab6a9aded2 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -32,6 +32,7 @@ select:
           - snps,dwmac-4.20a
           - snps,dwmac-5.10a
           - snps,dwmac-5.20
+          - snps,dwmac-5.30a
           - snps,dwxgmac
           - snps,dwxgmac-2.10
 
@@ -98,8 +99,10 @@ properties:
         - snps,dwmac-4.20a
         - snps,dwmac-5.10a
         - snps,dwmac-5.20
+        - snps,dwmac-5.30a
         - snps,dwxgmac
         - snps,dwxgmac-2.10
+        - sophgo,sg2044-dwmac
         - starfive,jh7100-dwmac
         - starfive,jh7110-dwmac
         - thead,th1520-gmac
@@ -631,6 +634,7 @@ allOf:
                 - snps,dwmac-4.20a
                 - snps,dwmac-5.10a
                 - snps,dwmac-5.20
+                - snps,dwmac-5.30a
                 - snps,dwxgmac
                 - snps,dwxgmac-2.10
                 - st,spear600-gmac
diff --git a/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
new file mode 100644
index 000000000000..4dd2dc9c678b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
@@ -0,0 +1,126 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/sophgo,sg2044-dwmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo SG2044 DWMAC glue layer
+
+maintainers:
+  - Inochi Amaoto <inochiama at gmail.com>
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - sophgo,sg2044-dwmac
+  required:
+    - compatible
+
+properties:
+  compatible:
+    items:
+      - const: sophgo,sg2044-dwmac
+      - const: snps,dwmac-5.30a
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: GMAC main clock
+      - description: PTP clock
+      - description: TX clock
+
+  clock-names:
+    items:
+      - const: stmmaceth
+      - const: ptp_ref
+      - const: tx
+
+  dma-noncoherent: true
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    const: stmmaceth
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - resets
+  - reset-names
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    ethernet at 30006000 {
+      compatible = "sophgo,sg2044-dwmac", "snps,dwmac-5.30a";
+      reg = <0x30006000 0x4000>;
+      clocks = <&clk 151>, <&clk 152>, <&clk 154>;
+      clock-names = "stmmaceth", "ptp_ref", "tx";
+      interrupt-parent = <&intc>;
+      interrupts = <296 IRQ_TYPE_LEVEL_HIGH>;
+      interrupt-names = "macirq";
+      resets = <&rst 30>;
+      reset-names = "stmmaceth";
+      snps,multicast-filter-bins = <0>;
+      snps,perfect-filter-entries = <1>;
+      snps,aal;
+      snps,tso;
+      snps,txpbl = <32>;
+      snps,rxpbl = <32>;
+      snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
+      snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
+      snps,axi-config = <&gmac0_stmmac_axi_setup>;
+      status = "disabled";
+
+      gmac0_mtl_rx_setup: rx-queues-config {
+        snps,rx-queues-to-use = <8>;
+        snps,rx-sched-wsp;
+        queue0 {};
+        queue1 {};
+        queue2 {};
+        queue3 {};
+        queue4 {};
+        queue5 {};
+        queue6 {};
+        queue7 {};
+      };
+
+      gmac0_mtl_tx_setup: tx-queues-config {
+        snps,tx-queues-to-use = <8>;
+        queue0 {};
+        queue1 {};
+        queue2 {};
+        queue3 {};
+        queue4 {};
+        queue5 {};
+        queue6 {};
+        queue7 {};
+      };
+
+      gmac0_stmmac_axi_setup: stmmac-axi-config {
+        snps,blen = <16 8 4 0 0 0 0>;
+        snps,wr_osr_lmt = <1>;
+        snps,rd_osr_lmt = <2>;
+      };
+    };
-- 
2.48.1



From inochiama at gmail.com  Tue Mar  4 22:39:15 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed,  5 Mar 2025 14:39:15 +0800
Subject: [PATCH net-next v6 3/4] net: stmmac: platform: Add snps,dwmac-5.30a IP compatible string
In-Reply-To: <20250305063920.803601-1-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
Message-ID: <20250305063920.803601-4-inochiama@gmail.com>

Add "snps,dwmac-5.30a" compatible string for 5.30a version that can avoid
to define some platform data in the glue layer.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 4a3fe44b780d..8dc3bd6946c6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -412,6 +412,7 @@ static const char * const stmmac_gmac4_compats[] = {
 	"snps,dwmac-4.20a",
 	"snps,dwmac-5.10a",
 	"snps,dwmac-5.20",
+	"snps,dwmac-5.30a",
 	NULL
 };
 
-- 
2.48.1



From inochiama at gmail.com  Tue Mar  4 22:45:56 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Wed, 5 Mar 2025 14:45:56 +0800
Subject: [PATCH net-next v6 1/4] dt-bindings: net: Add support for Sophgo
 SG2044 dwmac
In-Reply-To: <20250305063920.803601-2-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
 <20250305063920.803601-2-inochiama@gmail.com>
Message-ID: <n7jfcncujogjlysfd6v5bbt7tzun2sicx3r3jq3s5ogm5k4ths@y7wwlyijemgx>

On Wed, Mar 05, 2025 at 02:39:13PM +0800, Inochi Amaoto wrote:
> The GMAC IP on SG2044 is almost a standard Synopsys DesignWare
> MAC (version 5.30a) with some extra clock.
> 
> Add necessary compatible string for this device.
> 
> Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../devicetree/bindings/net/snps,dwmac.yaml   |   4 +
>  .../bindings/net/sophgo,sg2044-dwmac.yaml     | 126 ++++++++++++++++++
>  2 files changed, 130 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index 91e75eb3f329..02ab6a9aded2 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -32,6 +32,7 @@ select:
>            - snps,dwmac-4.20a
>            - snps,dwmac-5.10a
>            - snps,dwmac-5.20
> +          - snps,dwmac-5.30a
>            - snps,dwxgmac
>            - snps,dwxgmac-2.10
>  
> @@ -98,8 +99,10 @@ properties:
>          - snps,dwmac-4.20a
>          - snps,dwmac-5.10a
>          - snps,dwmac-5.20
> +        - snps,dwmac-5.30a
>          - snps,dwxgmac
>          - snps,dwxgmac-2.10
> +        - sophgo,sg2044-dwmac
>          - starfive,jh7100-dwmac
>          - starfive,jh7110-dwmac
>          - thead,th1520-gmac
> @@ -631,6 +634,7 @@ allOf:
>                  - snps,dwmac-4.20a
>                  - snps,dwmac-5.10a
>                  - snps,dwmac-5.20
> +                - snps,dwmac-5.30a
>                  - snps,dwxgmac
>                  - snps,dwxgmac-2.10
>                  - st,spear600-gmac
> diff --git a/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
> new file mode 100644
> index 000000000000..4dd2dc9c678b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
> @@ -0,0 +1,126 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/sophgo,sg2044-dwmac.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Sophgo SG2044 DWMAC glue layer
> +
> +maintainers:
> +  - Inochi Amaoto <inochiama at gmail.com>
> +
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - sophgo,sg2044-dwmac
> +  required:
> +    - compatible
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: sophgo,sg2044-dwmac
> +      - const: snps,dwmac-5.30a
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: GMAC main clock
> +      - description: PTP clock
> +      - description: TX clock
> +
> +  clock-names:
> +    items:
> +      - const: stmmaceth
> +      - const: ptp_ref
> +      - const: tx
> +
> +  dma-noncoherent: true

Hi, Krzysztof,

I add this property due to the discussion on PCIe binding of SG2044, it
can be found on link [1]. As a similar change (at link [2]) was acked by
Conor. I preserve your tag on this binding. If you have any further
requirement, please let me know. I will appreciate it.

[1] https://lore.kernel.org/all/20250221013758.370936-2-inochiama at gmail.com/
[2] https://lore.kernel.org/all/20250303065649.937233-1-inochiama at gmail.com/

Regards,
Inochi


From hanchunchao at inspur.com  Tue Mar  4 23:00:22 2025
From: hanchunchao at inspur.com (Charles Han)
Date: Wed, 5 Mar 2025 15:00:22 +0800
Subject: [PATCH] PCI: mediatek-gen3: fix inconsistent indenting warning
Message-ID: <20250305070022.4668-1-hanchunchao@inspur.com>

Fix below inconsistent indenting smatch warning.
smatch warnings:
drivers/pci/controller/pcie-mediatek-gen3.c:922 mtk_pcie_parse_port() warn: inconsistent indenting

Signed-off-by: Charles Han <hanchunchao at inspur.com>
---
 drivers/pci/controller/pcie-mediatek-gen3.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index 3583e5481dc8..2d1675ba496b 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -919,13 +919,13 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
 		return pcie->num_clks;
 	}
 
-       ret = of_property_read_u32(dev->of_node, "num-lanes", &num_lanes);
-       if (ret == 0) {
-	       if (num_lanes == 0 || num_lanes > 16 || (num_lanes != 1 && num_lanes % 2))
+	ret = of_property_read_u32(dev->of_node, "num-lanes", &num_lanes);
+	if (ret == 0) {
+		if (num_lanes == 0 || num_lanes > 16 || (num_lanes != 1 && num_lanes % 2))
 			dev_warn(dev, "invalid num-lanes, using controller defaults\n");
-	       else
+		else
 			pcie->num_lanes = num_lanes;
-       }
+	}
 
 	return 0;
 }
-- 
2.43.0



From krzk at kernel.org  Tue Mar  4 23:05:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:05:02 +0100
Subject: [PATCH v3 01/20] ASoC: dt-bindings: Add document for
 mt6359-accdet
In-Reply-To: <20250304-mt6359-accdet-dts-v3-1-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
 <20250304-mt6359-accdet-dts-v3-1-5b0eafc29f5b@collabora.com>
Message-ID: <20250305-stylish-grumpy-chital-ea6e4c@krzk-bin>

On Tue, Mar 04, 2025 at 12:15:42PM -0300, N?colas F. R. A. Prado wrote:
> Add dt-binding for the MT6359 ACCDET hardware block.
> 
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  .../bindings/sound/mediatek,mt6359-accdet.yaml     | 42 ++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..1d27148ed7bffee3f73015c8af88bfffa8701843
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6359-accdet.yaml
> @@ -0,0 +1,42 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mediatek,mt6359-accdet.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MT6359 Accessory Detection
> +
> +maintainers:
> +  - N?colas F. R. A. Prado <nfraprado at collabora.com>
> +
> +description:
> +  The MT6359 Accessory Detection block is part of the MT6359 PMIC and allows
> +  detecting audio jack insertion and removal, as well as identifying the type of
> +  events connected to the jack.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt6359-accdet

There are no resources here, so this should be folded into parent node.

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar  4 23:06:15 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:06:15 +0100
Subject: [PATCH v3 02/20] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250304-mt6359-accdet-dts-v3-2-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
 <20250304-mt6359-accdet-dts-v3-2-5b0eafc29f5b@collabora.com>
Message-ID: <20250305-dancing-amethyst-tortoise-d98036@krzk-bin>

On Tue, Mar 04, 2025 at 12:15:43PM -0300, N?colas F. R. A. Prado wrote:
> Describe the accdet as a possible subnode of the MT6359 PMIC.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Neither this nor cover letter explains dependencies between patches.
Good luck in making maintainers guessing this.

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar  4 23:13:04 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:13:04 +0100
Subject: [PATCH v3 2/6] dt-bindings: soc: imx93-media-blk-ctrl: Add LDB
 subnode into schema and example
In-Reply-To: <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
Message-ID: <20250305-dandelion-axolotl-of-excitement-05fa70@krzk-bin>

On Tue, Mar 04, 2025 at 04:49:21PM +0100, Alexander Stein wrote:
> Document the LDB bridge subnode and add the subnode into the example.
> For the subnode to work, the block control must scan its subnodes and

Don't describe drivers, but describe the hardware.


> bind drivers to them, do not misuse either simple-bus or simple-mfd
> here.

I don't understand that simple-bus or simple-mfd statement. There are no
such compatibles here.

> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
>  .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 +++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> index b3554e7f9e76d..cd785111928bf 100644
> --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> @@ -24,6 +24,14 @@ properties:
>    reg:
>      maxItems: 1
>  
> +  ranges: true
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 1
> +
>    '#power-domain-cells':
>      const: 1
>  
> @@ -46,9 +54,20 @@ properties:
>        - const: csi
>        - const: dsi
>  
> +  bridge at 20:

@20 looks wrong. Use 'ranges;' and try again your DTS...

Binding is supposed to be complete. We have several examples when people
added children one-by-one, everytime with different reasoning about
child addressing.

So please confirm: this is complete and no other children will ever be
added here... or you are 100% sure that all future children will be
unit-addressable (will have unit address and appropriate properties).

BTW, I don't quite get why this is both syscon and has translation for
child addresses. Does it mean your child does not use the same MMIO as
parent, thus leading to unsynchronized reg access?

> +    type: object
> +    additionalProperties: true
> +    properties:
> +      compatible:
> +        contains:
> +          const: fsl,imx93-ldb
> +
>  required:
>    - compatible
>    - reg
> +  - ranges
> +  - '#address-cells'
> +  - '#size-cells'
>    - power-domains
>    - clocks
>    - clock-names
> @@ -77,4 +96,36 @@ examples:
>                 clock-names = "apb", "axi", "nic", "disp", "cam",
>                               "pxp", "lcdif", "isi", "csi", "dsi";
>        #power-domain-cells = <1>;
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      ranges = <0x0 0x4ac10000 0x10000>;
> +
> +      bridge at 20 {
> +          compatible = "fsl,imx93-ldb";
> +          reg = <0x20 0x4>, <0x24 0x4>;
> +          reg-names = "ldb", "lvds";
> +          clocks = <&clk IMX93_CLK_LVDS_GATE>;
> +          clock-names = "ldb";
> +
> +          ports {
> +              #address-cells = <1>;
> +              #size-cells = <0>;
> +
> +              port at 0 {
> +                  reg = <0>;
> +
> +                  ldb_from_lcdif2: endpoint {
> +                      remote-endpoint = <&lcdif2_to_ldb>;
> +                  };
> +              };
> +
> +              port at 1 {
> +                  reg = <1>;
> +
> +                  ldb_lvds: endpoint {
> +                      remote-endpoint = <&ldb_to_panel>;
> +                  };
> +              };
> +          };

Messed indentation.

> +        };

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar  4 23:17:23 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:17:23 +0100
Subject: [PATCH v3 3/6] pmdomain: imx93-blk-ctrl: Scan subnodes and bind
 drivers to them
In-Reply-To: <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>
Message-ID: <20250305-keen-shaggy-bullfinch-fc77fd@krzk-bin>

On Tue, Mar 04, 2025 at 04:49:22PM +0100, Alexander Stein wrote:
> +#include <linux/of_platform.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> @@ -297,8 +298,14 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
>  
>  	dev_set_drvdata(dev, bc);
>  
> +	ret = devm_of_platform_populate(dev);

This means in remove() you will depopulate in different order than error
path (e.g. after genpd removal). This is rather unexpected - remove()
should be cleaning up in exactly reversed order of probe. Not sure if it
can lead to any issues, but usual recommendation is that you either use
devm() or not.

Best regards,
Krzysztof



From kw at linux.com  Tue Mar  4 23:26:32 2025
From: kw at linux.com ('Krzysztof =?utf-8?Q?Wilczy=C5=84ski'?=)
Date: Wed, 5 Mar 2025 16:26:32 +0900
Subject: [PATCH v7 4/5] Add debugfs based error injection support in DWC
In-Reply-To: <061301db8d27$02e0ced0$08a26c70$@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132039epcas5p31913eab0acec1eb5e7874897a084c725@epcas5p3.samsung.com>
 <20250221131548.59616-5-shradha.t@samsung.com>
 <20250303095200.GB1065658@rocinante>
 <20250304152952.pal66goo2dwegevh@thinkpad>
 <20250304153509.GA2310180@rocinante>
 <061301db8d27$02e0ced0$08a26c70$@samsung.com>
Message-ID: <20250305072632.GB847772@rocinante>

Hello,

[...]
> > > > > +		29) Generates duplicate TLPs - duplicate_dllp
> > > > > +		30) Generates Nullified TLPs - nullified_tlp
> > > >
> > > > Would the above field called "duplicate_dllp" for duplicate TLPs be
> > > > a potential typo?  Perhaps this should be called "duplicate_tlp"?
> > > >
> > >
> > > Looks like a typo. As per Synopsys documentation, there is only 'duplicate TLP'
> > > field.
> > >
> > > Good catch!
> > 
> > Updated.  Thank you!
> > 
> 
> Sorry, this was a typo. Krzysztof, we need another change for this typo.

Not a problem.  I am glad we caught this early.

[...]
> --- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> @@ -113,7 +113,7 @@ static const struct dwc_pcie_err_inj err_inj_list[] = {
>         {"posted_tlp_data", 0x4, 0x4},
>         {"non_post_tlp_data", 0x4, 0x5},
>         {"cmpl_tlp_data", 0x4, 0x6},
> -       {"duplicate_dllp", 0x5, 0x0},
> +       {"duplicate_tlp", 0x5, 0x0},
>         {"nullified_tlp", 0x5, 0x1},
>  };

Oh here too.  No worries.  I missed this one. :)

> So sorry for the inconvenience! Should I post a patch for this?

No, no need.  I will update this directly on the branch.

Thank you!

	Krzysztof


From krzk at kernel.org  Tue Mar  4 23:32:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:32:06 +0100
Subject: [PATCH v2 2/9] dt-bindings: phy: Add the M31 based eUSB2 PHY
 bindings
In-Reply-To: <20250304-sm8750_usb_master-v2-2-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-2-a698a2e68e06@quicinc.com>
Message-ID: <20250305-furry-finch-of-camouflage-e7ee5e@krzk-bin>

On Tue, Mar 04, 2025 at 01:56:35PM -0800, Melody Olvera wrote:
> +  vdd-supply:
> +    description:
> +      Phandle to 0.88V regulator supply to PHY digital circuit.
> +
> +  vdda12-supply:
> +    description:
> +      Phandle to 1.2V regulator supply to PHY refclk pll block.
> +
> +required:
> +  - compatible
> +  - reg
> +  - "#phy-cells"
> +  - clocks
> +  - clock-names
> +  - vdd-supply
> +  - vdda12-supply
> +  - resets

Keep the same order as in "properties" list.

> +
> +additionalProperties: false

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From tglx at linutronix.de  Tue Mar  4 23:41:28 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Wed, 05 Mar 2025 08:41:28 +0100
Subject: [PATCH v2 06/15] irqchip/sunxi-nmi: Support Allwinner A523 NMI
 controller
In-Reply-To: <20250304222309.29385-7-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-7-andre.przywara@arm.com>
Message-ID: <87frjr6i1j.ffs@tglx>

On Tue, Mar 04 2025 at 22:23, Andre Przywara wrote:
>  
> -struct sunxi_sc_nmi_reg_offs {
> +struct sunxi_sc_nmi_data {
>  	u32 ctrl;
>  	u32 pend;
>  	u32 enable;
> +	u32 enable_val;

The data structure name and the corresponding variable/argument name
were making the code pretty obvious, but now this is opaque and
incomprehensible.

data::ctrl does not even give the slightest hint what this is about. You
need to read up in the code to figure out what it means. Something like:

struct sunxi_sc_nmi_data {
	u32	reg_offs_ctrl;
  	u32	reg_offs_pend;
  	u32	reg_offs_enable;
	u32	enable_val;
};

or even better:

struct sunxi_sc_nmi_data {
	struct {
		u32	ctrl;
  		u32	pend;
  		u32	enable;
        } reg_offs;
	u32		enable_val;
};

makes it clear and obvious, no?

> +static const struct sunxi_sc_nmi_data sun55i_a523_data __initconst = {
> +	.ctrl	= SUN9I_NMI_CTRL,
> +	.pend	= SUN9I_NMI_PENDING,
> +	.enable	= SUN9I_NMI_ENABLE,
> +	.enable_val = BIT(31),

https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-declarations-and-initializers

Thanks,

        tglx


From linus.walleij at linaro.org  Tue Mar  4 23:44:12 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 5 Mar 2025 08:44:12 +0100
Subject: [PATCH v2 0/6] ASoC: samsung: GPIO descriptor conversion
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <CACRpkda_QjBpfyA1ig2cC+pn8Xf0Rk8Ox+pecQkbcbYY+8N7Cw@mail.gmail.com>

On Wed, Mar 5, 2025 at 8:39?AM Linus Walleij <linus.walleij at linaro.org> wrote:

> This drops unused includes and converts one Samsung
> codec to use GPIO descriptors.

Oh I see it was already applied (I don't read my mail fast enough
in the mornings), no worries I can send an incremental
fix instead.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue Mar  4 23:39:12 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:12 +0100
Subject: [PATCH v2 0/6] ASoC: samsung: GPIO descriptor conversion
Message-ID: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>

This drops unused includes and converts one Samsung
codec to use GPIO descriptors.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
Changes in v2:
- Collect Review tags
- Add a devm action to drop the gpiod table in speyside
- Link to v1: https://lore.kernel.org/r/20250303-samsung-codecs-v1-0-56a2299dd928 at linaro.org

---
Linus Walleij (6):
      ASoC: samsung: bells: Drop unused include
      ASoC: samsung: littlemill: Drop unused include
      ASoC: samsung: lowland: Drop unused include
      ASoC: samsung: speyside: Convert to GPIO descriptor
      ASoC: samsung: tobermory: Drop unused include
      ASoC: samsung: tm2_wm5110: Drop unused include

 sound/soc/samsung/bells.c      |  1 -
 sound/soc/samsung/littlemill.c |  1 -
 sound/soc/samsung/lowland.c    |  1 -
 sound/soc/samsung/speyside.c   | 47 +++++++++++++++++++++++++++++++++++-------
 sound/soc/samsung/tm2_wm5110.c |  1 -
 sound/soc/samsung/tobermory.c  |  1 -
 6 files changed, 40 insertions(+), 12 deletions(-)
---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20250302-samsung-codecs-6366e1b3f283

Best regards,
-- 
Linus Walleij <linus.walleij at linaro.org>



From linus.walleij at linaro.org  Tue Mar  4 23:39:13 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:13 +0100
Subject: [PATCH v2 1/6] ASoC: samsung: bells: Drop unused include
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-1-20bc980c6445@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/bells.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 365b1aca4855c885e0b59a1101475d8edb86374f..b4c0857ae35134b58a125b0746af07a5fff040fa 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm5102.h"

-- 
2.48.1



From linus.walleij at linaro.org  Tue Mar  4 23:39:14 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:14 +0100
Subject: [PATCH v2 2/6] ASoC: samsung: littlemill: Drop unused include
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-2-20bc980c6445@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/littlemill.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index c5260e101c2a136001c6273200fa35740e618829..9fa5e3ff9215164491839d6ffdf499a3eeadfbaa 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8994.h"

-- 
2.48.1



From linus.walleij at linaro.org  Tue Mar  4 23:39:15 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:15 +0100
Subject: [PATCH v2 3/6] ASoC: samsung: lowland: Drop unused include
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-3-20bc980c6445@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/lowland.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
index 702cb4cc1ce9f07e55ddf9435b19c4691e0236e5..d4088b72d43c2295102d850197f8b9eac50d7120 100644
--- a/sound/soc/samsung/lowland.c
+++ b/sound/soc/samsung/lowland.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm5100.h"

-- 
2.48.1



From linus.walleij at linaro.org  Tue Mar  4 23:39:16 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:16 +0100
Subject: [PATCH v2 4/6] ASoC: samsung: speyside: Convert to GPIO descriptor
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-4-20bc980c6445@linaro.org>

The Speyside ASoC uses a single GPIO from the WM8996
that we can provide from the local offset on that chip
rather than from the global GPIO numberspace as is being
done currently.

The offset 2 was done by calculating the base offset
for the CODEC (i.e. wm8996) GPIOs to 212, by reading
arch/arm/mach-s3c/gpio-samsung-s3c64xx.h and
arch/arm/mach-s3c/crag6410.h and adding up all the
offsets that were occasionally adding a +1 blank GPIO
between each GPIO provider.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
ChangeLog v1->v2:
- Patch in a devm action to drop the gpiod table.
---
 sound/soc/samsung/speyside.c | 47 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 79476e8eb680984434a1198ff691ddd4b9fe07c1..d6b8c62e015a3114c7a746e1f754217ffacb7044 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -7,13 +7,13 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8996.h"
 #include "../codecs/wm9081.h"
 
-#define WM8996_HPSEL_GPIO 214
 #define MCLK_AUDIO_RATE (512 * 48000)
 
 static int speyside_set_bias_level(struct snd_soc_card *card,
@@ -105,6 +105,7 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = {
 	},
 };
 
+static struct gpio_desc *speyside_hpsel_gpio;
 /* Default the headphone selection to active high */
 static int speyside_jack_polarity;
 
@@ -123,7 +124,7 @@ static void speyside_set_polarity(struct snd_soc_component *component,
 				  int polarity)
 {
 	speyside_jack_polarity = !polarity;
-	gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
+	gpiod_direction_output(speyside_hpsel_gpio, speyside_jack_polarity);
 
 	/* Re-run DAPM to make sure we're using the correct mic bias */
 	snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
@@ -145,16 +146,22 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
 	struct snd_soc_component *component = dai->component;
+	enum gpiod_flags flags;
 	int ret;
 
 	ret = snd_soc_dai_set_sysclk(dai, WM8996_SYSCLK_MCLK2, 32768, 0);
 	if (ret < 0)
 		return ret;
 
-	ret = gpio_request(WM8996_HPSEL_GPIO, "HP_SEL");
-	if (ret != 0)
-		pr_err("Failed to request HP_SEL GPIO: %d\n", ret);
-	gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
+	if (speyside_jack_polarity)
+		flags = GPIOD_OUT_HIGH;
+	else
+		flags = GPIOD_OUT_LOW;
+	speyside_hpsel_gpio = devm_gpiod_get(rtd->card->dev,
+					     "hp-sel",
+					     flags);
+	if (IS_ERR(speyside_hpsel_gpio))
+		return PTR_ERR(speyside_hpsel_gpio);
 
 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset",
 					 SND_JACK_LINEOUT | SND_JACK_HEADSET |
@@ -325,6 +332,26 @@ static struct snd_soc_card speyside = {
 	.late_probe = speyside_late_probe,
 };
 
+static struct gpiod_lookup_table wm8996_gpiod_table = {
+	/* Hardcoded device name in board file mach-crag6410.c */
+	.dev_id = "speyside",
+	.table = {
+		/*
+		 * This line was hardcoded to 214 in the global GPIO
+		 * number space, S3C GPIO macros seems top set the
+		 * wm8996 codec GPIO start offset to 212, so this will
+		 * be GPIO 214 - 212 = 2 on the wm8996.
+		 */
+		GPIO_LOOKUP("wm8996", 2, "hp-sel", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
+static void speyside_gpiod_table_action(void *data)
+{
+	gpiod_remove_lookup_table(&wm8996_gpiod_table);
+}
+
 static int speyside_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = &speyside;
@@ -332,6 +359,12 @@ static int speyside_probe(struct platform_device *pdev)
 
 	card->dev = &pdev->dev;
 
+	gpiod_add_lookup_table(&wm8996_gpiod_table);
+	ret = devm_add_action_or_reset(&pdev->dev, speyside_gpiod_table_action,
+				       NULL);
+	if (ret)
+		return ret;
+
 	ret = devm_snd_soc_register_card(&pdev->dev, card);
 	if (ret)
 		dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n");

-- 
2.48.1



From linus.walleij at linaro.org  Tue Mar  4 23:39:17 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:17 +0100
Subject: [PATCH v2 5/6] ASoC: samsung: tobermory: Drop unused include
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-5-20bc980c6445@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/tobermory.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index 2bdd81bf821a5b9bdc56479bb2cd5d0089fab339..bc2608dbaddc4feeb9af77639699fed89540b44b 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -7,7 +7,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/jack.h>
-#include <linux/gpio.h>
 #include <linux/module.h>
 
 #include "../codecs/wm8962.h"

-- 
2.48.1



From linus.walleij at linaro.org  Tue Mar  4 23:39:18 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 05 Mar 2025 08:39:18 +0100
Subject: [PATCH v2 6/6] ASoC: samsung: tm2_wm5110: Drop unused include
In-Reply-To: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
References: <20250305-samsung-codecs-v2-0-20bc980c6445@linaro.org>
Message-ID: <20250305-samsung-codecs-v2-6-20bc980c6445@linaro.org>

This file does not use the symbols from the legacy
<linux/gpio.h> header, so let's drop it.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 sound/soc/samsung/tm2_wm5110.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
index 2417b91a328f083f991af8505c5586d3b27d9bbd..cc76963105d9fa37fe0bc45acf9a28720fdde158 100644
--- a/sound/soc/samsung/tm2_wm5110.c
+++ b/sound/soc/samsung/tm2_wm5110.c
@@ -6,7 +6,6 @@
 //          Sylwester Nawrocki <s.nawrocki at samsung.com>
 
 #include <linux/clk.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>

-- 
2.48.1



From krzk at kernel.org  Tue Mar  4 23:41:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 08:41:24 +0100
Subject: [PATCH v2 10/15] dt-bindings: arm: sunxi: Add new board names
 for A523 generation
In-Reply-To: <20250304222309.29385-11-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-11-andre.przywara@arm.com>
Message-ID: <20250305-gigantic-dinosaur-of-perspective-c3acad@krzk-bin>

On Tue, Mar 04, 2025 at 10:23:04PM +0000, Andre Przywara wrote:
> The new Allwinner A523 SoC family comes in different packages, though
> they all share the same die, and so the devicetree bindings.
> 
> Add three board names that use a version from this SoC family:
> - The Avaota A1: an Open Source hardware router board.
> - The Radxa Cubie A5E: a typical development board
> - The X96QPro+: a TV box
> 
> Add their compatible name to the list.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From kw at linux.com  Tue Mar  4 23:44:47 2025
From: kw at linux.com ('Krzysztof =?utf-8?Q?Wilczy=C5=84ski'?=)
Date: Wed, 5 Mar 2025 16:44:47 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <061201db8d25$dd1e2bd0$975a8370$@samsung.com>
References: <20250221131548.59616-1-shradha.t@samsung.com>
 <CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
 <20250221131548.59616-4-shradha.t@samsung.com>
 <Z8XrYxP_pZr6tFU8@debian>
 <20250303194647.GC1552306@rocinante>
 <CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
 <20250304154638.GB2310180@rocinante>
 <061201db8d25$dd1e2bd0$975a8370$@samsung.com>
Message-ID: <20250305074447.GC847772@rocinante>

Hello,

> I think we shouldn't move the log level to be a WARN. I believe many
> controllers might not support RAS DES feature in their design and giving
> a warn dump would draw unnecessary attention.

There will be no backtrack printed with neither dev_err() nor dev_warn(),
which is what we were using here.  Using dev_WARN() or the WARN() macro
directly would be an overkill in this case, indeed.

> My opinion is to silently let it fail unless the user is actually
> interested in getting the RAS DES feature up.

I think, what we have there now is fine.  We don't error on the lack of RAS
DES capability when the platform does not support it, and only return an
error following a memory allocation failure, which should ideally never
happen.

That said, have a look at the following:

  https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/log/?h=controller/dwc

This is how the code looks like at the moment.

We can still move it to dev_dbg(), so basically suppress any errors or
warnings from being printed outside of the debug log level, if you think
it would be better.

Thank you!

	Krzysztof


From kw at linux.com  Tue Mar  4 23:53:02 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 5 Mar 2025 16:53:02 +0900
Subject: [PATCH] PCI: mediatek-gen3: fix inconsistent indenting warning
In-Reply-To: <20250305070022.4668-1-hanchunchao@inspur.com>
References: <20250305070022.4668-1-hanchunchao@inspur.com>
Message-ID: <20250305075302.GD847772@rocinante>

Hello,

> Fix below inconsistent indenting smatch warning.
> smatch warnings:
> drivers/pci/controller/pcie-mediatek-gen3.c:922 mtk_pcie_parse_port() warn: inconsistent indenting

Applied to controller/mediatek, thank you!

	Krzysztof


From mike.rudenko at gmail.com  Tue Mar  4 23:40:31 2025
From: mike.rudenko at gmail.com (Mikhail Rudenko)
Date: Wed, 05 Mar 2025 10:40:31 +0300
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in
 dma-contig
In-Reply-To: <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
 <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>
 <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
Message-ID: <87y0xj29rz.fsf@gmail.com>

Hi Nicolas,

On 2025-03-03 at 10:24 -05, Nicolas Dufresne <nicolas at ndufresne.ca> wrote:

> Hi Mikhail,
>
> Le lundi 03 mars 2025 ? 14:40 +0300, Mikhail Rudenko a ?crit?:
>> When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
>> commit 129134e5415d ("media: media/v4l2: remove
>> V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
>> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
>> no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
>> introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
>> V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
>> no-ops, making cache maintenance for non-coherent dmabufs allocated
>> by
>> dma-contig impossible.
>>
>> Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
>> {flush,invalidate}_kernel_vmap_range calls to
>> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
>> buffers.
>>
>> Fixes: c0acf9cfeee0 ("media: videobuf2: handle
>> V4L2_MEMORY_FLAG_NON_COHERENT flag")
>> Cc: stable at vger.kernel.org
>> Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
>> ---
>> ?.../media/common/videobuf2/videobuf2-dma-contig.c? | 22
>> ++++++++++++++++++++++
>> ?1 file changed, 22 insertions(+)
>>
>> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> index
>> a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7
>> bc888a84a95d5 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> @@ -427,6 +427,17 @@ static int
>> ?vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
>> ?				?? enum dma_data_direction
>> direction)
>> ?{
>> +	struct vb2_dc_buf *buf = dbuf->priv;
>> +	struct sg_table *sgt = buf->dma_sgt;
>> +
>> +	if (!buf->non_coherent_mem)
>> +		return 0;
>> +
>> +	if (buf->vaddr)
>> +		invalidate_kernel_vmap_range(buf->vaddr, buf->size);
>
> What would make me a lot more confortable with this change is if you
> enable kernel mappings for one test. This will ensure you cover the
> call to "invalidate" in your testing. I'd like to know about the
> performance impact. With this implementation it should be identical to
> the VB2 one.

I'll enable kernel mappings and rerun my tests later this week.

> What I was trying to say in previous comments, is that my impression is
> that we can skip this for CPU read access, since we don't guaranty
> concurrent access anyway. Both address space can keep their cache in
> that case. Though, I see RKISP does not use kernel mapping plus I'm not
> reporting a bug, but checking if we should leave a comment for possible
> users of kernel mapping in the future ?

I trust Tomasz here, I'd wait for his comment on v4.

>> +
>> +	dma_sync_sgtable_for_cpu(buf->dev, sgt, direction);
>> +
>> ?	return 0;
>> ?}
>>
>> @@ -434,6 +445,17 @@ static int
>> ?vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
>> ?				 enum dma_data_direction direction)
>> ?{
>> +	struct vb2_dc_buf *buf = dbuf->priv;
>> +	struct sg_table *sgt = buf->dma_sgt;
>> +
>> +	if (!buf->non_coherent_mem)
>> +		return 0;
>> +
>> +	if (buf->vaddr)
>> +		flush_kernel_vmap_range(buf->vaddr, buf->size);
>> +
>> +	dma_sync_sgtable_for_device(buf->dev, sgt, direction);
>> +
>> ?	return 0;
>> ?}
>>
>>


--
Best regards,
Mikhail Rudenko


From shawn.lin at rock-chips.com  Tue Mar  4 23:54:12 2025
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed,  5 Mar 2025 15:54:12 +0800
Subject: [PATCH v2] arm64: defconfig: Enable Rockchip UFS host driver
Message-ID: <1741161252-138526-1-git-send-email-shawn.lin@rock-chips.com>

Enable Rockchip UFS host driver.

This driver is first introduced on Rockchip RK3576 SoC, and will
be used for more SoCs in near future, so add it to defconfig
will make these platforms work better.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
---

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706d..907e92d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1191,6 +1191,7 @@ CONFIG_SCSI_UFS_HISI=y
 CONFIG_SCSI_UFS_RENESAS=m
 CONFIG_SCSI_UFS_TI_J721E=m
 CONFIG_SCSI_UFS_EXYNOS=y
+CONFIG_SCSI_UFS_ROCKCHIP=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS_MULTICOLOR=m
-- 
2.7.4



From linus.walleij at linaro.org  Wed Mar  5 00:04:05 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 5 Mar 2025 09:04:05 +0100
Subject: [PATCH v3 0/6] pinctrl: bcm281xx: Add support for BCM21664 pinmux
In-Reply-To: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com>
Message-ID: <CACRpkdYTsym-YqV8CQh7up57q_R2ZGSnsCD8FiYSpQnS5CaFig@mail.gmail.com>

On Mon, Mar 3, 2025 at 9:54?PM Artur Weber <aweber.kernel at gmail.com> wrote:

> BCM21664 is another chip from the Kona line of Broadcom SoCs, and
> its pinmux shares a lot of similarities with the BCM281xx pinmux.
>
> Add support for the BCM21664 pinmux controller to the BCM281xx driver.
>
> This also enables pinmux support for the BCM23550, which has an
> identical pinmux config to the BCM21664 (hence they can share a
> single compatible, brcm,bcm21664-pinctrl).
>
> While we're at it - fix a bug that affected higher registers in the
> BCM281XX driver and replace bare "unsigned" with "unsigned int" to
> comply with checkpatch requirements.
>
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
(...)
> Artur Weber (6):
>       dt-bindings: pinctrl: Add bindings for BCM21664 pin controller
>       pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned"
>       pinctrl: bcm281xx: Provide pinctrl device info as OF platform data
>       pinctrl: bcm281xx: Add support for BCM21664 pinmux

Bindings are ACKed and not much other feedback so:

I applied these 4 patches, I had to rebase the one dependent on the
fix a bit and then Torvalds can fix that up in the merge window.

>       ARM: dts: bcm2166x-common: Add pinctrl node
>       ARM: dts: bcm2166x: Add bcm2166x-pinctrl DTSI

Please funnel these two through the SoC tree!

Yours,
Linus Walleij


From tfiga at chromium.org  Wed Mar  5 00:12:31 2025
From: tfiga at chromium.org (Tomasz Figa)
Date: Wed, 5 Mar 2025 17:12:31 +0900
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in dma-contig
In-Reply-To: <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
 <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com> <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
Message-ID: <CAAFQd5CMsgjs9t3Lp-r3rqHG1dFJV5bFEFciWmKU+vq=TtAOvA@mail.gmail.com>

On Tue, Mar 4, 2025 at 12:24?AM Nicolas Dufresne <nicolas at ndufresne.ca> wrote:
>
> Hi Mikhail,
>
> Le lundi 03 mars 2025 ? 14:40 +0300, Mikhail Rudenko a ?crit :
> > When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
> > commit 129134e5415d ("media: media/v4l2: remove
> > V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
> > vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
> > no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
> > introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
> > V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
> > no-ops, making cache maintenance for non-coherent dmabufs allocated
> > by
> > dma-contig impossible.
> >
> > Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
> > {flush,invalidate}_kernel_vmap_range calls to
> > vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
> > buffers.
> >
> > Fixes: c0acf9cfeee0 ("media: videobuf2: handle
> > V4L2_MEMORY_FLAG_NON_COHERENT flag")
> > Cc: stable at vger.kernel.org
> > Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
> > ---
> >  .../media/common/videobuf2/videobuf2-dma-contig.c  | 22
> > ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> >
> > diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> > b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> > index
> > a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7
> > bc888a84a95d5 100644
> > --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> > +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> > @@ -427,6 +427,17 @@ static int
> >  vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
> >                                  enum dma_data_direction
> > direction)
> >  {
> > +     struct vb2_dc_buf *buf = dbuf->priv;
> > +     struct sg_table *sgt = buf->dma_sgt;
> > +
> > +     if (!buf->non_coherent_mem)
> > +             return 0;
> > +
> > +     if (buf->vaddr)
> > +             invalidate_kernel_vmap_range(buf->vaddr, buf->size);
>
> What would make me a lot more confortable with this change is if you
> enable kernel mappings for one test. This will ensure you cover the
> call to "invalidate" in your testing. I'd like to know about the
> performance impact. With this implementation it should be identical to
> the VB2 one.

I agree that it would be good to test that path as well. I wonder if
we could somehow do it with one of the vi* drivers...

>
> What I was trying to say in previous comments, is that my impression is
> that we can skip this for CPU read access, since we don't guaranty
> concurrent access anyway. Both address space can keep their cache in
> that case. Though, I see RKISP does not use kernel mapping plus I'm not
> reporting a bug, but checking if we should leave a comment for possible
> users of kernel mapping in the future ?

We can't skip it for CPU read access, because it may be the first read
after the DMA writing to the buffer, so we need to invalidate the
caches.

That said, on majority of systems this will be a no-op, because it
only applies to VIVT and VIPT aliasing caches + only when the kernel
mapping is actually used (the buf->vaddr mapping is created on
demand).

>
> > +
> > +     dma_sync_sgtable_for_cpu(buf->dev, sgt, direction);
> > +
> >       return 0;
> >  }
> >
> > @@ -434,6 +445,17 @@ static int
> >  vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
> >                                enum dma_data_direction direction)
> >  {
> > +     struct vb2_dc_buf *buf = dbuf->priv;
> > +     struct sg_table *sgt = buf->dma_sgt;
> > +
> > +     if (!buf->non_coherent_mem)
> > +             return 0;
> > +
> > +     if (buf->vaddr)
> > +             flush_kernel_vmap_range(buf->vaddr, buf->size);
> > +
> > +     dma_sync_sgtable_for_device(buf->dev, sgt, direction);
> > +
> >       return 0;
> >  }
> >
> >
>


From razor at blackwall.org  Wed Mar  5 00:29:34 2025
From: razor at blackwall.org (Nikolay Aleksandrov)
Date: Wed, 5 Mar 2025 10:29:34 +0200
Subject: [PATCH v8 net-next 15/15] netfilter: nft_flow_offload: Add
 bridgeflow to nft_flow_offload_eval()
In-Reply-To: <20250228201533.23836-16-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
 <20250228201533.23836-16-ericwouds@gmail.com>
Message-ID: <1975f2a1-9461-400d-8b3f-f40e8b94be80@blackwall.org>

On 2/28/25 22:15, Eric Woudstra wrote:
> Edit nft_flow_offload_eval() to make it possible to handle a flowtable of
> the nft bridge family.
> 
> Use nft_flow_offload_bridge_init() to fill the flow tuples. It uses
> nft_dev_fill_bridge_path() in each direction.
> 
> Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
> ---
>  net/netfilter/nft_flow_offload.c | 142 +++++++++++++++++++++++++++++--
>  1 file changed, 137 insertions(+), 5 deletions(-)
> 

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>



From claudiu.beznea at tuxon.dev  Wed Mar  5 00:30:09 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Wed, 5 Mar 2025 10:30:09 +0200
Subject: [PATCH] ARM: dts: microchip: sama7g5: add ADC hw trigger edge
 type
In-Reply-To: <20250304-sama7g5-hw-trigger-enable-v1-1-61b5618285f0@microchip.com>
References: <20250304-sama7g5-hw-trigger-enable-v1-1-61b5618285f0@microchip.com>
Message-ID: <1e33b374-0454-4d03-a673-75f36e6fabfc@tuxon.dev>



On 04.03.2025 08:15, Nayab Sayed via B4 Relay wrote:
> From: Nayab Sayed <nayabbasha.sayed at microchip.com>
> 
> Set ADC trigger edge type property as interrupt edge rising value.
> 
> Signed-off-by: Nayab Sayed <nayabbasha.sayed at microchip.com>

Applied to at91-dt, thanks!


From razor at blackwall.org  Wed Mar  5 00:20:18 2025
From: razor at blackwall.org (Nikolay Aleksandrov)
Date: Wed, 5 Mar 2025 10:20:18 +0200
Subject: [PATCH v8 net-next 04/15] netfilter: bridge: Add conntrack double
 vlan and pppoe
In-Reply-To: <20250228201533.23836-5-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
 <20250228201533.23836-5-ericwouds@gmail.com>
Message-ID: <2690fc33-0646-4aff-aacf-2760706139e1@blackwall.org>

On 2/28/25 22:15, Eric Woudstra wrote:
> This adds the capability to conntrack 802.1ad, QinQ, PPPoE and PPPoE-in-Q
> packets that are passing a bridge.
> 
> Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
> ---
>  net/bridge/netfilter/nf_conntrack_bridge.c | 83 ++++++++++++++++++----
>  1 file changed, 71 insertions(+), 12 deletions(-)
>

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>



From jjian.zhou at mediatek.com  Wed Mar  5 00:20:37 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Wed, 5 Mar 2025 16:20:37 +0800
Subject: [PATCH RFC 0/3] add VCP mailbox and IPC driver
Message-ID: <20250305082047.15746-1-jjian.zhou@mediatek.com>

The VCP mailbox has 5 groups. Each group has corresponding interrupts,
registers, and 64 slots (each slot is 4 bytes). Since different features
share one of the mailbox groups, the VCP mailbox needs to establish a
send table and a receive table. The send table is used to record the
feature ID, mailbox ID, and the number of slots occupied. The receive table
is used to record the feature ID, mailbox ID, the number of slots occupied,
and the receive options. The API setup_mbox_table in mtk-vcp-ipc.c calculates
the slot offset and pin index for each feature ID based on the mailbox ID and
slot number in the send and receive tables (several slots form a pin, and
each pin can trigger an interrupt). These descriptions are written in the
mtk-vcp-ipc.c file -- we call it the IPC layer.

We have two questions:
How should we describe the mailbox and IPI?
Can the intermediate IPC layer be rewritten as a virtual mailbox layer?

Example of send and recve table:
Operation | mbox_id | ipi_id | msg_size | align_size | slot_ofs | pin_index |  notes
send          0          0       18          18           0          0
recv          0          1       18          18          18          9
send          1         15        8           8           0          0
send          1         16       18          18           8          4
send          1          9        2           2          26         13
recv          1         15        8           8          28         14       ack of send ipi_id=15
recv          1         17       18          18          36         18
recv          1         10        2           2          54         27       ack of send ipi_id=2
send          2         11       18          18           0          0
send          2          2        2           2          18          9
send          2          3        3           4          20         10
send          2         32        2           2          24         12
recv          2         12       18          18          26         13
recv          2          5        1           2          44         22
recv          2          2        1           2          46         23

Recv ipi_id=2 is the ack of send ipi_id=2(The ipi_id=15 is the same.)

Jjian Zhou (3):
  mailbox: mediatek: Add mtk-vcp-mailbox driver
  firmware: mediatek: Add vcp ipc protocol interface
  dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document

 .../bindings/mailbox/mtk,vcp-mbox.yaml        |  49 ++
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 drivers/mailbox/Kconfig                       |   9 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c             | 179 +++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 include/linux/mailbox/mtk-vcp-mailbox.h       |  34 ++
 9 files changed, 915 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

--
2.45.2



From jjian.zhou at mediatek.com  Wed Mar  5 00:20:38 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Wed, 5 Mar 2025 16:20:38 +0800
Subject: [PATCH RFC 1/3] mailbox: mediatek: Add mtk-vcp-mailbox driver
In-Reply-To: <20250305082047.15746-1-jjian.zhou@mediatek.com>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
Message-ID: <20250305082047.15746-2-jjian.zhou@mediatek.com>

Add mtk-vcp-mailbox driver to support the communication with
VCP remote microprocessor.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/mailbox/Kconfig                 |   9 ++
 drivers/mailbox/Makefile                |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c       | 179 ++++++++++++++++++++++++
 include/linux/mailbox/mtk-vcp-mailbox.h |  34 +++++
 4 files changed, 224 insertions(+)
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ed52db272f4d..ffc4a5491462 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -275,6 +275,15 @@ config MTK_CMDQ_MBOX
 	  critical time limitation, such as updating display configuration
 	  during the vblank.

+config MTK_VCP_MBOX
+	tristate "MediaTek VCP Mailbox Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  Say yes here to add support for the MediaTek VCP mailbox driver.
+	  The mailbox implementation provides access from the application
+	  processor to the MediaTek Video Processing Unit.
+	  If unsure say N.
+
 config ZYNQMP_IPI_MBOX
 	tristate "Xilinx ZynqMP IPI Mailbox"
 	depends on ARCH_ZYNQMP && OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 9a1542b55539..75a200a9d2d2 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -59,6 +59,8 @@ obj-$(CONFIG_MTK_ADSP_MBOX)	+= mtk-adsp-mailbox.o

 obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o

+obj-$(CONFIG_MTK_VCP_MBOX)	+= mtk-vcp-mailbox.o
+
 obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o

 obj-$(CONFIG_SUN6I_MSGBOX)	+= sun6i-msgbox.o
diff --git a/drivers/mailbox/mtk-vcp-mailbox.c b/drivers/mailbox/mtk-vcp-mailbox.c
new file mode 100644
index 000000000000..fd7a123c71c8
--- /dev/null
+++ b/drivers/mailbox/mtk-vcp-mailbox.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Corporation. All rights reserved.
+ * Author: Jjian Zhou <jjian.zhou. at mediatek.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct mtk_vcp_mbox_priv {
+	void __iomem *base;
+	struct device *dev;
+	struct mbox_controller mbox;
+	const struct mtk_vcp_mbox_cfg *cfg;
+	struct mtk_ipi_info ipi_recv;
+};
+
+struct mtk_vcp_mbox_cfg {
+	u32 set_in;
+	u32 clr_out;
+};
+
+static inline struct mtk_vcp_mbox_priv *get_mtk_vcp_mbox_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct mtk_vcp_mbox_priv, mbox);
+}
+
+static irqreturn_t mtk_vcp_mbox_irq_thread(int irq, void *data)
+{
+	struct mbox_chan *chan = data;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+
+	/* get irq status */
+	priv->ipi_recv.irq_status = readl(priv->base + priv->cfg->clr_out);
+
+	__ioread32_copy(priv->ipi_recv.msg, priv->base, MAX_SLOT_NUM);
+
+	mbox_chan_received_data(chan, &priv->ipi_recv);
+
+	/* clear irq status */
+	writel(priv->ipi_recv.irq_status, priv->base + priv->cfg->clr_out);
+
+	return IRQ_HANDLED;
+}
+
+static struct mbox_chan *mtk_vcp_mbox_xlate(struct mbox_controller *mbox,
+					    const struct of_phandle_args *sp)
+{
+	if (sp->args_count)
+		return NULL;
+
+	return mbox->chans;
+}
+
+static int mtk_vcp_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	struct mtk_ipi_info *ipi_info = data;
+	u32 status;
+
+	if (!ipi_info->msg) {
+		dev_err(priv->dev, "msg buffer is NULL.\n");
+		return -ENOMEM;
+	}
+
+	status = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	if (status) {
+		dev_err(priv->dev, "mailbox IPI %d is busy.\n", ipi_info->id);
+		return -EBUSY;
+	}
+
+	if (ipi_info->slot_ofs + ipi_info->len > MBOX_SLOT_MAX_SIZE)
+		return -EINVAL;
+	__iowrite32_copy(priv->base + ipi_info->slot_ofs, ipi_info->msg,
+			 ipi_info->len);
+
+	writel(BIT(ipi_info->index), priv->base + priv->cfg->set_in);
+
+	return 0;
+}
+
+static bool mtk_vcp_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	struct mtk_ipi_info *ipi_info = chan->active_req;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	u32 op;
+
+	op = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	return !op;
+}
+
+static const struct mbox_chan_ops mtk_vcp_mbox_chan_ops = {
+	.send_data	= mtk_vcp_mbox_send_data,
+	.last_tx_done	= mtk_vcp_mbox_last_tx_done,
+};
+
+static int mtk_vcp_mbox_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_mbox_priv *priv;
+	struct mbox_controller *mbox;
+	int ret, irq;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	mbox = &priv->mbox;
+	mbox->dev = dev;
+	mbox->ops = &mtk_vcp_mbox_chan_ops;
+	mbox->txdone_irq = false;
+	mbox->txdone_poll = true;
+	mbox->of_xlate = mtk_vcp_mbox_xlate;
+	mbox->num_chans = 1;
+	mbox->chans = devm_kzalloc(dev, sizeof(*mbox->chans), GFP_KERNEL);
+	if (!mbox->chans)
+		return -ENOMEM;
+
+	priv->ipi_recv.msg = devm_kzalloc(dev, sizeof(u8) * MBOX_SLOT_MAX_SIZE,
+					  GFP_KERNEL);
+	if (!priv->ipi_recv.msg)
+		return -ENOMEM;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->cfg = of_device_get_match_data(dev);
+	if (!priv->cfg)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_threaded_irq(dev, irq, NULL,
+					mtk_vcp_mbox_irq_thread, IRQF_ONESHOT,
+					dev_name(dev), mbox->chans);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);
+
+	dev_dbg(dev, "MTK VCP mailbox initialized\n");
+
+	return devm_mbox_controller_register(dev, &priv->mbox);
+}
+
+static const struct mtk_vcp_mbox_cfg mt8196_cfg = {
+	.set_in		= 0x100,
+	.clr_out	= 0x10C,
+};
+
+static const struct of_device_id mtk_vcp_mbox_of_match[] = {
+	{ .compatible = "mediatek,mt8196-vcp-mbox", .data = &mt8196_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_vcp_mbox_of_match);
+
+static struct platform_driver mtk_vcp_mbox_driver = {
+	.probe		= mtk_vcp_mbox_probe,
+	.driver = {
+		.name	= "mtk_vcp_mbox",
+		.of_match_table = mtk_vcp_mbox_of_match,
+	},
+};
+module_platform_driver(mtk_vcp_mbox_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MTK VCP Mailbox Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mailbox/mtk-vcp-mailbox.h b/include/linux/mailbox/mtk-vcp-mailbox.h
new file mode 100644
index 000000000000..953499b7cfeb
--- /dev/null
+++ b/include/linux/mailbox/mtk-vcp-mailbox.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_MAILBOX_H__
+#define __MTK_VCP_MAILBOX_H__
+
+#define MBOX_SLOT_MAX_SIZE	0x100 /* mbox max slot size */
+#define MAX_SLOT_NUM	64
+
+/**
+ * struct mtk_ipi_info - channel table that belong to mtk_ipi_device
+ * @msg: The share buffer between IPC and mailbox driver
+ * @len: Message length
+ * @id: IPI number
+ * @recv_opt: Recv option,  0:receive ,1: response
+ * @index: The pin groups number of the mailbox channel
+ * @slot_ofs: Slot offset of the mailbox channel
+ * @irq_status: Indicate which pin groups triggered the interrupt
+ *
+ * It is used between IPC with mailbox driver.
+ */
+struct mtk_ipi_info {
+	void *msg;
+	u32 len;
+	u32 id;
+	u32 recv_opt;
+	u32 index;
+	u32 slot_ofs;
+	u32 irq_status;
+};
+
+#endif
--
2.45.2



From jjian.zhou at mediatek.com  Wed Mar  5 00:20:39 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Wed, 5 Mar 2025 16:20:39 +0800
Subject: [PATCH RFC 2/3] firmware: mediatek: Add VCP IPC protocol interface
In-Reply-To: <20250305082047.15746-1-jjian.zhou@mediatek.com>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
Message-ID: <20250305082047.15746-3-jjian.zhou@mediatek.com>

Some of mediatek processors contain the Risc-V coprocessor.

The communication between Host CPU and vcp firmware is
taking place using a shared memory area for message passing.

VCP IPC protocol offers (send/recv) interfaces using
mediatek-mailbox APIs.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 4 files changed, 642 insertions(+)
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 37e43f287e78..98c4ff667836 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -179,6 +179,15 @@ config MTK_ADSP_IPC
 	  ADSP exists on some mtk processors.
 	  Client might use shared memory to exchange information with ADSP.
 
+config MTK_VCP_IPC
+	tristate "MTK VCP IPC Protocol driver"
+	depends on MTK_VCP_MBOX
+	help
+	  Say yes here to add support for the MediaTek VCP IPC
+	  between host AP (Linux) and the firmware running on VCP.
+	  VCP exists on some mtk processors.
+	  Client might use shared memory to exchange information with VCP.
+
 config SYSFB
 	bool
 	select BOOT_VESA_SUPPORT
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 91efcc868a05..2b9894e5169a 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
 obj-$(CONFIG_MTK_ADSP_IPC)	+= mtk-adsp-ipc.o
+obj-$(CONFIG_MTK_VCP_IPC)	+= mtk-vcp-ipc.o
 obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
 obj-$(CONFIG_FW_CFG_SYSFS)	+= qemu_fw_cfg.o
 obj-$(CONFIG_SYSFB)		+= sysfb.o
diff --git a/drivers/firmware/mtk-vcp-ipc.c b/drivers/firmware/mtk-vcp-ipc.c
new file mode 100644
index 000000000000..744937c56b67
--- /dev/null
+++ b/drivers/firmware/mtk-vcp-ipc.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/firmware/mediatek/mtk-vcp-ipc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/sched/clock.h>
+#include <linux/time64.h>
+#include <linux/vmalloc.h>
+
+/**
+ * struct mtk_ipi_chan_table - channel table that belong to mtk_ipi_device
+ * @mbox: the mbox channel number
+ * @mbox_pin_cb: callback function
+ * @holder: keep 1 if there are ipi waiters (to wait the reply)
+ * @ipi_record: timestamp of each ipi transmission stage
+ * @pin_buf: buffer point
+ * @prdata: private data
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @notify: completion notify process
+ * @send_ofs: message offset in the slots of a mbox
+ * @send_index: bit offset in the mbox
+ * @msg_zie: slot size of the ipi message
+ *
+ * All of these data should be initialized by mtk_ipi_device_register()
+ */
+struct mtk_ipi_chan_table {
+	u32 mbox;
+	mbox_pin_cb_t mbox_pin_cb;
+	atomic_t holder;
+	void *pin_buf;
+	void *prdata;
+	u32 recv_opt;
+	struct completion notify;
+	/* define a mutex for remote response */
+	struct mutex mutex_send;
+	u32 send_ofs;
+	u32 send_index;
+	u32 msg_size;
+};
+
+/**
+ * mbox information
+ *
+ * @mbdev: mbox device
+ * @mbox_id: mbox id
+ * @slot: how many slots that mbox used
+ * @opt: option for tx mode, 0:mbox, 1:share memory 2:queue
+ * @base: mbox base address
+ * @mbox_client: mbox client
+ * @mbox_chan: mbox channel
+ */
+struct mtk_mbox_info {
+	struct mtk_vcp_ipc *vcp_ipc;
+	u32 mbox_id;
+	u32 slot;
+	u32 opt;
+	/* lock of mbox */
+	spinlock_t mbox_lock;
+	struct mbox_client cl;
+	struct mbox_chan *ch;
+	struct mtk_ipi_info ipi_info;
+};
+
+static const char * const mbox_names[VCP_MBOX_NUM] = {
+	"mbox0", "mbox1", "mbox2", "mbox3", "mbox4"
+};
+
+/**
+ * mtk_vcp_ipc_recv - recv callback used by MTK VCP mailbox
+ *
+ * @c: mbox client
+ * @msg: message received
+ *
+ * Users of VCP IPC will need to provide handle_reply and handle_request
+ * callbacks.
+ */
+static void mtk_vcp_ipc_recv(struct mbox_client *c, void *msg)
+{
+	struct mtk_mbox_info *minfo = container_of(c, struct mtk_mbox_info, cl);
+	struct mtk_vcp_ipc *vcp_ipc = minfo->vcp_ipc;
+	struct mtk_ipi_info *ipi_info = msg;
+	struct mtk_ipi_device *ipidev = vcp_ipc->ipi_priv;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_mbox_recv_table *mbox_recv;
+	u32 id;
+
+	/* execute all receive pin handler */
+	for (id = 0; id < vcp_ipc->mbdev->recv_count; id++) {
+		mbox_recv = &vcp_ipc->mbdev->recv_table[id];
+		if (mbox_recv->mbox_id != minfo->mbox_id)
+			continue;
+
+		if (!(BIT(mbox_recv->pin_index) & ipi_info->irq_status))
+			continue;
+
+		table = &ipidev->table[mbox_recv->ipi_id];
+		if (!table->pin_buf) {
+			dev_err(vcp_ipc->dev, "IPI%d buf is null.\n",
+				mbox_recv->ipi_id);
+			continue;
+		}
+
+		memcpy(table->pin_buf,
+		       ipi_info->msg + mbox_recv->offset * MBOX_SLOT_SIZE,
+		       mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		if (!mbox_recv->recv_opt && table->mbox_pin_cb)
+			table->mbox_pin_cb(mbox_recv->ipi_id,
+					   table->prdata,
+					   table->pin_buf,
+					   mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		/* notify task */
+		if (table->recv_opt == MBOX_RECV_MESSAGE ||
+		    atomic_read(&table->holder))
+			complete(&table->notify);
+	}
+}
+
+/*
+ * mtk_vcp_ipc_send - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 id, void *data, u32 len)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	mutex_unlock(&table[id].mutex_send);
+	if (ret < 0) {
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send);
+
+/*
+ * mtk_vcp_ipc_send_compl - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ * @timeout_ms:
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 id,
+			   void *data, u32 len, u32 timeout_ms)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	atomic_inc(&table[id].holder);
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	if (ret < 0) {
+		atomic_set(&table[id].holder, 0);
+		mutex_unlock(&table[id].mutex_send);
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	/* wait for completion */
+	ret = wait_for_completion_timeout(&table[id].notify,
+					  msecs_to_jiffies(timeout_ms));
+	atomic_set(&table[id].holder, 0);
+	if (ret > 0)
+		ret = IPI_ACTION_DONE;
+
+	mutex_unlock(&table[id].mutex_send);
+
+	return ret;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send_compl);
+
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+	if (!msg)
+		return IPI_NO_MSGBUF;
+
+	if (ipidev->table[id].pin_buf)
+		return IPI_ALREADY_USED;
+	ipidev->table[id].mbox_pin_cb = cb;
+	ipidev->table[id].pin_buf = msg;
+	ipidev->table[id].prdata = prdata;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_register);
+
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int id)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+
+	/* Drop the ipi and reset the record */
+	complete(&ipidev->table[id].notify);
+
+	ipidev->table[id].mbox_pin_cb = NULL;
+	ipidev->table[id].pin_buf = NULL;
+	ipidev->table[id].prdata = NULL;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_unregister);
+
+static void mtk_fill_in_entry(struct mtk_ipi_chan_table *entry, const u32 ipi_id,
+			      const struct mtk_mbox_table *mbdev)
+{
+	const struct mtk_mbox_send_table *mbox_send = mbdev->send_table;
+	u32 index;
+
+	for (index = 0; index < mbdev->send_count; index++) {
+		if (ipi_id != mbox_send[index].ipi_id)
+			continue;
+
+		entry->send_ofs = mbox_send[index].offset;
+		entry->send_index = mbox_send[index].pin_index;
+		entry->msg_size = mbox_send[index].msg_size;
+		entry->mbox = mbox_send[index].mbox_id;
+		return;
+	}
+
+	entry->mbox = -ENOENT;
+}
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count, struct mtk_vcp_ipc *vcp_ipc)
+{
+	struct mtk_ipi_chan_table *ipi_chan_table;
+	struct mtk_mbox_table *mbdev;
+	u32 index;
+
+	if (!vcp_ipc || !ipidev)
+		return -EINVAL;
+
+	ipi_chan_table = kcalloc(ipi_chan_count,
+				 sizeof(struct mtk_ipi_chan_table), GFP_KERNEL);
+	if (!ipi_chan_table)
+		return -ENOMEM;
+
+	mbdev = vcp_ipc->mbdev;
+	vcp_ipc->ipi_priv = (void *)ipidev;
+	ipidev->table = ipi_chan_table;
+	ipidev->vcp_ipc = vcp_ipc;
+
+	for (index = 0; index < ipi_chan_count; index++) {
+		atomic_set(&ipi_chan_table[index].holder, 0);
+		mutex_init(&ipi_chan_table[index].mutex_send);
+		init_completion(&ipi_chan_table[index].notify);
+		mtk_fill_in_entry(&ipi_chan_table[index], index, mbdev);
+	}
+
+	ipidev->ipi_inited = 1;
+
+	dev_dbg(vcp_ipc->dev, "%s (with %d IPI) has registered.\n",
+		ipidev->name, ipi_chan_count);
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_device_register);
+
+static int setup_mbox_table(struct mtk_mbox_table *mbdev, u32 mbox)
+{
+	struct mtk_mbox_send_table *mbox_send = &mbdev->send_table[0];
+	struct mtk_mbox_recv_table *mbox_recv = &mbdev->recv_table[0];
+	u32 i, last_ofs = 0, last_idx = 0, last_slot = 0, last_sz = 0;
+
+	for (i = 0; i < mbdev->send_count; i++) {
+		if (mbox == mbox_send[i].mbox_id) {
+			mbox_send[i].offset = last_ofs + last_slot;
+			mbox_send[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_send[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_send[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_send[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	for (i = 0; i < mbdev->recv_count; i++) {
+		if (mbox == mbox_recv[i].mbox_id) {
+			mbox_recv[i].offset = last_ofs + last_slot;
+			mbox_recv[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_recv[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_recv[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_recv[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	if (last_idx > MBOX_MAX_PIN || (last_ofs + last_slot) > MAX_SLOT_NUM)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mtk_vcp_ipc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mbox_client *cl;
+	struct mtk_mbox_info *minfo;
+	int ret;
+	u32 mbox, i;
+	struct mtk_mbox_table *mbox_data = dev_get_platdata(dev);
+
+	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
+	vcp_ipc = devm_kzalloc(dev, sizeof(*vcp_ipc), GFP_KERNEL);
+	if (!vcp_ipc)
+		return -ENOMEM;
+
+	if (!mbox_data) {
+		dev_err(dev, "No platform data available\n");
+		return -EINVAL;
+	}
+	vcp_ipc->mbdev = mbox_data;
+
+	/* alloc and init mmup_mbox_info */
+	vcp_ipc->info_table = vzalloc(sizeof(*vcp_ipc->info_table) * VCP_MBOX_NUM);
+	if (!vcp_ipc->info_table)
+		return -ENOMEM;
+
+	/* create mbox dev */
+	for (mbox = 0; mbox < VCP_MBOX_NUM; mbox++) {
+		minfo = &vcp_ipc->info_table[mbox];
+		minfo->mbox_id = mbox;
+		minfo->vcp_ipc = vcp_ipc;
+		spin_lock_init(&minfo->mbox_lock);
+
+		ret = setup_mbox_table(vcp_ipc->mbdev, mbox);
+		if (ret)
+			return ret;
+
+		cl = &minfo->cl;
+		cl->dev = &pdev->dev;
+		cl->tx_block = false;
+		cl->knows_txdone = false;
+		cl->tx_prepare = NULL;
+		cl->rx_callback = mtk_vcp_ipc_recv;
+		minfo->ch = mbox_request_channel_byname(cl, mbox_names[mbox]);
+		if (IS_ERR(minfo->ch)) {
+			ret = PTR_ERR(minfo->ch);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to request mbox channel %s ret %d\n",
+					mbox_names[mbox], ret);
+
+			for (i = 0; i < mbox; i++) {
+				minfo = &vcp_ipc->info_table[i];
+				mbox_free_channel(minfo->ch);
+			}
+
+			vfree(vcp_ipc->info_table);
+			return ret;
+		}
+	}
+
+	vcp_ipc->dev = dev;
+	dev_set_drvdata(dev, vcp_ipc);
+	dev_dbg(dev, "MTK VCP IPC initialized\n");
+
+	return 0;
+}
+
+static void mtk_vcp_ipc_remove(struct platform_device *pdev)
+{
+	struct mtk_vcp_ipc *vcp_ipc = dev_get_drvdata(&pdev->dev);
+	struct mtk_mbox_info *minfo;
+	int i;
+
+	for (i = 0; i < VCP_MBOX_NUM; i++) {
+		minfo = &vcp_ipc->info_table[i];
+		mbox_free_channel(minfo->ch);
+	}
+
+	vfree(vcp_ipc->info_table);
+}
+
+static struct platform_driver mtk_vcp_ipc_driver = {
+	.probe = mtk_vcp_ipc_probe,
+	.remove = mtk_vcp_ipc_remove,
+	.driver = {
+		.name = "mtk-vcp-ipc",
+	},
+};
+builtin_platform_driver(mtk_vcp_ipc_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek VCP IPC Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/mediatek/mtk-vcp-ipc.h b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
new file mode 100644
index 000000000000..dc34b0ba9dd8
--- /dev/null
+++ b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_IPC_H__
+#define __MTK_VCP_IPC_H__
+
+#include <linux/completion.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* IPI result definition */
+#define IPI_ACTION_DONE	  0
+#define IPI_DEV_ILLEGAL	 -1 /* ipi device is not initialized */
+#define IPI_ALREADY_USED	 -2 /* the ipi has be registered */
+#define IPI_UNAVAILABLE	 -3 /* the ipi can't be found */
+#define IPI_NO_MSGBUF		 -4 /* receiver doesn't have message buffer */
+#define IPI_MSG_TOO_BIG		 -5 /* message length is larger than defined */
+#define IPI_MBOX_ERR		-99 /* some error from rpmsg layer */
+
+/* mbox recv action definition */
+enum mtk_ipi_recv_opt {
+	MBOX_RECV_MESSAGE  = 0,
+	MBOX_RECV_ACK      = 1,
+};
+
+/* mbox table item number definition */
+#define send_item_num	3
+#define recv_item_num	4
+#define VCP_MBOX_NUM	5
+
+/* mbox slot size definition: 1 slot for 4 bytes */
+#define MBOX_SLOT_SIZE	0x4
+#define MBOX_MAX_PIN	32
+#define VCP_MBOX_NUM	5
+#define MBOX_SLOT_ALIGN	2
+
+struct mtk_vcp_ipc;
+struct mtk_ipi_chan_table;
+
+typedef int (*mbox_pin_cb_t)(u32 ipi_id, void *prdata, void *data, u32 len);
+
+/**
+ * mbox pin structure, this is for send definition,
+ * @offset: message offset in the slots of a mbox
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_send_table {
+	u32 offset;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * mbox pin structure, this is for receive definition,
+ * @offset: message offset in the slots of a mbox
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_recv_table {
+	u32 offset;
+	u32 recv_opt;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * struct mtk_ipi_device - device for represent the tinysys using mtk ipi
+ * @name: name of tinysys device
+ * @id: device id (used to match between rpmsg drivers and devices)
+ * @vcp_ipc: vcp ipc structure for tinysys device
+ * @table: channel table with endpoint & channel_info & mbox_pin info
+ * @prdata: private data for the callback use
+ * @ipi_inited: set when vcp_ipi_device_register() done
+ */
+struct mtk_ipi_device  {
+	const char *name;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mtk_ipi_chan_table *table;
+	void *prdata;
+	int ipi_inited;
+};
+
+/**
+ * The mtk_mbox_table is a structure used to record the send
+ * table and recv table. The send table is used to record
+ * the feature ID and size of the sent data. The recv table
+ * is used to record the feature ID and size of the received
+ * data, and whether a callback needs to be invoked.
+ *
+ * Following are platform specific interfacer
+ * @recv_table: structure mtk_mbox_recv_table
+ * @send_table: structure mtk_mbox_send_table
+ * @recv_count: receive feature number in this channel
+ * @send_count: send feature number in this channel
+ */
+struct mtk_mbox_table {
+	struct mtk_mbox_recv_table recv_table[32];
+	struct mtk_mbox_send_table send_table[32];
+	u32 recv_count;
+	u32 send_count;
+};
+
+/**
+ * Mbox is a dedicate hardware of a tinysys consists of:
+ * 1) a share memory tightly coupled to the tinysys
+ * 2) several IRQs
+ *
+ * Following are platform specific interface
+ * @dev: vcp device
+ * @name: identity of the device
+ * @info_table: mbox info structure
+ * @ipi_priv: private data for synchronization layer
+ * @mbox_id: mbox number
+ * @mbdev: mtk_mbox_table structure
+ */
+struct mtk_vcp_ipc {
+	struct device *dev;
+	const char *name;
+	struct mtk_mbox_info *info_table;
+	void *ipi_priv;
+	void *mbox_id;
+	struct mtk_mbox_table *mbdev;
+};
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count,
+				struct mtk_vcp_ipc *vcp_ipc);
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 ipi_id,
+		     void *data, u32 len);
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 ipi_id,
+			   void *data, u32 len, u32 timeout_ms);
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int ipi_id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg);
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int ipi_id);
+
+#endif
-- 
2.45.2



From jjian.zhou at mediatek.com  Wed Mar  5 00:20:40 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Wed, 5 Mar 2025 16:20:40 +0800
Subject: [PATCH RFC 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document
In-Reply-To: <20250305082047.15746-1-jjian.zhou@mediatek.com>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
Message-ID: <20250305082047.15746-4-jjian.zhou@mediatek.com>

This patch adds document for mediatek vcp mbox.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 .../bindings/mailbox/mtk,vcp-mbox.yaml        | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml

diff --git a/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
new file mode 100644
index 000000000000..d5afe295af14
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/mtk,vcp-mbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Video Companion Processor (VCP) mailbox
+
+maintainers:
+  - Jjian Zhou <Jjian.Zhou at mediatek.com>
+
+description: |
+  The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
+  messages through 64 32-bit wide registers. It has 32 interrupt vectors in
+  either direction for signalling purposes.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8196-vcp-mbox
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  "#mbox-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - "#mbox-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    vcp_mailbox0: mailbox at 31b80000 {
+        compatible = "mediatek,mt8196-vcp-mbox";
+        reg = <0x31b80000 0x1000>;
+        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
+        #mbox-cells = <0>;
+    };
-- 
2.45.2



From razor at blackwall.org  Wed Mar  5 00:21:33 2025
From: razor at blackwall.org (Nikolay Aleksandrov)
Date: Wed, 5 Mar 2025 10:21:33 +0200
Subject: [PATCH v8 net-next 01/15] net: pppoe: avoid zero-length arrays in
 struct pppoe_hdr
In-Reply-To: <20250228201533.23836-2-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
 <20250228201533.23836-2-ericwouds@gmail.com>
Message-ID: <b3b5418c-65d5-48bf-8868-2d9abcb4f758@blackwall.org>

On 2/28/25 22:15, Eric Woudstra wrote:
> Jakub Kicinski suggested following patch:
> 
> W=1 C=1 GCC build gives us:
> 
> net/bridge/netfilter/nf_conntrack_bridge.c: note: in included file (through
> ../include/linux/if_pppox.h, ../include/uapi/linux/netfilter_bridge.h,
> ../include/linux/netfilter_bridge.h): include/uapi/linux/if_pppox.h:
> 153:29: warning: array of flexible structures
> 
> It doesn't like that hdr has a zero-length array which overlaps proto.
> The kernel code doesn't currently need those arrays.
> 
> PPPoE connection is functional after applying this patch.
> 
> Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
> ---
>  drivers/net/ppp/pppoe.c       | 2 +-
>  include/uapi/linux/if_pppox.h | 4 ++++
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>



From razor at blackwall.org  Wed Mar  5 00:22:35 2025
From: razor at blackwall.org (Nikolay Aleksandrov)
Date: Wed, 5 Mar 2025 10:22:35 +0200
Subject: [PATCH v8 net-next 11/15] netfilter: nft_flow_offload: Add
 DEV_PATH_MTK_WDMA to nft_dev_path_info()
In-Reply-To: <20250228201533.23836-12-ericwouds@gmail.com>
References: <20250228201533.23836-1-ericwouds@gmail.com>
 <20250228201533.23836-12-ericwouds@gmail.com>
Message-ID: <350a057e-39ae-4e8d-a4ec-12b2f78f51cb@blackwall.org>

On 2/28/25 22:15, Eric Woudstra wrote:
> In case of using mediatek wireless, in nft_dev_fill_forward_path(), the
> forward path is filled, ending with mediatek wlan1.
> 
> Because DEV_PATH_MTK_WDMA is unknown inside nft_dev_path_info() it returns
> with info.indev = NULL. Then nft_dev_forward_path() returns without
> setting the direct transmit parameters.
> 
> This results in a neighbor transmit, and direct transmit not possible.
> But we want to use it for flow between bridged interfaces.
> 
> So this patch adds DEV_PATH_MTK_WDMA to nft_dev_path_info() and makes
> direct transmission possible.
> 
> Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
> ---
>  net/netfilter/nft_flow_offload.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
> index 323c531c7046..b9e6d9e6df66 100644
> --- a/net/netfilter/nft_flow_offload.c
> +++ b/net/netfilter/nft_flow_offload.c
> @@ -105,6 +105,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
>  		switch (path->type) {
>  		case DEV_PATH_ETHERNET:
>  		case DEV_PATH_DSA:
> +		case DEV_PATH_MTK_WDMA:
>  		case DEV_PATH_VLAN:
>  		case DEV_PATH_PPPOE:
>  			info->indev = path->dev;
> @@ -117,6 +118,10 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
>  				i = stack->num_paths;
>  				break;
>  			}
> +			if (path->type == DEV_PATH_MTK_WDMA) {
> +				i = stack->num_paths;
> +				break;
> +			}
>  
>  			/* DEV_PATH_VLAN and DEV_PATH_PPPOE */
>  			if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>



From hpa at zytor.com  Wed Mar  5 00:29:45 2025
From: hpa at zytor.com (H. Peter Anvin)
Date: Wed, 05 Mar 2025 00:29:45 -0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn> <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net> <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com> <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net> <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com> <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com> <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
Message-ID: <694E52E0-C9E5-49D2-A677-09A5EE442590@zytor.com>

On March 4, 2025 5:19:09 PM PST, Menglong Dong <menglong8.dong at gmail.com> wrote:
>On Tue, Mar 4, 2025 at 10:53?PM H. Peter Anvin <hpa at zytor.com> wrote:
>>
>> On March 4, 2025 1:42:20 AM PST, Peter Zijlstra <peterz at infradead.org> wrote:
>> >On Tue, Mar 04, 2025 at 03:47:45PM +0800, Menglong Dong wrote:
>> >> We don't have to select FUNCTION_ALIGNMENT_32B, so the
>> >> worst case is to increase ~2.2%.
>> >>
>> >> What do you think?
>> >
>> >Well, since I don't understand what you need this for at all, I'm firmly
>> >on the side of not doing this.
>> >
>> >What actual problem is being solved with this meta data nonsense? Why is
>> >it worth blowing up our I$ footprint over.
>> >
>> >Also note, that if you're going to be explaining this, start from
>> >scratch, as I have absolutely 0 clues about BPF and such.
>>
>> I would appreciate such information as well. The idea seems dubious on the surface.
>
>Ok, let me explain it from the beginning. (My English is not good,
>but I'll try to describe it as clear as possible :/)
>
>Many BPF program types need to depend on the BPF trampoline,
>such as BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_EXT,
>BPF_PROG_TYPE_LSM, etc. BPF trampoline is a bridge between
>the kernel (or bpf) function and BPF program, and it acts just like the
>trampoline that ftrace uses.
>
>Generally speaking, it is used to hook a function, just like what ftrace
>do:
>
>foo:
>    endbr
>    nop5  -->  call trampoline_foo
>    xxxx
>
>In short, the trampoline_foo can be this:
>
>trampoline_foo:
>    prepare a array and store the args of foo to the array
>    call fentry_bpf1
>    call fentry_bpf2
>    ......
>    call foo+4 (origin call)
>    save the return value of foo
>    call fexit_bpf1 (this bpf can get the return value of foo)
>    call fexit_bpf2
>    .......
>    return to the caller of foo
>
>We can see that the trampoline_foo can be only used for
>the function foo, as different kernel function can be attached
>different BPF programs, and have different argument count,
>etc. Therefore, we have to create 1000 BPF trampolines if
>we want to attach a BPF program to 1000 kernel functions.
>
>The creation of the BPF trampoline is expensive. According to
>my testing, It will spend more than 1 second to create 100 bpf
>trampoline. What's more, it consumes more memory.
>
>If we have the per-function metadata supporting, then we can
>create a global BPF trampoline, like this:
>
>trampoline_global:
>    prepare a array and store the args of foo to the array
>    get the metadata by the ip
>    call metadata.fentry_bpf1
>    call metadata.fentry_bpf2
>    ....
>    call foo+4 (origin call)
>    save the return value of foo
>    call metadata.fexit_bpf1 (this bpf can get the return value of foo)
>    call metadata.fexit_bpf2
>    .......
>    return to the caller of foo
>
>(The metadata holds more information for the global trampoline than
>I described.)
>
>Then, we don't need to create a trampoline for every kernel function
>anymore.
>
>Another beneficiary can be ftrace. For now, all the kernel functions that
>are enabled by dynamic ftrace will be added to a filter hash if there are
>more than one callbacks. And hash lookup will happen when the traced
>functions are called, which has an impact on the performance, see
>__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
>metadata supporting, we can store the information that if the callback is
>enabled on the kernel function to the metadata, which can make the performance
>much better.
>
>The per-function metadata storage is a basic function, and I think there
>may be other functions that can use it for better performance in the feature
>too.
>
>(Hope that I'm describing it clearly :/)
>
>Thanks!
>Menglong Dong
>

This is way too cursory. For one thing, you need to start by explaining why you are asking to put this *inline* with the code, which is something that normally would be avoided at all cost.


From lukasz.luba at arm.com  Wed Mar  5 00:42:11 2025
From: lukasz.luba at arm.com (Lukasz Luba)
Date: Wed, 5 Mar 2025 08:42:11 +0000
Subject: [PATCH v3 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <CANAwSgSWf_YxSi-pzWPaRoiJx7RLrWUz+HTWx5hf+E2x1ZGmoQ@mail.gmail.com>
References: <20250216195850.5352-1-linux.amoon@gmail.com>
 <20250216195850.5352-5-linux.amoon@gmail.com>
 <f44efd1a-1f6e-456d-9395-de2a55ef2279@arm.com>
 <CANAwSgTpV_kGFEU-ND0N+OEtT6+j4ceq37xAoLyC7iHPWAuLjg@mail.gmail.com>
 <CANAwSgSWf_YxSi-pzWPaRoiJx7RLrWUz+HTWx5hf+E2x1ZGmoQ@mail.gmail.com>
Message-ID: <7a1cac10-b065-4b4c-b048-10d6b4132f3d@arm.com>



On 3/4/25 12:20, Anand Moon wrote:
> Hi Lukasz,
> 
> On Sat, 1 Mar 2025 at 00:06, Anand Moon <linux.amoon at gmail.com> wrote:
>>
>> Hi Lukasz,
>>
>> On Fri, 28 Feb 2025 at 22:58, Lukasz Luba <lukasz.luba at arm.com> wrote:
>>>
>>>
>>>
>>> On 2/16/25 19:58, Anand Moon wrote:
>>>> Using guard notation makes the code more compact and error handling
>>>> more robust by ensuring that mutexes are released in all code paths
>>>> when control leaves critical section.
>>>>
>>>> Signed-off-by: Anand Moon <linux.amoon at gmail.com>
>>>> ---
>>>> v3: new patch
>>>> ---
>>>>    drivers/thermal/samsung/exynos_tmu.c | 21 +++++++--------------
>>>>    1 file changed, 7 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>>> index fe090c1a93ab..a34ba3858d64 100644
>>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>>> @@ -256,7 +256,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>        unsigned int status;
>>>>        int ret = 0;
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>        clk_enable(data->clk_sec);
>>>>
>>>> @@ -270,7 +270,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>
>>>>        clk_disable(data->clk_sec);
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>
>>>>        return ret;
>>>>    }
>>>> @@ -292,13 +291,12 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
>>>>                return ret;
>>>>        }
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>
>>>>        data->tmu_set_crit_temp(data, temp / MCELSIUS);
>>>>
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>
>>>>        return 0;
>>>>    }
>>>> @@ -325,12 +323,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>>    {
>>>>        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>        data->tmu_control(pdev, on);
>>>>        data->enabled = on;
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>    }
>>>>
>>>>    static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
>>>> @@ -645,7 +642,7 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
>>>>                 */
>>>>                return -EAGAIN;
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>
>>>>        value = data->tmu_read(data);
>>>> @@ -655,7 +652,6 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
>>>>                *temp = code_to_temp(data, value) * MCELSIUS;
>>>>
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>
>>>>        return ret;
>>>>    }
>>>> @@ -720,11 +716,10 @@ static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
>>>>        if (temp && temp < MCELSIUS)
>>>>                goto out;
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>        data->tmu_set_emulation(data, temp);
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>        return 0;
>>>>    out:
>>>>        return ret;
>>>> @@ -760,14 +755,13 @@ static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id)
>>>>
>>>>        thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>
>>>>        /* TODO: take action based on particular interrupt */
>>>>        data->tmu_clear_irqs(data);
>>>>
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>
>>>>        return IRQ_HANDLED;
>>>>    }
>>>> @@ -987,7 +981,7 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
>>>>    {
>>>>        struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
>>>>
>>>> -     mutex_lock(&data->lock);
>>>> +     guard(mutex)(&data->lock);
>>>>        clk_enable(data->clk);
>>>>
>>>>        if (low > INT_MIN)
>>>> @@ -1000,7 +994,6 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
>>>>                data->tmu_disable_high(data);
>>>>
>>>>        clk_disable(data->clk);
>>>> -     mutex_unlock(&data->lock);
>>>>
>>>>        return 0;
>>>>    }
>>
>> Thanks for your review comments.
>>>
>>> IMO you should be able to even use something like we have
>>> core framework:
>>>
>>> guard(thermal_zone)(tz);
>>>
>>> Your mutex name is simply 'lock' in the struct exynos_tmu_data
>>> so you should be able to leverage this by:
>>>
>>> guard(exynos_tmu_data)(data);
>>>
> 
> If I introduce the guard it creates a compilation error
> 
> amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ vi
> drivers/thermal/samsung/exynos_tmu.c +306
> amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ make -j$(nproc)
> ARCH=arm CROSS_COMPILE=arm-none-eabi- LOCALVERSION=-u3ml dtbs zImage
> modules
>    CALL    scripts/checksyscalls.sh
>    CHK     kernel/kheaders_data.tar.xz
>    CC      drivers/thermal/samsung/exynos_tmu.o
>    CC [M]  drivers/md/raid10.o
> In file included from ./include/linux/irqflags.h:17,
>                   from ./arch/arm/include/asm/bitops.h:28,
>                   from ./include/linux/bitops.h:68,
>                   from ./include/linux/kernel.h:23,
>                   from ./include/linux/clk.h:13,
>                   from drivers/thermal/samsung/exynos_tmu.c:14:
> drivers/thermal/samsung/exynos_tmu.c: In function 'exynos_tmu_update_bit':
> ./include/linux/cleanup.h:258:9: error: unknown type name
> 'class_exynos_tmu_data_t'
>    258 |         class_##_name##_t var
> __cleanup(class_##_name##_destructor) =   \
>        |         ^~~~~~
> ./include/linux/cleanup.h:309:9: note: in expansion of macro 'CLASS'
>    309 |         CLASS(_name, __UNIQUE_ID(guard))
>        |         ^~~~~
> drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
>    338 |         guard(exynos_tmu_data)(data);
>        |         ^~~~~
> drivers/thermal/samsung/exynos_tmu.c:338:9: error: cleanup argument
> not a function

[snip]

Right, you're missing the definition at the begging, like:

DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *, 
mutex_lock(&_T->lock),
              mutex_unlock(&_T->lock))

below the struct exynos_tmu_data definition.

Also, make sure you include the cleanup.h (it might not complain,
but it would be explicit and more clear)


From aliceryhl at google.com  Wed Mar  5 00:42:57 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Wed, 5 Mar 2025 08:42:57 +0000
Subject: [PATCH v3 5/5] rust: Add warn_on and warn_on_once
In-Reply-To: <20250213135759.190006-6-fujita.tomonori@gmail.com>
References: <20250213135759.190006-1-fujita.tomonori@gmail.com> <20250213135759.190006-6-fujita.tomonori@gmail.com>
Message-ID: <Z8gOkeJ8o2pMCwGu@google.com>

On Thu, Feb 13, 2025 at 10:57:59PM +0900, FUJITA Tomonori wrote:
> Add warn_on and warn_on_once macros. Wrapping the C's WARN_* and BUG_*
> macros doesn't work so this uses the assembly code exported by the C
> side via ARCH_WARN_ASM macro. Like the static branch code, this
> generates the assembly code for rust at compile time by using the C
> preprocessor.
> 
> file()! macro doesn't work for the Rust inline assembly in the same
> way as __FILE__ for the C inline assembly. So the code to handle a
> file name is different from the C assembly code (similar to the
> arm64/loongarch assembly).

Nit: Should be file!() not file()!.

> diff --git a/rust/kernel/.gitignore b/rust/kernel/.gitignore
> index 6ba39a178f30..f1d7f4225332 100644
> --- a/rust/kernel/.gitignore
> +++ b/rust/kernel/.gitignore
> @@ -1,3 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  /generated_arch_static_branch_asm.rs
> +/generated_arch_warn_asm.rs
> +/generated_arch_reachable_asm.rs
> \ No newline at end of file

There should be a newline.

> +++ b/rust/kernel/bug.rs
> @@ -0,0 +1,100 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2024 FUJITA Tomonori

2025?

> +#[macro_export]
> +#[doc(hidden)]
> +#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
> +macro_rules! warn_flags {
> +    ($flags:expr) => {
> +        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
> +        // SAFETY: Just an FFI call.
> +        #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
> +        unsafe {
> +            $crate::asm!(concat!(
> +                "/* {size} */",
> +                ".pushsection .rodata.str1.1, \"aMS\", at progbits, 1\n",
> +                "111:\t .string ", "\"", file!(), "\"\n",
> +                ".popsection\n",
> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
> +            line = const line!(),
> +            flags = const FLAGS,
> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
> +            );
> +        }
> +        // SAFETY: Just an FFI call.
> +        #[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
> +        unsafe {
> +            $crate::asm!(
> +            concat!(
> +                "/* {size} */",
> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
> +            flags = const FLAGS,
> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
> +            );
> +        }

I generally prefer to have the cfgs on the macro rather in its
expansion. That avoids emitting a lot of code that is not actually used.

> +#[doc(hidden)]
> +#[macro_export]
> +macro_rules! bugflag_taint {
> +    ($taint:expr) => {
> +        $taint << 8
> +    };
> +}

This could just be a const fn.

> +/// Report a warning only once.
> +#[macro_export]
> +macro_rules! warn_on_once {
> +    ($cond:expr) => {
> +        if $cond {
> +            $crate::warn_flags!(
> +                $crate::bindings::BUGFLAG_ONCE
> +                    | $crate::bugflag_taint!($crate::bindings::TAINT_WARN)

Or maybe a constant?

const WARN_ON_ONCE_FLAGS: u32 = bindings::BUGFLAG_ONCE | (bindings::TAINT_WARN << 8);

$crate::warn_flags!($crate::bug::WARN_ON_ONCE_FLAGS);

Alice


From shameerali.kolothum.thodi at huawei.com  Wed Mar  5 00:50:17 2025
From: shameerali.kolothum.thodi at huawei.com (Shameerali Kolothum Thodi)
Date: Wed, 5 Mar 2025 08:50:17 +0000
Subject: [PATCH v1 1/4] iommu/arm-smmu-v3: Pass in vmid to
 arm_smmu_make_s2_domain_ste()
In-Reply-To: <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>
Message-ID: <a95b39a55c324907a7001d3a2cdf076b@huawei.com>

Hi Nicolin,

Thanks for sending out this series. This might as well help me to rework my pinned KVM
VMID series here,
https://lore.kernel.org/linux-iommu/20240208151837.35068-1-shameerali.kolothum.thodi at huawei.com/


> -----Original Message-----
> From: Nicolin Chen <nicolinc at nvidia.com>
> Sent: Wednesday, March 5, 2025 5:04 AM
> To: will at kernel.org; robin.murphy at arm.com; jgg at nvidia.com
> Cc: joro at 8bytes.org; linux-arm-kernel at lists.infradead.org;
> iommu at lists.linux.dev; linux-kernel at vger.kernel.org; Shameerali Kolothum
> Thodi <shameerali.kolothum.thodi at huawei.com>
> Subject: [PATCH v1 1/4] iommu/arm-smmu-v3: Pass in vmid to
> arm_smmu_make_s2_domain_ste()
> 
> An stage-2 STE requires a vmid that has been so far allocated per domain,
> so arm_smmu_make_s2_domain_ste() has been extracting the vmid from
> the S2
> domain.
> 
> To share an S2 parent domain across vSMMUs in the same VM, a vmid will
> be
> no longer allocated for nor stored in the S2 domain, but per vSMMU, which
> means the arm_smmu_make_s2_domain_ste() can get a vmid either from
> an S2
> domain (non nesting parent) or a vSMMU.
> 
> Allow to pass in vmid explicitly to arm_smmu_make_s2_domain_ste(),
> giving
> its callers a chance to pick the vmid between a domain or a vSMMU.
> 
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 2 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 6 ++++--
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c    | 3 ++-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c         | 6 +++---
>  4 files changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> index bd9d7c85576a..e08c4ede4b2d 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -887,7 +887,7 @@ struct arm_smmu_entry_writer_ops {
>  void arm_smmu_make_abort_ste(struct arm_smmu_ste *target);
>  void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
>  				 struct arm_smmu_master *master,
> -				 struct arm_smmu_domain *smmu_domain,
> +				 struct arm_smmu_domain *smmu_domain,
> u16 vmid,
>  				 bool ats_enabled);

Now that vmid is an input, do we need some kind of validation here as
at least vmid = 0 is reserved I guess for bypass STEs.

Thanks,
Shameer



From menglong8.dong at gmail.com  Wed Mar  5 00:49:47 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Wed, 5 Mar 2025 16:49:47 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <694E52E0-C9E5-49D2-A677-09A5EE442590@zytor.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
 <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com> <694E52E0-C9E5-49D2-A677-09A5EE442590@zytor.com>
Message-ID: <CADxym3Zu1u1xF0k+N4gZ50jHtZ9iRRQ0ZTtt_koG8Ta+B0DPJg@mail.gmail.com>

On Wed, Mar 5, 2025 at 4:30?PM H. Peter Anvin <hpa at zytor.com> wrote:
>
> On March 4, 2025 5:19:09 PM PST, Menglong Dong <menglong8.dong at gmail.com> wrote:
> >On Tue, Mar 4, 2025 at 10:53?PM H. Peter Anvin <hpa at zytor.com> wrote:
> >>
> >> On March 4, 2025 1:42:20 AM PST, Peter Zijlstra <peterz at infradead.org> wrote:
> >> >On Tue, Mar 04, 2025 at 03:47:45PM +0800, Menglong Dong wrote:
> >> >> We don't have to select FUNCTION_ALIGNMENT_32B, so the
> >> >> worst case is to increase ~2.2%.
> >> >>
> >> >> What do you think?
> >> >
> >> >Well, since I don't understand what you need this for at all, I'm firmly
> >> >on the side of not doing this.
> >> >
> >> >What actual problem is being solved with this meta data nonsense? Why is
> >> >it worth blowing up our I$ footprint over.
> >> >
> >> >Also note, that if you're going to be explaining this, start from
> >> >scratch, as I have absolutely 0 clues about BPF and such.
> >>
> >> I would appreciate such information as well. The idea seems dubious on the surface.
> >
> >Ok, let me explain it from the beginning. (My English is not good,
> >but I'll try to describe it as clear as possible :/)
> >
> >Many BPF program types need to depend on the BPF trampoline,
> >such as BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_EXT,
> >BPF_PROG_TYPE_LSM, etc. BPF trampoline is a bridge between
> >the kernel (or bpf) function and BPF program, and it acts just like the
> >trampoline that ftrace uses.
> >
> >Generally speaking, it is used to hook a function, just like what ftrace
> >do:
> >
> >foo:
> >    endbr
> >    nop5  -->  call trampoline_foo
> >    xxxx
> >
> >In short, the trampoline_foo can be this:
> >
> >trampoline_foo:
> >    prepare a array and store the args of foo to the array
> >    call fentry_bpf1
> >    call fentry_bpf2
> >    ......
> >    call foo+4 (origin call)
> >    save the return value of foo
> >    call fexit_bpf1 (this bpf can get the return value of foo)
> >    call fexit_bpf2
> >    .......
> >    return to the caller of foo
> >
> >We can see that the trampoline_foo can be only used for
> >the function foo, as different kernel function can be attached
> >different BPF programs, and have different argument count,
> >etc. Therefore, we have to create 1000 BPF trampolines if
> >we want to attach a BPF program to 1000 kernel functions.
> >
> >The creation of the BPF trampoline is expensive. According to
> >my testing, It will spend more than 1 second to create 100 bpf
> >trampoline. What's more, it consumes more memory.
> >
> >If we have the per-function metadata supporting, then we can
> >create a global BPF trampoline, like this:
> >
> >trampoline_global:
> >    prepare a array and store the args of foo to the array
> >    get the metadata by the ip
> >    call metadata.fentry_bpf1
> >    call metadata.fentry_bpf2
> >    ....
> >    call foo+4 (origin call)
> >    save the return value of foo
> >    call metadata.fexit_bpf1 (this bpf can get the return value of foo)
> >    call metadata.fexit_bpf2
> >    .......
> >    return to the caller of foo
> >
> >(The metadata holds more information for the global trampoline than
> >I described.)
> >
> >Then, we don't need to create a trampoline for every kernel function
> >anymore.
> >
> >Another beneficiary can be ftrace. For now, all the kernel functions that
> >are enabled by dynamic ftrace will be added to a filter hash if there are
> >more than one callbacks. And hash lookup will happen when the traced
> >functions are called, which has an impact on the performance, see
> >__ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
> >metadata supporting, we can store the information that if the callback is
> >enabled on the kernel function to the metadata, which can make the performance
> >much better.
> >
> >The per-function metadata storage is a basic function, and I think there
> >may be other functions that can use it for better performance in the feature
> >too.
> >
> >(Hope that I'm describing it clearly :/)
> >
> >Thanks!
> >Menglong Dong
> >
>
> This is way too cursory. For one thing, you need to start by explaining why you are asking to put this *inline* with the code, which is something that normally would be avoided at all cost.

Hi,

Sorry that I don't understand the *inline* here, do you mean
why puting the metadata in the function padding?


From Jason-JH.Lin at mediatek.com  Wed Mar  5 00:36:58 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Wed, 5 Mar 2025 08:36:58 +0000
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
	 <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
Message-ID: <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>

Hi Angelo,

Thanks for the reviews.

On Tue, 2025-03-04 at 10:32 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > MT8196 has 3 new hardware configuration compared with the previous
> > SoC,
> > which correspond to the 3 new driver data:
> > 
> > 1. mminfra_offset: For GCE data plane control
> > ??? Since GCE has been moved into mminfra, GCE needs to append the
> > ??? mminfra offset to the DRAM address when accessing the DRAM.
> > 
> > 2. gce_vm: For GCE hardware virtualization
> > ??? Currently, the first version of the mt8196 mailbox controller
> > only
> > ??? requires setting the VM-related registers to enable the
> > permissions
> > ??? of a host VM.
> 
> I think that the GCE VM changes should go to a different commit, as
> that
> looks like being something not critical for basic functionality of
> the
> MMINFRA GCE.
> 
> I really like seeing support for that, but please split the basic
> stuff
> from the extra functionality :-)
> 

The VM configuration is the basic configuration for MT8196, so I put it
together with other configurations in one patch.
But I can understand you want the new function as a independent patch.
So I will split the VM related part, mminfra_offset part and dma_mask
part to 3 single pathes. Then add them as a driver data for MT8196 in
this patch.

> > 
> > 3. dma_mask_bit: For dma address bit control
> > ??? In order to avoid the hardware limitations of MT8196 accessing
> > DRAM,
> > ??? GCE needs to configure the DMA address to be less than 35 bits.
> > 
> > Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> > ---
> > ? drivers/mailbox/mtk-cmdq-mailbox.c?????? | 90
> > +++++++++++++++++++++---
> > ? include/linux/mailbox/mtk-cmdq-mailbox.h |? 2 +
> > ? 2 files changed, 84 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > index d186865b8dce..0abe10a7fef9 100644
> > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > @@ -43,6 +43,17 @@
> > ? #define GCE_CTRL_BY_SW????????????????????????????? GENMASK(2, 0)
> > ? #define GCE_DDR_EN????????????????????????? GENMASK(18, 16)
> > 
> > +#define GCE_VM_ID_MAP0?????????????????????? 0x5018
> > +#define GCE_VM_MAP0_ALL_HOST???????????????? GENMASK(29, 0)
> > +#define GCE_VM_ID_MAP1?????????????????????? 0x501c
> > +#define GCE_VM_MAP1_ALL_HOST???????????????? GENMASK(29, 0)
> > +#define GCE_VM_ID_MAP2?????????????????????? 0x5020
> > +#define GCE_VM_MAP2_ALL_HOST???????????????? GENMASK(29, 0)
> > +#define GCE_VM_ID_MAP3?????????????????????? 0x5024
> > +#define GCE_VM_MAP3_ALL_HOST???????????????? GENMASK(5, 0)
> > +#define GCE_VM_CPR_GSIZE???????????? 0x50c4
> > +#define GCE_VM_CPR_GSIZE_HSOT??????????????????????? GENMASK(3, 0)
> 
> typo: GSIZE_HOST....
> 

Thanks, I'll fix it.

> ...but also, if you could add some brief description of what the
> VMIDs are used for
> and what the GSIZE is... that'd be very much appreciated from whoever
> is reading
> this.
> 
VMID_MAP configuration is in the previous reply mail for CK.
CPR_GSIZE is the setting for allocating the CPR SRAM size to each VM.

> The GCE stuff isn't even properly described in datasheets - I do
> (probably!)
> understand what those are for, but asking people to get years of
> experience on
> MediaTek to understand what's going on would be a bit rude, wouldn't
> it? :-D
> 

I agree with you :-)
I'll put them in the VM patch and add some brief description for them.

> > +
> > ? #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
> > ? #define CMDQ_THR_ENABLED??????????? 0x1
> > ? #define CMDQ_THR_DISABLED?????????? 0x0
> > @@ -87,11 +98,24 @@ struct cmdq {
> > ? struct gce_plat {
> > ????? u32 thread_nr;
> > ????? u8 shift;
> > +???? dma_addr_t mminfra_offset;
> 
> It looks like this is exactly the DRAM's iostart... at least, I can
> see that in the
> downstream devicetree that's where it starts.
> 
> ??????? memory: memory at 80000000 {
> ??????????????? device_type = "memory";
> ??????????????? reg = <0 0x80000000 0 0x40000000>;
> ??????? };
> 
> It doesn't really look like being a coincidence, but, for the sake of
> asking:
> is this just a coincidence? :-)
> 

As the confirmation with the hardware designer in previous reply mail
for CK:
https://patchwork.kernel.org/project/linux-mediatek/patch/20250218054405.2017918-4-jason-jh.lin at mediatek.com/#26258463

Since the MMINFRA remap subtracting 2G is done in the hardware circuit
and cannot be configured by software, the address +2G adjustment is
necessary to implement in the CMDQ driver.

So that might not be a coincidence.
But even if DRAM start address changes, this mminfra_offset is still
subtracting 2G, so I think it is a better choice to define it as the
driver data for MT8196.

> > ????? bool control_by_sw;
> > ????? bool sw_ddr_en;
> > +???? bool gce_vm;
> > +???? u32 dma_mask_bit;
> > ????? u32 gce_num;
> > ? };
> > 
> > +static inline u32 cmdq_reg_shift_addr(dma_addr_t addr, const
> > struct gce_plat *pdata)
> > +{
> > +???? return ((addr + pdata->mminfra_offset) >> pdata->shift);
> > +}
> > +
> > +static inline u32 cmdq_reg_revert_addr(dma_addr_t addr, const
> > struct gce_plat *pdata)
> > +{
> > +???? return ((addr << pdata->shift) - pdata->mminfra_offset);
> > +}
> 
> I'm not sure that you really need those two functions... probably
> it's simply
> cleaner and easier to just write that single line every time... and
> I'm
> saying that especially for how you're using those functions, with
> some readl()
> passed directly as param, decreasing human readability by "a whole
> lot" :-)
> 

The reason why I use API wrapper instead of writing it directly in
readl() is to avoid missing the shift or mminfra_offset conversion in
some places.
This problem is not easy to debug, and I have encountered it at least
twice...

I think the advantage of using function is that it can be uniformly
modified to all places that need to handle DRAM address conversion.
What do you think? :-)

> > +
> > ? static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> > ? {
> > ????? WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
> > @@ -112,6 +136,30 @@ u8 cmdq_get_shift_pa(struct mbox_chan *chan)
> > ? }
> > ? EXPORT_SYMBOL(cmdq_get_shift_pa);
> > 
> > +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan)
> > +{
> > +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > mbox);
> > +
> > +???? return cmdq->pdata->mminfra_offset;
> > +}
> > +EXPORT_SYMBOL(cmdq_get_offset_pa);
> 
> I think I remember this get_offset_pa from the old times, then CK
> removed it (and I
> was really happy about that disappearing), or am I confusing this
> with something
> else?
> 
> (of course, this wasn't used for mminfra, but for something else!)
> 

I can't find any remove history in mtk-cmdq-mailbox.c.

Maybe you mean the patch in this series?
https://lore.kernel.org/all/171213938049.123698.15573779837703602591.b4-ty at collabora.com/

> > +
> > +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t
> > addr)
> > +{
> > +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > mbox);
> > +
> > +???? if (cmdq->pdata->mminfra_offset == 0)
> > +???????????? return false;
> > +
> > +???? /*
> > +????? * mminfra will recognize the addr that greater than the
> > mminfra_offset
> > +????? * as a transaction to DRAM.
> > +????? * So the caller needs to append mminfra_offset for the true
> > case.
> > +????? */
> > +???? return (addr >= cmdq->pdata->mminfra_offset);
> 
> 
> /**
> ? * cmdq_is_mminfra_gce() - Brief description
> ? * @args.....
> ? *
> ? * The MMINFRA GCE will recognize an address greater than DRAM
> iostart as a
> ? * DRAM transaction instead of ....xyz
> ? *
> ? * In order for callers to perform (xyz) transactions through the
> CMDQ, those
> ? * need to know if they are using a GCE located in MMINFRA.
> ? */
> bool cmdq_is_mminfra_gce(...)
> {
> ??????? return cmdq->pdata->mminfra_offset &&
> ?????????????? (addr >= cmdq->pdata->mminfra_offset)
> 
> > +}
> > +EXPORT_SYMBOL(cmdq_addr_need_offset);
> > +
> 

OK, I'll modify the API like this.

> ...but then, is there really no way of just handling the GCE being in
> MMINFRA
> transparently from the callers? Do the callers really *need* to know
> that they're
> using a new GCE?!
> 

Since the address subtracting is done in MMINFRA hardware, I think GCE
users really need to handle it in driver.

> Another way of saying: can't we just handle the address translation
> in here instead
> of instructing each and every driver about how to communicate with
> the new GCE?!
> 

The DRAM address may not only be the command buffer to GCE, but also
the working buffer provided by CMDQ users and being a part of GCE
instruction, so we need to handle the address translation in CMDQ
helper driver for the instruction generation.
E.g. ISP drivers may use GCE to write a hardware settings to a DRAM as
backup buffer. The GCE write instruction will be:
WRITE the value of ISP register to DRAM address + mminfra_offset.

But most of the CMDQ users only need to use GCE to write hardware
register, so I only keep the translation in cmdq_pkt_mem_move(),
cmdq_pkt_poll_addr() and cmdq_pkt_jump_abs() at the latest series.

Regards,
Jason-JH lin

> 
> Cheers,
> Angelo


From yangyicong at huawei.com  Wed Mar  5 01:01:34 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Wed, 5 Mar 2025 17:01:34 +0800
Subject: [PATCH v11 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <153df413-9989-42fe-b574-598ff0fa9716@arm.com>
References: <20250218141018.18082-1-yangyicong@huawei.com>
 <20250218141018.18082-4-yangyicong@huawei.com> <Z8HAkZiHYRjj97M7@bogus>
 <336e9c4e-cd9c-4449-ba7b-60ee8774115d@arm.com>
 <20250228190641.q23vd53aaw42tcdi@bogus>
 <a52972c7-aadd-4a77-a292-057fa5f8372d@arm.com> <Z8WPiOweOjFZqTwN@bogus>
 <32e572d6-dedd-d8a3-13be-6de02303a64d@huawei.com>
 <2fdea4f6-db98-4dc7-947f-e19ee54d2c3c@arm.com> <Z8bPtsO7dEV0lq2M@bogus>
 <153df413-9989-42fe-b574-598ff0fa9716@arm.com>
Message-ID: <86e32fb3-0ff5-f4f0-3d44-222e63b5a69f@huawei.com>

On 2025/3/4 23:07, Pierre Gondois wrote:
> 
> 
> On 3/4/25 11:02, Sudeep Holla wrote:
>> On Tue, Mar 04, 2025 at 09:25:02AM +0100, Pierre Gondois wrote:
>>>
>>>
>>> On 3/3/25 15:40, Yicong Yang wrote:
>>>> On 2025/3/3 19:16, Sudeep Holla wrote:
>>>>> On Mon, Mar 03, 2025 at 10:56:12AM +0100, Pierre Gondois wrote:
>>>>>> On 2/28/25 20:06, Sudeep Holla wrote:
>>>>>>>>>
>>>>>>>>> Ditto as previous patch, can get rid if it is default 1.
>>>>>>>>>
>>>>>>>>
>>>>>>>> On non-SMT platforms, not calling cpu_smt_set_num_threads() leaves
>>>>>>>> cpu_smt_num_threads uninitialized to UINT_MAX:
>>>>>>>>
>>>>>>>> smt/active:0
>>>>>>>> smt/control:-1
>>>>>>>>
>>>>>>>> If cpu_smt_set_num_threads() is called:
>>>>>>>> active:0
>>>>>>>> control:notsupported
>>>>>>>>
>>>>>>>> So it might be slightly better to still initialize max_smt_thread_num.
>>>>>>>>
>>>>>>>
>>>>>>> Sure, what I meant is to have max_smt_thread_num set to 1 by default is
>>>>>>> that is what needed anyways and the above code does that now.
>>>>>>>
>>>>>>> Why not start with initialised to 1 instead ?
>>>>>>> Of course some current logic needs to change around testing it for zero.
>>>>>>>
>>>>>>
>>>>>> I think there would still be a way to check against the default value.
>>>>>> If we have:
>>>>>> unsigned int max_smt_thread_num = 1;
>>>>>>
>>>>>> then on a platform with 2 threads, the detection condition would trigger:
>>>>>> xa_for_each(&hetero_cpu, hetero_id, entry) {
>>>>>> ????? if (entry->thread_num != max_smt_thread_num && max_smt_thread_num)???? <---- (entry->thread_num=2) and (max_smt_thread_num=1)
>>>>>> ????????? pr_warn_once("Heterogeneous SMT topology is partly
>>>>>> ??????????????????????? supported by SMT control\n");
>>>>>>
>>>>>> so we would need an additional variable:
>>>>>> bool is_initialized = false;
>>>>>
>>>>> Sure, we could do that or skip the check if max_smt_thread_num == 1 ?
>>>>>
>>>>> I mean
>>>>> ????if (entry->thread_num != max_smt_thread_num && max_smt_thread_num != 1)
>>>>>
>>>
>>> I think it will be problematic if we parse:
>>> - first a CPU with 1 thread
>>> - then a CPU with 2 threads
>>>
>>> in that case we should detect the 'Heterogeneous SMT topology',
>>> but we cannot because we don't know whether max_smt_thread_num=1
>>> because 1 is the default value or we found a CPU with one thread.
>>
>> Right, but as per Dietmar's and my previous response, it may be a valid
>> case. See latest response from Dietmar which is explicitly requesting
>> support for this. It may need some special handling if we decide to support
>> that.
> 
> Ah ok, right indeed.
> For heterogeneous SMT platforms, the 'smt/control' file is able to accept
> on/off/forceoff strings. But providing the max #count of threads as an integer would
> be wrong if the CPU doesn't have this #count of threads.
> 
> Initially the idea was to just warn that support might be needed for heterogeneous
> SMT platforms, and let whoever would have such platform solve this case, but just
> disabling the integer interface in this case would solve the issue generically.
> 

ok so let's regard the asymmetric platform as a valid case as suggested (also mentioned
by Dietmar on another thread) and remove the check here. Will update and test.

Thanks.



From shameerali.kolothum.thodi at huawei.com  Wed Mar  5 01:01:40 2025
From: shameerali.kolothum.thodi at huawei.com (Shameerali Kolothum Thodi)
Date: Wed, 5 Mar 2025 09:01:40 +0000
Subject: [PATCH v1 4/4] iommu/arm-smmu-v3-iommufd: Allow a shared
 s2_parent to allocate vSMMU
In-Reply-To: <564eda8dee4bbf4c6e1d1dd9ed6bd40cc1a2df26.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <564eda8dee4bbf4c6e1d1dd9ed6bd40cc1a2df26.1741150594.git.nicolinc@nvidia.com>
Message-ID: <1b51a7f7bfc0419b8941cf7ee0601b70@huawei.com>



> -----Original Message-----
> From: Nicolin Chen <nicolinc at nvidia.com>
> Sent: Wednesday, March 5, 2025 5:04 AM
> To: will at kernel.org; robin.murphy at arm.com; jgg at nvidia.com
> Cc: joro at 8bytes.org; linux-arm-kernel at lists.infradead.org;
> iommu at lists.linux.dev; linux-kernel at vger.kernel.org; Shameerali Kolothum
> Thodi <shameerali.kolothum.thodi at huawei.com>
> Subject: [PATCH v1 4/4] iommu/arm-smmu-v3-iommufd: Allow a shared
> s2_parent to allocate vSMMU
> 
> Now, vmids are stored in vSMMU objects. So all vSMMUs assigned to the
> same
> VM can share a s2_parent domain. This means a vIOMMU allocation per
> device
> behind one SMMU can be given with a s2_parent domain that's allocated
> per
> another device behind another SMMU, i.e. s2_parent->smmu != master-
> >smmu.
> 
> Remove the validation line to allow this use case.
> 
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> index 2c5a9d0abed5..9bfa5fa5bafa 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> @@ -378,9 +378,6 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct
> device *dev,
>  	if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
>  		return ERR_PTR(-EOPNOTSUPP);
> 
> -	if (s2_parent->smmu != master->smmu)
> -		return ERR_PTR(-EINVAL);
> -

Not sure we can just relax this like this. What if the two physical SMMUs are different in
functionality/features? Do we need some kind of sanity check here?

Thanks,
Shameer



From w.egorov at phytec.de  Wed Mar  5 00:55:37 2025
From: w.egorov at phytec.de (Wadim Egorov)
Date: Wed, 5 Mar 2025 09:55:37 +0100
Subject: [PATCH v2 5/5] arm64: dts: ti: k3-am62a-phycore-som: Reorder properties per DTS coding style
In-Reply-To: <20250305085537.3976579-1-w.egorov@phytec.de>
References: <20250305085537.3976579-1-w.egorov@phytec.de>
Message-ID: <20250305085537.3976579-5-w.egorov@phytec.de>

Reorder properties to comply with the DeviceTree coding style guidelines:
https://docs.kernel.org/devicetree/bindings/dts-coding-style.html

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
v2: No changes
---
 arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
index 7920559e84a3..147d56b87984 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
@@ -171,7 +171,6 @@ AM62AX_IOPAD(0x1f4, PIN_INPUT, 0) /* (D16) EXTINTn */
 };
 
 &cpsw3g {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_rgmii1_pins_default>;
 	status = "okay";
@@ -225,8 +224,8 @@ pmic at 30 {
 		interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-controller;
 		#interrupt-cells = <1>;
-		ti,power-button;
 		system-power-controller;
+		ti,power-button;
 
 		regulators {
 			vdd_3v3: buck1 {
-- 
2.34.1



From w.egorov at phytec.de  Wed Mar  5 00:55:33 2025
From: w.egorov at phytec.de (Wadim Egorov)
Date: Wed, 5 Mar 2025 09:55:33 +0100
Subject: [PATCH v2 1/5] arm64: dts: ti: k3-am62x-phyboard-lyra: Add boot phase tags
Message-ID: <20250305085537.3976579-1-w.egorov@phytec.de>

The bootph-all and bootph-pre-ram tags were introduced in dt-schema
(dtschema/schemas/bootph.yaml) to define node usage across different
boot phases.

Add boot phase tags to all required nodes to ensure boot support from
all sources, including UART, USB (DFU), Ethernet, uSD card, eMMC, and
OSPI NOR Flash.

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2025-February/1006239.html
v2:
  - Add bootph-all to cpsw_port1 and main_pktma 
  - Remove bootph-all from cpsw3g
---
 arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi   | 15 +++++++++++++++
 .../arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi |  9 +++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
index 2ef4cbaec789..effab2f810c2 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
@@ -29,6 +29,7 @@ aliases {
 	memory at 80000000 {
 		device_type = "memory";
 		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+		bootph-all;
 	};
 
 	reserved_memory: reserved-memory {
@@ -131,6 +132,7 @@ main_i2c0_pins_default: main-i2c0-default-pins {
 			AM62X_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */
 			AM62X_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */
 		>;
+		bootph-all;
 	};
 
 	main_mdio1_pins_default: main-mdio1-default-pins {
@@ -138,6 +140,7 @@ main_mdio1_pins_default: main-mdio1-default-pins {
 			AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24) MDIO0_MDC */
 			AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22) MDIO0_MDIO */
 		>;
+		bootph-all;
 	};
 
 	main_mmc0_pins_default: main-mmc0-default-pins {
@@ -153,6 +156,7 @@ AM62X_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */
 			AM62X_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */
 			AM62X_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */
 		>;
+		bootph-all;
 	};
 
 	main_rgmii1_pins_default: main-rgmii1-default-pins {
@@ -170,6 +174,7 @@ AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */
 			AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */
 			AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */
 		>;
+		bootph-all;
 	};
 
 	ospi0_pins_default: ospi0-default-pins {
@@ -186,6 +191,7 @@ AM62X_IOPAD(0x024, PIN_INPUT, 0) /* (H25) OSPI0_D6 */
 			AM62X_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */
 			AM62X_IOPAD(0x008, PIN_INPUT, 0) /* (J24) OSPI0_DQS */
 		>;
+		bootph-all;
 	};
 
 	pmic_irq_pins_default: pmic-irq-default-pins {
@@ -210,6 +216,7 @@ &cpsw3g {
 &cpsw_port1 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&cpsw3g_phy1>;
+	bootph-all;
 };
 
 &cpsw3g_mdio {
@@ -220,6 +227,7 @@ &cpsw3g_mdio {
 	cpsw3g_phy1: ethernet-phy at 1 {
 		compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
 		reg = <1>;
+		bootph-all;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 	};
@@ -232,10 +240,15 @@ mbox_m4_0: mbox-m4-0 {
 	};
 };
 
+&main_pktdma {
+	bootph-all;
+};
+
 &main_i2c0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
+	bootph-all;
 	status = "okay";
 
 	pmic at 30 {
@@ -355,6 +368,7 @@ serial_flash: flash at 0 {
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <0>;
+		bootph-all;
 	};
 };
 
@@ -363,5 +377,6 @@ &sdhci0 {
 	pinctrl-0 = <&main_mmc0_pins_default>;
 	disable-wp;
 	non-removable;
+	bootph-all;
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
index 922cad14c9f8..aab74d6019b0 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
@@ -138,6 +138,7 @@ vcc_3v3_mmc: regulator-vcc-3v3-mmc {
 		regulator-max-microvolt = <3300000>;
 		regulator-always-on;
 		regulator-boot-on;
+		bootph-all;
 	};
 
 	vcc_3v3_sw: regulator-vcc-3v3-sw {
@@ -233,6 +234,7 @@ AM62X_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (C21) MMC1_DAT2 */
 			AM62X_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (D22) MMC1_DAT3 */
 			AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */
 		>;
+		bootph-all;
 	};
 
 	main_rgmii2_pins_default: main-rgmii2-default-pins {
@@ -257,6 +259,7 @@ main_uart0_pins_default: main-uart0-default-pins {
 			AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
 			AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
 		>;
+		bootph-all;
 	};
 
 	main_uart1_pins_default: main-uart1-default-pins {
@@ -266,6 +269,7 @@ AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */
 			AM62X_IOPAD(0x1ac, PIN_INPUT, 2) /* (E19) MCASP0_AFSR.UART1_RXD */
 			AM62X_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */
 		>;
+		bootph-pre-ram;
 	};
 
 	main_usb1_pins_default: main-usb1-default-pins {
@@ -430,12 +434,14 @@ &main_mcan0 {
 &main_uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
+	bootph-all;
 	status = "okay";
 };
 
 &main_uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart1_pins_default>;
+	bootph-pre-ram;
 	/* Main UART1 may be used by TIFS firmware */
 	status = "okay";
 };
@@ -467,11 +473,13 @@ &sdhci1 {
 	pinctrl-0 = <&main_mmc1_pins_default>;
 	disable-wp;
 	no-1-8-v;
+	bootph-all;
 	status = "okay";
 };
 
 &usbss0 {
 	ti,vbus-divider;
+	bootph-all;
 	status = "okay";
 };
 
@@ -482,6 +490,7 @@ &usbss1 {
 
 &usb0 {
 	usb-role-switch;
+	bootph-all;
 
 	port {
 		typec_hs: endpoint {
-- 
2.34.1



From w.egorov at phytec.de  Wed Mar  5 00:55:35 2025
From: w.egorov at phytec.de (Wadim Egorov)
Date: Wed, 5 Mar 2025 09:55:35 +0100
Subject: [PATCH v2 3/5] arm64: dts: ti: k3-am642-phyboard-electra: Add boot phase tags
In-Reply-To: <20250305085537.3976579-1-w.egorov@phytec.de>
References: <20250305085537.3976579-1-w.egorov@phytec.de>
Message-ID: <20250305085537.3976579-3-w.egorov@phytec.de>

The bootph-all and bootph-pre-ram tags were introduced in dt-schema
(dtschema/schemas/bootph.yaml) to define node usage across different
boot phases.

Add boot phase tags to all required nodes to ensure boot support from
all sources, including UART, Ethernet, uSD card, eMMC, and OSPI NOR Flash.

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2025-February/1006243.html
v2:
  - Add bootph-all to main_pktdma
  - Drop bootph-all from cpsw3g
---
 arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi   | 15 +++++++++++++++
 .../boot/dts/ti/k3-am642-phyboard-electra-rdk.dts |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
index 99a6fdfaa7fb..74423ca3204f 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
@@ -27,6 +27,7 @@ aliases {
 	memory at 80000000 {
 		device_type = "memory";
 		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+		bootph-all;
 	};
 
 	reserved_memory: reserved-memory {
@@ -132,6 +133,7 @@ AM64X_IOPAD(0x01f8, PIN_INPUT, 4)	/* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */
 			AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4)	/* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */
 			AM64X_IOPAD(0x0100, PIN_OUTPUT, 7)	/* (V7) PRG1_PRU0_GPO18.GPIO0_63 */
 		>;
+		bootph-all;
 	};
 
 	cpsw_rgmii1_pins_default: cpsw-rgmii1-default-pins {
@@ -150,6 +152,7 @@ AM64X_IOPAD(0x01f4, PIN_INPUT, 4)	/* (V5) PRG0_PRU1_GPO17.RGMII1_RD3 */
 			AM64X_IOPAD(0x014c, PIN_OUTPUT, 4)	/* (AA14) PRG1_PRU1_GPO17.RGMII1_TD3 */
 			AM64X_IOPAD(0x0154, PIN_INPUT, 7)	/* (V12) PRG1_PRU1_GPO19.GPIO0_84 */
 		>;
+		bootph-all;
 	};
 
 	eeprom_wp_pins_default: eeprom-wp-default-pins {
@@ -169,6 +172,7 @@ main_i2c0_pins_default: main-i2c0-default-pins {
 			AM64X_IOPAD(0x0260, PIN_INPUT, 0)	/* (A18) I2C0_SCL */
 			AM64X_IOPAD(0x0264, PIN_INPUT, 0)	/* (B18) I2C0_SDA */
 		>;
+		bootph-all;
 	};
 
 	ospi0_pins_default: ospi0-default-pins {
@@ -185,6 +189,7 @@ AM64X_IOPAD(0x0024, PIN_INPUT, 0)	/* (N18) OSPI0_D6 */
 			AM64X_IOPAD(0x0028, PIN_INPUT, 0)	/* (M17) OSPI0_D7 */
 			AM64X_IOPAD(0x002c, PIN_OUTPUT, 0)	/* (L19) OSPI0_CSn0 */
 		>;
+		bootph-all;
 	};
 
 	rtc_pins_default: rtc-defaults-pins {
@@ -204,6 +209,7 @@ &cpsw3g_mdio {
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&cpsw_mdio_pins_default>;
+	bootph-all;
 
 	cpsw3g_phy1: ethernet-phy at 1 {
 		compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
@@ -215,12 +221,14 @@ cpsw3g_phy1: ethernet-phy at 1 {
 		reset-gpios = <&main_gpio0 63 GPIO_ACTIVE_LOW>;
 		reset-assert-us = <1000>;
 		reset-deassert-us = <1000>;
+		bootph-all;
 	};
 };
 
 &cpsw_port1 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&cpsw3g_phy1>;
+	bootph-all;
 	status = "okay";
 };
 
@@ -266,6 +274,7 @@ &main_i2c0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
+	bootph-all;
 
 	eeprom at 50 {
 		compatible = "atmel,24c32";
@@ -330,6 +339,10 @@ vdda_1v8: ldo1 {
 	};
 };
 
+&main_pktdma {
+	bootph-all;
+};
+
 &main_r5fss0_core0 {
 	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>;
 	memory-region = <&main_r5fss0_core0_dma_memory_region>,
@@ -377,6 +390,7 @@ serial_flash: flash at 0 {
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <0>;
+		bootph-all;
 	};
 };
 
@@ -386,6 +400,7 @@ &sdhci0 {
 	ti,driver-strength-ohm = <50>;
 	disable-wp;
 	keep-power-in-suspend;
+	bootph-all;
 };
 
 &tscadc0 {
diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
index bc8e1ce11047..6fbd8d932396 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
@@ -171,6 +171,7 @@ vcc_3v3_mmc: regulator-sd {
 		regulator-max-microvolt = <3300000>;
 		regulator-boot-on;
 		regulator-always-on;
+		bootph-all;
 	};
 };
 
@@ -275,6 +276,7 @@ AM64X_IOPAD(0x0290, PIN_INPUT, 0)		/* MMC1_CLKLB */
 			AM64X_IOPAD(0x0294, PIN_INPUT_PULLUP, 0)	/* (J19) MMC1_CMD */
 			AM64X_IOPAD(0x0298, PIN_INPUT_PULLUP, 0)	/* (D19) MMC1_SDCD */
 		>;
+		bootph-all;
 	};
 
 	main_spi0_pins_default: main-spi0-default-pins {
@@ -291,6 +293,7 @@ main_uart0_pins_default: main-uart0-default-pins {
 			AM64X_IOPAD(0x0230, PIN_INPUT, 0)	/* (D15) UART0_RXD */
 			AM64X_IOPAD(0x0234, PIN_OUTPUT, 0)	/* (C16) UART0_TXD */
 		>;
+		bootph-all;
 	};
 
 	main_uart1_pins_default: main-uart1-default-pins {
@@ -413,6 +416,7 @@ &main_uart0 {
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
+	bootph-all;
 };
 
 &main_uart1 {
@@ -429,6 +433,7 @@ &sdhci1 {
 	pinctrl-0 = <&main_mmc1_pins_default>;
 	disable-wp;
 	no-1-8-v;
+	bootph-all;
 };
 
 &serdes0 {
-- 
2.34.1



From w.egorov at phytec.de  Wed Mar  5 00:55:34 2025
From: w.egorov at phytec.de (Wadim Egorov)
Date: Wed, 5 Mar 2025 09:55:34 +0100
Subject: [PATCH v2 2/5] arm64: dts: ti: k3-am62a-phycore-som: Add boot phase tags
In-Reply-To: <20250305085537.3976579-1-w.egorov@phytec.de>
References: <20250305085537.3976579-1-w.egorov@phytec.de>
Message-ID: <20250305085537.3976579-2-w.egorov@phytec.de>

The bootph-all and bootph-pre-ram tags were introduced in dt-schema
(dtschema/schemas/bootph.yaml) to define node usage across different
boot phases.

Add boot phase tags to all required nodes to ensure boot support from
all sources, including UART, USB (DFU), Ethernet, uSD card, eMMC, and
OSPI NOR Flash.

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2025-February/1006241.html
v2:
  - Add bootph-all to cpsw_port1 & main_pktdma
  - Drop bootph-all from cpsw3g
---
 arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
index a5aceaa39670..7920559e84a3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
@@ -42,6 +42,7 @@ memory at 80000000 {
 		device_type = "memory";
 		/* 2G RAM */
 		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+		bootph-all;
 	};
 
 	reserved-memory {
@@ -99,6 +100,7 @@ main_i2c0_pins_default: main-i2c0-default-pins {
 			AM62AX_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (D17) I2C0_SCL */
 			AM62AX_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (E16) I2C0_SDA */
 		>;
+		bootph-all;
 	};
 
 	main_mdio1_pins_default: main-mdio1-default-pins {
@@ -106,6 +108,7 @@ main_mdio1_pins_default: main-mdio1-default-pins {
 			AM62AX_IOPAD(0x160, PIN_OUTPUT, 0) /* (V12) MDIO0_MDC */
 			AM62AX_IOPAD(0x15c, PIN_INPUT, 0) /* (V13) MDIO0_MDIO */
 		>;
+		bootph-all;
 	};
 
 	main_mmc0_pins_default: main-mmc0-default-pins {
@@ -121,6 +124,7 @@ AM62AX_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (W7) MMC0_DAT5 */
 			AM62AX_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (W9) MMC0_DAT6 */
 			AM62AX_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AB8) MMC0_DAT7 */
 		>;
+		bootph-all;
 	};
 
 	main_rgmii1_pins_default: main-rgmii1-default-pins {
@@ -138,6 +142,7 @@ AM62AX_IOPAD(0x140, PIN_OUTPUT, 0) /* (AA17) RGMII1_TD3 */
 			AM62AX_IOPAD(0x130, PIN_OUTPUT, 0) /* (AB17) RGMII1_TXC */
 			AM62AX_IOPAD(0x12c, PIN_OUTPUT, 0) /* (W16) RGMII1_TX_CTL */
 		>;
+		bootph-all;
 	};
 
 	ospi0_pins_default: ospi0-default-pins {
@@ -155,6 +160,7 @@ AM62AX_IOPAD(0x024, PIN_INPUT, 0) /* (J20) OSPI0_D6 */
 			AM62AX_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */
 			AM62AX_IOPAD(0x008, PIN_INPUT, 0) /* (L21) OSPI0_DQS */
 		>;
+		bootph-all;
 	};
 
 	pmic_irq_pins_default: pmic-irq-default-pins {
@@ -168,11 +174,13 @@ &cpsw3g {
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_rgmii1_pins_default>;
+	status = "okay";
 };
 
 &cpsw_port1 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&cpsw3g_phy1>;
+	bootph-all;
 };
 
 &cpsw3g_mdio {
@@ -182,6 +190,7 @@ &cpsw3g_mdio {
 	cpsw3g_phy1: ethernet-phy at 1 {
 		compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
 		reg = <1>;
+		bootph-all;
 		ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
@@ -196,6 +205,7 @@ &main_i2c0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
+	bootph-all;
 	status = "okay";
 
 	pmic at 30 {
@@ -302,6 +312,10 @@ &main_gpio_intr {
 	status = "okay";
 };
 
+&main_pktdma {
+	bootph-all;
+};
+
 &ospi0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ospi0_pins_default>;
@@ -318,6 +332,7 @@ serial_flash: flash at 0 {
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <0>;
+		bootph-all;
 	};
 };
 
@@ -326,5 +341,6 @@ &sdhci0 {
 	pinctrl-0 = <&main_mmc0_pins_default>;
 	disable-wp;
 	non-removable;
+	bootph-all;
 	status = "okay";
 };
-- 
2.34.1



From w.egorov at phytec.de  Wed Mar  5 00:55:36 2025
From: w.egorov at phytec.de (Wadim Egorov)
Date: Wed, 5 Mar 2025 09:55:36 +0100
Subject: [PATCH v2 4/5] arm64: dts: ti: k3-am642-phyboard-electra: Reorder properties per DTS coding style
In-Reply-To: <20250305085537.3976579-1-w.egorov@phytec.de>
References: <20250305085537.3976579-1-w.egorov@phytec.de>
Message-ID: <20250305085537.3976579-4-w.egorov@phytec.de>

Reorder properties to comply with the DeviceTree coding style guidelines:
https://docs.kernel.org/devicetree/bindings/dts-coding-style.html

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
v2: No changes
---
 arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi    | 12 ++++++------
 .../boot/dts/ti/k3-am642-phyboard-electra-rdk.dts  | 14 +++++++-------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
index 74423ca3204f..5d7da292eeb9 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
@@ -206,22 +206,22 @@ &cpsw3g {
 };
 
 &cpsw3g_mdio {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&cpsw_mdio_pins_default>;
 	bootph-all;
+	status = "okay";
 
 	cpsw3g_phy1: ethernet-phy at 1 {
 		compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
 		reg = <1>;
 		interrupt-parent = <&main_gpio0>;
 		interrupts = <84 IRQ_TYPE_EDGE_FALLING>;
-		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 		reset-gpios = <&main_gpio0 63 GPIO_ACTIVE_LOW>;
 		reset-assert-us = <1000>;
 		reset-deassert-us = <1000>;
 		bootph-all;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
 	};
 };
 
@@ -270,11 +270,11 @@ mbox_m4_0: mbox-m4-0 {
 };
 
 &main_i2c0 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
 	bootph-all;
+	status = "okay";
 
 	eeprom at 50 {
 		compatible = "atmel,24c32";
@@ -375,9 +375,9 @@ &mcu_m4fss {
 };
 
 &ospi0 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&ospi0_pins_default>;
+	status = "okay";
 
 	serial_flash: flash at 0 {
 		compatible = "jedec,spi-nor";
@@ -395,12 +395,12 @@ serial_flash: flash at 0 {
 };
 
 &sdhci0 {
-	status = "okay";
 	non-removable;
 	ti,driver-strength-ohm = <50>;
 	disable-wp;
 	keep-power-in-suspend;
 	bootph-all;
+	status = "okay";
 };
 
 &tscadc0 {
diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
index 6fbd8d932396..f63c101b7d61 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
@@ -352,10 +352,10 @@ &i2c_som_rtc {
 };
 
 &main_i2c1 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
+	status = "okay";
 
 	eeprom at 51 {
 		compatible = "atmel,24c02";
@@ -385,25 +385,25 @@ led-5 {
 };
 
 &main_mcan0 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan0_pins_default>;
 	phys = <&can_tc1>;
+	status = "okay";
 };
 
 &main_mcan1 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan1_pins_default>;
 	phys = <&can_tc2>;
+	status = "okay";
 };
 
 &main_spi0 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_spi0_pins_default>;
 	cs-gpios = <0>, <&main_gpio1 43 GPIO_ACTIVE_LOW>;
 	ti,pindir-d0-out-d1-in;
+	status = "okay";
 
 	tpm at 1 {
 		compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
@@ -413,27 +413,27 @@ tpm at 1 {
 };
 
 &main_uart0 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 	bootph-all;
+	status = "okay";
 };
 
 &main_uart1 {
-	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart1_pins_default>;
 	uart-has-rtscts;
+	status = "okay";
 };
 
 &sdhci1 {
-	status = "okay";
 	vmmc-supply = <&vcc_3v3_mmc>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mmc1_pins_default>;
 	disable-wp;
 	no-1-8-v;
 	bootph-all;
+	status = "okay";
 };
 
 &serdes0 {
-- 
2.34.1



From alexander.stein at ew.tq-group.com  Wed Mar  5 00:56:55 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Wed, 05 Mar 2025 09:56:55 +0100
Subject: [PATCH v3 3/6] pmdomain: imx93-blk-ctrl: Scan subnodes and bind drivers
 to them
In-Reply-To: <20250305-keen-shaggy-bullfinch-fc77fd@krzk-bin>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-4-alexander.stein@ew.tq-group.com>
 <20250305-keen-shaggy-bullfinch-fc77fd@krzk-bin>
Message-ID: <23858231.6Emhk5qWAg@steina-w>

Hi Krzysztof,

Am Mittwoch, 5. M?rz 2025, 08:17:23 CET schrieb Krzysztof Kozlowski:
> On Tue, Mar 04, 2025 at 04:49:22PM +0100, Alexander Stein wrote:
> > +#include <linux/of_platform.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_runtime.h>
> > @@ -297,8 +298,14 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
> >  
> >  	dev_set_drvdata(dev, bc);
> >  
> > +	ret = devm_of_platform_populate(dev);
> 
> This means in remove() you will depopulate in different order than error
> path (e.g. after genpd removal). This is rather unexpected - remove()
> should be cleaning up in exactly reversed order of probe. Not sure if it
> can lead to any issues, but usual recommendation is that you either use
> devm() or not.

Thanks for pointing out. I will add a devm_of_platform_depopulate() to
remove().

Best regards
Alexander
-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From alexander.stein at ew.tq-group.com  Wed Mar  5 01:02:16 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Wed, 05 Mar 2025 10:02:16 +0100
Subject: [PATCH v3 2/6] dt-bindings: soc: imx93-media-blk-ctrl: Add LDB subnode
 into schema and example
In-Reply-To: <20250305-dandelion-axolotl-of-excitement-05fa70@krzk-bin>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
 <20250305-dandelion-axolotl-of-excitement-05fa70@krzk-bin>
Message-ID: <4414669.ejJDZkT8p0@steina-w>

Hi,

Am Mittwoch, 5. M?rz 2025, 08:13:04 CET schrieb Krzysztof Kozlowski:
> On Tue, Mar 04, 2025 at 04:49:21PM +0100, Alexander Stein wrote:
> > Document the LDB bridge subnode and add the subnode into the example.
> > For the subnode to work, the block control must scan its subnodes and
> 
> Don't describe drivers, but describe the hardware.

Thanks, I'll rephrase to describe the hardware better regarding LVDS.

> 
> > bind drivers to them, do not misuse either simple-bus or simple-mfd
> > here.
> 
> I don't understand that simple-bus or simple-mfd statement. There are no
> such compatibles here.

Same as above, the wording stems from 1cb0c87d27dcc ("dt-bindings: soc:
imx8mp-media-blk-ctrl: Add LDB subnode into schema and example").
I'll drop it to avoid confusion.

> 
> > 
> > Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> > ---
> >  .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 +++++++++++++++++++
> >  1 file changed, 51 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> > index b3554e7f9e76d..cd785111928bf 100644
> > --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> > +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
> > @@ -24,6 +24,14 @@ properties:
> >    reg:
> >      maxItems: 1
> >  
> > +  ranges: true
> > +
> > +  '#address-cells':
> > +    const: 1
> > +
> > +  '#size-cells':
> > +    const: 1
> > +
> >    '#power-domain-cells':
> >      const: 1
> >  
> > @@ -46,9 +54,20 @@ properties:
> >        - const: csi
> >        - const: dsi
> >  
> > +  bridge at 20:
> 
> @20 looks wrong. Use 'ranges;' and try again your DTS...
> 
> Binding is supposed to be complete. We have several examples when people
> added children one-by-one, everytime with different reasoning about
> child addressing.
> 
> So please confirm: this is complete and no other children will ever be
> added here... or you are 100% sure that all future children will be
> unit-addressable (will have unit address and appropriate properties).

This block control is a collection of registers for different purposes:
* MIPI-DSI
* MIPI-CSI
* Parallel camera
* LVDS
* CAMERA_MUX

At lease for parallel camera, another subnode is expected ([1]).

[1] https://lore.kernel.org/all/20240819024001.850065-1-victor.liu at nxp.com/

> BTW, I don't quite get why this is both syscon and has translation for
> child addresses. Does it mean your child does not use the same MMIO as
> parent, thus leading to unsynchronized reg access?

I'm not sure what the best practices are. This LDB has two registers
inside this block. So it seems reasonable to me to indicate this using
a reg property. On the other hand, access is solely done by accessing
via syscon, so unsynchronized reg access is not an issue.

What I am getting from your comments this node should not have 'reg'
property, as it uses syscon anyway.

> > +    type: object
> > +    additionalProperties: true
> > +    properties:
> > +      compatible:
> > +        contains:
> > +          const: fsl,imx93-ldb
> > +
> >  required:
> >    - compatible
> >    - reg
> > +  - ranges
> > +  - '#address-cells'
> > +  - '#size-cells'
> >    - power-domains
> >    - clocks
> >    - clock-names
> > @@ -77,4 +96,36 @@ examples:
> >                 clock-names = "apb", "axi", "nic", "disp", "cam",
> >                               "pxp", "lcdif", "isi", "csi", "dsi";
> >        #power-domain-cells = <1>;
> > +      #address-cells = <1>;
> > +      #size-cells = <1>;
> > +      ranges = <0x0 0x4ac10000 0x10000>;
> > +
> > +      bridge at 20 {
> > +          compatible = "fsl,imx93-ldb";
> > +          reg = <0x20 0x4>, <0x24 0x4>;
> > +          reg-names = "ldb", "lvds";
> > +          clocks = <&clk IMX93_CLK_LVDS_GATE>;
> > +          clock-names = "ldb";
> > +
> > +          ports {
> > +              #address-cells = <1>;
> > +              #size-cells = <0>;
> > +
> > +              port at 0 {
> > +                  reg = <0>;
> > +
> > +                  ldb_from_lcdif2: endpoint {
> > +                      remote-endpoint = <&lcdif2_to_ldb>;
> > +                  };
> > +              };
> > +
> > +              port at 1 {
> > +                  reg = <1>;
> > +
> > +                  ldb_lvds: endpoint {
> > +                      remote-endpoint = <&ldb_to_panel>;
> > +                  };
> > +              };
> > +          };
> 
> Messed indentation.

This is already from the original binding. I'll fix in a separate commit.

Best regards,
Alexander

> 
> > +        };
> 
> Best regards,
> Krzysztof
> 
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From m-malladi at ti.com  Wed Mar  5 01:23:07 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Wed, 5 Mar 2025 14:53:07 +0530
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth: Add
 XDP support
In-Reply-To: <61117a07-35b5-48c0-93d9-f97db8e15503@stanley.mountain>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
 <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
 <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>
 <40ce8ed3-b36c-4d5f-b75a-7e0409beb713@ti.com>
 <61117a07-35b5-48c0-93d9-f97db8e15503@stanley.mountain>
Message-ID: <fd989751-e7f6-40bb-a0bf-058c752cc7bc@ti.com>

Hi Dan,

On 3/3/2025 7:38 PM, Dan Carpenter wrote:
> What I mean is just compile the .o file with and without the unlikely(). 
> $ md5sum drivers/net/ethernet/ti/icssg/icssg_common.?o* 
> 2de875935222b9ecd8483e61848c4fc9 drivers/net/ethernet/ti/icssg/ 
> icssg_common.?o.?annotation 2de875935222b9ecd8483e61848c4fc9
> ZjQcmQRYFpfptBannerStart
> This message was sent from outside of Texas Instruments.
> Do not click links or open attachments unless you recognize the source 
> of this email and know the content is safe.
> Report?Suspicious
> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK! 
> uldq3TevVoc7KuXEXHnDf- 
> TXtuZ0bON9iO0jTE7PyIS1jjfs_CzpvIiMi93PVt0MVDzjHGQSK__vY_-6rO7q86rFmBMGW4SSqK5pvNE$>
> ZjQcmQRYFpfptBannerEnd
> 
> What I mean is just compile the .o file with and without the unlikely().
> 
> $ md5sum drivers/net/ethernet/ti/icssg/icssg_common.o*
> 2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.annotation
> 2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.no_anotation
> 
> Generally the rule is that you should leave likely/unlikely() annotations
> out unless it's going to make a difference on a benchmark.  I'm not going
> to jump down people's throat about this, and if you want to leave it,
> it's fine.  But it just struct me as weird so that's why I commented on
> it.
> 

I have done some performance tests to see if unlikely() is gonna make 
any impact and I see around ~9000 pps and 6Mbps drop without unlikely() 
for small packet sizes (60 Bytes)

You can see summary of the tests here:

packet size   with unlikely(pps)  without unlikely(pps)   regression

       60        462377                453251                 9126

       80        403020                399372                 3648

       96        402059                396881                 5178

      120        392725                391312                 4413

      140        327706                327099                 607

packet size  with unlikely(Mbps)  without unlikely(Mbps)  regression

      60         311                   305                    6

      80         335                   332                    3

      96         386                   381                    5

      120        456                   451                    5

      140        430                   429                    1

For more details on the logs, please 
refer:https://gist.github.com/MeghanaMalladiTI/cc6cc7709791376cb486eb1222de67be

Regards,
Meghana Malladi

> regards,
> dan carpenter
> 
> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
> index 34d16e00c2ec..3db5bae44e61 100644
> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
> @@ -672,7 +672,7 @@ static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
>   	case XDP_TX:
>   		/* Send packet to TX ring for immediate transmission */
>   		xdpf = xdp_convert_buff_to_frame(xdp);
> -		if (unlikely(!xdpf))
> +		if (!xdpf)
>   			goto drop;
>   
>   		q_idx = smp_processor_id() % emac->tx_ch_num;
> 



From dan.carpenter at linaro.org  Wed Mar  5 01:31:24 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Wed, 5 Mar 2025 12:31:24 +0300
Subject: [EXTERNAL] Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth:
 Add XDP support
In-Reply-To: <fd989751-e7f6-40bb-a0bf-058c752cc7bc@ti.com>
References: <20250224110102.1528552-1-m-malladi@ti.com>
 <20250224110102.1528552-4-m-malladi@ti.com>
 <d362a527-88cf-4cd5-a22f-7eeb938d4469@stanley.mountain>
 <21f21dfb-264b-4e01-9cb3-8d0133b5b31b@ti.com>
 <2c0c1a4f-95d4-40c9-9ede-6f92b173f05d@stanley.mountain>
 <40ce8ed3-b36c-4d5f-b75a-7e0409beb713@ti.com>
 <61117a07-35b5-48c0-93d9-f97db8e15503@stanley.mountain>
 <fd989751-e7f6-40bb-a0bf-058c752cc7bc@ti.com>
Message-ID: <5f716740-ac45-4881-a27d-91a93de6f8c7@stanley.mountain>

On Wed, Mar 05, 2025 at 02:53:07PM +0530, Malladi, Meghana wrote:
> Hi Dan,
> 
> On 3/3/2025 7:38 PM, Dan Carpenter wrote:
> > What I mean is just compile the .o file with and without the unlikely().
> > $ md5sum drivers/net/ethernet/ti/icssg/icssg_common.?o*
> > 2de875935222b9ecd8483e61848c4fc9 drivers/net/ethernet/ti/icssg/
> > icssg_common.?o.?annotation 2de875935222b9ecd8483e61848c4fc9
> > ZjQcmQRYFpfptBannerStart
> > This message was sent from outside of Texas Instruments.
> > Do not click links or open attachments unless you recognize the source
> > of this email and know the content is safe.
> > Report?Suspicious
> > <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK!
> > uldq3TevVoc7KuXEXHnDf- TXtuZ0bON9iO0jTE7PyIS1jjfs_CzpvIiMi93PVt0MVDzjHGQSK__vY_-6rO7q86rFmBMGW4SSqK5pvNE$>
> > ZjQcmQRYFpfptBannerEnd
> > 
> > What I mean is just compile the .o file with and without the unlikely().
> > 
> > $ md5sum drivers/net/ethernet/ti/icssg/icssg_common.o*
> > 2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.annotation
> > 2de875935222b9ecd8483e61848c4fc9  drivers/net/ethernet/ti/icssg/icssg_common.o.no_anotation
> > 
> > Generally the rule is that you should leave likely/unlikely() annotations
> > out unless it's going to make a difference on a benchmark.  I'm not going
> > to jump down people's throat about this, and if you want to leave it,
> > it's fine.  But it just struct me as weird so that's why I commented on
> > it.
> > 
> 
> I have done some performance tests to see if unlikely() is gonna make any
> impact and I see around ~9000 pps and 6Mbps drop without unlikely() for
> small packet sizes (60 Bytes)
> 
> You can see summary of the tests here:
> 
> packet size   with unlikely(pps)  without unlikely(pps)   regression
> 
>       60        462377                453251                 9126
> 
>       80        403020                399372                 3648
> 
>       96        402059                396881                 5178
> 
>      120        392725                391312                 4413
> 
>      140        327706                327099                 607
> 
> packet size  with unlikely(Mbps)  without unlikely(Mbps)  regression
> 
>      60         311                   305                    6
> 
>      80         335                   332                    3
> 
>      96         386                   381                    5
> 
>      120        456                   451                    5
> 
>      140        430                   429                    1
> 
> For more details on the logs, please refer:https://gist.github.com/MeghanaMalladiTI/cc6cc7709791376cb486eb1222de67be
> 

Huh.  That's very interesting.  Fine, then.

regards,
dan carpenter



From ryan_chen at aspeedtech.com  Wed Mar  5 01:35:51 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Wed, 5 Mar 2025 09:35:51 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
Message-ID: <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 27/02/2025 09:19, Ryan Chen wrote:
> >>
> >>
> >>> aspeed,enable-byte:
> >>> Force i2c controller use byte mode transfer. the byte mode transfer
> >>> will send i2c data each byte by byte, inlcude address read/write.
> >>
> >> Isn't this standard FIFO mode?
> > Yes, it is.
> >>
> >> Why anyone would need to enable byte mode for given board?
> > By default, it is buffer-mode, for performance, I don't want user enable
> byte-mode, it will increase CPU utilize.
> > But someone want to be force enable byte-mode, so I add properties.
> > https://patchwork.ozlabs.org/project/linux-aspeed/patch/20241007035235
> > .2254138-3-ryan_chen at aspeedtech.com/
> 
> 
> I don't see the reason why this would be a board property.
> 
> I understood need for DMA because it is shared and only some of the
> controllers can use it. But why choice between buffer and FIFO depending on
> hardware?

By default, the I2C controller runs in buffer mode. Each i2c bus have 16bytes buffer to transmit data.
Enabling byte mode will increases CPU utilization, so it is not recommended. 
However, some user might require forcing byte mode, so I added this property to allow that.

> 
> 
> >>
> >>>
> >>>>
> >>>>> +      may require a DTS to manually allocate which controller can
> >>>>> + use
> >>>> DMA mode.
> >>>>> +      The "aspeed,enable-dma" property allows control of this.
> >>>>> +
> >>>>> +      In cases where one the hardware design results in a specific
> >>>>> +      controller handling a larger amount of data, a DTS would likely
> >>>>> +      enable DMA mode for that one controller.
> >>>>> +
> >>>>> +  aspeed,enable-byte:
> >>>>> +    type: boolean
> >>>>> +    description: |
> >>>>> +      I2C bus enable byte mode transfer.
> >>>>
> >>>> No, either this is expressed as lack of dma mode property or if you
> >>>> have three modes, then rather some enum (aspeed,transfer-mode ?)
> >>>
> >>> Thanks suggestion, I will using an enum property like
> >>> aspeed,transfer-mode
> >> instead.
> >>>>
> >>>>
> >>>>
> >>>>> +
> >>>>> +  aspeed,global-regs:
> >>>>> +    $ref: /schemas/types.yaml#/definitions/phandle
> >>>>> +    description: The phandle of i2c global register node.
> >>>>
> >>>> For what? Same question as usual: do not repeat property name, but
> >>>> say what is this used for and what exactly it points to.
> >>>>
> >>>> s/i2c/I2C/ but then what is "I2C global register node"? This is how
> >>>> you call your device in datasheet?
> >>>>
> >>> I do descript in cover, should add into the yaml file ?
> >>
> >>
> >> Again, cover letter does not matter. Your hardware must be explained here.
> > Will add into commit.
> >>
> >>>
> >>> aspeed,global-regs:
> >>> This global register is needed, global register is setting for new
> >>> clock divide control, and new register set control.
> >>
> >> So this means you implement clock controller via syscon?
> > No, it is just mode switch. It also explain in cover. I will add it in commit.
> > The legacy register layout is mix controller/target register control together.
> The following is add more detail description about new register layout. And
> new feature set add for register.
> >>
> >>>
> >>>>
> >>>>> +
> >>>>>  required:
> >>>>>    - reg
> >>>>>    - compatible
> >>>>>    - clocks
> >>>>>    - resets
> >>>>>
> >>>>> +allOf:
> >>>>> +  - $ref: /schemas/i2c/i2c-controller.yaml#
> >>>>> +  - if:
> >>>>> +      properties:
> >>>>> +        compatible:
> >>>>> +          contains:
> >>>>> +            const: aspeed,ast2600-i2cv2
> >>>>
> >>>> NAK, undocumented compatible.
> >>>
> >>> Sorry, I should add what kind of document about this compatible?
> >>
> >> You cannot add new compatibles without documenting them.
> >> Documentation is in the form of DT schema and each compatible must be
> >> listed (in some
> >> way) in compatible property description.
> >
> > Sorry, do you mean, I add following in yaml or commit message?
> 
> You need to list this in compatibles first.

I will add it in compatible in next submit.

	enum:
		-aspeed,ast2600-i2cv2
> 
> >
> > This series add AST2600 i2cv2 new register set driver. The i2cv2 driver is new
> register set that have new clock divider option for more flexiable generation.
> And also have separate i2c controller and target register set for control, patch
> #2 is i2c controller driver only, patch #3 is add i2c target mode driver.
> 
> All this describes driver, not hardware.

Sorry, the cover letter description the register. I will add int in commit message.

-Add new clock divider option for more flexible and accurate clock rate
generation -Add tCKHighMin timing to guarantee SCL high pulse width.
-Add support dual pool buffer mode, split 32 bytes pool buffer of each
device into 2 x 16 bytes for Tx and Rx individually.
-Increase DMA buffer size to 4096 bytes and support byte alignment.
-Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
-Re-define registers for separating controller and target mode control.
-Support 4 individual DMA buffers for controller Tx and Rx,
target Tx and Rx.

And following is new register set for package transfer sequence.
-New Master operation mode:
 S -> Aw -> P
 S -> Aw -> TxD -> P
 S -> Ar -> RxD -> P
 S -> Aw -> RxD -> Sr -> Ar -> TxD -> P
-Bus SDA lock auto-release capability for new controller DMA command mode.
-Bus auto timeout for new controller/target DMA mode.

The following is two versus register layout.
Old:
{I2CD00}: Function Control Register
{I2CD04}: Clock and AC Timing Control Register
{I2CD08}: Clock and AC Timing Control Register
{I2CD0C}: Interrupt Control Register
{I2CD10}: Interrupt Status Register
{I2CD14}: Command/Status Register
{I2CD18}: Slave Device Address Register
{I2CD1C}: Pool Buffer Control Register
{I2CD20}: Transmit/Receive Byte Buffer Register
{I2CD24}: DMA Mode Buffer Address Register
{I2CD28}: DMA Transfer Length Register
{I2CD2C}: Original DMA Mode Buffer Address Setting
{I2CD30}: Original DMA Transfer Length Setting and Final Status

New Register mode
{I2CC00}: Master/Slave Function Control Register
{I2CC04}: Master/Slave Clock and AC Timing Control Register
{I2CC08}: Master/Slave Transmit/Receive Byte Buffer Register
{I2CC0C}: Master/Slave Pool Buffer Control Register
{I2CM10}: Master Interrupt Control Register
{I2CM14}: Master Interrupt Status Register
{I2CM18}: Master Command/Status Register
{I2CM1C}: Master DMA Buffer Length Register
{I2CS20}: Slave~ Interrupt Control Register
{I2CS24}: Slave~ Interrupt Status Register
{I2CS28}: Slave~ Command/Status Register
{I2CS2C}: Slave~ DMA Buffer Length Register
{I2CM30}: Master DMA Mode Tx Buffer Base Address
{I2CM34}: Master DMA Mode Rx Buffer Base Address
{I2CS38}: Slave~ DMA Mode Tx Buffer Base Address
{I2CS3C}: Slave~ DMA Mode Rx Buffer Base Address
{I2CS40}: Slave Device Address Register
{I2CM48}: Master DMA Length Status Register
{I2CS4C}: Slave  DMA Length Status Register
{I2CC50}: Current DMA Operating Address Status
{I2CC54}: Current DMA Operating Length  Status

> 
> >
> > The legacy register layout is mix controller/target register control together.
> The following is add more detail description about new register layout. And
> new feature set add for register.
> >
> > -Add new clock divider option for more flexible and accurate clock rate
> generation -Add tCKHighMin timing to guarantee SCL high pulse width.
> > -Add support dual pool buffer mode, split 32 bytes pool buffer of each device
> into 2 x 16 bytes for Tx and Rx individually.
> > -Increase DMA buffer size to 4096 bytes and support byte alignment.
> > -Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
> > -Re-define registers for separating controller and target mode control.
> > -Support 4 individual DMA buffers for controller Tx and Rx, target Tx and Rx.
> 
> Does it mean hardware changed on AST2600? 
No Hw change, it is different mode setting will have another mode register setting.
Mode setting is in global register, I will add in next commit message

I2CG00: Device Master Mode Interrupt Status Register (I2CG0C[3]=1)
I2CG00: Device Master/Slave Mode Interrupt Status Register (I2CG0C[3]=0)
I2CG04: Device Slave Mode Interrupt Status Register
I2CG0C: Global Control Register
I2CG10: New Clock Divider Control Register (I2CG0C[1] = 1)

> Or these are different devices
> than aspeed,ast2600-i2c-bus? If this is not a different device, how one SoC can
> have two different flavors of same device in the same instance?

When global setting for new, will new register mapping, no setting will keep old register mapping.
> 
> 
> 
> 
> Best regards,
> Krzysztof

From james.clark at linaro.org  Wed Mar  5 01:37:40 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 5 Mar 2025 09:37:40 +0000
Subject: [PATCH] Remove some PMU events for FUJITSU-MONAKA
In-Reply-To: <OS3PR01MB6903726FDA70250F72A73410D4CB2@OS3PR01MB6903.jpnprd01.prod.outlook.com>
References: <20250227054045.1340090-1-fj5100bi@fujitsu.com>
 <96b323eb-15b2-4b60-8522-83bf2f57694b@linaro.org>
 <OSZPR01MB6908AA7CEB24ED38F9289D6DD4CC2@OSZPR01MB6908.jpnprd01.prod.outlook.com>
 <OS3PR01MB6903726FDA70250F72A73410D4CB2@OS3PR01MB6903.jpnprd01.prod.outlook.com>
Message-ID: <36123515-a268-40cb-b010-2600c2f5c1c6@linaro.org>



On 05/03/2025 6:40 am, Yoshihiro Furudera (Fujitsu) wrote:
> Hi, James
> 
>>
>> Hi, James
>> Thank you for your comment.
>>
>>> On 27/02/2025 5:40 am, Yoshihiro Furudera wrote:
>>>> The following events are not counted properly:
>>>>
>>>> 0x0037 LL_CACHE_MISS_RD
>>>> 0x400B L3D_CACHE_LMISS_RD
>>>
>>> These two are discoverable so will still appear in
>>> /sys/bus/event_source/devices/armv8_pmuv3_0/events/ if the hardware
>>> says they exist. It might be better to change the json strings of
>>> these two to warn that they don't work if that's the case, otherwise
>>> Perf will still list them and you'll be worse off.
>>
>> I will leave these 2 events and
>> add a warning message to the description in the JSON file.
>> I will handle other events in the same way as these 2 events.
> 
> I'm thinking of adding one of the following warnings
> to the description of events where inaccurate counts
> occur on FUJITSU-MONAKA.
> Is this okay?
> 
> 1.Simple version
> "Note: This event does not count accurately."
> 
> 2.Detailed version
> "Note: This event does not count accurately because it counts as a miss regardless of whether the L3 prefetch is a hit or miss."
> 
> I think "2.Detailed version" is better.
> 
> example:
> {
>      "EventCode": "0x0396",
>      "EventName": "L2D_CACHE_REFILL_L3D_MISS",
>      "BriefDescription": "This event counts operations that cause a miss of the L3 cache. Note: This event does not count accurately because it counts as a miss regardless of whether the L3 prefetch is a hit or miss."
> }
> 
> Best Regards,
> Yoshihiro Furudera

You could have both by using BriefDescription and PublicDescription. The 
longer one being available with 'perf list -v'. I think that's what that 
feature is for.

Either way you should probably also update the description before the 
note, so add 'hit or miss' to the first sentence:

"EventCode": "0x0396",
"EventName": "L2D_CACHE_REFILL_L3D_MISS",
"BriefDescription": "This event counts operations that cause a hit or 
miss of the L3 cache. Note that this incorrectly counts both hits _and_ 
misses."




From sudeep.holla at arm.com  Wed Mar  5 01:41:04 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 5 Mar 2025 09:41:04 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <20250305004522.GC31667@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
 <20250305004522.GC31667@willie-the-truck>
Message-ID: <20250305094104.vctshdtgdukno2aj@bogus>

On Wed, Mar 05, 2025 at 12:45:23AM +0000, Will Deacon wrote:
> On Thu, Feb 27, 2025 at 06:17:49PM +0000, Sebastian Ene wrote:
> > Introduce the release FF-A call to notify Trustzone that the hypervisor
> > has finished copying the data from the buffer shared with Trustzone to
> > the non-secure partition.
> > 
> > Reported-by: Andrei Homescu <ahomescu at google.com>
> > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > ---
> >  arch/arm64/kvm/hyp/nvhe/ffa.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > index 861f24de97cb..7da0203f1ee9 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > @@ -725,6 +725,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
> >  	DECLARE_REG(u32, uuid3, ctxt, 4);
> >  	DECLARE_REG(u32, flags, ctxt, 5);
> >  	u32 count, partition_sz, copy_sz;
> > +	struct arm_smccc_res _res;
> >  
> >  	hyp_spin_lock(&host_buffers.lock);
> >  	if (!host_buffers.rx) {
> > @@ -741,7 +742,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
> >  
> >  	count = res->a2;
> >  	if (!count)
> > -		goto out_unlock;
> > +		goto release_rx;
> >  
> >  	if (hyp_ffa_version > FFA_VERSION_1_0) {
> >  		/* Get the number of partitions deployed in the system */
> > @@ -757,10 +758,12 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
> >  	copy_sz = partition_sz * count;
> >  	if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
> >  		ffa_to_smccc_res(res, FFA_RET_ABORTED);
> > -		goto out_unlock;
> > +		goto release_rx;
> >  	}
> >  
> >  	memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
> > +release_rx:
> > +	ffa_rx_release(&_res);
> 
> Hmm, the FFA spec is characteristically unclear as to whether or not we
> need to release the rx buffer in the case that the flags indicate use of
> the rx buffer but the returned partition count is 0.
> 
> Sudeep -- do you know what we should be doing in that case?
> 

We need to call RX_RELEASE here. I went back to the spec to confirm the
same again.

v1.2 EAC0 spec Section 7.2.2.4.2 Transfer of buffer ownership
(Or just look for the section title in any version of the spec)
"
2. Ownership transfer for the RX buffer takes place as follows.
    2. For a framework message,
       1. Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership
       of the caller?s RX buffer from the Producer to the Consumer.
3. For both types of messages, an invocation of the following FF-A ABIs
    transfers the ownership from the Consumer to the Producer.
       1. FFA_MSG_WAIT ...
       2. FFA_RX_RELEASE.
"

Hope that helps, can dig deeper if there are any ambiguities around this.

-- 
Regards,
Sudeep


From Jason-JH.Lin at mediatek.com  Wed Mar  5 01:46:22 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Wed, 5 Mar 2025 09:46:22 +0000
Subject: [PATCH v4 4/8] soc: mediatek: mtk-cmdq: Add pa_base parsing for
 unsupported subsys ID hardware
In-Reply-To: <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
	 <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>
Message-ID: <03c523e66fd56442f49c38456476cf18be59e8fb.camel@mediatek.com>

On Tue, 2025-03-04 at 10:35 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > When GCE executes instructions, the corresponding hardware register
> > can be found through the subsys ID. For hardware that does not
> > support
> > subsys ID, its subsys ID will be set to invalid value and its
> > physical
> > address needs to be used to generate GCE instructions.
> > 
> > This commit adds a pa_base parsing flow to the cmdq_client_reg
> > structure
> > for these unsupported subsys ID hardware.
> > 
> 
> Does this work only for the MMINFRA located GCEs, or does this work
> also for
> the legacy ones in MT8173/83/88/92/95 // MT6795/6893/etc?
> 
> In order to actually review and decide, I do need to know :-)
> 

Yes, it's for the SoCs without subsys ID, it's not related to the
MMINFRA.

This can also work on MT8173/83/92/95 // MT6795/6893/etc.
You can remove the `mediatek,gce-client-reg` properties in their dtsi
and cherry-pick this series to verify it. :-)

Regards,
Jason-JH Lin

> Thanks,
> Angelo
> 
> 


From ping.bai at nxp.com  Wed Mar  5 01:55:22 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Wed,  5 Mar 2025 17:55:22 +0800
Subject: [PATCH v2] irqchip: irq-imx-irqsteer: Update the CHAN_MAX_OUTPUT_INT to 15
Message-ID: <20250305095522.2177843-1-ping.bai@nxp.com>

From: Shengjiu Wang <shengjiu.wang at nxp.com>

For the irqsteer channel, it can support up to 960 interrupt
inputs. All the interrupt inputs are divided into groups of 64
each. Each group of interrupts uses one irqsteer interrupt output
connected to the parent interrupt controller like GIC.

The CHAN_MAX_OUTPUT_INT is used to define the max interrupt outputs
from the irqsteer. For previous i.MX SoCs, the irqsteer instance is
designed with max 512 interrupt inputs. If the max interrupt
inputs is 512, the max interrupt outputs is 512 / 64 = 8. But for
i.MX94 family, the irqsteer is design with max 960 interrupt inputs
capability, The CHAN_MAX_OUTPUT_INT is 15.

Update the CHAN_MAX_OUTPUT_INT to 15 and do necessary code changes
to support the max 960 interrupt inputs case.

Signed-off-by: Shengjiu Wang <shengjiu.wang at nxp.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
Reviewed-by: Ye Li <ye.li at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 - v2 changes:
  - Improve the changelog
---
 drivers/irqchip/irq-imx-irqsteer.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index b0e9788c0045..afbfcce3b1e3 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -24,7 +24,7 @@
 #define CHAN_MINTDIS(t)		(CTRL_STRIDE_OFF(t, 3) + 0x4)
 #define CHAN_MASTRSTAT(t)	(CTRL_STRIDE_OFF(t, 3) + 0x8)
 
-#define CHAN_MAX_OUTPUT_INT	0x8
+#define CHAN_MAX_OUTPUT_INT	0xF
 
 struct irqsteer_data {
 	void __iomem		*regs;
@@ -228,10 +228,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
 
 	for (i = 0; i < data->irq_count; i++) {
 		data->irq[i] = irq_of_parse_and_map(np, i);
-		if (!data->irq[i]) {
-			ret = -EINVAL;
-			goto out;
-		}
+		if (!data->irq[i])
+			break;
 
 		irq_set_chained_handler_and_data(data->irq[i],
 						 imx_irqsteer_irq_handler,
@@ -254,9 +252,13 @@ static void imx_irqsteer_remove(struct platform_device *pdev)
 	struct irqsteer_data *irqsteer_data = platform_get_drvdata(pdev);
 	int i;
 
-	for (i = 0; i < irqsteer_data->irq_count; i++)
+	for (i = 0; i < irqsteer_data->irq_count; i++) {
+		if (!irqsteer_data->irq[i])
+			break;
+
 		irq_set_chained_handler_and_data(irqsteer_data->irq[i],
 						 NULL, NULL);
+	}
 
 	irq_domain_remove(irqsteer_data->domain);
 
-- 
2.34.1



From leo.yan at arm.com  Wed Mar  5 01:53:04 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 5 Mar 2025 09:53:04 +0000
Subject: [PATCH v3 00/12] perf script: Refactor branch flags for Arm SPE
In-Reply-To: <Z8dJ00nIeVqMMncD@google.com>
References: <20250217195908.176207-1-leo.yan@arm.com>
 <20250303093853.GG2157064@e132581.arm.com>
 <Z8YYY2Q_ZPIaZ74g@google.com>
 <20250304113350.GK2157064@e132581.arm.com>
 <Z8dJ00nIeVqMMncD@google.com>
Message-ID: <20250305095304.GF13418@e132581.arm.com>

On Tue, Mar 04, 2025 at 10:43:31AM -0800, Namhyung Kim wrote:

[...]

> > Please consider picking the latest change (either the whole v4 series or
> > just the updated patch 01 would be fine).
> 
> Sure, I'll add v4 to the tmp branch soon.

Thanks, Namhyung!  Also thanks Adrian's review for v4!

Leo


From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:28 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:28 +0100
Subject: [PATCH v3 1/8] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-2-fabrice.gasnier@foss.st.com>

Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
STM32MP25 SoC. Some features has been updated or added to the low-power
timer:
- new capture compare channels
- up to two PWM channels
- PWM input capture
- peripheral interconnect in stm32mp25 has been updated (new triggers).
- registers/bits has been added or revisited (IER access).
So introduce a new compatible to handle this diversity.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V3:
- Fix yaml indentation issue found by Rob's bot
Changes in V2:
- Use fallback compatibles, along with stm32mp25 specific compatible
- trigger identifier can be up to 4 (e.g. from LPTIM1..5)
---
 .../bindings/mfd/st,stm32-lptimer.yaml        | 40 ++++++++++++++++---
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index d41308856408..4eabafb8079d 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -21,7 +21,12 @@ maintainers:
 
 properties:
   compatible:
-    const: st,stm32-lptimer
+    oneOf:
+      - items:
+          - const: st,stm32mp25-lptimer
+          - const: st,stm32-lptimer
+      - items:
+          - const: st,stm32-lptimer
 
   reg:
     maxItems: 1
@@ -48,13 +53,21 @@ properties:
     minItems: 1
     maxItems: 2
 
+  power-domains:
+    maxItems: 1
+
   pwm:
     type: object
     additionalProperties: false
 
     properties:
       compatible:
-        const: st,stm32-pwm-lp
+        oneOf:
+          - items:
+              - const: st,stm32mp25-pwm-lp
+              - const: st,stm32-pwm-lp
+          - items:
+              - const: st,stm32-pwm-lp
 
       "#pwm-cells":
         const: 3
@@ -69,7 +82,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-counter
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-counter
+              - const: st,stm32-lptimer-counter
+          - items:
+              - const: st,stm32-lptimer-counter
 
     required:
       - compatible
@@ -80,7 +98,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-timer
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-timer
+              - const: st,stm32-lptimer-timer
+          - items:
+              - const: st,stm32-lptimer-timer
 
     required:
       - compatible
@@ -92,13 +115,18 @@ patternProperties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-trigger
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-trigger
+              - const: st,stm32-lptimer-trigger
+          - items:
+              - const: st,stm32-lptimer-trigger
 
       reg:
         description: Identify trigger hardware block.
         items:
           minimum: 0
-          maximum: 2
+          maximum: 4
 
     required:
       - compatible
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:30 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:30 +0100
Subject: [PATCH v3 3/8] iio: trigger: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-4-fabrice.gasnier@foss.st.com>

From: Olivier Moysan <olivier.moysan at foss.st.com>

Add support for STM32MP25 SoC. Use newly introduced compatible to handle
this new HW variant. Add new trigger definitions that can be used by the
stm32 analog-to-digital converter. Use compatible data to identify them.

Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 drivers/iio/trigger/stm32-lptimer-trigger.c   | 109 +++++++++++++++---
 include/linux/iio/timer/stm32-lptim-trigger.h |   9 ++
 2 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c
index f1e18913236a..995234c1e7d5 100644
--- a/drivers/iio/trigger/stm32-lptimer-trigger.c
+++ b/drivers/iio/trigger/stm32-lptimer-trigger.c
@@ -16,16 +16,44 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 
-/* List Low-Power Timer triggers */
-static const char * const stm32_lptim_triggers[] = {
-	LPTIM1_OUT,
-	LPTIM2_OUT,
-	LPTIM3_OUT,
+/* Maximum triggers + one trailing null entry to indicate the end of array */
+#define MAX_TRIGGERS 3
+
+struct stm32_lptim_cfg {
+	const char * const (*triggers)[MAX_TRIGGERS];
+	unsigned int nb_triggers;
+};
+
+/* List Low-Power Timer triggers for H7, MP13, MP15 */
+static const char * const stm32_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_OUT,},
+	{ LPTIM2_OUT,},
+	{ LPTIM3_OUT,},
+};
+
+/* List Low-Power Timer triggers for STM32MP25 */
+static const char * const stm32mp25_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_CH1, LPTIM1_CH2, },
+	{ LPTIM2_CH1, LPTIM2_CH2, },
+	{ LPTIM3_CH1,},
+	{ LPTIM4_CH1,},
+	{ LPTIM5_OUT,},
+};
+
+static const struct stm32_lptim_cfg stm32mp15_lptim_cfg = {
+	.triggers = stm32_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32_lptim_triggers),
+};
+
+static const struct stm32_lptim_cfg stm32mp25_lptim_cfg = {
+	.triggers = stm32mp25_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32mp25_lptim_triggers),
 };
 
 struct stm32_lptim_trigger {
 	struct device *dev;
-	const char *trg;
+	const char * const *triggers;
+	struct list_head tr_list;
 };
 
 static int stm32_lptim_validate_device(struct iio_trigger *trig,
@@ -54,25 +82,49 @@ bool is_stm32_lptim_trigger(struct iio_trigger *trig)
 }
 EXPORT_SYMBOL(is_stm32_lptim_trigger);
 
-static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv)
+static void stm32_lptim_unregister_triggers(struct stm32_lptim_trigger *priv)
 {
-	struct iio_trigger *trig;
+	struct iio_trigger *tr;
 
-	trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg);
-	if  (!trig)
-		return -ENOMEM;
+	list_for_each_entry(tr, &priv->tr_list, alloc_list)
+		iio_trigger_unregister(tr);
+}
+
+static int stm32_lptim_register_triggers(struct stm32_lptim_trigger *priv)
+{
+	const char * const *cur = priv->triggers;
+	int ret;
 
-	trig->dev.parent = priv->dev->parent;
-	trig->ops = &stm32_lptim_trigger_ops;
-	iio_trigger_set_drvdata(trig, priv);
+	INIT_LIST_HEAD(&priv->tr_list);
 
-	return devm_iio_trigger_register(priv->dev, trig);
+	while (cur && *cur) {
+		struct iio_trigger *trig;
+
+		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
+		if  (!trig)
+			return -ENOMEM;
+
+		trig->dev.parent = priv->dev->parent;
+		trig->ops = &stm32_lptim_trigger_ops;
+		iio_trigger_set_drvdata(trig, priv);
+
+		ret = iio_trigger_register(trig);
+		if (ret)
+			return ret;
+
+		list_add_tail(&trig->alloc_list, &priv->tr_list);
+		cur++;
+	}
+
+	return 0;
 }
 
 static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 {
 	struct stm32_lptim_trigger *priv;
+	struct stm32_lptim_cfg const *lptim_cfg;
 	u32 index;
+	int ret;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -81,23 +133,42 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 	if (device_property_read_u32(&pdev->dev, "reg", &index))
 		return -EINVAL;
 
-	if (index >= ARRAY_SIZE(stm32_lptim_triggers))
+	lptim_cfg = device_get_match_data(&pdev->dev);
+
+	if (index >= lptim_cfg->nb_triggers)
 		return -EINVAL;
 
 	priv->dev = &pdev->dev;
-	priv->trg = stm32_lptim_triggers[index];
+	priv->triggers = lptim_cfg->triggers[index];
+
+	ret = stm32_lptim_register_triggers(priv);
+	if (ret) {
+		stm32_lptim_unregister_triggers(priv);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static void stm32_lptim_trigger_remove(struct platform_device *pdev)
+{
+	struct stm32_lptim_trigger *priv = platform_get_drvdata(pdev);
 
-	return stm32_lptim_setup_trig(priv);
+	stm32_lptim_unregister_triggers(priv);
 }
 
 static const struct of_device_id stm32_lptim_trig_of_match[] = {
-	{ .compatible = "st,stm32-lptimer-trigger", },
+	{ .compatible = "st,stm32-lptimer-trigger", .data = (void *)&stm32mp15_lptim_cfg },
+	{ .compatible = "st,stm32mp25-lptimer-trigger", .data = (void *)&stm32mp25_lptim_cfg},
 	{},
 };
 MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match);
 
 static struct platform_driver stm32_lptim_trigger_driver = {
 	.probe = stm32_lptim_trigger_probe,
+	.remove = stm32_lptim_trigger_remove,
 	.driver = {
 		.name = "stm32-lptimer-trigger",
 		.of_match_table = stm32_lptim_trig_of_match,
diff --git a/include/linux/iio/timer/stm32-lptim-trigger.h b/include/linux/iio/timer/stm32-lptim-trigger.h
index a34dcf6a6001..ce3cf0addb2e 100644
--- a/include/linux/iio/timer/stm32-lptim-trigger.h
+++ b/include/linux/iio/timer/stm32-lptim-trigger.h
@@ -14,6 +14,15 @@
 #define LPTIM1_OUT	"lptim1_out"
 #define LPTIM2_OUT	"lptim2_out"
 #define LPTIM3_OUT	"lptim3_out"
+#define LPTIM4_OUT	"lptim4_out"
+#define LPTIM5_OUT	"lptim5_out"
+
+#define LPTIM1_CH1	"lptim1_ch1"
+#define LPTIM1_CH2	"lptim1_ch2"
+#define LPTIM2_CH1	"lptim2_ch1"
+#define LPTIM2_CH2	"lptim2_ch2"
+#define LPTIM3_CH1	"lptim3_ch1"
+#define LPTIM4_CH1	"lptim4_ch1"
 
 #if IS_REACHABLE(CONFIG_IIO_STM32_LPTIMER_TRIGGER)
 bool is_stm32_lptim_trigger(struct iio_trigger *trig);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:27 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:27 +0100
Subject: [PATCH v3 0/8] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
Message-ID: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>

This series adds support for STM32MP25 to MFD PWM, IIO, counter and
clocksource low-power timer (LPTIM) drivers.
This new variant is managed by using a new DT compatible string, hardware
configuration and version registers.
It comes with a slightly updated register set, some new features and new
interconnect signals inside the SoC.
Same feature list as on STM32MP1x is supported currently.
The device tree files add all instances in stm32mp251 dtsi file.

Changes in V3
---
- Yaml indentation issue fixed, reported by Rob's bot

Changes in V2
---
- Review comments from Krzysztof
  - Adopt compatible fallback in dt-bindings and driver
  - drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
  - counter driver: no update (patch dropped)
  - defconfig: only enable the necessary config for upstream board
  - add lptimer DT node in stm32mp257f-ev1 board
- Add missing management of IER access for stm32mp25

Fabrice Gasnier (7):
  dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
  mfd: stm32-lptimer: add support for stm32mp25
  clocksource: stm32-lptimer: add support for stm32mp25
  pwm: stm32-lp: add support for stm32mp25
  arm64: defconfig: enable STM32 LP timer clockevent driver
  arm64: dts: st: add low-power timer nodes on stm32mp251
  arm64: dts: st: use lptimer3 as tick broadcast source on
    stm32mp257f-ev1

Olivier Moysan (1):
  iio: trigger: stm32-lptimer: add support for stm32mp25

 .../bindings/mfd/st,stm32-lptimer.yaml        |  40 +++-
 arch/arm64/boot/dts/st/stm32mp251.dtsi        | 177 ++++++++++++++
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts    |   8 +
 arch/arm64/configs/defconfig                  |   2 +
 drivers/clocksource/timer-stm32-lp.c          |  26 ++-
 drivers/iio/trigger/stm32-lptimer-trigger.c   | 109 +++++++--
 drivers/mfd/stm32-lptimer.c                   |  33 ++-
 drivers/pwm/pwm-stm32-lp.c                    | 219 +++++++++++++++---
 include/linux/iio/timer/stm32-lptim-trigger.h |   9 +
 include/linux/mfd/stm32-lptimer.h             |  35 ++-
 10 files changed, 599 insertions(+), 59 deletions(-)

-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:32 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:32 +0100
Subject: [PATCH v3 5/8] pwm: stm32-lp: add support for stm32mp25
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-6-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC. A new compatible has been added to the
dt-bindings. It represents handle new features, registers and bits
diversity.
It isn't used currently in the driver, as matching is done by retrieving
MFD parent data.

New dedicated capture/compare channels has been added: e.g. a new compare
register for channel 2. Some controls (polarity / cc channel enable) are
handled in CCMR register on this new variant (instead of wavepol bit).

So, Low-power timer can now have up to two PWM outputs. Use device data
from the MFD parent to configure the number of PWM channels e.g. 'npwm'.

Update current get_state() and apply() ops to support either:
- one PWM channel (as on older revision, or LPTIM5 on STM32MP25)
- two PWM channels (e.g. LPTIM1/2/3/4 on STM32MP25 that has the full
  feature set)
Introduce new routines to manage common prescaler, reload register and
global enable bit.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Matching is achieved by using MFD parent data.
- renamed registers/bits defintions
---
 drivers/pwm/pwm-stm32-lp.c | 219 ++++++++++++++++++++++++++++++++-----
 1 file changed, 193 insertions(+), 26 deletions(-)

diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 5832dce8ed9d..4789eafb8bac 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -20,6 +20,7 @@
 struct stm32_pwm_lp {
 	struct clk *clk;
 	struct regmap *regmap;
+	unsigned int num_cc_chans;
 };
 
 static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
@@ -30,13 +31,101 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
 /* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
 #define STM32_LPTIM_MAX_PRESCALER	128
 
+static int stm32_pwm_lp_update_allowed(struct stm32_pwm_lp *priv, int channel)
+{
+	int ret;
+	u32 ccmr1;
+	unsigned long ccmr;
+
+	/* Only one PWM on this LPTIMER: enable, prescaler and reload value can be changed */
+	if (!priv->num_cc_chans)
+		return true;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+	ccmr = ccmr1 & (STM32_LPTIM_CC1E | STM32_LPTIM_CC2E);
+
+	/* More than one channel enabled: enable, prescaler or ARR value can't be changed */
+	if (bitmap_weight(&ccmr, sizeof(u32) * BITS_PER_BYTE) > 1)
+		return false;
+
+	/*
+	 * Only one channel is enabled (or none): check status on the other channel, to
+	 * report if enable, prescaler or ARR value can be changed.
+	 */
+	if (channel)
+		return !(ccmr1 & STM32_LPTIM_CC1E);
+	else
+		return !(ccmr1 & STM32_LPTIM_CC2E);
+}
+
+static int stm32_pwm_lp_compare_channel_apply(struct stm32_pwm_lp *priv, int channel,
+					      bool enable, enum pwm_polarity polarity)
+{
+	u32 ccmr1, val, mask;
+	bool reenable;
+	int ret;
+
+	/* No dedicated CC channel: nothing to do */
+	if (!priv->num_cc_chans)
+		return 0;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+
+	if (channel) {
+		/* Must disable CC channel (CCxE) to modify polarity (CCxP), then re-enable */
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC2E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC2P, ccmr1));
+
+		mask = STM32_LPTIM_CC2SEL | STM32_LPTIM_CC2E | STM32_LPTIM_CC2P;
+		val = FIELD_PREP(STM32_LPTIM_CC2P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC2E, enable);
+	} else {
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC1E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC1P, ccmr1));
+
+		mask = STM32_LPTIM_CC1SEL | STM32_LPTIM_CC1E | STM32_LPTIM_CC1P;
+		val = FIELD_PREP(STM32_LPTIM_CC1P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC1E, enable);
+	}
+
+	if (reenable) {
+		u32 cfgr, presc;
+		unsigned long rate;
+		unsigned int delay_us;
+
+		ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1,
+					 channel ? STM32_LPTIM_CC2E : STM32_LPTIM_CC1E, 0);
+		if (ret)
+			return ret;
+		/*
+		 * After a write to the LPTIM_CCMRx register, a new write operation can only be
+		 * performed after a delay of at least (PRESC ? 3) clock cycles
+		 */
+		ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+		if (ret)
+			return ret;
+		presc = FIELD_GET(STM32_LPTIM_PRESC, cfgr);
+		rate = clk_get_rate(priv->clk) >> presc;
+		if (!rate)
+			return -EINVAL;
+		delay_us = 3 * DIV_ROUND_UP(USEC_PER_SEC, rate);
+		usleep_range(delay_us, delay_us * 2);
+	}
+
+	return regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1, mask, val);
+}
+
 static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			      const struct pwm_state *state)
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long long prd, div, dty;
 	struct pwm_state cstate;
-	u32 val, mask, cfgr, presc = 0;
+	u32 arr, val, mask, cfgr, presc = 0;
 	bool reenable;
 	int ret;
 
@@ -45,10 +134,28 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	if (!state->enabled) {
 		if (cstate.enabled) {
-			/* Disable LP timer */
-			ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+			/* Disable CC channel if any */
+			ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, false,
+								 state->polarity);
 			if (ret)
 				return ret;
+			ret = regmap_write(priv->regmap, pwm->hwpwm ?
+					   STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, 0);
+			if (ret)
+				return ret;
+
+			/* Check if the timer can be disabled */
+			ret = stm32_pwm_lp_update_allowed(priv, pwm->hwpwm);
+			if (ret < 0)
+				return ret;
+
+			if (ret) {
+				/* Disable LP timer */
+				ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+				if (ret)
+					return ret;
+			}
+
 			/* disable clock to PWM counter */
 			clk_disable(priv->clk);
 		}
@@ -79,6 +186,23 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	dty = prd * state->duty_cycle;
 	do_div(dty, state->period);
 
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+	if (ret)
+		return ret;
+
+	/*
+	 * When there are several channels, they share the same prescaler and reload value.
+	 * Check if this can be changed, or the values are the same for all channels.
+	 */
+	if (!stm32_pwm_lp_update_allowed(priv, pwm->hwpwm)) {
+		ret = regmap_read(priv->regmap, STM32_LPTIM_ARR, &arr);
+		if (ret)
+			return ret;
+
+		if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || (arr != prd - 1))
+			return -EBUSY;
+	}
+
 	if (!cstate.enabled) {
 		/* enable clock to drive PWM counter */
 		ret = clk_enable(priv->clk);
@@ -86,15 +210,20 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			return ret;
 	}
 
-	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
-	if (ret)
-		goto err;
-
 	if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||
-	    (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {
+	    ((FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity) && !priv->num_cc_chans)) {
 		val = FIELD_PREP(STM32_LPTIM_PRESC, presc);
-		val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
-		mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;
+		mask = STM32_LPTIM_PRESC;
+
+		if (!priv->num_cc_chans) {
+			/*
+			 * WAVPOL bit is only available when no capature compare channel is used,
+			 * e.g. on LPTIMER instances that have only one output channel. CCMR1 is
+			 * used otherwise.
+			 */
+			val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
+			mask |= STM32_LPTIM_WAVPOL;
+		}
 
 		/* Must disable LP timer to modify CFGR */
 		reenable = true;
@@ -120,20 +249,27 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (ret)
 		goto err;
 
-	ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));
+	/* Write CMP/CCRx register and ensure it's been properly written */
+	ret = regmap_write(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP,
+			   prd - (1 + dty));
 	if (ret)
 		goto err;
 
-	/* ensure CMP & ARR registers are properly written */
-	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
+	/* ensure ARR and CMP/CCRx registers are properly written */
+	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, pwm->hwpwm ?
+				       (val & STM32_LPTIM_CMP2_ARROK) == STM32_LPTIM_CMP2_ARROK :
 				       (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
 				       100, 1000);
 	if (ret) {
 		dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
 		goto err;
 	}
-	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
-			   STM32_LPTIM_CMPOKCF_ARROKCF);
+	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, pwm->hwpwm ?
+			   STM32_LPTIM_CMP2OKCF_ARROKCF : STM32_LPTIM_CMPOKCF_ARROKCF);
+	if (ret)
+		goto err;
+
+	ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, true, state->polarity);
 	if (ret)
 		goto err;
 
@@ -161,11 +297,22 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long rate = clk_get_rate(priv->clk);
-	u32 val, presc, prd;
+	u32 val, presc, prd, ccmr1;
+	bool enabled;
 	u64 tmp;
 
 	regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
-	state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	if (priv->num_cc_chans) {
+		/* There's a CC chan, need to also check if it's enabled */
+		regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+		if (pwm->hwpwm)
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC2E, ccmr1);
+		else
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC1E, ccmr1);
+	}
+	state->enabled = enabled;
+
 	/* Keep PWM counter clock refcount in sync with PWM initial state */
 	if (state->enabled) {
 		int ret = clk_enable(priv->clk);
@@ -176,14 +323,21 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 
 	regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);
 	presc = FIELD_GET(STM32_LPTIM_PRESC, val);
-	state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	if (priv->num_cc_chans) {
+		if (pwm->hwpwm)
+			state->polarity = FIELD_GET(STM32_LPTIM_CC2P, ccmr1);
+		else
+			state->polarity = FIELD_GET(STM32_LPTIM_CC1P, ccmr1);
+	} else {
+		state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	}
 
 	regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);
 	tmp = prd + 1;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
 
-	regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);
+	regmap_read(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, &val);
 	tmp = prd - val;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
@@ -201,15 +355,25 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
 	struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
 	struct stm32_pwm_lp *priv;
 	struct pwm_chip *chip;
+	unsigned int npwm;
 	int ret;
 
-	chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+	if (!ddata->num_cc_chans) {
+		/* No dedicated CC channel, so there's only one PWM channel */
+		npwm = 1;
+	} else {
+		/* There are dedicated CC channels, each with one PWM output */
+		npwm = ddata->num_cc_chans;
+	}
+
+	chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*priv));
 	if (IS_ERR(chip))
 		return PTR_ERR(chip);
 	priv = to_stm32_pwm_lp(chip);
 
 	priv->regmap = ddata->regmap;
 	priv->clk = ddata->clk;
+	priv->num_cc_chans = ddata->num_cc_chans;
 	chip->ops = &stm32_pwm_lp_ops;
 
 	ret = devm_pwmchip_add(&pdev->dev, chip);
@@ -225,12 +389,15 @@ static int stm32_pwm_lp_suspend(struct device *dev)
 {
 	struct pwm_chip *chip = dev_get_drvdata(dev);
 	struct pwm_state state;
-
-	pwm_get_state(&chip->pwms[0], &state);
-	if (state.enabled) {
-		dev_err(dev, "The consumer didn't stop us (%s)\n",
-			chip->pwms[0].label);
-		return -EBUSY;
+	unsigned int i;
+
+	for (i = 0; i < chip->npwm; i++) {
+		pwm_get_state(&chip->pwms[i], &state);
+		if (state.enabled) {
+			dev_err(dev, "The consumer didn't stop us (%s)\n",
+				chip->pwms[i].label);
+			return -EBUSY;
+		}
 	}
 
 	return pinctrl_pm_select_sleep_state(dev);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:33 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:33 +0100
Subject: [PATCH v3 6/8] arm64: defconfig: enable STM32 LP timer clockevent driver
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-7-fabrice.gasnier@foss.st.com>

Enable the STM32 LP timer MFD core and clockevent drivers used on
STM32MP257F-EV1 board, for PSCI OSI.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in v2:
- dropped unused IIO trigger, PWM and counter driver unused on upstream
board currently, as advised by Krzysztof
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1f25423de383..b29b2350ae27 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -775,6 +775,7 @@ CONFIG_MFD_TI_LP873X=m
 CONFIG_MFD_TPS65219=y
 CONFIG_MFD_TPS6594_I2C=m
 CONFIG_MFD_ROHM_BD718XX=y
+CONFIG_MFD_STM32_LPTIMER=m
 CONFIG_MFD_WCD934X=m
 CONFIG_MFD_KHADAS_MCU=m
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -1401,6 +1402,7 @@ CONFIG_CLK_RENESAS_VBATTB=m
 CONFIG_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_TEGRA186_TIMER=y
+CONFIG_CLKSRC_STM32_LP=y
 CONFIG_RENESAS_OSTM=y
 CONFIG_ARM_MHU=y
 CONFIG_IMX_MBOX=y
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:31 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:31 +0100
Subject: [PATCH v3 4/8] clocksource: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-5-fabrice.gasnier@foss.st.com>

On stm32mp25, DIER (former IER) must only be modified when the lptimer
is enabled. On earlier SoCs, it must be only be modified when it is
disabled. Read the LPTIM_VERR register to properly manage the enable
state, before accessing IER.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Use version data from MFD core.
- Added interrupt enable register access update in (missed in V1)
---
 drivers/clocksource/timer-stm32-lp.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index a4c95161cb22..96d975adf7a4 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -25,6 +25,7 @@ struct stm32_lp_private {
 	struct clock_event_device clkevt;
 	unsigned long period;
 	struct device *dev;
+	bool ier_wr_enabled;	/* Enables LPTIMER before writing into IER register */
 };
 
 static struct stm32_lp_private*
@@ -37,8 +38,15 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
 {
 	struct stm32_lp_private *priv = to_priv(clkevt);
 
-	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	/* Disable LPTIMER either before or after writing IER register (else, keep it enabled) */
+	if (!priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+
 	regmap_write(priv->reg, STM32_LPTIM_IER, 0);
+
+	if (priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+
 	/* clear pending flags */
 	regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
 
@@ -51,12 +59,21 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
 {
 	struct stm32_lp_private *priv = to_priv(clkevt);
 
-	/* disable LPTIMER to be able to write into IER register*/
-	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	if (!priv->ier_wr_enabled) {
+		/* Disable LPTIMER to be able to write into IER register */
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+	} else {
+		/* Enable LPTIMER to be able to write into IER register */
+		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+	}
+
 	/* enable ARR interrupt */
 	regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
+
 	/* enable LPTIMER to be able to write into ARR register */
-	regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+	if (!priv->ier_wr_enabled)
+		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+
 	/* set next event counter */
 	regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
 
@@ -151,6 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	priv->reg = ddata->regmap;
+	priv->ier_wr_enabled = ddata->version == STM32_LPTIM_VERR_23;
 	ret = clk_prepare_enable(ddata->clk);
 	if (ret)
 		return -EINVAL;
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:29 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:29 +0100
Subject: [PATCH v3 2/8] mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-3-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC.
A new hardware configuration register (HWCFGR2) has been added, to gather
number of capture/compare channels, autonomous mode and input capture
capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
supports a smaller set of features. This can now be read from HWCFGR
registers.

Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
Update the stm32_lptimer data struct so signal the number of
capture/compare channels to the child devices.
Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Compatibility is added by reading hardware configuration
  registers.
- read version register, to be used by clockevent child driver
- rename register/bits definitions
---
 drivers/mfd/stm32-lptimer.c       | 33 ++++++++++++++++++++++++++++-
 include/linux/mfd/stm32-lptimer.h | 35 ++++++++++++++++++++++++++++---
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c
index b2704a9809c7..09073dbc9c80 100644
--- a/drivers/mfd/stm32-lptimer.c
+++ b/drivers/mfd/stm32-lptimer.c
@@ -6,6 +6,7 @@
  * Inspired by Benjamin Gaignard's stm32-timers driver
  */
 
+#include <linux/bitfield.h>
 #include <linux/mfd/stm32-lptimer.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
@@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
 	return 0;
 }
 
+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
+{
+	u32 val;
+	int ret;
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
+	if (ret)
+		return ret;
+
+	/* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
+	if (ret)
+		return ret;
+
+	/* Fallback to legacy init if HWCFGR isn't present */
+	if (!val)
+		return stm32_lptimer_detect_encoder(ddata);
+
+	ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
+	if (ret)
+		return ret;
+
+	/* Number of capture/compare channels */
+	ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
+
+	return 0;
+}
+
 static int stm32_lptimer_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
 	if (IS_ERR(ddata->clk))
 		return PTR_ERR(ddata->clk);
 
-	ret = stm32_lptimer_detect_encoder(ddata);
+	ret = stm32_lptimer_detect_hwcfgr(ddata);
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h
index 06d3f11dc3c9..30ebd3152e1a 100644
--- a/include/linux/mfd/stm32-lptimer.h
+++ b/include/linux/mfd/stm32-lptimer.h
@@ -17,20 +17,28 @@
 #define STM32_LPTIM_IER		0x08	/* Interrupt Enable Reg      */
 #define STM32_LPTIM_CFGR	0x0C	/* Configuration Reg         */
 #define STM32_LPTIM_CR		0x10	/* Control Reg               */
-#define STM32_LPTIM_CMP		0x14	/* Compare Reg               */
+#define STM32_LPTIM_CMP		0x14	/* Compare Reg (MP25 CCR1)   */
 #define STM32_LPTIM_ARR		0x18	/* Autoreload Reg            */
 #define STM32_LPTIM_CNT		0x1C	/* Counter Reg               */
+#define STM32_LPTIM_CCMR1	0x2C	/* Capture/Compare Mode MP25 */
+#define STM32_LPTIM_CCR2	0x34	/* Compare Reg2 MP25         */
+
+#define STM32_LPTIM_HWCFGR2	0x3EC	/* Hardware configuration register 2 - MP25 */
+#define STM32_LPTIM_HWCFGR1	0x3F0	/* Hardware configuration register 1 - MP15 */
+#define STM32_LPTIM_VERR	0x3F4	/* Version identification register - MP15 */
 
 /* STM32_LPTIM_ISR - bit fields */
+#define STM32_LPTIM_CMP2_ARROK		(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOK_ARROK		GENMASK(4, 3)
 #define STM32_LPTIM_ARROK		BIT(4)
 #define STM32_LPTIM_CMPOK		BIT(3)
 
 /* STM32_LPTIM_ICR - bit fields */
-#define STM32_LPTIM_ARRMCF		BIT(1)
+#define STM32_LPTIM_CMP2OKCF_ARROKCF	(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOKCF_ARROKCF	GENMASK(4, 3)
+#define STM32_LPTIM_ARRMCF		BIT(1)
 
-/* STM32_LPTIM_IER - bit flieds */
+/* STM32_LPTIM_IER - bit fields */
 #define STM32_LPTIM_ARRMIE	BIT(1)
 
 /* STM32_LPTIM_CR - bit fields */
@@ -53,16 +61,37 @@
 /* STM32_LPTIM_ARR */
 #define STM32_LPTIM_MAX_ARR	0xFFFF
 
+/* STM32_LPTIM_CCMR1 */
+#define STM32_LPTIM_CC2P	GENMASK(19, 18)
+#define STM32_LPTIM_CC2E	BIT(17)
+#define STM32_LPTIM_CC2SEL	BIT(16)
+#define STM32_LPTIM_CC1P	GENMASK(3, 2)
+#define STM32_LPTIM_CC1E	BIT(1)
+#define STM32_LPTIM_CC1SEL	BIT(0)
+
+/* STM32_LPTIM_HWCFGR1 */
+#define STM32_LPTIM_HWCFGR1_ENCODER	BIT(16)
+
+/* STM32_LPTIM_HWCFGR2 */
+#define STM32_LPTIM_HWCFGR2_CHAN_NUM	GENMASK(3, 0)
+
+/* STM32_LPTIM_VERR */
+#define STM32_LPTIM_VERR_23	0x23	/* STM32MP25 */
+
 /**
  * struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
  * @clk: clock reference for this instance
  * @regmap: register map reference for this instance
  * @has_encoder: indicates this Low-Power Timer supports encoder mode
+ * @num_cc_chans: indicates the number of capture/compare channels
+ * @version: indicates the major and minor revision of the controller
  */
 struct stm32_lptimer {
 	struct clk *clk;
 	struct regmap *regmap;
 	bool has_encoder;
+	unsigned int num_cc_chans;
+	u32 version;
 };
 
 #endif
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:35 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:35 +0100
Subject: [PATCH v3 8/8] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-9-fabrice.gasnier@foss.st.com>

During the low power modes the generic ARM timer is deactivated, so the
the tick broadcast is used, based on LPTIMER3 which is clocked by LSE on
STMicroelectronics boards.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1..242115863ab4 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -190,6 +190,14 @@ &i2c8 {
 	status = "disabled";
 };
 
+/* use LPTIMER with tick broadcast for suspend mode */
+&lptimer3 {
+	status = "okay";
+	timer {
+		status = "okay";
+	};
+};
+
 &rtc {
 	status = "okay";
 };
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Wed Mar  5 01:49:34 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 10:49:34 +0100
Subject: [PATCH v3 7/8] arm64: dts: st: add low-power timer nodes on stm32mp251
In-Reply-To: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250305094935.595667-8-fabrice.gasnier@foss.st.com>

Add low-power timer (LPTimer) support on STM32MP25 SoC.
The full feature set is implemented in LPTIM1/2/3/4. LPTIM5 supports a
smaller set of features (no capture/compare) channel. Still, LPTIM5 can
be used as single PWM, counter, trigger or timer.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- Adopt two compatibles: newly introduced "st,stm32mp25-..." compatible,
  and fallback "st,stm32-...".
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 +++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008..505176276e72 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -238,6 +238,78 @@ rifsc: bus at 42080000 {
 			#access-controller-cells = <1>;
 			ranges;
 
+			lptimer1: timer at 40090000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x40090000 0x400>;
+				interrupts-extended = <&exti1 47 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM1>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 17>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 0 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <0>;
+					status = "disabled";
+				};
+			};
+
+			lptimer2: timer at 400a0000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x400a0000 0x400>;
+				interrupts-extended = <&exti1 48 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM2>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 18>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 1 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <1>;
+					status = "disabled";
+				};
+			};
+
 			i2s2: audio-controller at 400b0000 {
 				compatible = "st,stm32mp25-i2s";
 				reg = <0x400b0000 0x400>;
@@ -799,6 +871,111 @@ i2c8: i2c at 46040000 {
 				status = "disabled";
 			};
 
+			lptimer3: timer at 46050000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46050000 0x400>;
+				interrupts-extended = <&exti2 29 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM3>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 19>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 2 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <2>;
+					status = "disabled";
+				};
+			};
+
+			lptimer4: timer at 46060000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46060000 0x400>;
+				interrupts-extended = <&exti2 30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM4>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 20>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 3 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <3>;
+					status = "disabled";
+				};
+			};
+
+			lptimer5: timer at 46070000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46070000 0x400>;
+				interrupts-extended = <&exti2 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM5>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 21>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 4 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+
 			csi: csi at 48020000 {
 				compatible = "st,stm32mp25-csi";
 				reg = <0x48020000 0x2000>;
-- 
2.25.1



From daniel.baluta at nxp.com  Wed Mar  5 02:00:28 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:28 +0200
Subject: [PATCH v4 0/8] imx8mp: Add support to Run/Stall DSP via reset API
Message-ID: <20250305100037.373782-1-daniel.baluta@nxp.com>

This patch series adds support to control the Run/Stall DSP bits found on
i.MX8MP via the reset controller API instead of using the syscon API.

DSP found on i.MX8MP doesn't have a direct reset line so according to hardware
design team in order to handle assert/deassert/reset functionality we
need to use a combination of control bits from two modules.

Audio block control module:
	- for Run/Stall control bits of the DSP

Debug Access Port (DAP)
	- for Software Reset via IMX8M_DAP_PWRCTL register

The current implementation for IMX DSP Remotproc driver and for Sound Open
Firmware driver (already upstream) uses the following approach:
	- maps the Audio Block Control address via syscon API through
          the fsl,dsp-ctrl property of the dsp node.
	- maps the DAP address space using directly a call to ioremap
          with IMX8M_DAP_DEBUG macro depicting the DAP base address.

The both approaches are problematic when comes to describing the address
spaces via the DT:
	- for Audio Block Control, because it uses the syscon interface
	- for DAP because it hardcodes de base address instead of using a dt node.

This patch series aims to fix the Audio Block control usage of the
syscon interface and replace it with Reset Controller interface.

Main advantages of using the Reset Controller API is that we stop
abusing the syscon interface, offer a better probe ordering, PM runtime
support. Main critique of using the Reset Controller API is that
Run/Stall bits are not reset bits (but according the hardware design
team they are part of the reset proccess since there is no real reset
line).

Initial discussion is here:
https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Note that we can safely remove the fsl,dsp-ctrl property usage from IMX DSP
remoteproc driver because there is no Device Tree users.

Changes since v3:
https://lore.kernel.org/linux-arm-kernel/20250225102005.408773-5-daniel.baluta at nxp.com/T/
	- renamed resets ids as per Philipp comments
	- add boths resets (named them runstall and softreset) as per Philipp comments

Changes since v2:
(https://lore.kernel.org/lkml/Z7ZNngd3wtJ5MZgl at lizhi-Precision-Tower-5810/T/)
        - picked R-b and A-b tags
        - use run_stall instead of reset to refer to reset controller
          instance
        - remove 'resets' description as it is a common property
        - add correct include in the yaml dts snippet example
Changes since v1:
(https://lore.kernel.org/imx/20250219030809.GD6537 at nxa18884-linux/T/)
        - addresed comments received on v1
        - picked up R-b and A-b tags

Daniel Baluta (8):
  dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
  dt-bindings: dsp: fsl,dsp: Add resets property
  arm64: dts: imx8mp: Use resets property
  reset: imx8mp-audiomix: Add prefix for internal macro
  reset: imx8mp-audiomix: Prepare the code for more reset bits
  reset: imx8mp-audiomix: Introduce active_low configuration option
  reset: imx8mp-audiomix: Add support for DSP run/stall
  imx_dsp_rproc: Use reset controller API to control the DSP

 .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 +++++-
 arch/arm64/boot/dts/freescale/imx8mp.dtsi     |  3 +
 drivers/remoteproc/imx_dsp_rproc.c            | 25 ++++--
 drivers/remoteproc/imx_rproc.h                |  2 +
 drivers/reset/reset-imx8mp-audiomix.c         | 78 +++++++++++++------
 .../dt-bindings/reset/imx8mp-reset-audiomix.h | 13 ++++
 6 files changed, 114 insertions(+), 31 deletions(-)
 create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h

-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:29 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:29 +0200
Subject: [PATCH v4 1/8] dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-2-daniel.baluta@nxp.com>

Add reset ids used for EARC and DSP on i.MX8MP platform.

Acked-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 include/dt-bindings/reset/imx8mp-reset-audiomix.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h

diff --git a/include/dt-bindings/reset/imx8mp-reset-audiomix.h b/include/dt-bindings/reset/imx8mp-reset-audiomix.h
new file mode 100644
index 000000000000..746c1337ed99
--- /dev/null
+++ b/include/dt-bindings/reset/imx8mp-reset-audiomix.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef DT_BINDING_RESET_IMX8MP_AUDIOMIX_H
+#define DT_BINDING_RESET_IMX8MP_AUDIOMIX_H
+
+#define IMX8MP_AUDIOMIX_EARC_RESET	0
+#define IMX8MP_AUDIOMIX_EARC_PHY_RESET	1
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL	2
+
+#endif /* DT_BINDING_RESET_IMX8MP_AUDIOMIX_H */
-- 
2.43.0



From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Mar  5 02:02:59 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 05 Mar 2025 18:02:59 +0800
Subject: [PATCH v3 4/4] arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
Message-ID: <20250305-irqchip-gpio-a4-a5-v3-4-1eec70352fea@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 17a6316de891..32ed1776891b 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -48,3 +48,15 @@ pwrc: power-controller {
 		};
 	};
 };
+
+&apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a5-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+};

-- 
2.37.1




From daniel.baluta at nxp.com  Wed Mar  5 02:00:30 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:30 +0200
Subject: [PATCH v4 2/8] dt-bindings: dsp: fsl,dsp: Add resets property
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-3-daniel.baluta@nxp.com>

Assert and deassert functionality of the DSP found on i.MX8MP is
realized by combining control bits from two modules: Audio Block
Control and Debug Access Port.

Audio block control bits are used to Run/Stall the DSP core
while the DAP bits are used for software reset the core.

The original plan was to use fsl,dsp-ctrl property and to refer the
audiomix bits via syscon interface. This proposal received NACK from
community we shouldn't abuse the syscon interface [1].

So remove fsl,dsp-ctrl property for i.MX8MP and use reset control
interface instead.

Example dts node only uses runstall control now, but softreset will
be added in the future when we will convert the softreset functionality
to use reset controller API.

[1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 ++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
index ab93ffd3d2e5..b8693e4b4b0d 100644
--- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
@@ -82,6 +82,15 @@ properties:
     description:
       Phandle to syscon block which provide access for processor enablement
 
+  resets:
+    minItems: 1
+
+  reset-names:
+    minItems: 1
+    items:
+      - const: runstall
+      - const: softreset
+
 required:
   - compatible
   - reg
@@ -164,6 +173,17 @@ allOf:
             - const: txdb1
             - const: rxdb0
             - const: rxdb1
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - fsl,imx8mp-dsp
+              - fsl,imx8mp-hifi4
+    then:
+      required:
+        - resets
+        - reset-names
 
 additionalProperties: false
 
@@ -186,6 +206,7 @@ examples:
     };
   - |
     #include <dt-bindings/clock/imx8mp-clock.h>
+    #include <dt-bindings/reset/imx8mp-reset-audiomix.h>
     dsp_reserved: dsp at 92400000 {
       reg = <0x92400000 0x1000000>;
       no-map;
@@ -220,5 +241,6 @@ examples:
                <&mu2 3 0>;
       memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
                       <&dsp_vdev0vring1>, <&dsp_reserved>;
-      fsl,dsp-ctrl = <&audio_blk_ctrl>;
+      resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+      reset-names = "runstall";
     };
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:31 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:31 +0200
Subject: [PATCH v4 3/8] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-4-daniel.baluta@nxp.com>

Add resets property to dsp node in order to be able to control the dsp
run/stall bit from audio block control.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index e0d3b8cba221..90ecee81e465 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/imx8mp-clock.h>
 #include <dt-bindings/power/imx8mp-power.h>
 #include <dt-bindings/reset/imx8mp-reset.h>
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interconnect/fsl,imx8mp.h>
@@ -2421,6 +2422,8 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+			reset-names = "runstall";
 			status = "disabled";
 		};
 	};
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:32 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:32 +0200
Subject: [PATCH v4 4/8] reset: imx8mp-audiomix: Add prefix for internal macro
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-5-daniel.baluta@nxp.com>

This adds IMX8MP_AUDIOMIX_ prefix to internal macros in order to show
that specific macros are related to audiomix.

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 6e3f3069f727..c2c3e8113182 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -11,8 +11,8 @@
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
 
-#define EARC			0x200
-#define EARC_RESET_MASK		0x3
+#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET	0x200
+#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		0x3
 
 struct imx8mp_audiomix_reset {
 	struct reset_controller_dev rcdev;
@@ -35,8 +35,8 @@ static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
 
 	mask = BIT(id);
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + EARC);
-	writel(reg & ~mask, reg_addr + EARC);
+	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	writel(reg & ~mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -52,8 +52,8 @@ static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 
 	mask = BIT(id);
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + EARC);
-	writel(reg | mask, reg_addr + EARC);
+	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	writel(reg | mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -78,7 +78,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
 	spin_lock_init(&priv->lock);
 
 	priv->rcdev.owner     = THIS_MODULE;
-	priv->rcdev.nr_resets = fls(EARC_RESET_MASK);
+	priv->rcdev.nr_resets = fls(IMX8MP_AUDIOMIX_EARC_RESET_MASK);
 	priv->rcdev.ops       = &imx8mp_audiomix_reset_ops;
 	priv->rcdev.of_node   = dev->parent->of_node;
 	priv->rcdev.dev	      = dev;
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:33 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:33 +0200
Subject: [PATCH v4 5/8] reset: imx8mp-audiomix: Prepare the code for more reset bits
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-6-daniel.baluta@nxp.com>

Current code supports EARC PHY Software Reset and EARC Software Reset
but it is not easily extensible to more reset bits.

So, refactor the code in order to easily allow more reset bits in the
future.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 43 ++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index c2c3e8113182..abef6d768e62 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -3,6 +3,8 @@
  * Copyright 2024 NXP
  */
 
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
+
 #include <linux/auxiliary_bus.h>
 #include <linux/device.h>
 #include <linux/io.h>
@@ -12,7 +14,24 @@
 #include <linux/reset-controller.h>
 
 #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET	0x200
-#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		0x3
+#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		BIT(1)
+#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK	BIT(2)
+
+struct imx8mp_reset_map {
+	unsigned int offset;
+	unsigned int mask;
+};
+
+static const struct imx8mp_reset_map reset_map[] = {
+	[IMX8MP_AUDIOMIX_EARC_RESET] = {
+		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+	},
+	[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
+		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
+	},
+};
 
 struct imx8mp_audiomix_reset {
 	struct reset_controller_dev rcdev;
@@ -30,13 +49,15 @@ static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, reg;
+	unsigned int mask, offset, reg;
 	unsigned long flags;
 
-	mask = BIT(id);
+	mask = reset_map[id].mask;
+	offset = reset_map[id].offset;
+
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
-	writel(reg & ~mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	reg = readl(reg_addr + offset);
+	writel(reg & ~mask, reg_addr + offset);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -47,13 +68,15 @@ static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, reg;
+	unsigned int mask, offset, reg;
 	unsigned long flags;
 
-	mask = BIT(id);
+	mask = reset_map[id].mask;
+	offset = reset_map[id].offset;
+
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
-	writel(reg | mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	reg = readl(reg_addr + offset);
+	writel(reg | mask, reg_addr + offset);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -78,7 +101,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
 	spin_lock_init(&priv->lock);
 
 	priv->rcdev.owner     = THIS_MODULE;
-	priv->rcdev.nr_resets = fls(IMX8MP_AUDIOMIX_EARC_RESET_MASK);
+	priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
 	priv->rcdev.ops       = &imx8mp_audiomix_reset_ops;
 	priv->rcdev.of_node   = dev->parent->of_node;
 	priv->rcdev.dev	      = dev;
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:34 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:34 +0200
Subject: [PATCH v4 6/8] reset: imx8mp-audiomix: Introduce active_low configuration option
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-7-daniel.baluta@nxp.com>

For EARC and EARC PHY the reset happens when clearing the reset bits.
Refactor assert/deassert function in order to take into account the
active_low configuration option.

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 41 ++++++++++++++-------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index abef6d768e62..04ad27aca806 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -20,16 +20,19 @@
 struct imx8mp_reset_map {
 	unsigned int offset;
 	unsigned int mask;
+	bool active_low;
 };
 
 static const struct imx8mp_reset_map reset_map[] = {
 	[IMX8MP_AUDIOMIX_EARC_RESET] = {
 		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
 		.mask	= IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+		.active_low = true,
 	},
 	[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
 		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
 		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
+		.active_low = true,
 	},
 };
 
@@ -44,42 +47,42 @@ static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_contr
 	return container_of(rcdev, struct imx8mp_audiomix_reset, rcdev);
 }
 
-static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
-					unsigned long id)
+static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
+				  unsigned long id, bool assert)
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, offset, reg;
-	unsigned long flags;
+	unsigned int mask, offset, active_low;
+	unsigned long reg, flags;
 
 	mask = reset_map[id].mask;
 	offset = reset_map[id].offset;
+	active_low = reset_map[id].active_low;
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	reg = readl(reg_addr + offset);
-	writel(reg & ~mask, reg_addr + offset);
+	if (active_low ^ assert)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	writel(reg, reg_addr + offset);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
 }
 
+static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
+					unsigned long id)
+{
+	return imx8mp_audiomix_update(rcdev, id, true);
+}
+
 static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 					  unsigned long id)
 {
-	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
-	void __iomem *reg_addr = priv->base;
-	unsigned int mask, offset, reg;
-	unsigned long flags;
-
-	mask = reset_map[id].mask;
-	offset = reset_map[id].offset;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + offset);
-	writel(reg | mask, reg_addr + offset);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
+	return imx8mp_audiomix_update(rcdev, id, false);
 }
 
 static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:35 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:35 +0200
Subject: [PATCH v4 7/8] reset: imx8mp-audiomix: Add support for DSP run/stall
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-8-daniel.baluta@nxp.com>

We can Run/Stall the DSP via audio block control bits found in audiomix.
Implement this functionality using the reset controller and use assert
for Stall and deassert for Run.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 04ad27aca806..6b357adfe646 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -17,6 +17,9 @@
 #define IMX8MP_AUDIOMIX_EARC_RESET_MASK		BIT(1)
 #define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK	BIT(2)
 
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET	0x108
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK	BIT(5)
+
 struct imx8mp_reset_map {
 	unsigned int offset;
 	unsigned int mask;
@@ -34,6 +37,11 @@ static const struct imx8mp_reset_map reset_map[] = {
 		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
 		.active_low = true,
 	},
+	[IMX8MP_AUDIOMIX_DSP_RUNSTALL] = {
+		.offset	= IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK,
+		.active_low = false,
+	},
 };
 
 struct imx8mp_audiomix_reset {
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar  5 02:00:36 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed,  5 Mar 2025 12:00:36 +0200
Subject: [PATCH v4 8/8] imx_dsp_rproc: Use reset controller API to control the DSP
In-Reply-To: <20250305100037.373782-1-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
Message-ID: <20250305100037.373782-9-daniel.baluta@nxp.com>

DSP on i.MX8MP doesn't have a direct reset line so according to hardware
design team in order to handle assert/deassert/reset functionality we
need to use a combination of control bits from two modules. Audio block
control module for Run/Stall control of the DSP and DAP module in order
to do software reset.

Initial design accessed RunStall bits from audio block control using the
syscon interface but this got NACKed by community because of abusing the
syscon interface [1].

So instead we use the reset controller API.

[1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/remoteproc/imx_dsp_rproc.c | 25 +++++++++++++++++--------
 drivers/remoteproc/imx_rproc.h     |  2 ++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index ea5024919c2f..bc60edcdd661 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -19,6 +19,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 
 #include "imx_rproc.h"
@@ -111,6 +112,7 @@ enum imx_dsp_rp_mbox_messages {
  */
 struct imx_dsp_rproc {
 	struct regmap				*regmap;
+	struct reset_control			*run_stall;
 	struct rproc				*rproc;
 	const struct imx_dsp_rproc_dcfg		*dsp_dcfg;
 	struct clk_bulk_data			clks[DSP_RPROC_CLK_MAX];
@@ -192,9 +194,7 @@ static int imx8mp_dsp_reset(struct imx_dsp_rproc *priv)
 	/* Keep reset asserted for 10 cycles */
 	usleep_range(1, 2);
 
-	regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2,
-			   IMX8M_AudioDSP_REG2_RUNSTALL,
-			   IMX8M_AudioDSP_REG2_RUNSTALL);
+	reset_control_assert(priv->run_stall);
 
 	/* Take the DSP out of reset and keep stalled for FW loading */
 	pwrctl = readl(dap + IMX8M_DAP_PWRCTL);
@@ -231,13 +231,9 @@ static int imx8ulp_dsp_reset(struct imx_dsp_rproc *priv)
 
 /* Specific configuration for i.MX8MP */
 static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = {
-	.src_reg	= IMX8M_AudioDSP_REG2,
-	.src_mask	= IMX8M_AudioDSP_REG2_RUNSTALL,
-	.src_start	= 0,
-	.src_stop	= IMX8M_AudioDSP_REG2_RUNSTALL,
 	.att		= imx_dsp_rproc_att_imx8mp,
 	.att_size	= ARRAY_SIZE(imx_dsp_rproc_att_imx8mp),
-	.method		= IMX_RPROC_MMIO,
+	.method		= IMX_RPROC_RESET_CONTROLLER,
 };
 
 static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = {
@@ -329,6 +325,9 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
 					  true,
 					  rproc->bootaddr);
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		ret = reset_control_deassert(priv->run_stall);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -369,6 +368,9 @@ static int imx_dsp_rproc_stop(struct rproc *rproc)
 					  false,
 					  rproc->bootaddr);
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		ret = reset_control_assert(priv->run_stall);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -995,6 +997,13 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv)
 
 		priv->regmap = regmap;
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall");
+		if (IS_ERR(priv->run_stall)) {
+			dev_err(dev, "Failed to get DSP runstall reset control\n");
+			return PTR_ERR(priv->run_stall);
+		}
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		break;
diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
index 17a7d051c531..cfd38d37e146 100644
--- a/drivers/remoteproc/imx_rproc.h
+++ b/drivers/remoteproc/imx_rproc.h
@@ -24,6 +24,8 @@ enum imx_rproc_method {
 	IMX_RPROC_SMC,
 	/* Through System Control Unit API */
 	IMX_RPROC_SCU_API,
+	/* Through Reset Controller API */
+	IMX_RPROC_RESET_CONTROLLER,
 };
 
 /* dcfg flags */
-- 
2.43.0



From wbg at kernel.org  Wed Mar  5 02:01:19 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Wed, 05 Mar 2025 19:01:19 +0900
Subject: [PATCH] counter: microchip-tcb-capture: Fix undefined counter
 channel state on probe
Message-ID: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>

Hardware initialize of the timer counter channel does not occur on probe
thus leaving the Count in an undefined state until the first
function_write() callback is executed. Fix this by performing the proper
hardware initialization during probe.

Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
Reported-by: Cs?k?s Bence <csokas.bence at prolan.hu>
Closes: https://lore.kernel.org/all/bfa70e78-3cc3-4295-820b-3925c26135cb at prolan.hu/
Signed-off-by: William Breathitt Gray <wbg at kernel.org>
---
This should fix the issue where a user needs to set the count function
before they can use the counter. I don't have this hardware in person,
so please test this patch and let me know whether it works for you.
---
 drivers/counter/microchip-tcb-capture.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 2f096a5b973d18edf5de5a2b33f2f72571deefb7..c391ac38b990939c6764a9120a4bd03289f68469 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -368,6 +368,25 @@ static int mchp_tc_probe(struct platform_device *pdev)
 			channel);
 	}
 
+	/* Disable Quadrature Decoder and position measure */
+	ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0);
+	if (ret)
+		return ret;
+
+	/* Setup the period capture mode */
+	ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR),
+				 ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK |
+				 ATMEL_TC_TCCLKS,
+				 ATMEL_TC_CMR_MASK);
+	if (ret)
+		return ret;
+
+	/* Enable clock and trigger counter */
+	ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR),
+			   ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
+	if (ret)
+		return ret;
+
 	priv->tc_cfg = tcb_config;
 	priv->regmap = regmap;
 	counter->name = dev_name(&pdev->dev);

---
base-commit: 8744dcd4fc7800de2eb9369410470bb2930d4c14
change-id: 20250305-preset-capture-mode-microchip-tcb-capture-fa31550ef594

Best regards,
-- 
William Breathitt Gray <wbg at kernel.org>



From manikandan.m at microchip.com  Wed Mar  5 02:01:34 2025
From: manikandan.m at microchip.com (Manikandan Muralidharan)
Date: Wed, 5 Mar 2025 15:31:34 +0530
Subject: [PATCH 2/2] ARM: dts: microchip: sama5d29_curiosity: Add nvmem-layout in QSPI to describe EUI48 MAC address region
In-Reply-To: <20250305100134.1171124-1-manikandan.m@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
Message-ID: <20250305100134.1171124-2-manikandan.m@microchip.com>

Add nvmem-layout in QSPI to describe EUI48 MAC address region.
This is useful for cases where U-Boot is skipped and the Ethernet
MAC address is needed to be configured in Linux.

Signed-off-by: Manikandan Muralidharan <manikandan.m at microchip.com>
---
 .../arm/boot/dts/microchip/at91-sama5d29_curiosity.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
index 7be215781549..81aca8502195 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
@@ -480,6 +480,16 @@ flash at 0 {
 		label = "atmel_qspi1";
 		status = "okay";
 
+		nvmem-layout {
+			compatible = "fixed-layout";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			mac_address_eui48: mac-address at 261 {
+				reg = <0x261 0x6>;
+			};
+		};
+
 		at91bootstrap at 0 {
 			label = "at91bootstrap";
 			reg = <0x0 0x40000>;
-- 
2.25.1



From manikandan.m at microchip.com  Wed Mar  5 02:01:33 2025
From: manikandan.m at microchip.com (Manikandan Muralidharan)
Date: Wed, 5 Mar 2025 15:31:33 +0530
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM framework to read MAC Address
Message-ID: <20250305100134.1171124-1-manikandan.m@microchip.com>

From: Varshini Rajendran <varshini.rajendran at microchip.com>

EUI identifier and the MAC Address of the Ethernet Interface is stored
after the SFDP table of contents starting at address 0x260 in the
QSPI memory.
Register the entire SFDP region read by the spi-nor (nor->sfdp) into the
NVMEM framework and read the MAC Address when requested using the nvmem
properties in the DT by the net drivers.

In kernel the Ethernet MAC address relied on U-Boot env variables or
generated a random address, which posed challenges for boards without
on-board EEPROMs or with multiple Ethernet ports.
This change ensures consistent and reliable MAC address retrieval from QSPI,
benefiting boards like the sama5d29 curiosity and sam9x75 curiosity.

Signed-off-by: Varshini Rajendran <varshini.rajendran at microchip.com>
[manikandan.m at microchip.com: Integrate the nvmem->read callback framework]
Signed-off-by: Manikandan Muralidharan <manikandan.m at microchip.com>
---
 drivers/mtd/spi-nor/sst.c | 62 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 175211fe6a5e..a0abf201ad41 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/mtd/spi-nor.h>
+#include <linux/nvmem-provider.h>
 
 #include "core.h"
 
@@ -13,6 +14,8 @@
 
 #define SST26VF_CR_BPNV		BIT(3)
 
+#define SST26VF_SFDP_EUI48	0x30
+
 static int sst26vf_nor_lock(struct spi_nor *nor, loff_t ofs, u64 len)
 {
 	return -EOPNOTSUPP;
@@ -56,8 +59,67 @@ static int sst26vf_nor_late_init(struct spi_nor *nor)
 	return 0;
 }
 
+/**
+ * sst26vf_sfdp_mac_addr_read() - check if the EUI-48 MAC Address is programmed
+ * and read the data from the prestored SFDP data
+ *
+ * @priv: User context passed to read callbacks.
+ * @offset: Offset within the NVMEM device.
+ * @val: pointer where to fill the ethernet address
+ * @bytes: Length of the NVMEM cell
+ *
+ * Return: 0 on success, -EINVAL  otherwise.
+ */
+static int sst26vf_sfdp_mac_addr_read(void *priv, unsigned int off,
+				      void *val, size_t bytes)
+{
+	struct spi_nor *nor = priv;
+	struct sfdp *sfdp = nor->sfdp;
+	loff_t offset = off;
+	size_t sfdp_size;
+
+	/*
+	 * Check if the EUI-48 MAC address is programmed in the next six address
+	 * locations.
+	 * @off is programmed in the DT and stores the start of MAC Address
+	 * byte, (off - 1) stores the bit length of the Extended Unique
+	 * Identifier
+	 */
+	if (SST26VF_SFDP_EUI48 != *((u8 *)sfdp->dwords + (offset - 1)))
+		return -EINVAL;
+
+	sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords);
+	memory_read_from_buffer(val, bytes, &offset, sfdp->dwords,
+				sfdp_size);
+	return 0;
+}
+
+static struct nvmem_config sst26vf_sfdp_nvmem_config = {
+	.word_size = 1,
+	.stride = 1,
+};
+
+static int sst26vf_nor_post_sfdp(struct spi_nor *nor)
+{
+	struct nvmem_device *nvmem;
+
+	sst26vf_sfdp_nvmem_config.dev = nor->dev;
+	sst26vf_sfdp_nvmem_config.size = nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords);
+	sst26vf_sfdp_nvmem_config.priv = nor;
+	sst26vf_sfdp_nvmem_config.reg_read = sst26vf_sfdp_mac_addr_read;
+
+	nvmem = devm_nvmem_register(nor->dev, &sst26vf_sfdp_nvmem_config);
+	if (IS_ERR(nvmem)) {
+		dev_err(nor->dev, "failed to register NVMEM device: %ld\n", PTR_ERR(nvmem));
+		return PTR_ERR(nvmem);
+	}
+
+	return 0;
+}
+
 static const struct spi_nor_fixups sst26vf_nor_fixups = {
 	.late_init = sst26vf_nor_late_init,
+	.post_sfdp = sst26vf_nor_post_sfdp,
 };
 
 static const struct flash_info sst_nor_parts[] = {
-- 
2.25.1



From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Mar  5 02:02:58 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 05 Mar 2025 18:02:58 +0800
Subject: [PATCH v3 3/4] arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
Message-ID: <20250305-irqchip-gpio-a4-a5-v3-3-1eec70352fea@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index efba8565af3c..fa80fa365f13 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -51,6 +51,25 @@ pwrc: power-controller {
 };
 
 &apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a4-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+
+	gpio_ao_intc: interrupt-controller at 8e72c {
+		compatible = "amlogic,a4-gpio-ao-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x8e72c 0x0 0x0c>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts = <140 141>;
+	};
+
 	periphs_pinctrl: pinctrl {
 		compatible = "amlogic,pinctrl-a4";
 		#address-cells = <2>;

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Mar  5 02:02:56 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 05 Mar 2025 18:02:56 +0800
Subject: [PATCH v3 1/4] dt-bindings: interrupt-controller: Add support for
 Amlogic A4 and A5 SoCs
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
Message-ID: <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Update dt-binding document for GPIO interrupt controller
of Amlogic A4 and A5 SoCs

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 .../amlogic,meson-gpio-intc.yaml                    | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
index a93744763787..3c5853c71efa 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
@@ -35,6 +35,9 @@ properties:
               - amlogic,meson-sm1-gpio-intc
               - amlogic,meson-a1-gpio-intc
               - amlogic,meson-s4-gpio-intc
+              - amlogic,a4-gpio-intc
+              - amlogic,a4-gpio-ao-intc
+              - amlogic,a5-gpio-intc
               - amlogic,c3-gpio-intc
               - amlogic,t7-gpio-intc
           - const: amlogic,meson-gpio-intc
@@ -49,8 +52,6 @@ properties:
 
   amlogic,channel-interrupts:
     description: Array with the upstream hwirq numbers
-    minItems: 8
-    maxItems: 12
     $ref: /schemas/types.yaml#/definitions/uint32-array
 
 required:
@@ -60,6 +61,22 @@ required:
   - "#interrupt-cells"
   - amlogic,channel-interrupts
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: amlogic,a4-gpio-ao-intc
+then:
+  properties:
+    amlogic,channel-interrupts:
+      minItems: 2
+      maxItems: 12
+else:
+  properties:
+    amlogic,channel-interrupts:
+      minItems: 8
+      maxItems: 12
+
 additionalProperties: false
 
 examples:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Mar  5 02:02:55 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 05 Mar 2025 18:02:55 +0800
Subject: [PATCH v3 0/4] Add GPIO interrupt support for Amlogic A4 and A5
 SoCs
Message-ID: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>

This patch adds GPIO interrupt support for Amlogic A4 and A5 SoCs

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Changes in v3:
- Fix warning when run 'make ARCH=arm64 dtbs_check'.
- Fix warning when run 'make ARCH=arm64 Image W=1'.
- Rebase file amlogic-a4.dtsi.
- Link to v2: https://lore.kernel.org/r/20250226-irqchip-gpio-a4-a5-v2-0-c55b1050cb55 at amlogic.com

Changes in v2:
- Use if/then instead of direct modification minimum value for property 'amlogic,channel-interrupts'.
- Add register offsets to the parameter structure to reduce definition of a function.
- Link to v1: https://lore.kernel.org/r/20250219-irqchip-gpio-a4-a5-v1-0-3c8e44ae42df at amlogic.com

---
Xianwei Zhao (4):
      dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
      irqchip: Add support for Amlogic A4 and A5 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

 .../amlogic,meson-gpio-intc.yaml                   | 21 ++++++++++--
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 19 ++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 +++++++
 drivers/irqchip/irq-meson-gpio.c                   | 40 +++++++++++++++++++---
 4 files changed, 85 insertions(+), 7 deletions(-)
---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20241213-irqchip-gpio-a4-a5-80c50a1456c4

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Mar  5 02:02:57 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 05 Mar 2025 18:02:57 +0800
Subject: [PATCH v3 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
Message-ID: <20250305-irqchip-gpio-a4-a5-v3-2-1eec70352fea@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

The Amlogic A4 SoCs support 12 GPIO IRQ lines and 2 AO GPIO IRQ lines,
A5 SoCs support 12 GPIO IRQ lines, details are as below.

A4 IRQ Number:
- 72:55   18 pins on bank T
- 54:32   23 pins on bank X
- 31:16   16 pins on bank D
- 15:14    2 pins on bank E
- 13:0    14 pins on bank B

A4 AO IRQ Number:
- 7       1 pin  on bank TESTN
- 6:0     7 pins on bank AO

A5 IRQ Number:
- 98      1 pin  on bank TESTN
- 97:82   16 pins on bank Z
- 81:62   20 pins on bank X
- 61:48   14 pins on bank T
- 47:32   16 pins on bank D
- 31:27    5 pins on bank H
- 26:25    2 pins on bank E
- 24:14   11 pins on bank C
- 13:0    14 pins on bank B

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/irqchip/irq-meson-gpio.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index cd789fa51519..1cc12f5b52d5 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -26,8 +26,6 @@
 
 /* use for A1 like chips */
 #define REG_PIN_A1_SEL	0x04
-/* Used for s4 chips */
-#define REG_EDGE_POL_S4	0x1c
 
 /*
  * Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
@@ -72,6 +70,7 @@ struct meson_gpio_irq_params {
 	bool support_edge_both;
 	unsigned int edge_both_offset;
 	unsigned int edge_single_offset;
+	unsigned int edge_pol_reg;
 	unsigned int pol_low_offset;
 	unsigned int pin_sel_mask;
 	struct irq_ctl_ops ops;
@@ -105,6 +104,18 @@ struct meson_gpio_irq_params {
 	.pin_sel_mask = 0x7f,					\
 	.nr_channels = 8,					\
 
+#define INIT_MESON_A4_AO_COMMON_DATA(irqs)			\
+	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
+			  meson_a1_gpio_irq_sel_pin,		\
+			  meson_s4_gpio_irq_set_type)		\
+	.support_edge_both = true,				\
+	.edge_both_offset = 0,					\
+	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x8,					\
+	.pol_low_offset = 0,					\
+	.pin_sel_mask = 0xff,					\
+	.nr_channels = 2,					\
+
 #define INIT_MESON_S4_COMMON_DATA(irqs)				\
 	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
 			  meson_a1_gpio_irq_sel_pin,		\
@@ -112,6 +123,7 @@ struct meson_gpio_irq_params {
 	.support_edge_both = true,				\
 	.edge_both_offset = 0,					\
 	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x1c,					\
 	.pol_low_offset = 0,					\
 	.pin_sel_mask = 0xff,					\
 	.nr_channels = 12,					\
@@ -146,6 +158,18 @@ static const struct meson_gpio_irq_params a1_params = {
 	INIT_MESON_A1_COMMON_DATA(62)
 };
 
+static const struct meson_gpio_irq_params a4_params = {
+	INIT_MESON_S4_COMMON_DATA(81)
+};
+
+static const struct meson_gpio_irq_params a4_ao_params = {
+	INIT_MESON_A4_AO_COMMON_DATA(8)
+};
+
+static const struct meson_gpio_irq_params a5_params = {
+	INIT_MESON_S4_COMMON_DATA(99)
+};
+
 static const struct meson_gpio_irq_params s4_params = {
 	INIT_MESON_S4_COMMON_DATA(82)
 };
@@ -168,6 +192,9 @@ static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
 	{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
 	{ .compatible = "amlogic,meson-a1-gpio-intc", .data = &a1_params },
 	{ .compatible = "amlogic,meson-s4-gpio-intc", .data = &s4_params },
+	{ .compatible = "amlogic,a4-gpio-ao-intc", .data = &a4_ao_params },
+	{ .compatible = "amlogic,a4-gpio-intc", .data = &a4_params },
+	{ .compatible = "amlogic,a5-gpio-intc", .data = &a5_params },
 	{ .compatible = "amlogic,c3-gpio-intc", .data = &c3_params },
 	{ .compatible = "amlogic,t7-gpio-intc", .data = &t7_params },
 	{ }
@@ -358,16 +385,19 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 {
 	u32 val = 0;
 	unsigned int idx;
+	const struct meson_gpio_irq_params *params;
+
+	params = ctl->params;
 
 	idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
 
 	type &= IRQ_TYPE_SENSE_MASK;
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4, BIT(idx), 0);
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg, BIT(idx), 0);
 
 	if (type == IRQ_TYPE_EDGE_BOTH) {
 		val |= BIT(ctl->params->edge_both_offset + idx);
-		meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4,
+		meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
 					   BIT(ctl->params->edge_both_offset + idx), val);
 		return 0;
 	}
@@ -378,7 +408,7 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
 		val |= BIT(ctl->params->edge_single_offset + idx);
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
 				   BIT(idx) | BIT(12 + idx), val);
 	return 0;
 };

-- 
2.37.1




From george.cherian at marvell.com  Wed Mar  5 02:10:23 2025
From: george.cherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 10:10:23 +0000
Subject: [PATCH v4 0/2] Add stop_on_panic support for watchdog 
Message-ID: <20250305101025.2279951-1-george.cherian@marvell.com>

This series adds a new kernel command line option to watchdog core to
stop the watchdog on panic. This is useul in certain systems which prevents
successful loading of kdump kernel due to watchdog reset.

Some of the watchdog drivers stop function could sleep. For such
drivers the stop_on_panic is not valid as the notifier callback happens
in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
options to indicate whether the stop function would sleep.


Changelog:
v1 -> v2
- Remove the per driver flag setting option
- Take the parameter via kernel command-line parameter to watchdog_core.

v2 -> v3
- Remove the helper function watchdog_stop_on_panic() from watchdog.h.
- There are no users for this. 

v3 -> v4
- Since the panic notifier is in atomic context, watchdog functions
  which sleep can't be called. 
- Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
  function sleeps.
- Simplify the stop_on_panic kernel command line parsing.
- Enable the panic notiffier only if the watchdog stop function doesn't
  sleep

George Cherian (2):
  watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
  drivers: watchdog: Add support for panic notifier callback

 drivers/watchdog/advantech_ec_wdt.c |  3 ++-
 drivers/watchdog/arm_smc_wdt.c      |  3 ++-
 drivers/watchdog/armada_37xx_wdt.c  |  2 +-
 drivers/watchdog/asm9260_wdt.c      |  2 +-
 drivers/watchdog/bcm47xx_wdt.c      |  3 ++-
 drivers/watchdog/bd9576_wdt.c       |  2 +-
 drivers/watchdog/bd96801_wdt.c      |  2 +-
 drivers/watchdog/cgbc_wdt.c         |  2 +-
 drivers/watchdog/cros_ec_wdt.c      |  5 ++++-
 drivers/watchdog/da9052_wdt.c       |  3 ++-
 drivers/watchdog/da9055_wdt.c       |  4 +++-
 drivers/watchdog/da9062_wdt.c       |  4 +++-
 drivers/watchdog/da9063_wdt.c       |  4 +++-
 drivers/watchdog/db8500_wdt.c       |  5 ++++-
 drivers/watchdog/dw_wdt.c           |  5 +++--
 drivers/watchdog/f71808e_wdt.c      |  3 ++-
 drivers/watchdog/gpio_wdt.c         |  2 +-
 drivers/watchdog/i6300esb.c         |  5 ++++-
 drivers/watchdog/imx_sc_wdt.c       |  2 +-
 drivers/watchdog/intel-mid_wdt.c    |  5 ++++-
 drivers/watchdog/it87_wdt.c         |  5 ++++-
 drivers/watchdog/jz4740_wdt.c       |  5 ++++-
 drivers/watchdog/kempld_wdt.c       |  3 ++-
 drivers/watchdog/lenovo_se10_wdt.c  |  5 ++++-
 drivers/watchdog/max77620_wdt.c     |  5 ++++-
 drivers/watchdog/mei_wdt.c          |  3 ++-
 drivers/watchdog/menf21bmc_wdt.c    |  4 +++-
 drivers/watchdog/mlx_wdt.c          |  2 +-
 drivers/watchdog/msc313e_wdt.c      |  5 ++++-
 drivers/watchdog/npcm_wdt.c         |  3 ++-
 drivers/watchdog/omap_wdt.c         |  5 ++++-
 drivers/watchdog/pm8916_wdt.c       |  5 +++--
 drivers/watchdog/pseries-wdt.c      |  2 +-
 drivers/watchdog/rave-sp-wdt.c      |  5 ++++-
 drivers/watchdog/renesas_wdt.c      |  7 ++++--
 drivers/watchdog/retu_wdt.c         |  5 ++++-
 drivers/watchdog/rn5t618_wdt.c      |  6 +++--
 drivers/watchdog/rzg2l_wdt.c        |  5 ++++-
 drivers/watchdog/rzv2h_wdt.c        |  5 ++++-
 drivers/watchdog/shwdt.c            |  6 +++--
 drivers/watchdog/sl28cpld_wdt.c     |  5 ++++-
 drivers/watchdog/softdog.c          |  5 ++++-
 drivers/watchdog/sp805_wdt.c        |  5 ++++-
 drivers/watchdog/starfive-wdt.c     |  3 ++-
 drivers/watchdog/stpmic1_wdt.c      |  5 ++++-
 drivers/watchdog/ts4800_wdt.c       |  5 ++++-
 drivers/watchdog/twl4030_wdt.c      |  5 ++++-
 drivers/watchdog/uniphier_wdt.c     |  3 ++-
 drivers/watchdog/w83627hf_wdt.c     |  5 ++++-
 drivers/watchdog/watchdog_core.c    | 35 +++++++++++++++++++++++++++++
 drivers/watchdog/wm831x_wdt.c       |  5 ++++-
 drivers/watchdog/wm8350_wdt.c       |  5 ++++-
 drivers/watchdog/xen_wdt.c          |  5 ++++-
 drivers/watchdog/ziirave_wdt.c      |  5 ++++-
 include/linux/watchdog.h            |  2 ++
 include/uapi/linux/watchdog.h       |  1 +
 56 files changed, 198 insertions(+), 58 deletions(-)

-- 
2.34.1



From george.cherian at marvell.com  Wed Mar  5 02:10:25 2025
From: george.cherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 10:10:25 +0000
Subject: [PATCH v4 2/2] drivers: watchdog: Add support for panic notifier callback
In-Reply-To: <20250305101025.2279951-1-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
Message-ID: <20250305101025.2279951-3-george.cherian@marvell.com>

Watchdog is not turned off in kernel panic situation.
In certain systems this might prevent the successful loading
of kdump kernel. The kdump kernel might hit a watchdog reset
while it is booting.

To avoid such scenarios add a panic notifier call back function
which can stop the watchdog. This provision can be enabled by
passing watchdog.stop_on_panic=1 via kernel command-line parameter.

Signed-off-by: George Cherian <george.cherian at marvell.com>
---
 drivers/watchdog/watchdog_core.c | 35 ++++++++++++++++++++++++++++++++
 include/linux/watchdog.h         |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index d46d8c8c01f2..f0006d90da92 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -34,6 +34,7 @@
 #include <linux/idr.h>		/* For ida_* macros */
 #include <linux/err.h>		/* For IS_ERR macros */
 #include <linux/of.h>		/* For of_get_timeout_sec */
+#include <linux/panic_notifier.h> /* For panic handler */
 #include <linux/suspend.h>
 
 #include "watchdog_core.h"	/* For watchdog_dev_register/... */
@@ -47,6 +48,9 @@ static int stop_on_reboot = -1;
 module_param(stop_on_reboot, int, 0444);
 MODULE_PARM_DESC(stop_on_reboot, "Stop watchdogs on reboot (0=keep watching, 1=stop)");
 
+static bool stop_on_panic;
+module_param(stop_on_panic, bool, 0444);
+MODULE_PARM_DESC(stop_on_panic, "Stop watchdogs on panic (0=keep watching, 1=stop)");
 /*
  * Deferred Registration infrastructure.
  *
@@ -155,6 +159,23 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
 }
 EXPORT_SYMBOL_GPL(watchdog_init_timeout);
 
+static int watchdog_panic_notify(struct notifier_block *nb,
+				 unsigned long action, void *data)
+{
+	struct watchdog_device *wdd;
+
+	wdd = container_of(nb, struct watchdog_device, panic_nb);
+	if (watchdog_active(wdd)) {
+		int ret;
+
+		ret = wdd->ops->stop(wdd);
+		if (ret)
+			return NOTIFY_BAD;
+	}
+
+	return NOTIFY_DONE;
+}
+
 static int watchdog_reboot_notifier(struct notifier_block *nb,
 				    unsigned long code, void *data)
 {
@@ -334,6 +355,17 @@ static int ___watchdog_register_device(struct watchdog_device *wdd)
 				wdd->id, ret);
 	}
 
+	if (stop_on_panic) {
+		if (wdd->ops->stop && !(wdd->info->options & WDIOF_STOP_MAYSLEEP)) {
+			wdd->panic_nb.notifier_call = watchdog_panic_notify;
+			atomic_notifier_chain_register(&panic_notifier_list,
+						       &wdd->panic_nb);
+			set_bit(WDOG_STOP_ON_PANIC, &wdd->status);
+		} else {
+			pr_warn("watchdog%d: stop_on_panic not supported\n", wdd->id);
+		}
+	}
+
 	return 0;
 }
 
@@ -390,6 +422,9 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)
 	if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status))
 		unregister_reboot_notifier(&wdd->reboot_nb);
 
+	if (test_bit(WDOG_STOP_ON_PANIC, &wdd->status))
+		atomic_notifier_chain_unregister(&panic_notifier_list,
+						 &wdd->panic_nb);
 	watchdog_dev_unregister(wdd);
 	ida_free(&watchdog_ida, wdd->id);
 }
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 99660197a36c..ef6f1136a4c5 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -108,6 +108,7 @@ struct watchdog_device {
 	struct notifier_block reboot_nb;
 	struct notifier_block restart_nb;
 	struct notifier_block pm_nb;
+	struct notifier_block panic_nb;
 	void *driver_data;
 	struct watchdog_core_data *wd_data;
 	unsigned long status;
@@ -118,6 +119,7 @@ struct watchdog_device {
 #define WDOG_HW_RUNNING		3	/* True if HW watchdog running */
 #define WDOG_STOP_ON_UNREGISTER	4	/* Should be stopped on unregister */
 #define WDOG_NO_PING_ON_SUSPEND	5	/* Ping worker should be stopped on suspend */
+#define WDOG_STOP_ON_PANIC	6	/* Should be stopped on panic for loading kdump kernels */
 	struct list_head deferred;
 };
 
-- 
2.34.1



From george.cherian at marvell.com  Wed Mar  5 02:10:24 2025
From: george.cherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 10:10:24 +0000
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <20250305101025.2279951-1-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
Message-ID: <20250305101025.2279951-2-george.cherian@marvell.com>

A new option flag is added to watchdog_info. This helps the watchdog
core to check whether stop functions would sleep or not.
The option flags of individual drivers are also updated accordingly.

Signed-off-by: George Cherian <george.cherian at marvell.com>
---
 drivers/watchdog/advantech_ec_wdt.c | 3 ++-
 drivers/watchdog/arm_smc_wdt.c      | 3 ++-
 drivers/watchdog/armada_37xx_wdt.c  | 2 +-
 drivers/watchdog/asm9260_wdt.c      | 2 +-
 drivers/watchdog/bcm47xx_wdt.c      | 3 ++-
 drivers/watchdog/bd9576_wdt.c       | 2 +-
 drivers/watchdog/bd96801_wdt.c      | 2 +-
 drivers/watchdog/cgbc_wdt.c         | 2 +-
 drivers/watchdog/cros_ec_wdt.c      | 5 ++++-
 drivers/watchdog/da9052_wdt.c       | 3 ++-
 drivers/watchdog/da9055_wdt.c       | 4 +++-
 drivers/watchdog/da9062_wdt.c       | 4 +++-
 drivers/watchdog/da9063_wdt.c       | 4 +++-
 drivers/watchdog/db8500_wdt.c       | 5 ++++-
 drivers/watchdog/dw_wdt.c           | 5 +++--
 drivers/watchdog/f71808e_wdt.c      | 3 ++-
 drivers/watchdog/gpio_wdt.c         | 2 +-
 drivers/watchdog/i6300esb.c         | 5 ++++-
 drivers/watchdog/imx_sc_wdt.c       | 2 +-
 drivers/watchdog/intel-mid_wdt.c    | 5 ++++-
 drivers/watchdog/it87_wdt.c         | 5 ++++-
 drivers/watchdog/jz4740_wdt.c       | 5 ++++-
 drivers/watchdog/kempld_wdt.c       | 3 ++-
 drivers/watchdog/lenovo_se10_wdt.c  | 5 ++++-
 drivers/watchdog/max77620_wdt.c     | 5 ++++-
 drivers/watchdog/mei_wdt.c          | 3 ++-
 drivers/watchdog/menf21bmc_wdt.c    | 4 +++-
 drivers/watchdog/mlx_wdt.c          | 2 +-
 drivers/watchdog/msc313e_wdt.c      | 5 ++++-
 drivers/watchdog/npcm_wdt.c         | 3 ++-
 drivers/watchdog/omap_wdt.c         | 5 ++++-
 drivers/watchdog/pm8916_wdt.c       | 5 +++--
 drivers/watchdog/pseries-wdt.c      | 2 +-
 drivers/watchdog/rave-sp-wdt.c      | 5 ++++-
 drivers/watchdog/renesas_wdt.c      | 7 +++++--
 drivers/watchdog/retu_wdt.c         | 5 ++++-
 drivers/watchdog/rn5t618_wdt.c      | 6 ++++--
 drivers/watchdog/rzg2l_wdt.c        | 5 ++++-
 drivers/watchdog/rzv2h_wdt.c        | 5 ++++-
 drivers/watchdog/shwdt.c            | 6 ++++--
 drivers/watchdog/sl28cpld_wdt.c     | 5 ++++-
 drivers/watchdog/softdog.c          | 5 ++++-
 drivers/watchdog/sp805_wdt.c        | 5 ++++-
 drivers/watchdog/starfive-wdt.c     | 3 ++-
 drivers/watchdog/stpmic1_wdt.c      | 5 ++++-
 drivers/watchdog/ts4800_wdt.c       | 5 ++++-
 drivers/watchdog/twl4030_wdt.c      | 5 ++++-
 drivers/watchdog/uniphier_wdt.c     | 3 ++-
 drivers/watchdog/w83627hf_wdt.c     | 5 ++++-
 drivers/watchdog/wm831x_wdt.c       | 5 ++++-
 drivers/watchdog/wm8350_wdt.c       | 5 ++++-
 drivers/watchdog/xen_wdt.c          | 5 ++++-
 drivers/watchdog/ziirave_wdt.c      | 5 ++++-
 include/uapi/linux/watchdog.h       | 1 +
 54 files changed, 161 insertions(+), 58 deletions(-)

diff --git a/drivers/watchdog/advantech_ec_wdt.c b/drivers/watchdog/advantech_ec_wdt.c
index 7c380f90ca58..5b62c675c2cb 100644
--- a/drivers/watchdog/advantech_ec_wdt.c
+++ b/drivers/watchdog/advantech_ec_wdt.c
@@ -131,7 +131,8 @@ static const struct watchdog_info adv_ec_wdt_info = {
 	.identity =	DRIVER_NAME,
 	.options =	WDIOF_SETTIMEOUT |
 			WDIOF_MAGICCLOSE |
-			WDIOF_KEEPALIVEPING,
+			WDIOF_KEEPALIVEPING |
+			WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops adv_ec_wdt_ops = {
diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c
index 8f3d0c3a005f..794cf0086912 100644
--- a/drivers/watchdog/arm_smc_wdt.c
+++ b/drivers/watchdog/arm_smc_wdt.c
@@ -90,7 +90,8 @@ static const struct watchdog_info smcwd_info = {
 	.identity	= DRV_NAME,
 	.options	= WDIOF_SETTIMEOUT |
 			  WDIOF_KEEPALIVEPING |
-			  WDIOF_MAGICCLOSE,
+			  WDIOF_MAGICCLOSE |
+			  WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops smcwd_ops = {
diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c
index a17a7911771a..4e5ed9e1ed90 100644
--- a/drivers/watchdog/armada_37xx_wdt.c
+++ b/drivers/watchdog/armada_37xx_wdt.c
@@ -232,7 +232,7 @@ static int armada_37xx_wdt_stop(struct watchdog_device *wdt)
 }
 
 static const struct watchdog_info armada_37xx_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_STOP_MAYSLEEP,
 	.identity = "Armada 37xx Watchdog",
 };
 
diff --git a/drivers/watchdog/asm9260_wdt.c b/drivers/watchdog/asm9260_wdt.c
index 45047e514b8e..24402206659b 100644
--- a/drivers/watchdog/asm9260_wdt.c
+++ b/drivers/watchdog/asm9260_wdt.c
@@ -181,7 +181,7 @@ static int asm9260_restart(struct watchdog_device *wdd, unsigned long action,
 
 static const struct watchdog_info asm9260_wdt_ident = {
 	.options          =     WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
-				| WDIOF_MAGICCLOSE,
+				| WDIOF_MAGICCLOSE | WDIOF_STOP_MAYSLEEP,
 	.identity         =	"Alphascale asm9260 Watchdog",
 };
 
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 06a54c7de40b..93771f12895e 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -162,7 +162,8 @@ static const struct watchdog_info bcm47xx_wdt_info = {
 	.identity	= DRV_NAME,
 	.options	= WDIOF_SETTIMEOUT |
 				WDIOF_KEEPALIVEPING |
-				WDIOF_MAGICCLOSE,
+				WDIOF_MAGICCLOSE |
+				WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops bcm47xx_wdt_soft_ops = {
diff --git a/drivers/watchdog/bd9576_wdt.c b/drivers/watchdog/bd9576_wdt.c
index f00ea1b4e40b..876ac9636f32 100644
--- a/drivers/watchdog/bd9576_wdt.c
+++ b/drivers/watchdog/bd9576_wdt.c
@@ -68,7 +68,7 @@ static int bd9576_wdt_stop(struct watchdog_device *wdd)
 
 static const struct watchdog_info bd957x_wdt_ident = {
 	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
-			  WDIOF_SETTIMEOUT,
+			  WDIOF_SETTIMEOUT | WDIOF_STOP_MAYSLEEP,
 	.identity	= "BD957x Watchdog",
 };
 
diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c
index 12b74fd2bc05..4985a4724a6b 100644
--- a/drivers/watchdog/bd96801_wdt.c
+++ b/drivers/watchdog/bd96801_wdt.c
@@ -89,7 +89,7 @@ static int bd96801_wdt_stop(struct watchdog_device *wdt)
 
 static const struct watchdog_info bd96801_wdt_info = {
 	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
-			  WDIOF_SETTIMEOUT,
+			  WDIOF_SETTIMEOUT | WDIOF_STOP_MAYSLEEP,
 	.identity	= "BD96801 Watchdog",
 };
 
diff --git a/drivers/watchdog/cgbc_wdt.c b/drivers/watchdog/cgbc_wdt.c
index 702b055ba6f4..3ec2d53bb8e0 100644
--- a/drivers/watchdog/cgbc_wdt.c
+++ b/drivers/watchdog/cgbc_wdt.c
@@ -151,7 +151,7 @@ static int cgbc_wdt_set_timeout(struct watchdog_device *wdd,
 static const struct watchdog_info cgbc_wdt_info = {
 	.identity	= "CGBC Watchdog",
 	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-		WDIOF_MAGICCLOSE | WDIOF_PRETIMEOUT
+		WDIOF_MAGICCLOSE | WDIOF_PRETIMEOUT | WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops cgbc_wdt_ops = {
diff --git a/drivers/watchdog/cros_ec_wdt.c b/drivers/watchdog/cros_ec_wdt.c
index ba045e29f9a5..5cefeb388ef5 100644
--- a/drivers/watchdog/cros_ec_wdt.c
+++ b/drivers/watchdog/cros_ec_wdt.c
@@ -107,7 +107,10 @@ static int cros_ec_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
 }
 
 static const struct watchdog_info cros_ec_wdt_ident = {
-	.options          = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options          = WDIOF_SETTIMEOUT |
+			    WDIOF_KEEPALIVEPING |
+			    WDIOF_MAGICCLOSE |
+			    WDIOF_STOP_MAYSLEEP,
 	.firmware_version = 0,
 	.identity         = DRV_NAME,
 };
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
index 77039f2f0be5..ac6980342fcd 100644
--- a/drivers/watchdog/da9052_wdt.c
+++ b/drivers/watchdog/da9052_wdt.c
@@ -139,7 +139,8 @@ static const struct watchdog_info da9052_wdt_info = {
 			WDIOF_KEEPALIVEPING |
 			WDIOF_CARDRESET |
 			WDIOF_OVERHEAT |
-			WDIOF_POWERUNDER,
+			WDIOF_POWERUNDER |
+			WDIOF_STOP_MAYSLEEP,
 	.identity	= "DA9052 Watchdog",
 };
 
diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c
index 9d5a2009466f..dbfe02647a62 100644
--- a/drivers/watchdog/da9055_wdt.c
+++ b/drivers/watchdog/da9055_wdt.c
@@ -105,7 +105,9 @@ static int da9055_wdt_stop(struct watchdog_device *wdt_dev)
 }
 
 static const struct watchdog_info da9055_wdt_info = {
-	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options	= WDIOF_SETTIMEOUT |
+			  WDIOF_KEEPALIVEPING |
+			  WDIOF_STOP_MAYSLEEP,
 	.identity	= "DA9055 Watchdog",
 };
 
diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c
index 426962547df1..06507af68f79 100644
--- a/drivers/watchdog/da9062_wdt.c
+++ b/drivers/watchdog/da9062_wdt.c
@@ -180,7 +180,9 @@ static int da9062_wdt_restart(struct watchdog_device *wdd, unsigned long action,
 }
 
 static const struct watchdog_info da9062_watchdog_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "DA9062 WDT",
 };
 
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index 92e1b78ff481..ac7f5f14a21d 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -198,7 +198,9 @@ static int da9063_wdt_restart(struct watchdog_device *wdd, unsigned long action,
 }
 
 static const struct watchdog_info da9063_watchdog_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "DA9063 Watchdog",
 };
 
diff --git a/drivers/watchdog/db8500_wdt.c b/drivers/watchdog/db8500_wdt.c
index 97148ac0aa54..dfcb671f1a3e 100644
--- a/drivers/watchdog/db8500_wdt.c
+++ b/drivers/watchdog/db8500_wdt.c
@@ -61,7 +61,10 @@ static int db8500_wdt_set_timeout(struct watchdog_device *wdd,
 }
 
 static const struct watchdog_info db8500_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "DB8500 WDT",
 	.firmware_version = 1,
 };
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 26efca9ae0e7..74cd691cf900 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -336,13 +336,14 @@ static unsigned int dw_wdt_get_timeleft(struct watchdog_device *wdd)
 
 static const struct watchdog_info dw_wdt_ident = {
 	.options	= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
-			  WDIOF_MAGICCLOSE,
+			  WDIOF_MAGICCLOSE | WDIOF_STOP_MAYSLEEP,
 	.identity	= "Synopsys DesignWare Watchdog",
 };
 
 static const struct watchdog_info dw_wdt_pt_ident = {
 	.options	= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
-			  WDIOF_PRETIMEOUT | WDIOF_MAGICCLOSE,
+			  WDIOF_PRETIMEOUT | WDIOF_MAGICCLOSE |
+			  WDIOF_STOP_MAYSLEEP,
 	.identity	= "Synopsys DesignWare Watchdog",
 };
 
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index 6a16d3d0bb1e..4f47023d1992 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -469,7 +469,8 @@ static int fintek_wdt_probe(struct platform_device *pdev)
 	wd->ident.options = WDIOF_SETTIMEOUT
 			| WDIOF_MAGICCLOSE
 			| WDIOF_KEEPALIVEPING
-			| WDIOF_CARDRESET;
+			| WDIOF_CARDRESET
+			| WDIOF_STOP_MAYSLEEP;
 
 	snprintf(wd->ident.identity,
 		sizeof(wd->ident.identity), "%s watchdog",
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index a7b814ea740b..fc5143b14553 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -93,7 +93,7 @@ static int gpio_wdt_stop(struct watchdog_device *wdd)
 
 static const struct watchdog_info gpio_wdt_ident = {
 	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
-			  WDIOF_SETTIMEOUT,
+			  WDIOF_SETTIMEOUT | WDIOF_STOP_MAYSLEEP,
 	.identity	= "GPIO Watchdog",
 };
 
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index a30835f547b3..ccbfd610a1a8 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -190,7 +190,10 @@ static int esb_timer_set_heartbeat(struct watchdog_device *wdd,
 
 static struct watchdog_info esb_info = {
 	.identity = ESB_MODULE_NAME,
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops esb_ops = {
diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c
index 1280b9b1ec2a..2b5e9db39528 100644
--- a/drivers/watchdog/imx_sc_wdt.c
+++ b/drivers/watchdog/imx_sc_wdt.c
@@ -172,7 +172,7 @@ static const struct watchdog_ops imx_sc_wdt_ops = {
 static struct watchdog_info imx_sc_wdt_info = {
 	.identity	= "i.MX SC watchdog timer",
 	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-			  WDIOF_MAGICCLOSE,
+			  WDIOF_MAGICCLOSE | WDIOF_STOP_MAYSLEEP,
 };
 
 static int imx_sc_wdt_probe(struct platform_device *pdev)
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 756d262dc580..2f8446c8643a 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -112,7 +112,10 @@ static irqreturn_t mid_wdt_irq(int irq, void *dev_id)
 
 static const struct watchdog_info mid_wdt_info = {
 	.identity = "Intel MID SCU watchdog",
-	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+	.options = WDIOF_KEEPALIVEPING |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops mid_wdt_ops = {
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index a1e23dce8810..e4ce51978a8b 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -265,7 +265,10 @@ static const struct dmi_system_id it87_quirks[] = {
 };
 
 static const struct watchdog_info ident = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.firmware_version = 1,
 	.identity = WATCHDOG_NAME,
 };
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 395bde79e292..4cfdc367b7c2 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -112,7 +112,10 @@ static int jz4740_wdt_restart(struct watchdog_device *wdt_dev,
 }
 
 static const struct watchdog_info jz4740_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "jz4740 Watchdog",
 };
 
diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c
index e6c7a2906680..b1b8cc588d49 100644
--- a/drivers/watchdog/kempld_wdt.c
+++ b/drivers/watchdog/kempld_wdt.c
@@ -419,7 +419,8 @@ static const struct watchdog_info kempld_wdt_info = {
 	.options	= WDIOF_SETTIMEOUT |
 			WDIOF_KEEPALIVEPING |
 			WDIOF_MAGICCLOSE |
-			WDIOF_PRETIMEOUT
+			WDIOF_PRETIMEOUT |
+			WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops kempld_wdt_ops = {
diff --git a/drivers/watchdog/lenovo_se10_wdt.c b/drivers/watchdog/lenovo_se10_wdt.c
index cd0500e5080b..be5e27d4aa28 100644
--- a/drivers/watchdog/lenovo_se10_wdt.c
+++ b/drivers/watchdog/lenovo_se10_wdt.c
@@ -140,7 +140,10 @@ static int wdt_ping(struct watchdog_device *wdog)
 }
 
 static const struct watchdog_info wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "Lenovo SE10 Watchdog",
 };
 
diff --git a/drivers/watchdog/max77620_wdt.c b/drivers/watchdog/max77620_wdt.c
index d3ced783a5f4..b6ed7f52c1c3 100644
--- a/drivers/watchdog/max77620_wdt.c
+++ b/drivers/watchdog/max77620_wdt.c
@@ -144,7 +144,10 @@ static int max77620_wdt_set_timeout(struct watchdog_device *wdt_dev,
 
 static const struct watchdog_info max77620_wdt_info = {
 	.identity = "max77620-watchdog",
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops max77620_wdt_ops = {
diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
index c7a7235e6224..691df89d90b1 100644
--- a/drivers/watchdog/mei_wdt.c
+++ b/drivers/watchdog/mei_wdt.c
@@ -315,7 +315,8 @@ static struct watchdog_info wd_info = {
 	.identity = INTEL_AMT_WATCHDOG_ID,
 	.options  = WDIOF_KEEPALIVEPING |
 		    WDIOF_SETTIMEOUT |
-		    WDIOF_ALARMONLY,
+		    WDIOF_ALARMONLY |
+		    WDIOF_STOP_MAYSLEEP,
 };
 
 /**
diff --git a/drivers/watchdog/menf21bmc_wdt.c b/drivers/watchdog/menf21bmc_wdt.c
index 81ebdfc371f4..589313d82a16 100644
--- a/drivers/watchdog/menf21bmc_wdt.c
+++ b/drivers/watchdog/menf21bmc_wdt.c
@@ -99,7 +99,9 @@ static int menf21bmc_wdt_ping(struct watchdog_device *wdt)
 }
 
 static const struct watchdog_info menf21bmc_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = DEVNAME,
 };
 
diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c
index 5dc69363f06a..38452f97b79f 100644
--- a/drivers/watchdog/mlx_wdt.c
+++ b/drivers/watchdog/mlx_wdt.c
@@ -24,7 +24,7 @@
 #define MLXREG_WDT_MAX_TIMEOUT_TYPE3	65535
 #define MLXREG_WDT_MIN_TIMEOUT		1
 #define MLXREG_WDT_OPTIONS_BASE (WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | \
-				 WDIOF_SETTIMEOUT)
+				 WDIOF_SETTIMEOUT | WDIOF_STOP_MAYSLEEP)
 
 /**
  * struct mlxreg_wdt - wd private data:
diff --git a/drivers/watchdog/msc313e_wdt.c b/drivers/watchdog/msc313e_wdt.c
index 90171431fc59..532f575f48bd 100644
--- a/drivers/watchdog/msc313e_wdt.c
+++ b/drivers/watchdog/msc313e_wdt.c
@@ -77,7 +77,10 @@ static int msc313e_wdt_settimeout(struct watchdog_device *wdev, unsigned int new
 
 static const struct watchdog_info msc313e_wdt_ident = {
 	.identity = "MSC313e watchdog",
-	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops msc313e_wdt_ops = {
diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
index a5dd1c230137..4988be7db94c 100644
--- a/drivers/watchdog/npcm_wdt.c
+++ b/drivers/watchdog/npcm_wdt.c
@@ -176,7 +176,8 @@ static const struct watchdog_info npcm_wdt_info = {
 	.identity	= KBUILD_MODNAME,
 	.options	= WDIOF_SETTIMEOUT
 			| WDIOF_KEEPALIVEPING
-			| WDIOF_MAGICCLOSE,
+			| WDIOF_MAGICCLOSE
+			| WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops npcm_wdt_ops = {
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index d523428a8d22..7b0a2b7c3694 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -213,7 +213,10 @@ static unsigned int omap_wdt_get_timeleft(struct watchdog_device *wdog)
 }
 
 static const struct watchdog_info omap_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "OMAP Watchdog",
 };
 
diff --git a/drivers/watchdog/pm8916_wdt.c b/drivers/watchdog/pm8916_wdt.c
index 007ed139ab96..d384803f0fab 100644
--- a/drivers/watchdog/pm8916_wdt.c
+++ b/drivers/watchdog/pm8916_wdt.c
@@ -117,14 +117,15 @@ static irqreturn_t pm8916_wdt_isr(int irq, void *arg)
 
 static const struct watchdog_info pm8916_wdt_ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
-		   WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER,
+		   WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "QCOM PM8916 PON WDT",
 };
 
 static const struct watchdog_info pm8916_wdt_pt_ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
 		   WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER |
-		   WDIOF_PRETIMEOUT,
+		   WDIOF_PRETIMEOUT | WDIOF_STOP_MAYSLEEP,
 	.identity = "QCOM PM8916 PON WDT",
 };
 
diff --git a/drivers/watchdog/pseries-wdt.c b/drivers/watchdog/pseries-wdt.c
index 7f53b5293409..7f0b7a111e38 100644
--- a/drivers/watchdog/pseries-wdt.c
+++ b/drivers/watchdog/pseries-wdt.c
@@ -133,7 +133,7 @@ static int pseries_wdt_stop(struct watchdog_device *wdd)
 static struct watchdog_info pseries_wdt_info = {
 	.identity = DRV_NAME,
 	.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT
-	    | WDIOF_PRETIMEOUT,
+	    | WDIOF_PRETIMEOUT | WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops pseries_wdt_ops = {
diff --git a/drivers/watchdog/rave-sp-wdt.c b/drivers/watchdog/rave-sp-wdt.c
index 5d1c2176d445..3b366196a1ca 100644
--- a/drivers/watchdog/rave-sp-wdt.c
+++ b/drivers/watchdog/rave-sp-wdt.c
@@ -211,7 +211,10 @@ static int rave_sp_wdt_ping(struct watchdog_device *wdd)
 }
 
 static const struct watchdog_info rave_sp_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "RAVE SP Watchdog",
 };
 
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index c0b2a9c5250d..e328f0b6915e 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -158,8 +158,11 @@ static int rwdt_restart(struct watchdog_device *wdev, unsigned long action,
 }
 
 static const struct watchdog_info rwdt_ident = {
-	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
-		WDIOF_CARDRESET,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_CARDRESET |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "Renesas WDT Watchdog",
 };
 
diff --git a/drivers/watchdog/retu_wdt.c b/drivers/watchdog/retu_wdt.c
index 2b9017e1cd91..1ff740a97d96 100644
--- a/drivers/watchdog/retu_wdt.c
+++ b/drivers/watchdog/retu_wdt.c
@@ -87,7 +87,10 @@ static int retu_wdt_set_timeout(struct watchdog_device *wdog,
 }
 
 static const struct watchdog_info retu_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "Retu watchdog",
 };
 
diff --git a/drivers/watchdog/rn5t618_wdt.c b/drivers/watchdog/rn5t618_wdt.c
index 87d06d210ac9..db56540e5d94 100644
--- a/drivers/watchdog/rn5t618_wdt.c
+++ b/drivers/watchdog/rn5t618_wdt.c
@@ -125,8 +125,10 @@ static int rn5t618_wdt_ping(struct watchdog_device *wdt_dev)
 }
 
 static const struct watchdog_info rn5t618_wdt_info = {
-	.options	= WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
-			  WDIOF_KEEPALIVEPING,
+	.options	= WDIOF_SETTIMEOUT |
+			  WDIOF_MAGICCLOSE |
+			  WDIOF_KEEPALIVEPING |
+			  WDIOF_STOP_MAYSLEEP,
 	.identity	= DRIVER_NAME,
 };
 
diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
index 11bbe48160ec..b3569c881abe 100644
--- a/drivers/watchdog/rzg2l_wdt.c
+++ b/drivers/watchdog/rzg2l_wdt.c
@@ -219,7 +219,10 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
 }
 
 static const struct watchdog_info rzg2l_wdt_ident = {
-	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "Renesas RZ/G2L WDT Watchdog",
 };
 
diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c
index 8defd0241213..8c96e872e2a2 100644
--- a/drivers/watchdog/rzv2h_wdt.c
+++ b/drivers/watchdog/rzv2h_wdt.c
@@ -135,7 +135,10 @@ static int rzv2h_wdt_stop(struct watchdog_device *wdev)
 }
 
 static const struct watchdog_info rzv2h_wdt_ident = {
-	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "Renesas RZ/V2H WDT Watchdog",
 };
 
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 7f0150c39421..246ff99af3be 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -194,8 +194,10 @@ static void sh_wdt_ping(struct timer_list *t)
 }
 
 static const struct watchdog_info sh_wdt_info = {
-	.options		= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
-				  WDIOF_MAGICCLOSE,
+	.options		= WDIOF_KEEPALIVEPING |
+				  WDIOF_SETTIMEOUT |
+				  WDIOF_MAGICCLOSE |
+				  WDIOF_STOP_MAYSLEEP,
 	.firmware_version	= 1,
 	.identity		= "SH WDT",
 };
diff --git a/drivers/watchdog/sl28cpld_wdt.c b/drivers/watchdog/sl28cpld_wdt.c
index 8630c29818f2..bee1f597615c 100644
--- a/drivers/watchdog/sl28cpld_wdt.c
+++ b/drivers/watchdog/sl28cpld_wdt.c
@@ -104,7 +104,10 @@ static int sl28cpld_wdt_set_timeout(struct watchdog_device *wdd,
 }
 
 static const struct watchdog_info sl28cpld_wdt_info = {
-	.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "sl28cpld watchdog",
 };
 
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 7a1096265f18..4cc481157a5d 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -162,7 +162,10 @@ static int softdog_stop(struct watchdog_device *w)
 
 static struct watchdog_info softdog_info = {
 	.identity = "Software Watchdog",
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops softdog_ops = {
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index c2125f204a13..fed64b4ba991 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -214,7 +214,10 @@ static int wdt_disable(struct watchdog_device *wdd)
 }
 
 static const struct watchdog_info wdt_info = {
-	.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = MODULE_NAME,
 };
 
diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c
index 355918d62f63..46aebeeca2ee 100644
--- a/drivers/watchdog/starfive-wdt.c
+++ b/drivers/watchdog/starfive-wdt.c
@@ -409,7 +409,8 @@ static int starfive_wdt_set_timeout(struct watchdog_device *wdd,
 	return 0;
 }
 
-#define STARFIVE_WDT_OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
+#define STARFIVE_WDT_OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | \
+				WDIOF_MAGICCLOSE | WDIOF_STOP_MAYSLEEP)
 
 static const struct watchdog_info starfive_wdt_info = {
 	.options = STARFIVE_WDT_OPTIONS,
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
index 45d0c543466f..2783ebd74a54 100644
--- a/drivers/watchdog/stpmic1_wdt.c
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -67,7 +67,10 @@ static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
 }
 
 static const struct watchdog_info pmic_watchdog_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "STPMIC1 PMIC Watchdog",
 };
 
diff --git a/drivers/watchdog/ts4800_wdt.c b/drivers/watchdog/ts4800_wdt.c
index 24b1ad52102e..2a3b917be46a 100644
--- a/drivers/watchdog/ts4800_wdt.c
+++ b/drivers/watchdog/ts4800_wdt.c
@@ -100,7 +100,10 @@ static const struct watchdog_ops ts4800_wdt_ops = {
 };
 
 static const struct watchdog_info ts4800_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "TS-4800 Watchdog",
 };
 
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index 8c80d04811e4..b80098bf23f7 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -45,7 +45,10 @@ static int twl4030_wdt_set_timeout(struct watchdog_device *wdt,
 }
 
 static const struct watchdog_info twl4030_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "TWL4030 Watchdog",
 };
 
diff --git a/drivers/watchdog/uniphier_wdt.c b/drivers/watchdog/uniphier_wdt.c
index 8e9242c23022..b2e7840c0f61 100644
--- a/drivers/watchdog/uniphier_wdt.c
+++ b/drivers/watchdog/uniphier_wdt.c
@@ -168,7 +168,8 @@ static const struct watchdog_info uniphier_wdt_info = {
 	.options	= WDIOF_SETTIMEOUT |
 			  WDIOF_KEEPALIVEPING |
 			  WDIOF_MAGICCLOSE |
-			  WDIOF_OVERHEAT,
+			  WDIOF_OVERHEAT |
+			  WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops uniphier_wdt_ops = {
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index bc33b63c5a5d..139adb8eee7a 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -314,7 +314,10 @@ static unsigned int wdt_get_time(struct watchdog_device *wdog)
  */
 
 static const struct watchdog_info wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "W83627HF Watchdog",
 };
 
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index d96ad8f38bd2..a7ce9c797725 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -156,7 +156,10 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
 }
 
 static const struct watchdog_info wm831x_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "WM831x Watchdog",
 };
 
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index c82c1b77d91b..476a6e8dcf7d 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -117,7 +117,10 @@ static int wm8350_wdt_ping(struct watchdog_device *wdt_dev)
 }
 
 static const struct watchdog_info wm8350_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "WM8350 Watchdog",
 };
 
diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
index b343f421dc72..0248d9c8c451 100644
--- a/drivers/watchdog/xen_wdt.c
+++ b/drivers/watchdog/xen_wdt.c
@@ -99,7 +99,10 @@ static unsigned int xen_wdt_get_timeleft(struct watchdog_device *wdd)
 
 static struct watchdog_info xen_wdt_info = {
 	.identity = DRV_NAME,
-	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_STOP_MAYSLEEP,
 };
 
 static const struct watchdog_ops xen_wdt_ops = {
diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c
index fcc1ba02e75b..ee42099c8b46 100644
--- a/drivers/watchdog/ziirave_wdt.c
+++ b/drivers/watchdog/ziirave_wdt.c
@@ -417,7 +417,10 @@ static int ziirave_firm_upload(struct watchdog_device *wdd,
 }
 
 static const struct watchdog_info ziirave_wdt_info = {
-	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.options = WDIOF_SETTIMEOUT |
+		   WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_STOP_MAYSLEEP,
 	.identity = "RAVE Switch Watchdog",
 };
 
diff --git a/include/uapi/linux/watchdog.h b/include/uapi/linux/watchdog.h
index b15cde5c9054..83b6407c712f 100644
--- a/include/uapi/linux/watchdog.h
+++ b/include/uapi/linux/watchdog.h
@@ -48,6 +48,7 @@ struct watchdog_info {
 #define	WDIOF_PRETIMEOUT	0x0200  /* Pretimeout (in seconds), get/set */
 #define	WDIOF_ALARMONLY		0x0400	/* Watchdog triggers a management or
 					   other external alarm not a reboot */
+#define WDIOF_STOP_MAYSLEEP	0x0800  /* Watchdog Stop may sleep */
 #define	WDIOF_KEEPALIVEPING	0x8000	/* Keep alive ping reply */
 
 #define	WDIOS_DISABLECARD	0x0001	/* Turn off the watchdog timer */
-- 
2.34.1



From m-malladi at ti.com  Wed Mar  5 02:14:19 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Wed, 5 Mar 2025 15:44:19 +0530
Subject: [PATCH net-next v4 0/3] net: ti: icssg-prueth: Add native mode XDP support
Message-ID: <20250305101422.1908370-1-m-malladi@ti.com>

This series adds native XDP support using page_pool.
XDP zero copy support is not included in this patch series.

Patch 1/3: Replaces skb with page pool for Rx buffer allocation
Patch 2/3: Adds prueth_swdata struct for SWDATA for all swdata cases
Patch 3/3: Introduces native mode XDP support

v3: https://lore.kernel.org/all/20250224110102.1528552-1-m-malladi at ti.com/

Changes since v3 (v4-v3):
1/3:
- Get rid of skb from Rx management code in SR1 as suggested by 
Roger Quadros <rogerq at kernel.org>
2/3:
- remove SWDATA size information from commit message
- Fix handling of packets for non-skb type inside emac_tx_complete_packets()
- Remove incrementing budget for incorrect swdata type
- use PRUETH_SWDATA_CMD in emac_send_command_sr1()
All the above changes are suggested by Roger Quadros <rogerq at kernel.org> and
Dan Carpenter <dan.carpenter at linaro.org>
3/3:
- few cosmetic changes inside emac_xmit_xdp_frame() func
- change xdp_state type to u32 from int
Above changes are suggested by Dan Carpenter <dan.carpenter at linaro.org>
- Few improvements in emac_run_xdp case handling as suggested by 
Roger Quadros <rogerq at kernel.org>

Roger Quadros (3):
  net: ti: icssg-prueth: Use page_pool API for RX buffer allocation
  net: ti: icssg-prueth: introduce and use prueth_swdata struct for
    SWDATA
  net: ti: icssg-prueth: Add XDP support

 drivers/net/ethernet/ti/Kconfig               |   1 +
 drivers/net/ethernet/ti/icssg/icssg_common.c  | 417 ++++++++++++++----
 drivers/net/ethernet/ti/icssg/icssg_prueth.c  | 131 +++++-
 drivers/net/ethernet/ti/icssg/icssg_prueth.h  |  47 +-
 .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  58 ++-
 5 files changed, 541 insertions(+), 113 deletions(-)


base-commit: f77f12010f67259bd0e1ad18877ed27c721b627a
-- 
2.43.0



From m-malladi at ti.com  Wed Mar  5 02:14:20 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Wed, 5 Mar 2025 15:44:20 +0530
Subject: [PATCH net-next v4 1/3] net: ti: icssg-prueth: Use page_pool API for RX buffer allocation
In-Reply-To: <20250305101422.1908370-1-m-malladi@ti.com>
References: <20250305101422.1908370-1-m-malladi@ti.com>
Message-ID: <20250305101422.1908370-2-m-malladi@ti.com>

From: Roger Quadros <rogerq at kernel.org>

This is to prepare for native XDP support.

The page pool API is more faster in allocating pages than
__alloc_skb(). Drawback is that it works at PAGE_SIZE granularity
so we are not efficient in memory usage.
i.e. we are using PAGE_SIZE (4KB) memory for 1.5KB max packet size.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
Changes from v3 (v4-v3):
- Get rid of skb from Rx management code in SR1 as suggested by 
Roger Quadros <rogerq at kernel.org>

 drivers/net/ethernet/ti/Kconfig               |   1 +
 drivers/net/ethernet/ti/icssg/icssg_common.c  | 174 ++++++++++++------
 drivers/net/ethernet/ti/icssg/icssg_prueth.h  |  14 +-
 .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  51 +++--
 4 files changed, 150 insertions(+), 90 deletions(-)

diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 3a13d60a947a..a07c910c497a 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -205,6 +205,7 @@ config TI_ICSSG_PRUETH_SR1
 	select PHYLIB
 	select TI_ICSS_IEP
 	select TI_K3_CPPI_DESC_POOL
+	select PAGE_POOL
 	depends on PRU_REMOTEPROC
 	depends on NET_SWITCHDEV
 	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index 74f0f200a89d..acbb79ad8b0c 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -45,6 +45,11 @@ void prueth_cleanup_rx_chns(struct prueth_emac *emac,
 			    struct prueth_rx_chn *rx_chn,
 			    int max_rflows)
 {
+	if (rx_chn->pg_pool) {
+		page_pool_destroy(rx_chn->pg_pool);
+		rx_chn->pg_pool = NULL;
+	}
+
 	if (rx_chn->desc_pool)
 		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
 
@@ -461,17 +466,17 @@ int prueth_init_rx_chns(struct prueth_emac *emac,
 }
 EXPORT_SYMBOL_GPL(prueth_init_rx_chns);
 
-int prueth_dma_rx_push(struct prueth_emac *emac,
-		       struct sk_buff *skb,
-		       struct prueth_rx_chn *rx_chn)
+int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
+			      struct prueth_rx_chn *rx_chn,
+			      struct page *page, u32 buf_len)
 {
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
-	u32 pkt_len = skb_tailroom(skb);
 	dma_addr_t desc_dma;
 	dma_addr_t buf_dma;
 	void **swdata;
 
+	buf_dma = page_pool_get_dma_addr(page) + PRUETH_HEADROOM;
 	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
 	if (!desc_rx) {
 		netdev_err(ndev, "rx push: failed to allocate descriptor\n");
@@ -479,25 +484,18 @@ int prueth_dma_rx_push(struct prueth_emac *emac,
 	}
 	desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx);
 
-	buf_dma = dma_map_single(rx_chn->dma_dev, skb->data, pkt_len, DMA_FROM_DEVICE);
-	if (unlikely(dma_mapping_error(rx_chn->dma_dev, buf_dma))) {
-		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
-		netdev_err(ndev, "rx push: failed to map rx pkt buffer\n");
-		return -EINVAL;
-	}
-
 	cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
 			 PRUETH_NAV_PS_DATA_SIZE);
 	k3_udma_glue_rx_dma_to_cppi5_addr(rx_chn->rx_chn, &buf_dma);
-	cppi5_hdesc_attach_buf(desc_rx, buf_dma, skb_tailroom(skb), buf_dma, skb_tailroom(skb));
+	cppi5_hdesc_attach_buf(desc_rx, buf_dma, buf_len, buf_dma, buf_len);
 
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	*swdata = skb;
+	*swdata = page;
 
-	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, 0,
+	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, PRUETH_RX_FLOW_DATA,
 					desc_rx, desc_dma);
 }
-EXPORT_SYMBOL_GPL(prueth_dma_rx_push);
+EXPORT_SYMBOL_GPL(prueth_dma_rx_push_mapped);
 
 u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns)
 {
@@ -541,12 +539,16 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 	u32 buf_dma_len, pkt_len, port_id = 0;
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
-	struct sk_buff *skb, *new_skb;
 	dma_addr_t desc_dma, buf_dma;
+	struct page *page, *new_page;
+	struct page_pool *pool;
+	struct sk_buff *skb;
 	void **swdata;
 	u32 *psdata;
+	void *pa;
 	int ret;
 
+	pool = rx_chn->pg_pool;
 	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
 	if (ret) {
 		if (ret != -ENODATA)
@@ -558,15 +560,9 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 		return 0;
 
 	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
-
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	skb = *swdata;
-
-	psdata = cppi5_hdesc_get_psdata(desc_rx);
-	/* RX HW timestamp */
-	if (emac->rx_ts_enabled)
-		emac_rx_timestamp(emac, skb, psdata);
-
+	page = *swdata;
+	page_pool_dma_sync_for_cpu(pool, page, 0, PAGE_SIZE);
 	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
 	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
 	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
@@ -574,32 +570,51 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 	pkt_len -= 4;
 	cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
 
-	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
 	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
 
-	skb->dev = ndev;
-	new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
 	/* if allocation fails we drop the packet but push the
-	 * descriptor back to the ring with old skb to prevent a stall
+	 * descriptor back to the ring with old page to prevent a stall
 	 */
-	if (!new_skb) {
+	new_page = page_pool_dev_alloc_pages(pool);
+	if (unlikely(!new_page)) {
+		new_page = page;
 		ndev->stats.rx_dropped++;
-		new_skb = skb;
-	} else {
-		/* send the filled skb up the n/w stack */
-		skb_put(skb, pkt_len);
-		if (emac->prueth->is_switch_mode)
-			skb->offload_fwd_mark = emac->offload_fwd_mark;
-		skb->protocol = eth_type_trans(skb, ndev);
-		napi_gro_receive(&emac->napi_rx, skb);
-		ndev->stats.rx_bytes += pkt_len;
-		ndev->stats.rx_packets++;
+		goto requeue;
+	}
+
+	/* prepare skb and send to n/w stack */
+	pa = page_address(page);
+	skb = napi_build_skb(pa, PAGE_SIZE);
+	if (!skb) {
+		ndev->stats.rx_dropped++;
+		page_pool_recycle_direct(pool, page);
+		goto requeue;
 	}
 
+	skb_reserve(skb, PRUETH_HEADROOM);
+	skb_put(skb, pkt_len);
+	skb->dev = ndev;
+
+	psdata = cppi5_hdesc_get_psdata(desc_rx);
+	/* RX HW timestamp */
+	if (emac->rx_ts_enabled)
+		emac_rx_timestamp(emac, skb, psdata);
+
+	if (emac->prueth->is_switch_mode)
+		skb->offload_fwd_mark = emac->offload_fwd_mark;
+	skb->protocol = eth_type_trans(skb, ndev);
+
+	skb_mark_for_recycle(skb);
+	napi_gro_receive(&emac->napi_rx, skb);
+	ndev->stats.rx_bytes += pkt_len;
+	ndev->stats.rx_packets++;
+
+requeue:
 	/* queue another RX DMA */
-	ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_chns);
+	ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page,
+					PRUETH_MAX_PKT_SIZE);
 	if (WARN_ON(ret < 0)) {
-		dev_kfree_skb_any(new_skb);
+		page_pool_recycle_direct(pool, new_page);
 		ndev->stats.rx_errors++;
 		ndev->stats.rx_dropped++;
 	}
@@ -611,22 +626,16 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma)
 {
 	struct prueth_rx_chn *rx_chn = data;
 	struct cppi5_host_desc_t *desc_rx;
-	struct sk_buff *skb;
-	dma_addr_t buf_dma;
-	u32 buf_dma_len;
+	struct page_pool *pool;
+	struct page *page;
 	void **swdata;
 
+	pool = rx_chn->pg_pool;
 	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	skb = *swdata;
-	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
-	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
-
-	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len,
-			 DMA_FROM_DEVICE);
+	page = *swdata;
+	page_pool_recycle_direct(pool, page);
 	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
-
-	dev_kfree_skb_any(skb);
 }
 
 static int prueth_tx_ts_cookie_get(struct prueth_emac *emac)
@@ -907,29 +916,71 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
 }
 EXPORT_SYMBOL_GPL(icssg_napi_rx_poll);
 
+static struct page_pool *prueth_create_page_pool(struct prueth_emac *emac,
+						 struct device *dma_dev,
+						 int size)
+{
+	struct page_pool_params pp_params = { 0 };
+	struct page_pool *pool;
+
+	pp_params.order = 0;
+	pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
+	pp_params.pool_size = size;
+	pp_params.nid = dev_to_node(emac->prueth->dev);
+	pp_params.dma_dir = DMA_BIDIRECTIONAL;
+	pp_params.dev = dma_dev;
+	pp_params.napi = &emac->napi_rx;
+	pp_params.max_len = PAGE_SIZE;
+
+	pool = page_pool_create(&pp_params);
+	if (IS_ERR(pool))
+		netdev_err(emac->ndev, "cannot create rx page pool\n");
+
+	return pool;
+}
+
 int prueth_prepare_rx_chan(struct prueth_emac *emac,
 			   struct prueth_rx_chn *chn,
 			   int buf_size)
 {
-	struct sk_buff *skb;
+	struct page_pool *pool;
+	struct page *page;
 	int i, ret;
 
+	pool = prueth_create_page_pool(emac, chn->dma_dev, chn->descs_num);
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+
+	chn->pg_pool = pool;
+
 	for (i = 0; i < chn->descs_num; i++) {
-		skb = __netdev_alloc_skb_ip_align(NULL, buf_size, GFP_KERNEL);
-		if (!skb)
-			return -ENOMEM;
+		/* NOTE: we're not using memory efficiently here.
+		 * 1 full page (4KB?) used here instead of
+		 * PRUETH_MAX_PKT_SIZE (~1.5KB?)
+		 */
+		page = page_pool_dev_alloc_pages(pool);
+		if (!page) {
+			netdev_err(emac->ndev, "couldn't allocate rx page\n");
+			ret = -ENOMEM;
+			goto recycle_alloc_pg;
+		}
 
-		ret = prueth_dma_rx_push(emac, skb, chn);
+		ret = prueth_dma_rx_push_mapped(emac, chn, page, buf_size);
 		if (ret < 0) {
 			netdev_err(emac->ndev,
-				   "cannot submit skb for rx chan %s ret %d\n",
+				   "cannot submit page for rx chan %s ret %d\n",
 				   chn->name, ret);
-			kfree_skb(skb);
-			return ret;
+			page_pool_recycle_direct(pool, page);
+			goto recycle_alloc_pg;
 		}
 	}
 
 	return 0;
+
+recycle_alloc_pg:
+	prueth_reset_rx_chan(&emac->rx_chns, PRUETH_MAX_RX_FLOWS, false);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(prueth_prepare_rx_chan);
 
@@ -958,6 +1009,9 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
 					  prueth_rx_cleanup, !!i);
 	if (disable)
 		k3_udma_glue_disable_rx_chn(chn->rx_chn);
+
+	page_pool_destroy(chn->pg_pool);
+	chn->pg_pool = NULL;
 }
 EXPORT_SYMBOL_GPL(prueth_reset_rx_chan);
 
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 329b46e9ee53..c7b906de18af 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -33,6 +33,8 @@
 #include <linux/dma/k3-udma-glue.h>
 
 #include <net/devlink.h>
+#include <net/xdp.h>
+#include <net/page_pool/helpers.h>
 
 #include "icssg_config.h"
 #include "icss_iep.h"
@@ -131,6 +133,7 @@ struct prueth_rx_chn {
 	u32 descs_num;
 	unsigned int irq[ICSSG_MAX_RFLOWS];	/* separate irq per flow */
 	char name[32];
+	struct page_pool *pg_pool;
 };
 
 /* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3)
@@ -210,6 +213,10 @@ struct prueth_emac {
 	struct netdev_hw_addr_list vlan_mcast_list[MAX_VLAN_ID];
 };
 
+/* The buf includes headroom compatible with both skb and xdpf */
+#define PRUETH_HEADROOM_NA (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN)
+#define PRUETH_HEADROOM  ALIGN(PRUETH_HEADROOM_NA, sizeof(long))
+
 /**
  * struct prueth_pdata - PRUeth platform data
  * @fdqring_mode: Free desc queue mode
@@ -410,9 +417,10 @@ int prueth_init_rx_chns(struct prueth_emac *emac,
 			struct prueth_rx_chn *rx_chn,
 			char *name, u32 max_rflows,
 			u32 max_desc_num);
-int prueth_dma_rx_push(struct prueth_emac *emac,
-		       struct sk_buff *skb,
-		       struct prueth_rx_chn *rx_chn);
+int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
+			      struct prueth_rx_chn *rx_chn,
+			      struct page *page, u32 buf_len);
+unsigned int prueth_rxbuf_total_len(unsigned int len);
 void emac_rx_timestamp(struct prueth_emac *emac,
 		       struct sk_buff *skb, u32 *psdata);
 enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
index 64a19ff39562..8f5719a98614 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
@@ -268,15 +268,15 @@ static int emac_phy_connect(struct prueth_emac *emac)
  * Returns skb pointer if packet found else NULL
  * Caller must free the returned skb.
  */
-static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
-					     u32 flow_id)
+static struct page *prueth_process_rx_mgm(struct prueth_emac *emac,
+					  u32 flow_id)
 {
 	struct prueth_rx_chn *rx_chn = &emac->rx_mgm_chn;
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
-	struct sk_buff *skb, *new_skb;
+	struct page *page, *new_page;
 	dma_addr_t desc_dma, buf_dma;
-	u32 buf_dma_len, pkt_len;
+	u32 buf_dma_len;
 	void **swdata;
 	int ret;
 
@@ -299,34 +299,31 @@ static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
 	}
 
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	skb = *swdata;
+	page = *swdata;
 	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
-	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
 
 	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
 	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
 
-	new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
+	new_page = page_pool_dev_alloc_pages(rx_chn->pg_pool);
 	/* if allocation fails we drop the packet but push the
 	 * descriptor back to the ring with old skb to prevent a stall
 	 */
-	if (!new_skb) {
+	if (!new_page) {
 		netdev_err(ndev,
-			   "skb alloc failed, dropped mgm pkt from flow %d\n",
+			   "page alloc failed, dropped mgm pkt from flow %d\n",
 			   flow_id);
-		new_skb = skb;
-		skb = NULL;	/* return NULL */
-	} else {
-		/* return the filled skb */
-		skb_put(skb, pkt_len);
+		new_page = page;
+		page = NULL;	/* return NULL */
 	}
 
 	/* queue another DMA */
-	ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_mgm_chn);
+	ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page,
+					PRUETH_MAX_PKT_SIZE);
 	if (WARN_ON(ret < 0))
-		dev_kfree_skb_any(new_skb);
+		page_pool_recycle_direct(rx_chn->pg_pool, new_page);
 
-	return skb;
+	return page;
 }
 
 static void prueth_tx_ts_sr1(struct prueth_emac *emac,
@@ -362,14 +359,14 @@ static void prueth_tx_ts_sr1(struct prueth_emac *emac,
 static irqreturn_t prueth_rx_mgm_ts_thread_sr1(int irq, void *dev_id)
 {
 	struct prueth_emac *emac = dev_id;
-	struct sk_buff *skb;
+	struct page *page;
 
-	skb = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_TIMESTAMP_SR1);
-	if (!skb)
+	page = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_TIMESTAMP_SR1);
+	if (!page)
 		return IRQ_NONE;
 
-	prueth_tx_ts_sr1(emac, (void *)skb->data);
-	dev_kfree_skb_any(skb);
+	prueth_tx_ts_sr1(emac, (void *)page_address(page));
+	page_pool_recycle_direct(page->pp, page);
 
 	return IRQ_HANDLED;
 }
@@ -377,15 +374,15 @@ static irqreturn_t prueth_rx_mgm_ts_thread_sr1(int irq, void *dev_id)
 static irqreturn_t prueth_rx_mgm_rsp_thread(int irq, void *dev_id)
 {
 	struct prueth_emac *emac = dev_id;
-	struct sk_buff *skb;
+	struct page *page;
 	u32 rsp;
 
-	skb = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_RESPONSE_SR1);
-	if (!skb)
+	page = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_RESPONSE_SR1);
+	if (!page)
 		return IRQ_NONE;
 
 	/* Process command response */
-	rsp = le32_to_cpu(*(__le32 *)skb->data) & 0xffff0000;
+	rsp = le32_to_cpu(*(__le32 *)page_address(page)) & 0xffff0000;
 	if (rsp == ICSSG_SHUTDOWN_CMD_SR1) {
 		netdev_dbg(emac->ndev, "f/w Shutdown cmd resp %x\n", rsp);
 		complete(&emac->cmd_complete);
@@ -394,7 +391,7 @@ static irqreturn_t prueth_rx_mgm_rsp_thread(int irq, void *dev_id)
 		complete(&emac->cmd_complete);
 	}
 
-	dev_kfree_skb_any(skb);
+	page_pool_recycle_direct(page->pp, page);
 
 	return IRQ_HANDLED;
 }
-- 
2.43.0



From m-malladi at ti.com  Wed Mar  5 02:14:21 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Wed, 5 Mar 2025 15:44:21 +0530
Subject: [PATCH net-next v4 2/3] net: ti: icssg-prueth: introduce and use prueth_swdata struct for SWDATA
In-Reply-To: <20250305101422.1908370-1-m-malladi@ti.com>
References: <20250305101422.1908370-1-m-malladi@ti.com>
Message-ID: <20250305101422.1908370-3-m-malladi@ti.com>

From: Roger Quadros <rogerq at kernel.org>

We have different cases for SWDATA (skb, page, cmd, etc)
so it is better to have a dedicated data structure for that.
We can embed the type field inside the struct and use it
to interpret the data in completion handlers.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
Changes from v3 (v4-v3):
- remove SWDATA size information from commit message
- Fix handling of packets for non-skb type inside emac_tx_complete_packets()
- Remove incrementing budget for incorrect swdata type
- use PRUETH_SWDATA_CMD in emac_send_command_sr1()
All the above changes are suggested by Roger Quadros <rogerq at kernel.org> and
Dan Carpenter <dan.carpenter at linaro.org>

 drivers/net/ethernet/ti/icssg/icssg_common.c  | 52 +++++++++++--------
 drivers/net/ethernet/ti/icssg/icssg_prueth.c  |  3 ++
 drivers/net/ethernet/ti/icssg/icssg_prueth.h  | 16 ++++++
 .../net/ethernet/ti/icssg/icssg_prueth_sr1.c  |  9 ++--
 4 files changed, 54 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index acbb79ad8b0c..fee1204db367 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -136,12 +136,12 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_tx;
 	struct netdev_queue *netif_txq;
+	struct prueth_swdata *swdata;
 	struct prueth_tx_chn *tx_chn;
 	unsigned int total_bytes = 0;
 	struct sk_buff *skb;
 	dma_addr_t desc_dma;
 	int res, num_tx = 0;
-	void **swdata;
 
 	tx_chn = &emac->tx_chns[chn];
 
@@ -161,16 +161,11 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
 		desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
 						     desc_dma);
 		swdata = cppi5_hdesc_get_swdata(desc_tx);
-
-		/* was this command's TX complete? */
-		if (emac->is_sr1 && *(swdata) == emac->cmd_data) {
-			prueth_xmit_free(tx_chn, desc_tx);
-			continue;
-		}
-
-		skb = *(swdata);
 		prueth_xmit_free(tx_chn, desc_tx);
+		if (swdata->type != PRUETH_SWDATA_SKB)
+			continue;
 
+		skb = swdata->data.skb;
 		ndev = skb->dev;
 		ndev->stats.tx_packets++;
 		ndev->stats.tx_bytes += skb->len;
@@ -472,9 +467,9 @@ int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
 {
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
 	dma_addr_t desc_dma;
 	dma_addr_t buf_dma;
-	void **swdata;
 
 	buf_dma = page_pool_get_dma_addr(page) + PRUETH_HEADROOM;
 	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
@@ -490,7 +485,8 @@ int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
 	cppi5_hdesc_attach_buf(desc_rx, buf_dma, buf_len, buf_dma, buf_len);
 
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	*swdata = page;
+	swdata->type = PRUETH_SWDATA_PAGE;
+	swdata->data.page = page;
 
 	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, PRUETH_RX_FLOW_DATA,
 					desc_rx, desc_dma);
@@ -539,11 +535,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 	u32 buf_dma_len, pkt_len, port_id = 0;
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
 	dma_addr_t desc_dma, buf_dma;
 	struct page *page, *new_page;
 	struct page_pool *pool;
 	struct sk_buff *skb;
-	void **swdata;
 	u32 *psdata;
 	void *pa;
 	int ret;
@@ -561,7 +557,13 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 
 	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	page = *swdata;
+	if (swdata->type != PRUETH_SWDATA_PAGE) {
+		netdev_err(ndev, "rx_pkt: invalid swdata->type %d\n", swdata->type);
+		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+		return 0;
+	}
+
+	page = swdata->data.page;
 	page_pool_dma_sync_for_cpu(pool, page, 0, PAGE_SIZE);
 	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
 	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
@@ -626,15 +628,18 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma)
 {
 	struct prueth_rx_chn *rx_chn = data;
 	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
 	struct page_pool *pool;
 	struct page *page;
-	void **swdata;
 
 	pool = rx_chn->pg_pool;
 	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	page = *swdata;
-	page_pool_recycle_direct(pool, page);
+	if (swdata->type == PRUETH_SWDATA_PAGE) {
+		page = swdata->data.page;
+		page_pool_recycle_direct(pool, page);
+	}
+
 	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
 }
 
@@ -671,13 +676,13 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
 	struct prueth_emac *emac = netdev_priv(ndev);
 	struct prueth *prueth = emac->prueth;
 	struct netdev_queue *netif_txq;
+	struct prueth_swdata *swdata;
 	struct prueth_tx_chn *tx_chn;
 	dma_addr_t desc_dma, buf_dma;
 	u32 pkt_len, dst_tag_id;
 	int i, ret = 0, q_idx;
 	bool in_tx_ts = 0;
 	int tx_ts_cookie;
-	void **swdata;
 	u32 *epib;
 
 	pkt_len = skb_headlen(skb);
@@ -739,7 +744,8 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
 	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
 	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
 	swdata = cppi5_hdesc_get_swdata(first_desc);
-	*swdata = skb;
+	swdata->type = PRUETH_SWDATA_SKB;
+	swdata->data.skb = skb;
 
 	/* Handle the case where skb is fragmented in pages */
 	cur_desc = first_desc;
@@ -842,15 +848,17 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
 {
 	struct prueth_tx_chn *tx_chn = data;
 	struct cppi5_host_desc_t *desc_tx;
+	struct prueth_swdata *swdata;
 	struct sk_buff *skb;
-	void **swdata;
 
 	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
 	swdata = cppi5_hdesc_get_swdata(desc_tx);
-	skb = *(swdata);
-	prueth_xmit_free(tx_chn, desc_tx);
+	if (swdata->type == PRUETH_SWDATA_SKB) {
+		skb = swdata->data.skb;
+		dev_kfree_skb_any(skb);
+	}
 
-	dev_kfree_skb_any(skb);
+	prueth_xmit_free(tx_chn, desc_tx);
 }
 
 irqreturn_t prueth_rx_irq(int irq, void *dev_id)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 00ed97860547..3ff8c322f9d9 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -1522,6 +1522,9 @@ static int prueth_probe(struct platform_device *pdev)
 
 	np = dev->of_node;
 
+	BUILD_BUG_ON_MSG((sizeof(struct prueth_swdata) > PRUETH_NAV_SW_DATA_SIZE),
+			 "insufficient SW_DATA size");
+
 	prueth = devm_kzalloc(dev, sizeof(*prueth), GFP_KERNEL);
 	if (!prueth)
 		return -ENOMEM;
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index c7b906de18af..3bbabd007129 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -136,6 +136,22 @@ struct prueth_rx_chn {
 	struct page_pool *pg_pool;
 };
 
+enum prueth_swdata_type {
+	PRUETH_SWDATA_INVALID = 0,
+	PRUETH_SWDATA_SKB,
+	PRUETH_SWDATA_PAGE,
+	PRUETH_SWDATA_CMD,
+};
+
+struct prueth_swdata {
+	enum prueth_swdata_type type;
+	union prueth_data {
+		struct sk_buff *skb;
+		struct page *page;
+		u32 cmd;
+	} data;
+};
+
 /* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3)
  * and lower three are lower priority channels or threads.
  */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
index 8f5719a98614..ff5f41bf499e 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
@@ -84,7 +84,7 @@ static int emac_send_command_sr1(struct prueth_emac *emac, u32 cmd)
 	__le32 *data = emac->cmd_data;
 	dma_addr_t desc_dma, buf_dma;
 	struct prueth_tx_chn *tx_chn;
-	void **swdata;
+	struct prueth_swdata *swdata;
 	int ret = 0;
 	u32 *epib;
 
@@ -122,7 +122,8 @@ static int emac_send_command_sr1(struct prueth_emac *emac, u32 cmd)
 
 	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
 	swdata = cppi5_hdesc_get_swdata(first_desc);
-	*swdata = data;
+	swdata->type = PRUETH_SWDATA_CMD;
+	swdata->data.cmd = le32_to_cpu(data[0]);
 
 	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
 	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
@@ -275,9 +276,9 @@ static struct page *prueth_process_rx_mgm(struct prueth_emac *emac,
 	struct net_device *ndev = emac->ndev;
 	struct cppi5_host_desc_t *desc_rx;
 	struct page *page, *new_page;
+	struct prueth_swdata *swdata;
 	dma_addr_t desc_dma, buf_dma;
 	u32 buf_dma_len;
-	void **swdata;
 	int ret;
 
 	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
@@ -299,7 +300,7 @@ static struct page *prueth_process_rx_mgm(struct prueth_emac *emac,
 	}
 
 	swdata = cppi5_hdesc_get_swdata(desc_rx);
-	page = *swdata;
+	page = swdata->data.page;
 	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
 
 	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
-- 
2.43.0



From m-malladi at ti.com  Wed Mar  5 02:14:22 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Wed, 5 Mar 2025 15:44:22 +0530
Subject: [PATCH net-next v4 3/3] net: ti: icssg-prueth: Add XDP support
In-Reply-To: <20250305101422.1908370-1-m-malladi@ti.com>
References: <20250305101422.1908370-1-m-malladi@ti.com>
Message-ID: <20250305101422.1908370-4-m-malladi@ti.com>

From: Roger Quadros <rogerq at kernel.org>

Add native XDP support. We do not support zero copy yet.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
Changes from v3 (v4-v3):
- few cosmetic changes inside emac_xmit_xdp_frame() func
- change xdp_state type to u32 from int
Above changes are suggested by Dan Carpenter <dan.carpenter at linaro.org>
- Few improvements in emac_run_xdp case handling as suggested by 
Roger Quadros <rogerq at kernel.org>

 drivers/net/ethernet/ti/icssg/icssg_common.c | 225 +++++++++++++++++--
 drivers/net/ethernet/ti/icssg/icssg_prueth.c | 128 ++++++++++-
 drivers/net/ethernet/ti/icssg/icssg_prueth.h |  17 ++
 3 files changed, 355 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index fee1204db367..df5da7a98abf 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -98,11 +98,20 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
 {
 	struct cppi5_host_desc_t *first_desc, *next_desc;
 	dma_addr_t buf_dma, next_desc_dma;
+	struct prueth_swdata *swdata;
+	struct page *page;
 	u32 buf_dma_len;
 
 	first_desc = desc;
 	next_desc = first_desc;
 
+	swdata = cppi5_hdesc_get_swdata(desc);
+	if (swdata->type == PRUETH_SWDATA_PAGE) {
+		page = swdata->data.page;
+		page_pool_recycle_direct(page->pp, swdata->data.page);
+		goto free_desc;
+	}
+
 	cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len);
 	k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma);
 
@@ -126,6 +135,7 @@ void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
 		k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
 	}
 
+free_desc:
 	k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc);
 }
 EXPORT_SYMBOL_GPL(prueth_xmit_free);
@@ -139,6 +149,7 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
 	struct prueth_swdata *swdata;
 	struct prueth_tx_chn *tx_chn;
 	unsigned int total_bytes = 0;
+	struct xdp_frame *xdpf;
 	struct sk_buff *skb;
 	dma_addr_t desc_dma;
 	int res, num_tx = 0;
@@ -161,16 +172,28 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
 		desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
 						     desc_dma);
 		swdata = cppi5_hdesc_get_swdata(desc_tx);
-		prueth_xmit_free(tx_chn, desc_tx);
-		if (swdata->type != PRUETH_SWDATA_SKB)
+
+		switch (swdata->type) {
+		case PRUETH_SWDATA_SKB:
+			skb = swdata->data.skb;
+			dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
+			total_bytes += skb->len;
+			napi_consume_skb(skb, budget);
+			break;
+		case PRUETH_SWDATA_XDPF:
+			xdpf = swdata->data.xdpf;
+			dev_sw_netstats_tx_add(ndev, 1, xdpf->len);
+			total_bytes += xdpf->len;
+			xdp_return_frame(xdpf);
+			break;
+		default:
+			netdev_err(ndev, "tx_complete: invalid swdata type %d\n", swdata->type);
+			prueth_xmit_free(tx_chn, desc_tx);
+			ndev->stats.tx_dropped++;
 			continue;
+		}
 
-		skb = swdata->data.skb;
-		ndev = skb->dev;
-		ndev->stats.tx_packets++;
-		ndev->stats.tx_bytes += skb->len;
-		total_bytes += skb->len;
-		napi_consume_skb(skb, budget);
+		prueth_xmit_free(tx_chn, desc_tx);
 		num_tx++;
 	}
 
@@ -529,7 +552,153 @@ void emac_rx_timestamp(struct prueth_emac *emac,
 	ssh->hwtstamp = ns_to_ktime(ns);
 }
 
-static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
+/**
+ * emac_xmit_xdp_frame - transmits an XDP frame
+ * @emac: emac device
+ * @xdpf: data to transmit
+ * @page: page from page pool if already DMA mapped
+ * @q_idx: queue id
+ *
+ * Return: XDP state
+ */
+u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
+			struct xdp_frame *xdpf,
+			struct page *page,
+			unsigned int q_idx)
+{
+	struct cppi5_host_desc_t *first_desc;
+	struct net_device *ndev = emac->ndev;
+	struct prueth_tx_chn *tx_chn;
+	dma_addr_t desc_dma, buf_dma;
+	struct prueth_swdata *swdata;
+	u32 *epib;
+	int ret;
+
+	if (q_idx >= PRUETH_MAX_TX_QUEUES) {
+		netdev_err(ndev, "xdp tx: invalid q_id %d\n", q_idx);
+		return ICSSG_XDP_CONSUMED;	/* drop */
+	}
+
+	tx_chn = &emac->tx_chns[q_idx];
+
+	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+	if (!first_desc) {
+		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
+		goto drop_free_descs;	/* drop */
+	}
+
+	if (page) { /* already DMA mapped by page_pool */
+		buf_dma = page_pool_get_dma_addr(page);
+		buf_dma += xdpf->headroom + sizeof(struct xdp_frame);
+	} else { /* Map the linear buffer */
+		buf_dma = dma_map_single(tx_chn->dma_dev, xdpf->data, xdpf->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
+			netdev_err(ndev, "xdp tx: failed to map data buffer\n");
+			goto drop_free_descs;	/* drop */
+		}
+	}
+
+	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 PRUETH_NAV_PS_DATA_SIZE);
+	cppi5_hdesc_set_pkttype(first_desc, 0);
+	epib = first_desc->epib;
+	epib[0] = 0;
+	epib[1] = 0;
+
+	/* set dst tag to indicate internal qid at the firmware which is at
+	 * bit8..bit15. bit0..bit7 indicates port num for directed
+	 * packets in case of switch mode operation
+	 */
+	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
+	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
+	cppi5_hdesc_attach_buf(first_desc, buf_dma, xdpf->len, buf_dma, xdpf->len);
+	swdata = cppi5_hdesc_get_swdata(first_desc);
+	if (page) {
+		swdata->type = PRUETH_SWDATA_PAGE;
+		swdata->data.page = page;
+	} else {
+		swdata->type = PRUETH_SWDATA_XDPF;
+		swdata->data.xdpf = xdpf;
+	}
+
+	cppi5_hdesc_set_pktlen(first_desc, xdpf->len);
+	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+
+	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+	if (ret) {
+		netdev_err(ndev, "xdp tx: push failed: %d\n", ret);
+		goto drop_free_descs;
+	}
+
+	return ICSSG_XDP_TX;
+
+drop_free_descs:
+	prueth_xmit_free(tx_chn, first_desc);
+	return ICSSG_XDP_CONSUMED;
+}
+EXPORT_SYMBOL_GPL(emac_xmit_xdp_frame);
+
+/**
+ * emac_run_xdp - run an XDP program
+ * @emac: emac device
+ * @xdp: XDP buffer containing the frame
+ * @page: page with RX data if already DMA mapped
+ * @len: Rx descriptor packet length
+ *
+ * Return: XDP state
+ */
+static u32 emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
+			struct page *page, u32 *len)
+{
+	struct net_device *ndev = emac->ndev;
+	struct bpf_prog *xdp_prog;
+	struct xdp_frame *xdpf;
+	u32 pkt_len = *len;
+	u32 act, result;
+	int q_idx, err;
+
+	xdp_prog = READ_ONCE(emac->xdp_prog);
+	act = bpf_prog_run_xdp(xdp_prog, xdp);
+	switch (act) {
+	case XDP_PASS:
+		return ICSSG_XDP_PASS;
+	case XDP_TX:
+		/* Send packet to TX ring for immediate transmission */
+		xdpf = xdp_convert_buff_to_frame(xdp);
+		if (unlikely(!xdpf)) {
+			ndev->stats.tx_dropped++;
+			goto drop;
+		}
+
+		q_idx = smp_processor_id() % emac->tx_ch_num;
+		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
+		if (result == ICSSG_XDP_CONSUMED)
+			goto drop;
+
+		dev_sw_netstats_rx_add(ndev, xdpf->len);
+		return result;
+	case XDP_REDIRECT:
+		err = xdp_do_redirect(emac->ndev, xdp, xdp_prog);
+		if (err)
+			goto drop;
+
+		dev_sw_netstats_rx_add(ndev, pkt_len);
+		return ICSSG_XDP_REDIR;
+	default:
+		bpf_warn_invalid_xdp_action(emac->ndev, xdp_prog, act);
+		fallthrough;
+	case XDP_ABORTED:
+drop:
+		trace_xdp_exception(emac->ndev, xdp_prog, act);
+		fallthrough; /* handle aborts by dropping packet */
+	case XDP_DROP:
+		ndev->stats.rx_dropped++;
+		page_pool_recycle_direct(emac->rx_chns.pg_pool, page);
+		return ICSSG_XDP_CONSUMED;
+	}
+}
+
+static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state)
 {
 	struct prueth_rx_chn *rx_chn = &emac->rx_chns;
 	u32 buf_dma_len, pkt_len, port_id = 0;
@@ -540,10 +709,12 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 	struct page *page, *new_page;
 	struct page_pool *pool;
 	struct sk_buff *skb;
+	struct xdp_buff xdp;
 	u32 *psdata;
 	void *pa;
 	int ret;
 
+	*xdp_state = 0;
 	pool = rx_chn->pg_pool;
 	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
 	if (ret) {
@@ -584,9 +755,21 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
 		goto requeue;
 	}
 
-	/* prepare skb and send to n/w stack */
 	pa = page_address(page);
-	skb = napi_build_skb(pa, PAGE_SIZE);
+	if (emac->xdp_prog) {
+		xdp_init_buff(&xdp, PAGE_SIZE, &rx_chn->xdp_rxq);
+		xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false);
+
+		*xdp_state = emac_run_xdp(emac, &xdp, page, &pkt_len);
+		if (*xdp_state == ICSSG_XDP_PASS)
+			skb = xdp_build_skb_from_buff(&xdp);
+		else
+			goto requeue;
+	} else {
+		/* prepare skb and send to n/w stack */
+		skb = napi_build_skb(pa, PAGE_SIZE);
+	}
+
 	if (!skb) {
 		ndev->stats.rx_dropped++;
 		page_pool_recycle_direct(pool, page);
@@ -849,13 +1032,23 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
 	struct prueth_tx_chn *tx_chn = data;
 	struct cppi5_host_desc_t *desc_tx;
 	struct prueth_swdata *swdata;
+	struct xdp_frame *xdpf;
 	struct sk_buff *skb;
 
 	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
 	swdata = cppi5_hdesc_get_swdata(desc_tx);
-	if (swdata->type == PRUETH_SWDATA_SKB) {
+
+	switch (swdata->type) {
+	case PRUETH_SWDATA_SKB:
 		skb = swdata->data.skb;
 		dev_kfree_skb_any(skb);
+		break;
+	case PRUETH_SWDATA_XDPF:
+		xdpf = swdata->data.xdpf;
+		xdp_return_frame(xdpf);
+		break;
+	default:
+		break;
 	}
 
 	prueth_xmit_free(tx_chn, desc_tx);
@@ -892,15 +1085,18 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
 		PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA;
 	int flow = emac->is_sr1 ?
 		PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
+	int xdp_state_or = 0;
 	int num_rx = 0;
 	int cur_budget;
+	u32 xdp_state;
 	int ret;
 
 	while (flow--) {
 		cur_budget = budget - num_rx;
 
 		while (cur_budget--) {
-			ret = emac_rx_packet(emac, flow);
+			ret = emac_rx_packet(emac, flow, &xdp_state);
+			xdp_state_or |= xdp_state;
 			if (ret)
 				break;
 			num_rx++;
@@ -910,6 +1106,9 @@ int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget)
 			break;
 	}
 
+	if (xdp_state_or & ICSSG_XDP_REDIR)
+		xdp_do_flush();
+
 	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
 		if (unlikely(emac->rx_pace_timeout_ns)) {
 			hrtimer_start(&emac->rx_hrtimer,
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 3ff8c322f9d9..c4a995630eca 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -559,6 +559,33 @@ const struct icss_iep_clockops prueth_iep_clockops = {
 	.perout_enable = prueth_perout_enable,
 };
 
+static int prueth_create_xdp_rxqs(struct prueth_emac *emac)
+{
+	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
+	struct page_pool *pool = emac->rx_chns.pg_pool;
+	int ret;
+
+	ret = xdp_rxq_info_reg(rxq, emac->ndev, 0, emac->napi_rx.napi_id);
+	if (ret)
+		return ret;
+
+	ret = xdp_rxq_info_reg_mem_model(rxq, MEM_TYPE_PAGE_POOL, pool);
+	if (ret)
+		xdp_rxq_info_unreg(rxq);
+
+	return ret;
+}
+
+static void prueth_destroy_xdp_rxqs(struct prueth_emac *emac)
+{
+	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
+
+	if (!xdp_rxq_info_is_reg(rxq))
+		return;
+
+	xdp_rxq_info_unreg(rxq);
+}
+
 static int icssg_prueth_add_mcast(struct net_device *ndev, const u8 *addr)
 {
 	struct net_device *real_dev;
@@ -780,10 +807,14 @@ static int emac_ndo_open(struct net_device *ndev)
 	if (ret)
 		goto free_tx_ts_irq;
 
-	ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
+	ret = prueth_create_xdp_rxqs(emac);
 	if (ret)
 		goto reset_rx_chn;
 
+	ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
+	if (ret)
+		goto destroy_xdp_rxqs;
+
 	for (i = 0; i < emac->tx_ch_num; i++) {
 		ret = k3_udma_glue_enable_tx_chn(emac->tx_chns[i].tx_chn);
 		if (ret)
@@ -809,6 +840,8 @@ static int emac_ndo_open(struct net_device *ndev)
 	 * any SKB for completion. So set false to free_skb
 	 */
 	prueth_reset_tx_chan(emac, i, false);
+destroy_xdp_rxqs:
+	prueth_destroy_xdp_rxqs(emac);
 reset_rx_chn:
 	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false);
 free_tx_ts_irq:
@@ -879,7 +912,7 @@ static int emac_ndo_stop(struct net_device *ndev)
 	k3_udma_glue_tdown_rx_chn(emac->rx_chns.rx_chn, true);
 
 	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, true);
-
+	prueth_destroy_xdp_rxqs(emac);
 	napi_disable(&emac->napi_rx);
 	hrtimer_cancel(&emac->rx_hrtimer);
 
@@ -1024,6 +1057,93 @@ static int emac_ndo_vlan_rx_del_vid(struct net_device *ndev,
 	return 0;
 }
 
+/**
+ * emac_xdp_xmit - Implements ndo_xdp_xmit
+ * @dev: netdev
+ * @n: number of frames
+ * @frames: array of XDP buffer pointers
+ * @flags: XDP extra info
+ *
+ * Return: number of frames successfully sent. Failed frames
+ * will be free'ed by XDP core.
+ *
+ * For error cases, a negative errno code is returned and no-frames
+ * are transmitted (caller must handle freeing frames).
+ **/
+static int emac_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
+			 u32 flags)
+{
+	struct prueth_emac *emac = netdev_priv(dev);
+	struct net_device *ndev = emac->ndev;
+	struct xdp_frame *xdpf;
+	unsigned int q_idx;
+	int nxmit = 0;
+	u32 err;
+	int i;
+
+	q_idx = smp_processor_id() % emac->tx_ch_num;
+
+	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+		return -EINVAL;
+
+	for (i = 0; i < n; i++) {
+		xdpf = frames[i];
+		err = emac_xmit_xdp_frame(emac, xdpf, NULL, q_idx);
+		if (err != ICSSG_XDP_TX) {
+			ndev->stats.tx_dropped++;
+			break;
+		}
+		nxmit++;
+	}
+
+	return nxmit;
+}
+
+/**
+ * emac_xdp_setup - add/remove an XDP program
+ * @emac: emac device
+ * @bpf: XDP program
+ *
+ * Return: Always 0 (Success)
+ **/
+static int emac_xdp_setup(struct prueth_emac *emac, struct netdev_bpf *bpf)
+{
+	struct bpf_prog *prog = bpf->prog;
+	xdp_features_t val;
+
+	val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+	      NETDEV_XDP_ACT_NDO_XMIT;
+	xdp_set_features_flag(emac->ndev, val);
+
+	if (!emac->xdpi.prog && !prog)
+		return 0;
+
+	WRITE_ONCE(emac->xdp_prog, prog);
+
+	xdp_attachment_setup(&emac->xdpi, bpf);
+
+	return 0;
+}
+
+/**
+ * emac_ndo_bpf - implements ndo_bpf for icssg_prueth
+ * @ndev: network adapter device
+ * @bpf: XDP program
+ *
+ * Return: 0 on success, error code on failure.
+ **/
+static int emac_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	switch (bpf->command) {
+	case XDP_SETUP_PROG:
+		return emac_xdp_setup(emac, bpf);
+	default:
+		return -EINVAL;
+	}
+}
+
 static const struct net_device_ops emac_netdev_ops = {
 	.ndo_open = emac_ndo_open,
 	.ndo_stop = emac_ndo_stop,
@@ -1038,6 +1158,8 @@ static const struct net_device_ops emac_netdev_ops = {
 	.ndo_fix_features = emac_ndo_fix_features,
 	.ndo_vlan_rx_add_vid = emac_ndo_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid = emac_ndo_vlan_rx_del_vid,
+	.ndo_bpf = emac_ndo_bpf,
+	.ndo_xdp_xmit = emac_xdp_xmit,
 };
 
 static int prueth_netdev_init(struct prueth *prueth,
@@ -1066,6 +1188,8 @@ static int prueth_netdev_init(struct prueth *prueth,
 	emac->prueth = prueth;
 	emac->ndev = ndev;
 	emac->port_id = port;
+	emac->xdp_prog = NULL;
+	emac->ndev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
 	emac->cmd_wq = create_singlethread_workqueue("icssg_cmd_wq");
 	if (!emac->cmd_wq) {
 		ret = -ENOMEM;
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 3bbabd007129..1dd76e2adfcd 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -8,6 +8,8 @@
 #ifndef __NET_TI_ICSSG_PRUETH_H
 #define __NET_TI_ICSSG_PRUETH_H
 
+#include <linux/bpf.h>
+#include <linux/bpf_trace.h>
 #include <linux/etherdevice.h>
 #include <linux/genalloc.h>
 #include <linux/if_vlan.h>
@@ -134,6 +136,7 @@ struct prueth_rx_chn {
 	unsigned int irq[ICSSG_MAX_RFLOWS];	/* separate irq per flow */
 	char name[32];
 	struct page_pool *pg_pool;
+	struct xdp_rxq_info xdp_rxq;
 };
 
 enum prueth_swdata_type {
@@ -141,6 +144,7 @@ enum prueth_swdata_type {
 	PRUETH_SWDATA_SKB,
 	PRUETH_SWDATA_PAGE,
 	PRUETH_SWDATA_CMD,
+	PRUETH_SWDATA_XDPF,
 };
 
 struct prueth_swdata {
@@ -149,6 +153,7 @@ struct prueth_swdata {
 		struct sk_buff *skb;
 		struct page *page;
 		u32 cmd;
+		struct xdp_frame *xdpf;
 	} data;
 };
 
@@ -159,6 +164,12 @@ struct prueth_swdata {
 
 #define PRUETH_MAX_TX_TS_REQUESTS	50 /* Max simultaneous TX_TS requests */
 
+/* XDP BPF state */
+#define ICSSG_XDP_PASS           0
+#define ICSSG_XDP_CONSUMED       BIT(0)
+#define ICSSG_XDP_TX             BIT(1)
+#define ICSSG_XDP_REDIR          BIT(2)
+
 /* Minimum coalesce time in usecs for both Tx and Rx */
 #define ICSSG_MIN_COALESCE_USECS 20
 
@@ -227,6 +238,8 @@ struct prueth_emac {
 	unsigned long rx_pace_timeout_ns;
 
 	struct netdev_hw_addr_list vlan_mcast_list[MAX_VLAN_ID];
+	struct bpf_prog *xdp_prog;
+	struct xdp_attachment_info xdpi;
 };
 
 /* The buf includes headroom compatible with both skb and xdpf */
@@ -465,5 +478,9 @@ void prueth_put_cores(struct prueth *prueth, int slice);
 
 /* Revision specific helper */
 u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns);
+u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
+			struct xdp_frame *xdpf,
+			struct page *page,
+			unsigned int q_idx);
 
 #endif /* __NET_TI_ICSSG_PRUETH_H */
-- 
2.43.0



From kabel at kernel.org  Wed Mar  5 02:18:23 2025
From: kabel at kernel.org (Marek =?utf-8?B?QmVow7pu?=)
Date: Wed, 5 Mar 2025 11:18:23 +0100
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <20250305101025.2279951-2-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
Message-ID: <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>

Hi George,

why is armada_37xx_wdt also here?
The stop function in that driver may not sleep.

Marek


From heiko at sntech.de  Wed Mar  5 02:21:48 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Wed, 05 Mar 2025 11:21:48 +0100
Subject: [PATCH 6/8] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF
 region
In-Reply-To: <20250301104724.36399-1-ziyao@disroot.org>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104724.36399-1-ziyao@disroot.org>
Message-ID: <2583035.OBFZWjSADL@diego>

Hi,

Am Samstag, 1. M?rz 2025, 11:47:24 MEZ schrieb Yao Zi:
> These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
> tuning purpose. Add their definitions and register them in driver if
> corresponding GRF is available.

(no critique, just an observation :-) )

this puts a completely new meaning on the "general register files"
as dumping ground ;-) .

Whoever got the idea of making sdmm/sdio tuning controls part
of GRFs that are supposed display and/or video encoder parts :-D


> GRFs are looked up by compatible to simplify devicetree binding.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---

>  static int __init clk_rk3528_probe(struct platform_device *pdev)
>  {
> +	unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
> +	unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
> +	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
>  	struct rockchip_clk_provider *ctx;
>  	struct device *dev = &pdev->dev;
>  	struct device_node *np = dev->of_node;
> -	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
> -	unsigned long nr_clks;
> +	struct regmap *vo_grf, *vpu_grf;
>  	void __iomem *reg_base;
> -
> -	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
> -					       nr_branches) + 1;
> +	unsigned long nr_clks;
>  
>  	reg_base = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(reg_base))
>  		return dev_err_probe(dev, PTR_ERR(reg_base),
>  				     "could not map cru region");
>  
> +	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
> +					       nr_branches) + 1;
> +
> +	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
> +	if (!IS_ERR(vo_grf))

for readability, please make this into something like
	if (!IS_ERR(vo_grf)) {
		nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
							   nr_vo_branches) + 1;
		nr_clks = max(nr_vo_clks, nr_clks);
	}

> +	else if (PTR_ERR(vo_grf) != ENODEV)
> +		return dev_err_probe(dev, PTR_ERR(vo_grf),
> +				     "failed to look up VO GRF\n");
> +
> +	vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
> +	if (!IS_ERR(vpu_grf))
> +		nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
> +							   nr_vpu_branches) + 1,
> +			      nr_clks);

same here please

> +	else if (PTR_ERR(vpu_grf) != ENODEV)
> +		return dev_err_probe(dev, PTR_ERR(vpu_grf),
> +				     "failed to look up VPU GRF\n");
> +
>  	ctx = rockchip_clk_init(np, reg_base, nr_clks);
>  	if (IS_ERR(ctx))
>  		return dev_err_probe(dev, PTR_ERR(ctx),

Thanks
Heiko




From miquel.raynal at bootlin.com  Wed Mar  5 02:22:09 2025
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 05 Mar 2025 11:22:09 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <20250305100134.1171124-1-manikandan.m@microchip.com> (Manikandan
	Muralidharan's message of "Wed, 5 Mar 2025 15:31:33 +0530")
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
Message-ID: <87ikonydym.fsf@bootlin.com>

On 05/03/2025 at 15:31:33 +0530, Manikandan Muralidharan <manikandan.m at microchip.com> wrote:

> From: Varshini Rajendran <varshini.rajendran at microchip.com>
>
> EUI identifier and the MAC Address of the Ethernet Interface is stored
> after the SFDP table of contents starting at address 0x260 in the
> QSPI memory.
> Register the entire SFDP region read by the spi-nor (nor->sfdp) into the
> NVMEM framework and read the MAC Address when requested using the nvmem
> properties in the DT by the net drivers.
>
> In kernel the Ethernet MAC address relied on U-Boot env variables or
> generated a random address, which posed challenges for boards without
> on-board EEPROMs or with multiple Ethernet ports.
> This change ensures consistent and reliable MAC address retrieval from QSPI,
> benefiting boards like the sama5d29 curiosity and sam9x75 curiosity.

Do you mean spi-nor have a programmable area in their SFDP table? Isn't
this supposed to be a read-only area written once in factory?

I am not a big fan of exposing the whole SFDP area. I would suggest to
expose just the MAC address. You can make use of nvmem layout drivers if
that is needed.

Thanks,
Miqu?l


From fujita.tomonori at gmail.com  Wed Mar  5 02:24:03 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed, 05 Mar 2025 19:24:03 +0900 (JST)
Subject: [PATCH v3 5/5] rust: Add warn_on and warn_on_once
In-Reply-To: <Z8gOkeJ8o2pMCwGu@google.com>
References: <20250213135759.190006-1-fujita.tomonori@gmail.com>
	<20250213135759.190006-6-fujita.tomonori@gmail.com>
	<Z8gOkeJ8o2pMCwGu@google.com>
Message-ID: <20250305.192403.996225631653343672.fujita.tomonori@gmail.com>

On Wed, 5 Mar 2025 08:42:57 +0000
Alice Ryhl <aliceryhl at google.com> wrote:

> On Thu, Feb 13, 2025 at 10:57:59PM +0900, FUJITA Tomonori wrote:
>> Add warn_on and warn_on_once macros. Wrapping the C's WARN_* and BUG_*
>> macros doesn't work so this uses the assembly code exported by the C
>> side via ARCH_WARN_ASM macro. Like the static branch code, this
>> generates the assembly code for rust at compile time by using the C
>> preprocessor.
>> 
>> file()! macro doesn't work for the Rust inline assembly in the same
>> way as __FILE__ for the C inline assembly. So the code to handle a
>> file name is different from the C assembly code (similar to the
>> arm64/loongarch assembly).
> 
> Nit: Should be file!() not file()!.

Ops, thanks.

Actually, the above comment is obsolete. With your solution in the
previous mail, I can remove the asm code for the file name. I'll
remove the comment.


>> diff --git a/rust/kernel/.gitignore b/rust/kernel/.gitignore
>> index 6ba39a178f30..f1d7f4225332 100644
>> --- a/rust/kernel/.gitignore
>> +++ b/rust/kernel/.gitignore
>> @@ -1,3 +1,5 @@
>>  # SPDX-License-Identifier: GPL-2.0
>>  
>>  /generated_arch_static_branch_asm.rs
>> +/generated_arch_warn_asm.rs
>> +/generated_arch_reachable_asm.rs
>> \ No newline at end of file
> 
> There should be a newline.

Ah, I'll fix.

>> +++ b/rust/kernel/bug.rs
>> @@ -0,0 +1,100 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +// Copyright (C) 2024 FUJITA Tomonori
> 
> 2025?

I'll add.

>> +#[macro_export]
>> +#[doc(hidden)]
>> +#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
>> +macro_rules! warn_flags {
>> +    ($flags:expr) => {
>> +        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
>> +        // SAFETY: Just an FFI call.
>> +        #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
>> +        unsafe {
>> +            $crate::asm!(concat!(
>> +                "/* {size} */",
>> +                ".pushsection .rodata.str1.1, \"aMS\", at progbits, 1\n",
>> +                "111:\t .string ", "\"", file!(), "\"\n",
>> +                ".popsection\n",
>> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
>> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
>> +            line = const line!(),
>> +            flags = const FLAGS,
>> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
>> +            );
>> +        }
>> +        // SAFETY: Just an FFI call.
>> +        #[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
>> +        unsafe {
>> +            $crate::asm!(
>> +            concat!(
>> +                "/* {size} */",
>> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
>> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
>> +            flags = const FLAGS,
>> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
>> +            );
>> +        }
> 
> I generally prefer to have the cfgs on the macro rather in its
> expansion. That avoids emitting a lot of code that is not actually used.

You prefer the following?

#[cfg(all(CONFIG_BUG, CONFIG_DEBUG_BUGVERBOSE, not(CONFIG_UML)))]
macro_rules! warn_flags {
...
}

#[cfg(all(CONFIG_BUG, not(CONFIG_DEBUG_BUGVERBOSE), not(CONFIG_UML)))]
macro_rules! warn_flags {
...
}

>> +#[doc(hidden)]
>> +#[macro_export]
>> +macro_rules! bugflag_taint {
>> +    ($taint:expr) => {
>> +        $taint << 8
>> +    };
>> +}
> 
> This could just be a const fn.

Yeah, would a const fn be preferable?

>> +/// Report a warning only once.
>> +#[macro_export]
>> +macro_rules! warn_on_once {
>> +    ($cond:expr) => {
>> +        if $cond {
>> +            $crate::warn_flags!(
>> +                $crate::bindings::BUGFLAG_ONCE
>> +                    | $crate::bugflag_taint!($crate::bindings::TAINT_WARN)
> 
> Or maybe a constant?
> 
> const WARN_ON_ONCE_FLAGS: u32 = bindings::BUGFLAG_ONCE | (bindings::TAINT_WARN << 8);

Ok, but you prefer "<< 8" than using const fn bugflag_taint()?

> $crate::warn_flags!($crate::bug::WARN_ON_ONCE_FLAGS);


From mwalle at kernel.org  Wed Mar  5 02:24:47 2025
From: mwalle at kernel.org (Michael Walle)
Date: Wed, 05 Mar 2025 11:24:47 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <20250305100134.1171124-1-manikandan.m@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
Message-ID: <D889CRJC6W19.2LDQCDVG7BLNG@kernel.org>

On Wed Mar 5, 2025 at 11:01 AM CET, Manikandan Muralidharan wrote:
> From: Varshini Rajendran <varshini.rajendran at microchip.com>
>
> EUI identifier and the MAC Address of the Ethernet Interface is stored
> after the SFDP table of contents starting at address 0x260 in the
> QSPI memory.
> Register the entire SFDP region read by the spi-nor (nor->sfdp) into the
> NVMEM framework and read the MAC Address when requested using the nvmem
> properties in the DT by the net drivers.
>
> In kernel the Ethernet MAC address relied on U-Boot env variables or
> generated a random address, which posed challenges for boards without
> on-board EEPROMs or with multiple Ethernet ports.
> This change ensures consistent and reliable MAC address retrieval from QSPI,
> benefiting boards like the sama5d29 curiosity and sam9x75 curiosity.
>
> Signed-off-by: Varshini Rajendran <varshini.rajendran at microchip.com>
> [manikandan.m at microchip.com: Integrate the nvmem->read callback framework]
> Signed-off-by: Manikandan Muralidharan <manikandan.m at microchip.com>
> ---
>  drivers/mtd/spi-nor/sst.c | 62 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>
> diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
> index 175211fe6a5e..a0abf201ad41 100644
> --- a/drivers/mtd/spi-nor/sst.c
> +++ b/drivers/mtd/spi-nor/sst.c
> @@ -5,6 +5,7 @@
>   */
>  
>  #include <linux/mtd/spi-nor.h>
> +#include <linux/nvmem-provider.h>
>  
>  #include "core.h"
>  
> @@ -13,6 +14,8 @@
>  
>  #define SST26VF_CR_BPNV		BIT(3)
>  
> +#define SST26VF_SFDP_EUI48	0x30
> +
>  static int sst26vf_nor_lock(struct spi_nor *nor, loff_t ofs, u64 len)
>  {
>  	return -EOPNOTSUPP;
> @@ -56,8 +59,67 @@ static int sst26vf_nor_late_init(struct spi_nor *nor)
>  	return 0;
>  }
>  
> +/**
> + * sst26vf_sfdp_mac_addr_read() - check if the EUI-48 MAC Address is programmed
> + * and read the data from the prestored SFDP data
> + *
> + * @priv: User context passed to read callbacks.
> + * @offset: Offset within the NVMEM device.
> + * @val: pointer where to fill the ethernet address
> + * @bytes: Length of the NVMEM cell
> + *
> + * Return: 0 on success, -EINVAL  otherwise.
> + */
> +static int sst26vf_sfdp_mac_addr_read(void *priv, unsigned int off,
> +				      void *val, size_t bytes)
> +{
> +	struct spi_nor *nor = priv;
> +	struct sfdp *sfdp = nor->sfdp;
> +	loff_t offset = off;
> +	size_t sfdp_size;
> +
> +	/*
> +	 * Check if the EUI-48 MAC address is programmed in the next six address
> +	 * locations.
> +	 * @off is programmed in the DT and stores the start of MAC Address
> +	 * byte, (off - 1) stores the bit length of the Extended Unique
> +	 * Identifier
> +	 */
> +	if (SST26VF_SFDP_EUI48 != *((u8 *)sfdp->dwords + (offset - 1)))
> +		return -EINVAL;

What happens if you read at a different offset? You're exposing
the entire SFDP region. What happens if there is a 0x30 at a
different location?

> +
> +	sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords);
> +	memory_read_from_buffer(val, bytes, &offset, sfdp->dwords,
> +				sfdp_size);
> +	return 0;
> +}
> +
> +static struct nvmem_config sst26vf_sfdp_nvmem_config = {
> +	.word_size = 1,
> +	.stride = 1,
> +};
> +
> +static int sst26vf_nor_post_sfdp(struct spi_nor *nor)
> +{
> +	struct nvmem_device *nvmem;
> +
> +	sst26vf_sfdp_nvmem_config.dev = nor->dev;
> +	sst26vf_sfdp_nvmem_config.size = nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords);
> +	sst26vf_sfdp_nvmem_config.priv = nor;
> +	sst26vf_sfdp_nvmem_config.reg_read = sst26vf_sfdp_mac_addr_read;
> +
> +	nvmem = devm_nvmem_register(nor->dev, &sst26vf_sfdp_nvmem_config);
> +	if (IS_ERR(nvmem)) {
> +		dev_err(nor->dev, "failed to register NVMEM device: %ld\n", PTR_ERR(nvmem));
> +		return PTR_ERR(nvmem);

I don't think it makes sense to have this one-off in a particular
driver. If at all, this should be handled in the core. Sorry, but
this really looks like an ugly hack.

-michael

> +	}
> +
> +	return 0;
> +}
> +
>  static const struct spi_nor_fixups sst26vf_nor_fixups = {
>  	.late_init = sst26vf_nor_late_init,
> +	.post_sfdp = sst26vf_nor_post_sfdp,
>  };
>  
>  static const struct flash_info sst_nor_parts[] = {



From sudeep.holla at arm.com  Wed Mar  5 02:25:42 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 5 Mar 2025 10:25:42 +0000
Subject: [PATCH v2] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <Z8fv3X0Pivh8zbMg@cse-cd02-lnx.ap.qualcomm.com>
References: <20241120103749.1450017-1-ping.bai@nxp.com>
 <Z8fv3X0Pivh8zbMg@cse-cd02-lnx.ap.qualcomm.com>
Message-ID: <20250305102542.36q7lmctx5jm4mg7@bogus>

Hi Jacky,

I wasn't Cc-ed on the original patch.

I was searching to provide feedback but couldn't find one.

On Wed, Mar 05, 2025 at 02:31:57PM +0800, Yuanjie Yang wrote:
> On Wed, Nov 20, 2024 at 06:37:49PM +0800, Jacky Bai wrote:
> > With 'nosmp' or 'maxcpus=0' boot command line parameters,
> > the 'cpu_present_mask' may not be the same as 'cpu_possible_mask'.
> > 
> > In current psci cpuidle driver init, for_each_possible_cpu()
> > is used to init the cpuidle for each possible CPU. but in
> > drivers/base/cpu.c ->cpu_dev_register_generic(),
> > for_each_present_cpu() is used to register cpu device for
> > present CPUs.
> > 
> > When boot system with 'nosmp' or 'maxcpus=0', the cpuidle driver
> > init failed due to no valid CPU device sysfs node for non-boot CPUs.
> > 
> > [ 0.182993] Failed to register cpuidle device for cpu1
> > 
> > Use for_each_present_cpu() to register cpuidle only for present
> > CPUs.
> > 

Can you reword it something like
"

for_each_possible_cpu() is currently used to initialize cpuidle in the
PSCI cpuidle driver.

However, in cpu_dev_register_generic(), for_each_present_cpu() is used
to register CPU devices which means the CPU devices are only registered
for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, leading to the
failure:

  |  Failed to register cpuidle device for cpu1

Change for_each_possible_cpu() to for_each_present_cpu() in the PSCI
cpuidle driver to ensure it only registers cpuidle devices for CPUs
that are actually present.

"

With that, you can add:

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

Please cc Ulf Hansson <ulf.hansson at linaro.org> as well. Either him or
Rafael can then pick up the patch.

-- 
Regards,
Sudeep


From ping.bai at nxp.com  Wed Mar  5 02:29:30 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Wed, 5 Mar 2025 10:29:30 +0000
Subject: [PATCH v2] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <20250305102542.36q7lmctx5jm4mg7@bogus>
References: <20241120103749.1450017-1-ping.bai@nxp.com>
 <Z8fv3X0Pivh8zbMg@cse-cd02-lnx.ap.qualcomm.com>
 <20250305102542.36q7lmctx5jm4mg7@bogus>
Message-ID: <AS8PR04MB8642344F9CA6D423D068E46C87CB2@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2] cpuidle: psci: Init cpuidle only for present CPUs
> 
> Hi Jacky,
> 
> I wasn't Cc-ed on the original patch.
> 
> I was searching to provide feedback but couldn't find one.
> 
> On Wed, Mar 05, 2025 at 02:31:57PM +0800, Yuanjie Yang wrote:
> > On Wed, Nov 20, 2024 at 06:37:49PM +0800, Jacky Bai wrote:
> > > With 'nosmp' or 'maxcpus=0' boot command line parameters, the
> > > 'cpu_present_mask' may not be the same as 'cpu_possible_mask'.
> > >
> > > In current psci cpuidle driver init, for_each_possible_cpu() is used
> > > to init the cpuidle for each possible CPU. but in drivers/base/cpu.c
> > > ->cpu_dev_register_generic(),
> > > for_each_present_cpu() is used to register cpu device for present
> > > CPUs.
> > >
> > > When boot system with 'nosmp' or 'maxcpus=0', the cpuidle driver
> > > init failed due to no valid CPU device sysfs node for non-boot CPUs.
> > >
> > > [ 0.182993] Failed to register cpuidle device for cpu1
> > >
> > > Use for_each_present_cpu() to register cpuidle only for present
> > > CPUs.
> > >
> 
> Can you reword it something like
> "
> 
> for_each_possible_cpu() is currently used to initialize cpuidle in the PSCI
> cpuidle driver.
> 
> However, in cpu_dev_register_generic(), for_each_present_cpu() is used to
> register CPU devices which means the CPU devices are only registered for
> present CPUs and not all possible CPUs.
> 
> With nosmp or maxcpus=0, only the boot CPU is present, leading to the
> failure:
> 
>   |  Failed to register cpuidle device for cpu1
> 
> Change for_each_possible_cpu() to for_each_present_cpu() in the PSCI
> cpuidle driver to ensure it only registers cpuidle devices for CPUs that are
> actually present.
> 
> "
> 
> With that, you can add:
> 
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> 
> Please cc Ulf Hansson <ulf.hansson at linaro.org> as well. Either him or Rafael
> can then pick up the patch.
> 

Sorry, I should Cc you in the list. Thank you for your suggestion, I will resolve it in v3.

BR

> --
> Regards,
> Sudeep


From ericwouds at gmail.com  Wed Mar  5 02:29:34 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:34 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
Message-ID: <20250305102949.16370-1-ericwouds@gmail.com>

This patchset makes it possible to set up a software fastpath between
bridged interfaces. One patch adds the flow rule for the hardware
fastpath. This creates the possibility to have a hardware offloaded
fastpath between bridged interfaces. More patches are added to solve
issues found with the existing code.

To set up the fastpath with offloading, add this extra flowtable:

table bridge filter {
        flowtable fb {
                hook ingress priority filter
                devices = { lan0, lan1, lan2, lan3, lan4, wlan0, wlan1 }
                flags offload
        }
        chain forward {
                type filter hook forward priority filter; policy accept;
		ct state established flow add @fb
        }
}

Creating a separate fastpath for bridges.

         forward fastpath bypass
 .----------------------------------------.
/                                          \
|                        IP - forwarding    |
|                       /                \  v
|                      /                  wan ...
|                     /
|                     |
|                     |
|                   brlan.1
|                     |
|    +-------------------------------+
|    |           vlan 1              |
|    |                               |
|    |     brlan (vlan-filtering)    |
|    +---------------+               |
|    |  DSA-SWITCH   |               |
|    |               |    vlan 1     |
|    |               |      to       |
|    |   vlan 1      |   untagged    |
|    +---------------+---------------+
.         /                   \
 ------>lan0                 wlan1
        .  ^                 ^
        .  |                 |
        .  \_________________/
        .  bridge fastpath bypass
        .
        ^
     vlan 1 tagged packets

To have the ability to handle xmit direct with outgoing encaps in the
bridge fastpass bypass, we need to be able to handle them without going
through vlan/pppoe devices. So I've applied, amended and squashed wenxu's
patchset. This patch also makes it possible to egress from vlan-filtering
brlan to lan0 with vlan tagged packets, if the bridge master port is doing
the vlan tagging, instead of the vlan-device. Without this patch, this is
not possible in the bridge-fastpath and also not in the forward-fastpath,
as seen in the figure above.

There are also some more fixes for filling in the forward path. These
fixes also apply to for the forward-fastpath. They include handling
DEV_PATH_MTK_WDMA in nft_dev_path_info(). There are now 2 patches for
avoiding ingress_vlans bit set for bridged dsa user ports and foreign
(dsa) ports.

Another patch introduces DEV_PATH_BR_VLAN_KEEP_HW, needed for the
bridge-fastpath only.

Conntrack bridge only tracks untagged and 802.1q. To make the bridge
fastpath experience more similar to the forward fastpath experience,
I've added double vlan, pppoe and pppoe-in-q tagged packets to bridge
conntrack and to bridge filter chain.

Note: While testing direct transmit in the software forward-fastpath,
without the capability of setting the offload flag, it is sometimes useful
to enslave the wan interface to another bridge, brwan. This will make
sure both directions of the software forward-fastpath use direct transmit,
which also happens when the offload flag is set.

I have send RFC v2 as I previously only owned a dsa device. I now have
obtained a switchdev supporting SWITCHDEV_OBJ_ID_PORT_VLAN, and found
there was more to do to handle the ingress_vlans bit and corresponding
vlan encap.

I send v4 and above as non-RFC as the previous 2 RFC's did not get any
comment.

Changes in v9:
- No changes, resend to netfilter

Changes in v8:
- Added commit on top: Avoid zero-length arrays in struct pppoe_hdr.

Changes in v7:
- Inside br_vlan_fill_forward_path_pvid(), replaced usage of
   br_vlan_group() with br_vlan_group_rcu() and
   nbp_vlan_group() with nbp_vlan_group_rcu().

Changes in v6:
- Conntrack double vlan and pppoe patch: Set ph and vhdr after the calls
   to pskb_may_pull().

Changes in v5:
- Conntrack double vlan and pppoe patch: Moved pskb_may_pull() up to the
   first switch statement, to the start of the cases. Removed the second
   switch statement. Replaced 0xffffffff with U32_MAX.
- Added patch removing hw_outdev, out.hw_ifindex and out.hw_ifidx members.
- Fix error path returned from nft_flow_offload_bridge_init().
- Cosmetics.

Changes in v4:
- Added !CONFIG_NET_SWITCHDEV version of
   br_switchdev_port_vlan_no_foreign_add().

Changes in v3:
- Squashed the two 'port to port' patches to avoid build errors when only
   one of the two commits is applied.

Changes in v2:
- Introduce DEV_PATH_BR_VLAN_KEEP_HW for use in the bridge-fastpath only.
   It is needed for switchdevs supporting SWITCHDEV_OBJ_ID_PORT_VLAN.
- Different approach for handling BR_VLFLAG_ADDED_BY_SWITCHDEV in
   br_vlan_fill_forward_path_mode() for foreign devices. Introduce
   SWITCHDEV_F_NO_FOREIGN, BR_VLFLAG_TAGGING_BY_SWITCHDEV and
   br_switchdev_port_vlan_no_foreign_add(). The latter function can be
   used to make sure the vlan was added to a switchdev native device.
   When that fails, adding the vlan with br_switchdev_port_vlan_add()
   means it was added to a switchdev foreign device.
- Clear ingress_vlans bit and corresponding encap for dsa user ports.
- Add check for ingress_vlans bit to nft_dev_fill_bridge_path().
- Adapted cover letter description to make clear the patches apply
   to software fastpath, making hardware-offloaded fastpath possible.
- Fixed clang error for vlan_hdr * and struct ppp_hdr * by adding block.
- Updated !CONFIG_BRIDGE_VLAN_FILTERING version of
   br_vlan_fill_forward_path_pvid().
- Removed erroneous check netif_is_bridge_master(ctx->dev) from
   dev_fill_bridge_path().
- Cosmetic changes.

Eric Woudstra (15):
  net: pppoe: avoid zero-length arrays in struct pppoe_hdr
  netfilter: nf_flow_table_offload: Add nf_flow_encap_push() for xmit
    direct
  netfilter: flow: remove hw_outdev, out.hw_ifindex and out.hw_ifidx
  netfilter: bridge: Add conntrack double vlan and pppoe
  netfilter: nft_chain_filter: Add bridge double vlan and pppoe
  bridge: Add filling forward path from port to port
  net: core: dev: Add dev_fill_bridge_path()
  netfilter :nf_flow_table_offload: Add nf_flow_rule_bridge()
  netfilter: nf_flow_table_inet: Add nf_flowtable_type flowtable_bridge
  netfilter: nft_flow_offload: Add NFPROTO_BRIDGE to validate
  netfilter: nft_flow_offload: Add DEV_PATH_MTK_WDMA to
    nft_dev_path_info()
  netfilter: nft_flow_offload: No ingress_vlan forward info for dsa user
    port
  bridge: No DEV_PATH_BR_VLAN_UNTAG_HW for dsa foreign
  bridge: Introduce DEV_PATH_BR_VLAN_KEEP_HW for bridge-fastpath
  netfilter: nft_flow_offload: Add bridgeflow to nft_flow_offload_eval()

 drivers/net/ppp/pppoe.c                    |   2 +-
 include/linux/netdevice.h                  |   3 +
 include/net/netfilter/nf_flow_table.h      |   5 +-
 include/net/switchdev.h                    |   1 +
 include/uapi/linux/if_pppox.h              |   4 +
 net/bridge/br_device.c                     |  23 ++-
 net/bridge/br_private.h                    |  12 ++
 net/bridge/br_switchdev.c                  |  15 ++
 net/bridge/br_vlan.c                       |  29 +++-
 net/bridge/netfilter/nf_conntrack_bridge.c |  83 ++++++++--
 net/core/dev.c                             |  66 ++++++--
 net/netfilter/nf_flow_table_core.c         |   1 -
 net/netfilter/nf_flow_table_inet.c         |  13 ++
 net/netfilter/nf_flow_table_ip.c           |  96 +++++++++++-
 net/netfilter/nf_flow_table_offload.c      |  15 +-
 net/netfilter/nft_chain_filter.c           |  20 ++-
 net/netfilter/nft_flow_offload.c           | 168 +++++++++++++++++++--
 net/switchdev/switchdev.c                  |   2 +-
 18 files changed, 497 insertions(+), 61 deletions(-)

-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:36 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:36 +0100
Subject: [PATCH v9 nf 02/15] netfilter: nf_flow_table_offload: Add nf_flow_encap_push() for xmit direct
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-3-ericwouds@gmail.com>

Loosely based on wenxu's patches:

"nf_flow_table_offload: offload the vlan/PPPoE encap in the flowtable".

Fixed double vlan and pppoe packets, almost entirely rewriting the patch.

After this patch, it is possible to transmit packets in the fastpath with
outgoing encaps, without using vlan- and/or pppoe-devices.

This makes it possible to use more different kinds of network setups.
For example, when bridge tagging is used to egress vlan tagged
packets using the forward fastpath. Another example is passing 802.1q
tagged packets through a bridge using the bridge fastpath.

This also makes the software fastpath process more similar to the
hardware offloaded fastpath process, where encaps are also pushed.

After applying this patch, always info->outdev = info->hw_outdev,
so the netfilter code can be further cleaned up by removing:
 * hw_outdev from struct nft_forward_info
 * out.hw_ifindex from struct nf_flow_route
 * out.hw_ifidx from struct flow_offload_tuple

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nf_flow_table_ip.c | 96 +++++++++++++++++++++++++++++++-
 net/netfilter/nft_flow_offload.c |  6 +-
 2 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 8cd4cf7ae211..d0c3c459c4d2 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -306,6 +306,92 @@ static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
 	return false;
 }
 
+static int nf_flow_vlan_inner_push(struct sk_buff *skb, __be16 proto, u16 id)
+{
+	struct vlan_hdr *vhdr;
+
+	if (skb_cow_head(skb, VLAN_HLEN))
+		return -1;
+
+	__skb_push(skb, VLAN_HLEN);
+	skb_reset_network_header(skb);
+
+	vhdr = (struct vlan_hdr *)(skb->data);
+	vhdr->h_vlan_TCI = htons(id);
+	vhdr->h_vlan_encapsulated_proto = skb->protocol;
+	skb->protocol = proto;
+
+	return 0;
+}
+
+static int nf_flow_ppoe_push(struct sk_buff *skb, u16 id)
+{
+	struct ppp_hdr {
+		struct pppoe_hdr hdr;
+		__be16 proto;
+	} *ph;
+	int data_len = skb->len + 2;
+	__be16 proto;
+
+	if (skb_cow_head(skb, PPPOE_SES_HLEN))
+		return -1;
+
+	if (skb->protocol == htons(ETH_P_IP))
+		proto = htons(PPP_IP);
+	else if (skb->protocol == htons(ETH_P_IPV6))
+		proto = htons(PPP_IPV6);
+	else
+		return -1;
+
+	__skb_push(skb, PPPOE_SES_HLEN);
+	skb_reset_network_header(skb);
+
+	ph = (struct ppp_hdr *)(skb->data);
+	ph->hdr.ver  = 1;
+	ph->hdr.type = 1;
+	ph->hdr.code = 0;
+	ph->hdr.sid  = htons(id);
+	ph->hdr.length = htons(data_len);
+	ph->proto = proto;
+	skb->protocol = htons(ETH_P_PPP_SES);
+
+	return 0;
+}
+
+static int nf_flow_encap_push(struct sk_buff *skb,
+			      struct flow_offload_tuple_rhash *tuplehash,
+			      unsigned short *type)
+{
+	int i = 0, ret = 0;
+
+	if (!tuplehash->tuple.encap_num)
+		return 0;
+
+	if (tuplehash->tuple.encap[i].proto == htons(ETH_P_8021Q) ||
+	    tuplehash->tuple.encap[i].proto == htons(ETH_P_8021AD)) {
+		__vlan_hwaccel_put_tag(skb, tuplehash->tuple.encap[i].proto,
+				       tuplehash->tuple.encap[i].id);
+		i++;
+		if (i >= tuplehash->tuple.encap_num)
+			return 0;
+	}
+
+	switch (tuplehash->tuple.encap[i].proto) {
+	case htons(ETH_P_8021Q):
+		*type = ETH_P_8021Q;
+		ret = nf_flow_vlan_inner_push(skb,
+					      tuplehash->tuple.encap[i].proto,
+					      tuplehash->tuple.encap[i].id);
+		break;
+	case htons(ETH_P_PPP_SES):
+		*type = ETH_P_PPP_SES;
+		ret = nf_flow_ppoe_push(skb,
+					tuplehash->tuple.encap[i].id);
+		break;
+	}
+	return ret;
+}
+
 static void nf_flow_encap_pop(struct sk_buff *skb,
 			      struct flow_offload_tuple_rhash *tuplehash)
 {
@@ -335,6 +421,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
 
 static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
 				       const struct flow_offload_tuple_rhash *tuplehash,
+				       struct flow_offload_tuple_rhash *other_tuplehash,
 				       unsigned short type)
 {
 	struct net_device *outdev;
@@ -343,6 +430,9 @@ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
 	if (!outdev)
 		return NF_DROP;
 
+	if (nf_flow_encap_push(skb, other_tuplehash, &type) < 0)
+		return NF_DROP;
+
 	skb->dev = outdev;
 	dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest,
 			tuplehash->tuple.out.h_source, skb->len);
@@ -462,7 +552,8 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
 		ret = NF_STOLEN;
 		break;
 	case FLOW_OFFLOAD_XMIT_DIRECT:
-		ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IP);
+		ret = nf_flow_queue_xmit(state->net, skb, tuplehash,
+					 &flow->tuplehash[!dir], ETH_P_IP);
 		if (ret == NF_DROP)
 			flow_offload_teardown(flow);
 		break;
@@ -757,7 +848,8 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
 		ret = NF_STOLEN;
 		break;
 	case FLOW_OFFLOAD_XMIT_DIRECT:
-		ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IPV6);
+		ret = nf_flow_queue_xmit(state->net, skb, tuplehash,
+					 &flow->tuplehash[!dir], ETH_P_IPV6);
 		if (ret == NF_DROP)
 			flow_offload_teardown(flow);
 		break;
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 46a6d280b09c..b4baee519e18 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -124,13 +124,12 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 				info->indev = NULL;
 				break;
 			}
-			if (!info->outdev)
-				info->outdev = path->dev;
 			info->encap[info->num_encaps].id = path->encap.id;
 			info->encap[info->num_encaps].proto = path->encap.proto;
 			info->num_encaps++;
 			if (path->type == DEV_PATH_PPPOE)
 				memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
+			info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
 			break;
 		case DEV_PATH_BRIDGE:
 			if (is_zero_ether_addr(info->h_source))
@@ -158,8 +157,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 			break;
 		}
 	}
-	if (!info->outdev)
-		info->outdev = info->indev;
+	info->outdev = info->indev;
 
 	info->hw_outdev = info->indev;
 
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:35 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:35 +0100
Subject: [PATCH v9 nf 01/15] net: pppoe: avoid zero-length arrays in struct pppoe_hdr
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-2-ericwouds@gmail.com>

Jakub Kicinski suggested following patch:

W=1 C=1 GCC build gives us:

net/bridge/netfilter/nf_conntrack_bridge.c: note: in included file (through
../include/linux/if_pppox.h, ../include/uapi/linux/netfilter_bridge.h,
../include/linux/netfilter_bridge.h): include/uapi/linux/if_pppox.h:
153:29: warning: array of flexible structures

It doesn't like that hdr has a zero-length array which overlaps proto.
The kernel code doesn't currently need those arrays.

PPPoE connection is functional after applying this patch.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 drivers/net/ppp/pppoe.c       | 2 +-
 include/uapi/linux/if_pppox.h | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 68e631718ab0..17946af6a8cf 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -882,7 +882,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
 	skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
 
 	ph = skb_put(skb, total_len + sizeof(struct pppoe_hdr));
-	start = (char *)&ph->tag[0];
+	start = (char *)ph + sizeof(*ph);
 
 	error = memcpy_from_msg(start, m, total_len);
 	if (error < 0) {
diff --git a/include/uapi/linux/if_pppox.h b/include/uapi/linux/if_pppox.h
index 9abd80dcc46f..29b804aa7474 100644
--- a/include/uapi/linux/if_pppox.h
+++ b/include/uapi/linux/if_pppox.h
@@ -122,7 +122,9 @@ struct sockaddr_pppol2tpv3in6 {
 struct pppoe_tag {
 	__be16 tag_type;
 	__be16 tag_len;
+#ifndef __KERNEL__
 	char tag_data[];
+#endif
 } __attribute__ ((packed));
 
 /* Tag identifiers */
@@ -150,7 +152,9 @@ struct pppoe_hdr {
 	__u8 code;
 	__be16 sid;
 	__be16 length;
+#ifndef __KERNEL__
 	struct pppoe_tag tag[];
+#endif
 } __packed;
 
 /* Length of entire PPPoE + PPP header */
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:37 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:37 +0100
Subject: [PATCH v9 nf 03/15] netfilter: flow: remove hw_outdev, out.hw_ifindex and out.hw_ifidx
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-4-ericwouds@gmail.com>

Now always info->outdev == info->hw_outdev, so the netfilter code can be
further cleaned up by removing:
 * hw_outdev from struct nft_forward_info
 * out.hw_ifindex from struct nf_flow_route
 * out.hw_ifidx from struct flow_offload_tuple

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 include/net/netfilter/nf_flow_table.h | 2 --
 net/netfilter/nf_flow_table_core.c    | 1 -
 net/netfilter/nf_flow_table_offload.c | 2 +-
 net/netfilter/nft_flow_offload.c      | 4 ----
 4 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index d711642e78b5..4ab32fb61865 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -145,7 +145,6 @@ struct flow_offload_tuple {
 		};
 		struct {
 			u32		ifidx;
-			u32		hw_ifidx;
 			u8		h_source[ETH_ALEN];
 			u8		h_dest[ETH_ALEN];
 		} out;
@@ -211,7 +210,6 @@ struct nf_flow_route {
 		} in;
 		struct {
 			u32			ifindex;
-			u32			hw_ifindex;
 			u8			h_source[ETH_ALEN];
 			u8			h_dest[ETH_ALEN];
 		} out;
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 9d8361526f82..1e5d3735c028 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -127,7 +127,6 @@ static int flow_offload_fill_route(struct flow_offload *flow,
 		memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source,
 		       ETH_ALEN);
 		flow_tuple->out.ifidx = route->tuple[dir].out.ifindex;
-		flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex;
 		dst_release(dst);
 		break;
 	case FLOW_OFFLOAD_XMIT_XFRM:
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index e06bc36f49fe..d8f7bfd60ac6 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -555,7 +555,7 @@ static void flow_offload_redirect(struct net *net,
 	switch (this_tuple->xmit_type) {
 	case FLOW_OFFLOAD_XMIT_DIRECT:
 		this_tuple = &flow->tuplehash[dir].tuple;
-		ifindex = this_tuple->out.hw_ifidx;
+		ifindex = this_tuple->out.ifidx;
 		break;
 	case FLOW_OFFLOAD_XMIT_NEIGH:
 		other_tuple = &flow->tuplehash[!dir].tuple;
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index b4baee519e18..5ef2f4ba7ab8 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -80,7 +80,6 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
 struct nft_forward_info {
 	const struct net_device *indev;
 	const struct net_device *outdev;
-	const struct net_device *hw_outdev;
 	struct id {
 		__u16	id;
 		__be16	proto;
@@ -159,8 +158,6 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 	}
 	info->outdev = info->indev;
 
-	info->hw_outdev = info->indev;
-
 	if (nf_flowtable_hw_offload(flowtable) &&
 	    nft_is_valid_ether_device(info->indev))
 		info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
@@ -212,7 +209,6 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
 		memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
 		memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
 		route->tuple[dir].out.ifindex = info.outdev->ifindex;
-		route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex;
 		route->tuple[dir].xmit_type = info.xmit_type;
 	}
 }
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:39 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:39 +0100
Subject: [PATCH v9 nf 05/15] netfilter: nft_chain_filter: Add bridge double vlan and pppoe
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-6-ericwouds@gmail.com>

This adds the capability to evaluate 802.1ad, QinQ, PPPoE and PPPoE-in-Q
packets in the bridge filter chain.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nft_chain_filter.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c
index 19a553550c76..7c7080c1a67d 100644
--- a/net/netfilter/nft_chain_filter.c
+++ b/net/netfilter/nft_chain_filter.c
@@ -232,11 +232,27 @@ nft_do_chain_bridge(void *priv,
 		    struct sk_buff *skb,
 		    const struct nf_hook_state *state)
 {
+	struct ethhdr *ethh = eth_hdr(skb);
 	struct nft_pktinfo pkt;
+	int thoff;
 
 	nft_set_pktinfo(&pkt, skb, state);
 
-	switch (eth_hdr(skb)->h_proto) {
+	switch (ethh->h_proto) {
+	case htons(ETH_P_PPP_SES):
+		thoff = PPPOE_SES_HLEN;
+		ethh += thoff;
+		break;
+	case htons(ETH_P_8021Q):
+		thoff = VLAN_HLEN;
+		ethh += thoff;
+		break;
+	default:
+		thoff = 0;
+		break;
+	}
+
+	switch (ethh->h_proto) {
 	case htons(ETH_P_IP):
 		nft_set_pktinfo_ipv4_validate(&pkt);
 		break;
@@ -248,6 +264,8 @@ nft_do_chain_bridge(void *priv,
 		break;
 	}
 
+	pkt.thoff += thoff;
+
 	return nft_do_chain(&pkt, priv);
 }
 
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:38 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:38 +0100
Subject: [PATCH v9 nf 04/15] netfilter: bridge: Add conntrack double vlan and pppoe
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-5-ericwouds@gmail.com>

This adds the capability to conntrack 802.1ad, QinQ, PPPoE and PPPoE-in-Q
packets that are passing a bridge.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/bridge/netfilter/nf_conntrack_bridge.c | 83 ++++++++++++++++++----
 1 file changed, 71 insertions(+), 12 deletions(-)

diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
index 816bb0fde718..4b4e3751fb13 100644
--- a/net/bridge/netfilter/nf_conntrack_bridge.c
+++ b/net/bridge/netfilter/nf_conntrack_bridge.c
@@ -242,53 +242,112 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
 {
 	struct nf_hook_state bridge_state = *state;
 	enum ip_conntrack_info ctinfo;
+	int ret, offset = 0;
 	struct nf_conn *ct;
-	u32 len;
-	int ret;
+	__be16 outer_proto;
+	u32 len, data_len;
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if ((ct && !nf_ct_is_template(ct)) ||
 	    ctinfo == IP_CT_UNTRACKED)
 		return NF_ACCEPT;
 
+	switch (skb->protocol) {
+	case htons(ETH_P_PPP_SES): {
+		struct ppp_hdr {
+			struct pppoe_hdr hdr;
+			__be16 proto;
+		} *ph;
+
+		offset = PPPOE_SES_HLEN;
+		if (!pskb_may_pull(skb, offset))
+			return NF_ACCEPT;
+		outer_proto = skb->protocol;
+		ph = (struct ppp_hdr *)(skb->data);
+		switch (ph->proto) {
+		case htons(PPP_IP):
+			skb->protocol = htons(ETH_P_IP);
+			break;
+		case htons(PPP_IPV6):
+			skb->protocol = htons(ETH_P_IPV6);
+			break;
+		default:
+			nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+			return NF_ACCEPT;
+		}
+		data_len = ntohs(ph->hdr.length) - 2;
+		skb_pull_rcsum(skb, offset);
+		skb_reset_network_header(skb);
+		break;
+	}
+	case htons(ETH_P_8021Q): {
+		struct vlan_hdr *vhdr;
+
+		offset = VLAN_HLEN;
+		if (!pskb_may_pull(skb, offset))
+			return NF_ACCEPT;
+		outer_proto = skb->protocol;
+		vhdr = (struct vlan_hdr *)(skb->data);
+		skb->protocol = vhdr->h_vlan_encapsulated_proto;
+		data_len = U32_MAX;
+		skb_pull_rcsum(skb, offset);
+		skb_reset_network_header(skb);
+		break;
+	}
+	default:
+		data_len = U32_MAX;
+		break;
+	}
+
+	ret = NF_ACCEPT;
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
 		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		len = skb_ip_totlen(skb);
+		if (data_len < len)
+			len = data_len;
 		if (pskb_trim_rcsum(skb, len))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		if (nf_ct_br_ip_check(skb))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		bridge_state.pf = NFPROTO_IPV4;
 		ret = nf_ct_br_defrag4(skb, &bridge_state);
 		break;
 	case htons(ETH_P_IPV6):
 		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
+		if (data_len < len)
+			len = data_len;
 		if (pskb_trim_rcsum(skb, len))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		if (nf_ct_br_ipv6_check(skb))
-			return NF_ACCEPT;
+			goto do_not_track;
 
 		bridge_state.pf = NFPROTO_IPV6;
 		ret = nf_ct_br_defrag6(skb, &bridge_state);
 		break;
 	default:
 		nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
-		return NF_ACCEPT;
+		goto do_not_track;
 	}
 
-	if (ret != NF_ACCEPT)
-		return ret;
+	if (ret == NF_ACCEPT)
+		ret = nf_conntrack_in(skb, &bridge_state);
 
-	return nf_conntrack_in(skb, &bridge_state);
+do_not_track:
+	if (offset) {
+		skb_push_rcsum(skb, offset);
+		skb_reset_network_header(skb);
+		skb->protocol = outer_proto;
+	}
+	return ret;
 }
 
 static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:40 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:40 +0100
Subject: [PATCH v9 nf 06/15] bridge: Add filling forward path from port to port
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-7-ericwouds@gmail.com>

If a port is passed as argument instead of the master, then:

At br_fill_forward_path(): find the master and use it to fill the
forward path.

At br_vlan_fill_forward_path_pvid(): lookup vlan group from port
instead.

Changed call to br_vlan_group() into br_vlan_group_rcu() while at it.

Acked-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/bridge/br_device.c  | 19 ++++++++++++++-----
 net/bridge/br_private.h |  2 ++
 net/bridge/br_vlan.c    |  6 +++++-
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 9d8c72ed01ab..02eb23e8aab8 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -383,16 +383,25 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
 static int br_fill_forward_path(struct net_device_path_ctx *ctx,
 				struct net_device_path *path)
 {
+	struct net_bridge_port *src, *dst;
 	struct net_bridge_fdb_entry *f;
-	struct net_bridge_port *dst;
 	struct net_bridge *br;
 
-	if (netif_is_bridge_port(ctx->dev))
-		return -1;
+	if (netif_is_bridge_port(ctx->dev)) {
+		struct net_device *br_dev;
+
+		br_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx->dev);
+		if (!br_dev)
+			return -1;
 
-	br = netdev_priv(ctx->dev);
+		src = br_port_get_rcu(ctx->dev);
+		br = netdev_priv(br_dev);
+	} else {
+		src = NULL;
+		br = netdev_priv(ctx->dev);
+	}
 
-	br_vlan_fill_forward_path_pvid(br, ctx, path);
+	br_vlan_fill_forward_path_pvid(br, src, ctx, path);
 
 	f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id);
 	if (!f)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1054b8a88edc..a0b950390a16 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1584,6 +1584,7 @@ bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
 			     const struct net_bridge_vlan *range_end);
 
 void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+				    struct net_bridge_port *p,
 				    struct net_device_path_ctx *ctx,
 				    struct net_device_path *path);
 int br_vlan_fill_forward_path_mode(struct net_bridge *br,
@@ -1753,6 +1754,7 @@ static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p,
 }
 
 static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+						  struct net_bridge_port *p,
 						  struct net_device_path_ctx *ctx,
 						  struct net_device_path *path)
 {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index d9a69ec9affe..a18c7da12ebd 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1441,6 +1441,7 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)
 EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
 
 void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+				    struct net_bridge_port *p,
 				    struct net_device_path_ctx *ctx,
 				    struct net_device_path *path)
 {
@@ -1453,7 +1454,10 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
 	if (!br_opt_get(br, BROPT_VLAN_ENABLED))
 		return;
 
-	vg = br_vlan_group(br);
+	if (p)
+		vg = nbp_vlan_group_rcu(p);
+	else
+		vg = br_vlan_group_rcu(br);
 
 	if (idx >= 0 &&
 	    ctx->vlan[idx].proto == br->vlan_proto) {
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:42 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:42 +0100
Subject: [PATCH v9 nf 08/15] netfilter :nf_flow_table_offload: Add nf_flow_rule_bridge()
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-9-ericwouds@gmail.com>

Add nf_flow_rule_bridge().

It only calls the common rule and adds the redirect.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 include/net/netfilter/nf_flow_table.h |  3 +++
 net/netfilter/nf_flow_table_offload.c | 13 +++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index 4ab32fb61865..a7f5d6166088 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -340,6 +340,9 @@ void nf_flow_table_offload_flush_cleanup(struct nf_flowtable *flowtable);
 int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
 				struct net_device *dev,
 				enum flow_block_command cmd);
+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,
+			enum flow_offload_tuple_dir dir,
+			struct nf_flow_rule *flow_rule);
 int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,
 			    enum flow_offload_tuple_dir dir,
 			    struct nf_flow_rule *flow_rule);
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index d8f7bfd60ac6..3cc30ebfa6ff 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -679,6 +679,19 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,
 	return 0;
 }
 
+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,
+			enum flow_offload_tuple_dir dir,
+			struct nf_flow_rule *flow_rule)
+{
+	if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0)
+		return -1;
+
+	flow_offload_redirect(net, flow, dir, flow_rule);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nf_flow_rule_bridge);
+
 int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,
 			    enum flow_offload_tuple_dir dir,
 			    struct nf_flow_rule *flow_rule)
-- 
2.47.1



From mathis.foerst at mt.com  Wed Mar  5 03:38:01 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Wed,  5 Mar 2025 12:38:01 +0100
Subject: [PATCH v1 0/1] media: imx: csi: Parse link configuration from fw_node
Message-ID: <20250305113802.897087-1-mathis.foerst@mt.com>

Hi,

this patch fixes the imx-media-csi driver to work with camera drivers that
do not implement the subdev-pad-operation "get_mbus_format".

It's the follow up of this discussion:
https://lore.kernel.org/linux-media/Z8AoA6WjbXQufqR6 at kekkonen.localdomain/

I tested the changes successfully on an i.MX6DL with an MT9M114 and an 
MT9V032 camera. They both use the parallel camera interface.
Sadly, I don't have the hardware to test with a MIPI CSI-2 camera.

Best regards,
Mathis Foerst


Mathis Foerst (1):
  media: imx: csi: Parse link configuration from fw_node

 drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
 1 file changed, 32 insertions(+), 4 deletions(-)


base-commit: ac9c34d1e45a4c25174ced4fc0cfc33ff3ed08c7
-- 
2.34.1



From mathis.foerst at mt.com  Wed Mar  5 03:38:02 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Wed,  5 Mar 2025 12:38:02 +0100
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from fw_node
In-Reply-To: <20250305113802.897087-1-mathis.foerst@mt.com>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
Message-ID: <20250305113802.897087-2-mathis.foerst@mt.com>

The imx-media-csi driver requires upstream camera drivers to implement
the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
implement this function are not usable on the i.MX6.

The docs for get_mbus_config [1] say:
@get_mbus_config: get the media bus configuration of a remote sub-device.
            The media bus configuration is usually retrieved from the
            firmware interface at sub-device probe time, immediately
            applied to the hardware and eventually adjusted by the
            driver.

Currently, the imx-media-csi driver is not incorporating the information
from the firmware interface and therefore relies on the implementation of
get_mbus_config by the camera driver.

To be compatible with camera drivers not implementing get_mbus_config
(which is the usual case), use the bus information from the fw interface:

The camera does not necessarily has a direct media bus link to the CSI as
the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
between them on the media pipeline.
The CSI driver already implements the functionality to find the connected
camera sub-device to call get_mbus_config on it.

At this point the driver is modified as follows:
In the case that get_mbus_config is not implemented by the upstream
camera, try to get its endpoint configuration from the firmware interface
usign v4l2_fwnode_endpoint_parse.
For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
configuration.
For all other mbus_types, return an error.

Note that parsing the mbus_config from the fw interface is not done during
probing because the camera that's connected to the CSI can change based on
the selected input of the video-mux at runtime.

[0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
[1] include/media/v4l2-subdev.h - line 814

Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
---
 drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 3edbc57be2ca..394a9321a10b 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 {
 	struct v4l2_subdev *sd, *remote_sd;
 	struct media_pad *remote_pad;
+	struct fwnode_handle *ep_node;
+	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
 	int ret;
 
 	if (!priv->src_sd)
@@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 
 	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
 			       remote_pad->index, mbus_cfg);
-	if (ret == -ENOIOCTLCMD)
-		v4l2_err(&priv->sd,
-			 "entity %s does not implement get_mbus_config()\n",
-			 remote_pad->entity->name);
+	if (ret == -ENOIOCTLCMD) {
+		/*
+		 * If the upstream sd does not implement get_mbus_config,
+		 * try to parse the link configuration from its fw_node
+		 */
+		ep_node = fwnode_graph_get_endpoint_by_id(dev_fwnode(remote_sd->dev),
+							  0, 0,
+							  FWNODE_GRAPH_ENDPOINT_NEXT);
+		if (!ep_node)
+			return -ENOTCONN;
+
+		ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
+		fwnode_handle_put(ep_node);
+		if (ret)
+			return ret;
 
+		mbus_cfg->type = ep.bus_type;
+		switch (ep.bus_type) {
+		case V4L2_MBUS_PARALLEL:
+		case V4L2_MBUS_BT656:
+			mbus_cfg->bus.parallel = ep.bus.parallel;
+			break;
+		case V4L2_MBUS_CSI2_DPHY:
+			mbus_cfg->bus.mipi_csi2 = ep.bus.mipi_csi2;
+			break;
+		default:
+			v4l2_err(&priv->sd, "Unsupported mbus_type: %i\n",
+				 ep.bus_type);
+			return -EINVAL;
+		}
+	}
 	return ret;
 }
 
-- 
2.34.1



From a.fatoum at pengutronix.de  Wed Mar  5 03:39:27 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 5 Mar 2025 12:39:27 +0100
Subject: [EXTERNAL] Re: [PATCH v4 0/2] Add stop_on_panic support for
 watchdog
In-Reply-To: <PH8PR18MB53817EC09B918852B78DF3AAC5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>
 <PH8PR18MB53817EC09B918852B78DF3AAC5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
Message-ID: <28d0ea70-db7a-40e7-aac9-86808320f252@pengutronix.de>

Hi George,

On 05.03.25 12:28, George Cherian wrote:
> Hi Ahmad,
>> Hi George,
>> On 05.03.25 11:10, George Cherian wrote:
>>> This series adds a new kernel command line option to watchdog core to
>>> stop the watchdog on panic. This is useul in certain systems which prevents
>>> successful loading of kdump kernel due to watchdog reset.
>>>
>>> Some of the watchdog drivers stop function could sleep. For such
>>> drivers the stop_on_panic is not valid as the notifier callback happens
>>> in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
>>> options to indicate whether the stop function would sleep.
>>
>> Did you consider having a reset_on_panic instead, which sets a user-specified
>> timeout on panic? This would make the mechanism useful also for watchdogs
> 
> /proc/sys/kernel/panic already provides that support. You may echo a non-zero value 
> and the system tries for a soft reboot after those many seconds. But this doesn't happen 
> in case of a kdump kernel load after panic.

The timeout specified to the Watchdog reset_on_panic option would be programmed into
the active watchdogs and not be used to trigger a software-induced reboot.

>> that can't be disabled and would protect against system lock up: 
>> Consider a memory-corruption bug (perhaps externally via DMA), which partially
>> overwrites both main and kdump kernel. With a disabled watchdog, the system
>> may not be able to recover on its own.
> 
> Yes, that is the reason why the kernel command-line is optional and by default it is set to zero.
> So that in cases if you have a corrupted kdump kernel then watchdog kicks in.

The existing option isn't enough for the kdump kernel use case.
If we (i.e. you) are going to do something about it, wouldn't it be
better to have a solution that's applicable to a wider number of
watchdog devices?

>> If you did consider it, what made you decide against it?
> watchdog.stop_on_panic=1 is specifically for systems which can't boot a kdump kernel due to the fact 
> that the kdump kernel gets a watchdog reset while booting, may be due to a shorter watchdog time.
> For eg: a 32-bit watchdog down counter running at 1GHz.
> reset_on_panic can guarantee only the largest watchdog timeout supported by HW, 
> since there is no one to ping the watchdog.

If you are serious with the watchdog use, you'll want to use the watchdog to
monitor kernel startup as well. If the bootloader can set a watchdog timeout
just before starting the kernel and it doesn't expire before the kernel watchdog
driver takes over, why can't we do the same just before starting the dumpkernel?

Thanks,
Ahmad

 
>>
>> Thanks,
>> Ahmad
>>
>>>
>>>
>> Changelog:
>> v1 -> v2
>> - Remove the per driver flag setting option
>> - Take the parameter via kernel command-line parameter to watchdog_core.
>>
>> v2 -> v3
>> - Remove the helper function watchdog_stop_on_panic() from watchdog.h.
>> - There are no users for this. 
>>
>> v3 -> v4
>> - Since the panic notifier is in atomic context, watchdog functions
>>   which sleep can't be called. 
>> - Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
>>   function sleeps.
>> - Simplify the stop_on_panic kernel command line parsing.
>> - Enable the panic notiffier only if the watchdog stop function doesn't
>>   sleep
>>
>> George Cherian (2):
>>   watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
>>   drivers: watchdog: Add support for panic notifier callback
> 
> - George


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From leo.yan at arm.com  Wed Mar  5 03:42:11 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 5 Mar 2025 11:42:11 +0000
Subject: [PATCH] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20241217171132.834943-1-james.clark@linaro.org>
References: <20241217171132.834943-1-james.clark@linaro.org>
Message-ID: <20250305114211.GG13418@e132581.arm.com>

On Tue, Dec 17, 2024 at 05:11:31PM +0000, James Clark wrote:
> 
> Add a test to confirm that default sink selection skips over an ETF
> and returns an ETR even if it's further away.
> 
> This also makes it easier to add new unit tests in the future.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  drivers/hwtracing/coresight/Kconfig           |  9 ++
>  drivers/hwtracing/coresight/Makefile          |  1 +
>  drivers/hwtracing/coresight/coresight-core.c  |  1 +
>  .../coresight/coresight-kunit-tests.c         | 90 +++++++++++++++++++
>  4 files changed, 101 insertions(+)
>  create mode 100644 drivers/hwtracing/coresight/coresight-kunit-tests.c
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index 06f0a7594169..056d04bc540a 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -247,4 +247,13 @@ config CORESIGHT_DUMMY
> 
>           To compile this driver as a module, choose M here: the module will be
>           called coresight-dummy.
> +
> +config CORESIGHT_KUNIT_TESTS
> +         tristate "Enable Coresight unit tests"
> +         depends on KUNIT
> +         default KUNIT_ALL_TESTS
> +         help
> +           Enable Coresight unit tests. Only useful for development and not
> +           intended for production.
> +
>  endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 4ba478211b31..c170a41b3056 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -51,3 +51,4 @@ coresight-cti-y := coresight-cti-core.o       coresight-cti-platform.o \
>                    coresight-cti-sysfs.o
>  obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>  obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index ea38ecf26fcb..ce63b68d5503 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -869,6 +869,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>         }
>         return csdev->def_sink;
>  }
> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
> 
>  static int coresight_remove_sink_ref(struct device *dev, void *data)
>  {
> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> new file mode 100644
> index 000000000000..d022bacc8357
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +#include <kunit/device.h>
> +#include <linux/coresight.h>
> +
> +#include "coresight-priv.h"
> +
> +static struct coresight_device *coresight_test_device(struct device *dev)
> +{
> +       struct coresight_device *csdev = devm_kcalloc(dev, 1,
> +                                                    sizeof(struct coresight_device),
> +                                                    GFP_KERNEL);
> +       csdev->pdata = devm_kcalloc(dev, 1,
> +                                  sizeof(struct coresight_platform_data),
> +                                  GFP_KERNEL);
> +       return csdev;
> +}
> +
> +static void coresight_free_test_device(struct device *dev,
> +                                      struct coresight_device *csdev)
> +{
> +       devm_kfree(dev, csdev->pdata->out_conns);

It will lead memory leaking if we don't release connections pointed by
'out_conns' pointer array.  Something like:

          for (i = 0; i < csdev->pdata->nr_outconns; i++)
               devm_kfree(dev, csdev->pdata->out_conns[i]);
          devm_kfree(dev, csdev->pdata->out_conns);

Otherwise, it looks good to me.

Thanks,
Leo

> +       devm_kfree(dev, csdev->pdata);
> +       devm_kfree(dev, csdev);
> +}
> +
> +static int coresight_test_cpuid(struct coresight_device *csdev)
> +{
> +       return 0;
> +}
> +
> +static void test_default_sink(struct kunit *test)
> +{
> +       /*
> +        * ETM -> ETF -> ETR -> CATU
> +        *                ^
> +        *                | default
> +        */
> +       struct device *dev = kunit_device_register(test, "coresight_kunit");
> +       struct coresight_device *etm = coresight_test_device(dev),
> +                               *etf = coresight_test_device(dev),
> +                               *etr = coresight_test_device(dev),
> +                               *catu = coresight_test_device(dev);
> +       struct coresight_connection conn = {};
> +       struct coresight_ops_source src_ops = {.cpu_id = coresight_test_cpuid };
> +       struct coresight_ops etm_cs_ops = { .source_ops = &src_ops };
> +
> +       etm->type = CORESIGHT_DEV_TYPE_SOURCE;
> +       etm->ops = &etm_cs_ops;
> +       etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
> +       etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
> +       etr->type = CORESIGHT_DEV_TYPE_SINK;
> +       etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
> +       catu->type = CORESIGHT_DEV_TYPE_HELPER;
> +
> +       conn.src_dev = etm;
> +       conn.dest_dev = etf;
> +       coresight_add_out_conn(dev, etm->pdata, &conn);
> +
> +       conn.src_dev = etf;
> +       conn.dest_dev = etr;
> +       coresight_add_out_conn(dev, etf->pdata, &conn);
> +
> +       conn.src_dev = etr;
> +       conn.dest_dev = catu;
> +       coresight_add_out_conn(dev, etr->pdata, &conn);
> +
> +       KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
> +
> +       coresight_free_test_device(dev, etm);
> +       coresight_free_test_device(dev, etf);
> +       coresight_free_test_device(dev, etr);
> +       coresight_free_test_device(dev, catu);
> +}
> +
> +static struct kunit_case coresight_testcases[] = {
> +       KUNIT_CASE(test_default_sink),
> +       {}
> +};
> +
> +static struct kunit_suite coresight_test_suite = {
> +       .name = "coresight_test_suite",
> +       .test_cases = coresight_testcases,
> +};
> +
> +kunit_test_suites(&coresight_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
> +MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From laurent.pinchart at ideasonboard.com  Wed Mar  5 03:45:36 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed, 5 Mar 2025 13:45:36 +0200
Subject: [PATCH] media: imx-mipi-csis: Fix v4l2 mbus frame descriptor type
In-Reply-To: <20250305055655.6622-1-inbaraj.e@samsung.com>
References: <CGME20250305060259epcas5p20c02f4c4b4ff84b0f790b4ea446056e6@epcas5p2.samsung.com>
 <20250305055655.6622-1-inbaraj.e@samsung.com>
Message-ID: <20250305114536.GB31618@pendragon.ideasonboard.com>

Hi Inbaraj,

Thank you for the patch.

On Wed, Mar 05, 2025 at 11:26:55AM +0530, Inbaraj E wrote:
> For MIPI CSI2 v4l2 mbus frame descriptor type should be set to
> V4L2_MBUS_FRAME_DESC_TYPE_CSI2. Now frame descriptor type is set to
> V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL. So changing the frame descriptor
> type to V4L2_MBUS_FRAME_DESC_TYPE_CSI2.

The frame descriptor describes the bus on the *output* of the CSIS.
That's not CSI-2 anymore, but a parallel bus.

Is this patch fixing an actual issue ?

> Fixes: d200de90de2a0 ("media: imx: imx-mipi-csis: Implement the .get_frame_desc() operation")
> Signed-off-by: Inbaraj E <inbaraj.e at samsung.com>
> ---
>  drivers/media/platform/nxp/imx-mipi-csis.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
> index 29523bb84d95..bb6550bed230 100644
> --- a/drivers/media/platform/nxp/imx-mipi-csis.c
> +++ b/drivers/media/platform/nxp/imx-mipi-csis.c
> @@ -1137,7 +1137,7 @@ static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
>  	if (!csis_fmt)
>  		return -EPIPE;
>  
> -	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
> +	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
>  	fd->num_entries = 1;
>  
>  	entry->flags = 0;

-- 
Regards,

Laurent Pinchart


From andre.przywara at arm.com  Wed Mar  5 03:55:35 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 5 Mar 2025 11:55:35 +0000
Subject: [PATCH v2 06/15] irqchip/sunxi-nmi: Support Allwinner A523 NMI
 controller
In-Reply-To: <87frjr6i1j.ffs@tglx>
References: <20250304222309.29385-1-andre.przywara@arm.com>
	<20250304222309.29385-7-andre.przywara@arm.com>
	<87frjr6i1j.ffs@tglx>
Message-ID: <20250305115535.619ba087@donnerap.manchester.arm.com>

On Wed, 05 Mar 2025 08:41:28 +0100
Thomas Gleixner <tglx at linutronix.de> wrote:

Hi Thomas,

thanks for having a look!

> On Tue, Mar 04 2025 at 22:23, Andre Przywara wrote:
> >  
> > -struct sunxi_sc_nmi_reg_offs {
> > +struct sunxi_sc_nmi_data {
> >  	u32 ctrl;
> >  	u32 pend;
> >  	u32 enable;
> > +	u32 enable_val;  
> 
> The data structure name and the corresponding variable/argument name
> were making the code pretty obvious, but now this is opaque and
> incomprehensible.
> 
> data::ctrl does not even give the slightest hint what this is about. You
> need to read up in the code to figure out what it means. Something like:
> 
> struct sunxi_sc_nmi_data {
> 	u32	reg_offs_ctrl;
>   	u32	reg_offs_pend;
>   	u32	reg_offs_enable;
> 	u32	enable_val;
> };
> 
> or even better:
> 
> struct sunxi_sc_nmi_data {
> 	struct {
> 		u32	ctrl;
>   		u32	pend;
>   		u32	enable;
>         } reg_offs;
> 	u32		enable_val;
> };
> 
> makes it clear and obvious, no?

Sure, will change it, it was just the usual decision between reworking the
existing code or just adding my small change in. 50% chance of getting that
right, I guess ;-)

> 
> > +static const struct sunxi_sc_nmi_data sun55i_a523_data __initconst = {
> > +	.ctrl	= SUN9I_NMI_CTRL,
> > +	.pend	= SUN9I_NMI_PENDING,
> > +	.enable	= SUN9I_NMI_ENABLE,
> > +	.enable_val = BIT(31),  
> 
> https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-declarations-and-initializers

Oops, missed that.

Thanks,
Andre

> 
> Thanks,
> 
>         tglx


From aliceryhl at google.com  Wed Mar  5 03:59:58 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Wed, 5 Mar 2025 11:59:58 +0000
Subject: [Bug report] Memory leak in scmi_device_create
Message-ID: <Z8g8vhS9rqQ_ez48@google.com>

Dear SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message
Protocol drivers maintainers,

I flashed a v6.13-rc3 kernel onto a Rock5B board and noticed the
following output in my terminal:

[  687.694465] kmemleak: 4 new suspected memory leaks (see /sys/kernel/debug/kmemleak)

It seems that there is a memory leak for devices created with
scmi_device_create.

This was with a kernel running v6.13-rc3, but as far as I can tell, no
relevant changes have landed since v6.13-rc3. My tree *does* include
commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
not happening consistently.

See below for the full kmemleak report.

Alice

$ sudo cat /sys/kernel/debug/kmemleak
unreferenced object 0xffffff8106c86000 (size 2048):
  comm "swapper/0", pid 1, jiffies 4294893094
  hex dump (first 32 bytes):
    02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
    60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
  backtrace (crc feae9680):
    [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
    [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
    [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
    [<000000008714917b>] scmi_device_create+0x40/0x194
    [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
    [<00000000970bad38>] scmi_probe+0x584/0xa78
    [<000000002600d2fd>] platform_probe+0xbc/0xf0
    [<00000000f6f556b4>] really_probe+0x1b8/0x520
    [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
    [<00000000d613b754>] driver_probe_device+0x6c/0x208
    [<00000000187a9170>] __driver_attach+0x168/0x328
    [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
    [<00000000984a3176>] driver_attach+0x34/0x44
    [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
    [<00000000747fce19>] driver_register+0xc0/0x1a0
    [<0000000081cb8754>] __platform_driver_register+0x40/0x50
unreferenced object 0xffffff8103bc01c0 (size 32):
  comm "swapper/0", pid 1, jiffies 4294893094
  hex dump (first 32 bytes):
    5f 5f 73 63 6d 69 5f 74 72 61 6e 73 70 6f 72 74  __scmi_transport
    5f 64 65 76 69 63 65 5f 72 78 5f 31 30 00 ff ff  _device_rx_10...
  backtrace (crc 8dab7ca7):
    [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
    [<00000000500dbc08>] __kmalloc_node_track_caller_noprof+0x234/0x528
    [<000000004990eea4>] kstrdup+0x48/0x80
    [<00000000ad4d2923>] kstrdup_const+0x30/0x3c
    [<00000000e9d3bdc3>] __scmi_device_create+0xd4/0x2b4
    [<000000008714917b>] scmi_device_create+0x40/0x194
    [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
    [<00000000970bad38>] scmi_probe+0x584/0xa78
    [<000000002600d2fd>] platform_probe+0xbc/0xf0
    [<00000000f6f556b4>] really_probe+0x1b8/0x520
    [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
    [<00000000d613b754>] driver_probe_device+0x6c/0x208
    [<00000000187a9170>] __driver_attach+0x168/0x328
    [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
    [<00000000984a3176>] driver_attach+0x34/0x44
    [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
unreferenced object 0xffffff8103ba6760 (size 16):
  comm "swapper/0", pid 1, jiffies 4294893094
  hex dump (first 16 bytes):
    73 63 6d 69 5f 64 65 76 2e 32 00 03 81 ff ff ff  scmi_dev.2......
  backtrace (crc ccc21b9a):
    [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
    [<00000000500dbc08>] __kmalloc_node_track_caller_noprof+0x234/0x528
    [<00000000cdc440a0>] kvasprintf+0x90/0x11c
    [<00000000500fc732>] kvasprintf_const+0x98/0x138
    [<0000000030e28143>] kobject_set_name_vargs+0x68/0x104
    [<00000000f15f6ece>] dev_set_name+0x6c/0x98
    [<00000000c1f76eb4>] __scmi_device_create+0x17c/0x2b4
    [<000000008714917b>] scmi_device_create+0x40/0x194
    [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
    [<00000000970bad38>] scmi_probe+0x584/0xa78
    [<000000002600d2fd>] platform_probe+0xbc/0xf0
    [<00000000f6f556b4>] really_probe+0x1b8/0x520
    [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
    [<00000000d613b754>] driver_probe_device+0x6c/0x208
    [<00000000187a9170>] __driver_attach+0x168/0x328
    [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
unreferenced object 0xffffff810637c800 (size 512):
  comm "swapper/0", pid 1, jiffies 4294893094
  hex dump (first 32 bytes):
    00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
    ff ff ff ff ff ff ff ff 00 1e ee 83 c0 ff ff ff  ................
  backtrace (crc 732b3ae6):
    [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
    [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
    [<0000000026a3cb30>] device_add+0x54/0x570
    [<00000000e515c343>] device_register+0x20/0x30
    [<0000000042008204>] __scmi_device_create+0x184/0x2b4
    [<000000008714917b>] scmi_device_create+0x40/0x194
    [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
    [<00000000970bad38>] scmi_probe+0x584/0xa78
    [<000000002600d2fd>] platform_probe+0xbc/0xf0
    [<00000000f6f556b4>] really_probe+0x1b8/0x520
    [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
    [<00000000d613b754>] driver_probe_device+0x6c/0x208
    [<00000000187a9170>] __driver_attach+0x168/0x328
    [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
    [<00000000984a3176>] driver_attach+0x34/0x44
    [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358


From amadeus at jmu.edu.cn  Wed Mar  5 02:00:15 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Wed,  5 Mar 2025 18:00:15 +0800
Subject: [PATCH 6/8] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
In-Reply-To: <20250301104724.36399-1-ziyao@disroot.org>
References: <20250301104724.36399-1-ziyao@disroot.org>
Message-ID: <20250305100015.1353849-1-amadeus@jmu.edu.cn>

Hi,

> +	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
> +					       nr_branches) + 1;
> +
> +	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
> +	if (!IS_ERR(vo_grf))
> +		nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
> +							   nr_vo_branches) + 1,

drivers/clk/rockchip/clk-rk3528.c: In function 'clk_rk3528_probe':
drivers/clk/rockchip/clk-rk3528.c:1105:27: error: implicit declaration of function 'MAX'; did you mean 'MUX'?
 1105 |                 nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
      |                           ^~~
      |                           MUX

It seems that missing definition with older kernels.

Thanks,
Chukun

-- 
2.25.1



From ericwouds at gmail.com  Wed Mar  5 02:29:43 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:43 +0100
Subject: [PATCH v9 nf 09/15] netfilter: nf_flow_table_inet: Add nf_flowtable_type flowtable_bridge
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-10-ericwouds@gmail.com>

This will allow a flowtable to be added to the nft bridge family.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nf_flow_table_inet.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c
index b0f199171932..80b238196f29 100644
--- a/net/netfilter/nf_flow_table_inet.c
+++ b/net/netfilter/nf_flow_table_inet.c
@@ -65,6 +65,16 @@ static int nf_flow_rule_route_inet(struct net *net,
 	return err;
 }
 
+static struct nf_flowtable_type flowtable_bridge = {
+	.family		= NFPROTO_BRIDGE,
+	.init		= nf_flow_table_init,
+	.setup		= nf_flow_table_offload_setup,
+	.action		= nf_flow_rule_bridge,
+	.free		= nf_flow_table_free,
+	.hook		= nf_flow_offload_inet_hook,
+	.owner		= THIS_MODULE,
+};
+
 static struct nf_flowtable_type flowtable_inet = {
 	.family		= NFPROTO_INET,
 	.init		= nf_flow_table_init,
@@ -97,6 +107,7 @@ static struct nf_flowtable_type flowtable_ipv6 = {
 
 static int __init nf_flow_inet_module_init(void)
 {
+	nft_register_flowtable_type(&flowtable_bridge);
 	nft_register_flowtable_type(&flowtable_ipv4);
 	nft_register_flowtable_type(&flowtable_ipv6);
 	nft_register_flowtable_type(&flowtable_inet);
@@ -109,6 +120,7 @@ static void __exit nf_flow_inet_module_exit(void)
 	nft_unregister_flowtable_type(&flowtable_inet);
 	nft_unregister_flowtable_type(&flowtable_ipv6);
 	nft_unregister_flowtable_type(&flowtable_ipv4);
+	nft_unregister_flowtable_type(&flowtable_bridge);
 }
 
 module_init(nf_flow_inet_module_init);
@@ -118,5 +130,6 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pablo Neira Ayuso <pablo at netfilter.org>");
 MODULE_ALIAS_NF_FLOWTABLE(AF_INET);
 MODULE_ALIAS_NF_FLOWTABLE(AF_INET6);
+MODULE_ALIAS_NF_FLOWTABLE(AF_BRIDGE);
 MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */
 MODULE_DESCRIPTION("Netfilter flow table mixed IPv4/IPv6 module");
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:41 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:41 +0100
Subject: [PATCH v9 nf 07/15] net: core: dev: Add dev_fill_bridge_path()
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-8-ericwouds@gmail.com>

New function dev_fill_bridge_path(), similar to dev_fill_forward_path().
It handles starting from a bridge port instead of the bridge master.
The structures ctx and nft_forward_info need to be already filled in with
the (vlan) encaps.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 include/linux/netdevice.h |  2 ++
 net/core/dev.c            | 66 +++++++++++++++++++++++++++++++--------
 2 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7ab86ec228b7..81cdad85d9f1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3318,6 +3318,8 @@ void dev_remove_offload(struct packet_offload *po);
 
 int dev_get_iflink(const struct net_device *dev);
 int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,
+			 struct net_device_path_stack *stack);
 int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
 			  struct net_device_path_stack *stack);
 struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
diff --git a/net/core/dev.c b/net/core/dev.c
index 2dc705604509..d0810f052d3a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -714,44 +714,84 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
 	return &stack->path[k];
 }
 
-int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
-			  struct net_device_path_stack *stack)
+static int dev_fill_forward_path_common(struct net_device_path_ctx *ctx,
+					struct net_device_path_stack *stack)
 {
 	const struct net_device *last_dev;
-	struct net_device_path_ctx ctx = {
-		.dev	= dev,
-	};
 	struct net_device_path *path;
 	int ret = 0;
 
-	memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
-	stack->num_paths = 0;
-	while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
-		last_dev = ctx.dev;
+	while (ctx->dev && ctx->dev->netdev_ops->ndo_fill_forward_path) {
+		last_dev = ctx->dev;
 		path = dev_fwd_path(stack);
 		if (!path)
 			return -1;
 
 		memset(path, 0, sizeof(struct net_device_path));
-		ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
+		ret = ctx->dev->netdev_ops->ndo_fill_forward_path(ctx, path);
 		if (ret < 0)
 			return -1;
 
-		if (WARN_ON_ONCE(last_dev == ctx.dev))
+		if (WARN_ON_ONCE(last_dev == ctx->dev))
 			return -1;
 	}
 
-	if (!ctx.dev)
+	if (!ctx->dev)
 		return ret;
 
 	path = dev_fwd_path(stack);
 	if (!path)
 		return -1;
 	path->type = DEV_PATH_ETHERNET;
-	path->dev = ctx.dev;
+	path->dev = ctx->dev;
 
 	return ret;
 }
+
+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,
+			 struct net_device_path_stack *stack)
+{
+	const struct net_device *last_dev, *br_dev;
+	struct net_device_path *path;
+
+	stack->num_paths = 0;
+
+	if (!ctx->dev || !netif_is_bridge_port(ctx->dev))
+		return -1;
+
+	br_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx->dev);
+	if (!br_dev || !br_dev->netdev_ops->ndo_fill_forward_path)
+		return -1;
+
+	last_dev = ctx->dev;
+	path = dev_fwd_path(stack);
+	if (!path)
+		return -1;
+
+	memset(path, 0, sizeof(struct net_device_path));
+	if (br_dev->netdev_ops->ndo_fill_forward_path(ctx, path) < 0)
+		return -1;
+
+	if (!ctx->dev || WARN_ON_ONCE(last_dev == ctx->dev))
+		return -1;
+
+	return dev_fill_forward_path_common(ctx, stack);
+}
+EXPORT_SYMBOL_GPL(dev_fill_bridge_path);
+
+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+			  struct net_device_path_stack *stack)
+{
+	struct net_device_path_ctx ctx = {
+		.dev	= dev,
+	};
+
+	memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
+
+	stack->num_paths = 0;
+
+	return dev_fill_forward_path_common(&ctx, stack);
+}
 EXPORT_SYMBOL_GPL(dev_fill_forward_path);
 
 /* must be called under rcu_read_lock(), as we dont take a reference */
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:44 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:44 +0100
Subject: [PATCH v9 nf 10/15] netfilter: nft_flow_offload: Add NFPROTO_BRIDGE to validate
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-11-ericwouds@gmail.com>

Need to add NFPROTO_BRIDGE to nft_flow_offload_validate() to support
the bridge-fastpath.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nft_flow_offload.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 5ef2f4ba7ab8..323c531c7046 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -421,7 +421,8 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
 
 	if (ctx->family != NFPROTO_IPV4 &&
 	    ctx->family != NFPROTO_IPV6 &&
-	    ctx->family != NFPROTO_INET)
+	    ctx->family != NFPROTO_INET &&
+	    ctx->family != NFPROTO_BRIDGE)
 		return -EOPNOTSUPP;
 
 	return nft_chain_validate_hooks(ctx->chain, hook_mask);
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:45 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:45 +0100
Subject: [PATCH v9 nf 11/15] netfilter: nft_flow_offload: Add DEV_PATH_MTK_WDMA to nft_dev_path_info()
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-12-ericwouds@gmail.com>

In case of using mediatek wireless, in nft_dev_fill_forward_path(), the
forward path is filled, ending with mediatek wlan1.

Because DEV_PATH_MTK_WDMA is unknown inside nft_dev_path_info() it returns
with info.indev = NULL. Then nft_dev_forward_path() returns without
setting the direct transmit parameters.

This results in a neighbor transmit, and direct transmit not possible.
But we want to use it for flow between bridged interfaces.

So this patch adds DEV_PATH_MTK_WDMA to nft_dev_path_info() and makes
direct transmission possible.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nft_flow_offload.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 323c531c7046..b9e6d9e6df66 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -105,6 +105,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 		switch (path->type) {
 		case DEV_PATH_ETHERNET:
 		case DEV_PATH_DSA:
+		case DEV_PATH_MTK_WDMA:
 		case DEV_PATH_VLAN:
 		case DEV_PATH_PPPOE:
 			info->indev = path->dev;
@@ -117,6 +118,10 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 				i = stack->num_paths;
 				break;
 			}
+			if (path->type == DEV_PATH_MTK_WDMA) {
+				i = stack->num_paths;
+				break;
+			}
 
 			/* DEV_PATH_VLAN and DEV_PATH_PPPOE */
 			if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:46 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:46 +0100
Subject: [PATCH v9 nf 12/15] netfilter: nft_flow_offload: No ingress_vlan forward info for dsa user port
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-13-ericwouds@gmail.com>

The bitfield info->ingress_vlans and corresponding vlan encap are used for
a switchdev user port. However, they should not be set for a dsa user port.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nft_flow_offload.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index b9e6d9e6df66..c95fad495460 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -116,6 +116,11 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 				break;
 			if (path->type == DEV_PATH_DSA) {
 				i = stack->num_paths;
+				if (!info->num_encaps ||
+				    !(info->ingress_vlans & BIT(info->num_encaps - 1)))
+					break;
+				info->num_encaps--;
+				info->ingress_vlans &= ~BIT(info->num_encaps - 1);
 				break;
 			}
 			if (path->type == DEV_PATH_MTK_WDMA) {
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:48 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:48 +0100
Subject: [PATCH v9 nf 14/15] bridge: Introduce DEV_PATH_BR_VLAN_KEEP_HW for bridge-fastpath
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-15-ericwouds@gmail.com>

This patch introduces DEV_PATH_BR_VLAN_KEEP_HW. It is needed in the
bridge fastpath for switchdevs supporting SWITCHDEV_OBJ_ID_PORT_VLAN.

It is similar to DEV_PATH_BR_VLAN_TAG, with the correcponding bit in
ingress_vlans set.

In the forward fastpath it is not needed.

Acked-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 include/linux/netdevice.h        |  1 +
 net/bridge/br_device.c           |  4 ++++
 net/bridge/br_vlan.c             | 18 +++++++++++-------
 net/netfilter/nft_flow_offload.c |  3 +++
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 81cdad85d9f1..1e2f519e8802 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -887,6 +887,7 @@ struct net_device_path {
 				DEV_PATH_BR_VLAN_TAG,
 				DEV_PATH_BR_VLAN_UNTAG,
 				DEV_PATH_BR_VLAN_UNTAG_HW,
+				DEV_PATH_BR_VLAN_KEEP_HW,
 			}		vlan_mode;
 			u16		vlan_id;
 			__be16		vlan_proto;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 02eb23e8aab8..55c64a1d2758 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -430,6 +430,10 @@ static int br_fill_forward_path(struct net_device_path_ctx *ctx,
 	case DEV_PATH_BR_VLAN_UNTAG:
 		ctx->num_vlans--;
 		break;
+	case DEV_PATH_BR_VLAN_KEEP_HW:
+		if (!src)
+			path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
+		break;
 	case DEV_PATH_BR_VLAN_KEEP:
 		break;
 	}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index aea94d401a30..114d47d5f90f 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1494,13 +1494,17 @@ int br_vlan_fill_forward_path_mode(struct net_bridge *br,
 	if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED))
 		return 0;
 
-	if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
-		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
-	else if (v->priv_flags & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
-		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
-	else
-		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
-
+	if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) {
+		if (v->priv_flags & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
+			path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP_HW;
+		else
+			path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
+	} else {
+		if (v->priv_flags & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
+			path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
+		else
+			path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
+	}
 	return 0;
 }
 
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index c95fad495460..c0c310c569cd 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -148,6 +148,9 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 			case DEV_PATH_BR_VLAN_UNTAG_HW:
 				info->ingress_vlans |= BIT(info->num_encaps - 1);
 				break;
+			case DEV_PATH_BR_VLAN_KEEP_HW:
+				info->ingress_vlans |= BIT(info->num_encaps);
+				fallthrough;
 			case DEV_PATH_BR_VLAN_TAG:
 				info->encap[info->num_encaps].id = path->bridge.vlan_id;
 				info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:47 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:47 +0100
Subject: [PATCH v9 nf 13/15] bridge: No DEV_PATH_BR_VLAN_UNTAG_HW for dsa foreign
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-14-ericwouds@gmail.com>

In network setup as below:

             fastpath bypass
 .----------------------------------------.
/                                          \
|                        IP - forwarding    |
|                       /                \  v
|                      /                  wan ...
|                     /
|                     |
|                     |
|                   brlan.1
|                     |
|    +-------------------------------+
|    |           vlan 1              |
|    |                               |
|    |     brlan (vlan-filtering)    |
|    |               +---------------+
|    |               |  DSA-SWITCH   |
|    |    vlan 1     |               |
|    |      to       |               |
|    |   untagged    1     vlan 1    |
|    +---------------+---------------+
.         /                   \
 ----->wlan1                 lan0
       .                       .
       .                       ^
       ^                     vlan 1 tagged packets
     untagged packets

br_vlan_fill_forward_path_mode() sets DEV_PATH_BR_VLAN_UNTAG_HW when
filling in from brlan.1 towards wlan1. But it should be set to
DEV_PATH_BR_VLAN_UNTAG in this case. Using BR_VLFLAG_ADDED_BY_SWITCHDEV
is not correct. The dsa switchdev adds it as a foreign port.

The same problem for all foreignly added dsa vlans on the bridge.

First add the vlan, trying only native devices.
If this fails, we know this may be a vlan from a foreign device.

Use BR_VLFLAG_TAGGING_BY_SWITCHDEV to make sure DEV_PATH_BR_VLAN_UNTAG_HW
is set only when there if no foreign device involved.

Acked-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 include/net/switchdev.h   |  1 +
 net/bridge/br_private.h   | 10 ++++++++++
 net/bridge/br_switchdev.c | 15 +++++++++++++++
 net/bridge/br_vlan.c      |  7 ++++++-
 net/switchdev/switchdev.c |  2 +-
 5 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 8346b0d29542..ee500706496b 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -15,6 +15,7 @@
 #define SWITCHDEV_F_NO_RECURSE		BIT(0)
 #define SWITCHDEV_F_SKIP_EOPNOTSUPP	BIT(1)
 #define SWITCHDEV_F_DEFER		BIT(2)
+#define SWITCHDEV_F_NO_FOREIGN		BIT(3)
 
 enum switchdev_attr_id {
 	SWITCHDEV_ATTR_ID_UNDEFINED,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a0b950390a16..b950db453d8d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -180,6 +180,7 @@ enum {
 	BR_VLFLAG_MCAST_ENABLED = BIT(2),
 	BR_VLFLAG_GLOBAL_MCAST_ENABLED = BIT(3),
 	BR_VLFLAG_NEIGH_SUPPRESS_ENABLED = BIT(4),
+	BR_VLFLAG_TAGGING_BY_SWITCHDEV = BIT(5),
 };
 
 /**
@@ -2184,6 +2185,8 @@ void br_switchdev_mdb_notify(struct net_device *dev,
 			     int type);
 int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
 			       bool changed, struct netlink_ext_ack *extack);
+int br_switchdev_port_vlan_no_foreign_add(struct net_device *dev, u16 vid, u16 flags,
+					  bool changed, struct netlink_ext_ack *extack);
 int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
 void br_switchdev_init(struct net_bridge *br);
 
@@ -2267,6 +2270,13 @@ static inline int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid,
 	return -EOPNOTSUPP;
 }
 
+static inline int br_switchdev_port_vlan_no_foreign_add(struct net_device *dev, u16 vid,
+							u16 flags, bool changed,
+							struct netlink_ext_ack *extack)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
 {
 	return -EOPNOTSUPP;
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 7b41ee8740cb..efa7a055b8f9 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -187,6 +187,21 @@ int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
 	return switchdev_port_obj_add(dev, &v.obj, extack);
 }
 
+int br_switchdev_port_vlan_no_foreign_add(struct net_device *dev, u16 vid, u16 flags,
+					  bool changed, struct netlink_ext_ack *extack)
+{
+	struct switchdev_obj_port_vlan v = {
+		.obj.orig_dev = dev,
+		.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+		.obj.flags = SWITCHDEV_F_NO_FOREIGN,
+		.flags = flags,
+		.vid = vid,
+		.changed = changed,
+	};
+
+	return switchdev_port_obj_add(dev, &v.obj, extack);
+}
+
 int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
 {
 	struct switchdev_obj_port_vlan v = {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index a18c7da12ebd..aea94d401a30 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -109,6 +109,11 @@ static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
 	/* Try switchdev op first. In case it is not supported, fallback to
 	 * 8021q add.
 	 */
+	err = br_switchdev_port_vlan_no_foreign_add(dev, v->vid, flags, false, extack);
+	if (err != -EOPNOTSUPP) {
+		v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV | BR_VLFLAG_TAGGING_BY_SWITCHDEV;
+		return err;
+	}
 	err = br_switchdev_port_vlan_add(dev, v->vid, flags, false, extack);
 	if (err == -EOPNOTSUPP)
 		return vlan_vid_add(dev, br->vlan_proto, v->vid);
@@ -1491,7 +1496,7 @@ int br_vlan_fill_forward_path_mode(struct net_bridge *br,
 
 	if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
 		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
-	else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)
+	else if (v->priv_flags & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
 		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
 	else
 		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 6488ead9e464..c48f66643e99 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -749,7 +749,7 @@ static int __switchdev_handle_port_obj_add(struct net_device *dev,
 	/* Event is neither on a bridge nor a LAG. Check whether it is on an
 	 * interface that is in a bridge with us.
 	 */
-	if (!foreign_dev_check_cb)
+	if (!foreign_dev_check_cb || port_obj_info->obj->flags & SWITCHDEV_F_NO_FOREIGN)
 		return err;
 
 	br = netdev_master_upper_dev_get(dev);
-- 
2.47.1



From ericwouds at gmail.com  Wed Mar  5 02:29:49 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed,  5 Mar 2025 11:29:49 +0100
Subject: [PATCH v9 nf 15/15] netfilter: nft_flow_offload: Add bridgeflow to nft_flow_offload_eval()
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <20250305102949.16370-16-ericwouds@gmail.com>

Edit nft_flow_offload_eval() to make it possible to handle a flowtable of
the nft bridge family.

Use nft_flow_offload_bridge_init() to fill the flow tuples. It uses
nft_dev_fill_bridge_path() in each direction.

Reviewed-by: Nikolay Aleksandrov <razor at blackwall.org>
Signed-off-by: Eric Woudstra <ericwouds at gmail.com>
---
 net/netfilter/nft_flow_offload.c | 142 +++++++++++++++++++++++++++++--
 1 file changed, 137 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index c0c310c569cd..03a0b5f7e8d2 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -193,6 +193,128 @@ static bool nft_flowtable_find_dev(const struct net_device *dev,
 	return found;
 }
 
+static int nft_dev_fill_bridge_path(struct flow_offload *flow,
+				    struct nft_flowtable *ft,
+				    enum ip_conntrack_dir dir,
+				    const struct net_device *src_dev,
+				    const struct net_device *dst_dev,
+				    unsigned char *src_ha,
+				    unsigned char *dst_ha)
+{
+	struct flow_offload_tuple_rhash *th = flow->tuplehash;
+	struct net_device_path_ctx ctx = {};
+	struct net_device_path_stack stack;
+	struct nft_forward_info info = {};
+	int i, j = 0;
+
+	for (i = th[dir].tuple.encap_num - 1; i >= 0 ; i--) {
+		if (info.num_encaps >= NF_FLOW_TABLE_ENCAP_MAX)
+			return -1;
+
+		if (th[dir].tuple.in_vlan_ingress & BIT(i))
+			continue;
+
+		info.encap[info.num_encaps].id = th[dir].tuple.encap[i].id;
+		info.encap[info.num_encaps].proto = th[dir].tuple.encap[i].proto;
+		info.num_encaps++;
+
+		if (th[dir].tuple.encap[i].proto == htons(ETH_P_PPP_SES))
+			continue;
+
+		if (ctx.num_vlans >= NET_DEVICE_PATH_VLAN_MAX)
+			return -1;
+		ctx.vlan[ctx.num_vlans].id = th[dir].tuple.encap[i].id;
+		ctx.vlan[ctx.num_vlans].proto = th[dir].tuple.encap[i].proto;
+		ctx.num_vlans++;
+	}
+	ctx.dev = src_dev;
+	ether_addr_copy(ctx.daddr, dst_ha);
+
+	if (dev_fill_bridge_path(&ctx, &stack) < 0)
+		return -1;
+
+	nft_dev_path_info(&stack, &info, dst_ha, &ft->data);
+
+	if (!info.indev || info.indev != dst_dev)
+		return -1;
+
+	th[!dir].tuple.iifidx = info.indev->ifindex;
+	for (i = info.num_encaps - 1; i >= 0; i--) {
+		th[!dir].tuple.encap[j].id = info.encap[i].id;
+		th[!dir].tuple.encap[j].proto = info.encap[i].proto;
+		if (info.ingress_vlans & BIT(i))
+			th[!dir].tuple.in_vlan_ingress |= BIT(j);
+		j++;
+	}
+	th[!dir].tuple.encap_num = info.num_encaps;
+
+	th[dir].tuple.mtu = dst_dev->mtu;
+	ether_addr_copy(th[dir].tuple.out.h_source, src_ha);
+	ether_addr_copy(th[dir].tuple.out.h_dest, dst_ha);
+	th[dir].tuple.out.ifidx = info.outdev->ifindex;
+	th[dir].tuple.xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
+
+	return 0;
+}
+
+static int nft_flow_offload_bridge_init(struct flow_offload *flow,
+					const struct nft_pktinfo *pkt,
+					enum ip_conntrack_dir dir,
+					struct nft_flowtable *ft)
+{
+	const struct net_device *in_dev, *out_dev;
+	struct ethhdr *eth = eth_hdr(pkt->skb);
+	struct flow_offload_tuple *tuple;
+	struct pppoe_hdr *phdr;
+	struct vlan_hdr *vhdr;
+	int err, i = 0;
+
+	in_dev = nft_in(pkt);
+	if (!in_dev || !nft_flowtable_find_dev(in_dev, ft))
+		return -1;
+
+	out_dev = nft_out(pkt);
+	if (!out_dev || !nft_flowtable_find_dev(out_dev, ft))
+		return -1;
+
+	tuple =  &flow->tuplehash[!dir].tuple;
+
+	if (skb_vlan_tag_present(pkt->skb)) {
+		tuple->encap[i].id = skb_vlan_tag_get(pkt->skb);
+		tuple->encap[i].proto = pkt->skb->vlan_proto;
+		i++;
+	}
+	switch (pkt->skb->protocol) {
+	case htons(ETH_P_8021Q):
+		vhdr = (struct vlan_hdr *)skb_network_header(pkt->skb);
+		tuple->encap[i].id = ntohs(vhdr->h_vlan_TCI);
+		tuple->encap[i].proto = pkt->skb->protocol;
+		i++;
+		break;
+	case htons(ETH_P_PPP_SES):
+		phdr = (struct pppoe_hdr *)skb_network_header(pkt->skb);
+		tuple->encap[i].id = ntohs(phdr->sid);
+		tuple->encap[i].proto = pkt->skb->protocol;
+		i++;
+		break;
+	}
+	tuple->encap_num = i;
+
+	err = nft_dev_fill_bridge_path(flow, ft, !dir, out_dev, in_dev,
+				       eth->h_dest, eth->h_source);
+	if (err < 0)
+		return err;
+
+	memset(tuple->encap, 0, sizeof(tuple->encap));
+
+	err = nft_dev_fill_bridge_path(flow, ft, dir, in_dev, out_dev,
+				       eth->h_source, eth->h_dest);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static void nft_dev_forward_path(struct nf_flow_route *route,
 				 const struct nf_conn *ct,
 				 enum ip_conntrack_dir dir,
@@ -311,6 +433,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
 	struct nft_flow_offload *priv = nft_expr_priv(expr);
 	struct nf_flowtable *flowtable = &priv->flowtable->data;
+	bool routing = flowtable->type->family != NFPROTO_BRIDGE;
 	struct tcphdr _tcph, *tcph = NULL;
 	struct nf_flow_route route = {};
 	enum ip_conntrack_info ctinfo;
@@ -364,14 +487,21 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 		goto out;
 
 	dir = CTINFO2DIR(ctinfo);
-	if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0)
-		goto err_flow_route;
+	if (routing) {
+		if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0)
+			goto err_flow_route;
+	}
 
 	flow = flow_offload_alloc(ct);
 	if (!flow)
 		goto err_flow_alloc;
 
-	flow_offload_route_init(flow, &route);
+	if (routing)
+		flow_offload_route_init(flow, &route);
+	else
+		if (nft_flow_offload_bridge_init(flow, pkt, dir, priv->flowtable) < 0)
+			goto err_flow_add;
+
 	if (tcph)
 		flow_offload_ct_tcp(ct);
 
@@ -419,8 +549,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 err_flow_add:
 	flow_offload_free(flow);
 err_flow_alloc:
-	dst_release(route.tuple[dir].dst);
-	dst_release(route.tuple[!dir].dst);
+	if (routing) {
+		dst_release(route.tuple[dir].dst);
+		dst_release(route.tuple[!dir].dst);
+	}
 err_flow_route:
 	clear_bit(IPS_OFFLOAD_BIT, &ct->status);
 out:
-- 
2.47.1



From andy at kernel.org  Wed Mar  5 02:30:21 2025
From: andy at kernel.org (Andy Shevchenko)
Date: Wed, 5 Mar 2025 12:30:21 +0200
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <20250305101025.2279951-2-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
Message-ID: <Z8gnvXQ9OMXoq9Fz@smile.fi.intel.com>

On Wed, Mar 05, 2025 at 10:10:24AM +0000, George Cherian wrote:
> A new option flag is added to watchdog_info. This helps the watchdog
> core to check whether stop functions would sleep or not.
> The option flags of individual drivers are also updated accordingly.

...

>  	.options =	WDIOF_SETTIMEOUT |
>  			WDIOF_MAGICCLOSE |
> -			WDIOF_KEEPALIVEPING,
> +			WDIOF_KEEPALIVEPING |
> +			WDIOF_STOP_MAYSLEEP,

You may heavily reduce this change if you squeeze the new option just before
the last one. Currently it's a lot of unneeded churn that makes review a bit
harder (each needs to be carefully checked for the correctness).

-- 
With Best Regards,
Andy Shevchenko




From hanchunchao at inspur.com  Wed Mar  5 02:30:42 2025
From: hanchunchao at inspur.com (Charles Han)
Date: Wed, 5 Mar 2025 18:30:42 +0800
Subject: [PATCH] drm/imx: legacy-bridge: fix inconsistent indenting warning
Message-ID: <20250305103042.3017-1-hanchunchao@inspur.com>

Fix below inconsistent indenting smatch warning.
smatch warnings:
drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c:79 devm_imx_drm_legacy_bridge() warn: inconsistent indenting

Signed-off-by: Charles Han <hanchunchao at inspur.com>
---
 drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
index 3ebf0b9866de..55a763045812 100644
--- a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
+++ b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
@@ -76,9 +76,9 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev,
 	imx_bridge->base.ops = DRM_BRIDGE_OP_MODES;
 	imx_bridge->base.type = type;
 
-       ret = devm_drm_bridge_add(dev, &imx_bridge->base);
-       if (ret)
-               return ERR_PTR(ret);
+	ret = devm_drm_bridge_add(dev, &imx_bridge->base);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return &imx_bridge->base;
 }
-- 
2.43.0



From wbg at kernel.org  Wed Mar  5 02:31:27 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Wed, 5 Mar 2025 19:31:27 +0900
Subject: [PATCH] counter: microchip-tcb-capture: Fix undefined counter
 channel state on probe
In-Reply-To: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
References: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
Message-ID: <Z8gn_4qxtEqbn20O@ishi>

On Wed, Mar 05, 2025 at 07:01:19PM +0900, William Breathitt Gray wrote:
> Hardware initialize of the timer counter channel does not occur on probe
> thus leaving the Count in an undefined state until the first
> function_write() callback is executed. Fix this by performing the proper
> hardware initialization during probe.
> 
> Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
> Reported-by: Cs?k?s Bence <csokas.bence at prolan.hu>
> Closes: https://lore.kernel.org/all/bfa70e78-3cc3-4295-820b-3925c26135cb at prolan.hu/
> Signed-off-by: William Breathitt Gray <wbg at kernel.org>
> ---
> This should fix the issue where a user needs to set the count function
> before they can use the counter. I don't have this hardware in person,
> so please test this patch and let me know whether it works for you.

While developing this bug fix, I noticed the following code in the
mchp_tc_count_function_write() function:

	if (!priv->tc_cfg->has_gclk)
		cmr |= ATMEL_TC_TIMER_CLOCK2;
	else
		cmr |= ATMEL_TC_TIMER_CLOCK1;
	/* Setup the period capture mode */
	cmr |=  ATMEL_TC_CMR_MASK;
	cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0);

It looks like it's trying to choose the TCCLKS value by evaluating
has_gclk. However, a couple lines later the cmr value is masked by
ATMEL_TC_XC0 which will clobber the previous choice by resetting bit 0.

Is this a bug, or am I misunderstanding how the TCCLKS value is set by
these defines?

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/67e1c2da/attachment.sig>

From andy at kernel.org  Wed Mar  5 02:31:22 2025
From: andy at kernel.org (Andy Shevchenko)
Date: Wed, 5 Mar 2025 12:31:22 +0200
Subject: [PATCH v4 0/2] Add stop_on_panic support for watchdog
In-Reply-To: <20250305101025.2279951-1-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
Message-ID: <Z8gn-jxUH_7FT4b2@smile.fi.intel.com>

On Wed, Mar 05, 2025 at 10:10:23AM +0000, George Cherian wrote:
> This series adds a new kernel command line option to watchdog core to
> stop the watchdog on panic. This is useul in certain systems which prevents
> successful loading of kdump kernel due to watchdog reset.
> 
> Some of the watchdog drivers stop function could sleep. For such
> drivers the stop_on_panic is not valid as the notifier callback happens
> in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
> options to indicate whether the stop function would sleep.

Should you only enable this if the kdump is enabled in the kernel configuration?

-- 
With Best Regards,
Andy Shevchenko




From mwalle at kernel.org  Wed Mar  5 02:31:36 2025
From: mwalle at kernel.org (Michael Walle)
Date: Wed, 05 Mar 2025 11:31:36 +0100
Subject: [PATCH 2/2] ARM: dts: microchip: sama5d29_curiosity: Add
 nvmem-layout in QSPI to describe EUI48 MAC address region
In-Reply-To: <20250305100134.1171124-2-manikandan.m@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
 <20250305100134.1171124-2-manikandan.m@microchip.com>
Message-ID: <D889HZF97H8U.1UUX54BAVLAC3@kernel.org>

On Wed Mar 5, 2025 at 11:01 AM CET, Manikandan Muralidharan wrote:
> Add nvmem-layout in QSPI to describe EUI48 MAC address region.
> This is useful for cases where U-Boot is skipped and the Ethernet
> MAC address is needed to be configured in Linux.
>
> Signed-off-by: Manikandan Muralidharan <manikandan.m at microchip.com>
> ---
>  .../arm/boot/dts/microchip/at91-sama5d29_curiosity.dts | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
> index 7be215781549..81aca8502195 100644
> --- a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
> +++ b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
> @@ -480,6 +480,16 @@ flash at 0 {
>  		label = "atmel_qspi1";
>  		status = "okay";
>  
> +		nvmem-layout {
> +			compatible = "fixed-layout";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			mac_address_eui48: mac-address at 261 {

I don't think the offset should be hardcoded in the device tree.
Apparently it is a property of this very chip (and not backed up by
a JEDEC standard). What happens if the SFDP are changed for this
flash? I.e. The length of the SFDP region changes.

Also, this looks like it is a layout for the SPI flash contents and
not the SFDP, how do you differentiate between these two? Also
please update your device tree to use 'compatible =
"fixed-partitions"'.

-michael

> +				reg = <0x261 0x6>;
> +			};
> +		};



> +
>  		at91bootstrap at 0 {
>  			label = "at91bootstrap";
>  			reg = <0x0 0x40000>;



From andy at kernel.org  Wed Mar  5 02:33:41 2025
From: andy at kernel.org (Andy Shevchenko)
Date: Wed, 5 Mar 2025 12:33:41 +0200
Subject: [PATCH v4 2/2] drivers: watchdog: Add support for panic notifier
 callback
In-Reply-To: <20250305101025.2279951-3-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-3-george.cherian@marvell.com>
Message-ID: <Z8gohVIQqlA6QquZ@smile.fi.intel.com>

On Wed, Mar 05, 2025 at 10:10:25AM +0000, George Cherian wrote:
> Watchdog is not turned off in kernel panic situation.
> In certain systems this might prevent the successful loading
> of kdump kernel. The kdump kernel might hit a watchdog reset
> while it is booting.
> 
> To avoid such scenarios add a panic notifier call back function
> which can stop the watchdog. This provision can be enabled by
> passing watchdog.stop_on_panic=1 via kernel command-line parameter.

...

First of all, do we really need a new module parameter for that? Why can't it
be done automatically if kdump is expected?

> +static bool stop_on_panic;
> +module_param(stop_on_panic, bool, 0444);
> +MODULE_PARM_DESC(stop_on_panic, "Stop watchdogs on panic (0=keep watching, 1=stop)");

+ blank line.

Also I do not see the documentation update. Where is it lost?

>  /*

-- 
With Best Regards,
Andy Shevchenko




From gcherian at marvell.com  Wed Mar  5 02:34:49 2025
From: gcherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 10:34:49 +0000
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
Message-ID: <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>

From: Marek Beh?n <kabel at kernel.org> 
Sent: Wednesday, March 5, 2025 3:48 PM
To: George Cherian <gcherian at marvell.com>
Cc: linux at roeck-us.net; wim at linux-watchdog.org; jwerner at chromium.org; evanbenn at chromium.org; krzk at kernel.org; mazziesaccount at gmail.com; thomas.richard at bootlin.com; lma at chromium.org; bleung at chromium.org; support.opensource at diasemi.com; shawnguo at kernel.org; s.hauer at pengutronix.de; kernel at pengutronix.de; festevam at gmail.com; andy at kernel.org; paul at crapouillou.net; alexander.usyskin at intel.com; andreas.werner at men.de; daniel at thingy.jp; romain.perier at gmail.com; avifishman70 at gmail.com; tmaimon77 at gmail.com; tali.perry1 at gmail.com; venture at google.com; yuenn at google.com; benjaminfair at google.com; maddy at linux.ibm.com; mpe at ellerman.id.au; npiggin at gmail.com; christophe.leroy at csgroup.eu; naveen at kernel.org; mwalle at kernel.org; xingyu.wu at starfivetech.com; ziv.xu at starfivetech.com; hayashi.kunihiko at socionext.com; mhiramat at kernel.org; linux-watchdog at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; chrome-platform at lists.linux.dev; imx at lists.linux.dev; linux-mips at vger.kernel.org; openbmc at lists.ozlabs.org; linuxppc-dev at lists.ozlabs.org; patches at opensource.cirrus.com
Subject: Re: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
> Hi George,
>
> why is armada_37xx_wdt also here?
> The stop function in that driver may not sleep.
Marek,

Thanks for reviewing.
Since the stop function has a regmap_write(), I thought it might sleep.
Now that you pointed it out, I assume that it is an MMIO based regmap being used for armada.
I will update the same in the next version

>
> Marek

-George

From aliceryhl at google.com  Wed Mar  5 02:36:22 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Wed, 5 Mar 2025 10:36:22 +0000
Subject: [PATCH v3 5/5] rust: Add warn_on and warn_on_once
In-Reply-To: <20250305.192403.996225631653343672.fujita.tomonori@gmail.com>
References: <20250213135759.190006-1-fujita.tomonori@gmail.com>
 <20250213135759.190006-6-fujita.tomonori@gmail.com> <Z8gOkeJ8o2pMCwGu@google.com>
 <20250305.192403.996225631653343672.fujita.tomonori@gmail.com>
Message-ID: <Z8gpJsQlkjAQ0EwU@google.com>

On Wed, Mar 05, 2025 at 07:24:03PM +0900, FUJITA Tomonori wrote:
> On Wed, 5 Mar 2025 08:42:57 +0000
> Alice Ryhl <aliceryhl at google.com> wrote:
> 
> > On Thu, Feb 13, 2025 at 10:57:59PM +0900, FUJITA Tomonori wrote:
> >> Add warn_on and warn_on_once macros. Wrapping the C's WARN_* and BUG_*
> >> macros doesn't work so this uses the assembly code exported by the C
> >> side via ARCH_WARN_ASM macro. Like the static branch code, this
> >> generates the assembly code for rust at compile time by using the C
> >> preprocessor.
> >> 
> >> file()! macro doesn't work for the Rust inline assembly in the same
> >> way as __FILE__ for the C inline assembly. So the code to handle a
> >> file name is different from the C assembly code (similar to the
> >> arm64/loongarch assembly).
> > 
> > Nit: Should be file!() not file()!.
> 
> Ops, thanks.
> 
> Actually, the above comment is obsolete. With your solution in the
> previous mail, I can remove the asm code for the file name. I'll
> remove the comment.
> 
> 
> >> diff --git a/rust/kernel/.gitignore b/rust/kernel/.gitignore
> >> index 6ba39a178f30..f1d7f4225332 100644
> >> --- a/rust/kernel/.gitignore
> >> +++ b/rust/kernel/.gitignore
> >> @@ -1,3 +1,5 @@
> >>  # SPDX-License-Identifier: GPL-2.0
> >>  
> >>  /generated_arch_static_branch_asm.rs
> >> +/generated_arch_warn_asm.rs
> >> +/generated_arch_reachable_asm.rs
> >> \ No newline at end of file
> > 
> > There should be a newline.
> 
> Ah, I'll fix.
> 
> >> +++ b/rust/kernel/bug.rs
> >> @@ -0,0 +1,100 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +
> >> +// Copyright (C) 2024 FUJITA Tomonori
> > 
> > 2025?
> 
> I'll add.
> 
> >> +#[macro_export]
> >> +#[doc(hidden)]
> >> +#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
> >> +macro_rules! warn_flags {
> >> +    ($flags:expr) => {
> >> +        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
> >> +        // SAFETY: Just an FFI call.
> >> +        #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
> >> +        unsafe {
> >> +            $crate::asm!(concat!(
> >> +                "/* {size} */",
> >> +                ".pushsection .rodata.str1.1, \"aMS\", at progbits, 1\n",
> >> +                "111:\t .string ", "\"", file!(), "\"\n",
> >> +                ".popsection\n",
> >> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
> >> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
> >> +            line = const line!(),
> >> +            flags = const FLAGS,
> >> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
> >> +            );
> >> +        }
> >> +        // SAFETY: Just an FFI call.
> >> +        #[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
> >> +        unsafe {
> >> +            $crate::asm!(
> >> +            concat!(
> >> +                "/* {size} */",
> >> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
> >> +                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
> >> +            flags = const FLAGS,
> >> +            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
> >> +            );
> >> +        }
> > 
> > I generally prefer to have the cfgs on the macro rather in its
> > expansion. That avoids emitting a lot of code that is not actually used.
> 
> You prefer the following?
> 
> #[cfg(all(CONFIG_BUG, CONFIG_DEBUG_BUGVERBOSE, not(CONFIG_UML)))]
> macro_rules! warn_flags {
> ...
> }
> 
> #[cfg(all(CONFIG_BUG, not(CONFIG_DEBUG_BUGVERBOSE), not(CONFIG_UML)))]
> macro_rules! warn_flags {
> ...
> }

In this case it probably reads better as

#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
macro_rules! warn_flags {
...
}

#[cfg(all(CONFIG_BUG, not(CONFIG_UML)))]
#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
macro_rules! warn_flags {
...
}

but yes.

> >> +#[doc(hidden)]
> >> +#[macro_export]
> >> +macro_rules! bugflag_taint {
> >> +    ($taint:expr) => {
> >> +        $taint << 8
> >> +    };
> >> +}
> > 
> > This could just be a const fn.
> 
> Yeah, would a const fn be preferable?

Yes, I think a constant or const fn is preferable over a macro whenever
possible.

> >> +/// Report a warning only once.
> >> +#[macro_export]
> >> +macro_rules! warn_on_once {
> >> +    ($cond:expr) => {
> >> +        if $cond {
> >> +            $crate::warn_flags!(
> >> +                $crate::bindings::BUGFLAG_ONCE
> >> +                    | $crate::bugflag_taint!($crate::bindings::TAINT_WARN)
> > 
> > Or maybe a constant?
> > 
> > const WARN_ON_ONCE_FLAGS: u32 = bindings::BUGFLAG_ONCE | (bindings::TAINT_WARN << 8);
> 
> Ok, but you prefer "<< 8" than using const fn bugflag_taint()?

I'm also happy with
const WARN_ON_ONCE_FLAGS: u32 = bindings::BUGFLAG_ONCE | bugflag_taint(bindings::TAINT_WARN);

Up to you.

Alice


From a.fatoum at pengutronix.de  Wed Mar  5 02:41:49 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 5 Mar 2025 11:41:49 +0100
Subject: [PATCH v4 0/2] Add stop_on_panic support for watchdog
In-Reply-To: <20250305101025.2279951-1-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
Message-ID: <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>

Hi George,

On 05.03.25 11:10, George Cherian wrote:
> This series adds a new kernel command line option to watchdog core to
> stop the watchdog on panic. This is useul in certain systems which prevents
> successful loading of kdump kernel due to watchdog reset.
> 
> Some of the watchdog drivers stop function could sleep. For such
> drivers the stop_on_panic is not valid as the notifier callback happens
> in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
> options to indicate whether the stop function would sleep.

Did you consider having a reset_on_panic instead, which sets a user-specified
timeout on panic? This would make the mechanism useful also for watchdogs
that can't be disabled and would protect against system lock up:
Consider a memory-corruption bug (perhaps externally via DMA), which partially
overwrites both main and kdump kernel. With a disabled watchdog, the system
may not be able to recover on its own.

If you did consider it, what made you decide against it?

Thanks,
Ahmad

> 
> 
> Changelog:
> v1 -> v2
> - Remove the per driver flag setting option
> - Take the parameter via kernel command-line parameter to watchdog_core.
> 
> v2 -> v3
> - Remove the helper function watchdog_stop_on_panic() from watchdog.h.
> - There are no users for this. 
> 
> v3 -> v4
> - Since the panic notifier is in atomic context, watchdog functions
>   which sleep can't be called. 
> - Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
>   function sleeps.
> - Simplify the stop_on_panic kernel command line parsing.
> - Enable the panic notiffier only if the watchdog stop function doesn't
>   sleep
> 
> George Cherian (2):
>   watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
>   drivers: watchdog: Add support for panic notifier callback
> 
>  drivers/watchdog/advantech_ec_wdt.c |  3 ++-
>  drivers/watchdog/arm_smc_wdt.c      |  3 ++-
>  drivers/watchdog/armada_37xx_wdt.c  |  2 +-
>  drivers/watchdog/asm9260_wdt.c      |  2 +-
>  drivers/watchdog/bcm47xx_wdt.c      |  3 ++-
>  drivers/watchdog/bd9576_wdt.c       |  2 +-
>  drivers/watchdog/bd96801_wdt.c      |  2 +-
>  drivers/watchdog/cgbc_wdt.c         |  2 +-
>  drivers/watchdog/cros_ec_wdt.c      |  5 ++++-
>  drivers/watchdog/da9052_wdt.c       |  3 ++-
>  drivers/watchdog/da9055_wdt.c       |  4 +++-
>  drivers/watchdog/da9062_wdt.c       |  4 +++-
>  drivers/watchdog/da9063_wdt.c       |  4 +++-
>  drivers/watchdog/db8500_wdt.c       |  5 ++++-
>  drivers/watchdog/dw_wdt.c           |  5 +++--
>  drivers/watchdog/f71808e_wdt.c      |  3 ++-
>  drivers/watchdog/gpio_wdt.c         |  2 +-
>  drivers/watchdog/i6300esb.c         |  5 ++++-
>  drivers/watchdog/imx_sc_wdt.c       |  2 +-
>  drivers/watchdog/intel-mid_wdt.c    |  5 ++++-
>  drivers/watchdog/it87_wdt.c         |  5 ++++-
>  drivers/watchdog/jz4740_wdt.c       |  5 ++++-
>  drivers/watchdog/kempld_wdt.c       |  3 ++-
>  drivers/watchdog/lenovo_se10_wdt.c  |  5 ++++-
>  drivers/watchdog/max77620_wdt.c     |  5 ++++-
>  drivers/watchdog/mei_wdt.c          |  3 ++-
>  drivers/watchdog/menf21bmc_wdt.c    |  4 +++-
>  drivers/watchdog/mlx_wdt.c          |  2 +-
>  drivers/watchdog/msc313e_wdt.c      |  5 ++++-
>  drivers/watchdog/npcm_wdt.c         |  3 ++-
>  drivers/watchdog/omap_wdt.c         |  5 ++++-
>  drivers/watchdog/pm8916_wdt.c       |  5 +++--
>  drivers/watchdog/pseries-wdt.c      |  2 +-
>  drivers/watchdog/rave-sp-wdt.c      |  5 ++++-
>  drivers/watchdog/renesas_wdt.c      |  7 ++++--
>  drivers/watchdog/retu_wdt.c         |  5 ++++-
>  drivers/watchdog/rn5t618_wdt.c      |  6 +++--
>  drivers/watchdog/rzg2l_wdt.c        |  5 ++++-
>  drivers/watchdog/rzv2h_wdt.c        |  5 ++++-
>  drivers/watchdog/shwdt.c            |  6 +++--
>  drivers/watchdog/sl28cpld_wdt.c     |  5 ++++-
>  drivers/watchdog/softdog.c          |  5 ++++-
>  drivers/watchdog/sp805_wdt.c        |  5 ++++-
>  drivers/watchdog/starfive-wdt.c     |  3 ++-
>  drivers/watchdog/stpmic1_wdt.c      |  5 ++++-
>  drivers/watchdog/ts4800_wdt.c       |  5 ++++-
>  drivers/watchdog/twl4030_wdt.c      |  5 ++++-
>  drivers/watchdog/uniphier_wdt.c     |  3 ++-
>  drivers/watchdog/w83627hf_wdt.c     |  5 ++++-
>  drivers/watchdog/watchdog_core.c    | 35 +++++++++++++++++++++++++++++
>  drivers/watchdog/wm831x_wdt.c       |  5 ++++-
>  drivers/watchdog/wm8350_wdt.c       |  5 ++++-
>  drivers/watchdog/xen_wdt.c          |  5 ++++-
>  drivers/watchdog/ziirave_wdt.c      |  5 ++++-
>  include/linux/watchdog.h            |  2 ++
>  include/uapi/linux/watchdog.h       |  1 +
>  56 files changed, 198 insertions(+), 58 deletions(-)
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From ziyao at disroot.org  Wed Mar  5 02:49:21 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed, 5 Mar 2025 10:49:21 +0000
Subject: [PATCH 6/8] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in
 GRF region
In-Reply-To: <2583035.OBFZWjSADL@diego>
References: <20250301104250.36295-1-ziyao@disroot.org>
 <20250301104724.36399-1-ziyao@disroot.org>
 <2583035.OBFZWjSADL@diego>
Message-ID: <Z8gsGlZ7GgNF-zoc@pie.lan>

On Wed, Mar 05, 2025 at 11:21:48AM +0100, Heiko St?bner wrote:
> Hi,
> 
> Am Samstag, 1. M?rz 2025, 11:47:24 MEZ schrieb Yao Zi:
> > These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
> > tuning purpose. Add their definitions and register them in driver if
> > corresponding GRF is available.
> 
> (no critique, just an observation :-) )
> 
> this puts a completely new meaning on the "general register files"
> as dumping ground ;-) .
> 
> Whoever got the idea of making sdmm/sdio tuning controls part
> of GRFs that are supposed display and/or video encoder parts :-D

Yes, the register layout is quite weird. Additionally some USB2 phy
registers locate in VO GRF as well...

> 
> > GRFs are looked up by compatible to simplify devicetree binding.
> > 
> > Signed-off-by: Yao Zi <ziyao at disroot.org>
> > ---
> 
> >  static int __init clk_rk3528_probe(struct platform_device *pdev)
> >  {
> > +	unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
> > +	unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
> > +	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
> >  	struct rockchip_clk_provider *ctx;
> >  	struct device *dev = &pdev->dev;
> >  	struct device_node *np = dev->of_node;
> > -	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
> > -	unsigned long nr_clks;
> > +	struct regmap *vo_grf, *vpu_grf;
> >  	void __iomem *reg_base;
> > -
> > -	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
> > -					       nr_branches) + 1;
> > +	unsigned long nr_clks;
> >  
> >  	reg_base = devm_platform_ioremap_resource(pdev, 0);
> >  	if (IS_ERR(reg_base))
> >  		return dev_err_probe(dev, PTR_ERR(reg_base),
> >  				     "could not map cru region");
> >  
> > +	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
> > +					       nr_branches) + 1;
> > +
> > +	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
> > +	if (!IS_ERR(vo_grf))
> 
> for readability, please make this into something like
> 	if (!IS_ERR(vo_grf)) {
> 		nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
> 							   nr_vo_branches) + 1;
> 		nr_clks = max(nr_vo_clks, nr_clks);
> 	}

Thanks for the suggestion, will take it.

> > +	else if (PTR_ERR(vo_grf) != ENODEV)
> > +		return dev_err_probe(dev, PTR_ERR(vo_grf),
> > +				     "failed to look up VO GRF\n");
> > +
> > +	vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
> > +	if (!IS_ERR(vpu_grf))
> > +		nr_clks = MAX(rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
> > +							   nr_vpu_branches) + 1,
> > +			      nr_clks);
> 
> same here please
> 
> > +	else if (PTR_ERR(vpu_grf) != ENODEV)
> > +		return dev_err_probe(dev, PTR_ERR(vpu_grf),
> > +				     "failed to look up VPU GRF\n");
> > +
> >  	ctx = rockchip_clk_init(np, reg_base, nr_clks);
> >  	if (IS_ERR(ctx))
> >  		return dev_err_probe(dev, PTR_ERR(ctx),
> 
> Thanks
> Heiko
> 

Cheers,
Yao Zi


From vschneid at redhat.com  Wed Mar  5 02:49:24 2025
From: vschneid at redhat.com (Valentin Schneider)
Date: Wed,  5 Mar 2025 11:49:24 +0100
Subject: [PATCH 0/1] arm64: enable PREEMPT_LAZY
Message-ID: <20250305104925.189198-1-vschneid@redhat.com>

Hey folks,

This is a resubmission of Mark's patch [1]. I didn't end up changing anything
other than fluffing up the changelog.

I ran this under an arm64 VM, added some trace_printk's and checked that
sched_switch's between runnable hackbench threads would occurr in the right
conditions:
o with TIF_NEED_RESCHED_LAZY set
  o at the tick
  o at do_notify_resume()
o with TIF_NEED_RESCHED set  

[1]: https://lore.kernel.org/linux-rt-users/Z2B5y3HiLuRHPfdv at J2N7QTR9R3.cambridge.arm.com/

Cheers,
Valentin

Mark Rutland (1):
  arm64: enable PREEMPT_LAZY

 arch/arm64/Kconfig                   |  1 +
 arch/arm64/include/asm/thread_info.h | 16 +++++++++-------
 arch/arm64/kernel/entry-common.c     |  2 +-
 3 files changed, 11 insertions(+), 8 deletions(-)

--
2.43.0



From vschneid at redhat.com  Wed Mar  5 02:49:25 2025
From: vschneid at redhat.com (Valentin Schneider)
Date: Wed,  5 Mar 2025 11:49:25 +0100
Subject: [PATCH 1/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <20250305104925.189198-1-vschneid@redhat.com>
References: <20250305104925.189198-1-vschneid@redhat.com>
Message-ID: <20250305104925.189198-2-vschneid@redhat.com>

From: Mark Rutland <mark.rutland at arm.com>

For an architecture to enable CONFIG_ARCH_HAS_RESCHED_LAZY, two things are
required:
1) Adding a TIF_NEED_RESCHED_LAZY flag definition
2) Checking for TIF_NEED_RESCHED_LAZY in the appropriate locations

2) is handled in a generic manner by CONFIG_GENERIC_ENTRY, which isn't
(yet) implemented for arm64. However, outside of core scheduler code,
TIF_NEED_RESCHED_LAZY only needs to be checked on a kernel exit, meaning:
o return/entry to userspace.
o return/entry to guest.

The return/entry to a guest is all handled by xfer_to_guest_mode_handle_work()
which already does the right thing, so it can be left as-is.

arm64 doesn't use common entry's exit_to_user_mode_prepare(), so update its
return to user path to check for TIF_NEED_RESCHED_LAZY and call into
schedule() accordingly.

Link: https://lore.kernel.org/linux-rt-users/20241216190451.1c61977c at mordecai.tesarici.cz/
Link: https://lore.kernel.org/all/xhsmh4j0fl0p3.mognet at vschneid-thinkpadt14sgen2i.remote.csb/
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
[testdrive, _TIF_WORK_MASK fixlet and changelog.]
Signed-off-by: Mike Galbraith <efault at gmx.de>
[Another round of testing; changelog faff]
Signed-off-by: Valentin Schneider <vschneid at redhat.com>
---
 arch/arm64/Kconfig                   |  1 +
 arch/arm64/include/asm/thread_info.h | 16 +++++++++-------
 arch/arm64/kernel/entry-common.c     |  2 +-
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fcdd0ed3eca89..7789d7fb6f191 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -41,6 +41,7 @@ config ARM64
 	select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
 	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT
+	select ARCH_HAS_PREEMPT_LAZY
 	select ARCH_HAS_PTE_DEVMAP
 	select ARCH_HAS_PTE_SPECIAL
 	select ARCH_HAS_HW_PTE_YOUNG
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 1114c1c3300a1..4443ef2789758 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -59,11 +59,12 @@ void arch_setup_new_exec(void);
 
 #define TIF_SIGPENDING		0	/* signal pending */
 #define TIF_NEED_RESCHED	1	/* rescheduling necessary */
-#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
-#define TIF_FOREIGN_FPSTATE	3	/* CPU's FP state is not current's */
-#define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
-#define TIF_MTE_ASYNC_FAULT	5	/* MTE Asynchronous Tag Check Fault */
-#define TIF_NOTIFY_SIGNAL	6	/* signal notifications exist */
+#define TIF_NEED_RESCHED_LAZY	2	/* Lazy rescheduling needed */
+#define TIF_NOTIFY_RESUME	3	/* callback before returning to user */
+#define TIF_FOREIGN_FPSTATE	4	/* CPU's FP state is not current's */
+#define TIF_UPROBE		5	/* uprobe breakpoint or singlestep */
+#define TIF_MTE_ASYNC_FAULT	6	/* MTE Asynchronous Tag Check Fault */
+#define TIF_NOTIFY_SIGNAL	7	/* signal notifications exist */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing */
 #define TIF_SYSCALL_TRACEPOINT	10	/* syscall tracepoint for ftrace */
@@ -85,6 +86,7 @@ void arch_setup_new_exec(void);
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY	(1 << TIF_NEED_RESCHED_LAZY)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_FOREIGN_FPSTATE	(1 << TIF_FOREIGN_FPSTATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -100,10 +102,10 @@ void arch_setup_new_exec(void);
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
 #define _TIF_TSC_SIGSEGV	(1 << TIF_TSC_SIGSEGV)
 
-#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
 				 _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
-				 _TIF_NOTIFY_SIGNAL)
+				 _TIF_NOTIFY_SIGNAL | _TIF_SIGPENDING)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index b260ddc4d3e9a..7993fab0cab4c 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -132,7 +132,7 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 	do {
 		local_irq_enable();
 
-		if (thread_flags & _TIF_NEED_RESCHED)
+		if (thread_flags & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY))
 			schedule();
 
 		if (thread_flags & _TIF_UPROBE)
-- 
2.43.0



From csokas.bence at prolan.hu  Wed Mar  5 02:50:27 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Wed, 5 Mar 2025 11:50:27 +0100
Subject: [PATCH] counter: microchip-tcb-capture: Fix undefined counter
 channel state on probe
In-Reply-To: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
References: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
Message-ID: <93ce1511-53f6-42a3-b1a5-b6732105e87d@prolan.hu>

Hi,

thanks for fixing this up!

On 2025. 03. 05. 11:01, William Breathitt Gray wrote:
> Hardware initialize of the timer counter channel does not occur on probe
> thus leaving the Count in an undefined state until the first
> function_write() callback is executed. Fix this by performing the proper
> hardware initialization during probe.
> 
> Fixes: 106b104137fd ("counter: Add microchip TCB capture counter")
> Reported-by: Cs?k?s Bence <csokas.bence at prolan.hu>
> Closes: https://lore.kernel.org/all/bfa70e78-3cc3-4295-820b-3925c26135cb at prolan.hu/
> Signed-off-by: William Breathitt Gray <wbg at kernel.org>
> ---
> This should fix the issue where a user needs to set the count function
> before they can use the counter. I don't have this hardware in person,
> so please test this patch and let me know whether it works for you.
> ---
>   drivers/counter/microchip-tcb-capture.c | 19 +++++++++++++++++++
>   1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
> index 2f096a5b973d18edf5de5a2b33f2f72571deefb7..c391ac38b990939c6764a9120a4bd03289f68469 100644
> --- a/drivers/counter/microchip-tcb-capture.c
> +++ b/drivers/counter/microchip-tcb-capture.c
> @@ -368,6 +368,25 @@ static int mchp_tc_probe(struct platform_device *pdev)
>   			channel);
>   	}
>   
> +	/* Disable Quadrature Decoder and position measure */
> +	ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0);
> +	if (ret)
> +		return ret;
> +
> +	/* Setup the period capture mode */
> +	ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR),
> +				 ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK |
> +				 ATMEL_TC_TCCLKS,
> +				 ATMEL_TC_CMR_MASK);
> +	if (ret)
> +		return ret;
> +
> +	/* Enable clock and trigger counter */
> +	ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR),
> +			   ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
> +	if (ret)
> +		return ret;
> +

This duplicates a lot of `mchp_tc_count_function_write()`. I'd much 
rather have this code in a separate function called something like 
`mchp_tc_setup_channels()`, that, depending on `priv->qdec_mode`, sets 
up the BMR, CCR and CMRs, and then have both probe() and 
function_write() call it. Or alternatively, have probe() call 
function_write() at the end, but that's not as nice.

> ---
> base-commit: 8744dcd4fc7800de2eb9369410470bb2930d4c14
> change-id: 20250305-preset-capture-mode-microchip-tcb-capture-fa31550ef594
> 
> Best regards,

Bence



From mazziesaccount at gmail.com  Wed Mar  5 02:54:33 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Wed, 5 Mar 2025 12:54:33 +0200
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
 <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
 <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
Message-ID: <54a031d0-df47-4baa-a23a-1a79c0922542@gmail.com>

Thanks for the review David.

On 04/03/2025 11:25, David Lechner wrote:
> On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
> <mazziesaccount at gmail.com> wrote:
>>
>> There are ADC ICs which may have some of the AIN pins usable for other
>> functions. These ICs may have some of the AIN pins wired so that they
>> should not be used for ADC.
>>
>> (Preferred?) way for marking pins which can be used as ADC inputs is to
>> add corresponding channels at N nodes in the device tree as described in
>> the ADC binding yaml.
>>
>> Add couple of helper functions which can be used to retrieve the channel
>> information from the device node.
>>
>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
>>
>> ---

>> + *
>> + * Return:     Number of found channels on succes. Negative value to indicate
> 
> s/succes/success/

Thanks!

>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
>> +                                         const struct iio_chan_spec *template,
>> +                                         int max_chan_id,
>> +                                         struct iio_chan_spec **cs)
>> +{
>> +       struct iio_chan_spec *chan_array, *chan;
>> +       int num_chan = 0, ret;
>> +
>> +       num_chan = iio_adc_device_num_channels(dev);
>> +       if (num_chan < 1)
>> +               return num_chan;
>> +
>> +       chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
>> +                                 GFP_KERNEL);
>> +       if (!chan_array)
>> +               return -ENOMEM;
>> +
>> +       chan = &chan_array[0];
>> +
>> +       device_for_each_child_node_scoped(dev, child) {
>> +               u32 ch;
>> +
>> +               if (!fwnode_name_eq(child, "channel"))
>> +                       continue;
>> +
>> +               ret = fwnode_property_read_u32(child, "reg", &ch);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               if (max_chan_id != -1 && ch > max_chan_id)
>> +                       return -ERANGE;
>> +
> 
> Should we use return dev_err_probe() on these to help with debugging a bad dtb?
> 

I am not fan of using dev_err_probe() in a 'library code'. This is 
because we never know if there'll be some odd use-case where this is not 
called from the probe.

All in all, I'd leave adding most of the debugs to the callers - 
especially because we do not expect to have bad device-trees after the 
initial 'development stage' of a board. The board 'development stage' 
should really reveal bugs which prevent the channels from being 
registered - and after the DT is correct, these debug prints become 
unnecessary (albeit minor) binary bloat.

>> +               *chan = *template;
>> +               chan->channel = ch;
>> +               chan++;
>> +       }
>> +
>> +       *cs = chan_array;
>> +
>> +       return num_chan;
>> +}
>> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
> 
> We can make this less verbose by setting #define
> DEFAULT_SYMBOL_NAMESPACE at the start of the file. Then we can just do
> EXPORT_SYMBOL_GPL() throughout the rest of the file.

I am not sure what to think of this. I use the good old 'ctrl + ]' in my 
editor when I need to check how a function was supposed to be used. That 
jumps to the spot of code where the function is. I'd like to see the 
namespace mentioned there in order to not accidentally miss the fact the 
function belongs to one.

OTOH, I do like simplifications. Yet, the added simplification might not 
warrant the namespace not being visible in the function definition.

> Also, I would prefer if the namespace matched config name (IIO_ADC_HELPER).

I had some lengthy discussion about this with Andy and Jonathan during 
earlier review versions. In short, I don't like the idea of very 
fragmented namespaces in IIO, which will just complicate the drivers 
without providing any obvious benefit.

https://lore.kernel.org/all/20250222174842.57c091c5 at jic23-huawei/

>> +
>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
>> +                                         const struct iio_chan_spec *template,
>> +                                         int max_chan_id,
>> +                                         struct iio_chan_spec **cs);
>> +
> 
> There are some different opinions on this, but on the last patch I did
> introducing a new namespace, the consensus seems to be that putting
> the MODULE_IMPORT_NS() in the header file was convenient so that users
> of the API don't have to remember to both include the header and add
> the import macro.
> 

I do like this suggestion, and I believe this would be the balance 
between getting the benefit of hiding part of the symbols - while not 
unnecessarily complicating the callers. I know some people are opposing 
it though. My personal opinion is that having the MODULE_IMPORT_NS() in 
a header would be neatly simplifying the calling code with very little 
harm, especially here where including the header hardly has use-cases 
outside the IIO ADC.

Unfortunately, the "safety" seems to often be a synonym for just "making 
it intentionally hard". As Finnish people say: "K?rsi, k?rsi, 
kirkkaamman kruunun saat". :)
(Roughly translated as "Suffer, suffer, you will get a brighter crown").

Let's hear what Jonathan thinks of your suggestion.

Thanks!
	-- Matti



From wbg at kernel.org  Wed Mar  5 03:02:15 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Wed, 5 Mar 2025 20:02:15 +0900
Subject: [PATCH] counter: microchip-tcb-capture: Fix undefined counter
 channel state on probe
In-Reply-To: <93ce1511-53f6-42a3-b1a5-b6732105e87d@prolan.hu>
References: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
 <93ce1511-53f6-42a3-b1a5-b6732105e87d@prolan.hu>
Message-ID: <Z8gvN1CvcSV8nfVP@ishi>

On Wed, Mar 05, 2025 at 11:50:27AM +0100, Cs?k?s Bence wrote:
> This duplicates a lot of `mchp_tc_count_function_write()`. I'd much rather
> have this code in a separate function called something like
> `mchp_tc_setup_channels()`, that, depending on `priv->qdec_mode`, sets up
> the BMR, CCR and CMRs, and then have both probe() and function_write() call
> it. Or alternatively, have probe() call function_write() at the end, but
> that's not as nice.

Hi Bence,

I agree, the mchp_tc_count_function_write() could be cleaned up and
divided into separate functions dedicated to configuring each mode
(perhaps regmap_update_bits() could be leveraged too), but that would be
a much more invasive update. For the sake of making backporting easy to
address this particular issue, I've kept the changes here localized to
just the probe() function. Once the fix is merged, someone can try
tackling a more proper refactor of the mchp_tc_count_function_write()
code.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/97a5e16b/attachment.sig>

From angelogioacchino.delregno at collabora.com  Wed Mar  5 03:03:18 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 12:03:18 +0100
Subject: [PATCH v4 4/8] soc: mediatek: mtk-cmdq: Add pa_base parsing for
 unsupported subsys ID hardware
In-Reply-To: <03c523e66fd56442f49c38456476cf18be59e8fb.camel@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
 <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>
 <03c523e66fd56442f49c38456476cf18be59e8fb.camel@mediatek.com>
Message-ID: <8203317e-7f99-4ea5-bda0-fcd791602a9f@collabora.com>

Il 05/03/25 10:46, Jason-JH Lin (???) ha scritto:
> On Tue, 2025-03-04 at 10:35 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
>>> When GCE executes instructions, the corresponding hardware register
>>> can be found through the subsys ID. For hardware that does not
>>> support
>>> subsys ID, its subsys ID will be set to invalid value and its
>>> physical
>>> address needs to be used to generate GCE instructions.
>>>
>>> This commit adds a pa_base parsing flow to the cmdq_client_reg
>>> structure
>>> for these unsupported subsys ID hardware.
>>>
>>
>> Does this work only for the MMINFRA located GCEs, or does this work
>> also for
>> the legacy ones in MT8173/83/88/92/95 // MT6795/6893/etc?
>>
>> In order to actually review and decide, I do need to know :-)
>>
> 
> Yes, it's for the SoCs without subsys ID, it's not related to the
> MMINFRA.
> 
> This can also work on MT8173/83/92/95 // MT6795/6893/etc.
> You can remove the `mediatek,gce-client-reg` properties in their dtsi
> and cherry-pick this series to verify it. :-)
> 

This is curious - and that brings more questions to the table (for curiosity
more than anything else at this point).

Since this is a way to make use of the CMDQ for address ranges that are not tied
to any subsys id (hence no gce-client-reg and just physical address parsing for
generating instructions), do you know what are the performance implications of
using this, instead of subsys IDs on SoCs that do support them?

Being clear: if we were to migrate a SoC like MT8195 to using this globally
instead of using subsys ids, would the performance be degraded?
And if yes, do you know by how much?

What you're proposing almost looks like being too good to be true - and makes
me wonder, at this point, why the subsys id was used in the first place :-)

Cheers!
Angelo

> Regards,
> Jason-JH Lin
> 
>> Thanks,
>> Angelo
>>
>>
> 





From suzuki.poulose at arm.com  Wed Mar  5 03:05:31 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Wed,  5 Mar 2025 11:05:31 +0000
Subject: [PATCH v15 00/10] [subset] Coresight: Add Coresight TMC Control Unit driver
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <174117263579.1942819.17038167511866554035.b4-ty@arm.com>


On Mon, 03 Mar 2025 11:29:21 +0800, Jie Gan wrote:
> The Coresight TMC Control Unit(CTCU) device hosts miscellaneous configuration
> registers to control various features related to TMC ETR device.
> 
> The CTCU device works as a helper device physically connected to the TMC ETR device.
> ---------------------------------------------------------
>              |ETR0|             |ETR1|
>               . \                 / .
>               .  \               /  .
>               .   \             /   .
>               .    \           /    .
> ---------------------------------------------------
> ETR0ATID0-ETR0ATID3     CTCU    ETR1ATID0-ETR1ATID3
> ---------------------------------------------------
> Each ETR has four ATID registers with 128 bits long in total.
> e.g. ETR0ATID0-ETR0ATID3 registers are used by ETR0 device.
> 
> [...]

I have applied patches 1-9, leaving the DTS update for the platform.

[01/10] Coresight: Add support for new APB clock name
        https://git.kernel.org/coresight/c/dc872c5f
[02/10] Coresight: Add trace_id function to retrieving the trace ID
        https://git.kernel.org/coresight/c/c367a89d
[03/10] Coresight: Use coresight_etm_get_trace_id() in traceid_show()
        https://git.kernel.org/coresight/c/182e8c70
[04/10] Coresight: Introduce a new struct coresight_path
        https://git.kernel.org/coresight/c/3c03c49b
[05/10] Coresight: Allocate trace ID after building the path
        https://git.kernel.org/coresight/c/d87d76d8
[06/10] Coresight: Change to read the trace ID from coresight_path
        https://git.kernel.org/coresight/c/7b365f05
[07/10] Coresight: Change functions to accept the coresight_path
        https://git.kernel.org/coresight/c/080ee83c
[08/10] dt-bindings: arm: Add Coresight TMC Control Unit hardware
        https://git.kernel.org/coresight/c/166df2a1
[09/10] Coresight: Add Coresight TMC Control Unit driver
        https://git.kernel.org/coresight/c/f78d206f

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From bigeasy at linutronix.de  Wed Mar  5 03:06:51 2025
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Wed, 5 Mar 2025 12:06:51 +0100
Subject: [PATCH 1/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <20250305104925.189198-2-vschneid@redhat.com>
References: <20250305104925.189198-1-vschneid@redhat.com>
 <20250305104925.189198-2-vschneid@redhat.com>
Message-ID: <20250305110651.6dpe0xQU@linutronix.de>

On 2025-03-05 11:49:25 [+0100], Valentin Schneider wrote:
> From: Mark Rutland <mark.rutland at arm.com>
> 
> For an architecture to enable CONFIG_ARCH_HAS_RESCHED_LAZY, two things are
> required:
> 1) Adding a TIF_NEED_RESCHED_LAZY flag definition
> 2) Checking for TIF_NEED_RESCHED_LAZY in the appropriate locations
> 
> 2) is handled in a generic manner by CONFIG_GENERIC_ENTRY, which isn't
> (yet) implemented for arm64. However, outside of core scheduler code,
> TIF_NEED_RESCHED_LAZY only needs to be checked on a kernel exit, meaning:
> o return/entry to userspace.
> o return/entry to guest.
> 
> The return/entry to a guest is all handled by xfer_to_guest_mode_handle_work()
> which already does the right thing, so it can be left as-is.
> 
> arm64 doesn't use common entry's exit_to_user_mode_prepare(), so update its
> return to user path to check for TIF_NEED_RESCHED_LAZY and call into
> schedule() accordingly.
> 
> Link: https://lore.kernel.org/linux-rt-users/20241216190451.1c61977c at mordecai.tesarici.cz/
> Link: https://lore.kernel.org/all/xhsmh4j0fl0p3.mognet at vschneid-thinkpadt14sgen2i.remote.csb/
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> [testdrive, _TIF_WORK_MASK fixlet and changelog.]
> Signed-off-by: Mike Galbraith <efault at gmx.de>
> [Another round of testing; changelog faff]
> Signed-off-by: Valentin Schneider <vschneid at redhat.com>

I somehow assumed it was already merged. For what it is worth, this
looks like patch Mike posted in
	https://lore.kernel.org/a198a7dd9076f97b89d8882bb249b3bf303564ef.camel at gmx.de

and tested 

Reviewed-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

Sebastian


From mike.leach at linaro.org  Wed Mar  5 03:07:43 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Wed, 5 Mar 2025 11:07:43 +0000
Subject: [PATCH v15 02/10] Coresight: Add trace_id function to retrieving
 the trace ID
In-Reply-To: <20250303032931.2500935-3-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com> <20250303032931.2500935-3-quic_jiegan@quicinc.com>
Message-ID: <CAJ9a7VgGp4YqzN-yx0x+NiZG8now6SCmnimaou2Z=exYcoiegw@mail.gmail.com>

Hi,

On Mon, 3 Mar 2025 at 03:30, Jie Gan <quic_jiegan at quicinc.com> wrote:
>
> Add 'trace_id' function pointer in coresight_ops. It's responsible for retrieving
> the device's trace ID.
>
> Co-developed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: James Clark <james.clark at linaro.org>
> Reviewed-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>  drivers/hwtracing/coresight/coresight-core.c  | 30 +++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-dummy.c | 13 +++++++-
>  .../coresight/coresight-etm3x-core.c          |  1 +
>  .../coresight/coresight-etm4x-core.c          |  1 +
>  drivers/hwtracing/coresight/coresight-stm.c   | 11 +++++++
>  drivers/hwtracing/coresight/coresight-tpda.c  | 11 +++++++
>  include/linux/coresight.h                     |  5 ++++
>  7 files changed, 71 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index ab55e10d4b79..32aa07f4f8c1 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -24,6 +24,7 @@
>  #include "coresight-etm-perf.h"
>  #include "coresight-priv.h"
>  #include "coresight-syscfg.h"
> +#include "coresight-trace-id.h"
>
>  /*
>   * Mutex used to lock all sysfs enable and disable actions and loading and
> @@ -1557,6 +1558,35 @@ void coresight_remove_driver(struct amba_driver *amba_drv,
>  }
>  EXPORT_SYMBOL_GPL(coresight_remove_driver);
>
> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
> +                              struct coresight_device *sink)
> +{
> +       int trace_id;
> +       int cpu = source_ops(csdev)->cpu_id(csdev);
> +

This is a global funciton so need to check that this csdev is a
source,. and does provide a cpu  function before calling it.

> +       switch (mode) {
> +       case CS_MODE_SYSFS:
> +               trace_id = coresight_trace_id_get_cpu_id(cpu);
> +               break;
> +       case CS_MODE_PERF:
> +               if (WARN_ON(!sink))
> +                       return -EINVAL;
> +
> +               trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
> +               break;
> +       default:
> +               trace_id = -EINVAL;
> +               break;
> +       }
> +
> +       if (!IS_VALID_CS_TRACE_ID(trace_id))
> +               dev_err(&csdev->dev,
> +                       "Failed to allocate trace ID on CPU%d\n", cpu);
> +
> +       return trace_id;
> +}
> +EXPORT_SYMBOL_GPL(coresight_etm_get_trace_id);
> +
>  MODULE_LICENSE("GPL v2");
>  MODULE_AUTHOR("Pratik Patel <pratikp at codeaurora.org>");
>  MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier at linaro.org>");
> diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
> index 9be53be8964b..b5692ba358c1 100644
> --- a/drivers/hwtracing/coresight/coresight-dummy.c
> +++ b/drivers/hwtracing/coresight/coresight-dummy.c
> @@ -41,6 +41,16 @@ static void dummy_source_disable(struct coresight_device *csdev,
>         dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
>  }
>
> +static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> +                                __maybe_unused struct coresight_device *sink)
> +{
> +       struct dummy_drvdata *drvdata;
> +
> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +       return drvdata->traceid;
> +}
> +
>  static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
>                                 void *data)
>  {
> @@ -62,7 +72,8 @@ static const struct coresight_ops_source dummy_source_ops = {
>  };
>
>  static const struct coresight_ops dummy_source_cs_ops = {
> -       .source_ops = &dummy_source_ops,
> +       .trace_id       = dummy_source_trace_id,
> +       .source_ops     = &dummy_source_ops,
>  };
>
>  static const struct coresight_ops_sink dummy_sink_ops = {
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> index c103f4c70f5d..c1dda4bc4a2f 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> @@ -704,6 +704,7 @@ static const struct coresight_ops_source etm_source_ops = {
>  };
>
>  static const struct coresight_ops etm_cs_ops = {
> +       .trace_id       = coresight_etm_get_trace_id,
>         .source_ops     = &etm_source_ops,
>  };
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 2c1a60577728..cfd116b87460 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -1067,6 +1067,7 @@ static const struct coresight_ops_source etm4_source_ops = {
>  };
>
>  static const struct coresight_ops etm4_cs_ops = {
> +       .trace_id       = coresight_etm_get_trace_id,
>         .source_ops     = &etm4_source_ops,
>  };
>
> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> index b581a30a1cd9..aca25b5e3be2 100644
> --- a/drivers/hwtracing/coresight/coresight-stm.c
> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> @@ -281,12 +281,23 @@ static void stm_disable(struct coresight_device *csdev,
>         }
>  }
>
> +static int stm_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> +                       __maybe_unused struct coresight_device *sink)
> +{
> +       struct stm_drvdata *drvdata;
> +
> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +       return drvdata->traceid;
> +}
> +
>  static const struct coresight_ops_source stm_source_ops = {
>         .enable         = stm_enable,
>         .disable        = stm_disable,
>  };
>
>  static const struct coresight_ops stm_cs_ops = {
> +       .trace_id       = stm_trace_id,
>         .source_ops     = &stm_source_ops,
>  };
>
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> index 573da8427428..94c2201fc8d3 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> @@ -241,12 +241,23 @@ static void tpda_disable(struct coresight_device *csdev,
>         dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
>  }
>
> +static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> +                        __maybe_unused struct coresight_device *sink)
> +{
> +       struct tpda_drvdata *drvdata;
> +
> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +       return drvdata->atid;
> +}
> +
>  static const struct coresight_ops_link tpda_link_ops = {
>         .enable         = tpda_enable,
>         .disable        = tpda_disable,
>  };
>
>  static const struct coresight_ops tpda_cs_ops = {
> +       .trace_id       = tpda_trace_id,
>         .link_ops       = &tpda_link_ops,
>  };
>
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index c7cd5886c908..ce9a5e71b261 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -335,6 +335,7 @@ enum cs_mode {
>         CS_MODE_PERF,
>  };
>
> +#define coresight_ops(csdev)   csdev->ops
>  #define source_ops(csdev)      csdev->ops->source_ops
>  #define sink_ops(csdev)                csdev->ops->sink_ops
>  #define link_ops(csdev)                csdev->ops->link_ops
> @@ -421,6 +422,8 @@ struct coresight_ops_panic {
>  };
>
>  struct coresight_ops {
> +       int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
> +                       struct coresight_device *sink);
>         const struct coresight_ops_sink *sink_ops;
>         const struct coresight_ops_link *link_ops;
>         const struct coresight_ops_source *source_ops;
> @@ -709,4 +712,6 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
>
>  void coresight_remove_driver(struct amba_driver *amba_drv,
>                              struct platform_driver *pdev_drv);
> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
> +                              struct coresight_device *sink);
>  #endif         /* _LINUX_COREISGHT_H */
> --
> 2.34.1
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From wiagn233 at outlook.com  Wed Mar  5 03:09:37 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Wed,  5 Mar 2025 19:09:37 +0800
Subject: [PATCH v8] wifi: mt76: mt7915: add wds support when wed is enabled
Message-ID: <TYCPR01MB84374EEAC0DDDA4223B8997298CB2@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The current WED only supports 256 wcid, whereas mt7986 can support up to
512 entries, so firmware provides a rule to get sta_info by DA when wcid
is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
to 0xff by host driver.

However, firmware is unable to get sta_info from DA as DA != RA for
4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
and (768 ~ 783) for sync up to get correct sta_info.

Currently WDS+WED config is completely broken on MT7986/7981 devices if
without this patch.

Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
Changes since v1:
 - Drop duplicate setting in mmio
 - Reduce the patch size by redefining mt76_wcid_alloc
Changes since v2:
 - Rework wds wcid getting flow
Changes since v3:
 - Rebase to next-20240703
 - Sync with downstream patch
Changes since v4:
 - Rebase to next-20240802
Changes since v5:
 - Fixed build test error reported by robot
 - Rebase to next-20240805
Changes since v6:
 - Fix potential race conditions on tx/rx packets during the transition
 - Rebase to Felix's newest codebase
Changes since v7:
 - Fix build fail
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  9 ++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 45 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 ++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
 drivers/net/wireless/mediatek/mt76/util.c     | 37 +++++++++++++--
 drivers/net/wireless/mediatek/mt76/util.h     |  7 ++-
 6 files changed, 106 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b1070..638ee9fae0c73 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -28,6 +28,9 @@
 
 #define MT76_TOKEN_FREE_THR	64
 
+#define MT76_WED_WDS_MIN    256
+#define MT76_WED_WDS_MAX    272
+
 #define MT_QFLAG_WED_RING	GENMASK(1, 0)
 #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
 #define MT_QFLAG_WED		BIT(5)
@@ -73,6 +76,12 @@ enum mt76_wed_type {
 	MT76_WED_RRO_Q_IND,
 };
 
+enum mt76_wed_state {
+	MT76_WED_DEFAULT,
+	MT76_WED_ACTIVE,
+	MT76_WED_WDS_ACTIVE,
+};
+
 struct mt76_bus_ops {
 	u32 (*rr)(struct mt76_dev *dev, u32 offset);
 	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 3aa31c5cefa6a..c489130b6ae2a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
 	bool ext_phy = mvif->phy != &dev->phy;
 	int idx;
+	u8 flags = MT76_WED_DEFAULT;
 
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76)) {
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+	}
+
+	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
 	if (idx < 0)
 		return -ENOSPC;
 
@@ -1271,6 +1278,10 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 {
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
+	struct ieee80211_sta *pre_sta;
+	u8 flags = MT76_WED_DEFAULT;
+	int temp_idx;
 
 	if (enabled)
 		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
@@ -1280,6 +1291,30 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 	if (!msta->wcid.sta)
 		return;
 
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76) &&
+	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+		pre_sta = kzalloc(sizeof(*sta) + sizeof(*msta), GFP_KERNEL);
+		memmove(pre_sta, sta, sizeof(*sta) + sizeof(*msta));
+
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+
+		temp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
+		((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = (u16)temp_idx;
+		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
+		rcu_assign_pointer(dev->mt76.wcid[temp_idx], &msta->wcid);
+
+		temp_idx = msta->wcid.idx;
+		msta->wcid.idx = ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx;
+		((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = (u16)temp_idx;
+		rcu_assign_pointer(dev->mt76.wcid[temp_idx], NULL);
+
+		synchronize_rcu();
+		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
+		kfree(pre_sta);
+	}
+
 	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
 }
 
@@ -1726,15 +1761,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
 	path->mtk_wdma.queue = phy != &dev->phy;
+	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
+	    is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = msta->wcid.idx;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
 
 	ctx->dev = NULL;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9d790f234e82c..32c5aa1a361e8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
 
 	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
 
-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-	     is_mt7915(&dev->mt76)) ||
-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+		if (is_mt7915(&dev->mt76) ||
+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+						0, 0, 0);
+		else
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+						MCU_WA_PARAM_WED_VERSION,
+						dev->mt76.mmio.wed.rev_id, 0);
+		if (ret)
+			return ret;
+	}
+#endif
 
 	ret = mt7915_mcu_set_mwds(dev, 1);
 	if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 49476a4182fd1..c3dd0cb4a5d38 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
 	MCU_WA_PARAM_PDMA_RX = 0x04,
 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
 	MCU_WA_PARAM_RED = 0x0e,
+	MCU_WA_PARAM_WED_VERSION = 0x32,
 	MCU_WA_PARAM_RED_SETTING = 0x40,
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 95b3dc96e4c45..7fac9c79ebdf3 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 }
 EXPORT_SYMBOL_GPL(____mt76_poll_msec);
 
-int mt76_wcid_alloc(u32 *mask, int size)
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
 {
 	int i, idx = 0, cur;
+	int min = MT76_WED_WDS_MIN;
+	int max = MT76_WED_WDS_MAX;
 
 	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
 		idx = ffs(~mask[i]);
@@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
 
 		idx--;
 		cur = i * 32 + idx;
-		if (cur >= size)
+
+		switch (flag) {
+		case MT76_WED_ACTIVE:
+			if (cur >= min && cur < max)
+				continue;
+
+			if (cur >= size) {
+				u32 end = max - min - 1;
+
+				i = min / 32;
+				idx = ffs(~mask[i] & GENMASK(end, 0));
+				if (!idx)
+					goto error;
+				idx--;
+				cur = min + idx;
+			}
+
 			break;
+		case MT76_WED_WDS_ACTIVE:
+			if (cur < min)
+				continue;
+			if (cur >= max)
+				goto error;
+
+			break;
+		default:
+			if (cur >= size)
+				goto error;
+			break;
+		}
 
 		mask[i] |= BIT(idx);
 		return cur;
 	}
 
+error:
 	return -1;
 }
-EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
 
 int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94cf..99b7263c0a205 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -27,7 +27,12 @@ enum {
 #define MT76_INCR(_var, _size) \
 	(_var = (((_var) + 1) % (_size)))
 
-int mt76_wcid_alloc(u32 *mask, int size);
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+	return __mt76_wcid_alloc(mask, size, 0);
+}
 
 static inline void
 mt76_wcid_mask_set(u32 *mask, int idx)
-- 
2.48.1



From fujita.tomonori at gmail.com  Wed Mar  5 03:08:10 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed,  5 Mar 2025 20:08:10 +0900
Subject: [PATCH v4 0/4] rust: Add bug/warn abstractions
Message-ID: <20250305110814.272792-1-fujita.tomonori@gmail.com>

This patchset adds warn_on macro with the bug/warn abstraction that
utilizes the kernel's BUG/WARN feature via assembly.

Currently, Rust code simply wraps BUG() macro; however the approach
doesn't provide the proper debug information. For example, I added
bindings::BUG() to rnull's init method and got the following output:

# insmod /root/rnull_mod.ko
rnull_mod: Rust null_blk loaded
------------[ cut here ]------------
kernel BUG at rust/helpers/bug.c:7!
Oops: invalid opcode: 0000 [#1] SMP CPU: 0 UID: 0 PID: 31 Comm: insmod Not tainted 6.14.0-rc1+ #103
RIP: 0010:rust_helper_BUG+0x8/0x10
(snip)

The kernel's BUG/WARN feature (lib/bug.c) can only be used from
assembly. Rust code needs to directly execute the same assembly code
used on the C side. To avoid duplicating the assembly code, this
approach follows the same strategy as the static branch code: it
generates the assembly code for Rust using the C preprocessor at
compile time.

The 1st to 3th patches export the BUG/WARN assembly code for Rust on
x86, RISC-V, and ARM64 architecture, with no functional changes on the
C side. They have already been acked by the maintainers of their
respective architectures.

The change for LoongArch assembly hasn't been acked yet so the v4
doesnt' include it. LoongArch still uses the current approach; just
wrapping C's macro.

UML doesn't use the assembly BUG/WARN feature; just wrapping generic
BUG/WARN functions implemented in C works.

The last patch adds warn_on implementation on the top of the
abstraction. To make the patchset easier to review, the remaining
features such as bug() are not included in this patchset. These
features will be added after this patchset is merged.

This has been tested on x86, ARM64, and RISC-V (QEMU), with only a
compile test performed for LoongArch and UML.

v4:
- added Acked-by tag to the RISC-V and ARM64 asm change
- simplify the asm code
- use the cfgs on the macro rather in its expansion
- use a const fn for bugflag_taint over macro
- dropped LoongArch assembly change
- dropped warn_on_once; make the patch easier to review
v3: https://lore.kernel.org/rust-for-linux/20250213135759.190006-1-fujita.tomonori at gmail.com/
- rebased on rust-next
- use ANNOTATE_REACHABLE macro (replaced ASM_REACHABLE)
- added Acked-by tag to the x86 change
v2: https://lore.kernel.org/linux-arm-kernel/20241218062009.2402650-1-fujita.tomonori at gmail.com/
- remove target_arch cfg by using asm comment
- clean up the changes to loongarch asm
v1: https://lore.kernel.org/linux-arm-kernel/20241210001802.228725-1-fujita.tomonori at gmail.com/


FUJITA Tomonori (4):
  x86/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with
    Rust
  riscv/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with
    Rust
  arm64/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with
    Rust
  rust: Add warn_on macro

 arch/arm64/include/asm/asm-bug.h              |  33 ++++-
 arch/riscv/include/asm/bug.h                  |  37 +++---
 arch/x86/include/asm/bug.h                    |  56 ++++-----
 rust/Makefile                                 |   8 ++
 rust/helpers/bug.c                            |   5 +
 rust/kernel/.gitignore                        |   2 +
 rust/kernel/bug.rs                            | 113 ++++++++++++++++++
 rust/kernel/generated_arch_reachable_asm.rs.S |   7 ++
 rust/kernel/generated_arch_warn_asm.rs.S      |   7 ++
 rust/kernel/lib.rs                            |   1 +
 10 files changed, 222 insertions(+), 47 deletions(-)
 create mode 100644 rust/kernel/bug.rs
 create mode 100644 rust/kernel/generated_arch_reachable_asm.rs.S
 create mode 100644 rust/kernel/generated_arch_warn_asm.rs.S


base-commit: beeb78d46249cab8b2b8359a2ce8fa5376b5ad2d
-- 
2.43.0



From fujita.tomonori at gmail.com  Wed Mar  5 03:08:11 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed,  5 Mar 2025 20:08:11 +0900
Subject: [PATCH v4 1/4] x86/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust
In-Reply-To: <20250305110814.272792-1-fujita.tomonori@gmail.com>
References: <20250305110814.272792-1-fujita.tomonori@gmail.com>
Message-ID: <20250305110814.272792-2-fujita.tomonori@gmail.com>

Add new ARCH_WARN_ASM macro for BUG/WARN assembly code sharing with
Rust to avoid the duplication.

No functional changes.

Acked-by: Peter Zijlstra (Intel) <peterz at infradead.org>
Signed-off-by: FUJITA Tomonori <fujita.tomonori at gmail.com>
---
 arch/x86/include/asm/bug.h | 56 +++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index e85ac0c7c039..61570ec9464c 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -28,45 +28,42 @@
 #ifdef CONFIG_GENERIC_BUG
 
 #ifdef CONFIG_X86_32
-# define __BUG_REL(val)	".long " __stringify(val)
+# define __BUG_REL(val)	".long " val
 #else
-# define __BUG_REL(val)	".long " __stringify(val) " - ."
+# define __BUG_REL(val)	".long " val " - ."
 #endif
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+#define __BUG_ENTRY(file, line, flags)					\
+	"2:\t" __BUG_REL("1b") "\t# bug_entry::bug_addr\n"		\
+	"\t" __BUG_REL(file)   "\t# bug_entry::file\n"			\
+	"\t.word " line        "\t# bug_entry::line\n"			\
+	"\t.word " flags       "\t# bug_entry::flags\n"
+#else
+#define __BUG_ENTRY(file, ine, flags)					\
+	"2:\t" __BUG_REL("1b") "\t# bug_entry::bug_addr\n"		\
+	"\t.word " flags       "\t# bug_entry::flags\n"
+#endif
+
+#define _BUG_FLAGS_ASM(ins, file, line, flags, size, extra)		\
+	"1:\t" ins "\n"							\
+	".pushsection __bug_table,\"aw\"\n"				\
+	__BUG_ENTRY(file, line, flags)					\
+	"\t.org 2b + " size "\n"					\
+	".popsection\n"							\
+	extra
 
 #define _BUG_FLAGS(ins, flags, extra)					\
 do {									\
-	asm_inline volatile("1:\t" ins "\n"				\
-		     ".pushsection __bug_table,\"aw\"\n"		\
-		     "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n"	\
-		     "\t"  __BUG_REL(%c0) "\t# bug_entry::file\n"	\
-		     "\t.word %c1"        "\t# bug_entry::line\n"	\
-		     "\t.word %c2"        "\t# bug_entry::flags\n"	\
-		     "\t.org 2b+%c3\n"					\
-		     ".popsection\n"					\
-		     extra						\
+	asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c0",			\
+					   "%c1", "%c2", "%c3", extra)	\
 		     : : "i" (__FILE__), "i" (__LINE__),		\
 			 "i" (flags),					\
 			 "i" (sizeof(struct bug_entry)));		\
 } while (0)
 
-#else /* !CONFIG_DEBUG_BUGVERBOSE */
-
-#define _BUG_FLAGS(ins, flags, extra)					\
-do {									\
-	asm_inline volatile("1:\t" ins "\n"				\
-		     ".pushsection __bug_table,\"aw\"\n"		\
-		     "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n"	\
-		     "\t.word %c0"        "\t# bug_entry::flags\n"	\
-		     "\t.org 2b+%c1\n"					\
-		     ".popsection\n"					\
-		     extra						\
-		     : : "i" (flags),					\
-			 "i" (sizeof(struct bug_entry)));		\
-} while (0)
-
-#endif /* CONFIG_DEBUG_BUGVERBOSE */
+#define ARCH_WARN_ASM(file, line, flags, size)				\
+	_BUG_FLAGS_ASM(ASM_UD2, file, line, flags, size, "")
 
 #else
 
@@ -88,11 +85,14 @@ do {								\
  * were to trigger, we'd rather wreck the machine in an attempt to get the
  * message out than not know about it.
  */
+
+#define ARCH_WARN_REACHABLE	ANNOTATE_REACHABLE(1b)
+
 #define __WARN_FLAGS(flags)					\
 do {								\
 	__auto_type __flags = BUGFLAG_WARNING|(flags);		\
 	instrumentation_begin();				\
-	_BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b));	\
+	_BUG_FLAGS(ASM_UD2, __flags, ARCH_WARN_REACHABLE);	\
 	instrumentation_end();					\
 } while (0)
 
-- 
2.43.0



From fujita.tomonori at gmail.com  Wed Mar  5 03:08:12 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed,  5 Mar 2025 20:08:12 +0900
Subject: [PATCH v4 2/4] riscv/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust
In-Reply-To: <20250305110814.272792-1-fujita.tomonori@gmail.com>
References: <20250305110814.272792-1-fujita.tomonori@gmail.com>
Message-ID: <20250305110814.272792-3-fujita.tomonori@gmail.com>

Add new ARCH_WARN_ASM macro for BUG/WARN assembly code sharing with
Rust to avoid the duplication.

No functional changes.

Acked-by: Alexandre Ghiti <alexghiti at rivosinc.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori at gmail.com>
---
 arch/riscv/include/asm/bug.h | 37 +++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h
index 1aaea81fb141..6ab13b56feb0 100644
--- a/arch/riscv/include/asm/bug.h
+++ b/arch/riscv/include/asm/bug.h
@@ -31,40 +31,45 @@ typedef u32 bug_insn_t;
 
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
 #define __BUG_ENTRY_ADDR	RISCV_INT " 1b - ."
-#define __BUG_ENTRY_FILE	RISCV_INT " %0 - ."
+#define __BUG_ENTRY_FILE(file)	RISCV_INT " " file " - ."
 #else
 #define __BUG_ENTRY_ADDR	RISCV_PTR " 1b"
-#define __BUG_ENTRY_FILE	RISCV_PTR " %0"
+#define __BUG_ENTRY_FILE(file)	RISCV_PTR " " file
 #endif
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-#define __BUG_ENTRY			\
+#define __BUG_ENTRY(file, line, flags)	\
 	__BUG_ENTRY_ADDR "\n\t"		\
-	__BUG_ENTRY_FILE "\n\t"		\
-	RISCV_SHORT " %1\n\t"		\
-	RISCV_SHORT " %2"
+	__BUG_ENTRY_FILE(file) "\n\t"	\
+	RISCV_SHORT " " line "\n\t"	\
+	RISCV_SHORT " " flags
 #else
-#define __BUG_ENTRY			\
-	__BUG_ENTRY_ADDR "\n\t"		\
-	RISCV_SHORT " %2"
+#define __BUG_ENTRY(file, line, flags)		\
+	__BUG_ENTRY_ADDR "\n\t"			\
+	RISCV_SHORT " " flags
 #endif
 
 #ifdef CONFIG_GENERIC_BUG
-#define __BUG_FLAGS(flags)					\
-do {								\
-	__asm__ __volatile__ (					\
+
+#define ARCH_WARN_ASM(file, line, flags, size)			\
 		"1:\n\t"					\
 			"ebreak\n"				\
 			".pushsection __bug_table,\"aw\"\n\t"	\
 		"2:\n\t"					\
-			__BUG_ENTRY "\n\t"			\
-			".org 2b + %3\n\t"                      \
-			".popsection"				\
+		__BUG_ENTRY(file, line, flags) "\n\t"		\
+			".org 2b + " size "\n\t"                \
+			".popsection\n"				\
+
+#define __BUG_FLAGS(flags)					\
+do {								\
+	__asm__ __volatile__ (					\
+		ARCH_WARN_ASM("%0", "%1", "%2", "%3")		\
 		:						\
 		: "i" (__FILE__), "i" (__LINE__),		\
 		  "i" (flags),					\
 		  "i" (sizeof(struct bug_entry)));              \
 } while (0)
+
 #else /* CONFIG_GENERIC_BUG */
 #define __BUG_FLAGS(flags) do {					\
 	__asm__ __volatile__ ("ebreak\n");			\
@@ -78,6 +83,8 @@ do {								\
 
 #define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags))
 
+#define ARCH_WARN_REACHABLE
+
 #define HAVE_ARCH_BUG
 
 #include <asm-generic/bug.h>
-- 
2.43.0



From fujita.tomonori at gmail.com  Wed Mar  5 03:08:13 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed,  5 Mar 2025 20:08:13 +0900
Subject: [PATCH v4 3/4] arm64/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust
In-Reply-To: <20250305110814.272792-1-fujita.tomonori@gmail.com>
References: <20250305110814.272792-1-fujita.tomonori@gmail.com>
Message-ID: <20250305110814.272792-4-fujita.tomonori@gmail.com>

Add new ARCH_WARN_ASM macro for BUG/WARN assembly code sharing with
Rust to avoid the duplication.

No functional changes.

Acked-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori at gmail.com>
---
 arch/arm64/include/asm/asm-bug.h | 33 ++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h
index 6e73809f6492..a5f13801b784 100644
--- a/arch/arm64/include/asm/asm-bug.h
+++ b/arch/arm64/include/asm/asm-bug.h
@@ -21,16 +21,21 @@
 #endif
 
 #ifdef CONFIG_GENERIC_BUG
-
-#define __BUG_ENTRY(flags) 				\
+#define __BUG_ENTRY_START				\
 		.pushsection __bug_table,"aw";		\
 		.align 2;				\
 	14470:	.long 14471f - .;			\
-_BUGVERBOSE_LOCATION(__FILE__, __LINE__)		\
-		.short flags; 				\
+
+#define __BUG_ENTRY_END					\
 		.align 2;				\
 		.popsection;				\
 	14471:
+
+#define __BUG_ENTRY(flags)				\
+		__BUG_ENTRY_START			\
+_BUGVERBOSE_LOCATION(__FILE__, __LINE__)		\
+		.short flags;				\
+		__BUG_ENTRY_END
 #else
 #define __BUG_ENTRY(flags)
 #endif
@@ -41,4 +46,24 @@ _BUGVERBOSE_LOCATION(__FILE__, __LINE__)		\
 
 #define ASM_BUG()	ASM_BUG_FLAGS(0)
 
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define __BUG_LOCATION_STRING(file, line)		\
+		".long " file "- .;"			\
+		".short " line ";"
+#else
+#define __BUG_LOCATION_STRING(file, line)
+#endif
+
+#define __BUG_ENTRY_STRING(file, line, flags)		\
+		__stringify(__BUG_ENTRY_START)		\
+		__BUG_LOCATION_STRING(file, line)	\
+		".short " flags ";"			\
+		__stringify(__BUG_ENTRY_END)
+
+#define ARCH_WARN_ASM(file, line, flags, size)		\
+	__BUG_ENTRY_STRING(file, line, flags)		\
+	__stringify(brk BUG_BRK_IMM)
+
+#define ARCH_WARN_REACHABLE
+
 #endif /* __ASM_ASM_BUG_H */
-- 
2.43.0



From fujita.tomonori at gmail.com  Wed Mar  5 03:08:14 2025
From: fujita.tomonori at gmail.com (FUJITA Tomonori)
Date: Wed,  5 Mar 2025 20:08:14 +0900
Subject: [PATCH v4 4/4] rust: Add warn_on macro
In-Reply-To: <20250305110814.272792-1-fujita.tomonori@gmail.com>
References: <20250305110814.272792-1-fujita.tomonori@gmail.com>
Message-ID: <20250305110814.272792-5-fujita.tomonori@gmail.com>

Add warn_on macro, uses the BUG/WARN feature (lib/bug.c) via assembly
for x86_64/arm64/riscv.

The current Rust code simply wraps BUG() macro but doesn't provide the
proper debug information. The BUG/WARN feature can only be used from
assembly.

This uses the assembly code exported by the C side via ARCH_WARN_ASM
macro. To avoid duplicating the assembly code, this approach follows
the same strategy as the static branch code: it generates the assembly
code for Rust using the C preprocessor at compile time.

Similarly, ARCH_WARN_REACHABLE is also used at compile time to
generate the assembly code; objtool's reachable anotation code. It's
used for only architectures that use objtool.

For now, Loongarch just uses a wrapper for WARN macro.

UML doesn't use the assembly BUG/WARN feature; just wrapping generic
BUG/WARN functions implemented in C works.

Signed-off-by: FUJITA Tomonori <fujita.tomonori at gmail.com>
---
 rust/Makefile                                 |   8 ++
 rust/helpers/bug.c                            |   5 +
 rust/kernel/.gitignore                        |   2 +
 rust/kernel/bug.rs                            | 113 ++++++++++++++++++
 rust/kernel/generated_arch_reachable_asm.rs.S |   7 ++
 rust/kernel/generated_arch_warn_asm.rs.S      |   7 ++
 rust/kernel/lib.rs                            |   1 +
 7 files changed, 143 insertions(+)
 create mode 100644 rust/kernel/bug.rs
 create mode 100644 rust/kernel/generated_arch_reachable_asm.rs.S
 create mode 100644 rust/kernel/generated_arch_warn_asm.rs.S

diff --git a/rust/Makefile b/rust/Makefile
index 8fcfd60447bc..a295b65c43f3 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -34,6 +34,9 @@ obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o
 obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
 
 always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
+ifndef CONFIG_UML
+always-$(subst y,$(CONFIG_RUST),$(CONFIG_BUG)) += kernel/generated_arch_warn_asm.rs kernel/generated_arch_reachable_asm.rs
+endif
 
 # Avoids running `$(RUSTC)` when it may not be available.
 ifdef CONFIG_RUST
@@ -481,5 +484,10 @@ $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
 ifdef CONFIG_JUMP_LABEL
 $(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs
 endif
+ifndef CONFIG_UML
+ifdef CONFIG_BUG
+$(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generated_arch_reachable_asm.rs
+endif
+endif
 
 endif # CONFIG_RUST
diff --git a/rust/helpers/bug.c b/rust/helpers/bug.c
index e2d13babc737..a62c96f507d1 100644
--- a/rust/helpers/bug.c
+++ b/rust/helpers/bug.c
@@ -6,3 +6,8 @@ __noreturn void rust_helper_BUG(void)
 {
 	BUG();
 }
+
+bool rust_helper_WARN_ON(bool cond)
+{
+	return WARN_ON(cond);
+}
diff --git a/rust/kernel/.gitignore b/rust/kernel/.gitignore
index 6ba39a178f30..f636ad95aaf3 100644
--- a/rust/kernel/.gitignore
+++ b/rust/kernel/.gitignore
@@ -1,3 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
 /generated_arch_static_branch_asm.rs
+/generated_arch_warn_asm.rs
+/generated_arch_reachable_asm.rs
diff --git a/rust/kernel/bug.rs b/rust/kernel/bug.rs
new file mode 100644
index 000000000000..a010033be5a2
--- /dev/null
+++ b/rust/kernel/bug.rs
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2024, 2025 FUJITA Tomonori <fujita.tomonori at gmail.com>
+
+//! Support for BUG and WARN functionality.
+//!
+//! C header: [`include/asm-generic/bug.h`](srctree/include/asm-generic/bug.h)
+
+#[macro_export]
+#[doc(hidden)]
+#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH)))]
+#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
+macro_rules! warn_flags {
+    ($flags:expr) => {
+        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
+        const _FILE: &[u8] = file!().as_bytes();
+        // Plus one for null-terminator.
+        static FILE: [u8; _FILE.len() + 1] = {
+            let mut bytes = [0; _FILE.len() + 1];
+            let mut i = 0;
+            while i < _FILE.len() {
+                bytes[i] = _FILE[i];
+                i += 1;
+            }
+            bytes
+        };
+        // SAFETY: Just an FFI call.
+        unsafe {
+            $crate::asm!(concat!(
+                "/* {size} */",
+                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
+                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
+            file = sym FILE,
+            line = const line!(),
+            flags = const FLAGS,
+            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
+            );
+        }
+    }
+}
+
+#[macro_export]
+#[doc(hidden)]
+#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH)))]
+#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
+macro_rules! warn_flags {
+    ($flags:expr) => {
+        const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
+        // SAFETY: Just an FFI call.
+        unsafe {
+            $crate::asm!(
+            concat!(
+                "/* {size} */",
+                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
+                include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
+            flags = const FLAGS,
+            size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
+            );
+        }
+    }
+}
+
+#[macro_export]
+#[doc(hidden)]
+#[cfg(all(CONFIG_BUG, CONFIG_UML))]
+macro_rules! warn_flags {
+    ($flags:expr) => {
+        // SAFETY: Just an FFI call.
+        unsafe {
+            $crate::bindings::warn_slowpath_fmt(
+                $crate::c_str!(::core::file!()).as_ptr() as *const ::core::ffi::c_uchar,
+                line!() as i32,
+                $flags as u32,
+                ::core::ptr::null() as *const ::core::ffi::c_uchar,
+            );
+        }
+    };
+}
+
+#[macro_export]
+#[doc(hidden)]
+#[cfg(all(CONFIG_BUG, CONFIG_LOONGARCH))]
+macro_rules! warn_flags {
+    ($flags:expr) => {
+        // SAFETY: Just an FFI call.
+        unsafe { $crate::bindings::WARN_ON(true) }
+    };
+}
+
+#[macro_export]
+#[doc(hidden)]
+#[cfg(not(CONFIG_BUG))]
+macro_rules! warn_flags {
+    ($flags:expr) => {};
+}
+
+#[doc(hidden)]
+pub const fn bugflag_taint(value: u32) -> u32 {
+    value << 8
+}
+
+/// Report a warning if `cond` is true and return the condition's evaluation result.
+#[macro_export]
+macro_rules! warn_on {
+    ($cond:expr) => {{
+        if $cond {
+            const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
+
+            $crate::warn_flags!(WARN_ON_FLAGS);
+        }
+        $cond
+    }};
+}
diff --git a/rust/kernel/generated_arch_reachable_asm.rs.S b/rust/kernel/generated_arch_reachable_asm.rs.S
new file mode 100644
index 000000000000..3886a9ad3a99
--- /dev/null
+++ b/rust/kernel/generated_arch_reachable_asm.rs.S
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/bug.h>
+
+// Cut here.
+
+::kernel::concat_literals!(ARCH_WARN_REACHABLE)
diff --git a/rust/kernel/generated_arch_warn_asm.rs.S b/rust/kernel/generated_arch_warn_asm.rs.S
new file mode 100644
index 000000000000..409eb4c2d3a1
--- /dev/null
+++ b/rust/kernel/generated_arch_warn_asm.rs.S
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/bug.h>
+
+// Cut here.
+
+::kernel::concat_literals!(ARCH_WARN_ASM("{file}", "{line}",  "{flags}", "{size}"))
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 496ed32b0911..c0720846b249 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -38,6 +38,7 @@
 pub mod alloc;
 #[cfg(CONFIG_BLOCK)]
 pub mod block;
+pub mod bug;
 #[doc(hidden)]
 pub mod build_assert;
 pub mod cred;
-- 
2.43.0



From danishanwar at ti.com  Wed Mar  5 03:16:08 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Wed, 5 Mar 2025 16:46:08 +0530
Subject: [PATCH net-next v2] net: ti: icssg-prueth: Add ICSSG FW Stats
Message-ID: <20250305111608.520042-1-danishanwar@ti.com>

The ICSSG firmware maintains set of stats called PA_STATS.
Currently the driver only dumps 4 stats. Add support for dumping more
stats.

The offset for different stats are defined as MACROs in icssg_switch_map.h
file. All the offsets are for Slice0. Slice1 offsets are slice0 + 4.
The offset calculation is taken care while reading the stats in
emac_update_hardware_stats().

The statistics are documented in
Documentation/networking/device_drivers/icssg_prueth.rst

Reviewed-by: Simon Horman <horms at kernel.org>
Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
---
v1 - v2:
*) Created icssg_prueth.rst and added Documentation of firmware statistics
as suggested by Jakub Kicinski <kuba at kernel.org>
*) Removed unimplemented preemption statistics.
*) Collected RB tag from Simon Horman <horms at kernel.org>

v1 - https://lore.kernel.org/all/20250227093712.2130561-1-danishanwar at ti.com/

 .../device_drivers/ethernet/index.rst         |  1 +
 .../ethernet/ti/icssg_prueth.rst              | 56 ++++++++++++++++++
 drivers/net/ethernet/ti/icssg/icssg_prueth.h  |  2 +-
 drivers/net/ethernet/ti/icssg/icssg_stats.c   |  6 +-
 drivers/net/ethernet/ti/icssg/icssg_stats.h   | 58 ++++++++++++-------
 .../net/ethernet/ti/icssg/icssg_switch_map.h  | 33 +++++++++++
 6 files changed, 129 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/networking/device_drivers/ethernet/ti/icssg_prueth.rst

diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/Documentation/networking/device_drivers/ethernet/index.rst
index 6fc1961492b7..cd5f31dd07ce 100644
--- a/Documentation/networking/device_drivers/ethernet/index.rst
+++ b/Documentation/networking/device_drivers/ethernet/index.rst
@@ -55,6 +55,7 @@ Contents:
    ti/cpsw_switchdev
    ti/am65_nuss_cpsw_switchdev
    ti/tlan
+   ti/icssg_prueth
    toshiba/spider_net
    wangxun/txgbe
    wangxun/ngbe
diff --git a/Documentation/networking/device_drivers/ethernet/ti/icssg_prueth.rst b/Documentation/networking/device_drivers/ethernet/ti/icssg_prueth.rst
new file mode 100644
index 000000000000..da21ddf431bb
--- /dev/null
+++ b/Documentation/networking/device_drivers/ethernet/ti/icssg_prueth.rst
@@ -0,0 +1,56 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================================
+Texas Instruments ICSSG PRUETH ethernet driver
+==============================================
+
+:Version: 1.0
+
+ICSSG Firmware
+==============
+
+Every ICSSG core has two Programmable Real-Time Unit(PRUs), two auxiliary
+Real-Time Transfer Unit (RTUs), and two Transmit Real-Time Transfer Units
+(TX_PRUs). Each one of these runs its own firmware. The firmwares combnined are
+referred as ICSSG Firmware.
+
+Firmware Statistics
+===================
+
+The ICSSG firmware maintains certain statistics which are dumped by the driver
+via ``ethtool -S <interface>``
+
+These statistics are as follows,
+
+ - ``FW_RTU_PKT_DROP``: Diagnostic error counter which increments when RTU drops a locally injected packet due to port being disabled or rule violation.
+ - ``FW_Q0_OVERFLOW``: TX overflow counter for queue0
+ - ``FW_Q1_OVERFLOW``: TX overflow counter for queue1
+ - ``FW_Q2_OVERFLOW``: TX overflow counter for queue2
+ - ``FW_Q3_OVERFLOW``: TX overflow counter for queue3
+ - ``FW_Q4_OVERFLOW``: TX overflow counter for queue4
+ - ``FW_Q5_OVERFLOW``: TX overflow counter for queue5
+ - ``FW_Q6_OVERFLOW``: TX overflow counter for queue6
+ - ``FW_Q7_OVERFLOW``: TX overflow counter for queue7
+ - ``FW_DROPPED_PKT``: This counter is incremented when a packet is dropped at PRU because of rule violation.
+ - ``FW_RX_ERROR``: Incremented if there was a CRC error or Min/Max frame error at PRU
+ - ``FW_RX_DS_INVALID``: Incremented when RTU detects Data Status invalid condition
+ - ``FW_TX_DROPPED_PACKET``: Counter for packets dropped via TX Port
+ - ``FW_TX_TS_DROPPED_PACKET``: Counter for packets with TS flag dropped via TX Port
+ - ``FW_INF_PORT_DISABLED``: Incremented when RX frame is dropped due to port being disabled
+ - ``FW_INF_SAV``: Incremented when RX frame is dropped due to Source Address violation
+ - ``FW_INF_SA_DL``: Incremented when RX frame is dropped due to Source Address being in the denylist
+ - ``FW_INF_PORT_BLOCKED``: Incremented when RX frame is dropped due to port being blocked and frame being a special frame
+ - ``FW_INF_DROP_TAGGED`` : Incremented when RX frame is dropped for being tagged
+ - ``FW_INF_DROP_PRIOTAGGED``: Incremented when RX frame is dropped for being priority tagged
+ - ``FW_INF_DROP_NOTAG``: Incremented when RX frame is dropped for being untagged
+ - ``FW_INF_DROP_NOTMEMBER``: Incremented when RX frame is dropped for port not being member of VLAN
+ - ``FW_RX_EOF_SHORT_FRMERR``: Incremented if End Of Frame (EOF) task is scheduled without seeing RX_B1
+ - ``FW_RX_B0_DROP_EARLY_EOF``: Incremented when frame is dropped due to Early EOF
+ - ``FW_TX_JUMBO_FRM_CUTOFF``: Incremented when frame is cut off to prevent packet size > 2000 Bytes
+ - ``FW_RX_EXP_FRAG_Q_DROP``: Incremented when express frame is received in the same queue as the previous fragment
+ - ``FW_RX_FIFO_OVERRUN``: RX fifo overrun counter
+ - ``FW_CUT_THR_PKT``: Incremented when a packet is forwarded using Cut-Through forwarding method
+ - ``FW_HOST_RX_PKT_CNT``: Number of valid packets sent by Rx PRU to Host on PSI
+ - ``FW_HOST_TX_PKT_CNT``: Number of valid packets copied by RTU0 to Tx queues
+ - ``FW_HOST_EGRESS_Q_PRE_OVERFLOW``: Host Egress Q (Pre-emptible) Overflow Counter
+ - ``FW_HOST_EGRESS_Q_EXP_OVERFLOW``: Host Egress Q (Pre-emptible) Overflow Counter
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 329b46e9ee53..ff7fce26e851 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -50,7 +50,7 @@
 
 #define ICSSG_MAX_RFLOWS	8	/* per slice */
 
-#define ICSSG_NUM_PA_STATS	4
+#define ICSSG_NUM_PA_STATS	32
 #define ICSSG_NUM_MIIG_STATS	60
 /* Number of ICSSG related stats */
 #define ICSSG_NUM_STATS (ICSSG_NUM_MIIG_STATS + ICSSG_NUM_PA_STATS)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c
index 8800bd3a8d07..3f1400e0207c 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
@@ -11,7 +11,6 @@
 
 #define ICSSG_TX_PACKET_OFFSET	0xA0
 #define ICSSG_TX_BYTE_OFFSET	0xEC
-#define ICSSG_FW_STATS_BASE	0x0248
 
 static u32 stats_base[] = {	0x54c,	/* Slice 0 stats start */
 				0xb18,	/* Slice 1 stats start */
@@ -44,9 +43,8 @@ void emac_update_hardware_stats(struct prueth_emac *emac)
 
 	if (prueth->pa_stats) {
 		for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) {
-			reg = ICSSG_FW_STATS_BASE +
-			      icssg_all_pa_stats[i].offset *
-			      PRUETH_NUM_MACS + slice * sizeof(u32);
+			reg = icssg_all_pa_stats[i].offset +
+			      slice * sizeof(u32);
 			regmap_read(prueth->pa_stats, reg, &val);
 			emac->pa_stats[i] += val;
 		}
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h
index e88b919f532c..5ec0b38e0c67 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h
@@ -155,24 +155,10 @@ static const struct icssg_miig_stats icssg_all_miig_stats[] = {
 	ICSSG_MIIG_STATS(tx_bytes, true),
 };
 
-/**
- * struct pa_stats_regs - ICSSG Firmware maintained PA Stats register
- * @fw_rx_cnt: Number of valid packets sent by Rx PRU to Host on PSI
- * @fw_tx_cnt: Number of valid packets copied by RTU0 to Tx queues
- * @fw_tx_pre_overflow: Host Egress Q (Pre-emptible) Overflow Counter
- * @fw_tx_exp_overflow: Host Egress Q (Express) Overflow Counter
- */
-struct pa_stats_regs {
-	u32 fw_rx_cnt;
-	u32 fw_tx_cnt;
-	u32 fw_tx_pre_overflow;
-	u32 fw_tx_exp_overflow;
-};
-
-#define ICSSG_PA_STATS(field)			\
-{						\
-	#field,					\
-	offsetof(struct pa_stats_regs, field),	\
+#define ICSSG_PA_STATS(field)	\
+{				\
+	#field,			\
+	field,			\
 }
 
 struct icssg_pa_stats {
@@ -181,10 +167,38 @@ struct icssg_pa_stats {
 };
 
 static const struct icssg_pa_stats icssg_all_pa_stats[] = {
-	ICSSG_PA_STATS(fw_rx_cnt),
-	ICSSG_PA_STATS(fw_tx_cnt),
-	ICSSG_PA_STATS(fw_tx_pre_overflow),
-	ICSSG_PA_STATS(fw_tx_exp_overflow),
+	ICSSG_PA_STATS(FW_RTU_PKT_DROP),
+	ICSSG_PA_STATS(FW_Q0_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q1_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q2_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q3_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q4_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q5_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q6_OVERFLOW),
+	ICSSG_PA_STATS(FW_Q7_OVERFLOW),
+	ICSSG_PA_STATS(FW_DROPPED_PKT),
+	ICSSG_PA_STATS(FW_RX_ERROR),
+	ICSSG_PA_STATS(FW_RX_DS_INVALID),
+	ICSSG_PA_STATS(FW_TX_DROPPED_PACKET),
+	ICSSG_PA_STATS(FW_TX_TS_DROPPED_PACKET),
+	ICSSG_PA_STATS(FW_INF_PORT_DISABLED),
+	ICSSG_PA_STATS(FW_INF_SAV),
+	ICSSG_PA_STATS(FW_INF_SA_DL),
+	ICSSG_PA_STATS(FW_INF_PORT_BLOCKED),
+	ICSSG_PA_STATS(FW_INF_DROP_TAGGED),
+	ICSSG_PA_STATS(FW_INF_DROP_PRIOTAGGED),
+	ICSSG_PA_STATS(FW_INF_DROP_NOTAG),
+	ICSSG_PA_STATS(FW_INF_DROP_NOTMEMBER),
+	ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
+	ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
+	ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
+	ICSSG_PA_STATS(FW_RX_EXP_FRAG_Q_DROP),
+	ICSSG_PA_STATS(FW_RX_FIFO_OVERRUN),
+	ICSSG_PA_STATS(FW_CUT_THR_PKT),
+	ICSSG_PA_STATS(FW_HOST_RX_PKT_CNT),
+	ICSSG_PA_STATS(FW_HOST_TX_PKT_CNT),
+	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_PRE_OVERFLOW),
+	ICSSG_PA_STATS(FW_HOST_EGRESS_Q_EXP_OVERFLOW),
 };
 
 #endif /* __NET_TI_ICSSG_STATS_H */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
index 424a7e945ea8..490a9cc06fb0 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
@@ -231,4 +231,37 @@
 /* Start of 32 bits PA_STAT counters */
 #define PA_STAT_32b_START_OFFSET                           0x0080
 
+#define FW_RTU_PKT_DROP			0x0088
+#define FW_Q0_OVERFLOW			0x0090
+#define FW_Q1_OVERFLOW			0x0098
+#define FW_Q2_OVERFLOW			0x00A0
+#define FW_Q3_OVERFLOW			0x00A8
+#define FW_Q4_OVERFLOW			0x00B0
+#define FW_Q5_OVERFLOW			0x00B8
+#define FW_Q6_OVERFLOW			0x00C0
+#define FW_Q7_OVERFLOW			0x00C8
+#define FW_DROPPED_PKT			0x00F8
+#define FW_RX_ERROR			0x0100
+#define FW_RX_DS_INVALID		0x0108
+#define FW_TX_DROPPED_PACKET		0x0110
+#define FW_TX_TS_DROPPED_PACKET		0x0118
+#define FW_INF_PORT_DISABLED		0x0120
+#define FW_INF_SAV			0x0128
+#define FW_INF_SA_DL			0x0130
+#define FW_INF_PORT_BLOCKED		0x0138
+#define FW_INF_DROP_TAGGED		0x0140
+#define FW_INF_DROP_PRIOTAGGED		0x0148
+#define FW_INF_DROP_NOTAG		0x0150
+#define FW_INF_DROP_NOTMEMBER		0x0158
+#define FW_RX_EOF_SHORT_FRMERR		0x0188
+#define FW_RX_B0_DROP_EARLY_EOF		0x0190
+#define FW_TX_JUMBO_FRM_CUTOFF		0x0198
+#define FW_RX_EXP_FRAG_Q_DROP		0x01A0
+#define FW_RX_FIFO_OVERRUN		0x01A8
+#define FW_CUT_THR_PKT			0x01B0
+#define FW_HOST_RX_PKT_CNT		0x0248
+#define FW_HOST_TX_PKT_CNT		0x0250
+#define FW_HOST_EGRESS_Q_PRE_OVERFLOW	0x0258
+#define FW_HOST_EGRESS_Q_EXP_OVERFLOW	0x0260
+
 #endif /* __NET_TI_ICSSG_SWITCH_MAP_H  */

base-commit: f252f23ab657cd224cb8334ba69966396f3f629b
-- 
2.34.1



From a.fatoum at pengutronix.de  Wed Mar  5 03:01:53 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 5 Mar 2025 12:01:53 +0100
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
 <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
Message-ID: <7ac2b8db-22c7-4168-b1b7-4f9f0ab10531@pengutronix.de>

Hi George,
Hi Guenter,

On 05.03.25 11:34, George Cherian wrote:
>> why is armada_37xx_wdt also here?
>> The stop function in that driver may not sleep.
> Marek,
> 
> Thanks for reviewing.
> Since the stop function has a regmap_write(), I thought it might sleep.
> Now that you pointed it out, I assume that it is an MMIO based regmap being used for armada.
> I will update the same in the next version

Failure to add WDIOF_STOP_MAYSLEEP when it's needed can lead to
kernel hanging. Failure to add an alternative WDIOF_STOP_ATOMIC
would lead to the kernel option being a no-op.

I think a no-op stop_on_panic (or reset_on_panic) is a saner default.

Cheers,
Ahmad

> 
>>
>> Marek
> 
> -George


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From gcherian at marvell.com  Wed Mar  5 03:28:40 2025
From: gcherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 11:28:40 +0000
Subject: [EXTERNAL] Re: [PATCH v4 0/2] Add stop_on_panic support for
 watchdog
In-Reply-To: <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>
Message-ID: <PH8PR18MB53817EC09B918852B78DF3AAC5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>

Hi Ahmad,
>Hi George,
> On 05.03.25 11:10, George Cherian wrote:
>> This series adds a new kernel command line option to watchdog core to
>> stop the watchdog on panic. This is useul in certain systems which prevents
>> successful loading of kdump kernel due to watchdog reset.
>> 
>> Some of the watchdog drivers stop function could sleep. For such
>> drivers the stop_on_panic is not valid as the notifier callback happens
>> in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
>> options to indicate whether the stop function would sleep.
>
>Did you consider having a reset_on_panic instead, which sets a user-specified
>timeout on panic? This would make the mechanism useful also for watchdogs

/proc/sys/kernel/panic already provides that support. You may echo a non-zero value 
and the system tries for a soft reboot after those many seconds. But this doesn't happen 
in case of a kdump kernel load after panic.
>that can't be disabled and would protect against system lock up: 
>Consider a memory-corruption bug (perhaps externally via DMA), which partially
>overwrites both main and kdump kernel. With a disabled watchdog, the system
>may not be able to recover on its own.

Yes, that is the reason why the kernel command-line is optional and by default it is set to zero.
So that in cases if you have a corrupted kdump kernel then watchdog kicks in.
>
>If you did consider it, what made you decide against it?
watchdog.stop_on_panic=1 is specifically for systems which can't boot a kdump kernel due to the fact 
that the kdump kernel gets a watchdog reset while booting, may be due to a shorter watchdog time.
For eg: a 32-bit watchdog down counter running at 1GHz.
reset_on_panic can guarantee only the largest watchdog timeout supported by HW, 
since there is no one to ping the watchdog. 
>
>Thanks,
>Ahmad
>
>> 
>> 
> Changelog:
> v1 -> v2
> - Remove the per driver flag setting option
> - Take the parameter via kernel command-line parameter to watchdog_core.
> 
> v2 -> v3
> - Remove the helper function watchdog_stop_on_panic() from watchdog.h.
> - There are no users for this. 
> 
> v3 -> v4
> - Since the panic notifier is in atomic context, watchdog functions
>   which sleep can't be called. 
> - Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
>   function sleeps.
> - Simplify the stop_on_panic kernel command line parsing.
> - Enable the panic notiffier only if the watchdog stop function doesn't
>   sleep
> 
> George Cherian (2):
>   watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
>   drivers: watchdog: Add support for panic notifier callback

- George

From andre.przywara at arm.com  Wed Mar  5 03:34:30 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 5 Mar 2025 11:34:30 +0000
Subject: [PATCH v3 04/15] dt-bindings: clk: sunxi-ng: document Allwinner
 A523 CCU
In-Reply-To: <20250304141125.GA2518548-robh@kernel.org>
References: <20250304012805.28594-1-andre.przywara@arm.com>
	<20250304012805.28594-5-andre.przywara@arm.com>
	<20250304141125.GA2518548-robh@kernel.org>
Message-ID: <20250305113430.47166de3@donnerap.manchester.arm.com>

On Tue, 4 Mar 2025 08:11:25 -0600
Rob Herring <robh at kernel.org> wrote:

Hi,

> On Tue, Mar 04, 2025 at 01:27:54AM +0000, Andre Przywara wrote:
> > The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> > the main CCU.
> > 
> > The source clock list differs in some annoying details, and folding this
> > into the existing Allwinner CCU clock binding document gets quite
> > unwieldy, so create a new document for these CCUs.
> > Add the new compatible string, along with the required input clock
> > lists. This conditionally describes the input clock list, to make for
> > an easier patch adding the other CCUs.
> > 
> > Also add the DT binding headers, listing all the clocks with their ID
> > numbers.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> >  .../clock/allwinner,sun55i-a523-ccu.yaml      |  77 +++++++
> >  include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
> >  include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
> >  3 files changed, 354 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> >  create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
> >  create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
> > 
> > diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> > new file mode 100644
> > index 0000000000000..2eacaeaeabac7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> > @@ -0,0 +1,77 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Allwinner A523 Clock Control Unit
> > +
> > +maintainers:
> > +  - Andre Przywara <andre.przywara at arm.com>
> > +
> > +properties:
> > +  "#clock-cells":
> > +    const: 1
> > +
> > +  "#reset-cells":
> > +    const: 1
> > +
> > +  compatible:
> > +    enum:
> > +      - allwinner,sun55i-a523-ccu
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    minItems: 4
> > +    maxItems: 4
> > +
> > +  clock-names:
> > +    minItems: 4
> > +    maxItems: 4
> > +
> > +required:
> > +  - "#clock-cells"
> > +  - "#reset-cells"
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +
> > +if:  
> 
> Put this under an allOf and use another 'if' instead of the 'else' 
> clause in the 2nd patch.

Ah, that's a neat idea! What do I do with the clocks and clock-names
above, then? Just have them as "true"?

Krzysztof, would you agree with this approach, and shall I still combine
both in just one patch?

Cheers,
Andre

> > +  properties:
> > +    compatible:
> > +      enum:
> > +        - allwinner,sun55i-a523-ccu
> > +
> > +then:
> > +  properties:
> > +    clocks:
> > +      items:
> > +        - description: High Frequency Oscillator (usually at 24MHz)
> > +        - description: Low Frequency Oscillator (usually at 32kHz)
> > +        - description: Internal Oscillator
> > +        - description: Low Frequency Oscillator fanout
> > +
> > +    clock-names:
> > +      items:
> > +        - const: hosc
> > +        - const: losc
> > +        - const: iosc
> > +        - const: losc-fanout
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    ccu: clock at 2001000 {  
> 
> Drop ccu and it's 'clock-controller' not 'clock'.
> 
> > +        compatible = "allwinner,sun55i-a523-ccu";
> > +        reg = <0x2001000 0x1000>;
> > +        clocks = <&osc24M>, <&osc32k>, <&iosc>, <&r_ccu 2>;
> > +        clock-names = "hosc", "losc", "iosc", "losc-fanout";
> > +        #clock-cells = <1>;
> > +        #reset-cells = <1>;
> > +    };
> > +
> > +...  



From krzk at kernel.org  Wed Mar  5 03:35:15 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 12:35:15 +0100
Subject: [PATCH v3 2/6] dt-bindings: soc: imx93-media-blk-ctrl: Add LDB
 subnode into schema and example
In-Reply-To: <4414669.ejJDZkT8p0@steina-w>
References: <20250304154929.1785200-1-alexander.stein@ew.tq-group.com>
 <20250304154929.1785200-3-alexander.stein@ew.tq-group.com>
 <20250305-dandelion-axolotl-of-excitement-05fa70@krzk-bin>
 <4414669.ejJDZkT8p0@steina-w>
Message-ID: <c7129d8e-87de-444c-be52-b2eedf03585f@kernel.org>

On 05/03/2025 10:02, Alexander Stein wrote:
> Hi,
> 
> Am Mittwoch, 5. M?rz 2025, 08:13:04 CET schrieb Krzysztof Kozlowski:
>> On Tue, Mar 04, 2025 at 04:49:21PM +0100, Alexander Stein wrote:
>>> Document the LDB bridge subnode and add the subnode into the example.
>>> For the subnode to work, the block control must scan its subnodes and
>>
>> Don't describe drivers, but describe the hardware.
> 
> Thanks, I'll rephrase to describe the hardware better regarding LVDS.
> 
>>
>>> bind drivers to them, do not misuse either simple-bus or simple-mfd
>>> here.
>>
>> I don't understand that simple-bus or simple-mfd statement. There are no
>> such compatibles here.
> 
> Same as above, the wording stems from 1cb0c87d27dcc ("dt-bindings: soc:
> imx8mp-media-blk-ctrl: Add LDB subnode into schema and example").
> I'll drop it to avoid confusion.
> 
>>
>>>
>>> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
>>> ---
>>>  .../soc/imx/fsl,imx93-media-blk-ctrl.yaml     | 51 +++++++++++++++++++
>>>  1 file changed, 51 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
>>> index b3554e7f9e76d..cd785111928bf 100644
>>> --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
>>> +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
>>> @@ -24,6 +24,14 @@ properties:
>>>    reg:
>>>      maxItems: 1
>>>  
>>> +  ranges: true
>>> +
>>> +  '#address-cells':
>>> +    const: 1
>>> +
>>> +  '#size-cells':
>>> +    const: 1
>>> +
>>>    '#power-domain-cells':
>>>      const: 1
>>>  
>>> @@ -46,9 +54,20 @@ properties:
>>>        - const: csi
>>>        - const: dsi
>>>  
>>> +  bridge at 20:
>>
>> @20 looks wrong. Use 'ranges;' and try again your DTS...
>>
>> Binding is supposed to be complete. We have several examples when people
>> added children one-by-one, everytime with different reasoning about
>> child addressing.
>>
>> So please confirm: this is complete and no other children will ever be
>> added here... or you are 100% sure that all future children will be
>> unit-addressable (will have unit address and appropriate properties).
> 
> This block control is a collection of registers for different purposes:
> * MIPI-DSI
> * MIPI-CSI
> * Parallel camera
> * LVDS
> * CAMERA_MUX
> 
> At lease for parallel camera, another subnode is expected ([1]).


That one at least have MMIO as well. No I wonder whether the others will
come without MMIO one day.

Why this cannot be sent all at once? Entire device binding?

> 
> [1] https://lore.kernel.org/all/20240819024001.850065-1-victor.liu at nxp.com/
> 
>> BTW, I don't quite get why this is both syscon and has translation for
>> child addresses. Does it mean your child does not use the same MMIO as
>> parent, thus leading to unsynchronized reg access?
> 
> I'm not sure what the best practices are. This LDB has two registers
> inside this block. So it seems reasonable to me to indicate this using

reg is fine, but you added ranges which means there is translation
between child addressing and parent MMIO. Usually, although not always,
when child is expected to use parent's syscon, you do not have ranges,
because the syscon deals with that translation.

What's more, your @20 means you depend on one specific value of ranges.

I would just skip the ranges and claim there is no direct mapping of
addresses. Reg defines offsets within this device addressing and this
device will handle it.

> a reg property. On the other hand, access is solely done by accessing
> via syscon, so unsynchronized reg access is not an issue.
> 
> What I am getting from your comments this node should not have 'reg'
> property, as it uses syscon anyway.


> 
>>> +    type: object
>>> +    additionalProperties: true
>>> +    properties:
>>> +      compatible:
>>> +        contains:
>>> +          const: fsl,imx93-ldb
>>> +
>>>  required:
>>>    - compatible
>>>    - reg
>>> +  - ranges
>>> +  - '#address-cells'
>>> +  - '#size-cells'
>>>    - power-domains
>>>    - clocks
>>>    - clock-names
>>> @@ -77,4 +96,36 @@ examples:
>>>                 clock-names = "apb", "axi", "nic", "disp", "cam",
>>>                               "pxp", "lcdif", "isi", "csi", "dsi";
>>>        #power-domain-cells = <1>;
>>> +      #address-cells = <1>;
>>> +      #size-cells = <1>;
>>> +      ranges = <0x0 0x4ac10000 0x10000>;
>>> +
>>> +      bridge at 20 {
>>> +          compatible = "fsl,imx93-ldb";
>>> +          reg = <0x20 0x4>, <0x24 0x4>;
>>> +          reg-names = "ldb", "lvds";
>>> +          clocks = <&clk IMX93_CLK_LVDS_GATE>;
>>> +          clock-names = "ldb";
>>> +
>>> +          ports {
>>> +              #address-cells = <1>;
>>> +              #size-cells = <0>;
>>> +
>>> +              port at 0 {
>>> +                  reg = <0>;
>>> +
>>> +                  ldb_from_lcdif2: endpoint {
>>> +                      remote-endpoint = <&lcdif2_to_ldb>;
>>> +                  };
>>> +              };
>>> +
>>> +              port at 1 {
>>> +                  reg = <1>;
>>> +
>>> +                  ldb_lvds: endpoint {
>>> +                      remote-endpoint = <&ldb_to_panel>;
>>> +                  };
>>> +              };
>>> +          };
>>
>> Messed indentation.
> 
> This is already from the original binding. I'll fix in a separate commit.

How? I did not see any '-', only adding here.


Best regards,
Krzysztof


From angelogioacchino.delregno at collabora.com  Wed Mar  5 04:05:41 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 13:05:41 +0100
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
 <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
 <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>
Message-ID: <9d383fc5-8c64-478c-8aab-6c56bf5b45be@collabora.com>

Il 05/03/25 09:36, Jason-JH Lin (???) ha scritto:
> Hi Angelo,
> 
> Thanks for the reviews.
> 
> On Tue, 2025-03-04 at 10:32 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
>>> MT8196 has 3 new hardware configuration compared with the previous
>>> SoC,
>>> which correspond to the 3 new driver data:
>>>
>>> 1. mminfra_offset: For GCE data plane control
>>>  ??? Since GCE has been moved into mminfra, GCE needs to append the
>>>  ??? mminfra offset to the DRAM address when accessing the DRAM.
>>>
>>> 2. gce_vm: For GCE hardware virtualization
>>>  ??? Currently, the first version of the mt8196 mailbox controller
>>> only
>>>  ??? requires setting the VM-related registers to enable the
>>> permissions
>>>  ??? of a host VM.
>>
>> I think that the GCE VM changes should go to a different commit, as
>> that
>> looks like being something not critical for basic functionality of
>> the
>> MMINFRA GCE.
>>
>> I really like seeing support for that, but please split the basic
>> stuff
>> from the extra functionality :-)
>>
> 
> The VM configuration is the basic configuration for MT8196, so I put it
> together with other configurations in one patch.
> But I can understand you want the new function as a independent patch.
> So I will split the VM related part, mminfra_offset part and dma_mask
> part to 3 single pathes. Then add them as a driver data for MT8196 in
> this patch.
> 

Yeah, thanks, the log simply gets more readable like that.

>>>
>>> 3. dma_mask_bit: For dma address bit control
>>>  ??? In order to avoid the hardware limitations of MT8196 accessing
>>> DRAM,
>>>  ??? GCE needs to configure the DMA address to be less than 35 bits.
>>>
>>> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
>>> ---
>>>  ? drivers/mailbox/mtk-cmdq-mailbox.c?????? | 90
>>> +++++++++++++++++++++---
>>>  ? include/linux/mailbox/mtk-cmdq-mailbox.h |? 2 +
>>>  ? 2 files changed, 84 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
>>> b/drivers/mailbox/mtk-cmdq-mailbox.c
>>> index d186865b8dce..0abe10a7fef9 100644
>>> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
>>> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
>>> @@ -43,6 +43,17 @@
>>>  ? #define GCE_CTRL_BY_SW????????????????????????????? GENMASK(2, 0)
>>>  ? #define GCE_DDR_EN????????????????????????? GENMASK(18, 16)
>>>
>>> +#define GCE_VM_ID_MAP0?????????????????????? 0x5018
>>> +#define GCE_VM_MAP0_ALL_HOST???????????????? GENMASK(29, 0)
>>> +#define GCE_VM_ID_MAP1?????????????????????? 0x501c
>>> +#define GCE_VM_MAP1_ALL_HOST???????????????? GENMASK(29, 0)
>>> +#define GCE_VM_ID_MAP2?????????????????????? 0x5020
>>> +#define GCE_VM_MAP2_ALL_HOST???????????????? GENMASK(29, 0)
>>> +#define GCE_VM_ID_MAP3?????????????????????? 0x5024
>>> +#define GCE_VM_MAP3_ALL_HOST???????????????? GENMASK(5, 0)
>>> +#define GCE_VM_CPR_GSIZE???????????? 0x50c4
>>> +#define GCE_VM_CPR_GSIZE_HSOT??????????????????????? GENMASK(3, 0)
>>
>> typo: GSIZE_HOST....
>>
> 
> Thanks, I'll fix it.
> 
>> ...but also, if you could add some brief description of what the
>> VMIDs are used for
>> and what the GSIZE is... that'd be very much appreciated from whoever
>> is reading
>> this.
>>
> VMID_MAP configuration is in the previous reply mail for CK.

Oh, sorry, too many emails - sometimes I lose some :-)

> CPR_GSIZE is the setting for allocating the CPR SRAM size to each VM.

Would be awesome if you could then clarify the comment that you have later in
the code here, from...

/* config cpr size for host vm */

to

/* Set the amount of CPR SRAM to allocate to each VM */

...that could be a way of more properly describing what the writel there is doing.

> 
>> The GCE stuff isn't even properly described in datasheets - I do
>> (probably!)
>> understand what those are for, but asking people to get years of
>> experience on
>> MediaTek to understand what's going on would be a bit rude, wouldn't
>> it? :-D
>>
> 
> I agree with you :-)
> I'll put them in the VM patch and add some brief description for them.
> 

Thanks, much appreciated!

>>> +
>>>  ? #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
>>>  ? #define CMDQ_THR_ENABLED??????????? 0x1
>>>  ? #define CMDQ_THR_DISABLED?????????? 0x0
>>> @@ -87,11 +98,24 @@ struct cmdq {
>>>  ? struct gce_plat {
>>>  ????? u32 thread_nr;
>>>  ????? u8 shift;
>>> +???? dma_addr_t mminfra_offset;
>>
>> It looks like this is exactly the DRAM's iostart... at least, I can
>> see that in the
>> downstream devicetree that's where it starts.
>>
>>  ??????? memory: memory at 80000000 {
>>  ??????????????? device_type = "memory";
>>  ??????????????? reg = <0 0x80000000 0 0x40000000>;
>>  ??????? };
>>
>> It doesn't really look like being a coincidence, but, for the sake of
>> asking:
>> is this just a coincidence? :-)
>>
> 
> As the confirmation with the hardware designer in previous reply mail
> for CK:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20250218054405.2017918-4-jason-jh.lin at mediatek.com/#26258463
> 

That explanation was simply wonderful.

> Since the MMINFRA remap subtracting 2G is done in the hardware circuit
> and cannot be configured by software, the address +2G adjustment is
> necessary to implement in the CMDQ driver.
> 
> So that might not be a coincidence.
> But even if DRAM start address changes, this mminfra_offset is still
> subtracting 2G, so I think it is a better choice to define it as the
> driver data for MT8196.
> 

....so, this makes me think the following:

1. The DRAM start address cannot *ever* be less than 2G, because otherwise the
    MMINFRA HW would have a hole in the usable address range;
    1a. If the start address changes to less than 2G, then also the IOMMU would
        get limitations, not only the mminfra..!
    2b. This makes it very very very unlikely for the start address to be changed
        to less than 0x80000000

2. If the DRAM start address changes to be ABOVE 2G (so more than 0x80000000),
    there would be no point for MMINFRA to start a "config path" write (or read)
    in the SMMU DRAM block, would it? ;-)

I get it - if the DRAM moves up, MMINFRA is still at 2G because that's hard baked
into the hardware, but I foresee that it'll be unlikely to see a platform changing
the DRAM start address arbitrarily, getting out-of-sync with MMINFRA.

I propose to just get the address from the memory node for now, and to add a nice
comment in the code that explains that "In at least MT8196, the MMINFRA hardware
subtracts xyz etc etc" (and that explanation from the previous email is again
wonderful and shall not be lost: either use that in the comment, or add it to
the commit description, because it's really that good).

Should a new SoC appear in the future requiring an offset from the DRAM start
address, we will think about how to make that work in the best possible way: in
that case we could either reference something else to get the right address or
we can just change this driver to just use the 2G offset statically for all.

What I'm trying to do here is to reduce the amount of changes that we'd need for
adding new SoCs: since that 2G MMINFRA offset -> 2G DRAM start is not a coincidence
I think that, should the DRAM start vary on new SoCs, the MMINFRA offset will
follow the trend and vary with it.

So what I think is:
1. If I'm right, adding a new SoC (with different MMINFRA + DRAM offset) will be
    as easy as adding a compatible string in the bindings, no effort in changing
    this driver with new pdata offsets;
2. If I'm wrong, adding a new SoC means adding compat string and adding pdata and
    one variable in the cmdq struct.

Where N.2 is what we would do anyway if we don't go with my proposed solution...

All this is just to give you my considerations about this topic - you're left
completely free to disagree with me.
If you disagree, I will trust your judgement, no problem here.

>>>  ????? bool control_by_sw;
>>>  ????? bool sw_ddr_en;
>>> +???? bool gce_vm;
>>> +???? u32 dma_mask_bit;
>>>  ????? u32 gce_num;
>>>  ? };
>>>
>>> +static inline u32 cmdq_reg_shift_addr(dma_addr_t addr, const
>>> struct gce_plat *pdata)
>>> +{
>>> +???? return ((addr + pdata->mminfra_offset) >> pdata->shift);
>>> +}
>>> +
>>> +static inline u32 cmdq_reg_revert_addr(dma_addr_t addr, const
>>> struct gce_plat *pdata)
>>> +{
>>> +???? return ((addr << pdata->shift) - pdata->mminfra_offset);
>>> +}
>>
>> I'm not sure that you really need those two functions... probably
>> it's simply
>> cleaner and easier to just write that single line every time... and
>> I'm
>> saying that especially for how you're using those functions, with
>> some readl()
>> passed directly as param, decreasing human readability by "a whole
>> lot" :-)
>>
> 
> The reason why I use API wrapper instead of writing it directly in
> readl() is to avoid missing the shift or mminfra_offset conversion in
> some places.
> This problem is not easy to debug, and I have encountered it at least
> twice...
> 
> I think the advantage of using function is that it can be uniformly
> modified to all places that need to handle DRAM address conversion.
> What do you think? :-)
> 

Eh, if you put it like that... it makes sense, so.. yeah, okay :-)

Still, please cleanup those instances of

`cmdq_reg_revert_addr(readl(something), pdata)`

those might be hard to read, so please just do something like:

regval = readl(something);
curr_pa = cmdq_revert_addr(regval, pdata);

...reword to your own liking, of course.

>>> +
>>>  ? static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
>>>  ? {
>>>  ????? WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
>>> @@ -112,6 +136,30 @@ u8 cmdq_get_shift_pa(struct mbox_chan *chan)
>>>  ? }
>>>  ? EXPORT_SYMBOL(cmdq_get_shift_pa);
>>>
>>> +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan)
>>> +{
>>> +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
>>> mbox);
>>> +
>>> +???? return cmdq->pdata->mminfra_offset;
>>> +}
>>> +EXPORT_SYMBOL(cmdq_get_offset_pa);
>>
>> I think I remember this get_offset_pa from the old times, then CK
>> removed it (and I
>> was really happy about that disappearing), or am I confusing this
>> with something
>> else?
>>
>> (of course, this wasn't used for mminfra, but for something else!)
>>
> 
> I can't find any remove history in mtk-cmdq-mailbox.c.
> 
> Maybe you mean the patch in this series?
> https://lore.kernel.org/all/171213938049.123698.15573779837703602591.b4-ty at collabora.com/
> 

Uhm, I think I may have confused something here, but yes I was remembering the
patch series that you pointed out, definitely.

At the end, that series is doing something else, so nevermind, was just confusion.

>>> +
>>> +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t
>>> addr)
>>> +{
>>> +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
>>> mbox);
>>> +
>>> +???? if (cmdq->pdata->mminfra_offset == 0)
>>> +???????????? return false;
>>> +
>>> +???? /*
>>> +????? * mminfra will recognize the addr that greater than the
>>> mminfra_offset
>>> +????? * as a transaction to DRAM.
>>> +????? * So the caller needs to append mminfra_offset for the true
>>> case.
>>> +????? */
>>> +???? return (addr >= cmdq->pdata->mminfra_offset);
>>
>>
>> /**
>>  ? * cmdq_is_mminfra_gce() - Brief description
>>  ? * @args.....
>>  ? *
>>  ? * The MMINFRA GCE will recognize an address greater than DRAM
>> iostart as a
>>  ? * DRAM transaction instead of ....xyz
>>  ? *
>>  ? * In order for callers to perform (xyz) transactions through the
>> CMDQ, those
>>  ? * need to know if they are using a GCE located in MMINFRA.
>>  ? */
>> bool cmdq_is_mminfra_gce(...)
>> {
>>  ??????? return cmdq->pdata->mminfra_offset &&
>>  ?????????????? (addr >= cmdq->pdata->mminfra_offset)
>>
>>> +}
>>> +EXPORT_SYMBOL(cmdq_addr_need_offset);
>>> +
>>
> 
> OK, I'll modify the API like this.
> 
>> ...but then, is there really no way of just handling the GCE being in
>> MMINFRA
>> transparently from the callers? Do the callers really *need* to know
>> that they're
>> using a new GCE?!
>>
> 
> Since the address subtracting is done in MMINFRA hardware, I think GCE
> users really need to handle it in driver.
> 

Since the users of this infrastructure are multimedia related (disp/MDP3),
I'd also like to get an opinion from MediaTek engineers familiar with that.

CK, Moudy, any opinion on that, please?

>> Another way of saying: can't we just handle the address translation
>> in here instead
>> of instructing each and every driver about how to communicate with
>> the new GCE?!
>>
> 
> The DRAM address may not only be the command buffer to GCE, but also
> the working buffer provided by CMDQ users and being a part of GCE
> instruction, so we need to handle the address translation in CMDQ
> helper driver for the instruction generation.
> E.g. ISP drivers may use GCE to write a hardware settings to a DRAM as
> backup buffer. The GCE write instruction will be:
> WRITE the value of ISP register to DRAM address + mminfra_offset.
> 
> But most of the CMDQ users only need to use GCE to write hardware
> register, so I only keep the translation in cmdq_pkt_mem_move(),
> cmdq_pkt_poll_addr() and cmdq_pkt_jump_abs() at the latest series.

Yeah you're choosing the best of both worlds in that case, I do agree, but
still - if there's a way to avoid drivers to have different handling for
mminfra vs no-mminfra, that'd still be preferred.

Having the handling for something *centralized* somewhere, instead of it
being sparse here and there, would make maintenance way easier...

...and that's why I'm asking for CK and Moudy's opinion, nothing else :-)

Cheers!
Angelo



From mark.rutland at arm.com  Wed Mar  5 04:15:35 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 5 Mar 2025 12:15:35 +0000
Subject: [PATCH 1/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <20250305104925.189198-2-vschneid@redhat.com>
References: <20250305104925.189198-1-vschneid@redhat.com>
 <20250305104925.189198-2-vschneid@redhat.com>
Message-ID: <Z8hAZ09Q40fxLJSk@J2N7QTR9R3>

On Wed, Mar 05, 2025 at 11:49:25AM +0100, Valentin Schneider wrote:
> From: Mark Rutland <mark.rutland at arm.com>
> 
> For an architecture to enable CONFIG_ARCH_HAS_RESCHED_LAZY, two things are
> required:
> 1) Adding a TIF_NEED_RESCHED_LAZY flag definition
> 2) Checking for TIF_NEED_RESCHED_LAZY in the appropriate locations
> 
> 2) is handled in a generic manner by CONFIG_GENERIC_ENTRY, which isn't
> (yet) implemented for arm64. However, outside of core scheduler code,
> TIF_NEED_RESCHED_LAZY only needs to be checked on a kernel exit, meaning:
> o return/entry to userspace.
> o return/entry to guest.
> 
> The return/entry to a guest is all handled by xfer_to_guest_mode_handle_work()
> which already does the right thing, so it can be left as-is.
> 
> arm64 doesn't use common entry's exit_to_user_mode_prepare(), so update its
> return to user path to check for TIF_NEED_RESCHED_LAZY and call into
> schedule() accordingly.
> 
> Link: https://lore.kernel.org/linux-rt-users/20241216190451.1c61977c at mordecai.tesarici.cz/
> Link: https://lore.kernel.org/all/xhsmh4j0fl0p3.mognet at vschneid-thinkpadt14sgen2i.remote.csb/
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> [testdrive, _TIF_WORK_MASK fixlet and changelog.]
> Signed-off-by: Mike Galbraith <efault at gmx.de>
> [Another round of testing; changelog faff]
> Signed-off-by: Valentin Schneider <vschneid at redhat.com>
> ---
>  arch/arm64/Kconfig                   |  1 +
>  arch/arm64/include/asm/thread_info.h | 16 +++++++++-------
>  arch/arm64/kernel/entry-common.c     |  2 +-
>  3 files changed, 11 insertions(+), 8 deletions(-)

Catalin, Will, given this is small and self-contained, I reckon it makes
sense to pick this up ahead of Jinjie's series to move arm64 over to the
generic entry library (which is on my queue of things to review). Even
if we pick up both, it'll be easier to bisect and debug issues caused by
this patch alone.

The fixes/cleanups from Mike and Valentin look right to me, so FWIW:

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index fcdd0ed3eca89..7789d7fb6f191 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -41,6 +41,7 @@ config ARM64
>  	select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
>  	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
>  	select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT
> +	select ARCH_HAS_PREEMPT_LAZY
>  	select ARCH_HAS_PTE_DEVMAP
>  	select ARCH_HAS_PTE_SPECIAL
>  	select ARCH_HAS_HW_PTE_YOUNG
> diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
> index 1114c1c3300a1..4443ef2789758 100644
> --- a/arch/arm64/include/asm/thread_info.h
> +++ b/arch/arm64/include/asm/thread_info.h
> @@ -59,11 +59,12 @@ void arch_setup_new_exec(void);
>  
>  #define TIF_SIGPENDING		0	/* signal pending */
>  #define TIF_NEED_RESCHED	1	/* rescheduling necessary */
> -#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
> -#define TIF_FOREIGN_FPSTATE	3	/* CPU's FP state is not current's */
> -#define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
> -#define TIF_MTE_ASYNC_FAULT	5	/* MTE Asynchronous Tag Check Fault */
> -#define TIF_NOTIFY_SIGNAL	6	/* signal notifications exist */
> +#define TIF_NEED_RESCHED_LAZY	2	/* Lazy rescheduling needed */
> +#define TIF_NOTIFY_RESUME	3	/* callback before returning to user */
> +#define TIF_FOREIGN_FPSTATE	4	/* CPU's FP state is not current's */
> +#define TIF_UPROBE		5	/* uprobe breakpoint or singlestep */
> +#define TIF_MTE_ASYNC_FAULT	6	/* MTE Asynchronous Tag Check Fault */
> +#define TIF_NOTIFY_SIGNAL	7	/* signal notifications exist */
>  #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
>  #define TIF_SYSCALL_AUDIT	9	/* syscall auditing */
>  #define TIF_SYSCALL_TRACEPOINT	10	/* syscall tracepoint for ftrace */
> @@ -85,6 +86,7 @@ void arch_setup_new_exec(void);
>  
>  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
>  #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
> +#define _TIF_NEED_RESCHED_LAZY	(1 << TIF_NEED_RESCHED_LAZY)
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
>  #define _TIF_FOREIGN_FPSTATE	(1 << TIF_FOREIGN_FPSTATE)
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
> @@ -100,10 +102,10 @@ void arch_setup_new_exec(void);
>  #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
>  #define _TIF_TSC_SIGSEGV	(1 << TIF_TSC_SIGSEGV)
>  
> -#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
> +#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \
>  				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
>  				 _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
> -				 _TIF_NOTIFY_SIGNAL)
> +				 _TIF_NOTIFY_SIGNAL | _TIF_SIGPENDING)
>  
>  #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
>  				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index b260ddc4d3e9a..7993fab0cab4c 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -132,7 +132,7 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
>  	do {
>  		local_irq_enable();
>  
> -		if (thread_flags & _TIF_NEED_RESCHED)
> +		if (thread_flags & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY))
>  			schedule();
>  
>  		if (thread_flags & _TIF_UPROBE)
> -- 
> 2.43.0
> 


From gcherian at marvell.com  Wed Mar  5 04:15:28 2025
From: gcherian at marvell.com (George Cherian)
Date: Wed, 5 Mar 2025 12:15:28 +0000
Subject: [PATCH v4 0/2] Add stop_on_panic support for watchdog
In-Reply-To: <28d0ea70-db7a-40e7-aac9-86808320f252@pengutronix.de>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>
 <PH8PR18MB53817EC09B918852B78DF3AAC5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
 <28d0ea70-db7a-40e7-aac9-86808320f252@pengutronix.de>
Message-ID: <PH8PR18MB5381B857859C6413392DD007C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>

Hi Ahmad,

>Hi George,
>
>On 05.03.25 12:28, George Cherian wrote:
> Hi Ahmad,
>>> Hi George,
>>> On 05.03.25 11:10, George Cherian wrote:
>>>> This series adds a new kernel command line option to watchdog core to
>>>> stop the watchdog on panic. This is useul in certain systems which prevents
>>>> successful loading of kdump kernel due to watchdog reset.
>>>>
>>>> Some of the watchdog drivers stop function could sleep. For such
>>>> drivers the stop_on_panic is not valid as the notifier callback happens
>>>> in atomic context. Introduce WDIOF_STOP_MAYSLEEP flag to watchdog_info
>>>> options to indicate whether the stop function would sleep.
>>>
>>> Did you consider having a reset_on_panic instead, which sets a user-specified
>>> timeout on panic? This would make the mechanism useful also for watchdogs
>> 
>> /proc/sys/kernel/panic already provides that support. You may echo a non-zero value 
>> and the system tries for a soft reboot after those many seconds. But this doesn't happen 
>> in case of a kdump kernel load after panic.
>
>The timeout specified to the Watchdog reset_on_panic option would be programmed into
>the active watchdogs and not be used to trigger a software-induced reboot. 
Yes.
>
>>> that can't be disabled and would protect against system lock up: 
>>> Consider a memory-corruption bug (perhaps externally via DMA), which partially
>>> overwrites both main and kdump kernel. With a disabled watchdog, the system
>>> may not be able to recover on its own.
>> 
>> Yes, that is the reason why the kernel command-line is optional and by default it is set to zero.
>> So that in cases if you have a corrupted kdump kernel then watchdog kicks in.
>
>The existing option isn't enough for the kdump kernel use case.
>If we (i.e. you) are going to do something about it, wouldn't it be
>better to have a solution that's applicable to a wider number of
>watchdog devices?

I need a slight clarification here. 
1. reset_on_panic takes the number of seconds to be reloaded to watchdog HW, so that it initiates a 
watchdog reset after the specified timeout, if kdump kernel fails to boot or hung while booting.
2. in case reset_on_panic = 0 then it behaves like stop_on_panic=1.
Is this what you meant?

I would let Guenter comment on this approach.
>>> If you did consider it, what made you decide against it?
>> watchdog.stop_on_panic=1 is specifically for systems which can't boot a kdump kernel due to the fact 
>> that the kdump kernel gets a watchdog reset while booting, may be due to a shorter watchdog time.
>> For eg: a 32-bit watchdog down counter running at 1GHz.
>> reset_on_panic can guarantee only the largest watchdog timeout supported by HW, 
>> since there is no one to ping the watchdog.

>If you are serious with the watchdog use, you'll want to use the watchdog to
>monitor kernel startup as well. If the bootloader can set a watchdog timeout
>just before starting the kernel and it doesn't expire before the kernel watchdog
>driver takes over, why can't we do the same just before starting the dumpkernel?

Yes, in an ideal world with ideal HW. But there are HW with issues which cannot have large
enough Watchdog time. Such HW would boot from FW to kernel without watchdog enabled.
And stop_on_panic does the similar for kdump kernel too.

-George
>
>Thanks,
>Ahmad
>
> 
>>
>> Thanks,
>> Ahmad
>>
>>>
>>>
>> Changelog:
>> v1 -> v2
>> - Remove the per driver flag setting option
>> - Take the parameter via kernel command-line parameter to watchdog_core.
>>
>> v2 -> v3
>> - Remove the helper function watchdog_stop_on_panic() from watchdog.h.
>> - There are no users for this. 
>>
>> v3 -> v4
>> - Since the panic notifier is in atomic context, watchdog functions
>>   which sleep can't be called. 
>> - Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
>>   function sleeps.
>> - Simplify the stop_on_panic kernel command line parsing.
>> - Enable the panic notiffier only if the watchdog stop function doesn't
>>   sleep
>>
>> George Cherian (2):
>>   watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
>>   drivers: watchdog: Add support for panic notifier callback
> 
> - George


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | https://urldefense.proofpoint.com/v2/url?u=http-3A__www.pengutronix.de_&d=DwICaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=npgTSgHrUSLmXpBZJKVhk0lE_XNvtVDl8ZA2zBvBqPw&m=Df3J3ZRga7XxcgUdJOqYVMJ-ALX5jC3eiII4YhsAdC5pYhr1xwcqbzhIy6MCEqws&s=ybglw-WK4VGE8gHGNwMrC1_VliOv72pjDLEIm9FF_dE&e=  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

From a.fatoum at pengutronix.de  Wed Mar  5 04:23:46 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 5 Mar 2025 13:23:46 +0100
Subject: [PATCH v4 0/2] Add stop_on_panic support for watchdog
In-Reply-To: <PH8PR18MB5381B857859C6413392DD007C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <43fb0965-04b7-41dc-ae3f-54676eefdbb5@pengutronix.de>
 <PH8PR18MB53817EC09B918852B78DF3AAC5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
 <28d0ea70-db7a-40e7-aac9-86808320f252@pengutronix.de>
 <PH8PR18MB5381B857859C6413392DD007C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
Message-ID: <f6eccbe2-b0cd-4f9e-99e0-82003a00fe5e@pengutronix.de>

Hello George,

On 05.03.25 13:15, George Cherian wrote:
>> On 05.03.25 12:28, George Cherian wrote:
>>>> that can't be disabled and would protect against system lock up: 
>>>> Consider a memory-corruption bug (perhaps externally via DMA), which partially
>>>> overwrites both main and kdump kernel. With a disabled watchdog, the system
>>>> may not be able to recover on its own.
>>>
>>> Yes, that is the reason why the kernel command-line is optional and by default it is set to zero.
>>> So that in cases if you have a corrupted kdump kernel then watchdog kicks in.
>>
>> The existing option isn't enough for the kdump kernel use case.
>> If we (i.e. you) are going to do something about it, wouldn't it be
>> better to have a solution that's applicable to a wider number of
>> watchdog devices?
> 
> I need a slight clarification here. 
> 1. reset_on_panic takes the number of seconds to be reloaded to watchdog HW, so that it initiates a 
> watchdog reset after the specified timeout, if kdump kernel fails to boot or hung while booting.

Yes.

> 2. in case reset_on_panic = 0 then it behaves like stop_on_panic=1.
> Is this what you meant?

Alternatively, reset_on_panic = 0 could also mean stopping the watchdog as
you do now. I haven't thought though yet what would make the most sense.

> I would let Guenter comment on this approach.

+1.

>> If you are serious with the watchdog use, you'll want to use the watchdog to
>> monitor kernel startup as well. If the bootloader can set a watchdog timeout
>> just before starting the kernel and it doesn't expire before the kernel watchdog
>> driver takes over, why can't we do the same just before starting the dumpkernel?
> 
> Yes, in an ideal world with ideal HW. But there are HW with issues which cannot have large
> enough Watchdog time. Such HW would boot from FW to kernel without watchdog enabled.
> And stop_on_panic does the similar for kdump kernel too.

Yes, but there is likely more kinds of watchdog devices that can not be disabled,
so it makes sense to have a solution that is more broadly applicable from the get-go.

Cheers,
Ahmad

> 
> -George
>>
>> Thanks,
>> Ahmad
>>
>>
>>>
>>> Thanks,
>>> Ahmad
>>>
>>>>
>>>>
>>> Changelog:
>>> v1 -> v2
>>> - Remove the per driver flag setting option
>>> - Take the parameter via kernel command-line parameter to watchdog_core.
>>>
>>> v2 -> v3
>>> - Remove the helper function watchdog_stop_on_panic() from watchdog.h.
>>> - There are no users for this. 
>>>
>>> v3 -> v4
>>> - Since the panic notifier is in atomic context, watchdog functions
>>>   which sleep can't be called. 
>>> - Add an options flag WDIOF_STOP_MAYSLEEP to indicate whether stop
>>>   function sleeps.
>>> - Simplify the stop_on_panic kernel command line parsing.
>>> - Enable the panic notiffier only if the watchdog stop function doesn't
>>>   sleep
>>>
>>> George Cherian (2):
>>>   watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
>>>   drivers: watchdog: Add support for panic notifier callback
>>
>> - George
> 
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 04:33:55 2025
From: faizal.abdul.rahim at linux.intel.com (Abdul Rahim, Faizal)
Date: Wed, 5 Mar 2025 20:33:55 +0800
Subject: [PATCH iwl-next v7 5/9] igc: Add support for frame preemption
 verification
In-Reply-To: <20250304152644.y7j7eshr4qxhmxq2@skbuf>
References: <20250303102658.3580232-1-faizal.abdul.rahim@linux.intel.com>
 <20250303102658.3580232-6-faizal.abdul.rahim@linux.intel.com>
 <20250304152644.y7j7eshr4qxhmxq2@skbuf>
Message-ID: <4882bd5b-1a64-4ac7-ba51-66143d029e8a@linux.intel.com>



On 4/3/2025 11:26 pm, Vladimir Oltean wrote:
> On Mon, Mar 03, 2025 at 05:26:54AM -0500, Faizal Rahim wrote:
>> +static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
>> +						 unsigned int size)
>> +{
>> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
>> +	int smd;
>> +
>> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
>> +
>> +	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
>> +		size == SMD_FRAME_SIZE;
>> +}
> 
> The NIC should explicitly not respond to frames which have an SMD-V but
> are not "verify" mPackets (7 octets of 0x55 + 1 octet SMD-V + 60 octets
> of 0x00 + mCRC - as per 802.3 definitions). Similarly, it should only
> treat SMD-R frames which contain 7 octets of 0x55 + 1 octet SMD-R + 60
> octets of 0x00 + mCRC as "respond" mPackets, and only advance its
> verification state machine based on those.
> 
> Specifically, it doesn't look like you are ensuring the packet payload
> contains 60 octets of zeroes. Is this something that the hardware
> already does for you, or is it something that needs further validation
> and differentiation in software?

The hardware doesn?t handle this, so the igc driver have to do it manually. 
I missed this handling, and Chwee Lin also noticed the issue while testing 
this patch series?it wasn?t rejecting SMD-V and SMD-R with a non-zero 
payload. I?ll update this patch to include the fix that Chwee Lin 
implemented and tested. Thanks.


From iuliana.prodan at oss.nxp.com  Wed Mar  5 04:39:23 2025
From: iuliana.prodan at oss.nxp.com (Iuliana Prodan (OSS))
Date: Wed,  5 Mar 2025 14:39:23 +0200
Subject: [PATCH] remoteproc: imx_dsp_rproc: conditionally wait for FW_READY
Message-ID: <20250305123923.514386-1-iuliana.prodan@oss.nxp.com>

From: Iuliana Prodan <iuliana.prodan at nxp.com>

Some DSP firmware requires a FW_READY signal before proceeding,
while others do not.
Introduce imx_dsp_rproc_wait_fw_ready() to check the resource table
and determine if waiting is needed.

Use the WAIT_FW_READY flag (bit 1) to distinguish cases where
waiting is required, as bit 0 is reserved for VIRTIO_RPMSG_F_NS
in OpenAMP and mentioned in rpmsg documentation (not used in Linux,
so far).
This flag is set by the remote processor in the dfeatures member of
struct fw_rsc_vdev, indicating supported virtio device features.

Update imx_dsp_rproc_start() to handle this condition accordingly.

Signed-off-by: Iuliana Prodan <iuliana.prodan at nxp.com>
---
 drivers/remoteproc/imx_dsp_rproc.c | 84 +++++++++++++++++++++++++++---
 1 file changed, 77 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index b9bb15970966..8eefaee28061 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright 2021 NXP */
+/* Copyright 2021, 2025 NXP */
 
 #include <dt-bindings/firmware/imx/rsrc.h>
 #include <linux/arm-smccc.h>
@@ -38,6 +38,15 @@ MODULE_PARM_DESC(no_mailboxes,
 #define REMOTE_IS_READY				BIT(0)
 #define REMOTE_READY_WAIT_MAX_RETRIES		500
 
+/*
+ * This flag is set by the remote processor in the dfeatures member of
+ * struct fw_rsc_vdev, indicating supported virtio device features
+ *
+ * Use bit 1 since bit 0 is used for VIRTIO_RPMSG_F_NS
+ * in OpenAMP and mentioned in kernel's rpmsg documentation
+ */
+#define WAIT_FW_READY				BIT(1)
+
 /* att flags */
 /* DSP own area */
 #define ATT_OWN					BIT(31)
@@ -300,13 +309,74 @@ static int imx_dsp_rproc_ready(struct rproc *rproc)
 	return -ETIMEDOUT;
 }
 
+/*
+ * Determines whether we should wait for a FW_READY reply
+ * from the remote processor.
+ *
+ * This function inspects the resource table associated with the remote
+ * processor to check if the firmware has indicated that waiting
+ * for a FW_READY signal is necessary.
+ * By default, wait for FW_READY unless an RSC_VDEV explicitly
+ * indicates otherwise.
+ *
+ * Return:
+ *   - true: If we should wait for FW READY
+ *   - false: If FW_READY wait is not required
+ */
+static bool imx_dsp_rproc_wait_fw_ready(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct fw_rsc_hdr *hdr;
+	struct fw_rsc_vdev *rsc;
+	int i, offset, avail;
+
+	/*
+	 * If there is no resource table, wait for FW_READY
+	 * unless no_mailboxes module param is used
+	 */
+	if (!rproc->table_ptr)
+		return true;
+
+	/* Iterate over each resource entry in the resource table */
+	for (i = 0; i < rproc->table_ptr->num; i++) {
+		offset = rproc->table_ptr->offset[i];
+		hdr = (void *)rproc->table_ptr + offset;
+		avail = rproc->table_sz - offset - sizeof(*hdr);
+
+		/* Ensure the resource table is not truncated */
+		if (avail < 0) {
+			dev_err(dev, "Resource table is truncated\n");
+			return true;
+		}
+
+		/* Check if the resource type is a virtio device */
+		if (hdr->type == RSC_VDEV) {
+			rsc = (struct fw_rsc_vdev *)((void *)hdr + sizeof(*hdr));
+
+			/* vdev does not require waiting for FW_READY */
+			return !!(rsc->dfeatures & WAIT_FW_READY);
+		}
+	}
+
+	/*
+	 * By default, wait for the FW_READY
+	 * unless a vdev entry disables it
+	 */
+	return true;
+}
+
 /*
  * Start function for rproc_ops
  *
- * There is a handshake for start procedure: when DSP starts, it
- * will send a doorbell message to this driver, then the
- * REMOTE_IS_READY flags is set, then driver will kick
- * a message to DSP.
+ * The start procedure involves a handshake: when the DSP starts, it
+ * sends a doorbell message to this driver, which sets the
+ * REMOTE_IS_READY flag. The driver then sends a message to the DSP.
+ *
+ * Before proceeding, the driver checks if it needs to wait for a
+ * firmware ready reply using imx_dsp_rproc_wait_fw_ready().
+ * If waiting is required, it calls imx_dsp_rproc_ready() to complete
+ * the initialization.
+ * If waiting is not required, the start function returns.
  */
 static int imx_dsp_rproc_start(struct rproc *rproc)
 {
@@ -335,8 +405,8 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
 
 	if (ret)
 		dev_err(dev, "Failed to enable remote core!\n");
-	else
-		ret = imx_dsp_rproc_ready(rproc);
+	else if (imx_dsp_rproc_wait_fw_ready(rproc))
+		return imx_dsp_rproc_ready(rproc);
 
 	return ret;
 }
-- 
2.25.1



From tglx at linutronix.de  Wed Mar  5 04:48:30 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Wed, 05 Mar 2025 13:48:30 +0100
Subject: [PATCH 1/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <20250305104925.189198-2-vschneid@redhat.com>
References: <20250305104925.189198-1-vschneid@redhat.com>
 <20250305104925.189198-2-vschneid@redhat.com>
Message-ID: <87cyev63tt.ffs@tglx>

On Wed, Mar 05 2025 at 11:49, Valentin Schneider wrote:
> From: Mark Rutland <mark.rutland at arm.com>
>
> For an architecture to enable CONFIG_ARCH_HAS_RESCHED_LAZY, two things are
> required:
> 1) Adding a TIF_NEED_RESCHED_LAZY flag definition
> 2) Checking for TIF_NEED_RESCHED_LAZY in the appropriate locations
>
> 2) is handled in a generic manner by CONFIG_GENERIC_ENTRY, which isn't
> (yet) implemented for arm64. However, outside of core scheduler code,
> TIF_NEED_RESCHED_LAZY only needs to be checked on a kernel exit, meaning:
> o return/entry to userspace.
> o return/entry to guest.
>
> The return/entry to a guest is all handled by xfer_to_guest_mode_handle_work()
> which already does the right thing, so it can be left as-is.
>
> arm64 doesn't use common entry's exit_to_user_mode_prepare(), so update its
> return to user path to check for TIF_NEED_RESCHED_LAZY and call into
> schedule() accordingly.
>
> Link: https://lore.kernel.org/linux-rt-users/20241216190451.1c61977c at mordecai.tesarici.cz/
> Link: https://lore.kernel.org/all/xhsmh4j0fl0p3.mognet at vschneid-thinkpadt14sgen2i.remote.csb/
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> [testdrive, _TIF_WORK_MASK fixlet and changelog.]
> Signed-off-by: Mike Galbraith <efault at gmx.de>
> [Another round of testing; changelog faff]
> Signed-off-by: Valentin Schneider <vschneid at redhat.com>

Reviewed-by: Thomas Gleixner <tglx at linutronix.de>


From quic_vikramsa at quicinc.com  Wed Mar  5 04:45:11 2025
From: quic_vikramsa at quicinc.com (Vikram Sharma)
Date: Wed, 5 Mar 2025 18:15:11 +0530
Subject: [PATCH v14 2/2] arm64: dts: qcom:
 qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
In-Reply-To: <f5c2044e-e78e-4839-9c29-63610ff406e2@linaro.org>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
 <20250208225143.2868279-3-quic_vikramsa@quicinc.com>
 <ca8e6569-b466-4f83-83af-38c51891d395@kernel.org> <Z8a7cMmxJuHIhgjo@trex>
 <baae2a56-5299-486f-acf1-14fe13fd2f81@kernel.org> <Z8a/Dk7zjZ7RQT2/@trex>
 <f5c2044e-e78e-4839-9c29-63610ff406e2@linaro.org>
Message-ID: <b3203de4-e888-41e2-80bd-0d60fb8c520e@quicinc.com>


On 3/4/2025 3:17 PM, Bryan O'Donoghue wrote:
> On 04/03/2025 08:51, Jorge Ramirez wrote:
>> On 04/03/25 09:40:21, Krzysztof Kozlowski wrote:
>>> On 04/03/2025 09:36, Jorge Ramirez wrote:
>>>> On 03/03/25 18:13:20, Krzysztof Kozlowski wrote:
>>>>> On 08/02/2025 23:51, Vikram Sharma wrote:
>>>>>> The Vision Mezzanine for the Qualcomm RB3 Gen 2 ships with an imx577
>>>>>> camera sensor. Enable IMX577 on the vision mezzanine.
>>>>>>
>>>>>> An example media-ctl pipeline for the imx577 is:
>>>>>>
>>>>>> media-ctl --reset
>>>>>> media-ctl -V '"imx577 '17-001a'":0[fmt:SRGGB10/4056x3040 
>>>>>> field:none]'
>>>>>
>>>>> AFAIU, camss does not support SRGGB10, but only SRGGB10P.
>>>>>
>>>>> Based on tests reported on IRC I think this might not have been 
>>>>> tested
>>>>> correctly.
Hi everyone,

Thank you for your comments and discussion on this thread.
I can confirm that I have verified this implementation using the same 
steps mentioned in the commit text.

Here is the sample output.

yavta -B capture-mplane -c -I -n 5 -f SRGGB10P -s 4056x3040 -F /dev/video0
Device /dev/video0 opened.
Device `Qualcomm Camera Subsystem' on `platform:acb3000.isp' (driver 
'qcom-camss') supports video, capture, with mplanes.
Video format set: SRGGB10P (41415270) 4056x3040 field none, 1 planes:
 ?* Stride 5072, buffer size 15418880
Video format: SRGGB10P (41415270) 4056x3040 field none, 1 planes:
 ?* Stride 5072, buffer size 15418880
5 buffers requested.
length: 1 offset: 3791353960 timestamp type/source: mono/EoF
Buffer 0/0 mapped at address 0xffff7eb7b000.
length: 1 offset: 3791353960 timestamp type/source: mono/EoF
Buffer 1/0 mapped at address 0xffff7dcc6000.
length: 1 offset: 3791353960 timestamp type/source: mono/EoF
Buffer 2/0 mapped at address 0xffff7ce11000.
length: 1 offset: 3791353960 timestamp type/source: mono/EoF
Buffer 3/0 mapped at address 0xffff7bf5c000.
length: 1 offset: 3791353960 timestamp type/source: mono/EoF
Buffer 4/0 mapped at address 0xffff7b0a7000.
0 (0) [-] none 0 15418880 B 114.742722 114.744108 20.839 fps ts mono/EoF
1 (1) [-] none 1 15418880 B 114.775069 114.775932 30.915 fps ts mono/EoF
2 (2) [-] none 2 15418880 B 114.808401 114.886861 30.001 fps ts mono/EoF
3 (3) [-] none 3 15418880 B 114.841923 114.899629 29.831 fps ts mono/EoF
4 (4) [-] none 4 15418880 B 114.875247 114.949205 30.008 fps ts mono/EoF
5 (0) [-] none 5 15418880 B 114.908511 114.963073 30.063 fps ts mono/EoF
6 (1) [-] none 6 15418880 B 114.941727 114.997570 30.106 fps ts mono/EoF
7 (2) [-] none 7 15418880 B 114.975066 115.011758 29.995 fps ts mono/EoF
8 (3) [-] none 8 15418880 B 115.008486 115.047468 29.922 fps ts mono/EoF
9 (4) [-] none 9 15418880 B 115.041750 115.060305 30.063 fps ts mono/EoF
10 (0) [-] none 10 15418880 B 115.075060 115.106941 30.021 fps ts mono/EoF
...

Best Regards,
Vikram

>>>>
>>>> I acquired SRGGB10P (10 bit packed) frames from the camera despite the
>>>> pipeline being set to SRGGB10 (16 bit) samples.
>>>>
>>>> so something does not add up.
>>>
>>> Then the commands are actually correct, just the camss or media behave
>>> here a bit unexpected?
>>>
>>
>> setting the pipeline (CSI) as SRGGB10 (16 bit samples) as per below
>>
>> media-ctl --reset
>> media-ctl -v -V '"imx577 '19-001a'":0[fmt:SRGGB10/4056x3040 field:none]'
>> media-ctl -V '"msm_csiphy3":0[fmt:SRGGB10/4056x3040]'
>> media-ctl -V '"msm_csid0":0[fmt:SRGGB10/4056x3040]'
>> media-ctl -V '"msm_vfe0_rdi0":0[fmt:SRGGB10/4056x3040]'
>> media-ctl -l '"msm_csiphy3":1->"msm_csid0":0[1]'
>> media-ctl -l '"msm_csid0":1->"msm_vfe0_rdi0":0[1]'
>>
>> allows to capture SRGGB10P samples (frames-xxxx.bin files contain 10 
>> bit samples for the size)
>>
>> ? ==> yavta -B capture-mplane -c -I -n 5 -f SRGGB10P -s 4056x3040 -F 
>> /dev/video0
>>
>>
>> shouldnt the CSI need to be set to SRGGB10P instead?
>>
>>
>>> Best regards,
>>> Krzysztof
>>
>
> No an internal media bus format MEDIA_BUS_FMT_THING is used
>
> See
>
> 87889f1b7ea40d2544b49c62092e6ef2792dced7
> 5480b0c67f120a6c293cc5eff72fa1d6a74de504
> 3c1dfb5a69cf836f513a2a49113ee946a4b9d95d
>
> Yavta is specifying a v4l2 pixel format SRGGB10P which then gets 
> translated into a media bus format MEDIA_BUS_FMT_SRGGB10_1X10.
>
> I'm not sure what the historical reasons for that are, probably good 
> ones.
>
> ---
> bod



From daniel.baluta at gmail.com  Wed Mar  5 04:47:45 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Wed, 5 Mar 2025 14:47:45 +0200
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml schema
In-Reply-To: <Z8cp1xoIXT8lgD8T@lizhi-Precision-Tower-5810>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com> <Z8cp1xoIXT8lgD8T@lizhi-Precision-Tower-5810>
Message-ID: <CAEnQRZCT4vfFBApv+C3Wp17Fk0-Rwx36h4eCTTygaXFYFipEGg@mail.gmail.com>

Hello Frank, Conor, Krzysztof,

Thanks a lot for your comments and help.

In this initial patchseries we only add minimal OF support and
introduce a minimal binding.

> How did you pickup the maintainer entry?

We got the author of the first commit for
See 0d8400c5a2ce ("hwmon: (emc2305) add support for EMC2301/2/3/5 RPM-based")

> If only one reg You can go through trivial-devices.yaml

This is not a trivial device as we will add some specific properties
with our next patches
(e.g polarity etc)

> Missing descriptions of the fans, no?
> missing $ref to fan-controller schema.

Do we need to add this now? As this is only the minimal binding
support. We want to add that
in a follow up patch when we go into specifics.

> The emc2301 label here can be dropped, it is not used.

Will fix.

> The nodename should be "fan-controller", not pwm here I guess.

Sure, will fix.

On Tue, Mar 4, 2025 at 6:56?PM Frank Li <Frank.li at nxp.com> wrote:
>
> On Tue, Mar 04, 2025 at 06:21:34PM +0200, florin.leotescu at oss.nxp.com wrote:
> > From: Florin Leotescu <florin.leotescu at nxp.com>
> >
> > Introduce yaml schema for Microchip emc2305 pwm fan controller.
> >
> > Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> > ---
> >  .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
> >  1 file changed, 43 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > new file mode 100644
> > index 000000000000..cac0075a65bb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > @@ -0,0 +1,43 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Microchip EMC2305 SMBus compliant PWM fan controller
> > +
> > +maintainers:
> > +  - Michael Shych <michaelsh at nvidia.com>
>
> who is it? look like not Microchip and hwmon maintainer.
>
> > +
> > +description: |
>
> Needn't |
>
> > +  Microchip EMC2301/2/3/5 pwm controller which supports up
> > +  to five programmable fan control circuits
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - microchip,emc2301
> > +      - microchip,emc2302
> > +      - microchip,emc2303
> > +      - microchip,emc2305
>
> According to your driver code look like all compatible with microchip,emc2301
>
> oneOf:
>   - enum:
>       - microchip,emc2301
>   - items:
>       - enum:
>           - microchip,emc2302
>           - microchip,emc2303
>           - microchip,emc2305
>       - const: microchip,emc2301
>
> So your driver just need one "microchip,emc2301" compatible string.
>
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    i2c {
> > +        #address-cells = <1>;
> > +        #size-cells = <0>;
> > +
> > +        emc2301: pwm at 2f {
> > +            compatible = "microchip,emc2301";
> > +            reg = <0x2f>;
>
> If only one reg:
> You can go through trivial-devices.yaml
>
> Frank
>
> > +        };
> > +    };
> > --
> > 2.34.1
> >
>


From kever.yang at rock-chips.com  Wed Mar  5 04:49:16 2025
From: kever.yang at rock-chips.com (Kever Yang)
Date: Wed, 5 Mar 2025 20:49:16 +0800
Subject: [PATCH] arm64: dts: rockchip: Enable ufshc on RK3576 evb1 board
In-Reply-To: <1741148307-137177-1-git-send-email-shawn.lin@rock-chips.com>
References: <1741148307-137177-1-git-send-email-shawn.lin@rock-chips.com>
Message-ID: <f96f7559-0b07-4c7f-a8e7-64dbfa58bee8@rock-chips.com>


On 2025/3/5 12:18, Shawn Lin wrote:
> RK3576 evb1 board supports UFS, so enable it.
>
> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> ---
>
>   arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
> index 782ca00..5412c60 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
> @@ -711,6 +711,10 @@
>   	status = "okay";
>   };
>   
> +&ufshc {
> +	status = "okay";
> +};

This node suppose to after the uart0.


Thanks,
- Kever
> +
>   &uart0 {
>   	status = "okay";
>   };


From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:23 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:23 -0500
Subject: [PATCH iwl-next v8 08/11] igc: add support to set tx-min-frag-size
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>

Add support to set tx-min-frag-size via set_mm callback in igc.
Increase the max limit of tx-ming-frag-size in ethtool from 252 to 256
since i225/6 value range is 64, 128, 192 and 256.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |  1 +
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  5 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 37 ++++++++++++++++++--
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  2 +-
 net/ethtool/mm.c                             |  2 +-
 6 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index d9ecb7cf80c9..4dfd133b4d6f 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *);
 
 struct igc_fpe_t {
 	struct ethtool_mmsv mmsv;
+	u32 tx_min_frag_size;
 };
 
 enum igc_mac_filter_type {
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 22db1de02964..038ee89f1e08 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -551,6 +551,7 @@
 #define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
+#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000
 
 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
 #define IGC_TXQCTL_STRICT_CYCLE		0x00000002
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index b64d5c6c1d20..529654ccd83f 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_fpe_t *fpe = &adapter->fpe;
 
+	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
+	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");
+
 	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
 		if (cmd->pmac_enabled)
 			static_branch_inc(&igc_fpe_enabled);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 0a2c747fde2d..2ec5909bf8b0 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -6,6 +6,12 @@
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+#define MIN_MULTPLIER_TX_MIN_FRAG	0
+#define MAX_MULTPLIER_TX_MIN_FRAG	3
+/* Frag size is based on the Section 8.12.2 of the SW User Manual */
+#define TX_MIN_FRAG_SIZE		64
+#define TX_MAX_FRAG_SIZE	(TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1))
+
 DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 static int igc_fpe_init_smd_frame(struct igc_ring *ring,
@@ -128,6 +134,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = {
 
 void igc_fpe_init(struct igc_adapter *adapter)
 {
+	adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
 	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
 }
 
@@ -278,7 +285,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
 		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
-		      IGC_TQAVCTRL_PREEMPT_ENA);
+		      IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -324,12 +331,34 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
 	wr32(IGC_RETX_CTL, retxctl);
 }
 
+static u8 igc_fpe_get_frag_size_mult(const struct igc_fpe_t *fpe)
+{
+	u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1;
+
+	return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG,
+		       MAX_MULTPLIER_TX_MIN_FRAG);
+}
+
+u32 igc_fpe_get_supported_frag_size(u32 frag_size)
+{
+	const u32 supported_sizes[] = {64, 128, 192, 256};
+
+	/* Find the smallest supported size that is >= frag_size */
+	for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) {
+		if (frag_size <= supported_sizes[i])
+			return supported_sizes[i];
+	}
+
+	return TX_MAX_FRAG_SIZE; /* Should not happen, value > 256 is blocked by ethtool */
+}
+
 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
 	u32 sec, nsec, cycle, rxpbs;
 	ktime_t base_time, systim;
+	u32 frag_size_mult;
 	int i;
 
 	wr32(IGC_TSAUXC, 0);
@@ -501,13 +530,15 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	}
 
 	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
-		   IGC_TQAVCTRL_PREEMPT_ENA);
-
+		   IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
 	if (adapter->fpe.mmsv.pmac_enabled)
 		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
 
+	frag_size_mult = igc_fpe_get_frag_size_mult(&adapter->fpe);
+	tqavctrl |= FIELD_PREP(IGC_TQAVCTRL_MIN_FRAG_MASK, frag_size_mult);
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index a2534228cc0e..975f4e38836e 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -14,7 +14,7 @@ enum igc_txd_popts_type {
 DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 void igc_fpe_init(struct igc_adapter *adapter);
-u32 igc_fpe_get_supported_frag_size(u32 user_frag_size);
+u32 igc_fpe_get_supported_frag_size(u32 frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index ad9b40034003..4c395cd949ab 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -153,7 +153,7 @@ const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1] = {
 	[ETHTOOL_A_MM_VERIFY_TIME]	= NLA_POLICY_RANGE(NLA_U32, 1, 128),
 	[ETHTOOL_A_MM_TX_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
 	[ETHTOOL_A_MM_PMAC_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
-	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 252),
+	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 256),
 };
 
 static void mm_state_to_cfg(const struct ethtool_mm_state *state,
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:24 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:24 -0500
Subject: [PATCH iwl-next v8 09/11] igc: block setting preemptible traffic class in taprio
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-10-faizal.abdul.rahim@linux.intel.com>

Since preemptible tc implementation is not ready yet, block it from being
set in taprio. The existing code already blocks it in mqprio.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index a9f40fffc4fd..6db926bc9d11 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6407,6 +6407,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 	if (!validate_schedule(adapter, qopt))
 		return -EINVAL;
 
+	/* preemptible isn't supported yet */
+	if (qopt->mqprio.preemptible_tcs)
+		return -EOPNOTSUPP;
+
 	igc_ptp_read(adapter, &now);
 
 	if (igc_tsn_is_taprio_activated_by_user(adapter) &&
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:25 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:25 -0500
Subject: [PATCH iwl-next v8 10/11] igc: add support to get MAC Merge data via ethtool
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-11-faizal.abdul.rahim@linux.intel.com>

Implement "ethtool --show-mm" callback for IGC.

Tested with command:
$ ethtool --show-mm enp1s0.
  MAC Merge layer state for enp1s0:
  pMAC enabled: on
  TX enabled: on
  TX active: on
  TX minimum fragment size: 64
  RX minimum fragment size: 60
  Verify enabled: on
  Verify time: 128
  Max verify time: 128
  Verification status: SUCCEEDED

Verified that the fields value are retrieved correctly.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 14 ++++++++++++++
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 529654ccd83f..fd4b4b332309 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1782,6 +1782,19 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_get_mm(struct net_device *netdev,
+			      struct ethtool_mm_state *cmd)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	ethtool_mmsv_get_mm(&fpe->mmsv, cmd);
+	cmd->tx_min_frag_size = fpe->tx_min_frag_size;
+	cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE;
+
+	return 0;
+}
+
 static int igc_ethtool_set_mm(struct net_device *netdev,
 			      struct ethtool_mm_cfg *cmd,
 			      struct netlink_ext_ack *extack)
@@ -2101,6 +2114,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 975f4e38836e..2b885f98e720 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,6 +4,7 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define IGC_RX_MIN_FRAG_SIZE		60
 #define SMD_FRAME_SIZE			60
 
 enum igc_txd_popts_type {
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:26 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:26 -0500
Subject: [PATCH iwl-next v8 11/11] igc: add support to get frame preemption statistics via ethtool
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>

Implemented "ethtool --include-statistics --show-mm" callback for IGC.

Tested preemption scenario to check preemption statistics:
1) Trigger verification handshake on both boards:
    $ sudo ethtool --set-mm enp1s0 pmac-enabled on
    $ sudo ethtool --set-mm enp1s0 tx-enabled on
    $ sudo ethtool --set-mm enp1s0 verify-enabled on
2) Set preemptible or express queue in taprio for tx board:
    $ sudo tc qdisc replace dev enp1s0 parent root handle 100 taprio \
      num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
      queues 1 at 0 1 at 1 1 at 2 1 at 3 base-time 0 sched-entry S F 100000 \
      fp E E P P
3) Send large size packets on preemptible queue
4) Send small size packets on express queue to preempt packets in
   preemptible queue
5) Show preemption statistics on the receiving board:
   $ ethtool --include-statistics --show-mm enp1s0
     MAC Merge layer state for enp1s0:
     pMAC enabled: on
     TX enabled: on
     TX active: on
     TX minimum fragment size: 64
     RX minimum fragment size: 60
     Verify enabled: on
     Verify time: 128
     Max verify time: 128
     Verification status: SUCCEEDED
     Statistics:
      MACMergeFrameAssErrorCount: 0
      MACMergeFrameSmdErrorCount: 0
      MACMergeFrameAssOkCount: 511
      MACMergeFragCountRx: 764
      MACMergeFragCountTx: 0
      MACMergeHoldCount: 0

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 39 ++++++++++++++++++++
 drivers/net/ethernet/intel/igc/igc_regs.h    | 16 ++++++++
 2 files changed, 55 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index fd4b4b332309..1ed08a3fa78b 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1819,6 +1819,44 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	return igc_tsn_offload_apply(adapter);
 }
 
+/**
+ * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
+ * @reg_value: Register value for IGC_PRMEXCPRCNT
+ * Return: The count of frame assembly errors.
+ */
+static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
+{
+	u32 ooo_frame_cnt, ooo_frag_cnt; /* Out of order statistics */
+	u32 miss_frame_frag_cnt;
+
+	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
+	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
+	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
+
+	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
+}
+
+static u64 igc_ethtool_get_frame_smd_error(u32 reg_value)
+{
+	return FIELD_GET(IGC_PRMEXCPRCNT_OOO_SMDC, reg_value);
+}
+
+static void igc_ethtool_get_mm_stats(struct net_device *dev,
+				     struct ethtool_mm_stats *stats)
+{
+	struct igc_adapter *adapter = netdev_priv(dev);
+	struct igc_hw *hw = &adapter->hw;
+	u32 reg_value;
+
+	reg_value = rd32(IGC_PRMEXCPRCNT);
+
+	stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(reg_value);
+	stats->MACMergeFrameSmdErrorCount = igc_ethtool_get_frame_smd_error(reg_value);
+	stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT);
+	stats->MACMergeFragCountRx = rd32(IGC_PRMEVNTRCNT);
+	stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2116,6 +2154,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.self_test		= igc_ethtool_diag_test,
 	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
+	.get_mm_stats		= igc_ethtool_get_mm_stats,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index 12ddc5793651..f343c6bfc6be 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -222,6 +222,22 @@
 
 #define IGC_FTQF(_n)	(0x059E0 + (4 * (_n)))  /* 5-tuple Queue Fltr */
 
+/* Time sync registers - preemption statistics */
+#define IGC_PRMPTDRCNT		0x04284	/* Good RX Preempted Packets */
+#define IGC_PRMEVNTTCNT		0x04298	/* TX Preemption event counter */
+#define IGC_PRMEVNTRCNT		0x0429C	/* RX Preemption event counter */
+
+ /* Preemption Exception Counter */
+ #define IGC_PRMEXCPRCNT				0x42A0
+/* Received out of order packets with SMD-C */
+#define IGC_PRMEXCPRCNT_OOO_SMDC			0x000000FF
+/* Received out of order packets with SMD-C and wrong Frame CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAME_CNT			0x0000FF00
+/* Received out of order packets with SMD-C and wrong Frag CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAG_CNT			0x00FF0000
+/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
+#define IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
+
 /* Transmit Scheduling Registers */
 #define IGC_TQAVCTRL		0x3570
 #define IGC_TXQCTL(_n)		(0x3344 + 0x4 * (_n))
-- 
2.34.1



From jens.wiklander at linaro.org  Wed Mar  5 05:04:06 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:06 +0100
Subject: [PATCH v6 00/10] TEE subsystem for restricted dma-buf allocations
Message-ID: <20250305130634.1850178-1-jens.wiklander@linaro.org>

Hi,

This patch set allocates the restricted DMA-bufs from a DMA-heap
instantiated from the TEE subsystem.

The TEE subsystem handles the DMA-buf allocations since it is the TEE
(OP-TEE, AMD-TEE, TS-TEE, or perhaps a future QTEE) which sets up the
restrictions for the memory used for the DMA-bufs.

The DMA-heap uses a restricted memory pool provided by the backend TEE
driver, allowing it to choose how to allocate the restricted physical
memory.

The allocated DMA-bufs must be imported with a new TEE_IOC_SHM_REGISTER_FD
before they can be passed as arguments when requesting services from the
secure world.

Three use-cases (Secure Video Playback, Trusted UI, and Secure Video
Recording) has been identified so far to serve as examples of what can be
expected. The use-cases has predefined DMA-heap names,
"restricted,secure-video", "restricted,trusted-ui", and
"restricted,secure-video-record". The backend driver registers restricted
memory pools for the use-cases it supports.

Each use-case has it's own restricted memory pool since different use-cases
requires isolation from different parts of the system. A restricted memory
pool can be based on a static carveout instantiated while probing the TEE
backend driver, or dynamically allocated from CMA and made restricted as
needed by the TEE.

This can be tested on a RockPi 4B+ with the following steps:
repo init -u https://github.com/jenswi-linaro/manifest.git -m rockpi4.xml \
        -b prototype/sdp-v6
repo sync -j8
cd build
make toolchains -j$(nproc)
make all -j$(nproc)
# Copy ../out/rockpi4.img to an SD card and boot the RockPi from that
# Connect a monitor to the RockPi
# login and at the prompt:
gst-launch-1.0 videotestsrc ! \
        aesenc key=1f9423681beb9a79215820f6bda73d0f \
                iv=e9aa8e834d8d70b7e0d254ff670dd718 serialize-iv=true ! \
        aesdec key=1f9423681beb9a79215820f6bda73d0f ! \
        kmssink

The aesdec module has been hacked to use an OP-TEE TA to decrypt the stream
into restricted DMA-bufs which are consumed by the kmssink.

The primitive QEMU tests from previous patch set can be tested on RockPi
in the same way with:
xtest --sdp-basic

The primitive test are tested on QEMU with the following steps:
repo init -u https://github.com/jenswi-linaro/manifest.git -m qemu_v8.xml \
        -b prototype/sdp-v6
repo sync -j8
cd build
make toolchains -j$(nproc)
make SPMC_AT_EL=1 all -j$(nproc)
make SPMC_AT_EL=1 run-only
# login and at the prompt:
xtest --sdp-basic

The SPMC_AT_EL=1 parameter configures the build with FF-A and an SPMC at
S-EL1 inside OP-TEE. The parameter can be changed into SPMC_AT_EL=n to test
without FF-A using the original SMC ABI instead. Please remember to do
%rm -rf ../trusted-firmware-a/build/qemu
for TF-A to be rebuilt properly using the new configuration.

https://optee.readthedocs.io/en/latest/building/prerequisites.html
list dependencies needed to build the above.

The tests are pretty basic, mostly checking that a Trusted Application in
the secure world can access and manipulate the memory. There are also some
negative tests for out of bounds buffers etc.

Thanks,
Jens

Changes since V5:
* Removing "tee: add restricted memory allocation" and
  "tee: add TEE_IOC_RSTMEM_FD_INFO"
* Adding "tee: implement restricted DMA-heap",
  "tee: new ioctl to a register tee_shm from a dmabuf file descriptor",
  "tee: add tee_shm_alloc_cma_phys_mem()",
  "optee: pass parent device to tee_device_alloc()", and
  "tee: tee_device_alloc(): copy dma_mask from parent device"
* The two TEE driver OPs "rstmem_alloc()" and "rstmem_free()" are replaced
  with a struct tee_rstmem_pool abstraction.
* Replaced the the TEE_IOC_RSTMEM_ALLOC user space API with the DMA-heap API

Changes since V4:
* Adding the patch "tee: add TEE_IOC_RSTMEM_FD_INFO" needed by the
  GStreamer demo
* Removing the dummy CPU access and mmap functions from the dma_buf_ops
* Fixing a compile error in "optee: FF-A: dynamic restricted memory allocation"
  reported by kernel test robot <lkp at intel.com>

Changes since V3:
* Make the use_case and flags field in struct tee_shm u32's instead of
  u16's
* Add more description for TEE_IOC_RSTMEM_ALLOC in the header file
* Import namespace DMA_BUF in module tee, reported by lkp at intel.com
* Added a note in the commit message for "optee: account for direction
  while converting parameters" why it's needed
* Factor out dynamic restricted memory allocation from
  "optee: support restricted memory allocation" into two new commits
  "optee: FF-A: dynamic restricted memory allocation" and
  "optee: smc abi: dynamic restricted memory allocation"
* Guard CMA usage with #ifdef CONFIG_CMA, effectively disabling dynamic
  restricted memory allocate if CMA isn't configured

Changes since the V2 RFC:
* Based on v6.12
* Replaced the flags for SVP and Trusted UID memory with a u32 field with
  unique id for each use case
* Added dynamic allocation of restricted memory pools
* Added OP-TEE ABI both with and without FF-A for dynamic restricted memory
* Added support for FF-A with FFA_LEND

Changes since the V1 RFC:
* Based on v6.11
* Complete rewrite, replacing the restricted heap with TEE_IOC_RSTMEM_ALLOC

Changes since Olivier's post [2]:
* Based on Yong Wu's post [1] where much of dma-buf handling is done in
  the generic restricted heap
* Simplifications and cleanup
* New commit message for "dma-buf: heaps: add Linaro restricted dmabuf heap
  support"
* Replaced the word "secure" with "restricted" where applicable

Etienne Carriere (1):
  tee: new ioctl to a register tee_shm from a dmabuf file descriptor

Jens Wiklander (9):
  tee: tee_device_alloc(): copy dma_mask from parent device
  optee: pass parent device to tee_device_alloc()
  optee: account for direction while converting parameters
  optee: sync secure world ABI headers
  tee: implement restricted DMA-heap
  tee: add tee_shm_alloc_cma_phys_mem()
  optee: support restricted memory allocation
  optee: FF-A: dynamic restricted memory allocation
  optee: smc abi: dynamic restricted memory allocation

 drivers/tee/Makefile              |   1 +
 drivers/tee/optee/Makefile        |   1 +
 drivers/tee/optee/call.c          |  10 +-
 drivers/tee/optee/core.c          |   1 +
 drivers/tee/optee/ffa_abi.c       | 194 +++++++++++-
 drivers/tee/optee/optee_ffa.h     |  27 +-
 drivers/tee/optee/optee_msg.h     |  65 ++++-
 drivers/tee/optee/optee_private.h |  55 +++-
 drivers/tee/optee/optee_smc.h     |  71 ++++-
 drivers/tee/optee/rpc.c           |  31 +-
 drivers/tee/optee/rstmem.c        | 329 +++++++++++++++++++++
 drivers/tee/optee/smc_abi.c       | 190 ++++++++++--
 drivers/tee/tee_core.c            | 147 +++++++---
 drivers/tee/tee_heap.c            | 470 ++++++++++++++++++++++++++++++
 drivers/tee/tee_private.h         |   7 +
 drivers/tee/tee_shm.c             | 199 ++++++++++++-
 include/linux/tee_core.h          |  67 +++++
 include/linux/tee_drv.h           |  10 +
 include/uapi/linux/tee.h          |  29 ++
 19 files changed, 1781 insertions(+), 123 deletions(-)
 create mode 100644 drivers/tee/optee/rstmem.c
 create mode 100644 drivers/tee/tee_heap.c


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:08 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:08 +0100
Subject: [PATCH v6 02/10] optee: pass parent device to tee_device_alloc()
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-3-jens.wiklander@linaro.org>

During probing of the OP-TEE driver, pass the parent device to
tee_device_alloc() so the dma_mask of the new devices can be updated
accordingly.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/ffa_abi.c | 8 ++++----
 drivers/tee/optee/smc_abi.c | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index f3af5666bb11..4ca1d5161b82 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -914,16 +914,16 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
 	    (sec_caps & OPTEE_FFA_SEC_CAP_RPMB_PROBE))
 		optee->in_kernel_rpmb_routing = true;
 
-	teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
-				  optee);
+	teedev = tee_device_alloc(&optee_ffa_clnt_desc, &ffa_dev->dev,
+				  optee->pool, optee);
 	if (IS_ERR(teedev)) {
 		rc = PTR_ERR(teedev);
 		goto err_free_pool;
 	}
 	optee->teedev = teedev;
 
-	teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
-				  optee);
+	teedev = tee_device_alloc(&optee_ffa_supp_desc, &ffa_dev->dev,
+				  optee->pool, optee);
 	if (IS_ERR(teedev)) {
 		rc = PTR_ERR(teedev);
 		goto err_unreg_teedev;
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index f0c3ac1103bb..165fadd9abc9 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1691,14 +1691,14 @@ static int optee_probe(struct platform_device *pdev)
 	    (sec_caps & OPTEE_SMC_SEC_CAP_RPMB_PROBE))
 		optee->in_kernel_rpmb_routing = true;
 
-	teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
+	teedev = tee_device_alloc(&optee_clnt_desc, &pdev->dev, pool, optee);
 	if (IS_ERR(teedev)) {
 		rc = PTR_ERR(teedev);
 		goto err_free_optee;
 	}
 	optee->teedev = teedev;
 
-	teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
+	teedev = tee_device_alloc(&optee_supp_desc, &pdev->dev, pool, optee);
 	if (IS_ERR(teedev)) {
 		rc = PTR_ERR(teedev);
 		goto err_unreg_teedev;
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:07 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:07 +0100
Subject: [PATCH v6 01/10] tee: tee_device_alloc(): copy dma_mask from parent device
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-2-jens.wiklander@linaro.org>

If a parent device is supplied to tee_device_alloc(), copy the dma_mask
field into the new device. This avoids future warnings when mapping a
DMA-buf for the device.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/tee_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index d113679b1e2d..685afcaa3ea1 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -922,6 +922,8 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
 	teedev->dev.class = &tee_class;
 	teedev->dev.release = tee_release_device;
 	teedev->dev.parent = dev;
+	if (dev)
+		teedev->dev.dma_mask = dev->dma_mask;
 
 	teedev->dev.devt = MKDEV(MAJOR(tee_devt), teedev->id);
 
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:10 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:10 +0100
Subject: [PATCH v6 04/10] optee: sync secure world ABI headers
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-5-jens.wiklander@linaro.org>

Update the header files describing the secure world ABI, both with and
without FF-A. The ABI is extended to deal with restricted memory, but as
usual backward compatible.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/optee_ffa.h | 27 ++++++++++---
 drivers/tee/optee/optee_msg.h | 65 ++++++++++++++++++++++++++++++--
 drivers/tee/optee/optee_smc.h | 71 ++++++++++++++++++++++++++++++++++-
 3 files changed, 154 insertions(+), 9 deletions(-)

diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
index 257735ae5b56..7bd037200343 100644
--- a/drivers/tee/optee/optee_ffa.h
+++ b/drivers/tee/optee/optee_ffa.h
@@ -81,7 +81,7 @@
  *                   as the second MSG arg struct for
  *                   OPTEE_FFA_YIELDING_CALL_WITH_ARG.
  *        Bit[31:8]: Reserved (MBZ)
- * w5:	  Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below,
+ * w5:	  Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_*
  * w6:	  The maximum secure world notification number
  * w7:	  Not used (MBZ)
  */
@@ -94,6 +94,8 @@
 #define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF	BIT(1)
 /* OP-TEE supports probing for RPMB device if needed */
 #define OPTEE_FFA_SEC_CAP_RPMB_PROBE	BIT(2)
+/* OP-TEE supports Restricted Memory for secure data path */
+#define OPTEE_FFA_SEC_CAP_RSTMEM	BIT(3)
 
 #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
 
@@ -108,7 +110,7 @@
  *
  * Return register usage:
  * w3:    Error code, 0 on success
- * w4-w7: Note used (MBZ)
+ * w4-w7: Not used (MBZ)
  */
 #define OPTEE_FFA_UNREGISTER_SHM	OPTEE_FFA_BLOCKING_CALL(3)
 
@@ -119,16 +121,31 @@
  * Call register usage:
  * w3:    Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF
  * w4:	  Notification value to request bottom half processing, should be
- *	  less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE.
+ *	  less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE
  * w5-w7: Not used (MBZ)
  *
  * Return register usage:
  * w3:    Error code, 0 on success
- * w4-w7: Note used (MBZ)
+ * w4-w7: Not used (MBZ)
  */
 #define OPTEE_FFA_ENABLE_ASYNC_NOTIF	OPTEE_FFA_BLOCKING_CALL(5)
 
-#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64
+#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE	64
+
+/*
+ * Release Restricted memory
+ *
+ * Call register usage:
+ * w3:    Service ID, OPTEE_FFA_RECLAIM_RSTMEM
+ * w4:    Shared memory handle, lower bits
+ * w5:    Shared memory handle, higher bits
+ * w6-w7: Not used (MBZ)
+ *
+ * Return register usage:
+ * w3:    Error code, 0 on success
+ * w4-w7: Note used (MBZ)
+ */
+#define OPTEE_FFA_RELEASE_RSTMEM	OPTEE_FFA_BLOCKING_CALL(8)
 
 /*
  * Call with struct optee_msg_arg as argument in the supplied shared memory
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
index e8840a82b983..1b558526e7d9 100644
--- a/drivers/tee/optee/optee_msg.h
+++ b/drivers/tee/optee/optee_msg.h
@@ -133,13 +133,13 @@ struct optee_msg_param_rmem {
 };
 
 /**
- * struct optee_msg_param_fmem - ffa memory reference parameter
+ * struct optee_msg_param_fmem - FF-A memory reference parameter
  * @offs_lower:	   Lower bits of offset into shared memory reference
  * @offs_upper:	   Upper bits of offset into shared memory reference
  * @internal_offs: Internal offset into the first page of shared memory
  *		   reference
  * @size:	   Size of the buffer
- * @global_id:	   Global identifier of Shared memory
+ * @global_id:	   Global identifier of the shared memory
  */
 struct optee_msg_param_fmem {
 	u32 offs_low;
@@ -165,7 +165,7 @@ struct optee_msg_param_value {
  * @attr:	attributes
  * @tmem:	parameter by temporary memory reference
  * @rmem:	parameter by registered memory reference
- * @fmem:	parameter by ffa registered memory reference
+ * @fmem:	parameter by FF-A registered memory reference
  * @value:	parameter by opaque value
  * @octets:	parameter by octet string
  *
@@ -296,6 +296,18 @@ struct optee_msg_arg {
  */
 #define OPTEE_MSG_FUNCID_GET_OS_REVISION	0x0001
 
+/*
+ * Values used in OPTEE_MSG_CMD_LEND_RSTMEM below
+ * OPTEE_MSG_RSTMEM_RESERVED		Reserved
+ * OPTEE_MSG_RSTMEM_SECURE_VIDEO_PLAY	Secure Video Playback
+ * OPTEE_MSG_RSTMEM_TRUSTED_UI		Trused UI
+ * OPTEE_MSG_RSTMEM_SECURE_VIDEO_RECORD	Secure Video Recording
+ */
+#define OPTEE_MSG_RSTMEM_RESERVED		0
+#define OPTEE_MSG_RSTMEM_SECURE_VIDEO_PLAY	1
+#define OPTEE_MSG_RSTMEM_TRUSTED_UI		2
+#define OPTEE_MSG_RSTMEM_SECURE_VIDEO_RECORD	3
+
 /*
  * Do a secure call with struct optee_msg_arg as argument
  * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
@@ -337,6 +349,49 @@ struct optee_msg_arg {
  * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is
  * normal world unable to process asynchronous notifications. Typically
  * used when the driver is shut down.
+ *
+ * OPTEE_MSG_CMD_LEND_RSTMEM lends restricted memory. The passed normal
+ * physical memory is restricted from normal world access. The memory
+ * should be unmapped prior to this call since it becomes inaccessible
+ * during the request.
+ * Parameters are passed as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
+ * [in] param[0].u.value.a		OPTEE_MSG_RSTMEM_* defined above
+ * [in] param[1].attr			OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+ * [in] param[1].u.tmem.buf_ptr		physical address
+ * [in] param[1].u.tmem.size		size
+ * [in] param[1].u.tmem.shm_ref		holds restricted memory reference
+ *
+ * OPTEE_MSG_CMD_RECLAIM_RSTMEM reclaims a previously lent restricted
+ * memory reference. The physical memory is accessible by the normal world
+ * after this function has return and can be mapped again. The information
+ * is passed as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
+ * [in] param[0].u.value.a		holds restricted memory cookie
+ *
+ * OPTEE_MSG_CMD_GET_RSTMEM_CONFIG get configuration for a specific
+ * restricted memory use case. Parameters are passed as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INOUT
+ * [in] param[0].value.a		OPTEE_MSG_RSTMEM_*
+ * [in] param[1].attr			OPTEE_MSG_ATTR_TYPE_{R,F}MEM_OUTPUT
+ * [in] param[1].u.{r,f}mem		Buffer or NULL
+ * [in] param[1].u.{r,f}mem.size	Provided size of buffer or 0 for query
+ * output for the restricted use case:
+ * [out] param[0].value.a		Minimal size of SDP memory
+ * [out] param[0].value.b		Required alignment of size and start of
+ *					restricted memory
+ * [out] param[1].{r,f}mem.size		Size of output data
+ * [out] param[1].{r,f}mem		If non-NULL, contains an array of
+ *					uint16_t holding endpoints that
+ *					must be included when lending
+ *					memory for this use case
+ *
+ * OPTEE_MSG_CMD_ASSIGN_RSTMEM assigns use-case to restricted memory
+ * previously lent using the FFA_LEND framework ABI. Parameters are passed
+ * as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
+ * [in] param[0].u.value.a		holds restricted memory cookie
+ * [in] param[0].u.value.b		OPTEE_MSG_RSTMEM_* defined above
  */
 #define OPTEE_MSG_CMD_OPEN_SESSION	0
 #define OPTEE_MSG_CMD_INVOKE_COMMAND	1
@@ -346,6 +401,10 @@ struct optee_msg_arg {
 #define OPTEE_MSG_CMD_UNREGISTER_SHM	5
 #define OPTEE_MSG_CMD_DO_BOTTOM_HALF	6
 #define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF	7
+#define OPTEE_MSG_CMD_LEND_RSTMEM	8
+#define OPTEE_MSG_CMD_RECLAIM_RSTMEM	9
+#define OPTEE_MSG_CMD_GET_RSTMEM_CONFIG	10
+#define OPTEE_MSG_CMD_ASSIGN_RSTMEM	11
 #define OPTEE_MSG_FUNCID_CALL_WITH_ARG	0x0004
 
 #endif /* _OPTEE_MSG_H */
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
index 879426300821..abc379ce190c 100644
--- a/drivers/tee/optee/optee_smc.h
+++ b/drivers/tee/optee/optee_smc.h
@@ -264,7 +264,6 @@ struct optee_smc_get_shm_config_result {
 #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM	BIT(0)
 /* Secure world can communicate via previously unregistered shared memory */
 #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM	BIT(1)
-
 /*
  * Secure world supports commands "register/unregister shared memory",
  * secure world accepts command buffers located in any parts of non-secure RAM
@@ -280,6 +279,10 @@ struct optee_smc_get_shm_config_result {
 #define OPTEE_SMC_SEC_CAP_RPC_ARG		BIT(6)
 /* Secure world supports probing for RPMB device if needed */
 #define OPTEE_SMC_SEC_CAP_RPMB_PROBE		BIT(7)
+/* Secure world supports Secure Data Path */
+#define OPTEE_SMC_SEC_CAP_SDP			BIT(8)
+/* Secure world supports dynamic restricted memory */
+#define OPTEE_SMC_SEC_CAP_DYNAMIC_RSTMEM	BIT(9)
 
 #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES	9
 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \
@@ -451,6 +454,72 @@ struct optee_smc_disable_shm_cache_result {
 
 /* See OPTEE_SMC_CALL_WITH_REGD_ARG above */
 #define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG	19
+/*
+ * Get Secure Data Path memory config
+ *
+ * Returns the Secure Data Path memory config.
+ *
+ * Call register usage:
+ * a0   SMC Function ID, OPTEE_SMC_GET_SDP_CONFIG
+ * a2-6	Not used, must be zero
+ * a7	Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1	Physical address of start of SDP memory
+ * a2	Size of SDP memory
+ * a3	Not used
+ * a4-7	Preserved
+ *
+ * Not available register usage:
+ * a0	OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-3 Not used
+ * a4-7	Preserved
+ */
+#define OPTEE_SMC_FUNCID_GET_SDP_CONFIG		20
+#define OPTEE_SMC_GET_SDP_CONFIG \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SDP_CONFIG)
+
+struct optee_smc_get_sdp_config_result {
+	unsigned long status;
+	unsigned long start;
+	unsigned long size;
+	unsigned long flags;
+};
+
+/*
+ * Get Secure Data Path dynamic memory config
+ *
+ * Returns the Secure Data Path dynamic memory config.
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_GET_DYN_SHM_CONFIG
+ * a2-6	Not used, must be zero
+ * a7	Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1	Minamal size of SDP memory
+ * a2	Required alignment of size and start of registered SDP memory
+ * a3	Not used
+ * a4-7	Preserved
+ *
+ * Not available register usage:
+ * a0	OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-3 Not used
+ * a4-7	Preserved
+ */
+
+#define OPTEE_SMC_FUNCID_GET_DYN_SDP_CONFIG	21
+#define OPTEE_SMC_GET_DYN_SDP_CONFIG \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_DYN_SDP_CONFIG)
+
+struct optee_smc_get_dyn_sdp_config_result {
+	unsigned long status;
+	unsigned long size;
+	unsigned long align;
+	unsigned long flags;
+};
 
 /*
  * Resume from RPC (for example after processing a foreign interrupt)
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:09 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:09 +0100
Subject: [PATCH v6 03/10] optee: account for direction while converting parameters
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-4-jens.wiklander@linaro.org>

The OP-TEE backend driver has two internal function pointers to convert
between the subsystem type struct tee_param and the OP-TEE type struct
optee_msg_param.

The conversion is done from one of the types to the other, which is then
involved in some operation and finally converted back to the original
type. When converting to prepare the parameters for the operation, all
fields must be taken into account, but then converting back, it's enough
to update only out-values and out-sizes. So, an update_out parameter is
added to the conversion functions to tell if all or only some fields
must be copied.

This is needed in a later patch where it might get confusing when
converting back in from_msg_param() callback since an allocated
restricted SHM can be using the sec_world_id of the used restricted
memory pool and that doesn't translate back well.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/call.c          | 10 ++--
 drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
 drivers/tee/optee/optee_private.h | 42 +++++++++++------
 drivers/tee/optee/rpc.c           | 31 +++++++++----
 drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
 5 files changed, 144 insertions(+), 58 deletions(-)

diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index 16eb953e14bb..f1533b894726 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
 	export_uuid(msg_arg->params[1].u.octets, &client_uuid);
 
 	rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
-				      arg->num_params, param);
+				      arg->num_params, param,
+				      false /*!update_out*/);
 	if (rc)
 		goto out;
 
@@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
 	}
 
 	if (optee->ops->from_msg_param(optee, param, arg->num_params,
-				       msg_arg->params + 2)) {
+				       msg_arg->params + 2,
+				       true /*update_out*/)) {
 		arg->ret = TEEC_ERROR_COMMUNICATION;
 		arg->ret_origin = TEEC_ORIGIN_COMMS;
 		/* Close session again to avoid leakage */
@@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
 	msg_arg->cancel_id = arg->cancel_id;
 
 	rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
-				      param);
+				      param, false /*!update_out*/);
 	if (rc)
 		goto out;
 
@@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
 	}
 
 	if (optee->ops->from_msg_param(optee, param, arg->num_params,
-				       msg_arg->params)) {
+				       msg_arg->params, true /*update_out*/)) {
 		msg_arg->ret = TEEC_ERROR_COMMUNICATION;
 		msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
 	}
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 4ca1d5161b82..e4b08cd195f3 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
  */
 
 static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
-				   u32 attr, const struct optee_msg_param *mp)
+				   u32 attr, const struct optee_msg_param *mp,
+				   bool update_out)
 {
 	struct tee_shm *shm = NULL;
 	u64 offs_high = 0;
 	u64 offs_low = 0;
 
+	if (update_out) {
+		if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
+			return;
+		goto out;
+	}
+
 	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
 		  attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
-	p->u.memref.size = mp->u.fmem.size;
 
 	if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
 		shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
@@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
 		offs_high = mp->u.fmem.offs_high;
 	}
 	p->u.memref.shm_offs = offs_low | offs_high << 32;
+out:
+	p->u.memref.size = mp->u.fmem.size;
 }
 
 /**
@@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
  * @params:	subsystem internal parameter representation
  * @num_params:	number of elements in the parameter arrays
  * @msg_params:	OPTEE_MSG parameters
+ * @update_out: update parameter for output only
  *
  * Returns 0 on success or <0 on failure
  */
 static int optee_ffa_from_msg_param(struct optee *optee,
 				    struct tee_param *params, size_t num_params,
-				    const struct optee_msg_param *msg_params)
+				    const struct optee_msg_param *msg_params,
+				    bool update_out)
 {
 	size_t n;
 
@@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
 
 		switch (attr) {
 		case OPTEE_MSG_ATTR_TYPE_NONE:
+			if (update_out)
+				break;
 			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
 			memset(&p->u, 0, sizeof(p->u));
 			break;
 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
-			optee_from_msg_param_value(p, attr, mp);
+			optee_from_msg_param_value(p, attr, mp, update_out);
 			break;
 		case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
 		case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
 		case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
-			from_msg_param_ffa_mem(optee, p, attr, mp);
+			from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
 			break;
 		default:
 			return -EINVAL;
@@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
 }
 
 static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
-				const struct tee_param *p)
+				const struct tee_param *p, bool update_out)
 {
 	struct tee_shm *shm = p->u.memref.shm;
 
+	if (update_out) {
+		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+			return 0;
+		goto out;
+	}
+
 	mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
 		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
 
@@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
 		memset(&mp->u, 0, sizeof(mp->u));
 		mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
 	}
+out:
 	mp->u.fmem.size = p->u.memref.size;
 
 	return 0;
@@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
  * @optee:	main service struct
  * @msg_params:	OPTEE_MSG parameters
  * @num_params:	number of elements in the parameter arrays
- * @params:	subsystem itnernal parameter representation
+ * @params:	subsystem internal parameter representation
+ * @update_out: update parameter for output only
  * Returns 0 on success or <0 on failure
  */
 static int optee_ffa_to_msg_param(struct optee *optee,
 				  struct optee_msg_param *msg_params,
 				  size_t num_params,
-				  const struct tee_param *params)
+				  const struct tee_param *params,
+				  bool update_out)
 {
 	size_t n;
 
@@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
 
 		switch (p->attr) {
 		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+			if (update_out)
+				break;
 			mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
 			memset(&mp->u, 0, sizeof(mp->u));
 			break;
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
-			optee_to_msg_param_value(mp, p);
+			optee_to_msg_param_value(mp, p, update_out);
 			break;
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
-			if (to_msg_param_ffa_mem(mp, p))
+			if (to_msg_param_ffa_mem(mp, p, update_out))
 				return -EINVAL;
 			break;
 		default:
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index dc0f355ef72a..20eda508dbac 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -185,10 +185,12 @@ struct optee_ops {
 				bool system_thread);
 	int (*to_msg_param)(struct optee *optee,
 			    struct optee_msg_param *msg_params,
-			    size_t num_params, const struct tee_param *params);
+			    size_t num_params, const struct tee_param *params,
+			    bool update_out);
 	int (*from_msg_param)(struct optee *optee, struct tee_param *params,
 			      size_t num_params,
-			      const struct optee_msg_param *msg_params);
+			      const struct optee_msg_param *msg_params,
+			      bool update_out);
 };
 
 /**
@@ -316,23 +318,35 @@ void optee_release(struct tee_context *ctx);
 void optee_release_supp(struct tee_context *ctx);
 
 static inline void optee_from_msg_param_value(struct tee_param *p, u32 attr,
-					      const struct optee_msg_param *mp)
+					      const struct optee_msg_param *mp,
+					      bool update_out)
 {
-	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
-		  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
-	p->u.value.a = mp->u.value.a;
-	p->u.value.b = mp->u.value.b;
-	p->u.value.c = mp->u.value.c;
+	if (!update_out)
+		p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+			  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+
+	if (attr == OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT ||
+	    attr == OPTEE_MSG_ATTR_TYPE_VALUE_INOUT || !update_out) {
+		p->u.value.a = mp->u.value.a;
+		p->u.value.b = mp->u.value.b;
+		p->u.value.c = mp->u.value.c;
+	}
 }
 
 static inline void optee_to_msg_param_value(struct optee_msg_param *mp,
-					    const struct tee_param *p)
+					    const struct tee_param *p,
+					    bool update_out)
 {
-	mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
-		   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
-	mp->u.value.a = p->u.value.a;
-	mp->u.value.b = p->u.value.b;
-	mp->u.value.c = p->u.value.c;
+	if (!update_out)
+		mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+			   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+
+	if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
+	    p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || !update_out) {
+		mp->u.value.a = p->u.value.a;
+		mp->u.value.b = p->u.value.b;
+		mp->u.value.c = p->u.value.c;
+	}
 }
 
 void optee_cq_init(struct optee_call_queue *cq, int thread_count);
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index ebbbd42b0e3e..580e6b9b0606 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -63,7 +63,7 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
 	}
 
 	if (optee->ops->from_msg_param(optee, params, arg->num_params,
-				       arg->params))
+				       arg->params, false /*!update_out*/))
 		goto bad;
 
 	for (i = 0; i < arg->num_params; i++) {
@@ -107,7 +107,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
 	} else {
 		params[3].u.value.a = msg.len;
 		if (optee->ops->to_msg_param(optee, arg->params,
-					     arg->num_params, params))
+					     arg->num_params, params,
+					     true /*update_out*/))
 			arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		else
 			arg->ret = TEEC_SUCCESS;
@@ -188,6 +189,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
 static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
 				struct optee_msg_arg *arg)
 {
+	bool update_out = false;
 	struct tee_param *params;
 
 	arg->ret_origin = TEEC_ORIGIN_COMMS;
@@ -200,15 +202,21 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
 	}
 
 	if (optee->ops->from_msg_param(optee, params, arg->num_params,
-				       arg->params)) {
+				       arg->params, update_out)) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		goto out;
 	}
 
 	arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
 
+	/*
+	 * Special treatment for OPTEE_RPC_CMD_SHM_ALLOC since input is a
+	 * value type, but the output is a memref type.
+	 */
+	if (arg->cmd != OPTEE_RPC_CMD_SHM_ALLOC)
+		update_out = true;
 	if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
-				     params))
+				     params, update_out))
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 out:
 	kfree(params);
@@ -270,7 +278,7 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
 
 	if (arg->num_params != ARRAY_SIZE(params) ||
 	    optee->ops->from_msg_param(optee, params, arg->num_params,
-				       arg->params) ||
+				       arg->params, false /*!update_out*/) ||
 	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		return;
@@ -280,7 +288,8 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
 	params[0].u.value.b = 0;
 	params[0].u.value.c = 0;
 	if (optee->ops->to_msg_param(optee, arg->params,
-				     arg->num_params, params)) {
+				     arg->num_params, params,
+				     true /*update_out*/)) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		return;
 	}
@@ -324,7 +333,7 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
 
 	if (arg->num_params != ARRAY_SIZE(params) ||
 	    optee->ops->from_msg_param(optee, params, arg->num_params,
-				       arg->params) ||
+				       arg->params, false /*!update_out*/) ||
 	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
 	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -358,7 +367,8 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
 	params[0].u.value.b = rdev->descr.capacity;
 	params[0].u.value.c = rdev->descr.reliable_wr_count;
 	if (optee->ops->to_msg_param(optee, arg->params,
-				     arg->num_params, params)) {
+				     arg->num_params, params,
+				     true /*update_out*/)) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		return;
 	}
@@ -384,7 +394,7 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
 
 	if (arg->num_params != ARRAY_SIZE(params) ||
 	    optee->ops->from_msg_param(optee, params, arg->num_params,
-				       arg->params) ||
+				       arg->params, false /*!update_out*/) ||
 	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
 	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -401,7 +411,8 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
 		goto out;
 	}
 	if (optee->ops->to_msg_param(optee, arg->params,
-				     arg->num_params, params)) {
+				     arg->num_params, params,
+				     true /*update_out*/)) {
 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 		goto out;
 	}
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 165fadd9abc9..cfdae266548b 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -81,20 +81,26 @@ static int optee_cpuhp_disable_pcpu_irq(unsigned int cpu)
  */
 
 static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
-				  const struct optee_msg_param *mp)
+				  const struct optee_msg_param *mp,
+				  bool update_out)
 {
 	struct tee_shm *shm;
 	phys_addr_t pa;
 	int rc;
 
+	if (update_out) {
+		if (attr == OPTEE_MSG_ATTR_TYPE_TMEM_INPUT)
+			return 0;
+		goto out;
+	}
+
 	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
 		  attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
-	p->u.memref.size = mp->u.tmem.size;
 	shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
 	if (!shm) {
 		p->u.memref.shm_offs = 0;
 		p->u.memref.shm = NULL;
-		return 0;
+		goto out;
 	}
 
 	rc = tee_shm_get_pa(shm, 0, &pa);
@@ -103,18 +109,25 @@ static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
 
 	p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
 	p->u.memref.shm = shm;
-
+out:
+	p->u.memref.size = mp->u.tmem.size;
 	return 0;
 }
 
 static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
-				   const struct optee_msg_param *mp)
+				   const struct optee_msg_param *mp,
+				   bool update_out)
 {
 	struct tee_shm *shm;
 
+	if (update_out) {
+		if (attr == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT)
+			return;
+		goto out;
+	}
+
 	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
 		  attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
-	p->u.memref.size = mp->u.rmem.size;
 	shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
 
 	if (shm) {
@@ -124,6 +137,8 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
 		p->u.memref.shm_offs = 0;
 		p->u.memref.shm = NULL;
 	}
+out:
+	p->u.memref.size = mp->u.rmem.size;
 }
 
 /**
@@ -133,11 +148,13 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
  * @params:	subsystem internal parameter representation
  * @num_params:	number of elements in the parameter arrays
  * @msg_params:	OPTEE_MSG parameters
+ * @update_out:	update parameter for output only
  * Returns 0 on success or <0 on failure
  */
 static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
 				size_t num_params,
-				const struct optee_msg_param *msg_params)
+				const struct optee_msg_param *msg_params,
+				bool update_out)
 {
 	int rc;
 	size_t n;
@@ -149,25 +166,27 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
 
 		switch (attr) {
 		case OPTEE_MSG_ATTR_TYPE_NONE:
+			if (update_out)
+				break;
 			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
 			memset(&p->u, 0, sizeof(p->u));
 			break;
 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
-			optee_from_msg_param_value(p, attr, mp);
+			optee_from_msg_param_value(p, attr, mp, update_out);
 			break;
 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
-			rc = from_msg_param_tmp_mem(p, attr, mp);
+			rc = from_msg_param_tmp_mem(p, attr, mp, update_out);
 			if (rc)
 				return rc;
 			break;
 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
-			from_msg_param_reg_mem(p, attr, mp);
+			from_msg_param_reg_mem(p, attr, mp, update_out);
 			break;
 
 		default:
@@ -178,20 +197,25 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
 }
 
 static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
-				const struct tee_param *p)
+				const struct tee_param *p, bool update_out)
 {
 	int rc;
 	phys_addr_t pa;
 
+	if (update_out) {
+		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+			return 0;
+		goto out;
+	}
+
 	mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
 		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
 
 	mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
-	mp->u.tmem.size = p->u.memref.size;
 
 	if (!p->u.memref.shm) {
 		mp->u.tmem.buf_ptr = 0;
-		return 0;
+		goto out;
 	}
 
 	rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
@@ -201,19 +225,27 @@ static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
 	mp->u.tmem.buf_ptr = pa;
 	mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
 		    OPTEE_MSG_ATTR_CACHE_SHIFT;
-
+out:
+	mp->u.tmem.size = p->u.memref.size;
 	return 0;
 }
 
 static int to_msg_param_reg_mem(struct optee_msg_param *mp,
-				const struct tee_param *p)
+				const struct tee_param *p, bool update_out)
 {
+	if (update_out) {
+		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
+			return 0;
+		goto out;
+	}
+
 	mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
 		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
 
 	mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
-	mp->u.rmem.size = p->u.memref.size;
 	mp->u.rmem.offs = p->u.memref.shm_offs;
+out:
+	mp->u.rmem.size = p->u.memref.size;
 	return 0;
 }
 
@@ -223,11 +255,13 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
  * @msg_params:	OPTEE_MSG parameters
  * @num_params:	number of elements in the parameter arrays
  * @params:	subsystem itnernal parameter representation
+ * @update_out:	update parameter for output only
  * Returns 0 on success or <0 on failure
  */
 static int optee_to_msg_param(struct optee *optee,
 			      struct optee_msg_param *msg_params,
-			      size_t num_params, const struct tee_param *params)
+			      size_t num_params, const struct tee_param *params,
+			      bool update_out)
 {
 	int rc;
 	size_t n;
@@ -238,21 +272,23 @@ static int optee_to_msg_param(struct optee *optee,
 
 		switch (p->attr) {
 		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+			if (update_out)
+				break;
 			mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
 			memset(&mp->u, 0, sizeof(mp->u));
 			break;
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
-			optee_to_msg_param_value(mp, p);
+			optee_to_msg_param_value(mp, p, update_out);
 			break;
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
 			if (tee_shm_is_dynamic(p->u.memref.shm))
-				rc = to_msg_param_reg_mem(mp, p);
+				rc = to_msg_param_reg_mem(mp, p, update_out);
 			else
-				rc = to_msg_param_tmp_mem(mp, p);
+				rc = to_msg_param_tmp_mem(mp, p, update_out);
 			if (rc)
 				return rc;
 			break;
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:11 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:11 +0100
Subject: [PATCH v6 05/10] tee: implement restricted DMA-heap
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-6-jens.wiklander@linaro.org>

Implement DMA heap for restricted DMA-buf allocation in the TEE
subsystem.

Restricted memory refers to memory buffers behind a hardware enforced
firewall. It is not accessible to the kernel during normal circumstances
but rather only accessible to certain hardware IPs or CPUs executing in
higher or differently privileged mode than the kernel itself. This
interface allows to allocate and manage such restricted memory buffers
via interaction with a TEE implementation.

The restricted memory is allocated for a specific use-case, like Secure
Video Playback, Trusted UI, or Secure Video Recording where certain
hardware devices can access the memory.

The DMA-heaps are enabled explicitly by the TEE backend driver. The TEE
backend drivers needs to implement restricted memory pool to manage the
restricted memory.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/Makefile      |   1 +
 drivers/tee/tee_heap.c    | 470 ++++++++++++++++++++++++++++++++++++++
 drivers/tee/tee_private.h |   6 +
 include/linux/tee_core.h  |  62 +++++
 4 files changed, 539 insertions(+)
 create mode 100644 drivers/tee/tee_heap.c

diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
index 5488cba30bd2..949a6a79fb06 100644
--- a/drivers/tee/Makefile
+++ b/drivers/tee/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_TEE) += tee.o
 tee-objs += tee_core.o
+tee-objs += tee_heap.o
 tee-objs += tee_shm.o
 tee-objs += tee_shm_pool.o
 obj-$(CONFIG_OPTEE) += optee/
diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c
new file mode 100644
index 000000000000..476ab2e27260
--- /dev/null
+++ b/drivers/tee/tee_heap.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025, Linaro Limited
+ */
+
+#include <linux/scatterlist.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+#include <linux/genalloc.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/tee_core.h>
+#include <linux/xarray.h>
+
+#include "tee_private.h"
+
+struct tee_dma_heap {
+	struct dma_heap *heap;
+	enum tee_dma_heap_id id;
+	struct tee_rstmem_pool *pool;
+	struct tee_device *teedev;
+	/* Protects pool and teedev above */
+	struct mutex mu;
+};
+
+struct tee_heap_buffer {
+	struct tee_rstmem_pool *pool;
+	struct tee_device *teedev;
+	size_t size;
+	size_t offs;
+	struct sg_table table;
+};
+
+struct tee_heap_attachment {
+	struct sg_table table;
+	struct device *dev;
+};
+
+struct tee_rstmem_static_pool {
+	struct tee_rstmem_pool pool;
+	struct gen_pool *gen_pool;
+	phys_addr_t pa_base;
+};
+
+#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_DMABUF_HEAPS)
+static DEFINE_XARRAY_ALLOC(tee_dma_heap);
+
+static int copy_sg_table(struct sg_table *dst, struct sg_table *src)
+{
+	struct scatterlist *dst_sg;
+	struct scatterlist *src_sg;
+	int ret;
+	int i;
+
+	ret = sg_alloc_table(dst, src->orig_nents, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	dst_sg = dst->sgl;
+	for_each_sgtable_sg(src, src_sg, i) {
+		sg_set_page(dst_sg, sg_page(src_sg), src_sg->length,
+			    src_sg->offset);
+		dst_sg = sg_next(dst_sg);
+	}
+
+	return 0;
+}
+
+static int tee_heap_attach(struct dma_buf *dmabuf,
+			   struct dma_buf_attachment *attachment)
+{
+	struct tee_heap_buffer *buf = dmabuf->priv;
+	struct tee_heap_attachment *a;
+	int ret;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	ret = copy_sg_table(&a->table, &buf->table);
+	if (ret) {
+		kfree(a);
+		return ret;
+	}
+
+	a->dev = attachment->dev;
+	attachment->priv = a;
+
+	return 0;
+}
+
+static void tee_heap_detach(struct dma_buf *dmabuf,
+			    struct dma_buf_attachment *attachment)
+{
+	struct tee_heap_attachment *a = attachment->priv;
+
+	sg_free_table(&a->table);
+	kfree(a);
+}
+
+static struct sg_table *
+tee_heap_map_dma_buf(struct dma_buf_attachment *attachment,
+		     enum dma_data_direction direction)
+{
+	struct tee_heap_attachment *a = attachment->priv;
+	int ret;
+
+	ret = dma_map_sgtable(attachment->dev, &a->table, direction,
+			      DMA_ATTR_SKIP_CPU_SYNC);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &a->table;
+}
+
+static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
+				   struct sg_table *table,
+				   enum dma_data_direction direction)
+{
+	struct tee_heap_attachment *a = attachment->priv;
+
+	WARN_ON(&a->table != table);
+
+	dma_unmap_sgtable(attachment->dev, table, direction,
+			  DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static void tee_heap_buf_free(struct dma_buf *dmabuf)
+{
+	struct tee_heap_buffer *buf = dmabuf->priv;
+	struct tee_device *teedev = buf->teedev;
+
+	buf->pool->ops->free(buf->pool, &buf->table);
+	tee_device_put(teedev);
+}
+
+static const struct dma_buf_ops tee_heap_buf_ops = {
+	.attach = tee_heap_attach,
+	.detach = tee_heap_detach,
+	.map_dma_buf = tee_heap_map_dma_buf,
+	.unmap_dma_buf = tee_heap_unmap_dma_buf,
+	.release = tee_heap_buf_free,
+};
+
+static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap,
+					  unsigned long len, u32 fd_flags,
+					  u64 heap_flags)
+{
+	struct tee_dma_heap *h = dma_heap_get_drvdata(heap);
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct tee_device *teedev = NULL;
+	struct tee_heap_buffer *buf;
+	struct tee_rstmem_pool *pool;
+	struct dma_buf *dmabuf;
+	int rc;
+
+	mutex_lock(&h->mu);
+	if (tee_device_get(h->teedev)) {
+		teedev = h->teedev;
+		pool = h->pool;
+	}
+	mutex_unlock(&h->mu);
+
+	if (!teedev)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf) {
+		dmabuf = ERR_PTR(-ENOMEM);
+		goto err;
+	}
+	buf->size = len;
+	buf->pool = pool;
+	buf->teedev = teedev;
+
+	rc = pool->ops->alloc(pool, &buf->table, len, &buf->offs);
+	if (rc) {
+		dmabuf = ERR_PTR(rc);
+		goto err_kfree;
+	}
+
+	exp_info.ops = &tee_heap_buf_ops;
+	exp_info.size = len;
+	exp_info.priv = buf;
+	exp_info.flags = fd_flags;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf))
+		goto err_rstmem_free;
+
+	return dmabuf;
+
+err_rstmem_free:
+	pool->ops->free(pool, &buf->table);
+err_kfree:
+	kfree(buf);
+err:
+	tee_device_put(h->teedev);
+	return dmabuf;
+}
+
+static const struct dma_heap_ops tee_dma_heap_ops = {
+	.allocate = tee_dma_heap_alloc,
+};
+
+static const char *heap_id_2_name(enum tee_dma_heap_id id)
+{
+	switch (id) {
+	case TEE_DMA_HEAP_SECURE_VIDEO_PLAY:
+		return "restricted,secure-video";
+	case TEE_DMA_HEAP_TRUSTED_UI:
+		return "restricted,trusted-ui";
+	case TEE_DMA_HEAP_SECURE_VIDEO_RECORD:
+		return "restricted,secure-video-record";
+	default:
+		return NULL;
+	}
+}
+
+static int alloc_dma_heap(struct tee_device *teedev, enum tee_dma_heap_id id,
+			  struct tee_rstmem_pool *pool)
+{
+	struct dma_heap_export_info exp_info = {
+		.ops = &tee_dma_heap_ops,
+		.name = heap_id_2_name(id),
+	};
+	struct tee_dma_heap *h;
+	int rc;
+
+	if (!exp_info.name)
+		return -EINVAL;
+
+	if (xa_reserve(&tee_dma_heap, id, GFP_KERNEL)) {
+		if (!xa_load(&tee_dma_heap, id))
+			return -EEXIST;
+		return -ENOMEM;
+	}
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+	h->id = id;
+	h->teedev = teedev;
+	h->pool = pool;
+	mutex_init(&h->mu);
+
+	exp_info.priv = h;
+	h->heap = dma_heap_add(&exp_info);
+	if (IS_ERR(h->heap)) {
+		rc = PTR_ERR(h->heap);
+		kfree(h);
+
+		return rc;
+	}
+
+	/* "can't fail" due to the call to xa_reserve() above */
+	return WARN(xa_store(&tee_dma_heap, id, h, GFP_KERNEL),
+		    "xa_store() failed");
+}
+
+int tee_device_register_dma_heap(struct tee_device *teedev,
+				 enum tee_dma_heap_id id,
+				 struct tee_rstmem_pool *pool)
+{
+	struct tee_dma_heap *h;
+	int rc;
+
+	h = xa_load(&tee_dma_heap, id);
+	if (h) {
+		mutex_lock(&h->mu);
+		if (h->teedev) {
+			rc = -EBUSY;
+		} else {
+			h->teedev = teedev;
+			h->pool = pool;
+			rc = 0;
+		}
+		mutex_unlock(&h->mu);
+	} else {
+		rc = alloc_dma_heap(teedev, id, pool);
+	}
+
+	if (rc)
+		dev_err(&teedev->dev, "can't register DMA heap id %d (%s)\n",
+			id, heap_id_2_name(id));
+
+	return rc;
+}
+
+void tee_device_unregister_all_dma_heaps(struct tee_device *teedev)
+{
+	struct tee_rstmem_pool *pool;
+	struct tee_dma_heap *h;
+	u_long i;
+
+	xa_for_each(&tee_dma_heap, i, h) {
+		if (h) {
+			pool = NULL;
+			mutex_lock(&h->mu);
+			if (h->teedev == teedev) {
+				pool = h->pool;
+				h->teedev = NULL;
+				h->pool = NULL;
+			}
+			mutex_unlock(&h->mu);
+			if (pool)
+				pool->ops->destroy_pool(pool);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
+
+int tee_heap_update_from_dma_buf(struct tee_device *teedev,
+				 struct dma_buf *dmabuf, size_t *offset,
+				 struct tee_shm *shm,
+				 struct tee_shm **parent_shm)
+{
+	struct tee_heap_buffer *buf;
+	int rc;
+
+	/* The DMA-buf must be from our heap */
+	if (dmabuf->ops != &tee_heap_buf_ops)
+		return -EINVAL;
+
+	buf = dmabuf->priv;
+	/* The buffer must be from the same teedev */
+	if (buf->teedev != teedev)
+		return -EINVAL;
+
+	shm->size = buf->size;
+
+	rc = buf->pool->ops->update_shm(buf->pool, &buf->table, buf->offs, shm,
+					parent_shm);
+	if (!rc && *parent_shm)
+		*offset = buf->offs;
+
+	return rc;
+}
+#else
+int tee_device_register_dma_heap(struct tee_device *teedev __always_unused,
+				 enum tee_dma_heap_id id __always_unused,
+				 struct tee_rstmem_pool *pool __always_unused)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(tee_device_register_dma_heap);
+
+void
+tee_device_unregister_all_dma_heaps(struct tee_device *teedev __always_unused)
+{
+}
+EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
+
+int tee_heap_update_from_dma_buf(struct tee_device *teedev __always_unused,
+				 struct dma_buf *dmabuf __always_unused,
+				 size_t *offset __always_unused,
+				 struct tee_shm *shm __always_unused,
+				 struct tee_shm **parent_shm __always_unused)
+{
+	return -EINVAL;
+}
+#endif
+
+static struct tee_rstmem_static_pool *
+to_rstmem_static_pool(struct tee_rstmem_pool *pool)
+{
+	return container_of(pool, struct tee_rstmem_static_pool, pool);
+}
+
+static int rstmem_pool_op_static_alloc(struct tee_rstmem_pool *pool,
+				       struct sg_table *sgt, size_t size,
+				       size_t *offs)
+{
+	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
+	phys_addr_t pa;
+	int ret;
+
+	pa = gen_pool_alloc(stp->gen_pool, size);
+	if (!pa)
+		return -ENOMEM;
+
+	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+	if (ret) {
+		gen_pool_free(stp->gen_pool, pa, size);
+		return ret;
+	}
+
+	sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
+	*offs = pa - stp->pa_base;
+
+	return 0;
+}
+
+static void rstmem_pool_op_static_free(struct tee_rstmem_pool *pool,
+				       struct sg_table *sgt)
+{
+	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sgtable_sg(sgt, sg, i)
+		gen_pool_free(stp->gen_pool, sg_phys(sg), sg->length);
+	sg_free_table(sgt);
+}
+
+static int rstmem_pool_op_static_update_shm(struct tee_rstmem_pool *pool,
+					    struct sg_table *sgt, size_t offs,
+					    struct tee_shm *shm,
+					    struct tee_shm **parent_shm)
+{
+	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
+
+	shm->paddr = stp->pa_base + offs;
+	*parent_shm = NULL;
+
+	return 0;
+}
+
+static void rstmem_pool_op_static_destroy_pool(struct tee_rstmem_pool *pool)
+{
+	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
+
+	gen_pool_destroy(stp->gen_pool);
+	kfree(stp);
+}
+
+static struct tee_rstmem_pool_ops rstmem_pool_ops_static = {
+	.alloc = rstmem_pool_op_static_alloc,
+	.free = rstmem_pool_op_static_free,
+	.update_shm = rstmem_pool_op_static_update_shm,
+	.destroy_pool = rstmem_pool_op_static_destroy_pool,
+};
+
+struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
+						     size_t size)
+{
+	const size_t page_mask = PAGE_SIZE - 1;
+	struct tee_rstmem_static_pool *stp;
+	int rc;
+
+	/* Check it's page aligned */
+	if ((paddr | size) & page_mask)
+		return ERR_PTR(-EINVAL);
+
+	stp = kzalloc(sizeof(*stp), GFP_KERNEL);
+	if (!stp)
+		return ERR_PTR(-ENOMEM);
+
+	stp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
+	if (!stp->gen_pool) {
+		rc = -ENOMEM;
+		goto err_free;
+	}
+
+	rc = gen_pool_add(stp->gen_pool, paddr, size, -1);
+	if (rc)
+		goto err_free_pool;
+
+	stp->pool.ops = &rstmem_pool_ops_static;
+	stp->pa_base = paddr;
+	return &stp->pool;
+
+err_free_pool:
+	gen_pool_destroy(stp->gen_pool);
+err_free:
+	kfree(stp);
+
+	return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(tee_rstmem_static_pool_alloc);
diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
index 9bc50605227c..6c6ff5d5eed2 100644
--- a/drivers/tee/tee_private.h
+++ b/drivers/tee/tee_private.h
@@ -8,6 +8,7 @@
 #include <linux/cdev.h>
 #include <linux/completion.h>
 #include <linux/device.h>
+#include <linux/dma-buf.h>
 #include <linux/kref.h>
 #include <linux/mutex.h>
 #include <linux/types.h>
@@ -24,4 +25,9 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
 struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
 					  unsigned long addr, size_t length);
 
+int tee_heap_update_from_dma_buf(struct tee_device *teedev,
+				 struct dma_buf *dmabuf, size_t *offset,
+				 struct tee_shm *shm,
+				 struct tee_shm **parent_shm);
+
 #endif /*TEE_PRIVATE_H*/
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index a38494d6b5f4..16ef078247ae 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -8,9 +8,11 @@
 
 #include <linux/cdev.h>
 #include <linux/device.h>
+#include <linux/dma-buf.h>
 #include <linux/idr.h>
 #include <linux/kref.h>
 #include <linux/list.h>
+#include <linux/scatterlist.h>
 #include <linux/tee.h>
 #include <linux/tee_drv.h>
 #include <linux/types.h>
@@ -30,6 +32,12 @@
 #define TEE_DEVICE_FLAG_REGISTERED	0x1
 #define TEE_MAX_DEV_NAME_LEN		32
 
+enum tee_dma_heap_id {
+	TEE_DMA_HEAP_SECURE_VIDEO_PLAY = 1,
+	TEE_DMA_HEAP_TRUSTED_UI,
+	TEE_DMA_HEAP_SECURE_VIDEO_RECORD,
+};
+
 /**
  * struct tee_device - TEE Device representation
  * @name:	name of device
@@ -116,6 +124,33 @@ struct tee_desc {
 	u32 flags;
 };
 
+/**
+ * struct tee_rstmem_pool - restricted memory pool
+ * @ops:		operations
+ *
+ * This is an abstract interface where this struct is expected to be
+ * embedded in another struct specific to the implementation.
+ */
+struct tee_rstmem_pool {
+	const struct tee_rstmem_pool_ops *ops;
+};
+
+/**
+ * struct tee_rstmem_pool_ops - restricted memory pool operations
+ * @alloc:		called when allocating restricted memory
+ * @free:		called when freeing restricted memory
+ * @destroy_pool:	called when destroying the pool
+ */
+struct tee_rstmem_pool_ops {
+	int (*alloc)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
+		     size_t size, size_t *offs);
+	void (*free)(struct tee_rstmem_pool *pool, struct sg_table *sgt);
+	int (*update_shm)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
+			  size_t offs, struct tee_shm *shm,
+			  struct tee_shm **parent_shm);
+	void (*destroy_pool)(struct tee_rstmem_pool *pool);
+};
+
 /**
  * tee_device_alloc() - Allocate a new struct tee_device instance
  * @teedesc:	Descriptor for this driver
@@ -154,6 +189,11 @@ int tee_device_register(struct tee_device *teedev);
  */
 void tee_device_unregister(struct tee_device *teedev);
 
+int tee_device_register_dma_heap(struct tee_device *teedev,
+				 enum tee_dma_heap_id id,
+				 struct tee_rstmem_pool *pool);
+void tee_device_unregister_all_dma_heaps(struct tee_device *teedev);
+
 /**
  * tee_device_set_dev_groups() - Set device attribute groups
  * @teedev:	Device to register
@@ -229,6 +269,28 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
 	pool->ops->destroy_pool(pool);
 }
 
+/**
+ * tee_rstmem_static_pool_alloc() - Create a restricted memory manager
+ * @paddr:	Physical address of start of pool
+ * @size:	Size in bytes of the pool
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
+						     size_t size);
+
+/**
+ * tee_rstmem_pool_free() - Free a restricted memory pool
+ * @pool:	The restricted memory pool to free
+ *
+ * There must be no remaining restricted memory allocated from this pool
+ * when this function is called.
+ */
+static inline void tee_rstmem_pool_free(struct tee_rstmem_pool *pool)
+{
+	pool->ops->destroy_pool(pool);
+}
+
 /**
  * tee_get_drvdata() - Return driver_data pointer
  * @returns the driver_data pointer supplied to tee_register().
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:13 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:13 +0100
Subject: [PATCH v6 07/10] tee: add tee_shm_alloc_cma_phys_mem()
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-8-jens.wiklander@linaro.org>

Add tee_shm_alloc_cma_phys_mem() to allocate a physical memory using
from the default CMA pool. The memory is represented by a tee_shm object
using the new flag TEE_SHM_CMA_BUF to identify it as physical memory
from CMA.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/tee_shm.c    | 55 ++++++++++++++++++++++++++++++++++++++--
 include/linux/tee_core.h |  4 +++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 8b79918468b5..8d8341f8ebd7 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -3,8 +3,11 @@
  * Copyright (c) 2015-2017, 2019-2021 Linaro Limited
  */
 #include <linux/anon_inodes.h>
+#include <linux/cma.h>
 #include <linux/device.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-map-ops.h>
+#include <linux/highmem.h>
 #include <linux/idr.h>
 #include <linux/io.h>
 #include <linux/mm.h>
@@ -13,7 +16,6 @@
 #include <linux/tee_core.h>
 #include <linux/uaccess.h>
 #include <linux/uio.h>
-#include <linux/highmem.h>
 #include "tee_private.h"
 
 /* extra references appended to shm object for registered shared memory */
@@ -59,7 +61,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
 	struct tee_shm *parent_shm = NULL;
 	void *p = shm;
 
-	if (shm->flags & TEE_SHM_DMA_BUF) {
+	if (shm->flags & TEE_SHM_CMA_BUF) {
+#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_CMA)
+		struct page *page = phys_to_page(shm->paddr);
+		struct cma *cma = dev_get_cma_area(&shm->ctx->teedev->dev);
+
+		cma_release(cma, page, shm->size / PAGE_SIZE);
+#endif
+	} else if (shm->flags & TEE_SHM_DMA_BUF) {
 		struct tee_shm_dmabuf_ref *ref;
 
 		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
@@ -341,6 +350,48 @@ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size)
 }
 EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf);
 
+struct tee_shm *tee_shm_alloc_cma_phys_mem(struct tee_context *ctx,
+					   size_t page_count, size_t align)
+{
+#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_CMA)
+	struct tee_device *teedev = ctx->teedev;
+	struct cma *cma = dev_get_cma_area(&teedev->dev);
+	struct tee_shm *shm;
+	struct page *page;
+
+	if (!tee_device_get(teedev))
+		return ERR_PTR(-EINVAL);
+
+	page = cma_alloc(cma, page_count, align, true/*no_warn*/);
+	if (!page)
+		goto err_put_teedev;
+
+	shm = kzalloc(sizeof(*shm), GFP_KERNEL);
+	if (!shm)
+		goto err_cma_crelease;
+
+	refcount_set(&shm->refcount, 1);
+	shm->ctx = ctx;
+	shm->paddr = page_to_phys(page);
+	shm->size = page_count * PAGE_SIZE;
+	shm->flags = TEE_SHM_CMA_BUF;
+
+	teedev_ctx_get(ctx);
+
+	return shm;
+
+err_cma_crelease:
+	cma_release(cma, page, page_count);
+err_put_teedev:
+	tee_device_put(teedev);
+
+	return ERR_PTR(-ENOMEM);
+#else
+	return ERR_PTR(-EINVAL);
+#endif
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc_cma_phys_mem);
+
 int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
 			     int (*shm_register)(struct tee_context *ctx,
 						 struct tee_shm *shm,
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index 6bd833b6d0e1..b6727d9a3556 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -29,6 +29,7 @@
 #define TEE_SHM_POOL		BIT(2)  /* Memory allocated from pool */
 #define TEE_SHM_PRIV		BIT(3)  /* Memory private to TEE driver */
 #define TEE_SHM_DMA_BUF		BIT(4)	/* Memory with dma-buf handle */
+#define TEE_SHM_CMA_BUF		BIT(5)	/* CMA allocated memory */
 
 #define TEE_DEVICE_FLAG_REGISTERED	0x1
 #define TEE_MAX_DEV_NAME_LEN		32
@@ -307,6 +308,9 @@ void *tee_get_drvdata(struct tee_device *teedev);
  */
 struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size);
 
+struct tee_shm *tee_shm_alloc_cma_phys_mem(struct tee_context *ctx,
+					   size_t page_count, size_t align);
+
 int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
 			     int (*shm_register)(struct tee_context *ctx,
 						 struct tee_shm *shm,
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:12 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:12 +0100
Subject: [PATCH v6 06/10] tee: new ioctl to a register tee_shm from a dmabuf file descriptor
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-7-jens.wiklander@linaro.org>

From: Etienne Carriere <etienne.carriere at linaro.org>

Enable userspace to create a tee_shm object that refers to a dmabuf
reference.

Userspace registers the dmabuf file descriptor as in a tee_shm object.
The registration is completed with a tee_shm file descriptor returned to
userspace.

Userspace is free to close the dmabuf file descriptor now since all the
resources are now held via the tee_shm object.

Closing the tee_shm file descriptor will release all resources used by the
tee_shm object.

This change only support dmabuf references that relates to physically
contiguous memory buffers.

New tee_shm flag to identify tee_shm objects built from a registered
dmabuf, TEE_SHM_DMA_BUF.

Signed-off-by: Etienne Carriere <etienne.carriere at linaro.org>
Signed-off-by: Olivier Masse <olivier.masse at nxp.com>
Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/tee_core.c    | 145 ++++++++++++++++++++++++++-----------
 drivers/tee/tee_private.h |   1 +
 drivers/tee/tee_shm.c     | 146 ++++++++++++++++++++++++++++++++++++--
 include/linux/tee_core.h  |   1 +
 include/linux/tee_drv.h   |  10 +++
 include/uapi/linux/tee.h  |  29 ++++++++
 6 files changed, 288 insertions(+), 44 deletions(-)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 685afcaa3ea1..3a71643766d5 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -353,6 +353,103 @@ tee_ioctl_shm_register(struct tee_context *ctx,
 	return ret;
 }
 
+static int
+tee_ioctl_shm_register_fd(struct tee_context *ctx,
+			  struct tee_ioctl_shm_register_fd_data __user *udata)
+{
+	struct tee_ioctl_shm_register_fd_data data;
+	struct tee_shm *shm;
+	long ret;
+
+	if (copy_from_user(&data, udata, sizeof(data)))
+		return -EFAULT;
+
+	/* Currently no input flags are supported */
+	if (data.flags)
+		return -EINVAL;
+
+	shm = tee_shm_register_fd(ctx, data.fd);
+	if (IS_ERR(shm))
+		return -EINVAL;
+
+	data.id = shm->id;
+	data.flags = shm->flags;
+	data.size = shm->size;
+
+	if (copy_to_user(udata, &data, sizeof(data)))
+		ret = -EFAULT;
+	else
+		ret = tee_shm_get_fd(shm);
+
+	/*
+	 * When user space closes the file descriptor the shared memory
+	 * should be freed or if tee_shm_get_fd() failed then it will
+	 * be freed immediately.
+	 */
+	tee_shm_put(shm);
+	return ret;
+}
+
+static int param_from_user_memref(struct tee_context *ctx,
+				  struct tee_param_memref *memref,
+				  struct tee_ioctl_param *ip)
+{
+	struct tee_shm *shm;
+	size_t offs = 0;
+
+	/*
+	 * If a NULL pointer is passed to a TA in the TEE,
+	 * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
+	 * indicating a NULL memory reference.
+	 */
+	if (ip->c != TEE_MEMREF_NULL) {
+		/*
+		 * If we fail to get a pointer to a shared
+		 * memory object (and increase the ref count)
+		 * from an identifier we return an error. All
+		 * pointers that has been added in params have
+		 * an increased ref count. It's the callers
+		 * responibility to do tee_shm_put() on all
+		 * resolved pointers.
+		 */
+		shm = tee_shm_get_from_id(ctx, ip->c);
+		if (IS_ERR(shm))
+			return PTR_ERR(shm);
+
+		/*
+		 * Ensure offset + size does not overflow
+		 * offset and does not overflow the size of
+		 * the referred shared memory object.
+		 */
+		if ((ip->a + ip->b) < ip->a ||
+		    (ip->a + ip->b) > shm->size) {
+			tee_shm_put(shm);
+			return -EINVAL;
+		}
+
+		if (shm->flags & TEE_SHM_DMA_BUF) {
+			struct tee_shm *parent_shm;
+
+			parent_shm = tee_shm_get_parent_shm(shm, &offs);
+			if (parent_shm) {
+				tee_shm_put(shm);
+				shm = parent_shm;
+			}
+		}
+	} else if (ctx->cap_memref_null) {
+		/* Pass NULL pointer to OP-TEE */
+		shm = NULL;
+	} else {
+		return -EINVAL;
+	}
+
+	memref->shm_offs = ip->a + offs;
+	memref->size = ip->b;
+	memref->shm = shm;
+
+	return 0;
+}
+
 static int params_from_user(struct tee_context *ctx, struct tee_param *params,
 			    size_t num_params,
 			    struct tee_ioctl_param __user *uparams)
@@ -360,8 +457,8 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
 	size_t n;
 
 	for (n = 0; n < num_params; n++) {
-		struct tee_shm *shm;
 		struct tee_ioctl_param ip;
+		int rc;
 
 		if (copy_from_user(&ip, uparams + n, sizeof(ip)))
 			return -EFAULT;
@@ -384,45 +481,10 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
-			/*
-			 * If a NULL pointer is passed to a TA in the TEE,
-			 * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
-			 * indicating a NULL memory reference.
-			 */
-			if (ip.c != TEE_MEMREF_NULL) {
-				/*
-				 * If we fail to get a pointer to a shared
-				 * memory object (and increase the ref count)
-				 * from an identifier we return an error. All
-				 * pointers that has been added in params have
-				 * an increased ref count. It's the callers
-				 * responibility to do tee_shm_put() on all
-				 * resolved pointers.
-				 */
-				shm = tee_shm_get_from_id(ctx, ip.c);
-				if (IS_ERR(shm))
-					return PTR_ERR(shm);
-
-				/*
-				 * Ensure offset + size does not overflow
-				 * offset and does not overflow the size of
-				 * the referred shared memory object.
-				 */
-				if ((ip.a + ip.b) < ip.a ||
-				    (ip.a + ip.b) > shm->size) {
-					tee_shm_put(shm);
-					return -EINVAL;
-				}
-			} else if (ctx->cap_memref_null) {
-				/* Pass NULL pointer to OP-TEE */
-				shm = NULL;
-			} else {
-				return -EINVAL;
-			}
-
-			params[n].u.memref.shm_offs = ip.a;
-			params[n].u.memref.size = ip.b;
-			params[n].u.memref.shm = shm;
+			rc = param_from_user_memref(ctx, &params[n].u.memref,
+						    &ip);
+			if (rc)
+				return rc;
 			break;
 		default:
 			/* Unknown attribute */
@@ -827,6 +889,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return tee_ioctl_shm_alloc(ctx, uarg);
 	case TEE_IOC_SHM_REGISTER:
 		return tee_ioctl_shm_register(ctx, uarg);
+	case TEE_IOC_SHM_REGISTER_FD:
+		return tee_ioctl_shm_register_fd(ctx, uarg);
 	case TEE_IOC_OPEN_SESSION:
 		return tee_ioctl_open_session(ctx, uarg);
 	case TEE_IOC_INVOKE:
@@ -1288,3 +1352,4 @@ MODULE_AUTHOR("Linaro");
 MODULE_DESCRIPTION("TEE Driver");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
index 6c6ff5d5eed2..aad7f6c7e0f0 100644
--- a/drivers/tee/tee_private.h
+++ b/drivers/tee/tee_private.h
@@ -24,6 +24,7 @@ void teedev_ctx_put(struct tee_context *ctx);
 struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
 struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
 					  unsigned long addr, size_t length);
+struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs);
 
 int tee_heap_update_from_dma_buf(struct tee_device *teedev,
 				 struct dma_buf *dmabuf, size_t *offset,
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index daf6e5cfd59a..8b79918468b5 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -4,6 +4,7 @@
  */
 #include <linux/anon_inodes.h>
 #include <linux/device.h>
+#include <linux/dma-buf.h>
 #include <linux/idr.h>
 #include <linux/io.h>
 #include <linux/mm.h>
@@ -15,6 +16,16 @@
 #include <linux/highmem.h>
 #include "tee_private.h"
 
+/* extra references appended to shm object for registered shared memory */
+struct tee_shm_dmabuf_ref {
+	struct tee_shm shm;
+	size_t offset;
+	struct dma_buf *dmabuf;
+	struct dma_buf_attachment *attach;
+	struct sg_table *sgt;
+	struct tee_shm *parent_shm;
+};
+
 static void shm_put_kernel_pages(struct page **pages, size_t page_count)
 {
 	size_t n;
@@ -45,7 +56,23 @@ static void release_registered_pages(struct tee_shm *shm)
 
 static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
 {
-	if (shm->flags & TEE_SHM_POOL) {
+	struct tee_shm *parent_shm = NULL;
+	void *p = shm;
+
+	if (shm->flags & TEE_SHM_DMA_BUF) {
+		struct tee_shm_dmabuf_ref *ref;
+
+		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
+		parent_shm = ref->parent_shm;
+		p = ref;
+		if (ref->attach) {
+			dma_buf_unmap_attachment(ref->attach, ref->sgt,
+						 DMA_BIDIRECTIONAL);
+
+			dma_buf_detach(ref->dmabuf, ref->attach);
+		}
+		dma_buf_put(ref->dmabuf);
+	} else if (shm->flags & TEE_SHM_POOL) {
 		teedev->pool->ops->free(teedev->pool, shm);
 	} else if (shm->flags & TEE_SHM_DYNAMIC) {
 		int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
@@ -57,9 +84,10 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
 		release_registered_pages(shm);
 	}
 
-	teedev_ctx_put(shm->ctx);
+	if (shm->ctx)
+		teedev_ctx_put(shm->ctx);
 
-	kfree(shm);
+	kfree(p);
 
 	tee_device_put(teedev);
 }
@@ -169,7 +197,7 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
  * tee_client_invoke_func(). The memory allocated is later freed with a
  * call to tee_shm_free().
  *
- * @returns a pointer to 'struct tee_shm'
+ * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
  */
 struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
 {
@@ -179,6 +207,116 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
 }
 EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
 
+struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
+{
+	struct tee_shm_dmabuf_ref *ref;
+	int rc;
+
+	if (!tee_device_get(ctx->teedev))
+		return ERR_PTR(-EINVAL);
+
+	teedev_ctx_get(ctx);
+
+	ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+	if (!ref) {
+		rc = -ENOMEM;
+		goto err_put_tee;
+	}
+
+	refcount_set(&ref->shm.refcount, 1);
+	ref->shm.ctx = ctx;
+	ref->shm.id = -1;
+	ref->shm.flags = TEE_SHM_DMA_BUF;
+
+	ref->dmabuf = dma_buf_get(fd);
+	if (IS_ERR(ref->dmabuf)) {
+		rc = PTR_ERR(ref->dmabuf);
+		goto err_kfree_ref;
+	}
+
+	rc = tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf,
+					  &ref->offset, &ref->shm,
+					  &ref->parent_shm);
+	if (!rc)
+		goto out;
+	if (rc != -EINVAL)
+		goto err_put_dmabuf;
+
+	ref->attach = dma_buf_attach(ref->dmabuf, &ctx->teedev->dev);
+	if (IS_ERR(ref->attach)) {
+		rc = PTR_ERR(ref->attach);
+		goto err_put_dmabuf;
+	}
+
+	ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(ref->sgt)) {
+		rc = PTR_ERR(ref->sgt);
+		goto err_detach;
+	}
+
+	if (sg_nents(ref->sgt->sgl) != 1) {
+		rc = PTR_ERR(ref->sgt->sgl);
+		goto err_unmap_attachement;
+	}
+
+	ref->shm.paddr = page_to_phys(sg_page(ref->sgt->sgl));
+	ref->shm.size = ref->sgt->sgl->length;
+
+out:
+	mutex_lock(&ref->shm.ctx->teedev->mutex);
+	ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
+				1, 0, GFP_KERNEL);
+	mutex_unlock(&ref->shm.ctx->teedev->mutex);
+	if (ref->shm.id < 0) {
+		rc = ref->shm.id;
+		if (ref->attach)
+			goto err_unmap_attachement;
+		goto err_put_dmabuf;
+	}
+
+	return &ref->shm;
+
+err_unmap_attachement:
+	dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL);
+err_detach:
+	dma_buf_detach(ref->dmabuf, ref->attach);
+err_put_dmabuf:
+	dma_buf_put(ref->dmabuf);
+err_kfree_ref:
+	kfree(ref);
+err_put_tee:
+	teedev_ctx_put(ctx);
+	tee_device_put(ctx->teedev);
+
+	return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(tee_shm_register_fd);
+
+struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs)
+{
+	struct tee_shm *parent_shm = NULL;
+
+	if (shm->flags & TEE_SHM_DMA_BUF) {
+		struct tee_shm_dmabuf_ref *ref;
+
+		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
+		if (ref->parent_shm) {
+			/*
+			 * the shm already has one reference to
+			 * ref->parent_shm so we should be clear of 0.
+			 * We're getting another reference since the caller
+			 * of this function expects to put the returned
+			 * parent_shm when it's done with it.
+			 */
+			parent_shm = ref->parent_shm;
+			refcount_inc(&parent_shm->refcount);
+			*offs = ref->offset;
+		}
+	}
+
+	return parent_shm;
+}
+
 /**
  * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared
  *			      kernel buffer
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index 16ef078247ae..6bd833b6d0e1 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -28,6 +28,7 @@
 #define TEE_SHM_USER_MAPPED	BIT(1)  /* Memory mapped in user space */
 #define TEE_SHM_POOL		BIT(2)  /* Memory allocated from pool */
 #define TEE_SHM_PRIV		BIT(3)  /* Memory private to TEE driver */
+#define TEE_SHM_DMA_BUF		BIT(4)	/* Memory with dma-buf handle */
 
 #define TEE_DEVICE_FLAG_REGISTERED	0x1
 #define TEE_MAX_DEV_NAME_LEN		32
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index a54c203000ed..824f1251de60 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -116,6 +116,16 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
 struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
 					    void *addr, size_t length);
 
+/**
+ * tee_shm_register_fd() - Register shared memory from file descriptor
+ *
+ * @ctx:	Context that allocates the shared memory
+ * @fd:		Shared memory file descriptor reference
+ *
+ * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
+ */
+struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
+
 /**
  * tee_shm_free() - Free shared memory
  * @shm:	Handle to shared memory to free
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
index d0430bee8292..1f9a4ac2b211 100644
--- a/include/uapi/linux/tee.h
+++ b/include/uapi/linux/tee.h
@@ -118,6 +118,35 @@ struct tee_ioctl_shm_alloc_data {
 #define TEE_IOC_SHM_ALLOC	_IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
 				     struct tee_ioctl_shm_alloc_data)
 
+/**
+ * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
+ * @fd:		[in] File descriptor identifying the shared memory
+ * @size:	[out] Size of shared memory to allocate
+ * @flags:	[in] Flags to/from allocation.
+ * @id:		[out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_REGISTER_FD below.
+ */
+struct tee_ioctl_shm_register_fd_data {
+	__s64 fd;
+	__u64 size;
+	__u32 flags;
+	__s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor refers to the shared memory object in kernel
+ * land. The shared memory is freed when the descriptor is closed.
+ */
+#define TEE_IOC_SHM_REGISTER_FD	_IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
+				     struct tee_ioctl_shm_register_fd_data)
+
 /**
  * struct tee_ioctl_buf_data - Variable sized buffer
  * @buf_ptr:	[in] A __user pointer to a buffer
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:14 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:14 +0100
Subject: [PATCH v6 08/10] optee: support restricted memory allocation
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-9-jens.wiklander@linaro.org>

Add support in the OP-TEE backend driver for restricted memory
allocation. The support is limited to only the SMC ABI and for secure
video buffers.

OP-TEE is probed for the range of restricted physical memory and a
memory pool allocator is initialized if OP-TEE have support for such
memory.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/core.c    |  1 +
 drivers/tee/optee/smc_abi.c | 44 +++++++++++++++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index c75fddc83576..c7fd8040480e 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -181,6 +181,7 @@ void optee_remove_common(struct optee *optee)
 	tee_device_unregister(optee->supp_teedev);
 	tee_device_unregister(optee->teedev);
 
+	tee_device_unregister_all_dma_heaps(optee->teedev);
 	tee_shm_pool_free(optee->pool);
 	optee_supp_uninit(&optee->supp);
 	mutex_destroy(&optee->call_queue.mutex);
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index cfdae266548b..a14ff0b7d3b3 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1620,6 +1620,41 @@ static inline int optee_load_fw(struct platform_device *pdev,
 }
 #endif
 
+static int optee_sdp_pool_init(struct optee *optee)
+{
+	enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
+	struct tee_rstmem_pool *pool;
+	int rc;
+
+	if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP) {
+		union {
+			struct arm_smccc_res smccc;
+			struct optee_smc_get_sdp_config_result result;
+		} res;
+
+		optee->smc.invoke_fn(OPTEE_SMC_GET_SDP_CONFIG, 0, 0, 0, 0, 0, 0,
+				     0, &res.smccc);
+		if (res.result.status != OPTEE_SMC_RETURN_OK) {
+			pr_err("Secure Data Path service not available\n");
+			return 0;
+		}
+
+		pool = tee_rstmem_static_pool_alloc(res.result.start,
+						    res.result.size);
+		if (IS_ERR(pool))
+			return PTR_ERR(pool);
+
+		rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
+		if (rc)
+			goto err;
+	}
+
+	return 0;
+err:
+	pool->ops->destroy_pool(pool);
+	return rc;
+}
+
 static int optee_probe(struct platform_device *pdev)
 {
 	optee_invoke_fn *invoke_fn;
@@ -1715,7 +1750,7 @@ static int optee_probe(struct platform_device *pdev)
 	optee = kzalloc(sizeof(*optee), GFP_KERNEL);
 	if (!optee) {
 		rc = -ENOMEM;
-		goto err_free_pool;
+		goto err_free_shm_pool;
 	}
 
 	optee->ops = &optee_ops;
@@ -1788,6 +1823,10 @@ static int optee_probe(struct platform_device *pdev)
 		pr_info("Asynchronous notifications enabled\n");
 	}
 
+	rc = optee_sdp_pool_init(optee);
+	if (rc)
+		goto err_notif_uninit;
+
 	/*
 	 * Ensure that there are no pre-existing shm objects before enabling
 	 * the shm cache so that there's no chance of receiving an invalid
@@ -1823,6 +1862,7 @@ static int optee_probe(struct platform_device *pdev)
 		optee_disable_shm_cache(optee);
 	optee_smc_notif_uninit_irq(optee);
 	optee_unregister_devices();
+	tee_device_unregister_all_dma_heaps(optee->teedev);
 err_notif_uninit:
 	optee_notif_uninit(optee);
 err_close_ctx:
@@ -1839,7 +1879,7 @@ static int optee_probe(struct platform_device *pdev)
 	tee_device_unregister(optee->teedev);
 err_free_optee:
 	kfree(optee);
-err_free_pool:
+err_free_shm_pool:
 	tee_shm_pool_free(pool);
 	if (memremaped_shm)
 		memunmap(memremaped_shm);
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:15 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:15 +0100
Subject: [PATCH v6 09/10] optee: FF-A: dynamic restricted memory allocation
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-10-jens.wiklander@linaro.org>

Add support in the OP-TEE backend driver dynamic restricted memory
allocation with FF-A.

The restricted memory pools for dynamically allocated restrict memory
are instantiated when requested by user-space. This instantiation can
fail if OP-TEE doesn't support the requested use-case of restricted
memory.

Restricted memory pools based on a static carveout or dynamic allocation
can coexist for different use-cases. We use only dynamic allocation with
FF-A.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/Makefile        |   1 +
 drivers/tee/optee/ffa_abi.c       | 143 ++++++++++++-
 drivers/tee/optee/optee_private.h |  13 +-
 drivers/tee/optee/rstmem.c        | 329 ++++++++++++++++++++++++++++++
 4 files changed, 483 insertions(+), 3 deletions(-)
 create mode 100644 drivers/tee/optee/rstmem.c

diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index a6eff388d300..498969fb8e40 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -4,6 +4,7 @@ optee-objs += core.o
 optee-objs += call.o
 optee-objs += notif.o
 optee-objs += rpc.o
+optee-objs += rstmem.o
 optee-objs += supp.o
 optee-objs += device.o
 optee-objs += smc_abi.o
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index e4b08cd195f3..6a55114232ef 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -672,6 +672,123 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
 	return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread);
 }
 
+static int do_call_lend_rstmem(struct optee *optee, u64 cookie, u32 use_case)
+{
+	struct optee_shm_arg_entry *entry;
+	struct optee_msg_arg *msg_arg;
+	struct tee_shm *shm;
+	u_int offs;
+	int rc;
+
+	msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
+	if (IS_ERR(msg_arg))
+		return PTR_ERR(msg_arg);
+
+	msg_arg->cmd = OPTEE_MSG_CMD_ASSIGN_RSTMEM;
+	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+	msg_arg->params[0].u.value.a = cookie;
+	msg_arg->params[0].u.value.b = use_case;
+
+	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
+	if (rc)
+		goto out;
+	if (msg_arg->ret != TEEC_SUCCESS) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+out:
+	optee_free_msg_arg(optee->ctx, entry, offs);
+	return rc;
+}
+
+static int optee_ffa_lend_rstmem(struct optee *optee, struct tee_shm *rstmem,
+				 u16 *end_points, unsigned int ep_count,
+				 u32 use_case)
+{
+	struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
+	const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
+	const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
+	struct ffa_send_direct_data data;
+	struct ffa_mem_region_attributes *mem_attr;
+	struct ffa_mem_ops_args args = {
+		.use_txbuf = true,
+		.tag = use_case,
+	};
+	struct page *page;
+	struct scatterlist sgl;
+	unsigned int n;
+	int rc;
+
+	mem_attr = kcalloc(ep_count, sizeof(*mem_attr), GFP_KERNEL);
+	for (n = 0; n < ep_count; n++) {
+		mem_attr[n].receiver = end_points[n];
+		mem_attr[n].attrs = FFA_MEM_RW;
+	}
+	args.attrs = mem_attr;
+	args.nattrs = ep_count;
+
+	page = phys_to_page(rstmem->paddr);
+	sg_init_table(&sgl, 1);
+	sg_set_page(&sgl, page, rstmem->size, 0);
+
+	args.sg = &sgl;
+	rc = mem_ops->memory_lend(&args);
+	kfree(mem_attr);
+	if (rc)
+		return rc;
+
+	rc = do_call_lend_rstmem(optee, args.g_handle, use_case);
+	if (rc)
+		goto err_reclaim;
+
+	rc = optee_shm_add_ffa_handle(optee, rstmem, args.g_handle);
+	if (rc)
+		goto err_unreg;
+
+	rstmem->sec_world_id = args.g_handle;
+
+	return 0;
+
+err_unreg:
+	data = (struct ffa_send_direct_data){
+		.data0 = OPTEE_FFA_RELEASE_RSTMEM,
+		.data1 = (u32)args.g_handle,
+		.data2 = (u32)(args.g_handle >> 32),
+	};
+	msg_ops->sync_send_receive(ffa_dev, &data);
+err_reclaim:
+	mem_ops->memory_reclaim(args.g_handle, 0);
+	return rc;
+}
+
+static int optee_ffa_reclaim_rstmem(struct optee *optee, struct tee_shm *rstmem)
+{
+	struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
+	const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
+	const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
+	u64 global_handle = rstmem->sec_world_id;
+	struct ffa_send_direct_data data = {
+		.data0 = OPTEE_FFA_RELEASE_RSTMEM,
+		.data1 = (u32)global_handle,
+		.data2 = (u32)(global_handle >> 32)
+	};
+	int rc;
+
+	optee_shm_rem_ffa_handle(optee, global_handle);
+	rstmem->sec_world_id = 0;
+
+	rc = msg_ops->sync_send_receive(ffa_dev, &data);
+	if (rc)
+		pr_err("Release SHM id 0x%llx rc %d\n", global_handle, rc);
+
+	rc = mem_ops->memory_reclaim(global_handle, 0);
+	if (rc)
+		pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
+
+	return rc;
+}
+
 /*
  * 6. Driver initialization
  *
@@ -833,6 +950,8 @@ static const struct optee_ops optee_ffa_ops = {
 	.do_call_with_arg = optee_ffa_do_call_with_arg,
 	.to_msg_param = optee_ffa_to_msg_param,
 	.from_msg_param = optee_ffa_from_msg_param,
+	.lend_rstmem = optee_ffa_lend_rstmem,
+	.reclaim_rstmem = optee_ffa_reclaim_rstmem,
 };
 
 static void optee_ffa_remove(struct ffa_device *ffa_dev)
@@ -941,7 +1060,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
 				  optee->pool, optee);
 	if (IS_ERR(teedev)) {
 		rc = PTR_ERR(teedev);
-		goto err_free_pool;
+		goto err_free_shm_pool;
 	}
 	optee->teedev = teedev;
 
@@ -988,6 +1107,24 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
 			       rc);
 	}
 
+	if (IS_ENABLED(CONFIG_CMA) && !IS_MODULE(CONFIG_OPTEE) &&
+	    (sec_caps & OPTEE_FFA_SEC_CAP_RSTMEM)) {
+		enum tee_dma_heap_id id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
+		struct tee_rstmem_pool *pool;
+
+		pool = optee_rstmem_alloc_cma_pool(optee, id);
+		if (IS_ERR(pool)) {
+			rc = PTR_ERR(pool);
+			goto err_notif_uninit;
+		}
+
+		rc = tee_device_register_dma_heap(optee->teedev, id, pool);
+		if (rc) {
+			pool->ops->destroy_pool(pool);
+			goto err_notif_uninit;
+		}
+	}
+
 	rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
 	if (rc)
 		goto err_unregister_devices;
@@ -1001,6 +1138,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
 
 err_unregister_devices:
 	optee_unregister_devices();
+	tee_device_unregister_all_dma_heaps(optee->teedev);
+err_notif_uninit:
 	if (optee->ffa.bottom_half_value != U32_MAX)
 		notif_ops->notify_relinquish(ffa_dev,
 					     optee->ffa.bottom_half_value);
@@ -1018,7 +1157,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
 	tee_device_unregister(optee->supp_teedev);
 err_unreg_teedev:
 	tee_device_unregister(optee->teedev);
-err_free_pool:
+err_free_shm_pool:
 	tee_shm_pool_free(pool);
 err_free_optee:
 	kfree(optee);
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 20eda508dbac..faab31ad7c52 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -174,9 +174,14 @@ struct optee;
  * @do_call_with_arg:	enters OP-TEE in secure world
  * @to_msg_param:	converts from struct tee_param to OPTEE_MSG parameters
  * @from_msg_param:	converts from OPTEE_MSG parameters to struct tee_param
+ * @lend_rstmem:	lends physically contiguous memory as restricted
+ *			memory, inaccessible by the kernel
+ * @reclaim_rstmem:	reclaims restricted memory previously lent with
+ *			@lend_rstmem() and makes it accessible by the
+ *			kernel again
  *
  * These OPs are only supposed to be used internally in the OP-TEE driver
- * as a way of abstracting the different methogs of entering OP-TEE in
+ * as a way of abstracting the different methods of entering OP-TEE in
  * secure world.
  */
 struct optee_ops {
@@ -191,6 +196,10 @@ struct optee_ops {
 			      size_t num_params,
 			      const struct optee_msg_param *msg_params,
 			      bool update_out);
+	int (*lend_rstmem)(struct optee *optee, struct tee_shm *rstmem,
+			   u16 *end_points, unsigned int ep_count,
+			   u32 use_case);
+	int (*reclaim_rstmem)(struct optee *optee, struct tee_shm *rstmem);
 };
 
 /**
@@ -285,6 +294,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
 void optee_supp_init(struct optee_supp *supp);
 void optee_supp_uninit(struct optee_supp *supp);
 void optee_supp_release(struct optee_supp *supp);
+struct tee_rstmem_pool *optee_rstmem_alloc_cma_pool(struct optee *optee,
+						    enum tee_dma_heap_id id);
 
 int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
 		    struct tee_param *param);
diff --git a/drivers/tee/optee/rstmem.c b/drivers/tee/optee/rstmem.c
new file mode 100644
index 000000000000..ea27769934d4
--- /dev/null
+++ b/drivers/tee/optee/rstmem.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025, Linaro Limited
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/errno.h>
+#include <linux/genalloc.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tee_core.h>
+#include <linux/types.h>
+#include "optee_private.h"
+
+struct optee_rstmem_cma_pool {
+	struct tee_rstmem_pool pool;
+	struct gen_pool *gen_pool;
+	struct optee *optee;
+	size_t page_count;
+	u16 *end_points;
+	u_int end_point_count;
+	u_int align;
+	refcount_t refcount;
+	u32 use_case;
+	struct tee_shm *rstmem;
+	/* Protects when initializing and tearing down this struct */
+	struct mutex mutex;
+};
+
+static struct optee_rstmem_cma_pool *
+to_rstmem_cma_pool(struct tee_rstmem_pool *pool)
+{
+	return container_of(pool, struct optee_rstmem_cma_pool, pool);
+}
+
+static int init_cma_rstmem(struct optee_rstmem_cma_pool *rp)
+{
+	int rc;
+
+	rp->rstmem = tee_shm_alloc_cma_phys_mem(rp->optee->ctx, rp->page_count,
+						rp->align);
+	if (IS_ERR(rp->rstmem)) {
+		rc = PTR_ERR(rp->rstmem);
+		goto err_null_rstmem;
+	}
+
+	/*
+	 * TODO unmap the memory range since the physical memory will
+	 * become inaccesible after the lend_rstmem() call.
+	 */
+	rc = rp->optee->ops->lend_rstmem(rp->optee, rp->rstmem, rp->end_points,
+					 rp->end_point_count, rp->use_case);
+	if (rc)
+		goto err_put_shm;
+	rp->rstmem->flags |= TEE_SHM_DYNAMIC;
+
+	rp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
+	if (!rp->gen_pool) {
+		rc = -ENOMEM;
+		goto err_reclaim;
+	}
+
+	rc = gen_pool_add(rp->gen_pool, rp->rstmem->paddr,
+			  rp->rstmem->size, -1);
+	if (rc)
+		goto err_free_pool;
+
+	refcount_set(&rp->refcount, 1);
+	return 0;
+
+err_free_pool:
+	gen_pool_destroy(rp->gen_pool);
+	rp->gen_pool = NULL;
+err_reclaim:
+	rp->optee->ops->reclaim_rstmem(rp->optee, rp->rstmem);
+err_put_shm:
+	tee_shm_put(rp->rstmem);
+err_null_rstmem:
+	rp->rstmem = NULL;
+	return rc;
+}
+
+static int get_cma_rstmem(struct optee_rstmem_cma_pool *rp)
+{
+	int rc = 0;
+
+	if (!refcount_inc_not_zero(&rp->refcount)) {
+		mutex_lock(&rp->mutex);
+		if (rp->gen_pool) {
+			/*
+			 * Another thread has already initialized the pool
+			 * before us, or the pool was just about to be torn
+			 * down. Either way we only need to increase the
+			 * refcount and we're done.
+			 */
+			refcount_inc(&rp->refcount);
+		} else {
+			rc = init_cma_rstmem(rp);
+		}
+		mutex_unlock(&rp->mutex);
+	}
+
+	return rc;
+}
+
+static void release_cma_rstmem(struct optee_rstmem_cma_pool *rp)
+{
+	gen_pool_destroy(rp->gen_pool);
+	rp->gen_pool = NULL;
+
+	rp->optee->ops->reclaim_rstmem(rp->optee, rp->rstmem);
+	rp->rstmem->flags &= ~TEE_SHM_DYNAMIC;
+
+	WARN(refcount_read(&rp->rstmem->refcount) != 1, "Unexpected refcount");
+	tee_shm_put(rp->rstmem);
+	rp->rstmem = NULL;
+}
+
+static void put_cma_rstmem(struct optee_rstmem_cma_pool *rp)
+{
+	if (refcount_dec_and_test(&rp->refcount)) {
+		mutex_lock(&rp->mutex);
+		if (rp->gen_pool)
+			release_cma_rstmem(rp);
+		mutex_unlock(&rp->mutex);
+	}
+}
+
+static int rstmem_pool_op_cma_alloc(struct tee_rstmem_pool *pool,
+				    struct sg_table *sgt, size_t size,
+				    size_t *offs)
+{
+	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
+	size_t sz = ALIGN(size, PAGE_SIZE);
+	phys_addr_t pa;
+	int rc;
+
+	rc = get_cma_rstmem(rp);
+	if (rc)
+		return rc;
+
+	pa = gen_pool_alloc(rp->gen_pool, sz);
+	if (!pa) {
+		rc = -ENOMEM;
+		goto err_put;
+	}
+
+	rc = sg_alloc_table(sgt, 1, GFP_KERNEL);
+	if (rc)
+		goto err_free;
+
+	sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
+	*offs = pa - rp->rstmem->paddr;
+
+	return 0;
+err_free:
+	gen_pool_free(rp->gen_pool, pa, size);
+err_put:
+	put_cma_rstmem(rp);
+
+	return rc;
+}
+
+static void rstmem_pool_op_cma_free(struct tee_rstmem_pool *pool,
+				    struct sg_table *sgt)
+{
+	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sgtable_sg(sgt, sg, i)
+		gen_pool_free(rp->gen_pool, sg_phys(sg), sg->length);
+	sg_free_table(sgt);
+	put_cma_rstmem(rp);
+}
+
+static int rstmem_pool_op_cma_update_shm(struct tee_rstmem_pool *pool,
+					 struct sg_table *sgt, size_t offs,
+					 struct tee_shm *shm,
+					 struct tee_shm **parent_shm)
+{
+	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
+
+	*parent_shm = rp->rstmem;
+
+	return 0;
+}
+
+static void pool_op_cma_destroy_pool(struct tee_rstmem_pool *pool)
+{
+	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
+
+	mutex_destroy(&rp->mutex);
+	kfree(rp);
+}
+
+static struct tee_rstmem_pool_ops rstmem_pool_ops_cma = {
+	.alloc = rstmem_pool_op_cma_alloc,
+	.free = rstmem_pool_op_cma_free,
+	.update_shm = rstmem_pool_op_cma_update_shm,
+	.destroy_pool = pool_op_cma_destroy_pool,
+};
+
+static int get_rstmem_config(struct optee *optee, u32 use_case,
+			     size_t *min_size, u_int *min_align,
+			     u16 *end_points, u_int *ep_count)
+{
+	struct tee_param params[2] = {
+		[0] = {
+			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT,
+			.u.value.a = use_case,
+		},
+		[1] = {
+			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT,
+		},
+	};
+	struct optee_shm_arg_entry *entry;
+	struct tee_shm *shm_param = NULL;
+	struct optee_msg_arg *msg_arg;
+	struct tee_shm *shm;
+	u_int offs;
+	int rc;
+
+	if (end_points && *ep_count) {
+		params[1].u.memref.size = *ep_count * sizeof(*end_points);
+		shm_param = tee_shm_alloc_priv_buf(optee->ctx,
+						   params[1].u.memref.size);
+		if (IS_ERR(shm_param))
+			return PTR_ERR(shm_param);
+		params[1].u.memref.shm = shm_param;
+	}
+
+	msg_arg = optee_get_msg_arg(optee->ctx, ARRAY_SIZE(params), &entry,
+				    &shm, &offs);
+	if (IS_ERR(msg_arg)) {
+		rc = PTR_ERR(msg_arg);
+		goto out_free_shm;
+	}
+	msg_arg->cmd = OPTEE_MSG_CMD_GET_RSTMEM_CONFIG;
+
+	rc = optee->ops->to_msg_param(optee, msg_arg->params,
+				      ARRAY_SIZE(params), params,
+				      false /*!update_out*/);
+	if (rc)
+		goto out_free_msg;
+
+	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
+	if (rc)
+		goto out_free_msg;
+	if (msg_arg->ret && msg_arg->ret != TEEC_ERROR_SHORT_BUFFER) {
+		rc = -EINVAL;
+		goto out_free_msg;
+	}
+
+	rc = optee->ops->from_msg_param(optee, params, ARRAY_SIZE(params),
+					msg_arg->params, true /*update_out*/);
+	if (rc)
+		goto out_free_msg;
+
+	if (!msg_arg->ret && end_points &&
+	    *ep_count < params[1].u.memref.size / sizeof(u16)) {
+		rc = -EINVAL;
+		goto out_free_msg;
+	}
+
+	*min_size = params[0].u.value.a;
+	*min_align = params[0].u.value.b;
+	*ep_count = params[1].u.memref.size / sizeof(u16);
+
+	if (msg_arg->ret == TEEC_ERROR_SHORT_BUFFER) {
+		rc = -ENOSPC;
+		goto out_free_msg;
+	}
+
+	if (end_points)
+		memcpy(end_points, tee_shm_get_va(shm_param, 0),
+		       params[1].u.memref.size);
+
+out_free_msg:
+	optee_free_msg_arg(optee->ctx, entry, offs);
+out_free_shm:
+	if (shm_param)
+		tee_shm_free(shm_param);
+	return rc;
+}
+
+struct tee_rstmem_pool *optee_rstmem_alloc_cma_pool(struct optee *optee,
+						    enum tee_dma_heap_id id)
+{
+	struct optee_rstmem_cma_pool *rp;
+	u32 use_case = id;
+	size_t min_size;
+	int rc;
+
+	rp = kzalloc(sizeof(*rp), GFP_KERNEL);
+	if (!rp)
+		return ERR_PTR(-ENOMEM);
+	rp->use_case = use_case;
+
+	rc = get_rstmem_config(optee, use_case, &min_size, &rp->align, NULL,
+			       &rp->end_point_count);
+	if (rc) {
+		if (rc != -ENOSPC)
+			goto err;
+		rp->end_points = kcalloc(rp->end_point_count,
+					 sizeof(*rp->end_points), GFP_KERNEL);
+		if (!rp->end_points) {
+			rc = -ENOMEM;
+			goto err;
+		}
+		rc = get_rstmem_config(optee, use_case, &min_size, &rp->align,
+				       rp->end_points, &rp->end_point_count);
+		if (rc)
+			goto err_kfree_eps;
+	}
+
+	rp->pool.ops = &rstmem_pool_ops_cma;
+	rp->optee = optee;
+	rp->page_count = min_size / PAGE_SIZE;
+	mutex_init(&rp->mutex);
+
+	return &rp->pool;
+
+err_kfree_eps:
+	kfree(rp->end_points);
+err:
+	kfree(rp);
+	return ERR_PTR(rc);
+}
-- 
2.43.0



From jens.wiklander at linaro.org  Wed Mar  5 05:04:16 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed,  5 Mar 2025 14:04:16 +0100
Subject: [PATCH v6 10/10] optee: smc abi: dynamic restricted memory allocation
In-Reply-To: <20250305130634.1850178-1-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
Message-ID: <20250305130634.1850178-11-jens.wiklander@linaro.org>

Add support in the OP-TEE backend driver for dynamic restricted memory
allocation using the SMC ABI.

Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
 drivers/tee/optee/smc_abi.c | 96 +++++++++++++++++++++++++++++++------
 1 file changed, 81 insertions(+), 15 deletions(-)

diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index a14ff0b7d3b3..aa574ee6e277 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1001,6 +1001,69 @@ static int optee_smc_do_call_with_arg(struct tee_context *ctx,
 	return rc;
 }
 
+static int optee_smc_lend_rstmem(struct optee *optee, struct tee_shm *rstmem,
+				 u16 *end_points, unsigned int ep_count,
+				 u32 use_case)
+{
+	struct optee_shm_arg_entry *entry;
+	struct optee_msg_arg *msg_arg;
+	struct tee_shm *shm;
+	u_int offs;
+	int rc;
+
+	msg_arg = optee_get_msg_arg(optee->ctx, 2, &entry, &shm, &offs);
+	if (IS_ERR(msg_arg))
+		return PTR_ERR(msg_arg);
+
+	msg_arg->cmd = OPTEE_MSG_CMD_LEND_RSTMEM;
+	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+	msg_arg->params[0].u.value.a = use_case;
+	msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+	msg_arg->params[1].u.tmem.buf_ptr = rstmem->paddr;
+	msg_arg->params[1].u.tmem.size = rstmem->size;
+	msg_arg->params[1].u.tmem.shm_ref = (u_long)rstmem;
+
+	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
+	if (rc)
+		goto out;
+	if (msg_arg->ret != TEEC_SUCCESS) {
+		rc = -EINVAL;
+		goto out;
+	}
+	rstmem->sec_world_id = (u_long)rstmem;
+
+out:
+	optee_free_msg_arg(optee->ctx, entry, offs);
+	return rc;
+}
+
+static int optee_smc_reclaim_rstmem(struct optee *optee, struct tee_shm *rstmem)
+{
+	struct optee_shm_arg_entry *entry;
+	struct optee_msg_arg *msg_arg;
+	struct tee_shm *shm;
+	u_int offs;
+	int rc;
+
+	msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
+	if (IS_ERR(msg_arg))
+		return PTR_ERR(msg_arg);
+
+	msg_arg->cmd = OPTEE_MSG_CMD_RECLAIM_RSTMEM;
+	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+	msg_arg->params[0].u.rmem.shm_ref = (u_long)rstmem;
+
+	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
+	if (rc)
+		goto out;
+	if (msg_arg->ret != TEEC_SUCCESS)
+		rc = -EINVAL;
+
+out:
+	optee_free_msg_arg(optee->ctx, entry, offs);
+	return rc;
+}
+
 /*
  * 5. Asynchronous notification
  */
@@ -1252,6 +1315,8 @@ static const struct optee_ops optee_ops = {
 	.do_call_with_arg = optee_smc_do_call_with_arg,
 	.to_msg_param = optee_to_msg_param,
 	.from_msg_param = optee_from_msg_param,
+	.lend_rstmem = optee_smc_lend_rstmem,
+	.reclaim_rstmem = optee_smc_reclaim_rstmem,
 };
 
 static int enable_async_notif(optee_invoke_fn *invoke_fn)
@@ -1622,11 +1687,13 @@ static inline int optee_load_fw(struct platform_device *pdev,
 
 static int optee_sdp_pool_init(struct optee *optee)
 {
+	bool sdp = optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP;
+	bool dyn_sdp = optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_RSTMEM;
 	enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
-	struct tee_rstmem_pool *pool;
-	int rc;
+	struct tee_rstmem_pool *pool = ERR_PTR(-EINVAL);
+	int rc = -EINVAL;
 
-	if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP) {
+	if (sdp) {
 		union {
 			struct arm_smccc_res smccc;
 			struct optee_smc_get_sdp_config_result result;
@@ -1634,25 +1701,24 @@ static int optee_sdp_pool_init(struct optee *optee)
 
 		optee->smc.invoke_fn(OPTEE_SMC_GET_SDP_CONFIG, 0, 0, 0, 0, 0, 0,
 				     0, &res.smccc);
-		if (res.result.status != OPTEE_SMC_RETURN_OK) {
-			pr_err("Secure Data Path service not available\n");
-			return 0;
-		}
+		if (res.result.status == OPTEE_SMC_RETURN_OK)
+			pool = tee_rstmem_static_pool_alloc(res.result.start,
+							    res.result.size);
+	}
 
-		pool = tee_rstmem_static_pool_alloc(res.result.start,
-						    res.result.size);
-		if (IS_ERR(pool))
-			return PTR_ERR(pool);
+	if (dyn_sdp && IS_ERR(pool))
+		pool = optee_rstmem_alloc_cma_pool(optee, heap_id);
 
+	if (!IS_ERR(pool)) {
 		rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
 		if (rc)
-			goto err;
+			pool->ops->destroy_pool(pool);
 	}
 
+	if (rc && (sdp || dyn_sdp))
+		pr_err("Secure Data Path service not available\n");
+
 	return 0;
-err:
-	pool->ops->destroy_pool(pool);
-	return rc;
 }
 
 static int optee_probe(struct platform_device *pdev)
-- 
2.43.0



From shawn.lin at rock-chips.com  Wed Mar  5 05:16:26 2025
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed,  5 Mar 2025 21:16:26 +0800
Subject: [PATCH v2] arm64: dts: rockchip: Enable ufshc on rk3576 evb1 board
Message-ID: <1741180586-140422-1-git-send-email-shawn.lin@rock-chips.com>

RK3576 evb1 board supports UFS, so enable it.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
---

 arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
index 782ca00..78efa91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts
@@ -715,6 +715,10 @@
 	status = "okay";
 };
 
+&ufshc {
+	status = "okay";
+};
+
 &usbdp_phy {
 	rockchip,dp-lane-mux = <2 3>;
 	status = "okay";
-- 
2.7.4



From s-vadapalli at ti.com  Wed Mar  5 05:20:18 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Wed, 5 Mar 2025 18:50:18 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for J784S4
Message-ID: <20250305132018.2260771-1-s-vadapalli@ti.com>

Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
to the Technical Reference Manual and Register Documentation for the J784S4
SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
the field for the link-state interrupt. Instead, it is BIT(10) of the
"PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".

Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
already reuse this macro since it accurately represents the link-state
field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.

[0]: https://www.ti.com/lit/zip/spruj52
Fixes: e49ad667815d ("PCI: j721e: Add TI J784S4 PCIe configuration")
Cc: stable at vger.kernel.org
Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---

Hello,

This patch is based on commit
48a5eed9ad58 Merge tag 'devicetree-fixes-for-6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
of the master branch of Linux.

Patch has been tested on J784S4-EVM, validating that disconnecting an
Endpoint Device connected to J784S4-EVM results in the following message
on the J784S4-EVM:
	j721e-pcie 2900000.pcie: LINK DOWN!
which wasn't seen earlier.

Regards,
Siddharth.

 drivers/pci/controller/cadence/pci-j721e.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index 0341d51d6aed..1da9d9918d0d 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -376,13 +376,13 @@ static const struct j721e_pcie_data j784s4_pcie_rc_data = {
 	.mode = PCI_MODE_RC,
 	.quirk_retrain_flag = true,
 	.byte_access_allowed = false,
-	.linkdown_irq_regfield = LINK_DOWN,
+	.linkdown_irq_regfield = J7200_LINK_DOWN,
 	.max_lanes = 4,
 };
 
 static const struct j721e_pcie_data j784s4_pcie_ep_data = {
 	.mode = PCI_MODE_EP,
-	.linkdown_irq_regfield = LINK_DOWN,
+	.linkdown_irq_regfield = J7200_LINK_DOWN,
 	.max_lanes = 4,
 };
 
-- 
2.34.1



From angelogioacchino.delregno at collabora.com  Wed Mar  5 05:25:28 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 05 Mar 2025 14:25:28 +0100
Subject: [PATCH v2 0/2] mt8395-radxa-nio-12l: Add overlay for Radxa 8HD
 panel
In-Reply-To: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
References: <20250304-radxa-panel-overlay-v2-0-3ee6797d3f86@collabora.com>
Message-ID: <174118112837.81899.67489907591418089.b4-ty@collabora.com>

On Tue, 04 Mar 2025 15:01:54 +0100, Julien Massot wrote:
> small series to enable a DSI panel on Radxa NIO 12L.
> 
> The first patch adds missing dts nodes to expose some
> feature of the DSI0 port.
> 
> The second patch adds the Radxa 8 HD panel as an overlay.
> 
> [...]

Applied to v6.14-next/dts64, thanks!

[1/2] arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI DSI port
      commit: d4642e25bede20135d84e0ffdc234b72aaa1b6ba
[2/2] arm64: dts: mediatek: mt8395-radxa-nio-12l: Add Radxa 8 HD panel
      commit: 052cb5d105721a1bb517d278a005b0a100d27a62

Cheers,
Angelo




From quic_jiegan at quicinc.com  Wed Mar  5 05:27:17 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 5 Mar 2025 21:27:17 +0800
Subject: [PATCH v15 02/10] Coresight: Add trace_id function to retrieving
 the trace ID
In-Reply-To: <CAJ9a7VgGp4YqzN-yx0x+NiZG8now6SCmnimaou2Z=exYcoiegw@mail.gmail.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-3-quic_jiegan@quicinc.com>
 <CAJ9a7VgGp4YqzN-yx0x+NiZG8now6SCmnimaou2Z=exYcoiegw@mail.gmail.com>
Message-ID: <7fe6c345-85cf-4114-b419-f50d1a6cbef1@quicinc.com>



On 3/5/2025 7:07 PM, Mike Leach wrote:
> Hi,
> 
> On Mon, 3 Mar 2025 at 03:30, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>
>> Add 'trace_id' function pointer in coresight_ops. It's responsible for retrieving
>> the device's trace ID.
>>
>> Co-developed-by: James Clark <james.clark at linaro.org>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> Reviewed-by: James Clark <james.clark at linaro.org>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>>   drivers/hwtracing/coresight/coresight-core.c  | 30 +++++++++++++++++++
>>   drivers/hwtracing/coresight/coresight-dummy.c | 13 +++++++-
>>   .../coresight/coresight-etm3x-core.c          |  1 +
>>   .../coresight/coresight-etm4x-core.c          |  1 +
>>   drivers/hwtracing/coresight/coresight-stm.c   | 11 +++++++
>>   drivers/hwtracing/coresight/coresight-tpda.c  | 11 +++++++
>>   include/linux/coresight.h                     |  5 ++++
>>   7 files changed, 71 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index ab55e10d4b79..32aa07f4f8c1 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -24,6 +24,7 @@
>>   #include "coresight-etm-perf.h"
>>   #include "coresight-priv.h"
>>   #include "coresight-syscfg.h"
>> +#include "coresight-trace-id.h"
>>
>>   /*
>>    * Mutex used to lock all sysfs enable and disable actions and loading and
>> @@ -1557,6 +1558,35 @@ void coresight_remove_driver(struct amba_driver *amba_drv,
>>   }
>>   EXPORT_SYMBOL_GPL(coresight_remove_driver);
>>
>> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
>> +                              struct coresight_device *sink)
>> +{
>> +       int trace_id;
>> +       int cpu = source_ops(csdev)->cpu_id(csdev);
>> +
> 
> This is a global funciton so need to check that this csdev is a
> source,. and does provide a cpu  function before calling it.
> 

Hi Mike,

I put this function here because it's required by etm3x and etm4x. It's 
intended to be called only by ETM devices, which are definitely source 
devices and have a cpu function.

Jie

>> +       switch (mode) {
>> +       case CS_MODE_SYSFS:
>> +               trace_id = coresight_trace_id_get_cpu_id(cpu);
>> +               break;
>> +       case CS_MODE_PERF:
>> +               if (WARN_ON(!sink))
>> +                       return -EINVAL;
>> +
>> +               trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
>> +               break;
>> +       default:
>> +               trace_id = -EINVAL;
>> +               break;
>> +       }
>> +
>> +       if (!IS_VALID_CS_TRACE_ID(trace_id))
>> +               dev_err(&csdev->dev,
>> +                       "Failed to allocate trace ID on CPU%d\n", cpu);
>> +
>> +       return trace_id;
>> +}
>> +EXPORT_SYMBOL_GPL(coresight_etm_get_trace_id);
>> +
>>   MODULE_LICENSE("GPL v2");
>>   MODULE_AUTHOR("Pratik Patel <pratikp at codeaurora.org>");
>>   MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier at linaro.org>");
>> diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
>> index 9be53be8964b..b5692ba358c1 100644
>> --- a/drivers/hwtracing/coresight/coresight-dummy.c
>> +++ b/drivers/hwtracing/coresight/coresight-dummy.c
>> @@ -41,6 +41,16 @@ static void dummy_source_disable(struct coresight_device *csdev,
>>          dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
>>   }
>>
>> +static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>> +                                __maybe_unused struct coresight_device *sink)
>> +{
>> +       struct dummy_drvdata *drvdata;
>> +
>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       return drvdata->traceid;
>> +}
>> +
>>   static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
>>                                  void *data)
>>   {
>> @@ -62,7 +72,8 @@ static const struct coresight_ops_source dummy_source_ops = {
>>   };
>>
>>   static const struct coresight_ops dummy_source_cs_ops = {
>> -       .source_ops = &dummy_source_ops,
>> +       .trace_id       = dummy_source_trace_id,
>> +       .source_ops     = &dummy_source_ops,
>>   };
>>
>>   static const struct coresight_ops_sink dummy_sink_ops = {
>> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
>> index c103f4c70f5d..c1dda4bc4a2f 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
>> @@ -704,6 +704,7 @@ static const struct coresight_ops_source etm_source_ops = {
>>   };
>>
>>   static const struct coresight_ops etm_cs_ops = {
>> +       .trace_id       = coresight_etm_get_trace_id,
>>          .source_ops     = &etm_source_ops,
>>   };
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index 2c1a60577728..cfd116b87460 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -1067,6 +1067,7 @@ static const struct coresight_ops_source etm4_source_ops = {
>>   };
>>
>>   static const struct coresight_ops etm4_cs_ops = {
>> +       .trace_id       = coresight_etm_get_trace_id,
>>          .source_ops     = &etm4_source_ops,
>>   };
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
>> index b581a30a1cd9..aca25b5e3be2 100644
>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>> @@ -281,12 +281,23 @@ static void stm_disable(struct coresight_device *csdev,
>>          }
>>   }
>>
>> +static int stm_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>> +                       __maybe_unused struct coresight_device *sink)
>> +{
>> +       struct stm_drvdata *drvdata;
>> +
>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       return drvdata->traceid;
>> +}
>> +
>>   static const struct coresight_ops_source stm_source_ops = {
>>          .enable         = stm_enable,
>>          .disable        = stm_disable,
>>   };
>>
>>   static const struct coresight_ops stm_cs_ops = {
>> +       .trace_id       = stm_trace_id,
>>          .source_ops     = &stm_source_ops,
>>   };
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
>> index 573da8427428..94c2201fc8d3 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>> @@ -241,12 +241,23 @@ static void tpda_disable(struct coresight_device *csdev,
>>          dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
>>   }
>>
>> +static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>> +                        __maybe_unused struct coresight_device *sink)
>> +{
>> +       struct tpda_drvdata *drvdata;
>> +
>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       return drvdata->atid;
>> +}
>> +
>>   static const struct coresight_ops_link tpda_link_ops = {
>>          .enable         = tpda_enable,
>>          .disable        = tpda_disable,
>>   };
>>
>>   static const struct coresight_ops tpda_cs_ops = {
>> +       .trace_id       = tpda_trace_id,
>>          .link_ops       = &tpda_link_ops,
>>   };
>>
>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>> index c7cd5886c908..ce9a5e71b261 100644
>> --- a/include/linux/coresight.h
>> +++ b/include/linux/coresight.h
>> @@ -335,6 +335,7 @@ enum cs_mode {
>>          CS_MODE_PERF,
>>   };
>>
>> +#define coresight_ops(csdev)   csdev->ops
>>   #define source_ops(csdev)      csdev->ops->source_ops
>>   #define sink_ops(csdev)                csdev->ops->sink_ops
>>   #define link_ops(csdev)                csdev->ops->link_ops
>> @@ -421,6 +422,8 @@ struct coresight_ops_panic {
>>   };
>>
>>   struct coresight_ops {
>> +       int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
>> +                       struct coresight_device *sink);
>>          const struct coresight_ops_sink *sink_ops;
>>          const struct coresight_ops_link *link_ops;
>>          const struct coresight_ops_source *source_ops;
>> @@ -709,4 +712,6 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
>>
>>   void coresight_remove_driver(struct amba_driver *amba_drv,
>>                               struct platform_driver *pdev_drv);
>> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
>> +                              struct coresight_device *sink);
>>   #endif         /* _LINUX_COREISGHT_H */
>> --
>> 2.34.1
>>
> 
> 



From geert+renesas at glider.be  Wed Mar  5 05:35:13 2025
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Wed,  5 Mar 2025 14:35:13 +0100
Subject: [PATCH] arm64: dts: renesas: r8a779f4: Add UFS tuning parameters in E-FUSE
Message-ID: <3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas@glider.be>

Describe the location in the E-FUSE block of the PLL and AFE tuning
parameters for the Universal Flash Storage controller.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
Updated DT bindings and driver code are available in "[PATCH v3 0/7]
scsi: ufs: renesas: Add support for R-Car S4-8 ES1.2"
https://lore.kernel.org/cover.1741179611.git.geert+renesas at glider.be
---
 arch/arm64/boot/dts/renesas/r8a779f4.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a779f4.dtsi b/arch/arm64/boot/dts/renesas/r8a779f4.dtsi
index ebed41892df3346c..b216d605c321c2f3 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f4.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f4.dtsi
@@ -10,3 +10,20 @@
 / {
 	compatible = "renesas,r8a779f4", "renesas,r8a779f0";
 };
+
+&fuse {
+	nvmem-layout {
+		compatible = "fixed-layout";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ufs_tune: calib at 144 {
+			reg = <0x144 0x08>;
+		};
+	};
+};
+
+&ufs {
+	nvmem-cells = <&ufs_tune>;
+	nvmem-cell-names = "calibration";
+};
-- 
2.43.0



From alyssa at rosenzweig.io  Wed Mar  5 05:43:51 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Wed, 05 Mar 2025 08:43:51 -0500
Subject: [PATCH v8 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <20250224-adpdrm-v8-0-cccf96710f0f@gmail.com>
References: <20250224-adpdrm-v8-0-cccf96710f0f@gmail.com>
Message-ID: <174118223158.156873.6982508045942987984.b4-ty@rosenzweig.io>


On Mon, 24 Feb 2025 12:02:15 +0100, Sasha Finkelstein wrote:
> This patch series adds support for a secondary display controller
> present on Apple M1/M2 chips and used to drive the display of the
> "touchbar" touch panel present on those.
> 
> 

Applied, thanks!

[1/5] dt-bindings: display: Add Apple pre-DCP display controller
      commit: 7a108b930a84e71be71c3370eef6dd96fbb8f618
[2/5] drm: adp: Add Apple Display Pipe driver
      commit: 332122eba628d537a1b7b96b976079753fd03039
[3/5] drm: panel: Add a panel driver for the Summit display
      (no commit info)
[4/5] arm64: dts: apple: Add touchbar screen nodes
      (no commit info)
[5/5] MAINTAINERS: Add entries for touchbar display driver
      commit: 4d2a877cc0efefa815648f1ed5f5b2b796f55bab

Best regards,
-- 
Alyssa Rosenzweig <alyssa at rosenzweig.io>



From fabrice.gasnier at foss.st.com  Wed Mar  5 04:51:46 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Wed, 5 Mar 2025 13:51:46 +0100
Subject: [PATCH] clocksource: stm32-lptimer: use wakeup capable instead of init wakeup
Message-ID: <20250305125146.1858978-1-fabrice.gasnier@foss.st.com>

From: Alexandre Torgue <alexandre.torgue at foss.st.com>

"wakeup-source" property describes a device which has wakeup capability
but should not force this device as a wakeup source.

Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 drivers/clocksource/timer-stm32-lp.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index 96d975adf7a4..f08baa6720f8 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -186,9 +186,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 	}
 
 	if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
-		ret = device_init_wakeup(&pdev->dev, true);
-		if (ret)
-			goto out_clk_disable;
+		device_set_wakeup_capable(&pdev->dev, true);
 
 		ret = dev_pm_set_wake_irq(&pdev->dev, irq);
 		if (ret)
-- 
2.25.1



From angelogioacchino.delregno at collabora.com  Wed Mar  5 04:55:32 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 13:55:32 +0100
Subject: [PATCH 3/3] ASoC: mediatek: mt8188-mt6359: Add headset jack
 detect support
In-Reply-To: <fc9863ef-8781-46a0-ba8c-6dabd9fb6cdf@notapiano>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
 <20250214-mt8188-accdet-v1-3-6bbd5483855b@collabora.com>
 <d976b28d-f44f-4d51-8b61-4c046c571412@collabora.com>
 <fc9863ef-8781-46a0-ba8c-6dabd9fb6cdf@notapiano>
Message-ID: <d64b11be-b516-46ab-8618-f563075064dd@collabora.com>

Il 04/03/25 21:16, N?colas F. R. A. Prado ha scritto:
> On Tue, Mar 04, 2025 at 04:39:33PM +0100, AngeloGioacchino Del Regno wrote:
>> Il 14/02/25 16:14, N?colas F. R. A. Prado ha scritto:
>>> Enable headset jack detection for MT8188 platforms using the MT6359
>>> ACCDET block for it.
>>>
>>> Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
>>> Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
>>> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
>>> ---
>>>    sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
>>>    1 file changed, 43 insertions(+)
>>>
>>> diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
>>> index 2d0d04e0232da07ba43a030b14853322427d55e7..4e19e6cfad1e1f42863b2e2f27131f880c5883bf 100644
>>> --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
>>> +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
>>> @@ -17,6 +17,7 @@
>>>    #include "mt8188-afe-common.h"
>>>    #include "../../codecs/nau8825.h"
>>>    #include "../../codecs/mt6359.h"
>>> +#include "../../codecs/mt6359-accdet.h"
>>>    #include "../../codecs/rt5682.h"
>>>    #include "../common/mtk-afe-platform-driver.h"
>>>    #include "../common/mtk-soundcard-driver.h"
>>> @@ -266,6 +267,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
>>>    	},
>>>    };
>>> +static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = {
>>
>> This is the same as nau8825_jack_pins... perhaps we could reuse that?
> 
> The difference is the pin name: "Headphone Jack", which results in a difference
> in the widget's name. I remember you wanted to not have the "Jack" in the
> widget's name to standardize it among other MTK platforms, and we could do that
> here by dropping it from the nau8825_jack_pins. But since that name is also used
> on the audio routes in a few DTs, those would need updating as well:
> 

No it's that "Jack" should be automatically appended if not present in the
jack name :-)

> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku0.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku1.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku3.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku2.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku5.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku7.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku4.dts
> arch/arm64/boot/dts/mediatek/mt8188-geralt-ciri-sku6.dts
> 
> The name is not used in upstream alsa-ucm-conf though, so it should be safe to
> update.
> 
> In any case, I didn't want to expand the scope of this series to that unrelated
> change, so that's why I introduced this separate struct, thinking we could
> commonize as a later step.
> 

That's fine for me, but are we adding unnecessary duplication?

>>
>>> +	{
>>> +		.pin    = "Headphone",
>>> +		.mask   = SND_JACK_HEADPHONE,
>>> +	},
>>> +	{
>>> +		.pin    = "Headset Mic",
>>> +		.mask   = SND_JACK_MICROPHONE,
>>> +	},
>>> +};
>>> +
>>>    static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
>>>    	SOC_DAPM_PIN_SWITCH("Ext Spk"),
>>>    };
>>> @@ -500,6 +512,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
>>>    	return 0;
>>>    }
>>> +static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd)
>>> +{
>>> +	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
>>> +	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
>>> +	int ret;
>>> +
>>> +	if (!soc_card_data->accdet)
>>> +		return 0;
>>
>> I'm not sure... if we have mediatek,accdet (so accdet is present here), but we also
>> have a NAU8825, or RT5682S, or ES8326 codec, this function will create a headset
>> jack for MT6359, but then mt8188_headset_codec_init() will do the same again!
>>
>> I think we should find a way to avoid that situation, as I'm mostly sure that this
>> will give issues in the long run.
>>
>> Even if it wouldn't, having two headset jacks exposed, of which one doesn't work
>> because it doesn't exist on the physical board... would be confusing for the user.
> 
> IMO that situation happening would mean the DT is wrong. If the board has the
> headset jack pins wired to a headset codec, and that's responsible for jack
> detection, then those pins won't be wired to the ACCDET block, and therefore the
> board DT shouldn't have the mediatek,accdet property.
> 

That might make sense.

> I think you're imagining having the mediatek,accdet property always present, and
> the logic you propose would allow specifying a headset codec to essentially
> override it (making the mediatek,accdet property useless in this case). But
> there can also be boards with no jacks at all, and in those cases we don't want
> jack widgets exposed to userspace, so the mediatek,accdet property should be
> omitted for those boards, and only present on boards where the ACCDET is
> actually wired to.
> 

I am imagining that because ACCDET is something that is always present on the
MT6359 PMIC, as it is always integrated, physically, into the silicon.

Having that always present in the PMIC DT doesn't mean that the actual sound card
node would have it, so... okay, I get the point, looks good, but it does only if

.... (scroll down)

>>
>> I guess that the best option here would be:
>>   - Let the `for_each_card_prelinks()` loop finish
>>   - Check if any of the external codecs are providing 3.5mm jack
>>     - External codec providing jack means that the detection should be performed
>>       by the external codec, as the jack should not be physically routed to the
>>       MediaTek ACCDET related PMIC pins (right?)
>>     - No external codec means that the accessory detection can only be performed
>>       by the MediaTek ACCDET IP
>>   - If external codec manages 3.5mm jack: do nothing
>>   - If no external codec managing 3.5mm jack: check if accdet provided in DT and
>>     initialize it
>>
>> ....unless I'm wrong - and if I am, please explain why (and also add explanation
>> to the commit description).
> 
> I can add to the commit message:
> 
> Only boards that have jack detection managed by the MT6359 ACCDET block will
> have the mediatek,accdet property present.

....only if you add that, because this really makes things clear - and had you
added that to the commit description in this version, I wouldn't have had this
question ;-)

So yes, please add it.

On another note, I don't understand what's the problem with using nau8825_jack_pins
instead of adding a mt8188_headset_jack_pins before you cleanup.

Really, it's just about doing:

/*
  * nau8825_jack_pins lists the exact same pin names and types as the
  * MT6359 PMIC: reuse to avoid useless duplication
  */
ret = snd_soc_card_jack_new_pins(rtd->card, .... etc etc

Cheers!

> 
> Thanks,
> N?colas
> 
>>
>> Cheers,
>> Angelo
>>
>>> +
>>> +	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
>>> +				   SND_JACK_HEADSET | SND_JACK_BTN_0 |
>>> +				   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
>>> +				   SND_JACK_BTN_3,
>>> +				   jack, mt8188_headset_jack_pins,
>>> +				   ARRAY_SIZE(mt8188_headset_jack_pins));
>>> +	if (ret) {
>>> +		dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack);
>>> +	if (ret) {
>>> +		dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
>>>    {
>>>    	struct snd_soc_component *cmpnt_codec =
>>> @@ -512,6 +553,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
>>>    	/* mtkaif calibration */
>>>    	mt8188_mt6359_mtkaif_calibration(rtd);
>>> +	mt8188_mt6359_accdet_init(rtd);
>>> +
>>>    	return 0;
>>>    }
>>>



From shradha.t at samsung.com  Wed Mar  5 01:04:39 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Wed, 5 Mar 2025 14:34:39 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250305074447.GC847772@rocinante>
References: <20250221131548.59616-1-shradha.t@samsung.com>
	<CGME20250221132035epcas5p47221a5198df9bf86020abcefdfded789@epcas5p4.samsung.com>
	<20250221131548.59616-4-shradha.t@samsung.com> <Z8XrYxP_pZr6tFU8@debian>
	<20250303194647.GC1552306@rocinante>
	<CAMuHMdWens9ZZrjNH1Bd2AN3PJEP1KSUGdiJcBCt0uPGH_GiiA@mail.gmail.com>
	<20250304154638.GB2310180@rocinante>
	<061201db8d25$dd1e2bd0$975a8370$@samsung.com>
	<20250305074447.GC847772@rocinante>
Message-ID: <065b01db8dad$a2f0a4a0$e8d1ede0$@samsung.com>



> -----Original Message-----
> From: 'Krzysztof Wilczy?ski' <kw at linux.com>
> Sent: 05 March 2025 13:15
> To: Shradha Todi <shradha.t at samsung.com>
> Cc: 'Geert Uytterhoeven' <geert at linux-m68k.org>; 'Fan Ni' <nifan.cxl at gmail.com>; linux-kernel at vger.kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org;
> lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com; jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com;
> a.manzanares at samsung.com; pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com;
> xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com; 'Yoshihiro Shimoda'
> <yoshihiro.shimoda.uh at renesas.com>; 'Linux-Renesas' <linux-renesas-soc at vger.kernel.org>
> Subject: Re: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
> 
> Hello,
> 
> > I think we shouldn't move the log level to be a WARN. I believe many
> > controllers might not support RAS DES feature in their design and
> > giving a warn dump would draw unnecessary attention.
> 
> There will be no backtrack printed with neither dev_err() nor dev_warn(), which is what we were using here.  Using dev_WARN() or
> the WARN() macro directly would be an overkill in this case, indeed.
> 

Oh sorry, I thought we were talking about WARN() here.

> > My opinion is to silently let it fail unless the user is actually
> > interested in getting the RAS DES feature up.
> 
> I think, what we have there now is fine.  We don't error on the lack of RAS DES capability when the platform does not support it,
and
> only return an error following a memory allocation failure, which should ideally never happen.
> 
> That said, have a look at the following:
> 
>   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/log/?h=controller/dwc
> 
> This is how the code looks like at the moment.
> 
> We can still move it to dev_dbg(), so basically suppress any errors or warnings from being printed outside of the debug log level,
if you
> think it would be better.
> 

No, the current version looks perfect. Thanks!

> Thank you!
> 
> 	Krzysztof




From swathi.ks at samsung.com  Wed Mar  5 01:12:44 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Wed,  5 Mar 2025 14:42:44 +0530
Subject: [PATCH v8 0/2] net: stmmac: dwc-qos: Add FSD EQoS support
References: <CGME20250305091845epcas5p1689eda3ba03572377997897271636cfd@epcas5p1.samsung.com>
Message-ID: <20250305091246.106626-1-swathi.ks@samsung.com>

FSD platform has two instances of EQoS IP, one is in FSYS0 block and
another one is in PERIC block. This patch series add required DT binding
and platform driver specific changes for the same.

Changes since v1:
1. Updated dwc_eqos_setup_rxclock() function as per the review comments
given by Andrew.

Changes since v2:
1. Addressed all the review comments suggested by Krzysztof with respect to
DT binding file.
2. Added SOB Swathi.

Changes since v3:
1. Avoided using alias-id to configure the HW.
2. Modified the clock implementation.

Changes since v4:
1. Avoided switching between internal and external clocks for every open/
close.
2. Addressed the review comments on DT bindings

Changes since v5:
1. Addressed the review comment on correcting the intendation.
2. Corrected the compatible name in dt-binding file.
3. Listed and described the clocks in dt-binding.
4. Modified FSD probe as per the changes in the refactoring patch given
below: https://lore.kernel.org/netdev/20250207121849.55815-1-swathi.ks at samsung.com/

Changes since v6:
1. Addressed review comments by Krzysztof on dt-binding file regarding
clock-names property
2. Corrected indentation issue in dt-binding
3. Addressed Andrew's comment on listing phy-modes.

Changes since v7:
1. Modified the example given in DT binding as per Russell's review
comment on setting clock tree in DT
2. Removed FSD probe since clock tree setting would be done via DT.

Here is the link to v7 patches for reference:
https://lore.kernel.org/netdev/20250220043712.31966-1-swathi.ks at samsung.com/

Swathi K S (2):
  dt-bindings: net: Add FSD EQoS device tree bindings
  net: stmmac: dwc-qos: Add FSD EQoS support

 .../devicetree/bindings/net/snps,dwmac.yaml   |   5 +-
 .../bindings/net/tesla,fsd-ethqos.yaml        | 118 ++++++++++++++++++
 .../stmicro/stmmac/dwmac-dwc-qos-eth.c        |   8 +-
 3 files changed, 128 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml

-- 
2.17.1



From swathi.ks at samsung.com  Wed Mar  5 01:12:45 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Wed,  5 Mar 2025 14:42:45 +0530
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree bindings
In-Reply-To: <20250305091246.106626-1-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
Message-ID: <20250305091246.106626-2-swathi.ks@samsung.com>

Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
Ethernet YAML schema to enable the DT validation.

Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
Signed-off-by: Swathi K S <swathi.ks at samsung.com>
---
 .../devicetree/bindings/net/snps,dwmac.yaml   |   5 +-
 .../bindings/net/tesla,fsd-ethqos.yaml        | 118 ++++++++++++++++++
 2 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml

diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 91e75eb3f329..c7004eaa8eae 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -102,6 +102,7 @@ properties:
         - snps,dwxgmac-2.10
         - starfive,jh7100-dwmac
         - starfive,jh7110-dwmac
+        - tesla,fsd-ethqos
         - thead,th1520-gmac
 
   reg:
@@ -126,7 +127,7 @@ properties:
 
   clocks:
     minItems: 1
-    maxItems: 8
+    maxItems: 10
     additionalItems: true
     items:
       - description: GMAC main clock
@@ -138,7 +139,7 @@ properties:
 
   clock-names:
     minItems: 1
-    maxItems: 8
+    maxItems: 10
     additionalItems: true
     contains:
       enum:
diff --git a/Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml b/Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml
new file mode 100644
index 000000000000..dd7481bb16e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/tesla,fsd-ethqos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: FSD Ethernet Quality of Service
+
+maintainers:
+  - Swathi K S <swathi.ks at samsung.com>
+
+description:
+  Tesla ethernet devices based on dwmmac support Gigabit ethernet.
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+
+properties:
+  compatible:
+    const: tesla,fsd-ethqos
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    items:
+      - const: macirq
+
+  clocks:
+    minItems: 5
+    items:
+      - description: PTP clock
+      - description: Master bus clock
+      - description: Slave bus clock
+      - description: MAC TX clock
+      - description: MAC RX clock
+      - description: Master2 bus clock
+      - description: Slave2 bus clock
+      - description: RX MUX clock
+      - description: PHY RX clock
+      - description: PERIC RGMII clock
+
+  clock-names:
+    minItems: 5
+    items:
+      - const: ptp_ref
+      - const: master_bus
+      - const: slave_bus
+      - const: tx
+      - const: rx
+      - const: master2_bus
+      - const: slave2_bus
+      - const: eqos_rxclk_mux
+      - const: eqos_phyrxclk
+      - const: dout_peric_rgmii_clk
+
+  iommus:
+    maxItems: 1
+
+  phy-mode:
+    enum:
+      - rgmii
+      - rgmii-id
+      - rgmii-rxid
+      - rgmii-txid
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - iommus
+  - phy-mode
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/fsd-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        ethernet1: ethernet at 14300000 {
+            compatible = "tesla,fsd-ethqos";
+            reg = <0x0 0x14300000 0x0 0x10000>;
+            interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "macirq";
+            clocks = <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I>,
+                     <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_ACLK_I>,
+                     <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_HCLK_I>,
+                     <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_RGMII_CLK_I>,
+                     <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_RX_I>,
+                     <&clock_peric PERIC_BUS_D_PERIC_IPCLKPORT_EQOSCLK>,
+                     <&clock_peric PERIC_BUS_P_PERIC_IPCLKPORT_EQOSCLK>,
+                     <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
+                     <&clock_peric PERIC_EQOS_PHYRXCLK>,
+                     <&clock_peric PERIC_DOUT_RGMII_CLK>;
+            clock-names = "ptp_ref", "master_bus", "slave_bus","tx",
+                          "rx", "master2_bus", "slave2_bus", "eqos_rxclk_mux",
+                          "eqos_phyrxclk","dout_peric_rgmii_clk";
+            assigned-clocks = <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
+                              <&clock_peric PERIC_EQOS_PHYRXCLK>;
+            assigned-clock-parents = <&clock_peric PERIC_EQOS_PHYRXCLK>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&eth1_tx_clk>, <&eth1_tx_data>, <&eth1_tx_ctrl>,
+                        <&eth1_phy_intr>, <&eth1_rx_clk>, <&eth1_rx_data>,
+                        <&eth1_rx_ctrl>, <&eth1_mdio>;
+            iommus = <&smmu_peric 0x0 0x1>;
+            phy-mode = "rgmii-id";
+        };
+    };
+
+...
-- 
2.17.1



From swathi.ks at samsung.com  Wed Mar  5 01:12:46 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Wed,  5 Mar 2025 14:42:46 +0530
Subject: [PATCH v8 2/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <20250305091246.106626-1-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091856epcas5p4228c09989c7acfe45a99541eef01fbcd@epcas5p4.samsung.com>
Message-ID: <20250305091246.106626-3-swathi.ks@samsung.com>

The FSD SoC contains two instance of the Synopsys DWC ethernet QOS IP core.
The binding that it uses is slightly different from existing ones because
of the integration (clocks, resets).

Signed-off-by: Swathi K S <swathi.ks at samsung.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 6cadf24a575c..e9038d015cf0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -325,6 +325,10 @@ static const struct dwc_eth_dwmac_data tegra_eqos_data = {
 	.stmmac_clk_name = "slave_bus",
 };
 
+static const struct dwc_eth_dwmac_data fsd_eqos_data = {
+	.stmmac_clk_name = "slave_bus",
+};
+
 static int dwc_eth_dwmac_probe(struct platform_device *pdev)
 {
 	const struct dwc_eth_dwmac_data *data;
@@ -365,7 +369,8 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev)
 	plat_dat->stmmac_clk = dwc_eth_find_clk(plat_dat,
 						data->stmmac_clk_name);
 
-	ret = data->probe(pdev, plat_dat, &stmmac_res);
+	if (data->probe)
+		ret = data->probe(pdev, plat_dat, &stmmac_res);
 	if (ret < 0) {
 		dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n");
 		clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks);
@@ -406,6 +411,7 @@ static void dwc_eth_dwmac_remove(struct platform_device *pdev)
 static const struct of_device_id dwc_eth_dwmac_match[] = {
 	{ .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
 	{ .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
+	{ .compatible = "tesla,fsd-ethqos", .data = &fsd_eqos_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
-- 
2.17.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:15 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:15 -0500
Subject: [PATCH iwl-next v8 00/11] igc: Add support for Frame Preemption feature in IGC
Message-ID: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>

Introduces support for the FPE feature in the IGC driver.

The patches aligns with the upstream FPE API:
https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.oltean at nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.oltean at nxp.com/

It builds upon earlier work:
https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.1098888-1-vinicius.gomes at intel.com/

The patch series adds the following functionalities to the IGC driver:
a) Configure FPE using `ethtool --set-mm`.
b) Display FPE settings via `ethtool --show-mm`.
c) View FPE statistics using `ethtool --include-statistics --show-mm'.
e) Block setting preemptible tc in taprio since it is not supported yet.
   Existing code already blocks it in mqprio.

Tested:
Enabled CONFIG_PROVE_LOCKING, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_DMA_API_DEBUG, and CONFIG_KASAN
1) selftests
2) netdev down/up cycles
3) suspend/resume cycles
4) fpe verification

No bugs or unusual dmesg logs were observed.
Ran 1), 2) and 3) with and without the patch series, compared dmesg and selftest logs ? no differences found.

Change Log:
v7 -> v8:
- Reject SMD-V and SMD-R if the payload contains non-zero values (Vladimir, Chwee Lin)
- Move resetting verification state when link is down to a new patch 3/11 (Vladimir)
- Move frag_size related handling outside of spin_lock_irq_save(), patch 1/11 (Vladimir)
- Renamed IGC_PRMEXPRCNT to IGC_PRMEXCPRCNT, to align with i226 SW User Manual, patch 11/11 (Chwee Lin)
- Use IGC_PRMEXPRCNT_OOO_SMDC for frame smd errors instead of frame assembly errors, 11/11 (Chwee Lin)

v6 -> v7:
- Squash the cpu param to the prev line (Przemek Kitszel)
- Use igc_ prefix for fpe_t (Przemek Kitszel)
- Move new ops to different line in igc_ethtool_ops (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): rx -> Rx (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): s/IGC/the driver/ (Przemek Kitszel)
- Change preferred style of init, from { }, to {} (Przemek Kitszel)
- Remove inclusion of umbrella header <linux/kernel.h> in igc_tsn.c (Przemek Kitszel)
- End enum with "," in igc_txd_popts_type (Przemek Kitszel)
- Remove unnecessary braces in igc_fpe_is_verify_or_response() (Przemek Kitszel)

v5 -> v6:
- Added Tested-by: Furong Xu for patch 1/9 (Vladimir, Furong Xu)
- Updated logic in ethtool_mmsv_link_state_handle() (Vladimir, Furong Xu)
- Swap sequence of function call in stmmac_set_mm() (Furong Xu)
- Log an error if igc_enable_empty_addr_recv() fails (Vladimir)
- Move the patch ".. Block setting preemptible traffic .." before ".. Add support to get MAC Merge data .." (Vladimir)
- Move mmsv function kernel-doc from .h to .c file (Vladimir)

v4 -> v5:
- Remove "igc: Add support for preemptible traffic class in taprio" patch (Vladimir)
- Add a new patch "igc: Block setting preemptible traffic classes in taprio" (Vladimir)
- Add kernel-doc for mmsv api (Vladimir)
- olininfo_status to use host byte order (Simon)
- status_error should host byte type (Simon)
- Some code was misplaced in the wrong patch (Vladimir)
- Mix of tabs and spaces in patch description (Vladimir)
- Created igc_is_pmac_enabled() to reduce code repetition (Vladimir)

v3 -> v4:
- Fix compilation warnings introduced by this patch series

v2 -> v3:
- Implement configure_tx() mmsv callback (Vladimir)
- Use static_branch_inc() and static_branch_dec() (Vladimir)
- Add adapter->fpe.mmsv.pmac_enabled as extra check (Vladimir)
- Remove unnecessary error check in igc_fpe_init_tx_descriptor() (Vladimir)
- Additional places to use FIELD_PREP() instead of manual bit manipulation (Vladimir)
- IGC_TXD_POPTS_SMD_V and IGC_TXD_POPTS_SMD_R type change to enum (Vladimir)
- Remove unnecessary netif_running() check in igc_fpe_xmit_frame (Vladimir)
- Rate limit print in igc_fpe_send_mpacket (Vladimir)

v1 -> v2:
- Extract the stmmac verification logic into a common library (Vladimir)
- igc to use common library for verification (Vladimir)
- Fix syntax for kernel-doc to use "Return:" (Vladimir)
- Use FIELD_GET instead of manual bit masking (Vladimir)
- Don't assign 0 to statistics counter in igc_ethtool_get_mm_stats() (Vladimir)
- Use pmac-enabled as a condition to allow MAC address value 0 (Vladimir)
- Define macro register value in increasing value order (Vladimir)
- Fix tx-min-frag-size handling for igc (Vladimir)
- Handle link state changes with verification in igc (Vladimir)
- Add static key for fast path code (Vladimir)
- rx_min_frag_size get from constant (Vladimir)

v1: https://patchwork.kernel.org/project/netdevbpf/cover/20241216064720.931522-1-faizal.abdul.rahim at linux.intel.com/
v2: https://patchwork.kernel.org/project/netdevbpf/cover/20250205100524.1138523-1-faizal.abdul.rahim at linux.intel.com/
v3: https://patchwork.kernel.org/project/netdevbpf/cover/20250207165649.2245320-1-faizal.abdul.rahim at linux.intel.com/
v4: https://patchwork.kernel.org/project/netdevbpf/cover/20250210070207.2615418-1-faizal.abdul.rahim at linux.intel.com/
v5: https://patchwork.kernel.org/project/netdevbpf/cover/20250220025349.3007793-1-faizal.abdul.rahim at linux.intel.com/
v6: https://patchwork.kernel.org/project/netdevbpf/cover/20250227140158.2129988-1-faizal.abdul.rahim at linux.intel.com/
v7: https://patchwork.kernel.org/project/netdevbpf/cover/20250303102658.3580232-1-faizal.abdul.rahim at linux.intel.com/

Faizal Rahim (10):
  net: stmmac: move frag_size handling out of spin_lock
  net: ethtool: mm: reset verification status when link is down
  igc: rename xdp_get_tx_ring() for non-xdp usage
  igc: optimize the TX packet buffer utilization
  igc: set the RX packet buffer size for TSN mode
  igc: add support for frame preemption verification
  igc: add support to set tx-min-frag-size
  igc: block setting preemptible traffic class in taprio
  igc: add support to get MAC Merge data via ethtool
  igc: add support to get frame preemption statistics via ethtool

Vladimir Oltean (1):
  net: ethtool: mm: extract stmmac verification logic into common
    library

 drivers/net/ethernet/intel/igc/igc.h          |  15 +-
 drivers/net/ethernet/intel/igc/igc_base.h     |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h  |  15 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |  79 +++++
 drivers/net/ethernet/intel/igc/igc_main.c     |  66 +++-
 drivers/net/ethernet/intel/igc/igc_regs.h     |  16 +
 drivers/net/ethernet/intel/igc/igc_tsn.c      | 192 +++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h      |  54 ++++
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  41 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 281 +++++++++++++++++-
 15 files changed, 819 insertions(+), 217 deletions(-)

--
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:16 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:16 -0500
Subject: [PATCH iwl-next v8 01/11] net: stmmac: move frag_size handling out of spin_lock
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>

The upcoming patch will extract verification logic into a new module,
MMSV (MAC Merge Software Verification). MMSV will handle most FPE fields,
except frag_size. It introduces its own lock (mmsv->lock), replacing
fpe_cfg->lock.

Since frag_size handling remains in the driver, the existing rtnl_lock()
is sufficient. Move frag_size handling out of spin_lock_irq_save() to keep
the upcoming patch a pure refactoring without behavior changes.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 918a32f8fda8..cfe5aea24549 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1216,6 +1216,10 @@ static int stmmac_get_mm(struct net_device *ndev,
 	if (!stmmac_fpe_supported(priv))
 		return -EOPNOTSUPP;
 
+	state->rx_min_frag_size = ETH_ZLEN;
+	frag_size = stmmac_fpe_get_add_frag_size(priv);
+	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
+
 	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
 
 	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
@@ -1224,7 +1228,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	state->verify_time = priv->fpe_cfg.verify_time;
 	state->tx_enabled = priv->fpe_cfg.tx_enabled;
 	state->verify_status = priv->fpe_cfg.status;
-	state->rx_min_frag_size = ETH_ZLEN;
 
 	/* FPE active if common tx_enabled and
 	 * (verification success or disabled(forced))
@@ -1236,9 +1239,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	else
 		state->tx_active = false;
 
-	frag_size = stmmac_fpe_get_add_frag_size(priv);
-	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
-
 	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
 
 	return 0;
@@ -1258,6 +1258,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (err)
 		return err;
 
+	stmmac_fpe_set_add_frag_size(priv, frag_size);
+
 	/* Wait for the verification that's currently in progress to finish */
 	timer_shutdown_sync(&fpe_cfg->verify_timer);
 
@@ -1271,7 +1273,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (!cfg->verify_enabled)
 		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
 
-	stmmac_fpe_set_add_frag_size(priv, frag_size);
 	stmmac_fpe_apply(priv);
 
 	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:17 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:17 -0500
Subject: [PATCH iwl-next v8 02/11] net: ethtool: mm: extract stmmac verification logic into common library
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-3-faizal.abdul.rahim@linux.intel.com>

From: Vladimir Oltean <vladimir.oltean at nxp.com>

It appears that stmmac is not the only hardware which requires a
software-driven verification state machine for the MAC Merge layer.

While on the one hand it's good to encourage hardware implementations,
on the other hand it's quite difficult to tolerate multiple drivers
implementing independently fairly non-trivial logic.

Extract the hardware-independent logic from stmmac into library code and
put it in ethtool. Name the state structure "mmsv" for MAC Merge
Software Verification. Let this expose an operations structure for
executing the hardware stuff: sync hardware with the tx_active boolean
(result of verification process), enable/disable the pMAC, send mPackets,
notify library of external events (reception of mPackets), as well as
link state changes.

Note that it is assumed that the external events are received in hardirq
context. If they are not, it is probably a good idea to disable hardirqs
when calling ethtool_mmsv_event_handle(), because the library does not
do so.

Also, the MM software verification process has no business with the
tx_min_frag_size, that is all the driver's to handle.

Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Co-developed-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Tested-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Furong Xu <0x1207 at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  42 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 278 +++++++++++++++++-
 7 files changed, 394 insertions(+), 202 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index f05cae103d83..c9cc41af258a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -147,21 +147,9 @@ struct stmmac_channel {
 };
 
 struct stmmac_fpe_cfg {
-	/* Serialize access to MAC Merge state between ethtool requests
-	 * and link state updates.
-	 */
-	spinlock_t lock;
-
+	struct ethtool_mmsv mmsv;
 	const struct stmmac_fpe_reg *reg;
-	u32 fpe_csr;				/* MAC_FPE_CTRL_STS reg cache */
-
-	enum ethtool_mm_verify_status status;
-	struct timer_list verify_timer;
-	bool verify_enabled;
-	int verify_retries;
-	bool pmac_enabled;
-	u32 verify_time;
-	bool tx_enabled;
+	u32 fpe_csr;	/* MAC_FPE_CTRL_STS reg cache */
 };
 
 struct stmmac_tc_entry {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index cfe5aea24549..44ee73569cb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1210,7 +1210,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 			 struct ethtool_mm_state *state)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long flags;
 	u32 frag_size;
 
 	if (!stmmac_fpe_supported(priv))
@@ -1220,26 +1219,7 @@ static int stmmac_get_mm(struct net_device *ndev,
 	frag_size = stmmac_fpe_get_add_frag_size(priv);
 	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
 
-	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
-
-	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	state->verify_enabled = priv->fpe_cfg.verify_enabled;
-	state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
-	state->verify_time = priv->fpe_cfg.verify_time;
-	state->tx_enabled = priv->fpe_cfg.tx_enabled;
-	state->verify_status = priv->fpe_cfg.status;
-
-	/* FPE active if common tx_enabled and
-	 * (verification success or disabled(forced))
-	 */
-	if (state->tx_enabled &&
-	    (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
-	     state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
-		state->tx_active = true;
-	else
-		state->tx_active = false;
-
-	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
+	ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
 
 	return 0;
 }
@@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 			 struct netlink_ext_ack *extack)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
 	u32 frag_size;
 	int err;
 
@@ -1259,23 +1237,7 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 		return err;
 
 	stmmac_fpe_set_add_frag_size(priv, frag_size);
-
-	/* Wait for the verification that's currently in progress to finish */
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	fpe_cfg->verify_enabled = cfg->verify_enabled;
-	fpe_cfg->pmac_enabled = cfg->pmac_enabled;
-	fpe_cfg->verify_time = cfg->verify_time;
-	fpe_cfg->tx_enabled = cfg->tx_enabled;
-
-	if (!cfg->verify_enabled)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-
-	stmmac_fpe_apply(priv);
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+	ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index 3a4bee029c7f..75b470ee621a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -27,12 +27,6 @@
 #define STMMAC_MAC_FPE_CTRL_STS_SVER	BIT(1)
 #define STMMAC_MAC_FPE_CTRL_STS_EFPE	BIT(0)
 
-/* FPE link-partner hand-shaking mPacket type */
-enum stmmac_mpacket_type {
-	MPACKET_VERIFY = 0,
-	MPACKET_RESPONSE = 1,
-};
-
 struct stmmac_fpe_reg {
 	const u32 mac_fpe_reg;		/* offset of MAC_FPE_CTRL_STS */
 	const u32 mtl_fpe_reg;		/* offset of MTL_FPE_CTRL_STS */
@@ -48,10 +42,10 @@ bool stmmac_fpe_supported(struct stmmac_priv *priv)
 		priv->hw->mac->fpe_map_preemption_class;
 }
 
-static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
-				 bool pmac_enable)
+static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
 {
-	struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
 	const struct stmmac_fpe_reg *reg = cfg->reg;
 	u32 num_rxq = priv->plat->rx_queues_to_use;
 	void __iomem *ioaddr = priv->ioaddr;
@@ -68,6 +62,15 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 		cfg->fpe_csr = 0;
 	}
 	writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
+}
+
+static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
+{
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
+	void __iomem *ioaddr = priv->ioaddr;
+	u32 value;
 
 	value = readl(ioaddr + reg->int_en_reg);
 
@@ -85,47 +88,45 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 	writel(value, ioaddr + reg->int_en_reg);
 }
 
-static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
-				    enum stmmac_mpacket_type type)
+static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				    enum ethtool_mpacket type)
 {
-	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
 	void __iomem *ioaddr = priv->ioaddr;
-	u32 value = priv->fpe_cfg.fpe_csr;
+	u32 value = cfg->fpe_csr;
 
-	if (type == MPACKET_VERIFY)
+	if (type == ETHTOOL_MPACKET_VERIFY)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
-	else if (type == MPACKET_RESPONSE)
+	else if (type == ETHTOOL_MPACKET_RESPONSE)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
 
 	writel(value, ioaddr + reg->mac_fpe_reg);
 }
 
+static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
+	.configure_tx = stmmac_fpe_configure_tx,
+	.configure_pmac = stmmac_fpe_configure_pmac,
+	.send_mpacket = stmmac_fpe_send_mpacket,
+};
+
 static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
 {
 	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+	struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv;
 
-	/* This is interrupt context, just spin_lock() */
-	spin_lock(&fpe_cfg->lock);
-
-	if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
-		goto unlock_out;
+	if (status == FPE_EVENT_UNKNOWN)
+		return;
 
-	/* LP has sent verify mPacket */
 	if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
-		stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
 
-	/* Local has sent verify mPacket */
-	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
 
-	/* LP has sent response mPacket */
-	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
-	    fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
-
-unlock_out:
-	spin_unlock(&fpe_cfg->lock);
+	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
 }
 
 void stmmac_fpe_irq_status(struct stmmac_priv *priv)
@@ -164,119 +165,16 @@ void stmmac_fpe_irq_status(struct stmmac_priv *priv)
 	stmmac_fpe_event_status(priv, status);
 }
 
-/**
- * stmmac_fpe_verify_timer - Timer for MAC Merge verification
- * @t:  timer_list struct containing private info
- *
- * Verify the MAC Merge capability in the local TX direction, by
- * transmitting Verify mPackets up to 3 times. Wait until link
- * partner responds with a Response mPacket, otherwise fail.
- */
-static void stmmac_fpe_verify_timer(struct timer_list *t)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
-	struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
-						fpe_cfg);
-	unsigned long flags;
-	bool rearm = false;
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	switch (fpe_cfg->status) {
-	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
-	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
-		if (fpe_cfg->verify_retries != 0) {
-			stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
-			rearm = true;
-		} else {
-			fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
-		}
-
-		fpe_cfg->verify_retries--;
-		break;
-
-	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
-		stmmac_fpe_configure(priv, true, true);
-		break;
-
-	default:
-		break;
-	}
-
-	if (rearm) {
-		mod_timer(&fpe_cfg->verify_timer,
-			  jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
-static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
-{
-	if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
-	    fpe_cfg->verify_enabled &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
-		timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
-		mod_timer(&fpe_cfg->verify_timer, jiffies);
-	}
-}
-
 void stmmac_fpe_init(struct stmmac_priv *priv)
 {
-	priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-	priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-	timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
-	spin_lock_init(&priv->fpe_cfg.lock);
+	ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev,
+			  &stmmac_mmsv_ops);
 
 	if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
 	    priv->dma_cap.fpesel)
 		dev_info(priv->device, "FPE is not supported by driver.\n");
 }
 
-void stmmac_fpe_apply(struct stmmac_priv *priv)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
-	/* If verification is disabled, configure FPE right away.
-	 * Otherwise let the timer code do it.
-	 */
-	if (!fpe_cfg->verify_enabled) {
-		stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
-				     fpe_cfg->pmac_enabled);
-	} else {
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
-		fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-
-		if (netif_running(priv->dev))
-			stmmac_fpe_verify_timer_arm(fpe_cfg);
-	}
-}
-
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
-
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	if (is_up && fpe_cfg->pmac_enabled) {
-		/* VERIFY process requires pmac enabled when NIC comes up */
-		stmmac_fpe_configure(priv, false, true);
-
-		/* New link => maybe new partner => new verification process */
-		stmmac_fpe_apply(priv);
-	} else {
-		/* No link => turn off EFPE */
-		stmmac_fpe_configure(priv, false, false);
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
 {
 	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
index b884eac7142d..3fc46acf7001 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
@@ -9,15 +9,10 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 
-#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES	3
-#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS	128
-
 struct stmmac_priv;
 
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
 bool stmmac_fpe_supported(struct stmmac_priv *priv);
 void stmmac_fpe_init(struct stmmac_priv *priv);
-void stmmac_fpe_apply(struct stmmac_priv *priv);
 void stmmac_fpe_irq_status(struct stmmac_priv *priv);
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
 void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d04543e5697b..8f723f9e84ba 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -992,7 +992,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, false);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, false);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, false);
 }
 
 static void stmmac_mac_link_up(struct phylink_config *config,
@@ -1100,7 +1100,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, true);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, true);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, true);
 
 	if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
 		stmmac_hwtstamp_correct_latency(priv, priv);
@@ -4097,7 +4097,7 @@ static int stmmac_release(struct net_device *dev)
 	stmmac_release_ptp(priv);
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	pm_runtime_put(priv->device);
 
@@ -7822,7 +7822,7 @@ int stmmac_suspend(struct device *dev)
 	rtnl_unlock();
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	priv->speed = SPEED_UNKNOWN;
 	return 0;
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 870994cc3ef7..b4b8eaf1f256 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -17,9 +17,13 @@
 #include <linux/compat.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
+#include <linux/timer_types.h>
 #include <uapi/linux/ethtool.h>
 #include <uapi/linux/net_tstamp.h>
 
+#define ETHTOOL_MM_MAX_VERIFY_TIME_MS		128
+#define ETHTOOL_MM_MAX_VERIFY_RETRIES		3
+
 struct compat_ethtool_rx_flow_spec {
 	u32		flow_type;
 	union ethtool_flow_union h_u;
@@ -710,6 +714,75 @@ struct ethtool_mm_stats {
 	u64 MACMergeHoldCount;
 };
 
+enum ethtool_mmsv_event {
+	ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET,
+};
+
+/* MAC Merge verification mPacket type */
+enum ethtool_mpacket {
+	ETHTOOL_MPACKET_VERIFY,
+	ETHTOOL_MPACKET_RESPONSE,
+};
+
+struct ethtool_mmsv;
+
+/**
+ * struct ethtool_mmsv_ops - Operations for MAC Merge Software Verification
+ * @configure_tx: Driver callback for the event where the preemptible TX
+ *		  becomes active or inactive. Preemptible traffic
+ *		  classes must be committed to hardware only while
+ *		  preemptible TX is active.
+ * @configure_pmac: Driver callback for the event where the pMAC state
+ *		    changes as result of an administrative setting
+ *		    (ethtool) or a call to ethtool_mmsv_link_state_handle().
+ * @send_mpacket: Driver-provided method for sending a Verify or a Response
+ *		  mPacket.
+ */
+struct ethtool_mmsv_ops {
+	void (*configure_tx)(struct ethtool_mmsv *mmsv, bool tx_active);
+	void (*configure_pmac)(struct ethtool_mmsv *mmsv, bool pmac_enabled);
+	void (*send_mpacket)(struct ethtool_mmsv *mmsv, enum ethtool_mpacket mpacket);
+};
+
+/**
+ * struct ethtool_mmsv - MAC Merge Software Verification
+ * @ops: operations for MAC Merge Software Verification
+ * @dev: pointer to net_device structure
+ * @lock: serialize access to MAC Merge state between
+ *	  ethtool requests and link state updates.
+ * @status: current verification FSM state
+ * @verify_timer: timer for verification in local TX direction
+ * @verify_enabled: indicates if verification is enabled
+ * @verify_retries: number of retries for verification
+ * @pmac_enabled: indicates if the preemptible MAC is enabled
+ * @verify_time: time for verification in milliseconds
+ * @tx_enabled: indicates if transmission is enabled
+ */
+struct ethtool_mmsv {
+	const struct ethtool_mmsv_ops *ops;
+	struct net_device *dev;
+	spinlock_t lock;
+	enum ethtool_mm_verify_status status;
+	struct timer_list verify_timer;
+	bool verify_enabled;
+	int verify_retries;
+	bool pmac_enabled;
+	u32 verify_time;
+	bool tx_enabled;
+};
+
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv);
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up);
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event);
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state);
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg);
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops);
+
 /**
  * struct ethtool_rxfh_param - RXFH (RSS) parameters
  * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index 2816bb23c3ad..aa43df2ecac0 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright 2022-2023 NXP
+ * Copyright 2022-2025 NXP
+ * Copyright 2024 Furong Xu <0x1207 at gmail.com>
  */
 #include "common.h"
 #include "netlink.h"
@@ -282,3 +283,278 @@ bool ethtool_dev_mm_supported(struct net_device *dev)
 	return supported;
 }
 EXPORT_SYMBOL_GPL(ethtool_dev_mm_supported);
+
+static void ethtool_mmsv_configure_tx(struct ethtool_mmsv *mmsv,
+				      bool tx_active)
+{
+	if (mmsv->ops->configure_tx)
+		mmsv->ops->configure_tx(mmsv, tx_active);
+}
+
+static void ethtool_mmsv_configure_pmac(struct ethtool_mmsv *mmsv,
+					bool pmac_enabled)
+{
+	if (mmsv->ops->configure_pmac)
+		mmsv->ops->configure_pmac(mmsv, pmac_enabled);
+}
+
+static void ethtool_mmsv_send_mpacket(struct ethtool_mmsv *mmsv,
+				      enum ethtool_mpacket mpacket)
+{
+	if (mmsv->ops->send_mpacket)
+		mmsv->ops->send_mpacket(mmsv, mpacket);
+}
+
+/**
+ * ethtool_mmsv_verify_timer - Timer for MAC Merge verification
+ * @t: timer_list struct containing private info
+ *
+ * Verify the MAC Merge capability in the local TX direction, by
+ * transmitting Verify mPackets up to 3 times. Wait until link
+ * partner responds with a Response mPacket, otherwise fail.
+ */
+static void ethtool_mmsv_verify_timer(struct timer_list *t)
+{
+	struct ethtool_mmsv *mmsv = from_timer(mmsv, t, verify_timer);
+	unsigned long flags;
+	bool rearm = false;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	switch (mmsv->status) {
+	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+		if (mmsv->verify_retries != 0) {
+			ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_VERIFY);
+			rearm = true;
+		} else {
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+		}
+
+		mmsv->verify_retries--;
+		break;
+
+	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+		ethtool_mmsv_configure_tx(mmsv, true);
+		break;
+
+	default:
+		break;
+	}
+
+	if (rearm) {
+		mod_timer(&mmsv->verify_timer,
+			  jiffies + msecs_to_jiffies(mmsv->verify_time));
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+
+static void ethtool_mmsv_verify_timer_arm(struct ethtool_mmsv *mmsv)
+{
+	if (mmsv->pmac_enabled && mmsv->tx_enabled && mmsv->verify_enabled &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
+		timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+		mod_timer(&mmsv->verify_timer, jiffies);
+	}
+}
+
+static void ethtool_mmsv_apply(struct ethtool_mmsv *mmsv)
+{
+	/* If verification is disabled, configure FPE right away.
+	 * Otherwise let the timer code do it.
+	 */
+	if (!mmsv->verify_enabled) {
+		ethtool_mmsv_configure_pmac(mmsv, mmsv->pmac_enabled);
+		ethtool_mmsv_configure_tx(mmsv, mmsv->tx_enabled);
+	} else {
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+
+		if (netif_running(mmsv->dev))
+			ethtool_mmsv_verify_timer_arm(mmsv);
+	}
+}
+
+/**
+ * ethtool_mmsv_stop() - Stop MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ *
+ * Drivers should call this method in a state where the hardware is
+ * about to lose state, like ndo_stop() or suspend(), and turning off
+ * MAC Merge features would be superfluous. Otherwise, prefer
+ * ethtool_mmsv_link_state_handle() with up=false.
+ */
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv)
+{
+	timer_shutdown_sync(&mmsv->verify_timer);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_stop);
+
+/**
+ * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification
+ *				      of link state changes
+ * @mmsv: MAC Merge Software Verification state
+ * @up: True if device carrier is up and able to pass verification packets
+ *
+ * Calling context is expected to be from a task, interrupts enabled.
+ */
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
+{
+	unsigned long flags;
+
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	if (up && mmsv->pmac_enabled) {
+		/* VERIFY process requires pMAC enabled when NIC comes up */
+		ethtool_mmsv_configure_pmac(mmsv, true);
+
+		/* New link => maybe new partner => new verification process */
+		ethtool_mmsv_apply(mmsv);
+	} else {
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+
+		/* No link or pMAC not enabled */
+		ethtool_mmsv_configure_pmac(mmsv, false);
+		ethtool_mmsv_configure_tx(mmsv, false);
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle);
+
+/**
+ * ethtool_mmsv_event_handle() - Inform MAC Merge Software Verification
+ *				 of interrupt-based events
+ * @mmsv: MAC Merge Software Verification state
+ * @event: Event which took place (packet transmission or reception)
+ *
+ * Calling context expects to have interrupts disabled.
+ */
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event)
+{
+	/* This is interrupt context, just spin_lock() */
+	spin_lock(&mmsv->lock);
+
+	if (!mmsv->pmac_enabled)
+		goto unlock;
+
+	switch (event) {
+	case ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET:
+		/* Link partner has sent verify mPacket */
+		ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_RESPONSE);
+		break;
+	case ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET:
+		/* Local device has sent verify mPacket */
+		if (mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+		break;
+	case ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET:
+		/* Link partner has sent response mPacket */
+		if (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+		break;
+	}
+
+unlock:
+	spin_unlock(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_event_handle);
+
+static bool ethtool_mmsv_is_tx_active(struct ethtool_mmsv *mmsv)
+{
+	/* TX is active if administratively enabled, and verification either
+	 * succeeded, or was administratively disabled.
+	 */
+	return mmsv->tx_enabled &&
+	       (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
+	       mmsv->status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
+}
+
+/**
+ * ethtool_mmsv_get_mm() - get_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @state: see struct ethtool_mm_state
+ *
+ * Drivers are expected to call this from their ethtool_ops :: get_mm()
+ * method.
+ */
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	state->verify_enabled = mmsv->verify_enabled;
+	state->pmac_enabled = mmsv->pmac_enabled;
+	state->verify_time = mmsv->verify_time;
+	state->tx_enabled = mmsv->tx_enabled;
+	state->verify_status = mmsv->status;
+	state->tx_active = ethtool_mmsv_is_tx_active(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_get_mm);
+
+/**
+ * ethtool_mmsv_set_mm() - set_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @cfg: see struct ethtool_mm_cfg
+ *
+ * Drivers are expected to call this from their ethtool_ops :: set_mm()
+ * method.
+ */
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg)
+{
+	unsigned long flags;
+
+	/* Wait for the verification that's currently in progress to finish */
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	mmsv->verify_enabled = cfg->verify_enabled;
+	mmsv->pmac_enabled = cfg->pmac_enabled;
+	mmsv->verify_time = cfg->verify_time;
+	mmsv->tx_enabled = cfg->tx_enabled;
+
+	if (!cfg->verify_enabled)
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+
+	ethtool_mmsv_apply(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_set_mm);
+
+/**
+ * ethtool_mmsv_init() - Initialize MAC Merge Software Verification state
+ * @mmsv: MAC Merge Software Verification state
+ * @dev: Pointer to network interface
+ * @ops: Methods for implementing the generic functionality
+ *
+ * The MAC Merge Software Verification is a timer- and event-based state
+ * machine intended for network interfaces which lack a hardware-based
+ * TX verification process (as per IEEE 802.3 clause 99.4.3). The timer
+ * is managed by the core code, whereas events are supplied by the
+ * driver explicitly calling one of the other API functions.
+ */
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops)
+{
+	mmsv->ops = ops;
+	mmsv->dev = dev;
+	mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+	mmsv->verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+	timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+	spin_lock_init(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_init);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:18 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:18 -0500
Subject: [PATCH iwl-next v8 03/11] net: ethtool: mm: reset verification status when link is down
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-4-faizal.abdul.rahim@linux.intel.com>

When the link partner goes down, "ethtool --show-mm" still displays
"Verification status: SUCCEEDED," reflecting a previous state that is
no longer valid.

Reset the verification status to ensure it reflects the current state.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 net/ethtool/mm.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index aa43df2ecac0..ad9b40034003 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -415,8 +415,9 @@ void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
 		/* New link => maybe new partner => new verification process */
 		ethtool_mmsv_apply(mmsv);
 	} else {
-		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
-		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+		/* Reset the reported verification state while the link is down */
+		if (mmsv->verify_enabled)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
 
 		/* No link or pMAC not enabled */
 		ethtool_mmsv_configure_pmac(mmsv, false);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:19 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:19 -0500
Subject: [PATCH iwl-next v8 04/11] igc: rename xdp_get_tx_ring() for non-xdp usage
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-5-faizal.abdul.rahim@linux.intel.com>

Renamed xdp_get_tx_ring() function to a more generic name for use in
upcoming frame preemption patches.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h      | 2 +-
 drivers/net/ethernet/intel/igc/igc_main.c | 9 ++++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index b8111ad9a9a8..22ecdac26cf4 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -736,7 +736,7 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
-
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 56a35d58e7a6..db4a36afcec6 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2444,8 +2444,7 @@ static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
 	return -ENOMEM;
 }
 
-static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
-					    int cpu)
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu)
 {
 	int index = cpu;
 
@@ -2469,7 +2468,7 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
 	if (unlikely(!xdpf))
 		return -EFAULT;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
@@ -2546,7 +2545,7 @@ static void igc_finalize_xdp(struct igc_adapter *adapter, int status)
 	struct igc_ring *ring;
 
 	if (status & IGC_XDP_TX) {
-		ring = igc_xdp_get_tx_ring(adapter, cpu);
+		ring = igc_get_tx_ring(adapter, cpu);
 		nq = txring_txq(ring);
 
 		__netif_tx_lock(nq, cpu);
@@ -6699,7 +6698,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
 	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
 		return -EINVAL;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:20 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:20 -0500
Subject: [PATCH iwl-next v8 05/11] igc: optimize the TX packet buffer utilization
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-6-faizal.abdul.rahim@linux.intel.com>

Packet buffers (RX + TX) total 64KB. Neither RX or TX buffers can be
larger than 34KB. So divide the buffer equally, 32KB for each.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 8e449904aa7d..516ef70c98e9 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -400,7 +400,8 @@
 #define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
 #define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */
 
-#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
+ /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/
+#define IGC_TXPBSIZE_TSN	0x041c71c7
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:21 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:21 -0500
Subject: [PATCH iwl-next v8 06/11] igc: set the RX packet buffer size for TSN mode
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-7-faizal.abdul.rahim@linux.intel.com>

In preparation for supporting frame preemption, when entering TSN mode
set the receive packet buffer to 16KB for the Express MAC, 16KB for
the Preemptible MAC and 2KB for the BMC, according to the datasheet
section 7.1.3.2.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h |  3 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 13 +++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 516ef70c98e9..b19ac6f30dac 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -402,6 +402,9 @@
 
  /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/
 #define IGC_TXPBSIZE_TSN	0x041c71c7
+/* 15KB for EXP + 15KB for BE + 2KB for BMC */
+#define IGC_RXPBSIZE_TSN	0x0000f08f
+#define IGC_RXPBSIZE_SIZE_MASK	0x0001FFFF
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 1e44374ca1ff..f0213cfce07d 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -132,13 +132,17 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 {
 	u16 queue_per_tc[4] = { 3, 2, 1, 0 };
 	struct igc_hw *hw = &adapter->hw;
-	u32 tqavctrl;
+	u32 tqavctrl, rxpbs;
 	int i;
 
 	wr32(IGC_GTXOFFSET, 0);
 	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
+	rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
+	rxpbs |= I225_RXPBSIZE_DEFAULT;
+	wr32(IGC_RXPBS, rxpbs);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_restore_retx_default(adapter);
 
@@ -194,7 +198,7 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
-	u32 sec, nsec, cycle;
+	u32 sec, nsec, cycle, rxpbs;
 	ktime_t base_time, systim;
 	int i;
 
@@ -202,6 +206,11 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
 
+	rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
+	rxpbs |= IGC_RXPBSIZE_TSN;
+
+	wr32(IGC_RXPBS, rxpbs);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_set_retx_qbvfullthreshold(adapter);
 
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Wed Mar  5 05:00:22 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Wed,  5 Mar 2025 08:00:22 -0500
Subject: [PATCH iwl-next v8 07/11] igc: add support for frame preemption verification
In-Reply-To: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305130026.642219-8-faizal.abdul.rahim@linux.intel.com>

This patch implements the "ethtool --set-mm" callback to trigger the
frame preemption verification handshake.

Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool
to perform the verification handshake for igc.
The structure fpe.mmsv is set by mmsv in ethtool and should remain
read-only for the driver.

Other mmsv callbacks:
a) configure_tx() -> not used yet at this point
   - igc lacks registers to configure FPE in the transmit direction, so
     this API is not utilized for now. A future patch will use it to
     control preemptible queue config.

b) configure_pmac() -> not used
   - this callback dynamically controls pmac_enabled at runtime. For
     example, mmsv calls configure_pmac() and disables pmac_enabled when
     the link partner goes down, even if the user previously enabled it.
     The intention is to save power but it is not feasible in igc
     because it causes an endless adapter reset loop:

   1) Board A and Board B complete the verification handshake. Tx mode
      register for both boards are in TSN mode.
   2) Board B link goes down.

   On Board A:
   3) mmsv calls configure_pmac() with pmac_enabled = false.
   4) configure_pmac() in igc updates a new field based on pmac_enabled.
      Driver uses this field in igc_tsn_new_flags() to indicate that the
      user enabled/disabled FPE.
   5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
      whether an adapter reset is needed. Calls existing logic in
      igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
   6) Since pmac_enabled is now disabled and no other TSN feature is
      active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
      mode will switch from TSN to Legacy.
   7) Driver resets the adapter.
   8) Registers are set, and Tx mode switches to Legacy.
   9) When link partner is up, steps 3?8 repeat, but this time with
      pmac_enabled = true, reactivating TSN.
      igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
      mode will switch from Legacy to TSN.
  10) Driver resets the adapter.
  11) Rest adapter completes, registers are set, and Tx mode switches to
      TSN.

  On Board B:
  12) Adapter reset on Board A at step 10 causes it to detect its link
      partner as down.
  13) Repeats steps 3?8.
  14) Once reset adapter on Board A is completed at step 11, it detects
      its link partner as up.
  15) Repeats steps 9?11.

   - this cycle repeats indefinitely. To avoid this issue, igc only uses
     mmsv.pmac_enabled to track whether FPE is enabled or disabled.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  12 +-
 drivers/net/ethernet/intel/igc/igc_base.h    |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |   8 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  21 +++
 drivers/net/ethernet/intel/igc/igc_main.c    |  53 ++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 146 ++++++++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  53 +++++++
 7 files changed, 289 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 22ecdac26cf4..d9ecb7cf80c9 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -40,6 +40,10 @@ void igc_ethtool_set_ops(struct net_device *);
 
 #define IGC_MAX_TX_TSTAMP_REGS		4
 
+struct igc_fpe_t {
+	struct ethtool_mmsv mmsv;
+};
+
 enum igc_mac_filter_type {
 	IGC_MAC_FILTER_TYPE_DST = 0,
 	IGC_MAC_FILTER_TYPE_SRC
@@ -332,6 +336,8 @@ struct igc_adapter {
 		struct timespec64 period;
 	} perout[IGC_N_PEROUT];
 
+	struct igc_fpe_t fpe;
+
 	/* LEDs */
 	struct mutex led_mutex;
 	struct igc_led_classdev *leds;
@@ -389,10 +395,11 @@ extern char igc_driver_name[];
 #define IGC_FLAG_TSN_QBV_ENABLED	BIT(17)
 #define IGC_FLAG_TSN_QAV_ENABLED	BIT(18)
 #define IGC_FLAG_TSN_LEGACY_ENABLED	BIT(19)
+#define IGC_FLAG_TSN_PREEMPT_ENABLED	BIT(20)
 
 #define IGC_FLAG_TSN_ANY_ENABLED				\
 	(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED |	\
-	 IGC_FLAG_TSN_LEGACY_ENABLED)
+	 IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)
 
 #define IGC_FLAG_RSS_FIELD_IPV4_UDP	BIT(6)
 #define IGC_FLAG_RSS_FIELD_IPV6_UDP	BIT(7)
@@ -736,7 +743,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter);
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter);
 struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
+void igc_flush_tx_descriptors(struct igc_ring *ring);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h
index bf8cdfbba9ff..6320eabb72fe 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.h
+++ b/drivers/net/ethernet/intel/igc/igc_base.h
@@ -49,6 +49,7 @@ struct igc_adv_tx_context_desc {
 #define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
 #define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
 #define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
+#define IGC_ADVTXD_PAYLEN_MASK	0XFFFFC000 /* Adv desc PAYLEN mask */
 #define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */
 
 #define IGC_RAR_ENTRIES		16
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b19ac6f30dac..22db1de02964 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -308,6 +308,8 @@
 #define IGC_TXD_DTYP_C		0x00000000 /* Context Descriptor */
 #define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
 #define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
+#define IGC_TXD_POPTS_SMD_MASK	0x3000     /* Indicates whether it's SMD-V or SMD-R */
+
 #define IGC_TXD_CMD_EOP		0x01000000 /* End of Packet */
 #define IGC_TXD_CMD_IC		0x04000000 /* Insert Checksum */
 #define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
@@ -363,6 +365,8 @@
 #define IGC_SRRCTL_TIMER0SEL(timer)	(((timer) & 0x3) << 17)
 
 /* Receive Descriptor bit definitions */
+#define IGC_RXD_STAT_SMD_TYPE_V	0x01	/* SMD-V Packet */
+#define IGC_RXD_STAT_SMD_TYPE_R	0x02	/* SMD-R Packet */
 #define IGC_RXD_STAT_EOP	0x02	/* End of Packet */
 #define IGC_RXD_STAT_IXSM	0x04	/* Ignore checksum */
 #define IGC_RXD_STAT_UDPCS	0x10	/* UDP xsum calculated */
@@ -372,7 +376,8 @@
 #define IGC_RXDEXT_STATERR_LB	0x00040000
 
 /* Advanced Receive Descriptor bit definitions */
-#define IGC_RXDADV_STAT_TSIP	0x08000 /* timestamp in packet */
+#define IGC_RXDADV_STAT_SMD_TYPE_MASK	0x06000
+#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */
 
 #define IGC_RXDEXT_STATERR_L4E		0x20000000
 #define IGC_RXDEXT_STATERR_IPE		0x40000000
@@ -543,6 +548,7 @@
 
 /* Transmit Scheduling */
 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
+#define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
 
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 817838677817..b64d5c6c1d20 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -8,6 +8,7 @@
 
 #include "igc.h"
 #include "igc_diag.h"
+#include "igc_tsn.h"
 
 /* forward declaration */
 struct igc_stats {
@@ -1781,6 +1782,25 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_set_mm(struct net_device *netdev,
+			      struct ethtool_mm_cfg *cmd,
+			      struct netlink_ext_ack *extack)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
+		if (cmd->pmac_enabled)
+			static_branch_inc(&igc_fpe_enabled);
+		else
+			static_branch_dec(&igc_fpe_enabled);
+	}
+
+	ethtool_mmsv_set_mm(&fpe->mmsv, cmd);
+
+	return igc_tsn_offload_apply(adapter);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2076,6 +2096,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.set_mm			= igc_ethtool_set_mm,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index db4a36afcec6..a9f40fffc4fd 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2528,7 +2528,7 @@ static int igc_xdp_run_prog(struct igc_adapter *adapter, struct xdp_buff *xdp)
 }
 
 /* This function assumes __netif_tx_lock is held by the caller. */
-static void igc_flush_tx_descriptors(struct igc_ring *ring)
+void igc_flush_tx_descriptors(struct igc_ring *ring)
 {
 	/* Once tail pointer is updated, hardware can fetch the descriptors
 	 * any time so we issue a write membar here to ensure all memory
@@ -2617,6 +2617,15 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
 			size -= IGC_TS_HDR_LEN;
 		}
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_is_verify_or_response(rx_desc, size, pktbuf)) {
+			igc_fpe_lp_event_status(rx_desc, &adapter->fpe.mmsv);
+			/* Advance the ring next-to-clean */
+			igc_is_non_eop(rx_ring, rx_desc);
+			cleaned_count++;
+			continue;
+		}
+
 		if (!skb) {
 			xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
 			xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
@@ -3064,6 +3073,11 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
 		if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD)))
 			break;
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_transmitted_smd_v(tx_desc))
+			ethtool_mmsv_event_handle(&adapter->fpe.mmsv,
+						  ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
+
 		/* Hold the completions while there's a pending tx hardware
 		 * timestamp request from XDP Tx metadata.
 		 */
@@ -3955,6 +3969,30 @@ static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr)
 	return 0;
 }
 
+/**
+ * igc_enable_empty_addr_recv - Enable Rx of packets with all-zeroes MAC address
+ * @adapter: Pointer to the igc_adapter structure.
+ *
+ * Frame preemption verification requires that packets with the all-zeroes
+ * MAC address are allowed to be received by the driver. This function adds the
+ * all-zeroes destination address to the list of acceptable addresses.
+ *
+ * Return: 0 on success, negative value otherwise.
+ */
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty, -1);
+}
+
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty);
+}
+
 /**
  * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
  * @netdev: network interface device structure
@@ -5230,6 +5268,9 @@ void igc_down(struct igc_adapter *adapter)
 	igc_disable_all_tx_rings_hw(adapter);
 	igc_clean_all_tx_rings(adapter);
 	igc_clean_all_rx_rings(adapter);
+
+	if (adapter->fpe.mmsv.pmac_enabled)
+		ethtool_mmsv_stop(&adapter->fpe.mmsv);
 }
 
 void igc_reinit_locked(struct igc_adapter *adapter)
@@ -5754,6 +5795,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			 */
 			igc_tsn_adjust_txtime_offset(adapter);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       true);
+
 			if (adapter->link_speed != SPEED_1000)
 				goto no_wait;
 
@@ -5789,6 +5834,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			netdev_info(netdev, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       false);
+
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGC_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
@@ -7109,6 +7158,8 @@ static int igc_probe(struct pci_dev *pdev,
 
 	igc_tsn_clear_schedule(adapter);
 
+	igc_fpe_init(adapter);
+
 	/* reset the hardware with the new settings */
 	igc_reset(adapter);
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index f0213cfce07d..0a2c747fde2d 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -2,9 +2,135 @@
 /* Copyright (c)  2019 Intel Corporation */
 
 #include "igc.h"
+#include "igc_base.h"
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+static int igc_fpe_init_smd_frame(struct igc_ring *ring,
+				  struct igc_tx_buffer *buffer,
+				  struct sk_buff *skb)
+{
+	dma_addr_t dma = dma_map_single(ring->dev, skb->data, skb->len,
+					DMA_TO_DEVICE);
+
+	if (dma_mapping_error(ring->dev, dma)) {
+		netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
+		return -ENOMEM;
+	}
+
+	buffer->skb = skb;
+	buffer->protocol = 0;
+	buffer->bytecount = skb->len;
+	buffer->gso_segs = 1;
+	buffer->time_stamp = jiffies;
+	dma_unmap_len_set(buffer, len, skb->len);
+	dma_unmap_addr_set(buffer, dma, dma);
+
+	return 0;
+}
+
+static int igc_fpe_init_tx_descriptor(struct igc_ring *ring,
+				      struct sk_buff *skb,
+				      enum igc_txd_popts_type type)
+{
+	u32 cmd_type, olinfo_status = 0;
+	struct igc_tx_buffer *buffer;
+	union igc_adv_tx_desc *desc;
+	int err;
+
+	if (!igc_desc_unused(ring))
+		return -EBUSY;
+
+	buffer = &ring->tx_buffer_info[ring->next_to_use];
+	err = igc_fpe_init_smd_frame(ring, buffer, skb);
+	if (err)
+		return err;
+
+	cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
+		   IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
+		   buffer->bytecount;
+
+	olinfo_status |= FIELD_PREP(IGC_ADVTXD_PAYLEN_MASK, buffer->bytecount);
+
+	switch (type) {
+	case SMD_V:
+	case SMD_R:
+		olinfo_status |= FIELD_PREP(IGC_TXD_POPTS_SMD_MASK, type);
+		break;
+	}
+
+	desc = IGC_TX_DESC(ring, ring->next_to_use);
+	desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+	desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+	desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
+
+	netdev_tx_sent_queue(txring_txq(ring), skb->len);
+
+	buffer->next_to_watch = desc;
+	ring->next_to_use = (ring->next_to_use + 1) % ring->count;
+
+	return 0;
+}
+
+static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
+				  enum igc_txd_popts_type type)
+{
+	int cpu = smp_processor_id();
+	struct netdev_queue *nq;
+	struct igc_ring *ring;
+	struct sk_buff *skb;
+	int err;
+
+	ring = igc_get_tx_ring(adapter, cpu);
+	nq = txring_txq(ring);
+
+	skb = alloc_skb(SMD_FRAME_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put_zero(skb, SMD_FRAME_SIZE);
+
+	__netif_tx_lock(nq, cpu);
+
+	err = igc_fpe_init_tx_descriptor(ring, skb, type);
+	igc_flush_tx_descriptors(ring);
+
+	__netif_tx_unlock(nq);
+
+	return err;
+}
+
+static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				 enum ethtool_mpacket type)
+{
+	struct igc_fpe_t *fpe = container_of(mmsv, struct igc_fpe_t, mmsv);
+	struct igc_adapter *adapter;
+	int err;
+
+	adapter = container_of(fpe, struct igc_adapter, fpe);
+
+	if (type == ETHTOOL_MPACKET_VERIFY) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_V);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-V\n");
+	} else if (type == ETHTOOL_MPACKET_RESPONSE) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_R);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-R frame\n");
+	}
+}
+
+static const struct ethtool_mmsv_ops igc_mmsv_ops = {
+	.send_mpacket = igc_fpe_send_mpacket,
+};
+
+void igc_fpe_init(struct igc_adapter *adapter)
+{
+	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
+}
+
 static bool is_any_launchtime(struct igc_adapter *adapter)
 {
 	int i;
@@ -49,6 +175,9 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
 	if (adapter->strict_priority_enable)
 		new_flags |= IGC_FLAG_TSN_LEGACY_ENABLED;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		new_flags |= IGC_FLAG_TSN_PREEMPT_ENABLED;
+
 	return new_flags;
 }
 
@@ -148,7 +277,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
-		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
+		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
+		      IGC_TQAVCTRL_PREEMPT_ENA);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -370,10 +500,14 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 		wr32(IGC_TXQCTL(i), txqctl);
 	}
 
-	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
+	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
+		   IGC_TQAVCTRL_PREEMPT_ENA);
 
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
@@ -434,6 +568,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)
 	unsigned int new_flags;
 	int err = 0;
 
+	if (adapter->fpe.mmsv.pmac_enabled) {
+		err = igc_enable_empty_addr_recv(adapter);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error adding empty address to MAC filter\n");
+	} else {
+		igc_disable_empty_addr_recv(adapter);
+	}
+
 	new_flags = igc_tsn_new_flags(adapter);
 
 	if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 98ec845a86bf..a2534228cc0e 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,9 +4,62 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define SMD_FRAME_SIZE			60
+
+enum igc_txd_popts_type {
+	SMD_V = 0x01,
+	SMD_R = 0x02,
+};
+
+DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+void igc_fpe_init(struct igc_adapter *adapter);
+u32 igc_fpe_get_supported_frag_size(u32 user_frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
 bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter);
 
+static inline bool igc_fpe_is_pmac_enabled(struct igc_adapter *adapter)
+{
+	return static_branch_unlikely(&igc_fpe_enabled) &&
+	       adapter->fpe.mmsv.pmac_enabled;
+}
+
+static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
+						 unsigned int size, void *pktbuf)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	static const u8 zero_payload[SMD_FRAME_SIZE] = {0};
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+
+	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
+		size == SMD_FRAME_SIZE &&
+		!memcmp(pktbuf, zero_payload, SMD_FRAME_SIZE); /* Buffer is all zeros */
+}
+
+static inline void igc_fpe_lp_event_status(union igc_adv_rx_desc *rx_desc,
+					   struct ethtool_mmsv *mmsv)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+
+	if (smd == IGC_RXD_STAT_SMD_TYPE_V)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
+	else if (smd == IGC_RXD_STAT_SMD_TYPE_R)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
+}
+
+static inline bool igc_fpe_transmitted_smd_v(union igc_adv_tx_desc *tx_desc)
+{
+	u32 olinfo_status = le32_to_cpu(tx_desc->read.olinfo_status);
+	u8 smd = FIELD_GET(IGC_TXD_POPTS_SMD_MASK, olinfo_status);
+
+	return smd == SMD_V;
+}
+
 #endif /* _IGC_BASE_H */
-- 
2.34.1



From alyssa at rosenzweig.io  Wed Mar  5 05:48:39 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Wed, 5 Mar 2025 08:48:39 -0500
Subject: [PATCH v7 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <dn7zskhxgdgr25nvbnsjyn5brc3yoc446dxz3vqgbiwoccvlcr@5l6f4byj53fo>
References: <20250217-adpdrm-v7-0-ca2e44b3c7d8@gmail.com>
 <c3927b51-55ef-4a38-8931-18ff00caa8d8@linaro.org>
 <Z8XcH7xoDC7TA7ZC@blossom>
 <dn7zskhxgdgr25nvbnsjyn5brc3yoc446dxz3vqgbiwoccvlcr@5l6f4byj53fo>
Message-ID: <Z8hWN4DpNyTHQf7I@blossom>

> > > All patches are reviewed, can we funnel patches 1, 2 & 5 via drm-misc-next now ?
> > 
> > I'm planning to do so today, just need to get dim setup first :)
> 
> Nice! As a heads up, it would be really-really nice if you can send any
> kind of 'applied' message. If you are using 'dim b4-shazam', then
> 'b4 ty -a' might do that for you. Otherwise just a simple 'hey, applied'
> email is useful enough.

Oh cool, it didn't occur to me that `b4 ty` would compose with `dim
b4-shazam`. Sent a very belated message and will try to make a habit of
it going forward.

Thanks for the tip!

Cheers,
Alyssa


From james.clark at linaro.org  Wed Mar  5 05:52:46 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 5 Mar 2025 13:52:46 +0000
Subject: [PATCH] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20250305114211.GG13418@e132581.arm.com>
References: <20241217171132.834943-1-james.clark@linaro.org>
 <20250305114211.GG13418@e132581.arm.com>
Message-ID: <67c484d7-6929-4a65-b89c-f3fb85682028@linaro.org>



On 05/03/2025 11:42 am, Leo Yan wrote:
> On Tue, Dec 17, 2024 at 05:11:31PM +0000, James Clark wrote:
>>
>> Add a test to confirm that default sink selection skips over an ETF
>> and returns an ETR even if it's further away.
>>
>> This also makes it easier to add new unit tests in the future.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>   drivers/hwtracing/coresight/Kconfig           |  9 ++
>>   drivers/hwtracing/coresight/Makefile          |  1 +
>>   drivers/hwtracing/coresight/coresight-core.c  |  1 +
>>   .../coresight/coresight-kunit-tests.c         | 90 +++++++++++++++++++
>>   4 files changed, 101 insertions(+)
>>   create mode 100644 drivers/hwtracing/coresight/coresight-kunit-tests.c
>>
>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
>> index 06f0a7594169..056d04bc540a 100644
>> --- a/drivers/hwtracing/coresight/Kconfig
>> +++ b/drivers/hwtracing/coresight/Kconfig
>> @@ -247,4 +247,13 @@ config CORESIGHT_DUMMY
>>
>>            To compile this driver as a module, choose M here: the module will be
>>            called coresight-dummy.
>> +
>> +config CORESIGHT_KUNIT_TESTS
>> +         tristate "Enable Coresight unit tests"
>> +         depends on KUNIT
>> +         default KUNIT_ALL_TESTS
>> +         help
>> +           Enable Coresight unit tests. Only useful for development and not
>> +           intended for production.
>> +
>>   endif
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
>> index 4ba478211b31..c170a41b3056 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -51,3 +51,4 @@ coresight-cti-y := coresight-cti-core.o       coresight-cti-platform.o \
>>                     coresight-cti-sysfs.o
>>   obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index ea38ecf26fcb..ce63b68d5503 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -869,6 +869,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>>          }
>>          return csdev->def_sink;
>>   }
>> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>>
>>   static int coresight_remove_sink_ref(struct device *dev, void *data)
>>   {
>> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> new file mode 100644
>> index 000000000000..d022bacc8357
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> @@ -0,0 +1,90 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#include <kunit/test.h>
>> +#include <kunit/device.h>
>> +#include <linux/coresight.h>
>> +
>> +#include "coresight-priv.h"
>> +
>> +static struct coresight_device *coresight_test_device(struct device *dev)
>> +{
>> +       struct coresight_device *csdev = devm_kcalloc(dev, 1,
>> +                                                    sizeof(struct coresight_device),
>> +                                                    GFP_KERNEL);
>> +       csdev->pdata = devm_kcalloc(dev, 1,
>> +                                  sizeof(struct coresight_platform_data),
>> +                                  GFP_KERNEL);
>> +       return csdev;
>> +}
>> +
>> +static void coresight_free_test_device(struct device *dev,
>> +                                      struct coresight_device *csdev)
>> +{
>> +       devm_kfree(dev, csdev->pdata->out_conns);
> 
> It will lead memory leaking if we don't release connections pointed by
> 'out_conns' pointer array.  Something like:
> 
>            for (i = 0; i < csdev->pdata->nr_outconns; i++)
>                 devm_kfree(dev, csdev->pdata->out_conns[i]);
>            devm_kfree(dev, csdev->pdata->out_conns);
> 
> Otherwise, it looks good to me.
> 
> Thanks,
> Leo
> 

Ah yeah, I'll just free the whole device instead of the individual 
kfrees then and let devm handle it.



From piotr.oniszczuk at gmail.com  Wed Mar  5 05:56:12 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Wed, 5 Mar 2025 14:56:12 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
Message-ID: <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 5 mar 2025, o godz. 03:30:
> 
>> 
> 
> I only see the HDMI connector from your dri/state ; so it appears the DP driver hasn't been successfully
> initialized?I think kernel dmesg can tell that?. 
> Have you enabled CONFIG_ROCKCHIP_DW_DP ? This is needed.
> 


Andy,

Do you mean CONFIG_ROCKCHIP_DW_DP or CONFIG_DRM_DW_DP ?

If CONFIG_DRM_DW_DP - then yes - i have it: https://github.com/warpme/minimyth2/blob/2e267842b1033bbc4c2c5d80c1756a142e347cc5/script/kernel/linux-6.14/files/linux-6.14-arm64-armv8.config#L5024

Kernel dmesg: https://termbin.com/uiup





From amadeus at jmu.edu.cn  Wed Mar  5 06:00:09 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Wed,  5 Mar 2025 22:00:09 +0800
Subject: [PATCH 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
Message-ID: <20250305140009.2485859-2-amadeus@jmu.edu.cn>

Copy QoS nodes and add rk3528 compatible from bsp kernel,
these can be used for power-domain.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 5b334690356a..794f35654975 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -122,6 +122,166 @@ gic: interrupt-controller at fed01000 {
 			#interrupt-cells = <3>;
 		};
 
+		qos_crypto_a: qos at ff200000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200000 0x0 0x20>;
+		};
+
+		qos_crypto_p: qos at ff200080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200080 0x0 0x20>;
+		};
+
+		qos_dcf: qos at ff200100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200100 0x0 0x20>;
+		};
+
+		qos_dft2apb: qos at ff200200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200200 0x0 0x20>;
+		};
+
+		qos_dma2ddr: qos at ff200280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200280 0x0 0x20>;
+		};
+
+		qos_dmac: qos at ff200300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200300 0x0 0x20>;
+		};
+
+		qos_keyreader: qos at ff200380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200380 0x0 0x20>;
+		};
+
+		qos_cpu: qos at ff210000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff210000 0x0 0x20>;
+		};
+
+		qos_debug: qos at ff210080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff210080 0x0 0x20>;
+		};
+
+		qos_gpu_m0: qos at ff220000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff220000 0x0 0x20>;
+		};
+
+		qos_gpu_m1: qos at ff220080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff220080 0x0 0x20>;
+		};
+
+		qos_pmu_mcu: qos at ff240000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff240000 0x0 0x20>;
+		};
+
+		qos_rkvdec: qos at ff250000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff250000 0x0 0x20>;
+		};
+
+		qos_rkvenc: qos at ff260000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff260000 0x0 0x20>;
+		};
+
+		qos_gmac0: qos at ff270000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270000 0x0 0x20>;
+		};
+
+		qos_hdcp: qos at ff270080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270080 0x0 0x20>;
+		};
+
+		qos_jpegdec: qos at ff270100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270100 0x0 0x20>;
+		};
+
+		qos_rga2_m0ro: qos at ff270200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270200 0x0 0x20>;
+		};
+
+		qos_rga2_m0wo: qos at ff270280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270280 0x0 0x20>;
+		};
+
+		qos_sdmmc0: qos at ff270300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270300 0x0 0x20>;
+		};
+
+		qos_usb2host: qos at ff270380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270380 0x0 0x20>;
+		};
+
+		qos_vdpp: qos at ff270480 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270480 0x0 0x20>;
+		};
+
+		qos_vop: qos at ff270500 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270500 0x0 0x20>;
+		};
+
+		qos_emmc: qos at ff280000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280000 0x0 0x20>;
+		};
+
+		qos_fspi: qos at ff280080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280080 0x0 0x20>;
+		};
+
+		qos_gmac1: qos at ff280100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280100 0x0 0x20>;
+		};
+
+		qos_pcie: qos at ff280180 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280180 0x0 0x20>;
+		};
+
+		qos_sdio0: qos at ff280200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280200 0x0 0x20>;
+		};
+
+		qos_sdio1: qos at ff280280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280280 0x0 0x20>;
+		};
+
+		qos_tsp: qos at ff280300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280300 0x0 0x20>;
+		};
+
+		qos_usb3otg: qos at ff280380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280380 0x0 0x20>;
+		};
+
+		qos_vpu: qos at ff280400 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280400 0x0 0x20>;
+		};
+
 		cru: clock-controller at ff4a0000 {
 			compatible = "rockchip,rk3528-cru";
 			reg = <0x0 0xff4a0000 0x0 0x30000>;
-- 
2.25.1



From amadeus at jmu.edu.cn  Wed Mar  5 06:00:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Wed,  5 Mar 2025 22:00:08 +0800
Subject: [PATCH 1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
Message-ID: <20250305140009.2485859-1-amadeus@jmu.edu.cn>

Document rk3528 compatible for QoS registers.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 4d67ff26d445..fcfd293b9bf1 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -103,6 +103,7 @@ select:
           - rockchip,rk3288-qos
           - rockchip,rk3368-qos
           - rockchip,rk3399-qos
+          - rockchip,rk3528-qos
           - rockchip,rk3562-qos
           - rockchip,rk3568-qos
           - rockchip,rk3576-qos
-- 
2.25.1



From alyssa at rosenzweig.io  Wed Mar  5 06:01:13 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Wed, 5 Mar 2025 09:01:13 -0500
Subject: [PATCH v8 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <174118223158.156873.6982508045942987984.b4-ty@rosenzweig.io>
References: <20250224-adpdrm-v8-0-cccf96710f0f@gmail.com>
 <174118223158.156873.6982508045942987984.b4-ty@rosenzweig.io>
Message-ID: <Z8hZKW_F-HtzYm-w@blossom>

Er... I only applied 1, 2, and 5. Patch 3 was already merged, and patch
4 is going in via arm soc. I am, new to b4, sorry!

Le Wed, Mar 05, 2025 at 08:43:51AM -0500, Alyssa Rosenzweig a ?crit :
> 
> On Mon, 24 Feb 2025 12:02:15 +0100, Sasha Finkelstein wrote:
> > This patch series adds support for a secondary display controller
> > present on Apple M1/M2 chips and used to drive the display of the
> > "touchbar" touch panel present on those.
> > 
> > 
> 
> Applied, thanks!
> 
> [1/5] dt-bindings: display: Add Apple pre-DCP display controller
>       commit: 7a108b930a84e71be71c3370eef6dd96fbb8f618
> [2/5] drm: adp: Add Apple Display Pipe driver
>       commit: 332122eba628d537a1b7b96b976079753fd03039
> [3/5] drm: panel: Add a panel driver for the Summit display
>       (no commit info)
> [4/5] arm64: dts: apple: Add touchbar screen nodes
>       (no commit info)
> [5/5] MAINTAINERS: Add entries for touchbar display driver
>       commit: 4d2a877cc0efefa815648f1ed5f5b2b796f55bab
> 
> Best regards,
> -- 
> Alyssa Rosenzweig <alyssa at rosenzweig.io>
> 
> 


From pauld at redhat.com  Wed Mar  5 06:03:05 2025
From: pauld at redhat.com (Phil Auld)
Date: Wed, 5 Mar 2025 09:03:05 -0500
Subject: [PATCH 0/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <20250305104925.189198-1-vschneid@redhat.com>
References: <20250305104925.189198-1-vschneid@redhat.com>
Message-ID: <20250305140305.GA51446@pauld.westford.csb>

On Wed, Mar 05, 2025 at 11:49:24AM +0100 Valentin Schneider wrote:
> Hey folks,
> 
> This is a resubmission of Mark's patch [1]. I didn't end up changing anything
> other than fluffing up the changelog.
> 
> I ran this under an arm64 VM, added some trace_printk's and checked that
> sched_switch's between runnable hackbench threads would occurr in the right
> conditions:
> o with TIF_NEED_RESCHED_LAZY set
>   o at the tick
>   o at do_notify_resume()
> o with TIF_NEED_RESCHED set  
> 
> [1]: https://lore.kernel.org/linux-rt-users/Z2B5y3HiLuRHPfdv at J2N7QTR9R3.cambridge.arm.com/
>

Thanks!  I was looking for this the other day :) 


Cheers,
Phil

> Cheers,
> Valentin
> 
> Mark Rutland (1):
>   arm64: enable PREEMPT_LAZY
> 
>  arch/arm64/Kconfig                   |  1 +
>  arch/arm64/include/asm/thread_info.h | 16 +++++++++-------
>  arch/arm64/kernel/entry-common.c     |  2 +-
>  3 files changed, 11 insertions(+), 8 deletions(-)
> 
> --
> 2.43.0
> 

-- 



From neil.armstrong at linaro.org  Wed Mar  5 06:06:20 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Wed, 5 Mar 2025 15:06:20 +0100
Subject: [PATCH v8 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <Z8hZKW_F-HtzYm-w@blossom>
References: <20250224-adpdrm-v8-0-cccf96710f0f@gmail.com>
 <174118223158.156873.6982508045942987984.b4-ty@rosenzweig.io>
 <Z8hZKW_F-HtzYm-w@blossom>
Message-ID: <18f9658f-f2ca-4fd9-809c-ec4d198072be@linaro.org>

On 05/03/2025 15:01, Alyssa Rosenzweig wrote:
> Er... I only applied 1, 2, and 5. Patch 3 was already merged, and patch
> 4 is going in via arm soc. I am, new to b4, sorry!

Yeah it's because you applied the whole patchset, and discarded/skipped
patch 3 & 4 afterwards, so b4 gets confused.

Next time specify which patch you want to apply with -P 1,2,5
and b4 with know which patch you applied and generate a good ty patch.

Neil

> 
> Le Wed, Mar 05, 2025 at 08:43:51AM -0500, Alyssa Rosenzweig a ?crit :
>>
>> On Mon, 24 Feb 2025 12:02:15 +0100, Sasha Finkelstein wrote:
>>> This patch series adds support for a secondary display controller
>>> present on Apple M1/M2 chips and used to drive the display of the
>>> "touchbar" touch panel present on those.
>>>
>>>
>>
>> Applied, thanks!
>>
>> [1/5] dt-bindings: display: Add Apple pre-DCP display controller
>>        commit: 7a108b930a84e71be71c3370eef6dd96fbb8f618
>> [2/5] drm: adp: Add Apple Display Pipe driver
>>        commit: 332122eba628d537a1b7b96b976079753fd03039
>> [3/5] drm: panel: Add a panel driver for the Summit display
>>        (no commit info)
>> [4/5] arm64: dts: apple: Add touchbar screen nodes
>>        (no commit info)
>> [5/5] MAINTAINERS: Add entries for touchbar display driver
>>        commit: 4d2a877cc0efefa815648f1ed5f5b2b796f55bab
>>
>> Best regards,
>> -- 
>> Alyssa Rosenzweig <alyssa at rosenzweig.io>
>>
>>



From dario.binacchi at amarulasolutions.com  Wed Mar  5 06:09:16 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Wed,  5 Mar 2025 15:09:16 +0100
Subject: [RESEND PATCH v3] drm/mxsfb: Remove generic DRM drivers in probe function
Message-ID: <20250305140929.174398-1-dario.binacchi@amarulasolutions.com>

Use aperture helpers to remove all generic graphics drivers before
loading mxsfb. Makes mxsfb compatible with simpledrm.

Co-developed-by: Michael Trimarchi <michael at amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Thomas Zimmermann <tzimmermann at suse.de>

---

Changes in v3:
- Add 'Reviewed-by' of  Thomas Zimmermann

Changes in v2:
- Use aperture_remove_all_conflicting_devices() instead of
  drm_aperture_remove_framebuffers().

 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 59020862cf65..e5eb644b54ae 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -8,6 +8,7 @@
  * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  */
 
+#include <linux/aperture.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
@@ -361,6 +362,15 @@ static int mxsfb_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_free;
 
+	/*
+	 * Remove early framebuffers (ie. simplefb). The framebuffer can be
+	 * located anywhere in RAM
+	 */
+	ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "can't kick out existing framebuffers\n");
+
 	ret = drm_dev_register(drm, 0);
 	if (ret)
 		goto err_unload;
-- 
2.43.0



From tudor.ambarus at linaro.org  Wed Mar  5 06:23:04 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Wed, 5 Mar 2025 14:23:04 +0000
Subject: [PATCH 1/2] clk: samsung: Add missing mod_devicetable.h header
In-Reply-To: <20250304-clk-samsung-headers-cleanup-v1-1-81718e38246e@linaro.org>
References: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
 <20250304-clk-samsung-headers-cleanup-v1-1-81718e38246e@linaro.org>
Message-ID: <9063abd1-b417-4623-b44d-fcb18f3c71b7@linaro.org>



On 3/4/25 6:45 PM, Krzysztof Kozlowski wrote:
>  drivers/clk/samsung/clk-exynos-audss.c   | 1 +
>  drivers/clk/samsung/clk-exynos-clkout.c  | 1 +

drivers/clk/samsung/clk-exynos2200.c can benefit of the inclusion too.

>  drivers/clk/samsung/clk-exynos3250.c     | 2 +-

drivers/clk/samsung/clk-exynos4.c too

>  drivers/clk/samsung/clk-exynos4412-isp.c | 1 +

drivers/clk/samsung/clk-exynos5-subcmu.c too

>  drivers/clk/samsung/clk-exynos5250.c     | 1 +
>  drivers/clk/samsung/clk-exynos5420.c     | 1 +
>  drivers/clk/samsung/clk-exynos5433.c     | 1 +

drivers/clk/samsung/clk-exynos7870.c too

>  drivers/clk/samsung/clk-exynos7885.c     | 1 +
>  drivers/clk/samsung/clk-exynos850.c      | 1 +
>  drivers/clk/samsung/clk-exynos8895.c     | 1 +
>  drivers/clk/samsung/clk-exynos990.c      | 1 +
>  drivers/clk/samsung/clk-exynosautov9.c   | 1 +
>  drivers/clk/samsung/clk-exynosautov920.c | 1 +
>  drivers/clk/samsung/clk-fsd.c            | 1 +
>  drivers/clk/samsung/clk-gs101.c          | 1 +
>  drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +

drivers/clk/samsung/clk.c and drivers/clk/samsung/clk.h too.

With that:
Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>

>  16 files changed, 16 insertions(+), 1 deletion(-)




From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:30 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:30 +0100
Subject: [PATCH net-next 0/7] net: ethtool: Introduce ethnl dump helpers
Message-ID: <20250305141938.319282-1-maxime.chevallier@bootlin.com>

Hi everyone,

This series adds some scaffolding into ethnl to ease the support of
DUMP operations.

As of today when using ethnl's default ops, the DUMP requests will
simply perform a GET for each netdev.

That hits limitations for commands that may return multiple messages for
a single netdev, such as :

 - RSS (listing contexts)
 - All PHY-specific commands (PLCA, PSE-PD, phy)
 - tsinfo (one item for the netdev +  one per phy)

 Commands that need a non-default DUMP support have to re-implement
 ->dumpit() themselves, which prevents using most of ethnl's internal
 circuitry.

This series therefore introduces a better support for dump operations in
ethnl.

The patches 1 and 2 introduce the support for filtered DUMPs, where an
ifindex/ifname can be passed in the request header for the DUMP
operation. This is for when we want to dump everything a netdev
supports, but without doing so for every single netdev. ethtool's
"--show-phys ethX" option for example performs a filtered dump.

Patch 3 introduces 3 new ethnl ops : 
 ->dump_start() to initialize a dump context
 ->dump_one_dev(), that can be implemented per-command to dump
 everything on a given netdev
 ->dump_done() to release the context

The default behaviour for dumps remains the same, calling the whole
->doit() path for each netdev.

Patch 4 introduces a set of ->dump_start(), ->dump_one_dev() and
->dump_done() callback implementations that can simply be plugged into
the existing commands that list objects per-phy, making the 
phy-targeting command behaviour more coherent.

Patch 5 uses that new set of helpers to rewrite the phy.c support, which
now uses the regulat ethnl_ops instead of fully custom genl ops. This
one is the hardest to review, sorry about that, I couldn't really manage
to incrementally rework that file :(

Patches 6 and 7 are where the new dump infra shines, adding per-netdev
per-phy dump support for PLCA and PSE-PD.

We could also consider converting tsinfo/tsconfig, rss and tunnels to
these new ->dump_***() operations as well, but that's out of this
series' scope.

I've tested that series with some netdevsim PHY patches that I plan to
submit (they can be found here [1]), with the refcount tracker
for net/netns enabled to make sure the lock usage is somewhat coherent.

Thanks,

Maxime

[1]: https://github.com/minimaxwell/linux/tree/mc/netdevsim-phy



Maxime Chevallier (7):
  net: ethtool: netlink: Allow per-netdevice DUMP operations
  net: ethtool: netlink: Rename ethnl_default_dump_one
  net: ethtool: netlink: Introduce command-specific dump_one_dev
  net: ethtool: netlink: Introduce per-phy DUMP helpers
  net: ethtool: phy: Convert the PHY_GET command to generic phy dump
  net: ethtool: plca: Use per-PHY DUMP operations
  net: ethtool: pse-pd: Use per-PHY DUMP operations

 net/ethtool/netlink.c | 161 ++++++++++++++------
 net/ethtool/netlink.h |  46 +++++-
 net/ethtool/phy.c     | 335 ++++++++++++------------------------------
 net/ethtool/plca.c    |  12 ++
 net/ethtool/pse-pd.c  |   6 +
 5 files changed, 277 insertions(+), 283 deletions(-)

-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:33 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:33 +0100
Subject: [PATCH net-next 3/7] net: ethtool: netlink: Introduce command-specific dump_one_dev
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-4-maxime.chevallier@bootlin.com>

Prepare more generic ethnl DUMP hanldling, by allowing netlink commands
to register their own dump_one_dev() callback. This avoids having to
roll with a fully custom genl ->dumpit callback, allowing the re-use of some
ethnl plumbing.

Fallback to the default dump_one_dev behaviour when no custom callback
is found.

The command dump context is maintained within the ethnl_dump_ctx, that
we move in netlink.h so that command handlers can access it.

This context can be allocated/freed in new ->dump_start() and
->dump_done() callbacks.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 58 +++++++++++++++++++++++++------------------
 net/ethtool/netlink.h | 35 ++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 6dddaea2babb..c0215f4acc05 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -336,24 +336,6 @@ int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
 
 /* GET request helpers */
 
-/**
- * struct ethnl_dump_ctx - context structure for generic dumpit() callback
- * @ops:        request ops of currently processed message type
- * @req_info:   parsed request header of processed request
- * @reply_data: data needed to compose the reply
- * @pos_ifindex: saved iteration position - ifindex
- *
- * These parameters are kept in struct netlink_callback as context preserved
- * between iterations. They are initialized by ethnl_default_start() and used
- * in ethnl_default_dumpit() and ethnl_default_done().
- */
-struct ethnl_dump_ctx {
-	const struct ethnl_request_ops	*ops;
-	struct ethnl_req_info		*req_info;
-	struct ethnl_reply_data		*reply_data;
-	unsigned long			pos_ifindex;
-};
-
 static const struct ethnl_request_ops *
 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_STRSET_GET]	= &ethnl_strset_request_ops,
@@ -533,9 +515,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				      const struct ethnl_dump_ctx *ctx,
-				      const struct genl_info *info)
+static int ethnl_default_dump_one(struct sk_buff *skb,
+				  const struct ethnl_dump_ctx *ctx,
+				  const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -546,13 +528,13 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 	if (!ehdr)
 		return -EMSGSIZE;
 
-	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
 	rtnl_lock();
 	ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
 	rtnl_unlock();
 	if (ret < 0)
 		goto out;
-	ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
+	ret = ethnl_fill_reply_header(skb, ctx->reply_data->dev,
+				      ctx->ops->hdr_attr);
 	if (ret < 0)
 		goto out;
 	ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data);
@@ -560,11 +542,29 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 out:
 	if (ctx->ops->cleanup_data)
 		ctx->ops->cleanup_data(ctx->reply_data);
-	ctx->reply_data->dev = NULL;
+
 	if (ret < 0)
 		genlmsg_cancel(skb, ehdr);
 	else
 		genlmsg_end(skb, ehdr);
+
+	return ret;
+}
+
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
+{
+	int ret;
+
+	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
+
+	if (ctx->ops->dump_one_dev)
+		ret = ctx->ops->dump_one_dev(skb, ctx, info);
+	else
+		ret = ethnl_default_dump_one(skb, ctx, info);
+
+	ctx->reply_data->dev = NULL;
 	return ret;
 }
 
@@ -593,6 +593,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
+			ctx->req_info->dev = dev;
 			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
 							 genl_info_dump(cb));
 
@@ -655,6 +656,12 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	ctx->reply_data = reply_data;
 	ctx->pos_ifindex = 0;
 
+	if (ctx->ops->dump_start) {
+		ret = ctx->ops->dump_start(ctx);
+		if (ret)
+			goto free_reply_data;
+	}
+
 	return 0;
 
 free_reply_data:
@@ -670,6 +677,9 @@ static int ethnl_default_done(struct netlink_callback *cb)
 {
 	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
 
+	if (ctx->ops->dump_done)
+		ctx->ops->dump_done(ctx);
+
 	kfree(ctx->reply_data);
 	kfree(ctx->req_info);
 
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 4db27182741f..d7506b08e5d6 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -307,6 +307,26 @@ struct ethnl_reply_data {
 	struct net_device		*dev;
 };
 
+/**
+ * struct ethnl_dump_ctx - context structure for generic dumpit() callback
+ * @ops:        request ops of currently processed message type
+ * @req_info:   parsed request header of processed request
+ * @reply_data: data needed to compose the reply
+ * @pos_ifindex: saved iteration position - ifindex
+ * @cmd_ctx: command-specific context to maintain across the dump.
+ *
+ * These parameters are kept in struct netlink_callback as context preserved
+ * between iterations. They are initialized by ethnl_default_start() and used
+ * in ethnl_default_dumpit() and ethnl_default_done().
+ */
+struct ethnl_dump_ctx {
+	const struct ethnl_request_ops	*ops;
+	struct ethnl_req_info		*req_info;
+	struct ethnl_reply_data		*reply_data;
+	unsigned long			pos_ifindex;
+	void				*cmd_ctx;
+};
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
@@ -372,6 +392,15 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  *	 - 0 if no configuration has changed
  *	 - 1 if configuration changed and notification should be generated
  *	 - negative errno on errors
+ * @dump_start:
+ *	Optional callback to prepare a dump operation, should there be a need
+ *	to maintain some context across the dump.
+ * @dump_one_dev;
+ *	Optional callback to generate all messages for a given netdev. This
+ *	is relevant only when a request can produce different results for the
+ *	same netdev depending on command-specific attributes.
+ * @dump_done:
+ *	Optional callback to cleanup any context allocated in ->dump_start()
  *
  * Description of variable parts of GET request handling when using the
  * unified infrastructure. When used, a pointer to an instance of this
@@ -408,6 +437,12 @@ struct ethnl_request_ops {
 			    struct genl_info *info);
 	int (*set)(struct ethnl_req_info *req_info,
 		   struct genl_info *info);
+
+	int (*dump_start)(struct ethnl_dump_ctx *ctx);
+	int (*dump_one_dev)(struct sk_buff *skb,
+			    struct ethnl_dump_ctx *ctx,
+			    const struct genl_info *info);
+	void (*dump_done)(struct ethnl_dump_ctx *ctx);
 };
 
 /* request handlers */
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:31 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:31 +0100
Subject: [PATCH net-next 1/7] net: ethtool: netlink: Allow per-netdevice DUMP operations
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-2-maxime.chevallier@bootlin.com>

We have a number of netlink commands in the ethnl family that may have
multiple objects to dump even for a single net_device, including :

 - PLCA, PSE-PD, phy: one message per PHY device
 - tsinfo: one message per timestamp source (netdev + phys)
 - rss: One per RSS context

To get this behaviour, these netlink commands need to roll a custom
->dumpit().

To prepare making per-netdev DUMP more generic in ethnl, introduce a
member in the ethnl ops to indicate if a given command may allow
pernetdev DUMPs (also referred to as filtered DUMPs).

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
 net/ethtool/netlink.h |  1 +
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 734849a57369..0815b28ba32f 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -578,21 +578,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 	int ret = 0;
 
 	rcu_read_lock();
-	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
-		dev_hold(dev);
+	if (ctx->req_info->dev) {
+		dev = ctx->req_info->dev;
 		rcu_read_unlock();
-
-		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
-
+		/* Filtered DUMP request targeted to a single netdev. We already
+		 * hold a ref to the netdev from ->start()
+		 */
+		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+						 genl_info_dump(cb));
 		rcu_read_lock();
-		dev_put(dev);
-
-		if (ret < 0 && ret != -EOPNOTSUPP) {
-			if (likely(skb->len))
-				ret = skb->len;
-			break;
+		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
+	} else {
+		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
+			dev_hold(dev);
+			rcu_read_unlock();
+
+			ret = ethnl_default_dump_one(skb, dev, ctx,
+						     genl_info_dump(cb));
+
+			rcu_read_lock();
+			dev_put(dev);
+
+			if (ret < 0 && ret != -EOPNOTSUPP) {
+				if (likely(skb->len))
+					ret = skb->len;
+				break;
+			}
+			ret = 0;
 		}
-		ret = 0;
 	}
 	rcu_read_unlock();
 
@@ -626,10 +639,10 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	}
 
 	ret = ethnl_default_parse(req_info, &info->info, ops, false);
-	if (req_info->dev) {
-		/* We ignore device specification in dump requests but as the
-		 * same parser as for non-dump (doit) requests is used, it
-		 * would take reference to the device if it finds one
+	if (req_info->dev && !ops->allow_pernetdev_dump) {
+		/* We ignore device specification in unfiltered dump requests
+		 * but as the same parser as for non-dump (doit) requests is
+		 * used, it would take reference to the device if it finds one
 		 */
 		netdev_put(req_info->dev, &req_info->dev_tracker);
 		req_info->dev = NULL;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index ec6ab5443a6f..4db27182741f 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -388,6 +388,7 @@ struct ethnl_request_ops {
 	unsigned int		req_info_size;
 	unsigned int		reply_data_size;
 	bool			allow_nodev_do;
+	bool			allow_pernetdev_dump;
 	u8			set_ntf_cmd;
 
 	int (*parse_request)(struct ethnl_req_info *req_info,
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:34 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:34 +0100
Subject: [PATCH net-next 4/7] net: ethtool: netlink: Introduce per-phy DUMP helpers
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-5-maxime.chevallier@bootlin.com>

As there are multiple ethnl commands that report messages based on
phy_device information, let's introduce a set of ethnl generic dump
helpers to allow DUMP support for each PHY on a given netdev.

This logic iterates over the phy_link_topology of each netdev (or a
single netdev for filtered DUMP), and call ethnl_default_dump_one() with
the req_info populated with ifindex + phyindex.

This allows re-using all the existing infra for phy-targetting commands
that already use ethnl generic helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 53 +++++++++++++++++++++++++++++++++++++++++++
 net/ethtool/netlink.h |  6 +++++
 2 files changed, 59 insertions(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index c0215f4acc05..474362af1aea 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -551,6 +551,59 @@ static int ethnl_default_dump_one(struct sk_buff *skb,
 	return ret;
 }
 
+/* Specific context for phy-targeting command DUMP operatins. We keep in context
+ * the latest phy_index we dumped, in case of an interrupted DUMP.
+ */
+struct ethnl_dump_ctx_perphy {
+	unsigned long phy_index;
+};
+
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx;
+
+	dump_ctx = kzalloc(sizeof(*dump_ctx), GFP_KERNEL);
+	if (!dump_ctx)
+		return -ENOMEM;
+
+	ctx->cmd_ctx = dump_ctx;
+
+	return 0;
+}
+
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx)
+{
+	kfree(ctx->cmd_ctx);
+}
+
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb,
+			      struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx = ctx->cmd_ctx;
+	struct net_device *dev = ctx->reply_data->dev;
+	struct phy_device_node *pdn;
+	int ret = 0;
+
+	if (!dev->link_topo)
+		return 0;
+
+	xa_for_each_start(&dev->link_topo->phys, dump_ctx->phy_index,
+			  pdn, dump_ctx->phy_index) {
+		ctx->req_info->phy_index = dump_ctx->phy_index;
+
+		/* We can re-use the original dump_one as ->prepare_data in
+		 * commands use ethnl_req_get_phydev(), which gets the PHY from
+		 * what's in req_info
+		 */
+		ret = ethnl_default_dump_one(skb, ctx, info);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
 				      struct ethnl_dump_ctx *ctx,
 				      const struct genl_info *info)
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index d7506b08e5d6..835376a9c84c 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -327,6 +327,12 @@ struct ethnl_dump_ctx {
 	void				*cmd_ctx;
 };
 
+/* Generic callbacks to be used by PHY targeting commands */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx);
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb, struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info);
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx);
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:32 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:32 +0100
Subject: [PATCH net-next 2/7] net: ethtool: netlink: Rename ethnl_default_dump_one
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-3-maxime.chevallier@bootlin.com>

As we work on getting more objects out of a per-netdev DUMP, rename
ethnl_default_dump_one() into ethnl_default_dump_one_dev(), making it
explicit that this dumps everything for one netdev.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 0815b28ba32f..6dddaea2babb 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -533,9 +533,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
-				  const struct ethnl_dump_ctx *ctx,
-				  const struct genl_info *info)
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      const struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -593,8 +593,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
-			ret = ethnl_default_dump_one(skb, dev, ctx,
-						     genl_info_dump(cb));
+			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+							 genl_info_dump(cb));
 
 			rcu_read_lock();
 			dev_put(dev);
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:35 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:35 +0100
Subject: [PATCH net-next 5/7] net: ethtool: phy: Convert the PHY_GET command to generic phy dump
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-6-maxime.chevallier@bootlin.com>

Now that we have an infrastructure in ethnl for perphy DUMPs, we can get
rid of the custom ->doit and ->dumpit to deal with PHY listing commands.

As most of the code was custom, this basically means re-writing how we
deal with PHY listing.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c |   9 +-
 net/ethtool/netlink.h |   4 -
 net/ethtool/phy.c     | 335 ++++++++++++------------------------------
 3 files changed, 103 insertions(+), 245 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 474362af1aea..b4d774786849 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -379,6 +379,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_MM_SET]		= &ethnl_mm_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_GET]	= &ethnl_tsconfig_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_SET]	= &ethnl_tsconfig_request_ops,
+	[ETHTOOL_MSG_PHY_GET]		= &ethnl_phy_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1332,10 +1333,10 @@ static const struct genl_ops ethtool_genl_ops[] = {
 	},
 	{
 		.cmd	= ETHTOOL_MSG_PHY_GET,
-		.doit	= ethnl_phy_doit,
-		.start	= ethnl_phy_start,
-		.dumpit	= ethnl_phy_dumpit,
-		.done	= ethnl_phy_done,
+		.doit	= ethnl_default_doit,
+		.start	= ethnl_default_start,
+		.dumpit	= ethnl_default_dumpit,
+		.done	= ethnl_default_done,
 		.policy = ethnl_phy_get_policy,
 		.maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1,
 	},
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 835376a9c84c..bc6dde699a32 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -541,10 +541,6 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info);
 int ethnl_rss_dump_start(struct netlink_callback *cb);
 int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_start(struct netlink_callback *cb);
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_done(struct netlink_callback *cb);
 int ethnl_tsinfo_start(struct netlink_callback *cb);
 int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_tsinfo_done(struct netlink_callback *cb);
diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c
index ed8f690f6bac..90c27dd1a5c6 100644
--- a/net/ethtool/phy.c
+++ b/net/ethtool/phy.c
@@ -11,296 +11,157 @@
 #include <linux/sfp.h>
 
 struct phy_req_info {
-	struct ethnl_req_info		base;
-	struct phy_device_node		*pdn;
+	struct ethnl_req_info base;
 };
 
-#define PHY_REQINFO(__req_base) \
-	container_of(__req_base, struct phy_req_info, base)
+struct phy_reply_data {
+	struct ethnl_reply_data	base;
+	u32 phyindex;
+	char *drvname;
+	char *name;
+	unsigned int upstream_type;
+	char *upstream_sfp_name;
+	unsigned int upstream_index;
+	char *downstream_sfp_name;
+};
+
+#define PHY_REPDATA(__reply_base) \
+	container_of(__reply_base, struct phy_reply_data, base)
 
 const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1] = {
 	[ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
-/* Caller holds rtnl */
-static ssize_t
-ethnl_phy_reply_size(const struct ethnl_req_info *req_base,
-		     struct netlink_ext_ack *extack)
+static int phy_reply_size(const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 	size_t size = 0;
 
-	ASSERT_RTNL();
-
 	/* ETHTOOL_A_PHY_INDEX */
 	size += nla_total_size(sizeof(u32));
 
 	/* ETHTOOL_A_DRVNAME */
-	if (phydev->drv)
-		size += nla_total_size(strlen(phydev->drv->name) + 1);
+	if (rep_data->drvname)
+		size += nla_total_size(strlen(rep_data->drvname) + 1);
 
 	/* ETHTOOL_A_NAME */
-	size += nla_total_size(strlen(dev_name(&phydev->mdio.dev)) + 1);
+	size += nla_total_size(strlen(rep_data->name) + 1);
 
 	/* ETHTOOL_A_PHY_UPSTREAM_TYPE */
 	size += nla_total_size(sizeof(u32));
 
-	if (phy_on_sfp(phydev)) {
-		const char *upstream_sfp_name = sfp_get_name(pdn->parent_sfp_bus);
-
-		/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
-		if (upstream_sfp_name)
-			size += nla_total_size(strlen(upstream_sfp_name) + 1);
+	if (rep_data->upstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->upstream_sfp_name) + 1);
 
-		/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	if (rep_data->upstream_index)
 		size += nla_total_size(sizeof(u32));
-	}
-
-	/* ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME */
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
 
-		if (sfp_name)
-			size += nla_total_size(strlen(sfp_name) + 1);
-	}
+	if (rep_data->downstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->downstream_sfp_name) + 1);
 
 	return size;
 }
 
-static int
-ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff *skb)
+static int phy_prepare_data(const struct ethnl_req_info *req_info,
+			    struct ethnl_reply_data *reply_data,
+			    const struct genl_info *info)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
-	enum phy_upstream ptype;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
+	struct phy_link_topology *topo = reply_data->dev->link_topo;
+	struct nlattr **tb = info->attrs;
+	struct phy_device_node *pdn;
+	struct phy_device *phydev;
 
-	ptype = pdn->upstream_type;
+	/* RTNL is held by th caller */
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
+				      info->extack);
+	if (IS_ERR_OR_NULL(phydev))
+		return -EOPNOTSUPP;
 
-	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, phydev->phyindex) ||
-	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, dev_name(&phydev->mdio.dev)) ||
-	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, ptype))
-		return -EMSGSIZE;
+	pdn = xa_load(&topo->phys, phydev->phyindex);
+	if (!pdn)
+		return -EOPNOTSUPP;
 
-	if (phydev->drv &&
-	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, phydev->drv->name))
-		return -EMSGSIZE;
+	rep_data->phyindex = phydev->phyindex;
+	rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
+	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+	rep_data->upstream_type = pdn->upstream_type;
 
-	if (ptype == PHY_UPSTREAM_PHY) {
+	if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
 		struct phy_device *upstream = pdn->upstream.phydev;
-		const char *sfp_upstream_name;
-
-		/* Parent index */
-		if (nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX, upstream->phyindex))
-			return -EMSGSIZE;
-
-		if (pdn->parent_sfp_bus) {
-			sfp_upstream_name = sfp_get_name(pdn->parent_sfp_bus);
-			if (sfp_upstream_name &&
-			    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
-					   sfp_upstream_name))
-				return -EMSGSIZE;
-		}
+		rep_data->upstream_index = upstream->phyindex;
 	}
 
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
+	if (pdn->parent_sfp_bus)
+		rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
+						      GFP_KERNEL);
 
-		if (sfp_name &&
-		    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
-				   sfp_name))
-			return -EMSGSIZE;
-	}
+	if (phydev->sfp_bus)
+		rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
+							GFP_KERNEL);
 
 	return 0;
 }
 
-static int ethnl_phy_parse_request(struct ethnl_req_info *req_base,
-				   struct nlattr **tb,
-				   struct netlink_ext_ack *extack)
+static int phy_fill_reply(struct sk_buff *skb,
+			  const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_link_topology *topo = req_base->dev->link_topo;
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device *phydev;
-
-	phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PHY_HEADER],
-				      extack);
-	if (!phydev)
-		return 0;
-
-	if (IS_ERR(phydev))
-		return PTR_ERR(phydev);
-
-	if (!topo)
-		return 0;
-
-	req_info->pdn = xa_load(&topo->phys, phydev->phyindex);
-
-	return 0;
-}
-
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info)
-{
-	struct phy_req_info req_info = {};
-	struct nlattr **tb = info->attrs;
-	struct sk_buff *rskb;
-	void *reply_payload;
-	int reply_len;
-	int ret;
-
-	ret = ethnl_parse_header_dev_get(&req_info.base,
-					 tb[ETHTOOL_A_PHY_HEADER],
-					 genl_info_net(info), info->extack,
-					 true);
-	if (ret < 0)
-		return ret;
-
-	rtnl_lock();
-
-	ret = ethnl_phy_parse_request(&req_info.base, tb, info->extack);
-	if (ret < 0)
-		goto err_unlock_rtnl;
-
-	/* No PHY, return early */
-	if (!req_info.pdn)
-		goto err_unlock_rtnl;
-
-	ret = ethnl_phy_reply_size(&req_info.base, info->extack);
-	if (ret < 0)
-		goto err_unlock_rtnl;
-	reply_len = ret + ethnl_reply_header_size();
-
-	rskb = ethnl_reply_init(reply_len, req_info.base.dev,
-				ETHTOOL_MSG_PHY_GET_REPLY,
-				ETHTOOL_A_PHY_HEADER,
-				info, &reply_payload);
-	if (!rskb) {
-		ret = -ENOMEM;
-		goto err_unlock_rtnl;
-	}
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	ret = ethnl_phy_fill_reply(&req_info.base, rskb);
-	if (ret)
-		goto err_free_msg;
-
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	genlmsg_end(rskb, reply_payload);
-
-	return genlmsg_reply(rskb, info);
-
-err_free_msg:
-	nlmsg_free(rskb);
-err_unlock_rtnl:
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	return ret;
-}
-
-struct ethnl_phy_dump_ctx {
-	struct phy_req_info	*phy_req_info;
-	unsigned long ifindex;
-	unsigned long phy_index;
-};
-
-int ethnl_phy_start(struct netlink_callback *cb)
-{
-	const struct genl_info *info = genl_info_dump(cb);
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	int ret;
+	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, rep_data->phyindex) ||
+	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, rep_data->name) ||
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, rep_data->upstream_type))
+		return -EMSGSIZE;
 
-	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+	if (rep_data->drvname &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, rep_data->drvname))
+		return -EMSGSIZE;
 
-	ctx->phy_req_info = kzalloc(sizeof(*ctx->phy_req_info), GFP_KERNEL);
-	if (!ctx->phy_req_info)
-		return -ENOMEM;
+	if (rep_data->upstream_index &&
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX,
+			rep_data->upstream_index))
+		return -EMSGSIZE;
 
-	ret = ethnl_parse_header_dev_get(&ctx->phy_req_info->base,
-					 info->attrs[ETHTOOL_A_PHY_HEADER],
-					 sock_net(cb->skb->sk), cb->extack,
-					 false);
-	ctx->ifindex = 0;
-	ctx->phy_index = 0;
+	if (rep_data->upstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+			   rep_data->upstream_sfp_name))
+		return -EMSGSIZE;
 
-	if (ret)
-		kfree(ctx->phy_req_info);
+	if (rep_data->downstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+			   rep_data->downstream_sfp_name))
+		return -EMSGSIZE;
 
-	return ret;
+	return 0;
 }
 
-int ethnl_phy_done(struct netlink_callback *cb)
+static void phy_cleanup_data(struct ethnl_reply_data *reply_data)
 {
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-
-	if (ctx->phy_req_info->base.dev)
-		ethnl_parse_header_dev_put(&ctx->phy_req_info->base);
-
-	kfree(ctx->phy_req_info);
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	return 0;
+	kfree(rep_data->drvname);
+	kfree(rep_data->name);
+	kfree(rep_data->upstream_sfp_name);
+	kfree(rep_data->downstream_sfp_name);
 }
 
-static int ethnl_phy_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				  struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct phy_req_info *pri = ctx->phy_req_info;
-	struct phy_device_node *pdn;
-	int ret = 0;
-	void *ehdr;
-
-	if (!dev->link_topo)
-		return 0;
-
-	xa_for_each_start(&dev->link_topo->phys, ctx->phy_index, pdn, ctx->phy_index) {
-		ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_PHY_GET_REPLY);
-		if (!ehdr) {
-			ret = -EMSGSIZE;
-			break;
-		}
-
-		ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_PHY_HEADER);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		pri->pdn = pdn;
-		ret = ethnl_phy_fill_reply(&pri->base, skb);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		genlmsg_end(skb, ehdr);
-	}
+const struct ethnl_request_ops ethnl_phy_request_ops = {
+	.request_cmd		= ETHTOOL_MSG_PHY_GET,
+	.reply_cmd		= ETHTOOL_MSG_PHY_GET_REPLY,
+	.hdr_attr		= ETHTOOL_A_PHY_HEADER,
+	.req_info_size		= sizeof(struct phy_req_info),
+	.reply_data_size	= sizeof(struct phy_reply_data),
 
-	return ret;
-}
+	.prepare_data		= phy_prepare_data,
+	.reply_size		= phy_reply_size,
+	.fill_reply		= phy_fill_reply,
+	.cleanup_data		= phy_cleanup_data,
 
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct net *net = sock_net(skb->sk);
-	struct net_device *dev;
-	int ret = 0;
-
-	rtnl_lock();
-
-	if (ctx->phy_req_info->base.dev) {
-		ret = ethnl_phy_dump_one_dev(skb, ctx->phy_req_info->base.dev, cb);
-	} else {
-		for_each_netdev_dump(net, dev, ctx->ifindex) {
-			ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-			if (ret)
-				break;
-
-			ctx->phy_index = 0;
-		}
-	}
-	rtnl_unlock();
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
 
-	return ret;
-}
+	.allow_pernetdev_dump	= true,
+};
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:36 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:36 +0100
Subject: [PATCH net-next 6/7] net: ethtool: plca: Use per-PHY DUMP operations
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-7-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PLCA-able PHY on the link.

This is done for both PLCA status and PLCA config.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/plca.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c
index e1f7820a6158..2148ff607561 100644
--- a/net/ethtool/plca.c
+++ b/net/ethtool/plca.c
@@ -191,6 +191,12 @@ const struct ethnl_request_ops ethnl_plca_cfg_request_ops = {
 
 	.set			= ethnl_set_plca,
 	.set_ntf_cmd		= ETHTOOL_MSG_PLCA_NTF,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
 
 // PLCA get status message -------------------------------------------------- //
@@ -268,4 +274,10 @@ const struct ethnl_request_ops ethnl_plca_status_request_ops = {
 	.prepare_data		= plca_get_status_prepare_data,
 	.reply_size		= plca_get_status_reply_size,
 	.fill_reply		= plca_get_status_fill_reply,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From maxime.chevallier at bootlin.com  Wed Mar  5 06:19:37 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed,  5 Mar 2025 15:19:37 +0100
Subject: [PATCH net-next 7/7] net: ethtool: pse-pd: Use per-PHY DUMP operations
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305141938.319282-8-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PSE PHY on the link.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/pse-pd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
index 4f6b99eab2a6..f3d14be8bdd9 100644
--- a/net/ethtool/pse-pd.c
+++ b/net/ethtool/pse-pd.c
@@ -314,4 +314,10 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
 
 	.set			= ethnl_set_pse,
 	/* PSE has no notification */
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From tudor.ambarus at linaro.org  Wed Mar  5 06:27:31 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Wed, 5 Mar 2025 14:27:31 +0000
Subject: [PATCH 2/2] clk: samsung: Drop unused clk.h and of.h headers
In-Reply-To: <20250304-clk-samsung-headers-cleanup-v1-2-81718e38246e@linaro.org>
References: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
 <20250304-clk-samsung-headers-cleanup-v1-2-81718e38246e@linaro.org>
Message-ID: <ac6ef67b-84bb-4679-a344-07bba50e054b@linaro.org>



On 3/4/25 6:45 PM, Krzysztof Kozlowski wrote:
>  drivers/clk/samsung/clk-gs101.c          | 1 -

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>


From jic23 at kernel.org  Wed Mar  5 06:38:24 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 5 Mar 2025 14:38:24 +0000
Subject: [PATCH 3/8] iio: trigger: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250224180150.3689638-4-fabrice.gasnier@foss.st.com>
References: <20250224180150.3689638-1-fabrice.gasnier@foss.st.com>
	<20250224180150.3689638-4-fabrice.gasnier@foss.st.com>
Message-ID: <20250305143824.138a2605@jic23-huawei>

On Mon, 24 Feb 2025 19:01:45 +0100
Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:

> From: Olivier Moysan <olivier.moysan at foss.st.com>
> 
> Add support for STM32MP25 SoC. Use newly introduced compatible to handle
> this new HW variant. Add new trigger definitions that can be used by the
> stm32 analog-to-digital converter. Use compatible data to identify them.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>

Hi. I'm not really following why you can't use devm calls for the
trigger probe path and hence why you need the explicit remove.
Feels like a lot of infrastructure and I can't see why we need it.

Jonathan


> @@ -54,25 +82,49 @@ bool is_stm32_lptim_trigger(struct iio_trigger *trig)
>  }
>  EXPORT_SYMBOL(is_stm32_lptim_trigger);
>  
> -static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv)
> +static void stm32_lptim_unregister_triggers(struct stm32_lptim_trigger *priv)
>  {
> -	struct iio_trigger *trig;
> +	struct iio_trigger *tr;
>  
> -	trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg);
> -	if  (!trig)
> -		return -ENOMEM;
> +	list_for_each_entry(tr, &priv->tr_list, alloc_list)
> +		iio_trigger_unregister(tr);
> +}
> +
> +static int stm32_lptim_register_triggers(struct stm32_lptim_trigger *priv)
> +{
> +	const char * const *cur = priv->triggers;
> +	int ret;
>  
> -	trig->dev.parent = priv->dev->parent;
> -	trig->ops = &stm32_lptim_trigger_ops;
> -	iio_trigger_set_drvdata(trig, priv);
> +	INIT_LIST_HEAD(&priv->tr_list);
>  
> -	return devm_iio_trigger_register(priv->dev, trig);
> +	while (cur && *cur) {
> +		struct iio_trigger *trig;
> +
> +		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
> +		if  (!trig)
> +			return -ENOMEM;
> +
> +		trig->dev.parent = priv->dev->parent;
> +		trig->ops = &stm32_lptim_trigger_ops;
> +		iio_trigger_set_drvdata(trig, priv);
> +
> +		ret = iio_trigger_register(trig);

I'm not really following why you can't use devm_iio_trigger_register() here
and avoid your own tracking with the list below.


> +		if (ret)
> +			return ret;
> +
> +		list_add_tail(&trig->alloc_list, &priv->tr_list);
> +		cur++;
> +	}
> +
> +	return 0;
>  }
>  
>  static int stm32_lptim_trigger_probe(struct platform_device *pdev)
>  {
>  	struct stm32_lptim_trigger *priv;
> +	struct stm32_lptim_cfg const *lptim_cfg;
>  	u32 index;
> +	int ret;
>  
>  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>  	if (!priv)
> @@ -81,23 +133,42 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev)
>  	if (device_property_read_u32(&pdev->dev, "reg", &index))
>  		return -EINVAL;
>  
> -	if (index >= ARRAY_SIZE(stm32_lptim_triggers))
> +	lptim_cfg = device_get_match_data(&pdev->dev);
> +
> +	if (index >= lptim_cfg->nb_triggers)
>  		return -EINVAL;
>  
>  	priv->dev = &pdev->dev;
> -	priv->trg = stm32_lptim_triggers[index];
> +	priv->triggers = lptim_cfg->triggers[index];
> +
> +	ret = stm32_lptim_register_triggers(priv);
> +	if (ret) {
> +		stm32_lptim_unregister_triggers(priv);
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	return 0;
> +}
> +
> +static void stm32_lptim_trigger_remove(struct platform_device *pdev)
> +{
> +	struct stm32_lptim_trigger *priv = platform_get_drvdata(pdev);
>  
> -	return stm32_lptim_setup_trig(priv);
> +	stm32_lptim_unregister_triggers(priv);

Why not a devm_add_action_or_reset?
or for that matter a devm_iio_trigger_register() in the first place.

>  }
>  
>  static const struct of_device_id stm32_lptim_trig_of_match[] = {
> -	{ .compatible = "st,stm32-lptimer-trigger", },
> +	{ .compatible = "st,stm32-lptimer-trigger", .data = (void *)&stm32mp15_lptim_cfg },
> +	{ .compatible = "st,stm32mp25-lptimer-trigger", .data = (void *)&stm32mp25_lptim_cfg},
Why cast away a const then pass it to a const void *?

That is I don't think the casts are needed.

>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match);
>  
>  static struct platform_driver stm32_lptim_trigger_driver = {
>  	.probe = stm32_lptim_trigger_probe,
> +	.remove = stm32_lptim_trigger_remove,
>  	.driver = {
>  		.name = "stm32-lptimer-trigger",
>  		.of_match_table = stm32_lptim_trig_of_match,
> diff --git a/include/linux/iio/timer/stm32-lptim-trigger.h b/include/linux/iio/timer/stm32-lptim-trigger.h
> index a34dcf6a6001..ce3cf0addb2e 100644
> --- a/include/linux/iio/timer/stm32-lptim-trigger.h
> +++ b/include/linux/iio/timer/stm32-lptim-trigger.h
> @@ -14,6 +14,15 @@
>  #define LPTIM1_OUT	"lptim1_out"
>  #define LPTIM2_OUT	"lptim2_out"
>  #define LPTIM3_OUT	"lptim3_out"
> +#define LPTIM4_OUT	"lptim4_out"
> +#define LPTIM5_OUT	"lptim5_out"
> +
> +#define LPTIM1_CH1	"lptim1_ch1"
> +#define LPTIM1_CH2	"lptim1_ch2"
> +#define LPTIM2_CH1	"lptim2_ch1"
> +#define LPTIM2_CH2	"lptim2_ch2"
> +#define LPTIM3_CH1	"lptim3_ch1"
> +#define LPTIM4_CH1	"lptim4_ch1"
>  
>  #if IS_REACHABLE(CONFIG_IIO_STM32_LPTIMER_TRIGGER)
>  bool is_stm32_lptim_trigger(struct iio_trigger *trig);



From florin.leotescu at oss.nxp.com  Wed Mar  5 06:49:55 2025
From: florin.leotescu at oss.nxp.com (Florin Leotescu (OSS))
Date: Wed, 5 Mar 2025 14:49:55 +0000
Subject: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml
 schema
In-Reply-To: <CAEnQRZCT4vfFBApv+C3Wp17Fk0-Rwx36h4eCTTygaXFYFipEGg@mail.gmail.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-2-florin.leotescu@oss.nxp.com>
 <Z8cp1xoIXT8lgD8T@lizhi-Precision-Tower-5810>
 <CAEnQRZCT4vfFBApv+C3Wp17Fk0-Rwx36h4eCTTygaXFYFipEGg@mail.gmail.com>
Message-ID: <DU7PR04MB11163EE82B1F5228F797A0D64FFCB2@DU7PR04MB11163.eurprd04.prod.outlook.com>

Hello Frank, Conor, Krzysztof,

Thanks a lot for your feedback, time and patience. 
We will address the changes in V4.

Regards,
Florin

-----Original Message-----
From: Daniel Baluta <daniel.baluta at gmail.com> 
Sent: Wednesday, March 5, 2025 2:48 PM
To: Frank Li <frank.li at nxp.com>; Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Florin Leotescu (OSS) <florin.leotescu at oss.nxp.com>; Jean Delvare <jdelvare at suse.com>; Guenter Roeck <linux at roeck-us.net>; Rob Herring <robh at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Michael Shych <michaelsh at nvidia.com>; linux-hwmon at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; Viorel Suman <viorel.suman at nxp.com>; Carlos Song <carlos.song at nxp.com>; linux-arm-kernel at lists.infradead.org; imx at lists.linux.dev; festevam at gmail.com; Florin Leotescu <florin.leotescu at nxp.com>
Subject: Re: [PATCH v3 1/3] dt-bindings: hwmon: Add Microchip emc2305 yaml schema

Hello Frank, Conor, Krzysztof,

Thanks a lot for your comments and help.

In this initial patchseries we only add minimal OF support and introduce a minimal binding.

> How did you pickup the maintainer entry?

We got the author of the first commit for See 0d8400c5a2ce ("hwmon: (emc2305) add support for EMC2301/2/3/5 RPM-based")

> If only one reg You can go through trivial-devices.yaml

This is not a trivial device as we will add some specific properties with our next patches (e.g polarity etc)

> Missing descriptions of the fans, no?
> missing $ref to fan-controller schema.

Do we need to add this now? As this is only the minimal binding support. We want to add that in a follow up patch when we go into specifics.

> The emc2301 label here can be dropped, it is not used.

Will fix.

> The nodename should be "fan-controller", not pwm here I guess.

Sure, will fix.

On Tue, Mar 4, 2025 at 6:56?PM Frank Li <Frank.li at nxp.com> wrote:
>
> On Tue, Mar 04, 2025 at 06:21:34PM +0200, florin.leotescu at oss.nxp.com wrote:
> > From: Florin Leotescu <florin.leotescu at nxp.com>
> >
> > Introduce yaml schema for Microchip emc2305 pwm fan controller.
> >
> > Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> > ---
> >  .../bindings/hwmon/microchip,emc2305.yaml     | 43 +++++++++++++++++++
> >  1 file changed, 43 insertions(+)
> >  create mode 100644 
> > Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> >
> > diff --git 
> > a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml 
> > b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > new file mode 100644
> > index 000000000000..cac0075a65bb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > @@ -0,0 +1,43 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Microchip EMC2305 SMBus compliant PWM fan controller
> > +
> > +maintainers:
> > +  - Michael Shych <michaelsh at nvidia.com>
>
> who is it? look like not Microchip and hwmon maintainer.
>
> > +
> > +description: |
>
> Needn't |
>
> > +  Microchip EMC2301/2/3/5 pwm controller which supports up  to five 
> > + programmable fan control circuits
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - microchip,emc2301
> > +      - microchip,emc2302
> > +      - microchip,emc2303
> > +      - microchip,emc2305
>
> According to your driver code look like all compatible with 
> microchip,emc2301
>
> oneOf:
>   - enum:
>       - microchip,emc2301
>   - items:
>       - enum:
>           - microchip,emc2302
>           - microchip,emc2303
>           - microchip,emc2305
>       - const: microchip,emc2301
>
> So your driver just need one "microchip,emc2301" compatible string.
>
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    i2c {
> > +        #address-cells = <1>;
> > +        #size-cells = <0>;
> > +
> > +        emc2301: pwm at 2f {
> > +            compatible = "microchip,emc2301";
> > +            reg = <0x2f>;
>
> If only one reg:
> You can go through trivial-devices.yaml
>
> Frank
>
> > +        };
> > +    };
> > --
> > 2.34.1
> >
>

From ulf.hansson at linaro.org  Wed Mar  5 06:53:24 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 5 Mar 2025 15:53:24 +0100
Subject: [PATCH] pmdomain: rockchip: add regulator dependency
In-Reply-To: <20250304142803.689201-1-arnd@kernel.org>
References: <20250304142803.689201-1-arnd@kernel.org>
Message-ID: <CAPDyKFo79xyTOKxN7A52J2Et50++fifdosUpyb2mm3NMc+EC1Q@mail.gmail.com>

On Tue, 4 Mar 2025 at 15:28, Arnd Bergmann <arnd at kernel.org> wrote:
>
> From: Arnd Bergmann <arnd at arndb.de>
>
> When CONFIG_REGULATOR is disabled, this pmdomain driver fails to build:
>
> drivers/pmdomain/rockchip/pm-domains.c:653:30: error: implicit declaration of function 'devm_of_regulator_get'; did you mean 'devm_regulator_get'? [-Wimplicit-function-declaration]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                              ^~~~~~~~~~~~~~~~~~~~~
>       |                              devm_regulator_get
> drivers/pmdomain/rockchip/pm-domains.c:653:28: error: assignment to 'struct regulator *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
>   653 |                 pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
>       |                            ^
>
> Add a Kconfig dependency.
>
> Fixes: db6df2e3fc16 ("pmdomain: rockchip: add regulator support")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/pmdomain/rockchip/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/pmdomain/rockchip/Kconfig b/drivers/pmdomain/rockchip/Kconfig
> index 7e4f9b628f0b..218d43186e5b 100644
> --- a/drivers/pmdomain/rockchip/Kconfig
> +++ b/drivers/pmdomain/rockchip/Kconfig
> @@ -5,6 +5,7 @@ config ROCKCHIP_PM_DOMAINS
>         bool "Rockchip generic power domain"
>         depends on PM
>         depends on HAVE_ARM_SMCCC_DISCOVERY
> +       depends on REGULATOR
>         select PM_GENERIC_DOMAINS
>         help
>           Say y here to enable power domain support.
> --
> 2.39.5
>


From eichest at gmail.com  Wed Mar  5 06:43:14 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Wed,  5 Mar 2025 15:43:14 +0100
Subject: [PATCH v2 0/2] phy: freescale: imx8m-pcie: fix and cleanup phy
Message-ID: <20250305144355.20364-1-eichest@gmail.com>

The imx8m-pcie PHY PLL fails to lock under certain conditions when
returning from suspend. This is resolved by asserting the PHY reset when
powering off the PHY during suspend. This ensures that the PHY is
properly reset when powering on again in resume.

Changes in v2:
- Remove unnecessary check if perst is not null (Philipp)

Stefan Eichenberger (2):
  phy: freescale: imx8m-pcie: cleanup reset logic
  phy: freescale: imx8m-pcie: assert phy reset and perst in power off

 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 23 +++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

-- 
2.45.2



From eichest at gmail.com  Wed Mar  5 06:43:15 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Wed,  5 Mar 2025 15:43:15 +0100
Subject: [PATCH v2 1/2] phy: freescale: imx8m-pcie: cleanup reset logic
In-Reply-To: <20250305144355.20364-1-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
Message-ID: <20250305144355.20364-2-eichest@gmail.com>

From: Stefan Eichenberger <stefan.eichenberger at toradex.com>

Remove the switch statement and base perst release on whether it is
found in the device tree. The probe function fails without the reset
property, making it mandatory. Therefore, always release reset
independent of the variant.

This does not change the behavior of the driver but reduces driver
complexity and allows for easier future modifications.

Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
---
 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index e98361dcdeadf..5b505e34ca364 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -141,15 +141,9 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
 			   IMX8MM_GPR_PCIE_REF_CLK_PLL);
 	usleep_range(100, 200);
 
-	switch (imx8_phy->drvdata->variant) {
-	case IMX8MP:
-		reset_control_deassert(imx8_phy->perst);
-		fallthrough;
-	case IMX8MM:
-		reset_control_deassert(imx8_phy->reset);
-		usleep_range(200, 500);
-		break;
-	}
+	reset_control_deassert(imx8_phy->perst);
+	reset_control_deassert(imx8_phy->reset);
+	usleep_range(200, 500);
 
 	/* Do the PHY common block reset */
 	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
-- 
2.45.2



From eichest at gmail.com  Wed Mar  5 06:43:16 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Wed,  5 Mar 2025 15:43:16 +0100
Subject: [PATCH v2 2/2] phy: freescale: imx8m-pcie: assert phy reset and perst in power off
In-Reply-To: <20250305144355.20364-1-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
Message-ID: <20250305144355.20364-3-eichest@gmail.com>

From: Stefan Eichenberger <stefan.eichenberger at toradex.com>

Ensure the PHY reset and perst is asserted during power-off to
guarantee it is in a reset state upon repeated power-on calls. This
resolves an issue where the PHY may not properly initialize during
subsequent power-on cycles. Power-on will deassert the reset at the
appropriate time after tuning the PHY parameters.

During suspend/resume cycles, we observed that the PHY PLL failed to
lock during resume when the CPU temperature increased from 65C to 75C.
The observed errors were:
  phy phy-32f00000.pcie-phy.3: phy poweron failed --> -110
  imx6q-pcie 33800000.pcie: waiting for PHY ready timeout!
  imx6q-pcie 33800000.pcie: PM: dpm_run_callback(): genpd_resume_noirq+0x0/0x80 returns -110
  imx6q-pcie 33800000.pcie: PM: failed to resume noirq: error -110

This resulted in a complete CPU freeze, which is resolved by ensuring
the PHY is in reset during power-on, thus preventing PHY PLL failures.

Cc: stable at vger.kernel.org
Fixes: 1aa97b002258 ("phy: freescale: pcie: Initialize the imx8 pcie standalone phy driver")
Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
---
 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index 5b505e34ca364..7355d9921b646 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -156,6 +156,16 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
 	return ret;
 }
 
+static int imx8_pcie_phy_power_off(struct phy *phy)
+{
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	reset_control_assert(imx8_phy->reset);
+	reset_control_assert(imx8_phy->perst);
+
+	return 0;
+}
+
 static int imx8_pcie_phy_init(struct phy *phy)
 {
 	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
@@ -176,6 +186,7 @@ static const struct phy_ops imx8_pcie_phy_ops = {
 	.init		= imx8_pcie_phy_init,
 	.exit		= imx8_pcie_phy_exit,
 	.power_on	= imx8_pcie_phy_power_on,
+	.power_off	= imx8_pcie_phy_power_off,
 	.owner		= THIS_MODULE,
 };
 
-- 
2.45.2



From jic23 at kernel.org  Wed Mar  5 06:45:39 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 5 Mar 2025 14:45:39 +0000
Subject: [PATCH v3 3/8] iio: trigger: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250305094935.595667-4-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
	<20250305094935.595667-4-fabrice.gasnier@foss.st.com>
Message-ID: <20250305144539.54a75689@jic23-huawei>

On Wed, 5 Mar 2025 10:49:30 +0100
Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:

> From: Olivier Moysan <olivier.moysan at foss.st.com>
> 
> Add support for STM32MP25 SoC. Use newly introduced compatible to handle
> this new HW variant. Add new trigger definitions that can be used by the
> stm32 analog-to-digital converter. Use compatible data to identify them.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
Hi. Oops I replied to v1 without looking for other versions.
From a quick glance feedback still applies here.



From alyssa at rosenzweig.io  Wed Mar  5 06:45:49 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Wed, 5 Mar 2025 09:45:49 -0500
Subject: [PATCH v8 0/5] Driver for pre-DCP apple display controller.
In-Reply-To: <18f9658f-f2ca-4fd9-809c-ec4d198072be@linaro.org>
References: <20250224-adpdrm-v8-0-cccf96710f0f@gmail.com>
 <174118223158.156873.6982508045942987984.b4-ty@rosenzweig.io>
 <Z8hZKW_F-HtzYm-w@blossom>
 <18f9658f-f2ca-4fd9-809c-ec4d198072be@linaro.org>
Message-ID: <Z8hjnRyCn82OrDcO@blossom>

> Yeah it's because you applied the whole patchset, and discarded/skipped
> patch 3 & 4 afterwards, so b4 gets confused.
> 
> Next time specify which patch you want to apply with -P 1,2,5
> and b4 with know which patch you applied and generate a good ty patch.

Ah nice, didn't know about -P, thanks!


From linux at armlinux.org.uk  Wed Mar  5 06:43:52 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 5 Mar 2025 14:43:52 +0000
Subject: [PATCH v8 2/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <20250305091246.106626-3-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091856epcas5p4228c09989c7acfe45a99541eef01fbcd@epcas5p4.samsung.com>
 <20250305091246.106626-3-swathi.ks@samsung.com>
Message-ID: <Z8hjKI1ZqU19nrTP@shell.armlinux.org.uk>

On Wed, Mar 05, 2025 at 02:42:46PM +0530, Swathi K S wrote:
> The FSD SoC contains two instance of the Synopsys DWC ethernet QOS IP core.
> The binding that it uses is slightly different from existing ones because
> of the integration (clocks, resets).
> 
> Signed-off-by: Swathi K S <swathi.ks at samsung.com>

This looks much better!

Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From ulf.hansson at linaro.org  Wed Mar  5 06:53:29 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 5 Mar 2025 15:53:29 +0100
Subject: [PATCH] pmdomain: amlogic: fix T7 ISP secpower
In-Reply-To: <20250303-fix-t7-pwrc-v1-1-b563612bcd86@amlogic.com>
References: <20250303-fix-t7-pwrc-v1-1-b563612bcd86@amlogic.com>
Message-ID: <CAPDyKFoTBt4g=M1rHrZEPLO1y61csy3_cHfJDANPbvV+bH+YXw@mail.gmail.com>

On Mon, 3 Mar 2025 at 10:06, Xianwei Zhao via B4 Relay
<devnull+xianwei.zhao.amlogic.com at kernel.org> wrote:
>
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>
> ISP and MIPI_ISP, these two have a parent-child relationship,
> ISP depends on MIPI_ISP.
>
> Fixes: ca75e4b214c6 ("pmdomain: amlogic: Add support for T7 power domains controller")
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>

Applied for fixes and by adding a stable tag, thanks!

Kind regards
Uffe


> ---
>  drivers/pmdomain/amlogic/meson-secure-pwrc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> index 42ce41a2fe3a..ff76ea36835e 100644
> --- a/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> +++ b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
> @@ -221,7 +221,7 @@ static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
>         SEC_PD(T7_VI_CLK2,      0),
>         /* ETH is for ethernet online wakeup, and should be always on */
>         SEC_PD(T7_ETH,          GENPD_FLAG_ALWAYS_ON),
> -       SEC_PD(T7_ISP,          0),
> +       TOP_PD(T7_ISP,          0, PWRC_T7_MIPI_ISP_ID),
>         SEC_PD(T7_MIPI_ISP,     0),
>         TOP_PD(T7_GDC,          0, PWRC_T7_NIC3_ID),
>         TOP_PD(T7_DEWARP,       0, PWRC_T7_NIC3_ID),
>
> ---
> base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
> change-id: 20250303-fix-t7-pwrc-f33650b190ef
>
> Best regards,
> --
> Xianwei Zhao <xianwei.zhao at amlogic.com>
>
>


From mike.leach at linaro.org  Wed Mar  5 06:58:31 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Wed, 5 Mar 2025 14:58:31 +0000
Subject: [PATCH v15 02/10] Coresight: Add trace_id function to retrieving
 the trace ID
In-Reply-To: <7fe6c345-85cf-4114-b419-f50d1a6cbef1@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-3-quic_jiegan@quicinc.com> <CAJ9a7VgGp4YqzN-yx0x+NiZG8now6SCmnimaou2Z=exYcoiegw@mail.gmail.com>
 <7fe6c345-85cf-4114-b419-f50d1a6cbef1@quicinc.com>
Message-ID: <CAJ9a7Vhx293H6r6HGwVOQ46PDu+sQ8LPONvAbwAtxGFt0ad+Ww@mail.gmail.com>

Hi Jie

On Wed, 5 Mar 2025 at 13:27, Jie Gan <quic_jiegan at quicinc.com> wrote:
>
>
>
> On 3/5/2025 7:07 PM, Mike Leach wrote:
> > Hi,
> >
> > On Mon, 3 Mar 2025 at 03:30, Jie Gan <quic_jiegan at quicinc.com> wrote:
> >>
> >> Add 'trace_id' function pointer in coresight_ops. It's responsible for retrieving
> >> the device's trace ID.
> >>
> >> Co-developed-by: James Clark <james.clark at linaro.org>
> >> Signed-off-by: James Clark <james.clark at linaro.org>
> >> Reviewed-by: James Clark <james.clark at linaro.org>
> >> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> >> ---
> >>   drivers/hwtracing/coresight/coresight-core.c  | 30 +++++++++++++++++++
> >>   drivers/hwtracing/coresight/coresight-dummy.c | 13 +++++++-
> >>   .../coresight/coresight-etm3x-core.c          |  1 +
> >>   .../coresight/coresight-etm4x-core.c          |  1 +
> >>   drivers/hwtracing/coresight/coresight-stm.c   | 11 +++++++
> >>   drivers/hwtracing/coresight/coresight-tpda.c  | 11 +++++++
> >>   include/linux/coresight.h                     |  5 ++++
> >>   7 files changed, 71 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> >> index ab55e10d4b79..32aa07f4f8c1 100644
> >> --- a/drivers/hwtracing/coresight/coresight-core.c
> >> +++ b/drivers/hwtracing/coresight/coresight-core.c
> >> @@ -24,6 +24,7 @@
> >>   #include "coresight-etm-perf.h"
> >>   #include "coresight-priv.h"
> >>   #include "coresight-syscfg.h"
> >> +#include "coresight-trace-id.h"
> >>
> >>   /*
> >>    * Mutex used to lock all sysfs enable and disable actions and loading and
> >> @@ -1557,6 +1558,35 @@ void coresight_remove_driver(struct amba_driver *amba_drv,
> >>   }
> >>   EXPORT_SYMBOL_GPL(coresight_remove_driver);
> >>
> >> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
> >> +                              struct coresight_device *sink)
> >> +{
> >> +       int trace_id;
> >> +       int cpu = source_ops(csdev)->cpu_id(csdev);
> >> +
> >
> > This is a global funciton so need to check that this csdev is a
> > source,. and does provide a cpu  function before calling it.
> >
>
> Hi Mike,
>
> I put this function here because it's required by etm3x and etm4x. It's
> intended to be called only by ETM devices, which are definitely source
> devices and have a cpu function.
>

I fully understand the intent, but for a function that can be accessed
from anywhere, it is safer to validate input rather than assume any
caller will always respect the input conditions.
Lots of other places in the coresight drivers check that these
functions exist before calling them.

Regards

Mike

> Jie
>
> >> +       switch (mode) {
> >> +       case CS_MODE_SYSFS:
> >> +               trace_id = coresight_trace_id_get_cpu_id(cpu);
> >> +               break;
> >> +       case CS_MODE_PERF:
> >> +               if (WARN_ON(!sink))
> >> +                       return -EINVAL;
> >> +
> >> +               trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
> >> +               break;
> >> +       default:
> >> +               trace_id = -EINVAL;
> >> +               break;
> >> +       }
> >> +
> >> +       if (!IS_VALID_CS_TRACE_ID(trace_id))
> >> +               dev_err(&csdev->dev,
> >> +                       "Failed to allocate trace ID on CPU%d\n", cpu);
> >> +
> >> +       return trace_id;
> >> +}
> >> +EXPORT_SYMBOL_GPL(coresight_etm_get_trace_id);
> >> +
> >>   MODULE_LICENSE("GPL v2");
> >>   MODULE_AUTHOR("Pratik Patel <pratikp at codeaurora.org>");
> >>   MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier at linaro.org>");
> >> diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
> >> index 9be53be8964b..b5692ba358c1 100644
> >> --- a/drivers/hwtracing/coresight/coresight-dummy.c
> >> +++ b/drivers/hwtracing/coresight/coresight-dummy.c
> >> @@ -41,6 +41,16 @@ static void dummy_source_disable(struct coresight_device *csdev,
> >>          dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
> >>   }
> >>
> >> +static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> >> +                                __maybe_unused struct coresight_device *sink)
> >> +{
> >> +       struct dummy_drvdata *drvdata;
> >> +
> >> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> >> +
> >> +       return drvdata->traceid;
> >> +}
> >> +
> >>   static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
> >>                                  void *data)
> >>   {
> >> @@ -62,7 +72,8 @@ static const struct coresight_ops_source dummy_source_ops = {
> >>   };
> >>
> >>   static const struct coresight_ops dummy_source_cs_ops = {
> >> -       .source_ops = &dummy_source_ops,
> >> +       .trace_id       = dummy_source_trace_id,
> >> +       .source_ops     = &dummy_source_ops,
> >>   };
> >>
> >>   static const struct coresight_ops_sink dummy_sink_ops = {
> >> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> >> index c103f4c70f5d..c1dda4bc4a2f 100644
> >> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> >> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> >> @@ -704,6 +704,7 @@ static const struct coresight_ops_source etm_source_ops = {
> >>   };
> >>
> >>   static const struct coresight_ops etm_cs_ops = {
> >> +       .trace_id       = coresight_etm_get_trace_id,
> >>          .source_ops     = &etm_source_ops,
> >>   };
> >>
> >> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> >> index 2c1a60577728..cfd116b87460 100644
> >> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> >> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> >> @@ -1067,6 +1067,7 @@ static const struct coresight_ops_source etm4_source_ops = {
> >>   };
> >>
> >>   static const struct coresight_ops etm4_cs_ops = {
> >> +       .trace_id       = coresight_etm_get_trace_id,
> >>          .source_ops     = &etm4_source_ops,
> >>   };
> >>
> >> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> >> index b581a30a1cd9..aca25b5e3be2 100644
> >> --- a/drivers/hwtracing/coresight/coresight-stm.c
> >> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> >> @@ -281,12 +281,23 @@ static void stm_disable(struct coresight_device *csdev,
> >>          }
> >>   }
> >>
> >> +static int stm_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> >> +                       __maybe_unused struct coresight_device *sink)
> >> +{
> >> +       struct stm_drvdata *drvdata;
> >> +
> >> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> >> +
> >> +       return drvdata->traceid;
> >> +}
> >> +
> >>   static const struct coresight_ops_source stm_source_ops = {
> >>          .enable         = stm_enable,
> >>          .disable        = stm_disable,
> >>   };
> >>
> >>   static const struct coresight_ops stm_cs_ops = {
> >> +       .trace_id       = stm_trace_id,
> >>          .source_ops     = &stm_source_ops,
> >>   };
> >>
> >> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> >> index 573da8427428..94c2201fc8d3 100644
> >> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> >> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> >> @@ -241,12 +241,23 @@ static void tpda_disable(struct coresight_device *csdev,
> >>          dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
> >>   }
> >>
> >> +static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
> >> +                        __maybe_unused struct coresight_device *sink)
> >> +{
> >> +       struct tpda_drvdata *drvdata;
> >> +
> >> +       drvdata = dev_get_drvdata(csdev->dev.parent);
> >> +
> >> +       return drvdata->atid;
> >> +}
> >> +
> >>   static const struct coresight_ops_link tpda_link_ops = {
> >>          .enable         = tpda_enable,
> >>          .disable        = tpda_disable,
> >>   };
> >>
> >>   static const struct coresight_ops tpda_cs_ops = {
> >> +       .trace_id       = tpda_trace_id,
> >>          .link_ops       = &tpda_link_ops,
> >>   };
> >>
> >> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> >> index c7cd5886c908..ce9a5e71b261 100644
> >> --- a/include/linux/coresight.h
> >> +++ b/include/linux/coresight.h
> >> @@ -335,6 +335,7 @@ enum cs_mode {
> >>          CS_MODE_PERF,
> >>   };
> >>
> >> +#define coresight_ops(csdev)   csdev->ops
> >>   #define source_ops(csdev)      csdev->ops->source_ops
> >>   #define sink_ops(csdev)                csdev->ops->sink_ops
> >>   #define link_ops(csdev)                csdev->ops->link_ops
> >> @@ -421,6 +422,8 @@ struct coresight_ops_panic {
> >>   };
> >>
> >>   struct coresight_ops {
> >> +       int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
> >> +                       struct coresight_device *sink);
> >>          const struct coresight_ops_sink *sink_ops;
> >>          const struct coresight_ops_link *link_ops;
> >>          const struct coresight_ops_source *source_ops;
> >> @@ -709,4 +712,6 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
> >>
> >>   void coresight_remove_driver(struct amba_driver *amba_drv,
> >>                               struct platform_driver *pdev_drv);
> >> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
> >> +                              struct coresight_device *sink);
> >>   #endif         /* _LINUX_COREISGHT_H */
> >> --
> >> 2.34.1
> >>
> >
> >
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From rostedt at goodmis.org  Wed Mar  5 07:03:06 2025
From: rostedt at goodmis.org (Steven Rostedt)
Date: Wed, 5 Mar 2025 10:03:06 -0500
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
	<20250303132837.498938-2-dongml2@chinatelecom.cn>
	<20250303165454.GB11590@noisy.programming.kicks-ass.net>
	<CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
	<20250304053853.GA7099@noisy.programming.kicks-ass.net>
	<20250304061635.GA29480@noisy.programming.kicks-ass.net>
	<CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
	<20250304094220.GC11590@noisy.programming.kicks-ass.net>
	<6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
	<CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
Message-ID: <20250305100306.4685333a@gandalf.local.home>

On Wed, 5 Mar 2025 09:19:09 +0800
Menglong Dong <menglong8.dong at gmail.com> wrote:

> Ok, let me explain it from the beginning. (My English is not good,
> but I'll try to describe it as clear as possible :/)

I always appreciate those who struggle with English having these
conversations. Thank you for that, as I know I am horrible in speaking any
other language. (I can get by in German, but even Germans tell me to switch
back to English ;-)

> 
> Many BPF program types need to depend on the BPF trampoline,
> such as BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_EXT,
> BPF_PROG_TYPE_LSM, etc. BPF trampoline is a bridge between
> the kernel (or bpf) function and BPF program, and it acts just like the
> trampoline that ftrace uses.
> 
> Generally speaking, it is used to hook a function, just like what ftrace
> do:
> 
> foo:
>     endbr
>     nop5  -->  call trampoline_foo
>     xxxx
> 
> In short, the trampoline_foo can be this:
> 
> trampoline_foo:
>     prepare a array and store the args of foo to the array
>     call fentry_bpf1
>     call fentry_bpf2
>     ......
>     call foo+4 (origin call)

Note, I brought up this issue when I first heard about how BPF does this.
The calling of the original function from the trampoline. I said this will
cause issues, and is only good for a few functions. Once you start doing
this for 1000s of functions, it's going to be a nightmare.

Looks like you are now in the nightmare phase.

My argument was once you have this case, you need to switch over to the
kretprobe / function graph way of doing things, which is to have a shadow
stack and hijack the return address. Yes, that has slightly more overhead,
but it's better than having to add all theses hacks.

And function graph has been updated so that it can do this for other users.
fprobes uses it now, and bpf can too.

>     save the return value of foo
>     call fexit_bpf1 (this bpf can get the return value of foo)
>     call fexit_bpf2
>     .......
>     return to the caller of foo
> 
> We can see that the trampoline_foo can be only used for
> the function foo, as different kernel function can be attached
> different BPF programs, and have different argument count,
> etc. Therefore, we have to create 1000 BPF trampolines if
> we want to attach a BPF program to 1000 kernel functions.
> 
> The creation of the BPF trampoline is expensive. According to
> my testing, It will spend more than 1 second to create 100 bpf
> trampoline. What's more, it consumes more memory.
> 
> If we have the per-function metadata supporting, then we can
> create a global BPF trampoline, like this:
> 
> trampoline_global:
>     prepare a array and store the args of foo to the array
>     get the metadata by the ip
>     call metadata.fentry_bpf1
>     call metadata.fentry_bpf2
>     ....
>     call foo+4 (origin call)

So if this is a global trampoline, wouldn't this "call foo" need to be an
indirect call? It can't be a direct call, otherwise you need a separate
trampoline for that.

This means you need to mitigate for spectre here, and you just lost the
performance gain from not using function graph.


>     save the return value of foo
>     call metadata.fexit_bpf1 (this bpf can get the return value of foo)
>     call metadata.fexit_bpf2
>     .......
>     return to the caller of foo
> 
> (The metadata holds more information for the global trampoline than
> I described.)
> 
> Then, we don't need to create a trampoline for every kernel function
> anymore.
> 
> Another beneficiary can be ftrace. For now, all the kernel functions that
> are enabled by dynamic ftrace will be added to a filter hash if there are
> more than one callbacks. And hash lookup will happen when the traced
> functions are called, which has an impact on the performance, see
> __ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
> metadata supporting, we can store the information that if the callback is
> enabled on the kernel function to the metadata, which can make the performance
> much better.

Let me say now that ftrace will not use this. Looks like too much work for
little gain. The only time this impacts ftrace is when there's two
different callbacks tracing the same function, and it only impacts that
function. All other functions being traced still call the appropriate
trampoline for the callback.

-- Steve

> 
> The per-function metadata storage is a basic function, and I think there
> may be other functions that can use it for better performance in the feature
> too.
> 
> (Hope that I'm describing it clearly :/)



From james.clark at linaro.org  Wed Mar  5 07:07:19 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 05 Mar 2025 15:07:19 +0000
Subject: [PATCH v2] coresight: Add a KUnit test for
 coresight_find_default_sink()
Message-ID: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>

Add a test to confirm that default sink selection skips over an ETF
and returns an ETR even if it's further away.

This also makes it easier to add new unit tests in the future.

Signed-off-by: James Clark <james.clark at linaro.org>
---
Changes in v2:
- Let devm free everything rather than doing individual kfrees:
  "Like with managed drivers, KUnit-managed fake devices are
  automatically cleaned up when the test finishes, but can be manually
  cleaned up early with kunit_device_unregister()."
- Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
---
 drivers/hwtracing/coresight/Kconfig                |  9 +++
 drivers/hwtracing/coresight/Makefile               |  3 +-
 drivers/hwtracing/coresight/coresight-core.c       |  1 +
 .../hwtracing/coresight/coresight-kunit-tests.c    | 77 ++++++++++++++++++++++
 4 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index ecd7086a5b83..f064e3d172b3 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called coresight-dummy.
+
+config CORESIGHT_KUNIT_TESTS
+	  tristate "Enable Coresight unit tests"
+	  depends on KUNIT
+	  default KUNIT_ALL_TESTS
+	  help
+	    Enable Coresight unit tests. Only useful for development and not
+	    intended for production.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 8e62c3150aeb..96f0dfedb1bf 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
 		   coresight-cti-sysfs.o
 obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
-obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
-coresight-ctcu-y := coresight-ctcu-core.o
+obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..b101aa133ceb 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
 	}
 	return csdev->def_sink;
 }
+EXPORT_SYMBOL_GPL(coresight_find_default_sink);
 
 static int coresight_remove_sink_ref(struct device *dev, void *data)
 {
diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
new file mode 100644
index 000000000000..a136af05eaf4
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <kunit/test.h>
+#include <kunit/device.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+static struct coresight_device *coresight_test_device(struct device *dev)
+{
+	struct coresight_device *csdev = devm_kcalloc(dev, 1,
+						     sizeof(struct coresight_device),
+						     GFP_KERNEL);
+	csdev->pdata = devm_kcalloc(dev, 1,
+				   sizeof(struct coresight_platform_data),
+				   GFP_KERNEL);
+	return csdev;
+}
+
+static int coresight_test_cpuid(struct coresight_device *csdev)
+{
+	return 0;
+}
+
+static void test_default_sink(struct kunit *test)
+{
+	/*
+	 * ETM -> ETF -> ETR -> CATU
+	 *                ^
+	 *                | default
+	 */
+	struct device *dev = kunit_device_register(test, "coresight_kunit");
+	struct coresight_device *etm = coresight_test_device(dev),
+				*etf = coresight_test_device(dev),
+				*etr = coresight_test_device(dev),
+				*catu = coresight_test_device(dev);
+	struct coresight_connection conn = {};
+	struct coresight_ops_source src_ops = {.cpu_id = coresight_test_cpuid };
+	struct coresight_ops etm_cs_ops = { .source_ops	= &src_ops };
+
+	etm->type = CORESIGHT_DEV_TYPE_SOURCE;
+	etm->ops = &etm_cs_ops;
+	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
+	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	etr->type = CORESIGHT_DEV_TYPE_SINK;
+	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
+	catu->type = CORESIGHT_DEV_TYPE_HELPER;
+
+	conn.src_dev = etm;
+	conn.dest_dev = etf;
+	coresight_add_out_conn(dev, etm->pdata, &conn);
+
+	conn.src_dev = etf;
+	conn.dest_dev = etr;
+	coresight_add_out_conn(dev, etf->pdata, &conn);
+
+	conn.src_dev = etr;
+	conn.dest_dev = catu;
+	coresight_add_out_conn(dev, etr->pdata, &conn);
+
+	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
+}
+
+static struct kunit_case coresight_testcases[] = {
+	KUNIT_CASE(test_default_sink),
+	{}
+};
+
+static struct kunit_suite coresight_test_suite = {
+	.name = "coresight_test_suite",
+	.test_cases = coresight_testcases,
+};
+
+kunit_test_suites(&coresight_test_suite);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
+MODULE_DESCRIPTION("Arm CoreSight KUnit tests");

---
base-commit: eeafe6a8790ea125252ca2e23c1a2469eaff1d9a
change-id: 20250305-james-cs-kunit-test-3af1df2401e6

Best regards,
-- 
James Clark <james.clark at linaro.org>



From robh at kernel.org  Wed Mar  5 07:09:53 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 05 Mar 2025 09:09:53 -0600
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <20250305100134.1171124-1-manikandan.m@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
Message-ID: <174118733199.1974433.9410395684855092118.robh@kernel.org>


On Wed, 05 Mar 2025 15:31:33 +0530, Manikandan Muralidharan wrote:
> From: Varshini Rajendran <varshini.rajendran at microchip.com>
> 
> EUI identifier and the MAC Address of the Ethernet Interface is stored
> after the SFDP table of contents starting at address 0x260 in the
> QSPI memory.
> Register the entire SFDP region read by the spi-nor (nor->sfdp) into the
> NVMEM framework and read the MAC Address when requested using the nvmem
> properties in the DT by the net drivers.
> 
> In kernel the Ethernet MAC address relied on U-Boot env variables or
> generated a random address, which posed challenges for boards without
> on-board EEPROMs or with multiple Ethernet ports.
> This change ensures consistent and reliable MAC address retrieval from QSPI,
> benefiting boards like the sama5d29 curiosity and sam9x75 curiosity.
> 
> Signed-off-by: Varshini Rajendran <varshini.rajendran at microchip.com>
> [manikandan.m at microchip.com: Integrate the nvmem->read callback framework]
> Signed-off-by: Manikandan Muralidharan <manikandan.m at microchip.com>
> ---
>  drivers/mtd/spi-nor/sst.c | 62 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/microchip/' for 20250305100134.1171124-1-manikandan.m at microchip.com:

arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dtb: flash at 0: Unevaluated properties are not allowed ('nvmem-layout' was unexpected)
	from schema $id: http://devicetree.org/schemas/mtd/jedec,spi-nor.yaml#







From leo.yan at arm.com  Wed Mar  5 07:20:09 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 5 Mar 2025 15:20:09 +0000
Subject: [PATCH v2] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
References: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
Message-ID: <20250305152009.GH13418@e132581.arm.com>

On Wed, Mar 05, 2025 at 03:07:19PM +0000, James Clark wrote:
> Add a test to confirm that default sink selection skips over an ETF
> and returns an ETR even if it's further away.
> 
> This also makes it easier to add new unit tests in the future.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

LGTM:

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
> Changes in v2:
> - Let devm free everything rather than doing individual kfrees:
>   "Like with managed drivers, KUnit-managed fake devices are
>   automatically cleaned up when the test finishes, but can be manually
>   cleaned up early with kunit_device_unregister()."
> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
> ---
>  drivers/hwtracing/coresight/Kconfig                |  9 +++
>  drivers/hwtracing/coresight/Makefile               |  3 +-
>  drivers/hwtracing/coresight/coresight-core.c       |  1 +
>  .../hwtracing/coresight/coresight-kunit-tests.c    | 77 ++++++++++++++++++++++
>  4 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index ecd7086a5b83..f064e3d172b3 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>  
>  	  To compile this driver as a module, choose M here: the module will be
>  	  called coresight-dummy.
> +
> +config CORESIGHT_KUNIT_TESTS
> +	  tristate "Enable Coresight unit tests"
> +	  depends on KUNIT
> +	  default KUNIT_ALL_TESTS
> +	  help
> +	    Enable Coresight unit tests. Only useful for development and not
> +	    intended for production.
> +
>  endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 8e62c3150aeb..96f0dfedb1bf 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
>  		   coresight-cti-sysfs.o
>  obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>  obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
> -coresight-ctcu-y := coresight-ctcu-core.o
> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index bd0a7edd38c9..b101aa133ceb 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>  	}
>  	return csdev->def_sink;
>  }
> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>  
>  static int coresight_remove_sink_ref(struct device *dev, void *data)
>  {
> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> new file mode 100644
> index 000000000000..a136af05eaf4
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +#include <kunit/device.h>
> +#include <linux/coresight.h>
> +
> +#include "coresight-priv.h"
> +
> +static struct coresight_device *coresight_test_device(struct device *dev)
> +{
> +	struct coresight_device *csdev = devm_kcalloc(dev, 1,
> +						     sizeof(struct coresight_device),
> +						     GFP_KERNEL);
> +	csdev->pdata = devm_kcalloc(dev, 1,
> +				   sizeof(struct coresight_platform_data),
> +				   GFP_KERNEL);
> +	return csdev;
> +}
> +
> +static int coresight_test_cpuid(struct coresight_device *csdev)
> +{
> +	return 0;
> +}
> +
> +static void test_default_sink(struct kunit *test)
> +{
> +	/*
> +	 * ETM -> ETF -> ETR -> CATU
> +	 *                ^
> +	 *                | default
> +	 */
> +	struct device *dev = kunit_device_register(test, "coresight_kunit");
> +	struct coresight_device *etm = coresight_test_device(dev),
> +				*etf = coresight_test_device(dev),
> +				*etr = coresight_test_device(dev),
> +				*catu = coresight_test_device(dev);
> +	struct coresight_connection conn = {};
> +	struct coresight_ops_source src_ops = {.cpu_id = coresight_test_cpuid };
> +	struct coresight_ops etm_cs_ops = { .source_ops	= &src_ops };
> +
> +	etm->type = CORESIGHT_DEV_TYPE_SOURCE;
> +	etm->ops = &etm_cs_ops;
> +	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
> +	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
> +	etr->type = CORESIGHT_DEV_TYPE_SINK;
> +	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
> +	catu->type = CORESIGHT_DEV_TYPE_HELPER;
> +
> +	conn.src_dev = etm;
> +	conn.dest_dev = etf;
> +	coresight_add_out_conn(dev, etm->pdata, &conn);
> +
> +	conn.src_dev = etf;
> +	conn.dest_dev = etr;
> +	coresight_add_out_conn(dev, etf->pdata, &conn);
> +
> +	conn.src_dev = etr;
> +	conn.dest_dev = catu;
> +	coresight_add_out_conn(dev, etr->pdata, &conn);
> +
> +	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
> +}
> +
> +static struct kunit_case coresight_testcases[] = {
> +	KUNIT_CASE(test_default_sink),
> +	{}
> +};
> +
> +static struct kunit_suite coresight_test_suite = {
> +	.name = "coresight_test_suite",
> +	.test_cases = coresight_testcases,
> +};
> +
> +kunit_test_suites(&coresight_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
> +MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
> 
> ---
> base-commit: eeafe6a8790ea125252ca2e23c1a2469eaff1d9a
> change-id: 20250305-james-cs-kunit-test-3af1df2401e6
> 
> Best regards,
> -- 
> James Clark <james.clark at linaro.org>
> 


From oleg at redhat.com  Wed Mar  5 07:20:55 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Wed, 5 Mar 2025 16:20:55 +0100
Subject: [PATCH -next v1 0/3] kernel/events/uprobes:
 uprobe_write_opcode() rewrite
In-Reply-To: <20250304154846.1937958-1-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
Message-ID: <20250305152055.GB28112@redhat.com>

On 03/04, David Hildenbrand wrote:
>
> Currently, uprobe_write_opcode() implements COW-breaking manually, which is
> really far from ideal.

To say at least ;)

David, thanks for doing this. I'll try to read 3/3 tomorrow, but I don't
think I can really help. Let me repeat, this code was written many years
ago, I forgot everything, and today my understanding of mm/ is very poor.
But I'll try anyway.

> Are there any uprobe tests / benchmarks that are worth running?

All I know about uprobe tests is that bpf people run a lot of tests which
use uprobes.

Andrii, Jiri, what you advise?

Oleg.



From quic_jiegan at quicinc.com  Wed Mar  5 07:25:34 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 5 Mar 2025 23:25:34 +0800
Subject: [PATCH v15 02/10] Coresight: Add trace_id function to retrieving
 the trace ID
In-Reply-To: <CAJ9a7Vhx293H6r6HGwVOQ46PDu+sQ8LPONvAbwAtxGFt0ad+Ww@mail.gmail.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-3-quic_jiegan@quicinc.com>
 <CAJ9a7VgGp4YqzN-yx0x+NiZG8now6SCmnimaou2Z=exYcoiegw@mail.gmail.com>
 <7fe6c345-85cf-4114-b419-f50d1a6cbef1@quicinc.com>
 <CAJ9a7Vhx293H6r6HGwVOQ46PDu+sQ8LPONvAbwAtxGFt0ad+Ww@mail.gmail.com>
Message-ID: <d4ae3dc1-e722-43cd-8e3e-aa13b21de8ba@quicinc.com>



On 3/5/2025 10:58 PM, Mike Leach wrote:
> Hi Jie
> 
> On Wed, 5 Mar 2025 at 13:27, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>
>>
>>
>> On 3/5/2025 7:07 PM, Mike Leach wrote:
>>> Hi,
>>>
>>> On Mon, 3 Mar 2025 at 03:30, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>>>
>>>> Add 'trace_id' function pointer in coresight_ops. It's responsible for retrieving
>>>> the device's trace ID.
>>>>
>>>> Co-developed-by: James Clark <james.clark at linaro.org>
>>>> Signed-off-by: James Clark <james.clark at linaro.org>
>>>> Reviewed-by: James Clark <james.clark at linaro.org>
>>>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>>>> ---
>>>>    drivers/hwtracing/coresight/coresight-core.c  | 30 +++++++++++++++++++
>>>>    drivers/hwtracing/coresight/coresight-dummy.c | 13 +++++++-
>>>>    .../coresight/coresight-etm3x-core.c          |  1 +
>>>>    .../coresight/coresight-etm4x-core.c          |  1 +
>>>>    drivers/hwtracing/coresight/coresight-stm.c   | 11 +++++++
>>>>    drivers/hwtracing/coresight/coresight-tpda.c  | 11 +++++++
>>>>    include/linux/coresight.h                     |  5 ++++
>>>>    7 files changed, 71 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>>>> index ab55e10d4b79..32aa07f4f8c1 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-core.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>>>> @@ -24,6 +24,7 @@
>>>>    #include "coresight-etm-perf.h"
>>>>    #include "coresight-priv.h"
>>>>    #include "coresight-syscfg.h"
>>>> +#include "coresight-trace-id.h"
>>>>
>>>>    /*
>>>>     * Mutex used to lock all sysfs enable and disable actions and loading and
>>>> @@ -1557,6 +1558,35 @@ void coresight_remove_driver(struct amba_driver *amba_drv,
>>>>    }
>>>>    EXPORT_SYMBOL_GPL(coresight_remove_driver);
>>>>
>>>> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
>>>> +                              struct coresight_device *sink)
>>>> +{
>>>> +       int trace_id;
>>>> +       int cpu = source_ops(csdev)->cpu_id(csdev);
>>>> +
>>>
>>> This is a global funciton so need to check that this csdev is a
>>> source,. and does provide a cpu  function before calling it.
>>>
>>
>> Hi Mike,
>>
>> I put this function here because it's required by etm3x and etm4x. It's
>> intended to be called only by ETM devices, which are definitely source
>> devices and have a cpu function.
>>
> 
> I fully understand the intent, but for a function that can be accessed
> from anywhere, it is safer to validate input rather than assume any
> caller will always respect the input conditions.
> Lots of other places in the coresight drivers check that these
> functions exist before calling them.
> 

Hi Mike,

I agree with you. I will send another patch to fix it. Thanks for comment.

Jie

> Regards
> 
> Mike
> 
>> Jie
>>
>>>> +       switch (mode) {
>>>> +       case CS_MODE_SYSFS:
>>>> +               trace_id = coresight_trace_id_get_cpu_id(cpu);
>>>> +               break;
>>>> +       case CS_MODE_PERF:
>>>> +               if (WARN_ON(!sink))
>>>> +                       return -EINVAL;
>>>> +
>>>> +               trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
>>>> +               break;
>>>> +       default:
>>>> +               trace_id = -EINVAL;
>>>> +               break;
>>>> +       }
>>>> +
>>>> +       if (!IS_VALID_CS_TRACE_ID(trace_id))
>>>> +               dev_err(&csdev->dev,
>>>> +                       "Failed to allocate trace ID on CPU%d\n", cpu);
>>>> +
>>>> +       return trace_id;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(coresight_etm_get_trace_id);
>>>> +
>>>>    MODULE_LICENSE("GPL v2");
>>>>    MODULE_AUTHOR("Pratik Patel <pratikp at codeaurora.org>");
>>>>    MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier at linaro.org>");
>>>> diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
>>>> index 9be53be8964b..b5692ba358c1 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-dummy.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-dummy.c
>>>> @@ -41,6 +41,16 @@ static void dummy_source_disable(struct coresight_device *csdev,
>>>>           dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
>>>>    }
>>>>
>>>> +static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>>>> +                                __maybe_unused struct coresight_device *sink)
>>>> +{
>>>> +       struct dummy_drvdata *drvdata;
>>>> +
>>>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>>>> +
>>>> +       return drvdata->traceid;
>>>> +}
>>>> +
>>>>    static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
>>>>                                   void *data)
>>>>    {
>>>> @@ -62,7 +72,8 @@ static const struct coresight_ops_source dummy_source_ops = {
>>>>    };
>>>>
>>>>    static const struct coresight_ops dummy_source_cs_ops = {
>>>> -       .source_ops = &dummy_source_ops,
>>>> +       .trace_id       = dummy_source_trace_id,
>>>> +       .source_ops     = &dummy_source_ops,
>>>>    };
>>>>
>>>>    static const struct coresight_ops_sink dummy_sink_ops = {
>>>> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
>>>> index c103f4c70f5d..c1dda4bc4a2f 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
>>>> @@ -704,6 +704,7 @@ static const struct coresight_ops_source etm_source_ops = {
>>>>    };
>>>>
>>>>    static const struct coresight_ops etm_cs_ops = {
>>>> +       .trace_id       = coresight_etm_get_trace_id,
>>>>           .source_ops     = &etm_source_ops,
>>>>    };
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>>> index 2c1a60577728..cfd116b87460 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>>> @@ -1067,6 +1067,7 @@ static const struct coresight_ops_source etm4_source_ops = {
>>>>    };
>>>>
>>>>    static const struct coresight_ops etm4_cs_ops = {
>>>> +       .trace_id       = coresight_etm_get_trace_id,
>>>>           .source_ops     = &etm4_source_ops,
>>>>    };
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
>>>> index b581a30a1cd9..aca25b5e3be2 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>>>> @@ -281,12 +281,23 @@ static void stm_disable(struct coresight_device *csdev,
>>>>           }
>>>>    }
>>>>
>>>> +static int stm_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>>>> +                       __maybe_unused struct coresight_device *sink)
>>>> +{
>>>> +       struct stm_drvdata *drvdata;
>>>> +
>>>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>>>> +
>>>> +       return drvdata->traceid;
>>>> +}
>>>> +
>>>>    static const struct coresight_ops_source stm_source_ops = {
>>>>           .enable         = stm_enable,
>>>>           .disable        = stm_disable,
>>>>    };
>>>>
>>>>    static const struct coresight_ops stm_cs_ops = {
>>>> +       .trace_id       = stm_trace_id,
>>>>           .source_ops     = &stm_source_ops,
>>>>    };
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
>>>> index 573da8427428..94c2201fc8d3 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>>>> @@ -241,12 +241,23 @@ static void tpda_disable(struct coresight_device *csdev,
>>>>           dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
>>>>    }
>>>>
>>>> +static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode,
>>>> +                        __maybe_unused struct coresight_device *sink)
>>>> +{
>>>> +       struct tpda_drvdata *drvdata;
>>>> +
>>>> +       drvdata = dev_get_drvdata(csdev->dev.parent);
>>>> +
>>>> +       return drvdata->atid;
>>>> +}
>>>> +
>>>>    static const struct coresight_ops_link tpda_link_ops = {
>>>>           .enable         = tpda_enable,
>>>>           .disable        = tpda_disable,
>>>>    };
>>>>
>>>>    static const struct coresight_ops tpda_cs_ops = {
>>>> +       .trace_id       = tpda_trace_id,
>>>>           .link_ops       = &tpda_link_ops,
>>>>    };
>>>>
>>>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>>>> index c7cd5886c908..ce9a5e71b261 100644
>>>> --- a/include/linux/coresight.h
>>>> +++ b/include/linux/coresight.h
>>>> @@ -335,6 +335,7 @@ enum cs_mode {
>>>>           CS_MODE_PERF,
>>>>    };
>>>>
>>>> +#define coresight_ops(csdev)   csdev->ops
>>>>    #define source_ops(csdev)      csdev->ops->source_ops
>>>>    #define sink_ops(csdev)                csdev->ops->sink_ops
>>>>    #define link_ops(csdev)                csdev->ops->link_ops
>>>> @@ -421,6 +422,8 @@ struct coresight_ops_panic {
>>>>    };
>>>>
>>>>    struct coresight_ops {
>>>> +       int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
>>>> +                       struct coresight_device *sink);
>>>>           const struct coresight_ops_sink *sink_ops;
>>>>           const struct coresight_ops_link *link_ops;
>>>>           const struct coresight_ops_source *source_ops;
>>>> @@ -709,4 +712,6 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
>>>>
>>>>    void coresight_remove_driver(struct amba_driver *amba_drv,
>>>>                                struct platform_driver *pdev_drv);
>>>> +int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
>>>> +                              struct coresight_device *sink);
>>>>    #endif         /* _LINUX_COREISGHT_H */
>>>> --
>>>> 2.34.1
>>>>
>>>
>>>
>>
> 
> 



From Frank.li at nxp.com  Wed Mar  5 07:42:13 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 5 Mar 2025 10:42:13 -0500
Subject: [PATCH v2 2/2] phy: freescale: imx8m-pcie: assert phy reset and
 perst in power off
In-Reply-To: <20250305144355.20364-3-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
 <20250305144355.20364-3-eichest@gmail.com>
Message-ID: <Z8hw1W0PBsmanylZ@lizhi-Precision-Tower-5810>

On Wed, Mar 05, 2025 at 03:43:16PM +0100, Stefan Eichenberger wrote:
> From: Stefan Eichenberger <stefan.eichenberger at toradex.com>
>
> Ensure the PHY reset and perst is asserted during power-off to
> guarantee it is in a reset state upon repeated power-on calls. This
> resolves an issue where the PHY may not properly initialize during
> subsequent power-on cycles. Power-on will deassert the reset at the
> appropriate time after tuning the PHY parameters.
>
> During suspend/resume cycles, we observed that the PHY PLL failed to
> lock during resume when the CPU temperature increased from 65C to 75C.
> The observed errors were:
>   phy phy-32f00000.pcie-phy.3: phy poweron failed --> -110
>   imx6q-pcie 33800000.pcie: waiting for PHY ready timeout!
>   imx6q-pcie 33800000.pcie: PM: dpm_run_callback(): genpd_resume_noirq+0x0/0x80 returns -110
>   imx6q-pcie 33800000.pcie: PM: failed to resume noirq: error -110
>
> This resulted in a complete CPU freeze, which is resolved by ensuring
> the PHY is in reset during power-on, thus preventing PHY PLL failures.
>
> Cc: stable at vger.kernel.org
> Fixes: 1aa97b002258 ("phy: freescale: pcie: Initialize the imx8 pcie standalone phy driver")
> Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> index 5b505e34ca364..7355d9921b646 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> @@ -156,6 +156,16 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
>  	return ret;
>  }
>
> +static int imx8_pcie_phy_power_off(struct phy *phy)
> +{
> +	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> +
> +	reset_control_assert(imx8_phy->reset);
> +	reset_control_assert(imx8_phy->perst);
> +
> +	return 0;
> +}
> +
>  static int imx8_pcie_phy_init(struct phy *phy)
>  {
>  	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
> @@ -176,6 +186,7 @@ static const struct phy_ops imx8_pcie_phy_ops = {
>  	.init		= imx8_pcie_phy_init,
>  	.exit		= imx8_pcie_phy_exit,
>  	.power_on	= imx8_pcie_phy_power_on,
> +	.power_off	= imx8_pcie_phy_power_off,
>  	.owner		= THIS_MODULE,
>  };
>
> --
> 2.45.2
>


From Frank.li at nxp.com  Wed Mar  5 07:40:40 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 5 Mar 2025 10:40:40 -0500
Subject: [PATCH v2 1/2] phy: freescale: imx8m-pcie: cleanup reset logic
In-Reply-To: <20250305144355.20364-2-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
 <20250305144355.20364-2-eichest@gmail.com>
Message-ID: <Z8hweDIy0AuxzBRR@lizhi-Precision-Tower-5810>

On Wed, Mar 05, 2025 at 03:43:15PM +0100, Stefan Eichenberger wrote:
> From: Stefan Eichenberger <stefan.eichenberger at toradex.com>
>
> Remove the switch statement and base perst release on whether it is
> found in the device tree. The probe function fails without the reset
> property, making it mandatory. Therefore, always release reset
> independent of the variant.

Thanks for clean up this.

"Remove the switch statement for releasing 'perst' and 'reset' since they
are already correctly set at probe and are no-ops for
reset_control_deassert(NULL). Call these unconditionally."

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>
> This does not change the behavior of the driver but reduces driver
> complexity and allows for easier future modifications.
>
> Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
> ---
>  drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 12 +++---------
>  1 file changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> index e98361dcdeadf..5b505e34ca364 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
> @@ -141,15 +141,9 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
>  			   IMX8MM_GPR_PCIE_REF_CLK_PLL);
>  	usleep_range(100, 200);
>
> -	switch (imx8_phy->drvdata->variant) {
> -	case IMX8MP:
> -		reset_control_deassert(imx8_phy->perst);
> -		fallthrough;
> -	case IMX8MM:
> -		reset_control_deassert(imx8_phy->reset);
> -		usleep_range(200, 500);
> -		break;
> -	}
> +	reset_control_deassert(imx8_phy->perst);
> +	reset_control_deassert(imx8_phy->reset);
> +	usleep_range(200, 500);
>
>  	/* Do the PHY common block reset */
>  	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
> --
> 2.45.2
>


From krzk at kernel.org  Wed Mar  5 07:41:23 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 16:41:23 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250305140009.2485859-2-amadeus@jmu.edu.cn>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
 <20250305140009.2485859-2-amadeus@jmu.edu.cn>
Message-ID: <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>

On 05/03/2025 15:00, Chukun Pan wrote:
> Copy QoS nodes and add rk3528 compatible from bsp kernel,

No, don't copy stuff from BSP kernel. It results in terrible DTS.

> these can be used for power-domain.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
>  1 file changed, 160 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 5b334690356a..794f35654975 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -122,6 +122,166 @@ gic: interrupt-controller at fed01000 {
>  			#interrupt-cells = <3>;
>  		};
>  
> +		qos_crypto_a: qos at ff200000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200000 0x0 0x20>;
> +		};
> +
> +		qos_crypto_p: qos at ff200080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200080 0x0 0x20>;
> +		};


Did you just define syscon per few registers? Third case last weeks...
so no, define what is your device here. 8 registers is not a device usually.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar  5 07:42:19 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 16:42:19 +0100
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <20250305091246.106626-2-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
 <20250305091246.106626-2-swathi.ks@samsung.com>
Message-ID: <89dcfb2a-d093-48f9-b6d7-af99b383a1bc@kernel.org>

On 05/03/2025 10:12, Swathi K S wrote:
> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
> Ethernet YAML schema to enable the DT validation.
> 
> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> Signed-off-by: Swathi K S <swathi.ks at samsung.com>

<form letter>
This is a friendly reminder during the review process.

It looks like you received a tag and forgot to add it.

If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Please read:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577

If a tag was not added on purpose, please state why and what changed.
</form letter>

Best regards,
Krzysztof


From james.clark at linaro.org  Wed Mar  5 07:51:46 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 5 Mar 2025 15:51:46 +0000
Subject: [PATCH] coresight: docs: Remove target sink from examples
In-Reply-To: <20241210144933.295798-1-james.clark@linaro.org>
References: <20241210144933.295798-1-james.clark@linaro.org>
Message-ID: <7ac4947b-76b1-4748-8ea0-a949613a3cfc@linaro.org>



On 10/12/2024 2:49 pm, James Clark wrote:
> Previously the sink had to be specified, but now it auto selects one by
> default. Including a sink in the examples causes issues when copy
> pasting the command because it might not work if that sink isn't
> present. Remove the sink from all the basic examples and create a new
> section specifically about overriding the default one.
> 
> Make the text a but more concise now that it's in the advanced section,
> and similarly for removing the old kernel advice.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---

Ping, thanks.

I think Steve's comments are somewhat related, but shouldn't block this 
change going in.



From Jason-JH.Lin at mediatek.com  Wed Mar  5 07:58:46 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Wed, 5 Mar 2025 15:58:46 +0000
Subject: [PATCH v4 4/8] soc: mediatek: mtk-cmdq: Add pa_base parsing for
 unsupported subsys ID hardware
In-Reply-To: <8203317e-7f99-4ea5-bda0-fcd791602a9f@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
	 <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>
	 <03c523e66fd56442f49c38456476cf18be59e8fb.camel@mediatek.com>
	 <8203317e-7f99-4ea5-bda0-fcd791602a9f@collabora.com>
Message-ID: <c27653233ed2ee2ee6eb0d40ad2167721a2b1476.camel@mediatek.com>

On Wed, 2025-03-05 at 12:03 +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 05/03/25 10:46, Jason-JH Lin (???) ha scritto:
> > On Tue, 2025-03-04 at 10:35 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > > > When GCE executes instructions, the corresponding hardware
> > > > register
> > > > can be found through the subsys ID. For hardware that does not
> > > > support
> > > > subsys ID, its subsys ID will be set to invalid value and its
> > > > physical
> > > > address needs to be used to generate GCE instructions.
> > > > 
> > > > This commit adds a pa_base parsing flow to the cmdq_client_reg
> > > > structure
> > > > for these unsupported subsys ID hardware.
> > > > 
> > > 
> > > Does this work only for the MMINFRA located GCEs, or does this
> > > work
> > > also for
> > > the legacy ones in MT8173/83/88/92/95 // MT6795/6893/etc?
> > > 
> > > In order to actually review and decide, I do need to know :-)
> > > 
> > 
> > Yes, it's for the SoCs without subsys ID, it's not related to the
> > MMINFRA.
> > 
> > This can also work on MT8173/83/92/95 // MT6795/6893/etc.
> > You can remove the `mediatek,gce-client-reg` properties in their
> > dtsi
> > and cherry-pick this series to verify it. :-)
> > 
> 
> This is curious - and that brings more questions to the table (for
> curiosity
> more than anything else at this point).
> 
> Since this is a way to make use of the CMDQ for address ranges that
> are not tied
> to any subsys id (hence no gce-client-reg and just physical address
> parsing for
> generating instructions), do you know what are the performance
> implications of
> using this, instead of subsys IDs on SoCs that do support them?
> 

The main advantage of using subsys ID is to reduce the number of
instruction.
Without subsy ID, you will need one more `ASSIGN` instruction to assign
the high bytes of the physical address.

E,g. In mt8195-gce.h: #define SUBSYS_1c00XXXX 3

If you want GCE to write the value 0x0000000f to 0x1c00_002c.

With subsys ID, you can use only one instruction to achieve it:
1. WRITE value: 0x000000f to subsys: 0x3 + offset: 0x0002c
- OP code: WRTIE = 0x90
- subsys ID: 0x1c00XXXX = 0x03
- offset: 0x002c
- value: 0x0000000f

Without subsys ID, you will need 2 instructions to achieve it:
1. ASSIGN address high bytes: 0x1c00 to GCE temp register: SPR0
- OP code: LOGIC = 0xa0
- arg_type: register, value, value = (0x8)
- sub OP: ASSIGN = 0x0
- register index to store the assign value: SPR0 = 0x0
- value to assign: 0x1c00
2. WRITE value: 0x0000000f to temp register: SPR0 + offset:0x002c
- OP code: WRITE = 0x90
- sub OP(temp register index): SPR0 = 0x0
- offset for temp register: 0x002c
- value: 0x0000000f

> Being clear: if we were to migrate a SoC like MT8195 to using this
> globally
> instead of using subsys ids, would the performance be degraded?
> And if yes, do you know by how much?
> 

E,g. If the inst number with subsys ID is N.
1. If CMDQ is implement like this, then inst number will be (N * 2):
assign SPR0 = 0x1c00
write A to SPR0 + offset: 0x2c 
assign SPR0 = 0x1c00
write B to SPR0 + offset: 0x3c 
assign SPR0 = 0x1c00
write C to SPR0 + offset: 0x4c 
...

2. If CMDQ is implement like this, the inst number will be (N + 1 * n):
assign SPR0 = 0x1c00
write A to SPR0 + offset: 0x2c 
write B to SPR0 + offset: 0x3c
write C to SPR0 + offset: 0x4c
...

When the same cmd buffer changes the base address for n times:
assign SPR0 = 0x1c00
write A to SPR0 + offset: 0x2c
assign SPR0 = 0x1c01
write B to SPR0 + offset: 0x2c
assign SPR0 = 0x1c02
write C to SPR0 + offset: 0x2c
assign SPR0 = 0x1c00
write D to SPR0 + offset: 0x3c
...

So you can imagine the performance will increase, but maybe not too
much if we use it in the right way...
Except the old SoC that didn't support SPR and CPR. The reason will be
addressed in the next paragraph.

> What you're proposing almost looks like being too good to be true -
> and makes
> me wonder, at this point, why the subsys id was used in the first
> place :-)
> 

That's because of the old GCE version in the old SoC only support GPR,
it didn't support SPR and CPR.

GPR:
All 32 GCE threads share the same GPR0~GPR15, GPR will be affected by
other GCE threads if they use it at the same time.

SPR:
Each GCE thread has 4 SPR, SPR won't be affected by another GCE thread.

CPR:
All 32 GCE threads share the same CPR, there are over 1000 CPR can be
used. It need to be managed properly to avoid the resource conflicting.

Due to the GPR resource restriction in the old GCE version, the usage
of subsys ID can avoid GPR conflicting issues when multiple GCE threads
are using GPR to physical assign high bytes all the time.


I have simplified some complicate instruction rules, so the description
above may not be 100% matched to the CMDQ helper driver code.
But I think the main concept is correct.
Hope these explanation can help well :-)

Regards,
Jason-JH Lin

> Cheers!
> Angelo
> 
> > Regards,
> > Jason-JH Lin
> > 
> > > Thanks,
> > > Angelo
> > > 
> > > 
> > 
> 
> 
> 


From linux.amoon at gmail.com  Wed Mar  5 07:59:27 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Wed, 5 Mar 2025 21:29:27 +0530
Subject: [PATCH v3 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <7a1cac10-b065-4b4c-b048-10d6b4132f3d@arm.com>
References: <20250216195850.5352-1-linux.amoon@gmail.com> <20250216195850.5352-5-linux.amoon@gmail.com>
 <f44efd1a-1f6e-456d-9395-de2a55ef2279@arm.com> <CANAwSgTpV_kGFEU-ND0N+OEtT6+j4ceq37xAoLyC7iHPWAuLjg@mail.gmail.com>
 <CANAwSgSWf_YxSi-pzWPaRoiJx7RLrWUz+HTWx5hf+E2x1ZGmoQ@mail.gmail.com> <7a1cac10-b065-4b4c-b048-10d6b4132f3d@arm.com>
Message-ID: <CANAwSgQErDnKfaBOkpEwpJsoyUMhNTC2TJNW-eQYHgHu46poCA@mail.gmail.com>

Hi Lukasz,

On Wed, 5 Mar 2025 at 14:12, Lukasz Luba <lukasz.luba at arm.com> wrote:
>
>
>
> On 3/4/25 12:20, Anand Moon wrote:
> > Hi Lukasz,
> >
> > On Sat, 1 Mar 2025 at 00:06, Anand Moon <linux.amoon at gmail.com> wrote:
> >>
> >> Hi Lukasz,
> >>
> >> On Fri, 28 Feb 2025 at 22:58, Lukasz Luba <lukasz.luba at arm.com> wrote:
> >>>
> >>>
> >>>
> >>> On 2/16/25 19:58, Anand Moon wrote:
> >>>> Using guard notation makes the code more compact and error handling
> >>>> more robust by ensuring that mutexes are released in all code paths
> >>>> when control leaves critical section.
> >>>>
> >>>> Signed-off-by: Anand Moon <linux.amoon at gmail.com>
> >>>> ---
> >>>> v3: new patch
> >>>> ---
> >>>>    drivers/thermal/samsung/exynos_tmu.c | 21 +++++++--------------
> >>>>    1 file changed, 7 insertions(+), 14 deletions(-)
> >>>>
> >>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> >>>> index fe090c1a93ab..a34ba3858d64 100644
> >>>> --- a/drivers/thermal/samsung/exynos_tmu.c
> >>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
> >>>> @@ -256,7 +256,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> >>>>        unsigned int status;
> >>>>        int ret = 0;
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>        clk_enable(data->clk_sec);
> >>>>
> >>>> @@ -270,7 +270,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> >>>>
> >>>>        clk_disable(data->clk_sec);
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>
> >>>>        return ret;
> >>>>    }
> >>>> @@ -292,13 +291,12 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
> >>>>                return ret;
> >>>>        }
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>
> >>>>        data->tmu_set_crit_temp(data, temp / MCELSIUS);
> >>>>
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>
> >>>>        return 0;
> >>>>    }
> >>>> @@ -325,12 +323,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
> >>>>    {
> >>>>        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>        data->tmu_control(pdev, on);
> >>>>        data->enabled = on;
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>    }
> >>>>
> >>>>    static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
> >>>> @@ -645,7 +642,7 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
> >>>>                 */
> >>>>                return -EAGAIN;
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>
> >>>>        value = data->tmu_read(data);
> >>>> @@ -655,7 +652,6 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
> >>>>                *temp = code_to_temp(data, value) * MCELSIUS;
> >>>>
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>
> >>>>        return ret;
> >>>>    }
> >>>> @@ -720,11 +716,10 @@ static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
> >>>>        if (temp && temp < MCELSIUS)
> >>>>                goto out;
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>        data->tmu_set_emulation(data, temp);
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>        return 0;
> >>>>    out:
> >>>>        return ret;
> >>>> @@ -760,14 +755,13 @@ static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id)
> >>>>
> >>>>        thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>
> >>>>        /* TODO: take action based on particular interrupt */
> >>>>        data->tmu_clear_irqs(data);
> >>>>
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>
> >>>>        return IRQ_HANDLED;
> >>>>    }
> >>>> @@ -987,7 +981,7 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
> >>>>    {
> >>>>        struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
> >>>>
> >>>> -     mutex_lock(&data->lock);
> >>>> +     guard(mutex)(&data->lock);
> >>>>        clk_enable(data->clk);
> >>>>
> >>>>        if (low > INT_MIN)
> >>>> @@ -1000,7 +994,6 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
> >>>>                data->tmu_disable_high(data);
> >>>>
> >>>>        clk_disable(data->clk);
> >>>> -     mutex_unlock(&data->lock);
> >>>>
> >>>>        return 0;
> >>>>    }
> >>
> >> Thanks for your review comments.
> >>>
> >>> IMO you should be able to even use something like we have
> >>> core framework:
> >>>
> >>> guard(thermal_zone)(tz);
> >>>
> >>> Your mutex name is simply 'lock' in the struct exynos_tmu_data
> >>> so you should be able to leverage this by:
> >>>
> >>> guard(exynos_tmu_data)(data);
> >>>
> >
> > If I introduce the guard it creates a compilation error
> >
> > amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ vi
> > drivers/thermal/samsung/exynos_tmu.c +306
> > amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ make -j$(nproc)
> > ARCH=arm CROSS_COMPILE=arm-none-eabi- LOCALVERSION=-u3ml dtbs zImage
> > modules
> >    CALL    scripts/checksyscalls.sh
> >    CHK     kernel/kheaders_data.tar.xz
> >    CC      drivers/thermal/samsung/exynos_tmu.o
> >    CC [M]  drivers/md/raid10.o
> > In file included from ./include/linux/irqflags.h:17,
> >                   from ./arch/arm/include/asm/bitops.h:28,
> >                   from ./include/linux/bitops.h:68,
> >                   from ./include/linux/kernel.h:23,
> >                   from ./include/linux/clk.h:13,
> >                   from drivers/thermal/samsung/exynos_tmu.c:14:
> > drivers/thermal/samsung/exynos_tmu.c: In function 'exynos_tmu_update_bit':
> > ./include/linux/cleanup.h:258:9: error: unknown type name
> > 'class_exynos_tmu_data_t'
> >    258 |         class_##_name##_t var
> > __cleanup(class_##_name##_destructor) =   \
> >        |         ^~~~~~
> > ./include/linux/cleanup.h:309:9: note: in expansion of macro 'CLASS'
> >    309 |         CLASS(_name, __UNIQUE_ID(guard))
> >        |         ^~~~~
> > drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
> >    338 |         guard(exynos_tmu_data)(data);
> >        |         ^~~~~
> > drivers/thermal/samsung/exynos_tmu.c:338:9: error: cleanup argument
> > not a function
>
> [snip]
>
> Right, you're missing the definition at the begging, like:
>
> DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *,
> mutex_lock(&_T->lock),
>               mutex_unlock(&_T->lock))
>
> below the struct exynos_tmu_data definition.
>
> Also, make sure you include the cleanup.h (it might not complain,
> but it would be explicit and more clear)

Thanks for this tip.
However, incorporating guard(exynos_tmu_data)(data); results
in a recursive deadlock with the mutex during initialization, as this
data structure is common to all the code configurations of Exynos TMU

Thanks
-Anand


From lkp at intel.com  Wed Mar  5 08:00:01 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 00:00:01 +0800
Subject: [PATCH v3 05/11] arm64: hugetlb: Use set_ptes_anysz() and
 ptep_get_and_clear_anysz()
In-Reply-To: <20250304150444.3788920-6-ryan.roberts@arm.com>
References: <20250304150444.3788920-6-ryan.roberts@arm.com>
Message-ID: <202503052315.vk7m958M-lkp@intel.com>

Hi Ryan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.14-rc5 next-20250305]
[cannot apply to arm64/for-next/core akpm-mm/mm-everything arm-perf/for-next/perf]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Roberts/arm64-hugetlb-Cleanup-huge_pte-size-discovery-mechanisms/20250304-230647
base:   linus/master
patch link:    https://lore.kernel.org/r/20250304150444.3788920-6-ryan.roberts%40arm.com
patch subject: [PATCH v3 05/11] arm64: hugetlb: Use set_ptes_anysz() and ptep_get_and_clear_anysz()
config: arm64-randconfig-003-20250305 (https://download.01.org/0day-ci/archive/20250305/202503052315.vk7m958M-lkp at intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503052315.vk7m958M-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503052315.vk7m958M-lkp at intel.com/

All warnings (new ones prefixed by >>):

   In file included from arch/arm64/mm/hugetlbpage.c:12:
   In file included from include/linux/mm.h:2224:
   include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     504 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     505 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     511 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     512 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
>> arch/arm64/mm/hugetlbpage.c:154:23: warning: parameter 'addr' set but not used [-Wunused-but-set-parameter]
     154 |                              unsigned long addr,
         |                                            ^
   3 warnings generated.


vim +/addr +154 arch/arm64/mm/hugetlbpage.c

bc5dfb4fd7bd471 Baolin Wang       2022-05-16  144  
d8bdcff2876424d Steve Capper      2017-08-22  145  /*
d8bdcff2876424d Steve Capper      2017-08-22  146   * Changing some bits of contiguous entries requires us to follow a
d8bdcff2876424d Steve Capper      2017-08-22  147   * Break-Before-Make approach, breaking the whole contiguous set
d8bdcff2876424d Steve Capper      2017-08-22  148   * before we can change any entries. See ARM DDI 0487A.k_iss10775,
d8bdcff2876424d Steve Capper      2017-08-22  149   * "Misprogramming of the Contiguous bit", page D4-1762.
d8bdcff2876424d Steve Capper      2017-08-22  150   *
d8bdcff2876424d Steve Capper      2017-08-22  151   * This helper performs the break step.
d8bdcff2876424d Steve Capper      2017-08-22  152   */
fb396bb459c1fa3 Anshuman Khandual 2022-05-10  153  static pte_t get_clear_contig(struct mm_struct *mm,
d8bdcff2876424d Steve Capper      2017-08-22 @154  			     unsigned long addr,
d8bdcff2876424d Steve Capper      2017-08-22  155  			     pte_t *ptep,
d8bdcff2876424d Steve Capper      2017-08-22  156  			     unsigned long pgsize,
d8bdcff2876424d Steve Capper      2017-08-22  157  			     unsigned long ncontig)
d8bdcff2876424d Steve Capper      2017-08-22  158  {
49c87f7677746f3 Ryan Roberts      2025-02-26  159  	pte_t pte, tmp_pte;
49c87f7677746f3 Ryan Roberts      2025-02-26  160  	bool present;
49c87f7677746f3 Ryan Roberts      2025-02-26  161  
66251d3eadf78e2 Ryan Roberts      2025-03-04  162  	pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
49c87f7677746f3 Ryan Roberts      2025-02-26  163  	present = pte_present(pte);
49c87f7677746f3 Ryan Roberts      2025-02-26  164  	while (--ncontig) {
49c87f7677746f3 Ryan Roberts      2025-02-26  165  		ptep++;
49c87f7677746f3 Ryan Roberts      2025-02-26  166  		addr += pgsize;
66251d3eadf78e2 Ryan Roberts      2025-03-04  167  		tmp_pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
49c87f7677746f3 Ryan Roberts      2025-02-26  168  		if (present) {
49c87f7677746f3 Ryan Roberts      2025-02-26  169  			if (pte_dirty(tmp_pte))
49c87f7677746f3 Ryan Roberts      2025-02-26  170  				pte = pte_mkdirty(pte);
49c87f7677746f3 Ryan Roberts      2025-02-26  171  			if (pte_young(tmp_pte))
49c87f7677746f3 Ryan Roberts      2025-02-26  172  				pte = pte_mkyoung(pte);
d8bdcff2876424d Steve Capper      2017-08-22  173  		}
49c87f7677746f3 Ryan Roberts      2025-02-26  174  	}
49c87f7677746f3 Ryan Roberts      2025-02-26  175  	return pte;
d8bdcff2876424d Steve Capper      2017-08-22  176  }
d8bdcff2876424d Steve Capper      2017-08-22  177  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From robin.murphy at arm.com  Wed Mar  5 08:10:05 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed,  5 Mar 2025 16:10:05 +0000
Subject: [PATCH 0/3] perf/arm_cspmu: Add PMEVFILT2R support
Message-ID: <cover.1741190362.git.robin.murphy@arm.com>

Hi all,

This is part of something I'm working towards, but I figure it stands
up on its own enough to be worth getting out early. Compile-tested
only, but it's straightforward enough that I'm confident.

Cheers,
Robin.


Robin Murphy (3):
  perf/arm_cspmu: Move register definitons to header
  perf/arm_cspmu: Generalise event filtering
  perf/arm_cspmu: Add PMEVFILT2R support

 drivers/perf/arm_cspmu/ampere_cspmu.c | 32 ++++-------
 drivers/perf/arm_cspmu/arm_cspmu.c    | 81 ++++++---------------------
 drivers/perf/arm_cspmu/arm_cspmu.h    | 57 +++++++++++++++++--
 drivers/perf/arm_cspmu/nvidia_cspmu.c | 21 ++++++-
 4 files changed, 100 insertions(+), 91 deletions(-)

-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Wed Mar  5 08:10:06 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed,  5 Mar 2025 16:10:06 +0000
Subject: [PATCH 1/3] perf/arm_cspmu: Move register definitons to header
In-Reply-To: <cover.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
Message-ID: <5a3c796560665b51cb63fec0d473afd8f8d0a836.1741190362.git.robin.murphy@arm.com>

Implementations may occasionally want to refer to register offsets, so
for the sake of consistency move all of the register definitions to join
the PMIIDR fields in the private header where they can be shared. As an
example nicety, we can then define Ampere's imp-def filters in terms of
the architectural PMIMPDEF range rather than open-coded offsets.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/perf/arm_cspmu/ampere_cspmu.c |  8 ++---
 drivers/perf/arm_cspmu/arm_cspmu.c    | 45 --------------------------
 drivers/perf/arm_cspmu/arm_cspmu.h    | 46 +++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 49 deletions(-)

diff --git a/drivers/perf/arm_cspmu/ampere_cspmu.c b/drivers/perf/arm_cspmu/ampere_cspmu.c
index f72f5689923c..31cc1a4ac9df 100644
--- a/drivers/perf/arm_cspmu/ampere_cspmu.c
+++ b/drivers/perf/arm_cspmu/ampere_cspmu.c
@@ -10,10 +10,10 @@
 
 #include "arm_cspmu.h"
 
-#define PMAUXR0		0xD80
-#define PMAUXR1		0xD84
-#define PMAUXR2		0xD88
-#define PMAUXR3		0xD8C
+#define PMAUXR0		PMIMPDEF
+#define PMAUXR1		(PMIMPDEF + 0x4)
+#define PMAUXR2		(PMIMPDEF + 0x8)
+#define PMAUXR3		(PMIMPDEF + 0xC)
 
 #define to_ampere_cspmu_ctx(cspmu)	((struct ampere_cspmu_ctx *)(cspmu->impl.ctx))
 
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 81e8b97e9353..769466d55bea 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -40,51 +40,6 @@
 	ARM_CSPMU_EXT_ATTR(_name, arm_cspmu_cpumask_show,	\
 				(unsigned long)_config)
 
-/*
- * CoreSight PMU Arch register offsets.
- */
-#define PMEVCNTR_LO					0x0
-#define PMEVCNTR_HI					0x4
-#define PMEVTYPER					0x400
-#define PMCCFILTR					0x47C
-#define PMEVFILTR					0xA00
-#define PMCNTENSET					0xC00
-#define PMCNTENCLR					0xC20
-#define PMINTENSET					0xC40
-#define PMINTENCLR					0xC60
-#define PMOVSCLR					0xC80
-#define PMOVSSET					0xCC0
-#define PMCFGR						0xE00
-#define PMCR						0xE04
-#define PMIIDR						0xE08
-
-/* PMCFGR register field */
-#define PMCFGR_NCG					GENMASK(31, 28)
-#define PMCFGR_HDBG					BIT(24)
-#define PMCFGR_TRO					BIT(23)
-#define PMCFGR_SS					BIT(22)
-#define PMCFGR_FZO					BIT(21)
-#define PMCFGR_MSI					BIT(20)
-#define PMCFGR_UEN					BIT(19)
-#define PMCFGR_NA					BIT(17)
-#define PMCFGR_EX					BIT(16)
-#define PMCFGR_CCD					BIT(15)
-#define PMCFGR_CC					BIT(14)
-#define PMCFGR_SIZE					GENMASK(13, 8)
-#define PMCFGR_N					GENMASK(7, 0)
-
-/* PMCR register field */
-#define PMCR_TRO					BIT(11)
-#define PMCR_HDBG					BIT(10)
-#define PMCR_FZO					BIT(9)
-#define PMCR_NA						BIT(8)
-#define PMCR_DP						BIT(5)
-#define PMCR_X						BIT(4)
-#define PMCR_D						BIT(3)
-#define PMCR_C						BIT(2)
-#define PMCR_P						BIT(1)
-#define PMCR_E						BIT(0)
-
 /* Each SET/CLR register supports up to 32 counters. */
 #define ARM_CSPMU_SET_CLR_COUNTER_SHIFT		5
 #define ARM_CSPMU_SET_CLR_COUNTER_NUM		\
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 2621f3111148..576249e0deea 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -65,6 +65,52 @@
 /* The cycle counter, if implemented, is located at counter[31]. */
 #define ARM_CSPMU_CYCLE_CNTR_IDX	31
 
+/*
+ * CoreSight PMU Arch register offsets.
+ */
+#define PMEVCNTR_LO			0x0
+#define PMEVCNTR_HI			0x4
+#define PMEVTYPER			0x400
+#define PMCCFILTR			0x47C
+#define PMEVFILTR			0xA00
+#define PMCNTENSET			0xC00
+#define PMCNTENCLR			0xC20
+#define PMINTENSET			0xC40
+#define PMINTENCLR			0xC60
+#define PMOVSCLR			0xC80
+#define PMOVSSET			0xCC0
+#define PMIMPDEF			0xD80
+#define PMCFGR				0xE00
+#define PMCR				0xE04
+#define PMIIDR				0xE08
+
+/* PMCFGR register field */
+#define PMCFGR_NCG			GENMASK(31, 28)
+#define PMCFGR_HDBG			BIT(24)
+#define PMCFGR_TRO			BIT(23)
+#define PMCFGR_SS			BIT(22)
+#define PMCFGR_FZO			BIT(21)
+#define PMCFGR_MSI			BIT(20)
+#define PMCFGR_UEN			BIT(19)
+#define PMCFGR_NA			BIT(17)
+#define PMCFGR_EX			BIT(16)
+#define PMCFGR_CCD			BIT(15)
+#define PMCFGR_CC			BIT(14)
+#define PMCFGR_SIZE			GENMASK(13, 8)
+#define PMCFGR_N			GENMASK(7, 0)
+
+/* PMCR register field */
+#define PMCR_TRO			BIT(11)
+#define PMCR_HDBG			BIT(10)
+#define PMCR_FZO			BIT(9)
+#define PMCR_NA				BIT(8)
+#define PMCR_DP				BIT(5)
+#define PMCR_X				BIT(4)
+#define PMCR_D				BIT(3)
+#define PMCR_C				BIT(2)
+#define PMCR_P				BIT(1)
+#define PMCR_E				BIT(0)
+
 /* PMIIDR register field */
 #define ARM_CSPMU_PMIIDR_IMPLEMENTER	GENMASK(11, 0)
 #define ARM_CSPMU_PMIIDR_PRODUCTID	GENMASK(31, 20)
-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Wed Mar  5 08:10:08 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed,  5 Mar 2025 16:10:08 +0000
Subject: [PATCH 3/3] perf/arm_cspmu: Add PMEVFILT2R support
In-Reply-To: <cover.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
Message-ID: <b11be3f23a72bc27088b115099c8fe865b70babc.1741190362.git.robin.murphy@arm.com>

Architecturally we have two filters for each regular event counter,
so add generic support for the second one too.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/perf/arm_cspmu/arm_cspmu.c | 7 +++++--
 drivers/perf/arm_cspmu/arm_cspmu.h | 3 +++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 053bb7920df6..efa9b229e701 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -183,6 +183,7 @@ arm_cspmu_event_attr_is_visible(struct kobject *kobj,
 static struct attribute *arm_cspmu_format_attrs[] = {
 	ARM_CSPMU_FORMAT_EVENT_ATTR,
 	ARM_CSPMU_FORMAT_FILTER_ATTR,
+	ARM_CSPMU_FORMAT_FILTER2_ATTR,
 	NULL,
 };
 
@@ -767,9 +768,11 @@ static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
 				    const struct perf_event *event)
 {
 	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
-	u32 offset = PMEVFILTR + (4 * hwc->idx);
+	u32 filter2 = event->attr.config2 & ARM_CSPMU_FILTER_MASK;
+	u32 offset = 4 * event->hw.idx;
 
-	writel(filter, cspmu->base0 + offset);
+	writel(filter, cspmu->base0 + PMEVFILTR + offset);
+	writel(filter2, cspmu->base0 + PMEVFILT2R + offset);
 }
 
 static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index d59040d6a7e3..19684b76bd96 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -47,6 +47,8 @@
 /* Default filter format */
 #define ARM_CSPMU_FORMAT_FILTER_ATTR	\
 	ARM_CSPMU_FORMAT_ATTR(filter, "config1:0-31")
+#define ARM_CSPMU_FORMAT_FILTER2_ATTR	\
+	ARM_CSPMU_FORMAT_ATTR(filter2, "config2:0-31")
 
 /*
  * This is the default event number for cycle count, if supported, since the
@@ -72,6 +74,7 @@
 #define PMEVCNTR_HI			0x4
 #define PMEVTYPER			0x400
 #define PMCCFILTR			0x47C
+#define PMEVFILT2R			0x800
 #define PMEVFILTR			0xA00
 #define PMCNTENSET			0xC00
 #define PMCNTENCLR			0xC20
-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Wed Mar  5 08:10:07 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed,  5 Mar 2025 16:10:07 +0000
Subject: [PATCH 2/3] perf/arm_cspmu: Generalise event filtering
In-Reply-To: <cover.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
Message-ID: <c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com>

The notion of a single u32 filter value for any event doesn't scale well
when the potential architectural scope is already two 64-bit values, and
implementations may add custom stuff on the side too. Rather than try to
thread arbitrary filter data through the common path, let's just make
the set_ev_filter op self-contained in terms of parsing and configuring
any and all filtering for the given event - splitting out a distinct op
for cycles events which inherently differ - and let implementations
override the whole thing if they want to do something different. This
already allows the Ampere code to stop looking a bit hacky.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/perf/arm_cspmu/ampere_cspmu.c | 24 ++++++----------------
 drivers/perf/arm_cspmu/arm_cspmu.c    | 29 +++++++++++----------------
 drivers/perf/arm_cspmu/arm_cspmu.h    |  8 ++++----
 drivers/perf/arm_cspmu/nvidia_cspmu.c | 21 ++++++++++++++++++-
 4 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/drivers/perf/arm_cspmu/ampere_cspmu.c b/drivers/perf/arm_cspmu/ampere_cspmu.c
index 31cc1a4ac9df..b8ca69fd9d1d 100644
--- a/drivers/perf/arm_cspmu/ampere_cspmu.c
+++ b/drivers/perf/arm_cspmu/ampere_cspmu.c
@@ -132,32 +132,20 @@ ampere_cspmu_get_name(const struct arm_cspmu *cspmu)
 	return ctx->name;
 }
 
-static u32 ampere_cspmu_event_filter(const struct perf_event *event)
+static void ampere_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
+				       const struct perf_event *event)
 {
 	/*
-	 * PMEVFILTR or PMCCFILTR aren't used in Ampere SoC PMU but are marked
-	 * as RES0. Make sure, PMCCFILTR is written zero.
+	 * PMCCFILTR is RES0, so this is just a dummy callback to override
+	 * the default implementation and avoid writing to it.
 	 */
-	return 0;
 }
 
 static void ampere_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
-				       struct hw_perf_event *hwc,
-				       u32 filter)
+				       const struct perf_event *event)
 {
-	struct perf_event *event;
-	unsigned int idx;
 	u32 threshold, rank, bank;
 
-	/*
-	 * At this point, all the events have the same filter settings.
-	 * Therefore, take the first event and use its configuration.
-	 */
-	idx = find_first_bit(cspmu->hw_events.used_ctrs,
-			     cspmu->cycle_counter_logical_idx);
-
-	event = cspmu->hw_events.events[idx];
-
 	threshold	= get_threshold(event);
 	rank		= get_rank(event);
 	bank		= get_bank(event);
@@ -233,7 +221,7 @@ static int ampere_cspmu_init_ops(struct arm_cspmu *cspmu)
 
 	cspmu->impl.ctx = ctx;
 
-	impl_ops->event_filter		= ampere_cspmu_event_filter;
+	impl_ops->set_cc_filter		= ampere_cspmu_set_cc_filter;
 	impl_ops->set_ev_filter		= ampere_cspmu_set_ev_filter;
 	impl_ops->validate_event	= ampere_cspmu_validate_event;
 	impl_ops->get_name		= ampere_cspmu_get_name;
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 769466d55bea..053bb7920df6 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -66,7 +66,9 @@ static unsigned long arm_cspmu_cpuhp_state;
 static DEFINE_MUTEX(arm_cspmu_lock);
 
 static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
-				    struct hw_perf_event *hwc, u32 filter);
+				    const struct perf_event *event);
+static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
+				    const struct perf_event *event);
 
 static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
 {
@@ -205,11 +207,6 @@ static bool arm_cspmu_is_cycle_counter_event(const struct perf_event *event)
 	return (event->attr.config == ARM_CSPMU_EVT_CYCLES_DEFAULT);
 }
 
-static u32 arm_cspmu_event_filter(const struct perf_event *event)
-{
-	return event->attr.config1 & ARM_CSPMU_FILTER_MASK;
-}
-
 static ssize_t arm_cspmu_identifier_show(struct device *dev,
 					 struct device_attribute *attr,
 					 char *page)
@@ -371,7 +368,7 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
 		DEFAULT_IMPL_OP(get_name),
 		DEFAULT_IMPL_OP(is_cycle_counter_event),
 		DEFAULT_IMPL_OP(event_type),
-		DEFAULT_IMPL_OP(event_filter),
+		DEFAULT_IMPL_OP(set_cc_filter),
 		DEFAULT_IMPL_OP(set_ev_filter),
 		DEFAULT_IMPL_OP(event_attr_is_visible),
 	};
@@ -767,26 +764,26 @@ static inline void arm_cspmu_set_event(struct arm_cspmu *cspmu,
 }
 
 static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
-					struct hw_perf_event *hwc,
-					u32 filter)
+				    const struct perf_event *event)
 {
+	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
 	u32 offset = PMEVFILTR + (4 * hwc->idx);
 
 	writel(filter, cspmu->base0 + offset);
 }
 
-static inline void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu, u32 filter)
+static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
+				    const struct perf_event *event)
 {
-	u32 offset = PMCCFILTR;
+	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
 
-	writel(filter, cspmu->base0 + offset);
+	writel(filter, cspmu->base0 + PMCCFILTR);
 }
 
 static void arm_cspmu_start(struct perf_event *event, int pmu_flags)
 {
 	struct arm_cspmu *cspmu = to_arm_cspmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
-	u32 filter;
 
 	/* We always reprogram the counter */
 	if (pmu_flags & PERF_EF_RELOAD)
@@ -794,13 +791,11 @@ static void arm_cspmu_start(struct perf_event *event, int pmu_flags)
 
 	arm_cspmu_set_event_period(event);
 
-	filter = cspmu->impl.ops.event_filter(event);
-
 	if (event->hw.extra_reg.idx == cspmu->cycle_counter_logical_idx) {
-		arm_cspmu_set_cc_filter(cspmu, filter);
+		cspmu->impl.ops.set_cc_filter(cspmu, event);
 	} else {
 		arm_cspmu_set_event(cspmu, hwc);
-		cspmu->impl.ops.set_ev_filter(cspmu, hwc, filter);
+		cspmu->impl.ops.set_ev_filter(cspmu, event);
 	}
 
 	hwc->state = 0;
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 576249e0deea..d59040d6a7e3 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -149,11 +149,11 @@ struct arm_cspmu_impl_ops {
 	bool (*is_cycle_counter_event)(const struct perf_event *event);
 	/* Decode event type/id from configs */
 	u32 (*event_type)(const struct perf_event *event);
-	/* Decode filter value from configs */
-	u32 (*event_filter)(const struct perf_event *event);
-	/* Set event filter */
+	/* Set event filters */
+	void (*set_cc_filter)(struct arm_cspmu *cspmu,
+			      const struct perf_event *event);
 	void (*set_ev_filter)(struct arm_cspmu *cspmu,
-			      struct hw_perf_event *hwc, u32 filter);
+			      const struct perf_event *event);
 	/* Implementation specific event validation */
 	int (*validate_event)(struct arm_cspmu *cspmu,
 			      struct perf_event *event);
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index 8116c7846a46..9e817f120828 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -183,6 +183,24 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
 	return filter_val;
 }
 
+static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
+				   const struct perf_event *event)
+{
+	u32 filter = nv_cspmu_event_filter(event);
+	u32 offset = PMEVFILTR + (4 * event->hw.idx);
+
+	writel(filter, cspmu->base0 + offset);
+}
+
+static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
+				   const struct perf_event *event)
+{
+	u32 filter = nv_cspmu_event_filter(event);
+
+	writel(filter, cspmu->base0 + PMCCFILTR);
+}
+
+
 enum nv_cspmu_name_fmt {
 	NAME_FMT_GENERIC,
 	NAME_FMT_SOCKET
@@ -322,7 +340,8 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
 	cspmu->impl.ctx = ctx;
 
 	/* NVIDIA specific callbacks. */
-	impl_ops->event_filter			= nv_cspmu_event_filter;
+	impl_ops->set_cc_filter			= nv_cspmu_set_cc_filter;
+	impl_ops->set_ev_filter			= nv_cspmu_set_ev_filter;
 	impl_ops->get_event_attrs		= nv_cspmu_get_event_attrs;
 	impl_ops->get_format_attrs		= nv_cspmu_get_format_attrs;
 	impl_ops->get_name			= nv_cspmu_get_name;
-- 
2.39.2.101.g768bb238c484.dirty



From Jason-JH.Lin at mediatek.com  Wed Mar  5 08:12:39 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Wed, 5 Mar 2025 16:12:39 +0000
Subject: [PATCH v4 6/8] soc: mediatek: Add programming flow for
 unsupported subsys ID hardware
In-Reply-To: <c52b132b-fc08-4d1c-8276-1771f7457014@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-7-jason-jh.lin@mediatek.com>
	 <c52b132b-fc08-4d1c-8276-1771f7457014@collabora.com>
Message-ID: <ddcf01c82f92ee461875e1122b009b7fca691127.camel@mediatek.com>

On Tue, 2025-03-04 at 10:41 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > To support hardware without subsys IDs on new SoCs, add a
> > programming
> > flow that checks whether the subsys ID is valid. If the subsys ID
> > is
> > invalid, the flow will call 2 alternative CMDQ APIs:
> > cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the same
> > functionality.
> > 
> > Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> > ---
> > ? drivers/soc/mediatek/mtk-mmsys.c | 14 +++++++++++---
> > ? drivers/soc/mediatek/mtk-mutex.c | 11 +++++++++--
> > ? 2 files changed, 20 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/soc/mediatek/mtk-mmsys.c
> > b/drivers/soc/mediatek/mtk-mmsys.c
> > index bb4639ca0b8c..ce949b863b05 100644
> > --- a/drivers/soc/mediatek/mtk-mmsys.c
> > +++ b/drivers/soc/mediatek/mtk-mmsys.c
> > @@ -167,9 +167,17 @@ static void mtk_mmsys_update_bits(struct
> > mtk_mmsys *mmsys, u32 offset, u32 mask,
> > ????? u32 tmp;
> > 
> > ????? if (mmsys->cmdq_base.size && cmdq_pkt) {
> > -???????????? ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys-
> > >cmdq_base.subsys,
> > -?????????????????????????????????????? mmsys->cmdq_base.offset +
> > offset, val,
> > -?????????????????????????????????????? mask);
> > +???????????? offset += mmsys->cmdq_base.offset;
> > +???????????? if (mmsys->cmdq_base.subsys != CMDQ_SUBSYS_INVALID) {
> 
> You're still anyway passing the subsys to cmdq_pkt_write_mask(),
> right?!
> Why don't you just handle this in cmdq_pkt_write_mask() then? ;-)
> 
> I can see this pattern being repeated over and over in both
> drm/mediatek and MDP3
> drivers, and it's not necessary to duplicate this many times when you
> can write it
> just once.
> 
> Would've also been faster for you to implement... :-D
> 

I think did it in the series V1:
https://patchwork.kernel.org/project/linux-mediatek/patch/20241121042602.32730-5-jason-jh.lin at mediatek.com/

Because it'll need to passing the base_pa and that will need to change
the interface for original APIs.

And CK think that's not a necessary to change the APIs. It can be done
by cmdq_pkt_assign() + cmdq_pkt_write_s_mask_value() in the client
drivers. Then you can see this pattern in everywhere. :-)

Regards,
Jason-JH Lin

> Cheers,
> Angelo

From steven.price at arm.com  Wed Mar  5 08:25:17 2025
From: steven.price at arm.com (Steven Price)
Date: Wed, 5 Mar 2025 16:25:17 +0000
Subject: [PATCH v7 09/45] kvm: arm64: Expose debug HW register numbers for
 Realm
In-Reply-To: <cec600f2-2ddc-4c71-9bab-0a0403132b43@redhat.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-10-steven.price@arm.com>
 <cec600f2-2ddc-4c71-9bab-0a0403132b43@redhat.com>
Message-ID: <ea9bb982-cf31-4079-8fea-dc39e91a975b@arm.com>

Hi Gavin,

On 03/03/2025 04:48, Gavin Shan wrote:
> On 2/14/25 2:13 AM, Steven Price wrote:
>> From: Suzuki K Poulose <suzuki.poulose at arm.com>
>>
>> Expose VM specific Debug HW register numbers.

Looking at this now, this patch description is garbage. Probably the
patch has changed over time - so I suspect it's my fault not Suzuki's.
We're not exposing anything new here. This is purely about telling the
VMM that a realm cannot (currently) be debugged. Something like the
below would be more accurate:

"""
kvm: arm64: Don't expose debug capabilities for realm guests

RMM v1.0 provides no mechanism for the host to perform debug operations
on the guest. So don't expose KVM_CAP_SET_GUEST_DEBUG and report 0
breakpoints and 0 watch points.
"""

>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>> Signed-off-by: Steven Price <steven.price at arm.com>
>> ---
>> ? arch/arm64/kvm/arm.c | 24 +++++++++++++++++++++---
>> ? 1 file changed, 21 insertions(+), 3 deletions(-)
>>
> 
> Documentation/virt/kvm/api.rst needs to be updated accordingly.

I don't think (with the above clarification) there's anything to update
in the API documentation. There's nothing new being added, just
capabilities being hidden where the functionality isn't available.

And eventually we hope to add support for this (in a later RMM spec) - I
don't yet know exactly what form this will take, but I hope to keep the
interfaces as close as possible to what we already have so that existing
tooling can be used.

Thanks,
Steve

>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index b8fa82be251c..df6eb5e9ca96 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -78,6 +78,22 @@ bool is_kvm_arm_initialised(void)
>> ????? return kvm_arm_initialised;
>> ? }
>> ? +static u32 kvm_arm_get_num_brps(struct kvm *kvm)
>> +{
>> +??? if (!kvm_is_realm(kvm))
>> +??????? return get_num_brps();
>> +??? /* Realm guest is not debuggable. */
>> +??? return 0;
>> +}
>> +
>> +static u32 kvm_arm_get_num_wrps(struct kvm *kvm)
>> +{
>> +??? if (!kvm_is_realm(kvm))
>> +??????? return get_num_wrps();
>> +??? /* Realm guest is not debuggable. */
>> +??? return 0;
>> +}
>> +
> 
> The above two comments "Realm guest is not debuggable." can be dropped
> since
> the code is self-explanatory, and those two functions are unnecessary to be
> kept in that way, for example:
> 
> ????case KVM_CAP_GUEST_DEBUG_HW_BPS:
> ??????? return kvm_is_realm(kvm) ? 0 : get_num_brps();
> ????case KVM_CAP_GUEST_DEBUG_HW_WRPS:
> ??????? return kvm_is_realm(kvm) ? 0 : get_num_wrps();
> 
> 
>> ? int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>> ? {
>> ????? return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
>> @@ -323,7 +339,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm,
>> long ext)
>> ????? case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
>> ????? case KVM_CAP_ARM_NISV_TO_USER:
>> ????? case KVM_CAP_ARM_INJECT_EXT_DABT:
>> -??? case KVM_CAP_SET_GUEST_DEBUG:
>> ????? case KVM_CAP_VCPU_ATTRIBUTES:
>> ????? case KVM_CAP_PTP_KVM:
>> ????? case KVM_CAP_ARM_SYSTEM_SUSPEND:
>> @@ -331,6 +346,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm,
>> long ext)
>> ????? case KVM_CAP_COUNTER_OFFSET:
>> ????????? r = 1;
>> ????????? break;
>> +??? case KVM_CAP_SET_GUEST_DEBUG:
>> +??????? r = !kvm_is_realm(kvm);
>> +??????? break;
>> ????? case KVM_CAP_SET_GUEST_DEBUG2:
>> ????????? return KVM_GUESTDBG_VALID_MASK;
>> ????? case KVM_CAP_ARM_SET_DEVICE_ADDR:
>> @@ -376,10 +394,10 @@ int kvm_vm_ioctl_check_extension(struct kvm
>> *kvm, long ext)
>> ????????? r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
>> ????????? break;
>> ????? case KVM_CAP_GUEST_DEBUG_HW_BPS:
>> -??????? r = get_num_brps();
>> +??????? r = kvm_arm_get_num_brps(kvm);
>> ????????? break;
>> ????? case KVM_CAP_GUEST_DEBUG_HW_WPS:
>> -??????? r = get_num_wrps();
>> +??????? r = kvm_arm_get_num_wrps(kvm);
>> ????????? break;
>> ????? case KVM_CAP_ARM_PMU_V3:
>> ????????? r = kvm_arm_support_pmu_v3();
> 
> Thanks,
> Gavin
> 



From Jason-JH.Lin at mediatek.com  Wed Mar  5 08:26:55 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Wed, 5 Mar 2025 16:26:55 +0000
Subject: [PATCH v4 5/8] soc: mediatek: mtk-cmdq: Add mminfra_offset
 compatibility for DRAM address
In-Reply-To: <c1395546-9cfe-4da9-b87a-e5cc392910f6@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-6-jason-jh.lin@mediatek.com>
	 <c1395546-9cfe-4da9-b87a-e5cc392910f6@collabora.com>
Message-ID: <524d152b9e9261981b0ee3aa2ff43376a26be294.camel@mediatek.com>

On Tue, 2025-03-04 at 10:37 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > Since GCE has been moved to mminfra in MT8196, all transactions
> > from
> > mminfra to DRAM will have their addresses adjusted by subtracting a
> > mminfra offset.
> > This information should be handled inside the CMDQ driver, allowing
> > CMDQ users to call CMDQ APIs as usual.
> > 
> > Therefore, CMDQ driver needs to use the mbox API to get the
> > mminfra_offset value of the SoC, and then add it to the DRAM
> > address
> > when generating instructions to ensure GCE accesses the correct
> > DRAM
> > address.
> > 
> > Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> > ---
> > ? drivers/soc/mediatek/mtk-cmdq-helper.c | 35
> > ++++++++++++++++++++++++--
> > ? 1 file changed, 33 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c
> > b/drivers/soc/mediatek/mtk-cmdq-helper.c
> > index aa9853100d78..f2853a74af01 100644
> > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c
> > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
> > @@ -314,10 +314,22 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value);
> > 
> > ? int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr,
> > dma_addr_t dst_addr)
> > ? {
> > +???? struct cmdq_client *cl = (struct cmdq_client *)pkt->cl;
> > ????? const u16 high_addr_reg_idx? = CMDQ_THR_SPR_IDX0;
> > ????? const u16 value_reg_idx = CMDQ_THR_SPR_IDX1;
> > ????? int ret;
> > 
> > +???? if (!cl) {
> > +???????????? pr_err("%s %d: pkt->cl is NULL!\n", __func__,
> > __LINE__);
> > +???????????? return -EINVAL;
> > +???? }
> > +
> > +???? if (cmdq_addr_need_offset(cl->chan, src_addr))
> > +???????????? src_addr += cmdq_get_offset_pa(cl->chan);
> 
> If the offset is just DRAM IOSTART, you could manage that differently
> in the cmdq
> helper as well as the cmdq mailbox... :-)
> 

The offset_pa is not DRAM IOSTART, it is the MMINFRA subtracting
offset.

CMDQ helper is used to generate the instruction to the command buffer.
Since this offset_pa is added for the PA put into the instruction, I
think adding the offset_pa here is more suitable than CMDQ mailbox.
Does that make sense? :-)

Regards,
Jason-JH Lin

> > +
> > +???? if (cmdq_addr_need_offset(cl->chan, dst_addr))
> > +???????????? dst_addr += cmdq_get_offset_pa(cl->chan);
> > +
> Cheers,
> Angelo


From Frank.Li at nxp.com  Wed Mar  5 08:20:21 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Wed, 05 Mar 2025 11:20:21 -0500
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
Message-ID: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>

This patches basic on
https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/

I have not hardware to test.

Look for driver owner, who help test this and start move forward to remove
cpu_addr_fixup() work.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Frank Li (2):
      ARM: dts: ti: dra7: Correct ranges for PCIe and parent bus nodes
      PCI: dra7xx: Use use_parent_dt_ranges and clean up dra7xx_pcie_cpu_addr_fixup()

 arch/arm/boot/dts/ti/omap/dra7.dtsi     | 18 +++++++++---------
 drivers/pci/controller/dwc/pci-dra7xx.c |  8 +-------
 2 files changed, 10 insertions(+), 16 deletions(-)
---
base-commit: 1552be4855dacca5ea39b15b1ef0b96c91dbea0d
change-id: 20250305-dra-a7fea1c035bd

Best regards,
---
Frank Li <Frank.Li at nxp.com>



From Frank.Li at nxp.com  Wed Mar  5 08:20:22 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Wed, 05 Mar 2025 11:20:22 -0500
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
Message-ID: <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>

According to code in drivers/pci/controller/dwc/pci-dra7xx.c

dra7xx_pcie_cpu_addr_fixup()
{
	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
}

PCI parent bus trim high 4 bits address to 0. Correct ranges in
target-module at 51000000 to algin hardware behavior, which translate PCIe
outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.

Set 'config' and 'addr_space' reg values to 0.
Change parent bus address of downstream I/O and non-prefetchable memory to
0.

Ensure no functional impact on the final address translation result.

Prepare for the removal of the driver?s cpu_addr_fixup().

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
index b709703f6c0d4..9213fdd25330b 100644
--- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
+++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
@@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
 			#size-cells = <1>;
 			#address-cells = <1>;
 			ranges = <0x51000000 0x51000000 0x3000>,
-				 <0x20000000 0x20000000 0x10000000>;
+				 <0x00000000 0x20000000 0x10000000>;
 			dma-ranges;
 			/**
 			 * To enable PCI endpoint mode, disable the pcie1_rc
@@ -205,14 +205,14 @@ axi0: target-module at 51000000 {
 			pcie1_rc: pcie at 51000000 {
 				reg = <0x51000000 0x2000>,
 				      <0x51002000 0x14c>,
-				      <0x20001000 0x2000>;
+				      <0x00001000 0x2000>;
 				reg-names = "rc_dbics", "ti_conf", "config";
 				interrupts = <0 232 0x4>, <0 233 0x4>;
 				#address-cells = <3>;
 				#size-cells = <2>;
 				device_type = "pci";
-				ranges = <0x81000000 0 0x00000000 0x20003000 0 0x00010000>,
-					 <0x82000000 0 0x20013000 0x20013000 0 0x0ffed000>;
+				ranges = <0x81000000 0 0x00000000 0x00003000 0 0x00010000>,
+					 <0x82000000 0 0x20013000 0x00013000 0 0x0ffed000>;
 				bus-range = <0x00 0xff>;
 				#interrupt-cells = <1>;
 				num-lanes = <1>;
@@ -238,7 +238,7 @@ pcie1_ep: pcie_ep at 51000000 {
 				reg = <0x51000000 0x28>,
 				      <0x51002000 0x14c>,
 				      <0x51001000 0x28>,
-				      <0x20001000 0x10000000>;
+				      <0x00001000 0x10000000>;
 				reg-names = "ep_dbics", "ti_conf", "ep_dbics2", "addr_space";
 				interrupts = <0 232 0x4>;
 				num-lanes = <1>;
@@ -270,20 +270,20 @@ axi1: target-module at 51800000 {
 			#size-cells = <1>;
 			#address-cells = <1>;
 			ranges = <0x51800000 0x51800000 0x3000>,
-				 <0x30000000 0x30000000 0x10000000>;
+				 <0x00000000 0x30000000 0x10000000>;
 			dma-ranges;
 			status = "disabled";
 			pcie2_rc: pcie at 51800000 {
 				reg = <0x51800000 0x2000>,
 				      <0x51802000 0x14c>,
-				      <0x30001000 0x2000>;
+				      <0x00001000 0x2000>;
 				reg-names = "rc_dbics", "ti_conf", "config";
 				interrupts = <0 355 0x4>, <0 356 0x4>;
 				#address-cells = <3>;
 				#size-cells = <2>;
 				device_type = "pci";
-				ranges = <0x81000000 0 0x00000000 0x30003000 0 0x00010000>,
-					 <0x82000000 0 0x30013000 0x30013000 0 0x0ffed000>;
+				ranges = <0x81000000 0 0x00000000 0x00003000 0 0x00010000>,
+					 <0x82000000 0 0x30013000 0x00013000 0 0x0ffed000>;
 				bus-range = <0x00 0xff>;
 				#interrupt-cells = <1>;
 				num-lanes = <1>;

-- 
2.34.1



From Frank.Li at nxp.com  Wed Mar  5 08:20:23 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Wed, 05 Mar 2025 11:20:23 -0500
Subject: [PATCH PATCH RFC NOT TESTED 2/2] PCI: dra7xx: Use
 use_parent_dt_ranges and clean up dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
Message-ID: <20250305-dra-v1-2-8dc6d9a0e1c0@nxp.com>

Remove dra7xx_pcie_cpu_addr_fixup() as the DT bus fabric should provide correct
address translation. Set use_parent_dt_ranges to allow the DWC core driver to
fetch address translation from the device tree

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/pci/controller/dwc/pci-dra7xx.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index 33d6bf460ffe5..d6e0bf67a07b3 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -72,7 +72,6 @@
 
 #define	PCIECTRL_DRA7XX_CONF_PHY_CS			0x010C
 #define	LINK_UP						BIT(16)
-#define	DRA7XX_CPU_TO_BUS_ADDR				0x0FFFFFFF
 
 #define	PCIECTRL_TI_CONF_INTX_ASSERT			0x0124
 #define	PCIECTRL_TI_CONF_INTX_DEASSERT			0x0128
@@ -113,11 +112,6 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
 	writel(value, pcie->base + offset);
 }
 
-static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
-{
-	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;
-}
-
 static int dra7xx_pcie_link_up(struct dw_pcie *pci)
 {
 	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
@@ -514,7 +508,6 @@ static int dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
-	.cpu_addr_fixup = dra7xx_pcie_cpu_addr_fixup,
 	.start_link = dra7xx_pcie_establish_link,
 	.stop_link = dra7xx_pcie_stop_link,
 	.link_up = dra7xx_pcie_link_up,
@@ -712,6 +705,7 @@ static int dra7xx_pcie_probe(struct platform_device *pdev)
 
 	pci->dev = dev;
 	pci->ops = &dw_pcie_ops;
+	pci->use_parent_dt_ranges = true;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)

-- 
2.34.1



From conor at kernel.org  Wed Mar  5 08:28:16 2025
From: conor at kernel.org (Conor Dooley)
Date: Wed, 5 Mar 2025 16:28:16 +0000
Subject: [PATCH v3 1/4] dt-bindings: interrupt-controller: Add support
 for Amlogic A4 and A5 SoCsy
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>
Message-ID: <20250305-corral-unfair-a7f25abbfd64@spud>

On Wed, Mar 05, 2025 at 06:02:56PM +0800, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> 
> Update dt-binding document for GPIO interrupt controller
> of Amlogic A4 and A5 SoCs
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  .../amlogic,meson-gpio-intc.yaml                    | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> index a93744763787..3c5853c71efa 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> @@ -35,6 +35,9 @@ properties:
>                - amlogic,meson-sm1-gpio-intc
>                - amlogic,meson-a1-gpio-intc
>                - amlogic,meson-s4-gpio-intc
> +              - amlogic,a4-gpio-intc
> +              - amlogic,a4-gpio-ao-intc
> +              - amlogic,a5-gpio-intc
>                - amlogic,c3-gpio-intc
>                - amlogic,t7-gpio-intc
>            - const: amlogic,meson-gpio-intc
> @@ -49,8 +52,6 @@ properties:
>  
>    amlogic,channel-interrupts:
>      description: Array with the upstream hwirq numbers
> -    minItems: 8
> -    maxItems: 12

Please leave the widest constraints here, and let the more restricted
ones in your if/else below.

>      $ref: /schemas/types.yaml#/definitions/uint32-array
>  
>  required:
> @@ -60,6 +61,22 @@ required:
>    - "#interrupt-cells"
>    - amlogic,channel-interrupts
>  
> +if:
> +  properties:
> +    compatible:
> +      contains:
> +        const: amlogic,a4-gpio-ao-intc
> +then:
> +  properties:
> +    amlogic,channel-interrupts:
> +      minItems: 2
> +      maxItems: 12
> +else:
> +  properties:
> +    amlogic,channel-interrupts:
> +      minItems: 8
> +      maxItems: 12
> +
>  additionalProperties: false
>  
>  examples:
> 
> -- 
> 2.37.1
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/66b46cf7/attachment.sig>

From conor at kernel.org  Wed Mar  5 08:31:23 2025
From: conor at kernel.org (Conor Dooley)
Date: Wed, 5 Mar 2025 16:31:23 +0000
Subject: [PATCH RFC 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <20250305082047.15746-4-jjian.zhou@mediatek.com>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
 <20250305082047.15746-4-jjian.zhou@mediatek.com>
Message-ID: <20250305-chewing-henchman-aea98c18b412@spud>

On Wed, Mar 05, 2025 at 04:20:40PM +0800, Jjian Zhou wrote:
> This patch adds document for mediatek vcp mbox.
> 
> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> ---
>  .../bindings/mailbox/mtk,vcp-mbox.yaml        | 49 +++++++++++++++++++
>  1 file changed, 49 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> new file mode 100644
> index 000000000000..d5afe295af14
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml

When you go !RFC, filename matching compatible please.

> @@ -0,0 +1,49 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mailbox/mtk,vcp-mbox.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek Video Companion Processor (VCP) mailbox
> +
> +maintainers:
> +  - Jjian Zhou <Jjian.Zhou at mediatek.com>
> +
> +description: |
> +  The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
> +  messages through 64 32-bit wide registers. It has 32 interrupt vectors in
> +  either direction for signalling purposes.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - mediatek,mt8196-vcp-mbox
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  "#mbox-cells":
> +    const: 0
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - "#mbox-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    vcp_mailbox0: mailbox at 31b80000 {

label here is unused, please drop it.

Cheers,
Conor.

> +        compatible = "mediatek,mt8196-vcp-mbox";
> +        reg = <0x31b80000 0x1000>;
> +        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
> +        #mbox-cells = <0>;
> +    };
> -- 
> 2.45.2
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/da3c8034/attachment.sig>

From ryan.roberts at arm.com  Wed Mar  5 08:32:21 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Wed, 5 Mar 2025 16:32:21 +0000
Subject: [PATCH v3 05/11] arm64: hugetlb: Use set_ptes_anysz() and
 ptep_get_and_clear_anysz()
In-Reply-To: <202503052315.vk7m958M-lkp@intel.com>
References: <20250304150444.3788920-6-ryan.roberts@arm.com>
 <202503052315.vk7m958M-lkp@intel.com>
Message-ID: <47fd6aed-cb91-488d-ac2c-92f9ce73887f@arm.com>

On 05/03/2025 16:00, kernel test robot wrote:
> Hi Ryan,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on linus/master]
> [also build test WARNING on v6.14-rc5 next-20250305]
> [cannot apply to arm64/for-next/core akpm-mm/mm-everything arm-perf/for-next/perf]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Roberts/arm64-hugetlb-Cleanup-huge_pte-size-discovery-mechanisms/20250304-230647
> base:   linus/master
> patch link:    https://lore.kernel.org/r/20250304150444.3788920-6-ryan.roberts%40arm.com
> patch subject: [PATCH v3 05/11] arm64: hugetlb: Use set_ptes_anysz() and ptep_get_and_clear_anysz()
> config: arm64-randconfig-003-20250305 (https://download.01.org/0day-ci/archive/20250305/202503052315.vk7m958M-lkp at intel.com/config)
> compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503052315.vk7m958M-lkp at intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202503052315.vk7m958M-lkp at intel.com/
> 
> All warnings (new ones prefixed by >>):
> 
>    In file included from arch/arm64/mm/hugetlbpage.c:12:
>    In file included from include/linux/mm.h:2224:
>    include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>      504 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>          |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>      505 |                            item];
>          |                            ~~~~
>    include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>      511 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>          |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>      512 |                            NR_VM_NUMA_EVENT_ITEMS +
>          |                            ~~~~~~~~~~~~~~~~~~~~~~
>>> arch/arm64/mm/hugetlbpage.c:154:23: warning: parameter 'addr' set but not used [-Wunused-but-set-parameter]
>      154 |                              unsigned long addr,
>          |                                            ^
>    3 warnings generated.
> 
> 
> vim +/addr +154 arch/arm64/mm/hugetlbpage.c
> 
> bc5dfb4fd7bd471 Baolin Wang       2022-05-16  144  
> d8bdcff2876424d Steve Capper      2017-08-22  145  /*
> d8bdcff2876424d Steve Capper      2017-08-22  146   * Changing some bits of contiguous entries requires us to follow a
> d8bdcff2876424d Steve Capper      2017-08-22  147   * Break-Before-Make approach, breaking the whole contiguous set
> d8bdcff2876424d Steve Capper      2017-08-22  148   * before we can change any entries. See ARM DDI 0487A.k_iss10775,
> d8bdcff2876424d Steve Capper      2017-08-22  149   * "Misprogramming of the Contiguous bit", page D4-1762.
> d8bdcff2876424d Steve Capper      2017-08-22  150   *
> d8bdcff2876424d Steve Capper      2017-08-22  151   * This helper performs the break step.
> d8bdcff2876424d Steve Capper      2017-08-22  152   */
> fb396bb459c1fa3 Anshuman Khandual 2022-05-10  153  static pte_t get_clear_contig(struct mm_struct *mm,
> d8bdcff2876424d Steve Capper      2017-08-22 @154  			     unsigned long addr,
> d8bdcff2876424d Steve Capper      2017-08-22  155  			     pte_t *ptep,
> d8bdcff2876424d Steve Capper      2017-08-22  156  			     unsigned long pgsize,
> d8bdcff2876424d Steve Capper      2017-08-22  157  			     unsigned long ncontig)
> d8bdcff2876424d Steve Capper      2017-08-22  158  {
> 49c87f7677746f3 Ryan Roberts      2025-02-26  159  	pte_t pte, tmp_pte;
> 49c87f7677746f3 Ryan Roberts      2025-02-26  160  	bool present;
> 49c87f7677746f3 Ryan Roberts      2025-02-26  161  
> 66251d3eadf78e2 Ryan Roberts      2025-03-04  162  	pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
> 49c87f7677746f3 Ryan Roberts      2025-02-26  163  	present = pte_present(pte);
> 49c87f7677746f3 Ryan Roberts      2025-02-26  164  	while (--ncontig) {
> 49c87f7677746f3 Ryan Roberts      2025-02-26  165  		ptep++;
> 49c87f7677746f3 Ryan Roberts      2025-02-26  166  		addr += pgsize;

Ahh yes, thanks! Looks like this line can be removed since we no longer need the
address.

Catalin, I was optimistically hoping this might be the final version. If it is,
are you happy to fold this in? Or do you want me to re-spin regardless?

> 66251d3eadf78e2 Ryan Roberts      2025-03-04  167  		tmp_pte = ptep_get_and_clear_anysz(mm, ptep, pgsize);
> 49c87f7677746f3 Ryan Roberts      2025-02-26  168  		if (present) {
> 49c87f7677746f3 Ryan Roberts      2025-02-26  169  			if (pte_dirty(tmp_pte))
> 49c87f7677746f3 Ryan Roberts      2025-02-26  170  				pte = pte_mkdirty(pte);
> 49c87f7677746f3 Ryan Roberts      2025-02-26  171  			if (pte_young(tmp_pte))
> 49c87f7677746f3 Ryan Roberts      2025-02-26  172  				pte = pte_mkyoung(pte);
> d8bdcff2876424d Steve Capper      2017-08-22  173  		}
> 49c87f7677746f3 Ryan Roberts      2025-02-26  174  	}
> 49c87f7677746f3 Ryan Roberts      2025-02-26  175  	return pte;
> d8bdcff2876424d Steve Capper      2017-08-22  176  }
> d8bdcff2876424d Steve Capper      2017-08-22  177  
> 



From robh at kernel.org  Wed Mar  5 08:45:27 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 5 Mar 2025 10:45:27 -0600
Subject: [PATCH v2 05/15] dt-bindings: irq: sun7i-nmi: document the
 Allwinner A523 NMI controller
In-Reply-To: <20250304222309.29385-6-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-6-andre.przywara@arm.com>
Message-ID: <174119312747.2117747.1409262151131178032.robh@kernel.org>


On Tue, 04 Mar 2025 22:22:59 +0000, Andre Przywara wrote:
> The Allwinner A523 SoC contains an NMI controller very close to the one
> used in the recent Allwinner SoCs, but it adds another bit that needs to
> be toggled to actually deliver the IRQs. Sigh.
> 
> Add the A523 specific name to the list of allowed compatible strings.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml         | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Wed Mar  5 08:46:27 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 10:46:27 -0600
Subject: [PATCH RFC 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <20250305082047.15746-4-jjian.zhou@mediatek.com>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
 <20250305082047.15746-4-jjian.zhou@mediatek.com>
Message-ID: <20250305164627.GA2117924-robh@kernel.org>

On Wed, Mar 05, 2025 at 04:20:40PM +0800, Jjian Zhou wrote:
> This patch adds document for mediatek vcp mbox.
> 
> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> ---
>  .../bindings/mailbox/mtk,vcp-mbox.yaml        | 49 +++++++++++++++++++
>  1 file changed, 49 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> new file mode 100644
> index 000000000000..d5afe295af14
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> @@ -0,0 +1,49 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mailbox/mtk,vcp-mbox.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek Video Companion Processor (VCP) mailbox
> +
> +maintainers:
> +  - Jjian Zhou <Jjian.Zhou at mediatek.com>
> +
> +description: |

Don't need '|' if no formatting

> +  The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
> +  messages through 64 32-bit wide registers. It has 32 interrupt vectors in
> +  either direction for signalling purposes.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - mediatek,mt8196-vcp-mbox
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  "#mbox-cells":
> +    const: 0
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - "#mbox-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    vcp_mailbox0: mailbox at 31b80000 {
> +        compatible = "mediatek,mt8196-vcp-mbox";
> +        reg = <0x31b80000 0x1000>;
> +        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
> +        #mbox-cells = <0>;
> +    };
> -- 
> 2.45.2
> 


From robh at kernel.org  Wed Mar  5 08:47:58 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 5 Mar 2025 10:47:58 -0600
Subject: [PATCH v3 1/8] dt-bindings: mfd: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250305094935.595667-2-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-2-fabrice.gasnier@foss.st.com>
Message-ID: <174119327848.2121305.11563216194052431018.robh@kernel.org>


On Wed, 05 Mar 2025 10:49:28 +0100, Fabrice Gasnier wrote:
> Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
> STM32MP25 SoC. Some features has been updated or added to the low-power
> timer:
> - new capture compare channels
> - up to two PWM channels
> - PWM input capture
> - peripheral interconnect in stm32mp25 has been updated (new triggers).
> - registers/bits has been added or revisited (IER access).
> So introduce a new compatible to handle this diversity.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
> Changes in V3:
> - Fix yaml indentation issue found by Rob's bot
> Changes in V2:
> - Use fallback compatibles, along with stm32mp25 specific compatible
> - trigger identifier can be up to 4 (e.g. from LPTIM1..5)
> ---
>  .../bindings/mfd/st,stm32-lptimer.yaml        | 40 ++++++++++++++++---
>  1 file changed, 34 insertions(+), 6 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From aweber.kernel at gmail.com  Wed Mar  5 08:52:12 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Wed, 5 Mar 2025 17:52:12 +0100
Subject: [PATCH v6 02/10] dt-bindings: mfd: brcm,bcm59056: Add compatible
 for BCM59054
In-Reply-To: <20250304141933.GA2543583-robh@kernel.org>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-2-ae8302358443@gmail.com>
 <20250304141933.GA2543583-robh@kernel.org>
Message-ID: <51cefa7f-df05-49d4-9006-59ed216915a4@gmail.com>

On 4.03.2025 15:19, Rob Herring wrote:
> On Tue, Mar 04, 2025 at 07:20:33AM +0100, Artur Weber wrote:
>> The BCM59054 MFD is fairly similar to the BCM59056, and will use
>> the same driver. Add compatible and specify the allowed regulator
>> nodes.
>>
>> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
>> ...
> And drop the allOf below.
> 
>>   
>>   required:
>>     - compatible
>> @@ -30,6 +31,27 @@ required:
>>   
>>   additionalProperties: false
>>   
>> +allOf:
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            const: brcm,bcm59054
>> +    then:
>> +      properties:
>> +        regulators:
>> +          $ref: /schemas/regulator/brcm,bcm59054.yaml#
>> +
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            const: brcm,bcm59056
>> +    then:
>> +      properties:
>> +        regulators:
>> +          $ref: /schemas/regulator/brcm,bcm59056.yaml#
>> +
>>   examples:
>>     - |
>>       #include <dt-bindings/interrupt-controller/arm-gic.h>

"Drop the allOf" as in, drop just the "allOf" line or the entire block
with "if" statements? If it's the latter - wouldn't that break the
bindings for the "regulators" subnode?

Best regards
Artur


From jgg at nvidia.com  Wed Mar  5 08:54:52 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 12:54:52 -0400
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <cover.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
Message-ID: <20250305165452.GY133783@nvidia.com>

On Tue, Mar 04, 2025 at 09:03:59PM -0800, Nicolin Chen wrote:

> Have a pair of patches getting the functions ready for the vmid migration.
> Decouple the vmid from S2 parent domains and move its allocation to vSMMU
> instances. Note that a regular S2 domain (!nest_parent) has to retain the
> s2_cfg and vmid for non-nesting use cases, if the SMMU HW doesn't support
> stage 1. Then, an S2 invalidation has to be iterated for all the vmids in
> the vSMMU list introduced in the S2 parent domain.

I was planning to also fix the S2 to be able to attach to multiple
IOMMU instances at the same time as getting VMID to the viommu.. It
doesn't quite make sense to me that viommu would allow multi-attach
but the normal cases wouldn't. Did you find a shortcut?

The main issue here was to do this without degrading the invalidation
workflow and harming SVA and DMA API performance..

Jason


From jgg at nvidia.com  Wed Mar  5 08:55:19 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 12:55:19 -0400
Subject: [PATCH v1 1/4] iommu/arm-smmu-v3: Pass in vmid to
 arm_smmu_make_s2_domain_ste()
In-Reply-To: <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>
Message-ID: <20250305165519.GZ133783@nvidia.com>

On Tue, Mar 04, 2025 at 09:04:00PM -0800, Nicolin Chen wrote:
> An stage-2 STE requires a vmid that has been so far allocated per domain,
> so arm_smmu_make_s2_domain_ste() has been extracting the vmid from the S2
> domain.
> 
> To share an S2 parent domain across vSMMUs in the same VM, a vmid will be
> no longer allocated for nor stored in the S2 domain, but per vSMMU, which
> means the arm_smmu_make_s2_domain_ste() can get a vmid either from an S2
> domain (non nesting parent) or a vSMMU.
> 
> Allow to pass in vmid explicitly to arm_smmu_make_s2_domain_ste(), giving
> its callers a chance to pick the vmid between a domain or a vSMMU.
> 
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 2 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 6 ++++--
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c    | 3 ++-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c         | 6 +++---
>  4 files changed, 10 insertions(+), 7 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

Jason


From linux at roeck-us.net  Wed Mar  5 08:54:27 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 5 Mar 2025 08:54:27 -0800
Subject: [PATCH v3 3/3] hwmon: emc2305: Use
 devm_thermal_of_cooling_device_register
In-Reply-To: <20250304162136.1963384-4-florin.leotescu@oss.nxp.com>
References: <20250304162136.1963384-1-florin.leotescu@oss.nxp.com>
 <20250304162136.1963384-4-florin.leotescu@oss.nxp.com>
Message-ID: <23608097-f226-471b-b070-d3834e5c129b@roeck-us.net>

On 3/4/25 08:21, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> This prepares emc2305 driver to use configuration from Device Tree nodes.
> Using devm_thermal_of_cooling_device_register also simplifies cleanup
> procedure, so we are able to remove the emc2305_unset_tz and emc2305_remove
> functions which are no longer used.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>   drivers/hwmon/emc2305.c | 28 +++-------------------------
>   1 file changed, 3 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
> index a236f27c75bc..5f3f06308826 100644
> --- a/drivers/hwmon/emc2305.c
> +++ b/drivers/hwmon/emc2305.c
> @@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
>   	"emc2305_fan5",
>   };
>   
> -static void emc2305_unset_tz(struct device *dev);
> -
>   static int emc2305_get_max_channel(const struct emc2305_data *data)
>   {
>   	return data->pwm_num;
> @@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
>   	pwm = data->pwm_min[cdev_idx];
>   
>   	data->cdev_data[cdev_idx].cdev =
> -		thermal_cooling_device_register(emc2305_fan_name[idx], data,
> -						&emc2305_cooling_ops);
> +		devm_thermal_of_cooling_device_register(dev, dev->of_node,
> +							emc2305_fan_name[idx], data,
> +							&emc2305_cooling_ops);
>   
>   	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
>   		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
> @@ -337,21 +336,9 @@ static int emc2305_set_tz(struct device *dev)
>   	return 0;
>   
>   thermal_cooling_device_register_fail:

This label is no longer necessary. Instead, any goto can be replaced with
an immediate return statement.

> -	emc2305_unset_tz(dev);
>   	return ret;
>   }
>   
> -static void emc2305_unset_tz(struct device *dev)
> -{
> -	struct emc2305_data *data = dev_get_drvdata(dev);
> -	int i;
> -
> -	/* Unregister cooling device. */
> -	for (i = 0; i < EMC2305_PWM_MAX; i++)
> -		if (data->cdev_data[i].cdev)
> -			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
> -}
> -
>   static umode_t
>   emc2305_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
>   {
> @@ -599,14 +586,6 @@ static int emc2305_probe(struct i2c_client *client)
>   	return 0;
>   }
>   
> -static void emc2305_remove(struct i2c_client *client)
> -{
> -	struct device *dev = &client->dev;
> -
> -	if (IS_REACHABLE(CONFIG_THERMAL))
> -		emc2305_unset_tz(dev);
> -}
> -
>   static const struct of_device_id of_emc2305_match_table[] = {
>   	{ .compatible = "microchip,emc2301", },
>   	{ .compatible = "microchip,emc2302", },
> @@ -622,7 +601,6 @@ static struct i2c_driver emc2305_driver = {
>   		.of_match_table = of_emc2305_match_table,
>   	},
>   	.probe = emc2305_probe,
> -	.remove	  = emc2305_remove,
>   	.id_table = emc2305_ids,
>   };
>   



From jgg at nvidia.com  Wed Mar  5 08:57:43 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 12:57:43 -0400
Subject: [PATCH v1 4/4] iommu/arm-smmu-v3-iommufd: Allow a shared
 s2_parent to allocate vSMMU
In-Reply-To: <1b51a7f7bfc0419b8941cf7ee0601b70@huawei.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <564eda8dee4bbf4c6e1d1dd9ed6bd40cc1a2df26.1741150594.git.nicolinc@nvidia.com>
 <1b51a7f7bfc0419b8941cf7ee0601b70@huawei.com>
Message-ID: <20250305165743.GA133783@nvidia.com>

On Wed, Mar 05, 2025 at 09:01:40AM +0000, Shameerali Kolothum Thodi wrote:

> >  	if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
> >  		return ERR_PTR(-EOPNOTSUPP);
> > 
> > -	if (s2_parent->smmu != master->smmu)
> > -		return ERR_PTR(-EINVAL);
> > -
> 
> Not sure we can just relax this like this. What if the two physical SMMUs are different in
> functionality/features? Do we need some kind of sanity check here?

Yes, a function to check if a domain's iopgtbl config is compatible
with the instance is required.

Jason


From angelogioacchino.delregno at collabora.com  Wed Mar  5 09:09:08 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 18:09:08 +0100
Subject: [PATCH] arm64: dts: mediatek: mt8390-genio-common: Add jack
 detection with accdet
In-Reply-To: <20250304-genio700-accdet-dts-v1-1-86d77c5cc745@collabora.com>
References: <20250304-genio700-accdet-dts-v1-1-86d77c5cc745@collabora.com>
Message-ID: <dc68cb1c-0304-4ebf-ae38-444817a02f78@collabora.com>

Il 04/03/25 22:43, N?colas F. R. A. Prado ha scritto:
> Enable audio jack detection for the Genio 700 and 510 EVK boards. This
> is handled by the MT6359 ACCDET block, which on these boards has the
> HP_EINT pin pulled high and connected to a normally open 3.5mm jack.
> 
> Add a phandle to the accdet in the sound card node so the machine sound
> driver can initialize the accdet.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

For the next merge cycle;

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

> ---
> This patch depends on both "Allow retrieving accessory detection
> reference on MT8188" [1] and "Get mt6359-accdet ready for usage in
> Devicetree" [2].
> 
> [1] https://lore.kernel.org/all/20250304-mt8188-accdet-v2-0-27f496c4aede at collabora.com
> [2] https://lore.kernel.org/all/20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b at collabora.com
> ---
>   arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi | 1 +
>   1 file changed, 1 insertion(+)
> 


From jgg at nvidia.com  Wed Mar  5 09:01:57 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 13:01:57 -0400
Subject: [PATCH v1 3/4] iommu/arm-smmu-v3: Decouple vmid from S2
 nest_parent domain
In-Reply-To: <0429d554fb0f54f6d79bdacacb3fb3e7877ca8f7.1741150594.git.nicolinc@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <0429d554fb0f54f6d79bdacacb3fb3e7877ca8f7.1741150594.git.nicolinc@nvidia.com>
Message-ID: <20250305170157.GB133783@nvidia.com>

On Tue, Mar 04, 2025 at 09:04:02PM -0800, Nicolin Chen wrote:
> @@ -2249,10 +2249,22 @@ static void arm_smmu_tlb_inv_context(void *cookie)
>  	 */
>  	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
>  		arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
> -	} else {
> +	} else if (!smmu_domain->nest_parent) {
>  		cmd.opcode	= CMDQ_OP_TLBI_S12_VMALL;
>  		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
>  		arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
> +	} else {
> +		struct arm_vsmmu *vsmmu, *next;
> +		unsigned long flags;
> +
> +		cmd.opcode = CMDQ_OP_TLBI_S12_VMALL;
> +		spin_lock_irqsave(&smmu_domain->vsmmus.lock, flags);
> +		list_for_each_entry_safe(vsmmu, next, &smmu_domain->vsmmus.list,
> +					 vsmmus_elm) {
> +			cmd.tlbi.vmid = vsmmu->vmid;
> +			arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
> +		}
> +		spin_unlock_irqrestore(&smmu_domain->vsmmus.lock, flags);
>  	}

I see.. So this just makes a 3rd classification of invalidation
protocol that uses a spinlock and linked list

>  	arm_smmu_atc_inv_domain(smmu_domain, 0, 0);

This is no good, arm_smmu_atc_inv_domain() is invalidating against the
instance that created the domain.

IMHO if you do this you should set domain->iommu = NULL to indicate
that the iommu is non-valid in this mode to catch issues.

Jason


From robh at kernel.org  Wed Mar  5 09:02:15 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 11:02:15 -0600
Subject: [PATCH v6 02/10] dt-bindings: mfd: brcm,bcm59056: Add compatible
 for BCM59054
In-Reply-To: <51cefa7f-df05-49d4-9006-59ed216915a4@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-2-ae8302358443@gmail.com> <20250304141933.GA2543583-robh@kernel.org>
 <51cefa7f-df05-49d4-9006-59ed216915a4@gmail.com>
Message-ID: <CAL_Jsq+Qsu-6Z72uXYKwc62idq2K169S1t0nUrrgNOyezgfYsA@mail.gmail.com>

On Wed, Mar 5, 2025 at 10:52?AM Artur Weber <aweber.kernel at gmail.com> wrote:
>
> On 4.03.2025 15:19, Rob Herring wrote:
> > On Tue, Mar 04, 2025 at 07:20:33AM +0100, Artur Weber wrote:
> >> The BCM59054 MFD is fairly similar to the BCM59056, and will use
> >> the same driver. Add compatible and specify the allowed regulator
> >> nodes.
> >>
> >> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> >> ...
> > And drop the allOf below.
> >
> >>
> >>   required:
> >>     - compatible
> >> @@ -30,6 +31,27 @@ required:
> >>
> >>   additionalProperties: false
> >>
> >> +allOf:
> >> +  - if:
> >> +      properties:
> >> +        compatible:
> >> +          contains:
> >> +            const: brcm,bcm59054
> >> +    then:
> >> +      properties:
> >> +        regulators:
> >> +          $ref: /schemas/regulator/brcm,bcm59054.yaml#
> >> +
> >> +  - if:
> >> +      properties:
> >> +        compatible:
> >> +          contains:
> >> +            const: brcm,bcm59056
> >> +    then:
> >> +      properties:
> >> +        regulators:
> >> +          $ref: /schemas/regulator/brcm,bcm59056.yaml#
> >> +
> >>   examples:
> >>     - |
> >>       #include <dt-bindings/interrupt-controller/arm-gic.h>
>
> "Drop the allOf" as in, drop just the "allOf" line or the entire block
> with "if" statements? If it's the latter - wouldn't that break the
> bindings for the "regulators" subnode?

Uh, I misread this thinking the regulators node had a compatible... Never mind.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>


From maxime.chevallier at bootlin.com  Wed Mar  5 09:02:52 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Wed, 5 Mar 2025 18:02:52 +0100
Subject: [PATCH net-next 0/7] net: ethtool: Introduce ethnl dump helpers
In-Reply-To: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
Message-ID: <20250305180252.5a0ceb86@fedora.home>

On Wed,  5 Mar 2025 15:19:30 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> Hi everyone,
> 
> This series adds some scaffolding into ethnl to ease the support of
> DUMP operations.
> 
> As of today when using ethnl's default ops, the DUMP requests will
> simply perform a GET for each netdev.
> 
> That hits limitations for commands that may return multiple messages for
> a single netdev, such as :
> 
>  - RSS (listing contexts)
>  - All PHY-specific commands (PLCA, PSE-PD, phy)
>  - tsinfo (one item for the netdev +  one per phy)
> 
>  Commands that need a non-default DUMP support have to re-implement
>  ->dumpit() themselves, which prevents using most of ethnl's internal  
>  circuitry.
> 
> This series therefore introduces a better support for dump operations in
> ethnl.
> 
> The patches 1 and 2 introduce the support for filtered DUMPs, where an
> ifindex/ifname can be passed in the request header for the DUMP
> operation. This is for when we want to dump everything a netdev
> supports, but without doing so for every single netdev. ethtool's
> "--show-phys ethX" option for example performs a filtered dump.
> 
> Patch 3 introduces 3 new ethnl ops : 
>  ->dump_start() to initialize a dump context
>  ->dump_one_dev(), that can be implemented per-command to dump  
>  everything on a given netdev
>  ->dump_done() to release the context  
> 
> The default behaviour for dumps remains the same, calling the whole
> ->doit() path for each netdev.  
> 
> Patch 4 introduces a set of ->dump_start(), ->dump_one_dev() and
> ->dump_done() callback implementations that can simply be plugged into  
> the existing commands that list objects per-phy, making the 
> phy-targeting command behaviour more coherent.
> 
> Patch 5 uses that new set of helpers to rewrite the phy.c support, which
> now uses the regulat ethnl_ops instead of fully custom genl ops. This
> one is the hardest to review, sorry about that, I couldn't really manage
> to incrementally rework that file :(
> 
> Patches 6 and 7 are where the new dump infra shines, adding per-netdev
> per-phy dump support for PLCA and PSE-PD.
> 
> We could also consider converting tsinfo/tsconfig, rss and tunnels to
> these new ->dump_***() operations as well, but that's out of this
> series' scope.
> 
> I've tested that series with some netdevsim PHY patches that I plan to
> submit (they can be found here [1]), with the refcount tracker
> for net/netns enabled to make sure the lock usage is somewhat coherent.
> 
> Thanks,
> 
> Maxime
> 
> [1]: https://github.com/minimaxwell/linux/tree/mc/netdevsim-phy
> 

This series will very likely conflict with Stanislav's netdev lock
work [2], I'll of course be happy to rebase should it get merged :)

Thanks,

Maxime

[2]: https://lore.kernel.org/netdev/20250305163732.2766420-1-sdf at fomichev.me/T/#t

> 
> Maxime Chevallier (7):
>   net: ethtool: netlink: Allow per-netdevice DUMP operations
>   net: ethtool: netlink: Rename ethnl_default_dump_one
>   net: ethtool: netlink: Introduce command-specific dump_one_dev
>   net: ethtool: netlink: Introduce per-phy DUMP helpers
>   net: ethtool: phy: Convert the PHY_GET command to generic phy dump
>   net: ethtool: plca: Use per-PHY DUMP operations
>   net: ethtool: pse-pd: Use per-PHY DUMP operations
> 
>  net/ethtool/netlink.c | 161 ++++++++++++++------
>  net/ethtool/netlink.h |  46 +++++-
>  net/ethtool/phy.c     | 335 ++++++++++++------------------------------
>  net/ethtool/plca.c    |  12 ++
>  net/ethtool/pse-pd.c  |   6 +
>  5 files changed, 277 insertions(+), 283 deletions(-)
> 



From robh at kernel.org  Wed Mar  5 09:05:12 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 5 Mar 2025 11:05:12 -0600
Subject: [PATCH v4 2/8] dt-bindings: dsp: fsl,dsp: Add resets property
In-Reply-To: <20250305100037.373782-3-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-3-daniel.baluta@nxp.com>
Message-ID: <174119431164.2143223.3829886855063677866.robh@kernel.org>


On Wed, 05 Mar 2025 12:00:30 +0200, Daniel Baluta wrote:
> Assert and deassert functionality of the DSP found on i.MX8MP is
> realized by combining control bits from two modules: Audio Block
> Control and Debug Access Port.
> 
> Audio block control bits are used to Run/Stall the DSP core
> while the DAP bits are used for software reset the core.
> 
> The original plan was to use fsl,dsp-ctrl property and to refer the
> audiomix bits via syscon interface. This proposal received NACK from
> community we shouldn't abuse the syscon interface [1].
> 
> So remove fsl,dsp-ctrl property for i.MX8MP and use reset control
> interface instead.
> 
> Example dts node only uses runstall control now, but softreset will
> be added in the future when we will convert the softreset functionality
> to use reset controller API.
> 
> [1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
>  .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 ++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Wed Mar  5 09:07:23 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 11:07:23 -0600
Subject: [PATCH v3 1/4] dt-bindings: interrupt-controller: Add support
 for Amlogic A4 and A5 SoCsy
In-Reply-To: <20250305-corral-unfair-a7f25abbfd64@spud>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>
 <20250305-corral-unfair-a7f25abbfd64@spud>
Message-ID: <20250305170723.GA2143418-robh@kernel.org>

On Wed, Mar 05, 2025 at 04:28:16PM +0000, Conor Dooley wrote:
> On Wed, Mar 05, 2025 at 06:02:56PM +0800, Xianwei Zhao via B4 Relay wrote:
> > From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> > 
> > Update dt-binding document for GPIO interrupt controller
> > of Amlogic A4 and A5 SoCs
> > 
> > Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> > ---
> >  .../amlogic,meson-gpio-intc.yaml                    | 21 +++++++++++++++++++--
> >  1 file changed, 19 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> > index a93744763787..3c5853c71efa 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> > @@ -35,6 +35,9 @@ properties:
> >                - amlogic,meson-sm1-gpio-intc
> >                - amlogic,meson-a1-gpio-intc
> >                - amlogic,meson-s4-gpio-intc
> > +              - amlogic,a4-gpio-intc
> > +              - amlogic,a4-gpio-ao-intc
> > +              - amlogic,a5-gpio-intc
> >                - amlogic,c3-gpio-intc
> >                - amlogic,t7-gpio-intc
> >            - const: amlogic,meson-gpio-intc
> > @@ -49,8 +52,6 @@ properties:
> >  
> >    amlogic,channel-interrupts:
> >      description: Array with the upstream hwirq numbers
> > -    minItems: 8
> > -    maxItems: 12
> 
> Please leave the widest constraints here, and let the more restricted
> ones in your if/else below.
> 
> >      $ref: /schemas/types.yaml#/definitions/uint32-array
> >  
> >  required:
> > @@ -60,6 +61,22 @@ required:
> >    - "#interrupt-cells"
> >    - amlogic,channel-interrupts
> >  
> > +if:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        const: amlogic,a4-gpio-ao-intc
> > +then:
> > +  properties:
> > +    amlogic,channel-interrupts:
> > +      minItems: 2
> > +      maxItems: 12

And then you don't need this clause as 2-12 is the full range.

> > +else:
> > +  properties:
> > +    amlogic,channel-interrupts:
> > +      minItems: 8
> > +      maxItems: 12

And 12 is already the max, so you only need 'minItems: 8'.

> > +
> >  additionalProperties: false
> >  
> >  examples:
> > 
> > -- 
> > 2.37.1
> > 
> > 




From cristian.marussi at arm.com  Wed Mar  5 09:10:16 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Wed, 5 Mar 2025 17:10:16 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8g8vhS9rqQ_ez48@google.com>
References: <Z8g8vhS9rqQ_ez48@google.com>
Message-ID: <Z8iFeEWq16pNQdMa@pluto>

On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> Dear SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message
> Protocol drivers maintainers,
> 
> I flashed a v6.13-rc3 kernel onto a Rock5B board and noticed the
> following output in my terminal:
> 
> [  687.694465] kmemleak: 4 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
> 
> It seems that there is a memory leak for devices created with
> scmi_device_create.
> 
`
Hi Alice,

thanks for this report.

> This was with a kernel running v6.13-rc3, but as far as I can tell, no
> relevant changes have landed since v6.13-rc3. My tree *does* include
> commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> not happening consistently.
> 
> See below for the full kmemleak report.
> 
> Alice
> 
> $ sudo cat /sys/kernel/debug/kmemleak
> unreferenced object 0xffffff8106c86000 (size 2048):
>   comm "swapper/0", pid 1, jiffies 4294893094
>   hex dump (first 32 bytes):
>     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
>     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
>   backtrace (crc feae9680):
>     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
>     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
>     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
>     [<000000008714917b>] scmi_device_create+0x40/0x194
>     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
>     [<00000000970bad38>] scmi_probe+0x584/0xa78
>     [<000000002600d2fd>] platform_probe+0xbc/0xf0
>     [<00000000f6f556b4>] really_probe+0x1b8/0x520
>     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
>     [<00000000d613b754>] driver_probe_device+0x6c/0x208
>     [<00000000187a9170>] __driver_attach+0x168/0x328
>     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
>     [<00000000984a3176>] driver_attach+0x34/0x44
>     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
>     [<00000000747fce19>] driver_register+0xc0/0x1a0
>     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> unreferenced object 0xffffff8103bc01c0 (size 32):

I could not reproduce on my setup, even though I run a system with
all the existent SCMI protocols (and related drivers) enabled (and
so a lot of device creations) and a downstream test driver that causes
even more SCMI devices to be created/destroyed at load/unload.

Coming down the path from scmi_chan_setup(), it seems something around
transport devices creation, but it is not obvious to me where the leak
could hide....

...any particular setup on your side ? ...using LKMs, loading/unloading,
any usage pattern that could help me reproduce ?

Thanks,
Cristian


From namhyung at kernel.org  Wed Mar  5 09:14:38 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Wed, 05 Mar 2025 09:14:38 -0800
Subject: [PATCH v4 00/12] perf script: Refactor branch flags for Arm
 SPE
In-Reply-To: <20250304111240.3378214-1-leo.yan@arm.com>
References: <20250304111240.3378214-1-leo.yan@arm.com>
Message-ID: <174119487820.3243158.8048766791168980891.b4-ty@kernel.org>

On Tue, 04 Mar 2025 11:12:28 +0000, Leo Yan wrote:
> This patch series refactors branch flags for support Arm SPE.  The patch
> set is divided into two parts, the first part is for refactoring common
> code and the second part is for enabling Arm SPE.
> 
> For refactoring branch flags, the sample flaghs are classified as branch
> types and events.  A program branch type can be conditional branch,
> function call, return or expection taken.  A branch event happens when
> taking a branch.  This series combines branch types and the associated
> events to present a sample flag.
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From robh at kernel.org  Wed Mar  5 09:17:24 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 11:17:24 -0600
Subject: [PATCH 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
 <20250305140009.2485859-2-amadeus@jmu.edu.cn>
 <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>
Message-ID: <20250305171724.GA2149138-robh@kernel.org>

On Wed, Mar 05, 2025 at 04:41:23PM +0100, Krzysztof Kozlowski wrote:
> On 05/03/2025 15:00, Chukun Pan wrote:
> > Copy QoS nodes and add rk3528 compatible from bsp kernel,
> 
> No, don't copy stuff from BSP kernel. It results in terrible DTS.
> 
> > these can be used for power-domain.
> > 
> > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
> >  1 file changed, 160 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > index 5b334690356a..794f35654975 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > @@ -122,6 +122,166 @@ gic: interrupt-controller at fed01000 {
> >  			#interrupt-cells = <3>;
> >  		};
> >  
> > +		qos_crypto_a: qos at ff200000 {
> > +			compatible = "rockchip,rk3528-qos", "syscon";
> > +			reg = <0x0 0xff200000 0x0 0x20>;
> > +		};
> > +
> > +		qos_crypto_p: qos at ff200080 {
> > +			compatible = "rockchip,rk3528-qos", "syscon";
> > +			reg = <0x0 0xff200080 0x0 0x20>;
> > +		};
> 
> 
> Did you just define syscon per few registers? Third case last weeks...
> so no, define what is your device here. 8 registers is not a device usually.

Well, it is just a new compatible on top of existing 'qos' compatibles.
And in a quick scan I didn't see other things adjacent. 


From angelogioacchino.delregno at collabora.com  Wed Mar  5 09:18:41 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 18:18:41 +0100
Subject: [PATCH v2 3/3] ASoC: mediatek: mt8188-mt6359: Add accdet headset
 jack detect support
In-Reply-To: <20250304-mt8188-accdet-v2-3-27f496c4aede@collabora.com>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
 <20250304-mt8188-accdet-v2-3-27f496c4aede@collabora.com>
Message-ID: <59d0d382-1d15-46c4-b9e4-b66c32c188d3@collabora.com>

Il 04/03/25 22:35, N?colas F. R. A. Prado ha scritto:
> Enable headset jack detection for MT8188 platforms that use the MT6359
> ACCDET block for it, indicated by the mediatek,accdet property in DT.
> For those platforms, register a jack and initialize the ACCDET block to
> report jack events through it.
> 
> Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
> Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

We chatted about the issue that I raised before with mt8188_headset_jack_pins[],
it's fine to have it for now, as whatever we do with that would still duplicate
things and there's no way around that for now.

The sound card driver should get a bigger cleanup anyway, and it's not really
possible even because otherwise we'd break UCM2 confs, so it is what it is.

> ---
>   sound/soc/mediatek/Kconfig                |  1 +
>   sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
>   2 files changed, 44 insertions(+)
> 
> diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
> index 3033e2d3fe16840631a465dd967da77f7a6ff43c..64155ea7965a1cc50593fef442ce90761836f328 100644
> --- a/sound/soc/mediatek/Kconfig
> +++ b/sound/soc/mediatek/Kconfig
> @@ -237,6 +237,7 @@ config SND_SOC_MT8188_MT6359
>   	select SND_SOC_NAU8825
>   	select SND_SOC_RT5682S
>   	select SND_SOC_ES8326
> +	select SND_SOC_MT6359_ACCDET

The only remaining complaint that I have is that this driver shouldn't really
add a select SND_SOC_MT6359_ACCDET.

Instead, the mt6359-accdet.h header should be modified to stub-ify the accdet
driver functions in the case in which it's not built in, or not available as a
module anyway.

This is because the accdet driver is not *mandatory* for this driver to work,
and being it an optional peripheral, adding a dependency doesn't really make
a lot of sense as it'd only force in bloat when not wanted.

So...

Get to that mt6359-accdet.h header and:

#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET)

function signatures

#else

static .... { return -EINVAL; (or whatever else) }

#endif

That said, for the future v3 of this commit, after removing the select
SND_SOC_MT6359_ACCDET (and granted that the proposed header fix is in place),
you can add my

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Cheers,
Angelo




From daniel.lezcano at linaro.org  Wed Mar  5 09:23:06 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Wed, 5 Mar 2025 18:23:06 +0100
Subject: [PATCH] clocksource: stm32-lptimer: use wakeup capable instead of
 init wakeup
In-Reply-To: <20250305125146.1858978-1-fabrice.gasnier@foss.st.com>
References: <20250305125146.1858978-1-fabrice.gasnier@foss.st.com>
Message-ID: <a7489f16-ca31-4530-8ef1-33079b3c99a9@linaro.org>

On 05/03/2025 13:51, Fabrice Gasnier wrote:
> From: Alexandre Torgue <alexandre.torgue at foss.st.com>
> 
> "wakeup-source" property describes a device which has wakeup capability
> but should not force this device as a wakeup source.

Is that a fix to be carried on ?

> Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
>   drivers/clocksource/timer-stm32-lp.c | 4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
> index 96d975adf7a4..f08baa6720f8 100644
> --- a/drivers/clocksource/timer-stm32-lp.c
> +++ b/drivers/clocksource/timer-stm32-lp.c
> @@ -186,9 +186,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
>   	}
>   
>   	if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
> -		ret = device_init_wakeup(&pdev->dev, true);
> -		if (ret)
> -			goto out_clk_disable;
> +		device_set_wakeup_capable(&pdev->dev, true);
>   
>   		ret = dev_pm_set_wake_irq(&pdev->dev, irq);
>   		if (ret)


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From broonie at kernel.org  Wed Mar  5 09:23:29 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 5 Mar 2025 17:23:29 +0000
Subject: [PATCH v2 3/3] ASoC: mediatek: mt8188-mt6359: Add accdet headset
 jack detect support
In-Reply-To: <59d0d382-1d15-46c4-b9e4-b66c32c188d3@collabora.com>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
 <20250304-mt8188-accdet-v2-3-27f496c4aede@collabora.com>
 <59d0d382-1d15-46c4-b9e4-b66c32c188d3@collabora.com>
Message-ID: <7661b71a-9d5a-46c4-9639-0fba1b118b52@sirena.org.uk>

On Wed, Mar 05, 2025 at 06:18:41PM +0100, AngeloGioacchino Del Regno wrote:

> Get to that mt6359-accdet.h header and:

> #if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET)

> function signatures

> #else

> static .... { return -EINVAL; (or whatever else) }

> #endif
> 

It should probably be return 0 for the registration/unregistration
functions so the caller doesn't fail if it checks the return code when
the accessory detection is configured out.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/29e53e1d/attachment.sig>

From cristian.marussi at arm.com  Wed Mar  5 09:29:54 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Wed, 5 Mar 2025 17:29:54 +0000
Subject: [PATCH NOT APPLY v2 4/4] clk: scmi: Support spread spectrum
In-Reply-To: <20250303041125.GC13236@nxa18884-linux>
References: <20250205-clk-ssc-v2-0-fa73083caa92@nxp.com>
 <20250205-clk-ssc-v2-4-fa73083caa92@nxp.com>
 <Z6SqeNsAqbZM8nr1@pluto>
 <20250303041125.GC13236@nxa18884-linux>
Message-ID: <Z8iKErarE0lHWxEy@pluto>

On Mon, Mar 03, 2025 at 12:11:25PM +0800, Peng Fan wrote:
> Hi Cristian,
> 
> On Thu, Feb 06, 2025 at 12:26:32PM +0000, Cristian Marussi wrote:
> >On Wed, Feb 05, 2025 at 05:49:54PM +0800, Peng Fan (OSS) wrote:
> >> From: Peng Fan <peng.fan at nxp.com>
> >> 
> >> Support Spread Spectrum with adding scmi_clk_set_spread_spectrum
> >> 
> >
> >Hi,
> >
> >I forwarded ATG with our latest exchange on the possibility of using a
> >standard OEM type instead of Vendor one if it is general enough....
> 
> Do you have any update?
> 

Yes I think you can go on with your original plan of using vendor OEM
types: as of now we are not gonna standardize a new commmon SCMI type
for Clock-SS, given there is really just one SCMI user of such clock
features...maybe in the future if more users shows up...

Thanks,
Cristian


From ryan.wanner at microchip.com  Wed Mar  5 09:39:06 2025
From: ryan.wanner at microchip.com (Ryan Wanner)
Date: Wed, 5 Mar 2025 10:39:06 -0700
Subject: [PATCH v3 00/21] Enable Power Modes Support for SAMA7D65 SoC
In-Reply-To: <2a18e305-090c-41fe-9b27-97ebe93fd4e4@tuxon.dev>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <2a18e305-090c-41fe-9b27-97ebe93fd4e4@tuxon.dev>
Message-ID: <ebb161f2-632b-4d10-8c5c-4187a06a06c8@microchip.com>

On 3/3/25 01:40, Claudiu Beznea wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27.02.2025 17:51, Ryan.Wanner at microchip.com wrote:
>> Ryan Wanner (20):
>>   ARM: at91: Add PM support to sama7d65
>>   ARM: at91: pm: add DT compatible support for sama7d65
>>   ARM: at91: PM: Add Backup mode for SAMA7D65
>>   ARM: at91: pm: Enable ULP0/ULP1 for SAMA7D65
> 
> Applied to at91-soc with some adjustments, please check!
Checked! This is correct.
> 
>>   ARM: dts: microchip: sama7d65: Add Reset Controller to sama7d65 SoC
>>   ARM: dts: microchip: sama7d65: Add Shutdown controller support
>>   ARM: dts: microchip: sama7d65: Add RTC support for sama7d65
>>   ARM: dts: microchip: sama7d65: Add SFRBU support to sama7d65
>>   ARM: dts: microchip: sama7d65: Enable shutdown controller
> 
> Applied to at91-dt with some adjustments, please check!
Same here

Thank you!
> 
> Thank you!



From helgaas at kernel.org  Wed Mar  5 09:38:26 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 5 Mar 2025 11:38:26 -0600
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250304171154.njoygsvfd567pb66@thinkpad>
Message-ID: <20250305173826.GA303920@bhelgaas>

On Tue, Mar 04, 2025 at 10:41:54PM +0530, Manivannan Sadhasivam wrote:
> On Wed, Mar 05, 2025 at 12:46:38AM +0900, Krzysztof Wilczy?ski wrote:
> > > On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> > > > [...]
> > > > > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > > > > +{
> > > > > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > > > > +   struct device *dev = pci->dev;
> > > > > > +   struct debugfs_info *debugfs;
> > > > > > +   struct dentry *dir;
> > > > > > +   int ret;
> > > > > > +
> > > > > > +   /* Create main directory for each platform driver */
> > > > > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > > > > +   dir = debugfs_create_dir(dirname, NULL);
> > > > > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > > > > +   if (!debugfs)
> > > > > > +           return -ENOMEM;
> > > > > > +
> > > > > > +   debugfs->debug_dir = dir;
> > > > > > +   pci->debugfs = debugfs;
> > > > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > > > +   if (ret)
> > > > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > > > >
> > > > > What will happen if ret != 0? still return 0?
> > > 
> > > And that is exactly what happens on Gray Hawk Single with R-Car
> > > V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> > > dwc_pcie_rasdes_debugfs_init() to return -ENODEV.
> > > 
> > > Debugfs issues should never be propagated upstream!
> ...

> > > So while applying, you changed this like:
> > > 
> > >             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > >     -       if (ret)
> > >     -               dev_dbg(dev, "RASDES debugfs init failed\n");
> > >     +       if (ret) {
> > >     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
> > >     +               return ret;
> > >     +       }
> > > 
> > >             return 0;
> > > 
> > > Hence this is now a fatal error, causing the probe to fail.

> Even though debugfs_init() failure is not supposed to fail the probe(),
> dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> failure would be canolically correct IMO.

I'm not sure about this.  What's the requirement to propagate
devm_kzalloc() failures?  I think devres will free any allocs that
were successful regardless.

IIUC, we resolved the Gray Hawk Single issue by changing
dwc_pcie_rasdes_debugfs_init() to return success without doing
anything when there's no RAS DES Capability.

But dwc_pcie_debugfs_init() can still return failure, and that still
causes dw_pcie_ep_init_registers() to fail, which breaks the "don't
propagate debugfs issues upstream" rule:

  int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
  {
          ...
          ret = dwc_pcie_debugfs_init(pci);
          if (ret)
                  goto err_remove_edma;

          return 0;

  err_remove_edma:
          dw_pcie_edma_remove(pci);

          return ret;
  }

We can say that kzalloc() failure should "never" happen, and therefore
it's OK to fail the driver probe if it happens, but that doesn't seem
like a strong argument for breaking the "don't propagate debugfs
issues" rule.  And someday there may be other kinds of failures from
dwc_pcie_debugfs_init().

Bjorn


From angelogioacchino.delregno at collabora.com  Wed Mar  5 09:40:31 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 18:40:31 +0100
Subject: [PATCH v4 4/8] soc: mediatek: mtk-cmdq: Add pa_base parsing for
 unsupported subsys ID hardware
In-Reply-To: <c27653233ed2ee2ee6eb0d40ad2167721a2b1476.camel@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-5-jason-jh.lin@mediatek.com>
 <581fc075-25d8-4104-a4ee-8c97e1a017e6@collabora.com>
 <03c523e66fd56442f49c38456476cf18be59e8fb.camel@mediatek.com>
 <8203317e-7f99-4ea5-bda0-fcd791602a9f@collabora.com>
 <c27653233ed2ee2ee6eb0d40ad2167721a2b1476.camel@mediatek.com>
Message-ID: <0d929810-1189-41ce-8f8a-3b7230c3b2a9@collabora.com>

Il 05/03/25 16:58, Jason-JH Lin (???) ha scritto:
> On Wed, 2025-03-05 at 12:03 +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 05/03/25 10:46, Jason-JH Lin (???) ha scritto:
>>> On Tue, 2025-03-04 at 10:35 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
>>>>> When GCE executes instructions, the corresponding hardware
>>>>> register
>>>>> can be found through the subsys ID. For hardware that does not
>>>>> support
>>>>> subsys ID, its subsys ID will be set to invalid value and its
>>>>> physical
>>>>> address needs to be used to generate GCE instructions.
>>>>>
>>>>> This commit adds a pa_base parsing flow to the cmdq_client_reg
>>>>> structure
>>>>> for these unsupported subsys ID hardware.
>>>>>
>>>>
>>>> Does this work only for the MMINFRA located GCEs, or does this
>>>> work
>>>> also for
>>>> the legacy ones in MT8173/83/88/92/95 // MT6795/6893/etc?
>>>>
>>>> In order to actually review and decide, I do need to know :-)
>>>>
>>>
>>> Yes, it's for the SoCs without subsys ID, it's not related to the
>>> MMINFRA.
>>>
>>> This can also work on MT8173/83/92/95 // MT6795/6893/etc.
>>> You can remove the `mediatek,gce-client-reg` properties in their
>>> dtsi
>>> and cherry-pick this series to verify it. :-)
>>>
>>
>> This is curious - and that brings more questions to the table (for
>> curiosity
>> more than anything else at this point).
>>
>> Since this is a way to make use of the CMDQ for address ranges that
>> are not tied
>> to any subsys id (hence no gce-client-reg and just physical address
>> parsing for
>> generating instructions), do you know what are the performance
>> implications of
>> using this, instead of subsys IDs on SoCs that do support them?
>>
> 
> The main advantage of using subsys ID is to reduce the number of
> instruction.
> Without subsy ID, you will need one more `ASSIGN` instruction to assign
> the high bytes of the physical address.
> 
> E,g. In mt8195-gce.h: #define SUBSYS_1c00XXXX 3
> 
> If you want GCE to write the value 0x0000000f to 0x1c00_002c.
> 
> With subsys ID, you can use only one instruction to achieve it:
> 1. WRITE value: 0x000000f to subsys: 0x3 + offset: 0x0002c
> - OP code: WRTIE = 0x90
> - subsys ID: 0x1c00XXXX = 0x03
> - offset: 0x002c
> - value: 0x0000000f
> 
> Without subsys ID, you will need 2 instructions to achieve it:
> 1. ASSIGN address high bytes: 0x1c00 to GCE temp register: SPR0
> - OP code: LOGIC = 0xa0
> - arg_type: register, value, value = (0x8)
> - sub OP: ASSIGN = 0x0
> - register index to store the assign value: SPR0 = 0x0
> - value to assign: 0x1c00
> 2. WRITE value: 0x0000000f to temp register: SPR0 + offset:0x002c
> - OP code: WRITE = 0x90
> - sub OP(temp register index): SPR0 = 0x0
> - offset for temp register: 0x002c
> - value: 0x0000000f
> 
>> Being clear: if we were to migrate a SoC like MT8195 to using this
>> globally
>> instead of using subsys ids, would the performance be degraded?
>> And if yes, do you know by how much?
>>
> 
> E,g. If the inst number with subsys ID is N.
> 1. If CMDQ is implement like this, then inst number will be (N * 2):
> assign SPR0 = 0x1c00
> write A to SPR0 + offset: 0x2c
> assign SPR0 = 0x1c00
> write B to SPR0 + offset: 0x3c
> assign SPR0 = 0x1c00
> write C to SPR0 + offset: 0x4c
> ...
> 
> 2. If CMDQ is implement like this, the inst number will be (N + 1 * n):
> assign SPR0 = 0x1c00
> write A to SPR0 + offset: 0x2c
> write B to SPR0 + offset: 0x3c
> write C to SPR0 + offset: 0x4c
> ...
> 
> When the same cmd buffer changes the base address for n times:
> assign SPR0 = 0x1c00
> write A to SPR0 + offset: 0x2c
> assign SPR0 = 0x1c01
> write B to SPR0 + offset: 0x2c
> assign SPR0 = 0x1c02
> write C to SPR0 + offset: 0x2c
> assign SPR0 = 0x1c00
> write D to SPR0 + offset: 0x3c
> ...
> 
> So you can imagine the performance will increase, but maybe not too
> much if we use it in the right way...
> Except the old SoC that didn't support SPR and CPR. The reason will be
> addressed in the next paragraph.
> 
>> What you're proposing almost looks like being too good to be true -
>> and makes
>> me wonder, at this point, why the subsys id was used in the first
>> place :-)
>>
> 
> That's because of the old GCE version in the old SoC only support GPR,
> it didn't support SPR and CPR.
> 
> GPR:
> All 32 GCE threads share the same GPR0~GPR15, GPR will be affected by
> other GCE threads if they use it at the same time.
> 
> SPR:
> Each GCE thread has 4 SPR, SPR won't be affected by another GCE thread.
> 
> CPR:
> All 32 GCE threads share the same CPR, there are over 1000 CPR can be
> used. It need to be managed properly to avoid the resource conflicting.
> 
> Due to the GPR resource restriction in the old GCE version, the usage
> of subsys ID can avoid GPR conflicting issues when multiple GCE threads
> are using GPR to physical assign high bytes all the time.
> 
> 
> I have simplified some complicate instruction rules, so the description
> above may not be 100% matched to the CMDQ helper driver code.
> But I think the main concept is correct.
> Hope these explanation can help well :-)
> 

Jason, that's simply wonderful. Thanks a lot for this precious description.

Yes, this has clarified even more than I was asking for, and besides,
yeah I know that there are some rules to follow, some of which I know,
some of which I imagine - and describing all of that would need lots
and lots of text - again, I know, and no worries about that! :-D

Thanks again!
Angelo

> Regards,
> Jason-JH Lin
> 
>> Cheers!
>> Angelo
>>
>>> Regards,
>>> Jason-JH Lin
>>>
>>>> Thanks,
>>>> Angelo
>>>>
>>>>
>>>
>>
>>
>>
> 



From nicolinc at nvidia.com  Wed Mar  5 09:44:30 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 09:44:30 -0800
Subject: [PATCH v1 1/4] iommu/arm-smmu-v3: Pass in vmid to
 arm_smmu_make_s2_domain_ste()
In-Reply-To: <a95b39a55c324907a7001d3a2cdf076b@huawei.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <214b10db02f1046efdc70e2c4803111357f60070.1741150594.git.nicolinc@nvidia.com>
 <a95b39a55c324907a7001d3a2cdf076b@huawei.com>
Message-ID: <Z8iNfnZ9N5Lczxmq@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 08:50:17AM +0000, Shameerali Kolothum Thodi wrote:
> > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> > b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> > index bd9d7c85576a..e08c4ede4b2d 100644
> > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> > @@ -887,7 +887,7 @@ struct arm_smmu_entry_writer_ops {
> >  void arm_smmu_make_abort_ste(struct arm_smmu_ste *target);
> >  void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
> >  				 struct arm_smmu_master *master,
> > -				 struct arm_smmu_domain *smmu_domain,
> > +				 struct arm_smmu_domain *smmu_domain,
> > u16 vmid,
> >  				 bool ats_enabled);
> 
> Now that vmid is an input, do we need some kind of validation here as
> at least vmid = 0 is reserved I guess for bypass STEs.

Perhaps it should do a WARN_ON_ONCE(!vmid), as it doesn't make
sense for a caller to make an S2-bypass STE with this function.

Thanks
Nicolin


From rmk+kernel at armlinux.org.uk  Wed Mar  5 10:00:39 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 05 Mar 2025 18:00:39 +0000
Subject: [PATCH net-next 1/2] net: phylink: add functions to block/unblock rx
 clock stop
In-Reply-To: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>
References: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>
Message-ID: <E1tpt2t-005UNB-MC@rmk-PC.armlinux.org.uk>

Some MACs require the PHY receive clock to be running to complete setup
actions. This may fail if the PHY has negotiated EEE, the MAC supports
receive clock stop, and the link has entered LPI state. Provide a pair
of APIs that MAC drivers can use to temporarily block the PHY disabling
the receive clock.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 50 +++++++++++++++++++++++++++++++++++++++
 include/linux/phylink.h   |  3 +++
 2 files changed, 53 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3b186ab3854..8f93b597d019 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -88,6 +88,7 @@ struct phylink {
 	bool mac_enable_tx_lpi;
 	bool mac_tx_clk_stop;
 	u32 mac_tx_lpi_timer;
+	u8 mac_rx_clk_stop_blocked;
 
 	struct sfp_bus *sfp_bus;
 	bool sfp_may_have_phy;
@@ -2592,6 +2593,55 @@ void phylink_stop(struct phylink *pl)
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
+
+void phylink_rx_clk_stop_block(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Disable PHY receive clock stop if this is the first time this
+	 * function has been called and clock-stop was previously enabled.
+	 */
+	if (pl->mac_rx_clk_stop_blocked++ == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev)
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, false);
+}
+
+/**
+ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * All calls to phylink_rx_clk_stop_block() must be balanced with a
+ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
+ * clock stop ability.
+ */
+void phylink_rx_clk_stop_unblock(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == 0) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Re-enable PHY receive clock stop if the number of unblocks matches
+	 * the number of calls to the block function above.
+	 */
+	if (--pl->mac_rx_clk_stop_blocked == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, true);
+}
+
 /**
  * phylink_suspend() - handle a network device suspend event
  * @pl: a pointer to a &struct phylink returned from phylink_create()
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 08df65f6867a..249c437d6b7b 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -698,6 +698,9 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
 void phylink_start(struct phylink *);
 void phylink_stop(struct phylink *);
 
+void phylink_rx_clk_stop_block(struct phylink *);
+void phylink_rx_clk_stop_unblock(struct phylink *);
+
 void phylink_suspend(struct phylink *pl, bool mac_wol);
 void phylink_resume(struct phylink *pl);
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar  5 10:00:44 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 05 Mar 2025 18:00:44 +0000
Subject: [PATCH net-next 2/2] net: stmmac: block PHY rx clock-stop over reset
In-Reply-To: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>
References: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>
Message-ID: <E1tpt2y-005UNH-QS@rmk-PC.armlinux.org.uk>

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6924df893e42..037039a9a33b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3096,7 +3096,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
 		priv->plat->dma_cfg->atds = 1;
 
+	/* Note that the PHY clock must be running for reset to complete. */
+	phylink_rx_clk_stop_block(priv->phylink);
 	ret = stmmac_reset(priv, priv->ioaddr);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 	if (ret) {
 		netdev_err(priv->dev, "Failed to reset the dma\n");
 		return ret;
-- 
2.30.2



From jernej.skrabec at gmail.com  Wed Mar  5 10:06:36 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:06:36 +0100
Subject: [PATCH v3 7/8] pinctrl: sunxi: Add support for the Allwinner A523
In-Reply-To: <20250227231447.20161-8-andre.przywara@arm.com>
References: <20250227231447.20161-1-andre.przywara@arm.com>
 <20250227231447.20161-8-andre.przywara@arm.com>
Message-ID: <1819482.VLH7GnMWUR@jernej-laptop>

Dne petek, 28. februar 2025 ob 00:14:46 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Allwinner A523 contains pins in 10 out of the 11 possible pin banks;
> it just skips port A.
> Use the newly introduced DT based pinctrl driver to describe just the
> generic pinctrl properties, so advertise the number of pins per bank
> and the interrupt capabilities. The actual function/mux assignment is
> taken from the devicetree.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From nicolinc at nvidia.com  Wed Mar  5 09:49:37 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 09:49:37 -0800
Subject: [PATCH v1 4/4] iommu/arm-smmu-v3-iommufd: Allow a shared
 s2_parent to allocate vSMMU
In-Reply-To: <20250305165743.GA133783@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <564eda8dee4bbf4c6e1d1dd9ed6bd40cc1a2df26.1741150594.git.nicolinc@nvidia.com>
 <1b51a7f7bfc0419b8941cf7ee0601b70@huawei.com>
 <20250305165743.GA133783@nvidia.com>
Message-ID: <Z8iOsTIa37XzNcW1@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 12:57:43PM -0400, Jason Gunthorpe wrote:
> On Wed, Mar 05, 2025 at 09:01:40AM +0000, Shameerali Kolothum Thodi wrote:
> 
> > >  	if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
> > >  		return ERR_PTR(-EOPNOTSUPP);
> > > 
> > > -	if (s2_parent->smmu != master->smmu)
> > > -		return ERR_PTR(-EINVAL);
> > > -
> > 
> > Not sure we can just relax this like this. What if the two physical SMMUs are different in
> > functionality/features? Do we need some kind of sanity check here?
> 
> Yes, a function to check if a domain's iopgtbl config is compatible
> with the instance is required.

Yea. Will rework.

Thanks!
Nicolin


From jernej.skrabec at gmail.com  Wed Mar  5 09:50:34 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 18:50:34 +0100
Subject: [PATCH v3 4/8] pinctrl: sunxi: support moved power configuration
 registers
In-Reply-To: <20250227231447.20161-5-andre.przywara@arm.com>
References: <20250227231447.20161-1-andre.przywara@arm.com>
 <20250227231447.20161-5-andre.przywara@arm.com>
Message-ID: <6028746.MhkbZ0Pkbq@jernej-laptop>

Dne petek, 28. februar 2025 ob 00:14:43 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Allwinner pincontroller IP features some registers to control the
> withstand voltage of each pin group. So far those registers were always
> located at the same offset, but the A523 SoC has moved them (probably to
> accommodate all eleven pin banks).
> 
> Add a flag to note this feature, and use that to program the registers
> either at offset 0x340 or 0x380. So far no pincontroller driver uses
> this flag, but we need it for the upcoming A523 support.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 15 +++++++++++----
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h |  7 +++++--
>  2 files changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 83a031ceb29f2..fc12e6f807e4d 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -736,9 +736,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
>  		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
>  
>  		raw_spin_lock_irqsave(&pctl->lock, flags);
> -		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> +		reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
>  		reg &= ~BIT(bank);
> -		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> +		writel(reg | val, pctl->membase + pctl->pow_mod_sel_offset);

These two are missing "+ PIO_POW_MOD_CTL_OFS" right?

>  		raw_spin_unlock_irqrestore(&pctl->lock, flags);
>  
>  		fallthrough;
> @@ -746,9 +746,12 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
>  		val = uV <= 1800000 ? 1 : 0;
>  
>  		raw_spin_lock_irqsave(&pctl->lock, flags);
> -		reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
> +		reg = readl(pctl->membase + pctl->pow_mod_sel_offset +
> +			    PIO_POW_MOD_CTL_OFS);
>  		reg &= ~(1 << bank);
> -		writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
> +		writel(reg | val << bank,
> +		       pctl->membase + pctl->pow_mod_sel_offset +
> +		       PIO_POW_MOD_CTL_OFS);

And these two have "+ PIO_POW_MOD_CTL_OFS" too much, right?

Best regards,
Jernej

>  		raw_spin_unlock_irqrestore(&pctl->lock, flags);
>  		return 0;
>  	default:
> @@ -1520,6 +1523,10 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
>  		pctl->pull_regs_offset = PULL_REGS_OFFSET;
>  		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
>  	}
> +	if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
> +		pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
> +	else
> +		pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
>  
>  	pctl->irq_array = devm_kcalloc(&pdev->dev,
>  				       IRQ_PER_BANK * pctl->desc->irq_banks,
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index 6cf721876d89d..742fc795c7664 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -87,9 +87,11 @@
>  #define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
>  #define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)
>  #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
> +#define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
>  
> -#define PIO_POW_MOD_SEL_REG	0x340
> -#define PIO_POW_MOD_CTL_REG	0x344
> +#define PIO_POW_MOD_SEL_REG		0x340
> +#define PIO_11B_POW_MOD_SEL_REG		0x380
> +#define PIO_POW_MOD_CTL_OFS		0x004
>  
>  #define PIO_BANK_K_OFFSET		0x500
>  
> @@ -173,6 +175,7 @@ struct sunxi_pinctrl {
>  	u32				bank_mem_size;
>  	u32				pull_regs_offset;
>  	u32				dlevel_field_width;
> +	u32				pow_mod_sel_offset;
>  };
>  
>  #define SUNXI_PIN(_pin, ...)					\
> 






From heiko at sntech.de  Wed Mar  5 09:51:43 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Wed, 05 Mar 2025 18:51:43 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250305171724.GA2149138-robh@kernel.org>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
 <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>
 <20250305171724.GA2149138-robh@kernel.org>
Message-ID: <3543865.CbtlEUcBR6@diego>

Am Mittwoch, 5. M?rz 2025, 18:17:24 MEZ schrieb Rob Herring:
> On Wed, Mar 05, 2025 at 04:41:23PM +0100, Krzysztof Kozlowski wrote:
> > On 05/03/2025 15:00, Chukun Pan wrote:
> > > Copy QoS nodes and add rk3528 compatible from bsp kernel,
> > 
> > No, don't copy stuff from BSP kernel. It results in terrible DTS.
> > 
> > > these can be used for power-domain.
> > > 
> > > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> > > ---
> > >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
> > >  1 file changed, 160 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > > index 5b334690356a..794f35654975 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > > @@ -122,6 +122,166 @@ gic: interrupt-controller at fed01000 {
> > >  			#interrupt-cells = <3>;
> > >  		};
> > >  
> > > +		qos_crypto_a: qos at ff200000 {
> > > +			compatible = "rockchip,rk3528-qos", "syscon";
> > > +			reg = <0x0 0xff200000 0x0 0x20>;
> > > +		};
> > > +
> > > +		qos_crypto_p: qos at ff200080 {
> > > +			compatible = "rockchip,rk3528-qos", "syscon";
> > > +			reg = <0x0 0xff200080 0x0 0x20>;
> > > +		};
> > 
> > 
> > Did you just define syscon per few registers? Third case last weeks...
> > so no, define what is your device here. 8 registers is not a device usually.
> 
> Well, it is just a new compatible on top of existing 'qos' compatibles.
> And in a quick scan I didn't see other things adjacent. 

Also, those "Quality-of-Service" register-sets are generally identically and
configure the interconnect-voodoo for the individual devices they're
attached to.

And while we are not "tuning" stuff at the moment, the register contents
need to be saved and restored when the device's power-domain is
turned off or on.




From acme at kernel.org  Wed Mar  5 09:52:56 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Wed, 5 Mar 2025 14:52:56 -0300
Subject: [PATCH v4 01/11] perf dso: Move libunwind dso_data variables
 into ifdef
In-Reply-To: <20250304050305.901167-2-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
 <20250304050305.901167-2-irogers@google.com>
Message-ID: <Z8iPeEbldTUqotsQ@x1>

On Mon, Mar 03, 2025 at 09:02:55PM -0800, Ian Rogers wrote:
> The variables elf_base_addr, debug_frame_offset, eh_frame_hdr_addr and
> eh_frame_hdr_offset are only accessed in unwind-libunwind-local.c
> which is conditionally built on having libunwind support. Make the
> variables conditional on libunwind support too.

Reviewed-by: Arnaldo Carvalho de Melo <acme at redhat.com>
 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/util/dso.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index bb8e8f444054..dfd763a0bd9d 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -154,10 +154,12 @@ struct dso_data {
>  	int		 status;
>  	u32		 status_seen;
>  	u64		 file_size;
> +#ifdef HAVE_LIBUNWIND_SUPPORT
>  	u64		 elf_base_addr;
>  	u64		 debug_frame_offset;
>  	u64		 eh_frame_hdr_addr;
>  	u64		 eh_frame_hdr_offset;
> +#endif
>  };
>  
>  struct dso_bpf_prog {
> -- 
> 2.48.1.711.g2feabab25a-goog


From acme at kernel.org  Wed Mar  5 09:54:46 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Wed, 5 Mar 2025 14:54:46 -0300
Subject: [PATCH v4 02/11] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250304050305.901167-3-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
 <20250304050305.901167-3-irogers@google.com>
Message-ID: <Z8iP5r3nVyCG8Iai@x1>

On Mon, Mar 03, 2025 at 09:02:56PM -0800, Ian Rogers wrote:
> There are many and non-obvious meanings to the dso_binary_type enum
> values. Add kernel-doc to speed interpretting their meanings.


Acked-by: Arnaldo Carvalho de Melo <acme at redhat.com>
 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/util/dso.h | 53 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index dfd763a0bd9d..f3ca2a5e7670 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -20,30 +20,83 @@ struct perf_env;
>  #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
>  #define DSO__NAME_KCORE		"[kernel.kcore]"
>  
> +/**
> + * enum dso_binary_type - The kind of DSO generally associated with a memory
> + *                        region (struct map).
> + */
>  enum dso_binary_type {
> +	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
>  	DSO_BINARY_TYPE__KALLSYMS = 0,
> +	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
>  	DSO_BINARY_TYPE__GUEST_KALLSYMS,
> +	/** @DSO_BINARY_TYPE__VMLINUX: Path to guest kernel /boot/vmlinux file. */
>  	DSO_BINARY_TYPE__VMLINUX,
> +	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to kernel /boot/vmlinux file. */
>  	DSO_BINARY_TYPE__GUEST_VMLINUX,
> +	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
>  	DSO_BINARY_TYPE__JAVA_JIT,
> +	/**
> +	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
> +	 * in the .gnu_debuglink ELF section of the dso.
> +	 */
>  	DSO_BINARY_TYPE__DEBUGLINK,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
> +	 * the buildid cache with an elf filename.
> +	 */
>  	DSO_BINARY_TYPE__BUILD_ID_CACHE,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
> +	 * located in the buildid cache with a debug filename.
> +	 */
>  	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
> +	 * with .debug suffix.
> +	 */
>  	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
>  	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
> +	 * file in /usr/lib/debug/lib rather than the expected
> +	 * /usr/lib/debug/usr/lib.
> +	 */
>  	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
> +	 * in /usr/lib/debug/.build-id/.
> +	 */
>  	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
> +	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
>  	DSO_BINARY_TYPE__GUEST_KMODULE,
> +	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
>  	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
> +	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
>  	DSO_BINARY_TYPE__KCORE,
> +	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
>  	DSO_BINARY_TYPE__GUEST_KCORE,
> +	/**
> +	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
> +	 * package debug info.
> +	 */
>  	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
>  	DSO_BINARY_TYPE__BPF_PROG_INFO,
> +	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
>  	DSO_BINARY_TYPE__BPF_IMAGE,
> +	/**
> +	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
> +	 * instructions or optimized kprobes or ftrace trampolines.
> +	 */
>  	DSO_BINARY_TYPE__OOL,
> +	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
>  	DSO_BINARY_TYPE__NOT_FOUND,
>  };
>  
> -- 
> 2.48.1.711.g2feabab25a-goog
> 


From rmk+kernel at armlinux.org.uk  Wed Mar  5 09:54:16 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 05 Mar 2025 17:54:16 +0000
Subject: [PATCH net-next] net: stmmac: avoid shadowing global buf_sz
Message-ID: <E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk>

stmmac_rx() declares a local variable named "buf_sz" but there is also
a global variable for a module parameter which is called the same. To
avoid confusion, rename the local variable.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 334d41b8fa70..cb5099caecd0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5475,10 +5475,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 	struct sk_buff *skb = NULL;
 	struct stmmac_xdp_buff ctx;
 	int xdp_status = 0;
-	int buf_sz;
+	int bufsz;
 
 	dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
-	buf_sz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+	bufsz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
 	limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
 
 	if (netif_msg_rx_status(priv)) {
@@ -5591,7 +5591,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 			net_prefetch(page_address(buf->page) +
 				     buf->page_offset);
 
-			xdp_init_buff(&ctx.xdp, buf_sz, &rx_q->xdp_rxq);
+			xdp_init_buff(&ctx.xdp, bufsz, &rx_q->xdp_rxq);
 			xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
 					 buf->page_offset, buf1_len, true);
 
-- 
2.30.2



From jgg at ziepe.ca  Wed Mar  5 09:55:57 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 13:55:57 -0400
Subject: [PATCH v2 2/4] iommu: Resolve ops in iommu_init_device()
In-Reply-To: <fa4b6cfc67a352488b7f4e0b736008307ce9ac2e.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <fa4b6cfc67a352488b7f4e0b736008307ce9ac2e.1740753261.git.robin.murphy@arm.com>
Message-ID: <20250305175557.GI5011@ziepe.ca>

On Fri, Feb 28, 2025 at 03:46:31PM +0000, Robin Murphy wrote:
> Since iommu_init_device() was factored out, it is in fact the only
> consumer of the ops which __iommu_probe_device() is resolving, so let it
> do that itself rather than passing them in. This also puts the ops
> lookup at a more logical point relative to the rest of the flow through
> __iommu_probe_device().
> 
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> 
> v2: New
> 
>  drivers/iommu/iommu.c | 30 ++++++++++++++++--------------
>  1 file changed, 16 insertions(+), 14 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

Jason


From rmk+kernel at armlinux.org.uk  Wed Mar  5 09:54:21 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 05 Mar 2025 17:54:21 +0000
Subject: [PATCH net-next] net: stmmac: mostly remove "buf_sz"
Message-ID: <E1tpswn-005U6I-TU@rmk-PC.armlinux.org.uk>

The "buf_sz" parameter is not used in the stmmac driver - there is one
place where the value of buf_sz is validated, and two places where it
is written. It is otherwise unused.

Remove these accesses. However, leave the module parameter in place as
removing it could cause module load to fail, breaking user setups.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index cb5099caecd0..037039a9a33b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -101,6 +101,7 @@ static int tc = TC_DEFAULT;
 module_param(tc, int, 0644);
 MODULE_PARM_DESC(tc, "DMA threshold control value");
 
+/* This is unused */
 #define	DEFAULT_BUFSIZE	1536
 static int buf_sz = DEFAULT_BUFSIZE;
 module_param(buf_sz, int, 0644);
@@ -218,8 +219,6 @@ static void stmmac_verify_args(void)
 {
 	if (unlikely(watchdog < 0))
 		watchdog = TX_TIMEO;
-	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
-		buf_sz = DEFAULT_BUFSIZE;
 	if (unlikely((pause < 0) || (pause > 0xffff)))
 		pause = PAUSE_TIME;
 
@@ -4018,7 +4017,6 @@ static int __stmmac_open(struct net_device *dev,
 		}
 	}
 
-	buf_sz = dma_conf->dma_buf_sz;
 	for (int i = 0; i < MTL_MAX_TX_QUEUES; i++)
 		if (priv->dma_conf.tx_queue[i].tbs & STMMAC_TBS_EN)
 			dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs;
@@ -7973,9 +7971,6 @@ static int __init stmmac_cmdline_opt(char *str)
 		} else if (!strncmp(opt, "phyaddr:", 8)) {
 			if (kstrtoint(opt + 8, 0, &phyaddr))
 				goto err;
-		} else if (!strncmp(opt, "buf_sz:", 7)) {
-			if (kstrtoint(opt + 7, 0, &buf_sz))
-				goto err;
 		} else if (!strncmp(opt, "tc:", 3)) {
 			if (kstrtoint(opt + 3, 0, &tc))
 				goto err;
-- 
2.30.2



From linux at armlinux.org.uk  Wed Mar  5 10:00:19 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 5 Mar 2025 18:00:19 +0000
Subject: [PATCH net-next 0/2] net: stmmac: approach 2 to solve EEE LPI reset
 issues
Message-ID: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>

Hi,

This is a second approach to solving the STMMAC reset issues caused by
the lack of receive clock from the PHY where the media is in low power
mode with a PHY that supports receive clock-stop.

The first approach centred around only addressing the issue in the
resume path, but it seems to also happen when the platform glue module
is removed and re-inserted (Jon - can you check whether that's also
the case for you please?)

As this is more targetted, I've dropped the patches from this series
which move the call to phylink_resume(), so the link may still come
up too early on resume - but that's something I also intend to fix.

This is experimental - so I value test reports for this change.

As mentioned recently, the reset timeout will only occur if the PHY
receive clock is actually stopped at the moment that stmmac_reset()
is called and remains stopped for the duration of the timeout.
Network activity can wake up the link, causing the PHY to restart
its receive clock and allow reset to complete. So, careful testing
with and without these patches is necessary.

Change from RFC: drop unnecessary first patch.

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |  3 ++
 drivers/net/phy/phylink.c                         | 50 +++++++++++++++++++++++
 include/linux/phylink.h                           |  3 ++
 3 files changed, 56 insertions(+)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From jernej.skrabec at gmail.com  Wed Mar  5 10:08:02 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:08:02 +0100
Subject: [PATCH v3 8/8] pinctrl: sunxi: Add support for the secondary A523 GPIO
 ports
In-Reply-To: <20250227231447.20161-9-andre.przywara@arm.com>
References: <20250227231447.20161-1-andre.przywara@arm.com>
 <20250227231447.20161-9-andre.przywara@arm.com>
Message-ID: <3535684.QJadu78ljV@jernej-laptop>

Dne petek, 28. februar 2025 ob 00:14:47 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> As most other Allwinner SoCs before, the A523 chip contains a second
> GPIO controller, managing banks PL and PM.
> Use the newly introduced DT based pinctrl driver to describe just the
> generic pinctrl properties, so advertise the number of pins per bank
> and the interrupt capabilities. The actual function/mux assignment is
> taken from the devicetree.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From angelogioacchino.delregno at collabora.com  Wed Mar  5 10:08:07 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 5 Mar 2025 19:08:07 +0100
Subject: [PATCH v4 6/8] soc: mediatek: Add programming flow for
 unsupported subsys ID hardware
In-Reply-To: <ddcf01c82f92ee461875e1122b009b7fca691127.camel@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-7-jason-jh.lin@mediatek.com>
 <c52b132b-fc08-4d1c-8276-1771f7457014@collabora.com>
 <ddcf01c82f92ee461875e1122b009b7fca691127.camel@mediatek.com>
Message-ID: <d02b6bbe-0d32-4e3f-985e-a0b610f72d98@collabora.com>

Il 05/03/25 17:12, Jason-JH Lin (???) ha scritto:
> On Tue, 2025-03-04 at 10:41 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
>>> To support hardware without subsys IDs on new SoCs, add a
>>> programming
>>> flow that checks whether the subsys ID is valid. If the subsys ID
>>> is
>>> invalid, the flow will call 2 alternative CMDQ APIs:
>>> cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the same
>>> functionality.
>>>
>>> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
>>> ---
>>>  ? drivers/soc/mediatek/mtk-mmsys.c | 14 +++++++++++---
>>>  ? drivers/soc/mediatek/mtk-mutex.c | 11 +++++++++--
>>>  ? 2 files changed, 20 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/soc/mediatek/mtk-mmsys.c
>>> b/drivers/soc/mediatek/mtk-mmsys.c
>>> index bb4639ca0b8c..ce949b863b05 100644
>>> --- a/drivers/soc/mediatek/mtk-mmsys.c
>>> +++ b/drivers/soc/mediatek/mtk-mmsys.c
>>> @@ -167,9 +167,17 @@ static void mtk_mmsys_update_bits(struct
>>> mtk_mmsys *mmsys, u32 offset, u32 mask,
>>>  ????? u32 tmp;
>>>
>>>  ????? if (mmsys->cmdq_base.size && cmdq_pkt) {
>>> -???????????? ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys-
>>>> cmdq_base.subsys,
>>> -?????????????????????????????????????? mmsys->cmdq_base.offset +
>>> offset, val,
>>> -?????????????????????????????????????? mask);
>>> +???????????? offset += mmsys->cmdq_base.offset;
>>> +???????????? if (mmsys->cmdq_base.subsys != CMDQ_SUBSYS_INVALID) {
>>
>> You're still anyway passing the subsys to cmdq_pkt_write_mask(),
>> right?!
>> Why don't you just handle this in cmdq_pkt_write_mask() then? ;-)
>>
>> I can see this pattern being repeated over and over in both
>> drm/mediatek and MDP3
>> drivers, and it's not necessary to duplicate this many times when you
>> can write it
>> just once.
>>
>> Would've also been faster for you to implement... :-D
>>
> 
> I think did it in the series V1:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20241121042602.32730-5-jason-jh.lin at mediatek.com/
> 
> Because it'll need to passing the base_pa and that will need to change
> the interface for original APIs.
> 
> And CK think that's not a necessary to change the APIs. It can be done
> by cmdq_pkt_assign() + cmdq_pkt_write_s_mask_value() in the client
> drivers. Then you can see this pattern in everywhere. :-)
> 

Using likely(x) and unlikely(x) should be avoided, really, unless it's something
that is really really really really ... really ... rea.... likely or unlikely :-)

Btw. Changing the APIs is a bit difficult, but I disagree with CK about not
"inventing" a new API for the unsupported-subsys flow.

It's true, it is not *strictly* needed to add a function, but it's good for any
kind of future maintainability - as I explained, it's easier then to fix a problem
if there's one.... and well, I can see that you agree with me, because effectively
you did it the first time :-)

CK mentioned using cmdq_pkt_write() *or* cmdq_pkt_assignwrite/cmdq_pkt_write_pa()
(however you wanna call it, it's fine for me), in drivers that know that there
always is or there always isn't a subsys ID: that's a good suggestion, as this can
be eventually done with assigning a function pointer, so, no conditionals at each
operation.

My point of view, finally, is:
  - This is just another way of doing cmdq_pkt_write()
    - This, at the end of the day, does exactly what cmdq_pkt_write() is doing,
      except it's doing it with two instructions instead of one;
  - The same thing can be done in two different ways (depending on SoC)
    - This same thing should have a function that does it.

A function that does it can be

int cmdq_pkt_write_pa(struct cmdq_pkt *pkt, u8 subsys /*unused*/, u32 pa_base, u16 
offset, u32 value)
{
	err = cmdq_pkt_assign(pkt, 0, CMDQ_ADDR_HIGH(pa_base));
	if (err < 0)
		return err;

	return cmdq_pkt_write_s_value( .... etc)
}

int cmdq_pkt_write() <--- unchanged, scheduled for removal after all drivers migrated

int cmdq_pkt_write_subsys(struct cmdq_pkt *pkt, u8 subsys, u32 pa_base /*unused*/, 
u16 offset, u32 value)
{
	/* This function will get the contents of cmdq_pkt_write once removed,
            but, in the meanwhile, to avoid duplication we just call that: */

	return cmdq_pkt_write(pkt, subsys, offset, value);
}

- Are we adding one more function parameter? Yes
- Is this impacting performance overall? Not really

After all, we're living in an ARMv8 (actually, ARMv9 for new ones) world, so
one more function param won't hurt anyone.

I think that's the best of both worlds, and makes everyone happy.
Are you happy with that? :-)

Cheers,
Angelo



From jgg at ziepe.ca  Wed Mar  5 10:14:35 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 14:14:35 -0400
Subject: [PATCH v2 3/4] iommu: Keep dev->iommu state consistent
In-Reply-To: <d219663a3f23001f23d520a883ac622d70b4e642.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <d219663a3f23001f23d520a883ac622d70b4e642.1740753261.git.robin.murphy@arm.com>
Message-ID: <20250305181435.GJ5011@ziepe.ca>

On Fri, Feb 28, 2025 at 03:46:32PM +0000, Robin Murphy wrote:
> @@ -127,6 +128,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
>  		mutex_unlock(&iommu_probe_device_lock);
>  		return 0;
>  	}
> +	dev_iommu_present = dev->iommu;

I feel like this deserves a comment..

Maybe it is:

/*
 * If of_iommu_configure is called outside the iommu probe path
 * dev->iommu should be NULL and it needs to remain as NULL
 * If it is called within the probe path then the dev->iommu
 * was setup by iommu_init_device() and must not be changed.
 */

And I think the commit message should explain what consistent
means.. AFAICT you are going for !dev->iommu means no probe has
succeed / dev->iommu means a probe is ongoing in this call chain or
it has succeeded?

Otherwise:

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

Jason


From lkp at intel.com  Wed Mar  5 10:16:24 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 02:16:24 +0800
Subject: [PATCH v8 2/4] rtc: s32g: add NXP S32G2/S32G3 SoC support
In-Reply-To: <20250228081812.3115478-3-ciprianmarian.costea@oss.nxp.com>
References: <20250228081812.3115478-3-ciprianmarian.costea@oss.nxp.com>
Message-ID: <202503060247.j7Mbl9vb-lkp@intel.com>

Hi Ciprian,

kernel test robot noticed the following build errors:

[auto build test ERROR on robh/for-next]
[also build test ERROR on arm64/for-next/core krzk-dt/for-next linus/master v6.14-rc5 next-20250305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ciprian-Costea/dt-bindings-rtc-add-schema-for-NXP-S32G2-S32G3-SoCs/20250228-162229
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250228081812.3115478-3-ciprianmarian.costea%40oss.nxp.com
patch subject: [PATCH v8 2/4] rtc: s32g: add NXP S32G2/S32G3 SoC support
config: sparc-allmodconfig (https://download.01.org/0day-ci/archive/20250306/202503060247.j7Mbl9vb-lkp at intel.com/config)
compiler: sparc64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250306/202503060247.j7Mbl9vb-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503060247.j7Mbl9vb-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/rtc/rtc-s32g.c: In function 'rtc_clk_src_setup':
>> drivers/rtc/rtc-s32g.c:204:16: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
     204 |         rtcc = FIELD_PREP(RTCC_CLKSEL_MASK, priv->clk_src_idx);
         |                ^~~~~~~~~~


vim +/FIELD_PREP +204 drivers/rtc/rtc-s32g.c

   196	
   197	static int rtc_clk_src_setup(struct rtc_priv *priv)
   198	{
   199		u32 rtcc;
   200	
   201		if (priv->rtc_data->reserved_clk_mask & (1 << priv->clk_src_idx))
   202			return -EOPNOTSUPP;
   203	
 > 204		rtcc = FIELD_PREP(RTCC_CLKSEL_MASK, priv->clk_src_idx);
   205	
   206		switch (priv->rtc_data->clk_div) {
   207		case DIV512_32:
   208			rtcc |= RTCC_DIV512EN;
   209			rtcc |= RTCC_DIV32EN;
   210			break;
   211		case DIV512:
   212			rtcc |= RTCC_DIV512EN;
   213			break;
   214		case DIV32:
   215			rtcc |= RTCC_DIV32EN;
   216			break;
   217		case DIV1:
   218			break;
   219		default:
   220			return -EINVAL;
   221		}
   222	
   223		rtcc |= RTCC_APIEN | RTCC_APIIE;
   224		/*
   225		 * Make sure the CNTEN is 0 before we configure
   226		 * the clock source and dividers.
   227		 */
   228		s32g_rtc_disable(priv);
   229		writel(rtcc, priv->rtc_base + RTCC_OFFSET);
   230		s32g_rtc_enable(priv);
   231	
   232		return 0;
   233	}
   234	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From nicolinc at nvidia.com  Wed Mar  5 10:23:36 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 10:23:36 -0800
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <20250305165452.GY133783@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <20250305165452.GY133783@nvidia.com>
Message-ID: <Z8iWqOBga8Xdunac@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 12:54:52PM -0400, Jason Gunthorpe wrote:
> On Tue, Mar 04, 2025 at 09:03:59PM -0800, Nicolin Chen wrote:
> 
> > Have a pair of patches getting the functions ready for the vmid migration.
> > Decouple the vmid from S2 parent domains and move its allocation to vSMMU
> > instances. Note that a regular S2 domain (!nest_parent) has to retain the
> > s2_cfg and vmid for non-nesting use cases, if the SMMU HW doesn't support
> > stage 1. Then, an S2 invalidation has to be iterated for all the vmids in
> > the vSMMU list introduced in the S2 parent domain.
> 
> I was planning to also fix the S2 to be able to attach to multiple
> IOMMU instances at the same time as getting VMID to the viommu.. It
> doesn't quite make sense to me that viommu would allow multi-attach
> but the normal cases wouldn't. Did you find a shortcut?

Hmm, not quite following the question. You mean vIOMMU attaching to
multiple S2 domains?

> The main issue here was to do this without degrading the invalidation
> workflow and harming SVA and DMA API performance..

I see.. The ATC_INV and TLBI_NH_ALL will be increased for the shared
S2, even if the S2 change is about a device behind one physical SMMU.

Thanks
Nicolin


From manivannan.sadhasivam at linaro.org  Wed Mar  5 10:28:33 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Wed, 5 Mar 2025 23:58:33 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250305173826.GA303920@bhelgaas>
References: <20250304171154.njoygsvfd567pb66@thinkpad>
 <20250305173826.GA303920@bhelgaas>
Message-ID: <20250305182833.cgrwbrcwzjscxmku@thinkpad>

On Wed, Mar 05, 2025 at 11:38:26AM -0600, Bjorn Helgaas wrote:
> On Tue, Mar 04, 2025 at 10:41:54PM +0530, Manivannan Sadhasivam wrote:
> > On Wed, Mar 05, 2025 at 12:46:38AM +0900, Krzysztof Wilczy?ski wrote:
> > > > On Mon, 3 Mar 2025 at 20:47, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> > > > > [...]
> > > > > > > +int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > > > > > +{
> > > > > > > +   char dirname[DWC_DEBUGFS_BUF_MAX];
> > > > > > > +   struct device *dev = pci->dev;
> > > > > > > +   struct debugfs_info *debugfs;
> > > > > > > +   struct dentry *dir;
> > > > > > > +   int ret;
> > > > > > > +
> > > > > > > +   /* Create main directory for each platform driver */
> > > > > > > +   snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > > > > > > +   dir = debugfs_create_dir(dirname, NULL);
> > > > > > > +   debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > > > > > +   if (!debugfs)
> > > > > > > +           return -ENOMEM;
> > > > > > > +
> > > > > > > +   debugfs->debug_dir = dir;
> > > > > > > +   pci->debugfs = debugfs;
> > > > > > > +   ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > > > > > +   if (ret)
> > > > > > > +           dev_dbg(dev, "RASDES debugfs init failed\n");
> > > > > >
> > > > > > What will happen if ret != 0? still return 0?
> > > > 
> > > > And that is exactly what happens on Gray Hawk Single with R-Car
> > > > V4M: dw_pcie_find_rasdes_capability() returns NULL, causing
> > > > dwc_pcie_rasdes_debugfs_init() to return -ENODEV.
> > > > 
> > > > Debugfs issues should never be propagated upstream!
> > ...
> 
> > > > So while applying, you changed this like:
> > > > 
> > > >             ret = dwc_pcie_rasdes_debugfs_init(pci, dir);
> > > >     -       if (ret)
> > > >     -               dev_dbg(dev, "RASDES debugfs init failed\n");
> > > >     +       if (ret) {
> > > >     +               dev_err(dev, "failed to initialize RAS DES debugfs\n");
> > > >     +               return ret;
> > > >     +       }
> > > > 
> > > >             return 0;
> > > > 
> > > > Hence this is now a fatal error, causing the probe to fail.
> 
> > Even though debugfs_init() failure is not supposed to fail the probe(),
> > dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> > failure would be canolically correct IMO.
> 
> I'm not sure about this.  What's the requirement to propagate
> devm_kzalloc() failures?  I think devres will free any allocs that
> were successful regardless.
> 
> IIUC, we resolved the Gray Hawk Single issue by changing
> dwc_pcie_rasdes_debugfs_init() to return success without doing
> anything when there's no RAS DES Capability.
> 
> But dwc_pcie_debugfs_init() can still return failure, and that still
> causes dw_pcie_ep_init_registers() to fail, which breaks the "don't
> propagate debugfs issues upstream" rule:
> 
>   int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>   {
>           ...
>           ret = dwc_pcie_debugfs_init(pci);
>           if (ret)
>                   goto err_remove_edma;
> 
>           return 0;
> 
>   err_remove_edma:
>           dw_pcie_edma_remove(pci);
> 
>           return ret;
>   }
> 
> We can say that kzalloc() failure should "never" happen, and therefore
> it's OK to fail the driver probe if it happens, but that doesn't seem
> like a strong argument for breaking the "don't propagate debugfs
> issues" rule.  And someday there may be other kinds of failures from
> dwc_pcie_debugfs_init().
> 

Fine with me. I was not too sure about propagating failure either.

- Mani

-- 
????????? ????????


From jgg at ziepe.ca  Wed Mar  5 10:29:51 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 14:29:51 -0400
Subject: [PATCH] iommu: Unexport iommu_fwspec_free()
In-Reply-To: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
References: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
Message-ID: <20250305182951.GL5011@ziepe.ca>

On Thu, Feb 27, 2025 at 02:47:47PM +0000, Robin Murphy wrote:
> The drivers doing their own fwspec parsing have no need to call
> iommu_fwspec_free() since fwspecs were moved into dev_iommu, as
> returning an error from .probe_device will tear down the whole lot
> anyway. Move it into the private interface now that it only serves
> for of_iommu to clean up in an error case.
> 
> I have no idea what mtk_v1 was doing in effectively guaranteeing
> a NULL fwspec would be dereferenced if no "iommus" DT property was
> found, so add a check for that to at least make the code look sane.

> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu.c |  1 -
>  drivers/iommu/iommu-priv.h            |  2 ++
>  drivers/iommu/iommu.c                 |  1 -
>  drivers/iommu/mtk_iommu_v1.c          | 14 ++++----------
>  drivers/iommu/tegra-smmu.c            |  1 -
>  include/linux/iommu.h                 |  5 -----
>  6 files changed, 6 insertions(+), 18 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

Jason


From jgg at nvidia.com  Wed Mar  5 10:31:51 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 14:31:51 -0400
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <Z8iWqOBga8Xdunac@Asurada-Nvidia>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <20250305165452.GY133783@nvidia.com>
 <Z8iWqOBga8Xdunac@Asurada-Nvidia>
Message-ID: <20250305183151.GE133783@nvidia.com>

On Wed, Mar 05, 2025 at 10:23:36AM -0800, Nicolin Chen wrote:
> On Wed, Mar 05, 2025 at 12:54:52PM -0400, Jason Gunthorpe wrote:
> > On Tue, Mar 04, 2025 at 09:03:59PM -0800, Nicolin Chen wrote:
> > 
> > > Have a pair of patches getting the functions ready for the vmid migration.
> > > Decouple the vmid from S2 parent domains and move its allocation to vSMMU
> > > instances. Note that a regular S2 domain (!nest_parent) has to retain the
> > > s2_cfg and vmid for non-nesting use cases, if the SMMU HW doesn't support
> > > stage 1. Then, an S2 invalidation has to be iterated for all the vmids in
> > > the vSMMU list introduced in the S2 parent domain.
> > 
> > I was planning to also fix the S2 to be able to attach to multiple
> > IOMMU instances at the same time as getting VMID to the viommu.. It
> > doesn't quite make sense to me that viommu would allow multi-attach
> > but the normal cases wouldn't. Did you find a shortcut?
> 
> Hmm, not quite following the question. You mean vIOMMU attaching to
> multiple S2 domains?

I mean a normal S2 domain attaching to multiple devices on multiple
instances.

Jason


From jgg at ziepe.ca  Wed Mar  5 10:28:58 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 14:28:58 -0400
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
Message-ID: <20250305182858.GK5011@ziepe.ca>

On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
> +	if (!dev->driver && dev->bus->dma_configure) {
> +		mutex_unlock(&iommu_probe_device_lock);
> +		dev->bus->dma_configure(dev);
> +		mutex_lock(&iommu_probe_device_lock);
> +	}

I think it would be very nice to get rid of the lock/unlock.. It makes
me nervous that we continue on assuming dev->iommu was freshly
allocated..

 setup the dev->iommu partially, then drop the lock.

There is only one other caller in:

static int really_probe(struct device *dev, const struct device_driver *drv)
{
	if (dev->bus->dma_configure) {
		ret = dev->bus->dma_configure(dev);
		if (ret)
			goto pinctrl_bind_failed;
	}

Is it feasible to make it so the caller has to hold the
iommu_probe_device_lock prior to calling the op?

That would require moving the locking inside of_dma_configure to less
inside, and using a new iommu_probe_device() wrapper.

However, if you plan to turn this inside out soonish then it would not
be worth the bother.

Anyhow:

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

Jason


From sebastianene at google.com  Wed Mar  5 10:36:01 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Wed, 5 Mar 2025 18:36:01 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <20250305003808.GA31667@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
 <Z8ZPBZF7J-qKdb_i@google.com>
 <20250304015633.GA30882@willie-the-truck>
 <Z8c6enoolJe7Zeqk@google.com>
 <20250305003808.GA31667@willie-the-truck>
Message-ID: <Z8iZkQHknZfY7mpn@google.com>

On Wed, Mar 05, 2025 at 12:38:08AM +0000, Will Deacon wrote:
> On Tue, Mar 04, 2025 at 05:38:02PM +0000, Sebastian Ene wrote:
> > On Tue, Mar 04, 2025 at 01:56:35AM +0000, Will Deacon wrote:
> > > On Tue, Mar 04, 2025 at 12:53:25AM +0000, Sebastian Ene wrote:
> > > > On Mon, Mar 03, 2025 at 11:43:03PM +0000, Will Deacon wrote:
> > > > > On Thu, Feb 27, 2025 at 06:17:48PM +0000, Sebastian Ene wrote:
> > > > > > Map the hypervisor's buffers irrespective to the host and return
> > > > > > a linux error code from the FF-A error code on failure. Remove
> > > > > > the unmap ff-a buffers calls from the hypervisor as it will
> > > > > > never be called.
> > > > > > Prevent the host from using FF-A directly with Trustzone
> > > > > > if the hypervisor could not map its own buffers.
> > > > > > 
> > > > > > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > > > > > ---
> > > > > >  arch/arm64/kvm/hyp/nvhe/ffa.c | 46 +++++++++++++----------------------
> > > > > >  1 file changed, 17 insertions(+), 29 deletions(-)
> > > > > 
> > > > > [...]
> > > > > 
> > > > > > @@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
> > > > > >  {
> > > > > >  	struct arm_smccc_res res;
> > > > > >  	void *tx, *rx;
> > > > > > +	int ret;
> > > > > >  
> > > > > >  	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
> > > > > >  		return 0;
> > > > > > @@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
> > > > > >  		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
> > > > > >  	};
> > > > > >  
> > > > > > +	/* Map our hypervisor buffers into the SPMD */
> > > > > > +	ret = ffa_map_hyp_buffers();
> > > > > > +	if (ret)
> > > > > > +		return ret;
> > > > > 
> > > > > Doesn't calling RXTX_MAP here undo the fix from c9c012625e12 ("KVM:
> > > > > arm64: Trap FFA_VERSION host call in pKVM") where we want to allow for
> > > > > the host to negotiate the version lazily?
> > > > 
> > > > We still have the same behaviour where we don't allow memory
> > > > sharing to happen until the version is negotiated but this
> > > > separates the hypervisor buffer mapping part from the host.
> > > 
> > > Sadly, the spec doesn't restrict this to the memory sharing calls:
> > > 
> > >   | [...] negotiation of the version must happen before an invocation of
> > >   | any other FF-A ABI
> > > 
> > 
> > We do that, as the hypervisor negotiates its own version in
> > hyp_ffa_init.
> 
> hyp_ffa_init() only issues FFA_VERSION afaict, which is the one call
> that you're allowed to make during negotiation. So the existing code is
> fine.
> 
> > I think the host shouldn't be allowed to overwrite the
> > hyp_ffa_version obtained from _init, this feels wrong as you
> > can have a driver that forcefully downgrades the hypervisor to an old
> > version.
> 
> I think that's also fine. The FFA code in the hypervisor exists solely
> to proxy requests from the host; it's not used for anything else and so,
> from the host's persective, FFA should behave identically to the case in
> which the proxy is not present (e.g. if we were just using VHE). That
> means that we're doing the right thing by deferring to the host for
> version negotation.
> 
> Are you saying there's a bug in the current code if the host negotiates
> the downgrade?

It is an issue *only* for doing guest-ffa (which isn't posted here yet).
If we allow the host to dictate the version & there is an issue with TZ
FF-A dispatcher in that version => the guests will be affected by this
as well.

> 
> > We need to do three things, Sudeep & Will please correct me if I am
> > wrong, but this is how I see it:
> > 
> > - the hypervisor should act as a separate entity (it has a different ID and
> > in the current implementation we don't do a distinction between host/hyp) and
> > it should be able to lock its own version from init.
> 
> I strongly disagree with that. The hypervisor isn't using FFA for
> anything other than proxying the host and so we don't need to negotiate
> a separate version.
> 
> What would we gain by doing this? Is there a bug with what we're doing
> at the moment?

I think we need to make a distinction between the host and the
hypervisor when we are adding support for guest-ffa. We currently have
the same id (== 0) for both of them.

> 
> > - keep a separate version negotiated for the host
> > - trap FFA_ID_GET from the host and return ID=1 because
> >   currently we forward the call to the TZ and it returns the same ID
> >   as the (hypervisor == 0).
> 
> Why is this beneficial? It just looks like complexity at EL2 for no gain
> to me, but maybe I'm missing something.
>

Because the host can impersonate the hypervisor using ff-a direct calls atm.
and we are in a position to restrict the host from playing nasty games
with TZ.

> Will

Thanks,
Sebastian


From nicolinc at nvidia.com  Wed Mar  5 10:45:49 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 10:45:49 -0800
Subject: [PATCH v1 3/4] iommu/arm-smmu-v3: Decouple vmid from S2
 nest_parent domain
In-Reply-To: <20250305170157.GB133783@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <0429d554fb0f54f6d79bdacacb3fb3e7877ca8f7.1741150594.git.nicolinc@nvidia.com>
 <20250305170157.GB133783@nvidia.com>
Message-ID: <Z8ib3XngBXzFGARI@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 01:01:57PM -0400, Jason Gunthorpe wrote:
> On Tue, Mar 04, 2025 at 09:04:02PM -0800, Nicolin Chen wrote:
> > @@ -2249,10 +2249,22 @@ static void arm_smmu_tlb_inv_context(void *cookie)
> >  	 */
> >  	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> >  		arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
> > -	} else {
> > +	} else if (!smmu_domain->nest_parent) {
> >  		cmd.opcode	= CMDQ_OP_TLBI_S12_VMALL;
> >  		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
> >  		arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
> > +	} else {
> > +		struct arm_vsmmu *vsmmu, *next;
> > +		unsigned long flags;
> > +
> > +		cmd.opcode = CMDQ_OP_TLBI_S12_VMALL;
> > +		spin_lock_irqsave(&smmu_domain->vsmmus.lock, flags);
> > +		list_for_each_entry_safe(vsmmu, next, &smmu_domain->vsmmus.list,
> > +					 vsmmus_elm) {
> > +			cmd.tlbi.vmid = vsmmu->vmid;
> > +			arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);

Just noticed that here should be vsmmu->smmu.

> > +		}
> > +		spin_unlock_irqrestore(&smmu_domain->vsmmus.lock, flags);
> >  	}
> 
> I see.. So this just makes a 3rd classification of invalidation
> protocol that uses a spinlock and linked list
>
> >  	arm_smmu_atc_inv_domain(smmu_domain, 0, 0);
> 
> This is no good, arm_smmu_atc_inv_domain() is invalidating against the
> instance that created the domain.

Oh right... we might need an arm_smmu_atc_inv_all() that takes
an smmu pointer. This might have some performance downgrade as
you worried about though.

> IMHO if you do this you should set domain->iommu = NULL to indicate
> that the iommu is non-valid in this mode to catch issues.

You mean smmu_domain->smmu pointer right?

Thanks
Nicolin


From jernej.skrabec at gmail.com  Wed Mar  5 10:46:20 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:46:20 +0100
Subject: [PATCH v2 08/15] arm64: dts: allwinner: Add Allwinner A523 .dtsi file
In-Reply-To: <20250304222309.29385-9-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-9-andre.przywara@arm.com>
Message-ID: <2646028.Lt9SDvczpP@jernej-laptop>

Dne torek, 4. marec 2025 ob 23:23:02 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Allwinner A523, and its siblings A527 and T527, which share the same
> die, are a new family of SoCs introduced in 2023. They features eight
> Arm Cortex-A55 cores, and, among the other usual peripherals, a PCIe and
> USB 3.0 controller.
> 
> Add the basic SoC devicetree .dtsi for the chip, describing the
> fundamental peripherals: the cores, GIC, timer, RTC, CCU and pinctrl.
> Also some other peripherals are fully compatible with previous IP, so
> add the USB and MMC nodes as well.
> The other peripherals will be added in the future, once we understand
> their compatibility and DT requirements.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
>  1 file changed, 598 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> 
> diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> new file mode 100644
> index 0000000000000..01e662bdf5521
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> @@ -0,0 +1,598 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +// Copyright (C) 2023-2024 Arm Ltd.
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sun6i-rtc.h>
> +#include <dt-bindings/clock/sun55i-a523-ccu.h>
> +#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
> +#include <dt-bindings/reset/sun55i-a523-ccu.h>
> +#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu at 0 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x000>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu1: cpu at 100 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x100>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu2: cpu at 200 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x200>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu3: cpu at 300 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x300>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu4: cpu at 400 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x400>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu5: cpu at 500 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x500>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu6: cpu at 600 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x600>;
> +			enable-method = "psci";
> +		};
> +
> +		cpu7: cpu at 700 {
> +			compatible = "arm,cortex-a55";
> +			device_type = "cpu";
> +			reg = <0x700>;
> +			enable-method = "psci";
> +		};
> +	};
> +
> +	osc24M: osc24M-clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "osc24M";
> +	};
> +
> +	pmu {
> +		compatible = "arm,cortex-a55-pmu";
> +		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		arm,no-tick-in-suspend;
> +		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
> +	};
> +
> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges = <0x0 0x0 0x0 0x40000000>;
> +
> +		pio: pinctrl at 2000000 {
> +			compatible = "allwinner,sun55i-a523-pinctrl";
> +			reg = <0x2000000 0x800>;
> +			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc CLK_OSC32K>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;
> +
> +			mmc0_pins: mmc0-pins {
> +				pins = "PF0" ,"PF1", "PF2", "PF3", "PF4", "PF5";
> +				allwinner,pinmux = <2>;
> +				function = "mmc0";
> +				drive-strength = <30>;
> +				bias-pull-up;
> +			};
> +
> +			/omit-if-no-ref/
> +			mmc1_pins: mmc1-pins {
> +				pins = "PG0" ,"PG1", "PG2", "PG3", "PG4", "PG5";
> +				allwinner,pinmux = <2>;
> +				function = "mmc1";
> +				drive-strength = <30>;
> +				bias-pull-up;
> +			};
> +
> +			mmc2_pins: mmc2-pins {
> +				pins = "PC1" ,"PC5", "PC6", "PC8", "PC9",
> +				       "PC10", "PC11", "PC13", "PC14", "PC15",
> +				       "PC16";

I guess PC0 should be also included, for HS400 capable cards.

With that fixed:
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej

> +				allwinner,pinmux = <3>;
> +				function = "mmc2";
> +				drive-strength = <30>;
> +				bias-pull-up;
> +			};
> +
> +			uart0_pb_pins: uart0-pb-pins {
> +				pins = "PB9", "PB10";
> +				allwinner,pinmux = <2>;
> +				function = "uart0";
> +			};
> +		};
> +
> +		ccu: clock at 2001000 {
> +			compatible = "allwinner,sun55i-a523-ccu";
> +			reg = <0x02001000 0x1000>;
> +			clocks = <&osc24M>, <&rtc CLK_OSC32K>,
> +				 <&rtc CLK_IOSC>, <&rtc CLK_OSC32K_FANOUT>;
> +			clock-names = "hosc", "losc",
> +				      "iosc", "losc-fanout";
> +			#clock-cells = <1>;
> +			#reset-cells = <1>;
> +		};
> +
> +		mmc0: mmc at 4020000 {
> +			compatible = "allwinner,sun55i-a523-mmc",
> +				     "allwinner,sun20i-d1-mmc";
> +			reg = <0x04020000 0x1000>;
> +			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
> +			clock-names = "ahb", "mmc";
> +			resets = <&ccu RST_BUS_MMC0>;
> +			reset-names = "ahb";
> +			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&mmc0_pins>;
> +			status = "disabled";
> +
> +			max-frequency = <150000000>;
> +			cap-sd-highspeed;
> +			cap-mmc-highspeed;
> +			cap-sdio-irq;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		mmc1: mmc at 4021000 {
> +			compatible = "allwinner,sun55i-a523-mmc",
> +				     "allwinner,sun20i-d1-mmc";
> +			reg = <0x04021000 0x1000>;
> +			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
> +			clock-names = "ahb", "mmc";
> +			resets = <&ccu RST_BUS_MMC1>;
> +			reset-names = "ahb";
> +			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&mmc1_pins>;
> +			status = "disabled";
> +
> +			max-frequency = <150000000>;
> +			cap-sd-highspeed;
> +			cap-mmc-highspeed;
> +			cap-sdio-irq;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		mmc2: mmc at 4022000 {
> +			compatible = "allwinner,sun55i-a523-mmc",
> +				     "allwinner,sun20i-d1-mmc";
> +			reg = <0x04022000 0x1000>;
> +			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
> +			clock-names = "ahb", "mmc";
> +			resets = <&ccu RST_BUS_MMC2>;
> +			reset-names = "ahb";
> +			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&mmc2_pins>;
> +			status = "disabled";
> +
> +			max-frequency = <150000000>;
> +			cap-sd-highspeed;
> +			cap-mmc-highspeed;
> +			cap-sdio-irq;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		wdt: watchdog at 2050000 {
> +			compatible = "allwinner,sun55i-a523-wdt";
> +			reg = <0x2050000 0x20>;
> +			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&osc24M>, <&rtc CLK_OSC32K>;
> +			clock-names = "hosc", "losc";
> +			status = "okay";
> +		};
> +
> +		uart0: serial at 2500000 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02500000 0x400>;
> +			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART0>;
> +			resets = <&ccu RST_BUS_UART0>;
> +			status = "disabled";
> +		};
> +
> +		uart1: serial at 2500400 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02500400 0x400>;
> +			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART1>;
> +			resets = <&ccu RST_BUS_UART1>;
> +			status = "disabled";
> +		};
> +
> +		uart2: serial at 2500800 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02500800 0x400>;
> +			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART2>;
> +			resets = <&ccu RST_BUS_UART2>;
> +			status = "disabled";
> +		};
> +
> +		uart3: serial at 2500c00 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02500c00 0x400>;
> +			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART3>;
> +			resets = <&ccu RST_BUS_UART3>;
> +			status = "disabled";
> +		};
> +
> +		uart4: serial at 2501000 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02501000 0x400>;
> +			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART4>;
> +			resets = <&ccu RST_BUS_UART4>;
> +			status = "disabled";
> +		};
> +
> +		uart5: serial at 2501400 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02501400 0x400>;
> +			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART5>;
> +			resets = <&ccu RST_BUS_UART5>;
> +			status = "disabled";
> +		};
> +
> +		uart6: serial at 2501800 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02501800 0x400>;
> +			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART6>;
> +			resets = <&ccu RST_BUS_UART6>;
> +			status = "disabled";
> +		};
> +
> +		uart7: serial at 2501c00 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x02501c00 0x400>;
> +			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			clocks = <&ccu CLK_BUS_UART7>;
> +			resets = <&ccu RST_BUS_UART7>;
> +			status = "disabled";
> +		};
> +
> +		i2c0: i2c at 2502000 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2502000 0x400>;
> +			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C0>;
> +			resets = <&ccu RST_BUS_I2C0>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		i2c1: i2c at 2502400 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2502400 0x400>;
> +			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C1>;
> +			resets = <&ccu RST_BUS_I2C1>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		i2c2: i2c at 2502800 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2502800 0x400>;
> +			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C2>;
> +			resets = <&ccu RST_BUS_I2C2>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		i2c3: i2c at 2502c00 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2502c00 0x400>;
> +			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C3>;
> +			resets = <&ccu RST_BUS_I2C3>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		i2c4: i2c at 2503000 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2503000 0x400>;
> +			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C4>;
> +			resets = <&ccu RST_BUS_I2C4>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		i2c5: i2c at 2503400 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x2503400 0x400>;
> +			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_I2C5>;
> +			resets = <&ccu RST_BUS_I2C5>;
> +			status = "disabled";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		gic: interrupt-controller at 3400000 {
> +			compatible = "arm,gic-v3";
> +			#address-cells = <1>;
> +			#interrupt-cells = <3>;
> +			#size-cells = <1>;
> +			ranges;
> +			interrupt-controller;
> +			reg = <0x3400000 0x10000>,
> +			      <0x3460000 0x100000>;
> +			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
> +			dma-noncoherent;
> +
> +			its: msi-controller at 3440000 {
> +				compatible = "arm,gic-v3-its";
> +				reg = <0x3440000 0x20000>;
> +				msi-controller;
> +				#msi-cells = <1>;
> +				dma-noncoherent;
> +			};
> +		};
> +
> +		usb_otg: usb at 4100000 {
> +			compatible = "allwinner,sun55i-a523-musb",
> +				     "allwinner,sun8i-a33-musb";
> +			reg = <0x4100000 0x400>;
> +			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "mc";
> +			clocks = <&ccu CLK_BUS_OTG>;
> +			resets = <&ccu RST_BUS_OTG>;
> +			extcon = <&usbphy 0>;
> +			phys = <&usbphy 0>;
> +			phy-names = "usb";
> +			status = "disabled";
> +		};
> +
> +		usbphy: phy at 4100400 {
> +			compatible = "allwinner,sun55i-a523-usb-phy",
> +				     "allwinner,sun20i-d1-usb-phy";
> +			reg = <0x4100400 0x100>,
> +			      <0x4101800 0x100>,
> +			      <0x4200800 0x100>;
> +			reg-names = "phy_ctrl",
> +				    "pmu0",
> +				    "pmu1";
> +			clocks = <&osc24M>,
> +				 <&osc24M>;
> +			clock-names = "usb0_phy",
> +				      "usb1_phy";
> +			resets = <&ccu RST_USB_PHY0>,
> +				 <&ccu RST_USB_PHY1>;
> +			reset-names = "usb0_reset",
> +				      "usb1_reset";
> +			status = "disabled";
> +			#phy-cells = <1>;
> +		};
> +
> +		ehci0: usb at 4101000 {
> +			compatible = "allwinner,sun55i-a523-ehci",
> +				     "generic-ehci";
> +			reg = <0x4101000 0x100>;
> +			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_OHCI0>,
> +				 <&ccu CLK_BUS_EHCI0>,
> +				 <&ccu CLK_USB_OHCI0>;
> +			resets = <&ccu RST_BUS_OHCI0>,
> +				 <&ccu RST_BUS_EHCI0>;
> +			phys = <&usbphy 0>;
> +			phy-names = "usb";
> +			status = "disabled";
> +		};
> +
> +		ohci0: usb at 4101400 {
> +			compatible = "allwinner,sun55i-a523-ohci",
> +				     "generic-ohci";
> +			reg = <0x4101400 0x100>;
> +			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_OHCI0>,
> +				 <&ccu CLK_USB_OHCI0>;
> +			resets = <&ccu RST_BUS_OHCI0>;
> +			phys = <&usbphy 0>;
> +			phy-names = "usb";
> +			status = "disabled";
> +		};
> +
> +		ehci1: usb at 4200000 {
> +			compatible = "allwinner,sun55i-a523-ehci",
> +				     "generic-ehci";
> +			reg = <0x4200000 0x100>;
> +			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_OHCI1>,
> +				 <&ccu CLK_BUS_EHCI1>,
> +				 <&ccu CLK_USB_OHCI1>;
> +			resets = <&ccu RST_BUS_OHCI1>,
> +				 <&ccu RST_BUS_EHCI1>;
> +			phys = <&usbphy 1>;
> +			phy-names = "usb";
> +			status = "disabled";
> +		};
> +
> +		ohci1: usb at 4200400 {
> +			compatible = "allwinner,sun55i-a523-ohci",
> +				     "generic-ohci";
> +			reg = <0x4200400 0x100>;
> +			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_OHCI1>,
> +				 <&ccu CLK_USB_OHCI1>;
> +			resets = <&ccu RST_BUS_OHCI1>;
> +			phys = <&usbphy 1>;
> +			phy-names = "usb";
> +			status = "disabled";
> +		};
> +
> +		r_ccu: clock-controller at 7010000 {
> +			compatible = "allwinner,sun55i-a523-r-ccu";
> +			reg = <0x7010000 0x250>;
> +			clocks = <&osc24M>,
> +				 <&rtc CLK_OSC32K>,
> +				 <&rtc CLK_IOSC>,
> +				 <&ccu CLK_PLL_PERIPH0_200M>,
> +				 <&ccu CLK_PLL_AUDIO0_4X>;
> +			clock-names = "hosc",
> +				      "losc",
> +				      "iosc",
> +				      "pll-periph",
> +				      "pll-audio";
> +			#clock-cells = <1>;
> +			#reset-cells = <1>;
> +		};
> +
> +		nmi_intc: interrupt-controller at 7010320 {
> +			compatible = "allwinner,sun55i-a523-nmi";
> +			reg = <0x07010320 0xc>;
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +		};
> +
> +		r_pio: pinctrl at 7022000 {
> +			compatible = "allwinner,sun55i-a523-r-pinctrl";
> +			reg = <0x7022000 0x800>;
> +			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&r_ccu CLK_R_APB0>,
> +				 <&osc24M>,
> +				 <&rtc CLK_OSC32K>;
> +			clock-names = "apb", "hosc", "losc";
> +			gpio-controller;
> +			#gpio-cells = <3>;
> +			interrupt-controller;
> +			#interrupt-cells = <3>;
> +
> +			r_i2c_pins: r-i2c-pins {
> +				pins = "PL0" ,"PL1";
> +				allwinner,pinmux = <2>;
> +				function = "r_i2c0";
> +			};
> +		};
> +
> +		r_i2c0: i2c at 7081400 {
> +			compatible = "allwinner,sun55i-a523-i2c",
> +				     "allwinner,sun8i-v536-i2c",
> +				     "allwinner,sun6i-a31-i2c";
> +			reg = <0x07081400 0x400>;
> +			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&r_ccu CLK_BUS_R_I2C0>;
> +			resets = <&r_ccu RST_BUS_R_I2C0>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&r_i2c_pins>;
> +			status = "disabled";
> +
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
> +		rtc: rtc at 7090000 {
> +			compatible = "allwinner,sun55i-a523-rtc",
> +				     "allwinner,sun50i-r329-rtc";
> +			reg = <0x7090000 0x400>;
> +			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&r_ccu CLK_BUS_R_RTC>,
> +				 <&osc24M>,
> +				 <&r_ccu CLK_R_AHB>;
> +			clock-names = "bus", "hosc", "ahb";
> +			#clock-cells = <1>;
> +		};
> +	};
> +};
> 






From catalin.marinas at arm.com  Wed Mar  5 10:48:19 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 5 Mar 2025 18:48:19 +0000
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
In-Reply-To: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
References: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
Message-ID: <Z8iccxCo7tkqvE_p@arm.com>

On Tue, Mar 04, 2025 at 12:51:27AM -0800, Piotr Jaroszynski wrote:
> Update the __flush_tlb_range_op macro not to modify its parameters as
> these are unexepcted semantics. In practice, this fixes the call to
> mmu_notifier_arch_invalidate_secondary_tlbs() in
> __flush_tlb_range_nosync() to use the correct range instead of an empty
> range with start=end. The empty range was (un)lucky as it results in
> taking the invalidate-all path that doesn't cause correctness issues,
> but can certainly result in suboptimal perf.
> 
> This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
> invalidate_range() when invalidating TLBs") when the call to the
> notifiers was added to __flush_tlb_range(). It predates the addition of
> the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
> Refactor the core flush algorithm of __flush_tlb_range") that made the
> bug hard to spot.

That's the problem with macros.

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>

Will, do you want to take this as a fix? It's only a performance
regression, though you never know how it breaks the callers of the macro
at some point.

> Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")
> 
> Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Robin Murphy <robin.murphy at arm.com>
> Cc: Alistair Popple <apopple at nvidia.com>
> Cc: Raghavendra Rao Ananta <rananta at google.com>
> Cc: SeongJae Park <sj at kernel.org>
> Cc: Jason Gunthorpe <jgg at nvidia.com>
> Cc: John Hubbard <jhubbard at nvidia.com>
> Cc: Nicolin Chen <nicolinc at nvidia.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: iommu at lists.linux.dev
> Cc: linux-mm at kvack.org
> Cc: linux-kernel at vger.kernel.org
> Cc: stable at vger.kernel.org
> ---
>  arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++----------
>  1 file changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
> index bc94e036a26b..8104aee4f9a0 100644
> --- a/arch/arm64/include/asm/tlbflush.h
> +++ b/arch/arm64/include/asm/tlbflush.h
> @@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
>  #define __flush_tlb_range_op(op, start, pages, stride,			\
>  				asid, tlb_level, tlbi_user, lpa2)	\
>  do {									\
> +	typeof(start) __flush_start = start;				\
> +	typeof(pages) __flush_pages = pages;				\
>  	int num = 0;							\
>  	int scale = 3;							\
>  	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
>  	unsigned long addr;						\
>  									\
> -	while (pages > 0) {						\
> +	while (__flush_pages > 0) {					\
>  		if (!system_supports_tlb_range() ||			\
> -		    pages == 1 ||					\
> -		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
> -			addr = __TLBI_VADDR(start, asid);		\
> +		    __flush_pages == 1 ||				\
> +		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
> +			addr = __TLBI_VADDR(__flush_start, asid);	\
>  			__tlbi_level(op, addr, tlb_level);		\
>  			if (tlbi_user)					\
>  				__tlbi_user_level(op, addr, tlb_level);	\
> -			start += stride;				\
> -			pages -= stride >> PAGE_SHIFT;			\
> +			__flush_start += stride;			\
> +			__flush_pages -= stride >> PAGE_SHIFT;		\
>  			continue;					\
>  		}							\
>  									\
> -		num = __TLBI_RANGE_NUM(pages, scale);			\
> +		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
>  		if (num >= 0) {						\
> -			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
> +			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
>  						scale, num, tlb_level);	\
>  			__tlbi(r##op, addr);				\
>  			if (tlbi_user)					\
>  				__tlbi_user(r##op, addr);		\
> -			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
> -			pages -= __TLBI_RANGE_PAGES(num, scale);	\
> +			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
> +			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
>  		}							\
>  		scale--;						\
>  	}								\
> 
> base-commit: 99fa936e8e4f117d62f229003c9799686f74cebc
> -- 
> 2.22.1.7.gac84d6e93c.dirty

-- 
Catalin


From jernej.skrabec at gmail.com  Wed Mar  5 10:48:59 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:48:59 +0100
Subject: [PATCH v2 11/15] arm64: dts: allwinner: a523: add Avaota-A1 router
 support
In-Reply-To: <20250304222309.29385-12-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-12-andre.przywara@arm.com>
Message-ID: <2224762.Mh6RI2rZIc@jernej-laptop>

Dne torek, 4. marec 2025 ob 23:23:05 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Avaota A1 router board is an Open Source hardware board, designed
> by YuzukiHD. Pine64 produces some boards and sells them. It uses the
> Allwinner A527 or T527 SoC, and comes with the following features:
>   - Eight ARM Cortex-A55 cores, Mali-G57 MC1 GPU
>   - 1GiB/2GiB/4GiB LPDDR4 DRAM
>   - AXP717 + AXP323 PMIC
>   - Raspberry-Pi-2 compatible GPIO header
>   - 1 USB 2.0 type A host port, 1 USB 3.0 type A host post
>   - 1 USB 2.0 type C port (OTG + serial debug)
>   - MicroSD slot
>   - eMMC between 16 and 128 GiB
>   - on-board 16MiB bootable SPI NOR flash
>   - two 1Gbps Ethernet ports (via RTL8211F PHYs)
>   - HDMI port
>   - DP port
>   - camera and LCD connectors
>   - 3.5mm headphone jack
>   - (yet) unsupported WiFi/BT chip
>   - 1.3" LC display, connected via SPI
>   - 12 V barrel plug for power supply
> 
> Add the devicetree file describing the currently supported features.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Wed Mar  5 10:50:28 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:50:28 +0100
Subject: [PATCH v2 12/15] arm64: dts: allwinner: a523: add X96Q-Pro+ support
In-Reply-To: <20250304222309.29385-13-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-13-andre.przywara@arm.com>
Message-ID: <3805591.MHq7AAxBmi@jernej-laptop>

Dne torek, 4. marec 2025 ob 23:23:06 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The X96QPro+ is a TV box using the Allwinner H728 SoC. That SoC seems to
> be a package variant of the A523 family, at least it uses the same SoC
> ID and is compatible as far as we can assess.
> 
> It comes with the following specs:
>   - Allwinner H728 SoC: 8 Arm Cortex-A55 cores, Mali-G57 MC1 GPU
>   - 2 or 4GiB DDR3L DRAM
>   - 32, 64, or 128 GiB eMMC flash
>   - AXP717 + AXP323 PMICs
>   - Gigabit Ethernet (using MAXIO PHY)
>   - HDMI port
>   - 2 * USB 2.0 ports
>   - 1 * USB 3.0 port
>   - microSD card slot
>   - TOSLINK digital audio output
>   - 3.5mm A/V port
>   - infrared sensor
>   - 7-segment display
>   - 5V barrel plug power supply
>   - power button
> 
> The PCB provides holes for soldering a UART header or cable, this is
> connected to the debug UART0. There is another set of UART pins
> available. The board also features a FEL button (accessible through the
> 3.5mm socket) and a reset button (only accessible when case is open).
> 
> This .dts just describes the basic peripherals as far as we support them
> at the moment. The PMIC rail assignments are reverse engineered as far
> as possible, by dumping them from a running Android system, and correlating
> them to other boards using the same SoC.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From nicolinc at nvidia.com  Wed Mar  5 10:51:38 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 10:51:38 -0800
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <20250305183151.GE133783@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <20250305165452.GY133783@nvidia.com>
 <Z8iWqOBga8Xdunac@Asurada-Nvidia>
 <20250305183151.GE133783@nvidia.com>
Message-ID: <Z8idOr67A0EG1/PN@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 02:31:51PM -0400, Jason Gunthorpe wrote:
> On Wed, Mar 05, 2025 at 10:23:36AM -0800, Nicolin Chen wrote:
> > On Wed, Mar 05, 2025 at 12:54:52PM -0400, Jason Gunthorpe wrote:
> > > On Tue, Mar 04, 2025 at 09:03:59PM -0800, Nicolin Chen wrote:
> > > 
> > > > Have a pair of patches getting the functions ready for the vmid migration.
> > > > Decouple the vmid from S2 parent domains and move its allocation to vSMMU
> > > > instances. Note that a regular S2 domain (!nest_parent) has to retain the
> > > > s2_cfg and vmid for non-nesting use cases, if the SMMU HW doesn't support
> > > > stage 1. Then, an S2 invalidation has to be iterated for all the vmids in
> > > > the vSMMU list introduced in the S2 parent domain.
> > > 
> > > I was planning to also fix the S2 to be able to attach to multiple
> > > IOMMU instances at the same time as getting VMID to the viommu.. It
> > > doesn't quite make sense to me that viommu would allow multi-attach
> > > but the normal cases wouldn't. Did you find a shortcut?
> > 
> > Hmm, not quite following the question. You mean vIOMMU attaching to
> > multiple S2 domains?
> 
> I mean a normal S2 domain attaching to multiple devices on multiple
> instances.

Oh, I haven't thought about a !nest_parent S2 case.

A nest_parent case will not allow devices to attach the S2 but
always to a proxy nested S1 as we discussed previously. So, I
think the implementation could be very different?

Thanks
Nicolin


From jernej.skrabec at gmail.com  Wed Mar  5 10:52:49 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:52:49 +0100
Subject: [PATCH v2 13/15] arm64: dts: allwinner: a523: add Radxa A5E support
In-Reply-To: <20250304222309.29385-14-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-14-andre.przywara@arm.com>
Message-ID: <1888259.atdPhlSkOF@jernej-laptop>

Dne torek, 4. marec 2025 ob 23:23:07 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Radxa A5E is a development board using the Allwinner A527 SoC, which
> is using the same die as the A523 SoC, just exposing the pins of more
> peripherals (like HDMI or the 2nd MAC). The board features:
> 
>   - Allwinner A527/T527 SoC: 8 ARM Cortex-A55 cores, Mali-G57 MC1 GPU
>   - 1GiB/2GiB/4GiB LPDDR4 DRAM
>   - AXP717 + AXP323 PMICs
>   - Raspberry-Pi-2 compatible 40pin GPIO header
>   - 1 USB 2.0 type C port (OTG), also power supply
>   - 1 USB 3.0 type A host port (multiplexed with M.2 slot)
>   - 1 M.2 M-key 2230 slot, with 1 PCIe2.1 lane connected (multiplexed
>     with USB 3.0 port)
>   - MicroSD slot
>   - optional eMMC, 8, 16 or 32GB available
>   - optional on-board 16MiB bootable SPI NOR flash
>   - two 1Gbps Ethernet ports (via MAXIO MAE0621A PHYs)
>   - PoE header for optional supply circuit on one Ethernet port
>   - WiFi 802.11 a/b/g/n/ac/ax (LB-Link BL-M8800DS2 module using AIC8800)
>   - HDMI port
>   - camera and LCD connectors
>   - power supply via USB-C connector (but no PD) or GPIO header pins
> 
> This .dts describes the devices as far as we support them at the moment.
> The PMIC rails have been assigned as per the schematics.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Wed Mar  5 10:54:10 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 05 Mar 2025 19:54:10 +0100
Subject: [PATCH v2 15/15] arm64: dts: allwinner: h616: add YuzukiHD Chameleon
 support
In-Reply-To: <20250304222309.29385-16-andre.przywara@arm.com>
References: <20250304222309.29385-1-andre.przywara@arm.com>
 <20250304222309.29385-16-andre.przywara@arm.com>
Message-ID: <2227598.Icojqenx9y@jernej-laptop>

Dne torek, 4. marec 2025 ob 23:23:09 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Chameleon board is an OpenHardware devboard made by YuzukiTsuru.
> The form factor resembles the Raspberry Pi Model A boards, though it
> differs significantly in its features:
> 
>   - Allwinner H618 SoC (4 * Arm Cortex-A53 cores, 1MB L2 cache, 1.4 GHz)
>   - between 512MiB and 2GiB DDR3 DRAM
>   - up to 128 GiB eMMC flash
>   - AXP313a PMIC
>   - 100 Mbit/s Ethernet pins on a header
>   - XR829 WIFI+Bluetooth chip
>   - 4 * USB 2.0 USB-C ports
>   - microSD card slot
>   - 3.5mm A/V port
> 
> Add the devicetree describing the board's peripherals and their
> connections.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From krzysztof.kozlowski at linaro.org  Wed Mar  5 11:55:12 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:55:12 +0100
Subject: [PATCH 1/2] clk: samsung: Add missing mod_devicetable.h header
In-Reply-To: <9063abd1-b417-4623-b44d-fcb18f3c71b7@linaro.org>
References: <20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e@linaro.org>
 <20250304-clk-samsung-headers-cleanup-v1-1-81718e38246e@linaro.org>
 <9063abd1-b417-4623-b44d-fcb18f3c71b7@linaro.org>
Message-ID: <56487b08-d4ae-4eb0-88bc-9c65ae866508@linaro.org>

On 05/03/2025 15:23, Tudor Ambarus wrote:
> 
> 
> On 3/4/25 6:45 PM, Krzysztof Kozlowski wrote:
>>  drivers/clk/samsung/clk-exynos-audss.c   | 1 +
>>  drivers/clk/samsung/clk-exynos-clkout.c  | 1 +
> 
> drivers/clk/samsung/clk-exynos2200.c can benefit of the inclusion too.

Yes, this was reported by Stephen and I was waiting for reply from the
author.

> 
>>  drivers/clk/samsung/clk-exynos3250.c     | 2 +-
> 
> drivers/clk/samsung/clk-exynos4.c too

I missed it, weird. Thanks.

> 
>>  drivers/clk/samsung/clk-exynos4412-isp.c | 1 +
> 
> drivers/clk/samsung/clk-exynos5-subcmu.c too

How did I search for of_device_id...

> 
>>  drivers/clk/samsung/clk-exynos5250.c     | 1 +
>>  drivers/clk/samsung/clk-exynos5420.c     | 1 +
>>  drivers/clk/samsung/clk-exynos5433.c     | 1 +
> 
> drivers/clk/samsung/clk-exynos7870.c too

Same as Exynos2200. I guess I will fix it, instead of authors.

> 
>>  drivers/clk/samsung/clk-exynos7885.c     | 1 +
>>  drivers/clk/samsung/clk-exynos850.c      | 1 +
>>  drivers/clk/samsung/clk-exynos8895.c     | 1 +
>>  drivers/clk/samsung/clk-exynos990.c      | 1 +
>>  drivers/clk/samsung/clk-exynosautov9.c   | 1 +
>>  drivers/clk/samsung/clk-exynosautov920.c | 1 +
>>  drivers/clk/samsung/clk-fsd.c            | 1 +
>>  drivers/clk/samsung/clk-gs101.c          | 1 +
>>  drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +
> 
> drivers/clk/samsung/clk.c and drivers/clk/samsung/clk.h too.

Indeed.

> 
> With that:
> Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>

Thanks

Best regards,
Krzysztof


From nfraprado at collabora.com  Wed Mar  5 10:58:15 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:15 -0300
Subject: [PATCH v4 00/19] Get mt6359-accdet ready for usage in Devicetree
Message-ID: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>

This series prepares the MT6359 ACCDET for actual usage in the
Devicetree. Patch 1 adds the required DT bindings, patches 2 and 3 get
the mt6359-accdet driver probing, patches 4-17 clean up code related to
DT property parsing, patch 18 adds the node in the Devicetree and patch
19 enables the kconfig for the driver.

Together with the series "Allow retrieving accessory detection reference
on MT8188" [1], and one extra patch on top enabling it on the
genio-700-evk DT, this series was tested on the Genio 700 EVK to get
audio jack detection working on it.

[1] https://lore.kernel.org/all/20250214-mt8188-accdet-v1-0-6bbd5483855b at collabora.com

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
Changes in v4:
- Moved DT-binding for accdet from standalone file
  (sound/mediatek,mt6359-accdet.yaml) to parent mfd's file
  (mfd/mediatek,mt6397.yaml), squashing patches 1 and 2.
- Link to v3: https://lore.kernel.org/r/20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b at collabora.com

Changes in v3:
- Removed unneeded '|' in mt6359-accdet's dt-binding description
- Removed unneeded unevaluatedProperties for accdet node in mt6397's
  dt-binding
- Clarified HP_EINT pin is on the MT6359 PMIC in mediatek,hp-eint-high's
  description in the mt6359-accdet dt-binding
- Link to v2: https://lore.kernel.org/r/20250302-mt6359-accdet-dts-v2-0-5bd633ee0d47 at collabora.com

Changes in v2:
- Removed all DT-binding properties except for EINT polarity one
  (mediatek,eint-level-pol / mediatek,hp-eint-high)
  - Added patches 12-18 to make those settings internal to driver
- Renamed mediatek,eint-level-pol to mediatek,hp-eint-high and made it
  bool
- Added patch 20 to enable the MT6359 ACCDET Kconfig in the defconfig
- Removed unused btn_type variable as part of "Drop dead code for button
  detection" patch.
- Link to v1: https://lore.kernel.org/r/20250214-mt6359-accdet-dts-v1-0-677a151b9b4c at collabora.com

---
Andrew Perepech (2):
      mfd: mt6397-core: Add mfd_cell for mt6359-accdet
      ASoC: mediatek: mt6359-accdet: Implement HP_EINT polarity configuration

N?colas F. R. A. Prado (17):
      dt-bindings: mfd: mediatek: mt6397: Add accdet subnode
      ASoC: mediatek: mt6359-accdet: Add compatible property
      ASoC: mediatek: mt6359-accdet: Handle hp-eint-high property
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT/GPIO IRQ handling
      ASoC: mediatek: mt6359-accdet: Drop dead code for EINT trigger setting
      ASoC: mediatek: mt6359-accdet: Drop dead code for button detection
      ASoC: mediatek: mt6359-accdet: Drop dead code for plugout-debounce
      ASoC: mediatek: mt6359-accdet: Drop unused moisture variables
      ASoC: mediatek: mt6359-accdet: Always use internal resistor
      ASoC: mediatek: mt6359-accdet: Make PWM debounce settings internal
      ASoC: mediatek: mt6359-accdet: Always use eint detect mode 4
      ASoC: mediatek: mt6359-accdet: Always set micbias1 to 2.8V
      ASoC: mediatek: mt6359-accdet: Always configure hardware as mic-mode 2
      ASoC: mediatek: mt6359-accdet: Always set comp-vth to 1.6V
      ASoC: mediatek: mt6359-accdet: Always use EINT0 IRQ
      arm64: dts: mt6359: Add accessory detect node
      arm64: defconfig: Enable MT6359 ACCDET

 .../devicetree/bindings/mfd/mediatek,mt6397.yaml   |  51 ++
 arch/arm64/boot/dts/mediatek/mt6359.dtsi           |   4 +
 arch/arm64/configs/defconfig                       |   1 +
 drivers/mfd/mt6397-core.c                          |  12 +
 sound/soc/codecs/mt6359-accdet.c                   | 599 +++++----------------
 sound/soc/codecs/mt6359-accdet.h                   |  55 +-
 6 files changed, 198 insertions(+), 524 deletions(-)
---
base-commit: 20d5c66e1810e6e8805ec0d01373afb2dba9f51a
change-id: 20250214-mt6359-accdet-dts-00b189847f3c

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Wed Mar  5 10:58:16 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:16 -0300
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>

Describe the accessory detection (accdet) module as a possible subnode
of the MT6359 PMIC.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../devicetree/bindings/mfd/mediatek,mt6397.yaml   | 51 ++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..51012b8bbfaef3df7bdb619a4f8d828d6f9cc15a 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -24,6 +24,7 @@ description: |
   - LED
   - Keys
   - Power controller
+  - Accessory Detection
 
   It is interfaced to host controller using SPI interface by a proprietary hardware
   called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
@@ -224,6 +225,30 @@ properties:
     description:
       Pin controller
 
+  accdet:
+    type: object
+    additionalProperties: false
+    description:
+      The Accessory Detection module found on the PMIC allows detecting audio
+      jack insertion and removal, as well as identifying the type of events
+      connected to the jack.
+
+    properties:
+      compatible:
+        const: mediatek,mt6359-accdet
+
+      mediatek,hp-eint-high:
+        type: boolean
+        description:
+          By default, MT6359's HP_EINT pin is assumed to be pulled high and
+          connected to a normally open 3.5mm jack. Plug insertion is detected
+          when the pin is brought low in that case. Add this property if the
+          behavior should be inverted, for example if a normally closed 3.5mm
+          jack is used, or if the line is pulled low on open.
+
+    required:
+      - compatible
+
 required:
   - compatible
   - regulators
@@ -598,3 +623,29 @@ examples:
             compatible = "mediatek,mt6397-rtc";
         };
     };
+  - |
+    #include <dt-bindings/input/input.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    pmic {
+        compatible = "mediatek,mt6359";
+        interrupt-controller;
+        #interrupt-cells = <2>;
+
+        accdet {
+            compatible = "mediatek,mt6359-accdet";
+            mediatek,hp-eint-high;
+        };
+
+        regulators {
+            compatible = "mediatek,mt6359-regulator";
+
+            buck_vs1 {
+                    regulator-name = "vs1";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <2200000>;
+                    regulator-enable-ramp-delay = <0>;
+                    regulator-always-on;
+            };
+        };
+    };

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:17 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:17 -0300
Subject: [PATCH v4 02/19] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-2-e5ffa5ee9991@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
allow the mt6359-accdet driver to probe.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 drivers/mfd/mt6397-core.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 0e5d59ae064a696ae2111e2b558b316667c14773..5f8ed898890783c0ce4e34c7eae0d8f678e7d7bc 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -84,6 +84,12 @@ static const struct resource mt6359_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
 };
 
+static const struct resource mt6359_accdet_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET, "accdet_irq"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT0, "accdet_eint0"),
+	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT1, "accdet_eint1"),
+};
+
 static const struct resource mt6323_keys_resources[] = {
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
@@ -239,6 +245,12 @@ static const struct mfd_cell mt6359_devs[] = {
 		.resources = mt6359_keys_resources,
 		.of_compatible = "mediatek,mt6359-keys"
 	},
+	{
+		.name = "mt6359-accdet",
+		.of_compatible = "mediatek,mt6359-accdet",
+		.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
+		.resources = mt6359_accdet_resources,
+	},
 };
 
 static const struct mfd_cell mt6397_devs[] = {

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:18 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:18 -0300
Subject: [PATCH v4 03/19] ASoC: mediatek: mt6359-accdet: Add compatible
 property
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-3-e5ffa5ee9991@collabora.com>

Add a compatible property and add it to the module device table for the
mt6359-accdet platform driver to allow automatic module loading and
probing when the compatible is present in DT.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ed34cc15b80e856356c07fd53af22207124e0d19..9bbd4497e8d481ee125693be2fc576b439574b39 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -1047,9 +1047,16 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	return ret;
 }
 
+const struct of_device_id accdet_of_match[] = {
+	{ .compatible = "mediatek,mt6359-accdet", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, accdet_of_match);
+
 static struct platform_driver mt6359_accdet_driver = {
 	.driver = {
 		.name = "pmic-codec-accdet",
+		.of_match_table = accdet_of_match,
 	},
 	.probe = mt6359_accdet_probe,
 };

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:19 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:19 -0300
Subject: [PATCH v4 04/19] ASoC: mediatek: mt6359-accdet: Handle
 hp-eint-high property
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-4-e5ffa5ee9991@collabora.com>

Now that the dt-binding was introduced, the property that governs the
eint polarity is a boolean called mediatek,hp-eint-high, while the
current code handles a u32 property called mediatek,eint-level-pol.
Update the driver handling accordingly.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 +----
 sound/soc/codecs/mt6359-accdet.h | 2 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 9bbd4497e8d481ee125693be2fc576b439574b39..ca3be59d2d0ecaadccd9ba399649ba93f20490c4 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -578,10 +578,7 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!ret)
 		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
 
-	ret = of_property_read_u32(node, "mediatek,eint-level-pol",
-				   &priv->data->eint_pol);
-	if (ret)
-		priv->data->eint_pol = 8;
+	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index c234f2f4276a12853a6fe0b13c4198dfc551b6b4..a54a328bdf3797ce642da446c0cc6792f72ec939 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -86,7 +86,7 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	unsigned int plugout_deb;
-	unsigned int eint_pol;
+	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	struct three_key_threshold three_key;
 	struct four_key_threshold four_key;

-- 
2.48.1



From catalin.marinas at arm.com  Wed Mar  5 10:59:43 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 5 Mar 2025 18:59:43 +0000
Subject: [PATCH v9] arm64: mm: Populate vmemmap at the page level if not
 section aligned
In-Reply-To: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
References: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
Message-ID: <Z8ifH6HILN_7sZDk@arm.com>

On Tue, Mar 04, 2025 at 03:27:00PM +0800, Zhenhua Huang wrote:
> On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
> to 27, making one section 128M. The related page struct which vmemmap
> points to is 2M then.
> Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
> vmemmap to populate at the PMD section level which was suitable
> initially since hot plug granule is always one section(128M). However,
> commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
> existing arm64 assumptions.
> 
> The first problem is that if start or end is not aligned to a section
> boundary, such as when a subsection is hot added, populating the entire
> section is wasteful.
> 
> The next problem is if we hotplug something that spans part of 128 MiB
> section (subsections, let's call it memblock1), and then hotplug something
> that spans another part of a 128 MiB section(subsections, let's call it
> memblock2), and subsequently unplug memblock1, vmemmap_free() will clear
> the entire PMD entry which also supports memblock2 even though memblock2
> is still active.
> 
> Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the
> fix similar to x86-64: populate to pages levels if start/end is not aligned
> with section boundary.
> 
> Cc: <stable at vger.kernel.org> # v5.4+
> Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> Acked-by: David Hildenbrand <david at redhat.com>
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
> ---
>  arch/arm64/mm/mmu.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>

Will, another bug that has been around for ages. Do you want to take it
as a fix?

> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b4df5bc5b1b8..1dfe1a8efdbe 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
>  		struct vmem_altmap *altmap)
>  {
>  	WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
> +	/* [start, end] should be within one section */
> +	WARN_ON_ONCE(end - start > PAGES_PER_SECTION * sizeof(struct page));
>  
> -	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
> +	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
> +	    (end - start < PAGES_PER_SECTION * sizeof(struct page)))
>  		return vmemmap_populate_basepages(start, end, node, altmap);
>  	else
>  		return vmemmap_populate_hugepages(start, end, node, altmap);
> -- 
> 2.25.1
> 

-- 
Catalin


From nfraprado at collabora.com  Wed Mar  5 10:58:20 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:20 -0300
Subject: [PATCH v4 05/19] ASoC: mediatek: mt6359-accdet: Implement HP_EINT
 polarity configuration
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-5-e5ffa5ee9991@collabora.com>

From: Andrew Perepech <andrew.perepech at mediatek.com>

The driver currently reads the HP_EINT polarity from the Devicetree but
never actually configures the hardware accordingly.

Implement the polarity configuration in hardware.

Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ca3be59d2d0ecaadccd9ba399649ba93f20490c4..1d4481109f6e4f473610e0797c9d3c636bdf12cf 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -730,6 +730,17 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 		}
 	}
+
+	if (priv->data->hp_eint_high) {
+		/* EINT polarity inverse */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT,
+				   BIT(ACCDET_EINT_IN_INVERSE_SFT));
+	} else {
+		/* EINT polarity normal */
+		regmap_update_bits(priv->regmap, ACCDET_EINT_IN_INVERSE_ADDR,
+				   ACCDET_EINT_IN_INVERSE_MASK_SFT, 0);
+	}
 }
 
 static void config_eint_init_by_mode(struct mt6359_accdet *priv)

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:21 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:21 -0300
Subject: [PATCH v4 06/19] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT/GPIO IRQ handling
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-6-e5ffa5ee9991@collabora.com>

The ACCDET supports two modes for IRQ generation: PMIC EINT or AP GPIO,
which in principle could be configured through a DT property. However
this DT property has no user nor is documented in a binding, and the
driver only implements the PMIC EINT case, so drop the unused code
intended to handle both cases.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 1d4481109f6e4f473610e0797c9d3c636bdf12cf..ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,9 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT_IRQ		BIT(0)
-#define ACCDET_AP_GPIO_EINT		BIT(1)
-
 #define ACCDET_PMIC_EINT0		BIT(2)
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
@@ -448,8 +445,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		mt6359_accdet_recover_jd_setting(priv);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ)
-		recover_eint_setting(priv);
+	recover_eint_setting(priv);
 	mutex_unlock(&priv->res_lock);
 }
 
@@ -580,14 +576,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT_IRQ;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_AP_GPIO_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
 				   &priv->data->eint_detect_mode);
 	if (ret) {
@@ -902,10 +890,8 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 				   0x3 << RG_ANALOGFDEN_SFT);
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT_IRQ) {
-		config_eint_init_by_mode(priv);
-		config_digital_init_by_mode(priv);
-	}
+	config_eint_init_by_mode(priv);
+	config_digital_init_by_mode(priv);
 }
 
 int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:22 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:22 -0300
Subject: [PATCH v4 07/19] ASoC: mediatek: mt6359-accdet: Drop dead code for
 EINT trigger setting
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-7-e5ffa5ee9991@collabora.com>

None of the EINT trigger options are implemented and the DT property is
not described in the binding. Remove the unused code.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index ce8a5e64e0b9ca508124043ca1f93aaa3cc5f9a0..a21c6544174517e3eebc8cf25d1ea3029ba014f6 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -35,8 +35,6 @@
 #define ACCDET_PMIC_EINT1		BIT(3)
 #define ACCDET_PMIC_BI_EINT		BIT(4)
 
-#define ACCDET_PMIC_GPIO_TRIG_EINT	BIT(5)
-#define ACCDET_PMIC_INVERTER_TRIG_EINT	BIT(6)
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_THREE_KEY		BIT(8)
@@ -593,15 +591,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-trig-mode",
-				   &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT;
-
 	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
 				   &priv->data->eint_use_ext_res);
 	if (ret) {

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:23 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:23 -0300
Subject: [PATCH v4 08/19] ASoC: mediatek: mt6359-accdet: Drop dead code for
 button detection
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-8-e5ffa5ee9991@collabora.com>

The button detection functionality depends on a calibration voltage
value which is currently not updated anywhere in the driver code, and
hence it doesn't actually do anything. Remove this unused code.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 92 ++--------------------------------------
 sound/soc/codecs/mt6359-accdet.h | 17 --------
 2 files changed, 3 insertions(+), 106 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a21c6544174517e3eebc8cf25d1ea3029ba014f6..6b0178976d91e37c32540991693ebfd8e29c11f5 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -37,9 +37,6 @@
 
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
-#define ACCDET_THREE_KEY		BIT(8)
-#define ACCDET_FOUR_KEY			BIT(9)
-#define ACCDET_TRI_KEY_CDD		BIT(10)
 #define ACCDET_RSV_KEY			BIT(11)
 
 #define ACCDET_ANALOG_FASTDISCHARGE	BIT(12)
@@ -255,7 +252,6 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 			    priv->data->pwm_deb->debounce3);
 
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_jack_report(priv);
 }
@@ -318,45 +314,10 @@ static void mt6359_accdet_jack_report(struct mt6359_accdet *priv)
 	if (!priv->jack)
 		return;
 
-	report = priv->jack_type | priv->btn_type;
+	report = priv->jack_type;
 	snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK);
 }
 
-static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v)
-{
-	if (priv->caps & ACCDET_FOUR_KEY) {
-		if (v < priv->data->four_key.down &&
-		    v >= priv->data->four_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->four_key.up &&
-		    v >= priv->data->four_key.voice)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->four_key.voice &&
-		    v >= priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_3;
-		if (v < priv->data->four_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	} else {
-		if (v < priv->data->three_key.down &&
-		    v >= priv->data->three_key.up)
-			priv->btn_type = SND_JACK_BTN_1;
-		if (v < priv->data->three_key.up &&
-		    v >= priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_2;
-		if (v < priv->data->three_key.mid)
-			priv->btn_type = SND_JACK_BTN_0;
-	}
-	return 0;
-}
-
-static void is_key_pressed(struct mt6359_accdet *priv, bool pressed)
-{
-	priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK;
-
-	if (pressed)
-		check_button(priv, priv->cali_voltage);
-}
-
 static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
@@ -368,15 +329,11 @@ static inline void check_jack_btn_type(struct mt6359_accdet *priv)
 
 	switch (priv->accdet_status) {
 	case 0:
-		if (priv->jack_type == SND_JACK_HEADSET)
-			is_key_pressed(priv, true);
-		else
+		if (priv->jack_type != SND_JACK_HEADSET)
 			priv->jack_type = SND_JACK_HEADPHONE;
 		break;
 	case 1:
-		if (priv->jack_type == SND_JACK_HEADSET) {
-			is_key_pressed(priv, false);
-		} else {
+		if (priv->jack_type != SND_JACK_HEADSET) {
 			priv->jack_type = SND_JACK_HEADSET;
 			accdet_set_debounce(priv, eint_state011, 0x1);
 		}
@@ -603,48 +560,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->eint_comp_vth = 0x0;
 
-	ret = of_property_read_u32(node, "mediatek,key-mode", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_THREE_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,three-key-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	} else if (tmp == 1) {
-		int four_key[5];
-
-		priv->caps |= ACCDET_FOUR_KEY;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,four-key-thr",
-						 four_key,
-						 ARRAY_SIZE(four_key));
-		if (!ret) {
-			memcpy(&priv->data->four_key, four_key + 1,
-			       sizeof(struct four_key_threshold));
-		} else {
-			dev_warn(priv->dev,
-				 "accdet no 4-key-thrsh dts, use efuse\n");
-		}
-	} else if (tmp == 2) {
-		int three_key[4];
-
-		priv->caps |= ACCDET_TRI_KEY_CDD;
-		ret = of_property_read_u32_array(node,
-						 "mediatek,tri-key-cdd-thr",
-						 three_key,
-						 ARRAY_SIZE(three_key));
-		if (!ret)
-			memcpy(&priv->data->three_key, three_key + 1,
-			       sizeof(struct three_key_threshold));
-	}
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -1015,7 +930,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 
 	priv->jd_sts = M_PLUG_OUT;
 	priv->jack_type = 0;
-	priv->btn_type = 0;
 	priv->accdet_status = 0x3;
 	mt6359_accdet_init(priv);
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index a54a328bdf3797ce642da446c0cc6792f72ec939..09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,19 +50,6 @@ enum {
 	eint_inverter_state000,
 };
 
-struct three_key_threshold {
-	unsigned int mid;
-	unsigned int up;
-	unsigned int down;
-};
-
-struct four_key_threshold {
-	unsigned int mid;
-	unsigned int voice;
-	unsigned int up;
-	unsigned int down;
-};
-
 struct pwm_deb_settings {
 	unsigned int pwm_width;
 	unsigned int pwm_thresh;
@@ -88,8 +75,6 @@ struct dts_data {
 	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	struct three_key_threshold three_key;
-	struct four_key_threshold four_key;
 	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
@@ -112,10 +97,8 @@ struct mt6359_accdet {
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;
-	unsigned int btn_type;
 	unsigned int accdet_status;
 	unsigned int pre_accdet_status;
-	unsigned int cali_voltage;
 	unsigned int jd_sts;
 	struct work_struct accdet_work;
 	struct workqueue_struct *accdet_workqueue;

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:24 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:24 -0300
Subject: [PATCH v4 09/19] ASoC: mediatek: mt6359-accdet: Drop dead code for
 plugout-debounce
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-9-e5ffa5ee9991@collabora.com>

The mediatek,plugout-debounce property is undocumented in the binding
and unhandled by the driver. Remove it.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 5 -----
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 6 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6b0178976d91e37c32540991693ebfd8e29c11f5..d78d7516342a5c2273b1c2962c0346646aa6390f 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -513,11 +513,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_vol = 8;
 
-	ret = of_property_read_u32(node, "mediatek,plugout-debounce",
-				   &priv->data->plugout_deb);
-	if (ret)
-		priv->data->plugout_deb = 1;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 09e1072b61a4c929bf6b764b4fab3c4b26f7cf4a..54a33a0f0e084f80df33386b3df9bba9525fa880 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -72,7 +72,6 @@ struct pwm_deb_settings {
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
-	unsigned int plugout_deb;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int moisture_detect_enable;

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:25 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:25 -0300
Subject: [PATCH v4 10/19] ASoC: mediatek: mt6359-accdet: Drop unused
 moisture variables
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-10-e5ffa5ee9991@collabora.com>

The dts_data struct contains several variables for moisture
configuration that are simply never used. Drop them.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 54a33a0f0e084f80df33386b3df9bba9525fa880..38c36d59b9cc68bd90e16137a05a62b521b75ac1 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -74,14 +74,9 @@ struct dts_data {
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
-	unsigned int moisture_detect_enable;
 	unsigned int eint_detect_mode;
 	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
-	unsigned int moisture_detect_mode;
-	unsigned int moisture_comp_vth;
-	unsigned int moisture_comp_vref2;
-	unsigned int moisture_use_ext_res;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:26 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:26 -0300
Subject: [PATCH v4 11/19] ASoC: mediatek: mt6359-accdet: Always use
 internal resistor
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-11-e5ffa5ee9991@collabora.com>

The code currently reads a property mediatek,eint-use-ext-res with
values ranging between 0 and 4. Not only should this be a boolean
property, but there's no need for it to even be a DT property, seeing as
all current boards will use the internal resistor anyway. Since there's
no current dt-binding or Devicetree user of this property, remove its
handling and make the driver always configure the internal resistor.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 53 +++++++++++-----------------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 14 insertions(+), 40 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index d78d7516342a5c2273b1c2962c0346646aa6390f..e04cfb9a607aa5d38d46329eb1387545fda37ccc 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -82,14 +82,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 					   RG_EINT1CONFIGACCDET_MASK_SFT,
 					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
-		if (priv->data->eint_use_ext_res == 0x3 ||
-		    priv->data->eint_use_ext_res == 0x4) {
-			/*select 500k, use internal resistor */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0HIRENB_ADDR,
-					   RG_EINT0HIRENB_MASK_SFT,
-					   BIT(RG_EINT0HIRENB_SFT));
-		}
+		/*select 500k, use internal resistor */
+		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+				   RG_EINT0HIRENB_MASK_SFT,
+				   BIT(RG_EINT0HIRENB_SFT));
 	}
 	return 0;
 }
@@ -543,13 +539,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
-				   &priv->data->eint_use_ext_res);
-	if (ret) {
-		/* eint use internal resister */
-		priv->data->eint_use_ext_res = 0x0;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
 				   &priv->data->eint_comp_vth);
 	if (ret)
@@ -651,30 +640,16 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	if (priv->data->eint_detect_mode == 0x1 ||
 	    priv->data->eint_detect_mode == 0x2 ||
 	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->data->eint_use_ext_res == 0x1) {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   0);
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   0);
-			}
-		} else {
-			if (priv->caps & ACCDET_PMIC_EINT0) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT0CONFIGACCDET_ADDR,
-						   RG_EINT0CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT0CONFIGACCDET_SFT));
-			} else if (priv->caps & ACCDET_PMIC_EINT1) {
-				regmap_update_bits(priv->regmap,
-						   RG_EINT1CONFIGACCDET_ADDR,
-						   RG_EINT1CONFIGACCDET_MASK_SFT,
-						   BIT(RG_EINT1CONFIGACCDET_SFT));
-			}
+		if (priv->caps & ACCDET_PMIC_EINT0) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT0CONFIGACCDET_ADDR,
+					   RG_EINT0CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT0CONFIGACCDET_SFT));
+		} else if (priv->caps & ACCDET_PMIC_EINT1) {
+			regmap_update_bits(priv->regmap,
+					   RG_EINT1CONFIGACCDET_ADDR,
+					   RG_EINT1CONFIGACCDET_MASK_SFT,
+					   BIT(RG_EINT1CONFIGACCDET_SFT));
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 38c36d59b9cc68bd90e16137a05a62b521b75ac1..99de5037a2294b62cb8535fc45dbf4c6fafb5c7f 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -75,7 +75,6 @@ struct dts_data {
 	bool hp_eint_high;
 	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
-	unsigned int eint_use_ext_res;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:27 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:27 -0300
Subject: [PATCH v4 12/19] ASoC: mediatek: mt6359-accdet: Make PWM debounce
 settings internal
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-12-e5ffa5ee9991@collabora.com>

Instead of reading a bunch of PWM debounce settings from the Devicetree,
set reasonable values inside the driver that are known to work across
multiple boards. There are no current users of these DT properties, so
no backward compatibility needs to be maintained. The properties can be
properly introduced in the binding in the future if different boards
really need to override them.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 70 ++++++++++++++++++++++------------------
 sound/soc/codecs/mt6359-accdet.h | 20 ------------
 2 files changed, 38 insertions(+), 52 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index e04cfb9a607aa5d38d46329eb1387545fda37ccc..6728f1018c992fc9d4e4133dbaf091d256567683 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -43,6 +43,25 @@
 #define ACCDET_DIGITAL_FASTDISCHARGE	BIT(13)
 #define ACCDET_AD_FASTDISCHRAGE		BIT(14)
 
+/* Debounce time = (DEBOUNCE/32768) sec */
+#define ACCDET_DEBOUNCE0_625MS 0x800
+#define ACCDET_DEBOUNCE1_625MS 0x800
+#define ACCDET_DEBOUNCE3_976US 0x20
+#define ACCDET_DEBOUNCE_AUXADC_2MS 0x44
+/* PWM frequency = 32768/(PWM_WIDTH + 1) Hz */
+#define ACCDET_PWM_WIDTH_25_580HZ 0x500
+/* Duty cycle = (PWM_THRESH + 1) / (PWM_WIDTH + 1) */
+#define ACCDET_PWM_THRESH_100PERCENT ACCDET_PWM_WIDTH_25_580HZ
+#define ACCDET_RISE_DELAY 0x1f0
+#define ACCDET_FALL_DELAY 1
+#define ACCDET_EINT_DEBOUNCE0_1MS 5
+#define ACCDET_EINT_DEBOUNCE1_900US 3
+#define ACCDET_EINT_DEBOUNCE2_900US 3
+#define ACCDET_EINT_DEBOUNCE3_1MS 5
+#define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
+#define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
+#define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
 
@@ -130,7 +149,7 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 	} else if (priv->jd_sts == M_PLUG_OUT) {
 		/* set debounce to 1ms */
 		accdet_set_debounce(priv, eint_state000,
-				    priv->data->pwm_deb->eint_debounce0);
+				    ACCDET_EINT_DEBOUNCE0_1MS);
 	} else {
 		dev_dbg(priv->dev, "should not be here %s()\n", __func__);
 	}
@@ -241,11 +260,11 @@ static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 
 	/* recover accdet debounce0,3 */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 
 	priv->jack_type = 0;
 	priv->accdet_status = 0x3;
@@ -390,7 +409,7 @@ static void mt6359_accdet_jd_work(struct work_struct *work)
 		priv->jack_plugged = false;
 
 		accdet_set_debounce(priv, accdet_state011,
-				    priv->data->pwm_deb->debounce3);
+				    ACCDET_DEBOUNCE3_976US);
 		regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,
 				   ACCDET_SW_EN_MASK_SFT, 0);
 		mt6359_accdet_recover_jd_setting(priv);
@@ -497,7 +516,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	int pwm_deb[15] = {0};
 	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
@@ -514,12 +532,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (ret)
 		priv->data->mic_mode = 2;
 
-	ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting",
-					 pwm_deb, ARRAY_SIZE(pwm_deb));
-	/* debounce8(auxadc debounce) is default, needn't get from dts */
-	if (!ret)
-		memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
@@ -554,8 +566,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 {
 	/* enable eint cmpmem pwm */
 	regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR,
-		     (priv->data->pwm_deb->eint_pwm_width << 4 |
-		     priv->data->pwm_deb->eint_pwm_thresh));
+		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
+		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
 	if (priv->caps & ACCDET_PMIC_EINT0) {
 		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
@@ -675,22 +687,22 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 	mdelay(1);
 	/* init the debounce time (debounce/32768)sec */
 	accdet_set_debounce(priv, accdet_state000,
-			    priv->data->pwm_deb->debounce0);
+			    ACCDET_DEBOUNCE0_625MS);
 	accdet_set_debounce(priv, accdet_state001,
-			    priv->data->pwm_deb->debounce1);
+			    ACCDET_DEBOUNCE1_625MS);
 	accdet_set_debounce(priv, accdet_state011,
-			    priv->data->pwm_deb->debounce3);
+			    ACCDET_DEBOUNCE3_976US);
 	accdet_set_debounce(priv, accdet_auxadc,
-			    priv->data->pwm_deb->debounce4);
+			    ACCDET_DEBOUNCE_AUXADC_2MS);
 
 	accdet_set_debounce(priv, eint_state000,
-			    priv->data->pwm_deb->eint_debounce0);
+			    ACCDET_EINT_DEBOUNCE0_1MS);
 	accdet_set_debounce(priv, eint_state001,
-			    priv->data->pwm_deb->eint_debounce1);
+			    ACCDET_EINT_DEBOUNCE1_900US);
 	accdet_set_debounce(priv, eint_state011,
-			    priv->data->pwm_deb->eint_debounce3);
+			    ACCDET_EINT_DEBOUNCE3_1MS);
 	accdet_set_debounce(priv, eint_inverter_state000,
-			    priv->data->pwm_deb->eint_inverter_debounce);
+			    ACCDET_EINT_INVERTER_DEBOUNCE_256MS);
 
 	regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,
 			   RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT));
@@ -705,12 +717,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 
 	/* init pwm frequency, duty & rise/falling delay */
 	regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_width));
+		     REGISTER_VAL(ACCDET_PWM_WIDTH_25_580HZ));
 	regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR,
-		     REGISTER_VAL(priv->data->pwm_deb->pwm_thresh));
+		     REGISTER_VAL(ACCDET_PWM_THRESH_100PERCENT));
 	regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR,
-		     (priv->data->pwm_deb->fall_delay << 15 |
-		      priv->data->pwm_deb->rise_delay));
+		     (ACCDET_FALL_DELAY << 15 |
+		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
 	if (priv->data->mic_vol <= 7) {
@@ -806,12 +818,6 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 	if (!priv->data)
 		return -ENOMEM;
 
-	priv->data->pwm_deb = devm_kzalloc(&pdev->dev,
-					   sizeof(struct pwm_deb_settings),
-					   GFP_KERNEL);
-	if (!priv->data->pwm_deb)
-		return -ENOMEM;
-
 	priv->regmap = mt6397->regmap;
 	if (IS_ERR(priv->regmap)) {
 		ret = PTR_ERR(priv->regmap);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 99de5037a2294b62cb8535fc45dbf4c6fafb5c7f..287201eebe0330fa170093fd6192bf5694c30469 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -50,30 +50,10 @@ enum {
 	eint_inverter_state000,
 };
 
-struct pwm_deb_settings {
-	unsigned int pwm_width;
-	unsigned int pwm_thresh;
-	unsigned int fall_delay;
-	unsigned int rise_delay;
-	unsigned int debounce0;
-	unsigned int debounce1;
-	unsigned int debounce3;
-	unsigned int debounce4;
-	unsigned int eint_pwm_width;
-	unsigned int eint_pwm_thresh;
-	unsigned int eint_debounce0;
-	unsigned int eint_debounce1;
-	unsigned int eint_debounce2;
-	unsigned int eint_debounce3;
-	unsigned int eint_inverter_debounce;
-
-};
-
 struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	struct pwm_deb_settings *pwm_deb;
 	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:28 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:28 -0300
Subject: [PATCH v4 13/19] ASoC: mediatek: mt6359-accdet: Always use eint
 detect mode 4
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-13-e5ffa5ee9991@collabora.com>

The driver currently reads a mediatek,eint-detect-mode property from DT,
which determines certain register configurations. Since there are no
users of the property, it doesn't directly describe the hardware, and
the default value (4) is known to work across multiple boards, remove
the handling for this property and always assume mode 4 is used. The
property can be properly introduced in the binding in the future if
different boards actually need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 208 +++++++++++++--------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 70 insertions(+), 139 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 6728f1018c992fc9d4e4133dbaf091d256567683..83e65b6d5845dea00a8a77d68df4b7df1f62a87c 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -81,31 +81,22 @@ static void recover_eint_setting(struct mt6359_accdet *priv);
 
 static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches off */
-		regmap_update_bits(priv->regmap,
-				   RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-		/*select 500k, use internal resistor */
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT,
-				   BIT(RG_EINT0HIRENB_SFT));
+	/* ESD switches off */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT0CONFIGACCDET_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT,
+				   BIT(RG_EINT1CONFIGACCDET_SFT));
 	}
+	/*select 500k, use internal resistor */
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
 	return 0;
 }
 
@@ -123,18 +114,14 @@ static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
 	}
 
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* set DA stable signal */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* set DA stable signal */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
 	}
 	return 0;
 }
@@ -159,27 +146,19 @@ static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
 
 static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
-	if (priv->data->eint_detect_mode == 0x3 ||
-	    priv->data->eint_detect_mode == 0x4) {
-		/* ESD switches on */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   1 << 8, 1 << 8);
-	}
-	if (priv->data->eint_detect_mode == 0x4) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* disable RG_EINT0CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* disable RG_EINT1CONFIGACCDET */
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-		}
-		regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
-				   RG_EINT0HIRENB_MASK_SFT, 0);
+	/* ESD switches on */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* disable RG_EINT0CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* disable RG_EINT1CONFIGACCDET */
+		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
+				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
 	}
+	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
+			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
@@ -193,37 +172,30 @@ static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 				   ACCDET_EINT1_M_SW_EN_ADDR,
 				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
 	}
-	if (priv->data->eint_detect_mode == 0x4) {
+	if (priv->caps & ACCDET_PMIC_EINT0) {
 		/* enable eint0cen */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable eint0cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable eint1cen */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_DA_STABLE_ADDR,
-					   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-					   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-		}
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable eint1cen */
+		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
+				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
 	}
 
-	if (priv->data->eint_detect_mode != 0x1) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			/* enable inverter */
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		/* enable inverter */
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 }
 
@@ -534,13 +506,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
-				   &priv->data->eint_detect_mode);
-	if (ret) {
-		/* eint detection mode equals to EINT HW Mode */
-		priv->data->eint_detect_mode = 0x4;
-	}
-
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
 	if (ret)
 		tmp = 0;
@@ -592,31 +557,16 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->data->eint_detect_mode == 0x1) {
-		/* disable inverter detection */
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   0);
-		}
-	} else {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-					   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-					   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-		}
+	if (priv->caps & ACCDET_PMIC_EINT0) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
+	} else if (priv->caps & ACCDET_PMIC_EINT1) {
+		regmap_update_bits(priv->regmap,
+				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
+				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
+				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
 	}
 
 	if (priv->data->hp_eint_high) {
@@ -649,28 +599,10 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 	regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR,
 			   RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT));
 
-	if (priv->data->eint_detect_mode == 0x1 ||
-	    priv->data->eint_detect_mode == 0x2 ||
-	    priv->data->eint_detect_mode == 0x3) {
-		if (priv->caps & ACCDET_PMIC_EINT0) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT0CONFIGACCDET_ADDR,
-					   RG_EINT0CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT0CONFIGACCDET_SFT));
-		} else if (priv->caps & ACCDET_PMIC_EINT1) {
-			regmap_update_bits(priv->regmap,
-					   RG_EINT1CONFIGACCDET_ADDR,
-					   RG_EINT1CONFIGACCDET_MASK_SFT,
-					   BIT(RG_EINT1CONFIGACCDET_SFT));
-		}
-	}
-
-	if (priv->data->eint_detect_mode != 0x1) {
-		/* current detect set 0.25uA */
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << RG_ACCDETSPARE_SFT,
-				   0x3 << RG_ACCDETSPARE_SFT);
-	}
+	/* current detect set 0.25uA */
+	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
+			   0x3 << RG_ACCDETSPARE_SFT,
+			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
 		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
 }
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 287201eebe0330fa170093fd6192bf5694c30469..ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -54,7 +54,6 @@ struct dts_data {
 	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
-	unsigned int eint_detect_mode;
 	unsigned int eint_comp_vth;
 };
 

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:29 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:29 -0300
Subject: [PATCH v4 14/19] ASoC: mediatek: mt6359-accdet: Always set
 micbias1 to 2.8V
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-14-e5ffa5ee9991@collabora.com>

The driver currently reads a mediatek,mic-vol property from DT to
determine the micbias1 setting to configure in hardware. Since there are
no current users of the property and the default value (2.8V) is known
to work on multiple boards, remove the code handling this property and
instead always configure the micbias1 to 2.8V. The property can be
properly introduced in the binding in the future if it really turns out
that different boards need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 23 +++--------------------
 sound/soc/codecs/mt6359-accdet.h |  1 -
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 83e65b6d5845dea00a8a77d68df4b7df1f62a87c..a31e084560c7643b14fb71871699e3167075d9d9 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-vol",
-				   &priv->data->mic_vol);
-	if (ret)
-		priv->data->mic_vol = 8;
-
 	ret = of_property_read_u32(node, "mediatek,mic-mode",
 				   &priv->data->mic_mode);
 	if (ret)
@@ -657,22 +652,10 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 		      ACCDET_RISE_DELAY));
 
 	regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, &reg);
-	if (priv->data->mic_vol <= 7) {
-		/* micbias1 <= 2.7V */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 8) {
-		/* micbias1 = 2.8v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
+	/* micbias1 = 2.8v */
+	regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
+		     reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	} else if (priv->data->mic_vol == 9) {
-		/* micbias1 = 2.85v */
-		regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-			     reg | (1 << RG_AUDMICBIAS1HVEN_SFT) |
-			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
-	}
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
 	if (priv->data->mic_mode == HEADSET_MODE_1) {
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index ff5cd6ea1b06f045b6e1b9f6bc53ef80d78e3b92..46dcd4759230a5190434b9b7c785e8b9ed12fd3d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -51,7 +51,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_vol;
 	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:30 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:30 -0300
Subject: [PATCH v4 15/19] ASoC: mediatek: mt6359-accdet: Always configure
 hardware as mic-mode 2
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-15-e5ffa5ee9991@collabora.com>

The driver currently reads a mediatek,mic-mode property from DT to
determine certain register configurations. Since there are no current
users of the property, the property doesn't directly reflect the
hardware  and the default value (2) is known to work on
multiple boards, remove the code handling this property and instead
always configure the hardware according to the known to work default.
This property can be properly introduced in the binding in the future
if it really turns out that different boards need different
configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 43 ++++++----------------------------------
 sound/soc/codecs/mt6359-accdet.h |  5 -----
 2 files changed, 6 insertions(+), 42 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index a31e084560c7643b14fb71871699e3167075d9d9..12697b02faff1be39317116cd7d8ffa359f2cd4e 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -494,11 +494,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	if (!node)
 		return -EINVAL;
 
-	ret = of_property_read_u32(node, "mediatek,mic-mode",
-				   &priv->data->mic_mode);
-	if (ret)
-		priv->data->mic_mode = 2;
-
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
 	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
@@ -658,38 +653,12 @@ static void mt6359_accdet_init(struct mt6359_accdet *priv)
 			     RG_AUDMICBIAS1LOWPEN_MASK_SFT);
 	/* mic mode setting */
 	regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, &reg);
-	if (priv->data->mic_mode == HEADSET_MODE_1) {
-		/* ACC mode*/
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE1);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   RG_ANALOGFDEN_MASK_SFT,
-				   BIT(RG_ANALOGFDEN_SFT));
-		regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
-				   0x3 << 11, 0x3 << 11);
-	} else if (priv->data->mic_mode == HEADSET_MODE_2) {
-		/* DCC mode Low cost mode without internal bias */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE2);
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	} else if (priv->data->mic_mode == HEADSET_MODE_6) {
-		/* DCC mode Low cost mode with internal bias,
-		 * bit8 = 1 to use internal bias
-		 */
-		regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
-			     reg | RG_ACCDET_MODE_ANA11_MODE6);
-		regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
-				   RG_AUDMICBIAS1DCSW1PEN_MASK_SFT,
-				   BIT(RG_AUDMICBIAS1DCSW1PEN_SFT));
-		/* enable analog fast discharge */
-		regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
-				   0x3 << RG_ANALOGFDEN_SFT,
-				   0x3 << RG_ANALOGFDEN_SFT);
-	}
+	/* DCC mode Low cost mode without internal bias */
+	regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
+		     reg | RG_ACCDET_MODE_ANA11_MODE2);
+	/* enable analog fast discharge */
+	regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
+			   0x3 << RG_ANALOGFDEN_SFT, 0x3 << RG_ANALOGFDEN_SFT);
 
 	config_eint_init_by_mode(priv);
 	config_digital_init_by_mode(priv);
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 46dcd4759230a5190434b9b7c785e8b9ed12fd3d..579373807c414130b2a7384db4978e01cf1d046c 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -12,10 +12,6 @@
 
 #define ACCDET_DEVNAME "accdet"
 
-#define HEADSET_MODE_1		(1)
-#define HEADSET_MODE_2		(2)
-#define HEADSET_MODE_6		(6)
-
 #define MT6359_ACCDET_NUM_BUTTONS 4
 #define MT6359_ACCDET_JACK_MASK (SND_JACK_HEADPHONE | \
 				SND_JACK_HEADSET | \
@@ -51,7 +47,6 @@ enum {
 };
 
 struct dts_data {
-	unsigned int mic_mode;
 	bool hp_eint_high;
 	unsigned int eint_comp_vth;
 };

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:31 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:31 -0300
Subject: [PATCH v4 16/19] ASoC: mediatek: mt6359-accdet: Always set
 comp-vth to 1.6V
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-16-e5ffa5ee9991@collabora.com>

The driver currently reads a mediatek,eint-comp-vth property from DT to
determine the voltage threshold of the EINT comparator. Since there are
no current users of the property and setting it to 1.6V is known to work
across multiple boards, remove the code handling this property and
instead always configure it to 1.6V. The property can be properly
introduced in the binding in the future if it really turns out that
different boards need different configurations.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 8 ++------
 sound/soc/codecs/mt6359-accdet.h | 1 -
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 12697b02faff1be39317116cd7d8ffa359f2cd4e..3f6a97e8de8d174e59e512d53135fadc5765b5c1 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -61,6 +61,7 @@
 #define ACCDET_EINT_INVERTER_DEBOUNCE_256MS 0xe
 #define ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS 4
 #define ACCDET_EINT_CMPMEN_PWM_THRESH_2MS 1
+#define ACCDET_EINT_COMP_VTH_1600MV 2
 
 static struct platform_driver mt6359_accdet_driver;
 static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
@@ -506,11 +507,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 	else if (tmp == 2)
 		priv->caps |= ACCDET_PMIC_BI_EINT;
 
-	ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
-				   &priv->data->eint_comp_vth);
-	if (ret)
-		priv->data->eint_comp_vth = 0x0;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -594,7 +590,7 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 			   0x3 << RG_ACCDETSPARE_SFT,
 			   0x3 << RG_ACCDETSPARE_SFT);
 	regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
-		     val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
+		     val | ACCDET_EINT_COMP_VTH_1600MV << RG_EINTCOMPVTH_SFT);
 }
 
 static void mt6359_accdet_init(struct mt6359_accdet *priv)
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 579373807c414130b2a7384db4978e01cf1d046c..288b8fbf7c5efaee6520a2c0a5845e156f3b805d 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -48,7 +48,6 @@ enum {
 
 struct dts_data {
 	bool hp_eint_high;
-	unsigned int eint_comp_vth;
 };
 
 struct mt6359_accdet {

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:32 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:32 -0300
Subject: [PATCH v4 17/19] ASoC: mediatek: mt6359-accdet: Always use EINT0
 IRQ
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-17-e5ffa5ee9991@collabora.com>

The ACCDET block can generate two distinct EINT interrupts: EINT0 and
EINT1, and which is enabled is currently determined by mediatek,eint-num
property in DT. However, only EINT0 is used on the boards that are
known to have working ACCDET. Since there are no current users of the
property, remove its handling and instead always enable EINT0. The
property can be properly introduced in the binding in the future if it
really turns out that other boards require EINT1.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.c | 187 +++++++++------------------------------
 sound/soc/codecs/mt6359-accdet.h |   1 -
 2 files changed, 43 insertions(+), 145 deletions(-)

diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 3f6a97e8de8d174e59e512d53135fadc5765b5c1..b1e63f3f7fa44687b1cac47c0e33f68a28e15a47 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -31,10 +31,6 @@
 #define REGISTER_VAL(x)	((x) - 1)
 
 /* mt6359 accdet capability */
-#define ACCDET_PMIC_EINT0		BIT(2)
-#define ACCDET_PMIC_EINT1		BIT(3)
-#define ACCDET_PMIC_BI_EINT		BIT(4)
-
 #define ACCDET_PMIC_RSV_EINT		BIT(7)
 
 #define ACCDET_RSV_KEY			BIT(11)
@@ -84,17 +80,10 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches off */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 0);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT0CONFIGACCDET_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT,
-				   BIT(RG_EINT1CONFIGACCDET_SFT));
-	}
+	/* enable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT,
+			   BIT(RG_EINT0CONFIGACCDET_SFT));
 	/*select 500k, use internal resistor */
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, BIT(RG_EINT0HIRENB_SFT));
@@ -103,27 +92,13 @@ static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
 
 static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
-	}
+	/* disable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* set DA stable signal */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
-	}
+	/* set DA stable signal */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
 	return 0;
 }
 
@@ -149,55 +124,26 @@ static void recover_eint_analog_setting(struct mt6359_accdet *priv)
 {
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, 1 << 8, 1 << 8);
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* disable RG_EINT0CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
-				   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* disable RG_EINT1CONFIGACCDET */
-		regmap_update_bits(priv->regmap, RG_EINT1CONFIGACCDET_ADDR,
-				   RG_EINT1CONFIGACCDET_MASK_SFT, 0);
-	}
+	/* disable RG_EINT0CONFIGACCDET */
+	regmap_update_bits(priv->regmap, RG_EINT0CONFIGACCDET_ADDR,
+			   RG_EINT0CONFIGACCDET_MASK_SFT, 0);
 	regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
 			   RG_EINT0HIRENB_MASK_SFT, 0);
 }
 
 static void recover_eint_digital_setting(struct mt6359_accdet *priv)
 {
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_M_SW_EN_ADDR,
-				   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_M_SW_EN_ADDR,
-				   ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
-	}
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable eint0cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable eint1cen */
-		regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
-				   ACCDET_EINT1_CEN_STABLE_MASK_SFT,
-				   BIT(ACCDET_EINT1_CEN_STABLE_SFT));
-	}
-
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		/* enable inverter */
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_M_SW_EN_ADDR,
+			   ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
+	/* enable eint0cen */
+	regmap_update_bits(priv->regmap, ACCDET_DA_STABLE_ADDR,
+			   ACCDET_EINT0_CEN_STABLE_MASK_SFT,
+			   BIT(ACCDET_EINT0_CEN_STABLE_SFT));
+
+	/* enable inverter */
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 }
 
 static void recover_eint_setting(struct mt6359_accdet *priv)
@@ -486,10 +432,8 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
 
 static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 {
-	int ret;
 	struct device *dev = priv->dev;
 	struct device_node *node = NULL;
-	unsigned int tmp = 0;
 
 	node = of_get_child_by_name(dev->parent->of_node, "accdet");
 	if (!node)
@@ -497,16 +441,6 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 
 	priv->data->hp_eint_high = of_property_read_bool(node, "mediatek,hp-eint-high");
 
-	ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
-	if (ret)
-		tmp = 0;
-	if (tmp == 0)
-		priv->caps |= ACCDET_PMIC_EINT0;
-	else if (tmp == 1)
-		priv->caps |= ACCDET_PMIC_EINT1;
-	else if (tmp == 2)
-		priv->caps |= ACCDET_PMIC_BI_EINT;
-
 	of_node_put(node);
 	dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
 
@@ -520,13 +454,8 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 		     (ACCDET_EINT_CMPMEN_PWM_WIDTH_400MS << 4 |
 		      ACCDET_EINT_CMPMEN_PWM_THRESH_2MS));
 	/* DA signal stable */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT0_STABLE_VAL);
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
-			     ACCDET_EINT1_STABLE_VAL);
-	}
+	regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
+		     ACCDET_EINT0_STABLE_VAL);
 	/* after receive n+1 number, interrupt issued. */
 	regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR,
 			   ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT,
@@ -543,17 +472,9 @@ static void config_digital_init_by_mode(struct mt6359_accdet *priv)
 	/* enable PWM */
 	regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
 	/* enable inverter detection */
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT0_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap,
-				   ACCDET_EINT1_INVERTER_SW_EN_ADDR,
-				   ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
-				   BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, ACCDET_EINT0_INVERTER_SW_EN_ADDR,
+			   ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
+			   BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
 
 	if (priv->data->hp_eint_high) {
 		/* EINT polarity inverse */
@@ -571,13 +492,8 @@ static void config_eint_init_by_mode(struct mt6359_accdet *priv)
 {
 	unsigned int val = 0;
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR,
-				   RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT));
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR,
-				   RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT));
-	}
+	regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR, RG_EINT0EN_MASK_SFT,
+			   BIT(RG_EINT0EN_SFT));
 	/* ESD switches on */
 	regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
 			   1 << 8, 1 << 8);
@@ -727,35 +643,18 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (priv->caps & ACCDET_PMIC_EINT0) {
-		priv->accdet_eint0 = platform_get_irq(pdev, 1);
-		if (priv->accdet_eint0 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint0,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT0", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint0 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
-		}
-	} else if (priv->caps & ACCDET_PMIC_EINT1) {
-		priv->accdet_eint1 = platform_get_irq(pdev, 2);
-		if (priv->accdet_eint1 >= 0) {
-			ret = devm_request_threaded_irq(&pdev->dev,
-							priv->accdet_eint1,
-							NULL, mt6359_accdet_irq,
-							IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-							"ACCDET_EINT1", priv);
-			if (ret) {
-				dev_err(&pdev->dev,
-					"Failed to request eint1 IRQ (%d)\n",
-					ret);
-				return ret;
-			}
+	priv->accdet_eint0 = platform_get_irq(pdev, 1);
+	if (priv->accdet_eint0 >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+						priv->accdet_eint0,
+						NULL, mt6359_accdet_irq,
+						IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+						"ACCDET_EINT0", priv);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request eint0 IRQ (%d)\n",
+				ret);
+			return ret;
 		}
 	}
 
diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index 288b8fbf7c5efaee6520a2c0a5845e156f3b805d..4156cbc7f0a1744226d5f28746bd13fec6c615b4 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -58,7 +58,6 @@ struct mt6359_accdet {
 	unsigned int caps;
 	int accdet_irq;
 	int accdet_eint0;
-	int accdet_eint1;
 	struct mutex res_lock; /* lock protection */
 	bool jack_plugged;
 	unsigned int jack_type;

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:33 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:33 -0300
Subject: [PATCH v4 18/19] arm64: dts: mt6359: Add accessory detect node
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-18-e5ffa5ee9991@collabora.com>

Add audio jack detection node. PMIC accessory detect driver will
create an input device that will send key events on jack
insertion/removal or accessory device key presses.

Co-developed-by: Andrew Perepech <andrew.perepech at mediatek.com>
Signed-off-by: Andrew Perepech <andrew.perepech at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Macpaul Lin <macpaul.lin at mediatek.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/boot/dts/mediatek/mt6359.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
index 7b10f9c59819a9ad02319f00938f35c931091f9f..e24e4aeb3b9cafa2af56c62bc4c549df27d0ec73 100644
--- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
@@ -15,6 +15,10 @@ pmic_adc: adc {
 			#io-channel-cells = <1>;
 		};
 
+		accdet: accdet {
+			compatible = "mediatek,mt6359-accdet";
+		};
+
 		mt6359codec: audio-codec {
 			compatible = "mediatek,mt6359-codec";
 		};

-- 
2.48.1



From nfraprado at collabora.com  Wed Mar  5 10:58:34 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Wed, 05 Mar 2025 15:58:34 -0300
Subject: [PATCH v4 19/19] arm64: defconfig: Enable MT6359 ACCDET
In-Reply-To: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
Message-ID: <20250305-mt6359-accdet-dts-v4-19-e5ffa5ee9991@collabora.com>

Enable support for the ACCDET block in the MT6359 PMIC, which provides
jack detection capabilities to MediaTek platforms.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db29822036d25a7228f8936e2ad613b208..d4a6eeec8ba0db110dd831e146716a0e50cc294f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1066,6 +1066,7 @@ CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_SOC_WSA881X=m
 CONFIG_SND_SOC_WSA883X=m
 CONFIG_SND_SOC_WSA884X=m
+CONFIG_SND_SOC_MT6359_ACCDET=m
 CONFIG_SND_SOC_NAU8822=m
 CONFIG_SND_SOC_LPASS_WSA_MACRO=m
 CONFIG_SND_SOC_LPASS_VA_MACRO=m

-- 
2.48.1



From krzysztof.kozlowski at linaro.org  Wed Mar  5 11:05:50 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 20:05:50 +0100
Subject: (subset) [PATCH v4 1/7] dt-bindings: soc: samsung: exynos-pmu:
 add exynos7870-pmu compatible
In-Reply-To: <20250301-exynos7870-v4-1-2925537f9b2a@disroot.org>
References: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
 <20250301-exynos7870-v4-1-2925537f9b2a@disroot.org>
Message-ID: <174120155027.74217.562001377328469243.b4-ty@linaro.org>


On Sat, 01 Mar 2025 01:16:49 +0530, Kaustabh Chakraborty wrote:
> Document the compatible string for the Exynos7870 PMU. It's compatible
> with the Exynos7 PMU design. It handles syscon reboot, syscon reboot mode,
> as well as other system control registers (i.e registers for the USB PHY).
> 
> 

Applied, thanks!

[1/7] dt-bindings: soc: samsung: exynos-pmu: add exynos7870-pmu compatible
      https://git.kernel.org/krzk/linux/c/bf869ecfb8d3d0fef07ed2752df93c977cc257b6

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Wed Mar  5 11:05:52 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 20:05:52 +0100
Subject: (subset) [PATCH v4 3/7] soc: samsung: exynos-chipid: add
 support for exynos7870
In-Reply-To: <20250301-exynos7870-v4-3-2925537f9b2a@disroot.org>
References: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
 <20250301-exynos7870-v4-3-2925537f9b2a@disroot.org>
Message-ID: <174120155205.74217.13161571019009381202.b4-ty@linaro.org>


On Sat, 01 Mar 2025 01:16:51 +0530, Kaustabh Chakraborty wrote:
> Add the product ID of Exynos7870 (S5E7870) to the existing list.
> 
> 

Applied, thanks!

[3/7] soc: samsung: exynos-chipid: add support for exynos7870
      https://git.kernel.org/krzk/linux/c/13a24175005fad410464bee482ed58af144ba250

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From robdclark at gmail.com  Wed Mar  5 11:07:00 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:07:00 -0800
Subject: [PATCH v4 5/5] drm/msm: Temporarily disable stall-on-fault after
 a page fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-5-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com> <20250304-msm-gpu-fault-fixes-next-v4-5-be14be37f4c3@gmail.com>
Message-ID: <CAF6AEGufRP9NuqC1gYy6jrQ9z+XqGFd7KNsbQw8C8NscSOJnJQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> When things go wrong, the GPU is capable of quickly generating millions
> of faulting translation requests per second. When that happens, in the
> stall-on-fault model each access will stall until it wins the race to
> signal the fault and then the RESUME register is written. This slows
> processing page faults to a crawl as the GPU can generate faults much
> faster than the CPU can acknowledge them. It also means that all
> available resources in the SMMU are saturated waiting for the stalled
> transactions, so that other transactions such as transactions generated
> by the GMU, which shares a context bank with the GPU, cannot proceed.

Nit, the GMU does not actually share a cb.. looking on x1e80100.dtsi,
the GMU has cb 5 and gpu has 0 and 1.  (Currently we just use the
first, but I guess the 2nd would be used if we supported protected
content?)

fwiw, you can read this from dtsi, ie. in the GMU node, "iommus =
<&adreno_smmu 5 0x0>;"

> This causes a GMU watchdog timeout, which leads to a failed reset
> because GX cannot collapse when there is a transaction pending and a
> permanently hung GPU.
>
> On older platforms with qcom,smmu-v2, it seems that when one transaction
> is stalled subsequent faulting transactions are terminated, which avoids
> this problem, but the MMU-500 follows the spec here.
>
> To work around these problem, disable stall-on-fault as soon as we get a
> page fault until a cooldown period after pagefaults stop. This allows
> the GMU some guaranteed time to continue working. We only use
> stall-on-fault to halt the GPU while we collect a devcoredump and we
> always terminate the transaction afterward, so it's fine to miss some
> subsequent page faults. We also keep it disabled so long as the current
> devcoredump hasn't been deleted, because in that case we likely won't
> capture another one if there's a fault.
>
> After this commit HFI messages still occasionally time out, because the
> crashdump handler doesn't run fast enough to let the GMU resume, but the
> driver seems to recover from it. This will probably go away after the
> HFI timeout is increased.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 ++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  4 ++++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 42 ++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h | 24 +++++++++++++++++++
>  drivers/gpu/drm/msm/msm_iommu.c         |  9 +++++++
>  drivers/gpu/drm/msm/msm_mmu.h           |  1 +
>  6 files changed, 81 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 71dca78cd7a5324e9ff5b14f173e2209fa42e196..670141531112c9d29cef8ef1fd51b74759fdd6d2 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>         struct msm_ringbuffer *ring = submit->ring;
>         unsigned int i, ibs = 0;
>
> +       adreno_check_and_reenable_stall(adreno_gpu);
> +
>         if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
>                 ring->cur_ctx_seqno = 0;
>                 a5xx_submit_in_rb(gpu, submit);
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 0ae29a7c8a4d3f74236a35cc919f69d5c0a384a0..5a34cd2109a2d74c92841448a61ccb0d4f34e264 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -212,6 +212,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>         struct msm_ringbuffer *ring = submit->ring;
>         unsigned int i, ibs = 0;
>
> +       adreno_check_and_reenable_stall(adreno_gpu);
> +
>         a6xx_set_pagetable(a6xx_gpu, ring, submit);
>
>         get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
> @@ -335,6 +337,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>         struct msm_ringbuffer *ring = submit->ring;
>         unsigned int i, ibs = 0;
>
> +       adreno_check_and_reenable_stall(adreno_gpu);
> +
>         /*
>          * Toggle concurrent binning for pagetable switch and set the thread to
>          * BR since only it can execute the pagetable switch packets.
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 1238f326597808eb28b4c6822cbd41a26e555eb9..bac586101dc0494f46b069a8440a45825dfe9b5e 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -246,16 +246,53 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
>         return SZ_4G;
>  }
>
> +void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
> +{
> +       struct msm_gpu *gpu = &adreno_gpu->base;
> +       unsigned long flags;
> +
> +       /*
> +        * Wait until the cooldown period has passed and we would actually
> +        * collect a crashdump to re-enable stall-on-fault.
> +        */
> +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, flags);
> +       if (!adreno_gpu->stall_enabled &&
> +                       ktime_after(ktime_get(), adreno_gpu->stall_reenable_time) &&
> +                       !READ_ONCE(gpu->crashstate)) {
> +               adreno_gpu->stall_enabled = true;
> +
> +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
> +       }
> +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, flags);
> +}
> +
>  #define ARM_SMMU_FSR_TF                 BIT(1)
>  #define ARM_SMMU_FSR_PF                        BIT(3)
>  #define ARM_SMMU_FSR_EF                        BIT(4)
> +#define ARM_SMMU_FSR_SS                        BIT(30)
>
>  int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
>                          struct adreno_smmu_fault_info *info, const char *block,
>                          u32 scratch[4])
>  {
> +       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>         const char *type = "UNKNOWN";
> -       bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
> +       bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
> +               !READ_ONCE(gpu->crashstate);
> +       unsigned long irq_flags;
> +
> +       /*
> +        * In case there is a subsequent storm of pagefaults, disable
> +        * stall-on-fault for at least half a second.
> +        */
> +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, irq_flags);
> +       if (adreno_gpu->stall_enabled) {
> +               adreno_gpu->stall_enabled = false;
> +
> +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
> +       }
> +       adreno_gpu->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
> +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, irq_flags);
>
>         /*
>          * If we aren't going to be resuming later from fault_worker, then do
> @@ -1143,6 +1180,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
>                 adreno_gpu->info->inactive_period);
>         pm_runtime_use_autosuspend(dev);
>
> +       spin_lock_init(&adreno_gpu->fault_stall_lock);
> +       adreno_gpu->stall_enabled = true;
> +
>         return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
>                         gpu_name, &adreno_gpu_config);
>  }
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> index dcf454629ce037b2a8274a6699674ad754ce1f07..a528036b46216bd898f6d48c5fb0555c4c4b053b 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> @@ -205,6 +205,28 @@ struct adreno_gpu {
>         /* firmware: */
>         const struct firmware *fw[ADRENO_FW_MAX];
>
> +       /**
> +        * fault_stall_lock:

nit, @fault_stall_lock:  And for
fault_stall_reenable_time/stall_enabled, it wouldn't hurt to add
something along the lines of "Protected by @fault_stall_lock".  I've
been slowly trying to improve the comment docs over time, I have some
of that in my vmbind patchset.

Anyways, with those nits addressed, r-b

BR,
-R

> +        *
> +        * Serialize changes to stall-on-fault state.
> +        */
> +       spinlock_t fault_stall_lock;
> +
> +       /**
> +        * fault_stall_reenable_time:
> +        *
> +        * if stall_enabled is false, when to reenable stall-on-fault.
> +        */
> +       ktime_t stall_reenable_time;
> +
> +       /**
> +        * stall_enabled:
> +        *
> +        * Whether stall-on-fault is currently enabled.
> +        */
> +       bool stall_enabled;
> +
> +
>         struct {
>                 /**
>                  * @rgb565_predicator: Unknown, introduced with A650 family,
> @@ -629,6 +651,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
>                          struct adreno_smmu_fault_info *info, const char *block,
>                          u32 scratch[4]);
>
> +void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
> +
>  int adreno_read_speedbin(struct device *dev, u32 *speedbin);
>
>  /*
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index 2a94e82316f95c5f9dcc37ef0a4664a29e3492b2..8d5380e6dcc217c7c209b51527bf15748b3ada71 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
> @@ -351,6 +351,14 @@ static void msm_iommu_resume_translation(struct msm_mmu *mmu)
>                 adreno_smmu->resume_translation(adreno_smmu->cookie, true);
>  }
>
> +static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
> +{
> +       struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
> +
> +       if (adreno_smmu->set_stall)
> +               adreno_smmu->set_stall(adreno_smmu->cookie, enable);
> +}
> +
>  static void msm_iommu_detach(struct msm_mmu *mmu)
>  {
>         struct msm_iommu *iommu = to_msm_iommu(mmu);
> @@ -399,6 +407,7 @@ static const struct msm_mmu_funcs funcs = {
>                 .unmap = msm_iommu_unmap,
>                 .destroy = msm_iommu_destroy,
>                 .resume_translation = msm_iommu_resume_translation,
> +               .set_stall = msm_iommu_set_stall,
>  };
>
>  struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
> diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
> index 88af4f490881f2a6789ae2d03e1c02d10046331a..2694a356a17904e7572b767b16ed0cee806406cf 100644
> --- a/drivers/gpu/drm/msm/msm_mmu.h
> +++ b/drivers/gpu/drm/msm/msm_mmu.h
> @@ -16,6 +16,7 @@ struct msm_mmu_funcs {
>         int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
>         void (*destroy)(struct msm_mmu *mmu);
>         void (*resume_translation)(struct msm_mmu *mmu);
> +       void (*set_stall)(struct msm_mmu *mmu, bool enable);
>  };
>
>  enum msm_mmu_type {
>
> --
> 2.47.1
>


From krzk at kernel.org  Wed Mar  5 11:08:05 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:08:05 +0100
Subject: [PATCH v4 0/7] Add support for the Exynos7870 SoC, along with
 three devices
In-Reply-To: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
References: <20250301-exynos7870-v4-0-2925537f9b2a@disroot.org>
Message-ID: <de3cc07a-e2f2-475d-9418-2621cb0a5d2c@kernel.org>

On 28/02/2025 20:46, Kaustabh Chakraborty wrote:
> Additional features implemented in this series include:
>  * I2C	- touchscreen, IIO sensors, etc.
>  * UART	- bluetooth and serial debugging
>  * MMC	- eMMC, Wi-Fi SDIO, SDCard
>  * USB	- micro-USB 2.0 interface
> 
> Build dependencies are in these sub-series:
>  * bootmode	  	- https://lore.kernel.org/all/20250204-exynos7870-bootmode-v1-1-0f17b3033c2d at disroot.org/
>  * pmu-clocks		- https://lore.kernel.org/all/20250301-exynos7870-pmu-clocks-v4-0-0f3e73b10db7 at disroot.org/
> 
> Other related sub-series:
>  * gpu			R https://lore.kernel.org/all/20250204-exynos7870-gpu-v1-1-0db4c163a030 at disroot.org/
>  * i2c	      		A https://lore.kernel.org/all/20250204-exynos7870-i2c-v1-0-63d67871ab7e at disroot.org/
>  * mmc			- https://lore.kernel.org/all/20250219-exynos7870-mmc-v2-0-b4255a3e39ed at disroot.org/
>  * pinctrl	  	- https://lore.kernel.org/all/20250301-exynos7870-pinctrl-v3-0-ba1da9d3cd2f at disroot.org/
>  * pmic-regulators	- https://lore.kernel.org/all/20250301-exynos7870-pmic-regulators-v3-0-808d0b47a564 at disroot.org/
>  * uart			R https://lore.kernel.org/all/20250219-exynos7870-uart-v2-1-c8c67f3a936c at disroot.org/
>  * usb			- https://lore.kernel.org/all/20250301-exynos7870-usb-v3-0-f01697165d19 at disroot.org/
>  * usbphy		- https://lore.kernel.org/all/20250219-exynos7870-usbphy-v2-0-b8ba4e7a72e9 at disroot.org/
> (Legend: [R]eviewed, [A]pplied)


Seems this will have to wait for the next cycle. I saw also some
checkpatch warnings, which anyway need fixing.

Best regards,
Krzysztof


From robdclark at gmail.com  Wed Mar  5 11:08:39 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:08:39 -0800
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com> <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
Message-ID: <CAF6AEGsd2DcdGdLX67RDNob9aev8wojwzyMqgwxMmN4RZiJKrA@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> In some cases drm/msm has to resume a stalled transaction directly in
> its fault handler. Experimentally this doesn't work on SMMU500 if the
> fault hasn't already been acknowledged by clearing FSR. Rather than
> trying to clear FSR in msm's fault handler and implementing a
> tricky handshake to avoid accidentally clearing FSR twice, we want to
> clear FSR before calling the fault handlers, but this means that the
> contents of registers can change underneath us in the fault handler and
> msm currently uses a private function to read the register contents for
> its own purposes in its fault handler, such as using the
> implementation-defined FSYNR1 to determine which block caused the fault.
> Fix this by making msm use the register values already read by arm-smmu
> itself before clearing FSR rather than messing around with reading
> registers directly.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>

Reviewed-by: Rob Clark <robdclark at gmail.com>

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
>  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
>  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
>  3 files changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index 6372f3e25c4bc24cb52f9233095170e8aa510a53..186d6ad4fd1c990398df4dec53f4d58ada9e658c 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -62,16 +62,15 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie,
>                 struct adreno_smmu_fault_info *info)
>  {
>         struct arm_smmu_domain *smmu_domain = (void *)cookie;
> -       struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> -       struct arm_smmu_device *smmu = smmu_domain->smmu;
> -
> -       info->fsr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSR);
> -       info->fsynr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR0);
> -       info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1);
> -       info->far = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_FAR);
> -       info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
> -       info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0);
> -       info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR);
> +       struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
> +
> +       info->fsr = cfi->fsr;
> +       info->fsynr0 = cfi->fsynr0;
> +       info->fsynr1 = cfi->fsynr1;
> +       info->far = cfi->iova;
> +       info->cbfrsynra = cfi->cbfrsynra;
> +       info->ttbr0 = cfi->ttbr0;
> +       info->contextidr = cfi->contextidr;
>  }
>
>  static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index a9213e0f1579d1e3be0bfba75eea1d5de23117de..498b96e95cb4fdb67c246ef13de1eb8f40d68f7d 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -453,26 +453,26 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
>
>  static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
>  {
> -       struct arm_smmu_context_fault_info cfi;
>         struct arm_smmu_domain *smmu_domain = dev;
> +       struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
>         struct arm_smmu_device *smmu = smmu_domain->smmu;
>         static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
>                                       DEFAULT_RATELIMIT_BURST);
>         int idx = smmu_domain->cfg.cbndx;
>         int ret;
>
> -       arm_smmu_read_context_fault_info(smmu, idx, &cfi);
> +       arm_smmu_read_context_fault_info(smmu, idx, cfi);
>
> -       if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
> +       if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
>                 return IRQ_NONE;
>
> -       ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -               cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +       ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
> +               cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>
>         if (ret == -ENOSYS && __ratelimit(&rs))
> -               arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> +               arm_smmu_print_context_fault_info(smmu, idx, cfi);
>
> -       arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
> +       arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
>         return IRQ_HANDLED;
>  }
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
>         ARM_SMMU_DOMAIN_NESTED,
>  };
>
> +struct arm_smmu_context_fault_info {
> +       unsigned long iova;
> +       u64 ttbr0;
> +       u32 fsr;
> +       u32 fsynr0;
> +       u32 fsynr1;
> +       u32 cbfrsynra;
> +       u32 contextidr;
> +};
> +
>  struct arm_smmu_domain {
>         struct arm_smmu_device          *smmu;
>         struct io_pgtable_ops           *pgtbl_ops;
> @@ -380,6 +390,7 @@ struct arm_smmu_domain {
>         const struct iommu_flush_ops    *flush_ops;
>         struct arm_smmu_cfg             cfg;
>         enum arm_smmu_domain_stage      stage;
> +       struct arm_smmu_context_fault_info cfi;
>         struct mutex                    init_mutex; /* Protects smmu pointer */
>         spinlock_t                      cb_lock; /* Serialises ATS1* ops and TLB syncs */
>         struct iommu_domain             domain;
> @@ -541,16 +552,6 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
>  void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
>  int arm_mmu500_reset(struct arm_smmu_device *smmu);
>
> -struct arm_smmu_context_fault_info {
> -       unsigned long iova;
> -       u64 ttbr0;
> -       u32 fsr;
> -       u32 fsynr0;
> -       u32 fsynr1;
> -       u32 cbfrsynra;
> -       u32 contextidr;
> -};
> -
>  void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
>                                       struct arm_smmu_context_fault_info *cfi);
>
>
> --
> 2.47.1
>


From robdclark at gmail.com  Wed Mar  5 11:09:10 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:09:10 -0800
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com> <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
Message-ID: <CAF6AEGvPvQuptuA07kDYdUDQh4iQA=g+c3t0OCjR1HfWZ6mSbg@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> This will be used by drm/msm for GPU page faults, replacing the manual
> register reading it does.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>

Reviewed-by: Rob Clark <robdclark at gmail.com>

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
>  drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
>  drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
>  3 files changed, 21 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>
>         if (list_empty(&tbu_list)) {
>                 ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -                                        cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +                                        cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>
>                 if (ret == -ENOSYS)
>                         arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>         phys_soft = ops->iova_to_phys(ops, cfi.iova);
>
>         tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -                                cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +                                cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>         if (!tmp || tmp == -EBUSY) {
>                 ret = IRQ_HANDLED;
>                 resume = ARM_SMMU_RESUME_TERMINATE;
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
>                                       struct arm_smmu_context_fault_info *cfi)
>  {
>         cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> +       cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
>         cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> -       cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> +       cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> +       cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
>         cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> +       cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
>  }
>
>  void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
> @@ -419,7 +422,7 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
>  {
>         dev_err(smmu->dev,
>                 "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
> -               cfi->fsr, cfi->iova, cfi->fsynr, cfi->cbfrsynra, idx);
> +               cfi->fsr, cfi->iova, cfi->fsynr0, cfi->cbfrsynra, idx);
>
>         dev_err(smmu->dev, "FSR    = %08x [%s%sFormat=%u%s%s%s%s%s%s%s%s], SID=0x%x\n",
>                 cfi->fsr,
> @@ -437,15 +440,15 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
>                 cfi->cbfrsynra);
>
>         dev_err(smmu->dev, "FSYNR0 = %08x [S1CBNDX=%u%s%s%s%s%s%s PLVL=%u]\n",
> -               cfi->fsynr,
> -               (u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr),
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
> -               (cfi->fsynr & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
> -               (u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr));
> +               cfi->fsynr0,
> +               (u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr0),
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
> +               (cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
> +               (u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr0));
>  }
>
>  static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
> @@ -464,7 +467,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
>                 return IRQ_NONE;
>
>         ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -               cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +               cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>
>         if (ret == -ENOSYS && __ratelimit(&rs))
>                 arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index e2aeb511ae903302e3c15d2cf5f22e2a26ac2346..d3bc77dcd4d40f25bc70f3289616fb866649b022 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -543,9 +543,12 @@ int arm_mmu500_reset(struct arm_smmu_device *smmu);
>
>  struct arm_smmu_context_fault_info {
>         unsigned long iova;
> +       u64 ttbr0;
>         u32 fsr;
> -       u32 fsynr;
> +       u32 fsynr0;
> +       u32 fsynr1;
>         u32 cbfrsynra;
> +       u32 contextidr;
>  };
>
>  void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
>
> --
> 2.47.1
>


From krzysztof.kozlowski at linaro.org  Wed Mar  5 11:09:34 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 20:09:34 +0100
Subject: [PATCH] clk: samsung: gs101: fix synchronous external abort in
 samsung_clk_save()
In-Reply-To: <20250303-clk-suspend-fix-v1-1-c2edaf66260f@linaro.org>
References: <20250303-clk-suspend-fix-v1-1-c2edaf66260f@linaro.org>
Message-ID: <174120177454.75135.6216013717633178470.b4-ty@linaro.org>


On Mon, 03 Mar 2025 13:11:21 +0000, Peter Griffin wrote:
> EARLY_WAKEUP_SW_TRIG_*_SET and EARLY_WAKEUP_SW_TRIG_*_CLEAR
> registers are only writeable. Attempting to read these registers
> during samsung_clk_save() causes a synchronous external abort.
> 
> Remove these 8 registers from cmu_top_clk_regs[] array so that
> system suspend gets further.
> 
> [...]

Applied, thanks!

[1/1] clk: samsung: gs101: fix synchronous external abort in samsung_clk_save()
      https://git.kernel.org/krzk/linux/c/f2052a4a62465c0037aef7ea7426bffdb3531e41

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From kw at linux.com  Wed Mar  5 11:09:55 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Thu, 6 Mar 2025 04:09:55 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250305182833.cgrwbrcwzjscxmku@thinkpad>
References: <20250304171154.njoygsvfd567pb66@thinkpad>
 <20250305173826.GA303920@bhelgaas>
 <20250305182833.cgrwbrcwzjscxmku@thinkpad>
Message-ID: <20250305190955.GK847772@rocinante>

Hello,

[...]
> > > Even though debugfs_init() failure is not supposed to fail the probe(),
> > > dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> > > failure would be canolically correct IMO.
> > 
> > I'm not sure about this.  What's the requirement to propagate
> > devm_kzalloc() failures?  I think devres will free any allocs that
> > were successful regardless.
> > 
> > IIUC, we resolved the Gray Hawk Single issue by changing
> > dwc_pcie_rasdes_debugfs_init() to return success without doing
> > anything when there's no RAS DES Capability.
> > 
> > But dwc_pcie_debugfs_init() can still return failure, and that still
> > causes dw_pcie_ep_init_registers() to fail, which breaks the "don't
> > propagate debugfs issues upstream" rule:
> > 
> >   int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> >   {
> >           ...
> >           ret = dwc_pcie_debugfs_init(pci);
> >           if (ret)
> >                   goto err_remove_edma;
> > 
> >           return 0;
> > 
> >   err_remove_edma:
> >           dw_pcie_edma_remove(pci);
> > 
> >           return ret;
> >   }
> > 
> > We can say that kzalloc() failure should "never" happen, and therefore
> > it's OK to fail the driver probe if it happens, but that doesn't seem
> > like a strong argument for breaking the "don't propagate debugfs
> > issues" rule.  And someday there may be other kinds of failures from
> > dwc_pcie_debugfs_init().
> > 
> 
> Fine with me. I was not too sure about propagating failure either.

What if we do this?

diff --git i/drivers/pci/controller/dwc/pcie-designware-debugfs.c w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
index 586a9d107434..fddf71f014c4 100644
--- i/drivers/pci/controller/dwc/pcie-designware-debugfs.c
+++ w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
@@ -162,7 +162,7 @@ void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
 	debugfs_remove_recursive(pci->debugfs->debug_dir);
 }

-int dwc_pcie_debugfs_init(struct dw_pcie *pci)
+void dwc_pcie_debugfs_init(struct dw_pcie *pci)
 {
 	char dirname[DWC_DEBUGFS_BUF_MAX];
 	struct device *dev = pci->dev;
@@ -174,17 +174,15 @@ int dwc_pcie_debugfs_init(struct dw_pcie *pci)
 	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
 	dir = debugfs_create_dir(dirname, NULL);
 	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
-	if (!debugfs)
-		return -ENOMEM;
+	if (!debugfs) {
+		dev_err(dev, "failed to allocate memory for debugfs\n");
+		return;
+	}

 	debugfs->debug_dir = dir;
 	pci->debugfs = debugfs;
 	err = dwc_pcie_rasdes_debugfs_init(pci, dir);
-	if (err) {
-		dev_err(dev, "failed to initialize RAS DES debugfs, err=%d\n",
-			err);
-		return err;
-	}
-
-	return 0;
+	if (err)
+		dev_warn(dev, "failed to initialize RAS DES debugfs, err=%d",
+			 err);
 }
diff --git i/drivers/pci/controller/dwc/pcie-designware-ep.c w/drivers/pci/controller/dwc/pcie-designware-ep.c
index c6e76a07c2c9..11ff292ca87d 100644
--- i/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ w/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -838,9 +838,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)

 	dw_pcie_ep_init_non_sticky_registers(pci);

-	ret = dwc_pcie_debugfs_init(pci);
-	if (ret)
-		goto err_remove_edma;
+	dwc_pcie_debugfs_init(pci);

 	return 0;

diff --git i/drivers/pci/controller/dwc/pcie-designware-host.c w/drivers/pci/controller/dwc/pcie-designware-host.c
index 2081e8c72d12..6501fb062c70 100644
--- i/drivers/pci/controller/dwc/pcie-designware-host.c
+++ w/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -548,9 +548,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (pp->ops->post_init)
 		pp->ops->post_init(pp);

-	ret = dwc_pcie_debugfs_init(pci);
-	if (ret)
-		goto err_stop_link;
+	dwc_pcie_debugfs_init(pci);

 	return 0;

diff --git i/drivers/pci/controller/dwc/pcie-designware.h w/drivers/pci/controller/dwc/pcie-designware.h
index 7f9807d4e5de..dd129718fb41 100644
--- i/drivers/pci/controller/dwc/pcie-designware.h
+++ w/drivers/pci/controller/dwc/pcie-designware.h
@@ -815,12 +815,11 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
 #endif

 #ifdef CONFIG_PCIE_DW_DEBUGFS
-int dwc_pcie_debugfs_init(struct dw_pcie *pci);
+void dwc_pcie_debugfs_init(struct dw_pcie *pci);
 void dwc_pcie_debugfs_deinit(struct dw_pcie *pci);
 #else
-static inline int dwc_pcie_debugfs_init(struct dw_pcie *pci)
+static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci)
 {
-	return 0;
 }
 static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
 {

I think this would be fine, especially given the rules around debugfs and
a quick look around Git history to see what the prefernce would be typically.

Thank you!

	Krzysztof


From robdclark at gmail.com  Wed Mar  5 11:09:52 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:09:52 -0800
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com> <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
Message-ID: <CAF6AEGszbZ_2J_LkkPMuCeQwma1xtO2=ZwWQcyrsxb+=qb-koQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> Up until now we have only called the set_stall callback during
> initialization when the device is off. But we will soon start calling it
> to temporarily disable stall-on-fault when the device is on, so handle
> that by checking if the device is on and writing SCTLR.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>

Reviewed-by: Rob Clark <robdclark at gmail.com>

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
>  {
>         struct arm_smmu_domain *smmu_domain = (void *)cookie;
>         struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> -       struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> +       struct arm_smmu_device *smmu = smmu_domain->smmu;
> +       struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> +       u32 mask = BIT(cfg->cbndx);
> +       bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> +       unsigned long flags;
>
>         if (enabled)
> -               qsmmu->stall_enabled |= BIT(cfg->cbndx);
> +               qsmmu->stall_enabled |= mask;
>         else
> -               qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> +               qsmmu->stall_enabled &= ~mask;
> +
> +       /*
> +        * If the device is on and we changed the setting, update the register.
> +        */
> +       if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> +               spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> +
> +               u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> +
> +               if (enabled)
> +                       reg |= ARM_SMMU_SCTLR_CFCFG;
> +               else
> +                       reg &= ~ARM_SMMU_SCTLR_CFCFG;
> +
> +               arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
> +
> +               spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
> +
> +               pm_runtime_put_autosuspend(smmu->dev);
> +       }
>  }
>
>  static void qcom_adreno_smmu_resume_translation(const void *cookie, bool terminate)
>
> --
> 2.47.1
>


From krzk at kernel.org  Wed Mar  5 11:12:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:12:32 +0100
Subject: [PATCH v2 2/2] clk: samsung: update PLL locktime for PLL142XX
 used on FSD platform
In-Reply-To: <c5cef589-8091-41ce-94e7-82b56ba4143f@kernel.org>
References: <20250225131918.50925-1-v.pavani@samsung.com>
 <CGME20250225132507epcas5p455347acbd580b26ee807e467d3a6a05e@epcas5p4.samsung.com>
 <20250225131918.50925-3-v.pavani@samsung.com>
 <c5cef589-8091-41ce-94e7-82b56ba4143f@kernel.org>
Message-ID: <cbbb1f9c-8361-43b1-a24b-afc5c91919e8@kernel.org>

On 01/03/2025 15:14, Krzysztof Kozlowski wrote:
> On 25/02/2025 14:19, Varada Pavani wrote:
>> Currently PLL142XX locktime is 270. As per spec, it should be 150. Hence
>> update PLL142XX controller locktime to 150.
>>
>> Cc: stable at vger.kernel.org
> 
> Fixes commit?

If this is a fix, commit msg should describe the bug. You decided to
drop the fixes tag, but you kept stable, so this makes no sense.

Best regards,
Krzysztof


From robdclark at gmail.com  Wed Mar  5 11:12:36 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:12:36 -0800
Subject: [PATCH v4 3/5] iommu/arm-smmu: Fix spurious interrupts with stall-on-fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-3-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com> <20250304-msm-gpu-fault-fixes-next-v4-3-be14be37f4c3@gmail.com>
Message-ID: <CAF6AEGsi1s4rO0_HSy44ikFGXNJAkBxfBMucRyGA+xokzOsP_A@mail.gmail.com>

On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> On some SMMUv2 implementations, including MMU-500, SMMU_CBn_FSR.SS
> asserts an interrupt. The only way to clear that bit is to resume the
> transaction by writing SMMU_CBn_RESUME, but typically resuming the
> transaction requires complex operations (copying in pages, etc.) that
> can't be done in IRQ context. drm/msm already has a problem, because
> its fault handler sometimes schedules a job to dump the GPU state and
> doesn't resume translation until this is complete.
>
> Work around this by disabling context fault interrupts until after the
> transaction is resumed. Because other context banks can share an IRQ
> line, we may still get an interrupt intended for another context bank,
> but in this case only SMMU_CBn_FSR.SS will be asserted and we can skip
> it assuming that interrupts are disabled which is accomplished by
> removing the bit from ARM_SMMU_CB_FSR_FAULT. SMMU_CBn_FSR.SS won't be
> asserted unless an external user enabled stall-on-fault, and they are
> expected to resume the translation and re-enable interrupts.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> Reviewed-by Robin Murphy <robin.murphy at arm.com>

Reviewed-by: Rob Clark <robdclark at gmail.com>

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 15 ++++++++++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 41 +++++++++++++++++++++++++++++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.h      |  1 -
>  3 files changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index 186d6ad4fd1c990398df4dec53f4d58ada9e658c..a428e53add08d451fb2152e3ab80e0fba936e214 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -90,12 +90,25 @@ static void qcom_adreno_smmu_resume_translation(const void *cookie, bool termina
>         struct arm_smmu_domain *smmu_domain = (void *)cookie;
>         struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
>         struct arm_smmu_device *smmu = smmu_domain->smmu;
> -       u32 reg = 0;
> +       u32 reg = 0, sctlr;
> +       unsigned long flags;
>
>         if (terminate)
>                 reg |= ARM_SMMU_RESUME_TERMINATE;
>
> +       spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> +
>         arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg);
> +
> +       /*
> +        * Re-enable interrupts after they were disabled by
> +        * arm_smmu_context_fault().
> +        */
> +       sctlr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> +       sctlr |= ARM_SMMU_SCTLR_CFIE;
> +       arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, sctlr);
> +
> +       spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
>  }
>
>  #define QCOM_ADRENO_SMMU_GPU_SID 0
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 498b96e95cb4fdb67c246ef13de1eb8f40d68f7d..284079ef95cd2deeb71816a284850523897badd8 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -466,13 +466,52 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
>         if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
>                 return IRQ_NONE;
>
> +       /*
> +        * On some implementations FSR.SS asserts a context fault
> +        * interrupt. We do not want this behavior, because resolving the
> +        * original context fault typically requires operations that cannot be
> +        * performed in IRQ context but leaving the stall unacknowledged will
> +        * immediately lead to another spurious interrupt as FSR.SS is still
> +        * set. Work around this by disabling interrupts for this context bank.
> +        * It's expected that interrupts are re-enabled after resuming the
> +        * translation.
> +        *
> +        * We have to do this before report_iommu_fault() so that we don't
> +        * leave interrupts disabled in case the downstream user decides the
> +        * fault can be resolved inside its fault handler.
> +        *
> +        * There is a possible race if there are multiple context banks sharing
> +        * the same interrupt and both signal an interrupt in between writing
> +        * RESUME and SCTLR. We could disable interrupts here before we
> +        * re-enable them in the resume handler, leaving interrupts enabled.
> +        * Lock the write to serialize it with the resume handler.
> +        */
> +       if (cfi->fsr & ARM_SMMU_CB_FSR_SS) {
> +               u32 val;
> +
> +               spin_lock(&smmu_domain->cb_lock);
> +               val = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_SCTLR);
> +               val &= ~ARM_SMMU_SCTLR_CFIE;
> +               arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, val);
> +               spin_unlock(&smmu_domain->cb_lock);
> +       }
> +
> +       /*
> +        * The SMMUv2 architecture specification says that if stall-on-fault is
> +        * enabled the correct sequence is to write to SMMU_CBn_FSR to clear
> +        * the fault and then write to SMMU_CBn_RESUME. Clear the interrupt
> +        * first before running the user's fault handler to make sure we follow
> +        * this sequence. It should be ok if there is another fault in the
> +        * meantime because we have already read the fault info.
> +        */
> +       arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
> +
>         ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
>                 cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>
>         if (ret == -ENOSYS && __ratelimit(&rs))
>                 arm_smmu_print_context_fault_info(smmu, idx, cfi);
>
> -       arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
>         return IRQ_HANDLED;
>  }
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index 411d807e0a7033833716635efb3968a0bd3ff237..4235b772c2cb032778816578c9e6644512543a5e 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -214,7 +214,6 @@ enum arm_smmu_cbar_type {
>                                          ARM_SMMU_CB_FSR_TLBLKF)
>
>  #define ARM_SMMU_CB_FSR_FAULT          (ARM_SMMU_CB_FSR_MULTI |        \
> -                                        ARM_SMMU_CB_FSR_SS |           \
>                                          ARM_SMMU_CB_FSR_UUT |          \
>                                          ARM_SMMU_CB_FSR_EF |           \
>                                          ARM_SMMU_CB_FSR_PF |           \
>
> --
> 2.47.1
>


From krzk at kernel.org  Wed Mar  5 11:14:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:14:20 +0100
Subject: [PATCH v2 2/2] clk: samsung: update PLL locktime for PLL142XX
 used on FSD platform
In-Reply-To: <cbbb1f9c-8361-43b1-a24b-afc5c91919e8@kernel.org>
References: <20250225131918.50925-1-v.pavani@samsung.com>
 <CGME20250225132507epcas5p455347acbd580b26ee807e467d3a6a05e@epcas5p4.samsung.com>
 <20250225131918.50925-3-v.pavani@samsung.com>
 <c5cef589-8091-41ce-94e7-82b56ba4143f@kernel.org>
 <cbbb1f9c-8361-43b1-a24b-afc5c91919e8@kernel.org>
Message-ID: <f386adc4-0572-4c43-ac67-e1a0837381db@kernel.org>

On 05/03/2025 20:12, Krzysztof Kozlowski wrote:
> On 01/03/2025 15:14, Krzysztof Kozlowski wrote:
>> On 25/02/2025 14:19, Varada Pavani wrote:
>>> Currently PLL142XX locktime is 270. As per spec, it should be 150. Hence
>>> update PLL142XX controller locktime to 150.
>>>
>>> Cc: stable at vger.kernel.org
>>
>> Fixes commit?
> 
> If this is a fix, commit msg should describe the bug. You decided to
> drop the fixes tag, but you kept stable, so this makes no sense.
> 
Also in the future: run checkpatch.

CHECK: Alignment should match open parenthesis

Best regards,
Krzysztof


From krzysztof.kozlowski at linaro.org  Wed Mar  5 11:15:06 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 20:15:06 +0100
Subject: (subset) [PATCH v2 2/2] clk: samsung: update PLL locktime for
 PLL142XX used on FSD platform
In-Reply-To: <20250225131918.50925-3-v.pavani@samsung.com>
References: <20250225131918.50925-1-v.pavani@samsung.com>
 <CGME20250225132507epcas5p455347acbd580b26ee807e467d3a6a05e@epcas5p4.samsung.com>
 <20250225131918.50925-3-v.pavani@samsung.com>
Message-ID: <174120210653.76378.2120670200586172536.b4-ty@linaro.org>


On Tue, 25 Feb 2025 18:49:18 +0530, Varada Pavani wrote:
> Currently PLL142XX locktime is 270. As per spec, it should be 150. Hence
> update PLL142XX controller locktime to 150.
> 
> 

Applied, thanks!

[2/2] clk: samsung: update PLL locktime for PLL142XX used on FSD platform
      https://git.kernel.org/krzk/linux/c/53517a70873c7a91675f7244768aad5006cc45de

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzk at kernel.org  Wed Mar  5 11:15:28 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:15:28 +0100
Subject: [PATCH v2 1/2] clk: samsung: Use samsung CCF common function
In-Reply-To: <20250225131918.50925-2-v.pavani@samsung.com>
References: <20250225131918.50925-1-v.pavani@samsung.com>
 <CGME20250225132447epcas5p4576a3dac624edbd5edc0a047e008de05@epcas5p4.samsung.com>
 <20250225131918.50925-2-v.pavani@samsung.com>
Message-ID: <6cbd3df3-344f-4c4f-886d-f0bb99b824da@kernel.org>

On 25/02/2025 14:19, Varada Pavani wrote:
> Use samsung CCF function which registers multiple clock providers using
> single function call samsung_cmu_register_clocks().
> 
> Signed-off-by: Varada Pavani <v.pavani at samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos4.c | 78 +++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 34 deletions(-)

Please run scripts/checkpatch.pl and fix reported warnings. After that,
run also `scripts/checkpatch.pl --strict` and (probably) fix more
warnings. Some warnings can be ignored, especially from --strict run,
but the code here looks like it needs a fix. Feel free to get in touch
if the warning is not clear.

Best regards,
Krzysztof


From nfraprado at collabora.com  Wed Mar  5 11:20:19 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Wed, 5 Mar 2025 16:20:19 -0300
Subject: [PATCH v2 3/3] ASoC: mediatek: mt8188-mt6359: Add accdet headset
 jack detect support
In-Reply-To: <7661b71a-9d5a-46c4-9639-0fba1b118b52@sirena.org.uk>
References: <20250304-mt8188-accdet-v2-0-27f496c4aede@collabora.com>
 <20250304-mt8188-accdet-v2-3-27f496c4aede@collabora.com>
 <59d0d382-1d15-46c4-b9e4-b66c32c188d3@collabora.com>
 <7661b71a-9d5a-46c4-9639-0fba1b118b52@sirena.org.uk>
Message-ID: <f3666689-42e3-4fb6-b113-68efbbea450f@notapiano>

On Wed, Mar 05, 2025 at 05:23:29PM +0000, Mark Brown wrote:
> On Wed, Mar 05, 2025 at 06:18:41PM +0100, AngeloGioacchino Del Regno wrote:
> 
> > Get to that mt6359-accdet.h header and:
> 
> > #if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET)
> 
> > function signatures
> 
> > #else
> 
> > static .... { return -EINVAL; (or whatever else) }
> 
> > #endif
> > 
> 
> It should probably be return 0 for the registration/unregistration
> functions so the caller doesn't fail if it checks the return code when
> the accessory detection is configured out.

Actually, given this function will only be called on platforms where the
accessory detection is present, I agree with Angelo that we should return an
error (and print the error message), so the user can easily figure out that the
accdet initialization failed due to the missing config.

Thanks,
N?colas


From catalin.marinas at arm.com  Wed Mar  5 11:28:41 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed,  5 Mar 2025 19:28:41 +0000
Subject: [PATCH 0/2] kselftest/arm64: mte: Minor fixes to the MTE hugetlb test
In-Reply-To: <20250221093331.2184245-1-catalin.marinas@arm.com>
References: <20250221093331.2184245-1-catalin.marinas@arm.com>
Message-ID: <174120291692.1422545.4418874969040688067.b4-ty@arm.com>

On Fri, 21 Feb 2025 09:33:29 +0000, Catalin Marinas wrote:
> The first patch makes use of the correct terminology for synchronous and
> asynchronous errors. The second patch checks whether PROT_MTE is
> supported on hugetlb mappings before continuing with the tests. Such
> support was added in 6.13 but people tend to use current kselftests on
> older kernels. Avoid the failure reporting on such kernels, just skip
> the tests.
> 
> [...]

Applied to arm64 (for-next/kselftest), thanks!

[1/2] kselftest/arm64: mte: Use the correct naming for tag check modes in check_hugetlb_options.c
      https://git.kernel.org/arm64/c/7ae95109c64d
[2/2] kselftest/arm64: mte: Skip the hugetlb tests if MTE not supported on such mappings
      https://git.kernel.org/arm64/c/306219d59b72

-- 
Catalin



From jgg at nvidia.com  Wed Mar  5 11:29:50 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 5 Mar 2025 15:29:50 -0400
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <Z8idOr67A0EG1/PN@Asurada-Nvidia>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <20250305165452.GY133783@nvidia.com>
 <Z8iWqOBga8Xdunac@Asurada-Nvidia>
 <20250305183151.GE133783@nvidia.com>
 <Z8idOr67A0EG1/PN@Asurada-Nvidia>
Message-ID: <20250305192950.GA354511@nvidia.com>

On Wed, Mar 05, 2025 at 10:51:38AM -0800, Nicolin Chen wrote:

> > I mean a normal S2 domain attaching to multiple devices on multiple
> > instances.
> 
> Oh, I haven't thought about a !nest_parent S2 case.
> 
> A nest_parent case will not allow devices to attach the S2 but
> always to a proxy nested S1 as we discussed previously. So, I
> think the implementation could be very different?

It could, and that is what you show here

But also, it could be the same implementation.

Jason


From willy at infradead.org  Wed Mar  5 11:30:57 2025
From: willy at infradead.org (Matthew Wilcox)
Date: Wed, 5 Mar 2025 19:30:57 +0000
Subject: [PATCH -next v1 3/3] kernel/events/uprobes:
 uprobe_write_opcode() rewrite
In-Reply-To: <20250304154846.1937958-4-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
Message-ID: <Z8imcXuuW6EK1aLY@casper.infradead.org>

On Tue, Mar 04, 2025 at 04:48:46PM +0100, David Hildenbrand wrote:
> +static bool orig_page_is_identical(struct vm_area_struct *vma,
> +		unsigned long vaddr, struct page *page, bool *pmd_mappable)
> +{
> +	const pgoff_t index = vaddr_to_offset(vma, vaddr) >> PAGE_SHIFT;
> +	struct page *orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
> +					       index);
> +	struct folio *orig_folio;
> +	bool identical;
> +
> +	if (!orig_page)
> +		return false;
> +	orig_folio = page_folio(orig_page);

I'd rather write this as:

	struct folio *orig_folio = filemap_get_folio(vma->vm_file->f_mapping,
			index);
	struct page *orig_page;

	if (IS_ERR(orig_folio))
		return false;
	orig_page = folio_file_page(folio, index);



From will at kernel.org  Wed Mar  5 11:34:26 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 5 Mar 2025 19:34:26 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <20250305094104.vctshdtgdukno2aj@bogus>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
 <20250305004522.GC31667@willie-the-truck>
 <20250305094104.vctshdtgdukno2aj@bogus>
Message-ID: <20250305193425.GA32246@willie-the-truck>

On Wed, Mar 05, 2025 at 09:41:04AM +0000, Sudeep Holla wrote:
> On Wed, Mar 05, 2025 at 12:45:23AM +0000, Will Deacon wrote:
> > Hmm, the FFA spec is characteristically unclear as to whether or not we
> > need to release the rx buffer in the case that the flags indicate use of
> > the rx buffer but the returned partition count is 0.
> > 
> > Sudeep -- do you know what we should be doing in that case?
> > 
> 
> We need to call RX_RELEASE here. I went back to the spec to confirm the
> same again.
> 
> v1.2 EAC0 spec Section 7.2.2.4.2 Transfer of buffer ownership
> (Or just look for the section title in any version of the spec)
> "
> 2. Ownership transfer for the RX buffer takes place as follows.
>     2. For a framework message,
>        1. Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership
>        of the caller?s RX buffer from the Producer to the Consumer.
> 3. For both types of messages, an invocation of the following FF-A ABIs
>     transfers the ownership from the Consumer to the Producer.
>        1. FFA_MSG_WAIT ...
>        2. FFA_RX_RELEASE.
> "
> 
> Hope that helps, can dig deeper if there are any ambiguities around this.

Thanks Sudeep, but that also makes it sound like we need the RX_RELEASE
even if we're not using the RX buffer per the input flags. :/

Will


From will at kernel.org  Wed Mar  5 11:35:52 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 5 Mar 2025 19:35:52 +0000
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
In-Reply-To: <Z8iccxCo7tkqvE_p@arm.com>
References: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
 <Z8iccxCo7tkqvE_p@arm.com>
Message-ID: <20250305193551.GB32246@willie-the-truck>

On Wed, Mar 05, 2025 at 06:48:19PM +0000, Catalin Marinas wrote:
> On Tue, Mar 04, 2025 at 12:51:27AM -0800, Piotr Jaroszynski wrote:
> > Update the __flush_tlb_range_op macro not to modify its parameters as
> > these are unexepcted semantics. In practice, this fixes the call to
> > mmu_notifier_arch_invalidate_secondary_tlbs() in
> > __flush_tlb_range_nosync() to use the correct range instead of an empty
> > range with start=end. The empty range was (un)lucky as it results in
> > taking the invalidate-all path that doesn't cause correctness issues,
> > but can certainly result in suboptimal perf.
> > 
> > This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
> > invalidate_range() when invalidating TLBs") when the call to the
> > notifiers was added to __flush_tlb_range(). It predates the addition of
> > the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
> > Refactor the core flush algorithm of __flush_tlb_range") that made the
> > bug hard to spot.
> 
> That's the problem with macros.
> 
> Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
> 
> Will, do you want to take this as a fix? It's only a performance
> regression, though you never know how it breaks the callers of the macro
> at some point.

Yeah, I'll pick it up but I'm travelling atm so it may have to wait until
next week.

Will


From krzk at kernel.org  Wed Mar  5 11:37:00 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 20:37:00 +0100
Subject: [PATCH 3/3] firmware: samsung: add ACPM debugfs support
In-Reply-To: <20250224-acpm-debugfs-v1-3-2418a3ea1b17@linaro.org>
References: <20250224-acpm-debugfs-v1-0-2418a3ea1b17@linaro.org>
 <20250224-acpm-debugfs-v1-3-2418a3ea1b17@linaro.org>
Message-ID: <005424c2-7fb7-48db-b38c-c62f9f8b3897@kernel.org>

On 24/02/2025 09:01, Tudor Ambarus wrote:
> The ACPM firmware saves debug information to SRAM. Add debugfs entries
> in order to expose the ACPM logs.
> 
> acpm_framework/logb_gprio_level controls the ACPM print verbosity to
> the SRAM log buffer. It encodes a 64 bit value, 4 bits for each of the
> 16 Plugin IDs, with verbosity levels from 0xf (log error) to
> 0x0 (log debug).
> 
> echo 0xffffffffffffff1f > /sys/kernel/debug/acpm_framework/logb_gprio_level
> Will allow only LOG_ERR prints for all Plugin IDs but Plugin ID 1,
> which will issue prints for any log levels greater or equal to 1.
> On the ACPM firmware side, logb_gprio_level has a default value of zero,
> all logs enabled for all Plugin IDs.
> 
> acpm_framework/log_level has a maximum value of 2 and controls which
> SRAM log buffers are printed.
> 
> Finally, acpm_framework/acpm_debug_cmd provides a way to issue
> ACPM DEBUG commands to the firmware.

Please add something like above also as a comment to the driver, so the
interface will be documented.

> 
> Add ACPM debugfs support with the above capabilities.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> ---


...

> +
> +union acpm_log_entry {
> +	u32 raw[4];
> +	struct {
> +		u32 systicks0 : 24;
> +		u32 dummy : 2;
> +		u32 is_err : 1;
> +		u32 is_raw : 1;
> +		u32 plugin_id : 4;
> +		u32 systicks24;
> +		u32 msg : 24;
> +		u32 systicks56 : 8;
> +		u32 data;
> +	} __packed;
> +};
> +
> +static struct dentry *rootdir;

exynos-apcm.c is not a singleton, so neither should this be. You should
create entries per device (so with device name as subdirectory), just
for correctness.

> +
> +static DEFINE_MUTEX(acpm_log_level_mutex);

And this also looks per-device-instance.

> +
> +static void acpm_log_print_entry(struct acpm_info *acpm,
> +				 const union acpm_log_entry *log_entry)
> +{
> +	u64 systicks, time, msg;
> +
> +	if (log_entry->is_err)
> +		return;
> +
> +	if (log_entry->is_raw) {
> +		dev_info(acpm->dev, "[ACPM_FW raw] : id:%u, %x, %x, %x\n",
> +			 log_entry->plugin_id, log_entry->raw[1],
> +			 log_entry->raw[2], log_entry->raw[3]);
> +	} else {
> +		systicks = ((u64)(log_entry->systicks56) << 56) +
> +			   ((u64)(log_entry->systicks24) << 24) +
> +			   log_entry->systicks0;
> +
> +		/* report time in ns */
> +		time = mul_u64_u32_div(systicks, ACPM_APM_SYSTICK_PERIOD_PS,
> +				       1000);
> +
> +		msg = readl(acpm->sram_base + log_entry->msg);
> +
> +		dev_info(acpm->dev, "[ACPM_FW] : %llu id:%u, %s, %x\n", time,
> +			 log_entry->plugin_id, (char *)&msg, log_entry->data);


I don't think these should be printed to dmesg - these are not system
logs. You either return the contents to the caller's read() on debugfs
entry or, if this is anyhow crashdump related, it goes to
pstore/minidump once triggered. Or to ramoops.

Depends what these logs are (so please also explain what do you find
there in the commit msg).

Maybe something like CHROMEOS_PSTORE?

IOW, if enabled, this should go to ramoops/pstore unconditionally. For
runtime debugging this should be returned somehow to the userspace
reading the file. I think usually debugfs and sysfs is not expected to
provide more than PAGE_SIZE data, so this second part has to be
rethinked still.

> +	}
> +}
> +
> +static void acpm_log_print_entries(struct acpm_info *acpm,
> +				   struct acpm_log_buf *lbuf)
> +{
> +	union acpm_log_entry log_entry = {0};
> +	u32 front, rear;
> +
> +	front = readl(lbuf->q.front);
> +	rear = lbuf->rear_index;
> +
> +	while (rear != front) {
> +		__ioread32_copy(&log_entry, lbuf->q.base + lbuf->mlen * rear,
> +				sizeof(log_entry) / 4);
> +
> +		acpm_log_print_entry(acpm, &log_entry);
> +
> +		if (lbuf->qlen == rear + 1)
> +			rear = 0;
> +		else
> +			rear++;
> +
> +		lbuf->rear_index = rear;
> +		front = readl(lbuf->q.front);
> +	}
> +}
> +
> +static void acpm_log_print(struct acpm_info *acpm)
> +{
> +	struct acpm_log_info *acpm_log = acpm->log;
> +
> +	guard(mutex)(&acpm_log_level_mutex);
> +
> +	if (acpm_log->level == 0)
> +		return;
> +
> +	if (acpm_log->level == ACPM_LOG_LEVEL_MAX)
> +		acpm_log_print_entries(acpm, &acpm_log->preempt);
> +
> +	acpm_log_print_entries(acpm, &acpm_log->normal);
> +}
> +
> +static void acpm_work_fn(struct work_struct *work)
> +{
> +	struct acpm_log_info *acpm_log =
> +		container_of(work, struct acpm_log_info, work.work);
> +	struct acpm_info *acpm = acpm_log->acpm;
> +
> +	acpm_log_print(acpm);
> +
> +	queue_delayed_work(acpm_log->wq, &acpm_log->work,
> +			   msecs_to_jiffies(acpm_log->poll_period));
> +}
> +
> +static int acpm_log_level_get(void *data, u64 *val)
> +{
> +	struct acpm_info *acpm = data;
> +
> +	*val = acpm->log->level;
> +
> +	return 0;
> +}
> +
> +static int acpm_log_level_set(void *data, u64 val)
> +{
> +	struct acpm_info *acpm = data;
> +	struct acpm_log_info *acpm_log = acpm->log;
> +
> +	if (val > ACPM_LOG_LEVEL_MAX) {
> +		dev_err(acpm->dev, "Log level %llu out of range [0:%u]!\n",
> +			val, ACPM_LOG_LEVEL_MAX);
> +		return -EINVAL;
> +	}
> +
> +	scoped_guard(mutex, &acpm_log_level_mutex)
> +		acpm_log->level = val;
> +
> +	if (acpm_log->level == 0)
> +		cancel_delayed_work_sync(&acpm_log->work);
> +	else
> +		queue_delayed_work(acpm_log->wq, &acpm_log->work,
> +				   msecs_to_jiffies(acpm_log->poll_period));
> +	return 0;
> +}
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(acpm_log_level_fops, acpm_log_level_get,
> +			 acpm_log_level_set, "0%llu\n");

I also do not think debugfs is a knob to control loglevel of messages
going to dmesg.

Best regards,
Krzysztof


From david at redhat.com  Wed Mar  5 11:37:02 2025
From: david at redhat.com (David Hildenbrand)
Date: Wed, 5 Mar 2025 20:37:02 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <Z8imcXuuW6EK1aLY@casper.infradead.org>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
 <Z8imcXuuW6EK1aLY@casper.infradead.org>
Message-ID: <bf8ac5ba-74ca-4ddb-bf28-1c2834907146@redhat.com>

On 05.03.25 20:30, Matthew Wilcox wrote:
> On Tue, Mar 04, 2025 at 04:48:46PM +0100, David Hildenbrand wrote:
>> +static bool orig_page_is_identical(struct vm_area_struct *vma,
>> +		unsigned long vaddr, struct page *page, bool *pmd_mappable)
>> +{
>> +	const pgoff_t index = vaddr_to_offset(vma, vaddr) >> PAGE_SHIFT;
>> +	struct page *orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
>> +					       index);
>> +	struct folio *orig_folio;
>> +	bool identical;
>> +
>> +	if (!orig_page)
>> +		return false;
>> +	orig_folio = page_folio(orig_page);
> 
> I'd rather write this as:
> 
> 	struct folio *orig_folio = filemap_get_folio(vma->vm_file->f_mapping,
> 			index);
> 	struct page *orig_page;
> 
> 	if (IS_ERR(orig_folio))
> 		return false;
> 	orig_page = folio_file_page(folio, index);
> 

Willy, you read my mind. I was staring at that code and thought "there 
must be an easier way using pages", and folio_file_page() was the 
missing piece.

Thanks!

-- 
Cheers,

David / dhildenb



From catalin.marinas at arm.com  Wed Mar  5 11:33:05 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed,  5 Mar 2025 19:33:05 +0000
Subject: [PATCH V3] arm64/hugetlb: Consistently use pud_sect_supported()
In-Reply-To: <20250220050534.799645-1-anshuman.khandual@arm.com>
References: <20250220050534.799645-1-anshuman.khandual@arm.com>
Message-ID: <174120317313.1423488.11091478258805705032.b4-ty@arm.com>

On Thu, 20 Feb 2025 10:35:34 +0530, Anshuman Khandual wrote:
> Let's be consistent in using pud_sect_supported() for PUD_SIZE sized pages.
> Hence change hugetlb_mask_last_page() and arch_make_huge_pte() as required.
> Also re-arranged the switch statement for a common warning message.
> 
> 

Applied to arm64 (for-next/pgtable-cleanups), thanks!

[1/1] arm64/hugetlb: Consistently use pud_sect_supported()
      https://git.kernel.org/arm64/c/34e8e63a6dc1

-- 
Catalin



From cwabbott0 at gmail.com  Wed Mar  5 11:38:32 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 5 Mar 2025 14:38:32 -0500
Subject: [PATCH v4 5/5] drm/msm: Temporarily disable stall-on-fault after
 a page fault
In-Reply-To: <CAF6AEGufRP9NuqC1gYy6jrQ9z+XqGFd7KNsbQw8C8NscSOJnJQ@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-5-be14be37f4c3@gmail.com> <CAF6AEGufRP9NuqC1gYy6jrQ9z+XqGFd7KNsbQw8C8NscSOJnJQ@mail.gmail.com>
Message-ID: <CACu1E7FPO253T+EvdJdaBuqh3kb7H_r7WhBE+bVxSHMPq6ixEg@mail.gmail.com>

On Wed, Mar 5, 2025 at 2:07?PM Rob Clark <robdclark at gmail.com> wrote:
>
> On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
> >
> > When things go wrong, the GPU is capable of quickly generating millions
> > of faulting translation requests per second. When that happens, in the
> > stall-on-fault model each access will stall until it wins the race to
> > signal the fault and then the RESUME register is written. This slows
> > processing page faults to a crawl as the GPU can generate faults much
> > faster than the CPU can acknowledge them. It also means that all
> > available resources in the SMMU are saturated waiting for the stalled
> > transactions, so that other transactions such as transactions generated
> > by the GMU, which shares a context bank with the GPU, cannot proceed.
>
> Nit, the GMU does not actually share a cb.. looking on x1e80100.dtsi,
> the GMU has cb 5 and gpu has 0 and 1.  (Currently we just use the
> first, but I guess the 2nd would be used if we supported protected
> content?)

Yeah, I realized after writing this that's the case. But I guess the
QoS issues happen even with separate context banks due to the way they
allocate translation units?

Connor

>
> fwiw, you can read this from dtsi, ie. in the GMU node, "iommus =
> <&adreno_smmu 5 0x0>;"
>
> > This causes a GMU watchdog timeout, which leads to a failed reset
> > because GX cannot collapse when there is a transaction pending and a
> > permanently hung GPU.
> >
> > On older platforms with qcom,smmu-v2, it seems that when one transaction
> > is stalled subsequent faulting transactions are terminated, which avoids
> > this problem, but the MMU-500 follows the spec here.
> >
> > To work around these problem, disable stall-on-fault as soon as we get a
> > page fault until a cooldown period after pagefaults stop. This allows
> > the GMU some guaranteed time to continue working. We only use
> > stall-on-fault to halt the GPU while we collect a devcoredump and we
> > always terminate the transaction afterward, so it's fine to miss some
> > subsequent page faults. We also keep it disabled so long as the current
> > devcoredump hasn't been deleted, because in that case we likely won't
> > capture another one if there's a fault.
> >
> > After this commit HFI messages still occasionally time out, because the
> > crashdump handler doesn't run fast enough to let the GMU resume, but the
> > driver seems to recover from it. This will probably go away after the
> > HFI timeout is increased.
> >
> > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > ---
> >  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 ++
> >  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  4 ++++
> >  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 42 ++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/msm/adreno/adreno_gpu.h | 24 +++++++++++++++++++
> >  drivers/gpu/drm/msm/msm_iommu.c         |  9 +++++++
> >  drivers/gpu/drm/msm/msm_mmu.h           |  1 +
> >  6 files changed, 81 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > index 71dca78cd7a5324e9ff5b14f173e2209fa42e196..670141531112c9d29cef8ef1fd51b74759fdd6d2 100644
> > --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > @@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> >         struct msm_ringbuffer *ring = submit->ring;
> >         unsigned int i, ibs = 0;
> >
> > +       adreno_check_and_reenable_stall(adreno_gpu);
> > +
> >         if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
> >                 ring->cur_ctx_seqno = 0;
> >                 a5xx_submit_in_rb(gpu, submit);
> > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > index 0ae29a7c8a4d3f74236a35cc919f69d5c0a384a0..5a34cd2109a2d74c92841448a61ccb0d4f34e264 100644
> > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > @@ -212,6 +212,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> >         struct msm_ringbuffer *ring = submit->ring;
> >         unsigned int i, ibs = 0;
> >
> > +       adreno_check_and_reenable_stall(adreno_gpu);
> > +
> >         a6xx_set_pagetable(a6xx_gpu, ring, submit);
> >
> >         get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
> > @@ -335,6 +337,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> >         struct msm_ringbuffer *ring = submit->ring;
> >         unsigned int i, ibs = 0;
> >
> > +       adreno_check_and_reenable_stall(adreno_gpu);
> > +
> >         /*
> >          * Toggle concurrent binning for pagetable switch and set the thread to
> >          * BR since only it can execute the pagetable switch packets.
> > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > index 1238f326597808eb28b4c6822cbd41a26e555eb9..bac586101dc0494f46b069a8440a45825dfe9b5e 100644
> > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > @@ -246,16 +246,53 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
> >         return SZ_4G;
> >  }
> >
> > +void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
> > +{
> > +       struct msm_gpu *gpu = &adreno_gpu->base;
> > +       unsigned long flags;
> > +
> > +       /*
> > +        * Wait until the cooldown period has passed and we would actually
> > +        * collect a crashdump to re-enable stall-on-fault.
> > +        */
> > +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, flags);
> > +       if (!adreno_gpu->stall_enabled &&
> > +                       ktime_after(ktime_get(), adreno_gpu->stall_reenable_time) &&
> > +                       !READ_ONCE(gpu->crashstate)) {
> > +               adreno_gpu->stall_enabled = true;
> > +
> > +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
> > +       }
> > +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, flags);
> > +}
> > +
> >  #define ARM_SMMU_FSR_TF                 BIT(1)
> >  #define ARM_SMMU_FSR_PF                        BIT(3)
> >  #define ARM_SMMU_FSR_EF                        BIT(4)
> > +#define ARM_SMMU_FSR_SS                        BIT(30)
> >
> >  int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
> >                          struct adreno_smmu_fault_info *info, const char *block,
> >                          u32 scratch[4])
> >  {
> > +       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> >         const char *type = "UNKNOWN";
> > -       bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
> > +       bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
> > +               !READ_ONCE(gpu->crashstate);
> > +       unsigned long irq_flags;
> > +
> > +       /*
> > +        * In case there is a subsequent storm of pagefaults, disable
> > +        * stall-on-fault for at least half a second.
> > +        */
> > +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, irq_flags);
> > +       if (adreno_gpu->stall_enabled) {
> > +               adreno_gpu->stall_enabled = false;
> > +
> > +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
> > +       }
> > +       adreno_gpu->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
> > +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, irq_flags);
> >
> >         /*
> >          * If we aren't going to be resuming later from fault_worker, then do
> > @@ -1143,6 +1180,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
> >                 adreno_gpu->info->inactive_period);
> >         pm_runtime_use_autosuspend(dev);
> >
> > +       spin_lock_init(&adreno_gpu->fault_stall_lock);
> > +       adreno_gpu->stall_enabled = true;
> > +
> >         return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
> >                         gpu_name, &adreno_gpu_config);
> >  }
> > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > index dcf454629ce037b2a8274a6699674ad754ce1f07..a528036b46216bd898f6d48c5fb0555c4c4b053b 100644
> > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > @@ -205,6 +205,28 @@ struct adreno_gpu {
> >         /* firmware: */
> >         const struct firmware *fw[ADRENO_FW_MAX];
> >
> > +       /**
> > +        * fault_stall_lock:
>
> nit, @fault_stall_lock:  And for
> fault_stall_reenable_time/stall_enabled, it wouldn't hurt to add
> something along the lines of "Protected by @fault_stall_lock".  I've
> been slowly trying to improve the comment docs over time, I have some
> of that in my vmbind patchset.
>
> Anyways, with those nits addressed, r-b
>
> BR,
> -R
>
> > +        *
> > +        * Serialize changes to stall-on-fault state.
> > +        */
> > +       spinlock_t fault_stall_lock;
> > +
> > +       /**
> > +        * fault_stall_reenable_time:
> > +        *
> > +        * if stall_enabled is false, when to reenable stall-on-fault.
> > +        */
> > +       ktime_t stall_reenable_time;
> > +
> > +       /**
> > +        * stall_enabled:
> > +        *
> > +        * Whether stall-on-fault is currently enabled.
> > +        */
> > +       bool stall_enabled;
> > +
> > +
> >         struct {
> >                 /**
> >                  * @rgb565_predicator: Unknown, introduced with A650 family,
> > @@ -629,6 +651,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
> >                          struct adreno_smmu_fault_info *info, const char *block,
> >                          u32 scratch[4]);
> >
> > +void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
> > +
> >  int adreno_read_speedbin(struct device *dev, u32 *speedbin);
> >
> >  /*
> > diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> > index 2a94e82316f95c5f9dcc37ef0a4664a29e3492b2..8d5380e6dcc217c7c209b51527bf15748b3ada71 100644
> > --- a/drivers/gpu/drm/msm/msm_iommu.c
> > +++ b/drivers/gpu/drm/msm/msm_iommu.c
> > @@ -351,6 +351,14 @@ static void msm_iommu_resume_translation(struct msm_mmu *mmu)
> >                 adreno_smmu->resume_translation(adreno_smmu->cookie, true);
> >  }
> >
> > +static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
> > +{
> > +       struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
> > +
> > +       if (adreno_smmu->set_stall)
> > +               adreno_smmu->set_stall(adreno_smmu->cookie, enable);
> > +}
> > +
> >  static void msm_iommu_detach(struct msm_mmu *mmu)
> >  {
> >         struct msm_iommu *iommu = to_msm_iommu(mmu);
> > @@ -399,6 +407,7 @@ static const struct msm_mmu_funcs funcs = {
> >                 .unmap = msm_iommu_unmap,
> >                 .destroy = msm_iommu_destroy,
> >                 .resume_translation = msm_iommu_resume_translation,
> > +               .set_stall = msm_iommu_set_stall,
> >  };
> >
> >  struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
> > diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
> > index 88af4f490881f2a6789ae2d03e1c02d10046331a..2694a356a17904e7572b767b16ed0cee806406cf 100644
> > --- a/drivers/gpu/drm/msm/msm_mmu.h
> > +++ b/drivers/gpu/drm/msm/msm_mmu.h
> > @@ -16,6 +16,7 @@ struct msm_mmu_funcs {
> >         int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
> >         void (*destroy)(struct msm_mmu *mmu);
> >         void (*resume_translation)(struct msm_mmu *mmu);
> > +       void (*set_stall)(struct msm_mmu *mmu, bool enable);
> >  };
> >
> >  enum msm_mmu_type {
> >
> > --
> > 2.47.1
> >


From catalin.marinas at arm.com  Wed Mar  5 11:32:56 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed,  5 Mar 2025 19:32:56 +0000
Subject: [PATCH V2] arm64/mm: Convert __pte_to_phys() and __phys_to_pte_val() as functions
In-Reply-To: <20250227022412.2015835-1-anshuman.khandual@arm.com>
References: <20250227022412.2015835-1-anshuman.khandual@arm.com>
Message-ID: <174120317313.1423488.2871713663228556221.b4-ty@arm.com>

On Thu, 27 Feb 2025 07:54:12 +0530, Anshuman Khandual wrote:
> When CONFIG_ARM64_PA_BITS_52 is enabled, page table helpers __pte_to_phys()
> and __phys_to_pte_val() are functions which return phys_addr_t and pteval_t
> respectively as expected. But otherwise without this config being enabled,
> they are defined as macros and their return types are implicit.
> 
> Until now this has worked out correctly as both pte_t and phys_addr_t data
> types have been 64 bits. But with the introduction of 128 bit page tables,
> pte_t becomes 128 bits. Hence this ends up with incorrect widths after the
> conversions, which leads to compiler warnings.
> 
> [...]

Applied to arm64 (for-next/pgtable-cleanups), thanks!

[1/1] arm64/mm: Convert __pte_to_phys() and __phys_to_pte_val() as functions
      https://git.kernel.org/arm64/c/2d7872f3ae3b

-- 
Catalin



From ziyao at disroot.org  Wed Mar  5 11:42:09 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:42:09 +0000
Subject: [PATCH v2 0/8] Support SD/SDIO controllers on RK3528
Message-ID: <20250305194217.47052-1-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller. This
series adds essential support for their tuning clocks, document the
controller in dt-bindings and bring the SD/MMC one up on Radxa E20C
board. Both HS and SDR104 mode are verified.

This is based on v2 of the SARADC series[1]

- Changed from v1
  - Apply review tags
  - Rebase on top of linux-rockchip/for-next and saradc v2 series
  - rk3528 clock driver:
    - explicitly include minmax.h, replace MAX() with more robust max()
    - readability improvements
    - fix error checks: ERR_PTR(-ENODEV), instead of ERR_PTR(ENODEV), is
      returned when syscon_regmap_lookup_by_compatible() fails for missing
      such syscon
  - RK3528 devicetree
    - Add default pinctrl
    - Move the per-SoC property, rockchip,default-sample-phase, into the
      SoC devicetree
  - rk3528-radxa-e20c devicetree
    - Assign sdcard to mmc1
    - Add missing regulators
    - Apply no-sdio for the sdmmc controller
    - Sort nodes
  - Link to v1: https://lore.kernel.org/all/20250301104250.36295-1-ziyao at disroot.org/

Thanks for your time and review.

[1]: https://lore.kernel.org/all/20250304201642.831218-1-jonas at kwiboo.se/

Yao Zi (8):
  dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
  dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
  dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
  dt-bindings: clock: Add GRF clock definition for RK3528
  clk: rockchip: Support MMC clocks in GRF region
  clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
  arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
  arm64: dts: rockchip: Enable SD-card interface on Radxa E20C

 .../bindings/mmc/rockchip-dw-mshc.yaml        |  1 +
 .../devicetree/bindings/soc/rockchip/grf.yaml |  2 +
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 34 +++++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 70 +++++++++++++++++++
 drivers/clk/rockchip/clk-mmc-phase.c          | 24 +++++--
 drivers/clk/rockchip/clk-rk3528.c             | 61 ++++++++++++++--
 drivers/clk/rockchip/clk.c                    | 42 +++++++++++
 drivers/clk/rockchip/clk.h                    | 23 +++++-
 .../dt-bindings/clock/rockchip,rk3528-cru.h   |  6 ++
 9 files changed, 252 insertions(+), 11 deletions(-)

-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:42:10 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:42:10 +0000
Subject: [PATCH v2 1/8] dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194217.47052-2-ziyao@disroot.org>

Add compatible string for VO GRF found on RK3528 SoC.

Signed-off-by: Yao Zi <ziyao at disroot.org>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index b4ed4cb555bd..98a0670359f6 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -16,6 +16,7 @@ properties:
           - enum:
               - rockchip,rk3288-sgrf
               - rockchip,rk3528-ioc-grf
+              - rockchip,rk3528-vo-grf
               - rockchip,rk3566-pipe-grf
               - rockchip,rk3568-pcie3-phy-grf
               - rockchip,rk3568-pipe-grf
-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:42:11 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:42:11 +0000
Subject: [PATCH v2 2/8] dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194217.47052-3-ziyao@disroot.org>

Add compatible string for VPU GRF found on RK3528 SoC.

Signed-off-by: Yao Zi <ziyao at disroot.org>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index 98a0670359f6..2f61c1b95fea 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -17,6 +17,7 @@ properties:
               - rockchip,rk3288-sgrf
               - rockchip,rk3528-ioc-grf
               - rockchip,rk3528-vo-grf
+              - rockchip,rk3528-vpu-grf
               - rockchip,rk3566-pipe-grf
               - rockchip,rk3568-pcie3-phy-grf
               - rockchip,rk3568-pipe-grf
-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:42:12 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:42:12 +0000
Subject: [PATCH v2 3/8] dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194217.47052-4-ziyao@disroot.org>

Add RK3528 compatible string for SD/SDIO interface.

Signed-off-by: Yao Zi <ziyao at disroot.org>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
index 06df1269f247..ea0feb733e32 100644
--- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
@@ -38,6 +38,7 @@ properties:
               - rockchip,rk3328-dw-mshc
               - rockchip,rk3368-dw-mshc
               - rockchip,rk3399-dw-mshc
+              - rockchip,rk3528-dw-mshc
               - rockchip,rk3568-dw-mshc
               - rockchip,rk3588-dw-mshc
               - rockchip,rv1108-dw-mshc
-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:42:13 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:42:13 +0000
Subject: [PATCH v2 4/8] dt-bindings: clock: Add GRF clock definition for RK3528
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194217.47052-5-ziyao@disroot.org>

These clocks are for SD/SDIO tuning purpose and come with registers
in GRF syscon.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h
index 55a448f5ed6d..0245a53fc334 100644
--- a/include/dt-bindings/clock/rockchip,rk3528-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h
@@ -414,6 +414,12 @@
 #define MCLK_I2S2_2CH_SAI_SRC_PRE	402
 #define MCLK_I2S3_8CH_SAI_SRC_PRE	403
 #define MCLK_SDPDIF_SRC_PRE		404
+#define SCLK_SDMMC_DRV			405
+#define SCLK_SDMMC_SAMPLE		406
+#define SCLK_SDIO0_DRV			407
+#define SCLK_SDIO0_SAMPLE		408
+#define SCLK_SDIO1_DRV			409
+#define SCLK_SDIO1_SAMPLE		410
 
 /* scmi-clocks indices */
 #define SCMI_PCLK_KEYREADER		0
-- 
2.48.1



From andrii.nakryiko at gmail.com  Wed Mar  5 11:43:52 2025
From: andrii.nakryiko at gmail.com (Andrii Nakryiko)
Date: Wed, 5 Mar 2025 11:43:52 -0800
Subject: [PATCH -next v1 0/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
In-Reply-To: <20250305152055.GB28112@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com> <20250305152055.GB28112@redhat.com>
Message-ID: <CAEf4BzbyFy0eQHLac3zR8GiGDOUqYoTGAWDbFaeou903OGOTpg@mail.gmail.com>

On Wed, Mar 5, 2025 at 7:22?AM Oleg Nesterov <oleg at redhat.com> wrote:
>
> On 03/04, David Hildenbrand wrote:
> >
> > Currently, uprobe_write_opcode() implements COW-breaking manually, which is
> > really far from ideal.
>
> To say at least ;)
>
> David, thanks for doing this. I'll try to read 3/3 tomorrow, but I don't
> think I can really help. Let me repeat, this code was written many years
> ago, I forgot everything, and today my understanding of mm/ is very poor.
> But I'll try anyway.
>
> > Are there any uprobe tests / benchmarks that are worth running?
>
> All I know about uprobe tests is that bpf people run a lot of tests which
> use uprobes.
>
> Andrii, Jiri, what you advise?
>

We do have a bunch of tests within BPF selftests:

cd tools/testing/selftest/bpf && make -j$(nproc) && sudo ./test_progs -t uprobe

I also built an uprobe-stress tool to validate uprobe optimizations I
was doing, this one is the most stand-alone thing to use for testing,
please consider checking that. You can find it at [0], and see also
[1] and [2] where  I was helping Peter to build it from sources, so
that might be useful for you as well, if you run into problems with
building. Running something like `sudo ./uprobe-stress -a10 -t5 -m5
-f3` would hammer on this quite a bit.

I'm just about to leave on a short vacation, so won't have time to go
over patches, but I plan to look at them when I'm back next week.

  [0] https://github.com/libbpf/libbpf-bootstrap/tree/uprobe-stress
  [1] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZ+ygwfk8FKn5AS_Ny=igvGcFzdDLE2FjcvwjCKazEWMA at mail.gmail.com/
  [2] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZqKCR-EQz6LTi-YvFY4RnYb_NnQXtwgZCv6aUo7gjkHg at mail.gmail.com

> Oleg.
>


From ziyao at disroot.org  Wed Mar  5 11:45:13 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:45:13 +0000
Subject: [PATCH v2 5/8] clk: rockchip: Support MMC clocks in GRF region
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194513.47139-1-ziyao@disroot.org>

Registers of MMC drive/sample clocks in Rockchip RV1106 and RK3528
locate in GRF regions. Adjust MMC clock code to support register
operations through regmap. Also add a helper to ease registration of GRF
clocks.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-mmc-phase.c | 24 +++++++++++++---
 drivers/clk/rockchip/clk.c           | 42 ++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h           | 20 ++++++++++++-
 3 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 91012078681b..b3ed8e7523e5 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -9,11 +9,14 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct regmap	*grf;
+	int		grf_reg;
 	int		shift;
 	int		cached_phase;
 	struct notifier_block clk_rate_change_nb;
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
 	if (!rate)
 		return 0;
 
-	raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
+	if (mmc_clock->grf)
+		regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
+	else
+		raw_value = readl(mmc_clock->reg);
+
+	raw_value >>= mmc_clock->shift;
 
 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
 
@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
 	raw_value |= nineties;
-	writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
-	       mmc_clock->reg);
+	raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
+
+	if (mmc_clock->grf)
+		regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
+	else
+		writel(raw_value, mmc_clock->reg);
 
 	pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
 		clk_hw_get_name(hw), degrees, delay_num,
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift)
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift)
 {
 	struct clk_init_data init;
 	struct rockchip_mmc_clock *mmc_clock;
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 
 	mmc_clock->hw.init = &init;
 	mmc_clock->reg = reg;
+	mmc_clock->grf = grf;
+	mmc_clock->grf_reg = grf_reg;
 	mmc_clock->shift = shift;
 
 	clk = clk_register(NULL, &mmc_clock->hw);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index cbf93ea119a9..ce2f3323d84e 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -590,6 +590,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 				list->name,
 				list->parent_names, list->num_parents,
 				ctx->reg_base + list->muxdiv_offset,
+				NULL, 0,
 				list->div_shift
 			);
 			break;
@@ -619,6 +620,11 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 			break;
 		case branch_linked_gate:
 			/* must be registered late, fall-through for error message */
+		case branch_mmc_grf:
+			/*
+			 * must be registered through rockchip_clk_register_grf_branches,
+			 * fall-through for error message
+			 */
 			break;
 		}
 
@@ -665,6 +671,42 @@ void rockchip_clk_register_late_branches(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(rockchip_clk_register_late_branches);
 
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk)
+{
+	unsigned int idx;
+	struct clk *clk;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = NULL;
+
+		switch (list->branch_type) {
+		case branch_mmc_grf:
+			clk = rockchip_clk_register_mmc(
+				list->name,
+				list->parent_names, list->num_parents,
+				NULL,
+				grf, list->muxdiv_offset,
+				list->div_shift
+			);
+			break;
+		default:
+			pr_err("%s: unknown clock type %d\n",
+			       __func__, list->branch_type);
+			break;
+		}
+
+		if (!clk)
+			pr_err("%s: failed to register clock %s: %ld\n",
+			       __func__, list->name, PTR_ERR(clk));
+		else
+			rockchip_clk_set_lookup(ctx, clk, list->id);
+	}
+}
+EXPORT_SYMBOL_GPL(rockchip_clk_register_grf_branches);
+
 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
 				  unsigned int lookup_id,
 				  const char *name, const char *const *parent_names,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index df2b2d706450..ec86ba1dd38c 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -594,7 +594,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift);
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift);
 
 /*
  * DDRCLK flags, including method of setting the rate
@@ -633,6 +635,7 @@ enum rockchip_clk_branch_type {
 	branch_gate,
 	branch_linked_gate,
 	branch_mmc,
+	branch_mmc_grf,
 	branch_inverter,
 	branch_factor,
 	branch_ddrclk,
@@ -983,6 +986,17 @@ struct rockchip_clk_branch {
 		.div_shift	= shift,			\
 	}
 
+#define MMC_GRF(_id, cname, pname, offset, shift)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_mmc_grf,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.muxdiv_offset	= offset,			\
+		.div_shift	= shift,			\
+	}
+
 #define INVERTER(_id, cname, pname, io, is, if)			\
 	{							\
 		.id		= _id,				\
@@ -1132,6 +1146,10 @@ void rockchip_clk_register_late_branches(struct device *dev,
 					 struct rockchip_clk_provider *ctx,
 					 struct rockchip_clk_branch *list,
 					 unsigned int nr_clk);
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk);
 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
 				struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:45:44 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:45:44 +0000
Subject: [PATCH v2 6/8] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194544.47155-1-ziyao@disroot.org>

These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
tuning purpose. Add their definitions and register them in driver if
corresponding GRF is available.

GRFs are looked up by compatible to simplify devicetree binding.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-rk3528.c | 61 ++++++++++++++++++++++++++++---
 drivers/clk/rockchip/clk.h        |  3 ++
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3528.c b/drivers/clk/rockchip/clk-rk3528.c
index b8b577b902a0..5c133a642ff9 100644
--- a/drivers/clk/rockchip/clk-rk3528.c
+++ b/drivers/clk/rockchip/clk-rk3528.c
@@ -10,6 +10,8 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/minmax.h>
 
 #include <dt-bindings/clock/rockchip,rk3528-cru.h>
 
@@ -1061,23 +1063,64 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = {
 			0, 1, 1),
 };
 
+static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(0), 1),
+	MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(1), 1),
+};
+
+static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(0), 1),
+	MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(1), 1),
+	MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(0), 1),
+	MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(1), 1),
+};
+
 static int __init clk_rk3528_probe(struct platform_device *pdev)
 {
-	struct rockchip_clk_provider *ctx;
+	unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
+	unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
+	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
+	unsigned long nr_clks, nr_vo_clks, nr_vpu_clks;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
-	unsigned long nr_clks;
+	struct rockchip_clk_provider *ctx;
+	struct regmap *vo_grf, *vpu_grf;
 	void __iomem *reg_base;
 
-	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
-					       nr_branches) + 1;
-
 	reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(reg_base))
 		return dev_err_probe(dev, PTR_ERR(reg_base),
 				     "could not map cru region");
 
+	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
+					       nr_branches) + 1;
+
+	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
+	if (!IS_ERR(vo_grf)) {
+		nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
+							  nr_vo_branches) + 1;
+		nr_clks = max(nr_clks, nr_vo_clks);
+	} else if (PTR_ERR(vo_grf) != -ENODEV) {
+		return dev_err_probe(dev, PTR_ERR(vo_grf),
+				     "failed to look up VO GRF\n");
+	}
+
+	vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
+	if (!IS_ERR(vpu_grf)) {
+		nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
+							   nr_vpu_branches) + 1;
+		nr_clks = max(nr_clks, nr_vpu_clks);
+	} else if (PTR_ERR(vpu_grf) != -ENODEV) {
+		return dev_err_probe(dev, PTR_ERR(vpu_grf),
+				     "failed to look up VPU GRF\n");
+	}
+
 	ctx = rockchip_clk_init(np, reg_base, nr_clks);
 	if (IS_ERR(ctx))
 		return dev_err_probe(dev, PTR_ERR(ctx),
@@ -1091,6 +1134,12 @@ static int __init clk_rk3528_probe(struct platform_device *pdev)
 				     &rk3528_cpuclk_data, rk3528_cpuclk_rates,
 				     ARRAY_SIZE(rk3528_cpuclk_rates));
 	rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches);
+	if (!IS_ERR(vo_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vo_clk_branches,
+						   vo_grf, nr_vo_branches);
+	if (!IS_ERR(vpu_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vpu_clk_branches,
+						   vpu_grf, nr_vpu_branches);
 
 	rk3528_rst_init(np, reg_base);
 
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index ec86ba1dd38c..f07cd1bb8952 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -217,6 +217,9 @@ struct clk;
 #define RK3528_CLKSEL_CON(x)		((x) * 0x4 + 0x300)
 #define RK3528_CLKGATE_CON(x)		((x) * 0x4 + 0x800)
 #define RK3528_SOFTRST_CON(x)		((x) * 0x4 + 0xa00)
+#define RK3528_SDMMC_CON(x)		((x) * 0x4 + 0x24)
+#define RK3528_SDIO0_CON(x)		((x) * 0x4 + 0x4)
+#define RK3528_SDIO1_CON(x)		((x) * 0x4 + 0xc)
 #define RK3528_PMU_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE)
 #define RK3528_PMU_CLKGATE_CON(x)	((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE)
 #define RK3528_PCIE_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE)
-- 
2.48.1



From ziyao at disroot.org  Wed Mar  5 11:46:11 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:46:11 +0000
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194612.47171-1-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller, describe
them in devicetree. Since their sample and drive clocks are located in
the VO and VPU GRFs, corresponding syscons are added to make these
clocks available.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 70 ++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index d3e2a64ff2d5..363023314e9c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -130,6 +130,16 @@ gic: interrupt-controller at fed01000 {
 			#interrupt-cells = <3>;
 		};
 
+		vpu_grf: syscon at ff340000 {
+			compatible = "rockchip,rk3528-vpu-grf", "syscon";
+			reg = <0x0 0xff340000 0x0 0x8000>;
+		};
+
+		vo_grf: syscon at ff360000 {
+			compatible = "rockchip,rk3528-vo-grf", "syscon";
+			reg = <0x0 0xff360000 0x0 0x10000>;
+		};
+
 		cru: clock-controller at ff4a0000 {
 			compatible = "rockchip,rk3528-cru";
 			reg = <0x0 0xff4a0000 0x0 0x30000>;
@@ -274,6 +284,66 @@ saradc: adc at ffae0000 {
 			resets = <&cru SRST_P_SARADC>;
 			reset-names = "saradc-apb";
 			#io-channel-cells = <1>;
+		};
+
+		sdio0: mmc at ffc10000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc10000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO0>,
+				 <&cru CCLK_SRC_SDIO0>,
+				 <&cru SCLK_SDIO0_DRV>,
+				 <&cru SCLK_SDIO0_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
+				    <&sdio0_det>, <&sdio0_pwren>;
+			resets = <&cru SRST_H_SDIO0>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdio1: mmc at ffc20000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc20000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO1>,
+				 <&cru CCLK_SRC_SDIO1>,
+				 <&cru SCLK_SDIO1_DRV>,
+				 <&cru SCLK_SDIO1_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
+				    <&sdio1_det>, <&sdio1_pwren>;
+			resets = <&cru SRST_H_SDIO1>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdmmc: mmc at ffc30000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc30000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDMMC0>,
+				 <&cru CCLK_SRC_SDMMC0>,
+				 <&cru SCLK_SDMMC_DRV>,
+				 <&cru SCLK_SDMMC_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>,
+				    <&sdmmc_det>;
+			resets = <&cru SRST_H_SDMMC0>;
+			reset-names = "reset";
+			rockchip,default-sample-phase = <90>;
 			status = "disabled";
 		};
 
-- 
2.48.1



From nicolinc at nvidia.com  Wed Mar  5 11:46:18 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 11:46:18 -0800
Subject: [PATCH v1 0/4] iommu/arm-smmu-v3: Allocate vmid per vsmmu
 instead of s2_parent
In-Reply-To: <20250305192950.GA354511@nvidia.com>
References: <cover.1741150594.git.nicolinc@nvidia.com>
 <20250305165452.GY133783@nvidia.com>
 <Z8iWqOBga8Xdunac@Asurada-Nvidia>
 <20250305183151.GE133783@nvidia.com>
 <Z8idOr67A0EG1/PN@Asurada-Nvidia>
 <20250305192950.GA354511@nvidia.com>
Message-ID: <Z8iqCpGo1Kx4TAvQ@Asurada-Nvidia>

On Wed, Mar 05, 2025 at 03:29:50PM -0400, Jason Gunthorpe wrote:
> On Wed, Mar 05, 2025 at 10:51:38AM -0800, Nicolin Chen wrote:
> 
> > > I mean a normal S2 domain attaching to multiple devices on multiple
> > > instances.
> > 
> > Oh, I haven't thought about a !nest_parent S2 case.
> > 
> > A nest_parent case will not allow devices to attach the S2 but
> > always to a proxy nested S1 as we discussed previously. So, I
> > think the implementation could be very different?
> 
> It could, and that is what you show here
> 
> But also, it could be the same implementation.

OK.

Obviously I underestimated this part of work.

Implementation aside, this at lease needs some assessment of any
invalidation impact. I should do some extra tracing.

Thanks
Nicolin


From ziyao at disroot.org  Wed Mar  5 11:46:38 2025
From: ziyao at disroot.org (Yao Zi)
Date: Wed,  5 Mar 2025 19:46:38 +0000
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <20250305194638.47187-1-ziyao@disroot.org>

SD-card is available on Radxa E20C board.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 5346ef457c2a..a52a7924bb75 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -15,6 +15,10 @@ / {
 	model = "Radxa E20C";
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
+	aliases {
+		mmc1 = &sdmmc;
+	};
+
 	chosen {
 		stdout-path = "serial0:1500000n8";
 	};
@@ -104,6 +108,18 @@ vcc5v0_sys: regulator-5v0-vcc-sys {
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
 	};
+
+	vccio_sd: regulator-vccio-sd {
+		compatible = "regulator-gpio";
+		gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_vol_ctrl_h>;
+		regulator-name = "vccio_sd";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		states = <1800000 0x0>, <3300000 0x1>;
+		vin-supply = <&vcc5v0_sys>;
+	};
 };
 
 &pinctrl {
@@ -126,6 +142,12 @@ wan_led_g: wan-led-g {
 			rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
+
+	sdmmc {
+		sdmmc_vol_ctrl_h: sdmmc-vol-ctrl-h {
+			rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
 };
 
 &saradc {
@@ -133,6 +155,18 @@ &saradc {
 	status = "okay";
 };
 
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+	no-sdio;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0m0_xfer>;
-- 
2.48.1



From david at redhat.com  Wed Mar  5 11:47:51 2025
From: david at redhat.com (David Hildenbrand)
Date: Wed, 5 Mar 2025 20:47:51 +0100
Subject: [PATCH -next v1 0/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <CAEf4BzbyFy0eQHLac3zR8GiGDOUqYoTGAWDbFaeou903OGOTpg@mail.gmail.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250305152055.GB28112@redhat.com>
 <CAEf4BzbyFy0eQHLac3zR8GiGDOUqYoTGAWDbFaeou903OGOTpg@mail.gmail.com>
Message-ID: <62f93f79-a8d4-44a5-b276-3ac5af4ab25c@redhat.com>

On 05.03.25 20:43, Andrii Nakryiko wrote:
> On Wed, Mar 5, 2025 at 7:22?AM Oleg Nesterov <oleg at redhat.com> wrote:
>>
>> On 03/04, David Hildenbrand wrote:
>>>
>>> Currently, uprobe_write_opcode() implements COW-breaking manually, which is
>>> really far from ideal.
>>
>> To say at least ;)
>>
>> David, thanks for doing this. I'll try to read 3/3 tomorrow, but I don't
>> think I can really help. Let me repeat, this code was written many years
>> ago, I forgot everything, and today my understanding of mm/ is very poor.
>> But I'll try anyway.
>>
>>> Are there any uprobe tests / benchmarks that are worth running?
>>
>> All I know about uprobe tests is that bpf people run a lot of tests which
>> use uprobes.
>>
>> Andrii, Jiri, what you advise?
>>
> 
> We do have a bunch of tests within BPF selftests:
> 
> cd tools/testing/selftest/bpf && make -j$(nproc) && sudo ./test_progs -t uprobe

I stumbled over them, but was so far not successful in building them in 
my test VM (did not try too hard, though). Will try harder now that I 
know that it actually tests uprobe properly :)

> 
> I also built an uprobe-stress tool to validate uprobe optimizations I
> was doing, this one is the most stand-alone thing to use for testing,
> please consider checking that. You can find it at [0], and see also
> [1] and [2] where  I was helping Peter to build it from sources, so
> that might be useful for you as well, if you run into problems with
> building. Running something like `sudo ./uprobe-stress -a10 -t5 -m5
> -f3` would hammer on this quite a bit.

Thanks, I'll play with that as well.

> 
> I'm just about to leave on a short vacation, so won't have time to go
> over patches, but I plan to look at them when I'm back next week.
> 
>    [0] https://github.com/libbpf/libbpf-bootstrap/tree/uprobe-stress
>    [1] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZ+ygwfk8FKn5AS_Ny=igvGcFzdDLE2FjcvwjCKazEWMA at mail.gmail.com/
>    [2] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZqKCR-EQz6LTi-YvFY4RnYb_NnQXtwgZCv6aUo7gjkHg at mail.gmail.com
> 
>> Oleg.
>>
> 


-- 
Cheers,

David / dhildenb



From robdclark at gmail.com  Wed Mar  5 11:56:27 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 5 Mar 2025 11:56:27 -0800
Subject: [PATCH v4 5/5] drm/msm: Temporarily disable stall-on-fault after
 a page fault
In-Reply-To: <CACu1E7FPO253T+EvdJdaBuqh3kb7H_r7WhBE+bVxSHMPq6ixEg@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-5-be14be37f4c3@gmail.com>
 <CAF6AEGufRP9NuqC1gYy6jrQ9z+XqGFd7KNsbQw8C8NscSOJnJQ@mail.gmail.com> <CACu1E7FPO253T+EvdJdaBuqh3kb7H_r7WhBE+bVxSHMPq6ixEg@mail.gmail.com>
Message-ID: <CAF6AEGu+eHBzSu-4vsGJEcJtDhOV=LnDM1xMZJVK3=1o71B0KQ@mail.gmail.com>

On Wed, Mar 5, 2025 at 11:38?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> On Wed, Mar 5, 2025 at 2:07?PM Rob Clark <robdclark at gmail.com> wrote:
> >
> > On Tue, Mar 4, 2025 at 8:57?AM Connor Abbott <cwabbott0 at gmail.com> wrote:
> > >
> > > When things go wrong, the GPU is capable of quickly generating millions
> > > of faulting translation requests per second. When that happens, in the
> > > stall-on-fault model each access will stall until it wins the race to
> > > signal the fault and then the RESUME register is written. This slows
> > > processing page faults to a crawl as the GPU can generate faults much
> > > faster than the CPU can acknowledge them. It also means that all
> > > available resources in the SMMU are saturated waiting for the stalled
> > > transactions, so that other transactions such as transactions generated
> > > by the GMU, which shares a context bank with the GPU, cannot proceed.
> >
> > Nit, the GMU does not actually share a cb.. looking on x1e80100.dtsi,
> > the GMU has cb 5 and gpu has 0 and 1.  (Currently we just use the
> > first, but I guess the 2nd would be used if we supported protected
> > content?)
>
> Yeah, I realized after writing this that's the case. But I guess the
> QoS issues happen even with separate context banks due to the way they
> allocate translation units?

Right, however resources are allocated to track pending translations
seems to be shared across CBs

BR,
-R

>
> Connor
>
> >
> > fwiw, you can read this from dtsi, ie. in the GMU node, "iommus =
> > <&adreno_smmu 5 0x0>;"
> >
> > > This causes a GMU watchdog timeout, which leads to a failed reset
> > > because GX cannot collapse when there is a transaction pending and a
> > > permanently hung GPU.
> > >
> > > On older platforms with qcom,smmu-v2, it seems that when one transaction
> > > is stalled subsequent faulting transactions are terminated, which avoids
> > > this problem, but the MMU-500 follows the spec here.
> > >
> > > To work around these problem, disable stall-on-fault as soon as we get a
> > > page fault until a cooldown period after pagefaults stop. This allows
> > > the GMU some guaranteed time to continue working. We only use
> > > stall-on-fault to halt the GPU while we collect a devcoredump and we
> > > always terminate the transaction afterward, so it's fine to miss some
> > > subsequent page faults. We also keep it disabled so long as the current
> > > devcoredump hasn't been deleted, because in that case we likely won't
> > > capture another one if there's a fault.
> > >
> > > After this commit HFI messages still occasionally time out, because the
> > > crashdump handler doesn't run fast enough to let the GMU resume, but the
> > > driver seems to recover from it. This will probably go away after the
> > > HFI timeout is increased.
> > >
> > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > ---
> > >  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 ++
> > >  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  4 ++++
> > >  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 42 ++++++++++++++++++++++++++++++++-
> > >  drivers/gpu/drm/msm/adreno/adreno_gpu.h | 24 +++++++++++++++++++
> > >  drivers/gpu/drm/msm/msm_iommu.c         |  9 +++++++
> > >  drivers/gpu/drm/msm/msm_mmu.h           |  1 +
> > >  6 files changed, 81 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > > index 71dca78cd7a5324e9ff5b14f173e2209fa42e196..670141531112c9d29cef8ef1fd51b74759fdd6d2 100644
> > > --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > > +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> > > @@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> > >         struct msm_ringbuffer *ring = submit->ring;
> > >         unsigned int i, ibs = 0;
> > >
> > > +       adreno_check_and_reenable_stall(adreno_gpu);
> > > +
> > >         if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
> > >                 ring->cur_ctx_seqno = 0;
> > >                 a5xx_submit_in_rb(gpu, submit);
> > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > > index 0ae29a7c8a4d3f74236a35cc919f69d5c0a384a0..5a34cd2109a2d74c92841448a61ccb0d4f34e264 100644
> > > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> > > @@ -212,6 +212,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> > >         struct msm_ringbuffer *ring = submit->ring;
> > >         unsigned int i, ibs = 0;
> > >
> > > +       adreno_check_and_reenable_stall(adreno_gpu);
> > > +
> > >         a6xx_set_pagetable(a6xx_gpu, ring, submit);
> > >
> > >         get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
> > > @@ -335,6 +337,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
> > >         struct msm_ringbuffer *ring = submit->ring;
> > >         unsigned int i, ibs = 0;
> > >
> > > +       adreno_check_and_reenable_stall(adreno_gpu);
> > > +
> > >         /*
> > >          * Toggle concurrent binning for pagetable switch and set the thread to
> > >          * BR since only it can execute the pagetable switch packets.
> > > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > > index 1238f326597808eb28b4c6822cbd41a26e555eb9..bac586101dc0494f46b069a8440a45825dfe9b5e 100644
> > > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> > > @@ -246,16 +246,53 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
> > >         return SZ_4G;
> > >  }
> > >
> > > +void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
> > > +{
> > > +       struct msm_gpu *gpu = &adreno_gpu->base;
> > > +       unsigned long flags;
> > > +
> > > +       /*
> > > +        * Wait until the cooldown period has passed and we would actually
> > > +        * collect a crashdump to re-enable stall-on-fault.
> > > +        */
> > > +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, flags);
> > > +       if (!adreno_gpu->stall_enabled &&
> > > +                       ktime_after(ktime_get(), adreno_gpu->stall_reenable_time) &&
> > > +                       !READ_ONCE(gpu->crashstate)) {
> > > +               adreno_gpu->stall_enabled = true;
> > > +
> > > +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
> > > +       }
> > > +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, flags);
> > > +}
> > > +
> > >  #define ARM_SMMU_FSR_TF                 BIT(1)
> > >  #define ARM_SMMU_FSR_PF                        BIT(3)
> > >  #define ARM_SMMU_FSR_EF                        BIT(4)
> > > +#define ARM_SMMU_FSR_SS                        BIT(30)
> > >
> > >  int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
> > >                          struct adreno_smmu_fault_info *info, const char *block,
> > >                          u32 scratch[4])
> > >  {
> > > +       struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> > >         const char *type = "UNKNOWN";
> > > -       bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
> > > +       bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
> > > +               !READ_ONCE(gpu->crashstate);
> > > +       unsigned long irq_flags;
> > > +
> > > +       /*
> > > +        * In case there is a subsequent storm of pagefaults, disable
> > > +        * stall-on-fault for at least half a second.
> > > +        */
> > > +       spin_lock_irqsave(&adreno_gpu->fault_stall_lock, irq_flags);
> > > +       if (adreno_gpu->stall_enabled) {
> > > +               adreno_gpu->stall_enabled = false;
> > > +
> > > +               gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
> > > +       }
> > > +       adreno_gpu->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
> > > +       spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, irq_flags);
> > >
> > >         /*
> > >          * If we aren't going to be resuming later from fault_worker, then do
> > > @@ -1143,6 +1180,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
> > >                 adreno_gpu->info->inactive_period);
> > >         pm_runtime_use_autosuspend(dev);
> > >
> > > +       spin_lock_init(&adreno_gpu->fault_stall_lock);
> > > +       adreno_gpu->stall_enabled = true;
> > > +
> > >         return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
> > >                         gpu_name, &adreno_gpu_config);
> > >  }
> > > diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > > index dcf454629ce037b2a8274a6699674ad754ce1f07..a528036b46216bd898f6d48c5fb0555c4c4b053b 100644
> > > --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> > > @@ -205,6 +205,28 @@ struct adreno_gpu {
> > >         /* firmware: */
> > >         const struct firmware *fw[ADRENO_FW_MAX];
> > >
> > > +       /**
> > > +        * fault_stall_lock:
> >
> > nit, @fault_stall_lock:  And for
> > fault_stall_reenable_time/stall_enabled, it wouldn't hurt to add
> > something along the lines of "Protected by @fault_stall_lock".  I've
> > been slowly trying to improve the comment docs over time, I have some
> > of that in my vmbind patchset.
> >
> > Anyways, with those nits addressed, r-b
> >
> > BR,
> > -R
> >
> > > +        *
> > > +        * Serialize changes to stall-on-fault state.
> > > +        */
> > > +       spinlock_t fault_stall_lock;
> > > +
> > > +       /**
> > > +        * fault_stall_reenable_time:
> > > +        *
> > > +        * if stall_enabled is false, when to reenable stall-on-fault.
> > > +        */
> > > +       ktime_t stall_reenable_time;
> > > +
> > > +       /**
> > > +        * stall_enabled:
> > > +        *
> > > +        * Whether stall-on-fault is currently enabled.
> > > +        */
> > > +       bool stall_enabled;
> > > +
> > > +
> > >         struct {
> > >                 /**
> > >                  * @rgb565_predicator: Unknown, introduced with A650 family,
> > > @@ -629,6 +651,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
> > >                          struct adreno_smmu_fault_info *info, const char *block,
> > >                          u32 scratch[4]);
> > >
> > > +void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
> > > +
> > >  int adreno_read_speedbin(struct device *dev, u32 *speedbin);
> > >
> > >  /*
> > > diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> > > index 2a94e82316f95c5f9dcc37ef0a4664a29e3492b2..8d5380e6dcc217c7c209b51527bf15748b3ada71 100644
> > > --- a/drivers/gpu/drm/msm/msm_iommu.c
> > > +++ b/drivers/gpu/drm/msm/msm_iommu.c
> > > @@ -351,6 +351,14 @@ static void msm_iommu_resume_translation(struct msm_mmu *mmu)
> > >                 adreno_smmu->resume_translation(adreno_smmu->cookie, true);
> > >  }
> > >
> > > +static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
> > > +{
> > > +       struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
> > > +
> > > +       if (adreno_smmu->set_stall)
> > > +               adreno_smmu->set_stall(adreno_smmu->cookie, enable);
> > > +}
> > > +
> > >  static void msm_iommu_detach(struct msm_mmu *mmu)
> > >  {
> > >         struct msm_iommu *iommu = to_msm_iommu(mmu);
> > > @@ -399,6 +407,7 @@ static const struct msm_mmu_funcs funcs = {
> > >                 .unmap = msm_iommu_unmap,
> > >                 .destroy = msm_iommu_destroy,
> > >                 .resume_translation = msm_iommu_resume_translation,
> > > +               .set_stall = msm_iommu_set_stall,
> > >  };
> > >
> > >  struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
> > > diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
> > > index 88af4f490881f2a6789ae2d03e1c02d10046331a..2694a356a17904e7572b767b16ed0cee806406cf 100644
> > > --- a/drivers/gpu/drm/msm/msm_mmu.h
> > > +++ b/drivers/gpu/drm/msm/msm_mmu.h
> > > @@ -16,6 +16,7 @@ struct msm_mmu_funcs {
> > >         int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
> > >         void (*destroy)(struct msm_mmu *mmu);
> > >         void (*resume_translation)(struct msm_mmu *mmu);
> > > +       void (*set_stall)(struct msm_mmu *mmu, bool enable);
> > >  };
> > >
> > >  enum msm_mmu_type {
> > >
> > > --
> > > 2.47.1
> > >


From andrii.nakryiko at gmail.com  Wed Mar  5 11:58:46 2025
From: andrii.nakryiko at gmail.com (Andrii Nakryiko)
Date: Wed, 5 Mar 2025 11:58:46 -0800
Subject: [PATCH -next v1 0/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
In-Reply-To: <62f93f79-a8d4-44a5-b276-3ac5af4ab25c@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com> <20250305152055.GB28112@redhat.com>
 <CAEf4BzbyFy0eQHLac3zR8GiGDOUqYoTGAWDbFaeou903OGOTpg@mail.gmail.com> <62f93f79-a8d4-44a5-b276-3ac5af4ab25c@redhat.com>
Message-ID: <CAEf4BzZcc6D3u5ATQmpkBt=8EhNuG7Xaibywx=hXcXTp346uFA@mail.gmail.com>

On Wed, Mar 5, 2025 at 11:47?AM David Hildenbrand <david at redhat.com> wrote:
>
> On 05.03.25 20:43, Andrii Nakryiko wrote:
> > On Wed, Mar 5, 2025 at 7:22?AM Oleg Nesterov <oleg at redhat.com> wrote:
> >>
> >> On 03/04, David Hildenbrand wrote:
> >>>
> >>> Currently, uprobe_write_opcode() implements COW-breaking manually, which is
> >>> really far from ideal.
> >>
> >> To say at least ;)
> >>
> >> David, thanks for doing this. I'll try to read 3/3 tomorrow, but I don't
> >> think I can really help. Let me repeat, this code was written many years
> >> ago, I forgot everything, and today my understanding of mm/ is very poor.
> >> But I'll try anyway.
> >>
> >>> Are there any uprobe tests / benchmarks that are worth running?
> >>
> >> All I know about uprobe tests is that bpf people run a lot of tests which
> >> use uprobes.
> >>
> >> Andrii, Jiri, what you advise?
> >>
> >
> > We do have a bunch of tests within BPF selftests:
> >
> > cd tools/testing/selftest/bpf && make -j$(nproc) && sudo ./test_progs -t uprobe
>
> I stumbled over them, but was so far not successful in building them in
> my test VM (did not try too hard, though). Will try harder now that I
> know that it actually tests uprobe properly :)

If you have decently recent Clang and pahole, then just make sure you
have kernel built before you build selftests. So above instructions
are more like:

1. cd <linux-repo>
2. cat tools/testing/selftests/bpf/{config, config.<your_arch>} >> .config
3. make -j$(nproc) # build kernel with that adjusted config
4. cd tools/testing/selftests/bpf
5. make -j$(nproc) # build BPF selftests
6. sudo ./test_progs -t uprobe # run selftests with "uprobe" in their name

>
> >
> > I also built an uprobe-stress tool to validate uprobe optimizations I
> > was doing, this one is the most stand-alone thing to use for testing,
> > please consider checking that. You can find it at [0], and see also
> > [1] and [2] where  I was helping Peter to build it from sources, so
> > that might be useful for you as well, if you run into problems with
> > building. Running something like `sudo ./uprobe-stress -a10 -t5 -m5
> > -f3` would hammer on this quite a bit.
>
> Thanks, I'll play with that as well.
>
> >
> > I'm just about to leave on a short vacation, so won't have time to go
> > over patches, but I plan to look at them when I'm back next week.
> >
> >    [0] https://github.com/libbpf/libbpf-bootstrap/tree/uprobe-stress
> >    [1] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZ+ygwfk8FKn5AS_Ny=igvGcFzdDLE2FjcvwjCKazEWMA at mail.gmail.com/
> >    [2] https://lore.kernel.org/linux-trace-kernel/CAEf4BzZqKCR-EQz6LTi-YvFY4RnYb_NnQXtwgZCv6aUo7gjkHg at mail.gmail.com
> >
> >> Oleg.
> >>
> >
>
>
> --
> Cheers,
>
> David / dhildenb
>


From krzysztof.kozlowski at linaro.org  Wed Mar  5 12:03:42 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 21:03:42 +0100
Subject: [PATCH v2 0/2] clk: samsung: Two header cleanups
Message-ID: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>

Changes in v2:
- mod_devicetable.h: also clk.c, clk.h, clk-exynos4.c,
  clk-exynos5-subcmu.c, clk-exynos2200.c and clk-exynos7870.c (Tudor)
- cleanup: clk-exynos2200.c and clk-exynos7870.c (Tudor)
- Rb tags
- Link to v1: https://lore.kernel.org/r/20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e at linaro.org

Best regards,
Krzysztof

---
Krzysztof Kozlowski (2):
      clk: samsung: Add missing mod_devicetable.h header
      clk: samsung: Drop unused clk.h and of.h headers

 drivers/clk/samsung/clk-exynos-audss.c   | 1 +
 drivers/clk/samsung/clk-exynos-clkout.c  | 1 +
 drivers/clk/samsung/clk-exynos2200.c     | 2 +-
 drivers/clk/samsung/clk-exynos3250.c     | 4 +---
 drivers/clk/samsung/clk-exynos4.c        | 2 +-
 drivers/clk/samsung/clk-exynos4412-isp.c | 2 +-
 drivers/clk/samsung/clk-exynos5-subcmu.c | 1 +
 drivers/clk/samsung/clk-exynos5250.c     | 1 +
 drivers/clk/samsung/clk-exynos5260.c     | 3 ---
 drivers/clk/samsung/clk-exynos5410.c     | 2 --
 drivers/clk/samsung/clk-exynos5420.c     | 1 +
 drivers/clk/samsung/clk-exynos5433.c     | 4 +---
 drivers/clk/samsung/clk-exynos7.c        | 1 -
 drivers/clk/samsung/clk-exynos7870.c     | 3 +--
 drivers/clk/samsung/clk-exynos7885.c     | 2 +-
 drivers/clk/samsung/clk-exynos850.c      | 2 +-
 drivers/clk/samsung/clk-exynos8895.c     | 2 +-
 drivers/clk/samsung/clk-exynos990.c      | 2 +-
 drivers/clk/samsung/clk-exynosautov9.c   | 2 +-
 drivers/clk/samsung/clk-exynosautov920.c | 2 +-
 drivers/clk/samsung/clk-fsd.c            | 2 +-
 drivers/clk/samsung/clk-gs101.c          | 2 +-
 drivers/clk/samsung/clk-s3c64xx.c        | 1 -
 drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +
 drivers/clk/samsung/clk-s5pv210.c        | 1 -
 drivers/clk/samsung/clk.c                | 2 +-
 drivers/clk/samsung/clk.h                | 1 +
 27 files changed, 22 insertions(+), 28 deletions(-)
---
base-commit: 7ec162622e66a4ff886f8f28712ea1b13069e1aa
change-id: 20250304-clk-samsung-headers-cleanup-c07b8dd50360

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Wed Mar  5 12:03:43 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 21:03:43 +0100
Subject: [PATCH v2 1/2] clk: samsung: Add missing mod_devicetable.h header
In-Reply-To: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
References: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
Message-ID: <20250305-clk-samsung-headers-cleanup-v2-1-ea1ae8e9e2bf@linaro.org>

Add an include for <mod_devicetable.h> in the drivers which use
of_device_id table to bring its declaration directly, not through some
other headers.

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos-audss.c   | 1 +
 drivers/clk/samsung/clk-exynos-clkout.c  | 1 +
 drivers/clk/samsung/clk-exynos2200.c     | 1 +
 drivers/clk/samsung/clk-exynos3250.c     | 2 +-
 drivers/clk/samsung/clk-exynos4.c        | 1 +
 drivers/clk/samsung/clk-exynos4412-isp.c | 1 +
 drivers/clk/samsung/clk-exynos5-subcmu.c | 1 +
 drivers/clk/samsung/clk-exynos5250.c     | 1 +
 drivers/clk/samsung/clk-exynos5420.c     | 1 +
 drivers/clk/samsung/clk-exynos5433.c     | 1 +
 drivers/clk/samsung/clk-exynos7870.c     | 1 +
 drivers/clk/samsung/clk-exynos7885.c     | 1 +
 drivers/clk/samsung/clk-exynos850.c      | 1 +
 drivers/clk/samsung/clk-exynos8895.c     | 1 +
 drivers/clk/samsung/clk-exynos990.c      | 1 +
 drivers/clk/samsung/clk-exynosautov9.c   | 1 +
 drivers/clk/samsung/clk-exynosautov920.c | 1 +
 drivers/clk/samsung/clk-fsd.c            | 1 +
 drivers/clk/samsung/clk-gs101.c          | 1 +
 drivers/clk/samsung/clk-s5pv210-audss.c  | 1 +
 drivers/clk/samsung/clk.c                | 1 +
 drivers/clk/samsung/clk.h                | 1 +
 22 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index e11ac67819ef26f04edfd4d1a26a5d9fde361aae..0f5ae3e8d000f9edddba4beb3c9a2e10d604c8a3 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index 2ef5748c139b37ca5429b9071ee0e06f44fcf28e..5f1a4f5e2e594f8e858dd92634de2019bbcf1ee3 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -10,6 +10,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/drivers/clk/samsung/clk-exynos2200.c b/drivers/clk/samsung/clk-exynos2200.c
index 151bdb35a46c42d0b50f48d47974065a892bbb5f..c7ee0fb58fca52ed711b12f1b729a5b732ebb20b 100644
--- a/drivers/clk/samsung/clk-exynos2200.c
+++ b/drivers/clk/samsung/clk-exynos2200.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index aec4d18c1f9ef93b62b718c85d731a6afd3e6b92..62ae5d845853e6fed2498cecb1151c8cf99bcae4 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -7,10 +7,10 @@
 
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
-
 #include <dt-bindings/clock/exynos3250.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 16be0c53903cf43537d6f5496c106a41eae62838..be5882e5c160f42154cb4472bbe54eb986d91637 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index 29c5644f059379f8a0770ce2214c32b9df7d76e3..a6595b8d918b972208ba0b61d4c0d7f13bccaa3d 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c
index 37312984730136a5f7220d8586469582f837ae54..03bbde76e3ce73d551e30711d527df67ba0b4b87 100644
--- a/drivers/clk/samsung/clk-exynos5-subcmu.c
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.c
@@ -5,6 +5,7 @@
 // Common Clock Framework support for Exynos5 power-domain dependent clocks
 
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 47e9ac2275ee356481f242ce59772f66daa32f14..e90d3a0848cbc24b2709c10795f6affcda404567 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/exynos5250.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 333c52fda17f69797d2defc36ad6293225d25e8a..a9df4e6db82fa7831d4e5c7210b0163d7d301ec1 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/exynos5420.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk.h>
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 609d31a7aa5247e6318884609d1e651001616b73..61e7e7ce1f60aba005018054aa2155455dece6bb 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
index 2ec4a4e489be30bd1cd2e6deac006bb8ac5bdc57..c0c8dc4aae746034b9d822ea11812ba1341abaa7 100644
--- a/drivers/clk/samsung/clk-exynos7870.c
+++ b/drivers/clk/samsung/clk-exynos7870.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
diff --git a/drivers/clk/samsung/clk-exynos7885.c b/drivers/clk/samsung/clk-exynos7885.c
index fc42251731edb6f8368d38638179056f8bc58335..79613affe8ab99d78cc677e688dbb03a2dc7cbb0 100644
--- a/drivers/clk/samsung/clk-exynos7885.c
+++ b/drivers/clk/samsung/clk-exynos7885.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index e00e213b1201c82ac0c70cfe23d5ccc9c04f2aa3..dfbb00312b03eea362f90149bfe36129a0d29285 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
index 29ec0c4a863524fe3fc5c223d762da87e5f13013..66f9b735e3818cc993f1f61acaef4c38bf2a3285 100644
--- a/drivers/clk/samsung/clk-exynos8895.c
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynos990.c b/drivers/clk/samsung/clk-exynos990.c
index 76f22a4a4631fadf400420b977f3f59f40f840c7..2cb77a7c3e7830163e8337fd035b5fa426480be5 100644
--- a/drivers/clk/samsung/clk-exynos990.c
+++ b/drivers/clk/samsung/clk-exynos990.c
@@ -7,6 +7,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
index 5971e680e566336ecdf55bdccacc3cea09a33201..1834751650df82a4a89a1a50de4c68d985a0cb60 100644
--- a/drivers/clk/samsung/clk-exynosautov9.c
+++ b/drivers/clk/samsung/clk-exynosautov9.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index 2a8bfd5d9abc8acced4e5a3eaacefe5fa724cbd2..f9b4e9f09bcd0e77ecf99e72273776454b302f31 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 9a6006c298c2a80da0e29aeca3b09cc827caac0c..079d3f4eda3f7acec84cc866b0ea7623104fa257 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 86b39edba12276745a124df6a2ea9c22d74b915a..97a4ccc103f62199cfd7d0d8d4b38bd2e127bfc3 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
index d19a3d9fd45239500c0f811aa27df86f832ea5c0..b1fd8fac3a4c0549f1143d02d11eeb95ee8967d3 100644
--- a/drivers/clk/samsung/clk-s5pv210-audss.c
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 #include <linux/init.h>
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 8d440cf56bd45970929bd556b739194ed7b80ce3..1ec00b06fe9151eb367344025e236961fa9db04f 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index fb06caa71f0aedaa4cb8cb14907fdc71cf7f72e2..18660c1ac6f0106b17b9efc9c6b3cd62d46f7b82 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -11,6 +11,7 @@
 #define __SAMSUNG_CLK_H
 
 #include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
 #include "clk-pll.h"
 #include "clk-cpu.h"
 

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 12:03:44 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 21:03:44 +0100
Subject: [PATCH v2 2/2] clk: samsung: Drop unused clk.h and of.h headers
In-Reply-To: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
References: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
Message-ID: <20250305-clk-samsung-headers-cleanup-v2-2-ea1ae8e9e2bf@linaro.org>

<clk.h> header is for clock consumers, so drop its include from the
Samsung clock controller drivers which do not use the consumer API
(there are few which do, so leave it there).

Drop including of <of.h> and <of_address.h> headers for all drivers
which do not use anything from generic OF API or of_iomap().

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos2200.c     | 1 -
 drivers/clk/samsung/clk-exynos3250.c     | 2 --
 drivers/clk/samsung/clk-exynos4.c        | 1 -
 drivers/clk/samsung/clk-exynos4412-isp.c | 1 -
 drivers/clk/samsung/clk-exynos5260.c     | 3 ---
 drivers/clk/samsung/clk-exynos5410.c     | 2 --
 drivers/clk/samsung/clk-exynos5433.c     | 3 ---
 drivers/clk/samsung/clk-exynos7.c        | 1 -
 drivers/clk/samsung/clk-exynos7870.c     | 2 --
 drivers/clk/samsung/clk-exynos7885.c     | 1 -
 drivers/clk/samsung/clk-exynos850.c      | 1 -
 drivers/clk/samsung/clk-exynos8895.c     | 1 -
 drivers/clk/samsung/clk-exynos990.c      | 1 -
 drivers/clk/samsung/clk-exynosautov9.c   | 1 -
 drivers/clk/samsung/clk-exynosautov920.c | 1 -
 drivers/clk/samsung/clk-fsd.c            | 1 -
 drivers/clk/samsung/clk-gs101.c          | 1 -
 drivers/clk/samsung/clk-s3c64xx.c        | 1 -
 drivers/clk/samsung/clk-s5pv210.c        | 1 -
 drivers/clk/samsung/clk.c                | 1 -
 20 files changed, 27 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos2200.c b/drivers/clk/samsung/clk-exynos2200.c
index c7ee0fb58fca52ed711b12f1b729a5b732ebb20b..eab9f5eecfa3de742560591c0e122096bfae3bcf 100644
--- a/drivers/clk/samsung/clk-exynos2200.c
+++ b/drivers/clk/samsung/clk-exynos2200.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos2200 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 62ae5d845853e6fed2498cecb1151c8cf99bcae4..84564ec4c8ecfa012743d3fa9826daeab4bb0f75 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -8,8 +8,6 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <dt-bindings/clock/exynos3250.h>
 
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index be5882e5c160f42154cb4472bbe54eb986d91637..374c26e5d9fda631cc5360eb73b3de498249cc49 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -9,7 +9,6 @@
 
 #include <dt-bindings/clock/exynos4.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index a6595b8d918b972208ba0b61d4c0d7f13bccaa3d..fa915057e109e0008ebe0b1b5d1652fd5804e82b 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -8,7 +8,6 @@
 
 #include <dt-bindings/clock/exynos4.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index fd0520d204dc7e993b443fa1811c81f0a2e16a3f..0a59598233704b201ea97e907286f761152f54aa 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -6,9 +6,6 @@
  * Common Clock Framework support for Exynos5260 SoC.
  */
 
-#include <linux/of.h>
-#include <linux/of_address.h>
-
 #include "clk-exynos5260.h"
 #include "clk.h"
 #include "clk-pll.h"
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 99b1bb4539fd0f08da61814887af7a40da06b002..baa9988c7bb717cd87fa3c340062afa784985090 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -9,8 +9,6 @@
 #include <dt-bindings/clock/exynos5410.h>
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/clk.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 61e7e7ce1f60aba005018054aa2155455dece6bb..4b2a861e7d573213e92666033893c44ae286b78a 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -6,11 +6,8 @@
  * Common Clock Framework support for Exynos5433 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index e6c938effa29bc067fa4cf864fe721cce37d9fda..fe0fa5bdbd4bca6921d07403637f93ba5c92208d 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -5,7 +5,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
 
 #include "clk.h"
 #include <dt-bindings/clock/exynos7-clk.h>
diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
index c0c8dc4aae746034b9d822ea11812ba1341abaa7..b3bcf3a1d0b7b1f66263c7ce135e7be758c95d72 100644
--- a/drivers/clk/samsung/clk-exynos7870.c
+++ b/drivers/clk/samsung/clk-exynos7870.c
@@ -6,11 +6,9 @@
  * Common Clock Framework support for Exynos7870.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 
 #include <dt-bindings/clock/samsung,exynos7870-cmu.h>
diff --git a/drivers/clk/samsung/clk-exynos7885.c b/drivers/clk/samsung/clk-exynos7885.c
index 79613affe8ab99d78cc677e688dbb03a2dc7cbb0..ba7cf79bc300112d01cc0f81e1d74f65309707eb 100644
--- a/drivers/clk/samsung/clk-exynos7885.c
+++ b/drivers/clk/samsung/clk-exynos7885.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos7885 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index dfbb00312b03eea362f90149bfe36129a0d29285..cf7e08cca78e04e496703b565881bf64dcf979c8 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos850 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
index 66f9b735e3818cc993f1f61acaef4c38bf2a3285..e6980a8f026fc33645e72a3bdfd3b5eb3a64fa84 100644
--- a/drivers/clk/samsung/clk-exynos8895.c
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for Exynos8895 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos990.c b/drivers/clk/samsung/clk-exynos990.c
index 2cb77a7c3e7830163e8337fd035b5fa426480be5..8d3f193d2b4d4c2146d9b8b57d76605b88dc9bbb 100644
--- a/drivers/clk/samsung/clk-exynos990.c
+++ b/drivers/clk/samsung/clk-exynos990.c
@@ -5,7 +5,6 @@
  * Common Clock Framework support for Exynos990.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
index 1834751650df82a4a89a1a50de4c68d985a0cb60..e4d7c7b96aa89be3677890102dd68f514a28aa08 100644
--- a/drivers/clk/samsung/clk-exynosautov9.c
+++ b/drivers/clk/samsung/clk-exynosautov9.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for ExynosAuto V9 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index f9b4e9f09bcd0e77ecf99e72273776454b302f31..dc8d4240f6defc623cc2e075923556747c98a59d 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for ExynosAuto v920 SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 079d3f4eda3f7acec84cc866b0ea7623104fa257..594931334574eba949af92095d2408f7a8f56933 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -8,7 +8,6 @@
  * Common Clock Framework support for FSD SoC.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 97a4ccc103f62199cfd7d0d8d4b38bd2e127bfc3..b58b8e1c272d594c2855a043cedcce5a3f293b84 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -6,7 +6,6 @@
  * Common Clock Framework support for GS101.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index e2ec8fe32e392844a85c63d837f10d3331d646f4..397a057af5d1e704e7ead7ba04b477fdc28c45bf 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -8,7 +8,6 @@
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/samsung.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
 
 #include <dt-bindings/clock/samsung,s3c64xx-clock.h>
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index cd85342e4ddbe28538d9f30e88c490089adc5e2c..9a4217cc1908aa60ebbe51b2b5c841138cc46ef3 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
 
 #include "clk.h"
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 1ec00b06fe9151eb367344025e236961fa9db04f..dbc9925ca8f46e951dfb5d391c0e744ca370abcc 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -10,7 +10,6 @@
 
 #include <linux/slab.h>
 #include <linux/clkdev.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>

-- 
2.43.0



From krzk at kernel.org  Wed Mar  5 12:14:05 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 21:14:05 +0100
Subject: [PATCH v5 2/2] clk: samsung: add initial exynos7870 clock driver
In-Reply-To: <b4fb36bc3970293ebdf1ac793bb3d752.sboyd@kernel.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org>
 <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
 <b4fb36bc3970293ebdf1ac793bb3d752.sboyd@kernel.org>
Message-ID: <0a7c72cb-4b59-4146-8438-52d13b457a18@kernel.org>

On 04/03/2025 19:16, Stephen Boyd wrote:
> Quoting Kaustabh Chakraborty (2025-02-28 19:57:13)
>> diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..2ec4a4e489be30bd1cd2e6deac006bb8ac5bdc57
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos7870.c
>> @@ -0,0 +1,1830 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2015 Samsung Electronics Co., Ltd.
>> + * Author: Kaustabh Chakraborty <kauschluss at disroot.org>
>> + *
>> + * Common Clock Framework support for Exynos7870.
>> + */
>> +
>> +#include <linux/clk.h>
> 
> Please remove this include as this is a clk provider and not a clk
> consumer.


I fixed it up for all drivers.

> 
>> +#include <linux/clk-provider.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include <dt-bindings/clock/samsung,exynos7870-cmu.h>
>> +
>> +#include "clk.h"
>> +#include "clk-exynos-arm64.h"
>> +
>> +/*
>> + * Register offsets for CMU_MIF (0x10460000)
>> + */
> [...]
>> +
>> +static const struct samsung_cmu_info peri_cmu_info __initconst = {
>> +       .gate_clks              = peri_gate_clks,
>> +       .nr_gate_clks           = ARRAY_SIZE(peri_gate_clks),
>> +       .clk_regs               = peri_clk_regs,
>> +       .nr_clk_regs            = ARRAY_SIZE(peri_clk_regs),
>> +       .nr_clk_ids             = PERI_NR_CLK,
>> +};
>> +
>> +static int __init exynos7870_cmu_probe(struct platform_device *pdev)
>> +{
>> +       const struct samsung_cmu_info *info;
>> +       struct device *dev = &pdev->dev;
>> +
>> +       info = of_device_get_match_data(dev);
> 
> Use device APIs please: device_get_match_data()


I expect here a follow up patch.

> 
>> +       exynos_arm64_register_cmu(dev, dev->of_node, info);
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct of_device_id exynos7870_cmu_of_match[] = {
>> +       {
>> +               .compatible = "samsung,exynos7870-cmu-mif",
>> +               .data = &mif_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-dispaud",
>> +               .data = &dispaud_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-fsys",
>> +               .data = &fsys_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-g3d",
>> +               .data = &g3d_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-isp",
>> +               .data = &isp_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-mfcmscl",
>> +               .data = &mfcmscl_cmu_info,
>> +       }, {
>> +               .compatible = "samsung,exynos7870-cmu-peri",
>> +               .data = &peri_cmu_info,
>> +       }, {
>> +       },
>> +};
>> +
>> +static struct platform_driver exynos7870_cmu_driver __refdata = {
> 
> Having __refdata here looks wrong.
> 
>> +       .driver = {
>> +               .name = "exynos7870-cmu",
>> +               .of_match_table = exynos7870_cmu_of_match,
>> +               .suppress_bind_attrs = true,
>> +       },
>> +       .probe = exynos7870_cmu_probe,
>> +};
>> +
>> +static int __init exynos7870_cmu_init(void)
>> +{
>> +       return platform_driver_register(&exynos7870_cmu_driver);
> 
> Is this supposed to be platform_driver_probe()? All the __init markings
> in the samsung clk driver look like potential problems if anything
> defers or is made into a module.

Indeed code is confusing but still correct. This is called from
core_initcall and nothing referencing __init/refdata can defer nor be a
module. There are modules but, AFAIR, they don't use __init/__refdata.

The __refdata here was probably so this can reference __initconst in
other places.

As you pointed out, probably the correct solution is to use
platform_driver_probe().


Best regards,
Krzysztof


From oliver.upton at linux.dev  Wed Mar  5 12:26:38 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:38 -0800
Subject: [PATCH v3 11/14] KVM: arm64: Remap PMUv3 events onto hardware
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-12-oliver.upton@linux.dev>

Map PMUv3 event IDs onto hardware, if the driver exposes such a helper.
This is expected to be quite rare, and only useful for non-PMUv3 hardware.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c    | 25 ++++++++++++++++++++++++-
 include/linux/perf/arm_pmu.h |  4 ++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 38d9490c17fd..5f4e9be8aa8b 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -677,6 +677,20 @@ static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
 	return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
 }
 
+static int kvm_map_pmu_event(struct kvm *kvm, unsigned int eventsel)
+{
+	struct arm_pmu *pmu = kvm->arch.arm_pmu;
+
+	/*
+	 * The CPU PMU likely isn't PMUv3; let the driver provide a mapping
+	 * for the guest's PMUv3 event ID.
+	 */
+	if (unlikely(pmu->map_pmuv3_event))
+		return pmu->map_pmuv3_event(eventsel);
+
+	return eventsel;
+}
+
 /**
  * kvm_pmu_create_perf_event - create a perf event for a counter
  * @pmc: Counter context
@@ -687,7 +701,8 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 	struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
 	struct perf_event *event;
 	struct perf_event_attr attr;
-	u64 eventsel, evtreg;
+	int eventsel;
+	u64 evtreg;
 
 	evtreg = kvm_pmc_read_evtreg(pmc);
 
@@ -713,6 +728,14 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 	    !test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
 		return;
 
+	/*
+	 * Don't create an event if we're running on hardware that requires
+	 * PMUv3 event translation and we couldn't find a valid mapping.
+	 */
+	eventsel = kvm_map_pmu_event(vcpu->kvm, eventsel);
+	if (eventsel < 0)
+		return;
+
 	memset(&attr, 0, sizeof(struct perf_event_attr));
 	attr.type = arm_pmu->pmu.type;
 	attr.size = sizeof(attr);
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 4b5b83677e3f..7ce6dea5bfa9 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -100,6 +100,10 @@ struct arm_pmu {
 	void		(*stop)(struct arm_pmu *);
 	void		(*reset)(void *);
 	int		(*map_event)(struct perf_event *event);
+	/*
+	 * Called by KVM to map the PMUv3 event space onto non-PMUv3 hardware.
+	 */
+	int		(*map_pmuv3_event)(unsigned int eventsel);
 	DECLARE_BITMAP(cntr_mask, ARMPMU_MAX_HWEVENTS);
 	bool		secure_access; /* 32-bit ARM only */
 #define ARMV8_PMUV3_MAX_COMMON_EVENTS		0x40
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:39 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:39 -0800
Subject: [PATCH v3 12/14] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-13-oliver.upton@linux.dev>

Apple M* parts carry some IMP DEF traps for guest accesses to PMUv3
registers, even though the underlying hardware doesn't implement PMUv3.
This means it is possible to virtualize PMUv3 for KVM guests.

Add a helper for mapping common PMUv3 event IDs onto hardware event IDs,
keeping the implementation-specific crud in the PMU driver rather than
KVM proper. Populate the pmceid_bitmap based on the supported events so
KVM can provide synthetic PMCEID* values to the guest.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 drivers/perf/apple_m1_cpu_pmu.c | 35 +++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index d6d4ff6da862..6be703619a97 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -12,6 +12,7 @@
 
 #include <linux/of.h>
 #include <linux/perf/arm_pmu.h>
+#include <linux/perf/arm_pmuv3.h>
 #include <linux/platform_device.h>
 
 #include <asm/apple_m1_pmu.h>
@@ -174,6 +175,17 @@ static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
 	[PERF_COUNT_HW_BRANCH_MISSES]		= M1_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
 };
 
+#define M1_PMUV3_EVENT_MAP(pmuv3_event, m1_event)				\
+	[ARMV8_PMUV3_PERFCTR_##pmuv3_event]	= M1_PMU_PERFCTR_##m1_event
+
+static const u16 m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
+	[0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1]	= HW_OP_UNSUPPORTED,
+	M1_PMUV3_EVENT_MAP(INST_RETIRED,	INST_ALL),
+	M1_PMUV3_EVENT_MAP(CPU_CYCLES,		CORE_ACTIVE_CYCLE),
+	M1_PMUV3_EVENT_MAP(BR_RETIRED,		INST_BRANCH),
+	M1_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED,	BRANCH_MISPRED_NONSPEC),
+};
+
 /* sysfs definitions */
 static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
 					struct device_attribute *attr,
@@ -558,6 +570,26 @@ static int m2_pmu_map_event(struct perf_event *event)
 	return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
 }
 
+static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
+{
+	u16 m1_event = HW_OP_UNSUPPORTED;
+
+	if (eventsel < ARMV8_PMUV3_MAX_COMMON_EVENTS)
+		m1_event = m1_pmu_pmceid_map[eventsel];
+
+	return m1_event == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : m1_event;
+}
+
+static void m1_pmu_init_pmceid(struct arm_pmu *pmu)
+{
+	unsigned int event;
+
+	for (event = 0; event < ARMV8_PMUV3_MAX_COMMON_EVENTS; event++) {
+		if (m1_pmu_map_pmuv3_event(event) >= 0)
+			set_bit(event, pmu->pmceid_bitmap);
+	}
+}
+
 static void m1_pmu_reset(void *info)
 {
 	int i;
@@ -618,6 +650,9 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
 	cpu_pmu->reset		  = m1_pmu_reset;
 	cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
 
+	cpu_pmu->map_pmuv3_event  = m1_pmu_map_pmuv3_event;
+	m1_pmu_init_pmceid(cpu_pmu);
+
 	bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
 	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
 	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:30:21 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:30:21 -0800
Subject: [PATCH v3 13/14] KVM: arm64: Provide 1 event counter on IMPDEF hardware
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305203021.428366-1-oliver.upton@linux.dev>

PMUv3 requires that all programmable event counters are capable of
counting any event. The Apple M* PMU is quite a bit different, and
events have affinities for particular PMCs.

Expose 1 event counter on IMPDEF hardware, allowing the guest to do
something useful with its PMU while also upholding the requirements of
the architecture.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 5f4e9be8aa8b..51fb47e0bf89 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1038,6 +1038,13 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
 {
 	struct arm_pmu *arm_pmu = kvm->arch.arm_pmu;
 
+	/*
+	 * PMUv3 requires that all event counters are capable of counting any
+	 * event, though the same may not be true of non-PMUv3 hardware.
+	 */
+	if (cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+		return 1;
+
 	/*
 	 * The arm_pmu->cntr_mask considers the fixed counter(s) as well.
 	 * Ignore those and return only the general-purpose counters.
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:30:40 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:30:40 -0800
Subject: [PATCH v3 14/14] arm64: Enable IMP DEF PMUv3 traps on Apple M*
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305203040.428448-1-oliver.upton@linux.dev>

Apple M1 and M2 CPUs support IMPDEF traps of the PMUv3 sysregs, allowing
a hypervisor to virtualize an architectural PMU for a VM. Flip the
appropriate bit in HACR_EL2 on supporting hardware.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kernel/cpu_errata.c | 44 ++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 7ce555862895..a1e16b156fab 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -194,6 +194,43 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
 	return is_midr_in_range(midr, &range) && has_dic;
 }
 
+static const struct midr_range impdef_pmuv3_cpus[] = {
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
+	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
+	{},
+};
+
+static bool has_impdef_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+	unsigned int pmuver;
+
+	if (!is_kernel_in_hyp_mode())
+		return false;
+
+	pmuver = cpuid_feature_extract_unsigned_field(dfr0,
+						      ID_AA64DFR0_EL1_PMUVer_SHIFT);
+	if (pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+		return false;
+
+	return is_midr_in_range_list(read_cpuid_id(), impdef_pmuv3_cpus);
+}
+
+static void cpu_enable_impdef_pmuv3_traps(const struct arm64_cpu_capabilities *__unused)
+{
+	sysreg_clear_set_s(SYS_HACR_EL2, 0, BIT(56));
+}
+
 #ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
 static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
@@ -794,6 +831,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 					{}
 				})),
 	},
+	{
+		.desc = "Apple IMPDEF PMUv3 Traps",
+		.capability = ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.matches = has_impdef_pmuv3,
+		.cpu_enable = cpu_enable_impdef_pmuv3_traps,
+	},
 	{
 	}
 };
-- 
2.39.5



From krzk at kernel.org  Wed Mar  5 12:37:10 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 21:37:10 +0100
Subject: [PATCH v5 2/2] clk: samsung: add initial exynos7870 clock driver
In-Reply-To: <0a7c72cb-4b59-4146-8438-52d13b457a18@kernel.org>
References: <20250301-exynos7870-pmu-clocks-v5-0-715b646d5206@disroot.org>
 <20250301-exynos7870-pmu-clocks-v5-2-715b646d5206@disroot.org>
 <b4fb36bc3970293ebdf1ac793bb3d752.sboyd@kernel.org>
 <0a7c72cb-4b59-4146-8438-52d13b457a18@kernel.org>
Message-ID: <aacbf2c0-1fda-4ce6-a04b-69663a34f0a0@kernel.org>

On 05/03/2025 21:14, Krzysztof Kozlowski wrote:
> On 04/03/2025 19:16, Stephen Boyd wrote:
>> Quoting Kaustabh Chakraborty (2025-02-28 19:57:13)
>>> diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
>>> new file mode 100644
>>> index 0000000000000000000000000000000000000000..2ec4a4e489be30bd1cd2e6deac006bb8ac5bdc57
>>> --- /dev/null
>>> +++ b/drivers/clk/samsung/clk-exynos7870.c
>>> @@ -0,0 +1,1830 @@
>>> +// SPDX-License-Identifier: GPL-2.0-only
>>> +/*
>>> + * Copyright (C) 2015 Samsung Electronics Co., Ltd.
>>> + * Author: Kaustabh Chakraborty <kauschluss at disroot.org>
>>> + *
>>> + * Common Clock Framework support for Exynos7870.
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>
>> Please remove this include as this is a clk provider and not a clk
>> consumer.
> 
> 
> I fixed it up for all drivers.
> 
>>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/platform_device.h>
>>> +
>>> +#include <dt-bindings/clock/samsung,exynos7870-cmu.h>
>>> +
>>> +#include "clk.h"
>>> +#include "clk-exynos-arm64.h"
>>> +
>>> +/*
>>> + * Register offsets for CMU_MIF (0x10460000)
>>> + */
>> [...]
>>> +
>>> +static const struct samsung_cmu_info peri_cmu_info __initconst = {
>>> +       .gate_clks              = peri_gate_clks,
>>> +       .nr_gate_clks           = ARRAY_SIZE(peri_gate_clks),
>>> +       .clk_regs               = peri_clk_regs,
>>> +       .nr_clk_regs            = ARRAY_SIZE(peri_clk_regs),
>>> +       .nr_clk_ids             = PERI_NR_CLK,
>>> +};
>>> +
>>> +static int __init exynos7870_cmu_probe(struct platform_device *pdev)
>>> +{
>>> +       const struct samsung_cmu_info *info;
>>> +       struct device *dev = &pdev->dev;
>>> +
>>> +       info = of_device_get_match_data(dev);
>>
>> Use device APIs please: device_get_match_data()
> 
> 
> I expect here a follow up patch.
> 
>>
>>> +       exynos_arm64_register_cmu(dev, dev->of_node, info);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct of_device_id exynos7870_cmu_of_match[] = {
>>> +       {
>>> +               .compatible = "samsung,exynos7870-cmu-mif",
>>> +               .data = &mif_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-dispaud",
>>> +               .data = &dispaud_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-fsys",
>>> +               .data = &fsys_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-g3d",
>>> +               .data = &g3d_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-isp",
>>> +               .data = &isp_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-mfcmscl",
>>> +               .data = &mfcmscl_cmu_info,
>>> +       }, {
>>> +               .compatible = "samsung,exynos7870-cmu-peri",
>>> +               .data = &peri_cmu_info,
>>> +       }, {
>>> +       },
>>> +};
>>> +
>>> +static struct platform_driver exynos7870_cmu_driver __refdata = {
>>
>> Having __refdata here looks wrong.
>>
>>> +       .driver = {
>>> +               .name = "exynos7870-cmu",
>>> +               .of_match_table = exynos7870_cmu_of_match,
>>> +               .suppress_bind_attrs = true,
>>> +       },
>>> +       .probe = exynos7870_cmu_probe,
>>> +};
>>> +
>>> +static int __init exynos7870_cmu_init(void)
>>> +{
>>> +       return platform_driver_register(&exynos7870_cmu_driver);
>>
>> Is this supposed to be platform_driver_probe()? All the __init markings
>> in the samsung clk driver look like potential problems if anything
>> defers or is made into a module.
> 
> Indeed code is confusing but still correct. This is called from
> core_initcall and nothing referencing __init/refdata can defer nor be a
> module. There are modules but, AFAIR, they don't use __init/__refdata.
> 
> The __refdata here was probably so this can reference __initconst in
> other places.
> 
> As you pointed out, probably the correct solution is to use
> platform_driver_probe().
I'll fix this and existing drivers.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar  5 12:37:42 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 21:37:42 +0100
Subject: [PATCH v2 3/3] clk: samsung: introduce Exynos2200 clock driver
In-Reply-To: <7b182615f1439dd39a17b8e74cf740bf.sboyd@kernel.org>
References: <20250223115601.723886-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223115601.723886-4-ivo.ivanov.ivanov1@gmail.com>
 <7b182615f1439dd39a17b8e74cf740bf.sboyd@kernel.org>
Message-ID: <d0f6fba8-cf04-4040-add4-35e001473f22@kernel.org>

On 04/03/2025 19:19, Stephen Boyd wrote:
> Quoting Ivaylo Ivanov (2025-02-23 03:56:00)
>> diff --git a/drivers/clk/samsung/clk-exynos2200.c b/drivers/clk/samsung/clk-exynos2200.c
>> new file mode 100644
>> index 000000000..151bdb35a
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos2200.c
>> @@ -0,0 +1,3928 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2025 Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>> + * Author: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>> + *
>> + * Common Clock Framework support for Exynos2200 SoC.
>> + */
>> +
>> +#include <linux/clk.h>
> 
> Remove this include because this is a clk provider and not a clk
> consumer.

I sent a fix for this.

> 

>> +static struct platform_driver exynos2200_cmu_driver __refdata = {
>> +       .driver = {
>> +               .name = "exynos2200-cmu",
>> +               .of_match_table = exynos2200_cmu_of_match,
>> +               .suppress_bind_attrs = true,
>> +       },
>> +       .probe = exynos2200_cmu_probe,
>> +};
>> +
>> +static int __init exynos2200_cmu_init(void)
>> +{
>> +       return platform_driver_register(&exynos2200_cmu_driver);
> 
> Was this supposed to be platform_driver_probe()? The __refdata usage
> suggests that but all of the __init markings and stuff in the samsung
> clk driver worry me.


I'll fix this and existing drivers.


Best regards,
Krzysztof


From david at redhat.com  Wed Mar  5 12:53:20 2025
From: david at redhat.com (David Hildenbrand)
Date: Wed, 5 Mar 2025 21:53:20 +0100
Subject: [PATCH -next v1 0/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <CAEf4BzZcc6D3u5ATQmpkBt=8EhNuG7Xaibywx=hXcXTp346uFA@mail.gmail.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250305152055.GB28112@redhat.com>
 <CAEf4BzbyFy0eQHLac3zR8GiGDOUqYoTGAWDbFaeou903OGOTpg@mail.gmail.com>
 <62f93f79-a8d4-44a5-b276-3ac5af4ab25c@redhat.com>
 <CAEf4BzZcc6D3u5ATQmpkBt=8EhNuG7Xaibywx=hXcXTp346uFA@mail.gmail.com>
Message-ID: <e34433c3-6e7c-490e-a334-92800db0d190@redhat.com>

On 05.03.25 20:58, Andrii Nakryiko wrote:
> On Wed, Mar 5, 2025 at 11:47?AM David Hildenbrand <david at redhat.com> wrote:
>>
>> On 05.03.25 20:43, Andrii Nakryiko wrote:
>>> On Wed, Mar 5, 2025 at 7:22?AM Oleg Nesterov <oleg at redhat.com> wrote:
>>>>
>>>> On 03/04, David Hildenbrand wrote:
>>>>>
>>>>> Currently, uprobe_write_opcode() implements COW-breaking manually, which is
>>>>> really far from ideal.
>>>>
>>>> To say at least ;)
>>>>
>>>> David, thanks for doing this. I'll try to read 3/3 tomorrow, but I don't
>>>> think I can really help. Let me repeat, this code was written many years
>>>> ago, I forgot everything, and today my understanding of mm/ is very poor.
>>>> But I'll try anyway.
>>>>
>>>>> Are there any uprobe tests / benchmarks that are worth running?
>>>>
>>>> All I know about uprobe tests is that bpf people run a lot of tests which
>>>> use uprobes.
>>>>
>>>> Andrii, Jiri, what you advise?
>>>>
>>>
>>> We do have a bunch of tests within BPF selftests:
>>>
>>> cd tools/testing/selftest/bpf && make -j$(nproc) && sudo ./test_progs -t uprobe
>>
>> I stumbled over them, but was so far not successful in building them in
>> my test VM (did not try too hard, though). Will try harder now that I
>> know that it actually tests uprobe properly :)
> 
> If you have decently recent Clang and pahole, then just make sure you
> have kernel built before you build selftests. So above instructions
> are more like:
> 
> 1. cd <linux-repo>
> 2. cat tools/testing/selftests/bpf/{config, config.<your_arch>} >> .config

^ that did the trick

> 3. make -j$(nproc) # build kernel with that adjusted config
> 4. cd tools/testing/selftests/bpf
> 5. make -j$(nproc) # build BPF selftests
> 6. sudo ./test_progs -t uprobe # run selftests with "uprobe" in their name

#444     uprobe:OK
#445     uprobe_autoattach:OK
#446/1   uprobe_multi_test/skel_api:OK
#446/2   uprobe_multi_test/attach_api_pattern:OK
#446/3   uprobe_multi_test/attach_api_syms:OK
#446/4   uprobe_multi_test/link_api:OK
#446/5   uprobe_multi_test/bench_uprobe:OK
#446/6   uprobe_multi_test/bench_usdt:OK
#446/7   uprobe_multi_test/attach_api_fails:OK
#446/8   uprobe_multi_test/attach_uprobe_fails:OK
#446/9   uprobe_multi_test/consumers:OK
#446/10  uprobe_multi_test/filter_fork:OK
#446/11  uprobe_multi_test/filter_clone_vm:OK
#446/12  uprobe_multi_test/session:OK
#446/13  uprobe_multi_test/session_single:OK
#446/14  uprobe_multi_test/session_cookie:OK
#446/15  uprobe_multi_test/session_cookie_recursive:OK
#446/16  uprobe_multi_test/uprobe_sesison_return_0:OK
#446/17  uprobe_multi_test/uprobe_sesison_return_1:OK
#446/18  uprobe_multi_test/uprobe_sesison_return_2:OK
#446     uprobe_multi_test:OK
#447/1   uprobe_syscall/uretprobe_regs_equal:OK
#447/2   uprobe_syscall/uretprobe_regs_change:OK
#447/3   uprobe_syscall/uretprobe_syscall_call:OK
#447/4   uprobe_syscall/uretprobe_shadow_stack:SKIP
#447     uprobe_syscall:OK (SKIP: 1/4)
Summary: 4/21 PASSED, 1 SKIPPED, 0 FAILED


Looks promising, thanks!

-- 
Cheers,

David / dhildenb



From arnd at kernel.org  Wed Mar  5 13:14:02 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Wed,  5 Mar 2025 22:14:02 +0100
Subject: [PATCH] soc: samsung: include linux/array_size.h where needed
Message-ID: <20250305211446.43772-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

This does not necessarily get included through asm/io.h:

drivers/soc/samsung/exynos3250-pmu.c:120:18: error: use of undeclared identifier 'ARRAY_SIZE'
  120 |         for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
      |                         ^
drivers/soc/samsung/exynos5250-pmu.c:162:18: error: use of undeclared identifier 'ARRAY_SIZE'
  162 |         for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
      |                         ^

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/soc/samsung/exynos-asv.c     | 1 +
 drivers/soc/samsung/exynos-chipid.c  | 1 +
 drivers/soc/samsung/exynos-pmu.c     | 1 +
 drivers/soc/samsung/exynos-usi.c     | 1 +
 drivers/soc/samsung/exynos3250-pmu.c | 1 +
 drivers/soc/samsung/exynos5250-pmu.c | 1 +
 drivers/soc/samsung/exynos5420-pmu.c | 1 +
 7 files changed, 7 insertions(+)

diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
index 97006cc3b946..8e681f519526 100644
--- a/drivers/soc/samsung/exynos-asv.c
+++ b/drivers/soc/samsung/exynos-asv.c
@@ -9,6 +9,7 @@
  * Samsung Exynos SoC Adaptive Supply Voltage support
  */
 
+#include <linux/array_size.h>
 #include <linux/cpu.h>
 #include <linux/device.h>
 #include <linux/energy_model.h>
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
index 3f1a654c7e66..deb1d882cd4c 100644
--- a/drivers/soc/samsung/exynos-chipid.c
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -12,6 +12,7 @@
  * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support
  */
 
+#include <linux/array_size.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/mfd/syscon.h>
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index dd5256e5aae1..c40313886a01 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -5,6 +5,7 @@
 //
 // Exynos - CPU PMU(Power Management Unit) support
 
+#include <linux/array_size.h>
 #include <linux/arm-smccc.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/drivers/soc/samsung/exynos-usi.c b/drivers/soc/samsung/exynos-usi.c
index 173b76720079..c5661ac19f7b 100644
--- a/drivers/soc/samsung/exynos-usi.c
+++ b/drivers/soc/samsung/exynos-usi.c
@@ -6,6 +6,7 @@
  * Samsung Exynos USI driver (Universal Serial Interface).
  */
 
+#include <linux/array_size.h>
 #include <linux/clk.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c
index 30f230ed1769..26c9c6e9f551 100644
--- a/drivers/soc/samsung/exynos3250-pmu.c
+++ b/drivers/soc/samsung/exynos3250-pmu.c
@@ -7,6 +7,7 @@
 
 #include <linux/soc/samsung/exynos-regs-pmu.h>
 #include <linux/soc/samsung/exynos-pmu.h>
+#include <linux/array_size.h>
 
 #include "exynos-pmu.h"
 
diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c
index 7a2d50be6b4a..ae693d8d508b 100644
--- a/drivers/soc/samsung/exynos5250-pmu.c
+++ b/drivers/soc/samsung/exynos5250-pmu.c
@@ -7,6 +7,7 @@
 
 #include <linux/soc/samsung/exynos-regs-pmu.h>
 #include <linux/soc/samsung/exynos-pmu.h>
+#include <linux/array_size.h>
 
 #include "exynos-pmu.h"
 
diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c
index 6fedcd78cb45..58a2209795f7 100644
--- a/drivers/soc/samsung/exynos5420-pmu.c
+++ b/drivers/soc/samsung/exynos5420-pmu.c
@@ -5,6 +5,7 @@
 //
 // Exynos5420 - CPU PMU (Power Management Unit) support
 
+#include <linux/array_size.h>
 #include <linux/pm.h>
 #include <linux/soc/samsung/exynos-regs-pmu.h>
 #include <linux/soc/samsung/exynos-pmu.h>
-- 
2.39.5



From nicolinc at nvidia.com  Wed Mar  5 13:18:00 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Wed, 5 Mar 2025 13:18:00 -0800
Subject: [PATCH] iommufd: Set domain->iommufd_hwpt in all hwpt->domain allocators
Message-ID: <20250305211800.229465-1-nicolinc@nvidia.com>

Setting domain->iommufd_hwpt in iommufd_hwpt_alloc() only covers the HWPT
allocations from user space, but not for an auto domain. This resulted in
a NULL pointer access in the auto domain pathway:
 Unable to handle kernel NULL pointer dereference at
 	virtual address 0000000000000008
 pc : iommufd_sw_msi+0x54/0x2b0
 lr : iommufd_sw_msi+0x40/0x2b0
 Call trace:
  iommufd_sw_msi+0x54/0x2b0 (P)
  iommu_dma_prepare_msi+0x64/0xa8
  its_irq_domain_alloc+0xf0/0x2c0
  irq_domain_alloc_irqs_parent+0x2c/0xa8
  msi_domain_alloc+0xa0/0x1a8

Since iommufd_sw_msi() requires to access the domain->iommufd_hwpt, it is
better to set that explicitly prior to calling iommu_domain_set_sw_msi().

Fixes: 748706d7ca06 ("iommu: Turn fault_data to iommufd private pointer")
Reported-by: Ankit Agrawal <ankita at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/hw_pagetable.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 268315b1d8bc..1d4cfe3677dc 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -159,6 +159,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
 			goto out_abort;
 		}
 	}
+	hwpt->domain->iommufd_hwpt = hwpt;
 	iommu_domain_set_sw_msi(hwpt->domain, iommufd_sw_msi);
 
 	/*
@@ -255,6 +256,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
 		goto out_abort;
 	}
 	hwpt->domain->owner = ops;
+	hwpt->domain->iommufd_hwpt = hwpt;
 	iommu_domain_set_sw_msi(hwpt->domain, iommufd_sw_msi);
 
 	if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED)) {
@@ -311,6 +313,7 @@ iommufd_viommu_alloc_hwpt_nested(struct iommufd_viommu *viommu, u32 flags,
 		hwpt->domain = NULL;
 		goto out_abort;
 	}
+	hwpt->domain->iommufd_hwpt = hwpt;
 	hwpt->domain->owner = viommu->iommu_dev->ops;
 	iommu_domain_set_sw_msi(hwpt->domain, iommufd_sw_msi);
 
@@ -415,7 +418,6 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
 		refcount_inc(&fault->obj.users);
 		iommufd_put_object(ucmd->ictx, &fault->obj);
 	}
-	hwpt->domain->iommufd_hwpt = hwpt;
 
 	cmd->out_hwpt_id = hwpt->obj.id;
 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
-- 
2.43.0



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:20 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:20 +0100
Subject: [PATCH 0/7] Add RK3576 SAI Audio Controller Support
Message-ID: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>

This series adds support for Rockchip's Serial Audio Interface (SAI)
controller, found on SoCs such as the RK3576. The SAI is a flexible
controller IP that allows both transmitting and receiving digital audio
in the I2S, TDM and PCM formats. Instances of this controller are used
both for externally exposed audio interfaces, as well as for audio on
video interfaces such as HDMI.

Patch 1 and 2 do some preparatory work in the clock bindings and clock
controller. The RK3576 has the SAI0 through SAI4 output mclks as well as
the FSPI0 and FSPI1 clocks gated behind some GRF register writes. The
RK3588 had this for its I2S audio clocks as well, but got away with not
caring about it in mainline because the clocks were ungated by default.
This is no longer the case with RK3576: the SAI mclk need to be ungated
before they can be used.

The gritty details are in patch 2, but to sum it up: we need to
introduce a new clock branch type, and also rework the rockchip clock
code to deal with multiple separate GRF regmaps.

NB: checkpatch.pl seems to trip over patch 2 in some way that seems like
a combination of the diff being too clever and at the same time too
stupid.

Patch 3 adds the devicetree schema for the SAI. Right now, we only have
a RK3576 compatible, but as I understand it, the RK3528 uses this audio
controller as well.

Patch 4 is the main course and adds the driver. It's based on the
downstream vendor driver, but substantial changes have been made in the
hopes to make it suitable for upstream inclusion.

Patch 5 and 6 are boring devicetree changes to add the nodes and use
them in the ArmSoM Sige5 board. Patch 6 goes into some schematic-derived
knowledge about where the audio signal can actually be tapped into in
order to test this.

Patch 7 enables the driver in the arm64 defconfig, as the RK3576 is
supported in mainline, so its drivers should be enabled in the
defconfig.

To test this on the Sige5, I both soldered to the output 2 testpads, as
well as fashioned a cable to plug into the headphone header. I should
have some stuff arriving by mid-March to make more such cables, so if
you have a Sige5 and want to test this but don't happen to sit on a pile
of 03SUR-32S cables, then you may contact me off-list to request I send
you such a cable from Switzerland, and I'll see what I can do.

HDMI audio isn't enabled in this series yet, but I'll look into it
either for a v2 or in a follow-up series. I really wanted to get this
out to be reviewed now, as there's a substantial amount of code to look
at that is ready for both review and testing.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
Nicolas Frattaroli (7):
      dt-bindings: clock: rk3576: add IOC gated clocks
      clk: rockchip: add support for GRF gated clocks
      ASoC: dt-bindings: add schema for rockchip SAI controllers
      ASoC: rockchip: add Serial Audio Interface (SAI) driver
      arm64: dts: rockchip: Add RK3576 SAI nodes
      arm64: dts: rockchip: Add analog audio on RK3576 Sige5
      arm64: defconfig: Enable Rockchip SAI

 .../devicetree/bindings/sound/rockchip,sai.yaml    |  151 ++
 MAINTAINERS                                        |    7 +
 .../boot/dts/rockchip/rk3576-armsom-sige5.dts      |   56 +
 arch/arm64/boot/dts/rockchip/rk3576.dtsi           |  194 +++
 arch/arm64/configs/defconfig                       |    1 +
 drivers/clk/rockchip/Makefile                      |    1 +
 drivers/clk/rockchip/clk-rk3328.c                  |    6 +-
 drivers/clk/rockchip/clk-rk3568.c                  |    2 +-
 drivers/clk/rockchip/clk-rk3576.c                  |   59 +-
 drivers/clk/rockchip/clk.c                         |   24 +-
 drivers/clk/rockchip/clk.h                         |   49 +-
 drivers/clk/rockchip/gate-grf.c                    |  105 ++
 include/dt-bindings/clock/rockchip,rk3576-cru.h    |   10 +
 sound/soc/rockchip/Kconfig                         |    8 +
 sound/soc/rockchip/Makefile                        |    2 +
 sound/soc/rockchip/rockchip_sai.c                  | 1623 ++++++++++++++++++++
 sound/soc/rockchip/rockchip_sai.h                  |  251 +++
 17 files changed, 2533 insertions(+), 16 deletions(-)
---
base-commit: a03be51d680391ba113e2e22b38743c276b6e2fa
change-id: 20250305-rk3576-sai-c78e0430898e

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:21 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:21 +0100
Subject: [PATCH 1/7] dt-bindings: clock: rk3576: add IOC gated clocks
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-1-64e6cf863e9a@collabora.com>

Certain clocks on the RK3576 are additionally essentially "gated" behind
some bit toggles in the IOC GRF range. Downstream ungates these by
adding a separate clock driver that maps over the GRF range and leaks
their implementation of this into the DT.

Instead, define some new clock IDs for these, so that consumers of these
types of clocks can properly articulate which clock they're using, so
that we can then add them to the clock driver for SoCs that need them.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 include/dt-bindings/clock/rockchip,rk3576-cru.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3576-cru.h b/include/dt-bindings/clock/rockchip,rk3576-cru.h
index 25aed298ac2c2e2d37e2b441c9d92ac68801be6e..9dbccd8ed4689ee85c9220c1404f971b73c7d4ea 100644
--- a/include/dt-bindings/clock/rockchip,rk3576-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3576-cru.h
@@ -589,4 +589,14 @@
 #define PCLK_EDP_S			569
 #define ACLK_KLAD			570
 
+/* IOC-controlled output clocks */
+#define CLK_SAI0_MCLKOUT_TO_IO		571
+#define CLK_SAI1_MCLKOUT_TO_IO		572
+#define CLK_SAI2_MCLKOUT_TO_IO		573
+#define CLK_SAI3_MCLKOUT_TO_IO		574
+#define CLK_SAI4_MCLKOUT_TO_IO		575
+#define CLK_SAI4_MCLKOUT_TO_IO		575
+#define CLK_FSPI0_TO_IO			576
+#define CLK_FSPI1_TO_IO			577
+
 #endif

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:22 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:22 +0100
Subject: [PATCH 2/7] clk: rockchip: add support for GRF gated clocks
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-2-64e6cf863e9a@collabora.com>

Certain Rockchip SoCs, the RK3576 in particular, have some clocks that
are essentially gated behind an additional GRF write. Downstream uses an
additional entirely separate clock driver that maps over the same
address range as ioc_grf in the DT.

Instead, this implementation introduces a new gate type, GRF gates.
These gates function quite like regular gates. In effect, this means
they'll only be enabled if the clock is used, which I feel is a more
appropriate way to describe this compared to doing it in, say, pinctrl,
or even in the drivers of the respective clock consumers such as SAI.

It should be noted that RK3588 has similar GRF-gated clocks, but has
gotten away with not having to deal with any of this because the clocks
are ungated by the hardware's register reset value by default. The
RK3576 is not so lucky, and the hardware's reset value gates them
instead, which means we'll have to ungate them somewhere.

In order to facilitate the GRF gating on RK3576, we introduce the
concept of auxiliary GRFs. The RK3576 has several defined GRF nodes, and
so far it could get away with just using one for MUXGRF by reassigning
the clock provider's grf member.

However, with the IOC GRF gated clocks, we now also need access to the
IOC GRF, so we can't get away with this anymore. Instead, we add a
hashtable to the clock provider struct, keyed by a grf type enum. The
clock branches can then specify through the use of a new member of that
enum's type (with corresponding changes to relevant macros) which GRF
range they would like to use.

The SoC-specific clk_init can then populate the hashtable with the GRFs
that it needs. This way, GRF-dependent clock branches don't have to be
registered in a different step than everything else, as they would need
to be had I extended the branch struct to instead take a pointer to a
GRF, which isn't available at the time most of our branches are defined.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 drivers/clk/rockchip/Makefile     |   1 +
 drivers/clk/rockchip/clk-rk3328.c |   6 +--
 drivers/clk/rockchip/clk-rk3568.c |   2 +-
 drivers/clk/rockchip/clk-rk3576.c |  59 +++++++++++++++++----
 drivers/clk/rockchip/clk.c        |  24 ++++++++-
 drivers/clk/rockchip/clk.h        |  49 +++++++++++++++++-
 drivers/clk/rockchip/gate-grf.c   | 105 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 230 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index e8ece20aebfdeffbdc5bfffd2c6f35f2cfcf74f6..f0e0b2c6e876a84610fb3ecf33cc1935b10058d9 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -14,6 +14,7 @@ clk-rockchip-y += clk-mmc-phase.o
 clk-rockchip-y += clk-muxgrf.o
 clk-rockchip-y += clk-ddr.o
 clk-rockchip-y += gate-link.o
+clk-rockchip-y += gate-grf.o
 clk-rockchip-$(CONFIG_RESET_CONTROLLER) += softrst.o
 
 obj-$(CONFIG_CLK_PX30)          += clk-px30.o
diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
index cf60fcf2fa5cde4ef97a05852f071763a4ccee40..cd5f65b6cdf55074c753f1dee96972c2a589c260 100644
--- a/drivers/clk/rockchip/clk-rk3328.c
+++ b/drivers/clk/rockchip/clk-rk3328.c
@@ -677,9 +677,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
 			RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
 			RK3328_CLKGATE_CON(3), 5, GFLAGS),
 	MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT,
-			RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
+			RK3328_GRF_MAC_CON1, 10, 1, MFLAGS, grf_type_sys),
 	MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT,
-			RK3328_GRF_SOC_CON4, 14, 1, MFLAGS),
+			RK3328_GRF_SOC_CON4, 14, 1, MFLAGS, grf_type_sys),
 
 	COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
 			RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
@@ -692,7 +692,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
 			RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
 			RK3328_CLKGATE_CON(9), 2, GFLAGS),
 	MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT,
-			RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
+			RK3328_GRF_MAC_CON2, 10, 1, MFLAGS, grf_type_sys),
 
 	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
 
diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
index 7d9279291e7692c5ebdda16563fd09f87732e6d1..5f250bb8260ca0447f7249f212a49597c6c54887 100644
--- a/drivers/clk/rockchip/clk-rk3568.c
+++ b/drivers/clk/rockchip/clk-rk3568.c
@@ -590,7 +590,7 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
 			RK3568_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS,
 			RK3568_CLKGATE_CON(4), 0, GFLAGS),
 	MUXGRF(CLK_DDR1X, "clk_ddr1x", clk_ddr1x_p, CLK_SET_RATE_PARENT,
-			RK3568_CLKSEL_CON(9), 15, 1, MFLAGS),
+			RK3568_CLKSEL_CON(9), 15, 1, MFLAGS, grf_type_sys),
 
 	COMPOSITE_NOMUX(CLK_MSCH, "clk_msch", "clk_ddr1x", CLK_IGNORE_UNUSED,
 			RK3568_CLKSEL_CON(10), 0, 2, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3576.c b/drivers/clk/rockchip/clk-rk3576.c
index be703f250197af2097fa591837de03accb8c51da..1e269490ac7f6b56ed4e53a711c7d4d922b6e149 100644
--- a/drivers/clk/rockchip/clk-rk3576.c
+++ b/drivers/clk/rockchip/clk-rk3576.c
@@ -15,6 +15,7 @@
 
 #define RK3576_GRF_SOC_STATUS0		0x600
 #define RK3576_PMU0_GRF_OSC_CON6	0x18
+#define RK3576_VCCIO_IOC_MISC_CON0	0x6400
 
 enum rk3576_plls {
 	bpll, lpll, vpll, aupll, cpll, gpll, ppll,
@@ -1481,6 +1482,14 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = {
 			RK3576_CLKGATE_CON(10), 0, GFLAGS),
 	GATE(CLK_SAI0_MCLKOUT, "clk_sai0_mclkout", "mclk_sai0_8ch", 0,
 			RK3576_CLKGATE_CON(10), 1, GFLAGS),
+	GATE_GRF(CLK_SAI0_MCLKOUT_TO_IO, "mclk_sai0_to_io", "clk_sai0_mclkout",
+			0, RK3576_VCCIO_IOC_MISC_CON0, 0, GFLAGS, grf_type_ioc),
+	GATE_GRF(CLK_SAI1_MCLKOUT_TO_IO, "mclk_sai1_to_io", "clk_sai1_mclkout",
+			0, RK3576_VCCIO_IOC_MISC_CON0, 1, GFLAGS, grf_type_ioc),
+	GATE_GRF(CLK_SAI2_MCLKOUT_TO_IO, "mclk_sai2_to_io", "clk_sai2_mclkout",
+			0, RK3576_VCCIO_IOC_MISC_CON0, 2, GFLAGS, grf_type_ioc),
+	GATE_GRF(CLK_SAI3_MCLKOUT_TO_IO, "mclk_sai3_to_io", "clk_sai3_mclkout",
+			0, RK3576_VCCIO_IOC_MISC_CON0, 3, GFLAGS, grf_type_ioc),
 
 	/* sdgmac */
 	COMPOSITE_NODIV(HCLK_SDGMAC_ROOT, "hclk_sdgmac_root", mux_200m_100m_50m_24m_p, 0,
@@ -1678,13 +1687,13 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = {
 
 	/* phy ref */
 	MUXGRF(CLK_PHY_REF_SRC, "clk_phy_ref_src", clk_phy_ref_src_p,  0,
-			RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS),
+			RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS, grf_type_pmu0),
 	MUXGRF(CLK_USBPHY_REF_SRC, "clk_usbphy_ref_src", clk_usbphy_ref_src_p,  0,
-			RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS),
+			RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS, grf_type_pmu0),
 	MUXGRF(CLK_CPLL_REF_SRC, "clk_cpll_ref_src", clk_cpll_ref_src_p,  0,
-			RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS),
+			RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS, grf_type_pmu0),
 	MUXGRF(CLK_AUPLL_REF_SRC, "clk_aupll_ref_src", clk_aupll_ref_src_p,  0,
-			RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS),
+			RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS, grf_type_pmu0),
 
 	/* secure ns */
 	COMPOSITE_NODIV(ACLK_SECURE_NS, "aclk_secure_ns", mux_350m_175m_116m_24m_p, CLK_IS_CRITICAL,
@@ -1727,17 +1736,26 @@ static void __init rk3576_clk_init(struct device_node *np)
 	struct rockchip_clk_provider *ctx;
 	unsigned long clk_nr_clks;
 	void __iomem *reg_base;
-	struct regmap *grf;
+	struct rockchip_aux_grf *ioc_grf_e;
+	struct rockchip_aux_grf *pmu0_grf_e;
+	struct regmap *ioc_grf;
+	struct regmap *pmu0_grf;
 
 	clk_nr_clks = rockchip_clk_find_max_clk_id(rk3576_clk_branches,
 					ARRAY_SIZE(rk3576_clk_branches)) + 1;
 
-	grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf");
-	if (IS_ERR(grf)) {
+	pmu0_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf");
+	if (IS_ERR(pmu0_grf)) {
 		pr_err("%s: could not get PMU0 GRF syscon\n", __func__);
 		return;
 	}
 
+	ioc_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-ioc-grf");
+	if (IS_ERR(ioc_grf)) {
+		pr_err("%s: could not get IOC GRF syscon\n", __func__);
+		return;
+	}
+
 	reg_base = of_iomap(np, 0);
 	if (!reg_base) {
 		pr_err("%s: could not map cru region\n", __func__);
@@ -1747,11 +1765,24 @@ static void __init rk3576_clk_init(struct device_node *np)
 	ctx = rockchip_clk_init(np, reg_base, clk_nr_clks);
 	if (IS_ERR(ctx)) {
 		pr_err("%s: rockchip clk init failed\n", __func__);
-		iounmap(reg_base);
-		return;
+		goto err_unmap;
 	}
 
-	ctx->grf = grf;
+	pmu0_grf_e = kzalloc(sizeof(*pmu0_grf_e), GFP_KERNEL);
+	if (!pmu0_grf_e)
+		goto err_unmap;
+
+	pmu0_grf_e->grf = pmu0_grf;
+	pmu0_grf_e->type = grf_type_pmu0;
+	hash_add(ctx->aux_grf_table, &pmu0_grf_e->node, grf_type_pmu0);
+
+	ioc_grf_e = kzalloc(sizeof(*ioc_grf_e), GFP_KERNEL);
+	if (!ioc_grf_e)
+		goto err_free_pmu0;
+
+	ioc_grf_e->grf = ioc_grf;
+	ioc_grf_e->type = grf_type_ioc;
+	hash_add(ctx->aux_grf_table, &ioc_grf_e->node, grf_type_ioc);
 
 	rockchip_clk_register_plls(ctx, rk3576_pll_clks,
 				   ARRAY_SIZE(rk3576_pll_clks),
@@ -1774,6 +1805,14 @@ static void __init rk3576_clk_init(struct device_node *np)
 	rockchip_register_restart_notifier(ctx, RK3576_GLB_SRST_FST, NULL);
 
 	rockchip_clk_of_add_provider(np, ctx);
+
+	return;
+
+err_free_pmu0:
+	kfree(pmu0_grf_e);
+err_unmap:
+	iounmap(reg_base);
+	return;
 }
 
 CLK_OF_DECLARE(rk3576_cru, "rockchip,rk3576-cru", rk3576_clk_init);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index cbf93ea119a9e25c037607ded1f6f358918e8656..8e035b08697eb5bf193ddb9ab4c6154332eb3af1 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -382,6 +382,8 @@ static struct rockchip_clk_provider *rockchip_clk_init_base(
 	ctx->cru_node = np;
 	spin_lock_init(&ctx->lock);
 
+	hash_init(ctx->aux_grf_table);
+
 	ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
 						   "rockchip,grf");
 
@@ -496,6 +498,8 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 				    struct rockchip_clk_branch *list,
 				    unsigned int nr_clk)
 {
+	struct regmap *grf = ctx->grf;
+	struct rockchip_aux_grf *agrf;
 	struct clk *clk;
 	unsigned int idx;
 	unsigned long flags;
@@ -504,6 +508,17 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 		flags = list->flags;
 		clk = NULL;
 
+		/* for GRF-dependant branches, choose the right grf first */
+		if ((list->branch_type == branch_muxgrf || list->branch_type == branch_grf_gate) &&
+				list->grf_type != grf_type_sys) {
+			hash_for_each_possible(ctx->aux_grf_table, agrf, node, list->grf_type) {
+				if (agrf->type == list->grf_type) {
+					grf = agrf->grf;
+					break;
+				}
+			}
+		}
+
 		/* catch simple muxes */
 		switch (list->branch_type) {
 		case branch_mux:
@@ -526,7 +541,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 		case branch_muxgrf:
 			clk = rockchip_clk_register_muxgrf(list->name,
 				list->parent_names, list->num_parents,
-				flags, ctx->grf, list->muxdiv_offset,
+				flags, grf, list->muxdiv_offset,
 				list->mux_shift, list->mux_width,
 				list->mux_flags);
 			break;
@@ -573,6 +588,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 				ctx->reg_base + list->gate_offset,
 				list->gate_shift, list->gate_flags, &ctx->lock);
 			break;
+		case branch_grf_gate:
+			flags |= CLK_SET_RATE_PARENT;
+			clk = rockchip_clk_register_gate_grf(list->name,
+				list->parent_names[0], flags, grf,
+				list->gate_offset, list->gate_shift,
+				list->gate_flags);
+			break;
 		case branch_composite:
 			clk = rockchip_clk_register_branch(list->name,
 				list->parent_names, list->num_parents,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index df2b2d706450f38dfe2b3c7762763c5e832b9892..ebaed429a30dc2c41c866f973f8cf78b32136311 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -19,6 +19,7 @@
 
 #include <linux/io.h>
 #include <linux/clk-provider.h>
+#include <linux/hashtable.h>
 
 struct clk;
 
@@ -440,12 +441,35 @@ enum rockchip_pll_type {
 	.k = _k,						\
 }
 
+enum rockchip_grf_type {
+	grf_type_sys = 0,
+	grf_type_pmu0,
+	grf_type_pmu1,
+	grf_type_ioc,
+};
+
+/* ceil(sqrt(enums in rockchip_grf_type - 1)) */
+#define GRF_HASH_ORDER 2
+
+/**
+ * struct rockchip_aux_grf - entry for the aux_grf_table hashtable
+ * @grf: pointer to the grf this entry references
+ * @type: what type of GRF this is
+ * @node: hlist node
+ */
+struct rockchip_aux_grf {
+	struct regmap *grf;
+	enum rockchip_grf_type type;
+	struct hlist_node node;
+};
+
 /**
  * struct rockchip_clk_provider - information about clock provider
  * @reg_base: virtual address for the register base.
  * @clk_data: holds clock related data like clk* and number of clocks.
  * @cru_node: device-node of the clock-provider
  * @grf: regmap of the general-register-files syscon
+ * @aux_grf_table: hashtable of auxiliary GRF regmaps, indexed by grf_type
  * @lock: maintains exclusion between callbacks for a given clock-provider.
  */
 struct rockchip_clk_provider {
@@ -453,6 +477,7 @@ struct rockchip_clk_provider {
 	struct clk_onecell_data clk_data;
 	struct device_node *cru_node;
 	struct regmap *grf;
+	DECLARE_HASHTABLE(aux_grf_table, GRF_HASH_ORDER);
 	spinlock_t lock;
 };
 
@@ -622,6 +647,11 @@ struct clk *rockchip_clk_register_muxgrf(const char *name,
 				int flags, struct regmap *grf, int reg,
 				int shift, int width, int mux_flags);
 
+struct clk *rockchip_clk_register_gate_grf(const char *name,
+				const char *parent_name, unsigned long flags,
+				struct regmap *regmap, unsigned int reg,
+				unsigned int shift, u8 gate_flags);
+
 #define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
@@ -631,6 +661,7 @@ enum rockchip_clk_branch_type {
 	branch_divider,
 	branch_fraction_divider,
 	branch_gate,
+	branch_grf_gate,
 	branch_linked_gate,
 	branch_mmc,
 	branch_inverter,
@@ -660,6 +691,7 @@ struct rockchip_clk_branch {
 	u8				gate_shift;
 	u8				gate_flags;
 	unsigned int			linked_clk_id;
+	enum rockchip_grf_type		grf_type;
 	struct rockchip_clk_branch	*child;
 };
 
@@ -900,7 +932,7 @@ struct rockchip_clk_branch {
 		.mux_table	= mt,				\
 	}
 
-#define MUXGRF(_id, cname, pnames, f, o, s, w, mf)		\
+#define MUXGRF(_id, cname, pnames, f, o, s, w, mf, gt)		\
 	{							\
 		.id		= _id,				\
 		.branch_type	= branch_muxgrf,		\
@@ -913,6 +945,7 @@ struct rockchip_clk_branch {
 		.mux_width	= w,				\
 		.mux_flags	= mf,				\
 		.gate_offset	= -1,				\
+		.grf_type	= gt,				\
 	}
 
 #define DIV(_id, cname, pname, f, o, s, w, df)			\
@@ -958,6 +991,20 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
+#define GATE_GRF(_id, cname, pname, f, o, b, gf, gt)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_grf_gate,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.gate_offset	= o,				\
+		.gate_shift	= b,				\
+		.gate_flags	= gf,				\
+		.grf_type	= gt,				\
+	}
+
 #define GATE_LINK(_id, cname, pname, linkedclk, f, o, b, gf)	\
 	{							\
 		.id		= _id,				\
diff --git a/drivers/clk/rockchip/gate-grf.c b/drivers/clk/rockchip/gate-grf.c
new file mode 100644
index 0000000000000000000000000000000000000000..8122f471f39134a7298be8daf0718cfa4f8852a7
--- /dev/null
+++ b/drivers/clk/rockchip/gate-grf.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 Collabora Ltd.
+ * Author: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
+ *
+ * Certain clocks on Rockchip are "gated" behind an additional register bit
+ * write in a GRF register, such as the SAI MCLKs on RK3576. This code
+ * implements a clock driver for these types of gates, based on regmaps.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+struct rockchip_gate_grf {
+	struct clk_hw		hw;
+	struct regmap		*regmap;
+	unsigned int		reg;
+	unsigned int		shift;
+	u8			flags;
+};
+
+#define to_gate_grf(_hw) container_of(_hw, struct rockchip_gate_grf, hw)
+
+static int rockchip_gate_grf_enable(struct clk_hw *hw)
+{
+	struct rockchip_gate_grf *gate = to_gate_grf(hw);
+	u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? BIT(gate->shift) : 0;
+	u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
+	int ret;
+
+	ret = regmap_update_bits(gate->regmap, gate->reg,
+				 hiword | BIT(gate->shift), hiword | val);
+
+	return ret;
+}
+
+static void rockchip_gate_grf_disable(struct clk_hw *hw)
+{
+	struct rockchip_gate_grf *gate = to_gate_grf(hw);
+	u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : BIT(gate->shift);
+	u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
+
+	regmap_update_bits(gate->regmap, gate->reg,
+			   hiword | BIT(gate->shift), hiword | val);
+}
+
+static int rockchip_gate_grf_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_gate_grf *gate = to_gate_grf(hw);
+	bool invert = !!(gate->flags & CLK_GATE_SET_TO_DISABLE);
+	int ret;
+
+	ret = regmap_test_bits(gate->regmap, gate->reg, BIT(gate->shift));
+	if (ret < 0)
+		ret = 0;
+
+	return invert ? 1 - ret : ret;
+
+}
+
+static const struct clk_ops rockchip_gate_grf_ops = {
+	.enable = rockchip_gate_grf_enable,
+	.disable = rockchip_gate_grf_disable,
+	.is_enabled = rockchip_gate_grf_is_enabled,
+};
+
+struct clk *rockchip_clk_register_gate_grf(const char *name,
+		const char *parent_name, unsigned long flags,
+		struct regmap *regmap, unsigned int reg, unsigned int shift,
+		u8 gate_flags)
+{
+	struct rockchip_gate_grf *gate;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	if (IS_ERR(regmap)) {
+		pr_err("%s: regmap not available\n", __func__);
+		return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = flags;
+	init.num_parents = parent_name ? 1 : 0;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.ops = &rockchip_gate_grf_ops;
+
+	gate->hw.init = &init;
+	gate->regmap = regmap;
+	gate->reg = reg;
+	gate->shift = shift;
+	gate->flags = gate_flags;
+
+	clk = clk_register(NULL, &gate->hw);
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:23 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:23 +0100
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI
 controllers
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>

Rockchip introduced a new audio controller called the "Serial Audio
Interface", or "SAI" for short, on some of their newer SoCs. In
particular, this controller is used several times on the RK3576 SoC.

Add a schema for it, with only an RK3576 compatible for now. Other SoCs
may follow as mainline support for them lands.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 .../devicetree/bindings/sound/rockchip,sai.yaml    | 151 +++++++++++++++++++++
 MAINTAINERS                                        |   6 +
 2 files changed, 157 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip,sai.yaml b/Documentation/devicetree/bindings/sound/rockchip,sai.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8f5a292a7f2a6c737d983d00cbe40ec45bfa6249
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,sai.yaml
@@ -0,0 +1,151 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/rockchip,sai.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip Serial Audio Interface Controller
+
+description:
+  The Rockchip Serial Audio Interface (SAI) controller is a flexible audio
+  controller that implements the I2S, I2S/TDM and the PDM standards.
+
+maintainers:
+  - Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: rockchip,rk3576-sai
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  dmas:
+    minItems: 1
+    maxItems: 2
+
+  dma-names:
+    minItems: 1
+    maxItems: 2
+    oneOf:
+      - const: tx
+      - const: rx
+      - items:
+          - const: tx
+          - const: rx
+
+  clocks:
+    items:
+      - description: master audio clock
+      - description: AHB clock driving the interface
+
+  clock-names:
+    items:
+      - const: mclk
+      - const: hclk
+
+  resets:
+    minItems: 1
+    maxItems: 2
+    description: resets for the mclk domain and ahb domain
+
+  reset-names:
+    minItems: 1
+    items:
+      - const: m
+      - const: h
+
+  port:
+    $ref: audio-graph-port.yaml#
+    unevaluatedProperties: false
+
+  power-domains:
+    maxItems: 1
+
+  "#sound-dai-cells":
+    const: 0
+
+  rockchip,sai-rx-route:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    description:
+      Defines the mapping of the controller's SDI ports to actual input lanes,
+      as well as the number of input lanes.
+      rockchip,sai-rx-route = <3> would mean sdi3 is receiving from data0, and
+      that there is only one receiving lane.
+      This property's absence is to be understood as only one receiving lane
+      being used if the controller has capture capabilities.
+    maxItems: 4
+    items:
+      enum: [0, 1, 2, 3]
+
+  rockchip,sai-tx-route:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    description:
+      Defines the mapping of the controller's SDO ports to actual output lanes,
+      as well as the number of output lanes.
+      rockchip,sai-tx-route = <3> would mean sdo3 is sending to data0, and
+      that there is only one transmitting lane.
+      This property's absence is to be understood as only one transmitting lane
+      being used if the controller has playback capabilities.
+    maxItems: 4
+    items:
+      enum: [0, 1, 2, 3]
+
+  rockchip,always-on:
+    type: boolean
+    description:
+      The hardware requires this controller to remain turned on.
+
+
+required:
+  - compatible
+  - reg
+  - dmas
+  - dma-names
+  - clocks
+  - clock-names
+  - "#sound-dai-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rockchip,rk3576-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/pinctrl/rockchip.h>
+    #include <dt-bindings/power/rockchip,rk3576-power.h>
+    #include <dt-bindings/reset/rockchip,rk3576-cru.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        sai1: sai at 2a610000 {
+            compatible = "rockchip,rk3576-sai";
+            reg = <0x0 0x2a610000 0x0 0x1000>;
+            interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&cru MCLK_SAI1_8CH>, <&cru HCLK_SAI1_8CH>;
+            clock-names = "mclk", "hclk";
+            dmas = <&dmac0 2>, <&dmac0 3>;
+            dma-names = "tx", "rx";
+            power-domains = <&power RK3576_PD_AUDIO>;
+            resets = <&cru SRST_M_SAI1_8CH>, <&cru SRST_H_SAI1_8CH>;
+            reset-names = "m", "h";
+            pinctrl-names = "default";
+            pinctrl-0 = <&sai1m0_lrck
+                         &sai1m0_sclk
+                         &sai1m0_sdi0
+                         &sai1m0_sdo0
+                         &sai1m0_sdo1
+                         &sai1m0_sdo2
+                         &sai1m0_sdo3>;
+            rockchip,sai-tx-route = <3 1 2 0>;
+            #sound-dai-cells = <0>;
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 4e9e0e52f92e3c649835ddfb65b2fde0a486198b..a68bf5391df6d3785f376c68ae61669d310cfb17 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20661,6 +20661,12 @@ F:	Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml
 F:	sound/soc/codecs/rk3308_codec.c
 F:	sound/soc/codecs/rk3308_codec.h
 
+ROCKCHIP SAI DRIVER
+M:	Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
+L:	linux-rockchip at lists.infradead.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/sound/rockchip,sai.yaml
+
 ROCKCHIP VIDEO DECODER DRIVER
 M:	Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
 L:	linux-media at vger.kernel.org

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:24 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:24 +0100
Subject: [PATCH 4/7] ASoC: rockchip: add Serial Audio Interface (SAI)
 driver
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-4-64e6cf863e9a@collabora.com>

The Rockchip RK3576 SoC features a new audio controller, the Serial
Audio Interface, or SAI for short. It is capable of both sending and
receiving audio over up to 4 lanes for each direction using the I2S,
PCM or TDM formats.

This driver is derived from the downstream vendor driver. That is why
its original author, Sugar Zhang, is listed as a Co-developer, with
their signoff. Since adjustments to make the driver suitable for
upstream were quite extensive, I've added myself to the authors and put
myself as the commit author; all added bugs are my fault alone, and not
that of the original author at Rockchip.

The hardware is somewhat similar to the Rockchip I2S-TDM hardware when
judged based on their register map, except it uses the same mclk for
tx and rx. It appears to be much more flexible with regards to TDM.
The loopback stuff and mono mode are new as well.

In line with the changes that were made to the Rockchip I2S-TDM driver
after upstreaming, the mclk-calibrate functionality was dropped, and
setting the mclk rate properly is now left up to the Common Clock
Framework, similar to how it is in the upstream I2S-TDM driver now.

A spinlock has been introduced to protect register write accesses that
depend on the bclk/fs to be stopped, i.e. XFER[1:0] being 0. I couldn't
find whether the asoc core held a per-instance lock so only one callback
can run at a time, and so it seemed prudent to add this.

I couldn't successfully test whether TDM was working, though I've tried
with a TAS6424 codec board. I'm not sure yet whether to blame the codec
driver, this version of the SAI driver, or the vendor implementation of
the SAI driver. The TDM mask registers remain untouched in both this
version and the downstream vendor version, which is suspicious, though
the Linux ASoC core wouldn't be able to support the 128 (!!!) slots of
TDM the hardware supports anyway.

Regular old 2-channel stereo I2S thrown at an I2S stereo codec works
well though. I tested with the CPU-side SAI controller in provider mode
and an Everest ES8388 codec as the consumer.

Some vendor driver features (no-dmaengine, fifo rockchip performance
monitoring, many kcontrols) were dropped for this initial upstream
version. They can always be added later if they make sense for upstream.

Co-developed-by: Sugar Zhang <sugar.zhang at rock-chips.com>
Signed-off-by: Sugar Zhang <sugar.zhang at rock-chips.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 MAINTAINERS                       |    1 +
 sound/soc/rockchip/Kconfig        |    8 +
 sound/soc/rockchip/Makefile       |    2 +
 sound/soc/rockchip/rockchip_sai.c | 1623 +++++++++++++++++++++++++++++++++++++
 sound/soc/rockchip/rockchip_sai.h |  251 ++++++
 5 files changed, 1885 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a68bf5391df6d3785f376c68ae61669d310cfb17..a787ebc0b597022410b9d6fd149d6056ca46fa01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20666,6 +20666,7 @@ M:	Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
 L:	linux-rockchip at lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/sound/rockchip,sai.yaml
+F:	sound/soc/rockchip/rockchip_sai.*
 
 ROCKCHIP VIDEO DECODER DRIVER
 M:	Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f98a2fa85edd6bb45d46e915e05bf8e64dc704aa..951e3c926e2aca227ba92ee57cc8e216aa7b7e55 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -37,6 +37,14 @@ config SND_SOC_ROCKCHIP_PDM
 	  Rockchip PDM Controller. The Controller supports up to maximum of
 	  8 channels record.
 
+config SND_SOC_ROCKCHIP_SAI
+	tristate "Rockchip SAI Controller Driver"
+	depends on HAVE_CLK && SND_SOC_ROCKCHIP
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	help
+	  Say Y or M if you want to add support for the Rockchip Serial Audio
+	  Interface controller found on Rockchip SoCs such as the RK3576.
+
 config SND_SOC_ROCKCHIP_SPDIF
 	tristate "Rockchip SPDIF Device Driver"
 	depends on HAVE_CLK && SND_SOC_ROCKCHIP
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index 2ee9c08131d1ef0ec0b49e126309a9e1dae11439..af6dc116534724ba88154501f0f74d088e38a27d 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -3,10 +3,12 @@
 snd-soc-rockchip-i2s-y := rockchip_i2s.o
 snd-soc-rockchip-i2s-tdm-y := rockchip_i2s_tdm.o
 snd-soc-rockchip-pdm-y := rockchip_pdm.o
+snd-soc-rockchip-sai-y := rockchip_sai.o
 snd-soc-rockchip-spdif-y := rockchip_spdif.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_SAI) += snd-soc-rockchip-sai.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S_TDM) += snd-soc-rockchip-i2s-tdm.o
 
diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c
new file mode 100644
index 0000000000000000000000000000000000000000..52bd4c15b802384211edb49a5c0b6fec75211394
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_sai.c
@@ -0,0 +1,1623 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ALSA SoC Audio Layer - Rockchip SAI Controller driver
+ *
+ * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Collabora Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/tlv.h>
+
+#include "rockchip_sai.h"
+
+#define DRV_NAME		"rockchip-sai"
+
+#define CLK_SHIFT_RATE_HZ_MAX	5
+#define FW_RATIO_MAX		8
+#define FW_RATIO_MIN		1
+#define MAXBURST_PER_FIFO	8
+
+#define DEFAULT_FS		48000
+#define TIMEOUT_US		1000
+#define WAIT_TIME_MS_MAX	10000
+#define QUIRK_ALWAYS_ON		BIT(0)
+
+#define MAX_LANES		4
+
+enum fpw_mode {
+	FPW_ONE_BCLK_WIDTH,
+	FPW_ONE_SLOT_WIDTH,
+	FPW_HALF_FRAME_WIDTH,
+};
+
+struct rk_sai_dev {
+	struct device *dev;
+	struct clk *hclk;
+	struct clk *mclk;
+	struct regmap *regmap;
+	struct reset_control *rst_h;
+	struct reset_control *rst_m;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
+	struct snd_pcm_substream *substreams[SNDRV_PCM_STREAM_LAST + 1];
+	unsigned int mclk_rate;
+	unsigned int wait_time[SNDRV_PCM_STREAM_LAST + 1];
+	unsigned int tx_lanes;
+	unsigned int rx_lanes;
+	unsigned int sdi[MAX_LANES];
+	unsigned int sdo[MAX_LANES];
+	unsigned int quirks;
+	unsigned int version;
+	enum fpw_mode fpw;
+	int  fw_ratio;
+	bool has_capture;
+	bool has_playback;
+	bool is_master_mode;
+	bool is_tdm;
+	bool initialized;
+	/* protects register writes that depend on the state of XFER[1:0] */
+	spinlock_t xfer_lock;
+};
+
+static const struct sai_of_quirks {
+	char *quirk;
+	int id;
+} of_quirks[] = {
+	{
+		.quirk = "rockchip,always-on",
+		.id = QUIRK_ALWAYS_ON,
+	},
+};
+
+static bool rockchip_sai_stream_valid(struct snd_pcm_substream *substream,
+				      struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+
+	if (!substream)
+		return false;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+	    sai->has_playback)
+		return true;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+	    sai->has_capture)
+		return true;
+
+	return false;
+}
+
+static int rockchip_sai_fsync_lost_detect(struct rk_sai_dev *sai, bool en)
+{
+	unsigned int fw, cnt;
+
+	if (sai->is_master_mode || sai->version < SAI_VER_2311)
+		return 0;
+
+	regmap_read(sai->regmap, SAI_FSCR, &fw);
+	cnt = SAI_FSCR_FW_V(fw) << 1; /* two fsync lost */
+
+	regmap_update_bits(sai->regmap, SAI_INTCR,
+			   SAI_INTCR_FSLOSTC, SAI_INTCR_FSLOSTC);
+	regmap_update_bits(sai->regmap, SAI_INTCR,
+			   SAI_INTCR_FSLOST_MASK,
+			   SAI_INTCR_FSLOST(en));
+	/*
+	 * The `cnt` is the number of SCLK cycles of the CRU's SCLK signal that
+	 * should be used as timeout. Consequently, in slave mode, this value
+	 * is only correct if the CRU SCLK is equal to the external SCLK.
+	 */
+	regmap_update_bits(sai->regmap, SAI_FS_TIMEOUT,
+			   SAI_FS_TIMEOUT_VAL_MASK | SAI_FS_TIMEOUT_EN_MASK,
+			   SAI_FS_TIMEOUT_VAL(cnt) | SAI_FS_TIMEOUT_EN(en));
+
+	return 0;
+}
+
+static int rockchip_sai_fsync_err_detect(struct rk_sai_dev *sai,
+					 bool en)
+{
+	if (sai->is_master_mode || sai->version < SAI_VER_2311)
+		return 0;
+
+	regmap_update_bits(sai->regmap, SAI_INTCR,
+			   SAI_INTCR_FSERRC, SAI_INTCR_FSERRC);
+	regmap_update_bits(sai->regmap, SAI_INTCR,
+			   SAI_INTCR_FSERR_MASK,
+			   SAI_INTCR_FSERR(en));
+
+	return 0;
+}
+
+static int rockchip_sai_poll_clk_idle(struct rk_sai_dev *sai)
+{
+	unsigned int reg, idle, val;
+	int ret;
+
+	if (sai->version >= SAI_VER_2307) {
+		reg = SAI_STATUS;
+		idle = SAI_STATUS_FS_IDLE;
+		idle = sai->version >= SAI_VER_2311 ? idle >> 1 : idle;
+	} else {
+		reg = SAI_XFER;
+		idle = SAI_XFER_FS_IDLE;
+	}
+
+	ret = regmap_read_poll_timeout_atomic(sai->regmap, reg, val,
+					      (val & idle), 10, TIMEOUT_US);
+	if (ret < 0)
+		dev_warn(sai->dev, "Failed to idle FS\n");
+
+	return ret;
+}
+
+static int rockchip_sai_poll_stream_idle(struct rk_sai_dev *sai, bool playback, bool capture)
+{
+	unsigned int reg, val;
+	unsigned int idle = 0;
+	int ret;
+
+	if (sai->version >= SAI_VER_2307) {
+		reg = SAI_STATUS;
+		if (playback)
+			idle |= SAI_STATUS_TX_IDLE;
+		if (capture)
+			idle |= SAI_STATUS_RX_IDLE;
+		idle = sai->version >= SAI_VER_2311 ? idle >> 1 : idle;
+	} else {
+		reg = SAI_XFER;
+		if (playback)
+			idle |= SAI_XFER_TX_IDLE;
+		if (capture)
+			idle |= SAI_XFER_RX_IDLE;
+	}
+
+	ret = regmap_read_poll_timeout_atomic(sai->regmap, reg, val,
+					      (val & idle), 10, TIMEOUT_US);
+	if (ret < 0)
+		dev_warn(sai->dev, "Failed to idle stream\n");
+
+	return ret;
+}
+
+/**
+ * rockchip_sai_xfer_clk_stop_and_wait() - stop the xfer clock and wait for it to be idle
+ * @sai: pointer to the driver instance's rk_sai_dev struct
+ * @to_restore: pointer to store the CLK/FSS register values in as they were
+ *              found before they were cleared, or NULL.
+ *
+ * Clear the XFER_CLK and XFER_FSS registers if needed, then busy-waits for the
+ * XFER clocks to be idle. Before clearing the bits, it stores the state of the
+ * registers as it encountered them in to_restore if it isn't NULL.
+ *
+ * Context: Any context. Expects sai->xfer_lock to be held by caller.
+ */
+static void rockchip_sai_xfer_clk_stop_and_wait(struct rk_sai_dev *sai, unsigned int *to_restore)
+{
+	unsigned int mask = SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK;
+	unsigned int disable = SAI_XFER_CLK_DIS | SAI_XFER_FSS_DIS;
+	unsigned int val;
+
+	assert_spin_locked(&sai->xfer_lock);
+
+	regmap_read(sai->regmap, SAI_XFER, &val);
+	if ((val & mask) == disable)
+		goto wait_for_idle;
+
+	if (sai->is_master_mode)
+		regmap_update_bits(sai->regmap, SAI_XFER, mask, disable);
+
+wait_for_idle:
+	rockchip_sai_poll_clk_idle(sai);
+
+	if (to_restore)
+		*to_restore = val;
+}
+
+static int rockchip_sai_runtime_suspend(struct device *dev)
+{
+	struct rk_sai_dev *sai = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	dev_dbg(dev, "Runtime suspending device!\n");
+
+	rockchip_sai_fsync_lost_detect(sai, 0);
+	rockchip_sai_fsync_err_detect(sai, 0);
+
+	spin_lock_irqsave(&sai->xfer_lock, flags);
+	rockchip_sai_xfer_clk_stop_and_wait(sai, NULL);
+	spin_unlock_irqrestore(&sai->xfer_lock, flags);
+
+	regcache_cache_only(sai->regmap, true);
+	/*
+	 * After FS is idle, we should wait at least 2 BCLK cycles to make sure
+	 * the CLK gate operation has completed, and only then disable mclk.
+	 *
+	 * Otherwise, the BCLK is still ungated, and once the mclk is enabled,
+	 * there is a risk that a few BCLK cycles leak. This is true especially
+	 * at low speeds, such as with a samplerate of 8k.
+	 *
+	 * Ideally we'd adjust the delay based on the samplerate, but it's such
+	 * a tiny value that we can just delay for the maximum clock period
+	 * for the sake of simplicity.
+	 *
+	 * The maximum BCLK period is 31us @ 8K-8Bit (64kHz BCLK). We wait for
+	 * 40us to give ourselves a safety margin in case udelay falls short.
+	 */
+	udelay(40);
+	clk_disable_unprepare(sai->mclk);
+	clk_disable_unprepare(sai->hclk);
+
+	return 0;
+}
+
+static int rockchip_sai_runtime_resume(struct device *dev)
+{
+	struct rk_sai_dev *sai = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret;
+
+	dev_dbg(dev, "Runtime resuming device!\n");
+
+	ret = clk_prepare_enable(sai->hclk);
+	if (ret)
+		goto err_hclk;
+
+	ret = clk_prepare_enable(sai->mclk);
+	if (ret)
+		goto err_mclk;
+
+	regcache_cache_only(sai->regmap, false);
+	regcache_mark_dirty(sai->regmap);
+	ret = regcache_sync(sai->regmap);
+	if (ret)
+		goto err_regmap;
+
+	if (sai->quirks & QUIRK_ALWAYS_ON && sai->is_master_mode) {
+		spin_lock_irqsave(&sai->xfer_lock, flags);
+		regmap_update_bits(sai->regmap, SAI_XFER,
+				   SAI_XFER_CLK_MASK |
+				   SAI_XFER_FSS_MASK,
+				   SAI_XFER_CLK_EN |
+				   SAI_XFER_FSS_EN);
+		spin_unlock_irqrestore(&sai->xfer_lock, flags);
+	}
+
+	return 0;
+
+err_regmap:
+	clk_disable_unprepare(sai->mclk);
+err_mclk:
+	clk_disable_unprepare(sai->hclk);
+err_hclk:
+	return ret;
+}
+
+static void rockchip_sai_fifo_xrun_detect(struct rk_sai_dev *sai,
+					  int stream, bool en)
+{
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* clear irq status which was asserted before TXUIE enabled */
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_TXUIC, SAI_INTCR_TXUIC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_TXUIE_MASK,
+				   SAI_INTCR_TXUIE(en));
+	} else {
+		/* clear irq status which was asserted before RXOIE enabled */
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_RXOIC, SAI_INTCR_RXOIC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_RXOIE_MASK,
+				   SAI_INTCR_RXOIE(en));
+	}
+}
+
+static void rockchip_sai_dma_ctrl(struct rk_sai_dev *sai,
+				  int stream, bool en)
+{
+	if (!en)
+		rockchip_sai_fifo_xrun_detect(sai, stream, 0);
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		regmap_update_bits(sai->regmap, SAI_DMACR,
+				   SAI_DMACR_TDE_MASK,
+				   SAI_DMACR_TDE(en));
+	} else {
+		regmap_update_bits(sai->regmap, SAI_DMACR,
+				   SAI_DMACR_RDE_MASK,
+				   SAI_DMACR_RDE(en));
+	}
+
+	if (en)
+		rockchip_sai_fifo_xrun_detect(sai, stream, 1);
+}
+
+static void rockchip_sai_reset(struct rk_sai_dev *sai)
+{
+	/*
+	 * It is advised to reset the hclk domain before resetting the mclk
+	 * domain, especially in slave mode without a clock input.
+	 *
+	 * To deal with the aforementioned case of slave mode without a clock
+	 * input, we work around a potential issue by resetting the whole
+	 * controller, bringing it back into master mode, and then recovering
+	 * the controller configuration in the regmap.
+	 */
+	reset_control_assert(sai->rst_h);
+	udelay(10);
+	reset_control_deassert(sai->rst_h);
+	udelay(10);
+	reset_control_assert(sai->rst_m);
+	udelay(10);
+	reset_control_deassert(sai->rst_m);
+	udelay(10);
+
+	/* recover regmap config */
+	regcache_mark_dirty(sai->regmap);
+	regcache_sync(sai->regmap);
+}
+
+static int rockchip_sai_clear(struct rk_sai_dev *sai, unsigned int clr)
+{
+	unsigned int val = 0;
+	int ret = 0;
+
+	regmap_update_bits(sai->regmap, SAI_CLR, clr, clr);
+	ret = regmap_read_poll_timeout_atomic(sai->regmap, SAI_CLR, val,
+					      !(val & clr), 10, TIMEOUT_US);
+	if (ret < 0) {
+		dev_warn(sai->dev, "Failed to clear %u\n", clr);
+		rockchip_sai_reset(sai);
+	}
+
+	return ret;
+}
+
+static void rockchip_sai_xfer_start(struct rk_sai_dev *sai, int stream)
+{
+	unsigned int msk, val;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		msk = SAI_XFER_TXS_MASK;
+		val = SAI_XFER_TXS_EN;
+
+	} else {
+		msk = SAI_XFER_RXS_MASK;
+		val = SAI_XFER_RXS_EN;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_XFER, msk, val);
+}
+
+static void rockchip_sai_xfer_stop(struct rk_sai_dev *sai, int stream)
+{
+	unsigned int msk = 0, val = 0, clr = 0;
+	bool playback;
+	bool capture;
+
+	if (stream < 0) {
+		playback = true;
+		capture = true;
+	} else if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		playback = true;
+		capture = false;
+	} else {
+		playback = true;
+		capture = false;
+	}
+
+	if (playback) {
+		msk |= SAI_XFER_TXS_MASK;
+		val |= SAI_XFER_TXS_DIS;
+		clr |= SAI_CLR_TXC;
+	}
+	if (capture) {
+		msk |= SAI_XFER_RXS_MASK;
+		val |= SAI_XFER_RXS_DIS;
+		clr |= SAI_CLR_RXC;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_XFER, msk, val);
+	rockchip_sai_poll_stream_idle(sai, playback, capture);
+
+	rockchip_sai_clear(sai, clr);
+}
+
+static void rockchip_sai_start(struct rk_sai_dev *sai, int stream)
+{
+	rockchip_sai_dma_ctrl(sai, stream, 1);
+	rockchip_sai_xfer_start(sai, stream);
+}
+
+static void rockchip_sai_stop(struct rk_sai_dev *sai, int stream)
+{
+	rockchip_sai_dma_ctrl(sai, stream, 0);
+	rockchip_sai_xfer_stop(sai, stream);
+}
+
+static void rockchip_sai_fmt_create(struct rk_sai_dev *sai, unsigned int fmt)
+{
+	unsigned int xcr_mask = 0, xcr_val = 0, xsft_mask = 0, xsft_val = 0;
+	unsigned int fscr_mask = 0, fscr_val = 0;
+
+	assert_spin_locked(&sai->xfer_lock);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		xcr_mask = SAI_XCR_VDJ_MASK | SAI_XCR_EDGE_SHIFT_MASK;
+		xcr_val = SAI_XCR_VDJ_R | SAI_XCR_EDGE_SHIFT_0;
+		xsft_mask = SAI_XSHIFT_RIGHT_MASK;
+		xsft_val = SAI_XSHIFT_RIGHT(0);
+		fscr_mask = SAI_FSCR_EDGE_MASK;
+		fscr_val = SAI_FSCR_EDGE_DUAL;
+		sai->fpw = FPW_HALF_FRAME_WIDTH;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		xcr_mask = SAI_XCR_VDJ_MASK | SAI_XCR_EDGE_SHIFT_MASK;
+		xcr_val = SAI_XCR_VDJ_L | SAI_XCR_EDGE_SHIFT_0;
+		xsft_mask = SAI_XSHIFT_RIGHT_MASK;
+		xsft_val = SAI_XSHIFT_RIGHT(0);
+		fscr_mask = SAI_FSCR_EDGE_MASK;
+		fscr_val = SAI_FSCR_EDGE_DUAL;
+		sai->fpw = FPW_HALF_FRAME_WIDTH;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		xcr_mask = SAI_XCR_VDJ_MASK | SAI_XCR_EDGE_SHIFT_MASK;
+		xcr_val = SAI_XCR_VDJ_L | SAI_XCR_EDGE_SHIFT_1;
+		xsft_mask = SAI_XSHIFT_RIGHT_MASK;
+		xsft_val = SAI_XSHIFT_RIGHT(2);
+		fscr_mask = SAI_FSCR_EDGE_MASK;
+		fscr_val = SAI_FSCR_EDGE_DUAL;
+		sai->fpw = FPW_HALF_FRAME_WIDTH;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		xcr_mask = SAI_XCR_VDJ_MASK | SAI_XCR_EDGE_SHIFT_MASK;
+		xcr_val = SAI_XCR_VDJ_L | SAI_XCR_EDGE_SHIFT_0;
+		xsft_mask = SAI_XSHIFT_RIGHT_MASK;
+		xsft_val = SAI_XSHIFT_RIGHT(2);
+		fscr_mask = SAI_FSCR_EDGE_MASK;
+		fscr_val = SAI_FSCR_EDGE_RISING;
+		sai->fpw = FPW_ONE_BCLK_WIDTH;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		xcr_mask = SAI_XCR_VDJ_MASK | SAI_XCR_EDGE_SHIFT_MASK;
+		xcr_val = SAI_XCR_VDJ_L | SAI_XCR_EDGE_SHIFT_0;
+		xsft_mask = SAI_XSHIFT_RIGHT_MASK;
+		xsft_val = SAI_XSHIFT_RIGHT(0);
+		fscr_mask = SAI_FSCR_EDGE_MASK;
+		fscr_val = SAI_FSCR_EDGE_RISING;
+		sai->fpw = FPW_ONE_BCLK_WIDTH;
+		break;
+	default:
+		dev_err(sai->dev, "Unsupported fmt %u\n", fmt);
+		break;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_TXCR, xcr_mask, xcr_val);
+	regmap_update_bits(sai->regmap, SAI_RXCR, xcr_mask, xcr_val);
+	regmap_update_bits(sai->regmap, SAI_TX_SHIFT, xsft_mask, xsft_val);
+	regmap_update_bits(sai->regmap, SAI_RX_SHIFT, xsft_mask, xsft_val);
+	regmap_update_bits(sai->regmap, SAI_FSCR, fscr_mask, fscr_val);
+}
+
+static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	unsigned int mask = 0, val = 0;
+	unsigned int clk_gates;
+	unsigned long flags;
+	int ret = 0;
+
+	pm_runtime_get_sync(dai->dev);
+
+	mask = SAI_CKR_MSS_MASK;
+	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+	case SND_SOC_DAIFMT_BP_FP:
+		val = SAI_CKR_MSS_MASTER;
+		sai->is_master_mode = true;
+		break;
+	case SND_SOC_DAIFMT_BC_FC:
+		val = SAI_CKR_MSS_SLAVE;
+		sai->is_master_mode = false;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_pm_put;
+	}
+
+	spin_lock_irqsave(&sai->xfer_lock, flags);
+	rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
+	if (sai->initialized) {
+		if (sai->has_capture && sai->has_playback)
+			rockchip_sai_xfer_stop(sai, -1);
+		else if (sai->has_capture)
+			rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE);
+		else
+			rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK);
+	} else {
+		rockchip_sai_clear(sai, 0);
+		sai->initialized = true;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
+
+	mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK;
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_xfer_unlock;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
+
+	rockchip_sai_fmt_create(sai, fmt);
+
+err_xfer_unlock:
+	if (clk_gates)
+		regmap_update_bits(sai->regmap, SAI_XFER,
+				SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
+				clk_gates);
+	spin_unlock_irqrestore(&sai->xfer_lock, flags);
+err_pm_put:
+	pm_runtime_put(dai->dev);
+
+	return ret;
+}
+
+static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	struct snd_dmaengine_dai_dma_data *dma_data;
+	unsigned int mclk_rate, mclk_req_rate, bclk_rate, div_bclk;
+	unsigned int ch_per_lane, slot_width;
+	unsigned int val, fscr, reg;
+	unsigned int lanes;
+	unsigned long flags;
+	int ret = 0;
+
+	if (!rockchip_sai_stream_valid(substream, dai))
+		return 0;
+
+	dma_data = snd_soc_dai_get_dma_data(dai, substream);
+	dma_data->maxburst = MAXBURST_PER_FIFO * params_channels(params) / 2;
+
+	pm_runtime_get_sync(sai->dev);
+
+	regmap_read(sai->regmap, SAI_DMACR, &val);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		reg = SAI_TXCR;
+		lanes = sai->tx_lanes;
+	} else {
+		reg = SAI_RXCR;
+		lanes = sai->rx_lanes;
+	}
+
+	if (!sai->is_tdm && lanes != DIV_ROUND_UP(params_channels(params), 2)) {
+		dev_err(sai->dev, "not enough lanes (%d) for requested number of %s channels (%d)\n",
+			lanes, reg == SAI_TXCR ? "playback" : "capture",
+			params_channels(params));
+		ret = -EINVAL;
+		goto err_pm_put;
+	}
+
+	dev_dbg(sai->dev, "using %d lanes totalling %d%s channels for %s\n",
+		lanes, params_channels(params), sai->is_tdm ? " (TDM)" : "",
+		reg == SAI_TXCR ? "playback" : "capture");
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+	case SNDRV_PCM_FORMAT_U8:
+		val = SAI_XCR_VDW(8);
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val = SAI_XCR_VDW(16);
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val = SAI_XCR_VDW(24);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+		val = SAI_XCR_VDW(32);
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_pm_put;
+	}
+
+	val |= SAI_XCR_CSR(lanes);
+
+	spin_lock_irqsave(&sai->xfer_lock, flags);
+
+	regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val);
+
+	regmap_read(sai->regmap, reg, &val);
+
+	slot_width = SAI_XCR_SBW_V(val);
+	ch_per_lane = params_channels(params) / lanes;
+
+	regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK,
+			   SAI_XCR_SNB(ch_per_lane));
+
+	fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane);
+
+	switch (sai->fpw) {
+	case FPW_ONE_BCLK_WIDTH:
+		fscr |= SAI_FSCR_FPW(1);
+		break;
+	case FPW_ONE_SLOT_WIDTH:
+		fscr |= SAI_FSCR_FPW(slot_width);
+		break;
+	case FPW_HALF_FRAME_WIDTH:
+		fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2);
+		break;
+	default:
+		dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw);
+		ret = -EINVAL;
+		goto err_xfer_unlock;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_FSCR,
+			   SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr);
+
+	if (sai->is_master_mode) {
+		bclk_rate = sai->fw_ratio * slot_width * ch_per_lane * params_rate(params);
+		ret = clk_set_rate(sai->mclk, sai->mclk_rate);
+		if (ret) {
+			dev_err(sai->dev, "Failed to set mclk to %u: %pe\n",
+				sai->mclk_rate, ERR_PTR(ret));
+			goto err_xfer_unlock;
+		}
+
+		mclk_rate = clk_get_rate(sai->mclk);
+		if (mclk_rate < bclk_rate) {
+			dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n",
+				mclk_rate, bclk_rate);
+			ret = -EINVAL;
+			goto err_xfer_unlock;
+		}
+
+		div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
+		mclk_req_rate = bclk_rate * div_bclk;
+
+		if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX ||
+		    mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) {
+			dev_err(sai->dev, "Mismatch mclk: %u, expected %u (+/- %dHz)\n",
+				mclk_rate, mclk_req_rate, CLK_SHIFT_RATE_HZ_MAX);
+			ret = -EINVAL;
+			goto err_xfer_unlock;
+		}
+
+		regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK,
+				   SAI_CKR_MDIV(div_bclk));
+	}
+
+err_xfer_unlock:
+	spin_unlock_irqrestore(&sai->xfer_lock, flags);
+err_pm_put:
+	pm_runtime_put(sai->dev);
+
+	return ret;
+}
+
+static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	unsigned long flags;
+
+	if (!rockchip_sai_stream_valid(substream, dai))
+		return 0;
+
+	if (sai->is_master_mode) {
+		/*
+		 * We should wait for the first BCLK pulse to have definitely
+		 * occurred after any DIV settings have potentially been
+		 * changed in order to guarantee a clean clock signal once we
+		 * ungate the clock.
+		 *
+		 * Ideally, this would be done depending on the samplerate, but
+		 * for the sake of simplicity, we'll just delay for the maximum
+		 * possible clock offset time, which is quite a small value.
+		 *
+		 * The maximum BCLK offset is 15.6us @ 8K-8Bit (64kHz BCLK). We
+		 * wait for 20us in order to give us a safety margin in case
+		 * udelay falls short.
+		 */
+		udelay(20);
+		spin_lock_irqsave(&sai->xfer_lock, flags);
+		regmap_update_bits(sai->regmap, SAI_XFER,
+				   SAI_XFER_CLK_MASK |
+				   SAI_XFER_FSS_MASK,
+				   SAI_XFER_CLK_EN |
+				   SAI_XFER_FSS_EN);
+		spin_unlock_irqrestore(&sai->xfer_lock, flags);
+	}
+
+	rockchip_sai_fsync_lost_detect(sai, 1);
+	rockchip_sai_fsync_err_detect(sai, 1);
+
+	return 0;
+}
+
+static void rockchip_sai_path_config(struct rk_sai_dev *sai,
+				     int num, bool is_rx)
+{
+	int i;
+
+	if (is_rx)
+		for (i = 0; i < num; i++)
+			regmap_update_bits(sai->regmap, SAI_PATH_SEL,
+					   SAI_RX_PATH_MASK(i),
+					   SAI_RX_PATH(i, sai->sdi[i]));
+	else
+		for (i = 0; i < num; i++)
+			regmap_update_bits(sai->regmap, SAI_PATH_SEL,
+					   SAI_TX_PATH_MASK(i),
+					   SAI_TX_PATH(i, sai->sdo[i]));
+}
+
+static int rockchip_sai_path_prepare(struct rk_sai_dev *sai,
+				     struct device_node *np,
+				     bool is_rx)
+{
+	const char *path_prop;
+	unsigned int *data;
+	unsigned int *lanes;
+	int i, num, ret;
+
+	if (is_rx) {
+		path_prop = "rockchip,sai-rx-route";
+		data = sai->sdi;
+		lanes = &sai->rx_lanes;
+	} else {
+		path_prop = "rockchip,sai-tx-route";
+		data = sai->sdo;
+		lanes = &sai->tx_lanes;
+	}
+
+	num = of_count_phandle_with_args(np, path_prop, NULL);
+	if (num == -ENOENT) {
+		return 0;
+	} else if (num > MAX_LANES || num == 0) {
+		dev_err(sai->dev, "found %d entries in %s, outside of range 1 to %d\n",
+			num, path_prop, MAX_LANES);
+		return -EINVAL;
+	} else if (num < 0) {
+		dev_err(sai->dev, "error in %s property: %pe\n", path_prop,
+			ERR_PTR(num));
+		return num;
+	}
+
+	*lanes = num;
+	ret = device_property_read_u32_array(sai->dev, path_prop, data, num);
+	if (ret < 0) {
+		dev_err(sai->dev, "failed to read property '%s': %pe\n",
+			path_prop, ERR_PTR(ret));
+		return ret;
+	}
+
+	for (i = 0; i < num; i++) {
+		if (data[i] >= MAX_LANES) {
+			dev_err(sai->dev, "%s[%d] is %d, should be less than %d\n",
+				path_prop, i, data[i], MAX_LANES);
+			return -EINVAL;
+		}
+	}
+
+	rockchip_sai_path_config(sai, num, is_rx);
+
+	return 0;
+}
+
+static int rockchip_sai_parse_paths(struct rk_sai_dev *sai,
+				    struct device_node *np)
+{
+	int ret;
+
+	if (sai->has_playback) {
+		sai->tx_lanes = 1;
+		ret = rockchip_sai_path_prepare(sai, np, false);
+		if (ret < 0) {
+			dev_err(sai->dev, "Failed to prepare TX path: %pe\n",
+				ERR_PTR(ret));
+			return ret;
+		}
+	}
+
+	if (sai->has_capture) {
+		sai->rx_lanes = 1;
+		ret = rockchip_sai_path_prepare(sai, np, true);
+		if (ret < 0) {
+			dev_err(sai->dev, "Failed to prepare RX path: %pe\n",
+				ERR_PTR(ret));
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int rockchip_sai_trigger(struct snd_pcm_substream *substream,
+				int cmd, struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	if (!rockchip_sai_stream_valid(substream, dai))
+		return 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		rockchip_sai_start(sai, substream->stream);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		rockchip_sai_stop(sai, substream->stream);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int rockchip_sai_dai_probe(struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+
+	snd_soc_dai_init_dma_data(dai,
+		sai->has_playback ? &sai->playback_dma_data : NULL,
+		sai->has_capture  ? &sai->capture_dma_data  : NULL);
+
+	return 0;
+}
+
+static int rockchip_sai_startup(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	int stream = substream->stream;
+
+	if (!rockchip_sai_stream_valid(substream, dai))
+		return 0;
+
+	if (sai->substreams[stream])
+		return -EBUSY;
+
+	if (sai->wait_time[stream])
+		substream->wait_time = sai->wait_time[stream];
+
+	sai->substreams[stream] = substream;
+
+	return 0;
+}
+
+static void rockchip_sai_shutdown(struct snd_pcm_substream *substream,
+				      struct snd_soc_dai *dai)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+
+	if (!rockchip_sai_stream_valid(substream, dai))
+		return;
+
+	sai->substreams[substream->stream] = NULL;
+}
+
+static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai,
+				     unsigned int tx_mask, unsigned int rx_mask,
+				     int slots, int slot_width)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+	unsigned long flags;
+	unsigned int clk_gates;
+
+	if (slot_width < 16 || slot_width > 32)
+		return -EINVAL;
+
+	pm_runtime_get_sync(dai->dev);
+	spin_lock_irqsave(&sai->xfer_lock, flags);
+	rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
+	regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK,
+			   SAI_XCR_SBW(slot_width));
+	regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK,
+			   SAI_XCR_SBW(slot_width));
+	regmap_update_bits(sai->regmap, SAI_XFER,
+			   SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
+			   clk_gates);
+	spin_unlock_irqrestore(&sai->xfer_lock, flags);
+	pm_runtime_put(dai->dev);
+
+	sai->is_tdm = true;
+
+	return 0;
+}
+
+static int rockchip_sai_set_sysclk(struct snd_soc_dai *dai, int stream,
+				   unsigned int freq, int dir)
+{
+	struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
+
+	sai->mclk_rate = freq;
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops rockchip_sai_dai_ops = {
+	.probe = rockchip_sai_dai_probe,
+	.startup = rockchip_sai_startup,
+	.shutdown = rockchip_sai_shutdown,
+	.hw_params = rockchip_sai_hw_params,
+	.set_fmt = rockchip_sai_set_fmt,
+	.set_sysclk = rockchip_sai_set_sysclk,
+	.prepare = rockchip_sai_prepare,
+	.trigger = rockchip_sai_trigger,
+	.set_tdm_slot = rockchip_sai_set_tdm_slot,
+};
+
+static const struct snd_soc_dai_driver rockchip_sai_dai = {
+	.ops = &rockchip_sai_dai_ops,
+	.symmetric_rate = 1,
+};
+
+static bool rockchip_sai_wr_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SAI_TXCR:
+	case SAI_FSCR:
+	case SAI_RXCR:
+	case SAI_MONO_CR:
+	case SAI_XFER:
+	case SAI_CLR:
+	case SAI_CKR:
+	case SAI_DMACR:
+	case SAI_INTCR:
+	case SAI_TXDR:
+	case SAI_PATH_SEL:
+	case SAI_TX_SLOT_MASK0:
+	case SAI_TX_SLOT_MASK1:
+	case SAI_TX_SLOT_MASK2:
+	case SAI_TX_SLOT_MASK3:
+	case SAI_RX_SLOT_MASK0:
+	case SAI_RX_SLOT_MASK1:
+	case SAI_RX_SLOT_MASK2:
+	case SAI_RX_SLOT_MASK3:
+	case SAI_TX_SHIFT:
+	case SAI_RX_SHIFT:
+	case SAI_FSXN:
+	case SAI_FS_TIMEOUT:
+	case SAI_LOOPBACK_LR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_sai_rd_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SAI_TXCR:
+	case SAI_FSCR:
+	case SAI_RXCR:
+	case SAI_MONO_CR:
+	case SAI_XFER:
+	case SAI_CLR:
+	case SAI_CKR:
+	case SAI_TXFIFOLR:
+	case SAI_RXFIFOLR:
+	case SAI_DMACR:
+	case SAI_INTCR:
+	case SAI_INTSR:
+	case SAI_TXDR:
+	case SAI_RXDR:
+	case SAI_PATH_SEL:
+	case SAI_TX_SLOT_MASK0:
+	case SAI_TX_SLOT_MASK1:
+	case SAI_TX_SLOT_MASK2:
+	case SAI_TX_SLOT_MASK3:
+	case SAI_RX_SLOT_MASK0:
+	case SAI_RX_SLOT_MASK1:
+	case SAI_RX_SLOT_MASK2:
+	case SAI_RX_SLOT_MASK3:
+	case SAI_TX_DATA_CNT:
+	case SAI_RX_DATA_CNT:
+	case SAI_TX_SHIFT:
+	case SAI_RX_SHIFT:
+	case SAI_STATUS:
+	case SAI_VERSION:
+	case SAI_FSXN:
+	case SAI_FS_TIMEOUT:
+	case SAI_LOOPBACK_LR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_sai_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SAI_XFER:
+	case SAI_INTCR:
+	case SAI_INTSR:
+	case SAI_CLR:
+	case SAI_TXFIFOLR:
+	case SAI_RXFIFOLR:
+	case SAI_TXDR:
+	case SAI_RXDR:
+	case SAI_TX_DATA_CNT:
+	case SAI_RX_DATA_CNT:
+	case SAI_STATUS:
+	case SAI_VERSION:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_sai_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SAI_RXDR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct reg_default rockchip_sai_reg_defaults[] = {
+	{ SAI_TXCR, 0x00000bff },
+	{ SAI_FSCR, 0x0001f03f },
+	{ SAI_RXCR, 0x00000bff },
+	{ SAI_PATH_SEL, 0x0000e4e4 },
+};
+
+static const struct regmap_config rockchip_sai_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = SAI_LOOPBACK_LR,
+	.reg_defaults = rockchip_sai_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(rockchip_sai_reg_defaults),
+	.writeable_reg = rockchip_sai_wr_reg,
+	.readable_reg = rockchip_sai_rd_reg,
+	.volatile_reg = rockchip_sai_volatile_reg,
+	.precious_reg = rockchip_sai_precious_reg,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct of_device_id rockchip_sai_match[] = {
+	{ .compatible = "rockchip,rk3576-sai", },
+	{},
+};
+
+static int rockchip_sai_init_dai(struct rk_sai_dev *sai, struct resource *res,
+				 struct snd_soc_dai_driver **dp)
+{
+	struct device_node *node = sai->dev->of_node;
+	struct snd_soc_dai_driver *dai;
+	struct property *dma_names;
+	const char *dma_name;
+
+	of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
+		if (!strcmp(dma_name, "tx"))
+			sai->has_playback = true;
+		if (!strcmp(dma_name, "rx"))
+			sai->has_capture = true;
+	}
+
+	dai = devm_kmemdup(sai->dev, &rockchip_sai_dai,
+			   sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	if (sai->has_playback) {
+		dai->playback.stream_name = "Playback";
+		dai->playback.channels_min = 1;
+		dai->playback.channels_max = 512;
+		dai->playback.rates = SNDRV_PCM_RATE_8000_384000;
+		dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |
+					SNDRV_PCM_FMTBIT_S16_LE |
+					SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE |
+					SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+
+		sai->playback_dma_data.addr = res->start + SAI_TXDR;
+		sai->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		sai->playback_dma_data.maxburst = MAXBURST_PER_FIFO;
+	}
+
+	if (sai->has_capture) {
+		dai->capture.stream_name = "Capture";
+		dai->capture.channels_min = 1;
+		dai->capture.channels_max = 512;
+		dai->capture.rates = SNDRV_PCM_RATE_8000_384000;
+		dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |
+				       SNDRV_PCM_FMTBIT_S16_LE |
+				       SNDRV_PCM_FMTBIT_S24_LE |
+				       SNDRV_PCM_FMTBIT_S32_LE |
+				       SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+
+		sai->capture_dma_data.addr = res->start + SAI_RXDR;
+		sai->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		sai->capture_dma_data.maxburst = MAXBURST_PER_FIFO;
+	}
+
+	regmap_update_bits(sai->regmap, SAI_DMACR, SAI_DMACR_TDL_MASK,
+			   SAI_DMACR_TDL(16));
+	regmap_update_bits(sai->regmap, SAI_DMACR, SAI_DMACR_RDL_MASK,
+			   SAI_DMACR_RDL(16));
+
+	if (dp)
+		*dp = dai;
+
+	return 0;
+}
+
+static const char * const mono_text[] = { "Disable", "Enable" };
+
+static DECLARE_TLV_DB_SCALE(rmss_tlv, 0, 128, 0);
+
+static const char * const lplrc_text[] = { "L:MIC R:LP", "L:LP R:MIC" };
+static const char * const lplr_text[] = { "Disable", "Enable" };
+
+static const char * const lpx_text[] = {
+	"From SDO0", "From SDO1", "From SDO2", "From SDO3" };
+
+static const char * const lps_text[] = { "Disable", "Enable" };
+static const char * const sync_out_text[] = { "From CRU", "From IO" };
+static const char * const sync_in_text[] = { "From IO", "From Sync Port" };
+
+static const char * const rpaths_text[] = {
+	"From SDI0", "From SDI1", "From SDI2", "From SDI3" };
+
+static const char * const tpaths_text[] = {
+	"From PATH0", "From PATH1", "From PATH2", "From PATH3" };
+
+/* MONO_CR */
+static SOC_ENUM_SINGLE_DECL(rmono_switch, SAI_MONO_CR, 1, mono_text);
+static SOC_ENUM_SINGLE_DECL(tmono_switch, SAI_MONO_CR, 0, mono_text);
+
+/* PATH_SEL */
+static SOC_ENUM_SINGLE_DECL(lp3_enum, SAI_PATH_SEL, 28, lpx_text);
+static SOC_ENUM_SINGLE_DECL(lp2_enum, SAI_PATH_SEL, 26, lpx_text);
+static SOC_ENUM_SINGLE_DECL(lp1_enum, SAI_PATH_SEL, 24, lpx_text);
+static SOC_ENUM_SINGLE_DECL(lp0_enum, SAI_PATH_SEL, 22, lpx_text);
+static SOC_ENUM_SINGLE_DECL(lp3_switch, SAI_PATH_SEL, 21, lps_text);
+static SOC_ENUM_SINGLE_DECL(lp2_switch, SAI_PATH_SEL, 20, lps_text);
+static SOC_ENUM_SINGLE_DECL(lp1_switch, SAI_PATH_SEL, 19, lps_text);
+static SOC_ENUM_SINGLE_DECL(lp0_switch, SAI_PATH_SEL, 18, lps_text);
+static SOC_ENUM_SINGLE_DECL(sync_out_switch, SAI_PATH_SEL, 17, sync_out_text);
+static SOC_ENUM_SINGLE_DECL(sync_in_switch, SAI_PATH_SEL, 16, sync_in_text);
+static SOC_ENUM_SINGLE_DECL(rpath3_enum, SAI_PATH_SEL, 14, rpaths_text);
+static SOC_ENUM_SINGLE_DECL(rpath2_enum, SAI_PATH_SEL, 12, rpaths_text);
+static SOC_ENUM_SINGLE_DECL(rpath1_enum, SAI_PATH_SEL, 10, rpaths_text);
+static SOC_ENUM_SINGLE_DECL(rpath0_enum, SAI_PATH_SEL, 8, rpaths_text);
+static SOC_ENUM_SINGLE_DECL(tpath3_enum, SAI_PATH_SEL, 6, tpaths_text);
+static SOC_ENUM_SINGLE_DECL(tpath2_enum, SAI_PATH_SEL, 4, tpaths_text);
+static SOC_ENUM_SINGLE_DECL(tpath1_enum, SAI_PATH_SEL, 2, tpaths_text);
+static SOC_ENUM_SINGLE_DECL(tpath0_enum, SAI_PATH_SEL, 0, tpaths_text);
+
+/* LOOPBACK_LR */
+static SOC_ENUM_SINGLE_DECL(lp3lrc_enum, SAI_LOOPBACK_LR, 7, lplrc_text);
+static SOC_ENUM_SINGLE_DECL(lp2lrc_enum, SAI_LOOPBACK_LR, 6, lplrc_text);
+static SOC_ENUM_SINGLE_DECL(lp1lrc_enum, SAI_LOOPBACK_LR, 5, lplrc_text);
+static SOC_ENUM_SINGLE_DECL(lp0lrc_enum, SAI_LOOPBACK_LR, 4, lplrc_text);
+static SOC_ENUM_SINGLE_DECL(lp3lr_switch, SAI_LOOPBACK_LR, 3, lplr_text);
+static SOC_ENUM_SINGLE_DECL(lp2lr_switch, SAI_LOOPBACK_LR, 2, lplr_text);
+static SOC_ENUM_SINGLE_DECL(lp1lr_switch, SAI_LOOPBACK_LR, 1, lplr_text);
+static SOC_ENUM_SINGLE_DECL(lp0lr_switch, SAI_LOOPBACK_LR, 0, lplr_text);
+
+static int rockchip_sai_wait_time_info(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = WAIT_TIME_MS_MAX;
+	uinfo->value.integer.step = 1;
+
+	return 0;
+}
+
+static int rockchip_sai_rd_wait_time_get(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rk_sai_dev *sai = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = sai->wait_time[SNDRV_PCM_STREAM_CAPTURE];
+
+	return 0;
+}
+
+static int rockchip_sai_rd_wait_time_put(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rk_sai_dev *sai = snd_soc_component_get_drvdata(component);
+
+	if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX)
+		return -EINVAL;
+
+	sai->wait_time[SNDRV_PCM_STREAM_CAPTURE] = ucontrol->value.integer.value[0];
+
+	return 1;
+}
+
+static int rockchip_sai_wr_wait_time_get(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rk_sai_dev *sai = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = sai->wait_time[SNDRV_PCM_STREAM_PLAYBACK];
+
+	return 0;
+}
+
+static int rockchip_sai_wr_wait_time_put(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rk_sai_dev *sai = snd_soc_component_get_drvdata(component);
+
+	if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX)
+		return -EINVAL;
+
+	sai->wait_time[SNDRV_PCM_STREAM_PLAYBACK] = ucontrol->value.integer.value[0];
+
+	return 1;
+}
+
+#define SAI_PCM_WAIT_TIME(xname, xhandler_get, xhandler_put)	\
+{	.iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname,	\
+	.info = rockchip_sai_wait_time_info,			\
+	.get = xhandler_get, .put = xhandler_put }
+
+static const struct snd_kcontrol_new rockchip_sai_controls[] = {
+	SOC_SINGLE_TLV("Receive Mono Slot Select", SAI_MONO_CR,
+		       2, 128, 0, rmss_tlv),
+	SOC_ENUM("Receive Mono Switch", rmono_switch),
+	SOC_ENUM("Transmit Mono Switch", tmono_switch),
+
+	SOC_ENUM("SDI3 Loopback I2S LR Channel Sel", lp3lrc_enum),
+	SOC_ENUM("SDI2 Loopback I2S LR Channel Sel", lp2lrc_enum),
+	SOC_ENUM("SDI1 Loopback I2S LR Channel Sel", lp1lrc_enum),
+	SOC_ENUM("SDI0 Loopback I2S LR Channel Sel", lp0lrc_enum),
+	SOC_ENUM("SDI3 Loopback I2S LR Switch", lp3lr_switch),
+	SOC_ENUM("SDI2 Loopback I2S LR Switch", lp2lr_switch),
+	SOC_ENUM("SDI1 Loopback I2S LR Switch", lp1lr_switch),
+	SOC_ENUM("SDI0 Loopback I2S LR Switch", lp0lr_switch),
+
+	SOC_ENUM("SDI3 Loopback Src Select", lp3_enum),
+	SOC_ENUM("SDI2 Loopback Src Select", lp2_enum),
+	SOC_ENUM("SDI1 Loopback Src Select", lp1_enum),
+	SOC_ENUM("SDI0 Loopback Src Select", lp0_enum),
+	SOC_ENUM("SDI3 Loopback Switch", lp3_switch),
+	SOC_ENUM("SDI2 Loopback Switch", lp2_switch),
+	SOC_ENUM("SDI1 Loopback Switch", lp1_switch),
+	SOC_ENUM("SDI0 Loopback Switch", lp0_switch),
+	SOC_ENUM("Sync Out Switch", sync_out_switch),
+	SOC_ENUM("Sync In Switch", sync_in_switch),
+	SOC_ENUM("Receive PATH3 Source Select", rpath3_enum),
+	SOC_ENUM("Receive PATH2 Source Select", rpath2_enum),
+	SOC_ENUM("Receive PATH1 Source Select", rpath1_enum),
+	SOC_ENUM("Receive PATH0 Source Select", rpath0_enum),
+	SOC_ENUM("Transmit SDO3 Source Select", tpath3_enum),
+	SOC_ENUM("Transmit SDO2 Source Select", tpath2_enum),
+	SOC_ENUM("Transmit SDO1 Source Select", tpath1_enum),
+	SOC_ENUM("Transmit SDO0 Source Select", tpath0_enum),
+
+	SAI_PCM_WAIT_TIME("PCM Read Wait Time MS",
+			  rockchip_sai_rd_wait_time_get,
+			  rockchip_sai_rd_wait_time_put),
+	SAI_PCM_WAIT_TIME("PCM Write Wait Time MS",
+			  rockchip_sai_wr_wait_time_get,
+			  rockchip_sai_wr_wait_time_put),
+};
+
+static const struct snd_soc_component_driver rockchip_sai_component = {
+	.name = DRV_NAME,
+	.controls = rockchip_sai_controls,
+	.num_controls = ARRAY_SIZE(rockchip_sai_controls),
+	.legacy_dai_naming = 1,
+};
+
+static irqreturn_t rockchip_sai_isr(int irq, void *devid)
+{
+	struct rk_sai_dev *sai = (struct rk_sai_dev *)devid;
+	struct snd_pcm_substream *substream;
+	u32 val;
+
+	regmap_read(sai->regmap, SAI_INTSR, &val);
+	if (val & SAI_INTSR_TXUI_ACT) {
+		dev_warn_ratelimited(sai->dev, "TX FIFO Underrun\n");
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_TXUIC, SAI_INTCR_TXUIC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_TXUIE_MASK,
+				   SAI_INTCR_TXUIE(0));
+		substream = sai->substreams[SNDRV_PCM_STREAM_PLAYBACK];
+		if (substream)
+			snd_pcm_stop_xrun(substream);
+	}
+
+	if (val & SAI_INTSR_RXOI_ACT) {
+		dev_warn_ratelimited(sai->dev, "RX FIFO Overrun\n");
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_RXOIC, SAI_INTCR_RXOIC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_RXOIE_MASK,
+				   SAI_INTCR_RXOIE(0));
+		substream = sai->substreams[SNDRV_PCM_STREAM_CAPTURE];
+		if (substream)
+			snd_pcm_stop_xrun(substream);
+	}
+
+	if (val & SAI_INTSR_FSERRI_ACT) {
+		dev_warn_ratelimited(sai->dev, "Frame Sync Error\n");
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_FSERRC, SAI_INTCR_FSERRC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_FSERR_MASK,
+				   SAI_INTCR_FSERR(0));
+	}
+
+	if (val & SAI_INTSR_FSLOSTI_ACT) {
+		dev_warn_ratelimited(sai->dev, "Frame Sync Lost\n");
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_FSLOSTC, SAI_INTCR_FSLOSTC);
+		regmap_update_bits(sai->regmap, SAI_INTCR,
+				   SAI_INTCR_FSLOST_MASK,
+				   SAI_INTCR_FSLOST(0));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int rockchip_sai_keep_clk_always_on(struct rk_sai_dev *sai)
+{
+	unsigned int mclk_rate, bclk_rate, div_bclk;
+
+	sai->is_master_mode = true;
+
+	/* init I2S fmt default */
+	rockchip_sai_fmt_create(sai, SND_SOC_DAIFMT_I2S);
+
+	regmap_update_bits(sai->regmap, SAI_FSCR,
+			   SAI_FSCR_FW_MASK |
+			   SAI_FSCR_FPW_MASK,
+			   SAI_FSCR_FW(64) |
+			   SAI_FSCR_FPW(32));
+
+	mclk_rate = clk_get_rate(sai->mclk);
+	bclk_rate = DEFAULT_FS * 64;
+	div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
+
+	regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK,
+			   SAI_CKR_MDIV(div_bclk));
+
+	pm_runtime_forbid(sai->dev);
+
+	dev_info(sai->dev, "CLK-ALWAYS-ON: mclk: %d, bclk: %d, fsync: %d\n",
+		 mclk_rate, bclk_rate, DEFAULT_FS);
+
+	return 0;
+}
+
+static int rockchip_sai_parse_quirks(struct rk_sai_dev *sai)
+{
+	int ret = 0, i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
+		if (device_property_read_bool(sai->dev, of_quirks[i].quirk))
+			sai->quirks |= of_quirks[i].id;
+
+	if (sai->quirks & QUIRK_ALWAYS_ON)
+		ret = rockchip_sai_keep_clk_always_on(sai);
+
+	return ret;
+}
+
+static int rockchip_sai_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct rk_sai_dev *sai;
+	struct snd_soc_dai_driver *dai;
+	struct resource *res;
+	void __iomem *regs;
+	int ret, irq;
+
+	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
+	if (!sai)
+		return -ENOMEM;
+
+	sai->dev = &pdev->dev;
+	sai->fw_ratio = 1;
+	/* match to register default */
+	sai->is_master_mode = true;
+	dev_set_drvdata(&pdev->dev, sai);
+
+	spin_lock_init(&sai->xfer_lock);
+
+	sai->rst_h = devm_reset_control_get_optional_exclusive(&pdev->dev, "h");
+	if (IS_ERR(sai->rst_h))
+		return dev_err_probe(&pdev->dev, PTR_ERR(sai->rst_h),
+				     "Error in 'h' reset control\n");
+
+	sai->rst_m = devm_reset_control_get_optional_exclusive(&pdev->dev, "m");
+	if (IS_ERR(sai->rst_m))
+		return dev_err_probe(&pdev->dev, PTR_ERR(sai->rst_m),
+				     "Error in 'm' reset control\n");
+
+	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+	if (IS_ERR(regs))
+		return dev_err_probe(&pdev->dev, PTR_ERR(regs),
+				     "Failed to get and ioremap resource\n");
+
+	sai->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+					    &rockchip_sai_regmap_config);
+	if (IS_ERR(sai->regmap))
+		return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap),
+				     "Failed to initialize regmap\n");
+
+	irq = platform_get_irq_optional(pdev, 0);
+	if (irq > 0) {
+		ret = devm_request_irq(&pdev->dev, irq, rockchip_sai_isr,
+				       IRQF_SHARED, node->name, sai);
+		if (ret) {
+			return dev_err_probe(&pdev->dev, ret,
+					     "Failed to request irq %d\n", irq);
+		}
+	} else {
+		dev_dbg(&pdev->dev, "Asked for an IRQ but got %d\n", irq);
+	}
+
+	sai->mclk = devm_clk_get(&pdev->dev, "mclk");
+	if (IS_ERR(sai->mclk)) {
+		return dev_err_probe(&pdev->dev, PTR_ERR(sai->mclk),
+				     "Failed to get mclk\n");
+	}
+
+	sai->hclk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(sai->hclk)) {
+		return dev_err_probe(&pdev->dev, PTR_ERR(sai->hclk),
+				     "Failed to get hclk\n");
+	}
+
+	ret = clk_prepare_enable(sai->hclk);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Failed to enable hclk\n");
+
+	regmap_read(sai->regmap, SAI_VERSION, &sai->version);
+
+	ret = rockchip_sai_parse_quirks(sai);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to parse device quirks: %d\n", ret);
+		goto err_disable_hclk;
+	}
+
+	ret = rockchip_sai_init_dai(sai, res, &dai);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize DAI: %d\n", ret);
+		goto err_disable_hclk;
+	}
+
+	ret = rockchip_sai_parse_paths(sai, node);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to parse paths: %d\n", ret);
+		goto err_disable_hclk;
+	}
+
+	/*
+	 * From here on, all register accesses need to be wrapped in
+	 * pm_runtime_get_sync/pm_runtime_put calls
+	 *
+	 * NB: we don't rely on _resume_and_get in case of !CONFIG_PM
+	 */
+	devm_pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+	ret = rockchip_sai_runtime_resume(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to resume device: %pe\n", ERR_PTR(ret));
+		goto err_disable_hclk;
+	}
+
+	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register PCM: %d\n", ret);
+		goto err_runtime_suspend;
+	}
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &rockchip_sai_component,
+					      dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register component: %d\n", ret);
+		goto err_runtime_suspend;
+	}
+
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_put(&pdev->dev);
+
+	/*
+	 * runtime_resume already enabled our hclk again, so we need to also
+	 * get rid of the manual enable we did earlier to balance the counts.
+	 */
+	clk_disable_unprepare(sai->hclk);
+
+	return 0;
+
+err_runtime_suspend:
+	/* If we're !CONFIG_PM, we get -ENOSYS and disable manually */
+	if (pm_runtime_put(&pdev->dev))
+		rockchip_sai_runtime_suspend(&pdev->dev);
+err_disable_hclk:
+	clk_disable_unprepare(sai->hclk);
+
+	return ret;
+}
+
+static void rockchip_sai_remove(struct platform_device *pdev)
+{
+#ifndef CONFIG_PM
+	rockchip_sai_runtime_suspend(&pdev->dev);
+#endif
+}
+
+static const struct dev_pm_ops rockchip_sai_pm_ops = {
+	SET_RUNTIME_PM_OPS(rockchip_sai_runtime_suspend, rockchip_sai_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+};
+
+static struct platform_driver rockchip_sai_driver = {
+	.probe = rockchip_sai_probe,
+	.remove = rockchip_sai_remove,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = of_match_ptr(rockchip_sai_match),
+		.pm = &rockchip_sai_pm_ops,
+	},
+};
+module_platform_driver(rockchip_sai_driver);
+
+MODULE_DESCRIPTION("Rockchip SAI ASoC Interface");
+MODULE_AUTHOR("Sugar Zhang <sugar.zhang at rock-chips.com>");
+MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli at collabora.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_sai_match);
diff --git a/sound/soc/rockchip/rockchip_sai.h b/sound/soc/rockchip/rockchip_sai.h
new file mode 100644
index 0000000000000000000000000000000000000000..c359c5d0311cae3ca4d45309e54c88d059bf254a
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_sai.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ALSA SoC Audio Layer - Rockchip SAI Controller driver
+ *
+ * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
+ */
+
+#ifndef _ROCKCHIP_SAI_H
+#define _ROCKCHIP_SAI_H
+
+/* XCR Transmit / Receive Control Register */
+#define SAI_XCR_START_SEL_MASK		BIT(23)
+#define SAI_XCR_START_SEL_CHAINED	BIT(23)
+#define SAI_XCR_START_SEL_STANDALONE	0
+#define SAI_XCR_EDGE_SHIFT_MASK		BIT(22)
+#define SAI_XCR_EDGE_SHIFT_1		BIT(22)
+#define SAI_XCR_EDGE_SHIFT_0		0
+#define SAI_XCR_CSR_MASK		GENMASK(21, 20)
+#define SAI_XCR_CSR(x)			((x - 1) << 20)
+#define SAI_XCR_CSR_V(v)		((((v) & SAI_XCR_CSR_MASK) >> 20) + 1)
+#define SAI_XCR_SJM_MASK		BIT(19)
+#define SAI_XCR_SJM_L			BIT(19)
+#define SAI_XCR_SJM_R			0
+#define SAI_XCR_FBM_MASK		BIT(18)
+#define SAI_XCR_FBM_LSB			BIT(18)
+#define SAI_XCR_FBM_MSB			0
+#define SAI_XCR_SNB_MASK		GENMASK(17, 11)
+#define SAI_XCR_SNB(x)			((x - 1) << 11)
+#define SAI_XCR_VDJ_MASK		BIT(10)
+#define SAI_XCR_VDJ_L			BIT(10)
+#define SAI_XCR_VDJ_R			0
+#define SAI_XCR_SBW_MASK		GENMASK(9, 5)
+#define SAI_XCR_SBW(x)			((x - 1) << 5)
+#define SAI_XCR_SBW_V(v)		((((v) & SAI_XCR_SBW_MASK) >> 5) + 1)
+#define SAI_XCR_VDW_MASK		GENMASK(4, 0)
+#define SAI_XCR_VDW(x)			((x - 1) << 0)
+
+/* FSCR Frame Sync Control Register */
+#define SAI_FSCR_EDGE_MASK		BIT(24)
+#define SAI_FSCR_EDGE_DUAL		BIT(24)
+#define SAI_FSCR_EDGE_RISING		0
+#define SAI_FSCR_FPW_MASK		GENMASK(23, 12)
+#define SAI_FSCR_FPW(x)			((x - 1) << 12)
+#define SAI_FSCR_FW_MASK		GENMASK(11, 0)
+#define SAI_FSCR_FW(x)			((x - 1) << 0)
+#define SAI_FSCR_FW_V(v)		((((v) & SAI_FSCR_FW_MASK) >> 0) + 1)
+
+/* MONO_CR Mono Control Register */
+#define SAI_MCR_RX_MONO_SLOT_MASK	GENMASK(8, 2)
+#define SAI_MCR_RX_MONO_SLOT_SEL(x)	((x - 1) << 2)
+#define SAI_MCR_RX_MONO_MASK		BIT(1)
+#define SAI_MCR_RX_MONO_EN		BIT(1)
+#define SAI_MCR_RX_MONO_DIS		0
+#define SAI_MCR_TX_MONO_MASK		BIT(0)
+#define SAI_MCR_TX_MONO_EN		BIT(0)
+#define SAI_MCR_TX_MONO_DIS		0
+
+/* XFER Transfer Start Register */
+#define SAI_XFER_RX_IDLE		BIT(8)
+#define SAI_XFER_TX_IDLE		BIT(7)
+#define SAI_XFER_FS_IDLE		BIT(6)
+/*
+ * Used for TX only (VERSION >= SAI_VER_2311)
+ *
+ * SCLK/FSYNC auto gated when TX FIFO empty.
+ */
+#define SAI_XFER_TX_AUTO_MASK		BIT(6)
+#define SAI_XFER_TX_AUTO_EN		BIT(6)
+#define SAI_XFER_TX_AUTO_DIS		0
+#define SAI_XFER_RX_CNT_MASK		BIT(5)
+#define SAI_XFER_RX_CNT_EN		BIT(5)
+#define SAI_XFER_RX_CNT_DIS		0
+#define SAI_XFER_TX_CNT_MASK		BIT(4)
+#define SAI_XFER_TX_CNT_EN		BIT(4)
+#define SAI_XFER_TX_CNT_DIS		0
+#define SAI_XFER_RXS_MASK		BIT(3)
+#define SAI_XFER_RXS_EN			BIT(3)
+#define SAI_XFER_RXS_DIS		0
+#define SAI_XFER_TXS_MASK		BIT(2)
+#define SAI_XFER_TXS_EN			BIT(2)
+#define SAI_XFER_TXS_DIS		0
+#define SAI_XFER_FSS_MASK		BIT(1)
+#define SAI_XFER_FSS_EN			BIT(1)
+#define SAI_XFER_FSS_DIS		0
+#define SAI_XFER_CLK_MASK		BIT(0)
+#define SAI_XFER_CLK_EN			BIT(0)
+#define SAI_XFER_CLK_DIS		0
+
+/* CLR Clear Logic Register */
+#define SAI_CLR_FCR			BIT(3)	/* TODO: what is this? */
+#define SAI_CLR_FSC			BIT(2)
+#define SAI_CLR_RXC			BIT(1)
+#define SAI_CLR_TXC			BIT(0)
+
+/* CKR Clock Generation Register */
+#define SAI_CKR_MDIV_MASK		GENMASK(14, 3)
+#define SAI_CKR_MDIV(x)			((x - 1) << 3)
+#define SAI_CKR_MSS_MASK		BIT(2)
+#define SAI_CKR_MSS_SLAVE		BIT(2)
+#define SAI_CKR_MSS_MASTER		0
+#define SAI_CKR_CKP_MASK		BIT(1)
+#define SAI_CKR_CKP_INVERTED		BIT(1)
+#define SAI_CKR_CKP_NORMAL		0
+#define SAI_CKR_FSP_MASK		BIT(0)
+#define SAI_CKR_FSP_INVERTED		BIT(0)
+#define SAI_CKR_FSP_NORMAL		0
+
+/* DMACR DMA Control Register */
+#define SAI_DMACR_RDE_MASK		BIT(24)
+#define SAI_DMACR_RDE(x)		((x) << 24)
+#define SAI_DMACR_RDL_MASK		GENMASK(20, 16)
+#define SAI_DMACR_RDL(x)		((x - 1) << 16)
+#define SAI_DMACR_RDL_V(v)		((((v) & SAI_DMACR_RDL_MASK) >> 16) + 1)
+#define SAI_DMACR_TDE_MASK		BIT(8)
+#define SAI_DMACR_TDE(x)		((x) << 8)
+#define SAI_DMACR_TDL_MASK		GENMASK(4, 0)
+#define SAI_DMACR_TDL(x)		((x) << 0)
+#define SAI_DMACR_TDL_V(v)		(((v) & SAI_DMACR_TDL_MASK) >> 0)
+
+/* INTCR Interrupt Ctrl Register */
+#define SAI_INTCR_FSLOSTC			BIT(28)
+#define SAI_INTCR_FSLOST_MASK		BIT(27)
+#define SAI_INTCR_FSLOST(x)		((x) << 27)
+#define SAI_INTCR_FSERRC			BIT(26)
+#define SAI_INTCR_FSERR_MASK		BIT(25)
+#define SAI_INTCR_FSERR(x)		((x) << 25)
+#define SAI_INTCR_RXOIC			BIT(18)
+#define SAI_INTCR_RXOIE_MASK		BIT(17)
+#define SAI_INTCR_RXOIE(x)		((x) << 17)
+#define SAI_INTCR_TXUIC			BIT(2)
+#define SAI_INTCR_TXUIE_MASK		BIT(1)
+#define SAI_INTCR_TXUIE(x)		((x) << 1)
+
+/* INTSR Interrupt Status Register */
+#define SAI_INTSR_FSLOSTI_INA		0
+#define SAI_INTSR_FSLOSTI_ACT		BIT(19)
+#define SAI_INTSR_FSERRI_INA		0
+#define SAI_INTSR_FSERRI_ACT		BIT(18)
+#define SAI_INTSR_RXOI_INA		0
+#define SAI_INTSR_RXOI_ACT		BIT(17)
+#define SAI_INTSR_TXUI_INA		0
+#define SAI_INTSR_TXUI_ACT		BIT(1)
+
+/* PATH_SEL: Transfer / Receive Path Select Register */
+#define SAI_RX_PATH_SHIFT(x)		(8 + (x) * 2)
+#define SAI_RX_PATH_MASK(x)		(0x3 << SAI_RX_PATH_SHIFT(x))
+#define SAI_RX_PATH(x, v)		((v) << SAI_RX_PATH_SHIFT(x))
+#define SAI_TX_PATH_SHIFT(x)		(0 + (x) * 2)
+#define SAI_TX_PATH_MASK(x)		(0x3 << SAI_TX_PATH_SHIFT(x))
+#define SAI_TX_PATH(x, v)		((v) << SAI_TX_PATH_SHIFT(x))
+
+/* XSHIFT: Transfer / Receive Frame Sync Shift Register */
+
+/*
+ * TX-ONLY: LEFT Direction Feature
+ * +------------------------------------------------+
+ * | DATA LEFTx (step: 0.5 cycle) | FSYNC Edge      |
+ * +------------------------------------------------+
+ */
+#define SAI_XSHIFT_LEFT_MASK		GENMASK(25, 24)
+#define SAI_XSHIFT_LEFT(x)		((x) << 24)
+/*
+ * +------------------------------------------------+
+ * | FSYNC Edge | DATA RIGHTx (step: 0.5 cycle)     |
+ * +------------------------------------------------+
+ */
+#define SAI_XSHIFT_RIGHT_MASK		GENMASK(23, 0)
+#define SAI_XSHIFT_RIGHT(x)		(x)
+
+/* XFIFOLR: Transfer / Receive FIFO Level Register */
+#define SAI_FIFOLR_XFL3_SHIFT		18
+#define SAI_FIFOLR_XFL3_MASK		GENMASK(23, 18)
+#define SAI_FIFOLR_XFL2_SHIFT		12
+#define SAI_FIFOLR_XFL2_MASK		GENMASK(17, 12)
+#define SAI_FIFOLR_XFL1_SHIFT		6
+#define SAI_FIFOLR_XFL1_MASK		GENMASK(11, 6)
+#define SAI_FIFOLR_XFL0_SHIFT		0
+#define SAI_FIFOLR_XFL0_MASK		GENMASK(5, 0)
+
+/* STATUS Status Register (VERSION >= SAI_VER_2307) */
+#define SAI_STATUS_RX_IDLE		BIT(3)
+#define SAI_STATUS_TX_IDLE		BIT(2)
+#define SAI_STATUS_FS_IDLE		BIT(1)
+
+/* VERSION */
+/*
+ * Updates:
+ *
+ * VERSION >= SAI_VER_2311
+ *
+ * Support Frame Sync xN (FSXN)
+ * Support Frame Sync Error Detect (FSE)
+ * Support Frame Sync Lost Detect (FSLOST)
+ * Support Force Clear (FCR)
+ * Support SAIn-Chained (e.g. SAI0-CLK-DATA + SAI3-DATA +...)
+ * Support Transmit Auto Gate Mode
+ * Support Timing Shift Left for TX
+ *
+ * Optimize SCLK/FSYNC Timing Alignment
+ *
+ * VERSION >= SAI_VER_2403
+ *
+ * Support Loopback LR Select (e.g. L:MIC R:LP)
+ *
+ */
+#define SAI_VER_2307			0x23073576
+#define SAI_VER_2311			0x23112118
+#define SAI_VER_2401			0x24013506
+#define SAI_VER_2403			0x24031103
+
+/* FS_TIMEOUT: Frame Sync Timeout Register */
+#define SAI_FS_TIMEOUT_VAL_MASK		GENMASK(31, 1)
+#define SAI_FS_TIMEOUT_VAL(x)		((x) << 1)
+#define SAI_FS_TIMEOUT_EN_MASK		BIT(0)
+#define SAI_FS_TIMEOUT_EN(x)		((x) << 0)
+
+/* SAI Registers */
+#define SAI_TXCR			(0x0000)
+#define SAI_FSCR			(0x0004)
+#define SAI_RXCR			(0x0008)
+#define SAI_MONO_CR			(0x000c)
+#define SAI_XFER			(0x0010)
+#define SAI_CLR				(0x0014)
+#define SAI_CKR				(0x0018)
+#define SAI_TXFIFOLR			(0x001c)
+#define SAI_RXFIFOLR			(0x0020)
+#define SAI_DMACR			(0x0024)
+#define SAI_INTCR			(0x0028)
+#define SAI_INTSR			(0x002c)
+#define SAI_TXDR			(0x0030)
+#define SAI_RXDR			(0x0034)
+#define SAI_PATH_SEL			(0x0038)
+#define SAI_TX_SLOT_MASK0		(0x003c)
+#define SAI_TX_SLOT_MASK1		(0x0040)
+#define SAI_TX_SLOT_MASK2		(0x0044)
+#define SAI_TX_SLOT_MASK3		(0x0048)
+#define SAI_RX_SLOT_MASK0		(0x004c)
+#define SAI_RX_SLOT_MASK1		(0x0050)
+#define SAI_RX_SLOT_MASK2		(0x0054)
+#define SAI_RX_SLOT_MASK3		(0x0058)
+#define SAI_TX_DATA_CNT			(0x005c)
+#define SAI_RX_DATA_CNT			(0x0060)
+#define SAI_TX_SHIFT			(0x0064)
+#define SAI_RX_SHIFT			(0x0068)
+#define SAI_STATUS			(0x006c)
+#define SAI_VERSION			(0x0070)
+#define SAI_FSXN			(0x0074)
+#define SAI_FS_TIMEOUT			(0x0078)
+#define SAI_LOOPBACK_LR			(0x007c)
+
+#endif /* _ROCKCHIP_SAI_H */

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:25 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:25 +0100
Subject: [PATCH 5/7] arm64: dts: rockchip: Add RK3576 SAI nodes
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-5-64e6cf863e9a@collabora.com>

The RK3576 SoC has 10 SAI controllers in total. Five of them are in the
video output power domains, and are used for digital audio output along
with the video signal of those, e.g. HDMI audio.

The other five, SAI0 through SAI4, are exposed externally. SAI0 and SAI1
are capable of 8-channel audio, whereas SAI2, SAI3 and SAI4 are limited
to two channels. These five are in the audio power domain.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3576.dtsi | 194 +++++++++++++++++++++++++++++++
 1 file changed, 194 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
index 8591065b575223a5eb2da70f723f16969aa2ecf7..2691efea02a3852babfdeb25c490f9309356c3b7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -1010,6 +1010,38 @@ vop_mmu: iommu at 27d07e00 {
 			status = "disabled";
 		};
 
+		sai5: sai at 27d40000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x27d40000 0x0 0x1000>;
+			interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI5_8CH>, <&cru HCLK_SAI5_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac2 3>;
+			dma-names = "rx";
+			power-domains = <&power RK3576_PD_VO0>;
+			resets = <&cru SRST_M_SAI5_8CH>, <&cru SRST_H_SAI5_8CH>;
+			reset-names = "m", "h";
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI5";
+			status = "disabled";
+		};
+
+		sai6: sai at 27d50000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x27d50000 0x0 0x1000>;
+			interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI6_8CH>, <&cru HCLK_SAI6_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac2 4>, <&dmac2 5>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_VO0>;
+			resets = <&cru SRST_M_SAI6_8CH>, <&cru SRST_H_SAI6_8CH>;
+			reset-names = "m", "h";
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI6";
+			status = "disabled";
+		};
+
 		hdmi: hdmi at 27da0000 {
 			compatible = "rockchip,rk3576-dw-hdmi-qp";
 			reg = <0x0 0x27da0000 0x0 0x20000>;
@@ -1050,6 +1082,54 @@ hdmi_out: port at 1 {
 			};
 		};
 
+		sai7: sai at 27ed0000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x27ed0000 0x0 0x1000>;
+			interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI7_8CH>, <&cru HCLK_SAI7_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac2 19>;
+			dma-names = "tx";
+			power-domains = <&power RK3576_PD_VO1>;
+			resets = <&cru SRST_M_SAI7_8CH>, <&cru SRST_H_SAI7_8CH>;
+			reset-names = "m", "h";
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI7";
+			status = "disabled";
+		};
+
+		sai8: sai at 27ee0000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x27ee0000 0x0 0x1000>;
+			interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI8_8CH>, <&cru HCLK_SAI8_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac1 7>;
+			dma-names = "tx";
+			power-domains = <&power RK3576_PD_VO1>;
+			resets = <&cru SRST_M_SAI8_8CH>, <&cru SRST_H_SAI8_8CH>;
+			reset-names = "m", "h";
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI8";
+			status = "disabled";
+		};
+
+		sai9: sai at 27ef0000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x27ef0000 0x0 0x1000>;
+			interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI9_8CH>, <&cru HCLK_SAI9_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac0 26>;
+			dma-names = "tx";
+			power-domains = <&power RK3576_PD_VO1>;
+			resets = <&cru SRST_M_SAI9_8CH>, <&cru SRST_H_SAI9_8CH>;
+			reset-names = "m", "h";
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI9";
+			status = "disabled";
+		};
+
 		qos_hdcp1: qos at 27f02000 {
 			compatible = "rockchip,rk3576-qos", "syscon";
 			reg = <0x0 0x27f02000 0x0 0x20>;
@@ -1436,6 +1516,120 @@ log_leakage: log-leakage at 22 {
 			};
 		};
 
+		sai0: sai at 2a600000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x2a600000 0x0 0x1000>;
+			interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI0_8CH>, <&cru HCLK_SAI0_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac0 0>, <&dmac0 1>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_AUDIO>;
+			resets = <&cru SRST_M_SAI0_8CH>, <&cru SRST_H_SAI0_8CH>;
+			reset-names = "m", "h";
+			pinctrl-names = "default";
+			pinctrl-0 = <&sai0m0_lrck
+				&sai0m0_sclk
+				&sai0m0_sdi0
+				&sai0m0_sdi1
+				&sai0m0_sdi2
+				&sai0m0_sdi3
+				&sai0m0_sdo0
+				&sai0m0_sdo1
+				&sai0m0_sdo2
+				&sai0m0_sdo3>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI0";
+			status = "disabled";
+		};
+
+		sai1: sai at 2a610000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x2a610000 0x0 0x1000>;
+			interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI1_8CH>, <&cru HCLK_SAI1_8CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac0 2>, <&dmac0 3>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_AUDIO>;
+			resets = <&cru SRST_M_SAI1_8CH>, <&cru SRST_H_SAI1_8CH>;
+			reset-names = "m", "h";
+			pinctrl-names = "default";
+			pinctrl-0 = <&sai1m0_lrck
+				&sai1m0_sclk
+				&sai1m0_sdi0
+				&sai1m0_sdo0
+				&sai1m0_sdo1
+				&sai1m0_sdo2
+				&sai1m0_sdo3>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI1";
+			status = "disabled";
+		};
+
+		sai2: sai at 2a620000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x2a620000 0x0 0x1000>;
+			interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI2_2CH>, <&cru HCLK_SAI2_2CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac1 0>, <&dmac1 1>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_AUDIO>;
+			resets = <&cru SRST_M_SAI2_2CH>, <&cru SRST_H_SAI2_2CH>;
+			reset-names = "m", "h";
+			pinctrl-names = "default";
+			pinctrl-0 = <&sai2m0_lrck
+				&sai2m0_sclk
+				&sai2m0_sdi
+				&sai2m0_sdo>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI2";
+			status = "disabled";
+		};
+
+		sai3: sai at 2a630000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x2a630000 0x0 0x1000>;
+			interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI3_2CH>, <&cru HCLK_SAI3_2CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac1 2>, <&dmac1 3>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_AUDIO>;
+			resets = <&cru SRST_M_SAI3_2CH>, <&cru SRST_H_SAI3_2CH>;
+			reset-names = "m", "h";
+			pinctrl-names = "default";
+			pinctrl-0 = <&sai3m0_lrck
+				&sai3m0_sclk
+				&sai3m0_sdi
+				&sai3m0_sdo>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI3";
+			status = "disabled";
+		};
+
+		sai4: sai at 2a640000 {
+			compatible = "rockchip,rk3576-sai";
+			reg = <0x0 0x2a640000 0x0 0x1000>;
+			interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru MCLK_SAI4_2CH>, <&cru HCLK_SAI4_2CH>;
+			clock-names = "mclk", "hclk";
+			dmas = <&dmac2 0>, <&dmac2 1>;
+			dma-names = "tx", "rx";
+			power-domains = <&power RK3576_PD_AUDIO>;
+			resets = <&cru SRST_M_SAI4_2CH>, <&cru SRST_H_SAI4_2CH>;
+			reset-names = "m", "h";
+			pinctrl-names = "default";
+			pinctrl-0 = <&sai4m0_lrck
+				&sai4m0_sclk
+				&sai4m0_sdi
+				&sai4m0_sdo>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SAI4";
+			status = "disabled";
+		};
+
 		gic: interrupt-controller at 2a701000 {
 			compatible = "arm,gic-400";
 			reg = <0x0 0x2a701000 0 0x10000>,

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:26 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:26 +0100
Subject: [PATCH 6/7] arm64: dts: rockchip: Add analog audio on RK3576 Sige5
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-6-64e6cf863e9a@collabora.com>

The ArmSoM Sige5 board features an Everest ES8388 codec to provide
analog stereo audio output, as well as analog audio input. The codec
hangs off the i2c2 bus and responds to address 0x10. It is connected to
the SAI1 audio controller of the RK3576, with one SDO (output) lane and
one SDI (input) lane.

The codec has two sets of outputs. One set, LOUT1/ROUT1, is connected
through a set of 22uF non-polarised coupling capacitors to a 3-position
connector that appears to be a clone of the JST BM03B-SURS-TF header,
and is capable of mating with a JST 03SUR-32S (or JST 03SUR-36L if you
prefer lemon-lime) or compatible clone connector. The right headphone
output is the one closest to the Type-C DC input connector, the left
headphone output is the one in the middle, and the third position, the
one closest to the USB3 Type-A host connector, is puzzingly labelled as
"HP_GND" in the schematic but is in fact connected to the codecs RIN1
input through a 1uF non-plarised coupling capacitor.

LOUT2 and ROUT2 are routed to 1mm test pads T36 and T37 respectively.
These are located on the bottom of the board, and do not go through any
coupling capacitor. For use as line out, the ES8388 datasheet recommends
adding 1uF coupling capacitor if one wishes to use it as a line-level
output.

There is also a pair of inputs for a stereo microphone, going from two
1mm testpads T34 and T35, which are decoupled with a 100pF capacitor and
pulled to 3.3v and ground respectively. These inputs then go through 1uF
capacitors each and end up in the LINPUT2 and RINPUT2 pins of the
ES8388 codec.

The codec's power inputs are routed to receive 3.3V for both its analog
and digital inputs, though from different supplies.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 .../boot/dts/rockchip/rk3576-armsom-sige5.dts      | 56 ++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
index 78798b0722a3f36831b1d2c9f29acb83910631cf..4970a7de70cd33040b2761122c04c7b8b20c99d5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
@@ -56,6 +56,34 @@ red_led: red-led {
 		};
 	};
 
+	es8388_sound: es8388-sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,mclk-fs = <256>;
+		simple-audio-card,name = "On-board Analog ES8388";
+		simple-audio-card,widgets = "Microphone", "Headphone Mic",
+					    "Microphone", "Mic Pads",
+					    "Headphone", "Headphone",
+					    "Line Out", "Line Out";
+		simple-audio-card,routing = "Headphone", "LOUT1",
+					    "Headphone", "ROUT1",
+					    "Line Out", "LOUT2",
+					    "Line Out", "ROUT2",
+					    "RINPUT1", "Headphone Mic",
+					    "LINPUT2", "Mic Pads",
+					    "RINPUT2", "Mic Pads";
+		simple-audio-card,pin-switches = "Headphone", "Line Out";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai1>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&es8388>;
+			system-clock-frequency = <12288000>;
+		};
+	};
+
 	vcc_12v0_dcin: regulator-vcc-12v0-dcin {
 		compatible = "regulator-fixed";
 		regulator-name = "vcc_12v0_dcin";
@@ -619,6 +647,25 @@ hym8563: rtc at 51 {
 	};
 };
 
+&i2c3 {
+	status = "okay";
+
+	es8388: audio-codec at 10 {
+		compatible = "everest,es8388", "everest,es8328";
+		reg = <0x10>;
+		clocks = <&cru CLK_SAI1_MCLKOUT_TO_IO>;
+		AVDD-supply = <&vcca_3v3_s0>;
+		DVDD-supply = <&vcc_3v3_s0>;
+		HPVDD-supply = <&vcca_3v3_s0>;
+		PVDD-supply = <&vcc_3v3_s0>;
+		assigned-clocks = <&cru CLK_SAI1_MCLKOUT_TO_IO>;
+		assigned-clock-rates = <12288000>;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sai1m0_mclk>;
+	};
+};
+
 &mdio0 {
 	rgmii_phy0: phy at 1 {
 		compatible = "ethernet-phy-ieee802.3-c22";
@@ -658,6 +705,15 @@ led_rgb_g: led-green-en {
 	};
 };
 
+&sai1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sai1m0_lrck
+		     &sai1m0_sclk
+		     &sai1m0_sdi0
+		     &sai1m0_sdo0>;
+	status = "okay";
+};
+
 &sdhci {
 	bus-width = <8>;
 	full-pwr-cycle-in-suspend;

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Wed Mar  5 13:24:27 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Wed, 05 Mar 2025 22:24:27 +0100
Subject: [PATCH 7/7] arm64: defconfig: Enable Rockchip SAI
In-Reply-To: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
Message-ID: <20250305-rk3576-sai-v1-7-64e6cf863e9a@collabora.com>

The RK3576 uses Rockchip SAI for audio output.

Enable it in the defconfig.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db29822036d25a7228f8936e2ad613b208..d503b5de2d2efb6d66d7fb8d7bafc10c0cf37b36 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1002,6 +1002,7 @@ CONFIG_SND_SOC_SC7280=m
 CONFIG_SND_SOC_X1E80100=m
 CONFIG_SND_SOC_ROCKCHIP=m
 CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m
+CONFIG_SND_SOC_ROCKCHIP_SAI=m
 CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
 CONFIG_SND_SOC_ROCKCHIP_RT5645=m
 CONFIG_SND_SOC_RK3399_GRU_SOUND=m

-- 
2.48.1



From jonas at kwiboo.se  Wed Mar  5 13:41:01 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed,  5 Mar 2025 21:41:01 +0000
Subject: [PATCH 0/3] rockchip: Add support for onboard eMMC on Radxa E20C
Message-ID: <20250305214108.1327208-1-jonas@kwiboo.se>

The Radxa E20C may come with an onboard eMMC (8GB / 16GB / 32GB / 64GB).

This series add dt-binding and SoC DT node for the SDHCI controller
and enable use of the SDCHI controller on the Radxa E20C.

This series add support for the onboard eMMC on Radxa E20C.

Driver changes to use different delay and tap num is needed to be able
to support HS400 modes, something for a future series. With this HS200
mode should work:

  mmc0: SDHCI controller on ffbf0000.mmc [ffbf0000.mmc] using ADMA
  mmc0: new HS200 MMC card at address 0001
  mmcblk0: mmc0:0001 TLi16G 14.7 GiB
   mmcblk0: p1 p2 p3
  mmcblk0boot0: mmc0:0001 TLi16G 4.00 MiB
  mmcblk0boot1: mmc0:0001 TLi16G 4.00 MiB
  mmcblk0rpmb: mmc0:0001 TLi16G 4.00 MiB, chardev (499:0)

  ~ # cat /sys/kernel/debug/mmc0/ios
  clock:          200000000 Hz
  actual clock:   198000000 Hz
  vdd:            21 (3.3 ~ 3.4V)
  bus mode:       2 (push-pull)
  chip select:    0 (don't care)
  power mode:     2 (on)
  bus width:      3 (8bits)
  timing spec:    9 (mmc HS200)
  signal voltage: 1 (1.80 V)
  driver type:    0 (driver type B)

  ~ # hdparm -t /dev/mmcblk0p1
  /dev/mmcblk0p1:
  Timing buffered disk reads:   64 MB in 0.37 seconds = 173154 kB/s

This series depends on v2 of the "Support SD/SDIO controllers on RK3528"
series for a clean apply.

Jonas Karlman (3):
  dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible string for RK3528
  arm64: dts: rockchip: Add SDHCI controller for RK3528
  arm64: dts: rockchip: Enable onboard eMMC on Radxa E20C

 .../bindings/mmc/snps,dwcmshc-sdhci.yaml      |  4 +++-
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 12 ++++++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 24 +++++++++++++++++++
 3 files changed, 39 insertions(+), 1 deletion(-)

-- 
2.48.1



From jonas at kwiboo.se  Wed Mar  5 13:41:02 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed,  5 Mar 2025 21:41:02 +0000
Subject: [PATCH 1/3] dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible string for RK3528
In-Reply-To: <20250305214108.1327208-1-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
Message-ID: <20250305214108.1327208-2-jonas@kwiboo.se>

The SDHCI controller in Rockchip RK3528 is similar to the one included
in RK3588.

Add compatible string for the SDHCI controller in RK3528.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index c3d5e0230af1..fb2115e805f5 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -14,7 +14,9 @@ properties:
   compatible:
     oneOf:
       - items:
-          - const: rockchip,rk3576-dwcmshc
+          - enum:
+              - rockchip,rk3528-dwcmshc
+              - rockchip,rk3576-dwcmshc
           - const: rockchip,rk3588-dwcmshc
       - enum:
           - rockchip,rk3568-dwcmshc
-- 
2.48.1



From jonas at kwiboo.se  Wed Mar  5 13:41:03 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed,  5 Mar 2025 21:41:03 +0000
Subject: [PATCH 2/3] arm64: dts: rockchip: Add SDHCI controller for RK3528
In-Reply-To: <20250305214108.1327208-1-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
Message-ID: <20250305214108.1327208-3-jonas@kwiboo.se>

The SDHCI controller in Rockchip RK3528 is similar to the one included
in RK3588.

Add device tree node for the SDHCI controller in RK3528.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 363023314e9c..c1a71ea81e03 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -286,6 +286,30 @@ saradc: adc at ffae0000 {
 			#io-channel-cells = <1>;
 		};
 
+		sdhci: mmc at ffbf0000 {
+			compatible = "rockchip,rk3528-dwcmshc",
+				     "rockchip,rk3588-dwcmshc";
+			reg = <0x0 0xffbf0000 0x0 0x10000>;
+			assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>,
+					  <&cru CCLK_SRC_EMMC>;
+			assigned-clock-rates = <200000000>, <24000000>,
+					       <200000000>;
+			clocks = <&cru CCLK_SRC_EMMC>, <&cru HCLK_EMMC>,
+				 <&cru ACLK_EMMC>, <&cru BCLK_EMMC>,
+				 <&cru TCLK_EMMC>;
+			clock-names = "core", "bus", "axi", "block", "timer";
+			interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <200000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&emmc_bus8>, <&emmc_clk>, <&emmc_cmd>,
+				    <&emmc_strb>;
+			resets = <&cru SRST_C_EMMC>, <&cru SRST_H_EMMC>,
+				 <&cru SRST_A_EMMC>, <&cru SRST_B_EMMC>,
+				 <&cru SRST_T_EMMC>;
+			reset-names = "core", "bus", "axi", "block", "timer";
+			status = "disabled";
+		};
+
 		sdio0: mmc at ffc10000 {
 			compatible = "rockchip,rk3528-dw-mshc",
 				     "rockchip,rk3288-dw-mshc";
-- 
2.48.1



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:42:01 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:42:01 +0100
Subject: [PATCH 00/12] clk: samsung: Use platform_driver_probe() to avoid
 __refdata
Message-ID: <20250305-clk-samsung-ref-init-data-v1-0-cd144b4fe31f@linaro.org>

RFT/RFC because testing needed. I tried to do the same on exynos5-subcmu
and it caused weird oopses which even KASAN did not narrow. Probably
because of multiple exynos5-subcmu devices?

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Best regards,
Krzysztof

---
Krzysztof Kozlowski (12):
      clk: samsung: exynos2200: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos4412-isp: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos5433: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos7870: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos7885: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos850: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos8895: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos990: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynosautov9: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynosautov920: Use platform_driver_probe() to avoid __refdata
      clk: samsung: fsd: Use platform_driver_probe() to avoid __refdata
      clk: samsung: gs101: Use platform_driver_probe() to avoid __refdata

 drivers/clk/samsung/clk-exynos2200.c     | 7 +++----
 drivers/clk/samsung/clk-exynos4412-isp.c | 7 +++----
 drivers/clk/samsung/clk-exynos5433.c     | 7 +++----
 drivers/clk/samsung/clk-exynos7870.c     | 7 +++----
 drivers/clk/samsung/clk-exynos7885.c     | 7 +++----
 drivers/clk/samsung/clk-exynos850.c      | 7 +++----
 drivers/clk/samsung/clk-exynos8895.c     | 7 +++----
 drivers/clk/samsung/clk-exynos990.c      | 7 +++----
 drivers/clk/samsung/clk-exynosautov9.c   | 5 ++---
 drivers/clk/samsung/clk-exynosautov920.c | 7 +++----
 drivers/clk/samsung/clk-fsd.c            | 7 +++----
 drivers/clk/samsung/clk-gs101.c          | 7 +++----
 12 files changed, 35 insertions(+), 47 deletions(-)
---
base-commit: 7ec162622e66a4ff886f8f28712ea1b13069e1aa
change-id: 20250305-clk-samsung-ref-init-data-6b2cd242409f

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:31 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 5 Mar 2025 22:43:31 +0100
Subject: [PATCH 00/12] clk: samsung: Use platform_driver_probe() to avoid
 __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-cd144b4fe31f@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-cd144b4fe31f@linaro.org>
Message-ID: <d54262ca-2229-4230-bd2d-6d9efa7257a4@linaro.org>

On 05/03/2025 22:42, Krzysztof Kozlowski wrote:
> RFT/RFC because testing needed. I tried to do the same on exynos5-subcmu
> and it caused weird oopses which even KASAN did not narrow. Probably
> because of multiple exynos5-subcmu devices?
> 
> Switch registering platform driver to platform_driver_probe(), so the
> 'struct platform_driver' can be properly discarded after init and there
> won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.
> 
> The change requires using subsys_initcall instead of core_initcall,
> because no device drivers would bound in the latter, as required by
> platform_driver_probe().

Forgot to set prefix and I aborted this send. Please ignore, new posting
coming.

Best regards,
Krzysztof


From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:35 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:35 +0100
Subject: [PATCH RFC/RFT 00/12] clk: samsung: Use platform_driver_probe() to
 avoid __refdata
Message-ID: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>

RFT/RFC because testing needed. I tried to do the same on exynos5-subcmu
and it caused weird oopses which even KASAN did not narrow. Probably
because of multiple exynos5-subcmu devices?

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Best regards,
Krzysztof

---
Krzysztof Kozlowski (12):
      clk: samsung: exynos2200: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos4412-isp: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos5433: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos7870: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos7885: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos850: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos8895: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynos990: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynosautov9: Use platform_driver_probe() to avoid __refdata
      clk: samsung: exynosautov920: Use platform_driver_probe() to avoid __refdata
      clk: samsung: fsd: Use platform_driver_probe() to avoid __refdata
      clk: samsung: gs101: Use platform_driver_probe() to avoid __refdata

 drivers/clk/samsung/clk-exynos2200.c     | 7 +++----
 drivers/clk/samsung/clk-exynos4412-isp.c | 7 +++----
 drivers/clk/samsung/clk-exynos5433.c     | 7 +++----
 drivers/clk/samsung/clk-exynos7870.c     | 7 +++----
 drivers/clk/samsung/clk-exynos7885.c     | 7 +++----
 drivers/clk/samsung/clk-exynos850.c      | 7 +++----
 drivers/clk/samsung/clk-exynos8895.c     | 7 +++----
 drivers/clk/samsung/clk-exynos990.c      | 7 +++----
 drivers/clk/samsung/clk-exynosautov9.c   | 5 ++---
 drivers/clk/samsung/clk-exynosautov920.c | 7 +++----
 drivers/clk/samsung/clk-fsd.c            | 7 +++----
 drivers/clk/samsung/clk-gs101.c          | 7 +++----
 12 files changed, 35 insertions(+), 47 deletions(-)
---
base-commit: 7ec162622e66a4ff886f8f28712ea1b13069e1aa
change-id: 20250305-clk-samsung-ref-init-data-6b2cd242409f

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:36 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:36 +0100
Subject: [PATCH RFC/RFT 01/12] clk: samsung: exynos2200: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-1-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Testing needed.

My initial tests on Exynos5422 lead to weird, unrelated oopses, probably
because of multiple exynos5-subcmu devices. Not sure if applicable here,
but change of initcal might have actual impact.
---
 drivers/clk/samsung/clk-exynos2200.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos2200.c b/drivers/clk/samsung/clk-exynos2200.c
index 151bdb35a46c42d0b50f48d47974065a892bbb5f..f1251d4f01781fd503f24189cc53b23e627ab5e1 100644
--- a/drivers/clk/samsung/clk-exynos2200.c
+++ b/drivers/clk/samsung/clk-exynos2200.c
@@ -3912,17 +3912,16 @@ static const struct of_device_id exynos2200_cmu_of_match[] = {
 	}, { }
 };
 
-static struct platform_driver exynos2200_cmu_driver __refdata = {
+static struct platform_driver exynos2200_cmu_driver __initdata = {
 	.driver = {
 		.name = "exynos2200-cmu",
 		.of_match_table = exynos2200_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos2200_cmu_probe,
 };
 
 static int __init exynos2200_cmu_init(void)
 {
-	return platform_driver_register(&exynos2200_cmu_driver);
+	return platform_driver_probe(&exynos2200_cmu_driver, exynos2200_cmu_probe);
 }
-core_initcall(exynos2200_cmu_init);
+subsys_initcall(exynos2200_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:37 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:37 +0100
Subject: [PATCH RFC/RFT 02/12] clk: samsung: exynos4412-isp: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-2-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos4412-isp.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index 29c5644f059379f8a0770ce2214c32b9df7d76e3..f288c152d3f769fbb5123c3b79fe4ddc8c23aa55 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -155,18 +155,17 @@ static const struct dev_pm_ops exynos4x12_isp_pm_ops = {
 				     pm_runtime_force_resume)
 };
 
-static struct platform_driver exynos4x12_isp_clk_driver __refdata = {
+static struct platform_driver exynos4x12_isp_clk_driver __initdata = {
 	.driver	= {
 		.name = "exynos4x12-isp-clk",
 		.of_match_table = exynos4x12_isp_clk_of_match,
 		.suppress_bind_attrs = true,
 		.pm = &exynos4x12_isp_pm_ops,
 	},
-	.probe = exynos4x12_isp_clk_probe,
 };
 
 static int __init exynos4x12_isp_clk_init(void)
 {
-	return platform_driver_register(&exynos4x12_isp_clk_driver);
+	return platform_driver_probe(&exynos4x12_isp_clk_driver, exynos4x12_isp_clk_probe);
 }
-core_initcall(exynos4x12_isp_clk_init);
+subsys_initcall(exynos4x12_isp_clk_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:38 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:38 +0100
Subject: [PATCH RFC/RFT 03/12] clk: samsung: exynos5433: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-3-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos5433.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 609d31a7aa5247e6318884609d1e651001616b73..d18b4f7b96b66e48fb94b86b663443ec691e968d 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -5555,18 +5555,17 @@ static const struct dev_pm_ops exynos5433_cmu_pm_ops = {
 				     pm_runtime_force_resume)
 };
 
-static struct platform_driver exynos5433_cmu_driver __refdata = {
+static struct platform_driver exynos5433_cmu_driver __initdata = {
 	.driver	= {
 		.name = "exynos5433-cmu",
 		.of_match_table = exynos5433_cmu_of_match,
 		.suppress_bind_attrs = true,
 		.pm = &exynos5433_cmu_pm_ops,
 	},
-	.probe = exynos5433_cmu_probe,
 };
 
 static int __init exynos5433_cmu_init(void)
 {
-	return platform_driver_register(&exynos5433_cmu_driver);
+	return platform_driver_probe(&exynos5433_cmu_driver, exynos5433_cmu_probe);
 }
-core_initcall(exynos5433_cmu_init);
+subsys_initcall(exynos5433_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:39 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:39 +0100
Subject: [PATCH RFC/RFT 04/12] clk: samsung: exynos7870: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-4-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos7870.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos7870.c b/drivers/clk/samsung/clk-exynos7870.c
index 2ec4a4e489be30bd1cd2e6deac006bb8ac5bdc57..c3d7d816cab673518c7b01ce35b0faf249692835 100644
--- a/drivers/clk/samsung/clk-exynos7870.c
+++ b/drivers/clk/samsung/clk-exynos7870.c
@@ -1814,17 +1814,16 @@ static const struct of_device_id exynos7870_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver exynos7870_cmu_driver __refdata = {
+static struct platform_driver exynos7870_cmu_driver __initdata = {
 	.driver = {
 		.name = "exynos7870-cmu",
 		.of_match_table = exynos7870_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos7870_cmu_probe,
 };
 
 static int __init exynos7870_cmu_init(void)
 {
-	return platform_driver_register(&exynos7870_cmu_driver);
+	return platform_driver_probe(&exynos7870_cmu_driver, exynos7870_cmu_probe);
 }
-core_initcall(exynos7870_cmu_init);
+subsys_initcall(exynos7870_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:40 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:40 +0100
Subject: [PATCH RFC/RFT 05/12] clk: samsung: exynos7885: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-5-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos7885.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos7885.c b/drivers/clk/samsung/clk-exynos7885.c
index fc42251731edb6f8368d38638179056f8bc58335..0066c89e3515b852c7c6265322f8a1dc07af57ad 100644
--- a/drivers/clk/samsung/clk-exynos7885.c
+++ b/drivers/clk/samsung/clk-exynos7885.c
@@ -832,17 +832,16 @@ static const struct of_device_id exynos7885_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver exynos7885_cmu_driver __refdata = {
+static struct platform_driver exynos7885_cmu_driver __initdata = {
 	.driver	= {
 		.name = "exynos7885-cmu",
 		.of_match_table = exynos7885_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos7885_cmu_probe,
 };
 
 static int __init exynos7885_cmu_init(void)
 {
-	return platform_driver_register(&exynos7885_cmu_driver);
+	return platform_driver_probe(&exynos7885_cmu_driver, exynos7885_cmu_probe);
 }
-core_initcall(exynos7885_cmu_init);
+subsys_initcall(exynos7885_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:41 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:41 +0100
Subject: [PATCH RFC/RFT 06/12] clk: samsung: exynos850: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-6-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos850.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index e00e213b1201c82ac0c70cfe23d5ccc9c04f2aa3..37c06cbbe78f87e18877d33425fcd03b97a61e7f 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -2322,17 +2322,16 @@ static const struct of_device_id exynos850_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver exynos850_cmu_driver __refdata = {
+static struct platform_driver exynos850_cmu_driver __initdata = {
 	.driver	= {
 		.name = "exynos850-cmu",
 		.of_match_table = exynos850_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos850_cmu_probe,
 };
 
 static int __init exynos850_cmu_init(void)
 {
-	return platform_driver_register(&exynos850_cmu_driver);
+	return platform_driver_probe(&exynos850_cmu_driver, exynos850_cmu_probe);
 }
-core_initcall(exynos850_cmu_init);
+subsys_initcall(exynos850_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:42 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:42 +0100
Subject: [PATCH RFC/RFT 07/12] clk: samsung: exynos8895: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-7-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos8895.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
index 29ec0c4a863524fe3fc5c223d762da87e5f13013..6b85d917871d20fd3a3f6768937eb5694760ffd2 100644
--- a/drivers/clk/samsung/clk-exynos8895.c
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -2787,17 +2787,16 @@ static const struct of_device_id exynos8895_cmu_of_match[] = {
 	{ }
 };
 
-static struct platform_driver exynos8895_cmu_driver __refdata = {
+static struct platform_driver exynos8895_cmu_driver __initdata = {
 	.driver = {
 		.name = "exynos8895-cmu",
 		.of_match_table = exynos8895_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos8895_cmu_probe,
 };
 
 static int __init exynos8895_cmu_init(void)
 {
-	return platform_driver_register(&exynos8895_cmu_driver);
+	return platform_driver_probe(&exynos8895_cmu_driver, exynos8895_cmu_probe);
 }
-core_initcall(exynos8895_cmu_init);
+subsys_initcall(exynos8895_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:43 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:43 +0100
Subject: [PATCH RFC/RFT 08/12] clk: samsung: exynos990: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-8-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynos990.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos990.c b/drivers/clk/samsung/clk-exynos990.c
index 76f22a4a4631fadf400420b977f3f59f40f840c7..d00050d8765f25042698cbe6bfa06623931c7414 100644
--- a/drivers/clk/samsung/clk-exynos990.c
+++ b/drivers/clk/samsung/clk-exynos990.c
@@ -1504,18 +1504,17 @@ static const struct of_device_id exynos990_cmu_of_match[] = {
 	{ },
 };
 
-static struct platform_driver exynos990_cmu_driver __refdata = {
+static struct platform_driver exynos990_cmu_driver __initdata = {
 	.driver	= {
 		.name = "exynos990-cmu",
 		.of_match_table = exynos990_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynos990_cmu_probe,
 };
 
 static int __init exynos990_cmu_init(void)
 {
-	return platform_driver_register(&exynos990_cmu_driver);
+	return platform_driver_probe(&exynos990_cmu_driver, exynos990_cmu_probe);
 }
 
-core_initcall(exynos990_cmu_init);
+subsys_initcall(exynos990_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:44 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:44 +0100
Subject: [PATCH RFC/RFT 09/12] clk: samsung: exynosautov9: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-9-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynosautov9.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
index 5971e680e566336ecdf55bdccacc3cea09a33201..627f3d2666740fc4cba205e6e2da65f53b8df186 100644
--- a/drivers/clk/samsung/clk-exynosautov9.c
+++ b/drivers/clk/samsung/clk-exynosautov9.c
@@ -2190,17 +2190,16 @@ static const struct of_device_id exynosautov9_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver exynosautov9_cmu_driver __refdata = {
+static struct platform_driver exynosautov9_cmu_driver __initdata = {
 	.driver = {
 		.name = "exynosautov9-cmu",
 		.of_match_table = exynosautov9_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynosautov9_cmu_probe,
 };
 
 static int __init exynosautov9_cmu_init(void)
 {
-	return platform_driver_register(&exynosautov9_cmu_driver);
+	return platform_driver_probe(&exynosautov9_cmu_driver, exynosautov9_cmu_probe);
 }
 core_initcall(exynosautov9_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:45 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:45 +0100
Subject: [PATCH RFC/RFT 10/12] clk: samsung: exynosautov920: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-10-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-exynosautov920.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index 2a8bfd5d9abc8acced4e5a3eaacefe5fa724cbd2..e0ba75fd20177022dc7f461af5968c154b6a8a37 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -1447,17 +1447,16 @@ static const struct of_device_id exynosautov920_cmu_of_match[] = {
 	{ }
 };
 
-static struct platform_driver exynosautov920_cmu_driver __refdata = {
+static struct platform_driver exynosautov920_cmu_driver __initdata = {
 	.driver = {
 		.name = "exynosautov920-cmu",
 		.of_match_table = exynosautov920_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = exynosautov920_cmu_probe,
 };
 
 static int __init exynosautov920_cmu_init(void)
 {
-	return platform_driver_register(&exynosautov920_cmu_driver);
+	return platform_driver_probe(&exynosautov920_cmu_driver, exynosautov920_cmu_probe);
 }
-core_initcall(exynosautov920_cmu_init);
+subsys_initcall(exynosautov920_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:46 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:46 +0100
Subject: [PATCH RFC/RFT 11/12] clk: samsung: fsd: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-11-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-fsd.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 9a6006c298c2a80da0e29aeca3b09cc827caac0c..bc0287c780bfe3a68a38f53f554440b3000b1ca7 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -1794,17 +1794,16 @@ static const struct of_device_id fsd_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver fsd_cmu_driver __refdata = {
+static struct platform_driver fsd_cmu_driver __initdata = {
 	.driver	= {
 		.name = "fsd-cmu",
 		.of_match_table = fsd_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = fsd_cmu_probe,
 };
 
 static int __init fsd_cmu_init(void)
 {
-	return platform_driver_register(&fsd_cmu_driver);
+	return platform_driver_probe(&fsd_cmu_driver, fsd_cmu_probe);
 }
-core_initcall(fsd_cmu_init);
+subsys_initcall(fsd_cmu_init);

-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Wed Mar  5 13:43:47 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 05 Mar 2025 22:43:47 +0100
Subject: [PATCH RFC/RFT 12/12] clk: samsung: gs101: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <20250305-clk-samsung-ref-init-data-v1-12-a4e03a019306@linaro.org>

Switch registering platform driver to platform_driver_probe(), so the
'struct platform_driver' can be properly discarded after init and there
won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.

The change requires using subsys_initcall instead of core_initcall,
because no device drivers would bound in the latter, as required by
platform_driver_probe().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/clk/samsung/clk-gs101.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 86b39edba12276745a124df6a2ea9c22d74b915a..69c121d478f3fec98dcd84e0639e204fe604e91c 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -4412,17 +4412,16 @@ static const struct of_device_id gs101_cmu_of_match[] = {
 	},
 };
 
-static struct platform_driver gs101_cmu_driver __refdata = {
+static struct platform_driver gs101_cmu_driver __initdata = {
 	.driver	= {
 		.name = "gs101-cmu",
 		.of_match_table = gs101_cmu_of_match,
 		.suppress_bind_attrs = true,
 	},
-	.probe = gs101_cmu_probe,
 };
 
 static int __init gs101_cmu_init(void)
 {
-	return platform_driver_register(&gs101_cmu_driver);
+	return platform_driver_probe(&gs101_cmu_driver, gs101_cmu_probe);
 }
-core_initcall(gs101_cmu_init);
+subsys_initcall(gs101_cmu_init);

-- 
2.43.0



From sebastian.reichel at collabora.com  Wed Mar  5 13:52:36 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Wed, 5 Mar 2025 22:52:36 +0100
Subject: [PATCH v2 2/2] phy: rockchip: usbdp: re-init the phy on
 orientation-change
In-Reply-To: <2af85aa0-96dc-43ea-9542-88f91b21a028@cherry.de>
References: <20250226103810.3746018-1-heiko@sntech.de>
 <20250226103810.3746018-3-heiko@sntech.de>
 <02757b21-7599-4ee7-9f97-247b04ba646a@cherry.de>
 <dkjpudmzuuxvaotz4mx46yx7iacof7q6ck746j3rrqvlgbq3hk@6vtvy3gy3kff>
 <2af85aa0-96dc-43ea-9542-88f91b21a028@cherry.de>
Message-ID: <4mhobm5oxhjim6m2dwzmt63riuoruwaivmftnuaodwvplnleeg@w7yyv3zyxewe>

Hi,

On Mon, Mar 03, 2025 at 10:27:31AM +0100, Quentin Schulz wrote:
> On 3/1/25 10:19 PM, Sebastian Reichel wrote:
> > On Wed, Feb 26, 2025 at 01:38:10PM +0100, Quentin Schulz wrote:
> > > Unrelated to this patch (but may be triggered by this patch?), I'm wondering
> > > how flip is really handled.
> > > 
> > > It seems like we have flip store the orientation of the cable, but also if
> > > rockchip,dp-lane-mux is set to <0 1>. But wouldn't that break if we ignore
> > > that initial flipped lane-mux whenever a USB-C cable is inserted in reverse?
> > > Basically, shouldn't a reserve orientation of the cable when
> > > rockchip,dp-lane-mux is set to <0 1> mean "normal mux"?
> > 
> > If a USB-C connector is involved, the TypeC controller is supposed to
> > setup the lane muxing based on the connector orientation. This
> > happens via the typec API and in this hardware setup the PHY should
> > not have the rockchip,dp-lane-mux DT property set.
> > 
> 
> I could see some HW routing "mistake" where the USB-C connector in normal
> orientation has DP lanes routed to RX1/TX1? Or is this expected to just be
> faulty HW we shouldn't attempt at supporting?

You mean somebody routing the RK3588 SSTX1 and SSRX1 pins to SSTX2
and SSRX2 of the TypeC connector and vice versa and thus effectively
inverting the orientation on their board? I would say let's worry
about that once somebody comes up with such a cursed hardware design.

Note, that rockchip,dp-lane-mux wouldn't be a good property for this
setup either. With USB-C you don't necessarily have 2 lanes USB3 and
2 lanes DP. You can also have 4 lanes USB3 (not supported by RK3588)
or 4 lanes DP (should be supported by RK3588 hardware). So
hardwiring the mux is a bad idea. Probably would require some flag
for the TypeC orientation switch to handle the orientation
information inverted.

> > The rockchip,dp-lane-mux property is required if no USB-C connector
> > is involved. For example if the lanes are routed to a Displayport
> > connector. In that case the lane setup is fixed in hardware and
> > there is no TypeC controller involved, which could do any setup ;)
> > 
> 
> Yup I've seen that for the Rock 5 ITX and the evaluation board(s) do this.
> Quite interesting :)
> 
> Cheers,
> Quentin

Greetings,

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250305/dcb8d0c2/attachment.sig>

From robh at kernel.org  Wed Mar  5 14:19:46 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 16:19:46 -0600
Subject: [PATCH 1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
In-Reply-To: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
Message-ID: <CAL_JsqJgjD69wtJJfLuvBQ4g+JprxQ9mKGPWGgY1dmziehe-Kw@mail.gmail.com>

On Wed, Mar 5, 2025 at 8:00?AM Chukun Pan <amadeus at jmu.edu.cn> wrote:
>
> Document rk3528 compatible for QoS registers.
>
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
> index 4d67ff26d445..fcfd293b9bf1 100644
> --- a/Documentation/devicetree/bindings/mfd/syscon.yaml
> +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
> @@ -103,6 +103,7 @@ select:
>            - rockchip,rk3288-qos
>            - rockchip,rk3368-qos
>            - rockchip,rk3399-qos
> +          - rockchip,rk3528-qos

There's 2 spots you have to add this.

>            - rockchip,rk3562-qos
>            - rockchip,rk3568-qos
>            - rockchip,rk3576-qos
> --
> 2.25.1
>


From cki-project at redhat.com  Wed Mar  5 12:22:04 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Wed, 05 Mar 2025 20:22:04 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <43734.125030515220700439@us-mta-673.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1701722580

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1701722580-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From devnull+fnkl.kernel.gmail.com at kernel.org  Wed Mar  5 12:26:38 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Wed, 05 Mar 2025 21:26:38 +0100
Subject: [PATCH 0/3] Driver for Apple SPMI controller
Message-ID: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>

Hi.

This patch series adds support for the SPMI controller persent in most
Apple SoCs. The drivers for the attached PMU and subdevices will be in
further patch series.

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
Jean-Francois Bortolotti (1):
      spmi: add a spmi driver for Apple SoC

Sasha Finkelstein (2):
      dt-bindings: spmi: Add Apple SPMI controller
      arm64: dts: apple: Add SPMI controller nodes

 .../devicetree/bindings/spmi/apple,spmi.yaml       |  56 +++++++
 MAINTAINERS                                        |   2 +
 arch/arm64/boot/dts/apple/t600x-die0.dtsi          |   7 +
 arch/arm64/boot/dts/apple/t8103.dtsi               |   8 +
 arch/arm64/boot/dts/apple/t8112.dtsi               |   8 +
 drivers/spmi/Kconfig                               |   8 +
 drivers/spmi/Makefile                              |   1 +
 drivers/spmi/spmi-apple-controller.c               | 176 +++++++++++++++++++++
 8 files changed, 266 insertions(+)
---
base-commit: 48a5eed9ad584315c30ed35204510536235ce402
change-id: 20250304-spmi-6d3c24b9027a




From devnull+fnkl.kernel.gmail.com at kernel.org  Wed Mar  5 12:26:39 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Wed, 05 Mar 2025 21:26:39 +0100
Subject: [PATCH 1/3] dt-bindings: spmi: Add Apple SPMI controller
In-Reply-To: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
Message-ID: <20250305-spmi-v1-1-c98f561fa99f@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add bindings for the SPMI controller present on most Apple SoCs

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 .../devicetree/bindings/spmi/apple,spmi.yaml       | 56 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 57 insertions(+)

diff --git a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6404af8adec52f4631200c48956f4c1695e88a39
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SPMI controller
+
+maintainers:
+  - Sasha Finkelstein <fnkl.kernel at gmail.com>
+
+description: A SPMI controller present on most Apple SoCs
+
+allOf:
+  - $ref: spmi.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - apple,t8103-spmi
+          - apple,t6000-spmi
+          - apple,t8112-spmi
+      - const: apple,spmi
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "pmu@[0-9a-f]$":
+    type: object
+
+    description:
+      PMIC properties, which are specific to the used SPMI PMIC device(s).
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+
+    spmi at 920a1300 {
+        compatible = "apple,t6000-spmi", "apple,spmi";
+        reg = <0x920a1300 0x100>;
+        #address-cells = <2>;
+        #size-cells = <0>;
+
+        pmu at f {
+            reg = <0xf SPMI_USID>;
+            /* PMIC-specific properties */
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0e33544fa373a4978b7dae18c040c..271ff8110df83c2d4fe7fbbfffc0a72259460bc5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2236,6 +2236,7 @@ F:	Documentation/devicetree/bindings/pci/apple,pcie.yaml
 F:	Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
 F:	Documentation/devicetree/bindings/power/apple*
 F:	Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
+F:	Documentation/devicetree/bindings/spmi/apple,spmi.yaml
 F:	Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
 F:	arch/arm64/boot/dts/apple/
 F:	drivers/bluetooth/hci_bcm4377.c

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Wed Mar  5 12:26:40 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Wed, 05 Mar 2025 21:26:40 +0100
Subject: [PATCH 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
Message-ID: <20250305-spmi-v1-2-c98f561fa99f@gmail.com>

From: Jean-Francois Bortolotti <jeff at borto.fr>

Signed-off-by: Jean-Francois Bortolotti <jeff at borto.fr>
Co-developed-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 MAINTAINERS                          |   1 +
 drivers/spmi/Kconfig                 |   8 ++
 drivers/spmi/Makefile                |   1 +
 drivers/spmi/spmi-apple-controller.c | 176 +++++++++++++++++++++++++++++++++++
 4 files changed, 186 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 271ff8110df83c2d4fe7fbbfffc0a72259460bc5..9006695261d29fbc1e15659c2b43d7afeee0b656 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2254,6 +2254,7 @@ F:	drivers/nvmem/apple-efuses.c
 F:	drivers/pinctrl/pinctrl-apple-gpio.c
 F:	drivers/pwm/pwm-apple.c
 F:	drivers/soc/apple/*
+F:	drivers/spmi/spmi-apple-controller.c
 F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 73780204631463631cabcbad5bf83e8dbbee94ce..9005fa91d9f4e541403ccc7bf84e0592402ac41e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,14 @@ menuconfig SPMI
 
 if SPMI
 
+config SPMI_APPLE
+	tristate "Apple SoC SPMI Controller platform driver"
+	depends on ARCH_APPLE || COMPILE_TEST
+	help
+	  If you say yes to this option, support will be included for the
+	  SPMI controller present on many Apple SoCs, including the
+	  t8103 (M1) and t600x (M1 Pro/Max).
+
 config SPMI_HISI3670
 	tristate "Hisilicon 3670 SPMI Controller"
 	select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 7f152167bb05b2c24a0f9669f60278152898eebb..38ac635645ba65aa46cb5e8a50072ed9771e229b 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,6 +4,7 @@
 #
 obj-$(CONFIG_SPMI)	+= spmi.o spmi-devres.o
 
+obj-$(CONFIG_SPMI_APPLE)	+= spmi-apple-controller.o
 obj-$(CONFIG_SPMI_HISI3670)	+= hisi-spmi-controller.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
 obj-$(CONFIG_SPMI_MTK_PMIF)	+= spmi-mtk-pmif.o
diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c
new file mode 100644
index 0000000000000000000000000000000000000000..194fa5dd7c2c6fc4ecfbee0db7930b0c73b02550
--- /dev/null
+++ b/drivers/spmi/spmi-apple-controller.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple SoC SPMI device driver
+ *
+ * Copyright The Asahi Linux Contributors
+ *
+ * Inspired by:
+ *		OpenBSD support Copyright (c) 2021 Mark Kettenis <kettenis at openbsd.org>
+ *		Correllium support Copyright (C) 2021 Corellium LLC
+ *		hisi-spmi-controller.c
+ *		spmi-pmic-ard.c Copyright (c) 2021, The Linux Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+/* SPMI Controller Registers */
+#define SPMI_STATUS_REG 0
+#define SPMI_CMD_REG 0x4
+#define SPMI_RSP_REG 0x8
+
+#define SPMI_RX_FIFO_EMPTY BIT(24)
+
+#define REG_POLL_INTERVAL 10000
+#define REG_POLL_TIMEOUT (REG_POLL_INTERVAL * 5)
+
+struct apple_spmi {
+	void __iomem *regs;
+};
+
+#define poll_reg(spmi, reg, val, cond) \
+	readl_relaxed_poll_timeout((spmi)->regs + (reg), (val), (cond), \
+				   REG_POLL_INTERVAL, REG_POLL_TIMEOUT)
+
+static inline u32 read_reg(struct apple_spmi *spmi, int offset)
+{
+	return readl_relaxed(spmi->regs + offset);
+}
+
+static inline void write_reg(u32 value, struct apple_spmi *spmi, int offset)
+{
+	writel_relaxed(value, spmi->regs + offset);
+}
+
+static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			 u16 saddr, u8 *__buf, size_t bc)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = opc | sid << 8 | saddr << 16 | (bc - 1) | (1 << 15);
+	u32 rsp;
+	u32 status;
+	size_t len_to_read = 0;
+	u8 i;
+	int ret;
+
+	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+
+	/* Wait for Rx FIFO to have something */
+	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
+	if (ret) {
+		dev_err(&ctrl->dev,
+			"%s:Failed to wait for RX FIFO not empty\n", __func__);
+		return ret;
+	}
+
+	/* Discard SPMI reply status */
+	read_reg(spmi, SPMI_RSP_REG);
+
+	/* Read SPMI data reply */
+	while (len_to_read < bc) {
+		rsp = read_reg(spmi, SPMI_RSP_REG);
+		i = 0;
+		while ((len_to_read < bc) && (i < 4)) {
+			__buf[len_to_read++] = ((0xff << (8 * i)) & rsp) >>
+					       (8 * i);
+			i += 1;
+		}
+	}
+
+	return 0;
+}
+
+static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			  u16 saddr, const u8 *__buf, size_t bc)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = opc | sid << 8 | saddr << 16 | (bc - 1) | (1 << 15);
+	u32 status;
+	size_t i = 0, j;
+	int ret;
+
+	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+
+	while (i < bc) {
+		j = 0;
+		spmi_cmd = 0;
+		while ((j < 4) & (i < bc))
+			spmi_cmd |= __buf[i++] << (j++ * 8);
+
+		write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+	}
+
+	/* Wait for Rx FIFO to have something */
+	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
+	if (ret) {
+		dev_err(&ctrl->dev,
+			"%s:Failed to wait for RX FIFO not empty\n", __func__);
+		return ret;
+	}
+
+	/* Discard */
+	read_reg(spmi, SPMI_RSP_REG);
+
+	return 0;
+}
+
+static int spmi_controller_probe(struct platform_device *pdev)
+{
+	struct apple_spmi *spmi;
+	struct spmi_controller *ctrl;
+	int ret;
+
+	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
+	if (IS_ERR(ctrl)) {
+		dev_err_probe(&pdev->dev, PTR_ERR(ctrl),
+			      "Can't allocate spmi_controller data\n");
+		return -ENOMEM;
+	}
+
+	spmi = spmi_controller_get_drvdata(ctrl);
+
+	spmi->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(spmi->regs)) {
+		dev_err_probe(&pdev->dev, PTR_ERR(spmi->regs),
+			      "Can't get ioremap regs\n");
+		return PTR_ERR(spmi->regs);
+	}
+
+	ctrl->dev.of_node = of_node_get(pdev->dev.of_node);
+
+	ctrl->read_cmd = spmi_read_cmd;
+	ctrl->write_cmd = spmi_write_cmd;
+
+	ret = devm_spmi_controller_add(&pdev->dev, ctrl);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"spmi_controller_add failed with error %d!\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id spmi_controller_match_table[] = {
+	{ .compatible = "apple,spmi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, spmi_controller_match_table);
+
+static struct platform_driver spmi_controller_driver = {
+	.probe		= spmi_controller_probe,
+	.driver		= {
+		.name	= "apple-spmi",
+		.of_match_table = spmi_controller_match_table,
+	},
+};
+module_platform_driver(spmi_controller_driver);
+
+MODULE_AUTHOR("Jean-Francois Bortolotti <jeff at borto.fr>");
+MODULE_DESCRIPTION("Apple SoC SPMI driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Wed Mar  5 12:26:41 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Wed, 05 Mar 2025 21:26:41 +0100
Subject: [PATCH 3/3] arm64: dts: apple: Add SPMI controller nodes
In-Reply-To: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
Message-ID: <20250305-spmi-v1-3-c98f561fa99f@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add device tree entries for the SPMI controller

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 arch/arm64/boot/dts/apple/t600x-die0.dtsi | 7 +++++++
 arch/arm64/boot/dts/apple/t8103.dtsi      | 8 ++++++++
 arch/arm64/boot/dts/apple/t8112.dtsi      | 8 ++++++++
 3 files changed, 23 insertions(+)

diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index b1c875e692c8fb9c0af46a23568a7b0cd720141b..d544a35c8af414c583d38b040e1aa753902f1c93 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -53,6 +53,13 @@ wdt: watchdog at 2922b0000 {
 		interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	nub_spmi0: spmi at 2920a1300 {
+		compatible = "apple,t6000-spmi", "apple,spmi";
+		reg = <0x2 0x920a1300 0x0 0x100>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+	};
+
 	sio_dart_0: iommu at 39b004000 {
 		compatible = "apple,t6000-dart";
 		reg = <0x3 0x9b004000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 9b0dad6b618444ac6b1c9735c50cccfc3965f947..0f03dc808cf7c6b7d71afc79dd29d368f957f979 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/interrupt-controller/apple-aic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
 
 / {
 	compatible = "apple,t8103", "apple,arm-platform";
@@ -604,6 +605,13 @@ pcie_pins: pcie-pins {
 			};
 		};
 
+		nub_spmi: spmi at 23d0d9300 {
+			compatible = "apple,t8103-spmi", "apple,spmi";
+			reg = <0x2 0x3d0d9300 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_nub: pinctrl at 23d1f0000 {
 			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3d1f0000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 1666e6ab250bc0be9b8318e3c8fc903ccd3f3760..4b3730c46c4d14a582627f69094b458ec7481da9 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -641,6 +641,14 @@ pcie_pins: pcie-pins {
 			};
 		};
 
+
+		nub_spmi: spmi at 23d714000 {
+			compatible = "apple,t8112-spmi", "apple,spmi";
+			reg = <0x2 0x3d714000 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_nub: pinctrl at 23d1f0000 {
 			compatible = "apple,t8112-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3d1f0000 0x0 0x4000>;

-- 
2.48.1




From oliver.upton at linux.dev  Wed Mar  5 12:26:29 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:29 -0800
Subject: [PATCH v3 02/14] drivers/perf: apple_m1: Support host/guest event filtering
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-3-oliver.upton@linux.dev>

The PMU appears to have a separate register for filtering 'guest'
exception levels (i.e. EL1 and !ELIsInHost(EL0)) which has the same
layout as PMCR1_EL1. Conveniently, there exists a VHE register alias
(PMCR1_EL12) that can be used to configure it.

Support guest events by programming the EL12 register with the intended
guest kernel/userspace filters. Limit support for guest events to VHE
(i.e. kernel running at EL2), as it avoids involving KVM to context
switch PMU registers. VHE is the only supported mode on M* parts anyway,
so this isn't an actual feature limitation.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/include/asm/apple_m1_pmu.h |  1 +
 drivers/perf/apple_m1_cpu_pmu.c       | 20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/apple_m1_pmu.h b/arch/arm64/include/asm/apple_m1_pmu.h
index 99483b19b99f..02e05d05851f 100644
--- a/arch/arm64/include/asm/apple_m1_pmu.h
+++ b/arch/arm64/include/asm/apple_m1_pmu.h
@@ -37,6 +37,7 @@
 #define PMCR0_PMI_ENABLE_8_9	GENMASK(45, 44)
 
 #define SYS_IMP_APL_PMCR1_EL1	sys_reg(3, 1, 15, 1, 0)
+#define SYS_IMP_APL_PMCR1_EL12	sys_reg(3, 1, 15, 7, 2)
 #define PMCR1_COUNT_A64_EL0_0_7	GENMASK(15, 8)
 #define PMCR1_COUNT_A64_EL1_0_7	GENMASK(23, 16)
 #define PMCR1_COUNT_A64_EL0_8_9	GENMASK(41, 40)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index cea80afd1253..d6d4ff6da862 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -120,6 +120,8 @@ enum m1_pmu_events {
 	 */
 	M1_PMU_CFG_COUNT_USER					= BIT(8),
 	M1_PMU_CFG_COUNT_KERNEL					= BIT(9),
+	M1_PMU_CFG_COUNT_HOST					= BIT(10),
+	M1_PMU_CFG_COUNT_GUEST					= BIT(11),
 };
 
 /*
@@ -328,7 +330,7 @@ static void m1_pmu_disable_counter_interrupt(unsigned int index)
 }
 
 static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
-					    bool kernel)
+					    bool kernel, bool host)
 {
 	u64 clear, set, user_bit, kernel_bit;
 
@@ -356,7 +358,10 @@ static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
 	else
 		clear |= kernel_bit;
 
-	sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+	if (host)
+		sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+	else if (is_kernel_in_hyp_mode())
+		sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL12, clear, set);
 }
 
 static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
@@ -391,10 +396,13 @@ static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
 static void m1_pmu_configure_counter(unsigned int index, unsigned long config_base)
 {
 	bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL;
+	bool guest = config_base & M1_PMU_CFG_COUNT_GUEST;
+	bool host = config_base & M1_PMU_CFG_COUNT_HOST;
 	bool user = config_base & M1_PMU_CFG_COUNT_USER;
 	u8 evt = config_base & M1_PMU_CFG_EVENT;
 
-	__m1_pmu_configure_event_filter(index, user, kernel);
+	__m1_pmu_configure_event_filter(index, user && host, kernel && host, true);
+	__m1_pmu_configure_event_filter(index, user && guest, kernel && guest, false);
 	__m1_pmu_configure_eventsel(index, evt);
 }
 
@@ -570,7 +578,7 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
 {
 	unsigned long config_base = 0;
 
-	if (!attr->exclude_guest) {
+	if (!attr->exclude_guest && !is_kernel_in_hyp_mode()) {
 		pr_debug("ARM performance counters do not support mode exclusion\n");
 		return -EOPNOTSUPP;
 	}
@@ -578,6 +586,10 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
 		config_base |= M1_PMU_CFG_COUNT_KERNEL;
 	if (!attr->exclude_user)
 		config_base |= M1_PMU_CFG_COUNT_USER;
+	if (!attr->exclude_host)
+		config_base |= M1_PMU_CFG_COUNT_HOST;
+	if (!attr->exclude_guest)
+		config_base |= M1_PMU_CFG_COUNT_GUEST;
 
 	event->config_base = config_base;
 
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:28 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:28 -0800
Subject: [PATCH v3 01/14] drivers/perf: apple_m1: Refactor event select/filter configuration
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-2-oliver.upton@linux.dev>

Supporting guest mode events will necessitate programming two event
filters. Prepare by splitting up the programming of the event selector +
event filter into separate headers.

Opportunistically replace RMW patterns with sysreg_clear_set_s().

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 drivers/perf/apple_m1_cpu_pmu.c | 52 ++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 06fd317529fc..cea80afd1253 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -327,11 +327,10 @@ static void m1_pmu_disable_counter_interrupt(unsigned int index)
 	__m1_pmu_enable_counter_interrupt(index, false);
 }
 
-static void m1_pmu_configure_counter(unsigned int index, u8 event,
-				     bool user, bool kernel)
+static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
+					    bool kernel)
 {
-	u64 val, user_bit, kernel_bit;
-	int shift;
+	u64 clear, set, user_bit, kernel_bit;
 
 	switch (index) {
 	case 0 ... 7:
@@ -346,19 +345,24 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
 		BUG();
 	}
 
-	val = read_sysreg_s(SYS_IMP_APL_PMCR1_EL1);
-
+	clear = set = 0;
 	if (user)
-		val |= user_bit;
+		set |= user_bit;
 	else
-		val &= ~user_bit;
+		clear |= user_bit;
 
 	if (kernel)
-		val |= kernel_bit;
+		set |= kernel_bit;
 	else
-		val &= ~kernel_bit;
+		clear |= kernel_bit;
 
-	write_sysreg_s(val, SYS_IMP_APL_PMCR1_EL1);
+	sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+}
+
+static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
+{
+	u64 clear = 0, set = 0;
+	int shift;
 
 	/*
 	 * Counters 0 and 1 have fixed events. For anything else,
@@ -371,21 +375,29 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
 		break;
 	case 2 ... 5:
 		shift = (index - 2) * 8;
-		val = read_sysreg_s(SYS_IMP_APL_PMESR0_EL1);
-		val &= ~((u64)0xff << shift);
-		val |= (u64)event << shift;
-		write_sysreg_s(val, SYS_IMP_APL_PMESR0_EL1);
+		clear |= (u64)0xff << shift;
+		set |= (u64)event << shift;
+		sysreg_clear_set_s(SYS_IMP_APL_PMESR0_EL1, clear, set);
 		break;
 	case 6 ... 9:
 		shift = (index - 6) * 8;
-		val = read_sysreg_s(SYS_IMP_APL_PMESR1_EL1);
-		val &= ~((u64)0xff << shift);
-		val |= (u64)event << shift;
-		write_sysreg_s(val, SYS_IMP_APL_PMESR1_EL1);
+		clear |= (u64)0xff << shift;
+		set |= (u64)event << shift;
+		sysreg_clear_set_s(SYS_IMP_APL_PMESR1_EL1, clear, set);
 		break;
 	}
 }
 
+static void m1_pmu_configure_counter(unsigned int index, unsigned long config_base)
+{
+	bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL;
+	bool user = config_base & M1_PMU_CFG_COUNT_USER;
+	u8 evt = config_base & M1_PMU_CFG_EVENT;
+
+	__m1_pmu_configure_event_filter(index, user, kernel);
+	__m1_pmu_configure_eventsel(index, evt);
+}
+
 /* arm_pmu backend */
 static void m1_pmu_enable_event(struct perf_event *event)
 {
@@ -400,7 +412,7 @@ static void m1_pmu_enable_event(struct perf_event *event)
 	m1_pmu_disable_counter(event->hw.idx);
 	isb();
 
-	m1_pmu_configure_counter(event->hw.idx, evt, user, kernel);
+	m1_pmu_configure_counter(event->hw.idx, event->hw.config_base);
 	m1_pmu_enable_counter(event->hw.idx);
 	m1_pmu_enable_counter_interrupt(event->hw.idx);
 	isb();
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:27 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:27 -0800
Subject: [PATCH v3 00/14] KVM: arm64: FEAT_PMUv3 on Apple hardware
Message-ID: <20250305202641.428114-1-oliver.upton@linux.dev>

Hopefully close to the last spin, this time addressing Marc's comments
on v2.

Full details found in the v1 cover letter.

v1: https://lore.kernel.org/kvmarm/20241217212048.3709204-1-oliver.upton at linux.dev/
v2: https://lore.kernel.org/kvmarm/20250203183111.191519-1-oliver.upton at linux.dev/

v2 -> v3:
 - Reorder and restructure patches to include map_pmuv3_event()
   definition w/ KVM usage.
 - Disallow events that lack a valid PMUv3 -> HW mapping
 - Various minor fixes/typos

Oliver Upton (14):
  drivers/perf: apple_m1: Refactor event select/filter configuration
  drivers/perf: apple_m1: Support host/guest event filtering
  KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
  KVM: arm64: Always support SW_INCR PMU event
  KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
  KVM: arm64: Drop kvm_arm_pmu_available static key
  KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
  KVM: arm64: Move PMUVer filtering into KVM code
  KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
  KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
  KVM: arm64: Remap PMUv3 events onto hardware
  drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
  KVM: arm64: Provide 1 event counter on IMPDEF hardware
  arm64: Enable IMP DEF PMUv3 traps on Apple M*

 arch/arm64/include/asm/apple_m1_pmu.h   |   1 +
 arch/arm64/include/asm/cpucaps.h        |   2 +
 arch/arm64/include/asm/cpufeature.h     |  28 +----
 arch/arm64/kernel/cpu_errata.c          |  44 ++++++++
 arch/arm64/kernel/cpufeature.c          |  28 +++++
 arch/arm64/kernel/image-vars.h          |   5 -
 arch/arm64/kvm/arm.c                    |   4 +-
 arch/arm64/kvm/hyp/include/hyp/switch.h |   4 +-
 arch/arm64/kvm/hyp/vhe/switch.c         |  22 ++++
 arch/arm64/kvm/pmu-emul.c               | 138 +++++++++++++++++-------
 arch/arm64/kvm/pmu.c                    |  10 +-
 arch/arm64/tools/cpucaps                |   2 +
 drivers/perf/apple_m1_cpu_pmu.c         | 101 +++++++++++++----
 include/kvm/arm_pmu.h                   |  12 +--
 include/linux/perf/arm_pmu.h            |   4 +
 15 files changed, 301 insertions(+), 104 deletions(-)


base-commit: 0ad2507d5d93f39619fc42372c347d6006b64319
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:30 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:30 -0800
Subject: [PATCH v3 03/14] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-4-oliver.upton@linux.dev>

The PMUv3 driver populates a couple of bitmaps with the values of
PMCEID{0,1}, from which the guest's PMCEID{0,1} can be derived. This
is particularly convenient when virtualizing PMUv3 on IMP DEF hardware,
as reading the nonexistent PMCEID registers leads to a rather unpleasant
UNDEF.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c | 47 ++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 6c5950b9ceac..104672a0c5a2 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -842,8 +842,42 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
 	return pmu;
 }
 
+static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
+{
+	u32 hi[2], lo[2];
+
+	bitmap_to_arr32(lo, pmu->pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
+	bitmap_to_arr32(hi, pmu->pmceid_ext_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
+
+	return ((u64)hi[pmceid1] << 32) | lo[pmceid1];
+}
+
+static u64 compute_pmceid0(struct arm_pmu *pmu)
+{
+	u64 val = __compute_pmceid(pmu, 0);
+
+	/* always support CHAIN */
+	val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
+	return val;
+}
+
+static u64 compute_pmceid1(struct arm_pmu *pmu)
+{
+	u64 val = __compute_pmceid(pmu, 1);
+
+	/*
+	 * Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
+	 * as RAZ
+	 */
+	val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
+		 BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
+		 BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
+	return val;
+}
+
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
 {
+	struct arm_pmu *cpu_pmu = vcpu->kvm->arch.arm_pmu;
 	unsigned long *bmap = vcpu->kvm->arch.pmu_filter;
 	u64 val, mask = 0;
 	int base, i, nr_events;
@@ -852,19 +886,10 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
 		return 0;
 
 	if (!pmceid1) {
-		val = read_sysreg(pmceid0_el0);
-		/* always support CHAIN */
-		val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
+		val = compute_pmceid0(cpu_pmu);
 		base = 0;
 	} else {
-		val = read_sysreg(pmceid1_el0);
-		/*
-		 * Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
-		 * as RAZ
-		 */
-		val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
-			 BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
-			 BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
+		val = compute_pmceid1(cpu_pmu);
 		base = 32;
 	}
 
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:31 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:31 -0800
Subject: [PATCH v3 04/14] KVM: arm64: Always support SW_INCR PMU event
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-5-oliver.upton@linux.dev>

Support for SW_INCR is unconditional, as KVM traps accesses to
PMSWINC_EL0 and emulates the intended event increment. While it is
expected that ~all PMUv3 implementations already advertise this event,
non-PMUv3 hardware may not.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 104672a0c5a2..62349b670cf9 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -856,6 +856,8 @@ static u64 compute_pmceid0(struct arm_pmu *pmu)
 {
 	u64 val = __compute_pmceid(pmu, 0);
 
+	/* always support SW_INCR */
+	val |= BIT(ARMV8_PMUV3_PERFCTR_SW_INCR);
 	/* always support CHAIN */
 	val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
 	return val;
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:32 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:32 -0800
Subject: [PATCH v3 05/14] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-6-oliver.upton@linux.dev>

KVM is about to learn some new tricks to virtualize PMUv3 on IMPDEF
hardware. As part of that, we now need to differentiate host support
from guest support for PMUv3.

Add a cpucap to determine if an architectural PMUv3 is present to guard
host usage of PMUv3 controls.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/include/asm/cpucaps.h        |  2 ++
 arch/arm64/include/asm/cpufeature.h     |  5 +++++
 arch/arm64/kernel/cpufeature.c          | 28 +++++++++++++++++++++++++
 arch/arm64/kvm/hyp/include/hyp/switch.h |  4 ++--
 arch/arm64/kvm/pmu.c                    | 10 ++++-----
 arch/arm64/tools/cpucaps                |  1 +
 include/kvm/arm_pmu.h                   |  2 +-
 7 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 0b5ca6e0eb09..9d769291a306 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -71,6 +71,8 @@ cpucap_is_possible(const unsigned int cap)
 		 * KVM MPAM support doesn't rely on the host kernel supporting MPAM.
 		*/
 		return true;
+	case ARM64_HAS_PMUV3:
+		return IS_ENABLED(CONFIG_HW_PERF_EVENTS);
 	}
 
 	return true;
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..0eff048848b8 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
 	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
 }
 
+static inline bool system_supports_pmuv3(void)
+{
+	return cpus_have_final_cap(ARM64_HAS_PMUV3);
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d561cf3b8ac7..ce2c1e688d8c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1898,6 +1898,26 @@ static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
 }
 #endif
 
+static bool has_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+	unsigned int pmuver;
+
+	/*
+	 * PMUVer follows the standard ID scheme for an unsigned field with the
+	 * exception of 0xF (IMP_DEF) which is treated specially and implies
+	 * FEAT_PMUv3 is not implemented.
+	 *
+	 * See DDI0487L.a D24.1.3.2 for more details.
+	 */
+	pmuver = cpuid_feature_extract_unsigned_field(dfr0,
+						      ID_AA64DFR0_EL1_PMUVer_SHIFT);
+	if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+		return false;
+
+	return pmuver >= ID_AA64DFR0_EL1_PMUVer_IMP;
+}
+
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 #define KPTI_NG_TEMP_VA		(-(1UL << PMD_SHIFT))
 
@@ -2998,6 +3018,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.matches = has_cpuid_feature,
 		ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP)
 	},
+#endif
+#ifdef CONFIG_HW_PERF_EVENTS
+	{
+		.desc = "PMUv3",
+		.capability = ARM64_HAS_PMUV3,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_pmuv3,
+	},
 #endif
 	{},
 };
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 23bbe28eaaf9..b741ea6aefa5 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -244,7 +244,7 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
 	 * counter, which could make a PMXEVCNTR_EL0 access UNDEF at
 	 * EL1 instead of being trapped to EL2.
 	 */
-	if (kvm_arm_support_pmu_v3()) {
+	if (system_supports_pmuv3()) {
 		struct kvm_cpu_context *hctxt;
 
 		write_sysreg(0, pmselr_el0);
@@ -281,7 +281,7 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
 	write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
 
 	write_sysreg(0, hstr_el2);
-	if (kvm_arm_support_pmu_v3()) {
+	if (system_supports_pmuv3()) {
 		struct kvm_cpu_context *hctxt;
 
 		hctxt = host_data_ptr(host_ctxt);
diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
index 0b3adf3e17b4..6b48a3d16d0d 100644
--- a/arch/arm64/kvm/pmu.c
+++ b/arch/arm64/kvm/pmu.c
@@ -41,7 +41,7 @@ void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr)
 {
 	struct kvm_pmu_events *pmu = kvm_get_pmu_events();
 
-	if (!kvm_arm_support_pmu_v3() || !kvm_pmu_switch_needed(attr))
+	if (!system_supports_pmuv3() || !kvm_pmu_switch_needed(attr))
 		return;
 
 	if (!attr->exclude_host)
@@ -57,7 +57,7 @@ void kvm_clr_pmu_events(u64 clr)
 {
 	struct kvm_pmu_events *pmu = kvm_get_pmu_events();
 
-	if (!kvm_arm_support_pmu_v3())
+	if (!system_supports_pmuv3())
 		return;
 
 	pmu->events_host &= ~clr;
@@ -133,7 +133,7 @@ void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
 	struct kvm_pmu_events *pmu;
 	u64 events_guest, events_host;
 
-	if (!kvm_arm_support_pmu_v3() || !has_vhe())
+	if (!system_supports_pmuv3() || !has_vhe())
 		return;
 
 	preempt_disable();
@@ -154,7 +154,7 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu)
 	struct kvm_pmu_events *pmu;
 	u64 events_guest, events_host;
 
-	if (!kvm_arm_support_pmu_v3() || !has_vhe())
+	if (!system_supports_pmuv3() || !has_vhe())
 		return;
 
 	pmu = kvm_get_pmu_events();
@@ -180,7 +180,7 @@ bool kvm_set_pmuserenr(u64 val)
 	struct kvm_cpu_context *hctxt;
 	struct kvm_vcpu *vcpu;
 
-	if (!kvm_arm_support_pmu_v3() || !has_vhe())
+	if (!system_supports_pmuv3() || !has_vhe())
 		return false;
 
 	vcpu = kvm_get_running_vcpu();
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1e65f2fb45bd..ee4316cb3690 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -45,6 +45,7 @@ HAS_LSE_ATOMICS
 HAS_MOPS
 HAS_NESTED_VIRT
 HAS_PAN
+HAS_PMUV3
 HAS_S1PIE
 HAS_S1POE
 HAS_RAS_EXTN
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 147bd3ee4f7b..3a8edd78240f 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -86,7 +86,7 @@ void kvm_vcpu_pmu_resync_el0(void);
  */
 #define kvm_pmu_update_vcpu_events(vcpu)				\
 	do {								\
-		if (!has_vhe() && kvm_arm_support_pmu_v3())		\
+		if (!has_vhe() && system_supports_pmuv3())		\
 			vcpu->arch.pmu.events = *kvm_get_pmu_events();	\
 	} while (0)
 
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:33 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:33 -0800
Subject: [PATCH v3 06/14] KVM: arm64: Drop kvm_arm_pmu_available static key
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-7-oliver.upton@linux.dev>

With the PMUv3 cpucap, kvm_arm_pmu_available is no longer used in the
hot path of guest entry/exit. On top of that, guest support for PMUv3
may not correlate with host support for the feature, e.g. on IMPDEF
hardware.

Throw out the static key and just inspect the list of PMUs to determine
if PMUv3 is supported for KVM guests.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kernel/image-vars.h |  5 -----
 arch/arm64/kvm/arm.c           |  4 ++--
 arch/arm64/kvm/pmu-emul.c      | 11 ++++++-----
 include/kvm/arm_pmu.h          | 10 ++--------
 4 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index ef3a69cc398e..e705c64138ce 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -112,11 +112,6 @@ KVM_NVHE_ALIAS(broken_cntvoff_key);
 KVM_NVHE_ALIAS(__start___kvm_ex_table);
 KVM_NVHE_ALIAS(__stop___kvm_ex_table);
 
-/* PMU available static key */
-#ifdef CONFIG_HW_PERF_EVENTS
-KVM_NVHE_ALIAS(kvm_arm_pmu_available);
-#endif
-
 /* Position-independent library routines */
 KVM_NVHE_ALIAS_HYP(clear_page, __pi_clear_page);
 KVM_NVHE_ALIAS_HYP(copy_page, __pi_copy_page);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b8e55a441282..dc27d4eb503a 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -366,7 +366,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 		r = get_num_wrps();
 		break;
 	case KVM_CAP_ARM_PMU_V3:
-		r = kvm_arm_support_pmu_v3();
+		r = kvm_supports_guest_pmuv3();
 		break;
 	case KVM_CAP_ARM_INJECT_SERROR_ESR:
 		r = cpus_have_final_cap(ARM64_HAS_RAS_EXTN);
@@ -1388,7 +1388,7 @@ static unsigned long system_supported_vcpu_features(void)
 	if (!cpus_have_final_cap(ARM64_HAS_32BIT_EL1))
 		clear_bit(KVM_ARM_VCPU_EL1_32BIT, &features);
 
-	if (!kvm_arm_support_pmu_v3())
+	if (!kvm_supports_guest_pmuv3())
 		clear_bit(KVM_ARM_VCPU_PMU_V3, &features);
 
 	if (!system_supports_sve())
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 62349b670cf9..120f48136a0f 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -17,8 +17,6 @@
 
 #define PERF_ATTR_CFG1_COUNTER_64BIT	BIT(0)
 
-DEFINE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
-
 static LIST_HEAD(arm_pmus);
 static DEFINE_MUTEX(arm_pmus_lock);
 
@@ -26,6 +24,12 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc);
 static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc);
 static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc);
 
+bool kvm_supports_guest_pmuv3(void)
+{
+	guard(mutex)(&arm_pmus_lock);
+	return !list_empty(&arm_pmus);
+}
+
 static struct kvm_vcpu *kvm_pmc_to_vcpu(const struct kvm_pmc *pmc)
 {
 	return container_of(pmc, struct kvm_vcpu, arch.pmu.pmc[pmc->idx]);
@@ -795,9 +799,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
 	entry->arm_pmu = pmu;
 	list_add_tail(&entry->entry, &arm_pmus);
 
-	if (list_is_singular(&arm_pmus))
-		static_branch_enable(&kvm_arm_pmu_available);
-
 out_unlock:
 	mutex_unlock(&arm_pmus_lock);
 }
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 3a8edd78240f..58fc7f932b3f 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -37,13 +37,7 @@ struct arm_pmu_entry {
 	struct arm_pmu *arm_pmu;
 };
 
-DECLARE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
-
-static __always_inline bool kvm_arm_support_pmu_v3(void)
-{
-	return static_branch_likely(&kvm_arm_pmu_available);
-}
-
+bool kvm_supports_guest_pmuv3(void);
 #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
@@ -102,7 +96,7 @@ void kvm_pmu_nested_transition(struct kvm_vcpu *vcpu);
 struct kvm_pmu {
 };
 
-static inline bool kvm_arm_support_pmu_v3(void)
+static inline bool kvm_supports_guest_pmuv3(void)
 {
 	return false;
 }
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:34 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:34 -0800
Subject: [PATCH v3 07/14] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-8-oliver.upton@linux.dev>

Get rid of some goto label patterns by using guard() to drop the
arm_pmus_lock when returning from a function.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 120f48136a0f..fee3d0003d54 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -790,26 +790,23 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
 	if (!pmuv3_implemented(kvm_arm_pmu_get_pmuver_limit()))
 		return;
 
-	mutex_lock(&arm_pmus_lock);
+	guard(mutex)(&arm_pmus_lock);
 
 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		goto out_unlock;
+		return;
 
 	entry->arm_pmu = pmu;
 	list_add_tail(&entry->entry, &arm_pmus);
-
-out_unlock:
-	mutex_unlock(&arm_pmus_lock);
 }
 
 static struct arm_pmu *kvm_pmu_probe_armpmu(void)
 {
-	struct arm_pmu *tmp, *pmu = NULL;
 	struct arm_pmu_entry *entry;
+	struct arm_pmu *pmu;
 	int cpu;
 
-	mutex_lock(&arm_pmus_lock);
+	guard(mutex)(&arm_pmus_lock);
 
 	/*
 	 * It is safe to use a stale cpu to iterate the list of PMUs so long as
@@ -830,17 +827,13 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
 	 */
 	cpu = raw_smp_processor_id();
 	list_for_each_entry(entry, &arm_pmus, entry) {
-		tmp = entry->arm_pmu;
+		pmu = entry->arm_pmu;
 
-		if (cpumask_test_cpu(cpu, &tmp->supported_cpus)) {
-			pmu = tmp;
-			break;
-		}
+		if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
+			return pmu;
 	}
 
-	mutex_unlock(&arm_pmus_lock);
-
-	return pmu;
+	return NULL;
 }
 
 static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:35 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:35 -0800
Subject: [PATCH v3 08/14] KVM: arm64: Move PMUVer filtering into KVM code
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-9-oliver.upton@linux.dev>

The supported guest PMU version on a particular platform is ultimately a
KVM decision. Move PMUVer filtering into KVM code.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/include/asm/cpufeature.h | 23 -----------------------
 arch/arm64/kvm/pmu-emul.c           | 15 +++++++++------
 2 files changed, 9 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 0eff048848b8..c4326f1cb917 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -525,29 +525,6 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
 	return cpuid_feature_extract_unsigned_field_width(features, field, 4);
 }
 
-/*
- * Fields that identify the version of the Performance Monitors Extension do
- * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
- * "Alternative ID scheme used for the Performance Monitors Extension version".
- */
-static inline u64 __attribute_const__
-cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
-{
-	u64 val = cpuid_feature_extract_unsigned_field(features, field);
-	u64 mask = GENMASK_ULL(field + 3, field);
-
-	/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
-	if (val == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
-		val = 0;
-
-	if (val > cap) {
-		features &= ~mask;
-		features |= (cap << field) & mask;
-	}
-
-	return features;
-}
-
 static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
 {
 	return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index fee3d0003d54..0a2023aabe18 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1226,13 +1226,16 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 
 u8 kvm_arm_pmu_get_pmuver_limit(void)
 {
-	u64 tmp;
+	unsigned int pmuver;
 
-	tmp = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
-	tmp = cpuid_feature_cap_perfmon_field(tmp,
-					      ID_AA64DFR0_EL1_PMUVer_SHIFT,
-					      ID_AA64DFR0_EL1_PMUVer_V3P5);
-	return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), tmp);
+	pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer,
+			       read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
+
+	/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+	if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+		return 0;
+
+	return min(pmuver, ID_AA64DFR0_EL1_PMUVer_V3P5);
 }
 
 /**
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:36 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:36 -0800
Subject: [PATCH v3 09/14] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-10-oliver.upton@linux.dev>

Apple M* CPUs provide an IMPDEF trap for PMUv3 sysregs, where ESR_EL2.EC
is a reserved value (0x3F) and a sysreg-like ISS is reported in
AFSR1_EL2.

Compute a synthetic ESR for these PMUv3 traps, giving the illusion of
something architectural to the rest of KVM.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/hyp/vhe/switch.c | 22 ++++++++++++++++++++++
 arch/arm64/tools/cpucaps        |  1 +
 2 files changed, 23 insertions(+)

diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 647737d6e8d0..731a0378ed13 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -527,6 +527,25 @@ static bool kvm_hyp_handle_sysreg_vhe(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return kvm_hyp_handle_sysreg(vcpu, exit_code);
 }
 
+static bool kvm_hyp_handle_impdef(struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+	u64 iss;
+
+	if (!cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+		return false;
+
+	/*
+	 * Compute a synthetic ESR for a sysreg trap. Conveniently, AFSR1_EL2
+	 * is populated with a correct ISS for a sysreg trap. These fruity
+	 * parts are 64bit only, so unconditionally set IL.
+	 */
+	iss = ESR_ELx_ISS(read_sysreg_s(SYS_AFSR1_EL2));
+	vcpu->arch.fault.esr_el2 = FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SYS64) |
+				   FIELD_PREP(ESR_ELx_ISS_MASK, iss) |
+				   ESR_ELx_IL;
+	return false;
+}
+
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
@@ -538,6 +557,9 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_WATCHPT_LOW]	= kvm_hyp_handle_watchpt_low,
 	[ESR_ELx_EC_ERET]		= kvm_hyp_handle_eret,
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
+
+	/* Apple shenanigans */
+	[0x3F]				= kvm_hyp_handle_impdef,
 };
 
 static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index ee4316cb3690..772c1b008e43 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -105,6 +105,7 @@ WORKAROUND_CAVIUM_TX2_219_TVM
 WORKAROUND_CLEAN_CACHE
 WORKAROUND_DEVICE_LOAD_ACQUIRE
 WORKAROUND_NVIDIA_CARMEL_CNP
+WORKAROUND_PMUV3_IMPDEF_TRAPS
 WORKAROUND_QCOM_FALKOR_E1003
 WORKAROUND_QCOM_ORYON_CNTVOFF
 WORKAROUND_REPEAT_TLBI
-- 
2.39.5



From oliver.upton at linux.dev  Wed Mar  5 12:26:37 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 12:26:37 -0800
Subject: [PATCH v3 10/14] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <20250305202641.428114-11-oliver.upton@linux.dev>

Advertise a baseline PMUv3 implementation when running on hardware with
IMPDEF traps of the PMUv3 sysregs.

Tested-by: Janne Grunau <j at jannau.net>
Signed-off-by: Oliver Upton <oliver.upton at linux.dev>
---
 arch/arm64/kvm/pmu-emul.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 0a2023aabe18..38d9490c17fd 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1231,7 +1231,17 @@ u8 kvm_arm_pmu_get_pmuver_limit(void)
 	pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer,
 			       read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
 
-	/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+	/*
+	 * Spoof a barebones PMUv3 implementation if the system supports IMPDEF
+	 * traps of the PMUv3 sysregs
+	 */
+	if (cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+		return ID_AA64DFR0_EL1_PMUVer_IMP;
+
+	/*
+	 * Otherwise, treat IMPLEMENTATION DEFINED functionality as
+	 * unimplemented
+	 */
 	if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
 		return 0;
 
-- 
2.39.5



From kw at linux.com  Wed Mar  5 13:57:31 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Thu, 6 Mar 2025 06:57:31 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250305190955.GK847772@rocinante>
References: <20250304171154.njoygsvfd567pb66@thinkpad>
 <20250305173826.GA303920@bhelgaas>
 <20250305182833.cgrwbrcwzjscxmku@thinkpad>
 <20250305190955.GK847772@rocinante>
Message-ID: <20250305215731.GL847772@rocinante>

> > > > Even though debugfs_init() failure is not supposed to fail the probe(),
> > > > dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> > > > failure would be canolically correct IMO.
> > > 
> > > I'm not sure about this.  What's the requirement to propagate
> > > devm_kzalloc() failures?  I think devres will free any allocs that
> > > were successful regardless.
> > > 
> > > IIUC, we resolved the Gray Hawk Single issue by changing
> > > dwc_pcie_rasdes_debugfs_init() to return success without doing
> > > anything when there's no RAS DES Capability.
> > > 
> > > But dwc_pcie_debugfs_init() can still return failure, and that still
> > > causes dw_pcie_ep_init_registers() to fail, which breaks the "don't
> > > propagate debugfs issues upstream" rule:
> > > 
> > >   int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> > >   {
> > >           ...
> > >           ret = dwc_pcie_debugfs_init(pci);
> > >           if (ret)
> > >                   goto err_remove_edma;
> > > 
> > >           return 0;
> > > 
> > >   err_remove_edma:
> > >           dw_pcie_edma_remove(pci);
> > > 
> > >           return ret;
> > >   }
> > > 
> > > We can say that kzalloc() failure should "never" happen, and therefore
> > > it's OK to fail the driver probe if it happens, but that doesn't seem
> > > like a strong argument for breaking the "don't propagate debugfs
> > > issues" rule.  And someday there may be other kinds of failures from
> > > dwc_pcie_debugfs_init().
> > > 
> > 
> > Fine with me. I was not too sure about propagating failure either.
> 
> What if we do this?
> 
> diff --git i/drivers/pci/controller/dwc/pcie-designware-debugfs.c w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> index 586a9d107434..fddf71f014c4 100644
> --- i/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> +++ w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> @@ -162,7 +162,7 @@ void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
>  	debugfs_remove_recursive(pci->debugfs->debug_dir);
>  }
> 
> -int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> +void dwc_pcie_debugfs_init(struct dw_pcie *pci)
>  {
>  	char dirname[DWC_DEBUGFS_BUF_MAX];
>  	struct device *dev = pci->dev;
> @@ -174,17 +174,15 @@ int dwc_pcie_debugfs_init(struct dw_pcie *pci)
>  	snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
>  	dir = debugfs_create_dir(dirname, NULL);
>  	debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> -	if (!debugfs)
> -		return -ENOMEM;
> +	if (!debugfs) {
> +		dev_err(dev, "failed to allocate memory for debugfs\n");
> +		return;
> +	}
> 
>  	debugfs->debug_dir = dir;
>  	pci->debugfs = debugfs;
>  	err = dwc_pcie_rasdes_debugfs_init(pci, dir);
> -	if (err) {
> -		dev_err(dev, "failed to initialize RAS DES debugfs, err=%d\n",
> -			err);
> -		return err;
> -	}
> -
> -	return 0;
> +	if (err)
> +		dev_warn(dev, "failed to initialize RAS DES debugfs, err=%d",
> +			 err);
>  }
> diff --git i/drivers/pci/controller/dwc/pcie-designware-ep.c w/drivers/pci/controller/dwc/pcie-designware-ep.c
> index c6e76a07c2c9..11ff292ca87d 100644
> --- i/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ w/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -838,9 +838,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> 
>  	dw_pcie_ep_init_non_sticky_registers(pci);
> 
> -	ret = dwc_pcie_debugfs_init(pci);
> -	if (ret)
> -		goto err_remove_edma;
> +	dwc_pcie_debugfs_init(pci);
> 
>  	return 0;
> 
> diff --git i/drivers/pci/controller/dwc/pcie-designware-host.c w/drivers/pci/controller/dwc/pcie-designware-host.c
> index 2081e8c72d12..6501fb062c70 100644
> --- i/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ w/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -548,9 +548,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	if (pp->ops->post_init)
>  		pp->ops->post_init(pp);
> 
> -	ret = dwc_pcie_debugfs_init(pci);
> -	if (ret)
> -		goto err_stop_link;
> +	dwc_pcie_debugfs_init(pci);
> 
>  	return 0;
> 
> diff --git i/drivers/pci/controller/dwc/pcie-designware.h w/drivers/pci/controller/dwc/pcie-designware.h
> index 7f9807d4e5de..dd129718fb41 100644
> --- i/drivers/pci/controller/dwc/pcie-designware.h
> +++ w/drivers/pci/controller/dwc/pcie-designware.h
> @@ -815,12 +815,11 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
>  #endif
> 
>  #ifdef CONFIG_PCIE_DW_DEBUGFS
> -int dwc_pcie_debugfs_init(struct dw_pcie *pci);
> +void dwc_pcie_debugfs_init(struct dw_pcie *pci);
>  void dwc_pcie_debugfs_deinit(struct dw_pcie *pci);
>  #else
> -static inline int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> +static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci)
>  {
> -	return 0;
>  }
>  static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
>  {
> 
> I think this would be fine, especially given the rules around debugfs and
> a quick look around Git history to see what the prefernce would be typically.

Changed dev_warn() to dev_err() per Bjorn's feedback off mailing list,
and squashed against the current code on the branch.

Thank you!

	Krzysztof


From jonas at kwiboo.se  Wed Mar  5 13:41:04 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed,  5 Mar 2025 21:41:04 +0000
Subject: [PATCH 3/3] arm64: dts: rockchip: Enable onboard eMMC on Radxa E20C
In-Reply-To: <20250305214108.1327208-1-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
Message-ID: <20250305214108.1327208-4-jonas@kwiboo.se>

The Radxa E20C may come with an onboard eMMC (8GB / 16GB / 32GB / 64GB).

Enable support for the onboard eMMC on Radxa E20C.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index a52a7924bb75..a511e2a2d4a5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -16,6 +16,7 @@ / {
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
 	aliases {
+		mmc0 = &sdhci;
 		mmc1 = &sdmmc;
 	};
 
@@ -155,6 +156,17 @@ &saradc {
 	status = "okay";
 };
 
+&sdhci {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	no-sd;
+	no-sdio;
+	non-removable;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vcc_1v8>;
+	status = "okay";
+};
+
 &sdmmc {
 	bus-width = <4>;
 	cap-mmc-highspeed;
-- 
2.48.1



From robh at kernel.org  Wed Mar  5 14:03:20 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 5 Mar 2025 16:03:20 -0600
Subject: [PATCH 1/3] dt-bindings: spmi: Add Apple SPMI controller
In-Reply-To: <20250305-spmi-v1-1-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com> <20250305-spmi-v1-1-c98f561fa99f@gmail.com>
Message-ID: <CAL_JsqJU0AqQcVNTJqrHTAu7wDP4bbLC8vPHP-XvdojuS8nDiQ@mail.gmail.com>

On Wed, Mar 5, 2025 at 2:26?PM Sasha Finkelstein via B4 Relay
<devnull+fnkl.kernel.gmail.com at kernel.org> wrote:
>
> From: Sasha Finkelstein <fnkl.kernel at gmail.com>
>
> Add bindings for the SPMI controller present on most Apple SoCs
>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
>  .../devicetree/bindings/spmi/apple,spmi.yaml       | 56 ++++++++++++++++++++++
>  MAINTAINERS                                        |  1 +
>  2 files changed, 57 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..6404af8adec52f4631200c48956f4c1695e88a39
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
> @@ -0,0 +1,56 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Apple SPMI controller
> +
> +maintainers:
> +  - Sasha Finkelstein <fnkl.kernel at gmail.com>
> +
> +description: A SPMI controller present on most Apple SoCs
> +
> +allOf:
> +  - $ref: spmi.yaml#
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - apple,t8103-spmi
> +          - apple,t6000-spmi
> +          - apple,t8112-spmi
> +      - const: apple,spmi
> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +
> +patternProperties:
> +  "pmu@[0-9a-f]$":

Typically 'pmic' is the name used here. However, you should just drop
this because spmi.yaml already defines child node structure.

With that,

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>

> +    type: object
> +
> +    description:
> +      PMIC properties, which are specific to the used SPMI PMIC device(s).
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/spmi/spmi.h>
> +
> +    spmi at 920a1300 {
> +        compatible = "apple,t6000-spmi", "apple,spmi";
> +        reg = <0x920a1300 0x100>;
> +        #address-cells = <2>;
> +        #size-cells = <0>;
> +
> +        pmu at f {
> +            reg = <0xf SPMI_USID>;
> +            /* PMIC-specific properties */
> +        };
> +    };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8e0736dc2ee0e33544fa373a4978b7dae18c040c..271ff8110df83c2d4fe7fbbfffc0a72259460bc5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2236,6 +2236,7 @@ F:        Documentation/devicetree/bindings/pci/apple,pcie.yaml
>  F:     Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
>  F:     Documentation/devicetree/bindings/power/apple*
>  F:     Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
> +F:     Documentation/devicetree/bindings/spmi/apple,spmi.yaml
>  F:     Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
>  F:     arch/arm64/boot/dts/apple/
>  F:     drivers/bluetooth/hci_bcm4377.c
>
> --
> 2.48.1
>
>


From alexandre.belloni at bootlin.com  Wed Mar  5 14:10:01 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Wed, 5 Mar 2025 23:10:01 +0100
Subject: [PATCH v2 00/16] a few rtc driver cleanups
In-Reply-To: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
References: <20250304-rtc-cleanups-v2-0-d4689a71668c@linaro.org>
Message-ID: <174121255394.1152777.11765502116426784970.b4-ty@bootlin.com>

On Tue, 04 Mar 2025 17:05:28 +0000, Andr? Draszik wrote:
> While looking at RTC, I noticed that various drivers are keeping
> pointers to data that they're not using themselves throughout their
> lifetime.
> 
> So I took the liberty to drop these pointers and this series is the
> result.
> 
> [...]

Applied, thanks!

[01/16] rtc: max77686: drop needless struct max77686_rtc_info::rtc member
        https://git.kernel.org/abelloni/c/6c9405fd2581
[02/16] rtc: s5m: drop needless struct s5m_rtc_info::i2c member
        https://git.kernel.org/abelloni/c/afe5f9f94d11
[03/16] rtc: aspeed: drop needless struct aspeed_rtc::rtc_dev member
        https://git.kernel.org/abelloni/c/d19111dff9c2
[04/16] rtc: ds2404: drop needless struct ds2404::rtc member
        https://git.kernel.org/abelloni/c/1b625aaf335a
[05/16] rtc: ep93xx: drop needless struct ep93xx_rtc::rtc member
        https://git.kernel.org/abelloni/c/5d0ad519f503
[06/16] rtc: ftrtc010: drop needless struct ftrtc010_rtc::rtc_dev member
        https://git.kernel.org/abelloni/c/a55d44807b63
[07/16] rtc: m48t86: drop needless struct m48t86_rtc_info::rtc member
        https://git.kernel.org/abelloni/c/013df5bdf8b4
[08/16] rtc: meson: drop needless struct meson_rtc::rtc member
        https://git.kernel.org/abelloni/c/a0470062748f
[09/16] rtc: meson-vrtc: drop needless struct meson_vrtc_data::rtc member
        https://git.kernel.org/abelloni/c/38c7aaeab8b8
[10/16] rtc: pl030: drop needless struct pl030_rtc::rtc member
        https://git.kernel.org/abelloni/c/3d5d0fe1cb82
[11/16] rtc: rx8581: drop needless struct rx8581
        https://git.kernel.org/abelloni/c/3b87c6872aed
[12/16] rtc: s35390a: drop needless struct s35390a::rtc member
        https://git.kernel.org/abelloni/c/cd2a7052482e
[13/16] rtc: sd2405al: drop needless struct sd2405al::rtc member
        https://git.kernel.org/abelloni/c/d94bc2bbf8d9
[14/16] rtc: sd3078: drop needless struct sd3078
        https://git.kernel.org/abelloni/c/6158c6b82444
[15/16] rtc: max77686: use dev_err_probe() where appropriate
        https://git.kernel.org/abelloni/c/e6403ae59ce1
[16/16] rtc: s5m: convert to dev_err_probe() where appropriate
        https://git.kernel.org/abelloni/c/0c57c2e72c5d

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From sboyd at kernel.org  Wed Mar  5 14:11:05 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Wed, 05 Mar 2025 14:11:05 -0800
Subject: [PATCH 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250305-spmi-v1-2-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com> <20250305-spmi-v1-2-c98f561fa99f@gmail.com>
Message-ID: <f17372963b92074144b07d34f3e91ba7.sboyd@kernel.org>

Quoting Sasha Finkelstein via B4 Relay (2025-03-05 12:26:40)
> From: Jean-Francois Bortolotti <jeff at borto.fr>
> 

Please write some commit text explaining why this driver is important to
review. Maybe it's necessary for something to work?

> diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..194fa5dd7c2c6fc4ecfbee0db7930b0c73b02550
> --- /dev/null
> +++ b/drivers/spmi/spmi-apple-controller.c
> @@ -0,0 +1,176 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Apple SoC SPMI device driver
> + *
> + * Copyright The Asahi Linux Contributors
> + *
> + * Inspired by:
> + *             OpenBSD support Copyright (c) 2021 Mark Kettenis <kettenis at openbsd.org>
> + *             Correllium support Copyright (C) 2021 Corellium LLC
> + *             hisi-spmi-controller.c
> + *             spmi-pmic-ard.c Copyright (c) 2021, The Linux Foundation.

spmi-pmic-arb?

> + */
> +
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>

Are these includes used? I think you need mod_devicetable.h

> +#include <linux/platform_device.h>
> +#include <linux/spmi.h>
> +
> +/* SPMI Controller Registers */
> +#define SPMI_STATUS_REG 0
> +#define SPMI_CMD_REG 0x4
> +#define SPMI_RSP_REG 0x8
> +
> +#define SPMI_RX_FIFO_EMPTY BIT(24)
> +
> +#define REG_POLL_INTERVAL 10000
> +#define REG_POLL_TIMEOUT (REG_POLL_INTERVAL * 5)
> +
> +struct apple_spmi {
> +       void __iomem *regs;
> +};
> +
> +#define poll_reg(spmi, reg, val, cond) \
> +       readl_relaxed_poll_timeout((spmi)->regs + (reg), (val), (cond), \
> +                                  REG_POLL_INTERVAL, REG_POLL_TIMEOUT)
> +
> +static inline u32 read_reg(struct apple_spmi *spmi, int offset)
> +{
> +       return readl_relaxed(spmi->regs + offset);
> +}
> +
> +static inline void write_reg(u32 value, struct apple_spmi *spmi, int offset)
> +{
> +       writel_relaxed(value, spmi->regs + offset);
> +}

I'm not a huge fan of these wrappers but OK. Why relaxed accessors?

> +
> +static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +                        u16 saddr, u8 *__buf, size_t bc)

Drop the underscore because the variable 'buf' is never used.

> +{
> +       struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +       u32 spmi_cmd = opc | sid << 8 | saddr << 16 | (bc - 1) | (1 << 15);

Can this be some function like apple_spmi_pack_cmd()? I suspect 'bc' is
byte_count? Usually we just call that 'len'.

> +       u32 rsp;
> +       u32 status;
> +       size_t len_to_read = 0;

len_to_read would imply that it is non-zero to start. Maybe 'len_read'
past tense, or decrement 'bc'.

> +       u8 i;
> +       int ret;
> +
> +       write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +
> +       /* Wait for Rx FIFO to have something */
> +       ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
> +       if (ret) {
> +               dev_err(&ctrl->dev,
> +                       "%s:Failed to wait for RX FIFO not empty\n", __func__);
> +               return ret;
> +       }

This chunk is the same. Maybe have apple_spmi_wait_for_rx_fifo() that
does everything including the error message?

> +
> +       /* Discard SPMI reply status */
> +       read_reg(spmi, SPMI_RSP_REG);
> +
> +       /* Read SPMI data reply */
> +       while (len_to_read < bc) {
> +               rsp = read_reg(spmi, SPMI_RSP_REG);
> +               i = 0;
> +               while ((len_to_read < bc) && (i < 4)) {
> +                       __buf[len_to_read++] = ((0xff << (8 * i)) & rsp) >>
> +                                              (8 * i);
> +                       i += 1;
> +               }

Is this ioread32_rep()?

> +       }
> +
> +       return 0;
> +}
> +
> +static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +                         u16 saddr, const u8 *__buf, size_t bc)
> +{
> +       struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +       u32 spmi_cmd = opc | sid << 8 | saddr << 16 | (bc - 1) | (1 << 15);
> +       u32 status;
> +       size_t i = 0, j;
> +       int ret;
> +
> +       write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +
> +       while (i < bc) {
> +               j = 0;
> +               spmi_cmd = 0;
> +               while ((j < 4) & (i < bc))
> +                       spmi_cmd |= __buf[i++] << (j++ * 8);

Is this iowrite32_rep()? Perhaps unaligned sizes have to be dealt with,
but otherwise I suspect it would be more efficient to use
iowrite32_rep() until the number of bytes is less than 4 and then do the
one extra pack.

> +
> +               write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +       }
> +
> +       /* Wait for Rx FIFO to have something */
> +       ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
> +       if (ret) {
> +               dev_err(&ctrl->dev,
> +                       "%s:Failed to wait for RX FIFO not empty\n", __func__);
                             ^
Please put a space after  ---|

> +               return ret;
> +       }
> +
> +       /* Discard */
> +       read_reg(spmi, SPMI_RSP_REG);
> +
> +       return 0;
> +}
> +
> +static int spmi_controller_probe(struct platform_device *pdev)
> +{
> +       struct apple_spmi *spmi;
> +       struct spmi_controller *ctrl;
> +       int ret;
> +
> +       ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
> +       if (IS_ERR(ctrl)) {
> +               dev_err_probe(&pdev->dev, PTR_ERR(ctrl),
> +                             "Can't allocate spmi_controller data\n");

This is likely redundant given that the spmi core API prints errors. I
could see a patch that moves to dev_err_probe() there.

> +               return -ENOMEM;
> +       }
> +
> +       spmi = spmi_controller_get_drvdata(ctrl);
> +
> +       spmi->regs = devm_platform_ioremap_resource(pdev, 0);

This already prints an error message so the dev_err_probe() later is
redundant. Please remove.

> +       if (IS_ERR(spmi->regs)) {
> +               dev_err_probe(&pdev->dev, PTR_ERR(spmi->regs),
> +                             "Can't get ioremap regs\n");
> +               return PTR_ERR(spmi->regs);
> +       }
> +
> +       ctrl->dev.of_node = of_node_get(pdev->dev.of_node);

Drop the of_node_get(), especially because it never gets put.

> +
> +       ctrl->read_cmd = spmi_read_cmd;
> +       ctrl->write_cmd = spmi_write_cmd;
> +
> +       ret = devm_spmi_controller_add(&pdev->dev, ctrl);
> +       if (ret) {
> +               dev_err(&pdev->dev,
> +                       "spmi_controller_add failed with error %d!\n", ret);

Use 'return dev_err_probe()'?

> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id spmi_controller_match_table[] = {
> +       { .compatible = "apple,spmi", },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, spmi_controller_match_table);
> +
> +static struct platform_driver spmi_controller_driver = {

How about apple_spmi_driver?

> +       .probe          = spmi_controller_probe,

And apple_spmi_probe?

> +       .driver         = {
> +               .name   = "apple-spmi",
> +               .of_match_table = spmi_controller_match_table,

And apple_spmi_match_table?

> +       },
> +};
> +module_platform_driver(spmi_controller_driver);


From alexandre.belloni at bootlin.com  Wed Mar  5 14:16:59 2025
From: alexandre.belloni at bootlin.com (alexandre.belloni at bootlin.com)
Date: Wed,  5 Mar 2025 23:16:59 +0100
Subject: [PATCH] rtc: pl031: document struct pl031_vendor_data members
Message-ID: <20250305221659.1153495-1-alexandre.belloni@bootlin.com>

From: Alexandre Belloni <alexandre.belloni at bootlin.com>

Document the range related members of struct pl031_vendor_data.

Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503011015.SYvdddTc-lkp at intel.com/
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
---
 drivers/rtc/rtc-pl031.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 47bfc5395e59..0401c51191e5 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -74,6 +74,8 @@
  * @st_weekday: if this is an ST Microelectronics silicon version that need
  *	the weekday fix
  * @irqflags: special IRQ flags per variant
+ * @range_min: minimum date/time supported by the RTC
+ * @range_maximum: maximum date/time supported by the RTC
  */
 struct pl031_vendor_data {
 	struct rtc_class_ops ops;
-- 
2.48.1



From heiko at sntech.de  Wed Mar  5 14:21:12 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 05 Mar 2025 23:21:12 +0100
Subject: [PATCH 2/7] clk: rockchip: add support for GRF gated clocks
In-Reply-To: <20250305-rk3576-sai-v1-2-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-2-64e6cf863e9a@collabora.com>
Message-ID: <4964374.GXAFRqVoOG@phil>

Hey,

Am Mittwoch, 5. M?rz 2025, 22:24:22 MEZ schrieb Nicolas Frattaroli:
> Certain Rockchip SoCs, the RK3576 in particular, have some clocks that
> are essentially gated behind an additional GRF write. Downstream uses an
> additional entirely separate clock driver that maps over the same
> address range as ioc_grf in the DT.
> 
> Instead, this implementation introduces a new gate type, GRF gates.
> These gates function quite like regular gates. In effect, this means
> they'll only be enabled if the clock is used, which I feel is a more
> appropriate way to describe this compared to doing it in, say, pinctrl,
> or even in the drivers of the respective clock consumers such as SAI.
> 
> It should be noted that RK3588 has similar GRF-gated clocks, but has
> gotten away with not having to deal with any of this because the clocks
> are ungated by the hardware's register reset value by default. The
> RK3576 is not so lucky, and the hardware's reset value gates them
> instead, which means we'll have to ungate them somewhere.
> 
> In order to facilitate the GRF gating on RK3576, we introduce the
> concept of auxiliary GRFs. The RK3576 has several defined GRF nodes, and
> so far it could get away with just using one for MUXGRF by reassigning
> the clock provider's grf member.
> 
> However, with the IOC GRF gated clocks, we now also need access to the
> IOC GRF, so we can't get away with this anymore. Instead, we add a
> hashtable to the clock provider struct, keyed by a grf type enum. The
> clock branches can then specify through the use of a new member of that
> enum's type (with corresponding changes to relevant macros) which GRF
> range they would like to use.
> 
> The SoC-specific clk_init can then populate the hashtable with the GRFs
> that it needs. This way, GRF-dependent clock branches don't have to be
> registered in a different step than everything else, as they would need
> to be had I extended the branch struct to instead take a pointer to a
> GRF, which isn't available at the time most of our branches are defined.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>

I only did a short look through the patch and didn't see anything
glaringly wrong, but this wants to be at least 3 patches:
- add the handling (hash-table etc) for multiple grfs
  (including adapting the grf-mux)
- adding the grf-gate clock-type
- adding the rk3576 grf-gates


Heiko




From robh at kernel.org  Wed Mar  5 14:23:32 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 05 Mar 2025 16:23:32 -0600
Subject: [PATCH 1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register
 compatible
In-Reply-To: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
References: <20250305140009.2485859-1-amadeus@jmu.edu.cn>
Message-ID: <174121292938.2932177.8424049595857198215.robh@kernel.org>


On Wed, 05 Mar 2025 22:00:08 +0800, Chukun Pan wrote:
> Document rk3528 compatible for QoS registers.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/rockchip/' for 20250305140009.2485859-1-amadeus at jmu.edu.cn:

arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200080: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200100: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200200: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200280: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200300: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff200380: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff210000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff210080: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff220000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff220080: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff240000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff250000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff260000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270080: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270100: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270200: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270280: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270300: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270380: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270480: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff270500: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280000: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280080: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280100: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280180: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280200: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280280: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280300: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280380: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dtb: qos at ff280400: compatible:0: 'rockchip,rk3528-qos' is not one of ['al,alpine-sysfabric-service', 'allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'altr,l3regs', 'altr,sdr-ctl', 'amd,pensando-elba-syscon', 'amlogic,meson-mx-assist', 'amlogic,meson-mx-bootrom', 'amlogic,meson8-analog-top', 'amlogic,meson8b-analog-top', 'amlogic,meson8-pmu', 'amlogic,meson8b-pmu', 'apm,merlin-poweroff-mailbox', 'apm,mustang-poweroff-mailbox', 'apm,xgene-csw', 'apm,xgene-efuse', 'apm,xgene-mcb', 'apm,xgene-rb', 'apm,xgene-scu', 'atmel,sama5d2-sfrbu', 'atmel,sama5d3-nfc-io', 'atmel,sama5d3-sfrbu', 'atmel,sama5d4-sfrbu', 'axis,artpec6-syscon', 'brcm,cru-clkset', 'brcm,sr-cdru', 'brcm,sr-mhb', 'cirrus,ep7209-syscon1', 'cirrus,ep7209-syscon2', 'cirrus,ep7209-syscon3', 'cnxt,cx92755-uc', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-
 syscfg', 'fsl,imx93-wakeupmix-syscfg', 'fsl,ls1088a-reset', 'fsl,vf610-anatop', 'fsl,vf610-mscm-cpucfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,hip04-ppe', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'lsi,axxia-syscon', 'marvell,armada-3700-cpu-misc', 'marvell,armada-3700-nb-pm', 'marvell,armada-3700-avs', 'marvell,armada-3700-usb2-host-misc', 'marvell,dove-global-config', 'mediatek,mt2701-pctl-a-syscfg', 'mediatek,mt2712-pctl-a-syscfg', 'mediatek,mt6397-pctl-pmic-syscfg', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8173-pctl-a-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,mpfs-sysreg-scb', 'microchip,sam9x60-sfr', 'microchip,sama7g5-ddr3phy', 'mscc,ocelot-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3
 128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3562-qos', 'rockchip,rk3568-qos', 'rockchip,rk3576-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'st,spear1340-misc', 'stericsson,nomadik-pmu', 'starfive,jh7100-sysmain', 'ti,am62-opp-efuse-table', 'ti,am62-usb-phy-ctrl', 'ti,am625-dss-oldi-io-ctrl', 'ti,am62p-cpsw-mac-efuse', 'ti,am654-dss-oldi-io-ctrl', 'ti,j784s4-acspcie-proxy-ctrl', 'ti,j784s4-pcie-ctrl', 'ti,keystone-pllctrl']
	from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#







From robh at kernel.org  Wed Mar  5 14:23:35 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 05 Mar 2025 16:23:35 -0600
Subject: [PATCH] arm64: dts: renesas: r8a779f4: Add UFS tuning
 parameters in E-FUSE
In-Reply-To: <3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas@glider.be>
References: <3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas@glider.be>
Message-ID: <174121293051.2932459.11282638089781621289.robh@kernel.org>


On Wed, 05 Mar 2025 14:35:13 +0100, Geert Uytterhoeven wrote:
> Describe the location in the E-FUSE block of the PLL and AFE tuning
> parameters for the Universal Flash Storage controller.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> Updated DT bindings and driver code are available in "[PATCH v3 0/7]
> scsi: ufs: renesas: Add support for R-Car S4-8 ES1.2"
> https://lore.kernel.org/cover.1741179611.git.geert+renesas at glider.be
> ---
>  arch/arm64/boot/dts/renesas/r8a779f4.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/renesas/' for 3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas at glider.be:

arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dtb: ufs at e6860000: Unevaluated properties are not allowed ('nvmem-cell-names', 'nvmem-cells' were unexpected)
	from schema $id: http://devicetree.org/schemas/ufs/renesas,ufs.yaml#







From vladimir.oltean at nxp.com  Wed Mar  5 14:30:29 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 00:30:29 +0200
Subject: [PATCH iwl-next v8 01/11] net: stmmac: move frag_size handling
 out of spin_lock
In-Reply-To: <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305223029.yh3fglyq5isncjni@skbuf>

On Wed, Mar 05, 2025 at 08:00:16AM -0500, Faizal Rahim wrote:
> The upcoming patch will extract verification logic into a new module,
> MMSV (MAC Merge Software Verification). MMSV will handle most FPE fields,
> except frag_size. It introduces its own lock (mmsv->lock), replacing
> fpe_cfg->lock.
> 
> Since frag_size handling remains in the driver, the existing rtnl_lock()
> is sufficient. Move frag_size handling out of spin_lock_irq_save() to keep
> the upcoming patch a pure refactoring without behavior changes.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar  5 14:45:37 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 00:45:37 +0200
Subject: [PATCH iwl-next v8 03/11] net: ethtool: mm: reset verification
 status when link is down
In-Reply-To: <20250305130026.642219-4-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-4-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305224537.77vatd2553pna7wq@skbuf>

On Wed, Mar 05, 2025 at 08:00:18AM -0500, Faizal Rahim wrote:
> When the link partner goes down, "ethtool --show-mm" still displays
> "Verification status: SUCCEEDED," reflecting a previous state that is
> no longer valid.
> 
> Reset the verification status to ensure it reflects the current state.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  net/ethtool/mm.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
> index aa43df2ecac0..ad9b40034003 100644
> --- a/net/ethtool/mm.c
> +++ b/net/ethtool/mm.c
> @@ -415,8 +415,9 @@ void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
>  		/* New link => maybe new partner => new verification process */
>  		ethtool_mmsv_apply(mmsv);
>  	} else {
> -		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
> -		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;

This is not what I requested. The lines with "-" here should have never
been introduced by patch 02/11 in the first place.

> +		/* Reset the reported verification state while the link is down */
> +		if (mmsv->verify_enabled)
> +			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
>  
>  		/* No link or pMAC not enabled */
>  		ethtool_mmsv_configure_pmac(mmsv, false);
> -- 
> 2.34.1
>


From vladimir.oltean at nxp.com  Wed Mar  5 14:46:42 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 00:46:42 +0200
Subject: [PATCH iwl-next v8 05/11] igc: optimize the TX packet buffer
 utilization
In-Reply-To: <20250305130026.642219-6-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-6-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305224642.7c6dz52mhj35f4f4@skbuf>

On Wed, Mar 05, 2025 at 08:00:20AM -0500, Faizal Rahim wrote:
> Packet buffers (RX + TX) total 64KB. Neither RX or TX buffers can be
> larger than 34KB. So divide the buffer equally, 32KB for each.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  drivers/net/ethernet/intel/igc/igc_defines.h | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
> index 8e449904aa7d..516ef70c98e9 100644
> --- a/drivers/net/ethernet/intel/igc/igc_defines.h
> +++ b/drivers/net/ethernet/intel/igc/igc_defines.h
> @@ -400,7 +400,8 @@
>  #define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
>  #define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */
>  
> -#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
> + /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/

Strange formatting here: space before "/*" but no space before "*/"?

> +#define IGC_TXPBSIZE_TSN	0x041c71c7
>  
>  #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
>  #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
> -- 
> 2.34.1
>


From jwerner at chromium.org  Wed Mar  5 14:50:20 2025
From: jwerner at chromium.org (Julius Werner)
Date: Wed, 5 Mar 2025 14:50:20 -0800
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <20250305101025.2279951-2-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com> <20250305101025.2279951-2-george.cherian@marvell.com>
Message-ID: <CAODwPW_3BCfTcTu=K+6Q3PMe8DtWTiKFHC6+HO2q+cTqs=EPAA@mail.gmail.com>

>  static const struct watchdog_ops adv_ec_wdt_ops = {
> diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c
> index 8f3d0c3a005f..794cf0086912 100644
> --- a/drivers/watchdog/arm_smc_wdt.c
> +++ b/drivers/watchdog/arm_smc_wdt.c
> @@ -90,7 +90,8 @@ static const struct watchdog_info smcwd_info = {
>         .identity       = DRV_NAME,
>         .options        = WDIOF_SETTIMEOUT |
>                           WDIOF_KEEPALIVEPING |
> -                         WDIOF_MAGICCLOSE,
> +                         WDIOF_MAGICCLOSE |
> +                         WDIOF_STOP_MAYSLEEP,
>  };

I don't think this driver can sleep, unless I'm missing something?
`arm_smccc_smc()` does a synchronous call into firmware that always
returns back to the caller.


From linux at roeck-us.net  Wed Mar  5 15:03:56 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 5 Mar 2025 15:03:56 -0800
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <20250305101025.2279951-2-george.cherian@marvell.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
Message-ID: <35c97316-1e40-45ed-93b0-7e4f7dbce56d@roeck-us.net>

On 3/5/25 02:10, George Cherian wrote:
> A new option flag is added to watchdog_info. This helps the watchdog
> core to check whether stop functions would sleep or not.
> The option flags of individual drivers are also updated accordingly.
> 
> Signed-off-by: George Cherian <george.cherian at marvell.com>
> ---
>   drivers/watchdog/advantech_ec_wdt.c | 3 ++-
>   drivers/watchdog/arm_smc_wdt.c      | 3 ++-
>   drivers/watchdog/armada_37xx_wdt.c  | 2 +-


... and many more. Sorry, I didn't expect that this would touch
that many drivers. My bad.

Let's do the opposite instead: Introduce WDIOF_STOP_NOSLEEP,
and let drivers opt in instead of opting out.

I still have to look into the other feedback. I think someone
suggested to introduce a callback instead, which would stop the
watchdog at runtime if needed (especially during kdump).
That may be a better solution than having a module parameter.

Either case, please separate driver patches from the patches
introducing the new flag. Since the flag is opt-in, that should
be ok - drivers supporting it can be modified over time.

Thanks,
Guenter



From vladimir.oltean at nxp.com  Wed Mar  5 14:58:03 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 00:58:03 +0200
Subject: [PATCH iwl-next v8 06/11] igc: set the RX packet buffer size for
 TSN mode
In-Reply-To: <20250305130026.642219-7-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-7-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250305225803.kozn26ilnrnjrgbz@skbuf>

On Wed, Mar 05, 2025 at 08:00:21AM -0500, Faizal Rahim wrote:
> In preparation for supporting frame preemption, when entering TSN mode
> set the receive packet buffer to 16KB for the Express MAC, 16KB for
> the Preemptible MAC and 2KB for the BMC, according to the datasheet
> section 7.1.3.2.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  drivers/net/ethernet/intel/igc/igc_defines.h |  3 +++
>  drivers/net/ethernet/intel/igc/igc_tsn.c     | 13 +++++++++++--
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
> index 516ef70c98e9..b19ac6f30dac 100644
> --- a/drivers/net/ethernet/intel/igc/igc_defines.h
> +++ b/drivers/net/ethernet/intel/igc/igc_defines.h
> @@ -402,6 +402,9 @@
>  
>   /* 7KB bytes buffer for each tx queue (total 4 queues) + 4KB for BMC*/
>  #define IGC_TXPBSIZE_TSN	0x041c71c7
> +/* 15KB for EXP + 15KB for BE + 2KB for BMC */
> +#define IGC_RXPBSIZE_TSN	0x0000f08f
> +#define IGC_RXPBSIZE_SIZE_MASK	0x0001FFFF

Does 0x0000f08f have any further meaning, does it represent anything
bitwise? (similar question for IGC_TXPBSIZE_TSN in the previous patch).
I don't see the correlation between the values mentioned in the comment
and the magic constant. If RXPBPSIZE has a bitwise meaning, maybe you
could rewrite the magic value with macros for each field.


From lkp at intel.com  Wed Mar  5 15:19:10 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 07:19:10 +0800
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
Message-ID: <202503060750.pkwFWR24-lkp@intel.com>

Hi Kevin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus lee-leds/for-leds-next lee-mfd/for-mfd-next robh/for-next lee-mfd/for-mfd-fixes linus/master v6.14-rc5 next-20250305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kevin-Chen/ARM-dts-aspeed-g6-Add-AST2600-LPC-PCC-support/20250304-194530
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250304104434.481429-4-kevin_chen%40aspeedtech.com
patch subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
config: s390-kismet-CONFIG_MFD_SYSCON-CONFIG_ASPEED_LPC_PCC-0-0 (https://download.01.org/0day-ci/archive/20250306/202503060750.pkwFWR24-lkp at intel.com/config)
reproduce: (https://download.01.org/0day-ci/archive/20250306/202503060750.pkwFWR24-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503060750.pkwFWR24-lkp at intel.com/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for MFD_SYSCON when selected by ASPEED_LPC_PCC
   WARNING: unmet direct dependencies detected for MFD_SYSCON
     Depends on [n]: HAS_IOMEM [=n]
     Selected by [y]:
     - ASPEED_LPC_PCC [=y]

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From gshan at redhat.com  Wed Mar  5 15:31:43 2025
From: gshan at redhat.com (Gavin Shan)
Date: Thu, 6 Mar 2025 09:31:43 +1000
Subject: [PATCH v7 09/45] kvm: arm64: Expose debug HW register numbers for
 Realm
In-Reply-To: <ea9bb982-cf31-4079-8fea-dc39e91a975b@arm.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-10-steven.price@arm.com>
 <cec600f2-2ddc-4c71-9bab-0a0403132b43@redhat.com>
 <ea9bb982-cf31-4079-8fea-dc39e91a975b@arm.com>
Message-ID: <3190c4b0-4826-4d9b-9b12-8063acff57fa@redhat.com>

Hi Steven,

On 3/6/25 2:25 AM, Steven Price wrote:
> On 03/03/2025 04:48, Gavin Shan wrote:
>> On 2/14/25 2:13 AM, Steven Price wrote:
>>> From: Suzuki K Poulose <suzuki.poulose at arm.com>
>>>
>>> Expose VM specific Debug HW register numbers.
> 
> Looking at this now, this patch description is garbage. Probably the
> patch has changed over time - so I suspect it's my fault not Suzuki's.
> We're not exposing anything new here. This is purely about telling the
> VMM that a realm cannot (currently) be debugged. Something like the
> below would be more accurate:
> 
> """
> kvm: arm64: Don't expose debug capabilities for realm guests
> 
> RMM v1.0 provides no mechanism for the host to perform debug operations
> on the guest. So don't expose KVM_CAP_SET_GUEST_DEBUG and report 0
> breakpoints and 0 watch points.
> """
> 

Yes, the improved change log looks good to me.

>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>>> Signed-off-by: Steven Price <steven.price at arm.com>
>>> ---
>>>  ? arch/arm64/kvm/arm.c | 24 +++++++++++++++++++++---
>>>  ? 1 file changed, 21 insertions(+), 3 deletions(-)
>>>
>>
>> Documentation/virt/kvm/api.rst needs to be updated accordingly.
> 
> I don't think (with the above clarification) there's anything to update
> in the API documentation. There's nothing new being added, just
> capabilities being hidden where the functionality isn't available.
> 
> And eventually we hope to add support for this (in a later RMM spec) - I
> don't yet know exactly what form this will take, but I hope to keep the
> interfaces as close as possible to what we already have so that existing
> tooling can be used.
> 

Ok.

>>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>>> index b8fa82be251c..df6eb5e9ca96 100644
>>> --- a/arch/arm64/kvm/arm.c
>>> +++ b/arch/arm64/kvm/arm.c
>>> @@ -78,6 +78,22 @@ bool is_kvm_arm_initialised(void)
>>>  ????? return kvm_arm_initialised;
>>>  ? }
>>>  ? +static u32 kvm_arm_get_num_brps(struct kvm *kvm)
>>> +{
>>> +??? if (!kvm_is_realm(kvm))
>>> +??????? return get_num_brps();
>>> +??? /* Realm guest is not debuggable. */
>>> +??? return 0;
>>> +}
>>> +
>>> +static u32 kvm_arm_get_num_wrps(struct kvm *kvm)
>>> +{
>>> +??? if (!kvm_is_realm(kvm))
>>> +??????? return get_num_wrps();
>>> +??? /* Realm guest is not debuggable. */
>>> +??? return 0;
>>> +}
>>> +
>>
>> The above two comments "Realm guest is not debuggable." can be dropped
>> since
>> the code is self-explanatory, and those two functions are unnecessary to be
>> kept in that way, for example:
>>
>>  ????case KVM_CAP_GUEST_DEBUG_HW_BPS:
>>  ??????? return kvm_is_realm(kvm) ? 0 : get_num_brps();
>>  ????case KVM_CAP_GUEST_DEBUG_HW_WRPS:
>>  ??????? return kvm_is_realm(kvm) ? 0 : get_num_wrps();
>>
>>
>>>  ? int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>>>  ? {
>>>  ????? return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
>>> @@ -323,7 +339,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm,
>>> long ext)
>>>  ????? case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
>>>  ????? case KVM_CAP_ARM_NISV_TO_USER:
>>>  ????? case KVM_CAP_ARM_INJECT_EXT_DABT:
>>> -??? case KVM_CAP_SET_GUEST_DEBUG:
>>>  ????? case KVM_CAP_VCPU_ATTRIBUTES:
>>>  ????? case KVM_CAP_PTP_KVM:
>>>  ????? case KVM_CAP_ARM_SYSTEM_SUSPEND:
>>> @@ -331,6 +346,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm,
>>> long ext)
>>>  ????? case KVM_CAP_COUNTER_OFFSET:
>>>  ????????? r = 1;
>>>  ????????? break;
>>> +??? case KVM_CAP_SET_GUEST_DEBUG:
>>> +??????? r = !kvm_is_realm(kvm);
>>> +??????? break;
>>>  ????? case KVM_CAP_SET_GUEST_DEBUG2:
>>>  ????????? return KVM_GUESTDBG_VALID_MASK;
>>>  ????? case KVM_CAP_ARM_SET_DEVICE_ADDR:
>>> @@ -376,10 +394,10 @@ int kvm_vm_ioctl_check_extension(struct kvm
>>> *kvm, long ext)
>>>  ????????? r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
>>>  ????????? break;
>>>  ????? case KVM_CAP_GUEST_DEBUG_HW_BPS:
>>> -??????? r = get_num_brps();
>>> +??????? r = kvm_arm_get_num_brps(kvm);
>>>  ????????? break;
>>>  ????? case KVM_CAP_GUEST_DEBUG_HW_WPS:
>>> -??????? r = get_num_wrps();
>>> +??????? r = kvm_arm_get_num_wrps(kvm);
>>>  ????????? break;
>>>  ????? case KVM_CAP_ARM_PMU_V3:
>>>  ????????? r = kvm_arm_support_pmu_v3();
>>

Thanks,
Gavin



From apopple at nvidia.com  Wed Mar  5 15:49:30 2025
From: apopple at nvidia.com (Alistair Popple)
Date: Thu, 6 Mar 2025 10:49:30 +1100
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
In-Reply-To: <Z8iccxCo7tkqvE_p@arm.com>
References: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
 <Z8iccxCo7tkqvE_p@arm.com>
Message-ID: <3wosp7lqbcwzspgv7gq25ii5hdr3fztrvnhcha3uqcyellulro@xyz7gx7qjkq2>

On Wed, Mar 05, 2025 at 06:48:19PM +0000, Catalin Marinas wrote:
> On Tue, Mar 04, 2025 at 12:51:27AM -0800, Piotr Jaroszynski wrote:
> > Update the __flush_tlb_range_op macro not to modify its parameters as
> > these are unexepcted semantics. In practice, this fixes the call to
> > mmu_notifier_arch_invalidate_secondary_tlbs() in
> > __flush_tlb_range_nosync() to use the correct range instead of an empty
> > range with start=end. The empty range was (un)lucky as it results in
> > taking the invalidate-all path that doesn't cause correctness issues,
> > but can certainly result in suboptimal perf.
> > 
> > This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
> > invalidate_range() when invalidating TLBs") when the call to the
> > notifiers was added to __flush_tlb_range(). It predates the addition of
> > the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
> > Refactor the core flush algorithm of __flush_tlb_range") that made the
> > bug hard to spot.
> 
> That's the problem with macros.

Yep, that's why I missed it when adding the notifier call. Anyway:

Reviewed-by: Alistair Popple <apopple at nvidia.com>

> Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
> 
> Will, do you want to take this as a fix? It's only a performance
> regression, though you never know how it breaks the callers of the macro
> at some point.
> 
> > Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")
> > 
> > Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
> > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > Cc: Will Deacon <will at kernel.org>
> > Cc: Robin Murphy <robin.murphy at arm.com>
> > Cc: Alistair Popple <apopple at nvidia.com>
> > Cc: Raghavendra Rao Ananta <rananta at google.com>
> > Cc: SeongJae Park <sj at kernel.org>
> > Cc: Jason Gunthorpe <jgg at nvidia.com>
> > Cc: John Hubbard <jhubbard at nvidia.com>
> > Cc: Nicolin Chen <nicolinc at nvidia.com>
> > Cc: linux-arm-kernel at lists.infradead.org
> > Cc: iommu at lists.linux.dev
> > Cc: linux-mm at kvack.org
> > Cc: linux-kernel at vger.kernel.org
> > Cc: stable at vger.kernel.org
> > ---
> >  arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++----------
> >  1 file changed, 12 insertions(+), 10 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
> > index bc94e036a26b..8104aee4f9a0 100644
> > --- a/arch/arm64/include/asm/tlbflush.h
> > +++ b/arch/arm64/include/asm/tlbflush.h
> > @@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
> >  #define __flush_tlb_range_op(op, start, pages, stride,			\
> >  				asid, tlb_level, tlbi_user, lpa2)	\
> >  do {									\
> > +	typeof(start) __flush_start = start;				\
> > +	typeof(pages) __flush_pages = pages;				\
> >  	int num = 0;							\
> >  	int scale = 3;							\
> >  	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
> >  	unsigned long addr;						\
> >  									\
> > -	while (pages > 0) {						\
> > +	while (__flush_pages > 0) {					\
> >  		if (!system_supports_tlb_range() ||			\
> > -		    pages == 1 ||					\
> > -		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
> > -			addr = __TLBI_VADDR(start, asid);		\
> > +		    __flush_pages == 1 ||				\
> > +		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
> > +			addr = __TLBI_VADDR(__flush_start, asid);	\
> >  			__tlbi_level(op, addr, tlb_level);		\
> >  			if (tlbi_user)					\
> >  				__tlbi_user_level(op, addr, tlb_level);	\
> > -			start += stride;				\
> > -			pages -= stride >> PAGE_SHIFT;			\
> > +			__flush_start += stride;			\
> > +			__flush_pages -= stride >> PAGE_SHIFT;		\
> >  			continue;					\
> >  		}							\
> >  									\
> > -		num = __TLBI_RANGE_NUM(pages, scale);			\
> > +		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
> >  		if (num >= 0) {						\
> > -			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
> > +			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
> >  						scale, num, tlb_level);	\
> >  			__tlbi(r##op, addr);				\
> >  			if (tlbi_user)					\
> >  				__tlbi_user(r##op, addr);		\
> > -			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
> > -			pages -= __TLBI_RANGE_PAGES(num, scale);	\
> > +			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
> > +			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
> >  		}							\
> >  		scale--;						\
> >  	}								\
> > 
> > base-commit: 99fa936e8e4f117d62f229003c9799686f74cebc
> > -- 
> > 2.22.1.7.gac84d6e93c.dirty
> 
> -- 
> Catalin


From linux at roeck-us.net  Wed Mar  5 15:58:40 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 5 Mar 2025 15:58:40 -0800
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <7ac2b8db-22c7-4168-b1b7-4f9f0ab10531@pengutronix.de>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
 <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
 <7ac2b8db-22c7-4168-b1b7-4f9f0ab10531@pengutronix.de>
Message-ID: <28a711e5-b2cb-4d5f-bb78-259a01cd4bcc@roeck-us.net>

On 3/5/25 03:01, Ahmad Fatoum wrote:
> Hi George,
> Hi Guenter,
> 
> On 05.03.25 11:34, George Cherian wrote:
>>> why is armada_37xx_wdt also here?
>>> The stop function in that driver may not sleep.
>> Marek,
>>
>> Thanks for reviewing.
>> Since the stop function has a regmap_write(), I thought it might sleep.
>> Now that you pointed it out, I assume that it is an MMIO based regmap being used for armada.
>> I will update the same in the next version
> 
> Failure to add WDIOF_STOP_MAYSLEEP when it's needed can lead to
> kernel hanging. Failure to add an alternative WDIOF_STOP_ATOMIC
> would lead to the kernel option being a no-op.
> 
> I think a no-op stop_on_panic (or reset_on_panic) is a saner default.
> 

Agreed. Also, I like WDIOF_STOP_ATOMIC more than the WDIOF_STOP_NOSLEEP
I had suggested in my other response.

Thanks,
Guenter



From oliver.upton at linux.dev  Wed Mar  5 15:58:56 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed,  5 Mar 2025 15:58:56 -0800
Subject: [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration
In-Reply-To: <20250221140229.12588-1-shameerali.kolothum.thodi@huawei.com>
References: <20250221140229.12588-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <174121899987.513001.15032119490654823649.b4-ty@linux.dev>

On Fri, 21 Feb 2025 14:02:23 +0000, Shameer Kolothum wrote:
> v7-->v8
> https://lore.kernel.org/kvmarm/20250214151343.61348-1-shameerali.kolothum.thodi at huawei.com/
> 
> Changes:
>  -Fixed the compile error issue due to CONFIG_CORESIGHT_SOURCE_ETM4X=m
>   (Thanks to Sebastian for checking that config)- patch #4
>  -Added R-by tags.
> 
> [...]

The feature branch for all of this can be found here should the need arise.

git://git.kernel.org/pub/scm/linux/kernel/git/oupton/linux.git kvm-arm64/pv-cpuid

Applied to next, thanks!

[1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally
      https://git.kernel.org/kvmarm/kvmarm/c/e3121298c7fc
[2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations
      https://git.kernel.org/kvmarm/kvmarm/c/57e5cc9b8a39
[3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2
      https://git.kernel.org/kvmarm/kvmarm/c/c0000e58c74e
[4/6] arm64: Make _midr_in_range_list() an exported function
      https://git.kernel.org/kvmarm/kvmarm/c/c8c2647e69be
[5/6] smccc/kvm_guest: Enable errata based on implementation CPUs
      https://git.kernel.org/kvmarm/kvmarm/c/86edf6bdcf05
[6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2
      https://git.kernel.org/kvmarm/kvmarm/c/f69656656fa7

--
Best,
Oliver


From linux at roeck-us.net  Wed Mar  5 16:00:48 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 5 Mar 2025 16:00:48 -0800
Subject: [PATCH v4 2/2] drivers: watchdog: Add support for panic notifier
 callback
In-Reply-To: <Z8gohVIQqlA6QquZ@smile.fi.intel.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-3-george.cherian@marvell.com>
 <Z8gohVIQqlA6QquZ@smile.fi.intel.com>
Message-ID: <5ca55233-b370-4176-9632-8e5df8d4c4ce@roeck-us.net>

On 3/5/25 02:33, Andy Shevchenko wrote:
> On Wed, Mar 05, 2025 at 10:10:25AM +0000, George Cherian wrote:
>> Watchdog is not turned off in kernel panic situation.
>> In certain systems this might prevent the successful loading
>> of kdump kernel. The kdump kernel might hit a watchdog reset
>> while it is booting.
>>
>> To avoid such scenarios add a panic notifier call back function
>> which can stop the watchdog. This provision can be enabled by
>> passing watchdog.stop_on_panic=1 via kernel command-line parameter.
> 
> ...
> 
> First of all, do we really need a new module parameter for that? Why can't it
> be done automatically if kdump is expected?
> 

Sounds like a good idea to me.

Guenter



From hongxing.zhu at nxp.com  Wed Mar  5 16:24:42 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Thu, 6 Mar 2025 00:24:42 +0000
Subject: [PATCH v2 0/2] phy: freescale: imx8m-pcie: fix and cleanup phy
In-Reply-To: <20250305144355.20364-1-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
Message-ID: <AS8PR04MB8676367C2BD21FB1A8C386748CCA2@AS8PR04MB8676.eurprd04.prod.outlook.com>

Hi Stefan:
Thanks for the clean up and bug fix. Please update the commit with Frank's comments.
For this series, Acked-by: Richard Zhu <hongxing.zhu at nxp.com>

Best Regards
Richard Zhu

> -----Original Message-----
> From: Stefan Eichenberger <eichest at gmail.com>
> Sent: 2025?3?5? 22:43
> To: vkoul at kernel.org; kishon at kernel.org; shawnguo at kernel.org;
> s.hauer at pengutronix.de; kernel at pengutronix.de; festevam at gmail.com;
> p.zabel at pengutronix.de; tharvey at gateworks.com; Hongxing Zhu
> <hongxing.zhu at nxp.com>; Francesco Dolcini <francesco.dolcini at toradex.com>
> Cc: linux-phy at lists.infradead.org; imx at lists.linux.dev;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: [PATCH v2 0/2] phy: freescale: imx8m-pcie: fix and cleanup phy
> 
> The imx8m-pcie PHY PLL fails to lock under certain conditions when returning
> from suspend. This is resolved by asserting the PHY reset when powering off the
> PHY during suspend. This ensures that the PHY is properly reset when powering
> on again in resume.
> 
> Changes in v2:
> - Remove unnecessary check if perst is not null (Philipp)
> 
> Stefan Eichenberger (2):
>   phy: freescale: imx8m-pcie: cleanup reset logic
>   phy: freescale: imx8m-pcie: assert phy reset and perst in power off
> 
>  drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 23 +++++++++++++---------
>  1 file changed, 14 insertions(+), 9 deletions(-)
> 
> --
> 2.45.2


From vladimir.oltean at nxp.com  Wed Mar  5 16:28:25 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 02:28:25 +0200
Subject: [PATCH iwl-next v8 07/11] igc: add support for frame preemption
 verification
In-Reply-To: <20250305130026.642219-8-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-8-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250306002825.rva7wjsymmms7kbd@skbuf>

On Wed, Mar 05, 2025 at 08:00:22AM -0500, Faizal Rahim wrote:
> b) configure_pmac() -> not used
>    - this callback dynamically controls pmac_enabled at runtime. For
>      example, mmsv calls configure_pmac() and disables pmac_enabled when
>      the link partner goes down, even if the user previously enabled it.
>      The intention is to save power but it is not feasible in igc
>      because it causes an endless adapter reset loop:
> 
>    1) Board A and Board B complete the verification handshake. Tx mode
>       register for both boards are in TSN mode.
>    2) Board B link goes down.
> 
>    On Board A:
>    3) mmsv calls configure_pmac() with pmac_enabled = false.
>    4) configure_pmac() in igc updates a new field based on pmac_enabled.
>       Driver uses this field in igc_tsn_new_flags() to indicate that the
>       user enabled/disabled FPE.
>    5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
>       whether an adapter reset is needed. Calls existing logic in
>       igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
>    6) Since pmac_enabled is now disabled and no other TSN feature is
>       active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
>       mode will switch from TSN to Legacy.
>    7) Driver resets the adapter.
>    8) Registers are set, and Tx mode switches to Legacy.
>    9) When link partner is up, steps 3?8 repeat, but this time with
>       pmac_enabled = true, reactivating TSN.
>       igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
>       mode will switch from Legacy to TSN.
>   10) Driver resets the adapter.
>   11) Rest adapter completes, registers are set, and Tx mode switches to

s/Rest adapter/Adapter reset/

>       TSN.
> 
>   On Board B:
>   12) Adapter reset on Board A at step 10 causes it to detect its link
>       partner as down.
>   13) Repeats steps 3?8.
>   14) Once reset adapter on Board A is completed at step 11, it detects
>       its link partner as up.
>   15) Repeats steps 9?11.
> 
>    - this cycle repeats indefinitely. To avoid this issue, igc only uses
>      mmsv.pmac_enabled to track whether FPE is enabled or disabled.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
> Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
> +static inline bool igc_fpe_is_pmac_enabled(struct igc_adapter *adapter)
> +{
> +	return static_branch_unlikely(&igc_fpe_enabled) &&
> +	       adapter->fpe.mmsv.pmac_enabled;
> +}
> +
> +static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
> +						 unsigned int size, void *pktbuf)
> +{
> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
> +	static const u8 zero_payload[SMD_FRAME_SIZE] = {0};
> +	int smd;
> +
> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
> +
> +	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
> +		size == SMD_FRAME_SIZE &&
> +		!memcmp(pktbuf, zero_payload, SMD_FRAME_SIZE); /* Buffer is all zeros */

Using this definition...

> +}
> +
> +static inline void igc_fpe_lp_event_status(union igc_adv_rx_desc *rx_desc,
> +					   struct ethtool_mmsv *mmsv)
> +{
> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
> +	int smd;
> +
> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
> +
> +	if (smd == IGC_RXD_STAT_SMD_TYPE_V)
> +		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
> +	else if (smd == IGC_RXD_STAT_SMD_TYPE_R)
> +		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
> +}
> @@ -2617,6 +2617,15 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
>  			size -= IGC_TS_HDR_LEN;
>  		}
>  
> +		if (igc_fpe_is_pmac_enabled(adapter) &&
> +		    igc_fpe_is_verify_or_response(rx_desc, size, pktbuf)) {

... invalid SMD-R and SMD-V frames will skip this code block altogether, and
will be passed up the network stack, and visible at least in tcpdump, correct?
Essentially, if the link partner would craft an ICMP request packet with
an SMD-V or SMD-R, your station would respond to it, which is incorrect.

A bit strange, the behavior in this case seems a bit under-specified in
the standard, and I don't see any counter that should be incremented.

> +			igc_fpe_lp_event_status(rx_desc, &adapter->fpe.mmsv);
> +			/* Advance the ring next-to-clean */
> +			igc_is_non_eop(rx_ring, rx_desc);
> +			cleaned_count++;
> +			continue;
> +		}

To fix this, don't you want to merge the unnaturally split
igc_fpe_is_verify_or_response() and igc_fpe_lp_event_status() into a
single function, which returns true whenever the mPacket should be
consumed by the driver, but decides whether to emit a mmsv event on its
own? Merging the two would also avoid reading rx_desc->wb.upper.status_error
twice.

Something like this:

static inline bool igc_fpe_handle_mpacket(struct igc_adapter *adapter,
					  union igc_adv_rx_desc *rx_desc,
					  unsigned int size, void *pktbuf)
{
	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
	int smd;

	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
	if (smd != IGC_RXD_STAT_SMD_TYPE_V && smd != IGC_RXD_STAT_SMD_TYPE_R)
		return false;

	if (size == SMD_FRAME_SIZE && mem_is_zero(pktbuf, SMD_FRAME_SIZE)) {
		struct ethtool_mmsv *mmsv = &adapter->fpe.mmsv;
		enum ethtool_mmsv_event event;

		if (smd == IGC_RXD_STAT_SMD_TYPE_V)
			event = ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET;
		else
			event = ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET;

		ethtool_mmsv_event_handle(mmsv, event);
	}

	return true;
}

		if (igc_fpe_is_pmac_enabled(adapter) &&
		    igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf)) {
			/* Advance the ring next-to-clean */
			igc_is_non_eop(rx_ring, rx_desc);
			cleaned_count++;
			continue;
		}

[ also remark the use of mem_is_zero() instead of memcmp() with a buffer
  pre-filled with zeroes. It should be more efficient, for the simple
  reason that it's accessing a single memory buffer and not two. Though
  I'm surprised how widespread the memcmp() pattern is throughout the
  kernel. ]


From lee at kernel.org  Wed Mar  5 16:40:29 2025
From: lee at kernel.org (Lee Jones)
Date: Wed, 5 Mar 2025 16:40:29 -0800
Subject: [PATCH v3 03/20] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
In-Reply-To: <a8fbb536-a246-4650-8085-d576652b0301@sirena.org.uk>
References: <20250304-mt6359-accdet-dts-v3-0-5b0eafc29f5b@collabora.com>
 <20250304-mt6359-accdet-dts-v3-3-5b0eafc29f5b@collabora.com>
 <a8fbb536-a246-4650-8085-d576652b0301@sirena.org.uk>
Message-ID: <20250306004029.GB8350@google.com>

On Tue, 04 Mar 2025, Mark Brown wrote:

> On Tue, Mar 04, 2025 at 12:15:44PM -0300, N?colas F. R. A. Prado wrote:
> > From: Andrew Perepech <andrew.perepech at mediatek.com>
> > 
> > Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
> > allow the mt6359-accdet driver to probe.
> 
> Lee, is this OK to merge via ASoC?

Yeah, should be okay.

Acked-by: Lee Jones <lee at kernel.org>

-- 
Lee Jones [???]


From vladimir.oltean at nxp.com  Wed Mar  5 16:48:09 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 02:48:09 +0200
Subject: [PATCH iwl-next v8 11/11] igc: add support to get frame
 preemption statistics via ethtool
In-Reply-To: <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250306004809.q2x565rys5zja6kh@skbuf>

On Wed, Mar 05, 2025 at 08:00:26AM -0500, Faizal Rahim wrote:
> +/* Received out of order packets with SMD-C */
> +#define IGC_PRMEXCPRCNT_OOO_SMDC			0x000000FF
> +/* Received out of order packets with SMD-C and wrong Frame CNT */
> +#define IGC_PRMEXCPRCNT_OOO_FRAME_CNT			0x0000FF00
> +/* Received out of order packets with SMD-C and wrong Frag CNT */
> +#define IGC_PRMEXCPRCNT_OOO_FRAG_CNT			0x00FF0000
> +/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
> +#define IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
>  
> +/**
> + * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
> + * @reg_value: Register value for IGC_PRMEXCPRCNT
> + * Return: The count of frame assembly errors.
> + */
> +static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
> +{
> +	u32 ooo_frame_cnt, ooo_frag_cnt; /* Out of order statistics */
> +	u32 miss_frame_frag_cnt;
> +
> +	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
> +	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
> +	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
> +
> +	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
> +}

These counters are quite small (8 bits each). What is their behavior
once they reach 255? Saturate? Truncate? Do they clear on read?


From vladimir.oltean at nxp.com  Wed Mar  5 16:43:01 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 6 Mar 2025 02:43:01 +0200
Subject: [PATCH iwl-next v8 08/11] igc: add support to set
 tx-min-frag-size
In-Reply-To: <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250306004301.evw34gqoyll36mso@skbuf>

On Wed, Mar 05, 2025 at 08:00:23AM -0500, Faizal Rahim wrote:
> Add support to set tx-min-frag-size via set_mm callback in igc.
> Increase the max limit of tx-ming-frag-size in ethtool from 252 to 256
> since i225/6 value range is 64, 128, 192 and 256.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  drivers/net/ethernet/intel/igc/igc.h         |  1 +
>  drivers/net/ethernet/intel/igc/igc_defines.h |  1 +
>  drivers/net/ethernet/intel/igc/igc_ethtool.c |  5 +++
>  drivers/net/ethernet/intel/igc/igc_tsn.c     | 37 ++++++++++++++++++--
>  drivers/net/ethernet/intel/igc/igc_tsn.h     |  2 +-
>  net/ethtool/mm.c                             |  2 +-
>  6 files changed, 43 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
> index d9ecb7cf80c9..4dfd133b4d6f 100644
> --- a/drivers/net/ethernet/intel/igc/igc.h
> +++ b/drivers/net/ethernet/intel/igc/igc.h
> @@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *);
>  
>  struct igc_fpe_t {
>  	struct ethtool_mmsv mmsv;
> +	u32 tx_min_frag_size;
>  };
>  
>  enum igc_mac_filter_type {
> diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
> index 22db1de02964..038ee89f1e08 100644
> --- a/drivers/net/ethernet/intel/igc/igc_defines.h
> +++ b/drivers/net/ethernet/intel/igc/igc_defines.h
> @@ -551,6 +551,7 @@
>  #define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
>  #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
>  #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
> +#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000
>  
>  #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
>  #define IGC_TXQCTL_STRICT_CYCLE		0x00000002
> diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
> index b64d5c6c1d20..529654ccd83f 100644
> --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
> +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
> @@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
>  	struct igc_adapter *adapter = netdev_priv(netdev);
>  	struct igc_fpe_t *fpe = &adapter->fpe;
>  
> +	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
> +	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");
> +
>  	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
>  		if (cmd->pmac_enabled)
>  			static_branch_inc(&igc_fpe_enabled);
> diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
> index 0a2c747fde2d..2ec5909bf8b0 100644
> --- a/drivers/net/ethernet/intel/igc/igc_tsn.c
> +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
> @@ -6,6 +6,12 @@
>  #include "igc_hw.h"
>  #include "igc_tsn.h"
>  
> +#define MIN_MULTPLIER_TX_MIN_FRAG	0
> +#define MAX_MULTPLIER_TX_MIN_FRAG	3
> +/* Frag size is based on the Section 8.12.2 of the SW User Manual */
> +#define TX_MIN_FRAG_SIZE		64
> +#define TX_MAX_FRAG_SIZE	(TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1))
> +
>  DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
>  
>  static int igc_fpe_init_smd_frame(struct igc_ring *ring,
> @@ -128,6 +134,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = {
>  
>  void igc_fpe_init(struct igc_adapter *adapter)
>  {
> +	adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
>  	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
>  }
>  
> @@ -278,7 +285,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
>  	tqavctrl = rd32(IGC_TQAVCTRL);
>  	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
>  		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
> -		      IGC_TQAVCTRL_PREEMPT_ENA);
> +		      IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
>  
>  	wr32(IGC_TQAVCTRL, tqavctrl);
>  
> @@ -324,12 +331,34 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
>  	wr32(IGC_RETX_CTL, retxctl);
>  }
>  
> +static u8 igc_fpe_get_frag_size_mult(const struct igc_fpe_t *fpe)
> +{
> +	u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1;
> +
> +	return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG,
> +		       MAX_MULTPLIER_TX_MIN_FRAG);
> +}
> +
> +u32 igc_fpe_get_supported_frag_size(u32 frag_size)
> +{
> +	const u32 supported_sizes[] = {64, 128, 192, 256};
> +
> +	/* Find the smallest supported size that is >= frag_size */
> +	for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) {
> +		if (frag_size <= supported_sizes[i])
> +			return supported_sizes[i];
> +	}
> +
> +	return TX_MAX_FRAG_SIZE; /* Should not happen, value > 256 is blocked by ethtool */

Try to place comments on separate lines from code.

> +}
> +
>  static int igc_tsn_enable_offload(struct igc_adapter *adapter)
>  {
>  	struct igc_hw *hw = &adapter->hw;
>  	u32 tqavctrl, baset_l, baset_h;
>  	u32 sec, nsec, cycle, rxpbs;
>  	ktime_t base_time, systim;
> +	u32 frag_size_mult;
>  	int i;
>  
>  	wr32(IGC_TSAUXC, 0);
> @@ -501,13 +530,15 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
>  	}
>  
>  	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
> -		   IGC_TQAVCTRL_PREEMPT_ENA);
> -
> +		   IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
>  	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
>  
>  	if (adapter->fpe.mmsv.pmac_enabled)
>  		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
>  
> +	frag_size_mult = igc_fpe_get_frag_size_mult(&adapter->fpe);
> +	tqavctrl |= FIELD_PREP(IGC_TQAVCTRL_MIN_FRAG_MASK, frag_size_mult);
> +
>  	adapter->qbv_count++;
>  
>  	cycle = adapter->cycle_time;
> diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
> index a2534228cc0e..975f4e38836e 100644
> --- a/drivers/net/ethernet/intel/igc/igc_tsn.h
> +++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
> @@ -14,7 +14,7 @@ enum igc_txd_popts_type {
>  DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
>  
>  void igc_fpe_init(struct igc_adapter *adapter);
> -u32 igc_fpe_get_supported_frag_size(u32 user_frag_size);
> +u32 igc_fpe_get_supported_frag_size(u32 frag_size);

The "-" piece shouldn't exist. You are renaming a function argument for
a function declaration that shouldn't have existed in the code prior to
the introduction of its definition. Please delete it from the original
patch that added it.

>  int igc_tsn_offload_apply(struct igc_adapter *adapter);
>  int igc_tsn_reset(struct igc_adapter *adapter);
>  void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
> diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
> index ad9b40034003..4c395cd949ab 100644
> --- a/net/ethtool/mm.c
> +++ b/net/ethtool/mm.c
> @@ -153,7 +153,7 @@ const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1] = {
>  	[ETHTOOL_A_MM_VERIFY_TIME]	= NLA_POLICY_RANGE(NLA_U32, 1, 128),
>  	[ETHTOOL_A_MM_TX_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
>  	[ETHTOOL_A_MM_PMAC_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
> -	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 252),
> +	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 256),

Please make this a separate patch with a reasonably convincing
justification for any reader, and also state why it is a change that
will not introduce regressions to the other drivers. It shows that
you've done the due dilligence of checking that they all use
ethtool_mm_frag_size_min_to_add(), which errors out on non-standard
values.

To be clear, extending the policy from 252 to 256 is just to suppress
the netlink warning which states that the driver rounds up the minimum
fragment size, correct? Because even if you pass 252 (the current
netlink maximum), the driver will still use 256.

>  };
>  
>  static void mm_state_to_cfg(const struct ethtool_mm_state *state,
> -- 
> 2.34.1
>


From andyshrk at 163.com  Wed Mar  5 16:59:13 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 6 Mar 2025 08:59:13 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
Message-ID: <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>


Hi Piotr,

? 2025-03-05 21:56:12?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 5 mar 2025, o godz. 03:30:
>> 
>>> 
>> 
>> I only see the HDMI connector from your dri/state ; so it appears the DP driver hasn't been successfully
>> initialized?I think kernel dmesg can tell that?. 
>> Have you enabled CONFIG_ROCKCHIP_DW_DP ? This is needed.
>> 
>
>
>Andy,
>
>Do you mean CONFIG_ROCKCHIP_DW_DP or CONFIG_DRM_DW_DP ?
>
>If CONFIG_DRM_DW_DP - then yes - i have it: https://github.com/warpme/minimyth2/blob/2e267842b1033bbc4c2c5d80c1756a142e347cc5/script/kernel/linux-6.14/files/linux-6.14-arm64-armv8.config#L5024
>
>Kernel dmesg: https://termbin.com/uiup


Both of the two config options should be enabled.
andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
4044:CONFIG_ROCKCHIP_DW_DP=y
4218:CONFIG_DRM_DW_DP=y

And if dw dp driver boots success, you will see dmesg like bellow:

 [    1.058634] arm-smmu-v3 fc900000.iommu: msi_domain absent - falling back to wired irqs
[    1.062458] rockchip-vop2 fdd90000.vop: Adding to iommu group 0
[    1.067908] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
[    1.068981] rockchip-drm display-subsystem: bound fde60000.dp (ops dw_dp_rockchip_component_ops)
[    1.070133] dwhdmiqp-rockchip fde80000.hdmi: registered DesignWare HDMI QP I2C bus driver
[    1.070859] rockchip-drm display-subsystem: bound fde80000.hdmi (ops dw_hdmi_qp_rockchip_ops)
[    1.072103] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 0
[    1.080191] loop: module loaded

But I just see hdmi  driver boots from your dmesg.

>
>
>

From towinchenmi at gmail.com  Wed Mar  5 17:20:53 2025
From: towinchenmi at gmail.com (Nick Chan)
Date: Thu, 6 Mar 2025 09:20:53 +0800
Subject: [PATCH 3/3] arm64: dts: apple: Add SPMI controller nodes
In-Reply-To: <20250305-spmi-v1-3-c98f561fa99f@gmail.com>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com>
 <20250305-spmi-v1-3-c98f561fa99f@gmail.com>
Message-ID: <b13f29b8-2906-489d-b955-3f94a9bcb231@gmail.com>


Sasha Finkelstein via B4 Relay ? 2025/3/6 ??4:26 ??:
> From: Sasha Finkelstein <fnkl.kernel at gmail.com>
>
> Add device tree entries for the SPMI controller
>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
>  arch/arm64/boot/dts/apple/t600x-die0.dtsi | 7 +++++++
>  arch/arm64/boot/dts/apple/t8103.dtsi      | 8 ++++++++
>  arch/arm64/boot/dts/apple/t8112.dtsi      | 8 ++++++++
>  3 files changed, 23 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> index b1c875e692c8fb9c0af46a23568a7b0cd720141b..d544a35c8af414c583d38b040e1aa753902f1c93 100644
> --- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> +++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> @@ -53,6 +53,13 @@ wdt: watchdog at 2922b0000 {
>  		interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
>  	};
>  
> +	nub_spmi0: spmi at 2920a1300 {
> +		compatible = "apple,t6000-spmi", "apple,spmi";
> +		reg = <0x2 0x920a1300 0x0 0x100>;
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +	};
> +
>  	sio_dart_0: iommu at 39b004000 {
>  		compatible = "apple,t6000-dart";
>  		reg = <0x3 0x9b004000 0x0 0x4000>;
> diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
> index 9b0dad6b618444ac6b1c9735c50cccfc3965f947..0f03dc808cf7c6b7d71afc79dd29d368f957f979 100644
> --- a/arch/arm64/boot/dts/apple/t8103.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8103.dtsi
> @@ -11,6 +11,7 @@
>  #include <dt-bindings/interrupt-controller/apple-aic.h>
>  #include <dt-bindings/interrupt-controller/irq.h>
>  #include <dt-bindings/pinctrl/apple.h>
> +#include <dt-bindings/spmi/spmi.h>
>  
>  / {
>  	compatible = "apple,t8103", "apple,arm-platform";
> @@ -604,6 +605,13 @@ pcie_pins: pcie-pins {
>  			};
>  		};
>  
> +		nub_spmi: spmi at 23d0d9300 {
> +			compatible = "apple,t8103-spmi", "apple,spmi";
> +			reg = <0x2 0x3d0d9300 0x0 0x100>;
> +			#address-cells = <2>;
> +			#size-cells = <0>;
> +		};
> +
>  		pinctrl_nub: pinctrl at 23d1f0000 {
>  			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
>  			reg = <0x2 0x3d1f0000 0x0 0x4000>;
> diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
> index 1666e6ab250bc0be9b8318e3c8fc903ccd3f3760..4b3730c46c4d14a582627f69094b458ec7481da9 100644
> --- a/arch/arm64/boot/dts/apple/t8112.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8112.dtsi
> @@ -641,6 +641,14 @@ pcie_pins: pcie-pins {
>  			};
>  		};
>  
> +
> +		nub_spmi: spmi at 23d714000 {
> +			compatible = "apple,t8112-spmi", "apple,spmi";
> +			reg = <0x2 0x3d714000 0x0 0x100>;
> +			#address-cells = <2>;
> +			#size-cells = <0>;
> +		};
> +
>  		pinctrl_nub: pinctrl at 23d1f0000 {
>  			compatible = "apple,t8112-pinctrl", "apple,pinctrl";
>  			reg = <0x2 0x3d1f0000 0x0 0x4000>;
>
Reviewed-by: Nick Chan <towinchenmi at gmail.com>


From 0x1207 at gmail.com  Wed Mar  5 18:09:13 2025
From: 0x1207 at gmail.com (Furong Xu)
Date: Thu, 6 Mar 2025 10:09:13 +0800
Subject: [PATCH iwl-next v8 01/11] net: stmmac: move frag_size handling
 out of spin_lock
In-Reply-To: <20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
	<20250305130026.642219-2-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250306100913.00005bb8@gmail.com>

On Wed,  5 Mar 2025 08:00:16 -0500
Faizal Rahim <faizal.abdul.rahim at linux.intel.com> wrote:

> The upcoming patch will extract verification logic into a new module,
> MMSV (MAC Merge Software Verification). MMSV will handle most FPE fields,
> except frag_size. It introduces its own lock (mmsv->lock), replacing
> fpe_cfg->lock.
> 
> Since frag_size handling remains in the driver, the existing rtnl_lock()
> is sufficient. Move frag_size handling out of spin_lock_irq_save() to keep
> the upcoming patch a pure refactoring without behavior changes.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index 918a32f8fda8..cfe5aea24549 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -1216,6 +1216,10 @@ static int stmmac_get_mm(struct net_device *ndev,
>  	if (!stmmac_fpe_supported(priv))
>  		return -EOPNOTSUPP;
>  
> +	state->rx_min_frag_size = ETH_ZLEN;
> +	frag_size = stmmac_fpe_get_add_frag_size(priv);
> +	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
> +
>  	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
>  
>  	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
> @@ -1224,7 +1228,6 @@ static int stmmac_get_mm(struct net_device *ndev,
>  	state->verify_time = priv->fpe_cfg.verify_time;
>  	state->tx_enabled = priv->fpe_cfg.tx_enabled;
>  	state->verify_status = priv->fpe_cfg.status;
> -	state->rx_min_frag_size = ETH_ZLEN;
>  
>  	/* FPE active if common tx_enabled and
>  	 * (verification success or disabled(forced))
> @@ -1236,9 +1239,6 @@ static int stmmac_get_mm(struct net_device *ndev,
>  	else
>  		state->tx_active = false;
>  
> -	frag_size = stmmac_fpe_get_add_frag_size(priv);
> -	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
> -
>  	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
>  
>  	return 0;
> @@ -1258,6 +1258,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
>  	if (err)
>  		return err;
>  
> +	stmmac_fpe_set_add_frag_size(priv, frag_size);
> +
>  	/* Wait for the verification that's currently in progress to finish */
>  	timer_shutdown_sync(&fpe_cfg->verify_timer);
>  
> @@ -1271,7 +1273,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
>  	if (!cfg->verify_enabled)
>  		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
>  
> -	stmmac_fpe_set_add_frag_size(priv, frag_size);
>  	stmmac_fpe_apply(priv);
>  
>  	spin_unlock_irqrestore(&fpe_cfg->lock, flags);

Reviewed-by: Furong Xu <0x1207 at gmail.com>



From 0x1207 at gmail.com  Wed Mar  5 18:20:37 2025
From: 0x1207 at gmail.com (Furong Xu)
Date: Thu, 6 Mar 2025 10:20:37 +0800
Subject: [PATCH net-next] net: stmmac: mostly remove "buf_sz"
In-Reply-To: <E1tpswn-005U6I-TU@rmk-PC.armlinux.org.uk>
References: <E1tpswn-005U6I-TU@rmk-PC.armlinux.org.uk>
Message-ID: <20250306102037.000007ab@gmail.com>

On Wed, 05 Mar 2025 17:54:21 +0000
"Russell King (Oracle)" <rmk+kernel at armlinux.org.uk> wrote:

> The "buf_sz" parameter is not used in the stmmac driver - there is one
> place where the value of buf_sz is validated, and two places where it
> is written. It is otherwise unused.
> 
> Remove these accesses. However, leave the module parameter in place as
> removing it could cause module load to fail, breaking user setups.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index cb5099caecd0..037039a9a33b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -101,6 +101,7 @@ static int tc = TC_DEFAULT;
>  module_param(tc, int, 0644);
>  MODULE_PARM_DESC(tc, "DMA threshold control value");
>  
> +/* This is unused */
>  #define	DEFAULT_BUFSIZE	1536
>  static int buf_sz = DEFAULT_BUFSIZE;
>  module_param(buf_sz, int, 0644);
> @@ -218,8 +219,6 @@ static void stmmac_verify_args(void)
>  {
>  	if (unlikely(watchdog < 0))
>  		watchdog = TX_TIMEO;
> -	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
> -		buf_sz = DEFAULT_BUFSIZE;
>  	if (unlikely((pause < 0) || (pause > 0xffff)))
>  		pause = PAUSE_TIME;
>  
> @@ -4018,7 +4017,6 @@ static int __stmmac_open(struct net_device *dev,
>  		}
>  	}
>  
> -	buf_sz = dma_conf->dma_buf_sz;
>  	for (int i = 0; i < MTL_MAX_TX_QUEUES; i++)
>  		if (priv->dma_conf.tx_queue[i].tbs & STMMAC_TBS_EN)
>  			dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs;
> @@ -7973,9 +7971,6 @@ static int __init stmmac_cmdline_opt(char *str)
>  		} else if (!strncmp(opt, "phyaddr:", 8)) {
>  			if (kstrtoint(opt + 8, 0, &phyaddr))
>  				goto err;
> -		} else if (!strncmp(opt, "buf_sz:", 7)) {
> -			if (kstrtoint(opt + 7, 0, &buf_sz))
> -				goto err;
>  		} else if (!strncmp(opt, "tc:", 3)) {
>  			if (kstrtoint(opt + 3, 0, &tc))
>  				goto err;

Reviewed-by: Furong Xu <0x1207 at gmail.com>



From 0x1207 at gmail.com  Wed Mar  5 18:21:07 2025
From: 0x1207 at gmail.com (Furong Xu)
Date: Thu, 6 Mar 2025 10:21:07 +0800
Subject: [PATCH net-next] net: stmmac: avoid shadowing global buf_sz
In-Reply-To: <E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk>
References: <E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk>
Message-ID: <20250306102107.00003c31@gmail.com>

On Wed, 05 Mar 2025 17:54:16 +0000
"Russell King (Oracle)" <rmk+kernel at armlinux.org.uk> wrote:

> stmmac_rx() declares a local variable named "buf_sz" but there is also
> a global variable for a module parameter which is called the same. To
> avoid confusion, rename the local variable.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 334d41b8fa70..cb5099caecd0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -5475,10 +5475,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
>  	struct sk_buff *skb = NULL;
>  	struct stmmac_xdp_buff ctx;
>  	int xdp_status = 0;
> -	int buf_sz;
> +	int bufsz;
>  
>  	dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
> -	buf_sz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
> +	bufsz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
>  	limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
>  
>  	if (netif_msg_rx_status(priv)) {
> @@ -5591,7 +5591,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
>  			net_prefetch(page_address(buf->page) +
>  				     buf->page_offset);
>  
> -			xdp_init_buff(&ctx.xdp, buf_sz, &rx_q->xdp_rxq);
> +			xdp_init_buff(&ctx.xdp, bufsz, &rx_q->xdp_rxq);
>  			xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
>  					 buf->page_offset, buf1_len, true);
>  

Reviewed-by: Furong Xu <0x1207 at gmail.com>



From victor.liu at nxp.com  Wed Mar  5 18:32:49 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Thu, 6 Mar 2025 10:32:49 +0800
Subject: [PATCH] drm/imx: legacy-bridge: fix inconsistent indenting
 warning
In-Reply-To: <20250305103042.3017-1-hanchunchao@inspur.com>
References: <20250305103042.3017-1-hanchunchao@inspur.com>
Message-ID: <62642284-ab9c-49fd-b682-6606850aa6c7@nxp.com>

On 03/05/2025, Charles Han wrote:
> Fix below inconsistent indenting smatch warning.
> smatch warnings:
> drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c:79 devm_imx_drm_legacy_bridge() warn: inconsistent indenting
> 
> Signed-off-by: Charles Han <hanchunchao at inspur.com>
> ---
>  drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Reviewed-by: Liu Ying <victor.liu at nxp.com>


From jiapeng.chong at linux.alibaba.com  Wed Mar  5 18:47:16 2025
From: jiapeng.chong at linux.alibaba.com (Jiapeng Chong)
Date: Thu,  6 Mar 2025 10:47:16 +0800
Subject: [PATCH -next] spi: stm32: Remove unnecessary print function dev_err()
Message-ID: <20250306024716.27856-1-jiapeng.chong@linux.alibaba.com>

The print function dev_err() is redundant because platform_get_irq()
already prints an error.

./drivers/spi/spi-stm32-ospi.c:798:2-9: line 798 is redundant because platform_get_irq() already prints an error.

Reported-by: Abaci Robot <abaci at linux.alibaba.com>
Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=19220
Signed-off-by: Jiapeng Chong <jiapeng.chong at linux.alibaba.com>
---
 drivers/spi/spi-stm32-ospi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index 8eadcb64f34a..114ebb1516d4 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -794,10 +794,8 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
 	}
 
 	ospi->irq = platform_get_irq(pdev, 0);
-	if (ospi->irq < 0) {
-		dev_err(dev, "Can't get irq %d\n", ospi->irq);
+	if (ospi->irq < 0)
 		return ospi->irq;
-	}
 
 	ret = devm_request_irq(dev, ospi->irq, stm32_ospi_irq, 0,
 			       dev_name(dev), ospi);
-- 
2.32.0.3.g01195cf9f



From kuba at kernel.org  Wed Mar  5 18:47:49 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Wed, 5 Mar 2025 18:47:49 -0800
Subject: [PATCH net-next 0/7] net: ethtool: Introduce ethnl dump helpers
In-Reply-To: <20250305180252.5a0ceb86@fedora.home>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
	<20250305180252.5a0ceb86@fedora.home>
Message-ID: <20250305184749.5519e7a9@kernel.org>

On Wed, 5 Mar 2025 18:02:52 +0100 Maxime Chevallier wrote:
> This series will very likely conflict with Stanislav's netdev lock
> work [2], I'll of course be happy to rebase should it get merged :)

Also this doesn't build. Please hold off on reposting for a couple of
days - because of the large conflict radius the previous few revisions
of the locking series haven't even gotten into the selftest CI queue :(


From menglong8.dong at gmail.com  Wed Mar  5 18:58:18 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Thu, 6 Mar 2025 10:58:18 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <20250305100306.4685333a@gandalf.local.home>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
 <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com> <20250305100306.4685333a@gandalf.local.home>
Message-ID: <CADxym3ZB_eQny=-aO4AwrHiwT264NXitdKwjRUYrnGJ2tH=Qwg@mail.gmail.com>

On Wed, Mar 5, 2025 at 11:02?PM Steven Rostedt <rostedt at goodmis.org> wrote:
>
> On Wed, 5 Mar 2025 09:19:09 +0800
> Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> > Ok, let me explain it from the beginning. (My English is not good,
> > but I'll try to describe it as clear as possible :/)
>
> I always appreciate those who struggle with English having these
> conversations. Thank you for that, as I know I am horrible in speaking any
> other language. (I can get by in German, but even Germans tell me to switch
> back to English ;-)
>
> >
> > Many BPF program types need to depend on the BPF trampoline,
> > such as BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_EXT,
> > BPF_PROG_TYPE_LSM, etc. BPF trampoline is a bridge between
> > the kernel (or bpf) function and BPF program, and it acts just like the
> > trampoline that ftrace uses.
> >
> > Generally speaking, it is used to hook a function, just like what ftrace
> > do:
> >
> > foo:
> >     endbr
> >     nop5  -->  call trampoline_foo
> >     xxxx
> >
> > In short, the trampoline_foo can be this:
> >
> > trampoline_foo:
> >     prepare a array and store the args of foo to the array
> >     call fentry_bpf1
> >     call fentry_bpf2
> >     ......
> >     call foo+4 (origin call)
>
> Note, I brought up this issue when I first heard about how BPF does this.
> The calling of the original function from the trampoline. I said this will
> cause issues, and is only good for a few functions. Once you start doing
> this for 1000s of functions, it's going to be a nightmare.
>
> Looks like you are now in the nightmare phase.
>
> My argument was once you have this case, you need to switch over to the
> kretprobe / function graph way of doing things, which is to have a shadow
> stack and hijack the return address. Yes, that has slightly more overhead,
> but it's better than having to add all theses hacks.
>
> And function graph has been updated so that it can do this for other users.
> fprobes uses it now, and bpf can too.

Yeah, I heard that the kretprobe is able to get the function
arguments too, which benefits from the function graph.

Besides the overhead, another problem is that we can't do
direct memory access if we use the BPF based on kretprobe.

>
> >     save the return value of foo
> >     call fexit_bpf1 (this bpf can get the return value of foo)
> >     call fexit_bpf2
> >     .......
> >     return to the caller of foo
> >
> > We can see that the trampoline_foo can be only used for
> > the function foo, as different kernel function can be attached
> > different BPF programs, and have different argument count,
> > etc. Therefore, we have to create 1000 BPF trampolines if
> > we want to attach a BPF program to 1000 kernel functions.
> >
> > The creation of the BPF trampoline is expensive. According to
> > my testing, It will spend more than 1 second to create 100 bpf
> > trampoline. What's more, it consumes more memory.
> >
> > If we have the per-function metadata supporting, then we can
> > create a global BPF trampoline, like this:
> >
> > trampoline_global:
> >     prepare a array and store the args of foo to the array
> >     get the metadata by the ip
> >     call metadata.fentry_bpf1
> >     call metadata.fentry_bpf2
> >     ....
> >     call foo+4 (origin call)
>
> So if this is a global trampoline, wouldn't this "call foo" need to be an
> indirect call? It can't be a direct call, otherwise you need a separate
> trampoline for that.
>
> This means you need to mitigate for spectre here, and you just lost the
> performance gain from not using function graph.

Yeah, you are right, this is an indirect call here. I haven't done
any research on mitigating for spectre yet, and maybe we can
convert it into a direct call somehow? Such as, we maintain a
trampoline_table:
    some preparation
    jmp +%eax (eax is the index of the target function)
    call foo1 + 4
    return
    call foo2 + 4
    return
    call foo3 + 4
    return

(Hmm......Is the jmp above also an indirect call?)

And in the trampoline_global, we can call it like this:

    mov metadata.index %eax
    call trampoline_table

I'm not sure if it works. However, indirect call is also used
in function graph, so we still have better performance. Isn't it?

Let me have a look at the code of the function graph first :/

Thanks!
Menglong Dong

>
>
> >     save the return value of foo
> >     call metadata.fexit_bpf1 (this bpf can get the return value of foo)
> >     call metadata.fexit_bpf2
> >     .......
> >     return to the caller of foo
> >
> > (The metadata holds more information for the global trampoline than
> > I described.)
> >
> > Then, we don't need to create a trampoline for every kernel function
> > anymore.
> >
> > Another beneficiary can be ftrace. For now, all the kernel functions that
> > are enabled by dynamic ftrace will be added to a filter hash if there are
> > more than one callbacks. And hash lookup will happen when the traced
> > functions are called, which has an impact on the performance, see
> > __ftrace_ops_list_func() -> ftrace_ops_test(). With the per-function
> > metadata supporting, we can store the information that if the callback is
> > enabled on the kernel function to the metadata, which can make the performance
> > much better.
>
> Let me say now that ftrace will not use this. Looks like too much work for
> little gain. The only time this impacts ftrace is when there's two
> different callbacks tracing the same function, and it only impacts that
> function. All other functions being traced still call the appropriate
> trampoline for the callback.
>
> -- Steve
>
> >
> > The per-function metadata storage is a basic function, and I think there
> > may be other functions that can use it for better performance in the feature
> > too.
> >
> > (Hope that I'm describing it clearly :/)
>


From patchwork-bot+netdevbpf at kernel.org  Wed Mar  5 19:20:34 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 06 Mar 2025 03:20:34 +0000
Subject: [PATCH net-next v3 0/8] net: phy: move PHY package code to its own
 source file
In-Reply-To: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
References: <5c5e60b3-0378-4960-8cf0-07ce0e219c68@gmail.com>
Message-ID: <174123123425.1112346.6998420178306205592.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Mon, 3 Mar 2025 21:13:05 +0100 you wrote:
> This series contributes to cleaning up phylib by moving PHY package
> related code to its own source file.
> 
> v2:
> - rename the getters
> - add a new header file phylib.h, which is used by PHY drivers only
> v3:
> - include phylib.h in bcm54140.c
> 
> [...]

Here is the summary with links:
  - [net-next,v3,1/8] net: phy: move PHY package code from phy_device.c to own source file
    https://git.kernel.org/netdev/net-next/c/61dc9cae8727
  - [net-next,v3,2/8] net: phy: add getters for public members in struct phy_package_shared
    https://git.kernel.org/netdev/net-next/c/2c8cd9783f46
  - [net-next,v3,3/8] net: phy: qca807x: use new phy_package_shared getters
    https://git.kernel.org/netdev/net-next/c/947030f3c32b
  - [net-next,v3,4/8] net: phy: micrel: use new phy_package_shared getters
    https://git.kernel.org/netdev/net-next/c/890fe6841d81
  - [net-next,v3,5/8] net: phy: mediatek: use new phy_package_shared getters
    https://git.kernel.org/netdev/net-next/c/dc5a6164feda
  - [net-next,v3,6/8] net: phy: mscc: use new phy_package_shared getters
    https://git.kernel.org/netdev/net-next/c/e0327e9f8597
  - [net-next,v3,7/8] net: phy: move PHY package related code from phy.h to phy_package.c
    https://git.kernel.org/netdev/net-next/c/e7f984e925d2
  - [net-next,v3,8/8] net: phy: remove remaining PHY package related definitions from phy.h
    https://git.kernel.org/netdev/net-next/c/a40028497769

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Wed Mar  5 19:20:35 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 06 Mar 2025 03:20:35 +0000
Subject: [PATCH net-next v9 0/6] Enable SGMII and 2500BASEX interface mode
 switching for Intel platforms
In-Reply-To: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
Message-ID: <174123123550.1112346.5967919465567432247.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Thu, 27 Feb 2025 20:15:16 +0800 you wrote:
> During the interface mode change, the 'phylink_major_config' function will
> be triggered in phylink. The modification of the following functions will
> support the switching between SGMII and 2500BASE-X interface modes for
> the Intel platform:
> 
> - xpcs_switch_interface_mode: Re-initiates clause 37 auto-negotiation for
>   the SGMII interface mode to perform auto-negotiation.
> - mac_finish: Configures the SerDes according to the interface mode.
> 
> [...]

Here is the summary with links:
  - [net-next,v9,1/6] net: phylink: use pl->link_interface in phylink_expects_phy()
    https://git.kernel.org/netdev/net-next/c/b63263555eaa
  - [net-next,v9,2/6] net: pcs: xpcs: re-initiate clause 37 Auto-negotiation
    https://git.kernel.org/netdev/net-next/c/065d3cef99a1
  - [net-next,v9,3/6] arch: x86: add IPC mailbox accessor function and add SoC register access
    https://git.kernel.org/netdev/net-next/c/7e2f7e25f6ff
  - [net-next,v9,4/6] net: stmmac: configure SerDes on mac_finish
    https://git.kernel.org/netdev/net-next/c/e654cfc718d4
  - [net-next,v9,5/6] net: stmmac: configure SerDes according to the interface mode
    https://git.kernel.org/netdev/net-next/c/a42f6b3f1cc1
  - [net-next,v9,6/6] net: stmmac: interface switching support for ADL-N platform
    https://git.kernel.org/netdev/net-next/c/7598ef621a43

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From kevin.tian at intel.com  Wed Mar  5 19:21:03 2025
From: kevin.tian at intel.com (Tian, Kevin)
Date: Thu, 6 Mar 2025 03:21:03 +0000
Subject: [PATCH] iommufd: Set domain->iommufd_hwpt in all hwpt->domain
 allocators
In-Reply-To: <20250305211800.229465-1-nicolinc@nvidia.com>
References: <20250305211800.229465-1-nicolinc@nvidia.com>
Message-ID: <BN9PR11MB52766B3F3ED1F7F14EA3B7B48CCA2@BN9PR11MB5276.namprd11.prod.outlook.com>

> From: Nicolin Chen <nicolinc at nvidia.com>
> Sent: Thursday, March 6, 2025 5:18 AM
> 
> Setting domain->iommufd_hwpt in iommufd_hwpt_alloc() only covers the
> HWPT
> allocations from user space, but not for an auto domain. This resulted in
> a NULL pointer access in the auto domain pathway:
>  Unable to handle kernel NULL pointer dereference at
>  	virtual address 0000000000000008
>  pc : iommufd_sw_msi+0x54/0x2b0
>  lr : iommufd_sw_msi+0x40/0x2b0
>  Call trace:
>   iommufd_sw_msi+0x54/0x2b0 (P)
>   iommu_dma_prepare_msi+0x64/0xa8
>   its_irq_domain_alloc+0xf0/0x2c0
>   irq_domain_alloc_irqs_parent+0x2c/0xa8
>   msi_domain_alloc+0xa0/0x1a8
> 
> Since iommufd_sw_msi() requires to access the domain->iommufd_hwpt, it
> is
> better to set that explicitly prior to calling iommu_domain_set_sw_msi().
> 
> Fixes: 748706d7ca06 ("iommu: Turn fault_data to iommufd private pointer")
> Reported-by: Ankit Agrawal <ankita at nvidia.com>
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>

Reviewed-by: Kevin Tian <kevin.tian at intel.com>


From patchwork-bot+netdevbpf at kernel.org  Wed Mar  5 19:30:31 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 06 Mar 2025 03:30:31 +0000
Subject: [PATCH net] net: dsa: mt7530: Fix traffic flooding for MMIO
 devices
In-Reply-To: <20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org>
References: <20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org>
Message-ID: <174123183127.1114452.4008171486418029850.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Tue, 04 Mar 2025 09:50:23 +0100 you wrote:
> On MMIO devices (e.g. MT7988 or EN7581) unicast traffic received on lanX
> port is flooded on all other user ports if the DSA switch is configured
> without VLAN support since PORT_MATRIX in PCR regs contains all user
> ports. Similar to MDIO devices (e.g. MT7530 and MT7531) fix the issue
> defining default VLAN-ID 0 for MT7530 MMIO devices.
> 
> Fixes: 110c18bfed414 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch")
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> 
> [...]

Here is the summary with links:
  - [net] net: dsa: mt7530: Fix traffic flooding for MMIO devices
    https://git.kernel.org/netdev/net/c/ccc2f5a436fb

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From anshuman.khandual at arm.com  Wed Mar  5 19:37:22 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Thu, 6 Mar 2025 09:07:22 +0530
Subject: [PATCH] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <0fe6f3b2-1011-4418-bc19-612a3b98c78d@arm.com>
References: <20250303041834.2796751-1-anshuman.khandual@arm.com>
 <0fe6f3b2-1011-4418-bc19-612a3b98c78d@arm.com>
Message-ID: <e0c2841b-3776-4d78-9514-b03ada39c739@arm.com>



On 3/4/25 21:51, Ryan Roberts wrote:
> On 03/03/2025 04:18, Anshuman Khandual wrote:
>> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
>> section mapping at all page table levels except the last level. This works
>> fine as the section mapping masks are exactly the same (0x1UL) for all page
>> table levels.
>>
>> This will change in the future with D128 page tables that have unique skip
>> level values (SKL) required for creating section mapping at different page
>> table levels. Hence use page table level specific section mapping macros
>> instead of the common PMD_TYPE_SECT.
>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: linux-kernel at vger.kernel.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>> This patch applies on 6.14-rc5
>>
>> PGD_TYPE_SECT for level -1 section map handling has been added for 4K
>> base pages with 52 bit VA configuration that has 5 page table levels.
>> In such cases (CONFIG_PGTABLE_LEVELS = 5) early_map_kernel() can call
>> map_range() eventually with -1 (i.e 4 - CONFIG_PGTABLE_LEVELS) as the
>> root_level.
> 
> Table Table D8-16 on page D8-6459 of ARM DDI 0487 L.a says that block mappings
> at level -1 are not permitted for 4K pages; only levels 0-3 support leaf
> mappings. Similarly for 16K, table D8-26 says only levels 1-3 permit leaf
> mappings. And for 64K, table D8-35 says only levels 1-3 permit leaf mappings.

Then seems like the current code is actually wrong because PMD_TYPE_SECT
is being set at all levels (except level 3) regardless of the configured
page size ?

> 
> So I don't think PGD_TYPE_SECT is the right solution. Perhaps we need to
> explicitly force the unsupported levels to be table entries even if the
> alignment is correct?

Just wondering - something like the following will work instead ? Tested
on both 4K and 64K page sizes.

--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -26,6 +26,21 @@
  * @va_offset:         Offset between a physical page and its current mapping
  *                     in the VA space
  */
+static bool sect_supported(int level)
+{
+       switch(level) {
+       case -1:
+               return false;
+       case 0:
+               if(IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
+                  IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+                       return false;
+               fallthrough;
+       default:
+               return true;
+       }
+}
+
 void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
                      int level, pte_t *tbl, bool may_use_cont, u64 va_offset)
 {
@@ -44,13 +59,30 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
         * Set the right block/page bits for this level unless we are
         * clearing the mapping
         */
-       if (protval)
-               protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
+       if (protval && sect_supported(level)) {
+               switch (level) {
+               case 3:
+                       protval |= PTE_TYPE_PAGE;
+                       break;
+               case 2:
+                       protval |= PMD_TYPE_SECT;
+                       break;
+               case 1:
+                       protval |= PUD_TYPE_SECT;
+                       break;
+               case 0:
+                       protval |= P4D_TYPE_SECT;
+                       break;
+               default:
+                       break;
+               }
+       }
 
        while (start < end) {
                u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
 
-               if (level < 3 && (start | next | pa) & lmask) {
+               if ((level < 3 && (start | next | pa) & lmask) ||
+                    !sect_supported(level)){
                        /*
                         * This chunk needs a finer grained mapping. Create a
                         * table mapping if necessary and recurse.

> 
> Thanks,
> Ryan
> 
>>
>>  arch/arm64/include/asm/pgtable-hwdef.h |  1 +
>>  arch/arm64/kernel/pi/map_range.c       | 23 +++++++++++++++++++++--
>>  2 files changed, 22 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
>> index a9136cc551cc..fd0a82e8878c 100644
>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>> @@ -99,6 +99,7 @@
>>  #define PGD_TYPE_TABLE		(_AT(pgdval_t, 3) << 0)
>>  #define PGD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
>>  #define PGD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
>> +#define PGD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
>>  #define PGD_TABLE_AF		(_AT(pgdval_t, 1) << 10)	/* Ignored if no FEAT_HAFT */
>>  #define PGD_TABLE_PXN		(_AT(pgdval_t, 1) << 59)
>>  #define PGD_TABLE_UXN		(_AT(pgdval_t, 1) << 60)
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 2b69e3beeef8..9ea869f5745f 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -44,8 +44,27 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>  	 * Set the right block/page bits for this level unless we are
>>  	 * clearing the mapping
>>  	 */
>> -	if (protval)
>> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
>> +	if (protval) {
>> +		switch (level) {
>> +		case 3:
>> +			protval |= PTE_TYPE_PAGE;
>> +			break;
>> +		case 2:
>> +			protval |= PMD_TYPE_SECT;
>> +			break;
>> +		case 1:
>> +			protval |= PUD_TYPE_SECT;
>> +			break;
>> +		case 0:
>> +			protval |= P4D_TYPE_SECT;
>> +			break;
>> +		case -1:
>> +			protval |= PGD_TYPE_SECT;
>> +			break;
>> +		default:
>> +			break;
>> +		}
>> +	}
>>  
>>  	while (start < end) {
>>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
> 


From alexei.starovoitov at gmail.com  Wed Mar  5 19:39:20 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Wed, 5 Mar 2025 19:39:20 -0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3ZB_eQny=-aO4AwrHiwT264NXitdKwjRUYrnGJ2tH=Qwg@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
 <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
 <20250305100306.4685333a@gandalf.local.home> <CADxym3ZB_eQny=-aO4AwrHiwT264NXitdKwjRUYrnGJ2tH=Qwg@mail.gmail.com>
Message-ID: <CAADnVQJ0_+Hij=kf9eVPX_ZND=2=uDHaYPWvv1x-WmR5sZRSmA@mail.gmail.com>

On Wed, Mar 5, 2025 at 6:59?PM Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> I'm not sure if it works. However, indirect call is also used
> in function graph, so we still have better performance. Isn't it?
>
> Let me have a look at the code of the function graph first :/

Menglong,

Function graph infra isn't going to help.
"call foo" isn't a problem either.

But we have to step back.
per-function metadata is an optimization and feels like
we're doing a premature optimization here without collecting
performance numbers first.

Let's implement multi-fentry with generic get_metadata_by_ip() first.
get_metadata_by_ip() will be a hashtable in such a case and
then we can compare its performance when it's implemented as
a direct lookup from ip-4 (this patch) vs hash table
(that does 'ip' to 'metadata' lookup).

If/when we decide to do this per-function metadata we can also
punt to generic hashtable for cfi, IBT, FineIBT, etc configs.
When mitigations are enabled the performance suffers anyway,
so hashtable lookup vs direct ip-4 lookup won't make much difference.
So we can enable per-function metadata only on non-mitigation configs
when FUNCTION_ALIGNMENT=16.
There will be some number of bytes available before every function
and if we can tell gcc/llvm to leave at least 5 bytes there
the growth of vmlinux .text will be within a noise.

So let's figure out the design of multi-fenty first with a hashtable
for metadata and decide next steps afterwards.


From swathi.ks at samsung.com  Wed Mar  5 19:40:49 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Thu, 6 Mar 2025 09:10:49 +0530
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <89dcfb2a-d093-48f9-b6d7-af99b383a1bc@kernel.org>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
	<20250305091246.106626-2-swathi.ks@samsung.com>
	<89dcfb2a-d093-48f9-b6d7-af99b383a1bc@kernel.org>
Message-ID: <00e301db8e49$95bfbf90$c13f3eb0$@samsung.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: 05 March 2025 21:12
> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> conor+dt at kernel.org; richardcochran at gmail.com;
> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> gost.dev at samsung.com
> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
> bindings
> 
> On 05/03/2025 10:12, Swathi K S wrote:
> > Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
> > Ethernet YAML schema to enable the DT validation.
> >
> > Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> > Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> > Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> 
> <form letter>
> This is a friendly reminder during the review process.
> 
> It looks like you received a tag and forgot to add it.
> 
> If you do not know the process, here is a short explanation:
> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
> versions of patchset, under or above your Signed-off-by tag, unless patch
> changed significantly (e.g. new properties added to the DT bindings). Tag is
> "received", when provided in a message replied to you on the mailing list.
> Tools like b4 can help here. However, there's no need to repost patches
> *only* to add the tags. The upstream maintainer will do that for tags
> received on the version they apply.
> 
> Please read:
> https://protect2.fireeye.com/v1/url?k=19972162-781c345b-1996aa2d-
> 000babffae10-7bd6b1a1d78b210b&q=1&e=94dcc3a6-5303-441a-8c1e-
> de696b216f86&u=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv6.12-
> rc3%2Fsource%2FDocumentation%2Fprocess%2Fsubmitting-
> patches.rst%23L577
> 
> If a tag was not added on purpose, please state why and what changed.

Hi Krzysztof, 
As per a review comment received from Russell, I had added 2 new properties to the DT - assigned-clocks and assigned-clock-parents properties. 
The example in the DT binding reflects the same.
I felt it wouldn't be fair to add 'Reviewed-by' tag without you reviewing the updates again.
But I should have mentioned that in cover letter and apologies for missing to do that.

- Swathi

> </form letter>
> 
> Best regards,
> Krzysztof



From swathi.ks at samsung.com  Wed Mar  5 19:48:34 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Thu, 6 Mar 2025 09:18:34 +0530
Subject: [PATCH v7 1/2] arm64: dts: fsd: Add Ethernet support for FSYS0
 Block of FSD SoC
In-Reply-To: <7328e538-31cf-4674-83d2-943f1a2d1455@kernel.org>
References: <20250220073527.22233-1-swathi.ks@samsung.com>
	<CGME20250220073944epcas5p495ee305ca577a7e1be51ff916f20fc53@epcas5p4.samsung.com>
	<20250220073527.22233-2-swathi.ks@samsung.com>
	<7328e538-31cf-4674-83d2-943f1a2d1455@kernel.org>
Message-ID: <00e801db8e4a$b7c2e990$2748bcb0$@samsung.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: 01 March 2025 19:29
> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org; linux-
> fsd at tesla.com; robh at kernel.org; conor+dt at kernel.org;
> richardcochran at gmail.com; alim.akhtar at samsung.com
> Cc: jayati.sahu at samsung.com; linux-arm-kernel at lists.infradead.org; linux-
> samsung-soc at vger.kernel.org; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org; netdev at vger.kernel.org;
> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> gost.dev at samsung.com
> Subject: Re: [PATCH v7 1/2] arm64: dts: fsd: Add Ethernet support for FSYS0
> Block of FSD SoC
> 
> On 20/02/2025 08:35, Swathi K S wrote:
> >  &pinctrl_peric {
> > diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi
> > b/arch/arm64/boot/dts/tesla/fsd.dtsi
> > index 690b4ed9c29b..01850fbf761f 100644
> > --- a/arch/arm64/boot/dts/tesla/fsd.dtsi
> > +++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
> > @@ -1007,6 +1007,26 @@
> >  			clocks = <&clock_fsys0
> UFS0_MPHY_REFCLK_IXTAL26>;
> >  			clock-names = "ref_clk";
> >  		};
> > +
> > +		ethernet0: ethernet at 15300000 {
> > +			compatible = "tesla,fsd-ethqos";
> 
> I don't see bindings in the linux-next, so I am dropping this patch from my
> queue. Please resend when the bindings hit the linux-next.

Thanks for informing me.
I have posted v8 of DT bindings: https://lore.kernel.org/netdev/89dcfb2a-d093-48f9-b6d7-af99b383a1bc at kernel.org/
Will wait for some time for the DT binding to reflect on linux-next before posting v8 patches of DT files.

- Swathi

> 
> Best regards,
> Krzysztof



From lkp at intel.com  Wed Mar  5 20:24:46 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 12:24:46 +0800
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <20250305100134.1171124-1-manikandan.m@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
Message-ID: <202503061244.wH2sylN8-lkp@intel.com>

Hi Manikandan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mtd/spi-nor/next]
[also build test WARNING on robh/for-next abelloni/rtc-next linus/master v6.14-rc5 next-20250305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Manikandan-Muralidharan/ARM-dts-microchip-sama5d29_curiosity-Add-nvmem-layout-in-QSPI-to-describe-EUI48-MAC-address-region/20250305-180433
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git spi-nor/next
patch link:    https://lore.kernel.org/r/20250305100134.1171124-1-manikandan.m%40microchip.com
patch subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM framework to read MAC Address
config: m68k-stmark2_defconfig (https://download.01.org/0day-ci/archive/20250306/202503061244.wH2sylN8-lkp at intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250306/202503061244.wH2sylN8-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503061244.wH2sylN8-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/mtd/spi-nor/sst.c:75: warning: Function parameter or struct member 'off' not described in 'sst26vf_sfdp_mac_addr_read'
>> drivers/mtd/spi-nor/sst.c:75: warning: Excess function parameter 'offset' description in 'sst26vf_sfdp_mac_addr_read'


vim +75 drivers/mtd/spi-nor/sst.c

    61	
    62	/**
    63	 * sst26vf_sfdp_mac_addr_read() - check if the EUI-48 MAC Address is programmed
    64	 * and read the data from the prestored SFDP data
    65	 *
    66	 * @priv: User context passed to read callbacks.
    67	 * @offset: Offset within the NVMEM device.
    68	 * @val: pointer where to fill the ethernet address
    69	 * @bytes: Length of the NVMEM cell
    70	 *
    71	 * Return: 0 on success, -EINVAL  otherwise.
    72	 */
    73	static int sst26vf_sfdp_mac_addr_read(void *priv, unsigned int off,
    74					      void *val, size_t bytes)
  > 75	{
    76		struct spi_nor *nor = priv;
    77		struct sfdp *sfdp = nor->sfdp;
    78		loff_t offset = off;
    79		size_t sfdp_size;
    80	
    81		/*
    82		 * Check if the EUI-48 MAC address is programmed in the next six address
    83		 * locations.
    84		 * @off is programmed in the DT and stores the start of MAC Address
    85		 * byte, (off - 1) stores the bit length of the Extended Unique
    86		 * Identifier
    87		 */
    88		if (SST26VF_SFDP_EUI48 != *((u8 *)sfdp->dwords + (offset - 1)))
    89			return -EINVAL;
    90	
    91		sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords);
    92		memory_read_from_buffer(val, bytes, &offset, sfdp->dwords,
    93					sfdp_size);
    94		return 0;
    95	}
    96	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From vulab at iscas.ac.cn  Wed Mar  5 20:27:20 2025
From: vulab at iscas.ac.cn (Wentao Liang)
Date: Thu,  6 Mar 2025 12:27:20 +0800
Subject: [PATCH] drm/exynos/vidi: Remove redundant error handling in vidi_get_modes()
Message-ID: <20250306042720.2296-1-vulab@iscas.ac.cn>

In the?vidi_get_modes()?function, if either?drm_edid_dup()?or?
drm_edid_alloc()?fails, the function will immediately return 0,
indicating that no display modes can be retrieved. However, in
the event of failure in these two functions, it is still necessary
to call the subsequent?drm_edid_connector_update()?function with
a NULL?drm_edid?as an argument. This ensures that operations such
as connector settings are performed in its callee function,?
_drm_edid_connector_property_update. To maintain the integrity of
the operation, redundant error handling needs to be removed.

Signed-off-by: Wentao Liang <vulab at iscas.ac.cn>
---
 drivers/gpu/drm/exynos/exynos_drm_vidi.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index fd388b1dbe68..a956cdb2f33a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -312,9 +312,6 @@ static int vidi_get_modes(struct drm_connector *connector)
 	else
 		drm_edid = drm_edid_alloc(fake_edid_info, sizeof(fake_edid_info));
 
-	if (!drm_edid)
-		return 0;
-
 	drm_edid_connector_update(connector, drm_edid);
 
 	count = drm_edid_connector_add_modes(connector);
-- 
2.42.0.windows.2



From lkp at intel.com  Wed Mar  5 21:08:16 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 13:08:16 +0800
Subject: [PATCH v3 04/11] arm64/mm: Refactor __set_ptes() and
 __ptep_get_and_clear()
In-Reply-To: <20250304150444.3788920-5-ryan.roberts@arm.com>
References: <20250304150444.3788920-5-ryan.roberts@arm.com>
Message-ID: <202503061237.QurSXHSC-lkp@intel.com>

Hi Ryan,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.14-rc5 next-20250305]
[cannot apply to arm64/for-next/core akpm-mm/mm-everything arm-perf/for-next/perf]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Roberts/arm64-hugetlb-Cleanup-huge_pte-size-discovery-mechanisms/20250304-230647
base:   linus/master
patch link:    https://lore.kernel.org/r/20250304150444.3788920-5-ryan.roberts%40arm.com
patch subject: [PATCH v3 04/11] arm64/mm: Refactor __set_ptes() and __ptep_get_and_clear()
config: arm64-randconfig-001-20250305 (https://download.01.org/0day-ci/archive/20250306/202503061237.QurSXHSC-lkp at intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250306/202503061237.QurSXHSC-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503061237.QurSXHSC-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from arch/arm64/kernel/asm-offsets.c:12:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/arm64/include/asm/hardirq.h:17:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:14:
   In file included from arch/arm64/include/asm/io.h:12:
   In file included from include/linux/pgtable.h:6:
>> arch/arm64/include/asm/pgtable.h:639:7: error: duplicate case value '536870912'
           case PUD_SIZE:
                ^
   include/asm-generic/pgtable-nopud.h:20:20: note: expanded from macro 'PUD_SIZE'
   #define PUD_SIZE        (1UL << PUD_SHIFT)
                           ^
   arch/arm64/include/asm/pgtable.h:636:7: note: previous case defined here
           case PMD_SIZE:
                ^
   include/asm-generic/pgtable-nopmd.h:22:20: note: expanded from macro 'PMD_SIZE'
   #define PMD_SIZE        (1UL << PMD_SHIFT)
                           ^
   In file included from arch/arm64/kernel/asm-offsets.c:12:
   In file included from include/linux/ftrace.h:10:
   In file included from include/linux/trace_recursion.h:5:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/arm64/include/asm/hardirq.h:17:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:14:
   In file included from arch/arm64/include/asm/io.h:12:
   In file included from include/linux/pgtable.h:6:
   arch/arm64/include/asm/pgtable.h:1303:7: error: duplicate case value '536870912'
           case PUD_SIZE:
                ^
   include/asm-generic/pgtable-nopud.h:20:20: note: expanded from macro 'PUD_SIZE'
   #define PUD_SIZE        (1UL << PUD_SHIFT)
                           ^
   arch/arm64/include/asm/pgtable.h:1300:7: note: previous case defined here
           case PMD_SIZE:
                ^
   include/asm-generic/pgtable-nopmd.h:22:20: note: expanded from macro 'PMD_SIZE'
   #define PMD_SIZE        (1UL << PMD_SHIFT)
                           ^
   2 errors generated.
   make[3]: *** [scripts/Makefile.build:102: arch/arm64/kernel/asm-offsets.s] Error 1 shuffle=4064171735
   make[3]: Target 'prepare' not remade because of errors.
   make[2]: *** [Makefile:1264: prepare0] Error 2 shuffle=4064171735
   make[2]: Target 'prepare' not remade because of errors.
   make[1]: *** [Makefile:251: __sub-make] Error 2 shuffle=4064171735
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:251: __sub-make] Error 2 shuffle=4064171735
   make: Target 'prepare' not remade because of errors.


vim +/536870912 +639 arch/arm64/include/asm/pgtable.h

   626	
   627	static inline void set_ptes_anysz(struct mm_struct *mm, pte_t *ptep, pte_t pte,
   628					  unsigned int nr, unsigned long pgsize)
   629	{
   630		unsigned long stride = pgsize >> PAGE_SHIFT;
   631	
   632		switch (pgsize) {
   633		case PAGE_SIZE:
   634			page_table_check_ptes_set(mm, ptep, pte, nr);
   635			break;
   636		case PMD_SIZE:
   637			page_table_check_pmds_set(mm, (pmd_t *)ptep, pte_pmd(pte), nr);
   638			break;
 > 639		case PUD_SIZE:
   640			page_table_check_puds_set(mm, (pud_t *)ptep, pte_pud(pte), nr);
   641			break;
   642		default:
   643			VM_WARN_ON(1);
   644		}
   645	
   646		__sync_cache_and_tags(pte, nr * stride);
   647	
   648		for (;;) {
   649			__check_safe_pte_update(mm, ptep, pte);
   650			__set_pte(ptep, pte);
   651			if (--nr == 0)
   652				break;
   653			ptep++;
   654			pte = pte_advance_pfn(pte, stride);
   655		}
   656	}
   657	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From peng.fan at nxp.com  Wed Mar  5 21:31:04 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Thu, 6 Mar 2025 05:31:04 +0000
Subject: [PATCH v4 3/8] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250305100037.373782-4-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-4-daniel.baluta@nxp.com>
Message-ID: <PAXPR04MB845952FE7669DE5B363C906E88CA2@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: [PATCH v4 3/8] arm64: dts: imx8mp: Use resets property
> 
> Add resets property to dsp node in order to be able to control the dsp
> run/stall bit from audio block control.
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
Reviewed-by: Peng Fan <peng.fan at nxp.com>


From shengjiu.wang at nxp.com  Wed Mar  5 21:31:38 2025
From: shengjiu.wang at nxp.com (Shengjiu Wang)
Date: Thu,  6 Mar 2025 13:31:38 +0800
Subject: [PATCH] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph port
Message-ID: <20250306053138.1914956-1-shengjiu.wang@nxp.com>

This device can be used in conjunction with audio-graph-card to provide
an endpoint for binding with the other side of the audio link.

Signed-off-by: Shengjiu Wang <shengjiu.wang at nxp.com>
---
 .../devicetree/bindings/sound/fsl,imx-asrc.yaml      | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
index abac5084d63b..85799f83e65f 100644
--- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
@@ -77,6 +77,10 @@ properties:
   power-domains:
     maxItems: 1
 
+  port:
+    $ref: audio-graph-port.yaml#
+    unevaluatedProperties: false
+
   fsl,asrc-rate:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: The mutual sample rate used by DPCM Back Ends
@@ -174,4 +178,12 @@ examples:
                     "txa", "txb", "txc";
         fsl,asrc-rate  = <48000>;
         fsl,asrc-width = <16>;
+
+        port {
+            playback-only;
+
+            asrc_endpoint: endpoint {
+                remote-endpoint = <&fe00_ep>;
+            };
+       };
     };
-- 
2.34.1



From peng.fan at nxp.com  Wed Mar  5 21:31:51 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Thu, 6 Mar 2025 05:31:51 +0000
Subject: [PATCH v4 7/8] reset: imx8mp-audiomix: Add support for DSP
 run/stall
In-Reply-To: <20250305100037.373782-8-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-8-daniel.baluta@nxp.com>
Message-ID: <PAXPR04MB8459A76403E76253B3D4010F88CA2@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: [PATCH v4 7/8] reset: imx8mp-audiomix: Add support for DSP
> run/stall
> 
> We can Run/Stall the DSP via audio block control bits found in
> audiomix.
> Implement this functionality using the reset controller and use assert
> for Stall and deassert for Run.
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>

Reviewed-by: Peng Fan <peng.fan at nxp.com>



From wbg at kernel.org  Wed Mar  5 21:49:14 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu, 6 Mar 2025 14:49:14 +0900
Subject: [PATCH v7 1/2] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <20250304155156.374150-2-csokas.bence@prolan.hu>
References: <20250304155156.374150-1-csokas.bence@prolan.hu>
 <20250304155156.374150-2-csokas.bence@prolan.hu>
Message-ID: <Z8k3WlJHCrYPdW4j@ishi>

On Tue, Mar 04, 2025 at 04:51:51PM +0100, Bence Cs?k?s wrote:
> Add interrupt servicing to allow userspace to wait for the following:
> * Change-of-state caused by external trigger
> * Capture of timer value into RA/RB
> * Compare to RC register
> * Overflow
> 
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>

Hi Bence,

I'm mostly statisfied with this patch now, but I have one minor
suggestion below.

> @@ -27,6 +33,7 @@ struct mchp_tc_data {
>  	int qdec_mode;
>  	int num_channels;
>  	int channel[2];
> +	int irq;

We don't use the irq member during the driver operation, so I don't
think this value needs to be saved here with the driver data. It seems
to only be needed in mchp_tc_irq_enable() for devm_request_irq().
Perhaps you can pass the irq value as a parameter to
mchp_tc_irq_enable() instead.

With that change made, I think I'll be ready to pick up this patchset
and merge it into counter-next.

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/ba7e4415/attachment.sig>

From peng.fan at nxp.com  Wed Mar  5 21:31:30 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Thu, 6 Mar 2025 05:31:30 +0000
Subject: [PATCH v4 5/8] reset: imx8mp-audiomix: Prepare the code for more
 reset bits
In-Reply-To: <20250305100037.373782-6-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-6-daniel.baluta@nxp.com>
Message-ID: <PAXPR04MB8459C23CCFB582614905FEED88CA2@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: [PATCH v4 5/8] reset: imx8mp-audiomix: Prepare the code for
> more reset bits
> 
> Current code supports EARC PHY Software Reset and EARC Software
> Reset but it is not easily extensible to more reset bits.
> 
> So, refactor the code in order to easily allow more reset bits in the
> future.
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>

Reviewed-by: Peng Fan <peng.fan at nxp.com>

> ---


From wbg at kernel.org  Wed Mar  5 21:51:00 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu, 6 Mar 2025 14:51:00 +0900
Subject: [PATCH v7 2/2] counter: microchip-tcb-capture: Add capture
 extensions for registers RA/RB
In-Reply-To: <20250304155156.374150-3-csokas.bence@prolan.hu>
References: <20250304155156.374150-1-csokas.bence@prolan.hu>
 <20250304155156.374150-3-csokas.bence@prolan.hu>
Message-ID: <Z8k3xLaR2c1IR9uu@ishi>

On Tue, Mar 04, 2025 at 04:51:52PM +0100, Bence Cs?k?s wrote:
> TCB hardware is capable of capturing the timer value to registers RA and
> RB. Add these registers as capture extensions.
> 
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>

I'm putting my Acked-by line here to be a remainder for myself in the
next revision that this patch is fine and I already reviewed it.

Acked-by: William Breathitt Gray <wbg at kernel.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/25c9ef42/attachment.sig>

From ping.bai at nxp.com  Wed Mar  5 22:18:05 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu,  6 Mar 2025 14:18:05 +0800
Subject: [PATCH v3] cpuidle: psci: Init cpuidle only for present CPUs
Message-ID: <20250306061805.2318154-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpuidle
in the PSCI cpuidle driver.

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, leading
to the failure:

  |  Failed to register cpuidle device for cpu1

Change for_each_possible_cpu() to for_each_present_cpu() in the
PSCI cpuidle driver to ensure it only registers cpuidle devices
for CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Reviewed-by: Dhruva Gole <d-gole at ti.com>
Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v2 changes:
  - Improve the changelog as suggested by Sudeep
---
 drivers/cpuidle/cpuidle-psci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 2562dc001fc1..00117e9b33e8 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -410,7 +410,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = psci_idle_init_cpu(&pdev->dev, cpu);
 		if (ret)
 			goto out_fail;
-- 
2.34.1



From andyshrk at 163.com  Wed Mar  5 22:59:51 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu,  6 Mar 2025 14:59:51 +0800
Subject: [PATCH] phy: rockchip: usbdp: Check these parameters only when the corresponding set flags are set
Message-ID: <20250306065952.485809-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

According documentation of phy_configure_opts_dp, at the configure
stage, we should only verify/configure the link_rate when set_rate
flag is set, the same applies to lanes and voltage.

So we do it as the documentation says, also record the link rate
and lanes in phy internal for set_voltate stage.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 drivers/phy/rockchip/phy-rockchip-usbdp.c | 63 +++++++++++------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index c04cf64f8a35..d1bbdf382aa2 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -187,6 +187,8 @@ struct rk_udphy {
 	u32 dp_aux_din_sel;
 	bool dp_sink_hpd_sel;
 	bool dp_sink_hpd_cfg;
+	unsigned int link_rate;
+	unsigned int lanes;
 	u8 bw;
 	int id;
 
@@ -1102,42 +1104,39 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
 	return 0;
 }
 
-static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
-{
-	switch (link_rate) {
-	case 1620:
-	case 2700:
-	case 5400:
-	case 8100:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
 					 struct phy_configure_opts_dp *dp)
 {
-	int i, ret;
+	int i;
 
-	/* If changing link rate was required, verify it's supported. */
-	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
-	if (ret)
-		return ret;
+	/* Verify link rate. */
+	if (dp->set_rate) {
+		switch (dp->link_rate) {
+		case 1620:
+		case 2700:
+		case 5400:
+		case 8100:
+			udphy->link_rate = dp->link_rate;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
 
 	/* Verify lane count. */
-	switch (dp->lanes) {
-	case 1:
-	case 2:
-	case 4:
-		/* valid lane count. */
-		break;
+	if (dp->set_lanes) {
+		switch (dp->lanes) {
+		case 1:
+		case 2:
+		case 4:
+			/* valid lane count. */
+			udphy->lanes = dp->lanes;
+			break;
 
-	default:
-		return -EINVAL;
+		default:
+			return -EINVAL;
+		}
 	}
 
 	/*
@@ -1146,7 +1145,7 @@ static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
 	 */
 	if (dp->set_voltages) {
 		/* Lane count verified previously. */
-		for (i = 0; i < dp->lanes; i++) {
+		for (i = 0; i < udphy->lanes; i++) {
 			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
 				return -EINVAL;
 
@@ -1243,9 +1242,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
 	}
 
 	if (dp->set_voltages) {
-		for (i = 0; i < dp->lanes; i++) {
+		for (i = 0; i < udphy->lanes; i++) {
 			lane = udphy->dp_lane_sel[i];
-			switch (dp->link_rate) {
+			switch (udphy->link_rate) {
 			case 1620:
 			case 2700:
 				regmap_update_bits(udphy->pma_regmap,
-- 
2.34.1



From wbg at kernel.org  Wed Mar  5 23:05:44 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu, 06 Mar 2025 16:05:44 +0900
Subject: [PATCH 2/2] counter: microchip-tcb-capture: Add support for RC
 Compare
In-Reply-To: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
References: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
Message-ID: <20250306-introduce-compare-component-v1-2-93993b3dca9c@kernel.org>

In Capture mode, the RC register serves as a compare register for the
Timer Counter Channel. When a the Counter Value reaches the RC value, a
RC Compare event occurs (COUNTER_EVENT_THRESHOLD). This patch exposes
the RC register to userspace as the 'compare' Count extension, thus
allowing users to configure the threshold condition for these events.

Signed-off-by: William Breathitt Gray <wbg at kernel.org>
---
 drivers/counter/microchip-tcb-capture.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 2f096a5b973d18edf5de5a2b33f2f72571deefb7..e32f8d324cb373909e0a093b14d742fa0a93e07e 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -247,6 +247,37 @@ static int mchp_tc_count_read(struct counter_device *counter,
 	return 0;
 }
 
+static int mchp_tc_count_compare_read(struct counter_device *counter, struct counter_count *count,
+				      u64 *val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	u32 cnt;
+	int ret;
+
+	ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), &cnt);
+	if (ret < 0)
+		return ret;
+
+	*val = cnt;
+
+	return 0;
+}
+
+static int mchp_tc_count_compare_write(struct counter_device *counter, struct counter_count *count,
+				       u64 val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+
+	if (val > U32_MAX)
+		return -ERANGE;
+
+	return regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), val);
+}
+
+static struct counter_comp mchp_tc_count_ext[] = {
+	COUNTER_COMP_COMPARE(mchp_tc_count_compare_read, mchp_tc_count_compare_write),
+};
+
 static struct counter_count mchp_tc_counts[] = {
 	{
 		.id = 0,
@@ -255,6 +286,8 @@ static struct counter_count mchp_tc_counts[] = {
 		.num_functions = ARRAY_SIZE(mchp_tc_count_functions),
 		.synapses = mchp_tc_count_synapses,
 		.num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
+		.ext = mchp_tc_count_ext,
+		.num_ext = ARRAY_SIZE(mchp_tc_count_ext),
 	},
 };
 

-- 
2.48.1



From krzk at kernel.org  Wed Mar  5 23:05:23 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:05:23 +0100
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <00e301db8e49$95bfbf90$c13f3eb0$@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
 <20250305091246.106626-2-swathi.ks@samsung.com>
 <89dcfb2a-d093-48f9-b6d7-af99b383a1bc@kernel.org>
 <00e301db8e49$95bfbf90$c13f3eb0$@samsung.com>
Message-ID: <a9ddeccf-8fc6-453c-af62-55e895888a77@kernel.org>

On 06/03/2025 04:40, Swathi K S wrote:
> 
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: 05 March 2025 21:12
>> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
>> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
>> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
>> conor+dt at kernel.org; richardcochran at gmail.com;
>> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
>> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
>> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
>> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
>> gost.dev at samsung.com
>> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
>> bindings
>>
>> On 05/03/2025 10:12, Swathi K S wrote:
>>> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
>>> Ethernet YAML schema to enable the DT validation.
>>>
>>> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
>>> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
>>> Signed-off-by: Swathi K S <swathi.ks at samsung.com>
>>
>> <form letter>
>> This is a friendly reminder during the review process.
>>
>> It looks like you received a tag and forgot to add it.
>>
>> If you do not know the process, here is a short explanation:
>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
>> versions of patchset, under or above your Signed-off-by tag, unless patch
>> changed significantly (e.g. new properties added to the DT bindings). Tag is
>> "received", when provided in a message replied to you on the mailing list.
>> Tools like b4 can help here. However, there's no need to repost patches
>> *only* to add the tags. The upstream maintainer will do that for tags
>> received on the version they apply.
>>
>> Please read:
>> https://protect2.fireeye.com/v1/url?k=19972162-781c345b-1996aa2d-
>> 000babffae10-7bd6b1a1d78b210b&q=1&e=94dcc3a6-5303-441a-8c1e-
>> de696b216f86&u=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv6.12-
>> rc3%2Fsource%2FDocumentation%2Fprocess%2Fsubmitting-
>> patches.rst%23L577
>>
>> If a tag was not added on purpose, please state why and what changed.
> 
> Hi Krzysztof, 
> As per a review comment received from Russell, I had added 2 new properties to the DT - assigned-clocks and assigned-clock-parents properties. 
> The example in the DT binding reflects the same.
> I felt it wouldn't be fair to add 'Reviewed-by' tag without you reviewing the updates again.
> But I should have mentioned that in cover letter and apologies for missing to do that.
Nothing in changelog explained new properties. Nothing mentioned
dropping tag, which you always must explicitly say.

Best regards,
Krzysztof


From wbg at kernel.org  Wed Mar  5 23:05:42 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu, 06 Mar 2025 16:05:42 +0900
Subject: [PATCH 0/2] counter: Introduce the compare component
Message-ID: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>

In previous drivers, we have exposed compare operations as part of a
larger set of functionalities; such as preseting a Count channel,
defining ceiling and floor boundaries, etc. However, we've lacked a
standard way to expose the compare operation in its strict sense as a
threshold comparison.

The need has become apparent in the microchip-tcb-capture module, which
requires a way to configure the threshold value provided by the RC
register for compare operations. To that end, a new compare component is
introduced with a helper macro COUNTER_COMP_COMPARE() to create such.

Signed-off-by: William Breathitt Gray <wbg at kernel.org>
---
William Breathitt Gray (2):
      counter: Introduce the compare component
      counter: microchip-tcb-capture: Add support for RC Compare

 Documentation/ABI/testing/sysfs-bus-counter |  9 ++++++++
 drivers/counter/microchip-tcb-capture.c     | 33 +++++++++++++++++++++++++++++
 include/linux/counter.h                     |  3 +++
 3 files changed, 45 insertions(+)
---
base-commit: c2a756660324fceca26780a50950e6d91dfdc210
change-id: 20250306-introduce-compare-component-11f22ace88b1

Best regards,
-- 
William Breathitt Gray <wbg at kernel.org>



From wbg at kernel.org  Wed Mar  5 23:05:43 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu, 06 Mar 2025 16:05:43 +0900
Subject: [PATCH 1/2] counter: Introduce the compare component
In-Reply-To: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
References: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
Message-ID: <20250306-introduce-compare-component-v1-1-93993b3dca9c@kernel.org>

Compare registers are used in devices to compare a counter channel
against a particular count value (e.g. to check if a threshold has been
reached). A macro COUNTER_COMP_COMPARE() is introduced to facilitate the
creation of compare components as Count extensions.

Signed-off-by: William Breathitt Gray <wbg at kernel.org>
---
 Documentation/ABI/testing/sysfs-bus-counter | 9 +++++++++
 include/linux/counter.h                     | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter
index 73ac84c0bca76e013f2534efc40c0f0e8d5fb023..3e8259e56d384225ec6e952b6d5d75208f185736 100644
--- a/Documentation/ABI/testing/sysfs-bus-counter
+++ b/Documentation/ABI/testing/sysfs-bus-counter
@@ -34,6 +34,14 @@ Contact:	linux-iio at vger.kernel.org
 Description:
 		Count data of Count Y represented as a string.
 
+What:		/sys/bus/counter/devices/counterX/countY/compare
+KernelVersion:	6.15
+Contact:	linux-iio at vger.kernel.org
+Description:
+		If the counter device supports compare registers -- registers
+		used to compare counter channels against a particular count --
+		the compare count for channel Y is provided by this attribute.
+
 What:		/sys/bus/counter/devices/counterX/countY/capture
 KernelVersion:	6.1
 Contact:	linux-iio at vger.kernel.org
@@ -301,6 +309,7 @@ Description:
 
 What:		/sys/bus/counter/devices/counterX/cascade_counts_enable_component_id
 What:		/sys/bus/counter/devices/counterX/external_input_phase_clock_select_component_id
+What:		/sys/bus/counter/devices/counterX/countY/compare_component_id
 What:		/sys/bus/counter/devices/counterX/countY/capture_component_id
 What:		/sys/bus/counter/devices/counterX/countY/ceiling_component_id
 What:		/sys/bus/counter/devices/counterX/countY/floor_component_id
diff --git a/include/linux/counter.h b/include/linux/counter.h
index 426b7d58a438d59e5178bc5e76bac82e99737323..f208e867dd0f6995f58cf6a41c67538dad6428d0 100644
--- a/include/linux/counter.h
+++ b/include/linux/counter.h
@@ -580,6 +580,9 @@ struct counter_array {
 #define COUNTER_COMP_CEILING(_read, _write) \
 	COUNTER_COMP_COUNT_U64("ceiling", _read, _write)
 
+#define COUNTER_COMP_COMPARE(_read, _write) \
+	COUNTER_COMP_COUNT_U64("compare", _read, _write)
+
 #define COUNTER_COMP_COUNT_MODE(_read, _write, _available) \
 { \
 	.type = COUNTER_COMP_COUNT_MODE, \

-- 
2.48.1



From krzk at kernel.org  Wed Mar  5 23:09:40 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:09:40 +0100
Subject: [PATCH v8 0/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <20250305091246.106626-1-swathi.ks@samsung.com>
References: <CGME20250305091845epcas5p1689eda3ba03572377997897271636cfd@epcas5p1.samsung.com>
 <20250305091246.106626-1-swathi.ks@samsung.com>
Message-ID: <041d55fd-99f0-4b55-92e5-fa46f37096c1@kernel.org>

On 05/03/2025 10:12, Swathi K S wrote:
> FSD platform has two instances of EQoS IP, one is in FSYS0 block and
> another one is in PERIC block. This patch series add required DT binding
> and platform driver specific changes for the same.
> 
> Changes since v1:
> 1. Updated dwc_eqos_setup_rxclock() function as per the review comments
> given by Andrew.
> 
Please stop referencing some other threads in your email headers via
"References". This is neither necessary nor helping our tools. I can
never compare your patches because this makes b4 busy 100%:

b4 diff -C '<20250305091246.106626-2-swathi.ks at samsung.com>'
Grabbing thread from
lore.kernel.org/all/20250305091246.106626-2-swathi.ks at samsung.com/t.mbox.gz
Checking for older revisions
  Added from v7: 3 patches
---
Analyzing 86 messages in the thread
Preparing fake-am for v7: dt-bindings: net: Add FSD EQoS device tree
bindings
<never ends, 100% CPU>

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar  5 23:14:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:14:56 +0100
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <20250305091246.106626-2-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
 <20250305091246.106626-2-swathi.ks@samsung.com>
Message-ID: <789ecb2f-dddc-491b-b9f8-5fb89058fd1b@kernel.org>

On 05/03/2025 10:12, Swathi K S wrote:
> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
> Ethernet YAML schema to enable the DT validation.
> 
> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> ---
>  .../devicetree/bindings/net/snps,dwmac.yaml   |   5 +-
>  .../bindings/net/tesla,fsd-ethqos.yaml        | 118 ++++++++++++++++++
>  2 files changed, 121 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml
> 

I tried and did not see any differences, so point me exactly to any
difference in the binding (binding!) which would justify dropping review?

Best regards,
Krzysztof


From amadeus at jmu.edu.cn  Wed Mar  5 23:15:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 15:15:02 +0800
Subject: [PATCH 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>
References: <52155b03-20f3-4e64-b636-70042db03ffa@kernel.org>
Message-ID: <20250306071502.96949-1-amadeus@jmu.edu.cn>

Hi,

>> Copy QoS nodes and add rk3528 compatible from bsp kernel,
>
> No, don't copy stuff from BSP kernel. It results in terrible DTS.

But there is no public datasheet for rk3528, it's just a minimal change.

> Did you just define syscon per few registers? Third case last weeks...
> so no, define what is your device here. 8 registers is not a device usually.

As commit 3e712a03d0481f7b0c24d961a43e385dcfa78c74 says:

---
ARM: dts: rockchip: add qos nodes found on rk3066 and rk3188

QoS nodes keep information about priorites etc on the interconnect
and loose state when the power-domain gets disabled. Therefore the
power-domain driver stores the settings of available qos nodes and
restores them when the power-domain gets enabled again.
---

I add these so they can connect to the power-domains of rk3528 SoC:

	pmu: power-management at ff600000 {
		compatible = "rockchip,rk3528-pmu", "syscon", "simple-mfd";
		reg = <0x0 0xff600000 0x0 0x2000>;

		power: power-controller {
			compatible = "rockchip,rk3528-power-controller";
			#power-domain-cells = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			pd_gpu at RK3528_PD_GPU {
				reg = <RK3528_PD_GPU>;
				clocks = <&cru ACLK_GPU_MALI>,
					 <&cru PCLK_GPU_ROOT>;
				pm_qos = <&qos_gpu_m0>,
					 <&qos_gpu_m1>;
			};
                  ......
		};
	};

This is also what the other rockchip SoCs do.

Thanks,
Chukun

-- 
2.25.1



From andy.shevchenko at gmail.com  Wed Mar  5 23:15:39 2025
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Thu, 6 Mar 2025 09:15:39 +0200
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
Message-ID: <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>

Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:
> Intel platform will configure the SerDes through PMC API based on the
> provided interface mode.

> This patch adds several new functions below:-
> - intel_tsn_lane_is_available(): This new function reads FIA lane
>   ownership registers and common lane registers through IPC commands
>   to know which lane the mGbE port is assigned to.
> - intel_mac_finish(): To configure the SerDes based on the assigned
>   lane and latest interface mode, it sends IPC command to the PMC through
>   PMC driver/API. The PMC acts as a proxy for R/W on behalf of the driver.
> - intel_set_reg_access(): Set the register access to the available TSN
>   interface.

...

> config DWMAC_INTEL

>  	default X86
>  	depends on X86 && STMMAC_ETH && PCI
>  	depends on COMMON_CLK
> +	depends on ACPI

Stray and unexplained change. Please, fix it. We don't need the dependencies
which are not realised in the compile time.

-- 
With Best Regards,
Andy Shevchenko




From krzk at kernel.org  Wed Mar  5 23:29:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:29:06 +0100
Subject: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset controller
 node
In-Reply-To: <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
 <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
Message-ID: <03b14353-5d47-48de-99fd-9cc48bad5651@kernel.org>

On 04/03/2025 20:08, Wilson Ding wrote:
> 
> I did consider shrinking the syscon's register address range to
> make the reset-controller node to be independent from the
> syscon node. However, I found the syscon node is also referred
> by some devices for miscellaneous configurations . The reset
> configuration register happens to be located in between these
> registers and clock/GPIO registers.
> 
>> drop offset in your patch or unify everything into 'reg'.
>>
> 
> This is exactly what I proposed in v3 patch. Do I misunderstand
> you?
> 
> CP11X_LABEL(swrst): reset-controller at 268 {
> 	compatible = "marvell,armada8k-reset";
> 	reg = <0x268 0x4>;
> 	#reset-cells = <1>;
> };

I don't see the other device being fixed here. How did you unify them?

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar  5 23:37:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:37:54 +0100
Subject: [PATCH 4/7] ASoC: rockchip: add Serial Audio Interface (SAI)
 driver
In-Reply-To: <20250305-rk3576-sai-v1-4-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-4-64e6cf863e9a@collabora.com>
Message-ID: <20e4754b-ea9a-404d-b529-ec44a7263cbf@kernel.org>

On 05/03/2025 22:24, Nicolas Frattaroli wrote:
...

> +
> +static int rockchip_sai_runtime_resume(struct device *dev)
> +{
> +	struct rk_sai_dev *sai = dev_get_drvdata(dev);
> +	unsigned long flags;
> +	int ret;
> +
> +	dev_dbg(dev, "Runtime resuming device!\n");

Drop probe entry/exit messages. Core already gives you tracing for this.

> +
> +	ret = clk_prepare_enable(sai->hclk);
> +	if (ret)
> +		goto err_hclk;
> +
> +	ret = clk_prepare_enable(sai->mclk);
> +	if (ret)
> +		goto err_mclk;
> +
> +	regcache_cache_only(sai->regmap, false);
> +	regcache_mark_dirty(sai->regmap);
> +	ret = regcache_sync(sai->regmap);
> +	if (ret)
> +		goto err_regmap;
> +
> +	if (sai->quirks & QUIRK_ALWAYS_ON && sai->is_master_mode) {
> +		spin_lock_irqsave(&sai->xfer_lock, flags);
> +		regmap_update_bits(sai->regmap, SAI_XFER,
> +				   SAI_XFER_CLK_MASK |
> +				   SAI_XFER_FSS_MASK,
> +				   SAI_XFER_CLK_EN |
> +				   SAI_XFER_FSS_EN);
> +		spin_unlock_irqrestore(&sai->xfer_lock, flags);
> +	}
> +

...

> +
> +	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register PCM: %d\n", ret);
> +		goto err_runtime_suspend;
> +	}
> +
> +	ret = devm_snd_soc_register_component(&pdev->dev,
> +					      &rockchip_sai_component,
> +					      dai, 1);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register component: %d\n", ret);
> +		goto err_runtime_suspend;
> +	}
> +
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	pm_runtime_put(&pdev->dev);
> +
> +	/*
> +	 * runtime_resume already enabled our hclk again, so we need to also
> +	 * get rid of the manual enable we did earlier to balance the counts.
> +	 */

Your way of handling this is extra confusing. You rely on some other
methods to poke the enable/disable count. It is rather expected that
each function handles this fully, so it disables what it have enabled.
You must not rely on PM runtime to do something with clocks which you
now unwind.

> +	clk_disable_unprepare(sai->hclk);
> +
> +	return 0;
> +
> +err_runtime_suspend:
> +	/* If we're !CONFIG_PM, we get -ENOSYS and disable manually */
> +	if (pm_runtime_put(&pdev->dev))
> +		rockchip_sai_runtime_suspend(&pdev->dev);
> +err_disable_hclk:
> +	clk_disable_unprepare(sai->hclk);
> +
> +	return ret;
> +}
> +

_device_id tables are supposed to be around probe, not beginning of the
file.

> +static void rockchip_sai_remove(struct platform_device *pdev)
> +{
> +#ifndef CONFIG_PM
> +	rockchip_sai_runtime_suspend(&pdev->dev);> +#endif
> +}
> +
> +static const struct dev_pm_ops rockchip_sai_pm_ops = {
> +	SET_RUNTIME_PM_OPS(rockchip_sai_runtime_suspend, rockchip_sai_runtime_resume, NULL)
> +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
> +};
> +
> +static struct platform_driver rockchip_sai_driver = {
> +	.probe = rockchip_sai_probe,
> +	.remove = rockchip_sai_remove,
> +	.driver = {
> +		.name = DRV_NAME,
> +		.of_match_table = of_match_ptr(rockchip_sai_match),

Drop of_match_ptr, you have warning here.

> +		.pm = &rockchip_sai_pm_ops,
> +	},
> +};
> +module_platform_driver(rockchip_sai_driver);
> +
> +MODULE_DESCRIPTION("Rockchip SAI ASoC Interface");
> +MODULE_AUTHOR("Sugar Zhang <sugar.zhang at rock-chips.com>");
> +MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli at collabora.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRV_NAME);

You should not need MODULE_ALIAS() in normal cases. If you need it,
usually it means your device ID table is wrong (e.g. misses either
entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute
for incomplete ID table.


> +MODULE_DEVICE_TABLE(of, rockchip_sai_match);


Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar  5 23:38:58 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:38:58 +0100
Subject: [PATCH 1/7] dt-bindings: clock: rk3576: add IOC gated clocks
In-Reply-To: <20250305-rk3576-sai-v1-1-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-1-64e6cf863e9a@collabora.com>
Message-ID: <295caed0-7db6-4b87-9991-e4b7e7621f38@kernel.org>

On 05/03/2025 22:24, Nicolas Frattaroli wrote:
> Certain clocks on the RK3576 are additionally essentially "gated" behind
> some bit toggles in the IOC GRF range. Downstream ungates these by
> adding a separate clock driver that maps over the GRF range and leaks
> their implementation of this into the DT.
> 

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From mwalle at kernel.org  Wed Mar  5 23:41:17 2025
From: mwalle at kernel.org (Michael Walle)
Date: Thu, 06 Mar 2025 08:41:17 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <84b1def7-fba7-4f29-a49b-d117efe26d26@microchip.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
 <87ikonydym.fsf@bootlin.com>
 <84b1def7-fba7-4f29-a49b-d117efe26d26@microchip.com>
Message-ID: <D890I4EPARNO.O0VS9VZUL6IR@kernel.org>

Hi,

> >> From: Varshini Rajendran <varshini.rajendran at microchip.com>
> >>
> >> EUI identifier and the MAC Address of the Ethernet Interface is stored
> >> after the SFDP table of contents starting at address 0x260 in the
> >> QSPI memory.
> >> Register the entire SFDP region read by the spi-nor (nor->sfdp) into the
> >> NVMEM framework and read the MAC Address when requested using the nvmem
> >> properties in the DT by the net drivers.
> >>
> >> In kernel the Ethernet MAC address relied on U-Boot env variables or
> >> generated a random address, which posed challenges for boards without
> >> on-board EEPROMs or with multiple Ethernet ports.
> >> This change ensures consistent and reliable MAC address retrieval from QSPI,
> >> benefiting boards like the sama5d29 curiosity and sam9x75 curiosity.
> > 
> > Do you mean spi-nor have a programmable area in their SFDP table? Isn't
> > this supposed to be a read-only area written once in factory?
> > 
> The SST26VF064BEUI serial quad flash memory is programmed at the factory 
> with a globally unique address stored in the SFDP vendor
> parameter table and it is permanently write-protected.

Why didn't you mention that this is a vendor table in the commit
message?

Anyway, please write proper support in the core for parsing vendor
tables and exposing them as a nvmem device if needed (and asked to
do so by the driver of course).

-michael


From maxime.chevallier at bootlin.com  Wed Mar  5 23:42:01 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 6 Mar 2025 08:42:01 +0100
Subject: [PATCH net-next 0/7] net: ethtool: Introduce ethnl dump helpers
In-Reply-To: <20250305184749.5519e7a9@kernel.org>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
	<20250305180252.5a0ceb86@fedora.home>
	<20250305184749.5519e7a9@kernel.org>
Message-ID: <20250306084201.23885f5b@fedora.home>

On Wed, 5 Mar 2025 18:47:49 -0800
Jakub Kicinski <kuba at kernel.org> wrote:

> On Wed, 5 Mar 2025 18:02:52 +0100 Maxime Chevallier wrote:
> > This series will very likely conflict with Stanislav's netdev lock
> > work [2], I'll of course be happy to rebase should it get merged :)  
> 
> Also this doesn't build. Please hold off on reposting for a couple of
> days - because of the large conflict radius the previous few revisions
> of the locking series haven't even gotten into the selftest CI queue :(

Sure no problem. I'll try t figure out what's up with the build in the
meantime, looks like I inverted a few changes that break
bissecatability.

I'll keep an eye on Stanislav's work in the meantime as well.

Thanks,

Maxime


From krzk at kernel.org  Wed Mar  5 23:42:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:42:54 +0100
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI
 controllers
In-Reply-To: <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
Message-ID: <ffd6287c-cbfd-4ba8-9332-45bad4e60583@kernel.org>

On 05/03/2025 22:24, Nicolas Frattaroli wrote:
> Rockchip introduced a new audio controller called the "Serial Audio
> Interface", or "SAI" for short, on some of their newer SoCs. In
> particular, this controller is used several times on the RK3576 SoC.
> 
> Add a schema for it, with only an RK3576 compatible for now. Other SoCs
> may follow as mainline support for them lands.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
>  .../devicetree/bindings/sound/rockchip,sai.yaml    | 151 +++++++++++++++++++++

Filename based on compatible.

>  MAINTAINERS                                        |   6 +
>  2 files changed, 157 insertions(+)
> 

...

> +
> +  dma-names:
> +    minItems: 1
> +    maxItems: 2
> +    oneOf:
> +      - const: tx
> +      - const: rx
> +      - items:
> +          - const: tx
> +          - const: rx

Why all combinations are possible?

> +
> +  clocks:
> +    items:
> +      - description: master audio clock
> +      - description: AHB clock driving the interface
> +
> +  clock-names:
> +    items:
> +      - const: mclk
> +      - const: hclk
> +
> +  resets:
> +    minItems: 1
> +    maxItems: 2
> +    description: resets for the mclk domain and ahb domain

List the items instead with description and minItems: 1.

> +
> +  reset-names:
> +    minItems: 1
> +    items:
> +      - const: m
> +      - const: h
> +
> +  port:
> +    $ref: audio-graph-port.yaml#
> +    unevaluatedProperties: false
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  "#sound-dai-cells":
> +    const: 0
> +
> +  rockchip,sai-rx-route:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    description:
> +      Defines the mapping of the controller's SDI ports to actual input lanes,
> +      as well as the number of input lanes.
> +      rockchip,sai-rx-route = <3> would mean sdi3 is receiving from data0, and
> +      that there is only one receiving lane.
> +      This property's absence is to be understood as only one receiving lane
> +      being used if the controller has capture capabilities.
> +    maxItems: 4
> +    items:
> +      enum: [0, 1, 2, 3]
> +
> +  rockchip,sai-tx-route:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    description:
> +      Defines the mapping of the controller's SDO ports to actual output lanes,
> +      as well as the number of output lanes.
> +      rockchip,sai-tx-route = <3> would mean sdo3 is sending to data0, and

I understand this is only example because = <3> would not be allowed
(test it).

> +      that there is only one transmitting lane.
> +      This property's absence is to be understood as only one transmitting lane
> +      being used if the controller has playback capabilities.
> +    maxItems: 4
> +    items:
> +      enum: [0, 1, 2, 3]
> +
> +  rockchip,always-on:
> +    type: boolean
> +    description:
> +      The hardware requires this controller to remain turned on.

How hardware requires this? You rather miss proper PM domain handling or
some other resources.

> +
> +

Just one blank line.

> +required:
> +  - compatible
> +  - reg
> +  - dmas
> +  - dma-names
> +  - clocks
> +  - clock-names
> +  - "#sound-dai-cells"
> +
> +unevaluatedProperties: false



Best regards,
Krzysztof


From ankur.a.arora at oracle.com  Wed Mar  5 23:53:19 2025
From: ankur.a.arora at oracle.com (Ankur Arora)
Date: Wed, 05 Mar 2025 23:53:19 -0800
Subject: [PATCH 1/4] asm-generic: barrier: Add
 smp_cond_load_relaxed_timewait()
In-Reply-To: <Z8dRalfxYcJIcLGj@arm.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-2-ankur.a.arora@oracle.com>
 <Z8dRalfxYcJIcLGj@arm.com>
Message-ID: <87pliusihc.fsf@oracle.com>


Catalin Marinas <catalin.marinas at arm.com> writes:

> On Mon, Feb 03, 2025 at 01:49:08PM -0800, Ankur Arora wrote:
>> Add smp_cond_load_relaxed_timewait(), a timed variant of
>> smp_cond_load_relaxed(). This is useful for cases where we want to
>> wait on a conditional variable but don't want to wait indefinitely.
>
> Bikeshedding: why not "timeout" rather than "timewait"?

Well my reasons, such as they are, also involved a fair amount of bikeshedding:

 - timewait and spinwait have same length names which just minimized all
   the indentation issues.
 - timeout seems to suggest a timing mechanism of some kind.

>> diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
>> index d4f581c1e21d..31de8ed2a05e 100644
>> --- a/include/asm-generic/barrier.h
>> +++ b/include/asm-generic/barrier.h
>> @@ -273,6 +273,54 @@ do {									\
>>  })
>>  #endif
>>
>> +#ifndef smp_cond_time_check_count
>> +/*
>> + * Limit how often smp_cond_load_relaxed_timewait() evaluates time_expr_ns.
>> + * This helps reduce the number of instructions executed while spin-waiting.
>> + */
>> +#define smp_cond_time_check_count	200
>> +#endif
>
> While this was indeed added to the poll_idle() loop, it feels completely
> random in a generic implementation. It's highly dependent on the
> time_expr_ns passed.

I agree about this feeling quite out of place. For one thing, this is
exposed unnecessarily to the arch code.

> Can the caller not move the loop in time_expr_ns
> before invoking this macro?

You mean add a loop count conditional of some kind in the time_cond_expr?

Might need to change the direction of some of the checks, but let me
play with that. (The one below won't work.)

Even if we could do that though, it seems that how often the time-check
is done should be an internal detail of the interface. Seems ugly to expose
this to the caller:

    flags = smp_cond_load_relaxed_timewait(&current_thread_info()->flags,
                                           (VAL & _TIF_NEED_RESCHED),
                                           (count++ % POLL_IDLE_RELAX_COUNT) ||
                                           (local_clock_noinstr() >= time_limit)));

(Anyway more on this below.)

>> +
>> +/**
>> + * smp_cond_load_relaxed_timewait() - (Spin) wait for cond with no ordering
>> + * guarantees until a timeout expires.
>> + * @ptr: pointer to the variable to wait on
>> + * @cond: boolean expression to wait for
>> + * @time_expr_ns: evaluates to the current time
>> + * @time_limit_ns: compared against time_expr_ns
>> + *
>> + * Equivalent to using READ_ONCE() on the condition variable.
>> + *
>> + * Note that the time check in time_expr_ns can be synchronous or
>> + * asynchronous.
>> + * In the generic version the check is synchronous but kept coarse
>> + * to minimize instructions executed while spin-waiting.
>> + */
>
> Not sure exactly what synchronous vs asynchronous here mean. I see the
> latter more like an interrupt. I guess what you have in mind is the WFE
> wakeup events on arm64, though they don't interrupt the instruction
> flow. I'd not bother specifying this at all.

Yeah, with fresh eyes this feels quite unnecessary.

 In the generic version the time check is done in the loop but kept coarse
 to minimize instructions executed while spin-waiting. Architecture code
 might implement this without spin-waiting.

>> +#ifndef __smp_cond_load_relaxed_spinwait
>> +#define __smp_cond_load_relaxed_spinwait(ptr, cond_expr, time_expr_ns,	\
>> +					 time_limit_ns) ({		\
>> +	typeof(ptr) __PTR = (ptr);					\
>> +	__unqual_scalar_typeof(*ptr) VAL;				\
>> +	unsigned int __count = 0;					\
>> +	for (;;) {							\
>> +		VAL = READ_ONCE(*__PTR);				\
>> +		if (cond_expr)						\
>> +			break;						\
>> +		cpu_relax();						\
>> +		if (__count++ < smp_cond_time_check_count)		\
>> +			continue;					\
>> +		if ((time_expr_ns) >= (time_limit_ns))			\
>> +			break;						\
>> +		__count = 0;						\
>> +	}								\
>> +	(typeof(*ptr))VAL;						\
>> +})
>> +#endif
>> +
>> +#ifndef smp_cond_load_relaxed_timewait
>> +#define smp_cond_load_relaxed_timewait  __smp_cond_load_relaxed_spinwait
>> +#endif
>
> What I don't particularly like about this interface is (1) no idea of
> what time granularity it offers, how much it can slip past the deadline,
> even though there's some nanoseconds implied and

So, one problem with that is that the time granularity probably varies
wildly with the implementation and some don't have a clear idea
of the granularity at all:

- generic version (x86): does not have a well defined granularity. The
  assumption is that calling cpu_relax() is "fast" but at least for how
  it is used via poll_idle(), each iteration is at least around 2k-4k
  cycles. (Also depends on the particular CPU model.)

- arm64 WFE version: well defined, potentially query-able granularity
  (say 100us)

- a future arm64 WFET version: similar to the WFE version with a
  smaller granularity.

- generic code: arm64 fallback: granularity not well defined. For
  implementations that implement YIELD as NOP, it's probably
  extremely fast and hot.

> (2) time_expr_ns leaves
> the caller to figure out why time function to use for tracking the time.
> Well, I can be ok with (2) if we make it a bit more generic.

> The way it is written, I guess the type of the time expression and limit
> no longer matters as long as you can compare them. The naming implies
> nanoseconds but we don't have such precision, especially with the WFE
> implementation for arm64. We could add a slack range argument like the
> delta_ns for some of the hrtimer API and let the arch code decide
> whether to honour it.

Yeah and as you say, none of the code actually cares for the unit so
that _ns stuff is unnecessary.

> What about we drop the time_limit_ns and build it into the time_expr_ns
> as a 'time_cond' argument? The latter would return the result of some
> comparison and the loop bails out if true.

Yeah the interface can't actually do anything with the time_expr_ns and
time_limit_ns anyway so just using a combined time_cond seems like a good
idea.

But more below.

> An additional argument would
> be the minimum granularity for checking the time_cond and the arch code
> may decide to fall back to busy loops if the granularity is larger than
> what the caller required.

As you mention mention, there are two problems with the time-check:
constraints on how much it can overflow and how much tardiness we can
bring to bear on the actual evaluation of the presumed expensive
time-check (the smp_cond_time_check_count).

Both of these are conceptually related but the first one only really
applies to WFE like implementations, and the second only to spinning
implementations.

I think some kind of a granularity parameter might help with both of
these.

Taking a step back, we have the following time related parameters:

  1. time_expr
  2. time_limit

Or (1) and (2) combined via time_cond.

And, these are some different ways to put constraints on the time-check:

  3. time_slack: int, representing some kind of percentage/order etc limiting
     value for the overflow. This needs a visible value for (2).

  4. time_check_coarse: bool, representing coarse or fine.
  5. time_granularity: int, specifying the granularity (say
     1/10/100/1000 us) the caller wants.

     This allows the caller to dynamically choose a particular value
     based on (2). poll_idle(), for instance, would evaluate
     cpuidle_poll_time() to decide what value to use.

IMO (3), and (5) both have too much precision that neither of the known
users seem to need:
 - poll_idle(): the only thing waiting for it on the other side of an
   expired timeout is that it goes to a deeper idle state. So, it should
   be fine to be a bit late.

 - resilient spinlock timeout: current timeout value is 0.25s
   (RES_DEF_TIMEOUT [1]) which is pretty large.

So, instead it might be enough for the users to just specify what kind
of timeout or time-check they want (specifying coarse/fine via (4)) and
let the interface use that to handle its overflow and the tardiness
constraints.

With that the generic version could be:

#define __smp_cond_load_relaxed_spinwait(ptr, cond_expr, time_cond,     \
                                         time_check_coarse) ({          \
        typeof(ptr) __PTR = (ptr);                                      \
        __unqual_scalar_typeof(*ptr) VAL;                               \
        unsigned int __count = 0;                                       \
        unsigned int __time_check_count = 200;                          \
                                                                        \
        if (!time_check_coarse)                                         \
                __time_check_count /= 4;                                \
                                                                        \
        for (;;) {                                                      \
                VAL = READ_ONCE(*__PTR);                                \
                if (cond_expr)                                          \
                        break;                                          \
                cpu_relax();                                            \
                if (__count++ < __time_check_count)                     \
                        continue;                                       \
                if (time_cond)                                          \
                        break;                                          \
                __count = 0;                                            \
        }                                                               \
        (typeof(*ptr))VAL;                                              \
})

(The constant is still arbitrary, but it seems to fit in the broad
coarse/fine outlines.)

And the arm64 version:

#define smp_cond_load_relaxed_timewait(ptr, cond_expr,                  \
                                       time_cond, time_check_coarse)    \
({                                                                      \
        __unqual_scalar_typeof(*ptr) _val;                              \
        bool __wfe = arch_timer_evtstrm_available();                    \
                                                                        \
        if (time_check_coarse && __wfe)                                 \
                _val = __smp_cond_load_relaxed_timewait(ptr, cond_expr, \
                                                        time_cond);     \
        else                                                            \
                _val = __smp_cond_load_relaxed_spinwait(ptr, cond_expr, \
                                                        time_cond,      \
                                                        time_check_coarse); \
        (typeof(*ptr))_val;                                             \
})


What do you think?

Oh and thanks for the very helpful review!

[1] https://lore.kernel.org/lkml/20250303152305.3195648-8-memxor at gmail.com/

--
ankur


From krzk at kernel.org  Wed Mar  5 23:57:27 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 08:57:27 +0100
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
Message-ID: <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>

On Wed, Mar 05, 2025 at 03:58:16PM -0300, N?colas F. R. A. Prado wrote:
> Describe the accessory detection (accdet) module as a possible subnode
> of the MT6359 PMIC.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  .../devicetree/bindings/mfd/mediatek,mt6397.yaml   | 51 ++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..51012b8bbfaef3df7bdb619a4f8d828d6f9cc15a 100644
> --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> @@ -24,6 +24,7 @@ description: |
>    - LED
>    - Keys
>    - Power controller
> +  - Accessory Detection
>  
>    It is interfaced to host controller using SPI interface by a proprietary hardware
>    called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
> @@ -224,6 +225,30 @@ properties:
>      description:
>        Pin controller
>  
> +  accdet:
> +    type: object
> +    additionalProperties: false
> +    description:
> +      The Accessory Detection module found on the PMIC allows detecting audio
> +      jack insertion and removal, as well as identifying the type of events
> +      connected to the jack.
> +
> +    properties:
> +      compatible:
> +        const: mediatek,mt6359-accdet

You just removed the other file, no folding happened here. Drop the
accdet node and fold this into parent.

Best regards,
Krzysztof



From ankur.a.arora at oracle.com  Wed Mar  5 23:58:14 2025
From: ankur.a.arora at oracle.com (Ankur Arora)
Date: Wed, 05 Mar 2025 23:58:14 -0800
Subject: [PATCH 3/4] arm64: barrier: Add smp_cond_load_relaxed_timewait()
In-Reply-To: <Z8dUg5zzclvDpPtZ@arm.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-4-ankur.a.arora@oracle.com>
 <Z8dUg5zzclvDpPtZ@arm.com>
Message-ID: <87bjuesi95.fsf@oracle.com>


Catalin Marinas <catalin.marinas at arm.com> writes:

> On Mon, Feb 03, 2025 at 01:49:10PM -0800, Ankur Arora wrote:
>> diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
>> index 1ca947d5c939..25721275a5a2 100644
>> --- a/arch/arm64/include/asm/barrier.h
>> +++ b/arch/arm64/include/asm/barrier.h
>> @@ -216,6 +216,44 @@ do {									\
>>  	(typeof(*ptr))VAL;						\
>>  })
>>
>> +#define __smp_cond_load_relaxed_timewait(ptr, cond_expr,		\
>> +					 time_expr_ns, time_limit_ns)	\
>> +({									\
>> +	typeof(ptr) __PTR = (ptr);					\
>> +	__unqual_scalar_typeof(*ptr) VAL;				\
>> +	for (;;) {							\
>> +		VAL = READ_ONCE(*__PTR);				\
>> +		if (cond_expr)						\
>> +			break;						\
>> +		__cmpwait_relaxed(__PTR, VAL);				\
>> +		if ((time_expr_ns) >= (time_limit_ns))			\
>> +			break;						\
>> +	}								\
>> +	(typeof(*ptr))VAL;						\
>> +})
>
> Rename this to something like *_evstrm as this doesn't really work
> unless we have the event stream.

Ack.

> Another one would be *_wfet.

Hadn't sent out the WFET version yet.

Did you mean that this should be *_evtstrm or *_wfet?

>> +
>> +/*
>> + * For the unlikely case that the event-stream is unavailable,
>> + * ward off the possibility of waiting forever by falling back
>> + * to the generic spin-wait.
>> + */
>> +#define smp_cond_load_relaxed_timewait(ptr, cond_expr,			\
>> +				       time_expr_ns, time_limit_ns)	\
>> +({									\
>> +	__unqual_scalar_typeof(*ptr) _val;				\
>> +	int __wfe = arch_timer_evtstrm_available();			\
>
> This should be a bool.

Yeah. Will fix.

>> +									\
>> +	if (likely(__wfe))						\
>> +		_val = __smp_cond_load_relaxed_timewait(ptr, cond_expr,	\
>> +							time_expr_ns,	\
>> +							time_limit_ns);	\
>> +	else								\
>> +		_val = __smp_cond_load_relaxed_spinwait(ptr, cond_expr,	\
>> +							time_expr_ns,	\
>> +							time_limit_ns);	\
>> +	(typeof(*ptr))_val;						\
>> +})
>
> Not sure there's much to say here, this depends on the actual interface
> introduced by patch 1. If we make some statements about granularity of
> some time_cond_expr check, we'll have to take that into account.

Agreed.

Thanks for the review!

--
ankur


From swathi.ks at samsung.com  Wed Mar  5 23:44:13 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Thu, 6 Mar 2025 13:14:13 +0530
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <789ecb2f-dddc-491b-b9f8-5fb89058fd1b@kernel.org>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
	<20250305091246.106626-2-swathi.ks@samsung.com>
	<789ecb2f-dddc-491b-b9f8-5fb89058fd1b@kernel.org>
Message-ID: <012701db8e6b$950550c0$bf0ff240$@samsung.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: 06 March 2025 12:45
> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> conor+dt at kernel.org; richardcochran at gmail.com;
> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> gost.dev at samsung.com
> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
> bindings
> 
> On 05/03/2025 10:12, Swathi K S wrote:
> > Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
> > Ethernet YAML schema to enable the DT validation.
> >
> > Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> > Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> > Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> > ---
> >  .../devicetree/bindings/net/snps,dwmac.yaml   |   5 +-
> >  .../bindings/net/tesla,fsd-ethqos.yaml        | 118 ++++++++++++++++++
> >  2 files changed, 121 insertions(+), 2 deletions(-)  create mode
> > 100644 Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml
> >
> 
> I tried and did not see any differences, so point me exactly to any difference
> in the binding (binding!) which would justify dropping review?

Added the following in the example given in DT binding doc:

assigned-clocks = <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
                                <&clock_peric PERIC_EQOS_PHYRXCLK>;
assigned-clock-parents = <&clock_peric PERIC_EQOS_PHYRXCLK>;

Given the significance of these changes, I assumed the changes need to be reviewed again.
That was why the tag was removed. Please correct me if I am wrong and provide your feedback on this patch.

- Swathi

> 
> Best regards,
> Krzysztof



From swathi.ks at samsung.com  Wed Mar  5 23:45:45 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Thu, 6 Mar 2025 13:15:45 +0530
Subject: [PATCH v8 0/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <041d55fd-99f0-4b55-92e5-fa46f37096c1@kernel.org>
References: <CGME20250305091845epcas5p1689eda3ba03572377997897271636cfd@epcas5p1.samsung.com>
	<20250305091246.106626-1-swathi.ks@samsung.com>
	<041d55fd-99f0-4b55-92e5-fa46f37096c1@kernel.org>
Message-ID: <012801db8e6b$cb835bb0$628a1310$@samsung.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: 06 March 2025 12:40
> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> conor+dt at kernel.org; richardcochran at gmail.com;
> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> gost.dev at samsung.com; tools at linux.kernel.org
> Subject: Re: [PATCH v8 0/2] net: stmmac: dwc-qos: Add FSD EQoS support
> 
> On 05/03/2025 10:12, Swathi K S wrote:
> > FSD platform has two instances of EQoS IP, one is in FSYS0 block and
> > another one is in PERIC block. This patch series add required DT
> > binding and platform driver specific changes for the same.
> >
> > Changes since v1:
> > 1. Updated dwc_eqos_setup_rxclock() function as per the review
> > comments given by Andrew.
> >
> Please stop referencing some other threads in your email headers via
> "References". This is neither necessary nor helping our tools. I can never
> compare your patches because this makes b4 busy 100%:

Will take care in future

- Swathi

> 
> b4 diff -C '<20250305091246.106626-2-swathi.ks at samsung.com>'
> Grabbing thread from
> lore.kernel.org/all/20250305091246.106626-2-
> swathi.ks at samsung.com/t.mbox.gz
> Checking for older revisions
>   Added from v7: 3 patches
> ---
> Analyzing 86 messages in the thread
> Preparing fake-am for v7: dt-bindings: net: Add FSD EQoS device tree
> bindings <never ends, 100% CPU>
> 
> Best regards,
> Krzysztof



From swathi.ks at samsung.com  Wed Mar  5 23:48:37 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Thu, 6 Mar 2025 13:18:37 +0530
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <a9ddeccf-8fc6-453c-af62-55e895888a77@kernel.org>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
	<20250305091246.106626-2-swathi.ks@samsung.com>
	<89dcfb2a-d093-48f9-b6d7-af99b383a1bc@kernel.org>
	<00e301db8e49$95bfbf90$c13f3eb0$@samsung.com>
	<a9ddeccf-8fc6-453c-af62-55e895888a77@kernel.org>
Message-ID: <012901db8e6c$3179a730$946cf590$@samsung.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: 06 March 2025 12:35
> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> conor+dt at kernel.org; richardcochran at gmail.com;
> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> gost.dev at samsung.com
> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
> bindings
> 
> On 06/03/2025 04:40, Swathi K S wrote:
> >
> >
> >> -----Original Message-----
> >> From: Krzysztof Kozlowski <krzk at kernel.org>
> >> Sent: 05 March 2025 21:12
> >> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
> >> andrew+netdev at lunn.ch; davem at davemloft.net;
> edumazet at google.com;
> >> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> >> conor+dt at kernel.org; richardcochran at gmail.com;
> >> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
> >> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
> >> devicetree at vger.kernel.org; linux-stm32 at st-md-
> mailman.stormreply.com;
> >> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> >> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
> >> gost.dev at samsung.com
> >> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device
> >> tree bindings
> >>
> >> On 05/03/2025 10:12, Swathi K S wrote:
> >>> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add
> >>> FSD Ethernet YAML schema to enable the DT validation.
> >>>
> >>> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> >>> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> >>> Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> >>
> >> <form letter>
> >> This is a friendly reminder during the review process.
> >>
> >> It looks like you received a tag and forgot to add it.
> >>
> >> If you do not know the process, here is a short explanation:
> >> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
> >> versions of patchset, under or above your Signed-off-by tag, unless
> >> patch changed significantly (e.g. new properties added to the DT
> >> bindings). Tag is "received", when provided in a message replied to you
> on the mailing list.
> >> Tools like b4 can help here. However, there's no need to repost
> >> patches
> >> *only* to add the tags. The upstream maintainer will do that for tags
> >> received on the version they apply.
> >>
> >> Please read:
> >> https://protect2.fireeye.com/v1/url?k=19972162-781c345b-1996aa2d-
> >> 000babffae10-7bd6b1a1d78b210b&q=1&e=94dcc3a6-5303-441a-8c1e-
> >> de696b216f86&u=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv6.12-
> >> rc3%2Fsource%2FDocumentation%2Fprocess%2Fsubmitting-
> >> patches.rst%23L577
> >>
> >> If a tag was not added on purpose, please state why and what changed.
> >
> > Hi Krzysztof,
> > As per a review comment received from Russell, I had added 2 new
> properties to the DT - assigned-clocks and assigned-clock-parents properties.
> > The example in the DT binding reflects the same.
> > I felt it wouldn't be fair to add 'Reviewed-by' tag without you reviewing the
> updates again.
> > But I should have mentioned that in cover letter and apologies for missing
> to do that.
> Nothing in changelog explained new properties. Nothing mentioned

Had mentioned under 'changes since v7' in the cover letter patch where I had mentioned about addressing Russell's comment and corresponding DT binding example changes of setting clock tree in DT.

- Swathi 

> dropping tag, which you always must explicitly say.
> 
> Best regards,
> Krzysztof



From quic_yuanfang at quicinc.com  Thu Mar  6 00:22:20 2025
From: quic_yuanfang at quicinc.com (Yuanfang Zhang)
Date: Thu, 6 Mar 2025 16:22:20 +0800
Subject: [PATCH v2 2/5] coresight: add coresight Trace NOC driver
In-Reply-To: <20250227113910.GA2157064@e132581.arm.com>
References: <20250226-trace-noc-driver-v2-0-8afc6584afc5@quicinc.com>
 <20250226-trace-noc-driver-v2-2-8afc6584afc5@quicinc.com>
 <20250227113910.GA2157064@e132581.arm.com>
Message-ID: <c0848f24-26c4-4282-9813-1842c2a50c1e@quicinc.com>



On 2/27/2025 7:39 PM, Leo Yan wrote:
> Hi Yuanfang,
> 
> On Wed, Feb 26, 2025 at 07:05:51PM +0800, Yuanfang Zhang wrote:
>>
>> Add driver to support Coresight device Trace NOC(Network On Chip).
>> Trace NOC is an integration hierarchy which is a replacement of
>> Dragonlink configuration. It brings together debug components like
>> TPDA, funnel and interconnect Trace Noc.
>>
>> It sits in the different subsystem of SOC and aggregates the trace
>> and transports to QDSS trace bus.
>>
>> Signed-off-by: Yuanfang Zhang <quic_yuanfang at quicinc.com>
>> ---
>>  drivers/hwtracing/coresight/Kconfig          |  13 ++
>>  drivers/hwtracing/coresight/Makefile         |   1 +
>>  drivers/hwtracing/coresight/coresight-tnoc.c | 190 +++++++++++++++++++++++++++
>>  drivers/hwtracing/coresight/coresight-tnoc.h |  53 ++++++++
>>  4 files changed, 257 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
>> index 06f0a7594169c5f03ca5f893b7debd294587de78..6cfd160f09d383ab5f5aa276fa57496a52c8f961 100644
>> --- a/drivers/hwtracing/coresight/Kconfig
>> +++ b/drivers/hwtracing/coresight/Kconfig
>> @@ -247,4 +247,17 @@ config CORESIGHT_DUMMY
>>
>>           To compile this driver as a module, choose M here: the module will be
>>           called coresight-dummy.
>> +
>> +config CORESIGHT_TNOC
>> +       tristate "Coresight Trace Noc driver"
>> +       help
>> +         This driver provides support for Trace NoC component.
>> +         Trace NoC is a interconnect that is used to collect trace from
>> +         various subsystems and transport it QDSS trace sink.It sits in
> 
> Trace NoC is an interconnect used to collect traces from various
> subsystems and transport to a QDSS trace sink.
sure, will update in next version.
> 
>> +         the different tiles of SOC and aggregates the trace local to the
>> +         tile and transports it another tile or to QDSS trace sink eventually.
>> +
>> +         To compile this driver as a module, choose M here: the module will be
>> +         called coresight-tnoc.
>> +
>>  endif
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
>> index 4ba478211b318ea5305f9f98dda40a041759f09f..60b729979f19c8f8848c77c290605132dba1a991 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -34,6 +34,7 @@ obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
>>  obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
>>  obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
>>                                            coresight-replicator.o
>> +obj-$(CONFIG_CORESIGHT_TNOC) += coresight-tnoc.o
>>  obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o
>>  coresight-etm3x-y := coresight-etm3x-core.o coresight-etm-cp14.o \
>>                      coresight-etm3x-sysfs.o
>> diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..fad8e61f05ef25989aba1be342c547f835e8953a
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-tnoc.c
>> @@ -0,0 +1,190 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/amba/bus.h>
>> +#include <linux/io.h>
>> +#include <linux/coresight.h>
>> +#include <linux/of.h>
> 
> Please include headers in alphabetical ordering.
sure, will update in next version.
> 
>> +#include "coresight-priv.h"
>> +#include "coresight-tnoc.h"
>> +#include "coresight-trace-id.h"
>> +
>> +static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
>> +{
>> +       u32 val;
>> +
>> +       /* Set ATID */
>> +       writel_relaxed(drvdata->atid, drvdata->base + TRACE_NOC_XLD);
>> +
>> +       /* Config sync CR */
>> +       writel_relaxed(0xffff, drvdata->base + TRACE_NOC_SYNCR);
>> +
>> +       /* Set frequency value */
>> +       writel_relaxed(drvdata->freq_req_val, drvdata->base + TRACE_NOC_FREQVAL);
>> +
>> +       /* Set Ctrl register */
>> +       val = readl_relaxed(drvdata->base + TRACE_NOC_CTRL);
>> +
>> +       if (drvdata->flag_type == FLAG_TS)
>> +               val = val | TRACE_NOC_CTRL_FLAGTYPE;
>> +       else
>> +               val = val & ~TRACE_NOC_CTRL_FLAGTYPE;
>> +
>> +       if (drvdata->freq_type == FREQ_TS)
>> +               val = val | TRACE_NOC_CTRL_FREQTYPE;
>> +       else
>> +               val = val & ~TRACE_NOC_CTRL_FREQTYPE;
>> +
>> +       val = val | TRACE_NOC_CTRL_PORTEN;
>> +       writel_relaxed(val, drvdata->base + TRACE_NOC_CTRL);
> 
> It is fine for using writel_relaxed() for continuous writing into the
> same component.  However, the last writing into TRACE_NOC_CTRL enales
> the NOC but without any barrier guard, it might cause the out-of-order
> issue with Arm CoreSight modules (or any other relevant endpoints).
sure, will update in next version.
> 
> I'd like suggest to use writel() for writing TRACE_NOC_CTRL.
> 
>> +       dev_dbg(drvdata->dev, "Trace NOC is enabled\n");
>> +}
>> +
>> +static int trace_noc_enable(struct coresight_device *csdev, struct coresight_connection *inport,
>> +                           struct coresight_connection *outport)
>> +{
>> +       struct trace_noc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       spin_lock(&drvdata->spinlock);
>> +       if (csdev->refcnt == 0)
> 
> AFAICT csdev->refcnt is only used in sink drivers.  This driver is for
> funnel, it should use `inport->dest_refcnt` as the counter.
sure, will update in next version.
> 
>> +               trace_noc_enable_hw(drvdata);
>> +
>> +       csdev->refcnt++;
>> +       spin_unlock(&drvdata->spinlock);
>> +
>> +       return 0;
>> +}
>> +
>> +static void trace_noc_disable_hw(struct trace_noc_drvdata *drvdata)
>> +{
>> +       writel_relaxed(0x0, drvdata->base + TRACE_NOC_CTRL);
> 
> Same with the comment above for using writel() to replace
> writel_relaxed().
sure.
> 
>> +       dev_dbg(drvdata->dev, "Trace NOC is disabled\n");
>> +}
>> +
>> +static void trace_noc_disable(struct coresight_device *csdev, struct coresight_connection *inport,
>> +                             struct coresight_connection *outport)
>> +{
>> +       struct trace_noc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       spin_lock(&drvdata->spinlock);
>> +       if (--csdev->refcnt == 0)
>> +               trace_noc_disable_hw(drvdata);
>> +
>> +       spin_unlock(&drvdata->spinlock);
>> +       dev_info(drvdata->dev, "Trace NOC is disabled\n");
>> +}
>> +
>> +static const struct coresight_ops_link trace_noc_link_ops = {
>> +       .enable         = trace_noc_enable,
>> +       .disable        = trace_noc_disable,
>> +};
>> +
>> +static const struct coresight_ops trace_noc_cs_ops = {
>> +       .link_ops       = &trace_noc_link_ops,
>> +};
>> +
>> +static int trace_noc_init_default_data(struct trace_noc_drvdata *drvdata)
>> +{
>> +       int atid;
>> +
>> +       atid = coresight_trace_id_get_system_id();
>> +       if (atid < 0)
>> +               return atid;
>> +
>> +       drvdata->atid = atid;
>> +
>> +       drvdata->freq_type = FREQ_TS;
> 
> I don't see anywhere uses FREQ.  Please remove the unused definitions
> and related code.
it is used in trace_noc_enable_hw().
> 
>> +       drvdata->flag_type = FLAG;
> 
> FLAG_TS is not used in the driver as well.  Remove it.
it is used in trace_noc_enable_hw().
> 
>> +       drvdata->freq_req_val = 0;
>> +
>> +       return 0;
>> +}
>> +
>> +static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
>> +{
>> +       struct device *dev = &adev->dev;
>> +       struct coresight_platform_data *pdata;
>> +       struct trace_noc_drvdata *drvdata;
>> +       struct coresight_desc desc = { 0 };
>> +       int ret;
>> +
>> +       desc.name = coresight_alloc_device_name(&trace_noc_devs, dev);
>> +       if (!desc.name)
>> +               return -ENOMEM;
>> +       pdata = coresight_get_platform_data(dev);
>> +       if (IS_ERR(pdata))
>> +               return PTR_ERR(pdata);
>> +       adev->dev.platform_data = pdata;
>> +
>> +       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
>> +       if (!drvdata)
>> +               return -ENOMEM;
>> +
>> +       drvdata->dev = &adev->dev;
>> +       dev_set_drvdata(dev, drvdata);
>> +
>> +       drvdata->base = devm_ioremap_resource(dev, &adev->res);
>> +       if (!drvdata->base)
>> +               return -ENOMEM;
>> +
>> +       spin_lock_init(&drvdata->spinlock);
>> +
>> +       ret = trace_noc_init_default_data(drvdata);
>> +       if (ret)
>> +               return ret;
>> +
>> +       desc.ops = &trace_noc_cs_ops;
>> +       desc.type = CORESIGHT_DEV_TYPE_LINK;
>> +       desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
>> +       desc.pdata = adev->dev.platform_data;
>> +       desc.dev = &adev->dev;
>> +       desc.access = CSDEV_ACCESS_IOMEM(drvdata->base);
>> +       drvdata->csdev = coresight_register(&desc);
>> +       if (IS_ERR(drvdata->csdev))
>> +               return PTR_ERR(drvdata->csdev);
>> +
>> +       pm_runtime_put(&adev->dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static void trace_noc_remove(struct amba_device *adev)
>> +{
>> +       struct trace_noc_drvdata *drvdata = dev_get_drvdata(&adev->dev);
>> +
>> +       coresight_trace_id_put_system_id(drvdata->atid);
>> +       coresight_unregister(drvdata->csdev);
>> +}
>> +
>> +static struct amba_id trace_noc_ids[] = {
>> +       {
>> +               .id     = 0x000f0c00,
>> +               .mask   = 0x000fff00,
> 
> Unlike Arm CoreSight drivers (the mask value is 0x000fffff in most
> cases), could you remind me why here the mask is 0x000fff00?
Because bit 0-7 has different values, records the number of trace initiator NIUs implemented in the NoC. 
> 
>> +       },
>> +       {},
>> +};
>> +MODULE_DEVICE_TABLE(amba, trace_noc_ids);
>> +
>> +static struct amba_driver trace_noc_driver = {
>> +       .drv = {
>> +               .name   = "coresight-trace-noc",
>> +               .owner  = THIS_MODULE,
> 
> I don't think you need to explicitly set `THIS_MODULE`, as this will
> be set default by amba_driver_register().
will remove in next version.
> 
>> +               .suppress_bind_attrs = true,
>> +       },
>> +       .probe          = trace_noc_probe,
>> +       .remove         = trace_noc_remove,
>> +       .id_table       = trace_noc_ids,
>> +};
>> +
>> +module_amba_driver(trace_noc_driver);
>> +
>> +MODULE_LICENSE("GPL");
>> +MODULE_DESCRIPTION("Trace NOC driver");
>> diff --git a/drivers/hwtracing/coresight/coresight-tnoc.h b/drivers/hwtracing/coresight/coresight-tnoc.h
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..b6bd1ef659897d8e0994c5e8514e8cbdd16eebd8
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-tnoc.h
>> @@ -0,0 +1,53 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#define TRACE_NOC_CTRL 0x008
>> +#define TRACE_NOC_XLD  0x010
>> +#define TRACE_NOC_FREQVAL      0x018
>> +#define TRACE_NOC_SYNCR        0x020
>> +
>> +/* Enable generation of output ATB traffic.*/
>> +#define TRACE_NOC_CTRL_PORTEN  BIT(0)
>> +/* Writing 1 to issue a FREQ or FREQ_TS packet*/
>> +#define TRACE_NOC_CTRL_FREQTSREQ       BIT(5)
> 
> This is not used.  Remove it.
it is used in trace_noc_enable_hw().
> 
>> +/* Sets the type of issued ATB FLAG packets. 0: 'FLAG' packets; 1: 'FLAG_TS' packets.*/
>> +#define TRACE_NOC_CTRL_FLAGTYPE                BIT(7)
> 
>> +/* sets the type of issued ATB FREQ packets. 0: 'FREQ' packets; 1: 'FREQ_TS' packets.*/
>> +#define TRACE_NOC_CTRL_FREQTYPE                BIT(8)
>> +DEFINE_CORESIGHT_DEVLIST(trace_noc_devs, "traceNoc");
> 
> It is good to move the definition into C file.
will update in next version.
> 
> Thanks,
> Leo
> 
>> +
>> +/**
>> + * struct trace_noc_drvdata - specifics associated to a trace noc component
>> + * @base:      memory mapped base address for this component.
>> + * @dev:       device node for trace_noc_drvdata.
>> + * @csdev:     component vitals needed by the framework.
>> + * @spinlock:  only one at a time pls.
>> + * @atid:      id for the trace packet.
>> + * @freqtype:  0: 'FREQ' packets; 1: 'FREQ_TS' packets.
>> + * @flagtype:  0: 'FLAG' packets; 1: 'FLAG_TS' packets.
>> + * @freq_req_val:       set frequency values carried by 'FREQ' and 'FREQ_TS' packets.
>> + */
>> +struct trace_noc_drvdata {
>> +       void __iomem            *base;
>> +       struct device           *dev;
>> +       struct coresight_device *csdev;
>> +       spinlock_t              spinlock; /* lock for the drvdata. */
>> +       u32                     atid;
>> +       u32                     freq_type;
>> +       u32                     flag_type;
>> +       u32                     freq_req_val;
>> +};
>> +
>> +/* freq type */
>> +enum freq_type {
>> +       FREQ,
>> +       FREQ_TS,
>> +};
>> +
>> +/* flag type */
>> +enum flag_type {
>> +       FLAG,
>> +       FLAG_TS,
>> +};
>>
>> --
>> 2.34.1
>>
>> _______________________________________________
>> CoreSight mailing list -- coresight at lists.linaro.org
>> To unsubscribe send an email to coresight-leave at lists.linaro.org



From geert at linux-m68k.org  Thu Mar  6 00:22:34 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 6 Mar 2025 09:22:34 +0100
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250305190955.GK847772@rocinante>
References: <20250304171154.njoygsvfd567pb66@thinkpad> <20250305173826.GA303920@bhelgaas>
 <20250305182833.cgrwbrcwzjscxmku@thinkpad> <20250305190955.GK847772@rocinante>
Message-ID: <CAMuHMdVRSjkss3gPnocXpfPQ=mEo4AevpaU=fdGvm=kb3RTmcQ@mail.gmail.com>

Hi Krzysztof,

On Wed, 5 Mar 2025 at 20:10, Krzysztof Wilczy?ski <kw at linux.com> wrote:
> [...]
> > > > Even though debugfs_init() failure is not supposed to fail the probe(),
> > > > dwc_pcie_rasdes_debugfs_init() has a devm_kzalloc() and propagating that
> > > > failure would be canolically correct IMO.
> > >
> > > I'm not sure about this.  What's the requirement to propagate
> > > devm_kzalloc() failures?  I think devres will free any allocs that
> > > were successful regardless.
> > >
> > > IIUC, we resolved the Gray Hawk Single issue by changing
> > > dwc_pcie_rasdes_debugfs_init() to return success without doing
> > > anything when there's no RAS DES Capability.
> > >
> > > But dwc_pcie_debugfs_init() can still return failure, and that still
> > > causes dw_pcie_ep_init_registers() to fail, which breaks the "don't
> > > propagate debugfs issues upstream" rule:
> > >
> > >   int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> > >   {
> > >           ...
> > >           ret = dwc_pcie_debugfs_init(pci);
> > >           if (ret)
> > >                   goto err_remove_edma;
> > >
> > >           return 0;
> > >
> > >   err_remove_edma:
> > >           dw_pcie_edma_remove(pci);
> > >
> > >           return ret;
> > >   }
> > >
> > > We can say that kzalloc() failure should "never" happen, and therefore
> > > it's OK to fail the driver probe if it happens, but that doesn't seem
> > > like a strong argument for breaking the "don't propagate debugfs
> > > issues" rule.  And someday there may be other kinds of failures from
> > > dwc_pcie_debugfs_init().

pcie-designware-debugfs.c only does small allocations.  If any of
these fail, you have much bigger problems, and the system will die soon,
irrespective of propagating the -ENOMEM or not...

Another issue is that the caller does not handle failures correctly,
given (A) the irqdomain WARNING I got, and (B) the half-registered
PCI bus, oopsing on "lspci"...

> > Fine with me. I was not too sure about propagating failure either.
>
> What if we do this?
>
> diff --git i/drivers/pci/controller/dwc/pcie-designware-debugfs.c w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> index 586a9d107434..fddf71f014c4 100644
> --- i/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> +++ w/drivers/pci/controller/dwc/pcie-designware-debugfs.c
> @@ -162,7 +162,7 @@ void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
>         debugfs_remove_recursive(pci->debugfs->debug_dir);
>  }
>
> -int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> +void dwc_pcie_debugfs_init(struct dw_pcie *pci)
>  {
>         char dirname[DWC_DEBUGFS_BUF_MAX];
>         struct device *dev = pci->dev;
> @@ -174,17 +174,15 @@ int dwc_pcie_debugfs_init(struct dw_pcie *pci)
>         snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
>         dir = debugfs_create_dir(dirname, NULL);
>         debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> -       if (!debugfs)
> -               return -ENOMEM;
> +       if (!debugfs) {
> +               dev_err(dev, "failed to allocate memory for debugfs\n");

There is no need to print an error message when a memory allocation
fails, as the memory allocation core already takes care of that.
So please drop the dev_err() call.

> +               return;
> +       }
>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From fnkl.kernel at gmail.com  Thu Mar  6 00:25:21 2025
From: fnkl.kernel at gmail.com (Sasha Finkelstein)
Date: Thu, 6 Mar 2025 09:25:21 +0100
Subject: [PATCH 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <f17372963b92074144b07d34f3e91ba7.sboyd@kernel.org>
References: <20250305-spmi-v1-0-c98f561fa99f@gmail.com> <20250305-spmi-v1-2-c98f561fa99f@gmail.com>
 <f17372963b92074144b07d34f3e91ba7.sboyd@kernel.org>
Message-ID: <CAMT+MTREFq2_ABXZF-WsAkw9qP6eXd7gQwgFGm7fw6nBntdbyQ@mail.gmail.com>

On Wed, 5 Mar 2025 at 23:11, Stephen Boyd <sboyd at kernel.org> wrote:
>
> Quoting Sasha Finkelstein via B4 Relay (2025-03-05 12:26:40)
> > +       while (len_to_read < bc) {
> > +               rsp = read_reg(spmi, SPMI_RSP_REG);
> > +               i = 0;
> > +               while ((len_to_read < bc) && (i < 4)) {
> > +                       __buf[len_to_read++] = ((0xff << (8 * i)) & rsp) >>
> > +                                              (8 * i);
> > +                       i += 1;
> > +               }
>
> Is this ioread32_rep()?
>
[...]
> > +       while (i < bc) {
> > +               j = 0;
> > +               spmi_cmd = 0;
> > +               while ((j < 4) & (i < bc))
> > +                       spmi_cmd |= __buf[i++] << (j++ * 8);
>
> Is this iowrite32_rep()? Perhaps unaligned sizes have to be dealt with,
> but otherwise I suspect it would be more efficient to use
> iowrite32_rep() until the number of bytes is less than 4 and then do the
> one extra pack.

I think it would be better to leave them open-coded, io{read,write}32_rep
casts the buffer to u32 and accesses it that way, probably resulting in
unaligned accesses, and we are on arm64.


From maxime.chevallier at bootlin.com  Thu Mar  6 00:28:57 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 6 Mar 2025 09:28:57 +0100
Subject: [PATCH net-next 1/2] net: phylink: add functions to
 block/unblock rx clock stop
In-Reply-To: <E1tpt2t-005UNB-MC@rmk-PC.armlinux.org.uk>
References: <Z8iRM8Q9Sb-y3fR_@shell.armlinux.org.uk>
	<E1tpt2t-005UNB-MC@rmk-PC.armlinux.org.uk>
Message-ID: <20250306092857.5cafd6d4@fedora.home>

Hello Russell,

On Wed, 05 Mar 2025 18:00:39 +0000
"Russell King (Oracle)" <rmk+kernel at armlinux.org.uk> wrote:

> Some MACs require the PHY receive clock to be running to complete setup
> actions. This may fail if the PHY has negotiated EEE, the MAC supports
> receive clock stop, and the link has entered LPI state. Provide a pair
> of APIs that MAC drivers can use to temporarily block the PHY disabling
> the receive clock.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

I only have comments on the implementation, see below :)

> ---
>  drivers/net/phy/phylink.c | 50 +++++++++++++++++++++++++++++++++++++++
>  include/linux/phylink.h   |  3 +++
>  2 files changed, 53 insertions(+)
> 
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index a3b186ab3854..8f93b597d019 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -88,6 +88,7 @@ struct phylink {
>  	bool mac_enable_tx_lpi;
>  	bool mac_tx_clk_stop;
>  	u32 mac_tx_lpi_timer;
> +	u8 mac_rx_clk_stop_blocked;
>  
>  	struct sfp_bus *sfp_bus;
>  	bool sfp_may_have_phy;
> @@ -2592,6 +2593,55 @@ void phylink_stop(struct phylink *pl)
>  }
>  EXPORT_SYMBOL_GPL(phylink_stop);
>  
> +
> +void phylink_rx_clk_stop_block(struct phylink *pl)
> +{
> +	ASSERT_RTNL();
> +
> +	if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
> +		phylink_warn(pl, "%s called too many times - ignoring\n",
> +			     __func__);
> +		dump_stack();
> +		return;
> +	}
> +
> +	/* Disable PHY receive clock stop if this is the first time this
> +	 * function has been called and clock-stop was previously enabled.
> +	 */
> +	if (pl->mac_rx_clk_stop_blocked++ == 0 &&
> +	    pl->mac_supports_eee_ops && pl->phydev)
> +	    pl->config->eee_rx_clk_stop_enable)

Looks like there's an extra closing ')' here

> +		phy_eee_rx_clock_stop(pl->phydev, false);
> +}

Do you need an EXPORT_SYMBOL_GPL here as this will be used by MAC
drivers?

> +
> +/**
> + * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
> + * @pl: a pointer to a &struct phylink returned from phylink_create()
> + *
> + * All calls to phylink_rx_clk_stop_block() must be balanced with a
> + * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
> + * clock stop ability.
> + */
> +void phylink_rx_clk_stop_unblock(struct phylink *pl)
> +{
> +	ASSERT_RTNL();
> +
> +	if (pl->mac_rx_clk_stop_blocked == 0) {
> +		phylink_warn(pl, "%s called too many times - ignoring\n",
> +			     __func__);
> +		dump_stack();
> +		return;
> +	}
> +
> +	/* Re-enable PHY receive clock stop if the number of unblocks matches
> +	 * the number of calls to the block function above.
> +	 */
> +	if (--pl->mac_rx_clk_stop_blocked == 0 &&
> +	    pl->mac_supports_eee_ops && pl->phydev &&
> +	    pl->config->eee_rx_clk_stop_enable)
> +		phy_eee_rx_clock_stop(pl->phydev, true);
> +}

Same for the EXPORT_SYMBOL_GPL

Thanks,

Maxime


From pabeni at redhat.com  Thu Mar  6 00:30:11 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Thu, 6 Mar 2025 09:30:11 +0100
Subject: [PATCH net-next v4 02/13] net: phy: Use an internal, searchable
 storage for the linkmodes
In-Reply-To: <20250303090321.805785-3-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
 <20250303090321.805785-3-maxime.chevallier@bootlin.com>
Message-ID: <738bd67c-8688-4902-805f-4e35e6aaed4a@redhat.com>

On 3/3/25 10:03 AM, Maxime Chevallier wrote:
[...]
> +static int speed_duplex_to_capa(int speed, unsigned int duplex)
> +{
> +	if (duplex == DUPLEX_UNKNOWN ||
> +	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
> +		return -EINVAL;
> +
> +	switch (speed) {
> +	case SPEED_10: return duplex == DUPLEX_FULL ?
> +			      LINK_CAPA_10FD : LINK_CAPA_10HD;
> +	case SPEED_100: return duplex == DUPLEX_FULL ?
> +			       LINK_CAPA_100FD : LINK_CAPA_100HD;
> +	case SPEED_1000: return duplex == DUPLEX_FULL ?
> +				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
> +	case SPEED_2500: return LINK_CAPA_2500FD;
> +	case SPEED_5000: return LINK_CAPA_5000FD;
> +	case SPEED_10000: return LINK_CAPA_10000FD;
> +	case SPEED_20000: return LINK_CAPA_20000FD;
> +	case SPEED_25000: return LINK_CAPA_25000FD;
> +	case SPEED_40000: return LINK_CAPA_40000FD;
> +	case SPEED_50000: return LINK_CAPA_50000FD;
> +	case SPEED_56000: return LINK_CAPA_56000FD;
> +	case SPEED_100000: return LINK_CAPA_100000FD;
> +	case SPEED_200000: return LINK_CAPA_200000FD;
> +	case SPEED_400000: return LINK_CAPA_400000FD;
> +	case SPEED_800000: return LINK_CAPA_800000FD;
> +	}
> +

What about adding some code here to help future patch updating LINK_CAPA
definition as needed?

Something alike:

	pr_err_once("Unknown speed %d, please update LINK_CAPS\n", speed);


> +	return -EINVAL;
> +}
> +
> +/**
> + * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
> + */
> +void phy_caps_init(void)
> +{
> +	const struct link_mode_info *linkmode;
> +	int i, capa;
> +
> +	/* Fill the caps array from net/ethtool/common.c */
> +	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
> +		linkmode = &link_mode_params[i];
> +		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
> +
> +		if (capa < 0)
> +			continue;

Or even error-out here.

/P



From axe.yang at mediatek.com  Thu Mar  6 00:48:06 2025
From: axe.yang at mediatek.com (Axe Yang)
Date: Thu, 6 Mar 2025 16:48:06 +0800
Subject: [PATCH 2/2] mmc: mtk-sd: add support to disable single burst
In-Reply-To: <20250306085028.5024-1-axe.yang@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
Message-ID: <20250306085028.5024-3-axe.yang@mediatek.com>

Add support to disable 'single' burst type if the bus type is AXI.
Since the AMBA within some of the legacy and new designed MSDC IP
is AXI, this switch is necessary.

The burst type is not IC-specific, but host-specific. So we use a
devicetree property 'mediatek,disable-single-burst' to switch burst
type for specific MSDC host.

Signed-off-by: Axe Yang <axe.yang at mediatek.com>
---
 drivers/mmc/host/mtk-sd.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 345ea91629e0..ed46c69def1e 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -249,6 +249,7 @@
 #define MSDC_PATCH_BIT1_CMDTA     GENMASK(5, 3)    /* RW */
 #define MSDC_PB1_BUSY_CHECK_SEL   BIT(7)    /* RW */
 #define MSDC_PATCH_BIT1_STOP_DLY  GENMASK(11, 8)    /* RW */
+#define MSDC_PB1_SINGLE_BURST     BIT(16)   /* RW */
 
 #define MSDC_PATCH_BIT2_CFGRESP   BIT(15)   /* RW */
 #define MSDC_PATCH_BIT2_CFGCRCSTS BIT(28)   /* RW */
@@ -485,6 +486,7 @@ struct msdc_host {
 	u32 src_clk_freq;	/* source clock frequency */
 	unsigned char timing;
 	bool vqmmc_enabled;
+	bool disable_single_burst;
 	u32 latch_ck;
 	u32 hs400_ds_delay;
 	u32 hs400_ds_dly3;
@@ -1874,6 +1876,10 @@ static void msdc_init_hw(struct msdc_host *host)
 	writel(0xffff4089, host->base + MSDC_PATCH_BIT1);
 	sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
 
+	if (host->disable_single_burst)
+		sdr_clr_bits(host->base + MSDC_PATCH_BIT1,
+			     MSDC_PB1_SINGLE_BURST);
+
 	if (host->dev_comp->stop_clk_fix) {
 		if (host->dev_comp->stop_dly_sel)
 			sdr_set_field(host->base + MSDC_PATCH_BIT1,
@@ -2820,6 +2826,10 @@ static void msdc_of_property_parse(struct platform_device *pdev,
 		host->cqhci = true;
 	else
 		host->cqhci = false;
+
+	host->disable_single_burst =
+		of_property_read_bool(pdev->dev.of_node,
+				      "mediatek,disable-single-burst");
 }
 
 static int msdc_of_clock_parse(struct platform_device *pdev,
-- 
2.46.0



From xianwei.zhao at amlogic.com  Thu Mar  6 00:51:42 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Thu, 6 Mar 2025 16:51:42 +0800
Subject: [PATCH v3 1/4] dt-bindings: interrupt-controller: Add support for
 Amlogic A4 and A5 SoCsy
In-Reply-To: <20250305170723.GA2143418-robh@kernel.org>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>
 <20250305-corral-unfair-a7f25abbfd64@spud>
 <20250305170723.GA2143418-robh@kernel.org>
Message-ID: <5631fbe4-54a4-447f-ad45-e69d9484919b@amlogic.com>

Hi Rob,
    Thanks for your advice.

On 2025/3/6 01:07, Rob Herring wrote:
> [ EXTERNAL EMAIL ]
> 
> On Wed, Mar 05, 2025 at 04:28:16PM +0000, Conor Dooley wrote:
>> On Wed, Mar 05, 2025 at 06:02:56PM +0800, Xianwei Zhao via B4 Relay wrote:
>>> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>>
>>> Update dt-binding document for GPIO interrupt controller
>>> of Amlogic A4 and A5 SoCs
>>>
>>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>> ---
>>>   .../amlogic,meson-gpio-intc.yaml                    | 21 +++++++++++++++++++--
>>>   1 file changed, 19 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>>> index a93744763787..3c5853c71efa 100644
>>> --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>>> +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>>> @@ -35,6 +35,9 @@ properties:
>>>                 - amlogic,meson-sm1-gpio-intc
>>>                 - amlogic,meson-a1-gpio-intc
>>>                 - amlogic,meson-s4-gpio-intc
>>> +              - amlogic,a4-gpio-intc
>>> +              - amlogic,a4-gpio-ao-intc
>>> +              - amlogic,a5-gpio-intc
>>>                 - amlogic,c3-gpio-intc
>>>                 - amlogic,t7-gpio-intc
>>>             - const: amlogic,meson-gpio-intc
>>> @@ -49,8 +52,6 @@ properties:
>>>
>>>     amlogic,channel-interrupts:
>>>       description: Array with the upstream hwirq numbers
>>> -    minItems: 8
>>> -    maxItems: 12
>>
>> Please leave the widest constraints here, and let the more restricted
>> ones in your if/else below.
>>
>>>       $ref: /schemas/types.yaml#/definitions/uint32-array
>>>
>>>   required:
>>> @@ -60,6 +61,22 @@ required:
>>>     - "#interrupt-cells"
>>>     - amlogic,channel-interrupts
>>>
>>> +if:
>>> +  properties:
>>> +    compatible:
>>> +      contains:
>>> +        const: amlogic,a4-gpio-ao-intc
>>> +then:
>>> +  properties:
>>> +    amlogic,channel-interrupts:
>>> +      minItems: 2
>>> +      maxItems: 12
> 
> And then you don't need this clause as 2-12 is the full range.
> 

Indeed only 2. Will fix it.

>>> +else:
>>> +  properties:
>>> +    amlogic,channel-interrupts:
>>> +      minItems: 8
>>> +      maxItems: 12
> 
> And 12 is already the max, so you only need 'minItems: 8'.
> 

Will do.

>>> +
>>>   additionalProperties: false
>>>
>>>   examples:
>>>
>>> --
>>> 2.37.1
>>>
>>>
> 
> 


From menglong8.dong at gmail.com  Thu Mar  6 00:50:58 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Thu, 6 Mar 2025 16:50:58 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CAADnVQJ0_+Hij=kf9eVPX_ZND=2=uDHaYPWvv1x-WmR5sZRSmA@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
 <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
 <20250305100306.4685333a@gandalf.local.home> <CADxym3ZB_eQny=-aO4AwrHiwT264NXitdKwjRUYrnGJ2tH=Qwg@mail.gmail.com>
 <CAADnVQJ0_+Hij=kf9eVPX_ZND=2=uDHaYPWvv1x-WmR5sZRSmA@mail.gmail.com>
Message-ID: <CADxym3YMeAPpc+ozM2E7yW1qpB_arKJiDyAcRs8pW8sRqJZOZw@mail.gmail.com>

On Thu, Mar 6, 2025 at 11:39?AM Alexei Starovoitov
<alexei.starovoitov at gmail.com> wrote:
>
> On Wed, Mar 5, 2025 at 6:59?PM Menglong Dong <menglong8.dong at gmail.com> wrote:
> >
> > I'm not sure if it works. However, indirect call is also used
> > in function graph, so we still have better performance. Isn't it?
> >
> > Let me have a look at the code of the function graph first :/
>
> Menglong,
>
> Function graph infra isn't going to help.
> "call foo" isn't a problem either.
>
> But we have to step back.
> per-function metadata is an optimization and feels like
> we're doing a premature optimization here without collecting
> performance numbers first.
>
> Let's implement multi-fentry with generic get_metadata_by_ip() first.
> get_metadata_by_ip() will be a hashtable in such a case and
> then we can compare its performance when it's implemented as
> a direct lookup from ip-4 (this patch) vs hash table
> (that does 'ip' to 'metadata' lookup).

Hi, Alexei

You are right, I should do such a performance comparison.

>
> If/when we decide to do this per-function metadata we can also
> punt to generic hashtable for cfi, IBT, FineIBT, etc configs.
> When mitigations are enabled the performance suffers anyway,
> so hashtable lookup vs direct ip-4 lookup won't make much difference.
> So we can enable per-function metadata only on non-mitigation configs
> when FUNCTION_ALIGNMENT=16.
> There will be some number of bytes available before every function
> and if we can tell gcc/llvm to leave at least 5 bytes there
> the growth of vmlinux .text will be within a noise.

Sounds great! It's so different to make the per-function metadata
work in all the cases. Especially, we can't implement it in arm64
if CFI_CLANG is enabled. And the fallbacking to the hash table makes
it much easier in these cases.

>
> So let's figure out the design of multi-fenty first with a hashtable
> for metadata and decide next steps afterwards.

Ok, I'll develop a version for fentry multi-link with both hashtable
and function metadata, and do some performance testing. Thank
you for your advice :/

Thanks!
Menglong Dong


From andyshrk at 163.com  Thu Mar  6 00:53:21 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 6 Mar 2025 16:53:21 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
Message-ID: <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>


Hi,

? 2025-03-06 16:42:00?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 01:59:
>> 
>> 
>> 
>> 
>> Both of the two config options should be enabled.
>> andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
>> 4044:CONFIG_ROCKCHIP_DW_DP=y
>
>here i?m a bit lost?.
>greping on full kernel sources (with applied https://patchwork.kernel.org/project/linux-rockchip/list/?series=936784) gives me no single appearance of ROCKCHIP_DW_DP?
>Do i miss something?

see PATCH 3/6:   


diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 26c4410b2407..c8638baf9641 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
 	select DRM_PANEL
 	select VIDEOMODE_HELPERS
 	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
+	select DRM_DW_DP if ROCKCHIP_DW_DP
 	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
 	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
 	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
@@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
 	  RK3399 based SoC, you should select this
 	  option.
 
+config ROCKCHIP_DW_DP
+	bool "Rockchip specific extensions for Synopsys DW DP"
+	help
+	  Choose this option for Synopsys DesignWare Cores DisplayPort
+	  transmit controller support on Rockchip SoC.

 https://lore.kernel.org/linux-rockchip/047EECFC-7E55-44EC-896F-13FE04333E4D at gmail.com/T/#m178a325ea0ebc64187aae474d77c3f7a9e0bc93d
>

From miquel.raynal at bootlin.com  Thu Mar  6 00:56:42 2025
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Thu, 06 Mar 2025 09:56:42 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <D891QPQIT13L.1S55ZM1J286PE@kernel.org> (Michael Walle's message
	of "Thu, 06 Mar 2025 09:39:31 +0100")
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
	<D889CRJC6W19.2LDQCDVG7BLNG@kernel.org>
	<6fee6e71-106f-474b-9a0c-5df5fb0caa00@microchip.com>
	<87eczawo9q.fsf@bootlin.com> <D891QPQIT13L.1S55ZM1J286PE@kernel.org>
Message-ID: <87o6yev8ol.fsf@bootlin.com>


>> >> I don't think it makes sense to have this one-off in a particular
>> >> driver. If at all, this should be handled in the core. Sorry, but
>> >> this really looks like an ugly hack.
>> >> 
>> >
>> > Because the EUI identifier within the SFDP is unique to the 
>> > SST26VF064BEUI flash, I opted to handle it here rather than in the core.
>> >
>> > Also here the MAC address data resides within the 0x260-0x26F range, I 
>> > will resize the nvmem_config.size to 0x10 instead of registering the 
>> > full SFDP region as NVMEM.
>>
>> Open question to all parties in this thread: how do we give an offset in
>> the device tree that is relative to the sfdp region and not the data
>> region? I believe we care not to mix these areas while describing.
>
> You don't do it, because there is not even a relative offset that is
> fixed. There should be a pointer to the vendor table inside the SFDP
> structure. Thus, you need to properly parse it.

If there is nothing static and the location can be derived by reading
the chip tables, I'd suggest to offload this out of the spi-nor core and
instead use some kind of an nvmem layout driver to retrieve the
corresponding region?

> Regarding how to reference it within the device tree, I'd assume
> something along 'compatible = "jedec,sfdp-vendor-table-NNN";' or
> similar. But no static/relative offsets.

I see. We need to invoke our DT binding gurus.

Cheers,
Miqu?l


From maxime.chevallier at bootlin.com  Thu Mar  6 00:57:26 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 6 Mar 2025 09:57:26 +0100
Subject: [PATCH net-next v4 02/13] net: phy: Use an internal, searchable
 storage for the linkmodes
In-Reply-To: <738bd67c-8688-4902-805f-4e35e6aaed4a@redhat.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
	<20250303090321.805785-3-maxime.chevallier@bootlin.com>
	<738bd67c-8688-4902-805f-4e35e6aaed4a@redhat.com>
Message-ID: <20250306095726.04125e5f@fedora.home>

Hello Paolo,

On Thu, 6 Mar 2025 09:30:11 +0100
Paolo Abeni <pabeni at redhat.com> wrote:

> On 3/3/25 10:03 AM, Maxime Chevallier wrote:
> [...]
> > +static int speed_duplex_to_capa(int speed, unsigned int duplex)
> > +{
> > +	if (duplex == DUPLEX_UNKNOWN ||
> > +	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
> > +		return -EINVAL;
> > +
> > +	switch (speed) {
> > +	case SPEED_10: return duplex == DUPLEX_FULL ?
> > +			      LINK_CAPA_10FD : LINK_CAPA_10HD;
> > +	case SPEED_100: return duplex == DUPLEX_FULL ?
> > +			       LINK_CAPA_100FD : LINK_CAPA_100HD;
> > +	case SPEED_1000: return duplex == DUPLEX_FULL ?
> > +				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
> > +	case SPEED_2500: return LINK_CAPA_2500FD;
> > +	case SPEED_5000: return LINK_CAPA_5000FD;
> > +	case SPEED_10000: return LINK_CAPA_10000FD;
> > +	case SPEED_20000: return LINK_CAPA_20000FD;
> > +	case SPEED_25000: return LINK_CAPA_25000FD;
> > +	case SPEED_40000: return LINK_CAPA_40000FD;
> > +	case SPEED_50000: return LINK_CAPA_50000FD;
> > +	case SPEED_56000: return LINK_CAPA_56000FD;
> > +	case SPEED_100000: return LINK_CAPA_100000FD;
> > +	case SPEED_200000: return LINK_CAPA_200000FD;
> > +	case SPEED_400000: return LINK_CAPA_400000FD;
> > +	case SPEED_800000: return LINK_CAPA_800000FD;
> > +	}
> > +  
> 
> What about adding some code here to help future patch updating LINK_CAPA
> definition as needed?
> 
> Something alike:
> 
> 	pr_err_once("Unknown speed %d, please update LINK_CAPS\n", speed);
> 
> 
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
> > + */
> > +void phy_caps_init(void)
> > +{
> > +	const struct link_mode_info *linkmode;
> > +	int i, capa;
> > +
> > +	/* Fill the caps array from net/ethtool/common.c */
> > +	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
> > +		linkmode = &link_mode_params[i];
> > +		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
> > +
> > +		if (capa < 0)
> > +			continue;  
> 
> Or even error-out here.

Good point yes indeed. Russell raised the point for the need of keeping
this in sync with new SPEED_XXX definitions, I'll add a check that
errors out.

I hope that's OK though, as higher speeds are introduced and used by
NICs that usually don't use phylib at all, so there's a good chance
that the developper introducing the new speed won't have CONFIG_PHYLIB
enabled.

Is that still good ?

Maxime


From pabeni at redhat.com  Thu Mar  6 00:56:32 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Thu, 6 Mar 2025 09:56:32 +0100
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <20250303090321.805785-10-maxime.chevallier@bootlin.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
 <20250303090321.805785-10-maxime.chevallier@bootlin.com>
Message-ID: <350bb4f6-f4b5-44c3-a821-ac53c8641705@redhat.com>

On 3/3/25 10:03 AM, Maxime Chevallier wrote:
> @@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
>  	linkmode_copy(pl->link_config.advertising, pl->supported);
>  	phylink_validate(pl, pl->supported, &pl->link_config);
>  
> -	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
> -			       pl->supported, true);
> +	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
> +			    pl->supported, true);
> +	if (c)
> +		linkmode_and(match, pl->supported, c->linkmodes);

How about using only the first bit from `c->linkmodes`, to avoid
behavior changes?

Thanks!

Paolo



From krzysztof.kozlowski at linaro.org  Thu Mar  6 00:58:48 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Thu,  6 Mar 2025 09:58:48 +0100
Subject: [PATCH 1/2] dt-bindings: memory-controllers: samsung,exynos4210-srom: Enforce child props
Message-ID: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>

Samsung Exynos SROM peripheral properties were moved from the device
schema to separate "peripheral-props" schema for child node, but the
device schema does not reference the new one.

Reference the peripheral-props schema so the child nodes will be
properly validated from the device schema.

Fixes: 67bf606fcf18 ("dt-bindings: memory-controllers: samsung,exynos4210-srom: Split out child node properties")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Fix for Rob's tree.
---
 .../devicetree/bindings/memory-controllers/exynos-srom.yaml      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
index 2267c5107d60..1578514ec58d 100644
--- a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
@@ -38,6 +38,7 @@ properties:
 patternProperties:
   "^.*@[0-3],[a-f0-9]+$":
     type: object
+    $ref: mc-peripheral-props.yaml#
     additionalProperties: true
 
     properties:
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Thu Mar  6 00:58:49 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Thu,  6 Mar 2025 09:58:49 +0100
Subject: [PATCH 2/2] dt-bindings: memory-controllers: qcom,ebi2: Enforce child props
In-Reply-To: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
References: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250306085849.32852-2-krzysztof.kozlowski@linaro.org>

Qualcomm EBI2 peripheral properties were moved from the device schema to
separate "peripheral-props" schema for child node, but the device schema
does not reference the new one.

Reference the peripheral-props schema so the child nodes will be
properly validated from the device schema.

Fixes: 06652f348f28 ("dt-bindings: memory-controllers: qcom,ebi2: Split out child node properties")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Fix for Rob's tree.
---
 .../devicetree/bindings/memory-controllers/qcom,ebi2.yaml        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/qcom,ebi2.yaml b/Documentation/devicetree/bindings/memory-controllers/qcom,ebi2.yaml
index 3e6da1ba460e..423d7a75134f 100644
--- a/Documentation/devicetree/bindings/memory-controllers/qcom,ebi2.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/qcom,ebi2.yaml
@@ -104,6 +104,7 @@ required:
 patternProperties:
   "^.*@[0-5],[0-9a-f]+$":
     type: object
+    $ref: mc-peripheral-props.yaml#
     additionalProperties: true
 
 additionalProperties: false
-- 
2.43.0



From amadeus at jmu.edu.cn  Thu Mar  6 01:00:01 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 17:00:01 +0800
Subject: [PATCH 0/3] rockchip: Add support for onboard eMMC on Radxa E20C
In-Reply-To: <20250305214108.1327208-1-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
Message-ID: <20250306090001.113127-1-amadeus@jmu.edu.cn>

Hi,

> Driver changes to use different delay and tap num is needed to be able
> to support HS400 modes, something for a future series. With this HS200
> mode should work:

I have tried HS200 mode on other rk3528 boards and it works fine,
so can we enable HS200 mode for Radxa E20C first?

Thanks,
Chukun

-- 
2.25.1



From kw at linux.com  Thu Mar  6 01:02:34 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Thu, 6 Mar 2025 18:02:34 +0900
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <CAMuHMdVRSjkss3gPnocXpfPQ=mEo4AevpaU=fdGvm=kb3RTmcQ@mail.gmail.com>
References: <20250304171154.njoygsvfd567pb66@thinkpad>
 <20250305173826.GA303920@bhelgaas>
 <20250305182833.cgrwbrcwzjscxmku@thinkpad>
 <20250305190955.GK847772@rocinante>
 <CAMuHMdVRSjkss3gPnocXpfPQ=mEo4AevpaU=fdGvm=kb3RTmcQ@mail.gmail.com>
Message-ID: <20250306090234.GA390800@rocinante>

Hello,

[...]
> Another issue is that the caller does not handle failures correctly,
> given (A) the irqdomain WARNING I got, and (B) the half-registered
> PCI bus, oopsing on "lspci"...

This is something we will look into.  A more robust DesignWare core is
something we would definitely want to have.

Sorry about the issues with this...

[...]
> > -int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > +void dwc_pcie_debugfs_init(struct dw_pcie *pci)
> >  {
> >         char dirname[DWC_DEBUGFS_BUF_MAX];
> >         struct device *dev = pci->dev;
> > @@ -174,17 +174,15 @@ int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> >         snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> >         dir = debugfs_create_dir(dirname, NULL);
> >         debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > -       if (!debugfs)
> > -               return -ENOMEM;
> > +       if (!debugfs) {
> > +               dev_err(dev, "failed to allocate memory for debugfs\n");
> 
> There is no need to print an error message when a memory allocation
> fails, as the memory allocation core already takes care of that.
> So please drop the dev_err() call.

Done.  Thank you!

	Krzysztof


From arnd at arndb.de  Thu Mar  6 01:02:49 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 06 Mar 2025 10:02:49 +0100
Subject: [PATCH] irqchip: davinci: remove leftover header
In-Reply-To: <20250306084552.15894-1-brgl@bgdev.pl>
References: <20250306084552.15894-1-brgl@bgdev.pl>
Message-ID: <1f599860-0276-47a2-89cb-e655e516cf23@app.fastmail.com>

On Thu, Mar 6, 2025, at 09:45, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
>
> Commit fa8dede4d0a0 ("irqchip: remove davinci aintc driver") removed the
> davinci aintc driver but left behind the associated header. Remove it
> now.
>
> Fixes: fa8dede4d0a0 ("irqchip: remove davinci aintc driver")
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Acked-by: Arnd Bergmann <arnd at arndb.de>


From michael.riesch at wolfvision.net  Thu Mar  6 01:05:22 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 6 Mar 2025 10:05:22 +0100
Subject: [PATCH v4 06/11] media: rockchip: rkcif: add driver for mipi
 csi-2 host
In-Reply-To: <3fztpczfxlfzt3bdll4alzllrrqvvr3akhkiqtmtam2v2sbw2y@6hb3aok7h62x>
References: <20250219-v6-8-topic-rk3568-vicap-v4-0-e906600ae3b0@wolfvision.net>
 <20250219-v6-8-topic-rk3568-vicap-v4-6-e906600ae3b0@wolfvision.net>
 <3fztpczfxlfzt3bdll4alzllrrqvvr3akhkiqtmtam2v2sbw2y@6hb3aok7h62x>
Message-ID: <137eeb26-65df-4dfa-bece-08a7758ae5c2@wolfvision.net>

Hi Mehdi,

On 3/4/25 20:41, Mehdi Djait wrote:
> Hi Michael,
> 
> thank you for the patches.
> 
> Sorry for the big delay!

No worries, thanks for your comments!

> 
> On Wed, Feb 19, 2025 at 11:16:37AM +0100, Michael Riesch wrote:
>> The Rockchip RK3568 MIPI CSI-2 Host is a CSI-2 bridge with one input port
>> and one output port. It receives the data with the help of an external
>> MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip RK3568 Video
>> Capture (VICAP) block. Add a V4L2 subdevice driver for this unit.
>>
>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>> ---
>>  drivers/media/platform/rockchip/rkcif/Makefile     |   1 +
>>  .../platform/rockchip/rkcif/rkcif-mipi-csi-host.c  | 731 +++++++++++++++++++++
>>  2 files changed, 732 insertions(+)
>>
>> diff --git a/drivers/media/platform/rockchip/rkcif/Makefile b/drivers/media/platform/rockchip/rkcif/Makefile
>> index 818424972c7b..0c18efd1f1b4 100644
>> --- a/drivers/media/platform/rockchip/rkcif/Makefile
>> +++ b/drivers/media/platform/rockchip/rkcif/Makefile
>> @@ -4,4 +4,5 @@ rockchip-cif-objs += rkcif-dev.o \
>>  	rkcif-capture-dvp.o \
>>  	rkcif-capture-mipi.o \
>>  	rkcif-interface.o \
>> +	rkcif-mipi-csi-host.o \
> 
> [..]
> 
>>  	rkcif-stream.o
>> diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
>> new file mode 100644
>> index 000000000000..fa3f42b2dc55
> 
> SNIP
> 
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
>> +
>> +static struct platform_driver rkcif_csi_drv = {
>> +	.driver = {
>> +		   .name = "rockchip-mipi-csi",
>> +		   .of_match_table = rkcif_csi_of_match,
>> +		   .pm = &rkcif_csi_pm_ops,
>> +	},
>> +	.probe = rkcif_csi_probe,
>> +	.remove = rkcif_csi_remove,
>> +};
>> +module_platform_driver(rkcif_csi_drv);
> 
> [..]
> 
> When adding the driver for this CSI-2 Host bridge, you added another
> call to  module_platform_driver()
> 
> but in the definition of this macro:
> 
> "Each module may only use this macro once, and
> calling it replaces module_init() and module_exit()"
> 
> and as you can see in the diff of the Makefile,
> rkcif-mipi-csi-host.0 is part of the same module as rkcif-dev.o, where
> you already call module_platform_driver()

Indeed. Found that only after submitting v4... :-/

> I think the solution here is to call
> platform_register_drivers(drivers, ARRAY_SIZE(drivers)) in rkcif-dev.c
> 
> with
> 
> static struct platform_driver * const drivers[] = {
> 	&rkcif_csi_drv,
> 	&rkcif_plat_drv,
> };
> 
> then define module_init() and module_exit()

Ah, I haven't thought of that approach. Actually, I was going to split
the cif part and the mipi host part into two modules. This would keep
things modular (literally). What do you think about that?

> 
> Btw. MODULE_DEVICE_TABLE() is missing both here and in rkcif-dev.c

Huh, indeed. Nice catch, thanks!

Best regards,
Michael

> 
>> +
>> +MODULE_DESCRIPTION("Rockchip MIPI CSI-2 Host platform driver");
>> +MODULE_LICENSE("GPL");
>>
>> -- 
>> 2.34.1
>>
> 
> --
> Kind Regards
> Mehdi Djait



From andy.shevchenko at gmail.com  Thu Mar  6 01:05:08 2025
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Thu, 6 Mar 2025 11:05:08 +0200
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain> <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
Message-ID: <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>

On Thu, Mar 6, 2025 at 10:39?AM Choong Yong Liang
<yong.liang.choong at linux.intel.com> wrote:
> On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
> > Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:

...

> >> config DWMAC_INTEL
> >>      default X86
> >>      depends on X86 && STMMAC_ETH && PCI
> >>      depends on COMMON_CLK
> >> +    depends on ACPI
> > Stray and unexplained change. Please, fix it. We don't need the dependencies
> > which are not realised in the compile time.
>
> The dependency on ACPI is necessary because the intel_pmc_ipc.h header
> relies on ACPI functionality to interact with the Intel PMC.

So, that header has to be fixed as ACPI here is really unneeded
dependency for the cases when somebody (for whatever reasons) want to
build a kernel without ACPI support but with the driver enabled for
let's say PCI device.


-- 
With Best Regards,
Andy Shevchenko


From linus.walleij at linaro.org  Thu Mar  6 01:12:22 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 6 Mar 2025 10:12:22 +0100
Subject: [PATCH] rtc: pl031: document struct pl031_vendor_data members
In-Reply-To: <20250305221659.1153495-1-alexandre.belloni@bootlin.com>
References: <20250305221659.1153495-1-alexandre.belloni@bootlin.com>
Message-ID: <CACRpkdZKbEXEabB+4uYvbBRXfFR_Jk-hHVtrZYD+cpKXgcMsnA@mail.gmail.com>

On Wed, Mar 5, 2025 at 11:17?PM <alexandre.belloni at bootlin.com> wrote:

> From: Alexandre Belloni <alexandre.belloni at bootlin.com>
>
> Document the range related members of struct pl031_vendor_data.
>
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503011015.SYvdddTc-lkp at intel.com/
> Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From krzk at kernel.org  Thu Mar  6 00:31:57 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 09:31:57 +0100
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <012701db8e6b$950550c0$bf0ff240$@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
 <20250305091246.106626-2-swathi.ks@samsung.com>
 <789ecb2f-dddc-491b-b9f8-5fb89058fd1b@kernel.org>
 <012701db8e6b$950550c0$bf0ff240$@samsung.com>
Message-ID: <1f14fdfe-379b-4718-812b-820c90f58e27@kernel.org>

On 06/03/2025 08:44, Swathi K S wrote:
> 
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: 06 March 2025 12:45
>> To: Swathi K S <swathi.ks at samsung.com>; krzk+dt at kernel.org;
>> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
>> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
>> conor+dt at kernel.org; richardcochran at gmail.com;
>> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com
>> Cc: rmk+kernel at armlinux.org.uk; netdev at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-stm32 at st-md-mailman.stormreply.com;
>> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
>> pankaj.dubey at samsung.com; ravi.patel at samsung.com;
>> gost.dev at samsung.com
>> Subject: Re: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
>> bindings
>>
>> On 05/03/2025 10:12, Swathi K S wrote:
>>> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
>>> Ethernet YAML schema to enable the DT validation.
>>>
>>> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
>>> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
>>> Signed-off-by: Swathi K S <swathi.ks at samsung.com>
>>> ---
>>>  .../devicetree/bindings/net/snps,dwmac.yaml   |   5 +-
>>>  .../bindings/net/tesla,fsd-ethqos.yaml        | 118 ++++++++++++++++++
>>>  2 files changed, 121 insertions(+), 2 deletions(-)  create mode
>>> 100644 Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml
>>>
>>
>> I tried and did not see any differences, so point me exactly to any difference
>> in the binding (binding!) which would justify dropping review?
> 
> Added the following in the example given in DT binding doc:

OK, but that's an example, not the binding, so no new properties in the
binding.

> 
> assigned-clocks = <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
>                                 <&clock_peric PERIC_EQOS_PHYRXCLK>;
> assigned-clock-parents = <&clock_peric PERIC_EQOS_PHYRXCLK>;
> 
> Given the significance of these changes, I assumed the changes need to be reviewed again.

Adding standard properties to the example is not significant change. It
is really a minor change.



Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar  6 00:33:00 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 09:33:00 +0100
Subject: [PATCH v8 1/2] dt-bindings: net: Add FSD EQoS device tree
 bindings
In-Reply-To: <20250305091246.106626-2-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091852epcas5p18a0853e85a5ed3d36d5d42ef89735ca6@epcas5p1.samsung.com>
 <20250305091246.106626-2-swathi.ks@samsung.com>
Message-ID: <c1bf7e68-c23b-4e73-8369-4480c7f080fc@kernel.org>

On 05/03/2025 10:12, Swathi K S wrote:
> Add FSD Ethernet compatible in Synopsys dt-bindings document. Add FSD
> Ethernet YAML schema to enable the DT validation.
> 
> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> Signed-off-by: Ravi Patel <ravi.patel at samsung.com>
> Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From miquel.raynal at bootlin.com  Thu Mar  6 00:34:41 2025
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Thu, 06 Mar 2025 09:34:41 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <6fee6e71-106f-474b-9a0c-5df5fb0caa00@microchip.com> (Manikandan
	M.'s message of "Thu, 6 Mar 2025 07:09:44 +0000")
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
	<D889CRJC6W19.2LDQCDVG7BLNG@kernel.org>
	<6fee6e71-106f-474b-9a0c-5df5fb0caa00@microchip.com>
Message-ID: <87eczawo9q.fsf@bootlin.com>


>>> +static int sst26vf_nor_post_sfdp(struct spi_nor *nor)
>>> +{
>>> +     struct nvmem_device *nvmem;
>>> +
>>> +     sst26vf_sfdp_nvmem_config.dev = nor->dev;
>>> +     sst26vf_sfdp_nvmem_config.size = nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords);
>>> +     sst26vf_sfdp_nvmem_config.priv = nor;
>>> +     sst26vf_sfdp_nvmem_config.reg_read = sst26vf_sfdp_mac_addr_read;
>>> +
>>> +     nvmem = devm_nvmem_register(nor->dev, &sst26vf_sfdp_nvmem_config);
>>> +     if (IS_ERR(nvmem)) {
>>> +             dev_err(nor->dev, "failed to register NVMEM device: %ld\n", PTR_ERR(nvmem));
>>> +             return PTR_ERR(nvmem);
>> 
>> I don't think it makes sense to have this one-off in a particular
>> driver. If at all, this should be handled in the core. Sorry, but
>> this really looks like an ugly hack.
>> 
>
> Because the EUI identifier within the SFDP is unique to the 
> SST26VF064BEUI flash, I opted to handle it here rather than in the core.
>
> Also here the MAC address data resides within the 0x260-0x26F range, I 
> will resize the nvmem_config.size to 0x10 instead of registering the 
> full SFDP region as NVMEM.

Open question to all parties in this thread: how do we give an offset in
the device tree that is relative to the sfdp region and not the data
region? I believe we care not to mix these areas while describing.

Thanks,
Miqu?l


From fabrice.gasnier at foss.st.com  Thu Mar  6 00:34:07 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 6 Mar 2025 09:34:07 +0100
Subject: [PATCH v2] clocksource: stm32-lptimer: use wakeup capable instead of init wakeup
Message-ID: <20250306083407.2374894-1-fabrice.gasnier@foss.st.com>

From: Alexandre Torgue <alexandre.torgue at foss.st.com>

"wakeup-source" property describes a device which has wakeup capability
but should not force this device as a wakeup source.

Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver")
Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 drivers/clocksource/timer-stm32-lp.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index a4c95161cb22..193e4f643358 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 	}
 
 	if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
-		ret = device_init_wakeup(&pdev->dev, true);
-		if (ret)
-			goto out_clk_disable;
+		device_set_wakeup_capable(&pdev->dev, true);
 
 		ret = dev_pm_set_wake_irq(&pdev->dev, irq);
 		if (ret)
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Thu Mar  6 00:37:15 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 6 Mar 2025 09:37:15 +0100
Subject: [PATCH] clocksource: stm32-lptimer: use wakeup capable instead of
 init wakeup
In-Reply-To: <a7489f16-ca31-4530-8ef1-33079b3c99a9@linaro.org>
References: <20250305125146.1858978-1-fabrice.gasnier@foss.st.com>
 <a7489f16-ca31-4530-8ef1-33079b3c99a9@linaro.org>
Message-ID: <4081d99c-1283-45a4-9cb8-8e6f8dbd635d@foss.st.com>

On 3/5/25 18:23, Daniel Lezcano wrote:
> On 05/03/2025 13:51, Fabrice Gasnier wrote:
>> From: Alexandre Torgue <alexandre.torgue at foss.st.com>
>>
>> "wakeup-source" property describes a device which has wakeup capability
>> but should not force this device as a wakeup source.
> 
> Is that a fix to be carried on ?

Hi Daniel,

Thanks for reviewing,
I just have sent a V2 with Fixes tag, and have CC'ed stable.

Please review there,
Best Regards,
Fabrice

Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver")
> 
>> Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
>> ---
>> ? drivers/clocksource/timer-stm32-lp.c | 4 +---
>> ? 1 file changed, 1 insertion(+), 3 deletions(-)
>>
>> diff --git a/drivers/clocksource/timer-stm32-lp.c
>> b/drivers/clocksource/timer-stm32-lp.c
>> index 96d975adf7a4..f08baa6720f8 100644
>> --- a/drivers/clocksource/timer-stm32-lp.c
>> +++ b/drivers/clocksource/timer-stm32-lp.c
>> @@ -186,9 +186,7 @@ static int stm32_clkevent_lp_probe(struct
>> platform_device *pdev)
>> ????? }
>> ? ????? if (of_property_read_bool(pdev->dev.parent->of_node,
>> "wakeup-source")) {
>> -??????? ret = device_init_wakeup(&pdev->dev, true);
>> -??????? if (ret)
>> -??????????? goto out_clk_disable;
>> +??????? device_set_wakeup_capable(&pdev->dev, true);
>> ? ????????? ret = dev_pm_set_wake_irq(&pdev->dev, irq);
>> ????????? if (ret)
> 
> 


From mwalle at kernel.org  Thu Mar  6 00:39:31 2025
From: mwalle at kernel.org (Michael Walle)
Date: Thu, 06 Mar 2025 09:39:31 +0100
Subject: [PATCH 1/2] mtd: spi-nor: sst: register SFDP region into NVMEM
 framework to read MAC Address
In-Reply-To: <87eczawo9q.fsf@bootlin.com>
References: <20250305100134.1171124-1-manikandan.m@microchip.com>
 <D889CRJC6W19.2LDQCDVG7BLNG@kernel.org>
 <6fee6e71-106f-474b-9a0c-5df5fb0caa00@microchip.com>
 <87eczawo9q.fsf@bootlin.com>
Message-ID: <D891QPQIT13L.1S55ZM1J286PE@kernel.org>

> >>> +static int sst26vf_nor_post_sfdp(struct spi_nor *nor)
> >>> +{
> >>> +     struct nvmem_device *nvmem;
> >>> +
> >>> +     sst26vf_sfdp_nvmem_config.dev = nor->dev;
> >>> +     sst26vf_sfdp_nvmem_config.size = nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords);
> >>> +     sst26vf_sfdp_nvmem_config.priv = nor;
> >>> +     sst26vf_sfdp_nvmem_config.reg_read = sst26vf_sfdp_mac_addr_read;
> >>> +
> >>> +     nvmem = devm_nvmem_register(nor->dev, &sst26vf_sfdp_nvmem_config);
> >>> +     if (IS_ERR(nvmem)) {
> >>> +             dev_err(nor->dev, "failed to register NVMEM device: %ld\n", PTR_ERR(nvmem));
> >>> +             return PTR_ERR(nvmem);
> >> 
> >> I don't think it makes sense to have this one-off in a particular
> >> driver. If at all, this should be handled in the core. Sorry, but
> >> this really looks like an ugly hack.
> >> 
> >
> > Because the EUI identifier within the SFDP is unique to the 
> > SST26VF064BEUI flash, I opted to handle it here rather than in the core.
> >
> > Also here the MAC address data resides within the 0x260-0x26F range, I 
> > will resize the nvmem_config.size to 0x10 instead of registering the 
> > full SFDP region as NVMEM.
>
> Open question to all parties in this thread: how do we give an offset in
> the device tree that is relative to the sfdp region and not the data
> region? I believe we care not to mix these areas while describing.

You don't do it, because there is not even a relative offset that is
fixed. There should be a pointer to the vendor table inside the SFDP
structure. Thus, you need to properly parse it.

Regarding how to reference it within the device tree, I'd assume
something along 'compatible = "jedec,sfdp-vendor-table-NNN";' or
similar. But no static/relative offsets.

-michael


From quic_yuanfang at quicinc.com  Thu Mar  6 00:39:27 2025
From: quic_yuanfang at quicinc.com (Yuanfang Zhang)
Date: Thu, 6 Mar 2025 16:39:27 +0800
Subject: [PATCH v2 3/5] coresight-tnoc: add nodes to configure flush
In-Reply-To: <20250227162349.GB2157064@e132581.arm.com>
References: <20250226-trace-noc-driver-v2-0-8afc6584afc5@quicinc.com>
 <20250226-trace-noc-driver-v2-3-8afc6584afc5@quicinc.com>
 <20250227162349.GB2157064@e132581.arm.com>
Message-ID: <7c702a81-fb6c-4399-8d7d-d8c4ad9a8c65@quicinc.com>



On 2/28/2025 12:23 AM, Leo Yan wrote:
> On Wed, Feb 26, 2025 at 07:05:52PM +0800, Yuanfang Zhang wrote:
>>
>> Two nodes for configure flush are added here:
>> 1. flush_req: write 1 to initiates a flush sequence.
>>
>> 2. flush_state: read this node to get flush status. 0: sequence in
>> progress; 1: sequence has been completed.
>>
>> Signed-off-by: Yuanfang Zhang <quic_yuanfang at quicinc.com>
>> ---
>>  drivers/hwtracing/coresight/coresight-tnoc.c | 73 ++++++++++++++++++++++++++++
>>  drivers/hwtracing/coresight/coresight-tnoc.h |  4 ++
>>  2 files changed, 77 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
>> index fad8e61f05ef25989aba1be342c547f835e8953a..20231f28ddcb6a60d9b3c1ca3e0ca4d731dac39c 100644
>> --- a/drivers/hwtracing/coresight/coresight-tnoc.c
>> +++ b/drivers/hwtracing/coresight/coresight-tnoc.c
>> @@ -16,6 +16,78 @@
>>  #include "coresight-tnoc.h"
>>  #include "coresight-trace-id.h"
>>
>> +static ssize_t flush_req_store(struct device *dev,
>> +                              struct device_attribute *attr,
>> +                              const char *buf,
>> +                              size_t size)
>> +{
>> +       struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +       struct coresight_device *csdev = drvdata->csdev;
>> +       unsigned long val;
>> +       u32 reg;
>> +
>> +       if (kstrtoul(buf, 10, &val))
>> +               return -EINVAL;
>> +
>> +       if (val != 1)
>> +               return -EINVAL;
>> +
>> +       spin_lock(&drvdata->spinlock);
>> +       if (csdev->refcnt == 0) {
>> +               spin_unlock(&drvdata->spinlock);
>> +               return -EPERM;
>> +       }
>> +
>> +       reg = readl_relaxed(drvdata->base + TRACE_NOC_CTRL);
>> +       reg = reg | TRACE_NOC_CTRL_FLUSHREQ;
>> +       writel_relaxed(reg, drvdata->base + TRACE_NOC_CTRL);
> 
> How can userspace determine when to trigger a flush?
It can be triggered under any circumstances.
> 
> Generally, a driver kicks off a flush operation for a hardware before
> reading data from buffer or when disable a link path.  I don't know the
> hardware mechanism of TNOC, but seems to me, it does not make sense to
> let the userspace to trigger a hardware flush, given the userspace has
> no knowledge for device's state.
TNOC supports the aforementioned flush operation, and it also adds this
flush functionality, allowing users to set the flush themselves.
> 
> Furthermore, based on my understanding for patch 02 and 03, the working
> flow is also concerned me.  IIUC, you want to use the driver to create
> a linkage and then use userspace program to poll state and trigger
> flushing.  Could you explain why use this way for managing the device?
> 
TNOC support flush just like other links. This interface simply provides
customers with an additional option to trigger the flush.

> Thanks,
> Leo
> 
>> +
>> +       spin_unlock(&drvdata->spinlock);
>> +
>> +       return size;
>> +}
>> +static DEVICE_ATTR_WO(flush_req);
>> +
>> +/*
>> + * flush-sequence status:
>> + * value 0: sequence in progress;
>> + * value 1: sequence has been completed.
>> + */
>> +static ssize_t flush_status_show(struct device *dev,
>> +                                struct device_attribute *attr,
>> +                                char *buf)
>> +{
>> +       struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +       struct coresight_device *csdev = drvdata->csdev;
>> +       u32 val;
>> +
>> +       spin_lock(&drvdata->spinlock);
>> +       if (csdev->refcnt == 0) {
>> +               spin_unlock(&drvdata->spinlock);
>> +               return -EPERM;
>> +       }
>> +
>> +       val = readl_relaxed(drvdata->base + TRACE_NOC_CTRL);
>> +       spin_unlock(&drvdata->spinlock);
>> +       return sysfs_emit(buf, "%lu\n", BMVAL(val, 2, 2));
>> +}
>> +static DEVICE_ATTR_RO(flush_status);
>> +
>> +static struct attribute *trace_noc_attrs[] = {
>> +       &dev_attr_flush_req.attr,
>> +       &dev_attr_flush_status.attr,
>> +       NULL,
>> +};
>> +
>> +static struct attribute_group trace_noc_attr_grp = {
>> +       .attrs = trace_noc_attrs,
>> +};
>> +
>> +static const struct attribute_group *trace_noc_attr_grps[] = {
>> +       &trace_noc_attr_grp,
>> +       NULL,
>> +};
>> +
>>  static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
>>  {
>>         u32 val;
>> @@ -142,6 +214,7 @@ static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
>>                 return ret;
>>
>>         desc.ops = &trace_noc_cs_ops;
>> +       desc.groups = trace_noc_attr_grps;
>>         desc.type = CORESIGHT_DEV_TYPE_LINK;
>>         desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
>>         desc.pdata = adev->dev.platform_data;
>> diff --git a/drivers/hwtracing/coresight/coresight-tnoc.h b/drivers/hwtracing/coresight/coresight-tnoc.h
>> index b6bd1ef659897d8e0994c5e8514e8cbdd16eebd8..d0fe8f52709ff4147d66dbf90987595012cfaa4e 100644
>> --- a/drivers/hwtracing/coresight/coresight-tnoc.h
>> +++ b/drivers/hwtracing/coresight/coresight-tnoc.h
>> @@ -10,6 +10,10 @@
>>
>>  /* Enable generation of output ATB traffic.*/
>>  #define TRACE_NOC_CTRL_PORTEN  BIT(0)
>> +/* Writing 1 to initiate a flush sequence.*/
>> +#define TRACE_NOC_CTRL_FLUSHREQ        BIT(1)
>> +/* 0: sequence in progress; 1: sequence has been completed.*/
>> +#define TRACE_NOC_CTRL_FLUSHSTATUS     BIT(2)
>>  /* Writing 1 to issue a FREQ or FREQ_TS packet*/
>>  #define TRACE_NOC_CTRL_FREQTSREQ       BIT(5)
>>  /* Sets the type of issued ATB FLAG packets. 0: 'FLAG' packets; 1: 'FLAG_TS' packets.*/
>>
>> --
>> 2.34.1
>>
>> _______________________________________________
>> CoreSight mailing list -- coresight at lists.linaro.org
>> To unsubscribe send an email to coresight-leave at lists.linaro.org



From yong.liang.choong at linux.intel.com  Thu Mar  6 00:39:38 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Thu, 6 Mar 2025 16:39:38 +0800
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>
Message-ID: <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>



On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
> Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:
>> Intel platform will configure the SerDes through PMC API based on the
>> provided interface mode.
>> This patch adds several new functions below:-
>> - intel_tsn_lane_is_available(): This new function reads FIA lane
>>    ownership registers and common lane registers through IPC commands
>>    to know which lane the mGbE port is assigned to.
>> - intel_mac_finish(): To configure the SerDes based on the assigned
>>    lane and latest interface mode, it sends IPC command to the PMC through
>>    PMC driver/API. The PMC acts as a proxy for R/W on behalf of the driver.
>> - intel_set_reg_access(): Set the register access to the available TSN
>>    interface.
> ...
> 
>> config DWMAC_INTEL
>>   	default X86
>>   	depends on X86 && STMMAC_ETH && PCI
>>   	depends on COMMON_CLK
>> +	depends on ACPI
> Stray and unexplained change. Please, fix it. We don't need the dependencies
> which are not realised in the compile time.
> 
> -- With Best Regards, Andy Shevchenko

Hi Andy,

The dependency on ACPI is necessary because the intel_pmc_ipc.h header 
relies on ACPI functionality to interact with the Intel PMC.


From krzk at kernel.org  Thu Mar  6 00:40:49 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 09:40:49 +0100
Subject: [PATCH v2 4/8] dt-bindings: clock: Add GRF clock definition for
 RK3528
In-Reply-To: <20250305194217.47052-5-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
 <20250305194217.47052-5-ziyao@disroot.org>
Message-ID: <20250306-imaginary-fox-of-hurricane-aa1fa9@krzk-bin>

On Wed, Mar 05, 2025 at 07:42:13PM +0000, Yao Zi wrote:
> These clocks are for SD/SDIO tuning purpose and come with registers
> in GRF syscon.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
>  1 file changed, 6 insertions(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From fabrice.gasnier at foss.st.com  Thu Mar  6 00:40:10 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 6 Mar 2025 09:40:10 +0100
Subject: [PATCH v3 3/8] iio: trigger: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250305144539.54a75689@jic23-huawei>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-4-fabrice.gasnier@foss.st.com>
 <20250305144539.54a75689@jic23-huawei>
Message-ID: <32aad66e-a9ae-493a-8bea-a06e096c88f2@foss.st.com>

On 3/5/25 15:45, Jonathan Cameron wrote:
> On Wed, 5 Mar 2025 10:49:30 +0100
> Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:
> 
>> From: Olivier Moysan <olivier.moysan at foss.st.com>
>>
>> Add support for STM32MP25 SoC. Use newly introduced compatible to handle
>> this new HW variant. Add new trigger definitions that can be used by the
>> stm32 analog-to-digital converter. Use compatible data to identify them.
>>
>> Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> Hi. Oops I replied to v1 without looking for other versions.
> From a quick glance feedback still applies here.

Hi Jonathan,

Thanks for reviewing, I've noticed your review comments on V1, I'll take
care of these in next revision (v4).

Best Regards,
Fabrice

> 


From brgl at bgdev.pl  Thu Mar  6 00:45:52 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Thu,  6 Mar 2025 09:45:52 +0100
Subject: [PATCH] irqchip: davinci: remove leftover header
Message-ID: <20250306084552.15894-1-brgl@bgdev.pl>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Commit fa8dede4d0a0 ("irqchip: remove davinci aintc driver") removed the
davinci aintc driver but left behind the associated header. Remove it
now.

Fixes: fa8dede4d0a0 ("irqchip: remove davinci aintc driver")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
---
 include/linux/irqchip/irq-davinci-aintc.h | 27 -----------------------
 1 file changed, 27 deletions(-)
 delete mode 100644 include/linux/irqchip/irq-davinci-aintc.h

diff --git a/include/linux/irqchip/irq-davinci-aintc.h b/include/linux/irqchip/irq-davinci-aintc.h
deleted file mode 100644
index ea4e087fac98..000000000000
--- a/include/linux/irqchip/irq-davinci-aintc.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Texas Instruments
- */
-
-#ifndef _LINUX_IRQ_DAVINCI_AINTC_
-#define _LINUX_IRQ_DAVINCI_AINTC_
-
-#include <linux/ioport.h>
-
-/**
- * struct davinci_aintc_config - configuration data for davinci-aintc driver.
- *
- * @reg: register range to map
- * @num_irqs: number of HW interrupts supported by the controller
- * @prios: an array of size num_irqs containing priority settings for
- *         each interrupt
- */
-struct davinci_aintc_config {
-	struct resource reg;
-	unsigned int num_irqs;
-	u8 *prios;
-};
-
-void davinci_aintc_init(const struct davinci_aintc_config *config);
-
-#endif /* _LINUX_IRQ_DAVINCI_AINTC_ */
-- 
2.45.2



From xianwei.zhao at amlogic.com  Thu Mar  6 00:48:00 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Thu, 6 Mar 2025 16:48:00 +0800
Subject: [PATCH v3 1/4] dt-bindings: interrupt-controller: Add support for
 Amlogic A4 and A5 SoCsy
In-Reply-To: <20250305-corral-unfair-a7f25abbfd64@spud>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-1-1eec70352fea@amlogic.com>
 <20250305-corral-unfair-a7f25abbfd64@spud>
Message-ID: <0dbd6e4f-3d96-40de-953c-48a7eae0e598@amlogic.com>

Hi Conor,
     Thanks for your advice.

On 2025/3/6 00:28, Conor Dooley wrote:
> On Wed, Mar 05, 2025 at 06:02:56PM +0800, Xianwei Zhao via B4 Relay wrote:
>> From: Xianwei Zhao<xianwei.zhao at amlogic.com>
>>
>> Update dt-binding document for GPIO interrupt controller
>> of Amlogic A4 and A5 SoCs
>>
>> Signed-off-by: Xianwei Zhao<xianwei.zhao at amlogic.com>
>> ---
>>   .../amlogic,meson-gpio-intc.yaml                    | 21 +++++++++++++++++++--
>>   1 file changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>> index a93744763787..3c5853c71efa 100644
>> --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>> +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
>> @@ -35,6 +35,9 @@ properties:
>>                 - amlogic,meson-sm1-gpio-intc
>>                 - amlogic,meson-a1-gpio-intc
>>                 - amlogic,meson-s4-gpio-intc
>> +              - amlogic,a4-gpio-intc
>> +              - amlogic,a4-gpio-ao-intc
>> +              - amlogic,a5-gpio-intc
>>                 - amlogic,c3-gpio-intc
>>                 - amlogic,t7-gpio-intc
>>             - const: amlogic,meson-gpio-intc
>> @@ -49,8 +52,6 @@ properties:
>>   
>>     amlogic,channel-interrupts:
>>       description: Array with the upstream hwirq numbers
>> -    minItems: 8
>> -    maxItems: 12
> Please leave the widest constraints here, and let the more restricted
> ones in your if/else below.
> 

Will do.

>>       $ref: /schemas/types.yaml#/definitions/uint32-array
>>   
>>   required:
>> @@ -60,6 +61,22 @@ required:
>>     - "#interrupt-cells"
>>     - amlogic,channel-interrupts
>>   
>> +if:
>> +  properties:
>> +    compatible:
>> +      contains:
>> +        const: amlogic,a4-gpio-ao-intc
>> +then:
>> +  properties:
>> +    amlogic,channel-interrupts:
>> +      minItems: 2
>> +      maxItems: 12
>> +else:
>> +  properties:
>> +    amlogic,channel-interrupts:
>> +      minItems: 8
>> +      maxItems: 12
>> +
>>   additionalProperties: false
>>   
>>   examples:
>>
>> -- 
>> 2.37.1
>>
>>


From piotr.oniszczuk at gmail.com  Thu Mar  6 00:42:00 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Thu, 6 Mar 2025 09:42:00 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
Message-ID: <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 01:59:
> 
> 
> 
> 
> Both of the two config options should be enabled.
> andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
> 4044:CONFIG_ROCKCHIP_DW_DP=y

here i?m a bit lost?.
greping on full kernel sources (with applied https://patchwork.kernel.org/project/linux-rockchip/list/?series=936784) gives me no single appearance of ROCKCHIP_DW_DP?
Do i miss something?




From axe.yang at mediatek.com  Thu Mar  6 00:48:05 2025
From: axe.yang at mediatek.com (Axe Yang)
Date: Thu, 6 Mar 2025 16:48:05 +0800
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <20250306085028.5024-1-axe.yang@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
Message-ID: <20250306085028.5024-2-axe.yang@mediatek.com>

Add 'mediatek,disable-single-burst' setting. This property can be
used to switch bus burst type, from single burst to INCR, which is
determined by the bus type within the IP. Some versions of the IP
are using AXI bus, thus this switch is necessary as 'single' is not
the burst type supported by the bus.

Signed-off-by: Axe Yang <axe.yang at mediatek.com>
---
 Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
index 0debccbd6519..6076aff0a689 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -100,6 +100,14 @@ properties:
     minimum: 0
     maximum: 0xffffffff
 
+  mediatek,disable-single-burst:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Burst type setting. For some versions of the IP that do not use
+      AHB bus, the burst type need to be switched to INCR.
+      If present, use INCR burst type.
+      If not present, use single burst type.
+
   mediatek,hs200-cmd-int-delay:
     $ref: /schemas/types.yaml#/definitions/uint32
     description:
-- 
2.46.0



From axe.yang at mediatek.com  Thu Mar  6 00:48:04 2025
From: axe.yang at mediatek.com (Axe Yang)
Date: Thu, 6 Mar 2025 16:48:04 +0800
Subject: [PATCH 0/2] mmc: mtk-sd: add support for burst type switch
Message-ID: <20250306085028.5024-1-axe.yang@mediatek.com>

Add a device tree property for MSDC node to switch burst type.
The default burst type is 'single', but for some versions of IP,
the AMBA type is AXI, which do not support 'single' burst type.

This series of changes provides a way to switch the burst type,
and is necessary as the AXI bus is being used more frequently
in the new versions of MSDC IP.

Axe Yang (2):
  dt-bindings: mmc: mtk-sd: add single burst switch
  mmc: mtk-sd: add support to disable single burst

 Documentation/devicetree/bindings/mmc/mtk-sd.yaml |  8 ++++++++
 drivers/mmc/host/mtk-sd.c                         | 10 ++++++++++
 2 files changed, 18 insertions(+)

-- 
2.46.0



From lukasz.luba at arm.com  Thu Mar  6 01:15:30 2025
From: lukasz.luba at arm.com (Lukasz Luba)
Date: Thu, 6 Mar 2025 09:15:30 +0000
Subject: [PATCH v3 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <CANAwSgQErDnKfaBOkpEwpJsoyUMhNTC2TJNW-eQYHgHu46poCA@mail.gmail.com>
References: <20250216195850.5352-1-linux.amoon@gmail.com>
 <20250216195850.5352-5-linux.amoon@gmail.com>
 <f44efd1a-1f6e-456d-9395-de2a55ef2279@arm.com>
 <CANAwSgTpV_kGFEU-ND0N+OEtT6+j4ceq37xAoLyC7iHPWAuLjg@mail.gmail.com>
 <CANAwSgSWf_YxSi-pzWPaRoiJx7RLrWUz+HTWx5hf+E2x1ZGmoQ@mail.gmail.com>
 <7a1cac10-b065-4b4c-b048-10d6b4132f3d@arm.com>
 <CANAwSgQErDnKfaBOkpEwpJsoyUMhNTC2TJNW-eQYHgHu46poCA@mail.gmail.com>
Message-ID: <dfc0b0e1-51fa-47a2-8a8b-87bed173254c@arm.com>



On 3/5/25 15:59, Anand Moon wrote:
> Hi Lukasz,
> 
> On Wed, 5 Mar 2025 at 14:12, Lukasz Luba <lukasz.luba at arm.com> wrote:
>>
>>
>>
>> On 3/4/25 12:20, Anand Moon wrote:
>>> Hi Lukasz,
>>>
>>> On Sat, 1 Mar 2025 at 00:06, Anand Moon <linux.amoon at gmail.com> wrote:
>>>>
>>>> Hi Lukasz,
>>>>
>>>> On Fri, 28 Feb 2025 at 22:58, Lukasz Luba <lukasz.luba at arm.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 2/16/25 19:58, Anand Moon wrote:
>>>>>> Using guard notation makes the code more compact and error handling
>>>>>> more robust by ensuring that mutexes are released in all code paths
>>>>>> when control leaves critical section.
>>>>>>
>>>>>> Signed-off-by: Anand Moon <linux.amoon at gmail.com>
>>>>>> ---
>>>>>> v3: new patch
>>>>>> ---
>>>>>>     drivers/thermal/samsung/exynos_tmu.c | 21 +++++++--------------
>>>>>>     1 file changed, 7 insertions(+), 14 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
>>>>>> index fe090c1a93ab..a34ba3858d64 100644
>>>>>> --- a/drivers/thermal/samsung/exynos_tmu.c
>>>>>> +++ b/drivers/thermal/samsung/exynos_tmu.c
>>>>>> @@ -256,7 +256,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>>>         unsigned int status;
>>>>>>         int ret = 0;
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>         clk_enable(data->clk_sec);
>>>>>>
>>>>>> @@ -270,7 +270,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>>>>
>>>>>>         clk_disable(data->clk_sec);
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>
>>>>>>         return ret;
>>>>>>     }
>>>>>> @@ -292,13 +291,12 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
>>>>>>                 return ret;
>>>>>>         }
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>
>>>>>>         data->tmu_set_crit_temp(data, temp / MCELSIUS);
>>>>>>
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>
>>>>>>         return 0;
>>>>>>     }
>>>>>> @@ -325,12 +323,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
>>>>>>     {
>>>>>>         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>         data->tmu_control(pdev, on);
>>>>>>         data->enabled = on;
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>     }
>>>>>>
>>>>>>     static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
>>>>>> @@ -645,7 +642,7 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
>>>>>>                  */
>>>>>>                 return -EAGAIN;
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>
>>>>>>         value = data->tmu_read(data);
>>>>>> @@ -655,7 +652,6 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
>>>>>>                 *temp = code_to_temp(data, value) * MCELSIUS;
>>>>>>
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>
>>>>>>         return ret;
>>>>>>     }
>>>>>> @@ -720,11 +716,10 @@ static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
>>>>>>         if (temp && temp < MCELSIUS)
>>>>>>                 goto out;
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>         data->tmu_set_emulation(data, temp);
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>         return 0;
>>>>>>     out:
>>>>>>         return ret;
>>>>>> @@ -760,14 +755,13 @@ static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id)
>>>>>>
>>>>>>         thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>
>>>>>>         /* TODO: take action based on particular interrupt */
>>>>>>         data->tmu_clear_irqs(data);
>>>>>>
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>
>>>>>>         return IRQ_HANDLED;
>>>>>>     }
>>>>>> @@ -987,7 +981,7 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
>>>>>>     {
>>>>>>         struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
>>>>>>
>>>>>> -     mutex_lock(&data->lock);
>>>>>> +     guard(mutex)(&data->lock);
>>>>>>         clk_enable(data->clk);
>>>>>>
>>>>>>         if (low > INT_MIN)
>>>>>> @@ -1000,7 +994,6 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
>>>>>>                 data->tmu_disable_high(data);
>>>>>>
>>>>>>         clk_disable(data->clk);
>>>>>> -     mutex_unlock(&data->lock);
>>>>>>
>>>>>>         return 0;
>>>>>>     }
>>>>
>>>> Thanks for your review comments.
>>>>>
>>>>> IMO you should be able to even use something like we have
>>>>> core framework:
>>>>>
>>>>> guard(thermal_zone)(tz);
>>>>>
>>>>> Your mutex name is simply 'lock' in the struct exynos_tmu_data
>>>>> so you should be able to leverage this by:
>>>>>
>>>>> guard(exynos_tmu_data)(data);
>>>>>
>>>
>>> If I introduce the guard it creates a compilation error
>>>
>>> amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ vi
>>> drivers/thermal/samsung/exynos_tmu.c +306
>>> amoon at anand-m920q:~/mainline/linux-exynos-6.y-devel$ make -j$(nproc)
>>> ARCH=arm CROSS_COMPILE=arm-none-eabi- LOCALVERSION=-u3ml dtbs zImage
>>> modules
>>>     CALL    scripts/checksyscalls.sh
>>>     CHK     kernel/kheaders_data.tar.xz
>>>     CC      drivers/thermal/samsung/exynos_tmu.o
>>>     CC [M]  drivers/md/raid10.o
>>> In file included from ./include/linux/irqflags.h:17,
>>>                    from ./arch/arm/include/asm/bitops.h:28,
>>>                    from ./include/linux/bitops.h:68,
>>>                    from ./include/linux/kernel.h:23,
>>>                    from ./include/linux/clk.h:13,
>>>                    from drivers/thermal/samsung/exynos_tmu.c:14:
>>> drivers/thermal/samsung/exynos_tmu.c: In function 'exynos_tmu_update_bit':
>>> ./include/linux/cleanup.h:258:9: error: unknown type name
>>> 'class_exynos_tmu_data_t'
>>>     258 |         class_##_name##_t var
>>> __cleanup(class_##_name##_destructor) =   \
>>>         |         ^~~~~~
>>> ./include/linux/cleanup.h:309:9: note: in expansion of macro 'CLASS'
>>>     309 |         CLASS(_name, __UNIQUE_ID(guard))
>>>         |         ^~~~~
>>> drivers/thermal/samsung/exynos_tmu.c:338:9: note: in expansion of macro 'guard'
>>>     338 |         guard(exynos_tmu_data)(data);
>>>         |         ^~~~~
>>> drivers/thermal/samsung/exynos_tmu.c:338:9: error: cleanup argument
>>> not a function
>>
>> [snip]
>>
>> Right, you're missing the definition at the begging, like:
>>
>> DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *,
>> mutex_lock(&_T->lock),
>>                mutex_unlock(&_T->lock))
>>
>> below the struct exynos_tmu_data definition.
>>
>> Also, make sure you include the cleanup.h (it might not complain,
>> but it would be explicit and more clear)
> 
> Thanks for this tip.
> However, incorporating guard(exynos_tmu_data)(data); results
> in a recursive deadlock with the mutex during initialization, as this
> data structure is common to all the code configurations of Exynos TMU
> 

Fair enough, it would be just a cosmetic change, so do fight with it
too much.

Please continue in v4 with your former approach with the 'guard'.


From angelogioacchino.delregno at collabora.com  Thu Mar  6 01:19:51 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 6 Mar 2025 10:19:51 +0100
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <20250306085028.5024-2-axe.yang@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
 <20250306085028.5024-2-axe.yang@mediatek.com>
Message-ID: <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>

Il 06/03/25 09:48, Axe Yang ha scritto:
> Add 'mediatek,disable-single-burst' setting. This property can be
> used to switch bus burst type, from single burst to INCR, which is
> determined by the bus type within the IP. Some versions of the IP
> are using AXI bus, thus this switch is necessary as 'single' is not
> the burst type supported by the bus.
> 
> Signed-off-by: Axe Yang <axe.yang at mediatek.com>

I am mostly sure that this is not something to put in devicetree, but as
platform data for specific SoC(s), as much as I'm mostly sure that all of
the instances of the MSDC IP in one SoC will be *all* using either single
or INCR.

So, I think I know the answer but I'll still ask just to be extremely sure:

is there any MediaTek SoC that has different IP versions for different MSDC
instances, and that hence require single burst on one instance and INCR on
another instance?

And if there is - is there a pattern? Is it always SDIO requiring INCR or
always eMMC/SD requiring it?

Regards,
Angelo

> ---
>   Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8 ++++++++
>   1 file changed, 8 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> index 0debccbd6519..6076aff0a689 100644
> --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> @@ -100,6 +100,14 @@ properties:
>       minimum: 0
>       maximum: 0xffffffff
>   
> +  mediatek,disable-single-burst:
> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      Burst type setting. For some versions of the IP that do not use
> +      AHB bus, the burst type need to be switched to INCR.
> +      If present, use INCR burst type.
> +      If not present, use single burst type.
> +
>     mediatek,hs200-cmd-int-delay:
>       $ref: /schemas/types.yaml#/definitions/uint32
>       description:





From james.clark at linaro.org  Thu Mar  6 01:32:43 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 6 Mar 2025 09:32:43 +0000
Subject: [PATCH 3/3] perf/arm_cspmu: Add PMEVFILT2R support
In-Reply-To: <b11be3f23a72bc27088b115099c8fe865b70babc.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
 <b11be3f23a72bc27088b115099c8fe865b70babc.1741190362.git.robin.murphy@arm.com>
Message-ID: <204e94a7-24e1-4dc2-b6ee-8527510a275b@linaro.org>



On 05/03/2025 4:10 pm, Robin Murphy wrote:
> Architecturally we have two filters for each regular event counter,
> so add generic support for the second one too.
> 
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>   drivers/perf/arm_cspmu/arm_cspmu.c | 7 +++++--
>   drivers/perf/arm_cspmu/arm_cspmu.h | 3 +++
>   2 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 053bb7920df6..efa9b229e701 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -183,6 +183,7 @@ arm_cspmu_event_attr_is_visible(struct kobject *kobj,
>   static struct attribute *arm_cspmu_format_attrs[] = {
>   	ARM_CSPMU_FORMAT_EVENT_ATTR,
>   	ARM_CSPMU_FORMAT_FILTER_ATTR,
> +	ARM_CSPMU_FORMAT_FILTER2_ATTR,
>   	NULL,
>   };
>   
> @@ -767,9 +768,11 @@ static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
>   				    const struct perf_event *event)
>   {
>   	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
> -	u32 offset = PMEVFILTR + (4 * hwc->idx);
> +	u32 filter2 = event->attr.config2 & ARM_CSPMU_FILTER_MASK;
> +	u32 offset = 4 * event->hw.idx;
>   
> -	writel(filter, cspmu->base0 + offset);
> +	writel(filter, cspmu->base0 + PMEVFILTR + offset);
> +	writel(filter2, cspmu->base0 + PMEVFILT2R + offset);
>   }
>   
>   static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index d59040d6a7e3..19684b76bd96 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -47,6 +47,8 @@
>   /* Default filter format */
>   #define ARM_CSPMU_FORMAT_FILTER_ATTR	\
>   	ARM_CSPMU_FORMAT_ATTR(filter, "config1:0-31")
> +#define ARM_CSPMU_FORMAT_FILTER2_ATTR	\
> +	ARM_CSPMU_FORMAT_ATTR(filter2, "config2:0-31")
>   
>   /*
>    * This is the default event number for cycle count, if supported, since the
> @@ -72,6 +74,7 @@
>   #define PMEVCNTR_HI			0x4
>   #define PMEVTYPER			0x400
>   #define PMCCFILTR			0x47C
> +#define PMEVFILT2R			0x800
>   #define PMEVFILTR			0xA00
>   #define PMCNTENSET			0xC00
>   #define PMCNTENCLR			0xC20

Reviewed-by: James Clark <james.clark at linaro.org>

Minor comment that the doc linked at the beginning of the file "ARM IHI 
0091 A.a-00bet0" doesn't have PMEVFILT2R, you need the latest version 
for that.



From krzk at kernel.org  Thu Mar  6 01:36:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 10:36:34 +0100
Subject: [PATCH 1/3] dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible
 string for RK3528
In-Reply-To: <20250305214108.1327208-2-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
 <20250305214108.1327208-2-jonas@kwiboo.se>
Message-ID: <20250306-frisky-spiffy-bullmastiff-ad9e49@krzk-bin>

On Wed, Mar 05, 2025 at 09:41:02PM +0000, Jonas Karlman wrote:
> The SDHCI controller in Rockchip RK3528 is similar to the one included
> in RK3588.
> 
> Add compatible string for the SDHCI controller in RK3528.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---

No power domains here? Post complete support, so this won't have to be
changed in near future.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From sudeep.holla at arm.com  Thu Mar  6 01:40:43 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 6 Mar 2025 09:40:43 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <20250305193425.GA32246@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
 <20250305004522.GC31667@willie-the-truck>
 <20250305094104.vctshdtgdukno2aj@bogus>
 <20250305193425.GA32246@willie-the-truck>
Message-ID: <Z8ltm55D1jrv8QtX@bogus>

On Wed, Mar 05, 2025 at 07:34:26PM +0000, Will Deacon wrote:
> On Wed, Mar 05, 2025 at 09:41:04AM +0000, Sudeep Holla wrote:
> > On Wed, Mar 05, 2025 at 12:45:23AM +0000, Will Deacon wrote:
> > > Hmm, the FFA spec is characteristically unclear as to whether or not we
> > > need to release the rx buffer in the case that the flags indicate use of
> > > the rx buffer but the returned partition count is 0.
> > > 
> > > Sudeep -- do you know what we should be doing in that case?
> > > 
> > 
> > We need to call RX_RELEASE here. I went back to the spec to confirm the
> > same again.
> > 
> > v1.2 EAC0 spec Section 7.2.2.4.2 Transfer of buffer ownership
> > (Or just look for the section title in any version of the spec)
> > "
> > 2. Ownership transfer for the RX buffer takes place as follows.
> >     2. For a framework message,
> >        1. Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership
> >        of the caller?s RX buffer from the Producer to the Consumer.
> > 3. For both types of messages, an invocation of the following FF-A ABIs
> >     transfers the ownership from the Consumer to the Producer.
> >        1. FFA_MSG_WAIT ...
> >        2. FFA_RX_RELEASE.
> > "
> > 
> > Hope that helps, can dig deeper if there are any ambiguities around this.
> 
> Thanks Sudeep, but that also makes it sound like we need the RX_RELEASE
> even if we're not using the RX buffer per the input flags. :/
> 

Good spot, I had forgotten about the input flags that can avoid using the
buffer. I will see if we can improve the spec in that regards.

-- 
Regards,
Sudeep


From gcherian at marvell.com  Thu Mar  6 01:40:50 2025
From: gcherian at marvell.com (George Cherian)
Date: Thu, 6 Mar 2025 09:40:50 +0000
Subject: [PATCH v4 1/2] watchdog: Add a new flag WDIOF_STOP_MAYSLEEP
In-Reply-To: <CAODwPW_3BCfTcTu=K+6Q3PMe8DtWTiKFHC6+HO2q+cTqs=EPAA@mail.gmail.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <CAODwPW_3BCfTcTu=K+6Q3PMe8DtWTiKFHC6+HO2q+cTqs=EPAA@mail.gmail.com>
Message-ID: <PH8PR18MB538137DD102CAA420746CDB8C5CA2@PH8PR18MB5381.namprd18.prod.outlook.com>

Hi Julius,
>>  static const struct watchdog_ops adv_ec_wdt_ops = {
>> diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c
>> index 8f3d0c3a005f..794cf0086912 100644
>> --- a/drivers/watchdog/arm_smc_wdt.c
>> +++ b/drivers/watchdog/arm_smc_wdt.c
>> @@ -90,7 +90,8 @@ static const struct watchdog_info smcwd_info = {
>>         .identity       = DRV_NAME,
>>         .options        = WDIOF_SETTIMEOUT |
>>                           WDIOF_KEEPALIVEPING |
>> -                         WDIOF_MAGICCLOSE,
>> +                         WDIOF_MAGICCLOSE |
>> +                         WDIOF_STOP_MAYSLEEP,
>>  };
>
>I don't think this driver can sleep, unless I'm missing something?

The only reason I added to avoid any inadvertent hang in TF-A.
Anyways the approach is going to change so this patch is not 
needed anymore.
>`arm_smccc_smc()` does a synchronous call into firmware that always
>returns back to the caller.

Thanks for the insight.
-George

From yeoreum.yun at arm.com  Thu Mar  6 01:47:55 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:55 +0000
Subject: [PATCH v5 4/9] coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-5-yeoreum.yun@arm.com>

In coresight-cti drivers, cti_drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since cti_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type cti_drvdata->spinlock in coresight-cti drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-cti-core.c  | 44 +++++------
 .../hwtracing/coresight/coresight-cti-sysfs.c | 76 +++++++++----------
 drivers/hwtracing/coresight/coresight-cti.h   |  2 +-
 3 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index d2b5a5718c29..80f6265e3740 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -93,7 +93,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 	unsigned long flags;
 	int rc = 0;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* no need to do anything if enabled or unpowered*/
 	if (config->hw_enabled || !config->hw_powered)
@@ -108,7 +108,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 
 	config->hw_enabled = true;
 	drvdata->config.enable_req_count++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 
 cti_state_unchanged:
@@ -116,7 +116,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 
 	/* cannot enable due to error */
 cti_err_not_enabled:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 }
 
@@ -125,7 +125,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
 {
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->hw_powered = true;
 
 	/* no need to do anything if no enable request */
@@ -138,12 +138,12 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
 
 	cti_write_all_hw_regs(drvdata);
 	config->hw_enabled = true;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return;
 
 	/* did not re-enable due to no claim / no request */
 cti_hp_not_enabled:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 }
 
 /* disable hardware */
@@ -153,7 +153,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
 	struct coresight_device *csdev = drvdata->csdev;
 	int ret = 0;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* don't allow negative refcounts, return an error */
 	if (!drvdata->config.enable_req_count) {
@@ -177,12 +177,12 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
 
 	coresight_disclaim_device_unlocked(csdev);
 	CS_LOCK(drvdata->base);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return ret;
 
 	/* not disabled this call */
 cti_not_disabled:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return ret;
 }
 
@@ -198,11 +198,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* write if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIINTACK, ackval);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 }
 
 /*
@@ -369,7 +369,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
 	reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
 		      CTIOUTEN(trigger_idx));
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* read - modify write - the trigger / channel enable value */
 	reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
@@ -388,7 +388,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, reg_value);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return 0;
 }
 
@@ -406,7 +406,7 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
 
 	chan_bitmask = BIT(channel_idx);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	reg_value = config->ctigate;
 	switch (op) {
 	case CTI_GATE_CHAN_ENABLE:
@@ -426,7 +426,7 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
 		if (cti_active(config))
 			cti_write_single_reg(drvdata, CTIGATE, reg_value);
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return err;
 }
 
@@ -445,7 +445,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 
 	chan_bitmask = BIT(channel_idx);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	reg_value = config->ctiappset;
 	switch (op) {
 	case CTI_CHAN_SET:
@@ -473,7 +473,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 
 	if ((err == 0) && cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, reg_value);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return err;
 }
@@ -676,7 +676,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
 	if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
 		return NOTIFY_BAD;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	switch (cmd) {
 	case CPU_PM_ENTER:
@@ -716,7 +716,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
 	}
 
 cti_notify_exit:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return notify_res;
 }
 
@@ -743,11 +743,11 @@ static int cti_dying_cpu(unsigned int cpu)
 	if (!drvdata)
 		return 0;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.hw_powered = false;
 	if (drvdata->config.hw_enabled)
 		coresight_disclaim_device(drvdata->csdev);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return 0;
 }
 
@@ -888,7 +888,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->ctidev.ctm_id = 0;
 	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	/* initialise CTI driver config values */
 	cti_set_default_config(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index d25dd2737b49..572b80ee96fb 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -84,11 +84,11 @@ static ssize_t enable_show(struct device *dev,
 	bool enabled, powered;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	enable_req = drvdata->config.enable_req_count;
 	powered = drvdata->config.hw_powered;
 	enabled = drvdata->config.hw_enabled;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	if (powered)
 		return sprintf(buf, "%d\n", enabled);
@@ -134,9 +134,9 @@ static ssize_t powered_show(struct device *dev,
 	bool powered;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	powered = drvdata->config.hw_powered;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return sprintf(buf, "%d\n", powered);
 }
@@ -181,10 +181,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
 	u32 val = 0;
 
 	pm_runtime_get_sync(dev->parent);
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (drvdata->config.hw_powered)
 		val = readl_relaxed(drvdata->base + cti_attr->off);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	pm_runtime_put_sync(dev->parent);
 	return sysfs_emit(buf, "0x%x\n", val);
 }
@@ -202,10 +202,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
 		return -EINVAL;
 
 	pm_runtime_get_sync(dev->parent);
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (drvdata->config.hw_powered)
 		cti_write_single_reg(drvdata, cti_attr->off, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	pm_runtime_put_sync(dev->parent);
 	return size;
 }
@@ -264,7 +264,7 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if ((reg_offset >= 0) && cti_active(config)) {
 		CS_UNLOCK(drvdata->base);
 		val = readl_relaxed(drvdata->base + reg_offset);
@@ -274,7 +274,7 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
 	} else if (pcached_val) {
 		val = *pcached_val;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#x\n", val);
 }
 
@@ -293,7 +293,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* local store */
 	if (pcached_val)
 		*pcached_val = (u32)val;
@@ -301,7 +301,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
 	/* write through if offset and enabled */
 	if ((reg_offset >= 0) && cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 
@@ -349,9 +349,9 @@ static ssize_t inout_sel_store(struct device *dev,
 	if (val > (CTIINOUTEN_MAX - 1))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.ctiinout_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(inout_sel);
@@ -364,10 +364,10 @@ static ssize_t inen_show(struct device *dev,
 	int index;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = drvdata->config.ctiinout_sel;
 	val = drvdata->config.ctiinen[index];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#lx\n", val);
 }
 
@@ -383,14 +383,14 @@ static ssize_t inen_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = config->ctiinout_sel;
 	config->ctiinen[index] = val;
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIINEN(index), val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(inen);
@@ -403,10 +403,10 @@ static ssize_t outen_show(struct device *dev,
 	int index;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = drvdata->config.ctiinout_sel;
 	val = drvdata->config.ctiouten[index];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#lx\n", val);
 }
 
@@ -422,14 +422,14 @@ static ssize_t outen_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = config->ctiinout_sel;
 	config->ctiouten[index] = val;
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIOUTEN(index), val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(outen);
@@ -463,7 +463,7 @@ static ssize_t appclear_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* a 1'b1 in appclr clears down the same bit in appset*/
 	config->ctiappset &= ~val;
@@ -471,7 +471,7 @@ static ssize_t appclear_store(struct device *dev,
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(appclear);
@@ -487,12 +487,12 @@ static ssize_t apppulse_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIAPPPULSE, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(apppulse);
@@ -681,9 +681,9 @@ static ssize_t trig_filter_enable_show(struct device *dev,
 	u32 val;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = drvdata->config.trig_filter_enable;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%d\n", val);
 }
 
@@ -697,9 +697,9 @@ static ssize_t trig_filter_enable_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.trig_filter_enable = !!val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(trig_filter_enable);
@@ -728,7 +728,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* clear the CTI trigger / channel programming registers */
 	for (i = 0; i < config->nr_trig_max; i++) {
@@ -747,7 +747,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
 	if (cti_active(config))
 		cti_write_all_hw_regs(drvdata);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(chan_xtrigs_reset);
@@ -768,9 +768,9 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
 	if (val > (drvdata->config.nr_ctm_channels - 1))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.xtrig_rchan_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 
@@ -781,9 +781,9 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
 	unsigned long val;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = drvdata->config.xtrig_rchan_sel;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return sprintf(buf, "%ld\n", val);
 }
@@ -838,12 +838,12 @@ static ssize_t print_chan_list(struct device *dev,
 	unsigned long inuse_bits = 0, chan_mask;
 
 	/* scan regs to get bitmap of channels in use. */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	for (i = 0; i < config->nr_trig_max; i++) {
 		inuse_bits |= config->ctiinen[i];
 		inuse_bits |= config->ctiouten[i];
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	/* inverse bits if printing free channels */
 	if (!inuse)
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index cb9ee616d01f..16e310e7e9d4 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -175,7 +175,7 @@ struct cti_drvdata {
 	void __iomem *base;
 	struct coresight_device	*csdev;
 	struct cti_device ctidev;
-	spinlock_t spinlock;
+	raw_spinlock_t spinlock;
 	struct cti_config config;
 	struct list_head node;
 	void (*csdev_release)(struct device *dev);
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:56 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:56 +0000
Subject: [PATCH v5 5/9] coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-6-yeoreum.yun@arm.com>

In coresight-etb10 drivers, etb_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since etb_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 26 +++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index aea9ac9c4bd0..7948597d483d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -84,7 +84,7 @@ struct etb_drvdata {
 	struct clk		*atclk;
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	local_t			reading;
 	pid_t			pid;
 	u8			*buf;
@@ -145,7 +145,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
 	unsigned long flags;
 	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't messup with perf sessions. */
 	if (coresight_get_mode(csdev) == CS_MODE_PERF) {
@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
 
 	csdev->refcnt++;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
 }
 
@@ -176,7 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* No need to continue if the component is already in used by sysFS. */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
@@ -219,7 +219,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
 }
 
@@ -352,11 +352,11 @@ static int etb_disable(struct coresight_device *csdev)
 	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	unsigned long flags;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -366,7 +366,7 @@ static int etb_disable(struct coresight_device *csdev)
 	/* Dissociate from monitored process. */
 	drvdata->pid = -1;
 	coresight_set_mode(csdev, CS_MODE_DISABLED);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "ETB disabled\n");
 	return 0;
@@ -443,7 +443,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
 
 	capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1)
@@ -566,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
 	__etb_enable_hw(drvdata);
 	CS_LOCK(drvdata->base);
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return to_read;
 }
@@ -587,13 +587,13 @@ static void etb_dump(struct etb_drvdata *drvdata)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
 		__etb_disable_hw(drvdata);
 		etb_dump_hw(drvdata);
 		__etb_enable_hw(drvdata);
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&drvdata->csdev->dev, "ETB dumped\n");
 }
@@ -746,7 +746,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->base = base;
 	desc.access = CSDEV_ACCESS_IOMEM(base);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
 
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:57 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:57 +0000
Subject: [PATCH v5 6/9] coresight-funnel: change funnel_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-7-yeoreum.yun@arm.com>

In coresight-funnel drivers, cti_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since funnel_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type funnel_drvdata->spinlock in
coresight-funnel drivers, which can be called by
perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
---
 drivers/hwtracing/coresight/coresight-funnel.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 8faf51469bb8..0541712b2bcb 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -47,7 +47,7 @@ struct funnel_drvdata {
 	struct clk		*pclk;
 	struct coresight_device	*csdev;
 	unsigned long		priority;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 };
 
 static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
@@ -85,7 +85,7 @@ static int funnel_enable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (in->dest_refcnt == 0) {
 		if (drvdata->base)
 			rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
@@ -94,7 +94,7 @@ static int funnel_enable(struct coresight_device *csdev,
 	}
 	if (!rc)
 		in->dest_refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n",
@@ -129,13 +129,13 @@ static void funnel_disable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (--in->dest_refcnt == 0) {
 		if (drvdata->base)
 			dynamic_funnel_disable_hw(drvdata, in->dest_port);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n",
@@ -266,7 +266,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
 	}
 	dev->platform_data = pdata;
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	desc.type = CORESIGHT_DEV_TYPE_LINK;
 	desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
 	desc.ops = &funnel_cs_ops;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From jonas at kwiboo.se  Thu Mar  6 01:16:00 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 10:16:00 +0100
Subject: [PATCH 0/3] rockchip: Add support for onboard eMMC on Radxa E20C
In-Reply-To: <20250306090001.113127-1-amadeus@jmu.edu.cn>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
 <20250306090001.113127-1-amadeus@jmu.edu.cn>
Message-ID: <ccd8be6a-c8d4-407b-906a-e4788a365775@kwiboo.se>

Hi Chukun,

On 2025-03-06 10:00, Chukun Pan wrote:
> Hi,
> 
>> Driver changes to use different delay and tap num is needed to be able
>> to support HS400 modes, something for a future series. With this HS200
>> mode should work:
> 
> I have tried HS200 mode on other rk3528 boards and it works fine,
> so can we enable HS200 mode for Radxa E20C first?

The host controller already report the HS200 mode, and as shown in cover
letter HS200 mode is being enabled/used with this series.

However, the driver must use different tap/delay num for HS400(ES) modes.
At top of [1] there is a commit that changes to use same tap/delay num
as vendor kernel and what I have tested worked in U-Boot. That commit
needs to be re-worked before it is ready. Also see [2] for pending work
before I plan to complete before moving on to the dwcmshc driver.

[1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250227-rk3528-rk3506/
[2] https://github.com/Kwiboo/linux-rockchip/commits/next-20250305-rk3528/

Regards,
Jonas

> 
> Thanks,
> Chukun
> 



From yeoreum.yun at arm.com  Thu Mar  6 01:47:58 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:58 +0000
Subject: [PATCH v5 7/9] coresight-replicator: change replicator_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-8-yeoreum.yun@arm.com>

In coresight-replicator drivers, replicator_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since replicator_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type replicator_drvdata->spinlock in
coresight-replicator drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/coresight-replicator.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index a1181c9048c0..ee7ee79f6cf7 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -41,7 +41,7 @@ struct replicator_drvdata {
 	struct clk		*atclk;
 	struct clk		*pclk;
 	struct coresight_device	*csdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	bool			check_idfilter_val;
 };
 
@@ -125,7 +125,7 @@ static int replicator_enable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (out->src_refcnt == 0) {
 		if (drvdata->base)
 			rc = dynamic_replicator_enable(drvdata, in->dest_port,
@@ -135,7 +135,7 @@ static int replicator_enable(struct coresight_device *csdev,
 	}
 	if (!rc)
 		out->src_refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "REPLICATOR enabled\n");
@@ -179,14 +179,14 @@ static void replicator_disable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (--out->src_refcnt == 0) {
 		if (drvdata->base)
 			dynamic_replicator_disable(drvdata, in->dest_port,
 						   out->src_port);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
@@ -277,7 +277,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
 	}
 	dev->platform_data = pdata;
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	desc.type = CORESIGHT_DEV_TYPE_LINK;
 	desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
 	desc.ops = &replicator_cs_ops;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:59 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:59 +0000
Subject: [PATCH v5 8/9] coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-9-yeoreum.yun@arm.com>

In coresight-tmc drivers, tmc_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since tmc_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type tmc_drvdata->spinlock in coresight-tmc drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-tmc-core.c  |  6 +--
 .../hwtracing/coresight/coresight-tmc-etf.c   | 48 +++++++++----------
 .../hwtracing/coresight/coresight-tmc-etr.c   | 40 ++++++++--------
 drivers/hwtracing/coresight/coresight-tmc.h   |  2 +-
 4 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index d5122e12daa7..829d104fdaca 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -801,7 +801,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
 	drvdata->base = base;
 	desc.access = CSDEV_ACCESS_IOMEM(base);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
 	drvdata->config_type = BMVAL(devid, 6, 7);
@@ -913,7 +913,7 @@ static void tmc_shutdown(struct amba_device *adev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_DISABLED)
 		goto out;
@@ -927,7 +927,7 @@ static void tmc_shutdown(struct amba_device *adev)
 	 * the system is going down after this.
 	 */
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 }
 
 static void __tmc_remove(struct device *dev)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index bdc3a7e9ba06..d858740001c2 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -185,9 +185,9 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 	 * If we don't have a buffer release the lock and allocate memory.
 	 * Otherwise keep the lock and move along.
 	 */
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (!drvdata->buf) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 		/* Allocating the memory here while outside of the spinlock */
 		buf = kzalloc(drvdata->size, GFP_KERNEL);
@@ -195,7 +195,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 			return -ENOMEM;
 
 		/* Let's try again */
-		spin_lock_irqsave(&drvdata->spinlock, flags);
+		raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	}
 
 	if (drvdata->reading) {
@@ -237,7 +237,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 		used = false;
 	}
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free memory outside the spinlock if need be */
 	if (!used)
@@ -255,7 +255,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	do {
 		ret = -EINVAL;
 		if (drvdata->reading)
@@ -298,7 +298,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
 			csdev->refcnt++;
 		}
 	} while (0);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -333,16 +333,16 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -353,7 +353,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
 	drvdata->pid = -1;
 	coresight_set_mode(csdev, CS_MODE_DISABLED);
 
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n");
 	return 0;
@@ -368,9 +368,9 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -383,7 +383,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
 	}
 	if (!ret)
 		csdev->refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "TMC-ETF enabled\n");
@@ -398,9 +398,9 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return;
 	}
 
@@ -410,7 +410,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 		coresight_set_mode(csdev, CS_MODE_DISABLED);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
@@ -490,7 +490,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
 	if (WARN_ON_ONCE(coresight_get_mode(csdev) != CS_MODE_PERF))
 		return 0;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1)
@@ -587,7 +587,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
 	 */
 	CS_LOCK(drvdata->base);
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return to_read;
 }
@@ -705,7 +705,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
 		ret = -EBUSY;
@@ -737,7 +737,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 
 	drvdata->reading = true;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -754,14 +754,14 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Re-enable the TMC if need be */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
 		/* There is no point in reading a TMC in HW FIFO mode */
 		mode = readl_relaxed(drvdata->base + TMC_MODE);
 		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 			return -EINVAL;
 		}
 		/*
@@ -775,7 +775,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 		memset(drvdata->buf, 0, drvdata->size);
 		rc = __tmc_etb_enable_hw(drvdata);
 		if (rc) {
-			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 			return rc;
 		}
 	} else {
@@ -788,7 +788,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/*
 	 * Free allocated memory outside of the spinlock.  There is no need
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index eda7cdad0e2b..e501bd5ac6e9 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1251,10 +1251,10 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 	 * buffer, provided the size matches. Any allocation has to be done
 	 * with the lock released.
 	 */
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
 	if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 		/* Allocate memory with the locks released */
 		free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
@@ -1262,7 +1262,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 			return new_buf;
 
 		/* Let's try again */
-		spin_lock_irqsave(&drvdata->spinlock, flags);
+		raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	}
 
 	if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) {
@@ -1281,7 +1281,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free memory outside the spinlock if need be */
 	if (free_buf)
@@ -1299,7 +1299,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
 	if (IS_ERR(sysfs_buf))
 		return PTR_ERR(sysfs_buf);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/*
 	 * In sysFS mode we can have multiple writers per sink.  Since this
@@ -1318,7 +1318,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (!ret)
 		dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@@ -1637,17 +1637,17 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
 	struct etr_perf_buffer *etr_perf = config;
 	struct etr_buf *etr_buf = etr_perf->etr_buf;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		goto out;
 	}
 
 	if (WARN_ON(drvdata->perf_buf != etr_buf)) {
 		lost = true;
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		goto out;
 	}
 
@@ -1657,7 +1657,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
 	tmc_sync_etr_buf(drvdata);
 
 	CS_LOCK(drvdata->base);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	lost = etr_buf->full;
 	offset = etr_buf->offset;
@@ -1726,7 +1726,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	 /* Don't use this sink if it is already claimed by sysFS */
 	if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
 		rc = -EBUSY;
@@ -1766,7 +1766,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
 	}
 
 unlock_out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 }
 
@@ -1788,16 +1788,16 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -1810,7 +1810,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
 	/* Reset perf specific data */
 	drvdata->perf_buf = NULL;
 
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "TMC-ETR disabled\n");
 	return 0;
@@ -1910,7 +1910,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
 		ret = -EBUSY;
 		goto out;
@@ -1932,7 +1932,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 
 	drvdata->reading = true;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -1946,7 +1946,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* RE-enable the TMC if need be */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
@@ -1966,7 +1966,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	}
 
 	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free allocated memory out side of the spinlock */
 	if (sysfs_buf)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index b48bc9a01cc0..6541a27a018e 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -249,7 +249,7 @@ struct tmc_drvdata {
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
 	struct miscdevice	crashdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	pid_t			pid;
 	bool			reading;
 	bool			stop_on_flush;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:48:00 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:48:00 +0000
Subject: [PATCH v5 9/9] coresight/ultrasoc: change smb_drv_data spinlock's type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-10-yeoreum.yun@arm.com>

In ultrasoc-smb drivers, smb_drv_data->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since smb__drv_data->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type smb_drv_data->spinlock in ultrasoc-smb drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/ultrasoc-smb.c | 12 ++++++------
 drivers/hwtracing/coresight/ultrasoc-smb.h |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index dc3c9504dd7c..26cfc939e5bd 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -98,7 +98,7 @@ static int smb_open(struct inode *inode, struct file *file)
 	struct smb_drv_data *drvdata = container_of(file->private_data,
 					struct smb_drv_data, miscdev);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	if (drvdata->reading)
 		return -EBUSY;
@@ -152,7 +152,7 @@ static int smb_release(struct inode *inode, struct file *file)
 	struct smb_drv_data *drvdata = container_of(file->private_data,
 					struct smb_drv_data, miscdev);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 	drvdata->reading = false;
 
 	return 0;
@@ -245,7 +245,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
 	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
 	int ret = 0;
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	/* Do nothing, the trace data is reading by other interface now */
 	if (drvdata->reading)
@@ -280,7 +280,7 @@ static int smb_disable(struct coresight_device *csdev)
 {
 	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	if (drvdata->reading)
 		return -EBUSY;
@@ -378,7 +378,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev,
 	if (!buf)
 		return 0;
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	/* Don't do anything if another tracer is using this sink. */
 	if (csdev->refcnt != 1)
@@ -563,7 +563,7 @@ static int smb_probe(struct platform_device *pdev)
 
 	smb_reset_buffer(drvdata);
 	platform_set_drvdata(pdev, drvdata);
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	drvdata->pid = -1;
 
 	ret = smb_register_sink(pdev, drvdata);
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h
index a91d39cfccb8..c4c111275627 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.h
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.h
@@ -115,7 +115,7 @@ struct smb_drv_data {
 	struct coresight_device	*csdev;
 	struct smb_data_buffer sdb;
 	struct miscdevice miscdev;
-	spinlock_t spinlock;
+	raw_spinlock_t spinlock;
 	bool reading;
 	pid_t pid;
 };
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From dan.carpenter at linaro.org  Thu Mar  6 01:48:34 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Thu, 6 Mar 2025 12:48:34 +0300
Subject: [PATCH next] spi: stm32-ospi: Fix an IS_ERR() vs NULL bug in
 stm32_ospi_get_resources()
Message-ID: <bc4c9123-df43-4616-962f-765801d30b4c@stanley.mountain>

The devm_ioremap() function returns NULL on error, it doesn't return
error pointers.  Fix the check to match.

Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/spi/spi-stm32-ospi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index 8eadcb64f34a..a544d7897edf 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -835,10 +835,10 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
 	if (rmem) {
 		ospi->mm_size = rmem->size;
 		ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size);
-		if (IS_ERR(ospi->mm_base)) {
+		if (!ospi->mm_base) {
 			dev_err(dev, "unable to map memory region: %pa+%pa\n",
 				&rmem->base, &rmem->size);
-			ret = PTR_ERR(ospi->mm_base);
+			ret = -ENOMEM;
 			goto err_dma;
 		}
 
-- 
2.47.2



From james.clark at linaro.org  Thu Mar  6 01:45:15 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 6 Mar 2025 09:45:15 +0000
Subject: [PATCH 2/3] perf/arm_cspmu: Generalise event filtering
In-Reply-To: <c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
 <c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com>
Message-ID: <749f9235-d7cb-4807-b671-2809b5e8b948@linaro.org>



On 05/03/2025 4:10 pm, Robin Murphy wrote:
> The notion of a single u32 filter value for any event doesn't scale well
> when the potential architectural scope is already two 64-bit values, and
> implementations may add custom stuff on the side too. Rather than try to
> thread arbitrary filter data through the common path, let's just make
> the set_ev_filter op self-contained in terms of parsing and configuring
> any and all filtering for the given event - splitting out a distinct op
> for cycles events which inherently differ - and let implementations
> override the whole thing if they want to do something different. This
> already allows the Ampere code to stop looking a bit hacky.
> 
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

Reviewed-by: James Clark <james.clark at linaro.org>



From james.clark at linaro.org  Thu Mar  6 01:45:30 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 6 Mar 2025 09:45:30 +0000
Subject: [PATCH 1/3] perf/arm_cspmu: Move register definitons to header
In-Reply-To: <5a3c796560665b51cb63fec0d473afd8f8d0a836.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
 <5a3c796560665b51cb63fec0d473afd8f8d0a836.1741190362.git.robin.murphy@arm.com>
Message-ID: <4484f7e8-e3c5-4488-9b1c-40d9c7124ecd@linaro.org>



On 05/03/2025 4:10 pm, Robin Murphy wrote:
> Implementations may occasionally want to refer to register offsets, so
> for the sake of consistency move all of the register definitions to join
> the PMIIDR fields in the private header where they can be shared. As an
> example nicety, we can then define Ampere's imp-def filters in terms of
> the architectural PMIMPDEF range rather than open-coded offsets.
> 
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---

Reviewed-by: James Clark <james.clark at linaro.org>



From angelogioacchino.delregno at collabora.com  Thu Mar  6 01:47:47 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 6 Mar 2025 10:47:47 +0100
Subject: [PATCH v4 7/8] drm/mediatek: Add programming flow for unsupported
 subsys ID hardware
In-Reply-To: <20250218054405.2017918-8-jason-jh.lin@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-8-jason-jh.lin@mediatek.com>
Message-ID: <d1c2dfa8-c7e0-40b2-8b39-c04854e3ee24@collabora.com>

Il 18/02/25 06:41, Jason-JH Lin ha scritto:
> To support hardware without subsys IDs on new SoCs, add a programming
> flow that checks whether the subsys ID is valid. If the subsys ID is
> invalid, the flow will call 2 alternative CMDQ APIs:
> cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the same
> functionality.
> 
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> Reviewed-by: CK Hu <ck.hu at mediatek.com>
> ---
>   drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 33 ++++++++++++++++++++-----
>   1 file changed, 27 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index edc6417639e6..219d67735a54 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -66,14 +66,37 @@ struct mtk_ddp_comp_dev {
>   	struct cmdq_client_reg cmdq_reg;
>   };
>   
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +static void mtk_ddp_write_cmdq_pkt(struct cmdq_pkt *cmdq_pkt, struct cmdq_client_reg *cmdq_reg,
> +				   unsigned int offset, unsigned int value, unsigned int mask)
> +{
> +	offset += cmdq_reg->offset;
> +
> +	if (cmdq_reg->subsys != CMDQ_SUBSYS_INVALID) {
> +		if (mask == GENMASK(31, 0))
> +			cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys, offset, value);
> +		else
> +			cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg->subsys, offset, value, mask);

Sorry but this is pointless, really...

Function cmdq_pkt_write_mask() in mtk-cmdq-helper is doing:

	if (mask != GENMASK(31, 0)) {
		err = cmdq_pkt_mask(pkt, mask);
		if (err < 0)
			return err;

		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
	}
	return cmdq_pkt_write(pkt, subsys, offset_mask, value);

here you're doing the exact inverse check.

At this point you can just do:

static int mtk_ddp_write_cmdq_pkt(struct cmdq_pkt *cmdq_pkt, struct cmdq_client_reg 
*cmdq_reg,
				  u16 offset, u32 value, u32 mask)
{
	u16 gce_offset = cmdq_reg->offset + offset;

	if (cmdq_reg->subsys != CMDQ_SUBSYS_INVALID)
		return cmdq_pkt_write_mask(pkt, cmdq_reg->subsys, gce_offset, value, mask);

	return cmdq_pkt_write_mask_pa(cmdq_pkt, cmdq_reg->pa_base, gce_offset, value, mask);
}

Cheers,
Angelo

> +	} else {
> +		/* only MMIO access, no need to check mminfro_offset */
> +		cmdq_pkt_assign(cmdq_pkt, 0, CMDQ_ADDR_HIGH(cmdq_reg->pa_base));
> +		if (mask == GENMASK(31, 0))
> +			cmdq_pkt_write_s_value(cmdq_pkt, CMDQ_THR_SPR_IDX0,
> +					       CMDQ_ADDR_LOW(offset), value);
> +		else
> +			cmdq_pkt_write_s_mask_value(cmdq_pkt, CMDQ_THR_SPR_IDX0,
> +						    CMDQ_ADDR_LOW(offset), value, mask);
> +	}
> +}
> +#endif
> +
>   void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
>   		   struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
>   		   unsigned int offset)
>   {
>   #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>   	if (cmdq_pkt)
> -		cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
> -			       cmdq_reg->offset + offset, value);
> +		mtk_ddp_write_cmdq_pkt(cmdq_pkt, cmdq_reg, offset, value, GENMASK(31, 0));
>   	else
>   #endif
>   		writel(value, regs + offset);
> @@ -85,8 +108,7 @@ void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
>   {
>   #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>   	if (cmdq_pkt)
> -		cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
> -			       cmdq_reg->offset + offset, value);
> +		mtk_ddp_write_cmdq_pkt(cmdq_pkt, cmdq_reg, offset, value, GENMASK(31, 0));
>   	else
>   #endif
>   		writel_relaxed(value, regs + offset);
> @@ -98,8 +120,7 @@ void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
>   {
>   #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>   	if (cmdq_pkt) {
> -		cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg->subsys,
> -				    cmdq_reg->offset + offset, value, mask);
> +		mtk_ddp_write_cmdq_pkt(cmdq_pkt, cmdq_reg, offset, value, mask);
>   	} else {
>   #endif
>   		u32 tmp = readl(regs + offset);



From yeoreum.yun at arm.com  Thu Mar  6 01:47:51 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:51 +0000
Subject: [PATCH v5 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
Message-ID: <20250306094800.1082950-1-yeoreum.yun@arm.com>

In some coresight drivers, drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this,change type drvdata->spinlock in some coresight drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

from v4:
   - rebase to origin/next for coresight tree

Yeoreum Yun (9):
  coresight: change coresight_device lock type to raw_spinlock_t
  coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
  coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
  coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
  coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
  coresight-funnel: change funnel_drvdata spinlock's type to
    raw_spinlock_t
  coresight-replicator: change replicator_drvdata spinlock's type to
    raw_spinlock_t
  coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
  coresight/ultrasoc: change smb_drv_data spinlock's type to
    raw_spinlock_t

 .../hwtracing/coresight/coresight-config.c    |   8 +-
 .../hwtracing/coresight/coresight-config.h    |   2 +-
 drivers/hwtracing/coresight/coresight-core.c  |   2 +-
 .../hwtracing/coresight/coresight-cti-core.c  |  44 +--
 .../hwtracing/coresight/coresight-cti-sysfs.c |  76 +++---
 drivers/hwtracing/coresight/coresight-cti.h   |   2 +-
 drivers/hwtracing/coresight/coresight-etb10.c |  26 +-
 .../coresight/coresight-etm4x-core.c          |  18 +-
 .../coresight/coresight-etm4x-sysfs.c         | 250 +++++++++---------
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
 .../hwtracing/coresight/coresight-funnel.c    |  12 +-
 .../coresight/coresight-replicator.c          |  12 +-
 .../hwtracing/coresight/coresight-syscfg.c    |  26 +-
 .../hwtracing/coresight/coresight-tmc-core.c  |   6 +-
 .../hwtracing/coresight/coresight-tmc-etf.c   |  48 ++--
 .../hwtracing/coresight/coresight-tmc-etr.c   |  40 +--
 drivers/hwtracing/coresight/coresight-tmc.h   |   2 +-
 .../hwtracing/coresight/coresight-trace-id.c  |  22 +-
 drivers/hwtracing/coresight/ultrasoc-smb.c    |  12 +-
 drivers/hwtracing/coresight/ultrasoc-smb.h    |   2 +-
 include/linux/coresight.h                     |   4 +-
 21 files changed, 308 insertions(+), 308 deletions(-)

--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:53 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:53 +0000
Subject: [PATCH v5 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-3-yeoreum.yun@arm.com>

In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during
__schedule() by perf_event_task_sched_out()/in().

Since etmv4_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type etmv4_drvdata->spinlock
in coresight-etm4x drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
---
 .../hwtracing/coresight/coresight-config.c    |   8 +-
 .../hwtracing/coresight/coresight-config.h    |   2 +-
 .../coresight/coresight-etm4x-core.c          |  18 +-
 .../coresight/coresight-etm4x-sysfs.c         | 250 +++++++++---------
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
 5 files changed, 140 insertions(+), 140 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
index 4723bf7402a2..4f72ae71b696 100644
--- a/drivers/hwtracing/coresight/coresight-config.c
+++ b/drivers/hwtracing/coresight/coresight-config.c
@@ -76,10 +76,10 @@ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
 	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_set_reg(&feat_csdev->regs_csdev[i]);
-	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
 	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
 		feat_csdev->feat_desc->name, "set on enable");
 	return 0;
@@ -91,10 +91,10 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
 	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_save_reg(&feat_csdev->regs_csdev[i]);
-	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
 	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
 		feat_csdev->feat_desc->name, "save on disable");
 }
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 6ba013975741..b9ebc9fcfb7f 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -206,7 +206,7 @@ struct cscfg_feature_csdev {
 	const struct cscfg_feature_desc *feat_desc;
 	struct coresight_device *csdev;
 	struct list_head node;
-	spinlock_t *drv_spinlock;
+	raw_spinlock_t *drv_spinlock;
 	int nr_params;
 	struct cscfg_parameter_csdev *params_csdev;
 	int nr_regs;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index bb1e80df2914..e5972f16abff 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -830,7 +830,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
 			return ret;
 	}
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	drvdata->trcid = path->trace_id;
 
@@ -849,7 +849,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
 	if (ret)
 		etm4_release_trace_id(drvdata);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	if (!ret)
 		dev_dbg(&csdev->dev, "ETM tracing enabled\n");
@@ -1011,7 +1011,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	 * DYING hotplug callback is serviced by the ETM driver.
 	 */
 	cpus_read_lock();
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/*
 	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
@@ -1019,7 +1019,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	 */
 	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	cpus_read_unlock();
 
 	/*
@@ -1698,13 +1698,13 @@ static int etm4_starting_cpu(unsigned int cpu)
 	if (!etmdrvdata[cpu])
 		return 0;
 
-	spin_lock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
 	if (!etmdrvdata[cpu]->os_unlock)
 		etm4_os_unlock(etmdrvdata[cpu]);
 
 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
 		etm4_enable_hw(etmdrvdata[cpu]);
-	spin_unlock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
 	return 0;
 }
 
@@ -1713,10 +1713,10 @@ static int etm4_dying_cpu(unsigned int cpu)
 	if (!etmdrvdata[cpu])
 		return 0;
 
-	spin_lock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
 		etm4_disable_hw(etmdrvdata[cpu]);
-	spin_unlock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
 	return 0;
 }
 
@@ -2160,7 +2160,7 @@ static int etm4_probe(struct device *dev)
 			return -ENOMEM;
 	}
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	drvdata->cpu = coresight_get_cpu(dev);
 	if (drvdata->cpu < 0)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index e5216c0f60da..fdd0956fecb3 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -175,7 +175,7 @@ static ssize_t reset_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (val)
 		config->mode = 0x0;
 
@@ -267,7 +267,7 @@ static ssize_t reset_store(struct device *dev,
 	config->vmid_mask0 = 0x0;
 	config->vmid_mask1 = 0x0;
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	/* for sysfs - only release trace id when resetting */
 	etm4_release_trace_id(drvdata);
@@ -301,7 +301,7 @@ static ssize_t mode_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->mode = val & ETMv4_MODE_ALL;
 
 	if (drvdata->instrp0 == true) {
@@ -438,7 +438,7 @@ static ssize_t mode_store(struct device *dev,
 	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
 		etm4_config_trace_mode(config);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return size;
 }
@@ -467,14 +467,14 @@ static ssize_t pe_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (val > drvdata->nr_pe) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 
 	config->pe_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(pe);
@@ -502,7 +502,7 @@ static ssize_t event_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	switch (drvdata->nr_event) {
 	case 0x0:
 		/* EVENT0, bits[7:0] */
@@ -523,7 +523,7 @@ static ssize_t event_store(struct device *dev,
 	default:
 		break;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event);
@@ -551,7 +551,7 @@ static ssize_t event_instren_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* start by clearing all instruction event enable bits */
 	config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
 	switch (drvdata->nr_event) {
@@ -579,7 +579,7 @@ static ssize_t event_instren_store(struct device *dev,
 	default:
 		break;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event_instren);
@@ -740,11 +740,11 @@ static ssize_t event_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
 	config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
 	config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event_vinst);
@@ -772,13 +772,13 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* clear all EXLEVEL_S bits  */
 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
 	/* enable instruction tracing for corresponding exception level */
 	val &= drvdata->s_ex_level;
 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(s_exlevel_vinst);
@@ -807,13 +807,13 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* clear EXLEVEL_NS bits  */
 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
 	/* enable instruction tracing for corresponding exception level */
 	val &= drvdata->ns_ex_level;
 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ns_exlevel_vinst);
@@ -847,9 +847,9 @@ static ssize_t addr_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->addr_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_idx);
@@ -863,7 +863,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
 	len = scnprintf(buf, PAGE_SIZE, "%s\n",
@@ -871,7 +871,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
 			(val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
 			(val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
 			"data_load_store")));
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return len;
 }
 
@@ -889,13 +889,13 @@ static ssize_t addr_instdatatype_store(struct device *dev,
 	if (sscanf(buf, "%s", str) != 1)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!strcmp(str, "instr"))
 		/* TYPE, bits[1:0] */
 		config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_instdatatype);
@@ -910,14 +910,14 @@ static ssize_t addr_single_show(struct device *dev,
 	struct etmv4_config *config = &drvdata->config;
 
 	idx = config->addr_idx;
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -933,17 +933,17 @@ static ssize_t addr_single_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_single);
@@ -957,23 +957,23 @@ static ssize_t addr_range_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val1 = (unsigned long)config->addr_val[idx];
 	val2 = (unsigned long)config->addr_val[idx + 1];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -996,10 +996,10 @@ static ssize_t addr_range_store(struct device *dev,
 	if (val1 > val2)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -1007,7 +1007,7 @@ static ssize_t addr_range_store(struct device *dev,
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -1024,7 +1024,7 @@ static ssize_t addr_range_store(struct device *dev,
 		exclude = config->mode & ETM_MODE_EXCLUDE;
 	etm4_set_mode_exclude(drvdata, exclude ? true : false);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_range);
@@ -1038,17 +1038,17 @@ static ssize_t addr_start_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1064,22 +1064,22 @@ static ssize_t addr_start_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_START;
 	config->vissctlr |= BIT(idx);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_start);
@@ -1093,17 +1093,17 @@ static ssize_t addr_stop_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1119,22 +1119,22 @@ static ssize_t addr_stop_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	       config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
 	config->vissctlr |= BIT(idx + 16);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_stop);
@@ -1148,14 +1148,14 @@ static ssize_t addr_ctxtype_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* CONTEXTTYPE, bits[3:2] */
 	val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
 	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
 			(val == ETM_CTX_CTXID ? "ctxid" :
 			(val == ETM_CTX_VMID ? "vmid" : "all")));
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return len;
 }
 
@@ -1173,7 +1173,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
 	if (sscanf(buf, "%s", str) != 1)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!strcmp(str, "none"))
 		/* start by clearing context type bits */
@@ -1200,7 +1200,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
 		if (drvdata->numvmidc)
 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_ctxtype);
@@ -1214,11 +1214,11 @@ static ssize_t addr_context_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* context ID comparator bits[6:4] */
 	val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1239,12 +1239,12 @@ static ssize_t addr_context_store(struct device *dev,
 		     drvdata->numcidc : drvdata->numvmidc))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* clear context ID comparator bits[6:4] */
 	config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_context);
@@ -1258,10 +1258,10 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1280,12 +1280,12 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev,
 	if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
 	config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_exlevel_s_ns);
@@ -1308,7 +1308,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
 	int size = 0;
 	bool exclude = false;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	addr_v = config->addr_val[idx];
 	addr_ctrl = config->addr_acc[idx];
@@ -1323,7 +1323,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
 		}
 		exclude = config->viiectlr & BIT(idx / 2 + 16);
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	if (addr_type) {
 		size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx,
 				 addr_type_names[addr_type], addr_v);
@@ -1367,9 +1367,9 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev,
 	if (!drvdata->nr_pe_cmp)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vipcssctlr = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop);
@@ -1403,9 +1403,9 @@ static ssize_t seq_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->seq_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(seq_idx);
@@ -1449,10 +1449,10 @@ static ssize_t seq_event_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->seq_idx;
 	val = config->seq_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1468,11 +1468,11 @@ static ssize_t seq_event_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->seq_idx;
 	/* Seq control has two masks B[15:8] F[7:0] */
 	config->seq_ctrl[idx] = val & 0xFFFF;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(seq_event);
@@ -1536,9 +1536,9 @@ static ssize_t cntr_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->cntr_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_idx);
@@ -1552,10 +1552,10 @@ static ssize_t cntrldvr_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntrldvr[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1573,10 +1573,10 @@ static ssize_t cntrldvr_store(struct device *dev,
 	if (val > ETM_CNTR_MAX_VAL)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntrldvr[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntrldvr);
@@ -1590,10 +1590,10 @@ static ssize_t cntr_val_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1611,10 +1611,10 @@ static ssize_t cntr_val_store(struct device *dev,
 	if (val > ETM_CNTR_MAX_VAL)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntr_val[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_val);
@@ -1628,10 +1628,10 @@ static ssize_t cntr_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntr_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1647,10 +1647,10 @@ static ssize_t cntr_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntr_ctrl[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_ctrl);
@@ -1688,9 +1688,9 @@ static ssize_t res_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->res_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(res_idx);
@@ -1704,10 +1704,10 @@ static ssize_t res_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->res_idx;
 	val = config->res_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1723,7 +1723,7 @@ static ssize_t res_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->res_idx;
 	/* For odd idx pair inversal bit is RES0 */
 	if (idx % 2 != 0)
@@ -1733,7 +1733,7 @@ static ssize_t res_ctrl_store(struct device *dev,
 				       TRCRSCTLRn_INV |
 				       TRCRSCTLRn_GROUP_MASK |
 				       TRCRSCTLRn_SELECT_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(res_ctrl);
@@ -1762,9 +1762,9 @@ static ssize_t sshot_idx_store(struct device *dev,
 	if (val >= drvdata->nr_ss_cmp)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->ss_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_idx);
@@ -1777,9 +1777,9 @@ static ssize_t sshot_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_ctrl[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1795,12 +1795,12 @@ static ssize_t sshot_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ss_idx;
 	config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
 	/* must clear bit 31 in related status register on programming */
 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_ctrl);
@@ -1812,9 +1812,9 @@ static ssize_t sshot_status_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_status[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 static DEVICE_ATTR_RO(sshot_status);
@@ -1827,9 +1827,9 @@ static ssize_t sshot_pe_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_pe_cmp[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1845,12 +1845,12 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ss_idx;
 	config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
 	/* must clear bit 31 in related status register on programming */
 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_pe_ctrl);
@@ -1884,9 +1884,9 @@ static ssize_t ctxid_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->ctxid_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_idx);
@@ -1907,10 +1907,10 @@ static ssize_t ctxid_pid_show(struct device *dev,
 	if (task_active_pid_ns(current) != &init_pid_ns)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ctxid_idx;
 	val = (unsigned long)config->ctxid_pid[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1945,10 +1945,10 @@ static ssize_t ctxid_pid_store(struct device *dev,
 	if (kstrtoul(buf, 16, &pid))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ctxid_idx;
 	config->ctxid_pid[idx] = (u64)pid;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_pid);
@@ -1968,10 +1968,10 @@ static ssize_t ctxid_masks_show(struct device *dev,
 	if (task_active_pid_ns(current) != &init_pid_ns)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val1 = config->ctxid_mask0;
 	val2 = config->ctxid_mask1;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -2004,7 +2004,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
 	if ((drvdata->numcidc > 4) && (nr_inputs != 2))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/*
 	 * each byte[0..3] controls mask value applied to ctxid
 	 * comparator[0..3]
@@ -2076,7 +2076,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
 			mask >>= 0x8;
 	}
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_masks);
@@ -2110,9 +2110,9 @@ static ssize_t vmid_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vmid_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_idx);
@@ -2132,9 +2132,9 @@ static ssize_t vmid_val_show(struct device *dev,
 	if (!task_is_in_init_pid_ns(current))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = (unsigned long)config->vmid_val[config->vmid_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -2162,9 +2162,9 @@ static ssize_t vmid_val_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vmid_val[config->vmid_idx] = (u64)val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_val);
@@ -2183,10 +2183,10 @@ static ssize_t vmid_masks_show(struct device *dev,
 	if (!task_is_in_init_pid_ns(current))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val1 = config->vmid_mask0;
 	val2 = config->vmid_mask1;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -2218,7 +2218,7 @@ static ssize_t vmid_masks_store(struct device *dev,
 	if ((drvdata->numvmidc > 4) && (nr_inputs != 2))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/*
 	 * each byte[0..3] controls mask value applied to vmid
@@ -2291,7 +2291,7 @@ static ssize_t vmid_masks_store(struct device *dev,
 		else
 			mask >>= 0x8;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_masks);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 2b92de17b5a2..bd7db36ba197 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -989,7 +989,7 @@ struct etmv4_drvdata {
 	struct clk			*pclk;
 	void __iomem			*base;
 	struct coresight_device		*csdev;
-	spinlock_t			spinlock;
+	raw_spinlock_t			spinlock;
 	int				cpu;
 	u8				arch;
 	u8				nr_pe;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:54 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:54 +0000
Subject: [PATCH v5 3/9] coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-4-yeoreum.yun@arm.com>

coresight_trace_id_map->lock can be acquired while coresight devices'
drvdata_lock.

But the drvdata_lock can be raw_spinlock_t (i.e) coresight-etm4x.

To address this, change type of coresight_trace_id_map->lock to
raw_spinlock_t

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c  |  2 +-
 .../hwtracing/coresight/coresight-trace-id.c  | 22 +++++++++----------
 include/linux/coresight.h                     |  2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..90649837c29e 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1296,7 +1296,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 
 	if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
 	    csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
-		spin_lock_init(&csdev->perf_sink_id_map.lock);
+		raw_spin_lock_init(&csdev->perf_sink_id_map.lock);
 		csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
 		if (!csdev->perf_sink_id_map.cpu_map) {
 			kfree(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-trace-id.c b/drivers/hwtracing/coresight/coresight-trace-id.c
index 378af743be45..7ed337d54d3e 100644
--- a/drivers/hwtracing/coresight/coresight-trace-id.c
+++ b/drivers/hwtracing/coresight/coresight-trace-id.c
@@ -22,7 +22,7 @@ enum trace_id_flags {
 static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
 static struct coresight_trace_id_map id_map_default = {
 	.cpu_map = &id_map_default_cpu_ids,
-	.lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock)
+	.lock = __RAW_SPIN_LOCK_UNLOCKED(id_map_default.lock)
 };
 
 /* #define TRACE_ID_DEBUG 1 */
@@ -131,11 +131,11 @@ static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map
 	unsigned long flags;
 	int cpu;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
 	for_each_possible_cpu(cpu)
 		atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 	DUMP_ID_MAP(id_map);
 }
 
@@ -144,7 +144,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
 	unsigned long flags;
 	int id;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 
 	/* check for existing allocation for this CPU */
 	id = _coresight_trace_id_read_cpu_id(cpu, id_map);
@@ -171,7 +171,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
 	atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
 
 get_cpu_id_out_unlock:
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID_CPU(cpu, id);
 	DUMP_ID_MAP(id_map);
@@ -188,12 +188,12 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma
 	if (!id)
 		return;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 
 	coresight_trace_id_free(id, id_map);
 	atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
 
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 	DUMP_ID_CPU(cpu, id);
 	DUMP_ID_MAP(id_map);
 }
@@ -204,9 +204,9 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i
 	unsigned long flags;
 	int id;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	id = coresight_trace_id_alloc_new_id(id_map, preferred_id, traceid_flags);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID(id);
 	DUMP_ID_MAP(id_map);
@@ -217,9 +217,9 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	coresight_trace_id_free(id, id_map);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID(id);
 	DUMP_ID_MAP(id_map);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 4541bfc1cc6b..d79a242b271d 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -239,7 +239,7 @@ struct coresight_trace_id_map {
 	DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX);
 	atomic_t __percpu *cpu_map;
 	atomic_t perf_cs_etm_session_active;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 };
 
 /**
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 01:47:52 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 09:47:52 +0000
Subject: [PATCH v5 1/9] coresight: change coresight_device lock type to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-1-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
Message-ID: <20250306094800.1082950-2-yeoreum.yun@arm.com>

coresight_device->cscfg_csdev_lock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since coresight->cscfg_csdev_lock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type of coresight_device->cscfg_csdev_lock
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-syscfg.c    | 26 +++++++++----------
 include/linux/coresight.h                     |  2 +-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 11138a9762b0..a70c1454b410 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -89,9 +89,9 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
 	}
 	/* if matched features, add config to device.*/
 	if (config_csdev) {
-		spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+		raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 		list_add(&config_csdev->node, &csdev->config_csdev_list);
-		spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+		raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 	}
 
 	return 0;
@@ -194,9 +194,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
 
 	/* add to internal csdev feature list & initialise using reset call */
 	cscfg_reset_feat(feat_csdev);
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_add(&feat_csdev->node, &csdev->feature_csdev_list);
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	return 0;
 }
@@ -765,7 +765,7 @@ static int cscfg_list_add_csdev(struct coresight_device *csdev,
 
 	INIT_LIST_HEAD(&csdev->feature_csdev_list);
 	INIT_LIST_HEAD(&csdev->config_csdev_list);
-	spin_lock_init(&csdev->cscfg_csdev_lock);
+	raw_spin_lock_init(&csdev->cscfg_csdev_lock);
 
 	return 0;
 }
@@ -855,7 +855,7 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 	struct cscfg_feature_csdev *feat_csdev;
 	unsigned long flags;
 
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	if (list_empty(&csdev->feature_csdev_list))
 		goto unlock_exit;
 
@@ -863,7 +863,7 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 		cscfg_reset_feat(feat_csdev);
 
 unlock_exit:
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
 
@@ -1059,7 +1059,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 	 * Look for matching configuration - set the active configuration
 	 * context if found.
 	 */
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
 		config_desc = config_csdev_item->config_desc;
 		if ((atomic_read(&config_desc->active_cnt)) &&
@@ -1069,7 +1069,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	/*
 	 * If found, attempt to enable
@@ -1090,12 +1090,12 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 			 *
 			 * Set enabled if OK, err if not.
 			 */
-			spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+			raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 			if (csdev->active_cscfg_ctxt)
 				config_csdev_active->enabled = true;
 			else
 				err = -EBUSY;
-			spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+			raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 		}
 	}
 	return err;
@@ -1124,7 +1124,7 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
 	 * If it was not enabled, we have no work to do, otherwise mark as disabled.
 	 * Clear the active config pointer.
 	 */
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
 	if (config_csdev) {
 		if (!config_csdev->enabled)
@@ -1133,7 +1133,7 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
 			config_csdev->enabled = false;
 	}
 	csdev->active_cscfg_ctxt = NULL;
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	/* true if there was an enabled active config */
 	if (config_csdev)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 89b781e70fe7..4541bfc1cc6b 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -302,7 +302,7 @@ struct coresight_device {
 	/* system configuration and feature lists */
 	struct list_head feature_csdev_list;
 	struct list_head config_csdev_list;
-	spinlock_t cscfg_csdev_lock;
+	raw_spinlock_t cscfg_csdev_lock;
 	void *active_cscfg_ctxt;
 };
 
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From horms at kernel.org  Thu Mar  6 01:57:10 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 6 Mar 2025 09:57:10 +0000
Subject: [PATCH net-next] net: stmmac: simplify phylink_suspend() and
 phylink_resume() calls
In-Reply-To: <E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk>
References: <E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk>
Message-ID: <20250306095710.GR3666230@kernel.org>

On Tue, Mar 04, 2025 at 11:21:27AM +0000, Russell King (Oracle) wrote:
> Currently, the calls to phylink's suspend and resume functions are
> inside overly complex tests, and boil down to:
> 
> 	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
> 		call phylink
> 	} else {
> 		call phylink and
> 		if (device_may_wakeup(priv->device))
> 			do something else
> 	}
> 
> This results in phylink always being called, possibly with differing
> arguments for phylink_suspend().
> 
> Simplify this code, noting that each site is slightly different due to
> the order in which phylink is called and the "something else".
> 
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Reviewed-by: Simon Horman <horms at kernel.org>


From maxime.chevallier at bootlin.com  Thu Mar  6 02:12:20 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 6 Mar 2025 11:12:20 +0100
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <350bb4f6-f4b5-44c3-a821-ac53c8641705@redhat.com>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
	<20250303090321.805785-10-maxime.chevallier@bootlin.com>
	<350bb4f6-f4b5-44c3-a821-ac53c8641705@redhat.com>
Message-ID: <20250306111220.28798e6b@fedora.home>

On Thu, 6 Mar 2025 09:56:32 +0100
Paolo Abeni <pabeni at redhat.com> wrote:

> On 3/3/25 10:03 AM, Maxime Chevallier wrote:
> > @@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
> >  	linkmode_copy(pl->link_config.advertising, pl->supported);
> >  	phylink_validate(pl, pl->supported, &pl->link_config);
> >  
> > -	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
> > -			       pl->supported, true);
> > +	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
> > +			    pl->supported, true);
> > +	if (c)
> > +		linkmode_and(match, pl->supported, c->linkmodes);  
> 
> How about using only the first bit from `c->linkmodes`, to avoid
> behavior changes?

If what we want is to keep the exact same behaviour, then we need to
go one step further and make sure we keep the same one as before, and
it's not guaranteed that the first bit in c->linkmodes is this one.

We could however have a default supported mask for fixed-link in phylink
that contains all the linkmodes we allow for fixed links, then filter
with the lookup, something like :


-       linkmode_fill(pl->supported);
+       /* (in a dedicated helper) Linkmodes reported for fixed links below
+        * 10G */
+       linkmode_zero(pl->supported);
+
+       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, pl->supported);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, pl->supported);
+
        linkmode_copy(pl->link_config.advertising, pl->supported);
        phylink_validate(pl, pl->supported, &pl->link_config);
 
-       s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
-                              pl->supported, true);
+       c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
+                           pl->supported, true);
+       if (c)
+               linkmode_and(match, pl->supported, c->linkmodes);

That way we should have a consistent behaviour with what we currently
have, and to me it's more explicit what will the  fixed-link linkmodes
be.

I'd like to make sure Russell is OK with that though :)

Thanks you for the review Paolo !

Maxime


From andre.draszik at linaro.org  Thu Mar  6 02:14:46 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Thu, 06 Mar 2025 10:14:46 +0000
Subject: [PATCH 1/3] arm64: defconfig: enable Maxim max77759 driver
In-Reply-To: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
References: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
Message-ID: <20250306-b4-max77759-mfd-dts-v1-1-9fe8b0eb8123@linaro.org>

Enable the Maxim max77759 as this is used by the gs101-oriole and
gs101-raven (Google Pixel 6 and Pixel 6 Pro) boards,

The child devices' defaults are based on this MFD driver's state, so
this commit enables those implicitly as well.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index a1cc3814b09b31ee659536a64b7db704153d6fe9..eaa88c3e6a93ce555468458763c2531fee2a903f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -763,6 +763,7 @@ CONFIG_MFD_EXYNOS_LPASS=m
 CONFIG_MFD_HI6421_PMIC=y
 CONFIG_MFD_HI655X_PMIC=y
 CONFIG_MFD_MAX77620=y
+CONFIG_MFD_MAX77759=m
 CONFIG_MFD_MT6360=y
 CONFIG_MFD_MT6397=y
 CONFIG_MFD_SPMI_PMIC=y

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From andre.draszik at linaro.org  Thu Mar  6 02:14:48 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Thu, 06 Mar 2025 10:14:48 +0000
Subject: [PATCH 3/3] arm64: dts: exynos: gs101-pixel-common: add
 nvmem-reboot-mode
In-Reply-To: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
References: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
Message-ID: <20250306-b4-max77759-mfd-dts-v1-3-9fe8b0eb8123@linaro.org>

Now that we have the NVMEM, we can also hook-in the nvmem-reboot-mode,
so as to have Linux communicate the requested boot mode to the boot
loader via it.

The two remarks regarding missing reboot modes from commit ae32b65c9359
("arm64: dts: exynos: gs101: add reboot-mode support (SYSIP_DAT0)")
apply to this commit as well.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 .../arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi b/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
index f67fa1e84d994de4d40f29a2d437ab6401ac133d..41f63b4d93fd34e1c955d1f47039cc0d9fb4813a 100644
--- a/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
+++ b/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
@@ -60,6 +60,20 @@ button-power {
 		};
 	};
 
+	reboot-mode {
+		compatible = "nvmem-reboot-mode";
+		nvmem-cells = <&nvmem_reboot_mode>;
+		nvmem-cell-names = "reboot-mode";
+		mode-bootloader = <0x800000fc>;
+		mode-charge = <0x8000000a>;
+		mode-fastboot = <0x800000fa>;
+		mode-reboot-ab-update = <0x80000052>;
+		mode-recovery = <0x800000ff>;
+		mode-rescue = <0x800000f9>;
+		mode-shutdown-thermal = <0x80000051>;
+		mode-shutdown-thermal-battery = <0x80000051>;
+	};
+
 	/* TODO: Remove this once PMIC is implemented  */
 	reg_placeholder: regulator-0 {
 		compatible = "regulator-fixed";
@@ -224,7 +238,7 @@ nvmem-layout {
 				#address-cells = <1>;
 				#size-cells = <1>;
 
-				reboot-mode at 0 {
+				nvmem_reboot_mode: reboot-mode at 0 {
 					reg = <0x0 0x4>;
 				};
 

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From andre.draszik at linaro.org  Thu Mar  6 02:14:45 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Thu, 06 Mar 2025 10:14:45 +0000
Subject: [PATCH 0/3] gs101 max77759 enablement (DT)
Message-ID: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>

Hi,

This series enables the recently submitted Maxim max77759 driver and
updates the DT for the Google Pixel 6 / Pro (oriole / raven) boards
accordingly.

!!! Dependency note !!!

This series depends on the corresponding driver and DT bindings
proposed in
https://lore.kernel.org/r/20250228-max77759-mfd-v3-0-0c3627d42526 at linaro.org

Note that in that series bindings and gpio driver are accepted, but mfd
and nvmem drivers are still waiting for review comments.

!!! Dependency note end !!!

This gives us some extra GPIOs, and enables NVMEM which is used to
communicate the requested boot mode to the bootloader when doing a cold
reset.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Andr? Draszik (3):
      arm64: defconfig: enable Maxim max77759 driver
      arm64: dts: exynos: gs101-pixel-common: add the MAX77759 PMIC
      arm64: dts: exynos: gs101-pixel-common: add nvmem-reboot-mode

 .../boot/dts/exynos/google/gs101-pixel-common.dtsi | 75 ++++++++++++++++++++++
 arch/arm64/configs/defconfig                       |  1 +
 2 files changed, 76 insertions(+)
---
base-commit: 0226d0ce98a477937ed295fb7df4cc30b46fc304
change-id: 20250306-b4-max77759-mfd-dts-fb88b6c6bd60

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Thu Mar  6 02:14:47 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Thu, 06 Mar 2025 10:14:47 +0000
Subject: [PATCH 2/3] arm64: dts: exynos: gs101-pixel-common: add the
 MAX77759 PMIC
In-Reply-To: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
References: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
Message-ID: <20250306-b4-max77759-mfd-dts-v1-2-9fe8b0eb8123@linaro.org>

Also add the subnodes for the GPIO expander and NVMEM, and define the
NVMEM layout.

The NVMEM layout is declared such that it matches downstream's
open-coded configuration [1].

The pinctrl nodes are kept sorted by the 'samsung,pins' property rather
than node name, as I think that makes it easier to look at and to add
new nodes unambiguously in the future.

Link: https://android.googlesource.com/kernel/google-modules/bms/+/96e729a83817/max77759_maxq.c#67 [1]
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 .../boot/dts/exynos/google/gs101-pixel-common.dtsi | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi b/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
index b25230495c64dce60916b7cd5dcb9a7cce5d0e4e..f67fa1e84d994de4d40f29a2d437ab6401ac133d 100644
--- a/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
+++ b/arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
@@ -188,6 +188,60 @@ usbc0_role_sw: endpoint {
 			};
 		};
 	};
+
+	pmic at 66 {
+		compatible = "maxim,max77759";
+		reg = <0x66>;
+
+		pinctrl-0 = <&if_pmic_int>;
+		pinctrl-names = "default";
+		interrupts-extended = <&gpa8 3 IRQ_TYPE_LEVEL_LOW>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		gpio {
+			compatible = "maxim,max77759-gpio";
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			/*
+			 * "Human-readable name [SIGNAL_LABEL]" where the
+			 * latter comes from the schematic
+			 */
+			gpio-line-names = "OTG boost [OTG_BOOST_EN]",
+					  "max20339 IRQ [MW_OVP_INT_L]";
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		nvmem-0 {
+			compatible = "maxim,max77759-nvmem";
+
+			nvmem-layout {
+				compatible = "fixed-layout";
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				reboot-mode at 0 {
+					reg = <0x0 0x4>;
+				};
+
+				boot-reason at 4 {
+					reg = <0x4 0x4>;
+				};
+
+				shutdown-user-flag at 8 {
+					reg = <0x8 0x1>;
+				};
+
+				rsoc at a {
+					reg = <0xa 0x2>;
+				};
+			};
+		};
+	};
 };
 
 &pinctrl_far_alive {
@@ -211,6 +265,13 @@ typec_int: typec-int-pins {
 		samsung,pin-pud = <GS101_PIN_PULL_UP>;
 		samsung,pin-drv = <GS101_PIN_DRV_2_5_MA>;
 	};
+
+	if_pmic_int: if-pmic-int-pins {
+		samsung,pins = "gpa8-3";
+		samsung,pin-function = <GS101_PIN_FUNC_EINT>;
+		samsung,pin-pud = <GS101_PIN_PULL_UP>;
+		samsung,pin-drv = <GS101_PIN_DRV_2_5_MA>;
+	};
 };
 
 &pinctrl_gpio_alive {

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From suzuki.poulose at arm.com  Thu Mar  6 02:25:37 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 6 Mar 2025 10:25:37 +0000
Subject: [PATCH v5 8/9] coresight-tmc: change tmc_drvdata spinlock's type
 to raw_spinlock_t
In-Reply-To: <20250306094800.1082950-9-yeoreum.yun@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
 <20250306094800.1082950-9-yeoreum.yun@arm.com>
Message-ID: <c7a142ee-d34f-494a-b4f9-921d739aeb59@arm.com>

Hi Levi,

On 06/03/2025 09:47, Yeoreum Yun wrote:
> In coresight-tmc drivers, tmc_drvdata->spinlock can be held
> during __schedule() by perf_event_task_sched_out()/in().
> 
> Since tmc_drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
> 
> To address this, change type tmc_drvdata->spinlock in coresight-tmc drivers,
> which can be called by perf_event_task_sched_out()/in(),
> from spinlock_t to raw_spinlock_t.
> 
> Reviewed-by: James Clark <james.clark at linaro.org>
> Reviewed-by: Mike Leach <mike.leach at linaro.org>
> Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>


Unfortunately, this still doesn't cover the current coresight next 
branch. I get build errors as below :

"[PATCH] coresight-tmc: change tmc_drvdata spinlock's type to" has style 
problems, please review. This is because, we merged the coresight panic
trace support in the coresight next, on 21st Feb.


NOTE: If any of the errors are false positives, please report
       them to the maintainer, see CHECKPATCH in MAINTAINERS.
   CALL    scripts/checksyscalls.sh
   CC [M]  drivers/hwtracing/coresight/coresight-tmc-core.o
   CC [M]  drivers/hwtracing/coresight/coresight-tmc-etf.o
   CC [M]  drivers/hwtracing/coresight/coresight-tmc-etr.o
   CC [M]  drivers/hwtracing/coresight/coresight-catu.o
In file included from ./include/linux/mmzone.h:8,
                  from ./include/linux/gfp.h:7,
                  from ./include/linux/slab.h:16,
                  from ./include/linux/resource_ext.h:11,
                  from ./include/linux/acpi.h:13,
                  from drivers/hwtracing/coresight/coresight-tmc-core.c:7:
drivers/hwtracing/coresight/coresight-tmc-core.c: In function 
?tmc_crashdata_open?:
drivers/hwtracing/coresight/coresight-tmc-core.c:361:20: error: passing 
argument 1 of ?spinlock_check? from incompatible pointer type 
[-Werror=incompatible-pointer-types]
   361 |  spin_lock_irqsave(&drvdata->spinlock, flags);
       |                    ^~~~~~~~~~~~~~~~~~
       |                    |
       |                    raw_spinlock_t * {aka struct raw_spinlock *}
./include/linux/spinlock.h:244:34: note: in definition of macro 
?raw_spin_lock_irqsave?
   244 |   flags = _raw_spin_lock_irqsave(lock); \
       |                                  ^~~~
drivers/hwtracing/coresight/coresight-tmc-core.c:361:2: note: in 
expansion of macro ?spin_lock_irqsave?
   361 |  spin_lock_irqsave(&drvdata->spinlock, flags);
       |  ^~~~~~~~~~~~~~~~~
In file included from ./include/linux/mmzone.h:8,
                  from ./include/linux/gfp.h:7,
                  from ./include/linux/slab.h:16,
                  from ./include/linux/resource_ext.h:11,
                  from ./include/linux/acpi.h:13,
                  from drivers/hwtracing/coresight/coresight-tmc-core.c:7:
./include/linux/spinlock.h:324:67: note: expected ?spinlock_t *? {aka 
?struct spinlock *?} but argument is of type ?raw_spinlock_t *? {aka 
?struct raw_spinlock *?}
   324 | static __always_inline raw_spinlock_t 
*spinlock_check(spinlock_t *lock)


Cheers
Suzuki



From fabrice.gasnier at foss.st.com  Thu Mar  6 02:25:01 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 6 Mar 2025 11:25:01 +0100
Subject: [PATCH v3] clocksource: stm32-lptimer: use wakeup capable instead of init wakeup
Message-ID: <20250306102501.2980153-1-fabrice.gasnier@foss.st.com>

From: Alexandre Torgue <alexandre.torgue at foss.st.com>

"wakeup-source" property describes a device which has wakeup capability
but should not force this device as a wakeup source.

Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver")
Cc: stable at vger.kernel.org
Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 drivers/clocksource/timer-stm32-lp.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index a4c95161cb22..193e4f643358 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 	}
 
 	if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
-		ret = device_init_wakeup(&pdev->dev, true);
-		if (ret)
-			goto out_clk_disable;
+		device_set_wakeup_capable(&pdev->dev, true);
 
 		ret = dev_pm_set_wake_irq(&pdev->dev, irq);
 		if (ret)
-- 
2.25.1



From patrice.chotard at foss.st.com  Thu Mar  6 02:26:58 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Thu, 6 Mar 2025 11:26:58 +0100
Subject: [PATCH next] spi: stm32-ospi: Fix an IS_ERR() vs NULL bug in
 stm32_ospi_get_resources()
In-Reply-To: <bc4c9123-df43-4616-962f-765801d30b4c@stanley.mountain>
References: <bc4c9123-df43-4616-962f-765801d30b4c@stanley.mountain>
Message-ID: <f681046c-449f-42fd-8c97-36c459fdb3e6@foss.st.com>



On 3/6/25 10:48, Dan Carpenter wrote:
> The devm_ioremap() function returns NULL on error, it doesn't return
> error pointers.  Fix the check to match.
> 
> Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
>  drivers/spi/spi-stm32-ospi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
> index 8eadcb64f34a..a544d7897edf 100644
> --- a/drivers/spi/spi-stm32-ospi.c
> +++ b/drivers/spi/spi-stm32-ospi.c
> @@ -835,10 +835,10 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
>  	if (rmem) {
>  		ospi->mm_size = rmem->size;
>  		ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size);
> -		if (IS_ERR(ospi->mm_base)) {
> +		if (!ospi->mm_base) {
>  			dev_err(dev, "unable to map memory region: %pa+%pa\n",
>  				&rmem->base, &rmem->size);
> -			ret = PTR_ERR(ospi->mm_base);
> +			ret = -ENOMEM;
>  			goto err_dma;
>  		}
>  


Reviewed-by: Patrice Chotard <patrice.chotard at foss.st.com>

Thanks
Patrice


From ankita at nvidia.com  Thu Mar  6 02:31:36 2025
From: ankita at nvidia.com (Ankit Agrawal)
Date: Thu, 6 Mar 2025 10:31:36 +0000
Subject: [PATCH] iommufd: Set domain->iommufd_hwpt in all hwpt->domain
 allocators
In-Reply-To: <BN9PR11MB52766B3F3ED1F7F14EA3B7B48CCA2@BN9PR11MB5276.namprd11.prod.outlook.com>
References: <20250305211800.229465-1-nicolinc@nvidia.com>
 <BN9PR11MB52766B3F3ED1F7F14EA3B7B48CCA2@BN9PR11MB5276.namprd11.prod.outlook.com>
Message-ID: <SA1PR12MB71999DB4E14F3A2F4650D964B0CA2@SA1PR12MB7199.namprd12.prod.outlook.com>

>> Since iommufd_sw_msi() requires to access the domain->iommufd_hwpt, it
>> is
>> better to set that explicitly prior to calling iommu_domain_set_sw_msi().
>>
>> Fixes: 748706d7ca06 ("iommu: Turn fault_data to iommufd private pointer")
>> Reported-by: Ankit Agrawal <ankita at nvidia.com>
>> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
>
> Reviewed-by: Kevin Tian <kevin.tian at intel.com>

Tested-by: Ankit Agrawal <ankita at nvidia.com>

From yeoreum.yun at arm.com  Thu Mar  6 02:35:07 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu, 6 Mar 2025 10:35:07 +0000
Subject: [PATCH v5 8/9] coresight-tmc: change tmc_drvdata spinlock's type
 to raw_spinlock_t
In-Reply-To: <c7a142ee-d34f-494a-b4f9-921d739aeb59@arm.com>
References: <20250306094800.1082950-1-yeoreum.yun@arm.com>
 <20250306094800.1082950-9-yeoreum.yun@arm.com>
 <c7a142ee-d34f-494a-b4f9-921d739aeb59@arm.com>
Message-ID: <Z8l6W8KtWkA5kS0s@e129823.arm.com>

Hi, Suzuki

> Unfortunately, this still doesn't cover the current coresight next branch. I
> get build errors as below :
>
> "[PATCH] coresight-tmc: change tmc_drvdata spinlock's type to" has style
> problems, please review. This is because, we merged the coresight panic
> trace support in the coresight next, on 21st Feb.
>
>
> NOTE: If any of the errors are false positives, please report
>       them to the maintainer, see CHECKPATCH in MAINTAINERS.
>   CALL    scripts/checksyscalls.sh
>   CC [M]  drivers/hwtracing/coresight/coresight-tmc-core.o
>   CC [M]  drivers/hwtracing/coresight/coresight-tmc-etf.o
>   CC [M]  drivers/hwtracing/coresight/coresight-tmc-etr.o
>   CC [M]  drivers/hwtracing/coresight/coresight-catu.o
> In file included from ./include/linux/mmzone.h:8,
>                  from ./include/linux/gfp.h:7,
>                  from ./include/linux/slab.h:16,
>                  from ./include/linux/resource_ext.h:11,
>                  from ./include/linux/acpi.h:13,
>                  from drivers/hwtracing/coresight/coresight-tmc-core.c:7:
> drivers/hwtracing/coresight/coresight-tmc-core.c: In function
> ?tmc_crashdata_open?:
> drivers/hwtracing/coresight/coresight-tmc-core.c:361:20: error: passing
> argument 1 of ?spinlock_check? from incompatible pointer type
> [-Werror=incompatible-pointer-types]
>   361 |  spin_lock_irqsave(&drvdata->spinlock, flags);
>       |                    ^~~~~~~~~~~~~~~~~~
>       |                    |
>       |                    raw_spinlock_t * {aka struct raw_spinlock *}
> ./include/linux/spinlock.h:244:34: note: in definition of macro
> ?raw_spin_lock_irqsave?
>   244 |   flags = _raw_spin_lock_irqsave(lock); \
>       |                                  ^~~~
> drivers/hwtracing/coresight/coresight-tmc-core.c:361:2: note: in expansion
> of macro ?spin_lock_irqsave?
>   361 |  spin_lock_irqsave(&drvdata->spinlock, flags);
>       |  ^~~~~~~~~~~~~~~~~
> In file included from ./include/linux/mmzone.h:8,
>                  from ./include/linux/gfp.h:7,
>                  from ./include/linux/slab.h:16,
>                  from ./include/linux/resource_ext.h:11,
>                  from ./include/linux/acpi.h:13,
>                  from drivers/hwtracing/coresight/coresight-tmc-core.c:7:
> ./include/linux/spinlock.h:324:67: note: expected ?spinlock_t *? {aka
> ?struct spinlock *?} but argument is of type ?raw_spinlock_t *? {aka ?struct
> raw_spinlock *?}
>   324 | static __always_inline raw_spinlock_t *spinlock_check(spinlock_t
> *lock)

Sorry! I'll rework again for this. thanks!



From pabeni at redhat.com  Thu Mar  6 02:47:22 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Thu, 6 Mar 2025 11:47:22 +0100
Subject: [PATCH net-next v4 02/13] net: phy: Use an internal, searchable
 storage for the linkmodes
In-Reply-To: <20250306095726.04125e5f@fedora.home>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
 <20250303090321.805785-3-maxime.chevallier@bootlin.com>
 <738bd67c-8688-4902-805f-4e35e6aaed4a@redhat.com>
 <20250306095726.04125e5f@fedora.home>
Message-ID: <5d0b952a-ec07-4ebf-8228-a424fc0de4cd@redhat.com>

On 3/6/25 9:57 AM, Maxime Chevallier wrote:
> On Thu, 6 Mar 2025 09:30:11 +0100
> Paolo Abeni <pabeni at redhat.com> wrote:
>> On 3/3/25 10:03 AM, Maxime Chevallier wrote:
[...]
>>> +/**
>>> + * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
>>> + */
>>> +void phy_caps_init(void)
>>> +{
>>> +	const struct link_mode_info *linkmode;
>>> +	int i, capa;
>>> +
>>> +	/* Fill the caps array from net/ethtool/common.c */
>>> +	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
>>> +		linkmode = &link_mode_params[i];
>>> +		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
>>> +
>>> +		if (capa < 0)
>>> +			continue;  
>>
>> Or even error-out here.
> 
> Good point yes indeed. Russell raised the point for the need of keeping
> this in sync with new SPEED_XXX definitions, I'll add a check that
> errors out.
> 
> I hope that's OK though, as higher speeds are introduced and used by
> NICs that usually don't use phylib at all, so there's a good chance
> that the developper introducing the new speed won't have CONFIG_PHYLIB
> enabled.
> 
> Is that still good ?

I think so. New linkmodes should be added on net-next. Booting the
kernel with phylib support on any device should catch the error. I think
even the CI should catch this.

Thanks,

Paolo



From ulf.hansson at linaro.org  Thu Mar  6 02:53:14 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Thu, 6 Mar 2025 11:53:14 +0100
Subject: [PATCH v3] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <20250306061805.2318154-1-ping.bai@nxp.com>
References: <20250306061805.2318154-1-ping.bai@nxp.com>
Message-ID: <CAPDyKForY4VNZtqietDPt2FQM3p4OsaoE_oJb0PPLUAh98WsHQ@mail.gmail.com>

On Thu, 6 Mar 2025 at 07:17, Jacky Bai <ping.bai at nxp.com> wrote:
>
> for_each_possible_cpu() is currently used to initialize cpuidle
> in the PSCI cpuidle driver.
>
> However, in cpu_dev_register_generic(), for_each_present_cpu()
> is used to register CPU devices which means the CPU devices are
> only registered for present CPUs and not all possible CPUs.
>
> With nosmp or maxcpus=0, only the boot CPU is present, leading
> to the failure:
>
>   |  Failed to register cpuidle device for cpu1
>
> Change for_each_possible_cpu() to for_each_present_cpu() in the
> PSCI cpuidle driver to ensure it only registers cpuidle devices
> for CPUs that are actually present.
>
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Reviewed-by: Dhruva Gole <d-gole at ti.com>
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>

Is this problem specific to cpuidle-psci?

Others are using for_each_possible_cpu() when registering their cpuidle drivers.

Kind regards
Uffe

> ---
>  - v2 changes:
>   - Improve the changelog as suggested by Sudeep
> ---
>  drivers/cpuidle/cpuidle-psci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 2562dc001fc1..00117e9b33e8 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -410,7 +410,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
>         struct cpuidle_driver *drv;
>         struct cpuidle_device *dev;
>
> -       for_each_possible_cpu(cpu) {
> +       for_each_present_cpu(cpu) {
>                 ret = psci_idle_init_cpu(&pdev->dev, cpu);
>                 if (ret)
>                         goto out_fail;
> --
> 2.34.1
>


From angelogioacchino.delregno at collabora.com  Thu Mar  6 02:53:53 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 6 Mar 2025 11:53:53 +0100
Subject: [PATCH v2] mailbox: mtk-cmdq: Refine GCE_GCTL_VALUE setting
In-Reply-To: <20250224105414.3576243-1-jason-jh.lin@mediatek.com>
References: <20250224105414.3576243-1-jason-jh.lin@mediatek.com>
Message-ID: <7af26747-34cd-4088-a6b5-865de9e87fba@collabora.com>

Il 24/02/25 11:50, Jason-JH Lin ha scritto:
> Add cmdq_gctl_value_toggle() to configure GCE_CTRL_BY_SW and GCE_DDR_EN
> together in the same GCE_GCTL_VALUE register.
> 
> For the SoCs whose GCE is located in MMINFRA and uses MMINFRA_AO power,
> this allows it to be written without enabling the clocks. Otherwise, all
> GCE registers should be written after the GCE clocks are enabled.
> Move this function into cmdq_runtime_resume() and cmdq_runtime_suspend()
> to ensure it is called when the GCE clock is enabled.
> 
> Fixes: 7abd037aa581 ("mailbox: mtk-cmdq: add gce ddr enable support flow")
> Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>

I have erroneously picked this patch in the MediaTek tree, as I had misread the
changed file, thought that it was mtk-cmdq-helper.c.

This patch also has the wrong recipients, as this should not go through the
MediaTek trees, but through the mailbox one.

Therefore, I dropped this patch from the MediaTek tree - sorry for the confusion.

Regards,
Angelo


From andre.draszik at linaro.org  Thu Mar  6 02:57:38 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 10:57:38 +0000
Subject: [PATCH 0/3] gs101 max77759 enablement (DT)
In-Reply-To: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
References: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
Message-ID: <b70f17589b91730ecf6080c626492368283ce7a1.camel@linaro.org>

On Thu, 2025-03-06 at 10:14 +0000, Andr? Draszik wrote:
> Hi,
> 
> This series enables the recently submitted Maxim max77759 driver and
> updates the DT for the Google Pixel 6 / Pro (oriole / raven) boards
> accordingly.
> 
> !!! Dependency note !!!
> 
> This series depends on the corresponding driver and DT bindings
> proposed in
> https://lore.kernel.org/r/20250228-max77759-mfd-v3-0-0c3627d42526 at linaro.org
> 
> Note that in that series bindings and gpio driver are accepted, but mfd
> and nvmem drivers are still waiting for review comments.

To avoid ambiguity... with 'accepted' I meant reviewed, but not merged!

A.



From msp at baylibre.com  Thu Mar  6 03:14:41 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:41 +0100
Subject: [PATCH v5 03/13] dt-bindings: can: m_can: Add wakeup properties
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-3-f9323d3744a2@baylibre.com>

The pins associated with m_can have to have a special configuration to
be able to wakeup the SoC from some system states. This configuration is
described in the wakeup pinctrl state while the default state describes
the default configuration.

Also m_can can be a wakeup-source if capable of wakeup.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 .../devicetree/bindings/net/can/bosch,m_can.yaml       | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
index c4887522e8fe97c3947357b4dbd4ecf20ee8100a..0c1f9fa7371897d45539ead49c9d290fb4966f30 100644
--- a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
+++ b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
@@ -106,6 +106,22 @@ properties:
         maximum: 32
     minItems: 1
 
+  pinctrl-0:
+    description: Default pinctrl state
+
+  pinctrl-1:
+    description: Wakeup pinctrl state
+
+  pinctrl-names:
+    description:
+      When present should contain at least "default" describing the default pin
+      states. The second state called "wakeup" describes the pins in their
+      wakeup configuration required to exit sleep states.
+    minItems: 1
+    items:
+      - const: default
+      - const: wakeup
+
   power-domains:
     description:
       Power domain provider node and an args specifier containing
@@ -122,6 +138,8 @@ properties:
     minItems: 1
     maxItems: 2
 
+  wakeup-source: true
+
 required:
   - compatible
   - reg

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:42 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:42 +0100
Subject: [PATCH v5 04/13] can: m_can: Map WoL to device_set_wakeup_enable
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-4-f9323d3744a2@baylibre.com>

In some devices the pins of the m_can module can act as a wakeup source.
This patch helps do that by connecting the PHY_WAKE WoL option to
device_set_wakeup_enable. By marking this device as being wakeup
enabled, this setting can be used by platform code to decide which
sleep or poweroff mode to use.

Also this prepares the driver for the next patch in which the pinctrl
settings are changed depending on the desired wakeup source.

Reviewed-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 drivers/net/can/m_can/m_can.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 884a6352c42b7bc372c55a6be19ca9fcb15d3d63..20f7533ad9e7735013ff000e6f3b11d016f8a09f 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -2222,6 +2222,36 @@ static int m_can_set_coalesce(struct net_device *dev,
 	return 0;
 }
 
+static void m_can_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct m_can_classdev *cdev = netdev_priv(dev);
+
+	wol->supported = device_can_wakeup(cdev->dev) ? WAKE_PHY : 0;
+	wol->wolopts = device_may_wakeup(cdev->dev) ? WAKE_PHY : 0;
+}
+
+static int m_can_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct m_can_classdev *cdev = netdev_priv(dev);
+	bool wol_enable = !!(wol->wolopts & WAKE_PHY);
+	int ret;
+
+	if (wol->wolopts & ~WAKE_PHY)
+		return -EINVAL;
+
+	if (wol_enable == device_may_wakeup(cdev->dev))
+		return 0;
+
+	ret = device_set_wakeup_enable(cdev->dev, wol_enable);
+	if (ret) {
+		netdev_err(cdev->net, "Failed to set wakeup enable %pE\n",
+			   ERR_PTR(ret));
+		return ret;
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops m_can_ethtool_ops_coalescing = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
 		ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |
@@ -2231,10 +2261,14 @@ static const struct ethtool_ops m_can_ethtool_ops_coalescing = {
 	.get_ts_info = ethtool_op_get_ts_info,
 	.get_coalesce = m_can_get_coalesce,
 	.set_coalesce = m_can_set_coalesce,
+	.get_wol = m_can_get_wol,
+	.set_wol = m_can_set_wol,
 };
 
 static const struct ethtool_ops m_can_ethtool_ops = {
 	.get_ts_info = ethtool_op_get_ts_info,
+	.get_wol = m_can_get_wol,
+	.set_wol = m_can_set_wol,
 };
 
 static int register_m_can_dev(struct m_can_classdev *cdev)
@@ -2361,6 +2395,9 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 		goto out;
 	}
 
+	if (dev->of_node && of_property_read_bool(dev->of_node, "wakeup-source"))
+		device_set_wakeup_capable(dev, true);
+
 	/* Get TX FIFO size
 	 * Defines the total amount of echo buffers for loopback
 	 */

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:43 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:43 +0100
Subject: [PATCH v5 05/13] can: m_can: Return ERR_PTR on error in allocation
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-5-f9323d3744a2@baylibre.com>

We have more detailed error values available, return them in the core
driver and the calling drivers to return proper errors to callers.

Reviewed-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 drivers/net/can/m_can/m_can.c          | 6 +++---
 drivers/net/can/m_can/m_can_pci.c      | 4 ++--
 drivers/net/can/m_can/m_can_platform.c | 4 ++--
 drivers/net/can/m_can/tcan4x5x-core.c  | 4 ++--
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 20f7533ad9e7735013ff000e6f3b11d016f8a09f..20fbef50db20ab5cea5afe4c44fda8b03e5c8c85 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -2392,7 +2392,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 					     sizeof(mram_config_vals) / 4);
 	if (ret) {
 		dev_err(dev, "Could not get Message RAM configuration.");
-		goto out;
+		return ERR_PTR(ret);
 	}
 
 	if (dev->of_node && of_property_read_bool(dev->of_node, "wakeup-source"))
@@ -2407,7 +2407,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 	net_dev = alloc_candev(sizeof_priv, tx_fifo_size);
 	if (!net_dev) {
 		dev_err(dev, "Failed to allocate CAN device");
-		goto out;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	class_dev = netdev_priv(net_dev);
@@ -2416,7 +2416,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 	SET_NETDEV_DEV(net_dev, dev);
 
 	m_can_of_parse_mram(class_dev, mram_config_vals);
-out:
+
 	return class_dev;
 }
 EXPORT_SYMBOL_GPL(m_can_class_allocate_dev);
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index 9ad7419f88f83016e93667f4847fe536eca39ad1..eb31ed1f964491ab41c7811be317706a09951390 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -111,8 +111,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
 
 	mcan_class = m_can_class_allocate_dev(&pci->dev,
 					      sizeof(struct m_can_pci_priv));
-	if (!mcan_class)
-		return -ENOMEM;
+	if (IS_ERR(mcan_class))
+		return PTR_ERR(mcan_class);
 
 	priv = cdev_to_priv(mcan_class);
 
diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
index b832566efda042929486578fad1879c7ad4a0cff..40bd10f71f0e2fab847c40c5bd5f7d85d3d46712 100644
--- a/drivers/net/can/m_can/m_can_platform.c
+++ b/drivers/net/can/m_can/m_can_platform.c
@@ -87,8 +87,8 @@ static int m_can_plat_probe(struct platform_device *pdev)
 
 	mcan_class = m_can_class_allocate_dev(&pdev->dev,
 					      sizeof(struct m_can_plat_priv));
-	if (!mcan_class)
-		return -ENOMEM;
+	if (IS_ERR(mcan_class))
+		return PTR_ERR(mcan_class);
 
 	priv = cdev_to_priv(mcan_class);
 
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
index e5c162f8c589b2c75c51cd8a994fc93ab507b9dc..5523ad8c9175cacd330a330b0f45d2c6515d11fa 100644
--- a/drivers/net/can/m_can/tcan4x5x-core.c
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
@@ -401,8 +401,8 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
 
 	mcan_class = m_can_class_allocate_dev(&spi->dev,
 					      sizeof(struct tcan4x5x_priv));
-	if (!mcan_class)
-		return -ENOMEM;
+	if (IS_ERR(mcan_class))
+		return PTR_ERR(mcan_class);
 
 	ret = m_can_check_mram_cfg(mcan_class, TCAN4X5X_MRAM_SIZE);
 	if (ret)

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:44 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:44 +0100
Subject: [PATCH v5 06/13] can: m_can: Support pinctrl wakeup state
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-6-f9323d3744a2@baylibre.com>

am62 requires a wakeup flag being set in pinctrl when mcan pins acts as
a wakeup source. Add support to select the wakeup state if WOL is
enabled.

Reviewed-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 drivers/net/can/m_can/m_can.c | 68 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/can/m_can/m_can.h |  4 +++
 2 files changed, 72 insertions(+)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 20fbef50db20ab5cea5afe4c44fda8b03e5c8c85..c1c5f8e90d37cde1daa8ab17c2be4b8be451dc50 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -2233,6 +2233,7 @@ static void m_can_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 static int m_can_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
+	struct pinctrl_state *new_pinctrl_state = NULL;
 	bool wol_enable = !!(wol->wolopts & WAKE_PHY);
 	int ret;
 
@@ -2249,7 +2250,28 @@ static int m_can_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 		return ret;
 	}
 
+	if (wol_enable)
+		new_pinctrl_state = cdev->pinctrl_state_wakeup;
+	else
+		new_pinctrl_state = cdev->pinctrl_state_default;
+
+	if (IS_ERR_OR_NULL(new_pinctrl_state))
+		return 0;
+
+	ret = pinctrl_select_state(cdev->pinctrl, new_pinctrl_state);
+	if (ret) {
+		netdev_err(cdev->net, "Failed to select pinctrl state %pE\n",
+			   ERR_PTR(ret));
+		goto err_wakeup_enable;
+	}
+
 	return 0;
+
+err_wakeup_enable:
+	/* Revert wakeup enable */
+	device_set_wakeup_enable(cdev->dev, !wol_enable);
+
+	return ret;
 }
 
 static const struct ethtool_ops m_can_ethtool_ops_coalescing = {
@@ -2377,6 +2399,44 @@ int m_can_class_get_clocks(struct m_can_classdev *cdev)
 }
 EXPORT_SYMBOL_GPL(m_can_class_get_clocks);
 
+static int m_can_class_setup_optional_pinctrl(struct m_can_classdev *class_dev)
+{
+	struct device *dev = class_dev->dev;
+	int ret;
+
+	class_dev->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(class_dev->pinctrl)) {
+		ret = PTR_ERR(class_dev->pinctrl);
+		class_dev->pinctrl = NULL;
+
+		if (ret == -ENODEV)
+			return 0;
+
+		return dev_err_probe(dev, ret, "Failed to get pinctrl\n");
+	}
+
+	class_dev->pinctrl_state_wakeup =
+		pinctrl_lookup_state(class_dev->pinctrl, "wakeup");
+	if (IS_ERR(class_dev->pinctrl_state_wakeup)) {
+		ret = PTR_ERR(class_dev->pinctrl_state_wakeup);
+		class_dev->pinctrl_state_wakeup = NULL;
+
+		if (ret == -ENODEV)
+			return 0;
+
+		return dev_err_probe(dev, ret, "Failed to lookup pinctrl wakeup state\n");
+	}
+
+	class_dev->pinctrl_state_default =
+		pinctrl_lookup_state(class_dev->pinctrl, "default");
+	if (IS_ERR(class_dev->pinctrl_state_default)) {
+		ret = PTR_ERR(class_dev->pinctrl_state_default);
+		return dev_err_probe(dev, ret, "Failed to lookup pinctrl default state\n");
+	}
+
+	return 0;
+}
+
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 						int sizeof_priv)
 {
@@ -2417,7 +2477,15 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
 
 	m_can_of_parse_mram(class_dev, mram_config_vals);
 
+	ret = m_can_class_setup_optional_pinctrl(class_dev);
+	if (ret)
+		goto err_free_candev;
+
 	return class_dev;
+
+err_free_candev:
+	free_candev(net_dev);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(m_can_class_allocate_dev);
 
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index bd4746c63af3f0a032910644dfd48a9ebb3a6168..353ad73649218dc0a03d9ba947c6abc847c958eb 100644
--- a/drivers/net/can/m_can/m_can.h
+++ b/drivers/net/can/m_can/m_can.h
@@ -128,6 +128,10 @@ struct m_can_classdev {
 	struct mram_cfg mcfg[MRAM_CFG_NUM];
 
 	struct hrtimer hrtimer;
+
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_state_default;
+	struct pinctrl_state *pinctrl_state_wakeup;
 };
 
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev, int sizeof_priv);

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:45 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:45 +0100
Subject: [PATCH v5 07/13] arm64: dts: ti: k3-pinctrl: Add WKUP_EN flag
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-7-f9323d3744a2@baylibre.com>

WKUP_EN is a flag to enable pin wakeup. Any activity will wakeup the SoC
in that case.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-pinctrl.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h
index cac7cccc111212eba520454396c8cc5c9fcba9b1..79a9f54fa0095c4e3864872bc06ef3d033215b2b 100644
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h
+++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h
@@ -18,6 +18,7 @@
 #define DS_OUT_VAL_SHIFT	(26)
 #define DS_PULLUD_EN_SHIFT	(27)
 #define DS_PULLTYPE_SEL_SHIFT	(28)
+#define WKUP_EN_SHIFT		(29)
 
 #define PULL_DISABLE		(1 << PULLUDEN_SHIFT)
 #define PULL_ENABLE		(0 << PULLUDEN_SHIFT)
@@ -56,6 +57,7 @@
 #define PIN_DS_PULLUD_DISABLE		(1 << DS_PULLUD_EN_SHIFT)
 #define PIN_DS_PULL_DOWN		(0 << DS_PULLTYPE_SEL_SHIFT)
 #define PIN_DS_PULL_UP			(1 << DS_PULLTYPE_SEL_SHIFT)
+#define WKUP_EN				(1 << WKUP_EN_SHIFT)
 
 /* Default mux configuration for gpio-ranges to use with pinctrl */
 #define PIN_GPIO_RANGE_IOPAD	(PIN_INPUT | 7)

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:46 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:46 +0100
Subject: [PATCH v5 08/13] arm64: dts: ti: k3-am62: Define possible system
 states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-8-f9323d3744a2@baylibre.com>

Add the system states that are available on am62 SoCs.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62.dtsi | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi
index bfb55ca113239be4367a1cf8edf219187fafa8a0..acc8cbc7e57bc5712ada8b4b225e302ffc368e26 100644
--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi
@@ -46,6 +46,28 @@ pmu: pmu {
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	system-idle-states {
+		system_partial_io: system-partial-io {
+			compatible = "system-idle-state";
+			idle-state-name = "Partial-IO";
+		};
+
+		system_deep_sleep: system-deep-sleep {
+			compatible = "system-idle-state";
+			idle-state-name = "DeepSleep";
+		};
+
+		system_mcu_only: system-mcu-only {
+			compatible = "system-idle-state";
+			idle-state-name = "MCU Only";
+		};
+
+		system_standby: system-standby {
+			compatible = "system-idle-state";
+			idle-state-name = "Standby";
+		};
+	};
+
 	cbass_main: bus at f0000 {
 		bootph-all;
 		compatible = "simple-bus";

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:47 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:47 +0100
Subject: [PATCH v5 09/13] arm64: dts: ti: k3-am62a: Define possible system
 states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-9-f9323d3744a2@baylibre.com>

Add the system states that are available on am62a SoCs.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62a.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62a.dtsi b/arch/arm64/boot/dts/ti/k3-am62a.dtsi
index 4d79b3e9486af18b8813a8980a57937669ff6095..0b58ade9561a3076fc89f3b85dbafa969285162f 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a.dtsi
@@ -46,6 +46,33 @@ pmu: pmu {
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	system-idle-states {
+		system_partial_io: system-partial-io {
+			compatible = "system-idle-state";
+			idle-state-name = "Partial-IO";
+		};
+
+		system_io_ddr: system-io-ddr {
+			compatible = "system-idle-state";
+			idle-state-name = "IO+DDR";
+		};
+
+		system_deep_sleep: system-deep-sleep {
+			compatible = "system-idle-state";
+			idle-state-name = "DeepSleep";
+		};
+
+		system_mcu_only: system-mcu-only {
+			compatible = "system-idle-state";
+			idle-state-name = "MCU Only";
+		};
+
+		system_standby: system-standby {
+			compatible = "system-idle-state";
+			idle-state-name = "Standby";
+		};
+	};
+
 	cbass_main: bus at f0000 {
 		compatible = "simple-bus";
 		#address-cells = <2>;

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:48 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:48 +0100
Subject: [PATCH v5 10/13] arm64: dts: ti: k3-am62p: Define possible system
 states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-10-f9323d3744a2@baylibre.com>

Add the system states that are available on am62p SoCs.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62p.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
index 75a15c368c11b068430362fe0b8d2d9ecc052588..64cd070f196fdd2999ddc7bfee3ac9a03f1366b4 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
@@ -44,6 +44,33 @@ pmu: pmu {
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	system-idle-states {
+		system_partial_io: system-partial-io {
+			compatible = "system-idle-state";
+			idle-state-name = "Partial-IO";
+		};
+
+		system_io_ddr: system-io-ddr {
+			compatible = "system-idle-state";
+			idle-state-name = "IO+DDR";
+		};
+
+		system_deep_sleep: system-deep-sleep {
+			compatible = "system-idle-state";
+			idle-state-name = "DeepSleep";
+		};
+
+		system_mcu_only: system-mcu-only {
+			compatible = "system-idle-state";
+			idle-state-name = "MCU Only";
+		};
+
+		system_standby: system-standby {
+			compatible = "system-idle-state";
+			idle-state-name = "Standby";
+		};
+	};
+
 	cbass_main: bus at f0000 {
 		compatible = "simple-bus";
 		#address-cells = <2>;

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:49 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:49 +0100
Subject: [PATCH v5 11/13] arm64: dts: ti: k3-am62-lp-sk: Set wakeup-source
 system-states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-11-f9323d3744a2@baylibre.com>

The CANUART pins of mcu_mcan0, mcu_mcan1, mcu_uart0 and wkup_uart0 are
powered during Partial-IO and IO+DDR and are capable of waking up the
system in these states. Specify the states in which these units can do a
wakeup on this board.

Note that the UARTs are not capable of wakeup in Partial-IO because of
of a UART mux on the board not being powered during Partial-IO. As
IO+DDR is not supported on am62, the UARTs are not added in this patch.

Add pincontrol definitions for mcu_mcan0 and mcu_mcan1 for wakeup from
Partial-IO. Add these as wakeup pinctrl entries for both devices.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts | 60 ++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
index 8e9fc00a6b3c7459a360f9e1d6bbb60e68c460ab..f19e53efabf30fc333e3a7d9832296140642fdf3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
@@ -232,3 +232,63 @@ &tlv320aic3106 {
 &gpmc0 {
 	ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
 };
+
+&mcu_mcan0 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_mcan1 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_pmx0 {
+	mcu_mcan0_tx_pins_default: mcu-mcan0-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_default: mcu-mcan0-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan1_tx_pins_default: mcu-mcan1-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x03c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_default: mcu-mcan1-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_wakeup: mcu-mcan1-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT | WKUP_EN, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+};

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:50 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:50 +0100
Subject: [PATCH v5 12/13] arm64: dts: ti: k3-am62a7-sk: Set wakeup-source
 system-states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-12-f9323d3744a2@baylibre.com>

The CANUART pins of mcu_mcan0, mcu_mcan1, mcu_uart0 and wkup_uart0 are
powered during Partial-IO and IO+DDR and are capable of waking up the
system in these states. Specify the states in which these units can do a
wakeup on this board.

Note that the UARTs are not capable of wakeup in Partial-IO because of
of a UART mux on the board not being powered during Partial-IO.

Add pincontrol definitions for mcu_mcan0 and mcu_mcan1 for wakeup from
Partial-IO. Add these as wakeup pinctrl entries for both devices.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 76 +++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index 1c9d95696c839a51b607839abb9429a8de6fa620..724d9a6f3c575fe35496fdd9e17d6d8e33869f92 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -741,3 +741,79 @@ dpi1_out: endpoint {
 		};
 	};
 };
+
+&mcu_mcan0 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_mcan1 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_uart0 {
+	wakeup-source = <&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+};
+
+&wkup_uart0 {
+	wakeup-source = <&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+};
+
+&mcu_pmx0 {
+	mcu_mcan0_tx_pins_default: mcu-mcan0-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_default: mcu-mcan0-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan1_tx_pins_default: mcu-mcan1-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x03c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_default: mcu-mcan1-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_wakeup: mcu-mcan1-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT | WKUP_EN, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+};

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:51 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:51 +0100
Subject: [PATCH v5 13/13] arm64: dts: ti: k3-am62p5-sk: Set wakeup-source
 system-states
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-13-f9323d3744a2@baylibre.com>

The CANUART pins of mcu_mcan0, mcu_mcan1, mcu_uart0 and wkup_uart0 are
powered during Partial-IO and IO+DDR and are capable of waking up the
system in these states. Specify the states in which these units can do a
wakeup on this board.

Note that the UARTs are not capable of wakeup in Partial-IO because of
of a UART mux on the board not being powered during Partial-IO.

Add pincontrol definitions for mcu_mcan0 and mcu_mcan1 for wakeup from
Partial-IO. Add these as wakeup pinctrl entries for both devices.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62p5-sk.dts | 76 +++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index d29f524600af017af607e2cb6122d3a581575ffc..35b950e444353c416e33344dfff42e2edeab3aba 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -683,3 +683,79 @@ &mcu_gpio0 {
 &mcu_gpio_intr {
 	status = "reserved";
 };
+
+&mcu_mcan0 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_mcan1 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_wakeup>;
+	wakeup-source = <&system_partial_io>,
+			<&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+	status = "okay";
+};
+
+&mcu_uart0 {
+	wakeup-source = <&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+};
+
+&wkup_uart0 {
+	wakeup-source = <&system_io_ddr>,
+			<&system_deep_sleep>,
+			<&system_mcu_only>,
+			<&system_standby>;
+};
+
+&mcu_pmx0 {
+	mcu_mcan0_tx_pins_default: mcu-mcan0-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_default: mcu-mcan0-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan1_tx_pins_default: mcu-mcan1-tx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x03c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_default: mcu-mcan1-rx-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_wakeup: mcu-mcan1-rx-wakeup-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT | WKUP_EN, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+};

-- 
2.47.2



From andre.draszik at linaro.org  Thu Mar  6 03:24:07 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 11:24:07 +0000
Subject: [PATCH v2 1/4] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-1-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
	 <20250301-pinctrl-fltcon-suspend-v2-1-a7eef9bb443b@linaro.org>
Message-ID: <4a200a7bf5f39034ce206a6c9240a307eadd45af.camel@linaro.org>

On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> On gs101 SoC the fltcon0 (filter configuration 0) offset
> isn't at a fixed offset like previous SoCs as the fltcon1
> register only exists when there are more than 4 pins in the
> bank.
> 
> Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
> macros that take an additional fltcon_offs variable.
> 
> This can then be used in suspend/resume callbacks to
> save and restore the fltcon0 and fltcon1 registers.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> Cc: stable at vger.kernel.org

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>



From msp at baylibre.com  Thu Mar  6 03:24:52 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 6 Mar 2025 12:24:52 +0100
Subject: [PATCH v5 00/13] firmware: ti_sci: Partial-IO support
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <kzmgga2d64ic5dxohu4jnmwqg4t5febclzh2mg5g57ygvfkwva@jniad5zhdwg7>

On Thu, Mar 06, 2025 at 12:14:38PM +0100, Markus Schneider-Pargmann wrote:
> Hi,
> 
> up to last series, the Partial-IO support consisted of two independent
> series. As this last rework introduced file-based conflicts, I merged
> the mcan series introducing wakeup support into this series:
> 
>   can: m_can: Add am62 wakeup support
>   https://lore.kernel.org/lkml/20241219-topic-mcan-wakeup-source-v6-12-v6-0-1356c7f7cfda at baylibre.com/
> 
> Series
> ------
> The series contains three parts:
>  - m_can support for Partial-IO, in particular 'wakeup' pinctrl support.
>  - ti_sci support for Partial-IO, which checks wakeup-sources if they
>    are enabled for Partial-IO
>  - DT description of system states on am62, am62a, am62p and the
>    enabling of wakeup support on the starter kits that support it.
> 
> The series is based on v6.14-rc1.

Small correction here, this is based on next-20250305.

Best
Markus

> 
> Partial-IO
> ----------
> Partial-IO is a low power system state in which nearly everything is
> turned off except the pins of the CANUART group. CANUART contains the
> mcu_mcan0, mcu_mcan1, wkup_uart0 and mcu_uart0 devices. These can
> trigger a wakeup of the system on pin activity. Note that this does not
> resume the system as the DDR is off as well. So this state can be
> considered a power-off state with wakeup capabilities.
> 
> The wakeup capability of a device is described in the devicetree with
> the wakeup-source property. This can hold phandles to system states in
> which the device is capable of wakeup. Additionally a WKUP_EN flag is
> set in the pinctrl of devices that are wakeup enabled.
> 
> On poweroff ti_sci checks if potential wakeup-sources for Partial-IO are
> wakeup-enabled by the user. If that is the case, the poweroff is done
> by TI_SCI by sending a PREPARE_SLEEP message with a specific mode. Once
> sent the system will poweroff apart from the CANUART pins.
> 
> Dependencies
> ------------
> This series requires an updated DT binding for the wakeup-source
> property that allows the use of system-states which are also being added
> in this pullrequest:
>  - dt-schema wakeup-source binding update
>    https://github.com/devicetree-org/dt-schema/pull/150
> 
> Testing
> -------
> After enabling Wake-on-LAN the system can be powered off and will enter
> the Partial-IO state in which it can be woken up by activity on the
> specific pins:
>     ethtool -s can0 wol p
>     ethtool -s can1 wol p
>     poweroff
> 
> These patches are tested on am62-lp-sk on linux-next.
> 
> Best,
> Markus
> 
> Previous versions "firmware: ti_sci: Partial-IO support":
>  v1: https://lore.kernel.org/lkml/20240523080225.1288617-1-msp at baylibre.com/
>  v2: https://lore.kernel.org/lkml/20240729080101.3859701-1-msp at baylibre.com/
>  v3: https://lore.kernel.org/r/20241012-topic-am62-partialio-v6-13-b4-v3-0-f7c6c2739681 at baylibre.com
>  v4: https://lore.kernel.org/r/20241219-topic-am62-partialio-v6-12-b4-v4-0-1cb8eabd407e at baylibre.com
> 
> Previous versions "can: m_can: Add am62 wakeup support":
>  v1: https://lore.kernel.org/lkml/20240523075347.1282395-1-msp at baylibre.com/
>  v2: https://lore.kernel.org/lkml/20240729074135.3850634-1-msp at baylibre.com/
>  v3: https://lore.kernel.org/lkml/20241011-topic-mcan-wakeup-source-v6-12-v3-0-9752c714ad12 at baylibre.com
>  v4: https://lore.kernel.org/r/20241015-topic-mcan-wakeup-source-v6-12-v4-0-fdac1d1e7aa6 at baylibre.com
>  v5: https://lore.kernel.org/r/20241028-topic-mcan-wakeup-source-v6-12-v5-0-33edc0aba629 at baylibre.com
>  v6: https://lore.kernel.org/r/20241219-topic-mcan-wakeup-source-v6-12-v6-0-1356c7f7cfda at baylibre.com
> 
> Changes in v5:
>  - Rebased to v6.14-rc1
>  - Merged m_can and ti_sci series to avoid conflicts and show
>    dependencies more easily
>  - Added definitions of system-states for am62/am62a/am62p
>  - Moved wakeup-source definitions into board dts files as they require
>    a bit of support on the board.
>  - Updated ti_sci support to walk through the wakeup-source phandle
>    lists
>  - Added pinctrl settings for mcu_mcan0/1 on all boards
>  - Minor style updates for ti_sci support for transfers without response
>  - Update and move the dt-binding for wakeup-source from the m_can
>    binding to the dt-schema repository
> 
> Changes in v4:
>  - Rebased to v6.13-rc1
>  - Removed all regulator related structures from patches and implemented
>    the wakeup-source property use instead.
> 
> Changes in v3:
>  - Remove other modes declared for PREPARE_SLEEP as they probably won't
>    ever be used in upstream.
>  - Replace the wait loop after sending PREPARE_SLEEP with msleep and do
>    an emergency_restart if it exits
>  - Remove uarts from DT wakeup sources
>  - Split no response handling in ti_sci_do_xfer() into a separate patch
>    and use goto instead of if ()
>  - Remove DT binding parital-io-wakeup-sources. Instead I am modeling
>    the devices that are in the relevant group that are powered during
>    Partial-IO with the power supplies that are externally provided to
>    the SoC. In this case they are provided through 'vddshv_canuart'. All
>    devices using this regulator can be considered a potential wakeup
>    source if they are wakeup capable and wakeup enabled.
>  - Added devicetree patches adding vcc_3v3_sys regulator and
>    vddshv_canuart for am62-lp-sk
>  - Add pinctrl entries for am62-lp-sk to add WKUP_EN for mcu_mcan0 and
>    mcu_mcan1
> 
> Changes in v2:
>  - Rebase to v6.11-rc1
>  - dt-binding:
>     - Update commit message
>     - Add more verbose description of the new binding for a better
>       explanation.
>  - ti_sci driver:
>     - Combine ti_sci_do_send() into ti_sci_do_xfer and only wait on a
>       response if a flag is set.
>     - On failure to enter Partial-IO, do emergency_restart()
>     - Add comments
>     - Fix small things
> 
> Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
> ---
> Markus Schneider-Pargmann (13):
>       firmware: ti_sci: Support transfers without response
>       firmware: ti_sci: Partial-IO support
>       dt-bindings: can: m_can: Add wakeup properties
>       can: m_can: Map WoL to device_set_wakeup_enable
>       can: m_can: Return ERR_PTR on error in allocation
>       can: m_can: Support pinctrl wakeup state
>       arm64: dts: ti: k3-pinctrl: Add WKUP_EN flag
>       arm64: dts: ti: k3-am62: Define possible system states
>       arm64: dts: ti: k3-am62a: Define possible system states
>       arm64: dts: ti: k3-am62p: Define possible system states
>       arm64: dts: ti: k3-am62-lp-sk: Set wakeup-source system-states
>       arm64: dts: ti: k3-am62a7-sk: Set wakeup-source system-states
>       arm64: dts: ti: k3-am62p5-sk: Set wakeup-source system-states
> 
>  .../devicetree/bindings/net/can/bosch,m_can.yaml   |  18 +++
>  arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts           |  60 +++++++++
>  arch/arm64/boot/dts/ti/k3-am62.dtsi                |  22 ++++
>  arch/arm64/boot/dts/ti/k3-am62a.dtsi               |  27 +++++
>  arch/arm64/boot/dts/ti/k3-am62a7-sk.dts            |  76 ++++++++++++
>  arch/arm64/boot/dts/ti/k3-am62p.dtsi               |  27 +++++
>  arch/arm64/boot/dts/ti/k3-am62p5-sk.dts            |  76 ++++++++++++
>  arch/arm64/boot/dts/ti/k3-pinctrl.h                |   2 +
>  drivers/firmware/ti_sci.c                          | 134 ++++++++++++++++++++-
>  drivers/firmware/ti_sci.h                          |   5 +
>  drivers/net/can/m_can/m_can.c                      | 111 ++++++++++++++++-
>  drivers/net/can/m_can/m_can.h                      |   4 +
>  drivers/net/can/m_can/m_can_pci.c                  |   4 +-
>  drivers/net/can/m_can/m_can_platform.c             |   4 +-
>  drivers/net/can/m_can/tcan4x5x-core.c              |   4 +-
>  15 files changed, 562 insertions(+), 12 deletions(-)
> ---
> base-commit: 7ec162622e66a4ff886f8f28712ea1b13069e1aa
> change-id: 20241008-topic-am62-partialio-v6-12-b4-c273fbac4447
> 
> Best regards,
> -- 
> Markus Schneider-Pargmann <msp at baylibre.com>
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/34e09f82/attachment.sig>

From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:49 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:49 +0100
Subject: [PATCH v10 00/18] Support spread spectrum clocking for i.MX8M PLLs
Message-ID: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>

This version keeps the version v9 patches that can be merged and
removes the patches that will need to be modified in case Peng's
PR https://github.com/devicetree-org/dt-schema/pull/154 is accepted.
The idea is to speed up the merging of the patches in the series
that have already been reviewed and are not dependent on the
introduction of the assigned-clocks-sscs property, and postpone
the patches for spread spectrum to a future series once it becomes
clear what needs to be done.

Specifically, the patches:

01/18 dt-bindings: clock: imx8mm: add VIDEO_PLL clocks
02/18 clk: imx8mm: rename video_pll1 to video_pll
03/18 dt-bindings: clock: imx8mp: add VIDEO_PLL clocks
04/18 clk: imx8mp: rename video_pll1 to video_pll

are a replica for i.MX8MM and i.MX8MP of the patch for i.MX8MM
bedcf9d1dcf88 ("clk: imx: rename video_pll1 to video_pll"), which was
merged some time ago. The patches are split into four because, during
the review, Krzysztof asked me to separate the driver modifications
from the dt-bindings changes.

All the other patches in the series, from 5 to 18, are necessary for
the implementation of the anatop driver for i.MX8M{M,N,P}. The review of
this series has taken a long time, partly due to misunderstandings
arising from incorrect design choices.

As Peng stated in [1]:
"In current design, CCM is taken as producer of CLK_IMX8M_VIDEO_PLL, not consumer."

These patches fix this issue by ensuring that the PLLs are now produced by
Anatop and consumed by CCM, aligning with the hardware logic.

Finally, a clarification: I decided to keep the same title for the series
despite having removed all the patches for spread spectrum support in order
to maintain a clear connection with the previous versions.

[1] https://patchwork.kernel.org/project/linux-clk/patch/20241106090549.3684963-2-dario.binacchi at amarulasolutions.com/

Changes in v10:
- Drop the v9 patches:
  16/23 dt-bindings: clock: imx8m-clock: support spread spectrum clocking
  17/23 clk: imx: pll14xx: support spread spectrum clock generation
  17/23 clk: imx8mn: support spread spectrum clock generation
  21/23 clk: imx8mp: support spread spectrum clock generation
  23/23 clk: imx8mm: support spread spectrum clock generation

Changes in v9:
- Add 'Reviewed-by' tag of Peng Fan for imx8mn platform patches
- Fix building warning raised by the kernel test robot for patch
  v8, 11/18 clk: imx: add support for i.MX8MN anatop clock driver
- Add patches for imx8m{m,p} platforms:
  - 23/23 clk: imx8mm: support spread spectrum clock generation
  - 22/23 clk: imx: add support for i.MX8MM anatop clock driver
  - 21/23 clk: imx8mp: support spread spectrum clock generation
  - 20/23 clk: imx8mp: rename ccm_base to base
  - 19/23 clk: imx: add support for i.MX8MP anatop clock driver

Changes in v8:
- Drop the patches added in version 7:
  - 10/23 dt-bindings: clock: imx8m-clock: add phandle to the anatop
  - 11/23 arm64: dts: imx8mm: add phandle to anatop within CCM
  - 12/23 arm64: dts: imx8mn: add phandle to anatop within CCM
  - 13/23 arm64: dts: imx8mp: add phandle to anatop within CCM
  - 14/23 arm64: dts: imx8mq: add phandle to anatop within CCM

Changes in v7:
- Add and manage fsl,anatop property as phandle to the anatop node with
  the new patches:
  - 10/23 dt-bindings: clock: imx8m-clock: add phandle to the anatop
  - 11/23 arm64: dts: imx8mm: add phandle to anatop within CCM
  - 12/23 arm64: dts: imx8mn: add phandle to anatop within CCM
  - 13/23 arm64: dts: imx8mp: add phandle to anatop within CCM
  - 14/23 arm64: dts: imx8mq: add phandle to anatop within CCM

Changes in v6:
- Merge patches:
  10/20 dt-bindings: clock: imx8mm: add binding definitions for anatop
  11/20 dt-bindings: clock: imx8mn: add binding definitions for anatop
  12/20 dt-bindings: clock: imx8mp: add binding definitions for anatop
  to
  05/20 dt-bindings: clock: imx8m-anatop: define clocks/clock-names
  now renamed
  05/18 dt-bindings: clock: imx8m-anatop: add oscillators and PLLs
- Split the patch
  15/20 dt-bindings-clock-imx8m-clock-support-spread-spectru.patch
  into
  12/18 dt-bindings: clock: imx8m-clock: add PLLs
  16/18 dt-bindings: clock: imx8m-clock: support spread spectrum clocking

Changes in v5:
- Fix compilation errors.
- Separate driver code from dt-bindings

Changes in v4:
- Add dt-bindings for anatop
- Add anatop driver
- Drop fsl,ssc-clocks from spread spectrum dt-bindings

Changes in v3:
- Patches 1/8 has been added in version 3. The dt-bindings have
  been moved from fsl,imx8m-anatop.yaml to imx8m-clock.yaml. The
  anatop device (fsl,imx8m-anatop.yaml) is indeed more or less a
  syscon, so it represents a memory area accessible by ccm
  (imx8m-clock.yaml) to setup the PLLs.
- Patches {3,5}/8 have been added in version 3.
- Patches {4,6,8}/8 use ccm device node instead of the anatop one.

Changes in v2:
- Add "allOf:" and place it after "required:" block, like in the
  example schema.
- Move the properties definition to the top-level.
- Drop unit types as requested by the "make dt_binding_check" command.

Dario Binacchi (18):
  dt-bindings: clock: imx8mm: add VIDEO_PLL clocks
  clk: imx8mm: rename video_pll1 to video_pll
  dt-bindings: clock: imx8mp: add VIDEO_PLL clocks
  clk: imx8mp: rename video_pll1 to video_pll
  dt-bindings: clock: imx8m-anatop: add oscillators and PLLs
  arm64: dts: imx8mm: add anatop clocks
  arm64: dts: imx8mn: add anatop clocks
  arm64: dts: imx8mp: add anatop clocks
  arm64: dts: imx8mq: add anatop clocks
  clk: imx: add hw API imx_anatop_get_clk_hw
  clk: imx: add support for i.MX8MM anatop clock driver
  clk: imx: add support for i.MX8MN anatop clock driver
  clk: imx: add support for i.MX8MP anatop clock driver
  clk: imx8mp: rename ccm_base to base
  dt-bindings: clock: imx8m-clock: add PLLs
  arm64: dts: imx8mm: add PLLs to clock controller module (CCM)
  arm64: dts: imx8mn: add PLLs to clock controller module (CCM)
  arm64: dts: imx8mp: add PLLs to clock controller module (CCM)

 .../bindings/clock/fsl,imx8m-anatop.yaml      |  53 +-
 .../bindings/clock/imx8m-clock.yaml           |  27 +-
 arch/arm64/boot/dts/freescale/imx8mm.dtsi     |  11 +-
 arch/arm64/boot/dts/freescale/imx8mn.dtsi     |  11 +-
 arch/arm64/boot/dts/freescale/imx8mp.dtsi     |  11 +-
 arch/arm64/boot/dts/freescale/imx8mq.dtsi     |   2 +
 drivers/clk/imx/Makefile                      |   6 +-
 drivers/clk/imx/clk-imx8mm-anatop.c           | 287 ++++++++
 drivers/clk/imx/clk-imx8mm.c                  | 262 ++++---
 drivers/clk/imx/clk-imx8mn-anatop.c           | 283 ++++++++
 drivers/clk/imx/clk-imx8mn.c                  | 183 +++--
 drivers/clk/imx/clk-imx8mp-anatop.c           | 306 ++++++++
 drivers/clk/imx/clk-imx8mp.c                  | 672 +++++++++---------
 drivers/clk/imx/clk.c                         |  15 +
 drivers/clk/imx/clk.h                         |   2 +
 include/dt-bindings/clock/imx8mm-clock.h      |  76 +-
 include/dt-bindings/clock/imx8mn-clock.h      |  64 ++
 include/dt-bindings/clock/imx8mp-clock.h      |  80 ++-
 18 files changed, 1740 insertions(+), 611 deletions(-)
 create mode 100644 drivers/clk/imx/clk-imx8mm-anatop.c
 create mode 100644 drivers/clk/imx/clk-imx8mn-anatop.c
 create mode 100644 drivers/clk/imx/clk-imx8mp-anatop.c

-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:50 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:50 +0100
Subject: [PATCH v10 01/18] dt-bindings: clock: imx8mm: add VIDEO_PLL clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-2-dario.binacchi@amarulasolutions.com>

Unlike audio_pll1 and audio_pll2, there is no video_pll2. Further, the
name used in the RM is video_pll. So, let's add the IMX8MM_VIDEO_PLL[_*]
definitions to be consistent with the RM and avoid misunderstandings.

The IMX8MM_VIDEO_PLL1* constants have not been removed to ensure
backward compatibility of the patch.

No functional changes intended.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v6)

Changes in v6:
- Add 'Acked-by' tag of Krzysztof Kozlowski

Changes in v5:
- New

 include/dt-bindings/clock/imx8mm-clock.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h
index 1f768b2eeb1a..102d8a6cdb55 100644
--- a/include/dt-bindings/clock/imx8mm-clock.h
+++ b/include/dt-bindings/clock/imx8mm-clock.h
@@ -16,7 +16,8 @@
 #define IMX8MM_CLK_EXT4				7
 #define IMX8MM_AUDIO_PLL1_REF_SEL		8
 #define IMX8MM_AUDIO_PLL2_REF_SEL		9
-#define IMX8MM_VIDEO_PLL1_REF_SEL		10
+#define IMX8MM_VIDEO_PLL_REF_SEL		10
+#define IMX8MM_VIDEO_PLL1_REF_SEL		IMX8MM_VIDEO_PLL_REF_SEL
 #define IMX8MM_DRAM_PLL_REF_SEL			11
 #define IMX8MM_GPU_PLL_REF_SEL			12
 #define IMX8MM_VPU_PLL_REF_SEL			13
@@ -26,7 +27,8 @@
 #define IMX8MM_SYS_PLL3_REF_SEL			17
 #define IMX8MM_AUDIO_PLL1			18
 #define IMX8MM_AUDIO_PLL2			19
-#define IMX8MM_VIDEO_PLL1			20
+#define IMX8MM_VIDEO_PLL			20
+#define IMX8MM_VIDEO_PLL1			IMX8MM_VIDEO_PLL
 #define IMX8MM_DRAM_PLL				21
 #define IMX8MM_GPU_PLL				22
 #define IMX8MM_VPU_PLL				23
@@ -36,7 +38,8 @@
 #define IMX8MM_SYS_PLL3				27
 #define IMX8MM_AUDIO_PLL1_BYPASS		28
 #define IMX8MM_AUDIO_PLL2_BYPASS		29
-#define IMX8MM_VIDEO_PLL1_BYPASS		30
+#define IMX8MM_VIDEO_PLL_BYPASS			30
+#define IMX8MM_VIDEO_PLL1_BYPASS		IMX8MM_VIDEO_PLL_BYPASS
 #define IMX8MM_DRAM_PLL_BYPASS			31
 #define IMX8MM_GPU_PLL_BYPASS			32
 #define IMX8MM_VPU_PLL_BYPASS			33
@@ -46,7 +49,8 @@
 #define IMX8MM_SYS_PLL3_BYPASS			37
 #define IMX8MM_AUDIO_PLL1_OUT			38
 #define IMX8MM_AUDIO_PLL2_OUT			39
-#define IMX8MM_VIDEO_PLL1_OUT			40
+#define IMX8MM_VIDEO_PLL_OUT			40
+#define IMX8MM_VIDEO_PLL1_OUT			IMX8MM_VIDEO_PLL_OUT
 #define IMX8MM_DRAM_PLL_OUT			41
 #define IMX8MM_GPU_PLL_OUT			42
 #define IMX8MM_VPU_PLL_OUT			43
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:51 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:51 +0100
Subject: [PATCH v10 02/18] clk: imx8mm: rename video_pll1 to video_pll
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-3-dario.binacchi@amarulasolutions.com>

Unlike audio_pll1 and audio_pll2, there is no video_pll2. Further, the
name used in the RM is video_pll. So, let's rename "video_pll1" to
"video_pll" to be consistent with the RM and avoid misunderstandings.

No functional changes intended.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>

---
The patch, which simply replaces video_pll1 with video_pll, highlights
many warnings raised by checkpatch.pl. These are not generated by the
changes made but are inherited from how the module was originally
written. Fixing them would have meant "obscuring" the actual changes
introduced.

(no changes since v7)

Changes in v7:
- Add 'Reviewed-by' tag of Peng Fan

Changes in v5:
- Split the patch dropping the dt-bindings changes.

Changes in v4:
- New

 drivers/clk/imx/clk-imx8mm.c | 102 +++++++++++++++++------------------
 1 file changed, 51 insertions(+), 51 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 342049b847b9..8a1fc7e17ba2 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -28,7 +28,7 @@ static u32 share_count_nand;
 static const char *pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
 static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
 static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char *video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
 static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
 static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
 static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
@@ -42,22 +42,22 @@ static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m
 static const char * const imx8mm_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
 
 static const char *imx8mm_m4_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "sys_pll1_266m",
-				       "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+				       "sys_pll1_800m", "audio_pll1_out", "video_pll_out", "sys_pll3_out", };
 
 static const char *imx8mm_vpu_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
 					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "vpu_pll_out", };
 
 static const char *imx8mm_gpu3d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
-					  "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+					  "sys_pll2_1000m", "audio_pll1_out", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_gpu2d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
-					  "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+					  "sys_pll2_1000m", "audio_pll1_out", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m", "sys_pll2_250m",
-					     "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "sys_pll1_100m",};
+					     "sys_pll2_1000m", "audio_pll1_out", "video_pll_out", "sys_pll1_100m",};
 
 static const char *imx8mm_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
-					     "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+					     "sys_pll2_200m", "audio_pll1_out", "video_pll_out", "sys_pll3_out", };
 
 static const char *imx8mm_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
 					       "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
@@ -72,28 +72,28 @@ static const char *imx8mm_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pl
 					     "sys_pll1_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", };
 
 static const char *imx8mm_disp_rtrm_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll2_200m", "sys_pll2_1000m",
-					      "audio_pll1_out", "video_pll1_out", "clk_ext2", "clk_ext3", };
+					      "audio_pll1_out", "video_pll_out", "clk_ext2", "clk_ext3", };
 
 static const char *imx8mm_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_100m",
 					    "sys_pll2_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", };
 
 static const char *imx8mm_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
-					    "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+					    "audio_pll1_out", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
-					    "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+					    "audio_pll1_out", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_1000m", "sys_pll2_500m",
-					"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+					"audio_pll1_out", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_noc_apb_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll3_out", "sys_pll2_333m", "sys_pll2_200m",
-					    "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", };
+					    "sys_pll1_800m", "audio_pll1_out", "video_pll_out", };
 
 static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
-					"sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+					"sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll_out", };
 
 static const char *imx8mm_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_1000m",
-					      "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+					      "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll_out", };
 
 static const char *imx8mm_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m", "sys_pll2_500m",
 					     "sys_pll2_1000m", "sys_pll3_out", "audio_pll1_out", "sys_pll1_266m", };
@@ -108,10 +108,10 @@ static const char *imx8mm_vpu_g2_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_8
 					   "sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
 
 static const char *imx8mm_disp_dtrc_sels[] = {"osc_24m", "dummy", "sys_pll1_800m", "sys_pll2_1000m",
-					      "sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+					      "sys_pll1_160m", "video_pll_out", "sys_pll3_out", "audio_pll2_out", };
 
 static const char *imx8mm_disp_dc8000_sels[] = {"osc_24m", "dummy", "sys_pll1_800m", "sys_pll2_1000m",
-						"sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+						"sys_pll1_160m", "video_pll_out", "sys_pll3_out", "audio_pll2_out", };
 
 static const char *imx8mm_pcie1_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
 					       "sys_pll1_800m", "sys_pll2_500m", "sys_pll2_333m", "sys_pll3_out", };
@@ -122,47 +122,47 @@ static const char *imx8mm_pcie1_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_p
 static const char *imx8mm_pcie1_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m", "sys_pll3_out",
 					      "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_160m", "sys_pll1_200m", };
 
-static const char *imx8mm_dc_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+static const char *imx8mm_dc_pixel_sels[] = {"osc_24m", "video_pll_out", "audio_pll2_out", "audio_pll1_out",
 					     "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
 
-static const char *imx8mm_lcdif_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+static const char *imx8mm_lcdif_pixel_sels[] = {"osc_24m", "video_pll_out", "audio_pll2_out", "audio_pll1_out",
 						"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
 
-static const char *imx8mm_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
 
-static const char *imx8mm_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mm_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
 
-static const char *imx8mm_sai4_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai4_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
 
-static const char *imx8mm_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mm_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					 "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
 
-static const char *imx8mm_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					   "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mm_spdif2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char *imx8mm_spdif2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					   "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
 
 static const char *imx8mm_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", "sys_pll2_100m",
-					     "sys_pll1_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4", };
+					     "sys_pll1_160m", "audio_pll1_out", "video_pll_out", "clk_ext4", };
 
 static const char *imx8mm_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", "clk_ext1", "clk_ext2",
-					       "clk_ext3", "clk_ext4", "video_pll1_out", };
+					       "clk_ext3", "clk_ext4", "video_pll_out", };
 
 static const char *imx8mm_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", "sys_pll2_200m",
-					     "sys_pll2_500m", "video_pll1_out", "audio_pll2_out", };
+					     "sys_pll2_500m", "video_pll_out", "audio_pll2_out", };
 
 static const char *imx8mm_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", "sys_pll1_400m",
-					 "audio_pll2_out", "sys_pll3_out", "sys_pll2_250m", "video_pll1_out", };
+					 "audio_pll2_out", "sys_pll3_out", "sys_pll2_250m", "video_pll_out", };
 
 static const char *imx8mm_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m", "sys_pll2_500m",
 					 "audio_pll2_out", "sys_pll1_266m", "sys_pll3_out", "sys_pll1_100m", };
@@ -174,16 +174,16 @@ static const char *imx8mm_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1
 					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
 
 static const char *imx8mm_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
-					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+					 "video_pll_out", "audio_pll2_out", "sys_pll1_133m", };
 
 static const char *imx8mm_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
-					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+					 "video_pll_out", "audio_pll2_out", "sys_pll1_133m", };
 
 static const char *imx8mm_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
-					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+					 "video_pll_out", "audio_pll2_out", "sys_pll1_133m", };
 
 static const char *imx8mm_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
-					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+					 "video_pll_out", "audio_pll2_out", "sys_pll1_133m", };
 
 static const char *imx8mm_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
 					  "sys_pll3_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
@@ -213,19 +213,19 @@ static const char *imx8mm_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1
 					   "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
 
 static const char *imx8mm_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
-					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll_out", };
 
 static const char *imx8mm_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
-					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+					 "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll_out", };
 
 static const char *imx8mm_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
-					 "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+					 "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll_out", };
 
 static const char *imx8mm_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
-					 "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+					 "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll_out", };
 
 static const char *imx8mm_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", "sys_pll1_40m",
-					 "video_pll1_out", "sys_pll1_80m", "audio_pll1_out", "clk_ext1" };
+					 "video_pll_out", "sys_pll1_80m", "audio_pll1_out", "clk_ext1" };
 
 static const char *imx8mm_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
 					 "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
@@ -234,31 +234,31 @@ static const char *imx8mm_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_ou
 					  "sys_pll1_266m", "sys_pll2_500m", "sys_pll1_100m", };
 
 static const char *imx8mm_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
-					     "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+					     "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m", "sys_pll1_800m",
-					    "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+					    "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m", "sys_pll1_800m",
-					    "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+					    "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
 					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
 
 static const char *imx8mm_csi1_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
-					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
-					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_csi1_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
 					     "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
 
 static const char *imx8mm_csi2_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
-					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+					      "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
-					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+					     "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll_out", };
 
 static const char *imx8mm_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
 					     "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
@@ -286,9 +286,9 @@ static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }
 static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", "sys_pll1_200m",
 					  "audio_pll2_out", "sys_pll2_500m", "vpu_pll", "sys_pll1_80m", };
 static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", "sys_pll2_166m",
-					  "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "osc_32k", };
+					  "sys_pll3_out", "audio_pll1_out", "video_pll_out", "osc_32k", };
 
-static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
 					   "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
 					   "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
 					   "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
@@ -327,7 +327,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MM_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MM_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MM_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
@@ -336,7 +336,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MM_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll);
 	hws[IMX8MM_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll);
-	hws[IMX8MM_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx_1443x_pll);
+	hws[IMX8MM_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", base + 0x28, &imx_1443x_pll);
 	hws[IMX8MM_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll);
 	hws[IMX8MM_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll);
 	hws[IMX8MM_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll);
@@ -348,7 +348,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 	/* PLL bypass out */
 	hws[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	hws[IMX8MM_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MM_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MM_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
@@ -358,7 +358,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 	/* PLL out gate */
 	hws[IMX8MM_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
 	hws[IMX8MM_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
-	hws[IMX8MM_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
+	hws[IMX8MM_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", base + 0x28, 13);
 	hws[IMX8MM_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
 	hws[IMX8MM_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
 	hws[IMX8MM_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11);
-- 
2.43.0



From vdonnefort at google.com  Thu Mar  6 03:00:29 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:29 +0000
Subject: [PATCH v2 0/9] Stage-2 huge mappings for pKVM np-guests
Message-ID: <20250306110038.3733649-1-vdonnefort@google.com>

Hi all,

This series adds support for stage-2 huge mappings (PMD_SIZE) to pKVM
np-guests, that is installing PMD-level mappings in the stage-2,
whenever the stage-1 is backed by either Hugetlbfs or THPs.

The last patch of that series is an optimization for CMOs using a shared
PMD_SIZE fixmap.

Changes since v1: https://lore.kernel.org/all/20250228102530.1229089-1-vdonnefort at google.com/

  - WARN_ON() on !PAGE_ALIGNED size for guest CMOs (Quentin)
  - check_range_allowed_memory() before accessing the Vmemmap (Quentin)

Quentin Perret (2):
  KVM: arm64: Convert pkvm_mappings to interval tree
  KVM: arm64: Add a range to pkvm_mappings

Vincent Donnefort (7):
  KVM: arm64: Handle huge mappings for np-guest CMOs
  KVM: arm64: Add a range to __pkvm_host_share_guest()
  KVM: arm64: Add a range to __pkvm_host_unshare_guest()
  KVM: arm64: Add a range to __pkvm_host_wrprotect_guest()
  KVM: arm64: Add a range to __pkvm_host_test_clear_young_guest()
  KVM: arm64: Stage-2 huge mappings for np-guests
  KVM: arm64: np-guest CMOs with PMD_SIZE fixmap

 arch/arm64/include/asm/kvm_pgtable.h          |   7 +-
 arch/arm64/include/asm/kvm_pkvm.h             |   2 +
 arch/arm64/kvm/hyp/include/nvhe/mem_protect.h |   8 +-
 arch/arm64/kvm/hyp/include/nvhe/mm.h          |   4 +-
 arch/arm64/kvm/hyp/nvhe/hyp-main.c            |  16 +-
 arch/arm64/kvm/hyp/nvhe/mem_protect.c         | 236 +++++++++++++-----
 arch/arm64/kvm/hyp/nvhe/mm.c                  |  86 ++++++-
 arch/arm64/kvm/hyp/nvhe/setup.c               |   2 +-
 arch/arm64/kvm/hyp/pgtable.c                  |   6 -
 arch/arm64/kvm/mmu.c                          |   5 +-
 arch/arm64/kvm/pkvm.c                         | 129 +++++-----
 11 files changed, 342 insertions(+), 159 deletions(-)


base-commit: d082ecbc71e9e0bf49883ee4afd435a77a5101b6
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:30 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:30 +0000
Subject: [PATCH v2 1/9] KVM: arm64: Handle huge mappings for np-guest CMOs
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-2-vdonnefort@google.com>

clean_dcache_guest_page() and invalidate_icache_guest_page() accept a
size as an argument. But they also rely on fixmap, which can only map a
single PAGE_SIZE page.

With the upcoming stage-2 huge mappings for pKVM np-guests, those
callbacks will get size > PAGE_SIZE. Loop the CMOs on PAGE_SIZE basis
until the whole range is done.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 19c3c631708c..63968c7740c3 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -219,14 +219,30 @@ static void guest_s2_put_page(void *addr)
 
 static void clean_dcache_guest_page(void *va, size_t size)
 {
-	__clean_dcache_guest_page(hyp_fixmap_map(__hyp_pa(va)), size);
-	hyp_fixmap_unmap();
+	if (WARN_ON(!PAGE_ALIGNED(size)))
+		return;
+
+	while (size) {
+		__clean_dcache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
+					  PAGE_SIZE);
+		hyp_fixmap_unmap();
+		va += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
 }
 
 static void invalidate_icache_guest_page(void *va, size_t size)
 {
-	__invalidate_icache_guest_page(hyp_fixmap_map(__hyp_pa(va)), size);
-	hyp_fixmap_unmap();
+	if (WARN_ON(!PAGE_ALIGNED(size)))
+		return;
+
+	while (size) {
+		__invalidate_icache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
+					       PAGE_SIZE);
+		hyp_fixmap_unmap();
+		va += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
 }
 
 int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:31 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:31 +0000
Subject: [PATCH v2 2/9] KVM: arm64: Add a range to __pkvm_host_share_guest()
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-3-vdonnefort@google.com>

In preparation for supporting stage-2 huge mappings for np-guest. Add a
nr_pages argument to the __pkvm_host_share_guest hypercall. This range
supports only two values: 1 or PMD_SIZE / PAGE_SIZE (that is 512 on a
4K-pages system).

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 978f38c386ee..1abbab5e2ff8 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -39,7 +39,7 @@ int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages);
 int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
 int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
 int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages);
-int __pkvm_host_share_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu,
+int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
 			    enum kvm_pgtable_prot prot);
 int __pkvm_host_unshare_guest(u64 gfn, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 2c37680d954c..e71601746935 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -249,7 +249,8 @@ static void handle___pkvm_host_share_guest(struct kvm_cpu_context *host_ctxt)
 {
 	DECLARE_REG(u64, pfn, host_ctxt, 1);
 	DECLARE_REG(u64, gfn, host_ctxt, 2);
-	DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3);
+	DECLARE_REG(u64, nr_pages, host_ctxt, 3);
+	DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 4);
 	struct pkvm_hyp_vcpu *hyp_vcpu;
 	int ret = -EINVAL;
 
@@ -264,7 +265,7 @@ static void handle___pkvm_host_share_guest(struct kvm_cpu_context *host_ctxt)
 	if (ret)
 		goto out;
 
-	ret = __pkvm_host_share_guest(pfn, gfn, hyp_vcpu, prot);
+	ret = __pkvm_host_share_guest(pfn, gfn, nr_pages, hyp_vcpu, prot);
 out:
 	cpu_reg(host_ctxt, 1) =  ret;
 }
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 63968c7740c3..7e3a249149a0 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -60,6 +60,9 @@ static void hyp_unlock_component(void)
 	hyp_spin_unlock(&pkvm_pgd_lock);
 }
 
+#define for_each_hyp_page(start, size, page)	\
+	for (page = hyp_phys_to_page(start); page < hyp_phys_to_page((start) + (size)); page++)
+
 static void *host_s2_zalloc_pages_exact(size_t size)
 {
 	void *addr = hyp_alloc_pages(&host_s2_pool, get_order(size));
@@ -509,10 +512,25 @@ int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
 
 static void __host_update_page_state(phys_addr_t addr, u64 size, enum pkvm_page_state state)
 {
-	phys_addr_t end = addr + size;
+	struct hyp_page *page;
 
-	for (; addr < end; addr += PAGE_SIZE)
-		hyp_phys_to_page(addr)->host_state = state;
+	for_each_hyp_page(addr, size, page)
+		page->host_state = state;
+}
+
+static void __host_update_share_guest_count(u64 phys, u64 size, bool inc)
+{
+	struct hyp_page *page;
+
+	for_each_hyp_page(phys, size, page) {
+		if (inc) {
+			WARN_ON(page->host_share_guest_count++ == U32_MAX);
+		} else {
+			WARN_ON(!page->host_share_guest_count--);
+			if (!page->host_share_guest_count)
+				page->host_state = PKVM_PAGE_OWNED;
+		}
+	}
 }
 
 int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
@@ -627,16 +645,16 @@ static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size,
 static int __host_check_page_state_range(u64 addr, u64 size,
 					 enum pkvm_page_state state)
 {
-	u64 end = addr + size;
+	struct hyp_page *page;
 	int ret;
 
-	ret = check_range_allowed_memory(addr, end);
+	ret = check_range_allowed_memory(addr, addr + size);
 	if (ret)
 		return ret;
 
 	hyp_assert_lock_held(&host_mmu.lock);
-	for (; addr < end; addr += PAGE_SIZE) {
-		if (hyp_phys_to_page(addr)->host_state != state)
+	for_each_hyp_page(addr, size, page) {
+		if (page->host_state != state)
 			return -EPERM;
 	}
 
@@ -686,10 +704,9 @@ static enum pkvm_page_state guest_get_page_state(kvm_pte_t pte, u64 addr)
 	return pkvm_getstate(kvm_pgtable_stage2_pte_prot(pte));
 }
 
-static int __guest_check_page_state_range(struct pkvm_hyp_vcpu *vcpu, u64 addr,
+static int __guest_check_page_state_range(struct pkvm_hyp_vm *vm, u64 addr,
 					  u64 size, enum pkvm_page_state state)
 {
-	struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
 	struct check_walk_data d = {
 		.desired	= state,
 		.get_page_state	= guest_get_page_state,
@@ -896,49 +913,83 @@ int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages)
 	return ret;
 }
 
-int __pkvm_host_share_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu,
+static int __guest_check_transition_size(u64 phys, u64 ipa, u64 nr_pages, u64 *size)
+{
+	if (nr_pages == 1) {
+		*size = PAGE_SIZE;
+		return 0;
+	}
+
+	/* We solely support PMD_SIZE huge-pages */
+	if (nr_pages != (1 << (PMD_SHIFT - PAGE_SHIFT)))
+		return -EINVAL;
+
+	if (!IS_ALIGNED(phys | ipa, PMD_SIZE))
+		return -EINVAL;
+
+	*size = PMD_SIZE;
+	return 0;
+}
+
+int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
 			    enum kvm_pgtable_prot prot)
 {
 	struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
 	u64 phys = hyp_pfn_to_phys(pfn);
 	u64 ipa = hyp_pfn_to_phys(gfn);
+	enum pkvm_page_state state;
 	struct hyp_page *page;
+	u64 size;
 	int ret;
 
 	if (prot & ~KVM_PGTABLE_PROT_RWX)
 		return -EINVAL;
 
-	ret = check_range_allowed_memory(phys, phys + PAGE_SIZE);
+	ret = __guest_check_transition_size(phys, ipa, nr_pages, &size);
+	if (ret)
+		return ret;
+
+	ret = check_range_allowed_memory(phys, phys + size);
 	if (ret)
 		return ret;
 
 	host_lock_component();
 	guest_lock_component(vm);
 
-	ret = __guest_check_page_state_range(vcpu, ipa, PAGE_SIZE, PKVM_NOPAGE);
+	ret = __guest_check_page_state_range(vm, ipa, size, PKVM_NOPAGE);
 	if (ret)
 		goto unlock;
 
-	page = hyp_phys_to_page(phys);
-	switch (page->host_state) {
+	state = hyp_phys_to_page(phys)->host_state;
+	for_each_hyp_page(phys, size, page) {
+		if (page->host_state != state) {
+			ret = -EPERM;
+			goto unlock;
+		}
+	}
+
+	switch (state) {
 	case PKVM_PAGE_OWNED:
-		WARN_ON(__host_set_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_SHARED_OWNED));
+		WARN_ON(__host_set_page_state_range(phys, size, PKVM_PAGE_SHARED_OWNED));
 		break;
 	case PKVM_PAGE_SHARED_OWNED:
-		if (page->host_share_guest_count)
-			break;
-		/* Only host to np-guest multi-sharing is tolerated */
-		WARN_ON(1);
-		fallthrough;
+		for_each_hyp_page(phys, size, page) {
+			/* Only host to np-guest multi-sharing is tolerated */
+			if (WARN_ON(!page->host_share_guest_count)) {
+				ret = -EPERM;
+				goto unlock;
+			}
+		}
+		break;
 	default:
 		ret = -EPERM;
 		goto unlock;
 	}
 
-	WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, PAGE_SIZE, phys,
+	WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, size, phys,
 				       pkvm_mkstate(prot, PKVM_PAGE_SHARED_BORROWED),
 				       &vcpu->vcpu.arch.pkvm_memcache, 0));
-	page->host_share_guest_count++;
+	__host_update_share_guest_count(phys, size, true);
 
 unlock:
 	guest_unlock_component(vm);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..00fd9a524bf7 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -361,7 +361,7 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
 		return -EINVAL;
 
 	lockdep_assert_held_write(&kvm->mmu_lock);
-	ret = kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, prot);
+	ret = kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, 1, prot);
 	if (ret) {
 		/* Is the gfn already mapped due to a racing vCPU? */
 		if (ret == -EPERM)
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:32 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:32 +0000
Subject: [PATCH v2 3/9] KVM: arm64: Add a range to __pkvm_host_unshare_guest()
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-4-vdonnefort@google.com>

In preparation for supporting stage-2 huge mappings for np-guest. Add a
nr_pages argument to the __pkvm_host_unshare_guest hypercall. This range
supports only two values: 1 or PMD_SIZE / PAGE_SIZE (that is 512 on a
4K-pages system).

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 1abbab5e2ff8..343569e4bdeb 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -41,7 +41,7 @@ int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
 int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages);
 int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
 			    enum kvm_pgtable_prot prot);
-int __pkvm_host_unshare_guest(u64 gfn, struct pkvm_hyp_vm *hyp_vm);
+int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot);
 int __pkvm_host_wrprotect_guest(u64 gfn, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index e71601746935..7f22d104c1f1 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -274,6 +274,7 @@ static void handle___pkvm_host_unshare_guest(struct kvm_cpu_context *host_ctxt)
 {
 	DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1);
 	DECLARE_REG(u64, gfn, host_ctxt, 2);
+	DECLARE_REG(u64, nr_pages, host_ctxt, 3);
 	struct pkvm_hyp_vm *hyp_vm;
 	int ret = -EINVAL;
 
@@ -284,7 +285,7 @@ static void handle___pkvm_host_unshare_guest(struct kvm_cpu_context *host_ctxt)
 	if (!hyp_vm)
 		goto out;
 
-	ret = __pkvm_host_unshare_guest(gfn, hyp_vm);
+	ret = __pkvm_host_unshare_guest(gfn, nr_pages, hyp_vm);
 	put_pkvm_hyp_vm(hyp_vm);
 out:
 	cpu_reg(host_ctxt, 1) =  ret;
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 7e3a249149a0..7b9b112e3ebf 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -998,13 +998,12 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu
 	return ret;
 }
 
-static int __check_host_shared_guest(struct pkvm_hyp_vm *vm, u64 *__phys, u64 ipa)
+static int __check_host_shared_guest(struct pkvm_hyp_vm *vm, u64 *__phys, u64 ipa, u64 size)
 {
-	enum pkvm_page_state state;
 	struct hyp_page *page;
 	kvm_pte_t pte;
-	u64 phys;
 	s8 level;
+	u64 phys;
 	int ret;
 
 	ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
@@ -1012,51 +1011,52 @@ static int __check_host_shared_guest(struct pkvm_hyp_vm *vm, u64 *__phys, u64 ip
 		return ret;
 	if (!kvm_pte_valid(pte))
 		return -ENOENT;
-	if (level != KVM_PGTABLE_LAST_LEVEL)
+	if (kvm_granule_size(level) != size)
 		return -E2BIG;
 
-	state = guest_get_page_state(pte, ipa);
-	if (state != PKVM_PAGE_SHARED_BORROWED)
-		return -EPERM;
+	ret = __guest_check_page_state_range(vm, ipa, size, PKVM_PAGE_SHARED_BORROWED);
+	if (ret)
+		return ret;
 
 	phys = kvm_pte_to_phys(pte);
-	ret = check_range_allowed_memory(phys, phys + PAGE_SIZE);
+	ret = check_range_allowed_memory(phys, phys + size);
 	if (WARN_ON(ret))
 		return ret;
 
-	page = hyp_phys_to_page(phys);
-	if (page->host_state != PKVM_PAGE_SHARED_OWNED)
-		return -EPERM;
-	if (WARN_ON(!page->host_share_guest_count))
-		return -EINVAL;
+	for_each_hyp_page(phys, size, page) {
+		if (page->host_state != PKVM_PAGE_SHARED_OWNED)
+			return -EPERM;
+		if (WARN_ON(!page->host_share_guest_count))
+			return -EINVAL;
+	}
 
 	*__phys = phys;
 
 	return 0;
 }
 
-int __pkvm_host_unshare_guest(u64 gfn, struct pkvm_hyp_vm *vm)
+int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *vm)
 {
 	u64 ipa = hyp_pfn_to_phys(gfn);
-	struct hyp_page *page;
-	u64 phys;
+	u64 size, phys;
 	int ret;
 
+	ret = __guest_check_transition_size(0, ipa, nr_pages, &size);
+	if (ret)
+		return ret;
+
 	host_lock_component();
 	guest_lock_component(vm);
 
-	ret = __check_host_shared_guest(vm, &phys, ipa);
+	ret = __check_host_shared_guest(vm, &phys, ipa, size);
 	if (ret)
 		goto unlock;
 
-	ret = kvm_pgtable_stage2_unmap(&vm->pgt, ipa, PAGE_SIZE);
+	ret = kvm_pgtable_stage2_unmap(&vm->pgt, ipa, size);
 	if (ret)
 		goto unlock;
 
-	page = hyp_phys_to_page(phys);
-	page->host_share_guest_count--;
-	if (!page->host_share_guest_count)
-		WARN_ON(__host_set_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_OWNED));
+	__host_update_share_guest_count(phys, size, false);
 
 unlock:
 	guest_unlock_component(vm);
@@ -1076,7 +1076,7 @@ static void assert_host_shared_guest(struct pkvm_hyp_vm *vm, u64 ipa)
 	host_lock_component();
 	guest_lock_component(vm);
 
-	ret = __check_host_shared_guest(vm, &phys, ipa);
+	ret = __check_host_shared_guest(vm, &phys, ipa, PAGE_SIZE);
 
 	guest_unlock_component(vm);
 	host_unlock_component();
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 00fd9a524bf7..b65fcf245fc9 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -385,7 +385,7 @@ int pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
 
 	lockdep_assert_held_write(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
-		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn);
+		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn, 1);
 		if (WARN_ON(ret))
 			break;
 		rb_erase(&mapping->node, &pgt->pkvm_mappings);
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:33 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:33 +0000
Subject: [PATCH v2 4/9] KVM: arm64: Add a range to __pkvm_host_wrprotect_guest()
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-5-vdonnefort@google.com>

In preparation for supporting stage-2 huge mappings for np-guest. Add a
nr_pages argument to the __pkvm_host_wrprotect_guest hypercall. This
range supports only two values: 1 or PMD_SIZE / PAGE_SIZE (that is 512
on a 4K-pages system).

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 343569e4bdeb..ad6131033114 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -43,8 +43,8 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu
 			    enum kvm_pgtable_prot prot);
 int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot);
-int __pkvm_host_wrprotect_guest(u64 gfn, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm);
+int __pkvm_host_wrprotect_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu);
 
 bool addr_is_memory(phys_addr_t phys);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 7f22d104c1f1..e13771a67827 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -314,6 +314,7 @@ static void handle___pkvm_host_wrprotect_guest(struct kvm_cpu_context *host_ctxt
 {
 	DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1);
 	DECLARE_REG(u64, gfn, host_ctxt, 2);
+	DECLARE_REG(u64, nr_pages, host_ctxt, 3);
 	struct pkvm_hyp_vm *hyp_vm;
 	int ret = -EINVAL;
 
@@ -324,7 +325,7 @@ static void handle___pkvm_host_wrprotect_guest(struct kvm_cpu_context *host_ctxt
 	if (!hyp_vm)
 		goto out;
 
-	ret = __pkvm_host_wrprotect_guest(gfn, hyp_vm);
+	ret = __pkvm_host_wrprotect_guest(gfn, nr_pages, hyp_vm);
 	put_pkvm_hyp_vm(hyp_vm);
 out:
 	cpu_reg(host_ctxt, 1) = ret;
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 7b9b112e3ebf..e113ece1b759 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1065,7 +1065,7 @@ int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *vm)
 	return ret;
 }
 
-static void assert_host_shared_guest(struct pkvm_hyp_vm *vm, u64 ipa)
+static void assert_host_shared_guest(struct pkvm_hyp_vm *vm, u64 ipa, u64 size)
 {
 	u64 phys;
 	int ret;
@@ -1076,7 +1076,7 @@ static void assert_host_shared_guest(struct pkvm_hyp_vm *vm, u64 ipa)
 	host_lock_component();
 	guest_lock_component(vm);
 
-	ret = __check_host_shared_guest(vm, &phys, ipa, PAGE_SIZE);
+	ret = __check_host_shared_guest(vm, &phys, ipa, size);
 
 	guest_unlock_component(vm);
 	host_unlock_component();
@@ -1096,7 +1096,7 @@ int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_
 	if (prot & ~KVM_PGTABLE_PROT_RWX)
 		return -EINVAL;
 
-	assert_host_shared_guest(vm, ipa);
+	assert_host_shared_guest(vm, ipa, PAGE_SIZE);
 	guest_lock_component(vm);
 	ret = kvm_pgtable_stage2_relax_perms(&vm->pgt, ipa, prot, 0);
 	guest_unlock_component(vm);
@@ -1104,17 +1104,21 @@ int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_
 	return ret;
 }
 
-int __pkvm_host_wrprotect_guest(u64 gfn, struct pkvm_hyp_vm *vm)
+int __pkvm_host_wrprotect_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *vm)
 {
-	u64 ipa = hyp_pfn_to_phys(gfn);
+	u64 size, ipa = hyp_pfn_to_phys(gfn);
 	int ret;
 
 	if (pkvm_hyp_vm_is_protected(vm))
 		return -EPERM;
 
-	assert_host_shared_guest(vm, ipa);
+	ret = __guest_check_transition_size(0, ipa, nr_pages, &size);
+	if (ret)
+		return ret;
+
+	assert_host_shared_guest(vm, ipa, size);
 	guest_lock_component(vm);
-	ret = kvm_pgtable_stage2_wrprotect(&vm->pgt, ipa, PAGE_SIZE);
+	ret = kvm_pgtable_stage2_wrprotect(&vm->pgt, ipa, size);
 	guest_unlock_component(vm);
 
 	return ret;
@@ -1128,7 +1132,7 @@ int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *
 	if (pkvm_hyp_vm_is_protected(vm))
 		return -EPERM;
 
-	assert_host_shared_guest(vm, ipa);
+	assert_host_shared_guest(vm, ipa, PAGE_SIZE);
 	guest_lock_component(vm);
 	ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, PAGE_SIZE, mkold);
 	guest_unlock_component(vm);
@@ -1144,7 +1148,7 @@ int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu)
 	if (pkvm_hyp_vm_is_protected(vm))
 		return -EPERM;
 
-	assert_host_shared_guest(vm, ipa);
+	assert_host_shared_guest(vm, ipa, PAGE_SIZE);
 	guest_lock_component(vm);
 	kvm_pgtable_stage2_mkyoung(&vm->pgt, ipa, 0);
 	guest_unlock_component(vm);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index b65fcf245fc9..3ea92bb79e8c 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -404,7 +404,7 @@ int pkvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
 
 	lockdep_assert_held(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
-		ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn);
+		ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn, 1);
 		if (WARN_ON(ret))
 			break;
 	}
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:34 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:34 +0000
Subject: [PATCH v2 5/9] KVM: arm64: Add a range to __pkvm_host_test_clear_young_guest()
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-6-vdonnefort@google.com>

In preparation for supporting stage-2 huge mappings for np-guest. Add a
nr_pages argument to the __pkvm_host_test_clear_young_guest hypercall.
This range supports only two values: 1 or PMD_SIZE / PAGE_SIZE (that is
512 on a 4K-pages system).

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index ad6131033114..0c88c92fc3a2 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -43,8 +43,8 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu
 			    enum kvm_pgtable_prot prot);
 int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
 int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot);
-int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm);
 int __pkvm_host_wrprotect_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
+int __pkvm_host_test_clear_young_guest(u64 gfn, u64 nr_pages, bool mkold, struct pkvm_hyp_vm *vm);
 int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu);
 
 bool addr_is_memory(phys_addr_t phys);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index e13771a67827..a6353aacc36c 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -335,7 +335,8 @@ static void handle___pkvm_host_test_clear_young_guest(struct kvm_cpu_context *ho
 {
 	DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1);
 	DECLARE_REG(u64, gfn, host_ctxt, 2);
-	DECLARE_REG(bool, mkold, host_ctxt, 3);
+	DECLARE_REG(u64, nr_pages, host_ctxt, 3);
+	DECLARE_REG(bool, mkold, host_ctxt, 4);
 	struct pkvm_hyp_vm *hyp_vm;
 	int ret = -EINVAL;
 
@@ -346,7 +347,7 @@ static void handle___pkvm_host_test_clear_young_guest(struct kvm_cpu_context *ho
 	if (!hyp_vm)
 		goto out;
 
-	ret = __pkvm_host_test_clear_young_guest(gfn, mkold, hyp_vm);
+	ret = __pkvm_host_test_clear_young_guest(gfn, nr_pages, mkold, hyp_vm);
 	put_pkvm_hyp_vm(hyp_vm);
 out:
 	cpu_reg(host_ctxt, 1) = ret;
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index e113ece1b759..61bf26a911e6 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1124,17 +1124,21 @@ int __pkvm_host_wrprotect_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *vm)
 	return ret;
 }
 
-int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm)
+int __pkvm_host_test_clear_young_guest(u64 gfn, u64 nr_pages, bool mkold, struct pkvm_hyp_vm *vm)
 {
-	u64 ipa = hyp_pfn_to_phys(gfn);
+	u64 size, ipa = hyp_pfn_to_phys(gfn);
 	int ret;
 
 	if (pkvm_hyp_vm_is_protected(vm))
 		return -EPERM;
 
-	assert_host_shared_guest(vm, ipa, PAGE_SIZE);
+	ret = __guest_check_transition_size(0, ipa, nr_pages, &size);
+	if (ret)
+		return ret;
+
+	assert_host_shared_guest(vm, ipa, size);
 	guest_lock_component(vm);
-	ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, PAGE_SIZE, mkold);
+	ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, size, mkold);
 	guest_unlock_component(vm);
 
 	return ret;
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 3ea92bb79e8c..2eb1cc30124e 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -434,7 +434,7 @@ bool pkvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr, u64
 	lockdep_assert_held(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping)
 		young |= kvm_call_hyp_nvhe(__pkvm_host_test_clear_young_guest, handle, mapping->gfn,
-					   mkold);
+					   1, mkold);
 
 	return young;
 }
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:35 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:35 +0000
Subject: [PATCH v2 6/9] KVM: arm64: Convert pkvm_mappings to interval tree
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-7-vdonnefort@google.com>

From: Quentin Perret <qperret at google.com>

In preparation for supporting stage-2 huge mappings for np-guest, let's
convert pgt.pkvm_mappings to an interval tree.

No functional change intended.

Suggested-by: Vincent Donnefort <vdonnefort at google.com>
Signed-off-by: Quentin Perret <qperret at google.com>
Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 6b9d274052c7..1b43bcd2a679 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -413,7 +413,7 @@ static inline bool kvm_pgtable_walk_lock_held(void)
  */
 struct kvm_pgtable {
 	union {
-		struct rb_root					pkvm_mappings;
+		struct rb_root_cached				pkvm_mappings;
 		struct {
 			u32					ia_bits;
 			s8					start_level;
diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h
index eb65f12e81d9..f0d52efb858e 100644
--- a/arch/arm64/include/asm/kvm_pkvm.h
+++ b/arch/arm64/include/asm/kvm_pkvm.h
@@ -166,6 +166,7 @@ struct pkvm_mapping {
 	struct rb_node node;
 	u64 gfn;
 	u64 pfn;
+	u64 __subtree_last;	/* Internal member for interval tree */
 };
 
 int pkvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu,
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 2eb1cc30124e..da637c565ac9 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interval_tree_generic.h>
 #include <linux/kmemleak.h>
 #include <linux/kvm_host.h>
 #include <asm/kvm_mmu.h>
@@ -270,80 +271,63 @@ static int __init finalize_pkvm(void)
 }
 device_initcall_sync(finalize_pkvm);
 
-static int cmp_mappings(struct rb_node *node, const struct rb_node *parent)
+static u64 __pkvm_mapping_start(struct pkvm_mapping *m)
 {
-	struct pkvm_mapping *a = rb_entry(node, struct pkvm_mapping, node);
-	struct pkvm_mapping *b = rb_entry(parent, struct pkvm_mapping, node);
-
-	if (a->gfn < b->gfn)
-		return -1;
-	if (a->gfn > b->gfn)
-		return 1;
-	return 0;
+	return m->gfn * PAGE_SIZE;
 }
 
-static struct rb_node *find_first_mapping_node(struct rb_root *root, u64 gfn)
+static u64 __pkvm_mapping_end(struct pkvm_mapping *m)
 {
-	struct rb_node *node = root->rb_node, *prev = NULL;
-	struct pkvm_mapping *mapping;
-
-	while (node) {
-		mapping = rb_entry(node, struct pkvm_mapping, node);
-		if (mapping->gfn == gfn)
-			return node;
-		prev = node;
-		node = (gfn < mapping->gfn) ? node->rb_left : node->rb_right;
-	}
-
-	return prev;
+	return (m->gfn + 1) * PAGE_SIZE - 1;
 }
 
-/*
- * __tmp is updated to rb_next(__tmp) *before* entering the body of the loop to allow freeing
- * of __map inline.
- */
+INTERVAL_TREE_DEFINE(struct pkvm_mapping, node, u64, __subtree_last,
+		     __pkvm_mapping_start, __pkvm_mapping_end, static,
+		     pkvm_mapping);
+
 #define for_each_mapping_in_range_safe(__pgt, __start, __end, __map)				\
-	for (struct rb_node *__tmp = find_first_mapping_node(&(__pgt)->pkvm_mappings,		\
-							     ((__start) >> PAGE_SHIFT));	\
+	for (struct pkvm_mapping *__tmp = pkvm_mapping_iter_first(&(__pgt)->pkvm_mappings,	\
+								  __start, __end - 1);		\
 	     __tmp && ({									\
-				__map = rb_entry(__tmp, struct pkvm_mapping, node);		\
-				__tmp = rb_next(__tmp);						\
+				__map = __tmp;							\
+				__tmp = pkvm_mapping_iter_next(__map, __start, __end - 1);	\
 				true;								\
 		       });									\
-	    )											\
-		if (__map->gfn < ((__start) >> PAGE_SHIFT))					\
-			continue;								\
-		else if (__map->gfn >= ((__end) >> PAGE_SHIFT))					\
-			break;									\
-		else
+	    )
 
 int pkvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu,
 			     struct kvm_pgtable_mm_ops *mm_ops)
 {
-	pgt->pkvm_mappings	= RB_ROOT;
+	pgt->pkvm_mappings	= RB_ROOT_CACHED;
 	pgt->mmu		= mmu;
 
 	return 0;
 }
 
-void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
+static int __pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 start, u64 end)
 {
 	struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
 	pkvm_handle_t handle = kvm->arch.pkvm.handle;
 	struct pkvm_mapping *mapping;
-	struct rb_node *node;
+	int ret;
 
 	if (!handle)
-		return;
+		return 0;
 
-	node = rb_first(&pgt->pkvm_mappings);
-	while (node) {
-		mapping = rb_entry(node, struct pkvm_mapping, node);
-		kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn);
-		node = rb_next(node);
-		rb_erase(&mapping->node, &pgt->pkvm_mappings);
+	for_each_mapping_in_range_safe(pgt, start, end, mapping) {
+		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn, 1);
+		if (WARN_ON(ret))
+			return ret;
+		pkvm_mapping_remove(mapping, &pgt->pkvm_mappings);
 		kfree(mapping);
 	}
+
+	return 0;
+}
+
+void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
+{
+	__pkvm_pgtable_stage2_unmap(pgt, 0, ~(0ULL));
 }
 
 int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
@@ -371,28 +355,16 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
 	swap(mapping, cache->mapping);
 	mapping->gfn = gfn;
 	mapping->pfn = pfn;
-	WARN_ON(rb_find_add(&mapping->node, &pgt->pkvm_mappings, cmp_mappings));
+	pkvm_mapping_insert(mapping, &pgt->pkvm_mappings);
 
 	return ret;
 }
 
 int pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
 {
-	struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
-	pkvm_handle_t handle = kvm->arch.pkvm.handle;
-	struct pkvm_mapping *mapping;
-	int ret = 0;
+	lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(pgt->mmu)->mmu_lock);
 
-	lockdep_assert_held_write(&kvm->mmu_lock);
-	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
-		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn, 1);
-		if (WARN_ON(ret))
-			break;
-		rb_erase(&mapping->node, &pgt->pkvm_mappings);
-		kfree(mapping);
-	}
-
-	return ret;
+	return __pkvm_pgtable_stage2_unmap(pgt, addr, addr + size);
 }
 
 int pkvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:36 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:36 +0000
Subject: [PATCH v2 7/9] KVM: arm64: Add a range to pkvm_mappings
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-8-vdonnefort@google.com>

From: Quentin Perret <qperret at google.com>

In preparation for supporting stage-2 huge mappings for np-guest, add a
nr_pages member for pkvm_mappings to allow EL1 to track the size of the
stage-2 mapping.

Signed-off-by: Quentin Perret <qperret at google.com>
Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h
index f0d52efb858e..0e944a754b96 100644
--- a/arch/arm64/include/asm/kvm_pkvm.h
+++ b/arch/arm64/include/asm/kvm_pkvm.h
@@ -166,6 +166,7 @@ struct pkvm_mapping {
 	struct rb_node node;
 	u64 gfn;
 	u64 pfn;
+	u64 nr_pages;
 	u64 __subtree_last;	/* Internal member for interval tree */
 };
 
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index da637c565ac9..9c9833f27fe3 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -278,7 +278,7 @@ static u64 __pkvm_mapping_start(struct pkvm_mapping *m)
 
 static u64 __pkvm_mapping_end(struct pkvm_mapping *m)
 {
-	return (m->gfn + 1) * PAGE_SIZE - 1;
+	return (m->gfn + m->nr_pages) * PAGE_SIZE - 1;
 }
 
 INTERVAL_TREE_DEFINE(struct pkvm_mapping, node, u64, __subtree_last,
@@ -315,7 +315,8 @@ static int __pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 start, u64 e
 		return 0;
 
 	for_each_mapping_in_range_safe(pgt, start, end, mapping) {
-		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn, 1);
+		ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_guest, handle, mapping->gfn,
+					mapping->nr_pages);
 		if (WARN_ON(ret))
 			return ret;
 		pkvm_mapping_remove(mapping, &pgt->pkvm_mappings);
@@ -345,16 +346,32 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
 		return -EINVAL;
 
 	lockdep_assert_held_write(&kvm->mmu_lock);
-	ret = kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, 1, prot);
-	if (ret) {
-		/* Is the gfn already mapped due to a racing vCPU? */
-		if (ret == -EPERM)
+
+	/*
+	 * Calling stage2_map() on top of existing mappings is either happening because of a race
+	 * with another vCPU, or because we're changing between page and block mappings. As per
+	 * user_mem_abort(), same-size permission faults are handled in the relax_perms() path.
+	 */
+	mapping = pkvm_mapping_iter_first(&pgt->pkvm_mappings, addr, addr + size - 1);
+	if (mapping) {
+		if (size == (mapping->nr_pages * PAGE_SIZE))
 			return -EAGAIN;
+
+		/* Remove _any_ pkvm_mapping overlapping with the range, bigger or smaller. */
+		ret = __pkvm_pgtable_stage2_unmap(pgt, addr, addr + size);
+		if (ret)
+			return ret;
+		mapping = NULL;
 	}
 
+	ret = kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, size / PAGE_SIZE, prot);
+	if (WARN_ON(ret))
+		return ret;
+
 	swap(mapping, cache->mapping);
 	mapping->gfn = gfn;
 	mapping->pfn = pfn;
+	mapping->nr_pages = size / PAGE_SIZE;
 	pkvm_mapping_insert(mapping, &pgt->pkvm_mappings);
 
 	return ret;
@@ -376,7 +393,8 @@ int pkvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
 
 	lockdep_assert_held(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
-		ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn, 1);
+		ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn,
+					mapping->nr_pages);
 		if (WARN_ON(ret))
 			break;
 	}
@@ -391,7 +409,8 @@ int pkvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size)
 
 	lockdep_assert_held(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping)
-		__clean_dcache_guest_page(pfn_to_kaddr(mapping->pfn), PAGE_SIZE);
+		__clean_dcache_guest_page(pfn_to_kaddr(mapping->pfn),
+					  PAGE_SIZE * mapping->nr_pages);
 
 	return 0;
 }
@@ -406,7 +425,7 @@ bool pkvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr, u64
 	lockdep_assert_held(&kvm->mmu_lock);
 	for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping)
 		young |= kvm_call_hyp_nvhe(__pkvm_host_test_clear_young_guest, handle, mapping->gfn,
-					   1, mkold);
+					   mapping->nr_pages, mkold);
 
 	return young;
 }
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:37 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:37 +0000
Subject: [PATCH v2 8/9] KVM: arm64: Stage-2 huge mappings for np-guests
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-9-vdonnefort@google.com>

Now np-guests hypercalls with range are supported, we can let the
hypervisor to install block mappings whenever the Stage-1 allows it,
that is when backed by either Hugetlbfs or THPs. The size of those block
mappings is limited to PMD_SIZE.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 61bf26a911e6..b7a995a1d70b 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -167,7 +167,7 @@ int kvm_host_prepare_stage2(void *pgt_pool_base)
 static bool guest_stage2_force_pte_cb(u64 addr, u64 end,
 				      enum kvm_pgtable_prot prot)
 {
-	return true;
+	return false;
 }
 
 static void *guest_s2_zalloc_pages_exact(size_t size)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..3143f3b52c93 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1525,7 +1525,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * logging_active is guaranteed to never be true for VM_PFNMAP
 	 * memslots.
 	 */
-	if (logging_active || is_protected_kvm_enabled()) {
+	if (logging_active) {
 		force_pte = true;
 		vma_shift = PAGE_SHIFT;
 	} else {
@@ -1535,7 +1535,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	switch (vma_shift) {
 #ifndef __PAGETABLE_PMD_FOLDED
 	case PUD_SHIFT:
-		if (fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE))
+		if (is_protected_kvm_enabled() ||
+		    fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE))
 			break;
 		fallthrough;
 #endif
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 9c9833f27fe3..b40bcdb1814d 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -342,7 +342,7 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
 	u64 pfn = phys >> PAGE_SHIFT;
 	int ret;
 
-	if (size != PAGE_SIZE)
+	if (size != PAGE_SIZE && size != PMD_SIZE)
 		return -EINVAL;
 
 	lockdep_assert_held_write(&kvm->mmu_lock);
-- 
2.48.1.711.g2feabab25a-goog



From vdonnefort at google.com  Thu Mar  6 03:00:38 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu,  6 Mar 2025 11:00:38 +0000
Subject: [PATCH v2 9/9] KVM: arm64: np-guest CMOs with PMD_SIZE fixmap
In-Reply-To: <20250306110038.3733649-1-vdonnefort@google.com>
References: <20250306110038.3733649-1-vdonnefort@google.com>
Message-ID: <20250306110038.3733649-10-vdonnefort@google.com>

With the introduction of stage-2 huge mappings in the pKVM hypervisor,
guest pages CMO is needed for PMD_SIZE size. Fixmap only supports
PAGE_SIZE and iterating over the huge-page is time consuming (mostly due
to TLBI on hyp_fixmap_unmap) which is a problem for EL2 latency.

Introduce a shared PMD_SIZE fixmap (hyp_fixblock_map/hyp_fixblock_unmap)
to improve guest page CMOs when stage-2 huge mappings are installed.

On a Pixel6, the iterative solution resulted in a latency of ~700us,
while the PMD_SIZE fixmap reduces it to ~100us.

Because of the horrendous private range allocation that would be
necessary, this is disabled for 64KiB pages systems.

Suggested-by: Quentin Perret <qperret at google.com>
Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
Signed-off-by: Quentin Perret <qperret at google.com>

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 1b43bcd2a679..2888b5d03757 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -59,6 +59,11 @@ typedef u64 kvm_pte_t;
 
 #define KVM_PHYS_INVALID		(-1ULL)
 
+#define KVM_PTE_TYPE			BIT(1)
+#define KVM_PTE_TYPE_BLOCK		0
+#define KVM_PTE_TYPE_PAGE		1
+#define KVM_PTE_TYPE_TABLE		1
+
 #define KVM_PTE_LEAF_ATTR_LO		GENMASK(11, 2)
 
 #define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX	GENMASK(4, 2)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mm.h b/arch/arm64/kvm/hyp/include/nvhe/mm.h
index 230e4f2527de..b0c72bc2d5ba 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mm.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mm.h
@@ -13,9 +13,11 @@
 extern struct kvm_pgtable pkvm_pgtable;
 extern hyp_spinlock_t pkvm_pgd_lock;
 
-int hyp_create_pcpu_fixmap(void);
+int hyp_create_fixmap(void);
 void *hyp_fixmap_map(phys_addr_t phys);
 void hyp_fixmap_unmap(void);
+void *hyp_fixblock_map(phys_addr_t phys);
+void hyp_fixblock_unmap(void);
 
 int hyp_create_idmap(u32 hyp_va_bits);
 int hyp_map_vectors(void);
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index b7a995a1d70b..5710c97cafb0 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -220,17 +220,53 @@ static void guest_s2_put_page(void *addr)
 	hyp_put_page(&current_vm->pool, addr);
 }
 
+static void *__fixmap_guest_page(void *va, size_t *size)
+{
+	if (IS_ALIGNED(*size, PMD_SIZE)) {
+		void *addr = hyp_fixblock_map(__hyp_pa(va));
+
+		if (addr)
+			return addr;
+
+		*size = PAGE_SIZE;
+	}
+
+	if (IS_ALIGNED(*size, PAGE_SIZE))
+		return hyp_fixmap_map(__hyp_pa(va));
+
+	WARN_ON(1);
+
+	return NULL;
+}
+
+static void __fixunmap_guest_page(size_t size)
+{
+	switch (size) {
+	case PAGE_SIZE:
+		hyp_fixmap_unmap();
+		break;
+	case PMD_SIZE:
+		hyp_fixblock_unmap();
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+
 static void clean_dcache_guest_page(void *va, size_t size)
 {
 	if (WARN_ON(!PAGE_ALIGNED(size)))
 		return;
 
 	while (size) {
-		__clean_dcache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
-					  PAGE_SIZE);
-		hyp_fixmap_unmap();
-		va += PAGE_SIZE;
-		size -= PAGE_SIZE;
+		size_t fixmap_size = size == PMD_SIZE ? size : PAGE_SIZE;
+		void *addr = __fixmap_guest_page(va, &fixmap_size);
+
+		__clean_dcache_guest_page(addr, fixmap_size);
+		__fixunmap_guest_page(fixmap_size);
+
+		size -= fixmap_size;
+		va += fixmap_size;
 	}
 }
 
@@ -240,11 +276,14 @@ static void invalidate_icache_guest_page(void *va, size_t size)
 		return;
 
 	while (size) {
-		__invalidate_icache_guest_page(hyp_fixmap_map(__hyp_pa(va)),
-					       PAGE_SIZE);
-		hyp_fixmap_unmap();
-		va += PAGE_SIZE;
-		size -= PAGE_SIZE;
+		size_t fixmap_size = size == PMD_SIZE ? size : PAGE_SIZE;
+		void *addr = __fixmap_guest_page(va, &fixmap_size);
+
+		__invalidate_icache_guest_page(addr, fixmap_size);
+		__fixunmap_guest_page(fixmap_size);
+
+		size -= fixmap_size;
+		va += fixmap_size;
 	}
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c
index f41c7440b34b..e3b1bece8504 100644
--- a/arch/arm64/kvm/hyp/nvhe/mm.c
+++ b/arch/arm64/kvm/hyp/nvhe/mm.c
@@ -229,9 +229,8 @@ int hyp_map_vectors(void)
 	return 0;
 }
 
-void *hyp_fixmap_map(phys_addr_t phys)
+static void *fixmap_map_slot(struct hyp_fixmap_slot *slot, phys_addr_t phys)
 {
-	struct hyp_fixmap_slot *slot = this_cpu_ptr(&fixmap_slots);
 	kvm_pte_t pte, *ptep = slot->ptep;
 
 	pte = *ptep;
@@ -243,10 +242,21 @@ void *hyp_fixmap_map(phys_addr_t phys)
 	return (void *)slot->addr;
 }
 
+void *hyp_fixmap_map(phys_addr_t phys)
+{
+	return fixmap_map_slot(this_cpu_ptr(&fixmap_slots), phys);
+}
+
 static void fixmap_clear_slot(struct hyp_fixmap_slot *slot)
 {
 	kvm_pte_t *ptep = slot->ptep;
 	u64 addr = slot->addr;
+	u32 level;
+
+	if (FIELD_GET(KVM_PTE_TYPE, *ptep) == KVM_PTE_TYPE_PAGE)
+		level = KVM_PGTABLE_LAST_LEVEL;
+	else
+		level = KVM_PGTABLE_LAST_LEVEL - 1; /* create_fixblock() guarantees PMD level */
 
 	WRITE_ONCE(*ptep, *ptep & ~KVM_PTE_VALID);
 
@@ -260,7 +270,7 @@ static void fixmap_clear_slot(struct hyp_fixmap_slot *slot)
 	 * https://lore.kernel.org/kvm/20221017115209.2099-1-will at kernel.org/T/#mf10dfbaf1eaef9274c581b81c53758918c1d0f03
 	 */
 	dsb(ishst);
-	__tlbi_level(vale2is, __TLBI_VADDR(addr, 0), KVM_PGTABLE_LAST_LEVEL);
+	__tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level);
 	dsb(ish);
 	isb();
 }
@@ -273,9 +283,9 @@ void hyp_fixmap_unmap(void)
 static int __create_fixmap_slot_cb(const struct kvm_pgtable_visit_ctx *ctx,
 				   enum kvm_pgtable_walk_flags visit)
 {
-	struct hyp_fixmap_slot *slot = per_cpu_ptr(&fixmap_slots, (u64)ctx->arg);
+	struct hyp_fixmap_slot *slot = (struct hyp_fixmap_slot *)ctx->arg;
 
-	if (!kvm_pte_valid(ctx->old) || ctx->level != KVM_PGTABLE_LAST_LEVEL)
+	if (!kvm_pte_valid(ctx->old) || (ctx->end - ctx->start) != kvm_granule_size(ctx->level))
 		return -EINVAL;
 
 	slot->addr = ctx->addr;
@@ -296,13 +306,73 @@ static int create_fixmap_slot(u64 addr, u64 cpu)
 	struct kvm_pgtable_walker walker = {
 		.cb	= __create_fixmap_slot_cb,
 		.flags	= KVM_PGTABLE_WALK_LEAF,
-		.arg = (void *)cpu,
+		.arg = (void *)per_cpu_ptr(&fixmap_slots, cpu),
 	};
 
 	return kvm_pgtable_walk(&pkvm_pgtable, addr, PAGE_SIZE, &walker);
 }
 
-int hyp_create_pcpu_fixmap(void)
+#ifndef CONFIG_ARM64_64K_PAGES
+static struct hyp_fixmap_slot hyp_fixblock_slot;
+static DEFINE_HYP_SPINLOCK(hyp_fixblock_lock);
+
+void *hyp_fixblock_map(phys_addr_t phys)
+{
+	hyp_spin_lock(&hyp_fixblock_lock);
+	return fixmap_map_slot(&hyp_fixblock_slot, phys);
+}
+
+void hyp_fixblock_unmap(void)
+{
+	fixmap_clear_slot(&hyp_fixblock_slot);
+	hyp_spin_unlock(&hyp_fixblock_lock);
+}
+
+static int create_fixblock(void)
+{
+	struct kvm_pgtable_walker walker = {
+		.cb	= __create_fixmap_slot_cb,
+		.flags	= KVM_PGTABLE_WALK_LEAF,
+		.arg = (void *)&hyp_fixblock_slot,
+	};
+	unsigned long addr;
+	phys_addr_t phys;
+	int ret, i;
+
+	/* Find a RAM phys address, PMD aligned */
+	for (i = 0; i < hyp_memblock_nr; i++) {
+		phys = ALIGN(hyp_memory[i].base, PMD_SIZE);
+		if (phys + PMD_SIZE < (hyp_memory[i].base + hyp_memory[i].size))
+			break;
+	}
+
+	if (i >= hyp_memblock_nr)
+		return -EINVAL;
+
+	hyp_spin_lock(&pkvm_pgd_lock);
+	addr = ALIGN(__io_map_base, PMD_SIZE);
+	ret = __pkvm_alloc_private_va_range(addr, PMD_SIZE);
+	if (ret)
+		goto unlock;
+
+	ret = kvm_pgtable_hyp_map(&pkvm_pgtable, addr, PMD_SIZE, phys, PAGE_HYP);
+	if (ret)
+		goto unlock;
+
+	ret = kvm_pgtable_walk(&pkvm_pgtable, addr, PMD_SIZE, &walker);
+
+unlock:
+	hyp_spin_unlock(&pkvm_pgd_lock);
+
+	return ret;
+}
+#else
+void hyp_fixblock_unmap(void) { WARN_ON(1); }
+void *hyp_fixblock_map(phys_addr_t phys) { return NULL; }
+static int create_fixblock(void) { return 0; }
+#endif
+
+int hyp_create_fixmap(void)
 {
 	unsigned long addr, i;
 	int ret;
@@ -322,7 +392,7 @@ int hyp_create_pcpu_fixmap(void)
 			return ret;
 	}
 
-	return 0;
+	return create_fixblock();
 }
 
 int hyp_create_idmap(u32 hyp_va_bits)
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index d62bcb5634a2..fb69cf5e6ea8 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -295,7 +295,7 @@ void __noreturn __pkvm_init_finalise(void)
 	if (ret)
 		goto out;
 
-	ret = hyp_create_pcpu_fixmap();
+	ret = hyp_create_fixmap();
 	if (ret)
 		goto out;
 
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index df5cc74a7dd0..c351b4abd5db 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -11,12 +11,6 @@
 #include <asm/kvm_pgtable.h>
 #include <asm/stage2_pgtable.h>
 
-
-#define KVM_PTE_TYPE			BIT(1)
-#define KVM_PTE_TYPE_BLOCK		0
-#define KVM_PTE_TYPE_PAGE		1
-#define KVM_PTE_TYPE_TABLE		1
-
 struct kvm_pgtable_walk_data {
 	struct kvm_pgtable_walker	*walker;
 
-- 
2.48.1.711.g2feabab25a-goog



From Jason-JH.Lin at mediatek.com  Thu Mar  6 03:00:54 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Thu, 6 Mar 2025 11:00:54 +0000
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <9d383fc5-8c64-478c-8aab-6c56bf5b45be@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
	 <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
	 <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>
	 <9d383fc5-8c64-478c-8aab-6c56bf5b45be@collabora.com>
Message-ID: <0efe42427be4eb619b6ea7db18687b0211d1ec9f.camel@mediatek.com>

[snip]
> 
> > CPR_GSIZE is the setting for allocating the CPR SRAM size to each
> > VM.
> 
> Would be awesome if you could then clarify the comment that you have
> later in
> the code here, from...
> 
> /* config cpr size for host vm */
> 
> to
> 
> /* Set the amount of CPR SRAM to allocate to each VM */
> 
> ...that could be a way of more properly describing what the writel
> there is doing.
> 

OK, I'll change it.

> > 
> > > The GCE stuff isn't even properly described in datasheets - I do
> > > (probably!)
> > > understand what those are for, but asking people to get years of
> > > experience on
> > > MediaTek to understand what's going on would be a bit rude,
> > > wouldn't
> > > it? :-D
> > > 
> > 
> > I agree with you :-)
> > I'll put them in the VM patch and add some brief description for
> > them.
> > 
> 
> Thanks, much appreciated!
> 
> > > > +
> > > > ?? #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
> > > > ?? #define CMDQ_THR_ENABLED??????????? 0x1
> > > > ?? #define CMDQ_THR_DISABLED?????????? 0x0
> > > > @@ -87,11 +98,24 @@ struct cmdq {
> > > > ?? struct gce_plat {
> > > > ?????? u32 thread_nr;
> > > > ?????? u8 shift;
> > > > +???? dma_addr_t mminfra_offset;
> > > 
> > > It looks like this is exactly the DRAM's iostart... at least, I
> > > can
> > > see that in the
> > > downstream devicetree that's where it starts.
> > > 
> > > ???????? memory: memory at 80000000 {
> > > ???????????????? device_type = "memory";
> > > ???????????????? reg = <0 0x80000000 0 0x40000000>;
> > > ???????? };
> > > 
> > > It doesn't really look like being a coincidence, but, for the
> > > sake of
> > > asking:
> > > is this just a coincidence? :-)
> > > 
> > 
> > As the confirmation with the hardware designer in previous reply
> > mail
> > for CK:
> > https://patchwork.kernel.org/project/linux-mediatek/patch/20250218054405.2017918-4-jason-jh.lin at mediatek.com/*26258463
> > 
> 
> That explanation was simply wonderful.
> 
> > Since the MMINFRA remap subtracting 2G is done in the hardware
> > circuit
> > and cannot be configured by software, the address +2G adjustment is
> > necessary to implement in the CMDQ driver.
> > 
> > So that might not be a coincidence.
> > But even if DRAM start address changes, this mminfra_offset is
> > still
> > subtracting 2G, so I think it is a better choice to define it as
> > the
> > driver data for MT8196.
> > 
> 
> ....so, this makes me think the following:
> 
> 1. The DRAM start address cannot *ever* be less than 2G, because
> otherwise the
> ??? MMINFRA HW would have a hole in the usable address range;
> ??? 1a. If the start address changes to less than 2G, then also the
> IOMMU would
> ??????? get limitations, not only the mminfra..!
> ??? 2b. This makes it very very very unlikely for the start address
> to be changed
> ??????? to less than 0x80000000
> 
> 2. If the DRAM start address changes to be ABOVE 2G (so more than
> 0x80000000),
> ??? there would be no point for MMINFRA to start a "config path"
> write (or read)
> ??? in the SMMU DRAM block, would it? ;-)
> 

GCE is using IOMMU in MT8196, so all the address put into the GCE
instruction or GCE register for GCE access should be IOVA.

The DRAM start address is 2G(PA=0x80000000, IOVA=0x0) currently, so
when GCE want to access the IOVA=0x0, it will need to +2G into the
instruction, then the MMINFRA will see it as data path(IOVA > 2G) and
subtract 2G for that IOVA, so GCE can finally access the IOVA=0x0.

I'm not sure if I've misunderstood what you mean by ABOVE 2G. :-)
If DRAM start address is changed to 3G(PA=0xc0000000) the IOVA is still
0x0, so GCE still need to + 2G to make MMINFRA go to the data path.

But if you mean PA=0x80000000 and IOVA start address is 3G(0xc0000000),
then MMINFRA will go to the data path without GCE +2G.
However, MMINFRA will -2G when going to the data path and that will
cause GCE access the wrong IOVA.
So GCE still need to +2G no matter IOVA start address is already can
make MMINFRA go to the data path(IOVA > 2G).

We have already complained to our hardware designer that MMINFRA -2G
con not be changed, which will make software operation very
troublesome.
So in the next few generations of SoC will change this MMINFRA -2G to
software configurable. Then we can just make IOVA start address to 2G
without adding the mminfra_offset to the IOVA for GCE.

> I get it - if the DRAM moves up, MMINFRA is still at 2G because
> that's hard baked
> into the hardware, but I foresee that it'll be unlikely to see a
> platform changing
> the DRAM start address arbitrarily, getting out-of-sync with MMINFRA.
> 
> I propose to just get the address from the memory node for now, and
> to add a nice
> comment in the code that explains that "In at least MT8196, the
> MMINFRA hardware
> subtracts xyz etc etc" (and that explanation from the previous email
> is again
> wonderful and shall not be lost: either use that in the comment, or
> add it to
> the commit description, because it's really that good).
> 
> Should a new SoC appear in the future requiring an offset from the
> DRAM start
> address, we will think about how to make that work in the best
> possible way: in
> that case we could either reference something else to get the right
> address or
> we can just change this driver to just use the 2G offset statically
> for all.
> 
> What I'm trying to do here is to reduce the amount of changes that
> we'd need for
> adding new SoCs: since that 2G MMINFRA offset -> 2G DRAM start is not
> a coincidence
> I think that, should the DRAM start vary on new SoCs, the MMINFRA
> offset will
> follow the trend and vary with it.
> 
> So what I think is:
> 1. If I'm right, adding a new SoC (with different MMINFRA + DRAM
> offset) will be
> ??? as easy as adding a compatible string in the bindings, no effort
> in changing
> ??? this driver with new pdata offsets;
> 2. If I'm wrong, adding a new SoC means adding compat string and
> adding pdata and
> ??? one variable in the cmdq struct.
> 
> Where N.2 is what we would do anyway if we don't go with my proposed
> solution...
> 
> All this is just to give you my considerations about this topic -
> you're left
> completely free to disagree with me.
> If you disagree, I will trust your judgement, no problem here.
> 

Yes, I think your are right. No matter the IOVA start address changing,
MMINFRA will still -2G(the start address of DRAM PA).
Do you mean we can get the mminfra_offset from the start address of
memory in DTS, rather than defining it in pdata?

> > > > ?????? bool control_by_sw;
> > > > ?????? bool sw_ddr_en;
> > > > +???? bool gce_vm;
> > > > +???? u32 dma_mask_bit;
> > > > ?????? u32 gce_num;
> > > > ?? };
> > > > 
> > > > +static inline u32 cmdq_reg_shift_addr(dma_addr_t addr, const
> > > > struct gce_plat *pdata)
> > > > +{
> > > > +???? return ((addr + pdata->mminfra_offset) >> pdata->shift);
> > > > +}
> > > > +
> > > > +static inline u32 cmdq_reg_revert_addr(dma_addr_t addr, const
> > > > struct gce_plat *pdata)
> > > > +{
> > > > +???? return ((addr << pdata->shift) - pdata->mminfra_offset);
> > > > +}
> > > 
> > > I'm not sure that you really need those two functions... probably
> > > it's simply
> > > cleaner and easier to just write that single line every time...
> > > and
> > > I'm
> > > saying that especially for how you're using those functions, with
> > > some readl()
> > > passed directly as param, decreasing human readability by "a
> > > whole
> > > lot" :-)
> > > 
> > 
> > The reason why I use API wrapper instead of writing it directly in
> > readl() is to avoid missing the shift or mminfra_offset conversion
> > in
> > some places.
> > This problem is not easy to debug, and I have encountered it at
> > least
> > twice...
> > 
> > I think the advantage of using function is that it can be uniformly
> > modified to all places that need to handle DRAM address conversion.
> > What do you think? :-)
> > 
> 
> Eh, if you put it like that... it makes sense, so.. yeah, okay :-)
> 
> Still, please cleanup those instances of
> 
> `cmdq_reg_revert_addr(readl(something), pdata)`
> 
> those might be hard to read, so please just do something like:
> 
> regval = readl(something);
> curr_pa = cmdq_revert_addr(regval, pdata);
> 
> ...reword to your own liking, of course.
> 

OK, I'll refine that. Thanks.

> > > > +
> > > > ?? static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool
> > > > enable)
> > > > ?? {
> > > > ?????? WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq-
> > > > >clocks));
> > > > @@ -112,6 +136,30 @@ u8 cmdq_get_shift_pa(struct mbox_chan
> > > > *chan)
> > > > ?? }
> > > > ?? EXPORT_SYMBOL(cmdq_get_shift_pa);
> > > > 
> > > > +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan)
> > > > +{
> > > > +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > > > mbox);
> > > > +
> > > > +???? return cmdq->pdata->mminfra_offset;
> > > > +}
> > > > +EXPORT_SYMBOL(cmdq_get_offset_pa);
> > > 
> > > I think I remember this get_offset_pa from the old times, then CK
> > > removed it (and I
> > > was really happy about that disappearing), or am I confusing this
> > > with something
> > > else?
> > > 
> > > (of course, this wasn't used for mminfra, but for something
> > > else!)
> > > 
> > 
> > I can't find any remove history in mtk-cmdq-mailbox.c.
> > 
> > Maybe you mean the patch in this series?
> > https://lore.kernel.org/all/171213938049.123698.15573779837703602591.b4-ty at collabora.com/
> > 
> 
> Uhm, I think I may have confused something here, but yes I was
> remembering the
> patch series that you pointed out, definitely.
> 
> At the end, that series is doing something else, so nevermind, was
> just confusion.
> 

OK, no problem.

> > > > +
> > > > +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t
> > > > addr)
> > > > +{
> > > > +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > > > mbox);
> > > > +
> > > > +???? if (cmdq->pdata->mminfra_offset == 0)
> > > > +???????????? return false;
> > > > +
> > > > +???? /*
> > > > +????? * mminfra will recognize the addr that greater than the
> > > > mminfra_offset
> > > > +????? * as a transaction to DRAM.
> > > > +????? * So the caller needs to append mminfra_offset for the
> > > > true
> > > > case.
> > > > +????? */
> > > > +???? return (addr >= cmdq->pdata->mminfra_offset);
> > > 
> > > 
> > > /**
> > > ?? * cmdq_is_mminfra_gce() - Brief description
> > > ?? * @args.....
> > > ?? *
> > > ?? * The MMINFRA GCE will recognize an address greater than DRAM
> > > iostart as a
> > > ?? * DRAM transaction instead of ....xyz
> > > ?? *
> > > ?? * In order for callers to perform (xyz) transactions through
> > > the
> > > CMDQ, those
> > > ?? * need to know if they are using a GCE located in MMINFRA.
> > > ?? */
> > > bool cmdq_is_mminfra_gce(...)
> > > {
> > > ???????? return cmdq->pdata->mminfra_offset &&
> > > ??????????????? (addr >= cmdq->pdata->mminfra_offset)
> > > 
> > > > +}
> > > > +EXPORT_SYMBOL(cmdq_addr_need_offset);
> > > > +
> > > 
> > 
> > OK, I'll modify the API like this.
> > 
> > > ...but then, is there really no way of just handling the GCE
> > > being in
> > > MMINFRA
> > > transparently from the callers? Do the callers really *need* to
> > > know
> > > that they're
> > > using a new GCE?!
> > > 
> > 
> > Since the address subtracting is done in MMINFRA hardware, I think
> > GCE
> > users really need to handle it in driver.
> > 
> 
> Since the users of this infrastructure are multimedia related
> (disp/MDP3),
> I'd also like to get an opinion from MediaTek engineers familiar with
> that.
> 
> CK, Moudy, any opinion on that, please?
> 
> > > Another way of saying: can't we just handle the address
> > > translation
> > > in here instead
> > > of instructing each and every driver about how to communicate
> > > with
> > > the new GCE?!
> > > 
> > 
> > The DRAM address may not only be the command buffer to GCE, but
> > also
> > the working buffer provided by CMDQ users and being a part of GCE
> > instruction, so we need to handle the address translation in CMDQ
> > helper driver for the instruction generation.
> > E.g. ISP drivers may use GCE to write a hardware settings to a DRAM
> > as
> > backup buffer. The GCE write instruction will be:
> > WRITE the value of ISP register to DRAM address + mminfra_offset.
> > 
> > But most of the CMDQ users only need to use GCE to write hardware
> > register, so I only keep the translation in cmdq_pkt_mem_move(),
> > cmdq_pkt_poll_addr() and cmdq_pkt_jump_abs() at the latest series.
> 
> Yeah you're choosing the best of both worlds in that case, I do
> agree, but
> still - if there's a way to avoid drivers to have different handling
> for
> mminfra vs no-mminfra, that'd still be preferred.
> 
> Having the handling for something *centralized* somewhere, instead of
> it
> being sparse here and there, would make maintenance way easier...
> 
> ...and that's why I'm asking for CK and Moudy's opinion, nothing else
> :-)
> 

Yes, I totally agree with you. Thanks for the asking!

Regards,
Jason-JH.Lin 

> Cheers!
> Angelo
> 


From dan.carpenter at linaro.org  Thu Mar  6 03:01:13 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Thu, 6 Mar 2025 14:01:13 +0300
Subject: [PATCH v2] cpufreq: scpi: compare kHz instead of Hz
In-Reply-To: <20250125084950.1680-1-zuoqian113@gmail.com>
References: <20250123075321.4442-1-zuoqian113@gmail.com>
 <20250125084950.1680-1-zuoqian113@gmail.com>
Message-ID: <c6b8aa98-b5d3-4fc4-9f5d-4bf2471c3d6a@stanley.mountain>

On Sat, Jan 25, 2025 at 08:49:49AM +0000, zuoqian wrote:
> The CPU rate from clk_get_rate() may not be divisible by 1000
> (e.g., 133333333). But the rate calculated from frequency(kHz) is
> always divisible by 1000 (e.g., 133333000).
> Comparing the rate causes a warning during CPU scaling:
> "cpufreq: __target_index: Failed to change cpu frequency: -5".
> When we choose to compare kHz here, the issue does not occur.
> 
> Fixes: 343a8d17fa8d ("cpufreq: scpi: remove arm_big_little dependency")
> Signed-off-by: zuoqian <zuoqian113 at gmail.com>
> ---
> V1 -> V2: rename freq to freq_khz, change rate to unsigned long, and
> update patch summary.

Thanks!

Reviewed-by: Dan Carpenter <dan.carpenter at linaro.org>

regards,
dan carpenter



From Jason-JH.Lin at mediatek.com  Thu Mar  6 03:05:22 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Thu, 6 Mar 2025 11:05:22 +0000
Subject: [PATCH v4 6/8] soc: mediatek: Add programming flow for
 unsupported subsys ID hardware
In-Reply-To: <d02b6bbe-0d32-4e3f-985e-a0b610f72d98@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-7-jason-jh.lin@mediatek.com>
	 <c52b132b-fc08-4d1c-8276-1771f7457014@collabora.com>
	 <ddcf01c82f92ee461875e1122b009b7fca691127.camel@mediatek.com>
	 <d02b6bbe-0d32-4e3f-985e-a0b610f72d98@collabora.com>
Message-ID: <451d1b8a5aed46fd119c546f15fe00371f9546f3.camel@mediatek.com>

On Wed, 2025-03-05 at 19:08 +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 05/03/25 17:12, Jason-JH Lin (???) ha scritto:
> > On Tue, 2025-03-04 at 10:41 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > > > To support hardware without subsys IDs on new SoCs, add a
> > > > programming
> > > > flow that checks whether the subsys ID is valid. If the subsys
> > > > ID
> > > > is
> > > > invalid, the flow will call 2 alternative CMDQ APIs:
> > > > cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the
> > > > same
> > > > functionality.
> > > > 
> > > > Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> > > > ---
> > > > ?? drivers/soc/mediatek/mtk-mmsys.c | 14 +++++++++++---
> > > > ?? drivers/soc/mediatek/mtk-mutex.c | 11 +++++++++--
> > > > ?? 2 files changed, 20 insertions(+), 5 deletions(-)
> > > > 
> > > > diff --git a/drivers/soc/mediatek/mtk-mmsys.c
> > > > b/drivers/soc/mediatek/mtk-mmsys.c
> > > > index bb4639ca0b8c..ce949b863b05 100644
> > > > --- a/drivers/soc/mediatek/mtk-mmsys.c
> > > > +++ b/drivers/soc/mediatek/mtk-mmsys.c
> > > > @@ -167,9 +167,17 @@ static void mtk_mmsys_update_bits(struct
> > > > mtk_mmsys *mmsys, u32 offset, u32 mask,
> > > > ?????? u32 tmp;
> > > > 
> > > > ?????? if (mmsys->cmdq_base.size && cmdq_pkt) {
> > > > -???????????? ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys-
> > > > > cmdq_base.subsys,
> > > > -?????????????????????????????????????? mmsys->cmdq_base.offset
> > > > +
> > > > offset, val,
> > > > -?????????????????????????????????????? mask);
> > > > +???????????? offset += mmsys->cmdq_base.offset;
> > > > +???????????? if (mmsys->cmdq_base.subsys !=
> > > > CMDQ_SUBSYS_INVALID) {
> > > 
> > > You're still anyway passing the subsys to cmdq_pkt_write_mask(),
> > > right?!
> > > Why don't you just handle this in cmdq_pkt_write_mask() then? ;-)
> > > 
> > > I can see this pattern being repeated over and over in both
> > > drm/mediatek and MDP3
> > > drivers, and it's not necessary to duplicate this many times when
> > > you
> > > can write it
> > > just once.
> > > 
> > > Would've also been faster for you to implement... :-D
> > > 
> > 
> > I think did it in the series V1:
> > https://patchwork.kernel.org/project/linux-mediatek/patch/20241121042602.32730-5-jason-jh.lin at mediatek.com
> > 
> > Because it'll need to passing the base_pa and that will need to
> > change
> > the interface for original APIs.
> > 
> > And CK think that's not a necessary to change the APIs. It can be
> > done
> > by cmdq_pkt_assign() + cmdq_pkt_write_s_mask_value() in the client
> > drivers. Then you can see this pattern in everywhere. :-)
> > 
> 
> Using likely(x) and unlikely(x) should be avoided, really, unless
> it's something
> that is really really really really ... really ... rea.... likely or
> unlikely :-)
> 
> Btw. Changing the APIs is a bit difficult, but I disagree with CK
> about not
> "inventing" a new API for the unsupported-subsys flow.
> 
> It's true, it is not *strictly* needed to add a function, but it's
> good for any
> kind of future maintainability - as I explained, it's easier then to
> fix a problem
> if there's one.... and well, I can see that you agree with me,
> because effectively
> you did it the first time :-)
> 
> CK mentioned using cmdq_pkt_write() *or*
> cmdq_pkt_assignwrite/cmdq_pkt_write_pa()
> (however you wanna call it, it's fine for me), in drivers that know
> that there
> always is or there always isn't a subsys ID: that's a good
> suggestion, as this can
> be eventually done with assigning a function pointer, so, no
> conditionals at each
> operation.
> 
> My point of view, finally, is:
> ? - This is just another way of doing cmdq_pkt_write()
> ??? - This, at the end of the day, does exactly what cmdq_pkt_write()
> is doing,
> ????? except it's doing it with two instructions instead of one;
> ? - The same thing can be done in two different ways (depending on
> SoC)
> ??? - This same thing should have a function that does it.
> 
> A function that does it can be
> 
> int cmdq_pkt_write_pa(struct cmdq_pkt *pkt, u8 subsys /*unused*/, u32
> pa_base, u16
> offset, u32 value)
> {
> ??????? err = cmdq_pkt_assign(pkt, 0, CMDQ_ADDR_HIGH(pa_base));
> ??????? if (err < 0)
> ??????????????? return err;
> 
> ??????? return cmdq_pkt_write_s_value( .... etc)
> }
> 
> int cmdq_pkt_write() <--- unchanged, scheduled for removal after all
> drivers migrated
> 
> int cmdq_pkt_write_subsys(struct cmdq_pkt *pkt, u8 subsys, u32
> pa_base /*unused*/,
> u16 offset, u32 value)
> {
> ??????? /* This function will get the contents of cmdq_pkt_write once
> removed,
> ??????????? but, in the meanwhile, to avoid duplication we just call
> that: */
> 
> ??????? return cmdq_pkt_write(pkt, subsys, offset, value);
> }
> 
> - Are we adding one more function parameter? Yes
> - Is this impacting performance overall? Not really
> 
> After all, we're living in an ARMv8 (actually, ARMv9 for new ones)
> world, so
> one more function param won't hurt anyone.
> 
> I think that's the best of both worlds, and makes everyone happy.
> Are you happy with that? :-)
> 

Yes, I am happy with that. :-)
And thanks for your detail coding.

I'll change it in the next version.

regards,
Jason-JH Lin

> Cheers,
> Angelo
> 


From aliceryhl at google.com  Thu Mar  6 03:09:33 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Thu, 6 Mar 2025 11:09:33 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8iFeEWq16pNQdMa@pluto>
References: <Z8g8vhS9rqQ_ez48@google.com> <Z8iFeEWq16pNQdMa@pluto>
Message-ID: <Z8mCbc2Z2QGd3f8M@google.com>

On Wed, Mar 05, 2025 at 05:10:16PM +0000, Cristian Marussi wrote:
> On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> > Dear SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message
> > Protocol drivers maintainers,
> > 
> > I flashed a v6.13-rc3 kernel onto a Rock5B board and noticed the
> > following output in my terminal:
> > 
> > [  687.694465] kmemleak: 4 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
> > 
> > It seems that there is a memory leak for devices created with
> > scmi_device_create.
> > 
> `
> Hi Alice,
> 
> thanks for this report.
> 
> > This was with a kernel running v6.13-rc3, but as far as I can tell, no
> > relevant changes have landed since v6.13-rc3. My tree *does* include
> > commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> > scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> > not happening consistently.
> > 
> > See below for the full kmemleak report.
> > 
> > Alice
> > 
> > $ sudo cat /sys/kernel/debug/kmemleak
> > unreferenced object 0xffffff8106c86000 (size 2048):
> >   comm "swapper/0", pid 1, jiffies 4294893094
> >   hex dump (first 32 bytes):
> >     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
> >     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
> >   backtrace (crc feae9680):
> >     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
> >     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
> >     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
> >     [<000000008714917b>] scmi_device_create+0x40/0x194
> >     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
> >     [<00000000970bad38>] scmi_probe+0x584/0xa78
> >     [<000000002600d2fd>] platform_probe+0xbc/0xf0
> >     [<00000000f6f556b4>] really_probe+0x1b8/0x520
> >     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
> >     [<00000000d613b754>] driver_probe_device+0x6c/0x208
> >     [<00000000187a9170>] __driver_attach+0x168/0x328
> >     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
> >     [<00000000984a3176>] driver_attach+0x34/0x44
> >     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
> >     [<00000000747fce19>] driver_register+0xc0/0x1a0
> >     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> > unreferenced object 0xffffff8103bc01c0 (size 32):
> 
> I could not reproduce on my setup, even though I run a system with
> all the existent SCMI protocols (and related drivers) enabled (and
> so a lot of device creations) and a downstream test driver that causes
> even more SCMI devices to be created/destroyed at load/unload.
> 
> Coming down the path from scmi_chan_setup(), it seems something around
> transport devices creation, but it is not obvious to me where the leak
> could hide....
> 
> ...any particular setup on your side ? ...using LKMs, loading/unloading,
> any usage pattern that could help me reproduce ?

I looked into this a bit more, and actually it does happen consistently.
It's just that kmemleak doesn't report it until 10 minutes after
booting, so I did not notice it.

As for my setup, well, I boot the kernel over pxe and the rootfs is
mounted over NFSv4. The memory leak happens even if I don't do anything
at all - I just boot and wait. The device is a Radxa Rock5B.

Not sure what other information there is to give.

I tried again with v6.14-rc5, and I still got the leak:

user at rk3588-ci:~$ sudo cat /sys/kernel/debug/kmemleak
unreferenced object 0xffffff81068c0000 (size 2048):
  comm "swapper/0", pid 1, jiffies 4294893128
  hex dump (first 32 bytes):
    02 00 00 00 10 00 00 00 40 a3 7a 03 81 ff ff ff  ........ at .z.....
    60 c8 79 03 81 ff ff ff 18 00 8c 06 81 ff ff ff  `.y.............
  backtrace (crc 60df30fb):
    kmemleak_alloc+0x34/0xa0
    __kmalloc_cache_noprof+0x1e0/0x450
    __scmi_device_create+0xb4/0x2b4
    scmi_device_create+0x40/0x194
    scmi_chan_setup+0x144/0x3b8
    scmi_probe+0x51c/0x9fc
    platform_probe+0xbc/0xf0
    really_probe+0x1b8/0x520
    __driver_probe_device+0xe0/0x1d8
    driver_probe_device+0x6c/0x208
    __driver_attach+0x168/0x328
    bus_for_each_dev+0x14c/0x178
    driver_attach+0x34/0x44
    bus_add_driver+0x1bc/0x358
    driver_register+0xc0/0x1a0
    __platform_driver_register+0x40/0x50
unreferenced object 0xffffff81037aa340 (size 32):
  comm "swapper/0", pid 1, jiffies 4294893128
  hex dump (first 32 bytes):
    5f 5f 73 63 6d 69 5f 74 72 61 6e 73 70 6f 72 74  __scmi_transport
    5f 64 65 76 69 63 65 5f 72 78 5f 31 30 00 ff ff  _device_rx_10...
  backtrace (crc 8dab7ca7):
    kmemleak_alloc+0x34/0xa0
    __kmalloc_node_track_caller_noprof+0x234/0x528
    kstrdup+0x48/0x80
    kstrdup_const+0x30/0x3c
    __scmi_device_create+0xd4/0x2b4
    scmi_device_create+0x40/0x194
    scmi_chan_setup+0x144/0x3b8
    scmi_probe+0x51c/0x9fc
    platform_probe+0xbc/0xf0
    really_probe+0x1b8/0x520
    __driver_probe_device+0xe0/0x1d8
    driver_probe_device+0x6c/0x208
    __driver_attach+0x168/0x328
    bus_for_each_dev+0x14c/0x178
    driver_attach+0x34/0x44
    bus_add_driver+0x1bc/0x358
unreferenced object 0xffffff810379c860 (size 16):
  comm "swapper/0", pid 1, jiffies 4294893128
  hex dump (first 16 bytes):
    73 63 6d 69 5f 64 65 76 2e 32 00 03 81 ff ff ff  scmi_dev.2......
  backtrace (crc ccc21b9a):
    kmemleak_alloc+0x34/0xa0
    __kmalloc_node_track_caller_noprof+0x234/0x528
    kvasprintf+0x90/0x11c
    kvasprintf_const+0x98/0x138
    kobject_set_name_vargs+0x68/0x104
    dev_set_name+0x6c/0x98
    __scmi_device_create+0x17c/0x2b4
    scmi_device_create+0x40/0x194
    scmi_chan_setup+0x144/0x3b8
    scmi_probe+0x51c/0x9fc
    platform_probe+0xbc/0xf0
    really_probe+0x1b8/0x520
    __driver_probe_device+0xe0/0x1d8
    driver_probe_device+0x6c/0x208
    __driver_attach+0x168/0x328
    bus_for_each_dev+0x14c/0x178
unreferenced object 0xffffff8105be7400 (size 512):
  comm "swapper/0", pid 1, jiffies 4294893128
  hex dump (first 32 bytes):
    00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
    ff ff ff ff ff ff ff ff c0 b4 f0 83 c0 ff ff ff  ................
  backtrace (crc 7b92a969):
    kmemleak_alloc+0x34/0xa0
    __kmalloc_cache_noprof+0x1e0/0x450
    device_add+0x54/0x570
    device_register+0x20/0x30
    __scmi_device_create+0x184/0x2b4
    scmi_device_create+0x40/0x194
    scmi_chan_setup+0x144/0x3b8
    scmi_probe+0x51c/0x9fc
    platform_probe+0xbc/0xf0
    really_probe+0x1b8/0x520
    __driver_probe_device+0xe0/0x1d8
    driver_probe_device+0x6c/0x208
    __driver_attach+0x168/0x328
    bus_for_each_dev+0x14c/0x178
    driver_attach+0x34/0x44
    bus_add_driver+0x1bc/0x358


From Jason-JH.Lin at mediatek.com  Thu Mar  6 03:10:26 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Thu, 6 Mar 2025 11:10:26 +0000
Subject: [PATCH v4 7/8] drm/mediatek: Add programming flow for unsupported
 subsys ID hardware
In-Reply-To: <d1c2dfa8-c7e0-40b2-8b39-c04854e3ee24@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-8-jason-jh.lin@mediatek.com>
	 <d1c2dfa8-c7e0-40b2-8b39-c04854e3ee24@collabora.com>
Message-ID: <5132cd9dd130917d0d08fc8c2e5057e7e5cef040.camel@mediatek.com>

On Thu, 2025-03-06 at 10:47 +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 18/02/25 06:41, Jason-JH Lin ha scritto:
> > To support hardware without subsys IDs on new SoCs, add a
> > programming
> > flow that checks whether the subsys ID is valid. If the subsys ID
> > is
> > invalid, the flow will call 2 alternative CMDQ APIs:
> > cmdq_pkt_assign() and cmdq_pkt_write_s_value() to achieve the same
> > functionality.
> > 
> > Signed-off-by: Jason-JH Lin <jason-jh.lin at mediatek.com>
> > Reviewed-by: CK Hu <ck.hu at mediatek.com>
> > ---
> > ? drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 33
> > ++++++++++++++++++++-----
> > ? 1 file changed, 27 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index edc6417639e6..219d67735a54 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -66,14 +66,37 @@ struct mtk_ddp_comp_dev {
> > ????? struct cmdq_client_reg cmdq_reg;
> > ? };
> > 
> > +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > +static void mtk_ddp_write_cmdq_pkt(struct cmdq_pkt *cmdq_pkt,
> > struct cmdq_client_reg *cmdq_reg,
> > +??????????????????????????????? unsigned int offset, unsigned int
> > value, unsigned int mask)
> > +{
> > +???? offset += cmdq_reg->offset;
> > +
> > +???? if (cmdq_reg->subsys != CMDQ_SUBSYS_INVALID) {
> > +???????????? if (mask == GENMASK(31, 0))
> > +???????????????????? cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
> > offset, value);
> > +???????????? else
> > +???????????????????? cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg-
> > >subsys, offset, value, mask);
> 
> Sorry but this is pointless, really...
> 
> Function cmdq_pkt_write_mask() in mtk-cmdq-helper is doing:
> 
> ??????? if (mask != GENMASK(31, 0)) {
> ??????????????? err = cmdq_pkt_mask(pkt, mask);
> ??????????????? if (err < 0)
> ??????????????????????? return err;
> 
> ??????????????? offset_mask |= CMDQ_WRITE_ENABLE_MASK;
> ??????? }
> ??????? return cmdq_pkt_write(pkt, subsys, offset_mask, value);
> 
> here you're doing the exact inverse check.
> 

Oh, I didn't notice that it was redundant. Thanks.

> At this point you can just do:
> 
> static int mtk_ddp_write_cmdq_pkt(struct cmdq_pkt *cmdq_pkt, struct
> cmdq_client_reg
> *cmdq_reg,
> ????????????????????????????????? u16 offset, u32 value, u32 mask)
> {
> ??????? u16 gce_offset = cmdq_reg->offset + offset;
> 
> ??????? if (cmdq_reg->subsys != CMDQ_SUBSYS_INVALID)
> ??????????????? return cmdq_pkt_write_mask(pkt, cmdq_reg->subsys,
> gce_offset, value, mask);
> 
> ??????? return cmdq_pkt_write_mask_pa(cmdq_pkt, cmdq_reg->pa_base,
> gce_offset, value, mask);
> }
> 

I'll change like this, Thanks!

Regards,
Jason-JH Lin

> Cheers,
> Angelo

From msp at baylibre.com  Thu Mar  6 03:14:38 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:38 +0100
Subject: [PATCH v5 00/13] firmware: ti_sci: Partial-IO support
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>

Hi,

up to last series, the Partial-IO support consisted of two independent
series. As this last rework introduced file-based conflicts, I merged
the mcan series introducing wakeup support into this series:

  can: m_can: Add am62 wakeup support
  https://lore.kernel.org/lkml/20241219-topic-mcan-wakeup-source-v6-12-v6-0-1356c7f7cfda at baylibre.com/

Series
------
The series contains three parts:
 - m_can support for Partial-IO, in particular 'wakeup' pinctrl support.
 - ti_sci support for Partial-IO, which checks wakeup-sources if they
   are enabled for Partial-IO
 - DT description of system states on am62, am62a, am62p and the
   enabling of wakeup support on the starter kits that support it.

The series is based on v6.14-rc1.

Partial-IO
----------
Partial-IO is a low power system state in which nearly everything is
turned off except the pins of the CANUART group. CANUART contains the
mcu_mcan0, mcu_mcan1, wkup_uart0 and mcu_uart0 devices. These can
trigger a wakeup of the system on pin activity. Note that this does not
resume the system as the DDR is off as well. So this state can be
considered a power-off state with wakeup capabilities.

The wakeup capability of a device is described in the devicetree with
the wakeup-source property. This can hold phandles to system states in
which the device is capable of wakeup. Additionally a WKUP_EN flag is
set in the pinctrl of devices that are wakeup enabled.

On poweroff ti_sci checks if potential wakeup-sources for Partial-IO are
wakeup-enabled by the user. If that is the case, the poweroff is done
by TI_SCI by sending a PREPARE_SLEEP message with a specific mode. Once
sent the system will poweroff apart from the CANUART pins.

Dependencies
------------
This series requires an updated DT binding for the wakeup-source
property that allows the use of system-states which are also being added
in this pullrequest:
 - dt-schema wakeup-source binding update
   https://github.com/devicetree-org/dt-schema/pull/150

Testing
-------
After enabling Wake-on-LAN the system can be powered off and will enter
the Partial-IO state in which it can be woken up by activity on the
specific pins:
    ethtool -s can0 wol p
    ethtool -s can1 wol p
    poweroff

These patches are tested on am62-lp-sk on linux-next.

Best,
Markus

Previous versions "firmware: ti_sci: Partial-IO support":
 v1: https://lore.kernel.org/lkml/20240523080225.1288617-1-msp at baylibre.com/
 v2: https://lore.kernel.org/lkml/20240729080101.3859701-1-msp at baylibre.com/
 v3: https://lore.kernel.org/r/20241012-topic-am62-partialio-v6-13-b4-v3-0-f7c6c2739681 at baylibre.com
 v4: https://lore.kernel.org/r/20241219-topic-am62-partialio-v6-12-b4-v4-0-1cb8eabd407e at baylibre.com

Previous versions "can: m_can: Add am62 wakeup support":
 v1: https://lore.kernel.org/lkml/20240523075347.1282395-1-msp at baylibre.com/
 v2: https://lore.kernel.org/lkml/20240729074135.3850634-1-msp at baylibre.com/
 v3: https://lore.kernel.org/lkml/20241011-topic-mcan-wakeup-source-v6-12-v3-0-9752c714ad12 at baylibre.com
 v4: https://lore.kernel.org/r/20241015-topic-mcan-wakeup-source-v6-12-v4-0-fdac1d1e7aa6 at baylibre.com
 v5: https://lore.kernel.org/r/20241028-topic-mcan-wakeup-source-v6-12-v5-0-33edc0aba629 at baylibre.com
 v6: https://lore.kernel.org/r/20241219-topic-mcan-wakeup-source-v6-12-v6-0-1356c7f7cfda at baylibre.com

Changes in v5:
 - Rebased to v6.14-rc1
 - Merged m_can and ti_sci series to avoid conflicts and show
   dependencies more easily
 - Added definitions of system-states for am62/am62a/am62p
 - Moved wakeup-source definitions into board dts files as they require
   a bit of support on the board.
 - Updated ti_sci support to walk through the wakeup-source phandle
   lists
 - Added pinctrl settings for mcu_mcan0/1 on all boards
 - Minor style updates for ti_sci support for transfers without response
 - Update and move the dt-binding for wakeup-source from the m_can
   binding to the dt-schema repository

Changes in v4:
 - Rebased to v6.13-rc1
 - Removed all regulator related structures from patches and implemented
   the wakeup-source property use instead.

Changes in v3:
 - Remove other modes declared for PREPARE_SLEEP as they probably won't
   ever be used in upstream.
 - Replace the wait loop after sending PREPARE_SLEEP with msleep and do
   an emergency_restart if it exits
 - Remove uarts from DT wakeup sources
 - Split no response handling in ti_sci_do_xfer() into a separate patch
   and use goto instead of if ()
 - Remove DT binding parital-io-wakeup-sources. Instead I am modeling
   the devices that are in the relevant group that are powered during
   Partial-IO with the power supplies that are externally provided to
   the SoC. In this case they are provided through 'vddshv_canuart'. All
   devices using this regulator can be considered a potential wakeup
   source if they are wakeup capable and wakeup enabled.
 - Added devicetree patches adding vcc_3v3_sys regulator and
   vddshv_canuart for am62-lp-sk
 - Add pinctrl entries for am62-lp-sk to add WKUP_EN for mcu_mcan0 and
   mcu_mcan1

Changes in v2:
 - Rebase to v6.11-rc1
 - dt-binding:
    - Update commit message
    - Add more verbose description of the new binding for a better
      explanation.
 - ti_sci driver:
    - Combine ti_sci_do_send() into ti_sci_do_xfer and only wait on a
      response if a flag is set.
    - On failure to enter Partial-IO, do emergency_restart()
    - Add comments
    - Fix small things

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
Markus Schneider-Pargmann (13):
      firmware: ti_sci: Support transfers without response
      firmware: ti_sci: Partial-IO support
      dt-bindings: can: m_can: Add wakeup properties
      can: m_can: Map WoL to device_set_wakeup_enable
      can: m_can: Return ERR_PTR on error in allocation
      can: m_can: Support pinctrl wakeup state
      arm64: dts: ti: k3-pinctrl: Add WKUP_EN flag
      arm64: dts: ti: k3-am62: Define possible system states
      arm64: dts: ti: k3-am62a: Define possible system states
      arm64: dts: ti: k3-am62p: Define possible system states
      arm64: dts: ti: k3-am62-lp-sk: Set wakeup-source system-states
      arm64: dts: ti: k3-am62a7-sk: Set wakeup-source system-states
      arm64: dts: ti: k3-am62p5-sk: Set wakeup-source system-states

 .../devicetree/bindings/net/can/bosch,m_can.yaml   |  18 +++
 arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts           |  60 +++++++++
 arch/arm64/boot/dts/ti/k3-am62.dtsi                |  22 ++++
 arch/arm64/boot/dts/ti/k3-am62a.dtsi               |  27 +++++
 arch/arm64/boot/dts/ti/k3-am62a7-sk.dts            |  76 ++++++++++++
 arch/arm64/boot/dts/ti/k3-am62p.dtsi               |  27 +++++
 arch/arm64/boot/dts/ti/k3-am62p5-sk.dts            |  76 ++++++++++++
 arch/arm64/boot/dts/ti/k3-pinctrl.h                |   2 +
 drivers/firmware/ti_sci.c                          | 134 ++++++++++++++++++++-
 drivers/firmware/ti_sci.h                          |   5 +
 drivers/net/can/m_can/m_can.c                      | 111 ++++++++++++++++-
 drivers/net/can/m_can/m_can.h                      |   4 +
 drivers/net/can/m_can/m_can_pci.c                  |   4 +-
 drivers/net/can/m_can/m_can_platform.c             |   4 +-
 drivers/net/can/m_can/tcan4x5x-core.c              |   4 +-
 15 files changed, 562 insertions(+), 12 deletions(-)
---
base-commit: 7ec162622e66a4ff886f8f28712ea1b13069e1aa
change-id: 20241008-topic-am62-partialio-v6-12-b4-c273fbac4447

Best regards,
-- 
Markus Schneider-Pargmann <msp at baylibre.com>



From msp at baylibre.com  Thu Mar  6 03:14:39 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:39 +0100
Subject: [PATCH v5 01/13] firmware: ti_sci: Support transfers without
 response
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-1-f9323d3744a2@baylibre.com>

Check the header flags if an response is expected or not. If it is not
expected skip the receive part of ti_sci_do_xfer(). This prepares the
driver for one-way messages as prepare_sleep for Partial-IO.

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 drivers/firmware/ti_sci.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 806a975fff22ae00ecb88587b2c47ba172120bc2..09d11e75e14e6a6a82f6d99ab1852c142aeb7e5f 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -398,6 +398,9 @@ static void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo,
 static inline int ti_sci_do_xfer(struct ti_sci_info *info,
 				 struct ti_sci_xfer *xfer)
 {
+	struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+	bool response_expected = !!(hdr->flags & (TI_SCI_FLAG_REQ_ACK_ON_PROCESSED |
+						  TI_SCI_FLAG_REQ_ACK_ON_RECEIVED));
 	int ret;
 	int timeout;
 	struct device *dev = info->dev;
@@ -409,12 +412,12 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
 
 	ret = 0;
 
-	if (system_state <= SYSTEM_RUNNING) {
+	if (response_expected && system_state <= SYSTEM_RUNNING) {
 		/* And we wait for the response. */
 		timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
 		if (!wait_for_completion_timeout(&xfer->done, timeout))
 			ret = -ETIMEDOUT;
-	} else {
+	} else if (response_expected) {
 		/*
 		 * If we are !running, we cannot use wait_for_completion_timeout
 		 * during noirq phase, so we must manually poll the completion.

-- 
2.47.2



From msp at baylibre.com  Thu Mar  6 03:14:40 2025
From: msp at baylibre.com (Markus Schneider-Pargmann)
Date: Thu, 06 Mar 2025 12:14:40 +0100
Subject: [PATCH v5 02/13] firmware: ti_sci: Partial-IO support
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
Message-ID: <20250306-topic-am62-partialio-v6-12-b4-v5-2-f9323d3744a2@baylibre.com>

Add support for Partial-IO poweroff. In Partial-IO pins of a few
hardware units can generate system wakeups while DDR memory is not
powered resulting in a fresh boot of the system. These hardware units in
the SoC are always powered so that some logic can detect pin activity.

If the system supports Partial-IO as described in the fw capabilities, a
sys_off handler is added. This sys_off handler decides if the poweroff
is executed by entering normal poweroff or Partial-IO instead. The
decision is made by checking if wakeup is enabled on all devices that
may wake up the SoC from Partial-IO.

The possible wakeup devices are found by checking which devices
reference a "Partial-IO" system state in the list of wakeup-source
system states. Only devices that are actually enabled by the user will
be considered as an active wakeup source. If none of the wakeup sources
is enabled the system will do a normal poweroff. If at least one wakeup
source is enabled it will instead send a TI_SCI_MSG_PREPARE_SLEEP
message from the sys_off handler. Sending this message will result in an
immediate shutdown of the system. No execution is expected after this
point. The code will wait for 5s and do an emergency_restart afterwards
if Partial-IO wasn't entered at that point.

A short documentation about Partial-IO can be found in section 6.2.4.5
of the TRM at
  https://www.ti.com/lit/pdf/spruiv7

Signed-off-by: Markus Schneider-Pargmann <msp at baylibre.com>
---
 drivers/firmware/ti_sci.c | 127 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/firmware/ti_sci.h |   5 ++
 2 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 09d11e75e14e6a6a82f6d99ab1852c142aeb7e5f..a4b7869134779c58f4ef381a940455dea1f86153 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -6,6 +6,7 @@
  *	Nishanth Menon
  */
 
+#include "linux/stddef.h"
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/bitmap.h>
@@ -3742,6 +3743,111 @@ static const struct dev_pm_ops ti_sci_pm_ops = {
 #endif
 };
 
+/*
+ * Enter Partial-IO, which disables everything including DDR with only a small
+ * logic being active for wakeup.
+ */
+static int ti_sci_enter_partial_io(struct ti_sci_info *info)
+{
+	struct ti_sci_msg_req_prepare_sleep *req;
+	struct ti_sci_xfer *xfer;
+	struct device *dev = info->dev;
+	int ret = 0;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP,
+				   TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
+				   sizeof(*req), sizeof(struct ti_sci_msg_hdr));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	req = (struct ti_sci_msg_req_prepare_sleep *)xfer->xfer_buf;
+	req->mode = TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO;
+	req->ctx_lo = 0;
+	req->ctx_hi = 0;
+	req->debug_flags = 0;
+
+	dev_info(dev, "Entering Partial-IO because a powered wakeup-enabled device was found.\n");
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/*
+ * Iterate all device nodes that have a wakeup-source property and check if one
+ * of the possible phandles points to a Partial-IO system state. If it
+ * does resolve the device node to an actual device and check if wakeup is
+ * enabled.
+ */
+static bool ti_sci_partial_io_wakeup_enabled(struct ti_sci_info *info)
+{
+	struct device_node *wakeup_node = NULL;
+
+	for_each_node_with_property(wakeup_node, "wakeup-source") {
+		struct of_phandle_iterator it;
+		int err;
+
+		of_for_each_phandle(&it, err, wakeup_node, "wakeup-source", NULL, 0) {
+			struct platform_device *pdev;
+			bool may_wakeup;
+
+			if (of_property_match_string(it.node, "idle-state-name", "Partial-IO"))
+				continue;
+
+			pdev = of_find_device_by_node(wakeup_node);
+			if (!pdev)
+				continue;
+
+			may_wakeup = device_may_wakeup(&pdev->dev);
+			put_device(&pdev->dev);
+
+			if (may_wakeup) {
+				dev_dbg(info->dev, "%pOF identified as wakeup source for Partial-IO\n",
+					wakeup_node);
+				of_node_put(it.node);
+				of_node_put(wakeup_node);
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static int ti_sci_sys_off_handler(struct sys_off_data *data)
+{
+	struct ti_sci_info *info = data->cb_data;
+	bool enter_partial_io = ti_sci_partial_io_wakeup_enabled(info);
+	int ret;
+
+	if (!enter_partial_io)
+		return NOTIFY_DONE;
+
+	ret = ti_sci_enter_partial_io(info);
+
+	if (ret) {
+		dev_err(info->dev,
+			"Failed to enter Partial-IO %pe, trying to do an emergency restart\n",
+			ERR_PTR(ret));
+		emergency_restart();
+	}
+
+	mdelay(5000);
+	emergency_restart();
+
+	return NOTIFY_DONE;
+}
+
 /* Description for K2G */
 static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
 	.default_host_id = 2,
@@ -3885,6 +3991,19 @@ static int ti_sci_probe(struct platform_device *pdev)
 		goto out;
 	}
 
+	if (info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO) {
+		ret = devm_register_sys_off_handler(dev,
+						    SYS_OFF_MODE_POWER_OFF,
+						    SYS_OFF_PRIO_FIRMWARE,
+						    ti_sci_sys_off_handler,
+						    info);
+		if (ret) {
+			dev_err(dev, "Failed to register sys_off_handler %pe\n",
+				ERR_PTR(ret));
+			goto out;
+		}
+	}
+
 	dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
 		 info->handle.version.abi_major, info->handle.version.abi_minor,
 		 info->handle.version.firmware_revision,
@@ -3894,7 +4013,13 @@ static int ti_sci_probe(struct platform_device *pdev)
 	list_add_tail(&info->node, &ti_sci_list);
 	mutex_unlock(&ti_sci_list_mutex);
 
-	return of_platform_populate(dev->of_node, NULL, NULL, dev);
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret) {
+		dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret));
+		goto out;
+	}
+	return 0;
+
 out:
 	if (!IS_ERR(info->chan_tx))
 		mbox_free_channel(info->chan_tx);
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 053387d7baa064498e6a208daa7f70040ef87281..dec9e20cbe5da8f6d9393d56bb9a1e73cb083a42 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -592,6 +592,11 @@ struct ti_sci_msg_resp_get_clock_freq {
 struct ti_sci_msg_req_prepare_sleep {
 	struct ti_sci_msg_hdr	hdr;
 
+/*
+ * When sending perpare_sleep with MODE_PARTIAL_IO no response will be sent,
+ * no further steps are required.
+ */
+#define TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO				0x03
 #define TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED				0xfd
 	u8			mode;
 	u32			ctx_lo;

-- 
2.47.2



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:52 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:52 +0100
Subject: [PATCH v10 03/18] dt-bindings: clock: imx8mp: add VIDEO_PLL clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-4-dario.binacchi@amarulasolutions.com>

Unlike audio_pll1 and audio_pll2, there is no video_pll2. Further, the
name used in the RM is video_pll. So, let's add the IMX8MP_VIDEO_PLL[_*]
definitions to be consistent with the RM and avoid misunderstandings.

The IMX8MP_VIDEO_PLL1* constants have not been removed to ensure
backward compatibility of the patch.

No functional changes intended.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v6)

Changes in v6:
- Add 'Acked-by' tag of Krzysztof Kozlowski

Changes in v5:
- New

 include/dt-bindings/clock/imx8mp-clock.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h
index 7da4243984b2..3235d7de3b62 100644
--- a/include/dt-bindings/clock/imx8mp-clock.h
+++ b/include/dt-bindings/clock/imx8mp-clock.h
@@ -16,7 +16,8 @@
 #define IMX8MP_CLK_EXT4				7
 #define IMX8MP_AUDIO_PLL1_REF_SEL		8
 #define IMX8MP_AUDIO_PLL2_REF_SEL		9
-#define IMX8MP_VIDEO_PLL1_REF_SEL		10
+#define IMX8MP_VIDEO_PLL_REF_SEL		10
+#define IMX8MP_VIDEO_PLL1_REF_SEL		IMX8MP_VIDEO_PLL_REF_SEL
 #define IMX8MP_DRAM_PLL_REF_SEL			11
 #define IMX8MP_GPU_PLL_REF_SEL			12
 #define IMX8MP_VPU_PLL_REF_SEL			13
@@ -26,7 +27,8 @@
 #define IMX8MP_SYS_PLL3_REF_SEL			17
 #define IMX8MP_AUDIO_PLL1			18
 #define IMX8MP_AUDIO_PLL2			19
-#define IMX8MP_VIDEO_PLL1			20
+#define IMX8MP_VIDEO_PLL			20
+#define IMX8MP_VIDEO_PLL1			IMX8MP_VIDEO_PLL
 #define IMX8MP_DRAM_PLL				21
 #define IMX8MP_GPU_PLL				22
 #define IMX8MP_VPU_PLL				23
@@ -36,7 +38,8 @@
 #define IMX8MP_SYS_PLL3				27
 #define IMX8MP_AUDIO_PLL1_BYPASS		28
 #define IMX8MP_AUDIO_PLL2_BYPASS		29
-#define IMX8MP_VIDEO_PLL1_BYPASS		30
+#define IMX8MP_VIDEO_PLL_BYPASS			30
+#define IMX8MP_VIDEO_PLL1_BYPASS		IMX8MP_VIDEO_PLL_BYPASS
 #define IMX8MP_DRAM_PLL_BYPASS			31
 #define IMX8MP_GPU_PLL_BYPASS			32
 #define IMX8MP_VPU_PLL_BYPASS			33
@@ -46,7 +49,8 @@
 #define IMX8MP_SYS_PLL3_BYPASS			37
 #define IMX8MP_AUDIO_PLL1_OUT			38
 #define IMX8MP_AUDIO_PLL2_OUT			39
-#define IMX8MP_VIDEO_PLL1_OUT			40
+#define IMX8MP_VIDEO_PLL_OUT			40
+#define IMX8MP_VIDEO_PLL1_OUT			IMX8MP_VIDEO_PLL_OUT
 #define IMX8MP_DRAM_PLL_OUT			41
 #define IMX8MP_GPU_PLL_OUT			42
 #define IMX8MP_VPU_PLL_OUT			43
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:53 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:53 +0100
Subject: [PATCH v10 04/18] clk: imx8mp: rename video_pll1 to video_pll
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-5-dario.binacchi@amarulasolutions.com>

Unlike audio_pll1 and audio_pll2, there is no video_pll2. Further, the
name used in the RM is video_pll. So, let's rename "video_pll1" to
"video_pll" to be consistent with the RM and avoid misunderstandings.

No functional changes intended.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>

---
The patch, which simply replaces video_pll1 with video_pll, highlights
many warnings raised by checkpatch.pl. These are not generated by the
changes made but are inherited from how the module was originally
written. Fixing them would have meant "obscuring" the actual changes
introduced.

(no changes since v7)

Changes in v7:
- Add 'Reviewed-by' tag of Peng Fan

Changes in v5:
- Split the patch dropping the dt-bindings changes.

Changes in v4:
- New

 drivers/clk/imx/clk-imx8mp.c | 118 +++++++++++++++++------------------
 1 file changed, 59 insertions(+), 59 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index fb18f507f121..063bf26453a0 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -23,7 +23,7 @@ static u32 share_count_audio;
 static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
 static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
 static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
 static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
 static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
 static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
@@ -40,27 +40,27 @@ static const char * const imx8mp_a53_core_sels[] = {"arm_a53_div", "arm_pll_out"
 
 static const char * const imx8mp_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m",
 					      "vpu_pll_out", "sys_pll1_800m", "audio_pll1_out",
-					      "video_pll1_out", "sys_pll3_out", };
+					      "video_pll_out", "sys_pll3_out", };
 
 static const char * const imx8mp_ml_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
 					      "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-					      "video_pll1_out", "audio_pll2_out", };
+					      "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_gpu3d_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
 						      "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						      "video_pll1_out", "audio_pll2_out", };
+						      "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_gpu3d_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
 							"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-							"video_pll1_out", "audio_pll2_out", };
+							"video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_gpu2d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
 						 "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						 "video_pll1_out", "audio_pll2_out", };
+						 "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_audio_axi_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
 						     "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						     "video_pll1_out", "audio_pll2_out", };
+						     "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_hsio_axi_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
 						    "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
@@ -72,11 +72,11 @@ static const char * const imx8mp_media_isp_sels[] = {"osc_24m", "sys_pll2_1000m"
 
 static const char * const imx8mp_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
 						    "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
-						    "video_pll1_out", "sys_pll1_100m",};
+						    "video_pll_out", "sys_pll1_100m",};
 
 static const char * const imx8mp_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
 						    "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
-						    "video_pll1_out", "sys_pll3_out", };
+						    "video_pll_out", "sys_pll3_out", };
 
 static const char * const imx8mp_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
 						      "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
@@ -96,35 +96,35 @@ static const char * const imx8mp_media_apb_sels[] = {"osc_24m", "sys_pll2_125m",
 
 static const char * const imx8mp_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
 						   "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						   "video_pll1_out", "audio_pll2_out", };
+						   "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
 						   "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						   "video_pll1_out", "audio_pll2_out", };
+						   "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
 					       "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
-					       "video_pll1_out", "audio_pll2_out", };
+					       "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_noc_io_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
 						  "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
-						  "video_pll1_out", "audio_pll2_out", };
+						  "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_ml_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
 						  "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						  "video_pll1_out", "audio_pll2_out", };
+						  "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_ml_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
 						  "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
-						  "video_pll1_out", "audio_pll2_out", };
+						  "video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m",
 					       "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
-					       "audio_pll1_out", "video_pll1_out", };
+					       "audio_pll1_out", "video_pll_out", };
 
 static const char * const imx8mp_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
 						     "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out",
-						     "audio_pll1_out", "video_pll1_out", };
+						     "audio_pll1_out", "video_pll_out", };
 
 static const char * const imx8mp_mipi_dsi_esc_rx_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
 							   "sys_pll1_800m", "sys_pll2_1000m",
@@ -159,56 +159,56 @@ static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m", "sys_pll2_200m",
 						    "sys_pll1_160m", "sys_pll1_200m", };
 
 static const char * const imx8mp_i2c5_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_i2c6_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext1", "clk_ext2", };
 
 static const char * const imx8mp_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext2", "clk_ext3", };
 
 static const char * const imx8mp_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mp_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext2", "clk_ext3", };
 
 static const char * const imx8mp_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mp_enet_qos_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
 						    "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
-						    "video_pll1_out", "clk_ext4", };
+						    "video_pll_out", "clk_ext4", };
 
 static const char * const imx8mp_enet_qos_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
 							  "clk_ext1", "clk_ext2", "clk_ext3",
-							  "clk_ext4", "video_pll1_out", };
+							  "clk_ext4", "video_pll_out", };
 
 static const char * const imx8mp_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
 						    "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
-						    "video_pll1_out", "clk_ext4", };
+						    "video_pll_out", "clk_ext4", };
 
 static const char * const imx8mp_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
 						      "clk_ext1", "clk_ext2", "clk_ext3",
-						      "clk_ext4", "video_pll1_out", };
+						      "clk_ext4", "video_pll_out", };
 
 static const char * const imx8mp_enet_phy_ref_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m",
 							"sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out",
-							"video_pll1_out", "audio_pll2_out", };
+							"video_pll_out", "audio_pll2_out", };
 
 static const char * const imx8mp_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
 						"sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
-						"sys_pll2_250m", "video_pll1_out", };
+						"sys_pll2_250m", "video_pll_out", };
 
 static const char * const imx8mp_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m",
 						"sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
@@ -223,19 +223,19 @@ static const char * const imx8mp_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "s
 						  "audio_pll2_out", "sys_pll1_100m", };
 
 static const char * const imx8mp_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						"sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						"audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
@@ -276,42 +276,42 @@ static const char * const imx8mp_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "s
 
 static const char * const imx8mp_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
 						"sys_pll1_40m", "sys_pll3_out", "clk_ext1",
-						"sys_pll1_80m", "video_pll1_out", };
+						"sys_pll1_80m", "video_pll_out", };
 
 static const char * const imx8mp_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
 						"sys_pll1_40m", "sys_pll3_out", "clk_ext1",
-						"sys_pll1_80m", "video_pll1_out", };
+						"sys_pll1_80m", "video_pll_out", };
 
 static const char * const imx8mp_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
 						"sys_pll1_40m", "sys_pll3_out", "clk_ext2",
-						"sys_pll1_80m", "video_pll1_out", };
+						"sys_pll1_80m", "video_pll_out", };
 
 static const char * const imx8mp_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
 						"sys_pll1_40m", "sys_pll3_out", "clk_ext2",
-						"sys_pll1_80m", "video_pll1_out", };
+						"sys_pll1_80m", "video_pll_out", };
 
 static const char * const imx8mp_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext1" };
 
 static const char * const imx8mp_gpt2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext2" };
 
 static const char * const imx8mp_gpt3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext3" };
 
 static const char * const imx8mp_gpt4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext1" };
 
 static const char * const imx8mp_gpt5_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext2" };
 
 static const char * const imx8mp_gpt6_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
-						"sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+						"sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
 						"audio_pll1_out", "clk_ext3" };
 
 static const char * const imx8mp_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m",
@@ -328,19 +328,19 @@ static const char * const imx8mp_ipp_do_clko1_sels[] = {"osc_24m", "sys_pll1_800
 
 static const char * const imx8mp_ipp_do_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
 							"sys_pll1_166m", "sys_pll3_out", "audio_pll1_out",
-							"video_pll1_out", "osc_32k" };
+							"video_pll_out", "osc_32k" };
 
 static const char * const imx8mp_hdmi_fdcc_tst_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
 							 "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
-							 "audio_pll2_out", "video_pll1_out", };
+							 "audio_pll2_out", "video_pll_out", };
 
 static const char * const imx8mp_hdmi_24m_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
-						    "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+						    "sys_pll3_out", "audio_pll1_out", "video_pll_out",
 						    "audio_pll2_out", "sys_pll1_133m", };
 
 static const char * const imx8mp_hdmi_ref_266m_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll3_out",
 							 "sys_pll2_333m", "sys_pll1_266m", "sys_pll2_200m",
-							 "audio_pll1_out", "video_pll1_out", };
+							 "audio_pll1_out", "video_pll_out", };
 
 static const char * const imx8mp_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
 						  "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
@@ -349,26 +349,26 @@ static const char * const imx8mp_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "s
 static const char * const imx8mp_media_cam1_pix_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
 							  "sys_pll1_800m", "sys_pll2_1000m",
 							  "sys_pll3_out", "audio_pll2_out",
-							  "video_pll1_out", };
+							  "video_pll_out", };
 
 static const char * const imx8mp_media_mipi_phy1_ref_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
 							       "sys_pll1_800m", "sys_pll2_1000m",
 							       "clk_ext2", "audio_pll2_out",
-							       "video_pll1_out", };
+							       "video_pll_out", };
 
-static const char * const imx8mp_media_disp_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+static const char * const imx8mp_media_disp_pix_sels[] = {"osc_24m", "video_pll_out", "audio_pll2_out",
 							   "audio_pll1_out", "sys_pll1_800m",
 							   "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
 
 static const char * const imx8mp_media_cam2_pix_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
 							  "sys_pll1_800m", "sys_pll2_1000m",
 							  "sys_pll3_out", "audio_pll2_out",
-							  "video_pll1_out", };
+							  "video_pll_out", };
 
 static const char * const imx8mp_media_ldb_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
 						     "sys_pll1_800m", "sys_pll2_1000m",
 						     "clk_ext2", "audio_pll2_out",
-						     "video_pll1_out", };
+						     "video_pll_out", };
 
 static const char * const imx8mp_memrepair_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
 							"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
@@ -392,12 +392,12 @@ static const char * const imx8mp_vpu_vc8000e_sels[] = {"osc_24m", "vpu_pll_out",
 						       "sys_pll3_out", "audio_pll1_out", };
 
 static const char * const imx8mp_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll_out", "sys_pll1_133m", "osc_hdmi",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
 
-static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
 						  "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
 						  "arm_pll_out", "sys_pll1_out", "sys_pll2_out",
 						  "sys_pll3_out", "dummy", "dummy", "osc_24m",
@@ -441,7 +441,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", anatop_base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", anatop_base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", anatop_base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", anatop_base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MP_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", anatop_base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MP_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", anatop_base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	hws[IMX8MP_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", anatop_base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
@@ -452,7 +452,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MP_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", anatop_base, &imx_1443x_pll);
 	hws[IMX8MP_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", anatop_base + 0x14, &imx_1443x_pll);
-	hws[IMX8MP_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", anatop_base + 0x28, &imx_1443x_pll);
+	hws[IMX8MP_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", anatop_base + 0x28, &imx_1443x_pll);
 	hws[IMX8MP_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", anatop_base + 0x50, &imx_1443x_dram_pll);
 	hws[IMX8MP_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", anatop_base + 0x64, &imx_1416x_pll);
 	hws[IMX8MP_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", anatop_base + 0x74, &imx_1416x_pll);
@@ -463,7 +463,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", anatop_base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", anatop_base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", anatop_base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+	hws[IMX8MP_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", anatop_base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MP_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", anatop_base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MP_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", anatop_base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX8MP_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", anatop_base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
@@ -474,7 +474,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	hws[IMX8MP_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", anatop_base, 13);
 	hws[IMX8MP_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", anatop_base + 0x14, 13);
-	hws[IMX8MP_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", anatop_base + 0x28, 13);
+	hws[IMX8MP_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", anatop_base + 0x28, 13);
 	hws[IMX8MP_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", anatop_base + 0x50, 13);
 	hws[IMX8MP_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", anatop_base + 0x64, 11);
 	hws[IMX8MP_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", anatop_base + 0x74, 11);
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:04 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:04 +0100
Subject: [PATCH v10 15/18] dt-bindings: clock: imx8m-clock: add PLLs
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-16-dario.binacchi@amarulasolutions.com>

Though adding the PLLs to clocks and clock-names properties will break
the ABI, it is required to accurately describe the hardware. Indeed,
the Clock Control Module (CCM) receives clocks from the PLLs and
oscillators and generates clocks for on-chip peripherals.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v7)

Changes in v7:
- Add 'Reviewed-by' tag of Krzysztof Kozlowski

Changes in v6:
- New

 .../bindings/clock/imx8m-clock.yaml           | 27 ++++++++++++++-----
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/imx8m-clock.yaml b/Documentation/devicetree/bindings/clock/imx8m-clock.yaml
index c643d4a81478..d96570bf60dc 100644
--- a/Documentation/devicetree/bindings/clock/imx8m-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/imx8m-clock.yaml
@@ -29,12 +29,12 @@ properties:
     maxItems: 2
 
   clocks:
-    minItems: 6
-    maxItems: 7
+    minItems: 7
+    maxItems: 10
 
   clock-names:
-    minItems: 6
-    maxItems: 7
+    minItems: 7
+    maxItems: 10
 
   '#clock-cells':
     const: 1
@@ -86,6 +86,10 @@ allOf:
             - description: ext2 clock input
             - description: ext3 clock input
             - description: ext4 clock input
+            - description: audio1 PLL input
+            - description: audio2 PLL input
+            - description: dram PLL input
+            - description: video PLL input
 
         clock-names:
           items:
@@ -95,20 +99,31 @@ allOf:
             - const: clk_ext2
             - const: clk_ext3
             - const: clk_ext4
+            - const: audio_pll1
+            - const: audio_pll2
+            - const: dram_pll
+            - const: video_pll
 
 additionalProperties: false
 
 examples:
   # Clock Control Module node:
   - |
+    #include <dt-bindings/clock/imx8mm-clock.h>
+
     clock-controller at 30380000 {
         compatible = "fsl,imx8mm-ccm";
         reg = <0x30380000 0x10000>;
         #clock-cells = <1>;
         clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
-                 <&clk_ext3>, <&clk_ext4>;
+                 <&clk_ext3>, <&clk_ext4>,
+                 <&anatop IMX8MM_ANATOP_AUDIO_PLL1>,
+                 <&anatop IMX8MM_ANATOP_AUDIO_PLL2>,
+                 <&anatop IMX8MM_ANATOP_DRAM_PLL>,
+                 <&anatop IMX8MM_ANATOP_VIDEO_PLL>;
         clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
-                      "clk_ext3", "clk_ext4";
+                      "clk_ext3", "clk_ext4", "audio_pll1", "audio_pll2",
+                      "dram_pll", "video_pll";
     };
 
   - |
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:05 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:05 +0100
Subject: [PATCH v10 16/18] arm64: dts: imx8mm: add PLLs to clock controller module (CCM)
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-17-dario.binacchi@amarulasolutions.com>

Add the PLLs generated by anatop to the clock list of the Clock
Controller Module (CCM) node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mm.dtsi | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 597041a05073..79f4c1ae7d8b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -642,9 +642,14 @@ clk: clock-controller at 30380000 {
 					     <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
 				clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
-					 <&clk_ext3>, <&clk_ext4>;
+					 <&clk_ext3>, <&clk_ext4>,
+					 <&anatop IMX8MM_ANATOP_AUDIO_PLL1>,
+					 <&anatop IMX8MM_ANATOP_AUDIO_PLL2>,
+					 <&anatop IMX8MM_ANATOP_DRAM_PLL>,
+					 <&anatop IMX8MM_ANATOP_VIDEO_PLL>;
 				clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
-					      "clk_ext3", "clk_ext4";
+					      "clk_ext3", "clk_ext4", "audio_pll1", "audio_pll2",
+					      "dram_pll", "video_pll";
 				assigned-clocks = <&clk IMX8MM_CLK_A53_SRC>,
 						<&clk IMX8MM_CLK_A53_CORE>,
 						<&clk IMX8MM_CLK_NOC>,
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:06 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:06 +0100
Subject: [PATCH v10 17/18] arm64: dts: imx8mn: add PLLs to clock controller module (CCM)
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-18-dario.binacchi@amarulasolutions.com>

Add the PLLs generated by anatop to the clock list of the Clock
Controller Module (CCM) node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mn.dtsi | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index 49be492b5687..01013c1fd61d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -643,9 +643,14 @@ clk: clock-controller at 30380000 {
 					     <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
 				clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
-					 <&clk_ext3>, <&clk_ext4>;
+					 <&clk_ext3>, <&clk_ext4>,
+					 <&anatop IMX8MN_ANATOP_AUDIO_PLL1>,
+					 <&anatop IMX8MN_ANATOP_AUDIO_PLL2>,
+					 <&anatop IMX8MN_ANATOP_DRAM_PLL>,
+					 <&anatop IMX8MN_ANATOP_VIDEO_PLL>;
 				clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
-					      "clk_ext3", "clk_ext4";
+					      "clk_ext3", "clk_ext4", "audio_pll1", "audio_pll2",
+					      "dram_pll", "video_pll";
 				assigned-clocks = <&clk IMX8MN_CLK_A53_SRC>,
 						<&clk IMX8MN_CLK_A53_CORE>,
 						<&clk IMX8MN_CLK_NOC>,
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:07 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:07 +0100
Subject: [PATCH v10 18/18] arm64: dts: imx8mp: add PLLs to clock controller module (CCM)
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-19-dario.binacchi@amarulasolutions.com>

Add the PLLs generated by anatop to the clock list of the Clock
Controller Module (CCM) node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

Changes in v10:
- Drop the v9 patches:
  16/23 dt-bindings: clock: imx8m-clock: support spread spectrum clocking
  17/23 clk: imx: pll14xx: support spread spectrum clock generation
  17/23 clk: imx8mn: support spread spectrum clock generation
  21/23 clk: imx8mp: support spread spectrum clock generation
  23/23 clk: imx8mm: support spread spectrum clock generation

Changes in v9:
- Add 'Reviewed-by' tag of Peng Fan for imx8mn platform patches
- Fix building warning raised by the kernel test robot for patch
  v8, 11/18 clk: imx: add support for i.MX8MN anatop clock driver
- Add patches for imx8m{m,p} platforms:
  - 23/23 clk: imx8mm: support spread spectrum clock generation
  - 22/23 clk: imx: add support for i.MX8MM anatop clock driver
  - 21/23 clk: imx8mp: support spread spectrum clock generation
  - 20/23 clk: imx8mp: rename ccm_base to base
  - 19/23 clk: imx: add support for i.MX8MP anatop clock driver

Changes in v8:
- Drop the patches added in version 7:
  - 10/23 dt-bindings: clock: imx8m-clock: add phandle to the anatop
  - 11/23 arm64: dts: imx8mm: add phandle to anatop within CCM
  - 12/23 arm64: dts: imx8mn: add phandle to anatop within CCM
  - 13/23 arm64: dts: imx8mp: add phandle to anatop within CCM
  - 14/23 arm64: dts: imx8mq: add phandle to anatop within CCM

Changes in v7:
- Add and manage fsl,anatop property as phandle to the anatop node with
  the new patches:
  - 10/23 dt-bindings: clock: imx8m-clock: add phandle to the anatop
  - 11/23 arm64: dts: imx8mm: add phandle to anatop within CCM
  - 12/23 arm64: dts: imx8mn: add phandle to anatop within CCM
  - 13/23 arm64: dts: imx8mp: add phandle to anatop within CCM
  - 14/23 arm64: dts: imx8mq: add phandle to anatop within CCM

Changes in v6:
- Merge patches:
  10/20 dt-bindings: clock: imx8mm: add binding definitions for anatop
  11/20 dt-bindings: clock: imx8mn: add binding definitions for anatop
  12/20 dt-bindings: clock: imx8mp: add binding definitions for anatop
  to
  05/20 dt-bindings: clock: imx8m-anatop: define clocks/clock-names
  now renamed
  05/18 dt-bindings: clock: imx8m-anatop: add oscillators and PLLs
- Split the patch
  15/20 dt-bindings-clock-imx8m-clock-support-spread-spectru.patch
  into
  12/18 dt-bindings: clock: imx8m-clock: add PLLs
  16/18 dt-bindings: clock: imx8m-clock: support spread spectrum clocking

Changes in v5:
- Fix compilation errors.
- Separate driver code from dt-bindings

Changes in v4:
- Add dt-bindings for anatop
- Add anatop driver
- Drop fsl,ssc-clocks from spread spectrum dt-bindings
- New

Changes in v3:
- Patches 1/8 has been added in version 3. The dt-bindings have
  been moved from fsl,imx8m-anatop.yaml to imx8m-clock.yaml. The
  anatop device (fsl,imx8m-anatop.yaml) is indeed more or less a
  syscon, so it represents a memory area accessible by ccm
  (imx8m-clock.yaml) to setup the PLLs.
- Patches {3,5}/8 have been added in version 3.
- Patches {4,6,8}/8 use ccm device node instead of the anatop one.

Changes in v2:
- Add "allOf:" and place it after "required:" block, like in the
  example schema.
- Move the properties definition to the top-level.
- Drop unit types as requested by the "make dt_binding_check" command.

 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 0b928e173f29..eab05170442d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -751,9 +751,14 @@ clk: clock-controller at 30380000 {
 					     <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
 				clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
-					 <&clk_ext3>, <&clk_ext4>;
+					 <&clk_ext3>, <&clk_ext4>,
+					 <&anatop IMX8MP_ANATOP_AUDIO_PLL1>,
+					 <&anatop IMX8MP_ANATOP_AUDIO_PLL2>,
+					 <&anatop IMX8MP_ANATOP_DRAM_PLL>,
+					 <&anatop IMX8MP_ANATOP_VIDEO_PLL>;
 				clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
-					      "clk_ext3", "clk_ext4";
+					      "clk_ext3", "clk_ext4", "audio_pll1", "audio_pll2",
+					      "dram_pll", "video_pll";
 				assigned-clocks = <&clk IMX8MP_CLK_A53_SRC>,
 						  <&clk IMX8MP_CLK_A53_CORE>,
 						  <&clk IMX8MP_CLK_NOC>,
-- 
2.43.0



From jonathanh at nvidia.com  Thu Mar  6 03:30:53 2025
From: jonathanh at nvidia.com (Jon Hunter)
Date: Thu, 6 Mar 2025 11:30:53 +0000
Subject: [PATCH RFC 0/5] net: stmmac: fix resume failures due to RX clock
In-Reply-To: <Z8B4tVd4nLUKXdQ4@shell.armlinux.org.uk>
References: <Z8B4tVd4nLUKXdQ4@shell.armlinux.org.uk>
Message-ID: <f783cf9c-9f79-4680-a6e9-d078abbd96ec@nvidia.com>

Hi Russell,

On 27/02/2025 14:37, Russell King (Oracle) wrote:
> Hi,
> 
> This series is likely dependent on the "net: stmmac: cleanup transmit
> clock setting" series which was submitted earlier today.

I tested this series without the above on top of mainline and I still 
saw some issues with suspend. However, when testing this on top of -next 
(which has the referenced series) it works like a charm. So yes it does 
appear to be dependent indeed.

I have tested this on Tegra186, Tegra194 and Tegra234 with -next and all 
are working fine. So with that feel free to add my ...

Tested-by: Jon Hunter <jonathanh at nvidia.com>

Thanks!
Jon

-- 
nvpublic



From lkp at intel.com  Thu Mar  6 03:33:28 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 19:33:28 +0800
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
References: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
Message-ID: <202503061910.eJW7M2H3-lkp@intel.com>

Hi Robin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on linus/master v6.14-rc5 next-20250305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Robin-Murphy/dt-bindings-dma-Add-Arm-DMA-350/20250301-012733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link:    https://lore.kernel.org/r/55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy%40arm.com
patch subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
config: nios2-randconfig-r111-20250306 (https://download.01.org/0day-ci/archive/20250306/202503061910.eJW7M2H3-lkp at intel.com/config)
compiler: nios2-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250306/202503061910.eJW7M2H3-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503061910.eJW7M2H3-lkp at intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/dma/arm-dma350.c:485:31: sparse: sparse: dubious: !x & y
   drivers/dma/arm-dma350.c: note: in included file (through include/linux/smp.h, include/linux/lockdep.h, include/linux/spinlock.h, ...):
   include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true
   include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true
   include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true
   include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true

vim +485 drivers/dma/arm-dma350.c

   462	
   463	static irqreturn_t d350_irq(int irq, void *data)
   464	{
   465		struct d350_chan *dch = data;
   466		struct device *dev = dch->vc.chan.device->dev;
   467		struct virt_dma_desc *vd = &dch->desc->vd;
   468		u32 ch_status;
   469	
   470		ch_status = readl(dch->base + CH_STATUS);
   471		if (!ch_status)
   472			return IRQ_NONE;
   473	
   474		if (ch_status & CH_STAT_INTR_ERR) {
   475			u32 errinfo = readl_relaxed(dch->base + CH_ERRINFO);
   476	
   477			if (errinfo & (CH_ERRINFO_AXIRDPOISERR | CH_ERRINFO_AXIRDRESPERR))
   478				vd->tx_result.result = DMA_TRANS_READ_FAILED;
   479			else if (errinfo & CH_ERRINFO_AXIWRRESPERR)
   480				vd->tx_result.result = DMA_TRANS_WRITE_FAILED;
   481			else
   482				vd->tx_result.result = DMA_TRANS_ABORTED;
   483	
   484			vd->tx_result.residue = d350_get_residue(dch);
 > 485		} else if (!ch_status & CH_STAT_INTR_DONE) {
   486			dev_warn(dev, "Unexpected IRQ source? 0x%08x\n", ch_status);
   487		}
   488		writel_relaxed(ch_status, dch->base + CH_STATUS);
   489	
   490		spin_lock(&dch->vc.lock);
   491		vchan_cookie_complete(vd);
   492		if (ch_status & CH_STAT_INTR_DONE) {
   493			dch->status = DMA_COMPLETE;
   494			dch->residue = 0;
   495			d350_start_next(dch);
   496		} else {
   497			dch->status = DMA_ERROR;
   498			dch->residue = vd->tx_result.residue;
   499		}
   500		spin_unlock(&dch->vc.lock);
   501	
   502		return IRQ_HANDLED;
   503	}
   504	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From angelogioacchino.delregno at collabora.com  Thu Mar  6 03:34:52 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu,  6 Mar 2025 12:34:52 +0100
Subject: [GIT,PULL,1/2] MediaTek ARM64 DTS updates for v6.15
Message-ID: <20250306113540.148342-1-angelogioacchino.delregno@collabora.com>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux.git tags/mtk-dts64-for-v6.15

for you to fetch changes up to 4c8ff61199a70e73e6c4d5e8a03f02d32730821c:

  arm64: dts: mediatek: mt8395-radxa-nio-12l: Add Radxa 8 HD panel (2025-03-06 10:53:07 +0100)

----------------------------------------------------------------
MediaTek ARM64 DTS updates for v6.15

This adds new SoCs and new machines, other than improving support for
currently supported ones.

In particular, for SoCs:
 - Airoha EN7581 gets support for its SCU clock controller, SPI NAND,
   hardware RNG, pinctrl, and i2c controllers;
 - MediaTek MT8365 SoC gets support for all of its Display Controller
   components;
 - MediaTek Genio 510 MT8370 - a lower binned variant of Genio 700
   MT8390 (which, in turn, is the same as MT8188) - is introduced;
 - MT8188 gets support for more Display Controller components (DSC
   and MERGE), for the tertiary MSDC (eMMC/SD/SDIO) controller, and
   for the MTU3 USB DRD controllers;
 - MT8195 and MT8188 both get migrated to the new OF Graph used for
   defining a pipeline for the Display Controller components (as
   this was previously hardcoded per-board in the drm driver, ugh!);

..and for boards:
 - Google Kukui (MT8183) is switched to Elan touchscreen driver
   instead of hid-over-i2c to fix probe failures in some cases;
 - Google Cherry (MT8195) and Geralt (MT8188) Chromebooks get
   migrated to using OF Graph for defining their board specific
   part of the display pipeline;
 - MediaTek Genio 350 (mt8365) EVK board adds support for HDMI output
   through the iTE IT66121 chip, and for DSI output to the Startek
   KD070FHFID015 display;
 - MediaTek Genio 510 EVK board is introduced with a common devicetree
   between mt8390 and mt8370 (Genio 700 and Genio 510) EVKs;
 - MediaTek Genio 700 (and 510) EVKs get support for their integrated
   dual Digital Microphones, for their RichTek RT1715 USB Type-C
   Controller with USB-PD capability, the iTE IT5205 Alternate Mode
   Passive MUX (USB3.1/DP1.4), and for USB Gadget/Host switching
   through the MTU3 DRD Controller, other than for USB in general;
 - MediaTek Genio 1200 EVK gets support for its MediaTek MT6360 PMIC
   integrated Type-C Controller, and the IT5205 MUX;
 - Radxa NIO-12L gets its DSI display pipeline preconfigured and also
   the introduction of a devicetree overlay for the official Radxa
   8HD DSI panel, enabling display output over DSI.

And fixes/cleanups:
 - MT8173 gets fixes for bindings validation: PMIC node drops the
   unnecessary address/size cells, disp-pwm gets its compatibles
   list fixed (as mt6595 was not expected there), and some nodes
   got the right name (clock controllers were disguides as power
   controllers, and intpol was changed to interrupt-controller);
 - MT8188-based (MT8390) Genio boards get a fix for duplicated
   regulator name;
 - MT6359 PMIC gets fixes for audio-codec node validation.

----------------------------------------------------------------
Alexandre Mergnat (2):
      arm64: dts: mediatek: add display blocks support for the MT8365 SoC
      arm64: dts: mediatek: add display support for mt8365-evk

AngeloGioacchino Del Regno (11):
      arm64: dts: mediatek: mt8188: Add VDO0's DSC and MERGE block nodes
      arm64: dts: mediatek: mt8188: Add tertiary eMMC/SD/SDIO controller
      dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP
      arm64: dts: mediatek: mt8188: Add MTU3 nodes and correctly describe USB
      arm64: dts: mediatek: mt8390-genio-700: Add USB, TypeC Controller, MUX
      arm64: dts: mediatek: mt8188: Add base display controller graph
      arm64: dts: mediatek: mt8188-geralt: Add graph for DSI and DP displays
      arm64: dts: mediatek: mt8390-genio-common: Configure touch vreg pins
      arm64: dts: mediatek: mt8195: Add base display controller graph
      arm64: mediatek: mt8195-cherry: Add graph for eDP and DP displays
      arm64: dts: mediatek: mt8395-nio-12l: Preconfigure DSI0 pipeline

Chen-Yu Tsai (3):
      arm64: dts: mediatek: mt8173-elm: Drop pmic's #address-cells and #size-cells
      arm64: dts: mediatek: mt8173: Fix disp-pwm compatible string
      arm64: dts: mediatek: mt8173: Fix some node names

Christian Marangi (3):
      arm64: dts: airoha: en7581: Add Clock Controller node
      arm64: dts: airoha: en7581: Add SNAND node
      arm64: dts: airoha: en7581: Add default partition table for EVB board

Fabien Parent (1):
      arm64: dts: mediatek: mt8395-genio-1200-evk: add support for TCPC port

Hsin-Te Yuan (1):
      arm64: dts: mediatek: mt8183: Switch to Elan touchscreen driver

Julien Massot (2):
      arm64: dts: mediatek: mt8395-nio-12l: Prepare MIPI DSI port
      arm64: dts: mediatek: mt8395-radxa-nio-12l: Add Radxa 8 HD panel

Lorenzo Bianconi (2):
      arm64: dts: airoha: en7581: Add more nodes to EN7581 SoC evaluation board
      arm64: dts: airoha: en7581: Fix clock-controller address

Louis-Alexis Eyraud (5):
      dt-bindings: arm: mediatek: add mt8370-evk board
      arm64: dts: mediatek: add support for MT8370 SoC
      arm64: dts: mediatek: mt8390-genio-700-evk: Move common parts to dtsi
      arm64: dts: mediatek: add device-tree for Genio 510 EVK board
      arm64: dts: mediatek: mt8390-genio-common: Fix duplicated regulator name

Macpaul Lin (2):
      arm64: dts: mediatek: mt6359: fix dtbs_check error for audio-codec
      dt-bindings: usb: mtu3: Add ports property

N?colas F. R. A. Prado (3):
      arm64: dts: mediatek: mt8188: Assign apll1 clock as parent to avoid hang
      arm64: dts: mediatek: mt8390-genio-common: Add routes for DMIC
      arm64: dts: mediatek: mt8390-genio-common: Add delay codec for DMIC

 Documentation/devicetree/bindings/arm/mediatek.yaml               |    5 +
 Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml      |    4 +
 Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml          |   12 +
 arch/arm64/boot/dts/airoha/en7581-evb.dts                         |   44 +++
 arch/arm64/boot/dts/airoha/en7581.dtsi                            |   91 ++++++
 arch/arm64/boot/dts/mediatek/Makefile                             |    3 +
 arch/arm64/boot/dts/mediatek/mt6359.dtsi                          |    3 +-
 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi                      |    2 -
 arch/arm64/boot/dts/mediatek/mt8173.dtsi                          |   12 +-
 arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts        |    9 +-
 arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts |    8 +-
 arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts |    8 +-
 arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts |    8 +-
 arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi                   |  173 +++++++++-
 arch/arm64/boot/dts/mediatek/mt8188.dtsi                          |  307 +++++++++++++++---
 arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi                   |  184 ++++++++++-
 arch/arm64/boot/dts/mediatek/mt8195.dtsi                          |  129 ++++++++
 arch/arm64/boot/dts/mediatek/mt8365-evk.dts                       |  245 +++++++++++++-
 arch/arm64/boot/dts/mediatek/mt8365.dtsi                          |  336 +++++++++++++++++++
 arch/arm64/boot/dts/mediatek/mt8370-genio-510-evk.dts             |   19 ++
 arch/arm64/boot/dts/mediatek/mt8370.dtsi                          |   64 ++++
 arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts             | 1033 +----------------------------------------------------------
 arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi             | 1223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts            |  102 ++++++
 arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso |   84 +++++
 arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts             |   71 +++++
 26 files changed, 3051 insertions(+), 1128 deletions(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8370-genio-510-evk.dts
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8370.dtsi
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l-8-hd-panel.dtso


From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:58 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:58 +0100
Subject: [PATCH v10 09/18] arm64: dts: imx8mq: add anatop clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-10-dario.binacchi@amarulasolutions.com>

Add clocks to anatop node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index d51de8d899b2..1d1424a136f0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -817,6 +817,8 @@ anatop: clock-controller at 30360000 {
 				reg = <0x30360000 0x10000>;
 				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
 				#clock-cells = <1>;
+				clocks = <&ckil>, <&osc_25m>, <&osc_27m>;
+				clock-names = "ckil", "osc_25m", "osc_27m";
 			};
 
 			snvs: snvs at 30370000 {
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:59 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:59 +0100
Subject: [PATCH v10 10/18] clk: imx: add hw API imx_anatop_get_clk_hw
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-11-dario.binacchi@amarulasolutions.com>

Get the hw of a clock registered by the anatop module. This function is
preparatory for future developments.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>

---

(no changes since v9)

Changes in v9:
- Add 'Reviewed-by' tag of Peng Fan

Changes in v7:
- Add device_node type parameter to imx8m_anatop_get_clk_hw()
- Rename imx8m_anatop_get_clk_hw() to imx_anatop_get_clk_hw()
- Drop the gaurding macros so the code can be used also by i.MX9

Changes in v5:
- Consider CONFIG_CLK_IMX8M{M,N,P,Q}_MODULE to fix compilation errors

Changes in v4:
- New

 drivers/clk/imx/clk.c | 15 +++++++++++++++
 drivers/clk/imx/clk.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index df83bd939492..a906d3cd960b 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -128,6 +128,21 @@ struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name)
 }
 EXPORT_SYMBOL_GPL(imx_get_clk_hw_by_name);
 
+struct clk_hw *imx_anatop_get_clk_hw(struct device_node *np, int id)
+{
+	struct of_phandle_args args;
+	struct clk_hw *hw;
+
+	args.np = np;
+	args.args_count = 1;
+	args.args[0] = id;
+
+	hw = __clk_get_hw(of_clk_get_from_provider(&args));
+	pr_debug("%s: got clk: %s\n", __func__, clk_hw_get_name(hw));
+	return hw;
+}
+EXPORT_SYMBOL_GPL(imx_anatop_get_clk_hw);
+
 /*
  * This fixups the register CCM_CSCMR1 write value.
  * The write/read/divider values of the aclk_podf field
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index aa5202f284f3..50e407cf48d9 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -487,4 +487,6 @@ struct clk_hw *imx_clk_gpr_mux(const char *name, const char *compatible,
 			       u32 reg, const char **parent_names,
 			       u8 num_parents, const u32 *mux_table, u32 mask);
 
+struct clk_hw *imx_anatop_get_clk_hw(struct device_node *np, int id);
+
 #endif
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:00 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:00 +0100
Subject: [PATCH v10 11/18] clk: imx: add support for i.MX8MM anatop clock driver
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-12-dario.binacchi@amarulasolutions.com>

Support NXP i.MX8M anatop PLL module which generates PLLs to CCM root.
By doing so, we also simplify the CCM driver code. The changes are
backward compatible.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
---

(no changes since v1)

 drivers/clk/imx/Makefile            |   2 +-
 drivers/clk/imx/clk-imx8mm-anatop.c | 287 ++++++++++++++++++++++++++++
 drivers/clk/imx/clk-imx8mm.c        | 172 ++++++++---------
 3 files changed, 367 insertions(+), 94 deletions(-)
 create mode 100644 drivers/clk/imx/clk-imx8mm-anatop.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 03f2b2a1ab63..bf35b1236591 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -25,7 +25,7 @@ mxc-clk-objs += clk-sscg-pll.o
 mxc-clk-objs += clk-gpr-mux.o
 obj-$(CONFIG_MXC_CLK) += mxc-clk.o
 
-obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
+obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm-anatop.o clk-imx8mm.o
 obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
 obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mm-anatop.c b/drivers/clk/imx/clk-imx8mm-anatop.c
new file mode 100644
index 000000000000..4ac870df6370
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mm-anatop.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-imx8mm-anatop.c - NXP i.MX8MM anatop clock driver
+ *
+ * Copyright (c) 2025 Dario Binacchi <dario.binacchi at amarulasolutions.com>
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+
+#include "clk.h"
+
+#define IMX8MM_ANATOP_CLK_END		(IMX8MM_ANATOP_CLK_CLKOUT2 + 1)
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
+					   "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
+					   "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
+					   "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
+
+static struct clk_hw_onecell_data *clk_hw_data;
+static struct clk_hw **hws;
+
+static int imx8mm_anatop_clocks_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	void __iomem *base;
+	int ret;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base)) {
+		dev_err(dev, "failed to get base address\n");
+		return PTR_ERR(base);
+	}
+
+	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+						    IMX8MM_ANATOP_CLK_END),
+				   GFP_KERNEL);
+	if (WARN_ON(!clk_hw_data))
+		return -ENOMEM;
+
+	clk_hw_data->num = IMX8MM_ANATOP_CLK_END;
+	hws = clk_hw_data->hws;
+
+	hws[IMX8MM_ANATOP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
+	hws[IMX8MM_ANATOP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	hws[IMX8MM_ANATOP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+
+	hws[IMX8MM_ANATOP_AUDIO_PLL1_REF_SEL] =
+		imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_AUDIO_PLL2_REF_SEL] =
+		imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_VIDEO_PLL_REF_SEL] =
+		imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_DRAM_PLL_REF_SEL] =
+		imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_GPU_PLL_REF_SEL] =
+		imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_VPU_PLL_REF_SEL] =
+		imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_ARM_PLL_REF_SEL] =
+		imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MM_ANATOP_SYS_PLL3_REF_SEL] =
+		imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+	hws[IMX8MM_ANATOP_AUDIO_PLL1] =
+		imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel",
+				   base, &imx_1443x_pll);
+	hws[IMX8MM_ANATOP_AUDIO_PLL2] =
+		imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel",
+				   base + 0x14, &imx_1443x_pll);
+	hws[IMX8MM_ANATOP_VIDEO_PLL] =
+		imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel",
+				   base + 0x28, &imx_1443x_pll);
+	hws[IMX8MM_ANATOP_DRAM_PLL] =
+		imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel",
+				   base + 0x50, &imx_1443x_dram_pll);
+	hws[IMX8MM_ANATOP_GPU_PLL] =
+		imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel",
+				   base + 0x64, &imx_1416x_pll);
+	hws[IMX8MM_ANATOP_VPU_PLL] =
+		imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel",
+				   base + 0x74, &imx_1416x_pll);
+	hws[IMX8MM_ANATOP_ARM_PLL] =
+		imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel",
+				   base + 0x84, &imx_1416x_pll);
+	hws[IMX8MM_ANATOP_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000);
+	hws[IMX8MM_ANATOP_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000);
+	hws[IMX8MM_ANATOP_SYS_PLL3] =
+		imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel",
+				   base + 0x114, &imx_1416x_pll);
+
+	/* PLL bypass out */
+	hws[IMX8MM_ANATOP_AUDIO_PLL1_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1,
+				     audio_pll1_bypass_sels,
+				     ARRAY_SIZE(audio_pll1_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_AUDIO_PLL2_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1,
+				     audio_pll2_bypass_sels,
+				     ARRAY_SIZE(audio_pll2_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_VIDEO_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1,
+				     video_pll_bypass_sels,
+				     ARRAY_SIZE(video_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_DRAM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1,
+				     dram_pll_bypass_sels,
+				     ARRAY_SIZE(dram_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_GPU_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1,
+				     gpu_pll_bypass_sels,
+				     ARRAY_SIZE(gpu_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_VPU_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1,
+				     vpu_pll_bypass_sels,
+				     ARRAY_SIZE(vpu_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_ARM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1,
+				     arm_pll_bypass_sels,
+				     ARRAY_SIZE(arm_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MM_ANATOP_SYS_PLL3_BYPASS] =
+		imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1,
+				     sys_pll3_bypass_sels,
+				     ARRAY_SIZE(sys_pll3_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+
+	/* PLL out gate */
+	hws[IMX8MM_ANATOP_AUDIO_PLL1_OUT] =
+		imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass",
+				base, 13);
+	hws[IMX8MM_ANATOP_AUDIO_PLL2_OUT] =
+		imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass",
+				base + 0x14, 13);
+	hws[IMX8MM_ANATOP_VIDEO_PLL_OUT] =
+		imx_clk_hw_gate("video_pll_out", "video_pll_bypass",
+				base + 0x28, 13);
+	hws[IMX8MM_ANATOP_DRAM_PLL_OUT] =
+		imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass",
+				base + 0x50, 13);
+	hws[IMX8MM_ANATOP_GPU_PLL_OUT] =
+		imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass",
+				base + 0x64, 11);
+	hws[IMX8MM_ANATOP_VPU_PLL_OUT] =
+		imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass",
+				base + 0x74, 11);
+	hws[IMX8MM_ANATOP_ARM_PLL_OUT] =
+		imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass",
+				base + 0x84, 11);
+	hws[IMX8MM_ANATOP_SYS_PLL3_OUT] =
+		imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass",
+				base + 0x114, 11);
+
+	/* SYS PLL1 fixed output */
+	hws[IMX8MM_ANATOP_SYS_PLL1_OUT] =
+		imx_clk_hw_gate("sys_pll1_out", "sys_pll1",
+				base + 0x94, 11);
+
+	hws[IMX8MM_ANATOP_SYS_PLL1_40M] =
+		imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+	hws[IMX8MM_ANATOP_SYS_PLL1_80M] =
+		imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+	hws[IMX8MM_ANATOP_SYS_PLL1_100M] =
+		imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+	hws[IMX8MM_ANATOP_SYS_PLL1_133M] =
+		imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+	hws[IMX8MM_ANATOP_SYS_PLL1_160M] =
+		imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+	hws[IMX8MM_ANATOP_SYS_PLL1_200M] =
+		imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+	hws[IMX8MM_ANATOP_SYS_PLL1_266M] =
+		imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+	hws[IMX8MM_ANATOP_SYS_PLL1_400M] =
+		imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+	hws[IMX8MM_ANATOP_SYS_PLL1_800M] =
+		imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+	/* SYS PLL2 fixed output */
+	hws[IMX8MM_ANATOP_SYS_PLL2_OUT] =
+		imx_clk_hw_gate("sys_pll2_out", "sys_pll2",
+				base + 0x104, 11);
+
+	hws[IMX8MM_ANATOP_SYS_PLL2_50M] =
+		imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+	hws[IMX8MM_ANATOP_SYS_PLL2_100M] =
+		imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+	hws[IMX8MM_ANATOP_SYS_PLL2_125M] =
+		imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+	hws[IMX8MM_ANATOP_SYS_PLL2_166M] =
+		imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+	hws[IMX8MM_ANATOP_SYS_PLL2_200M] =
+		imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+	hws[IMX8MM_ANATOP_SYS_PLL2_250M] =
+		imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+	hws[IMX8MM_ANATOP_SYS_PLL2_333M] =
+		imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+	hws[IMX8MM_ANATOP_SYS_PLL2_500M] =
+		imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+	hws[IMX8MM_ANATOP_SYS_PLL2_1000M] =
+		imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+	hws[IMX8MM_ANATOP_CLK_CLKOUT1_SEL] =
+		imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MM_ANATOP_CLK_CLKOUT1_DIV] =
+		imx_clk_hw_divider("clkout1_div", "clkout1_sel",
+				   base + 0x128, 0, 4);
+	hws[IMX8MM_ANATOP_CLK_CLKOUT1] =
+		imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
+	hws[IMX8MM_ANATOP_CLK_CLKOUT2_SEL] =
+		imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MM_ANATOP_CLK_CLKOUT2_DIV] =
+		imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128,
+				   16, 4);
+	hws[IMX8MM_ANATOP_CLK_CLKOUT2] =
+		imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
+
+	imx_check_clk_hws(hws, IMX8MM_ANATOP_CLK_END);
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+	if (ret < 0) {
+		imx_unregister_hw_clocks(hws, IMX8MM_ANATOP_CLK_END);
+		return dev_err_probe(dev, ret,
+				     "failed to register anatop clock provider\n");
+	}
+
+	dev_info(dev, "NXP i.MX8MM anatop clock driver probed\n");
+	return 0;
+}
+
+static const struct of_device_id imx8mm_anatop_clk_of_match[] = {
+	{ .compatible = "fsl,imx8mm-anatop" },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mm_anatop_clk_of_match);
+
+static struct platform_driver imx8mm_anatop_clk_driver = {
+	.probe = imx8mm_anatop_clocks_probe,
+	.driver = {
+		.name = "imx8mm-anatop",
+		/*
+		 * Disable bind attributes: clocks are not removed and
+		 * reloading the driver will crash or break devices.
+		 */
+		.suppress_bind_attrs = true,
+		.of_match_table = imx8mm_anatop_clk_of_match,
+	},
+};
+
+module_platform_driver(imx8mm_anatop_clk_driver);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi at amarulasolutions.com>");
+MODULE_DESCRIPTION("NXP i.MX8MM anatop clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 8a1fc7e17ba2..d39de0a81a6f 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -25,16 +25,6 @@ static u32 share_count_disp;
 static u32 share_count_pdm;
 static u32 share_count_nand;
 
-static const char *pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
-static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
-static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char *video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
-static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
-static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
-static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
-static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
-static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
-
 /* CCM ROOT */
 static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
 					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
@@ -288,21 +278,20 @@ static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", "
 static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", "sys_pll2_166m",
 					  "sys_pll3_out", "audio_pll1_out", "video_pll_out", "osc_32k", };
 
-static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
-					   "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
-					   "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
-					   "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
-
 static struct clk_hw_onecell_data *clk_hw_data;
 static struct clk_hw **hws;
 
 static int imx8mm_clocks_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *anp;
 	void __iomem *base;
 	int ret;
 
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (WARN_ON(IS_ERR(base)))
+		return PTR_ERR(base);
+
 	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
 					  IMX8MM_CLK_END), GFP_KERNEL);
 	if (WARN_ON(!clk_hw_data))
@@ -311,96 +300,92 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 	clk_hw_data->num = IMX8MM_CLK_END;
 	hws = clk_hw_data->hws;
 
-	hws[IMX8MM_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
-	hws[IMX8MM_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
-	hws[IMX8MM_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	anp = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
+	if (!anp)
+		return dev_err_probe(dev, -ENODEV, "missing anatop\n");
+
+	of_node_put(anp);
+
+	hws[IMX8MM_CLK_DUMMY] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_DUMMY);
+	hws[IMX8MM_CLK_24M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_24M);
+	hws[IMX8MM_CLK_32K] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_32K);
 	hws[IMX8MM_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
 	hws[IMX8MM_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
 	hws[IMX8MM_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
 	hws[IMX8MM_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
-	base = of_iomap(np, 0);
-	of_node_put(np);
-	if (WARN_ON(!base))
-		return -ENOMEM;
-
-	hws[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MM_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-
-	hws[IMX8MM_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll);
-	hws[IMX8MM_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll);
-	hws[IMX8MM_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", base + 0x28, &imx_1443x_pll);
-	hws[IMX8MM_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll);
-	hws[IMX8MM_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll);
-	hws[IMX8MM_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll);
-	hws[IMX8MM_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll);
-	hws[IMX8MM_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000);
-	hws[IMX8MM_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000);
-	hws[IMX8MM_SYS_PLL3] = imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx_1416x_pll);
+	hws[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL1_REF_SEL);
+	hws[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL2_REF_SEL);
+	hws[IMX8MM_VIDEO_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VIDEO_PLL_REF_SEL);
+	hws[IMX8MM_DRAM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_DRAM_PLL_REF_SEL);
+	hws[IMX8MM_GPU_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_GPU_PLL_REF_SEL);
+	hws[IMX8MM_VPU_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VPU_PLL_REF_SEL);
+	hws[IMX8MM_ARM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_ARM_PLL_REF_SEL);
+	hws[IMX8MM_SYS_PLL3_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL3_REF_SEL);
+
+	hws[IMX8MM_AUDIO_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL1);
+	hws[IMX8MM_AUDIO_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL2);
+	hws[IMX8MM_VIDEO_PLL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VIDEO_PLL);
+	hws[IMX8MM_DRAM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_DRAM_PLL);
+	hws[IMX8MM_GPU_PLL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_GPU_PLL);
+	hws[IMX8MM_VPU_PLL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VPU_PLL);
+	hws[IMX8MM_ARM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_ARM_PLL);
+	hws[IMX8MM_SYS_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1);
+	hws[IMX8MM_SYS_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2);
+	hws[IMX8MM_SYS_PLL3] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL3);
 
 	/* PLL bypass out */
-	hws[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MM_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+	hws[IMX8MM_AUDIO_PLL1_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL1_BYPASS);
+	hws[IMX8MM_AUDIO_PLL2_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL2_BYPASS);
+	hws[IMX8MM_VIDEO_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VIDEO_PLL_BYPASS);
+	hws[IMX8MM_DRAM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_DRAM_PLL_BYPASS);
+	hws[IMX8MM_GPU_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_GPU_PLL_BYPASS);
+	hws[IMX8MM_VPU_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VPU_PLL_BYPASS);
+	hws[IMX8MM_ARM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_ARM_PLL_BYPASS);
+	hws[IMX8MM_SYS_PLL3_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL3_BYPASS);
 
 	/* PLL out gate */
-	hws[IMX8MM_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
-	hws[IMX8MM_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
-	hws[IMX8MM_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", base + 0x28, 13);
-	hws[IMX8MM_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
-	hws[IMX8MM_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
-	hws[IMX8MM_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11);
-	hws[IMX8MM_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11);
-	hws[IMX8MM_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
+	hws[IMX8MM_AUDIO_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL1_OUT);
+	hws[IMX8MM_AUDIO_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_AUDIO_PLL2_OUT);
+	hws[IMX8MM_VIDEO_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VIDEO_PLL_OUT);
+	hws[IMX8MM_DRAM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_DRAM_PLL_OUT);
+	hws[IMX8MM_GPU_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_GPU_PLL_OUT);
+	hws[IMX8MM_VPU_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_VPU_PLL_OUT);
+	hws[IMX8MM_ARM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_ARM_PLL_OUT);
+	hws[IMX8MM_SYS_PLL3_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL3_OUT);
 
 	/* SYS PLL1 fixed output */
-	hws[IMX8MM_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11);
-
-	hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
-	hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
-	hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
-	hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
-	hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
-	hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
-	hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
-	hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
-	hws[IMX8MM_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+	hws[IMX8MM_SYS_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_OUT);
+
+	hws[IMX8MM_SYS_PLL1_40M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_40M);
+	hws[IMX8MM_SYS_PLL1_80M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_80M);
+	hws[IMX8MM_SYS_PLL1_100M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_100M);
+	hws[IMX8MM_SYS_PLL1_133M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_133M);
+	hws[IMX8MM_SYS_PLL1_160M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_160M);
+	hws[IMX8MM_SYS_PLL1_200M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_200M);
+	hws[IMX8MM_SYS_PLL1_266M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_266M);
+	hws[IMX8MM_SYS_PLL1_400M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_400M);
+	hws[IMX8MM_SYS_PLL1_800M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL1_800M);
 
 	/* SYS PLL2 fixed output */
-	hws[IMX8MM_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11);
-	hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
-	hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
-	hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
-	hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
-	hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
-	hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
-	hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
-	hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
-	hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
-
-	hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
-	hws[IMX8MM_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
-	hws[IMX8MM_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
-	hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
-	hws[IMX8MM_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
-	hws[IMX8MM_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
-
-	np = dev->of_node;
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (WARN_ON(IS_ERR(base)))
-		return PTR_ERR(base);
+	hws[IMX8MM_SYS_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_OUT);
+
+	hws[IMX8MM_SYS_PLL2_50M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_50M);
+	hws[IMX8MM_SYS_PLL2_100M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_100M);
+	hws[IMX8MM_SYS_PLL2_125M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_125M);
+	hws[IMX8MM_SYS_PLL2_166M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_166M);
+	hws[IMX8MM_SYS_PLL2_200M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_200M);
+	hws[IMX8MM_SYS_PLL2_250M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_250M);
+	hws[IMX8MM_SYS_PLL2_333M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_333M);
+	hws[IMX8MM_SYS_PLL2_500M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_500M);
+	hws[IMX8MM_SYS_PLL2_1000M] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_SYS_PLL2_1000M);
+
+	hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT1_SEL);
+	hws[IMX8MM_CLK_CLKOUT1_DIV] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT1_DIV);
+	hws[IMX8MM_CLK_CLKOUT1] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT1);
+	hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT2_SEL);
+	hws[IMX8MM_CLK_CLKOUT2_DIV] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT2_DIV);
+	hws[IMX8MM_CLK_CLKOUT2] = imx_anatop_get_clk_hw(anp, IMX8MM_ANATOP_CLK_CLKOUT2);
 
 	/* Core Slice */
 	hws[IMX8MM_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mm_a53_sels, base + 0x8000);
@@ -611,6 +596,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
 
 	imx_register_uart_clocks();
 
+	dev_info(dev, "NXP i.MX8MM ccm clock driver probed\n");
 	return 0;
 
 unregister_hws:
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:01 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:01 +0100
Subject: [PATCH v10 12/18] clk: imx: add support for i.MX8MN anatop clock driver
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-13-dario.binacchi@amarulasolutions.com>

Support NXP i.MX8M anatop PLL module which generates PLLs to CCM root.
By doing so, we also simplify the CCM driver code. The changes are
backward compatible.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>


---

(no changes since v9)

Changes in v9:
- Fix a build warning raised by the kernel test robot
- Add 'Reviewed-by' tag of Peng Fan

Changes in v8:
- Drop call of of_parse_phandle() to get the anatop's device node.

Changes in v7:
- Update the code based on the changes made to the
  imx8m_anatop_get_clk_hw():
  - Rename imx8m_anatop_get_clk_hw to imx_anatop_get_clk_hw
  - Add device_node type parameter
- Call of_parse_phandle() to get the anatop's device node.

Changes in v6:
- Define IMX8MN_ANATOP_CLK_END inside the driver after it has ben
  removed from include/dt-bindings/clock/imx8mn-clock.h.

Changes in v4:
- New

 drivers/clk/imx/Makefile            |   2 +-
 drivers/clk/imx/clk-imx8mn-anatop.c | 283 ++++++++++++++++++++++++++++
 drivers/clk/imx/clk-imx8mn.c        | 183 ++++++++----------
 3 files changed, 364 insertions(+), 104 deletions(-)
 create mode 100644 drivers/clk/imx/clk-imx8mn-anatop.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index bf35b1236591..8e0f42a0c69c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -26,7 +26,7 @@ mxc-clk-objs += clk-gpr-mux.o
 obj-$(CONFIG_MXC_CLK) += mxc-clk.o
 
 obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm-anatop.o clk-imx8mm.o
-obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
+obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn-anatop.o clk-imx8mn.o
 obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
 
diff --git a/drivers/clk/imx/clk-imx8mn-anatop.c b/drivers/clk/imx/clk-imx8mn-anatop.c
new file mode 100644
index 000000000000..5091794948eb
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mn-anatop.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-imx8mn-anatop.c - NXP i.MX8MN anatop clock driver
+ *
+ * Copyright (c) 2024 Dario Binacchi <dario.binacchi at amarulasolutions.com>
+ */
+
+#include <dt-bindings/clock/imx8mn-clock.h>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+
+#include "clk.h"
+
+#define IMX8MN_ANATOP_CLK_END		(IMX8MN_ANATOP_CLK_CLKOUT2 + 1)
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const m7_alt_pll_bypass_sels[] = {"m7_alt_pll", "m7_alt_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
+					   "dummy", "dummy", "gpu_pll_out", "dummy",
+					   "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
+					   "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
+
+static struct clk_hw_onecell_data *clk_hw_data;
+static struct clk_hw **hws;
+
+static int imx8mn_anatop_clocks_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	void __iomem *base;
+	int ret;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base)) {
+		dev_err(dev, "failed to get base address\n");
+		return PTR_ERR(base);
+	}
+
+	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+						    IMX8MN_ANATOP_CLK_END),
+				   GFP_KERNEL);
+	if (WARN_ON(!clk_hw_data))
+		return -ENOMEM;
+
+	clk_hw_data->num = IMX8MN_ANATOP_CLK_END;
+	hws = clk_hw_data->hws;
+
+	hws[IMX8MN_ANATOP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
+	hws[IMX8MN_ANATOP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	hws[IMX8MN_ANATOP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+
+	hws[IMX8MN_ANATOP_AUDIO_PLL1_REF_SEL] =
+		imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_AUDIO_PLL2_REF_SEL] =
+		imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_VIDEO_PLL_REF_SEL] =
+		imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_DRAM_PLL_REF_SEL] =
+		imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_GPU_PLL_REF_SEL] =
+		imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_M7_ALT_PLL_REF_SEL] =
+		imx_clk_hw_mux("m7_alt_pll_ref_sel", base + 0x74, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_ARM_PLL_REF_SEL] =
+		imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MN_ANATOP_SYS_PLL3_REF_SEL] =
+		imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+	hws[IMX8MN_ANATOP_AUDIO_PLL1] =
+		imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel",
+				   base, &imx_1443x_pll);
+	hws[IMX8MN_ANATOP_AUDIO_PLL2] =
+		imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel",
+				   base + 0x14, &imx_1443x_pll);
+	hws[IMX8MN_ANATOP_VIDEO_PLL] =
+		imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel",
+				   base + 0x28, &imx_1443x_pll);
+	hws[IMX8MN_ANATOP_DRAM_PLL] =
+		imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50,
+				   &imx_1443x_dram_pll);
+	hws[IMX8MN_ANATOP_GPU_PLL] =
+		imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64,
+				   &imx_1416x_pll);
+	hws[IMX8MN_ANATOP_M7_ALT_PLL] =
+		imx_clk_hw_pll14xx("m7_alt_pll", "m7_alt_pll_ref_sel",
+				   base + 0x74, &imx_1416x_pll);
+	hws[IMX8MN_ANATOP_ARM_PLL] =
+		imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84,
+				   &imx_1416x_pll);
+	hws[IMX8MN_ANATOP_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000);
+	hws[IMX8MN_ANATOP_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000);
+	hws[IMX8MN_ANATOP_SYS_PLL3] =
+		imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114,
+				   &imx_1416x_pll);
+
+	/* PLL bypass out */
+	hws[IMX8MN_ANATOP_AUDIO_PLL1_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1,
+				     audio_pll1_bypass_sels,
+				     ARRAY_SIZE(audio_pll1_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_AUDIO_PLL2_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1,
+				     audio_pll2_bypass_sels,
+				     ARRAY_SIZE(audio_pll2_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_VIDEO_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1,
+				     video_pll_bypass_sels,
+				     ARRAY_SIZE(video_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_DRAM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1,
+				     dram_pll_bypass_sels,
+				     ARRAY_SIZE(dram_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_GPU_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1,
+				     gpu_pll_bypass_sels,
+				     ARRAY_SIZE(gpu_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_M7_ALT_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("m7_alt_pll_bypass", base + 0x74, 28, 1,
+				     m7_alt_pll_bypass_sels,
+				     ARRAY_SIZE(m7_alt_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_ARM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1,
+				     arm_pll_bypass_sels,
+				     ARRAY_SIZE(arm_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MN_ANATOP_SYS_PLL3_BYPASS] =
+		imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1,
+				     sys_pll3_bypass_sels,
+				     ARRAY_SIZE(sys_pll3_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+
+	/* PLL out gate */
+	hws[IMX8MN_ANATOP_AUDIO_PLL1_OUT] =
+		imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass",
+				base, 13);
+	hws[IMX8MN_ANATOP_AUDIO_PLL2_OUT] =
+		imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass",
+				base + 0x14, 13);
+	hws[IMX8MN_ANATOP_VIDEO_PLL_OUT] =
+		imx_clk_hw_gate("video_pll_out", "video_pll_bypass",
+				base + 0x28, 13);
+	hws[IMX8MN_ANATOP_DRAM_PLL_OUT] =
+		imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass",
+				base + 0x50, 13);
+	hws[IMX8MN_ANATOP_GPU_PLL_OUT] =
+		imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass",
+				base + 0x64, 11);
+	hws[IMX8MN_ANATOP_M7_ALT_PLL_OUT] =
+		imx_clk_hw_gate("m7_alt_pll_out", "m7_alt_pll_bypass",
+				base + 0x74, 11);
+	hws[IMX8MN_ANATOP_ARM_PLL_OUT] =
+		imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass",
+				base + 0x84, 11);
+	hws[IMX8MN_ANATOP_SYS_PLL3_OUT] =
+		imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass",
+				base + 0x114, 11);
+
+	/* SYS PLL1 fixed output */
+	hws[IMX8MN_ANATOP_SYS_PLL1_OUT] =
+		imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11);
+	hws[IMX8MN_ANATOP_SYS_PLL1_40M] =
+		imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+	hws[IMX8MN_ANATOP_SYS_PLL1_80M] =
+		imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+	hws[IMX8MN_ANATOP_SYS_PLL1_100M] =
+		imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+	hws[IMX8MN_ANATOP_SYS_PLL1_133M] =
+		imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+	hws[IMX8MN_ANATOP_SYS_PLL1_160M] =
+		imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+	hws[IMX8MN_ANATOP_SYS_PLL1_200M] =
+		imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+	hws[IMX8MN_ANATOP_SYS_PLL1_266M] =
+		imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+	hws[IMX8MN_ANATOP_SYS_PLL1_400M] =
+		imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+	hws[IMX8MN_ANATOP_SYS_PLL1_800M] =
+		imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+	/* SYS PLL2 fixed output */
+	hws[IMX8MN_ANATOP_SYS_PLL2_OUT] =
+		imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11);
+	hws[IMX8MN_ANATOP_SYS_PLL2_50M] =
+		imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+	hws[IMX8MN_ANATOP_SYS_PLL2_100M] =
+		imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+	hws[IMX8MN_ANATOP_SYS_PLL2_125M] =
+		imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+	hws[IMX8MN_ANATOP_SYS_PLL2_166M] =
+		imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+	hws[IMX8MN_ANATOP_SYS_PLL2_200M] =
+		imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+	hws[IMX8MN_ANATOP_SYS_PLL2_250M] =
+		imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+	hws[IMX8MN_ANATOP_SYS_PLL2_333M] =
+		imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+	hws[IMX8MN_ANATOP_SYS_PLL2_500M] =
+		imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+	hws[IMX8MN_ANATOP_SYS_PLL2_1000M] =
+		imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+	hws[IMX8MN_ANATOP_CLK_CLKOUT1_SEL] =
+		imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MN_ANATOP_CLK_CLKOUT1_DIV] =
+		imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128,
+				   0, 4);
+	hws[IMX8MN_ANATOP_CLK_CLKOUT1] =
+		imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
+	hws[IMX8MN_ANATOP_CLK_CLKOUT2_SEL] =
+		imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MN_ANATOP_CLK_CLKOUT2_DIV] =
+		imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128,
+				   16, 4);
+	hws[IMX8MN_ANATOP_CLK_CLKOUT2] =
+		imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
+
+	imx_check_clk_hws(hws, IMX8MN_ANATOP_CLK_END);
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+	if (ret < 0) {
+		imx_unregister_hw_clocks(hws, IMX8MN_ANATOP_CLK_END);
+		return dev_err_probe(dev, ret,
+				     "failed to register anatop clock provider\n");
+	}
+
+	dev_info(dev, "NXP i.MX8MN anatop clock driver probed\n");
+	return 0;
+}
+
+static const struct of_device_id imx8mn_anatop_clk_of_match[] = {
+	{ .compatible = "fsl,imx8mn-anatop" },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mn_anatop_clk_of_match);
+
+static struct platform_driver imx8mn_anatop_clk_driver = {
+	.probe = imx8mn_anatop_clocks_probe,
+	.driver = {
+		.name = "imx8mn-anatop",
+		/*
+		 * Disable bind attributes: clocks are not removed and
+		 * reloading the driver will crash or break devices.
+		 */
+		.suppress_bind_attrs = true,
+		.of_match_table = imx8mn_anatop_clk_of_match,
+	},
+};
+
+module_platform_driver(imx8mn_anatop_clk_driver);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi at amarulasolutions.com>");
+MODULE_DESCRIPTION("NXP i.MX8MN anatop clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index ab77e148e70c..c3a3d063d58e 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -24,16 +24,6 @@ static u32 share_count_disp;
 static u32 share_count_pdm;
 static u32 share_count_nand;
 
-static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
-static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
-static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
-static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
-static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
-static const char * const m7_alt_pll_bypass_sels[] = {"m7_alt_pll", "m7_alt_pll_ref_sel", };
-static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
-static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
-
 static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m",
 					       "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
 					       "audio_pll1_out", "sys_pll3_out", };
@@ -308,21 +298,20 @@ static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sy
 						 "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
 						 "video_pll_out", "osc_32k", };
 
-static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
-					   "dummy", "dummy", "gpu_pll_out", "dummy",
-					   "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
-					   "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
-
 static struct clk_hw_onecell_data *clk_hw_data;
 static struct clk_hw **hws;
 
 static int imx8mn_clocks_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *anp;
 	void __iomem *base;
 	int ret;
 
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (WARN_ON(IS_ERR(base)))
+		return PTR_ERR(base);
+
 	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
 					  IMX8MN_CLK_END), GFP_KERNEL);
 	if (WARN_ON(!clk_hw_data))
@@ -331,99 +320,90 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
 	clk_hw_data->num = IMX8MN_CLK_END;
 	hws = clk_hw_data->hws;
 
-	hws[IMX8MN_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
-	hws[IMX8MN_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
-	hws[IMX8MN_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	anp = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
+	if (!anp)
+		return dev_err_probe(dev, -ENODEV, "missing anatop\n");
+
+	of_node_put(anp);
+
+	hws[IMX8MN_CLK_DUMMY] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_DUMMY);
+	hws[IMX8MN_CLK_24M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_24M);
+	hws[IMX8MN_CLK_32K] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_32K);
 	hws[IMX8MN_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
 	hws[IMX8MN_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
 	hws[IMX8MN_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
 	hws[IMX8MN_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
-	base = devm_of_iomap(dev, np, 0, NULL);
-	of_node_put(np);
-	if (WARN_ON(IS_ERR(base))) {
-		ret = PTR_ERR(base);
-		goto unregister_hws;
-	}
-
-	hws[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_M7_ALT_PLL_REF_SEL] = imx_clk_hw_mux("m7_alt_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-
-	hws[IMX8MN_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll);
-	hws[IMX8MN_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll);
-	hws[IMX8MN_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", base + 0x28, &imx_1443x_pll);
-	hws[IMX8MN_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll);
-	hws[IMX8MN_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll);
-	hws[IMX8MN_M7_ALT_PLL] = imx_clk_hw_pll14xx("m7_alt_pll", "m7_alt_pll_ref_sel", base + 0x74, &imx_1416x_pll);
-	hws[IMX8MN_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll);
-	hws[IMX8MN_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000);
-	hws[IMX8MN_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000);
-	hws[IMX8MN_SYS_PLL3] = imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx_1416x_pll);
+	hws[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL1_REF_SEL);
+	hws[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL2_REF_SEL);
+	hws[IMX8MN_VIDEO_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_VIDEO_PLL_REF_SEL);
+	hws[IMX8MN_DRAM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_DRAM_PLL_REF_SEL);
+	hws[IMX8MN_GPU_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_GPU_PLL_REF_SEL);
+	hws[IMX8MN_M7_ALT_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_M7_ALT_PLL_REF_SEL);
+	hws[IMX8MN_ARM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_ARM_PLL_REF_SEL);
+	hws[IMX8MN_SYS_PLL3_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL3_REF_SEL);
+
+	hws[IMX8MN_AUDIO_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL1);
+	hws[IMX8MN_AUDIO_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL2);
+	hws[IMX8MN_VIDEO_PLL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_VIDEO_PLL);
+	hws[IMX8MN_DRAM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_DRAM_PLL);
+	hws[IMX8MN_GPU_PLL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_GPU_PLL);
+	hws[IMX8MN_M7_ALT_PLL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_M7_ALT_PLL);
+	hws[IMX8MN_ARM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_ARM_PLL);
+	hws[IMX8MN_SYS_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1);
+	hws[IMX8MN_SYS_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2);
+	hws[IMX8MN_SYS_PLL3] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL3);
 
 	/* PLL bypass out */
-	hws[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_M7_ALT_PLL_BYPASS] = imx_clk_hw_mux_flags("m7_alt_pll_bypass", base + 0x74, 28, 1, m7_alt_pll_bypass_sels, ARRAY_SIZE(m7_alt_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+	hws[IMX8MN_AUDIO_PLL1_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL1_BYPASS);
+	hws[IMX8MN_AUDIO_PLL2_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL2_BYPASS);
+	hws[IMX8MN_VIDEO_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_VIDEO_PLL_BYPASS);
+	hws[IMX8MN_DRAM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_DRAM_PLL_BYPASS);
+	hws[IMX8MN_GPU_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_GPU_PLL_BYPASS);
+	hws[IMX8MN_M7_ALT_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_M7_ALT_PLL_BYPASS);
+	hws[IMX8MN_ARM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_ARM_PLL_BYPASS);
+	hws[IMX8MN_SYS_PLL3_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL3_BYPASS);
 
 	/* PLL out gate */
-	hws[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
-	hws[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
-	hws[IMX8MN_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", base + 0x28, 13);
-	hws[IMX8MN_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
-	hws[IMX8MN_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
-	hws[IMX8MN_M7_ALT_PLL_OUT] = imx_clk_hw_gate("m7_alt_pll_out", "m7_alt_pll_bypass", base + 0x74, 11);
-	hws[IMX8MN_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11);
-	hws[IMX8MN_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
+	hws[IMX8MN_AUDIO_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL1_OUT);
+	hws[IMX8MN_AUDIO_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_AUDIO_PLL2_OUT);
+	hws[IMX8MN_VIDEO_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_VIDEO_PLL_OUT);
+	hws[IMX8MN_DRAM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_DRAM_PLL_OUT);
+	hws[IMX8MN_GPU_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_GPU_PLL_OUT);
+	hws[IMX8MN_M7_ALT_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_M7_ALT_PLL_OUT);
+	hws[IMX8MN_ARM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_ARM_PLL_OUT);
+	hws[IMX8MN_SYS_PLL3_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL3_OUT);
 
 	/* SYS PLL1 fixed output */
-	hws[IMX8MN_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11);
-	hws[IMX8MN_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
-	hws[IMX8MN_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
-	hws[IMX8MN_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
-	hws[IMX8MN_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
-	hws[IMX8MN_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
-	hws[IMX8MN_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
-	hws[IMX8MN_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
-	hws[IMX8MN_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
-	hws[IMX8MN_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+	hws[IMX8MN_SYS_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_OUT);
+	hws[IMX8MN_SYS_PLL1_40M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_40M);
+	hws[IMX8MN_SYS_PLL1_80M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_80M);
+	hws[IMX8MN_SYS_PLL1_100M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_100M);
+	hws[IMX8MN_SYS_PLL1_133M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_133M);
+	hws[IMX8MN_SYS_PLL1_160M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_160M);
+	hws[IMX8MN_SYS_PLL1_200M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_200M);
+	hws[IMX8MN_SYS_PLL1_266M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_266M);
+	hws[IMX8MN_SYS_PLL1_400M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_400M);
+	hws[IMX8MN_SYS_PLL1_800M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL1_800M);
 
 	/* SYS PLL2 fixed output */
-	hws[IMX8MN_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11);
-	hws[IMX8MN_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
-	hws[IMX8MN_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
-	hws[IMX8MN_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
-	hws[IMX8MN_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
-	hws[IMX8MN_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
-	hws[IMX8MN_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
-	hws[IMX8MN_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
-	hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
-	hws[IMX8MN_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
-
-	hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
-	hws[IMX8MN_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
-	hws[IMX8MN_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
-	hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
-	hws[IMX8MN_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
-	hws[IMX8MN_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
-
-	np = dev->of_node;
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (WARN_ON(IS_ERR(base))) {
-		ret = PTR_ERR(base);
-		goto unregister_hws;
-	}
+	hws[IMX8MN_SYS_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_OUT);
+	hws[IMX8MN_SYS_PLL2_50M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_50M);
+	hws[IMX8MN_SYS_PLL2_100M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_100M);
+	hws[IMX8MN_SYS_PLL2_125M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_125M);
+	hws[IMX8MN_SYS_PLL2_166M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_166M);
+	hws[IMX8MN_SYS_PLL2_200M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_200M);
+	hws[IMX8MN_SYS_PLL2_250M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_250M);
+	hws[IMX8MN_SYS_PLL2_333M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_333M);
+	hws[IMX8MN_SYS_PLL2_500M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_500M);
+	hws[IMX8MN_SYS_PLL2_1000M] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_SYS_PLL2_1000M);
+
+	hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT1_SEL);
+	hws[IMX8MN_CLK_CLKOUT1_DIV] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT1_DIV);
+	hws[IMX8MN_CLK_CLKOUT1] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT1);
+	hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT2_SEL);
+	hws[IMX8MN_CLK_CLKOUT2_DIV] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT2_DIV);
+	hws[IMX8MN_CLK_CLKOUT2] = imx_anatop_get_clk_hw(anp, IMX8MN_ANATOP_CLK_CLKOUT2);
 
 	/* CORE */
 	hws[IMX8MN_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mn_a53_sels, base + 0x8000);
@@ -599,18 +579,15 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
 
 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
 	if (ret < 0) {
-		dev_err(dev, "failed to register hws for i.MX8MN\n");
-		goto unregister_hws;
+		imx_unregister_hw_clocks(hws, IMX8MN_CLK_END);
+		return dev_err_probe(dev, ret,
+				     "failed to register hws for i.MX8MN\n");
 	}
 
 	imx_register_uart_clocks();
 
+	dev_info(dev, "NXP i.MX8MN ccm clock driver probed\n");
 	return 0;
-
-unregister_hws:
-	imx_unregister_hw_clocks(hws, IMX8MN_CLK_END);
-
-	return ret;
 }
 
 static const struct of_device_id imx8mn_clk_of_match[] = {
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:02 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:02 +0100
Subject: [PATCH v10 13/18] clk: imx: add support for i.MX8MP anatop clock driver
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-14-dario.binacchi@amarulasolutions.com>

Support NXP i.MX8P anatop PLL module which generates PLLs to CCM root.
By doing so, we also simplify the CCM driver code. The changes are
backward compatible.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
---

(no changes since v1)

 drivers/clk/imx/Makefile            |   2 +-
 drivers/clk/imx/clk-imx8mp-anatop.c | 306 ++++++++++++++++++++++++++++
 drivers/clk/imx/clk-imx8mp.c        | 188 ++++++++---------
 3 files changed, 391 insertions(+), 105 deletions(-)
 create mode 100644 drivers/clk/imx/clk-imx8mp-anatop.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8e0f42a0c69c..311a557900a9 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_MXC_CLK) += mxc-clk.o
 
 obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm-anatop.o clk-imx8mm.o
 obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn-anatop.o clk-imx8mn.o
-obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o
+obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp-anatop.o clk-imx8mp.o clk-imx8mp-audiomix.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
 
 obj-$(CONFIG_CLK_IMX93) += clk-imx93.o
diff --git a/drivers/clk/imx/clk-imx8mp-anatop.c b/drivers/clk/imx/clk-imx8mp-anatop.c
new file mode 100644
index 000000000000..ac23fcf92fd1
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mp-anatop.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-imx8mp-anatop.c - NXP i.MX8MP anatop clock driver
+ *
+ * Copyright (c) 2025 Dario Binacchi <dario.binacchi at amarulasolutions.com>
+ */
+
+#include <dt-bindings/clock/imx8mp-clock.h>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+
+#include "clk.h"
+
+#define IMX8MP_ANATOP_CLK_END		(IMX8MP_ANATOP_CLK_CLKOUT2 + 1)
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
+					   "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
+					   "arm_pll_out", "sys_pll1_out", "sys_pll2_out",
+					   "sys_pll3_out", "dummy", "dummy", "osc_24m",
+					   "dummy", "osc_32k"};
+
+static struct clk_hw_onecell_data *clk_hw_data;
+static struct clk_hw **hws;
+
+static int imx8mp_anatop_clocks_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	void __iomem *base;
+	int ret;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base)) {
+		dev_err(dev, "failed to get base address\n");
+		return PTR_ERR(base);
+	}
+
+	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+						    IMX8MP_ANATOP_CLK_END),
+				   GFP_KERNEL);
+	if (WARN_ON(!clk_hw_data))
+		return -ENOMEM;
+
+	clk_hw_data->num = IMX8MP_ANATOP_CLK_END;
+	hws = clk_hw_data->hws;
+
+	hws[IMX8MP_ANATOP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
+	hws[IMX8MP_ANATOP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	hws[IMX8MP_ANATOP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+
+	hws[IMX8MP_ANATOP_AUDIO_PLL1_REF_SEL] =
+		imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_AUDIO_PLL2_REF_SEL] =
+		imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_VIDEO_PLL_REF_SEL] =
+		imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_DRAM_PLL_REF_SEL] =
+		imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_GPU_PLL_REF_SEL] =
+		imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_VPU_PLL_REF_SEL] =
+		imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_ARM_PLL_REF_SEL] =
+		imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_SYS_PLL1_REF_SEL] =
+		imx_clk_hw_mux("sys_pll1_ref_sel", base + 0x94, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_SYS_PLL2_REF_SEL] =
+		imx_clk_hw_mux("sys_pll2_ref_sel", base + 0x104, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+	hws[IMX8MP_ANATOP_SYS_PLL3_REF_SEL] =
+		imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
+			       pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+	hws[IMX8MP_ANATOP_AUDIO_PLL1] =
+		imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel",
+				   base, &imx_1443x_pll);
+	hws[IMX8MP_ANATOP_AUDIO_PLL2] =
+		imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel",
+				   base + 0x14, &imx_1443x_pll);
+	hws[IMX8MP_ANATOP_VIDEO_PLL] =
+		imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel",
+				   base + 0x28, &imx_1443x_pll);
+	hws[IMX8MP_ANATOP_DRAM_PLL] =
+		imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel",
+				   base + 0x50, &imx_1443x_dram_pll);
+	hws[IMX8MP_ANATOP_GPU_PLL] =
+		imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel",
+				   base + 0x64, &imx_1416x_pll);
+	hws[IMX8MP_ANATOP_VPU_PLL] =
+		imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel",
+				   base + 0x74, &imx_1416x_pll);
+	hws[IMX8MP_ANATOP_ARM_PLL] =
+		imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel",
+				   base + 0x84, &imx_1416x_pll);
+	hws[IMX8MP_ANATOP_SYS_PLL1] =
+		imx_clk_hw_pll14xx("sys_pll1", "sys_pll1_ref_sel",
+				   base + 0x94, &imx_1416x_pll);
+	hws[IMX8MP_ANATOP_SYS_PLL2] =
+		imx_clk_hw_pll14xx("sys_pll2", "sys_pll2_ref_sel",
+				   base + 0x104, &imx_1416x_pll);
+	hws[IMX8MP_ANATOP_SYS_PLL3] =
+		imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel",
+				   base + 0x114, &imx_1416x_pll);
+
+	hws[IMX8MP_ANATOP_AUDIO_PLL1_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1,
+				     audio_pll1_bypass_sels,
+				     ARRAY_SIZE(audio_pll1_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_AUDIO_PLL2_BYPASS] =
+		imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14,
+				     16, 1, audio_pll2_bypass_sels,
+				     ARRAY_SIZE(audio_pll2_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_VIDEO_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28,
+				     16, 1, video_pll_bypass_sels,
+				     ARRAY_SIZE(video_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_DRAM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50,
+				     16, 1, dram_pll_bypass_sels,
+				     ARRAY_SIZE(dram_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_GPU_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64,
+				     28, 1, gpu_pll_bypass_sels,
+				     ARRAY_SIZE(gpu_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_VPU_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74,
+				     28, 1, vpu_pll_bypass_sels,
+				     ARRAY_SIZE(vpu_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_ARM_PLL_BYPASS] =
+		imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84,
+				     28, 1, arm_pll_bypass_sels,
+				     ARRAY_SIZE(arm_pll_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_SYS_PLL1_BYPASS] =
+		imx_clk_hw_mux_flags("sys_pll1_bypass", base + 0x94,
+				     28, 1, sys_pll1_bypass_sels,
+				     ARRAY_SIZE(sys_pll1_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_SYS_PLL2_BYPASS] =
+		imx_clk_hw_mux_flags("sys_pll2_bypass", base + 0x104,
+				     28, 1, sys_pll2_bypass_sels,
+				     ARRAY_SIZE(sys_pll2_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+	hws[IMX8MP_ANATOP_SYS_PLL3_BYPASS] =
+		imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114,
+				     28, 1, sys_pll3_bypass_sels,
+				     ARRAY_SIZE(sys_pll3_bypass_sels),
+				     CLK_SET_RATE_PARENT);
+
+	hws[IMX8MP_ANATOP_AUDIO_PLL1_OUT] =
+		imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass",
+				base, 13);
+	hws[IMX8MP_ANATOP_AUDIO_PLL2_OUT] =
+		imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass",
+				base + 0x14, 13);
+	hws[IMX8MP_ANATOP_VIDEO_PLL_OUT] =
+		imx_clk_hw_gate("video_pll_out", "video_pll_bypass",
+				base + 0x28, 13);
+	hws[IMX8MP_ANATOP_DRAM_PLL_OUT] =
+		imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass",
+				base + 0x50, 13);
+	hws[IMX8MP_ANATOP_GPU_PLL_OUT] =
+		imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass",
+				base + 0x64, 11);
+	hws[IMX8MP_ANATOP_VPU_PLL_OUT] =
+		imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass",
+				base + 0x74, 11);
+	hws[IMX8MP_ANATOP_ARM_PLL_OUT] =
+		imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass",
+				base + 0x84, 11);
+	hws[IMX8MP_ANATOP_SYS_PLL3_OUT] =
+		imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass",
+				base + 0x114, 11);
+
+	hws[IMX8MP_ANATOP_SYS_PLL1_OUT] =
+		imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass",
+				base + 0x94, 11);
+
+	hws[IMX8MP_ANATOP_SYS_PLL1_40M] =
+		imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+	hws[IMX8MP_ANATOP_SYS_PLL1_80M] =
+		imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+	hws[IMX8MP_ANATOP_SYS_PLL1_100M] =
+		imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+	hws[IMX8MP_ANATOP_SYS_PLL1_133M] =
+		imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+	hws[IMX8MP_ANATOP_SYS_PLL1_160M] =
+		imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+	hws[IMX8MP_ANATOP_SYS_PLL1_200M] =
+		imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+	hws[IMX8MP_ANATOP_SYS_PLL1_266M] =
+		imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+	hws[IMX8MP_ANATOP_SYS_PLL1_400M] =
+		imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+	hws[IMX8MP_ANATOP_SYS_PLL1_800M] =
+		imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+	hws[IMX8MP_ANATOP_SYS_PLL2_OUT] =
+		imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass",
+				base + 0x104, 11);
+
+	hws[IMX8MP_ANATOP_SYS_PLL2_50M] =
+		imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+	hws[IMX8MP_ANATOP_SYS_PLL2_100M] =
+		imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+	hws[IMX8MP_ANATOP_SYS_PLL2_125M] =
+		imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+	hws[IMX8MP_ANATOP_SYS_PLL2_166M] =
+		imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+	hws[IMX8MP_ANATOP_SYS_PLL2_200M] =
+		imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+	hws[IMX8MP_ANATOP_SYS_PLL2_250M] =
+		imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+	hws[IMX8MP_ANATOP_SYS_PLL2_333M] =
+		imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+	hws[IMX8MP_ANATOP_SYS_PLL2_500M] =
+		imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+	hws[IMX8MP_ANATOP_SYS_PLL2_1000M] =
+		imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+	hws[IMX8MP_ANATOP_CLK_CLKOUT1_SEL] =
+		imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MP_ANATOP_CLK_CLKOUT1_DIV] =
+		imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128,
+				   0, 4);
+	hws[IMX8MP_ANATOP_CLK_CLKOUT1] =
+		imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
+	hws[IMX8MP_ANATOP_CLK_CLKOUT2_SEL] =
+		imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4,
+				clkout_sels, ARRAY_SIZE(clkout_sels));
+	hws[IMX8MP_ANATOP_CLK_CLKOUT2_DIV] =
+		imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128,
+				   16, 4);
+	hws[IMX8MP_ANATOP_CLK_CLKOUT2] =
+		imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
+
+	imx_check_clk_hws(hws, IMX8MP_ANATOP_CLK_END);
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+	if (ret < 0) {
+		imx_unregister_hw_clocks(hws, IMX8MP_ANATOP_CLK_END);
+		return dev_err_probe(dev, ret,
+				     "failed to register anatop clock provider\n");
+	}
+
+	dev_info(dev, "NXP i.MX8MP anatop clock driver probed\n");
+	return 0;
+}
+
+static const struct of_device_id imx8mp_anatop_clk_of_match[] = {
+	{ .compatible = "fsl,imx8mp-anatop" },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mp_anatop_clk_of_match);
+
+static struct platform_driver imx8mp_anatop_clk_driver = {
+	.probe = imx8mp_anatop_clocks_probe,
+	.driver = {
+		.name = "imx8mp-anatop",
+		/*
+		 * Disable bind attributes: clocks are not removed and
+		 * reloading the driver will crash or break devices.
+		 */
+		.suppress_bind_attrs = true,
+		.of_match_table = imx8mp_anatop_clk_of_match,
+	},
+};
+
+module_platform_driver(imx8mp_anatop_clk_driver);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi at amarulasolutions.com>");
+MODULE_DESCRIPTION("NXP i.MX8MP anatop clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index 063bf26453a0..9dda576e5fbd 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -20,18 +20,6 @@ static u32 share_count_media;
 static u32 share_count_usb;
 static u32 share_count_audio;
 
-static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
-static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
-static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
-static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
-static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
-static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
-static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
-static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
-static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
-static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
-
 static const char * const imx8mp_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m",
 					       "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
 					       "audio_pll1_out", "sys_pll3_out", };
@@ -397,29 +385,16 @@ static const char * const imx8mp_sai7_sels[] = {"osc_24m", "audio_pll1_out", "au
 
 static const char * const imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
 
-static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
-						  "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
-						  "arm_pll_out", "sys_pll1_out", "sys_pll2_out",
-						  "sys_pll3_out", "dummy", "dummy", "osc_24m",
-						  "dummy", "osc_32k"};
-
 static struct clk_hw **hws;
 static struct clk_hw_onecell_data *clk_hw_data;
 
 static int imx8mp_clocks_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np;
-	void __iomem *anatop_base, *ccm_base;
+	struct device_node *np = dev->of_node, *anp;
+	void __iomem *ccm_base;
 	int err;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
-	anatop_base = devm_of_iomap(dev, np, 0, NULL);
-	of_node_put(np);
-	if (WARN_ON(IS_ERR(anatop_base)))
-		return PTR_ERR(anatop_base);
-
-	np = dev->of_node;
 	ccm_base = devm_platform_ioremap_resource(pdev, 0);
 	if (WARN_ON(IS_ERR(ccm_base)))
 		return PTR_ERR(ccm_base);
@@ -431,88 +406,92 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 	clk_hw_data->num = IMX8MP_CLK_END;
 	hws = clk_hw_data->hws;
 
-	hws[IMX8MP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
-	hws[IMX8MP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
-	hws[IMX8MP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+	anp = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
+	if (!anp)
+		return dev_err_probe(dev, -ENODEV, "missing anatop\n");
+
+	of_node_put(anp);
+
+	hws[IMX8MP_CLK_DUMMY] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_DUMMY);
+	hws[IMX8MP_CLK_24M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_24M);
+	hws[IMX8MP_CLK_32K] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_32K);
 	hws[IMX8MP_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
 	hws[IMX8MP_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
 	hws[IMX8MP_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
 	hws[IMX8MP_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
 
-	hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", anatop_base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", anatop_base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", anatop_base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", anatop_base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", anatop_base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", anatop_base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", anatop_base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_SYS_PLL1_REF_SEL] = imx_clk_hw_mux("sys_pll1_ref_sel", anatop_base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_SYS_PLL2_REF_SEL] = imx_clk_hw_mux("sys_pll2_ref_sel", anatop_base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-	hws[IMX8MP_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", anatop_base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
-
-	hws[IMX8MP_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", anatop_base, &imx_1443x_pll);
-	hws[IMX8MP_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", anatop_base + 0x14, &imx_1443x_pll);
-	hws[IMX8MP_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", anatop_base + 0x28, &imx_1443x_pll);
-	hws[IMX8MP_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", anatop_base + 0x50, &imx_1443x_dram_pll);
-	hws[IMX8MP_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", anatop_base + 0x64, &imx_1416x_pll);
-	hws[IMX8MP_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", anatop_base + 0x74, &imx_1416x_pll);
-	hws[IMX8MP_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", anatop_base + 0x84, &imx_1416x_pll);
-	hws[IMX8MP_SYS_PLL1] = imx_clk_hw_pll14xx("sys_pll1", "sys_pll1_ref_sel", anatop_base + 0x94, &imx_1416x_pll);
-	hws[IMX8MP_SYS_PLL2] = imx_clk_hw_pll14xx("sys_pll2", "sys_pll2_ref_sel", anatop_base + 0x104, &imx_1416x_pll);
-	hws[IMX8MP_SYS_PLL3] = imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", anatop_base + 0x114, &imx_1416x_pll);
-
-	hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", anatop_base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", anatop_base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", anatop_base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", anatop_base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", anatop_base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", anatop_base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", anatop_base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_SYS_PLL1_BYPASS] = imx_clk_hw_mux_flags("sys_pll1_bypass", anatop_base + 0x94, 28, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_SYS_PLL2_BYPASS] = imx_clk_hw_mux_flags("sys_pll2_bypass", anatop_base + 0x104, 28, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX8MP_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", anatop_base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
-
-	hws[IMX8MP_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", anatop_base, 13);
-	hws[IMX8MP_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", anatop_base + 0x14, 13);
-	hws[IMX8MP_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", anatop_base + 0x28, 13);
-	hws[IMX8MP_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", anatop_base + 0x50, 13);
-	hws[IMX8MP_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", anatop_base + 0x64, 11);
-	hws[IMX8MP_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", anatop_base + 0x74, 11);
-	hws[IMX8MP_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", anatop_base + 0x84, 11);
-	hws[IMX8MP_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", anatop_base + 0x114, 11);
-
-	hws[IMX8MP_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass", anatop_base + 0x94, 11);
-
-	hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
-	hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
-	hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
-	hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
-	hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
-	hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
-	hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
-	hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
-	hws[IMX8MP_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
-
-	hws[IMX8MP_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass", anatop_base + 0x104, 11);
-
-	hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
-	hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
-	hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
-	hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
-	hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
-	hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
-	hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
-	hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
-	hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
-
-	hws[IMX8MP_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", anatop_base + 0x128, 4, 4,
-						      imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels));
-	hws[IMX8MP_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", anatop_base + 0x128, 0, 4);
-	hws[IMX8MP_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", anatop_base + 0x128, 8);
-	hws[IMX8MP_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", anatop_base + 0x128, 20, 4,
-						      imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels));
-	hws[IMX8MP_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", anatop_base + 0x128, 16, 4);
-	hws[IMX8MP_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", anatop_base + 0x128, 24);
+	hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL1_REF_SEL);
+	hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL2_REF_SEL);
+	hws[IMX8MP_VIDEO_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VIDEO_PLL_REF_SEL);
+	hws[IMX8MP_DRAM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_DRAM_PLL_REF_SEL);
+	hws[IMX8MP_GPU_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_GPU_PLL_REF_SEL);
+	hws[IMX8MP_VPU_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VPU_PLL_REF_SEL);
+	hws[IMX8MP_ARM_PLL_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_ARM_PLL_REF_SEL);
+	hws[IMX8MP_SYS_PLL1_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_REF_SEL);
+	hws[IMX8MP_SYS_PLL2_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_REF_SEL);
+	hws[IMX8MP_SYS_PLL3_REF_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL3_REF_SEL);
+
+	hws[IMX8MP_AUDIO_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL1);
+	hws[IMX8MP_AUDIO_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL2);
+	hws[IMX8MP_VIDEO_PLL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VIDEO_PLL);
+	hws[IMX8MP_DRAM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_DRAM_PLL);
+	hws[IMX8MP_GPU_PLL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_GPU_PLL);
+	hws[IMX8MP_VPU_PLL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VPU_PLL);
+	hws[IMX8MP_ARM_PLL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_ARM_PLL);
+	hws[IMX8MP_SYS_PLL1] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1);
+	hws[IMX8MP_SYS_PLL2] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2);
+	hws[IMX8MP_SYS_PLL3] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL3);
+
+	hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL1_BYPASS);
+	hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL2_BYPASS);
+	hws[IMX8MP_VIDEO_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VIDEO_PLL_BYPASS);
+	hws[IMX8MP_DRAM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_DRAM_PLL_BYPASS);
+	hws[IMX8MP_GPU_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_GPU_PLL_BYPASS);
+	hws[IMX8MP_VPU_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VPU_PLL_BYPASS);
+	hws[IMX8MP_ARM_PLL_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_ARM_PLL_BYPASS);
+	hws[IMX8MP_SYS_PLL1_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_BYPASS);
+	hws[IMX8MP_SYS_PLL2_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_BYPASS);
+	hws[IMX8MP_SYS_PLL3_BYPASS] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL3_BYPASS);
+
+	hws[IMX8MP_AUDIO_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL1_OUT);
+	hws[IMX8MP_AUDIO_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_AUDIO_PLL2_OUT);
+	hws[IMX8MP_VIDEO_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VIDEO_PLL_OUT);
+	hws[IMX8MP_DRAM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_DRAM_PLL_OUT);
+	hws[IMX8MP_GPU_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_GPU_PLL_OUT);
+	hws[IMX8MP_VPU_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_VPU_PLL_OUT);
+	hws[IMX8MP_ARM_PLL_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_ARM_PLL_OUT);
+	hws[IMX8MP_SYS_PLL3_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL3_OUT);
+
+	hws[IMX8MP_SYS_PLL1_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_OUT);
+
+	hws[IMX8MP_SYS_PLL1_40M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_40M);
+	hws[IMX8MP_SYS_PLL1_80M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_80M);
+	hws[IMX8MP_SYS_PLL1_100M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_100M);
+	hws[IMX8MP_SYS_PLL1_133M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_133M);
+	hws[IMX8MP_SYS_PLL1_160M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_160M);
+	hws[IMX8MP_SYS_PLL1_200M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_200M);
+	hws[IMX8MP_SYS_PLL1_266M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_266M);
+	hws[IMX8MP_SYS_PLL1_400M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_400M);
+	hws[IMX8MP_SYS_PLL1_800M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL1_800M);
+
+	hws[IMX8MP_SYS_PLL2_OUT] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_OUT);
+
+	hws[IMX8MP_SYS_PLL2_50M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_50M);
+	hws[IMX8MP_SYS_PLL2_100M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_100M);
+	hws[IMX8MP_SYS_PLL2_125M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_125M);
+	hws[IMX8MP_SYS_PLL2_166M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_166M);
+	hws[IMX8MP_SYS_PLL2_200M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_200M);
+	hws[IMX8MP_SYS_PLL2_250M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_250M);
+	hws[IMX8MP_SYS_PLL2_333M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_333M);
+	hws[IMX8MP_SYS_PLL2_500M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_500M);
+	hws[IMX8MP_SYS_PLL2_1000M] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_SYS_PLL2_1000M);
+
+	hws[IMX8MP_CLK_CLKOUT1_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT1_SEL);
+	hws[IMX8MP_CLK_CLKOUT1_DIV] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT1_DIV);
+	hws[IMX8MP_CLK_CLKOUT1] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT1);
+	hws[IMX8MP_CLK_CLKOUT2_SEL] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT2_SEL);
+	hws[IMX8MP_CLK_CLKOUT2_DIV] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT2_DIV);
+	hws[IMX8MP_CLK_CLKOUT2] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT2);
 
 	hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000);
 	hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV];
@@ -724,6 +703,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	imx_register_uart_clocks();
 
+	dev_info(dev, "NXP i.MX8MP ccm clock driver probed\n");
 	return 0;
 }
 
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:28:03 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:28:03 +0100
Subject: [PATCH v10 14/18] clk: imx8mp: rename ccm_base to base
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-15-dario.binacchi@amarulasolutions.com>

The old code also accessed the anatop address space and therefore used
the variables anatop_base and ccm_base to distinguish between the two
address spaces. However, now that a specific anatop driver exists for
the i.MX8MP platform, the variable ccm_base can be renamed to base, as
is usually the case for the variable pointing to the memory region
managed by a Linux driver.
The patch does not introduce any functional changes.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
---

(no changes since v1)

 drivers/clk/imx/clk-imx8mp.c | 378 +++++++++++++++++------------------
 1 file changed, 189 insertions(+), 189 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index 9dda576e5fbd..012cd3b52e3f 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -392,12 +392,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node, *anp;
-	void __iomem *ccm_base;
+	void __iomem *base;
 	int err;
 
-	ccm_base = devm_platform_ioremap_resource(pdev, 0);
-	if (WARN_ON(IS_ERR(ccm_base)))
-		return PTR_ERR(ccm_base);
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (WARN_ON(IS_ERR(base)))
+		return PTR_ERR(base);
 
 	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
 	if (WARN_ON(!clk_hw_data))
@@ -493,198 +493,198 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
 	hws[IMX8MP_CLK_CLKOUT2_DIV] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT2_DIV);
 	hws[IMX8MP_CLK_CLKOUT2] = imx_anatop_get_clk_hw(anp, IMX8MP_ANATOP_CLK_CLKOUT2);
 
-	hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000);
+	hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, base + 0x8000);
 	hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV];
 	hws[IMX8MP_CLK_A53_CG] = hws[IMX8MP_CLK_A53_DIV];
-	hws[IMX8MP_CLK_M7_CORE] = imx8m_clk_hw_composite_core("m7_core", imx8mp_m7_sels, ccm_base + 0x8080);
-	hws[IMX8MP_CLK_ML_CORE] = imx8m_clk_hw_composite_core("ml_core", imx8mp_ml_sels, ccm_base + 0x8100);
-	hws[IMX8MP_CLK_GPU3D_CORE] = imx8m_clk_hw_composite_core("gpu3d_core", imx8mp_gpu3d_core_sels, ccm_base + 0x8180);
-	hws[IMX8MP_CLK_GPU3D_SHADER_CORE] = imx8m_clk_hw_composite("gpu3d_shader_core", imx8mp_gpu3d_shader_sels, ccm_base + 0x8200);
-	hws[IMX8MP_CLK_GPU2D_CORE] = imx8m_clk_hw_composite("gpu2d_core", imx8mp_gpu2d_sels, ccm_base + 0x8280);
-	hws[IMX8MP_CLK_AUDIO_AXI] = imx8m_clk_hw_composite("audio_axi", imx8mp_audio_axi_sels, ccm_base + 0x8300);
+	hws[IMX8MP_CLK_M7_CORE] = imx8m_clk_hw_composite_core("m7_core", imx8mp_m7_sels, base + 0x8080);
+	hws[IMX8MP_CLK_ML_CORE] = imx8m_clk_hw_composite_core("ml_core", imx8mp_ml_sels, base + 0x8100);
+	hws[IMX8MP_CLK_GPU3D_CORE] = imx8m_clk_hw_composite_core("gpu3d_core", imx8mp_gpu3d_core_sels, base + 0x8180);
+	hws[IMX8MP_CLK_GPU3D_SHADER_CORE] = imx8m_clk_hw_composite("gpu3d_shader_core", imx8mp_gpu3d_shader_sels, base + 0x8200);
+	hws[IMX8MP_CLK_GPU2D_CORE] = imx8m_clk_hw_composite("gpu2d_core", imx8mp_gpu2d_sels, base + 0x8280);
+	hws[IMX8MP_CLK_AUDIO_AXI] = imx8m_clk_hw_composite("audio_axi", imx8mp_audio_axi_sels, base + 0x8300);
 	hws[IMX8MP_CLK_AUDIO_AXI_SRC] = hws[IMX8MP_CLK_AUDIO_AXI];
-	hws[IMX8MP_CLK_HSIO_AXI] = imx8m_clk_hw_composite("hsio_axi", imx8mp_hsio_axi_sels, ccm_base + 0x8380);
-	hws[IMX8MP_CLK_MEDIA_ISP] = imx8m_clk_hw_composite("media_isp", imx8mp_media_isp_sels, ccm_base + 0x8400);
+	hws[IMX8MP_CLK_HSIO_AXI] = imx8m_clk_hw_composite("hsio_axi", imx8mp_hsio_axi_sels, base + 0x8380);
+	hws[IMX8MP_CLK_MEDIA_ISP] = imx8m_clk_hw_composite("media_isp", imx8mp_media_isp_sels, base + 0x8400);
 
 	/* CORE SEL */
-	hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
-
-	hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
-	hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
-	hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
-	hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
-	hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
-	hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
-	hws[IMX8MP_CLK_HDMI_APB] = imx8m_clk_hw_composite_bus("hdmi_apb", imx8mp_media_apb_sels, ccm_base + 0x8b00);
-	hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
-	hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
-	hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
-	hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
-	hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_bus_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
-	hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
-	hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
-
-	hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
-	hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
-	hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
-	hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite_bus_flags("media_disp2_pix", imx8mp_media_disp_pix_sels, ccm_base + 0x9300, CLK_SET_RATE_PARENT);
-
-	hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1);
-
-	hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000);
-	hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080);
-	hws[IMX8MP_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mp_vpu_g1_sels, ccm_base + 0xa100);
-	hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, ccm_base + 0xa180);
-	hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, ccm_base + 0xa200);
-	hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2", imx8mp_can2_sels, ccm_base + 0xa280);
-	hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux", imx8mp_pcie_aux_sels, ccm_base + 0xa400);
-	hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5", imx8mp_i2c5_sels, ccm_base + 0xa480);
-	hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6", imx8mp_i2c6_sels, ccm_base + 0xa500);
-	hws[IMX8MP_CLK_SAI1] = imx8m_clk_hw_composite("sai1", imx8mp_sai1_sels, ccm_base + 0xa580);
-	hws[IMX8MP_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mp_sai2_sels, ccm_base + 0xa600);
-	hws[IMX8MP_CLK_SAI3] = imx8m_clk_hw_composite("sai3", imx8mp_sai3_sels, ccm_base + 0xa680);
-	hws[IMX8MP_CLK_SAI5] = imx8m_clk_hw_composite("sai5", imx8mp_sai5_sels, ccm_base + 0xa780);
-	hws[IMX8MP_CLK_SAI6] = imx8m_clk_hw_composite("sai6", imx8mp_sai6_sels, ccm_base + 0xa800);
-	hws[IMX8MP_CLK_ENET_QOS] = imx8m_clk_hw_composite("enet_qos", imx8mp_enet_qos_sels, ccm_base + 0xa880);
-	hws[IMX8MP_CLK_ENET_QOS_TIMER] = imx8m_clk_hw_composite("enet_qos_timer", imx8mp_enet_qos_timer_sels, ccm_base + 0xa900);
-	hws[IMX8MP_CLK_ENET_REF] = imx8m_clk_hw_composite("enet_ref", imx8mp_enet_ref_sels, ccm_base + 0xa980);
-	hws[IMX8MP_CLK_ENET_TIMER] = imx8m_clk_hw_composite("enet_timer", imx8mp_enet_timer_sels, ccm_base + 0xaa00);
-	hws[IMX8MP_CLK_ENET_PHY_REF] = imx8m_clk_hw_composite("enet_phy_ref", imx8mp_enet_phy_ref_sels, ccm_base + 0xaa80);
-	hws[IMX8MP_CLK_NAND] = imx8m_clk_hw_composite("nand", imx8mp_nand_sels, ccm_base + 0xab00);
-	hws[IMX8MP_CLK_QSPI] = imx8m_clk_hw_composite("qspi", imx8mp_qspi_sels, ccm_base + 0xab80);
-	hws[IMX8MP_CLK_USDHC1] = imx8m_clk_hw_composite("usdhc1", imx8mp_usdhc1_sels, ccm_base + 0xac00);
-	hws[IMX8MP_CLK_USDHC2] = imx8m_clk_hw_composite("usdhc2", imx8mp_usdhc2_sels, ccm_base + 0xac80);
-	hws[IMX8MP_CLK_I2C1] = imx8m_clk_hw_composite("i2c1", imx8mp_i2c1_sels, ccm_base + 0xad00);
-	hws[IMX8MP_CLK_I2C2] = imx8m_clk_hw_composite("i2c2", imx8mp_i2c2_sels, ccm_base + 0xad80);
-	hws[IMX8MP_CLK_I2C3] = imx8m_clk_hw_composite("i2c3", imx8mp_i2c3_sels, ccm_base + 0xae00);
-	hws[IMX8MP_CLK_I2C4] = imx8m_clk_hw_composite("i2c4", imx8mp_i2c4_sels, ccm_base + 0xae80);
-
-	hws[IMX8MP_CLK_UART1] = imx8m_clk_hw_composite("uart1", imx8mp_uart1_sels, ccm_base + 0xaf00);
-	hws[IMX8MP_CLK_UART2] = imx8m_clk_hw_composite("uart2", imx8mp_uart2_sels, ccm_base + 0xaf80);
-	hws[IMX8MP_CLK_UART3] = imx8m_clk_hw_composite("uart3", imx8mp_uart3_sels, ccm_base + 0xb000);
-	hws[IMX8MP_CLK_UART4] = imx8m_clk_hw_composite("uart4", imx8mp_uart4_sels, ccm_base + 0xb080);
-	hws[IMX8MP_CLK_USB_CORE_REF] = imx8m_clk_hw_composite("usb_core_ref", imx8mp_usb_core_ref_sels, ccm_base + 0xb100);
-	hws[IMX8MP_CLK_USB_PHY_REF] = imx8m_clk_hw_composite("usb_phy_ref", imx8mp_usb_phy_ref_sels, ccm_base + 0xb180);
-	hws[IMX8MP_CLK_GIC] = imx8m_clk_hw_composite_critical("gic", imx8mp_gic_sels, ccm_base + 0xb200);
-	hws[IMX8MP_CLK_ECSPI1] = imx8m_clk_hw_composite("ecspi1", imx8mp_ecspi1_sels, ccm_base + 0xb280);
-	hws[IMX8MP_CLK_ECSPI2] = imx8m_clk_hw_composite("ecspi2", imx8mp_ecspi2_sels, ccm_base + 0xb300);
-	hws[IMX8MP_CLK_PWM1] = imx8m_clk_hw_composite("pwm1", imx8mp_pwm1_sels, ccm_base + 0xb380);
-	hws[IMX8MP_CLK_PWM2] = imx8m_clk_hw_composite("pwm2", imx8mp_pwm2_sels, ccm_base + 0xb400);
-	hws[IMX8MP_CLK_PWM3] = imx8m_clk_hw_composite("pwm3", imx8mp_pwm3_sels, ccm_base + 0xb480);
-	hws[IMX8MP_CLK_PWM4] = imx8m_clk_hw_composite("pwm4", imx8mp_pwm4_sels, ccm_base + 0xb500);
-
-	hws[IMX8MP_CLK_GPT1] = imx8m_clk_hw_composite("gpt1", imx8mp_gpt1_sels, ccm_base + 0xb580);
-	hws[IMX8MP_CLK_GPT2] = imx8m_clk_hw_composite("gpt2", imx8mp_gpt2_sels, ccm_base + 0xb600);
-	hws[IMX8MP_CLK_GPT3] = imx8m_clk_hw_composite("gpt3", imx8mp_gpt3_sels, ccm_base + 0xb680);
-	hws[IMX8MP_CLK_GPT4] = imx8m_clk_hw_composite("gpt4", imx8mp_gpt4_sels, ccm_base + 0xb700);
-	hws[IMX8MP_CLK_GPT5] = imx8m_clk_hw_composite("gpt5", imx8mp_gpt5_sels, ccm_base + 0xb780);
-	hws[IMX8MP_CLK_GPT6] = imx8m_clk_hw_composite("gpt6", imx8mp_gpt6_sels, ccm_base + 0xb800);
-	hws[IMX8MP_CLK_WDOG] = imx8m_clk_hw_composite("wdog", imx8mp_wdog_sels, ccm_base + 0xb900);
-	hws[IMX8MP_CLK_WRCLK] = imx8m_clk_hw_composite("wrclk", imx8mp_wrclk_sels, ccm_base + 0xb980);
-	hws[IMX8MP_CLK_IPP_DO_CLKO1] = imx8m_clk_hw_composite("ipp_do_clko1", imx8mp_ipp_do_clko1_sels, ccm_base + 0xba00);
-	hws[IMX8MP_CLK_IPP_DO_CLKO2] = imx8m_clk_hw_composite("ipp_do_clko2", imx8mp_ipp_do_clko2_sels, ccm_base + 0xba80);
-	hws[IMX8MP_CLK_HDMI_FDCC_TST] = imx8m_clk_hw_composite("hdmi_fdcc_tst", imx8mp_hdmi_fdcc_tst_sels, ccm_base + 0xbb00);
-	hws[IMX8MP_CLK_HDMI_24M] = imx8m_clk_hw_composite("hdmi_24m", imx8mp_hdmi_24m_sels, ccm_base + 0xbb80);
-	hws[IMX8MP_CLK_HDMI_REF_266M] = imx8m_clk_hw_composite("hdmi_ref_266m", imx8mp_hdmi_ref_266m_sels, ccm_base + 0xbc00);
-	hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, ccm_base + 0xbc80);
-	hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, ccm_base + 0xbd00);
-	hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, ccm_base + 0xbd80);
-	hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite_bus_flags("media_disp1_pix", imx8mp_media_disp_pix_sels, ccm_base + 0xbe00, CLK_SET_RATE_PARENT);
-	hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
-	hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base + 0xbf00);
-	hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, ccm_base + 0xbf80);
-	hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] = imx8m_clk_hw_composite("media_mipi_test_byte", imx8mp_media_mipi_test_byte_sels, ccm_base + 0xc100);
-	hws[IMX8MP_CLK_ECSPI3] = imx8m_clk_hw_composite("ecspi3", imx8mp_ecspi3_sels, ccm_base + 0xc180);
-	hws[IMX8MP_CLK_PDM] = imx8m_clk_hw_composite("pdm", imx8mp_pdm_sels, ccm_base + 0xc200);
-	hws[IMX8MP_CLK_VPU_VC8000E] = imx8m_clk_hw_composite("vpu_vc8000e", imx8mp_vpu_vc8000e_sels, ccm_base + 0xc280);
-	hws[IMX8MP_CLK_SAI7] = imx8m_clk_hw_composite("sai7", imx8mp_sai7_sels, ccm_base + 0xc300);
+	hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
+
+	hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mp_main_axi_sels, base + 0x8800);
+	hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, base + 0x8880);
+	hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mp_nand_usdhc_sels, base + 0x8900);
+	hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, base + 0x8980);
+	hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, base + 0x8a00);
+	hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, base + 0x8a80);
+	hws[IMX8MP_CLK_HDMI_APB] = imx8m_clk_hw_composite_bus("hdmi_apb", imx8mp_media_apb_sels, base + 0x8b00);
+	hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, base + 0x8b80);
+	hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, base + 0x8c00);
+	hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, base + 0x8c80);
+	hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mp_noc_sels, base + 0x8d00);
+	hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_bus_critical("noc_io", imx8mp_noc_io_sels, base + 0x8d80);
+	hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, base + 0x8e00);
+	hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, base + 0x8e80);
+
+	hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, base + 0x9000);
+	hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, base + 0x9100);
+	hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, base + 0x9200);
+	hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite_bus_flags("media_disp2_pix", imx8mp_media_disp_pix_sels, base + 0x9300, CLK_SET_RATE_PARENT);
+
+	hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", base + 0x9080, 0, 1);
+
+	hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mp_dram_alt_sels, base + 0xa000);
+	hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mp_dram_apb_sels, base + 0xa080);
+	hws[IMX8MP_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mp_vpu_g1_sels, base + 0xa100);
+	hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, base + 0xa180);
+	hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, base + 0xa200);
+	hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2", imx8mp_can2_sels, base + 0xa280);
+	hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux", imx8mp_pcie_aux_sels, base + 0xa400);
+	hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5", imx8mp_i2c5_sels, base + 0xa480);
+	hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6", imx8mp_i2c6_sels, base + 0xa500);
+	hws[IMX8MP_CLK_SAI1] = imx8m_clk_hw_composite("sai1", imx8mp_sai1_sels, base + 0xa580);
+	hws[IMX8MP_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mp_sai2_sels, base + 0xa600);
+	hws[IMX8MP_CLK_SAI3] = imx8m_clk_hw_composite("sai3", imx8mp_sai3_sels, base + 0xa680);
+	hws[IMX8MP_CLK_SAI5] = imx8m_clk_hw_composite("sai5", imx8mp_sai5_sels, base + 0xa780);
+	hws[IMX8MP_CLK_SAI6] = imx8m_clk_hw_composite("sai6", imx8mp_sai6_sels, base + 0xa800);
+	hws[IMX8MP_CLK_ENET_QOS] = imx8m_clk_hw_composite("enet_qos", imx8mp_enet_qos_sels, base + 0xa880);
+	hws[IMX8MP_CLK_ENET_QOS_TIMER] = imx8m_clk_hw_composite("enet_qos_timer", imx8mp_enet_qos_timer_sels, base + 0xa900);
+	hws[IMX8MP_CLK_ENET_REF] = imx8m_clk_hw_composite("enet_ref", imx8mp_enet_ref_sels, base + 0xa980);
+	hws[IMX8MP_CLK_ENET_TIMER] = imx8m_clk_hw_composite("enet_timer", imx8mp_enet_timer_sels, base + 0xaa00);
+	hws[IMX8MP_CLK_ENET_PHY_REF] = imx8m_clk_hw_composite("enet_phy_ref", imx8mp_enet_phy_ref_sels, base + 0xaa80);
+	hws[IMX8MP_CLK_NAND] = imx8m_clk_hw_composite("nand", imx8mp_nand_sels, base + 0xab00);
+	hws[IMX8MP_CLK_QSPI] = imx8m_clk_hw_composite("qspi", imx8mp_qspi_sels, base + 0xab80);
+	hws[IMX8MP_CLK_USDHC1] = imx8m_clk_hw_composite("usdhc1", imx8mp_usdhc1_sels, base + 0xac00);
+	hws[IMX8MP_CLK_USDHC2] = imx8m_clk_hw_composite("usdhc2", imx8mp_usdhc2_sels, base + 0xac80);
+	hws[IMX8MP_CLK_I2C1] = imx8m_clk_hw_composite("i2c1", imx8mp_i2c1_sels, base + 0xad00);
+	hws[IMX8MP_CLK_I2C2] = imx8m_clk_hw_composite("i2c2", imx8mp_i2c2_sels, base + 0xad80);
+	hws[IMX8MP_CLK_I2C3] = imx8m_clk_hw_composite("i2c3", imx8mp_i2c3_sels, base + 0xae00);
+	hws[IMX8MP_CLK_I2C4] = imx8m_clk_hw_composite("i2c4", imx8mp_i2c4_sels, base + 0xae80);
+
+	hws[IMX8MP_CLK_UART1] = imx8m_clk_hw_composite("uart1", imx8mp_uart1_sels, base + 0xaf00);
+	hws[IMX8MP_CLK_UART2] = imx8m_clk_hw_composite("uart2", imx8mp_uart2_sels, base + 0xaf80);
+	hws[IMX8MP_CLK_UART3] = imx8m_clk_hw_composite("uart3", imx8mp_uart3_sels, base + 0xb000);
+	hws[IMX8MP_CLK_UART4] = imx8m_clk_hw_composite("uart4", imx8mp_uart4_sels, base + 0xb080);
+	hws[IMX8MP_CLK_USB_CORE_REF] = imx8m_clk_hw_composite("usb_core_ref", imx8mp_usb_core_ref_sels, base + 0xb100);
+	hws[IMX8MP_CLK_USB_PHY_REF] = imx8m_clk_hw_composite("usb_phy_ref", imx8mp_usb_phy_ref_sels, base + 0xb180);
+	hws[IMX8MP_CLK_GIC] = imx8m_clk_hw_composite_critical("gic", imx8mp_gic_sels, base + 0xb200);
+	hws[IMX8MP_CLK_ECSPI1] = imx8m_clk_hw_composite("ecspi1", imx8mp_ecspi1_sels, base + 0xb280);
+	hws[IMX8MP_CLK_ECSPI2] = imx8m_clk_hw_composite("ecspi2", imx8mp_ecspi2_sels, base + 0xb300);
+	hws[IMX8MP_CLK_PWM1] = imx8m_clk_hw_composite("pwm1", imx8mp_pwm1_sels, base + 0xb380);
+	hws[IMX8MP_CLK_PWM2] = imx8m_clk_hw_composite("pwm2", imx8mp_pwm2_sels, base + 0xb400);
+	hws[IMX8MP_CLK_PWM3] = imx8m_clk_hw_composite("pwm3", imx8mp_pwm3_sels, base + 0xb480);
+	hws[IMX8MP_CLK_PWM4] = imx8m_clk_hw_composite("pwm4", imx8mp_pwm4_sels, base + 0xb500);
+
+	hws[IMX8MP_CLK_GPT1] = imx8m_clk_hw_composite("gpt1", imx8mp_gpt1_sels, base + 0xb580);
+	hws[IMX8MP_CLK_GPT2] = imx8m_clk_hw_composite("gpt2", imx8mp_gpt2_sels, base + 0xb600);
+	hws[IMX8MP_CLK_GPT3] = imx8m_clk_hw_composite("gpt3", imx8mp_gpt3_sels, base + 0xb680);
+	hws[IMX8MP_CLK_GPT4] = imx8m_clk_hw_composite("gpt4", imx8mp_gpt4_sels, base + 0xb700);
+	hws[IMX8MP_CLK_GPT5] = imx8m_clk_hw_composite("gpt5", imx8mp_gpt5_sels, base + 0xb780);
+	hws[IMX8MP_CLK_GPT6] = imx8m_clk_hw_composite("gpt6", imx8mp_gpt6_sels, base + 0xb800);
+	hws[IMX8MP_CLK_WDOG] = imx8m_clk_hw_composite("wdog", imx8mp_wdog_sels, base + 0xb900);
+	hws[IMX8MP_CLK_WRCLK] = imx8m_clk_hw_composite("wrclk", imx8mp_wrclk_sels, base + 0xb980);
+	hws[IMX8MP_CLK_IPP_DO_CLKO1] = imx8m_clk_hw_composite("ipp_do_clko1", imx8mp_ipp_do_clko1_sels, base + 0xba00);
+	hws[IMX8MP_CLK_IPP_DO_CLKO2] = imx8m_clk_hw_composite("ipp_do_clko2", imx8mp_ipp_do_clko2_sels, base + 0xba80);
+	hws[IMX8MP_CLK_HDMI_FDCC_TST] = imx8m_clk_hw_composite("hdmi_fdcc_tst", imx8mp_hdmi_fdcc_tst_sels, base + 0xbb00);
+	hws[IMX8MP_CLK_HDMI_24M] = imx8m_clk_hw_composite("hdmi_24m", imx8mp_hdmi_24m_sels, base + 0xbb80);
+	hws[IMX8MP_CLK_HDMI_REF_266M] = imx8m_clk_hw_composite("hdmi_ref_266m", imx8mp_hdmi_ref_266m_sels, base + 0xbc00);
+	hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, base + 0xbc80);
+	hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, base + 0xbd00);
+	hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, base + 0xbd80);
+	hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite_bus_flags("media_disp1_pix", imx8mp_media_disp_pix_sels, base + 0xbe00, CLK_SET_RATE_PARENT);
+	hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, base + 0xbe80);
+	hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, base + 0xbf00);
+	hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, base + 0xbf80);
+	hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] = imx8m_clk_hw_composite("media_mipi_test_byte", imx8mp_media_mipi_test_byte_sels, base + 0xc100);
+	hws[IMX8MP_CLK_ECSPI3] = imx8m_clk_hw_composite("ecspi3", imx8mp_ecspi3_sels, base + 0xc180);
+	hws[IMX8MP_CLK_PDM] = imx8m_clk_hw_composite("pdm", imx8mp_pdm_sels, base + 0xc200);
+	hws[IMX8MP_CLK_VPU_VC8000E] = imx8m_clk_hw_composite("vpu_vc8000e", imx8mp_vpu_vc8000e_sels, base + 0xc280);
+	hws[IMX8MP_CLK_SAI7] = imx8m_clk_hw_composite("sai7", imx8mp_sai7_sels, base + 0xc300);
 
 	hws[IMX8MP_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
-	hws[IMX8MP_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", ccm_base + 0x9800, 24, 1, imx8mp_dram_core_sels, ARRAY_SIZE(imx8mp_dram_core_sels), CLK_IS_CRITICAL);
-
-	hws[IMX8MP_CLK_DRAM1_ROOT] = imx_clk_hw_gate4_flags("dram1_root_clk", "dram_core_clk", ccm_base + 0x4050, 0, CLK_IS_CRITICAL);
-	hws[IMX8MP_CLK_ECSPI1_ROOT] = imx_clk_hw_gate4("ecspi1_root_clk", "ecspi1", ccm_base + 0x4070, 0);
-	hws[IMX8MP_CLK_ECSPI2_ROOT] = imx_clk_hw_gate4("ecspi2_root_clk", "ecspi2", ccm_base + 0x4080, 0);
-	hws[IMX8MP_CLK_ECSPI3_ROOT] = imx_clk_hw_gate4("ecspi3_root_clk", "ecspi3", ccm_base + 0x4090, 0);
-	hws[IMX8MP_CLK_ENET1_ROOT] = imx_clk_hw_gate4("enet1_root_clk", "enet_axi", ccm_base + 0x40a0, 0);
-	hws[IMX8MP_CLK_GPIO1_ROOT] = imx_clk_hw_gate4("gpio1_root_clk", "ipg_root", ccm_base + 0x40b0, 0);
-	hws[IMX8MP_CLK_GPIO2_ROOT] = imx_clk_hw_gate4("gpio2_root_clk", "ipg_root", ccm_base + 0x40c0, 0);
-	hws[IMX8MP_CLK_GPIO3_ROOT] = imx_clk_hw_gate4("gpio3_root_clk", "ipg_root", ccm_base + 0x40d0, 0);
-	hws[IMX8MP_CLK_GPIO4_ROOT] = imx_clk_hw_gate4("gpio4_root_clk", "ipg_root", ccm_base + 0x40e0, 0);
-	hws[IMX8MP_CLK_GPIO5_ROOT] = imx_clk_hw_gate4("gpio5_root_clk", "ipg_root", ccm_base + 0x40f0, 0);
-	hws[IMX8MP_CLK_GPT1_ROOT] = imx_clk_hw_gate4("gpt1_root_clk", "gpt1", ccm_base + 0x4100, 0);
-	hws[IMX8MP_CLK_GPT2_ROOT] = imx_clk_hw_gate4("gpt2_root_clk", "gpt2", ccm_base + 0x4110, 0);
-	hws[IMX8MP_CLK_GPT3_ROOT] = imx_clk_hw_gate4("gpt3_root_clk", "gpt3", ccm_base + 0x4120, 0);
-	hws[IMX8MP_CLK_GPT4_ROOT] = imx_clk_hw_gate4("gpt4_root_clk", "gpt4", ccm_base + 0x4130, 0);
-	hws[IMX8MP_CLK_GPT5_ROOT] = imx_clk_hw_gate4("gpt5_root_clk", "gpt5", ccm_base + 0x4140, 0);
-	hws[IMX8MP_CLK_GPT6_ROOT] = imx_clk_hw_gate4("gpt6_root_clk", "gpt6", ccm_base + 0x4150, 0);
-	hws[IMX8MP_CLK_I2C1_ROOT] = imx_clk_hw_gate4("i2c1_root_clk", "i2c1", ccm_base + 0x4170, 0);
-	hws[IMX8MP_CLK_I2C2_ROOT] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2", ccm_base + 0x4180, 0);
-	hws[IMX8MP_CLK_I2C3_ROOT] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3", ccm_base + 0x4190, 0);
-	hws[IMX8MP_CLK_I2C4_ROOT] = imx_clk_hw_gate4("i2c4_root_clk", "i2c4", ccm_base + 0x41a0, 0);
-	hws[IMX8MP_CLK_MU_ROOT] = imx_clk_hw_gate4("mu_root_clk", "ipg_root", ccm_base + 0x4210, 0);
-	hws[IMX8MP_CLK_OCOTP_ROOT] = imx_clk_hw_gate4("ocotp_root_clk", "ipg_root", ccm_base + 0x4220, 0);
-	hws[IMX8MP_CLK_PCIE_ROOT] = imx_clk_hw_gate4("pcie_root_clk", "pcie_aux", ccm_base + 0x4250, 0);
-	hws[IMX8MP_CLK_PWM1_ROOT] = imx_clk_hw_gate4("pwm1_root_clk", "pwm1", ccm_base + 0x4280, 0);
-	hws[IMX8MP_CLK_PWM2_ROOT] = imx_clk_hw_gate4("pwm2_root_clk", "pwm2", ccm_base + 0x4290, 0);
-	hws[IMX8MP_CLK_PWM3_ROOT] = imx_clk_hw_gate4("pwm3_root_clk", "pwm3", ccm_base + 0x42a0, 0);
-	hws[IMX8MP_CLK_PWM4_ROOT] = imx_clk_hw_gate4("pwm4_root_clk", "pwm4", ccm_base + 0x42b0, 0);
-	hws[IMX8MP_CLK_QOS_ROOT] = imx_clk_hw_gate4("qos_root_clk", "ipg_root", ccm_base + 0x42c0, 0);
-	hws[IMX8MP_CLK_QOS_ENET_ROOT] = imx_clk_hw_gate4("qos_enet_root_clk", "ipg_root", ccm_base + 0x42e0, 0);
-	hws[IMX8MP_CLK_QSPI_ROOT] = imx_clk_hw_gate4("qspi_root_clk", "qspi", ccm_base + 0x42f0, 0);
-	hws[IMX8MP_CLK_NAND_ROOT] = imx_clk_hw_gate2_shared2("nand_root_clk", "nand", ccm_base + 0x4300, 0, &share_count_nand);
-	hws[IMX8MP_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_hw_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", ccm_base + 0x4300, 0, &share_count_nand);
-	hws[IMX8MP_CLK_I2C5_ROOT] = imx_clk_hw_gate2("i2c5_root_clk", "i2c5", ccm_base + 0x4330, 0);
-	hws[IMX8MP_CLK_I2C6_ROOT] = imx_clk_hw_gate2("i2c6_root_clk", "i2c6", ccm_base + 0x4340, 0);
-	hws[IMX8MP_CLK_CAN1_ROOT] = imx_clk_hw_gate2("can1_root_clk", "can1", ccm_base + 0x4350, 0);
-	hws[IMX8MP_CLK_CAN2_ROOT] = imx_clk_hw_gate2("can2_root_clk", "can2", ccm_base + 0x4360, 0);
-	hws[IMX8MP_CLK_SDMA1_ROOT] = imx_clk_hw_gate4("sdma1_root_clk", "ipg_root", ccm_base + 0x43a0, 0);
-	hws[IMX8MP_CLK_SIM_ENET_ROOT] = imx_clk_hw_gate4("sim_enet_root_clk", "enet_axi", ccm_base + 0x4400, 0);
-	hws[IMX8MP_CLK_ENET_QOS_ROOT] = imx_clk_hw_gate4("enet_qos_root_clk", "sim_enet_root_clk", ccm_base + 0x43b0, 0);
-	hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", ccm_base + 0x4450, 0);
-	hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", ccm_base + 0x4460, 0);
-	hws[IMX8MP_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", ccm_base + 0x4490, 0);
-	hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
-	hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0);
-	hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0);
-	hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0, &share_count_usb);
-	hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0, &share_count_usb);
-	hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0);
-	hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0);
-	hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0);
-	hws[IMX8MP_CLK_WDOG1_ROOT] = imx_clk_hw_gate4("wdog1_root_clk", "wdog", ccm_base + 0x4530, 0);
-	hws[IMX8MP_CLK_WDOG2_ROOT] = imx_clk_hw_gate4("wdog2_root_clk", "wdog", ccm_base + 0x4540, 0);
-	hws[IMX8MP_CLK_WDOG3_ROOT] = imx_clk_hw_gate4("wdog3_root_clk", "wdog", ccm_base + 0x4550, 0);
-	hws[IMX8MP_CLK_VPU_G1_ROOT] = imx_clk_hw_gate4("vpu_g1_root_clk", "vpu_g1", ccm_base + 0x4560, 0);
-	hws[IMX8MP_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_axi", ccm_base + 0x4570, 0);
-	hws[IMX8MP_CLK_VPU_VC8KE_ROOT] = imx_clk_hw_gate4("vpu_vc8ke_root_clk", "vpu_vc8000e", ccm_base + 0x4590, 0);
-	hws[IMX8MP_CLK_VPU_G2_ROOT] = imx_clk_hw_gate4("vpu_g2_root_clk", "vpu_g2", ccm_base + 0x45a0, 0);
-	hws[IMX8MP_CLK_NPU_ROOT] = imx_clk_hw_gate4("npu_root_clk", "ml_core", ccm_base + 0x45b0, 0);
-	hws[IMX8MP_CLK_HSIO_ROOT] = imx_clk_hw_gate4("hsio_root_clk", "ipg_root", ccm_base + 0x45c0, 0);
-	hws[IMX8MP_CLK_MEDIA_APB_ROOT] = imx_clk_hw_gate2_shared2("media_apb_root_clk", "media_apb", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_AXI_ROOT] = imx_clk_hw_gate2_shared2("media_axi_root_clk", "media_axi", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam1_pix_root_clk", "media_cam1_pix", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam2_pix_root_clk", "media_cam2_pix", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT] = imx_clk_hw_gate2_shared2("media_mipi_phy1_ref_root", "media_mipi_phy1_ref", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_LDB_ROOT] = imx_clk_hw_gate2_shared2("media_ldb_root_clk", "media_ldb", ccm_base + 0x45d0, 0, &share_count_media);
-	hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", ccm_base + 0x45d0, 0, &share_count_media);
-
-	hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", ccm_base + 0x45e0, 0);
-	hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
-	hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
-	hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
-
-	hws[IMX8MP_CLK_AUDIO_AHB_ROOT] = imx_clk_hw_gate2_shared2("audio_ahb_root", "audio_ahb", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_AUDIO_AXI_ROOT] = imx_clk_hw_gate2_shared2("audio_axi_root", "audio_axi", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI1_ROOT] = imx_clk_hw_gate2_shared2("sai1_root", "sai1", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI2_ROOT] = imx_clk_hw_gate2_shared2("sai2_root", "sai2", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI3_ROOT] = imx_clk_hw_gate2_shared2("sai3_root", "sai3", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI5_ROOT] = imx_clk_hw_gate2_shared2("sai5_root", "sai5", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root", "sai6", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_SAI7_ROOT] = imx_clk_hw_gate2_shared2("sai7_root", "sai7", ccm_base + 0x4650, 0, &share_count_audio);
-	hws[IMX8MP_CLK_PDM_ROOT] = imx_clk_hw_gate2_shared2("pdm_root", "pdm", ccm_base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mp_dram_core_sels, ARRAY_SIZE(imx8mp_dram_core_sels), CLK_IS_CRITICAL);
+
+	hws[IMX8MP_CLK_DRAM1_ROOT] = imx_clk_hw_gate4_flags("dram1_root_clk", "dram_core_clk", base + 0x4050, 0, CLK_IS_CRITICAL);
+	hws[IMX8MP_CLK_ECSPI1_ROOT] = imx_clk_hw_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0);
+	hws[IMX8MP_CLK_ECSPI2_ROOT] = imx_clk_hw_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
+	hws[IMX8MP_CLK_ECSPI3_ROOT] = imx_clk_hw_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
+	hws[IMX8MP_CLK_ENET1_ROOT] = imx_clk_hw_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+	hws[IMX8MP_CLK_GPIO1_ROOT] = imx_clk_hw_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0);
+	hws[IMX8MP_CLK_GPIO2_ROOT] = imx_clk_hw_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0);
+	hws[IMX8MP_CLK_GPIO3_ROOT] = imx_clk_hw_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0);
+	hws[IMX8MP_CLK_GPIO4_ROOT] = imx_clk_hw_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0);
+	hws[IMX8MP_CLK_GPIO5_ROOT] = imx_clk_hw_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0);
+	hws[IMX8MP_CLK_GPT1_ROOT] = imx_clk_hw_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0);
+	hws[IMX8MP_CLK_GPT2_ROOT] = imx_clk_hw_gate4("gpt2_root_clk", "gpt2", base + 0x4110, 0);
+	hws[IMX8MP_CLK_GPT3_ROOT] = imx_clk_hw_gate4("gpt3_root_clk", "gpt3", base + 0x4120, 0);
+	hws[IMX8MP_CLK_GPT4_ROOT] = imx_clk_hw_gate4("gpt4_root_clk", "gpt4", base + 0x4130, 0);
+	hws[IMX8MP_CLK_GPT5_ROOT] = imx_clk_hw_gate4("gpt5_root_clk", "gpt5", base + 0x4140, 0);
+	hws[IMX8MP_CLK_GPT6_ROOT] = imx_clk_hw_gate4("gpt6_root_clk", "gpt6", base + 0x4150, 0);
+	hws[IMX8MP_CLK_I2C1_ROOT] = imx_clk_hw_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
+	hws[IMX8MP_CLK_I2C2_ROOT] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
+	hws[IMX8MP_CLK_I2C3_ROOT] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0);
+	hws[IMX8MP_CLK_I2C4_ROOT] = imx_clk_hw_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0);
+	hws[IMX8MP_CLK_MU_ROOT] = imx_clk_hw_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0);
+	hws[IMX8MP_CLK_OCOTP_ROOT] = imx_clk_hw_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0);
+	hws[IMX8MP_CLK_PCIE_ROOT] = imx_clk_hw_gate4("pcie_root_clk", "pcie_aux", base + 0x4250, 0);
+	hws[IMX8MP_CLK_PWM1_ROOT] = imx_clk_hw_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0);
+	hws[IMX8MP_CLK_PWM2_ROOT] = imx_clk_hw_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0);
+	hws[IMX8MP_CLK_PWM3_ROOT] = imx_clk_hw_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0);
+	hws[IMX8MP_CLK_PWM4_ROOT] = imx_clk_hw_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0);
+	hws[IMX8MP_CLK_QOS_ROOT] = imx_clk_hw_gate4("qos_root_clk", "ipg_root", base + 0x42c0, 0);
+	hws[IMX8MP_CLK_QOS_ENET_ROOT] = imx_clk_hw_gate4("qos_enet_root_clk", "ipg_root", base + 0x42e0, 0);
+	hws[IMX8MP_CLK_QSPI_ROOT] = imx_clk_hw_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0);
+	hws[IMX8MP_CLK_NAND_ROOT] = imx_clk_hw_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand);
+	hws[IMX8MP_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_hw_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0, &share_count_nand);
+	hws[IMX8MP_CLK_I2C5_ROOT] = imx_clk_hw_gate2("i2c5_root_clk", "i2c5", base + 0x4330, 0);
+	hws[IMX8MP_CLK_I2C6_ROOT] = imx_clk_hw_gate2("i2c6_root_clk", "i2c6", base + 0x4340, 0);
+	hws[IMX8MP_CLK_CAN1_ROOT] = imx_clk_hw_gate2("can1_root_clk", "can1", base + 0x4350, 0);
+	hws[IMX8MP_CLK_CAN2_ROOT] = imx_clk_hw_gate2("can2_root_clk", "can2", base + 0x4360, 0);
+	hws[IMX8MP_CLK_SDMA1_ROOT] = imx_clk_hw_gate4("sdma1_root_clk", "ipg_root", base + 0x43a0, 0);
+	hws[IMX8MP_CLK_SIM_ENET_ROOT] = imx_clk_hw_gate4("sim_enet_root_clk", "enet_axi", base + 0x4400, 0);
+	hws[IMX8MP_CLK_ENET_QOS_ROOT] = imx_clk_hw_gate4("enet_qos_root_clk", "sim_enet_root_clk", base + 0x43b0, 0);
+	hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", base + 0x4450, 0);
+	hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", base + 0x4460, 0);
+	hws[IMX8MP_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
+	hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
+	hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
+	hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
+	hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", base + 0x44d0, 0, &share_count_usb);
+	hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", base + 0x44d0, 0, &share_count_usb);
+	hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0);
+	hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
+	hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
+	hws[IMX8MP_CLK_WDOG1_ROOT] = imx_clk_hw_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0);
+	hws[IMX8MP_CLK_WDOG2_ROOT] = imx_clk_hw_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0);
+	hws[IMX8MP_CLK_WDOG3_ROOT] = imx_clk_hw_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0);
+	hws[IMX8MP_CLK_VPU_G1_ROOT] = imx_clk_hw_gate4("vpu_g1_root_clk", "vpu_g1", base + 0x4560, 0);
+	hws[IMX8MP_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_axi", base + 0x4570, 0);
+	hws[IMX8MP_CLK_VPU_VC8KE_ROOT] = imx_clk_hw_gate4("vpu_vc8ke_root_clk", "vpu_vc8000e", base + 0x4590, 0);
+	hws[IMX8MP_CLK_VPU_G2_ROOT] = imx_clk_hw_gate4("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0);
+	hws[IMX8MP_CLK_NPU_ROOT] = imx_clk_hw_gate4("npu_root_clk", "ml_core", base + 0x45b0, 0);
+	hws[IMX8MP_CLK_HSIO_ROOT] = imx_clk_hw_gate4("hsio_root_clk", "ipg_root", base + 0x45c0, 0);
+	hws[IMX8MP_CLK_MEDIA_APB_ROOT] = imx_clk_hw_gate2_shared2("media_apb_root_clk", "media_apb", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_AXI_ROOT] = imx_clk_hw_gate2_shared2("media_axi_root_clk", "media_axi", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam1_pix_root_clk", "media_cam1_pix", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam2_pix_root_clk", "media_cam2_pix", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT] = imx_clk_hw_gate2_shared2("media_mipi_phy1_ref_root", "media_mipi_phy1_ref", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_LDB_ROOT] = imx_clk_hw_gate2_shared2("media_ldb_root_clk", "media_ldb", base + 0x45d0, 0, &share_count_media);
+	hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", base + 0x45d0, 0, &share_count_media);
+
+	hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0);
+	hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", base + 0x45f0, 0);
+	hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", base + 0x4620, 0);
+	hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", base + 0x4630, 0);
+
+	hws[IMX8MP_CLK_AUDIO_AHB_ROOT] = imx_clk_hw_gate2_shared2("audio_ahb_root", "audio_ahb", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_AUDIO_AXI_ROOT] = imx_clk_hw_gate2_shared2("audio_axi_root", "audio_axi", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI1_ROOT] = imx_clk_hw_gate2_shared2("sai1_root", "sai1", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI2_ROOT] = imx_clk_hw_gate2_shared2("sai2_root", "sai2", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI3_ROOT] = imx_clk_hw_gate2_shared2("sai3_root", "sai3", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI5_ROOT] = imx_clk_hw_gate2_shared2("sai5_root", "sai5", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root", "sai6", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_SAI7_ROOT] = imx_clk_hw_gate2_shared2("sai7_root", "sai7", base + 0x4650, 0, &share_count_audio);
+	hws[IMX8MP_CLK_PDM_ROOT] = imx_clk_hw_gate2_shared2("pdm_root", "pdm", base + 0x4650, 0, &share_count_audio);
 
 	hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
 					     hws[IMX8MP_CLK_A53_CORE]->clk,
-- 
2.43.0



From angelogioacchino.delregno at collabora.com  Thu Mar  6 03:34:53 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu,  6 Mar 2025 12:34:53 +0100
Subject: [GIT,PULL,2/2] MediaTek driver updates for v6.15
In-Reply-To: <20250306113540.148342-1-angelogioacchino.delregno@collabora.com>
References: <20250306113540.148342-1-angelogioacchino.delregno@collabora.com>
Message-ID: <20250306113540.148342-2-angelogioacchino.delregno@collabora.com>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux.git tags/mtk-soc-for-v6.15

for you to fetch changes up to 1e12efbee8f3fe09d23ad75d2e38a6335ca2d159:

  soc: mediatek: mtk-socinfo: Add extra entry for MT8395AV/ZA Genio 1200 (2025-03-06 11:54:21 +0100)

----------------------------------------------------------------
MediaTek driver	updates for v6.15

This adds entries for new and missing SoCs in the MediaTek SoCInfo
driver (MT8370AV/AZA, MT8390AV/AZA) and	an extra entry for a new
revision of the	MT8395AV/ZA SoC.

The MediaTek SoCInfo driver also gets its SoC attribute	information
restructured: now the family, machine and soc_id fields are correctly
populated.

MT8188 gains support for the secondary Display Parallel Interface
used for HDMI, and for the Display Stream Compression component
routing through mmsys and mutex tables.

All of the MMSYS drivers get an important overhaul: it was found that,
in multiple cases, the tables contained wrong mask/value pairs, hence
those were doing either nothing or breaking routings.
The mmsys tables were converted to use a newly introduced macro that
will perform a compile time check, making sure that each table entry's
value fits in the declared register mask.

Thanks to the new macro, multiple MediaTek SoCs got multiple fixes in
their MMSYS tables, addressing issues that were severely impacting the
functionality of the display controller pipelines.

----------------------------------------------------------------
AngeloGioacchino Del Regno (8):
      soc: mediatek: mtk-mutex: Add DPI1 SOF/EOF to MT8188 mutex tables
      soc: mediatek: mtk-mmsys: Fix MT8188 VDO1 DPI1 output selection
      soc: mediatek: mtk-mmsys: Add compile time check for mmsys routes
      soc: mediatek: mt8188-mmsys: Migrate to MMSYS_ROUTE() macro
      soc: mediatek: mt8167-mmsys: Fix missing regval in all entries
      soc: mediatek: mt8365-mmsys: Fix routing table masks and values
      soc: mediatek: mmsys: Migrate all tables to MMSYS_ROUTE() macro
      soc: mediatek: mt8188-mmsys: Add support for DSC on VDO0

Fei Shao (1):
      soc: mediatek: mtk-socinfo: Restructure SoC attribute information

Louis-Alexis Eyraud (4):
      soc: mediatek: mtk-socinfo: Add entry for MT8370AV/AZA Genio 510
      soc: mediatek: mtk-socinfo: Add entry for MT8390AV/AZA Genio 700
      soc: mediatek: mtk-socinfo: Avoid using machine attribute in SoC detection log
      soc: mediatek: mtk-socinfo: Add extra entry for MT8395AV/ZA Genio 1200

 drivers/soc/mediatek/mt8167-mmsys.h |  31 +++--
 drivers/soc/mediatek/mt8173-mmsys.h |  99 +++++++---------
 drivers/soc/mediatek/mt8183-mmsys.h |  50 ++++----
 drivers/soc/mediatek/mt8186-mmsys.h |  88 ++++++--------
 drivers/soc/mediatek/mt8188-mmsys.h | 266 +++++++++++++++++++------------------------
 drivers/soc/mediatek/mt8192-mmsys.h |  71 +++++-------
 drivers/soc/mediatek/mt8195-mmsys.h | 632 +++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------
 drivers/soc/mediatek/mt8365-mmsys.h |  84 ++++++--------
 drivers/soc/mediatek/mtk-mmsys.h    |  14 +++
 drivers/soc/mediatek/mtk-mutex.c    |   6 +
 drivers/soc/mediatek/mtk-socinfo.c  |  22 +++-
 11 files changed, 597 insertions(+), 766 deletions(-)



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:56 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:56 +0100
Subject: [PATCH v10 07/18] arm64: dts: imx8mn: add anatop clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-8-dario.binacchi@amarulasolutions.com>

Add clocks to anatop node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mn.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index a5f9cfb46e5d..49be492b5687 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -606,6 +606,8 @@ anatop: clock-controller at 30360000 {
 				compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop";
 				reg = <0x30360000 0x10000>;
 				#clock-cells = <1>;
+				clocks = <&osc_32k>, <&osc_24m>;
+				clock-names = "osc_32k", "osc_24m";
 			};
 
 			snvs: snvs at 30370000 {
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:57 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:57 +0100
Subject: [PATCH v10 08/18] arm64: dts: imx8mp: add anatop clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-9-dario.binacchi@amarulasolutions.com>

Add clocks to anatop node.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index e0d3b8cba221..0b928e173f29 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -709,6 +709,8 @@ anatop: clock-controller at 30360000 {
 				compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop";
 				reg = <0x30360000 0x10000>;
 				#clock-cells = <1>;
+				clocks = <&osc_32k>, <&osc_24m>;
+				clock-names = "osc_32k", "osc_24m";
 			};
 
 			snvs: snvs at 30370000 {
-- 
2.43.0



From suzuki.poulose at arm.com  Thu Mar  6 03:39:14 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 6 Mar 2025 11:39:14 +0000
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <7b5c90cf-00e4-4684-8719-f380badab064@samsung.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
 <CGME20250303113525eucas1p1099e087e2c11b9021603a6f13f8135c4@eucas1p1.samsung.com>
 <2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>
 <7b5c90cf-00e4-4684-8719-f380badab064@samsung.com>
Message-ID: <7ad365f0-d335-4da1-845a-8fe3bc5eb055@arm.com>

On 04/03/2025 13:40, Marek Szyprowski wrote:
> Hi,
> 
> On 03.03.2025 12:35, Suzuki K Poulose wrote:
>> On 27/02/2025 14:41, Suzuki K Poulose wrote:
>>> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13.
>>> The address
>>> space (GPA or IPA) of a Realm VM is split into two halves, with
>>> private bottom
>>> half and shared top half. In Linux we treat the "top" bit of the IPA
>>> space as
>>> an attribute, to indicate whether it is shared or not (MSB == 1
>>> implies shared).
>>> Stage2 (GPA to PA) translations used by the CPU accesses, cover the
>>> full IPA space,
>>> and are managed by RMM. The "top" bit as attribute is only a software
>>> construct.
>>>
>>> At present any device passed through to a Realm is treated as
>>> untrusted and the
>>> Realm uses bounce buffering for any DMA, using the "decrypted"
>>> (shared) DMA
>>> buffers (i.e., IPA with top bit set). In Linux, we only send the
>>> "DMA" address
>>> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are
>>> managed by the
>>> non-secure Host and thus it can be confusing for the host/device when
>>> an unmasked
>>> address is provided. Given there could be other hypervisors than
>>> Linux/KVM
>>> running Arm CCA guests, the Realm Guest must adhere to a single
>>> convention for
>>> the DMA address. This gets further complicated when we add support
>>> for trusted
>>> devices, which can DMA into the full Realm memory space, once
>>> accepted. Thus,
>>> a DMA masked address (with "top" bit lost) will prevent a trusted
>>> device from
>>> accessing a shared buffer.
>>>
>>> To resolve this Arm has decided to standardise the DMA address used
>>> by the Realm
>>> to include the full IPA address bits (including the "top" bit, which
>>> Linux uses
>>> as an attribute). This implies, any DMA to a shared buffer must have
>>> the top bit
>>> of the IPA space set.
>>>
>>> There is already a provision to do this in phys_to_dma* and
>>> dma_to_phys(), but
>>> that is specific to AMD SME and is quite the opposite of what we need
>>> for Arm CCA.
>>> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and
>>> clear the bit
>>> for "encrypted".
>>>
>>> This series converts the existing __sme_* helpers to a bit more
>>> generalised versions :
>>> dma_addr_decrypted() and dma_encrypted(). Also, while converting a
>>> DMA address back
>>> to CPU physical address requires clearing off any
>>> "encryption/decryption" bits.
>>> I have named this "dma_addr_canonical()". (The other options are :
>>>  ?? * dma_addr_clear_encryption - Well, not just for encryption, but
>>> we clear decryption
>>>  ???? too, so not ideal.
>>>  ?? * dma_addr_normal
>>>  ?? * dma_addr_clear
>>>  ?? * dma_addr_default
>>>
>>> This also implies that the VMMs must take care to :
>>>
>>>  ? 1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>>>  ? 2. Always mask the "top" bit off any IPA it receives from the Realm
>>> for DMA.
>>>  ???? KVM already does that today and no changes are required.
>>>
>>> A kvmtool branch with the changes above is available here [1]. There
>>> are two
>>> patches [2] & [3], that are really required on top of the Arm CCA
>>> support.
>>>
>>> Ideally it would be good to get this backported to v6.13 stable
>>> kernel releases
>>> to make sure that they are compliant with this change.
>>>
>>
>> Please could you take a look at this series and let us know your
>> thoughts ? If you are happy with the changes, are you happy to pull
>> this through the DMA MAP tree ? The relevant bits have been reviewed/
>> acked by people (arm64 and AMD bits).
> 
> The changes look fine. However I won't be able to setup new dma-mapping
> git tree this week because I got really sick has to stay in bed. :/ If
> You don't want such delay, please merge it via ARM64 tree. Here is my:

Sorry to hear that. Hope you feel better soon.

> 
> Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>

Thanks Marek.

Btw, this series fixes the "Realm Guest" support for Linux, which was 
merged in v6.13. To be precise, this should have :

Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")

Will/Catalin,

Please let me know if you would like me to send the series with
all the Acks, Reviews and mainly the Fixes tag added ?

Kind regards
Suzuki

> 
> 
> Best regards



From piotr.oniszczuk at gmail.com  Thu Mar  6 03:47:31 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Thu, 6 Mar 2025 12:47:31 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
Message-ID: <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>


> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 09:53:
> 
> 
> Hi,
> 
> ? 2025-03-06 16:42:00?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>> 
>> 
>>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 01:59:
>>> 
>>> 
>>> 
>>> 
>>> Both of the two config options should be enabled.
>>> andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
>>> 4044:CONFIG_ROCKCHIP_DW_DP=y
>> 
>> here i?m a bit lost?.
>> greping on full kernel sources (with applied https://patchwork.kernel.org/project/linux-rockchip/list/?series=936784) gives me no single appearance of ROCKCHIP_DW_DP?
>> Do i miss something?
> 
> see PATCH 3/6:   
> 
> 
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 26c4410b2407..c8638baf9641 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
> select DRM_PANEL
> select VIDEOMODE_HELPERS
> select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
> + select DRM_DW_DP if ROCKCHIP_DW_DP
> select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
> select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
> select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
> @@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
>  RK3399 based SoC, you should select this
>  option.
> 
> +config ROCKCHIP_DW_DP
> + bool "Rockchip specific extensions for Synopsys DW DP"
> + help
> +  Choose this option for Synopsys DesignWare Cores DisplayPort
> +  transmit controller support on Rockchip SoC.
> 
> https://lore.kernel.org/linux-rockchip/047EECFC-7E55-44EC-896F-13FE04333E4D at gmail.com/T/#m178a325ea0ebc64187aae474d77c3f7a9e0bc93d
>> 


Ah my bad!
One patch patch was commented - so not all dp code was applied.

Now it is much better:

root at myth-frontend-56b0f018b5e0:~ # dmesg | grep drm
[    9.795380] panthor fb000000.gpu: [drm] clock rate = 198000000
[    9.796257] panthor fb000000.gpu: [drm] mali-g610 id 0xa867 major 0x0 minor 0x0 status 0x5
[    9.796262] panthor fb000000.gpu: [drm] Features: L2:0x7120306 Tiler:0x809 Mem:0x301 MMU:0x2830 AS:0xff
[    9.796265] panthor fb000000.gpu: [drm] shader_present=0x50005 l2_present=0x1 tiler_present=0x1
[    9.851869] panthor fb000000.gpu: [drm] Firmware protected mode entry not be supported, ignoring
[    9.851921] panthor fb000000.gpu: [drm] Firmware git sha: 814b47b551159067b67a37c4e9adda458ad9d852
[    9.852127] panthor fb000000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 Instrumentation features 0x71
[    9.852436] [drm] Initialized panthor 1.3.0 for fb000000.gpu on minor 0
[   10.003108] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
[   10.004705] rockchip-drm display-subsystem: bound fde60000.dp (ops dw_dp_rockchip_component_ops)
[   10.006085] rockchip-drm display-subsystem: bound fdea0000.hdmi (ops dw_hdmi_qp_rockchip_ops)
[   10.006679] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 1
[   10.006737] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
[   10.007663] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes

Unfortunately still nothing on screen

dri state: https://gist.github.com/warpme/5e971dfd2e9fd52fae76641831cebe46

and kernel dmesg https://termbin.com/r0m3

i?m not sure what is missing (some dts enablement or?.)
  








From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:54 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:54 +0100
Subject: [PATCH v10 05/18] dt-bindings: clock: imx8m-anatop: add oscillators and PLLs
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-6-dario.binacchi@amarulasolutions.com>

Though adding clocks and clock-names properties will break the ABI,
it is required to accurately describe the hardware. Indeed, the anatop
module uses the input oscillators to generate various PLLs. In turn,
the Clock Control Module (CCM) receives clocks from the PLLs and
oscillators and generates clocks for on-chip peripherals.

Furthermore, as agreed in [1], this change represents the first step
toward the implementation of the anatop driver. Currently, in fact,
there is no dedicated anatop driver, but the CCM driver parses the
anatop node and registers the PLLs it produces.

[1] https://lore.kernel.org/imx/20241106090549.3684963-1-dario.binacchi at amarulasolutions.com/
Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

(no changes since v7)

Changes in v7:
- Add 'Reviewed-by' tag of Krzysztof Kozlowski

Changes in v6:
- Improve commit message
- Merge it with patch 10, 11, and 12:
  - 10/20 dt-bindings: clock: imx8mm: add binding definitions for anatop
  - 11/20 dt-bindings: clock: imx8mn: add binding definitions for anatop
  - 12/20 dt-bindings: clock: imx8mp: add binding definitions for anatop

Changes in v4:
- New

 .../bindings/clock/fsl,imx8m-anatop.yaml      | 53 ++++++++++++++-
 include/dt-bindings/clock/imx8mm-clock.h      | 64 +++++++++++++++++
 include/dt-bindings/clock/imx8mn-clock.h      | 64 +++++++++++++++++
 include/dt-bindings/clock/imx8mp-clock.h      | 68 +++++++++++++++++++
 4 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml b/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml
index bbd22e95b319..f439b0a94ce2 100644
--- a/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml
+++ b/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml
@@ -30,22 +30,73 @@ properties:
   interrupts:
     maxItems: 1
 
+  clocks:
+    minItems: 2
+    maxItems: 3
+
+  clock-names:
+    minItems: 2
+    maxItems: 3
+
   '#clock-cells':
     const: 1
 
 required:
   - compatible
   - reg
+  - clocks
+  - clock-names
   - '#clock-cells'
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,imx8mq-anatop
+    then:
+      properties:
+        clocks:
+          items:
+            - description: 32k osc
+            - description: 25m osc
+            - description: 27m osc
+        clock-names:
+          items:
+            - const: ckil
+            - const: osc_25m
+            - const: osc_27m
+    else:
+      properties:
+        clocks:
+          items:
+            - description: 32k osc
+            - description: 24m osc
+
+        clock-names:
+          items:
+            - const: osc_32k
+            - const: osc_24m
+
 additionalProperties: false
 
 examples:
   - |
-    anatop: clock-controller at 30360000 {
+    clock-controller at 30360000 {
         compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop";
         reg = <0x30360000 0x10000>;
         #clock-cells = <1>;
+        clocks = <&osc_32k>, <&osc_24m>;
+        clock-names = "osc_32k", "osc_24m";
+    };
+
+  - |
+    clock-controller at 30360000 {
+        compatible = "fsl,imx8mq-anatop";
+        reg = <0x30360000 0x10000>;
+        #clock-cells = <1>;
+        clocks = <&ckil>, <&osc_25m>, <&osc_27m>;
+        clock-names = "ckil", "osc_25m", "osc_27m";
     };
 
 ...
diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h
index 102d8a6cdb55..017c06e48430 100644
--- a/include/dt-bindings/clock/imx8mm-clock.h
+++ b/include/dt-bindings/clock/imx8mm-clock.h
@@ -287,4 +287,68 @@
 
 #define IMX8MM_CLK_END				258
 
+#define IMX8MM_ANATOP_CLK_DUMMY			0
+#define IMX8MM_ANATOP_CLK_32K			1
+#define IMX8MM_ANATOP_CLK_24M			2
+#define IMX8MM_ANATOP_AUDIO_PLL1_REF_SEL	3
+#define IMX8MM_ANATOP_AUDIO_PLL2_REF_SEL	4
+#define IMX8MM_ANATOP_VIDEO_PLL_REF_SEL		5
+#define IMX8MM_ANATOP_DRAM_PLL_REF_SEL		6
+#define IMX8MM_ANATOP_GPU_PLL_REF_SEL		7
+#define IMX8MM_ANATOP_VPU_PLL_REF_SEL		8
+#define IMX8MM_ANATOP_ARM_PLL_REF_SEL		9
+#define IMX8MM_ANATOP_SYS_PLL3_REF_SEL		10
+#define IMX8MM_ANATOP_AUDIO_PLL1		11
+#define IMX8MM_ANATOP_AUDIO_PLL2		12
+#define IMX8MM_ANATOP_VIDEO_PLL			13
+#define IMX8MM_ANATOP_DRAM_PLL			14
+#define IMX8MM_ANATOP_GPU_PLL			15
+#define IMX8MM_ANATOP_VPU_PLL			16
+#define IMX8MM_ANATOP_ARM_PLL			17
+#define IMX8MM_ANATOP_SYS_PLL1			18
+#define IMX8MM_ANATOP_SYS_PLL2			19
+#define IMX8MM_ANATOP_SYS_PLL3			20
+#define IMX8MM_ANATOP_AUDIO_PLL1_BYPASS		21
+#define IMX8MM_ANATOP_AUDIO_PLL2_BYPASS		22
+#define IMX8MM_ANATOP_VIDEO_PLL_BYPASS		23
+#define IMX8MM_ANATOP_DRAM_PLL_BYPASS		24
+#define IMX8MM_ANATOP_GPU_PLL_BYPASS		25
+#define IMX8MM_ANATOP_VPU_PLL_BYPASS		26
+#define IMX8MM_ANATOP_ARM_PLL_BYPASS		27
+#define IMX8MM_ANATOP_SYS_PLL3_BYPASS		28
+#define IMX8MM_ANATOP_AUDIO_PLL1_OUT		29
+#define IMX8MM_ANATOP_AUDIO_PLL2_OUT		30
+#define IMX8MM_ANATOP_VIDEO_PLL_OUT		31
+#define IMX8MM_ANATOP_DRAM_PLL_OUT		32
+#define IMX8MM_ANATOP_GPU_PLL_OUT		33
+#define IMX8MM_ANATOP_VPU_PLL_OUT		34
+#define IMX8MM_ANATOP_ARM_PLL_OUT		35
+#define IMX8MM_ANATOP_SYS_PLL3_OUT		36
+#define IMX8MM_ANATOP_SYS_PLL1_OUT		37
+#define IMX8MM_ANATOP_SYS_PLL1_40M		38
+#define IMX8MM_ANATOP_SYS_PLL1_80M		39
+#define IMX8MM_ANATOP_SYS_PLL1_100M		40
+#define IMX8MM_ANATOP_SYS_PLL1_133M		41
+#define IMX8MM_ANATOP_SYS_PLL1_160M		42
+#define IMX8MM_ANATOP_SYS_PLL1_200M		43
+#define IMX8MM_ANATOP_SYS_PLL1_266M		44
+#define IMX8MM_ANATOP_SYS_PLL1_400M		45
+#define IMX8MM_ANATOP_SYS_PLL1_800M		46
+#define IMX8MM_ANATOP_SYS_PLL2_OUT		47
+#define IMX8MM_ANATOP_SYS_PLL2_50M		48
+#define IMX8MM_ANATOP_SYS_PLL2_100M		49
+#define IMX8MM_ANATOP_SYS_PLL2_125M		50
+#define IMX8MM_ANATOP_SYS_PLL2_166M		51
+#define IMX8MM_ANATOP_SYS_PLL2_200M		52
+#define IMX8MM_ANATOP_SYS_PLL2_250M		53
+#define IMX8MM_ANATOP_SYS_PLL2_333M		54
+#define IMX8MM_ANATOP_SYS_PLL2_500M		55
+#define IMX8MM_ANATOP_SYS_PLL2_1000M		56
+#define IMX8MM_ANATOP_CLK_CLKOUT1_SEL		57
+#define IMX8MM_ANATOP_CLK_CLKOUT1_DIV		58
+#define IMX8MM_ANATOP_CLK_CLKOUT1		59
+#define IMX8MM_ANATOP_CLK_CLKOUT2_SEL		60
+#define IMX8MM_ANATOP_CLK_CLKOUT2_DIV		61
+#define IMX8MM_ANATOP_CLK_CLKOUT2		62
+
 #endif
diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h
index 04809edab33c..b2fa73803d45 100644
--- a/include/dt-bindings/clock/imx8mn-clock.h
+++ b/include/dt-bindings/clock/imx8mn-clock.h
@@ -267,4 +267,68 @@
 
 #define IMX8MN_CLK_END				235
 
+#define IMX8MN_ANATOP_CLK_DUMMY			0
+#define IMX8MN_ANATOP_CLK_32K			1
+#define IMX8MN_ANATOP_CLK_24M			2
+#define IMX8MN_ANATOP_AUDIO_PLL1_REF_SEL	3
+#define IMX8MN_ANATOP_AUDIO_PLL2_REF_SEL	4
+#define IMX8MN_ANATOP_VIDEO_PLL_REF_SEL		5
+#define IMX8MN_ANATOP_DRAM_PLL_REF_SEL		6
+#define IMX8MN_ANATOP_GPU_PLL_REF_SEL		7
+#define IMX8MN_ANATOP_M7_ALT_PLL_REF_SEL	8
+#define IMX8MN_ANATOP_ARM_PLL_REF_SEL		9
+#define IMX8MN_ANATOP_SYS_PLL3_REF_SEL		10
+#define IMX8MN_ANATOP_AUDIO_PLL1		11
+#define IMX8MN_ANATOP_AUDIO_PLL2		12
+#define IMX8MN_ANATOP_VIDEO_PLL			13
+#define IMX8MN_ANATOP_DRAM_PLL			14
+#define IMX8MN_ANATOP_GPU_PLL			15
+#define IMX8MN_ANATOP_M7_ALT_PLL		16
+#define IMX8MN_ANATOP_ARM_PLL			17
+#define IMX8MN_ANATOP_SYS_PLL1			18
+#define IMX8MN_ANATOP_SYS_PLL2			19
+#define IMX8MN_ANATOP_SYS_PLL3			20
+#define IMX8MN_ANATOP_AUDIO_PLL1_BYPASS		21
+#define IMX8MN_ANATOP_AUDIO_PLL2_BYPASS		22
+#define IMX8MN_ANATOP_VIDEO_PLL_BYPASS		23
+#define IMX8MN_ANATOP_DRAM_PLL_BYPASS		24
+#define IMX8MN_ANATOP_GPU_PLL_BYPASS		25
+#define IMX8MN_ANATOP_M7_ALT_PLL_BYPASS		26
+#define IMX8MN_ANATOP_ARM_PLL_BYPASS		27
+#define IMX8MN_ANATOP_SYS_PLL3_BYPASS		28
+#define IMX8MN_ANATOP_AUDIO_PLL1_OUT		29
+#define IMX8MN_ANATOP_AUDIO_PLL2_OUT		30
+#define IMX8MN_ANATOP_VIDEO_PLL_OUT		31
+#define IMX8MN_ANATOP_DRAM_PLL_OUT		32
+#define IMX8MN_ANATOP_GPU_PLL_OUT		33
+#define IMX8MN_ANATOP_M7_ALT_PLL_OUT		34
+#define IMX8MN_ANATOP_ARM_PLL_OUT		35
+#define IMX8MN_ANATOP_SYS_PLL3_OUT		36
+#define IMX8MN_ANATOP_SYS_PLL1_OUT		37
+#define IMX8MN_ANATOP_SYS_PLL1_40M		38
+#define IMX8MN_ANATOP_SYS_PLL1_80M		39
+#define IMX8MN_ANATOP_SYS_PLL1_100M		40
+#define IMX8MN_ANATOP_SYS_PLL1_133M		41
+#define IMX8MN_ANATOP_SYS_PLL1_160M		42
+#define IMX8MN_ANATOP_SYS_PLL1_200M		43
+#define IMX8MN_ANATOP_SYS_PLL1_266M		44
+#define IMX8MN_ANATOP_SYS_PLL1_400M		45
+#define IMX8MN_ANATOP_SYS_PLL1_800M		46
+#define IMX8MN_ANATOP_SYS_PLL2_OUT		47
+#define IMX8MN_ANATOP_SYS_PLL2_50M		48
+#define IMX8MN_ANATOP_SYS_PLL2_100M		49
+#define IMX8MN_ANATOP_SYS_PLL2_125M		50
+#define IMX8MN_ANATOP_SYS_PLL2_166M		51
+#define IMX8MN_ANATOP_SYS_PLL2_200M		52
+#define IMX8MN_ANATOP_SYS_PLL2_250M		53
+#define IMX8MN_ANATOP_SYS_PLL2_333M		54
+#define IMX8MN_ANATOP_SYS_PLL2_500M		55
+#define IMX8MN_ANATOP_SYS_PLL2_1000M		56
+#define IMX8MN_ANATOP_CLK_CLKOUT1_SEL		57
+#define IMX8MN_ANATOP_CLK_CLKOUT1_DIV		58
+#define IMX8MN_ANATOP_CLK_CLKOUT1		59
+#define IMX8MN_ANATOP_CLK_CLKOUT2_SEL		60
+#define IMX8MN_ANATOP_CLK_CLKOUT2_DIV		61
+#define IMX8MN_ANATOP_CLK_CLKOUT2		62
+
 #endif
diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h
index 3235d7de3b62..8c076225fd9e 100644
--- a/include/dt-bindings/clock/imx8mp-clock.h
+++ b/include/dt-bindings/clock/imx8mp-clock.h
@@ -402,4 +402,72 @@
 
 #define IMX8MP_CLK_AUDIOMIX_END			59
 
+#define IMX8MP_ANATOP_CLK_DUMMY			0
+#define IMX8MP_ANATOP_CLK_24M			1
+#define IMX8MP_ANATOP_CLK_32K			2
+#define IMX8MP_ANATOP_AUDIO_PLL1_REF_SEL	3
+#define IMX8MP_ANATOP_AUDIO_PLL2_REF_SEL	4
+#define IMX8MP_ANATOP_VIDEO_PLL_REF_SEL		5
+#define IMX8MP_ANATOP_DRAM_PLL_REF_SEL		6
+#define IMX8MP_ANATOP_GPU_PLL_REF_SEL		7
+#define IMX8MP_ANATOP_VPU_PLL_REF_SEL		8
+#define IMX8MP_ANATOP_ARM_PLL_REF_SEL		9
+#define IMX8MP_ANATOP_SYS_PLL1_REF_SEL		10
+#define IMX8MP_ANATOP_SYS_PLL2_REF_SEL		11
+#define IMX8MP_ANATOP_SYS_PLL3_REF_SEL		12
+#define IMX8MP_ANATOP_AUDIO_PLL1		13
+#define IMX8MP_ANATOP_AUDIO_PLL2		14
+#define IMX8MP_ANATOP_VIDEO_PLL			15
+#define IMX8MP_ANATOP_DRAM_PLL			16
+#define IMX8MP_ANATOP_GPU_PLL			17
+#define IMX8MP_ANATOP_VPU_PLL			18
+#define IMX8MP_ANATOP_ARM_PLL			19
+#define IMX8MP_ANATOP_SYS_PLL1			20
+#define IMX8MP_ANATOP_SYS_PLL2			21
+#define IMX8MP_ANATOP_SYS_PLL3			22
+#define IMX8MP_ANATOP_AUDIO_PLL1_BYPASS		23
+#define IMX8MP_ANATOP_AUDIO_PLL2_BYPASS		24
+#define IMX8MP_ANATOP_VIDEO_PLL_BYPASS		25
+#define IMX8MP_ANATOP_DRAM_PLL_BYPASS		26
+#define IMX8MP_ANATOP_GPU_PLL_BYPASS		27
+#define IMX8MP_ANATOP_VPU_PLL_BYPASS		28
+#define IMX8MP_ANATOP_ARM_PLL_BYPASS		29
+#define IMX8MP_ANATOP_SYS_PLL1_BYPASS		30
+#define IMX8MP_ANATOP_SYS_PLL2_BYPASS		31
+#define IMX8MP_ANATOP_SYS_PLL3_BYPASS		32
+#define IMX8MP_ANATOP_AUDIO_PLL1_OUT		33
+#define IMX8MP_ANATOP_AUDIO_PLL2_OUT		34
+#define IMX8MP_ANATOP_VIDEO_PLL_OUT		35
+#define IMX8MP_ANATOP_DRAM_PLL_OUT		36
+#define IMX8MP_ANATOP_GPU_PLL_OUT		37
+#define IMX8MP_ANATOP_VPU_PLL_OUT		38
+#define IMX8MP_ANATOP_ARM_PLL_OUT		39
+#define IMX8MP_ANATOP_SYS_PLL3_OUT		40
+#define IMX8MP_ANATOP_SYS_PLL1_OUT		41
+#define IMX8MP_ANATOP_SYS_PLL1_40M		42
+#define IMX8MP_ANATOP_SYS_PLL1_80M		43
+#define IMX8MP_ANATOP_SYS_PLL1_100M		44
+#define IMX8MP_ANATOP_SYS_PLL1_133M		45
+#define IMX8MP_ANATOP_SYS_PLL1_160M		46
+#define IMX8MP_ANATOP_SYS_PLL1_200M		47
+#define IMX8MP_ANATOP_SYS_PLL1_266M		48
+#define IMX8MP_ANATOP_SYS_PLL1_400M		49
+#define IMX8MP_ANATOP_SYS_PLL1_800M		50
+#define IMX8MP_ANATOP_SYS_PLL2_OUT		51
+#define IMX8MP_ANATOP_SYS_PLL2_50M		52
+#define IMX8MP_ANATOP_SYS_PLL2_100M		53
+#define IMX8MP_ANATOP_SYS_PLL2_125M		54
+#define IMX8MP_ANATOP_SYS_PLL2_166M		55
+#define IMX8MP_ANATOP_SYS_PLL2_200M		56
+#define IMX8MP_ANATOP_SYS_PLL2_250M		57
+#define IMX8MP_ANATOP_SYS_PLL2_333M		58
+#define IMX8MP_ANATOP_SYS_PLL2_500M		59
+#define IMX8MP_ANATOP_SYS_PLL2_1000M		60
+#define IMX8MP_ANATOP_CLK_CLKOUT1_SEL		61
+#define IMX8MP_ANATOP_CLK_CLKOUT1_DIV		62
+#define IMX8MP_ANATOP_CLK_CLKOUT1		63
+#define IMX8MP_ANATOP_CLK_CLKOUT2_SEL		64
+#define IMX8MP_ANATOP_CLK_CLKOUT2_DIV		65
+#define IMX8MP_ANATOP_CLK_CLKOUT2		66
+
 #endif
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Thu Mar  6 03:27:55 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu,  6 Mar 2025 12:27:55 +0100
Subject: [PATCH v10 06/18] arm64: dts: imx8mm: add anatop clocks
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250306112959.242131-7-dario.binacchi@amarulasolutions.com>

Add clocks to anatop node.

Add the bindings definitions for the anatop node. The patch is
preparatory for future developments.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

---

(no changes since v4)

Changes in v4:
- New

 arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 4de3bf22902b..597041a05073 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -600,6 +600,8 @@ anatop: clock-controller at 30360000 {
 				compatible = "fsl,imx8mm-anatop";
 				reg = <0x30360000 0x10000>;
 				#clock-cells = <1>;
+				clocks = <&osc_32k>, <&osc_24m>;
+				clock-names = "osc_32k", "osc_24m";
 			};
 
 			snvs: snvs at 30370000 {
-- 
2.43.0



From masahiroy at kernel.org  Thu Mar  6 03:36:21 2025
From: masahiroy at kernel.org (Masahiro Yamada)
Date: Thu, 6 Mar 2025 20:36:21 +0900
Subject: [PATCH] kbuild: rust: add rustc-min-version support function
In-Reply-To: <CANiq72n=95jgJs17NFAkit5uzxqtO9xij9Um3ybd_RiMCpFrDQ@mail.gmail.com>
References: <20250210164245.282886-1-ojeda@kernel.org> <CAK7LNAQBFX5q6yyKBJoxMoD5d9SwdKm0c23J4+LpjwA1eh=bZw@mail.gmail.com>
 <CANiq72n=95jgJs17NFAkit5uzxqtO9xij9Um3ybd_RiMCpFrDQ@mail.gmail.com>
Message-ID: <CAK7LNAQC5Q5EQjuvMEWS5NAs-pixj3b--rkCHZ=xGQDTHqBBFQ@mail.gmail.com>

On Sat, Feb 15, 2025 at 3:48?AM Miguel Ojeda
<miguel.ojeda.sandonis at gmail.com> wrote:
>
> On Fri, Feb 14, 2025 at 2:39?AM Masahiro Yamada <masahiroy at kernel.org> wrote:
> >
> > Do you want me to pick it up to kbuild tree,
> > or will you take it with my Ack?
> >
> > If you go with the latter,
> > Acked-by: Masahiro Yamada <masahiroy at kernel.org>
>
> Thanks a lot Masahiro -- happy to take it on my side if that means
> less work for you.
>
> Cheers,
> Miguel
>

This has not been picked up by any one in linux-next.

I applied this to linux-kbuild now. Thanks.




--
Best Regards
Masahiro Yamada


From sudeep.holla at arm.com  Thu Mar  6 04:42:39 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 6 Mar 2025 12:42:39 +0000
Subject: [PATCH v3] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <CAPDyKForY4VNZtqietDPt2FQM3p4OsaoE_oJb0PPLUAh98WsHQ@mail.gmail.com>
References: <20250306061805.2318154-1-ping.bai@nxp.com>
 <CAPDyKForY4VNZtqietDPt2FQM3p4OsaoE_oJb0PPLUAh98WsHQ@mail.gmail.com>
Message-ID: <Z8mYP7AGBPeDTvXn@bogus>

On Thu, Mar 06, 2025 at 11:53:14AM +0100, Ulf Hansson wrote:
> On Thu, 6 Mar 2025 at 07:17, Jacky Bai <ping.bai at nxp.com> wrote:
> >
> > for_each_possible_cpu() is currently used to initialize cpuidle
> > in the PSCI cpuidle driver.
> >
> > However, in cpu_dev_register_generic(), for_each_present_cpu()
> > is used to register CPU devices which means the CPU devices are
> > only registered for present CPUs and not all possible CPUs.
> >
> > With nosmp or maxcpus=0, only the boot CPU is present, leading
> > to the failure:
> >
> >   |  Failed to register cpuidle device for cpu1
> >
> > Change for_each_possible_cpu() to for_each_present_cpu() in the
> > PSCI cpuidle driver to ensure it only registers cpuidle devices
> > for CPUs that are actually present.
> >
> > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> 
> Is this problem specific to cpuidle-psci?
> 
> Others are using for_each_possible_cpu() when registering their cpuidle drivers.
> 

Good point. I assumed as this was very old patch, only this is left without
conversion to using present_cpumask. Looks like there are many other drivers
that need similar change. May be PSCI is most commonly used ones these days
and hardly anyone tests with nosmp or maxcpus=1 on those platforms.

But yes, all the users of for_each_possible_cpu() need to move to
for_each_present_cpu() if they are relying on CPU device being registered.

-- 
Regards,
Sudeep


From amadeus at jmu.edu.cn  Thu Mar  6 04:38:07 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 20:38:07 +0800
Subject: [PATCH v2 0/2] arm64: dts: rockchip: Add rk3528 QoS register node
Message-ID: <20250306123809.273655-1-amadeus@jmu.edu.cn>

Changes in v2:
  Improve commit message
  Add missing QoS compatible in DT

Chukun Pan (2):
  dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
  arm64: dts: rockchip: Add rk3528 QoS register node

 .../devicetree/bindings/mfd/syscon.yaml       |   2 +
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 160 ++++++++++++++++++
 2 files changed, 162 insertions(+)

-- 
2.25.1



From amadeus at jmu.edu.cn  Thu Mar  6 04:38:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 20:38:08 +0800
Subject: [PATCH v2 1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
In-Reply-To: <20250306123809.273655-1-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
Message-ID: <20250306123809.273655-2-amadeus@jmu.edu.cn>

Document rk3528 compatible for QoS registers.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 4d67ff26d445..2836e4793afc 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -103,6 +103,7 @@ select:
           - rockchip,rk3288-qos
           - rockchip,rk3368-qos
           - rockchip,rk3399-qos
+          - rockchip,rk3528-qos
           - rockchip,rk3562-qos
           - rockchip,rk3568-qos
           - rockchip,rk3576-qos
@@ -202,6 +203,7 @@ properties:
           - rockchip,rk3288-qos
           - rockchip,rk3368-qos
           - rockchip,rk3399-qos
+          - rockchip,rk3528-qos
           - rockchip,rk3562-qos
           - rockchip,rk3568-qos
           - rockchip,rk3576-qos
-- 
2.25.1



From amadeus at jmu.edu.cn  Thu Mar  6 04:38:09 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 20:38:09 +0800
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250306123809.273655-1-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
Message-ID: <20250306123809.273655-3-amadeus@jmu.edu.cn>

The Quality-of-Service (QsS) node stores/restores specific
register contents when the power domains is turned off/on.
Add QoS node so that they can connect to the power domain.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index b1713ed4d7e2..0c0e7f151462 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -129,6 +129,166 @@ gic: interrupt-controller at fed01000 {
 			#interrupt-cells = <3>;
 		};
 
+		qos_crypto_a: qos at ff200000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200000 0x0 0x20>;
+		};
+
+		qos_crypto_p: qos at ff200080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200080 0x0 0x20>;
+		};
+
+		qos_dcf: qos at ff200100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200100 0x0 0x20>;
+		};
+
+		qos_dft2apb: qos at ff200200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200200 0x0 0x20>;
+		};
+
+		qos_dma2ddr: qos at ff200280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200280 0x0 0x20>;
+		};
+
+		qos_dmac: qos at ff200300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200300 0x0 0x20>;
+		};
+
+		qos_keyreader: qos at ff200380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff200380 0x0 0x20>;
+		};
+
+		qos_cpu: qos at ff210000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff210000 0x0 0x20>;
+		};
+
+		qos_debug: qos at ff210080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff210080 0x0 0x20>;
+		};
+
+		qos_gpu_m0: qos at ff220000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff220000 0x0 0x20>;
+		};
+
+		qos_gpu_m1: qos at ff220080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff220080 0x0 0x20>;
+		};
+
+		qos_pmu_mcu: qos at ff240000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff240000 0x0 0x20>;
+		};
+
+		qos_rkvdec: qos at ff250000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff250000 0x0 0x20>;
+		};
+
+		qos_rkvenc: qos at ff260000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff260000 0x0 0x20>;
+		};
+
+		qos_gmac0: qos at ff270000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270000 0x0 0x20>;
+		};
+
+		qos_hdcp: qos at ff270080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270080 0x0 0x20>;
+		};
+
+		qos_jpegdec: qos at ff270100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270100 0x0 0x20>;
+		};
+
+		qos_rga2_m0ro: qos at ff270200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270200 0x0 0x20>;
+		};
+
+		qos_rga2_m0wo: qos at ff270280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270280 0x0 0x20>;
+		};
+
+		qos_sdmmc0: qos at ff270300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270300 0x0 0x20>;
+		};
+
+		qos_usb2host: qos at ff270380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270380 0x0 0x20>;
+		};
+
+		qos_vdpp: qos at ff270480 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270480 0x0 0x20>;
+		};
+
+		qos_vop: qos at ff270500 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff270500 0x0 0x20>;
+		};
+
+		qos_emmc: qos at ff280000 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280000 0x0 0x20>;
+		};
+
+		qos_fspi: qos at ff280080 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280080 0x0 0x20>;
+		};
+
+		qos_gmac1: qos at ff280100 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280100 0x0 0x20>;
+		};
+
+		qos_pcie: qos at ff280180 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280180 0x0 0x20>;
+		};
+
+		qos_sdio0: qos at ff280200 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280200 0x0 0x20>;
+		};
+
+		qos_sdio1: qos at ff280280 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280280 0x0 0x20>;
+		};
+
+		qos_tsp: qos at ff280300 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280300 0x0 0x20>;
+		};
+
+		qos_usb3otg: qos at ff280380 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280380 0x0 0x20>;
+		};
+
+		qos_vpu: qos at ff280400 {
+			compatible = "rockchip,rk3528-qos", "syscon";
+			reg = <0x0 0xff280400 0x0 0x20>;
+		};
+
 		cru: clock-controller at ff4a0000 {
 			compatible = "rockchip,rk3528-cru";
 			reg = <0x0 0xff4a0000 0x0 0x30000>;
-- 
2.25.1



From Friday.Yang at mediatek.com  Thu Mar  6 04:45:48 2025
From: Friday.Yang at mediatek.com (=?utf-8?B?RnJpZGF5IFlhbmcgKOadqOmYsyk=?=)
Date: Thu, 6 Mar 2025 12:45:48 +0000
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
	 <20250221074846.14105-2-friday.yang@mediatek.com>
	 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
Message-ID: <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>

On Mon, 2025-02-24 at 09:41 +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 21/02/25 08:48, Friday Yang ha scritto:
> > From: "Friday Yang" <friday.yang at mediatek.com>
> > 
> > On the MediaTek platform, some SMI LARBs are directly connected to
> > the SMI Common, while others are connected to the SMI Sub-Common,
> > which in turn is connected to the SMI Common. The hardware block
> > diagram can be described as follows.
> > 
> >               SMI-Common(Smart Multimedia Interface Common)
> >                   |
> >           +----------------+------------------+
> >           |                |                  |
> >           |                |                  |
> >           |                |                  |
> >           |                |                  |
> >           |                |                  |
> >         larb0       SMI-Sub-Common0     SMI-Sub-Common1
> >                     |      |     |      |             |
> >                    larb1  larb2 larb3  larb7       larb9
> > 
> > For previous discussion on the direction of the code modifications,
> > please refer to:
> > https://lore.kernel.org/all/CAFGrd9qZhObQXvm2_abqaX83xMLqxjQETB2=
> > wXpobDWU1CnvkA at mail.gmail.com/
> > https://lore.kernel.org/all/CAPDyKFpokXV2gJDgowbixTvOH_5VL3B5H8ey
> > hP+KJ5Fasm2rFg at mail.gmail.com/
> > 
> > On the MediaTek MT8188 SoC platform, we encountered power-off
> > failures
> > and SMI bus hang issues during camera stress tests. The issue
> > arises
> > because bus glitches are sometimes produced when MTCMOS powers on
> > or
> > off. While this is fairly normal, the software must handle these
> > glitches to avoid mistaking them for transaction signals. What's
> > more, this issue emerged only after the initial upstreaming of this
> > binding. Without these patches, the SMI becomes unstable during
> > camera
> > stress tests.
> > 
> > The software solutions can be summarized as follows:
> > 
> > 1. Use CLAMP to disable the SMI sub-common port after turning off
> > the
> >     LARB CG and before turning off the LARB MTCMOS.
> > 2. Use CLAMP to disable/enable the SMI sub-common port.
> > 3. Implement an AXI reset for SMI LARBs.
> > 
> > This patch primarily add two changes:
> > 1. Add compatible for SMI sub-common on MT8188 SoC.
> > 2. Add 'resets' and 'reset-names' properties for SMI LARBs to
> >     support SMI reset operations.
> > 
> > Signed-off-by: Friday Yang <friday.yang at mediatek.com>
> > ---
> >   .../mediatek,smi-common.yaml                  |  2 ++
> >   .../memory-controllers/mediatek,smi-larb.yaml | 20
> > +++++++++++++++++++
> >   2 files changed, 22 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-common.yaml
> > b/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-common.yaml
> > index 2f36ac23604c..4392d349878c 100644
> > --- a/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-common.yaml
> > +++ b/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-common.yaml
> > @@ -39,6 +39,7 @@ properties:
> >             - mediatek,mt8186-smi-common
> >             - mediatek,mt8188-smi-common-vdo
> >             - mediatek,mt8188-smi-common-vpp
> > +          - mediatek,mt8188-smi-sub-common
> >             - mediatek,mt8192-smi-common
> >             - mediatek,mt8195-smi-common-vdo
> >             - mediatek,mt8195-smi-common-vpp
> > @@ -107,6 +108,7 @@ allOf:
> >           compatible:
> >             contains:
> >               enum:
> > +              - mediatek,mt8188-smi-sub-common
> >                 - mediatek,mt8195-smi-sub-common
> >       then:
> >         required:
> > diff --git a/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-larb.yaml
> > b/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-larb.yaml
> > index 2381660b324c..2e86bb3455f9 100644
> > --- a/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-larb.yaml
> > +++ b/Documentation/devicetree/bindings/memory-
> > controllers/mediatek,smi-larb.yaml
> > @@ -69,6 +69,12 @@ properties:
> >       description: the hardware id of this larb. It's only required
> > when this
> >         hardware id is not consecutive from its M4U point of view.
> > 
> > +  resets:
> > +    maxItems: 1
> > +
> > +  reset-names:
> > +    const: larb
> > +
> >   required:
> >     - compatible
> >     - reg
> > @@ -125,6 +131,20 @@ allOf:
> >         required:
> >           - mediatek,larb-id
> > 
> > +  - if:  # only for image, camera and ipe subsys
> > +      properties:
> > +        compatible:
> > +          const: mediatek,mt8188-smi-larb
> > +        mediatek,larb-id:
> > +          oneOf:
> 
> Are you really sure that you need 'oneOf' here? :-)
> 
> Regards,
> Angelo

Yes, I have tested it. If I try to modify the 'examples'
like this. That is:
  change the compatible to "mediatek,mt8188-smi-larb",
  add 'mediatek,larb-id = <10>;'

examples:
  - |+
    #include <dt-bindings/clock/mt8173-clk.h>
    #includ
e <dt-bindings/power/mt8173-power.h>

    larb1: larb at 16010000 {
      compatible = "mediatek,mt8188-smi-larb";
      reg = <0x16010000 0x1000>;
      mediatek,smi = <&smi_common>;
      mediatek,larb-id = <10>;
      power-domains = <&scpsys MT8188_POWER_DOMAIN_VDEC>;
      clocks = <&vdecsys CLK_VDEC_CKEN>,
               <&vdecsys CLK_VDEC_LARB_CKEN>;
      clock-names = "apb", "smi";
    };

The 'dt_binding_check' could give the following
errors:

Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
larb.example.dtb: larb at 16010000: 'resets' is a required property
from schema $id: 
http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml#
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
larb.example.dtb: larb at 16010000: 'reset-names' is a required property
from schema $id:  
http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml#

And this is what I want to achieve. On the MediaTek MT8188 SoC
platform, 'resets' and 'reset-names' are only required for SMI LARBs
located in image, camera and ipe subsys. Others can be ignored. And the
'larb-id' of these SMI LARBs are shown in this array: [ 9, 10, 11, 12,
13, 16, 17, 18, 19, 20 ].

Please feel free to let me know if you have any doubts.

> 
> > +            - enum:
> > +                [ 9, 10, 11, 12, 13, 16, 17, 18, 19, 20 ]
> > +
> > +    then:
> > +      required:
> > +        - resets
> > +        - reset-names
> > +
> >   additionalProperties: false
> > 
> >   examples:
> > --
> > 2.46.0
> > 
> 
> 
> 

From krzk at kernel.org  Thu Mar  6 04:48:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 13:48:13 +0100
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
 <20250221074846.14105-2-friday.yang@mediatek.com>
 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
 <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
Message-ID: <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>

On 06/03/2025 13:45, Friday Yang (??) wrote:
>>> +          const: mediatek,mt8188-smi-larb
>>> +        mediatek,larb-id:
>>> +          oneOf:
>>
>> Are you really sure that you need 'oneOf' here? :-)
>>
>> Regards,
>> Angelo
> 
> Yes, I have tested it. If I try to modify the 'examples'
> like this. That is:
>   change the compatible to "mediatek,mt8188-smi-larb",
>   add 'mediatek,larb-id = <10>;'
> 
> examples:
>   - |+
>     #include <dt-bindings/clock/mt8173-clk.h>
>     #includ
> e <dt-bindings/power/mt8173-power.h>
> 
>     larb1: larb at 16010000 {
>       compatible = "mediatek,mt8188-smi-larb";
>       reg = <0x16010000 0x1000>;
>       mediatek,smi = <&smi_common>;
>       mediatek,larb-id = <10>;
>       power-domains = <&scpsys MT8188_POWER_DOMAIN_VDEC>;
>       clocks = <&vdecsys CLK_VDEC_CKEN>,
>                <&vdecsys CLK_VDEC_LARB_CKEN>;
>       clock-names = "apb", "smi";
>     };
> 
> The 'dt_binding_check' could give the following
> errors:
> 
> Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
> larb.example.dtb: larb at 16010000: 'resets' is a required property
> from schema $id: 
> http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml#
> Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
> larb.example.dtb: larb at 16010000: 'reset-names' is a required property
> from schema $id:  
> http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml#
> 
> And this is what I want to achieve. On the MediaTek MT8188 SoC
> platform, 'resets' and 'reset-names' are only required for SMI LARBs
> located in image, camera and ipe subsys. Others can be ignored. And the
> 'larb-id' of these SMI LARBs are shown in this array: [ 9, 10, 11, 12,
> 13, 16, 17, 18, 19, 20 ].
> 
> Please feel free to let me know if you have any doubts.

You did not really answer the question. Where is anything about oneOf in
your reply?

I am dropping this patchset from my queue.

Best regards,
Krzysztof


From linux at armlinux.org.uk  Thu Mar  6 04:48:13 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 6 Mar 2025 12:48:13 +0000
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <20250304154330.6e00961b@fedora.home>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
 <20250303090321.805785-10-maxime.chevallier@bootlin.com>
 <20250304154330.6e00961b@fedora.home>
Message-ID: <Z8mZjabeITVg1Khg@shell.armlinux.org.uk>

On Tue, Mar 04, 2025 at 03:43:30PM +0100, Maxime Chevallier wrote:
> On Mon,  3 Mar 2025 10:03:15 +0100
> Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:
> 
> > When phylink creates a fixed-link configuration, it finds a matching
> > linkmode to set as the advertised, lp_advertising and supported modes
> > based on the speed and duplex of the fixed link.
> > 
> > Use the newly introduced phy_caps_lookup to get these modes instead of
> > phy_lookup_settings(). This has the side effect that the matched
> > settings and configured linkmodes may now contain several linkmodes (the
> > intersection of supported linkmodes from the phylink settings and the
> > linkmodes that match speed/duplex) instead of the one from
> > phy_lookup_settings().
> > 
> > Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> > ---
> 
> Maybe before anything goes further with this patch, I'd like to get
> some feedback from it on a particular point. This changes the linkmodes
> that are reported on fixed-link interfaces. Instead of reporting one
> single mode, we report all modes supported by the fixed-link' speed and
> duplex settings.

This is a good question. We have historically only used the baseT link
modes because the software PHY implementation was based around clause
22 baseT PHYs (although that doesn't support >1G of course.)

The real question is... does it matter, to which I'd say I don't know.
One can argue that it shouldn't matter, and I think userspace would be
unlikely to break, but userspace tends to do weird stuff all the time
so there's never any guarantee.

> The fixed-link in question is for the CPU port of a DSA switch.
> 
> In my opinion, this is OK as the linkmodes expressed here don't match
> physical linkmodes on an actual wire, but as this is a user visible
> change, I'd like to make sure this is OK. Any comment here is more than
> welcome.

Maybe Andrew has an opinion, but I suspect like me, it's really a case
that "we don't know".

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From cristian.marussi at arm.com  Thu Mar  6 04:50:17 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Thu, 6 Mar 2025 12:50:17 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8mCbc2Z2QGd3f8M@google.com>
References: <Z8g8vhS9rqQ_ez48@google.com>
 <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com>
Message-ID: <Z8maCX5QJRqODl6u@pluto>

On Thu, Mar 06, 2025 at 11:09:33AM +0000, Alice Ryhl wrote:
> On Wed, Mar 05, 2025 at 05:10:16PM +0000, Cristian Marussi wrote:
> > On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> > > Dear SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message
> > > Protocol drivers maintainers,
> > > 
> > > I flashed a v6.13-rc3 kernel onto a Rock5B board and noticed the
> > > following output in my terminal:
> > > 
> > > [  687.694465] kmemleak: 4 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
> > > 
> > > It seems that there is a memory leak for devices created with
> > > scmi_device_create.
> > > 
> > `
> > Hi Alice,
> > 
> > thanks for this report.
> > 
> > > This was with a kernel running v6.13-rc3, but as far as I can tell, no
> > > relevant changes have landed since v6.13-rc3. My tree *does* include
> > > commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> > > scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> > > not happening consistently.
> > > 
> > > See below for the full kmemleak report.
> > > 
> > > Alice
> > > 
> > > $ sudo cat /sys/kernel/debug/kmemleak
> > > unreferenced object 0xffffff8106c86000 (size 2048):
> > >   comm "swapper/0", pid 1, jiffies 4294893094
> > >   hex dump (first 32 bytes):
> > >     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
> > >     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
> > >   backtrace (crc feae9680):
> > >     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
> > >     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
> > >     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
> > >     [<000000008714917b>] scmi_device_create+0x40/0x194
> > >     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
> > >     [<00000000970bad38>] scmi_probe+0x584/0xa78
> > >     [<000000002600d2fd>] platform_probe+0xbc/0xf0
> > >     [<00000000f6f556b4>] really_probe+0x1b8/0x520
> > >     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
> > >     [<00000000d613b754>] driver_probe_device+0x6c/0x208
> > >     [<00000000187a9170>] __driver_attach+0x168/0x328
> > >     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
> > >     [<00000000984a3176>] driver_attach+0x34/0x44
> > >     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
> > >     [<00000000747fce19>] driver_register+0xc0/0x1a0
> > >     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> > > unreferenced object 0xffffff8103bc01c0 (size 32):
> > 
> > I could not reproduce on my setup, even though I run a system with
> > all the existent SCMI protocols (and related drivers) enabled (and
> > so a lot of device creations) and a downstream test driver that causes
> > even more SCMI devices to be created/destroyed at load/unload.
> > 
> > Coming down the path from scmi_chan_setup(), it seems something around
> > transport devices creation, but it is not obvious to me where the leak
> > could hide....
> > 
> > ...any particular setup on your side ? ...using LKMs, loading/unloading,
> > any usage pattern that could help me reproduce ?
> 
> I looked into this a bit more, and actually it does happen consistently.
> It's just that kmemleak doesn't report it until 10 minutes after
> booting, so I did not notice it.
> 
> As for my setup, well, I boot the kernel over pxe and the rootfs is
> mounted over NFSv4. The memory leak happens even if I don't do anything
> at all - I just boot and wait. The device is a Radxa Rock5B.
> 
> Not sure what other information there is to give.
> 

My question as stated above was mainly to understand if the SCMI stack
was built-in or compiled as loadable modules (lsmod|grep -i scmi)...
...I am just to try to pin down a possible 'more-vulnerable' configuration..
..I could not see any report even triggering a kmemleak scan on v6.14-rc5
BUT I only tested with a fully built-in SCMI stack indeed as of now...so
the question.

> I tried again with v6.14-rc5, and I still got the leak:

Ok...thanks I will investigate with different configs.

Thanks,
Cristian


From linux at armlinux.org.uk  Thu Mar  6 04:51:16 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 6 Mar 2025 12:51:16 +0000
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <20250306111220.28798e6b@fedora.home>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
 <20250303090321.805785-10-maxime.chevallier@bootlin.com>
 <350bb4f6-f4b5-44c3-a821-ac53c8641705@redhat.com>
 <20250306111220.28798e6b@fedora.home>
Message-ID: <Z8maRNYsn1LzjryX@shell.armlinux.org.uk>

On Thu, Mar 06, 2025 at 11:12:20AM +0100, Maxime Chevallier wrote:
> On Thu, 6 Mar 2025 09:56:32 +0100
> Paolo Abeni <pabeni at redhat.com> wrote:
> 
> > On 3/3/25 10:03 AM, Maxime Chevallier wrote:
> > > @@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
> > >  	linkmode_copy(pl->link_config.advertising, pl->supported);
> > >  	phylink_validate(pl, pl->supported, &pl->link_config);
> > >  
> > > -	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
> > > -			       pl->supported, true);
> > > +	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
> > > +			    pl->supported, true);
> > > +	if (c)
> > > +		linkmode_and(match, pl->supported, c->linkmodes);  
> > 
> > How about using only the first bit from `c->linkmodes`, to avoid
> > behavior changes?
> 
> If what we want is to keep the exact same behaviour, then we need to
> go one step further and make sure we keep the same one as before, and
> it's not guaranteed that the first bit in c->linkmodes is this one.
> 
> We could however have a default supported mask for fixed-link in phylink
> that contains all the linkmodes we allow for fixed links, then filter
> with the lookup, something like :
> 
> 
> -       linkmode_fill(pl->supported);
> +       /* (in a dedicated helper) Linkmodes reported for fixed links below
> +        * 10G */
> +       linkmode_zero(pl->supported);
> +
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, pl->supported);
> +       linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, pl->supported);

Good idea, but do we have some way to automatically generate the baseT
link modes?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From yong.liang.choong at linux.intel.com  Thu Mar  6 04:56:05 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Thu, 6 Mar 2025 20:56:05 +0800
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>
 <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
 <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>
Message-ID: <d7c0094e-7fd3-4113-8d00-91b7a83ffd1f@linux.intel.com>



On 6/3/2025 5:05 pm, Andy Shevchenko wrote:
> On Thu, Mar 6, 2025 at 10:39?AM Choong Yong Liang
> <yong.liang.choong at linux.intel.com> wrote:
>> On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
>>> Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:
> ...
> 
>>>> config DWMAC_INTEL
>>>>       default X86
>>>>       depends on X86 && STMMAC_ETH && PCI
>>>>       depends on COMMON_CLK
>>>> +    depends on ACPI
>>> Stray and unexplained change. Please, fix it. We don't need the dependencies
>>> which are not realised in the compile time.
>> The dependency on ACPI is necessary because the intel_pmc_ipc.h header
>> relies on ACPI functionality to interact with the Intel PMC.
> So, that header has to be fixed as ACPI here is really unneeded
> dependency for the cases when somebody (for whatever reasons) want to
> build a kernel without ACPI support but with the driver enabled for
> let's say PCI device.
> 
> 
> -- With Best Regards, Andy Shevchenko

Hi Andy,

Thank you for your feedback, Andy.
I appreciate your insights regarding the ACPI dependency.
The intel_pmc_ipc.h header is under the ownership of David E Box, who 
focuses on the platform code, while my focus is on the netdev.

Hi David,

if you could kindly look into making the ACPI dependency optional in the 
intel_pmc_ipc.h header, it would be greatly appreciated.
I am more than willing to provide any support necessary to ensure a smooth 
resolution.

This patch series has already been accepted, but we recognize the 
importance of addressing this issue in the next patch series for upstream.
Our goal is to ensure that the driver can be compiled and function 
correctly in both ACPI and non-ACPI environments.

Thank you both for your understanding and collaboration.


From ryan.roberts at arm.com  Thu Mar  6 03:54:23 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 6 Mar 2025 11:54:23 +0000
Subject: [PATCH v3 04/11] arm64/mm: Refactor __set_ptes() and
 __ptep_get_and_clear()
In-Reply-To: <202503061237.QurSXHSC-lkp@intel.com>
References: <20250304150444.3788920-5-ryan.roberts@arm.com>
 <202503061237.QurSXHSC-lkp@intel.com>
Message-ID: <169f2d13-8374-48b2-8af1-db412f283e5b@arm.com>

On 06/03/2025 05:08, kernel test robot wrote:
> Hi Ryan,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v6.14-rc5 next-20250305]
> [cannot apply to arm64/for-next/core akpm-mm/mm-everything arm-perf/for-next/perf]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Roberts/arm64-hugetlb-Cleanup-huge_pte-size-discovery-mechanisms/20250304-230647
> base:   linus/master
> patch link:    https://lore.kernel.org/r/20250304150444.3788920-5-ryan.roberts%40arm.com
> patch subject: [PATCH v3 04/11] arm64/mm: Refactor __set_ptes() and __ptep_get_and_clear()
> config: arm64-randconfig-001-20250305 (https://download.01.org/0day-ci/archive/20250306/202503061237.QurSXHSC-lkp at intel.com/config)
> compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250306/202503061237.QurSXHSC-lkp at intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202503061237.QurSXHSC-lkp at intel.com/
> 
> All errors (new ones prefixed by >>):
> 
>    In file included from arch/arm64/kernel/asm-offsets.c:12:
>    In file included from include/linux/ftrace.h:10:
>    In file included from include/linux/trace_recursion.h:5:
>    In file included from include/linux/interrupt.h:11:
>    In file included from include/linux/hardirq.h:11:
>    In file included from arch/arm64/include/asm/hardirq.h:17:
>    In file included from include/asm-generic/hardirq.h:17:
>    In file included from include/linux/irq.h:20:
>    In file included from include/linux/io.h:14:
>    In file included from arch/arm64/include/asm/io.h:12:
>    In file included from include/linux/pgtable.h:6:
>>> arch/arm64/include/asm/pgtable.h:639:7: error: duplicate case value '536870912'
>            case PUD_SIZE:
>                 ^
>    include/asm-generic/pgtable-nopud.h:20:20: note: expanded from macro 'PUD_SIZE'
>    #define PUD_SIZE        (1UL << PUD_SHIFT)
>                            ^
>    arch/arm64/include/asm/pgtable.h:636:7: note: previous case defined here
>            case PMD_SIZE:
>                 ^
>    include/asm-generic/pgtable-nopmd.h:22:20: note: expanded from macro 'PMD_SIZE'
>    #define PMD_SIZE        (1UL << PMD_SHIFT)
>                            ^
>    In file included from arch/arm64/kernel/asm-offsets.c:12:
>    In file included from include/linux/ftrace.h:10:
>    In file included from include/linux/trace_recursion.h:5:
>    In file included from include/linux/interrupt.h:11:
>    In file included from include/linux/hardirq.h:11:
>    In file included from arch/arm64/include/asm/hardirq.h:17:
>    In file included from include/asm-generic/hardirq.h:17:
>    In file included from include/linux/irq.h:20:
>    In file included from include/linux/io.h:14:
>    In file included from arch/arm64/include/asm/io.h:12:
>    In file included from include/linux/pgtable.h:6:
>    arch/arm64/include/asm/pgtable.h:1303:7: error: duplicate case value '536870912'
>            case PUD_SIZE:
>                 ^
>    include/asm-generic/pgtable-nopud.h:20:20: note: expanded from macro 'PUD_SIZE'
>    #define PUD_SIZE        (1UL << PUD_SHIFT)
>                            ^
>    arch/arm64/include/asm/pgtable.h:1300:7: note: previous case defined here
>            case PMD_SIZE:
>                 ^
>    include/asm-generic/pgtable-nopmd.h:22:20: note: expanded from macro 'PMD_SIZE'
>    #define PMD_SIZE        (1UL << PMD_SHIFT)
>                            ^
>    2 errors generated.
>    make[3]: *** [scripts/Makefile.build:102: arch/arm64/kernel/asm-offsets.s] Error 1 shuffle=4064171735
>    make[3]: Target 'prepare' not remade because of errors.
>    make[2]: *** [Makefile:1264: prepare0] Error 2 shuffle=4064171735
>    make[2]: Target 'prepare' not remade because of errors.
>    make[1]: *** [Makefile:251: __sub-make] Error 2 shuffle=4064171735
>    make[1]: Target 'prepare' not remade because of errors.
>    make: *** [Makefile:251: __sub-make] Error 2 shuffle=4064171735
>    make: Target 'prepare' not remade because of errors.
> 
> 
> vim +/536870912 +639 arch/arm64/include/asm/pgtable.h
> 
>    626	
>    627	static inline void set_ptes_anysz(struct mm_struct *mm, pte_t *ptep, pte_t pte,
>    628					  unsigned int nr, unsigned long pgsize)
>    629	{
>    630		unsigned long stride = pgsize >> PAGE_SHIFT;
>    631	
>    632		switch (pgsize) {
>    633		case PAGE_SIZE:
>    634			page_table_check_ptes_set(mm, ptep, pte, nr);
>    635			break;
>    636		case PMD_SIZE:
>    637			page_table_check_pmds_set(mm, (pmd_t *)ptep, pte_pmd(pte), nr);
>    638			break;
>  > 639		case PUD_SIZE:
>    640			page_table_check_puds_set(mm, (pud_t *)ptep, pte_pud(pte), nr);
>    641			break;

Looks like this needs to be wrapped in `#ifndef __PAGETABLE_PMD_FOLDED`. This
failing config folds the PMD so PMD_SIZE and PUD_SIZE are the same.

Given there are now 2 kernel robot reports, I'll respin the series next week,
giving time for any interim review comments.

Thanks,
Ryan


>    642		default:
>    643			VM_WARN_ON(1);
>    644		}
>    645	
>    646		__sync_cache_and_tags(pte, nr * stride);
>    647	
>    648		for (;;) {
>    649			__check_safe_pte_update(mm, ptep, pte);
>    650			__set_pte(ptep, pte);
>    651			if (--nr == 0)
>    652				break;
>    653			ptep++;
>    654			pte = pte_advance_pfn(pte, stride);
>    655		}
>    656	}
>    657	
> 



From andre.draszik at linaro.org  Thu Mar  6 03:57:35 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 11:57:35 +0000
Subject: [PATCH v2 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-2-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
	 <20250301-pinctrl-fltcon-suspend-v2-2-a7eef9bb443b@linaro.org>
Message-ID: <f7c0101ff26ac0d4ef70a374ae31ee5d23b3c8fc.camel@linaro.org>

On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> gs101 needs it's own suspend/resume callbacks to use the newly
> added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> registers. It also differs to previous SoCs in that fltcon1
> register doesn't always exist for each bank.
> 
> exynosautov920 also has dedicated logic for using eint_con_offset
> and eint_mask_offset for saving & restoring it's registers.
> 
> Refactor the existing platform specific suspend/resume callback
> so that each SoC variant has their own callback containing the
> SoC specific logic.
> 
> Additionally we now call drvdata->suspend() & drvdata->resume()
> from within the loop that iterates the banks in
> samsung_pinctrl_suspend() and samsung_pinctrl_resume().
> 
> This simplifies the logic, and allows us to remove the
> clk_enable() and clk_disable() from the callbacks.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> Changes since v1:
> * Split code refactor & gs101 parts into separate patches (Andre)
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |? 28 ++--
> ?drivers/pinctrl/samsung/pinctrl-exynos.c?????? | 201 ++++++++++---------------
> ?drivers/pinctrl/samsung/pinctrl-exynos.h?????? |?? 6 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.c????? |? 11 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.h????? |?? 8 +-
> ?5 files changed, 111 insertions(+), 143 deletions(-)
> 
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> index e28fe8177646..57c98d2451b5 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> @@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> ?		.pin_banks	= exynosautov920_pin_banks0,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
> ?		.eint_wkup_init	= exynos_eint_wkup_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?		.retention_data	= &exynosautov920_retention_data,
> ?	}, {
> ?		/* pin-controller instance 1 AUD data */
> @@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> ?		.pin_banks	= exynosautov920_pin_banks2,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 3 HSI1 data */
> ?		.pin_banks	= exynosautov920_pin_banks3,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 4 HSI2 data */
> ?		.pin_banks	= exynosautov920_pin_banks4,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 5 HSI2UFS data */
> ?		.pin_banks	= exynosautov920_pin_banks5,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 6 PERIC0 data */
> ?		.pin_banks	= exynosautov920_pin_banks6,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 7 PERIC1 data */
> ?		.pin_banks	= exynosautov920_pin_banks7,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	},
> ?};
> ?
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
> index ac6dc22b37c9..d65a9fba0781 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
> @@ -761,153 +761,118 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
> ?	return 0;
> ?}
> ?
> -static void exynos_pinctrl_suspend_bank(
> -				struct samsung_pinctrl_drv_data *drvdata,
> -				struct samsung_pin_bank *bank)
> +static void exynos_set_wakeup(struct samsung_pin_bank *bank)
> ?{
> -	struct exynos_eint_gpio_save *save = bank->soc_priv;
> -	const void __iomem *regs = bank->eint_base;
> +	struct exynos_irq_chip *irq_chip = NULL;

This is a useless init and the value is overwritten right away.

> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for saving state\n");
> -		return;
> +	if (bank->eint_type == EINT_TYPE_WKUP) {
> +		if (bank->irq_chip) {
> +			irq_chip = bank->irq_chip;
> +			irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
> +		}
> ?	}
> -
> -	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> -						+ bank->eint_offset);
> -	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset);
> -	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset + 4);
> -	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> -						+ bank->eint_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> -
> -	pr_debug("%s: save???? con %#010x\n", bank->name, save->eint_con);
> -	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
> -	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
> -	pr_debug("%s: save??? mask %#010x\n", bank->name, save->eint_mask);
> ?}
> ?
> -static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
> -					??? struct samsung_pin_bank *bank)
> +void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	const void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for saving state\n");
> -		return;
> +	exynos_set_wakeup(bank);
> +
> +	if (bank->eint_type == EINT_TYPE_GPIO) {

Can you swap the order, and make the call to exynos_set_wakeup()
an else, to avoid some needless tests and make it clearer that
set_wakeup() is conditional as well, i.e.:

	if (bank->eint_type == EINT_TYPE_GPIO) {
	  ...
	} else {
	  exynos_set_wakeup(bank);
	}

What makes it hard to read is that as-is, it looks like the
set_wakeup() is unconditional, while it's also based on
bank->eint_type (which is also more obvious before your patch).

Or maybe even have exynos_set_wakeup() return a bool, as in
the follow-up gs101 patch, there are three tests of this type.

Other than that, I think I looks good.

Cheers,
Andre'

> +		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +				?????? + bank->eint_offset);
> +		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +					?? + 2 * bank->eint_offset);
> +		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +					?? + 2 * bank->eint_offset + 4);
> +		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> +					+ bank->eint_offset);
> +
> +		pr_debug("%s: save???? con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save fltcon0 %#010x\n",
> +			 bank->name, save->eint_fltcon0);
> +		pr_debug("%s: save fltcon1 %#010x\n",
> +			 bank->name, save->eint_fltcon1);
> +		pr_debug("%s: save??? mask %#010x\n",
> +			 bank->name, save->eint_mask);
> ?	}
> -
> -	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
> -	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> -
> -	pr_debug("%s: save???? con %#010x\n", bank->name, save->eint_con);
> -	pr_debug("%s: save??? mask %#010x\n", bank->name, save->eint_mask);
> ?}
> ?
> -void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
> +void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?{
> -	struct samsung_pin_bank *bank = drvdata->pin_banks;
> -	struct exynos_irq_chip *irq_chip = NULL;
> -	int i;
> +	struct exynos_eint_gpio_save *save = bank->soc_priv;
> +	const void __iomem *regs = bank->eint_base;
> ?
> -	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
> -		if (bank->eint_type == EINT_TYPE_GPIO) {
> -			if (bank->eint_con_offset)
> -				exynosauto_pinctrl_suspend_bank(drvdata, bank);
> -			else
> -				exynos_pinctrl_suspend_bank(drvdata, bank);
> -		}
> -		else if (bank->eint_type == EINT_TYPE_WKUP) {
> -			if (!irq_chip) {
> -				irq_chip = bank->irq_chip;
> -				irq_chip->set_eint_wakeup_mask(drvdata,
> -							?????? irq_chip);
> -			}
> -		}
> +	exynos_set_wakeup(bank);
> +
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		save->eint_con = readl(regs + bank->pctl_offset +
> +				?????? bank->eint_con_offset);
> +		save->eint_mask = readl(regs + bank->pctl_offset +
> +					bank->eint_mask_offset);
> +		pr_debug("%s: save???? con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save??? mask %#010x\n",
> +			 bank->name, save->eint_mask);
> ?	}
> ?}
> ?
> -static void exynos_pinctrl_resume_bank(
> -				struct samsung_pinctrl_drv_data *drvdata,
> -				struct samsung_pin_bank *bank)
> +void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for restoring state\n");
> -		return;
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +			?????? + bank->eint_offset), save->eint_con);
> +		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +			?????? + 2 * bank->eint_offset), save->eint_fltcon0);
> +		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +			?????? + 2 * bank->eint_offset + 4),
> +			?????? save->eint_fltcon1);
> +		pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->irq_chip->eint_mask
> +			?????? + bank->eint_offset), save->eint_mask);
> +
> +		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> +		?????? + bank->eint_offset);
> +		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +		?????? + 2 * bank->eint_offset);
> +		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +		?????? + 2 * bank->eint_offset + 4);
> +		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> +		?????? + bank->eint_offset);
> ?	}
> -
> -	pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_ECON_OFFSET
> -			+ bank->eint_offset), save->eint_con);
> -	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -			+ 2 * bank->eint_offset), save->eint_fltcon0);
> -	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
> -	pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> -			readl(regs + bank->irq_chip->eint_mask
> -			+ bank->eint_offset), save->eint_mask);
> -
> -	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> -						+ bank->eint_offset);
> -	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset);
> -	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset + 4);
> -	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> -						+ bank->eint_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> ?}
> ?
> -static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
> -					?? struct samsung_pin_bank *bank)
> +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for restoring state\n");
> -		return;
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		/* exynosautov920 has eint_con_offset for all but one bank */
> +		if (!bank->eint_con_offset)
> +			exynos_pinctrl_resume(bank);
> +
> +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
> +			?????? save->eint_con);
> +		pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->pctl_offset +
> +			?????? bank->eint_mask_offset), save->eint_mask);
> +
> +		writel(save->eint_con,
> +		?????? regs + bank->pctl_offset + bank->eint_con_offset);
> +		writel(save->eint_mask,
> +		?????? regs + bank->pctl_offset + bank->eint_mask_offset);
> ?	}
> -
> -	pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> -		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
> -	pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> -		 readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
> -
> -	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
> -	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> -}
> -
> -void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
> -{
> -	struct samsung_pin_bank *bank = drvdata->pin_banks;
> -	int i;
> -
> -	for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
> -		if (bank->eint_type == EINT_TYPE_GPIO) {
> -			if (bank->eint_con_offset)
> -				exynosauto_pinctrl_resume_bank(drvdata, bank);
> -			else
> -				exynos_pinctrl_resume_bank(drvdata, bank);
> -		}
> ?}
> ?
> ?static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
> index 33df21d5c9d6..35c2bc4ea488 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.h
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
> @@ -221,8 +221,10 @@ struct exynos_muxed_weint_data {
> ?
> ?int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
> ?int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
> -void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
> -void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
> +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
> +void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
> +void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
> +void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
> ?struct samsung_retention_ctrl *
> ?exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
> ?		????? const struct samsung_retention_data *data);
> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> index 963060920301..375634d8cc79 100644
> --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> @@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> ?		const u8 *widths = bank->type->fld_width;
> ?		enum pincfg_type type;
> ?
> +		if (drvdata->suspend)
> +			drvdata->suspend(bank);
> +
> ?		/* Registers without a powerdown config aren't lost */
> ?		if (!widths[PINCFG_TYPE_CON_PDN])
> ?			continue;
> @@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> ?
> ?	clk_disable(drvdata->pclk);
> ?
> -	if (drvdata->suspend)
> -		drvdata->suspend(drvdata);
> ?	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
> ?		drvdata->retention_ctrl->enable(drvdata);
> ?
> @@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> ?		return ret;
> ?	}
> ?
> -	if (drvdata->resume)
> -		drvdata->resume(drvdata);
> -
> ?	for (i = 0; i < drvdata->nr_banks; i++) {
> ?		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
> ?		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
> @@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> ?		const u8 *widths = bank->type->fld_width;
> ?		enum pincfg_type type;
> ?
> +		if (drvdata->resume)
> +			drvdata->resume(bank);
> +
> ?		/* Registers without a powerdown config aren't lost */
> ?		if (!widths[PINCFG_TYPE_CON_PDN])
> ?			continue;
> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
> index 371e4f02bbfb..e939e5bb0347 100644
> --- a/drivers/pinctrl/samsung/pinctrl-samsung.h
> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
> @@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
> ?	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
> ?	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
> ?	void		(*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
> -	void		(*suspend)(struct samsung_pinctrl_drv_data *);
> -	void		(*resume)(struct samsung_pinctrl_drv_data *);
> +	void		(*suspend)(struct samsung_pin_bank *bank);
> +	void		(*resume)(struct samsung_pin_bank *bank);
> ?};
> ?
> ?/**
> @@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
> ?
> ?	struct samsung_retention_ctrl	*retention_ctrl;
> ?
> -	void (*suspend)(struct samsung_pinctrl_drv_data *);
> -	void (*resume)(struct samsung_pinctrl_drv_data *);
> +	void (*suspend)(struct samsung_pin_bank *bank);
> +	void (*resume)(struct samsung_pin_bank *bank);
> ?};
> ?
> ?/**
> 



From ryan.roberts at arm.com  Thu Mar  6 03:57:36 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 6 Mar 2025 11:57:36 +0000
Subject: [PATCH] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <e0c2841b-3776-4d78-9514-b03ada39c739@arm.com>
References: <20250303041834.2796751-1-anshuman.khandual@arm.com>
 <0fe6f3b2-1011-4418-bc19-612a3b98c78d@arm.com>
 <e0c2841b-3776-4d78-9514-b03ada39c739@arm.com>
Message-ID: <5f1b36e2-6455-44d9-97b0-253aefd5024f@arm.com>

On 06/03/2025 03:37, Anshuman Khandual wrote:
> 
> 
> On 3/4/25 21:51, Ryan Roberts wrote:
>> On 03/03/2025 04:18, Anshuman Khandual wrote:
>>> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
>>> section mapping at all page table levels except the last level. This works
>>> fine as the section mapping masks are exactly the same (0x1UL) for all page
>>> table levels.
>>>
>>> This will change in the future with D128 page tables that have unique skip
>>> level values (SKL) required for creating section mapping at different page
>>> table levels. Hence use page table level specific section mapping macros
>>> instead of the common PMD_TYPE_SECT.
>>>
>>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>>> Cc: Will Deacon <will at kernel.org>
>>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>>> Cc: Ard Biesheuvel <ardb at kernel.org>
>>> Cc: linux-kernel at vger.kernel.org
>>> Cc: linux-arm-kernel at lists.infradead.org
>>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>>> ---
>>> This patch applies on 6.14-rc5
>>>
>>> PGD_TYPE_SECT for level -1 section map handling has been added for 4K
>>> base pages with 52 bit VA configuration that has 5 page table levels.
>>> In such cases (CONFIG_PGTABLE_LEVELS = 5) early_map_kernel() can call
>>> map_range() eventually with -1 (i.e 4 - CONFIG_PGTABLE_LEVELS) as the
>>> root_level.
>>
>> Table Table D8-16 on page D8-6459 of ARM DDI 0487 L.a says that block mappings
>> at level -1 are not permitted for 4K pages; only levels 0-3 support leaf
>> mappings. Similarly for 16K, table D8-26 says only levels 1-3 permit leaf
>> mappings. And for 64K, table D8-35 says only levels 1-3 permit leaf mappings.
> 
> Then seems like the current code is actually wrong because PMD_TYPE_SECT
> is being set at all levels (except level 3) regardless of the configured
> page size ?

Yes, I think so. In that case, you should mark it with Fixes: and Cc: stable.

But I feel like there might be some subtlely here that means that the problem
can't happen in practice. Ard might know?

> 
>>
>> So I don't think PGD_TYPE_SECT is the right solution. Perhaps we need to
>> explicitly force the unsupported levels to be table entries even if the
>> alignment is correct?
> 
> Just wondering - something like the following will work instead ? Tested
> on both 4K and 64K page sizes.

LGTM!

> 
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -26,6 +26,21 @@
>   * @va_offset:         Offset between a physical page and its current mapping
>   *                     in the VA space
>   */
> +static bool sect_supported(int level)
> +{
> +       switch(level) {
> +       case -1:
> +               return false;
> +       case 0:
> +               if(IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
> +                  IS_ENABLED(CONFIG_ARM64_64K_PAGES))
> +                       return false;
> +               fallthrough;
> +       default:
> +               return true;
> +       }
> +}
> +
>  void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>                       int level, pte_t *tbl, bool may_use_cont, u64 va_offset)
>  {
> @@ -44,13 +59,30 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>          * Set the right block/page bits for this level unless we are
>          * clearing the mapping
>          */
> -       if (protval)
> -               protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> +       if (protval && sect_supported(level)) {
> +               switch (level) {
> +               case 3:
> +                       protval |= PTE_TYPE_PAGE;
> +                       break;
> +               case 2:
> +                       protval |= PMD_TYPE_SECT;
> +                       break;
> +               case 1:
> +                       protval |= PUD_TYPE_SECT;
> +                       break;
> +               case 0:
> +                       protval |= P4D_TYPE_SECT;
> +                       break;
> +               default:
> +                       break;
> +               }
> +       }
>  
>         while (start < end) {
>                 u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -               if (level < 3 && (start | next | pa) & lmask) {
> +               if ((level < 3 && (start | next | pa) & lmask) ||
> +                    !sect_supported(level)){
>                         /*
>                          * This chunk needs a finer grained mapping. Create a
>                          * table mapping if necessary and recurse.
> 
>>
>> Thanks,
>> Ryan
>>
>>>
>>>  arch/arm64/include/asm/pgtable-hwdef.h |  1 +
>>>  arch/arm64/kernel/pi/map_range.c       | 23 +++++++++++++++++++++--
>>>  2 files changed, 22 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
>>> index a9136cc551cc..fd0a82e8878c 100644
>>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>>> @@ -99,6 +99,7 @@
>>>  #define PGD_TYPE_TABLE		(_AT(pgdval_t, 3) << 0)
>>>  #define PGD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
>>>  #define PGD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
>>> +#define PGD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
>>>  #define PGD_TABLE_AF		(_AT(pgdval_t, 1) << 10)	/* Ignored if no FEAT_HAFT */
>>>  #define PGD_TABLE_PXN		(_AT(pgdval_t, 1) << 59)
>>>  #define PGD_TABLE_UXN		(_AT(pgdval_t, 1) << 60)
>>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>>> index 2b69e3beeef8..9ea869f5745f 100644
>>> --- a/arch/arm64/kernel/pi/map_range.c
>>> +++ b/arch/arm64/kernel/pi/map_range.c
>>> @@ -44,8 +44,27 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>>  	 * Set the right block/page bits for this level unless we are
>>>  	 * clearing the mapping
>>>  	 */
>>> -	if (protval)
>>> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
>>> +	if (protval) {
>>> +		switch (level) {
>>> +		case 3:
>>> +			protval |= PTE_TYPE_PAGE;
>>> +			break;
>>> +		case 2:
>>> +			protval |= PMD_TYPE_SECT;
>>> +			break;
>>> +		case 1:
>>> +			protval |= PUD_TYPE_SECT;
>>> +			break;
>>> +		case 0:
>>> +			protval |= P4D_TYPE_SECT;
>>> +			break;
>>> +		case -1:
>>> +			protval |= PGD_TYPE_SECT;
>>> +			break;
>>> +		default:
>>> +			break;
>>> +		}
>>> +	}
>>>  
>>>  	while (start < end) {
>>>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>>



From yeoreum.yun at arm.com  Thu Mar  6 04:11:01 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:01 +0000
Subject: No subject
Message-ID: <20250306121110.1647948-1-yeoreum.yun@arm.com>

Subject: [PATCH v6 0/9] coresight: change some driver' spinlock type to raw_spinlock_t

In some coresight drivers, drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this,change type drvdata->spinlock in some coresight drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

from v5:
   - Fix build failure for coresight-tmc


Yeoreum Yun (9):
  coresight: change coresight_device lock type to raw_spinlock_t
  coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
  coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
  coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
  coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
  coresight-funnel: change funnel_drvdata spinlock's type to
    raw_spinlock_t
  coresight-replicator: change replicator_drvdata spinlock's type to
    raw_spinlock_t
  coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
  coresight/ultrasoc: change smb_drv_data spinlock's type to
    raw_spinlock_t

 .../hwtracing/coresight/coresight-config.c    |   8 +-
 .../hwtracing/coresight/coresight-config.h    |   2 +-
 drivers/hwtracing/coresight/coresight-core.c  |   2 +-
 .../hwtracing/coresight/coresight-cti-core.c  |  44 +--
 .../hwtracing/coresight/coresight-cti-sysfs.c |  76 +++---
 drivers/hwtracing/coresight/coresight-cti.h   |   2 +-
 drivers/hwtracing/coresight/coresight-etb10.c |  26 +-
 .../coresight/coresight-etm4x-core.c          |  18 +-
 .../coresight/coresight-etm4x-sysfs.c         | 250 +++++++++---------
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
 .../hwtracing/coresight/coresight-funnel.c    |  12 +-
 .../coresight/coresight-replicator.c          |  12 +-
 .../hwtracing/coresight/coresight-syscfg.c    |  26 +-
 .../hwtracing/coresight/coresight-tmc-core.c  |  14 +-
 .../hwtracing/coresight/coresight-tmc-etf.c   |  48 ++--
 .../hwtracing/coresight/coresight-tmc-etr.c   |  44 +--
 drivers/hwtracing/coresight/coresight-tmc.h   |   2 +-
 .../hwtracing/coresight/coresight-trace-id.c  |  22 +-
 drivers/hwtracing/coresight/ultrasoc-smb.c    |  12 +-
 drivers/hwtracing/coresight/ultrasoc-smb.h    |   2 +-
 include/linux/coresight.h                     |   4 +-
 21 files changed, 314 insertions(+), 314 deletions(-)

--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:02 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:02 +0000
Subject: [PATCH v6 1/9] coresight: change coresight_device lock type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-2-yeoreum.yun@arm.com>

coresight_device->cscfg_csdev_lock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since coresight->cscfg_csdev_lock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type of coresight_device->cscfg_csdev_lock
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-syscfg.c    | 26 +++++++++----------
 include/linux/coresight.h                     |  2 +-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 11138a9762b0..a70c1454b410 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -89,9 +89,9 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
 	}
 	/* if matched features, add config to device.*/
 	if (config_csdev) {
-		spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+		raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 		list_add(&config_csdev->node, &csdev->config_csdev_list);
-		spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+		raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 	}
 
 	return 0;
@@ -194,9 +194,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
 
 	/* add to internal csdev feature list & initialise using reset call */
 	cscfg_reset_feat(feat_csdev);
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_add(&feat_csdev->node, &csdev->feature_csdev_list);
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	return 0;
 }
@@ -765,7 +765,7 @@ static int cscfg_list_add_csdev(struct coresight_device *csdev,
 
 	INIT_LIST_HEAD(&csdev->feature_csdev_list);
 	INIT_LIST_HEAD(&csdev->config_csdev_list);
-	spin_lock_init(&csdev->cscfg_csdev_lock);
+	raw_spin_lock_init(&csdev->cscfg_csdev_lock);
 
 	return 0;
 }
@@ -855,7 +855,7 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 	struct cscfg_feature_csdev *feat_csdev;
 	unsigned long flags;
 
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	if (list_empty(&csdev->feature_csdev_list))
 		goto unlock_exit;
 
@@ -863,7 +863,7 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 		cscfg_reset_feat(feat_csdev);
 
 unlock_exit:
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
 
@@ -1059,7 +1059,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 	 * Look for matching configuration - set the active configuration
 	 * context if found.
 	 */
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
 		config_desc = config_csdev_item->config_desc;
 		if ((atomic_read(&config_desc->active_cnt)) &&
@@ -1069,7 +1069,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	/*
 	 * If found, attempt to enable
@@ -1090,12 +1090,12 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 			 *
 			 * Set enabled if OK, err if not.
 			 */
-			spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+			raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 			if (csdev->active_cscfg_ctxt)
 				config_csdev_active->enabled = true;
 			else
 				err = -EBUSY;
-			spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+			raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 		}
 	}
 	return err;
@@ -1124,7 +1124,7 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
 	 * If it was not enabled, we have no work to do, otherwise mark as disabled.
 	 * Clear the active config pointer.
 	 */
-	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
 	if (config_csdev) {
 		if (!config_csdev->enabled)
@@ -1133,7 +1133,7 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
 			config_csdev->enabled = false;
 	}
 	csdev->active_cscfg_ctxt = NULL;
-	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 
 	/* true if there was an enabled active config */
 	if (config_csdev)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 89b781e70fe7..4541bfc1cc6b 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -302,7 +302,7 @@ struct coresight_device {
 	/* system configuration and feature lists */
 	struct list_head feature_csdev_list;
 	struct list_head config_csdev_list;
-	spinlock_t cscfg_csdev_lock;
+	raw_spinlock_t cscfg_csdev_lock;
 	void *active_cscfg_ctxt;
 };
 
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:03 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:03 +0000
Subject: [PATCH v6 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-3-yeoreum.yun@arm.com>

In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during
__schedule() by perf_event_task_sched_out()/in().

Since etmv4_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type etmv4_drvdata->spinlock
in coresight-etm4x drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
---
 .../hwtracing/coresight/coresight-config.c    |   8 +-
 .../hwtracing/coresight/coresight-config.h    |   2 +-
 .../coresight/coresight-etm4x-core.c          |  18 +-
 .../coresight/coresight-etm4x-sysfs.c         | 250 +++++++++---------
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
 5 files changed, 140 insertions(+), 140 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
index 4723bf7402a2..4f72ae71b696 100644
--- a/drivers/hwtracing/coresight/coresight-config.c
+++ b/drivers/hwtracing/coresight/coresight-config.c
@@ -76,10 +76,10 @@ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
 	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_set_reg(&feat_csdev->regs_csdev[i]);
-	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
 	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
 		feat_csdev->feat_desc->name, "set on enable");
 	return 0;
@@ -91,10 +91,10 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
 	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_save_reg(&feat_csdev->regs_csdev[i]);
-	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
 	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
 		feat_csdev->feat_desc->name, "save on disable");
 }
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 6ba013975741..b9ebc9fcfb7f 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -206,7 +206,7 @@ struct cscfg_feature_csdev {
 	const struct cscfg_feature_desc *feat_desc;
 	struct coresight_device *csdev;
 	struct list_head node;
-	spinlock_t *drv_spinlock;
+	raw_spinlock_t *drv_spinlock;
 	int nr_params;
 	struct cscfg_parameter_csdev *params_csdev;
 	int nr_regs;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index bb1e80df2914..e5972f16abff 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -830,7 +830,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
 			return ret;
 	}
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	drvdata->trcid = path->trace_id;
 
@@ -849,7 +849,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
 	if (ret)
 		etm4_release_trace_id(drvdata);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	if (!ret)
 		dev_dbg(&csdev->dev, "ETM tracing enabled\n");
@@ -1011,7 +1011,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	 * DYING hotplug callback is serviced by the ETM driver.
 	 */
 	cpus_read_lock();
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/*
 	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
@@ -1019,7 +1019,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	 */
 	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	cpus_read_unlock();
 
 	/*
@@ -1698,13 +1698,13 @@ static int etm4_starting_cpu(unsigned int cpu)
 	if (!etmdrvdata[cpu])
 		return 0;
 
-	spin_lock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
 	if (!etmdrvdata[cpu]->os_unlock)
 		etm4_os_unlock(etmdrvdata[cpu]);
 
 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
 		etm4_enable_hw(etmdrvdata[cpu]);
-	spin_unlock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
 	return 0;
 }
 
@@ -1713,10 +1713,10 @@ static int etm4_dying_cpu(unsigned int cpu)
 	if (!etmdrvdata[cpu])
 		return 0;
 
-	spin_lock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
 		etm4_disable_hw(etmdrvdata[cpu]);
-	spin_unlock(&etmdrvdata[cpu]->spinlock);
+	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
 	return 0;
 }
 
@@ -2160,7 +2160,7 @@ static int etm4_probe(struct device *dev)
 			return -ENOMEM;
 	}
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	drvdata->cpu = coresight_get_cpu(dev);
 	if (drvdata->cpu < 0)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index e5216c0f60da..fdd0956fecb3 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -175,7 +175,7 @@ static ssize_t reset_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (val)
 		config->mode = 0x0;
 
@@ -267,7 +267,7 @@ static ssize_t reset_store(struct device *dev,
 	config->vmid_mask0 = 0x0;
 	config->vmid_mask1 = 0x0;
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	/* for sysfs - only release trace id when resetting */
 	etm4_release_trace_id(drvdata);
@@ -301,7 +301,7 @@ static ssize_t mode_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->mode = val & ETMv4_MODE_ALL;
 
 	if (drvdata->instrp0 == true) {
@@ -438,7 +438,7 @@ static ssize_t mode_store(struct device *dev,
 	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
 		etm4_config_trace_mode(config);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return size;
 }
@@ -467,14 +467,14 @@ static ssize_t pe_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (val > drvdata->nr_pe) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 
 	config->pe_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(pe);
@@ -502,7 +502,7 @@ static ssize_t event_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	switch (drvdata->nr_event) {
 	case 0x0:
 		/* EVENT0, bits[7:0] */
@@ -523,7 +523,7 @@ static ssize_t event_store(struct device *dev,
 	default:
 		break;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event);
@@ -551,7 +551,7 @@ static ssize_t event_instren_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* start by clearing all instruction event enable bits */
 	config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
 	switch (drvdata->nr_event) {
@@ -579,7 +579,7 @@ static ssize_t event_instren_store(struct device *dev,
 	default:
 		break;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event_instren);
@@ -740,11 +740,11 @@ static ssize_t event_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
 	config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
 	config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(event_vinst);
@@ -772,13 +772,13 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* clear all EXLEVEL_S bits  */
 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
 	/* enable instruction tracing for corresponding exception level */
 	val &= drvdata->s_ex_level;
 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(s_exlevel_vinst);
@@ -807,13 +807,13 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* clear EXLEVEL_NS bits  */
 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
 	/* enable instruction tracing for corresponding exception level */
 	val &= drvdata->ns_ex_level;
 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ns_exlevel_vinst);
@@ -847,9 +847,9 @@ static ssize_t addr_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->addr_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_idx);
@@ -863,7 +863,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
 	len = scnprintf(buf, PAGE_SIZE, "%s\n",
@@ -871,7 +871,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
 			(val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
 			(val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
 			"data_load_store")));
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return len;
 }
 
@@ -889,13 +889,13 @@ static ssize_t addr_instdatatype_store(struct device *dev,
 	if (sscanf(buf, "%s", str) != 1)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!strcmp(str, "instr"))
 		/* TYPE, bits[1:0] */
 		config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_instdatatype);
@@ -910,14 +910,14 @@ static ssize_t addr_single_show(struct device *dev,
 	struct etmv4_config *config = &drvdata->config;
 
 	idx = config->addr_idx;
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -933,17 +933,17 @@ static ssize_t addr_single_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_single);
@@ -957,23 +957,23 @@ static ssize_t addr_range_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val1 = (unsigned long)config->addr_val[idx];
 	val2 = (unsigned long)config->addr_val[idx + 1];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -996,10 +996,10 @@ static ssize_t addr_range_store(struct device *dev,
 	if (val1 > val2)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -1007,7 +1007,7 @@ static ssize_t addr_range_store(struct device *dev,
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -1024,7 +1024,7 @@ static ssize_t addr_range_store(struct device *dev,
 		exclude = config->mode & ETM_MODE_EXCLUDE;
 	etm4_set_mode_exclude(drvdata, exclude ? true : false);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_range);
@@ -1038,17 +1038,17 @@ static ssize_t addr_start_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1064,22 +1064,22 @@ static ssize_t addr_start_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_START;
 	config->vissctlr |= BIT(idx);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_start);
@@ -1093,17 +1093,17 @@ static ssize_t addr_stop_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = (unsigned long)config->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1119,22 +1119,22 @@ static ssize_t addr_stop_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EINVAL;
 	}
 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	       config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
+		raw_spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	config->addr_val[idx] = (u64)val;
 	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
 	config->vissctlr |= BIT(idx + 16);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_stop);
@@ -1148,14 +1148,14 @@ static ssize_t addr_ctxtype_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* CONTEXTTYPE, bits[3:2] */
 	val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
 	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
 			(val == ETM_CTX_CTXID ? "ctxid" :
 			(val == ETM_CTX_VMID ? "vmid" : "all")));
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return len;
 }
 
@@ -1173,7 +1173,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
 	if (sscanf(buf, "%s", str) != 1)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	if (!strcmp(str, "none"))
 		/* start by clearing context type bits */
@@ -1200,7 +1200,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
 		if (drvdata->numvmidc)
 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_ctxtype);
@@ -1214,11 +1214,11 @@ static ssize_t addr_context_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* context ID comparator bits[6:4] */
 	val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1239,12 +1239,12 @@ static ssize_t addr_context_store(struct device *dev,
 		     drvdata->numcidc : drvdata->numvmidc))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* clear context ID comparator bits[6:4] */
 	config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_context);
@@ -1258,10 +1258,10 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1280,12 +1280,12 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev,
 	if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
 	config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(addr_exlevel_s_ns);
@@ -1308,7 +1308,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
 	int size = 0;
 	bool exclude = false;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->addr_idx;
 	addr_v = config->addr_val[idx];
 	addr_ctrl = config->addr_acc[idx];
@@ -1323,7 +1323,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
 		}
 		exclude = config->viiectlr & BIT(idx / 2 + 16);
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	if (addr_type) {
 		size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx,
 				 addr_type_names[addr_type], addr_v);
@@ -1367,9 +1367,9 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev,
 	if (!drvdata->nr_pe_cmp)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vipcssctlr = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop);
@@ -1403,9 +1403,9 @@ static ssize_t seq_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->seq_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(seq_idx);
@@ -1449,10 +1449,10 @@ static ssize_t seq_event_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->seq_idx;
 	val = config->seq_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1468,11 +1468,11 @@ static ssize_t seq_event_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->seq_idx;
 	/* Seq control has two masks B[15:8] F[7:0] */
 	config->seq_ctrl[idx] = val & 0xFFFF;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(seq_event);
@@ -1536,9 +1536,9 @@ static ssize_t cntr_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->cntr_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_idx);
@@ -1552,10 +1552,10 @@ static ssize_t cntrldvr_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntrldvr[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1573,10 +1573,10 @@ static ssize_t cntrldvr_store(struct device *dev,
 	if (val > ETM_CNTR_MAX_VAL)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntrldvr[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntrldvr);
@@ -1590,10 +1590,10 @@ static ssize_t cntr_val_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntr_val[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1611,10 +1611,10 @@ static ssize_t cntr_val_store(struct device *dev,
 	if (val > ETM_CNTR_MAX_VAL)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntr_val[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_val);
@@ -1628,10 +1628,10 @@ static ssize_t cntr_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	val = config->cntr_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1647,10 +1647,10 @@ static ssize_t cntr_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->cntr_idx;
 	config->cntr_ctrl[idx] = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(cntr_ctrl);
@@ -1688,9 +1688,9 @@ static ssize_t res_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->res_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(res_idx);
@@ -1704,10 +1704,10 @@ static ssize_t res_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->res_idx;
 	val = config->res_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1723,7 +1723,7 @@ static ssize_t res_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->res_idx;
 	/* For odd idx pair inversal bit is RES0 */
 	if (idx % 2 != 0)
@@ -1733,7 +1733,7 @@ static ssize_t res_ctrl_store(struct device *dev,
 				       TRCRSCTLRn_INV |
 				       TRCRSCTLRn_GROUP_MASK |
 				       TRCRSCTLRn_SELECT_MASK);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(res_ctrl);
@@ -1762,9 +1762,9 @@ static ssize_t sshot_idx_store(struct device *dev,
 	if (val >= drvdata->nr_ss_cmp)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->ss_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_idx);
@@ -1777,9 +1777,9 @@ static ssize_t sshot_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_ctrl[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1795,12 +1795,12 @@ static ssize_t sshot_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ss_idx;
 	config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
 	/* must clear bit 31 in related status register on programming */
 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_ctrl);
@@ -1812,9 +1812,9 @@ static ssize_t sshot_status_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_status[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 static DEVICE_ATTR_RO(sshot_status);
@@ -1827,9 +1827,9 @@ static ssize_t sshot_pe_ctrl_show(struct device *dev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etmv4_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = config->ss_pe_cmp[config->ss_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1845,12 +1845,12 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ss_idx;
 	config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
 	/* must clear bit 31 in related status register on programming */
 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(sshot_pe_ctrl);
@@ -1884,9 +1884,9 @@ static ssize_t ctxid_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->ctxid_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_idx);
@@ -1907,10 +1907,10 @@ static ssize_t ctxid_pid_show(struct device *dev,
 	if (task_active_pid_ns(current) != &init_pid_ns)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ctxid_idx;
 	val = (unsigned long)config->ctxid_pid[idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1945,10 +1945,10 @@ static ssize_t ctxid_pid_store(struct device *dev,
 	if (kstrtoul(buf, 16, &pid))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	idx = config->ctxid_idx;
 	config->ctxid_pid[idx] = (u64)pid;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_pid);
@@ -1968,10 +1968,10 @@ static ssize_t ctxid_masks_show(struct device *dev,
 	if (task_active_pid_ns(current) != &init_pid_ns)
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val1 = config->ctxid_mask0;
 	val2 = config->ctxid_mask1;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -2004,7 +2004,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
 	if ((drvdata->numcidc > 4) && (nr_inputs != 2))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/*
 	 * each byte[0..3] controls mask value applied to ctxid
 	 * comparator[0..3]
@@ -2076,7 +2076,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
 			mask >>= 0x8;
 	}
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(ctxid_masks);
@@ -2110,9 +2110,9 @@ static ssize_t vmid_idx_store(struct device *dev,
 	 * Use spinlock to ensure index doesn't change while it gets
 	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vmid_idx = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_idx);
@@ -2132,9 +2132,9 @@ static ssize_t vmid_val_show(struct device *dev,
 	if (!task_is_in_init_pid_ns(current))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = (unsigned long)config->vmid_val[config->vmid_idx];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -2162,9 +2162,9 @@ static ssize_t vmid_val_store(struct device *dev,
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->vmid_val[config->vmid_idx] = (u64)val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_val);
@@ -2183,10 +2183,10 @@ static ssize_t vmid_masks_show(struct device *dev,
 	if (!task_is_in_init_pid_ns(current))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val1 = config->vmid_mask0;
 	val2 = config->vmid_mask1;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -2218,7 +2218,7 @@ static ssize_t vmid_masks_store(struct device *dev,
 	if ((drvdata->numvmidc > 4) && (nr_inputs != 2))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/*
 	 * each byte[0..3] controls mask value applied to vmid
@@ -2291,7 +2291,7 @@ static ssize_t vmid_masks_store(struct device *dev,
 		else
 			mask >>= 0x8;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(vmid_masks);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 2b92de17b5a2..bd7db36ba197 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -989,7 +989,7 @@ struct etmv4_drvdata {
 	struct clk			*pclk;
 	void __iomem			*base;
 	struct coresight_device		*csdev;
-	spinlock_t			spinlock;
+	raw_spinlock_t			spinlock;
 	int				cpu;
 	u8				arch;
 	u8				nr_pe;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:04 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:04 +0000
Subject: [PATCH v6 3/9] coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-4-yeoreum.yun@arm.com>

coresight_trace_id_map->lock can be acquired while coresight devices'
drvdata_lock.

But the drvdata_lock can be raw_spinlock_t (i.e) coresight-etm4x.

To address this, change type of coresight_trace_id_map->lock to
raw_spinlock_t

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c  |  2 +-
 .../hwtracing/coresight/coresight-trace-id.c  | 22 +++++++++----------
 include/linux/coresight.h                     |  2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..90649837c29e 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1296,7 +1296,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 
 	if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
 	    csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
-		spin_lock_init(&csdev->perf_sink_id_map.lock);
+		raw_spin_lock_init(&csdev->perf_sink_id_map.lock);
 		csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
 		if (!csdev->perf_sink_id_map.cpu_map) {
 			kfree(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-trace-id.c b/drivers/hwtracing/coresight/coresight-trace-id.c
index 378af743be45..7ed337d54d3e 100644
--- a/drivers/hwtracing/coresight/coresight-trace-id.c
+++ b/drivers/hwtracing/coresight/coresight-trace-id.c
@@ -22,7 +22,7 @@ enum trace_id_flags {
 static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
 static struct coresight_trace_id_map id_map_default = {
 	.cpu_map = &id_map_default_cpu_ids,
-	.lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock)
+	.lock = __RAW_SPIN_LOCK_UNLOCKED(id_map_default.lock)
 };
 
 /* #define TRACE_ID_DEBUG 1 */
@@ -131,11 +131,11 @@ static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map
 	unsigned long flags;
 	int cpu;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
 	for_each_possible_cpu(cpu)
 		atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 	DUMP_ID_MAP(id_map);
 }
 
@@ -144,7 +144,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
 	unsigned long flags;
 	int id;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 
 	/* check for existing allocation for this CPU */
 	id = _coresight_trace_id_read_cpu_id(cpu, id_map);
@@ -171,7 +171,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
 	atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
 
 get_cpu_id_out_unlock:
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID_CPU(cpu, id);
 	DUMP_ID_MAP(id_map);
@@ -188,12 +188,12 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma
 	if (!id)
 		return;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 
 	coresight_trace_id_free(id, id_map);
 	atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
 
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 	DUMP_ID_CPU(cpu, id);
 	DUMP_ID_MAP(id_map);
 }
@@ -204,9 +204,9 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i
 	unsigned long flags;
 	int id;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	id = coresight_trace_id_alloc_new_id(id_map, preferred_id, traceid_flags);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID(id);
 	DUMP_ID_MAP(id_map);
@@ -217,9 +217,9 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&id_map->lock, flags);
+	raw_spin_lock_irqsave(&id_map->lock, flags);
 	coresight_trace_id_free(id, id_map);
-	spin_unlock_irqrestore(&id_map->lock, flags);
+	raw_spin_unlock_irqrestore(&id_map->lock, flags);
 
 	DUMP_ID(id);
 	DUMP_ID_MAP(id_map);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 4541bfc1cc6b..d79a242b271d 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -239,7 +239,7 @@ struct coresight_trace_id_map {
 	DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX);
 	atomic_t __percpu *cpu_map;
 	atomic_t perf_cs_etm_session_active;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 };
 
 /**
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:05 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:05 +0000
Subject: [PATCH v6 4/9] coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-5-yeoreum.yun@arm.com>

In coresight-cti drivers, cti_drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().

Since cti_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type cti_drvdata->spinlock in coresight-cti drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-cti-core.c  | 44 +++++------
 .../hwtracing/coresight/coresight-cti-sysfs.c | 76 +++++++++----------
 drivers/hwtracing/coresight/coresight-cti.h   |  2 +-
 3 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index d2b5a5718c29..80f6265e3740 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -93,7 +93,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 	unsigned long flags;
 	int rc = 0;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* no need to do anything if enabled or unpowered*/
 	if (config->hw_enabled || !config->hw_powered)
@@ -108,7 +108,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 
 	config->hw_enabled = true;
 	drvdata->config.enable_req_count++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 
 cti_state_unchanged:
@@ -116,7 +116,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
 
 	/* cannot enable due to error */
 cti_err_not_enabled:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 }
 
@@ -125,7 +125,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
 {
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	config->hw_powered = true;
 
 	/* no need to do anything if no enable request */
@@ -138,12 +138,12 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
 
 	cti_write_all_hw_regs(drvdata);
 	config->hw_enabled = true;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return;
 
 	/* did not re-enable due to no claim / no request */
 cti_hp_not_enabled:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 }
 
 /* disable hardware */
@@ -153,7 +153,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
 	struct coresight_device *csdev = drvdata->csdev;
 	int ret = 0;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* don't allow negative refcounts, return an error */
 	if (!drvdata->config.enable_req_count) {
@@ -177,12 +177,12 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
 
 	coresight_disclaim_device_unlocked(csdev);
 	CS_LOCK(drvdata->base);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return ret;
 
 	/* not disabled this call */
 cti_not_disabled:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return ret;
 }
 
@@ -198,11 +198,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* write if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIINTACK, ackval);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 }
 
 /*
@@ -369,7 +369,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
 	reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
 		      CTIOUTEN(trigger_idx));
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* read - modify write - the trigger / channel enable value */
 	reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
@@ -388,7 +388,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, reg_value);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return 0;
 }
 
@@ -406,7 +406,7 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
 
 	chan_bitmask = BIT(channel_idx);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	reg_value = config->ctigate;
 	switch (op) {
 	case CTI_GATE_CHAN_ENABLE:
@@ -426,7 +426,7 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
 		if (cti_active(config))
 			cti_write_single_reg(drvdata, CTIGATE, reg_value);
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return err;
 }
 
@@ -445,7 +445,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 
 	chan_bitmask = BIT(channel_idx);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	reg_value = config->ctiappset;
 	switch (op) {
 	case CTI_CHAN_SET:
@@ -473,7 +473,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 
 	if ((err == 0) && cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, reg_value);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return err;
 }
@@ -676,7 +676,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
 	if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
 		return NOTIFY_BAD;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	switch (cmd) {
 	case CPU_PM_ENTER:
@@ -716,7 +716,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
 	}
 
 cti_notify_exit:
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return notify_res;
 }
 
@@ -743,11 +743,11 @@ static int cti_dying_cpu(unsigned int cpu)
 	if (!drvdata)
 		return 0;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.hw_powered = false;
 	if (drvdata->config.hw_enabled)
 		coresight_disclaim_device(drvdata->csdev);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return 0;
 }
 
@@ -888,7 +888,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->ctidev.ctm_id = 0;
 	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	/* initialise CTI driver config values */
 	cti_set_default_config(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index d25dd2737b49..572b80ee96fb 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -84,11 +84,11 @@ static ssize_t enable_show(struct device *dev,
 	bool enabled, powered;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	enable_req = drvdata->config.enable_req_count;
 	powered = drvdata->config.hw_powered;
 	enabled = drvdata->config.hw_enabled;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	if (powered)
 		return sprintf(buf, "%d\n", enabled);
@@ -134,9 +134,9 @@ static ssize_t powered_show(struct device *dev,
 	bool powered;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	powered = drvdata->config.hw_powered;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return sprintf(buf, "%d\n", powered);
 }
@@ -181,10 +181,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
 	u32 val = 0;
 
 	pm_runtime_get_sync(dev->parent);
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (drvdata->config.hw_powered)
 		val = readl_relaxed(drvdata->base + cti_attr->off);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	pm_runtime_put_sync(dev->parent);
 	return sysfs_emit(buf, "0x%x\n", val);
 }
@@ -202,10 +202,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
 		return -EINVAL;
 
 	pm_runtime_get_sync(dev->parent);
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if (drvdata->config.hw_powered)
 		cti_write_single_reg(drvdata, cti_attr->off, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	pm_runtime_put_sync(dev->parent);
 	return size;
 }
@@ -264,7 +264,7 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	if ((reg_offset >= 0) && cti_active(config)) {
 		CS_UNLOCK(drvdata->base);
 		val = readl_relaxed(drvdata->base + reg_offset);
@@ -274,7 +274,7 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
 	} else if (pcached_val) {
 		val = *pcached_val;
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#x\n", val);
 }
 
@@ -293,7 +293,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	/* local store */
 	if (pcached_val)
 		*pcached_val = (u32)val;
@@ -301,7 +301,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
 	/* write through if offset and enabled */
 	if ((reg_offset >= 0) && cti_active(config))
 		cti_write_single_reg(drvdata, reg_offset, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 
@@ -349,9 +349,9 @@ static ssize_t inout_sel_store(struct device *dev,
 	if (val > (CTIINOUTEN_MAX - 1))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.ctiinout_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(inout_sel);
@@ -364,10 +364,10 @@ static ssize_t inen_show(struct device *dev,
 	int index;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = drvdata->config.ctiinout_sel;
 	val = drvdata->config.ctiinen[index];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#lx\n", val);
 }
 
@@ -383,14 +383,14 @@ static ssize_t inen_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = config->ctiinout_sel;
 	config->ctiinen[index] = val;
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIINEN(index), val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(inen);
@@ -403,10 +403,10 @@ static ssize_t outen_show(struct device *dev,
 	int index;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = drvdata->config.ctiinout_sel;
 	val = drvdata->config.ctiouten[index];
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%#lx\n", val);
 }
 
@@ -422,14 +422,14 @@ static ssize_t outen_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	index = config->ctiinout_sel;
 	config->ctiouten[index] = val;
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIOUTEN(index), val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(outen);
@@ -463,7 +463,7 @@ static ssize_t appclear_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* a 1'b1 in appclr clears down the same bit in appset*/
 	config->ctiappset &= ~val;
@@ -471,7 +471,7 @@ static ssize_t appclear_store(struct device *dev,
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(appclear);
@@ -487,12 +487,12 @@ static ssize_t apppulse_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* write through if enabled */
 	if (cti_active(config))
 		cti_write_single_reg(drvdata, CTIAPPPULSE, val);
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(apppulse);
@@ -681,9 +681,9 @@ static ssize_t trig_filter_enable_show(struct device *dev,
 	u32 val;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = drvdata->config.trig_filter_enable;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return sprintf(buf, "%d\n", val);
 }
 
@@ -697,9 +697,9 @@ static ssize_t trig_filter_enable_store(struct device *dev,
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.trig_filter_enable = !!val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_RW(trig_filter_enable);
@@ -728,7 +728,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cti_config *config = &drvdata->config;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 
 	/* clear the CTI trigger / channel programming registers */
 	for (i = 0; i < config->nr_trig_max; i++) {
@@ -747,7 +747,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
 	if (cti_active(config))
 		cti_write_all_hw_regs(drvdata);
 
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR_WO(chan_xtrigs_reset);
@@ -768,9 +768,9 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
 	if (val > (drvdata->config.nr_ctm_channels - 1))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	drvdata->config.xtrig_rchan_sel = val;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 	return size;
 }
 
@@ -781,9 +781,9 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
 	unsigned long val;
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	val = drvdata->config.xtrig_rchan_sel;
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	return sprintf(buf, "%ld\n", val);
 }
@@ -838,12 +838,12 @@ static ssize_t print_chan_list(struct device *dev,
 	unsigned long inuse_bits = 0, chan_mask;
 
 	/* scan regs to get bitmap of channels in use. */
-	spin_lock(&drvdata->spinlock);
+	raw_spin_lock(&drvdata->spinlock);
 	for (i = 0; i < config->nr_trig_max; i++) {
 		inuse_bits |= config->ctiinen[i];
 		inuse_bits |= config->ctiouten[i];
 	}
-	spin_unlock(&drvdata->spinlock);
+	raw_spin_unlock(&drvdata->spinlock);
 
 	/* inverse bits if printing free channels */
 	if (!inuse)
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index cb9ee616d01f..16e310e7e9d4 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -175,7 +175,7 @@ struct cti_drvdata {
 	void __iomem *base;
 	struct coresight_device	*csdev;
 	struct cti_device ctidev;
-	spinlock_t spinlock;
+	raw_spinlock_t spinlock;
 	struct cti_config config;
 	struct list_head node;
 	void (*csdev_release)(struct device *dev);
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:06 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:06 +0000
Subject: [PATCH v6 5/9] coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-6-yeoreum.yun@arm.com>

In coresight-etb10 drivers, etb_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since etb_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 26 +++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index aea9ac9c4bd0..7948597d483d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -84,7 +84,7 @@ struct etb_drvdata {
 	struct clk		*atclk;
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	local_t			reading;
 	pid_t			pid;
 	u8			*buf;
@@ -145,7 +145,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
 	unsigned long flags;
 	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't messup with perf sessions. */
 	if (coresight_get_mode(csdev) == CS_MODE_PERF) {
@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
 
 	csdev->refcnt++;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
 }
 
@@ -176,7 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* No need to continue if the component is already in used by sysFS. */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
@@ -219,7 +219,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
 }
 
@@ -352,11 +352,11 @@ static int etb_disable(struct coresight_device *csdev)
 	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	unsigned long flags;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -366,7 +366,7 @@ static int etb_disable(struct coresight_device *csdev)
 	/* Dissociate from monitored process. */
 	drvdata->pid = -1;
 	coresight_set_mode(csdev, CS_MODE_DISABLED);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "ETB disabled\n");
 	return 0;
@@ -443,7 +443,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
 
 	capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1)
@@ -566,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
 	__etb_enable_hw(drvdata);
 	CS_LOCK(drvdata->base);
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return to_read;
 }
@@ -587,13 +587,13 @@ static void etb_dump(struct etb_drvdata *drvdata)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
 		__etb_disable_hw(drvdata);
 		etb_dump_hw(drvdata);
 		__etb_enable_hw(drvdata);
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&drvdata->csdev->dev, "ETB dumped\n");
 }
@@ -746,7 +746,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->base = base;
 	desc.access = CSDEV_ACCESS_IOMEM(base);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
 
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:08 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:08 +0000
Subject: [PATCH v6 7/9] coresight-replicator: change replicator_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-8-yeoreum.yun@arm.com>

In coresight-replicator drivers, replicator_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since replicator_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type replicator_drvdata->spinlock in
coresight-replicator drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/coresight-replicator.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index a1181c9048c0..ee7ee79f6cf7 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -41,7 +41,7 @@ struct replicator_drvdata {
 	struct clk		*atclk;
 	struct clk		*pclk;
 	struct coresight_device	*csdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	bool			check_idfilter_val;
 };
 
@@ -125,7 +125,7 @@ static int replicator_enable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (out->src_refcnt == 0) {
 		if (drvdata->base)
 			rc = dynamic_replicator_enable(drvdata, in->dest_port,
@@ -135,7 +135,7 @@ static int replicator_enable(struct coresight_device *csdev,
 	}
 	if (!rc)
 		out->src_refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "REPLICATOR enabled\n");
@@ -179,14 +179,14 @@ static void replicator_disable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (--out->src_refcnt == 0) {
 		if (drvdata->base)
 			dynamic_replicator_disable(drvdata, in->dest_port,
 						   out->src_port);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
@@ -277,7 +277,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
 	}
 	dev->platform_data = pdata;
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	desc.type = CORESIGHT_DEV_TYPE_LINK;
 	desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
 	desc.ops = &replicator_cs_ops;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:09 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:09 +0000
Subject: [PATCH v6 8/9] coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-9-yeoreum.yun@arm.com>

In coresight-tmc drivers, tmc_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since tmc_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type tmc_drvdata->spinlock in coresight-tmc drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 .../hwtracing/coresight/coresight-tmc-core.c  | 14 +++---
 .../hwtracing/coresight/coresight-tmc-etf.c   | 48 +++++++++----------
 .../hwtracing/coresight/coresight-tmc-etr.c   | 44 ++++++++---------
 drivers/hwtracing/coresight/coresight-tmc.h   |  2 +-
 4 files changed, 54 insertions(+), 54 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index d5122e12daa7..a7814e8e657b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -358,12 +358,12 @@ static int tmc_crashdata_open(struct inode *inode, struct file *file)
 	mdata = drvdata->crash_mdata.vaddr;
 	rbuf = &drvdata->resrv_buf;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (mdata->valid)
 		rbuf->reading = true;
 	else
 		err = -ENOENT;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	if (err)
 		goto exit;
 
@@ -408,9 +408,9 @@ static int tmc_crashdata_release(struct inode *inode, struct file *file)
 						   crashdev);
 
 	rbuf = &drvdata->resrv_buf;
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	rbuf->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__);
 	return ret;
@@ -801,7 +801,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
 	drvdata->base = base;
 	desc.access = CSDEV_ACCESS_IOMEM(base);
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 
 	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
 	drvdata->config_type = BMVAL(devid, 6, 7);
@@ -913,7 +913,7 @@ static void tmc_shutdown(struct amba_device *adev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_DISABLED)
 		goto out;
@@ -927,7 +927,7 @@ static void tmc_shutdown(struct amba_device *adev)
 	 * the system is going down after this.
 	 */
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 }
 
 static void __tmc_remove(struct device *dev)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index bdc3a7e9ba06..d858740001c2 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -185,9 +185,9 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 	 * If we don't have a buffer release the lock and allocate memory.
 	 * Otherwise keep the lock and move along.
 	 */
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (!drvdata->buf) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 		/* Allocating the memory here while outside of the spinlock */
 		buf = kzalloc(drvdata->size, GFP_KERNEL);
@@ -195,7 +195,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 			return -ENOMEM;
 
 		/* Let's try again */
-		spin_lock_irqsave(&drvdata->spinlock, flags);
+		raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	}
 
 	if (drvdata->reading) {
@@ -237,7 +237,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 		used = false;
 	}
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free memory outside the spinlock if need be */
 	if (!used)
@@ -255,7 +255,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	do {
 		ret = -EINVAL;
 		if (drvdata->reading)
@@ -298,7 +298,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
 			csdev->refcnt++;
 		}
 	} while (0);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -333,16 +333,16 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -353,7 +353,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
 	drvdata->pid = -1;
 	coresight_set_mode(csdev, CS_MODE_DISABLED);
 
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n");
 	return 0;
@@ -368,9 +368,9 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -383,7 +383,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
 	}
 	if (!ret)
 		csdev->refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "TMC-ETF enabled\n");
@@ -398,9 +398,9 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return;
 	}
 
@@ -410,7 +410,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 		coresight_set_mode(csdev, CS_MODE_DISABLED);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
@@ -490,7 +490,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
 	if (WARN_ON_ONCE(coresight_get_mode(csdev) != CS_MODE_PERF))
 		return 0;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1)
@@ -587,7 +587,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
 	 */
 	CS_LOCK(drvdata->base);
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return to_read;
 }
@@ -705,7 +705,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
 		ret = -EBUSY;
@@ -737,7 +737,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 
 	drvdata->reading = true;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -754,14 +754,14 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Re-enable the TMC if need be */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
 		/* There is no point in reading a TMC in HW FIFO mode */
 		mode = readl_relaxed(drvdata->base + TMC_MODE);
 		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 			return -EINVAL;
 		}
 		/*
@@ -775,7 +775,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 		memset(drvdata->buf, 0, drvdata->size);
 		rc = __tmc_etb_enable_hw(drvdata);
 		if (rc) {
-			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 			return rc;
 		}
 	} else {
@@ -788,7 +788,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/*
 	 * Free allocated memory outside of the spinlock.  There is no need
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index eda7cdad0e2b..76a8cb29b68a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1251,10 +1251,10 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 	 * buffer, provided the size matches. Any allocation has to be done
 	 * with the lock released.
 	 */
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
 	if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 		/* Allocate memory with the locks released */
 		free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
@@ -1262,7 +1262,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 			return new_buf;
 
 		/* Let's try again */
-		spin_lock_irqsave(&drvdata->spinlock, flags);
+		raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	}
 
 	if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) {
@@ -1281,7 +1281,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free memory outside the spinlock if need be */
 	if (free_buf)
@@ -1299,7 +1299,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
 	if (IS_ERR(sysfs_buf))
 		return PTR_ERR(sysfs_buf);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/*
 	 * In sysFS mode we can have multiple writers per sink.  Since this
@@ -1318,7 +1318,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
 	}
 
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (!ret)
 		dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@@ -1637,17 +1637,17 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
 	struct etr_perf_buffer *etr_perf = config;
 	struct etr_buf *etr_buf = etr_perf->etr_buf;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* Don't do anything if another tracer is using this sink */
 	if (csdev->refcnt != 1) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		goto out;
 	}
 
 	if (WARN_ON(drvdata->perf_buf != etr_buf)) {
 		lost = true;
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		goto out;
 	}
 
@@ -1657,7 +1657,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
 	tmc_sync_etr_buf(drvdata);
 
 	CS_LOCK(drvdata->base);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	lost = etr_buf->full;
 	offset = etr_buf->offset;
@@ -1726,7 +1726,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
 	struct perf_output_handle *handle = data;
 	struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	 /* Don't use this sink if it is already claimed by sysFS */
 	if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
 		rc = -EBUSY;
@@ -1766,7 +1766,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
 	}
 
 unlock_out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return rc;
 }
 
@@ -1788,16 +1788,16 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
 	csdev->refcnt--;
 	if (csdev->refcnt) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 		return -EBUSY;
 	}
 
@@ -1810,7 +1810,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
 	/* Reset perf specific data */
 	drvdata->perf_buf = NULL;
 
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_dbg(&csdev->dev, "TMC-ETR disabled\n");
 	return 0;
@@ -1910,7 +1910,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
 		ret = -EBUSY;
 		goto out;
@@ -1932,7 +1932,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 
 	drvdata->reading = true;
 out:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return ret;
 }
@@ -1946,7 +1946,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
 		return -EINVAL;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* RE-enable the TMC if need be */
 	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
@@ -1966,7 +1966,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	}
 
 	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	/* Free allocated memory out side of the spinlock */
 	if (sysfs_buf)
@@ -2023,14 +2023,14 @@ static int buf_mode_set_resrv(struct tmc_drvdata *drvdata)
 	rbuf = &drvdata->resrv_buf;
 
 	/* Ensure there are no active crashdata read sessions */
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (!rbuf->reading) {
 		tmc_crashdata_set_invalid(drvdata);
 		rbuf->len = 0;
 		drvdata->etr_mode = ETR_MODE_RESRV;
 		err = 0;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return err;
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index b48bc9a01cc0..6541a27a018e 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -249,7 +249,7 @@ struct tmc_drvdata {
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
 	struct miscdevice	crashdev;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 	pid_t			pid;
 	bool			reading;
 	bool			stop_on_flush;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:10 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:10 +0000
Subject: [PATCH v6 9/9] coresight/ultrasoc: change smb_drv_data spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-10-yeoreum.yun@arm.com>

In ultrasoc-smb drivers, smb_drv_data->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since smb__drv_data->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type smb_drv_data->spinlock in ultrasoc-smb drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.

Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
 drivers/hwtracing/coresight/ultrasoc-smb.c | 12 ++++++------
 drivers/hwtracing/coresight/ultrasoc-smb.h |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index dc3c9504dd7c..26cfc939e5bd 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -98,7 +98,7 @@ static int smb_open(struct inode *inode, struct file *file)
 	struct smb_drv_data *drvdata = container_of(file->private_data,
 					struct smb_drv_data, miscdev);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	if (drvdata->reading)
 		return -EBUSY;
@@ -152,7 +152,7 @@ static int smb_release(struct inode *inode, struct file *file)
 	struct smb_drv_data *drvdata = container_of(file->private_data,
 					struct smb_drv_data, miscdev);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 	drvdata->reading = false;
 
 	return 0;
@@ -245,7 +245,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
 	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
 	int ret = 0;
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	/* Do nothing, the trace data is reading by other interface now */
 	if (drvdata->reading)
@@ -280,7 +280,7 @@ static int smb_disable(struct coresight_device *csdev)
 {
 	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	if (drvdata->reading)
 		return -EBUSY;
@@ -378,7 +378,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev,
 	if (!buf)
 		return 0;
 
-	guard(spinlock)(&drvdata->spinlock);
+	guard(raw_spinlock)(&drvdata->spinlock);
 
 	/* Don't do anything if another tracer is using this sink. */
 	if (csdev->refcnt != 1)
@@ -563,7 +563,7 @@ static int smb_probe(struct platform_device *pdev)
 
 	smb_reset_buffer(drvdata);
 	platform_set_drvdata(pdev, drvdata);
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	drvdata->pid = -1;
 
 	ret = smb_register_sink(pdev, drvdata);
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h
index a91d39cfccb8..c4c111275627 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.h
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.h
@@ -115,7 +115,7 @@ struct smb_drv_data {
 	struct coresight_device	*csdev;
 	struct smb_data_buffer sdb;
 	struct miscdevice miscdev;
-	spinlock_t spinlock;
+	raw_spinlock_t spinlock;
 	bool reading;
 	pid_t pid;
 };
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From yeoreum.yun at arm.com  Thu Mar  6 04:11:07 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu,  6 Mar 2025 12:11:07 +0000
Subject: [PATCH v6 6/9] coresight-funnel: change funnel_drvdata spinlock's type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <20250306121110.1647948-7-yeoreum.yun@arm.com>

In coresight-funnel drivers, cti_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().

Since funnel_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.

To address this, change type funnel_drvdata->spinlock in
coresight-funnel drivers, which can be called by
perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
Reviewed-by: James Clark <james.clark at linaro.org>
Reviewed-by: Mike Leach <mike.leach at linaro.org>
---
 drivers/hwtracing/coresight/coresight-funnel.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 8faf51469bb8..0541712b2bcb 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -47,7 +47,7 @@ struct funnel_drvdata {
 	struct clk		*pclk;
 	struct coresight_device	*csdev;
 	unsigned long		priority;
-	spinlock_t		spinlock;
+	raw_spinlock_t		spinlock;
 };
 
 static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
@@ -85,7 +85,7 @@ static int funnel_enable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool first_enable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (in->dest_refcnt == 0) {
 		if (drvdata->base)
 			rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
@@ -94,7 +94,7 @@ static int funnel_enable(struct coresight_device *csdev,
 	}
 	if (!rc)
 		in->dest_refcnt++;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (first_enable)
 		dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n",
@@ -129,13 +129,13 @@ static void funnel_disable(struct coresight_device *csdev,
 	unsigned long flags;
 	bool last_disable = false;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
+	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (--in->dest_refcnt == 0) {
 		if (drvdata->base)
 			dynamic_funnel_disable_hw(drvdata, in->dest_port);
 		last_disable = true;
 	}
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	if (last_disable)
 		dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n",
@@ -266,7 +266,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
 	}
 	dev->platform_data = pdata;
 
-	spin_lock_init(&drvdata->spinlock);
+	raw_spin_lock_init(&drvdata->spinlock);
 	desc.type = CORESIGHT_DEV_TYPE_LINK;
 	desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
 	desc.ops = &funnel_cs_ops;
-- 
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From andyshrk at 163.com  Thu Mar  6 04:15:13 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 6 Mar 2025 20:15:13 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
Message-ID: <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>

Hi Piotr,

? 2025-03-06 19:47:31?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 09:53:
>> 
>> 
>> Hi,
>> 
>> ? 2025-03-06 16:42:00?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>>> 
>>> 
>>>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 01:59:
>>>> 
>>>> 
>>>> 
>>>> 
>>>> Both of the two config options should be enabled.
>>>> andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
>>>> 4044:CONFIG_ROCKCHIP_DW_DP=y
>>> 
>>> here i?m a bit lost?.
>>> greping on full kernel sources (with applied https://patchwork.kernel.org/project/linux-rockchip/list/?series=936784) gives me no single appearance of ROCKCHIP_DW_DP?
>>> Do i miss something?
>> 
>> see PATCH 3/6:   
>> 
>> 
>> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
>> index 26c4410b2407..c8638baf9641 100644
>> --- a/drivers/gpu/drm/rockchip/Kconfig
>> +++ b/drivers/gpu/drm/rockchip/Kconfig
>> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
>> select DRM_PANEL
>> select VIDEOMODE_HELPERS
>> select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
>> + select DRM_DW_DP if ROCKCHIP_DW_DP
>> select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
>> select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
>> select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
>> @@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
>>  RK3399 based SoC, you should select this
>>  option.
>> 
>> +config ROCKCHIP_DW_DP
>> + bool "Rockchip specific extensions for Synopsys DW DP"
>> + help
>> +  Choose this option for Synopsys DesignWare Cores DisplayPort
>> +  transmit controller support on Rockchip SoC.
>> 
>> https://lore.kernel.org/linux-rockchip/047EECFC-7E55-44EC-896F-13FE04333E4D at gmail.com/T/#m178a325ea0ebc64187aae474d77c3f7a9e0bc93d
>>> 
>
>
>Ah my bad!
>One patch patch was commented - so not all dp code was applied.
>
>Now it is much better:
>
>root at myth-frontend-56b0f018b5e0:~ # dmesg | grep drm
>[    9.795380] panthor fb000000.gpu: [drm] clock rate = 198000000
>[    9.796257] panthor fb000000.gpu: [drm] mali-g610 id 0xa867 major 0x0 minor 0x0 status 0x5
>[    9.796262] panthor fb000000.gpu: [drm] Features: L2:0x7120306 Tiler:0x809 Mem:0x301 MMU:0x2830 AS:0xff
>[    9.796265] panthor fb000000.gpu: [drm] shader_present=0x50005 l2_present=0x1 tiler_present=0x1
>[    9.851869] panthor fb000000.gpu: [drm] Firmware protected mode entry not be supported, ignoring
>[    9.851921] panthor fb000000.gpu: [drm] Firmware git sha: 814b47b551159067b67a37c4e9adda458ad9d852
>[    9.852127] panthor fb000000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 Instrumentation features 0x71
>[    9.852436] [drm] Initialized panthor 1.3.0 for fb000000.gpu on minor 0
>[   10.003108] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
>[   10.004705] rockchip-drm display-subsystem: bound fde60000.dp (ops dw_dp_rockchip_component_ops)
>[   10.006085] rockchip-drm display-subsystem: bound fdea0000.hdmi (ops dw_hdmi_qp_rockchip_ops)
>[   10.006679] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 1
>[   10.006737] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
>[   10.007663] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
>
>Unfortunately still nothing on screen
>
>dri state: https://gist.github.com/warpme/5e971dfd2e9fd52fae76641831cebe46
>
>and kernel dmesg https://termbin.com/r0m3
>
>i?m not sure what is missing (some dts enablement or?.)

From your dts,  I find you use gpio for hpd, I'm not sure how to handle it  with upstream  code now.


&dp1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&dp1_hpd>;
	hpd-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
};

I suggest a change like this:

&dp1 {
	status = "okay";
	pinctrl-names = "default";
        pinctrl-0 = <&dp1m0_pins>;

};

And also remove dp1_hpd pinctrl in your dts.

Then when you DP cable plugin, you can run command as bellow to see if the driver detects the HPD:

# cat /sys/class/drm/card0-DP-1/status 
connected
# 





>  
>
>
>
>
>

From gcherian at marvell.com  Thu Mar  6 04:18:20 2025
From: gcherian at marvell.com (George Cherian)
Date: Thu, 6 Mar 2025 12:18:20 +0000
Subject: [EXTERNAL] Re: [PATCH v4 1/2] watchdog: Add a new flag
 WDIOF_STOP_MAYSLEEP
In-Reply-To: <28a711e5-b2cb-4d5f-bb78-259a01cd4bcc@roeck-us.net>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
 <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
 <7ac2b8db-22c7-4168-b1b7-4f9f0ab10531@pengutronix.de>
 <28a711e5-b2cb-4d5f-bb78-259a01cd4bcc@roeck-us.net>
Message-ID: <PH8PR18MB53812FCAE180303E5D434275C5CA2@PH8PR18MB5381.namprd18.prod.outlook.com>

Hi Guenter,

I am summarizing the topics we discussed in multiple threads here.

>>On 3/5/25 03:01, Ahmad Fatoum wrote:
>> Hi George,
>> Hi Guenter,
>> 
>> On 05.03.25 11:34, George Cherian wrote:
>>>> why is armada_37xx_wdt also here?
>>>> The stop function in that driver may not sleep.
>>> Marek,
>>>
>>> Thanks for reviewing.
>>> Since the stop function has a regmap_write(), I thought it might sleep.
>>> Now that you pointed it out, I assume that it is an MMIO based regmap being used for armada.
>>> I will update the same in the next version
>> 
>> Failure to add WDIOF_STOP_MAYSLEEP when it's needed can lead to
>> kernel hanging. Failure to add an alternative WDIOF_STOP_ATOMIC
>> would lead to the kernel option being a no-op.
>> 
>> I think a no-op stop_on_panic (or reset_on_panic) is a saner default.
>> 
>
>Agreed. Also, I like WDIOF_STOP_ATOMIC more than the WDIOF_STOP_NOSLEEP
>I had suggested in my other response.

1. Instead of blacklisting drivers as WDIOF_STOP_MAYSLEEP, the option will an opt-in.
2. This may not be WDIOF_STOP_AOMIC, instead would be a generic flag not limited to STOP
    operation. May be WDIOF_OPS_ATOMIC (OPS include - .start, .stop, .set_timeout, .ping)
3. Remove the kernel command line option (stop_on_panic) and have a generic reset_on_panic.
4. reset_on_panic=60 (by default )  meaning on a panic the wdog timeout is updated to 60sec
     or the clamp_t(reset_on_panic, min, max_hw_heartbeat_ms).
5. if reset_on_panic=0, it means the watchdog is stopped on panic.
6. All of these to be done by default from panic handler incase of a configured kdump kernel.

-George

>
>Thanks,
>Guenter


From nfraprado at collabora.com  Thu Mar  6 04:19:22 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Thu, 6 Mar 2025 09:19:22 -0300
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
 <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>
Message-ID: <2fa6037d-b5e9-45b2-a5d5-dbc92fb3434b@notapiano>

On Thu, Mar 06, 2025 at 08:57:27AM +0100, Krzysztof Kozlowski wrote:
> On Wed, Mar 05, 2025 at 03:58:16PM -0300, N?colas F. R. A. Prado wrote:
> > Describe the accessory detection (accdet) module as a possible subnode
> > of the MT6359 PMIC.
> > 
> > Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> > ---
> >  .../devicetree/bindings/mfd/mediatek,mt6397.yaml   | 51 ++++++++++++++++++++++
> >  1 file changed, 51 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> > index 6a89b479d10fad3c8b61cab5a3af1453baca4d1a..51012b8bbfaef3df7bdb619a4f8d828d6f9cc15a 100644
> > --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> > +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
> > @@ -24,6 +24,7 @@ description: |
> >    - LED
> >    - Keys
> >    - Power controller
> > +  - Accessory Detection
> >  
> >    It is interfaced to host controller using SPI interface by a proprietary hardware
> >    called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
> > @@ -224,6 +225,30 @@ properties:
> >      description:
> >        Pin controller
> >  
> > +  accdet:
> > +    type: object
> > +    additionalProperties: false
> > +    description:
> > +      The Accessory Detection module found on the PMIC allows detecting audio
> > +      jack insertion and removal, as well as identifying the type of events
> > +      connected to the jack.
> > +
> > +    properties:
> > +      compatible:
> > +        const: mediatek,mt6359-accdet
> 
> You just removed the other file, no folding happened here. Drop the
> accdet node and fold this into parent.

Sorry, I'm still not sure what you mean by folding here then. Right now the
accdet is a subnode of the PMIC. If you want me to remove the accdet node, where
would its compatible and property go?

    pmic {
        compatible = "mediatek,mt6359";
        interrupt-controller;
        #interrupt-cells = <2>;

        accdet {
            compatible = "mediatek,mt6359-accdet";
            mediatek,hp-eint-high;
        };
    };

Thanks,
N?colas


From ptesarik at suse.com  Thu Mar  6 04:23:43 2025
From: ptesarik at suse.com (Petr Tesarik)
Date: Thu, 6 Mar 2025 13:23:43 +0100
Subject: [PATCH 1/1] arm64: enable PREEMPT_LAZY
In-Reply-To: <Z8hAZ09Q40fxLJSk@J2N7QTR9R3>
References: <20250305104925.189198-1-vschneid@redhat.com>
	<20250305104925.189198-2-vschneid@redhat.com>
	<Z8hAZ09Q40fxLJSk@J2N7QTR9R3>
Message-ID: <20250306132343.6b902a3d@mordecai.tesarici.cz>

On Wed, 5 Mar 2025 12:15:35 +0000
Mark Rutland <mark.rutland at arm.com> wrote:

> On Wed, Mar 05, 2025 at 11:49:25AM +0100, Valentin Schneider wrote:
> > From: Mark Rutland <mark.rutland at arm.com>
> > 
> > For an architecture to enable CONFIG_ARCH_HAS_RESCHED_LAZY, two things are
> > required:
> > 1) Adding a TIF_NEED_RESCHED_LAZY flag definition
> > 2) Checking for TIF_NEED_RESCHED_LAZY in the appropriate locations
> > 
> > 2) is handled in a generic manner by CONFIG_GENERIC_ENTRY, which isn't
> > (yet) implemented for arm64. However, outside of core scheduler code,
> > TIF_NEED_RESCHED_LAZY only needs to be checked on a kernel exit, meaning:
> > o return/entry to userspace.
> > o return/entry to guest.
> > 
> > The return/entry to a guest is all handled by xfer_to_guest_mode_handle_work()
> > which already does the right thing, so it can be left as-is.
> > 
> > arm64 doesn't use common entry's exit_to_user_mode_prepare(), so update its
> > return to user path to check for TIF_NEED_RESCHED_LAZY and call into
> > schedule() accordingly.
> > 
> > Link: https://lore.kernel.org/linux-rt-users/20241216190451.1c61977c at mordecai.tesarici.cz/
> > Link: https://lore.kernel.org/all/xhsmh4j0fl0p3.mognet at vschneid-thinkpadt14sgen2i.remote.csb/
> > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> > [testdrive, _TIF_WORK_MASK fixlet and changelog.]
> > Signed-off-by: Mike Galbraith <efault at gmx.de>
> > [Another round of testing; changelog faff]
> > Signed-off-by: Valentin Schneider <vschneid at redhat.com>
> > ---
> >  arch/arm64/Kconfig                   |  1 +
> >  arch/arm64/include/asm/thread_info.h | 16 +++++++++-------
> >  arch/arm64/kernel/entry-common.c     |  2 +-
> >  3 files changed, 11 insertions(+), 8 deletions(-)  
> 
> Catalin, Will, given this is small and self-contained, I reckon it makes
> sense to pick this up ahead of Jinjie's series to move arm64 over to the
> generic entry library (which is on my queue of things to review). Even
> if we pick up both, it'll be easier to bisect and debug issues caused by
> this patch alone.
> 
> The fixes/cleanups from Mike and Valentin look right to me, so FWIW:
> 
> Acked-by: Mark Rutland <mark.rutland at arm.com>

Thank you, all. Much appreciated.

Petr T


From miguel.ojeda.sandonis at gmail.com  Thu Mar  6 04:57:06 2025
From: miguel.ojeda.sandonis at gmail.com (Miguel Ojeda)
Date: Thu, 6 Mar 2025 13:57:06 +0100
Subject: [PATCH] kbuild: rust: add rustc-min-version support function
In-Reply-To: <CAK7LNAQC5Q5EQjuvMEWS5NAs-pixj3b--rkCHZ=xGQDTHqBBFQ@mail.gmail.com>
References: <20250210164245.282886-1-ojeda@kernel.org> <CAK7LNAQBFX5q6yyKBJoxMoD5d9SwdKm0c23J4+LpjwA1eh=bZw@mail.gmail.com>
 <CANiq72n=95jgJs17NFAkit5uzxqtO9xij9Um3ybd_RiMCpFrDQ@mail.gmail.com> <CAK7LNAQC5Q5EQjuvMEWS5NAs-pixj3b--rkCHZ=xGQDTHqBBFQ@mail.gmail.com>
Message-ID: <CANiq72nYUcGDmDG9Sx1AqgyXfkUWA4B5M3d5PexVfN7JB58Ryg@mail.gmail.com>

On Thu, Mar 6, 2025 at 12:37?PM Masahiro Yamada <masahiroy at kernel.org> wrote:
>
> This has not been picked up by any one in linux-next.

Yeah, I didn't start yet, sorry.

> I applied this to linux-kbuild now. Thanks.

Thanks!

Cheers,
Miguel


From amadeus at jmu.edu.cn  Thu Mar  6 05:40:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 21:40:02 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <4856313.kQq0lBPeGt@diego>
References: <4856313.kQq0lBPeGt@diego>
Message-ID: <20250306134002.380690-1-amadeus@jmu.edu.cn>

Hi,

> That sram is part of the soc (and has an mmio-address), so I'd think
> it should live inside the soc node?

But soc ranges starts from 0xfe000000, I don't know whether to change it.
And all other nodes are 0xf..., except this sram.
Any suggestions would be greatly appreciated.

Thanks,
Chukun

-- 
2.25.1



From robh at kernel.org  Thu Mar  6 05:39:59 2025
From: robh at kernel.org (Rob Herring)
Date: Thu, 6 Mar 2025 07:39:59 -0600
Subject: [PATCH 1/2] dt-bindings: memory-controllers: samsung,exynos4210-srom:
 Enforce child props
In-Reply-To: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
References: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
Message-ID: <CAL_JsqKODHZcrpqskA2aeK6EqGNx9aGNuPqGzhcZ_Nqiu+Ccww@mail.gmail.com>

On Thu, Mar 6, 2025 at 2:58?AM Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
>
> Samsung Exynos SROM peripheral properties were moved from the device
> schema to separate "peripheral-props" schema for child node, but the
> device schema does not reference the new one.
>
> Reference the peripheral-props schema so the child nodes will be
> properly validated from the device schema.
>
> Fixes: 67bf606fcf18 ("dt-bindings: memory-controllers: samsung,exynos4210-srom: Split out child node properties")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
>
> ---
>
> Fix for Rob's tree.
> ---
>  .../devicetree/bindings/memory-controllers/exynos-srom.yaml      | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
> index 2267c5107d60..1578514ec58d 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
> +++ b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
> @@ -38,6 +38,7 @@ properties:
>  patternProperties:
>    "^.*@[0-3],[a-f0-9]+$":
>      type: object
> +    $ref: mc-peripheral-props.yaml#

Why do we need this? Any child node should have a schema which needs
to include mc-peripheral-props.yaml if any properties from it can be
used.

Rob


From krzk at kernel.org  Thu Mar  6 05:43:21 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 14:43:21 +0100
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI
 controllers
In-Reply-To: <2376575.ElGaqSPkdT@workhorse>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
 <ffd6287c-cbfd-4ba8-9332-45bad4e60583@kernel.org>
 <2376575.ElGaqSPkdT@workhorse>
Message-ID: <81d60550-4929-48c1-b4d3-1473b902bf12@kernel.org>

On 06/03/2025 14:13, Nicolas Frattaroli wrote:
> On Thursday, 6 March 2025 08:42:54 Central European Standard Time Krzysztof 
> Kozlowski wrote:
>> On 05/03/2025 22:24, Nicolas Frattaroli wrote:
>>> Rockchip introduced a new audio controller called the "Serial Audio
>>> Interface", or "SAI" for short, on some of their newer SoCs. In
>>> particular, this controller is used several times on the RK3576 SoC.
>>>
>>> Add a schema for it, with only an RK3576 compatible for now. Other SoCs
>>> may follow as mainline support for them lands.
>>>
>>> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
>>> ---
>>>
>>>  .../devicetree/bindings/sound/rockchip,sai.yaml    | 151
>>>  +++++++++++++++++++++
>> Filename based on compatible.
> 
> Sure, but more compatibles will follow. Are you certain you want a file named 
> rockchip,rk3576-sai.yaml to then contain rockchip,rk3528-sai? If so then I do 

Yes (or the other way around if 3528 is older)

> not understand the reason behind this policy.

So the name will match hardware, instead of sai.yaml, sai2.yaml,
sai3.yaml and sai-green-frog.yaml.

> 
>>
>>>  MAINTAINERS                                        |   6 +
>>>  2 files changed, 157 insertions(+)
>>
>> ...
>>
>>> +
>>> +  dma-names:
>>> +    minItems: 1
>>> +    maxItems: 2
>>> +    oneOf:
>>> +      - const: tx
>>> +      - const: rx
>>> +      - items:
>>> +          - const: tx
>>> +          - const: rx
>>
>> Why all combinations are possible?
> 
> Because they are. sai5 in rk3576 is rx only. sai7 is tx only. Others are both 

What is sai5 and sai7? Instances on the same chip? Does it mean some of
instances can only receive and some only transmit?

> tx and rx. Do you want me to enforce that those with both are always tx 
> followed by rx?
> 
Best regards,
Krzysztof


From parvathi at couthit.com  Thu Mar  6 05:43:06 2025
From: parvathi at couthit.com (Parvathi Pudi)
Date: Thu, 6 Mar 2025 19:13:06 +0530 (IST)
Subject: [PATCH net-next v3 00/10] PRU-ICSSM Ethernet Driver
In-Reply-To: <506678778.717678.1740740287558.JavaMail.zimbra@couthit.local>
References: <20250214054702.1073139-1-parvathi@couthit.com> <20250226184408.d4gpr3uu2dm7oxa2@handwork> <506678778.717678.1740740287558.JavaMail.zimbra@couthit.local>
Message-ID: <1229872038.768025.1741268586173.JavaMail.zimbra@couthit.local>

Hi,

>> On 11:16-20250214, parvathi wrote:
>> [...]
>>> The patches presented in this series have gone through the patch verification
>>> tools and no warnings or errors are reported. Sample test logs verifying the
>>> functionality on Linux next kernel are available here:
>>> 
>>> [Interface up
>>> Testing](https://gist.github.com/ParvathiPudi/f481837cc6994e400284cb4b58972804)
>>> 
>>> [Ping
>>> Testing](https://gist.github.com/ParvathiPudi/a121aad402defcef389e93f303d79317)
>>> 
>>> [Iperf
>>> Testing](https://gist.github.com/ParvathiPudi/581db46b0e9814ddb5903bdfee73fc6f)
>>> 
>> 
>> 
>> I am looking at
>> https://lore.kernel.org/all/20250214085315.1077108-11-parvathi at couthit.com/
>> and wondering if i can see the test log for am335x and am47xx to make
>> sure that PRUs are functional on those two?
>> 
> 
> In this patch series we have added support for PRU-ICSS on the AM57x SOC.
> Hence the test log was only included for the AM57x SOC. We are working in
> parallel
> to add support for PRU-ICSS on the AM33x and AM43x SOC's as well. We will send
> it as
> a separate patch series at a later time.
> 

Further update:

We have successfully cross compiled the kernel (linux-next) with this patch series
for AM335x and AM437x SOC respectively.

Kernel is booting well on both the SOCs and we have verified PRU functionality by
loading simple example application (pru_addition.elf) on the PRU cores, by using
"remoteproc" driver from mainline kernel.

Below are the logs for the SOCs with boot log and running PRU with elf file specified
above:

AM335x test log: <https://gist.github.com/ParvathiPudi/87d7ddf949913b80f022ed99706337ac>
AM437x test log: <https://gist.github.com/ParvathiPudi/b2d556829cb4a9e3b6b4c5656dbdd594>


Thanks and Regards,
Parvathi.


From csokas.bence at prolan.hu  Thu Mar  6 05:44:37 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Thu, 6 Mar 2025 14:44:37 +0100
Subject: [PATCH v8 2/2] counter: microchip-tcb-capture: Add capture extensions for registers RA/RB
In-Reply-To: <20250306134441.582819-1-csokas.bence@prolan.hu>
References: <20250306134441.582819-1-csokas.bence@prolan.hu>
Message-ID: <20250306134441.582819-3-csokas.bence@prolan.hu>

TCB hardware is capable of capturing the timer value to registers RA and
RB. Add these registers as capture extensions.

Acked-by: William Breathitt Gray <wbg at kernel.org>
Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    Changes in v2:
    * Add IRQs
    Changes in v3:
    * Move IRQs to previous patch
    Changes in v4:
    * Return the status of the regmap_*() operations
    * Add names for the extension numbers
    Changes in v6:
    * Remove RC, as it is not a capture register
    Changes in v7:
    * Change enums to #define's in UAPI header
    * Return early on error in `mchp_tc_count_cap_read()`
    Changes in v8:
    * Collect William's tag

 drivers/counter/microchip-tcb-capture.c       | 58 +++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     |  6 ++
 2 files changed, 64 insertions(+)

diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 16707099bd69..aeaee6e0245e 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -253,6 +253,62 @@ static int mchp_tc_count_read(struct counter_device *counter,
 	return 0;
 }
 
+static int mchp_tc_count_cap_read(struct counter_device *counter,
+				  struct counter_count *count, size_t idx, u64 *val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	u32 cnt;
+	int ret;
+
+	switch (idx) {
+	case COUNTER_MCHP_EXCAP_RA:
+		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), &cnt);
+		break;
+	case COUNTER_MCHP_EXCAP_RB:
+		ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), &cnt);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	*val = cnt;
+
+	return 0;
+}
+
+static int mchp_tc_count_cap_write(struct counter_device *counter,
+				   struct counter_count *count, size_t idx, u64 val)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	int ret;
+
+	if (val > U32_MAX)
+		return -ERANGE;
+
+	switch (idx) {
+	case COUNTER_MCHP_EXCAP_RA:
+		ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), val);
+		break;
+	case COUNTER_MCHP_EXCAP_RB:
+		ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static DEFINE_COUNTER_ARRAY_CAPTURE(mchp_tc_cnt_cap_array, 2);
+
+static struct counter_comp mchp_tc_count_ext[] = {
+	COUNTER_COMP_ARRAY_CAPTURE(mchp_tc_count_cap_read, mchp_tc_count_cap_write,
+				   mchp_tc_cnt_cap_array),
+};
+
 static struct counter_count mchp_tc_counts[] = {
 	{
 		.id = 0,
@@ -261,6 +317,8 @@ static struct counter_count mchp_tc_counts[] = {
 		.num_functions = ARRAY_SIZE(mchp_tc_count_functions),
 		.synapses = mchp_tc_count_synapses,
 		.num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
+		.ext = mchp_tc_count_ext,
+		.num_ext = ARRAY_SIZE(mchp_tc_count_ext),
 	},
 };
 
diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
index f3ef315fe9f6..136e2faa7730 100644
--- a/include/uapi/linux/counter/microchip-tcb-capture.h
+++ b/include/uapi/linux/counter/microchip-tcb-capture.h
@@ -12,6 +12,8 @@
  * Count 0
  * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
  * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
+ * \__  Extension capture0    (RA register)
+ * \__  Extension capture1    (RB register)
  *
  * It also supports the following events:
  *
@@ -25,6 +27,10 @@
  * - RC compare triggered
  */
 
+/* Capture extensions */
+#define COUNTER_MCHP_EXCAP_RA 0
+#define COUNTER_MCHP_EXCAP_RB 1
+
 /* Event channels */
 #define COUNTER_MCHP_EVCHN_CV 0
 #define COUNTER_MCHP_EVCHN_RA 0
-- 
2.48.1




From Friday.Yang at mediatek.com  Thu Mar  6 04:46:06 2025
From: Friday.Yang at mediatek.com (=?utf-8?B?RnJpZGF5IFlhbmcgKOadqOmYsyk=?=)
Date: Thu, 6 Mar 2025 12:46:06 +0000
Subject: [PATCH v4 2/2] memory: mtk-smi: mt8188: Add SMI reset and clamp
 for MT8188
In-Reply-To: <771e1460-2372-4ecd-949b-016c1b91adb3@collabora.com>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
	 <20250221074846.14105-3-friday.yang@mediatek.com>
	 <771e1460-2372-4ecd-949b-016c1b91adb3@collabora.com>
Message-ID: <700ea49156e1beb0a5d000b6bbd569e663f8a487.camel@mediatek.com>

On Mon, 2025-02-24 at 09:41 +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 21/02/25 08:48, Friday Yang ha scritto:
> > From: "Friday Yang" <friday.yang at mediatek.com>
> > 
> > To prevent handling glitch signals during MTCMOS on/off
> > transitions,
> > SMI requires clamp and reset operations. Parse the reset settings
> > for
> > SMI LARBs and the clamp settings for the SMI Sub-Common. Register
> > genpd callback for the SMI LARBs located in image, camera and IPE
> > subsystems, and apply reset and clamp operations within the
> > callback.
> > 
> > Signed-off-by: Friday Yang <friday.yang at mediatek.com>
> > ---
> >   drivers/memory/mtk-smi.c | 141
> > +++++++++++++++++++++++++++++++++++++--
> >   1 file changed, 137 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> > index 5710348f72f6..51235c2a2081 100644
> > --- a/drivers/memory/mtk-smi.c
> > +++ b/drivers/memory/mtk-smi.c
> > @@ -10,11 +10,15 @@
> >   #include <linux/err.h>
> >   #include <linux/io.h>
> >   #include <linux/iopoll.h>
> > +#include <linux/mfd/syscon.h>
> >   #include <linux/module.h>
> >   #include <linux/of.h>
> >   #include <linux/of_platform.h>
> >   #include <linux/platform_device.h>
> > +#include <linux/pm_domain.h>
> >   #include <linux/pm_runtime.h>
> > +#include <linux/regmap.h>
> > +#include <linux/reset.h>
> >   #include <linux/soc/mediatek/mtk_sip_svc.h>
> >   #include <soc/mediatek/smi.h>
> >   #include <dt-bindings/memory/mt2701-larb-port.h>
> > @@ -36,6 +40,12 @@
> >   #define SMI_DCM                             0x300
> >   #define SMI_DUMMY                   0x444
> > 
> > +#define SMI_COMMON_CLAMP_EN          0x3c0
> > +#define SMI_COMMON_CLAMP_EN_SET              0x3c4
> > +#define SMI_COMMON_CLAMP_EN_CLR              0x3c8
> > +
> > +#define SMI_SUB_COMM_INPORT_NR               (8)
> > +
> >   /* SMI LARB */
> >   #define SMI_LARB_SLP_CON                0xc
> >   #define SLP_PROT_EN                     BIT(0)
> > @@ -134,6 +144,7 @@ struct mtk_smi_larb_gen {
> >       unsigned int                    larb_direct_to_common_mask;
> >       unsigned int                    flags_general;
> >       const
> > u8                        (*ostd)[SMI_LARB_PORT_NR_MAX];
> > +     const u8                        *clamp_port;
> >   };
> > 
> >   struct mtk_smi {
> > @@ -150,6 +161,7 @@ struct mtk_smi {
> >   };
> > 
> >   struct mtk_smi_larb { /* larb: local arbiter */
> > +     struct device                   *dev;
> >       struct mtk_smi                  smi;
> >       void __iomem                    *base;
> >       struct device                   *smi_common_dev; /* common or
> > sub-common dev */
> > @@ -157,6 +169,10 @@ struct mtk_smi_larb { /* larb: local arbiter
> > */
> >       int                             larbid;
> >       u32                             *mmu;
> >       unsigned char                   *bank;
> > +     struct regmap                   *sub_comm_syscon;
> > +     u8                              sub_comm_inport;
> > +     struct notifier_block           nb;
> > +     struct reset_control            *rst_con;
> >   };
> > 
> >   static int
> > @@ -377,6 +393,19 @@ static const u8
> > mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
> >       [28] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
> >   };
> > 
> > +static const u8 mtk_smi_larb_clamp_port_mt8188[MTK_LARB_NR_MAX] =
> > {
> > +     [9]     = BIT(1), /* larb10 */
> > +     [10]    = BIT(2), /* larb11a */
> > +     [11]    = BIT(2), /* larb11b */
> > +     [12]    = BIT(3), /* larb11c */
> > +     [13]    = BIT(0), /* larb12 */
> > +     [16]    = BIT(1), /* larb15 */
> > +     [17]    = BIT(2), /* larb16a */
> > +     [18]    = BIT(2), /* larb16b */
> > +     [19]    = BIT(3), /* larb17a */
> > +     [20]    = BIT(3), /* larb17b */
> > +};
> > +
> >   static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
> >       .port_in_larb = {
> >               LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
> > @@ -423,6 +452,7 @@ static const struct mtk_smi_larb_gen
> > mtk_smi_larb_mt8188 = {
> >       .flags_general              = MTK_SMI_FLAG_THRT_UPDATE |
> > MTK_SMI_FLAG_SW_FLAG |
> >                                     MTK_SMI_FLAG_SLEEP_CTL |
> > MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
> >       .ostd                       = mtk_smi_larb_mt8188_ostd,
> > +     .clamp_port                 = mtk_smi_larb_clamp_port_mt8188,
> >   };
> > 
> >   static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
> > @@ -472,6 +502,46 @@ static void
> > mtk_smi_larb_sleep_ctrl_disable(struct mtk_smi_larb *larb)
> >       writel_relaxed(0, larb->base + SMI_LARB_SLP_CON);
> >   }
> > 
> > +static int mtk_smi_larb_clamp_protect_enable(struct device *dev,
> > bool enable)
> > +{
> > +     struct mtk_smi_larb *larb = dev_get_drvdata(dev);
> > +     u32 reg;
> > +     int ret;
> > +
> > +     /* sub_comm_syscon could be NULL if larb directly linked to
> > SMI common */
> > +     if (!larb->sub_comm_syscon)
> > +             return -EINVAL;
> > +
> > +     reg = enable ? SMI_COMMON_CLAMP_EN_SET :
> > SMI_COMMON_CLAMP_EN_CLR;
> > +
> > +     ret = regmap_write(larb->sub_comm_syscon, reg,
> > +                        larb->sub_comm_inport);
> > +     if (ret)
> > +             dev_err(dev, "Unable to %s clamp for input port %d:
> > %d\n",
> > +                     enable ? "enable" : "disable",
> > +                     larb->sub_comm_inport, ret);
> > +
> > +     return ret;
> > +}
> > +
> > +static int mtk_smi_genpd_callback(struct notifier_block *nb,
> > +                               unsigned long flags, void *data)
> > +{
> > +     struct mtk_smi_larb *larb = container_of(nb, struct
> > mtk_smi_larb, nb);
> > +     struct device *dev = larb->dev;
> > +
> > +     if (flags == GENPD_NOTIFY_PRE_ON || flags ==
> > GENPD_NOTIFY_PRE_OFF) {
> > +             /* disable related SMI sub-common port */
> > +             mtk_smi_larb_clamp_protect_enable(dev, true);
> > +     } else if (flags == GENPD_NOTIFY_ON) {
> > +             /* enable related SMI sub-common port */
> > +             reset_control_reset(larb->rst_con);
> > +             mtk_smi_larb_clamp_protect_enable(dev, false);
> > +     }
> > +
> > +     return NOTIFY_OK;
> > +}
> > +
> >   static int mtk_smi_device_link_common(struct device *dev, struct
> > device **com_dev)
> >   {
> >       struct platform_device *smi_com_pdev;
> > @@ -528,6 +598,53 @@ static int mtk_smi_dts_clk_init(struct device
> > *dev, struct mtk_smi *smi,
> >       return ret;
> >   }
> > 
> > +static int mtk_smi_larb_parse_clamp_optional(struct mtk_smi_larb
> > *larb)
> > +{
> > +     struct device *dev = larb->dev;
> > +     const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
> > +     u32 larb_id;
> > +     int ret;
> > +
> > +     /**
> > +      * Only SMI LARBs in camera, image and IPE subsys need to
> > +      * apply clamp and reset operations, others can be skipped.
> > +      */
> > +     ret = of_property_read_u32(dev->of_node, "mediatek,larb-id",
> > &larb_id);
> > +     if (ret)
> > +             return -EINVAL;
> > +     if (!larb_gen->clamp_port || !larb_gen->clamp_port[larb_id])
> > +             return 0;
> > +
> > +     larb->sub_comm_inport = larb_gen->clamp_port[larb_id];
> > +     larb->sub_comm_syscon = syscon_regmap_lookup_by_phandle(dev-
> > >of_node,
> > +                                                             "medi
> > atek,smi");
> > +     if (IS_ERR(larb->sub_comm_syscon)) {
> > +             larb->sub_comm_syscon = NULL;
> > +             return dev_err_probe(dev, -EINVAL,
> > +                                  "Unknown clamp port for larb
> > %d\n", larb_id);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int mtk_smi_larb_parse_reset_optional(struct mtk_smi_larb
> > *larb)
> > +{
> > +     struct device *dev = larb->dev;
> > +     int ret;
> > +
> > +     larb->rst_con =
> > devm_reset_control_get_optional_exclusive(dev, "larb");
> > +     if (!larb->rst_con)
> > +             return 0;
> > +
> > +     larb->nb.notifier_call = mtk_smi_genpd_callback;
> > +     ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
> > +     if (ret)
> > +             return dev_err_probe(dev, -EINVAL,
> > +                                  "Failed to add genpd callback
> > %d\n", ret);
> > +
> > +     return 0;
> > +}
> > +
> >   static int mtk_smi_larb_probe(struct platform_device *pdev)
> >   {
> >       struct mtk_smi_larb *larb;
> > @@ -538,6 +655,7 @@ static int mtk_smi_larb_probe(struct
> > platform_device *pdev)
> >       if (!larb)
> >               return -ENOMEM;
> > 
> > +     larb->dev = dev;
> >       larb->larb_gen = of_device_get_match_data(dev);
> >       larb->base = devm_platform_ioremap_resource(pdev, 0);
> >       if (IS_ERR(larb->base))
> > @@ -554,15 +672,24 @@ static int mtk_smi_larb_probe(struct
> > platform_device *pdev)
> >       if (ret < 0)
> >               return ret;
> > 
> > -     pm_runtime_enable(dev);
> > +     ret = mtk_smi_larb_parse_clamp_optional(larb);
> > +     if (ret)
> > +             goto err_link_remove;
> > +
> > +     ret = mtk_smi_larb_parse_reset_optional(larb);
> > +     if (ret)
> > +             goto err_link_remove;
> > +
> 
> To avoid changing functionality, please call pm_runtime_enable()
> here, before
> component_add().
> 
> If you want to remove the goto, you could (please do it!) instead
> call
> devm_pm_runtime_enable() and error check.
> 
> Everything else looks good!
> 
> Cheers,
> Angelo


Thanks for your comments. I will replace pm_runtime_enable with 
devm_pm_runtime_enable and delete the pm_runtime_disable in 
mtk_smi_larb_remove and mtk_smi_common_remove. Just like this:

	ret = mtk_smi_larb_parse_reset_optional(larb);
	if (ret)
		goto err_link_remove;

	ret = devm_pm_runtime_enable(dev);
	if (ret)
		goto err_link_remove;

	platform_set_drvdata(pdev, larb);
	ret = component_add(dev, &mtk_smi_larb_component_ops);
	if (ret)
		goto err_link_remove;

	return 0;

err_link_remove:
	device_link_remove(dev, larb->smi_common_dev);


And I will update v5 as soon as possible.

> 
> >       platform_set_drvdata(pdev, larb);
> >       ret = component_add(dev, &mtk_smi_larb_component_ops);
> >       if (ret)
> > -             goto err_pm_disable;
> > +             goto err_link_remove;
> > +
> > +     pm_runtime_enable(dev);
> > +
> >       return 0;
> > 
> > -err_pm_disable:
> > -     pm_runtime_disable(dev);
> > +err_link_remove:
> >       device_link_remove(dev, larb->smi_common_dev);
> >       return ret;
> >   }
> > @@ -686,6 +813,11 @@ static const struct mtk_smi_common_plat
> > mtk_smi_common_mt8188_vpp = {
> >       .init     = mtk_smi_common_mt8195_init,
> >   };
> > 
> > +static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8188
> > = {
> > +     .type     = MTK_SMI_GEN2_SUB_COMM,
> > +     .has_gals = true,
> > +};
> > +
> >   static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
> >       .type     = MTK_SMI_GEN2,
> >       .has_gals = true,
> > @@ -729,6 +861,7 @@ static const struct of_device_id
> > mtk_smi_common_of_ids[] = {
> >       {.compatible = "mediatek,mt8186-smi-common", .data =
> > &mtk_smi_common_mt8186},
> >       {.compatible = "mediatek,mt8188-smi-common-vdo", .data =
> > &mtk_smi_common_mt8188_vdo},
> >       {.compatible = "mediatek,mt8188-smi-common-vpp", .data =
> > &mtk_smi_common_mt8188_vpp},
> > +     {.compatible = "mediatek,mt8188-smi-sub-common", .data =
> > &mtk_smi_sub_common_mt8188},
> >       {.compatible = "mediatek,mt8192-smi-common", .data =
> > &mtk_smi_common_mt8192},
> >       {.compatible = "mediatek,mt8195-smi-common-vdo", .data =
> > &mtk_smi_common_mt8195_vdo},
> >       {.compatible = "mediatek,mt8195-smi-common-vpp", .data =
> > &mtk_smi_common_mt8195_vpp},
> > --
> > 2.46.0
> > 
> 
> 

From angelogioacchino.delregno at collabora.com  Thu Mar  6 05:08:07 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 6 Mar 2025 14:08:07 +0100
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <0efe42427be4eb619b6ea7db18687b0211d1ec9f.camel@mediatek.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
 <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
 <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>
 <9d383fc5-8c64-478c-8aab-6c56bf5b45be@collabora.com>
 <0efe42427be4eb619b6ea7db18687b0211d1ec9f.camel@mediatek.com>
Message-ID: <1f9007ed-c978-431d-aab2-c04237d5d117@collabora.com>

Il 06/03/25 12:00, Jason-JH Lin (???) ha scritto:
> [snip]
>>
>>> CPR_GSIZE is the setting for allocating the CPR SRAM size to each
>>> VM.
>>
>> Would be awesome if you could then clarify the comment that you have
>> later in
>> the code here, from...
>>
>> /* config cpr size for host vm */
>>
>> to
>>
>> /* Set the amount of CPR SRAM to allocate to each VM */
>>
>> ...that could be a way of more properly describing what the writel
>> there is doing.
>>
> 
> OK, I'll change it.
> 
>>>
>>>> The GCE stuff isn't even properly described in datasheets - I do
>>>> (probably!)
>>>> understand what those are for, but asking people to get years of
>>>> experience on
>>>> MediaTek to understand what's going on would be a bit rude,
>>>> wouldn't
>>>> it? :-D
>>>>
>>>
>>> I agree with you :-)
>>> I'll put them in the VM patch and add some brief description for
>>> them.
>>>
>>
>> Thanks, much appreciated!
>>
>>>>> +
>>>>>  ?? #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
>>>>>  ?? #define CMDQ_THR_ENABLED??????????? 0x1
>>>>>  ?? #define CMDQ_THR_DISABLED?????????? 0x0
>>>>> @@ -87,11 +98,24 @@ struct cmdq {
>>>>>  ?? struct gce_plat {
>>>>>  ?????? u32 thread_nr;
>>>>>  ?????? u8 shift;
>>>>> +???? dma_addr_t mminfra_offset;
>>>>
>>>> It looks like this is exactly the DRAM's iostart... at least, I
>>>> can
>>>> see that in the
>>>> downstream devicetree that's where it starts.
>>>>
>>>>  ???????? memory: memory at 80000000 {
>>>>  ???????????????? device_type = "memory";
>>>>  ???????????????? reg = <0 0x80000000 0 0x40000000>;
>>>>  ???????? };
>>>>
>>>> It doesn't really look like being a coincidence, but, for the
>>>> sake of
>>>> asking:
>>>> is this just a coincidence? :-)
>>>>
>>>
>>> As the confirmation with the hardware designer in previous reply
>>> mail
>>> for CK:
>>> https://patchwork.kernel.org/project/linux-mediatek/patch/20250218054405.2017918-4-jason-jh.lin at mediatek.com/*26258463
>>>
>>
>> That explanation was simply wonderful.
>>
>>> Since the MMINFRA remap subtracting 2G is done in the hardware
>>> circuit
>>> and cannot be configured by software, the address +2G adjustment is
>>> necessary to implement in the CMDQ driver.
>>>
>>> So that might not be a coincidence.
>>> But even if DRAM start address changes, this mminfra_offset is
>>> still
>>> subtracting 2G, so I think it is a better choice to define it as
>>> the
>>> driver data for MT8196.
>>>
>>
>> ....so, this makes me think the following:
>>
>> 1. The DRAM start address cannot *ever* be less than 2G, because
>> otherwise the
>>  ??? MMINFRA HW would have a hole in the usable address range;
>>  ??? 1a. If the start address changes to less than 2G, then also the
>> IOMMU would
>>  ??????? get limitations, not only the mminfra..!
>>  ??? 2b. This makes it very very very unlikely for the start address
>> to be changed
>>  ??????? to less than 0x80000000
>>
>> 2. If the DRAM start address changes to be ABOVE 2G (so more than
>> 0x80000000),
>>  ??? there would be no point for MMINFRA to start a "config path"
>> write (or read)
>>  ??? in the SMMU DRAM block, would it? ;-)
>>
> 
> GCE is using IOMMU in MT8196, so all the address put into the GCE
> instruction or GCE register for GCE access should be IOVA.
> 
> The DRAM start address is 2G(PA=0x80000000, IOVA=0x0) currently, so
> when GCE want to access the IOVA=0x0, it will need to +2G into the
> instruction, then the MMINFRA will see it as data path(IOVA > 2G) and
> subtract 2G for that IOVA, so GCE can finally access the IOVA=0x0.
> 
> I'm not sure if I've misunderstood what you mean by ABOVE 2G. :-)
> If DRAM start address is changed to 3G(PA=0xc0000000) the IOVA is still
> 0x0, so GCE still need to + 2G to make MMINFRA go to the data path.
> 
> But if you mean PA=0x80000000 and IOVA start address is 3G(0xc0000000),
> then MMINFRA will go to the data path without GCE +2G.
> However, MMINFRA will -2G when going to the data path and that will
> cause GCE access the wrong IOVA.
> So GCE still need to +2G no matter IOVA start address is already can
> make MMINFRA go to the data path(IOVA > 2G).
> 
> We have already complained to our hardware designer that MMINFRA -2G
> con not be changed, which will make software operation very
> troublesome.
> So in the next few generations of SoC will change this MMINFRA -2G to
> software configurable. Then we can just make IOVA start address to 2G
> without adding the mminfra_offset to the IOVA for GCE.
> 

Okay now I got it, the reality is way worse than I was thinking... eww... :-(

>> I get it - if the DRAM moves up, MMINFRA is still at 2G because
>> that's hard baked
>> into the hardware, but I foresee that it'll be unlikely to see a
>> platform changing
>> the DRAM start address arbitrarily, getting out-of-sync with MMINFRA.
>>
>> I propose to just get the address from the memory node for now, and
>> to add a nice
>> comment in the code that explains that "In at least MT8196, the
>> MMINFRA hardware
>> subtracts xyz etc etc" (and that explanation from the previous email
>> is again
>> wonderful and shall not be lost: either use that in the comment, or
>> add it to
>> the commit description, because it's really that good).
>>
>> Should a new SoC appear in the future requiring an offset from the
>> DRAM start
>> address, we will think about how to make that work in the best
>> possible way: in
>> that case we could either reference something else to get the right
>> address or
>> we can just change this driver to just use the 2G offset statically
>> for all.
>>
>> What I'm trying to do here is to reduce the amount of changes that
>> we'd need for
>> adding new SoCs: since that 2G MMINFRA offset -> 2G DRAM start is not
>> a coincidence
>> I think that, should the DRAM start vary on new SoCs, the MMINFRA
>> offset will
>> follow the trend and vary with it.
>>
>> So what I think is:
>> 1. If I'm right, adding a new SoC (with different MMINFRA + DRAM
>> offset) will be
>>  ??? as easy as adding a compatible string in the bindings, no effort
>> in changing
>>  ??? this driver with new pdata offsets;
>> 2. If I'm wrong, adding a new SoC means adding compat string and
>> adding pdata and
>>  ??? one variable in the cmdq struct.
>>
>> Where N.2 is what we would do anyway if we don't go with my proposed
>> solution...
>>
>> All this is just to give you my considerations about this topic -
>> you're left
>> completely free to disagree with me.
>> If you disagree, I will trust your judgement, no problem here.
>>
> 
> Yes, I think your are right. No matter the IOVA start address changing,
> MMINFRA will still -2G(the start address of DRAM PA).
> Do you mean we can get the mminfra_offset from the start address of
> memory in DTS, rather than defining it in pdata?
> 

After the last explanation... no, it would be wrong to get the start from
memory in DTS, because then this will still need hacks.
I was somehow convinced that the DRAM start address and the MMINFRA offset
were directly related and that it would've been hard to change the DRAM
start address with the MMINFRA offset being -2G, but it's not, so doing it
my way will eventually backfire on us.

So my way is not good, as it's not showing the reality of things.

Just go with your current way, as it's really tied to the hardware and it's
not restricted to that dram start coincidence in the end. That's a pity.

Just instead of writing 0x80000000, use " SZ_2G " instead... and please
add a comment in the code that explains in brief that there's this strange
behavior for which we.. need that, and that's a static subtraction, and is
tied to the MMINFRA hardware, and cannot be changed :-(

btw, being clear..

#include <linux/sizes.h>

.mminfra_offset = SZ_2G,

..that way you don't even need a comment saying /* 2GB */ ....

Cheers!

>>>>>  ?????? bool control_by_sw;
>>>>>  ?????? bool sw_ddr_en;
>>>>> +???? bool gce_vm;
>>>>> +???? u32 dma_mask_bit;
>>>>>  ?????? u32 gce_num;
>>>>>  ?? };
>>>>>
>>>>> +static inline u32 cmdq_reg_shift_addr(dma_addr_t addr, const
>>>>> struct gce_plat *pdata)
>>>>> +{
>>>>> +???? return ((addr + pdata->mminfra_offset) >> pdata->shift);
>>>>> +}
>>>>> +
>>>>> +static inline u32 cmdq_reg_revert_addr(dma_addr_t addr, const
>>>>> struct gce_plat *pdata)
>>>>> +{
>>>>> +???? return ((addr << pdata->shift) - pdata->mminfra_offset);
>>>>> +}
>>>>
>>>> I'm not sure that you really need those two functions... probably
>>>> it's simply
>>>> cleaner and easier to just write that single line every time...
>>>> and
>>>> I'm
>>>> saying that especially for how you're using those functions, with
>>>> some readl()
>>>> passed directly as param, decreasing human readability by "a
>>>> whole
>>>> lot" :-)
>>>>
>>>
>>> The reason why I use API wrapper instead of writing it directly in
>>> readl() is to avoid missing the shift or mminfra_offset conversion
>>> in
>>> some places.
>>> This problem is not easy to debug, and I have encountered it at
>>> least
>>> twice...
>>>
>>> I think the advantage of using function is that it can be uniformly
>>> modified to all places that need to handle DRAM address conversion.
>>> What do you think? :-)
>>>
>>
>> Eh, if you put it like that... it makes sense, so.. yeah, okay :-)
>>
>> Still, please cleanup those instances of
>>
>> `cmdq_reg_revert_addr(readl(something), pdata)`
>>
>> those might be hard to read, so please just do something like:
>>
>> regval = readl(something);
>> curr_pa = cmdq_revert_addr(regval, pdata);
>>
>> ...reword to your own liking, of course.
>>
> 
> OK, I'll refine that. Thanks.
> 
>>>>> +
>>>>>  ?? static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool
>>>>> enable)
>>>>>  ?? {
>>>>>  ?????? WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq-
>>>>>> clocks));
>>>>> @@ -112,6 +136,30 @@ u8 cmdq_get_shift_pa(struct mbox_chan
>>>>> *chan)
>>>>>  ?? }
>>>>>  ?? EXPORT_SYMBOL(cmdq_get_shift_pa);
>>>>>
>>>>> +dma_addr_t cmdq_get_offset_pa(struct mbox_chan *chan)
>>>>> +{
>>>>> +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
>>>>> mbox);
>>>>> +
>>>>> +???? return cmdq->pdata->mminfra_offset;
>>>>> +}
>>>>> +EXPORT_SYMBOL(cmdq_get_offset_pa);
>>>>
>>>> I think I remember this get_offset_pa from the old times, then CK
>>>> removed it (and I
>>>> was really happy about that disappearing), or am I confusing this
>>>> with something
>>>> else?
>>>>
>>>> (of course, this wasn't used for mminfra, but for something
>>>> else!)
>>>>
>>>
>>> I can't find any remove history in mtk-cmdq-mailbox.c.
>>>
>>> Maybe you mean the patch in this series?
>>> https://lore.kernel.org/all/171213938049.123698.15573779837703602591.b4-ty at collabora.com/
>>>
>>
>> Uhm, I think I may have confused something here, but yes I was
>> remembering the
>> patch series that you pointed out, definitely.
>>
>> At the end, that series is doing something else, so nevermind, was
>> just confusion.
>>
> 
> OK, no problem.
> 
>>>>> +
>>>>> +bool cmdq_addr_need_offset(struct mbox_chan *chan, dma_addr_t
>>>>> addr)
>>>>> +{
>>>>> +???? struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
>>>>> mbox);
>>>>> +
>>>>> +???? if (cmdq->pdata->mminfra_offset == 0)
>>>>> +???????????? return false;
>>>>> +
>>>>> +???? /*
>>>>> +????? * mminfra will recognize the addr that greater than the
>>>>> mminfra_offset
>>>>> +????? * as a transaction to DRAM.
>>>>> +????? * So the caller needs to append mminfra_offset for the
>>>>> true
>>>>> case.
>>>>> +????? */
>>>>> +???? return (addr >= cmdq->pdata->mminfra_offset);
>>>>
>>>>
>>>> /**
>>>>  ?? * cmdq_is_mminfra_gce() - Brief description
>>>>  ?? * @args.....
>>>>  ?? *
>>>>  ?? * The MMINFRA GCE will recognize an address greater than DRAM
>>>> iostart as a
>>>>  ?? * DRAM transaction instead of ....xyz
>>>>  ?? *
>>>>  ?? * In order for callers to perform (xyz) transactions through
>>>> the
>>>> CMDQ, those
>>>>  ?? * need to know if they are using a GCE located in MMINFRA.
>>>>  ?? */
>>>> bool cmdq_is_mminfra_gce(...)
>>>> {
>>>>  ???????? return cmdq->pdata->mminfra_offset &&
>>>>  ??????????????? (addr >= cmdq->pdata->mminfra_offset)
>>>>
>>>>> +}
>>>>> +EXPORT_SYMBOL(cmdq_addr_need_offset);
>>>>> +
>>>>
>>>
>>> OK, I'll modify the API like this.
>>>
>>>> ...but then, is there really no way of just handling the GCE
>>>> being in
>>>> MMINFRA
>>>> transparently from the callers? Do the callers really *need* to
>>>> know
>>>> that they're
>>>> using a new GCE?!
>>>>
>>>
>>> Since the address subtracting is done in MMINFRA hardware, I think
>>> GCE
>>> users really need to handle it in driver.
>>>
>>
>> Since the users of this infrastructure are multimedia related
>> (disp/MDP3),
>> I'd also like to get an opinion from MediaTek engineers familiar with
>> that.
>>
>> CK, Moudy, any opinion on that, please?
>>
>>>> Another way of saying: can't we just handle the address
>>>> translation
>>>> in here instead
>>>> of instructing each and every driver about how to communicate
>>>> with
>>>> the new GCE?!
>>>>
>>>
>>> The DRAM address may not only be the command buffer to GCE, but
>>> also
>>> the working buffer provided by CMDQ users and being a part of GCE
>>> instruction, so we need to handle the address translation in CMDQ
>>> helper driver for the instruction generation.
>>> E.g. ISP drivers may use GCE to write a hardware settings to a DRAM
>>> as
>>> backup buffer. The GCE write instruction will be:
>>> WRITE the value of ISP register to DRAM address + mminfra_offset.
>>>
>>> But most of the CMDQ users only need to use GCE to write hardware
>>> register, so I only keep the translation in cmdq_pkt_mem_move(),
>>> cmdq_pkt_poll_addr() and cmdq_pkt_jump_abs() at the latest series.
>>
>> Yeah you're choosing the best of both worlds in that case, I do
>> agree, but
>> still - if there's a way to avoid drivers to have different handling
>> for
>> mminfra vs no-mminfra, that'd still be preferred.
>>
>> Having the handling for something *centralized* somewhere, instead of
>> it
>> being sparse here and there, would make maintenance way easier...
>>
>> ...and that's why I'm asking for CK and Moudy's opinion, nothing else
>> :-)
>>
> 
> Yes, I totally agree with you. Thanks for the asking!
> 
> Regards,
> Jason-JH.Lin
> 
>> Cheers!
>> Angelo
>>
> 





From amadeus at jmu.edu.cn  Thu Mar  6 05:10:15 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 21:10:15 +0800
Subject: [PATCH 0/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
Message-ID: <20250306131016.281290-1-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of standard ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

dmesg:
[    0.061333] scmi_core: SCMI protocol bus registered
[    0.125780] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
[    0.126628] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
[    0.127233] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0

CPU frequency: ~# mhz
count=611657 us50=19994 us250=99945 diff=79951 cpu_MHz=1530.080

Chukun Pan (1):
  arm64: dts: rockchip: enable SCMI clk for RK3528 SoC

 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 32 ++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

-- 
2.25.1



From amadeus at jmu.edu.cn  Thu Mar  6 05:10:16 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 21:10:16 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306131016.281290-1-amadeus@jmu.edu.cn>
References: <20250306131016.281290-1-amadeus@jmu.edu.cn>
Message-ID: <20250306131016.281290-2-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 32 ++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 0c0e7f151462..aa68c2fef2f3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -59,6 +59,7 @@ cpu0: cpu at 0 {
 			reg = <0x0>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu1: cpu at 1 {
@@ -66,6 +67,7 @@ cpu1: cpu at 1 {
 			reg = <0x1>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu2: cpu at 2 {
@@ -73,6 +75,7 @@ cpu2: cpu at 2 {
 			reg = <0x2>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu3: cpu at 3 {
@@ -80,6 +83,22 @@ cpu3: cpu at 3 {
 			reg = <0x3>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
+		};
+	};
+
+	firmware {
+		scmi: scmi {
+			compatible = "arm,scmi-smc";
+			arm,smc-id = <0x82000010>;
+			shmem = <&scmi_shmem>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_clk: protocol at 14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
 		};
 	};
 
@@ -110,6 +129,19 @@ gmac0_clk: clock-gmac50m {
 		#clock-cells = <0>;
 	};
 
+	sram at 10f000 {
+		compatible = "mmio-sram";
+		reg = <0x0 0x0010f000 0x0 0x100>;
+		ranges = <0 0x0 0x0010f000 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		scmi_shmem: sram at 0 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x100>;
+		};
+	};
+
 	soc {
 		compatible = "simple-bus";
 		ranges = <0x0 0xfe000000 0x0 0xfe000000 0x0 0x2000000>;
-- 
2.25.1



From nicolas.frattaroli at collabora.com  Thu Mar  6 05:13:18 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Thu, 06 Mar 2025 14:13:18 +0100
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI controllers
In-Reply-To: <ffd6287c-cbfd-4ba8-9332-45bad4e60583@kernel.org>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
 <ffd6287c-cbfd-4ba8-9332-45bad4e60583@kernel.org>
Message-ID: <2376575.ElGaqSPkdT@workhorse>

On Thursday, 6 March 2025 08:42:54 Central European Standard Time Krzysztof 
Kozlowski wrote:
> On 05/03/2025 22:24, Nicolas Frattaroli wrote:
> > Rockchip introduced a new audio controller called the "Serial Audio
> > Interface", or "SAI" for short, on some of their newer SoCs. In
> > particular, this controller is used several times on the RK3576 SoC.
> > 
> > Add a schema for it, with only an RK3576 compatible for now. Other SoCs
> > may follow as mainline support for them lands.
> > 
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> > ---
> > 
> >  .../devicetree/bindings/sound/rockchip,sai.yaml    | 151
> >  +++++++++++++++++++++
> Filename based on compatible.

Sure, but more compatibles will follow. Are you certain you want a file named 
rockchip,rk3576-sai.yaml to then contain rockchip,rk3528-sai? If so then I do 
not understand the reason behind this policy.

> 
> >  MAINTAINERS                                        |   6 +
> >  2 files changed, 157 insertions(+)
> 
> ...
> 
> > +
> > +  dma-names:
> > +    minItems: 1
> > +    maxItems: 2
> > +    oneOf:
> > +      - const: tx
> > +      - const: rx
> > +      - items:
> > +          - const: tx
> > +          - const: rx
> 
> Why all combinations are possible?

Because they are. sai5 in rk3576 is rx only. sai7 is tx only. Others are both 
tx and rx. Do you want me to enforce that those with both are always tx 
followed by rx?

> 
> > +
> > +  clocks:
> > +    items:
> > +      - description: master audio clock
> > +      - description: AHB clock driving the interface
> > +
> > +  clock-names:
> > +    items:
> > +      - const: mclk
> > +      - const: hclk
> > +
> > +  resets:
> > +    minItems: 1
> > +    maxItems: 2
> > +    description: resets for the mclk domain and ahb domain
> 
> List the items instead with description and minItems: 1.

Will do

> 
> > +
> > +  reset-names:
> > +    minItems: 1
> > +    items:
> > +      - const: m
> > +      - const: h
> > +
> > +  port:
> > +    $ref: audio-graph-port.yaml#
> > +    unevaluatedProperties: false
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +  "#sound-dai-cells":
> > +    const: 0
> > +
> > +  rockchip,sai-rx-route:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    description:
> > +      Defines the mapping of the controller's SDI ports to actual input
> > lanes, +      as well as the number of input lanes.
> > +      rockchip,sai-rx-route = <3> would mean sdi3 is receiving from
> > data0, and +      that there is only one receiving lane.
> > +      This property's absence is to be understood as only one receiving
> > lane +      being used if the controller has capture capabilities.
> > +    maxItems: 4
> > +    items:
> > +      enum: [0, 1, 2, 3]
> > +
> > +  rockchip,sai-tx-route:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    description:
> > +      Defines the mapping of the controller's SDO ports to actual output
> > lanes, +      as well as the number of output lanes.
> > +      rockchip,sai-tx-route = <3> would mean sdo3 is sending to data0,
> > and
> 
> I understand this is only example because = <3> would not be allowed
> (test it).

I'll have to look into that, I was fairly certain I tested it, but maybe I 
forgot to run a CHECK_DTBS with it in.

> 
> > +      that there is only one transmitting lane.
> > +      This property's absence is to be understood as only one
> > transmitting lane +      being used if the controller has playback
> > capabilities.
> > +    maxItems: 4
> > +    items:
> > +      enum: [0, 1, 2, 3]
> > +
> > +  rockchip,always-on:
> > +    type: boolean
> > +    description:
> > +      The hardware requires this controller to remain turned on.
> 
> How hardware requires this? You rather miss proper PM domain handling or
> some other resources.

This isn't about power domains. It's about the FS/SCLK generator inside the 
IP. I'll remove it in the next revision since downstream only uses it for a 
different IP on the RK3588, and I'd rather not get bogged down by discussions 
as to whether SAI should be modelled as a clock provider.

> 
> > +
> > +
> 
> Just one blank line.

Will do

> 
> > +required:
> > +  - compatible
> > +  - reg
> > +  - dmas
> > +  - dma-names
> > +  - clocks
> > +  - clock-names
> > +  - "#sound-dai-cells"
> > +
> > +unevaluatedProperties: false
> 
> Best regards,
> Krzysztof

Cheers,
Nicolas Frattaroli





From nicolas.frattaroli at collabora.com  Thu Mar  6 05:23:46 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Thu, 06 Mar 2025 14:23:46 +0100
Subject: [PATCH 4/7] ASoC: rockchip: add Serial Audio Interface (SAI) driver
In-Reply-To: <20e4754b-ea9a-404d-b529-ec44a7263cbf@kernel.org>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-4-64e6cf863e9a@collabora.com>
 <20e4754b-ea9a-404d-b529-ec44a7263cbf@kernel.org>
Message-ID: <13731095.uLZWGnKmhe@workhorse>

On Thursday, 6 March 2025 08:37:54 Central European Standard Time Krzysztof 
Kozlowski wrote:
> On 05/03/2025 22:24, Nicolas Frattaroli wrote:
> ...
> 
> > +
> > +static int rockchip_sai_runtime_resume(struct device *dev)
> > +{
> > +	struct rk_sai_dev *sai = dev_get_drvdata(dev);
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	dev_dbg(dev, "Runtime resuming device!\n");
> 
> Drop probe entry/exit messages. Core already gives you tracing for this.

Will do.

> 
> > +
> > +	ret = clk_prepare_enable(sai->hclk);
> > +	if (ret)
> > +		goto err_hclk;
> > +
> > +	ret = clk_prepare_enable(sai->mclk);
> > +	if (ret)
> > +		goto err_mclk;
> > +
> > +	regcache_cache_only(sai->regmap, false);
> > +	regcache_mark_dirty(sai->regmap);
> > +	ret = regcache_sync(sai->regmap);
> > +	if (ret)
> > +		goto err_regmap;
> > +
> > +	if (sai->quirks & QUIRK_ALWAYS_ON && sai->is_master_mode) {
> > +		spin_lock_irqsave(&sai->xfer_lock, flags);
> > +		regmap_update_bits(sai->regmap, SAI_XFER,
> > +				   SAI_XFER_CLK_MASK |
> > +				   SAI_XFER_FSS_MASK,
> > +				   SAI_XFER_CLK_EN |
> > +				   SAI_XFER_FSS_EN);
> > +		spin_unlock_irqrestore(&sai->xfer_lock, flags);
> > +	}
> > +
> 
> ...
> 
> > +
> > +	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "Failed to register PCM: %d\n", ret);
> > +		goto err_runtime_suspend;
> > +	}
> > +
> > +	ret = devm_snd_soc_register_component(&pdev->dev,
> > +					      
&rockchip_sai_component,
> > +					      dai, 1);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "Failed to register component: %d\n", 
ret);
> > +		goto err_runtime_suspend;
> > +	}
> > +
> > +	pm_runtime_use_autosuspend(&pdev->dev);
> > +	pm_runtime_put(&pdev->dev);
> > +
> > +	/*
> > +	 * runtime_resume already enabled our hclk again, so we need to also
> > +	 * get rid of the manual enable we did earlier to balance the 
counts.
> > +	 */
> 
> Your way of handling this is extra confusing. You rely on some other
> methods to poke the enable/disable count. It is rather expected that
> each function handles this fully, so it disables what it have enabled.
> You must not rely on PM runtime to do something with clocks which you
> now unwind.

I believe you misunderstand. I'm not unwinding what PM is doing. I'm unwinding 
the hclk enable the probe function does earlier on. I will make the comment 
more clear in V2 (or rather, remove it entirely since it creates more 
confusion than it clears up). It's unnecessary to talk about PM runtime also 
enabling hclk; the disable is for our function's enable.

> 
> > +	clk_disable_unprepare(sai->hclk);
> > +
> > +	return 0;
> > +
> > +err_runtime_suspend:
> > +	/* If we're !CONFIG_PM, we get -ENOSYS and disable manually */
> > +	if (pm_runtime_put(&pdev->dev))
> > +		rockchip_sai_runtime_suspend(&pdev->dev);
> > +err_disable_hclk:
> > +	clk_disable_unprepare(sai->hclk);
> > +
> > +	return ret;
> > +}
> > +
> 
> _device_id tables are supposed to be around probe, not beginning of the
> file.

Will do.

> 
> > +static void rockchip_sai_remove(struct platform_device *pdev)
> > +{
> > +#ifndef CONFIG_PM
> > +	rockchip_sai_runtime_suspend(&pdev->dev);> +#endif
> > +}
> > +
> > +static const struct dev_pm_ops rockchip_sai_pm_ops = {
> > +	SET_RUNTIME_PM_OPS(rockchip_sai_runtime_suspend,
> > rockchip_sai_runtime_resume, NULL)
> > +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> > pm_runtime_force_resume) +};
> > +
> > +static struct platform_driver rockchip_sai_driver = {
> > +	.probe = rockchip_sai_probe,
> > +	.remove = rockchip_sai_remove,
> > +	.driver = {
> > +		.name = DRV_NAME,
> > +		.of_match_table = of_match_ptr(rockchip_sai_match),
> 
> Drop of_match_ptr, you have warning here.

Will do.

> 
> > +		.pm = &rockchip_sai_pm_ops,
> > +	},
> > +};
> > +module_platform_driver(rockchip_sai_driver);
> > +
> > +MODULE_DESCRIPTION("Rockchip SAI ASoC Interface");
> > +MODULE_AUTHOR("Sugar Zhang <sugar.zhang at rock-chips.com>");
> > +MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli at collabora.com>");
> > +MODULE_LICENSE("GPL");
> > +MODULE_ALIAS("platform:" DRV_NAME);
> 
> You should not need MODULE_ALIAS() in normal cases. If you need it,
> usually it means your device ID table is wrong (e.g. misses either
> entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute
> for incomplete ID table.

Will do.

> 
> > +MODULE_DEVICE_TABLE(of, rockchip_sai_match);
> 
> Best regards,
> Krzysztof

Regards,
Nicolas Frattaroli





From aliceryhl at google.com  Thu Mar  6 05:25:25 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Thu, 6 Mar 2025 13:25:25 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8maCX5QJRqODl6u@pluto>
References: <Z8g8vhS9rqQ_ez48@google.com> <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com> <Z8maCX5QJRqODl6u@pluto>
Message-ID: <Z8miRewURwdvU36h@google.com>

On Thu, Mar 06, 2025 at 12:50:17PM +0000, Cristian Marussi wrote:
> On Thu, Mar 06, 2025 at 11:09:33AM +0000, Alice Ryhl wrote:
> > On Wed, Mar 05, 2025 at 05:10:16PM +0000, Cristian Marussi wrote:
> > > On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> > > > Dear SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message
> > > > Protocol drivers maintainers,
> > > > 
> > > > I flashed a v6.13-rc3 kernel onto a Rock5B board and noticed the
> > > > following output in my terminal:
> > > > 
> > > > [  687.694465] kmemleak: 4 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
> > > > 
> > > > It seems that there is a memory leak for devices created with
> > > > scmi_device_create.
> > > > 
> > > `
> > > Hi Alice,
> > > 
> > > thanks for this report.
> > > 
> > > > This was with a kernel running v6.13-rc3, but as far as I can tell, no
> > > > relevant changes have landed since v6.13-rc3. My tree *does* include
> > > > commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> > > > scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> > > > not happening consistently.
> > > > 
> > > > See below for the full kmemleak report.
> > > > 
> > > > Alice
> > > > 
> > > > $ sudo cat /sys/kernel/debug/kmemleak
> > > > unreferenced object 0xffffff8106c86000 (size 2048):
> > > >   comm "swapper/0", pid 1, jiffies 4294893094
> > > >   hex dump (first 32 bytes):
> > > >     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
> > > >     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
> > > >   backtrace (crc feae9680):
> > > >     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
> > > >     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
> > > >     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
> > > >     [<000000008714917b>] scmi_device_create+0x40/0x194
> > > >     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
> > > >     [<00000000970bad38>] scmi_probe+0x584/0xa78
> > > >     [<000000002600d2fd>] platform_probe+0xbc/0xf0
> > > >     [<00000000f6f556b4>] really_probe+0x1b8/0x520
> > > >     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
> > > >     [<00000000d613b754>] driver_probe_device+0x6c/0x208
> > > >     [<00000000187a9170>] __driver_attach+0x168/0x328
> > > >     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
> > > >     [<00000000984a3176>] driver_attach+0x34/0x44
> > > >     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
> > > >     [<00000000747fce19>] driver_register+0xc0/0x1a0
> > > >     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> > > > unreferenced object 0xffffff8103bc01c0 (size 32):
> > > 
> > > I could not reproduce on my setup, even though I run a system with
> > > all the existent SCMI protocols (and related drivers) enabled (and
> > > so a lot of device creations) and a downstream test driver that causes
> > > even more SCMI devices to be created/destroyed at load/unload.
> > > 
> > > Coming down the path from scmi_chan_setup(), it seems something around
> > > transport devices creation, but it is not obvious to me where the leak
> > > could hide....
> > > 
> > > ...any particular setup on your side ? ...using LKMs, loading/unloading,
> > > any usage pattern that could help me reproduce ?
> > 
> > I looked into this a bit more, and actually it does happen consistently.
> > It's just that kmemleak doesn't report it until 10 minutes after
> > booting, so I did not notice it.
> > 
> > As for my setup, well, I boot the kernel over pxe and the rootfs is
> > mounted over NFSv4. The memory leak happens even if I don't do anything
> > at all - I just boot and wait. The device is a Radxa Rock5B.
> > 
> > Not sure what other information there is to give.
> > 
> 
> My question as stated above was mainly to understand if the SCMI stack
> was built-in or compiled as loadable modules (lsmod|grep -i scmi)...
> ...I am just to try to pin down a possible 'more-vulnerable' configuration..
> ..I could not see any report even triggering a kmemleak scan on v6.14-rc5
> BUT I only tested with a fully built-in SCMI stack indeed as of now...so
> the question.
> 
> > I tried again with v6.14-rc5, and I still got the leak:
> 
> Ok...thanks I will investigate with different configs.

Here is the config I used:
https://gist.github.com/Darksonn/ecd31a0512f43f7e74a30ab83ff2196f

Alice


From maxime.chevallier at bootlin.com  Thu Mar  6 05:26:20 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 6 Mar 2025 14:26:20 +0100
Subject: [PATCH net-next v4 09/13] net: phylink: Use phy_caps_lookup for
 fixed-link configuration
In-Reply-To: <Z8maRNYsn1LzjryX@shell.armlinux.org.uk>
References: <20250303090321.805785-1-maxime.chevallier@bootlin.com>
	<20250303090321.805785-10-maxime.chevallier@bootlin.com>
	<350bb4f6-f4b5-44c3-a821-ac53c8641705@redhat.com>
	<20250306111220.28798e6b@fedora.home>
	<Z8maRNYsn1LzjryX@shell.armlinux.org.uk>
Message-ID: <20250306142620.002d8b8a@fedora.home>

On Thu, 6 Mar 2025 12:51:16 +0000
"Russell King (Oracle)" <linux at armlinux.org.uk> wrote:

> On Thu, Mar 06, 2025 at 11:12:20AM +0100, Maxime Chevallier wrote:
> > On Thu, 6 Mar 2025 09:56:32 +0100
> > Paolo Abeni <pabeni at redhat.com> wrote:
> >   
> > > On 3/3/25 10:03 AM, Maxime Chevallier wrote:  
> > > > @@ -879,8 +880,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
> > > >  	linkmode_copy(pl->link_config.advertising, pl->supported);
> > > >  	phylink_validate(pl, pl->supported, &pl->link_config);
> > > >  
> > > > -	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
> > > > -			       pl->supported, true);
> > > > +	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
> > > > +			    pl->supported, true);
> > > > +	if (c)
> > > > +		linkmode_and(match, pl->supported, c->linkmodes);    
> > > 
> > > How about using only the first bit from `c->linkmodes`, to avoid
> > > behavior changes?  
> > 
> > If what we want is to keep the exact same behaviour, then we need to
> > go one step further and make sure we keep the same one as before, and
> > it's not guaranteed that the first bit in c->linkmodes is this one.
> > 
> > We could however have a default supported mask for fixed-link in phylink
> > that contains all the linkmodes we allow for fixed links, then filter
> > with the lookup, something like :
> > 
> > 
> > -       linkmode_fill(pl->supported);
> > +       /* (in a dedicated helper) Linkmodes reported for fixed links below
> > +        * 10G */
> > +       linkmode_zero(pl->supported);
> > +
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, pl->supported);
> > +       linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, pl->supported);  
> 
> Good idea, but do we have some way to automatically generate the baseT
> link modes?

I think we could with some of the preliminary phy_port patches I had
sent before going into that phy_caps series :

https://lore.kernel.org/netdev/20250213101606.1154014-2-maxime.chevallier at bootlin.com/

It adds the information about medium, maybe we could adapt that, making
sure we filter out BaseT1 for example, but that would be a generic way
of generating that list indeed.

I don't necessarily mean to add this "mediums" thing into this series
right now, we could for now set that list of all BaseT modes in an
internal helper, then later on convert it to the mediums-based
linkmodes listing. I'll go back to phy_ports after phy_caps :)

Thanks,

Maxime



From heiko at sntech.de  Thu Mar  6 05:29:48 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Thu, 06 Mar 2025 14:29:48 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306131016.281290-2-amadeus@jmu.edu.cn>
References: <20250306131016.281290-1-amadeus@jmu.edu.cn>
 <20250306131016.281290-2-amadeus@jmu.edu.cn>
Message-ID: <4856313.kQq0lBPeGt@diego>

Hi,

Am Donnerstag, 6. M?rz 2025, 14:10:16 MEZ schrieb Chukun Pan:
> Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
> Add SCMI clk for CPU, GPU and RNG will also use it.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---

> @@ -110,6 +129,19 @@ gmac0_clk: clock-gmac50m {
>  		#clock-cells = <0>;
>  	};
>  
> +	sram at 10f000 {

That sram is part of the soc (and has an mmio-address), so I'd think
it should live inside the soc node?


Heiko




From heiko at sntech.de  Thu Mar  6 05:09:23 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu,  6 Mar 2025 14:09:23 +0100
Subject: [PATCH] arm64: dts: rockchip: Enable hdmi out display for rk3576-evb-v10
In-Reply-To: <20250305025128.479245-1-andyshrk@163.com>
References: <20250305025128.479245-1-andyshrk@163.com>
Message-ID: <174126656184.656541.9194102170806137461.b4-ty@sntech.de>


On Wed, 05 Mar 2025 10:51:11 +0800, Andy Yan wrote:
> Enable vop and hdmi on rk3576 evb1, so we can get a display output
> on this board now.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Enable hdmi out display for rk3576-evb-v10
      commit: 7641678ecb0c242498e2a3b2b0621961653a7c2c

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Thu Mar  6 05:09:25 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu,  6 Mar 2025 14:09:25 +0100
Subject: [PATCH v2] arm64: defconfig: Enable Rockchip UFS host driver
In-Reply-To: <1741161252-138526-1-git-send-email-shawn.lin@rock-chips.com>
References: <1741161252-138526-1-git-send-email-shawn.lin@rock-chips.com>
Message-ID: <174126656182.656541.13105092745592307525.b4-ty@sntech.de>


On Wed, 05 Mar 2025 15:54:12 +0800, Shawn Lin wrote:
> Enable Rockchip UFS host driver.
> 
> This driver is first introduced on Rockchip RK3576 SoC, and will
> be used for more SoCs in near future, so add it to defconfig
> will make these platforms work better.
> 
> 
> [...]

Applied, thanks!

[1/1] arm64: defconfig: Enable Rockchip UFS host driver
      commit: 769c2b450b89b6a71ed614b7c507d17a84f52a4e

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From mripard at kernel.org  Thu Mar  6 05:35:19 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Thu, 6 Mar 2025 14:35:19 +0100
Subject: [PATCH v4 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <155f609f-994f-4140-8453-7e38a5e6deef@collabora.com>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>
 <20250304-small-mindful-mongrel-bd6f8b@houat>
 <155f609f-994f-4140-8453-7e38a5e6deef@collabora.com>
Message-ID: <20250306-masked-voracious-octopus-be05b8@houat>

On Tue, Mar 04, 2025 at 02:04:18PM +0200, Cristian Ciocaltea wrote:
> Hi Maxime,
> 
> On 3/4/25 10:13 AM, Maxime Ripard wrote:
> > Hi,
> > 
> > On Tue, Mar 04, 2025 at 03:44:02AM +0200, Cristian Ciocaltea wrote:
> >> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
> >> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
> >> and not before.
> >>
> >> While at it, introduce a define for this rate limit constant.
> >>
> >> Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
> >> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> >> ---
> >>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
> >>  1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
> >> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> @@ -320,6 +320,7 @@
> >>  #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
> >>  #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
> >>  
> >> +#define HDMI14_MAX_RATE			340000000
> >>  #define HDMI20_MAX_RATE			600000000
> >>  
> >>  enum dp_link_rate {
> >> @@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
> >>  
> >>  	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
> >>  
> >> -	if (rate >= 3400000) {
> >> +	if (rate > HDMI14_MAX_RATE / 100) {
> > 
> > The rate seems to come from rk_hdptx_phy_power_on and eventually from
> > tmds_char_rate in the PHY config options, so its rate is in Hertz.
> 
> The rate coming from rk_hdptx_phy_power_on() is in hHz, since it passed
> via dw_hdmi_qp_rockchip_encoder_enable() as
> 
>   phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
> 
> > HDMI14_MAX_RATE and HDMI20_MAX_RATE are both defined in Hertz as well.
> > It seems super odd to mee that you then convert HDMI14_MAX_RATE to hHz?
> 
> This stems from the ropll_tmds_cfg table containing the configuration
> params for the supported rates which requires the search keys to be
> provided in hHz rather than Hz.
> 
> I agree this is nothing but confusing, that's why I fixed this up in
> "phy: rockchip: samsung-hdptx: Avoid Hz-hHz unit conversion overhead"

Yeah, sorry, I noticed it after sending the review. Still, I'd advise to
put that patch first, it's a bit weird to add more patch we're going to
rework later on.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/015a32b1/attachment.sig>

From heiko at sntech.de  Thu Mar  6 05:36:26 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu,  6 Mar 2025 14:36:26 +0100
Subject: (subset) [PATCH v2 0/8] Support SD/SDIO controllers on RK3528
In-Reply-To: <20250305194217.47052-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
Message-ID: <174126816885.664640.17521271236710485903.b4-ty@sntech.de>


On Wed, 05 Mar 2025 19:42:09 +0000, Yao Zi wrote:
> RK3528 features two SDIO controllers and one SD/MMC controller. This
> series adds essential support for their tuning clocks, document the
> controller in dt-bindings and bring the SD/MMC one up on Radxa E20C
> board. Both HS and SDR104 mode are verified.
> 
> This is based on v2 of the SARADC series[1]
> 
> [...]

Applied, thanks!

[1/8] dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
      commit: efc1bc1f36568a4297d20a691758b68c121cf982
[2/8] dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
      commit: 8f814d7c9f6cdffc1f5cc97637e12cd699ff9085

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From csokas.bence at prolan.hu  Thu Mar  6 05:44:36 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Thu, 6 Mar 2025 14:44:36 +0100
Subject: [PATCH v8 1/2] counter: microchip-tcb-capture: Add IRQ handling
In-Reply-To: <20250306134441.582819-1-csokas.bence@prolan.hu>
References: <20250306134441.582819-1-csokas.bence@prolan.hu>
Message-ID: <20250306134441.582819-2-csokas.bence@prolan.hu>

Add interrupt servicing to allow userspace to wait for the following:
* Change-of-state caused by external trigger
* Capture of timer value into RA/RB
* Compare to RC register
* Overflow

Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    New in v2
    Changes in v3:
    * Add IRQs for Capture events (from next patch)
    * Add IRQ for RC Compare
    * Add events as bullet points to commit msg
    Changes in v4:
    * Add uapi header, names for the event channels
    * Add check for -EPROBE_DEFER from `of_irq_get()`
    Changes in v5:
    * Split out UAPI header introduction
    Changes in v7:
    * Revert split-out
    * Drop `enum counter_mchp_signals` from UAPI
    * Change enums to #define's in UAPI header
    Changes in v8:
    * Remove `priv->irq` and replace with function arg

 MAINTAINERS                                   |  1 +
 drivers/counter/microchip-tcb-capture.c       | 74 +++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     | 34 +++++++++
 3 files changed, 109 insertions(+)
 create mode 100644 include/uapi/linux/counter/microchip-tcb-capture.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e047e20fbd8..d1d264210690 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15579,6 +15579,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-iio at vger.kernel.org
 S:	Maintained
 F:	drivers/counter/microchip-tcb-capture.c
+F:	include/uapi/linux/counter/microchip-tcb-capture.h
 
 MICROCHIP USB251XB DRIVER
 M:	Richard Leitner <richard.leitner at skidata.com>
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 2f096a5b973d..16707099bd69 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -6,18 +6,24 @@
  */
 #include <linux/clk.h>
 #include <linux/counter.h>
+#include <linux/interrupt.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <uapi/linux/counter/microchip-tcb-capture.h>
 #include <soc/at91/atmel_tcb.h>
 
 #define ATMEL_TC_CMR_MASK	(ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
 				 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
 				 ATMEL_TC_LDBSTOP)
 
+#define ATMEL_TC_DEF_IRQS	(ATMEL_TC_ETRGS | ATMEL_TC_COVFS | \
+				 ATMEL_TC_LDRAS | ATMEL_TC_LDRBS | ATMEL_TC_CPCS)
+
 #define ATMEL_TC_QDEN			BIT(8)
 #define ATMEL_TC_POSEN			BIT(9)
 
@@ -294,6 +300,65 @@ static const struct of_device_id atmel_tc_of_match[] = {
 	{ /* sentinel */ }
 };
 
+static irqreturn_t mchp_tc_isr(int irq, void *dev_id)
+{
+	struct counter_device *const counter = dev_id;
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	u32 sr, mask;
+
+	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
+	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], IMR), &mask);
+
+	sr &= mask;
+	if (!(sr & ATMEL_TC_ALL_IRQ))
+		return IRQ_NONE;
+
+	if (sr & ATMEL_TC_ETRGS)
+		counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE,
+				   COUNTER_MCHP_EVCHN_CV);
+	if (sr & ATMEL_TC_LDRAS)
+		counter_push_event(counter, COUNTER_EVENT_CAPTURE,
+				   COUNTER_MCHP_EVCHN_RA);
+	if (sr & ATMEL_TC_LDRBS)
+		counter_push_event(counter, COUNTER_EVENT_CAPTURE,
+				   COUNTER_MCHP_EVCHN_RB);
+	if (sr & ATMEL_TC_CPCS)
+		counter_push_event(counter, COUNTER_EVENT_THRESHOLD,
+				   COUNTER_MCHP_EVCHN_RC);
+	if (sr & ATMEL_TC_COVFS)
+		counter_push_event(counter, COUNTER_EVENT_OVERFLOW,
+				   COUNTER_MCHP_EVCHN_CV);
+
+	return IRQ_HANDLED;
+}
+
+static void mchp_tc_irq_remove(void *ptr)
+{
+	struct mchp_tc_data *priv = ptr;
+
+	regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IDR), ATMEL_TC_DEF_IRQS);
+}
+
+static int mchp_tc_irq_enable(struct counter_device *const counter, int irq)
+{
+	struct mchp_tc_data *const priv = counter_priv(counter);
+	int ret = devm_request_irq(counter->parent, irq, mchp_tc_isr, 0,
+				   dev_name(counter->parent), counter);
+
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IER), ATMEL_TC_DEF_IRQS);
+	if (ret < 0)
+		return ret;
+
+	ret = devm_add_action_or_reset(counter->parent, mchp_tc_irq_remove, priv);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static void mchp_tc_clk_remove(void *ptr)
 {
 	clk_disable_unprepare((struct clk *)ptr);
@@ -378,6 +443,15 @@ static int mchp_tc_probe(struct platform_device *pdev)
 	counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals);
 	counter->signals = mchp_tc_count_signals;
 
+	i = of_irq_get(np->parent, 0);
+	if (i == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (i > 0) {
+		ret = mchp_tc_irq_enable(counter, i);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret, "Failed to set up IRQ");
+	}
+
 	ret = devm_counter_add(&pdev->dev, counter);
 	if (ret < 0)
 		return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n");
diff --git a/include/uapi/linux/counter/microchip-tcb-capture.h b/include/uapi/linux/counter/microchip-tcb-capture.h
new file mode 100644
index 000000000000..f3ef315fe9f6
--- /dev/null
+++ b/include/uapi/linux/counter/microchip-tcb-capture.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Channel numbers used by the microchip-tcb-capture driver
+ * Copyright (C) 2025 Bence Cs?k?s
+ */
+#ifndef _UAPI_COUNTER_MCHP_TCB_H_
+#define _UAPI_COUNTER_MCHP_TCB_H_
+
+/*
+ * The driver defines the following components:
+ *
+ * Count 0
+ * \__  Synapse 0 -- Signal 0 (Channel A, i.e. TIOA)
+ * \__  Synapse 1 -- Signal 1 (Channel B, i.e. TIOB)
+ *
+ * It also supports the following events:
+ *
+ * Channel 0:
+ * - CV register changed
+ * - CV overflowed
+ * - RA captured
+ * Channel 1:
+ * - RB captured
+ * Channel 2:
+ * - RC compare triggered
+ */
+
+/* Event channels */
+#define COUNTER_MCHP_EVCHN_CV 0
+#define COUNTER_MCHP_EVCHN_RA 0
+#define COUNTER_MCHP_EVCHN_RB 1
+#define COUNTER_MCHP_EVCHN_RC 2
+
+#endif /* _UAPI_COUNTER_MCHP_TCB_H_ */
-- 
2.48.1




From csokas.bence at prolan.hu  Thu Mar  6 05:44:35 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Thu, 6 Mar 2025 14:44:35 +0100
Subject: [PATCH v8 0/2] microchip-tcb-capture: Add Capture, Compare, Overflow etc. events
Message-ID: <20250306134441.582819-1-csokas.bence@prolan.hu>

The TCB has three R/W-able "general purpose" hardware registers:
RA, RB and RC. The hardware is capable of:
* sampling Counter Value Register (CV) to RA/RB on a trigger edge
* sending an interrupt of this change
* sending an interrupt on CV change due to trigger
* triggering an interrupt on CV compare to RC
* stop counting after sampling to RB

To enable using these features in user-space, an interrupt handler
was added, generating the necessary counter events. On top, RA/RB
registers are added as Count Extensions. To aid interoperation, a
uapi header was also added, containing the various numeral IDs of
the Extensions, Event channels etc.

Bence Cs?k?s (2):
  counter: microchip-tcb-capture: Add IRQ handling
  counter: microchip-tcb-capture: Add capture extensions for registers
    RA/RB

 MAINTAINERS                                   |   1 +
 drivers/counter/microchip-tcb-capture.c       | 132 ++++++++++++++++++
 .../linux/counter/microchip-tcb-capture.h     |  40 ++++++
 3 files changed, 173 insertions(+)
 create mode 100644 include/uapi/linux/counter/microchip-tcb-capture.h

-- 
2.48.1




From krzk at kernel.org  Thu Mar  6 05:54:04 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 14:54:04 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <7020561.MhkbZ0Pkbq@diego>
References: <4856313.kQq0lBPeGt@diego>
 <20250306134002.380690-1-amadeus@jmu.edu.cn> <7020561.MhkbZ0Pkbq@diego>
Message-ID: <b57e0930-c9a3-4c44-a740-a5623d6904ba@kernel.org>

On 06/03/2025 14:51, Heiko St?bner wrote:
> Am Donnerstag, 6. M?rz 2025, 14:40:02 MEZ schrieb Chukun Pan:
>> Hi,
>>
>>> That sram is part of the soc (and has an mmio-address), so I'd think
>>> it should live inside the soc node?
>>
>> But soc ranges starts from 0xfe000000, I don't know whether to change it.
>> And all other nodes are 0xf..., except this sram.
>> Any suggestions would be greatly appreciated.
> 
> darn ... I didn't realize that this is not sram, but main memory :-)


Heh, I think carving out reserved blocks from the main RAM and calling
it a SRAM is a stretch.

Best regards,
Krzysztof


From heiko at sntech.de  Thu Mar  6 05:57:00 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Thu, 06 Mar 2025 14:57:00 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <b57e0930-c9a3-4c44-a740-a5623d6904ba@kernel.org>
References: <4856313.kQq0lBPeGt@diego> <7020561.MhkbZ0Pkbq@diego>
 <b57e0930-c9a3-4c44-a740-a5623d6904ba@kernel.org>
Message-ID: <3008437.usQuhbGJ8B@diego>

Am Donnerstag, 6. M?rz 2025, 14:54:04 MEZ schrieb Krzysztof Kozlowski:
> On 06/03/2025 14:51, Heiko St?bner wrote:
> > Am Donnerstag, 6. M?rz 2025, 14:40:02 MEZ schrieb Chukun Pan:
> >> Hi,
> >>
> >>> That sram is part of the soc (and has an mmio-address), so I'd think
> >>> it should live inside the soc node?
> >>
> >> But soc ranges starts from 0xfe000000, I don't know whether to change it.
> >> And all other nodes are 0xf..., except this sram.
> >> Any suggestions would be greatly appreciated.
> > 
> > darn ... I didn't realize that this is not sram, but main memory :-)
> 
> 
> Heh, I think carving out reserved blocks from the main RAM and calling
> it a SRAM is a stretch.

yep, hence going with the reserved memory instead
and not trying to call it sram :-)

And I just saw rk3576 has the same issue, only that there
the mmio area is sitting before the main memory address space




From heiko at sntech.de  Thu Mar  6 05:45:45 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu,  6 Mar 2025 14:45:45 +0100
Subject: [PATCH v5 1/2] dt-bindings: arm: rockchip: Add MNT Reform 2 (RCORE)
In-Reply-To: <Z8S5SHqUqKYiT6Wd@windev.fritz.box>
References: <Z8S5SHqUqKYiT6Wd@windev.fritz.box>
Message-ID: <174126874161.670332.12638948694058332407.b4-ty@sntech.de>


On Sun, 02 Mar 2025 21:02:16 +0100, Patrick Wildt wrote:
> Document board compatible bindings for the MNT Reform 2 with it's RCORE
> SoM, which is based on Firefly's iCore-3588Q.
> 
> 

Applied, thanks!

[1/2] dt-bindings: arm: rockchip: Add MNT Reform 2 (RCORE)
      commit: 3bf4fc44c6544f994237d8475bf56548a62011f5
[2/2] arm64: dts: rockchip: add MNT Reform 2
      commit: 5324af2d029d47a39ce22ae1613e2753e5e372a2

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From krzk at kernel.org  Thu Mar  6 05:45:49 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 14:45:49 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306134002.380690-1-amadeus@jmu.edu.cn>
References: <4856313.kQq0lBPeGt@diego>
 <20250306134002.380690-1-amadeus@jmu.edu.cn>
Message-ID: <10115c0f-4a7f-460a-a0bd-0c86d1e7d3b6@kernel.org>

On 06/03/2025 14:40, Chukun Pan wrote:
> Hi,
> 
>> That sram is part of the soc (and has an mmio-address), so I'd think
>> it should live inside the soc node?
> 
> But soc ranges starts from 0xfe000000, I don't know whether to change it.
> And all other nodes are 0xf..., except this sram.

Maybe they are wrong?

> Any suggestions would be greatly appreciated.
Where is the SRAM located? Inside the SoC or is it carved out external
ROM/RAM?

Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar  6 05:51:05 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 6 Mar 2025 14:51:05 +0100
Subject: [PATCH 1/2] dt-bindings: memory-controllers:
 samsung,exynos4210-srom: Enforce child props
In-Reply-To: <CAL_JsqKODHZcrpqskA2aeK6EqGNx9aGNuPqGzhcZ_Nqiu+Ccww@mail.gmail.com>
References: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
 <CAL_JsqKODHZcrpqskA2aeK6EqGNx9aGNuPqGzhcZ_Nqiu+Ccww@mail.gmail.com>
Message-ID: <ab483a68-40a8-4b44-ad73-d8a34bd32c69@kernel.org>

On 06/03/2025 14:39, Rob Herring wrote:
> Why do we need this? Any child node should have a schema which needs
> to include mc-peripheral-props.yaml if any properties from it can be
> used.

>From correctness point of view, you are right, we don't need it. However:

1. Convention was so far to have in every controller. I think this also
is easier to understand whenever one reads the bindings - clear
documentation what children on this bus should look like.

2. To clearly document from where samsung,srom-timing comes in the
required block:

https://web.git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git/tree/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml?h=dt/next#n50
Otherwise for me it is a bit confusing to require a property which is
nowhere here defined.


Best regards,
Krzysztof


From heiko at sntech.de  Thu Mar  6 05:51:16 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Thu, 06 Mar 2025 14:51:16 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306134002.380690-1-amadeus@jmu.edu.cn>
References: <4856313.kQq0lBPeGt@diego> <20250306134002.380690-1-amadeus@jmu.edu.cn>
Message-ID: <7020561.MhkbZ0Pkbq@diego>

Am Donnerstag, 6. M?rz 2025, 14:40:02 MEZ schrieb Chukun Pan:
> Hi,
> 
> > That sram is part of the soc (and has an mmio-address), so I'd think
> > it should live inside the soc node?
> 
> But soc ranges starts from 0xfe000000, I don't know whether to change it.
> And all other nodes are 0xf..., except this sram.
> Any suggestions would be greatly appreciated.

darn ... I didn't realize that this is not sram, but main memory :-)

in freescale/s32g3.dtsi and blaize/blaize-blzp1600.dtsi I see structures like:

        reserved-memory  {
                #address-cells = <2>;
                #size-cells = <2>;
                ranges;
                
                scmi_shmem: shm at d0000000 {
                        compatible = "arm,scmi-shmem";
                        reg = <0x0 0xd0000000 0x0 0x80>;
                        no-map;
                };
        };

does something like this work on the rk3528?

Heiko




From amadeus at jmu.edu.cn  Thu Mar  6 06:00:09 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 22:00:09 +0800
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
In-Reply-To: <20250305194612.47171-1-ziyao@disroot.org>
References: <20250305194612.47171-1-ziyao@disroot.org>
Message-ID: <20250306140009.384469-1-amadeus@jmu.edu.cn>

Hi,

> +		sdio0: mmc at ffc10000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc10000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO0>,
> +				 <&cru CCLK_SRC_SDIO0>,
> +				 <&cru SCLK_SDIO0_DRV>,
> +				 <&cru SCLK_SDIO0_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
> +				    <&sdio0_det>, <&sdio0_pwren>;

The sdio module is usually "non-removable", no need det,
and pwren may be other gpio (use mmc-pwrseq). So it should
be `pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>;`

> +			resets = <&cru SRST_H_SDIO0>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};
> +
> +		sdio1: mmc at ffc20000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc20000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO1>,
> +				 <&cru CCLK_SRC_SDIO1>,
> +				 <&cru SCLK_SDIO1_DRV>,
> +				 <&cru SCLK_SDIO1_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
> +				    <&sdio1_det>, <&sdio1_pwren>;

Same here.

> +			resets = <&cru SRST_H_SDIO1>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};

Thanks,
Chukun

-- 
2.25.1



From piotr.oniszczuk at gmail.com  Thu Mar  6 06:08:14 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Thu, 6 Mar 2025 15:08:14 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
Message-ID: <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 13:15:
> 
> Hi Piotr,
> 
> 
> 
> Then when you DP cable plugin, you can run command as bellow to see if the driver detects the HPD:
> 
> # cat /sys/class/drm/card0-DP-1/status 
> connected
> # 
> 


Andy,
Thx!

With above changes i?m getting ?connected?.
Also it looks crtc gets reasonable mode: https://gist.github.com/warpme/d6220e3cc502086a4c95f05bd9f9cf0c

Still black screen however...  

From wbg at kernel.org  Thu Mar  6 06:08:23 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Thu,  6 Mar 2025 23:08:23 +0900
Subject: [PATCH] counter: microchip-tcb-capture: Fix undefined counter channel state on probe
In-Reply-To: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
References: <20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org>
Message-ID: <174126995863.355997.16346927228585162675.b4-ty@kernel.org>


On Wed, 05 Mar 2025 19:01:19 +0900, William Breathitt Gray wrote:
> Hardware initialize of the timer counter channel does not occur on probe
> thus leaving the Count in an undefined state until the first
> function_write() callback is executed. Fix this by performing the proper
> hardware initialization during probe.
> 
> 

Applied to counter-fixes.

[1/1] counter: microchip-tcb-capture: Fix undefined counter channel state on probe
      commit: c0c9c73434666dc99ee156b25e7e722150bee001

Best regards,
-- 
William Breathitt Gray <wbg at kernel.org>


From geert at linux-m68k.org  Thu Mar  6 06:18:51 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 6 Mar 2025 15:18:51 +0100
Subject: [PATCH v2 2/7] clk: renesas: r9a09g047: Add clock and reset
 signals for the TSU IP
In-Reply-To: <20250227122453.30480-3-john.madieu.xa@bp.renesas.com>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com> <20250227122453.30480-3-john.madieu.xa@bp.renesas.com>
Message-ID: <CAMuHMdUoXSerYfb2L_tLmC2-5w9mhoZHc20LSYQgCHxB+bJOtw@mail.gmail.com>

On Thu, 27 Feb 2025 at 13:25, John Madieu <john.madieu.xa at bp.renesas.com> wrote:
> Add required clocks and resets signals for the TSU IP available on the
> Renesas RZ/G3E SoC
>
> Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
i.e. will queue in renesas-clk for v6.15.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From suzuki.poulose at arm.com  Thu Mar  6 06:19:39 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 6 Mar 2025 14:19:39 +0000
Subject: [PATCH v6 2/9] coresight-etm4x: change etmv4_drvdata spinlock
 type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-3-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
 <20250306121110.1647948-3-yeoreum.yun@arm.com>
Message-ID: <bd9040a2-b03a-4e4a-96a9-27f6a8db1d48@arm.com>

Hi Levi

On 06/03/2025 12:11, Yeoreum Yun wrote:
> In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during
> __schedule() by perf_event_task_sched_out()/in().
> 
> Since etmv4_drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
> 
> To address this, change type etmv4_drvdata->spinlock
> in coresight-etm4x drivers, which can be called
> by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
> Reviewed-by: James Clark <james.clark at linaro.org>
> ---
>   .../hwtracing/coresight/coresight-config.c    |   8 +-
>   .../hwtracing/coresight/coresight-config.h    |   2 +-
>   .../coresight/coresight-etm4x-core.c          |  18 +-
>   .../coresight/coresight-etm4x-sysfs.c         | 250 +++++++++---------
>   drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
>   5 files changed, 140 insertions(+), 140 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
> index 4723bf7402a2..4f72ae71b696 100644
> --- a/drivers/hwtracing/coresight/coresight-config.c
> +++ b/drivers/hwtracing/coresight/coresight-config.c
> @@ -76,10 +76,10 @@ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
>   	unsigned long flags;
>   	int i;
>   
> -	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> +	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
>   	for (i = 0; i < feat_csdev->nr_regs; i++)
>   		cscfg_set_reg(&feat_csdev->regs_csdev[i]);
> -	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> +	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
>   	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
>   		feat_csdev->feat_desc->name, "set on enable");
>   	return 0;
> @@ -91,10 +91,10 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
>   	unsigned long flags;
>   	int i;
>   
> -	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> +	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
>   	for (i = 0; i < feat_csdev->nr_regs; i++)
>   		cscfg_save_reg(&feat_csdev->regs_csdev[i]);
> -	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> +	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
>   	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
>   		feat_csdev->feat_desc->name, "save on disable");
>   }
> diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
> index 6ba013975741..b9ebc9fcfb7f 100644
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -206,7 +206,7 @@ struct cscfg_feature_csdev {
>   	const struct cscfg_feature_desc *feat_desc;
>   	struct coresight_device *csdev;
>   	struct list_head node;
> -	spinlock_t *drv_spinlock;
> +	raw_spinlock_t *drv_spinlock;
>   	int nr_params;
>   	struct cscfg_parameter_csdev *params_csdev;
>   	int nr_regs;

The changes above seems to be unrelated etm4x and not called for in the
patch description. Is there any reason why this cannot be separated from
etm4x changes ?

Suzuki


> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index bb1e80df2914..e5972f16abff 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -830,7 +830,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
>   			return ret;
>   	}
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   
>   	drvdata->trcid = path->trace_id;
>   
> @@ -849,7 +849,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
>   	if (ret)
>   		etm4_release_trace_id(drvdata);
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   
>   	if (!ret)
>   		dev_dbg(&csdev->dev, "ETM tracing enabled\n");
> @@ -1011,7 +1011,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
>   	 * DYING hotplug callback is serviced by the ETM driver.
>   	 */
>   	cpus_read_lock();
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   
>   	/*
>   	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
> @@ -1019,7 +1019,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
>   	 */
>   	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	cpus_read_unlock();
>   
>   	/*
> @@ -1698,13 +1698,13 @@ static int etm4_starting_cpu(unsigned int cpu)
>   	if (!etmdrvdata[cpu])
>   		return 0;
>   
> -	spin_lock(&etmdrvdata[cpu]->spinlock);
> +	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
>   	if (!etmdrvdata[cpu]->os_unlock)
>   		etm4_os_unlock(etmdrvdata[cpu]);
>   
>   	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
>   		etm4_enable_hw(etmdrvdata[cpu]);
> -	spin_unlock(&etmdrvdata[cpu]->spinlock);
> +	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
>   	return 0;
>   }
>   
> @@ -1713,10 +1713,10 @@ static int etm4_dying_cpu(unsigned int cpu)
>   	if (!etmdrvdata[cpu])
>   		return 0;
>   
> -	spin_lock(&etmdrvdata[cpu]->spinlock);
> +	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
>   	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
>   		etm4_disable_hw(etmdrvdata[cpu]);
> -	spin_unlock(&etmdrvdata[cpu]->spinlock);
> +	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
>   	return 0;
>   }
>   
> @@ -2160,7 +2160,7 @@ static int etm4_probe(struct device *dev)
>   			return -ENOMEM;
>   	}
>   
> -	spin_lock_init(&drvdata->spinlock);
> +	raw_spin_lock_init(&drvdata->spinlock);
>   
>   	drvdata->cpu = coresight_get_cpu(dev);
>   	if (drvdata->cpu < 0)
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index e5216c0f60da..fdd0956fecb3 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -175,7 +175,7 @@ static ssize_t reset_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	if (val)
>   		config->mode = 0x0;
>   
> @@ -267,7 +267,7 @@ static ssize_t reset_store(struct device *dev,
>   	config->vmid_mask0 = 0x0;
>   	config->vmid_mask1 = 0x0;
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   
>   	/* for sysfs - only release trace id when resetting */
>   	etm4_release_trace_id(drvdata);
> @@ -301,7 +301,7 @@ static ssize_t mode_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->mode = val & ETMv4_MODE_ALL;
>   
>   	if (drvdata->instrp0 == true) {
> @@ -438,7 +438,7 @@ static ssize_t mode_store(struct device *dev,
>   	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
>   		etm4_config_trace_mode(config);
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   
>   	return size;
>   }
> @@ -467,14 +467,14 @@ static ssize_t pe_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	if (val > drvdata->nr_pe) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EINVAL;
>   	}
>   
>   	config->pe_sel = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(pe);
> @@ -502,7 +502,7 @@ static ssize_t event_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	switch (drvdata->nr_event) {
>   	case 0x0:
>   		/* EVENT0, bits[7:0] */
> @@ -523,7 +523,7 @@ static ssize_t event_store(struct device *dev,
>   	default:
>   		break;
>   	}
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(event);
> @@ -551,7 +551,7 @@ static ssize_t event_instren_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	/* start by clearing all instruction event enable bits */
>   	config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
>   	switch (drvdata->nr_event) {
> @@ -579,7 +579,7 @@ static ssize_t event_instren_store(struct device *dev,
>   	default:
>   		break;
>   	}
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(event_instren);
> @@ -740,11 +740,11 @@ static ssize_t event_vinst_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
>   	config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
>   	config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(event_vinst);
> @@ -772,13 +772,13 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	/* clear all EXLEVEL_S bits  */
>   	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
>   	/* enable instruction tracing for corresponding exception level */
>   	val &= drvdata->s_ex_level;
>   	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(s_exlevel_vinst);
> @@ -807,13 +807,13 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	/* clear EXLEVEL_NS bits  */
>   	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
>   	/* enable instruction tracing for corresponding exception level */
>   	val &= drvdata->ns_ex_level;
>   	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(ns_exlevel_vinst);
> @@ -847,9 +847,9 @@ static ssize_t addr_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->addr_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_idx);
> @@ -863,7 +863,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
>   	len = scnprintf(buf, PAGE_SIZE, "%s\n",
> @@ -871,7 +871,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
>   			(val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
>   			(val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
>   			"data_load_store")));
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return len;
>   }
>   
> @@ -889,13 +889,13 @@ static ssize_t addr_instdatatype_store(struct device *dev,
>   	if (sscanf(buf, "%s", str) != 1)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (!strcmp(str, "instr"))
>   		/* TYPE, bits[1:0] */
>   		config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_instdatatype);
> @@ -910,14 +910,14 @@ static ssize_t addr_single_show(struct device *dev,
>   	struct etmv4_config *config = &drvdata->config;
>   
>   	idx = config->addr_idx;
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   	val = (unsigned long)config->addr_val[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -933,17 +933,17 @@ static ssize_t addr_single_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	config->addr_val[idx] = (u64)val;
>   	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_single);
> @@ -957,23 +957,23 @@ static ssize_t addr_range_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (idx % 2 != 0) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
>   	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
>   	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
>   	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	val1 = (unsigned long)config->addr_val[idx];
>   	val2 = (unsigned long)config->addr_val[idx + 1];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
>   }
>   
> @@ -996,10 +996,10 @@ static ssize_t addr_range_store(struct device *dev,
>   	if (val1 > val2)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (idx % 2 != 0) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
> @@ -1007,7 +1007,7 @@ static ssize_t addr_range_store(struct device *dev,
>   	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
>   	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
>   	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
> @@ -1024,7 +1024,7 @@ static ssize_t addr_range_store(struct device *dev,
>   		exclude = config->mode & ETM_MODE_EXCLUDE;
>   	etm4_set_mode_exclude(drvdata, exclude ? true : false);
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_range);
> @@ -1038,17 +1038,17 @@ static ssize_t addr_start_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	val = (unsigned long)config->addr_val[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1064,22 +1064,22 @@ static ssize_t addr_start_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (!drvdata->nr_addr_cmp) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EINVAL;
>   	}
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	config->addr_val[idx] = (u64)val;
>   	config->addr_type[idx] = ETM_ADDR_TYPE_START;
>   	config->vissctlr |= BIT(idx);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_start);
> @@ -1093,17 +1093,17 @@ static ssize_t addr_stop_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	val = (unsigned long)config->addr_val[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1119,22 +1119,22 @@ static ssize_t addr_stop_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (!drvdata->nr_addr_cmp) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EINVAL;
>   	}
>   	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
>   	       config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
> -		spin_unlock(&drvdata->spinlock);
> +		raw_spin_unlock(&drvdata->spinlock);
>   		return -EPERM;
>   	}
>   
>   	config->addr_val[idx] = (u64)val;
>   	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
>   	config->vissctlr |= BIT(idx + 16);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_stop);
> @@ -1148,14 +1148,14 @@ static ssize_t addr_ctxtype_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	/* CONTEXTTYPE, bits[3:2] */
>   	val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
>   	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
>   			(val == ETM_CTX_CTXID ? "ctxid" :
>   			(val == ETM_CTX_VMID ? "vmid" : "all")));
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return len;
>   }
>   
> @@ -1173,7 +1173,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
>   	if (sscanf(buf, "%s", str) != 1)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	if (!strcmp(str, "none"))
>   		/* start by clearing context type bits */
> @@ -1200,7 +1200,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
>   		if (drvdata->numvmidc)
>   			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
>   	}
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_ctxtype);
> @@ -1214,11 +1214,11 @@ static ssize_t addr_context_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	/* context ID comparator bits[6:4] */
>   	val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1239,12 +1239,12 @@ static ssize_t addr_context_store(struct device *dev,
>   		     drvdata->numcidc : drvdata->numvmidc))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	/* clear context ID comparator bits[6:4] */
>   	config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
>   	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_context);
> @@ -1258,10 +1258,10 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1280,12 +1280,12 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev,
>   	if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
>   	config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
>   	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(addr_exlevel_s_ns);
> @@ -1308,7 +1308,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
>   	int size = 0;
>   	bool exclude = false;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->addr_idx;
>   	addr_v = config->addr_val[idx];
>   	addr_ctrl = config->addr_acc[idx];
> @@ -1323,7 +1323,7 @@ static ssize_t addr_cmp_view_show(struct device *dev,
>   		}
>   		exclude = config->viiectlr & BIT(idx / 2 + 16);
>   	}
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	if (addr_type) {
>   		size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx,
>   				 addr_type_names[addr_type], addr_v);
> @@ -1367,9 +1367,9 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev,
>   	if (!drvdata->nr_pe_cmp)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->vipcssctlr = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop);
> @@ -1403,9 +1403,9 @@ static ssize_t seq_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->seq_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(seq_idx);
> @@ -1449,10 +1449,10 @@ static ssize_t seq_event_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->seq_idx;
>   	val = config->seq_ctrl[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1468,11 +1468,11 @@ static ssize_t seq_event_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->seq_idx;
>   	/* Seq control has two masks B[15:8] F[7:0] */
>   	config->seq_ctrl[idx] = val & 0xFFFF;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(seq_event);
> @@ -1536,9 +1536,9 @@ static ssize_t cntr_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->cntr_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(cntr_idx);
> @@ -1552,10 +1552,10 @@ static ssize_t cntrldvr_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	val = config->cntrldvr[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1573,10 +1573,10 @@ static ssize_t cntrldvr_store(struct device *dev,
>   	if (val > ETM_CNTR_MAX_VAL)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	config->cntrldvr[idx] = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(cntrldvr);
> @@ -1590,10 +1590,10 @@ static ssize_t cntr_val_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	val = config->cntr_val[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1611,10 +1611,10 @@ static ssize_t cntr_val_store(struct device *dev,
>   	if (val > ETM_CNTR_MAX_VAL)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	config->cntr_val[idx] = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(cntr_val);
> @@ -1628,10 +1628,10 @@ static ssize_t cntr_ctrl_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	val = config->cntr_ctrl[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1647,10 +1647,10 @@ static ssize_t cntr_ctrl_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->cntr_idx;
>   	config->cntr_ctrl[idx] = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(cntr_ctrl);
> @@ -1688,9 +1688,9 @@ static ssize_t res_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->res_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(res_idx);
> @@ -1704,10 +1704,10 @@ static ssize_t res_ctrl_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->res_idx;
>   	val = config->res_ctrl[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1723,7 +1723,7 @@ static ssize_t res_ctrl_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->res_idx;
>   	/* For odd idx pair inversal bit is RES0 */
>   	if (idx % 2 != 0)
> @@ -1733,7 +1733,7 @@ static ssize_t res_ctrl_store(struct device *dev,
>   				       TRCRSCTLRn_INV |
>   				       TRCRSCTLRn_GROUP_MASK |
>   				       TRCRSCTLRn_SELECT_MASK);
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(res_ctrl);
> @@ -1762,9 +1762,9 @@ static ssize_t sshot_idx_store(struct device *dev,
>   	if (val >= drvdata->nr_ss_cmp)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->ss_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(sshot_idx);
> @@ -1777,9 +1777,9 @@ static ssize_t sshot_ctrl_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val = config->ss_ctrl[config->ss_idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1795,12 +1795,12 @@ static ssize_t sshot_ctrl_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->ss_idx;
>   	config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
>   	/* must clear bit 31 in related status register on programming */
>   	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(sshot_ctrl);
> @@ -1812,9 +1812,9 @@ static ssize_t sshot_status_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val = config->ss_status[config->ss_idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   static DEVICE_ATTR_RO(sshot_status);
> @@ -1827,9 +1827,9 @@ static ssize_t sshot_pe_ctrl_show(struct device *dev,
>   	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>   	struct etmv4_config *config = &drvdata->config;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val = config->ss_pe_cmp[config->ss_idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1845,12 +1845,12 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->ss_idx;
>   	config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
>   	/* must clear bit 31 in related status register on programming */
>   	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(sshot_pe_ctrl);
> @@ -1884,9 +1884,9 @@ static ssize_t ctxid_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->ctxid_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(ctxid_idx);
> @@ -1907,10 +1907,10 @@ static ssize_t ctxid_pid_show(struct device *dev,
>   	if (task_active_pid_ns(current) != &init_pid_ns)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->ctxid_idx;
>   	val = (unsigned long)config->ctxid_pid[idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -1945,10 +1945,10 @@ static ssize_t ctxid_pid_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &pid))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	idx = config->ctxid_idx;
>   	config->ctxid_pid[idx] = (u64)pid;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(ctxid_pid);
> @@ -1968,10 +1968,10 @@ static ssize_t ctxid_masks_show(struct device *dev,
>   	if (task_active_pid_ns(current) != &init_pid_ns)
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val1 = config->ctxid_mask0;
>   	val2 = config->ctxid_mask1;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
>   }
>   
> @@ -2004,7 +2004,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
>   	if ((drvdata->numcidc > 4) && (nr_inputs != 2))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	/*
>   	 * each byte[0..3] controls mask value applied to ctxid
>   	 * comparator[0..3]
> @@ -2076,7 +2076,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
>   			mask >>= 0x8;
>   	}
>   
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(ctxid_masks);
> @@ -2110,9 +2110,9 @@ static ssize_t vmid_idx_store(struct device *dev,
>   	 * Use spinlock to ensure index doesn't change while it gets
>   	 * dereferenced multiple times within a spinlock block elsewhere.
>   	 */
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->vmid_idx = val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(vmid_idx);
> @@ -2132,9 +2132,9 @@ static ssize_t vmid_val_show(struct device *dev,
>   	if (!task_is_in_init_pid_ns(current))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val = (unsigned long)config->vmid_val[config->vmid_idx];
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>   }
>   
> @@ -2162,9 +2162,9 @@ static ssize_t vmid_val_store(struct device *dev,
>   	if (kstrtoul(buf, 16, &val))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	config->vmid_val[config->vmid_idx] = (u64)val;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(vmid_val);
> @@ -2183,10 +2183,10 @@ static ssize_t vmid_masks_show(struct device *dev,
>   	if (!task_is_in_init_pid_ns(current))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   	val1 = config->vmid_mask0;
>   	val2 = config->vmid_mask1;
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
>   }
>   
> @@ -2218,7 +2218,7 @@ static ssize_t vmid_masks_store(struct device *dev,
>   	if ((drvdata->numvmidc > 4) && (nr_inputs != 2))
>   		return -EINVAL;
>   
> -	spin_lock(&drvdata->spinlock);
> +	raw_spin_lock(&drvdata->spinlock);
>   
>   	/*
>   	 * each byte[0..3] controls mask value applied to vmid
> @@ -2291,7 +2291,7 @@ static ssize_t vmid_masks_store(struct device *dev,
>   		else
>   			mask >>= 0x8;
>   	}
> -	spin_unlock(&drvdata->spinlock);
> +	raw_spin_unlock(&drvdata->spinlock);
>   	return size;
>   }
>   static DEVICE_ATTR_RW(vmid_masks);
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 2b92de17b5a2..bd7db36ba197 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -989,7 +989,7 @@ struct etmv4_drvdata {
>   	struct clk			*pclk;
>   	void __iomem			*base;
>   	struct coresight_device		*csdev;
> -	spinlock_t			spinlock;
> +	raw_spinlock_t			spinlock;
>   	int				cpu;
>   	u8				arch;
>   	u8				nr_pe;



From amadeus at jmu.edu.cn  Thu Mar  6 06:20:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 22:20:08 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <10115c0f-4a7f-460a-a0bd-0c86d1e7d3b6@kernel.org>
References: <10115c0f-4a7f-460a-a0bd-0c86d1e7d3b6@kernel.org>
Message-ID: <20250306142008.389243-1-amadeus@jmu.edu.cn>

Hi,

>> Any suggestions would be greatly appreciated.
> Where is the SRAM located? Inside the SoC or is it carved out external
> ROM/RAM?

It is located in the SoC.
"Embedded Memory" Area:
BootROM | PMU_SRAM (8KB) | SYSTEM_SRAM (64KB) | OTP

Thanks,
Chukun

-- 
2.25.1



From heiko at sntech.de  Thu Mar  6 06:25:36 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Thu, 06 Mar 2025 15:25:36 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306142008.389243-1-amadeus@jmu.edu.cn>
References: <10115c0f-4a7f-460a-a0bd-0c86d1e7d3b6@kernel.org>
 <20250306142008.389243-1-amadeus@jmu.edu.cn>
Message-ID: <24848438.6Emhk5qWAg@diego>

Am Donnerstag, 6. M?rz 2025, 15:20:08 MEZ schrieb Chukun Pan:
> Hi,
> 
> >> Any suggestions would be greatly appreciated.
> > Where is the SRAM located? Inside the SoC or is it carved out external
> > ROM/RAM?
> 
> It is located in the SoC.
> "Embedded Memory" Area:
> BootROM | PMU_SRAM (8KB) | SYSTEM_SRAM (64KB) | OTP

are you really sure about that?

Looking at Jonas' recent rk3528 u-boot series [0]
0x0 _to_ 0xfc000000 is the SDRAM memory area
so 0x10f000 is a carveout of the main sdram.


Heiko


[0] https://lists.denx.de/pipermail/u-boot/2025-January/578393.html




From piotr.oniszczuk at gmail.com  Thu Mar  6 06:28:08 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Thu, 6 Mar 2025 15:28:08 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
 <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>
Message-ID: <326B91E9-FB91-43C3-B98B-3EF079F313C6@gmail.com>



> Wiadomo?? napisana przez Piotr Oniszczuk <piotr.oniszczuk at gmail.com> w dniu 6 mar 2025, o godz. 15:08:
> 
> 
> 
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 13:15:
>> 
>> Hi Piotr,
>> 
>> 
>> 
>> Then when you DP cable plugin, you can run command as bellow to see if the driver detects the HPD:
>> 
>> # cat /sys/class/drm/card0-DP-1/status 
>> connected
>> # 
>> 
> 
> 
> Andy,
> Thx!
> 
> With above changes i?m getting ?connected?.
> Also it looks crtc gets reasonable mode: https://gist.github.com/warpme/d6220e3cc502086a4c95f05bd9f9cf0c
> 
> Still black screen however?
>   

some additional data point: /sys/kernel/debug/dri/1/vop2/summary 


working hdmi:

Video Port1: ACTIVE
    Connector: HDMI-A-1
        bus_format[0]: Unknown
        output_mode[f] color_space[0]
    Display mode: 1920x1080p60
        clk[148500] real_clk[148500] type[48] flag[5]
        H: 1920 2008 2052 2200
        V: 1080 1084 1089 1125
    Cluster0-win0: ACTIVE
        win_id: 0
        format: XR24 little-endian (0x34325258) glb_alpha[0xff]
        rotate: xmirror: 0 ymirror: 0 rotate_90: 0 rotate_270: 0
        zpos: 0
        src: pos[0, 0] rect[1920 x 1080]
        dst: pos[0, 0] rect[1920 x 1080]
        buf[0]: addr: 0x00000000017e1000 pitch: 7680 offset: 0
Video Port2: DISABLED




non-working DP:

Video Port1: DISABLED
Video Port2: ACTIVE
    Connector: DP-1
        bus_format[100a]: RGB888_1X24
        output_mode[f] color_space[0]
    Display mode: 1920x1080p60
        clk[148500] real_clk[148500] type[48] flag[5]
        H: 1920 2008 2052 2200
        V: 1080 1084 1089 1125
    Cluster1-win0: ACTIVE
        win_id: 1
        format: XR24 little-endian (0x34325258) glb_alpha[0xff]
        rotate: xmirror: 0 ymirror: 0 rotate_90: 0 rotate_270: 0
        zpos: 0
        src: pos[0, 0] rect[1920 x 1080]
        dst: pos[0, 0] rect[1920 x 1080]
        buf[0]: addr: 0x00000000007ed000 pitch: 7680 offset: 0



From pabeni at redhat.com  Thu Mar  6 06:29:49 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Thu, 6 Mar 2025 15:29:49 +0100
Subject: [PATCH v3 net-next 04/13] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <20250304072201.1332603-5-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
 <20250304072201.1332603-5-wei.fang@nxp.com>
Message-ID: <03492277-b7e8-4cd1-b92e-699ee0d7dc85@redhat.com>

On 3/4/25 8:21 AM, Wei Fang wrote:
> +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16 si_bit,
> +					       struct enetc_mac_addr *mac,
> +					       int mac_cnt)
> +{
> +	struct enetc_mac_list_entry *entry;
> +	int i;
> +
> +	for (i = 0; i < mac_cnt; i++) {
> +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> +		if (entry) {
> +			entry->si_bitmap &= ~si_bit;
> +			if (!entry->si_bitmap) {


Minor nit: here and elsewhere you could reduce the level of indentation
restructoring the code as:

		if (!entry)
			continue;

		entry->si_bitmap &= ~si_bit;
		if (entry->si_bitmap)
			continue;
/P



From catalin.marinas at arm.com  Thu Mar  6 06:36:16 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 6 Mar 2025 14:36:16 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8mCbc2Z2QGd3f8M@google.com>
References: <Z8g8vhS9rqQ_ez48@google.com>
 <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com>
Message-ID: <Z8my4MZ-In0ibxVY@arm.com>

On Thu, Mar 06, 2025 at 11:09:33AM +0000, Alice Ryhl wrote:
> On Wed, Mar 05, 2025 at 05:10:16PM +0000, Cristian Marussi wrote:
> > On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> > > This was with a kernel running v6.13-rc3, but as far as I can tell, no
> > > relevant changes have landed since v6.13-rc3. My tree *does* include
> > > commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> > > scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> > > not happening consistently.
> > > 
> > > See below for the full kmemleak report.
> > > 
> > > Alice
> > > 
> > > $ sudo cat /sys/kernel/debug/kmemleak
> > > unreferenced object 0xffffff8106c86000 (size 2048):
> > >   comm "swapper/0", pid 1, jiffies 4294893094
> > >   hex dump (first 32 bytes):
> > >     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
> > >     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
> > >   backtrace (crc feae9680):
> > >     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
> > >     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
> > >     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
> > >     [<000000008714917b>] scmi_device_create+0x40/0x194
> > >     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
> > >     [<00000000970bad38>] scmi_probe+0x584/0xa78
> > >     [<000000002600d2fd>] platform_probe+0xbc/0xf0
> > >     [<00000000f6f556b4>] really_probe+0x1b8/0x520
> > >     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
> > >     [<00000000d613b754>] driver_probe_device+0x6c/0x208
> > >     [<00000000187a9170>] __driver_attach+0x168/0x328
> > >     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
> > >     [<00000000984a3176>] driver_attach+0x34/0x44
> > >     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
> > >     [<00000000747fce19>] driver_register+0xc0/0x1a0
> > >     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> > > unreferenced object 0xffffff8103bc01c0 (size 32):
> > 
> > I could not reproduce on my setup, even though I run a system with
> > all the existent SCMI protocols (and related drivers) enabled (and
> > so a lot of device creations) and a downstream test driver that causes
> > even more SCMI devices to be created/destroyed at load/unload.
> > 
> > Coming down the path from scmi_chan_setup(), it seems something around
> > transport devices creation, but it is not obvious to me where the leak
> > could hide....
> > 
> > ...any particular setup on your side ? ...using LKMs, loading/unloading,
> > any usage pattern that could help me reproduce ?
> 
> I looked into this a bit more, and actually it does happen consistently.
> It's just that kmemleak doesn't report it until 10 minutes after
> booting, so I did not notice it.

You can force the scanning with:

  echo scan > /sys/kernel/debug/kmemleak

Just do it a couple of times after boot, no need to wait 10 min for the
default background scanning.

> user at rk3588-ci:~$ sudo cat /sys/kernel/debug/kmemleak
> unreferenced object 0xffffff81068c0000 (size 2048):
>   comm "swapper/0", pid 1, jiffies 4294893128
>   hex dump (first 32 bytes):
>     02 00 00 00 10 00 00 00 40 a3 7a 03 81 ff ff ff  ........ at .z.....
>     60 c8 79 03 81 ff ff ff 18 00 8c 06 81 ff ff ff  `.y.............
>   backtrace (crc 60df30fb):
>     kmemleak_alloc+0x34/0xa0
>     __kmalloc_cache_noprof+0x1e0/0x450
>     __scmi_device_create+0xb4/0x2b4

Is this the kzalloc() for sizeof(*scmi_dev)? It's surprisingly large, I
thought it would go for the kmalloc-1k slab as struct device is below
this side, at least for my builds. Anyway...

>     scmi_device_create+0x40/0x194
>     scmi_chan_setup+0x144/0x3b8
>     scmi_probe+0x51c/0x9fc
>     platform_probe+0xbc/0xf0
>     really_probe+0x1b8/0x520
>     __driver_probe_device+0xe0/0x1d8
>     driver_probe_device+0x6c/0x208
>     __driver_attach+0x168/0x328
>     bus_for_each_dev+0x14c/0x178
>     driver_attach+0x34/0x44
>     bus_add_driver+0x1bc/0x358
>     driver_register+0xc0/0x1a0
>     __platform_driver_register+0x40/0x50
> unreferenced object 0xffffff81037aa340 (size 32):
>   comm "swapper/0", pid 1, jiffies 4294893128
>   hex dump (first 32 bytes):
>     5f 5f 73 63 6d 69 5f 74 72 61 6e 73 70 6f 72 74  __scmi_transport
>     5f 64 65 76 69 63 65 5f 72 78 5f 31 30 00 ff ff  _device_rx_10...
>   backtrace (crc 8dab7ca7):
>     kmemleak_alloc+0x34/0xa0
>     __kmalloc_node_track_caller_noprof+0x234/0x528
>     kstrdup+0x48/0x80
>     kstrdup_const+0x30/0x3c

These are referenced from the main structure above, so they'd be
reported as leaks as well.

This loop in scmi_device_create() looks strange:

	list_for_each_entry(rdev, phead, node) {
		struct scmi_device *sdev;

		sdev = __scmi_device_create(np, parent,
					    rdev->id_table->protocol_id,
					    rdev->id_table->name);
		/* Report errors and carry on... */
		if (sdev)
			scmi_dev = sdev;
		else
			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
			       of_node_full_name(parent->of_node),
			       rdev->id_table->protocol_id,
			       rdev->id_table->name);
	}

We can override scmi_dev a few times in the loop and lose the previous
sdev allocations. Is this intended?

-- 
Catalin


From yeoreum.yun at arm.com  Thu Mar  6 06:37:36 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu, 6 Mar 2025 14:37:36 +0000
Subject: [PATCH v6 2/9] coresight-etm4x: change etmv4_drvdata spinlock
 type to raw_spinlock_t
In-Reply-To: <bd9040a2-b03a-4e4a-96a9-27f6a8db1d48@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
 <20250306121110.1647948-3-yeoreum.yun@arm.com>
 <bd9040a2-b03a-4e4a-96a9-27f6a8db1d48@arm.com>
Message-ID: <Z8mzMI2xGm3qX9an@e129823.arm.com>

Hi Suzuki,

> > diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
> > index 4723bf7402a2..4f72ae71b696 100644
> > --- a/drivers/hwtracing/coresight/coresight-config.c
> > +++ b/drivers/hwtracing/coresight/coresight-config.c
> > @@ -76,10 +76,10 @@ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
> >   	unsigned long flags;
> >   	int i;
> > -	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> > +	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> >   	for (i = 0; i < feat_csdev->nr_regs; i++)
> >   		cscfg_set_reg(&feat_csdev->regs_csdev[i]);
> > -	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> > +	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> >   	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
> >   		feat_csdev->feat_desc->name, "set on enable");
> >   	return 0;
> > @@ -91,10 +91,10 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
> >   	unsigned long flags;
> >   	int i;
> > -	spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> > +	raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
> >   	for (i = 0; i < feat_csdev->nr_regs; i++)
> >   		cscfg_save_reg(&feat_csdev->regs_csdev[i]);
> > -	spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> > +	raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
> >   	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
> >   		feat_csdev->feat_desc->name, "save on disable");
> >   }
> > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
> > index 6ba013975741..b9ebc9fcfb7f 100644
> > --- a/drivers/hwtracing/coresight/coresight-config.h
> > +++ b/drivers/hwtracing/coresight/coresight-config.h
> > @@ -206,7 +206,7 @@ struct cscfg_feature_csdev {
> >   	const struct cscfg_feature_desc *feat_desc;
> >   	struct coresight_device *csdev;
> >   	struct list_head node;
> > -	spinlock_t *drv_spinlock;
> > +	raw_spinlock_t *drv_spinlock;
> >   	int nr_params;
> >   	struct cscfg_parameter_csdev *params_csdev;
> >   	int nr_regs;
>
> The changes above seems to be unrelated etm4x and not called for in the
> patch description. Is there any reason why this cannot be separated from
> etm4x changes ?
>
> Suzuki

This is change for cscfg_csdev_enable_active_config() function
which used in etm4x's enable path.
currently, the user of this function is only etm4x driver,
I've included these change in etm4x patch together
to solving the issue in etm4x driver.

Though it seems unrelated to solve the issue happening in etm4x,
I think it seems good to put together.

Any thought?

Thanks!



From nicolas.frattaroli at collabora.com  Thu Mar  6 06:38:58 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Thu, 06 Mar 2025 15:38:58 +0100
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI controllers
In-Reply-To: <81d60550-4929-48c1-b4d3-1473b902bf12@kernel.org>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <2376575.ElGaqSPkdT@workhorse>
 <81d60550-4929-48c1-b4d3-1473b902bf12@kernel.org>
Message-ID: <8514337.T7Z3S40VBb@workhorse>

On Thursday, 6 March 2025 14:43:21 Central European Standard Time Krzysztof 
Kozlowski wrote:
> On 06/03/2025 14:13, Nicolas Frattaroli wrote:
> > On Thursday, 6 March 2025 08:42:54 Central European Standard Time
> > Krzysztof
> > 
> > Kozlowski wrote:
> >> On 05/03/2025 22:24, Nicolas Frattaroli wrote:
> >>> Rockchip introduced a new audio controller called the "Serial Audio
> >>> Interface", or "SAI" for short, on some of their newer SoCs. In
> >>> particular, this controller is used several times on the RK3576 SoC.
> >>> 
> >>> Add a schema for it, with only an RK3576 compatible for now. Other SoCs
> >>> may follow as mainline support for them lands.
> >>> 
> >>> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> >>> ---
> >>> 
> >>>  .../devicetree/bindings/sound/rockchip,sai.yaml    | 151
> >>>  +++++++++++++++++++++
> >> 
> >> Filename based on compatible.
> > 
> > Sure, but more compatibles will follow. Are you certain you want a file
> > named rockchip,rk3576-sai.yaml to then contain rockchip,rk3528-sai? If so
> > then I do
> Yes (or the other way around if 3528 is older)

They were released at about the same time from what I know. I'll pick the 
RK3576 though since it was the first to get upstream support.

> 
> > not understand the reason behind this policy.
> 
> So the name will match hardware, instead of sai.yaml, sai2.yaml,
> sai3.yaml and sai-green-frog.yaml.

Downstream called the compatible "sai-v1" so you're onto something here I'm 
afraid. :)

> 
> >>>  MAINTAINERS                                        |   6 +
> >>>  2 files changed, 157 insertions(+)
> >> 
> >> ...
> >> 
> >>> +
> >>> +  dma-names:
> >>> +    minItems: 1
> >>> +    maxItems: 2
> >>> +    oneOf:
> >>> +      - const: tx
> >>> +      - const: rx
> >>> +      - items:
> >>> +          - const: tx
> >>> +          - const: rx
> >> 
> >> Why all combinations are possible?
> > 
> > Because they are. sai5 in rk3576 is rx only. sai7 is tx only. Others are
> > both
> What is sai5 and sai7? Instances on the same chip? Does it mean some of
> instances can only receive and some only transmit?

sai5 and sai7 are instances on the same chip, yes, see rk3576.dtsi changes in 
this series. Some instances can only receive, some can only transmit. Some can 
do both. I think the way I wrote the binding already allows for just "tx", 
just "rx", and "tx, rx" but not "rx, tx", which is I think what we want here.

> 
> > tx and rx. Do you want me to enforce that those with both are always tx
> > followed by rx?
> 
> Best regards,
> Krzysztof

Cheers,
Nicolas Frattaroli





From lkp at intel.com  Thu Mar  6 06:47:34 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 22:47:34 +0800
Subject: [PATCH v8 2/4] rtc: s32g: add NXP S32G2/S32G3 SoC support
In-Reply-To: <20250228081812.3115478-3-ciprianmarian.costea@oss.nxp.com>
References: <20250228081812.3115478-3-ciprianmarian.costea@oss.nxp.com>
Message-ID: <202503062204.QeQoZBYt-lkp@intel.com>

Hi Ciprian,

kernel test robot noticed the following build errors:

[auto build test ERROR on robh/for-next]
[also build test ERROR on arm64/for-next/core krzk-dt/for-next linus/master v6.14-rc5 next-20250306]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ciprian-Costea/dt-bindings-rtc-add-schema-for-NXP-S32G2-S32G3-SoCs/20250228-162229
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250228081812.3115478-3-ciprianmarian.costea%40oss.nxp.com
patch subject: [PATCH v8 2/4] rtc: s32g: add NXP S32G2/S32G3 SoC support
config: hexagon-allyesconfig (https://download.01.org/0day-ci/archive/20250306/202503062204.QeQoZBYt-lkp at intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250306/202503062204.QeQoZBYt-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503062204.QeQoZBYt-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/rtc/rtc-s32g.c:204:9: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     204 |         rtcc = FIELD_PREP(RTCC_CLKSEL_MASK, priv->clk_src_idx);
         |                ^
   1 error generated.


vim +/FIELD_PREP +204 drivers/rtc/rtc-s32g.c

   196	
   197	static int rtc_clk_src_setup(struct rtc_priv *priv)
   198	{
   199		u32 rtcc;
   200	
   201		if (priv->rtc_data->reserved_clk_mask & (1 << priv->clk_src_idx))
   202			return -EOPNOTSUPP;
   203	
 > 204		rtcc = FIELD_PREP(RTCC_CLKSEL_MASK, priv->clk_src_idx);
   205	
   206		switch (priv->rtc_data->clk_div) {
   207		case DIV512_32:
   208			rtcc |= RTCC_DIV512EN;
   209			rtcc |= RTCC_DIV32EN;
   210			break;
   211		case DIV512:
   212			rtcc |= RTCC_DIV512EN;
   213			break;
   214		case DIV32:
   215			rtcc |= RTCC_DIV32EN;
   216			break;
   217		case DIV1:
   218			break;
   219		default:
   220			return -EINVAL;
   221		}
   222	
   223		rtcc |= RTCC_APIEN | RTCC_APIIE;
   224		/*
   225		 * Make sure the CNTEN is 0 before we configure
   226		 * the clock source and dividers.
   227		 */
   228		s32g_rtc_disable(priv);
   229		writel(rtcc, priv->rtc_base + RTCC_OFFSET);
   230		s32g_rtc_enable(priv);
   231	
   232		return 0;
   233	}
   234	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From amadeus at jmu.edu.cn  Thu Mar  6 06:50:20 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 22:50:20 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <24848438.6Emhk5qWAg@diego>
References: <24848438.6Emhk5qWAg@diego>
Message-ID: <20250306145020.485848-1-amadeus@jmu.edu.cn>

Hi,

> are you really sure about that?
>
> Looking at Jonas' recent rk3528 u-boot series [0]
> 0x0 _to_ 0xfc000000 is the SDRAM memory area
> so 0x10f000 is a carveout of the main sdram.

Sorry, I was misled by the dtsi of rk3568.
Put it in reserved-memory works on rk3528:

~# dmesg | grep scmi
[    0.061452] scmi_core: SCMI protocol bus registered
[    0.125903] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
[    0.126763] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
[    0.127368] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0

Should we change this for rk3568 as well?

Thanks,
Chukun

-- 
2.25.1



From jonas at kwiboo.se  Thu Mar  6 06:54:24 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 15:54:24 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306131016.281290-2-amadeus@jmu.edu.cn>
References: <20250306131016.281290-1-amadeus@jmu.edu.cn>
 <20250306131016.281290-2-amadeus@jmu.edu.cn>
Message-ID: <3181e8a0-b98f-4860-a0fa-abc3130c9b35@kwiboo.se>

Hi Chukun,

On 2025-03-06 14:10, Chukun Pan wrote:
> Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
> Add SCMI clk for CPU, GPU and RNG will also use it.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 32 ++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 0c0e7f151462..aa68c2fef2f3 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -59,6 +59,7 @@ cpu0: cpu at 0 {
>  			reg = <0x0>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -66,6 +67,7 @@ cpu1: cpu at 1 {
>  			reg = <0x1>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
>  		};
>  
>  		cpu2: cpu at 2 {
> @@ -73,6 +75,7 @@ cpu2: cpu at 2 {
>  			reg = <0x2>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
>  		};
>  
>  		cpu3: cpu at 3 {
> @@ -80,6 +83,22 @@ cpu3: cpu at 3 {
>  			reg = <0x3>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +		};
> +	};
> +
> +	firmware {
> +		scmi: scmi {
> +			compatible = "arm,scmi-smc";
> +			arm,smc-id = <0x82000010>;
> +			shmem = <&scmi_shmem>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			scmi_clk: protocol at 14 {
> +				reg = <0x14>;
> +				#clock-cells = <1>;
> +			};
>  		};
>  	};
>  
> @@ -110,6 +129,19 @@ gmac0_clk: clock-gmac50m {
>  		#clock-cells = <0>;
>  	};
>  
> +	sram at 10f000 {
> +		compatible = "mmio-sram";
> +		reg = <0x0 0x0010f000 0x0 0x100>;
> +		ranges = <0 0x0 0x0010f000 0x100>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		scmi_shmem: sram at 0 {
> +			compatible = "arm,scmi-shmem";
> +			reg = <0x0 0x100>;
> +		};
> +	};

This does not look correct, the shared memory is located in DRAM not in
SRAM. I used reserved-memory in my work-in-progress commit for adding
the GPU [1], something like, not sure if this is more correct:

	reserved-memory  {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		scmi_shmem: scmi-shmem at 10f000 {
			compatible = "arm,scmi-shmem";
			reg = <0x0 0x0010f000 0x0 0x100>;
			no-map;
		};
	};

[1] https://github.com/Kwiboo/linux-rockchip/commit/f1cd58b2431a01e8cf6a430922204a71fee484f3

Regards,
Jonas

> +
>  	soc {
>  		compatible = "simple-bus";
>  		ranges = <0x0 0xfe000000 0x0 0xfe000000 0x0 0x2000000>;



From sudeep.holla at arm.com  Thu Mar  6 06:54:50 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 6 Mar 2025 14:54:50 +0000
Subject: [PATCH 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306131016.281290-2-amadeus@jmu.edu.cn>
References: <20250306131016.281290-1-amadeus@jmu.edu.cn>
 <20250306131016.281290-2-amadeus@jmu.edu.cn>
Message-ID: <Z8m3OkHAedbQyKbu@bogus>

On Thu, Mar 06, 2025 at 09:10:16PM +0800, Chukun Pan wrote:
> Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
> Add SCMI clk for CPU, GPU and RNG will also use it.
> 

It is highly recommended not to use clock protocol for CPUs and GPUs
especially if the plan is to drive regulators separately. Please use
the performance protocol instead which can abstract the clock and the
regulator details for the OS.

-- 
Regards,
Sudeep


From amadeus at jmu.edu.cn  Thu Mar  6 07:00:17 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 23:00:17 +0800
Subject: [PATCH v2 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250306150017.488975-1-amadeus@jmu.edu.cn>
References: <20250306150017.488975-1-amadeus@jmu.edu.cn>
Message-ID: <20250306150017.488975-2-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 33 ++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index b1713ed4d7e2..476b83f98834 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -59,6 +59,9 @@ cpu0: cpu at 0 {
 			reg = <0x0>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
+			assigned-clocks = <&scmi_clk SCMI_CLK_CPU>;
+			assigned-clock-rates = <1200000000>;
 		};
 
 		cpu1: cpu at 1 {
@@ -66,6 +69,7 @@ cpu1: cpu at 1 {
 			reg = <0x1>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu2: cpu at 2 {
@@ -73,6 +77,7 @@ cpu2: cpu at 2 {
 			reg = <0x2>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu3: cpu at 3 {
@@ -80,6 +85,22 @@ cpu3: cpu at 3 {
 			reg = <0x3>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
+		};
+	};
+
+	firmware {
+		scmi: scmi {
+			compatible = "arm,scmi-smc";
+			arm,smc-id = <0x82000010>;
+			shmem = <&scmi_shmem>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_clk: protocol at 14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
 		};
 	};
 
@@ -88,6 +109,18 @@ psci {
 		method = "smc";
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		scmi_shmem: shmem at 10f000 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x0010f000 0x0 0x100>;
+			no-map;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-- 
2.25.1



From amadeus at jmu.edu.cn  Thu Mar  6 07:00:16 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu,  6 Mar 2025 23:00:16 +0800
Subject: [PATCH v2 0/1]  arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
Message-ID: <20250306150017.488975-1-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of standard ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

dmesg:
[    0.061333] scmi_core: SCMI protocol bus registered
[    0.125780] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
[    0.126628] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
[    0.127233] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0

CPU frequency: ~# mhz
count=611657 us50=19994 us250=99945 diff=79951 cpu_MHz=1530.080

Changes in v2:
  Change sram to reserved-memory

Chukun Pan (1):
  arm64: dts: rockchip: enable SCMI clk for RK3528 SoC

 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 33 ++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

-- 
2.25.1



From Frank.li at nxp.com  Thu Mar  6 07:02:22 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 10:02:22 -0500
Subject: [PATCH] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph
 port
In-Reply-To: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
References: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
Message-ID: <Z8m4/ljU4h6BtB7g@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 01:31:38PM +0800, Shengjiu Wang wrote:
> This device can be used in conjunction with audio-graph-card to provide
> an endpoint for binding with the other side of the audio link.
>
> Signed-off-by: Shengjiu Wang <shengjiu.wang at nxp.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  .../devicetree/bindings/sound/fsl,imx-asrc.yaml      | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
> index abac5084d63b..85799f83e65f 100644
> --- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
> +++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml
> @@ -77,6 +77,10 @@ properties:
>    power-domains:
>      maxItems: 1
>
> +  port:
> +    $ref: audio-graph-port.yaml#
> +    unevaluatedProperties: false
> +
>    fsl,asrc-rate:
>      $ref: /schemas/types.yaml#/definitions/uint32
>      description: The mutual sample rate used by DPCM Back Ends
> @@ -174,4 +178,12 @@ examples:
>                      "txa", "txb", "txc";
>          fsl,asrc-rate  = <48000>;
>          fsl,asrc-width = <16>;
> +
> +        port {
> +            playback-only;
> +
> +            asrc_endpoint: endpoint {
> +                remote-endpoint = <&fe00_ep>;
> +            };
> +       };
>      };
> --
> 2.34.1
>


From andre.draszik at linaro.org  Thu Mar  6 07:12:11 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 15:12:11 +0000
Subject: [PATCH v2 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <f7c0101ff26ac0d4ef70a374ae31ee5d23b3c8fc.camel@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
		 <20250301-pinctrl-fltcon-suspend-v2-2-a7eef9bb443b@linaro.org>
	 <f7c0101ff26ac0d4ef70a374ae31ee5d23b3c8fc.camel@linaro.org>
Message-ID: <4f91fe1c5eed00e58a3587bceaef3e5e2a1124cf.camel@linaro.org>

On Thu, 2025-03-06 at 11:57 +0000, Andr? Draszik wrote:
> On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> > [...]
> > ?
> > -static void exynos_pinctrl_resume_bank(
> > -				struct samsung_pinctrl_drv_data *drvdata,
> > -				struct samsung_pin_bank *bank)
> > +void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> > ?{
> > ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> > ?	void __iomem *regs = bank->eint_base;
> > ?
> > -	if (clk_enable(bank->drvdata->pclk)) {
> > -		dev_err(bank->gpio_chip.parent,
> > -			"unable to enable clock for restoring state\n");
> > -		return;
> > +	if (bank->eint_type == EINT_TYPE_GPIO) {
> > +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> > +			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > +			?????? + bank->eint_offset), save->eint_con);
> > +		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> > +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +			?????? + 2 * bank->eint_offset), save->eint_fltcon0);
> > +		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> > +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +			?????? + 2 * bank->eint_offset + 4),
> > +			?????? save->eint_fltcon1);

The indent on this last line is a bit off.

> > +		pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> > +			 readl(regs + bank->irq_chip->eint_mask
> > +			?????? + bank->eint_offset), save->eint_mask);
> > +
> > +		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> > +		?????? + bank->eint_offset);
> > +		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +		?????? + 2 * bank->eint_offset);
> > +		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +		?????? + 2 * bank->eint_offset + 4);
> > +		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> > +		?????? + bank->eint_offset);
> > ?	}
> > -
> > -	pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> > -			readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > -			+ bank->eint_offset), save->eint_con);
> > -	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> > -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -			+ 2 * bank->eint_offset), save->eint_fltcon0);
> > -	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> > -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
> > -	pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> > -			readl(regs + bank->irq_chip->eint_mask
> > -			+ bank->eint_offset), save->eint_mask);
> > -
> > -	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> > -						+ bank->eint_offset);
> > -	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -						+ 2 * bank->eint_offset);
> > -	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -						+ 2 * bank->eint_offset + 4);
> > -	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> > -						+ bank->eint_offset);
> > -
> > -	clk_disable(bank->drvdata->pclk);
> > ?}
> > ?
> > -static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
> > -					?? struct samsung_pin_bank *bank)
> > +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
> > ?{
> > ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> > ?	void __iomem *regs = bank->eint_base;
> > ?
> > -	if (clk_enable(bank->drvdata->pclk)) {
> > -		dev_err(bank->gpio_chip.parent,
> > -			"unable to enable clock for restoring state\n");
> > -		return;
> > +	if (bank->eint_type == EINT_TYPE_GPIO) {
> > +		/* exynosautov920 has eint_con_offset for all but one bank */
> > +		if (!bank->eint_con_offset)
> > +			exynos_pinctrl_resume(bank);
> > +
> > +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> > +			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
> > +			?????? save->eint_con);

and here

Cheers,
Andre'



From andre.draszik at linaro.org  Thu Mar  6 07:12:32 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 15:12:32 +0000
Subject: [PATCH v2 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-3-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
	 <20250301-pinctrl-fltcon-suspend-v2-3-a7eef9bb443b@linaro.org>
Message-ID: <5fe34e1193a167c24c7af900f5b7cf85140d66e0.camel@linaro.org>

On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> gs101 differs to other SoCs in that fltcon1 register doesn't
> always exist. Additionally the offset of fltcon0 is not fixed
> and needs to use the newly added eint_fltcon_offset variable.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> Cc: stable at vger.kernel.org
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
> ?drivers/pinctrl/samsung/pinctrl-exynos.c?????? | 71 ++++++++++++++++++++++++++
> ?drivers/pinctrl/samsung/pinctrl-exynos.h?????? |? 2 +
> ?3 files changed, 85 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> index 57c98d2451b5..fca447ebc5f5 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> @@ -1455,15 +1455,15 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
> ?		.pin_banks	= gs101_pin_alive,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_alive),
> ?		.eint_wkup_init = exynos_eint_wkup_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	}, {
> ?		/* pin banks of gs101 pin-controller (FAR_ALIVE) */
> ?		.pin_banks	= gs101_pin_far_alive,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_far_alive),
> ?		.eint_wkup_init = exynos_eint_wkup_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	}, {
> ?		/* pin banks of gs101 pin-controller (GSACORE) */
> ?		.pin_banks	= gs101_pin_gsacore,
> @@ -1477,29 +1477,29 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
> ?		.pin_banks	= gs101_pin_peric0,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_peric0),
> ?		.eint_gpio_init = exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	}, {
> ?		/* pin banks of gs101 pin-controller (PERIC1) */
> ?		.pin_banks	= gs101_pin_peric1,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_peric1),
> ?		.eint_gpio_init = exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume	= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	}, {
> ?		/* pin banks of gs101 pin-controller (HSI1) */
> ?		.pin_banks	= gs101_pin_hsi1,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi1),
> ?		.eint_gpio_init = exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	}, {
> ?		/* pin banks of gs101 pin-controller (HSI2) */
> ?		.pin_banks	= gs101_pin_hsi2,
> ?		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi2),
> ?		.eint_gpio_init = exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= gs101_pinctrl_suspend,
> +		.resume		= gs101_pinctrl_resume,
> ?	},
> ?};
> ?
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
> index d65a9fba0781..ddc7245ec2e5 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
> @@ -801,6 +801,41 @@ void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?	}
> ?}
> ?
> +void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
> +{
> +	struct exynos_eint_gpio_save *save = bank->soc_priv;
> +	const void __iomem *regs = bank->eint_base;
> +
> +	exynos_set_wakeup(bank);

As for patch 2, would be good to have this if / else, to make it more
obvious that this is conditional, too.

> +
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +				?????? + bank->eint_offset);
> +
> +		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET +
> +					?? bank->eint_fltcon_offset);

If there's another version, maybe align style where the '+'
is placed (end of line vs start of line). It seems this file
generally uses + at start of line.

> +
> +		/* fltcon1 register only exists for pins 4-7 */
> +		if (bank->nr_pins > 4)
> +			save->eint_fltcon1 = readl(regs +
> +						EXYNOS_GPIO_EFLTCON_OFFSET +
> +						bank->eint_fltcon_offset + 4);
> +
> +		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> +					+ bank->eint_offset);
> +
> +		pr_debug("%s: save???? con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save fltcon0 %#010x\n",
> +			 bank->name, save->eint_fltcon0);
> +		if (bank->nr_pins > 4)
> +			pr_debug("%s: save fltcon1 %#010x\n",
> +				 bank->name, save->eint_fltcon1);
> +		pr_debug("%s: save??? mask %#010x\n",
> +			 bank->name, save->eint_mask);
> +	}
> +}
> +
> ?void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> @@ -820,6 +855,42 @@ void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?	}
> ?}
> ?
> +void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
> +{
> +	struct exynos_eint_gpio_save *save = bank->soc_priv;
> +
> +	void __iomem *regs = bank->eint_base;
> +	void __iomem *eint_fltcfg0 = regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +		???? + bank->eint_fltcon_offset;
> +
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +			?????? + bank->eint_offset), save->eint_con);
> +
> +		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> +			 readl(eint_fltcfg0), save->eint_fltcon0);
> +
> +		/* fltcon1 register only exists for pins 4-7 */
> +		if (bank->nr_pins > 4) {
> +			pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> +				 readl(eint_fltcfg0 + 4), save->eint_fltcon1);
> +		}

If there's another version, braces are not needed here.

Cheers,
Andre'


> +		pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->irq_chip->eint_mask
> +			?????? + bank->eint_offset), save->eint_mask);
> +
> +		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> +		?????? + bank->eint_offset);
> +		writel(save->eint_fltcon0, eint_fltcfg0);
> +
> +		if (bank->nr_pins > 4)
> +			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
> +		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> +		?????? + bank->eint_offset);
> +	}
> +}
> +
> ?void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
> index 35c2bc4ea488..773f161a82a3 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.h
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
> @@ -225,6 +225,8 @@ void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
> ?void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
> ?void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
> ?void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
> +void gs101_pinctrl_suspend(struct samsung_pin_bank *bank);
> +void gs101_pinctrl_resume(struct samsung_pin_bank *bank);
> ?struct samsung_retention_ctrl *
> ?exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
> ?		????? const struct samsung_retention_data *data);
> 



From jonas at kwiboo.se  Thu Mar  6 07:16:09 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 16:16:09 +0100
Subject: [PATCH v2 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528
 SoC
In-Reply-To: <20250306150017.488975-2-amadeus@jmu.edu.cn>
References: <20250306150017.488975-1-amadeus@jmu.edu.cn>
 <20250306150017.488975-2-amadeus@jmu.edu.cn>
Message-ID: <281b8025-8288-4274-b863-f091c05cbabe@kwiboo.se>

Hi Chukun,

On 2025-03-06 16:00, Chukun Pan wrote:
> Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
> Add SCMI clk for CPU, GPU and RNG will also use it.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 33 ++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index b1713ed4d7e2..476b83f98834 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -59,6 +59,9 @@ cpu0: cpu at 0 {
>  			reg = <0x0>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			assigned-clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			assigned-clock-rates = <1200000000>;

This is new compared to v1, please add operating-points instead.
cpu_pvtpll is already initialized to 1.2 GHz by firmware, see e.g. [1].

[1] https://lore.kernel.org/u-boot/20250123224844.3104592-5-jonas at kwiboo.se/

Regards,
Jonas

>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -66,6 +69,7 @@ cpu1: cpu at 1 {
>  			reg = <0x1>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
>  		};
>  
>  		cpu2: cpu at 2 {
> @@ -73,6 +77,7 @@ cpu2: cpu at 2 {
>  			reg = <0x2>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
>  		};
>  
>  		cpu3: cpu at 3 {
> @@ -80,6 +85,22 @@ cpu3: cpu at 3 {
>  			reg = <0x3>;
>  			device_type = "cpu";
>  			enable-method = "psci";
> +			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +		};
> +	};
> +
> +	firmware {
> +		scmi: scmi {
> +			compatible = "arm,scmi-smc";
> +			arm,smc-id = <0x82000010>;
> +			shmem = <&scmi_shmem>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			scmi_clk: protocol at 14 {
> +				reg = <0x14>;
> +				#clock-cells = <1>;
> +			};
>  		};
>  	};
>  
> @@ -88,6 +109,18 @@ psci {
>  		method = "smc";
>  	};
>  
> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		scmi_shmem: shmem at 10f000 {
> +			compatible = "arm,scmi-shmem";
> +			reg = <0x0 0x0010f000 0x0 0x100>;
> +			no-map;
> +		};
> +	};
> +
>  	timer {
>  		compatible = "arm,armv8-timer";
>  		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,



From robin.murphy at arm.com  Thu Mar  6 07:28:26 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 6 Mar 2025 15:28:26 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <20250228170006.390100-3-kristina.martsenko@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
Message-ID: <03dc25a3-c8a6-443b-ade7-2d3f69f2d0f4@arm.com>

On 28/02/2025 5:00 pm, Kristina Mart?enko wrote:
> A subsequent patch will use CPY* instructions to copy between user and
> kernel memory. Add handling for PAN faults caused by an intended kernel
> memory access erroneously accessing user memory, in order to make it
> easier to debug kernel bugs and to keep the same behavior as with
> regular loads/stores.

I'd be tempted to fold the search_exception_tables() call into 
insn_may_access_user() itself, but either way,

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

> Signed-off-by: Kristina Mart?enko <kristina.martsenko at arm.com>
> ---
>   arch/arm64/include/asm/extable.h |  3 +++
>   arch/arm64/mm/extable.c          | 11 +++++++++++
>   arch/arm64/mm/fault.c            |  4 +++-
>   3 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h
> index 5892b8977710..0a8cb2015c97 100644
> --- a/arch/arm64/include/asm/extable.h
> +++ b/arch/arm64/include/asm/extable.h
> @@ -33,6 +33,9 @@ do {							\
>   	(b)->data = (tmp).data;				\
>   } while (0)
>   
> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> +				  unsigned long esr);
> +
>   #ifdef CONFIG_BPF_JIT
>   bool ex_handler_bpf(const struct exception_table_entry *ex,
>   		    struct pt_regs *regs);
> diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
> index afb5241e4d91..f137596dda88 100644
> --- a/arch/arm64/mm/extable.c
> +++ b/arch/arm64/mm/extable.c
> @@ -20,6 +20,17 @@ static bool cpy_faulted_on_uaccess(const struct exception_table_entry *ex,
>   	return uaccess_is_write == fault_on_write;
>   }
>   
> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> +				  unsigned long esr)
> +{
> +	switch (ex->type) {
> +	case EX_TYPE_UACCESS_CPY:
> +		return cpy_faulted_on_uaccess(ex, esr);
> +	default:
> +		return true;
> +	}
> +}
> +
>   static inline unsigned long
>   get_ex_fixup(const struct exception_table_entry *ex)
>   {
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index da4854fc6150..c2f14f9c2d92 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -553,6 +553,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
>   	unsigned int mm_flags = FAULT_FLAG_DEFAULT;
>   	unsigned long addr = untagged_addr(far);
>   	struct vm_area_struct *vma;
> +	const struct exception_table_entry *ex;
>   	int si_code;
>   	int pkey = -1;
>   
> @@ -606,7 +607,8 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
>   			die_kernel_fault("execution of user memory",
>   					 addr, esr, regs);
>   
> -		if (!search_exception_tables(regs->pc))
> +		ex = search_exception_tables(regs->pc);
> +		if (!ex || !extable_insn_may_access_user(ex, esr))
>   			die_kernel_fault("access to user memory outside uaccess routines",
>   					 addr, esr, regs);
>   	}


From robin.murphy at arm.com  Thu Mar  6 07:23:19 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 6 Mar 2025 15:23:19 +0000
Subject: [PATCH v2 1/3] arm64: extable: Add fixup handling for uaccess
 CPY* instructions
In-Reply-To: <20250228170006.390100-2-kristina.martsenko@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-2-kristina.martsenko@arm.com>
Message-ID: <9d9569fa-79f5-4603-a4b4-98577006498e@arm.com>

On 28/02/2025 5:00 pm, Kristina Mart?enko wrote:
> A subsequent patch will use CPY* instructions to copy between user and
> kernel memory. Add a new exception fixup type to avoid fixing up faults
> on kernel memory accesses, in order to make it easier to debug kernel
> bugs and to keep the same behavior as with regular loads/stores.

Trusting my "the rest looks OK to me" from last time since I've already 
paged the details back out again... :)

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

> Signed-off-by: Kristina Mart?enko <kristina.martsenko at arm.com>
> ---
>   arch/arm64/include/asm/asm-extable.h | 10 +++++++++-
>   arch/arm64/include/asm/extable.h     |  2 +-
>   arch/arm64/mm/extable.c              | 25 ++++++++++++++++++++++++-
>   arch/arm64/mm/fault.c                |  2 +-
>   4 files changed, 35 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/asm-extable.h b/arch/arm64/include/asm/asm-extable.h
> index b8a5861dc7b7..292f2687a12e 100644
> --- a/arch/arm64/include/asm/asm-extable.h
> +++ b/arch/arm64/include/asm/asm-extable.h
> @@ -9,7 +9,8 @@
>   #define EX_TYPE_BPF			1
>   #define EX_TYPE_UACCESS_ERR_ZERO	2
>   #define EX_TYPE_KACCESS_ERR_ZERO	3
> -#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD	4
> +#define EX_TYPE_UACCESS_CPY		4
> +#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD	5
>   
>   /* Data fields for EX_TYPE_UACCESS_ERR_ZERO */
>   #define EX_DATA_REG_ERR_SHIFT	0
> @@ -23,6 +24,9 @@
>   #define EX_DATA_REG_ADDR_SHIFT	5
>   #define EX_DATA_REG_ADDR	GENMASK(9, 5)
>   
> +/* Data fields for EX_TYPE_UACCESS_CPY */
> +#define EX_DATA_UACCESS_WRITE	BIT(0)
> +
>   #ifdef __ASSEMBLY__
>   
>   #define __ASM_EXTABLE_RAW(insn, fixup, type, data)	\
> @@ -69,6 +73,10 @@
>   	.endif
>   	.endm
>   
> +	.macro		_asm_extable_uaccess_cpy, insn, fixup, uaccess_is_write
> +	__ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_UACCESS_CPY, \uaccess_is_write)
> +	.endm
> +
>   #else /* __ASSEMBLY__ */
>   
>   #include <linux/stringify.h>
> diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h
> index 72b0e71cc3de..5892b8977710 100644
> --- a/arch/arm64/include/asm/extable.h
> +++ b/arch/arm64/include/asm/extable.h
> @@ -45,5 +45,5 @@ bool ex_handler_bpf(const struct exception_table_entry *ex,
>   }
>   #endif /* !CONFIG_BPF_JIT */
>   
> -bool fixup_exception(struct pt_regs *regs);
> +bool fixup_exception(struct pt_regs *regs, unsigned long esr);
>   #endif
> diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
> index 228d681a8715..afb5241e4d91 100644
> --- a/arch/arm64/mm/extable.c
> +++ b/arch/arm64/mm/extable.c
> @@ -8,8 +8,18 @@
>   #include <linux/uaccess.h>
>   
>   #include <asm/asm-extable.h>
> +#include <asm/esr.h>
>   #include <asm/ptrace.h>
>   
> +static bool cpy_faulted_on_uaccess(const struct exception_table_entry *ex,
> +				   unsigned long esr)
> +{
> +	bool uaccess_is_write = FIELD_GET(EX_DATA_UACCESS_WRITE, ex->data);
> +	bool fault_on_write = esr & ESR_ELx_WNR;
> +
> +	return uaccess_is_write == fault_on_write;
> +}
> +
>   static inline unsigned long
>   get_ex_fixup(const struct exception_table_entry *ex)
>   {
> @@ -29,6 +39,17 @@ static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
>   	return true;
>   }
>   
> +static bool ex_handler_uaccess_cpy(const struct exception_table_entry *ex,
> +				   struct pt_regs *regs, unsigned long esr)
> +{
> +	/* Do not fix up faults on kernel memory accesses */
> +	if (!cpy_faulted_on_uaccess(ex, esr))
> +		return false;
> +
> +	regs->pc = get_ex_fixup(ex);
> +	return true;
> +}
> +
>   static bool
>   ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
>   				  struct pt_regs *regs)
> @@ -56,7 +77,7 @@ ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
>   	return true;
>   }
>   
> -bool fixup_exception(struct pt_regs *regs)
> +bool fixup_exception(struct pt_regs *regs, unsigned long esr)
>   {
>   	const struct exception_table_entry *ex;
>   
> @@ -70,6 +91,8 @@ bool fixup_exception(struct pt_regs *regs)
>   	case EX_TYPE_UACCESS_ERR_ZERO:
>   	case EX_TYPE_KACCESS_ERR_ZERO:
>   		return ex_handler_uaccess_err_zero(ex, regs);
> +	case EX_TYPE_UACCESS_CPY:
> +		return ex_handler_uaccess_cpy(ex, regs, esr);
>   	case EX_TYPE_LOAD_UNALIGNED_ZEROPAD:
>   		return ex_handler_load_unaligned_zeropad(ex, regs);
>   	}
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index ef63651099a9..da4854fc6150 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -375,7 +375,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
>   	 * Are we prepared to handle this kernel fault?
>   	 * We are almost certainly not prepared to handle instruction faults.
>   	 */
> -	if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
> +	if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
>   		return;
>   
>   	if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs),


From linux at armlinux.org.uk  Thu Mar  6 07:23:53 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 6 Mar 2025 15:23:53 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE LPI
 reset issues
Message-ID: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>

Hi,

This is a second approach to solving the STMMAC reset issues caused by
the lack of receive clock from the PHY where the media is in low power
mode with a PHY that supports receive clock-stop.

The first approach centred around only addressing the issue in the
resume path, but it seems to also happen when the platform glue module
is removed and re-inserted (Jon - can you check whether that's also
the case for you please?)

As this is more targetted, I've dropped the patches from this series
which move the call to phylink_resume(), so the link may still come
up too early on resume - but that's something I also intend to fix.

This is experimental - so I value test reports for this change.

As mentioned recently, the reset timeout will only occur if the PHY
receive clock is actually stopped at the moment that stmmac_reset()
is called and remains stopped for the duration of the timeout.
Network activity can wake up the link, causing the PHY to restart
its receive clock and allow reset to complete. So, careful testing
with and without these patches is necessary.

v2: add EXPORT_SYMBOL_GPL(), fix if() statement, add kerneldoc

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |  3 ++
 drivers/net/phy/phylink.c                         | 54 ++++++++++++++++++++++-
 include/linux/phylink.h                           |  3 ++
 3 files changed, 59 insertions(+), 1 deletion(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Thu Mar  6 07:23:51 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 06 Mar 2025 15:23:51 +0000
Subject: [PATCH net-next v2 1/2] net: phylink: add functions to block/unblock
 rx clock stop
In-Reply-To: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
Message-ID: <E1tqD4h-005Xx0-Ub@rmk-PC.armlinux.org.uk>

Some MACs require the PHY receive clock to be running to complete setup
actions. This may fail if the PHY has negotiated EEE, the MAC supports
receive clock stop, and the link has entered LPI state. Provide a pair
of APIs that MAC drivers can use to temporarily block the PHY disabling
the receive clock.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 59 +++++++++++++++++++++++++++++++++++++++
 include/linux/phylink.h   |  3 ++
 2 files changed, 62 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3b186ab3854..d0926f0096b1 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -88,6 +88,7 @@ struct phylink {
 	bool mac_enable_tx_lpi;
 	bool mac_tx_clk_stop;
 	u32 mac_tx_lpi_timer;
+	u8 mac_rx_clk_stop_blocked;
 
 	struct sfp_bus *sfp_bus;
 	bool sfp_may_have_phy;
@@ -2592,6 +2593,64 @@ void phylink_stop(struct phylink *pl)
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
+/**
+ * phylink_rx_clk_stop_block() - block PHY ability to stop receive clock in LPI
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Disable the PHY's ability to stop the receive clock while the receive path
+ * is in EEE LPI state, until the number of calls to phylink_rx_clk_stop_block()
+ * are balanced by calls to phylink_rx_clk_stop_unblock().
+ */
+void phylink_rx_clk_stop_block(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Disable PHY receive clock stop if this is the first time this
+	 * function has been called and clock-stop was previously enabled.
+	 */
+	if (pl->mac_rx_clk_stop_blocked++ == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, false);
+}
+EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_block);
+
+/**
+ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * All calls to phylink_rx_clk_stop_block() must be balanced with a
+ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
+ * ability to stop the receive clock when the receive path is in EEE LPI mode.
+ */
+void phylink_rx_clk_stop_unblock(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == 0) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Re-enable PHY receive clock stop if the number of unblocks matches
+	 * the number of calls to the block function above.
+	 */
+	if (--pl->mac_rx_clk_stop_blocked == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, true);
+}
+EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_unblock);
+
 /**
  * phylink_suspend() - handle a network device suspend event
  * @pl: a pointer to a &struct phylink returned from phylink_create()
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 08df65f6867a..249c437d6b7b 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -698,6 +698,9 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
 void phylink_start(struct phylink *);
 void phylink_stop(struct phylink *);
 
+void phylink_rx_clk_stop_block(struct phylink *);
+void phylink_rx_clk_stop_unblock(struct phylink *);
+
 void phylink_suspend(struct phylink *pl, bool mac_wol);
 void phylink_resume(struct phylink *pl);
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Thu Mar  6 07:23:57 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 06 Mar 2025 15:23:57 +0000
Subject: [PATCH net-next v2 2/2] net: stmmac: block PHY rx clock-stop over
 reset
In-Reply-To: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
Message-ID: <E1tqD4n-005Xx6-3l@rmk-PC.armlinux.org.uk>

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6924df893e42..037039a9a33b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3096,7 +3096,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
 		priv->plat->dma_cfg->atds = 1;
 
+	/* Note that the PHY clock must be running for reset to complete. */
+	phylink_rx_clk_stop_block(priv->phylink);
 	ret = stmmac_reset(priv, priv->ioaddr);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 	if (ret) {
 		netdev_err(priv->dev, "Failed to reset the dma\n");
 		return ret;
-- 
2.30.2



From james.quinlan at broadcom.com  Thu Mar  6 07:24:56 2025
From: james.quinlan at broadcom.com (Jim Quinlan)
Date: Thu, 6 Mar 2025 10:24:56 -0500
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of regulator_bulk_get()
In-Reply-To: <CA+-6iNwsCzf30a0vbgStqA+DCyBnk3bGwoXNv0UNYOThE1Us6Q@mail.gmail.com>
References: <20250214173944.47506-5-james.quinlan@broadcom.com>
 <20250303184011.GA172021@bhelgaas> <CA+-6iNwsCzf30a0vbgStqA+DCyBnk3bGwoXNv0UNYOThE1Us6Q@mail.gmail.com>
Message-ID: <CA+-6iNyXeXhqzwbV+pcizpyXg-c-gihcLEtPv1s1uczdNN_VOQ@mail.gmail.com>

On Tue, Mar 4, 2025 at 9:49?AM Jim Quinlan <james.quinlan at broadcom.com> wrote:
>
> On Mon, Mar 3, 2025 at 1:40?PM Bjorn Helgaas <helgaas at kernel.org> wrote:
> >
> > On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > > If regulator_bulk_get() returns an error, no regulators are created and we
> > > need to set their number to zero.  If we do not do this and the PCIe
> > > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> > >
> > > Also print out the error value, as we cannot return an error upwards as
> > > Linux will WARN on an error from add_bus().
> > >
> > > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > > ---
> > >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > index e0b20f58c604..56b49d3cae19 100644
> > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> > >
> > >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> > >               if (ret) {
> > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > > +                     pcie->sr = NULL;
> >
> > Is alloc_subdev_regulators() buying us something useful?  It seems
> > like it would be simpler to have:
> >
> >   struct brcm_pcie {
> >     ...
> >     struct regulator_bulk_data supplies[3];
> >     ...
> >   };
> >
> > I think that's what most callers of devm_regulator_bulk_get() do.
>
> Ack.

Hi Bjorn,

Manivannan stated that this series has already been merged.  So shall
I implement your comments with a commit sometime in the future?

Thanks,
Jim Quinlan
Broadcom STB/CM

>
> Jim Quinlan
> Broadcom STB/CM
> >
> > >                       goto no_regulators;
> > >               }
> > >
> > > --
> > > 2.43.0
> > >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4197 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/66440820/attachment.p7s>

From andre.draszik at linaro.org  Thu Mar  6 07:26:28 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 15:26:28 +0000
Subject: [PATCH v2 4/4] pinctrl: samsung: Add filter selection support
 for alive bank on gs101
In-Reply-To: <20250301-pinctrl-fltcon-suspend-v2-4-a7eef9bb443b@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
	 <20250301-pinctrl-fltcon-suspend-v2-4-a7eef9bb443b@linaro.org>
Message-ID: <ac831e724393dd928d3e62a4cfe2d9d30af7a081.camel@linaro.org>

On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> Newer Exynos based SoCs have a filter selection bitfield in the filter
> configuration registers on alive bank pins. This allows the selection of
> a digital or analog delay filter for each pin. Add support for selecting
> and enabling the filter.
> 
> On suspend we set the analog filter to all pins in the bank (as the
> digital filter relies on a clock). On resume the digital filter is
> reapplied to all pins in the bank. The digital filter is working via
> a clock and has an adjustable filter delay flt_width bitfield, whereas
> the analog filter uses a fixed delay.
> 
> The filter determines to what extent signal fluctuations received through
> the pad are considered glitches.
> 
> The code path can be exercised using
> echo mem > /sys/power/state
> And then wake the device using a eint gpio
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> 
> Changes since v1:
> * Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
> * Move filter config comment to header (Andre)
> * Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
> * Remove misleading old comment (Andre)
> * Refactor exynos_eint_update_flt_reg() into a loop (Andre)
> 
> Note: this patch was previously sent as part of the initial gs101/ Pixel 6
> series and was dropped in v6. This new version incorporates the review
> feedback from Sam Protsenko here in v5.
> 
> Link: https://lore.kernel.org/all/20231201160925.3136868-1-peter.griffin at linaro.org/T/#m79ced98939e895c840d812c8b4c2b3f33ce604c8
> 
> Changes since previous version
> * Drop fltcon_type enum and use bool eint_flt_selectable (Sam)
> * Refactor and add exynos_eint_update_flt_reg() (Sam)
> * Rename function to exynos_eint_set_filter() for easier readability (Sam)
> * Remove comments and `if bank->fltcon_type != FLT_DEFAULT)` checks and indentation (Sam)
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos.c | 35 ++++++++++++++++++++++++++++++++
> ?drivers/pinctrl/samsung/pinctrl-exynos.h | 21 +++++++++++++++++++
> ?2 files changed, 56 insertions(+)
> 
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
> index ddc7245ec2e5..4c467651b034 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
> @@ -369,6 +369,39 @@ struct exynos_eint_gpio_save {
> ?	u32 eint_mask;
> ?};
> ?
> +static void exynos_eint_update_flt_reg(void __iomem *reg, int cnt, int con)
> +{
> +	unsigned int val, shift;
> +	int i;
> +
> +	val = readl(reg);
> +	for (i = 0; i < cnt; i++) {
> +		shift = i * EXYNOS_FLTCON_LEN;
> +		val |= con << shift;

EXYNOS_FLTCON_ANALOG == 0, so this code still needs to clear
bit 6 to undo a previous enabling of digital filter:

    val &= ~(EXYNOS_FLTCON_DIGITAL << shift);
    val |= con << shift;


> +	}
> +	writel(val, reg);
> +}
> +
> +/*
> + * Set the desired filter (digital or analog delay) and enable it to
> + * every pin in the bank. Note the filter selection bitfield is only
> + * found on alive banks. The filter determines to what extent signal
> + * fluctuations received through the pad are considered glitches.
> + */
> +static void exynos_eint_set_filter(struct samsung_pin_bank *bank, int filter)
> +{
> +	unsigned int off = EXYNOS_GPIO_EFLTCON_OFFSET + bank->eint_fltcon_offset;
> +	void __iomem *reg = bank->drvdata->virt_base + off;
> +	unsigned int con = EXYNOS_FLTCON_EN | filter;
> +
> +	if (bank->eint_type != EINT_TYPE_WKUP)
> +		return;
> +
> +	for (int n = 0; n < bank->nr_pins; n += 4)
> +		exynos_eint_update_flt_reg(reg + n,
> +					?? min(bank->nr_pins - n, 4), con);
> +}
> +
> ?/*
> ? * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
> ? * @d: driver data of samsung pinctrl driver.
> @@ -834,6 +867,7 @@ void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?		pr_debug("%s: save??? mask %#010x\n",
> ?			 bank->name, save->eint_mask);
> ?	}
> +	exynos_eint_set_filter(bank, EXYNOS_FLTCON_ANALOG);

Similar to patch 2, might be nicer to have this all if / else if to
make it more obvious that set_filter() is not unconditional.


> ?}
> ?
> ?void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> @@ -889,6 +923,7 @@ void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
> ?		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> ?		?????? + bank->eint_offset);
> ?	}
> +	exynos_eint_set_filter(bank, EXYNOS_FLTCON_DIGITAL);

dito.

Cheers,
Andre'

> ?}
> ?
> ?void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
> index 773f161a82a3..203d4b76a956 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.h
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
> @@ -52,6 +52,27 @@
> ?#define EXYNOS_EINT_MAX_PER_BANK	8
> ?#define EXYNOS_EINT_NR_WKUP_EINT
> ?
> +/*
> + * EINT filter configuration register (on alive banks) has
> + * the following layout.
> + *
> + * BitfieldName[PinNum][Bit:Bit]
> + * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24]
> + * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16]
> + * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8]
> + * FLT_EN[0][7]? FLT_SEL[0][6]? FLT_WIDTH[0][5:0]
> + *
> + * FLT_EN	0x0 = Disable, 0x1=Enable
> + * FLT_SEL	0x0 = Analog delay filter, 0x1 Digital filter (clock count)
> + * FLT_WIDTH	Filtering width. Valid when FLT_SEL is 0x1
> + */
> +
> +#define EXYNOS_FLTCON_EN		BIT(7)
> +#define EXYNOS_FLTCON_DIGITAL		BIT(6)
> +#define EXYNOS_FLTCON_ANALOG		(0 << 6)
> +#define EXYNOS_FLTCON_MASK		GENMASK(7, 0)
> +#define EXYNOS_FLTCON_LEN		8
> +
> ?#define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
> ?	{						\
> ?		.type		= &bank_type_off,	\
> 



From thierry.bultel.yh at bp.renesas.com  Thu Mar  6 07:24:47 2025
From: thierry.bultel.yh at bp.renesas.com (Thierry Bultel)
Date: Thu,  6 Mar 2025 16:24:47 +0100
Subject: [PATCH v4 13/13] arm64: defconfig: Enable Renesas RZ/T2H serial SCI
In-Reply-To: <20250306152451.2356762-1-thierry.bultel.yh@bp.renesas.com>
References: <20250306152451.2356762-1-thierry.bultel.yh@bp.renesas.com>
Message-ID: <20250306152451.2356762-14-thierry.bultel.yh@bp.renesas.com>

Selects RZ/T2H (aka r9a09g077) SCI (serial) specific code.

Signed-off-by: Thierry Bultel <thierry.bultel.yh at bp.renesas.com>
---
Changes v3->v4:
   - Remove CONFIG_ARCH_R9A09G077=y
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..1403848d659e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -492,6 +492,7 @@ CONFIG_SERIAL_TEGRA_TCU=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_RZ_SCI=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_QCOM_GENI=y
-- 
2.43.0



From cki-project at redhat.com  Thu Mar  6 07:32:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 15:32:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <50385.125030610320703562@us-mta-517.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703216704

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703216704-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From linux at armlinux.org.uk  Thu Mar  6 07:44:30 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 6 Mar 2025 15:44:30 +0000
Subject: [PATCH RFC 0/5] net: stmmac: fix resume failures due to RX clock
In-Reply-To: <f783cf9c-9f79-4680-a6e9-d078abbd96ec@nvidia.com>
References: <Z8B4tVd4nLUKXdQ4@shell.armlinux.org.uk>
 <f783cf9c-9f79-4680-a6e9-d078abbd96ec@nvidia.com>
Message-ID: <Z8nC3vvZWAl5_8WZ@shell.armlinux.org.uk>

On Thu, Mar 06, 2025 at 11:30:53AM +0000, Jon Hunter wrote:
> Hi Russell,
> 
> On 27/02/2025 14:37, Russell King (Oracle) wrote:
> > Hi,
> > 
> > This series is likely dependent on the "net: stmmac: cleanup transmit
> > clock setting" series which was submitted earlier today.
> 
> I tested this series without the above on top of mainline and I still saw
> some issues with suspend. However, when testing this on top of -next (which
> has the referenced series) it works like a charm. So yes it does appear to
> be dependent indeed.
> 
> I have tested this on Tegra186, Tegra194 and Tegra234 with -next and all are
> working fine. So with that feel free to add my ...
> 
> Tested-by: Jon Hunter <jonathanh at nvidia.com>

Hi Jon,

I came up with an alternative approach which should make this safer -
for example, if the PHY remains linked with the partner over an
ifdown or module remove/re-insert.

Please see v2 of "net: stmmac: approach 2 to solve EEE LPI reset
issues" which replaces this series.

https://lore.kernel.org/r/Z8m-CRucPxDW5zZK at shell.armlinux.org.uk

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From robin.murphy at arm.com  Thu Mar  6 07:47:27 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 6 Mar 2025 15:47:27 +0000
Subject: [PATCH v2 3/3] arm64: lib: Use MOPS for usercopy routines
In-Reply-To: <20250228170006.390100-4-kristina.martsenko@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-4-kristina.martsenko@arm.com>
Message-ID: <e432f571-67e4-4ea2-982d-096fb1c35f77@arm.com>

On 28/02/2025 5:00 pm, Kristina Mart?enko wrote:
> Similarly to what was done with the memcpy() routines, make
> copy_to_user(), copy_from_user() and clear_user() also use the Armv8.8
> FEAT_MOPS instructions.
> 
> Both MOPS implementation options (A and B) are supported, including
> asymmetric systems. The exception fixup code fixes up the registers
> according to the option used.
> 
> In case of a fault the routines return precisely how much was not copied
> (as required by the comment in include/linux/uaccess.h), as unprivileged
> versions of CPY/SET are guaranteed not to have written past the
> addresses reported in the GPRs.
> 
> The MOPS instructions could possibly be inlined into callers (and
> patched to branch to the generic implementation if not detected;
> similarly to what x86 does), but as a first step this patch just uses
> them in the out-of-line routines.

I still think it's cleaner and demonstrably simpler to keep the 
clear_user() implementations independent (especially with a mind to 
future inlining), but we're clearly well into personal preferences on 
that, so FWIW,

Acked-by: Robin Murphy <robin.murphy at arm.com>

> Signed-off-by: Kristina Mart?enko <kristina.martsenko at arm.com>
> ---
>   arch/arm64/include/asm/asm-uaccess.h |  4 ++++
>   arch/arm64/lib/clear_user.S          | 25 +++++++++++++++++++++----
>   arch/arm64/lib/copy_from_user.S      | 10 ++++++++++
>   arch/arm64/lib/copy_template.S       | 10 ++++++++++
>   arch/arm64/lib/copy_to_user.S        | 10 ++++++++++
>   5 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h
> index 5b6efe8abeeb..9148f5a31968 100644
> --- a/arch/arm64/include/asm/asm-uaccess.h
> +++ b/arch/arm64/include/asm/asm-uaccess.h
> @@ -61,6 +61,10 @@ alternative_else_nop_endif
>   9999:	x;					\
>   	_asm_extable_uaccess	9999b, l
>   
> +#define USER_CPY(l, uaccess_is_write, x...)	\
> +9999:	x;					\
> +	_asm_extable_uaccess_cpy 9999b, l, uaccess_is_write
> +
>   /*
>    * Generate the assembly for LDTR/STTR with exception table entries.
>    * This is complicated as there is no post-increment or pair versions of the
> diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S
> index a5a5f5b97b17..de9a303b6ad0 100644
> --- a/arch/arm64/lib/clear_user.S
> +++ b/arch/arm64/lib/clear_user.S
> @@ -17,14 +17,27 @@
>    * Alignment fixed up by hardware.
>    */
>   
> -	.p2align 4
> -	// Alignment is for the loop, but since the prologue (including BTI)
> -	// is also 16 bytes we can keep any padding outside the function
>   SYM_FUNC_START(__arch_clear_user)
>   	add	x2, x0, x1
> +
> +#ifdef CONFIG_AS_HAS_MOPS
> +	.arch_extension mops
> +alternative_if_not ARM64_HAS_MOPS
> +	b	.Lno_mops
> +alternative_else_nop_endif
> +
> +USER(9f, setpt	[x0]!, x1!, xzr)
> +USER(6f, setmt	[x0]!, x1!, xzr)
> +USER(6f, setet	[x0]!, x1!, xzr)
> +	mov	x0, #0
> +	ret
> +.Lno_mops:
> +#endif
> +
>   	subs	x1, x1, #8
>   	b.mi	2f
> -1:
> +
> +1:	.p2align 4
>   USER(9f, sttr	xzr, [x0])
>   	add	x0, x0, #8
>   	subs	x1, x1, #8
> @@ -47,6 +60,10 @@ USER(7f, sttrb	wzr, [x2, #-1])
>   	ret
>   
>   	// Exception fixups
> +6:	b.cs	9f
> +	// Registers are in Option A format
> +	add	x0, x0, x1
> +	b	9f
>   7:	sub	x0, x2, #5	// Adjust for faulting on the final byte...
>   8:	add	x0, x0, #4	// ...or the second word of the 4-7 byte case
>   9:	sub	x0, x2, x0
> diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
> index 34e317907524..400057d607ec 100644
> --- a/arch/arm64/lib/copy_from_user.S
> +++ b/arch/arm64/lib/copy_from_user.S
> @@ -52,6 +52,13 @@
>   	stp \reg1, \reg2, [\ptr], \val
>   	.endm
>   
> +	.macro cpy1 dst, src, count
> +	.arch_extension mops
> +	USER_CPY(9997f, 0, cpyfprt [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 0, cpyfmrt [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 0, cpyfert [\dst]!, [\src]!, \count!)
> +	.endm
> +
>   end	.req	x5
>   srcin	.req	x15
>   SYM_FUNC_START(__arch_copy_from_user)
> @@ -62,6 +69,9 @@ SYM_FUNC_START(__arch_copy_from_user)
>   	ret
>   
>   	// Exception fixups
> +9996:	b.cs	9997f
> +	// Registers are in Option A format
> +	add	dst, dst, count
>   9997:	cmp	dst, dstin
>   	b.ne	9998f
>   	// Before being absolutely sure we couldn't copy anything, try harder
> diff --git a/arch/arm64/lib/copy_template.S b/arch/arm64/lib/copy_template.S
> index 488df234c49a..7f2f5a0e2fb9 100644
> --- a/arch/arm64/lib/copy_template.S
> +++ b/arch/arm64/lib/copy_template.S
> @@ -40,6 +40,16 @@ D_l	.req	x13
>   D_h	.req	x14
>   
>   	mov	dst, dstin
> +
> +#ifdef CONFIG_AS_HAS_MOPS
> +alternative_if_not ARM64_HAS_MOPS
> +	b	.Lno_mops
> +alternative_else_nop_endif
> +	cpy1	dst, src, count
> +	b	.Lexitfunc
> +.Lno_mops:
> +#endif
> +
>   	cmp	count, #16
>   	/*When memory length is less than 16, the accessed are not aligned.*/
>   	b.lo	.Ltiny15
> diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
> index 802231772608..819f2e3fc7a9 100644
> --- a/arch/arm64/lib/copy_to_user.S
> +++ b/arch/arm64/lib/copy_to_user.S
> @@ -51,6 +51,13 @@
>   	user_stp 9997f, \reg1, \reg2, \ptr, \val
>   	.endm
>   
> +	.macro cpy1 dst, src, count
> +	.arch_extension mops
> +	USER_CPY(9997f, 1, cpyfpwt [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 1, cpyfmwt [\dst]!, [\src]!, \count!)
> +	USER_CPY(9996f, 1, cpyfewt [\dst]!, [\src]!, \count!)
> +	.endm
> +
>   end	.req	x5
>   srcin	.req	x15
>   SYM_FUNC_START(__arch_copy_to_user)
> @@ -61,6 +68,9 @@ SYM_FUNC_START(__arch_copy_to_user)
>   	ret
>   
>   	// Exception fixups
> +9996:	b.cs	9997f
> +	// Registers are in Option A format
> +	add	dst, dst, count
>   9997:	cmp	dst, dstin
>   	b.ne	9998f
>   	// Before being absolutely sure we couldn't copy anything, try harder


From cristian.marussi at arm.com  Thu Mar  6 07:47:27 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Thu, 6 Mar 2025 15:47:27 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8my4MZ-In0ibxVY@arm.com>
References: <Z8g8vhS9rqQ_ez48@google.com>
 <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com>
 <Z8my4MZ-In0ibxVY@arm.com>
Message-ID: <Z8nDj129ZVeZBVSp@pluto>

On Thu, Mar 06, 2025 at 02:36:16PM +0000, Catalin Marinas wrote:
> On Thu, Mar 06, 2025 at 11:09:33AM +0000, Alice Ryhl wrote:
> > On Wed, Mar 05, 2025 at 05:10:16PM +0000, Cristian Marussi wrote:
> > > On Wed, Mar 05, 2025 at 11:59:58AM +0000, Alice Ryhl wrote:
> > > > This was with a kernel running v6.13-rc3, but as far as I can tell, no
> > > > relevant changes have landed since v6.13-rc3. My tree *does* include
> > > > commit 295416091e44 ("firmware: arm_scmi: Fix slab-use-after-free in
> > > > scmi_bus_notifier()"). I've only seen this kmemleak report once, so it's
> > > > not happening consistently.
> > > > 
> > > > See below for the full kmemleak report.
> > > > 
> > > > Alice
> > > > 
> > > > $ sudo cat /sys/kernel/debug/kmemleak
> > > > unreferenced object 0xffffff8106c86000 (size 2048):
> > > >   comm "swapper/0", pid 1, jiffies 4294893094
> > > >   hex dump (first 32 bytes):
> > > >     02 00 00 00 10 00 00 00 c0 01 bc 03 81 ff ff ff  ................
> > > >     60 67 ba 03 81 ff ff ff 18 60 c8 06 81 ff ff ff  `g.......`......
> > > >   backtrace (crc feae9680):
> > > >     [<00000000197aa008>] kmemleak_alloc+0x34/0xa0
> > > >     [<0000000056fe02c9>] __kmalloc_cache_noprof+0x1e0/0x450
> > > >     [<00000000a8b3dfe1>] __scmi_device_create+0xb4/0x2b4
> > > >     [<000000008714917b>] scmi_device_create+0x40/0x194
> > > >     [<000000001818f3cf>] scmi_chan_setup+0x144/0x3b8
> > > >     [<00000000970bad38>] scmi_probe+0x584/0xa78
> > > >     [<000000002600d2fd>] platform_probe+0xbc/0xf0
> > > >     [<00000000f6f556b4>] really_probe+0x1b8/0x520
> > > >     [<00000000eed93d59>] __driver_probe_device+0xe0/0x1d8
> > > >     [<00000000d613b754>] driver_probe_device+0x6c/0x208
> > > >     [<00000000187a9170>] __driver_attach+0x168/0x328
> > > >     [<00000000e3ff1834>] bus_for_each_dev+0x14c/0x178
> > > >     [<00000000984a3176>] driver_attach+0x34/0x44
> > > >     [<00000000fc35bf2a>] bus_add_driver+0x1bc/0x358
> > > >     [<00000000747fce19>] driver_register+0xc0/0x1a0
> > > >     [<0000000081cb8754>] __platform_driver_register+0x40/0x50
> > > > unreferenced object 0xffffff8103bc01c0 (size 32):
> > > 
> > > I could not reproduce on my setup, even though I run a system with
> > > all the existent SCMI protocols (and related drivers) enabled (and
> > > so a lot of device creations) and a downstream test driver that causes
> > > even more SCMI devices to be created/destroyed at load/unload.
> > > 
> > > Coming down the path from scmi_chan_setup(), it seems something around
> > > transport devices creation, but it is not obvious to me where the leak
> > > could hide....
> > > 
> > > ...any particular setup on your side ? ...using LKMs, loading/unloading,
> > > any usage pattern that could help me reproduce ?
> > 
> > I looked into this a bit more, and actually it does happen consistently.
> > It's just that kmemleak doesn't report it until 10 minutes after
> > booting, so I did not notice it.
> 
> You can force the scanning with:
> 
>   echo scan > /sys/kernel/debug/kmemleak
> 
> Just do it a couple of times after boot, no need to wait 10 min for the
> default background scanning.
> 
> > user at rk3588-ci:~$ sudo cat /sys/kernel/debug/kmemleak
> > unreferenced object 0xffffff81068c0000 (size 2048):
> >   comm "swapper/0", pid 1, jiffies 4294893128
> >   hex dump (first 32 bytes):
> >     02 00 00 00 10 00 00 00 40 a3 7a 03 81 ff ff ff  ........ at .z.....
> >     60 c8 79 03 81 ff ff ff 18 00 8c 06 81 ff ff ff  `.y.............
> >   backtrace (crc 60df30fb):
> >     kmemleak_alloc+0x34/0xa0
> >     __kmalloc_cache_noprof+0x1e0/0x450
> >     __scmi_device_create+0xb4/0x2b4
> 
> Is this the kzalloc() for sizeof(*scmi_dev)? It's surprisingly large, I
> thought it would go for the kmalloc-1k slab as struct device is below
> this side, at least for my builds. Anyway...
> 
> >     scmi_device_create+0x40/0x194
> >     scmi_chan_setup+0x144/0x3b8
> >     scmi_probe+0x51c/0x9fc
> >     platform_probe+0xbc/0xf0
> >     really_probe+0x1b8/0x520
> >     __driver_probe_device+0xe0/0x1d8
> >     driver_probe_device+0x6c/0x208
> >     __driver_attach+0x168/0x328
> >     bus_for_each_dev+0x14c/0x178
> >     driver_attach+0x34/0x44
> >     bus_add_driver+0x1bc/0x358
> >     driver_register+0xc0/0x1a0
> >     __platform_driver_register+0x40/0x50
> > unreferenced object 0xffffff81037aa340 (size 32):
> >   comm "swapper/0", pid 1, jiffies 4294893128
> >   hex dump (first 32 bytes):
> >     5f 5f 73 63 6d 69 5f 74 72 61 6e 73 70 6f 72 74  __scmi_transport
> >     5f 64 65 76 69 63 65 5f 72 78 5f 31 30 00 ff ff  _device_rx_10...
> >   backtrace (crc 8dab7ca7):
> >     kmemleak_alloc+0x34/0xa0
> >     __kmalloc_node_track_caller_noprof+0x234/0x528
> >     kstrdup+0x48/0x80
> >     kstrdup_const+0x30/0x3c
> 
> These are referenced from the main structure above, so they'd be
> reported as leaks as well.
> 
> This loop in scmi_device_create() looks strange:
> 
> 	list_for_each_entry(rdev, phead, node) {
> 		struct scmi_device *sdev;
> 
> 		sdev = __scmi_device_create(np, parent,
> 					    rdev->id_table->protocol_id,
> 					    rdev->id_table->name);
> 		/* Report errors and carry on... */
> 		if (sdev)
> 			scmi_dev = sdev;
> 		else
> 			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
> 			       of_node_full_name(parent->of_node),
> 			       rdev->id_table->protocol_id,
> 			       rdev->id_table->name);
> 	}
> 
> We can override scmi_dev a few times in the loop and lose the previous
> sdev allocations. Is this intended?

Yes...it is weird..but by design I would say :P ...

...because this is called to instantiate one single device OR instantiate at
once all the multiple devices needed for a protocol: in this latter case it
returns just one of the created devices to signal success or NULL if all the
devices' creation failed....we dont need to keep the allocated devices references
anyway here since on success those devices are now referenced and kept on the
SCMI bus, so they can be searched/scanned/destroyed from there.

But maybe this is the crux of the matter, or what fools kmemleak...I
will try to reproduce again.

Thanks,
Cristian


From cki-project at redhat.com  Thu Mar  6 07:52:07 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 15:52:07 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <11579.125030610520902893@us-mta-605.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703259619

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703259619-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From Frank.Li at nxp.com  Thu Mar  6 07:58:15 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 10:58:15 -0500
Subject: [PATCH 1/1] dt-bindings: i2c: imx-lpi2c: add i.MX94 LPI2C
Message-ID: <20250306155815.110514-1-Frank.Li@nxp.com>

Add compatible string "fsl,imx94-lpi2c" for the i.MX94 chip, which is
backward compatible with i.MX7ULP. Set it to fall back to
"fsl,imx7ulp-lpi2c".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
index 1dcb9c78de3b5..969030a6f82ab 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
@@ -26,6 +26,7 @@ properties:
               - fsl,imx8qm-lpi2c
               - fsl,imx8ulp-lpi2c
               - fsl,imx93-lpi2c
+              - fsl,imx94-lpi2c
               - fsl,imx95-lpi2c
           - const: fsl,imx7ulp-lpi2c
 
-- 
2.34.1



From jbrunet at baylibre.com  Thu Mar  6 07:58:59 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 06 Mar 2025 16:58:59 +0100
Subject: [PATCH v3 5/6] ASoC: meson: s4: Add s4 tocodec driver
In-Reply-To: <20250228-audio_drvier-v3-5-dbfd30507e4c@amlogic.com> (jiebing
	chen via's message of "Fri, 28 Feb 2025 16:04:13 +0800")
References: <20250228-audio_drvier-v3-0-dbfd30507e4c@amlogic.com>
	<20250228-audio_drvier-v3-5-dbfd30507e4c@amlogic.com>
Message-ID: <1jfrjq5ews.fsf@starbuckisacylon.baylibre.com>

On Fri 28 Feb 2025 at 16:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:

> From: jiebing chen <jiebing.chen at amlogic.com>
>
> S4 tocodec support 8 lane to input, It need to enable
> bclk and mclk control bit when work
>
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  sound/soc/meson/g12a-toacodec.c | 51 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>
> diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
> index 531bb8707a3ec4c47814d6a0676d5c62c705da75..41eef9980059285275f0189a06469fc694775955 100644
> --- a/sound/soc/meson/g12a-toacodec.c
> +++ b/sound/soc/meson/g12a-toacodec.c
> @@ -41,6 +41,9 @@
>  #define  CTRL0_BCLK_SEL_LSB		4
>  #define  CTRL0_MCLK_SEL			GENMASK(2, 0)
>  
> +#define CTRL0_BCLK_ENABLE_SHIFT		30
> +#define CTRL0_MCLK_ENABLE_SHIFT		29
> +
>  #define TOACODEC_OUT_CHMAX		2
>  
>  struct g12a_toacodec {
> @@ -129,6 +132,10 @@ static const struct snd_kcontrol_new g12a_toacodec_out_enable =
>  	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
>  				    CTRL0_ENABLE_SHIFT, 1, 0);
>  
> +static const struct snd_kcontrol_new s4_toacodec_clk_enable =
> +	SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
> +			CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
> +
>  static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
>  	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
>  			 &g12a_toacodec_mux),
> @@ -143,6 +150,15 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
>  			    &g12a_toacodec_out_enable),
>  };
>  
> +static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
> +	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
> +			 &sm1_toacodec_mux),
> +	SND_SOC_DAPM_SWITCH("OUT EN", SND_SOC_NOPM, 0, 0,
> +			    &g12a_toacodec_out_enable),
> +	SND_SOC_DAPM_SWITCH("CLK EN", SND_SOC_NOPM, 0, 0,
> +			    &s4_toacodec_clk_enable),

I don't see a reason for the user to control that.

A user controls if the component is enable or not, and possibly select
the lane ... but that's it

You could have to flipped automatically which dapm when the component is
powered, that would make a lot more sense.

> +};
> +
>  static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
>  					 struct snd_pcm_hw_params *params,
>  					 struct snd_soc_dai *dai)
> @@ -228,6 +244,15 @@ static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
>  	{ "OUT Capture", NULL, "OUT EN" },
>  };
>  
> +static const struct snd_soc_dapm_route s4_toacodec_routes[] = {
> +	{ "SRC", "I2S A", "IN A Playback" },
> +	{ "SRC", "I2S B", "IN B Playback" },
> +	{ "SRC", "I2S C", "IN C Playback" },
> +	{ "OUT EN", "Switch", "SRC" },
> +	{ "CLK EN", "Switch", "OUT EN" },
> +	{ "OUT Capture", NULL, "CLK EN" },
> +};
> +
>  static const struct snd_kcontrol_new g12a_toacodec_controls[] = {
>  	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL, 3, 0),
>  };
> @@ -236,6 +261,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
>  	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
>  };
>  
> +static const struct snd_kcontrol_new s4_toacodec_controls[] = {
> +	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 7, 0),
> +};
> +
>  static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
>  	.probe			= g12a_toacodec_component_probe,
>  	.controls		= g12a_toacodec_controls,
> @@ -258,6 +287,17 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
>  	.endianness		= 1,
>  };
>  
> +static const struct snd_soc_component_driver s4_toacodec_component_drv = {
> +	.probe			= sm1_toacodec_component_probe,
> +	.controls		= s4_toacodec_controls,
> +	.num_controls		= ARRAY_SIZE(s4_toacodec_controls),
> +	.dapm_widgets		= s4_toacodec_widgets,
> +	.num_dapm_widgets	= ARRAY_SIZE(s4_toacodec_widgets),
> +	.dapm_routes		= s4_toacodec_routes,
> +	.num_dapm_routes	= ARRAY_SIZE(s4_toacodec_routes),
> +	.endianness		= 1,
> +};
> +
>  static const struct regmap_config g12a_toacodec_regmap_cfg = {
>  	.reg_bits	= 32,
>  	.val_bits	= 32,
> @@ -278,6 +318,13 @@ static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
>  	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
>  };
>  
> +static const struct g12a_toacodec_match_data s4_toacodec_match_data = {
> +	.component_drv	= &s4_toacodec_component_drv,
> +	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 19, 20),
> +	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
> +	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
> +};
> +
>  static const struct of_device_id g12a_toacodec_of_match[] = {
>  	{
>  		.compatible = "amlogic,g12a-toacodec",
> @@ -287,6 +334,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
>  		.compatible = "amlogic,sm1-toacodec",
>  		.data = &sm1_toacodec_match_data,
>  	},
> +	{
> +		.compatible = "amlogic,s4-toacodec",
> +		.data = &s4_toacodec_match_data,
> +	},
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);

-- 
Jerome


From Ryan.Wanner at microchip.com  Thu Mar  6 08:03:18 2025
From: Ryan.Wanner at microchip.com (Ryan.Wanner at microchip.com)
Date: Thu, 6 Mar 2025 09:03:18 -0700
Subject: [RESEND PATCH v6 1/3] dt-bindings: serial: atmel,at91-usart: add microchip,sama7d65-usart
In-Reply-To: <cover.1736522006.git.Ryan.Wanner@microchip.com>
References: <cover.1736522006.git.Ryan.Wanner@microchip.com>
Message-ID: <07aa3489013b4d4105edb50d99fbee6a70ffca1e.1736522006.git.Ryan.Wanner@microchip.com>

From: Dharma Balasubiramani <dharma.b at microchip.com>

Add SAMA7D65 USART compatible to DT bindings documentation.

Signed-off-by: Dharma Balasubiramani <dharma.b at microchip.com>
Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
index f466c38518c4..087a8926f8b4 100644
--- a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
+++ b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
@@ -26,6 +26,7 @@ properties:
           - enum:
               - microchip,sam9x60-usart
               - microchip,sam9x7-usart
+              - microchip,sama7d65-usart
           - const: atmel,at91sam9260-usart
       - items:
           - const: microchip,sam9x60-dbgu
-- 
2.43.0



From Ryan.Wanner at microchip.com  Thu Mar  6 08:03:19 2025
From: Ryan.Wanner at microchip.com (Ryan.Wanner at microchip.com)
Date: Thu, 6 Mar 2025 09:03:19 -0700
Subject: [RESEND PATCH v6 2/3] dt-bindings: pinctrl: at91-pio4: add microchip,sama7d65-pinctrl
In-Reply-To: <cover.1736522006.git.Ryan.Wanner@microchip.com>
References: <cover.1736522006.git.Ryan.Wanner@microchip.com>
Message-ID: <821255840c09d8d9cebbb1f2daaedd8a7c138875.1736522006.git.Ryan.Wanner@microchip.com>

From: Dharma Balasubiramani <dharma.b at microchip.com>

Add pinctrl bindings for microchip sama7d65 SoC.

Signed-off-by: Dharma Balasubiramani <dharma.b at microchip.com>
Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
index 774c3c269c40..81a05a09f19f 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
@@ -6,6 +6,7 @@ configure it.
 Required properties:
 - compatible:
 	"atmel,sama5d2-pinctrl"
+	"microchip,sama7d65-pinctrl", "microchip,sama7g5-pinctrl"
 	"microchip,sama7g5-pinctrl"
 - reg: base address and length of the PIO controller.
 - interrupts: interrupt outputs from the controller, one for each bank.
-- 
2.43.0



From Ryan.Wanner at microchip.com  Thu Mar  6 08:03:17 2025
From: Ryan.Wanner at microchip.com (Ryan.Wanner at microchip.com)
Date: Thu, 6 Mar 2025 09:03:17 -0700
Subject: [RESEND PATCH v6 0/3] Add support for SAMA7D65
Message-ID: <cover.1736522006.git.Ryan.Wanner@microchip.com>

From: Ryan Wanner <Ryan.Wanner at microchip.com>

This series adds support for the SAMA7D65 SoC.

V2 of this series [1].
V3 of this series [2].
V4 of this series [4].
V5 of this series [6].

For the pinctrl and pit64 timers those will have DTB warnings due to
those bindings not being in the .yaml format.

Changes v1->v2:
- V1 set was sent incorrectly as multiple seprate patches v2 took all
  those patches and put them in 1 thread.

Changes v2->v3:
- Correct the patch order to follow correct practice.
- Correct flexcom dt-binding commit messge to reflect the changes in the
  coding style.
- Add missing SoB tags to patches.
- Moved export clocks to DT patch to be included with the clock binding
  patch.
- Separate Kconfig changes and defconfig changes into different patches
  and removed unused Kconfig params.
- Correct confusing SoB and Co-developed chain.
- Removed unsued nodes in DTSI file and sorted includes
  alphanumerically.
- Fix incorrect dts formatting.
- Separate dts and pinmux changes into two patches.
- Combine PLL and MCK changes into core clock driver patch.
- Correct formatting in main clock driver.
- MMC dt-binding changes are applied for next so have been removed from
  the set [3].

Changes v3->v4:
- Collect all tags from maintainers.
- Correct compile error on 11/13 and correct location of vendor specific
  properties.
- Add USB and UTMI selections to 12/13 to prevent compile errors due to
  functions in the clock driver that use the USB clock system.
- Add "microchip,sama7g5-pinctrl" compatible string as a fall back in
  9/13.
- Add missing kfree() to 8/13 to correctly handle error case.
- Replace bad spacing with correct tab formatting on 7/13.

Changes from v4->v5:
- Remove patches that have been applied [5].
- Update pinctrl dt-binding to use fallback formatting.

Changes from v5->v6:
- Remove patches that have been applied [6].
- Correct incorrect spacing formatting on pinctrl dt-binding.
- Reintroduce flexcom to the thread since it was removed due to an error
  in collecting applied patches.

Note:
- For the SDHCI DTB error that patch has been removed do to it being
applied see [3].
- There are DTB errors on microchip,sama7d65-pit64b and
  microchip,sama7d65-pinctrl, this is due to those bindings being .txt
  files.

1) https://lore.kernel.org/linux-arm-kernel/cover.1732030972.git.Ryan.Wanner at microchip.com/T/#m9691b4d58b62f36f6cbac1d06883c985766c2c0d
2) https://lore.kernel.org/linux-arm-kernel/cover.1733505542.git.Ryan.Wanner at microchip.com/T/#m3b52978236907198f727424e69ef21c8898e95c8
3) https://lore.kernel.org/linux-arm-kernel/cover.1732030972.git.Ryan.Wanner at microchip.com/T/#mccf6521c07e74e1c7dc61b09ae0ebdbbdde73a28
4) https://lore.kernel.org/linux-arm-kernel/70d429086fd8e858d79ca2824ad8cc4a09e3fe5d.1734723585.git.Ryan.Wanner at microchip.com/T/#m918b8db23c8d30981263846a02dafc085e17de14
5) https://lore.kernel.org/linux-arm-kernel/70d429086fd8e858d79ca2824ad8cc4a09e3fe5d.1734723585.git.Ryan.Wanner at microchip.com/T/#m69b8f11536e3b0ca3d69d125d0670c90412d4317
6) https://lore.kernel.org/linux-arm-kernel/20250107160850.120537-1-Ryan.Wanner at microchip.com/T/#m54eaea3dc49c687865e3db33e286eeb29edd7cf0

Dharma Balasubiramani (3):
  dt-bindings: serial: atmel,at91-usart: add microchip,sama7d65-usart
  dt-bindings: pinctrl: at91-pio4: add microchip,sama7d65-pinctrl
  dt-bindings: mfd: atmel,sama5d2-flexcom: add
    microchip,sama7d65-flexcom

 .../devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml   | 9 ++++-----
 .../bindings/pinctrl/atmel,at91-pio4-pinctrl.txt         | 1 +
 .../devicetree/bindings/serial/atmel,at91-usart.yaml     | 1 +
 3 files changed, 6 insertions(+), 5 deletions(-)

-- 
2.43.0



From Ryan.Wanner at microchip.com  Thu Mar  6 08:03:20 2025
From: Ryan.Wanner at microchip.com (Ryan.Wanner at microchip.com)
Date: Thu, 6 Mar 2025 09:03:20 -0700
Subject: [RESEND PATCH v6 3/3] dt-bindings: mfd: atmel,sama5d2-flexcom: add microchip,sama7d65-flexcom
In-Reply-To: <cover.1736522006.git.Ryan.Wanner@microchip.com>
References: <cover.1736522006.git.Ryan.Wanner@microchip.com>
Message-ID: <9656d46ee0255b9aba404d77d2d204376a9cb248.1736522006.git.Ryan.Wanner@microchip.com>

From: Dharma Balasubiramani <dharma.b at microchip.com>

Add flexcom binding documentation for sama7d65.

Consolidated entries into one enum to match proper coding style.

Signed-off-by: Dharma Balasubiramani <dharma.b at microchip.com>
Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml   | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml b/Documentation/devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml
index 0dc6a40b63f4..c7d6cf96796c 100644
--- a/Documentation/devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml
+++ b/Documentation/devicetree/bindings/mfd/atmel,sama5d2-flexcom.yaml
@@ -19,12 +19,11 @@ properties:
     oneOf:
       - const: atmel,sama5d2-flexcom
       - items:
-          - const: microchip,sam9x7-flexcom
+          - enum:
+              - microchip,sam9x7-flexcom
+              - microchip,sama7d65-flexcom
+              - microchip,sama7g5-flexcom
           - const: atmel,sama5d2-flexcom
-      - items:
-          - const: microchip,sama7g5-flexcom
-          - const: atmel,sama5d2-flexcom
-
 
   reg:
     maxItems: 1
-- 
2.43.0



From broonie at kernel.org  Thu Mar  6 08:10:39 2025
From: broonie at kernel.org (Mark Brown)
Date: Thu, 06 Mar 2025 16:10:39 +0000
Subject: [PATCH next] spi: stm32-ospi: Fix an IS_ERR() vs NULL bug in
 stm32_ospi_get_resources()
In-Reply-To: <bc4c9123-df43-4616-962f-765801d30b4c@stanley.mountain>
References: <bc4c9123-df43-4616-962f-765801d30b4c@stanley.mountain>
Message-ID: <174127743980.139137.18227484559909848489.b4-ty@kernel.org>

On Thu, 06 Mar 2025 12:48:34 +0300, Dan Carpenter wrote:
> The devm_ioremap() function returns NULL on error, it doesn't return
> error pointers.  Fix the check to match.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: stm32-ospi: Fix an IS_ERR() vs NULL bug in stm32_ospi_get_resources()
      commit: 7dfc9bdde9fa20cf1ac5cbea97b0446622ca74c7

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From catalin.marinas at arm.com  Thu Mar  6 08:18:38 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 6 Mar 2025 16:18:38 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8nDj129ZVeZBVSp@pluto>
References: <Z8g8vhS9rqQ_ez48@google.com>
 <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com>
 <Z8my4MZ-In0ibxVY@arm.com>
 <Z8nDj129ZVeZBVSp@pluto>
Message-ID: <Z8nK3uFkspy61yjP@arm.com>

On Thu, Mar 06, 2025 at 03:47:27PM +0000, Cristian Marussi wrote:
> On Thu, Mar 06, 2025 at 02:36:16PM +0000, Catalin Marinas wrote:
> > This loop in scmi_device_create() looks strange:
> > 
> > 	list_for_each_entry(rdev, phead, node) {
> > 		struct scmi_device *sdev;
> > 
> > 		sdev = __scmi_device_create(np, parent,
> > 					    rdev->id_table->protocol_id,
> > 					    rdev->id_table->name);
> > 		/* Report errors and carry on... */
> > 		if (sdev)
> > 			scmi_dev = sdev;
> > 		else
> > 			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
> > 			       of_node_full_name(parent->of_node),
> > 			       rdev->id_table->protocol_id,
> > 			       rdev->id_table->name);
> > 	}
> > 
> > We can override scmi_dev a few times in the loop and lose the previous
> > sdev allocations. Is this intended?
> 
> Yes...it is weird..but by design I would say :P ...
> 
> ...because this is called to instantiate one single device OR instantiate at
> once all the multiple devices needed for a protocol: in this latter case it
> returns just one of the created devices to signal success or NULL if all the
> devices' creation failed....we dont need to keep the allocated devices references
> anyway here since on success those devices are now referenced and kept on the
> SCMI bus, so they can be searched/scanned/destroyed from there.

Not sure why the pointer isn't found, device_add() should link it with
the parent. Unless something else fails, the parent is freed and the
linked devices unreachable. I'm not familiar at all with this code, I
just saw kmemleak and thought of replying.

The loop is still weird, scmi_chan_setup() seems to use the pointer to
scmi_device for something more meaningful than a pass/fail check. Also
the overall result is based only on what the last __scmi_device_create()
return value was, irrespective of the previous iterations of the loop.
You do have a pr_err() but no early bailing out of the loop on failure.
I'm curious if there are any SCMI errors in the Alice's kernel log.

-- 
Catalin


From mbland at motorola.com  Thu Mar  6 08:23:58 2025
From: mbland at motorola.com (Maxwell Bland)
Date: Thu, 6 Mar 2025 10:23:58 -0600
Subject: [RFC PATCH v3 00/15] pkeys-based page table hardening
In-Reply-To: <20250203101839.1223008-1-kevin.brodsky@arm.com>
References: <20250203101839.1223008-1-kevin.brodsky@arm.com>
Message-ID: <a32cjyekuecoowzbitc2xykilvpu6l3jjtityp7x5hw7xbiysp@5l2lptwmqiug>

On Mon, Feb 03, 2025 at 10:18:24AM +0000, Kevin Brodsky wrote:
> This is a proposal to leverage protection keys (pkeys) to harden
> critical kernel data, by making it mostly read-only. The series includes
> a simple framework called "kpkeys" to manipulate pkeys for in-kernel use,
> as well as a page table hardening feature based on that framework
> (kpkeys_hardened_pgtables). Both are implemented on arm64 as a proof of
> concept, but they are designed to be compatible with any architecture
> implementing pkeys.

Hi Kevin,

This is awesome. When working on some of these problems, I also thought
of leveraging the POE feature, but was not sure of a good way to make
it work.

> Page tables were chosen as they are a popular (and critical) target for
> attacks, but there are of course many others - this is only a starting
> point (see section "Further use-cases"). It has become more and more
> common for accesses to such target data to be mediated by a hypervisor
> in vendor kernels; the hope is that kpkeys can provide much of that
> protection in a simpler manner. No benchmarking has been performed at
> this stage, but the runtime overhead should also be lower (though likely
> not negligible).

Some notes here, having implemented similar page table protections,
albeit using stage-2 page table permissions and a fault handler.

https://lore.kernel.org/all/2wf4kmoqqmod6njviaq33lbxbx6gvdqbksljxykgltwnxo6ruy at 7ueumwmxxh72/

I wanted to know your thoughts on associating specific policies to
page table updates in cases where an adversary is able to corrupt
other state associated with parameters to the page table infrastructure
code, e.g.

arch/arm64/net/bpf_jit_comp.c
2417:		if (set_memory_rw(PAGE_MASK & ((uintptr_t)&plt->target),

Is this something we would assume is handled via the security_* hook
infrastructure, a shadow stack CFI method, or changing the kernel code
to reverify the data non-modularly, some combination of the above?

> - Pages in the linear mapping are assigned a pkey using set_memory_pkey().
>   This is sufficient for this series, but of course higher-level
>   interfaces can be introduced later to ask allocators to return pages
>   marked with a given pkey. It should also be possible to extend this to
>   vmalloc() if needed.

One of the interesting points here, acknowledged below, was that this
relies on having guarantees around the PC value/CFI of the function.
Since this is the baseline assumption, it feels natural that the
locking/unlocking would be associated into the existing CFI
instrumentation, since (from experience) point-patching each mutable
data structure allocation/deallocation is difficult.

> # Further use-cases
> 
> It should be possible to harden various targets using kpkeys, including:
> 
> - struct cred (enforcing a "mostly read-only" state once committed)
> 
> - fixmap (occasionally used even after early boot, e.g.
>   set_swapper_pgd() in arch/arm64/mm/mmu.c)
> 
> - SELinux state (e.g. struct selinux_state::initialized)
> 
> ... and many others.

Be wary that it is not just struct cred but pointers to struct cred.  We
quickly run into a problem of, for example, in updates to f_op,
bookkeeping which f_op is OK to have in the file, e.g., in Android's
6.1.x:

drivers/gpu/drm/i810/i810_dma.c
138:    file_priv->filp->f_op = &i810_buffer_fops;
144:    file_priv->filp->f_op = old_fops;

drivers/staging/android/ashmem.c
436:            vmfile->f_op = &vmfile_fops;

Where overwriting f_op is a "classic" bypass of protection systems like
this one.

I think this problem may be totally solvable if POE was integrated into
something like CFI, since we can guarantee only the code that sets f_op
to "vmfile_fops" can unlock/relock the file's page.

Maybe another approach would work better, though?

> # Open questions
> 
> A few aspects in this RFC that are debatable and/or worth discussing:
> 
> - There is currently no restriction on how kpkeys levels map to pkeys
>   permissions. A typical approach is to allocate one pkey per level and
>   make it writable at that level only. As the number of levels
>   increases, we may however run out of pkeys, especially on arm64 (just
>   8 pkeys with POE). Depending on the use-cases, it may be acceptable to
>   use the same pkey for the data associated to multiple levels.

Honestly, I associate each protected virtual page in stage-2 with a
unique tag (manually, right now, but Kees Cook has some magic that
does the same via alloc_tag.h), and this works really well to track
specific resources and resource modification semantics "over" a generic
protection ring.

I think, though, that the code you provided could be used to bootstrap
such a system by using the overlay to protect a similar page tag lookup
table, which then can provide the fine-grained protection semantics.

I.e. use this baseline to isolate a secure monitor system.

Hopefully that makes sense! (-:

> 
> - kpkeys_set_level() and kpkeys_restore_pkey_reg() are not symmetric:
>   the former takes a kpkeys level and returns a pkey register value, to
>   be consumed by the latter. It would be more intuitive to manipulate
>   kpkeys levels only. However this assumes that there is a 1:1 mapping
>   between kpkeys levels and pkey register values, while in principle
>   the mapping is 1:n (certain pkeys may be used outside the kpkeys
>   framework).

Another issue I'm not confident in is the assumption of adversary's
inability to manipulate system control registers. This is true in the
context of a Heki-like system (or any well-made HVCI), but not totally
true of a pure EL1 implementation?

> 
> - An architecture that supports kpkeys is expected to select
>   CONFIG_ARCH_HAS_KPKEYS and always enable them if available - there is
>   no CONFIG_KPKEYS to control this behaviour. Since this creates no
>   significant overhead (at least on arm64), it seemed better to keep it
>   simple. Each hardening feature does have its own option and arch
>   opt-in if needed (CONFIG_KPKEYS_HARDENED_PGTABLES,
>   CONFIG_ARCH_HAS_KPKEYS_HARDENED_PGTABLES).

There's so many pieces of data though/data structures! In this model,
you'd have a separate switch for thousands of types of data! But I do
think protecting PTs is the first step to a more complicated security
monitor, since it allows you to have integrity for specific physical
pages (or IPAs).
> 
> 
> Any comment or feedback will be highly appreciated, be it on the
> high-level approach or implementation choices!

Last note, I'd not totallllyyy trust the compiler to inline the
functions.... I've met cases where functions on memory protections
I expected to be inlined were not. I think __forceinline *may* work
here, vs standard "static inline", but am not confident/sure.

Hopefully the above is valuable at all. Thanks!

Maxwell Bland


From helgaas at kernel.org  Thu Mar  6 08:24:41 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 6 Mar 2025 10:24:41 -0600
Subject: [PATCH v2 4/8] PCI: brcmstb: Fix error path upon call of
 regulator_bulk_get()
In-Reply-To: <CA+-6iNyXeXhqzwbV+pcizpyXg-c-gihcLEtPv1s1uczdNN_VOQ@mail.gmail.com>
Message-ID: <20250306162441.GA344031@bhelgaas>

On Thu, Mar 06, 2025 at 10:24:56AM -0500, Jim Quinlan wrote:
> On Tue, Mar 4, 2025 at 9:49?AM Jim Quinlan <james.quinlan at broadcom.com> wrote:
> > On Mon, Mar 3, 2025 at 1:40?PM Bjorn Helgaas <helgaas at kernel.org> wrote:
> > > On Fri, Feb 14, 2025 at 12:39:32PM -0500, Jim Quinlan wrote:
> > > > If regulator_bulk_get() returns an error, no regulators are created and we
> > > > need to set their number to zero.  If we do not do this and the PCIe
> > > > link-up fails, regulator_bulk_free() will be invoked and effect a panic.
> > > >
> > > > Also print out the error value, as we cannot return an error upwards as
> > > > Linux will WARN on an error from add_bus().
> > > >
> > > > Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT")
> > > > Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
> > > > ---
> > > >  drivers/pci/controller/pcie-brcmstb.c | 3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > > index e0b20f58c604..56b49d3cae19 100644
> > > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > > @@ -1416,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus)
> > > >
> > > >               ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies);
> > > >               if (ret) {
> > > > -                     dev_info(dev, "No regulators for downstream device\n");
> > > > +                     dev_info(dev, "Did not get regulators; err=%d\n", ret);
> > > > +                     pcie->sr = NULL;
> > >
> > > Is alloc_subdev_regulators() buying us something useful?  It seems
> > > like it would be simpler to have:
> > >
> > >   struct brcm_pcie {
> > >     ...
> > >     struct regulator_bulk_data supplies[3];
> > >     ...
> > >   };
> > >
> > > I think that's what most callers of devm_regulator_bulk_get() do.
> 
> Manivannan stated that this series has already been merged.  So shall
> I implement your comments with a commit sometime in the future?

Sorry, I should have mentioned this would be something possible for
the future.  This current series is all set to go.

Bjorn


From conor at kernel.org  Thu Mar  6 08:27:46 2025
From: conor at kernel.org (Conor Dooley)
Date: Thu, 6 Mar 2025 16:27:46 +0000
Subject: [PATCH 1/1] dt-bindings: i2c: imx-lpi2c: add i.MX94 LPI2C
In-Reply-To: <20250306155815.110514-1-Frank.Li@nxp.com>
References: <20250306155815.110514-1-Frank.Li@nxp.com>
Message-ID: <20250306-backstab-chewing-89e93ccba5d7@spud>

On Thu, Mar 06, 2025 at 10:58:15AM -0500, Frank Li wrote:
> Add compatible string "fsl,imx94-lpi2c" for the i.MX94 chip, which is
> backward compatible with i.MX7ULP. Set it to fall back to
> "fsl,imx7ulp-lpi2c".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> index 1dcb9c78de3b5..969030a6f82ab 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> @@ -26,6 +26,7 @@ properties:
>                - fsl,imx8qm-lpi2c
>                - fsl,imx8ulp-lpi2c
>                - fsl,imx93-lpi2c
> +              - fsl,imx94-lpi2c
>                - fsl,imx95-lpi2c
>            - const: fsl,imx7ulp-lpi2c
>  
> -- 
> 2.34.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/21783906/attachment.sig>

From conor at kernel.org  Thu Mar  6 08:32:31 2025
From: conor at kernel.org (Conor Dooley)
Date: Thu, 6 Mar 2025 16:32:31 +0000
Subject: [PATCH v2 1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register
 compatible
In-Reply-To: <20250306123809.273655-2-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
 <20250306123809.273655-2-amadeus@jmu.edu.cn>
Message-ID: <20250306-powdery-jarring-bc74e2d12faa@spud>

On Thu, Mar 06, 2025 at 08:38:08PM +0800, Chukun Pan wrote:
> Document rk3528 compatible for QoS registers.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
> index 4d67ff26d445..2836e4793afc 100644
> --- a/Documentation/devicetree/bindings/mfd/syscon.yaml
> +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
> @@ -103,6 +103,7 @@ select:
>            - rockchip,rk3288-qos
>            - rockchip,rk3368-qos
>            - rockchip,rk3399-qos
> +          - rockchip,rk3528-qos
>            - rockchip,rk3562-qos
>            - rockchip,rk3568-qos
>            - rockchip,rk3576-qos
> @@ -202,6 +203,7 @@ properties:
>            - rockchip,rk3288-qos
>            - rockchip,rk3368-qos
>            - rockchip,rk3399-qos
> +          - rockchip,rk3528-qos
>            - rockchip,rk3562-qos
>            - rockchip,rk3568-qos
>            - rockchip,rk3576-qos
> -- 
> 2.25.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/d2b1fc48/attachment.sig>

From cki-project at redhat.com  Thu Mar  6 08:33:06 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 16:33:06 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <11843.125030611330900487@us-mta-70.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703333398

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703333398-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From sakari.ailus at iki.fi  Thu Mar  6 08:33:18 2025
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Thu, 6 Mar 2025 16:33:18 +0000
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <20250305113802.897087-2-mathis.foerst@mt.com>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
Message-ID: <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>

Hi Mathis,

Thanks for the patch.

On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> The imx-media-csi driver requires upstream camera drivers to implement
> the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> implement this function are not usable on the i.MX6.
> 
> The docs for get_mbus_config [1] say:
> @get_mbus_config: get the media bus configuration of a remote sub-device.
>             The media bus configuration is usually retrieved from the
>             firmware interface at sub-device probe time, immediately
>             applied to the hardware and eventually adjusted by the
>             driver.
> 
> Currently, the imx-media-csi driver is not incorporating the information
> from the firmware interface and therefore relies on the implementation of
> get_mbus_config by the camera driver.
> 
> To be compatible with camera drivers not implementing get_mbus_config
> (which is the usual case), use the bus information from the fw interface:
> 
> The camera does not necessarily has a direct media bus link to the CSI as
> the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> between them on the media pipeline.
> The CSI driver already implements the functionality to find the connected
> camera sub-device to call get_mbus_config on it.
> 
> At this point the driver is modified as follows:
> In the case that get_mbus_config is not implemented by the upstream
> camera, try to get its endpoint configuration from the firmware interface
> usign v4l2_fwnode_endpoint_parse.
> For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> configuration.
> For all other mbus_types, return an error.
> 
> Note that parsing the mbus_config from the fw interface is not done during
> probing because the camera that's connected to the CSI can change based on
> the selected input of the video-mux at runtime.
> 
> [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> [1] include/media/v4l2-subdev.h - line 814
> 
> Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> ---
>  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
>  1 file changed, 32 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> index 3edbc57be2ca..394a9321a10b 100644
> --- a/drivers/staging/media/imx/imx-media-csi.c
> +++ b/drivers/staging/media/imx/imx-media-csi.c
> @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
>  {
>  	struct v4l2_subdev *sd, *remote_sd;
>  	struct media_pad *remote_pad;
> +	struct fwnode_handle *ep_node;
> +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };

Are there any defaults in DT bindings (other than 0's)? Also initialising a
field to zero this way is redundant, just use {}.

>  	int ret;
>  
>  	if (!priv->src_sd)
> @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
>  
>  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
>  			       remote_pad->index, mbus_cfg);
> -	if (ret == -ENOIOCTLCMD)
> -		v4l2_err(&priv->sd,
> -			 "entity %s does not implement get_mbus_config()\n",
> -			 remote_pad->entity->name);
> +	if (ret == -ENOIOCTLCMD) {

	if (!ret)
		return 0;

And you can unindent the rest.

> +		/*
> +		 * If the upstream sd does not implement get_mbus_config,
> +		 * try to parse the link configuration from its fw_node
> +		 */
> +		ep_node = fwnode_graph_get_endpoint_by_id(dev_fwnode(remote_sd->dev),

Always parse only local, not remote endpoints.

Also: instead of supporting get_mbus_config() in a driver, we would ideally
have a helper that optionally uses it and secondarily gets the endpoint
configuration from a local endpoint. It's better to do that once rather
than have every driver do this differently, including a different set of
bugs.

That being said, V4L2 fwnode endpoint parsing is a somewhat driver specific
task and that should remain with the driver. So I'd think the helper should
take a driver-parsed struct v4l2_fwnode_endpoint as an argument, for that
endpoint.

I'm not saying no to this patch though. But in the long run we'll be better
off with a helper in the framework.

> +							  0, 0,
> +							  FWNODE_GRAPH_ENDPOINT_NEXT);
> +		if (!ep_node)
> +			return -ENOTCONN;
> +
> +		ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
> +		fwnode_handle_put(ep_node);
> +		if (ret)
> +			return ret;
>  
> +		mbus_cfg->type = ep.bus_type;
> +		switch (ep.bus_type) {
> +		case V4L2_MBUS_PARALLEL:
> +		case V4L2_MBUS_BT656:
> +			mbus_cfg->bus.parallel = ep.bus.parallel;
> +			break;
> +		case V4L2_MBUS_CSI2_DPHY:
> +			mbus_cfg->bus.mipi_csi2 = ep.bus.mipi_csi2;
> +			break;
> +		default:
> +			v4l2_err(&priv->sd, "Unsupported mbus_type: %i\n",
> +				 ep.bus_type);
> +			return -EINVAL;
> +		}
> +	}
>  	return ret;
>  }
>  

-- 
Kind regards,

Sakari Ailus


From cristian.ciocaltea at collabora.com  Thu Mar  6 08:38:53 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Thu, 6 Mar 2025 18:38:53 +0200
Subject: [PATCH v4 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250306-masked-voracious-octopus-be05b8@houat>
References: <20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7@collabora.com>
 <20250304-phy-sam-hdptx-bpc-v4-3-8657847c13f7@collabora.com>
 <20250304-small-mindful-mongrel-bd6f8b@houat>
 <155f609f-994f-4140-8453-7e38a5e6deef@collabora.com>
 <20250306-masked-voracious-octopus-be05b8@houat>
Message-ID: <0600430d-12c1-4af7-9082-76448943b02a@collabora.com>

On 3/6/25 3:35 PM, Maxime Ripard wrote:
> On Tue, Mar 04, 2025 at 02:04:18PM +0200, Cristian Ciocaltea wrote:
>> Hi Maxime,
>>
>> On 3/4/25 10:13 AM, Maxime Ripard wrote:
>>> Hi,
>>>
>>> On Tue, Mar 04, 2025 at 03:44:02AM +0200, Cristian Ciocaltea wrote:
>>>> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
>>>> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
>>>> and not before.
>>>>
>>>> While at it, introduce a define for this rate limit constant.
>>>>
>>>> Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
>>>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>>>> ---
>>>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
>>>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
>>>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> @@ -320,6 +320,7 @@
>>>>  #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
>>>>  #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
>>>>  
>>>> +#define HDMI14_MAX_RATE			340000000
>>>>  #define HDMI20_MAX_RATE			600000000
>>>>  
>>>>  enum dp_link_rate {
>>>> @@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
>>>>  
>>>>  	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
>>>>  
>>>> -	if (rate >= 3400000) {
>>>> +	if (rate > HDMI14_MAX_RATE / 100) {
>>>
>>> The rate seems to come from rk_hdptx_phy_power_on and eventually from
>>> tmds_char_rate in the PHY config options, so its rate is in Hertz.
>>
>> The rate coming from rk_hdptx_phy_power_on() is in hHz, since it passed
>> via dw_hdmi_qp_rockchip_encoder_enable() as
>>
>>   phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
>>
>>> HDMI14_MAX_RATE and HDMI20_MAX_RATE are both defined in Hertz as well.
>>> It seems super odd to mee that you then convert HDMI14_MAX_RATE to hHz?
>>
>> This stems from the ropll_tmds_cfg table containing the configuration
>> params for the supported rates which requires the search keys to be
>> provided in hHz rather than Hz.
>>
>> I agree this is nothing but confusing, that's why I fixed this up in
>> "phy: rockchip: samsung-hdptx: Avoid Hz-hHz unit conversion overhead"
> 
> Yeah, sorry, I noticed it after sending the review. Still, I'd advise to
> put that patch first, it's a bit weird to add more patch we're going to
> rework later on.

No worries and yes, I've already planned to move the patch before all
the others adding more stuff.  I'd still keep this patch as is, to make
it easier for backporting, as well as the next three patches dropping
stuff, before continuing with the unit conversion.


From dmitry.baryshkov at linaro.org  Thu Mar  6 08:39:48 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Thu, 6 Mar 2025 18:39:48 +0200
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
Message-ID: <zybxwxxkua2zqukcd7tn2z4uwbqjbxt2fdtnrmpsov4hy55tzn@moxuyfxtyagb>

On Thu, Mar 06, 2025 at 08:15:13PM +0800, Andy Yan wrote:
> Hi Piotr,
> 
> ? 2025-03-06 19:47:31?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
> >
> >> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 09:53:
> >> 
> >> 
> >> Hi,
> >> 
> >> ? 2025-03-06 16:42:00?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
> >>> 
> >>> 
> >>>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 01:59:
> >>>> 
> >>>> 
> >>>> 
> >>>> 
> >>>> Both of the two config options should be enabled.
> >>>> andy at Pro480:~/WorkSpace/linux-next$ rg DW_DP .config
> >>>> 4044:CONFIG_ROCKCHIP_DW_DP=y
> >>> 
> >>> here i?m a bit lost?.
> >>> greping on full kernel sources (with applied https://patchwork.kernel.org/project/linux-rockchip/list/?series=936784) gives me no single appearance of ROCKCHIP_DW_DP?
> >>> Do i miss something?
> >> 
> >> see PATCH 3/6:   
> >> 
> >> 
> >> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> >> index 26c4410b2407..c8638baf9641 100644
> >> --- a/drivers/gpu/drm/rockchip/Kconfig
> >> +++ b/drivers/gpu/drm/rockchip/Kconfig
> >> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
> >> select DRM_PANEL
> >> select VIDEOMODE_HELPERS
> >> select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
> >> + select DRM_DW_DP if ROCKCHIP_DW_DP
> >> select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
> >> select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
> >> select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
> >> @@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
> >>  RK3399 based SoC, you should select this
> >>  option.
> >> 
> >> +config ROCKCHIP_DW_DP
> >> + bool "Rockchip specific extensions for Synopsys DW DP"
> >> + help
> >> +  Choose this option for Synopsys DesignWare Cores DisplayPort
> >> +  transmit controller support on Rockchip SoC.
> >> 
> >> https://lore.kernel.org/linux-rockchip/047EECFC-7E55-44EC-896F-13FE04333E4D at gmail.com/T/#m178a325ea0ebc64187aae474d77c3f7a9e0bc93d
> >>> 
> >
> >
> >Ah my bad!
> >One patch patch was commented - so not all dp code was applied.
> >
> >Now it is much better:
> >
> >root at myth-frontend-56b0f018b5e0:~ # dmesg | grep drm
> >[    9.795380] panthor fb000000.gpu: [drm] clock rate = 198000000
> >[    9.796257] panthor fb000000.gpu: [drm] mali-g610 id 0xa867 major 0x0 minor 0x0 status 0x5
> >[    9.796262] panthor fb000000.gpu: [drm] Features: L2:0x7120306 Tiler:0x809 Mem:0x301 MMU:0x2830 AS:0xff
> >[    9.796265] panthor fb000000.gpu: [drm] shader_present=0x50005 l2_present=0x1 tiler_present=0x1
> >[    9.851869] panthor fb000000.gpu: [drm] Firmware protected mode entry not be supported, ignoring
> >[    9.851921] panthor fb000000.gpu: [drm] Firmware git sha: 814b47b551159067b67a37c4e9adda458ad9d852
> >[    9.852127] panthor fb000000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 Instrumentation features 0x71
> >[    9.852436] [drm] Initialized panthor 1.3.0 for fb000000.gpu on minor 0
> >[   10.003108] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
> >[   10.004705] rockchip-drm display-subsystem: bound fde60000.dp (ops dw_dp_rockchip_component_ops)
> >[   10.006085] rockchip-drm display-subsystem: bound fdea0000.hdmi (ops dw_hdmi_qp_rockchip_ops)
> >[   10.006679] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 1
> >[   10.006737] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
> >[   10.007663] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
> >
> >Unfortunately still nothing on screen
> >
> >dri state: https://gist.github.com/warpme/5e971dfd2e9fd52fae76641831cebe46
> >
> >and kernel dmesg https://termbin.com/r0m3
> >
> >i?m not sure what is missing (some dts enablement or?.)
> 
> From your dts,  I find you use gpio for hpd, I'm not sure how to handle it  with upstream  code now.
> 
> 
> &dp1 {
> 	status = "okay";
> 	pinctrl-names = "default";
> 	pinctrl-0 = <&dp1_hpd>;
> 	hpd-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;

If this GPIO is handled by the DP controller itself, it should be a part
of DP's node. Otherwise please move it to the correctponding
dp-connector node.

> };
> 
> I suggest a change like this:
> 
> &dp1 {
> 	status = "okay";
> 	pinctrl-names = "default";
>         pinctrl-0 = <&dp1m0_pins>;
> 
> };
> 
> And also remove dp1_hpd pinctrl in your dts.
> 
> Then when you DP cable plugin, you can run command as bellow to see if the driver detects the HPD:
> 
> # cat /sys/class/drm/card0-DP-1/status 
> connected
> # 

-- 
With best wishes
Dmitry


From jbrunet at baylibre.com  Thu Mar  6 08:41:19 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 06 Mar 2025 17:41:19 +0100
Subject: [PATCH v3 4/6] clk: meson: axg-audio: Add the mclk pad div for s4
In-Reply-To: <20250228-audio_drvier-v3-4-dbfd30507e4c@amlogic.com> (jiebing
	chen via's message of "Fri, 28 Feb 2025 16:04:12 +0800")
References: <20250228-audio_drvier-v3-0-dbfd30507e4c@amlogic.com>
	<20250228-audio_drvier-v3-4-dbfd30507e4c@amlogic.com>
Message-ID: <1ja59y5cy8.fsf@starbuckisacylon.baylibre.com>

On Fri 28 Feb 2025 at 16:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:

> From: jiebing chen <jiebing.chen at amlogic.com>
>
> Add mclk pad div support, Increased the number of lrclk
> and sclk pads to five
>
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  drivers/clk/meson/axg-audio.c | 410 +++++++++++++++++++++++++++++++++++++++++-
>  drivers/clk/meson/axg-audio.h |   4 +
>  2 files changed, 412 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
> index 9df627b142f89788966ede0262aaaf39e13f0b49..e70559ee0fd8deaf9858b0592e839fdf49d05886 100644
> --- a/drivers/clk/meson/axg-audio.c
> +++ b/drivers/clk/meson/axg-audio.c
> @@ -323,6 +323,16 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
>  	AUD_MUX(_name, _reg, 0x7, _shift, 0, _parents,		\
>  		CLK_SET_RATE_NO_REPARENT)
>  
> +#define AUD_MCLK_PAD_MUX(_name, _reg, _shift)					\
> +	AUD_MUX(_name##_sel, _reg, 0x7, _shift, CLK_MUX_ROUND_CLOSEST,			\
> +		mclk_pad_ctrl_parent_data, 0)
> +#define AUD_MCLK_PAD_DIV(_name, _reg, _shift)					\
> +	AUD_DIV(_name##_div, _reg, _shift, 8, CLK_DIVIDER_ROUND_CLOSEST,			\
> +		aud_##_name##_sel, CLK_SET_RATE_PARENT)
> +#define AUD_MCLK_PAD_GATE(_name, _reg, _shift)					\
> +	AUD_GATE(_name, _reg, _shift, aud_##_name##_div,			\
> +		 CLK_SET_RATE_PARENT)
> +
>  /* Common Clocks */
>  static struct clk_regmap ddr_arb =
>  	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
> @@ -826,6 +836,49 @@ static struct clk_regmap sm1_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
>  static struct clk_regmap sm1_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
>  	tdm_sclk_pad_2, AUDIO_SM1_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
>  
> +static struct clk_regmap s4_tdm_mclk_pad0_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 8);
> +static struct clk_regmap s4_tdm_mclk_pad1_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 24);
> +static struct clk_regmap s4_tdm_mclk_pad2_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 8);
> +
> +static struct clk_regmap s4_tdm_mclk_pad0_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 0);
> +static struct clk_regmap s4_tdm_mclk_pad1_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 16);
> +static struct clk_regmap s4_tdm_mclk_pad2_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 0);
> +
> +static struct clk_regmap s4_tdm_mclk_pad_0 =
> +	AUD_MCLK_PAD_GATE(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 15);
> +static struct clk_regmap s4_tdm_mclk_pad_1 =
> +	AUD_MCLK_PAD_GATE(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 31);
> +static struct clk_regmap s4_tdm_mclk_pad_2 =
> +	AUD_MCLK_PAD_GATE(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 15);
> +
> +static struct clk_regmap s4_tdm_sclk_pad_0 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL0, 0, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_1 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL0, 4, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_2 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL0, 8, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_3 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL0, 16, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_4 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL0, 20, lrclk_pad_ctrl_parent_data);
> +
> +static struct clk_regmap s4_tdm_lrclk_pad_0 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL1, 0, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_1 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL1, 4, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_2 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL1, 8, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_3 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL1, 16, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_4 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL1, 20, lrclk_pad_ctrl_parent_data);
> +
>  /*
>   * Array of all clocks provided by this provider
>   * The input clocks of the controller will be populated at runtime
> @@ -1257,6 +1310,177 @@ static struct clk_hw *sm1_audio_hw_clks[] = {
>  	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
>  };
>  
> +/*
> + * Array of all S4 clocks provided by this provider
> + * The input clocks of the controller will be populated at runtime
> + */
> +static struct clk_hw *s4_audio_hw_clks[] = {
> +	[AUD_CLKID_DDR_ARB]		= &ddr_arb.hw,
> +	[AUD_CLKID_PDM]			= &pdm.hw,
> +	[AUD_CLKID_TDMIN_A]		= &tdmin_a.hw,
> +	[AUD_CLKID_TDMIN_B]		= &tdmin_b.hw,
> +	[AUD_CLKID_TDMIN_C]		= &tdmin_c.hw,
> +	[AUD_CLKID_TDMIN_LB]		= &tdmin_lb.hw,
> +	[AUD_CLKID_TDMOUT_A]		= &tdmout_a.hw,
> +	[AUD_CLKID_TDMOUT_B]		= &tdmout_b.hw,
> +	[AUD_CLKID_TDMOUT_C]		= &tdmout_c.hw,
> +	[AUD_CLKID_FRDDR_A]		= &frddr_a.hw,
> +	[AUD_CLKID_FRDDR_B]		= &frddr_b.hw,
> +	[AUD_CLKID_FRDDR_C]		= &frddr_c.hw,
> +	[AUD_CLKID_TODDR_A]		= &toddr_a.hw,
> +	[AUD_CLKID_TODDR_B]		= &toddr_b.hw,
> +	[AUD_CLKID_TODDR_C]		= &toddr_c.hw,
> +	[AUD_CLKID_LOOPBACK]		= &loopback.hw,
> +	[AUD_CLKID_SPDIFIN]		= &spdifin.hw,
> +	[AUD_CLKID_SPDIFOUT]		= &spdifout.hw,
> +	[AUD_CLKID_RESAMPLE]		= &resample.hw,
> +	[AUD_CLKID_SPDIFOUT_B]		= &spdifout_b.hw,
> +	[AUD_CLKID_MST_A_MCLK_SEL]	= &sm1_mst_a_mclk_sel.hw,
> +	[AUD_CLKID_MST_B_MCLK_SEL]	= &sm1_mst_b_mclk_sel.hw,
> +	[AUD_CLKID_MST_C_MCLK_SEL]	= &sm1_mst_c_mclk_sel.hw,
> +	[AUD_CLKID_MST_D_MCLK_SEL]	= &sm1_mst_d_mclk_sel.hw,
> +	[AUD_CLKID_MST_E_MCLK_SEL]	= &sm1_mst_e_mclk_sel.hw,
> +	[AUD_CLKID_MST_F_MCLK_SEL]	= &sm1_mst_f_mclk_sel.hw,
> +	[AUD_CLKID_MST_A_MCLK_DIV]	= &sm1_mst_a_mclk_div.hw,
> +	[AUD_CLKID_MST_B_MCLK_DIV]	= &sm1_mst_b_mclk_div.hw,
> +	[AUD_CLKID_MST_C_MCLK_DIV]	= &sm1_mst_c_mclk_div.hw,
> +	[AUD_CLKID_MST_D_MCLK_DIV]	= &sm1_mst_d_mclk_div.hw,
> +	[AUD_CLKID_MST_E_MCLK_DIV]	= &sm1_mst_e_mclk_div.hw,
> +	[AUD_CLKID_MST_F_MCLK_DIV]	= &sm1_mst_f_mclk_div.hw,
> +	[AUD_CLKID_MST_A_MCLK]		= &sm1_mst_a_mclk.hw,
> +	[AUD_CLKID_MST_B_MCLK]		= &sm1_mst_b_mclk.hw,
> +	[AUD_CLKID_MST_C_MCLK]		= &sm1_mst_c_mclk.hw,
> +	[AUD_CLKID_MST_D_MCLK]		= &sm1_mst_d_mclk.hw,
> +	[AUD_CLKID_MST_E_MCLK]		= &sm1_mst_e_mclk.hw,
> +	[AUD_CLKID_MST_F_MCLK]		= &sm1_mst_f_mclk.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK_SEL]	= &spdifout_clk_sel.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK_DIV]	= &spdifout_clk_div.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK]	= &spdifout_clk.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK_SEL]	= &spdifout_b_clk_sel.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK_DIV]	= &spdifout_b_clk_div.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK]	= &spdifout_b_clk.hw,
> +	[AUD_CLKID_SPDIFIN_CLK_SEL]	= &spdifin_clk_sel.hw,
> +	[AUD_CLKID_SPDIFIN_CLK_DIV]	= &spdifin_clk_div.hw,
> +	[AUD_CLKID_SPDIFIN_CLK]		= &spdifin_clk.hw,
> +	[AUD_CLKID_PDM_DCLK_SEL]	= &pdm_dclk_sel.hw,
> +	[AUD_CLKID_PDM_DCLK_DIV]	= &pdm_dclk_div.hw,
> +	[AUD_CLKID_PDM_DCLK]		= &pdm_dclk.hw,
> +	[AUD_CLKID_PDM_SYSCLK_SEL]	= &pdm_sysclk_sel.hw,
> +	[AUD_CLKID_PDM_SYSCLK_DIV]	= &pdm_sysclk_div.hw,
> +	[AUD_CLKID_PDM_SYSCLK]		= &pdm_sysclk.hw,
> +	[AUD_CLKID_MST_A_SCLK_PRE_EN]	= &mst_a_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_B_SCLK_PRE_EN]	= &mst_b_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_C_SCLK_PRE_EN]	= &mst_c_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_D_SCLK_PRE_EN]	= &mst_d_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_E_SCLK_PRE_EN]	= &mst_e_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_F_SCLK_PRE_EN]	= &mst_f_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_A_SCLK_DIV]	= &mst_a_sclk_div.hw,
> +	[AUD_CLKID_MST_B_SCLK_DIV]	= &mst_b_sclk_div.hw,
> +	[AUD_CLKID_MST_C_SCLK_DIV]	= &mst_c_sclk_div.hw,
> +	[AUD_CLKID_MST_D_SCLK_DIV]	= &mst_d_sclk_div.hw,
> +	[AUD_CLKID_MST_E_SCLK_DIV]	= &mst_e_sclk_div.hw,
> +	[AUD_CLKID_MST_F_SCLK_DIV]	= &mst_f_sclk_div.hw,
> +	[AUD_CLKID_MST_A_SCLK_POST_EN]	= &mst_a_sclk_post_en.hw,
> +	[AUD_CLKID_MST_B_SCLK_POST_EN]	= &mst_b_sclk_post_en.hw,
> +	[AUD_CLKID_MST_C_SCLK_POST_EN]	= &mst_c_sclk_post_en.hw,
> +	[AUD_CLKID_MST_D_SCLK_POST_EN]	= &mst_d_sclk_post_en.hw,
> +	[AUD_CLKID_MST_E_SCLK_POST_EN]	= &mst_e_sclk_post_en.hw,
> +	[AUD_CLKID_MST_F_SCLK_POST_EN]	= &mst_f_sclk_post_en.hw,
> +	[AUD_CLKID_MST_A_SCLK]		= &mst_a_sclk.hw,
> +	[AUD_CLKID_MST_B_SCLK]		= &mst_b_sclk.hw,
> +	[AUD_CLKID_MST_C_SCLK]		= &mst_c_sclk.hw,
> +	[AUD_CLKID_MST_D_SCLK]		= &mst_d_sclk.hw,
> +	[AUD_CLKID_MST_E_SCLK]		= &mst_e_sclk.hw,
> +	[AUD_CLKID_MST_F_SCLK]		= &mst_f_sclk.hw,
> +	[AUD_CLKID_MST_A_LRCLK_DIV]	= &mst_a_lrclk_div.hw,
> +	[AUD_CLKID_MST_B_LRCLK_DIV]	= &mst_b_lrclk_div.hw,
> +	[AUD_CLKID_MST_C_LRCLK_DIV]	= &mst_c_lrclk_div.hw,
> +	[AUD_CLKID_MST_D_LRCLK_DIV]	= &mst_d_lrclk_div.hw,
> +	[AUD_CLKID_MST_E_LRCLK_DIV]	= &mst_e_lrclk_div.hw,
> +	[AUD_CLKID_MST_F_LRCLK_DIV]	= &mst_f_lrclk_div.hw,
> +	[AUD_CLKID_MST_A_LRCLK]		= &mst_a_lrclk.hw,
> +	[AUD_CLKID_MST_B_LRCLK]		= &mst_b_lrclk.hw,
> +	[AUD_CLKID_MST_C_LRCLK]		= &mst_c_lrclk.hw,
> +	[AUD_CLKID_MST_D_LRCLK]		= &mst_d_lrclk.hw,
> +	[AUD_CLKID_MST_E_LRCLK]		= &mst_e_lrclk.hw,
> +	[AUD_CLKID_MST_F_LRCLK]		= &mst_f_lrclk.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_SEL]	= &tdmin_a_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_SEL]	= &tdmin_b_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_SEL]	= &tdmin_c_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_SEL]	= &tdmin_lb_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_SEL]	= &tdmout_a_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_SEL]	= &tdmout_b_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_SEL]	= &tdmout_c_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_PRE_EN]	= &tdmin_a_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_PRE_EN]	= &tdmin_b_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_PRE_EN]	= &tdmin_c_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &tdmin_lb_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &tdmout_a_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &tdmout_b_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &tdmout_c_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &tdmin_a_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &tdmin_b_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &tdmin_c_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &tdmin_lb_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &tdmout_a_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &tdmout_b_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &tdmout_c_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK]	= &tdmin_a_sclk.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK]	= &g12a_tdmout_a_sclk.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK]	= &g12a_tdmout_b_sclk.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK]	= &g12a_tdmout_c_sclk.hw,
> +	[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
> +	[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
> +	[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
> +	[AUD_CLKID_TDMIN_LB_LRCLK]	= &tdmin_lb_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_A_LRCLK]	= &tdmout_a_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_B_LRCLK]	= &tdmout_b_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_C_LRCLK]	= &tdmout_c_lrclk.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0]	= &s4_tdm_mclk_pad_0.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1]	= &s4_tdm_mclk_pad_1.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD0]	= &s4_tdm_lrclk_pad_0.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD1]	= &s4_tdm_lrclk_pad_1.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD2]	= &s4_tdm_lrclk_pad_2.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD0]	= &s4_tdm_sclk_pad_0.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD1]	= &s4_tdm_sclk_pad_1.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD2]	= &s4_tdm_sclk_pad_2.hw,
> +	[AUD_CLKID_TOP]			= &sm1_aud_top.hw,
> +	[AUD_CLKID_TORAM]		= &toram.hw,
> +	[AUD_CLKID_EQDRC]		= &eqdrc.hw,
> +	[AUD_CLKID_RESAMPLE_B]		= &resample_b.hw,
> +	[AUD_CLKID_TOVAD]		= &tovad.hw,
> +	[AUD_CLKID_LOCKER]		= &locker.hw,
> +	[AUD_CLKID_SPDIFIN_LB]		= &spdifin_lb.hw,
> +	[AUD_CLKID_FRDDR_D]		= &frddr_d.hw,
> +	[AUD_CLKID_TODDR_D]		= &toddr_d.hw,
> +	[AUD_CLKID_LOOPBACK_B]		= &loopback_b.hw,
> +	[AUD_CLKID_CLK81_EN]		= &sm1_clk81_en.hw,
> +	[AUD_CLKID_SYSCLK_A_DIV]	= &sm1_sysclk_a_div.hw,
> +	[AUD_CLKID_SYSCLK_A_EN]		= &sm1_sysclk_a_en.hw,
> +	[AUD_CLKID_SYSCLK_B_DIV]	= &sm1_sysclk_b_div.hw,
> +	[AUD_CLKID_SYSCLK_B_EN]		= &sm1_sysclk_b_en.hw,
> +	[AUD_CLKID_EARCRX]		= &earcrx.hw,
> +	[AUD_CLKID_EARCRX_CMDC_SEL]	= &sm1_earcrx_cmdc_clk_sel.hw,
> +	[AUD_CLKID_EARCRX_CMDC_DIV]	= &sm1_earcrx_cmdc_clk_div.hw,
> +	[AUD_CLKID_EARCRX_CMDC]		= &sm1_earcrx_cmdc_clk.hw,
> +	[AUD_CLKID_EARCRX_DMAC_SEL]	= &sm1_earcrx_dmac_clk_sel.hw,
> +	[AUD_CLKID_EARCRX_DMAC_DIV]	= &sm1_earcrx_dmac_clk_div.hw,
> +	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0_SEL]		= &s4_tdm_mclk_pad0_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1_SEL]       = &s4_tdm_mclk_pad1_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0_DIV]		= &s4_tdm_mclk_pad0_div.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1_DIV]       = &s4_tdm_mclk_pad1_div.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2]	        = &s4_tdm_mclk_pad_2.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2_SEL]		= &s4_tdm_mclk_pad2_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2_DIV]       = &s4_tdm_mclk_pad2_div.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD3]	= &s4_tdm_sclk_pad_3.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD4]	= &s4_tdm_sclk_pad_4.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD3]	= &s4_tdm_lrclk_pad_3.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD4]	= &s4_tdm_lrclk_pad_4.hw,
> +};
>  
>  /* Convenience table to populate regmap in .probe(). */
>  static struct clk_regmap *const axg_clk_regmaps[] = {
> @@ -1678,6 +1902,174 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
>  	&sm1_earcrx_dmac_clk,
>  };
>  
> +static struct clk_regmap *const s4_clk_regmaps[] = {
> +	&ddr_arb,
> +	&pdm,
> +	&tdmin_a,
> +	&tdmin_b,
> +	&tdmin_c,
> +	&tdmin_lb,
> +	&tdmout_a,
> +	&tdmout_b,
> +	&tdmout_c,
> +	&frddr_a,
> +	&frddr_b,
> +	&frddr_c,
> +	&toddr_a,
> +	&toddr_b,
> +	&toddr_c,
> +	&loopback,
> +	&spdifin,
> +	&spdifout,
> +	&resample,
> +	&spdifout_b,
> +	&sm1_mst_a_mclk_sel,
> +	&sm1_mst_b_mclk_sel,
> +	&sm1_mst_c_mclk_sel,
> +	&sm1_mst_d_mclk_sel,
> +	&sm1_mst_e_mclk_sel,
> +	&sm1_mst_f_mclk_sel,
> +	&sm1_mst_a_mclk_div,
> +	&sm1_mst_b_mclk_div,
> +	&sm1_mst_c_mclk_div,
> +	&sm1_mst_d_mclk_div,
> +	&sm1_mst_e_mclk_div,
> +	&sm1_mst_f_mclk_div,
> +	&sm1_mst_a_mclk,
> +	&sm1_mst_b_mclk,
> +	&sm1_mst_c_mclk,
> +	&sm1_mst_d_mclk,
> +	&sm1_mst_e_mclk,
> +	&sm1_mst_f_mclk,
> +	&spdifout_clk_sel,
> +	&spdifout_clk_div,
> +	&spdifout_clk,
> +	&spdifin_clk_sel,
> +	&spdifin_clk_div,
> +	&spdifin_clk,
> +	&pdm_dclk_sel,
> +	&pdm_dclk_div,
> +	&pdm_dclk,
> +	&pdm_sysclk_sel,
> +	&pdm_sysclk_div,
> +	&pdm_sysclk,
> +	&mst_a_sclk_pre_en,
> +	&mst_b_sclk_pre_en,
> +	&mst_c_sclk_pre_en,
> +	&mst_d_sclk_pre_en,
> +	&mst_e_sclk_pre_en,
> +	&mst_f_sclk_pre_en,
> +	&mst_a_sclk_div,
> +	&mst_b_sclk_div,
> +	&mst_c_sclk_div,
> +	&mst_d_sclk_div,
> +	&mst_e_sclk_div,
> +	&mst_f_sclk_div,
> +	&mst_a_sclk_post_en,
> +	&mst_b_sclk_post_en,
> +	&mst_c_sclk_post_en,
> +	&mst_d_sclk_post_en,
> +	&mst_e_sclk_post_en,
> +	&mst_f_sclk_post_en,
> +	&mst_a_sclk,
> +	&mst_b_sclk,
> +	&mst_c_sclk,
> +	&mst_d_sclk,
> +	&mst_e_sclk,
> +	&mst_f_sclk,
> +	&mst_a_lrclk_div,
> +	&mst_b_lrclk_div,
> +	&mst_c_lrclk_div,
> +	&mst_d_lrclk_div,
> +	&mst_e_lrclk_div,
> +	&mst_f_lrclk_div,
> +	&mst_a_lrclk,
> +	&mst_b_lrclk,
> +	&mst_c_lrclk,
> +	&mst_d_lrclk,
> +	&mst_e_lrclk,
> +	&mst_f_lrclk,
> +	&tdmin_a_sclk_sel,
> +	&tdmin_b_sclk_sel,
> +	&tdmin_c_sclk_sel,
> +	&tdmin_lb_sclk_sel,
> +	&tdmout_a_sclk_sel,
> +	&tdmout_b_sclk_sel,
> +	&tdmout_c_sclk_sel,
> +	&tdmin_a_sclk_pre_en,
> +	&tdmin_b_sclk_pre_en,
> +	&tdmin_c_sclk_pre_en,
> +	&tdmin_lb_sclk_pre_en,
> +	&tdmout_a_sclk_pre_en,
> +	&tdmout_b_sclk_pre_en,
> +	&tdmout_c_sclk_pre_en,
> +	&tdmin_a_sclk_post_en,
> +	&tdmin_b_sclk_post_en,
> +	&tdmin_c_sclk_post_en,
> +	&tdmin_lb_sclk_post_en,
> +	&tdmout_a_sclk_post_en,
> +	&tdmout_b_sclk_post_en,
> +	&tdmout_c_sclk_post_en,
> +	&tdmin_a_sclk,
> +	&tdmin_b_sclk,
> +	&tdmin_c_sclk,
> +	&tdmin_lb_sclk,
> +	&g12a_tdmout_a_sclk,
> +	&g12a_tdmout_b_sclk,
> +	&g12a_tdmout_c_sclk,
> +	&tdmin_a_lrclk,
> +	&tdmin_b_lrclk,
> +	&tdmin_c_lrclk,
> +	&tdmin_lb_lrclk,
> +	&tdmout_a_lrclk,
> +	&tdmout_b_lrclk,
> +	&tdmout_c_lrclk,
> +	&spdifout_b_clk_sel,
> +	&spdifout_b_clk_div,
> +	&spdifout_b_clk,
> +	&s4_tdm_mclk_pad_0,
> +	&s4_tdm_mclk_pad_1,
> +	&s4_tdm_lrclk_pad_0,
> +	&s4_tdm_lrclk_pad_1,
> +	&s4_tdm_lrclk_pad_2,
> +	&s4_tdm_sclk_pad_0,
> +	&s4_tdm_sclk_pad_1,
> +	&s4_tdm_sclk_pad_2,
> +	&sm1_aud_top,
> +	&toram,
> +	&eqdrc,
> +	&resample_b,
> +	&tovad,
> +	&locker,
> +	&spdifin_lb,
> +	&frddr_d,
> +	&toddr_d,
> +	&loopback_b,
> +	&sm1_clk81_en,
> +	&sm1_sysclk_a_div,
> +	&sm1_sysclk_a_en,
> +	&sm1_sysclk_b_div,
> +	&sm1_sysclk_b_en,
> +	&earcrx,
> +	&sm1_earcrx_cmdc_clk_sel,
> +	&sm1_earcrx_cmdc_clk_div,
> +	&sm1_earcrx_cmdc_clk,
> +	&sm1_earcrx_dmac_clk_sel,
> +	&sm1_earcrx_dmac_clk_div,
> +	&sm1_earcrx_dmac_clk,
> +	&s4_tdm_mclk_pad0_sel,
> +	&s4_tdm_mclk_pad1_sel,
> +	&s4_tdm_mclk_pad0_div,
> +	&s4_tdm_mclk_pad1_div,
> +	&s4_tdm_mclk_pad_2,
> +	&s4_tdm_mclk_pad2_sel,
> +	&s4_tdm_mclk_pad2_div,
> +	&s4_tdm_sclk_pad_3,
> +	&s4_tdm_sclk_pad_4,
> +	&s4_tdm_lrclk_pad_3,
> +	&s4_tdm_lrclk_pad_4,
> +};
> +
>  struct axg_audio_reset_data {
>  	struct reset_controller_dev rstc;
>  	struct regmap *map;
> @@ -1822,7 +2214,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>  			continue;
>  
>  		name = hw->init->name;
> -
>  		ret = devm_clk_hw_register(dev, hw);
>  		if (ret) {
>  			dev_err(dev, "failed to register clock %s\n", name);
> @@ -1886,6 +2277,18 @@ static const struct audioclk_data sm1_audioclk_data = {
>  	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
>  };
>  
> +static const struct audioclk_data s4_audioclk_data = {
> +	.regmap_clks = s4_clk_regmaps,
> +	.regmap_clk_num = ARRAY_SIZE(s4_clk_regmaps),
> +	.hw_clks = {
> +		.hws = s4_audio_hw_clks,
> +		.num = ARRAY_SIZE(s4_audio_hw_clks),
> +	},
> +	.reset_offset = AUDIO_SM1_SW_RESET0,
> +	.reset_num = 39,
> +	.max_register = AUDIO_S4_SCLK_PAD_CTRL1,
> +};
> +
>  static const struct of_device_id clkc_match_table[] = {
>  	{
>  		.compatible = "amlogic,axg-audio-clkc",
> @@ -1896,7 +2299,10 @@ static const struct of_device_id clkc_match_table[] = {
>  	}, {
>  		.compatible = "amlogic,sm1-audio-clkc",
>  		.data = &sm1_audioclk_data
> -	}, {}
> +	}, {
> +		.compatible = "amlogic,s4-audio-clkc",
> +		.data = &s4_audioclk_data
> +	}, { }
>  };
>  MODULE_DEVICE_TABLE(of, clkc_match_table);
>  
> diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
> index 9e7765b630c96a8029140539ffda789b7db5277a..2dd1c41d775da8f91ed281470d06e9c970cfc92c 100644
> --- a/drivers/clk/meson/axg-audio.h
> +++ b/drivers/clk/meson/axg-audio.h
> @@ -66,5 +66,9 @@
>  #define AUDIO_CLK81_EN		0x034
>  #define AUDIO_EARCRX_CMDC_CLK_CTRL	0x0D0
>  #define AUDIO_EARCRX_DMAC_CLK_CTRL	0x0D4

Judging by the DT posted, there is plenty in between of non-clock
component in between these 2 offsets/regions

> +#define AUDIO_S4_MCLK_PAD_CTRL0 0xE80
> +#define AUDIO_S4_MCLK_PAD_CTRL1 0xE84
> +#define AUDIO_S4_SCLK_PAD_CTRL0 0xE88
> +#define AUDIO_S4_SCLK_PAD_CTRL1 0xE8C
>

... and this is not even mapped by the clock controller, so this won't
work with the DT you have posted.

>  #endif /*__AXG_AUDIO_CLKC_H */

-- 
Jerome


From ziyao at disroot.org  Thu Mar  6 08:43:54 2025
From: ziyao at disroot.org (Yao Zi)
Date: Thu, 6 Mar 2025 16:43:54 +0000
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers
 for RK3528
In-Reply-To: <20250306140009.384469-1-amadeus@jmu.edu.cn>
References: <20250305194612.47171-1-ziyao@disroot.org>
 <20250306140009.384469-1-amadeus@jmu.edu.cn>
Message-ID: <Z8nPjjbZvpRJ2R5B@pie.lan>

On Thu, Mar 06, 2025 at 10:00:09PM +0800, Chukun Pan wrote:
> Hi,
> 
> > +		sdio0: mmc at ffc10000 {
> > +			compatible = "rockchip,rk3528-dw-mshc",
> > +				     "rockchip,rk3288-dw-mshc";
> > +			reg = <0x0 0xffc10000 0x0 0x4000>;
> > +			clocks = <&cru HCLK_SDIO0>,
> > +				 <&cru CCLK_SRC_SDIO0>,
> > +				 <&cru SCLK_SDIO0_DRV>,
> > +				 <&cru SCLK_SDIO0_SAMPLE>;
> > +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> > +			fifo-depth = <0x100>;
> > +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> > +			max-frequency = <150000000>;
> > +			pinctrl-names = "default";
> > +			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
> > +				    <&sdio0_det>, <&sdio0_pwren>;
> 
> The sdio module is usually "non-removable", no need det,
> and pwren may be other gpio (use mmc-pwrseq). So it should
> be `pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>;`

This doesn't affect the fact that these two pins are assigned as
functional pins for SDIO0, as pointed out by the datasheet[1].

But with more digging, I found the reference design[2] of Rockchip
actually uses the two pins as normal GPIOs. This is more obvious in
downstream devicetree of an EVB[3]. Most of the existing boards (Radxa
2A, ArmSOM Sige 1) follow the reference design.

For me, it's kind of surprising that the SDIO IP functions with two
functional pins assigned as different modes. I'm not sure whether we
should apply pin configuration for these two pins in the SoC devicetree.
Jonas, what do you think about it?

> > +			resets = <&cru SRST_H_SDIO0>;
> > +			reset-names = "reset";
> > +			status = "disabled";
> > +		};
> > +
> > +		sdio1: mmc at ffc20000 {
> > +			compatible = "rockchip,rk3528-dw-mshc",
> > +				     "rockchip,rk3288-dw-mshc";
> > +			reg = <0x0 0xffc20000 0x0 0x4000>;
> > +			clocks = <&cru HCLK_SDIO1>,
> > +				 <&cru CCLK_SRC_SDIO1>,
> > +				 <&cru SCLK_SDIO1_DRV>,
> > +				 <&cru SCLK_SDIO1_SAMPLE>;
> > +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> > +			fifo-depth = <0x100>;
> > +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> > +			max-frequency = <150000000>;
> > +			pinctrl-names = "default";
> > +			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
> > +				    <&sdio1_det>, <&sdio1_pwren>;
> 
> Same here.
> 
> > +			resets = <&cru SRST_H_SDIO1>;
> > +			reset-names = "reset";
> > +			status = "disabled";
> > +		};
> 
> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Best regards,
Yao Zi

[1]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/Rockchip%C2%A0RK3528%C2%A0Datasheet%C2%A0V1.0-20230522.pdf
[2]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/RK3528_BOX_REF_V10_20230525.pdf
[3]: https://github.com/rockchip-linux/kernel/blob/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi#L128


From linux at martijnvandeventer.nl  Thu Mar  6 08:48:33 2025
From: linux at martijnvandeventer.nl (linux at martijnvandeventer.nl)
Date: Thu, 6 Mar 2025 17:48:33 +0100
Subject: [PATCH] clk: meson: g12a: Fix kernel warnings when no display attached
In-Reply-To: <1jplj3g21q.fsf@starbuckisacylon.baylibre.com>
References: <20250213221702.606-1-linux@martijnvandeventer.nl>	<1jpljkzyf0.fsf@starbuckisacylon.baylibre.com>	<003301db888e$8ea84e90$abf8ebb0$@martijnvandeventer.nl> <1jplj3g21q.fsf@starbuckisacylon.baylibre.com>
Message-ID: <004801db8eb7$99808e20$cc81aa60$@martijnvandeventer.nl>

Hi Jerome,

> >
> > Thank you for reviewing, and apologies for my late response due to a
> holiday.
> >
> >> On Thu 13 Feb 2025 at 23:17, Martijn van Deventer
> >> <linux at martijnvandeventer.nl> wrote:
> >>
> >> > When booting SM1 or G12A boards without a dislay attached to HDMI,
> >> > the kernel shows the following warning:
> >> >
> >> > [CRTC:46:meson_crtc] vblank wait timed out
> >> > WARNING: CPU: 2 PID: 265 at
> drivers/gpu/drm/drm_atomic_helper.c:1682
> >> drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
> >> > CPU: 2 UID: 0 PID: 265 Comm: setfont Tainted: G         C
> >> > Tainted: [C]=CRAP
> >> > pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> >> > pc : drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
> >> > lr : drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
> >> > Call trace:
> >> >  drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
> >> >  drm_atomic_helper_commit_tail_rpm+0x84/0xa0
> >> >  commit_tail+0xa4/0x18c
> >> >  drm_atomic_helper_commit+0x164/0x178
> >> >  drm_atomic_commit+0xb4/0xec
> >> >  drm_client_modeset_commit_atomic+0x210/0x270
> >> >  drm_client_modeset_commit_locked+0x5c/0x188
> >> >  drm_fb_helper_pan_display+0xb8/0x1d4
> >> >  fb_pan_display+0x7c/0x120
> >> >  bit_update_start+0x20/0x48
> >> >  fbcon_switch+0x418/0x54c
> >> >  el0t_64_sync+0x194/0x198
> >> >
> >> > This happens when the kernel disables the unused clocks.
> >> > Sometimes this causes the boot to hang.
> >> >
> >> > By (re)adding the flag CLK_IGNORE_UNUSED to the VCLK2 clocks, these
> >> > clocks will not be disabled.
> >> >
> >> > This partially reverts commit b70cb1a21a54 ("clk: meson: g12a:
> >> > make VCLK2 and ENCL clock path configurable by CCF").
> >>
> >> It looks like DRM needs those clock enabled regardless of connection
> >> status on HDMI. Even with this change applied, you would get the same
> >> problem again if the bootloader does not take of turning the clock on,
> >> which is not a given.
> >>
> >> CLK_IGNORE_UNUSED gives not guarantee a clock will be enabled or stay
> >> enabled at any point.
> >>
> >> A proper fix to this issue should be done in DRM, IMO.
> >
> > I know and I totally agree. Unfortunately, I don't have access to any 
> > vendor
> > documentation, nor do I have any real knowledge about the DRM/HDMI
> > subsystem to fix that.
>
> You have identified which clocks are not properly claimed, by what they
> are not claimed and even when. 50% of the job is done. Thanks for this.

You're welcome, no problem.

> >
> > And I guess if it were as easy as adding a clock to the DT and calling
> > clk_prepare_enable on it in the probe function, Neil would have done
> that
> > already.
> >
> > So, all I can do, for now, is revert to the previous situation when it 
> > did
> work
> > for (probably) most boards.
>
> Maybe so, but it does not make this change appropriate. The problem
> is the DRM driver which does not enable what it needs to properly
> operate. This should be fixed.

I understand. So I guess that is the end of the line for this patch.
Because this patch will not be accepted and if someone else finds the 
time and has the knowledge to fix this the proper way, it will be a 
completely different patch.

Although I, of course, agree with you that it should be fixed properly, 
I find it a bit difficult to accept that if we accidentally break something,
while trying to make things better, we are not allowed to revert it 
because it was already somewhat broken. Resulting in a more broken
situation than before...

On the other hand, I also understand that if you, as a maintainer, allow 
that, chances are it will never see a proper fix. :-)

Cheers!

> >
> >> >
> >> > Fixes: b70cb1a21a54 ("clk: meson: g12a: make VCLK2 and ENCL clock
> path
> >> configurable by CCF").
> >> > Signed-off-by: Martijn van Deventer <linux at martijnvandeventer.nl>
> >> > ---
> >> >  drivers/clk/meson/g12a.c | 12 ++++++------
> >> >  1 file changed, 6 insertions(+), 6 deletions(-)
> >> >
> >> > diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> >> > index cfffd434e998..1651898658f5 100644
> >> > --- a/drivers/clk/meson/g12a.c
> >> > +++ b/drivers/clk/meson/g12a.c
> >> > @@ -3234,7 +3234,7 @@ static struct clk_regmap g12a_vclk2_div = {
--
Best regards,
Martijn



From mike.leach at linaro.org  Thu Mar  6 08:57:35 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Thu, 6 Mar 2025 16:57:35 +0000
Subject: [PATCH v3 2/7] coresight: Add coresight TGU driver
In-Reply-To: <20250227092640.2666894-3-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com> <20250227092640.2666894-3-quic_songchai@quicinc.com>
Message-ID: <CAJ9a7Vip6Dda1q7R_LoQjB4696Yi3iDv6512Vsy6aqdpiPTWgw@mail.gmail.com>

Hi,

On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>
> From: Songwei Chai <quic_songchai at quicinc.com>
>
> Add driver to support Coresight device TGU (Trigger Generation Unit).
> TGU is a Data Engine which can be utilized to sense a plurality of
> signals and create a trigger into the CTI or generate interrupts to
> processors. Add probe/enable/disable functions for tgu.
>
> Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> Signed-off-by: songchai <quic_songchai at quicinc.com>
> ---
>  .../testing/sysfs-bus-coresight-devices-tgu   |   9 +
>  drivers/hwtracing/coresight/Kconfig           |  11 +
>  drivers/hwtracing/coresight/Makefile          |   1 +
>  drivers/hwtracing/coresight/coresight-tgu.c   | 218 ++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-tgu.h   |  36 +++
>  5 files changed, 275 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
>  create mode 100644 drivers/hwtracing/coresight/coresight-tgu.c
>  create mode 100644 drivers/hwtracing/coresight/coresight-tgu.h
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> new file mode 100644
> index 000000000000..741bc9fd9df5
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> @@ -0,0 +1,9 @@
> +What:          /sys/bus/coresight/devices/<tgu-name>/enable_tgu
> +Date:          February 2025
> +KernelVersion  6.15
> +Contact:       Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
> +Description:
> +               (RW) Set/Get the enable/disable status of TGU
> +               Accepts only one of the 2 values -  0 or 1.
> +               0 : disable TGU.
> +               1 : enable TGU.
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index 06f0a7594169..3fe59c745dd4 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -247,4 +247,15 @@ config CORESIGHT_DUMMY
>
>           To compile this driver as a module, choose M here: the module will be
>           called coresight-dummy.
> +
> +config CORESIGHT_TGU
> +       tristate "CoreSight Trigger Generation Unit driver"
> +       help
> +         This driver provides support for Trigger Generation Unit that is
> +         used to detect patterns or sequences on a given set of signals.
> +         TGU is used to monitor a particular bus within a given region to
> +         detect illegal transaction sequences or slave responses. It is also
> +         used to monitor a data stream to detect protocol violations and to
> +         provide a trigger point for centering data around a specific event
> +         within the trace data buffer.
>  endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 4ba478211b31..7c2b9e9cf1cd 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -51,3 +51,4 @@ coresight-cti-y := coresight-cti-core.o       coresight-cti-platform.o \
>                    coresight-cti-sysfs.o
>  obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>  obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
> +obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o
> diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c
> new file mode 100644
> index 000000000000..da4c04ac1097
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-tgu.c
> @@ -0,0 +1,218 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/amba/bus.h>
> +#include <linux/coresight.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +
> +#include "coresight-priv.h"
> +#include "coresight-tgu.h"
> +
> +DEFINE_CORESIGHT_DEVLIST(tgu_devs, "tgu");
> +
> +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
> +{
> +       CS_UNLOCK(drvdata->base);
> +       /* Enable TGU to program the triggers */
> +       tgu_writel(drvdata, 1, TGU_CONTROL);
> +       CS_LOCK(drvdata->base);
> +}
> +
> +static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode,
> +                     void *data)
> +{
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +       spin_lock(&drvdata->spinlock);
> +
> +       if (drvdata->enable) {
> +               spin_unlock(&drvdata->spinlock);
> +               return -EBUSY;
> +       }
> +       tgu_write_all_hw_regs(drvdata);
> +       drvdata->enable = true;
> +
> +       spin_unlock(&drvdata->spinlock);
> +       return 0;
> +}
> +
> +static int tgu_disable(struct coresight_device *csdev, void *data)
> +{
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +       spin_lock(&drvdata->spinlock);
> +
> +       if (!drvdata->enable) {

Could simplify by changing logic here -
if (enable) { do disable stuff }

and have a single return point

> +               spin_unlock(&drvdata->spinlock);
> +               return 0;
> +       }
> +
> +       CS_UNLOCK(drvdata->base);
> +       tgu_writel(drvdata, 0, TGU_CONTROL);
> +       CS_LOCK(drvdata->base);
> +
> +       drvdata->enable = false;
> +       spin_unlock(&drvdata->spinlock);
> +       return 0;
> +}
> +
> +static ssize_t enable_tgu_show(struct device *dev,
> +                              struct device_attribute *attr, char *buf)
> +{
> +       bool enabled;
> +
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +       spin_lock(&drvdata->spinlock);
> +       enabled = drvdata->enable;
> +       spin_unlock(&drvdata->spinlock);
> +
> +       return sprintf(buf, "%d\n", enabled);

sysfs_emit() should be used here.

> +}
> +
> +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */
> +static ssize_t enable_tgu_store(struct device *dev,
> +                               struct device_attribute *attr, const char *buf,
> +                               size_t size)
> +{
> +       int ret = 0;
> +       unsigned long val;
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +       ret = kstrtoul(buf, 0, &val);
> +       if (ret)
> +               return ret;
> +
> +       if (val) {
> +               ret = pm_runtime_resume_and_get(dev->parent);
> +               if (ret)
> +                       return ret;
> +               ret = tgu_enable(drvdata->csdev, CS_MODE_SYSFS, NULL);
> +               if (ret)
> +                       pm_runtime_put(dev->parent);
> +       } else {
> +               ret = tgu_disable(drvdata->csdev, NULL);
> +               if (!ret)


redundant - tgu_disable always returns 0.

> +                       pm_runtime_put(dev->parent);
> +       }
> +
> +       if (ret)
> +               return ret;
> +       return size;
> +}
> +static DEVICE_ATTR_RW(enable_tgu);
> +
> +static const struct coresight_ops_helper tgu_helper_ops = {
> +       .enable = tgu_enable,
> +       .disable = tgu_disable,
> +};
> +
> +static const struct coresight_ops tgu_ops = {
> +       .helper_ops = &tgu_helper_ops,
> +};
> +
> +static struct attribute *tgu_common_attrs[] = {
> +       &dev_attr_enable_tgu.attr,
> +       NULL,
> +};
> +
> +static const struct attribute_group tgu_common_grp = {
> +       .attrs = tgu_common_attrs,
> +       NULL,
> +};
> +
> +static const struct attribute_group *tgu_attr_groups[] = {
> +       &tgu_common_grp,
> +       NULL,
> +};
> +
> +static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +       int ret = 0;
> +       struct device *dev = &adev->dev;
> +       struct coresight_desc desc = { 0 };
> +       struct coresight_platform_data *pdata;
> +       struct tgu_drvdata *drvdata;
> +
> +       desc.name = coresight_alloc_device_name(&tgu_devs, dev);
> +       if (!desc.name)
> +               return -ENOMEM;
> +
> +       pdata = coresight_get_platform_data(dev);
> +       if (IS_ERR(pdata))
> +               return PTR_ERR(pdata);
> +
> +       adev->dev.platform_data = pdata;
> +
> +       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +       if (!drvdata)
> +               return -ENOMEM;
> +
> +       drvdata->dev = &adev->dev;
> +       dev_set_drvdata(dev, drvdata);
> +
> +       drvdata->base = devm_ioremap_resource(dev, &adev->res);
> +       if (!drvdata->base)
> +               return -ENOMEM;
> +
> +       spin_lock_init(&drvdata->spinlock);
> +
> +       drvdata->enable = false;
> +       desc.type = CORESIGHT_DEV_TYPE_HELPER;
> +       desc.pdata = adev->dev.platform_data;
> +       desc.dev = &adev->dev;
> +       desc.ops = &tgu_ops;
> +       desc.groups = tgu_attr_groups;
> +
> +       drvdata->csdev = coresight_register(&desc);
> +       if (IS_ERR(drvdata->csdev)) {
> +               ret = PTR_ERR(drvdata->csdev);
> +               goto err;
> +       }
> +
> +       pm_runtime_put(&adev->dev);
> +       return 0;
> +err:
> +       pm_runtime_put(&adev->dev);
> +       return ret;
> +}
> +
> +static void tgu_remove(struct amba_device *adev)
> +{
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
> +
> +       coresight_unregister(drvdata->csdev);
> +}
> +
> +static const struct amba_id tgu_ids[] = {
> +       {
> +               .id = 0x000f0e00,
> +               .mask = 0x000fffff,
> +               .data = "TGU",
> +       },
> +       { 0, 0, NULL },
> +};
> +
> +MODULE_DEVICE_TABLE(amba, tgu_ids);
> +
> +static struct amba_driver tgu_driver = {
> +       .drv = {
> +               .name = "coresight-tgu",
> +               .suppress_bind_attrs = true,
> +       },
> +       .probe  = tgu_probe,
> +       .remove = tgu_remove,
> +       .id_table       = tgu_ids,
> +};
> +
> +module_amba_driver(tgu_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("CoreSight TGU driver");
> diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h
> new file mode 100644
> index 000000000000..380686f94130
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-tgu.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _CORESIGHT_TGU_H
> +#define _CORESIGHT_TGU_H
> +
> +/* Register addresses */
> +#define TGU_CONTROL 0x0000
> +
> +/* Register read/write */
> +#define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
> +#define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off)
> +
> +/**
> + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) device
> + * @base: Memory-mapped base address of the TGU device
> + * @dev: Pointer to the associated device structure
> + * @csdev: Pointer to the associated coresight device
> + * @spinlock: Spinlock for handling concurrent access
> + * @enable: Flag indicating whether the TGU device is enabled
> + *
> + * This structure defines the data associated with a TGU device, including its base
> + * address, device pointers, clock, spinlock for synchronization, trigger data pointers,

I don't see any trigger data pointers or limits here. Comment on what
is there, if more is added later, expand the comment later.

> + * maximum limits for various trigger-related parameters, and enable status.
> + */
> +struct tgu_drvdata {
> +       void __iomem *base;
> +       struct device *dev;
> +       struct coresight_device *csdev;
> +       spinlock_t spinlock;
> +       bool enable;
> +};
> +
> +#endif
>

Regards

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From mike.leach at linaro.org  Thu Mar  6 08:57:46 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Thu, 6 Mar 2025 16:57:46 +0000
Subject: [PATCH v3 0/7] Provides support for Trigger Generation Unit
In-Reply-To: <20250227092640.2666894-1-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com>
Message-ID: <CAJ9a7ViFu6tP7wac-6NPOBOCHw2iA+gs6D=D4um-T07Syu-8CA@mail.gmail.com>

Hi,

On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>
> Provide support for the TGU (Trigger Generation Unit), which can be
> utilized to sense a plurality of signals and create a trigger into
> the CTI or generate interrupts to processors once the input signal
> meets the conditions. We can treat the TGU?s workflow as a flowsheet,
> it has some ?steps? regions for customization. In each step region,
> we can set the signals that we want with priority in priority_group, set
> the conditions in each step via condition_decode, and set the resultant
> action by condition_select. Meanwhile, some TGUs (not all) also provide
> timer/counter functionality. Based on the characteristics described
> above, we consider the TGU as a helper in the CoreSight subsystem.
> Its master device is the TPDM, which can transmit signals from other
> subsystems, and we reuse the existing ports mechanism to link the TPDM to
> the connected TGU.
>

I do not believe that his component is part of the Coresight subsystem.

1) It inputs multiple signals from the SoC to process and create an
trigger event - however, it can do this irrespective of CoreSight
trace being operational, especially where generating interrupts for
processors, or triggers for other non-coresight components. It would
appear that the TPDM can send output to more than just the TDPA which
generates coresight trace packets - a previously undisclosed feature.

2) The ports mechanism is a generic device tree mechanism, not
something unique to the Coresight subsystem.

3) The CTI trigger connection will be defined in devicetree under the
CTI component, as this is the interface between this component and
coresight.

As such this seems more like a general performance and debug
component, with optional inputs to the coresight trigger mechanisms,
rather than being a coresight component itself. Other SoCs have
non-coresight component inputs to CTIs. For example the PL011 serial
device on Juno has a signal into one of the system CTIs.

> Here is a detailed example to explain how to use the TGU:
>
> In this example, the TGU is configured to use 2 conditions, 2 steps, and
> the timer. The goal is to look for one of two patterns which are generated
> from TPDM, giving priority to one, and then generate a trigger once the
> timer reaches a certain value. In other words, two conditions are used
> for the first step to look for the two patterns, where the one with the
> highest priority is used in the first condition. Then, in the second step,
> the timer is enabled and set to be compared to the given value at each
> clock cycle. These steps are better shown below.
>
>
>             |-----------------|
>             |                 |
>             |       TPDM      |
>             |                 |
>             |-----------------|
>                      |
>                      |
>   --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ------
>   |                  |                                                 |
>   |                  |                          |--------------------| |
>   |    |---- --->    |                          |  Go to next steps  | |
>   |    |             |                |--- ---> |  Enable timer      | |
>   |    |             v                |         |                    | |
>   |    |    |-----------------|       |         |--------------------| |
>   |    |    |                 |  Yes  |                    |           |
>   |    |    |   inputs==0xB   | ----->|                    | <-------- |
>   |    |    |                 |       |                    |      No | |
>   | No |    |-----------------|       |                    v         | |
>   |    |             |                |          |-----------------| | |
>   |    |             |                |          |                 | | |
>   |    |             |                |          |      timer>=3   |-- |
>   |    |             v                |          |                 |   |
>   |    |    |-----------------|       |          |-----------------|   |
>   |    |    |                 |  Yes  |                    |           |
>   |    |--- |   inputs==0xA   | ----->|                    | Yes       |
>   |         |                 |                            |           |
>   |         |-----------------|                            v           |
>   |                                              |-----------------|   |
>   |                                              |                 |   |
>   |                                              |      Trigger    |   |
>   |                                              |                 |   |
>   |                                              |-----------------|   |
>   |  TGU                                                   |           |
>   |--- --- --- --- --- --- --- --- --- --- --- --- --- --- |--- --- -- |
>                                                            |
>                                                            v
>                                                   |-----------------|
>                                                   |The controllers  |
>                                                   |which will use   |
>                                                   |triggers further |
>                                                   |-----------------|
>
> steps:
>        1. Reset TGU /*it will disable tgu and reset dataset*/
>        - echo 1 > /sys/bus/coresight/devices/<tgu-name>/reset_tgu
>
>        2. Set the pattern match for priority0 to 0xA = 0b1010 and for
>           priority 1 to 0xB = 0b1011.
>        - echo 0x11113232 > /sys/bus/coresight/devices/<tgu-name>/step0_priority0/reg0
>        - echo 0x11113233 > /sys/bus/coresight/devices/<tgu-name>/step0_priority1/reg0
>
>        Note:
>             Bit distribution diagram for each priority register
>     |-------------------------------------------------------------------|
>     |   Bits          |       Field Nam   |    Description              |
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |     29:28       |   SEL_BIT7_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |     25:24       |   SEL_BIT6_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |     21:20       |   SEL_BIT5_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |     17:16       |   SEL_BIT4_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |     13:12       |   SEL_BIT3_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |      9:8        |   SEL_BIT2_TYPE2  | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |      5:4        |  SEL_BIT1_TYPE2   | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>     |                 |                   | 00 = bypass for OR output   |
>     |      1:0        |  SEL_BIT0_TYPE2   | 01 = bypass for AND output  |
>     |                 |                   | 10 = sense input '0' is true|
>     |                 |                   | 11 = sense input '1' is true|
>     |-------------------------------------------------------------------|
>         These bits are used to identify the signals we want to sense, with
>         a maximum signal number of 140. For example, to sense the signal
>         0xA (binary 1010), we set the value of bits 0 to 13 to 3232, which
>         represents 1010. The remaining bits are set to 1, as we want to use
>         AND gate to summarize all the signals we want to sense here. For
>         rising or falling edge detection of any input to the priority, set
>         the remaining bits to 0 to use an OR gate.
>
>        3. look for the pattern for priority_i i=0,1.
>        - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg0
>        - echo 0x30 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg1
>
>     |-------------------------------------------------------------------------------|
>     |   Bits          |    Field Nam        |            Description                |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |For each decoded condition, this       |
>     |      24         |       NOT           |inverts the output. If the condition   |
>     |                 |                     |decodes to true, and the NOT field     |
>     |                 |                     |is '1', then the output is NOT true.   |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from the associated|
>     |      21         |  BC0_COMP_ACTIVE    |comparator will be actively included in|
>     |                 |                     |the decoding of this particular        |
>     |                 |                     |condition.                             |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from the associated|
>     |                 |                     |comparator will need to be 1 to affect |
>     |      20         |   BC0_COMP_HIGH     |the decoding of this condition.        |
>     |                 |                     |Conversely, a '0' here requires a '0'  |
>     |                 |                     |from the comparator                    |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from the associated|
>     |      17         |                     |comparator will be actively included in|
>     |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
>     |                 |                     |condition.                             |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from the associated|
>     |                 |                     |comparator will need to be 1 to affect |
>     |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
>     |                 |                     |condition.Conversely, a 0 here         |
>     |                 |                     |requires a '0' from the comparator     |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from Priority_n    |
>     |                 |                     |OR logic will be actively              |
>     |     4n+3        | Priority_n_OR_ACTIVE|included in the decoding of            |
>     |                 |    (n=0,1,2,3)      |this particular condition.             |
>     |                 |                     |                                       |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from Priority_n    |
>     |                 |                     |will need to be '1' to affect the      |
>     |     4n+2        |  Priority_n_OR_HIGH |decoding of this particular            |
>     |                 |    (n=0,1,2,3)      |condition. Conversely, a '0' here      |
>     |                 |                     |requires a '0' from Priority_n OR logic|
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from Priority_n    |
>     |                 |                     |AND logic will be actively             |
>     |     4n+1        |Priority_n_AND_ACTIVE|included in the decoding of this       |
>     |                 |  (n=0,1,2,3)        |particular condition.                  |
>     |                 |                     |                                       |
>     |-------------------------------------------------------------------------------|
>     |                 |                     |When '1' the output from Priority_n    |
>     |                 |                     |AND logic will need to be '1' to       |
>     |      4n         | Priority_n_AND_HIGH |affect the decoding of this            |
>     |                 |   (n=0,1,2,3)       |particular condition. Conversely,      |
>     |                 |                     |a '0' here requires a '0' from         |
>     |                 |                     |Priority_n AND logic.                  |
>     |-------------------------------------------------------------------------------|
>         Since we use `priority_0` and `priority_1` with an AND output in step 2, we set `0x3`
>         and `0x30` here to activate them.
>
>        4. Set NEXT_STEP = 1 and TC0_ENABLE = 1 so that when the conditions
>           are met then the next step will be step 1 and the timer will be enabled.
>        - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg0
>        - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg1
>
>         |-----------------------------------------------------------------------------|
>         |   Bits          |       Field Nam   |            Description                |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This field defines the next step the   |
>         |    18:17        |     NEXT_STEP     |TGU will 'goto' for the associated     |
>         |                 |                   |Condition and Step.                    |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |For each possible output trigger       |
>         |    13           |     TRIGGER       |available, set a '1' if you want       |
>         |                 |                   |the trigger to go active for the       |
>         |                 |                   |associated condition and Step.         |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will cause BC0 to increment if the|
>         |    9            |     BC0_INC       |associated Condition is decoded for    |
>         |                 |                   |this step.                             |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will cause BC0 to decrement if the|
>         |    8            |     BC0_DEC       |associated Condition is decoded for    |
>         |                 |                   |this step.                             |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will clear BC0 count value to 0 if|
>         |    7            |     BC0_CLEAR     |the associated Condition is decoded    |
>         |                 |                   |for this step.                         |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will cause TC0 to increment until |
>         |    3            |     TC0_ENABLE    |paused or cleared if the associated    |
>         |                 |                   |Condition is decoded for this step.    |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will cause TC0 to pause until     |
>         |    2            |     TC0_PAUSE     |enabled if the associated Condition    |
>         |                 |                   |is decoded for this step.              |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will clear TC0 count value to 0   |
>         |    1            |     TC0_CLEAR     |if the associated Condition is         |
>         |                 |                   |decoded for this step.                 |
>         |-----------------------------------------------------------------------------|
>         |                 |                   |This will set the done signal to the   |
>         |    0            |     DONE          |TGU FSM if the associated Condition    |
>         |                 |                   |is decoded for this step.              |
>         |-----------------------------------------------------------------------------|
>         Based on the distribution diagram, we set `0x20008` for `priority0` and `priority1` to
>         achieve "jump to step 1 and enable TC0" once the signal is sensed.
>
>        5. activate the timer comparison for this step.
>        -  echo 0x30000  > /sys/bus/coresight/devices/<tgu-name>/step1_condition_decode/reg0
>
>         |-------------------------------------------------------------------------------|
>         |                 |                     |When '1' the output from the associated|
>         |      17         |                     |comparator will be actively included in|
>         |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
>         |                 |                     |condition.                             |
>         |-------------------------------------------------------------------------------|
>         |                 |                     |When '1' the output from the associated|
>         |                 |                     |comparator will need to be 1 to affect |
>         |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
>         |                 |                     |condition.Conversely, a 0 here         |
>         |                 |                     |requires a '0' from the comparator     |
>         |-------------------------------------------------------------------------------|
>         Accroding to the decode distribution diagram , we give 0x30000 here to set 16th&17th bit
>         to enable timer comparison.
>
>        6. Set the NEXT_STEP = 0 and TC0_PAUSE = 1 and TC0_CLEAR = 1 once the timer
>           has reached the given value.
>        - echo 0x6 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/reg0
>
>        7. Enable Trigger 0 for TGU when the condition 0 is met in step1,
>           i.e. when the timer reaches 3.
>        - echo 0x2000 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/default
>
>         Note:
>             1. 'default' register allows for establishing the resultant action for
>             the default condition
>
>             2. Trigger:For each possible output trigger available from
>             the Design document, there are three triggers: interrupts, CTI,
>             and Cross-TGU mapping.All three triggers can occur, but
>             the choice of which trigger to use depends on the user's
>             needs.
>
>        8. Compare the timer to 3 in step 1.
>        - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step1_timer/reg0
>
>        9. enale tgu
>        - echo 1 > /sys/bus/coresight/devices/<tgu-name>/enable_tgu
>

If this is version 3 - where is the list of differences from versions 1 - 2?

> Songwei Chai (7):
>   dt-bindings: arm: Add support for Coresight TGU trace
>   coresight: Add coresight TGU driver
>   coresight-tgu: Add signal priority support
>   coresight-tgu: Add TGU decode support
>   coresight-tgu: add support to configure next action
>   coresight-tgu: add timer/counter functionality for TGU
>   coresight-tgu: add reset node to initialize
>
>  .../testing/sysfs-bus-coresight-devices-tgu   |  51 ++
>  .../bindings/arm/qcom,coresight-tgu.yaml      | 135 ++++
>  drivers/hwtracing/coresight/Kconfig           |  11 +
>  drivers/hwtracing/coresight/Makefile          |   1 +
>  drivers/hwtracing/coresight/coresight-tgu.c   | 669 ++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-tgu.h   | 242 +++++++
>  6 files changed, 1109 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
>  create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
>  create mode 100644 drivers/hwtracing/coresight/coresight-tgu.c
>  create mode 100644 drivers/hwtracing/coresight/coresight-tgu.h
>

Regards


Mike

--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From Frank.Li at nxp.com  Thu Mar  6 09:06:28 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 12:06:28 -0500
Subject: [PATCH] dt-bindings: watchdog: fsl-imx7ulp-wdt: Add i.MX94 support
Message-ID: <20250306170628.236422-1-Frank.Li@nxp.com>

Add compatible string "fsl,imx94-wdt" for the i.MX94 chip, which is
backward compatible with i.MX93. Set it to fall back to "fsl,imx93-wdt".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 .../devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
index a09686b3030db..711c18efcd4fd 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
@@ -22,6 +22,10 @@ properties:
           - const: fsl,imx8ulp-wdt
           - const: fsl,imx7ulp-wdt
       - const: fsl,imx93-wdt
+      - items:
+          - enum:
+              - fsl,im94-wdt
+          - const: fsl,imx93-wdt
 
   reg:
     maxItems: 1
-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar  6 09:08:25 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 12:08:25 -0500
Subject: [PATCH] dt-bindings: iio: adc: Add i.MX94 and i.MX95 support
Message-ID: <20250306170825.239933-1-Frank.Li@nxp.com>

Add compatible string "nxp,imx94-adc" and "nxp,imx95-adc", which is
backward compatible with i.MX93. Set it to fall back to "nxp,imx93-adc".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 .../devicetree/bindings/iio/adc/nxp,imx93-adc.yaml       | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml b/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
index dfc3f512918f6..c2e5ff418920c 100644
--- a/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
@@ -19,7 +19,14 @@ description:
 
 properties:
   compatible:
-    const: nxp,imx93-adc
+    oneOf:
+      - enum:
+          - nxp,imx93-adc
+      - items:
+          - enum:
+              - nxp,imx94-adc
+              - nxp,imx95-adc
+          - const: nxp,imx93-adc
 
   reg:
     maxItems: 1
-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar  6 09:08:45 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 12:08:45 -0500
Subject: [PATCH] dt-bindings: pwm: imx: Add i.MX93, i.MX94 and i.MX95 support
Message-ID: <20250306170845.240555-1-Frank.Li@nxp.com>

Add compatible string "fsl,imx93-pwm", "fsl,imx94-pwm" and "fsl,imx95-pwm",
which is backward compatible with i.MX7ULP. Set it to fall back to
"fsl,imx7ulp-pwm".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 .../devicetree/bindings/pwm/imx-tpm-pwm.yaml          | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
index ac0a35bf8648c..d5a9340ff9209 100644
--- a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
@@ -23,8 +23,15 @@ properties:
     const: 3
 
   compatible:
-    enum:
-      - fsl,imx7ulp-pwm
+    oneOf:
+      - enum:
+          - fsl,imx7ulp-pwm
+      - items:
+          - enum:
+              - fsl,imx93-pwm
+              - fsl,imx94-pwm
+              - fsl,imx95-pwm
+          - const: fsl,imx7ulp-pwm
 
   reg:
     maxItems: 1
-- 
2.34.1



From jonas at kwiboo.se  Thu Mar  6 08:55:16 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 17:55:16 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250306123809.273655-3-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
 <20250306123809.273655-3-amadeus@jmu.edu.cn>
Message-ID: <cdbc1556-4662-4078-a4d6-33545e2e2491@kwiboo.se>

Hi Chukun,

On 2025-03-06 13:38, Chukun Pan wrote:
> The Quality-of-Service (QsS) node stores/restores specific
> register contents when the power domains is turned off/on.
> Add QoS node so that they can connect to the power domain.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
>  1 file changed, 160 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index b1713ed4d7e2..0c0e7f151462 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -129,6 +129,166 @@ gic: interrupt-controller at fed01000 {
>  			#interrupt-cells = <3>;
>  		};
>  
> +		qos_crypto_a: qos at ff200000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200000 0x0 0x20>;
> +		};
> +
> +		qos_crypto_p: qos at ff200080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200080 0x0 0x20>;
> +		};
> +
> +		qos_dcf: qos at ff200100 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200100 0x0 0x20>;
> +		};
> +
> +		qos_dft2apb: qos at ff200200 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200200 0x0 0x20>;
> +		};
> +
> +		qos_dma2ddr: qos at ff200280 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200280 0x0 0x20>;
> +		};
> +
> +		qos_dmac: qos at ff200300 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200300 0x0 0x20>;
> +		};
> +
> +		qos_keyreader: qos at ff200380 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff200380 0x0 0x20>;
> +		};
> +
> +		qos_cpu: qos at ff210000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff210000 0x0 0x20>;
> +		};
> +
> +		qos_debug: qos at ff210080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff210080 0x0 0x20>;
> +		};
> +
> +		qos_gpu_m0: qos at ff220000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff220000 0x0 0x20>;
> +		};
> +
> +		qos_gpu_m1: qos at ff220080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff220080 0x0 0x20>;
> +		};
> +
> +		qos_pmu_mcu: qos at ff240000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff240000 0x0 0x20>;
> +		};
> +
> +		qos_rkvdec: qos at ff250000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff250000 0x0 0x20>;
> +		};
> +
> +		qos_rkvenc: qos at ff260000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff260000 0x0 0x20>;
> +		};
> +
> +		qos_gmac0: qos at ff270000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270000 0x0 0x20>;
> +		};
> +
> +		qos_hdcp: qos at ff270080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270080 0x0 0x20>;
> +		};
> +
> +		qos_jpegdec: qos at ff270100 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270100 0x0 0x20>;
> +		};
> +
> +		qos_rga2_m0ro: qos at ff270200 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270200 0x0 0x20>;
> +		};
> +
> +		qos_rga2_m0wo: qos at ff270280 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270280 0x0 0x20>;
> +		};
> +
> +		qos_sdmmc0: qos at ff270300 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270300 0x0 0x20>;
> +		};
> +
> +		qos_usb2host: qos at ff270380 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270380 0x0 0x20>;
> +		};
> +
> +		qos_vdpp: qos at ff270480 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270480 0x0 0x20>;
> +		};
> +
> +		qos_vop: qos at ff270500 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff270500 0x0 0x20>;
> +		};
> +
> +		qos_emmc: qos at ff280000 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280000 0x0 0x20>;
> +		};
> +
> +		qos_fspi: qos at ff280080 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280080 0x0 0x20>;
> +		};
> +
> +		qos_gmac1: qos at ff280100 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280100 0x0 0x20>;
> +		};
> +
> +		qos_pcie: qos at ff280180 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280180 0x0 0x20>;
> +		};
> +
> +		qos_sdio0: qos at ff280200 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280200 0x0 0x20>;
> +		};
> +
> +		qos_sdio1: qos at ff280280 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280280 0x0 0x20>;
> +		};
> +
> +		qos_tsp: qos at ff280300 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280300 0x0 0x20>;
> +		};
> +
> +		qos_usb3otg: qos at ff280380 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280380 0x0 0x20>;
> +		};
> +
> +		qos_vpu: qos at ff280400 {
> +			compatible = "rockchip,rk3528-qos", "syscon";
> +			reg = <0x0 0xff280400 0x0 0x20>;
> +		};

These QoS node are typically referenced from power domains so that the
PMU driver know what QoS to save/restore when a power domain is power
cycled.

Vendor kernel only reference the two qos_gpu nodes in it's power domains,
do you have any documentation or knowledge about what power domain the
remaining QoS are related to?

It would have been helpful to include PMU support to help understand the
QoS <-> PD relationship, on their own they do not tell us that much :-)

Regards,
Jonas

> +
>  		cru: clock-controller at ff4a0000 {
>  			compatible = "rockchip,rk3528-cru";
>  			reg = <0x0 0xff4a0000 0x0 0x30000>;



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:01 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:01 +0100
Subject: [PATCH v5 00/11] media: rockchip: add a driver for the rockchip
 camera interface
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>

Habidere,

This series introduces support for the Rockchip Camera Interface (CIF),
which is featured in many Rockchip SoCs in different variations.
For example, the PX30 Video Input Processor (VIP) is able to receive
video data via the Digital Video Port (DVP, a parallel data interface)
and transfer it into system memory using a double-buffering mechanism
called ping-pong mode.
The RK3568 Video Capture (VICAP) unit, on the other hand, features a
DVP and a MIPI CSI-2 receiver that can receive video data independently
(both using the ping-pong scheme).
The different variants may have additional features, such as scaling
and/or cropping.
Finally, the RK3588 VICAP unit constitutes an essential piece of the
camera interface with one DVP, six MIPI CSI-2 receivers, scale/crop
units, and a data path multiplexer (to scaler units, to ISP, ...).

The v5 of the series adds a media controller centric V4L2 driver for
the Rockchip CIF with
 - support for the PX30 VIP (not tested, though, due to the lack of HW)
 - support for the RK3568 VICAP DVP
 - support for the RK3568 VICAP MIPI CSI-2 receiver
 - abstraction for the ping-pong scheme to allow for future extensions
 - abstraction for the INTERFACE and CROP parts to allow for future
   extensions
 - initial support for different virtual channels (not tested, though,
   due to the lack of HW)

The patches are functional and have been tested successfully on a
custom RK3568 board including the ITE Tech. IT6801 HDMI receiver and
the Sony IMX415 image sensor as subdevices attached to the DVP and the
MIPI CSI-2 receiver, respectively.
The IT6801 driver still needs some loving care but shall be submitted
as well at some point.

Please note that the MIPI CSI-2 receiver requires a patch w.r.t. critical
clocks [0].

However, several features are not yet addressed, such as
 - support for the RK3588 variant (-> next item on my TODO)
 - support for the scaling unit in the PX30 (-> cannot do due to the
   lack of HW)
 - support for the interface to the Rockchip ISP in the RK3568
   (apparently, data receive via VICAP DVP and the VICAP MIPI CSI-2
   receiver can be processed by the RK3568 ISP)
 - support for the MUX/SCALE/TOISP block in the RK3588 VICAP (which
   provides the base for image processing on the RK3588)

Looking forward to your comments!

[0] https://lore.kernel.org/linux-rockchip/20250210-rk3568-hclk-vi-v1-1-9ade2626f638 at wolfvision.net/

To: Mehdi Djait <mehdi.djait at linux.intel.com>
To: Maxime Chevallier <maxime.chevallier at bootlin.com>
To: Th?o Lebrun <theo.lebrun at bootlin.com>
To: Gerald Loacker <gerald.loacker at wolfvision.net>
To: Thomas Petazzoni <thomas.petazzoni at bootlin.com>
To: Sakari Ailus <sakari.ailus at iki.fi>
To: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
To: Mauro Carvalho Chehab <mchehab at kernel.org>
To: Rob Herring <robh+dt at kernel.org>
To: Krzysztof Kozlowski <krzk+dt at kernel.org>
To: Conor Dooley <conor+dt at kernel.org>
To: Heiko Stuebner <heiko at sntech.de>
To: Kever Yang <kever.yang at rock-chips.com>
To: Nicolas Dufresne <nicolas.dufresne at collabora.com>
To: Sebastian Fricke <sebastian.fricke at collabora.com>
To: Sebastian Reichel <sebastian.reichel at collabora.com>
To: Paul Kocialkowski <paulk at sys-base.io>
To: Alexander Shiyan <eagle.alexander923 at gmail.com>
To: Val Packett <val at packett.cool>
To: Rob Herring <robh at kernel.org>
To: Philipp Zabel <p.zabel at pengutronix.de>
Cc: linux-media at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-rockchip at lists.infradead.org
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>

Changes in v5:
- fixed issues raised by media-ci
- fixed dt bindings (comments by Rob and Sakari)
- fixed probe on system with no DVP in DT (comment by Alexander)
- fixed error path in register offset calculation
- split off MIPI CSI host driver into separate module (comment
  by Mehdi)
- added MODULE_DEVICE_TABLE() for both drivers (comment by Mehdi)
- Link to v4: https://lore.kernel.org/r/20250219-v6-8-topic-rk3568-vicap-v4-0-e906600ae3b0 at wolfvision.net

Changes in v4:
- added support for the MIPI CSI-2 receiver (new patches 4, 6, 7, 10)
- fixed asserts on stream stop
- fixed register address lookup
- fixed link validiation callback
- fixed issues raised by Rob's bot, kernel test robot, and media-ci
- Link to v3: https://lore.kernel.org/r/20250206-v6-8-topic-rk3568-vicap-v3-0-69d1f19e5c40 at wolfvision.net

Changes in v3:
- renamed the driver "cif" -> "rkcif"
- rebased onto v6.14-rc1
- abstracted the generic INTERFACE+CROP part
- addressed comments by Rob and Sakari
- added V4L2 MPLANE formats to DVP
- added patch that enables the RK3568 VICAP DVP on PF5 IO Expander
- fixed formatting issues raised by media-ci bot
- Link to v2: https://lore.kernel.org/r/20241217-v6-8-topic-rk3568-vicap-v2-0-b1d488fcc0d3 at wolfvision.net

Changes in v2:
- merged with Mehdi's v13
- refactored the complete driver towards a media controller centric driver
- abstracted the generic ping-pong stream (can be used for DVP as well as for CSI-2)
- switched to MPLANE API
- added support for notifications
- Link to v1: https://lore.kernel.org/r/20240220-v6-8-topic-rk3568-vicap-v1-0-2680a1fa640b at wolfvision.net

---
Mehdi Djait (2):
      media: dt-bindings: media: add bindings for rockchip px30 vip
      arm64: dts: rockchip: add the vip node to px30

Michael Riesch (9):
      media: dt-bindings: media: video-interfaces: add defines for sampling modes
      media: dt-bindings: media: add bindings for rockchip rk3568 vicap
      media: dt-bindings: media: add bindings for rockchip mipi csi host
      media: rockchip: add a driver for the rockchip camera interface
      media: rockchip: rkcif: add driver for mipi csi-2 host
      media: rockchip: rkcif: add support for mipi csi-2 receiver
      arm64: dts: rockchip: add vicap node to rk356x
      arm64: dts: rockchip: add mipi csi host node to rk356x
      arm64: dts: rockchip: enable vicap dvp on wolfvision pf5 io expander

 .../bindings/media/rockchip,px30-vip.yaml          | 123 +++
 .../bindings/media/rockchip,rk3568-mipi-csi.yaml   | 114 +++
 .../bindings/media/rockchip,rk3568-vicap.yaml      | 169 ++++
 MAINTAINERS                                        |  10 +
 arch/arm64/boot/dts/rockchip/px30.dtsi             |  12 +
 .../rk3568-wolfvision-pf5-io-expander.dtso         |  20 +
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi      |  75 ++
 drivers/media/platform/rockchip/Kconfig            |   1 +
 drivers/media/platform/rockchip/Makefile           |   1 +
 drivers/media/platform/rockchip/rkcif/Kconfig      |  15 +
 drivers/media/platform/rockchip/rkcif/Makefile     |  10 +
 .../platform/rockchip/rkcif/rkcif-capture-dvp.c    | 858 +++++++++++++++++++++
 .../platform/rockchip/rkcif/rkcif-capture-dvp.h    |  24 +
 .../platform/rockchip/rkcif/rkcif-capture-mipi.c   | 722 +++++++++++++++++
 .../platform/rockchip/rkcif/rkcif-capture-mipi.h   |  22 +
 .../media/platform/rockchip/rkcif/rkcif-common.h   | 236 ++++++
 drivers/media/platform/rockchip/rkcif/rkcif-dev.c  | 308 ++++++++
 .../platform/rockchip/rkcif/rkcif-interface.c      | 421 ++++++++++
 .../platform/rockchip/rkcif/rkcif-interface.h      |  30 +
 .../platform/rockchip/rkcif/rkcif-mipi-csi-host.c  | 731 ++++++++++++++++++
 drivers/media/platform/rockchip/rkcif/rkcif-regs.h | 154 ++++
 .../media/platform/rockchip/rkcif/rkcif-stream.c   | 622 +++++++++++++++
 .../media/platform/rockchip/rkcif/rkcif-stream.h   |  31 +
 include/dt-bindings/media/video-interfaces.h       |   4 +
 24 files changed, 4713 insertions(+)
---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20240220-v6-8-topic-rk3568-vicap-b9b3f9925f44

Best regards,
-- 
Michael Riesch <michael.riesch at wolfvision.net>



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:02 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:02 +0100
Subject: [PATCH v5 01/11] media: dt-bindings: media: video-interfaces: add
 defines for sampling modes
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-1-f02152534f3c@wolfvision.net>

Add defines for the pixel clock sampling modes (rising edge, falling edge,
dual edge) for parallel video interfaces.
This avoids hardcoded constants in device tree sources.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 include/dt-bindings/media/video-interfaces.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dt-bindings/media/video-interfaces.h b/include/dt-bindings/media/video-interfaces.h
index 88b9d05d8075..0b19c9b2e627 100644
--- a/include/dt-bindings/media/video-interfaces.h
+++ b/include/dt-bindings/media/video-interfaces.h
@@ -20,4 +20,8 @@
 #define MEDIA_BUS_CSI2_CPHY_LINE_ORDER_CAB	4
 #define MEDIA_BUS_CSI2_CPHY_LINE_ORDER_CBA	5
 
+#define MEDIA_PCLK_SAMPLE_FALLING_EDGE		0
+#define MEDIA_PCLK_SAMPLE_RISING_EDGE		1
+#define MEDIA_PCLK_SAMPLE_DUAL_EDGE		2
+
 #endif /* __DT_BINDINGS_MEDIA_VIDEO_INTERFACES_H__ */

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:03 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:03 +0100
Subject: [PATCH v5 02/11] media: dt-bindings: media: add bindings for
 rockchip px30 vip
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-2-f02152534f3c@wolfvision.net>

From: Mehdi Djait <mehdi.djait at bootlin.com>

Add documentation for the Rockchip PX30 Video Input Processor (VIP).

Signed-off-by: Mehdi Djait <mehdi.djait at bootlin.com>
[revised description]
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../bindings/media/rockchip,px30-vip.yaml          | 123 +++++++++++++++++++++
 MAINTAINERS                                        |   7 ++
 2 files changed, 130 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml b/Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
new file mode 100644
index 000000000000..d34c0974204f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/rockchip,px30-vip.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip PX30 Video Input Processor (VIP)
+
+maintainers:
+  - Mehdi Djait <mehdi.djait at linux.intel.com>
+  - Michael Riesch <michael.riesch at wolfvision.net>
+
+description:
+  The Rockchip PX30 Video Input Processor (VIP) receives the data from a camera
+  sensor or CCIR656 encoder and transfers it into system main memory by AXI bus.
+
+properties:
+  compatible:
+    const: rockchip,px30-vip
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: ACLK
+      - description: HCLK
+      - description: PCLK
+
+  clock-names:
+    items:
+      - const: aclk
+      - const: hclk
+      - const: pclk
+
+  resets:
+    items:
+      - description: AXI
+      - description: AHB
+      - description: PCLK IN
+
+  reset-names:
+    items:
+      - const: axi
+      - const: ahb
+      - const: pclkin
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port at 0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: input port on the parallel interface
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              bus-type:
+                enum: [5, 6]
+
+            required:
+              - bus-type
+
+    required:
+      - port at 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/px30-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/media/video-interfaces.h>
+    #include <dt-bindings/power/px30-power.h>
+
+    parent {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        video-capture at ff490000 {
+            compatible = "rockchip,px30-vip";
+            reg = <0x0 0xff490000 0x0 0x200>;
+            interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&cru ACLK_CIF>, <&cru HCLK_CIF>, <&cru PCLK_CIF>;
+            clock-names = "aclk", "hclk", "pclk";
+            power-domains = <&power PX30_PD_VI>;
+            resets = <&cru SRST_CIF_A>, <&cru SRST_CIF_H>, <&cru SRST_CIF_PCLKIN>;
+            reset-names = "axi", "ahb", "pclkin";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    cif_in: endpoint {
+                        remote-endpoint = <&tw9900_out>;
+                        bus-type = <MEDIA_BUS_TYPE_BT656>;
+                    };
+                };
+            };
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 896a307fa065..bbfaf35d50c6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20401,6 +20401,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
 F:	drivers/net/can/rockchip/
 
+ROCKCHIP CIF DRIVER
+M:	Mehdi Djait <mehdi.djait at linux.intel.com>
+M:	Michael Riesch <michael.riesch at wolfvision.net>
+L:	linux-media at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
+
 ROCKCHIP CRYPTO DRIVERS
 M:	Corentin Labbe <clabbe at baylibre.com>
 L:	linux-crypto at vger.kernel.org

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:04 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:04 +0100
Subject: [PATCH v5 03/11] media: dt-bindings: media: add bindings for
 rockchip rk3568 vicap
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-3-f02152534f3c@wolfvision.net>

Add documentation for the Rockchip RK3568 Video Capture (VICAP) unit.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../bindings/media/rockchip,rk3568-vicap.yaml      | 169 +++++++++++++++++++++
 MAINTAINERS                                        |   1 +
 2 files changed, 170 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
new file mode 100644
index 000000000000..0e61f02a9508
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/rockchip,rk3568-vicap.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip RK3568 Video Capture (VICAP)
+
+maintainers:
+  - Michael Riesch <michael.riesch at wolfvision.net>
+
+description:
+  The Rockchip RK3568 Video Capture (VICAP) block features a digital video
+  port (DVP, a parallel video interface) and a MIPI CSI-2 port. It receives
+  the data from camera sensors, video decoders, or other companion ICs and
+  transfers it into system main memory by AXI bus.
+
+properties:
+  compatible:
+    const: rockchip,rk3568-vicap
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: ACLK
+      - description: HCLK
+      - description: DCLK
+      - description: ICLK
+
+  clock-names:
+    items:
+      - const: aclk
+      - const: hclk
+      - const: dclk
+      - const: iclk
+
+  rockchip,cif-clk-delaynum:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 127
+    description:
+      Delay the DVP path clock input to align the sampling phase, only valid
+      in dual edge sampling mode. Delay is zero by default and can be adjusted
+      optionally.
+
+  iommus:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: ARST
+      - description: HRST
+      - description: DRST
+      - description: PRST
+      - description: IRST
+
+  reset-names:
+    items:
+      - const: arst
+      - const: hrst
+      - const: drst
+      - const: prst
+      - const: irst
+
+  rockchip,grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to general register file used for video input block control.
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port at 0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: The digital video port (DVP, a parallel video interface).
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              bus-type:
+                enum: [5, 6]
+
+            required:
+              - bus-type
+
+      port at 1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Internal port connected to a MIPI CSI-2 host.
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/rk3568-power.h>
+    #include <dt-bindings/media/video-interfaces.h>
+
+    parent {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        vicap: video-capture at fdfe0000 {
+            compatible = "rockchip,rk3568-vicap";
+            reg = <0x0 0xfdfe0000 0x0 0x200>;
+            interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+            assigned-clocks = <&cru DCLK_VICAP>;
+            assigned-clock-rates = <300000000>;
+            clocks = <&cru ACLK_VICAP>, <&cru HCLK_VICAP>,
+                     <&cru DCLK_VICAP>, <&cru ICLK_VICAP_G>;
+            clock-names = "aclk", "hclk", "dclk", "iclk";
+            iommus = <&vicap_mmu>;
+            power-domains = <&power RK3568_PD_VI>;
+            resets = <&cru SRST_A_VICAP>, <&cru SRST_H_VICAP>,
+                     <&cru SRST_D_VICAP>, <&cru SRST_P_VICAP>,
+                     <&cru SRST_I_VICAP>;
+            reset-names = "arst", "hrst", "drst", "prst", "irst";
+            rockchip,grf = <&grf>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                vicap_dvp: port at 0 {
+                    reg = <0>;
+
+                    vicap_dvp_input: endpoint {
+                        bus-type = <MEDIA_BUS_TYPE_BT656>;
+                        bus-width = <16>;
+                        pclk-sample = <MEDIA_PCLK_SAMPLE_DUAL_EDGE>;
+                        remote-endpoint = <&it6801_output>;
+                    };
+                };
+
+                vicap_mipi: port at 1 {
+                    reg = <1>;
+
+                    vicap_mipi_input: endpoint {
+                        remote-endpoint = <&csi_output>;
+                    };
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index bbfaf35d50c6..cd8fa1afe5eb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20407,6 +20407,7 @@ M:	Michael Riesch <michael.riesch at wolfvision.net>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
+F:	Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
 
 ROCKCHIP CRYPTO DRIVERS
 M:	Corentin Labbe <clabbe at baylibre.com>

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:05 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:05 +0100
Subject: [PATCH v5 04/11] media: dt-bindings: media: add bindings for
 rockchip mipi csi host
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-4-f02152534f3c@wolfvision.net>

Add documentation for the Rockchip RK3568 MIPI CSI-2 Host unit.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../bindings/media/rockchip,rk3568-mipi-csi.yaml   | 114 +++++++++++++++++++++
 MAINTAINERS                                        |   1 +
 2 files changed, 115 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
new file mode 100644
index 000000000000..900f5a32dab9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/rockchip,rk3568-mipi-csi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip RK3568 MIPI CSI-2 Host
+
+maintainers:
+  - Michael Riesch <michael.riesch at wolfvision.net>
+
+description:
+  The Rockchip RK3568 MIPI CSI-2 Host is a CSI-2 bridge with one input port
+  and one output port. It receives the data with the help of an external
+  MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip RK3568 Video Capture
+  (VICAP) block.
+
+properties:
+  compatible:
+    const: rockchip,rk3568-mipi-csi
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+    description: MIPI C-PHY or D-PHY.
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port at 0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: Input port node. Connect to e.g., a MIPI CSI-2 image sensor.
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              bus-type:
+                enum: [1, 4]
+
+            required:
+              - bus-type
+
+      port at 1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Internal port connected to a RK3568 VICAP port.
+
+    required:
+      - port at 0
+      - port at 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - phys
+  - phy-names
+  - ports
+  - power-domains
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/power/rk3568-power.h>
+
+    parent {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        csi: csi at fdfb0000 {
+            compatible = "rockchip,rk3568-mipi-csi";
+            reg = <0x0 0xfdfb0000 0x0 0x10000>;
+            clocks = <&cru PCLK_CSI2HOST1>;
+            phys = <&csi_dphy>;
+            power-domains = <&power RK3568_PD_VI>;
+            resets = <&cru SRST_P_CSI2HOST1>;
+            status = "disabled";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                csi_in: port at 0 {
+                    reg = <0>;
+                };
+
+                csi_out: port at 1 {
+                    reg = <1>;
+
+                    csi_output: endpoint {
+                        remote-endpoint = <&vicap_mipi_input>;
+                    };
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index cd8fa1afe5eb..d83a7762dbe3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20407,6 +20407,7 @@ M:	Michael Riesch <michael.riesch at wolfvision.net>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
+F:	Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
 F:	Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
 
 ROCKCHIP CRYPTO DRIVERS

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:06 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:06 +0100
Subject: [PATCH v5 05/11] media: rockchip: add a driver for the rockchip
 camera interface
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-5-f02152534f3c@wolfvision.net>

The Rockchip Camera Interface (CIF) is featured in many Rockchip SoCs
in different variations. For example, the PX30 Video Input Processor (VIP)
is able to receive video data via the Digital Video Port (DVP, a parallel
data interface) and transfer it into system memory using a
double-buffering mechanism called ping-pong mode.
The RK3568 Video Capture (VICAP) unit, on the other hand, features a DVP
and a MIPI CSI-2 receiver that can receive video data independently
(both using the ping-pong scheme).
The different variants may have additional features, such as scaling
and/or cropping.
Finally, the RK3588 VICAP unit constitutes an essential piece of the
camera interface with one DVP, six MIPI CSI-2 receivers, scale/crop
units, and a data path multiplexer (to scaler units, to ISP, ...).

Add a basic media controller centric V4L2 driver for the Rockchip CIF with
 - support for the PX30 VIP
 - support for the RK3568 VICAP DVP
 - abstraction for the ping-pong scheme to allow for future extensions
 - abstraction for the INTERFACE and CROP parts to allow for future
   extensions

[PX30 VIP support v1-v5]
Co-developed-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
[PX30 VIP support v6-v13]
Co-developed-by: Mehdi Djait <mehdi.djait at bootlin.com>
Signed-off-by: Mehdi Djait <mehdi.djait at bootlin.com>
[added RK3568 VICAP DVP support]
[refactored to media controller centric driver, added mplane support]
Co-developed-by: Gerald Loacker <gerald.loacker at wolfvision.net>
Signed-off-by: Gerald Loacker <gerald.loacker at wolfvision.net>
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 MAINTAINERS                                        |   1 +
 drivers/media/platform/rockchip/Kconfig            |   1 +
 drivers/media/platform/rockchip/Makefile           |   1 +
 drivers/media/platform/rockchip/rkcif/Kconfig      |  15 +
 drivers/media/platform/rockchip/rkcif/Makefile     |   7 +
 .../platform/rockchip/rkcif/rkcif-capture-dvp.c    | 858 +++++++++++++++++++++
 .../platform/rockchip/rkcif/rkcif-capture-dvp.h    |  24 +
 .../platform/rockchip/rkcif/rkcif-capture-mipi.c   |  27 +
 .../platform/rockchip/rkcif/rkcif-capture-mipi.h   |  20 +
 .../media/platform/rockchip/rkcif/rkcif-common.h   | 220 ++++++
 drivers/media/platform/rockchip/rkcif/rkcif-dev.c  | 307 ++++++++
 .../platform/rockchip/rkcif/rkcif-interface.c      | 418 ++++++++++
 .../platform/rockchip/rkcif/rkcif-interface.h      |  30 +
 drivers/media/platform/rockchip/rkcif/rkcif-regs.h | 132 ++++
 .../media/platform/rockchip/rkcif/rkcif-stream.c   | 622 +++++++++++++++
 .../media/platform/rockchip/rkcif/rkcif-stream.h   |  31 +
 16 files changed, 2714 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d83a7762dbe3..e9a648d4fcb4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20409,6 +20409,7 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
 F:	Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
 F:	Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
+F:	drivers/media/platform/rockchip/rkcif/
 
 ROCKCHIP CRYPTO DRIVERS
 M:	Corentin Labbe <clabbe at baylibre.com>
diff --git a/drivers/media/platform/rockchip/Kconfig b/drivers/media/platform/rockchip/Kconfig
index b41d3960c1b4..549f4e9f443e 100644
--- a/drivers/media/platform/rockchip/Kconfig
+++ b/drivers/media/platform/rockchip/Kconfig
@@ -3,4 +3,5 @@
 comment "Rockchip media platform drivers"
 
 source "drivers/media/platform/rockchip/rga/Kconfig"
+source "drivers/media/platform/rockchip/rkcif/Kconfig"
 source "drivers/media/platform/rockchip/rkisp1/Kconfig"
diff --git a/drivers/media/platform/rockchip/Makefile b/drivers/media/platform/rockchip/Makefile
index 4f782b876ac9..6aba32c8830c 100644
--- a/drivers/media/platform/rockchip/Makefile
+++ b/drivers/media/platform/rockchip/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += rga/
+obj-y += rkcif/
 obj-y += rkisp1/
diff --git a/drivers/media/platform/rockchip/rkcif/Kconfig b/drivers/media/platform/rockchip/rkcif/Kconfig
new file mode 100644
index 000000000000..f53e79a4b42d
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/Kconfig
@@ -0,0 +1,15 @@
+config VIDEO_ROCKCHIP_CIF
+	tristate "Rockchip Camera Interface (CIF)"
+	depends on VIDEO_DEV
+	depends on ARCH_ROCKCHIP || COMPILE_TEST
+	depends on V4L_PLATFORM_DRIVERS
+	depends on PM && COMMON_CLK
+	select MEDIA_CONTROLLER
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  This is a driver for Rockchip Camera Interface (CIF). It is featured
+	  in many Rockchips SoCs in different variations, such as the PX30
+	  Video Input Processor (VIP, one Digital Video Port (DVP)) or the
+	  RK3568 Video Capture (VICAP, one DVP, one MIPI CSI-2 receiver) unit.
diff --git a/drivers/media/platform/rockchip/rkcif/Makefile b/drivers/media/platform/rockchip/rkcif/Makefile
new file mode 100644
index 000000000000..818424972c7b
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_ROCKCHIP_CIF) += rockchip-cif.o
+rockchip-cif-objs += rkcif-dev.o \
+	rkcif-capture-dvp.o \
+	rkcif-capture-mipi.o \
+	rkcif-interface.o \
+	rkcif-stream.o
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.c
new file mode 100644
index 000000000000..e0a9ae6ba77f
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.c
@@ -0,0 +1,858 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2020 Maxime Chevallier <maxime.chevallier at bootlin.com>
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait at bootlin.com>
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+#include "rkcif-capture-dvp.h"
+#include "rkcif-common.h"
+#include "rkcif-interface.h"
+#include "rkcif-regs.h"
+#include "rkcif-stream.h"
+
+static const struct rkcif_output_fmt dvp_out_fmts[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV16M,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV61,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV61M,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
+			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
+		.cplanes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_RGB24,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_RGB565,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_BGR666,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB8,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG8,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG8,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR8,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB10,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG10,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG10,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR10,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB12,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG12,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG12,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR12,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR16,
+		.cplanes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_Y16,
+		.cplanes = 1,
+	},
+};
+
+static const struct rkcif_input_fmt px30_dvp_in_fmts[] = {
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	}
+};
+
+const struct rkcif_dvp_match_data px30_vip_dvp_match_data = {
+	.in_fmts = px30_dvp_in_fmts,
+	.in_fmts_num = ARRAY_SIZE(px30_dvp_in_fmts),
+	.out_fmts = dvp_out_fmts,
+	.out_fmts_num = ARRAY_SIZE(dvp_out_fmts),
+	.has_scaler = true,
+	.regs = {
+		[RKCIF_DVP_CTRL] = 0x00,
+		[RKCIF_DVP_INTEN] = 0x04,
+		[RKCIF_DVP_INTSTAT] = 0x08,
+		[RKCIF_DVP_FOR] = 0x0c,
+		[RKCIF_DVP_LINE_NUM_ADDR] = 0x10,
+		[RKCIF_DVP_FRM0_ADDR_Y] = 0x14,
+		[RKCIF_DVP_FRM0_ADDR_UV] = 0x18,
+		[RKCIF_DVP_FRM1_ADDR_Y] = 0x1c,
+		[RKCIF_DVP_FRM1_ADDR_UV] = 0x20,
+		[RKCIF_DVP_VIR_LINE_WIDTH] = 0x24,
+		[RKCIF_DVP_SET_SIZE] = 0x28,
+		[RKCIF_DVP_SCL_CTRL] = 0x48,
+		[RKCIF_DVP_FRAME_STATUS] = 0x60,
+		[RKCIF_DVP_LAST_LINE] = 0x68,
+		[RKCIF_DVP_LAST_PIX] = 0x6c,
+	},
+};
+
+static const struct rkcif_input_fmt rk3568_dvp_in_fmts[] = {
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
+		.fmt_type = RKCIF_FMT_TYPE_YUV,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
+			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
+			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
+			       RKCIF_FORMAT_BT1120_YC_SWAP |
+			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
+			       RKCIF_FORMAT_BT1120_YC_SWAP |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
+			       RKCIF_FORMAT_BT1120_YC_SWAP |
+			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
+			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
+			       RKCIF_FORMAT_BT1120_YC_SWAP |
+			       RKCIF_FORMAT_INPUT_MODE_BT1120,
+		.field = V4L2_FIELD_INTERLACED,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_Y12_1X12,
+		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
+			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
+		.fmt_type = RKCIF_FMT_TYPE_RAW,
+		.field = V4L2_FIELD_NONE,
+	},
+};
+
+static void rk3568_dvp_grf_setup(struct rkcif_device *rkcif)
+{
+	u32 con1 = RK3568_GRF_WRITE_ENABLE(RK3568_GRF_VI_CON1_CIF_DATAPATH |
+					   RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM);
+
+	if (!rkcif->grf)
+		return;
+
+	con1 |= rkcif->interfaces[0].dvp.cif_clk_delaynum &
+		RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM;
+
+	if (rkcif->interfaces[0].vep.bus.parallel.flags &
+	    V4L2_MBUS_PCLK_SAMPLE_DUALEDGE)
+		con1 |= RK3568_GRF_VI_CON1_CIF_DATAPATH;
+
+	regmap_write(rkcif->grf, RK3568_GRF_VI_CON1, con1);
+}
+
+const struct rkcif_dvp_match_data rk3568_vicap_dvp_match_data = {
+	.in_fmts = rk3568_dvp_in_fmts,
+	.in_fmts_num = ARRAY_SIZE(rk3568_dvp_in_fmts),
+	.out_fmts = dvp_out_fmts,
+	.out_fmts_num = ARRAY_SIZE(dvp_out_fmts),
+	.setup = rk3568_dvp_grf_setup,
+	.has_scaler = false,
+	.regs = {
+		[RKCIF_DVP_CTRL] = 0x00,
+		[RKCIF_DVP_INTEN] = 0x04,
+		[RKCIF_DVP_INTSTAT] = 0x08,
+		[RKCIF_DVP_FOR] = 0x0c,
+		[RKCIF_DVP_LINE_NUM_ADDR] = 0x2c,
+		[RKCIF_DVP_FRM0_ADDR_Y] = 0x14,
+		[RKCIF_DVP_FRM0_ADDR_UV] = 0x18,
+		[RKCIF_DVP_FRM1_ADDR_Y] = 0x1c,
+		[RKCIF_DVP_FRM1_ADDR_UV] = 0x20,
+		[RKCIF_DVP_VIR_LINE_WIDTH] = 0x24,
+		[RKCIF_DVP_SET_SIZE] = 0x28,
+		[RKCIF_DVP_CROP] = 0x34,
+		[RKCIF_DVP_FRAME_STATUS] = 0x3c,
+		[RKCIF_DVP_LAST_LINE] = 0x44,
+		[RKCIF_DVP_LAST_PIX] = 0x48,
+	},
+};
+
+static inline unsigned int cif_dvp_get_addr(struct rkcif_device *rkcif,
+					    unsigned int index)
+{
+	if (WARN_ON(index >= RKCIF_DVP_REGISTER_MAX))
+		return RKCIF_REGISTER_NOTSUPPORTED;
+
+	return rkcif->match_data->dvp->regs[index];
+}
+
+static inline __maybe_unused void cif_dvp_write(struct rkcif_device *rkcif,
+						unsigned int index, u32 val)
+{
+	unsigned int addr = cif_dvp_get_addr(rkcif, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return;
+
+	writel(val, rkcif->base_addr + addr);
+}
+
+static inline __maybe_unused u32 cif_dvp_read(struct rkcif_device *rkcif,
+					      unsigned int index)
+{
+	unsigned int addr = cif_dvp_get_addr(rkcif, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return 0;
+
+	return readl(rkcif->base_addr + addr);
+}
+
+static void cif_dvp_queue_buffer(struct rkcif_stream *stream,
+				 unsigned int index)
+{
+	struct rkcif_device *rkcif = stream->rkcif;
+	struct rkcif_buffer *buffer = stream->buffers[index];
+	u32 frm_addr_y, frm_addr_uv;
+
+	frm_addr_y = index ? RKCIF_DVP_FRM1_ADDR_Y : RKCIF_DVP_FRM0_ADDR_Y;
+	frm_addr_uv = index ? RKCIF_DVP_FRM1_ADDR_UV : RKCIF_DVP_FRM0_ADDR_UV;
+
+	cif_dvp_write(rkcif, frm_addr_y, buffer->buff_addr[RKCIF_PLANE_Y]);
+	cif_dvp_write(rkcif, frm_addr_uv, buffer->buff_addr[RKCIF_PLANE_UV]);
+}
+
+static int cif_dvp_start_streaming(struct rkcif_stream *stream)
+{
+	struct rkcif_device *rkcif = stream->rkcif;
+	struct rkcif_interface *interface = stream->interface;
+	struct v4l2_mbus_config_parallel *parallel;
+	struct v4l2_mbus_framefmt *source_fmt;
+	struct v4l2_subdev_state *state;
+	const struct rkcif_input_fmt *active_in_fmt;
+	const struct rkcif_output_fmt *active_out_fmt;
+	u32 val = 0;
+	int ret = -EINVAL;
+
+	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
+	source_fmt = v4l2_subdev_state_get_format(state, RKCIF_IF_PAD_SRC,
+						  stream->id);
+	if (!source_fmt)
+		goto out;
+
+	active_in_fmt = rkcif_interface_find_input_fmt(interface, false,
+						       source_fmt->code);
+	active_out_fmt = rkcif_stream_find_output_fmt(stream, false,
+						      stream->pix.pixelformat);
+	if (!active_in_fmt || !active_out_fmt)
+		goto out;
+
+	parallel = &interface->vep.bus.parallel;
+	if (parallel->bus_width == 16 &&
+	    (parallel->flags & V4L2_MBUS_PCLK_SAMPLE_DUALEDGE))
+		val |= RKCIF_FORMAT_BT1120_CLOCK_DOUBLE_EDGES;
+	val |= active_in_fmt->dvp_fmt_val;
+	val |= active_out_fmt->dvp_fmt_val;
+	cif_dvp_write(rkcif, RKCIF_DVP_FOR, val);
+
+	val = stream->pix.width;
+	if (active_in_fmt->fmt_type == RKCIF_FMT_TYPE_RAW)
+		val = stream->pix.width * 2;
+	cif_dvp_write(rkcif, RKCIF_DVP_VIR_LINE_WIDTH, val);
+
+	val = RKCIF_XY_COORD(stream->pix.width, stream->pix.height);
+	cif_dvp_write(rkcif, RKCIF_DVP_SET_SIZE, val);
+
+	cif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, RKCIF_FRAME_STAT_CLS);
+	cif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, RKCIF_INTSTAT_CLS);
+	if (rkcif->match_data->dvp->has_scaler) {
+		val = active_in_fmt->fmt_type == RKCIF_FMT_TYPE_YUV ?
+			      RKCIF_SCL_CTRL_ENABLE_YUV_16BIT_BYPASS :
+			      RKCIF_SCL_CTRL_ENABLE_RAW_16BIT_BYPASS;
+		cif_dvp_write(rkcif, RKCIF_DVP_SCL_CTRL, val);
+	}
+
+	cif_dvp_write(rkcif, RKCIF_DVP_INTEN,
+		      RKCIF_INTEN_FRAME_END_EN |
+			      RKCIF_INTEN_PST_INF_FRAME_END_EN);
+
+	cif_dvp_write(rkcif, RKCIF_DVP_CTRL,
+		      RKCIF_CTRL_AXI_BURST_16 | RKCIF_CTRL_MODE_PINGPONG |
+			      RKCIF_CTRL_ENABLE_CAPTURE);
+
+	ret = 0;
+
+out:
+	v4l2_subdev_unlock_state(state);
+	return ret;
+}
+
+static void cif_dvp_stop_streaming(struct rkcif_stream *stream)
+{
+	struct rkcif_device *rkcif = stream->rkcif;
+	u32 val;
+
+	val = cif_dvp_read(rkcif, RKCIF_DVP_CTRL);
+	cif_dvp_write(rkcif, RKCIF_DVP_CTRL,
+		      val & (~RKCIF_CTRL_ENABLE_CAPTURE));
+	cif_dvp_write(rkcif, RKCIF_DVP_INTEN, 0x0);
+	cif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, 0x3ff);
+	cif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, 0x0);
+
+	stream->stopping = false;
+}
+
+static void cif_dvp_reset_stream(struct rkcif_device *rkcif)
+{
+	u32 ctl = cif_dvp_read(rkcif, RKCIF_DVP_CTRL);
+
+	cif_dvp_write(rkcif, RKCIF_DVP_CTRL,
+		      ctl & (~RKCIF_CTRL_ENABLE_CAPTURE));
+	cif_dvp_write(rkcif, RKCIF_DVP_CTRL, ctl | RKCIF_CTRL_ENABLE_CAPTURE);
+}
+
+static void rkcif_dvp_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
+{
+	struct rkcif_device *rkcif = stream->rkcif;
+	u32 val;
+
+	val = RKCIF_XY_COORD(left, top);
+	cif_dvp_write(rkcif, RKCIF_DVP_CROP, val);
+}
+
+irqreturn_t rkcif_dvp_isr(int irq, void *ctx)
+{
+	struct device *dev = ctx;
+	struct rkcif_device *rkcif = dev_get_drvdata(dev);
+	struct rkcif_stream *stream;
+	u32 intstat, lastline, lastpix, cif_frmst;
+	irqreturn_t ret = IRQ_NONE;
+
+	if (!rkcif->match_data->dvp)
+		return ret;
+
+	intstat = cif_dvp_read(rkcif, RKCIF_DVP_INTSTAT);
+	cif_frmst = cif_dvp_read(rkcif, RKCIF_DVP_FRAME_STATUS);
+	lastline = RKCIF_FETCH_Y(cif_dvp_read(rkcif, RKCIF_DVP_LAST_LINE));
+	lastpix = RKCIF_FETCH_Y(cif_dvp_read(rkcif, RKCIF_DVP_LAST_PIX));
+
+	if (intstat & RKCIF_INTSTAT_FRAME_END) {
+		cif_dvp_write(rkcif, RKCIF_DVP_INTSTAT,
+			      RKCIF_INTSTAT_FRAME_END_CLR |
+				      RKCIF_INTSTAT_LINE_END_CLR);
+
+		stream = &rkcif->interfaces[RKCIF_DVP].streams[RKCIF_ID0];
+
+		if (stream->stopping) {
+			cif_dvp_stop_streaming(stream);
+			wake_up(&stream->wq_stopped);
+			return IRQ_HANDLED;
+		}
+
+		if (lastline != stream->pix.height) {
+			v4l2_err(&rkcif->v4l2_dev,
+				 "bad frame, irq:%#x frmst:%#x size:%dx%d\n",
+				 intstat, cif_frmst, lastpix, lastline);
+
+			cif_dvp_reset_stream(rkcif);
+		}
+
+		rkcif_stream_pingpong(stream);
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+int rkcif_dvp_register(struct rkcif_device *rkcif)
+{
+	struct rkcif_interface *interface;
+	int ret, i;
+
+	if (!rkcif->match_data->dvp)
+		return 0;
+
+	interface = &rkcif->interfaces[RKCIF_DVP];
+	interface->index = RKCIF_DVP;
+	interface->type = RKCIF_IF_DVP;
+	interface->in_fmts = rkcif->match_data->dvp->in_fmts;
+	interface->in_fmts_num = rkcif->match_data->dvp->in_fmts_num;
+	interface->set_crop = rkcif_dvp_set_crop;
+	ret = rkcif_interface_register(rkcif, interface);
+	if (ret)
+		return 0;
+
+	if (rkcif->match_data->dvp->setup)
+		rkcif->match_data->dvp->setup(rkcif);
+
+	interface->streams_num = rkcif->match_data->dvp->has_ids ? 4 : 1;
+	for (i = 0; i < interface->streams_num; i++) {
+		struct rkcif_stream *stream = &interface->streams[i];
+
+		stream->id = i;
+		stream->interface = interface;
+		stream->out_fmts = rkcif->match_data->dvp->out_fmts;
+		stream->out_fmts_num = rkcif->match_data->dvp->out_fmts_num;
+		stream->queue_buffer = cif_dvp_queue_buffer;
+		stream->start_streaming = cif_dvp_start_streaming;
+		stream->stop_streaming = cif_dvp_stop_streaming;
+
+		ret = rkcif_stream_register(rkcif, stream);
+		if (ret)
+			goto err_streams_unregister;
+	}
+	return 0;
+
+err_streams_unregister:
+	for (; i >= 0; i--)
+		rkcif_stream_unregister(&interface->streams[i]);
+	rkcif_interface_unregister(interface);
+
+	return ret;
+}
+
+void rkcif_dvp_unregister(struct rkcif_device *rkcif)
+{
+	struct rkcif_interface *interface;
+	int i;
+
+	if (!rkcif->match_data->dvp)
+		return;
+
+	interface = &rkcif->interfaces[RKCIF_DVP];
+
+	for (i = 0; i < interface->streams_num; i++)
+		rkcif_stream_unregister(&interface->streams[i]);
+	rkcif_interface_unregister(interface);
+}
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.h
new file mode 100644
index 000000000000..be4decfd80bc
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait at bootlin.com>
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_CAPTURE_DVP_H
+#define _RKCIF_CAPTURE_DVP_H
+
+#include "rkcif-common.h"
+
+extern const struct rkcif_dvp_match_data px30_vip_dvp_match_data;
+extern const struct rkcif_dvp_match_data rk3568_vicap_dvp_match_data;
+
+int rkcif_dvp_register(struct rkcif_device *rkcif);
+
+void rkcif_dvp_unregister(struct rkcif_device *rkcif);
+
+irqreturn_t rkcif_dvp_isr(int irq, void *ctx);
+
+#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
new file mode 100644
index 000000000000..0c3f7b8cfa18
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include "rkcif-capture-mipi.h"
+#include "rkcif-common.h"
+#include "rkcif-stream.h"
+
+irqreturn_t rkcif_mipi_isr(int irq, void *ctx)
+{
+	irqreturn_t ret = IRQ_NONE;
+
+	return ret;
+}
+
+int rkcif_mipi_register(struct rkcif_device *rkcif)
+{
+	return 0;
+}
+
+void rkcif_mipi_unregister(struct rkcif_device *rkcif)
+{
+}
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
new file mode 100644
index 000000000000..ee1a50a59505
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_CAPTURE_MIPI_H
+#define _RKCIF_CAPTURE_MIPI_H
+
+#include "rkcif-common.h"
+
+int rkcif_mipi_register(struct rkcif_device *rkcif);
+
+void rkcif_mipi_unregister(struct rkcif_device *rkcif);
+
+irqreturn_t rkcif_mipi_isr(int irq, void *ctx);
+
+#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-common.h b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
new file mode 100644
index 000000000000..32f6f0238656
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait at bootlin.com>
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_COMMON_H
+#define _RKCIF_COMMON_H
+
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "rkcif-regs.h"
+
+#define RKCIF_DRIVER_NAME "rockchip-cif"
+#define RKCIF_CLK_MAX	  4
+
+enum rkcif_format_type {
+	RKCIF_FMT_TYPE_INVALID,
+	RKCIF_FMT_TYPE_YUV,
+	RKCIF_FMT_TYPE_RAW,
+};
+
+enum rkcif_id_index {
+	RKCIF_ID0,
+	RKCIF_ID1,
+	RKCIF_ID2,
+	RKCIF_ID3,
+	RKCIF_ID_MAX
+};
+
+enum rkcif_interface_index {
+	RKCIF_DVP,
+	RKCIF_MIPI_BASE,
+	RKCIF_MIPI1 = RKCIF_MIPI_BASE,
+	RKCIF_MIPI2,
+	RKCIF_MIPI3,
+	RKCIF_MIPI4,
+	RKCIF_MIPI5,
+	RKCIF_MIPI6,
+	RKCIF_MIPI_MAX = RKCIF_MIPI6,
+	RKCIF_IF_MAX = RKCIF_MIPI_MAX
+};
+
+enum rkcif_interface_pad_index {
+	RKCIF_IF_PAD_SINK,
+	RKCIF_IF_PAD_SRC,
+	RKCIF_IF_PAD_MAX
+};
+
+enum rkcif_interface_status {
+	RKCIF_IF_INACTIVE,
+	RKCIF_IF_ACTIVE,
+};
+
+enum rkcif_interface_type {
+	RKCIF_IF_INVALID,
+	RKCIF_IF_DVP,
+	RKCIF_IF_MIPI,
+};
+
+enum rkcif_plane_index {
+	RKCIF_PLANE_Y,
+	RKCIF_PLANE_UV,
+	RKCIF_PLANE_MAX
+};
+
+struct rkcif_input_fmt {
+	u32 mbus_code;
+
+	enum rkcif_format_type fmt_type;
+	enum v4l2_field field;
+
+	union {
+		u32 dvp_fmt_val;
+	};
+};
+
+struct rkcif_output_fmt {
+	u32 fourcc;
+	u32 mbus_code;
+	u8 cplanes;
+
+	union {
+		u32 dvp_fmt_val;
+	};
+};
+
+struct rkcif_buffer {
+	struct vb2_v4l2_buffer vb;
+	struct list_head queue;
+	dma_addr_t buff_addr[VIDEO_MAX_PLANES];
+	bool is_dummy;
+};
+
+struct rkcif_dummy_buffer {
+	struct rkcif_buffer buffer;
+	void *vaddr;
+	u32 size;
+};
+
+struct rkcif_interface;
+
+struct rkcif_remote {
+	struct v4l2_async_connection async_conn;
+	struct v4l2_subdev *sd;
+
+	struct rkcif_interface *interface;
+};
+
+struct rkcif_stream {
+	enum rkcif_id_index id;
+	struct rkcif_device *rkcif;
+	struct rkcif_interface *interface;
+	const struct rkcif_output_fmt *out_fmts;
+	unsigned int out_fmts_num;
+
+	/* in ping-pong mode, two buffers can be provided to the HW */
+	struct rkcif_buffer *buffers[2];
+	int frame_idx;
+	int frame_phase;
+
+	/* in case of no available buffer, HW can write to the dummy buffer */
+	struct rkcif_dummy_buffer dummy;
+
+	bool stopping;
+	wait_queue_head_t wq_stopped;
+
+	/* queue of available buffers plus spinlock that protects it */
+	spinlock_t driver_queue_lock;
+	struct list_head driver_queue;
+
+	/* lock used by the V4L2 core */
+	struct mutex vlock;
+
+	struct media_pad pad;
+	struct media_pipeline pipeline;
+	struct v4l2_pix_format_mplane pix;
+	struct vb2_queue buf_queue;
+	struct video_device vdev;
+
+	void (*queue_buffer)(struct rkcif_stream *stream, unsigned int index);
+	int (*start_streaming)(struct rkcif_stream *stream);
+	void (*stop_streaming)(struct rkcif_stream *stream);
+};
+
+struct rkcif_dvp {
+	u32 cif_clk_delaynum;
+};
+
+struct rkcif_interface {
+	enum rkcif_interface_type type;
+	enum rkcif_interface_status status;
+	enum rkcif_interface_index index;
+	struct rkcif_device *rkcif;
+	struct rkcif_remote *remote;
+	struct rkcif_stream streams[RKCIF_ID_MAX];
+	unsigned int streams_num;
+	const struct rkcif_input_fmt *in_fmts;
+	unsigned int in_fmts_num;
+
+	struct media_pad pads[RKCIF_IF_PAD_MAX];
+	struct v4l2_fwnode_endpoint vep;
+	struct v4l2_subdev sd;
+
+	union {
+		struct rkcif_dvp dvp;
+	};
+
+	void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
+};
+
+struct rkcif_dvp_match_data {
+	const struct rkcif_input_fmt *in_fmts;
+	unsigned int in_fmts_num;
+	const struct rkcif_output_fmt *out_fmts;
+	unsigned int out_fmts_num;
+	void (*setup)(struct rkcif_device *rkcif);
+	bool has_scaler;
+	bool has_ids;
+	unsigned int regs[RKCIF_DVP_REGISTER_MAX];
+};
+
+struct rkcif_match_data {
+	const char *const *clks;
+	unsigned int clks_num;
+	const struct rkcif_dvp_match_data *dvp;
+};
+
+struct rkcif_device {
+	struct device *dev;
+
+	const struct rkcif_match_data *match_data;
+	struct clk_bulk_data clks[RKCIF_CLK_MAX];
+	unsigned int clks_num;
+	struct regmap *grf;
+	struct reset_control *reset;
+	void __iomem *base_addr;
+
+	struct rkcif_interface interfaces[RKCIF_IF_MAX];
+
+	struct media_device media_dev;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_async_notifier notifier;
+};
+
+#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
new file mode 100644
index 000000000000..2f45229183f6
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2020 Maxime Chevallier <maxime.chevallier at bootlin.com>
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait at bootlin.com>
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+
+#include "rkcif-capture-dvp.h"
+#include "rkcif-capture-mipi.h"
+#include "rkcif-common.h"
+
+const char *const px30_vip_clks[] = {
+	"aclk",
+	"hclk",
+	"pclk",
+};
+
+static const struct rkcif_match_data px30_vip_match_data = {
+	.clks = px30_vip_clks,
+	.clks_num = ARRAY_SIZE(px30_vip_clks),
+	.dvp = &px30_vip_dvp_match_data,
+};
+
+const char *const rk3568_vicap_clks[] = {
+	"aclk",
+	"hclk",
+	"dclk",
+	"iclk",
+};
+
+static const struct rkcif_match_data rk3568_vicap_match_data = {
+	.clks = rk3568_vicap_clks,
+	.clks_num = ARRAY_SIZE(rk3568_vicap_clks),
+	.dvp = &rk3568_vicap_dvp_match_data,
+};
+
+static const struct of_device_id rkcif_plat_of_match[] = {
+	{
+		.compatible = "rockchip,px30-vip",
+		.data = &px30_vip_match_data,
+	},
+	{
+		.compatible = "rockchip,rk3568-vicap",
+		.data = &rk3568_vicap_match_data,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, rkcif_plat_of_match);
+
+static int rkcif_notifier_bound(struct v4l2_async_notifier *notifier,
+				struct v4l2_subdev *sd,
+				struct v4l2_async_connection *asd)
+{
+	struct rkcif_device *rkcif =
+		container_of(notifier, struct rkcif_device, notifier);
+	struct rkcif_remote *remote =
+		container_of(asd, struct rkcif_remote, async_conn);
+	struct media_pad *sink_pad =
+		&remote->interface->pads[RKCIF_IF_PAD_SINK];
+	int ret;
+
+	ret = v4l2_create_fwnode_links_to_pad(sd, sink_pad,
+					      MEDIA_LNK_FL_ENABLED);
+	if (ret) {
+		dev_err(rkcif->dev, "failed to link source pad of %s\n",
+			sd->name);
+		return ret;
+	}
+
+	remote->sd = sd;
+
+	return 0;
+}
+
+static int rkcif_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+	struct rkcif_device *rkcif =
+		container_of(notifier, struct rkcif_device, notifier);
+
+	return v4l2_device_register_subdev_nodes(&rkcif->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations rkcif_notifier_ops = {
+	.bound = rkcif_notifier_bound,
+	.complete = rkcif_notifier_complete,
+};
+
+static int rkcif_register(struct rkcif_device *rkcif)
+{
+	struct v4l2_async_notifier *ntf = &rkcif->notifier;
+	int ret;
+
+	v4l2_async_nf_init(ntf, &rkcif->v4l2_dev);
+	ntf->ops = &rkcif_notifier_ops;
+
+	ret = rkcif_dvp_register(rkcif);
+	if (ret && ret != -ENODEV)
+		goto err_notifier_cleanup;
+
+	ret = rkcif_mipi_register(rkcif);
+	if (ret && ret != -ENODEV)
+		goto err_dvp_unregister;
+
+	ret = v4l2_async_nf_register(ntf);
+	if (ret)
+		goto err_mipi_unregister;
+
+	return 0;
+
+err_mipi_unregister:
+	rkcif_mipi_unregister(rkcif);
+err_dvp_unregister:
+	rkcif_dvp_unregister(rkcif);
+err_notifier_cleanup:
+	v4l2_async_nf_cleanup(&rkcif->notifier);
+	return ret;
+}
+
+static void rkcif_unregister(struct rkcif_device *rkcif)
+{
+	v4l2_async_nf_unregister(&rkcif->notifier);
+	rkcif_mipi_unregister(rkcif);
+	rkcif_dvp_unregister(rkcif);
+	v4l2_async_nf_cleanup(&rkcif->notifier);
+}
+
+static irqreturn_t rkcif_isr(int irq, void *ctx)
+{
+	irqreturn_t ret = IRQ_NONE;
+
+	if (rkcif_dvp_isr(irq, ctx) == IRQ_HANDLED)
+		ret = IRQ_HANDLED;
+
+	if (rkcif_mipi_isr(irq, ctx) == IRQ_HANDLED)
+		ret = IRQ_HANDLED;
+
+	return ret;
+}
+
+static int rkcif_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rkcif_device *rkcif;
+	u32 cif_clk_delaynum = 0;
+	int ret, irq, i;
+
+	rkcif = devm_kzalloc(dev, sizeof(*rkcif), GFP_KERNEL);
+	if (!rkcif)
+		return -ENOMEM;
+
+	rkcif->match_data = of_device_get_match_data(dev);
+	if (!rkcif->match_data)
+		return -ENODEV;
+
+	dev_set_drvdata(dev, rkcif);
+	rkcif->dev = dev;
+
+	rkcif->base_addr = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(rkcif->base_addr))
+		return PTR_ERR(rkcif->base_addr);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(dev, irq, rkcif_isr, IRQF_SHARED,
+			       dev_driver_string(dev), dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to request irq\n");
+
+	rkcif->clks_num = rkcif->match_data->clks_num;
+	for (i = 0; (i < rkcif->clks_num) && (i < RKCIF_CLK_MAX); i++)
+		rkcif->clks[i].id = rkcif->match_data->clks[i];
+	ret = devm_clk_bulk_get(dev, rkcif->clks_num, rkcif->clks);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to get clocks\n");
+
+	rkcif->reset = devm_reset_control_array_get_exclusive(dev);
+	if (IS_ERR(rkcif->reset))
+		return PTR_ERR(rkcif->reset);
+
+	rkcif->grf =
+		syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+	if (IS_ERR(rkcif->grf))
+		rkcif->grf = NULL;
+
+	if (rkcif->match_data->dvp) {
+		of_property_read_u32(dev->of_node, "rockchip,cif-clk-delaynum",
+				     &cif_clk_delaynum);
+		rkcif->interfaces[RKCIF_DVP].dvp.cif_clk_delaynum =
+			cif_clk_delaynum;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	rkcif->media_dev.dev = dev;
+	strscpy(rkcif->media_dev.model, RKCIF_DRIVER_NAME,
+		sizeof(rkcif->media_dev.model));
+	media_device_init(&rkcif->media_dev);
+
+	rkcif->v4l2_dev.mdev = &rkcif->media_dev;
+	ret = v4l2_device_register(dev, &rkcif->v4l2_dev);
+	if (ret)
+		goto err_media_dev_cleanup;
+
+	ret = media_device_register(&rkcif->media_dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register media device: %d\n", ret);
+		goto err_v4l2_dev_unregister;
+	}
+
+	ret = rkcif_register(rkcif);
+	if (ret) {
+		dev_err(dev, "failed to register media entities: %d\n", ret);
+		goto err_media_dev_unregister;
+	}
+
+	return 0;
+
+err_media_dev_unregister:
+	media_device_unregister(&rkcif->media_dev);
+err_v4l2_dev_unregister:
+	v4l2_device_unregister(&rkcif->v4l2_dev);
+err_media_dev_cleanup:
+	media_device_cleanup(&rkcif->media_dev);
+	pm_runtime_disable(&pdev->dev);
+	return ret;
+}
+
+static void rkcif_remove(struct platform_device *pdev)
+{
+	struct rkcif_device *rkcif = platform_get_drvdata(pdev);
+
+	rkcif_unregister(rkcif);
+	media_device_unregister(&rkcif->media_dev);
+	v4l2_device_unregister(&rkcif->v4l2_dev);
+	media_device_cleanup(&rkcif->media_dev);
+	pm_runtime_disable(&pdev->dev);
+}
+
+static int rkcif_runtime_suspend(struct device *dev)
+{
+	struct rkcif_device *rkcif = dev_get_drvdata(dev);
+
+	/*
+	 * Reset CIF (CRU, DMA, FIFOs) to allow a clean resume.
+	 * Since this resets the IOMMU too, we cannot issue this reset when
+	 * resuming.
+	 */
+	reset_control_assert(rkcif->reset);
+	udelay(5);
+	reset_control_deassert(rkcif->reset);
+
+	clk_bulk_disable_unprepare(rkcif->clks_num, rkcif->clks);
+
+	return 0;
+}
+
+static int rkcif_runtime_resume(struct device *dev)
+{
+	struct rkcif_device *rkcif = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_bulk_prepare_enable(rkcif->clks_num, rkcif->clks);
+	if (ret) {
+		dev_err(dev, "failed to enable clocks\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops rkcif_plat_pm_ops = {
+	.runtime_suspend = rkcif_runtime_suspend,
+	.runtime_resume = rkcif_runtime_resume,
+};
+
+static struct platform_driver rkcif_plat_drv = {
+	.driver = {
+		   .name = RKCIF_DRIVER_NAME,
+		   .of_match_table = rkcif_plat_of_match,
+		   .pm = &rkcif_plat_pm_ops,
+	},
+	.probe = rkcif_probe,
+	.remove = rkcif_remove,
+};
+module_platform_driver(rkcif_plat_drv);
+
+MODULE_DESCRIPTION("Rockchip Camera Interface (CIF) platform driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
new file mode 100644
index 000000000000..7131de68de2c
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+#include "rkcif-common.h"
+#include "rkcif-interface.h"
+
+static inline struct rkcif_interface *to_rkcif_interface(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct rkcif_interface, sd);
+}
+
+static const struct media_entity_operations rkcif_interface_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+	.has_pad_interdep = v4l2_subdev_has_pad_interdep,
+};
+
+static int rkcif_interface_set_fmt(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state,
+				   struct v4l2_subdev_format *format)
+{
+	struct rkcif_interface *interface = to_rkcif_interface(sd);
+	const struct rkcif_input_fmt *input;
+	struct v4l2_mbus_framefmt *sink, *src;
+
+	/* the format on the source pad always matches the sink pad */
+	if (format->pad == RKCIF_IF_PAD_SRC)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	input = rkcif_interface_find_input_fmt(interface, true,
+					       format->format.code);
+	format->format.code = input->mbus_code;
+
+	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
+	if (!sink)
+		return -EINVAL;
+
+	*sink = format->format;
+
+	/* propagate the format to the source pad */
+	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!src)
+		return -EINVAL;
+
+	*src = *sink;
+
+	return 0;
+}
+
+static int rkcif_interface_get_sel(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state,
+				   struct v4l2_subdev_selection *sel)
+{
+	struct v4l2_mbus_framefmt *sink;
+	struct v4l2_rect *crop;
+	int ret = 0;
+
+	if (sel->pad != RKCIF_IF_PAD_SRC)
+		return -EINVAL;
+
+	sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad,
+							    sel->stream);
+	if (!sink)
+		return -EINVAL;
+
+	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
+	if (!crop)
+		return -EINVAL;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = sink->width;
+		sel->r.height = sink->height;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = *crop;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rkcif_interface_set_sel(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state,
+				   struct v4l2_subdev_selection *sel)
+{
+	struct v4l2_mbus_framefmt *sink, *src;
+	struct v4l2_rect *crop;
+
+	if (sel->pad != RKCIF_IF_PAD_SRC || sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad,
+							    sel->stream);
+	if (!sink)
+		return -EINVAL;
+
+	src = v4l2_subdev_state_get_format(state, sel->pad, sel->stream);
+	if (!src)
+		return -EINVAL;
+
+	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
+	if (!crop)
+		return -EINVAL;
+
+	/* only starting point of crop can be specified */
+	sel->r.height = sink->height - sel->r.top;
+	sel->r.width = sink->width - sel->r.left;
+	*crop = sel->r;
+
+	src->height = sel->r.height;
+	src->width = sel->r.width;
+
+	return 0;
+}
+
+static int rkcif_interface_set_routing(struct v4l2_subdev *sd,
+				       struct v4l2_subdev_state *state,
+				       enum v4l2_subdev_format_whence which,
+				       struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	for (unsigned int i = 0; i < routing->num_routes; i++) {
+		const struct v4l2_subdev_route *route = &routing->routes[i];
+
+		if (route->source_stream >= RKCIF_ID_MAX)
+			return -EINVAL;
+	}
+
+	ret = v4l2_subdev_set_routing(sd, state, routing);
+
+	return ret;
+}
+
+static int rkcif_interface_apply_crop(struct rkcif_stream *stream,
+				      struct v4l2_subdev_state *state)
+{
+	struct rkcif_interface *interface = stream->interface;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_state_get_crop(state, RKCIF_IF_PAD_SRC, stream->id);
+	if (!crop)
+		return -EINVAL;
+
+	if (interface->set_crop)
+		interface->set_crop(stream, crop->left, crop->top);
+
+	return 0;
+}
+
+static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
+					  struct v4l2_subdev_state *state,
+					  u32 pad, u64 streams_mask)
+{
+	struct rkcif_interface *interface = to_rkcif_interface(sd);
+	struct rkcif_stream *stream;
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *remote_pad;
+	u64 mask;
+
+	remote_pad =
+		media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	/* DVP has one crop setting for all IDs */
+	if (interface->type == RKCIF_IF_DVP) {
+		stream = &interface->streams[RKCIF_ID0];
+		rkcif_interface_apply_crop(stream, state);
+	} else {
+		/* TODO implement for MIPI */
+	}
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
+					       RKCIF_IF_PAD_SRC, &streams_mask);
+
+	return v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
+}
+
+static int rkcif_interface_disable_streams(struct v4l2_subdev *sd,
+					   struct v4l2_subdev_state *state,
+					   u32 pad, u64 streams_mask)
+{
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *remote_pad;
+	u64 mask;
+
+	remote_pad =
+		media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
+					       RKCIF_IF_PAD_SRC, &streams_mask);
+
+	return v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
+}
+
+static const struct v4l2_subdev_pad_ops rkcif_interface_pad_ops = {
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = rkcif_interface_set_fmt,
+	.get_selection = rkcif_interface_get_sel,
+	.set_selection = rkcif_interface_set_sel,
+	.set_routing = rkcif_interface_set_routing,
+	.enable_streams = rkcif_interface_enable_streams,
+	.disable_streams = rkcif_interface_disable_streams,
+};
+
+static const struct v4l2_subdev_ops rkcif_interface_ops = {
+	.pad = &rkcif_interface_pad_ops,
+};
+
+static int rkcif_interface_init_state(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_state *state)
+{
+	struct rkcif_interface *interface = to_rkcif_interface(sd);
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = RKCIF_IF_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = RKCIF_IF_PAD_SRC,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+	struct v4l2_subdev_krouting routing = {
+		.len_routes = ARRAY_SIZE(routes),
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+	const struct v4l2_mbus_framefmt dvp_default_format = {
+		.width = 3840,
+		.height = 2160,
+		.code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_REC709,
+		.ycbcr_enc = V4L2_YCBCR_ENC_709,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_NONE,
+	};
+	const struct v4l2_mbus_framefmt mipi_default_format = {
+		.width = 3840,
+		.height = 2160,
+		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_RAW,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_FULL_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_NONE,
+	};
+	const struct v4l2_mbus_framefmt *default_format;
+	int ret;
+
+	default_format = (interface->type == RKCIF_IF_DVP) ?
+				 &dvp_default_format :
+				 &mipi_default_format;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
+					       default_format);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops rkcif_interface_internal_ops = {
+	.init_state = rkcif_interface_init_state,
+};
+
+static int rkcif_interface_add(struct rkcif_interface *interface)
+{
+	struct rkcif_device *rkcif = interface->rkcif;
+	struct rkcif_remote *remote;
+	struct v4l2_async_notifier *ntf = &rkcif->notifier;
+	struct v4l2_fwnode_endpoint *vep = &interface->vep;
+	struct device *dev = rkcif->dev;
+	struct fwnode_handle *ep;
+	int ret;
+
+	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), interface->index,
+					     0, 0);
+	if (!ep)
+		return -ENODEV;
+
+	vep->bus_type = V4L2_MBUS_UNKNOWN;
+	ret = v4l2_fwnode_endpoint_parse(ep, vep);
+	if (ret)
+		goto complete;
+
+	if (interface->type == RKCIF_IF_DVP) {
+		if (vep->bus_type != V4L2_MBUS_BT656 &&
+		    vep->bus_type != V4L2_MBUS_PARALLEL) {
+			ret = dev_err_probe(dev, -EINVAL,
+					    "unsupported bus type\n");
+			goto complete;
+		}
+	}
+
+	remote = v4l2_async_nf_add_fwnode_remote(ntf, ep, struct rkcif_remote);
+	if (IS_ERR(remote)) {
+		ret = PTR_ERR(remote);
+		goto complete;
+	}
+
+	remote->interface = interface;
+	interface->remote = remote;
+	interface->status = RKCIF_IF_ACTIVE;
+	ret = 0;
+
+complete:
+	fwnode_handle_put(ep);
+
+	return ret;
+}
+
+int rkcif_interface_register(struct rkcif_device *rkcif,
+			     struct rkcif_interface *interface)
+{
+	struct media_pad *pads = interface->pads;
+	struct v4l2_subdev *sd = &interface->sd;
+	int ret;
+
+	interface->rkcif = rkcif;
+
+	v4l2_subdev_init(sd, &rkcif_interface_ops);
+	sd->dev = rkcif->dev;
+	sd->entity.ops = &rkcif_interface_media_ops;
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+	sd->internal_ops = &rkcif_interface_internal_ops;
+	sd->owner = THIS_MODULE;
+
+	if (interface->type == RKCIF_IF_DVP)
+		snprintf(sd->name, sizeof(sd->name), "rkcif-dvp0");
+	else if (interface->type == RKCIF_IF_MIPI)
+		snprintf(sd->name, sizeof(sd->name), "rkcif-mipi%d",
+			 interface->index - RKCIF_MIPI_BASE);
+
+	pads[RKCIF_IF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[RKCIF_IF_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_pads_init(&sd->entity, RKCIF_IF_PAD_MAX, pads);
+	if (ret)
+		goto err;
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret)
+		goto err_entity_cleanup;
+
+	ret = v4l2_device_register_subdev(&rkcif->v4l2_dev, sd);
+	if (ret) {
+		dev_err(sd->dev, "failed to register subdev\n");
+		goto err_subdev_cleanup;
+	}
+
+	ret = rkcif_interface_add(interface);
+	if (ret)
+		goto err_subdev_unregister;
+
+	return 0;
+
+err_subdev_unregister:
+	v4l2_device_unregister_subdev(sd);
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(sd);
+err_entity_cleanup:
+	media_entity_cleanup(&sd->entity);
+err:
+	return ret;
+}
+
+void rkcif_interface_unregister(struct rkcif_interface *interface)
+{
+	struct v4l2_subdev *sd = &interface->sd;
+
+	if (interface->status != RKCIF_IF_ACTIVE)
+		return;
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_subdev_cleanup(sd);
+	media_entity_cleanup(&sd->entity);
+}
+
+const struct rkcif_input_fmt *
+rkcif_interface_find_input_fmt(struct rkcif_interface *interface, bool ret_def,
+			       u32 mbus_code)
+{
+	const struct rkcif_input_fmt *fmt;
+	unsigned int i;
+
+	WARN_ON(interface->in_fmts_num == 0);
+
+	for (i = 0; i < interface->in_fmts_num; i++) {
+		fmt = &interface->in_fmts[i];
+		if (fmt->mbus_code == mbus_code)
+			return fmt;
+	}
+	if (ret_def)
+		return &interface->in_fmts[0];
+	else
+		return NULL;
+}
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-interface.h b/drivers/media/platform/rockchip/rkcif/rkcif-interface.h
new file mode 100644
index 000000000000..5df6cf6e480d
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-interface.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Abstraction for the INTERFACE and CROP parts of the different CIF variants.
+ * They shall be represented as V4L2 subdevice with one sink pad and one
+ * source pad. The sink pad is connected to a subdevice: either the subdevice
+ * provided by the driver of the companion chip connected to the DVP, or the
+ * subdevice provided by the MIPI CSI Host driver in rkcif-mipi-csi-host.c.
+ * The source pad is connected to an instance of the DMA abstraction in
+ * rkcif-stream.c.
+ *
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_INTERFACE_H
+#define _RKCIF_INTERFACE_H
+
+#include "rkcif-common.h"
+
+int rkcif_interface_register(struct rkcif_device *rkcif,
+			     struct rkcif_interface *interface);
+
+void rkcif_interface_unregister(struct rkcif_interface *interface);
+
+const struct rkcif_input_fmt *
+rkcif_interface_find_input_fmt(struct rkcif_interface *interface, bool ret_def,
+			       u32 mbus_code);
+
+#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
new file mode 100644
index 000000000000..07fd64174e80
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait at bootlin.com>
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_REGS_H
+#define _RKCIF_REGS_H
+
+enum rkcif_dvp_register_index {
+	RKCIF_DVP_CTRL,
+	RKCIF_DVP_INTEN,
+	RKCIF_DVP_INTSTAT,
+	RKCIF_DVP_FOR,
+	RKCIF_DVP_LINE_NUM_ADDR,
+	RKCIF_DVP_FRM0_ADDR_Y,
+	RKCIF_DVP_FRM0_ADDR_UV,
+	RKCIF_DVP_FRM1_ADDR_Y,
+	RKCIF_DVP_FRM1_ADDR_UV,
+	RKCIF_DVP_VIR_LINE_WIDTH,
+	RKCIF_DVP_SET_SIZE,
+	RKCIF_DVP_SCL_CTRL,
+	RKCIF_DVP_CROP,
+	RKCIF_DVP_FRAME_STATUS,
+	RKCIF_DVP_LAST_LINE,
+	RKCIF_DVP_LAST_PIX,
+	RKCIF_DVP_REGISTER_MAX
+};
+
+#define RKCIF_REGISTER_NOTSUPPORTED           0x420000
+
+#define RKCIF_FETCH_Y(VAL)		       ((VAL) & 0x1fff)
+
+#define RKCIF_CTRL_ENABLE_CAPTURE	       BIT(0)
+#define RKCIF_CTRL_MODE_PINGPONG	       BIT(1)
+#define RKCIF_CTRL_MODE_LINELOOP	       BIT(2)
+#define RKCIF_CTRL_AXI_BURST_16		       (0xf << 12)
+
+#define RKCIF_INTEN_FRAME_END_EN	       BIT(0)
+#define RKCIF_INTEN_LINE_ERR_EN		       BIT(2)
+#define RKCIF_INTEN_BUS_ERR_EN		       BIT(6)
+#define RKCIF_INTEN_SCL_ERR_EN		       BIT(7)
+#define RKCIF_INTEN_PST_INF_FRAME_END_EN       BIT(9)
+
+#define RKCIF_INTSTAT_CLS		       0x3ff
+#define RKCIF_INTSTAT_FRAME_END		       BIT(0)
+#define RKCIF_INTSTAT_LINE_END		       BIT(1)
+#define RKCIF_INTSTAT_LINE_ERR		       BIT(2)
+#define RKCIF_INTSTAT_PIX_ERR		       BIT(3)
+#define RKCIF_INTSTAT_DFIFO_OF		       BIT(5)
+#define RKCIF_INTSTAT_BUS_ERR		       BIT(6)
+#define RKCIF_INTSTAT_PRE_INF_FRAME_END	       BIT(8)
+#define RKCIF_INTSTAT_PST_INF_FRAME_END	       BIT(9)
+#define RKCIF_INTSTAT_FRAME_END_CLR	       BIT(0)
+#define RKCIF_INTSTAT_LINE_END_CLR	       BIT(1)
+#define RKCIF_INTSTAT_LINE_ERR_CLR	       BIT(2)
+#define RKCIF_INTSTAT_PST_INF_FRAME_END_CLR    BIT(9)
+#define RKCIF_INTSTAT_ERR		       0xfc
+
+#define RKCIF_FRAME_STAT_CLS		       0x00
+#define RKCIF_FRAME_FRM0_STAT_CLS	       0x20
+
+#define RKCIF_FORMAT_VSY_HIGH_ACTIVE	       BIT(0)
+#define RKCIF_FORMAT_HSY_LOW_ACTIVE	       BIT(1)
+
+#define RKCIF_FORMAT_INPUT_MODE_YUV	       (0x00 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_PAL	       (0x02 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_NTSC	       (0x03 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_BT1120	       (0x07 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_RAW	       (0x04 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_JPEG	       (0x05 << 2)
+#define RKCIF_FORMAT_INPUT_MODE_MIPI	       (0x06 << 2)
+
+#define RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY      (0x00 << 5)
+#define RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU      (0x01 << 5)
+#define RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY      (0x02 << 5)
+#define RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV      (0x03 << 5)
+#define RKCIF_FORMAT_YUV_INPUT_422	       (0x00 << 7)
+#define RKCIF_FORMAT_YUV_INPUT_420	       BIT(7)
+
+#define RKCIF_FORMAT_INPUT_420_ORDER_ODD       BIT(8)
+
+#define RKCIF_FORMAT_CCIR_INPUT_ORDER_EVEN     BIT(9)
+
+#define RKCIF_FORMAT_RAW_DATA_WIDTH_8	       (0x00 << 11)
+#define RKCIF_FORMAT_RAW_DATA_WIDTH_10	       (0x01 << 11)
+#define RKCIF_FORMAT_RAW_DATA_WIDTH_12	       (0x02 << 11)
+
+#define RKCIF_FORMAT_YUV_OUTPUT_422	       (0x00 << 16)
+#define RKCIF_FORMAT_YUV_OUTPUT_420	       BIT(16)
+
+#define RKCIF_FORMAT_OUTPUT_420_ORDER_EVEN     (0x00 << 17)
+#define RKCIF_FORMAT_OUTPUT_420_ORDER_ODD      BIT(17)
+
+#define RKCIF_FORMAT_RAWD_DATA_LITTLE_ENDIAN   (0x00 << 18)
+#define RKCIF_FORMAT_RAWD_DATA_BIG_ENDIAN      BIT(18)
+
+#define RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV     (0x00 << 19)
+#define RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU     BIT(19)
+
+#define RKCIF_FORMAT_BT1120_CLOCK_SINGLE_EDGES (0x00 << 24)
+#define RKCIF_FORMAT_BT1120_CLOCK_DOUBLE_EDGES BIT(24)
+#define RKCIF_FORMAT_BT1120_TRANSMIT_INTERFACE (0x00 << 25)
+#define RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS  BIT(25)
+#define RKCIF_FORMAT_BT1120_YC_SWAP	       BIT(26)
+
+#define RKCIF_SCL_CTRL_ENABLE_SCL_DOWN	       BIT(0)
+#define RKCIF_SCL_CTRL_ENABLE_SCL_UP	       BIT(1)
+#define RKCIF_SCL_CTRL_ENABLE_YUV_16BIT_BYPASS BIT(4)
+#define RKCIF_SCL_CTRL_ENABLE_RAW_16BIT_BYPASS BIT(5)
+#define RKCIF_SCL_CTRL_ENABLE_32BIT_BYPASS     BIT(6)
+#define RKCIF_SCL_CTRL_DISABLE_32BIT_BYPASS    (0x00 << 6)
+
+#define RKCIF_INTSTAT_F0_READY		       BIT(0)
+#define RKCIF_INTSTAT_F1_READY		       BIT(1)
+
+#define RKCIF_XY_COORD(x, y)		       (((y) << 16) | (x))
+
+/* GRF register offsets */
+#define RK3568_GRF_VI_CON0		       0x340
+#define RK3568_GRF_VI_CON1		       0x344
+#define RK3568_GRF_VI_STATUS0		       0x348
+
+#define RK3568_GRF_VI_CON1_CIF_DATAPATH	       BIT(9)
+#define RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM    GENMASK(6, 0)
+
+#define RK3568_GRF_WRITE_ENABLE(x)	       ((x) << 16)
+
+#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-stream.c b/drivers/media/platform/rockchip/rkcif/rkcif-stream.c
new file mode 100644
index 000000000000..bfafd76f4494
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-stream.c
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "rkcif-common.h"
+#include "rkcif-stream.h"
+
+#define CIF_REQ_BUFS_MIN 8
+#define CIF_MIN_WIDTH	 64
+#define CIF_MIN_HEIGHT	 64
+#define CIF_MAX_WIDTH	 8192
+#define CIF_MAX_HEIGHT	 8192
+
+static inline struct rkcif_buffer *to_rkcif_buffer(struct vb2_v4l2_buffer *vb)
+{
+	return container_of(vb, struct rkcif_buffer, vb);
+}
+
+static inline struct rkcif_stream *to_rkcif_stream(struct video_device *vdev)
+{
+	return container_of(vdev, struct rkcif_stream, vdev);
+}
+
+static struct rkcif_buffer *rkcif_stream_pop_buffer(struct rkcif_stream *stream)
+{
+	struct rkcif_buffer *buffer = NULL;
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&stream->driver_queue_lock, lock_flags);
+
+	if (list_empty(&stream->driver_queue))
+		goto err_empty;
+
+	buffer = list_first_entry(&stream->driver_queue, struct rkcif_buffer,
+				  queue);
+	list_del(&buffer->queue);
+
+err_empty:
+	spin_unlock_irqrestore(&stream->driver_queue_lock, lock_flags);
+	return buffer;
+}
+
+static void rkcif_stream_push_buffer(struct rkcif_stream *stream,
+				     struct rkcif_buffer *buffer)
+{
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&stream->driver_queue_lock, lock_flags);
+	list_add_tail(&buffer->queue, &stream->driver_queue);
+	spin_unlock_irqrestore(&stream->driver_queue_lock, lock_flags);
+}
+
+static inline void rkcif_stream_return_buffer(struct rkcif_buffer *buffer,
+					      enum vb2_buffer_state state)
+{
+	struct vb2_v4l2_buffer *vb = &buffer->vb;
+
+	vb2_buffer_done(&vb->vb2_buf, state);
+}
+
+static void rkcif_stream_complete_buffer(struct rkcif_stream *stream,
+					 struct rkcif_buffer *buffer)
+{
+	struct vb2_v4l2_buffer *vb = &buffer->vb;
+
+	vb->vb2_buf.timestamp = ktime_get_ns();
+	vb->sequence = stream->frame_idx;
+	vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
+	stream->frame_idx++;
+}
+
+void rkcif_stream_pingpong(struct rkcif_stream *stream)
+{
+	struct rkcif_buffer *buffer;
+
+	buffer = stream->buffers[stream->frame_phase];
+	if (!buffer->is_dummy)
+		rkcif_stream_complete_buffer(stream, buffer);
+
+	buffer = rkcif_stream_pop_buffer(stream);
+	if (buffer) {
+		stream->buffers[stream->frame_phase] = buffer;
+		stream->buffers[stream->frame_phase]->is_dummy = false;
+	} else {
+		stream->buffers[stream->frame_phase] = &stream->dummy.buffer;
+		stream->buffers[stream->frame_phase]->is_dummy = true;
+		dev_warn(stream->rkcif->dev,
+			 "no buffer available, frame will be dropped\n");
+	}
+
+	if (stream->queue_buffer)
+		stream->queue_buffer(stream, stream->frame_phase);
+
+	stream->frame_phase = 1 - stream->frame_phase;
+}
+
+static int rkcif_stream_init_buffers(struct rkcif_stream *stream)
+{
+	struct v4l2_pix_format_mplane *pix = &stream->pix;
+	int i;
+
+	stream->buffers[0] = rkcif_stream_pop_buffer(stream);
+	if (!stream->buffers[0])
+		goto err_buff_0;
+
+	stream->buffers[1] = rkcif_stream_pop_buffer(stream);
+	if (!stream->buffers[1])
+		goto err_buff_1;
+
+	if (stream->queue_buffer) {
+		stream->queue_buffer(stream, 0);
+		stream->queue_buffer(stream, 1);
+	}
+
+	stream->dummy.size = pix->num_planes * pix->plane_fmt[0].sizeimage;
+	stream->dummy.vaddr =
+		dma_alloc_attrs(stream->rkcif->dev, stream->dummy.size,
+				&stream->dummy.buffer.buff_addr[0], GFP_KERNEL,
+				DMA_ATTR_NO_KERNEL_MAPPING);
+	if (!stream->dummy.vaddr)
+		goto err_dummy;
+
+	for (i = 1; i < pix->num_planes; i++)
+		stream->dummy.buffer.buff_addr[i] =
+			stream->dummy.buffer.buff_addr[i - 1] +
+			pix->plane_fmt[i - 1].bytesperline * pix->height;
+
+	return 0;
+
+err_dummy:
+	rkcif_stream_return_buffer(stream->buffers[1], VB2_BUF_STATE_QUEUED);
+	stream->buffers[1] = NULL;
+
+err_buff_1:
+	rkcif_stream_return_buffer(stream->buffers[0], VB2_BUF_STATE_QUEUED);
+	stream->buffers[0] = NULL;
+err_buff_0:
+	return -EINVAL;
+}
+
+static void rkcif_stream_return_all_buffers(struct rkcif_stream *stream,
+					    enum vb2_buffer_state state)
+{
+	struct rkcif_buffer *buffer;
+
+	if (stream->buffers[0] && !stream->buffers[0]->is_dummy) {
+		rkcif_stream_return_buffer(stream->buffers[0], state);
+		stream->buffers[0] = NULL;
+	}
+
+	if (stream->buffers[1] && !stream->buffers[1]->is_dummy) {
+		rkcif_stream_return_buffer(stream->buffers[1], state);
+		stream->buffers[1] = NULL;
+	}
+
+	while ((buffer = rkcif_stream_pop_buffer(stream)))
+		rkcif_stream_return_buffer(buffer, state);
+
+	if (stream->dummy.vaddr) {
+		dma_free_attrs(stream->rkcif->dev, stream->dummy.size,
+			       stream->dummy.vaddr,
+			       stream->dummy.buffer.buff_addr[0],
+			       DMA_ATTR_NO_KERNEL_MAPPING);
+		stream->dummy.vaddr = NULL;
+	}
+}
+
+static int rkcif_stream_setup_queue(struct vb2_queue *queue,
+				    unsigned int *num_buffers,
+				    unsigned int *num_planes,
+				    unsigned int sizes[],
+				    struct device *alloc_devs[])
+{
+	struct rkcif_stream *stream = queue->drv_priv;
+	struct v4l2_pix_format_mplane *pix = &stream->pix;
+	unsigned int i;
+
+	if (*num_planes) {
+		if (*num_planes != pix->num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < pix->num_planes; i++)
+			if (sizes[i] < pix->plane_fmt[i].sizeimage)
+				return -EINVAL;
+	} else {
+		*num_planes = pix->num_planes;
+		for (i = 0; i < pix->num_planes; i++)
+			sizes[i] = pix->plane_fmt[i].sizeimage;
+	}
+
+	return 0;
+}
+
+static int rkcif_stream_prepare_buffer(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf);
+	struct rkcif_stream *stream = vb->vb2_queue->drv_priv;
+	const struct rkcif_output_fmt *fmt;
+	struct v4l2_pix_format_mplane *pix = &stream->pix;
+	unsigned int i;
+
+	memset(buffer->buff_addr, 0, sizeof(buffer->buff_addr));
+	for (i = 0; i < pix->num_planes; i++)
+		buffer->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+
+	/* apply fallback for non-mplane formats, if required */
+	if (pix->num_planes == 1) {
+		fmt = rkcif_stream_find_output_fmt(stream, true,
+						   pix->pixelformat);
+		for (i = 1; i < fmt->cplanes; i++)
+			buffer->buff_addr[i] =
+				buffer->buff_addr[i - 1] +
+				pix->plane_fmt[i - 1].bytesperline *
+					pix->height;
+	}
+
+	for (i = 0; i < pix->num_planes; i++) {
+		unsigned long size = pix->plane_fmt[i].sizeimage;
+
+		if (vb2_plane_size(vb, i) < size) {
+			dev_err(stream->rkcif->dev,
+				"user buffer too small (%ld < %ld)\n",
+				vb2_plane_size(vb, i), size);
+			return -EINVAL;
+		}
+
+		vb2_set_plane_payload(vb, i, size);
+	}
+
+	return 0;
+}
+
+static void rkcif_stream_queue_buffer(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf);
+	struct rkcif_stream *stream = vb->vb2_queue->drv_priv;
+
+	rkcif_stream_push_buffer(stream, buffer);
+}
+
+static int rkcif_stream_start_streaming(struct vb2_queue *queue,
+					unsigned int count)
+{
+	struct rkcif_stream *stream = queue->drv_priv;
+	struct rkcif_device *rkcif = stream->rkcif;
+	u64 mask;
+	int ret;
+
+	stream->frame_idx = 0;
+	stream->frame_phase = 0;
+
+	ret = video_device_pipeline_start(&stream->vdev, &stream->pipeline);
+	if (ret) {
+		dev_err(rkcif->dev, "failed to start pipeline %d\n", ret);
+		goto err_out;
+	}
+
+	ret = pm_runtime_resume_and_get(rkcif->dev);
+	if (ret < 0) {
+		dev_err(rkcif->dev, "failed to get runtime pm, %d\n", ret);
+		goto err_pipeline_stop;
+	}
+
+	ret = rkcif_stream_init_buffers(stream);
+	if (ret)
+		goto err_runtime_put;
+
+	if (stream->start_streaming) {
+		ret = stream->start_streaming(stream);
+		if (ret < 0)
+			goto err_runtime_put;
+	}
+
+	mask = BIT_ULL(stream->id);
+	ret = v4l2_subdev_enable_streams(&stream->interface->sd,
+					 RKCIF_IF_PAD_SRC, mask);
+	if (ret < 0)
+		goto err_stop_stream;
+
+	return 0;
+
+err_stop_stream:
+	if (stream->stop_streaming)
+		stream->stop_streaming(stream);
+err_runtime_put:
+	pm_runtime_put(rkcif->dev);
+err_pipeline_stop:
+	video_device_pipeline_stop(&stream->vdev);
+err_out:
+	rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_QUEUED);
+	return ret;
+}
+
+static void rkcif_stream_stop_streaming(struct vb2_queue *queue)
+{
+	struct rkcif_stream *stream = queue->drv_priv;
+	struct rkcif_device *rkcif = stream->rkcif;
+	u64 mask;
+	int ret;
+
+	mask = BIT_ULL(stream->id);
+	v4l2_subdev_disable_streams(&stream->interface->sd, RKCIF_IF_PAD_SRC,
+				    mask);
+
+	stream->stopping = true;
+	ret = wait_event_timeout(stream->wq_stopped, !stream->stopping,
+				 msecs_to_jiffies(1000));
+
+	if (!ret && stream->stop_streaming)
+		stream->stop_streaming(stream);
+
+	pm_runtime_put(rkcif->dev);
+
+	rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_ERROR);
+
+	video_device_pipeline_stop(&stream->vdev);
+}
+
+static const struct vb2_ops rkcif_stream_vb2_ops = {
+	.queue_setup = rkcif_stream_setup_queue,
+	.buf_prepare = rkcif_stream_prepare_buffer,
+	.buf_queue = rkcif_stream_queue_buffer,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = rkcif_stream_start_streaming,
+	.stop_streaming = rkcif_stream_stop_streaming,
+};
+
+static int rkcif_stream_try_format(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct rkcif_stream *stream = video_drvdata(file);
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	const struct rkcif_output_fmt *fmt;
+	u32 height, width;
+
+	fmt = rkcif_stream_find_output_fmt(stream, true, pix->pixelformat);
+	height = clamp_t(u32, pix->height, CIF_MIN_HEIGHT, CIF_MAX_HEIGHT);
+	width = clamp_t(u32, pix->width, CIF_MIN_WIDTH, CIF_MAX_WIDTH);
+	v4l2_fill_pixfmt_mp(pix, fmt->fourcc, width, height);
+
+	return 0;
+}
+
+static int rkcif_stream_set_format(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct rkcif_stream *stream = video_drvdata(file);
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	int ret;
+
+	if (vb2_is_busy(&stream->buf_queue))
+		return -EBUSY;
+
+	ret = rkcif_stream_try_format(file, priv, f);
+	if (ret)
+		return ret;
+
+	stream->pix = *pix;
+
+	return 0;
+}
+
+static int rkcif_stream_get_format(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct rkcif_stream *stream = video_drvdata(file);
+
+	f->fmt.pix_mp = stream->pix;
+
+	return 0;
+}
+
+static int rkcif_stream_enum_formats(struct file *file, void *priv,
+				     struct v4l2_fmtdesc *f)
+{
+	struct rkcif_stream *stream = video_drvdata(file);
+
+	if (f->index >= stream->out_fmts_num)
+		return -EINVAL;
+
+	f->pixelformat = stream->out_fmts[f->index].fourcc;
+
+	return 0;
+}
+
+static int rkcif_stream_enum_framesizes(struct file *file, void *fh,
+					struct v4l2_frmsizeenum *fsize)
+{
+	if (fsize->index > 0)
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = CIF_MIN_WIDTH;
+	fsize->stepwise.max_width = CIF_MAX_WIDTH;
+	fsize->stepwise.step_width = 8;
+	fsize->stepwise.min_height = CIF_MIN_HEIGHT;
+	fsize->stepwise.max_height = CIF_MAX_HEIGHT;
+	fsize->stepwise.step_height = 8;
+
+	return 0;
+}
+
+static int rkcif_stream_querycap(struct file *file, void *priv,
+				 struct v4l2_capability *cap)
+{
+	struct rkcif_stream *stream = video_drvdata(file);
+	struct device *dev = stream->rkcif->dev;
+
+	strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
+	strscpy(cap->card, dev->driver->name, sizeof(cap->card));
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops rkcif_stream_ioctl_ops = {
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+	.vidioc_try_fmt_vid_cap_mplane = rkcif_stream_try_format,
+	.vidioc_s_fmt_vid_cap_mplane = rkcif_stream_set_format,
+	.vidioc_g_fmt_vid_cap_mplane = rkcif_stream_get_format,
+	.vidioc_enum_fmt_vid_cap = rkcif_stream_enum_formats,
+	.vidioc_enum_framesizes = rkcif_stream_enum_framesizes,
+	.vidioc_querycap = rkcif_stream_querycap,
+};
+
+static int rkcif_stream_link_validate(struct media_link *link)
+{
+	struct video_device *vdev =
+		media_entity_to_video_device(link->sink->entity);
+	struct v4l2_mbus_framefmt *source_fmt;
+	struct v4l2_subdev *sd;
+	struct v4l2_subdev_state *state;
+	struct rkcif_stream *stream = to_rkcif_stream(vdev);
+	int ret = -EINVAL;
+
+	if (!media_entity_remote_source_pad_unique(link->sink->entity))
+		return -ENOTCONN;
+
+	sd = media_entity_to_v4l2_subdev(link->source->entity);
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	source_fmt = v4l2_subdev_state_get_format(state, link->source->index,
+						  stream->id);
+	if (!source_fmt)
+		goto out;
+
+	if (source_fmt->height != stream->pix.height ||
+	    source_fmt->width != stream->pix.width) {
+		dev_dbg(stream->rkcif->dev,
+			"link '%s':%u -> '%s':%u not valid: %ux%u != %ux%u\n",
+			link->source->entity->name, link->source->index,
+			link->sink->entity->name, link->sink->index,
+			source_fmt->width, source_fmt->height,
+			stream->pix.width, stream->pix.height);
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	v4l2_subdev_unlock_state(state);
+	return ret;
+}
+
+static const struct media_entity_operations rkcif_stream_media_ops = {
+	.link_validate = rkcif_stream_link_validate,
+};
+
+static const struct v4l2_file_operations rkcif_stream_file_ops = {
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = vb2_fop_poll,
+	.mmap = vb2_fop_mmap,
+};
+
+static int rkcif_stream_init_vb2_queue(struct vb2_queue *q,
+				       struct rkcif_stream *stream)
+{
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->drv_priv = stream;
+	q->ops = &rkcif_stream_vb2_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct rkcif_buffer);
+	q->min_queued_buffers = CIF_REQ_BUFS_MIN;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &stream->vlock;
+	q->dev = stream->rkcif->dev;
+
+	return vb2_queue_init(q);
+}
+
+int rkcif_stream_register(struct rkcif_device *rkcif,
+			  struct rkcif_stream *stream)
+{
+	struct rkcif_interface *interface = stream->interface;
+	struct v4l2_device *v4l2_dev = &rkcif->v4l2_dev;
+	struct video_device *vdev = &stream->vdev;
+	u32 link_flags = 0;
+	int ret;
+
+	stream->rkcif = rkcif;
+
+	INIT_LIST_HEAD(&stream->driver_queue);
+	spin_lock_init(&stream->driver_queue_lock);
+
+	init_waitqueue_head(&stream->wq_stopped);
+
+	mutex_init(&stream->vlock);
+
+	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_IO_MC;
+	vdev->entity.ops = &rkcif_stream_media_ops;
+	vdev->fops = &rkcif_stream_file_ops;
+	vdev->ioctl_ops = &rkcif_stream_ioctl_ops;
+	vdev->lock = &stream->vlock;
+	vdev->minor = -1;
+	vdev->release = video_device_release_empty;
+	vdev->v4l2_dev = v4l2_dev;
+	vdev->vfl_dir = VFL_DIR_RX;
+	video_set_drvdata(vdev, stream);
+
+	stream->pad.flags = MEDIA_PAD_FL_SINK;
+
+	rkcif_stream_init_vb2_queue(&stream->buf_queue, stream);
+
+	vdev->queue = &stream->buf_queue;
+	if (interface->type == RKCIF_IF_DVP)
+		snprintf(vdev->name, sizeof(vdev->name), "rkcif-dvp0-id%d",
+			 stream->id);
+	else if (interface->type == RKCIF_IF_MIPI)
+		snprintf(vdev->name, sizeof(vdev->name), "rkcif-mipi%d-id%d",
+			 interface->index - RKCIF_MIPI_BASE, stream->id);
+
+	ret = media_entity_pads_init(&vdev->entity, 1, &stream->pad);
+	if (ret < 0) {
+		dev_err(rkcif->dev,
+			"failed to initialize stream media pad: %d\n", ret);
+		return ret;
+	}
+
+	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+	if (ret < 0) {
+		dev_err(rkcif->dev, "failed to register video device: %d\n",
+			ret);
+		goto err_media_entity_cleanup;
+	}
+
+	/* enable only stream ID0 by default */
+	if (stream->id == RKCIF_ID0)
+		link_flags |= MEDIA_LNK_FL_ENABLED;
+
+	ret = media_create_pad_link(&interface->sd.entity, RKCIF_IF_PAD_SRC,
+				    &stream->vdev.entity, 0, link_flags);
+	if (ret) {
+		dev_err(rkcif->dev, "failed to link stream media pad: %d\n",
+			ret);
+		goto err_video_unregister;
+	}
+
+	v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name,
+		  vdev->num);
+
+	return 0;
+
+err_video_unregister:
+	video_unregister_device(&stream->vdev);
+err_media_entity_cleanup:
+	media_entity_cleanup(&stream->vdev.entity);
+	return ret;
+}
+
+void rkcif_stream_unregister(struct rkcif_stream *stream)
+{
+	video_unregister_device(&stream->vdev);
+	media_entity_cleanup(&stream->vdev.entity);
+}
+
+const struct rkcif_output_fmt *
+rkcif_stream_find_output_fmt(struct rkcif_stream *stream, bool ret_def,
+			     u32 pixelfmt)
+{
+	const struct rkcif_output_fmt *fmt;
+	unsigned int i;
+
+	WARN_ON(stream->out_fmts_num == 0);
+
+	for (i = 0; i < stream->out_fmts_num; i++) {
+		fmt = &stream->out_fmts[i];
+		if (fmt->fourcc == pixelfmt)
+			return fmt;
+	}
+
+	if (ret_def)
+		return &stream->out_fmts[0];
+	else
+		return NULL;
+}
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-stream.h b/drivers/media/platform/rockchip/rkcif/rkcif-stream.h
new file mode 100644
index 000000000000..e50c9771f1b0
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-stream.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Rockchip Camera Interface (CIF) Driver
+ *
+ * Abstraction for the DMA part and the ping-pong scheme (a double-buffering
+ * mechanism) of the different CIF variants.
+ * Each stream is represented as V4L2 device whose corresponding media entity
+ * has one sink pad.
+ * The sink pad is connected to an instance of the INTERFACE/CROP abstraction
+ * in rkcif-interface.c.
+ *
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#ifndef _RKCIF_STREAM_H
+#define _RKCIF_STREAM_H
+
+#include "rkcif-common.h"
+
+void rkcif_stream_pingpong(struct rkcif_stream *stream);
+
+int rkcif_stream_register(struct rkcif_device *rkcif,
+			  struct rkcif_stream *stream);
+
+void rkcif_stream_unregister(struct rkcif_stream *stream);
+
+const struct rkcif_output_fmt *
+rkcif_stream_find_output_fmt(struct rkcif_stream *stream, bool ret_def,
+			     u32 pixelfmt);
+
+#endif

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:07 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:07 +0100
Subject: [PATCH v5 06/11] media: rockchip: rkcif: add driver for mipi csi-2
 host
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-6-f02152534f3c@wolfvision.net>

The Rockchip RK3568 MIPI CSI-2 Host is a CSI-2 bridge with one input port
and one output port. It receives the data with the help of an external
MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip RK3568 Video
Capture (VICAP) block. Add a V4L2 subdevice driver for this unit.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/media/platform/rockchip/rkcif/Makefile     |   3 +
 .../platform/rockchip/rkcif/rkcif-mipi-csi-host.c  | 731 +++++++++++++++++++++
 2 files changed, 734 insertions(+)

diff --git a/drivers/media/platform/rockchip/rkcif/Makefile b/drivers/media/platform/rockchip/rkcif/Makefile
index 818424972c7b..f3a91912c373 100644
--- a/drivers/media/platform/rockchip/rkcif/Makefile
+++ b/drivers/media/platform/rockchip/rkcif/Makefile
@@ -5,3 +5,6 @@ rockchip-cif-objs += rkcif-dev.o \
 	rkcif-capture-mipi.o \
 	rkcif-interface.o \
 	rkcif-stream.o
+
+obj-$(CONFIG_VIDEO_ROCKCHIP_CIF) += rockchip-mipi-csi.o
+rockchip-mipi-csi-objs += rkcif-mipi-csi-host.o
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
new file mode 100644
index 000000000000..58eb4b102d48
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-mipi-csi-host.c
@@ -0,0 +1,731 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip MIPI CSI-2 Host Driver
+ *
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define CSI2HOST_N_LANES     0x04
+#define CSI2HOST_CSI2_RESETN 0x10
+#define CSI2HOST_PHY_STATE   0x14
+#define CSI2HOST_ERR1	     0x20
+#define CSI2HOST_ERR2	     0x24
+#define CSI2HOST_MSK1	     0x28
+#define CSI2HOST_MSK2	     0x2c
+#define CSI2HOST_CONTROL     0x40
+
+#define SW_CPHY_EN(x)	     ((x) << 0)
+#define SW_DSI_EN(x)	     ((x) << 4)
+#define SW_DATATYPE_FS(x)    ((x) << 8)
+#define SW_DATATYPE_FE(x)    ((x) << 14)
+#define SW_DATATYPE_LS(x)    ((x) << 20)
+#define SW_DATATYPE_LE(x)    ((x) << 26)
+
+#define RKCIF_CSI_CLKS_MAX   1
+
+enum {
+	RKCIF_CSI_PAD_SINK,
+	RKCIF_CSI_PAD_SRC,
+	RKCIF_CSI_PAD_MAX,
+};
+
+struct rkcif_csi_format {
+	u32 code;
+	u8 depth;
+	u8 csi_dt;
+};
+
+struct rkcif_csi_device {
+	struct device *dev;
+
+	void __iomem *base_addr;
+	struct clk_bulk_data *clks;
+	unsigned int clks_num;
+	struct phy *phy;
+	struct reset_control *reset;
+
+	const struct rkcif_csi_format *formats;
+	unsigned int formats_num;
+
+	struct media_pad pads[RKCIF_CSI_PAD_MAX];
+	struct v4l2_async_notifier notifier;
+	struct v4l2_fwnode_endpoint vep;
+	struct v4l2_subdev sd;
+
+	struct v4l2_subdev *source_sd;
+	u32 source_pad;
+};
+
+const struct v4l2_mbus_framefmt default_format = {
+	.width = 3840,
+	.height = 2160,
+	.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_RAW,
+	.ycbcr_enc = V4L2_YCBCR_ENC_601,
+	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
+	.xfer_func = V4L2_XFER_FUNC_NONE,
+};
+
+static const struct rkcif_csi_format formats[] = {
+	/* YUV formats */
+	{
+		.code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_YVYU8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	/* RGB formats */
+	{
+		.code = MEDIA_BUS_FMT_RGB888_1X24,
+		.depth = 24,
+		.csi_dt = MIPI_CSI2_DT_RGB888,
+	},
+	{
+		.code = MEDIA_BUS_FMT_BGR888_1X24,
+		.depth = 24,
+		.csi_dt = MIPI_CSI2_DT_RGB888,
+	},
+	/* Bayer formats */
+	{
+		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+};
+
+static inline struct rkcif_csi_device *to_rkcif_csi(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct rkcif_csi_device, sd);
+}
+
+static inline __maybe_unused void
+rkcif_csi_write(struct rkcif_csi_device *csi_dev, unsigned int addr, u32 val)
+{
+	writel(val, csi_dev->base_addr + addr);
+}
+
+static inline __maybe_unused u32
+rkcif_csi_read(struct rkcif_csi_device *csi_dev, unsigned int addr)
+{
+	return readl(csi_dev->base_addr + addr);
+}
+
+static const struct rkcif_csi_format *
+rkcif_csi_find_format(struct rkcif_csi_device *csi_dev, u32 mbus_code)
+{
+	const struct rkcif_csi_format *format;
+
+	WARN_ON(csi_dev->formats_num == 0);
+
+	for (int i = 0; i < csi_dev->formats_num; i++) {
+		format = &csi_dev->formats[i];
+		if (format->code == mbus_code)
+			return format;
+	}
+
+	return NULL;
+}
+
+static int rkcif_csi_start(struct rkcif_csi_device *csi_dev)
+{
+	enum v4l2_mbus_type bus_type = csi_dev->vep.bus_type;
+	union phy_configure_opts opts;
+	s64 link_freq;
+	u32 lanes = csi_dev->vep.bus.mipi_csi2.num_data_lanes;
+	u32 control = 0;
+
+	if (lanes < 1 || lanes > 4)
+		return -EINVAL;
+
+	/* set mult and div to 0, thus completely rely on V4L2_CID_LINK_FREQ */
+	link_freq = v4l2_get_link_freq(csi_dev->source_sd->ctrl_handler, 0, 0);
+	if (link_freq <= 0)
+		return -EINVAL;
+
+	if (bus_type == V4L2_MBUS_CSI2_DPHY) {
+		struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+
+		phy_mipi_dphy_get_default_config_for_hsclk(link_freq * 2, lanes,
+							   cfg);
+		phy_set_mode(csi_dev->phy, PHY_MODE_MIPI_DPHY);
+		phy_configure(csi_dev->phy, &opts);
+
+		control |= SW_CPHY_EN(0);
+
+	} else if (bus_type == V4L2_MBUS_CSI2_CPHY) {
+		control |= SW_CPHY_EN(1);
+
+		/* TODO: implement CPHY configuration */
+	} else {
+		return -EINVAL;
+	}
+
+	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
+		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
+
+	rkcif_csi_write(csi_dev, CSI2HOST_N_LANES, lanes - 1);
+	rkcif_csi_write(csi_dev, CSI2HOST_CONTROL, control);
+	rkcif_csi_write(csi_dev, CSI2HOST_CSI2_RESETN, 1);
+
+	phy_power_on(csi_dev->phy);
+
+	return 0;
+}
+
+static void rkcif_csi_stop(struct rkcif_csi_device *csi_dev)
+{
+	phy_power_off(csi_dev->phy);
+
+	rkcif_csi_write(csi_dev, CSI2HOST_CSI2_RESETN, 0);
+	rkcif_csi_write(csi_dev, CSI2HOST_MSK1, ~0);
+	rkcif_csi_write(csi_dev, CSI2HOST_MSK2, ~0);
+}
+
+static const struct media_entity_operations rkcif_csi_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int rkcif_csi_enum_mbus_code(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_state *sd_state,
+				    struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct rkcif_csi_device *csi_dev = to_rkcif_csi(sd);
+
+	if (code->pad == RKCIF_CSI_PAD_SRC) {
+		const struct v4l2_mbus_framefmt *sink_fmt;
+
+		if (code->index)
+			return -EINVAL;
+
+		sink_fmt = v4l2_subdev_state_get_format(sd_state,
+							RKCIF_CSI_PAD_SINK);
+		code->code = sink_fmt->code;
+
+		return 0;
+	} else if (code->pad == RKCIF_CSI_PAD_SINK) {
+		if (code->index > csi_dev->formats_num)
+			return -EINVAL;
+
+		code->code = csi_dev->formats[code->index].code;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int rkcif_csi_set_fmt(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     struct v4l2_subdev_format *format)
+{
+	struct rkcif_csi_device *csi_dev = to_rkcif_csi(sd);
+	const struct rkcif_csi_format *fmt;
+	struct v4l2_mbus_framefmt *sink, *src;
+
+	/* the format on the source pad always matches the sink pad */
+	if (format->pad == RKCIF_CSI_PAD_SRC)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
+	if (!sink)
+		return -EINVAL;
+
+	fmt = rkcif_csi_find_format(csi_dev, format->format.code);
+	if (fmt)
+		*sink = format->format;
+	else
+		*sink = default_format;
+
+	/* propagate the format to the source pad */
+	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!src)
+		return -EINVAL;
+
+	*src = *sink;
+
+	return 0;
+}
+
+static int rkcif_csi_set_routing(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state,
+				 enum v4l2_subdev_format_whence which,
+				 struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing,
+					       &default_format);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int rkcif_csi_enable_streams(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_state *state, u32 pad,
+				    u64 streams_mask)
+{
+	struct rkcif_csi_device *csi_dev = to_rkcif_csi(sd);
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *sink_pad, *remote_pad;
+	struct device *dev = csi_dev->dev;
+	u64 mask;
+	int ret;
+
+	sink_pad = &sd->entity.pads[RKCIF_CSI_PAD_SINK];
+	remote_pad = media_pad_remote_pad_first(sink_pad);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_CSI_PAD_SINK,
+					       RKCIF_CSI_PAD_SRC,
+					       &streams_mask);
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		goto err;
+
+	ret = rkcif_csi_start(csi_dev);
+	if (ret) {
+		dev_err(dev, "failed to enable CSI hardware\n");
+		goto err_pm_runtime_put;
+	}
+
+	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
+	if (ret)
+		goto err_csi_stop;
+
+	return 0;
+
+err_csi_stop:
+	rkcif_csi_stop(csi_dev);
+err_pm_runtime_put:
+	pm_runtime_put_sync(dev);
+err:
+	return ret;
+}
+
+static int rkcif_csi_disable_streams(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_state *state, u32 pad,
+				     u64 streams_mask)
+{
+	struct rkcif_csi_device *csi_dev = to_rkcif_csi(sd);
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *sink_pad, *remote_pad;
+	struct device *dev = csi_dev->dev;
+	u64 mask;
+	int ret;
+
+	sink_pad = &sd->entity.pads[RKCIF_CSI_PAD_SINK];
+	remote_pad = media_pad_remote_pad_first(sink_pad);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_CSI_PAD_SINK,
+					       RKCIF_CSI_PAD_SRC,
+					       &streams_mask);
+
+	ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
+
+	rkcif_csi_stop(csi_dev);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_pad_ops rkcif_csi_pad_ops = {
+	.enum_mbus_code = rkcif_csi_enum_mbus_code,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = rkcif_csi_set_fmt,
+	.set_routing = rkcif_csi_set_routing,
+	.enable_streams = rkcif_csi_enable_streams,
+	.disable_streams = rkcif_csi_disable_streams,
+};
+
+static const struct v4l2_subdev_ops rkcif_csi_ops = {
+	.pad = &rkcif_csi_pad_ops,
+};
+
+static int rkcif_csi_init_state(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = RKCIF_CSI_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = RKCIF_CSI_PAD_SRC,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+	struct v4l2_subdev_krouting routing = {
+		.len_routes = ARRAY_SIZE(routes),
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+	int ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
+					       &default_format);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops rkcif_csi_internal_ops = {
+	.init_state = rkcif_csi_init_state,
+};
+
+static int rkcif_csi_notifier_bound(struct v4l2_async_notifier *notifier,
+				    struct v4l2_subdev *sd,
+				    struct v4l2_async_connection *asd)
+{
+	struct rkcif_csi_device *csi_dev =
+		container_of(notifier, struct rkcif_csi_device, notifier);
+	int source_pad;
+
+	source_pad = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode,
+						 MEDIA_PAD_FL_SOURCE);
+	if (source_pad < 0) {
+		dev_err(csi_dev->dev, "failed to find source pad for %s\n",
+			sd->name);
+		return source_pad;
+	}
+
+	csi_dev->source_sd = sd;
+	csi_dev->source_pad = source_pad;
+
+	return media_create_pad_link(&sd->entity, source_pad,
+				     &csi_dev->sd.entity, RKCIF_CSI_PAD_SINK,
+				     MEDIA_LNK_FL_ENABLED);
+}
+
+static const struct v4l2_async_notifier_operations rkcif_csi_notifier_ops = {
+	.bound = rkcif_csi_notifier_bound,
+};
+
+static int rkcif_register_notifier(struct rkcif_csi_device *csi_dev)
+{
+	struct v4l2_async_connection *asd;
+	struct v4l2_async_notifier *ntf = &csi_dev->notifier;
+	struct v4l2_fwnode_endpoint *vep = &csi_dev->vep;
+	struct v4l2_subdev *sd = &csi_dev->sd;
+	struct device *dev = csi_dev->dev;
+	struct fwnode_handle *ep;
+	int ret;
+
+	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
+	if (!ep)
+		return dev_err_probe(dev, -ENODEV, "failed to get endpoint\n");
+
+	vep->bus_type = V4L2_MBUS_UNKNOWN;
+	ret = v4l2_fwnode_endpoint_parse(ep, vep);
+	if (ret) {
+		ret = dev_err_probe(dev, ret, "failed to parse endpoint\n");
+		goto out;
+	}
+
+	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY &&
+	    vep->bus_type != V4L2_MBUS_CSI2_CPHY) {
+		ret = dev_err_probe(dev, -EINVAL,
+				    "invalid bus type of endpoint\n");
+		goto out;
+	}
+
+	v4l2_async_subdev_nf_init(ntf, sd);
+	ntf->ops = &rkcif_csi_notifier_ops;
+
+	asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
+					      struct v4l2_async_connection);
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
+		goto out;
+	}
+
+	ret = v4l2_async_nf_register(ntf);
+	if (ret) {
+		ret = dev_err_probe(dev, ret, "failed to register notifier\n");
+		v4l2_async_nf_cleanup(ntf);
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	fwnode_handle_put(ep);
+	return ret;
+}
+
+static int rkcif_csi_register(struct rkcif_csi_device *csi_dev)
+{
+	struct media_pad *pads = csi_dev->pads;
+	struct v4l2_subdev *sd = &csi_dev->sd;
+	int ret;
+
+	ret = rkcif_register_notifier(csi_dev);
+	if (ret)
+		goto err;
+
+	v4l2_subdev_init(sd, &rkcif_csi_ops);
+	sd->dev = csi_dev->dev;
+	sd->entity.ops = &rkcif_csi_media_ops;
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+	sd->internal_ops = &rkcif_csi_internal_ops;
+	sd->owner = THIS_MODULE;
+	snprintf(sd->name, sizeof(sd->name), "rockchip-mipi-csi %s",
+		 dev_name(csi_dev->dev));
+
+	pads[RKCIF_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
+					 MEDIA_PAD_FL_MUST_CONNECT;
+	pads[RKCIF_CSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE |
+					MEDIA_PAD_FL_MUST_CONNECT;
+	ret = media_entity_pads_init(&sd->entity, RKCIF_CSI_PAD_MAX, pads);
+	if (ret)
+		goto err_notifier_unregister;
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret)
+		goto err_entity_cleanup;
+
+	ret = v4l2_async_register_subdev(sd);
+	if (ret) {
+		dev_err(sd->dev, "failed to register CSI subdev\n");
+		goto err_subdev_cleanup;
+	}
+
+	return 0;
+
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(sd);
+err_entity_cleanup:
+	media_entity_cleanup(&sd->entity);
+err_notifier_unregister:
+	v4l2_async_nf_unregister(&csi_dev->notifier);
+	v4l2_async_nf_cleanup(&csi_dev->notifier);
+err:
+	return ret;
+}
+
+static void rkcif_csi_unregister(struct rkcif_csi_device *csi_dev)
+{
+	struct v4l2_subdev *sd = &csi_dev->sd;
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_subdev_cleanup(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_async_nf_unregister(&csi_dev->notifier);
+	v4l2_async_nf_cleanup(&csi_dev->notifier);
+}
+
+static const struct of_device_id rkcif_csi_of_match[] = {
+	{
+		.compatible = "rockchip,rk3568-mipi-csi",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, rkcif_csi_of_match);
+
+static int rkcif_csi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rkcif_csi_device *csi_dev;
+	int ret;
+
+	csi_dev = devm_kzalloc(dev, sizeof(*csi_dev), GFP_KERNEL);
+	if (!csi_dev)
+		return -ENOMEM;
+	csi_dev->dev = dev;
+	dev_set_drvdata(dev, csi_dev);
+
+	csi_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(csi_dev->base_addr))
+		return PTR_ERR(csi_dev->base_addr);
+
+	ret = devm_clk_bulk_get_all(dev, &csi_dev->clks);
+	if (ret != RKCIF_CSI_CLKS_MAX)
+		return dev_err_probe(dev, ret, "failed to get clocks\n");
+	csi_dev->clks_num = ret;
+
+	csi_dev->phy = devm_phy_get(dev, NULL);
+	if (IS_ERR(csi_dev->phy))
+		return dev_err_probe(dev, PTR_ERR(csi_dev->phy),
+				     "failed to get MIPI CSI PHY\n");
+
+	csi_dev->reset = devm_reset_control_array_get_exclusive(dev);
+	if (IS_ERR(csi_dev->reset))
+		return dev_err_probe(dev, PTR_ERR(csi_dev->reset),
+				     "failed to get reset\n");
+
+	csi_dev->formats = formats;
+	csi_dev->formats_num = ARRAY_SIZE(formats);
+
+	pm_runtime_enable(dev);
+
+	ret = phy_init(csi_dev->phy);
+	if (ret) {
+		ret = dev_err_probe(dev, ret,
+				    "failed to initialize MIPI CSI PHY\n");
+		goto err_pm_runtime_disable;
+	}
+
+	ret = rkcif_csi_register(csi_dev);
+	if (ret)
+		goto err_phy_exit;
+
+	return 0;
+
+err_phy_exit:
+	phy_exit(csi_dev->phy);
+err_pm_runtime_disable:
+	pm_runtime_disable(dev);
+	return ret;
+}
+
+static void rkcif_csi_remove(struct platform_device *pdev)
+{
+	struct rkcif_csi_device *csi_dev = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	rkcif_csi_unregister(csi_dev);
+	phy_exit(csi_dev->phy);
+	pm_runtime_disable(dev);
+}
+
+static int rkcif_csi_runtime_suspend(struct device *dev)
+{
+	struct rkcif_csi_device *csi_dev = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(csi_dev->clks_num, csi_dev->clks);
+
+	return 0;
+}
+
+static int rkcif_csi_runtime_resume(struct device *dev)
+{
+	struct rkcif_csi_device *csi_dev = dev_get_drvdata(dev);
+	int ret;
+
+	reset_control_assert(csi_dev->reset);
+	udelay(5);
+	reset_control_deassert(csi_dev->reset);
+
+	ret = clk_bulk_prepare_enable(csi_dev->clks_num, csi_dev->clks);
+	if (ret) {
+		dev_err(dev, "failed to enable clocks\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops rkcif_csi_pm_ops = {
+	.runtime_suspend = rkcif_csi_runtime_suspend,
+	.runtime_resume = rkcif_csi_runtime_resume,
+};
+
+static struct platform_driver rkcif_csi_drv = {
+	.driver = {
+		   .name = "rockchip-mipi-csi",
+		   .of_match_table = rkcif_csi_of_match,
+		   .pm = &rkcif_csi_pm_ops,
+	},
+	.probe = rkcif_csi_probe,
+	.remove = rkcif_csi_remove,
+};
+module_platform_driver(rkcif_csi_drv);
+
+MODULE_DESCRIPTION("Rockchip MIPI CSI-2 Host platform driver");
+MODULE_LICENSE("GPL");

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:08 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:08 +0100
Subject: [PATCH v5 07/11] media: rockchip: rkcif: add support for mipi
 csi-2 receiver
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-7-f02152534f3c@wolfvision.net>

The RK3568 Video Capture (VICAP) unit features a MIPI CSI-2 receiver
that can receive video data and write it into system memory using the
ping-pong scheme. Add support for it.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../platform/rockchip/rkcif/rkcif-capture-mipi.c   | 695 +++++++++++++++++++++
 .../platform/rockchip/rkcif/rkcif-capture-mipi.h   |   2 +
 .../media/platform/rockchip/rkcif/rkcif-common.h   |  16 +
 drivers/media/platform/rockchip/rkcif/rkcif-dev.c  |   1 +
 .../platform/rockchip/rkcif/rkcif-interface.c      |   5 +-
 drivers/media/platform/rockchip/rkcif/rkcif-regs.h |  24 +-
 6 files changed, 741 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
index 0c3f7b8cfa18..dcc0c4aeeec4 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
@@ -6,22 +6,717 @@
  * Copyright (C) 2025 Michael Riesch <michael.riesch at wolfvision.net>
  */
 
+#include <linux/interrupt.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
 #include "rkcif-capture-mipi.h"
 #include "rkcif-common.h"
+#include "rkcif-interface.h"
+#include "rkcif-regs.h"
 #include "rkcif-stream.h"
 
+#define RKCIF_MIPI_CTRL0_COMPACT_EN    BIT(6)
+#define RKCIF_MIPI_CTRL0_CROP_EN       BIT(5)
+#define RKCIF_MIPI_CTRL0_TYPE(type)    ((type) << 1)
+#define RKCIF_MIPI_CTRL0_TYPE_RAW8     RKCIF_MIPI_CTRL0_TYPE(0x0)
+#define RKCIF_MIPI_CTRL0_TYPE_RAW10    RKCIF_MIPI_CTRL0_TYPE(0x1)
+#define RKCIF_MIPI_CTRL0_TYPE_RAW12    RKCIF_MIPI_CTRL0_TYPE(0x2)
+#define RKCIF_MIPI_CTRL0_TYPE_RGB888   RKCIF_MIPI_CTRL0_TYPE(0x3)
+#define RKCIF_MIPI_CTRL0_TYPE_YUV422SP RKCIF_MIPI_CTRL0_TYPE(0x4)
+#define RKCIF_MIPI_CTRL0_TYPE_YUV420SP RKCIF_MIPI_CTRL0_TYPE(0x5)
+#define RKCIF_MIPI_CTRL0_TYPE_YUV400   RKCIF_MIPI_CTRL0_TYPE(0x6)
+#define RKCIF_MIPI_CTRL0_CAP_EN	       BIT(0)
+
+#define RKCIF_MIPI_INT_FRAME0_END(id)  BIT(8 + (id) * 2 + 0)
+#define RKCIF_MIPI_INT_FRAME1_END(id)  BIT(8 + (id) * 2 + 1)
+
+static const struct rkcif_output_fmt mipi_out_fmts[] = {
+	/* YUV formats */
+	{
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.depth = 16,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_YUV422_8B,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.depth = 16,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_YUV422_8B,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YVYU,
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
+		.depth = 16,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_YUV422_8B,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VYUY,
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.depth = 16,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_YUV422_8B,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	/* RGB formats */
+	{
+		.fourcc = V4L2_PIX_FMT_RGB24,
+		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
+		.depth = 24,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RGB888,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_BGR24,
+		.mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
+		.depth = 24,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RGB888,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888,
+		},
+	},
+	/* Bayer formats */
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR8,
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.depth = 8,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW8,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG8,
+		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.depth = 8,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW8,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG8,
+		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.depth = 8,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW8,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB8,
+		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.depth = 8,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW8,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR10,
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR10P,
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG10,
+		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG10P,
+		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG10,
+		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG10P,
+		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB10,
+		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB10P,
+		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.depth = 10,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW10,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR12,
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SBGGR12P,
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG12,
+		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGBRG12P,
+		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG12,
+		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SGRBG12P,
+		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB12,
+		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12,
+		},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_SRGGB12P,
+		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.depth = 12,
+		.cplanes = 1,
+		.mipi = {
+			.dt = MIPI_CSI2_DT_RAW12,
+			.ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN,
+		},
+	},
+};
+
+static const struct rkcif_input_fmt mipi_in_fmts[] = {
+	/* YUV formats */
+	{
+		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
+	},
+	/* RGB formats */
+	{
+		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
+	},
+	/* Bayer formats */
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+	},
+	{
+		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
+	},
+};
+
+const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data = {
+	.mipi_num = 1,
+	.regs = {
+		[RKCIF_MIPI_CTRL] = 0x20,
+		[RKCIF_MIPI_INTEN] = 0xa4,
+		[RKCIF_MIPI_INTSTAT] = 0xa8,
+	},
+	.regs_id = {
+		[RKCIF_ID0] = {
+			[RKCIF_MIPI_CTRL0] = 0x00,
+			[RKCIF_MIPI_CTRL1] = 0x04,
+			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24,
+			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c,
+			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x34,
+			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x3c,
+			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28,
+			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30,
+			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x38,
+			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x40,
+			[RKCIF_MIPI_CROP_START] = 0xbc,
+		},
+		[RKCIF_ID1] = {
+			[RKCIF_MIPI_CTRL0] = 0x08,
+			[RKCIF_MIPI_CTRL1] = 0x0c,
+			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x44,
+			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x4c,
+			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x54,
+			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x5c,
+			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x48,
+			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x50,
+			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x58,
+			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x60,
+			[RKCIF_MIPI_CROP_START] = 0xc0,
+		},
+		[RKCIF_ID2] = {
+			[RKCIF_MIPI_CTRL0] = 0x10,
+			[RKCIF_MIPI_CTRL1] = 0x14,
+			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x64,
+			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x6c,
+			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x74,
+			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x7c,
+			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x68,
+			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x70,
+			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x78,
+			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x80,
+			[RKCIF_MIPI_CROP_START] = 0xc4,
+		},
+		[RKCIF_ID3] = {
+			[RKCIF_MIPI_CTRL0] = 0x18,
+			[RKCIF_MIPI_CTRL1] = 0x1c,
+			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x84,
+			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x8c,
+			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x94,
+			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x9c,
+			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x88,
+			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x90,
+			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x98,
+			[RKCIF_MIPI_FRAME1_VLW_UV] = 0xa0,
+			[RKCIF_MIPI_CROP_START] = 0xc8,
+		},
+	},
+	.blocks = {
+		{
+			.offset = 0x80,
+		},
+	},
+};
+
+static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface,
+					      unsigned int index)
+{
+	struct rkcif_device *rkcif = interface->rkcif;
+	unsigned int block, offset, reg;
+
+	block = interface->index - RKCIF_MIPI_BASE;
+
+	if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
+	    WARN_ON(index > RKCIF_MIPI_REGISTER_MAX))
+		return RKCIF_REGISTER_NOTSUPPORTED;
+
+	offset = rkcif->match_data->mipi->blocks[block].offset;
+	reg = rkcif->match_data->mipi->regs[index];
+	if (reg == RKCIF_REGISTER_NOTSUPPORTED)
+		return reg;
+
+	return offset + reg;
+}
+
+static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream,
+						 unsigned int index)
+{
+	struct rkcif_device *rkcif = stream->rkcif;
+	unsigned int block, id, offset, reg;
+
+	block = stream->interface->index - RKCIF_MIPI_BASE;
+	id = stream->id;
+
+	if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
+	    WARN_ON(id > RKCIF_ID_MAX) ||
+	    WARN_ON(index > RKCIF_MIPI_ID_REGISTER_MAX))
+		return RKCIF_REGISTER_NOTSUPPORTED;
+
+	offset = rkcif->match_data->mipi->blocks[block].offset;
+	reg = rkcif->match_data->mipi->regs_id[id][index];
+	if (reg == RKCIF_REGISTER_NOTSUPPORTED)
+		return reg;
+
+	return offset + reg;
+}
+
+static inline __maybe_unused void
+rkcif_mipi_write(struct rkcif_interface *interface, unsigned int index, u32 val)
+{
+	unsigned int addr = rkcif_mipi_get_reg(interface, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return;
+
+	writel(val, interface->rkcif->base_addr + addr);
+}
+
+static inline __maybe_unused void
+rkcif_mipi_stream_write(struct rkcif_stream *stream, unsigned int index,
+			u32 val)
+{
+	unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return;
+
+	writel(val, stream->rkcif->base_addr + addr);
+}
+
+static inline __maybe_unused u32
+rkcif_mipi_read(struct rkcif_interface *interface, unsigned int index)
+{
+	unsigned int addr = rkcif_mipi_get_reg(interface, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return 0;
+
+	return readl(interface->rkcif->base_addr + addr);
+}
+
+static inline __maybe_unused u32
+rkcif_mipi_stream_read(struct rkcif_stream *stream, unsigned int index)
+{
+	unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
+
+	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
+		return 0;
+
+	return readl(stream->rkcif->base_addr + addr);
+}
+
+static void rkcif_mipi_queue_buffer(struct rkcif_stream *stream,
+				    unsigned int index)
+{
+	struct rkcif_buffer *buffer = stream->buffers[index];
+	u32 frm_addr_y, frm_addr_uv;
+
+	frm_addr_y = index ? RKCIF_MIPI_FRAME1_ADDR_Y :
+			     RKCIF_MIPI_FRAME0_ADDR_Y;
+	frm_addr_uv = index ? RKCIF_MIPI_FRAME1_ADDR_UV :
+			      RKCIF_MIPI_FRAME0_ADDR_UV;
+
+	rkcif_mipi_stream_write(stream, frm_addr_y,
+				buffer->buff_addr[RKCIF_PLANE_Y]);
+	rkcif_mipi_stream_write(stream, frm_addr_uv,
+				buffer->buff_addr[RKCIF_PLANE_UV]);
+}
+
+static int rkcif_mipi_start_streaming(struct rkcif_stream *stream)
+{
+	struct rkcif_interface *interface = stream->interface;
+	const struct rkcif_output_fmt *active_out_fmt;
+	struct v4l2_subdev_state *state;
+	u32 ctrl0 = 0, ctrl1 = 0, int_temp = 0, int_mask = 0, vlw = 0;
+	u16 height, width;
+	int ret = -EINVAL;
+
+	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
+
+	active_out_fmt = rkcif_stream_find_output_fmt(stream, false,
+						      stream->pix.pixelformat);
+	if (!active_out_fmt)
+		goto out;
+
+	height = stream->pix.height;
+	width = stream->pix.width;
+	/* TODO there may be different factors and/or alignment constraints */
+	vlw = ALIGN(width * 2, 8);
+
+	ctrl0 |= active_out_fmt->mipi.dt << 10;
+	ctrl0 |= active_out_fmt->mipi.ctrl0_val;
+	ctrl0 |= RKCIF_MIPI_CTRL0_CROP_EN;
+	ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN;
+
+	ctrl1 = RKCIF_XY_COORD(width, height);
+
+	int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
+	int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
+
+	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
+	int_temp |= int_mask;
+	rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
+
+	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
+	int_temp &= ~int_mask;
+	rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
+
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_Y, vlw);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_Y, vlw);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_UV, vlw);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_UV, vlw);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, 0x0);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0);
+
+	ret = 0;
+
+out:
+	v4l2_subdev_unlock_state(state);
+	return ret;
+}
+
+static void rkcif_mipi_stop_streaming(struct rkcif_stream *stream)
+{
+	struct rkcif_interface *interface = stream->interface;
+	struct v4l2_subdev_state *state;
+	u32 int_temp = 0, int_mask = 0;
+
+	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
+
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, 0);
+
+	int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
+	int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
+
+	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
+	int_temp &= ~int_mask;
+	rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
+
+	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
+	int_temp &= ~int_mask;
+	rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
+
+	stream->stopping = false;
+
+	v4l2_subdev_unlock_state(state);
+}
+
+static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
+{
+	u32 val;
+
+	val = RKCIF_XY_COORD(left, top);
+	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val);
+}
+
 irqreturn_t rkcif_mipi_isr(int irq, void *ctx)
 {
+	struct device *dev = ctx;
+	struct rkcif_device *rkcif = dev_get_drvdata(dev);
 	irqreturn_t ret = IRQ_NONE;
+	u32 intstat;
+
+	for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
+		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
+		struct rkcif_interface *interface = &rkcif->interfaces[index];
+
+		intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
+		rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat);
+
+		for (int j = 0; j < interface->streams_num; j++) {
+			struct rkcif_stream *stream = &interface->streams[j];
+
+			if (intstat & RKCIF_MIPI_INT_FRAME0_END(stream->id) ||
+			    intstat & RKCIF_MIPI_INT_FRAME1_END(stream->id)) {
+				rkcif_stream_pingpong(stream);
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
 
 	return ret;
 }
 
 int rkcif_mipi_register(struct rkcif_device *rkcif)
 {
+	int ret, i;
+
+	if (!rkcif->match_data->mipi)
+		return 0;
+
+	for (i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
+		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
+		struct rkcif_interface *interface = &rkcif->interfaces[index];
+
+		interface->index = index;
+		interface->type = RKCIF_IF_MIPI;
+		interface->in_fmts = mipi_in_fmts;
+		interface->in_fmts_num = ARRAY_SIZE(mipi_in_fmts);
+		interface->set_crop = rkcif_mipi_set_crop;
+		interface->streams_num = 0;
+		ret = rkcif_interface_register(rkcif, interface);
+		if (ret)
+			continue;
+
+		for (int j = 0; j < 4; j++) {
+			struct rkcif_stream *stream = &interface->streams[j];
+
+			stream->id = j;
+			stream->interface = interface;
+			stream->out_fmts = mipi_out_fmts;
+			stream->out_fmts_num = ARRAY_SIZE(mipi_out_fmts);
+			stream->queue_buffer = rkcif_mipi_queue_buffer;
+			stream->start_streaming = rkcif_mipi_start_streaming;
+			stream->stop_streaming = rkcif_mipi_stop_streaming;
+			ret = rkcif_stream_register(rkcif, stream);
+			if (ret)
+				goto err;
+			interface->streams_num++;
+		}
+	}
+
 	return 0;
+
+err:
+	for (; i >= 0; i--) {
+		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
+		struct rkcif_interface *interface = &rkcif->interfaces[index];
+
+		for (int j = 0; j < interface->streams_num; j++)
+			rkcif_stream_unregister(&interface->streams[j]);
+
+		rkcif_interface_unregister(interface);
+	}
+	return ret;
 }
 
 void rkcif_mipi_unregister(struct rkcif_device *rkcif)
 {
+	if (!rkcif->match_data->mipi)
+		return;
+
+	for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
+		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
+		struct rkcif_interface *interface = &rkcif->interfaces[index];
+
+		for (int j = 0; j < interface->streams_num; j++)
+			rkcif_stream_unregister(&interface->streams[j]);
+
+		rkcif_interface_unregister(interface);
+	}
 }
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
index ee1a50a59505..48d04a60c750 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
@@ -11,6 +11,8 @@
 
 #include "rkcif-common.h"
 
+extern const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data;
+
 int rkcif_mipi_register(struct rkcif_device *rkcif);
 
 void rkcif_mipi_unregister(struct rkcif_device *rkcif);
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-common.h b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
index 32f6f0238656..99249a85048e 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-common.h
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-common.h
@@ -93,9 +93,14 @@ struct rkcif_output_fmt {
 	u32 fourcc;
 	u32 mbus_code;
 	u8 cplanes;
+	u8 depth;
 
 	union {
 		u32 dvp_fmt_val;
+		struct {
+			u8 dt;
+			u32 ctrl0_val;
+		} mipi;
 	};
 };
 
@@ -183,6 +188,16 @@ struct rkcif_interface {
 	void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
 };
 
+struct rkcif_mipi_match_data {
+	unsigned int mipi_num;
+	unsigned int regs[RKCIF_MIPI_REGISTER_MAX];
+	unsigned int regs_id[RKCIF_ID_MAX][RKCIF_MIPI_ID_REGISTER_MAX];
+
+	struct {
+		unsigned int offset;
+	} blocks[RKCIF_MIPI_MAX - RKCIF_MIPI_BASE];
+};
+
 struct rkcif_dvp_match_data {
 	const struct rkcif_input_fmt *in_fmts;
 	unsigned int in_fmts_num;
@@ -198,6 +213,7 @@ struct rkcif_match_data {
 	const char *const *clks;
 	unsigned int clks_num;
 	const struct rkcif_dvp_match_data *dvp;
+	const struct rkcif_mipi_match_data *mipi;
 };
 
 struct rkcif_device {
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
index 2f45229183f6..5cc4e458ffa1 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
@@ -49,6 +49,7 @@ static const struct rkcif_match_data rk3568_vicap_match_data = {
 	.clks = rk3568_vicap_clks,
 	.clks_num = ARRAY_SIZE(rk3568_vicap_clks),
 	.dvp = &rk3568_vicap_dvp_match_data,
+	.mipi = &rk3568_vicap_mipi_match_data,
 };
 
 static const struct of_device_id rkcif_plat_of_match[] = {
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
index 7131de68de2c..163ee9e2fc6f 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c
@@ -188,7 +188,10 @@ static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
 		stream = &interface->streams[RKCIF_ID0];
 		rkcif_interface_apply_crop(stream, state);
 	} else {
-		/* TODO implement for MIPI */
+		for_each_active_route(&state->routing, route) {
+			stream = &interface->streams[route->sink_stream];
+			rkcif_interface_apply_crop(stream, state);
+		}
 	}
 
 	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
index 07fd64174e80..3d1f0c45c638 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h
@@ -30,7 +30,29 @@ enum rkcif_dvp_register_index {
 	RKCIF_DVP_REGISTER_MAX
 };
 
-#define RKCIF_REGISTER_NOTSUPPORTED           0x420000
+enum rkcif_mipi_register_index {
+	RKCIF_MIPI_CTRL,
+	RKCIF_MIPI_INTEN,
+	RKCIF_MIPI_INTSTAT,
+	RKCIF_MIPI_REGISTER_MAX
+};
+
+enum rkcif_mipi_id_register_index {
+	RKCIF_MIPI_CTRL0,
+	RKCIF_MIPI_CTRL1,
+	RKCIF_MIPI_FRAME0_ADDR_Y,
+	RKCIF_MIPI_FRAME0_ADDR_UV,
+	RKCIF_MIPI_FRAME0_VLW_Y,
+	RKCIF_MIPI_FRAME0_VLW_UV,
+	RKCIF_MIPI_FRAME1_ADDR_Y,
+	RKCIF_MIPI_FRAME1_ADDR_UV,
+	RKCIF_MIPI_FRAME1_VLW_Y,
+	RKCIF_MIPI_FRAME1_VLW_UV,
+	RKCIF_MIPI_CROP_START,
+	RKCIF_MIPI_ID_REGISTER_MAX
+};
+
+#define RKCIF_REGISTER_NOTSUPPORTED	       0x420000
 
 #define RKCIF_FETCH_Y(VAL)		       ((VAL) & 0x1fff)
 

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:09 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:09 +0100
Subject: [PATCH v5 08/11] arm64: dts: rockchip: add the vip node to px30
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-8-f02152534f3c@wolfvision.net>

From: Mehdi Djait <mehdi.djait at bootlin.com>

Add the device tree node for the PX30 Video Input Processor (VIP).

Signed-off-by: Mehdi Djait <mehdi.djait at bootlin.com>
[added cosmetic changes]
Reviewed-by: Michael Riesch <michael.riesch at wolfvision.net>
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm64/boot/dts/rockchip/px30.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi
index 9137dd76e72c..c2acf5952d08 100644
--- a/arch/arm64/boot/dts/rockchip/px30.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30.dtsi
@@ -1282,6 +1282,18 @@ isp_mmu: iommu at ff4a8000 {
 		#iommu-cells = <0>;
 	};
 
+	cif: video-capture at ff490000 {
+		compatible = "rockchip,px30-vip";
+		reg = <0x0 0xff490000 0x0 0x200>;
+		interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_CIF>, <&cru HCLK_CIF>, <&cru PCLK_CIF>;
+		clock-names = "aclk", "hclk", "pclk";
+		power-domains = <&power PX30_PD_VI>;
+		resets = <&cru SRST_CIF_A>, <&cru SRST_CIF_H>, <&cru SRST_CIF_PCLKIN>;
+		reset-names = "axi", "ahb", "pclkin";
+		status = "disabled";
+	};
+
 	qos_gmac: qos at ff518000 {
 		compatible = "rockchip,px30-qos", "syscon";
 		reg = <0x0 0xff518000 0x0 0x20>;

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:10 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:10 +0100
Subject: [PATCH v5 09/11] arm64: dts: rockchip: add vicap node to rk356x
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-9-f02152534f3c@wolfvision.net>

Add the device tree node for the RK356x Video Capture (VICAP) unit.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 44 +++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
index e55390629114..cba5092dbcea 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
@@ -553,6 +553,50 @@ gpu: gpu at fde60000 {
 		status = "disabled";
 	};
 
+	vicap: video-capture at fdfe0000 {
+		compatible = "rockchip,rk3568-vicap";
+		reg = <0x0 0xfdfe0000 0x0 0x200>;
+		interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+		assigned-clocks = <&cru DCLK_VICAP>;
+		assigned-clock-rates = <300000000>;
+		clocks = <&cru ACLK_VICAP>, <&cru HCLK_VICAP>,
+			 <&cru DCLK_VICAP>, <&cru ICLK_VICAP_G>;
+		clock-names = "aclk", "hclk", "dclk", "iclk";
+		iommus = <&vicap_mmu>;
+		power-domains = <&power RK3568_PD_VI>;
+		resets = <&cru SRST_A_VICAP>, <&cru SRST_H_VICAP>,
+			 <&cru SRST_D_VICAP>, <&cru SRST_P_VICAP>,
+			 <&cru SRST_I_VICAP>;
+		reset-names = "arst", "hrst", "drst", "prst", "irst";
+		rockchip,grf = <&grf>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vicap_dvp: port at 0 {
+				reg = <0>;
+			};
+
+			vicap_mipi: port at 1 {
+				reg = <1>;
+			};
+		};
+	};
+
+	vicap_mmu: iommu at fdfe0800 {
+		compatible = "rockchip,rk3568-iommu";
+		reg = <0x0 0xfdfe0800 0x0 0x100>;
+		interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VICAP>, <&cru HCLK_VICAP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		power-domains = <&power RK3568_PD_VI>;
+		rockchip,disable-mmu-reset;
+		status = "disabled";
+	};
+
 	vpu: video-codec at fdea0400 {
 		compatible = "rockchip,rk3568-vpu";
 		reg = <0x0 0xfdea0000 0x0 0x800>;

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:11 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:11 +0100
Subject: [PATCH v5 10/11] arm64: dts: rockchip: add mipi csi host node to
 rk356x
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-10-f02152534f3c@wolfvision.net>

Add the device tree node for the RK356x MIPI CSI-2 Host unit.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 31 +++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
index cba5092dbcea..da56a40e2aee 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
@@ -553,6 +553,33 @@ gpu: gpu at fde60000 {
 		status = "disabled";
 	};
 
+	csi: csi at fdfb0000 {
+		compatible = "rockchip,rk3568-mipi-csi";
+		reg = <0x0 0xfdfb0000 0x0 0x10000>;
+		clocks = <&cru PCLK_CSI2HOST1>;
+		phys = <&csi_dphy>;
+		power-domains = <&power RK3568_PD_VI>;
+		resets = <&cru SRST_P_CSI2HOST1>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			csi_in: port at 0 {
+				reg = <0>;
+			};
+
+			csi_out: port at 1 {
+				reg = <1>;
+
+				csi_output: endpoint {
+					remote-endpoint = <&vicap_mipi_input>;
+				};
+			};
+		};
+	};
+
 	vicap: video-capture at fdfe0000 {
 		compatible = "rockchip,rk3568-vicap";
 		reg = <0x0 0xfdfe0000 0x0 0x200>;
@@ -581,6 +608,10 @@ vicap_dvp: port at 0 {
 
 			vicap_mipi: port at 1 {
 				reg = <1>;
+
+				vicap_mipi_input: endpoint {
+					remote-endpoint = <&csi_output>;
+				};
 			};
 		};
 	};

-- 
2.34.1



From michael.riesch at wolfvision.net  Thu Mar  6 08:56:12 2025
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Thu, 06 Mar 2025 17:56:12 +0100
Subject: [PATCH v5 11/11] arm64: dts: rockchip: enable vicap dvp on
 wolfvision pf5 io expander
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
Message-ID: <20250306-v6-8-topic-rk3568-vicap-v5-11-f02152534f3c@wolfvision.net>

The Digital Video Port (DVP, the 16-bit variant) of the RK3568 VICAP
is broken out to the PF5 mainboard expansion header.
Enable it in the device tree overlay for the WolfVision PF5 IO
Expander board.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../rockchip/rk3568-wolfvision-pf5-io-expander.dtso  | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
index 048933de2943..411b06b534f8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
+++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
@@ -11,6 +11,7 @@
 #include <dt-bindings/clock/rk3568-cru.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/media/video-interfaces.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 
 &{/} {
@@ -134,3 +135,22 @@ &usb2phy0_host {
 	phy-supply = <&usb_host_vbus>;
 	status = "okay";
 };
+
+&vicap {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cif_clk &cif_dvp_clk &cif_dvp_bus16>;
+	rockchip,cif-clk-delaynum = <10>;
+	status = "okay";
+};
+
+&vicap_dvp {
+	vicap_dvp_input: endpoint {
+		bus-type = <MEDIA_BUS_TYPE_BT656>;
+		bus-width = <16>;
+		pclk-sample = <MEDIA_PCLK_SAMPLE_DUAL_EDGE>;
+	};
+};
+
+&vicap_mmu {
+	status = "okay";
+};

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar  6 09:09:37 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 12:09:37 -0500
Subject: [PATCH] dt-bindings: mmc: fsl-imx-esdhc: Add i.MX94 support
Message-ID: <20250306170937.242183-1-Frank.Li@nxp.com>

Add compatible string "fsl,imx94-usdhc" for the i.MX94 chip, which is
backward compatible with i.MX8mm. Set it to fall back to
"fsl,imx8mm-usdhc".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
index b9b9995705290..b98a84f932772 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
@@ -57,6 +57,7 @@ properties:
               - fsl,imx8mp-usdhc
               - fsl,imx8ulp-usdhc
               - fsl,imx93-usdhc
+              - fsl,imx94-usdhc
               - fsl,imx95-usdhc
           - const: fsl,imx8mm-usdhc
       - items:
-- 
2.34.1



From linux at roeck-us.net  Thu Mar  6 09:22:47 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 6 Mar 2025 09:22:47 -0800
Subject: [EXTERNAL] Re: [PATCH v4 1/2] watchdog: Add a new flag
 WDIOF_STOP_MAYSLEEP
In-Reply-To: <PH8PR18MB53812FCAE180303E5D434275C5CA2@PH8PR18MB5381.namprd18.prod.outlook.com>
References: <20250305101025.2279951-1-george.cherian@marvell.com>
 <20250305101025.2279951-2-george.cherian@marvell.com>
 <irmewriceyzxr6jvbiao5vqrvelpftbjalmheodx5w63zi6k2y@dg3wlvs6zryd>
 <PH8PR18MB538122CE6706872B8A836A94C5CB2@PH8PR18MB5381.namprd18.prod.outlook.com>
 <7ac2b8db-22c7-4168-b1b7-4f9f0ab10531@pengutronix.de>
 <28a711e5-b2cb-4d5f-bb78-259a01cd4bcc@roeck-us.net>
 <PH8PR18MB53812FCAE180303E5D434275C5CA2@PH8PR18MB5381.namprd18.prod.outlook.com>
Message-ID: <925869a6-7563-459b-b42b-b7b9b8ea0b0a@roeck-us.net>

On Thu, Mar 06, 2025 at 12:18:20PM +0000, George Cherian wrote:
> Hi Guenter,
> 
> I am summarizing the topics we discussed in multiple threads here.
> 
> >>On 3/5/25 03:01, Ahmad Fatoum wrote:
> >> Hi George,
> >> Hi Guenter,
> >> 
> >> On 05.03.25 11:34, George Cherian wrote:
> >>>> why is armada_37xx_wdt also here?
> >>>> The stop function in that driver may not sleep.
> >>> Marek,
> >>>
> >>> Thanks for reviewing.
> >>> Since the stop function has a regmap_write(), I thought it might sleep.
> >>> Now that you pointed it out, I assume that it is an MMIO based regmap being used for armada.
> >>> I will update the same in the next version
> >> 
> >> Failure to add WDIOF_STOP_MAYSLEEP when it's needed can lead to
> >> kernel hanging. Failure to add an alternative WDIOF_STOP_ATOMIC
> >> would lead to the kernel option being a no-op.
> >> 
> >> I think a no-op stop_on_panic (or reset_on_panic) is a saner default.
> >> 
> >
> >Agreed. Also, I like WDIOF_STOP_ATOMIC more than the WDIOF_STOP_NOSLEEP
> >I had suggested in my other response.
> 
> 1. Instead of blacklisting drivers as WDIOF_STOP_MAYSLEEP, the option will an opt-in.
> 2. This may not be WDIOF_STOP_AOMIC, instead would be a generic flag not limited to STOP
>     operation. May be WDIOF_OPS_ATOMIC (OPS include - .start, .stop, .set_timeout, .ping)

I don't see a value in this because AFAICS atomic operation is only needed when
stopping the watchdog. At least in theory, some watchdogs might need to sleep
for other functions, but not for the stop operation. Please provide a rationale.

> 3. Remove the kernel command line option (stop_on_panic) and have a generic reset_on_panic.
> 4. reset_on_panic=60 (by default )  meaning on a panic the wdog timeout is updated to 60sec
>      or the clamp_t(reset_on_panic, min, max_hw_heartbeat_ms).

Default should be the current behavior, that the watchdog keeps running with the
configured timeout.

> 5. if reset_on_panic=0, it means the watchdog is stopped on panic.

If we need both a panic timeout and the ability to disable the watchdog entirely
on panic, there should be two parameters - one to select the watchdog timeout
on panic, and one to disable the watchdog entirely on panic. If there is only
one parameter, it should be the watchdog timeout on panic, with ==0 meaning
"keep the configured timeout" (i.e., the current behavior).

Thanks,
Guenter


From luca.ceresoli at bootlin.com  Thu Mar  6 09:28:41 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 06 Mar 2025 18:28:41 +0100
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
Message-ID: <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>

This warning notifies a clock was set to an inaccurate value. Modify the
string to also show the clock name.

While doing that also rewrap the entire function call.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
 drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
--- a/drivers/gpu/drm/bridge/fsl-ldb.c
+++ b/drivers/gpu/drm/bridge/fsl-ldb.c
@@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
 
 	configured_link_freq = clk_get_rate(fsl_ldb->clk);
 	if (configured_link_freq != requested_link_freq)
-		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
-			 configured_link_freq,
-			 requested_link_freq);
+		dev_warn(fsl_ldb->dev,
+			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
+			 fsl_ldb->clk, configured_link_freq, requested_link_freq);
 
 	clk_prepare_enable(fsl_ldb->clk);
 

-- 
2.48.1



From luca.ceresoli at bootlin.com  Thu Mar  6 09:28:40 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 06 Mar 2025 18:28:40 +0100
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
Message-ID: <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>

'ret' can only be 0 at this point, being preceded by a 'if (ret) return
ret;'. So return 0 for clarity.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
 drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
@@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
 
 	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
 
-	return ret;
+	return 0;
 }
 
 static void imx8qxp_ldb_remove(struct platform_device *pdev)

-- 
2.48.1



From cki-project at redhat.com  Thu Mar  6 09:23:06 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 17:23:06 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <06769.125030612230803399@us-mta-128.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703414689

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703414689-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From jbrunet at baylibre.com  Thu Mar  6 09:26:03 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 06 Mar 2025 18:26:03 +0100
Subject: [PATCH] clk: meson: g12a: Fix kernel warnings when no display
 attached
In-Reply-To: <004801db8eb7$99808e20$cc81aa60$@martijnvandeventer.nl>
	(linux@martijnvandeventer.nl's message of "Thu, 6 Mar 2025 17:48:33
	+0100")
References: <20250213221702.606-1-linux@martijnvandeventer.nl>
	<1jpljkzyf0.fsf@starbuckisacylon.baylibre.com>
	<003301db888e$8ea84e90$abf8ebb0$@martijnvandeventer.nl>
	<1jplj3g21q.fsf@starbuckisacylon.baylibre.com>
	<004801db8eb7$99808e20$cc81aa60$@martijnvandeventer.nl>
Message-ID: <1j4j065avo.fsf@starbuckisacylon.baylibre.com>

On Thu 06 Mar 2025 at 17:48, <linux at martijnvandeventer.nl> wrote:

> Hi Jerome,
>
>> >
>> > Thank you for reviewing, and apologies for my late response due to a
>> holiday.
>> >
>> >> On Thu 13 Feb 2025 at 23:17, Martijn van Deventer
>> >> <linux at martijnvandeventer.nl> wrote:
>> >>
>> >> > When booting SM1 or G12A boards without a dislay attached to HDMI,
>> >> > the kernel shows the following warning:
>> >> >
>> >> > [CRTC:46:meson_crtc] vblank wait timed out
>> >> > WARNING: CPU: 2 PID: 265 at
>> drivers/gpu/drm/drm_atomic_helper.c:1682
>> >> drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
>> >> > CPU: 2 UID: 0 PID: 265 Comm: setfont Tainted: G         C
>> >> > Tainted: [C]=CRAP
>> >> > pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>> >> > pc : drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
>> >> > lr : drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
>> >> > Call trace:
>> >> >  drm_atomic_helper_wait_for_vblanks.part.0+0x240/0x264
>> >> >  drm_atomic_helper_commit_tail_rpm+0x84/0xa0
>> >> >  commit_tail+0xa4/0x18c
>> >> >  drm_atomic_helper_commit+0x164/0x178
>> >> >  drm_atomic_commit+0xb4/0xec
>> >> >  drm_client_modeset_commit_atomic+0x210/0x270
>> >> >  drm_client_modeset_commit_locked+0x5c/0x188
>> >> >  drm_fb_helper_pan_display+0xb8/0x1d4
>> >> >  fb_pan_display+0x7c/0x120
>> >> >  bit_update_start+0x20/0x48
>> >> >  fbcon_switch+0x418/0x54c
>> >> >  el0t_64_sync+0x194/0x198
>> >> >
>> >> > This happens when the kernel disables the unused clocks.
>> >> > Sometimes this causes the boot to hang.
>> >> >
>> >> > By (re)adding the flag CLK_IGNORE_UNUSED to the VCLK2 clocks, these
>> >> > clocks will not be disabled.
>> >> >
>> >> > This partially reverts commit b70cb1a21a54 ("clk: meson: g12a:
>> >> > make VCLK2 and ENCL clock path configurable by CCF").
>> >>
>> >> It looks like DRM needs those clock enabled regardless of connection
>> >> status on HDMI. Even with this change applied, you would get the same
>> >> problem again if the bootloader does not take of turning the clock on,
>> >> which is not a given.
>> >>
>> >> CLK_IGNORE_UNUSED gives not guarantee a clock will be enabled or stay
>> >> enabled at any point.
>> >>
>> >> A proper fix to this issue should be done in DRM, IMO.
>> >
>> > I know and I totally agree. Unfortunately, I don't have access to any 
>> > vendor
>> > documentation, nor do I have any real knowledge about the DRM/HDMI
>> > subsystem to fix that.
>>
>> You have identified which clocks are not properly claimed, by what they
>> are not claimed and even when. 50% of the job is done. Thanks for this.
>
> You're welcome, no problem.
>
>> >
>> > And I guess if it were as easy as adding a clock to the DT and calling
>> > clk_prepare_enable on it in the probe function, Neil would have done
>> that
>> > already.
>> >
>> > So, all I can do, for now, is revert to the previous situation when it 
>> > did
>> work
>> > for (probably) most boards.
>>
>> Maybe so, but it does not make this change appropriate. The problem
>> is the DRM driver which does not enable what it needs to properly
>> operate. This should be fixed.
>
> I understand. So I guess that is the end of the line for this patch.
> Because this patch will not be accepted and if someone else finds the 
> time and has the knowledge to fix this the proper way, it will be a 
> completely different patch.
>
> Although I, of course, agree with you that it should be fixed properly, 
> I find it a bit difficult to accept that if we accidentally break something,
> while trying to make things better, we are not allowed to revert it 
> because it was already somewhat broken. Resulting in a more broken
> situation than before...

Once again, you are encouraged to fix things up ... where fixes are needed.

DRM is hardly immutable. If you don't feel like you can do it on your own,
you can still engage with the other contributors who may know this
better and help you.

>
> On the other hand, I also understand that if you, as a maintainer, allow 
> that, chances are it will never see a proper fix. :-)
>
> Cheers!
>
>> >
>> >> >
>> >> > Fixes: b70cb1a21a54 ("clk: meson: g12a: make VCLK2 and ENCL clock
>> path
>> >> configurable by CCF").
>> >> > Signed-off-by: Martijn van Deventer <linux at martijnvandeventer.nl>
>> >> > ---
>> >> >  drivers/clk/meson/g12a.c | 12 ++++++------
>> >> >  1 file changed, 6 insertions(+), 6 deletions(-)
>> >> >
>> >> > diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
>> >> > index cfffd434e998..1651898658f5 100644
>> >> > --- a/drivers/clk/meson/g12a.c
>> >> > +++ b/drivers/clk/meson/g12a.c
>> >> > @@ -3234,7 +3234,7 @@ static struct clk_regmap g12a_vclk2_div = {

-- 
Jerome


From luca.ceresoli at bootlin.com  Thu Mar  6 09:28:39 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 06 Mar 2025 18:28:39 +0100
Subject: [PATCH 0/2] drm/bridge: two minor code improvements
Message-ID: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>

This small series brings small improvements to two bridge drivers.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
Luca Ceresoli (2):
      drm/bridge: imx8qxp-ldb: cleanup return value
      drm/bridge: fsl-ldb: make warning message more informative

 drivers/gpu/drm/bridge/fsl-ldb.c         | 6 +++---
 drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
---
base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
change-id: 20250306-drm-two-ldb-improvements-16fa67cc0eaf

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From wei.liu at kernel.org  Thu Mar  6 09:32:06 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Thu, 6 Mar 2025 17:32:06 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <f332b77a-940f-4007-a44a-de64878d5201@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <f332b77a-940f-4007-a44a-de64878d5201@linux.microsoft.com>
Message-ID: <Z8ncFkwzxi9qJFD3@liuwe-devbox-debian-v2>

On Thu, Feb 27, 2025 at 10:50:30AM -0800, Roman Kisel wrote:
> 
> 
> 
> On 2/26/2025 3:08 PM, Nuno Das Neves wrote:
> > Provide a set of IOCTLs for creating and managing child partitions when
> > running as root partition on Hyper-V. The new driver is enabled via
> > CONFIG_MSHV_ROOT.
> > 
> 
> [...]
> 
> 
> As I understood, the changes fall into these buckets:
> 
> 1. Partition management (VPs and memory). Built of the top of fd's which
>    looks as the right approach. There is ref counting etc.
> 2. Scheduling. Here, there is the mature KVM and Xen code to find
>    inspiration in. Xen being the Type 1 hypervisor should likely be
>    closer to MSHV in my understanding.

Yes and no.

When a hypervisor-based scheduler (either classic or core) is used, the
scheduling model is the same as Xen. In this model, the hypervisor makes
the scheduling decisions.

There is a second scheduler model. In that model, the hypervisor
delegates scheduling to the Linux kernel. The Linux scheduler makes the
scheduling decisions. It is similar to KVM.

We support both. Which model to use largely depends on the workload and
the desired behaviors of the system.

This is purely informational in case people wonder why the run vp
function branches off to two different code paths.

> 3. IOCTL code allocation. Not sure how this is allocated yet given that
>    the patch series has been through a multi-year review, that must be
>    settled by now.
> 4. IOCTLs themselves. The majority just marshals data to the
>    hypervisor.
> 
> Despite the rather large size of the patch, I spot-checked the places
> where I have the chance to make an informed decision, and could not find
> anything that'd stand out as suspicious to me. Going to extrapolate that
> the patch itself should be good enough. Given that this code has been in
> development and validation for a few years, I'd vote to merge it. That
> will also enable upstreaming the rest of the VTL mode code that powers
> Azure Boost (https://github.com/microsoft/OHCL-Linux-Kernel)
> 
> Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
> 

Thank you for the review.

Thanks,
Wei.

> -- 
> Thank you,
> Roman
> 


From dingwei at marvell.com  Thu Mar  6 09:42:56 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Thu, 6 Mar 2025 17:42:56 +0000
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <03b14353-5d47-48de-99fd-9cc48bad5651@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
 <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <03b14353-5d47-48de-99fd-9cc48bad5651@kernel.org>
Message-ID: <BY3PR18MB4673BD07048F8AF7EA55282CA7CA2@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Wednesday, March 5, 2025 11:29 PM
> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> robh at kernel.org
> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> sebastian.hesselbarth at gmail.com; krzk+dt at kernel.org; conor+dt at kernel.org;
> p.zabel at pengutronix.de; Sanghoon Lee <salee at marvell.com>;
> Geethasowjanya Akula <gakula at marvell.com>
> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset
> controller node
> 
> On 04/03/2025 20:08, Wilson Ding wrote:
> >
> > I did consider shrinking the syscon's register address range to make
> > the reset-controller node to be independent from the syscon node.
> > However, I found the syscon node is also referred by some devices for
> > miscellaneous configurations . The reset configuration register
> > happens to be located in between these registers and clock/GPIO
> > registers.
> >
> >> drop offset in your patch or unify everything into 'reg'.
> >>
> >
> > This is exactly what I proposed in v3 patch. Do I misunderstand you?
> >
> > CP11X_LABEL(swrst): reset-controller at 268 {
> > 	compatible = "marvell,armada8k-reset";
> > 	reg = <0x268 0x4>;
> > 	#reset-cells = <1>;
> > };
> 
> I don't see the other device being fixed here. How did you unify them?

This patch series is about the proposal of Armada8K's reset controller
dt-binding. The dt-bindings issues of clock/GPIO controllers have been
there for years. Having to say, it is not just a simple patch to fix it. It
will require to convert the dt-binding document into json schemas as
well as adapt these dt changes in the drivers. So I would suggest to
fixing it in later patches. How do you think about it?

> 
> Best regards,
> Krzysztof

From mathieu.poirier at linaro.org  Thu Mar  6 09:50:18 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Thu, 6 Mar 2025 10:50:18 -0700
Subject: [PATCH] remoteproc: imx_dsp_rproc: conditionally wait for
 FW_READY
In-Reply-To: <20250305123923.514386-1-iuliana.prodan@oss.nxp.com>
References: <20250305123923.514386-1-iuliana.prodan@oss.nxp.com>
Message-ID: <Z8ngWhbkO2770qMq@p14s>

Good morning,

On Wed, Mar 05, 2025 at 02:39:23PM +0200, Iuliana Prodan (OSS) wrote:
> From: Iuliana Prodan <iuliana.prodan at nxp.com>
> 
> Some DSP firmware requires a FW_READY signal before proceeding,
> while others do not.
> Introduce imx_dsp_rproc_wait_fw_ready() to check the resource table
> and determine if waiting is needed.
> 
> Use the WAIT_FW_READY flag (bit 1) to distinguish cases where
> waiting is required, as bit 0 is reserved for VIRTIO_RPMSG_F_NS
> in OpenAMP and mentioned in rpmsg documentation (not used in Linux,
> so far).

VIRTIO_RPMSG_F_NS is used in [1].

[1]. https://elixir.bootlin.com/linux/v6.14-rc5/source/drivers/rpmsg/virtio_rpmsg_bus.c#L1051

> This flag is set by the remote processor in the dfeatures member of
> struct fw_rsc_vdev, indicating supported virtio device features.
> 
> Update imx_dsp_rproc_start() to handle this condition accordingly.
> 
> Signed-off-by: Iuliana Prodan <iuliana.prodan at nxp.com>
> ---
>  drivers/remoteproc/imx_dsp_rproc.c | 84 +++++++++++++++++++++++++++---
>  1 file changed, 77 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
> index b9bb15970966..8eefaee28061 100644
> --- a/drivers/remoteproc/imx_dsp_rproc.c
> +++ b/drivers/remoteproc/imx_dsp_rproc.c
> @@ -1,5 +1,5 @@
>  // SPDX-License-Identifier: GPL-2.0-only
> -/* Copyright 2021 NXP */
> +/* Copyright 2021, 2025 NXP */
>  
>  #include <dt-bindings/firmware/imx/rsrc.h>
>  #include <linux/arm-smccc.h>
> @@ -38,6 +38,15 @@ MODULE_PARM_DESC(no_mailboxes,
>  #define REMOTE_IS_READY				BIT(0)
>  #define REMOTE_READY_WAIT_MAX_RETRIES		500
>  
> +/*
> + * This flag is set by the remote processor in the dfeatures member of
> + * struct fw_rsc_vdev, indicating supported virtio device features
> + *
> + * Use bit 1 since bit 0 is used for VIRTIO_RPMSG_F_NS
> + * in OpenAMP and mentioned in kernel's rpmsg documentation
> + */
> +#define WAIT_FW_READY				BIT(1)
> +
>  /* att flags */
>  /* DSP own area */
>  #define ATT_OWN					BIT(31)
> @@ -300,13 +309,74 @@ static int imx_dsp_rproc_ready(struct rproc *rproc)
>  	return -ETIMEDOUT;
>  }
>  
> +/*
> + * Determines whether we should wait for a FW_READY reply
> + * from the remote processor.
> + *
> + * This function inspects the resource table associated with the remote
> + * processor to check if the firmware has indicated that waiting
> + * for a FW_READY signal is necessary.
> + * By default, wait for FW_READY unless an RSC_VDEV explicitly
> + * indicates otherwise.
> + *
> + * Return:
> + *   - true: If we should wait for FW READY
> + *   - false: If FW_READY wait is not required
> + */
> +static bool imx_dsp_rproc_wait_fw_ready(struct rproc *rproc)
> +{
> +	struct device *dev = &rproc->dev;
> +	struct fw_rsc_hdr *hdr;
> +	struct fw_rsc_vdev *rsc;
> +	int i, offset, avail;
> +
> +	/*
> +	 * If there is no resource table, wait for FW_READY
> +	 * unless no_mailboxes module param is used
> +	 */
> +	if (!rproc->table_ptr)
> +		return true;
> +
> +	/* Iterate over each resource entry in the resource table */
> +	for (i = 0; i < rproc->table_ptr->num; i++) {
> +		offset = rproc->table_ptr->offset[i];
> +		hdr = (void *)rproc->table_ptr + offset;
> +		avail = rproc->table_sz - offset - sizeof(*hdr);
> +
> +		/* Ensure the resource table is not truncated */
> +		if (avail < 0) {
> +			dev_err(dev, "Resource table is truncated\n");
> +			return true;
> +		}
> +
> +		/* Check if the resource type is a virtio device */
> +		if (hdr->type == RSC_VDEV) {
> +			rsc = (struct fw_rsc_vdev *)((void *)hdr + sizeof(*hdr));
> +
> +			/* vdev does not require waiting for FW_READY */
> +			return !!(rsc->dfeatures & WAIT_FW_READY);

>From a virtIO perspective where one virtIO device pertains to one virtIO driver,
your approach is valid.  From a remoteproc perspecrtive though, we have one
virtIO driver [2] used by several implementation (NXP, ST, TI, ...).  So far,
information conveyed by rsc->dfeatures was applicable to all implementation and
things need to remain that way.  Otherwise, it is a matter of time before custom
and global features start clashing.

Using rsc->dfeatures in the way you do above means the resource table in the FW
image needs to be mofidied.  As such, you could take advantage of the vendor
specific resource table entry already supported by the remoteproc framework [3].
>From there you provide a resource handler specific to the iMX DSP driver and
things just work.  Moreover, you wouldn't have to parse the whole resource table
every time imx_dsp_rproc_start() is called.

Hopefully this works for you.

Thanks,
Mathieu

[2]. https://elixir.bootlin.com/linux/v6.14-rc5/source/drivers/rpmsg/virtio_rpmsg_bus.c#L1054
[3]. https://elixir.bootlin.com/linux/v6.14-rc5/source/drivers/remoteproc/remoteproc_core.c#L1044

> +		}
> +	}
> +
> +	/*
> +	 * By default, wait for the FW_READY
> +	 * unless a vdev entry disables it
> +	 */
> +	return true;
> +}
> +
>  /*
>   * Start function for rproc_ops
>   *
> - * There is a handshake for start procedure: when DSP starts, it
> - * will send a doorbell message to this driver, then the
> - * REMOTE_IS_READY flags is set, then driver will kick

> - * a message to DSP.
> + * The start procedure involves a handshake: when the DSP starts, it
> + * sends a doorbell message to this driver, which sets the
> + * REMOTE_IS_READY flag. The driver then sends a message to the DSP.
> + *
> + * Before proceeding, the driver checks if it needs to wait for a
> + * firmware ready reply using imx_dsp_rproc_wait_fw_ready().
> + * If waiting is required, it calls imx_dsp_rproc_ready() to complete
> + * the initialization.
> + * If waiting is not required, the start function returns.
>   */
>  static int imx_dsp_rproc_start(struct rproc *rproc)
>  {
> @@ -335,8 +405,8 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
>  
>  	if (ret)
>  		dev_err(dev, "Failed to enable remote core!\n");
> -	else
> -		ret = imx_dsp_rproc_ready(rproc);
> +	else if (imx_dsp_rproc_wait_fw_ready(rproc))
> +		return imx_dsp_rproc_ready(rproc);
>  
>  	return ret;
>  }
> -- 
> 2.25.1
> 


From cki-project at redhat.com  Thu Mar  6 09:52:12 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 17:52:12 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <06843.125030612521401693@us-mta-266.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703468997

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703468997-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From mhklinux at outlook.com  Thu Mar  6 09:57:44 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 17:57:44 +0000
Subject: [PATCH v5 01/10] hyperv: Convert Hyper-V status codes to strings
In-Reply-To: <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
> Introduce hv_result_to_string() for this purpose. This allows
> hypercall failures to be debugged more easily with dmesg.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---
>  drivers/hv/hv_common.c         | 65 ++++++++++++++++++++++++++++++++++
>  drivers/hv/hv_proc.c           | 13 ++++---
>  include/asm-generic/mshyperv.h |  1 +
>  3 files changed, 74 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 9804adb4cc56..ce20818688fe 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -740,3 +740,68 @@ void hv_identify_partition_type(void)
>  			pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
>  	}
>  }
> +
> +const char *hv_result_to_string(u64 hv_status)
> +{
> +	switch (hv_result(hv_status)) {
> +	case HV_STATUS_SUCCESS:
> +		return "HV_STATUS_SUCCESS";
> +	case HV_STATUS_INVALID_HYPERCALL_CODE:
> +		return "HV_STATUS_INVALID_HYPERCALL_CODE";
> +	case HV_STATUS_INVALID_HYPERCALL_INPUT:
> +		return "HV_STATUS_INVALID_HYPERCALL_INPUT";
> +	case HV_STATUS_INVALID_ALIGNMENT:
> +		return "HV_STATUS_INVALID_ALIGNMENT";
> +	case HV_STATUS_INVALID_PARAMETER:
> +		return "HV_STATUS_INVALID_PARAMETER";
> +	case HV_STATUS_ACCESS_DENIED:
> +		return "HV_STATUS_ACCESS_DENIED";
> +	case HV_STATUS_INVALID_PARTITION_STATE:
> +		return "HV_STATUS_INVALID_PARTITION_STATE";
> +	case HV_STATUS_OPERATION_DENIED:
> +		return "HV_STATUS_OPERATION_DENIED";
> +	case HV_STATUS_UNKNOWN_PROPERTY:
> +		return "HV_STATUS_UNKNOWN_PROPERTY";
> +	case HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE:
> +		return "HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE";
> +	case HV_STATUS_INSUFFICIENT_MEMORY:
> +		return "HV_STATUS_INSUFFICIENT_MEMORY";
> +	case HV_STATUS_INVALID_PARTITION_ID:
> +		return "HV_STATUS_INVALID_PARTITION_ID";
> +	case HV_STATUS_INVALID_VP_INDEX:
> +		return "HV_STATUS_INVALID_VP_INDEX";
> +	case HV_STATUS_NOT_FOUND:
> +		return "HV_STATUS_NOT_FOUND";
> +	case HV_STATUS_INVALID_PORT_ID:
> +		return "HV_STATUS_INVALID_PORT_ID";
> +	case HV_STATUS_INVALID_CONNECTION_ID:
> +		return "HV_STATUS_INVALID_CONNECTION_ID";
> +	case HV_STATUS_INSUFFICIENT_BUFFERS:
> +		return "HV_STATUS_INSUFFICIENT_BUFFERS";
> +	case HV_STATUS_NOT_ACKNOWLEDGED:
> +		return "HV_STATUS_NOT_ACKNOWLEDGED";
> +	case HV_STATUS_INVALID_VP_STATE:
> +		return "HV_STATUS_INVALID_VP_STATE";
> +	case HV_STATUS_NO_RESOURCES:
> +		return "HV_STATUS_NO_RESOURCES";
> +	case HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED:
> +		return "HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED";
> +	case HV_STATUS_INVALID_LP_INDEX:
> +		return "HV_STATUS_INVALID_LP_INDEX";
> +	case HV_STATUS_INVALID_REGISTER_VALUE:
> +		return "HV_STATUS_INVALID_REGISTER_VALUE";
> +	case HV_STATUS_OPERATION_FAILED:
> +		return "HV_STATUS_OPERATION_FAILED";
> +	case HV_STATUS_TIME_OUT:
> +		return "HV_STATUS_TIME_OUT";
> +	case HV_STATUS_CALL_PENDING:
> +		return "HV_STATUS_CALL_PENDING";
> +	case HV_STATUS_VTL_ALREADY_ENABLED:
> +		return "HV_STATUS_VTL_ALREADY_ENABLED";
> +	default:
> +		return "Unknown";
> +	};
> +	return "Unknown";
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_string);
> +
> diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
> index 2fae18e4f7d2..8fc30f509fa7 100644
> --- a/drivers/hv/hv_proc.c
> +++ b/drivers/hv/hv_proc.c
> @@ -87,7 +87,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32
> num_pages)
>  				     page_count, 0, input_page, NULL);
>  	local_irq_restore(flags);
>  	if (!hv_result_success(status)) {
> -		pr_err("Failed to deposit pages: %lld\n", status);
> +		pr_err("%s: Failed to deposit pages: %s\n", __func__,
> +		       hv_result_to_string(status));
>  		ret = hv_result_to_errno(status);
>  		goto err_free_allocations;
>  	}
> @@ -137,8 +138,9 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
> 
>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>  			if (!hv_result_success(status)) {
> -				pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
> -				       lp_index, apic_id, status);
> +				pr_err("%s: cpu %u apic ID %u, %s\n",
> +				       __func__, lp_index, apic_id,
> +				       hv_result_to_string(status));
>  				ret = hv_result_to_errno(status);
>  			}
>  			break;
> @@ -179,8 +181,9 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index,
> u32 flags)
> 
>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>  			if (!hv_result_success(status)) {
> -				pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
> -				       vp_index, flags, status);
> +				pr_err("%s: vcpu %u, lp %u, %s\n",
> +				       __func__, vp_index, flags,
> +				       hv_result_to_string(status));
>  				ret = hv_result_to_errno(status);
>  			}
>  			break;
> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> index b13b0cda4ac8..dc4729dba9ef 100644
> --- a/include/asm-generic/mshyperv.h
> +++ b/include/asm-generic/mshyperv.h
> @@ -298,6 +298,7 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
>  	return __cpumask_to_vpset(vpset, cpus, func);
>  }
> 
> +const char *hv_result_to_string(u64 hv_status);
>  int hv_result_to_errno(u64 status);
>  void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
>  bool hv_is_hyperv_initialized(void);
> --
> 2.34.1

I've read through the other comments on this patch. I definitely vote
for outputting both the hex code along with a string translation, which
could be empty if the hex code is unrecognized by the translation code.

I can see providing something like hv_hvcall_err() as Nuno proposed, since
that standardizes the text output. But I wonder if it would be too limiting.
For example, in the changes above, both hv_call_add_logical_proc() and
hv_call_create_vp() output additional debugging values, which we probably
don't want to give up.

Lastly, from an implementation standpoint, rather than using a big
switch statement, build a static array of entries that each have the
hex code and string equivalent. Then hv_result_to_string() loops through
the array looking for a match. This won't be any slower than the big switch
statement. I've seen other places in the kernel where string names are
output, and looking up the strings in a static array is the typical approach.
You'll have to work through the details and see if avoids being too clumsy,
but I think it will be OK.

Michael


From mhklinux at outlook.com  Thu Mar  6 10:09:11 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 18:09:11 +0000
Subject: [PATCH v5 01/10] hyperv: Convert Hyper-V status codes to strings
In-Reply-To: <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <SN6PR02MB4157629A6197A8A6C992BB75D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Michael Kelley <mhklinux at outlook.com> Sent: Thursday, March 6, 2025 9:58 AM

> 
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February
> 26, 2025 3:08 PM
> >
> > Introduce hv_result_to_string() for this purpose. This allows
> > hypercall failures to be debugged more easily with dmesg.
> >
> > Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> > ---
> >  drivers/hv/hv_common.c         | 65 ++++++++++++++++++++++++++++++++++
> >  drivers/hv/hv_proc.c           | 13 ++++---
> >  include/asm-generic/mshyperv.h |  1 +
> >  3 files changed, 74 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> > index 9804adb4cc56..ce20818688fe 100644
> > --- a/drivers/hv/hv_common.c
> > +++ b/drivers/hv/hv_common.c
> > @@ -740,3 +740,68 @@ void hv_identify_partition_type(void)
> >  			pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
> >  	}
> >  }
> > +
> > +const char *hv_result_to_string(u64 hv_status)
> > +{
> > +	switch (hv_result(hv_status)) {
> > +	case HV_STATUS_SUCCESS:
> > +		return "HV_STATUS_SUCCESS";
> > +	case HV_STATUS_INVALID_HYPERCALL_CODE:
> > +		return "HV_STATUS_INVALID_HYPERCALL_CODE";
> > +	case HV_STATUS_INVALID_HYPERCALL_INPUT:
> > +		return "HV_STATUS_INVALID_HYPERCALL_INPUT";
> > +	case HV_STATUS_INVALID_ALIGNMENT:
> > +		return "HV_STATUS_INVALID_ALIGNMENT";
> > +	case HV_STATUS_INVALID_PARAMETER:
> > +		return "HV_STATUS_INVALID_PARAMETER";
> > +	case HV_STATUS_ACCESS_DENIED:
> > +		return "HV_STATUS_ACCESS_DENIED";
> > +	case HV_STATUS_INVALID_PARTITION_STATE:
> > +		return "HV_STATUS_INVALID_PARTITION_STATE";
> > +	case HV_STATUS_OPERATION_DENIED:
> > +		return "HV_STATUS_OPERATION_DENIED";
> > +	case HV_STATUS_UNKNOWN_PROPERTY:
> > +		return "HV_STATUS_UNKNOWN_PROPERTY";
> > +	case HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE:
> > +		return "HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE";
> > +	case HV_STATUS_INSUFFICIENT_MEMORY:
> > +		return "HV_STATUS_INSUFFICIENT_MEMORY";
> > +	case HV_STATUS_INVALID_PARTITION_ID:
> > +		return "HV_STATUS_INVALID_PARTITION_ID";
> > +	case HV_STATUS_INVALID_VP_INDEX:
> > +		return "HV_STATUS_INVALID_VP_INDEX";
> > +	case HV_STATUS_NOT_FOUND:
> > +		return "HV_STATUS_NOT_FOUND";
> > +	case HV_STATUS_INVALID_PORT_ID:
> > +		return "HV_STATUS_INVALID_PORT_ID";
> > +	case HV_STATUS_INVALID_CONNECTION_ID:
> > +		return "HV_STATUS_INVALID_CONNECTION_ID";
> > +	case HV_STATUS_INSUFFICIENT_BUFFERS:
> > +		return "HV_STATUS_INSUFFICIENT_BUFFERS";
> > +	case HV_STATUS_NOT_ACKNOWLEDGED:
> > +		return "HV_STATUS_NOT_ACKNOWLEDGED";
> > +	case HV_STATUS_INVALID_VP_STATE:
> > +		return "HV_STATUS_INVALID_VP_STATE";
> > +	case HV_STATUS_NO_RESOURCES:
> > +		return "HV_STATUS_NO_RESOURCES";
> > +	case HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED:
> > +		return "HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED";
> > +	case HV_STATUS_INVALID_LP_INDEX:
> > +		return "HV_STATUS_INVALID_LP_INDEX";
> > +	case HV_STATUS_INVALID_REGISTER_VALUE:
> > +		return "HV_STATUS_INVALID_REGISTER_VALUE";
> > +	case HV_STATUS_OPERATION_FAILED:
> > +		return "HV_STATUS_OPERATION_FAILED";
> > +	case HV_STATUS_TIME_OUT:
> > +		return "HV_STATUS_TIME_OUT";
> > +	case HV_STATUS_CALL_PENDING:
> > +		return "HV_STATUS_CALL_PENDING";
> > +	case HV_STATUS_VTL_ALREADY_ENABLED:
> > +		return "HV_STATUS_VTL_ALREADY_ENABLED";
> > +	default:
> > +		return "Unknown";
> > +	};
> > +	return "Unknown";
> > +}
> > +EXPORT_SYMBOL_GPL(hv_result_to_string);
> > +
> > diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
> > index 2fae18e4f7d2..8fc30f509fa7 100644
> > --- a/drivers/hv/hv_proc.c
> > +++ b/drivers/hv/hv_proc.c
> > @@ -87,7 +87,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32
> > num_pages)
> >  				     page_count, 0, input_page, NULL);
> >  	local_irq_restore(flags);
> >  	if (!hv_result_success(status)) {
> > -		pr_err("Failed to deposit pages: %lld\n", status);
> > +		pr_err("%s: Failed to deposit pages: %s\n", __func__,
> > +		       hv_result_to_string(status));
> >  		ret = hv_result_to_errno(status);
> >  		goto err_free_allocations;
> >  	}
> > @@ -137,8 +138,9 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
> >
> >  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> >  			if (!hv_result_success(status)) {
> > -				pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
> > -				       lp_index, apic_id, status);
> > +				pr_err("%s: cpu %u apic ID %u, %s\n",
> > +				       __func__, lp_index, apic_id,
> > +				       hv_result_to_string(status));
> >  				ret = hv_result_to_errno(status);
> >  			}
> >  			break;
> > @@ -179,8 +181,9 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index,
> > u32 flags)
> >
> >  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> >  			if (!hv_result_success(status)) {
> > -				pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
> > -				       vp_index, flags, status);
> > +				pr_err("%s: vcpu %u, lp %u, %s\n",
> > +				       __func__, vp_index, flags,
> > +				       hv_result_to_string(status));
> >  				ret = hv_result_to_errno(status);
> >  			}
> >  			break;
> > diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> > index b13b0cda4ac8..dc4729dba9ef 100644
> > --- a/include/asm-generic/mshyperv.h
> > +++ b/include/asm-generic/mshyperv.h
> > @@ -298,6 +298,7 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
> >  	return __cpumask_to_vpset(vpset, cpus, func);
> >  }
> >
> > +const char *hv_result_to_string(u64 hv_status);
> >  int hv_result_to_errno(u64 status);
> >  void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
> >  bool hv_is_hyperv_initialized(void);
> > --
> > 2.34.1
> 
> I've read through the other comments on this patch. I definitely vote
> for outputting both the hex code along with a string translation, which
> could be empty if the hex code is unrecognized by the translation code.
> 
> I can see providing something like hv_hvcall_err() as Nuno proposed, since
> that standardizes the text output. But I wonder if it would be too limiting.
> For example, in the changes above, both hv_call_add_logical_proc() and
> hv_call_create_vp() output additional debugging values, which we probably
> don't want to give up.
> 
> Lastly, from an implementation standpoint, rather than using a big
> switch statement, build a static array of entries that each have the
> hex code and string equivalent. Then hv_result_to_string() loops through
> the array looking for a match. This won't be any slower than the big switch
> statement. I've seen other places in the kernel where string names are
> output, and looking up the strings in a static array is the typical approach.
> You'll have to work through the details and see if avoids being too clumsy,
> but I think it will be OK.
> 

Better yet, also include the translated errno in each static array entry.
Then hv_result_to_errno() can do the same kind of lookup instead of
having its own switch statement. I did a quick look to see if the two
functions might be combined to do only a single lookup, but that looks
somewhat clumsy unless someone else spots a better way to handle it.
The cost of doing two lookups doesn't really matter in an error case.

FWIW, hv_result_to_errno() and the new hv_result_to_string() are both
slightly misnamed. The input argument is a full 64-bit hv_status, not the
smaller 16-bit result field. hv_status_to_errno() and hv_status_to_string()
would be more precise.

Michael


From Frank.li at nxp.com  Thu Mar  6 10:00:44 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 13:00:44 -0500
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
Message-ID: <Z8nizEsd0QbYgsI/@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 06:28:41PM +0100, Luca Ceresoli wrote:
> This warning notifies a clock was set to an inaccurate value. Modify the
> string to also show the clock name.
>
> While doing that also rewrap the entire function call.
>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
> index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
> @@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
>
>  	configured_link_freq = clk_get_rate(fsl_ldb->clk);
>  	if (configured_link_freq != requested_link_freq)
> -		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> -			 configured_link_freq,
> -			 requested_link_freq);
> +		dev_warn(fsl_ldb->dev,
> +			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> +			 fsl_ldb->clk, configured_link_freq, requested_link_freq);

commit message said show clock name, but %p is for pointer value. Are sure
it show clock name?

Frank

>
>  	clk_prepare_enable(fsl_ldb->clk);
>
>
> --
> 2.48.1
>


From lkp at intel.com  Thu Mar  6 10:01:04 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 7 Mar 2025 02:01:04 +0800
Subject: [PATCH v9 3/3] clk: aspeed: add AST2700 clock driver
In-Reply-To: <20250224095506.2047064-4-ryan_chen@aspeedtech.com>
References: <20250224095506.2047064-4-ryan_chen@aspeedtech.com>
Message-ID: <202503070117.mMjnpop8-lkp@intel.com>

Hi Ryan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.14-rc5 next-20250306]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-binding-clock-ast2700-modify-soc0-1-clock-define/20250224-175830
base:   linus/master
patch link:    https://lore.kernel.org/r/20250224095506.2047064-4-ryan_chen%40aspeedtech.com
patch subject: [PATCH v9 3/3] clk: aspeed: add AST2700 clock driver
config: powerpc64-randconfig-r121-20250306 (https://download.01.org/0day-ci/archive/20250307/202503070117.mMjnpop8-lkp at intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250307/202503070117.mMjnpop8-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503070117.mMjnpop8-lkp at intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/clk/clk-ast2700.c:1066:92: sparse: sparse: Using plain integer as NULL pointer

vim +1066 drivers/clk/clk-ast2700.c

   952	
   953	static int ast2700_soc_clk_probe(struct platform_device *pdev)
   954	{
   955		const struct ast2700_clk_data *clk_data;
   956		struct ast2700_clk_ctrl *clk_ctrl;
   957		struct clk_hw_onecell_data *clk_hw_data;
   958		struct device *dev = &pdev->dev;
   959		void __iomem *clk_base;
   960		struct clk_hw **hws;
   961		char *reset_name;
   962		int ret;
   963		int i;
   964	
   965		clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL);
   966		if (!clk_ctrl)
   967			return -ENOMEM;
   968		clk_ctrl->dev = dev;
   969		dev_set_drvdata(&pdev->dev, clk_ctrl);
   970	
   971		spin_lock_init(&clk_ctrl->lock);
   972	
   973		clk_base = devm_platform_ioremap_resource(pdev, 0);
   974		if (IS_ERR(clk_base))
   975			return PTR_ERR(clk_base);
   976	
   977		clk_ctrl->base = clk_base;
   978	
   979		clk_data = device_get_match_data(dev);
   980		if (!clk_data)
   981			return -ENODEV;
   982	
   983		clk_ctrl->clk_data = clk_data;
   984		reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", clk_data->scu);
   985	
   986		clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, clk_data->nr_clks),
   987					   GFP_KERNEL);
   988		if (!clk_hw_data)
   989			return -ENOMEM;
   990	
   991		clk_hw_data->num = clk_data->nr_clks;
   992		hws = clk_hw_data->hws;
   993	
   994		if (clk_data->scu)
   995			ast2700_soc1_configure_i3c_clk(clk_ctrl);
   996	
   997		for (i = 0; i < clk_data->nr_clks; i++) {
   998			const struct ast2700_clk_info *clk = &clk_data->clk_info[i];
   999			void __iomem *reg;
  1000	
  1001			if (clk->type == CLK_FIXED) {
  1002				const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate;
  1003	
  1004				hws[i] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0,
  1005									 fixed_rate->fixed_rate);
  1006			} else if (clk->type == CLK_FIXED_FACTOR) {
  1007				const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor;
  1008	
  1009				hws[i] = devm_clk_hw_register_fixed_factor(dev, clk->name,
  1010									   factor->parent->name,
  1011									   0, factor->mult, factor->div);
  1012			} else if (clk->type == DCLK_FIXED) {
  1013				const struct ast2700_clk_pll_data *pll = &clk->data.pll;
  1014	
  1015				reg = clk_ctrl->base + pll->reg;
  1016				hws[i] = ast2700_clk_hw_register_dclk(reg, clk->name, clk_ctrl);
  1017			} else if (clk->type == CLK_HPLL) {
  1018				const struct ast2700_clk_pll_data *pll = &clk->data.pll;
  1019	
  1020				reg = clk_ctrl->base + pll->reg;
  1021				hws[i] = ast2700_clk_hw_register_hpll(reg, clk->name,
  1022								      pll->parent->name, clk_ctrl);
  1023			} else if (clk->type == CLK_PLL) {
  1024				const struct ast2700_clk_pll_data *pll = &clk->data.pll;
  1025	
  1026				reg = clk_ctrl->base + pll->reg;
  1027				hws[i] = ast2700_clk_hw_register_pll(i, reg, clk->name,
  1028								     pll->parent->name, clk_ctrl);
  1029			} else if (clk->type == CLK_UART_PLL) {
  1030				const struct ast2700_clk_pll_data *pll = &clk->data.pll;
  1031	
  1032				reg = clk_ctrl->base + pll->reg;
  1033				hws[i] = ast2700_clk_hw_register_uartpll(reg, clk->name,
  1034									 pll->parent->name, clk_ctrl);
  1035			} else if (clk->type == CLK_MUX) {
  1036				const struct ast2700_clk_mux_data *mux = &clk->data.mux;
  1037	
  1038				reg = clk_ctrl->base + mux->reg;
  1039				hws[i] = devm_clk_hw_register_mux_parent_data_table(dev, clk->name,
  1040										    mux->parents,
  1041										    mux->num_parents, 0,
  1042										    reg, mux->bit_shift,
  1043										    mux->bit_width, 0,
  1044										    NULL, &clk_ctrl->lock);
  1045			} else if (clk->type == CLK_MISC) {
  1046				const struct ast2700_clk_pll_data *misc = &clk->data.pll;
  1047	
  1048				reg = clk_ctrl->base + misc->reg;
  1049				hws[i] = ast2700_clk_hw_register_misc(i, reg, clk->name,
  1050								      misc->parent->name, clk_ctrl);
  1051			} else if (clk->type == CLK_DIVIDER) {
  1052				const struct ast2700_clk_div_data *div = &clk->data.div;
  1053	
  1054				reg = clk_ctrl->base + div->reg;
  1055				hws[i] = devm_clk_hw_register_divider_table(dev, clk->name,
  1056									    div->parent->name, 0,
  1057									    reg, div->bit_shift,
  1058									    div->bit_width, 0,
  1059									    div->div_table,
  1060									    &clk_ctrl->lock);
  1061			} else if (clk->type == CLK_GATE_ASPEED) {
  1062				const struct ast2700_clk_gate_data *gate = &clk->data.gate;
  1063	
  1064				reg = clk_ctrl->base + gate->reg;
  1065				hws[i] = ast2700_clk_hw_register_gate(dev, clk->name, gate->parent,
> 1066								      reg, gate->bit, gate->flags, 0);
  1067	
  1068			} else {
  1069				const struct ast2700_clk_gate_data *gate = &clk->data.gate;
  1070	
  1071				reg = clk_ctrl->base + gate->reg;
  1072				hws[i] = devm_clk_hw_register_gate_parent_data(dev, clk->name, gate->parent,
  1073									       0, reg, clk->clk_idx, 0,
  1074									       &clk_ctrl->lock);
  1075			}
  1076	
  1077			if (IS_ERR(hws[i]))
  1078				return PTR_ERR(hws[i]);
  1079		}
  1080	
  1081		ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
  1082		if (ret)
  1083			return ret;
  1084	
  1085		return aspeed_reset_controller_register(dev, clk_base, reset_name);
  1086	}
  1087	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From Frank.li at nxp.com  Thu Mar  6 10:02:10 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 13:02:10 -0500
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
Message-ID: <Z8njIsHSQcRq2S+g@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 06:28:40PM +0100, Luca Ceresoli wrote:
> 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
> ret;'. So return 0 for clarity.
>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
> --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> @@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
>
>  	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
>
> -	return ret;
> +	return 0;

I don't think it is necessary, no difference.

Frank

>  }
>
>  static void imx8qxp_ldb_remove(struct platform_device *pdev)
>
> --
> 2.48.1
>


From detlev.casanova at collabora.com  Thu Mar  6 10:03:44 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Thu,  6 Mar 2025 13:03:44 -0500
Subject: [PATCH] arm64: dts: rockchip: Add HDMI support for rock-4d
Message-ID: <20250306180344.126189-1-detlev.casanova@collabora.com>

Enable HDMI and VOP nodes for the rock-4d board.

Signed-off-by: Detlev Casanova <detlev.casanova at collabora.com>
---
 .../boot/dts/rockchip/rk3576-rock-4d.dts      | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts b/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
index 5dc1c18a3b211..f39bd441dce18 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
@@ -26,6 +26,17 @@ chosen {
 		stdout-path = "serial0:1500000n8";
 	};
 
+	hdmi-con {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
 	leds: leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -238,6 +249,27 @@ &gpu {
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_in {
+	hdmi_in_vp0: endpoint {
+		remote-endpoint = <&vp0_out_hdmi>;
+	};
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&hdptxphy {
+	status = "okay";
+};
+
+
 &i2c1 {
 	status = "okay";
 
@@ -687,3 +719,18 @@ &usb_drd1_dwc3 {
 	dr_mode = "host";
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0 {
+	vp0_out_hdmi: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+		remote-endpoint = <&hdmi_in_vp0>;
+	};
+};
-- 
2.48.1



From catalin.marinas at arm.com  Thu Mar  6 10:06:44 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 6 Mar 2025 18:06:44 +0000
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <7ad365f0-d335-4da1-845a-8fe3bc5eb055@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
 <CGME20250303113525eucas1p1099e087e2c11b9021603a6f13f8135c4@eucas1p1.samsung.com>
 <2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>
 <7b5c90cf-00e4-4684-8719-f380badab064@samsung.com>
 <7ad365f0-d335-4da1-845a-8fe3bc5eb055@arm.com>
Message-ID: <Z8nkNNR6vuoQ9bQD@arm.com>

On Thu, Mar 06, 2025 at 11:39:14AM +0000, Suzuki K Poulose wrote:
> On 04/03/2025 13:40, Marek Szyprowski wrote:
> > > On 27/02/2025 14:41, Suzuki K Poulose wrote:
> > > > Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> > > > space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> > > > half and shared top half. In Linux we treat the "top" bit of the IPA space as
> > > > an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> > > > Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> > > > and are managed by RMM. The "top" bit as attribute is only a software construct.
[...]
> > The changes look fine. However I won't be able to setup new dma-mapping
> > git tree this week because I got really sick has to stay in bed. :/ If
> > You don't want such delay, please merge it via ARM64 tree. Here is my:
> 
> Sorry to hear that. Hope you feel better soon.
> 
> > Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>
> 
> Thanks Marek.
> 
> Btw, this series fixes the "Realm Guest" support for Linux, which was merged
> in v6.13. To be precise, this should have :
> 
> Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")
> 
> Will/Catalin,
> 
> Please let me know if you would like me to send the series with
> all the Acks, Reviews and mainly the Fixes tag added ?

We can add the acks and fixes tag, no worries. I can queue them for 6.15
unless Will takes them as fixes for 6.14 (I'll wait for a bit).

-- 
Catalin


From detlev.casanova at collabora.com  Thu Mar  6 10:06:31 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Thu,  6 Mar 2025 13:06:31 -0500
Subject: [PATCH v2] arm64: dts: rockchip: Add HDMI support for rock-4d
Message-ID: <20250306180737.127726-1-detlev.casanova@collabora.com>

Enable HDMI and VOP nodes for the rock-4d board.

Signed-off-by: Detlev Casanova <detlev.casanova at collabora.com>
---

Changes since v1:
 - Remove extra blank line

 .../boot/dts/rockchip/rk3576-rock-4d.dts      | 46 +++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts b/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
index 5dc1c18a3b211..bccd77c3a906f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
@@ -26,6 +26,17 @@ chosen {
 		stdout-path = "serial0:1500000n8";
 	};
 
+	hdmi-con {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
 	leds: leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -238,6 +249,26 @@ &gpu {
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_in {
+	hdmi_in_vp0: endpoint {
+		remote-endpoint = <&vp0_out_hdmi>;
+	};
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&hdptxphy {
+	status = "okay";
+};
+
 &i2c1 {
 	status = "okay";
 
@@ -687,3 +718,18 @@ &usb_drd1_dwc3 {
 	dr_mode = "host";
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0 {
+	vp0_out_hdmi: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+		remote-endpoint = <&hdmi_in_vp0>;
+	};
+};
-- 
2.48.1



From wiagn233 at outlook.com  Thu Mar  6 10:07:42 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Fri, 7 Mar 2025 02:07:42 +0800
Subject: [PATCH v8] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <c56c9714c754451a8255ece79353da2b@realtek.com>
References: <TYCPR01MB84374EEAC0DDDA4223B8997298CB2@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <c56c9714c754451a8255ece79353da2b@realtek.com>
Message-ID: <TYCPR01MB8437874842FE7A17EB4D856598CA2@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Hi,

Thanks for reply. I'll change the code in next version.

Best regards,
Shengyu

? 2025/3/6 10:27, Ping-Ke Shih ??:
> Shengyu Qu <wiagn233 at outlook.com> wrote:
> 
> [...]
> 
>> @@ -1271,6 +1278,10 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>>   {
>>          struct mt7915_dev *dev = mt7915_hw_dev(hw);
>>          struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
>> +       int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
>> +       struct ieee80211_sta *pre_sta;
>> +       u8 flags = MT76_WED_DEFAULT;
>> +       int temp_idx;
> 
> In general 'temp' is short for temperature. 'tmp' is preferred.
> 
>>
>>          if (enabled)
>>                  set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
>> @@ -1280,6 +1291,30 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>>          if (!msta->wcid.sta)
>>                  return;
>>
>> +       if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> +           !is_mt7915(&dev->mt76) &&
>> +           (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
>> +               pre_sta = kzalloc(sizeof(*sta) + sizeof(*msta), GFP_KERNEL);
>> +               memmove(pre_sta, sta, sizeof(*sta) + sizeof(*msta));
> 
> Seemingly, kmemdup() = kzalloc() + memmove().
> 
>> +
>> +               flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
>> +                       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
>> +
>> +               temp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
> 
> Since __mt76_wcid_alloc() could return -1 for error case, shouldn't you handle that?
> 
>> +               ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = (u16)temp_idx;
> 
> Define a local `struct mt7915_sta *pre_msta = (struct mt7915_sta *)pre_sta->drv_priv`
> ahead. This statement would be simpler. Just `pre_msta-> wcid.idx = (u16)temp_idx`,
> but casting of '(u16)' is still not very preferred.
> 
>> +               mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
>> +               rcu_assign_pointer(dev->mt76.wcid[temp_idx], &msta->wcid);
>> +
>> +               temp_idx = msta->wcid.idx;
>> +               msta->wcid.idx = ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx;
>> +               ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = (u16)temp_idx;
>> +               rcu_assign_pointer(dev->mt76.wcid[temp_idx], NULL);
>> +
>> +               synchronize_rcu();
>> +               mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
>> +               kfree(pre_sta);
>> +       }
>> +
>>          mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
>>   }
>>
> 
> [...]
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/2c48da54/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/2c48da54/attachment.sig>

From heiko at sntech.de  Thu Mar  6 10:08:37 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Thu, 06 Mar 2025 19:08:37 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <cdbc1556-4662-4078-a4d6-33545e2e2491@kwiboo.se>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
 <20250306123809.273655-3-amadeus@jmu.edu.cn>
 <cdbc1556-4662-4078-a4d6-33545e2e2491@kwiboo.se>
Message-ID: <117081043.nniJfEyVGO@diego>

Am Donnerstag, 6. M?rz 2025, 17:55:16 MEZ schrieb Jonas Karlman:
> Hi Chukun,
> 
> On 2025-03-06 13:38, Chukun Pan wrote:
> > The Quality-of-Service (QsS) node stores/restores specific
> > register contents when the power domains is turned off/on.
> > Add QoS node so that they can connect to the power domain.
> > 
> > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
> >  1 file changed, 160 insertions(+)
> > 

> 
> These QoS node are typically referenced from power domains so that the
> PMU driver know what QoS to save/restore when a power domain is power
> cycled.
> 
> Vendor kernel only reference the two qos_gpu nodes in it's power domains,
> do you have any documentation or knowledge about what power domain the
> remaining QoS are related to?

I think the GPU actually is the _only_ fully switchable power-domain on the
rk3528. The other powerdomains seem to be always on, but can do this
idle-request thing.

At least that is what I'm reading from the pm-domain definitions in the
vendor-kernel, combined with a look at the pmu section of the rk3528 TRM.


Heiko




From krzysztof.kozlowski at linaro.org  Thu Mar  6 10:11:12 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Thu, 06 Mar 2025 19:11:12 +0100
Subject: [PATCH] soc: samsung: include linux/array_size.h where needed
In-Reply-To: <20250305211446.43772-1-arnd@kernel.org>
References: <20250305211446.43772-1-arnd@kernel.org>
Message-ID: <174128467279.252750.12742713284242817976.b4-ty@linaro.org>


On Wed, 05 Mar 2025 22:14:02 +0100, Arnd Bergmann wrote:
> This does not necessarily get included through asm/io.h:
> 
> drivers/soc/samsung/exynos3250-pmu.c:120:18: error: use of undeclared identifier 'ARRAY_SIZE'
>   120 |         for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
>       |                         ^
> drivers/soc/samsung/exynos5250-pmu.c:162:18: error: use of undeclared identifier 'ARRAY_SIZE'
>   162 |         for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
>       |                         ^
> 
> [...]

Applied, thanks!

[1/1] soc: samsung: include linux/array_size.h where needed
      https://git.kernel.org/krzk/linux/c/4c57930f68d90e0d52c396d058cfa9ed8447a6c4

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From florian.fainelli at broadcom.com  Thu Mar  6 10:21:36 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Thu,  6 Mar 2025 10:21:36 -0800
Subject: [PATCH v3 5/6] ARM: dts: bcm2166x-common: Add pinctrl node
In-Reply-To: <20250303-bcm21664-pinctrl-v3-5-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com> <20250303-bcm21664-pinctrl-v3-5-5f8b80e4ab51@gmail.com>
Message-ID: <20250306182136.1762272-1-florian.fainelli@broadcom.com>

From: Florian Fainelli <f.fainelli at gmail.com>

On Mon, 03 Mar 2025 21:54:50 +0100, Artur Weber <aweber.kernel at gmail.com> wrote:
> Now that the pinctrl driver supports the BCM21664, add a node for
> pinctrl in the DTS to allow for controlling pinmux pins.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---

Applied to https://github.com/Broadcom/stblinux/commits/devicetree/next, thanks!
--
Florian


From florian.fainelli at broadcom.com  Thu Mar  6 10:21:46 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Thu,  6 Mar 2025 10:21:46 -0800
Subject: [PATCH v3 6/6] ARM: dts: bcm2166x: Add bcm2166x-pinctrl DTSI
In-Reply-To: <20250303-bcm21664-pinctrl-v3-6-5f8b80e4ab51@gmail.com>
References: <20250303-bcm21664-pinctrl-v3-0-5f8b80e4ab51@gmail.com> <20250303-bcm21664-pinctrl-v3-6-5f8b80e4ab51@gmail.com>
Message-ID: <20250306182146.1762360-1-florian.fainelli@broadcom.com>

From: Florian Fainelli <f.fainelli at gmail.com>

On Mon, 03 Mar 2025 21:54:51 +0100, Artur Weber <aweber.kernel at gmail.com> wrote:
> Add common DTSI with common pin control configs for BCM21664/BCM23550
> and include it in bcm2166x-common.dtsi. The configs are kept in a
> separate DTSI to keep things cleaner (pin config definitions take up
> quite a lot of space).
> 
> Currently contains pins for BSC buses and SD/MMC; more pins can be
> added in the future.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---

Applied to https://github.com/Broadcom/stblinux/commits/devicetree/next, thanks!
--
Florian


From mhklinux at outlook.com  Thu Mar  6 10:30:21 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 18:30:21 +0000
Subject: [PATCH v5 02/10] x86/mshyperv: Add support for extended Hyper-V
 features
In-Reply-To: <1740611284-27506-3-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-3-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157CBBC2D186E1944E6773AD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
> From: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> 
> Extend the "ms_hyperv_info" structure to include a new field,
> "ext_features", for capturing extended Hyper-V features.
> Update the "ms_hyperv_init_platform" function to retrieve these features
> using the cpuid instruction and include them in the informational output.
> 
> Signed-off-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---
>  arch/x86/kernel/cpu/mshyperv.c | 6 ++++--
>  include/asm-generic/mshyperv.h | 1 +
>  2 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 4f01f424ea5b..2c29dfd6de19 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -434,13 +434,15 @@ static void __init ms_hyperv_init_platform(void)
>  	 */
>  	ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
>  	ms_hyperv.priv_high = cpuid_ebx(HYPERV_CPUID_FEATURES);
> +	ms_hyperv.ext_features = cpuid_ecx(HYPERV_CPUID_FEATURES);
>  	ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
>  	ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
> 
>  	hv_max_functions_eax = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS);
> 
> -	pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n",
> -		ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
> +	pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, ext 0x%x, hints 0x%x, misc 0x%x\n",
> +		ms_hyperv.features, ms_hyperv.priv_high,
> +		ms_hyperv.ext_features, ms_hyperv.hints,
>  		ms_hyperv.misc_features);
> 
>  	ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> index dc4729dba9ef..c020d5d0ec2a 100644
> --- a/include/asm-generic/mshyperv.h
> +++ b/include/asm-generic/mshyperv.h
> @@ -36,6 +36,7 @@ enum hv_partition_type {
>  struct ms_hyperv_info {
>  	u32 features;
>  	u32 priv_high;
> +	u32 ext_features;
>  	u32 misc_features;
>  	u32 hints;
>  	u32 nested_features;
> --
> 2.34.1

Are any of the extended features available on arm64? This code is obviously x86 specific,
so ms_hyperv.ext_features will be zero on arm64. From what I can see, ext_features is
referenced only in Patch 10 of this series, and in code that is under #ifdef CONFIG_X86_64,
so that should be OK.

The pr_info() line will now be slightly different on x86 and arm64 since arm64 won't have
the "ext" field, but I think that's OK too.

Reviewed-by: Michael Kelley <mhklinux at outlook.com>


From nunodasneves at linux.microsoft.com  Thu Mar  6 10:40:30 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Thu, 6 Mar 2025 10:40:30 -0800
Subject: [PATCH v5 01/10] hyperv: Convert Hyper-V status codes to strings
In-Reply-To: <SN6PR02MB4157629A6197A8A6C992BB75D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <SN6PR02MB4157629A6197A8A6C992BB75D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <9123b404-f6f8-464b-bad8-b793ea6fb21e@linux.microsoft.com>

On 3/6/2025 10:09 AM, Michael Kelley wrote:
> From: Michael Kelley <mhklinux at outlook.com> Sent: Thursday, March 6, 2025 9:58 AM
> 
>>
>> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February
>> 26, 2025 3:08 PM
>>>
>>> Introduce hv_result_to_string() for this purpose. This allows
>>> hypercall failures to be debugged more easily with dmesg.
>>>
>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>> ---
>>>  drivers/hv/hv_common.c         | 65 ++++++++++++++++++++++++++++++++++
>>>  drivers/hv/hv_proc.c           | 13 ++++---
>>>  include/asm-generic/mshyperv.h |  1 +
>>>  3 files changed, 74 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>>> index 9804adb4cc56..ce20818688fe 100644
>>> --- a/drivers/hv/hv_common.c
>>> +++ b/drivers/hv/hv_common.c
>>> @@ -740,3 +740,68 @@ void hv_identify_partition_type(void)
>>>  			pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
>>>  	}
>>>  }
>>> +
>>> +const char *hv_result_to_string(u64 hv_status)
>>> +{
>>> +	switch (hv_result(hv_status)) {
>>> +	case HV_STATUS_SUCCESS:
>>> +		return "HV_STATUS_SUCCESS";
>>> +	case HV_STATUS_INVALID_HYPERCALL_CODE:
>>> +		return "HV_STATUS_INVALID_HYPERCALL_CODE";
>>> +	case HV_STATUS_INVALID_HYPERCALL_INPUT:
>>> +		return "HV_STATUS_INVALID_HYPERCALL_INPUT";
>>> +	case HV_STATUS_INVALID_ALIGNMENT:
>>> +		return "HV_STATUS_INVALID_ALIGNMENT";
>>> +	case HV_STATUS_INVALID_PARAMETER:
>>> +		return "HV_STATUS_INVALID_PARAMETER";
>>> +	case HV_STATUS_ACCESS_DENIED:
>>> +		return "HV_STATUS_ACCESS_DENIED";
>>> +	case HV_STATUS_INVALID_PARTITION_STATE:
>>> +		return "HV_STATUS_INVALID_PARTITION_STATE";
>>> +	case HV_STATUS_OPERATION_DENIED:
>>> +		return "HV_STATUS_OPERATION_DENIED";
>>> +	case HV_STATUS_UNKNOWN_PROPERTY:
>>> +		return "HV_STATUS_UNKNOWN_PROPERTY";
>>> +	case HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE:
>>> +		return "HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE";
>>> +	case HV_STATUS_INSUFFICIENT_MEMORY:
>>> +		return "HV_STATUS_INSUFFICIENT_MEMORY";
>>> +	case HV_STATUS_INVALID_PARTITION_ID:
>>> +		return "HV_STATUS_INVALID_PARTITION_ID";
>>> +	case HV_STATUS_INVALID_VP_INDEX:
>>> +		return "HV_STATUS_INVALID_VP_INDEX";
>>> +	case HV_STATUS_NOT_FOUND:
>>> +		return "HV_STATUS_NOT_FOUND";
>>> +	case HV_STATUS_INVALID_PORT_ID:
>>> +		return "HV_STATUS_INVALID_PORT_ID";
>>> +	case HV_STATUS_INVALID_CONNECTION_ID:
>>> +		return "HV_STATUS_INVALID_CONNECTION_ID";
>>> +	case HV_STATUS_INSUFFICIENT_BUFFERS:
>>> +		return "HV_STATUS_INSUFFICIENT_BUFFERS";
>>> +	case HV_STATUS_NOT_ACKNOWLEDGED:
>>> +		return "HV_STATUS_NOT_ACKNOWLEDGED";
>>> +	case HV_STATUS_INVALID_VP_STATE:
>>> +		return "HV_STATUS_INVALID_VP_STATE";
>>> +	case HV_STATUS_NO_RESOURCES:
>>> +		return "HV_STATUS_NO_RESOURCES";
>>> +	case HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED:
>>> +		return "HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED";
>>> +	case HV_STATUS_INVALID_LP_INDEX:
>>> +		return "HV_STATUS_INVALID_LP_INDEX";
>>> +	case HV_STATUS_INVALID_REGISTER_VALUE:
>>> +		return "HV_STATUS_INVALID_REGISTER_VALUE";
>>> +	case HV_STATUS_OPERATION_FAILED:
>>> +		return "HV_STATUS_OPERATION_FAILED";
>>> +	case HV_STATUS_TIME_OUT:
>>> +		return "HV_STATUS_TIME_OUT";
>>> +	case HV_STATUS_CALL_PENDING:
>>> +		return "HV_STATUS_CALL_PENDING";
>>> +	case HV_STATUS_VTL_ALREADY_ENABLED:
>>> +		return "HV_STATUS_VTL_ALREADY_ENABLED";
>>> +	default:
>>> +		return "Unknown";
>>> +	};
>>> +	return "Unknown";
>>> +}
>>> +EXPORT_SYMBOL_GPL(hv_result_to_string);
>>> +
>>> diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
>>> index 2fae18e4f7d2..8fc30f509fa7 100644
>>> --- a/drivers/hv/hv_proc.c
>>> +++ b/drivers/hv/hv_proc.c
>>> @@ -87,7 +87,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32
>>> num_pages)
>>>  				     page_count, 0, input_page, NULL);
>>>  	local_irq_restore(flags);
>>>  	if (!hv_result_success(status)) {
>>> -		pr_err("Failed to deposit pages: %lld\n", status);
>>> +		pr_err("%s: Failed to deposit pages: %s\n", __func__,
>>> +		       hv_result_to_string(status));
>>>  		ret = hv_result_to_errno(status);
>>>  		goto err_free_allocations;
>>>  	}
>>> @@ -137,8 +138,9 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
>>>
>>>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>>>  			if (!hv_result_success(status)) {
>>> -				pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
>>> -				       lp_index, apic_id, status);
>>> +				pr_err("%s: cpu %u apic ID %u, %s\n",
>>> +				       __func__, lp_index, apic_id,
>>> +				       hv_result_to_string(status));
>>>  				ret = hv_result_to_errno(status);
>>>  			}
>>>  			break;
>>> @@ -179,8 +181,9 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index,
>>> u32 flags)
>>>
>>>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>>>  			if (!hv_result_success(status)) {
>>> -				pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
>>> -				       vp_index, flags, status);
>>> +				pr_err("%s: vcpu %u, lp %u, %s\n",
>>> +				       __func__, vp_index, flags,
>>> +				       hv_result_to_string(status));
>>>  				ret = hv_result_to_errno(status);
>>>  			}
>>>  			break;
>>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>>> index b13b0cda4ac8..dc4729dba9ef 100644
>>> --- a/include/asm-generic/mshyperv.h
>>> +++ b/include/asm-generic/mshyperv.h
>>> @@ -298,6 +298,7 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
>>>  	return __cpumask_to_vpset(vpset, cpus, func);
>>>  }
>>>
>>> +const char *hv_result_to_string(u64 hv_status);
>>>  int hv_result_to_errno(u64 status);
>>>  void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
>>>  bool hv_is_hyperv_initialized(void);
>>> --
>>> 2.34.1
>>
>> I've read through the other comments on this patch. I definitely vote
>> for outputting both the hex code along with a string translation, which
>> could be empty if the hex code is unrecognized by the translation code.
>>
>> I can see providing something like hv_hvcall_err() as Nuno proposed, since
>> that standardizes the text output. But I wonder if it would be too limiting.
>> For example, in the changes above, both hv_call_add_logical_proc() and
>> hv_call_create_vp() output additional debugging values, which we probably
>> don't want to give up.
>>
>> Lastly, from an implementation standpoint, rather than using a big
>> switch statement, build a static array of entries that each have the
>> hex code and string equivalent. Then hv_result_to_string() loops through
>> the array looking for a match. This won't be any slower than the big switch
>> statement. I've seen other places in the kernel where string names are
>> output, and looking up the strings in a static array is the typical approach.
>> You'll have to work through the details and see if avoids being too clumsy,
>> but I think it will be OK.
>>
> 
> Better yet, also include the translated errno in each static array entry.
> Then hv_result_to_errno() can do the same kind of lookup instead of
> having its own switch statement. I did a quick look to see if the two
> functions might be combined to do only a single lookup, but that looks
> somewhat clumsy unless someone else spots a better way to handle it.
> The cost of doing two lookups doesn't really matter in an error case.
> 
> FWIW, hv_result_to_errno() and the new hv_result_to_string() are both
> slightly misnamed. The input argument is a full 64-bit hv_status, not the
> smaller 16-bit result field. hv_status_to_errno() and hv_status_to_string()
> would be more precise.
> 
Hmm, well I'll admit I was and still am rather confused on this point.

In the TLFS (section 3.8) the entire 64-bit return value is called the
"hypercall result value".
The 16-bit HV_STATUS part is *also* called the "result" in this section.
Later, in section 3.12, the 16-bit field is referred to as a "status value
field".
Furthermore, the name of the 16-bit value, itself, is HV_STATUS.

Despite the inconsistency, in my mind it makes the most sense that the
16-bit HV_STATUS part the "status" and the entire 64-bit return value the
"result". I am aware that elsewhere (and in the driver patches in this
series), the name "status" is used to refer to the entire 64-bit return
value.

These functions were actually called hv_status_to_errno() and hv_status_to_string()
in the past, but I changed them to use "result" by following my own logic, and I
thought this also matched the naming of hv_result() and hv_result_success().
However I now realize that the "result" in these names refers to the *output* of
these functions... they take a u64 status as a parameter after all..

So in the end I'm rather bothered by this whole situation. I can change these
names back to "status" (although hv_result_to_errno() is already merged, I
could send a fixup), or I could keep "result", which I think is a more
logical name for the 64-bit value, even though it somewhat contradicts how
the term is already used in the kernel.

Given it doesn't seem to be well-defined in the first place, I'm not really
sure the best route.

Nuno

> Michael



From cki-project at redhat.com  Thu Mar  6 10:42:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 18:42:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <66225.125030613420703370@us-mta-618.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703542044

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703542044-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From sebott at redhat.com  Thu Mar  6 10:40:13 2025
From: sebott at redhat.com (Sebastian Ott)
Date: Thu,  6 Mar 2025 19:40:13 +0100
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
Message-ID: <20250306184013.30008-1-sebott@redhat.com>

Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
Disallow to change these fields for NV since kvm provides a sanitized view
for them based on the PAGE_SIZE.
Also add these bits to the set_id_regs selftest.

Signed-off-by: Sebastian Ott <sebott at redhat.com>
---
 arch/arm64/kvm/sys_regs.c                     | 21 +++++++++++++++----
 .../testing/selftests/kvm/arm64/set_id_regs.c |  3 +++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 14faf213d483..0730ed8314d0 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1948,6 +1948,21 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
 	return set_id_reg(vcpu, rd, user_val);
 }
 
+static int set_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu,
+				const struct sys_reg_desc *rd, u64 user_val)
+{
+	u64 sanitized_val = kvm_read_sanitised_id_reg(vcpu, rd);
+	u64 tgran2_mask = ID_AA64MMFR0_EL1_TGRAN4_2_MASK |
+			  ID_AA64MMFR0_EL1_TGRAN16_2_MASK |
+			  ID_AA64MMFR0_EL1_TGRAN64_2_MASK;
+
+	if (vcpu_has_nv(vcpu) &&
+	    ((sanitized_val & tgran2_mask) != (user_val & tgran2_mask)))
+		return -EINVAL;
+
+	return set_id_reg(vcpu, rd, user_val);
+}
+
 static int set_id_aa64mmfr2_el1(struct kvm_vcpu *vcpu,
 				const struct sys_reg_desc *rd, u64 user_val)
 {
@@ -2787,10 +2802,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	ID_UNALLOCATED(6,7),
 
 	/* CRm=7 */
-	ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
-					ID_AA64MMFR0_EL1_TGRAN4_2 |
-					ID_AA64MMFR0_EL1_TGRAN64_2 |
-					ID_AA64MMFR0_EL1_TGRAN16_2 |
+	ID_FILTERED(ID_AA64MMFR0_EL1, id_aa64mmfr0_el1,
+				      ~(ID_AA64MMFR0_EL1_RES0 |
 					ID_AA64MMFR0_EL1_ASIDBITS)),
 	ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
 					ID_AA64MMFR1_EL1_HCX |
diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
index 1d65f4a09e6f..322b9d3b0125 100644
--- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
+++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
@@ -146,6 +146,9 @@ static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] = {
 static const struct reg_ftr_bits ftr_id_aa64mmfr0_el1[] = {
 	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, ECV, 0),
 	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, EXS, 0),
+	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN4_2, 1),
+	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN64_2, 1),
+	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN16_2, 1),
 	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN4, 0),
 	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN64, 0),
 	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN16, 0),
-- 
2.42.0



From cristian.marussi at arm.com  Thu Mar  6 10:43:45 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Thu, 6 Mar 2025 18:43:45 +0000
Subject: [Bug report] Memory leak in scmi_device_create
In-Reply-To: <Z8nK3uFkspy61yjP@arm.com>
References: <Z8g8vhS9rqQ_ez48@google.com>
 <Z8iFeEWq16pNQdMa@pluto>
 <Z8mCbc2Z2QGd3f8M@google.com>
 <Z8my4MZ-In0ibxVY@arm.com>
 <Z8nDj129ZVeZBVSp@pluto>
 <Z8nK3uFkspy61yjP@arm.com>
Message-ID: <Z8ns4T6pas9DEy8B@pluto>

On Thu, Mar 06, 2025 at 04:18:38PM +0000, Catalin Marinas wrote:
> On Thu, Mar 06, 2025 at 03:47:27PM +0000, Cristian Marussi wrote:
> > On Thu, Mar 06, 2025 at 02:36:16PM +0000, Catalin Marinas wrote:
> > > This loop in scmi_device_create() looks strange:
> > > 
> > > 	list_for_each_entry(rdev, phead, node) {
> > > 		struct scmi_device *sdev;
> > > 
> > > 		sdev = __scmi_device_create(np, parent,
> > > 					    rdev->id_table->protocol_id,
> > > 					    rdev->id_table->name);
> > > 		/* Report errors and carry on... */
> > > 		if (sdev)
> > > 			scmi_dev = sdev;
> > > 		else
> > > 			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
> > > 			       of_node_full_name(parent->of_node),
> > > 			       rdev->id_table->protocol_id,
> > > 			       rdev->id_table->name);
> > > 	}
> > > 
> > > We can override scmi_dev a few times in the loop and lose the previous
> > > sdev allocations. Is this intended?
> > 
> > Yes...it is weird..but by design I would say :P ...
> > 
> > ...because this is called to instantiate one single device OR instantiate at
> > once all the multiple devices needed for a protocol: in this latter case it
> > returns just one of the created devices to signal success or NULL if all the
> > devices' creation failed....we dont need to keep the allocated devices references
> > anyway here since on success those devices are now referenced and kept on the
> > SCMI bus, so they can be searched/scanned/destroyed from there.
> 
> Not sure why the pointer isn't found, device_add() should link it with
> the parent. Unless something else fails, the parent is freed and the
> linked devices unreachable. I'm not familiar at all with this code, I
> just saw kmemleak and thought of replying.
> 
> The loop is still weird, scmi_chan_setup() seems to use the pointer to
> scmi_device for something more meaningful than a pass/fail check. Also
> the overall result is based only on what the last __scmi_device_create()
> return value was, irrespective of the previous iterations of the loop.
> You do have a pr_err() but no early bailing out of the loop on failure.
> I'm curious if there are any SCMI errors in the Alice's kernel log.
> 

Yes, the weirdness comes from the fact such function is used alternatively
to create a single named device (and make some use of it, like in
scmi_chan_setup) OR to create a bunch of devices for the same protocol
when no specific device is asked for (name==NULL)...anyway the case at
hand that kmemleak complains about does NOT pass through that weird loop...

...good news is, I was able to reproduce a similar report consistently
with a load/unload/load sequence....the culprit is that when looking for
a device to destroy on unload, the SCMI bus uses device_find_child()
and that bumps the device refcnt implicitly...as a result when the device
is destroyed the refcnt is NEVER found as zero and so NO device_release
is ever called...this results in dev->p private_data to be never released
and that is what kmemleak spotted (at the start of teh chain):


unreferenced object 0xffff00000f583800 (size 512):
      comm "insmod", pid 227, jiffies 4294912190
      hex dump (first 32 bytes):
        00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
        ff ff ff ff ff ff ff ff 60 36 1d 8a 00 80 ff ff  ........`6......
      backtrace (crc 114e2eed):
        kmemleak_alloc+0xbc/0xd8
        __kmalloc_cache_noprof+0x2dc/0x398
        device_add+0x954/0x12d0
        device_register+0x28/0x40
        __scmi_device_create.part.0+0x1bc/0x380
        scmi_device_create+0x2d0/0x390
        scmi_create_protocol_devices+0x74/0xf8
        scmi_device_request_notifier+0x1f8/0x2a8
        notifier_call_chain+0x110/0x3b0
        blocking_notifier_call_chain+0x70/0xb0
        scmi_driver_register+0x350/0x7f0
        0xffff80000a3b3038
        do_one_initcall+0x12c/0x730
        do_init_module+0x1dc/0x640
        load_module+0x4b20/0x5b70
        init_module_from_file+0xec/0x158
    
    $ ./scripts/faddr2line ./vmlinux device_add+0x954/0x12d0
    device_add+0x954/0x12d0:
    kmalloc_noprof at include/linux/slab.h:901
    (inlined by) kzalloc_noprof at include/linux/slab.h:1037
    (inlined by) device_private_init at drivers/base/core.c:3510
    (inlined by) device_add at drivers/base/core.c:3561

I am posting a fix.

Thanks for the report and the help.
Any feedback and testing is much welcomed :D

Cristian


From cristian.marussi at arm.com  Thu Mar  6 10:54:47 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Thu,  6 Mar 2025 18:54:47 +0000
Subject: [PATCH] firmware: arm_scmi: Balance device refcount when destroying devices
Message-ID: <20250306185447.2039336-1-cristian.marussi@arm.com>

Using device_find_child() to lookup the proper SCMI device to destroy
causes an unbalance in device refcount, since device_find_child() calls an
implicit get_device(): this, in turns, inhibits the call of the provided
release methods upon devices destruction.

As a consequence, one of the structures that is not freed properly upon
destruction is the internal struct device_private dev->p populated by the
drivers subsystem core.

KMemleak detects this situation since loading/unloding some SCMI driver
causes related devices to be created/destroyed without calling any
device_release method.

unreferenced object 0xffff00000f583800 (size 512):
  comm "insmod", pid 227, jiffies 4294912190
  hex dump (first 32 bytes):
    00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
    ff ff ff ff ff ff ff ff 60 36 1d 8a 00 80 ff ff  ........`6......
  backtrace (crc 114e2eed):
    kmemleak_alloc+0xbc/0xd8
    __kmalloc_cache_noprof+0x2dc/0x398
    device_add+0x954/0x12d0
    device_register+0x28/0x40
    __scmi_device_create.part.0+0x1bc/0x380
    scmi_device_create+0x2d0/0x390
    scmi_create_protocol_devices+0x74/0xf8
    scmi_device_request_notifier+0x1f8/0x2a8
    notifier_call_chain+0x110/0x3b0
    blocking_notifier_call_chain+0x70/0xb0
    scmi_driver_register+0x350/0x7f0
    0xffff80000a3b3038
    do_one_initcall+0x12c/0x730
    do_init_module+0x1dc/0x640
    load_module+0x4b20/0x5b70
    init_module_from_file+0xec/0x158

$ ./scripts/faddr2line ./vmlinux device_add+0x954/0x12d0
device_add+0x954/0x12d0:
kmalloc_noprof at include/linux/slab.h:901
(inlined by) kzalloc_noprof at include/linux/slab.h:1037
(inlined by) device_private_init at drivers/base/core.c:3510
(inlined by) device_add at drivers/base/core.c:3561

Balance device refcount by issuing a put_device() on devices found via
device_find_child().

Reported-by: Alice Ryhl <aliceryhl at google.com>
Closes: https://lore.kernel.org/linux-arm-kernel/Z8nK3uFkspy61yjP at arm.com/T/#mc1f73a0ea5e41014fa145147b7b839fc988ada8f
CC: Sudeep Holla <sudeep.holla at arm.com>
CC: Catalin Marinas <catalin.marinas at arm.com>
Fixes: d4f9dddd21f3 ("firmware: arm_scmi: Add dynamic scmi devices creation")
Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 725c7c565333..7732e46d8a95 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -271,6 +271,9 @@ static struct scmi_device *scmi_child_dev_find(struct device *parent,
 	if (!dev)
 		return NULL;
 
+	/* Drop the refcnt bumped implicitly by device_find_child */
+	put_device(dev);
+
 	return to_scmi_dev(dev);
 }
 
-- 
2.47.0



From mhklinux at outlook.com  Thu Mar  6 10:57:00 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 18:57:00 +0000
Subject: [PATCH v5 01/10] hyperv: Convert Hyper-V status codes to strings
In-Reply-To: <9123b404-f6f8-464b-bad8-b793ea6fb21e@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <SN6PR02MB4157629A6197A8A6C992BB75D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <9123b404-f6f8-464b-bad8-b793ea6fb21e@linux.microsoft.com>
Message-ID: <SN6PR02MB4157C148444E429FB6376C6ED4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Thursday, March 6, 2025 10:41 AM
> 
> On 3/6/2025 10:09 AM, Michael Kelley wrote:
> > From: Michael Kelley <mhklinux at outlook.com> Sent: Thursday, March 6, 2025 9:58 AM
> >

[snip]

> >> I've read through the other comments on this patch. I definitely vote
> >> for outputting both the hex code along with a string translation, which
> >> could be empty if the hex code is unrecognized by the translation code.
> >>
> >> I can see providing something like hv_hvcall_err() as Nuno proposed, since
> >> that standardizes the text output. But I wonder if it would be too limiting.
> >> For example, in the changes above, both hv_call_add_logical_proc() and
> >> hv_call_create_vp() output additional debugging values, which we probably
> >> don't want to give up.
> >>
> >> Lastly, from an implementation standpoint, rather than using a big
> >> switch statement, build a static array of entries that each have the
> >> hex code and string equivalent. Then hv_result_to_string() loops through
> >> the array looking for a match. This won't be any slower than the big switch
> >> statement. I've seen other places in the kernel where string names are
> >> output, and looking up the strings in a static array is the typical approach.
> >> You'll have to work through the details and see if avoids being too clumsy,
> >> but I think it will be OK.
> >>
> >
> > Better yet, also include the translated errno in each static array entry.
> > Then hv_result_to_errno() can do the same kind of lookup instead of
> > having its own switch statement. I did a quick look to see if the two
> > functions might be combined to do only a single lookup, but that looks
> > somewhat clumsy unless someone else spots a better way to handle it.
> > The cost of doing two lookups doesn't really matter in an error case.
> >
> > FWIW, hv_result_to_errno() and the new hv_result_to_string() are both
> > slightly misnamed. The input argument is a full 64-bit hv_status, not the
> > smaller 16-bit result field. hv_status_to_errno() and hv_status_to_string()
> > would be more precise.
> >
> Hmm, well I'll admit I was and still am rather confused on this point.
> 
> In the TLFS (section 3.8) the entire 64-bit return value is called the  "hypercall result value".
> The 16-bit HV_STATUS part is *also* called the "result" in this section.
> Later, in section 3.12, the 16-bit field is referred to as a "status value field".
> Furthermore, the name of the 16-bit value, itself, is HV_STATUS.
> 
> Despite the inconsistency, in my mind it makes the most sense that the
> 16-bit HV_STATUS part the "status" and the entire 64-bit return value the
> "result". I am aware that elsewhere (and in the driver patches in this
> series), the name "status" is used to refer to the entire 64-bit return
> value.
> 
> These functions were actually called hv_status_to_errno() and hv_status_to_string()
> in the past, but I changed them to use "result" by following my own logic, and I
> thought this also matched the naming of hv_result() and hv_result_success().
> However I now realize that the "result" in these names refers to the *output* of
> these functions... they take a u64 status as a parameter after all..
> 
> So in the end I'm rather bothered by this whole situation. I can change these
> names back to "status" (although hv_result_to_errno() is already merged, I
> could send a fixup), or I could keep "result", which I think is a more
> logical name for the 64-bit value, even though it somewhat contradicts how
> the term is already used in the kernel.
> 
> Given it doesn't seem to be well-defined in the first place, I'm not really
> sure the best route.
> 

Hmmm. You are right. I had in my mind that "status" is the full 64-bit
value, and "result" is the 16-bit error code. But that's certainly not
always the case. And as you point out, it doesn't comport with the TLFS,
and the TLFS itself is not consistent in the terminology.

Ignore my comment. The difference doesn't have any real impact. Leave
the sorting out for some other time. :-)

Michael

From mhklinux at outlook.com  Thu Mar  6 11:05:42 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 19:05:42 +0000
Subject: [PATCH v5 03/10] arm64/hyperv: Add some missing functions to
 arm64
In-Reply-To: <2fee888a-4f81-40aa-9545-617a49a7fb30@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-4-git-send-email-nunodasneves@linux.microsoft.com>
 <5f3d660d-fe2e-4ac1-94a7-66d6c8ffe579@linux.microsoft.com>
 <2fee888a-4f81-40aa-9545-617a49a7fb30@linux.microsoft.com>
Message-ID: <SN6PR02MB41579F4147561B96A2C1C057D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Thursday, February 27, 2025 4:21 PM
> 
> On 2/26/2025 9:56 PM, Easwar Hariharan wrote:
> > On 2/26/2025 3:07 PM, Nuno Das Neves wrote:
> >> These non-nested msr and fast hypercall functions are present in x86,
> >> but they must be available in both architetures for the root partition
> >
> > nit: *architectures*
> >
> >
> Thanks!
> 
> >> driver code.
> >>
> >> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >> ---
> >>  arch/arm64/hyperv/hv_core.c       | 17 +++++++++++++++++
> >>  arch/arm64/include/asm/mshyperv.h | 12 ++++++++++++
> >>  include/asm-generic/mshyperv.h    |  2 ++
> >>  3 files changed, 31 insertions(+)
> >>
> >> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
> >> index 69004f619c57..e33a9e3c366a 100644
> >> --- a/arch/arm64/hyperv/hv_core.c
> >> +++ b/arch/arm64/hyperv/hv_core.c
> >> @@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
> >>  }
> >>  EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
> >>
> >> +/*
> >> + * hv_do_fast_hypercall16 -- Invoke the specified hypercall
> >> + * with arguments in registers instead of physical memory.
> >> + * Avoids the overhead of virt_to_phys for simple hypercalls.
> >> + */
> >> +u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
> >> +{
> >> +	struct arm_smccc_res	res;
> >> +	u64			control;
> >> +
> >> +	control = (u64)code | HV_HYPERCALL_FAST_BIT;
> >> +
> >> +	arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
> >> +	return res.a0;
> >> +}
> >> +EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
> >> +
> >
> > I'd like this to have been in arch/arm64/include/asm/mshyperv.h like its x86
> > counterpart, but that's just my personal liking of symmetry. I see why it's here
> > with its slow and 8-byte brethren.
> >
> Good point, I don't see a good reason this can't be in the header.

I was trying to remember if there was some reason I originally put
hv_do_hypercall() and hv_do_fast_hypercall8() in the .c file instead of
the header like on x86. But I don't remember a reason. During
development, the code changed several times, and there might have
been a reason that didn't persistent in the version that was finally
accepted upstream.

My only comment is that hv_do_hypercall() and the 8 and 16 "fast"
versions should probably stay together one place on the arm64 side,
even if it doesn't match x86.

> 
> >>  /*
> >>   * Set a single VP register to a 64-bit value.
> >>   */
> >> diff --git a/arch/arm64/include/asm/mshyperv.h
> b/arch/arm64/include/asm/mshyperv.h
> >> index 2e2f83bafcfb..2a900ba00622 100644
> >> --- a/arch/arm64/include/asm/mshyperv.h
> >> +++ b/arch/arm64/include/asm/mshyperv.h
> >> @@ -40,6 +40,18 @@ static inline u64 hv_get_msr(unsigned int reg)
> >>  	return hv_get_vpreg(reg);
> >>  }
> >>
> >> +/*
> >> + * Nested is not supported on arm64
> >> + */
> >> +static inline void hv_set_non_nested_msr(unsigned int reg, u64 value)
> >> +{
> >> +	hv_set_msr(reg, value);
> >> +}
> >
> > empty line preferred here, also reported by checkpatch
> >
> Good point, missed that one...
> 
> >> +static inline u64 hv_get_non_nested_msr(unsigned int reg)
> >> +{
> >> +	return hv_get_msr(reg);
> >> +}
> >> +
> >>  /* SMCCC hypercall parameters */
> >>  #define HV_SMCCC_FUNC_NUMBER	1
> >>  #define HV_FUNC_ID	ARM_SMCCC_CALL_VAL(			\
> >> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> >> index c020d5d0ec2a..258034dfd829 100644
> >> --- a/include/asm-generic/mshyperv.h
> >> +++ b/include/asm-generic/mshyperv.h
> >> @@ -72,6 +72,8 @@ extern void * __percpu *hyperv_pcpu_output_arg;
> >>
> >>  extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
> >>  extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
> >> +extern u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
> >> +
> >
> > checkpatch warns against putting externs in header files, and FWIW, if
> hv_do_fast_hypercall16()
> > for arm64 were in arch/arm64/include/asm/mshyperv.h like its x86 counterpart, you
> probably
> > wouldn't need this?
> >
> Yes I wondered about that warning. That's true, if I just put it in the arm64 header
> then this won't be needed at all, so I might just do that!

I always thought the checkpatch warning was simply that "extern" on a function
declaration is superfluous. You can omit "extern" and nothing changes. Of
course, the same is not true for data items.

Michael

> 
> >>  bool hv_isolation_type_snp(void);
> >>  bool hv_isolation_type_tdx(void);
> >>


From dan.carpenter at linaro.org  Thu Mar  6 11:07:20 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Thu, 6 Mar 2025 22:07:20 +0300
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
Message-ID: <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>

On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> Hi Mathis,
> 
> Thanks for the patch.
> 
> On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > The imx-media-csi driver requires upstream camera drivers to implement
> > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > implement this function are not usable on the i.MX6.
> > 
> > The docs for get_mbus_config [1] say:
> > @get_mbus_config: get the media bus configuration of a remote sub-device.
> >             The media bus configuration is usually retrieved from the
> >             firmware interface at sub-device probe time, immediately
> >             applied to the hardware and eventually adjusted by the
> >             driver.
> > 
> > Currently, the imx-media-csi driver is not incorporating the information
> > from the firmware interface and therefore relies on the implementation of
> > get_mbus_config by the camera driver.
> > 
> > To be compatible with camera drivers not implementing get_mbus_config
> > (which is the usual case), use the bus information from the fw interface:
> > 
> > The camera does not necessarily has a direct media bus link to the CSI as
> > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > between them on the media pipeline.
> > The CSI driver already implements the functionality to find the connected
> > camera sub-device to call get_mbus_config on it.
> > 
> > At this point the driver is modified as follows:
> > In the case that get_mbus_config is not implemented by the upstream
> > camera, try to get its endpoint configuration from the firmware interface
> > usign v4l2_fwnode_endpoint_parse.
> > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > configuration.
> > For all other mbus_types, return an error.
> > 
> > Note that parsing the mbus_config from the fw interface is not done during
> > probing because the camera that's connected to the CSI can change based on
> > the selected input of the video-mux at runtime.
> > 
> > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > [1] include/media/v4l2-subdev.h - line 814
> > 
> > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > ---
> >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> >  1 file changed, 32 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > index 3edbc57be2ca..394a9321a10b 100644
> > --- a/drivers/staging/media/imx/imx-media-csi.c
> > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> >  {
> >  	struct v4l2_subdev *sd, *remote_sd;
> >  	struct media_pad *remote_pad;
> > +	struct fwnode_handle *ep_node;
> > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> 
> Are there any defaults in DT bindings (other than 0's)? Also initialising a
> field to zero this way is redundant, just use {}.
> 

I was going to respond in much the same way.  This is equivalen to:

struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };

> >  	int ret;
> >  
> >  	if (!priv->src_sd)
> > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> >  
> >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> >  			       remote_pad->index, mbus_cfg);
> > -	if (ret == -ENOIOCTLCMD)
> > -		v4l2_err(&priv->sd,
> > -			 "entity %s does not implement get_mbus_config()\n",
> > -			 remote_pad->entity->name);
> > +	if (ret == -ENOIOCTLCMD) {
> 
> 	if (!ret)
> 		return 0;
> 
> And you can unindent the rest.

I was going to say this too but then I thought actually this needs to
be:

	if (ret != -ENOIOCTLCMD)
		return ret;

Which is weird.  Better to break all the new code into a separate
helper function.

	if (ret == -ENOIOCTLCMD)
		ret = parse_fw_link_config_stuff();

	return ret;

regards,
dan carpenter




From broonie at kernel.org  Thu Mar  6 11:09:43 2025
From: broonie at kernel.org (Mark Brown)
Date: Thu, 06 Mar 2025 19:09:43 +0000
Subject: [PATCH -next] spi: stm32: Remove unnecessary print function
 dev_err()
In-Reply-To: <20250306024716.27856-1-jiapeng.chong@linux.alibaba.com>
References: <20250306024716.27856-1-jiapeng.chong@linux.alibaba.com>
Message-ID: <174128818323.185591.2600414701558020572.b4-ty@kernel.org>

On Thu, 06 Mar 2025 10:47:16 +0800, Jiapeng Chong wrote:
> The print function dev_err() is redundant because platform_get_irq()
> already prints an error.
> 
> ./drivers/spi/spi-stm32-ospi.c:798:2-9: line 798 is redundant because platform_get_irq() already prints an error.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: stm32: Remove unnecessary print function dev_err()
      commit: 3707fd9c383fc7ae19733a3ad2e5a82bf86370a0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From mhklinux at outlook.com  Thu Mar  6 11:12:43 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 19:12:43 +0000
Subject: [PATCH v5 04/10] hyperv: Introduce hv_recommend_using_aeoi()
In-Reply-To: <1740611284-27506-5-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-5-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157A8F9C0DAB7AF7D50EDBBD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> 
> Factor out the check for enabling auto eoi, to be reused in root
> partition code.

Reviewed-by: Michael Kelley <mhklinux at outlook.com>

> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---
>  drivers/hv/hv.c                | 12 +-----------
>  include/asm-generic/mshyperv.h | 13 +++++++++++++
>  2 files changed, 14 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
> index a38f84548bc2..308c8f279df8 100644
> --- a/drivers/hv/hv.c
> +++ b/drivers/hv/hv.c
> @@ -313,17 +313,7 @@ void hv_synic_enable_regs(unsigned int cpu)
> 
>  	shared_sint.vector = vmbus_interrupt;
>  	shared_sint.masked = false;
> -
> -	/*
> -	 * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
> -	 * it doesn't provide a recommendation flag and AEOI must be disabled.
> -	 */
> -#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
> -	shared_sint.auto_eoi =
> -			!(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
> -#else
> -	shared_sint.auto_eoi = 0;
> -#endif
> +	shared_sint.auto_eoi = hv_recommend_using_aeoi();
>  	hv_set_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
> 
>  	/* Enable the global synic bit */
> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> index 258034dfd829..1f46d19a16aa 100644
> --- a/include/asm-generic/mshyperv.h
> +++ b/include/asm-generic/mshyperv.h
> @@ -77,6 +77,19 @@ extern u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64
> input2);
>  bool hv_isolation_type_snp(void);
>  bool hv_isolation_type_tdx(void);
> 
> +/*
> + * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
> + * it doesn't provide a recommendation flag and AEOI must be disabled.
> + */
> +static inline bool hv_recommend_using_aeoi(void)
> +{
> +#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
> +	return !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
> +#else
> +	return false;
> +#endif
> +}
> +
>  static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node)
>  {
>  	struct hv_proximity_domain_info pxm_info = {};
> --
> 2.34.1



From mhklinux at outlook.com  Thu Mar  6 11:16:33 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 19:16:33 +0000
Subject: [PATCH v5 05/10] acpi: numa: Export node_to_pxm()
In-Reply-To: <1740611284-27506-6-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-6-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB41571D453D4835871A98023DD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> 
> node_to_pxm() is used by hv_numa_node_to_pxm_info().
> That helper will be used by Hyper-V root partition module code
> when CONFIG_MSHV_ROOT=m.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>

Reviewed-by: Michael Kelley <mhklinux at outlook.com>

> ---
>  drivers/acpi/numa/srat.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
> index 00ac0d7bb8c9..ce815d7cb8f6 100644
> --- a/drivers/acpi/numa/srat.c
> +++ b/drivers/acpi/numa/srat.c
> @@ -51,6 +51,7 @@ int node_to_pxm(int node)
>  		return PXM_INVAL;
>  	return node_to_pxm_map[node];
>  }
> +EXPORT_SYMBOL_GPL(node_to_pxm);
> 
>  static void __acpi_map_pxm_to_node(int pxm, int node)
>  {
> --
> 2.34.1



From thierry.reding at gmail.com  Thu Mar  6 11:19:46 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Thu, 6 Mar 2025 20:19:46 +0100
Subject: [PATCH v4 4/4] arm: defconfig: drop RT_GROUP_SCHED=y from
 bcm2835/tegra/omap2plus
In-Reply-To: <20250115-fix-riscv-rt_group_sched-v4-4-607606fe73a5@coelacanthus.name>
References: <20250115-fix-riscv-rt_group_sched-v4-0-607606fe73a5@coelacanthus.name>
 <20250115-fix-riscv-rt_group_sched-v4-4-607606fe73a5@coelacanthus.name>
Message-ID: <t2dustbykx2qd24wazjeiw5hch5nwr6z2ewmaf4srg6r2grwrf@rdw47chzkef2>

On Wed, Jan 15, 2025 at 04:41:23AM +0800, Celeste Liu wrote:
> Commit 673ce00c5d6c ("ARM: omap2plus_defconfig: Add support for distros
> with systemd") said it's because of recommendation from systemd. But
> systemd changed their recommendation later.[1]
> 
> For cgroup v1, if turned on, and there's any cgroup in the "cpu" hierarchy it
> needs an RT budget assigned, otherwise the processes in it will not be able to
> get RT at all. The problem with RT group scheduling is that it requires the
> budget assigned but there's no way we could assign a default budget, since the
> values to assign are both upper and lower time limits, are absolute, and need to
> be sum up to < 1 for each individal cgroup. That means we cannot really come up
> with values that would work by default in the general case.[2]
> 
> For cgroup v2, it's almost unusable as well. If it turned on, the cpu controller
> can only be enabled when all RT processes are in the root cgroup. But it will
> lose the benefits of cgroup v2 if all RT process were placed in the same cgroup.
> 
> Red Hat, Gentoo, Arch Linux and Debian all disable it. systemd also doesn't
> support it.
> 
> [1]: https://github.com/systemd/systemd/commit/f4e74be1856b3ac058acbf1be321c31d5299f69f
> [2]: https://bugzilla.redhat.com/show_bug.cgi?id=1229700
> 
> Tested-by: Stefan Wahren <wahrenst at gmx.net>
> Acked-by: Kevin Hilman <khilman at baylibre.com>
> Acked-by: Thierry Reding <treding at nvidia.com>
> Signed-off-by: Celeste Liu <uwu at coelacanthus.name>
> ---
>  arch/arm/configs/bcm2835_defconfig   | 1 -
>  arch/arm/configs/omap2plus_defconfig | 1 -
>  arch/arm/configs/tegra_defconfig     | 1 -
>  3 files changed, 3 deletions(-)

Hi Arnd,

is this something that you could pick up? I think so far only the RISC-V
patch was picked up, but nobody seems to feel responsible for the ARM
patch here.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250306/052c60d8/attachment.sig>

From cki-project at redhat.com  Thu Mar  6 11:23:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 19:23:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <91107.125030614230701377@us-mta-137.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703590650

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703590650-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From mhklinux at outlook.com  Thu Mar  6 11:23:15 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 6 Mar 2025 19:23:15 +0000
Subject: [PATCH v5 06/10] Drivers/hv: Export some functions for use by
 root partition module
In-Reply-To: <1740611284-27506-7-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-7-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB415706E75693B821FAF0A231D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 

Nit: For the patch Subject line, use prefix "Drivers: hv:" instead of with a slash.
That's what we usually use and what you have used for other patches in this
series.

> get_hypervisor_version, hv_call_deposit_pages, hv_call_create_vp,
> hv_call_deposit_pages, and hv_call_create_vp are all needed in module
> with CONFIG_MSHV_ROOT=m.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>

Modulo the nit:

Reviewed-by: Michael Kelley <mhklinux at outlook.com>

> ---
>  arch/arm64/hyperv/mshyperv.c   | 1 +
>  arch/x86/kernel/cpu/mshyperv.c | 1 +
>  drivers/hv/hv_common.c         | 1 +
>  drivers/hv/hv_proc.c           | 3 ++-
>  4 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index 2265ea5ce5ad..4e27cc29c79e 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -26,6 +26,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info
> *info)
> 
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
> 
>  static int __init hyperv_init(void)
>  {
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 2c29dfd6de19..0116d0e96ef9 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -420,6 +420,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info
> *info)
> 
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
> 
>  static void __init ms_hyperv_init_platform(void)
>  {
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index ce20818688fe..252fd66ad4db 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -717,6 +717,7 @@ int hv_result_to_errno(u64 status)
>  	}
>  	return -EIO;
>  }
> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> 
>  void hv_identify_partition_type(void)
>  {
> diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
> index 8fc30f509fa7..20c8cee81e2b 100644
> --- a/drivers/hv/hv_proc.c
> +++ b/drivers/hv/hv_proc.c
> @@ -108,6 +108,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
>  	kfree(counts);
>  	return ret;
>  }
> +EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
> 
>  int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
>  {
> @@ -194,4 +195,4 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
> 
>  	return ret;
>  }
> -
> +EXPORT_SYMBOL_GPL(hv_call_create_vp);
> --
> 2.34.1



From nicolas.frattaroli at collabora.com  Thu Mar  6 11:29:23 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Thu, 06 Mar 2025 20:29:23 +0100
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
Message-ID: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>

Despite the compatible already being listed in the bindings, the PHY
driver never gained explicit support for it. This is especially a
problem because the explicitly listed PHY addresses need to be specified
for each SoC.

To solve this, add the compatible, and a PHY config, with the address
gleaned from rk3576.dtsi.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
I thought this must've been already submitted somewhere, but it wasn't
in linux-next and searching for the modified file on lore also didn't
yield any results. I guess this slipped through the cracks, and
torpedoes HDMI support for RK3576 entirely until merged, so it'd be
great if this could be merged in time for 6.15.

Let me know if I'm just very confused and this is already handled in
some other series that's about to be applied.
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index f88369864c50e4563834ccbb26f1f9f440e99271..fe7c057483563686b8076cf2ce562440cfa6fe55 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -2017,6 +2017,13 @@ static const struct dev_pm_ops rk_hdptx_phy_pm_ops = {
 		       rk_hdptx_phy_runtime_resume, NULL)
 };
 
+static const struct rk_hdptx_phy_cfg rk3576_hdptx_phy_cfgs = {
+	.num_phys = 1,
+	.phy_ids = {
+		0x2b000000,
+	},
+};
+
 static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = {
 	.num_phys = 2,
 	.phy_ids = {
@@ -2026,6 +2033,10 @@ static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = {
 };
 
 static const struct of_device_id rk_hdptx_phy_of_match[] = {
+	{
+		.compatible = "rockchip,rk3576-hdptx-phy",
+		.data = &rk3576_hdptx_phy_cfgs
+	},
 	{
 		.compatible = "rockchip,rk3588-hdptx-phy",
 		.data = &rk3588_hdptx_phy_cfgs

---
base-commit: a03be51d680391ba113e2e22b38743c276b6e2fa
change-id: 20250306-rk3576-hdptx-phy-4ef6630166cd

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From Frank.Li at nxp.com  Thu Mar  6 11:30:14 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 14:30:14 -0500
Subject: [PATCH] arm64: dtsi: imx93: add alias id for bbnsm_rtc
Message-ID: <20250306193014.490091-1-Frank.Li@nxp.com>

From: Joy Zou <joy.zou at nxp.com>

Add rtc0 alias to set bbnsm_rtc as the default rtc.

Signed-off-by: Joy Zou <joy.zou at nxp.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx93.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index 56766fdb0b1e5..7d9aa15ebf5d0 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -34,6 +34,7 @@ aliases {
 		mmc0 = &usdhc1;
 		mmc1 = &usdhc2;
 		mmc2 = &usdhc3;
+		rtc0 = &bbnsm_rtc;
 		serial0 = &lpuart1;
 		serial1 = &lpuart2;
 		serial2 = &lpuart3;
-- 
2.34.1



From rostedt at goodmis.org  Thu Mar  6 11:56:07 2025
From: rostedt at goodmis.org (Steven Rostedt)
Date: Thu, 6 Mar 2025 14:56:07 -0500
Subject: [PATCH 02/11] ring-buffer: Expose buffer_data_page material
In-Reply-To: <20250224121353.98697-3-vdonnefort@google.com>
References: <20250224121353.98697-1-vdonnefort@google.com>
	<20250224121353.98697-3-vdonnefort@google.com>
Message-ID: <20250306145607.0aa91e22@gandalf.local.home>

On Mon, 24 Feb 2025 12:13:44 +0000
Vincent Donnefort <vdonnefort at google.com> wrote:

> @@ -61,11 +65,50 @@ enum ring_buffer_type {
>  	RINGBUF_TYPE_TIME_STAMP,
>  };
>  
> +#define TS_SHIFT        27
> +#define TS_MASK         ((1ULL << TS_SHIFT) - 1)
> +#define TS_DELTA_TEST   (~TS_MASK)

By moving this to include/linux you need to add a prefix to prevent name
space conflicts.

 RB_TS_SHIFT
 RB_TS_MASK
 RB_TS_DELTA_TEST

-- Steve


> +
> +/*
> + * We need to fit the time_stamp delta into 27 bits.
> + */
> +static inline bool test_time_stamp(u64 delta)
> +{
> +	return !!(delta & TS_DELTA_TEST);
> +}
> +


From sven at svenpeter.dev  Thu Mar  6 11:56:36 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Thu, 06 Mar 2025 20:56:36 +0100
Subject: [PATCH RESEND v2 0/5] arm64: dts: apple: Add DWI backlight dt
 nodes
In-Reply-To: <20250228-dwi-dt-v2-0-69e450bc4bfb@gmail.com>
References: <20250228-dwi-dt-v2-0-69e450bc4bfb@gmail.com>
Message-ID: <174129099660.23709.379545131530961336.b4-ty@svenpeter.dev>

On Fri, 28 Feb 2025 12:32:11 +0800, Nick Chan wrote:
> Add device tree nodes for DWI backlight found on some Apple iPhones, iPads
> and iPod touches. Not all devices have this feature, as some devices
> instead have their backlights directly connected to the WLED output of a
> PMU or use self-emissive panels.
> 
> Resned because a network error occured and some patches failed to send.
> 
> [...]

Applied to git at github.com:AsahiLinux/linux.git (asahi-soc/dt), thanks!

[1/5] arm64: dts: apple: s5l8960x: Add backlight nodes
      https://github.com/AsahiLinux/linux/commit/0f8f64b2329f
[2/5] arm64: dts: apple: t7000: Add backlight nodes
      https://github.com/AsahiLinux/linux/commit/897359ae3c50
[3/5] arm64: dts: apple: s800-0-3: Add backlight nodes
      https://github.com/AsahiLinux/linux/commit/4384b6c781bc
[4/5] arm64: dts: apple: t8010: Add backlight nodes
      https://github.com/AsahiLinux/linux/commit/074db7d6f51b
[5/5] arm64: dts: apple: t8015: Add backlight nodes
      https://github.com/AsahiLinux/linux/commit/e1bc21d8f8fd

Best regards,
-- 
Sven Peter <sven at svenpeter.dev>




From nfraprado at collabora.com  Thu Mar  6 11:52:14 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Thu, 06 Mar 2025 16:52:14 -0300
Subject: [PATCH v3 0/4] Allow retrieving accessory detection reference on
 MT8188
Message-ID: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>

This series enables the MT8188-MT6359 sound driver to retrieve the
MT6359 ACCDET sound component from a mediatek,accdet DT property, which
allows detecting jack insertion/removal.

Patch 1 describes the new property in the binding. Patch 2 implements
the sound component retrieval in the common MTK soundcard driver. Patch
4 updates the MT8188-MT6359 sound driver to register the audio jack and
initialize the ACCDET driver for detection, if the property is present.

Patch 3 adds a stub to prevent a linker failure in case the
MT6359-ACCDET config is disabled.

Tested on the Genio 700 EVK board.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
Changes in v3:
- Removed the config select for CONFIG_SND_SOC_MT6359_ACCDET
- Added patch 3 with stub for mt6359_accdet_enable_jack_detect()
- Fixed return checks for mediatek,accdet handling to check for non-null
  rather than !IS_ERR(), and added error messages
- Link to v2: https://lore.kernel.org/r/20250304-mt8188-accdet-v2-0-27f496c4aede at collabora.com

Changes in v2:
- Added CONFIG_SND_SOC_MT6359_ACCDET select in
  CONFIG_SND_SOC_MT8188_MT6359 to avoid build failure
- Clarified in mediatek,accdet dt-binding and commit description that
  the property should only be present if the accdet is actually used
- Link to v1: https://lore.kernel.org/r/20250214-mt8188-accdet-v1-0-6bbd5483855b at collabora.com

---
N?colas F. R. A. Prado (4):
      ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet
      ASoC: mediatek: common: Handle mediatek,accdet property
      ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect
      ASoC: mediatek: mt8188-mt6359: Add accdet headset jack detect support

 .../bindings/sound/mediatek,mt8188-mt6359.yaml     |  8 ++++
 sound/soc/codecs/mt6359-accdet.h                   |  9 +++++
 sound/soc/mediatek/common/mtk-soc-card.h           |  1 +
 sound/soc/mediatek/common/mtk-soundcard-driver.c   | 19 +++++++++-
 sound/soc/mediatek/mt8188/mt8188-mt6359.c          | 43 ++++++++++++++++++++++
 5 files changed, 79 insertions(+), 1 deletion(-)
---
base-commit: 565351ae7e0cee80e9b5ed84452a5b13644ffc4d
change-id: 20250214-mt8188-accdet-4deabb85534d

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Thu Mar  6 11:52:15 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Thu, 06 Mar 2025 16:52:15 -0300
Subject: [PATCH v3 1/4] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add
 mediatek,accdet
In-Reply-To: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
References: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
Message-ID: <20250306-mt8188-accdet-v3-1-7828e835ff4b@collabora.com>

Add a mediatek,accdet phandle property to allow getting a reference to
the MT6359 ACCDET block, which is responsible for detecting jack
insertion/removal.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml         | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
index 8c77e7f68ad7b6f5b88b53cedccb291139a2eeea..76d5a437dc8f4ad1f31c21f84304bad326b0facd 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
@@ -40,6 +40,14 @@ properties:
       hardware that provides additional audio functionalities if present.
       The AFE will link to ADSP when the phandle is provided.
 
+  mediatek,accdet:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      The phandle to the MT6359 accessory detection block, which detects audio
+      jack insertion and removal. This property should only be present if the
+      accdet block is actually wired to the audio jack pins and to be used for
+      jack detection.
+
 patternProperties:
   "^dai-link-[0-9]+$":
     type: object

-- 
2.48.1



From nfraprado at collabora.com  Thu Mar  6 11:52:16 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Thu, 06 Mar 2025 16:52:16 -0300
Subject: [PATCH v3 2/4] ASoC: mediatek: common: Handle mediatek,accdet
 property
In-Reply-To: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
References: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
Message-ID: <20250306-mt8188-accdet-v3-2-7828e835ff4b@collabora.com>

Handle the optional mediatek,accdet property. When present, retrieve the
sound component from its phandle, so the machine sound driver can use it
to register the audio jack and initialize the MT6359 ACCDET for jack
detection.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/mediatek/common/mtk-soc-card.h         |  1 +
 sound/soc/mediatek/common/mtk-soundcard-driver.c | 19 ++++++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h
index 3f6e24dd22df13ddb3aef1625a77d2e29e46fccf..a1d2794ac1f717997fb47023d5951a9ac4897788 100644
--- a/sound/soc/mediatek/common/mtk-soc-card.h
+++ b/sound/soc/mediatek/common/mtk-soc-card.h
@@ -16,6 +16,7 @@ struct mtk_soc_card_data {
 	const struct mtk_sof_priv *sof_priv;
 	struct list_head sof_dai_link_list;
 	struct mtk_platform_card_data *card_data;
+	struct snd_soc_component *accdet;
 	void *mach_priv;
 };
 
diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c
index f4314dddc46075d554b4e3f3aae8bcb5498f8ab5..713a368f79cf049f7879075c675457e91ba8332d 100644
--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c
+++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <sound/soc.h>
 
 #include "mtk-dsp-sof-common.h"
@@ -192,7 +193,9 @@ EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops);
 
 int mtk_soundcard_common_probe(struct platform_device *pdev)
 {
-	struct device_node *platform_node, *adsp_node;
+	struct device_node *platform_node, *adsp_node, *accdet_node;
+	struct snd_soc_component *accdet_comp;
+	struct platform_device *accdet_pdev;
 	const struct mtk_soundcard_pdata *pdata;
 	struct mtk_soc_card_data *soc_card_data;
 	struct snd_soc_dai_link *orig_dai_link, *dai_link;
@@ -250,6 +253,20 @@ int mtk_soundcard_common_probe(struct platform_device *pdev)
 
 	soc_card_data->card_data->jacks = jacks;
 
+	accdet_node = of_parse_phandle(pdev->dev.of_node, "mediatek,accdet", 0);
+	if (accdet_node) {
+		accdet_pdev = of_find_device_by_node(accdet_node);
+		if (accdet_pdev) {
+			accdet_comp = snd_soc_lookup_component(&accdet_pdev->dev, NULL);
+			if (accdet_comp)
+				soc_card_data->accdet = accdet_comp;
+			else
+				dev_err(&pdev->dev, "No sound component found from mediatek,accdet property\n");
+		} else {
+			dev_err(&pdev->dev, "No device found from mediatek,accdet property\n");
+		}
+	}
+
 	platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
 	if (!platform_node)
 		return dev_err_probe(&pdev->dev, -EINVAL,

-- 
2.48.1



From nfraprado at collabora.com  Thu Mar  6 11:52:17 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Thu, 06 Mar 2025 16:52:17 -0300
Subject: [PATCH v3 3/4] ASoC: mediatek: mt6359: Add stub for
 mt6359_accdet_enable_jack_detect
In-Reply-To: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
References: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
Message-ID: <20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com>

Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker
failures in the machine sound drivers calling it when
CONFIG_SND_SOC_MT6359_ACCDET is not enabled.

Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/codecs/mt6359-accdet.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
index c234f2f4276a12853a6fe0b13c4198dfc551b6b4..78ada3a5bfae55308135f37acc4c3857057bd203 100644
--- a/sound/soc/codecs/mt6359-accdet.h
+++ b/sound/soc/codecs/mt6359-accdet.h
@@ -123,6 +123,15 @@ struct mt6359_accdet {
 	struct workqueue_struct *jd_workqueue;
 };
 
+#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET)
 int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,
 				     struct snd_soc_jack *jack);
+#else
+static inline int
+mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,
+				 struct snd_soc_jack *jack)
+{
+	return -EOPNOTSUPP;
+}
+#endif
 #endif

-- 
2.48.1



From nfraprado at collabora.com  Thu Mar  6 11:52:18 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Thu, 06 Mar 2025 16:52:18 -0300
Subject: [PATCH v3 4/4] ASoC: mediatek: mt8188-mt6359: Add accdet headset
 jack detect support
In-Reply-To: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
References: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
Message-ID: <20250306-mt8188-accdet-v3-4-7828e835ff4b@collabora.com>

Enable headset jack detection for MT8188 platforms that use the MT6359
ACCDET block for it, indicated by the mediatek,accdet property in DT.
For those platforms, register a jack and initialize the ACCDET block to
report jack events through it.

Co-developed-by: Zoran Zhan <zoran.zhan at mediatek.com>
Signed-off-by: Zoran Zhan <zoran.zhan at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
index 420b1427b71dc1424a52f7ab6140c14659036733..20dc9470ba76b2a750e79a5ae3dafabd7c597f40 100644
--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
+++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
@@ -17,6 +17,7 @@
 #include "mt8188-afe-common.h"
 #include "../../codecs/nau8825.h"
 #include "../../codecs/mt6359.h"
+#include "../../codecs/mt6359-accdet.h"
 #include "../../codecs/rt5682.h"
 #include "../common/mtk-afe-platform-driver.h"
 #include "../common/mtk-soundcard-driver.h"
@@ -271,6 +272,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
 	},
 };
 
+static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = {
+	{
+		.pin    = "Headphone",
+		.mask   = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin    = "Headset Mic",
+		.mask   = SND_JACK_MICROPHONE,
+	},
+};
+
 static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Ext Spk"),
 };
@@ -506,6 +518,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
+	int ret;
+
+	if (!soc_card_data->accdet)
+		return 0;
+
+	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+				   SND_JACK_HEADSET | SND_JACK_BTN_0 |
+				   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+				   SND_JACK_BTN_3,
+				   jack, mt8188_headset_jack_pins,
+				   ARRAY_SIZE(mt8188_headset_jack_pins));
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_component *cmpnt_codec =
@@ -518,6 +559,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
 	/* mtkaif calibration */
 	mt8188_mt6359_mtkaif_calibration(rtd);
 
+	mt8188_mt6359_accdet_init(rtd);
+
 	return 0;
 }
 

-- 
2.48.1



From cki-project at redhat.com  Thu Mar  6 12:03:03 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 06 Mar 2025 20:03:03 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <04773.125030615030600374@us-mta-672.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1703653448

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1703653448-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From linux at martijnvandeventer.nl  Thu Mar  6 12:13:27 2025
From: linux at martijnvandeventer.nl (linux at martijnvandeventer.nl)
Date: Thu, 6 Mar 2025 21:13:27 +0100
Subject: [PATCH] clk: meson: g12a: Fix kernel warnings when no display attached
In-Reply-To: <1j4j065avo.fsf@starbuckisacylon.baylibre.com>
References: <20250213221702.606-1-linux@martijnvandeventer.nl>	<1jpljkzyf0.fsf@starbuckisacylon.baylibre.com>	<003301db888e$8ea84e90$abf8ebb0$@martijnvandeventer.nl>	<1jplj3g21q.fsf@starbuckisacylon.baylibre.com>	<004801db8eb7$99808e20$cc81aa60$@martijnvandeventer.nl> <1j4j065avo.fsf@starbuckisacylon.baylibre.com>
Message-ID: <001401db8ed4$392ef030$ab8cd090$@martijnvandeventer.nl>

Hi Jerome,
> 
> Once again, you are encouraged to fix things up ... where fixes are needed.

Encouragement is not the problem, time is ;-)

> DRM is hardly immutable. If you don't feel like you can do it on your own,
> you can still engage with the other contributors who may know this
> better and help you.

Maybe in a few months when I have some more time. Thanks.

> >
> > On the other hand, I also understand that if you, as a maintainer, allow
> > that, chances are it will never see a proper fix. :-)
> >
> > Cheers!
> >
-- 
Best regards,
Martijn



From cristian.ciocaltea at collabora.com  Thu Mar  6 12:21:01 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Thu, 6 Mar 2025 22:21:01 +0200
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
In-Reply-To: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
References: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
Message-ID: <751f18a4-900b-4644-9ae7-d28fa44888da@collabora.com>

Hi,

On 3/6/25 9:29 PM, Nicolas Frattaroli wrote:
> Despite the compatible already being listed in the bindings, the PHY
> driver never gained explicit support for it. This is especially a
> problem because the explicitly listed PHY addresses need to be specified
> for each SoC.
> 
> To solve this, add the compatible, and a PHY config, with the address
> gleaned from rk3576.dtsi.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
> I thought this must've been already submitted somewhere, but it wasn't
> in linux-next and searching for the modified file on lore also didn't
> yield any results. I guess this slipped through the cracks, and
> torpedoes HDMI support for RK3576 entirely until merged, so it'd be
> great if this could be merged in time for 6.15.
> 
> Let me know if I'm just very confused and this is already handled in
> some other series that's about to be applied.

I'm not aware of this being submitted as part of another series, that's
probably because commit f08d1c085638 ("phy: phy-rockchip-samsung-hdptx:
Don't use dt aliases to determine phy-id"), which actually changed the
approach of mapping the PHY IDs, has been applied fairly recently.

Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>

Cheers,
Cristian


From peter.griffin at linaro.org  Thu Mar  6 12:42:35 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 06 Mar 2025 20:42:35 +0000
Subject: [PATCH v3 1/4] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
Message-ID: <20250306-pinctrl-fltcon-suspend-v3-1-f9ab4ff6a24e@linaro.org>

On gs101 SoC the fltcon0 (filter configuration 0) offset
isn't at a fixed offset like previous SoCs as the fltcon1
register only exists when there are more than 4 pins in the
bank.

Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
macros that take an additional fltcon_offs variable.

This can then be used in suspend/resume callbacks to
save and restore the fltcon0 and fltcon1 registers.

Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 98 +++++++++++++-------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       | 22 ++++++
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  1 +
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  4 ++
 4 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 3ea7106ce5eae3c21f11790b5a40037042c1d407..e28fe81776466b693417c66bb15752d609b79eb1 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1370,83 +1370,83 @@ const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = {
 
 /* pin banks of gs101 pin-controller (ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10),
-	EXYNOS850_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14),
-	EXYNOS850_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18),
-	EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08, 0x10),
+	GS101_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c, 0x18),
+	GS101_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10, 0x1c),
+	GS101_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14, 0x20),
+	GS101_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18, 0x28),
+	GS101_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c, 0x30),
 };
 
 /* pin banks of gs101 pin-controller (FAR_ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_far_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c, 0x14),
 };
 
 /* pin banks of gs101 pin-controller (GSACORE) */
 static const struct samsung_pin_bank_data gs101_pin_gsacore[] = {
-	EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04, 0x04),
+	GS101_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08, 0x0c),
 };
 
 /* pin banks of gs101 pin-controller (GSACTRL) */
 static const struct samsung_pin_bank_data gs101_pin_gsactrl[] = {
-	EXYNOS850_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00),
+	GS101_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00, 0x00),
 };
 
 /* pin banks of gs101 pin-controller (PERIC0) */
 static const struct samsung_pin_bank_data gs101_pin_peric0[] = {
-	EXYNOS850_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c),
+	GS101_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10, 0x14),
+	GS101_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18, 0x1c),
+	GS101_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20, 0x24),
+	GS101_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24, 0x28),
+	GS101_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28, 0x2c),
+	GS101_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c, 0x30),
+	GS101_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30, 0x34),
+	GS101_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34, 0x38),
+	GS101_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38, 0x3c),
+	GS101_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c, 0x40),
+	GS101_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40, 0x44),
+	GS101_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44, 0x48),
+	GS101_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48, 0x4c),
+	GS101_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c, 0x50),
 };
 
 /* pin banks of gs101 pin-controller (PERIC1) */
 static const struct samsung_pin_bank_data gs101_pin_peric1[] = {
-	EXYNOS850_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c),
+	GS101_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14, 0x1c),
+	GS101_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c, 0x28),
 };
 
 /* pin banks of gs101 pin-controller (HSI1) */
 static const struct samsung_pin_bank_data gs101_pin_hsi1[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04, 0x08),
 };
 
 /* pin banks of gs101 pin-controller (HSI2) */
 static const struct samsung_pin_bank_data gs101_pin_hsi2[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08, 0x0c),
 };
 
 static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 7b7ff7ffeb56bdde2504ec90c8df13bdd1ace70e..33df21d5c9d61e852834031570d4a0ac0e51f6a4 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -175,6 +175,28 @@
 		.name			= id				\
 	}
 
+#define GS101_PIN_BANK_EINTG(pins, reg, id, offs, fltcon_offs) \
+	{							\
+		.type			= &exynos850_bank_type_off,	\
+		.pctl_offset		= reg,			\
+		.nr_pins		= pins,			\
+		.eint_type		= EINT_TYPE_GPIO,	\
+		.eint_offset		= offs,			\
+		.eint_fltcon_offset	= fltcon_offs,		\
+		.name			= id			\
+	}
+
+#define GS101_PIN_BANK_EINTW(pins, reg, id, offs, fltcon_offs) \
+	{								\
+		.type			= &exynos850_bank_type_alive,	\
+		.pctl_offset		= reg,				\
+		.nr_pins		= pins,				\
+		.eint_type		= EINT_TYPE_WKUP,		\
+		.eint_offset		= offs,				\
+		.eint_fltcon_offset	= fltcon_offs,			\
+		.name			= id				\
+	}
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index cfced7afd4ca6e99c7e72a588d780f0542990ed9..963060920301ec90affb2ee6d758d3d602ffb4a9 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1230,6 +1230,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
 		bank->eint_con_offset = bdata->eint_con_offset;
 		bank->eint_mask_offset = bdata->eint_mask_offset;
 		bank->eint_pend_offset = bdata->eint_pend_offset;
+		bank->eint_fltcon_offset = bdata->eint_fltcon_offset;
 		bank->name = bdata->name;
 
 		raw_spin_lock_init(&bank->slock);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index bb0689d52ea0b4392714fa9bcdcbae8d253c73a1..371e4f02bbfb375964b7833beb9bbc098a51f4a3 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -144,6 +144,7 @@ struct samsung_pin_bank_type {
  * @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  */
 struct samsung_pin_bank_data {
@@ -158,6 +159,7 @@ struct samsung_pin_bank_data {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 };
 
@@ -175,6 +177,7 @@ struct samsung_pin_bank_data {
  * @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  * @id: id of the bank, propagated to the pin range.
  * @pin_base: starting pin number of the bank.
@@ -201,6 +204,7 @@ struct samsung_pin_bank {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 	u32		id;
 

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Thu Mar  6 12:42:36 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 06 Mar 2025 20:42:36 +0000
Subject: [PATCH v3 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
Message-ID: <20250306-pinctrl-fltcon-suspend-v3-2-f9ab4ff6a24e@linaro.org>

gs101 needs it's own suspend/resume callbacks to use the newly
added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
registers. It also differs to previous SoCs in that fltcon1
register doesn't always exist for each bank.

exynosautov920 also has dedicated logic for using eint_con_offset
and eint_mask_offset for saving & restoring it's registers.

Refactor the existing platform specific suspend/resume callback
so that each SoC variant has their own callback containing the
SoC specific logic.

Additionally we now call drvdata->suspend() & drvdata->resume()
from within the loop that iterates the banks in
samsung_pinctrl_suspend() and samsung_pinctrl_resume().

This simplifies the logic, and allows us to remove the
clk_enable() and clk_disable() from the callbacks.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v2:
* Remove useless init (Andre)
* make it clear set_wakeup is conditional on bank->eint_type (Andre)

Changes since v1:
* Split code refactor & gs101 parts into separate patches (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |  28 ++--
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 201 ++++++++++---------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |   6 +-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  11 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |   8 +-
 5 files changed, 109 insertions(+), 145 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index e28fe81776466b693417c66bb15752d609b79eb1..57c98d2451b54b00d50e0e948e272ed53d386c34 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks0,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
 		.eint_wkup_init	= exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 		.retention_data	= &exynosautov920_retention_data,
 	}, {
 		/* pin-controller instance 1 AUD data */
@@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 3 HSI1 data */
 		.pin_banks	= exynosautov920_pin_banks3,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 4 HSI2 data */
 		.pin_banks	= exynosautov920_pin_banks4,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 5 HSI2UFS data */
 		.pin_banks	= exynosautov920_pin_banks5,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 6 PERIC0 data */
 		.pin_banks	= exynosautov920_pin_banks6,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 7 PERIC1 data */
 		.pin_banks	= exynosautov920_pin_banks7,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index ac6dc22b37c98ed5b7fca3335764f19abb2f71cc..f10ff09c1af01c11ff9229aaef77df32eb057b7b 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -761,153 +761,114 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	return 0;
 }
 
-static void exynos_pinctrl_suspend_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+static void exynos_set_wakeup(struct samsung_pin_bank *bank)
 {
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	const void __iomem *regs = bank->eint_base;
+	struct exynos_irq_chip *irq_chip;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
+	if (bank->irq_chip) {
+		irq_chip = bank->irq_chip;
+		irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
 	}
-
-	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
-	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
-					    struct samsung_pin_bank *bank)
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
-	}
-
-	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
-	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset);
+		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset + 4);
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		pr_debug("%s: save fltcon1 %#010x\n",
+			 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
 }
 
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	struct exynos_irq_chip *irq_chip = NULL;
-	int i;
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
 
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_suspend_bank(drvdata, bank);
-			else
-				exynos_pinctrl_suspend_bank(drvdata, bank);
-		}
-		else if (bank->eint_type == EINT_TYPE_WKUP) {
-			if (!irq_chip) {
-				irq_chip = bank->irq_chip;
-				irq_chip->set_eint_wakeup_mask(drvdata,
-							       irq_chip);
-			}
-		}
-	}
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + bank->pctl_offset +
+				       bank->eint_con_offset);
+		save->eint_mask = readl(regs + bank->pctl_offset +
+					bank->eint_mask_offset);
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
 }
 
-static void exynos_pinctrl_resume_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset), save->eint_fltcon0);
+		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset + 4),
+			       save->eint_fltcon1);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset);
+		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_ECON_OFFSET
-			+ bank->eint_offset), save->eint_con);
-	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset), save->eint_fltcon0);
-	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-			readl(regs + bank->irq_chip->eint_mask
-			+ bank->eint_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
 }
 
-static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
-					   struct samsung_pin_bank *bank)
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		/* exynosautov920 has eint_con_offset for all but one bank */
+		if (!bank->eint_con_offset)
+			exynos_pinctrl_resume(bank);
+
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
+			       save->eint_con);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset +
+			       bank->eint_mask_offset), save->eint_mask);
+
+		writel(save->eint_con,
+		       regs + bank->pctl_offset + bank->eint_con_offset);
+		writel(save->eint_mask,
+		       regs + bank->pctl_offset + bank->eint_mask_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
-	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-}
-
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	int i;
-
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_resume_bank(drvdata, bank);
-			else
-				exynos_pinctrl_resume_bank(drvdata, bank);
-		}
 }
 
 static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 33df21d5c9d61e852834031570d4a0ac0e51f6a4..35c2bc4ea488bda600ebfbda1492f5f49dbd9849 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -221,8 +221,10 @@ struct exynos_muxed_weint_data {
 
 int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
 int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 963060920301ec90affb2ee6d758d3d602ffb4a9..375634d8cc79d6533603e3eed562452181e2ee25 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->suspend)
+			drvdata->suspend(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
@@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 
 	clk_disable(drvdata->pclk);
 
-	if (drvdata->suspend)
-		drvdata->suspend(drvdata);
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
 		drvdata->retention_ctrl->enable(drvdata);
 
@@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		return ret;
 	}
 
-	if (drvdata->resume)
-		drvdata->resume(drvdata);
-
 	for (i = 0; i < drvdata->nr_banks; i++) {
 		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
 		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
@@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->resume)
+			drvdata->resume(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 371e4f02bbfb375964b7833beb9bbc098a51f4a3..e939e5bb0347458ae4a9014fd9657fc59c5c3994 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
 	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
 	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
 	void		(*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
-	void		(*suspend)(struct samsung_pinctrl_drv_data *);
-	void		(*resume)(struct samsung_pinctrl_drv_data *);
+	void		(*suspend)(struct samsung_pin_bank *bank);
+	void		(*resume)(struct samsung_pin_bank *bank);
 };
 
 /**
@@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
 
 	struct samsung_retention_ctrl	*retention_ctrl;
 
-	void (*suspend)(struct samsung_pinctrl_drv_data *);
-	void (*resume)(struct samsung_pinctrl_drv_data *);
+	void (*suspend)(struct samsung_pin_bank *bank);
+	void (*resume)(struct samsung_pin_bank *bank);
 };
 
 /**

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Thu Mar  6 12:42:37 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 06 Mar 2025 20:42:37 +0000
Subject: [PATCH v3 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
Message-ID: <20250306-pinctrl-fltcon-suspend-v3-3-f9ab4ff6a24e@linaro.org>

gs101 differs to other SoCs in that fltcon1 register doesn't
always exist. Additionally the offset of fltcon0 is not fixed
and needs to use the newly added eint_fltcon_offset variable.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
---
Changes since v2:
* make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
* align style where the '+' is placed (Andre)
* remove unnecessary braces (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 70 ++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  2 +
 3 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 57c98d2451b54b00d50e0e948e272ed53d386c34..fca447ebc5f5956b7e8d2f2d08f23622095b1ee6 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1455,15 +1455,15 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (FAR_ALIVE) */
 		.pin_banks	= gs101_pin_far_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_far_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (GSACORE) */
 		.pin_banks	= gs101_pin_gsacore,
@@ -1477,29 +1477,29 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_peric0,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric0),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (PERIC1) */
 		.pin_banks	= gs101_pin_peric1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume	= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI1) */
 		.pin_banks	= gs101_pin_hsi1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI2) */
 		.pin_banks	= gs101_pin_hsi2,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi2),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index f10ff09c1af01c11ff9229aaef77df32eb057b7b..9cffbe9ee64aa5236026978ac2466b709da5bffc 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -798,6 +798,40 @@ void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 		exynos_set_wakeup(bank);
 }
 
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + bank->eint_fltcon_offset);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			save->eint_fltcon1 = readl(regs +
+						EXYNOS_GPIO_EFLTCON_OFFSET
+						+ bank->eint_fltcon_offset + 4);
+
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		if (bank->nr_pins > 4)
+			pr_debug("%s: save fltcon1 %#010x\n",
+				 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
+}
+
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
@@ -816,6 +850,42 @@ void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 		exynos_set_wakeup(bank);
 }
 
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+
+	void __iomem *regs = bank->eint_base;
+	void __iomem *eint_fltcfg0 = regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		     + bank->eint_fltcon_offset;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(eint_fltcfg0), save->eint_fltcon0);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+				 readl(eint_fltcfg0 + 4), save->eint_fltcon1);
+
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, eint_fltcfg0);
+
+		if (bank->nr_pins > 4)
+			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
+	}
+}
+
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 35c2bc4ea488bda600ebfbda1492f5f49dbd9849..773f161a82a38cbaad05fcbc09a936300f5c7595 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -225,6 +225,8 @@ void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank);
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Thu Mar  6 12:42:38 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 06 Mar 2025 20:42:38 +0000
Subject: [PATCH v3 4/4] pinctrl: samsung: Add filter selection support for
 alive bank on gs101
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
Message-ID: <20250306-pinctrl-fltcon-suspend-v3-4-f9ab4ff6a24e@linaro.org>

Newer Exynos based SoCs have a filter selection bitfield in the filter
configuration registers on alive bank pins. This allows the selection of
a digital or analog delay filter for each pin. Add support for selecting
and enabling the filter.

On suspend we set the analog filter to all pins in the bank (as the
digital filter relies on a clock). On resume the digital filter is
reapplied to all pins in the bank. The digital filter is working via
a clock and has an adjustable filter delay flt_width bitfield, whereas
the analog filter uses a fixed delay.

The filter determines to what extent signal fluctuations received through
the pad are considered glitches.

The code path can be exercised using
echo mem > /sys/power/state
And then wake the device using a eint gpio

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---

Changes since v2:
* Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
* Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)

Changes since v1:
* Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
* Move filter config comment to header (Andre)
* Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
* Remove misleading old comment (Andre)
* Refactor exynos_eint_update_flt_reg() into a loop (Andre)

Note: this patch was previously sent as part of the initial gs101/ Pixel 6
series and was dropped in v6. This new version incorporates the review
feedback from Sam Protsenko here in v5.

Link: https://lore.kernel.org/all/20231201160925.3136868-1-peter.griffin at linaro.org/T/#m79ced98939e895c840d812c8b4c2b3f33ce604c8

Changes since previous version
* Drop fltcon_type enum and use bool eint_flt_selectable (Sam)
* Refactor and add exynos_eint_update_flt_reg() (Sam)
* Rename function to exynos_eint_set_filter() for easier readability (Sam)
* Remove comments and `if bank->fltcon_type != FLT_DEFAULT)` checks and indentation (Sam)
---
 drivers/pinctrl/samsung/pinctrl-exynos.c | 37 +++++++++++++++++++++++++++++++-
 drivers/pinctrl/samsung/pinctrl-exynos.h | 20 +++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 9cffbe9ee64aa5236026978ac2466b709da5bffc..1176efc0ef0464d1a6fc70b0a04f5ddd73ef88a4 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -369,6 +369,37 @@ struct exynos_eint_gpio_save {
 	u32 eint_mask;
 };
 
+static void exynos_eint_update_flt_reg(void __iomem *reg, int cnt, int con)
+{
+	unsigned int val, shift;
+	int i;
+
+	val = readl(reg);
+	for (i = 0; i < cnt; i++) {
+		shift = i * EXYNOS_FLTCON_LEN;
+		val &= ~(EXYNOS_FLTCON_DIGITAL << shift);
+		val |= con << shift;
+	}
+	writel(val, reg);
+}
+
+/*
+ * Set the desired filter (digital or analog delay) and enable it to
+ * every pin in the bank. Note the filter selection bitfield is only
+ * found on alive banks. The filter determines to what extent signal
+ * fluctuations received through the pad are considered glitches.
+ */
+static void exynos_eint_set_filter(struct samsung_pin_bank *bank, int filter)
+{
+	unsigned int off = EXYNOS_GPIO_EFLTCON_OFFSET + bank->eint_fltcon_offset;
+	void __iomem *reg = bank->drvdata->virt_base + off;
+	unsigned int con = EXYNOS_FLTCON_EN | filter;
+
+	for (int n = 0; n < bank->nr_pins; n += 4)
+		exynos_eint_update_flt_reg(reg + n,
+					   min(bank->nr_pins - n, 4), con);
+}
+
 /*
  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
  * @d: driver data of samsung pinctrl driver.
@@ -828,8 +859,10 @@ void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
 				 bank->name, save->eint_fltcon1);
 		pr_debug("%s: save    mask %#010x\n",
 			 bank->name, save->eint_mask);
-	} else if (bank->eint_type == EINT_TYPE_WKUP)
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
 		exynos_set_wakeup(bank);
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_ANALOG);
+	}
 }
 
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
@@ -883,6 +916,8 @@ void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
 			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
 		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 		       + bank->eint_offset);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_DIGITAL);
 	}
 }
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 773f161a82a38cbaad05fcbc09a936300f5c7595..66acbd08d3445ca6ee7358d3c4a6cb2be5d82842 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -52,6 +52,26 @@
 #define EXYNOS_EINT_MAX_PER_BANK	8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
+/*
+ * EINT filter configuration register (on alive banks) has
+ * the following layout.
+ *
+ * BitfieldName[PinNum][Bit:Bit]
+ * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24]
+ * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16]
+ * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8]
+ * FLT_EN[0][7]  FLT_SEL[0][6]  FLT_WIDTH[0][5:0]
+ *
+ * FLT_EN	0x0 = Disable, 0x1=Enable
+ * FLT_SEL	0x0 = Analog delay filter, 0x1 Digital filter (clock count)
+ * FLT_WIDTH	Filtering width. Valid when FLT_SEL is 0x1
+ */
+
+#define EXYNOS_FLTCON_EN		BIT(7)
+#define EXYNOS_FLTCON_DIGITAL		BIT(6)
+#define EXYNOS_FLTCON_ANALOG		(0 << 6)
+#define EXYNOS_FLTCON_LEN		8
+
 #define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
 	{						\
 		.type		= &bank_type_off,	\

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Thu Mar  6 12:47:01 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 6 Mar 2025 20:47:01 +0000
Subject: [PATCH v2 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <f7c0101ff26ac0d4ef70a374ae31ee5d23b3c8fc.camel@linaro.org>
References: <20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b@linaro.org>
 <20250301-pinctrl-fltcon-suspend-v2-2-a7eef9bb443b@linaro.org> <f7c0101ff26ac0d4ef70a374ae31ee5d23b3c8fc.camel@linaro.org>
Message-ID: <CADrjBPpF0ORvEP3fokS5FaoRtEZyE-xGFAK6uyCqck6+2F-JZg@mail.gmail.com>

Hi Andr?,

Thanks for the review feedback :)

On Thu, 6 Mar 2025 at 11:57, Andr? Draszik <andre.draszik at linaro.org> wrote:
>
> On Sat, 2025-03-01 at 11:43 +0000, Peter Griffin wrote:
> > gs101 needs it's own suspend/resume callbacks to use the newly
> > added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> > registers. It also differs to previous SoCs in that fltcon1
> > register doesn't always exist for each bank.
> >
> > exynosautov920 also has dedicated logic for using eint_con_offset
> > and eint_mask_offset for saving & restoring it's registers.
> >
> > Refactor the existing platform specific suspend/resume callback
> > so that each SoC variant has their own callback containing the
> > SoC specific logic.
> >
> > Additionally we now call drvdata->suspend() & drvdata->resume()
> > from within the loop that iterates the banks in
> > samsung_pinctrl_suspend() and samsung_pinctrl_resume().
> >
> > This simplifies the logic, and allows us to remove the
> > clk_enable() and clk_disable() from the callbacks.
> >
> > Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> > ---
> > Changes since v1:
> > * Split code refactor & gs101 parts into separate patches (Andre)
> > ---
> >  drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |  28 ++--
> >  drivers/pinctrl/samsung/pinctrl-exynos.c       | 201 ++++++++++---------------
> >  drivers/pinctrl/samsung/pinctrl-exynos.h       |   6 +-
> >  drivers/pinctrl/samsung/pinctrl-samsung.c      |  11 +-
> >  drivers/pinctrl/samsung/pinctrl-samsung.h      |   8 +-
> >  5 files changed, 111 insertions(+), 143 deletions(-)
> >
> > diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> > index e28fe8177646..57c98d2451b5 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> > +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> > @@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> >               .pin_banks      = exynosautov920_pin_banks0,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks0),
> >               .eint_wkup_init = exynos_eint_wkup_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >               .retention_data = &exynosautov920_retention_data,
> >       }, {
> >               /* pin-controller instance 1 AUD data */
> > @@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> >               .pin_banks      = exynosautov920_pin_banks2,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks2),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       }, {
> >               /* pin-controller instance 3 HSI1 data */
> >               .pin_banks      = exynosautov920_pin_banks3,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks3),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       }, {
> >               /* pin-controller instance 4 HSI2 data */
> >               .pin_banks      = exynosautov920_pin_banks4,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks4),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       }, {
> >               /* pin-controller instance 5 HSI2UFS data */
> >               .pin_banks      = exynosautov920_pin_banks5,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks5),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       }, {
> >               /* pin-controller instance 6 PERIC0 data */
> >               .pin_banks      = exynosautov920_pin_banks6,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks6),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       }, {
> >               /* pin-controller instance 7 PERIC1 data */
> >               .pin_banks      = exynosautov920_pin_banks7,
> >               .nr_banks       = ARRAY_SIZE(exynosautov920_pin_banks7),
> >               .eint_gpio_init = exynos_eint_gpio_init,
> > -             .suspend        = exynos_pinctrl_suspend,
> > -             .resume         = exynos_pinctrl_resume,
> > +             .suspend        = exynosautov920_pinctrl_suspend,
> > +             .resume         = exynosautov920_pinctrl_resume,
> >       },
> >  };
> >
> > diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
> > index ac6dc22b37c9..d65a9fba0781 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-exynos.c
> > +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
> > @@ -761,153 +761,118 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
> >       return 0;
> >  }
> >
> > -static void exynos_pinctrl_suspend_bank(
> > -                             struct samsung_pinctrl_drv_data *drvdata,
> > -                             struct samsung_pin_bank *bank)
> > +static void exynos_set_wakeup(struct samsung_pin_bank *bank)
> >  {
> > -     struct exynos_eint_gpio_save *save = bank->soc_priv;
> > -     const void __iomem *regs = bank->eint_base;
> > +     struct exynos_irq_chip *irq_chip = NULL;
>
> This is a useless init and the value is overwritten right away.

Will fix
>
> >
> > -     if (clk_enable(bank->drvdata->pclk)) {
> > -             dev_err(bank->gpio_chip.parent,
> > -                     "unable to enable clock for saving state\n");
> > -             return;
> > +     if (bank->eint_type == EINT_TYPE_WKUP) {
> > +             if (bank->irq_chip) {
> > +                     irq_chip = bank->irq_chip;
> > +                     irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
> > +             }
> >       }
> > -
> > -     save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > -                                             + bank->eint_offset);
> > -     save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                                             + 2 * bank->eint_offset);
> > -     save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                                             + 2 * bank->eint_offset + 4);
> > -     save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> > -                                             + bank->eint_offset);
> > -
> > -     clk_disable(bank->drvdata->pclk);
> > -
> > -     pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
> > -     pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
> > -     pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
> > -     pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
> >  }
> >
> > -static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
> > -                                         struct samsung_pin_bank *bank)
> > +void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
> >  {
> >       struct exynos_eint_gpio_save *save = bank->soc_priv;
> >       const void __iomem *regs = bank->eint_base;
> >
> > -     if (clk_enable(bank->drvdata->pclk)) {
> > -             dev_err(bank->gpio_chip.parent,
> > -                     "unable to enable clock for saving state\n");
> > -             return;
> > +     exynos_set_wakeup(bank);
> > +
> > +     if (bank->eint_type == EINT_TYPE_GPIO) {
>
> Can you swap the order, and make the call to exynos_set_wakeup()
> an else, to avoid some needless tests and make it clearer that
> set_wakeup() is conditional as well, i.e.:
>
>         if (bank->eint_type == EINT_TYPE_GPIO) {
>           ...
>         } else {
>           exynos_set_wakeup(bank);
>         }
>
> What makes it hard to read is that as-is, it looks like the
> set_wakeup() is unconditional, while it's also based on
> bank->eint_type (which is also more obvious before your patch).

I've addressed this and the rest of your review feedback in the v3
which I just sent.

Thanks,

Peter.

}
}



>
> Other than that, I think I looks good.
>
> Cheers,
> Andre'
>
> > +             save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > +                                    + bank->eint_offset);
> > +             save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                                        + 2 * bank->eint_offset);
> > +             save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                                        + 2 * bank->eint_offset + 4);
> > +             save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> > +                                     + bank->eint_offset);
> > +
> > +             pr_debug("%s: save     con %#010x\n",
> > +                      bank->name, save->eint_con);
> > +             pr_debug("%s: save fltcon0 %#010x\n",
> > +                      bank->name, save->eint_fltcon0);
> > +             pr_debug("%s: save fltcon1 %#010x\n",
> > +                      bank->name, save->eint_fltcon1);
> > +             pr_debug("%s: save    mask %#010x\n",
> > +                      bank->name, save->eint_mask);
> >       }
> > -
> > -     save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
> > -     save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
> > -
> > -     clk_disable(bank->drvdata->pclk);
> > -
> > -     pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
> > -     pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
> >  }
> >
> > -void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
> > +void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> >  {
> > -     struct samsung_pin_bank *bank = drvdata->pin_banks;
> > -     struct exynos_irq_chip *irq_chip = NULL;
> > -     int i;
> > +     struct exynos_eint_gpio_save *save = bank->soc_priv;
> > +     const void __iomem *regs = bank->eint_base;
> >
> > -     for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
> > -             if (bank->eint_type == EINT_TYPE_GPIO) {
> > -                     if (bank->eint_con_offset)
> > -                             exynosauto_pinctrl_suspend_bank(drvdata, bank);
> > -                     else
> > -                             exynos_pinctrl_suspend_bank(drvdata, bank);
> > -             }
> > -             else if (bank->eint_type == EINT_TYPE_WKUP) {
> > -                     if (!irq_chip) {
> > -                             irq_chip = bank->irq_chip;
> > -                             irq_chip->set_eint_wakeup_mask(drvdata,
> > -                                                            irq_chip);
> > -                     }
> > -             }
> > +     exynos_set_wakeup(bank);
> > +
> > +     if (bank->eint_type == EINT_TYPE_GPIO) {
> > +             save->eint_con = readl(regs + bank->pctl_offset +
> > +                                    bank->eint_con_offset);
> > +             save->eint_mask = readl(regs + bank->pctl_offset +
> > +                                     bank->eint_mask_offset);
> > +             pr_debug("%s: save     con %#010x\n",
> > +                      bank->name, save->eint_con);
> > +             pr_debug("%s: save    mask %#010x\n",
> > +                      bank->name, save->eint_mask);
> >       }
> >  }
> >
> > -static void exynos_pinctrl_resume_bank(
> > -                             struct samsung_pinctrl_drv_data *drvdata,
> > -                             struct samsung_pin_bank *bank)
> > +void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> >  {
> >       struct exynos_eint_gpio_save *save = bank->soc_priv;
> >       void __iomem *regs = bank->eint_base;
> >
> > -     if (clk_enable(bank->drvdata->pclk)) {
> > -             dev_err(bank->gpio_chip.parent,
> > -                     "unable to enable clock for restoring state\n");
> > -             return;
> > +     if (bank->eint_type == EINT_TYPE_GPIO) {
> > +             pr_debug("%s:     con %#010x => %#010x\n", bank->name,
> > +                      readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > +                            + bank->eint_offset), save->eint_con);
> > +             pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> > +                      readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                            + 2 * bank->eint_offset), save->eint_fltcon0);
> > +             pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> > +                      readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                            + 2 * bank->eint_offset + 4),
> > +                            save->eint_fltcon1);
> > +             pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
> > +                      readl(regs + bank->irq_chip->eint_mask
> > +                            + bank->eint_offset), save->eint_mask);
> > +
> > +             writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> > +                    + bank->eint_offset);
> > +             writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                    + 2 * bank->eint_offset);
> > +             writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                    + 2 * bank->eint_offset + 4);
> > +             writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> > +                    + bank->eint_offset);
> >       }
> > -
> > -     pr_debug("%s:     con %#010x => %#010x\n", bank->name,
> > -                     readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > -                     + bank->eint_offset), save->eint_con);
> > -     pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> > -                     readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                     + 2 * bank->eint_offset), save->eint_fltcon0);
> > -     pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> > -                     readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                     + 2 * bank->eint_offset + 4), save->eint_fltcon1);
> > -     pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
> > -                     readl(regs + bank->irq_chip->eint_mask
> > -                     + bank->eint_offset), save->eint_mask);
> > -
> > -     writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> > -                                             + bank->eint_offset);
> > -     writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                                             + 2 * bank->eint_offset);
> > -     writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > -                                             + 2 * bank->eint_offset + 4);
> > -     writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> > -                                             + bank->eint_offset);
> > -
> > -     clk_disable(bank->drvdata->pclk);
> >  }
> >
> > -static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
> > -                                        struct samsung_pin_bank *bank)
> > +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
> >  {
> >       struct exynos_eint_gpio_save *save = bank->soc_priv;
> >       void __iomem *regs = bank->eint_base;
> >
> > -     if (clk_enable(bank->drvdata->pclk)) {
> > -             dev_err(bank->gpio_chip.parent,
> > -                     "unable to enable clock for restoring state\n");
> > -             return;
> > +     if (bank->eint_type == EINT_TYPE_GPIO) {
> > +             /* exynosautov920 has eint_con_offset for all but one bank */
> > +             if (!bank->eint_con_offset)
> > +                     exynos_pinctrl_resume(bank);
> > +
> > +             pr_debug("%s:     con %#010x => %#010x\n", bank->name,
> > +                      readl(regs + bank->pctl_offset + bank->eint_con_offset),
> > +                            save->eint_con);
> > +             pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
> > +                      readl(regs + bank->pctl_offset +
> > +                            bank->eint_mask_offset), save->eint_mask);
> > +
> > +             writel(save->eint_con,
> > +                    regs + bank->pctl_offset + bank->eint_con_offset);
> > +             writel(save->eint_mask,
> > +                    regs + bank->pctl_offset + bank->eint_mask_offset);
> >       }
> > -
> > -     pr_debug("%s:     con %#010x => %#010x\n", bank->name,
> > -              readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
> > -     pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
> > -              readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
> > -
> > -     writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
> > -     writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
> > -
> > -     clk_disable(bank->drvdata->pclk);
> > -}
> > -
> > -void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
> > -{
> > -     struct samsung_pin_bank *bank = drvdata->pin_banks;
> > -     int i;
> > -
> > -     for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
> > -             if (bank->eint_type == EINT_TYPE_GPIO) {
> > -                     if (bank->eint_con_offset)
> > -                             exynosauto_pinctrl_resume_bank(drvdata, bank);
> > -                     else
> > -                             exynos_pinctrl_resume_bank(drvdata, bank);
> > -             }
> >  }
> >
> >  static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
> > diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
> > index 33df21d5c9d6..35c2bc4ea488 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-exynos.h
> > +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
> > @@ -221,8 +221,10 @@ struct exynos_muxed_weint_data {
> >
> >  int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
> >  int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
> > -void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
> > -void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
> > +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
> > +void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
> > +void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
> > +void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
> >  struct samsung_retention_ctrl *
> >  exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
> >                     const struct samsung_retention_data *data);
> > diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> > index 963060920301..375634d8cc79 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> > +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> > @@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> >               const u8 *widths = bank->type->fld_width;
> >               enum pincfg_type type;
> >
> > +             if (drvdata->suspend)
> > +                     drvdata->suspend(bank);
> > +
> >               /* Registers without a powerdown config aren't lost */
> >               if (!widths[PINCFG_TYPE_CON_PDN])
> >                       continue;
> > @@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> >
> >       clk_disable(drvdata->pclk);
> >
> > -     if (drvdata->suspend)
> > -             drvdata->suspend(drvdata);
> >       if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
> >               drvdata->retention_ctrl->enable(drvdata);
> >
> > @@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> >               return ret;
> >       }
> >
> > -     if (drvdata->resume)
> > -             drvdata->resume(drvdata);
> > -
> >       for (i = 0; i < drvdata->nr_banks; i++) {
> >               struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
> >               void __iomem *reg = bank->pctl_base + bank->pctl_offset;
> > @@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> >               const u8 *widths = bank->type->fld_width;
> >               enum pincfg_type type;
> >
> > +             if (drvdata->resume)
> > +                     drvdata->resume(bank);
> > +
> >               /* Registers without a powerdown config aren't lost */
> >               if (!widths[PINCFG_TYPE_CON_PDN])
> >                       continue;
> > diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
> > index 371e4f02bbfb..e939e5bb0347 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-samsung.h
> > +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
> > @@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
> >       int             (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
> >       int             (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
> >       void            (*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
> > -     void            (*suspend)(struct samsung_pinctrl_drv_data *);
> > -     void            (*resume)(struct samsung_pinctrl_drv_data *);
> > +     void            (*suspend)(struct samsung_pin_bank *bank);
> > +     void            (*resume)(struct samsung_pin_bank *bank);
> >  };
> >
> >  /**
> > @@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
> >
> >       struct samsung_retention_ctrl   *retention_ctrl;
> >
> > -     void (*suspend)(struct samsung_pinctrl_drv_data *);
> > -     void (*resume)(struct samsung_pinctrl_drv_data *);
> > +     void (*suspend)(struct samsung_pin_bank *bank);
> > +     void (*resume)(struct samsung_pin_bank *bank);
> >  };
> >
> >  /**
> >
>


From lkp at intel.com  Thu Mar  6 12:49:17 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 7 Mar 2025 04:49:17 +0800
Subject: [PATCH v3 04/20] ASoC: mediatek: mt6359-accdet: Add compatible
 property
In-Reply-To: <20250304-mt6359-accdet-dts-v3-4-5b0eafc29f5b@collabora.com>
References: <20250304-mt6359-accdet-dts-v3-4-5b0eafc29f5b@collabora.com>
Message-ID: <202503070421.25fbw6zg-lkp@intel.com>

Hi N?colas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 20d5c66e1810e6e8805ec0d01373afb2dba9f51a]

url:    https://github.com/intel-lab-lkp/linux/commits/N-colas-F-R-A-Prado/ASoC-dt-bindings-Add-document-for-mt6359-accdet/20250304-233834
base:   20d5c66e1810e6e8805ec0d01373afb2dba9f51a
patch link:    https://lore.kernel.org/r/20250304-mt6359-accdet-dts-v3-4-5b0eafc29f5b%40collabora.com
patch subject: [PATCH v3 04/20] ASoC: mediatek: mt6359-accdet: Add compatible property
config: s390-randconfig-r133-20250306 (https://download.01.org/0day-ci/archive/20250307/202503070421.25fbw6zg-lkp at intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce: (https://download.01.org/0day-ci/archive/20250307/202503070421.25fbw6zg-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503070421.25fbw6zg-lkp at intel.com/

sparse warnings: (new ones prefixed by >>)
>> sound/soc/codecs/mt6359-accdet.c:1050:27: sparse: sparse: symbol 'accdet_of_match' was not declared. Should it be static?

vim +/accdet_of_match +1050 sound/soc/codecs/mt6359-accdet.c

  1049	
> 1050	const struct of_device_id accdet_of_match[] = {
  1051		{ .compatible = "mediatek,mt6359-accdet", },
  1052		{ /* sentinel */ },
  1053	};
  1054	MODULE_DEVICE_TABLE(of, accdet_of_match);
  1055	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From david.e.box at linux.intel.com  Thu Mar  6 12:52:31 2025
From: david.e.box at linux.intel.com (David E. Box)
Date: Thu, 06 Mar 2025 12:52:31 -0800
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <d7c0094e-7fd3-4113-8d00-91b7a83ffd1f@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
	 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
	 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>
	 <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
	 <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>
	 <d7c0094e-7fd3-4113-8d00-91b7a83ffd1f@linux.intel.com>
Message-ID: <257769403908de3ac6271059e1febee88654fbdc.camel@linux.intel.com>

On Thu, 2025-03-06 at 20:56 +0800, Choong Yong Liang wrote:
> 
> 
> On 6/3/2025 5:05 pm, Andy Shevchenko wrote:
> > On Thu, Mar 6, 2025 at 10:39?AM Choong Yong Liang
> > <yong.liang.choong at linux.intel.com> wrote:
> > > On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
> > > > Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:
> > ...
> > 
> > > > > config DWMAC_INTEL
> > > > > ????? default X86
> > > > > ????? depends on X86 && STMMAC_ETH && PCI
> > > > > ????? depends on COMMON_CLK
> > > > > +??? depends on ACPI
> > > > Stray and unexplained change. Please, fix it. We don't need the
> > > > dependencies
> > > > which are not realised in the compile time.
> > > The dependency on ACPI is necessary because the intel_pmc_ipc.h header
> > > relies on ACPI functionality to interact with the Intel PMC.
> > So, that header has to be fixed as ACPI here is really unneeded
> > dependency for the cases when somebody (for whatever reasons) want to
> > build a kernel without ACPI support but with the driver enabled for
> > let's say PCI device.
> > 
> > 
> > -- With Best Regards, Andy Shevchenko
> 
> Hi Andy,
> 
> Thank you for your feedback, Andy.
> I appreciate your insights regarding the ACPI dependency.
> The intel_pmc_ipc.h header is under the ownership of David E Box, who 
> focuses on the platform code, while my focus is on the netdev.
> 
> Hi David,
> 
> if you could kindly look into making the ACPI dependency optional in the 
> intel_pmc_ipc.h header, it would be greatly appreciated.
> I am more than willing to provide any support necessary to ensure a smooth 
> resolution.

Choong you only need put the function under a #if CONFIG_ACPI block and provide
an alternative that returns an error when the code is not build. Like this,

#if CONFIG_ACPI
static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
*rbuf)
{
   ...
}
#else
static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
*rbuf) { return -ENODEV; }
#endif

David

> 
> This patch series has already been accepted, but we recognize the 
> importance of addressing this issue in the next patch series for upstream.
> Our goal is to ensure that the driver can be compiled and function 
> correctly in both ACPI and non-ACPI environments.
> 
> Thank you both for your understanding and collaboration.



From jonas at kwiboo.se  Thu Mar  6 12:38:52 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 20:38:52 +0000
Subject: [PATCH 1/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3328
In-Reply-To: <20250306203858.1677595-1-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
Message-ID: <20250306203858.1677595-2-jonas@kwiboo.se>

Support for Rockchip RK3328 GMAC and addition of the DELAY_ENABLE macro
was merged in the same merge window. This resulted in RK3328 not being
converted to use the new DELAY_ENABLE macro.

Change to use the DELAY_ENABLE macro to help disable MAC delay when
RGMII_ID/RXID/TXID is used.

Fixes: eaf70ad14cbb ("net: stmmac: dwmac-rk: Add handling for RGMII_ID/RXID/TXID")
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..297fa93e4a39 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -593,8 +593,7 @@ static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
 	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
 		     RK3328_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3328_GMAC_RMII_MODE_CLR |
-		     RK3328_GMAC_RXCLK_DLY_ENABLE |
-		     RK3328_GMAC_TXCLK_DLY_ENABLE);
+		     DELAY_ENABLE(RK3328, tx_delay, rx_delay));
 
 	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0,
 		     RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) |
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 12:38:51 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 20:38:51 +0000
Subject: [PATCH 0/3] Use DELAY_ENABLE macro for RK3328, RK3566/RK3568 and RK3588
Message-ID: <20250306203858.1677595-1-jonas@kwiboo.se>

Almost all Rockchip GMAC variants use the DELAY_ENABLE macro to help
enable or disable use of MAC rx/tx delay. However, RK3328, RK3566/RK3568
and RK3588 GMAC driver does not.

Use of the DELAY_ENABLE macro help ensure the MAC rx/tx delay is
disabled, instead of being enabled and using a zero delay, when
RGMII_ID/RXID/TXID is used.

RK3328 driver was merged around the same time as when DELAY_ENABLE was
introduced so it is understandable why it was missed. Both RK3566/RK3568
and RK3588 support were introduced much later yet they also missed using
the DELAY_ENABLE macro (so did vendor kernel at that time).

This series fixes all these cases to unify how GMAC delay feature is
enabled or disabled across the different GMAC variants.

Jonas Karlman (3):
  net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3328
  net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3566/RK3568
  net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3588

 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 12:38:53 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 20:38:53 +0000
Subject: [PATCH 2/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3566/RK3568
In-Reply-To: <20250306203858.1677595-1-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
Message-ID: <20250306203858.1677595-3-jonas@kwiboo.se>

Support for Rockchip RK3566/RK3568 GMAC was added without use of the
DELAY_ENABLE macro to assist with enable/disable use of MAC rx/tx delay.

Change to use the DELAY_ENABLE macro to help disable MAC delay when
RGMII_ID/RXID/TXID is used. This also re-order to enable/disable before
the delay is written to match all other GMAC and vendor kernel.

Fixes: 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 297fa93e4a39..37eb86e4e325 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1049,14 +1049,13 @@ static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
 	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
 				     RK3568_GRF_GMAC0_CON1;
 
+	regmap_write(bsp_priv->grf, con1,
+		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
+		     DELAY_ENABLE(RK3568, tx_delay, rx_delay));
+
 	regmap_write(bsp_priv->grf, con0,
 		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
 		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
-
-	regmap_write(bsp_priv->grf, con1,
-		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
-		     RK3568_GMAC_RXCLK_DLY_ENABLE |
-		     RK3568_GMAC_TXCLK_DLY_ENABLE);
 }
 
 static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 12:38:54 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 20:38:54 +0000
Subject: [PATCH 3/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3588
In-Reply-To: <20250306203858.1677595-1-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
Message-ID: <20250306203858.1677595-4-jonas@kwiboo.se>

Support for Rockchip RK3588 GMAC was added without use of the
DELAY_ENABLE macro to assist with enable/disable use of MAC rx/tx delay.

Change to use a variant of the DELAY_ENABLE macro to help disable MAC
delay when RGMII_ID/RXID/TXID is used.

Fixes: 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588")
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 37eb86e4e325..79db81d68afd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -91,6 +91,10 @@ struct rk_priv_data {
 	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
 	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
 
+#define DELAY_ENABLE_BY_ID(soc, tx, rx, id) \
+	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE(id) : soc##_GMAC_TXCLK_DLY_DISABLE(id)) | \
+	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE(id) : soc##_GMAC_RXCLK_DLY_DISABLE(id)))
+
 #define PX30_GRF_GMAC_CON1		0x0904
 
 /* PX30_GRF_GMAC_CON1 */
@@ -1322,8 +1326,7 @@ static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
 		     RK3588_GMAC_CLK_RGMII_MODE(id));
 
 	regmap_write(bsp_priv->grf, RK3588_GRF_GMAC_CON7,
-		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
-		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
+		     DELAY_ENABLE_BY_ID(RK3588, tx_delay, rx_delay, id));
 
 	regmap_write(bsp_priv->grf, offset_con,
 		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
-- 
2.48.1



From peter.griffin at linaro.org  Thu Mar  6 12:42:34 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 06 Mar 2025 20:42:34 +0000
Subject: [PATCH v3 0/4] samsung: pinctrl: Add support for
 eint_fltcon_offset and filter selection on gs101
Message-ID: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>

Hi folks,

This series fixes support for correctly saving and restoring fltcon0
and fltcon1 registers on gs101 for non-alive banks where the fltcon
register offset is not at a fixed offset (unlike previous SoCs).
This is done by adding a eint_fltcon_offset and providing GS101
specific pin macros that take an additional parameter (similar to
how exynosautov920 handles it's eint_con_offset).

Additionally the SoC specific suspend and resume callbacks are
re-factored so that each SoC variant has it's own callback containing
the peculiarities for that SoC.

Finally support for filter selection on alive banks is added, this is
currently only enabled for gs101. The code path can be excercised using
`echo mem > /sys/power/state`

regards,

Peter

To: Krzysztof Kozlowski <krzk at kernel.org>
To: Sylwester Nawrocki <s.nawrocki at samsung.com>
To: Alim Akhtar <alim.akhtar at samsung.com>
To: Linus Walleij <linus.walleij at linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-gpio at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: andre.draszik at linaro.org
Cc: tudor.ambarus at linaro.org
Cc: willmcvicker at google.com
Cc: semen.protsenko at linaro.org
Cc: kernel-team at android.com
Cc: jaewon02.kim at samsung.com

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes in v3:

- Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
- Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)
- Make it obvious exynos_set_wakeup() is conditional on bank type (Andre)
- Align style where the '+' is placed first (Andre)
- Remove unnecessary braces (Andre)
- Link to v2: https://lore.kernel.org/r/20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b at linaro.org

Changes in v2:
- Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
- Move filter config register comment to header file (Andre)
- Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
- Remove misleading old comment (Andre)
- Refactor exynos_eint_update_flt_reg() into a loop (Andre)
- Split refactor of suspend/resume callbacks & gs101 parts into separate patches (Andre)
- Link to v1: https://lore.kernel.org/r/20250120-pinctrl-fltcon-suspend-v1-0-e77900b2a854 at linaro.org

---
Peter Griffin (4):
      pinctrl: samsung: add support for eint_fltcon_offset
      pinctrl: samsung: add dedicated SoC eint suspend/resume callbacks
      pinctrl: samsung: add gs101 specific eint suspend/resume callbacks
      pinctrl: samsung: Add filter selection support for alive bank on gs101

 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 150 ++++++-------
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 294 +++++++++++++++----------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  50 ++++-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  12 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  12 +-
 5 files changed, 318 insertions(+), 200 deletions(-)
---
base-commit: 0761652a3b3b607787aebc386d412b1d0ae8008c
change-id: 20250120-pinctrl-fltcon-suspend-2333a137c4d4

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From robh at kernel.org  Thu Mar  6 12:52:51 2025
From: robh at kernel.org (Rob Herring)
Date: Thu, 6 Mar 2025 14:52:51 -0600
Subject: [PATCH 1/2] dt-bindings: memory-controllers: samsung,exynos4210-srom:
 Enforce child props
In-Reply-To: <ab483a68-40a8-4b44-ad73-d8a34bd32c69@kernel.org>
References: <20250306085849.32852-1-krzysztof.kozlowski@linaro.org>
 <CAL_JsqKODHZcrpqskA2aeK6EqGNx9aGNuPqGzhcZ_Nqiu+Ccww@mail.gmail.com> <ab483a68-40a8-4b44-ad73-d8a34bd32c69@kernel.org>
Message-ID: <CAL_Jsq+95KW-JwA_OZsqQ9htirBUtBE9reJpa5fzeZ8iwYBeOQ@mail.gmail.com>

On Thu, Mar 6, 2025 at 7:51?AM Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 06/03/2025 14:39, Rob Herring wrote:
> > Why do we need this? Any child node should have a schema which needs
> > to include mc-peripheral-props.yaml if any properties from it can be
> > used.
>
> From correctness point of view, you are right, we don't need it. However:
>
> 1. Convention was so far to have in every controller. I think this also
> is easier to understand whenever one reads the bindings - clear
> documentation what children on this bus should look like.
>
> 2. To clearly document from where samsung,srom-timing comes in the
> required block:

I could be wrong, but I want to say that's pretty much an exception.
They are usually optional (other than reg). Though I guess we want to
enforce 'reg'...

> https://web.git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git/tree/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml?h=dt/next#n50
> Otherwise for me it is a bit confusing to require a property which is
> nowhere here defined.

It's a bit weird that non-exynos properties are allowed too, though
that's always the case for these properties.

I'll apply these.

Rob


From dsimic at manjaro.org  Thu Mar  6 13:09:06 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 06 Mar 2025 22:09:06 +0100
Subject: [PATCH 1/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3328
In-Reply-To: <20250306203858.1677595-2-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-2-jonas@kwiboo.se>
Message-ID: <427cbfc8c6b71bf70804a0d535ff9d18@manjaro.org>

Hello Jonas,

On 2025-03-06 21:38, Jonas Karlman wrote:
> Support for Rockchip RK3328 GMAC and addition of the DELAY_ENABLE macro
> was merged in the same merge window. This resulted in RK3328 not being
> converted to use the new DELAY_ENABLE macro.
> 
> Change to use the DELAY_ENABLE macro to help disable MAC delay when
> RGMII_ID/RXID/TXID is used.
> 
> Fixes: eaf70ad14cbb ("net: stmmac: dwmac-rk: Add handling for
> RGMII_ID/RXID/TXID")
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index 003fa5cf42c3..297fa93e4a39 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -593,8 +593,7 @@ static void rk3328_set_to_rgmii(struct
> rk_priv_data *bsp_priv,
>  	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
>  		     RK3328_GMAC_PHY_INTF_SEL_RGMII |
>  		     RK3328_GMAC_RMII_MODE_CLR |
> -		     RK3328_GMAC_RXCLK_DLY_ENABLE |
> -		     RK3328_GMAC_TXCLK_DLY_ENABLE);
> +		     DELAY_ENABLE(RK3328, tx_delay, rx_delay));
> 
>  	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0,
>  		     RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) |

Thanks for this patch...  It's looking good to me, and good job
spotting this issue!  Please, feel free to include:

Reviewed-by: Dragan Simic <dsimic at manjaro.org>


From sakari.ailus at iki.fi  Thu Mar  6 13:13:46 2025
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Thu, 6 Mar 2025 21:13:46 +0000
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
Message-ID: <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>

Hi Dan,

On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > Hi Mathis,
> > 
> > Thanks for the patch.
> > 
> > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > The imx-media-csi driver requires upstream camera drivers to implement
> > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > implement this function are not usable on the i.MX6.
> > > 
> > > The docs for get_mbus_config [1] say:
> > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > >             The media bus configuration is usually retrieved from the
> > >             firmware interface at sub-device probe time, immediately
> > >             applied to the hardware and eventually adjusted by the
> > >             driver.
> > > 
> > > Currently, the imx-media-csi driver is not incorporating the information
> > > from the firmware interface and therefore relies on the implementation of
> > > get_mbus_config by the camera driver.
> > > 
> > > To be compatible with camera drivers not implementing get_mbus_config
> > > (which is the usual case), use the bus information from the fw interface:
> > > 
> > > The camera does not necessarily has a direct media bus link to the CSI as
> > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > between them on the media pipeline.
> > > The CSI driver already implements the functionality to find the connected
> > > camera sub-device to call get_mbus_config on it.
> > > 
> > > At this point the driver is modified as follows:
> > > In the case that get_mbus_config is not implemented by the upstream
> > > camera, try to get its endpoint configuration from the firmware interface
> > > usign v4l2_fwnode_endpoint_parse.
> > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > configuration.
> > > For all other mbus_types, return an error.
> > > 
> > > Note that parsing the mbus_config from the fw interface is not done during
> > > probing because the camera that's connected to the CSI can change based on
> > > the selected input of the video-mux at runtime.
> > > 
> > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > [1] include/media/v4l2-subdev.h - line 814
> > > 
> > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > ---
> > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > index 3edbc57be2ca..394a9321a10b 100644
> > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > >  {
> > >  	struct v4l2_subdev *sd, *remote_sd;
> > >  	struct media_pad *remote_pad;
> > > +	struct fwnode_handle *ep_node;
> > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > 
> > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > field to zero this way is redundant, just use {}.
> > 
> 
> I was going to respond in much the same way.  This is equivalen to:
> 
> struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };

Thinking about this in a context of parsing the endpoint, in fact the
bus_type should be specified. Presumably the hardware is D-PHY, so the
correct value would be V4L2_MBUS_CSI2_DPHY. This way
v4l2_fwnode_endpoint_parse() doesn't need to guess.

> 
> > >  	int ret;
> > >  
> > >  	if (!priv->src_sd)
> > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > >  
> > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > >  			       remote_pad->index, mbus_cfg);
> > > -	if (ret == -ENOIOCTLCMD)
> > > -		v4l2_err(&priv->sd,
> > > -			 "entity %s does not implement get_mbus_config()\n",
> > > -			 remote_pad->entity->name);
> > > +	if (ret == -ENOIOCTLCMD) {
> > 
> > 	if (!ret)
> > 		return 0;
> > 
> > And you can unindent the rest.
> 
> I was going to say this too but then I thought actually this needs to
> be:
> 
> 	if (ret != -ENOIOCTLCMD)
> 		return ret;
> 
> Which is weird.  Better to break all the new code into a separate
> helper function.
> 
> 	if (ret == -ENOIOCTLCMD)
> 		ret = parse_fw_link_config_stuff();
> 
> 	return ret;

Indeed. get_mbus_config() presumably wouldn't return an error but
correctness is usually a good idea.

-- 
Regards,

Sakari Ailus


From jonas at kwiboo.se  Thu Mar  6 13:09:44 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 21:09:44 +0000
Subject: [PATCH 0/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
Message-ID: <20250306210950.1686713-1-jonas@kwiboo.se>

All Rockchip GMAC variants require writing to GRF to configure e.g.
interface mode and MAC rx/tx delay. The GRF syscon regmap is located
with help of a rockchip,grf and rockchip,php-grf phandle.

However, validating the rockchip,grf and rockchip,php-grf syscon regmap
is deferred until e.g. interface mode or speed is configured.

This series change to validate the rockchip,grf and rockchip,php-grf
syscon regmap at probe time to help simplify the SoC specific operations.

I do not expect that this will introduce any regression. Prior to this,
use of a device tree without a rockchip,grf would fail when interface
mode or speed is configured, with this use of such device tree would
instead result in failure at probe time.

Jonas Karlman (2):
  dt-bindings: net: rockchip-dwmac: Require rockchip,grf and
    rockchip,php-grf
  net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe

 .../bindings/net/rockchip-dwmac.yaml          |  17 +-
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 269 ++----------------
 2 files changed, 32 insertions(+), 254 deletions(-)

-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 13:09:45 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 21:09:45 +0000
Subject: [PATCH 1/2] dt-bindings: net: rockchip-dwmac: Require rockchip,grf and rockchip,php-grf
In-Reply-To: <20250306210950.1686713-1-jonas@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
Message-ID: <20250306210950.1686713-2-jonas@kwiboo.se>

All Rockchip GMAC variants require writing to GRF to configure e.g.
interface mode and MAC rx/tx delay.

Change binding to require rockchip,grf and rockchip,php-grf to reflect
that GRF (and PHP-GRF for RK3576/RK3588) control part of GMAC.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
---
 .../devicetree/bindings/net/rockchip-dwmac.yaml | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
index f8a576611d6c..05a5605f1b51 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
@@ -32,9 +32,6 @@ select:
   required:
     - compatible
 
-allOf:
-  - $ref: snps,dwmac.yaml#
-
 properties:
   compatible:
     oneOf:
@@ -114,6 +111,20 @@ required:
   - compatible
   - clocks
   - clock-names
+  - rockchip,grf
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,rk3576-gmac
+              - rockchip,rk3588-gmac
+    then:
+      required:
+        - rockchip,php-grf
 
 unevaluatedProperties: false
 
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 13:09:46 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 21:09:46 +0000
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
In-Reply-To: <20250306210950.1686713-1-jonas@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
Message-ID: <20250306210950.1686713-3-jonas@kwiboo.se>

All Rockchip GMAC variants require writing to GRF to configure e.g.
interface mode and MAC rx/tx delay. The GRF syscon regmap is located
with help of a rockchip,grf and rockchip,php-grf phandle.

However, validating the rockchip,grf and rockchip,php-grf syscon regmap
is deferred until e.g. interface mode or speed is configured, inside the
indivitual SoC specific operations.

Change to validate the rockchip,grf and rockchip,php-grf syscon regmap
at probe time to simplify all SoC specific operations.

Prior to this, use of a device tree without a rockchip,grf would fail
when interface mode or speed is configured, with this use of such device
tree would instead result in failure at probe time.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 269 ++----------------
 1 file changed, 18 insertions(+), 251 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 79db81d68afd..ba1cd079adf2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -105,13 +105,6 @@ struct rk_priv_data {
 
 static void px30_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
 		     PX30_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -185,13 +178,6 @@ static const struct rk_gmac_ops px30_ops = {
 static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 		     RK3128_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3128_GMAC_RMII_MODE_CLR);
@@ -203,13 +189,6 @@ static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 		     RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE);
 }
@@ -218,11 +197,6 @@ static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 			     RK3128_GMAC_CLK_2_5M);
@@ -240,11 +214,6 @@ static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 			     RK3128_GMAC_RMII_CLK_2_5M |
@@ -301,13 +270,6 @@ static const struct rk_gmac_ops rk3128_ops = {
 static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 		     RK3228_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3228_GMAC_RMII_MODE_CLR |
@@ -320,13 +282,6 @@ static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 		     RK3228_GMAC_PHY_INTF_SEL_RMII |
 		     RK3228_GMAC_RMII_MODE);
@@ -339,11 +294,6 @@ static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 			     RK3228_GMAC_CLK_2_5M);
@@ -361,11 +311,6 @@ static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 			     RK3228_GMAC_RMII_CLK_2_5M |
@@ -423,13 +368,6 @@ static const struct rk_gmac_ops rk3228_ops = {
 static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3288_GMAC_RMII_MODE_CLR);
@@ -441,13 +379,6 @@ static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
 }
@@ -456,11 +387,6 @@ static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 			     RK3288_GMAC_CLK_2_5M);
@@ -478,11 +404,6 @@ static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 			     RK3288_GMAC_RMII_CLK_2_5M |
@@ -515,13 +436,6 @@ static const struct rk_gmac_ops rk3288_ops = {
 
 static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
 		     RK3308_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -530,11 +444,6 @@ static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
 			     RK3308_GMAC_SPEED_10M);
@@ -587,13 +496,6 @@ static const struct rk_gmac_ops rk3308_ops = {
 static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
 		     RK3328_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3328_GMAC_RMII_MODE_CLR |
@@ -606,14 +508,8 @@ static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int reg;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
 		  RK3328_GRF_MAC_CON1;
 
@@ -626,11 +522,6 @@ static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
 			     RK3328_GMAC_CLK_2_5M);
@@ -649,11 +540,6 @@ static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int reg;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
 		  RK3328_GRF_MAC_CON1;
 
@@ -714,13 +600,6 @@ static const struct rk_gmac_ops rk3328_ops = {
 static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 		     RK3366_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3366_GMAC_RMII_MODE_CLR);
@@ -732,13 +611,6 @@ static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 		     RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE);
 }
@@ -747,11 +619,6 @@ static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 			     RK3366_GMAC_CLK_2_5M);
@@ -769,11 +636,6 @@ static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 			     RK3366_GMAC_RMII_CLK_2_5M |
@@ -825,13 +687,6 @@ static const struct rk_gmac_ops rk3366_ops = {
 static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3368_GMAC_RMII_MODE_CLR);
@@ -843,13 +698,6 @@ static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
 }
@@ -858,11 +706,6 @@ static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 			     RK3368_GMAC_CLK_2_5M);
@@ -880,11 +723,6 @@ static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 			     RK3368_GMAC_RMII_CLK_2_5M |
@@ -936,13 +774,6 @@ static const struct rk_gmac_ops rk3368_ops = {
 static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 		     RK3399_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3399_GMAC_RMII_MODE_CLR);
@@ -954,13 +785,6 @@ static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 		     RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE);
 }
@@ -969,11 +793,6 @@ static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 			     RK3399_GMAC_CLK_2_5M);
@@ -991,11 +810,6 @@ static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 			     RK3399_GMAC_RMII_CLK_2_5M |
@@ -1040,14 +854,8 @@ static const struct rk_gmac_ops rk3399_ops = {
 static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 con0, con1;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	con0 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON0 :
 				     RK3568_GRF_GMAC0_CON0;
 	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
@@ -1064,14 +872,8 @@ static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 con1;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
 				     RK3568_GRF_GMAC0_CON1;
 	regmap_write(bsp_priv->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
@@ -1149,14 +951,8 @@ static const struct rk_gmac_ops rk3568_ops = {
 static void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int offset_con;
 
-	if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "Missing rockchip,grf or rockchip,php-grf property\n");
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 					 RK3576_GRF_GMAC_CON0;
 
@@ -1182,14 +978,8 @@ static void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3576_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int offset_con;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 					 RK3576_GRF_GMAC_CON0;
 
@@ -1308,14 +1098,8 @@ static const struct rk_gmac_ops rk3576_ops = {
 static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 offset_con, id = bsp_priv->id;
 
-	if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "Missing rockchip,grf or rockchip,php_grf property\n");
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3588_GRF_GMAC_CON9 :
 					 RK3588_GRF_GMAC_CON8;
 
@@ -1335,13 +1119,6 @@ static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3588_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "%s: Missing rockchip,php_grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
 		     RK3588_GMAC_PHY_INTF_SEL_RMII(bsp_priv->id));
 
@@ -1424,13 +1201,6 @@ static const struct rk_gmac_ops rk3588_ops = {
 
 static void rv1108_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
 		     RV1108_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -1439,11 +1209,6 @@ static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
 			     RV1108_GMAC_RMII_CLK_2_5M |
@@ -1492,13 +1257,6 @@ static const struct rk_gmac_ops rv1108_ops = {
 static void rv1126_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
 		     RV1126_GMAC_PHY_INTF_SEL_RGMII |
 		     RV1126_GMAC_M0_RXCLK_DLY_ENABLE |
@@ -1517,13 +1275,6 @@ static void rv1126_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
 		     RV1126_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -1813,8 +1564,24 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 
 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
 							"rockchip,grf");
-	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
-							    "rockchip,php-grf");
+	if (IS_ERR(bsp_priv->grf)) {
+		ret = PTR_ERR(bsp_priv->grf);
+		dev_err_probe(dev, ret, "failed to lookup rockchip,grf\n");
+		return ERR_PTR(ret);
+	}
+
+	bsp_priv->php_grf =
+		syscon_regmap_lookup_by_phandle_optional(dev->of_node,
+							 "rockchip,php-grf");
+	if ((of_device_is_compatible(dev->of_node, "rockchip,rk3588-gmac") ||
+	     of_device_is_compatible(dev->of_node, "rockchip,rk3576-gmac")) &&
+	    !bsp_priv->php_grf)
+		bsp_priv->php_grf = ERR_PTR(-ENODEV);
+	if (IS_ERR(bsp_priv->php_grf)) {
+		ret = PTR_ERR(bsp_priv->php_grf);
+		dev_err_probe(dev, ret, "failed to lookup rockchip,php-grf\n");
+		return ERR_PTR(ret);
+	}
 
 	if (plat->phy_node) {
 		bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
-- 
2.48.1



From andre.draszik at linaro.org  Thu Mar  6 13:15:19 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 21:15:19 +0000
Subject: [PATCH v3 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-2-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
	 <20250306-pinctrl-fltcon-suspend-v3-2-f9ab4ff6a24e@linaro.org>
Message-ID: <1418fde488646160a1be14b2153e409488f3d861.camel@linaro.org>

On Thu, 2025-03-06 at 20:42 +0000, Peter Griffin wrote:
> gs101 needs it's own suspend/resume callbacks to use the newly
> added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> registers. It also differs to previous SoCs in that fltcon1
> register doesn't always exist for each bank.
> 
> exynosautov920 also has dedicated logic for using eint_con_offset
> and eint_mask_offset for saving & restoring it's registers.
> 
> Refactor the existing platform specific suspend/resume callback
> so that each SoC variant has their own callback containing the
> SoC specific logic.
> 
> Additionally we now call drvdata->suspend() & drvdata->resume()
> from within the loop that iterates the banks in
> samsung_pinctrl_suspend() and samsung_pinctrl_resume().
> 
> This simplifies the logic, and allows us to remove the
> clk_enable() and clk_disable() from the callbacks.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> Changes since v2:
> * Remove useless init (Andre)
> * make it clear set_wakeup is conditional on bank->eint_type (Andre)
> 
> Changes since v1:
> * Split code refactor & gs101 parts into separate patches (Andre)
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |? 28 ++--
> ?drivers/pinctrl/samsung/pinctrl-exynos.c?????? | 201 ++++++++++---------------
> ?drivers/pinctrl/samsung/pinctrl-exynos.h?????? |?? 6 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.c????? |? 11 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.h????? |?? 8 +-
> ?5 files changed, 109 insertions(+), 145 deletions(-)

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>




From dsimic at manjaro.org  Thu Mar  6 13:26:45 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 06 Mar 2025 22:26:45 +0100
Subject: [PATCH 2/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3566/RK3568
In-Reply-To: <20250306203858.1677595-3-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-3-jonas@kwiboo.se>
Message-ID: <73ac54350ee3e42dee2b886403f003de@manjaro.org>

Hello Jonas,

On 2025-03-06 21:38, Jonas Karlman wrote:
> Support for Rockchip RK3566/RK3568 GMAC was added without use of the
> DELAY_ENABLE macro to assist with enable/disable use of MAC rx/tx 
> delay.
> 
> Change to use the DELAY_ENABLE macro to help disable MAC delay when
> RGMII_ID/RXID/TXID is used. This also re-order to enable/disable before

s/re-order/re-orders/

> the delay is written to match all other GMAC and vendor kernel.

s/GMAC/GMACs/

> Fixes: 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index 297fa93e4a39..37eb86e4e325 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -1049,14 +1049,13 @@ static void rk3568_set_to_rgmii(struct
> rk_priv_data *bsp_priv,
>  	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
>  				     RK3568_GRF_GMAC0_CON1;
> 
> +	regmap_write(bsp_priv->grf, con1,
> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
> +		     DELAY_ENABLE(RK3568, tx_delay, rx_delay));
> +
>  	regmap_write(bsp_priv->grf, con0,
>  		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
>  		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
> -
> -	regmap_write(bsp_priv->grf, con1,
> -		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
> -		     RK3568_GMAC_RXCLK_DLY_ENABLE |
> -		     RK3568_GMAC_TXCLK_DLY_ENABLE);
>  }
> 
>  static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)

Thanks for this patch...  It's looking good to me, and good job
spotting this issue!  Please, free to include:

Reviewed-by: Dragan Simic <dsimic at manjaro.org>


From linux at armlinux.org.uk  Thu Mar  6 13:21:12 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 6 Mar 2025 21:21:12 +0000
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <20250306210950.1686713-3-jonas@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
Message-ID: <Z8oRyHThun9mLgx8@shell.armlinux.org.uk>

On Thu, Mar 06, 2025 at 09:09:46PM +0000, Jonas Karlman wrote:
> @@ -1813,8 +1564,24 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>  
>  	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>  							"rockchip,grf");
> -	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
> -							    "rockchip,php-grf");
> +	if (IS_ERR(bsp_priv->grf)) {
> +		ret = PTR_ERR(bsp_priv->grf);
> +		dev_err_probe(dev, ret, "failed to lookup rockchip,grf\n");
> +		return ERR_PTR(ret);

Did you consider using ERR_CAST() for these, which would look like this:

		dev_err_probe(dev, PTR_ERR(bsp_priv->grf),
			      "failed to lookup rockchip,grf\n");
		return ERR_CAST(bsp_priv->grf);

?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From andre.draszik at linaro.org  Thu Mar  6 13:24:40 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 21:24:40 +0000
Subject: [PATCH v3 4/4] pinctrl: samsung: Add filter selection support
 for alive bank on gs101
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-4-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
	 <20250306-pinctrl-fltcon-suspend-v3-4-f9ab4ff6a24e@linaro.org>
Message-ID: <67ad046453d722ffd80370d45f4f515a432ec327.camel@linaro.org>

On Thu, 2025-03-06 at 20:42 +0000, Peter Griffin wrote:
> Newer Exynos based SoCs have a filter selection bitfield in the filter
> configuration registers on alive bank pins. This allows the selection of
> a digital or analog delay filter for each pin. Add support for selecting
> and enabling the filter.
> 
> On suspend we set the analog filter to all pins in the bank (as the
> digital filter relies on a clock). On resume the digital filter is
> reapplied to all pins in the bank. The digital filter is working via
> a clock and has an adjustable filter delay flt_width bitfield, whereas
> the analog filter uses a fixed delay.
> 
> The filter determines to what extent signal fluctuations received through
> the pad are considered glitches.
> 
> The code path can be exercised using
> echo mem > /sys/power/state
> And then wake the device using a eint gpio
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Thu Mar  6 13:25:08 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 21:25:08 +0000
Subject: [PATCH v3 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-3-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
	 <20250306-pinctrl-fltcon-suspend-v3-3-f9ab4ff6a24e@linaro.org>
Message-ID: <2c1cab545cd3b57a2155df2e87ad9830b2b94ab1.camel@linaro.org>

On Thu, 2025-03-06 at 20:42 +0000, Peter Griffin wrote:
> gs101 differs to other SoCs in that fltcon1 register doesn't
> always exist. Additionally the offset of fltcon0 is not fixed
> and needs to use the newly added eint_fltcon_offset variable.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> Cc: stable at vger.kernel.org
> ---
> Changes since v2:
> * make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
> * align style where the '+' is placed (Andre)
> * remove unnecessary braces (Andre)
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
> ?drivers/pinctrl/samsung/pinctrl-exynos.c?????? | 70 ++++++++++++++++++++++++++
> ?drivers/pinctrl/samsung/pinctrl-exynos.h?????? |? 2 +
> ?3 files changed, 84 insertions(+), 12 deletions(-)

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Thu Mar  6 13:29:39 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Thu, 06 Mar 2025 21:29:39 +0000
Subject: [PATCH v3 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250306-pinctrl-fltcon-suspend-v3-2-f9ab4ff6a24e@linaro.org>
References: <20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e@linaro.org>
	 <20250306-pinctrl-fltcon-suspend-v3-2-f9ab4ff6a24e@linaro.org>
Message-ID: <c1b8a01c0ef3761a33c9f2530152cb2eab1ff039.camel@linaro.org>

On Thu, 2025-03-06 at 20:42 +0000, Peter Griffin wrote:
> gs101 needs it's own suspend/resume callbacks to use the newly
> added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> registers. It also differs to previous SoCs in that fltcon1
> register doesn't always exist for each bank.
> 
> exynosautov920 also has dedicated logic for using eint_con_offset
> and eint_mask_offset for saving & restoring it's registers.
> 
> Refactor the existing platform specific suspend/resume callback
> so that each SoC variant has their own callback containing the
> SoC specific logic.
> 
> Additionally we now call drvdata->suspend() & drvdata->resume()
> from within the loop that iterates the banks in
> samsung_pinctrl_suspend() and samsung_pinctrl_resume().
> 
> This simplifies the logic, and allows us to remove the
> clk_enable() and clk_disable() from the callbacks.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> Changes since v2:
> * Remove useless init (Andre)
> * make it clear set_wakeup is conditional on bank->eint_type (Andre)

I think you missed
https://lore.kernel.org/all/4f91fe1c5eed00e58a3587bceaef3e5e2a1124cf.camel at linaro.org/

See below

> Changes since v1:
> * Split code refactor & gs101 parts into separate patches (Andre)
> ---
> ?drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |? 28 ++--
> ?drivers/pinctrl/samsung/pinctrl-exynos.c?????? | 201 ++++++++++---------------
> ?drivers/pinctrl/samsung/pinctrl-exynos.h?????? |?? 6 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.c????? |? 11 +-
> ?drivers/pinctrl/samsung/pinctrl-samsung.h????? |?? 8 +-
> ?5 files changed, 109 insertions(+), 145 deletions(-)
> 
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> index e28fe81776466b693417c66bb15752d609b79eb1..57c98d2451b54b00d50e0e948e272ed53d386c34 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
> @@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> ?		.pin_banks	= exynosautov920_pin_banks0,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
> ?		.eint_wkup_init	= exynos_eint_wkup_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?		.retention_data	= &exynosautov920_retention_data,
> ?	}, {
> ?		/* pin-controller instance 1 AUD data */
> @@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
> ?		.pin_banks	= exynosautov920_pin_banks2,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 3 HSI1 data */
> ?		.pin_banks	= exynosautov920_pin_banks3,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 4 HSI2 data */
> ?		.pin_banks	= exynosautov920_pin_banks4,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 5 HSI2UFS data */
> ?		.pin_banks	= exynosautov920_pin_banks5,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 6 PERIC0 data */
> ?		.pin_banks	= exynosautov920_pin_banks6,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	}, {
> ?		/* pin-controller instance 7 PERIC1 data */
> ?		.pin_banks	= exynosautov920_pin_banks7,
> ?		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
> ?		.eint_gpio_init	= exynos_eint_gpio_init,
> -		.suspend	= exynos_pinctrl_suspend,
> -		.resume		= exynos_pinctrl_resume,
> +		.suspend	= exynosautov920_pinctrl_suspend,
> +		.resume		= exynosautov920_pinctrl_resume,
> ?	},
> ?};
> ?
> diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
> index ac6dc22b37c98ed5b7fca3335764f19abb2f71cc..f10ff09c1af01c11ff9229aaef77df32eb057b7b 100644
> --- a/drivers/pinctrl/samsung/pinctrl-exynos.c
> +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
> @@ -761,153 +761,114 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
> ?	return 0;
> ?}
> ?
> -static void exynos_pinctrl_suspend_bank(
> -				struct samsung_pinctrl_drv_data *drvdata,
> -				struct samsung_pin_bank *bank)
> +static void exynos_set_wakeup(struct samsung_pin_bank *bank)
> ?{
> -	struct exynos_eint_gpio_save *save = bank->soc_priv;
> -	const void __iomem *regs = bank->eint_base;
> +	struct exynos_irq_chip *irq_chip;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for saving state\n");
> -		return;
> +	if (bank->irq_chip) {
> +		irq_chip = bank->irq_chip;
> +		irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
> ?	}
> -
> -	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> -						+ bank->eint_offset);
> -	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset);
> -	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset + 4);
> -	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> -						+ bank->eint_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> -
> -	pr_debug("%s: save???? con %#010x\n", bank->name, save->eint_con);
> -	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
> -	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
> -	pr_debug("%s: save??? mask %#010x\n", bank->name, save->eint_mask);
> ?}
> ?
> -static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
> -					??? struct samsung_pin_bank *bank)
> +void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	const void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for saving state\n");
> -		return;
> -	}
> -
> -	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
> -	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> -
> -	pr_debug("%s: save???? con %#010x\n", bank->name, save->eint_con);
> -	pr_debug("%s: save??? mask %#010x\n", bank->name, save->eint_mask);
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +				?????? + bank->eint_offset);
> +		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +					?? + 2 * bank->eint_offset);
> +		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +					?? + 2 * bank->eint_offset + 4);
> +		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> +					+ bank->eint_offset);
> +
> +		pr_debug("%s: save???? con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save fltcon0 %#010x\n",
> +			 bank->name, save->eint_fltcon0);
> +		pr_debug("%s: save fltcon1 %#010x\n",
> +			 bank->name, save->eint_fltcon1);
> +		pr_debug("%s: save??? mask %#010x\n",
> +			 bank->name, save->eint_mask);
> +	} else if (bank->eint_type == EINT_TYPE_WKUP)
> +		exynos_set_wakeup(bank);
> ?}
> ?
> -void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
> +void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
> ?{
> -	struct samsung_pin_bank *bank = drvdata->pin_banks;
> -	struct exynos_irq_chip *irq_chip = NULL;
> -	int i;
> +	struct exynos_eint_gpio_save *save = bank->soc_priv;
> +	const void __iomem *regs = bank->eint_base;
> ?
> -	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
> -		if (bank->eint_type == EINT_TYPE_GPIO) {
> -			if (bank->eint_con_offset)
> -				exynosauto_pinctrl_suspend_bank(drvdata, bank);
> -			else
> -				exynos_pinctrl_suspend_bank(drvdata, bank);
> -		}
> -		else if (bank->eint_type == EINT_TYPE_WKUP) {
> -			if (!irq_chip) {
> -				irq_chip = bank->irq_chip;
> -				irq_chip->set_eint_wakeup_mask(drvdata,
> -							?????? irq_chip);
> -			}
> -		}
> -	}
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		save->eint_con = readl(regs + bank->pctl_offset +
> +				?????? bank->eint_con_offset);
> +		save->eint_mask = readl(regs + bank->pctl_offset +
> +					bank->eint_mask_offset);
> +		pr_debug("%s: save???? con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save??? mask %#010x\n",
> +			 bank->name, save->eint_mask);
> +	} else if (bank->eint_type == EINT_TYPE_WKUP)
> +		exynos_set_wakeup(bank);
> ?}
> ?
> -static void exynos_pinctrl_resume_bank(
> -				struct samsung_pinctrl_drv_data *drvdata,
> -				struct samsung_pin_bank *bank)
> +void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for restoring state\n");
> -		return;
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +			?????? + bank->eint_offset), save->eint_con);
> +		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +			?????? + 2 * bank->eint_offset), save->eint_fltcon0);
> +		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> +			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +			?????? + 2 * bank->eint_offset + 4),
> +			?????? save->eint_fltcon1);

here

> +		pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->irq_chip->eint_mask
> +			?????? + bank->eint_offset), save->eint_mask);
> +
> +		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> +		?????? + bank->eint_offset);
> +		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +		?????? + 2 * bank->eint_offset);
> +		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +		?????? + 2 * bank->eint_offset + 4);
> +		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> +		?????? + bank->eint_offset);
> ?	}
> -
> -	pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_ECON_OFFSET
> -			+ bank->eint_offset), save->eint_con);
> -	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -			+ 2 * bank->eint_offset), save->eint_fltcon0);
> -	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
> -			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
> -	pr_debug("%s:??? mask %#010x => %#010x\n", bank->name,
> -			readl(regs + bank->irq_chip->eint_mask
> -			+ bank->eint_offset), save->eint_mask);
> -
> -	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
> -						+ bank->eint_offset);
> -	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset);
> -	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
> -						+ 2 * bank->eint_offset + 4);
> -	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
> -						+ bank->eint_offset);
> -
> -	clk_disable(bank->drvdata->pclk);
> ?}
> ?
> -static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
> -					?? struct samsung_pin_bank *bank)
> +void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
> ?{
> ?	struct exynos_eint_gpio_save *save = bank->soc_priv;
> ?	void __iomem *regs = bank->eint_base;
> ?
> -	if (clk_enable(bank->drvdata->pclk)) {
> -		dev_err(bank->gpio_chip.parent,
> -			"unable to enable clock for restoring state\n");
> -		return;
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		/* exynosautov920 has eint_con_offset for all but one bank */
> +		if (!bank->eint_con_offset)
> +			exynos_pinctrl_resume(bank);
> +
> +		pr_debug("%s:???? con %#010x => %#010x\n", bank->name,
> +			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
> +			?????? save->eint_con);

and here.

Cheers,
A.



From dsimic at manjaro.org  Thu Mar  6 13:33:23 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 06 Mar 2025 22:33:23 +0100
Subject: [PATCH 3/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3588
In-Reply-To: <20250306203858.1677595-4-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-4-jonas@kwiboo.se>
Message-ID: <8323ba9aba1155004bcd201b4fd7b2fa@manjaro.org>

Hello Jonas,

On 2025-03-06 21:38, Jonas Karlman wrote:
> Support for Rockchip RK3588 GMAC was added without use of the
> DELAY_ENABLE macro to assist with enable/disable use of MAC rx/tx 
> delay.
> 
> Change to use a variant of the DELAY_ENABLE macro to help disable MAC
> delay when RGMII_ID/RXID/TXID is used.
> 
> Fixes: 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac
> support for rk3588")
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index 37eb86e4e325..79db81d68afd 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -91,6 +91,10 @@ struct rk_priv_data {
>  	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) 
> | \
>  	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
> 
> +#define DELAY_ENABLE_BY_ID(soc, tx, rx, id) \
> +	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE(id) : 
> soc##_GMAC_TXCLK_DLY_DISABLE(id)) | \
> +	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE(id) : 
> soc##_GMAC_RXCLK_DLY_DISABLE(id)))
> +
>  #define PX30_GRF_GMAC_CON1		0x0904
> 
>  /* PX30_GRF_GMAC_CON1 */
> @@ -1322,8 +1326,7 @@ static void rk3588_set_to_rgmii(struct
> rk_priv_data *bsp_priv,
>  		     RK3588_GMAC_CLK_RGMII_MODE(id));
> 
>  	regmap_write(bsp_priv->grf, RK3588_GRF_GMAC_CON7,
> -		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
> -		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
> +		     DELAY_ENABLE_BY_ID(RK3588, tx_delay, rx_delay, id));
> 
>  	regmap_write(bsp_priv->grf, offset_con,
>  		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |

Thanks for this patch...  It's looking good to me, and good job
spotting this issue!  Please, free to include:

Reviewed-by: Dragan Simic <dsimic at manjaro.org>


From dsimic at manjaro.org  Thu Mar  6 13:41:03 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 06 Mar 2025 22:41:03 +0100
Subject: [PATCH 0/3] Use DELAY_ENABLE macro for RK3328, RK3566/RK3568 and
 RK3588
In-Reply-To: <20250306203858.1677595-1-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
Message-ID: <41bb2c8d963e890768bceb477488250e@manjaro.org>

Hello Jonas,

On 2025-03-06 21:38, Jonas Karlman wrote:
> Almost all Rockchip GMAC variants use the DELAY_ENABLE macro to help
> enable or disable use of MAC rx/tx delay. However, RK3328, 
> RK3566/RK3568
> and RK3588 GMAC driver does not.
> 
> Use of the DELAY_ENABLE macro help ensure the MAC rx/tx delay is
> disabled, instead of being enabled and using a zero delay, when
> RGMII_ID/RXID/TXID is used.
> 
> RK3328 driver was merged around the same time as when DELAY_ENABLE was
> introduced so it is understandable why it was missed. Both 
> RK3566/RK3568
> and RK3588 support were introduced much later yet they also missed 
> using
> the DELAY_ENABLE macro (so did vendor kernel at that time).
> 
> This series fixes all these cases to unify how GMAC delay feature is
> enabled or disabled across the different GMAC variants.
> 
> Jonas Karlman (3):
>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3328
>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3566/RK3568
>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3588
> 
>  .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)

As far as I can tell, the RV1126 GMAC should also be converted to use
the DELAY_ENABLE macro, which the vendor kernel already does. [*]  
Perhaps
that could be performed in new patch 4/4 in this series?

BTW, it would be quite neat to introduce the DELAY_VALUE macro, which
makes the function calls a bit more compact. [*]

[*] 
https://raw.githubusercontent.com/rockchip-linux/kernel/refs/heads/develop-5.10/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c


From sfr at canb.auug.org.au  Thu Mar  6 14:06:38 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Fri, 7 Mar 2025 09:06:38 +1100
Subject: linux-next: duplicate patch in the omap-fixes tree
Message-ID: <20250307090638.50776e07@canb.auug.org.au>

Hi all,

The following commit is also in the arm-soc-fixes tree as a different
commit (but the same patch):

  c2a5f8c4f28f ("ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP")

This is commit

  98f3ab18a0a5 ("ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP")

in te arm-soc-fixes tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/93a72331/attachment.sig>

From jonas at kwiboo.se  Thu Mar  6 14:07:23 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 23:07:23 +0100
Subject: [PATCH 0/3] Use DELAY_ENABLE macro for RK3328, RK3566/RK3568 and
 RK3588
In-Reply-To: <41bb2c8d963e890768bceb477488250e@manjaro.org>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <41bb2c8d963e890768bceb477488250e@manjaro.org>
Message-ID: <3ab13afd-0a9f-485e-bdf2-7b413d418065@kwiboo.se>

Hi Dragan,

On 2025-03-06 22:41, Dragan Simic wrote:
> Hello Jonas,
> 
> On 2025-03-06 21:38, Jonas Karlman wrote:
>> Almost all Rockchip GMAC variants use the DELAY_ENABLE macro to help
>> enable or disable use of MAC rx/tx delay. However, RK3328, 
>> RK3566/RK3568
>> and RK3588 GMAC driver does not.
>>
>> Use of the DELAY_ENABLE macro help ensure the MAC rx/tx delay is
>> disabled, instead of being enabled and using a zero delay, when
>> RGMII_ID/RXID/TXID is used.
>>
>> RK3328 driver was merged around the same time as when DELAY_ENABLE was
>> introduced so it is understandable why it was missed. Both 
>> RK3566/RK3568
>> and RK3588 support were introduced much later yet they also missed 
>> using
>> the DELAY_ENABLE macro (so did vendor kernel at that time).
>>
>> This series fixes all these cases to unify how GMAC delay feature is
>> enabled or disabled across the different GMAC variants.
>>
>> Jonas Karlman (3):
>>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3328
>>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3566/RK3568
>>   net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for RK3588
>>
>>  .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 19 ++++++++++---------
>>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> As far as I can tell, the RV1126 GMAC should also be converted to use
> the DELAY_ENABLE macro, which the vendor kernel already does. [*]  
> Perhaps
> that could be performed in new patch 4/4 in this series?

Good catch, the RV1126 seem to use a slight different M0/M1 variant and
unfortunately I do not have access to any RV1126 board to do any runtime
testing. For RK3328, RK356x and RK3588 I could at least do runtime
testing.

I can add an untested patch for RV1126 in a v2 if needed :-)

> 
> BTW, it would be quite neat to introduce the DELAY_VALUE macro, which
> makes the function calls a bit more compact. [*]

Personally, I do not see a real need for the DELAY_VALUE macro, current
use of the soc_GMAC_CLK_yX_DL_CFG() macro is readable enough.

The ENABLE_DELAY at least helps remove an otherwise more complex enable
or disable conditional handling.

Regards,
Jonas

> 
> [*] 
> https://raw.githubusercontent.com/rockchip-linux/kernel/refs/heads/develop-5.10/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c



From jonas at kwiboo.se  Thu Mar  6 14:13:56 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 22:13:56 +0000
Subject: [PATCH 3/4] arm64: dts: rockchip: Add GMAC nodes for RK3528
In-Reply-To: <20250306221402.1704196-1-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
Message-ID: <20250306221402.1704196-4-jonas@kwiboo.se>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add device tree nodes for the two Ethernet controllers in RK3528.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
gmac0 is missing the integrated-phy and has not been tested bacause I do
not have any board that use this Ethernet controller.
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 92 ++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index c1a71ea81e03..5940719cffec 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -286,6 +286,98 @@ saradc: adc at ffae0000 {
 			#io-channel-cells = <1>;
 		};
 
+		gmac0: ethernet at ffbd0000 {
+			compatible = "rockchip,rk3528-gmac", "snps,dwmac-4.20a";
+			reg = <0x0 0xffbd0000 0x0 0x10000>;
+			clocks = <&cru CLK_GMAC0_SRC>, <&cru CLK_GMAC0_RMII_50M>,
+				 <&cru CLK_GMAC0_RX>, <&cru CLK_GMAC0_TX>,
+				 <&cru PCLK_MAC_VO>, <&cru ACLK_MAC_VO>;
+			clock-names = "stmmaceth", "clk_mac_ref",
+				      "mac_clk_rx", "mac_clk_tx",
+				      "pclk_mac", "aclk_mac";
+			interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq";
+			resets = <&cru SRST_A_MAC_VO>;
+			reset-names = "stmmaceth";
+			rockchip,grf = <&vo_grf>;
+			snps,axi-config = <&gmac0_stmmac_axi_setup>;
+			snps,mixed-burst;
+			snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
+			snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
+			snps,tso;
+			status = "disabled";
+
+			mdio0: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+			};
+
+			gmac0_stmmac_axi_setup: stmmac-axi-config {
+				snps,blen = <0 0 0 0 16 8 4>;
+				snps,rd_osr_lmt = <8>;
+				snps,wr_osr_lmt = <4>;
+			};
+
+			gmac0_mtl_rx_setup: rx-queues-config {
+				snps,rx-queues-to-use = <1>;
+				queue0 {};
+			};
+
+			gmac0_mtl_tx_setup: tx-queues-config {
+				snps,tx-queues-to-use = <1>;
+				queue0 {};
+			};
+		};
+
+		gmac1: ethernet at ffbe0000 {
+			compatible = "rockchip,rk3528-gmac", "snps,dwmac-4.20a";
+			reg = <0x0 0xffbe0000 0x0 0x10000>;
+			clocks = <&cru CLK_GMAC1_SRC_VPU>,
+				 <&cru CLK_GMAC1_RMII_VPU>,
+				 <&cru PCLK_MAC_VPU>,
+				 <&cru ACLK_MAC_VPU>;
+			clock-names = "stmmaceth",
+				      "clk_mac_ref",
+				      "pclk_mac",
+				      "aclk_mac";
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq";
+			resets = <&cru SRST_A_MAC>;
+			reset-names = "stmmaceth";
+			rockchip,grf = <&vpu_grf>;
+			snps,axi-config = <&gmac1_stmmac_axi_setup>;
+			snps,mixed-burst;
+			snps,mtl-rx-config = <&gmac1_mtl_rx_setup>;
+			snps,mtl-tx-config = <&gmac1_mtl_tx_setup>;
+			snps,tso;
+			status = "disabled";
+
+			mdio1: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+			};
+
+			gmac1_stmmac_axi_setup: stmmac-axi-config {
+				snps,blen = <0 0 0 0 16 8 4>;
+				snps,rd_osr_lmt = <8>;
+				snps,wr_osr_lmt = <4>;
+			};
+
+			gmac1_mtl_rx_setup: rx-queues-config {
+				snps,rx-queues-to-use = <1>;
+				queue0 {};
+			};
+
+			gmac1_mtl_tx_setup: tx-queues-config {
+				snps,tx-queues-to-use = <1>;
+				queue0 {};
+			};
+		};
+
 		sdhci: mmc at ffbf0000 {
 			compatible = "rockchip,rk3528-dwcmshc",
 				     "rockchip,rk3588-dwcmshc";
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 14:13:53 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 22:13:53 +0000
Subject: [PATCH 0/4] rockchip: Enable Ethernet controller on Radxa E20C
Message-ID: <20250306221402.1704196-1-jonas@kwiboo.se>

The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
used with the integrated PHY and a second 1000/100/10 MAC to be used
with an external Ethernet PHY.

This series add initial support for the Ethernet controllers found in
RK3528 and enable the LAN interface on Radxa E20C.

This only add a bare minimum gmac0 node for the 100/10 MAC and skip e.g.
parts to power on and off the integrated PHY in GMAC driver becayse I do
not have any RK3528 device that make use of gmac0.

This series depends on the "net: stmmac: dwmac-rk: Validate rockchip,grf
and php-grf during probe" cleanup series to ensure bsp_priv->grf can be
used. And possible also on the leds+buttons, sdio+sdmmc and sdhci series
for RK3528 for a clean apply.

David Wu (1):
  ethernet: stmmac: dwmac-rk: Add GMAC support for RK3528

Jonas Karlman (3):
  dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
  arm64: dts: rockchip: Add GMAC nodes for RK3528
  arm64: dts: rockchip: Enable Ethernet controller on Radxa E20C

 .../bindings/net/rockchip-dwmac.yaml          |   4 +-
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   |  30 ++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      |  92 ++++++++++++
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 132 ++++++++++++++++++
 4 files changed, 257 insertions(+), 1 deletion(-)

-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 14:13:54 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 22:13:54 +0000
Subject: [PATCH 1/4] dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
In-Reply-To: <20250306221402.1704196-1-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
Message-ID: <20250306221402.1704196-2-jonas@kwiboo.se>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add compatible string for the RK3528 variant.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
I was not able to restrict the minItems change to only apply to the new
compatible, please advise on how to properly restrict the minItems
change if needed.

Also, because snps,dwmac-4.20a is already listed in snps,dwmac.yaml
adding the rockchip,rk3528-gmac compatible did not seem necessary.
---
 Documentation/devicetree/bindings/net/rockchip-dwmac.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
index 05a5605f1b51..3c25b49bd78e 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
@@ -24,6 +24,7 @@ select:
           - rockchip,rk3366-gmac
           - rockchip,rk3368-gmac
           - rockchip,rk3399-gmac
+          - rockchip,rk3528-gmac
           - rockchip,rk3568-gmac
           - rockchip,rk3576-gmac
           - rockchip,rk3588-gmac
@@ -49,6 +50,7 @@ properties:
               - rockchip,rv1108-gmac
       - items:
           - enum:
+              - rockchip,rk3528-gmac
               - rockchip,rk3568-gmac
               - rockchip,rk3576-gmac
               - rockchip,rk3588-gmac
@@ -56,7 +58,7 @@ properties:
           - const: snps,dwmac-4.20a
 
   clocks:
-    minItems: 5
+    minItems: 4
     maxItems: 8
 
   clock-names:
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 14:13:55 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 22:13:55 +0000
Subject: [PATCH 2/4] ethernet: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <20250306221402.1704196-1-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
Message-ID: <20250306221402.1704196-3-jonas@kwiboo.se>

From: David Wu <david.wu at rock-chips.com>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add initial support for the RK3528 variants.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
This does not include power on/off support for the integrated PHY.
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 132 ++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index ba1cd079adf2..0ae3ffacb794 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -830,6 +830,137 @@ static const struct rk_gmac_ops rk3399_ops = {
 	.set_rmii_speed = rk3399_set_rmii_speed,
 };
 
+#define RK3528_VO_GRF_GMAC_CON		0x0018
+#define RK3528_VO_GRF_MACPHY_CON0	0x001c
+#define RK3528_VO_GRF_MACPHY_CON1	0x0020
+#define RK3528_VPU_GRF_GMAC_CON5	0x0018
+#define RK3528_VPU_GRF_GMAC_CON6	0x001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII	GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII	GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII	GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELECT_CRU	GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELECT_IO	GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2	GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20	GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2	GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20	GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1	(GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5	(GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50	(GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE	GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE	GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE	GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE	GRF_CLR_BIT(9)
+
+static void rk3528_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
+{
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     DELAY_ENABLE(RK3528, tx_delay, rx_delay));
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON6,
+		     RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+	if (bsp_priv->id == 1)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_PHY_INTF_SEL_RMII);
+	else
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON,
+			     RK3528_GMAC0_PHY_INTF_SEL_RMII |
+			     RK3528_GMAC0_CLK_RMII_DIV2);
+}
+
+static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (speed == 10)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV50);
+	else if (speed == 100)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV5);
+	else if (speed == 1000)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV1);
+	else
+		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+	unsigned int reg, val;
+
+	if (speed == 10)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 :
+					  RK3528_GMAC0_CLK_RMII_DIV20;
+	else if (speed == 100)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 :
+					  RK3528_GMAC0_CLK_RMII_DIV2;
+	else {
+		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+		return;
+	}
+
+	reg = bsp_priv->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 :
+				  RK3528_VO_GRF_GMAC_CON;
+
+	regmap_write(bsp_priv->grf, reg, val);
+}
+
+static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
+				       bool input, bool enable)
+{
+	unsigned int val;
+
+	if (bsp_priv->id == 1) {
+		val = input ? RK3528_GMAC1_CLK_SELECT_IO :
+			      RK3528_GMAC1_CLK_SELECT_CRU;
+		val |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+				RK3528_GMAC1_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+	} else {
+		val = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+			       RK3528_GMAC0_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON, val);
+	}
+}
+
+static const struct rk_gmac_ops rk3528_ops = {
+	.set_to_rgmii = rk3528_set_to_rgmii,
+	.set_to_rmii = rk3528_set_to_rmii,
+	.set_rgmii_speed = rk3528_set_rgmii_speed,
+	.set_rmii_speed = rk3528_set_rmii_speed,
+	.set_clock_selection = rk3528_set_clock_selection,
+	.regs_valid = true,
+	.regs = {
+		0xffbd0000, /* gmac0 */
+		0xffbe0000, /* gmac1 */
+		0x0, /* sentinel */
+	},
+};
+
 #define RK3568_GRF_GMAC0_CON0		0x0380
 #define RK3568_GRF_GMAC0_CON1		0x0384
 #define RK3568_GRF_GMAC1_CON0		0x0388
@@ -1816,6 +1947,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
 	{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
 	{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
+	{ .compatible = "rockchip,rk3528-gmac", .data = &rk3528_ops },
 	{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
 	{ .compatible = "rockchip,rk3576-gmac", .data = &rk3576_ops },
 	{ .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },
-- 
2.48.1



From jonas at kwiboo.se  Thu Mar  6 14:13:57 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu,  6 Mar 2025 22:13:57 +0000
Subject: [PATCH 4/4] arm64: dts: rockchip: Enable Ethernet controller on Radxa E20C
In-Reply-To: <20250306221402.1704196-1-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
Message-ID: <20250306221402.1704196-5-jonas@kwiboo.se>

The Radxa E20C has two GbE ports, LAN and WAN. The LAN port is provided
using a GMAC controller and a YT8531C PHY and the WAN port is provided
by an RTL8111H PCIe Ethernet controller.

Enable support for the LAN port on Radxa E20C.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index a511e2a2d4a5..61ba0471095a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -16,6 +16,7 @@ / {
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
 	aliases {
+		ethernet0 = &gmac1;
 		mmc0 = &sdhci;
 		mmc1 = &sdmmc;
 	};
@@ -123,7 +124,36 @@ vccio_sd: regulator-vccio-sd {
 	};
 };
 
+&gmac1 {
+	clock_in_out = "output";
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-id";
+	phy-supply = <&vcc_3v3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_miim>, <&rgmii_tx_bus2>, <&rgmii_rx_bus2>,
+		    <&rgmii_rgmii_clk>, <&rgmii_rgmii_bus>;
+	status = "okay";
+};
+
+&mdio1 {
+	rgmii_phy: ethernet-phy at 1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0x1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&gmac1_rstn_l>;
+		reset-assert-us = <20000>;
+		reset-deassert-us = <100000>;
+		reset-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
+	};
+};
+
 &pinctrl {
+	ethernet {
+		gmac1_rstn_l: gmac1-rstn-l {
+			rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	gpio-keys {
 		user_key: user-key {
 			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
-- 
2.48.1



From Frank.Li at nxp.com  Thu Mar  6 14:23:58 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu,  6 Mar 2025 17:23:58 -0500
Subject: [PATCH] ARM64: dts: imx8mp-evk: add ecspi2 support
Message-ID: <20250306222359.797855-1-Frank.Li@nxp.com>

From: Clark Wang <xiaoning.wang at nxp.com>

Add ecspi2 node to support ECSPI on i.MX8MP EVK board.

Signed-off-by: Clark Wang <xiaoning.wang at nxp.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 30 ++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index c26954e5a6056..566fcf6aa5ef6 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -309,6 +309,22 @@ &aud2htx {
 	status = "okay";
 };
 
+&ecspi2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;
+	cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	spidev1: spi at 0 {
+		compatible = "rohm,dh2228fv";
+		reg = <0>;
+		spi-max-frequency = <500000>;
+	};
+};
+
 &eqos {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_eqos>;
@@ -835,6 +851,20 @@ MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29		0xd6
 		>;
 	};
 
+	pinctrl_ecspi2: ecspi2grp {
+		fsl,pins = <
+			MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK		0x82
+			MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI		0x82
+			MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO		0x82
+		>;
+	};
+
+	pinctrl_ecspi2_cs: ecspi2csgrp {
+		fsl,pins = <
+			MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13		0x40000
+		>;
+	};
+
 	pinctrl_eqos: eqosgrp {
 		fsl,pins = <
 			MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC				0x2
-- 
2.34.1



From andrew at lunn.ch  Thu Mar  6 14:25:15 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 6 Mar 2025 23:25:15 +0100
Subject: [PATCH 1/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3328
In-Reply-To: <20250306203858.1677595-2-jonas@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-2-jonas@kwiboo.se>
Message-ID: <d6b15dc2-f6b2-4703-a4da-07618eaed4db@lunn.ch>

On Thu, Mar 06, 2025 at 08:38:52PM +0000, Jonas Karlman wrote:
> Support for Rockchip RK3328 GMAC and addition of the DELAY_ENABLE macro
> was merged in the same merge window. This resulted in RK3328 not being
> converted to use the new DELAY_ENABLE macro.
> 
> Change to use the DELAY_ENABLE macro to help disable MAC delay when
> RGMII_ID/RXID/TXID is used.
> 
> Fixes: eaf70ad14cbb ("net: stmmac: dwmac-rk: Add handling for RGMII_ID/RXID/TXID")

Please add a description of the broken behaviour. How would i know i
need this fix? What would i see?

We also need to be careful with backwards compatibility. Is there the
potential for double bugs cancelling each other out? A board which has
the wrong phy-mode in DT, but because of this bug, the wrong register
is written and it actually works because of reset defaults?

    Andrew

---
pw-bot: cr


From kuba at kernel.org  Thu Mar  6 14:28:42 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Thu, 6 Mar 2025 14:28:42 -0800
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <20250304072201.1332603-2-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-2-wei.fang@nxp.com>
Message-ID: <20250306142842.476db52c@kernel.org>

On Tue,  4 Mar 2025 15:21:49 +0800 Wei Fang wrote:
> +config NXP_NETC_LIB
> +	tristate "NETC Library"

Remove the string after "tristate", the user should not be prompted
to make a choice for this, since the consumers "select" this config
directly.

> +	help
> +	  This module provides common functionalities for both ENETC and NETC
> +	  Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
> +	  flower and debugfs interfaces and so on.
> +
> +	  If compiled as module (M), the module name is nxp-netc-lib.

Not sure if the help makes sense for an invisible symbol either.

>  config FSL_ENETC
>  	tristate "ENETC PF driver"
>  	depends on PCI_MSI
> @@ -40,6 +50,7 @@ config NXP_ENETC4
>  	select FSL_ENETC_CORE
>  	select FSL_ENETC_MDIO
>  	select NXP_ENETC_PF_COMMON
> +	select NXP_NETC_LIB
>  	select PHYLINK
>  	select DIMLIB
>  	help

> +#pragma pack(1)

please don't blindly pack all structs, only if they are misaligned 
or will otherwise have holes.

> +#if IS_ENABLED(CONFIG_NXP_NETC_LIB)

why the ifdef, all callers select the config option



From andrew at lunn.ch  Thu Mar  6 14:32:18 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 6 Mar 2025 23:32:18 +0100
Subject: [PATCH 1/2] dt-bindings: net: rockchip-dwmac: Require
 rockchip,grf and rockchip,php-grf
In-Reply-To: <20250306210950.1686713-2-jonas@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-2-jonas@kwiboo.se>
Message-ID: <5d69f4a2-511a-4e7e-bafe-5ce6171cb1d5@lunn.ch>

On Thu, Mar 06, 2025 at 09:09:45PM +0000, Jonas Karlman wrote:
> All Rockchip GMAC variants require writing to GRF to configure e.g.
> interface mode and MAC rx/tx delay.
> 
> Change binding to require rockchip,grf and rockchip,php-grf to reflect
> that GRF (and PHP-GRF for RK3576/RK3588) control part of GMAC.

It is pretty unusual to change the binding such that something
optional becomes mandatory. I would expect a bit more of a comment
explaining why this does not cause backwards compatibility
issues. Have all the .dtsi files always had these properties?

    Andrew

---
pw-bot: cr


From kuba at kernel.org  Thu Mar  6 14:34:27 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Thu, 6 Mar 2025 14:34:27 -0800
Subject: [PATCH v3 net-next 06/13] net: enetc: add RSS support for
 i.MX95 ENETC PF
In-Reply-To: <20250304072201.1332603-7-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-7-wei.fang@nxp.com>
Message-ID: <20250306143427.2bf83572@kernel.org>

On Tue,  4 Mar 2025 15:21:54 +0800 Wei Fang wrote:
> Add Receive side scaling (RSS) support for i.MX95 ENETC PF to improve
> the network performance and balance the CPU loading. The main changes
> are as follows.
> 
> 1. Since i.MX95 ENETC (v4) use NTMP 2.0 to manage the RSS table, which
> is different from LS1028A ENETC (v1). In order to reuse some functions
> related to the RSS table, so add .get_rss_table() and .set_rss_table()
> hooks to enetc_si_ops.
> 
> 2. Since the offset of the RSS key registers of i.MX95 ENETC is also
> different from that of LS1028A, so add enetc_get_rss_key_base() to get
> the base offset for the different chips, so that enetc_set_rss_key()
> and enetc_get_rss_key() can be reused for this trivial.

Please split this patch into refactoring of existing code and new
additions.


From kuba at kernel.org  Thu Mar  6 14:35:05 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Thu, 6 Mar 2025 14:35:05 -0800
Subject: [PATCH v3 net-next 07/13] net: enetc: check if the RSS hfunc is
 toeplitz
In-Reply-To: <20250304072201.1332603-8-wei.fang@nxp.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-8-wei.fang@nxp.com>
Message-ID: <20250306143505.00f034e3@kernel.org>

On Tue,  4 Mar 2025 15:21:55 +0800 Wei Fang wrote:
> Both ENETC v1 and ENETC v4 only support the toeplitz algorithm for RSS,
> so add a check for RSS hfunc.

Rejecting unsupported configurations is considered a fix,
please send it to net with a Fixes tag.
-- 
pw-bot: cr


From andrew at lunn.ch  Thu Mar  6 14:37:27 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 6 Mar 2025 23:37:27 +0100
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <20250306210950.1686713-3-jonas@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
Message-ID: <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>

On Thu, Mar 06, 2025 at 09:09:46PM +0000, Jonas Karlman wrote:
> All Rockchip GMAC variants require writing to GRF to configure e.g.
> interface mode and MAC rx/tx delay. The GRF syscon regmap is located
> with help of a rockchip,grf and rockchip,php-grf phandle.

> @@ -1813,8 +1564,24 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>  
>  	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>  							"rockchip,grf");
> -	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
> -							    "rockchip,php-grf");
> +	if (IS_ERR(bsp_priv->grf)) {
> +		ret = PTR_ERR(bsp_priv->grf);
> +		dev_err_probe(dev, ret, "failed to lookup rockchip,grf\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	bsp_priv->php_grf =
> +		syscon_regmap_lookup_by_phandle_optional(dev->of_node,
> +							 "rockchip,php-grf");
> +	if ((of_device_is_compatible(dev->of_node, "rockchip,rk3588-gmac") ||
> +	     of_device_is_compatible(dev->of_node, "rockchip,rk3576-gmac")) &&
> +	    !bsp_priv->php_grf)
> +		bsp_priv->php_grf = ERR_PTR(-ENODEV);

It seems odd you say all variants need this property, and then you
look for two specific variants here and do something different? Why
are these two special?

	Andrew


From andrew at lunn.ch  Thu Mar  6 14:46:39 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 6 Mar 2025 23:46:39 +0100
Subject: [PATCH 3/4] arm64: dts: rockchip: Add GMAC nodes for RK3528
In-Reply-To: <20250306221402.1704196-4-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-4-jonas@kwiboo.se>
Message-ID: <a827e7e9-882a-40c6-9f2c-03d8181dff88@lunn.ch>

On Thu, Mar 06, 2025 at 10:13:56PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
> Ethernet QoS IP.
> 
> Add device tree nodes for the two Ethernet controllers in RK3528.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
> gmac0 is missing the integrated-phy and has not been tested bacause I do
> not have any board that use this Ethernet controller.

What do you know about the integrated PHY? Does it use one of the
standard phy-modes? RMII? Does the datasheet indicate what address it
uses on the MDIO bus? If you know these two bits of information, you
can probably add it.

    Andrew


From andrew at lunn.ch  Thu Mar  6 14:49:31 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 6 Mar 2025 23:49:31 +0100
Subject: [PATCH 4/4] arm64: dts: rockchip: Enable Ethernet controller on
 Radxa E20C
In-Reply-To: <20250306221402.1704196-5-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-5-jonas@kwiboo.se>
Message-ID: <e0e8fa5e-07a2-4f4f-80b9-ddb2332c27ea@lunn.ch>

> +&mdio1 {
> +	rgmii_phy: ethernet-phy at 1 {
> +		compatible = "ethernet-phy-ieee802.3-c22";

The compatible is not needed. That is the default.

	Andrew


From jonas at kwiboo.se  Thu Mar  6 14:53:27 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 6 Mar 2025 23:53:27 +0100
Subject: [PATCH 1/3] dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible
 string for RK3528
In-Reply-To: <20250306-frisky-spiffy-bullmastiff-ad9e49@krzk-bin>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
 <20250305214108.1327208-2-jonas@kwiboo.se>
 <20250306-frisky-spiffy-bullmastiff-ad9e49@krzk-bin>
Message-ID: <24a8691f-9faf-4657-b819-183fec3d1a15@kwiboo.se>

Hi Krzysztof,

On 2025-03-06 10:36, Krzysztof Kozlowski wrote:
> On Wed, Mar 05, 2025 at 09:41:02PM +0000, Jonas Karlman wrote:
>> The SDHCI controller in Rockchip RK3528 is similar to the one included
>> in RK3588.
>>
>> Add compatible string for the SDHCI controller in RK3528.
>>
>> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
>> ---
> 
> No power domains here? Post complete support, so this won't have to be
> changed in near future.

To my knowledge this should be complete support. However, there are some
rx/tx tap num and strobe delay num configuration that needs to be tuned
to fully support the faster HS400/HS400ES transfer modes.

For that we could need something like the PHY output/input tap delays
described in mmc/sdhci-am654.yaml. Still unclear to me if the different
delayed used by vendor driver is SoC specific and can live in driver or
if they instead are reference board specific and could be part of the
device tree.

Regards,
Jonas

> 
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> Best regards,
> Krzysztof
> 



From festevam at gmail.com  Thu Mar  6 14:55:36 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 6 Mar 2025 19:55:36 -0300
Subject: [PATCH] ARM64: dts: imx8mp-evk: add ecspi2 support
In-Reply-To: <20250306222359.797855-1-Frank.Li@nxp.com>
References: <20250306222359.797855-1-Frank.Li@nxp.com>
Message-ID: <CAOMZO5CL-qQSHuSoCtb+f_mqNG8vu4tTVDi-ThoHq+m9SeagxA@mail.gmail.com>

On Thu, Mar 6, 2025 at 7:24?PM Frank Li <Frank.Li at nxp.com> wrote:

> +&ecspi2 {
> +       #address-cells = <1>;
> +       #size-cells = <0>;
> +       num-cs = <1>;
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;
> +       cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
> +       status = "okay";
> +
> +       spidev1: spi at 0 {
> +               compatible = "rohm,dh2228fv";

That's not a correct description of the hardware.

Conor's effort was to clean up the abuses of using "rohm,dh2228fv" to
get spidev support.

Please check:

fc28d1c1fe3b3 ("spi: spidev: add correct compatible for Rohm BH2228FV")


From jonas at kwiboo.se  Thu Mar  6 15:05:16 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:05:16 +0100
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers
 for RK3528
In-Reply-To: <Z8nPjjbZvpRJ2R5B@pie.lan>
References: <20250305194612.47171-1-ziyao@disroot.org>
 <20250306140009.384469-1-amadeus@jmu.edu.cn> <Z8nPjjbZvpRJ2R5B@pie.lan>
Message-ID: <3d3db030-26e6-4fe1-9158-85f8cebef89c@kwiboo.se>

On 2025-03-06 17:43, Yao Zi wrote:
> On Thu, Mar 06, 2025 at 10:00:09PM +0800, Chukun Pan wrote:
>> Hi,
>>
>>> +		sdio0: mmc at ffc10000 {
>>> +			compatible = "rockchip,rk3528-dw-mshc",
>>> +				     "rockchip,rk3288-dw-mshc";
>>> +			reg = <0x0 0xffc10000 0x0 0x4000>;
>>> +			clocks = <&cru HCLK_SDIO0>,
>>> +				 <&cru CCLK_SRC_SDIO0>,
>>> +				 <&cru SCLK_SDIO0_DRV>,
>>> +				 <&cru SCLK_SDIO0_SAMPLE>;
>>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
>>> +			fifo-depth = <0x100>;
>>> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
>>> +			max-frequency = <150000000>;
>>> +			pinctrl-names = "default";
>>> +			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
>>> +				    <&sdio0_det>, <&sdio0_pwren>;
>>
>> The sdio module is usually "non-removable", no need det,
>> and pwren may be other gpio (use mmc-pwrseq). So it should
>> be `pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>;`
> 
> This doesn't affect the fact that these two pins are assigned as
> functional pins for SDIO0, as pointed out by the datasheet[1].
> 
> But with more digging, I found the reference design[2] of Rockchip
> actually uses the two pins as normal GPIOs. This is more obvious in
> downstream devicetree of an EVB[3]. Most of the existing boards (Radxa
> 2A, ArmSOM Sige 1) follow the reference design.
> 
> For me, it's kind of surprising that the SDIO IP functions with two
> functional pins assigned as different modes. I'm not sure whether we
> should apply pin configuration for these two pins in the SoC devicetree.
> Jonas, what do you think about it?

I think it make sense to match the pins used by reference boards, i.e.
the pinconf most likely to be used by majority of boards that will use
the sdio interface.

Of my RK3528 boards, only ArmSoM Sige1 use sdio for onboard wifi and
there I currently have following in my work-in-progress board DT [4]:

  pinctrl-names = "default";
  pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>, <&clkm1_32k_out>;

The Radxa ROCK 2A/2F seem to use USB for wifi/bt.

[4] https://github.com/Kwiboo/linux-rockchip/blob/next-20250305-rk3528/arch/arm64/boot/dts/rockchip/rk3528-armsom-sige1.dts

Regards,
Jonas

> 
>>> +			resets = <&cru SRST_H_SDIO0>;
>>> +			reset-names = "reset";
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		sdio1: mmc at ffc20000 {
>>> +			compatible = "rockchip,rk3528-dw-mshc",
>>> +				     "rockchip,rk3288-dw-mshc";
>>> +			reg = <0x0 0xffc20000 0x0 0x4000>;
>>> +			clocks = <&cru HCLK_SDIO1>,
>>> +				 <&cru CCLK_SRC_SDIO1>,
>>> +				 <&cru SCLK_SDIO1_DRV>,
>>> +				 <&cru SCLK_SDIO1_SAMPLE>;
>>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
>>> +			fifo-depth = <0x100>;
>>> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
>>> +			max-frequency = <150000000>;
>>> +			pinctrl-names = "default";
>>> +			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
>>> +				    <&sdio1_det>, <&sdio1_pwren>;
>>
>> Same here.
>>
>>> +			resets = <&cru SRST_H_SDIO1>;
>>> +			reset-names = "reset";
>>> +			status = "disabled";
>>> +		};
>>
>> Thanks,
>> Chukun
>>
>> -- 
>> 2.25.1
>>
> 
> Best regards,
> Yao Zi
> 
> [1]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/Rockchip%C2%A0RK3528%C2%A0Datasheet%C2%A0V1.0-20230522.pdf
> [2]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/RK3528_BOX_REF_V10_20230525.pdf
> [3]: https://github.com/rockchip-linux/kernel/blob/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi#L128



From Frank.li at nxp.com  Thu Mar  6 15:06:44 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 18:06:44 -0500
Subject: [PATCH] ARM64: dts: imx8mp-evk: add ecspi2 support
In-Reply-To: <CAOMZO5CL-qQSHuSoCtb+f_mqNG8vu4tTVDi-ThoHq+m9SeagxA@mail.gmail.com>
References: <20250306222359.797855-1-Frank.Li@nxp.com>
 <CAOMZO5CL-qQSHuSoCtb+f_mqNG8vu4tTVDi-ThoHq+m9SeagxA@mail.gmail.com>
Message-ID: <Z8oqhGmVOBCPlJUI@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 07:55:36PM -0300, Fabio Estevam wrote:
> On Thu, Mar 6, 2025 at 7:24?PM Frank Li <Frank.Li at nxp.com> wrote:
>
> > +&ecspi2 {
> > +       #address-cells = <1>;
> > +       #size-cells = <0>;
> > +       num-cs = <1>;
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;
> > +       cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
> > +       status = "okay";
> > +
> > +       spidev1: spi at 0 {
> > +               compatible = "rohm,dh2228fv";
>
> That's not a correct description of the hardware.
>
> Conor's effort was to clean up the abuses of using "rohm,dh2228fv" to
> get spidev support.
>
> Please check:
>
> fc28d1c1fe3b3 ("spi: spidev: add correct compatible for Rohm BH2228FV")

Thanks! It is actually to get spidev. From commit message, I don't know
what next steps should be did, use "rohm,bh2228fv" or other method to
support spidev?

Frank


From jonas at kwiboo.se  Thu Mar  6 15:07:06 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:07:06 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <117081043.nniJfEyVGO@diego>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
 <20250306123809.273655-3-amadeus@jmu.edu.cn>
 <cdbc1556-4662-4078-a4d6-33545e2e2491@kwiboo.se> <117081043.nniJfEyVGO@diego>
Message-ID: <7fa480bd-9bc5-4069-a623-afb140455192@kwiboo.se>

On 2025-03-06 19:08, Heiko St?bner wrote:
> Am Donnerstag, 6. M?rz 2025, 17:55:16 MEZ schrieb Jonas Karlman:
>> Hi Chukun,
>>
>> On 2025-03-06 13:38, Chukun Pan wrote:
>>> The Quality-of-Service (QsS) node stores/restores specific
>>> register contents when the power domains is turned off/on.
>>> Add QoS node so that they can connect to the power domain.
>>>
>>> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
>>> ---
>>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 160 +++++++++++++++++++++++
>>>  1 file changed, 160 insertions(+)
>>>
> 
>>
>> These QoS node are typically referenced from power domains so that the
>> PMU driver know what QoS to save/restore when a power domain is power
>> cycled.
>>
>> Vendor kernel only reference the two qos_gpu nodes in it's power domains,
>> do you have any documentation or knowledge about what power domain the
>> remaining QoS are related to?
> 
> I think the GPU actually is the _only_ fully switchable power-domain on the
> rk3528. The other powerdomains seem to be always on, but can do this
> idle-request thing.
> 
> At least that is what I'm reading from the pm-domain definitions in the
> vendor-kernel, combined with a look at the pmu section of the rk3528 TRM.

Thanks for this information.

Regards,
Jonas

> 
> 
> Heiko
> 
> 



From jonas at kwiboo.se  Thu Mar  6 15:14:16 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:14:16 +0100
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <Z8oRyHThun9mLgx8@shell.armlinux.org.uk>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
 <Z8oRyHThun9mLgx8@shell.armlinux.org.uk>
Message-ID: <ef815b08-207d-41c2-a2d0-aeab70111761@kwiboo.se>

On 2025-03-06 22:21, Russell King (Oracle) wrote:
> On Thu, Mar 06, 2025 at 09:09:46PM +0000, Jonas Karlman wrote:
>> @@ -1813,8 +1564,24 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>>  
>>  	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>>  							"rockchip,grf");
>> -	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>> -							    "rockchip,php-grf");
>> +	if (IS_ERR(bsp_priv->grf)) {
>> +		ret = PTR_ERR(bsp_priv->grf);
>> +		dev_err_probe(dev, ret, "failed to lookup rockchip,grf\n");
>> +		return ERR_PTR(ret);
> 
> Did you consider using ERR_CAST() for these, which would look like this:
> 
> 		dev_err_probe(dev, PTR_ERR(bsp_priv->grf),
> 			      "failed to lookup rockchip,grf\n");
> 		return ERR_CAST(bsp_priv->grf);
> 
> ?
> 

No, I did not, I only duplicated the same handling that was done for
the "failed to get phy regulator" case a little bit earlier in the
rk_gmac_setup() function.

I can adjust this (and the regulator case) to use ERR_CAST in a v2.

Regards,
Jonas


From ilkka at os.amperecomputing.com  Thu Mar  6 15:26:11 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 6 Mar 2025 15:26:11 -0800 (PST)
Subject: [PATCH 0/3] perf/arm_cspmu: Add PMEVFILT2R support
In-Reply-To: <cover.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
Message-ID: <d3388738-15f5-8b97-a793-867b8d537654@os.amperecomputing.com>



On Wed, 5 Mar 2025, Robin Murphy wrote:

> Hi all,
>
> This is part of something I'm working towards, but I figure it stands
> up on its own enough to be worth getting out early. Compile-tested
> only, but it's straightforward enough that I'm confident.
>
> Cheers,
> Robin.

I ran a very quick test on Ampere AmpereOne and everything seemed to work
as expected.

Cheers, Ilkka

> Robin Murphy (3):
>  perf/arm_cspmu: Move register definitons to header
>  perf/arm_cspmu: Generalise event filtering
>  perf/arm_cspmu: Add PMEVFILT2R support
>
> drivers/perf/arm_cspmu/ampere_cspmu.c | 32 ++++-------
> drivers/perf/arm_cspmu/arm_cspmu.c    | 81 ++++++---------------------
> drivers/perf/arm_cspmu/arm_cspmu.h    | 57 +++++++++++++++++--
> drivers/perf/arm_cspmu/nvidia_cspmu.c | 21 ++++++-
> 4 files changed, 100 insertions(+), 91 deletions(-)
>
> -- 
> 2.39.2.101.g768bb238c484.dirty
>
>
>


From jonas at kwiboo.se  Thu Mar  6 15:28:42 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:28:42 +0100
Subject: [PATCH 1/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3328
In-Reply-To: <d6b15dc2-f6b2-4703-a4da-07618eaed4db@lunn.ch>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-2-jonas@kwiboo.se>
 <d6b15dc2-f6b2-4703-a4da-07618eaed4db@lunn.ch>
Message-ID: <624f2474-9a39-46a3-a6e5-f9966471bf3d@kwiboo.se>

Hi Andrew,

On 2025-03-06 23:25, Andrew Lunn wrote:
> On Thu, Mar 06, 2025 at 08:38:52PM +0000, Jonas Karlman wrote:
>> Support for Rockchip RK3328 GMAC and addition of the DELAY_ENABLE macro
>> was merged in the same merge window. This resulted in RK3328 not being
>> converted to use the new DELAY_ENABLE macro.
>>
>> Change to use the DELAY_ENABLE macro to help disable MAC delay when
>> RGMII_ID/RXID/TXID is used.
>>
>> Fixes: eaf70ad14cbb ("net: stmmac: dwmac-rk: Add handling for RGMII_ID/RXID/TXID")
> 
> Please add a description of the broken behaviour. How would i know i
> need this fix? What would i see?

Based on my layman testing I have not seen any real broken behaviour
with current enablement of a zero rx/tx MAC delay for RGMII_ID/RXID/TXID.

The driver ops is called with a rx/tx_delay=0 for RGMII_ID/RXID/TXID
modes, what the MAC does with enable=true and rx/tx_delay=0 is unclear
to me.

> 
> We also need to be careful with backwards compatibility. Is there the
> potential for double bugs cancelling each other out? A board which has
> the wrong phy-mode in DT, but because of this bug, the wrong register
> is written and it actually works because of reset defaults?

To my knowledge this should have very limited effect, however I am no
network expert and after doing very basic testing on several different
rk3328/rk3566/rk3568/rk3588 I could not see any real affect with/without
this change.

The use of Fixes-tag was more to have a reference to the commit that
first should have used the DELAY_ENABLE macro.

Regards,
Jonas

> 
>     Andrew
> 
> ---
> pw-bot: cr
> 
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip



From ilkka at os.amperecomputing.com  Thu Mar  6 15:29:30 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 6 Mar 2025 15:29:30 -0800 (PST)
Subject: [PATCH 2/3] perf/arm_cspmu: Generalise event filtering
In-Reply-To: <c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com> <c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com>
Message-ID: <d3e13b6f-ce6e-6e73-6d3e-7c91856665c@os.amperecomputing.com>



On Wed, 5 Mar 2025, Robin Murphy wrote:

> The notion of a single u32 filter value for any event doesn't scale well
> when the potential architectural scope is already two 64-bit values, and
> implementations may add custom stuff on the side too. Rather than try to
> thread arbitrary filter data through the common path, let's just make
> the set_ev_filter op self-contained in terms of parsing and configuring
> any and all filtering for the given event - splitting out a distinct op
> for cycles events which inherently differ - and let implementations
> override the whole thing if they want to do something different. This
> already allows the Ampere code to stop looking a bit hacky.
>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

Reviewed-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>

> ---
> drivers/perf/arm_cspmu/ampere_cspmu.c | 24 ++++++----------------
> drivers/perf/arm_cspmu/arm_cspmu.c    | 29 +++++++++++----------------
> drivers/perf/arm_cspmu/arm_cspmu.h    |  8 ++++----
> drivers/perf/arm_cspmu/nvidia_cspmu.c | 21 ++++++++++++++++++-
> 4 files changed, 42 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/ampere_cspmu.c b/drivers/perf/arm_cspmu/ampere_cspmu.c
> index 31cc1a4ac9df..b8ca69fd9d1d 100644
> --- a/drivers/perf/arm_cspmu/ampere_cspmu.c
> +++ b/drivers/perf/arm_cspmu/ampere_cspmu.c
> @@ -132,32 +132,20 @@ ampere_cspmu_get_name(const struct arm_cspmu *cspmu)
> 	return ctx->name;
> }
>
> -static u32 ampere_cspmu_event_filter(const struct perf_event *event)
> +static void ampere_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> +				       const struct perf_event *event)
> {
> 	/*
> -	 * PMEVFILTR or PMCCFILTR aren't used in Ampere SoC PMU but are marked
> -	 * as RES0. Make sure, PMCCFILTR is written zero.
> +	 * PMCCFILTR is RES0, so this is just a dummy callback to override
> +	 * the default implementation and avoid writing to it.
> 	 */
> -	return 0;
> }
>
> static void ampere_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> -				       struct hw_perf_event *hwc,
> -				       u32 filter)
> +				       const struct perf_event *event)
> {
> -	struct perf_event *event;
> -	unsigned int idx;
> 	u32 threshold, rank, bank;
>
> -	/*
> -	 * At this point, all the events have the same filter settings.
> -	 * Therefore, take the first event and use its configuration.
> -	 */
> -	idx = find_first_bit(cspmu->hw_events.used_ctrs,
> -			     cspmu->cycle_counter_logical_idx);
> -
> -	event = cspmu->hw_events.events[idx];
> -
> 	threshold	= get_threshold(event);
> 	rank		= get_rank(event);
> 	bank		= get_bank(event);
> @@ -233,7 +221,7 @@ static int ampere_cspmu_init_ops(struct arm_cspmu *cspmu)
>
> 	cspmu->impl.ctx = ctx;
>
> -	impl_ops->event_filter		= ampere_cspmu_event_filter;
> +	impl_ops->set_cc_filter		= ampere_cspmu_set_cc_filter;
> 	impl_ops->set_ev_filter		= ampere_cspmu_set_ev_filter;
> 	impl_ops->validate_event	= ampere_cspmu_validate_event;
> 	impl_ops->get_name		= ampere_cspmu_get_name;
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 769466d55bea..053bb7920df6 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -66,7 +66,9 @@ static unsigned long arm_cspmu_cpuhp_state;
> static DEFINE_MUTEX(arm_cspmu_lock);
>
> static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> -				    struct hw_perf_event *hwc, u32 filter);
> +				    const struct perf_event *event);
> +static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> +				    const struct perf_event *event);
>
> static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
> {
> @@ -205,11 +207,6 @@ static bool arm_cspmu_is_cycle_counter_event(const struct perf_event *event)
> 	return (event->attr.config == ARM_CSPMU_EVT_CYCLES_DEFAULT);
> }
>
> -static u32 arm_cspmu_event_filter(const struct perf_event *event)
> -{
> -	return event->attr.config1 & ARM_CSPMU_FILTER_MASK;
> -}
> -
> static ssize_t arm_cspmu_identifier_show(struct device *dev,
> 					 struct device_attribute *attr,
> 					 char *page)
> @@ -371,7 +368,7 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
> 		DEFAULT_IMPL_OP(get_name),
> 		DEFAULT_IMPL_OP(is_cycle_counter_event),
> 		DEFAULT_IMPL_OP(event_type),
> -		DEFAULT_IMPL_OP(event_filter),
> +		DEFAULT_IMPL_OP(set_cc_filter),
> 		DEFAULT_IMPL_OP(set_ev_filter),
> 		DEFAULT_IMPL_OP(event_attr_is_visible),
> 	};
> @@ -767,26 +764,26 @@ static inline void arm_cspmu_set_event(struct arm_cspmu *cspmu,
> }
>
> static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> -					struct hw_perf_event *hwc,
> -					u32 filter)
> +				    const struct perf_event *event)
> {
> +	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
> 	u32 offset = PMEVFILTR + (4 * hwc->idx);
>
> 	writel(filter, cspmu->base0 + offset);
> }
>
> -static inline void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu, u32 filter)
> +static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> +				    const struct perf_event *event)
> {
> -	u32 offset = PMCCFILTR;
> +	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
>
> -	writel(filter, cspmu->base0 + offset);
> +	writel(filter, cspmu->base0 + PMCCFILTR);
> }
>
> static void arm_cspmu_start(struct perf_event *event, int pmu_flags)
> {
> 	struct arm_cspmu *cspmu = to_arm_cspmu(event->pmu);
> 	struct hw_perf_event *hwc = &event->hw;
> -	u32 filter;
>
> 	/* We always reprogram the counter */
> 	if (pmu_flags & PERF_EF_RELOAD)
> @@ -794,13 +791,11 @@ static void arm_cspmu_start(struct perf_event *event, int pmu_flags)
>
> 	arm_cspmu_set_event_period(event);
>
> -	filter = cspmu->impl.ops.event_filter(event);
> -
> 	if (event->hw.extra_reg.idx == cspmu->cycle_counter_logical_idx) {
> -		arm_cspmu_set_cc_filter(cspmu, filter);
> +		cspmu->impl.ops.set_cc_filter(cspmu, event);
> 	} else {
> 		arm_cspmu_set_event(cspmu, hwc);
> -		cspmu->impl.ops.set_ev_filter(cspmu, hwc, filter);
> +		cspmu->impl.ops.set_ev_filter(cspmu, event);
> 	}
>
> 	hwc->state = 0;
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index 576249e0deea..d59040d6a7e3 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -149,11 +149,11 @@ struct arm_cspmu_impl_ops {
> 	bool (*is_cycle_counter_event)(const struct perf_event *event);
> 	/* Decode event type/id from configs */
> 	u32 (*event_type)(const struct perf_event *event);
> -	/* Decode filter value from configs */
> -	u32 (*event_filter)(const struct perf_event *event);
> -	/* Set event filter */
> +	/* Set event filters */
> +	void (*set_cc_filter)(struct arm_cspmu *cspmu,
> +			      const struct perf_event *event);
> 	void (*set_ev_filter)(struct arm_cspmu *cspmu,
> -			      struct hw_perf_event *hwc, u32 filter);
> +			      const struct perf_event *event);
> 	/* Implementation specific event validation */
> 	int (*validate_event)(struct arm_cspmu *cspmu,
> 			      struct perf_event *event);
> diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> index 8116c7846a46..9e817f120828 100644
> --- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
> +++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> @@ -183,6 +183,24 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
> 	return filter_val;
> }
>
> +static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> +				   const struct perf_event *event)
> +{
> +	u32 filter = nv_cspmu_event_filter(event);
> +	u32 offset = PMEVFILTR + (4 * event->hw.idx);
> +
> +	writel(filter, cspmu->base0 + offset);
> +}
> +
> +static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> +				   const struct perf_event *event)
> +{
> +	u32 filter = nv_cspmu_event_filter(event);
> +
> +	writel(filter, cspmu->base0 + PMCCFILTR);
> +}
> +
> +
> enum nv_cspmu_name_fmt {
> 	NAME_FMT_GENERIC,
> 	NAME_FMT_SOCKET
> @@ -322,7 +340,8 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
> 	cspmu->impl.ctx = ctx;
>
> 	/* NVIDIA specific callbacks. */
> -	impl_ops->event_filter			= nv_cspmu_event_filter;
> +	impl_ops->set_cc_filter			= nv_cspmu_set_cc_filter;
> +	impl_ops->set_ev_filter			= nv_cspmu_set_ev_filter;
> 	impl_ops->get_event_attrs		= nv_cspmu_get_event_attrs;
> 	impl_ops->get_format_attrs		= nv_cspmu_get_format_attrs;
> 	impl_ops->get_name			= nv_cspmu_get_name;
> -- 
> 2.39.2.101.g768bb238c484.dirty
>
>


From ilkka at os.amperecomputing.com  Thu Mar  6 15:28:22 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 6 Mar 2025 15:28:22 -0800 (PST)
Subject: [PATCH 1/3] perf/arm_cspmu: Move register definitons to header
In-Reply-To: <5a3c796560665b51cb63fec0d473afd8f8d0a836.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com> <5a3c796560665b51cb63fec0d473afd8f8d0a836.1741190362.git.robin.murphy@arm.com>
Message-ID: <ffd0824-cada-d454-bea8-8c45e0a13b6c@os.amperecomputing.com>



On Wed, 5 Mar 2025, Robin Murphy wrote:

> Implementations may occasionally want to refer to register offsets, so
> for the sake of consistency move all of the register definitions to join
> the PMIIDR fields in the private header where they can be shared. As an
> example nicety, we can then define Ampere's imp-def filters in terms of
> the architectural PMIMPDEF range rather than open-coded offsets.
>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

Reviewed-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>


> ---
> drivers/perf/arm_cspmu/ampere_cspmu.c |  8 ++---
> drivers/perf/arm_cspmu/arm_cspmu.c    | 45 --------------------------
> drivers/perf/arm_cspmu/arm_cspmu.h    | 46 +++++++++++++++++++++++++++
> 3 files changed, 50 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/ampere_cspmu.c b/drivers/perf/arm_cspmu/ampere_cspmu.c
> index f72f5689923c..31cc1a4ac9df 100644
> --- a/drivers/perf/arm_cspmu/ampere_cspmu.c
> +++ b/drivers/perf/arm_cspmu/ampere_cspmu.c
> @@ -10,10 +10,10 @@
>
> #include "arm_cspmu.h"
>
> -#define PMAUXR0		0xD80
> -#define PMAUXR1		0xD84
> -#define PMAUXR2		0xD88
> -#define PMAUXR3		0xD8C
> +#define PMAUXR0		PMIMPDEF
> +#define PMAUXR1		(PMIMPDEF + 0x4)
> +#define PMAUXR2		(PMIMPDEF + 0x8)
> +#define PMAUXR3		(PMIMPDEF + 0xC)
>
> #define to_ampere_cspmu_ctx(cspmu)	((struct ampere_cspmu_ctx *)(cspmu->impl.ctx))
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 81e8b97e9353..769466d55bea 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -40,51 +40,6 @@
> 	ARM_CSPMU_EXT_ATTR(_name, arm_cspmu_cpumask_show,	\
> 				(unsigned long)_config)
>
> -/*
> - * CoreSight PMU Arch register offsets.
> - */
> -#define PMEVCNTR_LO					0x0
> -#define PMEVCNTR_HI					0x4
> -#define PMEVTYPER					0x400
> -#define PMCCFILTR					0x47C
> -#define PMEVFILTR					0xA00
> -#define PMCNTENSET					0xC00
> -#define PMCNTENCLR					0xC20
> -#define PMINTENSET					0xC40
> -#define PMINTENCLR					0xC60
> -#define PMOVSCLR					0xC80
> -#define PMOVSSET					0xCC0
> -#define PMCFGR						0xE00
> -#define PMCR						0xE04
> -#define PMIIDR						0xE08
> -
> -/* PMCFGR register field */
> -#define PMCFGR_NCG					GENMASK(31, 28)
> -#define PMCFGR_HDBG					BIT(24)
> -#define PMCFGR_TRO					BIT(23)
> -#define PMCFGR_SS					BIT(22)
> -#define PMCFGR_FZO					BIT(21)
> -#define PMCFGR_MSI					BIT(20)
> -#define PMCFGR_UEN					BIT(19)
> -#define PMCFGR_NA					BIT(17)
> -#define PMCFGR_EX					BIT(16)
> -#define PMCFGR_CCD					BIT(15)
> -#define PMCFGR_CC					BIT(14)
> -#define PMCFGR_SIZE					GENMASK(13, 8)
> -#define PMCFGR_N					GENMASK(7, 0)
> -
> -/* PMCR register field */
> -#define PMCR_TRO					BIT(11)
> -#define PMCR_HDBG					BIT(10)
> -#define PMCR_FZO					BIT(9)
> -#define PMCR_NA						BIT(8)
> -#define PMCR_DP						BIT(5)
> -#define PMCR_X						BIT(4)
> -#define PMCR_D						BIT(3)
> -#define PMCR_C						BIT(2)
> -#define PMCR_P						BIT(1)
> -#define PMCR_E						BIT(0)
> -
> /* Each SET/CLR register supports up to 32 counters. */
> #define ARM_CSPMU_SET_CLR_COUNTER_SHIFT		5
> #define ARM_CSPMU_SET_CLR_COUNTER_NUM		\
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index 2621f3111148..576249e0deea 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -65,6 +65,52 @@
> /* The cycle counter, if implemented, is located at counter[31]. */
> #define ARM_CSPMU_CYCLE_CNTR_IDX	31
>
> +/*
> + * CoreSight PMU Arch register offsets.
> + */
> +#define PMEVCNTR_LO			0x0
> +#define PMEVCNTR_HI			0x4
> +#define PMEVTYPER			0x400
> +#define PMCCFILTR			0x47C
> +#define PMEVFILTR			0xA00
> +#define PMCNTENSET			0xC00
> +#define PMCNTENCLR			0xC20
> +#define PMINTENSET			0xC40
> +#define PMINTENCLR			0xC60
> +#define PMOVSCLR			0xC80
> +#define PMOVSSET			0xCC0
> +#define PMIMPDEF			0xD80
> +#define PMCFGR				0xE00
> +#define PMCR				0xE04
> +#define PMIIDR				0xE08
> +
> +/* PMCFGR register field */
> +#define PMCFGR_NCG			GENMASK(31, 28)
> +#define PMCFGR_HDBG			BIT(24)
> +#define PMCFGR_TRO			BIT(23)
> +#define PMCFGR_SS			BIT(22)
> +#define PMCFGR_FZO			BIT(21)
> +#define PMCFGR_MSI			BIT(20)
> +#define PMCFGR_UEN			BIT(19)
> +#define PMCFGR_NA			BIT(17)
> +#define PMCFGR_EX			BIT(16)
> +#define PMCFGR_CCD			BIT(15)
> +#define PMCFGR_CC			BIT(14)
> +#define PMCFGR_SIZE			GENMASK(13, 8)
> +#define PMCFGR_N			GENMASK(7, 0)
> +
> +/* PMCR register field */
> +#define PMCR_TRO			BIT(11)
> +#define PMCR_HDBG			BIT(10)
> +#define PMCR_FZO			BIT(9)
> +#define PMCR_NA				BIT(8)
> +#define PMCR_DP				BIT(5)
> +#define PMCR_X				BIT(4)
> +#define PMCR_D				BIT(3)
> +#define PMCR_C				BIT(2)
> +#define PMCR_P				BIT(1)
> +#define PMCR_E				BIT(0)
> +
> /* PMIIDR register field */
> #define ARM_CSPMU_PMIIDR_IMPLEMENTER	GENMASK(11, 0)
> #define ARM_CSPMU_PMIIDR_PRODUCTID	GENMASK(31, 20)
> -- 
> 2.39.2.101.g768bb238c484.dirty
>
>


From ilkka at os.amperecomputing.com  Thu Mar  6 15:30:16 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 6 Mar 2025 15:30:16 -0800 (PST)
Subject: [PATCH 3/3] perf/arm_cspmu: Add PMEVFILT2R support
In-Reply-To: <b11be3f23a72bc27088b115099c8fe865b70babc.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com> <b11be3f23a72bc27088b115099c8fe865b70babc.1741190362.git.robin.murphy@arm.com>
Message-ID: <5ac3785a-83d5-e795-a9c8-d118973f86a@os.amperecomputing.com>



On Wed, 5 Mar 2025, Robin Murphy wrote:

> Architecturally we have two filters for each regular event counter,
> so add generic support for the second one too.
>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

Reviewed-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>

> ---
> drivers/perf/arm_cspmu/arm_cspmu.c | 7 +++++--
> drivers/perf/arm_cspmu/arm_cspmu.h | 3 +++
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 053bb7920df6..efa9b229e701 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -183,6 +183,7 @@ arm_cspmu_event_attr_is_visible(struct kobject *kobj,
> static struct attribute *arm_cspmu_format_attrs[] = {
> 	ARM_CSPMU_FORMAT_EVENT_ATTR,
> 	ARM_CSPMU_FORMAT_FILTER_ATTR,
> +	ARM_CSPMU_FORMAT_FILTER2_ATTR,
> 	NULL,
> };
>
> @@ -767,9 +768,11 @@ static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> 				    const struct perf_event *event)
> {
> 	u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
> -	u32 offset = PMEVFILTR + (4 * hwc->idx);
> +	u32 filter2 = event->attr.config2 & ARM_CSPMU_FILTER_MASK;
> +	u32 offset = 4 * event->hw.idx;
>
> -	writel(filter, cspmu->base0 + offset);
> +	writel(filter, cspmu->base0 + PMEVFILTR + offset);
> +	writel(filter2, cspmu->base0 + PMEVFILT2R + offset);
> }
>
> static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index d59040d6a7e3..19684b76bd96 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -47,6 +47,8 @@
> /* Default filter format */
> #define ARM_CSPMU_FORMAT_FILTER_ATTR	\
> 	ARM_CSPMU_FORMAT_ATTR(filter, "config1:0-31")
> +#define ARM_CSPMU_FORMAT_FILTER2_ATTR	\
> +	ARM_CSPMU_FORMAT_ATTR(filter2, "config2:0-31")
>
> /*
>  * This is the default event number for cycle count, if supported, since the
> @@ -72,6 +74,7 @@
> #define PMEVCNTR_HI			0x4
> #define PMEVTYPER			0x400
> #define PMCCFILTR			0x47C
> +#define PMEVFILT2R			0x800
> #define PMEVFILTR			0xA00
> #define PMCNTENSET			0xC00
> #define PMCNTENCLR			0xC20
> -- 
> 2.39.2.101.g768bb238c484.dirty
>
>


From patchwork-bot+netdevbpf at kernel.org  Thu Mar  6 15:40:37 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 06 Mar 2025 23:40:37 +0000
Subject: [PATCH v8 0/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <20250305091246.106626-1-swathi.ks@samsung.com>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
Message-ID: <174130443748.1819102.11441827117696182422.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Wed,  5 Mar 2025 14:42:44 +0530 you wrote:
> FSD platform has two instances of EQoS IP, one is in FSYS0 block and
> another one is in PERIC block. This patch series add required DT binding
> and platform driver specific changes for the same.
> 
> Changes since v1:
> 1. Updated dwc_eqos_setup_rxclock() function as per the review comments
> given by Andrew.
> 
> [...]

Here is the summary with links:
  - [v8,1/2] dt-bindings: net: Add FSD EQoS device tree bindings
    https://git.kernel.org/netdev/net-next/c/1f6c3899833a
  - [v8,2/2] net: stmmac: dwc-qos: Add FSD EQoS support
    https://git.kernel.org/netdev/net-next/c/ae7f6b34f5cd

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From andre.przywara at arm.com  Thu Mar  6 15:39:49 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 6 Mar 2025 23:39:49 +0000
Subject: [PATCH v3 4/8] pinctrl: sunxi: support moved power
 configuration registers
In-Reply-To: <6028746.MhkbZ0Pkbq@jernej-laptop>
References: <20250227231447.20161-1-andre.przywara@arm.com>
	<20250227231447.20161-5-andre.przywara@arm.com>
	<6028746.MhkbZ0Pkbq@jernej-laptop>
Message-ID: <20250306233949.23924567@minigeek.lan>

On Wed, 05 Mar 2025 18:50:34 +0100
Jernej ?krabec <jernej.skrabec at gmail.com> wrote:

Hi,

> Dne petek, 28. februar 2025 ob 00:14:43 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> > The Allwinner pincontroller IP features some registers to control the
> > withstand voltage of each pin group. So far those registers were always
> > located at the same offset, but the A523 SoC has moved them (probably to
> > accommodate all eleven pin banks).
> > 
> > Add a flag to note this feature, and use that to program the registers
> > either at offset 0x340 or 0x380. So far no pincontroller driver uses
> > this flag, but we need it for the upcoming A523 support.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> >  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 15 +++++++++++----
> >  drivers/pinctrl/sunxi/pinctrl-sunxi.h |  7 +++++--
> >  2 files changed, 16 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > index 83a031ceb29f2..fc12e6f807e4d 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > @@ -736,9 +736,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
> >  		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> >  
> >  		raw_spin_lock_irqsave(&pctl->lock, flags);
> > -		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> > +		reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
> >  		reg &= ~BIT(bank);
> > -		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> > +		writel(reg | val, pctl->membase + pctl->pow_mod_sel_offset);  
> 
> These two are missing "+ PIO_POW_MOD_CTL_OFS" right?

Ah, you are right, I mixed that up. Nice catch!

> >  		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> >  
> >  		fallthrough;
> > @@ -746,9 +746,12 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
> >  		val = uV <= 1800000 ? 1 : 0;
> >  
> >  		raw_spin_lock_irqsave(&pctl->lock, flags);
> > -		reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
> > +		reg = readl(pctl->membase + pctl->pow_mod_sel_offset +
> > +			    PIO_POW_MOD_CTL_OFS);
> >  		reg &= ~(1 << bank);
> > -		writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
> > +		writel(reg | val << bank,
> > +		       pctl->membase + pctl->pow_mod_sel_offset +
> > +		       PIO_POW_MOD_CTL_OFS);  
> 
> And these two have "+ PIO_POW_MOD_CTL_OFS" too much, right?

Indeed, fixed now.

Thanks,
Andre

> Best regards,
> Jernej
> 
> >  		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> >  		return 0;
> >  	default:
> > @@ -1520,6 +1523,10 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
> >  		pctl->pull_regs_offset = PULL_REGS_OFFSET;
> >  		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> >  	}
> > +	if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
> > +		pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
> > +	else
> > +		pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
> >  
> >  	pctl->irq_array = devm_kcalloc(&pdev->dev,
> >  				       IRQ_PER_BANK * pctl->desc->irq_banks,
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > index 6cf721876d89d..742fc795c7664 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > @@ -87,9 +87,11 @@
> >  #define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
> >  #define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)
> >  #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
> > +#define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
> >  
> > -#define PIO_POW_MOD_SEL_REG	0x340
> > -#define PIO_POW_MOD_CTL_REG	0x344
> > +#define PIO_POW_MOD_SEL_REG		0x340
> > +#define PIO_11B_POW_MOD_SEL_REG		0x380
> > +#define PIO_POW_MOD_CTL_OFS		0x004
> >  
> >  #define PIO_BANK_K_OFFSET		0x500
> >  
> > @@ -173,6 +175,7 @@ struct sunxi_pinctrl {
> >  	u32				bank_mem_size;
> >  	u32				pull_regs_offset;
> >  	u32				dlevel_field_width;
> > +	u32				pow_mod_sel_offset;
> >  };
> >  
> >  #define SUNXI_PIN(_pin, ...)					\
> >   
> 
> 
> 
> 
> 



From patchwork-bot+netdevbpf at kernel.org  Thu Mar  6 15:40:33 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 06 Mar 2025 23:40:33 +0000
Subject: [PATCH net-next] net: stmmac: mostly remove "buf_sz"
In-Reply-To: <E1tpswn-005U6I-TU@rmk-PC.armlinux.org.uk>
References: <E1tpswn-005U6I-TU@rmk-PC.armlinux.org.uk>
Message-ID: <174130443328.1819102.15961350109548099161.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Wed, 05 Mar 2025 17:54:21 +0000 you wrote:
> The "buf_sz" parameter is not used in the stmmac driver - there is one
> place where the value of buf_sz is validated, and two places where it
> is written. It is otherwise unused.
> 
> Remove these accesses. However, leave the module parameter in place as
> removing it could cause module load to fail, breaking user setups.
> 
> [...]

Here is the summary with links:
  - [net-next] net: stmmac: mostly remove "buf_sz"
    https://git.kernel.org/netdev/net-next/c/072dd84b4c5a

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From jonas at kwiboo.se  Thu Mar  6 15:42:22 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:42:22 +0100
Subject: [PATCH 1/2] dt-bindings: net: rockchip-dwmac: Require
 rockchip,grf and rockchip,php-grf
In-Reply-To: <5d69f4a2-511a-4e7e-bafe-5ce6171cb1d5@lunn.ch>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-2-jonas@kwiboo.se>
 <5d69f4a2-511a-4e7e-bafe-5ce6171cb1d5@lunn.ch>
Message-ID: <3f341b96-1add-4eeb-b185-b4bfe0bf0250@kwiboo.se>

Hi Andrew,

On 2025-03-06 23:32, Andrew Lunn wrote:
> On Thu, Mar 06, 2025 at 09:09:45PM +0000, Jonas Karlman wrote:
>> All Rockchip GMAC variants require writing to GRF to configure e.g.
>> interface mode and MAC rx/tx delay.
>>
>> Change binding to require rockchip,grf and rockchip,php-grf to reflect
>> that GRF (and PHP-GRF for RK3576/RK3588) control part of GMAC.
> 
> It is pretty unusual to change the binding such that something
> optional becomes mandatory. I would expect a bit more of a comment
> explaining why this does not cause backwards compatibility
> issues. Have all the .dtsi files always had these properties?

rockchip,grf was listed under required properties prior to the commit
b331b8ef86f0 ("dt-bindings: net: convert rockchip-dwmac to json-schema"),
maybe this was just lost during the conversion to yaml schema.

The DT's I have managed to check all seem to have the rockchip,grf prop
and the old .txt schema listed "phandle to the syscon grf used to
control speed and mode".

Without the rockchip,grf the driver just logged an error and ignored
trying to configure speed or mode.

We could possible leave it as optional, but when it is missing speed and
mode cannot be configured by the driver. Today this just result in an
error message, after this series there will instead be a probe error.

Regards,
Jonas

> 
>     Andrew
> 
> ---
> pw-bot: cr



From jonas at kwiboo.se  Thu Mar  6 15:49:38 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 00:49:38 +0100
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
 <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
Message-ID: <1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>

Hi Andrew,

On 2025-03-06 23:37, Andrew Lunn wrote:
> On Thu, Mar 06, 2025 at 09:09:46PM +0000, Jonas Karlman wrote:
>> All Rockchip GMAC variants require writing to GRF to configure e.g.
>> interface mode and MAC rx/tx delay. The GRF syscon regmap is located
>> with help of a rockchip,grf and rockchip,php-grf phandle.
> 
>> @@ -1813,8 +1564,24 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>>  
>>  	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>>  							"rockchip,grf");
>> -	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
>> -							    "rockchip,php-grf");
>> +	if (IS_ERR(bsp_priv->grf)) {
>> +		ret = PTR_ERR(bsp_priv->grf);
>> +		dev_err_probe(dev, ret, "failed to lookup rockchip,grf\n");
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	bsp_priv->php_grf =
>> +		syscon_regmap_lookup_by_phandle_optional(dev->of_node,
>> +							 "rockchip,php-grf");
>> +	if ((of_device_is_compatible(dev->of_node, "rockchip,rk3588-gmac") ||
>> +	     of_device_is_compatible(dev->of_node, "rockchip,rk3576-gmac")) &&
>> +	    !bsp_priv->php_grf)
>> +		bsp_priv->php_grf = ERR_PTR(-ENODEV);
> 
> It seems odd you say all variants need this property, and then you
> look for two specific variants here and do something different? Why
> are these two special?

rockchip,grf is required for all GMACs, rockchip,php-grf is also needed
on rk3576 and rk3588 (+rk3562 that has been posted on ML) :-S

Above use of of_device_is_compatible() was my attempt at requiring the
syscon regmap for those variants that make use of php_grf. And still not
break rk3562 depending on the order these would land.

Should probably clarify a little bit with a code comment in a v2.

Regards,
Jonas

> 
> 	Andrew



From sistema at brmidias.com.br  Thu Mar  6 15:54:18 2025
From: sistema at brmidias.com.br (sistema at brmidias.com.br)
Date: 6 Mar 2025 23:54:18 +0000
Subject: Sign and return #423 Date:3/6/2025 11:46:21 PM
Message-ID: <20250306234621.1DE8FB8489D38C55@email-ssl.com.br>

Hello linux-arm-kernel,

I?m Jordan Patel from Federante Ltd. We?re interested in placing 
an order and would love to see your latest product/service list 
along with pricing.

Could you kindly send the details to ifaldazos at federante.com.ar 
at your earliest convenience?

Looking forward to your response.

Best regards,
Jordan Patel
Federante Ltd.


From andre.przywara at arm.com  Thu Mar  6 15:58:23 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:23 +0000
Subject: [PATCH v4 4/8] pinctrl: sunxi: support moved power configuration registers
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-5-andre.przywara@arm.com>

The Allwinner pincontroller IP features some registers to control the
withstand voltage of each pin group. So far those registers were always
located at the same offset, but the A523 SoC has moved them (probably to
accommodate all eleven pin banks).

Add a flag to note this feature, and use that to program the registers
either at offset 0x340 or 0x380. So far no pincontroller driver uses
this flag, but we need it for the upcoming A523 support.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 15 +++++++++++----
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  7 +++++--
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 83a031ceb29f2..f1c5a991cf7b5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -736,9 +736,11 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
 
 		raw_spin_lock_irqsave(&pctl->lock, flags);
-		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
+		reg = readl(pctl->membase + pctl->pow_mod_sel_offset +
+			    PIO_POW_MOD_CTL_OFS);
 		reg &= ~BIT(bank);
-		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
+		writel(reg | val, pctl->membase + pctl->pow_mod_sel_offset +
+		       PIO_POW_MOD_CTL_OFS);
 		raw_spin_unlock_irqrestore(&pctl->lock, flags);
 
 		fallthrough;
@@ -746,9 +748,10 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		val = uV <= 1800000 ? 1 : 0;
 
 		raw_spin_lock_irqsave(&pctl->lock, flags);
-		reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
+		reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
 		reg &= ~(1 << bank);
-		writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
+		writel(reg | val << bank,
+		       pctl->membase + pctl->pow_mod_sel_offset);
 		raw_spin_unlock_irqrestore(&pctl->lock, flags);
 		return 0;
 	default:
@@ -1520,6 +1523,10 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 		pctl->pull_regs_offset = PULL_REGS_OFFSET;
 		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
 	}
+	if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
+		pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
+	else
+		pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
 
 	pctl->irq_array = devm_kcalloc(&pdev->dev,
 				       IRQ_PER_BANK * pctl->desc->irq_banks,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 6cf721876d89d..742fc795c7664 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -87,9 +87,11 @@
 #define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
 #define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)
 #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
+#define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
 
-#define PIO_POW_MOD_SEL_REG	0x340
-#define PIO_POW_MOD_CTL_REG	0x344
+#define PIO_POW_MOD_SEL_REG		0x340
+#define PIO_11B_POW_MOD_SEL_REG		0x380
+#define PIO_POW_MOD_CTL_OFS		0x004
 
 #define PIO_BANK_K_OFFSET		0x500
 
@@ -173,6 +175,7 @@ struct sunxi_pinctrl {
 	u32				bank_mem_size;
 	u32				pull_regs_offset;
 	u32				dlevel_field_width;
+	u32				pow_mod_sel_offset;
 };
 
 #define SUNXI_PIN(_pin, ...)					\
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:19 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:19 +0000
Subject: [PATCH v4 0/8] pinctrl: sunxi: Add Allwinner A523 support
Message-ID: <20250306235827.4895-1-andre.przywara@arm.com>

Hi,

this is the fourth drop of the series introducing pinctrl support for the
Allwinner A523 family of SoCs (comprising A523, A527, T527, H728). [1]
This time only a small fix, spotted by Jernej, thanks for that. Also
adding the new tags. Changelog below.

==============
The first four patches extend the sunxi pinctrl core code to deal with
some specialities of the new SoC: it uses every of the 11 possible banks
except the first one, which required some register remapping. The first
patch here is some cleanup, which we should take regardless, I think,
since it fixes some hack we introduced with the D1 support.

The main feature is actually patch 5, which introduces a new way to
express the required pinmux values for each function/pin pair. 
Traditionally, we dumped a rather large table of data into the (single
image!) kernel for that, but this approach now puts that value into
the DT, and builds the table at runtime. This patch was posted twice
before [2][3], the last time LinusW seemed to be fine with the idea,
just complained about the abuse of the generic pinmux property. I changed
that to allwinner,pinmux now.

The rest of the patches are the usual suspects: the two files for the
two pinctrl instances of the new SoC (now very small), and the DT
binding.

Based on v6.14-rc1. Please have a look, review and test!

Cheers,
Andre

[1] https://linux-sunxi.org/A523#Family_of_sun55iw3
[2] https://patchwork.ozlabs.org/project/linux-gpio/cover/20171113012523.2328-1-andre.przywara at arm.com/
[3] https://lore.kernel.org/linux-arm-kernel/20221110014255.20711-1-andre.przywara at arm.com/

Changelog v3 .. v4:
- fix mixed up POW_MOD_SEL registers
- add review tags (with thanks!)

Changelog v2 .. v3:
- rename POW_MOD_SEL symbol
- drop CCU binding header inclusion in DT binding example
- add review tags (with thanks!)

Changelog v1 .. v2:
- rebased on v6.14-rc1
- extend regulator array to cover PortK as well
- increase number of pins in A523 PortJ from 18 to 28
- extend comment for new pinctrl DT code
- move DT binding into separate yaml file
- Add Jernej's Reviewed-by (with thanks!)


Andre Przywara (8):
  pinctrl: sunxi: refactor pinctrl variants into flags
  pinctrl: sunxi: increase number of GPIO bank regulators
  pinctrl: sunxi: move bank K register offset
  pinctrl: sunxi: support moved power configuration registers
  pinctrl: sunxi: allow reading mux values from DT
  dt-bindings: pinctrl: add compatible for Allwinner A523/T527
  pinctrl: sunxi: Add support for the Allwinner A523
  pinctrl: sunxi: Add support for the secondary A523 GPIO ports

 .../allwinner,sun55i-a523-pinctrl.yaml        | 175 ++++++++
 drivers/pinctrl/sunxi/Kconfig                 |  10 +
 drivers/pinctrl/sunxi/Makefile                |   3 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c     |   6 +-
 drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c     |   8 +-
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c |  54 +++
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c   |  54 +++
 drivers/pinctrl/sunxi/pinctrl-sun5i.c         |   8 +-
 drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c     |   8 +-
 drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c     |   7 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c      | 374 ++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         |  54 ++-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  47 ++-
 13 files changed, 758 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c

-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:20 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:20 +0000
Subject: [PATCH v4 1/8] pinctrl: sunxi: refactor pinctrl variants into flags
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-2-andre.przywara@arm.com>

For some Allwinner SoCs we have one pinctrl driver caring for multiple
very similar chips, and are tagging certain pins with a variant bitmask.
The Allwinner D1 introduced a slightly extended register layout, and we
were abusing this variant mask to convey this bit of information into
the common code part.
Now there will be more pinctrl device properties to consider (has PortF
voltage switch, for instance), so shoehorning this into the variant
bitmask will not fly anymore.

Refactor the "variant" field into a more generic "flags" field. It turns
out that we don't need the variant bits to be unique across all SoCs,
but only among those SoCs that share one driver (table), of which there
are at most three variants at the moment. So the actual variant field can
be limited to say 8 bits, and the other bits in the flag register can be
re-purposed to hold other information, like this extended register
layout.
As a side effect we can move the variant definition into the per-SoC
pinctrl driver file, which makes it more obvious that this is just a
private definition, only relevant for this particular table.
This also changes the artificial sun20i-d1 "variant" into the actual
flag bit that we are after.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c |  6 ++----
 drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c |  8 ++++++--
 drivers/pinctrl/sunxi/pinctrl-sun5i.c     |  8 ++++++--
 drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c |  8 +++++---
 drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c |  7 +++++--
 drivers/pinctrl/sunxi/pinctrl-sunxi.c     | 10 +++++-----
 drivers/pinctrl/sunxi/pinctrl-sunxi.h     | 23 +++++++----------------
 7 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
index 8e2aab542fcfe..8efe35b77af4d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
@@ -820,15 +820,13 @@ static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
 
 static int d1_pinctrl_probe(struct platform_device *pdev)
 {
-	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
-
-	return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
+	return sunxi_pinctrl_init_with_flags(pdev, &d1_pinctrl_data,
+					     SUNXI_PINCTRL_NEW_REG_LAYOUT);
 }
 
 static const struct of_device_id d1_pinctrl_match[] = {
 	{
 		.compatible = "allwinner,sun20i-d1-pinctrl",
-		.data = (void *)PINCTRL_SUN20I_D1
 	},
 	{}
 };
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
index fa47fe36ee5bc..b2e82bf927b3c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
@@ -17,6 +17,10 @@
 
 #include "pinctrl-sunxi.h"
 
+#define PINCTRL_SUN4I_A10	BIT(0)
+#define PINCTRL_SUN7I_A20	BIT(1)
+#define PINCTRL_SUN8I_R40	BIT(2)
+
 static const struct sunxi_desc_pin sun4i_a10_pins[] = {
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -1295,8 +1299,8 @@ static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
 {
 	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
 
-	return sunxi_pinctrl_init_with_variant(pdev, &sun4i_a10_pinctrl_data,
-					       variant);
+	return sunxi_pinctrl_init_with_flags(pdev, &sun4i_a10_pinctrl_data,
+					     variant);
 }
 
 static const struct of_device_id sun4i_a10_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i.c b/drivers/pinctrl/sunxi/pinctrl-sun5i.c
index 06ecb121c8274..6eef314c93775 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i.c
@@ -16,6 +16,10 @@
 
 #include "pinctrl-sunxi.h"
 
+#define PINCTRL_SUN5I_A10S	BIT(0)
+#define PINCTRL_SUN5I_A13	BIT(1)
+#define PINCTRL_SUN5I_GR8	BIT(2)
+
 static const struct sunxi_desc_pin sun5i_pins[] = {
 	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(A, 0),
 		  PINCTRL_SUN5I_A10S,
@@ -719,8 +723,8 @@ static int sun5i_pinctrl_probe(struct platform_device *pdev)
 {
 	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
 
-	return sunxi_pinctrl_init_with_variant(pdev, &sun5i_pinctrl_data,
-					       variant);
+	return sunxi_pinctrl_init_with_flags(pdev, &sun5i_pinctrl_data,
+					     variant);
 }
 
 static const struct of_device_id sun5i_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
index 82ac064931df3..8d8c92ce41cff 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
@@ -17,6 +17,9 @@
 
 #include "pinctrl-sunxi.h"
 
+#define PINCTRL_SUN6I_A31	BIT(0)
+#define PINCTRL_SUN6I_A31S	BIT(1)
+
 static const struct sunxi_desc_pin sun6i_a31_pins[] = {
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -972,9 +975,8 @@ static int sun6i_a31_pinctrl_probe(struct platform_device *pdev)
 	unsigned long variant =
 		(unsigned long)of_device_get_match_data(&pdev->dev);
 
-	return sunxi_pinctrl_init_with_variant(pdev,
-					       &sun6i_a31_pinctrl_data,
-					       variant);
+	return sunxi_pinctrl_init_with_flags(pdev, &sun6i_a31_pinctrl_data,
+					     variant);
 }
 
 static const struct of_device_id sun6i_a31_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c
index 49c9a0b6a0eb4..696d7dd8d87ba 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v3s.c
@@ -22,6 +22,9 @@
 
 #include "pinctrl-sunxi.h"
 
+#define PINCTRL_SUN8I_V3	BIT(0)
+#define PINCTRL_SUN8I_V3S	BIT(1)
+
 static const struct sunxi_desc_pin sun8i_v3s_pins[] = {
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
@@ -552,8 +555,8 @@ static int sun8i_v3s_pinctrl_probe(struct platform_device *pdev)
 {
 	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
 
-	return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v3s_pinctrl_data,
-					       variant);
+	return sunxi_pinctrl_init_with_flags(pdev, &sun8i_v3s_pinctrl_data,
+					     variant);
 }
 
 static const struct of_device_id sun8i_v3s_pinctrl_match[] = {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index bde67ee31417f..ae281a3c2ed34 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1472,9 +1472,9 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
 	return 0;
 }
 
-int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
-				    const struct sunxi_pinctrl_desc *desc,
-				    unsigned long variant)
+int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
+				  const struct sunxi_pinctrl_desc *desc,
+				  unsigned long flags)
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct pinctrl_desc *pctrl_desc;
@@ -1497,8 +1497,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
 
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
-	pctl->variant = variant;
-	if (pctl->variant >= PINCTRL_SUN20I_D1) {
+	pctl->variant = flags & SUNXI_PINCTRL_VARIANT_MASK;
+	if (flags & SUNXI_PINCTRL_NEW_REG_LAYOUT) {
 		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
 		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
 		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a87a2f944d609..8e2eca45b57f8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -82,18 +82,9 @@
 #define SUN4I_FUNC_INPUT	0
 #define SUN4I_FUNC_IRQ		6
 
-#define PINCTRL_SUN5I_A10S	BIT(1)
-#define PINCTRL_SUN5I_A13	BIT(2)
-#define PINCTRL_SUN5I_GR8	BIT(3)
-#define PINCTRL_SUN6I_A31	BIT(4)
-#define PINCTRL_SUN6I_A31S	BIT(5)
-#define PINCTRL_SUN4I_A10	BIT(6)
-#define PINCTRL_SUN7I_A20	BIT(7)
-#define PINCTRL_SUN8I_R40	BIT(8)
-#define PINCTRL_SUN8I_V3	BIT(9)
-#define PINCTRL_SUN8I_V3S	BIT(10)
-/* Variants below here have an updated register layout. */
-#define PINCTRL_SUN20I_D1	BIT(11)
+#define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
+#define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)
+#define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
 
 #define PIO_POW_MOD_SEL_REG	0x340
 #define PIO_POW_MOD_CTL_REG	0x344
@@ -299,11 +290,11 @@ static inline u32 sunxi_grp_config_reg(u16 pin)
 	return GRP_CFG_REG + bank * 0x4;
 }
 
-int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
-				    const struct sunxi_pinctrl_desc *desc,
-				    unsigned long variant);
+int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
+				  const struct sunxi_pinctrl_desc *desc,
+				  unsigned long flags);
 
 #define sunxi_pinctrl_init(_dev, _desc) \
-	sunxi_pinctrl_init_with_variant(_dev, _desc, 0)
+	sunxi_pinctrl_init_with_flags(_dev, _desc, 0)
 
 #endif /* __PINCTRL_SUNXI_H */
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:21 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:21 +0000
Subject: [PATCH v4 2/8] pinctrl: sunxi: increase number of GPIO bank regulators
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-3-andre.przywara@arm.com>

By design, the Allwinner pinctrl IP always supported up to 11 GPIO banks,
though no SoC ever used more than 9 banks so far.
The Allwinner A523 has pins in all 11 banks, which exceeds the number of
per-bank regulators that we currently support, as this was set to 9.

Increase the size of the array to hold up to 11 regulator structs, to
support pins in bank J and K as well.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 8e2eca45b57f8..fbbf070a87542 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -155,7 +155,7 @@ struct sunxi_pinctrl {
 	struct gpio_chip		*chip;
 	const struct sunxi_pinctrl_desc	*desc;
 	struct device			*dev;
-	struct sunxi_pinctrl_regulator	regulators[9];
+	struct sunxi_pinctrl_regulator	regulators[11];
 	struct irq_domain		*domain;
 	struct sunxi_pinctrl_function	*functions;
 	unsigned			nfunctions;
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:22 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:22 +0000
Subject: [PATCH v4 3/8] pinctrl: sunxi: move bank K register offset
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-4-andre.przywara@arm.com>

The Allwinner pincontroller register layout used to allow for at least
11 banks per controller, any more banks would reside at a second
controller instance.
When the per-bank register map size was increased with the D1, it turned
out that the last bank (port K) of those maximum 11 banks actually would
not fit anymore in the 512 bytes reserved for the pincontroller registers.
On new SoCs Allwinner thus moved the last bank beyond the existing
registers, at offset 0x500.

So far SoCs never used more than 9 banks per controller, but the new
Allwinner A523 actually uses all 11 banks. Since that SoC also uses the
extended layout, its PortK needs to be programmed at offset 0x500.

Factor out the bank offset calculation into a new function, and handle
the case for the last bank separately. Since none of the older SoCs ever
used PortK, we can ignore this case, and just always use offset 0x500
for the last bank.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 29 +++++++++++++++++++--------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  4 ++++
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ae281a3c2ed34..83a031ceb29f2 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -58,13 +58,29 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
  * The following functions calculate the register and the bit offset to access.
  * They take a pin number which is relative to the start of the current device.
  */
+
+/*
+ * When using the extended register layout, Bank K does not fit into the
+ * space used for the other banks. Instead it lives at offset 0x500.
+ */
+static u32 sunxi_bank_offset(const struct sunxi_pinctrl *pctl, u32 pin)
+{
+	u32 offset = 0;
+
+	if (pin >= PK_BASE) {
+		pin -= PK_BASE;
+		offset = PIO_BANK_K_OFFSET;
+	}
+
+	return offset + (pin / PINS_PER_BANK) * pctl->bank_mem_size;
+}
+
 static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
 			  u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
-	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
 
-	*reg   = bank * pctl->bank_mem_size + MUX_REGS_OFFSET +
+	*reg   = sunxi_bank_offset(pctl, pin) + MUX_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
@@ -73,10 +89,9 @@ static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
 static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
 			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
-	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
 
-	*reg   = bank * pctl->bank_mem_size + DATA_REGS_OFFSET +
+	*reg   = sunxi_bank_offset(pctl, pin) + DATA_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
@@ -85,10 +100,9 @@ static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
 static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
 			     u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
-	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
 
-	*reg   = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET +
+	*reg   = sunxi_bank_offset(pctl, pin) + DLEVEL_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(pctl->dlevel_field_width) - 1) << *shift;
@@ -97,10 +111,9 @@ static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
 static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl,
 			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
-	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
 
-	*reg   = bank * pctl->bank_mem_size + pctl->pull_regs_offset +
+	*reg   = sunxi_bank_offset(pctl, pin) + pctl->pull_regs_offset +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index fbbf070a87542..6cf721876d89d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -25,6 +25,8 @@
 #define PG_BASE	192
 #define PH_BASE	224
 #define PI_BASE	256
+#define PJ_BASE	288
+#define PK_BASE	320
 #define PL_BASE	352
 #define PM_BASE	384
 #define PN_BASE	416
@@ -89,6 +91,8 @@
 #define PIO_POW_MOD_SEL_REG	0x340
 #define PIO_POW_MOD_CTL_REG	0x344
 
+#define PIO_BANK_K_OFFSET		0x500
+
 enum sunxi_desc_bias_voltage {
 	BIAS_VOLTAGE_NONE,
 	/*
-- 
2.46.3



From jonas at kwiboo.se  Thu Mar  6 16:05:34 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 01:05:34 +0100
Subject: [PATCH 3/4] arm64: dts: rockchip: Add GMAC nodes for RK3528
In-Reply-To: <a827e7e9-882a-40c6-9f2c-03d8181dff88@lunn.ch>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-4-jonas@kwiboo.se>
 <a827e7e9-882a-40c6-9f2c-03d8181dff88@lunn.ch>
Message-ID: <003d3726-680a-4e91-89cd-d127bc3b5609@kwiboo.se>

Hi Andrew,

On 2025-03-06 23:46, Andrew Lunn wrote:
> On Thu, Mar 06, 2025 at 10:13:56PM +0000, Jonas Karlman wrote:
>> Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
>> Ethernet QoS IP.
>>
>> Add device tree nodes for the two Ethernet controllers in RK3528.
>>
>> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
>> ---
>> gmac0 is missing the integrated-phy and has not been tested bacause I do
>> not have any board that use this Ethernet controller.
> 
> What do you know about the integrated PHY? Does it use one of the
> standard phy-modes? RMII? Does the datasheet indicate what address it
> uses on the MDIO bus? If you know these two bits of information, you
> can probably add it.

The SoC datasheet lists following:

  MAC 10/100/1000 Ethernet Controller (gmac1)
  - Support 10/100/1000 Mbps data transfer rates with the RGMII interfaces
  - Support 10/100 Mbps data transfer rates with the RMII interfaces
  - Support both full-duplex and half-duplex operation
  - Supports IEEE 802.1Q VLAN tag detection for reception frames
  - Support detection of LAN wake-up frames and AMD Magic Packet frames
  - Support checking IPv4 header checksum and TCP, UDP, or ICMP checksum
    encapsulated in IPv4 or IPv6 datagram
  - Support for TCP Segmentation Offload (TSO) and UDP Fragmentation
    Offload (UFO)

  MAC 10/100M Ethernet controller and MAC PHY (gmac0)
  - Support one Ethernet controllers
  - Support 10/100-Mbps data transfer rates with the RMII interfaces
  - Support both full-duplex and half-duplex operation

and vendor kernel use following DT node:

	phy-mode = "rmii";
	clock_in_out = "input";
	phy-handle = <&rmii0_phy>;

	mdio0: mdio {
		compatible = "snps,dwmac-mdio";
		#address-cells = <0x1>;
		#size-cells = <0x0>;

		rmii0_phy: ethernet-phy at 2 {
			compatible = "ethernet-phy-id0044.1400", "ethernet-phy-ieee802.3-c22";
			reg = <2>;
			clocks = <&cru CLK_MACPHY>;
			resets = <&cru SRST_MACPHY>;
			phy-is-integrated;
			pinctrl-names = "default";
			pinctrl-0 = <&fephym0_led_link &fephym0_led_spd>;
		};
	};

I could possible add something like that to the device tree, or I could
drop the entire gmac0 node and instead have it added in a future series.

Regards,
Jonas

> 
>     Andrew



From rmk+kernel at armlinux.org.uk  Thu Mar  6 16:11:29 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 07 Mar 2025 00:11:29 +0000
Subject: [PATCH net-next] net: stmmac: remove write-only priv->speed
Message-ID: <E1tqLJJ-005aQm-Mv@rmk-PC.armlinux.org.uk>

priv->speed is only ever written to in two locations, but never
read. Therefore, it serves no useful purpose. Remove this unnecessary
struct member.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h      | 1 -
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ---
 2 files changed, 4 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 04197496ee87..bddfa0f4aa21 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -282,7 +282,6 @@ struct stmmac_priv {
 	/* Generic channel for NAPI */
 	struct stmmac_channel channel[STMMAC_CH_MAX];
 
-	int speed;
 	unsigned int pause_time;
 	struct mii_bus *mii;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2ce18f52b717..982b7d82fd53 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1029,8 +1029,6 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 		}
 	}
 
-	priv->speed = speed;
-
 	if (priv->plat->fix_mac_speed)
 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed, mode);
 
@@ -7859,7 +7857,6 @@ int stmmac_suspend(struct device *dev)
 	if (stmmac_fpe_supported(priv))
 		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
 
-	priv->speed = SPEED_UNKNOWN;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(stmmac_suspend);
-- 
2.30.2



From andre.przywara at arm.com  Thu Mar  6 15:58:24 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:24 +0000
Subject: [PATCH v4 5/8] pinctrl: sunxi: allow reading mux values from DT
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-6-andre.przywara@arm.com>

So far every Allwinner SoC needs a large table in the kernel code, to
describe the mapping between the pinctrl function names ("uart") and
the actual pincontroller mux value to be written into the registers.
This adds a lot of data into a single image kernel, and also looks
somewhat weird, as the DT can easily store the mux value.

Add some code that allows to avoid that table: the struct that describes
the existing pins will be build at *runtime*, based on very basic
information provided by the respective SoC's pinctrl driver. This
consists of the number of pins per bank, plus information which bank
provides IRQ support, along with the mux value to use for that.
The code will then iterate over all children of the pincontroller DT
node (which describe each pin group), and populate that struct with the
mapping between function names and mux values. The only thing that needs
adding in the DT is a property with that value, per pin group.

When this table is built, it will be handed over to the existing sunxi
pinctrl driver, which cannot tell a difference between a hardcoded
struct and this new one built at runtime. It will take care of
registering the pinctrl device with the pinctrl subsystem.

All a new SoC driver would need to do is to provide two arrays, and then
call the sunxi_pinctrl_dt_table_init() function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/pinctrl/sunxi/Makefile           |   1 +
 drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c | 374 +++++++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.h    |   9 +
 3 files changed, 384 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c

diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 2ff5a55927ad6..f5bad7a529519 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 # Core
 obj-y					+= pinctrl-sunxi.o
+obj-y					+= pinctrl-sunxi-dt.o
 
 # SoC Drivers
 obj-$(CONFIG_PINCTRL_SUNIV_F1C100S)	+= pinctrl-suniv-f1c100s.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
new file mode 100644
index 0000000000000..1833078f68776
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017-2025 Arm Ltd.
+ *
+ * Generic DT driven Allwinner pinctrl driver routines.
+ * Builds the pin tables from minimal driver information and pin groups
+ * described in the DT. Then hands those tables of to the traditional
+ * sunxi pinctrl driver.
+ * sunxi_pinctrl_init() expects a table like shown below, previously spelled
+ * out in a per-SoC .c file. This code generates this table, like so:
+ *
+ *  SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),	// code iterates over every implemented
+ *				// pin, based on pins_per_bank[] array passed in
+ *
+ *    SUNXI_FUNCTION(0x0, "gpio_in"),	// always added, for every pin
+ *    SUNXI_FUNCTION(0x1, "gpio_out"),	// always added, for every pin
+ *
+ *    SUNXI_FUNCTION(0x2, "mmc0"),	// based on pingroup found in DT:
+ *				//   mmc0-pins {
+ *				//       pins = "PF0", "PF1", ...
+ *				//       function = "mmc0";
+ *				//       allwinner,pinmux = <2>;
+ *
+ *    SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 1)),	// derived by irq_bank_muxes[]
+ *						// array passed in
+ */
+
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-sunxi.h"
+
+#define INVALID_MUX	0xff
+
+/*
+ * Return the "index"th element from the "allwinner,pinmux" property. If the
+ * property does not hold enough entries, return the last one instead.
+ * For almost every group the pinmux value is actually the same, so this
+ * allows to just list one value in the property.
+ */
+static u8 sunxi_pinctrl_dt_read_pinmux(const struct device_node *node,
+				       int index)
+{
+	int ret, num_elems;
+	u32 value;
+
+	num_elems = of_property_count_u32_elems(node, "allwinner,pinmux");
+	if (num_elems <= 0)
+		return INVALID_MUX;
+
+	if (index >= num_elems)
+		index = num_elems - 1;
+
+	ret = of_property_read_u32_index(node, "allwinner,pinmux", index,
+					 &value);
+	if (ret)
+		return INVALID_MUX;
+
+	return value;
+}
+
+/*
+ * Allocate a table with a sunxi_desc_pin structure for every pin needed.
+ * Fills in the respective pin names ("PA0") and their pin numbers.
+ * Returns the pins array. We cannot use the member in *desc yet, as this
+ * is marked as const, and we will need to change the array still.
+ */
+static struct sunxi_desc_pin *init_pins_table(struct device *dev,
+					      const u8 *pins_per_bank,
+					      struct sunxi_pinctrl_desc *desc)
+{
+	struct sunxi_desc_pin *pins, *cur_pin;
+	int name_size = 0;
+	int port_base = desc->pin_base / PINS_PER_BANK;
+	char *pin_names, *cur_name;
+	int i, j;
+
+	/*
+	 * Find the total number of pins.
+	 * Also work out how much memory we need to store all the pin names.
+	 */
+	for (i = 0; i < SUNXI_PINCTRL_MAX_BANKS; i++) {
+		desc->npins += pins_per_bank[i];
+		if (pins_per_bank[i] < 10) {
+			/* 4 bytes for "PXy\0" */
+			name_size += pins_per_bank[i] * 4;
+		} else {
+			/* 4 bytes for each "PXy\0" */
+			name_size += 10 * 4;
+
+			/* 5 bytes for each "PXyy\0" */
+			name_size += (pins_per_bank[i] - 10) * 5;
+		}
+	}
+
+	if (desc->npins == 0) {
+		dev_err(dev, "no ports defined\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	pins = devm_kzalloc(dev, desc->npins * sizeof(*pins), GFP_KERNEL);
+	if (!pins)
+		return ERR_PTR(-ENOMEM);
+
+	/* Allocate memory to store the name for every pin. */
+	pin_names = devm_kmalloc(dev, name_size, GFP_KERNEL);
+	if (!pin_names)
+		return ERR_PTR(-ENOMEM);
+
+	/* Fill the pins array with the name and the number for each pin. */
+	cur_name = pin_names;
+	cur_pin = pins;
+	for (i = 0; i < SUNXI_PINCTRL_MAX_BANKS; i++) {
+		for (j = 0; j < pins_per_bank[i]; j++, cur_pin++) {
+			int nchars = sprintf(cur_name, "P%c%d",
+					     port_base + 'A' + i, j);
+
+			cur_pin->pin.number = (port_base + i) * PINS_PER_BANK + j;
+			cur_pin->pin.name = cur_name;
+			cur_name += nchars + 1;
+		}
+	}
+
+	return pins;
+}
+
+/*
+ * Work out the number of functions for each pin. This will visit every
+ * child node of the pinctrl DT node to find all advertised functions.
+ * Provide memory to hold the per-function information and assign it to
+ * the pin table.
+ * Fill in the GPIO in/out functions already (that every pin has), also add
+ * an "irq" function at the end, for those pins in IRQ-capable ports.
+ * We do not fill in the extra functions (those describe in DT nodes) yet.
+ * We (ab)use the "variant" member in each pin to keep track of the number of
+ * extra functions needed. At the end this will get reset to 2, so that we
+ * can add extra function later, after the two GPIO functions.
+ */
+static int prepare_function_table(struct device *dev, struct device_node *pnode,
+				  struct sunxi_desc_pin *pins, int npins,
+				  const u8 *irq_bank_muxes)
+{
+	struct device_node *node;
+	struct property *prop;
+	struct sunxi_desc_function *func;
+	int num_funcs, irq_bank, last_bank, i;
+
+	/*
+	 * We need at least three functions per pin:
+	 * - one for GPIO in
+	 * - one for GPIO out
+	 * - one for the sentinel signalling the end of the list
+	 */
+	num_funcs = 3 * npins;
+
+	/*
+	 * Add a function for each pin in a bank supporting interrupts.
+	 * We temporarily (ab)use the variant field to store the number of
+	 * functions per pin. This will be cleaned back to 0 before we hand
+	 * over the whole structure to the generic sunxi pinctrl setup code.
+	 */
+	for (i = 0; i < npins; i++) {
+		struct sunxi_desc_pin *pin = &pins[i];
+		int bank = pin->pin.number / PINS_PER_BANK;
+
+		if (irq_bank_muxes[bank]) {
+			pin->variant++;
+			num_funcs++;
+		}
+	}
+
+	/*
+	 * Go over each pin group (every child of the pinctrl DT node) and
+	 * add the number of special functions each pins has. Also update the
+	 * total number of functions required.
+	 * We might slightly overshoot here in case of double definitions.
+	 */
+	for_each_child_of_node(pnode, node) {
+		const char *name;
+
+		of_property_for_each_string(node, "pins", prop, name) {
+			for (i = 0; i < npins; i++) {
+				if (strcmp(pins[i].pin.name, name))
+					continue;
+
+				pins[i].variant++;
+				num_funcs++;
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Allocate the memory needed for the functions in one table.
+	 * We later use pointers into this table to mark each pin.
+	 */
+	func = devm_kzalloc(dev, num_funcs * sizeof(*func), GFP_KERNEL);
+	if (!func)
+		return -ENOMEM;
+
+	/*
+	 * Assign the function's memory and fill in GPIOs, IRQ and a sentinel.
+	 * The extra functions will be filled in later.
+	 */
+	irq_bank = 0;
+	last_bank = 0;
+	for (i = 0; i < npins; i++) {
+		struct sunxi_desc_pin *pin = &pins[i];
+		int bank = pin->pin.number / PINS_PER_BANK;
+		int lastfunc = pin->variant + 1;
+		int irq_mux = irq_bank_muxes[bank];
+
+		func[0].name = "gpio_in";
+		func[0].muxval = 0;
+		func[1].name = "gpio_out";
+		func[1].muxval = 1;
+
+		if (irq_mux) {
+			if (bank > last_bank)
+				irq_bank++;
+			func[lastfunc].muxval = irq_mux;
+			func[lastfunc].irqbank = irq_bank;
+			func[lastfunc].irqnum = pin->pin.number % PINS_PER_BANK;
+			func[lastfunc].name = "irq";
+		}
+
+		if (bank > last_bank)
+			last_bank = bank;
+
+		pin->functions = func;
+
+		/* Skip over the other needed functions and the sentinel. */
+		func += pin->variant + 3;
+
+		/*
+		 * Reset the value for filling in the remaining functions
+		 * behind the GPIOs later.
+		 */
+		pin->variant = 2;
+	}
+
+	return 0;
+}
+
+/*
+ * Iterate over all pins in a single group and add the function name and its
+ * mux value to the respective pin.
+ * The "variant" member is again used to temporarily track the number of
+ * already added functions.
+ */
+static void fill_pin_function(struct device *dev, struct device_node *node,
+			      struct sunxi_desc_pin *pins, int npins)
+{
+	const char *name, *funcname;
+	struct sunxi_desc_function *func;
+	struct property *prop;
+	int pin, i, index;
+	u8 muxval;
+
+	if (of_property_read_string(node, "function", &funcname)) {
+		dev_warn(dev, "missing \"function\" property\n");
+		return;
+	}
+
+	index = 0;
+	of_property_for_each_string(node, "pins", prop, name) {
+		/* Find the index of this pin in our table. */
+		for (pin = 0; pin < npins; pin++)
+			if (!strcmp(pins[pin].pin.name, name))
+				break;
+		if (pin == npins) {
+			dev_warn(dev, "%s: cannot find pin %s\n",
+				 of_node_full_name(node), name);
+			index++;
+			continue;
+		}
+
+		/* Read the associated mux value. */
+		muxval = sunxi_pinctrl_dt_read_pinmux(node, index);
+		if (muxval == INVALID_MUX) {
+			dev_warn(dev, "%s: invalid mux value for pin %s\n",
+				 of_node_full_name(node), name);
+			index++;
+			continue;
+		}
+
+		/*
+		 * Check for double definitions by comparing the to-be-added
+		 * function with already assigned ones.
+		 * Ignore identical pairs (function name and mux value the
+		 * same), but warn about conflicting assignments.
+		 */
+		for (i = 2; i < pins[pin].variant; i++) {
+			func = &pins[pin].functions[i];
+
+			/* Skip over totally unrelated functions. */
+			if (strcmp(func->name, funcname) &&
+			    func->muxval != muxval)
+				continue;
+
+			/* Ignore (but skip below) any identical functions. */
+			if (!strcmp(func->name, funcname) &&
+			    muxval == func->muxval)
+				break;
+
+			dev_warn(dev,
+				 "pin %s: function %s redefined to mux %d\n",
+				 name, funcname, muxval);
+			break;
+		}
+
+		/* Skip any pins with that function already assigned. */
+		if (i < pins[pin].variant) {
+			index++;
+			continue;
+		}
+
+		/* Assign function and muxval to the next free slot. */
+		func = &pins[pin].functions[pins[pin].variant];
+		func->muxval = muxval;
+		func->name = funcname;
+
+		pins[pin].variant++;
+		index++;
+	}
+}
+
+/*
+ * Initialise the pinctrl table, by building it from driver provided
+ * information: the number of pins per bank, the IRQ capable banks and their
+ * IRQ mux value.
+ * Then iterate over all pinctrl DT node children to enter the function name
+ * and mux values for each mentioned pin.
+ * At the end hand over this structure to the actual sunxi pinctrl driver.
+ */
+int sunxi_pinctrl_dt_table_init(struct platform_device *pdev,
+				const u8 *pins_per_bank,
+				const u8 *irq_bank_muxes,
+				struct sunxi_pinctrl_desc *desc,
+				unsigned long flags)
+{
+	struct device_node *pnode = pdev->dev.of_node, *node;
+	struct sunxi_desc_pin *pins;
+	int ret, i;
+
+	pins = init_pins_table(&pdev->dev, pins_per_bank, desc);
+	if (IS_ERR(pins))
+		return PTR_ERR(pins);
+
+	ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins,
+				     irq_bank_muxes);
+	if (ret)
+		return ret;
+
+	/*
+	 * Now iterate over all groups and add the respective function name
+	 * and mux values to each pin listed within.
+	 */
+	for_each_child_of_node(pnode, node)
+		fill_pin_function(&pdev->dev, node, pins, desc->npins);
+
+	/* Clear the temporary storage. */
+	for (i = 0; i < desc->npins; i++)
+		pins[i].variant = 0;
+
+	desc->pins = pins;
+
+	return sunxi_pinctrl_init_with_flags(pdev, desc, flags);
+}
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 742fc795c7664..ad26e4de16a85 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -31,6 +31,9 @@
 #define PM_BASE	384
 #define PN_BASE	416
 
+/* maximum number of banks per controller (PA -> PK) */
+#define SUNXI_PINCTRL_MAX_BANKS	11
+
 #define SUNXI_PINCTRL_PIN(bank, pin)		\
 	PINCTRL_PIN(P ## bank ## _BASE + (pin), "P" #bank #pin)
 
@@ -304,4 +307,10 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
 #define sunxi_pinctrl_init(_dev, _desc) \
 	sunxi_pinctrl_init_with_flags(_dev, _desc, 0)
 
+int sunxi_pinctrl_dt_table_init(struct platform_device *pdev,
+				const u8 *pins_per_bank,
+				const u8 *irq_bank_muxes,
+				struct sunxi_pinctrl_desc *desc,
+				unsigned long flags);
+
 #endif /* __PINCTRL_SUNXI_H */
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:25 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:25 +0000
Subject: [PATCH v4 6/8] dt-bindings: pinctrl: add compatible for Allwinner A523/T527
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-7-andre.przywara@arm.com>

The A523 contains a pin controller similar to previous SoCs, although
using 10 GPIO banks (PortB-PortK), all of them being IRQ capable.
With this SoC we introduce a new style of binding, where the pinmux values
for each pin group are stored in the new "allwinner,pinmux" property in
the DT node, instead of requiring every driver to store a mapping between
the function names and the required pinmux.

Add a new binding file, since all the different variants of the old
binding are making the file a bit unwieldy to handle already, and the new
property would make the situation worse.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../allwinner,sun55i-a523-pinctrl.yaml        | 175 ++++++++++++++++++
 1 file changed, 175 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
new file mode 100644
index 0000000000000..154e03da8ce98
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/allwinner,sun55i-a523-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A523 Pin Controller
+
+maintainers:
+  - Andre Przywara <andre.przywara at arm.com>
+
+properties:
+  "#gpio-cells":
+    const: 3
+    description:
+      GPIO consumers must use three arguments, first the number of the
+      bank, then the pin number inside that bank, and finally the GPIO
+      flags.
+
+  "#interrupt-cells":
+    const: 3
+    description:
+      Interrupts consumers must use three arguments, first the number
+      of the bank, then the pin number inside that bank, and finally
+      the interrupts flags.
+
+  compatible:
+    enum:
+      - allwinner,sun55i-a523-pinctrl
+      - allwinner,sun55i-a523-r-pinctrl
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    minItems: 2
+    maxItems: 10
+    description:
+      One interrupt per external interrupt bank supported on the
+      controller, sorted by bank number ascending order.
+
+  clocks:
+    items:
+      - description: Bus Clock
+      - description: High Frequency Oscillator
+      - description: Low Frequency Oscillator
+
+  clock-names:
+    items:
+      - const: apb
+      - const: hosc
+      - const: losc
+
+  gpio-controller: true
+  interrupt-controller: true
+  gpio-line-names: true
+
+  input-debounce:
+    description:
+      Debouncing periods in microseconds, one period per interrupt
+      bank found in the controller
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 2
+    maxItems: 10
+
+patternProperties:
+  # It's pretty scary, but the basic idea is that:
+  #   - One node name can start with either s- or r- for PRCM nodes,
+  #   - Then, the name itself can be any repetition of <string>- (to
+  #     accommodate with nodes like uart4-rts-cts-pins), where each
+  #     string can be either starting with 'p' but in a string longer
+  #     than 3, or something that doesn't start with 'p',
+  #   - Then, the bank name is optional and will be between pa and pm.
+  #     Some pins groups that have several options will have the pin
+  #     numbers then,
+  #   - Finally, the name will end with either -pin or pins.
+
+  "^([rs]-)?(([a-z0-9]{3,}|[a-oq-z][a-z0-9]*?)?-)+?(p[a-m][0-9]*?-)??pins?$":
+    type: object
+
+    properties:
+      pins: true
+      function: true
+      bias-disable: true
+      bias-pull-up: true
+      bias-pull-down: true
+
+      drive-strength:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        enum: [10, 20, 30, 40]
+
+      allwinner,pinmux:
+        $ref: /schemas/types.yaml#/definitions/uint32-array
+        description:
+          Pinmux selector value, for each pin. Almost every time this value
+          is the same for all pins, so any array shorter than the number of
+          pins will repeat the last value, to allow just specifying a single
+          cell, for all cells.
+
+    required:
+      - pins
+      - allwinner,pinmux
+      - function
+
+    additionalProperties: false
+
+  "^vcc-p[a-m]-supply$":
+    description:
+      Power supplies for pin banks.
+
+required:
+  - "#gpio-cells"
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - gpio-controller
+  - "#interrupt-cells"
+  - interrupts
+  - interrupt-controller
+
+allOf:
+  - $ref: pinctrl.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun55i-a523-pinctrl
+
+    then:
+      properties:
+        interrupts:
+          minItems: 10
+          maxItems: 10
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun55i-a523-r-pinctrl
+
+    then:
+      properties:
+        interrupts:
+          minItems: 2
+          maxItems: 2
+
+additionalProperties: false
+
+examples:
+  - |
+    r_pio: pinctrl at 7022000 {
+        compatible = "allwinner,sun55i-a523-r-pinctrl";
+        reg = <0x7022000 0x800>;
+        interrupts = <0 159 4>, <0 161 4>;
+        clocks = <&r_ccu 1>, <&osc24M>, <&osc32k>;
+        clock-names = "apb", "hosc", "losc";
+        gpio-controller;
+        #gpio-cells = <3>;
+        interrupt-controller;
+        #interrupt-cells = <3>;
+
+        r_i2c_pins: r-i2c-pins {
+            pins = "PL0", "PL1";
+            allwinner,pinmux = <2>;
+            function = "r_i2c0";
+            bias-pull-up;
+        };
+
+        r_spi_pins: r-spi-pins {
+            pins = "PL11" ,"PL12", "PL13";
+            allwinner,pinmux = <6>;
+            function = "r_spi";
+        };
+    };
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:26 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:26 +0000
Subject: [PATCH v4 7/8] pinctrl: sunxi: Add support for the Allwinner A523
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-8-andre.przywara@arm.com>

The Allwinner A523 contains pins in 10 out of the 11 possible pin banks;
it just skips port A.
Use the newly introduced DT based pinctrl driver to describe just the
generic pinctrl properties, so advertise the number of pins per bank
and the interrupt capabilities. The actual function/mux assignment is
taken from the devicetree.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/pinctrl/sunxi/Kconfig               |  5 ++
 drivers/pinctrl/sunxi/Makefile              |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c | 54 +++++++++++++++++++++
 3 files changed, 60 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index a78fdbbdfc0c7..0cbe466683650 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -131,4 +131,9 @@ config PINCTRL_SUN50I_H616_R
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN55I_A523
+	bool "Support for the Allwinner A523 PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index f5bad7a529519..4e55508ff7f76 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -27,5 +27,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
+obj-$(CONFIG_PINCTRL_SUN55I_A523)	+= pinctrl-sun55i-a523.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
new file mode 100644
index 0000000000000..7d2308c37d29e
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A523 SoC pinctrl driver.
+ *
+ * Copyright (C) 2023 Arm Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const u8 a523_nr_bank_pins[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PA  PB  PC  PD  PE  PF  PG  PH  PI  PJ  PK */
+	{  0, 15, 17, 24, 16,  7, 15, 20, 17, 28, 24 };
+
+static const unsigned int a523_irq_bank_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+static const u8 a523_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PA  PB  PC  PD  PE  PF  PG  PH  PI  PJ  PK */
+	{  0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
+
+static struct sunxi_pinctrl_desc a523_pinctrl_data = {
+	.irq_banks = ARRAY_SIZE(a523_irq_bank_map),
+	.irq_bank_map = a523_irq_bank_map,
+	.irq_read_needs_mux = true,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int a523_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_dt_table_init(pdev, a523_nr_bank_pins,
+					   a523_irq_bank_muxes,
+					   &a523_pinctrl_data,
+					   SUNXI_PINCTRL_NEW_REG_LAYOUT |
+					   SUNXI_PINCTRL_ELEVEN_BANKS);
+}
+
+static const struct of_device_id a523_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun55i-a523-pinctrl", },
+	{}
+};
+
+static struct platform_driver a523_pinctrl_driver = {
+	.probe	= a523_pinctrl_probe,
+	.driver	= {
+		.name		= "sun55i-a523-pinctrl",
+		.of_match_table	= a523_pinctrl_match,
+	},
+};
+builtin_platform_driver(a523_pinctrl_driver);
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 15:58:27 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  6 Mar 2025 23:58:27 +0000
Subject: [PATCH v4 8/8] pinctrl: sunxi: Add support for the secondary A523 GPIO ports
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <20250306235827.4895-9-andre.przywara@arm.com>

As most other Allwinner SoCs before, the A523 chip contains a second
GPIO controller, managing banks PL and PM.
Use the newly introduced DT based pinctrl driver to describe just the
generic pinctrl properties, so advertise the number of pins per bank
and the interrupt capabilities. The actual function/mux assignment is
taken from the devicetree.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/pinctrl/sunxi/Kconfig                 |  5 ++
 drivers/pinctrl/sunxi/Makefile                |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c | 54 +++++++++++++++++++
 3 files changed, 60 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 0cbe466683650..dc62eba96348e 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -136,4 +136,9 @@ config PINCTRL_SUN55I_A523
 	default ARM64 && ARCH_SUNXI
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN55I_A523_R
+	bool "Support for the Allwinner A523 R-PIO"
+	default ARM64 && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 4e55508ff7f76..951b3f1e4b4f1 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
 obj-$(CONFIG_PINCTRL_SUN55I_A523)	+= pinctrl-sun55i-a523.o
+obj-$(CONFIG_PINCTRL_SUN55I_A523_R)	+= pinctrl-sun55i-a523-r.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
new file mode 100644
index 0000000000000..69cd2b4ebd7d7
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A523 SoC r-pinctrl driver.
+ *
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const u8 a523_r_nr_bank_pins[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PL  PM */
+	{ 14,  6 };
+
+static const unsigned int a523_r_irq_bank_map[] = { 0, 1 };
+
+static const u8 a523_r_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
+/*	  PL  PM */
+	{ 14, 14 };
+
+static struct sunxi_pinctrl_desc a523_r_pinctrl_data = {
+	.irq_banks = ARRAY_SIZE(a523_r_irq_bank_map),
+	.irq_bank_map = a523_r_irq_bank_map,
+	.irq_read_needs_mux = true,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.pin_base = PL_BASE,
+};
+
+static int a523_r_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_dt_table_init(pdev, a523_r_nr_bank_pins,
+					   a523_r_irq_bank_muxes,
+					   &a523_r_pinctrl_data,
+					   SUNXI_PINCTRL_NEW_REG_LAYOUT);
+}
+
+static const struct of_device_id a523_r_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun55i-a523-r-pinctrl", },
+	{}
+};
+
+static struct platform_driver a523_r_pinctrl_driver = {
+	.probe	= a523_r_pinctrl_probe,
+	.driver	= {
+		.name		= "sun55i-a523-r-pinctrl",
+		.of_match_table	= a523_r_pinctrl_match,
+	},
+};
+builtin_platform_driver(a523_r_pinctrl_driver);
-- 
2.46.3



From dingwei at marvell.com  Thu Mar  6 16:03:13 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Fri, 7 Mar 2025 00:03:13 +0000
Subject: [PATCH v3 1/3] dt-bindings: reset: Add Armada8K reset controller
In-Reply-To: <d2929546-27de-4893-a611-dd4a3bca1a64@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-2-dingwei@marvell.com>
 <174068786548.161165.4348563654300627455.robh@kernel.org>
 <BY3PR18MB467346EB1FA7CEF0A3300350A7CD2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <d2929546-27de-4893-a611-dd4a3bca1a64@kernel.org>
Message-ID: <BY3PR18MB46734A2425361D8BE83E4282A7D52@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Thursday, February 27, 2025 10:53 PM
> To: Wilson Ding <dingwei at marvell.com>; Rob Herring (Arm)
> <robh at kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org; Sanghoon Lee <salee at marvell.com>;
> conor+dt at kernel.org; linux-kernel at vger.kernel.org;
> gregory.clement at bootlin.com; p.zabel at pengutronix.de; Geethasowjanya
> Akula <gakula at marvell.com>; devicetree at vger.kernel.org; andrew at lunn.ch;
> krzk+dt at kernel.org; sebastian.hesselbarth at gmail.com
> Subject: Re: [EXTERNAL] Re: [PATCH v3 1/3] dt-bindings: reset: Add
> Armada8K reset controller
> 
> On 27/02/2025 22:58, Wilson Ding wrote:
> >>
> >> dtschema/dtc warnings/errors:
> >> /builds/robherring/dt-review-
> >> ci/linux/Documentation/devicetree/bindings/reset/marvell,armada8k-
> >> reset.example.dtb: system-controller at 440000: compatible: ['syscon',
> >> 'simple- mfd'] is too short
> >> 	from schema $id: https://urldefense.proofpoint.com/v2/url?u=http-
> >> <https://urldefense.proofpoint.com/v2/url?u=http-  >>>
> >> 3A__devicetree.org_schemas_mfd_syscon-2Dcommon.yaml-
> >>
> 23&d=DwIDaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=sXDQZu4GyqNVDlFUXakS
> >> GJl0Dh81ZIPlU26YS4KHGIA&m=xw0M--
> >>
> 2th9TCt05M0q_c8C0jvg1t4qbuXx9_d3WgCc0HOBpg5_f5E6TjXP_xdcrU&s=3
> >> Gdm4ABV10PnYEpAvJXrV9x-TsfBAHIp5KCn60ohngM&e=
> >>
> >> doc reference errors (make refcheckdocs):
> >>
> >> See https://urldefense.proofpoint.com/v2/url?u=https-
> >> <https://urldefense.proofpoint.com/v2/url?u=https-  >>>
> >> 3A__patchwork.ozlabs.org_project_devicetree-
> >> 2Dbindings_patch_20250227192536.2426490-2D2-2Ddingwei-
> >>
> 40marvell.com&d=DwIDaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=sXDQZu4GyqN
> >> VDlFUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=xw0M--
> >>
> 2th9TCt05M0q_c8C0jvg1t4qbuXx9_d3WgCc0HOBpg5_f5E6TjXP_xdcrU&s=
> >> WJznALBWhejS9hq88jCvZqevaNdN_5-meKfowRfl-bA&e=
> >>
> >> The base for the series is generally the latest rc1. A different
> >> dependency should be noted in *this* patch.
> >>
> >> If you already ran 'make dt_binding_check' and didn't see the above
> >> error(s), then make sure 'yamllint' is installed and dt-schema is up
> >> to
> >> date:
> >>
> >> pip3 install dtschema --upgrade
> >>
> >> Please check and re-submit after running the above command yourself.
> >> Note that DT_SCHEMA_FILES can be set to your schema file to speed up
> >> checking your schema. However, it must be unset to test all examples
> >> with your schema.
> >
> > I cannot reproduce the above error with the latest 'yamllint' and 'dt-schema'.
> >
> > $ pip3 install dtschema --upgrade
> > Requirement already satisfied: dtschema in
> > /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> package
> > s (2025.2) Requirement already satisfied: ruamel.yaml>0.15.69 in
> > /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> package
> > s (from dtschema) (0.18.10) Requirement already satisfied:
> > jsonschema<4.18,>=4.1.2 in
> > /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> package
> > s (from dtschema) (4.17.3) Requirement already satisfied: rfc3987 in
> > /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> package
> > s (from dtschema) (1.3.8) Requirement already satisfied: pylibfdt in
> > /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> package
> > s (from dtschema) (1.7.2) Requirement already satisfied: attrs>=17.4.0
> > in /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (from jsonschema<4.18,>=4.1.2->dtschema) (25.1.0) Requirement
> already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in
> /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (from jsonschema<4.18,>=4.1.2->dtschema) (0.20.0) Requirement
> already satisfied: ruamel.yaml.clib>=0.2.7 in
> /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (from ruamel.yaml>0.15.69->dtschema) (0.2.12) $ pip3 install
> yamllint Requirement already satisfied: yamllint in
> /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (1.35.1) Requirement already satisfied: pathspec>=0.5.3 in
> /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (from yamllint) (0.12.1) Requirement already satisfied: pyyaml in
> /home/wilson/workspace/repos/external/venv/lib/python3.12/site-
> packages (from yamllint) (6.0.2) $ make dt_binding_check
> >   SCHEMA  Documentation/devicetree/bindings/processed-schema.json
> >   CHKDT   ./Documentation/devicetree/bindings
> >   LINT    ./Documentation/devicetree/bindings
> >   DTEX    Documentation/devicetree/bindings/reset/marvell,armada8k-
> reset.example.dts
> >   DTC [C]
> > Documentation/devicetree/bindings/reset/marvell,armada8k-reset.example
> > .dtb
> >
> 
> That's a bit odd but anyway warning is correct: you cannot have such
> compatibles alone.

I understand I need to add one compatible here to resolve the
warning. However, as we agreed, we keep the sud-nodes while
there will be no new compatibles in parent node. So how shall
I avoid this warning?

If we do want to add a compatible in parent node, what should
be used for the compatible name? I think the most suitable name
would be something like "marvell,cp110-system-controller0".
However, it was already taken for in Armada clock controller to
be compatible for legacy dt.

https://lore.kernel.org/all/bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-series.gregory.clement at free-electrons.com/

This is something about 8 years ago. I wonder if we do need to
have the backward compatibility for the field devices at that
time. Can we drop it now?

    syscon0: system-controller at 440000 {
        compatible = "marvell,cp110-system-controller0",
                                "syscon", "simple-mfd";
        reg = <0x440000 0x2000>;
        #address-cells = <1>;
        #size-cells = <1>;

        swrst: reset-controller at 268 {
            compatible = "marvell,armada8k-reset";
            reg = <0x268 0x4>;
            #reset-cells = <1>;
        };
    };

> 
> Best regards,
> Krzysztof

From andre.przywara at arm.com  Thu Mar  6 16:18:03 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 7 Mar 2025 00:18:03 +0000
Subject: [PATCH v3 03/15] clk: sunxi-ng: Add support for update bit
In-Reply-To: <3616088.iIbC2pHGDl@jernej-laptop>
References: <20250304012805.28594-1-andre.przywara@arm.com>
	<20250304012805.28594-4-andre.przywara@arm.com>
	<3616088.iIbC2pHGDl@jernej-laptop>
Message-ID: <20250307001803.2e4887d7@minigeek.lan>

On Tue, 04 Mar 2025 16:28:48 +0100
Jernej ?krabec <jernej.skrabec at gmail.com> wrote:

Hi,

> Dne torek, 4. marec 2025 ob 02:27:53 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> > Some clocks in the Allwinner A523 SoC contain an "update bit" (bit 27),
> > which must be set to apply any register changes, namely the mux
> > selector, the divider and the gate bit.
> > 
> > Add a new CCU feature bit to mark those clocks, and set bit 27 whenever
> > we are applying any changes.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> >  drivers/clk/sunxi-ng/ccu_common.h | 4 ++++
> >  drivers/clk/sunxi-ng/ccu_div.c    | 2 ++
> >  drivers/clk/sunxi-ng/ccu_gate.c   | 4 ++++
> >  drivers/clk/sunxi-ng/ccu_mux.c    | 2 ++
> >  4 files changed, 12 insertions(+)
> > 
> > diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
> > index 50fd268329671..d41d33bdff470 100644
> > --- a/drivers/clk/sunxi-ng/ccu_common.h
> > +++ b/drivers/clk/sunxi-ng/ccu_common.h
> > @@ -20,10 +20,14 @@
> >  #define CCU_FEATURE_KEY_FIELD		BIT(8)
> >  #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
> >  #define CCU_FEATURE_DUAL_DIV		BIT(10)
> > +#define CCU_FEATURE_UPDATE_BIT27	BIT(11)  
> 
> There is no reason to have "BIT27" in the name of the macro. This is similar
> to KEY_FIELD, which is generic name and doesn't specify either key or position
> of this key field. Maybe just CCU_FEATURE_UPDATE_BIT or something equaly
> generic.

Sure, done. This was mostly in anticipation of the typical Allwinner
behaviour of introducing another update bit at a different location in
the future. But I guess we use a bitmask should that happen.

> With that fixed:
> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Many thanks!

Cheers,
Andre

> 
> Best regards,
> Jernej
> 
> >  
> >  /* MMC timing mode switch bit */
> >  #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
> >  
> > +/* Some clocks need this bit to actually apply register changes */
> > +#define CCU_SUNXI_UPDATE_BIT		BIT(27)
> > +
> >  struct device_node;
> >  
> >  struct ccu_common {
> > diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
> > index 7f4691f09e01f..2d8b98fe4b13a 100644
> > --- a/drivers/clk/sunxi-ng/ccu_div.c
> > +++ b/drivers/clk/sunxi-ng/ccu_div.c
> > @@ -106,6 +106,8 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
> >  
> >  	reg = readl(cd->common.base + cd->common.reg);
> >  	reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
> > +	if (cd->common.features & CCU_FEATURE_UPDATE_BIT27)
> > +		reg |= CCU_SUNXI_UPDATE_BIT;
> >  
> >  	writel(reg | (val << cd->div.shift),
> >  	       cd->common.base + cd->common.reg);
> > diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
> > index ac52fd6bff677..0490f95781361 100644
> > --- a/drivers/clk/sunxi-ng/ccu_gate.c
> > +++ b/drivers/clk/sunxi-ng/ccu_gate.c
> > @@ -20,6 +20,8 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
> >  	spin_lock_irqsave(common->lock, flags);
> >  
> >  	reg = readl(common->base + common->reg);
> > +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> > +		reg |= CCU_SUNXI_UPDATE_BIT;
> >  	writel(reg & ~gate, common->base + common->reg);
> >  
> >  	spin_unlock_irqrestore(common->lock, flags);
> > @@ -44,6 +46,8 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
> >  	spin_lock_irqsave(common->lock, flags);
> >  
> >  	reg = readl(common->base + common->reg);
> > +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> > +		reg |= CCU_SUNXI_UPDATE_BIT;
> >  	writel(reg | gate, common->base + common->reg);
> >  
> >  	spin_unlock_irqrestore(common->lock, flags);
> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> > index d7ffbdeee9e04..82ee21e0d3a68 100644
> > --- a/drivers/clk/sunxi-ng/ccu_mux.c
> > +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> > @@ -197,6 +197,8 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
> >  	/* The key field always reads as zero. */
> >  	if (common->features & CCU_FEATURE_KEY_FIELD)
> >  		reg |= CCU_MUX_KEY_VALUE;
> > +	if (common->features & CCU_FEATURE_UPDATE_BIT27)
> > +		reg |= CCU_SUNXI_UPDATE_BIT;
> >  
> >  	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
> >  	writel(reg | (index << cm->shift), common->base + common->reg);
> >   
> 
> 
> 
> 
> 



From inochiama at gmail.com  Thu Mar  6 17:12:33 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri, 7 Mar 2025 09:12:33 +0800
Subject: [PATCH net-next v6 0/4] riscv: sophgo: Add ethernet support for
 SG2044
In-Reply-To: <20250306165931.7ffefe3a@kernel.org>
References: <20250305063920.803601-1-inochiama@gmail.com>
 <20250306165931.7ffefe3a@kernel.org>
Message-ID: <ptq4ujomkffgpizhikejfjjbjcg44vyzw4pwbs7kureqqndy6e@alxgdc3qkm7q>

On Thu, Mar 06, 2025 at 04:59:31PM -0800, Jakub Kicinski wrote:
> On Wed,  5 Mar 2025 14:39:12 +0800 Inochi Amaoto wrote:
> > The ethernet controller of SG2044 is Synopsys DesignWare IP with
> > custom clock. Add glue layer for it.
> 
> Looks like we have a conflict on the binding, could you rebase
> against latest net-next/main and repost?
> -- 
> pw-bot: cr

Yeah, I see a auto merge when cherry-pick here. I will send a
new version for it.

Regards,
Inochi


From cki-project at redhat.com  Thu Mar  6 17:13:03 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 01:13:03 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <52751.125030620130501046@us-mta-608.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704010058

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704010058-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From namhyung at kernel.org  Thu Mar  6 17:14:48 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 6 Mar 2025 17:14:48 -0800
Subject: [PATCH v4 02/11] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250304050305.901167-3-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
 <20250304050305.901167-3-irogers@google.com>
Message-ID: <Z8pIiM2Z_jtNNUhN@google.com>

On Mon, Mar 03, 2025 at 09:02:56PM -0800, Ian Rogers wrote:
> There are many and non-obvious meanings to the dso_binary_type enum
> values. Add kernel-doc to speed interpretting their meanings.
> 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/util/dso.h | 53 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index dfd763a0bd9d..f3ca2a5e7670 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -20,30 +20,83 @@ struct perf_env;
>  #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
>  #define DSO__NAME_KCORE		"[kernel.kcore]"
>  
> +/**
> + * enum dso_binary_type - The kind of DSO generally associated with a memory
> + *                        region (struct map).
> + */

Thanks for adding these comments!


>  enum dso_binary_type {
> +	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
>  	DSO_BINARY_TYPE__KALLSYMS = 0,
> +	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
>  	DSO_BINARY_TYPE__GUEST_KALLSYMS,
> +	/** @DSO_BINARY_TYPE__VMLINUX: Path to guest kernel /boot/vmlinux file. */
>  	DSO_BINARY_TYPE__VMLINUX,

It's not for guest.  Also I think the vmlinux file can come from
different places.


> +	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to kernel /boot/vmlinux file. */
>  	DSO_BINARY_TYPE__GUEST_VMLINUX,

This is for guest. :)

Thanks,
Namhyung


> +	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
>  	DSO_BINARY_TYPE__JAVA_JIT,
> +	/**
> +	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
> +	 * in the .gnu_debuglink ELF section of the dso.
> +	 */
>  	DSO_BINARY_TYPE__DEBUGLINK,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
> +	 * the buildid cache with an elf filename.
> +	 */
>  	DSO_BINARY_TYPE__BUILD_ID_CACHE,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
> +	 * located in the buildid cache with a debug filename.
> +	 */
>  	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
> +	 * with .debug suffix.
> +	 */
>  	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
>  	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
> +	 * file in /usr/lib/debug/lib rather than the expected
> +	 * /usr/lib/debug/usr/lib.
> +	 */
>  	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
> +	/**
> +	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
> +	 * in /usr/lib/debug/.build-id/.
> +	 */
>  	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
> +	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
>  	DSO_BINARY_TYPE__GUEST_KMODULE,
> +	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
>  	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
> +	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
>  	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
> +	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
>  	DSO_BINARY_TYPE__KCORE,
> +	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
>  	DSO_BINARY_TYPE__GUEST_KCORE,
> +	/**
> +	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
> +	 * package debug info.
> +	 */
>  	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> +	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
>  	DSO_BINARY_TYPE__BPF_PROG_INFO,
> +	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
>  	DSO_BINARY_TYPE__BPF_IMAGE,
> +	/**
> +	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
> +	 * instructions or optimized kprobes or ftrace trampolines.
> +	 */
>  	DSO_BINARY_TYPE__OOL,
> +	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
>  	DSO_BINARY_TYPE__NOT_FOUND,
>  };
>  
> -- 
> 2.48.1.711.g2feabab25a-goog
> 


From sfr at canb.auug.org.au  Thu Mar  6 17:15:12 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Fri, 7 Mar 2025 12:15:12 +1100
Subject: linux-next: duplicate patch in the tegra tree
Message-ID: <20250307121512.5735349a@canb.auug.org.au>

Hi all,

The following commit is also in the arm-soc tree as a different commit
(but the same patch):

  90a1dc90d08b ("arm64: tegra: Remove unused and undocumented "regulator-ramp-delay-scale" property")

This is commit

  828678a1f638 ("arm64: dts: nvidia: Remove unused and undocumented "regulator-ramp-delay-scale" property")

in the arm-soc tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/c7f720c7/attachment.sig>

From inochiama at gmail.com  Thu Mar  6 17:16:13 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri,  7 Mar 2025 09:16:13 +0800
Subject: [PATCH net-next v7 0/4] riscv: sophgo: Add ethernet support for SG2044
Message-ID: <20250307011623.440792-1-inochiama@gmail.com>

The ethernet controller of SG2044 is Synopsys DesignWare IP with
custom clock. Add glue layer for it.

Changed from v6:
- https://lore.kernel.org/netdev/20250305063920.803601-1-inochiama at gmail.com/
1. rebase against latest net-next/main

Changed from v5:
- https://lore.kernel.org/netdev/20250216123953.1252523-1-inochiama at gmail.com/
1. apply Andrew's tag for patch 2,3
3. patch 1: add dma-noncoherent property.
2. patch 2,3: separate original patch into 2 part
4. patch 4: adopt new stmmac_set_clk_tx_rate helper function

Changed from v4:
- https://lore.kernel.org/netdev/20250209013054.816580-1-inochiama at gmail.com/
1. apply Romain's tag
2. patch 3: use device variable to replace &pdev->dev.
3. patch 3: remove unused include.
4. patch 3: make error message more useful.

Changed from v3:
- https://lore.kernel.org/netdev/20241223005843.483805-1-inochiama at gmail.com/
1. rebase for 6.14.rc1
2. remove the dependency requirement as it was already merged
   into master.

Changed from RFC:
- https://lore.kernel.org/netdev/20241101014327.513732-1-inochiama at gmail.com/
1. patch 1: apply Krzysztof' tag

Changed from v2:
- https://lore.kernel.org/netdev/20241025011000.244350-1-inochiama at gmail.com/
1. patch 1: merge the first and the second bindings patch to show the all
            compatible change.
2. patch 2: use of_device_compatible_match helper function to perform check.
2. patch 3: remove unused include and sort the left.
3. patch 3: fix wrong variable usage in sophgo_dwmac_fix_mac_speed
4. patch 3: drop unused variable in the patch.

Changed from v1:
- https://lore.kernel.org/netdev/20241021103617.653386-1-inochiama at gmail.com/
1. patch 2: remove sophgo,syscon as this mac delay is resolved.
2. patch 2: apply all the properties unconditionally.
3. patch 4: remove sophgo,syscon code as this mac delay is resolved.
4. patch 4: use the helper function to compute rgmii clock.
5. patch 4: use remove instead of remove_new for the platform driver.

Inochi Amaoto (4):
  dt-bindings: net: Add support for Sophgo SG2044 dwmac
  net: stmmac: platform: Group GMAC4 compatible check
  net: stmmac: platform: Add snps,dwmac-5.30a IP compatible string
  net: stmmac: Add glue layer for Sophgo SG2044 SoC

 .../devicetree/bindings/net/snps,dwmac.yaml   |   4 +
 .../bindings/net/sophgo,sg2044-dwmac.yaml     | 126 ++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 ++
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-sophgo.c    |  75 +++++++++++
 .../ethernet/stmicro/stmmac/stmmac_platform.c |  17 ++-
 6 files changed, 229 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c

--
2.48.1



From inochiama at gmail.com  Thu Mar  6 17:16:14 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri,  7 Mar 2025 09:16:14 +0800
Subject: [PATCH net-next v7 1/4] dt-bindings: net: Add support for Sophgo SG2044 dwmac
In-Reply-To: <20250307011623.440792-1-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
Message-ID: <20250307011623.440792-2-inochiama@gmail.com>

The GMAC IP on SG2044 is almost a standard Synopsys DesignWare
MAC (version 5.30a) with some extra clock.

Add necessary compatible string for this device.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../devicetree/bindings/net/snps,dwmac.yaml   |   4 +
 .../bindings/net/sophgo,sg2044-dwmac.yaml     | 126 ++++++++++++++++++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml

diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index c7004eaa8eae..3f0aa46d798e 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -32,6 +32,7 @@ select:
           - snps,dwmac-4.20a
           - snps,dwmac-5.10a
           - snps,dwmac-5.20
+          - snps,dwmac-5.30a
           - snps,dwxgmac
           - snps,dwxgmac-2.10
 
@@ -98,8 +99,10 @@ properties:
         - snps,dwmac-4.20a
         - snps,dwmac-5.10a
         - snps,dwmac-5.20
+        - snps,dwmac-5.30a
         - snps,dwxgmac
         - snps,dwxgmac-2.10
+        - sophgo,sg2044-dwmac
         - starfive,jh7100-dwmac
         - starfive,jh7110-dwmac
         - tesla,fsd-ethqos
@@ -632,6 +635,7 @@ allOf:
                 - snps,dwmac-4.20a
                 - snps,dwmac-5.10a
                 - snps,dwmac-5.20
+                - snps,dwmac-5.30a
                 - snps,dwxgmac
                 - snps,dwxgmac-2.10
                 - st,spear600-gmac
diff --git a/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
new file mode 100644
index 000000000000..4dd2dc9c678b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml
@@ -0,0 +1,126 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/sophgo,sg2044-dwmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo SG2044 DWMAC glue layer
+
+maintainers:
+  - Inochi Amaoto <inochiama at gmail.com>
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - sophgo,sg2044-dwmac
+  required:
+    - compatible
+
+properties:
+  compatible:
+    items:
+      - const: sophgo,sg2044-dwmac
+      - const: snps,dwmac-5.30a
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: GMAC main clock
+      - description: PTP clock
+      - description: TX clock
+
+  clock-names:
+    items:
+      - const: stmmaceth
+      - const: ptp_ref
+      - const: tx
+
+  dma-noncoherent: true
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    const: stmmaceth
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - resets
+  - reset-names
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    ethernet at 30006000 {
+      compatible = "sophgo,sg2044-dwmac", "snps,dwmac-5.30a";
+      reg = <0x30006000 0x4000>;
+      clocks = <&clk 151>, <&clk 152>, <&clk 154>;
+      clock-names = "stmmaceth", "ptp_ref", "tx";
+      interrupt-parent = <&intc>;
+      interrupts = <296 IRQ_TYPE_LEVEL_HIGH>;
+      interrupt-names = "macirq";
+      resets = <&rst 30>;
+      reset-names = "stmmaceth";
+      snps,multicast-filter-bins = <0>;
+      snps,perfect-filter-entries = <1>;
+      snps,aal;
+      snps,tso;
+      snps,txpbl = <32>;
+      snps,rxpbl = <32>;
+      snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
+      snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
+      snps,axi-config = <&gmac0_stmmac_axi_setup>;
+      status = "disabled";
+
+      gmac0_mtl_rx_setup: rx-queues-config {
+        snps,rx-queues-to-use = <8>;
+        snps,rx-sched-wsp;
+        queue0 {};
+        queue1 {};
+        queue2 {};
+        queue3 {};
+        queue4 {};
+        queue5 {};
+        queue6 {};
+        queue7 {};
+      };
+
+      gmac0_mtl_tx_setup: tx-queues-config {
+        snps,tx-queues-to-use = <8>;
+        queue0 {};
+        queue1 {};
+        queue2 {};
+        queue3 {};
+        queue4 {};
+        queue5 {};
+        queue6 {};
+        queue7 {};
+      };
+
+      gmac0_stmmac_axi_setup: stmmac-axi-config {
+        snps,blen = <16 8 4 0 0 0 0>;
+        snps,wr_osr_lmt = <1>;
+        snps,rd_osr_lmt = <2>;
+      };
+    };
-- 
2.48.1



From inochiama at gmail.com  Thu Mar  6 17:16:15 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri,  7 Mar 2025 09:16:15 +0800
Subject: [PATCH net-next v7 2/4] net: stmmac: platform: Group GMAC4 compatible check
In-Reply-To: <20250307011623.440792-1-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
Message-ID: <20250307011623.440792-3-inochiama@gmail.com>

Use of_device_compatible_match to group existing compatible
check of GMAC4 device.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
---
 .../ethernet/stmicro/stmmac/stmmac_platform.c    | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index d0e61aa1a495..4a3fe44b780d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -405,6 +405,16 @@ static int stmmac_of_get_mac_mode(struct device_node *np)
 	return -ENODEV;
 }
 
+/* Compatible string array for all gmac4 devices */
+static const char * const stmmac_gmac4_compats[] = {
+	"snps,dwmac-4.00",
+	"snps,dwmac-4.10a",
+	"snps,dwmac-4.20a",
+	"snps,dwmac-5.10a",
+	"snps,dwmac-5.20",
+	NULL
+};
+
 /**
  * stmmac_probe_config_dt - parse device-tree driver parameters
  * @pdev: platform_device structure
@@ -538,11 +548,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
 		plat->pmt = 1;
 	}
 
-	if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
-	    of_device_is_compatible(np, "snps,dwmac-4.10a") ||
-	    of_device_is_compatible(np, "snps,dwmac-4.20a") ||
-	    of_device_is_compatible(np, "snps,dwmac-5.10a") ||
-	    of_device_is_compatible(np, "snps,dwmac-5.20")) {
+	if (of_device_compatible_match(np, stmmac_gmac4_compats)) {
 		plat->has_gmac4 = 1;
 		plat->has_gmac = 0;
 		plat->pmt = 1;
-- 
2.48.1



From inochiama at gmail.com  Thu Mar  6 17:16:16 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri,  7 Mar 2025 09:16:16 +0800
Subject: [PATCH net-next v7 3/4] net: stmmac: platform: Add snps,dwmac-5.30a IP compatible string
In-Reply-To: <20250307011623.440792-1-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
Message-ID: <20250307011623.440792-4-inochiama@gmail.com>

Add "snps,dwmac-5.30a" compatible string for 5.30a version that can avoid
to define some platform data in the glue layer.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 4a3fe44b780d..8dc3bd6946c6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -412,6 +412,7 @@ static const char * const stmmac_gmac4_compats[] = {
 	"snps,dwmac-4.20a",
 	"snps,dwmac-5.10a",
 	"snps,dwmac-5.20",
+	"snps,dwmac-5.30a",
 	NULL
 };
 
-- 
2.48.1



From inochiama at gmail.com  Thu Mar  6 17:16:17 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri,  7 Mar 2025 09:16:17 +0800
Subject: [PATCH net-next v7 4/4] net: stmmac: Add glue layer for Sophgo SG2044 SoC
In-Reply-To: <20250307011623.440792-1-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
Message-ID: <20250307011623.440792-5-inochiama@gmail.com>

Adds Sophgo dwmac driver support on the Sophgo SG2044 SoC.

Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   | 11 +++
 drivers/net/ethernet/stmicro/stmmac/Makefile  |  1 +
 .../ethernet/stmicro/stmmac/dwmac-sophgo.c    | 75 +++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index c5f94a67b3f2..3c820ef56775 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -181,6 +181,17 @@ config DWMAC_SOCFPGA
 	  for the stmmac device driver. This driver is used for
 	  arria5 and cyclone5 FPGA SoCs.
 
+config DWMAC_SOPHGO
+	tristate "Sophgo dwmac support"
+	depends on OF && (ARCH_SOPHGO || COMPILE_TEST)
+	default m if ARCH_SOPHGO
+	help
+	  Support for ethernet controllers on Sophgo RISC-V SoCs
+
+	  This selects the Sophgo SoC specific glue layer support
+	  for the stmmac device driver. This driver is used for the
+	  ethernet controllers on various Sophgo SoCs.
+
 config DWMAC_STARFIVE
 	tristate "StarFive dwmac support"
 	depends on OF && (ARCH_STARFIVE || COMPILE_TEST)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index b26f0e79c2b3..594883fb4164 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_RZN1)	+= dwmac-rzn1.o
 obj-$(CONFIG_DWMAC_S32)		+= dwmac-s32.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
+obj-$(CONFIG_DWMAC_SOPHGO)	+= dwmac-sophgo.o
 obj-$(CONFIG_DWMAC_STARFIVE)	+= dwmac-starfive.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
 obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c
new file mode 100644
index 000000000000..3303784cbbf8
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sophgo.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sophgo DWMAC platform driver
+ *
+ * Copyright (C) 2024 Inochi Amaoto <inochiama at gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+
+#include "stmmac_platform.h"
+
+static int sophgo_sg2044_dwmac_init(struct platform_device *pdev,
+				    struct plat_stmmacenet_data *plat_dat,
+				    struct stmmac_resources *stmmac_res)
+{
+	plat_dat->clk_tx_i = devm_clk_get_enabled(&pdev->dev, "tx");
+	if (IS_ERR(plat_dat->clk_tx_i))
+		return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat->clk_tx_i),
+				     "failed to get tx clock\n");
+
+	plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE;
+	plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
+	plat_dat->multicast_filter_bins = 0;
+	plat_dat->unicast_filter_entries = 1;
+
+	return 0;
+}
+
+static int sophgo_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to get platform resources\n");
+
+	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return dev_err_probe(dev, PTR_ERR(plat_dat),
+				     "failed to parse DT parameters\n");
+
+	ret = sophgo_sg2044_dwmac_init(pdev, plat_dat, &stmmac_res);
+	if (ret)
+		return ret;
+
+	return stmmac_dvr_probe(dev, plat_dat, &stmmac_res);
+}
+
+static const struct of_device_id sophgo_dwmac_match[] = {
+	{ .compatible = "sophgo,sg2044-dwmac" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sophgo_dwmac_match);
+
+static struct platform_driver sophgo_dwmac_driver = {
+	.probe  = sophgo_dwmac_probe,
+	.remove = stmmac_pltfr_remove,
+	.driver = {
+		.name = "sophgo-dwmac",
+		.pm = &stmmac_pltfr_pm_ops,
+		.of_match_table = sophgo_dwmac_match,
+	},
+};
+module_platform_driver(sophgo_dwmac_driver);
+
+MODULE_AUTHOR("Inochi Amaoto <inochiama at gmail.com>");
+MODULE_DESCRIPTION("Sophgo DWMAC platform driver");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From inochiama at gmail.com  Thu Mar  6 17:20:00 2025
From: inochiama at gmail.com (Inochi Amaoto)
Date: Fri, 7 Mar 2025 09:20:00 +0800
Subject: [PATCH net-next v6 0/4] riscv: sophgo: Add ethernet support for
 SG2044
In-Reply-To: <ptq4ujomkffgpizhikejfjjbjcg44vyzw4pwbs7kureqqndy6e@alxgdc3qkm7q>
References: <20250305063920.803601-1-inochiama@gmail.com>
 <20250306165931.7ffefe3a@kernel.org>
 <ptq4ujomkffgpizhikejfjjbjcg44vyzw4pwbs7kureqqndy6e@alxgdc3qkm7q>
Message-ID: <w7p3jnevmwumcblrkbpot7wpvajgf6enwpl4db5rbme4322hej@mxm54kytlguy>

On Fri, Mar 07, 2025 at 09:12:33AM +0800, Inochi Amaoto wrote:
> On Thu, Mar 06, 2025 at 04:59:31PM -0800, Jakub Kicinski wrote:
> > On Wed,  5 Mar 2025 14:39:12 +0800 Inochi Amaoto wrote:
> > > The ethernet controller of SG2044 is Synopsys DesignWare IP with
> > > custom clock. Add glue layer for it.
> > 
> > Looks like we have a conflict on the binding, could you rebase
> > against latest net-next/main and repost?
> > -- 
> > pw-bot: cr
> 
> Yeah, I see a auto merge when cherry-pick here. I will send a
> new version for it.
> 

Here is the new version:
https://lore.kernel.org/netdev/20250307011623.440792-1-inochiama at gmail.com/

Regards,
Inochi


From andre.przywara at arm.com  Thu Mar  6 16:26:14 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:14 +0000
Subject: [PATCH v4 00/14] clk: sunxi-ng: add A523 clock support
Message-ID: <20250307002628.10684-1-andre.przywara@arm.com>

Hi,

this is the fourth drop of the series introducing basic clock support for
the Allwinner A523 family of SoCs, comprising A523, A527, T527, H728. [1]
This times just a small rename of a macro name, and fixing the DT
binding, where the separate patches for the two CCUs got merged into
one. For a more detailed changelog, see below.

*************
Please note that the clock numbers changed compared to v1 and v2, (but
not against v3) so DTs from that older era cannot be used anymore with
this driver: you have to update the DTB. Just copying the binding header
and recompiling the DTB should do the trick, since the symbols stayed
mostly the same, at least as far they are used in the basic DTs we use
today.
*************

The SoCs contain *four* CCU components, aside from the usual main clock
device and the PRCM clock (in the always-on-domain), there is an MCU
clock and a CPU clock. This series just adds support for the first two,
the other two don't seem to be required for the basic functionality.

The clock tree of each SoC has always been individual, even though the
main clock *types* mostly remain the same. This time we see three slight
variations: There is an MP clock without the P (shift) part, there is one
with two dividers instead of one divider and one shift field, and certain
clocks require an "update" bit to be set to apply any changes.
The first three patches add support for these new clock types.

Patch 04 adds the DT binding description for the two CCUs, along with all
the clock numbers already defined in the binding headers.
Since the main CCU is massive, and contains a lot of detail, I decided
to split this driver up into 9 patches, simply to help review. I tried
to group them somewhat logically, although this is rather arbitrary, and
just to make each individual patch smaller. I am happy to squash them
all back into one patch once they have been reviewed, for the final
merge. The PRCM CCU is comparably small, so I kept this in one patch.

Interestingly the Allwinner BSP has switched to using the existing sunxi
CCU framework for modelling the clocks (they had their own way before), so
we could theoretically use their code. However when I started working on
this more than a year ago, their files had a GPL-3.0-only license header,
which, according to my research, makes them incompatible for mainline
inclusion. I thus started from "scratch" (adjusting the D1 driver, really).
Meanwhile they seem to have changed the license, and a quick comparison
turned up some differences, some of which seem to be bugs on their, some
on my side, probably. I hope having such a "reference" helps the mainline
code quality, as people can help the review by comparing code.

Given the level of detail required in CCU drivers, I am certain there are
still some bugs in there, also many things that can be improved. But after
starring and editing this for weeks, I feel like it's time for the
community to have a look, so please help with the review, and also test.

Based on v6.14-rc1.

Cheers,
Andre

[1] https://linux-sunxi.org/A523#Family_of_sun55iw3

Changelog v3 .. v4:
- rename new update bit flag to just CCU_FEATURE_UPDATE_BIT
- merge the two DT binding patches into one
- describe each CCU in its own "if" clause in the DT binding
- fix DT example in DT binding
- add one tag

Changelog v2 .. v3:
- rename PLL_DDR0 to PLL_DDR
- move bogus macro definition from PLL patch to an earlier patch
- adding CLK_SET_RATE_PARENT flags where needed (GPU, eDP, ...)
- remove CLK_SET_RATE_PARENT from clocks with only fixed parents
- add support for clocks with the "update" bit (BIT(27))
- flags IOMMU, MBUS and DRAM clocks as needing "update" bit
- remove leftover comment about missing mux
- fix TCON_TV parent list
- add TCON_LCD2 clock
- export PLL_GPU
- describe MBUS clock properly (was copy&pasted wrongly from D1)
- change MMC clocks to use better macro
- mark SPI and CSI clocks as being dual-divider clocks
- fix wrong DSP parent clock (480 instead of 400 MHz)
- properly implement fanout clocks (describe both dividers)
- fix MBUS gate clocks and add two new ones
- rename dpss clock to display0 and add display1 clocks
- drop non-existing bus_dsp_cfg_clk
- mark r_timer clocks as having no divider
- fix r_pwm mux width
- move DT bindings into separate yaml file
- describe different source clock sets correctly
- add review tags
- remove Chen-Yu's and Conor's tags from changed patches

Changelog v1 .. v2:
- rebase onto v6.14-rc1
- split main CCU definition patch into 9 smaller patches
- rename RST_BUS_VO1_TCONLCD0 to RST_BUS_TCON_LCD2
- insert CLK_PLL_VIDEO3_xx clocks
- add clock for 2nd EMAC
- fix ISP clock definition
- remove BSP comments from clocks now documented in the T527 manual
- add Conor's binding ACKs (with thanks!)

Andre Przywara (14):
  clk: sunxi-ng: mp: introduce dual-divider clock
  clk: sunxi-ng: mp: provide wrappers for setting feature flags
  clk: sunxi-ng: Add support for update bit
  dt-bindings: clk: sunxi-ng: document two Allwinner A523 CCUs
  clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
  clk: sunxi-ng: a523: Add support for bus clocks
  clk: sunxi-ng: a523: add video mod clocks
  clk: sunxi-ng: a523: add system mod clocks
  clk: sunxi-ng: a523: add interface mod clocks
  clk: sunxi-ng: a523: add USB mod clocks
  clk: sunxi-ng: a523: remaining mod clocks
  clk: sunxi-ng: a523: add bus clock gates
  clk: sunxi-ng: a523: add reset lines
  clk: sunxi-ng: add support for the A523/T527 PRCM CCU

 .../clock/allwinner,sun55i-a523-ccu.yaml      |  103 +
 drivers/clk/sunxi-ng/Kconfig                  |   10 +
 drivers/clk/sunxi-ng/Makefile                 |    4 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c      |  248 +++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h      |   14 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c        | 1685 +++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523.h        |   14 +
 drivers/clk/sunxi-ng/ccu_common.h             |    5 +
 drivers/clk/sunxi-ng/ccu_div.c                |    2 +
 drivers/clk/sunxi-ng/ccu_gate.c               |    4 +
 drivers/clk/sunxi-ng/ccu_mp.c                 |   51 +-
 drivers/clk/sunxi-ng/ccu_mp.h                 |   58 +-
 drivers/clk/sunxi-ng/ccu_mux.c                |    2 +
 include/dt-bindings/clock/sun55i-a523-ccu.h   |  189 ++
 include/dt-bindings/clock/sun55i-a523-r-ccu.h |   37 +
 include/dt-bindings/reset/sun55i-a523-ccu.h   |   88 +
 include/dt-bindings/reset/sun55i-a523-r-ccu.h |   25 +
 17 files changed, 2524 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h

-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:15 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:15 +0000
Subject: [PATCH v4 01/14] clk: sunxi-ng: mp: introduce dual-divider clock
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-2-andre.przywara@arm.com>

The Allwinner A523 SoC introduces some new MP-style mod clock, where the
second "P" divider is an actual numerical divider value, and not the
numbers of bits to shift (1..32 instead of 1,2,4,8).
The rest of the clock is the same as the existing MP clock, so enhance the
existing code to accommodate for this.

Introduce the new CCU feature bit CCU_FEATURE_DUAL_DIV to mark an MP
clock as having two dividers, and change the dividing and encoding code
to differentiate the two cases.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/clk/sunxi-ng/ccu_common.h |  1 +
 drivers/clk/sunxi-ng/ccu_mp.c     | 51 +++++++++++++++++++++++++------
 2 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index dd330426a6e5f..50fd268329671 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -19,6 +19,7 @@
 #define CCU_FEATURE_SIGMA_DELTA_MOD	BIT(7)
 #define CCU_FEATURE_KEY_FIELD		BIT(8)
 #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
+#define CCU_FEATURE_DUAL_DIV		BIT(10)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 2bb8987ddcc20..354c981943b6f 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -10,15 +10,23 @@
 #include "ccu_gate.h"
 #include "ccu_mp.h"
 
+static unsigned int next_div(unsigned int div, bool shift)
+{
+	if (shift)
+		return div << 1;
+	return div + 1;
+}
+
 static unsigned long ccu_mp_find_best(unsigned long parent, unsigned long rate,
 				      unsigned int max_m, unsigned int max_p,
+				      bool shift,
 				      unsigned int *m, unsigned int *p)
 {
 	unsigned long best_rate = 0;
 	unsigned int best_m = 0, best_p = 0;
 	unsigned int _m, _p;
 
-	for (_p = 1; _p <= max_p; _p <<= 1) {
+	for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
 		for (_m = 1; _m <= max_m; _m++) {
 			unsigned long tmp_rate = parent / _p / _m;
 
@@ -43,7 +51,8 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
 						      unsigned long *parent,
 						      unsigned long rate,
 						      unsigned int max_m,
-						      unsigned int max_p)
+						      unsigned int max_p,
+						      bool shift)
 {
 	unsigned long parent_rate_saved;
 	unsigned long parent_rate, now;
@@ -60,7 +69,7 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
 	maxdiv = max_m * max_p;
 	maxdiv = min(ULONG_MAX / rate, maxdiv);
 
-	for (_p = 1; _p <= max_p; _p <<= 1) {
+	for (_p = 1; _p <= max_p; _p = next_div(_p, shift)) {
 		for (_m = 1; _m <= max_m; _m++) {
 			div = _m * _p;
 
@@ -103,18 +112,26 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
 	struct ccu_mp *cmp = data;
 	unsigned int max_m, max_p;
 	unsigned int m, p;
+	bool shift = true;
 
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate *= cmp->fixed_post_div;
 
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		shift = false;
+
 	max_m = cmp->m.max ?: 1 << cmp->m.width;
-	max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	if (shift)
+		max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	else
+		max_p = cmp->p.max ?: 1 << cmp->p.width;
 
 	if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
-		rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
+		rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, shift,
+					&m, &p);
 	} else {
 		rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate,
-							max_m, max_p);
+							max_m, max_p, shift);
 	}
 
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
@@ -167,7 +184,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
 	p = reg >> cmp->p.shift;
 	p &= (1 << cmp->p.width) - 1;
 
-	rate = (parent_rate >> p) / m;
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		rate = (parent_rate / p) / m;
+	else
+		rate = (parent_rate >> p) / m;
+
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate /= cmp->fixed_post_div;
 
@@ -190,20 +211,27 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags;
 	unsigned int max_m, max_p;
 	unsigned int m, p;
+	bool shift = true;
 	u32 reg;
 
+	if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+		shift = false;
+
 	/* Adjust parent_rate according to pre-dividers */
 	parent_rate = ccu_mux_helper_apply_prediv(&cmp->common, &cmp->mux, -1,
 						  parent_rate);
 
 	max_m = cmp->m.max ?: 1 << cmp->m.width;
-	max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	if (shift)
+		max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
+	else
+		max_p = cmp->p.max ?: 1 << cmp->p.width;
 
 	/* Adjust target rate according to post-dividers */
 	if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate = rate * cmp->fixed_post_div;
 
-	ccu_mp_find_best(parent_rate, rate, max_m, max_p, &m, &p);
+	ccu_mp_find_best(parent_rate, rate, max_m, max_p, shift, &m, &p);
 
 	spin_lock_irqsave(cmp->common.lock, flags);
 
@@ -211,7 +239,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
 	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
 	reg |= (m - cmp->m.offset) << cmp->m.shift;
-	reg |= ilog2(p) << cmp->p.shift;
+	if (shift)
+		reg |= ilog2(p) << cmp->p.shift;
+	else
+		reg |= (p - cmp->p.offset) << cmp->p.shift;
 
 	writel(reg, cmp->common.base + cmp->common.reg);
 
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:16 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:16 +0000
Subject: [PATCH v4 02/14] clk: sunxi-ng: mp: provide wrappers for setting feature flags
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-3-andre.przywara@arm.com>

So far our sunxi clock instantiation macros set the required clock
features depending on the clock type, but the new "dual divider MP
clock" requires us to pass that piece of information in by the user.

Add new wrapper macros that allow to specify a "features" field, to
allow marking those dual-divider clocks accordingly. Also add two
convenience macros that deal with the most common cases.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu_mp.h | 58 ++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index 6e50f3728fb5f..b35aeec70484d 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -82,11 +82,35 @@ struct ccu_mp {
 				   _muxshift, _muxwidth,		\
 				   0, _flags)
 
-#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
-					_mshift, _mwidth,		\
-					_pshift, _pwidth,		\
-					_muxshift, _muxwidth,		\
-					_gate, _flags)			\
+#define SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(_struct, _name, _parents, _reg, \
+					      _mshift, _mwidth,		\
+					      _pshift, _pwidth,		\
+					      _muxshift, _muxwidth,	\
+					      _gate, _postdiv,		\
+					      _flags)			\
+	struct ccu_mp _struct = {					\
+		.enable	= _gate,					\
+		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
+		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
+		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
+		.fixed_post_div = _postdiv,				\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_FIXED_POSTDIV |	\
+						CCU_FEATURE_DUAL_DIV,	\
+			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
+								   _parents, \
+								   &ccu_mp_ops, \
+								   _flags), \
+		}							\
+	}
+
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
+					     _mshift, _mwidth,		\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _features,		\
+					     _flags)			\
 	struct ccu_mp _struct = {					\
 		.enable	= _gate,					\
 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
@@ -94,6 +118,7 @@ struct ccu_mp {
 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
 		.common	= {						\
 			.reg		= _reg,				\
+			.features	= _features,			\
 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
 								   _parents, \
 								   &ccu_mp_ops, \
@@ -101,6 +126,29 @@ struct ccu_mp {
 		}							\
 	}
 
+#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+					_mshift, _mwidth,		\
+					_pshift, _pwidth,		\
+					_muxshift, _muxwidth,		\
+					_gate, _flags)			\
+	SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents,	\
+					     _reg, _mshift, _mwidth,	\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _flags, 0)
+
+#define SUNXI_CCU_DUALDIV_MUX_GATE(_struct, _name, _parents, _reg,	\
+				   _mshift, _mwidth,			\
+				   _pshift, _pwidth,			\
+				   _muxshift, _muxwidth,		\
+				   _gate, _flags)			\
+	SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents,	\
+					     _reg, _mshift, _mwidth,	\
+					     _pshift, _pwidth,		\
+					     _muxshift, _muxwidth,	\
+					     _gate, _flags,		\
+					     CCU_FEATURE_DUAL_DIV)
+
 #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg,	\
 				   _mshift, _mwidth,			\
 				   _pshift, _pwidth,			\
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:17 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:17 +0000
Subject: [PATCH v4 03/14] clk: sunxi-ng: Add support for update bit
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-4-andre.przywara@arm.com>

Some clocks in the Allwinner A523 SoC contain an "update bit" (bit 27),
which must be set to apply any register changes, namely the mux
selector, the divider and the gate bit.

Add a new CCU feature bit to mark those clocks, and set bit 27 whenever
we are applying any changes.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/clk/sunxi-ng/ccu_common.h | 4 ++++
 drivers/clk/sunxi-ng/ccu_div.c    | 2 ++
 drivers/clk/sunxi-ng/ccu_gate.c   | 4 ++++
 drivers/clk/sunxi-ng/ccu_mux.c    | 2 ++
 4 files changed, 12 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 50fd268329671..bbec283b9d993 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -20,10 +20,14 @@
 #define CCU_FEATURE_KEY_FIELD		BIT(8)
 #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
 #define CCU_FEATURE_DUAL_DIV		BIT(10)
+#define CCU_FEATURE_UPDATE_BIT		BIT(11)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)
 
+/* Some clocks need this bit to actually apply register changes */
+#define CCU_SUNXI_UPDATE_BIT		BIT(27)
+
 struct device_node;
 
 struct ccu_common {
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 7f4691f09e01f..916d6da6d8a3b 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -106,6 +106,8 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	reg = readl(cd->common.base + cd->common.reg);
 	reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
+	if (cd->common.features & CCU_FEATURE_UPDATE_BIT)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 
 	writel(reg | (val << cd->div.shift),
 	       cd->common.base + cd->common.reg);
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
index ac52fd6bff677..474a9e8831f87 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -20,6 +20,8 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
 	spin_lock_irqsave(common->lock, flags);
 
 	reg = readl(common->base + common->reg);
+	if (common->features & CCU_FEATURE_UPDATE_BIT)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 	writel(reg & ~gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
@@ -44,6 +46,8 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
 	spin_lock_irqsave(common->lock, flags);
 
 	reg = readl(common->base + common->reg);
+	if (common->features & CCU_FEATURE_UPDATE_BIT)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 	writel(reg | gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index d7ffbdeee9e04..74f9e98a5d355 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -197,6 +197,8 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
 	/* The key field always reads as zero. */
 	if (common->features & CCU_FEATURE_KEY_FIELD)
 		reg |= CCU_MUX_KEY_VALUE;
+	if (common->features & CCU_FEATURE_UPDATE_BIT)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 
 	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
 	writel(reg | (index << cm->shift), common->base + common->reg);
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:18 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:18 +0000
Subject: [PATCH v4 04/14] dt-bindings: clk: sunxi-ng: document two Allwinner A523 CCUs
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-5-andre.przywara@arm.com>

The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
the main and the PRCM R-CCU.

The source clock list differs in some annoying details, and folding this
into the existing Allwinner CCU clock binding document gets quite
unwieldy, so create a new document for these CCUs.
Add the new compatible string, along with the required input clock
lists. This conditionally describes the input clock lists, to make
adding support for the other two CCUs easier.

Also add the DT binding headers, listing all the clocks with their ID
numbers.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../clock/allwinner,sun55i-a523-ccu.yaml      | 103 ++++++++++
 include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
 include/dt-bindings/clock/sun55i-a523-r-ccu.h |  37 ++++
 include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
 include/dt-bindings/reset/sun55i-a523-r-ccu.h |  25 +++
 5 files changed, 442 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
 create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
 create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
new file mode 100644
index 0000000000000..f5f62e9a10a1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/allwinner,sun55i-a523-ccu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A523 Clock Control Unit
+
+maintainers:
+  - Andre Przywara <andre.przywara at arm.com>
+
+properties:
+  "#clock-cells":
+    const: 1
+
+  "#reset-cells":
+    const: 1
+
+  compatible:
+    enum:
+      - allwinner,sun55i-a523-ccu
+      - allwinner,sun55i-a523-r-ccu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 4
+    maxItems: 5
+
+  clock-names:
+    minItems: 4
+    maxItems: 5
+
+required:
+  - "#clock-cells"
+  - "#reset-cells"
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun55i-a523-ccu
+
+    then:
+      properties:
+        clocks:
+          items:
+            - description: High Frequency Oscillator (usually at 24MHz)
+            - description: Low Frequency Oscillator (usually at 32kHz)
+            - description: Internal Oscillator
+            - description: Low Frequency Oscillator fanout
+
+        clock-names:
+          items:
+            - const: hosc
+            - const: losc
+            - const: iosc
+            - const: losc-fanout
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun55i-a523-r-ccu
+
+    then:
+      properties:
+        clocks:
+          items:
+            - description: High Frequency Oscillator (usually at 24MHz)
+            - description: Low Frequency Oscillator (usually at 32kHz)
+            - description: Internal Oscillator
+            - description: Peripherals PLL
+            - description: Audio PLL
+
+        clock-names:
+          items:
+            - const: hosc
+            - const: losc
+            - const: iosc
+            - const: pll-periph
+            - const: pll-audio
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller at 2001000 {
+        compatible = "allwinner,sun55i-a523-ccu";
+        reg = <0x02001000 0x1000>;
+        clocks = <&osc24M>, <&osc32k>, <&iosc>, <&r_ccu 1>;
+        clock-names = "hosc", "losc", "iosc", "losc-fanout";
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+    };
+
+...
diff --git a/include/dt-bindings/clock/sun55i-a523-ccu.h b/include/dt-bindings/clock/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..c8259ac5ada7a
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-ccu.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_
+
+#define CLK_PLL_DDR0		0
+#define CLK_PLL_PERIPH0_4X	1
+#define CLK_PLL_PERIPH0_2X	2
+#define CLK_PLL_PERIPH0_800M	3
+#define CLK_PLL_PERIPH0_480M	4
+#define CLK_PLL_PERIPH0_600M	5
+#define CLK_PLL_PERIPH0_400M	6
+#define CLK_PLL_PERIPH0_300M	7
+#define CLK_PLL_PERIPH0_200M	8
+#define CLK_PLL_PERIPH0_160M	9
+#define CLK_PLL_PERIPH0_150M	10
+#define CLK_PLL_PERIPH1_4X	11
+#define CLK_PLL_PERIPH1_2X	12
+#define CLK_PLL_PERIPH1_800M	13
+#define CLK_PLL_PERIPH1_480M	14
+#define CLK_PLL_PERIPH1_600M	15
+#define CLK_PLL_PERIPH1_400M	16
+#define CLK_PLL_PERIPH1_300M	17
+#define CLK_PLL_PERIPH1_200M	18
+#define CLK_PLL_PERIPH1_160M	19
+#define CLK_PLL_PERIPH1_150M	20
+#define CLK_PLL_GPU		21
+#define CLK_PLL_VIDEO0_8X	22
+#define CLK_PLL_VIDEO0_4X	23
+#define CLK_PLL_VIDEO0_3X	24
+#define CLK_PLL_VIDEO1_8X	25
+#define CLK_PLL_VIDEO1_4X	26
+#define CLK_PLL_VIDEO1_3X	27
+#define CLK_PLL_VIDEO2_8X	28
+#define CLK_PLL_VIDEO2_4X	29
+#define CLK_PLL_VIDEO2_3X	30
+#define CLK_PLL_VIDEO3_8X	31
+#define CLK_PLL_VIDEO3_4X	32
+#define CLK_PLL_VIDEO3_3X	33
+#define CLK_PLL_VE		34
+#define CLK_PLL_AUDIO0_4X	35
+#define CLK_PLL_AUDIO0_2X	36
+#define CLK_PLL_AUDIO0		37
+#define CLK_PLL_NPU_4X		38
+#define CLK_PLL_NPU_2X		39
+#define CLK_PLL_NPU		40
+#define CLK_AHB			41
+#define CLK_APB0		42
+#define CLK_APB1		43
+#define CLK_MBUS		44
+#define CLK_DE			45
+#define CLK_BUS_DE		46
+#define CLK_DI			47
+#define CLK_BUS_DI		48
+#define CLK_G2D			49
+#define CLK_BUS_G2D		50
+#define CLK_GPU			51
+#define CLK_BUS_GPU		52
+#define CLK_CE			53
+#define CLK_BUS_CE		54
+#define CLK_BUS_CE_SYS		55
+#define CLK_VE			56
+#define CLK_BUS_VE		57
+#define CLK_BUS_DMA		58
+#define CLK_BUS_MSGBOX		59
+#define CLK_BUS_SPINLOCK	60
+#define CLK_HSTIMER0		61
+#define CLK_HSTIMER1		62
+#define CLK_HSTIMER2		63
+#define CLK_HSTIMER3		64
+#define CLK_HSTIMER4		65
+#define CLK_HSTIMER5		66
+#define CLK_BUS_HSTIMER		67
+#define CLK_BUS_DBG		68
+#define CLK_BUS_PWM0		69
+#define CLK_BUS_PWM1		70
+#define CLK_IOMMU		71
+#define CLK_BUS_IOMMU		72
+#define CLK_DRAM		73
+#define CLK_MBUS_DMA		74
+#define CLK_MBUS_VE		75
+#define CLK_MBUS_CE		76
+#define CLK_MBUS_CSI		77
+#define CLK_MBUS_ISP		78
+#define CLK_MBUS_EMAC1		79
+#define CLK_BUS_DRAM		80
+#define CLK_NAND0		81
+#define CLK_NAND1		82
+#define CLK_BUS_NAND		83
+#define CLK_MMC0		84
+#define CLK_MMC1		85
+#define CLK_MMC2		86
+#define CLK_BUS_SYSDAP		87
+#define CLK_BUS_MMC0		88
+#define CLK_BUS_MMC1		89
+#define CLK_BUS_MMC2		90
+#define CLK_BUS_UART0		91
+#define CLK_BUS_UART1		92
+#define CLK_BUS_UART2		93
+#define CLK_BUS_UART3		94
+#define CLK_BUS_UART4		95
+#define CLK_BUS_UART5		96
+#define CLK_BUS_UART6		97
+#define CLK_BUS_UART7		98
+#define CLK_BUS_I2C0		99
+#define CLK_BUS_I2C1		100
+#define CLK_BUS_I2C2		101
+#define CLK_BUS_I2C3		102
+#define CLK_BUS_I2C4		103
+#define CLK_BUS_I2C5		104
+#define CLK_BUS_CAN		105
+#define CLK_SPI0		106
+#define CLK_SPI1		107
+#define CLK_SPI2		108
+#define CLK_SPIFC		109
+#define CLK_BUS_SPI0		110
+#define CLK_BUS_SPI1		111
+#define CLK_BUS_SPI2		112
+#define CLK_BUS_SPIFC		113
+#define CLK_EMAC0_25M		114
+#define CLK_EMAC1_25M		115
+#define CLK_BUS_EMAC0		116
+#define CLK_BUS_EMAC1		117
+#define CLK_IR_RX		118
+#define CLK_BUS_IR_RX		119
+#define CLK_IR_TX		120
+#define CLK_BUS_IR_TX		121
+#define CLK_GPADC0		122
+#define CLK_GPADC1		123
+#define CLK_BUS_GPADC0		124
+#define CLK_BUS_GPADC1		125
+#define CLK_BUS_THS		126
+#define CLK_USB_OHCI0		127
+#define CLK_USB_OHCI1		128
+#define CLK_BUS_OHCI0		129
+#define CLK_BUS_OHCI1		130
+#define CLK_BUS_EHCI0		131
+#define CLK_BUS_EHCI1		132
+#define CLK_BUS_OTG		133
+#define CLK_BUS_LRADC		134
+#define CLK_PCIE_AUX		135
+#define CLK_BUS_DISPLAY0_TOP	136
+#define CLK_BUS_DISPLAY1_TOP	137
+#define CLK_HDMI_24M		138
+#define CLK_HDMI_CEC_32K	139
+#define CLK_HDMI_CEC		140
+#define CLK_BUS_HDMI		141
+#define CLK_MIPI_DSI0		142
+#define CLK_MIPI_DSI1		143
+#define CLK_BUS_MIPI_DSI0	144
+#define CLK_BUS_MIPI_DSI1	145
+#define CLK_TCON_LCD0		146
+#define CLK_TCON_LCD1		147
+#define CLK_TCON_LCD2		148
+#define CLK_COMBOPHY_DSI0	149
+#define CLK_COMBOPHY_DSI1	150
+#define CLK_BUS_TCON_LCD0	151
+#define CLK_BUS_TCON_LCD1	152
+#define CLK_BUS_TCON_LCD2	153
+#define CLK_TCON_TV0		154
+#define CLK_TCON_TV1		155
+#define CLK_BUS_TCON_TV0	156
+#define CLK_BUS_TCON_TV1	157
+#define CLK_EDP			158
+#define CLK_BUS_EDP		159
+#define CLK_LEDC		160
+#define CLK_BUS_LEDC		161
+#define CLK_CSI_TOP		162
+#define CLK_CSI_MCLK0		163
+#define CLK_CSI_MCLK1		164
+#define CLK_CSI_MCLK2		165
+#define CLK_CSI_MCLK3		166
+#define CLK_BUS_CSI		167
+#define CLK_ISP			168
+#define CLK_DSP			169
+#define CLK_FANOUT_24M		170
+#define CLK_FANOUT_12M		171
+#define CLK_FANOUT_16M		172
+#define CLK_FANOUT_25M		173
+#define CLK_FANOUT_27M		174
+#define CLK_FANOUT_PCLK		175
+#define CLK_FANOUT0		176
+#define CLK_FANOUT1		177
+#define CLK_FANOUT2		178
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun55i-a523-r-ccu.h b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..365647499b9ab
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-r-ccu.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_
+
+#define CLK_R_AHB		0
+#define CLK_R_APB0		1
+#define CLK_R_APB1		2
+#define CLK_R_TIMER0		3
+#define CLK_R_TIMER1		4
+#define CLK_R_TIMER2		5
+#define CLK_BUS_R_TIMER		6
+#define CLK_BUS_R_TWD		7
+#define CLK_R_PWMCTRL		8
+#define CLK_BUS_R_PWMCTRL	9
+#define CLK_R_SPI		10
+#define CLK_BUS_R_SPI		11
+#define CLK_BUS_R_SPINLOCK	12
+#define CLK_BUS_R_MSGBOX	13
+#define CLK_BUS_R_UART0		14
+#define CLK_BUS_R_UART1		15
+#define CLK_BUS_R_I2C0		16
+#define CLK_BUS_R_I2C1		17
+#define CLK_BUS_R_I2C2		18
+#define CLK_BUS_R_PPU0		19
+#define CLK_BUS_R_PPU1		20
+#define CLK_BUS_R_CPU_BIST	21
+#define CLK_R_IR_RX		22
+#define CLK_BUS_R_IR_RX		23
+#define CLK_BUS_R_DMA		24
+#define CLK_BUS_R_RTC		25
+#define CLK_BUS_R_CPUCFG	26
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-ccu.h b/include/dt-bindings/reset/sun55i-a523-ccu.h
new file mode 100644
index 0000000000000..70df503f34feb
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-ccu.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_NSI		1
+#define RST_BUS_DE		2
+#define RST_BUS_DI		3
+#define RST_BUS_G2D		4
+#define RST_BUS_SYS		5
+#define RST_BUS_GPU		6
+#define RST_BUS_CE		7
+#define RST_BUS_SYS_CE		8
+#define RST_BUS_VE		9
+#define RST_BUS_DMA		10
+#define RST_BUS_MSGBOX		11
+#define RST_BUS_SPINLOCK	12
+#define RST_BUS_CPUXTIMER	13
+#define RST_BUS_DBG		14
+#define RST_BUS_PWM0		15
+#define RST_BUS_PWM1		16
+#define RST_BUS_DRAM		17
+#define RST_BUS_NAND		18
+#define RST_BUS_MMC0		19
+#define RST_BUS_MMC1		20
+#define RST_BUS_MMC2		21
+#define RST_BUS_SYSDAP		22
+#define RST_BUS_UART0		23
+#define RST_BUS_UART1		24
+#define RST_BUS_UART2		25
+#define RST_BUS_UART3		26
+#define RST_BUS_UART4		27
+#define RST_BUS_UART5		28
+#define RST_BUS_UART6		29
+#define RST_BUS_UART7		30
+#define RST_BUS_I2C0		31
+#define RST_BUS_I2C1		32
+#define RST_BUS_I2C2		33
+#define RST_BUS_I2C3		34
+#define RST_BUS_I2C4		35
+#define RST_BUS_I2C5		36
+#define RST_BUS_CAN		37
+#define RST_BUS_SPI0		38
+#define RST_BUS_SPI1		39
+#define RST_BUS_SPI2		40
+#define RST_BUS_SPIFC		41
+#define RST_BUS_EMAC0		42
+#define RST_BUS_EMAC1		43
+#define RST_BUS_IR_RX		44
+#define RST_BUS_IR_TX		45
+#define RST_BUS_GPADC0		46
+#define RST_BUS_GPADC1		47
+#define RST_BUS_THS		48
+#define RST_USB_PHY0		49
+#define RST_USB_PHY1		50
+#define RST_BUS_OHCI0		51
+#define RST_BUS_OHCI1		52
+#define RST_BUS_EHCI0		53
+#define RST_BUS_EHCI1		54
+#define RST_BUS_OTG		55
+#define RST_BUS_3		56
+#define RST_BUS_LRADC		57
+#define RST_BUS_PCIE_USB3	58
+#define RST_BUS_DISPLAY0_TOP	59
+#define RST_BUS_DISPLAY1_TOP	60
+#define RST_BUS_HDMI_MAIN	61
+#define RST_BUS_HDMI_SUB	62
+#define RST_BUS_MIPI_DSI0	63
+#define RST_BUS_MIPI_DSI1	64
+#define RST_BUS_TCON_LCD0	65
+#define RST_BUS_TCON_LCD1	66
+#define RST_BUS_TCON_LCD2	67
+#define RST_BUS_TCON_TV0	68
+#define RST_BUS_TCON_TV1	69
+#define RST_BUS_LVDS0		70
+#define RST_BUS_LVDS1		71
+#define RST_BUS_EDP		72
+#define RST_BUS_VIDEO_OUT0	73
+#define RST_BUS_VIDEO_OUT1	74
+#define RST_BUS_LEDC		75
+#define RST_BUS_CSI		76
+#define RST_BUS_ISP		77
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun55i-a523-r-ccu.h b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
new file mode 100644
index 0000000000000..dd6fbb372e190
--- /dev/null
+++ b/include/dt-bindings/reset/sun55i-a523-r-ccu.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_
+
+#define RST_BUS_R_TIMER		0
+#define RST_BUS_R_TWD		1
+#define RST_BUS_R_PWMCTRL	2
+#define RST_BUS_R_SPI		3
+#define RST_BUS_R_SPINLOCK	4
+#define RST_BUS_R_MSGBOX	5
+#define RST_BUS_R_UART0		6
+#define RST_BUS_R_UART1		7
+#define RST_BUS_R_I2C0		8
+#define RST_BUS_R_I2C1		9
+#define RST_BUS_R_I2C2		10
+#define RST_BUS_R_PPU1		11
+#define RST_BUS_R_IR_RX		12
+#define RST_BUS_R_RTC		13
+#define RST_BUS_R_CPUCFG	14
+
+#endif /* _DT_BINDINGS_RST_SUN55I_A523_R_CCU_H_ */
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:19 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:19 +0000
Subject: [PATCH v4 05/14] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-6-andre.przywara@arm.com>

Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
The clocks were modelled after the A523 and T527 manual, and double
checked by writing all 1's into the respective register, to spot all
implemented bits.

The PLL and mod clocks for the two CPU clusters and the DSU are part of
a separate CCU, also most audio clocks are collected in a DSP CCU, so
both of these clock groups are missing from this driver.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/Kconfig           |   5 +
 drivers/clk/sunxi-ng/Makefile          |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 481 +++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523.h |  14 +
 4 files changed, 502 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index b547198a2c654..04efbda847cf9 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -52,6 +52,11 @@ config SUN50I_H6_R_CCU
 	default y
 	depends on ARM64 || COMPILE_TEST
 
+config SUN55I_A523_CCU
+	tristate "Support for the Allwinner A523/T527 CCU"
+	default y
+	depends on ARM64 || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	tristate "Support for the Allwinner A10/A20 CCU"
 	default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6b3ae2b620db6..01a887f7824bb 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU)	+= sun50i-a100-r-ccu.o
 obj-$(CONFIG_SUN50I_H6_CCU)	+= sun50i-h6-ccu.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= sun50i-h6-r-ccu.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= sun50i-h616-ccu.o
+obj-$(CONFIG_SUN55I_A523_CCU)	+= sun55i-a523-ccu.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= sun4i-a10-ccu.o
 obj-$(CONFIG_SUN5I_CCU)		+= sun5i-ccu.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= sun6i-a31-ccu.o
@@ -58,6 +59,7 @@ sun50i-a100-r-ccu-y		+= ccu-sun50i-a100-r.o
 sun50i-h6-ccu-y			+= ccu-sun50i-h6.o
 sun50i-h6-r-ccu-y		+= ccu-sun50i-h6-r.o
 sun50i-h616-ccu-y		+= ccu-sun50i-h616.o
+sun55i-a523-ccu-y		+= ccu-sun55i-a523.o
 sun4i-a10-ccu-y			+= ccu-sun4i-a10.o
 sun5i-ccu-y			+= ccu-sun5i.o
 sun6i-a31-ccu-y			+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
new file mode 100644
index 0000000000000..455bca0c344bc
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023-2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ *   Copyright (c) 2020 huangzhenwei at allwinnertech.com
+ *   Copyright (C) 2021 Samuel Holland <samuel at sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "../clk.h"
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun55i-a523.h"
+
+/*
+ * The 24 MHz oscillator, the root of most of the clock tree.
+ * .fw_name is the string used in the DT "clock-names" property, used to
+ * identify the corresponding clock in the "clocks" property.
+ */
+static const struct clk_parent_data osc24M[] = {
+	{ .fw_name = "hosc" }
+};
+
+/**************************************************************************
+ *                              PLLs                                      *
+ **************************************************************************/
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN55I_A523_PLL_DDR0_REG		0x010
+static struct ccu_nkmp pll_ddr_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x010,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE |
+							   CLK_IS_CRITICAL),
+	},
+};
+
+/*
+ * There is no actual clock output with that frequency (2.4 GHz), instead it
+ * has multiple outputs with adjustable dividers from that base frequency.
+ * Model them separately as divider clocks based on that parent here.
+ */
+#define SUN55I_A523_PLL_PERIPH0_REG	0x020
+static struct ccu_nm pll_periph0_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x020,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+/*
+ * Most clock-defining macros expect an *array* of parent clocks, even if
+ * they do not contain a muxer to select between different parents.
+ * The macros ending in just _HW take a simple clock pointer, but then create
+ * a single-entry array out of that. The macros using _HWS take such an
+ * array (even when it is a single entry one), this avoids having those
+ * helper arrays created inside *every* clock definition.
+ * This means for every clock that is referenced more than once it is
+ * useful to create such a dummy array and use _HWS.
+ */
+static const struct clk_hw *pll_periph0_4x_hws[] = {
+	&pll_periph0_4x_clk.common.hw
+};
+
+static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+		       pll_periph0_4x_hws, 0x020, 16, 3, 0);
+static const struct clk_hw *pll_periph0_2x_hws[] = {
+	&pll_periph0_2x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M",
+		       pll_periph0_4x_hws, 0x020, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph0_480M_clk, "pll-periph0-480M",
+		       pll_periph0_4x_hws, 0x020, 2, 3, 0);
+static const struct clk_hw *pll_periph0_480M_hws[] = {
+	&pll_periph0_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph0_600M_clk, "pll-periph0-600M",
+			    pll_periph0_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_400M_clk, "pll-periph0-400M",
+			    pll_periph0_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_300M_clk, "pll-periph0-300M",
+			    pll_periph0_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_200M_clk, "pll-periph0-200M",
+			    pll_periph0_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
+			    pll_periph0_2x_hws, 8, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
+			    pll_periph0_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_PERIPH1_REG	0x028
+static struct ccu_nm pll_periph1_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x028,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph1-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_periph1_4x_hws[] = {
+	&pll_periph1_4x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+		       pll_periph1_4x_hws, 0x028, 16, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_800M_clk, "pll-periph1-800M",
+		       pll_periph1_4x_hws, 0x028, 20, 3, 0);
+static SUNXI_CCU_M_HWS(pll_periph1_480M_clk, "pll-periph1-480M",
+		       pll_periph1_4x_hws, 0x028, 2, 3, 0);
+
+static const struct clk_hw *pll_periph1_2x_hws[] = {
+	&pll_periph1_2x_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_600M_clk, "pll-periph1-600M",
+			    pll_periph1_2x_hws, 2, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_400M_clk, "pll-periph1-400M",
+			    pll_periph1_2x_hws, 3, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_300M_clk, "pll-periph1-300M",
+			    pll_periph1_2x_hws, 4, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_200M_clk, "pll-periph1-200M",
+			    pll_periph1_2x_hws, 6, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_periph1_150M_clk, "pll-periph1-150M",
+			    pll_periph1_2x_hws, 8, 1, 0);
+static const struct clk_hw *pll_periph1_480M_hws[] = {
+	&pll_periph1_480M_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_periph1_160M_clk, "pll-periph1-160M",
+			    pll_periph1_480M_hws, 3, 1, 0);
+
+#define SUN55I_A523_PLL_GPU_REG		0x030
+static struct ccu_nkmp pll_gpu_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x030,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-gpu", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+#define SUN55I_A523_PLL_VIDEO0_REG	0x040
+static struct ccu_nm pll_video0_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x040,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video0-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video0_8x_hws[] = {
+	&pll_video0_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video0_4x_clk, "pll-video0-4x",
+		       pll_video0_8x_hws, 0x040, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video0_3x_clk, "pll-video0-3x",
+			    pll_video0_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO1_REG	0x048
+static struct ccu_nm pll_video1_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x048,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video1-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video1_8x_hws[] = {
+	&pll_video1_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video1_4x_clk, "pll-video1-4x",
+		       pll_video1_8x_hws, 0x048, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video1_3x_clk, "pll-video1-3x",
+			    pll_video1_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VIDEO2_REG	0x050
+static struct ccu_nm pll_video2_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x050,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video2-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video2_8x_hws[] = {
+	&pll_video2_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video2_4x_clk, "pll-video2-4x",
+		       pll_video2_8x_hws, 0x050, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video2_3x_clk, "pll-video2-3x",
+			    pll_video2_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+#define SUN55I_A523_PLL_VE_REG		0x058
+static struct ccu_nkmp pll_ve_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
+	.common		= {
+		.reg		= 0x058,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M,
+							   &ccu_nkmp_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+#define SUN55I_A523_PLL_VIDEO3_REG	0x068
+static struct ccu_nm pll_video3_8x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.common		= {
+		.reg		= 0x068,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video3-8x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static const struct clk_hw *pll_video3_8x_hws[] = {
+	&pll_video3_8x_clk.common.hw
+};
+static SUNXI_CCU_M_HWS(pll_video3_4x_clk, "pll-video3-4x",
+		       pll_video3_8x_hws, 0x068, 0, 1, 0);
+static CLK_FIXED_FACTOR_HWS(pll_video3_3x_clk, "pll-video3-3x",
+			    pll_video3_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
+
+/*
+ * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors.
+ * Since we only need some fixed frequency from this PLL (22.5792MHz x 4 and
+ * 24.576MHz x 4), ignore those dividers and force both of them to 1 (encoded
+ * as 0), in the probe function below.
+ * The M factor must be an even number to produce a 50% duty cycle output.
+ */
+#define SUN55I_A523_PLL_AUDIO0_REG		0x078
+static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
+	{ .rate = 90316800, .pattern = 0xc000872b, .m = 20, .n = 75 },
+	{ .rate = 98304000, .pattern = 0xc0004dd3, .m = 12, .n = 49 },
+
+};
+
+static struct ccu_nm pll_audio0_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(16, 6),
+	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24),
+					 0x178, BIT(31)),
+	.min_rate	= 180000000U,
+	.max_rate	= 3000000000U,
+	.common		= {
+		.reg		= 0x078,
+		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+
+static CLK_FIXED_FACTOR_HW(pll_audio0_2x_clk, "pll-audio0-2x",
+			   &pll_audio0_4x_clk.common.hw, 2, 1, 0);
+static CLK_FIXED_FACTOR_HW(pll_audio0_clk, "pll-audio0",
+			   &pll_audio0_4x_clk.common.hw, 4, 1, 0);
+
+#define SUN55I_A523_PLL_NPU_REG			0x080
+static struct ccu_nm pll_npu_4x_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
+	.m		= _SUNXI_CCU_DIV(1, 1),	/* input divider */
+	.common		= {
+		.reg		= 0x0080,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-npu-4x",
+							   osc24M, &ccu_nm_ops,
+							   CLK_SET_RATE_GATE),
+	},
+};
+static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
+			   &pll_npu_4x_clk.common.hw, 2, 1, CLK_SET_RATE_PARENT);
+
+static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
+			   &pll_npu_4x_clk.common.hw, 4, 1, 0);
+
+/*
+ * Contains all clocks that are controlled by a hardware register. They
+ * have a (sunxi) .common member, which needs to be initialised by the common
+ * sunxi CCU code, to be filled with the MMIO base address and the shared lock.
+ */
+static struct ccu_common *sun55i_a523_ccu_clks[] = {
+	&pll_ddr_clk.common,
+	&pll_periph0_4x_clk.common,
+	&pll_periph0_2x_clk.common,
+	&pll_periph0_800M_clk.common,
+	&pll_periph0_480M_clk.common,
+	&pll_periph1_4x_clk.common,
+	&pll_periph1_2x_clk.common,
+	&pll_periph1_800M_clk.common,
+	&pll_periph1_480M_clk.common,
+	&pll_gpu_clk.common,
+	&pll_video0_8x_clk.common,
+	&pll_video0_4x_clk.common,
+	&pll_video1_8x_clk.common,
+	&pll_video1_4x_clk.common,
+	&pll_video2_8x_clk.common,
+	&pll_video2_4x_clk.common,
+	&pll_video3_8x_clk.common,
+	&pll_video3_4x_clk.common,
+	&pll_ve_clk.common,
+	&pll_audio0_4x_clk.common,
+	&pll_npu_4x_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
+	.num	= CLK_NUMBER,
+	.hws	= {
+		[CLK_PLL_DDR0]		= &pll_ddr_clk.common.hw,
+		[CLK_PLL_PERIPH0_4X]	= &pll_periph0_4x_clk.common.hw,
+		[CLK_PLL_PERIPH0_2X]	= &pll_periph0_2x_clk.common.hw,
+		[CLK_PLL_PERIPH0_800M]	= &pll_periph0_800M_clk.common.hw,
+		[CLK_PLL_PERIPH0_480M]	= &pll_periph0_480M_clk.common.hw,
+		[CLK_PLL_PERIPH0_600M]	= &pll_periph0_600M_clk.hw,
+		[CLK_PLL_PERIPH0_400M]	= &pll_periph0_400M_clk.hw,
+		[CLK_PLL_PERIPH0_300M]	= &pll_periph0_300M_clk.hw,
+		[CLK_PLL_PERIPH0_200M]	= &pll_periph0_200M_clk.hw,
+		[CLK_PLL_PERIPH0_160M]	= &pll_periph0_160M_clk.hw,
+		[CLK_PLL_PERIPH0_150M]	= &pll_periph0_150M_clk.hw,
+		[CLK_PLL_PERIPH1_4X]	= &pll_periph1_4x_clk.common.hw,
+		[CLK_PLL_PERIPH1_2X]	= &pll_periph1_2x_clk.common.hw,
+		[CLK_PLL_PERIPH1_800M]	= &pll_periph1_800M_clk.common.hw,
+		[CLK_PLL_PERIPH1_480M]	= &pll_periph1_480M_clk.common.hw,
+		[CLK_PLL_PERIPH1_600M]	= &pll_periph1_600M_clk.hw,
+		[CLK_PLL_PERIPH1_400M]	= &pll_periph1_400M_clk.hw,
+		[CLK_PLL_PERIPH1_300M]	= &pll_periph1_300M_clk.hw,
+		[CLK_PLL_PERIPH1_200M]	= &pll_periph1_200M_clk.hw,
+		[CLK_PLL_PERIPH1_160M]	= &pll_periph1_160M_clk.hw,
+		[CLK_PLL_PERIPH1_150M]	= &pll_periph1_150M_clk.hw,
+		[CLK_PLL_VIDEO0_8X]	= &pll_video0_8x_clk.common.hw,
+		[CLK_PLL_VIDEO0_4X]	= &pll_video0_4x_clk.common.hw,
+		[CLK_PLL_VIDEO0_3X]	= &pll_video0_3x_clk.hw,
+		[CLK_PLL_VIDEO1_8X]	= &pll_video1_8x_clk.common.hw,
+		[CLK_PLL_VIDEO1_4X]	= &pll_video1_4x_clk.common.hw,
+		[CLK_PLL_VIDEO1_3X]	= &pll_video1_3x_clk.hw,
+		[CLK_PLL_VIDEO2_8X]	= &pll_video2_8x_clk.common.hw,
+		[CLK_PLL_VIDEO2_4X]	= &pll_video2_4x_clk.common.hw,
+		[CLK_PLL_VIDEO2_3X]	= &pll_video2_3x_clk.hw,
+		[CLK_PLL_VIDEO3_8X]	= &pll_video3_8x_clk.common.hw,
+		[CLK_PLL_VIDEO3_4X]	= &pll_video3_4x_clk.common.hw,
+		[CLK_PLL_VIDEO3_3X]	= &pll_video3_3x_clk.hw,
+		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
+		[CLK_PLL_AUDIO0_4X]	= &pll_audio0_4x_clk.common.hw,
+		[CLK_PLL_AUDIO0_2X]	= &pll_audio0_2x_clk.hw,
+		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.hw,
+		[CLK_PLL_NPU_4X]	= &pll_npu_4x_clk.common.hw,
+		[CLK_PLL_NPU_2X]	= &pll_npu_2x_clk.hw,
+		[CLK_PLL_NPU]		= &pll_npu_1x_clk.hw,
+	},
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
+	.ccu_clks	= sun55i_a523_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_ccu_clks),
+
+	.hw_clks	= &sun55i_a523_hw_clks,
+};
+
+static const u32 pll_regs[] = {
+	SUN55I_A523_PLL_DDR0_REG,
+	SUN55I_A523_PLL_PERIPH0_REG,
+	SUN55I_A523_PLL_PERIPH1_REG,
+	SUN55I_A523_PLL_GPU_REG,
+	SUN55I_A523_PLL_VIDEO0_REG,
+	SUN55I_A523_PLL_VIDEO1_REG,
+	SUN55I_A523_PLL_VIDEO2_REG,
+	SUN55I_A523_PLL_VE_REG,
+	SUN55I_A523_PLL_VIDEO3_REG,
+	SUN55I_A523_PLL_AUDIO0_REG,
+	SUN55I_A523_PLL_NPU_REG,
+};
+
+static int sun55i_a523_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+	u32 val;
+	int i, ret;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/*
+	 * The PLL clock code does not model all bits, for instance it does
+	 * not support a separate enable and gate bit. We present the
+	 * gate bit(27) as the enable bit, but then have to set the
+	 * PLL Enable, LDO Enable, and Lock Enable bits on all PLLs here.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		val = readl(reg + pll_regs[i]);
+		val |= BIT(31) | BIT(30) | BIT(29);
+		writel(val, reg + pll_regs[i]);
+	}
+
+	/* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
+	val = readl(reg + SUN55I_A523_PLL_AUDIO0_REG);
+	val &= ~(BIT(1) | BIT(0));
+	writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
+
+	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id sun55i_a523_ccu_ids[] = {
+	{ .compatible = "allwinner,sun55i-a523-ccu" },
+	{ }
+};
+
+static struct platform_driver sun55i_a523_ccu_driver = {
+	.probe	= sun55i_a523_ccu_probe,
+	.driver	= {
+		.name			= "sun55i-a523-ccu",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sun55i_a523_ccu_ids,
+	},
+};
+module_platform_driver(sun55i_a523_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
new file mode 100644
index 0000000000000..fc8dd42f1b47b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_H
+#define _CCU_SUN55I_A523_H
+
+#include <dt-bindings/clock/sun55i-a523-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-ccu.h>
+
+#define CLK_NUMBER	(CLK_FANOUT2 + 1)
+
+#endif /* _CCU_SUN55I_A523_H */
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:20 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:20 +0000
Subject: [PATCH v4 06/14] clk: sunxi-ng: a523: Add support for bus clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-7-andre.przywara@arm.com>

Add the basic bus clocks for the Allwinner A523 and T527 SoCs.
This covers the AHB, APB0 and APB1 clocks. Linux is not supposed to
change those clocks, but they are needed as parents for many other mod
clocks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 39 ++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 455bca0c344bc..c8a96b642bb1e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -331,6 +331,39 @@ static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
 static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
 			   &pll_npu_4x_clk.common.hw, 4, 1, 0);
 
+
+/**************************************************************************
+ *                           bus clocks                                   *
+ **************************************************************************/
+
+static const struct clk_parent_data ahb_apb0_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_600M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
+				 0, 5,		/* M */
+				 24, 2,		/* mux */
+				 0);
+static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
+				 0, 5,		/* M */
+				 24, 2,	/* mux */
+				 0);
+
+static const struct clk_parent_data apb1_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
+				 0, 5,		/* M */
+				 24, 3,		/* mux */
+				 0);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -358,6 +391,9 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&pll_ve_clk.common,
 	&pll_audio0_4x_clk.common,
 	&pll_npu_4x_clk.common,
+	&ahb_clk.common,
+	&apb0_clk.common,
+	&apb1_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -403,6 +439,9 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_PLL_NPU_4X]	= &pll_npu_4x_clk.common.hw,
 		[CLK_PLL_NPU_2X]	= &pll_npu_2x_clk.hw,
 		[CLK_PLL_NPU]		= &pll_npu_1x_clk.hw,
+		[CLK_AHB]		= &ahb_clk.common.hw,
+		[CLK_APB0]		= &apb0_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:21 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:21 +0000
Subject: [PATCH v4 07/14] clk: sunxi-ng: a523: add video mod clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-8-andre.przywara@arm.com>

Add the clocks driving the various video subsystems of the SoC: the "DE"
display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
clocks for the various video output drivers (HDMI, DP, LCDs).

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 238 +++++++++++++++++++++++++
 1 file changed, 238 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index c8a96b642bb1e..17a4ffc0b7f52 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -364,6 +364,208 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 24, 3,		/* mux */
 				 0);
 
+
+/**************************************************************************
+ *                          mod clocks                                    *
+ **************************************************************************/
+
+static const struct clk_hw *de_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_video3_3x_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *di_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *g2d_parents[] = {
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_hw *gpu_parents[] = {
+	&pll_gpu_clk.common.hw,
+	&pll_periph0_800M_clk.common.hw,
+	&pll_periph0_600M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_200M_clk.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *ve_parents[] = {
+	&pll_ve_clk.common.hw,
+	&pll_periph0_480M_clk.common.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_300M_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data iommu_parents[] = {
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+	{ .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
+					    0x7b0,
+					    0, 5,	/* M */
+					    0, 0,	/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    CLK_SET_RATE_PARENT,
+					    CCU_FEATURE_UPDATE_BIT);
+
+static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
+
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
+				      pll_periph0_2x_hws,
+				      0xb10, BIT(30), 36621, 0);
+
+static const struct clk_parent_data hdmi_cec_parents[] = {
+	{ .fw_name = "losc" },
+	{ .hw = &hdmi_cec_32k_clk.common.hw },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
+				    0xb10,
+				    24, 1,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data mipi_dsi_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_200M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
+				      mipi_dsi_parents, 0xb24,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
+				      mipi_dsi_parents, 0xb28,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static const struct clk_hw *tcon_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+	&pll_video0_3x_clk.hw,
+	&pll_video1_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
+				    0xb60,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
+				    0xb64,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *tcon_tv_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd2_clk, "tcon-lcd2",
+				    tcon_tv_parents, 0xb68,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
+				    tcon_parents, 0xb6c,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
+				    tcon_parents, 0xb70,
+				    0,  5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_tv_parents,
+				    0xb80,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_tv_parents,
+				    0xb84,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *edp_parents[] = {
+	&pll_video0_4x_clk.common.hw,
+	&pll_video1_4x_clk.common.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_periph0_2x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
+				    0, 4,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    CLK_SET_RATE_PARENT);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -394,6 +596,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ahb_clk.common,
 	&apb0_clk.common,
 	&apb1_clk.common,
+	&de_clk.common,
+	&di_clk.common,
+	&g2d_clk.common,
+	&gpu_clk.common,
+	&ve_clk.common,
+	&iommu_clk.common,
+	&hdmi_24M_clk.common,
+	&hdmi_cec_32k_clk.common,
+	&hdmi_cec_clk.common,
+	&mipi_dsi0_clk.common,
+	&mipi_dsi1_clk.common,
+	&tcon_lcd0_clk.common,
+	&tcon_lcd1_clk.common,
+	&tcon_lcd2_clk.common,
+	&tcon_tv0_clk.common,
+	&tcon_tv1_clk.common,
+	&edp_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -420,6 +639,7 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_PLL_PERIPH1_200M]	= &pll_periph1_200M_clk.hw,
 		[CLK_PLL_PERIPH1_160M]	= &pll_periph1_160M_clk.hw,
 		[CLK_PLL_PERIPH1_150M]	= &pll_periph1_150M_clk.hw,
+		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
 		[CLK_PLL_VIDEO0_8X]	= &pll_video0_8x_clk.common.hw,
 		[CLK_PLL_VIDEO0_4X]	= &pll_video0_4x_clk.common.hw,
 		[CLK_PLL_VIDEO0_3X]	= &pll_video0_3x_clk.hw,
@@ -442,6 +662,24 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_AHB]		= &ahb_clk.common.hw,
 		[CLK_APB0]		= &apb0_clk.common.hw,
 		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_DE]		= &de_clk.common.hw,
+		[CLK_DI]		= &di_clk.common.hw,
+		[CLK_G2D]		= &g2d_clk.common.hw,
+		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
+		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
+		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
+		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
+		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
+		[CLK_TCON_LCD0]		= &tcon_lcd0_clk.common.hw,
+		[CLK_TCON_LCD1]		= &tcon_lcd1_clk.common.hw,
+		[CLK_TCON_LCD2]		= &tcon_lcd2_clk.common.hw,
+		[CLK_COMBOPHY_DSI0]	= &combophy_dsi0_clk.common.hw,
+		[CLK_COMBOPHY_DSI1]	= &combophy_dsi1_clk.common.hw,
+		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
+		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
+		[CLK_EDP]		= &edp_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:22 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:22 +0000
Subject: [PATCH v4 08/14] clk: sunxi-ng: a523: add system mod clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-9-andre.przywara@arm.com>

Add the clocks driving some core system related subsystems of the SoC:
the "CE" crypto engine, the high speed timers, the DRAM and the associated
MBUS clock, and the PCIe clock.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 135 +++++++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 17a4ffc0b7f52..c59f3f789d052 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -364,6 +364,21 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 24, 3,		/* mux */
 				 0);
 
+static const struct clk_parent_data mbus_parents[] = {
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph1_600M_clk.hw },
+	{ .hw = &pll_periph1_480M_clk.common.hw },
+	{ .hw = &pll_periph1_400M_clk.hw },
+	{ .hw = &pll_periph1_150M_clk.hw },
+	{ .fw_name = "hosc" },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
+					    0x540,
+					    0, 5,		/* M */
+					    0, 0,		/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    0, CCU_FEATURE_UPDATE_BIT);
 
 /**************************************************************************
  *                          mod clocks                                    *
@@ -423,6 +438,18 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static const struct clk_parent_data ce_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_300M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+				       0, 5,	/* M */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
 static const struct clk_hw *ve_parents[] = {
 	&pll_ve_clk.common.hw,
 	&pll_periph0_480M_clk.common.hw,
@@ -435,6 +462,65 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static const struct clk_parent_data hstimer_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "iosc" },
+	{ .fw_name = "losc" },
+	{ .hw = &pll_periph0_200M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
+				       hstimer_parents, 0x730,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
+				       hstimer_parents,
+				       0x734,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
+				       hstimer_parents,
+				       0x738,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
+				       hstimer_parents,
+				       0x73c,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
+				       hstimer_parents,
+				       0x740,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
+				       hstimer_parents,
+				       0x744,
+				       0, 0,	/* M */
+				       0, 3,	/* P */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
 static const struct clk_parent_data iommu_parents[] = {
 	{ .hw = &pll_periph0_600M_clk.hw },
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -453,6 +539,34 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 					    CLK_SET_RATE_PARENT,
 					    CCU_FEATURE_UPDATE_BIT);
 
+static const struct clk_parent_data dram_parents[] = {
+	{ .hw = &pll_ddr_clk.common.hw },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_150M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
+					    0x800,
+					    0, 5,	/* M */
+					    0, 0,	/* no P */
+					    24, 3,	/* mux */
+					    BIT(31),	/* gate */
+					    CLK_IS_CRITICAL,
+					    CCU_FEATURE_UPDATE_BIT);
+
+static const struct clk_parent_data losc_hosc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
+				      losc_hosc_parents, 0xaa0,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
 static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
@@ -596,12 +710,22 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ahb_clk.common,
 	&apb0_clk.common,
 	&apb1_clk.common,
+	&mbus_clk.common,
 	&de_clk.common,
 	&di_clk.common,
 	&g2d_clk.common,
 	&gpu_clk.common,
+	&ce_clk.common,
 	&ve_clk.common,
+	&hstimer0_clk.common,
+	&hstimer1_clk.common,
+	&hstimer2_clk.common,
+	&hstimer3_clk.common,
+	&hstimer4_clk.common,
+	&hstimer5_clk.common,
 	&iommu_clk.common,
+	&dram_clk.common,
+	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
 	&hdmi_cec_clk.common,
@@ -662,11 +786,22 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_AHB]		= &ahb_clk.common.hw,
 		[CLK_APB0]		= &apb0_clk.common.hw,
 		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_DE]		= &de_clk.common.hw,
 		[CLK_DI]		= &di_clk.common.hw,
 		[CLK_G2D]		= &g2d_clk.common.hw,
 		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_CE]		= &ce_clk.common.hw,
 		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_HSTIMER0]		= &hstimer0_clk.common.hw,
+		[CLK_HSTIMER1]		= &hstimer1_clk.common.hw,
+		[CLK_HSTIMER2]		= &hstimer2_clk.common.hw,
+		[CLK_HSTIMER3]		= &hstimer3_clk.common.hw,
+		[CLK_HSTIMER4]		= &hstimer4_clk.common.hw,
+		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
+		[CLK_IOMMU]		= &iommu_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
 		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:23 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:23 +0000
Subject: [PATCH v4 09/14] clk: sunxi-ng: a523: add interface mod clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-10-andre.przywara@arm.com>

Add the clocks driving what the user manual summarises under "interface"
devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
general purpose analogue/digital converter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 159 +++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index c59f3f789d052..953b11f7135cf 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -113,6 +113,9 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
 			    pll_periph0_2x_hws, 8, 1, 0);
 static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
 			    pll_periph0_480M_hws, 3, 1, 0);
+static const struct clk_hw *pll_periph0_150M_hws[] = {
+	&pll_periph0_150M_clk.hw
+};
 
 #define SUN55I_A523_PLL_PERIPH1_REG	0x028
 static struct ccu_nm pll_periph1_4x_clk = {
@@ -555,6 +558,132 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 					    CLK_IS_CRITICAL,
 					    CCU_FEATURE_UPDATE_BIT);
 
+static const struct clk_parent_data nand_mmc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_400M_clk.hw },
+	{ .hw = &pll_periph0_300M_clk.hw },
+	{ .hw = &pll_periph1_400M_clk.hw },
+	{ .hw = &pll_periph1_300M_clk.hw },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
+				    0x810,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
+				    0x814,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc0_clk, "mmc0", nand_mmc_parents,
+					     0x830,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc1_clk, "mmc1", nand_mmc_parents,
+					     0x834,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static const struct clk_parent_data mmc2_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_800M_clk.common.hw },
+	{ .hw = &pll_periph0_600M_clk.hw },
+	{ .hw = &pll_periph1_800M_clk.common.hw },
+	{ .hw = &pll_periph1_600M_clk.hw },
+};
+
+static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc2_clk, "mmc2", mmc2_parents,
+					     0x838,
+					     0, 5,	/* M */
+					     8, 5,	/* P */
+					     24, 3,	/* mux */
+					     BIT(31),	/* gate */
+					     2,		/* post div */
+					     0);
+
+static const struct clk_parent_data spi_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph0_300M_clk.hw },
+	{ .hw = &pll_periph0_200M_clk.hw },
+	{ .hw = &pll_periph1_300M_clk.hw },
+	{ .hw = &pll_periph1_200M_clk.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+static SUNXI_CCU_DUALDIV_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents, 0x950,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
+				      pll_periph0_150M_hws,
+				      0x970, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
+				      pll_periph0_150M_hws,
+				      0x974, BIT(31) | BIT(30), 6, 0);
+
+static const struct clk_parent_data ir_rx_parents[] = {
+	{ .fw_name = "losc" },
+	{ .fw_name = "hosc" },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+static const struct clk_parent_data ir_tx_ledc_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_periph1_600M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
+				      0x9c0,
+				      0, 5,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
+				 0, 5,		/* M */
+				 BIT(31),	/* gate */
+				 0);
+static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
+				 0, 5,		/* M */
+				 BIT(31),	/* gate */
+				 0);
+
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "losc" },
@@ -725,6 +854,21 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&hstimer5_clk.common,
 	&iommu_clk.common,
 	&dram_clk.common,
+	&nand0_clk.common,
+	&nand1_clk.common,
+	&mmc0_clk.common,
+	&mmc1_clk.common,
+	&mmc2_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&spi2_clk.common,
+	&spifc_clk.common,
+	&emac0_25M_clk.common,
+	&emac1_25M_clk.common,
+	&ir_rx_clk.common,
+	&ir_tx_clk.common,
+	&gpadc0_clk.common,
+	&gpadc1_clk.common,
 	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
@@ -801,6 +945,21 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
 		[CLK_IOMMU]		= &iommu_clk.common.hw,
 		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_NAND0]		= &nand0_clk.common.hw,
+		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_SPI2]		= &spi2_clk.common.hw,
+		[CLK_SPIFC]		= &spifc_clk.common.hw,
+		[CLK_EMAC0_25M]		= &emac0_25M_clk.common.hw,
+		[CLK_EMAC1_25M]		= &emac1_25M_clk.common.hw,
+		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
+		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:24 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:24 +0000
Subject: [PATCH v4 10/14] clk: sunxi-ng: a523: add USB mod clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-11-andre.przywara@arm.com>

Add the clocks driving the USB subsystem: this just covers the two
clocks creating the 12 MHz rate for the OHCI (USB 1.x) device. The rest
of the USB clocks are either gate clocks (added later) or created
internal to the USB IP.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 57 ++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 953b11f7135cf..f62a32fa70e4e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -684,6 +684,59 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
 				 BIT(31),	/* gate */
 				 0);
 
+/*
+ * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
+ * a 2x multiplier from osc24M synchronized by pll-periph0, and is also used by
+ * the OHCI module.
+ */
+static const struct clk_parent_data usb_ohci_parents[] = {
+	{ .hw = &pll_periph0_4x_clk.common.hw },
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+};
+static const struct ccu_mux_fixed_prediv usb_ohci_predivs[] = {
+	{ .index = 0, .div = 50 },
+	{ .index = 1, .div = 2 },
+};
+
+static struct ccu_mux usb_ohci0_clk = {
+	.enable		= BIT(31),
+	.mux		= {
+		.shift		= 24,
+		.width		= 2,
+		.fixed_predivs	= usb_ohci_predivs,
+		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
+	},
+	.common		= {
+		.reg		= 0xa70,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci0",
+							   usb_ohci_parents,
+							   &ccu_mux_ops,
+							   0),
+	},
+};
+
+static struct ccu_mux usb_ohci1_clk = {
+	.enable		= BIT(31),
+	.mux		= {
+		.shift		= 24,
+		.width		= 2,
+		.fixed_predivs	= usb_ohci_predivs,
+		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
+	},
+	.common		= {
+		.reg		= 0xa74,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci1",
+							   usb_ohci_parents,
+							   &ccu_mux_ops,
+							   0),
+	},
+};
+
+
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "losc" },
@@ -869,6 +922,8 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&ir_tx_clk.common,
 	&gpadc0_clk.common,
 	&gpadc1_clk.common,
+	&usb_ohci0_clk.common,
+	&usb_ohci1_clk.common,
 	&pcie_aux_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
@@ -960,6 +1015,8 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
 		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
 		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:25 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:25 +0000
Subject: [PATCH v4 11/14] clk: sunxi-ng: a523: remaining mod clocks
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-12-andre.przywara@arm.com>

Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
LED controller, the "CSI" camera interface, the "ISP" image processor,
the DSP clock, and the "fanout" clocks, which allow to put clock signals
on external pins.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 185 +++++++++++++++++++++++++
 1 file changed, 185 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index f62a32fa70e4e..0f28e453440ae 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -862,6 +862,157 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
+				      0xbf0,
+				      0, 4,	/* M */
+				      24, 1,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static const struct clk_hw *csi_top_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_periph0_480M_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+	&pll_video3_3x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
+				    0xc04,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data csi_mclk_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .hw = &pll_video3_4x_clk.common.hw },
+	{ .hw = &pll_video0_4x_clk.common.hw },
+	{ .hw = &pll_video1_4x_clk.common.hw },
+	{ .hw = &pll_video2_4x_clk.common.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents,
+				  0xc08,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents,
+				  0xc0c,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents,
+				  0xc10,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk3_clk, "csi-mclk3", csi_mclk_parents,
+				  0xc14,
+				  0, 5,		/* M */
+				  8, 5,		/* P */
+				  24, 3,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_hw *isp_parents[] = {
+	&pll_periph0_300M_clk.hw,
+	&pll_periph0_400M_clk.hw,
+	&pll_video2_4x_clk.common.hw,
+	&pll_video3_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
+				    0, 5,	/* M */
+				    24, 3,	/* mux */
+				    BIT(31),	/* gate */
+				    0);
+
+static const struct clk_parent_data dsp_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_periph0_2x_clk.common.hw },
+	{ .hw = &pll_periph0_480M_clk.common.hw, },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
+				      0, 5,	/* M */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
+			   0xf30, BIT(0), 0);
+static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
+				       0xf30, BIT(1), 2, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
+				      pll_periph0_480M_hws,
+				      0xf30, BIT(2), 30, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
+				      pll_periph0_2x_hws,
+				      0xf30, BIT(3), 48, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
+				      pll_periph0_2x_hws,
+				      0xf30, BIT(4), 24, 0);
+
+static const struct clk_parent_data fanout_27M_parents[] = {
+	{ .hw = &pll_video0_4x_clk.common.hw },
+	{ .hw = &pll_video1_4x_clk.common.hw },
+	{ .hw = &pll_video2_4x_clk.common.hw },
+	{ .hw = &pll_video3_4x_clk.common.hw },
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_27M_clk, "fanout-27M",
+				  fanout_27M_parents, 0xf34,
+				  0, 5,		/* div0 */
+				  8, 5,		/* div1 */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_parent_data fanout_pclk_parents[] = {
+	{ .hw = &apb0_clk.common.hw }
+};
+static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_pclk_clk, "fanout-pclk",
+				  fanout_pclk_parents,
+				  0xf38,
+				  0, 5,		/* div0 */
+				  5, 5,		/* div1 */
+				  0, 0,		/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const struct clk_parent_data fanout_parents[] = {
+	{ .fw_name = "losc-fanout" },
+	{ .hw = &fanout_12M_clk.common.hw, },
+	{ .hw = &fanout_16M_clk.common.hw, },
+	{ .hw = &fanout_24M_clk.common.hw, },
+	{ .hw = &fanout_25M_clk.common.hw, },
+	{ .hw = &fanout_27M_clk.common.hw, },
+	{ .hw = &fanout_pclk_clk.common.hw, },
+	{ .hw = &fanout_50M_clk.common.hw, },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
+				    0xf3c,
+				    0, 3,	/* mux */
+				    BIT(21),	/* gate */
+				    0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
+				    0xf3c,
+				    3, 3,	/* mux */
+				    BIT(22),	/* gate */
+				    0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
+				    0xf3c,
+				    6, 3,	/* mux */
+				    BIT(23),	/* gate */
+				    0);
+
 /*
  * Contains all clocks that are controlled by a hardware register. They
  * have a (sunxi) .common member, which needs to be initialised by the common
@@ -936,6 +1087,23 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&tcon_tv0_clk.common,
 	&tcon_tv1_clk.common,
 	&edp_clk.common,
+	&ledc_clk.common,
+	&csi_top_clk.common,
+	&csi_mclk0_clk.common,
+	&csi_mclk1_clk.common,
+	&csi_mclk2_clk.common,
+	&csi_mclk3_clk.common,
+	&isp_clk.common,
+	&dsp_clk.common,
+	&fanout_24M_clk.common,
+	&fanout_12M_clk.common,
+	&fanout_16M_clk.common,
+	&fanout_25M_clk.common,
+	&fanout_27M_clk.common,
+	&fanout_pclk_clk.common,
+	&fanout0_clk.common,
+	&fanout1_clk.common,
+	&fanout2_clk.common,
 };
 
 static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
@@ -1031,6 +1199,23 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
 		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
 		[CLK_EDP]		= &edp_clk.common.hw,
+		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_CSI_TOP]		= &csi_top_clk.common.hw,
+		[CLK_CSI_MCLK0]		= &csi_mclk0_clk.common.hw,
+		[CLK_CSI_MCLK1]		= &csi_mclk1_clk.common.hw,
+		[CLK_CSI_MCLK2]		= &csi_mclk2_clk.common.hw,
+		[CLK_CSI_MCLK3]		= &csi_mclk3_clk.common.hw,
+		[CLK_ISP]		= &isp_clk.common.hw,
+		[CLK_DSP]		= &dsp_clk.common.hw,
+		[CLK_FANOUT_24M]	= &fanout_24M_clk.common.hw,
+		[CLK_FANOUT_12M]	= &fanout_12M_clk.common.hw,
+		[CLK_FANOUT_16M]	= &fanout_16M_clk.common.hw,
+		[CLK_FANOUT_25M]	= &fanout_25M_clk.common.hw,
+		[CLK_FANOUT_27M]	= &fanout_27M_clk.common.hw,
+		[CLK_FANOUT_PCLK]	= &fanout_pclk_clk.common.hw,
+		[CLK_FANOUT0]		= &fanout0_clk.common.hw,
+		[CLK_FANOUT1]		= &fanout1_clk.common.hw,
+		[CLK_FANOUT2]		= &fanout2_clk.common.hw,
 	},
 };
 
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:26 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:26 +0000
Subject: [PATCH v4 12/14] clk: sunxi-ng: a523: add bus clock gates
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-13-andre.przywara@arm.com>

Add the various bus clock gates that control access to the devices'
register interface.
These clocks are each just one bit, typically the lower bits in some "BGR"
(Bus Gate / Reset) registers, for each device group: one for all UARTs,
one for all SPI interfaces, and so on.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 309 ++++++++++++++++++++++++-
 1 file changed, 308 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 0f28e453440ae..736544f6a1415 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -350,10 +350,13 @@ static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
 				 0, 5,		/* M */
 				 24, 2,		/* mux */
 				 0);
+static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
+
 static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
 				 0, 5,		/* M */
 				 24, 2,	/* mux */
 				 0);
+static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
 
 static const struct clk_parent_data apb1_parents[] = {
 	{ .fw_name = "hosc" },
@@ -366,6 +369,7 @@ static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 				 0, 5,		/* M */
 				 24, 3,		/* mux */
 				 0);
+static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
 
 static const struct clk_parent_data mbus_parents[] = {
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -383,8 +387,10 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
 					    BIT(31),	/* gate */
 					    0, CCU_FEATURE_UPDATE_BIT);
 
+static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw };
+
 /**************************************************************************
- *                          mod clocks                                    *
+ *                          mod clocks with gates                         *
  **************************************************************************/
 
 static const struct clk_hw *de_parents[] = {
@@ -400,6 +406,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
+
 static const struct clk_hw *di_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -413,6 +421,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
+
 static const struct clk_hw *g2d_parents[] = {
 	&pll_periph0_400M_clk.hw,
 	&pll_periph0_300M_clk.hw,
@@ -426,6 +436,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
+
 static const struct clk_hw *gpu_parents[] = {
 	&pll_gpu_clk.common.hw,
 	&pll_periph0_800M_clk.common.hw,
@@ -441,6 +453,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
+
 static const struct clk_parent_data ce_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_480M_clk.common.hw },
@@ -453,6 +467,10 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
 				       BIT(31),	/* gate */
 				       0);
 
+static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
+			  BIT(1), 0);
+
 static const struct clk_hw *ve_parents[] = {
 	&pll_ve_clk.common.hw,
 	&pll_periph0_480M_clk.common.hw,
@@ -465,6 +483,16 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
+			  BIT(0), 0);
+
 static const struct clk_parent_data hstimer_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .fw_name = "iosc" },
@@ -524,6 +552,15 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
 				       BIT(31),	/* gate */
 				       0);
 
+static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
+
 static const struct clk_parent_data iommu_parents[] = {
 	{ .hw = &pll_periph0_600M_clk.hw },
 	{ .hw = &pll_ddr_clk.common.hw },
@@ -542,6 +579,9 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 					    CLK_SET_RATE_PARENT,
 					    CCU_FEATURE_UPDATE_BIT);
 
+static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
+			  BIT(0), 0);
+
 static const struct clk_parent_data dram_parents[] = {
 	{ .hw = &pll_ddr_clk.common.hw },
 	{ .hw = &pll_periph0_600M_clk.hw },
@@ -558,6 +598,26 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 					    CLK_IS_CRITICAL,
 					    CCU_FEATURE_UPDATE_BIT);
 
+static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
+			  0x804, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
+			  0x804, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
+			  0x804, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(mbus_nand_clk, "mbus-nand", mbus_hws,
+			  0x804, BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(mbus_usb3_clk, "mbus-usb3", mbus_hws,
+			  0x804, BIT(6), 0);
+static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
+			  0x804, BIT(8), 0);
+static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
+			  0x804, BIT(9), 0);
+static SUNXI_CCU_GATE_HWS(mbus_gmac1_clk, "mbus-gmac1", mbus_hws,
+			  0x804, BIT(12), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
+			  BIT(0), CLK_IS_CRITICAL);
+
 static const struct clk_parent_data nand_mmc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_400M_clk.hw },
@@ -580,6 +640,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
+			  BIT(0), 0);
+
 static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc0_clk, "mmc0", nand_mmc_parents,
 					     0x830,
 					     0, 5,	/* M */
@@ -615,6 +678,39 @@ static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc2_clk, "mmc2", mmc2_parents,
 					     2,		/* post div */
 					     0);
 
+static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
+			  BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
+			  BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
+			  BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
+			  BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
+			  BIT(6), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
+			  BIT(7), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
+
 static const struct clk_parent_data spi_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_300M_clk.hw },
@@ -646,6 +742,11 @@ static SUNXI_CCU_DUALDIV_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents, 0x950,
 				  24, 3,	/* mux */
 				  BIT(31),	/* gate */
 				  0);
+static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
+			  BIT(3), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
 				      pll_periph0_150M_hws,
@@ -653,6 +754,10 @@ static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
 				      pll_periph0_150M_hws,
 				      0x974, BIT(31) | BIT(30), 6, 0);
+static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
+			  BIT(0), 0);
 
 static const struct clk_parent_data ir_rx_parents[] = {
 	{ .fw_name = "losc" },
@@ -664,6 +769,9 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
 				      24, 1,	/* mux */
 				      BIT(31),	/* gate */
 				      0);
+static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
+			  BIT(0), 0);
+
 static const struct clk_parent_data ir_tx_ledc_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph1_600M_clk.hw },
@@ -674,6 +782,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
 				      24, 1,	/* mux */
 				      BIT(31),	/* gate */
 				      0);
+static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
+			  BIT(0), 0);
 
 static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
 				 0, 5,		/* M */
@@ -683,6 +793,12 @@ static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
 				 0, 5,		/* M */
 				 BIT(31),	/* gate */
 				 0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
+			  BIT(1), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
 
 /*
  * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
@@ -736,6 +852,18 @@ static struct ccu_mux usb_ohci1_clk = {
 	},
 };
 
+static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
+			  BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
+			  BIT(5), 0);
+static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
+			  BIT(0), 0);
 
 static const struct clk_parent_data losc_hosc_parents[] = {
 	{ .fw_name = "hosc" },
@@ -749,6 +877,11 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_display0_top_clk, "bus-display0-top", ahb_hws,
+			  0xabc, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_display1_top_clk, "bus-display1-top", ahb_hws,
+			  0xacc, BIT(0), 0);
+
 static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
 
 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
@@ -765,6 +898,8 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
 				    BIT(31),	/* gate */
 				    0);
 
+static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
+
 static const struct clk_parent_data mipi_dsi_parents[] = {
 	{ .fw_name = "hosc" },
 	{ .hw = &pll_periph0_200M_clk.hw },
@@ -784,6 +919,12 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
+			  BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
+			  BIT(1), 0);
+
 static const struct clk_hw *tcon_parents[] = {
 	&pll_video0_4x_clk.common.hw,
 	&pll_video1_4x_clk.common.hw,
@@ -835,6 +976,13 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
+			  BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd2_clk, "bus-tcon-lcd2", ahb_hws, 0xb7c,
+			  BIT(2), 0);
+
 static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_tv_parents,
 				    0xb80,
 				    0, 4,	/* M */
@@ -849,6 +997,11 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_tv_parents,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
+			  BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
+			  BIT(1), 0);
+
 static const struct clk_hw *edp_parents[] = {
 	&pll_video0_4x_clk.common.hw,
 	&pll_video1_4x_clk.common.hw,
@@ -862,6 +1015,8 @@ static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
 				    BIT(31),	/* gate */
 				    CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
+
 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
 				      0xbf0,
 				      0, 4,	/* M */
@@ -869,6 +1024,8 @@ static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
 				      BIT(31),	/* gate */
 				      0);
 
+static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
+
 static const struct clk_hw *csi_top_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -922,6 +1079,8 @@ static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk3_clk, "csi-mclk3", csi_mclk_parents,
 				  BIT(31),	/* gate */
 				  0);
 
+static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
+
 static const struct clk_hw *isp_parents[] = {
 	&pll_periph0_300M_clk.hw,
 	&pll_periph0_400M_clk.hw,
@@ -1045,54 +1204,130 @@ static struct ccu_common *sun55i_a523_ccu_clks[] = {
 	&apb1_clk.common,
 	&mbus_clk.common,
 	&de_clk.common,
+	&bus_de_clk.common,
 	&di_clk.common,
+	&bus_di_clk.common,
 	&g2d_clk.common,
+	&bus_g2d_clk.common,
 	&gpu_clk.common,
+	&bus_gpu_clk.common,
 	&ce_clk.common,
+	&bus_ce_clk.common,
+	&bus_ce_sys_clk.common,
 	&ve_clk.common,
+	&bus_ve_clk.common,
+	&bus_dma_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
 	&hstimer0_clk.common,
 	&hstimer1_clk.common,
 	&hstimer2_clk.common,
 	&hstimer3_clk.common,
 	&hstimer4_clk.common,
 	&hstimer5_clk.common,
+	&bus_hstimer_clk.common,
+	&bus_dbg_clk.common,
+	&bus_pwm0_clk.common,
+	&bus_pwm1_clk.common,
 	&iommu_clk.common,
+	&bus_iommu_clk.common,
 	&dram_clk.common,
+	&mbus_dma_clk.common,
+	&mbus_ve_clk.common,
+	&mbus_ce_clk.common,
+	&mbus_nand_clk.common,
+	&mbus_usb3_clk.common,
+	&mbus_csi_clk.common,
+	&mbus_isp_clk.common,
+	&mbus_gmac1_clk.common,
+	&bus_dram_clk.common,
 	&nand0_clk.common,
 	&nand1_clk.common,
+	&bus_nand_clk.common,
 	&mmc0_clk.common,
 	&mmc1_clk.common,
 	&mmc2_clk.common,
+	&bus_sysdap_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_mmc2_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_uart4_clk.common,
+	&bus_uart5_clk.common,
+	&bus_uart6_clk.common,
+	&bus_uart7_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_i2c2_clk.common,
+	&bus_i2c3_clk.common,
+	&bus_i2c4_clk.common,
+	&bus_i2c5_clk.common,
+	&bus_can_clk.common,
 	&spi0_clk.common,
 	&spi1_clk.common,
 	&spi2_clk.common,
 	&spifc_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&bus_spi2_clk.common,
+	&bus_spifc_clk.common,
 	&emac0_25M_clk.common,
 	&emac1_25M_clk.common,
+	&bus_emac0_clk.common,
+	&bus_emac1_clk.common,
 	&ir_rx_clk.common,
+	&bus_ir_rx_clk.common,
 	&ir_tx_clk.common,
+	&bus_ir_tx_clk.common,
 	&gpadc0_clk.common,
 	&gpadc1_clk.common,
+	&bus_gpadc0_clk.common,
+	&bus_gpadc1_clk.common,
+	&bus_ths_clk.common,
 	&usb_ohci0_clk.common,
 	&usb_ohci1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ohci1_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_ehci1_clk.common,
+	&bus_otg_clk.common,
+	&bus_lradc_clk.common,
 	&pcie_aux_clk.common,
+	&bus_display0_top_clk.common,
+	&bus_display1_top_clk.common,
 	&hdmi_24M_clk.common,
 	&hdmi_cec_32k_clk.common,
 	&hdmi_cec_clk.common,
+	&bus_hdmi_clk.common,
 	&mipi_dsi0_clk.common,
 	&mipi_dsi1_clk.common,
+	&bus_mipi_dsi0_clk.common,
+	&bus_mipi_dsi1_clk.common,
 	&tcon_lcd0_clk.common,
 	&tcon_lcd1_clk.common,
 	&tcon_lcd2_clk.common,
+	&combophy_dsi0_clk.common,
+	&combophy_dsi1_clk.common,
+	&bus_tcon_lcd0_clk.common,
+	&bus_tcon_lcd1_clk.common,
+	&bus_tcon_lcd2_clk.common,
 	&tcon_tv0_clk.common,
 	&tcon_tv1_clk.common,
+	&bus_tcon_tv0_clk.common,
+	&bus_tcon_tv1_clk.common,
 	&edp_clk.common,
+	&bus_edp_clk.common,
 	&ledc_clk.common,
+	&bus_ledc_clk.common,
 	&csi_top_clk.common,
 	&csi_mclk0_clk.common,
 	&csi_mclk1_clk.common,
 	&csi_mclk2_clk.common,
 	&csi_mclk3_clk.common,
+	&bus_csi_clk.common,
 	&isp_clk.common,
 	&dsp_clk.common,
 	&fanout_24M_clk.common,
@@ -1155,56 +1390,128 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 		[CLK_APB1]		= &apb1_clk.common.hw,
 		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_DE]		= &de_clk.common.hw,
+		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
 		[CLK_DI]		= &di_clk.common.hw,
+		[CLK_BUS_DI]		= &bus_di_clk.common.hw,
 		[CLK_G2D]		= &g2d_clk.common.hw,
+		[CLK_BUS_G2D]		= &bus_g2d_clk.common.hw,
 		[CLK_GPU]		= &gpu_clk.common.hw,
+		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
 		[CLK_CE]		= &ce_clk.common.hw,
+		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
+		[CLK_BUS_CE_SYS]	= &bus_ce_sys_clk.common.hw,
 		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
 		[CLK_HSTIMER0]		= &hstimer0_clk.common.hw,
 		[CLK_HSTIMER1]		= &hstimer1_clk.common.hw,
 		[CLK_HSTIMER2]		= &hstimer2_clk.common.hw,
 		[CLK_HSTIMER3]		= &hstimer3_clk.common.hw,
 		[CLK_HSTIMER4]		= &hstimer4_clk.common.hw,
 		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
+		[CLK_BUS_PWM0]		= &bus_pwm0_clk.common.hw,
+		[CLK_BUS_PWM1]		= &bus_pwm1_clk.common.hw,
 		[CLK_IOMMU]		= &iommu_clk.common.hw,
+		[CLK_BUS_IOMMU]		= &bus_iommu_clk.common.hw,
 		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
+		[CLK_MBUS_VE]		= &mbus_ve_clk.common.hw,
+		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
+		[CLK_MBUS_CSI]		= &mbus_csi_clk.common.hw,
+		[CLK_MBUS_ISP]		= &mbus_isp_clk.common.hw,
+		[CLK_MBUS_EMAC1]	= &mbus_gmac1_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
 		[CLK_NAND0]		= &nand0_clk.common.hw,
 		[CLK_NAND1]		= &nand1_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
 		[CLK_MMC0]		= &mmc0_clk.common.hw,
 		[CLK_MMC1]		= &mmc1_clk.common.hw,
 		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_BUS_SYSDAP]	= &bus_sysdap_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
+		[CLK_BUS_UART5]		= &bus_uart5_clk.common.hw,
+		[CLK_BUS_UART6]		= &bus_uart6_clk.common.hw,
+		[CLK_BUS_UART7]		= &bus_uart7_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
+		[CLK_BUS_I2C3]		= &bus_i2c3_clk.common.hw,
+		[CLK_BUS_I2C4]		= &bus_i2c4_clk.common.hw,
+		[CLK_BUS_I2C5]		= &bus_i2c5_clk.common.hw,
+		[CLK_BUS_CAN]		= &bus_can_clk.common.hw,
 		[CLK_SPI0]		= &spi0_clk.common.hw,
 		[CLK_SPI1]		= &spi1_clk.common.hw,
 		[CLK_SPI2]		= &spi2_clk.common.hw,
 		[CLK_SPIFC]		= &spifc_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_BUS_SPI2]		= &bus_spi2_clk.common.hw,
+		[CLK_BUS_SPIFC]		= &bus_spifc_clk.common.hw,
 		[CLK_EMAC0_25M]		= &emac0_25M_clk.common.hw,
 		[CLK_EMAC1_25M]		= &emac1_25M_clk.common.hw,
+		[CLK_BUS_EMAC0]		= &bus_emac0_clk.common.hw,
+		[CLK_BUS_EMAC1]		= &bus_emac1_clk.common.hw,
 		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
+		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
 		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
+		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
 		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
 		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
+		[CLK_BUS_GPADC0]	= &bus_gpadc0_clk.common.hw,
+		[CLK_BUS_GPADC1]	= &bus_gpadc1_clk.common.hw,
+		[CLK_BUS_THS]		= &bus_ths_clk.common.hw,
 		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
 		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_BUS_LRADC]		= &bus_lradc_clk.common.hw,
 		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
+		[CLK_BUS_DISPLAY0_TOP]	= &bus_display0_top_clk.common.hw,
+		[CLK_BUS_DISPLAY1_TOP]	= &bus_display1_top_clk.common.hw,
 		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
 		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
 		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
+		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
 		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
 		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
+		[CLK_BUS_MIPI_DSI0]	= &bus_mipi_dsi0_clk.common.hw,
+		[CLK_BUS_MIPI_DSI1]	= &bus_mipi_dsi1_clk.common.hw,
 		[CLK_TCON_LCD0]		= &tcon_lcd0_clk.common.hw,
 		[CLK_TCON_LCD1]		= &tcon_lcd1_clk.common.hw,
 		[CLK_TCON_LCD2]		= &tcon_lcd2_clk.common.hw,
 		[CLK_COMBOPHY_DSI0]	= &combophy_dsi0_clk.common.hw,
 		[CLK_COMBOPHY_DSI1]	= &combophy_dsi1_clk.common.hw,
+		[CLK_BUS_TCON_LCD0]	= &bus_tcon_lcd0_clk.common.hw,
+		[CLK_BUS_TCON_LCD1]	= &bus_tcon_lcd1_clk.common.hw,
+		[CLK_BUS_TCON_LCD2]	= &bus_tcon_lcd2_clk.common.hw,
 		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
 		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
+		[CLK_BUS_TCON_TV0]	= &bus_tcon_tv0_clk.common.hw,
+		[CLK_BUS_TCON_TV1]	= &bus_tcon_tv1_clk.common.hw,
 		[CLK_EDP]		= &edp_clk.common.hw,
+		[CLK_BUS_EDP]		= &bus_edp_clk.common.hw,
 		[CLK_LEDC]		= &ledc_clk.common.hw,
+		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
 		[CLK_CSI_TOP]		= &csi_top_clk.common.hw,
 		[CLK_CSI_MCLK0]		= &csi_mclk0_clk.common.hw,
 		[CLK_CSI_MCLK1]		= &csi_mclk1_clk.common.hw,
 		[CLK_CSI_MCLK2]		= &csi_mclk2_clk.common.hw,
 		[CLK_CSI_MCLK3]		= &csi_mclk3_clk.common.hw,
+		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
 		[CLK_ISP]		= &isp_clk.common.hw,
 		[CLK_DSP]		= &dsp_clk.common.hw,
 		[CLK_FANOUT_24M]	= &fanout_24M_clk.common.hw,
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:27 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:27 +0000
Subject: [PATCH v4 13/14] clk: sunxi-ng: a523: add reset lines
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-14-andre.przywara@arm.com>

Allwinner SoCs do not contain a separate reset controller, instead the
reset lines for the various devices are integrated into the "BGR" (Bus
Gate / Reset) registers, for each device group: one for all UARTs, one
for all SPI interfaces, and so on.
The Allwinner CCU driver also doubles as a reset provider, and since the
reset lines are indeed just single bits in those BGR register, we can
represent them easily in an array of structs, just containing the
register offset and the bit number.

Add the location of the reset bits for all devices in the A523/T527
SoCs, using the existing sunxi CCU infrastructure.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 84 ++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 736544f6a1415..9efb9fd24b424 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -1526,11 +1526,95 @@ static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
 	},
 };
 
+static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
+	[RST_MBUS]		= { 0x540, BIT(30) },
+	[RST_BUS_NSI]		= { 0x54c, BIT(16) },
+	[RST_BUS_DE]		= { 0x60c, BIT(16) },
+	[RST_BUS_DI]		= { 0x62c, BIT(16) },
+	[RST_BUS_G2D]		= { 0x63c, BIT(16) },
+	[RST_BUS_SYS]		= { 0x64c, BIT(16) },
+	[RST_BUS_GPU]		= { 0x67c, BIT(16) },
+	[RST_BUS_CE]		= { 0x68c, BIT(16) },
+	[RST_BUS_SYS_CE]	= { 0x68c, BIT(17) },
+	[RST_BUS_VE]		= { 0x69c, BIT(16) },
+	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
+	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
+	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
+	[RST_BUS_CPUXTIMER]	= { 0x74c, BIT(16) },
+	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
+	[RST_BUS_PWM0]		= { 0x7ac, BIT(16) },
+	[RST_BUS_PWM1]		= { 0x7ac, BIT(17) },
+	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
+	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
+	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
+	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
+	[RST_BUS_MMC2]		= { 0x84c, BIT(18) },
+	[RST_BUS_SYSDAP]	= { 0x88c, BIT(16) },
+	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
+	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
+	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
+	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
+	[RST_BUS_UART4]		= { 0x90c, BIT(20) },
+	[RST_BUS_UART5]		= { 0x90c, BIT(21) },
+	[RST_BUS_UART6]		= { 0x90c, BIT(22) },
+	[RST_BUS_UART7]		= { 0x90c, BIT(23) },
+	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
+	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
+	[RST_BUS_I2C2]		= { 0x91c, BIT(18) },
+	[RST_BUS_I2C3]		= { 0x91c, BIT(19) },
+	[RST_BUS_I2C4]		= { 0x91c, BIT(20) },
+	[RST_BUS_I2C5]		= { 0x91c, BIT(21) },
+	[RST_BUS_CAN]		= { 0x92c, BIT(16) },
+	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
+	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
+	[RST_BUS_SPI2]		= { 0x96c, BIT(18) },
+	[RST_BUS_SPIFC]		= { 0x96c, BIT(19) },
+	[RST_BUS_EMAC0]		= { 0x97c, BIT(16) },
+	[RST_BUS_EMAC1]		= { 0x98c, BIT(16) | BIT(17) },	/* GMAC1-AXI */
+	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
+	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
+	[RST_BUS_GPADC0]	= { 0x9ec, BIT(16) },
+	[RST_BUS_GPADC1]	= { 0x9ec, BIT(17) },
+	[RST_BUS_THS]		= { 0x9fc, BIT(16) },
+	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
+	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
+	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
+	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
+	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
+	[RST_BUS_EHCI1]		= { 0xa8c, BIT(21) },
+	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
+	[RST_BUS_3]		= { 0xa8c, BIT(25) },	/* BSP + register */
+	[RST_BUS_LRADC]		= { 0xa9c, BIT(16) },
+	[RST_BUS_PCIE_USB3]	= { 0xaac, BIT(16) },
+	[RST_BUS_DISPLAY0_TOP]	= { 0xabc, BIT(16) },
+	[RST_BUS_DISPLAY1_TOP]	= { 0xacc, BIT(16) },
+	[RST_BUS_HDMI_MAIN]	= { 0xb1c, BIT(16) },
+	[RST_BUS_HDMI_SUB]	= { 0xb1c, BIT(17) },
+	[RST_BUS_MIPI_DSI0]	= { 0xb4c, BIT(16) },
+	[RST_BUS_MIPI_DSI1]	= { 0xb4c, BIT(17) },
+	[RST_BUS_TCON_LCD0]	= { 0xb7c, BIT(16) },
+	[RST_BUS_TCON_LCD1]	= { 0xb7c, BIT(17) },
+	[RST_BUS_TCON_LCD2]	= { 0xb7c, BIT(18) },
+	[RST_BUS_TCON_TV0]	= { 0xb9c, BIT(16) },
+	[RST_BUS_TCON_TV1]	= { 0xb9c, BIT(17) },
+	[RST_BUS_LVDS0]		= { 0xbac, BIT(16) },
+	[RST_BUS_LVDS1]		= { 0xbac, BIT(17) },
+	[RST_BUS_EDP]		= { 0xbbc, BIT(16) },
+	[RST_BUS_VIDEO_OUT0]	= { 0xbcc, BIT(16) },
+	[RST_BUS_VIDEO_OUT1]	= { 0xbcc, BIT(17) },
+	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
+	[RST_BUS_CSI]		= { 0xc1c, BIT(16) },
+	[RST_BUS_ISP]		= { 0xc2c, BIT(16) },	/* BSP + register */
+};
+
 static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
 	.ccu_clks	= sun55i_a523_ccu_clks,
 	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_ccu_clks),
 
 	.hw_clks	= &sun55i_a523_hw_clks,
+
+	.resets		= sun55i_a523_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun55i_a523_ccu_resets),
 };
 
 static const u32 pll_regs[] = {
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:26:28 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:26:28 +0000
Subject: [PATCH v4 14/14] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <20250307002628.10684-15-andre.przywara@arm.com>

The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
previous SoCs. For a change, the whole PRCM is documented in the A523
manual, including the system bus tree, so we can describe all those
clocks correctly based on that. There layout seems to be derived from
the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
have subtly changed.

Describe all the mod and gate clocks, including the three bus clocks
(R_AHB, R_APB0, and R_APB1).

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/clk/sunxi-ng/Kconfig             |   5 +
 drivers/clk/sunxi-ng/Makefile            |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c | 248 +++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h |  14 ++
 4 files changed, 269 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 04efbda847cf9..5830a9d87bf25 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -57,6 +57,11 @@ config SUN55I_A523_CCU
 	default y
 	depends on ARM64 || COMPILE_TEST
 
+config SUN55I_A523_R_CCU
+	tristate "Support for the Allwinner A523/T527 PRCM CCU"
+	default y
+	depends on ARM64 || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	tristate "Support for the Allwinner A10/A20 CCU"
 	default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 01a887f7824bb..82e471036de69 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUN50I_H6_CCU)	+= sun50i-h6-ccu.o
 obj-$(CONFIG_SUN50I_H6_R_CCU)	+= sun50i-h6-r-ccu.o
 obj-$(CONFIG_SUN50I_H616_CCU)	+= sun50i-h616-ccu.o
 obj-$(CONFIG_SUN55I_A523_CCU)	+= sun55i-a523-ccu.o
+obj-$(CONFIG_SUN55I_A523_R_CCU)	+= sun55i-a523-r-ccu.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= sun4i-a10-ccu.o
 obj-$(CONFIG_SUN5I_CCU)		+= sun5i-ccu.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= sun6i-a31-ccu.o
@@ -60,6 +61,7 @@ sun50i-h6-ccu-y			+= ccu-sun50i-h6.o
 sun50i-h6-r-ccu-y		+= ccu-sun50i-h6-r.o
 sun50i-h616-ccu-y		+= ccu-sun50i-h616.o
 sun55i-a523-ccu-y		+= ccu-sun55i-a523.o
+sun55i-a523-r-ccu-y		+= ccu-sun55i-a523-r.o
 sun4i-a10-ccu-y			+= ccu-sun4i-a10.o
 sun5i-ccu-y			+= ccu-sun5i.o
 sun6i-a31-ccu-y			+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
new file mode 100644
index 0000000000000..b5464d8083c8a
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ * Based on the D1 CCU driver:
+ *   Copyright (c) 2020 huangzhenwei at allwinnertech.com
+ *   Copyright (C) 2021 Samuel Holland <samuel at sholland.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+
+#include "ccu-sun55i-a523-r.h"
+
+static const struct clk_parent_data r_ahb_apb_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .fw_name = "pll-periph" },
+	{ .fw_name = "pll-audio" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
+				 r_ahb_apb_parents, 0x000,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
+				 r_ahb_apb_parents, 0x00c,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
+				 r_ahb_apb_parents, 0x010,
+				 0, 5,	/* M */
+				 24, 3,	/* mux */
+				 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
+				       r_ahb_apb_parents, 0x100,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				      0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
+				       r_ahb_apb_parents, 0x104,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				       0);
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
+				       r_ahb_apb_parents, 0x108,
+				       0, 0,	/* no M */
+				       1, 3,	/* P */
+				       4, 3,	/* mux */
+				       BIT(0),
+				       0);
+
+static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
+			 0x11c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_twd_clk,	"bus-r-twd", &r_apb0_clk.common.hw,
+			 0x12c, BIT(0), 0);
+
+static const struct clk_parent_data r_pwmctrl_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+};
+static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
+				  r_pwmctrl_parents, 0x130,
+				  24, 2,	/* mux */
+				  BIT(31),
+				  0);
+static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
+			 &r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
+
+/* SPI clock is /M/N (same as new MMC?) */
+static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
+			 &r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
+			 &r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
+			 &r_ahb_clk.common.hw, 0x17c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart0_clk, "bus-r-uart0",
+			 &r_apb1_clk.common.hw, 0x18c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_uart1_clk, "bus-r-uart1",
+			 &r_apb1_clk.common.hw, 0x18c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c0_clk, "bus-r-i2c0",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c1_clk, "bus-r-i2c1",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_i2c2_clk, "bus-r-i2c2",
+			 &r_apb1_clk.common.hw, 0x19c, BIT(2), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu0_clk, "bus-r-ppu0",
+			 &r_apb0_clk.common.hw, 0x1ac, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_ppu1_clk, "bus-r-ppu1",
+			 &r_apb0_clk.common.hw, 0x1ac, BIT(1), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpu_bist_clk, "bus-r-cpu-bist",
+			 &r_apb0_clk.common.hw, 0x1bc, BIT(0), 0);
+
+static const struct clk_parent_data r_ir_rx_parents[] = {
+	{ .fw_name = "losc" },
+	{ .fw_name = "hosc" },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
+				      r_ir_rx_parents, 0x1c0,
+				      0, 5,	/* M */
+				      24, 2,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+static SUNXI_CCU_GATE_HW(bus_r_ir_rx_clk, "bus-r-ir-rx",
+			 &r_apb0_clk.common.hw, 0x1cc, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HW(bus_r_dma_clk, "bus-r-dma",
+			 &r_apb0_clk.common.hw, 0x1dc, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_rtc_clk, "bus-r-rtc",
+			 &r_apb0_clk.common.hw, 0x20c, BIT(0), 0);
+static SUNXI_CCU_GATE_HW(bus_r_cpucfg_clk, "bus-r-cpucfg",
+			 &r_apb0_clk.common.hw, 0x22c, BIT(0), 0);
+
+static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
+	&r_ahb_clk.common,
+	&r_apb0_clk.common,
+	&r_apb1_clk.common,
+	&r_cpu_timer0.common,
+	&r_cpu_timer1.common,
+	&r_cpu_timer2.common,
+	&bus_r_timer_clk.common,
+	&bus_r_twd_clk.common,
+	&r_pwmctrl_clk.common,
+	&bus_r_pwmctrl_clk.common,
+	&bus_r_spi_clk.common,
+	&bus_r_spinlock_clk.common,
+	&bus_r_msgbox_clk.common,
+	&bus_r_uart0_clk.common,
+	&bus_r_uart1_clk.common,
+	&bus_r_i2c0_clk.common,
+	&bus_r_i2c1_clk.common,
+	&bus_r_i2c2_clk.common,
+	&bus_r_ppu0_clk.common,
+	&bus_r_ppu1_clk.common,
+	&bus_r_cpu_bist_clk.common,
+	&r_ir_rx_clk.common,
+	&bus_r_ir_rx_clk.common,
+	&bus_r_dma_clk.common,
+	&bus_r_rtc_clk.common,
+	&bus_r_cpucfg_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
+	.num	= CLK_NUMBER,
+	.hws	= {
+		[CLK_R_AHB]		= &r_ahb_clk.common.hw,
+		[CLK_R_APB0]		= &r_apb0_clk.common.hw,
+		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
+		[CLK_R_TIMER0]		= &r_cpu_timer0.common.hw,
+		[CLK_R_TIMER1]		= &r_cpu_timer1.common.hw,
+		[CLK_R_TIMER2]		= &r_cpu_timer2.common.hw,
+		[CLK_BUS_R_TIMER]	= &bus_r_timer_clk.common.hw,
+		[CLK_BUS_R_TWD]		= &bus_r_twd_clk.common.hw,
+		[CLK_R_PWMCTRL]		= &r_pwmctrl_clk.common.hw,
+		[CLK_BUS_R_PWMCTRL]	= &bus_r_pwmctrl_clk.common.hw,
+		[CLK_BUS_R_SPI]		= &bus_r_spi_clk.common.hw,
+		[CLK_BUS_R_SPINLOCK]	= &bus_r_spinlock_clk.common.hw,
+		[CLK_BUS_R_MSGBOX]	= &bus_r_msgbox_clk.common.hw,
+		[CLK_BUS_R_UART0]	= &bus_r_uart0_clk.common.hw,
+		[CLK_BUS_R_UART1]	= &bus_r_uart1_clk.common.hw,
+		[CLK_BUS_R_I2C0]	= &bus_r_i2c0_clk.common.hw,
+		[CLK_BUS_R_I2C1]	= &bus_r_i2c1_clk.common.hw,
+		[CLK_BUS_R_I2C2]	= &bus_r_i2c2_clk.common.hw,
+		[CLK_BUS_R_PPU0]	= &bus_r_ppu0_clk.common.hw,
+		[CLK_BUS_R_PPU1]	= &bus_r_ppu1_clk.common.hw,
+		[CLK_BUS_R_CPU_BIST]	= &bus_r_cpu_bist_clk.common.hw,
+		[CLK_R_IR_RX]		= &r_ir_rx_clk.common.hw,
+		[CLK_BUS_R_IR_RX]	= &bus_r_ir_rx_clk.common.hw,
+		[CLK_BUS_R_DMA]		= &bus_r_dma_clk.common.hw,
+		[CLK_BUS_R_RTC]		= &bus_r_rtc_clk.common.hw,
+		[CLK_BUS_R_CPUCFG]	= &bus_r_cpucfg_clk.common.hw,
+	},
+};
+
+static struct ccu_reset_map sun55i_a523_r_ccu_resets[] = {
+	[RST_BUS_R_TIMER]	= { 0x11c, BIT(16) },
+	[RST_BUS_R_TWD]		= { 0x12c, BIT(16) },
+	[RST_BUS_R_PWMCTRL]	= { 0x13c, BIT(16) },
+	[RST_BUS_R_SPI]		= { 0x15c, BIT(16) },
+	[RST_BUS_R_SPINLOCK]	= { 0x16c, BIT(16) },
+	[RST_BUS_R_MSGBOX]	= { 0x17c, BIT(16) },
+	[RST_BUS_R_UART0]	= { 0x18c, BIT(16) },
+	[RST_BUS_R_UART1]	= { 0x18c, BIT(17) },
+	[RST_BUS_R_I2C0]	= { 0x19c, BIT(16) },
+	[RST_BUS_R_I2C1]	= { 0x19c, BIT(17) },
+	[RST_BUS_R_I2C2]	= { 0x19c, BIT(18) },
+	[RST_BUS_R_PPU1]	= { 0x1ac, BIT(17) },
+	[RST_BUS_R_IR_RX]	= { 0x1cc, BIT(16) },
+	[RST_BUS_R_RTC]		= { 0x20c, BIT(16) },
+	[RST_BUS_R_CPUCFG]	= { 0x22c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_r_ccu_desc = {
+	.ccu_clks	= sun55i_a523_r_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_r_ccu_clks),
+
+	.hw_clks	= &sun55i_a523_r_hw_clks,
+
+	.resets		= sun55i_a523_r_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun55i_a523_r_ccu_resets),
+};
+
+static int sun55i_a523_r_ccu_probe(struct platform_device *pdev)
+{
+	void __iomem *reg;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_r_ccu_desc);
+}
+
+static const struct of_device_id sun55i_a523_r_ccu_ids[] = {
+	{ .compatible = "allwinner,sun55i-a523-r-ccu" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun55i_a523_r_ccu_ids);
+
+static struct platform_driver sun55i_a523_r_ccu_driver = {
+	.probe	= sun55i_a523_r_ccu_probe,
+	.driver	= {
+		.name			= "sun55i-a523-r-ccu",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sun55i_a523_r_ccu_ids,
+	},
+};
+module_platform_driver(sun55i_a523_r_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_DESCRIPTION("Support for the Allwinner A523 PRCM CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
new file mode 100644
index 0000000000000..d50f46ac4f3fe
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_R_H
+#define _CCU_SUN55I_A523_R_H
+
+#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
+
+#define CLK_NUMBER	(CLK_BUS_R_CPUCFG + 1)
+
+#endif /* _CCU_SUN55I_A523_R_H */
-- 
2.46.3



From sebastian.reichel at collabora.com  Thu Mar  6 16:48:22 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Fri, 7 Mar 2025 01:48:22 +0100
Subject: [PATCH 3/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3588
In-Reply-To: <8323ba9aba1155004bcd201b4fd7b2fa@manjaro.org>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-4-jonas@kwiboo.se>
 <8323ba9aba1155004bcd201b4fd7b2fa@manjaro.org>
Message-ID: <7pzama5c5u2voshlkougczic3mnqn4ezotdaqyflcjtb6k7myh@6biehccwcizx>

Hi,

On Thu, Mar 06, 2025 at 10:33:23PM +0100, Dragan Simic wrote:
> Hello Jonas,
> 
> On 2025-03-06 21:38, Jonas Karlman wrote:
> > Support for Rockchip RK3588 GMAC was added without use of the
> > DELAY_ENABLE macro to assist with enable/disable use of MAC rx/tx delay.
> > 
> > Change to use a variant of the DELAY_ENABLE macro to help disable MAC
> > delay when RGMII_ID/RXID/TXID is used.
> > 
> > Fixes: 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac
> > support for rk3588")
> > Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> > index 37eb86e4e325..79db81d68afd 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> > @@ -91,6 +91,10 @@ struct rk_priv_data {
> >  	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) |
> > \
> >  	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
> > 
> > +#define DELAY_ENABLE_BY_ID(soc, tx, rx, id) \
> > +	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE(id) :
> > soc##_GMAC_TXCLK_DLY_DISABLE(id)) | \
> > +	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE(id) :
> > soc##_GMAC_RXCLK_DLY_DISABLE(id)))
> > +
> >  #define PX30_GRF_GMAC_CON1		0x0904
> > 
> >  /* PX30_GRF_GMAC_CON1 */
> > @@ -1322,8 +1326,7 @@ static void rk3588_set_to_rgmii(struct
> > rk_priv_data *bsp_priv,
> >  		     RK3588_GMAC_CLK_RGMII_MODE(id));
> > 
> >  	regmap_write(bsp_priv->grf, RK3588_GRF_GMAC_CON7,
> > -		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
> > -		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
> > +		     DELAY_ENABLE_BY_ID(RK3588, tx_delay, rx_delay, id));
> > 
> >  	regmap_write(bsp_priv->grf, offset_con,
> >  		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
> 
> Thanks for this patch...  It's looking good to me, and good job
> spotting this issue!  Please, free to include:
> 
> Reviewed-by: Dragan Simic <dsimic at manjaro.org>

Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/3d02f75e/attachment.sig>

From andyshrk at 163.com  Thu Mar  6 16:48:55 2025
From: andyshrk at 163.com (Andy Yan)
Date: Fri, 7 Mar 2025 08:48:55 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <326B91E9-FB91-43C3-B98B-3EF079F313C6@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
 <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>
 <326B91E9-FB91-43C3-B98B-3EF079F313C6@gmail.com>
Message-ID: <545cc438.7e3.1956e13a3e2.Coremail.andyshrk@163.com>


Hi Piotr,
? 2025-03-06 22:28:08?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Piotr Oniszczuk <piotr.oniszczuk at gmail.com> w dniu 6 mar 2025, o godz. 15:08:
>> 
>> 
>> 
>>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 6 mar 2025, o godz. 13:15:
>>> 
>>> Hi Piotr,
>>> 
>>> 
>>> 
>>> Then when you DP cable plugin, you can run command as bellow to see if the driver detects the HPD:
>>> 
>>> # cat /sys/class/drm/card0-DP-1/status 
>>> connected
>>> # 
>>> 
>> 
>> 
>> Andy,
>> Thx!
>> 
>> With above changes i?m getting ?connected?.
>> Also it looks crtc gets reasonable mode: https://gist.github.com/warpme/d6220e3cc502086a4c95f05bd9f9cf0c
>> 
>> Still black screen however?
>>   
>
>some additional data point: /sys/kernel/debug/dri/1/vop2/summary 
>
>
>working hdmi:
>
>Video Port1: ACTIVE
>    Connector: HDMI-A-1
>        bus_format[0]: Unknown
>        output_mode[f] color_space[0]
>    Display mode: 1920x1080p60
>        clk[148500] real_clk[148500] type[48] flag[5]
>        H: 1920 2008 2052 2200
>        V: 1080 1084 1089 1125
>    Cluster0-win0: ACTIVE
>        win_id: 0
>        format: XR24 little-endian (0x34325258) glb_alpha[0xff]
>        rotate: xmirror: 0 ymirror: 0 rotate_90: 0 rotate_270: 0
>        zpos: 0
>        src: pos[0, 0] rect[1920 x 1080]
>        dst: pos[0, 0] rect[1920 x 1080]
>        buf[0]: addr: 0x00000000017e1000 pitch: 7680 offset: 0
>Video Port2: DISABLED
>
>
>
>
>non-working DP:
>
>Video Port1: DISABLED
>Video Port2: ACTIVE
>    Connector: DP-1
>        bus_format[100a]: RGB888_1X24
>        output_mode[f] color_space[0]
>    Display mode: 1920x1080p60
>        clk[148500] real_clk[148500] type[48] flag[5]
>        H: 1920 2008 2052 2200
>        V: 1080 1084 1089 1125
>    Cluster1-win0: ACTIVE
>        win_id: 1
>        format: XR24 little-endian (0x34325258) glb_alpha[0xff]
>        rotate: xmirror: 0 ymirror: 0 rotate_90: 0 rotate_270: 0
>        zpos: 0
>        src: pos[0, 0] rect[1920 x 1080]
>        dst: pos[0, 0] rect[1920 x 1080]
>        buf[0]: addr: 0x00000000007ed000 pitch: 7680 offset: 0

>

All dump information currently appears to be correct, so I'm temporarily unsure why
there is no display on the monitor.
Maybe try some plug and unplug for the DP cable, or try another cable or monitor?

It seems that this board uses a DP to HDMI converter? Does this transmitter need a driver?

I won't be at my computer over the next two or three days, so any further replies to your email
might have to wait until next week.



From patchwork-bot+netdevbpf at kernel.org  Thu Mar  6 16:50:38 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Fri, 07 Mar 2025 00:50:38 +0000
Subject: [PATCH net-next] net: stmmac: simplify phylink_suspend() and
 phylink_resume() calls
In-Reply-To: <E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk>
References: <E1tpQL1-005St4-Hn@rmk-PC.armlinux.org.uk>
Message-ID: <174130863899.1835493.10259048343165526348.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Tue, 04 Mar 2025 11:21:27 +0000 you wrote:
> Currently, the calls to phylink's suspend and resume functions are
> inside overly complex tests, and boil down to:
> 
> 	if (device_may_wakeup(priv->device) && priv->plat->pmt) {
> 		call phylink
> 	} else {
> 		call phylink and
> 		if (device_may_wakeup(priv->device))
> 			do something else
> 	}
> 
> [...]

Here is the summary with links:
  - [net-next] net: stmmac: simplify phylink_suspend() and phylink_resume() calls
    https://git.kernel.org/netdev/net-next/c/f732549eb303

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Thu Mar  6 16:50:40 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Fri, 07 Mar 2025 00:50:40 +0000
Subject: [PATCH net-next] net: stmmac: avoid shadowing global buf_sz
In-Reply-To: <E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk>
References: <E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk>
Message-ID: <174130864025.1835493.2395705293072394933.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Wed, 05 Mar 2025 17:54:16 +0000 you wrote:
> stmmac_rx() declares a local variable named "buf_sz" but there is also
> a global variable for a module parameter which is called the same. To
> avoid confusion, rename the local variable.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Here is the summary with links:
  - [net-next] net: stmmac: avoid shadowing global buf_sz
    https://git.kernel.org/netdev/net-next/c/876cfb20e889

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From kuba at kernel.org  Thu Mar  6 16:55:13 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Thu, 6 Mar 2025 16:55:13 -0800
Subject: [PATCH net-next v2] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250305111608.520042-1-danishanwar@ti.com>
References: <20250305111608.520042-1-danishanwar@ti.com>
Message-ID: <20250306165513.541ff46e@kernel.org>

On Wed, 5 Mar 2025 16:46:08 +0530 MD Danish Anwar wrote:
> + - ``FW_RTU_PKT_DROP``: Diagnostic error counter which increments when RTU drops a locally injected packet due to port being disabled or rule violation.
> + - ``FW_Q0_OVERFLOW``: TX overflow counter for queue0
> + - ``FW_Q1_OVERFLOW``: TX overflow counter for queue1
> + - ``FW_Q2_OVERFLOW``: TX overflow counter for queue2
> + - ``FW_Q3_OVERFLOW``: TX overflow counter for queue3
> + - ``FW_Q4_OVERFLOW``: TX overflow counter for queue4
> + - ``FW_Q5_OVERFLOW``: TX overflow counter for queue5
> + - ``FW_Q6_OVERFLOW``: TX overflow counter for queue6
> + - ``FW_Q7_OVERFLOW``: TX overflow counter for queue7
...

Thanks for the docs, it looks good. Now, do all of these get included
in the standard stats returned by icssg_ndo_get_stats64 ?
That's the primary source of information for the user regarding packet
loss.

>  	if (prueth->pa_stats) {
>  		for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) {
> -			reg = ICSSG_FW_STATS_BASE +
> -			      icssg_all_pa_stats[i].offset *
> -			      PRUETH_NUM_MACS + slice * sizeof(u32);
> +			reg = icssg_all_pa_stats[i].offset +
> +			      slice * sizeof(u32);
>  			regmap_read(prueth->pa_stats, reg, &val);
>  			emac->pa_stats[i] += val;

This gets called by icssg_ndo_get_stats64() which is under RCU 
protection and nothing else. I don't see any locking here, and
I hope the regmap doesn't sleep. cat /proc/net/dev to test.
You probably need to send some fixes to net.
-- 
pw-bot: cr


From andre.przywara at arm.com  Thu Mar  6 16:55:55 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 7 Mar 2025 00:55:55 +0000
Subject: [PATCH v2 08/15] arm64: dts: allwinner: Add Allwinner A523
 .dtsi file
In-Reply-To: <2646028.Lt9SDvczpP@jernej-laptop>
References: <20250304222309.29385-1-andre.przywara@arm.com>
	<20250304222309.29385-9-andre.przywara@arm.com>
	<2646028.Lt9SDvczpP@jernej-laptop>
Message-ID: <20250307005555.2c52199a@minigeek.lan>

On Wed, 05 Mar 2025 19:46:20 +0100
Jernej ?krabec <jernej.skrabec at gmail.com> wrote:

Hi,

> Dne torek, 4. marec 2025 ob 23:23:02 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> > The Allwinner A523, and its siblings A527 and T527, which share the same
> > die, are a new family of SoCs introduced in 2023. They features eight
> > Arm Cortex-A55 cores, and, among the other usual peripherals, a PCIe and
> > USB 3.0 controller.
> > 
> > Add the basic SoC devicetree .dtsi for the chip, describing the
> > fundamental peripherals: the cores, GIC, timer, RTC, CCU and pinctrl.
> > Also some other peripherals are fully compatible with previous IP, so
> > add the USB and MMC nodes as well.
> > The other peripherals will be added in the future, once we understand
> > their compatibility and DT requirements.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> >  .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
> >  1 file changed, 598 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> > 
> > diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> > new file mode 100644
> > index 0000000000000..01e662bdf5521
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> > @@ -0,0 +1,598 @@
> > +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> > +// Copyright (C) 2023-2024 Arm Ltd.
> > +

 ...

> > +
> > +			mmc2_pins: mmc2-pins {
> > +				pins = "PC1" ,"PC5", "PC6", "PC8", "PC9",
> > +				       "PC10", "PC11", "PC13", "PC14", "PC15",
> > +				       "PC16";  
> 
> I guess PC0 should be also included, for HS400 capable cards.

Sure, it doesn't conflict with much else (just NAND flash), so that's
no problem.

> With that fixed:
> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Many thanks for that!

Cheers,
Andre

> 
> Best regards,
> Jernej
> 



From andre.przywara at arm.com  Thu Mar  6 16:56:57 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:56:57 +0000
Subject: [PATCH v3 00/15] arm64: dts: allwinner: Add basic Allwinner A523 support
Message-ID: <20250307005712.16828-1-andre.przywara@arm.com>

Hi,

this in an update to the series introducing the basic DT support for the
Allwinner A523 SoC. It now comes with DTs for three boards, using
slightly different packages of that SoC.[1]
Functionality-wise it relies on the pinctrl[2] and clock[3] support
series, though there are no direct code dependency series between the
series. Two binding patches from there are required to pass dtbs_check,
git put their patch IDs in the footer below.
Compared to v2 only small fixes in the NMI controller driver: renaming
the struct to better reflect its new usage, add adding the DS pin to
the eMMC pingroup list. Adding accrued tags on the way, many thanks to
the diligent reviewers! More detailed changelog below.

The first patches add DT binding documentation for the most basic
peripherals, most of them actually being already supported, courtesy of
identical IP being used. This includes MMC and USB 2.0, so with the above
mentioned clock and pinctrl support this gives an already somewhat usable
mainline support for this new SoC family.
The watchdog is not completely compatible, but is an easy addition, so
this bit is included in here as well, the same is true for the NMI
controller, required for delivering PMIC interrupts.

The A523 features 8 Arm Cortex-A55 cores, organised in two clusters,
clocked separately, with different OPP limits, in some kind of
little/LITTLE configuration. The GPU is a Arm Mali G57 MC01, and the chip
also features a single PCIe 2.1 lane, sharing a PHY with some USB 3.1
controller - which means only one of the two can be used.
The rest of the SoC is the usual soup of multimedia SoC IP, with eDP
support and two Gigabit Ethernet MACs among the highlights.

The main feature is patch 08/15, which adds the SoC .dtsi. This for now
is limited to the parts that are supported and could be tested. Compared
to v1 we now have some basic TF-A support, so the PSCI nodes are in now.

The final patches add basic support for the Avaota-A1 router board, the
X96QPro+ TV box, and the Radxa A5E development board.

The mainline firmware side in general is coming together now: we have
basic U-Boot support working (including MMC and USB), most importantly
with proper DRAM support, so no more binary blobs, and some basic TF-A
support.

Please have a look at those DT bits here, ideally compare them to the
available user manual, and test them if you have access to hardware.

Based on v6.14-rc1.
I pushed a branch with all the three series combined here:
https://github.com/apritzel/linux/commits/a523-v3/

Cheers,
Andre

Changelog v2 .. v3:
- split NMI controller register offset into sub-struct
- properly align NMI controller data definition
- adding ACKs from Rob and Jernej (with thanks!)

Changelog v1 .. v2:
- drop USB, I2C, RTC binding patches: already merged
- add tags from reviewers (with thanks!)
- drop unrelated deprecation comment from MMC binding patch
- drop fallback compatible for NMI controller, stands on its own now
- adjust PHY binding to merged A100 binding (dropping tag)
- .dtsi: add secondary cores
- .dtsi: enable PSCI
- .dtsi: move 32K oscillator to board .dts files
- .dtsi: adjust CCU source clocks
- .dtsi: add MMC1 node (typcially for SDIO WiFi)
- .dtsi: add remaining UARTs
- .dtsi: add remaing I2C devices
- add two new board .dts files
- add DT bindings for those two new board names
- avaota.dts: drop reserved memory from (TF-A now in SRAM)
- avaota.dts: drop SD card dummy supply node
- avaota.dts: add eMMC node (shipped on most boards)
- avaota.dts: fix OTG mode, explain situation
- add Chameleon .dts file (depends on YuzukiHD vendor name patch)

[1] https://linux-sunxi.org/A523#Family_of_sun55iw3
[2] https://lore.kernel.org/linux-sunxi/20250306235827.4895-1-andre.przywara at arm.com/T/#u
[3] https://lore.kernel.org/linux-sunxi/20250307002628.10684-1-andre.przywara at arm.com/T/#u

Andre Przywara (15):
  dt-bindings: mmc: sunxi: Simplify compatible string listing
  dt-bindings: mmc: sunxi: add compatible strings for Allwinner A523
  dt-bindings: watchdog: sunxi: add Allwinner A523 compatible string
  watchdog: sunxi_wdt: Add support for Allwinner A523
  dt-bindings: irq: sun7i-nmi: document the Allwinner A523 NMI
    controller
  irqchip/sunxi-nmi: Support Allwinner A523 NMI controller
  dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
  arm64: dts: allwinner: Add Allwinner A523 .dtsi file
  dt-bindings: vendor-prefixes: Add YuzukiHD name
  dt-bindings: arm: sunxi: Add new board names for A523 generation
  arm64: dts: allwinner: a523: add Avaota-A1 router support
  arm64: dts: allwinner: a523: add X96Q-Pro+ support
  arm64: dts: allwinner: a523: add Radxa A5E support
  dt-bindings: arm: sunxi: Add YuzukiHD Chameleon board name
  arm64: dts: allwinner: h616: add YuzukiHD Chameleon support

 .../devicetree/bindings/arm/sunxi.yaml        |  20 +
 .../allwinner,sun7i-a20-sc-nmi.yaml           |   1 +
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml |  38 +-
 .../phy/allwinner,sun50i-a64-usb-phy.yaml     |   4 +-
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 .../watchdog/allwinner,sun4i-a10-wdt.yaml     |   2 +
 arch/arm64/boot/dts/allwinner/Makefile        |   4 +
 .../sun50i-h618-yuzukihd-chameleon.dts        | 222 +++++++
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
 .../dts/allwinner/sun55i-a527-radxa-a5e.dts   | 299 +++++++++
 .../dts/allwinner/sun55i-h728-x96qpro+.dts    | 287 +++++++++
 .../dts/allwinner/sun55i-t527-avaota-a1.dts   | 308 +++++++++
 drivers/irqchip/irq-sunxi-nmi.c               |  76 ++-
 drivers/watchdog/sunxi_wdt.c                  |  11 +
 14 files changed, 1821 insertions(+), 51 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts


base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
prerequisite-patch-id: 5b8a883819d2f3dfc975735a855291cb8b02dd39
prerequisite-patch-id: 26d4fd19d9e9cf345261bbad4b8c3697fe773e7c
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:56:58 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:56:58 +0000
Subject: [PATCH v3 01/15] dt-bindings: mmc: sunxi: Simplify compatible string listing
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-2-andre.przywara@arm.com>

New Allwinner SoCs only occasionally update their MMC IP, leading to many
pairs of compatible strings, though there are sometimes a number of them
being compatible with one particular SoC.

Collate the compatible string listing in the binding, to group those
being compatible together. This makes the list more readable, and allows
for easier addition of new SoC's MMC devices.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 36 ++++++++-----------
 1 file changed, 14 insertions(+), 22 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 0ccd632d56200..8e4c77b7e4ab9 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -30,38 +30,30 @@ properties:
       - const: allwinner,sun50i-a100-emmc
       - const: allwinner,sun50i-a100-mmc
       - items:
-          - const: allwinner,sun8i-a83t-mmc
+          - enum:
+              - allwinner,sun8i-a83t-mmc
+              - allwinner,suniv-f1c100s-mmc
           - const: allwinner,sun7i-a20-mmc
       - items:
-          - const: allwinner,sun8i-r40-emmc
+          - enum:
+              - allwinner,sun8i-r40-emmc
+              - allwinner,sun50i-h5-emmc
+              - allwinner,sun50i-h6-emmc
           - const: allwinner,sun50i-a64-emmc
       - items:
-          - const: allwinner,sun8i-r40-mmc
+          - enum:
+              - allwinner,sun8i-r40-mmc
+              - allwinner,sun50i-h5-mmc
+              - allwinner,sun50i-h6-mmc
           - const: allwinner,sun50i-a64-mmc
       - items:
-          - const: allwinner,sun50i-h5-emmc
-          - const: allwinner,sun50i-a64-emmc
-      - items:
-          - const: allwinner,sun50i-h5-mmc
-          - const: allwinner,sun50i-a64-mmc
-      - items:
-          - const: allwinner,sun50i-h6-emmc
-          - const: allwinner,sun50i-a64-emmc
-      - items:
-          - const: allwinner,sun50i-h6-mmc
-          - const: allwinner,sun50i-a64-mmc
-      - items:
-          - const: allwinner,sun20i-d1-emmc
-          - const: allwinner,sun50i-a100-emmc
-      - items:
-          - const: allwinner,sun50i-h616-emmc
+          - enum:
+              - allwinner,sun20i-d1-emmc
+              - allwinner,sun50i-h616-emmc
           - const: allwinner,sun50i-a100-emmc
       - items:
           - const: allwinner,sun50i-h616-mmc
           - const: allwinner,sun50i-a100-mmc
-      - items:
-          - const: allwinner,suniv-f1c100s-mmc
-          - const: allwinner,sun7i-a20-mmc
 
   reg:
     maxItems: 1
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:56:59 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:56:59 +0000
Subject: [PATCH v3 02/15] dt-bindings: mmc: sunxi: add compatible strings for Allwinner A523
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-3-andre.przywara@arm.com>

The Allwinner A523 uses the same MMC IP as the D1.

Introduce the new specific compatible strings, and use them with
fallbacks to the D1 strings.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml      | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index 8e4c77b7e4ab9..9f3b1edacaa02 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -50,10 +50,14 @@ properties:
           - enum:
               - allwinner,sun20i-d1-emmc
               - allwinner,sun50i-h616-emmc
+              - allwinner,sun55i-a523-emmc
           - const: allwinner,sun50i-a100-emmc
       - items:
           - const: allwinner,sun50i-h616-mmc
           - const: allwinner,sun50i-a100-mmc
+      - items:
+          - const: allwinner,sun55i-a523-mmc
+          - const: allwinner,sun20i-d1-mmc
 
   reg:
     maxItems: 1
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:00 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:00 +0000
Subject: [PATCH v3 03/15] dt-bindings: watchdog: sunxi: add Allwinner A523 compatible string
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-4-andre.przywara@arm.com>

The Allwinner A523 SoC features a watchdog similar to the one used in
previous SoCs, but moves some registers around (by just one word), making
it incompatible to existing IPs.

Add the new name to the list of compatible string, and also to the list
of IP requiring two clock inputs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml   | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index 64c8f73938099..b35ac03d51727 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -32,6 +32,7 @@ properties:
       - items:
           - const: allwinner,sun20i-d1-wdt-reset
           - const: allwinner,sun20i-d1-wdt
+      - const: allwinner,sun55i-a523-wdt
 
   reg:
     maxItems: 1
@@ -60,6 +61,7 @@ if:
           - allwinner,sun20i-d1-wdt-reset
           - allwinner,sun50i-r329-wdt
           - allwinner,sun50i-r329-wdt-reset
+          - allwinner,sun55i-a523-wdt
 
 then:
   properties:
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:01 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:01 +0000
Subject: [PATCH v3 04/15] watchdog: sunxi_wdt: Add support for Allwinner A523
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-5-andre.przywara@arm.com>

The Allwinner A523 SoC comes with a watchdog very similar to the ones in
the previous Allwinner SoCs, but oddly enough moves the first half of its
registers up by one word. Since we have different offsets for these
registers across the other SoCs as well, this can simply be modelled by
just stating the new offsets in our per-SoC struct.
The rest of the IP is the same as in the D1, although the A523 moves its
watchdog to a separate MMIO frame, so it's not embedded in the timer
anymore. The driver can be ignorant of this, because the DT will take
care of this.

Add a new struct for the A523, specifying the SoC-specific details, and
tie the new DT compatible string to it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 drivers/watchdog/sunxi_wdt.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
index b85354a995826..b6c761acc3de6 100644
--- a/drivers/watchdog/sunxi_wdt.c
+++ b/drivers/watchdog/sunxi_wdt.c
@@ -236,10 +236,21 @@ static const struct sunxi_wdt_reg sun20i_wdt_reg = {
 	.wdt_key_val = 0x16aa0000,
 };
 
+static const struct sunxi_wdt_reg sun55i_wdt_reg = {
+	.wdt_ctrl = 0x0c,
+	.wdt_cfg = 0x10,
+	.wdt_mode = 0x14,
+	.wdt_timeout_shift = 4,
+	.wdt_reset_mask = 0x03,
+	.wdt_reset_val = 0x01,
+	.wdt_key_val = 0x16aa0000,
+};
+
 static const struct of_device_id sunxi_wdt_dt_ids[] = {
 	{ .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg },
 	{ .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg },
 	{ .compatible = "allwinner,sun20i-d1-wdt", .data = &sun20i_wdt_reg },
+	{ .compatible = "allwinner,sun55i-a523-wdt", .data = &sun55i_wdt_reg },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:02 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:02 +0000
Subject: [PATCH v3 05/15] dt-bindings: irq: sun7i-nmi: document the Allwinner A523 NMI controller
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-6-andre.przywara@arm.com>

The Allwinner A523 SoC contains an NMI controller very close to the one
used in the recent Allwinner SoCs, but it adds another bit that needs to
be toggled to actually deliver the IRQs. Sigh.

Add the A523 specific name to the list of allowed compatible strings.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
index f49b43f45f3d9..06e3621a8c06c 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
@@ -26,6 +26,7 @@ properties:
         deprecated: true
       - const: allwinner,sun7i-a20-sc-nmi
       - const: allwinner,sun9i-a80-nmi
+      - const: allwinner,sun55i-a523-nmi
       - items:
           - enum:
               - allwinner,sun8i-v3s-nmi
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:03 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:03 +0000
Subject: [PATCH v3 06/15] irqchip/sunxi-nmi: Support Allwinner A523 NMI controller
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-7-andre.przywara@arm.com>

The NMI controller in the Allwinner A523 is almost compatible to the
previous versions of this IP, but requires the extra bit 31 to be set in
the enable register to actually report the NMI.

Add a mask to allow such an enable bit to be specified, and add this to
the per-SoC data structure. As this struct was just for different register
offsets so far, it was consequently named "reg_offs", which is now no
longer applicable, so rename this to the more generic "data" on the way,
and move the existing offsets into a struct of its own.

Also add the respective Allwinner A523 compatible string, and set bit 31
in its enable mask, to add support for this SoC.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/irqchip/irq-sunxi-nmi.c | 76 ++++++++++++++++++++-------------
 1 file changed, 47 insertions(+), 29 deletions(-)

diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 0b43121520243..b05904a147088 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -48,28 +48,38 @@ enum {
 	SUNXI_SRC_TYPE_EDGE_RISING,
 };
 
-struct sunxi_sc_nmi_reg_offs {
-	u32 ctrl;
-	u32 pend;
-	u32 enable;
+struct sunxi_sc_nmi_data {
+	struct {
+		u32 ctrl;
+		u32 pend;
+		u32 enable;
+	} reg_offs;
+	u32 enable_val;
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = {
-	.ctrl	= SUN6I_NMI_CTRL,
-	.pend	= SUN6I_NMI_PENDING,
-	.enable	= SUN6I_NMI_ENABLE,
+static const struct sunxi_sc_nmi_data sun6i_data __initconst = {
+	.reg_offs.ctrl		= SUN6I_NMI_CTRL,
+	.reg_offs.pend		= SUN6I_NMI_PENDING,
+	.reg_offs.enable	= SUN6I_NMI_ENABLE,
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun7i_reg_offs __initconst = {
-	.ctrl	= SUN7I_NMI_CTRL,
-	.pend	= SUN7I_NMI_PENDING,
-	.enable	= SUN7I_NMI_ENABLE,
+static const struct sunxi_sc_nmi_data sun7i_data __initconst = {
+	.reg_offs.ctrl		= SUN7I_NMI_CTRL,
+	.reg_offs.pend		= SUN7I_NMI_PENDING,
+	.reg_offs.enable	= SUN7I_NMI_ENABLE,
 };
 
-static const struct sunxi_sc_nmi_reg_offs sun9i_reg_offs __initconst = {
-	.ctrl	= SUN9I_NMI_CTRL,
-	.pend	= SUN9I_NMI_PENDING,
-	.enable	= SUN9I_NMI_ENABLE,
+static const struct sunxi_sc_nmi_data sun9i_data __initconst = {
+	.reg_offs.ctrl		= SUN9I_NMI_CTRL,
+	.reg_offs.pend		= SUN9I_NMI_PENDING,
+	.reg_offs.enable	= SUN9I_NMI_ENABLE,
+};
+
+static const struct sunxi_sc_nmi_data sun55i_a523_data __initconst = {
+	.reg_offs.ctrl		= SUN9I_NMI_CTRL,
+	.reg_offs.pend		= SUN9I_NMI_PENDING,
+	.reg_offs.enable	= SUN9I_NMI_ENABLE,
+	.enable_val		= BIT(31),
 };
 
 static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
@@ -143,7 +153,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
 }
 
 static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
-					const struct sunxi_sc_nmi_reg_offs *reg_offs)
+					const struct sunxi_sc_nmi_data *data)
 {
 	struct irq_domain *domain;
 	struct irq_chip_generic *gc;
@@ -186,27 +196,28 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
 	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit;
 	gc->chip_types[0].chip.irq_eoi		= irq_gc_ack_set_bit;
 	gc->chip_types[0].chip.irq_set_type	= sunxi_sc_nmi_set_type;
-	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
+	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED |
+						  IRQCHIP_EOI_IF_HANDLED |
 						  IRQCHIP_SKIP_SET_WAKE;
-	gc->chip_types[0].regs.ack		= reg_offs->pend;
-	gc->chip_types[0].regs.mask		= reg_offs->enable;
-	gc->chip_types[0].regs.type		= reg_offs->ctrl;
+	gc->chip_types[0].regs.ack		= data->reg_offs.pend;
+	gc->chip_types[0].regs.mask		= data->reg_offs.enable;
+	gc->chip_types[0].regs.type		= data->reg_offs.ctrl;
 
 	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;
 	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_set_bit;
 	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
 	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit;
 	gc->chip_types[1].chip.irq_set_type	= sunxi_sc_nmi_set_type;
-	gc->chip_types[1].regs.ack		= reg_offs->pend;
-	gc->chip_types[1].regs.mask		= reg_offs->enable;
-	gc->chip_types[1].regs.type		= reg_offs->ctrl;
+	gc->chip_types[1].regs.ack		= data->reg_offs.pend;
+	gc->chip_types[1].regs.mask		= data->reg_offs.enable;
+	gc->chip_types[1].regs.type		= data->reg_offs.ctrl;
 	gc->chip_types[1].handler		= handle_edge_irq;
 
 	/* Disable any active interrupts */
-	sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
+	sunxi_sc_nmi_write(gc, data->reg_offs.enable, data->enable_val);
 
 	/* Clear any pending NMI interrupts */
-	sunxi_sc_nmi_write(gc, reg_offs->pend, SUNXI_NMI_IRQ_BIT);
+	sunxi_sc_nmi_write(gc, data->reg_offs.pend, SUNXI_NMI_IRQ_BIT);
 
 	irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain);
 
@@ -221,20 +232,27 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
 static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
 					struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun6i_data);
 }
 IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init);
 
 static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
 					struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun7i_data);
 }
 IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
 
 static int __init sun9i_nmi_irq_init(struct device_node *node,
 				     struct device_node *parent)
 {
-	return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
+	return sunxi_sc_nmi_irq_init(node, &sun9i_data);
 }
 IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);
+
+static int __init sun55i_nmi_irq_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	return sunxi_sc_nmi_irq_init(node, &sun55i_a523_data);
+}
+IRQCHIP_DECLARE(sun55i_nmi, "allwinner,sun55i-a523-nmi", sun55i_nmi_irq_init);
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:04 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:04 +0000
Subject: [PATCH v3 07/15] dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-8-andre.przywara@arm.com>

The Allwinner A523 SoC contains a USB-2.0 PHY fully compatible to the
one used in the D1/T113s SoCs. This PHY controls the two USB-2.0 ports,
there is a separate and quite different PHY for the USB-3.0 port.

Add the new compatible string, with a fallback to the D1 version.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
index 21209126ed008..580c3296a18d7 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
@@ -20,7 +20,9 @@ properties:
           - allwinner,sun20i-d1-usb-phy
           - allwinner,sun50i-a64-usb-phy
       - items:
-          - const: allwinner,sun50i-a100-usb-phy
+          - enum:
+              - allwinner,sun50i-a100-usb-phy
+              - allwinner,sun55i-a523-usb-phy
           - const: allwinner,sun20i-d1-usb-phy
 
   reg:
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:05 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:05 +0000
Subject: [PATCH v3 08/15] arm64: dts: allwinner: Add Allwinner A523 .dtsi file
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-9-andre.przywara@arm.com>

The Allwinner A523, and its siblings A527 and T527, which share the same
die, are a new family of SoCs introduced in 2023. They features eight
Arm Cortex-A55 cores, and, among the other usual peripherals, a PCIe and
USB 3.0 controller.

Add the basic SoC devicetree .dtsi for the chip, describing the
fundamental peripherals: the cores, GIC, timer, RTC, CCU and pinctrl.
Also some other peripherals are fully compatible with previous IP, so
add the USB and MMC nodes as well.
The other peripherals will be added in the future, once we understand
their compatibility and DT requirements.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 598 ++++++++++++++++++
 1 file changed, 598 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
new file mode 100644
index 0000000000000..ee485899ba0af
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2023-2024 Arm Ltd.
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun55i-a523-ccu.h>
+#include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-ccu.h>
+#include <dt-bindings/reset/sun55i-a523-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x000>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 100 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x100>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 200 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x200>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 300 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x300>;
+			enable-method = "psci";
+		};
+
+		cpu4: cpu at 400 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x400>;
+			enable-method = "psci";
+		};
+
+		cpu5: cpu at 500 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x500>;
+			enable-method = "psci";
+		};
+
+		cpu6: cpu at 600 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x600>;
+			enable-method = "psci";
+		};
+
+		cpu7: cpu at 700 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x700>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	pmu {
+		compatible = "arm,cortex-a55-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		arm,no-tick-in-suspend;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x0 0x40000000>;
+
+		pio: pinctrl at 2000000 {
+			compatible = "allwinner,sun55i-a523-pinctrl";
+			reg = <0x2000000 0x800>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc CLK_OSC32K>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			mmc0_pins: mmc0-pins {
+				pins = "PF0" ,"PF1", "PF2", "PF3", "PF4", "PF5";
+				allwinner,pinmux = <2>;
+				function = "mmc0";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			/omit-if-no-ref/
+			mmc1_pins: mmc1-pins {
+				pins = "PG0" ,"PG1", "PG2", "PG3", "PG4", "PG5";
+				allwinner,pinmux = <2>;
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			mmc2_pins: mmc2-pins {
+				pins = "PC0", "PC1" ,"PC5", "PC6", "PC8",
+				       "PC9", "PC10", "PC11", "PC13", "PC14",
+				       "PC15", "PC16";
+				allwinner,pinmux = <3>;
+				function = "mmc2";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			uart0_pb_pins: uart0-pb-pins {
+				pins = "PB9", "PB10";
+				allwinner,pinmux = <2>;
+				function = "uart0";
+			};
+		};
+
+		ccu: clock-controller at 2001000 {
+			compatible = "allwinner,sun55i-a523-ccu";
+			reg = <0x02001000 0x1000>;
+			clocks = <&osc24M>, <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>, <&rtc CLK_OSC32K_FANOUT>;
+			clock-names = "hosc", "losc",
+				      "iosc", "losc-fanout";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mmc0: mmc at 4020000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04020000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc at 4021000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04021000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc1_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc2: mmc at 4022000 {
+			compatible = "allwinner,sun55i-a523-mmc",
+				     "allwinner,sun20i-d1-mmc";
+			reg = <0x04022000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC2>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc2_pins>;
+			status = "disabled";
+
+			max-frequency = <150000000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			cap-sdio-irq;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		wdt: watchdog at 2050000 {
+			compatible = "allwinner,sun55i-a523-wdt";
+			reg = <0x2050000 0x20>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+			clock-names = "hosc", "losc";
+			status = "okay";
+		};
+
+		uart0: serial at 2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500000 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial at 2500400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500400 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial at 2500800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500800 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial at 2500c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500c00 0x400>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			status = "disabled";
+		};
+
+		uart4: serial at 2501000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501000 0x400>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART4>;
+			resets = <&ccu RST_BUS_UART4>;
+			status = "disabled";
+		};
+
+		uart5: serial at 2501400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501400 0x400>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART5>;
+			resets = <&ccu RST_BUS_UART5>;
+			status = "disabled";
+		};
+
+		uart6: serial at 2501800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501800 0x400>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART6>;
+			resets = <&ccu RST_BUS_UART6>;
+			status = "disabled";
+		};
+
+		uart7: serial at 2501c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02501c00 0x400>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART7>;
+			resets = <&ccu RST_BUS_UART7>;
+			status = "disabled";
+		};
+
+		i2c0: i2c at 2502000 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502000 0x400>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C0>;
+			resets = <&ccu RST_BUS_I2C0>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: i2c at 2502400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502400 0x400>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C1>;
+			resets = <&ccu RST_BUS_I2C1>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c2: i2c at 2502800 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502800 0x400>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C2>;
+			resets = <&ccu RST_BUS_I2C2>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c3: i2c at 2502c00 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2502c00 0x400>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C3>;
+			resets = <&ccu RST_BUS_I2C3>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c4: i2c at 2503000 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2503000 0x400>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C4>;
+			resets = <&ccu RST_BUS_I2C4>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c5: i2c at 2503400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x2503400 0x400>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C5>;
+			resets = <&ccu RST_BUS_I2C5>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		gic: interrupt-controller at 3400000 {
+			compatible = "arm,gic-v3";
+			#address-cells = <1>;
+			#interrupt-cells = <3>;
+			#size-cells = <1>;
+			ranges;
+			interrupt-controller;
+			reg = <0x3400000 0x10000>,
+			      <0x3460000 0x100000>;
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			dma-noncoherent;
+
+			its: msi-controller at 3440000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x3440000 0x20000>;
+				msi-controller;
+				#msi-cells = <1>;
+				dma-noncoherent;
+			};
+		};
+
+		usb_otg: usb at 4100000 {
+			compatible = "allwinner,sun55i-a523-musb",
+				     "allwinner,sun8i-a33-musb";
+			reg = <0x4100000 0x400>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "mc";
+			clocks = <&ccu CLK_BUS_OTG>;
+			resets = <&ccu RST_BUS_OTG>;
+			extcon = <&usbphy 0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		usbphy: phy at 4100400 {
+			compatible = "allwinner,sun55i-a523-usb-phy",
+				     "allwinner,sun20i-d1-usb-phy";
+			reg = <0x4100400 0x100>,
+			      <0x4101800 0x100>,
+			      <0x4200800 0x100>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1";
+			clocks = <&osc24M>,
+				 <&osc24M>;
+			clock-names = "usb0_phy",
+				      "usb1_phy";
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>;
+			reset-names = "usb0_reset",
+				      "usb1_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
+		ehci0: usb at 4101000 {
+			compatible = "allwinner,sun55i-a523-ehci",
+				     "generic-ehci";
+			reg = <0x4101000 0x100>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_BUS_EHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>,
+				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci0: usb at 4101400 {
+			compatible = "allwinner,sun55i-a523-ohci",
+				     "generic-ohci";
+			reg = <0x4101400 0x100>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci1: usb at 4200000 {
+			compatible = "allwinner,sun55i-a523-ehci",
+				     "generic-ehci";
+			reg = <0x4200000 0x100>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_BUS_EHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>,
+				 <&ccu RST_BUS_EHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb at 4200400 {
+			compatible = "allwinner,sun55i-a523-ohci",
+				     "generic-ohci";
+			reg = <0x4200400 0x100>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		r_ccu: clock-controller at 7010000 {
+			compatible = "allwinner,sun55i-a523-r-ccu";
+			reg = <0x7010000 0x250>;
+			clocks = <&osc24M>,
+				 <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>,
+				 <&ccu CLK_PLL_PERIPH0_200M>,
+				 <&ccu CLK_PLL_AUDIO0_4X>;
+			clock-names = "hosc",
+				      "losc",
+				      "iosc",
+				      "pll-periph",
+				      "pll-audio";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		nmi_intc: interrupt-controller at 7010320 {
+			compatible = "allwinner,sun55i-a523-nmi";
+			reg = <0x07010320 0xc>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		r_pio: pinctrl at 7022000 {
+			compatible = "allwinner,sun55i-a523-r-pinctrl";
+			reg = <0x7022000 0x800>;
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB0>,
+				 <&osc24M>,
+				 <&rtc CLK_OSC32K>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			r_i2c_pins: r-i2c-pins {
+				pins = "PL0" ,"PL1";
+				allwinner,pinmux = <2>;
+				function = "r_i2c0";
+			};
+		};
+
+		r_i2c0: i2c at 7081400 {
+			compatible = "allwinner,sun55i-a523-i2c",
+				     "allwinner,sun8i-v536-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x07081400 0x400>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_BUS_R_I2C0>;
+			resets = <&r_ccu RST_BUS_R_I2C0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&r_i2c_pins>;
+			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		rtc: rtc at 7090000 {
+			compatible = "allwinner,sun55i-a523-rtc",
+				     "allwinner,sun50i-r329-rtc";
+			reg = <0x7090000 0x400>;
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_BUS_R_RTC>,
+				 <&osc24M>,
+				 <&r_ccu CLK_R_AHB>;
+			clock-names = "bus", "hosc", "ahb";
+			#clock-cells = <1>;
+		};
+	};
+};
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:06 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:06 +0000
Subject: [PATCH v3 09/15] dt-bindings: vendor-prefixes: Add YuzukiHD name
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-10-andre.przywara@arm.com>

YuzukiHD provides Open Source Hardware designs, and also offers
ready-made builds of them: https://github.com/YuzukiHD

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 5079ca6ce1d1e..8c0991e002ee8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1737,6 +1737,8 @@ patternProperties:
     description: Shenzhen Yashi Changhua Intelligent Technology Co., Ltd.
   "^ysoft,.*":
     description: Y Soft Corporation a.s.
+  "^yuzukihd,.*":
+    description: YuzukiHD Open Source Hardware
   "^zarlink,.*":
     description: Zarlink Semiconductor
   "^zealz,.*":
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:07 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:07 +0000
Subject: [PATCH v3 10/15] dt-bindings: arm: sunxi: Add new board names for A523 generation
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-11-andre.przywara@arm.com>

The new Allwinner A523 SoC family comes in different packages, though
they all share the same die, and so the devicetree bindings.

Add three board names that use a version from this SoC family:
- The Avaota A1: an Open Source hardware router board.
- The Radxa Cubie A5E: a typical development board
- The X96QPro+: a TV box

Add their compatible name to the list.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 046536d02706f..80096819fda91 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -840,6 +840,11 @@ properties:
           - const: allwinner,r7-tv-dongle
           - const: allwinner,sun5i-a10s
 
+      - description: Radxa Cubie A5E
+        items:
+          - const: radxa,cubie-a5e
+          - const: allwinner,sun55i-a527
+
       - description: Remix Mini PC
         items:
           - const: jide,remix-mini-pc
@@ -961,6 +966,11 @@ properties:
           - const: hechuang,x96-mate
           - const: allwinner,sun50i-h616
 
+      - description: X96Q Pro+
+        items:
+          - const: amediatech,x96q-pro-plus
+          - const: allwinner,sun55i-h728
+
       - description: Xunlong OrangePi
         items:
           - const: xunlong,orangepi
@@ -1076,4 +1086,9 @@ properties:
           - const: xunlong,orangepi-zero3
           - const: allwinner,sun50i-h618
 
+      - description: YuzukiHD Avaota A1
+        items:
+          - const: yuzukihd,avaota-a1
+          - const: allwinner,sun55i-t527
+
 additionalProperties: true
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:08 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:08 +0000
Subject: [PATCH v3 11/15] arm64: dts: allwinner: a523: add Avaota-A1 router support
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-12-andre.przywara@arm.com>

The Avaota A1 router board is an Open Source hardware board, designed
by YuzukiHD. Pine64 produces some boards and sells them. It uses the
Allwinner A527 or T527 SoC, and comes with the following features:
  - Eight ARM Cortex-A55 cores, Mali-G57 MC1 GPU
  - 1GiB/2GiB/4GiB LPDDR4 DRAM
  - AXP717 + AXP323 PMIC
  - Raspberry-Pi-2 compatible GPIO header
  - 1 USB 2.0 type A host port, 1 USB 3.0 type A host post
  - 1 USB 2.0 type C port (OTG + serial debug)
  - MicroSD slot
  - eMMC between 16 and 128 GiB
  - on-board 16MiB bootable SPI NOR flash
  - two 1Gbps Ethernet ports (via RTL8211F PHYs)
  - HDMI port
  - DP port
  - camera and LCD connectors
  - 3.5mm headphone jack
  - (yet) unsupported WiFi/BT chip
  - 1.3" LC display, connected via SPI
  - 12 V barrel plug for power supply

Add the devicetree file describing the currently supported features.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-t527-avaota-a1.dts   | 308 ++++++++++++++++++
 2 files changed, 309 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 00bed412ee31c..0d678a7499e3c 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,3 +52,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts
new file mode 100644
index 0000000000000..85a546aecdbe1
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2024 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Avaota A1";
+	compatible = "yuzukihd,avaota-a1", "allwinner,sun55i-t527";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc12v: vcc12v {
+		/* DC input jack */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-12v";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the 12V->5V regulator */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc12v>;
+		regulator-always-on;
+	};
+
+	reg_usb_vbus: vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc5v>;
+		gpio = <&pio 8 12 GPIO_ACTIVE_HIGH>;	/* PI12 */
+		enable-active-high;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_cldo3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	status = "okay";
+};
+
+&mmc2 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	non-removable;
+	vmmc-supply = <&reg_cldo3>;
+	vqmmc-supply = <&reg_cldo1>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_dcdc4>;
+	vcc-pe-supply = <&reg_dcdc4>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_dcdc4>;
+	vcc-pj-supply = <&reg_dcdc4>;
+	vcc-pk-supply = <&reg_bldo3>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 35 {
+		compatible = "x-powers,axp717";
+		reg = <0x35>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.4 GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1160000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vdd-io";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				/* not connected */
+			};
+
+			reg_aldo3: aldo3 {
+				/* supplies the I2C pins for this PMIC */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pl-pm";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-wifi-lvds";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-dram-1v8";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-cvp-pk-vid1v8";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pc";
+			};
+
+			reg_cldo2: cldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-efuse";
+			};
+
+			reg_cldo3: cldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-io-mmc-spi-ana";
+			};
+
+			reg_cldo4: cldo4 {
+				/* not connected */
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				/* not connected */
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			/* Some RISC-V management core related voltage */
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-dnr";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	 /*
+	  * The CC pins of the USB-C port have two pull-down resistors
+	  * connected to GND, which fixes this port to a peripheral role.
+	  * There is a regulator, controlled by a GPIO, to provide VBUS power
+	  * to the port, and a VBUSDET GPIO, to detect externally provided
+	  * power, but without the CC pins there is no real way to do a
+	  * runtime role detection.
+	  */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb0_vbus-supply = <&reg_usb_vbus>;
+	usb0_vbus_det-gpios = <&pio 8 13 GPIO_ACTIVE_HIGH>; /* PI13 */
+	status = "okay";
+};
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:09 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:09 +0000
Subject: [PATCH v3 12/15] arm64: dts: allwinner: a523: add X96Q-Pro+ support
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-13-andre.przywara@arm.com>

The X96QPro+ is a TV box using the Allwinner H728 SoC. That SoC seems to
be a package variant of the A523 family, at least it uses the same SoC
ID and is compatible as far as we can assess.

It comes with the following specs:
  - Allwinner H728 SoC: 8 Arm Cortex-A55 cores, Mali-G57 MC1 GPU
  - 2 or 4GiB DDR3L DRAM
  - 32, 64, or 128 GiB eMMC flash
  - AXP717 + AXP323 PMICs
  - Gigabit Ethernet (using MAXIO PHY)
  - HDMI port
  - 2 * USB 2.0 ports
  - 1 * USB 3.0 port
  - microSD card slot
  - TOSLINK digital audio output
  - 3.5mm A/V port
  - infrared sensor
  - 7-segment display
  - 5V barrel plug power supply
  - power button

The PCB provides holes for soldering a UART header or cable, this is
connected to the debug UART0. There is another set of UART pins
available. The board also features a FEL button (accessible through the
3.5mm socket) and a reset button (only accessible when case is open).

This .dts just describes the basic peripherals as far as we support them
at the moment. The PMIC rail assignments are reverse engineered as far
as possible, by dumping them from a running Android system, and correlating
them to other boards using the same SoC.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-h728-x96qpro+.dts    | 287 ++++++++++++++++++
 2 files changed, 288 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 0d678a7499e3c..983be49ea6ef8 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,4 +52,5 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-h728-x96qpro+.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
new file mode 100644
index 0000000000000..c0bce3f4fa925
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2024 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "X96Q Pro+";
+	compatible = "amediatech,x96q-pro-plus", "allwinner,sun55i-h728";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the barrel plug */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_vcc3v3: vcc3v3 {
+		/* 3.3V dummy supply for the SD card */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&reg_vcc5v>;
+		regulator-always-on;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_vcc3v3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	disable-wp;
+	status = "okay";
+};
+
+&mmc2 {
+	vmmc-supply = <&reg_cldo3>;
+	vqmmc-supply = <&reg_cldo1>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_dcdc4>;
+	vcc-pe-supply = <&reg_dcdc4>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_dcdc4>;
+	vcc-pj-supply = <&reg_dcdc4>;
+	vcc-pk-supply = <&reg_bldo3>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 34 {
+		compatible = "x-powers,axp717";
+		reg = <0x34>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.0(?) GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1360000>;
+				regulator-max-microvolt = <1360000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd-dcdc4";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				/* not connected */
+			};
+
+			reg_aldo3: aldo3 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-aldo3";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-wifi-lvds";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-dram-1v8";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-name = "vcc-bldo3";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-codec-sd";
+			};
+
+			reg_cldo2: cldo2 {
+			};
+
+			reg_cldo3: cldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-codec-eth-sd";
+			};
+
+			reg_cldo4: cldo4 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-eth-phy";
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				/* not connected */
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1050000>;
+				regulator-name = "vdd-dcdc3";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/* USB0 is a USB-A receptacle, always powered, so force host mode. */
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:11 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:11 +0000
Subject: [PATCH v3 14/15] dt-bindings: arm: sunxi: Add YuzukiHD Chameleon board name
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-15-andre.przywara@arm.com>

The Chameleon is an Open Source hardware board designed by YuzkuiHD,
using the Allwinner H618 SoC: https://github.com/YuzukiHD/YuzukiChameleon

Add its compatible name to the list of valid board name.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 80096819fda91..cce31492b0f11 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -1091,4 +1091,9 @@ properties:
           - const: yuzukihd,avaota-a1
           - const: allwinner,sun55i-t527
 
+      - description: YuzukiHD Chameleon
+        items:
+          - const: yuzukihd,chameleon
+          - const: allwinner,sun50i-h618
+
 additionalProperties: true
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:10 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:10 +0000
Subject: [PATCH v3 13/15] arm64: dts: allwinner: a523: add Radxa A5E support
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-14-andre.przywara@arm.com>

The Radxa A5E is a development board using the Allwinner A527 SoC, which
is using the same die as the A523 SoC, just exposing the pins of more
peripherals (like HDMI or the 2nd MAC). The board features:

  - Allwinner A527/T527 SoC: 8 ARM Cortex-A55 cores, Mali-G57 MC1 GPU
  - 1GiB/2GiB/4GiB LPDDR4 DRAM
  - AXP717 + AXP323 PMICs
  - Raspberry-Pi-2 compatible 40pin GPIO header
  - 1 USB 2.0 type C port (OTG), also power supply
  - 1 USB 3.0 type A host port (multiplexed with M.2 slot)
  - 1 M.2 M-key 2230 slot, with 1 PCIe2.1 lane connected (multiplexed
    with USB 3.0 port)
  - MicroSD slot
  - optional eMMC, 8, 16 or 32GB available
  - optional on-board 16MiB bootable SPI NOR flash
  - two 1Gbps Ethernet ports (via MAXIO MAE0621A PHYs)
  - PoE header for optional supply circuit on one Ethernet port
  - WiFi 802.11 a/b/g/n/ac/ax (LB-Link BL-M8800DS2 module using AIC8800)
  - HDMI port
  - camera and LCD connectors
  - power supply via USB-C connector (but no PD) or GPIO header pins

This .dts describes the devices as far as we support them at the moment.
The PMIC rails have been assigned as per the schematics.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../dts/allwinner/sun55i-a527-radxa-a5e.dts   | 299 ++++++++++++++++++
 2 files changed, 300 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 983be49ea6ef8..9d5e14695af0b 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -52,5 +52,6 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun55i-a527-radxa-a5e.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-h728-x96qpro+.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun55i-t527-avaota-a1.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
new file mode 100644
index 0000000000000..912e1bda974ce
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+// Copyright (C) 2025 Arm Ltd.
+
+/dts-v1/;
+
+#include "sun55i-a523.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Radxa A5E";
+	compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_osc32k: ext-osc32k-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply from the USB-C connector */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_vbus: vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc5v>;
+		gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>;	/* PL8 */
+		enable-active-high;
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_cldo3>;
+	cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pc-supply = <&reg_cldo1>;
+	vcc-pd-supply = <&reg_cldo3>;
+	vcc-pe-supply = <&reg_aldo2>;
+	vcc-pf-supply = <&reg_cldo3>;	/* actually switchable */
+	vcc-pg-supply = <&reg_bldo1>;
+	vcc-ph-supply = <&reg_cldo3>;	/* via VCC-IO */
+	vcc-pi-supply = <&reg_cldo3>;
+	vcc-pj-supply = <&reg_cldo4>;
+	vcc-pk-supply = <&reg_cldo1>;
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp717: pmic at 34 {
+		compatible = "x-powers,axp717";
+		reg = <0x34>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+		vin4-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies the "little" cluster (1.4 GHz cores) */
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpul";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <920000>;
+				regulator-max-microvolt = <920000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_aldo1: aldo1 {
+				/* not connected */
+			};
+
+			reg_aldo2: aldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pe";
+			};
+
+			reg_aldo3: aldo3 {
+				/* supplies the I2C pins for this PMIC */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pl-usb";
+			};
+
+			reg_aldo4: aldo4 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pll-dxco-avcc";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pg-iowifi";
+			};
+
+			reg_bldo2: bldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pm-lpddr4";
+			};
+
+			reg_bldo3: bldo3 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-mipi-cam";
+			};
+
+			reg_bldo4: bldo4 {
+				/* not connected */
+			};
+
+			reg_cldo1: cldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pc-and-their-dog";
+			};
+
+			reg_cldo2: cldo2 {
+				/* not connected */
+			};
+
+			reg_cldo3: cldo3 {
+				/* IO, USB-2, 3V3, card, NAND, sensor, PI */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-io-mmc-spi-ana";
+			};
+
+			reg_cldo4: cldo4 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-pj-phy";
+			};
+
+			reg_cpusldo: cpusldo {
+				/* supplies the management core */
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-cpus";
+			};
+		};
+	};
+
+	axp323: pmic at 36 {
+		compatible = "x-powers,axp323";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		status = "okay";
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			aldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-mipi-dsi";
+			};
+
+			dldo1 {
+				/* not connected */
+			};
+
+			/* Supplies the "big" cluster (1.8 GHz cores) */
+			reg_dcdc1_323: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1160000>;
+				regulator-name = "vdd-cpub";
+			};
+
+			/* DCDC2 is polyphased with DCDC1 */
+
+			/* RISC-V management core supply */
+			reg_dcdc3_323: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-name = "vdd-dnr";
+			};
+		};
+	};
+};
+
+&r_pio {
+/*
+ * Specifying the supply would create a circular dependency.
+ *
+ *	vcc-pl-supply = <&reg_aldo3>;
+ */
+	vcc-pm-supply = <&reg_aldo3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * The USB-C port is the primary power supply, so in this configuration
+	 * relies on the other end of the USB cable to supply the VBUS power.
+	 * So use this port in peripheral mode.
+	 * It is possible to supply the board with the 5V pins on the GPIO
+	 * header, and since the DCIN_5V line is hardwired to the USB-C VBUS
+	 * pins, the port turns into a host port, unconditionally supplying
+	 * power. The dr_mode property should be changed to "host" here, if
+	 * users choose this setup.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+/*
+ * The schematic describes USB0_ID (PL10), measuring VBUS_5V, which looks to
+ * be always on. Also there is USB-VBUSDET (PL2), which is measuring the same
+ * VBUS_5V. There is also DCIN_DET, which measures DCIN_5V, so the power
+ * input rail.
+ * None of them seem to make any sense in relation to detecting USB devices
+ * or whether there is power provided via any USB pins: they would always
+ * report high, otherwise the system wouldn't be running.
+ * The AXP717C provides proper USB-C CC pin functionality, but the PMIC is
+ * not connected to those pins of the USB-C connector.
+ */
+&usbphy {
+	usb0_vbus-supply = <&reg_vcc5v>;
+	usb1_vbus-supply = <&reg_usb_vbus>;
+	status = "okay";
+};
-- 
2.46.3



From andre.przywara at arm.com  Thu Mar  6 16:57:12 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  7 Mar 2025 00:57:12 +0000
Subject: [PATCH v3 15/15] arm64: dts: allwinner: h616: add YuzukiHD Chameleon support
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <20250307005712.16828-16-andre.przywara@arm.com>

The Chameleon board is an OpenHardware devboard made by YuzukiTsuru.
The form factor resembles the Raspberry Pi Model A boards, though it
differs significantly in its features:

  - Allwinner H618 SoC (4 * Arm Cortex-A53 cores, 1MB L2 cache, 1.4 GHz)
  - between 512MiB and 2GiB DDR3 DRAM
  - up to 128 GiB eMMC flash
  - AXP313a PMIC
  - 100 Mbit/s Ethernet pins on a header
  - XR829 WIFI+Bluetooth chip
  - 4 * USB 2.0 USB-C ports
  - microSD card slot
  - 3.5mm A/V port

Add the devicetree describing the board's peripherals and their
connections.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
---
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../sun50i-h618-yuzukihd-chameleon.dts        | 222 ++++++++++++++++++
 2 files changed, 223 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 9d5e14695af0b..c15f6a0d8d55a 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-longanpi-3h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero2w.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero3.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-transpeed-8k618-t.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-yuzukihd-chameleon.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
new file mode 100644
index 0000000000000..eae56908b9b4e
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-yuzukihd-chameleon.dts
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Yuzuki Chameleon";
+	compatible = "yuzukihd,chameleon", "allwinner,sun50i-h618";
+
+	aliases {
+		ethernet1 = &sdio_wifi;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply directly from the USB-C socket */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	wifi_pwrseq: pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&rtc CLK_OSC32K_FANOUT>;
+		clock-names = "ext_clock";
+		pinctrl-0 = <&x32clk_fanout_pin>;
+		pinctrl-names = "default";
+		reset-gpios = <&pio 6 11 GPIO_ACTIVE_LOW>; /* PG11 */
+	};
+};
+
+&codec {
+	allwinner,audio-routing = "Line Out", "LINEOUT";
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;	/* PF6 */
+	disable-wp;
+	vmmc-supply = <&reg_dldo1>;
+	status = "okay";
+};
+
+&mmc1 {
+	bus-width = <4>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	non-removable;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
+	status = "okay";
+
+	sdio_wifi: wifi at 1 {
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <6 12 IRQ_TYPE_LEVEL_LOW>;  /* PG12 */
+		interrupt-names = "host-wake";
+	};
+};
+
+&mmc2 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	mmc-ddr-3_3v;
+	non-removable;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_dldo1>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&pio {
+	vcc-pc-supply = <&reg_dldo1>;
+	vcc-pf-supply = <&reg_dldo1>;	/* via VCC_IO */
+	vcc-pg-supply = <&reg_dldo1>;
+	vcc-ph-supply = <&reg_dldo1>;	/* via VCC_IO */
+	vcc-pi-supply = <&reg_dldo1>;
+};
+
+&r_i2c {
+	status = "okay";
+
+	axp313: pmic at 36 {
+		compatible = "x-powers,axp313a";
+		reg = <0x36>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&pio>;
+		interrupts = <2 2 IRQ_TYPE_LEVEL_LOW>;	/* PC2 */
+
+		vin1-supply = <&reg_vcc5v>;
+		vin2-supply = <&reg_vcc5v>;
+		vin3-supply = <&reg_vcc5v>;
+
+		regulators {
+			/* Supplies VCC-PLL, so needs to be always on. */
+			reg_aldo1: aldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc1v8";
+			};
+
+			/* Supplies VCC-IO, so needs to be always on. */
+			reg_dldo1: dldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc3v3";
+			};
+
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <990000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpu";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd-dram";
+			};
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_ph_pins>;
+	status = "okay";
+};
+
+/* Connected to the Bluetooth UART pins of the XR829 Wifi/BT chip. */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg {
+	/*
+	 * PHY0 pins are connected to a USB-C socket, but a role switch
+	 * is not implemented: both CC pins are pulled to GND.
+	 * The VBUS pins power the device, so a fixed peripheral mode
+	 * is the best choice.
+	 * The board can be powered via GPIOs, in this case port0 *can*
+	 * act as a host (with a cable/adapter ignoring CC), as VBUS is
+	 * then provided by the GPIOs. Any user of this setup would
+	 * need to adjust the DT accordingly: dr_mode set to "host",
+	 * enabling OHCI0 and EHCI0.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb0_id_det-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18 */
+	usb0_vbus-supply = <&reg_vcc5v>;
+	usb1_vbus-supply = <&reg_vcc5v>;
+	usb2_vbus-supply = <&reg_vcc5v>;
+	usb3_vbus-supply = <&reg_vcc5v>;
+	status = "okay";
+};
-- 
2.46.3



From kuba at kernel.org  Thu Mar  6 16:59:31 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Thu, 6 Mar 2025 16:59:31 -0800
Subject: [PATCH net-next v6 0/4] riscv: sophgo: Add ethernet support for
 SG2044
In-Reply-To: <20250305063920.803601-1-inochiama@gmail.com>
References: <20250305063920.803601-1-inochiama@gmail.com>
Message-ID: <20250306165931.7ffefe3a@kernel.org>

On Wed,  5 Mar 2025 14:39:12 +0800 Inochi Amaoto wrote:
> The ethernet controller of SG2044 is Synopsys DesignWare IP with
> custom clock. Add glue layer for it.

Looks like we have a conflict on the binding, could you rebase
against latest net-next/main and repost?
-- 
pw-bot: cr


From sfr at canb.auug.org.au  Thu Mar  6 17:09:54 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Fri, 7 Mar 2025 12:09:54 +1100
Subject: linux-next: duplicate patch in the broadcom tree
Message-ID: <20250307120954.351dd8ae@canb.auug.org.au>

Hi all,

The following commit is also in the arm-soc-fixes tree as a different
commit (but the same patch):

  d0b7662f9a68 ("ARM: dts: bcm2711: Fix xHCI power-domain")

This is commit

  f44fa354a071 ("ARM: dts: bcm2711: Fix xHCI power-domain")

in the arm-soc-fixes tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/cdf6695b/attachment.sig>

From Jason-JH.Lin at mediatek.com  Thu Mar  6 17:11:04 2025
From: Jason-JH.Lin at mediatek.com (=?utf-8?B?SmFzb24tSkggTGluICjmnpfnnb/npaUp?=)
Date: Fri, 7 Mar 2025 01:11:04 +0000
Subject: [PATCH v4 3/8] mailbox: mtk-cmdq: Add driver data to support for
 MT8196
In-Reply-To: <1f9007ed-c978-431d-aab2-c04237d5d117@collabora.com>
References: <20250218054405.2017918-1-jason-jh.lin@mediatek.com>
	 <20250218054405.2017918-4-jason-jh.lin@mediatek.com>
	 <652e435c-563b-496a-a4c3-c2e2b665abcf@collabora.com>
	 <5aa04ff5fa567468f32921d4014bbae696c6470f.camel@mediatek.com>
	 <9d383fc5-8c64-478c-8aab-6c56bf5b45be@collabora.com>
	 <0efe42427be4eb619b6ea7db18687b0211d1ec9f.camel@mediatek.com>
	 <1f9007ed-c978-431d-aab2-c04237d5d117@collabora.com>
Message-ID: <a7a48975665ba3493166e0c55ecf9e82f6df8cca.camel@mediatek.com>

> > 

[snip]

> > > > > > +
> > > > > > ??? #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
> > > > > > ??? #define CMDQ_THR_ENABLED??????????? 0x1
> > > > > > ??? #define CMDQ_THR_DISABLED?????????? 0x0
> > > > > > @@ -87,11 +98,24 @@ struct cmdq {
> > > > > > ??? struct gce_plat {
> > > > > > ??????? u32 thread_nr;
> > > > > > ??????? u8 shift;
> > > > > > +???? dma_addr_t mminfra_offset;
> > > > > 
> > > > > It looks like this is exactly the DRAM's iostart... at least,
> > > > > I
> > > > > can
> > > > > see that in the
> > > > > downstream devicetree that's where it starts.
> > > > > 
> > > > > ????????? memory: memory at 80000000 {
> > > > > ????????????????? device_type = "memory";
> > > > > ????????????????? reg = <0 0x80000000 0 0x40000000>;
> > > > > ????????? };
> > > > > 
> > > > > It doesn't really look like being a coincidence, but, for the
> > > > > sake of
> > > > > asking:
> > > > > is this just a coincidence? :-)
> > > > > 
> > > > 
> > > > As the confirmation with the hardware designer in previous
> > > > reply
> > > > mail
> > > > for CK:
> > > > https://patchwork.kernel.org/project/linux-mediatek/patch/20250218054405.2017918-4-jason-jh.lin at mediatek.com/*26258463
> > > > 
> > > 
> > > That explanation was simply wonderful.
> > > 
> > > > Since the MMINFRA remap subtracting 2G is done in the hardware
> > > > circuit
> > > > and cannot be configured by software, the address +2G
> > > > adjustment is
> > > > necessary to implement in the CMDQ driver.
> > > > 
> > > > So that might not be a coincidence.
> > > > But even if DRAM start address changes, this mminfra_offset is
> > > > still
> > > > subtracting 2G, so I think it is a better choice to define it
> > > > as
> > > > the
> > > > driver data for MT8196.
> > > > 
> > > 
> > > ....so, this makes me think the following:
> > > 
> > > 1. The DRAM start address cannot *ever* be less than 2G, because
> > > otherwise the
> > > ???? MMINFRA HW would have a hole in the usable address range;
> > > ???? 1a. If the start address changes to less than 2G, then also
> > > the
> > > IOMMU would
> > > ???????? get limitations, not only the mminfra..!
> > > ???? 2b. This makes it very very very unlikely for the start
> > > address
> > > to be changed
> > > ???????? to less than 0x80000000
> > > 
> > > 2. If the DRAM start address changes to be ABOVE 2G (so more than
> > > 0x80000000),
> > > ???? there would be no point for MMINFRA to start a "config path"
> > > write (or read)
> > > ???? in the SMMU DRAM block, would it? ;-)
> > > 
> > 
> > GCE is using IOMMU in MT8196, so all the address put into the GCE
> > instruction or GCE register for GCE access should be IOVA.
> > 
> > The DRAM start address is 2G(PA=0x80000000, IOVA=0x0) currently, so
> > when GCE want to access the IOVA=0x0, it will need to +2G into the
> > instruction, then the MMINFRA will see it as data path(IOVA > 2G)
> > and
> > subtract 2G for that IOVA, so GCE can finally access the IOVA=0x0.
> > 
> > I'm not sure if I've misunderstood what you mean by ABOVE 2G. :-)
> > If DRAM start address is changed to 3G(PA=0xc0000000) the IOVA is
> > still
> > 0x0, so GCE still need to + 2G to make MMINFRA go to the data path.
> > 
> > But if you mean PA=0x80000000 and IOVA start address is
> > 3G(0xc0000000),
> > then MMINFRA will go to the data path without GCE +2G.
> > However, MMINFRA will -2G when going to the data path and that will
> > cause GCE access the wrong IOVA.
> > So GCE still need to +2G no matter IOVA start address is already
> > can
> > make MMINFRA go to the data path(IOVA > 2G).
> > 
> > We have already complained to our hardware designer that MMINFRA -
> > 2G
> > con not be changed, which will make software operation very
> > troublesome.
> > So in the next few generations of SoC will change this MMINFRA -2G
> > to
> > software configurable. Then we can just make IOVA start address to
> > 2G
> > without adding the mminfra_offset to the IOVA for GCE.
> > 
> 
> Okay now I got it, the reality is way worse than I was thinking...
> eww... :-(
> 
> > > I get it - if the DRAM moves up, MMINFRA is still at 2G because
> > > that's hard baked
> > > into the hardware, but I foresee that it'll be unlikely to see a
> > > platform changing
> > > the DRAM start address arbitrarily, getting out-of-sync with
> > > MMINFRA.
> > > 
> > > I propose to just get the address from the memory node for now,
> > > and
> > > to add a nice
> > > comment in the code that explains that "In at least MT8196, the
> > > MMINFRA hardware
> > > subtracts xyz etc etc" (and that explanation from the previous
> > > email
> > > is again
> > > wonderful and shall not be lost: either use that in the comment,
> > > or
> > > add it to
> > > the commit description, because it's really that good).
> > > 
> > > Should a new SoC appear in the future requiring an offset from
> > > the
> > > DRAM start
> > > address, we will think about how to make that work in the best
> > > possible way: in
> > > that case we could either reference something else to get the
> > > right
> > > address or
> > > we can just change this driver to just use the 2G offset
> > > statically
> > > for all.
> > > 
> > > What I'm trying to do here is to reduce the amount of changes
> > > that
> > > we'd need for
> > > adding new SoCs: since that 2G MMINFRA offset -> 2G DRAM start is
> > > not
> > > a coincidence
> > > I think that, should the DRAM start vary on new SoCs, the MMINFRA
> > > offset will
> > > follow the trend and vary with it.
> > > 
> > > So what I think is:
> > > 1. If I'm right, adding a new SoC (with different MMINFRA + DRAM
> > > offset) will be
> > > ???? as easy as adding a compatible string in the bindings, no
> > > effort
> > > in changing
> > > ???? this driver with new pdata offsets;
> > > 2. If I'm wrong, adding a new SoC means adding compat string and
> > > adding pdata and
> > > ???? one variable in the cmdq struct.
> > > 
> > > Where N.2 is what we would do anyway if we don't go with my
> > > proposed
> > > solution...
> > > 
> > > All this is just to give you my considerations about this topic -
> > > you're left
> > > completely free to disagree with me.
> > > If you disagree, I will trust your judgement, no problem here.
> > > 
> > 
> > Yes, I think your are right. No matter the IOVA start address
> > changing,
> > MMINFRA will still -2G(the start address of DRAM PA).
> > Do you mean we can get the mminfra_offset from the start address of
> > memory in DTS, rather than defining it in pdata?
> > 
> 
> After the last explanation... no, it would be wrong to get the start
> from
> memory in DTS, because then this will still need hacks.
> I was somehow convinced that the DRAM start address and the MMINFRA
> offset
> were directly related and that it would've been hard to change the
> DRAM
> start address with the MMINFRA offset being -2G, but it's not, so
> doing it
> my way will eventually backfire on us.
> 
> So my way is not good, as it's not showing the reality of things.
> 
> Just go with your current way, as it's really tied to the hardware
> and it's
> not restricted to that dram start coincidence in the end. That's a
> pity.
> 
> Just instead of writing 0x80000000, use " SZ_2G " instead... and
> please
> add a comment in the code that explains in brief that there's this
> strange
> behavior for which we.. need that, and that's a static subtraction,
> and is
> tied to the MMINFRA hardware, and cannot be changed :-(
> 
> btw, being clear..
> 
> #include <linux/sizes.h>
> 
> .mminfra_offset = SZ_2G,
> 
> ..that way you don't even need a comment saying /* 2GB */ ....
> 
> Cheers!

Got it. I'll modify it.
Thanks for the confirmation.

Regards,
Jason-JH Lin

From namhyung at kernel.org  Thu Mar  6 17:22:20 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 6 Mar 2025 17:22:20 -0800
Subject: [PATCH v4 06/11] perf dso: Add support for reading the e_machine
 type for a dso
In-Reply-To: <20250304050305.901167-7-irogers@google.com>
References: <20250304050305.901167-1-irogers@google.com>
 <20250304050305.901167-7-irogers@google.com>
Message-ID: <Z8pKTE7tOqdqNUdA@google.com>

On Mon, Mar 03, 2025 at 09:03:00PM -0800, Ian Rogers wrote:
> For ELF file dsos read the e_machine from the ELF header. For kernel
> types assume the e_machine matches the perf tool. In other cases
> return EM_NONE.
> 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/util/dso.c | 54 +++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/dso.h |  1 +
>  2 files changed, 55 insertions(+)
> 
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 5c6e85fdae0d..7f2f1af4f73b 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1170,6 +1170,60 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
>  	return data_read_write_offset(dso, machine, offset, data, size, true);
>  }
>  
> +uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
> +{
> +	uint16_t e_machine = EM_NONE;
> +	int fd;
> +
> +	switch (dso__binary_type(dso)) {
> +	case DSO_BINARY_TYPE__KALLSYMS:
> +	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> +	case DSO_BINARY_TYPE__VMLINUX:
> +	case DSO_BINARY_TYPE__GUEST_VMLINUX:
> +	case DSO_BINARY_TYPE__GUEST_KMODULE:
> +	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
> +	case DSO_BINARY_TYPE__KCORE:
> +	case DSO_BINARY_TYPE__GUEST_KCORE:
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> +	case DSO_BINARY_TYPE__BPF_IMAGE:
> +	case DSO_BINARY_TYPE__OOL:
> +	case DSO_BINARY_TYPE__JAVA_JIT:

I think some of them can be possible in recorded data.  But let's go
simple with EM_HOST as we haven't supported cross-arch trace.


> +		return EM_HOST;
> +	case DSO_BINARY_TYPE__DEBUGLINK:
> +	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
> +	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
> +	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
> +	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
> +	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
> +	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
> +	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
> +		break;
> +	case DSO_BINARY_TYPE__NOT_FOUND:
> +	default:
> +		return EM_NONE;
> +	}
> +
> +	pthread_mutex_lock(&dso__data_open_lock);

Hmm.. I'm afraid it'd slow down perf trace a bit more.  It sees
occasional LOST events.  But it may be ok as it's cached in thread later.


> +
> +	/*
> +	 * dso__data(dso)->fd might be closed if other thread opened another
> +	 * file (dso) due to open file limit (RLIMIT_NOFILE).
> +	 */
> +	try_to_open_dso(dso, machine);
> +	fd = dso__data(dso)->fd;
> +	if (fd >= 0) {
> +		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
> +		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
> +		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))

I think it needs to check the endianess and swap the data.

Thanks,
Namhyung


> +			e_machine = EM_NONE;
> +	}
> +	pthread_mutex_unlock(&dso__data_open_lock);
> +	return e_machine;
> +}
> +
>  /**
>   * dso__data_read_addr - Read data from dso address
>   * @dso: dso object
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index f3ca2a5e7670..ba9b83db061a 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -818,6 +818,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
>  off_t dso__data_size(struct dso *dso, struct machine *machine);
>  ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
>  			      u64 offset, u8 *data, ssize_t size);
> +uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
>  ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
>  			    struct machine *machine, u64 addr,
>  			    u8 *data, ssize_t size);
> -- 
> 2.48.1.711.g2feabab25a-goog
> 


From wei.fang at nxp.com  Thu Mar  6 17:22:54 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 7 Mar 2025 01:22:54 +0000
Subject: [PATCH v3 net-next 04/13] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <03492277-b7e8-4cd1-b92e-699ee0d7dc85@redhat.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
 <20250304072201.1332603-5-wei.fang@nxp.com>
 <03492277-b7e8-4cd1-b92e-699ee0d7dc85@redhat.com>
Message-ID: <PAXPR04MB8510638FA6F61973C620BEAE88D52@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On 3/4/25 8:21 AM, Wei Fang wrote:
> > +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16
> si_bit,
> > +					       struct enetc_mac_addr *mac,
> > +					       int mac_cnt)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	int i;
> > +
> > +	for (i = 0; i < mac_cnt; i++) {
> > +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> > +		if (entry) {
> > +			entry->si_bitmap &= ~si_bit;
> > +			if (!entry->si_bitmap) {
> 
> 
> Minor nit: here and elsewhere you could reduce the level of indentation
> restructoring the code as:

Okay, I will improve it, thanks.
> 
> 		if (!entry)
> 			continue;
> 
> 		entry->si_bitmap &= ~si_bit;
> 		if (entry->si_bitmap)
> 			continue;
> /P


From cki-project at redhat.com  Thu Mar  6 17:23:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 01:23:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <89706.125030620230800407@us-mta-112.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704019277

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704019277-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From jm at ti.com  Thu Mar  6 17:35:04 2025
From: jm at ti.com (Judith Mendez)
Date: Thu, 6 Mar 2025 19:35:04 -0600
Subject: [PATCH v5 06/10] arm64: dts: ti: k3-am62p5-sk: Enable IPC with
 remote processors
In-Reply-To: <64fa3794-e36b-2f77-ff8e-3c2ede3c3927@ti.com>
References: <20250210221530.1234009-1-jm@ti.com>
 <20250210221530.1234009-7-jm@ti.com>
 <04e77daf-e775-44fa-82bf-8b6ebf73bcef@ti.com>
 <787f9d24-25bc-4171-bd8a-88fe9cef694d@ti.com>
 <64fa3794-e36b-2f77-ff8e-3c2ede3c3927@ti.com>
Message-ID: <db72b7f7-0771-442c-91bf-507a3e08cfdc@ti.com>

Hi Devarsh,

On 2/27/25 6:05 AM, Devarsh Thakkar wrote:
> Hi Judith,
> 
> Thanks for the patch.
> 
> On 18/02/25 23:21, Judith Mendez wrote:
>> Hi Andrew,
>>
>>
>> On 2/18/25 10:38 AM, Andrew Davis wrote:
>>> On 2/10/25 4:15 PM, Judith Mendez wrote:
>>>> From: Devarsh Thakkar <devarsht at ti.com>
>>>>
>>>> For each remote proc, reserve memory for IPC and bind the mailbox
>>>> assignments. Two memory regions are reserved for each remote processor.
>>>> The first region of 1MB of memory is used for Vring shared buffers
>>>> and the second region is used as external memory to the remote processor
>>>> for the resource table and for tracebuffer allocations.
>>>>
>>>> Signed-off-by: Devarsh Thakkar <devarsht at ti.com>
>>>> Signed-off-by: Hari Nagalla <hnagalla at ti.com>
>>>> Signed-off-by: Judith Mendez <jm at ti.com>
>>>> ---
>>>> Changes since v4:
>>>> - Drop SRAM node for am62px MCU R5fSS0 core0
>>>> ---
>>>>  ? arch/arm64/boot/dts/ti/k3-am62p5-sk.dts | 50 ++++++++++++++++++++++---
>>>>  ? 1 file changed, 44 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
>>>> b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
>>>> index ad71d2f27f538..9609727d042d3 100644
>>>> --- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
>>>> +++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
>>>> @@ -48,6 +48,30 @@ reserved-memory {
>>>>  ????????? #size-cells = <2>;
>>>>  ????????? ranges;
>>>> +??????? mcu_r5fss0_core0_dma_memory_region:
>>>> mcu-r5fss-dma-memory-region at 9b800000 {
>>>> +??????????? compatible = "shared-dma-pool";
>>>> +??????????? reg = <0x00 0x9b800000 0x00 0x100000>;
>>>> +??????????? no-map;
>>>> +??????? };
>>>> +
> 
> I believe you are testing these carveouts against the default firmwares
> shipped with AM62P SDK (compiled from meta-arago), With the same firmwares,
> each remote core also does inter-processor communication with each other
> (RTOS<->RTOS) on bootup, so you need to reserve the regions for the same too
> as done here [1].

This is how I originally had the patch Devarsh, if you see earlier
review, we removed the SRAM nodes and the rtos-to-rtos memory carveouts.


> 
>>>> +??????? mcu_r5fss0_core0_memory_region: mcu-r5fss-memory-region at 9b900000 {
>>>> +??????????? compatible = "shared-dma-pool";
>>>> +??????????? reg = <0x00 0x9b900000 0x00 0xf00000>;
>>>> +??????????? no-map;
>>>> +??????? };
>>>> +
>>>> +??????? wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory at 9c800000 {
>>>> +??????????? compatible = "shared-dma-pool";
>>>> +??????????? reg = <0x00 0x9c800000 0x00 0x100000>;
>>>> +??????????? no-map;
>>>> +??????? };
>>>> +
>>>> +??????? wkup_r5fss0_core0_memory_region: r5f-memory at 9c900000 {
>>>> +??????????? compatible = "shared-dma-pool";
>>>> +??????????? reg = <0x00 0x9c900000 0x00 0x1e00000>;
>>>
>>> 0x1e00000?
>>>
>>> Yes I know you didn't add this and are just coping it from below, but it
>>> is still an issue. I see the same problem for the next patch, the R5F memory
>>> size is 0xc00000??
>>>
>>> Every remote core gets 15MB (0xf00000), this has been true for all K3, and
>>> all cores, DSP, R5F, M4, etc.. You even do it correct for the MCU R5F above,
>>> but the WKUP R5F on AM62P and AM62 are just randomly given 30M and 12MB?
>>
>> Not sure why FW requires 30MB here, I have reached out to FW team to
>> investigate this, will respond back here soon.
>>
> 
> You will need an alignment with the firmware team to make sure that it doesn't
> break with the default firmwares shipped with the AM62Px SDK. Also just FYI,
> this will leave a gap of 14 MiB between the wakeup R5 and the next component
> i.e. ATF, ideally we should have avoided this gap but seems like ATF nodes are
> already upstream [2], so probably can't do much, nevertheless I hope that 14
> MiB will be claimed/used by Linux in some manner.

I did a sanity boot test with the default firmwares shipped for am62px
SDK, no error with am62px boot so far. Changes are: removed SRAM node, 
reduced wkup r5 memory carveout, no rtos-to-rtos memory carveout).

But I realize this is not a complete test. I believe there may be
potentially memory corruption with these changes if all implemented.

Andrew, I am not sure we are going in a good direction here, unless we
have a different reduced/fixed FW in the am62px SDK, we may have memory
corruption issues on our hands.

~ Judith


> 
> Soumya,
> Please provide an ACK for this, if the DM R5 firmware is exceeding 15 MiB,
> then you will need to update your linker scripts and regenerate the ipc echo
> test firmwares to make sure the wakeup R5 code/data does not exceed to what is
> being proposed here (15 MiB).
> 
> [1]:
> https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts?h=11.00.05#n72
> 
> [2]:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts?h=next-20250227#n51
> 
> Regards
> Devarsh



From wei.fang at nxp.com  Thu Mar  6 17:47:03 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 7 Mar 2025 01:47:03 +0000
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250306142842.476db52c@kernel.org>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-2-wei.fang@nxp.com>
 <20250306142842.476db52c@kernel.org>
Message-ID: <PAXPR04MB85107A1E5990FBB63F12C3B888D52@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue,  4 Mar 2025 15:21:49 +0800 Wei Fang wrote:
> > +config NXP_NETC_LIB
> > +	tristate "NETC Library"
> 
> Remove the string after "tristate", the user should not be prompted
> to make a choice for this, since the consumers "select" this config
> directly.
> 

Okay, I will remove it.

> > +	help
> > +	  This module provides common functionalities for both ENETC and NETC
> > +	  Switch, such as NETC Table Management Protocol (NTMP) 2.0, common
> tc
> > +	  flower and debugfs interfaces and so on.
> > +
> > +	  If compiled as module (M), the module name is nxp-netc-lib.
> 
> Not sure if the help makes sense for an invisible symbol either.

Yes, I think it can also be removed. Thanks.
> 
> >  config FSL_ENETC
> >  	tristate "ENETC PF driver"
> >  	depends on PCI_MSI
> > @@ -40,6 +50,7 @@ config NXP_ENETC4
> >  	select FSL_ENETC_CORE
> >  	select FSL_ENETC_MDIO
> >  	select NXP_ENETC_PF_COMMON
> > +	select NXP_NETC_LIB
> >  	select PHYLINK
> >  	select DIMLIB
> >  	help
> 
> > +#pragma pack(1)
> 
> please don't blindly pack all structs, only if they are misaligned
> or will otherwise have holes.

Because these structures are in hardware buffer format and need
to be aligned, so for convenience, I simply used pack(1). You are right,
I should use pack() for structures with holes. Thanks.
> 
> > +#if IS_ENABLED(CONFIG_NXP_NETC_LIB)
> 
> why the ifdef, all callers select the config option

hm..., there are some interfaces of netc-lib are used in common .c files
in downstream, so I used "ifdef" in downstream. Now for the upstream,
I'm going to separate them from the common .c files. So yes, we can
remove it now.



From patchwork-bot+netdevbpf at kernel.org  Thu Mar  6 18:00:31 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Fri, 07 Mar 2025 02:00:31 +0000
Subject: [PATCH net-next v4 0/2] Add perout configuration support in IEP
 driver
In-Reply-To: <20250304105753.1552159-1-m-malladi@ti.com>
References: <20250304105753.1552159-1-m-malladi@ti.com>
Message-ID: <174131283199.1853786.11033321360799820644.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Tue, 4 Mar 2025 16:27:51 +0530 you wrote:
> IEP driver supported both perout and pps signal generation
> but perout feature is faulty with half-cooked support
> due to some missing configuration. Hence perout feature is
> removed as a bug fix. This patch series adds back this feature
> which configures perout signal based on the arguments passed
> by the perout request.
> 
> [...]

Here is the summary with links:
  - [net-next,v4,1/2] net: ti: icss-iep: Add pwidth configuration for perout signal
    https://git.kernel.org/netdev/net-next/c/e5b456a14215
  - [net-next,v4,2/2] net: ti: icss-iep: Add phase offset configuration for perout signal
    https://git.kernel.org/netdev/net-next/c/220cb1be647a

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From yangyicong at huawei.com  Thu Mar  6 18:18:09 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 7 Mar 2025 10:18:09 +0800
Subject: [PATCH 0/2] Update the watchdog period according to real CPU frequency
Message-ID: <20250307021811.46981-1-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

watchdog perf needs architecture to provide method for converting the watchdog
thresh to counter period. For arm64 we're using the max CPU frequency for
doing the conversion which is from cpufreq driver. But some cpufreq driver
are registered lately, for example cppc_cpufreq will be registered at late
initcall which is after the initialization of watchdog perf (initialized in
armv8_pmuv3 of device initcall). In such case the period of watchdog will not
be accurate enough. Fix this by registering a cpufreq notifier and update the
watchdog period once the cpufreq driver is initialized.

Yicong Yang (2):
  watchdog/perf: Provide function for adjusting the event period
  arm64/watchdog_hld: Add a cpufreq notifier for update watchdog thresh

 arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
 include/linux/nmi.h              |  2 ++
 kernel/watchdog_perf.c           | 21 ++++++++++++++++++++
 3 files changed, 57 insertions(+)

-- 
2.24.0



From yangyicong at huawei.com  Thu Mar  6 18:18:11 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 7 Mar 2025 10:18:11 +0800
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update watchdog thresh
In-Reply-To: <20250307021811.46981-1-yangyicong@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
Message-ID: <20250307021811.46981-3-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

arm64 depends on the cpufreq driver to gain the maximum cpu frequency
to convert the watchdog_thresh to perf event period. cpufreq drivers
like cppc_cpufreq will be initialized lately after the initializing of
the hard lockup detector so just use a safe cpufreq which will be
inaccurency. Use a cpufreq notifier to adjust the event's period to
a more accurate one.

Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
index dcd25322127c..719ae39e8bc0 100644
--- a/arch/arm64/kernel/watchdog_hld.c
+++ b/arch/arm64/kernel/watchdog_hld.c
@@ -34,3 +34,37 @@ bool __init arch_perf_nmi_is_available(void)
 	 */
 	return arm_pmu_irq_is_nmi();
 }
+
+static int watchdog_freq_notifier_callback(struct notifier_block *nb,
+					   unsigned long val, void *data)
+{
+	struct cpufreq_policy *policy = data;
+	unsigned long max_cpu_freq;
+	u64 new_period;
+	int cpu;
+
+	if (val != CPUFREQ_CREATE_POLICY)
+		return 0;
+
+	for_each_cpu(cpu, policy->cpus) {
+		max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
+		if (!max_cpu_freq)
+			continue;
+
+		new_period = watchdog_thresh * max_cpu_freq;
+		hardlockup_detector_perf_adjust_period(cpu, new_period);
+	}
+
+	return 0;
+}
+
+static struct notifier_block watchdog_freq_notifier = {
+	.notifier_call = watchdog_freq_notifier_callback,
+};
+
+static int __init init_watchdog_freq_notifier(void)
+{
+	return cpufreq_register_notifier(&watchdog_freq_notifier,
+					 CPUFREQ_POLICY_NOTIFIER);
+}
+core_initcall(init_watchdog_freq_notifier);
-- 
2.24.0



From yangyicong at huawei.com  Thu Mar  6 18:18:10 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 7 Mar 2025 10:18:10 +0800
Subject: [PATCH 1/2] watchdog/perf: Provide function for adjusting the event period
In-Reply-To: <20250307021811.46981-1-yangyicong@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
Message-ID: <20250307021811.46981-2-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Architecture's using perf events for hard lockup detection needs to
convert the watchdog_thresh to the event's period, some architecture
for example arm64 perform this conversion using the CPU's maximum
frequency which will be acquired by cpufreq. However by the time
the lockup detector's initialized the cpufreq driver may not be
initialized, thus launch a watchdog with inaccurate period. Provide
a function dhardlockup_detector_perf_adjust_period() to allowing
adjust the event period. Then architecture can update with more
accurate period if cpufreq is initialized.

Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 include/linux/nmi.h    |  2 ++
 kernel/watchdog_perf.c | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index a8dfb38c9bb6..2200ce481439 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -106,11 +106,13 @@ extern void hardlockup_detector_perf_stop(void);
 extern void hardlockup_detector_perf_restart(void);
 extern void hardlockup_detector_perf_cleanup(void);
 extern void hardlockup_config_perf_event(const char *str);
+extern void hardlockup_detector_perf_adjust_period(int cpu, u64 period);
 #else
 static inline void hardlockup_detector_perf_stop(void) { }
 static inline void hardlockup_detector_perf_restart(void) { }
 static inline void hardlockup_detector_perf_cleanup(void) { }
 static inline void hardlockup_config_perf_event(const char *str) { }
+static inline void hardlockup_detector_perf_adjust_period(int cpu, u64 period) { }
 #endif
 
 void watchdog_hardlockup_stop(void);
diff --git a/kernel/watchdog_perf.c b/kernel/watchdog_perf.c
index 59c1d86a73a2..bc00985d1f69 100644
--- a/kernel/watchdog_perf.c
+++ b/kernel/watchdog_perf.c
@@ -211,6 +211,27 @@ void hardlockup_detector_perf_cleanup(void)
 	cpumask_clear(&dead_events_mask);
 }
 
+/**
+ * hardlockup_detector_perf_adjust_period - Adjust the events period due
+ *                                          to cpu frequency change
+ */
+void hardlockup_detector_perf_adjust_period(int cpu, u64 period)
+{
+	struct perf_event *event = per_cpu(watchdog_ev, cpu);
+
+	if (!(watchdog_enabled & WATCHDOG_HARDLOCKUP_ENABLED))
+		return;
+
+	if (!event)
+		return;
+
+	if (event->attr.sample_period == period)
+		return;
+
+	if (perf_event_period(event, period))
+		pr_err("failed to change period to %llu\n", period);
+}
+
 /**
  * hardlockup_detector_perf_stop - Globally stop watchdog events
  *
-- 
2.24.0



From ping.bai at nxp.com  Thu Mar  6 18:33:13 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri, 7 Mar 2025 02:33:13 +0000
Subject: [PATCH v3] cpuidle: psci: Init cpuidle only for present CPUs
In-Reply-To: <Z8mYP7AGBPeDTvXn@bogus>
References: <20250306061805.2318154-1-ping.bai@nxp.com>
 <CAPDyKForY4VNZtqietDPt2FQM3p4OsaoE_oJb0PPLUAh98WsHQ@mail.gmail.com>
 <Z8mYP7AGBPeDTvXn@bogus>
Message-ID: <AS8PR04MB864268FE54C7EE0E51D2875087D52@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v3] cpuidle: psci: Init cpuidle only for present CPUs
> 
> On Thu, Mar 06, 2025 at 11:53:14AM +0100, Ulf Hansson wrote:
> > On Thu, 6 Mar 2025 at 07:17, Jacky Bai <ping.bai at nxp.com> wrote:
> > >
> > > for_each_possible_cpu() is currently used to initialize cpuidle in
> > > the PSCI cpuidle driver.
> > >
> > > However, in cpu_dev_register_generic(), for_each_present_cpu() is
> > > used to register CPU devices which means the CPU devices are only
> > > registered for present CPUs and not all possible CPUs.
> > >
> > > With nosmp or maxcpus=0, only the boot CPU is present, leading to
> > > the failure:
> > >
> > >   |  Failed to register cpuidle device for cpu1
> > >
> > > Change for_each_possible_cpu() to for_each_present_cpu() in the PSCI
> > > cpuidle driver to ensure it only registers cpuidle devices for CPUs
> > > that are actually present.
> > >
> > > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > > GENERIC_CPU_DEVICES")
> > > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> >
> > Is this problem specific to cpuidle-psci?
> >
> > Others are using for_each_possible_cpu() when registering their cpuidle
> drivers.
> >
> 
> Good point. I assumed as this was very old patch, only this is left without
> conversion to using present_cpumask. Looks like there are many other drivers
> that need similar change. May be PSCI is most commonly used ones these
> days and hardly anyone tests with nosmp or maxcpus=1 on those platforms.
> 
> But yes, all the users of for_each_possible_cpu() need to move to
> for_each_present_cpu() if they are relying on CPU device being registered.
> 

Yes, there are several other cpuidle drivers should have the similar issue, also
some other driver like cpufreq also need to covert to use present mask.

I will do a further check and fix them all together.

BR
> --
> Regards,
> Sudeep


From jiebing.chen at amlogic.com  Thu Mar  6 18:48:10 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Fri, 7 Mar 2025 10:48:10 +0800
Subject: [PATCH v3 5/6] ASoC: meson: s4: Add s4 tocodec driver
In-Reply-To: <1jfrjq5ews.fsf@starbuckisacylon.baylibre.com>
References: <20250228-audio_drvier-v3-0-dbfd30507e4c@amlogic.com>
 <20250228-audio_drvier-v3-5-dbfd30507e4c@amlogic.com>
 <1jfrjq5ews.fsf@starbuckisacylon.baylibre.com>
Message-ID: <26292ce9-7644-4a8f-8817-045cf6dd87b0@amlogic.com>


? 2025/3/6 23:58, Jerome Brunet ??:
> [ EXTERNAL EMAIL ]
>
> On Fri 28 Feb 2025 at 16:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:
>
>> From: jiebing chen <jiebing.chen at amlogic.com>
>>
>> S4 tocodec support 8 lane to input, It need to enable
>> bclk and mclk control bit when work
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   sound/soc/meson/g12a-toacodec.c | 51 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 51 insertions(+)
>>
>> diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
>> index 531bb8707a3ec4c47814d6a0676d5c62c705da75..41eef9980059285275f0189a06469fc694775955 100644
>> --- a/sound/soc/meson/g12a-toacodec.c
>> +++ b/sound/soc/meson/g12a-toacodec.c
>> @@ -41,6 +41,9 @@
>>   #define  CTRL0_BCLK_SEL_LSB          4
>>   #define  CTRL0_MCLK_SEL                      GENMASK(2, 0)
>>
>> +#define CTRL0_BCLK_ENABLE_SHIFT              30
>> +#define CTRL0_MCLK_ENABLE_SHIFT              29
>> +
>>   #define TOACODEC_OUT_CHMAX           2
>>
>>   struct g12a_toacodec {
>> @@ -129,6 +132,10 @@ static const struct snd_kcontrol_new g12a_toacodec_out_enable =
>>        SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
>>                                    CTRL0_ENABLE_SHIFT, 1, 0);
>>
>> +static const struct snd_kcontrol_new s4_toacodec_clk_enable =
>> +     SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
>> +                     CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
>> +
>>   static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
>>        SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
>>                         &g12a_toacodec_mux),
>> @@ -143,6 +150,15 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
>>                            &g12a_toacodec_out_enable),
>>   };
>>
>> +static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
>> +     SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
>> +                      &sm1_toacodec_mux),
>> +     SND_SOC_DAPM_SWITCH("OUT EN", SND_SOC_NOPM, 0, 0,
>> +                         &g12a_toacodec_out_enable),
>> +     SND_SOC_DAPM_SWITCH("CLK EN", SND_SOC_NOPM, 0, 0,
>> +                         &s4_toacodec_clk_enable),
> I don't see a reason for the user to control that.
>
> A user controls if the component is enable or not, and possibly select
> the lane ... but that's it
>
> You could have to flipped automatically which dapm when the component is
> powered, that would make a lot more sense.

Hi,Jerome

Thank you for your suggestion. Can we design it as a supply widget for 
tocodec bclk and mclk control?

when dapm poweron, and supply widget power on, Users do not have to 
operate additional Kcontrols

>
>> +};
>> +
>>   static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
>>                                         struct snd_pcm_hw_params *params,
>>                                         struct snd_soc_dai *dai)
>> @@ -228,6 +244,15 @@ static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
>>        { "OUT Capture", NULL, "OUT EN" },
>>   };
>>
>> +static const struct snd_soc_dapm_route s4_toacodec_routes[] = {
>> +     { "SRC", "I2S A", "IN A Playback" },
>> +     { "SRC", "I2S B", "IN B Playback" },
>> +     { "SRC", "I2S C", "IN C Playback" },
>> +     { "OUT EN", "Switch", "SRC" },
>> +     { "CLK EN", "Switch", "OUT EN" },
>> +     { "OUT Capture", NULL, "CLK EN" },
>> +};
>> +
>>   static const struct snd_kcontrol_new g12a_toacodec_controls[] = {
>>        SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL, 3, 0),
>>   };
>> @@ -236,6 +261,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
>>        SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
>>   };
>>
>> +static const struct snd_kcontrol_new s4_toacodec_controls[] = {
>> +     SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 7, 0),
>> +};
>> +
>>   static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
>>        .probe                  = g12a_toacodec_component_probe,
>>        .controls               = g12a_toacodec_controls,
>> @@ -258,6 +287,17 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
>>        .endianness             = 1,
>>   };
>>
>> +static const struct snd_soc_component_driver s4_toacodec_component_drv = {
>> +     .probe                  = sm1_toacodec_component_probe,
>> +     .controls               = s4_toacodec_controls,
>> +     .num_controls           = ARRAY_SIZE(s4_toacodec_controls),
>> +     .dapm_widgets           = s4_toacodec_widgets,
>> +     .num_dapm_widgets       = ARRAY_SIZE(s4_toacodec_widgets),
>> +     .dapm_routes            = s4_toacodec_routes,
>> +     .num_dapm_routes        = ARRAY_SIZE(s4_toacodec_routes),
>> +     .endianness             = 1,
>> +};
>> +
>>   static const struct regmap_config g12a_toacodec_regmap_cfg = {
>>        .reg_bits       = 32,
>>        .val_bits       = 32,
>> @@ -278,6 +318,13 @@ static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
>>        .field_bclk_sel = REG_FIELD(TOACODEC_CTRL0, 4, 6),
>>   };
>>
>> +static const struct g12a_toacodec_match_data s4_toacodec_match_data = {
>> +     .component_drv  = &s4_toacodec_component_drv,
>> +     .field_dat_sel  = REG_FIELD(TOACODEC_CTRL0, 19, 20),
>> +     .field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
>> +     .field_bclk_sel = REG_FIELD(TOACODEC_CTRL0, 4, 6),
>> +};
>> +
>>   static const struct of_device_id g12a_toacodec_of_match[] = {
>>        {
>>                .compatible = "amlogic,g12a-toacodec",
>> @@ -287,6 +334,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
>>                .compatible = "amlogic,sm1-toacodec",
>>                .data = &sm1_toacodec_match_data,
>>        },
>> +     {
>> +             .compatible = "amlogic,s4-toacodec",
>> +             .data = &s4_toacodec_match_data,
>> +     },
>>        {}
>>   };
>>   MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);
> --
> Jerome


From jiebing.chen at amlogic.com  Thu Mar  6 18:58:34 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Fri, 7 Mar 2025 10:58:34 +0800
Subject: [PATCH v3 4/6] clk: meson: axg-audio: Add the mclk pad div for s4
In-Reply-To: <1ja59y5cy8.fsf@starbuckisacylon.baylibre.com>
References: <20250228-audio_drvier-v3-0-dbfd30507e4c@amlogic.com>
 <20250228-audio_drvier-v3-4-dbfd30507e4c@amlogic.com>
 <1ja59y5cy8.fsf@starbuckisacylon.baylibre.com>
Message-ID: <25994adc-d89f-47fb-93d7-eb479f362c73@amlogic.com>


? 2025/3/7 0:41, Jerome Brunet ??:
> [ EXTERNAL EMAIL ]
>
> On Fri 28 Feb 2025 at 16:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:
>
>> From: jiebing chen <jiebing.chen at amlogic.com>
>>
>> Add mclk pad div support, Increased the number of lrclk
>> and sclk pads to five
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   drivers/clk/meson/axg-audio.c | 410 +++++++++++++++++++++++++++++++++++++++++-
>>   drivers/clk/meson/axg-audio.h |   4 +
>>   2 files changed, 412 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
>> index 9df627b142f89788966ede0262aaaf39e13f0b49..e70559ee0fd8deaf9858b0592e839fdf49d05886 100644
>> --- a/drivers/clk/meson/axg-audio.c
>> +++ b/drivers/clk/meson/axg-audio.c
>> @@ -323,6 +323,16 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
>>        AUD_MUX(_name, _reg, 0x7, _shift, 0, _parents,          \
>>                CLK_SET_RATE_NO_REPARENT)
>>
>> +#define AUD_MCLK_PAD_MUX(_name, _reg, _shift)                                        \
>> +     AUD_MUX(_name##_sel, _reg, 0x7, _shift, CLK_MUX_ROUND_CLOSEST,                  \
>> +             mclk_pad_ctrl_parent_data, 0)
>> +#define AUD_MCLK_PAD_DIV(_name, _reg, _shift)                                        \
>> +     AUD_DIV(_name##_div, _reg, _shift, 8, CLK_DIVIDER_ROUND_CLOSEST,                        \
>> +             aud_##_name##_sel, CLK_SET_RATE_PARENT)
>> +#define AUD_MCLK_PAD_GATE(_name, _reg, _shift)                                       \
>> +     AUD_GATE(_name, _reg, _shift, aud_##_name##_div,                        \
>> +              CLK_SET_RATE_PARENT)
>> +
>>   /* Common Clocks */
>>   static struct clk_regmap ddr_arb =
>>        AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
>> @@ -826,6 +836,49 @@ static struct clk_regmap sm1_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
>>   static struct clk_regmap sm1_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
>>        tdm_sclk_pad_2, AUDIO_SM1_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
>>
>> +static struct clk_regmap s4_tdm_mclk_pad0_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 8);
>> +static struct clk_regmap s4_tdm_mclk_pad1_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 24);
>> +static struct clk_regmap s4_tdm_mclk_pad2_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 8);
>> +
>> +static struct clk_regmap s4_tdm_mclk_pad0_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 0);
>> +static struct clk_regmap s4_tdm_mclk_pad1_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 16);
>> +static struct clk_regmap s4_tdm_mclk_pad2_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 0);
>> +
>> +static struct clk_regmap s4_tdm_mclk_pad_0 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 15);
>> +static struct clk_regmap s4_tdm_mclk_pad_1 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 31);
>> +static struct clk_regmap s4_tdm_mclk_pad_2 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 15);
>> +
>> +static struct clk_regmap s4_tdm_sclk_pad_0 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL0, 0, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_1 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL0, 4, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_2 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL0, 8, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_3 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL0, 16, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_4 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL0, 20, lrclk_pad_ctrl_parent_data);
>> +
>> +static struct clk_regmap s4_tdm_lrclk_pad_0 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL1, 0, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_1 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL1, 4, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_2 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL1, 8, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_3 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL1, 16, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_4 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL1, 20, lrclk_pad_ctrl_parent_data);
>> +
>>   /*
>>    * Array of all clocks provided by this provider
>>    * The input clocks of the controller will be populated at runtime
>> @@ -1257,6 +1310,177 @@ static struct clk_hw *sm1_audio_hw_clks[] = {
>>        [AUD_CLKID_EARCRX_DMAC]         = &sm1_earcrx_dmac_clk.hw,
>>   };
>>
>> +/*
>> + * Array of all S4 clocks provided by this provider
>> + * The input clocks of the controller will be populated at runtime
>> + */
>> +static struct clk_hw *s4_audio_hw_clks[] = {
>> +     [AUD_CLKID_DDR_ARB]             = &ddr_arb.hw,
>> +     [AUD_CLKID_PDM]                 = &pdm.hw,
>> +     [AUD_CLKID_TDMIN_A]             = &tdmin_a.hw,
>> +     [AUD_CLKID_TDMIN_B]             = &tdmin_b.hw,
>> +     [AUD_CLKID_TDMIN_C]             = &tdmin_c.hw,
>> +     [AUD_CLKID_TDMIN_LB]            = &tdmin_lb.hw,
>> +     [AUD_CLKID_TDMOUT_A]            = &tdmout_a.hw,
>> +     [AUD_CLKID_TDMOUT_B]            = &tdmout_b.hw,
>> +     [AUD_CLKID_TDMOUT_C]            = &tdmout_c.hw,
>> +     [AUD_CLKID_FRDDR_A]             = &frddr_a.hw,
>> +     [AUD_CLKID_FRDDR_B]             = &frddr_b.hw,
>> +     [AUD_CLKID_FRDDR_C]             = &frddr_c.hw,
>> +     [AUD_CLKID_TODDR_A]             = &toddr_a.hw,
>> +     [AUD_CLKID_TODDR_B]             = &toddr_b.hw,
>> +     [AUD_CLKID_TODDR_C]             = &toddr_c.hw,
>> +     [AUD_CLKID_LOOPBACK]            = &loopback.hw,
>> +     [AUD_CLKID_SPDIFIN]             = &spdifin.hw,
>> +     [AUD_CLKID_SPDIFOUT]            = &spdifout.hw,
>> +     [AUD_CLKID_RESAMPLE]            = &resample.hw,
>> +     [AUD_CLKID_SPDIFOUT_B]          = &spdifout_b.hw,
>> +     [AUD_CLKID_MST_A_MCLK_SEL]      = &sm1_mst_a_mclk_sel.hw,
>> +     [AUD_CLKID_MST_B_MCLK_SEL]      = &sm1_mst_b_mclk_sel.hw,
>> +     [AUD_CLKID_MST_C_MCLK_SEL]      = &sm1_mst_c_mclk_sel.hw,
>> +     [AUD_CLKID_MST_D_MCLK_SEL]      = &sm1_mst_d_mclk_sel.hw,
>> +     [AUD_CLKID_MST_E_MCLK_SEL]      = &sm1_mst_e_mclk_sel.hw,
>> +     [AUD_CLKID_MST_F_MCLK_SEL]      = &sm1_mst_f_mclk_sel.hw,
>> +     [AUD_CLKID_MST_A_MCLK_DIV]      = &sm1_mst_a_mclk_div.hw,
>> +     [AUD_CLKID_MST_B_MCLK_DIV]      = &sm1_mst_b_mclk_div.hw,
>> +     [AUD_CLKID_MST_C_MCLK_DIV]      = &sm1_mst_c_mclk_div.hw,
>> +     [AUD_CLKID_MST_D_MCLK_DIV]      = &sm1_mst_d_mclk_div.hw,
>> +     [AUD_CLKID_MST_E_MCLK_DIV]      = &sm1_mst_e_mclk_div.hw,
>> +     [AUD_CLKID_MST_F_MCLK_DIV]      = &sm1_mst_f_mclk_div.hw,
>> +     [AUD_CLKID_MST_A_MCLK]          = &sm1_mst_a_mclk.hw,
>> +     [AUD_CLKID_MST_B_MCLK]          = &sm1_mst_b_mclk.hw,
>> +     [AUD_CLKID_MST_C_MCLK]          = &sm1_mst_c_mclk.hw,
>> +     [AUD_CLKID_MST_D_MCLK]          = &sm1_mst_d_mclk.hw,
>> +     [AUD_CLKID_MST_E_MCLK]          = &sm1_mst_e_mclk.hw,
>> +     [AUD_CLKID_MST_F_MCLK]          = &sm1_mst_f_mclk.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &spdifout_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &spdifout_clk_div.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK]        = &spdifout_clk.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK_SEL]  = &spdifout_b_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK_DIV]  = &spdifout_b_clk_div.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK]      = &spdifout_b_clk.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK_SEL]     = &spdifin_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK_DIV]     = &spdifin_clk_div.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK]         = &spdifin_clk.hw,
>> +     [AUD_CLKID_PDM_DCLK_SEL]        = &pdm_dclk_sel.hw,
>> +     [AUD_CLKID_PDM_DCLK_DIV]        = &pdm_dclk_div.hw,
>> +     [AUD_CLKID_PDM_DCLK]            = &pdm_dclk.hw,
>> +     [AUD_CLKID_PDM_SYSCLK_SEL]      = &pdm_sysclk_sel.hw,
>> +     [AUD_CLKID_PDM_SYSCLK_DIV]      = &pdm_sysclk_div.hw,
>> +     [AUD_CLKID_PDM_SYSCLK]          = &pdm_sysclk.hw,
>> +     [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &mst_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &mst_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &mst_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &mst_d_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &mst_e_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &mst_f_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_A_SCLK_DIV]      = &mst_a_sclk_div.hw,
>> +     [AUD_CLKID_MST_B_SCLK_DIV]      = &mst_b_sclk_div.hw,
>> +     [AUD_CLKID_MST_C_SCLK_DIV]      = &mst_c_sclk_div.hw,
>> +     [AUD_CLKID_MST_D_SCLK_DIV]      = &mst_d_sclk_div.hw,
>> +     [AUD_CLKID_MST_E_SCLK_DIV]      = &mst_e_sclk_div.hw,
>> +     [AUD_CLKID_MST_F_SCLK_DIV]      = &mst_f_sclk_div.hw,
>> +     [AUD_CLKID_MST_A_SCLK_POST_EN]  = &mst_a_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_B_SCLK_POST_EN]  = &mst_b_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_C_SCLK_POST_EN]  = &mst_c_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_D_SCLK_POST_EN]  = &mst_d_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_E_SCLK_POST_EN]  = &mst_e_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_F_SCLK_POST_EN]  = &mst_f_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_A_SCLK]          = &mst_a_sclk.hw,
>> +     [AUD_CLKID_MST_B_SCLK]          = &mst_b_sclk.hw,
>> +     [AUD_CLKID_MST_C_SCLK]          = &mst_c_sclk.hw,
>> +     [AUD_CLKID_MST_D_SCLK]          = &mst_d_sclk.hw,
>> +     [AUD_CLKID_MST_E_SCLK]          = &mst_e_sclk.hw,
>> +     [AUD_CLKID_MST_F_SCLK]          = &mst_f_sclk.hw,
>> +     [AUD_CLKID_MST_A_LRCLK_DIV]     = &mst_a_lrclk_div.hw,
>> +     [AUD_CLKID_MST_B_LRCLK_DIV]     = &mst_b_lrclk_div.hw,
>> +     [AUD_CLKID_MST_C_LRCLK_DIV]     = &mst_c_lrclk_div.hw,
>> +     [AUD_CLKID_MST_D_LRCLK_DIV]     = &mst_d_lrclk_div.hw,
>> +     [AUD_CLKID_MST_E_LRCLK_DIV]     = &mst_e_lrclk_div.hw,
>> +     [AUD_CLKID_MST_F_LRCLK_DIV]     = &mst_f_lrclk_div.hw,
>> +     [AUD_CLKID_MST_A_LRCLK]         = &mst_a_lrclk.hw,
>> +     [AUD_CLKID_MST_B_LRCLK]         = &mst_b_lrclk.hw,
>> +     [AUD_CLKID_MST_C_LRCLK]         = &mst_c_lrclk.hw,
>> +     [AUD_CLKID_MST_D_LRCLK]         = &mst_d_lrclk.hw,
>> +     [AUD_CLKID_MST_E_LRCLK]         = &mst_e_lrclk.hw,
>> +     [AUD_CLKID_MST_F_LRCLK]         = &mst_f_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &tdmin_a_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &tdmin_b_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &tdmin_c_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &tdmin_lb_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &tdmout_a_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &tdmout_b_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &tdmout_c_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &tdmin_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &tdmin_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &tdmin_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &tdmin_lb_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &tdmout_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &tdmout_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &tdmout_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &tdmin_a_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &tdmin_b_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &tdmin_c_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &tdmin_lb_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &tdmout_a_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &tdmout_b_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &tdmout_c_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK]        = &tdmin_a_sclk.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK]        = &tdmin_b_sclk.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK]        = &tdmin_c_sclk.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK]       = &tdmin_lb_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK]       = &g12a_tdmout_a_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK]       = &g12a_tdmout_b_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK]       = &g12a_tdmout_c_sclk.hw,
>> +     [AUD_CLKID_TDMIN_A_LRCLK]       = &tdmin_a_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_B_LRCLK]       = &tdmin_b_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_C_LRCLK]       = &tdmin_c_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_LB_LRCLK]      = &tdmin_lb_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_A_LRCLK]      = &tdmout_a_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_B_LRCLK]      = &tdmout_b_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_C_LRCLK]      = &tdmout_c_lrclk.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0]       = &s4_tdm_mclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1]       = &s4_tdm_mclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD0]      = &s4_tdm_lrclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD1]      = &s4_tdm_lrclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD2]      = &s4_tdm_lrclk_pad_2.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD0]       = &s4_tdm_sclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD1]       = &s4_tdm_sclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD2]       = &s4_tdm_sclk_pad_2.hw,
>> +     [AUD_CLKID_TOP]                 = &sm1_aud_top.hw,
>> +     [AUD_CLKID_TORAM]               = &toram.hw,
>> +     [AUD_CLKID_EQDRC]               = &eqdrc.hw,
>> +     [AUD_CLKID_RESAMPLE_B]          = &resample_b.hw,
>> +     [AUD_CLKID_TOVAD]               = &tovad.hw,
>> +     [AUD_CLKID_LOCKER]              = &locker.hw,
>> +     [AUD_CLKID_SPDIFIN_LB]          = &spdifin_lb.hw,
>> +     [AUD_CLKID_FRDDR_D]             = &frddr_d.hw,
>> +     [AUD_CLKID_TODDR_D]             = &toddr_d.hw,
>> +     [AUD_CLKID_LOOPBACK_B]          = &loopback_b.hw,
>> +     [AUD_CLKID_CLK81_EN]            = &sm1_clk81_en.hw,
>> +     [AUD_CLKID_SYSCLK_A_DIV]        = &sm1_sysclk_a_div.hw,
>> +     [AUD_CLKID_SYSCLK_A_EN]         = &sm1_sysclk_a_en.hw,
>> +     [AUD_CLKID_SYSCLK_B_DIV]        = &sm1_sysclk_b_div.hw,
>> +     [AUD_CLKID_SYSCLK_B_EN]         = &sm1_sysclk_b_en.hw,
>> +     [AUD_CLKID_EARCRX]              = &earcrx.hw,
>> +     [AUD_CLKID_EARCRX_CMDC_SEL]     = &sm1_earcrx_cmdc_clk_sel.hw,
>> +     [AUD_CLKID_EARCRX_CMDC_DIV]     = &sm1_earcrx_cmdc_clk_div.hw,
>> +     [AUD_CLKID_EARCRX_CMDC]         = &sm1_earcrx_cmdc_clk.hw,
>> +     [AUD_CLKID_EARCRX_DMAC_SEL]     = &sm1_earcrx_dmac_clk_sel.hw,
>> +     [AUD_CLKID_EARCRX_DMAC_DIV]     = &sm1_earcrx_dmac_clk_div.hw,
>> +     [AUD_CLKID_EARCRX_DMAC]         = &sm1_earcrx_dmac_clk.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0_SEL]           = &s4_tdm_mclk_pad0_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1_SEL]       = &s4_tdm_mclk_pad1_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0_DIV]           = &s4_tdm_mclk_pad0_div.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1_DIV]       = &s4_tdm_mclk_pad1_div.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2]               = &s4_tdm_mclk_pad_2.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2_SEL]           = &s4_tdm_mclk_pad2_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2_DIV]       = &s4_tdm_mclk_pad2_div.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD3]       = &s4_tdm_sclk_pad_3.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD4]       = &s4_tdm_sclk_pad_4.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD3]      = &s4_tdm_lrclk_pad_3.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD4]      = &s4_tdm_lrclk_pad_4.hw,
>> +};
>>
>>   /* Convenience table to populate regmap in .probe(). */
>>   static struct clk_regmap *const axg_clk_regmaps[] = {
>> @@ -1678,6 +1902,174 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
>>        &sm1_earcrx_dmac_clk,
>>   };
>>
>> +static struct clk_regmap *const s4_clk_regmaps[] = {
>> +     &ddr_arb,
>> +     &pdm,
>> +     &tdmin_a,
>> +     &tdmin_b,
>> +     &tdmin_c,
>> +     &tdmin_lb,
>> +     &tdmout_a,
>> +     &tdmout_b,
>> +     &tdmout_c,
>> +     &frddr_a,
>> +     &frddr_b,
>> +     &frddr_c,
>> +     &toddr_a,
>> +     &toddr_b,
>> +     &toddr_c,
>> +     &loopback,
>> +     &spdifin,
>> +     &spdifout,
>> +     &resample,
>> +     &spdifout_b,
>> +     &sm1_mst_a_mclk_sel,
>> +     &sm1_mst_b_mclk_sel,
>> +     &sm1_mst_c_mclk_sel,
>> +     &sm1_mst_d_mclk_sel,
>> +     &sm1_mst_e_mclk_sel,
>> +     &sm1_mst_f_mclk_sel,
>> +     &sm1_mst_a_mclk_div,
>> +     &sm1_mst_b_mclk_div,
>> +     &sm1_mst_c_mclk_div,
>> +     &sm1_mst_d_mclk_div,
>> +     &sm1_mst_e_mclk_div,
>> +     &sm1_mst_f_mclk_div,
>> +     &sm1_mst_a_mclk,
>> +     &sm1_mst_b_mclk,
>> +     &sm1_mst_c_mclk,
>> +     &sm1_mst_d_mclk,
>> +     &sm1_mst_e_mclk,
>> +     &sm1_mst_f_mclk,
>> +     &spdifout_clk_sel,
>> +     &spdifout_clk_div,
>> +     &spdifout_clk,
>> +     &spdifin_clk_sel,
>> +     &spdifin_clk_div,
>> +     &spdifin_clk,
>> +     &pdm_dclk_sel,
>> +     &pdm_dclk_div,
>> +     &pdm_dclk,
>> +     &pdm_sysclk_sel,
>> +     &pdm_sysclk_div,
>> +     &pdm_sysclk,
>> +     &mst_a_sclk_pre_en,
>> +     &mst_b_sclk_pre_en,
>> +     &mst_c_sclk_pre_en,
>> +     &mst_d_sclk_pre_en,
>> +     &mst_e_sclk_pre_en,
>> +     &mst_f_sclk_pre_en,
>> +     &mst_a_sclk_div,
>> +     &mst_b_sclk_div,
>> +     &mst_c_sclk_div,
>> +     &mst_d_sclk_div,
>> +     &mst_e_sclk_div,
>> +     &mst_f_sclk_div,
>> +     &mst_a_sclk_post_en,
>> +     &mst_b_sclk_post_en,
>> +     &mst_c_sclk_post_en,
>> +     &mst_d_sclk_post_en,
>> +     &mst_e_sclk_post_en,
>> +     &mst_f_sclk_post_en,
>> +     &mst_a_sclk,
>> +     &mst_b_sclk,
>> +     &mst_c_sclk,
>> +     &mst_d_sclk,
>> +     &mst_e_sclk,
>> +     &mst_f_sclk,
>> +     &mst_a_lrclk_div,
>> +     &mst_b_lrclk_div,
>> +     &mst_c_lrclk_div,
>> +     &mst_d_lrclk_div,
>> +     &mst_e_lrclk_div,
>> +     &mst_f_lrclk_div,
>> +     &mst_a_lrclk,
>> +     &mst_b_lrclk,
>> +     &mst_c_lrclk,
>> +     &mst_d_lrclk,
>> +     &mst_e_lrclk,
>> +     &mst_f_lrclk,
>> +     &tdmin_a_sclk_sel,
>> +     &tdmin_b_sclk_sel,
>> +     &tdmin_c_sclk_sel,
>> +     &tdmin_lb_sclk_sel,
>> +     &tdmout_a_sclk_sel,
>> +     &tdmout_b_sclk_sel,
>> +     &tdmout_c_sclk_sel,
>> +     &tdmin_a_sclk_pre_en,
>> +     &tdmin_b_sclk_pre_en,
>> +     &tdmin_c_sclk_pre_en,
>> +     &tdmin_lb_sclk_pre_en,
>> +     &tdmout_a_sclk_pre_en,
>> +     &tdmout_b_sclk_pre_en,
>> +     &tdmout_c_sclk_pre_en,
>> +     &tdmin_a_sclk_post_en,
>> +     &tdmin_b_sclk_post_en,
>> +     &tdmin_c_sclk_post_en,
>> +     &tdmin_lb_sclk_post_en,
>> +     &tdmout_a_sclk_post_en,
>> +     &tdmout_b_sclk_post_en,
>> +     &tdmout_c_sclk_post_en,
>> +     &tdmin_a_sclk,
>> +     &tdmin_b_sclk,
>> +     &tdmin_c_sclk,
>> +     &tdmin_lb_sclk,
>> +     &g12a_tdmout_a_sclk,
>> +     &g12a_tdmout_b_sclk,
>> +     &g12a_tdmout_c_sclk,
>> +     &tdmin_a_lrclk,
>> +     &tdmin_b_lrclk,
>> +     &tdmin_c_lrclk,
>> +     &tdmin_lb_lrclk,
>> +     &tdmout_a_lrclk,
>> +     &tdmout_b_lrclk,
>> +     &tdmout_c_lrclk,
>> +     &spdifout_b_clk_sel,
>> +     &spdifout_b_clk_div,
>> +     &spdifout_b_clk,
>> +     &s4_tdm_mclk_pad_0,
>> +     &s4_tdm_mclk_pad_1,
>> +     &s4_tdm_lrclk_pad_0,
>> +     &s4_tdm_lrclk_pad_1,
>> +     &s4_tdm_lrclk_pad_2,
>> +     &s4_tdm_sclk_pad_0,
>> +     &s4_tdm_sclk_pad_1,
>> +     &s4_tdm_sclk_pad_2,
>> +     &sm1_aud_top,
>> +     &toram,
>> +     &eqdrc,
>> +     &resample_b,
>> +     &tovad,
>> +     &locker,
>> +     &spdifin_lb,
>> +     &frddr_d,
>> +     &toddr_d,
>> +     &loopback_b,
>> +     &sm1_clk81_en,
>> +     &sm1_sysclk_a_div,
>> +     &sm1_sysclk_a_en,
>> +     &sm1_sysclk_b_div,
>> +     &sm1_sysclk_b_en,
>> +     &earcrx,
>> +     &sm1_earcrx_cmdc_clk_sel,
>> +     &sm1_earcrx_cmdc_clk_div,
>> +     &sm1_earcrx_cmdc_clk,
>> +     &sm1_earcrx_dmac_clk_sel,
>> +     &sm1_earcrx_dmac_clk_div,
>> +     &sm1_earcrx_dmac_clk,
>> +     &s4_tdm_mclk_pad0_sel,
>> +     &s4_tdm_mclk_pad1_sel,
>> +     &s4_tdm_mclk_pad0_div,
>> +     &s4_tdm_mclk_pad1_div,
>> +     &s4_tdm_mclk_pad_2,
>> +     &s4_tdm_mclk_pad2_sel,
>> +     &s4_tdm_mclk_pad2_div,
>> +     &s4_tdm_sclk_pad_3,
>> +     &s4_tdm_sclk_pad_4,
>> +     &s4_tdm_lrclk_pad_3,
>> +     &s4_tdm_lrclk_pad_4,
>> +};
>> +
>>   struct axg_audio_reset_data {
>>        struct reset_controller_dev rstc;
>>        struct regmap *map;
>> @@ -1822,7 +2214,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>>                        continue;
>>
>>                name = hw->init->name;
>> -
>>                ret = devm_clk_hw_register(dev, hw);
>>                if (ret) {
>>                        dev_err(dev, "failed to register clock %s\n", name);
>> @@ -1886,6 +2277,18 @@ static const struct audioclk_data sm1_audioclk_data = {
>>        .max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
>>   };
>>
>> +static const struct audioclk_data s4_audioclk_data = {
>> +     .regmap_clks = s4_clk_regmaps,
>> +     .regmap_clk_num = ARRAY_SIZE(s4_clk_regmaps),
>> +     .hw_clks = {
>> +             .hws = s4_audio_hw_clks,
>> +             .num = ARRAY_SIZE(s4_audio_hw_clks),
>> +     },
>> +     .reset_offset = AUDIO_SM1_SW_RESET0,
>> +     .reset_num = 39,
>> +     .max_register = AUDIO_S4_SCLK_PAD_CTRL1,
>> +};
>> +
>>   static const struct of_device_id clkc_match_table[] = {
>>        {
>>                .compatible = "amlogic,axg-audio-clkc",
>> @@ -1896,7 +2299,10 @@ static const struct of_device_id clkc_match_table[] = {
>>        }, {
>>                .compatible = "amlogic,sm1-audio-clkc",
>>                .data = &sm1_audioclk_data
>> -     }, {}
>> +     }, {
>> +             .compatible = "amlogic,s4-audio-clkc",
>> +             .data = &s4_audioclk_data
>> +     }, { }
>>   };
>>   MODULE_DEVICE_TABLE(of, clkc_match_table);
>>
>> diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
>> index 9e7765b630c96a8029140539ffda789b7db5277a..2dd1c41d775da8f91ed281470d06e9c970cfc92c 100644
>> --- a/drivers/clk/meson/axg-audio.h
>> +++ b/drivers/clk/meson/axg-audio.h
>> @@ -66,5 +66,9 @@
>>   #define AUDIO_CLK81_EN               0x034
>>   #define AUDIO_EARCRX_CMDC_CLK_CTRL   0x0D0
>>   #define AUDIO_EARCRX_DMAC_CLK_CTRL   0x0D4
> Judging by the DT posted, there is plenty in between of non-clock
> component in between these 2 offsets/regions
>
>> +#define AUDIO_S4_MCLK_PAD_CTRL0 0xE80
>> +#define AUDIO_S4_MCLK_PAD_CTRL1 0xE84
>> +#define AUDIO_S4_SCLK_PAD_CTRL0 0xE88
>> +#define AUDIO_S4_SCLK_PAD_CTRL1 0xE8C
>>
> ... and this is not even mapped by the clock controller, so this won't
> work with the DT you have posted.

Hi, Jerome

thanks, I will recheck the register offset regmap, some register is? 
really not friendly enough,

so the software may need to change a lot in order to be compatible

>
>>   #endif /*__AXG_AUDIO_CLKC_H */
> --
> Jerome


From fj5100bi at fujitsu.com  Thu Mar  6 19:10:47 2025
From: fj5100bi at fujitsu.com (Yoshihiro Furudera (Fujitsu))
Date: Fri, 7 Mar 2025 03:10:47 +0000
Subject: [PATCH] Remove some PMU events for FUJITSU-MONAKA
In-Reply-To: <36123515-a268-40cb-b010-2600c2f5c1c6@linaro.org>
References: <20250227054045.1340090-1-fj5100bi@fujitsu.com>
 <96b323eb-15b2-4b60-8522-83bf2f57694b@linaro.org>
 <OSZPR01MB6908AA7CEB24ED38F9289D6DD4CC2@OSZPR01MB6908.jpnprd01.prod.outlook.com>
 <OS3PR01MB6903726FDA70250F72A73410D4CB2@OS3PR01MB6903.jpnprd01.prod.outlook.com>
 <36123515-a268-40cb-b010-2600c2f5c1c6@linaro.org>
Message-ID: <OS3PR01MB690377379ED81FDF8D60142DD4D52@OS3PR01MB6903.jpnprd01.prod.outlook.com>

Hi, James
Thank you for your comment.

> On 05/03/2025 6:40 am, Yoshihiro Furudera (Fujitsu) wrote:
> > Hi, James
> >
> >>
> >> Hi, James
> >> Thank you for your comment.
> >>
> >>> On 27/02/2025 5:40 am, Yoshihiro Furudera wrote:
> >>>> The following events are not counted properly:
> >>>>
> >>>> 0x0037 LL_CACHE_MISS_RD
> >>>> 0x400B L3D_CACHE_LMISS_RD
> >>>
> >>> These two are discoverable so will still appear in
> >>> /sys/bus/event_source/devices/armv8_pmuv3_0/events/ if the hardware
> >>> says they exist. It might be better to change the json strings of
> >>> these two to warn that they don't work if that's the case, otherwise
> >>> Perf will still list them and you'll be worse off.
> >>
> >> I will leave these 2 events and
> >> add a warning message to the description in the JSON file.
> >> I will handle other events in the same way as these 2 events.
> >
> > I'm thinking of adding one of the following warnings to the
> > description of events where inaccurate counts occur on FUJITSU-MONAKA.
> > Is this okay?
> >
> > 1.Simple version
> > "Note: This event does not count accurately."
> >
> > 2.Detailed version
> > "Note: This event does not count accurately because it counts as a miss
> regardless of whether the L3 prefetch is a hit or miss."
> >
> > I think "2.Detailed version" is better.
> >
> > example:
> > {
> >      "EventCode": "0x0396",
> >      "EventName": "L2D_CACHE_REFILL_L3D_MISS",
> >      "BriefDescription": "This event counts operations that cause a miss of the
> L3 cache. Note: This event does not count accurately because it counts as a miss
> regardless of whether the L3 prefetch is a hit or miss."
> > }
> >
> > Best Regards,
> > Yoshihiro Furudera
> 
> You could have both by using BriefDescription and PublicDescription. The longer
> one being available with 'perf list -v'. I think that's what that feature is for.

Thank you for your suggestion.
After discussing this with the OS team,
we would like to move forward with the policy of
defining "2.Detailed version" in the Brief Description.
Please let me make a final decision after discussing it
with the hardware team.

> 
> Either way you should probably also update the description before the note, so
> add 'hit or miss' to the first sentence:
> 
> "EventCode": "0x0396",
> "EventName": "L2D_CACHE_REFILL_L3D_MISS",
> "BriefDescription": "This event counts operations that cause a hit or miss of the L3
> cache. Note that this incorrectly counts both hits _and_ misses."

We will also discuss with the hardware team on this matter.

Best Regards,
Yoshihiro Furudera

From faizal.abdul.rahim at linux.intel.com  Thu Mar  6 19:20:53 2025
From: faizal.abdul.rahim at linux.intel.com (Abdul Rahim, Faizal)
Date: Fri, 7 Mar 2025 11:20:53 +0800
Subject: [PATCH iwl-next v8 11/11] igc: add support to get frame
 preemption statistics via ethtool
In-Reply-To: <20250306004809.q2x565rys5zja6kh@skbuf>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-12-faizal.abdul.rahim@linux.intel.com>
 <20250306004809.q2x565rys5zja6kh@skbuf>
Message-ID: <df5f2ff0-2ead-4074-a40e-8a2fc9b63339@linux.intel.com>



On 6/3/2025 8:48 am, Vladimir Oltean wrote:
> On Wed, Mar 05, 2025 at 08:00:26AM -0500, Faizal Rahim wrote:
>> +/* Received out of order packets with SMD-C */
>> +#define IGC_PRMEXCPRCNT_OOO_SMDC			0x000000FF
>> +/* Received out of order packets with SMD-C and wrong Frame CNT */
>> +#define IGC_PRMEXCPRCNT_OOO_FRAME_CNT			0x0000FF00
>> +/* Received out of order packets with SMD-C and wrong Frag CNT */
>> +#define IGC_PRMEXCPRCNT_OOO_FRAG_CNT			0x00FF0000
>> +/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
>> +#define IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
>>   
>> +/**
>> + * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
>> + * @reg_value: Register value for IGC_PRMEXCPRCNT
>> + * Return: The count of frame assembly errors.
>> + */
>> +static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
>> +{
>> +	u32 ooo_frame_cnt, ooo_frag_cnt; /* Out of order statistics */
>> +	u32 miss_frame_frag_cnt;
>> +
>> +	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
>> +	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
>> +	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
>> +
>> +	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
>> +}
> 
> These counters are quite small (8 bits each). What is their behavior
> once they reach 255? Saturate? Truncate? Do they clear on read?
> 
Hi Vladimir,

These are part of the statistic registers, which in IGC, reset upon read. 
When they reach their maximum value, each field remain at 0xFF.




From hanchunchao at inspur.com  Thu Mar  6 19:25:28 2025
From: hanchunchao at inspur.com (Charles Han)
Date: Fri, 7 Mar 2025 11:25:28 +0800
Subject: [PATCH] spi: stm32: Fix a NULL vs IS_ERR() bug
Message-ID: <20250307032530.116837-1-hanchunchao@inspur.com>

The devm_ioremap() function doesn't return error pointers, it may
returns NULL.  Update the error checking to match.

Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
Signed-off-by: Charles Han <hanchunchao at inspur.com>
---
 drivers/spi/spi-stm32-ospi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index 8eadcb64f34a..a544d7897edf 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -835,10 +835,10 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
 	if (rmem) {
 		ospi->mm_size = rmem->size;
 		ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size);
-		if (IS_ERR(ospi->mm_base)) {
+		if (!ospi->mm_base) {
 			dev_err(dev, "unable to map memory region: %pa+%pa\n",
 				&rmem->base, &rmem->size);
-			ret = PTR_ERR(ospi->mm_base);
+			ret = -ENOMEM;
 			goto err_dma;
 		}
 
-- 
2.43.0



From guangjie.song at mediatek.com  Thu Mar  6 19:27:10 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:10 +0800
Subject: [PATCH 14/26] clk: mediatek: Add MT8196 i2c clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-15-guangjie.song@mediatek.com>

Add MT8196 i2c clock controller which provides clock gate control for
i2c.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig                  |   7 +
 drivers/clk/mediatek/Makefile                 |   1 +
 .../clk/mediatek/clk-mt8196-imp_iic_wrap.c    | 211 ++++++++++++++++++
 3 files changed, 219 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-imp_iic_wrap.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index fe54dca0062e..bc373e9ab589 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1017,6 +1017,13 @@ config COMMON_CLK_MT8196_ADSP
 	help
 	  This driver supports MediaTek MT8196 adsp clocks
 
+config COMMON_CLK_MT8196_IMP_IIC_WRAP
+	tristate "Clock driver for MediaTek MT8196 imp_iic_wrap"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 i2c clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index c0d676930a80..beea4d8eeebe 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -154,6 +154,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys
 				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o \
 				   clk-mt8196-peri_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8196_ADSP) += clk-mt8196-adsp.o
+obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8196-imp_iic_wrap.c
new file mode 100644
index 000000000000..c514882e957e
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-imp_iic_wrap.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs impc_cg_regs = {
+	.set_ofs = 0xe08,
+	.clr_ofs = 0xe04,
+	.sta_ofs = 0xe00,
+};
+
+#define GATE_IMPC(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &impc_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_IMPC_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate impc_clks[] = {
+	GATE_IMPC(CLK_IMPC_I2C11, "impc_i2c11", "ck_i2c_p_ck", 0),
+	GATE_IMPC_V(CLK_IMPC_I2C11_I2C, "impc_i2c11_i2c", "impc_i2c11"),
+	GATE_IMPC(CLK_IMPC_I2C12, "impc_i2c12", "ck_i2c_p_ck", 1),
+	GATE_IMPC_V(CLK_IMPC_I2C12_I2C, "impc_i2c12_i2c", "impc_i2c12"),
+	GATE_IMPC(CLK_IMPC_I2C13, "impc_i2c13", "ck_i2c_p_ck", 2),
+	GATE_IMPC_V(CLK_IMPC_I2C13_I2C, "impc_i2c13_i2c", "impc_i2c13"),
+	GATE_IMPC(CLK_IMPC_I2C14, "impc_i2c14", "ck_i2c_p_ck", 3),
+	GATE_IMPC_V(CLK_IMPC_I2C14_I2C, "impc_i2c14_i2c", "impc_i2c14"),
+};
+
+static const struct mtk_clk_desc impc_mcd = {
+	.clks = impc_clks,
+	.num_clks = ARRAY_SIZE(impc_clks),
+};
+
+static const struct mtk_gate_regs impe_cg_regs = {
+	.set_ofs = 0xe08,
+	.clr_ofs = 0xe04,
+	.sta_ofs = 0xe00,
+};
+
+#define GATE_IMPE(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &impe_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_IMPE_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate impe_clks[] = {
+	GATE_IMPE(CLK_IMPE_I2C5, "impe_i2c5", "ck_i2c_east_ck", 0),
+	GATE_IMPE_V(CLK_IMPE_I2C5_I2C, "impe_i2c5_i2c", "impe_i2c5"),
+};
+
+static const struct mtk_clk_desc impe_mcd = {
+	.clks = impe_clks,
+	.num_clks = ARRAY_SIZE(impe_clks),
+};
+
+static const struct mtk_gate_regs impn_cg_regs = {
+	.set_ofs = 0xe08,
+	.clr_ofs = 0xe04,
+	.sta_ofs = 0xe00,
+};
+
+static const struct mtk_gate_regs impn_vote_regs = {
+	.set_ofs = 0x0000,
+	.clr_ofs = 0x0004,
+	.sta_ofs = 0x2c00,
+};
+
+#define GATE_IMPN(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &impn_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_IMPN_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_IMPN(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "vote-regmap",		\
+		.regs = &impn_cg_regs,			\
+		.vote_regs = &impn_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate impn_clks[] = {
+	GATE_IMPN(CLK_IMPN_I2C1, "impn_i2c1", "ck_i2c_north_ck", 0),
+	GATE_IMPN_V(CLK_IMPN_I2C1_I2C, "impn_i2c1_i2c", "impn_i2c1"),
+	GATE_IMPN(CLK_IMPN_I2C2, "impn_i2c2", "ck_i2c_north_ck", 1),
+	GATE_IMPN_V(CLK_IMPN_I2C2_I2C, "impn_i2c2_i2c", "impn_i2c2"),
+	GATE_IMPN(CLK_IMPN_I2C4, "impn_i2c4", "ck_i2c_north_ck", 2),
+	GATE_IMPN_V(CLK_IMPN_I2C4_I2C, "impn_i2c4_i2c", "impn_i2c4"),
+	GATE_VOTE_IMPN(CLK_IMPN_I2C7, "impn_i2c7", "ck_i2c_north_ck", 3),
+	GATE_IMPN_V(CLK_IMPN_I2C7_I2C, "impn_i2c7_i2c", "impn_i2c7"),
+	GATE_IMPN(CLK_IMPN_I2C8, "impn_i2c8", "ck_i2c_north_ck", 4),
+	GATE_IMPN_V(CLK_IMPN_I2C8_I2C, "impn_i2c8_i2c", "impn_i2c8"),
+	GATE_IMPN(CLK_IMPN_I2C9, "impn_i2c9", "ck_i2c_north_ck", 5),
+	GATE_IMPN_V(CLK_IMPN_I2C9_I2C, "impn_i2c9_i2c", "impn_i2c9"),
+};
+
+static const struct mtk_clk_desc impn_mcd = {
+	.clks = impn_clks,
+	.num_clks = ARRAY_SIZE(impn_clks),
+};
+
+static const struct mtk_gate_regs impw_cg_regs = {
+	.set_ofs = 0xe08,
+	.clr_ofs = 0xe04,
+	.sta_ofs = 0xe00,
+};
+
+#define GATE_IMPW(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &impw_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_IMPW_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate impw_clks[] = {
+	GATE_IMPW(CLK_IMPW_I2C0, "impw_i2c0", "ck_i2c_west_ck", 0),
+	GATE_IMPW_V(CLK_IMPW_I2C0_I2C, "impw_i2c0_i2c", "impw_i2c0"),
+	GATE_IMPW(CLK_IMPW_I2C3, "impw_i2c3", "ck_i2c_west_ck", 1),
+	GATE_IMPW_V(CLK_IMPW_I2C3_I2C, "impw_i2c3_i2c", "impw_i2c3"),
+	GATE_IMPW(CLK_IMPW_I2C6, "impw_i2c6", "ck_i2c_west_ck", 2),
+	GATE_IMPW_V(CLK_IMPW_I2C6_I2C, "impw_i2c6_i2c", "impw_i2c6"),
+	GATE_IMPW(CLK_IMPW_I2C10, "impw_i2c10", "ck_i2c_west_ck", 3),
+	GATE_IMPW_V(CLK_IMPW_I2C10_I2C, "impw_i2c10_i2c", "impw_i2c10"),
+};
+
+static const struct mtk_clk_desc impw_mcd = {
+	.clks = impw_clks,
+	.num_clks = ARRAY_SIZE(impw_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8196_imp_iic_wrap[] = {
+	{ .compatible = "mediatek,mt8196-imp_iic_wrap_c", .data = &impc_mcd, },
+	{ .compatible = "mediatek,mt8196-imp_iic_wrap_e", .data = &impe_mcd, },
+	{ .compatible = "mediatek,mt8196-imp_iic_wrap_n", .data = &impn_mcd, },
+	{ .compatible = "mediatek,mt8196-imp_iic_wrap_w", .data = &impw_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_imp_iic_wrap_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-imp_iic_wrap",
+		.of_match_table = of_match_clk_mt8196_imp_iic_wrap,
+	},
+};
+
+module_platform_driver(clk_mt8196_imp_iic_wrap_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:26:56 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:26:56 +0800
Subject: [PATCH 00/26] clk: mediatek: Add MT8196 clock support
Message-ID: <20250307032942.10447-1-guangjie.song@mediatek.com>

This series is based on linux-next, tag: next-20250306.

Changes:
- Update clock driver for MT8196
- Add MT8196 clock support

Guangjie Song (26):
  clk: mediatek: Add defines for vote
  clk: mediatek: Support voting for pll
  clk: mediatek: Support voting for mux
  clk: mediatek: Support voting for gate
  clk: mediatek: Add gate ops without disable
  dt-bindings: clock: mediatek: Add new MT8196 clock
  clk: mediatek: Add MT8196 apmixedsys clock support
  clk: mediatek: Add MT8196 apmixedsys_gp2 clock support
  clk: mediatek: Add MT8196 topckgen clock support
  clk: mediatek: Add MT8196 topckgen2 clock support
  clk: mediatek: Add MT8196 vlpckgen clock support
  clk: mediatek: Add MT8196 peripheral clock support
  clk: mediatek: Add MT8196 adsp clock support
  clk: mediatek: Add MT8196 i2c clock support
  clk: mediatek: Add MT8196 mcu clock support
  clk: mediatek: Add MT8196 mdpsys clock support
  clk: mediatek: Add MT8196 mfg clock support
  clk: mediatek: Add MT8196 disp0 clock support
  clk: mediatek: Add MT8196 disp1 clock support
  clk: mediatek: Add MT8196 disp-ao clock support
  clk: mediatek: Add MT8196 ovl0 clock support
  clk: mediatek: Add MT8196 ovl1 clock support
  clk: mediatek: Add MT8196 pextpsys clock support
  clk: mediatek: Add MT8196 ufssys clock support
  clk: mediatek: Add MT8196 vdecsys clock support
  clk: mediatek: Add MT8196 vencsys clock support

 .../bindings/clock/mediatek,mt8196-clock.yaml |   66 +
 .../clock/mediatek,mt8196-sys-clock.yaml      |   63 +
 drivers/clk/mediatek/Kconfig                  |   78 +
 drivers/clk/mediatek/Makefile                 |   14 +
 drivers/clk/mediatek/clk-gate.c               |  236 ++-
 drivers/clk/mediatek/clk-gate.h               |    6 +
 drivers/clk/mediatek/clk-mt8196-adsp.c        |  291 ++++
 drivers/clk/mediatek/clk-mt8196-apmixedsys.c  |  146 ++
 .../clk/mediatek/clk-mt8196-apmixedsys_gp2.c  |  154 ++
 drivers/clk/mediatek/clk-mt8196-disp0.c       |  247 +++
 drivers/clk/mediatek/clk-mt8196-disp1.c       |  260 +++
 .../clk/mediatek/clk-mt8196-imp_iic_wrap.c    |  211 +++
 drivers/clk/mediatek/clk-mt8196-mcu.c         |  167 ++
 drivers/clk/mediatek/clk-mt8196-mdpsys.c      |  357 ++++
 drivers/clk/mediatek/clk-mt8196-mfg.c         |  143 ++
 drivers/clk/mediatek/clk-mt8196-ovl0.c        |  256 +++
 drivers/clk/mediatek/clk-mt8196-ovl1.c        |  255 +++
 drivers/clk/mediatek/clk-mt8196-peri_ao.c     |  218 +++
 drivers/clk/mediatek/clk-mt8196-pextp.c       |  162 ++
 drivers/clk/mediatek/clk-mt8196-topckgen.c    | 1373 +++++++++++++++
 drivers/clk/mediatek/clk-mt8196-topckgen2.c   |  701 ++++++++
 drivers/clk/mediatek/clk-mt8196-ufs_ao.c      |  107 ++
 drivers/clk/mediatek/clk-mt8196-vdec.c        |  449 +++++
 drivers/clk/mediatek/clk-mt8196-vdisp_ao.c    |  100 ++
 drivers/clk/mediatek/clk-mt8196-venc.c        |  413 +++++
 drivers/clk/mediatek/clk-mt8196-vlpckgen.c    |  777 +++++++++
 drivers/clk/mediatek/clk-mtk.h                |   10 +
 drivers/clk/mediatek/clk-mux.c                |  198 ++-
 drivers/clk/mediatek/clk-mux.h                |   79 +
 drivers/clk/mediatek/clk-pll.c                |   51 +-
 drivers/clk/mediatek/clk-pll.h                |    5 +
 include/dt-bindings/clock/mt8196-clk.h        | 1503 +++++++++++++++++
 32 files changed, 9086 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml
 create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml
 create mode 100644 drivers/clk/mediatek/clk-mt8196-adsp.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-apmixedsys.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-apmixedsys_gp2.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-disp0.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-disp1.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-imp_iic_wrap.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mcu.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mdpsys.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mfg.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ovl0.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ovl1.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-peri_ao.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-pextp.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-topckgen.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-topckgen2.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ufs_ao.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vdisp_ao.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-venc.c
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vlpckgen.c
 create mode 100644 include/dt-bindings/clock/mt8196-clk.h

-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:26:57 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:26:57 +0800
Subject: [PATCH 01/26] clk: mediatek: Add defines for vote
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-2-guangjie.song@mediatek.com>

Clock supports voting mechanism. If any xPU votes clock on, the clock keep
on.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/clk-mtk.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index c17fe1c2d732..ba3917aabd83 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -20,6 +20,16 @@
 
 #define MHZ (1000 * 1000)
 
+#define MTK_WAIT_VOTE_PREPARE_CNT	200000
+#define MTK_WAIT_VOTE_PREPARE_US	1
+#define MTK_WAIT_VOTE_DONE_CNT		5000000
+#define MTK_WAIT_VOTE_DONE_US		1
+#define MTK_WAIT_FENC_DONE_CNT		5000000
+#define MTK_WAIT_FENC_DONE_US		1
+
+#define CLK_USE_VOTE	BIT(30)
+#define CLK_FENC_ENABLE	BIT(31)
+
 struct platform_device;
 
 /*
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:00 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:00 +0800
Subject: [PATCH 04/26] clk: mediatek: Support voting for gate
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-5-guangjie.song@mediatek.com>

Add data fields and ops to support voting for gate.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/clk-gate.c | 230 +++++++++++++++++++++++++++++++-
 drivers/clk/mediatek/clk-gate.h |   5 +
 2 files changed, 228 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index 67d9e741c5e7..be6cf4a6d246 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -12,14 +12,19 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
+#include "clk-mtk.h"
 #include "clk-gate.h"
 
 struct mtk_clk_gate {
 	struct clk_hw	hw;
 	struct regmap	*regmap;
+	struct regmap	*vote_regmap;
 	int		set_ofs;
 	int		clr_ofs;
 	int		sta_ofs;
+	int		vote_set_ofs;
+	int		vote_clr_ofs;
+	int		vote_sta_ofs;
 	u8		bit;
 };
 
@@ -100,6 +105,143 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
 	mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_vote_is_set(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 val = 0;
+
+	regmap_read(cg->vote_regmap, cg->vote_set_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static int mtk_cg_vote_is_done(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 val = 0;
+
+	regmap_read(cg->vote_regmap, cg->vote_sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static int __cg_vote_enable(struct clk_hw *hw, bool inv)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 val = 0, val2 = 0;
+	bool is_done = false;
+	int i = 0;
+
+	regmap_write(cg->vote_regmap, cg->vote_set_ofs, BIT(cg->bit));
+
+	while (!mtk_cg_vote_is_set(hw)) {
+		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
+			udelay(MTK_WAIT_VOTE_PREPARE_US);
+		} else {
+			pr_err("%s cg prepare timeout\n", clk_hw_get_name(hw));
+			return -EBUSY;
+		}
+
+		i++;
+	}
+
+	i = 0;
+
+	while (1) {
+		if (!is_done)
+			regmap_read(cg->vote_regmap, cg->vote_sta_ofs, &val);
+
+		if ((val & BIT(cg->bit)) != 0)
+			is_done = true;
+
+		if (is_done) {
+			regmap_read(cg->regmap, cg->sta_ofs, &val2);
+			if ((inv && (val2 & BIT(cg->bit)) != 0) ||
+			    (!inv && (val2 & BIT(cg->bit)) == 0))
+				break;
+		}
+
+		if (i < MTK_WAIT_VOTE_DONE_CNT) {
+			udelay(MTK_WAIT_VOTE_DONE_US);
+		} else {
+			pr_err("%s cg enable timeout(%x %x)\n", clk_hw_get_name(hw), val, val2);
+
+			if (inv)
+				regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+			else
+				regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+
+			return -EBUSY;
+		}
+
+		i++;
+	}
+
+	return 0;
+}
+
+static int mtk_cg_vote_enable(struct clk_hw *hw)
+{
+	return __cg_vote_enable(hw, false);
+}
+
+static int mtk_cg_vote_enable_inv(struct clk_hw *hw)
+{
+	return __cg_vote_enable(hw, true);
+}
+
+static void mtk_cg_vote_disable(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 val;
+	int i = 0;
+
+	/* dummy read to clr idle signal of hw voter bus */
+	regmap_read(cg->vote_regmap, cg->vote_clr_ofs, &val);
+
+	regmap_write(cg->vote_regmap, cg->vote_clr_ofs, BIT(cg->bit));
+
+	while (mtk_cg_vote_is_set(hw)) {
+		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
+			udelay(MTK_WAIT_VOTE_PREPARE_US);
+		} else {
+			pr_err("%s cg unprepare timeout\n", clk_hw_get_name(hw));
+			return;
+		}
+
+		i++;
+	}
+
+	i = 0;
+
+	while (!mtk_cg_vote_is_done(hw)) {
+		if (i < MTK_WAIT_VOTE_DONE_CNT) {
+			udelay(MTK_WAIT_VOTE_DONE_US);
+		} else {
+			pr_err("%s cg disable timeout\n", clk_hw_get_name(hw));
+			return;
+		}
+
+		i++;
+	}
+}
+
+static void mtk_cg_vote_disable_unused(struct clk_hw *hw)
+{
+	mtk_cg_vote_enable(hw);
+	mtk_cg_vote_disable(hw);
+}
+
+static void mtk_cg_vote_disable_unused_inv(struct clk_hw *hw)
+{
+	mtk_cg_vote_enable_inv(hw);
+	mtk_cg_vote_disable(hw);
+}
+
 static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
 {
 	mtk_cg_clr_bit_no_setclr(hw);
@@ -138,6 +280,22 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 };
 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr_inv);
 
+const struct clk_ops mtk_clk_gate_ops_vote = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_vote_enable,
+	.disable	= mtk_cg_vote_disable,
+	.disable_unused	= mtk_cg_vote_disable_unused,
+};
+EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_vote);
+
+const struct clk_ops mtk_clk_gate_ops_vote_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_vote_enable_inv,
+	.disable	= mtk_cg_vote_disable,
+	.disable_unused	= mtk_cg_vote_disable_unused_inv,
+};
+EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_vote_inv);
+
 const struct clk_ops mtk_clk_gate_ops_no_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable_no_setclr,
@@ -190,6 +348,53 @@ static struct clk_hw *mtk_clk_register_gate(struct device *dev, const char *name
 	return &cg->hw;
 }
 
+static struct clk_hw *mtk_clk_register_gate_vote(struct device *dev,
+						 const struct mtk_gate *gate,
+						 struct regmap *regmap,
+						 struct regmap *vote_regmap)
+{
+	struct mtk_clk_gate *cg;
+	int ret;
+	struct clk_init_data init = {};
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = gate->name;
+	init.flags = gate->flags | CLK_SET_RATE_PARENT;
+	init.parent_names = gate->parent_name ? &gate->parent_name : NULL;
+	init.num_parents = gate->parent_name ? 1 : 0;
+	if (vote_regmap)
+		init.ops = gate->ops;
+	else
+		init.ops = gate->dma_ops;
+
+	cg->regmap = regmap;
+	cg->vote_regmap = vote_regmap;
+	if (gate->regs) {
+		cg->set_ofs = gate->regs->set_ofs;
+		cg->clr_ofs = gate->regs->clr_ofs;
+		cg->sta_ofs = gate->regs->sta_ofs;
+	}
+	if (gate->vote_regs) {
+		cg->vote_set_ofs = gate->vote_regs->set_ofs;
+		cg->vote_clr_ofs = gate->vote_regs->clr_ofs;
+		cg->vote_sta_ofs = gate->vote_regs->sta_ofs;
+	}
+	cg->bit = gate->shift;
+
+	cg->hw.init = &init;
+
+	ret = clk_hw_register(dev, &cg->hw);
+	if (ret) {
+		kfree(cg);
+		return ERR_PTR(ret);
+	}
+
+	return &cg->hw;
+}
+
 static void mtk_clk_unregister_gate(struct clk_hw *hw)
 {
 	struct mtk_clk_gate *cg;
@@ -209,6 +414,7 @@ int mtk_clk_register_gates(struct device *dev, struct device_node *node,
 	int i;
 	struct clk_hw *hw;
 	struct regmap *regmap;
+	struct regmap  *vote_regmap = NULL;
 
 	if (!clk_data)
 		return -ENOMEM;
@@ -228,13 +434,23 @@ int mtk_clk_register_gates(struct device *dev, struct device_node *node,
 			continue;
 		}
 
-		hw = mtk_clk_register_gate(dev, gate->name, gate->parent_name,
-					    regmap,
-					    gate->regs->set_ofs,
-					    gate->regs->clr_ofs,
-					    gate->regs->sta_ofs,
-					    gate->shift, gate->ops,
-					    gate->flags);
+		if (gate->flags & CLK_USE_VOTE) {
+			if (gate->vote_comp) {
+				vote_regmap = syscon_regmap_lookup_by_phandle(node, gate->vote_comp);
+				if (IS_ERR(vote_regmap))
+					vote_regmap = NULL;
+			}
+
+			hw = mtk_clk_register_gate_vote(dev, gate, regmap, vote_regmap);
+		} else {
+			hw = mtk_clk_register_gate(dev, gate->name, gate->parent_name,
+						   regmap,
+						   gate->regs->set_ofs,
+						   gate->regs->clr_ofs,
+						   gate->regs->sta_ofs,
+						   gate->shift, gate->ops,
+						   gate->flags);
+		}
 
 		if (IS_ERR(hw)) {
 			pr_err("Failed to register clk %s: %pe\n", gate->name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index 1a46b4c56fc5..7d93fc84ad51 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -19,6 +19,8 @@ extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_vote;
+extern const struct clk_ops mtk_clk_gate_ops_vote_inv;
 
 struct mtk_gate_regs {
 	u32 sta_ofs;
@@ -30,9 +32,12 @@ struct mtk_gate {
 	int id;
 	const char *name;
 	const char *parent_name;
+	const char *vote_comp;
 	const struct mtk_gate_regs *regs;
+	const struct mtk_gate_regs *vote_regs;
 	int shift;
 	const struct clk_ops *ops;
+	const struct clk_ops *dma_ops;
 	unsigned long flags;
 };
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:26:59 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:26:59 +0800
Subject: [PATCH 03/26] clk: mediatek: Support voting for mux
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-4-guangjie.song@mediatek.com>

Add data fields, defines and ops to support voting for mux.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/clk-mux.c | 198 ++++++++++++++++++++++++++++++++-
 drivers/clk/mediatek/clk-mux.h |  79 +++++++++++++
 2 files changed, 275 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
index 60990296450b..8a2c89cb3cd5 100644
--- a/drivers/clk/mediatek/clk-mux.c
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -15,11 +15,13 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
+#include "clk-mtk.h"
 #include "clk-mux.h"
 
 struct mtk_clk_mux {
 	struct clk_hw hw;
 	struct regmap *regmap;
+	struct regmap *vote_regmap;
 	const struct mtk_mux *data;
 	spinlock_t *lock;
 	bool reparent;
@@ -30,6 +32,46 @@ static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
 	return container_of(hw, struct mtk_clk_mux, hw);
 }
 
+static int mtk_clk_mux_fenc_enable_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	unsigned long flags = 0;
+	u32 val = 0;
+	int i = 0;
+	int ret = 0;
+
+	if (mux->lock)
+		spin_lock_irqsave(mux->lock, flags);
+	else
+		__acquire(mux->lock);
+
+	regmap_write(mux->regmap, mux->data->clr_ofs, BIT(mux->data->gate_shift));
+
+	while (1) {
+		regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val);
+
+		if ((val & BIT(mux->data->fenc_shift)) != 0)
+			break;
+
+		if (i < MTK_WAIT_FENC_DONE_CNT) {
+			udelay(MTK_WAIT_FENC_DONE_US);
+		} else {
+			pr_err("%s wait fenc done timeout\n", clk_hw_get_name(hw));
+			ret = -EBUSY;
+			break;
+		}
+
+		i++;
+	}
+
+	if (mux->lock)
+		spin_unlock_irqrestore(mux->lock, flags);
+	else
+		__release(mux->lock);
+
+	return ret;
+}
+
 static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
 {
 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
@@ -70,6 +112,16 @@ static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
 			BIT(mux->data->gate_shift));
 }
 
+static int mtk_clk_mux_fenc_is_enabled(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	u32 val = 0;
+
+	regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val);
+
+	return (val & BIT(mux->data->fenc_shift)) != 0;
+}
+
 static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
 {
 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
@@ -80,6 +132,106 @@ static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
 	return (val & BIT(mux->data->gate_shift)) == 0;
 }
 
+static int mtk_clk_vote_mux_is_enabled(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	u32 val = 0;
+
+	regmap_read(mux->vote_regmap, mux->data->vote_set_ofs, &val);
+
+	return (val & BIT(mux->data->gate_shift)) != 0;
+}
+
+static int mtk_clk_vote_mux_is_done(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	u32 val = 0;
+
+	regmap_read(mux->vote_regmap, mux->data->vote_sta_ofs, &val);
+
+	return (val & BIT(mux->data->gate_shift)) != 0;
+}
+
+static int mtk_clk_mux_vote_fenc_enable(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	u32 val = 0, val2 = 0;
+	bool is_done = false;
+	int i = 0;
+
+	regmap_write(mux->vote_regmap, mux->data->vote_set_ofs, BIT(mux->data->gate_shift));
+
+	while (!mtk_clk_vote_mux_is_enabled(hw)) {
+		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
+			udelay(MTK_WAIT_VOTE_PREPARE_US);
+		} else {
+			pr_err("%s mux prepare timeout(%x)\n", clk_hw_get_name(hw), val);
+			return -EBUSY;
+		}
+
+		i++;
+	}
+
+	i = 0;
+
+	while (1) {
+		if (!is_done)
+			regmap_read(mux->vote_regmap, mux->data->vote_sta_ofs, &val);
+
+		if (((val & BIT(mux->data->gate_shift)) != 0))
+			is_done = true;
+
+		if (is_done) {
+			regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val2);
+			if ((val2 & BIT(mux->data->fenc_shift)) != 0)
+				break;
+		}
+
+		if (i < MTK_WAIT_VOTE_DONE_CNT) {
+			udelay(MTK_WAIT_VOTE_DONE_US);
+		} else {
+			pr_err("%s mux enable timeout(%x %x)\n", clk_hw_get_name(hw), val, val2);
+			return -EBUSY;
+		}
+
+		i++;
+	}
+
+	return 0;
+}
+
+static void mtk_clk_mux_vote_disable(struct clk_hw *hw)
+{
+	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+	int i = 0;
+
+	regmap_write(mux->vote_regmap, mux->data->vote_clr_ofs, BIT(mux->data->gate_shift));
+
+	while (mtk_clk_vote_mux_is_enabled(hw)) {
+		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
+			udelay(MTK_WAIT_VOTE_PREPARE_US);
+		} else {
+			pr_err("%s mux unprepare timeout\n", clk_hw_get_name(hw));
+			return;
+		}
+
+		i++;
+	}
+
+	i = 0;
+
+	while (!mtk_clk_vote_mux_is_done(hw)) {
+		if (i < MTK_WAIT_VOTE_DONE_CNT) {
+			udelay(MTK_WAIT_VOTE_DONE_US);
+		} else {
+			pr_err("%s mux disable timeout\n", clk_hw_get_name(hw));
+			return;
+		}
+
+		i++;
+	}
+}
+
 static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
 {
 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
@@ -151,6 +303,12 @@ static int mtk_clk_mux_determine_rate(struct clk_hw *hw,
 	return clk_mux_determine_rate_flags(hw, req, mux->data->flags);
 }
 
+static void mtk_clk_mux_vote_fenc_disable_unused(struct clk_hw *hw)
+{
+	mtk_clk_mux_vote_fenc_enable(hw);
+	mtk_clk_mux_vote_disable(hw);
+}
+
 const struct clk_ops mtk_mux_clr_set_upd_ops = {
 	.get_parent = mtk_clk_mux_get_parent,
 	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
@@ -168,9 +326,31 @@ const struct clk_ops mtk_mux_gate_clr_set_upd_ops  = {
 };
 EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops);
 
+const struct clk_ops mtk_mux_gate_fenc_clr_set_upd_ops = {
+	.enable = mtk_clk_mux_fenc_enable_setclr,
+	.disable = mtk_clk_mux_disable_setclr,
+	.is_enabled = mtk_clk_mux_fenc_is_enabled,
+	.get_parent = mtk_clk_mux_get_parent,
+	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
+	.determine_rate = mtk_clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(mtk_mux_gate_fenc_clr_set_upd_ops);
+
+const struct clk_ops mtk_mux_vote_fenc_ops = {
+	.enable = mtk_clk_mux_vote_fenc_enable,
+	.disable = mtk_clk_mux_vote_disable,
+	.is_enabled = mtk_clk_mux_fenc_is_enabled,
+	.get_parent = mtk_clk_mux_get_parent,
+	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
+	.determine_rate = mtk_clk_mux_determine_rate,
+	.disable_unused = mtk_clk_mux_vote_fenc_disable_unused,
+};
+EXPORT_SYMBOL_GPL(mtk_mux_vote_fenc_ops);
+
 static struct clk_hw *mtk_clk_register_mux(struct device *dev,
 					   const struct mtk_mux *mux,
 					   struct regmap *regmap,
+					   struct regmap *vote_regmap,
 					   spinlock_t *lock)
 {
 	struct mtk_clk_mux *clk_mux;
@@ -185,9 +365,17 @@ static struct clk_hw *mtk_clk_register_mux(struct device *dev,
 	init.flags = mux->flags;
 	init.parent_names = mux->parent_names;
 	init.num_parents = mux->num_parents;
-	init.ops = mux->ops;
+	if (mux->flags & CLK_USE_VOTE) {
+		if (vote_regmap)
+			init.ops = mux->ops;
+		else
+			init.ops = mux->dma_ops;
+	} else {
+		init.ops = mux->ops;
+	}
 
 	clk_mux->regmap = regmap;
+	clk_mux->vote_regmap = vote_regmap;
 	clk_mux->data = mux;
 	clk_mux->lock = lock;
 	clk_mux->hw.init = &init;
@@ -220,6 +408,7 @@ int mtk_clk_register_muxes(struct device *dev,
 			   struct clk_hw_onecell_data *clk_data)
 {
 	struct regmap *regmap;
+	struct regmap *vote_regmap = NULL;
 	struct clk_hw *hw;
 	int i;
 
@@ -238,8 +427,13 @@ int mtk_clk_register_muxes(struct device *dev,
 			continue;
 		}
 
-		hw = mtk_clk_register_mux(dev, mux, regmap, lock);
+		if (mux->vote_comp) {
+			vote_regmap = syscon_regmap_lookup_by_phandle(node, mux->vote_comp);
+			if (IS_ERR(vote_regmap))
+				vote_regmap = NULL;
+		}
 
+		hw = mtk_clk_register_mux(dev, mux, regmap, vote_regmap, lock);
 		if (IS_ERR(hw)) {
 			pr_err("Failed to register clk %s: %pe\n", mux->name,
 			       hw);
diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
index 943ad1d7ce4b..c202ad42be16 100644
--- a/drivers/clk/mediatek/clk-mux.h
+++ b/drivers/clk/mediatek/clk-mux.h
@@ -21,6 +21,7 @@ struct mtk_mux {
 	int id;
 	const char *name;
 	const char * const *parent_names;
+	const char *vote_comp;
 	const u8 *parent_index;
 	unsigned int flags;
 
@@ -28,13 +29,19 @@ struct mtk_mux {
 	u32 set_ofs;
 	u32 clr_ofs;
 	u32 upd_ofs;
+	u32 vote_set_ofs;
+	u32 vote_clr_ofs;
+	u32 vote_sta_ofs;
+	u32 fenc_sta_mon_ofs;
 
 	u8 mux_shift;
 	u8 mux_width;
 	u8 gate_shift;
 	s8 upd_shift;
+	u8 fenc_shift;
 
 	const struct clk_ops *ops;
+	const struct clk_ops *dma_ops;
 	signed char num_parents;
 };
 
@@ -77,6 +84,8 @@ struct mtk_mux {
 
 extern const struct clk_ops mtk_mux_clr_set_upd_ops;
 extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
+extern const struct clk_ops mtk_mux_gate_fenc_clr_set_upd_ops;
+extern const struct clk_ops mtk_mux_vote_fenc_ops;
 
 #define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
 			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
@@ -118,6 +127,76 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
 			0, _upd_ofs, _upd, CLK_SET_RATE_PARENT,		\
 			mtk_mux_clr_set_upd_ops)
 
+#define MUX_MULT_VOTE_FENC_FLAGS(_id, _name, _parents,			\
+			 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _vote_comp,\
+			_vote_sta_ofs, _vote_set_ofs, _vote_clr_ofs,	\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc, _flags) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_ofs = _mux_ofs,					\
+		.set_ofs = _mux_set_ofs,				\
+		.clr_ofs = _mux_clr_ofs,				\
+		.vote_comp = _vote_comp,				\
+		.vote_sta_ofs = _vote_sta_ofs,				\
+		.vote_set_ofs = _vote_set_ofs,				\
+		.vote_clr_ofs = _vote_clr_ofs,				\
+		.upd_ofs = _upd_ofs,					\
+		.fenc_sta_mon_ofs = _fenc_sta_mon_ofs,			\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = _gate,					\
+		.upd_shift = _upd,					\
+		.fenc_shift = _fenc,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags =  CLK_USE_VOTE | (_flags),			\
+		.ops = &mtk_mux_vote_fenc_ops,				\
+		.dma_ops = &mtk_mux_gate_fenc_clr_set_upd_ops,		\
+	}
+
+#define MUX_MULT_VOTE_FENC(_id, _name, _parents,				\
+			_mux_ofs, _mux_set_ofs, _mux_clr_ofs, _vote_comp,\
+			_vote_sta_ofs, _vote_set_ofs, _vote_clr_ofs,	\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc)			\
+		MUX_MULT_VOTE_FENC_FLAGS(_id, _name, _parents,		\
+			_mux_ofs, _mux_set_ofs, _mux_clr_ofs, _vote_comp,\
+			_vote_sta_ofs, _vote_set_ofs, _vote_clr_ofs,	\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc, 0)
+
+#define MUX_GATE_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents,		\
+			_mux_ofs, _mux_set_ofs, _mux_clr_ofs,		\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc, _flags) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_ofs = _mux_ofs,					\
+		.set_ofs = _mux_set_ofs,				\
+		.clr_ofs = _mux_clr_ofs,				\
+		.upd_ofs = _upd_ofs,					\
+		.fenc_sta_mon_ofs = _fenc_sta_mon_ofs,			\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = _gate,					\
+		.upd_shift = _upd,					\
+		.fenc_shift = _fenc,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = _flags,					\
+		.ops = &mtk_mux_gate_fenc_clr_set_upd_ops,		\
+	}
+
+#define MUX_GATE_FENC_CLR_SET_UPD(_id, _name, _parents,			\
+			_mux_ofs, _mux_set_ofs, _mux_clr_ofs,		\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc)			\
+		MUX_GATE_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents,	\
+			_mux_ofs, _mux_set_ofs, _mux_clr_ofs,		\
+			_shift, _width, _gate, _upd_ofs, _upd,		\
+			_fenc_sta_mon_ofs, _fenc, 0)
+
 int mtk_clk_register_muxes(struct device *dev,
 			   const struct mtk_mux *muxes,
 			   int num, struct device_node *node,
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:01 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:01 +0800
Subject: [PATCH 05/26] clk: mediatek: Add gate ops without disable
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-6-guangjie.song@mediatek.com>

Add gate ops without .disable and the ops is used for gate which is not
allowed to disable but cannot affect its parent clock to disable.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/clk-gate.c | 6 ++++++
 drivers/clk/mediatek/clk-gate.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index be6cf4a6d246..a36136c61252 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -273,6 +273,12 @@ const struct clk_ops mtk_clk_gate_ops_setclr = {
 };
 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr);
 
+const struct clk_ops mtk_clk_gate_ops_setclr_enable = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable,
+};
+EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr_enable);
+
 const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 	.is_enabled	= mtk_cg_bit_is_set,
 	.enable		= mtk_cg_enable_inv,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index 7d93fc84ad51..d992e3edd457 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -16,6 +16,7 @@ struct device;
 struct device_node;
 
 extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_enable;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:26:58 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:26:58 +0800
Subject: [PATCH 02/26] clk: mediatek: Support voting for pll
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-3-guangjie.song@mediatek.com>

Add data fields and ops to support voting for pll.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/clk-pll.c | 51 +++++++++++++++++++++++++++++++++-
 drivers/clk/mediatek/clk-pll.h |  5 ++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index ce453e1718e5..fdaa4ee74608 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -13,6 +13,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 
+#include "clk-mtk.h"
 #include "clk-pll.h"
 
 #define MHZ			(1000 * 1000)
@@ -37,6 +38,13 @@ int mtk_pll_is_prepared(struct clk_hw *hw)
 	return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0;
 }
 
+static int mtk_pll_fenc_is_prepared(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	return  (((readl(pll->fenc_addr) & pll->fenc_mask) != 0) || (pll->onoff_cnt != 0));
+}
+
 static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
 		u32 pcw, int postdiv)
 {
@@ -274,6 +282,30 @@ void mtk_pll_unprepare(struct clk_hw *hw)
 	writel(r, pll->pwr_addr);
 }
 
+static int mtk_pll_fenc_prepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	if (pll->onoff_cnt == 1) {
+		pr_err("%s: %s is already prepared\n", __func__, clk_hw_get_name(hw));
+		return -EPERM;
+	}
+
+	pll->onoff_cnt = 1;
+
+	return 0;
+}
+
+static void mtk_pll_fenc_unprepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	if (pll->onoff_cnt == 0)
+		pr_err("%s: %s is not prepared\n", __func__, clk_hw_get_name(hw));
+	else
+		pll->onoff_cnt = 0;
+}
+
 const struct clk_ops mtk_pll_ops = {
 	.is_prepared	= mtk_pll_is_prepared,
 	.prepare	= mtk_pll_prepare,
@@ -283,6 +315,15 @@ const struct clk_ops mtk_pll_ops = {
 	.set_rate	= mtk_pll_set_rate,
 };
 
+static const struct clk_ops mtk_pll_fenc_ops = {
+	.is_prepared	= mtk_pll_fenc_is_prepared,
+	.prepare	= mtk_pll_fenc_prepare,
+	.unprepare	= mtk_pll_fenc_unprepare,
+	.recalc_rate	= mtk_pll_recalc_rate,
+	.round_rate	= mtk_pll_round_rate,
+	.set_rate	= mtk_pll_set_rate,
+};
+
 struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
 					const struct mtk_pll_data *data,
 					void __iomem *base,
@@ -313,6 +354,11 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
 
 	init.name = data->name;
 	init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
+	if (data->flags & CLK_FENC_ENABLE) {
+		pll->fenc_addr = base + data->fenc_sta_ofs;
+		pll->fenc_mask = BIT(data->fenc_sta_bit);
+	}
+
 	init.ops = pll_ops;
 	if (data->parent_name)
 		init.parent_names = &data->parent_name;
@@ -338,7 +384,10 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
 	if (!pll)
 		return ERR_PTR(-ENOMEM);
 
-	hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
+	if (data->flags & CLK_FENC_ENABLE)
+		hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_fenc_ops);
+	else
+		hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
 	if (IS_ERR(hw))
 		kfree(pll);
 
diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
index 285c8db958b3..3a1e48006e34 100644
--- a/drivers/clk/mediatek/clk-pll.h
+++ b/drivers/clk/mediatek/clk-pll.h
@@ -29,6 +29,7 @@ struct mtk_pll_data {
 	u32 reg;
 	u32 pwr_reg;
 	u32 en_mask;
+	u32 fenc_sta_ofs;
 	u32 pd_reg;
 	u32 tuner_reg;
 	u32 tuner_en_reg;
@@ -49,6 +50,7 @@ struct mtk_pll_data {
 	u32 en_reg;
 	u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */
 	u8 pcw_chg_bit;
+	u8 fenc_sta_bit;
 };
 
 /*
@@ -69,6 +71,9 @@ struct mtk_clk_pll {
 	void __iomem	*pcw_chg_addr;
 	void __iomem	*en_addr;
 	const struct mtk_pll_data *data;
+	void __iomem	*fenc_addr;
+	u32		fenc_mask;
+	u32		onoff_cnt;
 };
 
 int mtk_clk_register_plls(struct device_node *node,
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:04 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:04 +0800
Subject: [PATCH 08/26] clk: mediatek: Add MT8196 apmixedsys_gp2 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-9-guangjie.song@mediatek.com>

Add MT8196 apmixedsys_gp2 clock controller which provides pll generated
from SoC 26m

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile                 |   2 +-
 .../clk/mediatek/clk-mt8196-apmixedsys_gp2.c  | 154 ++++++++++++++++++
 2 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-apmixedsys_gp2.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 6144fdce3f9a..247bad396cfb 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -150,7 +150,7 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VDOSYS) += clk-mt8195-vdo0.o clk-mt8195-vdo1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
-obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o
+obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-apmixedsys_gp2.c b/drivers/clk/mediatek/clk-mt8196-apmixedsys_gp2.c
new file mode 100644
index 000000000000..dc895d103bfe
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-apmixedsys_gp2.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+/* PLL REG */
+#define MAINPLL2_CON0	0x250
+#define MAINPLL2_CON1	0x254
+#define MAINPLL2_CON2	0x258
+#define MAINPLL2_CON3	0x25c
+#define UNIVPLL2_CON0	0x264
+#define UNIVPLL2_CON1	0x268
+#define UNIVPLL2_CON2	0x26c
+#define UNIVPLL2_CON3	0x270
+#define MMPLL2_CON0	0x278
+#define MMPLL2_CON1	0x27c
+#define MMPLL2_CON2	0x280
+#define MMPLL2_CON3	0x284
+#define IMGPLL_CON0	0x28c
+#define IMGPLL_CON1	0x290
+#define IMGPLL_CON2	0x294
+#define IMGPLL_CON3	0x298
+#define TVDPLL1_CON0	0x2a0
+#define TVDPLL1_CON1	0x2a4
+#define TVDPLL1_CON2	0x2a8
+#define TVDPLL1_CON3	0x2ac
+#define TVDPLL2_CON0	0x2b4
+#define TVDPLL2_CON1	0x2b8
+#define TVDPLL2_CON2	0x2bc
+#define TVDPLL2_CON3	0x2c0
+#define TVDPLL3_CON0	0x2c8
+#define TVDPLL3_CON1	0x2cc
+#define TVDPLL3_CON2	0x2d0
+#define TVDPLL3_CON3	0x2d4
+
+#define MT8196_PLL_FMAX		(3800UL * MHZ)
+#define MT8196_PLL_FMIN		(1500UL * MHZ)
+#define MT8196_INTEGER_BITS	8
+
+#define PLL_FENC(_id, _name, _reg, _fenc_sta_ofs, _fenc_sta_bit,\
+		 _flags, _pd_reg, _pd_shift,			\
+		 _pcw_reg, _pcw_shift, _pcwbits) {		\
+		.id = _id,					\
+		.name = _name,					\
+		.reg = _reg,					\
+		.fenc_sta_ofs = _fenc_sta_ofs,			\
+		.fenc_sta_bit = _fenc_sta_bit,			\
+		.flags = (_flags) | CLK_FENC_ENABLE,		\
+		.fmax = MT8196_PLL_FMAX,			\
+		.fmin = MT8196_PLL_FMIN,			\
+		.pd_reg = _pd_reg,				\
+		.pd_shift = _pd_shift,				\
+		.pcw_reg = _pcw_reg,				\
+		.pcw_shift = _pcw_shift,			\
+		.pcwbits = _pcwbits,				\
+		.pcwibits = MT8196_INTEGER_BITS,		\
+	}
+
+static const struct mtk_pll_data apmixed2_plls[] = {
+	PLL_FENC(CLK_APMIXED2_MAINPLL2, "mainpll2", MAINPLL2_CON0,
+		 0x03c, 6, 0,
+		 MAINPLL2_CON1, 24,
+		 MAINPLL2_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_UNIVPLL2, "univpll2", UNIVPLL2_CON0,
+		 0x03c, 5, 0,
+		 UNIVPLL2_CON1, 24,
+		 UNIVPLL2_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_MMPLL2, "mmpll2", MMPLL2_CON0,
+		 0x03c, 4, 0,
+		 MMPLL2_CON1, 24,
+		 MMPLL2_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_IMGPLL, "imgpll", IMGPLL_CON0,
+		 0x03c, 3, 0,
+		 IMGPLL_CON1, 24,
+		 IMGPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_TVDPLL1, "tvdpll1", TVDPLL1_CON0,
+		 0x03c, 2, 0,
+		 TVDPLL1_CON1, 24,
+		 TVDPLL1_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_TVDPLL2, "tvdpll2", TVDPLL2_CON0,
+		 0x03c, 1, 0,
+		 TVDPLL2_CON1, 24,
+		 TVDPLL2_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED2_TVDPLL3, "tvdpll3", TVDPLL3_CON0,
+		 0x03c, 0, 0,
+		 TVDPLL3_CON1, 24,
+		 TVDPLL3_CON1, 0, 22),
+};
+
+static int clk_mt8196_apmixed2_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = ARRAY_SIZE(apmixed2_plls);
+	int r;
+
+	clk_data = mtk_alloc_clk_data(num_plls);
+	if (!clk_data)
+		return -ENOMEM;
+
+	r = mtk_clk_register_plls(node, apmixed2_plls, num_plls, clk_data);
+	if (r) {
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r) {
+		mtk_clk_unregister_plls(apmixed2_plls, num_plls, clk_data);
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	return 0;
+}
+
+static void clk_mt8196_apmixed2_remove(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_plls(apmixed2_plls, ARRAY_SIZE(apmixed2_plls), clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8196_apmixed2[] = {
+	{ .compatible = "mediatek,mt8196-apmixedsys_gp2", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_apmixed2_drv = {
+	.probe = clk_mt8196_apmixed2_probe,
+	.remove = clk_mt8196_apmixed2_remove,
+	.driver = {
+		.name = "clk-mt8196-apmixed2",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_apmixed2,
+	},
+};
+
+module_platform_driver(clk_mt8196_apmixed2_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:03 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:03 +0800
Subject: [PATCH 07/26] clk: mediatek: Add MT8196 apmixedsys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-8-guangjie.song@mediatek.com>

Add MT8196 apmixedsys clock controller which provides pll generated from
SoC 26m.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig                 |   8 +
 drivers/clk/mediatek/Makefile                |   1 +
 drivers/clk/mediatek/clk-mt8196-apmixedsys.c | 146 +++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-apmixedsys.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 5f8e6d68fa14..1e0c6f177ecd 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1002,6 +1002,14 @@ config COMMON_CLK_MT8195_VENCSYS
 	help
 	  This driver supports MediaTek MT8195 vencsys clocks.
 
+config COMMON_CLK_MT8196
+	tristate "Clock driver for MediaTek MT8196"
+	depends on ARM64 || COMPILE_TEST
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	help
+	  This driver supports MediaTek MT8196 basic clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 6efec95406bd..6144fdce3f9a 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VDOSYS) += clk-mt8195-vdo0.o clk-mt8195-vdo1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
+obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-apmixedsys.c b/drivers/clk/mediatek/clk-mt8196-apmixedsys.c
new file mode 100644
index 000000000000..3aa62eec07f7
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-apmixedsys.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+/* PLL REG */
+#define MAINPLL_CON0	0x250
+#define MAINPLL_CON1	0x254
+#define MAINPLL_CON2	0x258
+#define MAINPLL_CON3	0x25c
+#define UNIVPLL_CON0	0x264
+#define UNIVPLL_CON1	0x268
+#define UNIVPLL_CON2	0x26c
+#define UNIVPLL_CON3	0x270
+#define MSDCPLL_CON0	0x278
+#define MSDCPLL_CON1	0x27c
+#define MSDCPLL_CON2	0x280
+#define MSDCPLL_CON3	0x284
+#define ADSPPLL_CON0	0x28c
+#define ADSPPLL_CON1	0x290
+#define ADSPPLL_CON2	0x294
+#define ADSPPLL_CON3	0x298
+#define EMIPLL_CON0	0x2a0
+#define EMIPLL_CON1	0x2a4
+#define EMIPLL_CON2	0x2a8
+#define EMIPLL_CON3	0x2ac
+#define EMIPLL2_CON0	0x2b4
+#define EMIPLL2_CON1	0x2b8
+#define EMIPLL2_CON2	0x2bc
+#define EMIPLL2_CON3	0x2c0
+
+#define MT8196_PLL_FMAX		(3800UL * MHZ)
+#define MT8196_PLL_FMIN		(1500UL * MHZ)
+#define MT8196_INTEGER_BITS	8
+
+#define PLL_FENC(_id, _name, _reg, _fenc_sta_ofs, _fenc_sta_bit,	\
+		 _flags, _pd_reg, _pd_shift,			\
+		 _pcw_reg, _pcw_shift, _pcwbits) {		\
+		.id = _id,					\
+		.name = _name,					\
+		.reg = _reg,					\
+		.fenc_sta_ofs = _fenc_sta_ofs,			\
+		.fenc_sta_bit = _fenc_sta_bit,			\
+		.flags = (_flags) | CLK_FENC_ENABLE,		\
+		.fmax = MT8196_PLL_FMAX,			\
+		.fmin = MT8196_PLL_FMIN,			\
+		.pd_reg = _pd_reg,				\
+		.pd_shift = _pd_shift,				\
+		.pcw_reg = _pcw_reg,				\
+		.pcw_shift = _pcw_shift,			\
+		.pcwbits = _pcwbits,				\
+		.pcwibits = MT8196_INTEGER_BITS,		\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL_FENC(CLK_APMIXED_MAINPLL, "mainpll", MAINPLL_CON0,
+		 0x003c, 7, PLL_AO,
+		 MAINPLL_CON1, 24,
+		 MAINPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED_UNIVPLL, "univpll", UNIVPLL_CON0,
+		 0x003c, 6, 0,
+		 UNIVPLL_CON1, 24,
+		 UNIVPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED_MSDCPLL, "msdcpll", MSDCPLL_CON0,
+		 0x003c, 5, 0,
+		 MSDCPLL_CON1, 24,
+		 MSDCPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED_ADSPPLL, "adsppll", ADSPPLL_CON0,
+		 0x003c, 4, 0,
+		 ADSPPLL_CON1, 24,
+		 ADSPPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED_EMIPLL, "emipll", EMIPLL_CON0,
+		 0x003c, 3, PLL_AO,
+		 EMIPLL_CON1, 24,
+		 EMIPLL_CON1, 0, 22),
+	PLL_FENC(CLK_APMIXED_EMIPLL2, "emipll2", EMIPLL2_CON0,
+		 0x003c, 2, PLL_AO,
+		 EMIPLL2_CON1, 24,
+		 EMIPLL2_CON1, 0, 22),
+};
+
+static int clk_mt8196_apmixed_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = ARRAY_SIZE(apmixed_plls);
+	int r;
+
+	clk_data = mtk_alloc_clk_data(num_plls);
+	if (!clk_data)
+		return -ENOMEM;
+
+	r = mtk_clk_register_plls(node, apmixed_plls, num_plls, clk_data);
+	if (r) {
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r) {
+		mtk_clk_unregister_plls(apmixed_plls, num_plls, clk_data);
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	return 0;
+}
+
+static void clk_mt8196_apmixed_remove(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_plls(apmixed_plls, ARRAY_SIZE(apmixed_plls), clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8196_apmixed[] = {
+	{ .compatible = "mediatek,mt8196-apmixedsys", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_apmixed_drv = {
+	.probe = clk_mt8196_apmixed_probe,
+	.remove = clk_mt8196_apmixed_remove,
+	.driver = {
+		.name = "clk-mt8196-apmixed",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_apmixed,
+	},
+};
+
+module_platform_driver(clk_mt8196_apmixed_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:02 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:02 +0800
Subject: [PATCH 06/26] dt-bindings: clock: mediatek: Add new MT8196 clock
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-7-guangjie.song@mediatek.com>

Add the new binding documentation for system clock and functional clock
on Mediatek MT8196.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 .../bindings/clock/mediatek,mt8196-clock.yaml |   66 +
 .../clock/mediatek,mt8196-sys-clock.yaml      |   63 +
 include/dt-bindings/clock/mt8196-clk.h        | 1503 +++++++++++++++++
 3 files changed, 1632 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml
 create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml
 create mode 100644 include/dt-bindings/clock/mt8196-clk.h

diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml
new file mode 100644
index 000000000000..014c6c4840f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/mediatek,mt8196-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Functional Clock Controller for MT8196
+
+maintainers:
+  - Guangjie Song <guangjie.song at mediatek.com>
+
+description:
+  The clock architecture in MediaTek like below
+  PLLs -->
+          dividers -->
+                      muxes
+                           -->
+                              clock gate
+
+  The devices provide clock gate control in different IP blocks.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8196-audiosys
+      - mediatek,mt8196-dispsys0
+      - mediatek,mt8196-dispsys1
+      - mediatek,mt8196-disp_vdisp_ao_config
+      - mediatek,mt8196-imp_iic_wrap_c
+      - mediatek,mt8196-imp_iic_wrap_e
+      - mediatek,mt8196-imp_iic_wrap_n
+      - mediatek,mt8196-imp_iic_wrap_w
+      - mediatek,mt8196-mdpsys
+      - mediatek,mt8196-mdpsys1
+      - mediatek,mt8196-ovlsys0
+      - mediatek,mt8196-ovlsys1
+      - mediatek,mt8196-pericfg_ao
+      - mediatek,mt8196-pextp0cfg_ao
+      - mediatek,mt8196-pextp1cfg_ao
+      - mediatek,mt8196-ufscfg_ao
+      - mediatek,mt8196-vdecsys
+      - mediatek,mt8196-vdecsys_soc
+      - mediatek,mt8196-vencsys
+      - mediatek,mt8196-vencsys_c1
+      - mediatek,mt8196-vencsys_c2
+
+  reg:
+    description: Address range of the subsys.
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller at 16300000 {
+        compatible = "mediatek,mt8196-imp_iic_wrap_c";
+        reg = <0x16300000 0x1000>;
+        #clock-cells = <1>;
+    };
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml
new file mode 100644
index 000000000000..0909b9f1ee52
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/mediatek,mt8196-sys-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek System Clock Controller for MT8196
+
+maintainers:
+  - Guangjie Song <guangjie.song at mediatek.com>
+
+description:
+  The clock architecture in MediaTek like below
+  PLLs -->
+          dividers -->
+                      muxes
+                           -->
+                              clock gate
+
+  The apmixedsys, vlp_cksys, armpll, ccipll, mfgpll and ptppll provides most of PLLs
+  which generated from SoC 26m.
+  The cksys, cksys_gp2 and vlp_cksys provides dividers and muxes which provide the
+  clock source to other IP blocks.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - mediatek,mt8196-armpll_ll_pll_ctrl
+          - mediatek,mt8196-armpll_bl_pll_ctrl
+          - mediatek,mt8196-armpll_b_pll_ctrl
+          - mediatek,mt8196-apmixedsys
+          - mediatek,mt8196-apmixedsys_gp2
+          - mediatek,mt8196-ccipll_pll_ctrl
+          - mediatek,mt8196-cksys
+          - mediatek,mt8196-cksys_gp2
+          - mediatek,mt8196-mfgpll_pll_ctrl
+          - mediatek,mt8196-mfgpll_sc0_pll_ctrl
+          - mediatek,mt8196-mfgpll_sc1_pll_ctrl
+          - mediatek,mt8196-ptppll_pll_ctrl
+          - mediatek,mt8196-vlp_cksys
+      - const: syscon
+
+  reg:
+    description: Address range of the subsys.
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller at 10000800 {
+        compatible = "mediatek,mt8196-apmixedsys", "syscon";
+        reg = <0 0x10000800 0 0x1000>;
+        #clock-cells = <1>;
+    };
diff --git a/include/dt-bindings/clock/mt8196-clk.h b/include/dt-bindings/clock/mt8196-clk.h
new file mode 100644
index 000000000000..9bd33c46f7de
--- /dev/null
+++ b/include/dt-bindings/clock/mt8196-clk.h
@@ -0,0 +1,1503 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8196_H
+#define _DT_BINDINGS_CLK_MT8196_H
+
+/* CKSYS */
+#define CLK_CK_AXI_SEL					0
+#define CLK_CK_MEM_SUB_SEL				1
+#define CLK_CK_IO_NOC_SEL				2
+#define CLK_CK_P_AXI_SEL				3
+#define CLK_CK_PEXTP0_AXI_SEL				4
+#define CLK_CK_PEXTP1_USB_AXI_SEL			5
+#define CLK_CK_P_FMEM_SUB_SEL				6
+#define CLK_CK_PEXPT0_MEM_SUB_SEL			7
+#define CLK_CK_PEXTP1_USB_MEM_SUB_SEL			8
+#define CLK_CK_P_NOC_SEL				9
+#define CLK_CK_EMI_N_SEL				10
+#define CLK_CK_EMI_S_SEL				11
+#define CLK_CK_AP2CONN_HOST_SEL				12
+#define CLK_CK_ATB_SEL					13
+#define CLK_CK_CIRQ_SEL					14
+#define CLK_CK_PBUS_156M_SEL				15
+#define CLK_CK_EFUSE_SEL				16
+#define CLK_CK_MCL3GIC_SEL				17
+#define CLK_CK_MCINFRA_SEL				18
+#define CLK_CK_DSP_SEL					19
+#define CLK_CK_MFG_REF_SEL				20
+#define CLK_CK_MFG_EB_SEL				21
+#define CLK_CK_UART_SEL					22
+#define CLK_CK_SPI0_BCLK_SEL				23
+#define CLK_CK_SPI1_BCLK_SEL				24
+#define CLK_CK_SPI2_BCLK_SEL				25
+#define CLK_CK_SPI3_BCLK_SEL				26
+#define CLK_CK_SPI4_BCLK_SEL				27
+#define CLK_CK_SPI5_BCLK_SEL				28
+#define CLK_CK_SPI6_BCLK_SEL				29
+#define CLK_CK_SPI7_BCLK_SEL				30
+#define CLK_CK_MSDC30_1_SEL				31
+#define CLK_CK_MSDC30_2_SEL				32
+#define CLK_CK_DISP_PWM_SEL				33
+#define CLK_CK_USB_TOP_1P_SEL				34
+#define CLK_CK_USB_XHCI_1P_SEL				35
+#define CLK_CK_USB_FMCNT_P1_SEL				36
+#define CLK_CK_I2C_P_SEL				37
+#define CLK_CK_I2C_EAST_SEL				38
+#define CLK_CK_I2C_WEST_SEL				39
+#define CLK_CK_I2C_NORTH_SEL				40
+#define CLK_CK_AES_UFSFDE_SEL				41
+#define CLK_CK_SEL					42
+#define CLK_CK_AUD_1_SEL				43
+#define CLK_CK_AUD_2_SEL				44
+#define CLK_CK_ADSP_SEL					45
+#define CLK_CK_ADSP_UARTHUB_BCLK_SEL			46
+#define CLK_CK_DPMAIF_MAIN_SEL				47
+#define CLK_CK_PWM_SEL					48
+#define CLK_CK_MCUPM_SEL				49
+#define CLK_CK_IPSEAST_SEL				50
+#define CLK_CK_TL_SEL					51
+#define CLK_CK_TL_P1_SEL				52
+#define CLK_CK_TL_P2_SEL				53
+#define CLK_CK_EMI_INTERFACE_546_SEL			54
+#define CLK_CK_SDF_SEL					55
+#define CLK_CK_UARTHUB_BCLK_SEL				56
+#define CLK_CK_DPSW_CMP_26M_SEL				57
+#define CLK_CK_SMAPCK_SEL				58
+#define CLK_CK_SSR_PKA_SEL				59
+#define CLK_CK_SSR_DMA_SEL				60
+#define CLK_CK_SSR_KDF_SEL				61
+#define CLK_CK_SSR_RNG_SEL				62
+#define CLK_CK_SPU0_SEL					63
+#define CLK_CK_SPU1_SEL					64
+#define CLK_CK_DXCC_SEL					65
+#define CLK_CK_APLL_I2SIN0_MCK_SEL			66
+#define CLK_CK_APLL_I2SIN1_MCK_SEL			67
+#define CLK_CK_APLL_I2SIN2_MCK_SEL			68
+#define CLK_CK_APLL_I2SIN3_MCK_SEL			69
+#define CLK_CK_APLL_I2SIN4_MCK_SEL			70
+#define CLK_CK_APLL_I2SIN6_MCK_SEL			71
+#define CLK_CK_APLL_I2SOUT0_MCK_SEL			72
+#define CLK_CK_APLL_I2SOUT1_MCK_SEL			73
+#define CLK_CK_APLL_I2SOUT2_MCK_SEL			74
+#define CLK_CK_APLL_I2SOUT3_MCK_SEL			75
+#define CLK_CK_APLL_I2SOUT4_MCK_SEL			76
+#define CLK_CK_APLL_I2SOUT6_MCK_SEL			77
+#define CLK_CK_APLL_FMI2S_MCK_SEL			78
+#define CLK_CK_APLL_TDMOUT_MCK_SEL			79
+#define CLK_CK_APLL12_CK_DIV_I2SIN0			80
+#define CLK_CK_APLL12_CK_DIV_I2SIN1			81
+#define CLK_CK_APLL12_CK_DIV_I2SIN2			82
+#define CLK_CK_APLL12_CK_DIV_I2SIN3			83
+#define CLK_CK_APLL12_CK_DIV_I2SIN4			84
+#define CLK_CK_APLL12_CK_DIV_I2SIN6			85
+#define CLK_CK_APLL12_CK_DIV_I2SOUT0			86
+#define CLK_CK_APLL12_CK_DIV_I2SOUT1			87
+#define CLK_CK_APLL12_CK_DIV_I2SOUT2			88
+#define CLK_CK_APLL12_CK_DIV_I2SOUT3			89
+#define CLK_CK_APLL12_CK_DIV_I2SOUT4			90
+#define CLK_CK_APLL12_CK_DIV_I2SOUT6			91
+#define CLK_CK_APLL12_CK_DIV_FMI2S			92
+#define CLK_CK_APLL12_CK_DIV_TDMOUT_M			93
+#define CLK_CK_APLL12_CK_DIV_TDMOUT_B			94
+#define CLK_CK_MAINPLL_D3				95
+#define CLK_CK_MAINPLL_D4				96
+#define CLK_CK_MAINPLL_D4_D2				97
+#define CLK_CK_MAINPLL_D4_D4				98
+#define CLK_CK_MAINPLL_D4_D8				99
+#define CLK_CK_MAINPLL_D5				100
+#define CLK_CK_MAINPLL_D5_D2				101
+#define CLK_CK_MAINPLL_D5_D4				102
+#define CLK_CK_MAINPLL_D5_D8				103
+#define CLK_CK_MAINPLL_D6				104
+#define CLK_CK_MAINPLL_D6_D2				105
+#define CLK_CK_MAINPLL_D7				106
+#define CLK_CK_MAINPLL_D7_D2				107
+#define CLK_CK_MAINPLL_D7_D4				108
+#define CLK_CK_MAINPLL_D7_D8				109
+#define CLK_CK_MAINPLL_D9				110
+#define CLK_CK_UNIVPLL_D4				111
+#define CLK_CK_UNIVPLL_D4_D2				112
+#define CLK_CK_UNIVPLL_D4_D4				113
+#define CLK_CK_UNIVPLL_D4_D8				114
+#define CLK_CK_UNIVPLL_D5				115
+#define CLK_CK_UNIVPLL_D5_D2				116
+#define CLK_CK_UNIVPLL_D5_D4				117
+#define CLK_CK_UNIVPLL_D6				118
+#define CLK_CK_UNIVPLL_D6_D2				119
+#define CLK_CK_UNIVPLL_D6_D4				120
+#define CLK_CK_UNIVPLL_D6_D8				121
+#define CLK_CK_UNIVPLL_D6_D16				122
+#define CLK_CK_UNIVPLL_192M				123
+#define CLK_CK_UNIVPLL_192M_D4				124
+#define CLK_CK_UNIVPLL_192M_D8				125
+#define CLK_CK_UNIVPLL_192M_D16				126
+#define CLK_CK_UNIVPLL_192M_D32				127
+#define CLK_CK_UNIVPLL_192M_D10				128
+#define CLK_CK_APLL1					129
+#define CLK_CK_APLL1_D4					130
+#define CLK_CK_APLL1_D8					131
+#define CLK_CK_APLL2					132
+#define CLK_CK_APLL2_D4					133
+#define CLK_CK_APLL2_D8					134
+#define CLK_CK_ADSPPLL					135
+#define CLK_CK_EMIPLL1					136
+#define CLK_CK_TVDPLL1_D2				137
+#define CLK_CK_MSDCPLL_D2				138
+#define CLK_CK_CLKRTC					139
+#define CLK_CK_TCK_26M_MX9				140
+#define CLK_CK_F26M					141
+#define CLK_CK_F26M_CK_D2				142
+#define CLK_CK_OSC					143
+#define CLK_CK_OSC_D2					144
+#define CLK_CK_OSC_D3					145
+#define CLK_CK_OSC_D4					146
+#define CLK_CK_OSC_D5					147
+#define CLK_CK_OSC_D7					148
+#define CLK_CK_OSC_D8					149
+#define CLK_CK_OSC_D10					150
+#define CLK_CK_OSC_D14					151
+#define CLK_CK_OSC_D20					152
+#define CLK_CK_OSC_D32					153
+#define CLK_CK_OSC_D40					154
+#define CLK_CK_OSC3					155
+#define CLK_CK_P_AXI					156
+#define CLK_CK_PEXTP0_AXI				157
+#define CLK_CK_PEXTP1_USB_AXI				158
+#define CLK_CK_PEXPT0_MEM_SUB				159
+#define CLK_CK_PEXTP1_USB_MEM_SUB			160
+#define CLK_CK_UART					161
+#define CLK_CK_SPI0_BCLK				162
+#define CLK_CK_SPI1_BCLK				163
+#define CLK_CK_SPI2_BCLK				164
+#define CLK_CK_SPI3_BCLK				165
+#define CLK_CK_SPI4_BCLK				166
+#define CLK_CK_SPI5_BCLK				167
+#define CLK_CK_SPI6_BCLK				168
+#define CLK_CK_SPI7_BCLK				169
+#define CLK_CK_MSDC30_1					170
+#define CLK_CK_MSDC30_2					171
+#define CLK_CK_I2C_PERI					172
+#define CLK_CK_I2C_EAST					173
+#define CLK_CK_I2C_WEST					174
+#define CLK_CK_I2C_NORTH				175
+#define CLK_CK_AES_UFSFDE				176
+#define CLK_CK_UFS					177
+#define CLK_CK_AUD_1					178
+#define CLK_CK_AUD_2					179
+#define CLK_CK_DPMAIF_MAIN				180
+#define CLK_CK_PWM					181
+#define CLK_CK_TL					182
+#define CLK_CK_TL_P1					183
+#define CLK_CK_TL_P2					184
+#define CLK_CK_SSR_RNG					185
+#define CLK_CK_SPU0					186
+#define CLK_CK_DXCC					187
+#define CLK_CK_SFLASH_SEL				188
+#define CLK_CK_SFLASH					189
+#define CLK_CK_NR_CLK					190
+
+/* APMIXEDSYS */
+#define CLK_APMIXED_MAINPLL				0
+#define CLK_APMIXED_UNIVPLL				1
+#define CLK_APMIXED_MSDCPLL				2
+#define CLK_APMIXED_ADSPPLL				3
+#define CLK_APMIXED_EMIPLL				4
+#define CLK_APMIXED_EMIPLL2				5
+#define CLK_APMIXED_NR_CLK				6
+
+/* CKSYS_GP2 */
+#define CLK_CK2_SENINF0_SEL				0
+#define CLK_CK2_SENINF1_SEL				1
+#define CLK_CK2_SENINF2_SEL				2
+#define CLK_CK2_SENINF3_SEL				3
+#define CLK_CK2_SENINF4_SEL				4
+#define CLK_CK2_SENINF5_SEL				5
+#define CLK_CK2_IMG1_SEL				6
+#define CLK_CK2_IPE_SEL					7
+#define CLK_CK2_CAM_SEL					8
+#define CLK_CK2_CAMTM_SEL				9
+#define CLK_CK2_DPE_SEL					10
+#define CLK_CK2_VDEC_SEL				11
+#define CLK_CK2_CCUSYS_SEL				12
+#define CLK_CK2_CCUTM_SEL				13
+#define CLK_CK2_VENC_SEL				14
+#define CLK_CK2_DP1_SEL					15
+#define CLK_CK2_DP0_SEL					16
+#define CLK_CK2_DISP_SEL				17
+#define CLK_CK2_MDP_SEL					18
+#define CLK_CK2_MMINFRA_SEL				19
+#define CLK_CK2_MMINFRA_SNOC_SEL			20
+#define CLK_CK2_MMUP_SEL				21
+#define CLK_CK2_MMINFRA_AO_SEL				22
+#define CLK_CK2_MAINPLL2_D2				23
+#define CLK_CK2_MAINPLL2_D3				24
+#define CLK_CK2_MAINPLL2_D4				25
+#define CLK_CK2_MAINPLL2_D4_D2				26
+#define CLK_CK2_MAINPLL2_D4_D4				27
+#define CLK_CK2_MAINPLL2_D5				28
+#define CLK_CK2_MAINPLL2_D5_D2				29
+#define CLK_CK2_MAINPLL2_D6				30
+#define CLK_CK2_MAINPLL2_D6_D2				31
+#define CLK_CK2_MAINPLL2_D7				32
+#define CLK_CK2_MAINPLL2_D7_D2				33
+#define CLK_CK2_MAINPLL2_D9				34
+#define CLK_CK2_UNIVPLL2_D3				35
+#define CLK_CK2_UNIVPLL2_D4				36
+#define CLK_CK2_UNIVPLL2_D4_D2				37
+#define CLK_CK2_UNIVPLL2_D5				38
+#define CLK_CK2_UNIVPLL2_D5_D2				39
+#define CLK_CK2_UNIVPLL2_D6				40
+#define CLK_CK2_UNIVPLL2_D6_D2				41
+#define CLK_CK2_UNIVPLL2_D6_D4				42
+#define CLK_CK2_UNIVPLL2_D7				43
+#define CLK_CK2_IMGPLL_D2				44
+#define CLK_CK2_IMGPLL_D4				45
+#define CLK_CK2_IMGPLL_D5				46
+#define CLK_CK2_IMGPLL_D5_D2				47
+#define CLK_CK2_MMPLL2_D3				48
+#define CLK_CK2_MMPLL2_D4				49
+#define CLK_CK2_MMPLL2_D4_D2				50
+#define CLK_CK2_MMPLL2_D5				51
+#define CLK_CK2_MMPLL2_D5_D2				52
+#define CLK_CK2_MMPLL2_D6				53
+#define CLK_CK2_MMPLL2_D6_D2				54
+#define CLK_CK2_MMPLL2_D7				55
+#define CLK_CK2_MMPLL2_D9				56
+#define CLK_CK2_TVDPLL1_D4				57
+#define CLK_CK2_TVDPLL1_D8				58
+#define CLK_CK2_TVDPLL1_D16				59
+#define CLK_CK2_TVDPLL2_D2				60
+#define CLK_CK2_TVDPLL2_D4				61
+#define CLK_CK2_TVDPLL2_D8				62
+#define CLK_CK2_TVDPLL2_D16				63
+#define CLK_CK2_CCUSYS					64
+#define CLK_CK2_VENC					65
+#define CLK_CK2_MMINFRA					66
+#define CLK_CK2_IMG1					67
+#define CLK_CK2_IPE					68
+#define CLK_CK2_CAM					69
+#define CLK_CK2_CAMTM					70
+#define CLK_CK2_DPE					71
+#define CLK_CK2_VDEC					72
+#define CLK_CK2_DP1					73
+#define CLK_CK2_DP0					74
+#define CLK_CK2_MDP					75
+#define CLK_CK2_DISP					76
+#define CLK_CK2_AVS_IMG					77
+#define CLK_CK2_AVS_VDEC				78
+#define CLK_CK2_DVO_SEL					79
+#define CLK_CK2_DVO_FAVT_SEL				80
+#define CLK_CK2_TVDPLL3_D2				81
+#define CLK_CK2_TVDPLL3_D4				82
+#define CLK_CK2_TVDPLL3_D8				83
+#define CLK_CK2_TVDPLL3_D16				84
+#define CLK_CK2_NR_CLK					85
+
+/* APMIXEDSYS_GP2 */
+#define CLK_APMIXED2_MAINPLL2				0
+#define CLK_APMIXED2_UNIVPLL2				1
+#define CLK_APMIXED2_MMPLL2				2
+#define CLK_APMIXED2_IMGPLL				3
+#define CLK_APMIXED2_TVDPLL1				4
+#define CLK_APMIXED2_TVDPLL2				5
+#define CLK_APMIXED2_TVDPLL3				6
+#define CLK_APMIXED2_NR_CLK				7
+
+/* IMP_IIC_WRAP_E */
+#define CLK_IMPE_I2C5					0
+#define CLK_IMPE_I2C5_I2C				1
+#define CLK_IMPE_NR_CLK					2
+
+/* IMP_IIC_WRAP_W */
+#define CLK_IMPW_I2C0					0
+#define CLK_IMPW_I2C0_I2C				1
+#define CLK_IMPW_I2C3					2
+#define CLK_IMPW_I2C3_I2C				3
+#define CLK_IMPW_I2C6					4
+#define CLK_IMPW_I2C6_I2C				5
+#define CLK_IMPW_I2C10					6
+#define CLK_IMPW_I2C10_I2C				7
+#define CLK_IMPW_NR_CLK					8
+
+/* IMP_IIC_WRAP_N */
+#define CLK_IMPN_I2C1					0
+#define CLK_IMPN_I2C1_I2C				1
+#define CLK_IMPN_I2C2					2
+#define CLK_IMPN_I2C2_I2C				3
+#define CLK_IMPN_I2C4					4
+#define CLK_IMPN_I2C4_I2C				5
+#define CLK_IMPN_I2C7					6
+#define CLK_IMPN_I2C7_I2C				7
+#define CLK_IMPN_I2C8					8
+#define CLK_IMPN_I2C8_I2C				9
+#define CLK_IMPN_I2C9					10
+#define CLK_IMPN_I2C9_I2C				11
+#define CLK_IMPN_NR_CLK					12
+
+/* IMP_IIC_WRAP_C */
+#define CLK_IMPC_I2C11					0
+#define CLK_IMPC_I2C11_I2C				1
+#define CLK_IMPC_I2C12					2
+#define CLK_IMPC_I2C12_I2C				3
+#define CLK_IMPC_I2C13					4
+#define CLK_IMPC_I2C13_I2C				5
+#define CLK_IMPC_I2C14					6
+#define CLK_IMPC_I2C14_I2C				7
+#define CLK_IMPC_NR_CLK					8
+
+/* PERICFG_AO */
+#define CLK_PERAO_UART0_BCLK				0
+#define CLK_PERAO_UART0_BCLK_UART			1
+#define CLK_PERAO_UART1_BCLK				2
+#define CLK_PERAO_UART1_BCLK_UART			3
+#define CLK_PERAO_UART2_BCLK				4
+#define CLK_PERAO_UART2_BCLK_UART			5
+#define CLK_PERAO_UART3_BCLK				6
+#define CLK_PERAO_UART3_BCLK_UART			7
+#define CLK_PERAO_UART4_BCLK				8
+#define CLK_PERAO_UART4_BCLK_UART			9
+#define CLK_PERAO_UART5_BCLK				10
+#define CLK_PERAO_UART5_BCLK_UART			11
+#define CLK_PERAO_PWM_X16W_HCLK				12
+#define CLK_PERAO_PWM_X16W_HCLK_PWM			13
+#define CLK_PERAO_PWM_X16W_BCLK				14
+#define CLK_PERAO_PWM_X16W_BCLK_PWM			15
+#define CLK_PERAO_PWM_PWM_BCLK0				16
+#define CLK_PERAO_PWM_PWM_BCLK0_PWM			17
+#define CLK_PERAO_PWM_PWM_BCLK1				18
+#define CLK_PERAO_PWM_PWM_BCLK1_PWM			19
+#define CLK_PERAO_PWM_PWM_BCLK2				20
+#define CLK_PERAO_PWM_PWM_BCLK2_PWM			21
+#define CLK_PERAO_PWM_PWM_BCLK3				22
+#define CLK_PERAO_PWM_PWM_BCLK3_PWM			23
+#define CLK_PERAO_SPI0_BCLK				24
+#define CLK_PERAO_SPI0_BCLK_SPI				25
+#define CLK_PERAO_SPI1_BCLK				26
+#define CLK_PERAO_SPI1_BCLK_SPI				27
+#define CLK_PERAO_SPI2_BCLK				28
+#define CLK_PERAO_SPI2_BCLK_SPI				29
+#define CLK_PERAO_SPI3_BCLK				30
+#define CLK_PERAO_SPI3_BCLK_SPI				31
+#define CLK_PERAO_SPI4_BCLK				32
+#define CLK_PERAO_SPI4_BCLK_SPI				33
+#define CLK_PERAO_SPI5_BCLK				34
+#define CLK_PERAO_SPI5_BCLK_SPI				35
+#define CLK_PERAO_SPI6_BCLK				36
+#define CLK_PERAO_SPI6_BCLK_SPI				37
+#define CLK_PERAO_SPI7_BCLK				38
+#define CLK_PERAO_SPI7_BCLK_SPI				39
+#define CLK_PERAO_AP_DMA_X32W_BCLK			40
+#define CLK_PERAO_AP_DMA_X32W_BCLK_UART			41
+#define CLK_PERAO_AP_DMA_X32W_BCLK_I2C			42
+#define CLK_PERAO_MSDC1_MSDC_SRC			43
+#define CLK_PERAO_MSDC1_MSDC_SRC_MSDC1			44
+#define CLK_PERAO_MSDC1_HCLK				45
+#define CLK_PERAO_MSDC1_HCLK_MSDC1			46
+#define CLK_PERAO_MSDC1_AXI				47
+#define CLK_PERAO_MSDC1_AXI_MSDC1			48
+#define CLK_PERAO_MSDC1_HCLK_WRAP			49
+#define CLK_PERAO_MSDC1_HCLK_WRAP_MSDC1			50
+#define CLK_PERAO_MSDC2_MSDC_SRC			51
+#define CLK_PERAO_MSDC2_MSDC_SRC_MSDC2			52
+#define CLK_PERAO_MSDC2_HCLK				53
+#define CLK_PERAO_MSDC2_HCLK_MSDC2			54
+#define CLK_PERAO_MSDC2_AXI				55
+#define CLK_PERAO_MSDC2_AXI_MSDC2			56
+#define CLK_PERAO_MSDC2_HCLK_WRAP			57
+#define CLK_PERAO_MSDC2_HCLK_WRAP_MSDC2			58
+#define CLK_PERAO_FLASHIF_FLASH				59
+#define CLK_PERAO_FLASHIF_FLASH_FLASHIF			60
+#define CLK_PERAO_FLASHIF_27M				61
+#define CLK_PERAO_FLASHIF_27M_FLASHIF			62
+#define CLK_PERAO_FLASHIF_DRAM				63
+#define CLK_PERAO_FLASHIF_DRAM_FLASHIF			64
+#define CLK_PERAO_FLASHIF_AXI				65
+#define CLK_PERAO_FLASHIF_AXI_FLASHIF			66
+#define CLK_PERAO_FLASHIF_BCLK				67
+#define CLK_PERAO_FLASHIF_BCLK_FLASHIF			68
+#define CLK_PERAO_NR_CLK				69
+
+/* UFSCFG_AO */
+#define CLK_UFSAO_UNIPRO_TX_SYM				0
+#define CLK_UFSAO_UNIPRO_TX_SYM_UFS			1
+#define CLK_UFSAO_UNIPRO_RX_SYM0			2
+#define CLK_UFSAO_UNIPRO_RX_SYM0_UFS			3
+#define CLK_UFSAO_UNIPRO_RX_SYM1			4
+#define CLK_UFSAO_UNIPRO_RX_SYM1_UFS			5
+#define CLK_UFSAO_UNIPRO_SYS				6
+#define CLK_UFSAO_UNIPRO_SYS_UFS			7
+#define CLK_UFSAO_UNIPRO_SAP				8
+#define CLK_UFSAO_UNIPRO_SAP_UFS			9
+#define CLK_UFSAO_PHY_SAP				10
+#define CLK_UFSAO_PHY_SAP_UFS				11
+#define CLK_UFSAO_UFSHCI_UFS				12
+#define CLK_UFSAO_UFSHCI_UFS_UFS			13
+#define CLK_UFSAO_UFSHCI_AES				14
+#define CLK_UFSAO_UFSHCI_AES_UFS			15
+#define CLK_UFSAO_NR_CLK				16
+
+/* PEXTP0CFG_AO */
+#define CLK_PEXT_PEXTP_MAC_P0_TL			0
+#define CLK_PEXT_PEXTP_MAC_P0_TL_PCIE			1
+#define CLK_PEXT_PEXTP_MAC_P0_REF			2
+#define CLK_PEXT_PEXTP_MAC_P0_REF_PCIE			3
+#define CLK_PEXT_PEXTP_PHY_P0_MCU_BUS			4
+#define CLK_PEXT_PEXTP_PHY_P0_MCU_BUS_PCIE		5
+#define CLK_PEXT_PEXTP_PHY_P0_PEXTP_REF			6
+#define CLK_PEXT_PEXTP_PHY_P0_PEXTP_REF_PCIE		7
+#define CLK_PEXT_PEXTP_MAC_P0_AXI_250			8
+#define CLK_PEXT_PEXTP_MAC_P0_AXI_250_PCIE		9
+#define CLK_PEXT_PEXTP_MAC_P0_AHB_APB			10
+#define CLK_PEXT_PEXTP_MAC_P0_AHB_APB_PCIE		11
+#define CLK_PEXT_PEXTP_MAC_P0_PL_P			12
+#define CLK_PEXT_PEXTP_MAC_P0_PL_P_PCIE			13
+#define CLK_PEXT_PEXTP_VLP_AO_P0_LP			14
+#define CLK_PEXT_PEXTP_VLP_AO_P0_LP_PCIE		15
+#define CLK_PEXT_NR_CLK					16
+
+/* PEXTP1CFG_AO */
+#define CLK_PEXT1_PEXTP_MAC_P1_TL			0
+#define CLK_PEXT1_PEXTP_MAC_P1_TL_PCIE			1
+#define CLK_PEXT1_PEXTP_MAC_P1_REF			2
+#define CLK_PEXT1_PEXTP_MAC_P1_REF_PCIE			3
+#define CLK_PEXT1_PEXTP_MAC_P2_TL			4
+#define CLK_PEXT1_PEXTP_MAC_P2_TL_PCIE			5
+#define CLK_PEXT1_PEXTP_MAC_P2_REF			6
+#define CLK_PEXT1_PEXTP_MAC_P2_REF_PCIE			7
+#define CLK_PEXT1_PEXTP_PHY_P1_MCU_BUS			8
+#define CLK_PEXT1_PEXTP_PHY_P1_MCU_BUS_PCIE		9
+#define CLK_PEXT1_PEXTP_PHY_P1_PEXTP_REF		10
+#define CLK_PEXT1_PEXTP_PHY_P1_PEXTP_REF_PCIE		11
+#define CLK_PEXT1_PEXTP_PHY_P2_MCU_BUS			12
+#define CLK_PEXT1_PEXTP_PHY_P2_MCU_BUS_PCIE		13
+#define CLK_PEXT1_PEXTP_PHY_P2_PEXTP_REF		14
+#define CLK_PEXT1_PEXTP_PHY_P2_PEXTP_REF_PCIE		15
+#define CLK_PEXT1_PEXTP_MAC_P1_AXI_250			16
+#define CLK_PEXT1_PEXTP_MAC_P1_AXI_250_PCIE		17
+#define CLK_PEXT1_PEXTP_MAC_P1_AHB_APB			18
+#define CLK_PEXT1_PEXTP_MAC_P1_AHB_APB_PCIE		19
+#define CLK_PEXT1_PEXTP_MAC_P1_PL_P			20
+#define CLK_PEXT1_PEXTP_MAC_P1_PL_P_PCIE		21
+#define CLK_PEXT1_PEXTP_MAC_P2_AXI_250			22
+#define CLK_PEXT1_PEXTP_MAC_P2_AXI_250_PCIE		23
+#define CLK_PEXT1_PEXTP_MAC_P2_AHB_APB			24
+#define CLK_PEXT1_PEXTP_MAC_P2_AHB_APB_PCIE		25
+#define CLK_PEXT1_PEXTP_MAC_P2_PL_P			26
+#define CLK_PEXT1_PEXTP_MAC_P2_PL_P_PCIE		27
+#define CLK_PEXT1_PEXTP_VLP_AO_P1_LP			28
+#define CLK_PEXT1_PEXTP_VLP_AO_P1_LP_PCIE		29
+#define CLK_PEXT1_PEXTP_VLP_AO_P2_LP			30
+#define CLK_PEXT1_PEXTP_VLP_AO_P2_LP_PCIE		31
+#define CLK_PEXT1_NR_CLK				32
+
+/* VLP_CKSYS */
+#define CLK_VLP_CK_VLP_APLL1				0
+#define CLK_VLP_CK_VLP_APLL2				1
+#define CLK_VLP_CK_SCP_SEL				2
+#define CLK_VLP_CK_SCP_SPI_SEL				3
+#define CLK_VLP_CK_SCP_IIC_SEL				4
+#define CLK_VLP_CK_SCP_IIC_HIGH_SPD_SEL			5
+#define CLK_VLP_CK_PWRAP_ULPOSC_SEL			6
+#define CLK_VLP_CK_SPMI_M_TIA_32K_SEL			7
+#define CLK_VLP_CK_APXGPT_26M_BCLK_SEL			8
+#define CLK_VLP_CK_DPSW_SEL				9
+#define CLK_VLP_CK_DPSW_CENTRAL_SEL			10
+#define CLK_VLP_CK_SPMI_M_MST_SEL			11
+#define CLK_VLP_CK_DVFSRC_SEL				12
+#define CLK_VLP_CK_PWM_VLP_SEL				13
+#define CLK_VLP_CK_AXI_VLP_SEL				14
+#define CLK_VLP_CK_SYSTIMER_26M_SEL			15
+#define CLK_VLP_CK_SSPM_SEL				16
+#define CLK_VLP_CK_SRCK_SEL				17
+#define CLK_VLP_CK_CAMTG0_SEL				18
+#define CLK_VLP_CK_CAMTG1_SEL				19
+#define CLK_VLP_CK_CAMTG2_SEL				20
+#define CLK_VLP_CK_CAMTG3_SEL				21
+#define CLK_VLP_CK_CAMTG4_SEL				22
+#define CLK_VLP_CK_CAMTG5_SEL				23
+#define CLK_VLP_CK_CAMTG6_SEL				24
+#define CLK_VLP_CK_CAMTG7_SEL				25
+#define CLK_VLP_CK_SSPM_26M_SEL				26
+#define CLK_VLP_CK_ULPOSC_SSPM_SEL			27
+#define CLK_VLP_CK_VLP_PBUS_26M_SEL			28
+#define CLK_VLP_CK_DEBUG_ERR_FLAG_SEL			29
+#define CLK_VLP_CK_DPMSRDMA_SEL				30
+#define CLK_VLP_CK_VLP_PBUS_156M_SEL			31
+#define CLK_VLP_CK_SPM_SEL				32
+#define CLK_VLP_CK_MMINFRA_VLP_SEL			33
+#define CLK_VLP_CK_USB_TOP_SEL				34
+#define CLK_VLP_CK_USB_XHCI_SEL				35
+#define CLK_VLP_CK_NOC_VLP_SEL				36
+#define CLK_VLP_CK_AUDIO_H_SEL				37
+#define CLK_VLP_CK_AUD_ENGEN1_SEL			38
+#define CLK_VLP_CK_AUD_ENGEN2_SEL			39
+#define CLK_VLP_CK_AUD_INTBUS_SEL			40
+#define CLK_VLP_CK_SPVLP_26M_SEL			41
+#define CLK_VLP_CK_SPU0_VLP_SEL				42
+#define CLK_VLP_CK_SPU1_VLP_SEL				43
+#define CLK_VLP_CK_OSC3					44
+#define CLK_VLP_CK_CLKSQ				45
+#define CLK_VLP_CK_AUDIO_H				46
+#define CLK_VLP_CK_AUD_ENGEN1				47
+#define CLK_VLP_CK_AUD_ENGEN2				48
+#define CLK_VLP_CK_INFRA_26M				49
+#define CLK_VLP_CK_AUD_CLKSQ				50
+#define CLK_VLP_CK_NR_CLK				51
+
+/* AFE */
+#define CLK_AFE_PCM1					0
+#define CLK_AFE_PCM1_AFE				1
+#define CLK_AFE_PCM0					2
+#define CLK_AFE_PCM0_AFE				3
+#define CLK_AFE_CM2					4
+#define CLK_AFE_CM2_AFE					5
+#define CLK_AFE_CM1					6
+#define CLK_AFE_CM1_AFE					7
+#define CLK_AFE_CM0					8
+#define CLK_AFE_CM0_AFE					9
+#define CLK_AFE_STF					10
+#define CLK_AFE_STF_AFE					11
+#define CLK_AFE_HW_GAIN23				12
+#define CLK_AFE_HW_GAIN23_AFE				13
+#define CLK_AFE_HW_GAIN01				14
+#define CLK_AFE_HW_GAIN01_AFE				15
+#define CLK_AFE_FM_I2S					16
+#define CLK_AFE_FM_I2S_AFE				17
+#define CLK_AFE_MTKAIFV4				18
+#define CLK_AFE_MTKAIFV4_AFE				19
+#define CLK_AFE_UL2_ADC_HIRES_TML			20
+#define CLK_AFE_UL2_ADC_HIRES_TML_AFE			21
+#define CLK_AFE_UL2_ADC_HIRES				22
+#define CLK_AFE_UL2_ADC_HIRES_AFE			23
+#define CLK_AFE_UL2_TML					24
+#define CLK_AFE_UL2_TML_AFE				25
+#define CLK_AFE_UL2_ADC					26
+#define CLK_AFE_UL2_ADC_AFE				27
+#define CLK_AFE_UL1_ADC_HIRES_TML			28
+#define CLK_AFE_UL1_ADC_HIRES_TML_AFE			29
+#define CLK_AFE_UL1_ADC_HIRES				30
+#define CLK_AFE_UL1_ADC_HIRES_AFE			31
+#define CLK_AFE_UL1_TML					32
+#define CLK_AFE_UL1_TML_AFE				33
+#define CLK_AFE_UL1_ADC					34
+#define CLK_AFE_UL1_ADC_AFE				35
+#define CLK_AFE_UL0_ADC_HIRES_TML			36
+#define CLK_AFE_UL0_ADC_HIRES_TML_AFE			37
+#define CLK_AFE_UL0_ADC_HIRES				38
+#define CLK_AFE_UL0_ADC_HIRES_AFE			39
+#define CLK_AFE_UL0_TML					40
+#define CLK_AFE_UL0_TML_AFE				41
+#define CLK_AFE_UL0_ADC					42
+#define CLK_AFE_UL0_ADC_AFE				43
+#define CLK_AFE_ETDM_IN6				44
+#define CLK_AFE_ETDM_IN6_AFE				45
+#define CLK_AFE_ETDM_IN5				46
+#define CLK_AFE_ETDM_IN5_AFE				47
+#define CLK_AFE_ETDM_IN4				48
+#define CLK_AFE_ETDM_IN4_AFE				49
+#define CLK_AFE_ETDM_IN3				50
+#define CLK_AFE_ETDM_IN3_AFE				51
+#define CLK_AFE_ETDM_IN2				52
+#define CLK_AFE_ETDM_IN2_AFE				53
+#define CLK_AFE_ETDM_IN1				54
+#define CLK_AFE_ETDM_IN1_AFE				55
+#define CLK_AFE_ETDM_IN0				56
+#define CLK_AFE_ETDM_IN0_AFE				57
+#define CLK_AFE_ETDM_OUT6				58
+#define CLK_AFE_ETDM_OUT6_AFE				59
+#define CLK_AFE_ETDM_OUT5				60
+#define CLK_AFE_ETDM_OUT5_AFE				61
+#define CLK_AFE_ETDM_OUT4				62
+#define CLK_AFE_ETDM_OUT4_AFE				63
+#define CLK_AFE_ETDM_OUT3				64
+#define CLK_AFE_ETDM_OUT3_AFE				65
+#define CLK_AFE_ETDM_OUT2				66
+#define CLK_AFE_ETDM_OUT2_AFE				67
+#define CLK_AFE_ETDM_OUT1				68
+#define CLK_AFE_ETDM_OUT1_AFE				69
+#define CLK_AFE_ETDM_OUT0				70
+#define CLK_AFE_ETDM_OUT0_AFE				71
+#define CLK_AFE_TDM_OUT					72
+#define CLK_AFE_TDM_OUT_AFE				73
+#define CLK_AFE_GENERAL15_ASRC				74
+#define CLK_AFE_GENERAL15_ASRC_AFE			75
+#define CLK_AFE_GENERAL14_ASRC				76
+#define CLK_AFE_GENERAL14_ASRC_AFE			77
+#define CLK_AFE_GENERAL13_ASRC				78
+#define CLK_AFE_GENERAL13_ASRC_AFE			79
+#define CLK_AFE_GENERAL12_ASRC				80
+#define CLK_AFE_GENERAL12_ASRC_AFE			81
+#define CLK_AFE_GENERAL11_ASRC				82
+#define CLK_AFE_GENERAL11_ASRC_AFE			83
+#define CLK_AFE_GENERAL10_ASRC				84
+#define CLK_AFE_GENERAL10_ASRC_AFE			85
+#define CLK_AFE_GENERAL9_ASRC				86
+#define CLK_AFE_GENERAL9_ASRC_AFE			87
+#define CLK_AFE_GENERAL8_ASRC				88
+#define CLK_AFE_GENERAL8_ASRC_AFE			89
+#define CLK_AFE_GENERAL7_ASRC				90
+#define CLK_AFE_GENERAL7_ASRC_AFE			91
+#define CLK_AFE_GENERAL6_ASRC				92
+#define CLK_AFE_GENERAL6_ASRC_AFE			93
+#define CLK_AFE_GENERAL5_ASRC				94
+#define CLK_AFE_GENERAL5_ASRC_AFE			95
+#define CLK_AFE_GENERAL4_ASRC				96
+#define CLK_AFE_GENERAL4_ASRC_AFE			97
+#define CLK_AFE_GENERAL3_ASRC				98
+#define CLK_AFE_GENERAL3_ASRC_AFE			99
+#define CLK_AFE_GENERAL2_ASRC				100
+#define CLK_AFE_GENERAL2_ASRC_AFE			101
+#define CLK_AFE_GENERAL1_ASRC				102
+#define CLK_AFE_GENERAL1_ASRC_AFE			103
+#define CLK_AFE_GENERAL0_ASRC				104
+#define CLK_AFE_GENERAL0_ASRC_AFE			105
+#define CLK_AFE_CONNSYS_I2S_ASRC			106
+#define CLK_AFE_CONNSYS_I2S_ASRC_AFE			107
+#define CLK_AFE_AUDIO_HOPPING				108
+#define CLK_AFE_AUDIO_HOPPING_AFE			109
+#define CLK_AFE_AUDIO_F26M				110
+#define CLK_AFE_AUDIO_F26M_AFE				111
+#define CLK_AFE_APLL1					112
+#define CLK_AFE_APLL1_AFE				113
+#define CLK_AFE_APLL2					114
+#define CLK_AFE_APLL2_AFE				115
+#define CLK_AFE_H208M					116
+#define CLK_AFE_H208M_AFE				117
+#define CLK_AFE_APLL_TUNER2				118
+#define CLK_AFE_APLL_TUNER2_AFE				119
+#define CLK_AFE_APLL_TUNER1				120
+#define CLK_AFE_APLL_TUNER1_AFE				121
+#define CLK_AFE_NR_CLK					122
+
+/* DISPSYS_CONFIG */
+#define CLK_MM_CONFIG					0
+#define CLK_MM_CONFIG_DISP				1
+#define CLK_MM_DISP_MUTEX0				2
+#define CLK_MM_DISP_MUTEX0_DISP				3
+#define CLK_MM_DISP_AAL0				4
+#define CLK_MM_DISP_AAL0_PQ				5
+#define CLK_MM_DISP_AAL1				6
+#define CLK_MM_DISP_AAL1_PQ				7
+#define CLK_MM_DISP_C3D0				8
+#define CLK_MM_DISP_C3D0_PQ				9
+#define CLK_MM_DISP_C3D1				10
+#define CLK_MM_DISP_C3D1_PQ				11
+#define CLK_MM_DISP_C3D2				12
+#define CLK_MM_DISP_C3D2_PQ				13
+#define CLK_MM_DISP_C3D3				14
+#define CLK_MM_DISP_C3D3_PQ				15
+#define CLK_MM_DISP_CCORR0				16
+#define CLK_MM_DISP_CCORR0_PQ				17
+#define CLK_MM_DISP_CCORR1				18
+#define CLK_MM_DISP_CCORR1_PQ				19
+#define CLK_MM_DISP_CCORR2				20
+#define CLK_MM_DISP_CCORR2_PQ				21
+#define CLK_MM_DISP_CCORR3				22
+#define CLK_MM_DISP_CCORR3_PQ				23
+#define CLK_MM_DISP_CHIST0				24
+#define CLK_MM_DISP_CHIST0_PQ				25
+#define CLK_MM_DISP_CHIST1				26
+#define CLK_MM_DISP_CHIST1_PQ				27
+#define CLK_MM_DISP_COLOR0				28
+#define CLK_MM_DISP_COLOR0_PQ				29
+#define CLK_MM_DISP_COLOR1				30
+#define CLK_MM_DISP_COLOR1_PQ				31
+#define CLK_MM_DISP_DITHER0				32
+#define CLK_MM_DISP_DITHER0_PQ				33
+#define CLK_MM_DISP_DITHER1				34
+#define CLK_MM_DISP_DITHER1_PQ				35
+#define CLK_MM_DISP_DLI_ASYNC0				36
+#define CLK_MM_DISP_DLI_ASYNC0_DISP			37
+#define CLK_MM_DISP_DLI_ASYNC1				38
+#define CLK_MM_DISP_DLI_ASYNC1_DISP			39
+#define CLK_MM_DISP_DLI_ASYNC2				40
+#define CLK_MM_DISP_DLI_ASYNC2_DISP			41
+#define CLK_MM_DISP_DLI_ASYNC3				42
+#define CLK_MM_DISP_DLI_ASYNC3_DISP			43
+#define CLK_MM_DISP_DLI_ASYNC4				44
+#define CLK_MM_DISP_DLI_ASYNC4_DISP			45
+#define CLK_MM_DISP_DLI_ASYNC5				46
+#define CLK_MM_DISP_DLI_ASYNC5_DISP			47
+#define CLK_MM_DISP_DLI_ASYNC6				48
+#define CLK_MM_DISP_DLI_ASYNC6_DISP			49
+#define CLK_MM_DISP_DLI_ASYNC7				50
+#define CLK_MM_DISP_DLI_ASYNC7_DISP			51
+#define CLK_MM_DISP_DLI_ASYNC8				52
+#define CLK_MM_DISP_DLI_ASYNC8_DISP			53
+#define CLK_MM_DISP_DLI_ASYNC9				54
+#define CLK_MM_DISP_DLI_ASYNC9_DISP			55
+#define CLK_MM_DISP_DLI_ASYNC10				56
+#define CLK_MM_DISP_DLI_ASYNC10_DISP			57
+#define CLK_MM_DISP_DLI_ASYNC11				58
+#define CLK_MM_DISP_DLI_ASYNC11_DISP			59
+#define CLK_MM_DISP_DLI_ASYNC12				60
+#define CLK_MM_DISP_DLI_ASYNC12_DISP			61
+#define CLK_MM_DISP_DLI_ASYNC13				62
+#define CLK_MM_DISP_DLI_ASYNC13_DISP			63
+#define CLK_MM_DISP_DLI_ASYNC14				64
+#define CLK_MM_DISP_DLI_ASYNC14_DISP			65
+#define CLK_MM_DISP_DLI_ASYNC15				66
+#define CLK_MM_DISP_DLI_ASYNC15_DISP			67
+#define CLK_MM_DISP_DLO_ASYNC0				68
+#define CLK_MM_DISP_DLO_ASYNC0_DISP			69
+#define CLK_MM_DISP_DLO_ASYNC1				70
+#define CLK_MM_DISP_DLO_ASYNC1_DISP			71
+#define CLK_MM_DISP_DLO_ASYNC2				72
+#define CLK_MM_DISP_DLO_ASYNC2_DISP			73
+#define CLK_MM_DISP_DLO_ASYNC3				74
+#define CLK_MM_DISP_DLO_ASYNC3_DISP			75
+#define CLK_MM_DISP_DLO_ASYNC4				76
+#define CLK_MM_DISP_DLO_ASYNC4_DISP			77
+#define CLK_MM_DISP_DLO_ASYNC5				78
+#define CLK_MM_DISP_DLO_ASYNC5_DISP			79
+#define CLK_MM_DISP_DLO_ASYNC6				80
+#define CLK_MM_DISP_DLO_ASYNC6_DISP			81
+#define CLK_MM_DISP_DLO_ASYNC7				82
+#define CLK_MM_DISP_DLO_ASYNC7_DISP			83
+#define CLK_MM_DISP_DLO_ASYNC8				84
+#define CLK_MM_DISP_DLO_ASYNC8_DISP			85
+#define CLK_MM_DISP_GAMMA0				86
+#define CLK_MM_DISP_GAMMA0_PQ				87
+#define CLK_MM_DISP_GAMMA1				88
+#define CLK_MM_DISP_GAMMA1_PQ				89
+#define CLK_MM_MDP_AAL0					90
+#define CLK_MM_MDP_AAL0_PQ				91
+#define CLK_MM_MDP_AAL1					92
+#define CLK_MM_MDP_AAL1_PQ				93
+#define CLK_MM_MDP_RDMA0				94
+#define CLK_MM_MDP_RDMA0_DISP				95
+#define CLK_MM_DISP_POSTMASK0				96
+#define CLK_MM_DISP_POSTMASK0_DISP			97
+#define CLK_MM_DISP_POSTMASK1				98
+#define CLK_MM_DISP_POSTMASK1_DISP			99
+#define CLK_MM_MDP_RSZ0					100
+#define CLK_MM_MDP_RSZ0_DISP				101
+#define CLK_MM_MDP_RSZ1					102
+#define CLK_MM_MDP_RSZ1_DISP				103
+#define CLK_MM_DISP_SPR0				104
+#define CLK_MM_DISP_SPR0_DISP				105
+#define CLK_MM_DISP_TDSHP0				106
+#define CLK_MM_DISP_TDSHP0_PQ				107
+#define CLK_MM_DISP_TDSHP1				108
+#define CLK_MM_DISP_TDSHP1_PQ				109
+#define CLK_MM_DISP_WDMA0				110
+#define CLK_MM_DISP_WDMA0_DISP				111
+#define CLK_MM_DISP_Y2R0				112
+#define CLK_MM_DISP_Y2R0_DISP				113
+#define CLK_MM_SMI_SUB_COMM0				114
+#define CLK_MM_SMI_SUB_COMM0_SMI			115
+#define CLK_MM_DISP_FAKE_ENG0				116
+#define CLK_MM_DISP_FAKE_ENG0_DISP			117
+#define CLK_MM_NR_CLK					118
+
+/* DISPSYS1_CONFIG */
+#define CLK_MM1_DISPSYS1_CONFIG				0
+#define CLK_MM1_DISPSYS1_CONFIG_DISP			1
+#define CLK_MM1_DISPSYS1_S_CONFIG			2
+#define CLK_MM1_DISPSYS1_S_CONFIG_DISP			3
+#define CLK_MM1_DISP_MUTEX0				4
+#define CLK_MM1_DISP_MUTEX0_DISP			5
+#define CLK_MM1_DISP_DLI_ASYNC20			6
+#define CLK_MM1_DISP_DLI_ASYNC20_DISP			7
+#define CLK_MM1_DISP_DLI_ASYNC21			8
+#define CLK_MM1_DISP_DLI_ASYNC21_DISP			9
+#define CLK_MM1_DISP_DLI_ASYNC22			10
+#define CLK_MM1_DISP_DLI_ASYNC22_DISP			11
+#define CLK_MM1_DISP_DLI_ASYNC23			12
+#define CLK_MM1_DISP_DLI_ASYNC23_DISP			13
+#define CLK_MM1_DISP_DLI_ASYNC24			14
+#define CLK_MM1_DISP_DLI_ASYNC24_DISP			15
+#define CLK_MM1_DISP_DLI_ASYNC25			16
+#define CLK_MM1_DISP_DLI_ASYNC25_DISP			17
+#define CLK_MM1_DISP_DLI_ASYNC26			18
+#define CLK_MM1_DISP_DLI_ASYNC26_DISP			19
+#define CLK_MM1_DISP_DLI_ASYNC27			20
+#define CLK_MM1_DISP_DLI_ASYNC27_DISP			21
+#define CLK_MM1_DISP_DLI_ASYNC28			22
+#define CLK_MM1_DISP_DLI_ASYNC28_DISP			23
+#define CLK_MM1_DISP_RELAY0				24
+#define CLK_MM1_DISP_RELAY0_DISP			25
+#define CLK_MM1_DISP_RELAY1				26
+#define CLK_MM1_DISP_RELAY1_DISP			27
+#define CLK_MM1_DISP_RELAY2				28
+#define CLK_MM1_DISP_RELAY2_DISP			29
+#define CLK_MM1_DISP_RELAY3				30
+#define CLK_MM1_DISP_RELAY3_DISP			31
+#define CLK_MM1_DISP_DP_INTF0				32
+#define CLK_MM1_DISP_DP_INTF0_DISP			33
+#define CLK_MM1_DISP_DP_INTF1				34
+#define CLK_MM1_DISP_DP_INTF1_DISP			35
+#define CLK_MM1_DISP_DSC_WRAP0				36
+#define CLK_MM1_DISP_DSC_WRAP0_DISP			37
+#define CLK_MM1_DISP_DSC_WRAP1				38
+#define CLK_MM1_DISP_DSC_WRAP1_DISP			39
+#define CLK_MM1_DISP_DSC_WRAP2				40
+#define CLK_MM1_DISP_DSC_WRAP2_DISP			41
+#define CLK_MM1_DISP_DSC_WRAP3				42
+#define CLK_MM1_DISP_DSC_WRAP3_DISP			43
+#define CLK_MM1_DISP_DSI0				44
+#define CLK_MM1_DISP_DSI0_DISP				45
+#define CLK_MM1_DISP_DSI1				46
+#define CLK_MM1_DISP_DSI1_DISP				47
+#define CLK_MM1_DISP_DSI2				48
+#define CLK_MM1_DISP_DSI2_DISP				49
+#define CLK_MM1_DISP_DVO0				50
+#define CLK_MM1_DISP_DVO0_DISP				51
+#define CLK_MM1_DISP_GDMA0				52
+#define CLK_MM1_DISP_GDMA0_DISP				53
+#define CLK_MM1_DISP_MERGE0				54
+#define CLK_MM1_DISP_MERGE0_DISP			55
+#define CLK_MM1_DISP_MERGE1				56
+#define CLK_MM1_DISP_MERGE1_DISP			57
+#define CLK_MM1_DISP_MERGE2				58
+#define CLK_MM1_DISP_MERGE2_DISP			59
+#define CLK_MM1_DISP_ODDMR0				60
+#define CLK_MM1_DISP_ODDMR0_PQ				61
+#define CLK_MM1_DISP_POSTALIGN0				62
+#define CLK_MM1_DISP_POSTALIGN0_PQ			63
+#define CLK_MM1_DISP_DITHER2				64
+#define CLK_MM1_DISP_DITHER2_PQ				65
+#define CLK_MM1_DISP_R2Y0				66
+#define CLK_MM1_DISP_R2Y0_DISP				67
+#define CLK_MM1_DISP_SPLITTER0				68
+#define CLK_MM1_DISP_SPLITTER0_DISP			69
+#define CLK_MM1_DISP_SPLITTER1				70
+#define CLK_MM1_DISP_SPLITTER1_DISP			71
+#define CLK_MM1_DISP_SPLITTER2				72
+#define CLK_MM1_DISP_SPLITTER2_DISP			73
+#define CLK_MM1_DISP_SPLITTER3				74
+#define CLK_MM1_DISP_SPLITTER3_DISP			75
+#define CLK_MM1_DISP_VDCM0				76
+#define CLK_MM1_DISP_VDCM0_DISP				77
+#define CLK_MM1_DISP_WDMA1				78
+#define CLK_MM1_DISP_WDMA1_DISP				79
+#define CLK_MM1_DISP_WDMA2				80
+#define CLK_MM1_DISP_WDMA2_DISP				81
+#define CLK_MM1_DISP_WDMA3				82
+#define CLK_MM1_DISP_WDMA3_DISP				83
+#define CLK_MM1_DISP_WDMA4				84
+#define CLK_MM1_DISP_WDMA4_DISP				85
+#define CLK_MM1_MDP_RDMA1				86
+#define CLK_MM1_MDP_RDMA1_DISP				87
+#define CLK_MM1_SMI_LARB0				88
+#define CLK_MM1_SMI_LARB0_SMI				89
+#define CLK_MM1_MOD1					90
+#define CLK_MM1_MOD1_DISP				91
+#define CLK_MM1_MOD2					92
+#define CLK_MM1_MOD2_DISP				93
+#define CLK_MM1_MOD3					94
+#define CLK_MM1_MOD3_DISP				95
+#define CLK_MM1_MOD4					96
+#define CLK_MM1_MOD4_DISP				97
+#define CLK_MM1_MOD5					98
+#define CLK_MM1_MOD5_DISP				99
+#define CLK_MM1_MOD6					100
+#define CLK_MM1_MOD6_DISP				101
+#define CLK_MM1_CK_CG0					102
+#define CLK_MM1_CK_CG0_DISP				103
+#define CLK_MM1_CK_CG1					104
+#define CLK_MM1_CK_CG1_DISP				105
+#define CLK_MM1_CK_CG2					106
+#define CLK_MM1_CK_CG2_DISP				107
+#define CLK_MM1_CK_CG3					108
+#define CLK_MM1_CK_CG3_DISP				109
+#define CLK_MM1_CK_CG4					110
+#define CLK_MM1_CK_CG4_DISP				111
+#define CLK_MM1_CK_CG5					112
+#define CLK_MM1_CK_CG5_DISP				113
+#define CLK_MM1_CK_CG6					114
+#define CLK_MM1_CK_CG6_DISP				115
+#define CLK_MM1_CK_CG7					116
+#define CLK_MM1_CK_CG7_DISP				117
+#define CLK_MM1_F26M					118
+#define CLK_MM1_F26M_DISP				119
+#define CLK_MM1_NR_CLK					120
+
+/* OVLSYS_CONFIG */
+#define CLK_OVLSYS_CONFIG				0
+#define CLK_OVLSYS_CONFIG_DISP				1
+#define CLK_OVL_FAKE_ENG0				2
+#define CLK_OVL_FAKE_ENG0_DISP				3
+#define CLK_OVL_FAKE_ENG1				4
+#define CLK_OVL_FAKE_ENG1_DISP				5
+#define CLK_OVL_MUTEX0					6
+#define CLK_OVL_MUTEX0_DISP				7
+#define CLK_OVL_EXDMA0					8
+#define CLK_OVL_EXDMA0_DISP				9
+#define CLK_OVL_EXDMA1					10
+#define CLK_OVL_EXDMA1_DISP				11
+#define CLK_OVL_EXDMA2					12
+#define CLK_OVL_EXDMA2_DISP				13
+#define CLK_OVL_EXDMA3					14
+#define CLK_OVL_EXDMA3_DISP				15
+#define CLK_OVL_EXDMA4					16
+#define CLK_OVL_EXDMA4_DISP				17
+#define CLK_OVL_EXDMA5					18
+#define CLK_OVL_EXDMA5_DISP				19
+#define CLK_OVL_EXDMA6					20
+#define CLK_OVL_EXDMA6_DISP				21
+#define CLK_OVL_EXDMA7					22
+#define CLK_OVL_EXDMA7_DISP				23
+#define CLK_OVL_EXDMA8					24
+#define CLK_OVL_EXDMA8_DISP				25
+#define CLK_OVL_EXDMA9					26
+#define CLK_OVL_EXDMA9_DISP				27
+#define CLK_OVL_BLENDER0				28
+#define CLK_OVL_BLENDER0_DISP				29
+#define CLK_OVL_BLENDER1				30
+#define CLK_OVL_BLENDER1_DISP				31
+#define CLK_OVL_BLENDER2				32
+#define CLK_OVL_BLENDER2_DISP				33
+#define CLK_OVL_BLENDER3				34
+#define CLK_OVL_BLENDER3_DISP				35
+#define CLK_OVL_BLENDER4				36
+#define CLK_OVL_BLENDER4_DISP				37
+#define CLK_OVL_BLENDER5				38
+#define CLK_OVL_BLENDER5_DISP				39
+#define CLK_OVL_BLENDER6				40
+#define CLK_OVL_BLENDER6_DISP				41
+#define CLK_OVL_BLENDER7				42
+#define CLK_OVL_BLENDER7_DISP				43
+#define CLK_OVL_BLENDER8				44
+#define CLK_OVL_BLENDER8_DISP				45
+#define CLK_OVL_BLENDER9				46
+#define CLK_OVL_BLENDER9_DISP				47
+#define CLK_OVL_OUTPROC0				48
+#define CLK_OVL_OUTPROC0_DISP				49
+#define CLK_OVL_OUTPROC1				50
+#define CLK_OVL_OUTPROC1_DISP				51
+#define CLK_OVL_OUTPROC2				52
+#define CLK_OVL_OUTPROC2_DISP				53
+#define CLK_OVL_OUTPROC3				54
+#define CLK_OVL_OUTPROC3_DISP				55
+#define CLK_OVL_OUTPROC4				56
+#define CLK_OVL_OUTPROC4_DISP				57
+#define CLK_OVL_OUTPROC5				58
+#define CLK_OVL_OUTPROC5_DISP				59
+#define CLK_OVL_MDP_RSZ0				60
+#define CLK_OVL_MDP_RSZ0_DISP				61
+#define CLK_OVL_MDP_RSZ1				62
+#define CLK_OVL_MDP_RSZ1_DISP				63
+#define CLK_OVL_DISP_WDMA0				64
+#define CLK_OVL_DISP_WDMA0_DISP				65
+#define CLK_OVL_DISP_WDMA1				66
+#define CLK_OVL_DISP_WDMA1_DISP				67
+#define CLK_OVL_UFBC_WDMA0				68
+#define CLK_OVL_UFBC_WDMA0_DISP				69
+#define CLK_OVL_MDP_RDMA0				70
+#define CLK_OVL_MDP_RDMA0_DISP				71
+#define CLK_OVL_MDP_RDMA1				72
+#define CLK_OVL_MDP_RDMA1_DISP				73
+#define CLK_OVL_BWM0					74
+#define CLK_OVL_BWM0_DISP				75
+#define CLK_OVL_DLI0					76
+#define CLK_OVL_DLI0_DISP				77
+#define CLK_OVL_DLI1					78
+#define CLK_OVL_DLI1_DISP				79
+#define CLK_OVL_DLI2					80
+#define CLK_OVL_DLI2_DISP				81
+#define CLK_OVL_DLI3					82
+#define CLK_OVL_DLI3_DISP				83
+#define CLK_OVL_DLI4					84
+#define CLK_OVL_DLI4_DISP				85
+#define CLK_OVL_DLI5					86
+#define CLK_OVL_DLI5_DISP				87
+#define CLK_OVL_DLI6					88
+#define CLK_OVL_DLI6_DISP				89
+#define CLK_OVL_DLI7					90
+#define CLK_OVL_DLI7_DISP				91
+#define CLK_OVL_DLI8					92
+#define CLK_OVL_DLI8_DISP				93
+#define CLK_OVL_DLO0					94
+#define CLK_OVL_DLO0_DISP				95
+#define CLK_OVL_DLO1					96
+#define CLK_OVL_DLO1_DISP				97
+#define CLK_OVL_DLO2					98
+#define CLK_OVL_DLO2_DISP				99
+#define CLK_OVL_DLO3					100
+#define CLK_OVL_DLO3_DISP				101
+#define CLK_OVL_DLO4					102
+#define CLK_OVL_DLO4_DISP				103
+#define CLK_OVL_DLO5					104
+#define CLK_OVL_DLO5_DISP				105
+#define CLK_OVL_DLO6					106
+#define CLK_OVL_DLO6_DISP				107
+#define CLK_OVL_DLO7					108
+#define CLK_OVL_DLO7_DISP				109
+#define CLK_OVL_DLO8					110
+#define CLK_OVL_DLO8_DISP				111
+#define CLK_OVL_DLO9					112
+#define CLK_OVL_DLO9_DISP				113
+#define CLK_OVL_DLO10					114
+#define CLK_OVL_DLO10_DISP				115
+#define CLK_OVL_DLO11					116
+#define CLK_OVL_DLO11_DISP				117
+#define CLK_OVL_DLO12					118
+#define CLK_OVL_DLO12_DISP				119
+#define CLK_OVLSYS_RELAY0				120
+#define CLK_OVLSYS_RELAY0_DISP				121
+#define CLK_OVL_INLINEROT0				122
+#define CLK_OVL_INLINEROT0_DISP				123
+#define CLK_OVL_SMI					124
+#define CLK_OVL_SMI_SMI					125
+#define CLK_OVL_NR_CLK					126
+
+/* OVLSYS1_CONFIG */
+#define CLK_OVL1_OVLSYS_CONFIG				0
+#define CLK_OVL1_OVLSYS_CONFIG_DISP			1
+#define CLK_OVL1_OVL_FAKE_ENG0				2
+#define CLK_OVL1_OVL_FAKE_ENG0_DISP			3
+#define CLK_OVL1_OVL_FAKE_ENG1				4
+#define CLK_OVL1_OVL_FAKE_ENG1_DISP			5
+#define CLK_OVL1_OVL_MUTEX0				6
+#define CLK_OVL1_OVL_MUTEX0_DISP			7
+#define CLK_OVL1_OVL_EXDMA0				8
+#define CLK_OVL1_OVL_EXDMA0_DISP			9
+#define CLK_OVL1_OVL_EXDMA1				10
+#define CLK_OVL1_OVL_EXDMA1_DISP			11
+#define CLK_OVL1_OVL_EXDMA2				12
+#define CLK_OVL1_OVL_EXDMA2_DISP			13
+#define CLK_OVL1_OVL_EXDMA3				14
+#define CLK_OVL1_OVL_EXDMA3_DISP			15
+#define CLK_OVL1_OVL_EXDMA4				16
+#define CLK_OVL1_OVL_EXDMA4_DISP			17
+#define CLK_OVL1_OVL_EXDMA5				18
+#define CLK_OVL1_OVL_EXDMA5_DISP			19
+#define CLK_OVL1_OVL_EXDMA6				20
+#define CLK_OVL1_OVL_EXDMA6_DISP			21
+#define CLK_OVL1_OVL_EXDMA7				22
+#define CLK_OVL1_OVL_EXDMA7_DISP			23
+#define CLK_OVL1_OVL_EXDMA8				24
+#define CLK_OVL1_OVL_EXDMA8_DISP			25
+#define CLK_OVL1_OVL_EXDMA9				26
+#define CLK_OVL1_OVL_EXDMA9_DISP			27
+#define CLK_OVL1_OVL_BLENDER0				28
+#define CLK_OVL1_OVL_BLENDER0_DISP			29
+#define CLK_OVL1_OVL_BLENDER1				30
+#define CLK_OVL1_OVL_BLENDER1_DISP			31
+#define CLK_OVL1_OVL_BLENDER2				32
+#define CLK_OVL1_OVL_BLENDER2_DISP			33
+#define CLK_OVL1_OVL_BLENDER3				34
+#define CLK_OVL1_OVL_BLENDER3_DISP			35
+#define CLK_OVL1_OVL_BLENDER4				36
+#define CLK_OVL1_OVL_BLENDER4_DISP			37
+#define CLK_OVL1_OVL_BLENDER5				38
+#define CLK_OVL1_OVL_BLENDER5_DISP			39
+#define CLK_OVL1_OVL_BLENDER6				40
+#define CLK_OVL1_OVL_BLENDER6_DISP			41
+#define CLK_OVL1_OVL_BLENDER7				42
+#define CLK_OVL1_OVL_BLENDER7_DISP			43
+#define CLK_OVL1_OVL_BLENDER8				44
+#define CLK_OVL1_OVL_BLENDER8_DISP			45
+#define CLK_OVL1_OVL_BLENDER9				46
+#define CLK_OVL1_OVL_BLENDER9_DISP			47
+#define CLK_OVL1_OVL_OUTPROC0				48
+#define CLK_OVL1_OVL_OUTPROC0_DISP			49
+#define CLK_OVL1_OVL_OUTPROC1				50
+#define CLK_OVL1_OVL_OUTPROC1_DISP			51
+#define CLK_OVL1_OVL_OUTPROC2				52
+#define CLK_OVL1_OVL_OUTPROC2_DISP			53
+#define CLK_OVL1_OVL_OUTPROC3				54
+#define CLK_OVL1_OVL_OUTPROC3_DISP			55
+#define CLK_OVL1_OVL_OUTPROC4				56
+#define CLK_OVL1_OVL_OUTPROC4_DISP			57
+#define CLK_OVL1_OVL_OUTPROC5				58
+#define CLK_OVL1_OVL_OUTPROC5_DISP			59
+#define CLK_OVL1_OVL_MDP_RSZ0				60
+#define CLK_OVL1_OVL_MDP_RSZ0_DISP			61
+#define CLK_OVL1_OVL_MDP_RSZ1				62
+#define CLK_OVL1_OVL_MDP_RSZ1_DISP			63
+#define CLK_OVL1_OVL_DISP_WDMA0				64
+#define CLK_OVL1_OVL_DISP_WDMA0_DISP			65
+#define CLK_OVL1_OVL_DISP_WDMA1				66
+#define CLK_OVL1_OVL_DISP_WDMA1_DISP			67
+#define CLK_OVL1_OVL_UFBC_WDMA0				68
+#define CLK_OVL1_OVL_UFBC_WDMA0_DISP			69
+#define CLK_OVL1_OVL_MDP_RDMA0				70
+#define CLK_OVL1_OVL_MDP_RDMA0_DISP			71
+#define CLK_OVL1_OVL_MDP_RDMA1				72
+#define CLK_OVL1_OVL_MDP_RDMA1_DISP			73
+#define CLK_OVL1_OVL_BWM0				74
+#define CLK_OVL1_OVL_BWM0_DISP				75
+#define CLK_OVL1_DLI0					76
+#define CLK_OVL1_DLI0_DISP				77
+#define CLK_OVL1_DLI1					78
+#define CLK_OVL1_DLI1_DISP				79
+#define CLK_OVL1_DLI2					80
+#define CLK_OVL1_DLI2_DISP				81
+#define CLK_OVL1_DLI3					82
+#define CLK_OVL1_DLI3_DISP				83
+#define CLK_OVL1_DLI4					84
+#define CLK_OVL1_DLI4_DISP				85
+#define CLK_OVL1_DLI5					86
+#define CLK_OVL1_DLI5_DISP				87
+#define CLK_OVL1_DLI6					88
+#define CLK_OVL1_DLI6_DISP				89
+#define CLK_OVL1_DLI7					90
+#define CLK_OVL1_DLI7_DISP				91
+#define CLK_OVL1_DLI8					92
+#define CLK_OVL1_DLI8_DISP				93
+#define CLK_OVL1_DLO0					94
+#define CLK_OVL1_DLO0_DISP				95
+#define CLK_OVL1_DLO1					96
+#define CLK_OVL1_DLO1_DISP				97
+#define CLK_OVL1_DLO2					98
+#define CLK_OVL1_DLO2_DISP				99
+#define CLK_OVL1_DLO3					100
+#define CLK_OVL1_DLO3_DISP				101
+#define CLK_OVL1_DLO4					102
+#define CLK_OVL1_DLO4_DISP				103
+#define CLK_OVL1_DLO5					104
+#define CLK_OVL1_DLO5_DISP				105
+#define CLK_OVL1_DLO6					106
+#define CLK_OVL1_DLO6_DISP				107
+#define CLK_OVL1_DLO7					108
+#define CLK_OVL1_DLO7_DISP				109
+#define CLK_OVL1_DLO8					110
+#define CLK_OVL1_DLO8_DISP				111
+#define CLK_OVL1_DLO9					112
+#define CLK_OVL1_DLO9_DISP				113
+#define CLK_OVL1_DLO10					114
+#define CLK_OVL1_DLO10_DISP				115
+#define CLK_OVL1_DLO11					116
+#define CLK_OVL1_DLO11_DISP				117
+#define CLK_OVL1_DLO12					118
+#define CLK_OVL1_DLO12_DISP				119
+#define CLK_OVL1_OVLSYS_RELAY0				120
+#define CLK_OVL1_OVLSYS_RELAY0_DISP			121
+#define CLK_OVL1_OVL_INLINEROT0				122
+#define CLK_OVL1_OVL_INLINEROT0_DISP			123
+#define CLK_OVL1_SMI					124
+#define CLK_OVL1_SMI_SMI				125
+#define CLK_OVL1_NR_CLK					126
+
+/* VDEC_SOC_GCON_BASE */
+#define CLK_VDE1_LARB1_CKEN				0
+#define CLK_VDE1_LARB1_CKEN_VDEC			1
+#define CLK_VDE1_LARB1_CKEN_SMI				2
+#define CLK_VDE1_LAT_CKEN				3
+#define CLK_VDE1_LAT_CKEN_VDEC				4
+#define CLK_VDE1_LAT_ACTIVE				5
+#define CLK_VDE1_LAT_ACTIVE_VDEC			6
+#define CLK_VDE1_LAT_CKEN_ENG				7
+#define CLK_VDE1_LAT_CKEN_ENG_VDEC			8
+#define CLK_VDE1_VDEC_CKEN				9
+#define CLK_VDE1_VDEC_CKEN_VDEC				10
+#define CLK_VDE1_VDEC_ACTIVE				11
+#define CLK_VDE1_VDEC_ACTIVE_VDEC			12
+#define CLK_VDE1_VDEC_CKEN_ENG				13
+#define CLK_VDE1_VDEC_CKEN_ENG_VDEC			14
+#define CLK_VDE1_VDEC_SOC_APTV_EN			15
+#define CLK_VDE1_VDEC_SOC_APTV_EN_VDEC			16
+#define CLK_VDE1_VDEC_SOC_APTV_TOP_EN			17
+#define CLK_VDE1_VDEC_SOC_APTV_TOP_EN_VDEC		18
+#define CLK_VDE1_VDEC_SOC_IPS_EN			19
+#define CLK_VDE1_VDEC_SOC_IPS_EN_VDEC			20
+#define CLK_VDE1_NR_CLK					21
+
+/* VDEC_GCON_BASE */
+#define CLK_VDE2_LARB1_CKEN				0
+#define CLK_VDE2_LARB1_CKEN_VDEC			1
+#define CLK_VDE2_LARB1_CKEN_SMI				2
+#define CLK_VDE2_LAT_CKEN				3
+#define CLK_VDE2_LAT_CKEN_VDEC				4
+#define CLK_VDE2_LAT_ACTIVE				5
+#define CLK_VDE2_LAT_ACTIVE_VDEC			6
+#define CLK_VDE2_LAT_CKEN_ENG				7
+#define CLK_VDE2_LAT_CKEN_ENG_VDEC			8
+#define CLK_VDE2_VDEC_CKEN				9
+#define CLK_VDE2_VDEC_CKEN_VDEC				10
+#define CLK_VDE2_VDEC_ACTIVE				11
+#define CLK_VDE2_VDEC_ACTIVE_VDEC			12
+#define CLK_VDE2_VDEC_CKEN_ENG				13
+#define CLK_VDE2_VDEC_CKEN_ENG_VDEC			14
+#define CLK_VDE2_NR_CLK					15
+
+/* VENC_GCON */
+#define CLK_VEN1_CKE0_LARB				0
+#define CLK_VEN1_CKE0_LARB_VENC				1
+#define CLK_VEN1_CKE0_LARB_JPGENC			2
+#define CLK_VEN1_CKE0_LARB_JPGDEC			3
+#define CLK_VEN1_CKE0_LARB_SMI				4
+#define CLK_VEN1_CKE1_VENC				5
+#define CLK_VEN1_CKE1_VENC_VENC				6
+#define CLK_VEN1_CKE1_VENC_SMI				7
+#define CLK_VEN1_CKE2_JPGENC				8
+#define CLK_VEN1_CKE2_JPGENC_JPGENC			9
+#define CLK_VEN1_CKE3_JPGDEC				10
+#define CLK_VEN1_CKE3_JPGDEC_JPGDEC			11
+#define CLK_VEN1_CKE4_JPGDEC_C1				12
+#define CLK_VEN1_CKE4_JPGDEC_C1_JPGDEC			13
+#define CLK_VEN1_CKE5_GALS				14
+#define CLK_VEN1_CKE5_GALS_VENC				15
+#define CLK_VEN1_CKE5_GALS_JPGENC			16
+#define CLK_VEN1_CKE5_GALS_JPGDEC			17
+#define CLK_VEN1_CKE29_VENC_ADAB_CTRL			18
+#define CLK_VEN1_CKE29_VENC_ADAB_CTRL_VENC		19
+#define CLK_VEN1_CKE29_VENC_XPC_CTRL			20
+#define CLK_VEN1_CKE29_VENC_XPC_CTRL_VENC		21
+#define CLK_VEN1_CKE29_VENC_XPC_CTRL_JPGENC		22
+#define CLK_VEN1_CKE29_VENC_XPC_CTRL_JPGDEC		23
+#define CLK_VEN1_CKE6_GALS_SRAM				24
+#define CLK_VEN1_CKE6_GALS_SRAM_VENC			25
+#define CLK_VEN1_RES_FLAT				26
+#define CLK_VEN1_RES_FLAT_VENC				27
+#define CLK_VEN1_RES_FLAT_JPGENC			28
+#define CLK_VEN1_RES_FLAT_JPGDEC			29
+#define CLK_VEN1_NR_CLK					30
+
+/* VENC_GCON_CORE1 */
+#define CLK_VEN2_CKE0_LARB				0
+#define CLK_VEN2_CKE0_LARB_VENC				1
+#define CLK_VEN2_CKE0_LARB_JPGENC			2
+#define CLK_VEN2_CKE0_LARB_JPGDEC			3
+#define CLK_VEN2_CKE0_LARB_SMI				4
+#define CLK_VEN2_CKE1_VENC				5
+#define CLK_VEN2_CKE1_VENC_VENC				6
+#define CLK_VEN2_CKE1_VENC_SMI				7
+#define CLK_VEN2_CKE2_JPGENC				8
+#define CLK_VEN2_CKE2_JPGENC_JPGENC			9
+#define CLK_VEN2_CKE3_JPGDEC				10
+#define CLK_VEN2_CKE3_JPGDEC_JPGDEC			11
+#define CLK_VEN2_CKE5_GALS				12
+#define CLK_VEN2_CKE5_GALS_VENC				13
+#define CLK_VEN2_CKE5_GALS_JPGENC			14
+#define CLK_VEN2_CKE5_GALS_JPGDEC			15
+#define CLK_VEN2_CKE29_VENC_XPC_CTRL			16
+#define CLK_VEN2_CKE29_VENC_XPC_CTRL_VENC		17
+#define CLK_VEN2_CKE29_VENC_XPC_CTRL_JPGENC		18
+#define CLK_VEN2_CKE29_VENC_XPC_CTRL_JPGDEC		19
+#define CLK_VEN2_CKE6_GALS_SRAM				20
+#define CLK_VEN2_CKE6_GALS_SRAM_VENC			21
+#define CLK_VEN2_RES_FLAT				22
+#define CLK_VEN2_RES_FLAT_VENC				23
+#define CLK_VEN2_RES_FLAT_JPGENC			24
+#define CLK_VEN2_RES_FLAT_JPGDEC			25
+#define CLK_VEN2_NR_CLK					26
+
+/* VENC_GCON_CORE2 */
+#define CLK_VEN_C2_CKE0_LARB				0
+#define CLK_VEN_C2_CKE0_LARB_VENC			1
+#define CLK_VEN_C2_CKE0_LARB_SMI			2
+#define CLK_VEN_C2_CKE1_VENC				3
+#define CLK_VEN_C2_CKE1_VENC_VENC			4
+#define CLK_VEN_C2_CKE1_VENC_SMI			5
+#define CLK_VEN_C2_CKE5_GALS				6
+#define CLK_VEN_C2_CKE5_GALS_VENC			7
+#define CLK_VEN_C2_CKE29_VENC_XPC_CTRL			8
+#define CLK_VEN_C2_CKE29_VENC_XPC_CTRL_VENC		9
+#define CLK_VEN_C2_CKE6_GALS_SRAM			10
+#define CLK_VEN_C2_CKE6_GALS_SRAM_VENC			11
+#define CLK_VEN_C2_RES_FLAT				12
+#define CLK_VEN_C2_RES_FLAT_VENC			13
+#define CLK_VEN_C2_NR_CLK				14
+
+/* MDPSYS_CONFIG */
+#define CLK_MDP_MDP_MUTEX0				0
+#define CLK_MDP_MDP_MUTEX0_MML				1
+#define CLK_MDP_SMI0					2
+#define CLK_MDP_SMI0_MML				3
+#define CLK_MDP_SMI0_SMI				4
+#define CLK_MDP_APB_BUS					5
+#define CLK_MDP_APB_BUS_MML				6
+#define CLK_MDP_MDP_RDMA0				7
+#define CLK_MDP_MDP_RDMA0_MML				8
+#define CLK_MDP_MDP_RDMA1				9
+#define CLK_MDP_MDP_RDMA1_MML				10
+#define CLK_MDP_MDP_RDMA2				11
+#define CLK_MDP_MDP_RDMA2_MML				12
+#define CLK_MDP_MDP_BIRSZ0				13
+#define CLK_MDP_MDP_BIRSZ0_MML				14
+#define CLK_MDP_MDP_HDR0				15
+#define CLK_MDP_MDP_HDR0_MML				16
+#define CLK_MDP_MDP_AAL0				17
+#define CLK_MDP_MDP_AAL0_MML				18
+#define CLK_MDP_MDP_RSZ0				19
+#define CLK_MDP_MDP_RSZ0_MML				20
+#define CLK_MDP_MDP_RSZ2				21
+#define CLK_MDP_MDP_RSZ2_MML				22
+#define CLK_MDP_MDP_TDSHP0				23
+#define CLK_MDP_MDP_TDSHP0_MML				24
+#define CLK_MDP_MDP_COLOR0				25
+#define CLK_MDP_MDP_COLOR0_MML				26
+#define CLK_MDP_MDP_WROT0				27
+#define CLK_MDP_MDP_WROT0_MML				28
+#define CLK_MDP_MDP_WROT1				29
+#define CLK_MDP_MDP_WROT1_MML				30
+#define CLK_MDP_MDP_WROT2				31
+#define CLK_MDP_MDP_WROT2_MML				32
+#define CLK_MDP_MDP_FAKE_ENG0				33
+#define CLK_MDP_MDP_FAKE_ENG0_MML			34
+#define CLK_MDP_APB_DB					35
+#define CLK_MDP_APB_DB_MML				36
+#define CLK_MDP_MDP_DLI_ASYNC0				37
+#define CLK_MDP_MDP_DLI_ASYNC0_MML			38
+#define CLK_MDP_MDP_DLI_ASYNC1				39
+#define CLK_MDP_MDP_DLI_ASYNC1_MML			40
+#define CLK_MDP_MDP_DLO_ASYNC0				41
+#define CLK_MDP_MDP_DLO_ASYNC0_MML			42
+#define CLK_MDP_MDP_DLO_ASYNC1				43
+#define CLK_MDP_MDP_DLO_ASYNC1_MML			44
+#define CLK_MDP_MDP_DLI_ASYNC2				45
+#define CLK_MDP_MDP_DLI_ASYNC2_MML			46
+#define CLK_MDP_MDP_DLO_ASYNC2				47
+#define CLK_MDP_MDP_DLO_ASYNC2_MML			48
+#define CLK_MDP_MDP_DLO_ASYNC3				49
+#define CLK_MDP_MDP_DLO_ASYNC3_MML			50
+#define CLK_MDP_IMG_DL_ASYNC0				51
+#define CLK_MDP_IMG_DL_ASYNC0_MML			52
+#define CLK_MDP_MDP_RROT0				53
+#define CLK_MDP_MDP_RROT0_MML				54
+#define CLK_MDP_MDP_MERGE0				55
+#define CLK_MDP_MDP_MERGE0_MML				56
+#define CLK_MDP_MDP_C3D0				57
+#define CLK_MDP_MDP_C3D0_MML				58
+#define CLK_MDP_MDP_FG0					59
+#define CLK_MDP_MDP_FG0_MML				60
+#define CLK_MDP_MDP_CLA2				61
+#define CLK_MDP_MDP_CLA2_MML				62
+#define CLK_MDP_MDP_DLO_ASYNC4				63
+#define CLK_MDP_MDP_DLO_ASYNC4_MML			64
+#define CLK_MDP_VPP_RSZ0				65
+#define CLK_MDP_VPP_RSZ0_MML				66
+#define CLK_MDP_VPP_RSZ1				67
+#define CLK_MDP_VPP_RSZ1_MML				68
+#define CLK_MDP_MDP_DLO_ASYNC5				69
+#define CLK_MDP_MDP_DLO_ASYNC5_MML			70
+#define CLK_MDP_IMG0					71
+#define CLK_MDP_IMG0_MML				72
+#define CLK_MDP_F26M					73
+#define CLK_MDP_F26M_MML				74
+#define CLK_MDP_IMG_DL_RELAY0				75
+#define CLK_MDP_IMG_DL_RELAY0_MML			76
+#define CLK_MDP_IMG_DL_RELAY1				77
+#define CLK_MDP_IMG_DL_RELAY1_MML			78
+#define CLK_MDP_NR_CLK					79
+
+/* MDPSYS1_CONFIG */
+#define CLK_MDP1_MDP_MUTEX0				0
+#define CLK_MDP1_MDP_MUTEX0_MML				1
+#define CLK_MDP1_SMI0					2
+#define CLK_MDP1_SMI0_SMI				3
+#define CLK_MDP1_APB_BUS				4
+#define CLK_MDP1_APB_BUS_MML				5
+#define CLK_MDP1_MDP_RDMA0				6
+#define CLK_MDP1_MDP_RDMA0_MML				7
+#define CLK_MDP1_MDP_RDMA1				8
+#define CLK_MDP1_MDP_RDMA1_MML				9
+#define CLK_MDP1_MDP_RDMA2				10
+#define CLK_MDP1_MDP_RDMA2_MML				11
+#define CLK_MDP1_MDP_BIRSZ0				12
+#define CLK_MDP1_MDP_BIRSZ0_MML				13
+#define CLK_MDP1_MDP_HDR0				14
+#define CLK_MDP1_MDP_HDR0_MML				15
+#define CLK_MDP1_MDP_AAL0				16
+#define CLK_MDP1_MDP_AAL0_MML				17
+#define CLK_MDP1_MDP_RSZ0				18
+#define CLK_MDP1_MDP_RSZ0_MML				19
+#define CLK_MDP1_MDP_RSZ2				20
+#define CLK_MDP1_MDP_RSZ2_MML				21
+#define CLK_MDP1_MDP_TDSHP0				22
+#define CLK_MDP1_MDP_TDSHP0_MML				23
+#define CLK_MDP1_MDP_COLOR0				24
+#define CLK_MDP1_MDP_COLOR0_MML				25
+#define CLK_MDP1_MDP_WROT0				26
+#define CLK_MDP1_MDP_WROT0_MML				27
+#define CLK_MDP1_MDP_WROT1				28
+#define CLK_MDP1_MDP_WROT1_MML				29
+#define CLK_MDP1_MDP_WROT2				30
+#define CLK_MDP1_MDP_WROT2_MML				31
+#define CLK_MDP1_MDP_FAKE_ENG0				32
+#define CLK_MDP1_MDP_FAKE_ENG0_MML			33
+#define CLK_MDP1_APB_DB					34
+#define CLK_MDP1_APB_DB_MML				35
+#define CLK_MDP1_MDP_DLI_ASYNC0				36
+#define CLK_MDP1_MDP_DLI_ASYNC0_MML			37
+#define CLK_MDP1_MDP_DLI_ASYNC1				38
+#define CLK_MDP1_MDP_DLI_ASYNC1_MML			39
+#define CLK_MDP1_MDP_DLO_ASYNC0				40
+#define CLK_MDP1_MDP_DLO_ASYNC0_MML			41
+#define CLK_MDP1_MDP_DLO_ASYNC1				42
+#define CLK_MDP1_MDP_DLO_ASYNC1_MML			43
+#define CLK_MDP1_MDP_DLI_ASYNC2				44
+#define CLK_MDP1_MDP_DLI_ASYNC2_MML			45
+#define CLK_MDP1_MDP_DLO_ASYNC2				46
+#define CLK_MDP1_MDP_DLO_ASYNC2_MML			47
+#define CLK_MDP1_MDP_DLO_ASYNC3				48
+#define CLK_MDP1_MDP_DLO_ASYNC3_MML			49
+#define CLK_MDP1_IMG_DL_ASYNC0				50
+#define CLK_MDP1_IMG_DL_ASYNC0_MML			51
+#define CLK_MDP1_MDP_RROT0				52
+#define CLK_MDP1_MDP_RROT0_MML				53
+#define CLK_MDP1_MDP_MERGE0				54
+#define CLK_MDP1_MDP_MERGE0_MML				55
+#define CLK_MDP1_MDP_C3D0				56
+#define CLK_MDP1_MDP_C3D0_MML				57
+#define CLK_MDP1_MDP_FG0				58
+#define CLK_MDP1_MDP_FG0_MML				59
+#define CLK_MDP1_MDP_CLA2				60
+#define CLK_MDP1_MDP_CLA2_MML				61
+#define CLK_MDP1_MDP_DLO_ASYNC4				62
+#define CLK_MDP1_MDP_DLO_ASYNC4_MML			63
+#define CLK_MDP1_VPP_RSZ0				64
+#define CLK_MDP1_VPP_RSZ0_MML				65
+#define CLK_MDP1_VPP_RSZ1				66
+#define CLK_MDP1_VPP_RSZ1_MML				67
+#define CLK_MDP1_MDP_DLO_ASYNC5				68
+#define CLK_MDP1_MDP_DLO_ASYNC5_MML			69
+#define CLK_MDP1_IMG0					70
+#define CLK_MDP1_IMG0_MML				71
+#define CLK_MDP1_F26M					72
+#define CLK_MDP1_F26M_MML				73
+#define CLK_MDP1_IMG_DL_RELAY0				74
+#define CLK_MDP1_IMG_DL_RELAY0_MML			75
+#define CLK_MDP1_IMG_DL_RELAY1				76
+#define CLK_MDP1_IMG_DL_RELAY1_MML			77
+#define CLK_MDP1_NR_CLK					78
+
+/* DISP_VDISP_AO_CONFIG */
+#define CLK_MM_V_DISP_VDISP_AO_CONFIG			0
+#define CLK_MM_V_DISP_VDISP_AO_CONFIG_DISP		1
+#define CLK_MM_V_DISP_DPC				2
+#define CLK_MM_V_DISP_DPC_DISP				3
+#define CLK_MM_V_SMI_SUB_SOMM0				4
+#define CLK_MM_V_SMI_SUB_SOMM0_SMI			5
+#define CLK_MM_V_NR_CLK					6
+
+/* MFGPLL_PLL_CTRL */
+#define CLK_MFG_AO_MFGPLL				0
+#define CLK_MFG_AO_NR_CLK				1
+
+/* MFGPLL_SC0_PLL_CTRL */
+#define CLK_MFGSC0_AO_MFGPLL_SC0			0
+#define CLK_MFGSC0_AO_NR_CLK				1
+
+/* MFGPLL_SC1_PLL_CTRL */
+#define CLK_MFGSC1_AO_MFGPLL_SC1			0
+#define CLK_MFGSC1_AO_NR_CLK				1
+
+/* CCIPLL_PLL_CTRL */
+#define CLK_CCIPLL					0
+#define CLK_CCI_NR_CLK					1
+
+/* ARMPLL_LL_PLL_CTRL */
+#define CLK_CPLL_ARMPLL_LL				0
+#define CLK_CPU_LL_NR_CLK				1
+
+/* ARMPLL_BL_PLL_CTRL */
+#define CLK_CPBL_ARMPLL_BL				0
+#define CLK_CPU_BL_NR_CLK				1
+
+/* ARMPLL_B_PLL_CTRL */
+#define CLK_CPB_ARMPLL_B				0
+#define CLK_CPU_B_NR_CLK				1
+
+/* PTPPLL_PLL_CTRL */
+#define CLK_PTPPLL					0
+#define CLK_PTP_NR_CLK					1
+
+#endif /* _DT_BINDINGS_CLK_MT8196_H */
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:05 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:05 +0800
Subject: [PATCH 09/26] clk: mediatek: Add MT8196 topckgen clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-10-guangjie.song@mediatek.com>

Add MT8196 topckgen clock controller which provides muxes and dividers
to handle variety clock selection in other IP blocks.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile              |    3 +-
 drivers/clk/mediatek/clk-mt8196-topckgen.c | 1373 ++++++++++++++++++++
 2 files changed, 1375 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-topckgen.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 247bad396cfb..cd6f42a6fd10 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -150,7 +150,8 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VDOSYS) += clk-mt8195-vdo0.o clk-mt8195-vdo1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
-obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o
+obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o \
+				   clk-mt8196-topckgen.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-topckgen.c b/drivers/clk/mediatek/clk-mt8196-topckgen.c
new file mode 100644
index 000000000000..41c5431561fe
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-topckgen.c
@@ -0,0 +1,1373 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+/* MUX SEL REG */
+#define CLK_CFG_UPDATE		0x0004
+#define CLK_CFG_UPDATE1		0x0008
+#define CLK_CFG_UPDATE2		0x000c
+#define CLK_CFG_0		0x0010
+#define CLK_CFG_0_SET		0x0014
+#define CLK_CFG_0_CLR		0x0018
+#define CLK_CFG_1		0x0020
+#define CLK_CFG_1_SET		0x0024
+#define CLK_CFG_1_CLR		0x0028
+#define CLK_CFG_2		0x0030
+#define CLK_CFG_2_SET		0x0034
+#define CLK_CFG_2_CLR		0x0038
+#define CLK_CFG_3		0x0040
+#define CLK_CFG_3_SET		0x0044
+#define CLK_CFG_3_CLR		0x0048
+#define CLK_CFG_4		0x0050
+#define CLK_CFG_4_SET		0x0054
+#define CLK_CFG_4_CLR		0x0058
+#define CLK_CFG_5		0x0060
+#define CLK_CFG_5_SET		0x0064
+#define CLK_CFG_5_CLR		0x0068
+#define CLK_CFG_6		0x0070
+#define CLK_CFG_6_SET		0x0074
+#define CLK_CFG_6_CLR		0x0078
+#define CLK_CFG_7		0x0080
+#define CLK_CFG_7_SET		0x0084
+#define CLK_CFG_7_CLR		0x0088
+#define CLK_CFG_8		0x0090
+#define CLK_CFG_8_SET		0x0094
+#define CLK_CFG_8_CLR		0x0098
+#define CLK_CFG_9		0x00a0
+#define CLK_CFG_9_SET		0x00a4
+#define CLK_CFG_9_CLR		0x00a8
+#define CLK_CFG_10		0x00b0
+#define CLK_CFG_10_SET		0x00b4
+#define CLK_CFG_10_CLR		0x00b8
+#define CLK_CFG_11		0x00c0
+#define CLK_CFG_11_SET		0x00c4
+#define CLK_CFG_11_CLR		0x00c8
+#define CLK_CFG_12		0x00d0
+#define CLK_CFG_12_SET		0x00d4
+#define CLK_CFG_12_CLR		0x00d8
+#define CLK_CFG_13		0x00e0
+#define CLK_CFG_13_SET		0x00e4
+#define CLK_CFG_13_CLR		0x00e8
+#define CLK_CFG_14		0x00f0
+#define CLK_CFG_14_SET		0x00f4
+#define CLK_CFG_14_CLR		0x00f8
+#define CLK_CFG_15		0x0100
+#define CLK_CFG_15_SET		0x0104
+#define CLK_CFG_15_CLR		0x0108
+#define CLK_CFG_16		0x0110
+#define CLK_CFG_16_SET		0x0114
+#define CLK_CFG_16_CLR		0x0118
+#define CLK_CFG_17		0x0120
+#define CLK_CFG_17_SET		0x0124
+#define CLK_CFG_17_CLR		0x0128
+#define CLK_CFG_18		0x0130
+#define CLK_CFG_18_SET		0x0134
+#define CLK_CFG_18_CLR		0x0138
+#define CLK_CFG_19		0x0140
+#define CLK_CFG_19_SET		0x0144
+#define CLK_CFG_19_CLR		0x0148
+#define CLK_AUDDIV_0		0x020c
+#define CLK_FENC_STATUS_MON_0	0x0270
+#define CLK_FENC_STATUS_MON_1	0x0274
+#define CLK_FENC_STATUS_MON_2	0x0278
+
+/* MUX SHIFT */
+#define TOP_MUX_AXI_SHIFT			0
+#define TOP_MUX_MEM_SUB_SHIFT			1
+#define TOP_MUX_IO_NOC_SHIFT			2
+#define TOP_MUX_PERI_AXI_SHIFT			3
+#define TOP_MUX_UFS_PEXTP0_AXI_SHIFT		4
+#define TOP_MUX_PEXTP1_USB_AXI_SHIFT		5
+#define TOP_MUX_PERI_FMEM_SUB_SHIFT		6
+#define TOP_MUX_UFS_PEXPT0_MEM_SUB_SHIFT	7
+#define TOP_MUX_PEXTP1_USB_MEM_SUB_SHIFT	8
+#define TOP_MUX_PERI_NOC_SHIFT			9
+#define TOP_MUX_EMI_N_SHIFT			10
+#define TOP_MUX_EMI_S_SHIFT			11
+#define TOP_MUX_AP2CONN_HOST_SHIFT		14
+#define TOP_MUX_ATB_SHIFT			15
+#define TOP_MUX_CIRQ_SHIFT			16
+#define TOP_MUX_PBUS_156M_SHIFT			17
+#define TOP_MUX_EFUSE_SHIFT			20
+#define TOP_MUX_MCU_L3GIC_SHIFT			21
+#define TOP_MUX_MCU_INFRA_SHIFT			22
+#define TOP_MUX_DSP_SHIFT			23
+#define TOP_MUX_MFG_REF_SHIFT			24
+#define TOP_MUX_MFG_EB_SHIFT			26
+#define TOP_MUX_UART_SHIFT			27
+#define TOP_MUX_SPI0_BCLK_SHIFT			28
+#define TOP_MUX_SPI1_BCLK_SHIFT			29
+#define TOP_MUX_SPI2_BCLK_SHIFT			30
+#define TOP_MUX_SPI3_BCLK_SHIFT			0
+#define TOP_MUX_SPI4_BCLK_SHIFT			1
+#define TOP_MUX_SPI5_BCLK_SHIFT			2
+#define TOP_MUX_SPI6_BCLK_SHIFT			3
+#define TOP_MUX_SPI7_BCLK_SHIFT			4
+#define TOP_MUX_MSDC30_1_SHIFT			7
+#define TOP_MUX_MSDC30_2_SHIFT			8
+#define TOP_MUX_DISP_PWM_SHIFT			9
+#define TOP_MUX_USB_TOP_1P_SHIFT		10
+#define TOP_MUX_SSUSB_XHCI_1P_SHIFT		11
+#define TOP_MUX_SSUSB_FMCNT_P1_SHIFT		12
+#define TOP_MUX_I2C_PERI_SHIFT			13
+#define TOP_MUX_I2C_EAST_SHIFT			14
+#define TOP_MUX_I2C_WEST_SHIFT			15
+#define TOP_MUX_I2C_NORTH_SHIFT			16
+#define TOP_MUX_AES_UFSFDE_SHIFT		17
+#define TOP_MUX_UFS_SHIFT			18
+#define TOP_MUX_AUD_1_SHIFT			21
+#define TOP_MUX_AUD_2_SHIFT			22
+#define TOP_MUX_ADSP_SHIFT			23
+#define TOP_MUX_ADSP_UARTHUB_BCLK_SHIFT		24
+#define TOP_MUX_DPMAIF_MAIN_SHIFT		25
+#define TOP_MUX_PWM_SHIFT			26
+#define TOP_MUX_MCUPM_SHIFT			27
+#define TOP_MUX_SFLASH_SHIFT			28
+#define TOP_MUX_IPSEAST_SHIFT			29
+#define TOP_MUX_TL_SHIFT			0
+#define TOP_MUX_TL_P1_SHIFT			1
+#define TOP_MUX_TL_P2_SHIFT			2
+#define TOP_MUX_EMI_INTERFACE_546_SHIFT		3
+#define TOP_MUX_SDF_SHIFT			4
+#define TOP_MUX_UARTHUB_BCLK_SHIFT		5
+#define TOP_MUX_DPSW_CMP_26M_SHIFT		6
+#define TOP_MUX_SMAPCK_SHIFT			7
+#define TOP_MUX_SSR_PKA_SHIFT			8
+#define TOP_MUX_SSR_DMA_SHIFT			9
+#define TOP_MUX_SSR_KDF_SHIFT			10
+#define TOP_MUX_SSR_RNG_SHIFT			11
+#define TOP_MUX_SPU0_SHIFT			12
+#define TOP_MUX_SPU1_SHIFT			13
+#define TOP_MUX_DXCC_SHIFT			14
+
+/* CKSTA REG */
+#define CKSTA_REG	0x01c8
+#define CKSTA_REG1	0x01cc
+#define CKSTA_REG2	0x01d0
+
+/* DIVIDER REG */
+#define CLK_AUDDIV_2	0x0214
+#define CLK_AUDDIV_3	0x0220
+#define CLK_AUDDIV_4	0x0224
+#define CLK_AUDDIV_5	0x0228
+
+/* HW Voter REG */
+#define VOTE_CG_0_SET	0x0000
+#define VOTE_CG_0_CLR	0x0004
+#define VOTE_CG_0_DONE	0x2c00
+#define VOTE_CG_1_SET	0x0008
+#define VOTE_CG_1_CLR	0x000c
+#define VOTE_CG_1_DONE	0x2c04
+#define VOTE_CG_2_SET	0x0010
+#define VOTE_CG_2_CLR	0x0014
+#define VOTE_CG_2_DONE	0x2c08
+#define VOTE_CG_3_SET	0x0018
+#define VOTE_CG_3_CLR	0x001c
+#define VOTE_CG_3_DONE	0x2c0c
+#define VOTE_CG_4_SET	0x0020
+#define VOTE_CG_4_CLR	0x0024
+#define VOTE_CG_4_DONE	0x2c10
+#define VOTE_CG_5_SET	0x0028
+#define VOTE_CG_5_CLR	0x002c
+#define VOTE_CG_5_DONE	0x2c14
+#define VOTE_CG_6_SET	0x0030
+#define VOTE_CG_6_CLR	0x0034
+#define VOTE_CG_6_DONE	0x2c18
+#define VOTE_CG_7_SET	0x0038
+#define VOTE_CG_7_CLR	0x003c
+#define VOTE_CG_7_DONE	0x2c1c
+#define VOTE_CG_8_SET	0x0040
+#define VOTE_CG_8_CLR	0x0044
+#define VOTE_CG_8_DONE	0x2c20
+
+static DEFINE_SPINLOCK(mt8196_clk_ck_lock);
+
+static const struct mtk_fixed_factor ck_divs[] = {
+	FACTOR(CLK_CK_MAINPLL_D3, "ck_mainpll_d3", "mainpll", 1, 3),
+	FACTOR(CLK_CK_MAINPLL_D4, "ck_mainpll_d4", "mainpll", 1, 4),
+	FACTOR(CLK_CK_MAINPLL_D4_D2, "ck_mainpll_d4_d2", "mainpll", 1, 8),
+	FACTOR(CLK_CK_MAINPLL_D4_D4, "ck_mainpll_d4_d4", "mainpll", 1, 16),
+	FACTOR(CLK_CK_MAINPLL_D4_D8, "ck_mainpll_d4_d8", "mainpll", 1, 32),
+	FACTOR(CLK_CK_MAINPLL_D5, "ck_mainpll_d5", "mainpll", 1, 5),
+	FACTOR(CLK_CK_MAINPLL_D5_D2, "ck_mainpll_d5_d2", "mainpll", 1, 10),
+	FACTOR(CLK_CK_MAINPLL_D5_D4, "ck_mainpll_d5_d4", "mainpll", 1, 20),
+	FACTOR(CLK_CK_MAINPLL_D5_D8, "ck_mainpll_d5_d8", "mainpll", 1, 40),
+	FACTOR(CLK_CK_MAINPLL_D6, "ck_mainpll_d6", "mainpll", 1, 6),
+	FACTOR(CLK_CK_MAINPLL_D6_D2, "ck_mainpll_d6_d2", "mainpll", 1, 12),
+	FACTOR(CLK_CK_MAINPLL_D7, "ck_mainpll_d7", "mainpll", 1, 7),
+	FACTOR(CLK_CK_MAINPLL_D7_D2, "ck_mainpll_d7_d2", "mainpll", 1, 14),
+	FACTOR(CLK_CK_MAINPLL_D7_D4, "ck_mainpll_d7_d4", "mainpll", 1, 28),
+	FACTOR(CLK_CK_MAINPLL_D7_D8, "ck_mainpll_d7_d8", "mainpll", 1, 56),
+	FACTOR(CLK_CK_MAINPLL_D9, "ck_mainpll_d9", "mainpll", 1, 9),
+	FACTOR(CLK_CK_UNIVPLL_D4, "ck_univpll_d4", "univpll", 1, 4),
+	FACTOR(CLK_CK_UNIVPLL_D4_D2, "ck_univpll_d4_d2", "univpll", 1, 8),
+	FACTOR(CLK_CK_UNIVPLL_D4_D4, "ck_univpll_d4_d4", "univpll", 1, 16),
+	FACTOR(CLK_CK_UNIVPLL_D4_D8, "ck_univpll_d4_d8", "univpll", 1, 32),
+	FACTOR(CLK_CK_UNIVPLL_D5, "ck_univpll_d5", "univpll", 1, 5),
+	FACTOR(CLK_CK_UNIVPLL_D5_D2, "ck_univpll_d5_d2", "univpll", 1, 10),
+	FACTOR(CLK_CK_UNIVPLL_D5_D4, "ck_univpll_d5_d4", "univpll", 1, 20),
+	FACTOR(CLK_CK_UNIVPLL_D6, "ck_univpll_d6", "univpll", 1, 6),
+	FACTOR(CLK_CK_UNIVPLL_D6_D2, "ck_univpll_d6_d2", "univpll", 1, 12),
+	FACTOR(CLK_CK_UNIVPLL_D6_D4, "ck_univpll_d6_d4", "univpll", 1, 24),
+	FACTOR(CLK_CK_UNIVPLL_D6_D8, "ck_univpll_d6_d8", "univpll", 1, 48),
+	FACTOR(CLK_CK_UNIVPLL_D6_D16, "ck_univpll_d6_d16", "univpll", 1, 96),
+	FACTOR(CLK_CK_UNIVPLL_192M, "ck_univpll_192m", "univpll", 1, 13),
+	FACTOR(CLK_CK_UNIVPLL_192M_D4, "ck_univpll_192m_d4", "univpll", 1, 52),
+	FACTOR(CLK_CK_UNIVPLL_192M_D8, "ck_univpll_192m_d8", "univpll", 1, 104),
+	FACTOR(CLK_CK_UNIVPLL_192M_D16, "ck_univpll_192m_d16", "univpll", 1, 208),
+	FACTOR(CLK_CK_UNIVPLL_192M_D32, "ck_univpll_192m_d32", "univpll", 1, 416),
+	FACTOR(CLK_CK_UNIVPLL_192M_D10, "ck_univpll_192m_d10", "univpll", 1, 130),
+	FACTOR(CLK_CK_APLL1, "ck_apll1_ck", "vlp_apll1", 1, 1),
+	FACTOR(CLK_CK_APLL1_D4, "ck_apll1_d4", "vlp_apll1", 1, 4),
+	FACTOR(CLK_CK_APLL1_D8, "ck_apll1_d8", "vlp_apll1", 1, 8),
+	FACTOR(CLK_CK_APLL2, "ck_apll2_ck", "vlp_apll2", 1, 1),
+	FACTOR(CLK_CK_APLL2_D4, "ck_apll2_d4", "vlp_apll2", 1, 4),
+	FACTOR(CLK_CK_APLL2_D8, "ck_apll2_d8", "vlp_apll2", 1, 8),
+	FACTOR(CLK_CK_ADSPPLL, "ck_adsppll_ck", "adsppll", 1, 1),
+	FACTOR(CLK_CK_EMIPLL1, "ck_emipll1_ck", "emipll", 1, 1),
+	FACTOR(CLK_CK_TVDPLL1_D2, "ck_tvdpll1_d2", "tvdpll1", 1, 2),
+	FACTOR(CLK_CK_MSDCPLL_D2, "ck_msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_CK_CLKRTC, "ck_clkrtc", "clk32k", 1, 1),
+	FACTOR(CLK_CK_TCK_26M_MX9, "ck_tck_26m_mx9_ck", "clk26m", 1, 1),
+	FACTOR(CLK_CK_F26M, "ck_f26m_ck", "clk26m", 1, 1),
+	FACTOR(CLK_CK_F26M_CK_D2, "ck_f26m_d2", "clk13m", 1, 1),
+	FACTOR(CLK_CK_OSC, "ck_osc", "ulposc", 1, 1),
+	FACTOR(CLK_CK_OSC_D2, "ck_osc_d2", "ulposc", 1, 2),
+	FACTOR(CLK_CK_OSC_D3, "ck_osc_d3", "ulposc", 1, 3),
+	FACTOR(CLK_CK_OSC_D4, "ck_osc_d4", "ulposc", 1, 4),
+	FACTOR(CLK_CK_OSC_D5, "ck_osc_d5", "ulposc", 1, 5),
+	FACTOR(CLK_CK_OSC_D7, "ck_osc_d7", "ulposc", 1, 7),
+	FACTOR(CLK_CK_OSC_D8, "ck_osc_d8", "ulposc", 1, 8),
+	FACTOR(CLK_CK_OSC_D10, "ck_osc_d10", "ulposc", 1, 10),
+	FACTOR(CLK_CK_OSC_D14, "ck_osc_d14", "ulposc", 1, 14),
+	FACTOR(CLK_CK_OSC_D20, "ck_osc_d20", "ulposc", 1, 20),
+	FACTOR(CLK_CK_OSC_D32, "ck_osc_d32", "ulposc", 1, 32),
+	FACTOR(CLK_CK_OSC_D40, "ck_osc_d40", "ulposc", 1, 40),
+	FACTOR(CLK_CK_OSC3, "ck_osc3", "ulposc3", 1, 1),
+	FACTOR(CLK_CK_P_AXI, "ck_p_axi_ck", "ck_p_axi_sel", 1, 1),
+	FACTOR(CLK_CK_PEXTP0_AXI, "ck_pextp0_axi_ck", "ck_pextp0_axi_sel", 1, 1),
+	FACTOR(CLK_CK_PEXTP1_USB_AXI, "ck_pextp1_usb_axi_ck", "ck_pextp1_usb_axi_sel", 1, 1),
+	FACTOR(CLK_CK_PEXPT0_MEM_SUB, "ck_pexpt0_mem_sub_ck", "ck_pexpt0_mem_sub_sel", 1, 1),
+	FACTOR(CLK_CK_PEXTP1_USB_MEM_SUB, "ck_pextp1_usb_mem_sub_ck", "ck_pextp1_usb_mem_sub_sel", 1, 1),
+	FACTOR(CLK_CK_UART, "ck_uart_ck", "ck_uart_sel", 1, 1),
+	FACTOR(CLK_CK_SPI0_BCLK, "ck_spi0_b_ck", "ck_spi0_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI1_BCLK, "ck_spi1_b_ck", "ck_spi1_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI2_BCLK, "ck_spi2_b_ck", "ck_spi2_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI3_BCLK, "ck_spi3_b_ck", "ck_spi3_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI4_BCLK, "ck_spi4_b_ck", "ck_spi4_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI5_BCLK, "ck_spi5_b_ck", "ck_spi5_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI6_BCLK, "ck_spi6_b_ck", "ck_spi6_b_sel", 1, 1),
+	FACTOR(CLK_CK_SPI7_BCLK, "ck_spi7_b_ck", "ck_spi7_b_sel", 1, 1),
+	FACTOR(CLK_CK_MSDC30_1, "ck_msdc30_1_ck", "ck_msdc30_1_sel", 1, 1),
+	FACTOR(CLK_CK_MSDC30_2, "ck_msdc30_2_ck", "ck_msdc30_2_sel", 1, 1),
+	FACTOR(CLK_CK_I2C_PERI, "ck_i2c_p_ck", "ck_i2c_p_sel", 1, 1),
+	FACTOR(CLK_CK_I2C_EAST, "ck_i2c_east_ck", "ck_i2c_east_sel", 1, 1),
+	FACTOR(CLK_CK_I2C_WEST, "ck_i2c_west_ck", "ck_i2c_west_sel", 1, 1),
+	FACTOR(CLK_CK_I2C_NORTH, "ck_i2c_north_ck", "ck_i2c_north_sel", 1, 1),
+	FACTOR(CLK_CK_AES_UFSFDE, "ck_aes_ufsfde_ck", "ck_aes_ufsfde_sel", 1, 1),
+	FACTOR(CLK_CK_UFS, "ck_ck", "ck_sel", 1, 1),
+	FACTOR(CLK_CK_AUD_1, "ck_aud_1_ck", "ck_aud_1_sel", 1, 1),
+	FACTOR(CLK_CK_AUD_2, "ck_aud_2_ck", "ck_aud_2_sel", 1, 1),
+	FACTOR(CLK_CK_DPMAIF_MAIN, "ck_dpmaif_main_ck", "ck_dpmaif_main_sel", 1, 1),
+	FACTOR(CLK_CK_PWM, "ck_pwm_ck", "ck_pwm_sel", 1, 1),
+	FACTOR(CLK_CK_TL, "ck_tl_ck", "ck_tl_sel", 1, 1),
+	FACTOR(CLK_CK_TL_P1, "ck_tl_p1_ck", "ck_tl_p1_sel", 1, 1),
+	FACTOR(CLK_CK_TL_P2, "ck_tl_p2_ck", "ck_tl_p2_sel", 1, 1),
+	FACTOR(CLK_CK_SSR_RNG, "ck_ssr_rng_ck", "ck_ssr_rng_sel", 1, 1),
+	FACTOR(CLK_CK_SFLASH, "ck_sflash_ck", "ck_sflash_sel", 1, 1),
+};
+
+static const char * const ck_axi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_osc_d8",
+	"ck_osc_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_mem_sub_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_osc_d4",
+	"ck_univpll_d4_d4",
+	"ck_osc_d3",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5",
+	"ck_mainpll_d4",
+	"ck_mainpll_d3"
+};
+
+static const char * const ck_io_noc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_osc_d8",
+	"ck_osc_d4",
+	"ck_mainpll_d6_d2",
+	"ck_mainpll_d9"
+};
+
+static const char * const ck_p_axi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d8",
+	"ck_mainpll_d5_d8",
+	"ck_osc_d8",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_pextp0_axi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d8",
+	"ck_mainpll_d5_d8",
+	"ck_osc_d8",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_pextp1_usb_axi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d8",
+	"ck_mainpll_d5_d8",
+	"ck_osc_d8",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_p_fmem_sub_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_osc_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5",
+	"ck_mainpll_d4"
+};
+
+static const char * const ck_pexpt0_mem_sub_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_osc_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5",
+	"ck_mainpll_d4"
+};
+
+static const char * const ck_pextp1_usb_mem_sub_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_osc_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5",
+	"ck_mainpll_d4"
+};
+
+static const char * const ck_p_noc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_osc_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5",
+	"ck_mainpll_d4",
+	"ck_mainpll_d3"
+};
+
+static const char * const ck_emi_n_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_emipll1_ck"
+};
+
+static const char * const ck_emi_s_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d5_d8",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_emipll1_ck"
+};
+
+static const char * const ck_ap2conn_host_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4"
+};
+
+static const char * const ck_atb_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6"
+};
+
+static const char * const ck_cirq_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d7_d4"
+};
+
+static const char * const ck_pbus_156m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d2",
+	"ck_osc_d2",
+	"ck_mainpll_d7"
+};
+
+static const char * const ck_efuse_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const ck_mcl3gic_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d8",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_mcinfra_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d9",
+	"ck_mainpll_d6"
+};
+
+static const char * const ck_dsp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck_univpll_d6_d2",
+	"ck_osc_d2",
+	"ck_univpll_d5",
+	"ck_osc"
+};
+
+static const char * const ck_mfg_ref_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const ck_mfg_eb_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d6_d2",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const ck_uart_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d8",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi0_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi1_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi2_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi3_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi4_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi5_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi6_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_spi7_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d4_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_192m",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_msdc30_1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_d6_d2",
+	"ck_msdcpll_d2"
+};
+
+static const char * const ck_msdc30_2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_d6_d2",
+	"ck_msdcpll_d2"
+};
+
+static const char * const ck_disp_pwm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d32",
+	"ck_osc_d8",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d5_d4",
+	"ck_osc_d4",
+	"ck_mainpll_d4_d4"
+};
+
+static const char * const ck_usb_1p_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d5_d4"
+};
+
+static const char * const ck_usb_xhci_1p_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d5_d4"
+};
+
+static const char * const ck_usb_fmcnt_p1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d4"
+};
+
+static const char * const ck_i2c_p_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d5_d2"
+};
+
+static const char * const ck_i2c_east_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d5_d2"
+};
+
+static const char * const ck_i2c_west_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d5_d2"
+};
+
+static const char * const ck_i2c_north_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8",
+	"ck_univpll_d5_d4",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d5_d2"
+};
+
+static const char * const ck_aes_ufsfde_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d6_d2",
+	"ck_mainpll_d4_d2",
+	"ck_univpll_d6",
+	"ck_mainpll_d4"
+};
+
+static const char * const ck_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_univpll_d6_d2",
+	"ck_mainpll_d4_d2",
+	"ck_univpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5"
+};
+
+static const char * const ck_aud_1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_apll1_ck"
+};
+
+static const char * const ck_aud_2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_apll2_ck"
+};
+
+static const char * const ck_adsp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_adsppll_ck"
+};
+
+static const char * const ck_adsp_uarthub_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_dpmaif_main_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d4_d4",
+	"ck_univpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_univpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_univpll_d6",
+	"ck_mainpll_d5",
+	"ck_univpll_d5"
+};
+
+static const char * const ck_pwm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4",
+	"ck_univpll_d4_d8"
+};
+
+static const char * const ck_mcupm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d6_d2",
+	"ck_univpll_d6_d2",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const ck_ipseast_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5",
+	"ck_mainpll_d4",
+	"ck_mainpll_d3"
+};
+
+static const char * const ck_tl_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const ck_tl_p1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const ck_tl_p2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const ck_md_emi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4"
+};
+
+static const char * const ck_sdf_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck_mainpll_d4",
+	"ck_univpll_d4"
+};
+
+static const char * const ck_uarthub_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_d6_d4",
+	"ck_univpll_d6_d2"
+};
+
+static const char * const ck_dpsw_cmp_26m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const ck_smapck_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8"
+};
+
+static const char * const ck_ssr_pka_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const char * const ck_ssr_dma_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const char * const ck_ssr_kdf_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7"
+};
+
+static const char * const ck_ssr_rng_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2"
+};
+
+static const char * const ck_spu0_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const char * const ck_spu1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const char * const ck_dxcc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d4_d8",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2"
+};
+
+static const char * const ck_apll_i2sin0_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sin1_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sin2_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sin3_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sin4_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sin6_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout0_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout1_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout2_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout3_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout4_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_i2sout6_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_fmi2s_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_apll_tdmout_m_parents[] = {
+	"ck_aud_1_sel",
+	"ck_aud_2_sel"
+};
+
+static const char * const ck_sflash_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d8",
+	"ck_univpll_d6_d8"
+};
+
+static const struct mtk_mux ck_muxes[] = {
+	/* CLK_CFG_0 */
+	MUX_CLR_SET_UPD(CLK_CK_AXI_SEL, "ck_axi_sel",
+		ck_axi_parents, CLK_CFG_0, CLK_CFG_0_SET,
+		CLK_CFG_0_CLR, 0, 3,
+		CLK_CFG_UPDATE, TOP_MUX_AXI_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_MEM_SUB_SEL, "ck_mem_sub_sel",
+		ck_mem_sub_parents, CLK_CFG_0, CLK_CFG_0_SET,
+		CLK_CFG_0_CLR, 8, 4,
+		CLK_CFG_UPDATE, TOP_MUX_MEM_SUB_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_IO_NOC_SEL, "ck_io_noc_sel",
+		ck_io_noc_parents, CLK_CFG_0, CLK_CFG_0_SET,
+		CLK_CFG_0_CLR, 16, 3,
+		CLK_CFG_UPDATE, TOP_MUX_IO_NOC_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_P_AXI_SEL, "ck_p_axi_sel",
+		ck_p_axi_parents, CLK_CFG_0, CLK_CFG_0_SET,
+		CLK_CFG_0_CLR, 24, 3,
+		CLK_CFG_UPDATE, TOP_MUX_PERI_AXI_SHIFT),
+	/* CLK_CFG_1 */
+	MUX_CLR_SET_UPD(CLK_CK_PEXTP0_AXI_SEL, "ck_pextp0_axi_sel",
+		ck_pextp0_axi_parents, CLK_CFG_1, CLK_CFG_1_SET,
+		CLK_CFG_1_CLR, 0, 3,
+		CLK_CFG_UPDATE, TOP_MUX_UFS_PEXTP0_AXI_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_PEXTP1_USB_AXI_SEL, "ck_pextp1_usb_axi_sel",
+		ck_pextp1_usb_axi_parents, CLK_CFG_1, CLK_CFG_1_SET,
+		CLK_CFG_1_CLR, 8, 3,
+		CLK_CFG_UPDATE, TOP_MUX_PEXTP1_USB_AXI_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_P_FMEM_SUB_SEL, "ck_p_fmem_sub_sel",
+		ck_p_fmem_sub_parents, CLK_CFG_1, CLK_CFG_1_SET,
+		CLK_CFG_1_CLR, 16, 4,
+		CLK_CFG_UPDATE, TOP_MUX_PERI_FMEM_SUB_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_PEXPT0_MEM_SUB_SEL, "ck_pexpt0_mem_sub_sel",
+		ck_pexpt0_mem_sub_parents, CLK_CFG_1, CLK_CFG_1_SET,
+		CLK_CFG_1_CLR, 24, 4,
+		CLK_CFG_UPDATE, TOP_MUX_UFS_PEXPT0_MEM_SUB_SHIFT),
+	/* CLK_CFG_2 */
+	MUX_CLR_SET_UPD(CLK_CK_PEXTP1_USB_MEM_SUB_SEL, "ck_pextp1_usb_mem_sub_sel",
+		ck_pextp1_usb_mem_sub_parents, CLK_CFG_2, CLK_CFG_2_SET,
+		CLK_CFG_2_CLR, 0, 4,
+		CLK_CFG_UPDATE, TOP_MUX_PEXTP1_USB_MEM_SUB_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_P_NOC_SEL, "ck_p_noc_sel",
+		ck_p_noc_parents, CLK_CFG_2, CLK_CFG_2_SET,
+		CLK_CFG_2_CLR, 8, 4,
+		CLK_CFG_UPDATE, TOP_MUX_PERI_NOC_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_EMI_N_SEL, "ck_emi_n_sel",
+		ck_emi_n_parents, CLK_CFG_2, CLK_CFG_2_SET,
+		CLK_CFG_2_CLR, 16, 3,
+		CLK_CFG_UPDATE, TOP_MUX_EMI_N_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_EMI_S_SEL, "ck_emi_s_sel",
+		ck_emi_s_parents, CLK_CFG_2, CLK_CFG_2_SET,
+		CLK_CFG_2_CLR, 24, 3,
+		CLK_CFG_UPDATE, TOP_MUX_EMI_S_SHIFT),
+	/* CLK_CFG_3 */
+	MUX_CLR_SET_UPD(CLK_CK_AP2CONN_HOST_SEL, "ck_ap2conn_host_sel",
+		ck_ap2conn_host_parents, CLK_CFG_3, CLK_CFG_3_SET,
+		CLK_CFG_3_CLR, 16, 1,
+		CLK_CFG_UPDATE, TOP_MUX_AP2CONN_HOST_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_ATB_SEL, "ck_atb_sel",
+		ck_atb_parents, CLK_CFG_3, CLK_CFG_3_SET,
+		CLK_CFG_3_CLR, 24, 2,
+		CLK_CFG_UPDATE, TOP_MUX_ATB_SHIFT),
+	/* CLK_CFG_4 */
+	MUX_CLR_SET_UPD(CLK_CK_CIRQ_SEL, "ck_cirq_sel",
+		ck_cirq_parents, CLK_CFG_4, CLK_CFG_4_SET,
+		CLK_CFG_4_CLR, 0, 2,
+		CLK_CFG_UPDATE, TOP_MUX_CIRQ_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_PBUS_156M_SEL, "ck_pbus_156m_sel",
+		ck_pbus_156m_parents, CLK_CFG_4, CLK_CFG_4_SET,
+		CLK_CFG_4_CLR, 8, 2,
+		CLK_CFG_UPDATE, TOP_MUX_PBUS_156M_SHIFT),
+	/* CLK_CFG_5 */
+	MUX_CLR_SET_UPD(CLK_CK_EFUSE_SEL, "ck_efuse_sel",
+		ck_efuse_parents, CLK_CFG_5, CLK_CFG_5_SET,
+		CLK_CFG_5_CLR, 0, 1,
+		CLK_CFG_UPDATE, TOP_MUX_EFUSE_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_MCL3GIC_SEL, "ck_mcl3gic_sel",
+		ck_mcl3gic_parents, CLK_CFG_5, CLK_CFG_5_SET,
+		CLK_CFG_5_CLR, 8, 2,
+		CLK_CFG_UPDATE, TOP_MUX_MCU_L3GIC_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_MCINFRA_SEL, "ck_mcinfra_sel",
+		ck_mcinfra_parents, CLK_CFG_5, CLK_CFG_5_SET,
+		CLK_CFG_5_CLR, 16, 3,
+		CLK_CFG_UPDATE, TOP_MUX_MCU_INFRA_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_DSP_SEL, "ck_dsp_sel",
+		ck_dsp_parents, CLK_CFG_5, CLK_CFG_5_SET,
+		CLK_CFG_5_CLR, 24, 3,
+		CLK_CFG_UPDATE, TOP_MUX_DSP_SHIFT),
+	/* CLK_CFG_6 */
+	MUX_GATE_FENC_CLR_SET_UPD_FLAGS(CLK_CK_MFG_REF_SEL, "ck_mfg_ref_sel", ck_mfg_ref_parents,
+		CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR,
+		0, 1, 7, CLK_CFG_UPDATE, TOP_MUX_MFG_REF_SHIFT,
+		CLK_FENC_STATUS_MON_0, 7, CLK_IGNORE_UNUSED),
+	MUX_CLR_SET_UPD(CLK_CK_MFG_EB_SEL, "ck_mfg_eb_sel",
+		ck_mfg_eb_parents, CLK_CFG_6, CLK_CFG_6_SET,
+		CLK_CFG_6_CLR, 16, 2,
+		CLK_CFG_UPDATE, TOP_MUX_MFG_EB_SHIFT),
+	MUX_MULT_VOTE_FENC(CLK_CK_UART_SEL, "ck_uart_sel", ck_uart_parents,
+		CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, "vote-regmap",
+		VOTE_CG_3_DONE, VOTE_CG_3_SET, VOTE_CG_3_CLR,
+		24, 2, 31, CLK_CFG_UPDATE, TOP_MUX_UART_SHIFT,
+		CLK_FENC_STATUS_MON_0, 4),
+	/* CLK_CFG_7 */
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI0_BCLK_SEL, "ck_spi0_b_sel", ck_spi0_b_parents,
+		CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, "vote-regmap",
+		VOTE_CG_4_DONE, VOTE_CG_4_SET, VOTE_CG_4_CLR,
+		0, 3, 7, CLK_CFG_UPDATE, TOP_MUX_SPI0_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_0, 3),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI1_BCLK_SEL, "ck_spi1_b_sel", ck_spi1_b_parents,
+		CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, "vote-regmap",
+		VOTE_CG_4_DONE, VOTE_CG_4_SET, VOTE_CG_4_CLR,
+		8, 3, 15, CLK_CFG_UPDATE, TOP_MUX_SPI1_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_0, 2),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI2_BCLK_SEL, "ck_spi2_b_sel", ck_spi2_b_parents,
+		CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, "vote-regmap",
+		VOTE_CG_4_DONE, VOTE_CG_4_SET, VOTE_CG_4_CLR,
+		16, 3, 23, CLK_CFG_UPDATE, TOP_MUX_SPI2_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_0, 1),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI3_BCLK_SEL, "ck_spi3_b_sel", ck_spi3_b_parents,
+		CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, "vote-regmap",
+		VOTE_CG_4_DONE, VOTE_CG_4_SET, VOTE_CG_4_CLR,
+		24, 3, 31, CLK_CFG_UPDATE1, TOP_MUX_SPI3_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_0, 0),
+	/* CLK_CFG_8 */
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI4_BCLK_SEL, "ck_spi4_b_sel", ck_spi4_b_parents,
+		CLK_CFG_8, CLK_CFG_8_SET, CLK_CFG_8_CLR, "vote-regmap",
+		VOTE_CG_5_DONE, VOTE_CG_5_SET, VOTE_CG_5_CLR,
+		0, 3, 7, CLK_CFG_UPDATE1, TOP_MUX_SPI4_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_1, 31),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI5_BCLK_SEL, "ck_spi5_b_sel", ck_spi5_b_parents,
+		CLK_CFG_8, CLK_CFG_8_SET, CLK_CFG_8_CLR, "vote-regmap",
+		VOTE_CG_5_DONE, VOTE_CG_5_SET, VOTE_CG_5_CLR,
+		8, 3, 15, CLK_CFG_UPDATE1, TOP_MUX_SPI5_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_1, 30),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI6_BCLK_SEL, "ck_spi6_b_sel", ck_spi6_b_parents,
+		CLK_CFG_8, CLK_CFG_8_SET, CLK_CFG_8_CLR, "vote-regmap",
+		VOTE_CG_5_DONE, VOTE_CG_5_SET, VOTE_CG_5_CLR,
+		16, 3, 23, CLK_CFG_UPDATE1, TOP_MUX_SPI6_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_1, 29),
+	MUX_MULT_VOTE_FENC(CLK_CK_SPI7_BCLK_SEL, "ck_spi7_b_sel", ck_spi7_b_parents,
+		CLK_CFG_8, CLK_CFG_8_SET, CLK_CFG_8_CLR, "vote-regmap",
+		VOTE_CG_5_DONE, VOTE_CG_5_SET, VOTE_CG_5_CLR,
+		24, 3, 31, CLK_CFG_UPDATE1, TOP_MUX_SPI7_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_1, 28),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_MSDC30_1_SEL, "ck_msdc30_1_sel", ck_msdc30_1_parents,
+		CLK_CFG_9, CLK_CFG_9_SET, CLK_CFG_9_CLR,
+		16, 3, 23, CLK_CFG_UPDATE1, TOP_MUX_MSDC30_1_SHIFT,
+		CLK_FENC_STATUS_MON_1, 25),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_MSDC30_2_SEL, "ck_msdc30_2_sel", ck_msdc30_2_parents,
+		CLK_CFG_9, CLK_CFG_9_SET, CLK_CFG_9_CLR,
+		24, 3, 31, CLK_CFG_UPDATE1, TOP_MUX_MSDC30_2_SHIFT,
+		CLK_FENC_STATUS_MON_1, 24),
+	/* CLK_CFG_10 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_DISP_PWM_SEL, "ck_disp_pwm_sel", ck_disp_pwm_parents,
+		CLK_CFG_10, CLK_CFG_10_SET, CLK_CFG_10_CLR,
+		0, 3, 7, CLK_CFG_UPDATE1, TOP_MUX_DISP_PWM_SHIFT,
+		CLK_FENC_STATUS_MON_1, 23),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_USB_TOP_1P_SEL, "ck_usb_1p_sel", ck_usb_1p_parents,
+		CLK_CFG_10, CLK_CFG_10_SET, CLK_CFG_10_CLR,
+		8, 1, 15, CLK_CFG_UPDATE1, TOP_MUX_USB_TOP_1P_SHIFT,
+		CLK_FENC_STATUS_MON_1, 22),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_USB_XHCI_1P_SEL, "ck_usb_xhci_1p_sel", ck_usb_xhci_1p_parents,
+		CLK_CFG_10, CLK_CFG_10_SET, CLK_CFG_10_CLR,
+		16, 1, 23, CLK_CFG_UPDATE1, TOP_MUX_SSUSB_XHCI_1P_SHIFT,
+		CLK_FENC_STATUS_MON_1, 21),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_USB_FMCNT_P1_SEL, "ck_usb_fmcnt_p1_sel", ck_usb_fmcnt_p1_parents,
+		CLK_CFG_10, CLK_CFG_10_SET, CLK_CFG_10_CLR,
+		24, 1, 31, CLK_CFG_UPDATE1, TOP_MUX_SSUSB_FMCNT_P1_SHIFT,
+		CLK_FENC_STATUS_MON_1, 20),
+	/* CLK_CFG_11 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_I2C_P_SEL, "ck_i2c_p_sel", ck_i2c_p_parents,
+		CLK_CFG_11, CLK_CFG_11_SET, CLK_CFG_11_CLR,
+		0, 3, 7, CLK_CFG_UPDATE1, TOP_MUX_I2C_PERI_SHIFT,
+		CLK_FENC_STATUS_MON_1, 19),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_I2C_EAST_SEL, "ck_i2c_east_sel", ck_i2c_east_parents,
+		CLK_CFG_11, CLK_CFG_11_SET, CLK_CFG_11_CLR,
+		8, 3, 15, CLK_CFG_UPDATE1, TOP_MUX_I2C_EAST_SHIFT,
+		CLK_FENC_STATUS_MON_1, 18),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_I2C_WEST_SEL, "ck_i2c_west_sel", ck_i2c_west_parents,
+		CLK_CFG_11, CLK_CFG_11_SET, CLK_CFG_11_CLR,
+		16, 3, 23, CLK_CFG_UPDATE1, TOP_MUX_I2C_WEST_SHIFT,
+		CLK_FENC_STATUS_MON_1, 17),
+	MUX_MULT_VOTE_FENC(CLK_CK_I2C_NORTH_SEL, "ck_i2c_north_sel", ck_i2c_north_parents,
+		CLK_CFG_11, CLK_CFG_11_SET, CLK_CFG_11_CLR, "vote-regmap",
+		VOTE_CG_6_DONE, VOTE_CG_6_SET, VOTE_CG_6_CLR,
+		24, 3, 31, CLK_CFG_UPDATE1, TOP_MUX_I2C_NORTH_SHIFT,
+		CLK_FENC_STATUS_MON_1, 16),
+	/* CLK_CFG_12 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_AES_UFSFDE_SEL, "ck_aes_ufsfde_sel", ck_aes_ufsfde_parents,
+		CLK_CFG_12, CLK_CFG_12_SET, CLK_CFG_12_CLR,
+		0, 3, 7, CLK_CFG_UPDATE1, TOP_MUX_AES_UFSFDE_SHIFT,
+		CLK_FENC_STATUS_MON_1, 15),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_SEL, "ck_sel", ck_parents,
+		CLK_CFG_12, CLK_CFG_12_SET, CLK_CFG_12_CLR,
+		8, 3, 15, CLK_CFG_UPDATE1, TOP_MUX_UFS_SHIFT,
+		CLK_FENC_STATUS_MON_1, 14),
+	/* CLK_CFG_13 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_AUD_1_SEL, "ck_aud_1_sel", ck_aud_1_parents,
+		CLK_CFG_13, CLK_CFG_13_SET, CLK_CFG_13_CLR,
+		0, 1, 7, CLK_CFG_UPDATE1, TOP_MUX_AUD_1_SHIFT,
+		CLK_FENC_STATUS_MON_1, 11),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_AUD_2_SEL, "ck_aud_2_sel", ck_aud_2_parents,
+		CLK_CFG_13, CLK_CFG_13_SET, CLK_CFG_13_CLR,
+		8, 1, 15, CLK_CFG_UPDATE1, TOP_MUX_AUD_2_SHIFT,
+		CLK_FENC_STATUS_MON_1, 10),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_ADSP_SEL, "ck_adsp_sel", ck_adsp_parents,
+		CLK_CFG_13, CLK_CFG_13_SET, CLK_CFG_13_CLR,
+		16, 1, 23, CLK_CFG_UPDATE1, TOP_MUX_ADSP_SHIFT,
+		CLK_FENC_STATUS_MON_1, 9),
+	MUX_GATE_CLR_SET_UPD(CLK_CK_ADSP_UARTHUB_BCLK_SEL, "ck_adsp_uarthub_b_sel",
+		ck_adsp_uarthub_b_parents, CLK_CFG_13, CLK_CFG_13_SET,
+		CLK_CFG_13_CLR, 24, 2, 31,
+		CLK_CFG_UPDATE1, TOP_MUX_ADSP_UARTHUB_BCLK_SHIFT),
+	/* CLK_CFG_14 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_DPMAIF_MAIN_SEL, "ck_dpmaif_main_sel", ck_dpmaif_main_parents,
+		CLK_CFG_14, CLK_CFG_14_SET, CLK_CFG_14_CLR,
+		0, 4, 7, CLK_CFG_UPDATE1, TOP_MUX_DPMAIF_MAIN_SHIFT,
+		CLK_FENC_STATUS_MON_1, 7),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_PWM_SEL, "ck_pwm_sel", ck_pwm_parents,
+		CLK_CFG_14, CLK_CFG_14_SET, CLK_CFG_14_CLR,
+		8, 2, 15, CLK_CFG_UPDATE1, TOP_MUX_PWM_SHIFT,
+		CLK_FENC_STATUS_MON_1, 6),
+	MUX_CLR_SET_UPD(CLK_CK_MCUPM_SEL, "ck_mcupm_sel",
+		ck_mcupm_parents, CLK_CFG_14, CLK_CFG_14_SET,
+		CLK_CFG_14_CLR, 16, 3,
+		CLK_CFG_UPDATE1, TOP_MUX_MCUPM_SHIFT),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_SFLASH_SEL, "ck_sflash_sel", ck_sflash_parents,
+		CLK_CFG_14, CLK_CFG_14_SET, CLK_CFG_14_CLR,
+		24, 2, 31, CLK_CFG_UPDATE1, TOP_MUX_SFLASH_SHIFT,
+		CLK_FENC_STATUS_MON_1, 4),
+	/* CLK_CFG_15 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_IPSEAST_SEL, "ck_ipseast_sel", ck_ipseast_parents,
+		CLK_CFG_15, CLK_CFG_15_SET, CLK_CFG_15_CLR,
+		0, 3, 7, CLK_CFG_UPDATE1, TOP_MUX_IPSEAST_SHIFT,
+		CLK_FENC_STATUS_MON_1, 3),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_TL_SEL, "ck_tl_sel", ck_tl_parents,
+		CLK_CFG_15, CLK_CFG_15_SET, CLK_CFG_15_CLR,
+		16, 2, 23, CLK_CFG_UPDATE2, TOP_MUX_TL_SHIFT,
+		CLK_FENC_STATUS_MON_1, 1),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_TL_P1_SEL, "ck_tl_p1_sel", ck_tl_p1_parents,
+		CLK_CFG_15, CLK_CFG_15_SET, CLK_CFG_15_CLR,
+		24, 2, 31, CLK_CFG_UPDATE2, TOP_MUX_TL_P1_SHIFT,
+		CLK_FENC_STATUS_MON_1, 0),
+	/* CLK_CFG_16 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK_TL_P2_SEL, "ck_tl_p2_sel", ck_tl_p2_parents,
+		CLK_CFG_16, CLK_CFG_16_SET, CLK_CFG_16_CLR,
+		0, 2, 7, CLK_CFG_UPDATE2, TOP_MUX_TL_P2_SHIFT,
+		CLK_FENC_STATUS_MON_2, 31),
+	MUX_CLR_SET_UPD(CLK_CK_EMI_INTERFACE_546_SEL, "ck_md_emi_sel",
+		ck_md_emi_parents, CLK_CFG_16, CLK_CFG_16_SET,
+		CLK_CFG_16_CLR, 8, 1,
+		CLK_CFG_UPDATE2, TOP_MUX_EMI_INTERFACE_546_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SDF_SEL, "ck_sdf_sel",
+		ck_sdf_parents, CLK_CFG_16, CLK_CFG_16_SET,
+		CLK_CFG_16_CLR, 16, 3,
+		CLK_CFG_UPDATE2, TOP_MUX_SDF_SHIFT),
+	MUX_MULT_VOTE_FENC(CLK_CK_UARTHUB_BCLK_SEL, "ck_uarthub_b_sel", ck_uarthub_b_parents,
+		CLK_CFG_16, CLK_CFG_16_SET, CLK_CFG_16_CLR, "vote-regmap",
+		VOTE_CG_7_DONE, VOTE_CG_7_SET, VOTE_CG_7_CLR,
+		24, 2, 31, CLK_CFG_UPDATE2, TOP_MUX_UARTHUB_BCLK_SHIFT,
+		CLK_FENC_STATUS_MON_2, 28),
+	/* CLK_CFG_17 */
+	MUX_CLR_SET_UPD(CLK_CK_DPSW_CMP_26M_SEL, "ck_dpsw_cmp_26m_sel",
+		ck_dpsw_cmp_26m_parents, CLK_CFG_17, CLK_CFG_17_SET,
+		CLK_CFG_17_CLR, 0, 1,
+		CLK_CFG_UPDATE2, TOP_MUX_DPSW_CMP_26M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SMAPCK_SEL, "ck_smapck_sel",
+		ck_smapck_parents, CLK_CFG_17, CLK_CFG_17_SET,
+		CLK_CFG_17_CLR, 8, 1,
+		CLK_CFG_UPDATE2, TOP_MUX_SMAPCK_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SSR_PKA_SEL, "ck_ssr_pka_sel",
+		ck_ssr_pka_parents, CLK_CFG_17, CLK_CFG_17_SET,
+		CLK_CFG_17_CLR, 16, 3,
+		CLK_CFG_UPDATE2, TOP_MUX_SSR_PKA_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SSR_DMA_SEL, "ck_ssr_dma_sel",
+		ck_ssr_dma_parents, CLK_CFG_17, CLK_CFG_17_SET,
+		CLK_CFG_17_CLR, 24, 3,
+		CLK_CFG_UPDATE2, TOP_MUX_SSR_DMA_SHIFT),
+	/* CLK_CFG_18 */
+	MUX_CLR_SET_UPD(CLK_CK_SSR_KDF_SEL, "ck_ssr_kdf_sel",
+		ck_ssr_kdf_parents, CLK_CFG_18, CLK_CFG_18_SET,
+		CLK_CFG_18_CLR, 0, 2,
+		CLK_CFG_UPDATE2, TOP_MUX_SSR_KDF_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SSR_RNG_SEL, "ck_ssr_rng_sel",
+		ck_ssr_rng_parents, CLK_CFG_18, CLK_CFG_18_SET,
+		CLK_CFG_18_CLR, 8, 2,
+		CLK_CFG_UPDATE2, TOP_MUX_SSR_RNG_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SPU0_SEL, "ck_spu0_sel",
+		ck_spu0_parents, CLK_CFG_18, CLK_CFG_18_SET,
+		CLK_CFG_18_CLR, 16, 3,
+		CLK_CFG_UPDATE2, TOP_MUX_SPU0_SHIFT),
+	MUX_CLR_SET_UPD(CLK_CK_SPU1_SEL, "ck_spu1_sel",
+		ck_spu1_parents, CLK_CFG_18, CLK_CFG_18_SET,
+		CLK_CFG_18_CLR, 24, 3,
+		CLK_CFG_UPDATE2, TOP_MUX_SPU1_SHIFT),
+	/* CLK_CFG_19 */
+	MUX_CLR_SET_UPD(CLK_CK_DXCC_SEL, "ck_dxcc_sel",
+		ck_dxcc_parents, CLK_CFG_19, CLK_CFG_19_SET,
+		CLK_CFG_19_CLR, 0, 2,
+		CLK_CFG_UPDATE2, TOP_MUX_DXCC_SHIFT),
+};
+
+static const struct mtk_composite ck_composites[] = {
+	/* CLK_AUDDIV_0 */
+	MUX(CLK_CK_APLL_I2SIN0_MCK_SEL, "ck_apll_i2sin0_m_sel",
+	    ck_apll_i2sin0_m_parents, 0x020c, 16, 1),
+	MUX(CLK_CK_APLL_I2SIN1_MCK_SEL, "ck_apll_i2sin1_m_sel",
+	    ck_apll_i2sin1_m_parents, 0x020c, 17, 1),
+	MUX(CLK_CK_APLL_I2SIN2_MCK_SEL, "ck_apll_i2sin2_m_sel",
+	    ck_apll_i2sin2_m_parents, 0x020c, 18, 1),
+	MUX(CLK_CK_APLL_I2SIN3_MCK_SEL, "ck_apll_i2sin3_m_sel",
+	    ck_apll_i2sin3_m_parents, 0x020c, 19, 1),
+	MUX(CLK_CK_APLL_I2SIN4_MCK_SEL, "ck_apll_i2sin4_m_sel",
+	    ck_apll_i2sin4_m_parents, 0x020c, 20, 1),
+	MUX(CLK_CK_APLL_I2SIN6_MCK_SEL, "ck_apll_i2sin6_m_sel",
+	    ck_apll_i2sin6_m_parents, 0x020c, 21, 1),
+	MUX(CLK_CK_APLL_I2SOUT0_MCK_SEL, "ck_apll_i2sout0_m_sel",
+	    ck_apll_i2sout0_m_parents, 0x020c, 22, 1),
+	MUX(CLK_CK_APLL_I2SOUT1_MCK_SEL, "ck_apll_i2sout1_m_sel",
+	    ck_apll_i2sout1_m_parents, 0x020c, 23, 1),
+	MUX(CLK_CK_APLL_I2SOUT2_MCK_SEL, "ck_apll_i2sout2_m_sel",
+	    ck_apll_i2sout2_m_parents, 0x020c, 24, 1),
+	MUX(CLK_CK_APLL_I2SOUT3_MCK_SEL, "ck_apll_i2sout3_m_sel",
+	    ck_apll_i2sout3_m_parents, 0x020c, 25, 1),
+	MUX(CLK_CK_APLL_I2SOUT4_MCK_SEL, "ck_apll_i2sout4_m_sel",
+	    ck_apll_i2sout4_m_parents, 0x020c, 26, 1),
+	MUX(CLK_CK_APLL_I2SOUT6_MCK_SEL, "ck_apll_i2sout6_m_sel",
+	    ck_apll_i2sout6_m_parents, 0x020c, 27, 1),
+	MUX(CLK_CK_APLL_FMI2S_MCK_SEL, "ck_apll_fmi2s_m_sel",
+	    ck_apll_fmi2s_m_parents, 0x020c, 28, 1),
+	MUX(CLK_CK_APLL_TDMOUT_MCK_SEL, "ck_apll_tdmout_m_sel",
+	    ck_apll_tdmout_m_parents, 0x020c, 29, 1),
+	/* CLK_AUDDIV_2 */
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN0, "ck_apll12_div_i2sin0",
+		"ck_apll_i2sin0_m_sel", 0x020c,
+		0, CLK_AUDDIV_2, 8, 0),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN1, "ck_apll12_div_i2sin1",
+		"ck_apll_i2sin1_m_sel", 0x020c,
+		1, CLK_AUDDIV_2, 8, 8),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN2, "ck_apll12_div_i2sin2",
+		"ck_apll_i2sin2_m_sel", 0x020c,
+		2, CLK_AUDDIV_2, 8, 16),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN3, "ck_apll12_div_i2sin3",
+		"ck_apll_i2sin3_m_sel", 0x020c,
+		3, CLK_AUDDIV_2, 8, 24),
+	/* CLK_AUDDIV_3 */
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN4, "ck_apll12_div_i2sin4",
+		"ck_apll_i2sin4_m_sel", 0x020c,
+		4, CLK_AUDDIV_3, 8, 0),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SIN6, "ck_apll12_div_i2sin6",
+		"ck_apll_i2sin6_m_sel", 0x020c,
+		5, CLK_AUDDIV_3, 8, 8),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT0, "ck_apll12_div_i2sout0",
+		"ck_apll_i2sout0_m_sel", 0x020c,
+		6, CLK_AUDDIV_3, 8, 16),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT1, "ck_apll12_div_i2sout1",
+		"ck_apll_i2sout1_m_sel", 0x020c,
+		7, CLK_AUDDIV_3, 8, 24),
+	/* CLK_AUDDIV_4 */
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT2, "ck_apll12_div_i2sout2",
+		"ck_apll_i2sout2_m_sel", 0x020c,
+		8, CLK_AUDDIV_4, 8, 0),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT3, "ck_apll12_div_i2sout3",
+		"ck_apll_i2sout3_m_sel", 0x020c,
+		9, CLK_AUDDIV_4, 8, 8),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT4, "ck_apll12_div_i2sout4",
+		"ck_apll_i2sout4_m_sel", 0x020c,
+		10, CLK_AUDDIV_4, 8, 16),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_I2SOUT6, "ck_apll12_div_i2sout6",
+		"ck_apll_i2sout6_m_sel", 0x020c,
+		11, CLK_AUDDIV_4, 8, 24),
+	/* CLK_AUDDIV_5 */
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_FMI2S, "ck_apll12_div_fmi2s",
+		"ck_apll_fmi2s_m_sel", 0x020c,
+		12, CLK_AUDDIV_5, 8, 0),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_TDMOUT_M, "ck_apll12_div_tdmout_m",
+		"ck_apll_tdmout_m_sel", 0x020c,
+		13, CLK_AUDDIV_5, 8, 8),
+	DIV_GATE(CLK_CK_APLL12_CK_DIV_TDMOUT_B, "ck_apll12_div_tdmout_b",
+		"ck_apll_tdmout_m_sel", 0x020c,
+		14, CLK_AUDDIV_5, 8, 16),
+};
+
+static int clk_mt8196_ck_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	void __iomem *base;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		dev_err(&pdev->dev, "%s(): ioremap failed\n", __func__);
+		return PTR_ERR(base);
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_CK_NR_CLK);
+
+	mtk_clk_register_factors(ck_divs, ARRAY_SIZE(ck_divs),
+			clk_data);
+
+	mtk_clk_register_muxes(&pdev->dev, ck_muxes, ARRAY_SIZE(ck_muxes), node,
+			&mt8196_clk_ck_lock, clk_data);
+
+	mtk_clk_register_composites(&pdev->dev, ck_composites, ARRAY_SIZE(ck_composites),
+			base, &mt8196_clk_ck_lock, clk_data);
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev, "%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static void clk_mt8196_ck_remove(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_composites(ck_composites, ARRAY_SIZE(ck_composites), clk_data);
+	mtk_clk_unregister_muxes(ck_muxes, ARRAY_SIZE(ck_muxes), clk_data);
+	mtk_clk_unregister_factors(ck_divs, ARRAY_SIZE(ck_divs), clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8196_ck[] = {
+	{ .compatible = "mediatek,mt8196-cksys", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_ck_drv = {
+	.probe = clk_mt8196_ck_probe,
+	.remove = clk_mt8196_ck_remove,
+	.driver = {
+		.name = "clk-mt8196-ck",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_ck,
+	},
+};
+
+module_platform_driver(clk_mt8196_ck_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:07 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:07 +0800
Subject: [PATCH 11/26] clk: mediatek: Add MT8196 vlpckgen clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-12-guangjie.song@mediatek.com>

Add MT8196 vlpckgen clock controller which provides muxes and dividers
to handle variety clock selection in other IP blocks.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile              |   2 +-
 drivers/clk/mediatek/clk-mt8196-vlpckgen.c | 777 +++++++++++++++++++++
 2 files changed, 778 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vlpckgen.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 5c058b64ff56..583e5b9a7d40 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -151,7 +151,7 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
 obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o \
-				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o
+				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-vlpckgen.c b/drivers/clk/mediatek/clk-mt8196-vlpckgen.c
new file mode 100644
index 000000000000..0bd6396a51ca
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-vlpckgen.c
@@ -0,0 +1,777 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-pll.h"
+
+/* MUX SEL REG */
+#define VLP_CLK_CFG_UPDATE		0x0004
+#define VLP_CLK_CFG_UPDATE1		0x0008
+#define VLP_CLK_CFG_0			0x0010
+#define VLP_CLK_CFG_0_SET		0x0014
+#define VLP_CLK_CFG_0_CLR		0x0018
+#define VLP_CLK_CFG_1			0x0020
+#define VLP_CLK_CFG_1_SET		0x0024
+#define VLP_CLK_CFG_1_CLR		0x0028
+#define VLP_CLK_CFG_2			0x0030
+#define VLP_CLK_CFG_2_SET		0x0034
+#define VLP_CLK_CFG_2_CLR		0x0038
+#define VLP_CLK_CFG_3			0x0040
+#define VLP_CLK_CFG_3_SET		0x0044
+#define VLP_CLK_CFG_3_CLR		0x0048
+#define VLP_CLK_CFG_4			0x0050
+#define VLP_CLK_CFG_4_SET		0x0054
+#define VLP_CLK_CFG_4_CLR		0x0058
+#define VLP_CLK_CFG_5			0x0060
+#define VLP_CLK_CFG_5_SET		0x0064
+#define VLP_CLK_CFG_5_CLR		0x0068
+#define VLP_CLK_CFG_6			0x0070
+#define VLP_CLK_CFG_6_SET		0x0074
+#define VLP_CLK_CFG_6_CLR		0x0078
+#define VLP_CLK_CFG_7			0x0080
+#define VLP_CLK_CFG_7_SET		0x0084
+#define VLP_CLK_CFG_7_CLR		0x0088
+#define VLP_CLK_CFG_8			0x0090
+#define VLP_CLK_CFG_8_SET		0x0094
+#define VLP_CLK_CFG_8_CLR		0x0098
+#define VLP_CLK_CFG_9			0x00a0
+#define VLP_CLK_CFG_9_SET		0x00a4
+#define VLP_CLK_CFG_9_CLR		0x00a8
+#define VLP_CLK_CFG_10			0x00b0
+#define VLP_CLK_CFG_10_SET		0x00b4
+#define VLP_CLK_CFG_10_CLR		0x00b8
+#define VLP_OCIC_FENC_STATUS_MON_0	0x039c
+#define VLP_OCIC_FENC_STATUS_MON_1	0x03a0
+
+/* MUX SHIFT */
+#define TOP_MUX_SCP_SHIFT			0
+#define TOP_MUX_SCP_SPI_SHIFT			1
+#define TOP_MUX_SCP_IIC_SHIFT			2
+#define TOP_MUX_SCP_IIC_HIGH_SPD_SHIFT		3
+#define TOP_MUX_PWRAP_ULPOSC_SHIFT		4
+#define TOP_MUX_SPMI_M_TIA_32K_SHIFT		5
+#define TOP_MUX_APXGPT_26M_BCLK_SHIFT		6
+#define TOP_MUX_DPSW_SHIFT			7
+#define TOP_MUX_DPSW_CENTRAL_SHIFT		8
+#define TOP_MUX_SPMI_M_MST_SHIFT		9
+#define TOP_MUX_DVFSRC_SHIFT			10
+#define TOP_MUX_PWM_VLP_SHIFT			11
+#define TOP_MUX_AXI_VLP_SHIFT			12
+#define TOP_MUX_SYSTIMER_26M_SHIFT		13
+#define TOP_MUX_SSPM_SHIFT			14
+#define TOP_MUX_SRCK_SHIFT			15
+#define TOP_MUX_CAMTG0_SHIFT			16
+#define TOP_MUX_CAMTG1_SHIFT			17
+#define TOP_MUX_CAMTG2_SHIFT			18
+#define TOP_MUX_CAMTG3_SHIFT			19
+#define TOP_MUX_CAMTG4_SHIFT			20
+#define TOP_MUX_CAMTG5_SHIFT			21
+#define TOP_MUX_CAMTG6_SHIFT			22
+#define TOP_MUX_CAMTG7_SHIFT			23
+#define TOP_MUX_SSPM_26M_SHIFT			25
+#define TOP_MUX_ULPOSC_SSPM_SHIFT		26
+#define TOP_MUX_VLP_PBUS_26M_SHIFT		27
+#define TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT	28
+#define TOP_MUX_DPMSRDMA_SHIFT			29
+#define TOP_MUX_VLP_PBUS_156M_SHIFT		30
+#define TOP_MUX_SPM_SHIFT			0
+#define TOP_MUX_MMINFRA_VLP_SHIFT		1
+#define TOP_MUX_USB_TOP_SHIFT			2
+#define TOP_MUX_SSUSB_XHCI_SHIFT		3
+#define TOP_MUX_NOC_VLP_SHIFT			4
+#define TOP_MUX_AUDIO_H_SHIFT			5
+#define TOP_MUX_AUD_ENGEN1_SHIFT		6
+#define TOP_MUX_AUD_ENGEN2_SHIFT		7
+#define TOP_MUX_AUD_INTBUS_SHIFT		8
+#define TOP_MUX_SPU_VLP_26M_SHIFT		9
+#define TOP_MUX_SPU0_VLP_SHIFT			10
+#define TOP_MUX_SPU1_VLP_SHIFT			11
+
+/* CKSTA REG */
+#define VLP_CKSTA_REG0			0x0250
+#define VLP_CKSTA_REG1			0x0254
+
+/* HW Voter REG */
+#define VOTE_CG_9_SET	0x0048
+#define VOTE_CG_9_CLR	0x004c
+#define VOTE_CG_9_DONE	0x2c24
+#define VOTE_CG_10_SET	0x0050
+#define VOTE_CG_10_CLR	0x0054
+#define VOTE_CG_10_DONE	0x2c28
+
+/* PLL REG */
+#define VLP_AP_PLL_CON3		0x264
+#define VLP_APLL1_TUNER_CON0	0x2a4
+#define VLP_APLL2_TUNER_CON0	0x2a8
+#define VLP_APLL1_CON0		0x274
+#define VLP_APLL1_CON1		0x278
+#define VLP_APLL1_CON2		0x27c
+#define VLP_APLL1_CON3		0x280
+#define VLP_APLL2_CON0		0x28c
+#define VLP_APLL2_CON1		0x290
+#define VLP_APLL2_CON2		0x294
+#define VLP_APLL2_CON3		0x298
+
+#define MT8196_PLL_FMAX		(3800UL * MHZ)
+#define MT8196_PLL_FMIN		(1500UL * MHZ)
+#define MT8196_INTEGER_BITS	8
+
+#define PLL_FENC(_id, _name, _reg, _fenc_sta_ofs, _fenc_sta_bit,\
+			_flags, _pd_reg, _pd_shift,		\
+			 _pcw_reg, _pcw_shift, _pcwbits) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.reg = _reg,					\
+		.fenc_sta_ofs = _fenc_sta_ofs,			\
+		.fenc_sta_bit = _fenc_sta_bit,			\
+		.flags = (_flags) | CLK_FENC_ENABLE,		\
+		.fmax = MT8196_PLL_FMAX,			\
+		.fmin = MT8196_PLL_FMIN,			\
+		.pd_reg = _pd_reg,				\
+		.pd_shift = _pd_shift,				\
+		.pcw_reg = _pcw_reg,				\
+		.pcw_shift = _pcw_shift,			\
+		.pcwbits = _pcwbits,				\
+		.pcwibits = MT8196_INTEGER_BITS,		\
+	}
+
+static DEFINE_SPINLOCK(mt8196_clk_vlp_ck_lock);
+
+static const struct mtk_fixed_factor vlp_ck_divs[] = {
+	FACTOR(CLK_VLP_CK_OSC3, "vlp_osc3", "ulposc3", 1, 1),
+	FACTOR(CLK_VLP_CK_CLKSQ, "vlp_clksq_ck", "clk26m", 1, 1),
+	FACTOR(CLK_VLP_CK_AUDIO_H, "vlp_audio_h_ck", "vlp_audio_h_sel", 1, 1),
+	FACTOR(CLK_VLP_CK_AUD_ENGEN1, "vlp_aud_engen1_ck", "vlp_aud_engen1_sel", 1, 1),
+	FACTOR(CLK_VLP_CK_AUD_ENGEN2, "vlp_aud_engen2_ck", "vlp_aud_engen2_sel", 1, 1),
+	FACTOR(CLK_VLP_CK_INFRA_26M, "vlp_infra_26m_ck", "ck_tck_26m_mx9_ck", 1, 1),
+	FACTOR(CLK_VLP_CK_AUD_CLKSQ, "vlp_aud_clksq_ck", "vlp_clksq_ck", 1, 1),
+};
+
+static const char * const vlp_scp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d6",
+	"ck_mainpll_d4",
+	"ck_mainpll_d3",
+	"ck_apll1_ck"
+};
+
+static const char * const vlp_scp_spi_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d5_d2"
+};
+
+static const char * const vlp_scp_iic_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const vlp_scp_iic_hs_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d5_d4",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d7"
+};
+
+static const char * const vlp_pwrap_ulposc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_osc_d14",
+	"ck_osc_d10"
+};
+
+static const char * const vlp_spmi_32ksel_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_clkrtc",
+	"ck_osc_d20",
+	"ck_osc_d14",
+	"ck_osc_d10"
+};
+
+static const char * const vlp_apxgpt_26m_b_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_dpsw_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d7",
+	"ck_mainpll_d7_d4"
+};
+
+static const char * const vlp_dpsw_central_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d7",
+	"ck_mainpll_d7_d4"
+};
+
+static const char * const vlp_spmi_m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_osc_d14",
+	"ck_osc_d10"
+};
+
+static const char * const vlp_dvfsrc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_pwm_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_clkrtc",
+	"ck_osc_d20",
+	"ck_osc_d8",
+	"ck_mainpll_d4_d8"
+};
+
+static const char * const vlp_axi_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d7_d4",
+	"ck_osc_d4",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const vlp_systimer_26m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_sspm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d5_d2",
+	"ck_osc_d2",
+	"ck_mainpll_d6"
+};
+
+static const char * const vlp_srck_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_camtg0_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc3",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc3",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg3_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg4_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg5_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg6_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_camtg7_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_univpll_192m_d32",
+	"ck_univpll_192m_d16",
+	"ck_f26m_d2",
+	"ck_osc_d40",
+	"ck_osc_d32",
+	"ck_univpll_192m_d10",
+	"ck_univpll_192m_d8",
+	"ck_univpll_d6_d16",
+	"ck_osc_d20",
+	"ck2_tvdpll1_d16",
+	"ck_univpll_d6_d8"
+};
+
+static const char * const vlp_sspm_26m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_ulposc_sspm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d2",
+	"ck_mainpll_d4_d2"
+};
+
+static const char * const vlp_vlp_pbus_26m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_debug_err_flag_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_dpmsrdma_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d2"
+};
+
+static const char * const vlp_vlp_pbus_156m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d2",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d7"
+};
+
+static const char * const vlp_spm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d7_d4"
+};
+
+static const char * const vlp_mminfra_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d3"
+};
+
+static const char * const vlp_usb_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d9"
+};
+
+static const char * const vlp_usb_xhci_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d9"
+};
+
+static const char * const vlp_noc_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d9"
+};
+
+static const char * const vlp_audio_h_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"vlp_clksq_ck",
+	"ck_apll1_ck",
+	"ck_apll2_ck"
+};
+
+static const char * const vlp_aud_engen1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"vlp_clksq_ck",
+	"ck_apll1_d8",
+	"ck_apll1_d4"
+};
+
+static const char * const vlp_aud_engen2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"vlp_clksq_ck",
+	"ck_apll2_d8",
+	"ck_apll2_d4"
+};
+
+static const char * const vlp_aud_intbus_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"vlp_clksq_ck",
+	"ck_mainpll_d7_d4",
+	"ck_mainpll_d4_d4"
+};
+
+static const char * const vlp_spvlp_26m_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20"
+};
+
+static const char * const vlp_spu0_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const char * const vlp_spu1_vlp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d20",
+	"ck_mainpll_d4_d4",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck_mainpll_d5"
+};
+
+static const struct mtk_mux vlp_ck_muxes[] = {
+	/* VLP_CLK_CFG_0 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_SCP_SEL, "vlp_scp_sel", vlp_scp_parents,
+		VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, VLP_CLK_CFG_0_CLR,
+		0, 3, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 31),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_SPI_SEL, "vlp_scp_spi_sel",
+		vlp_scp_spi_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
+		VLP_CLK_CFG_0_CLR, 8, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SPI_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_SEL, "vlp_scp_iic_sel",
+		vlp_scp_iic_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
+		VLP_CLK_CFG_0_CLR, 16, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_HIGH_SPD_SEL, "vlp_scp_iic_hs_sel",
+		vlp_scp_iic_hs_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET,
+		VLP_CLK_CFG_0_CLR, 24, 3,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_HIGH_SPD_SHIFT),
+	/* VLP_CLK_CFG_1 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_PWRAP_ULPOSC_SEL, "vlp_pwrap_ulposc_sel",
+		vlp_pwrap_ulposc_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
+		VLP_CLK_CFG_1_CLR, 0, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_PWRAP_ULPOSC_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPMI_M_TIA_32K_SEL, "vlp_spmi_32ksel",
+		vlp_spmi_32ksel_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
+		VLP_CLK_CFG_1_CLR, 8, 3,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_TIA_32K_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_APXGPT_26M_BCLK_SEL, "vlp_apxgpt_26m_b_sel",
+		vlp_apxgpt_26m_b_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
+		VLP_CLK_CFG_1_CLR, 16, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_APXGPT_26M_BCLK_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DPSW_SEL, "vlp_dpsw_sel",
+		vlp_dpsw_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET,
+		VLP_CLK_CFG_1_CLR, 24, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_SHIFT),
+	/* VLP_CLK_CFG_2 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DPSW_CENTRAL_SEL, "vlp_dpsw_central_sel",
+		vlp_dpsw_central_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
+		VLP_CLK_CFG_2_CLR, 0, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_CENTRAL_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPMI_M_MST_SEL, "vlp_spmi_m_sel",
+		vlp_spmi_m_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
+		VLP_CLK_CFG_2_CLR, 8, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_MST_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DVFSRC_SEL, "vlp_dvfsrc_sel",
+		vlp_dvfsrc_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET,
+		VLP_CLK_CFG_2_CLR, 16, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_DVFSRC_SHIFT),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_PWM_VLP_SEL, "vlp_pwm_vlp_sel", vlp_pwm_vlp_parents,
+		VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, VLP_CLK_CFG_2_CLR,
+		24, 3, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_PWM_VLP_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 20),
+	/* VLP_CLK_CFG_3 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_AXI_VLP_SEL, "vlp_axi_vlp_sel",
+		vlp_axi_vlp_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
+		VLP_CLK_CFG_3_CLR, 0, 3,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_AXI_VLP_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SYSTIMER_26M_SEL, "vlp_systimer_26m_sel",
+		vlp_systimer_26m_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
+		VLP_CLK_CFG_3_CLR, 8, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SYSTIMER_26M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_SEL, "vlp_sspm_sel",
+		vlp_sspm_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
+		VLP_CLK_CFG_3_CLR, 16, 3,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SRCK_SEL, "vlp_srck_sel",
+		vlp_srck_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET,
+		VLP_CLK_CFG_3_CLR, 24, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SRCK_SHIFT),
+	/* VLP_CLK_CFG_4 */
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG0_SEL, "vlp_camtg0_sel", vlp_camtg0_parents,
+		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, "vote-regmap",
+		VOTE_CG_9_DONE, VOTE_CG_9_SET, VOTE_CG_9_CLR,
+		0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG0_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 15),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG1_SEL, "vlp_camtg1_sel", vlp_camtg1_parents,
+		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, "vote-regmap",
+		VOTE_CG_9_DONE, VOTE_CG_9_SET, VOTE_CG_9_CLR,
+		8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG1_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 14),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG2_SEL, "vlp_camtg2_sel", vlp_camtg2_parents,
+		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, "vote-regmap",
+		VOTE_CG_9_DONE, VOTE_CG_9_SET, VOTE_CG_9_CLR,
+		16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG2_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 13),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG3_SEL, "vlp_camtg3_sel", vlp_camtg3_parents,
+		VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, "vote-regmap",
+		VOTE_CG_9_DONE, VOTE_CG_9_SET, VOTE_CG_9_CLR,
+		24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG3_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 12),
+	/* VLP_CLK_CFG_5 */
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG4_SEL, "vlp_camtg4_sel", vlp_camtg4_parents,
+		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, "vote-regmap",
+		VOTE_CG_10_DONE, VOTE_CG_10_SET, VOTE_CG_10_CLR,
+		0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG4_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 11),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG5_SEL, "vlp_camtg5_sel", vlp_camtg5_parents,
+		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, "vote-regmap",
+		VOTE_CG_10_DONE, VOTE_CG_10_SET, VOTE_CG_10_CLR,
+		8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG5_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 10),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG6_SEL, "vlp_camtg6_sel", vlp_camtg6_parents,
+		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, "vote-regmap",
+		VOTE_CG_10_DONE, VOTE_CG_10_SET, VOTE_CG_10_CLR,
+		16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG6_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 9),
+	MUX_MULT_VOTE_FENC(CLK_VLP_CK_CAMTG7_SEL, "vlp_camtg7_sel", vlp_camtg7_parents,
+		VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, "vote-regmap",
+		VOTE_CG_10_DONE, VOTE_CG_10_SET, VOTE_CG_10_CLR,
+		24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG7_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_0, 8),
+	/* VLP_CLK_CFG_6 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_26M_SEL, "vlp_sspm_26m_sel",
+		vlp_sspm_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
+		VLP_CLK_CFG_6_CLR, 8, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_26M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_ULPOSC_SSPM_SEL, "vlp_ulposc_sspm_sel",
+		vlp_ulposc_sspm_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
+		VLP_CLK_CFG_6_CLR, 16, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_ULPOSC_SSPM_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_VLP_PBUS_26M_SEL, "vlp_vlp_pbus_26m_sel",
+		vlp_vlp_pbus_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET,
+		VLP_CLK_CFG_6_CLR, 24, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_26M_SHIFT),
+	/* VLP_CLK_CFG_7 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DEBUG_ERR_FLAG_SEL, "vlp_debug_err_flag_sel",
+		vlp_debug_err_flag_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
+		VLP_CLK_CFG_7_CLR, 0, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_DPMSRDMA_SEL, "vlp_dpmsrdma_sel",
+		vlp_dpmsrdma_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
+		VLP_CLK_CFG_7_CLR, 8, 1,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_DPMSRDMA_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_VLP_PBUS_156M_SEL, "vlp_vlp_pbus_156m_sel",
+		vlp_vlp_pbus_156m_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
+		VLP_CLK_CFG_7_CLR, 16, 2,
+		VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_156M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPM_SEL, "vlp_spm_sel",
+		vlp_spm_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET,
+		VLP_CLK_CFG_7_CLR, 24, 1,
+		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPM_SHIFT),
+	/* VLP_CLK_CFG_8 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_MMINFRA_VLP_SEL, "vlp_mminfra_vlp_sel", vlp_mminfra_vlp_parents,
+		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
+		0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_MMINFRA_VLP_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 31),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_USB_TOP_SEL, "vlp_usb_sel", vlp_usb_parents,
+		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
+		8, 1, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_USB_TOP_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 30),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_USB_XHCI_SEL, "vlp_usb_xhci_sel", vlp_usb_xhci_parents,
+		VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR,
+		16, 1, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_SSUSB_XHCI_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 29),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_NOC_VLP_SEL, "vlp_noc_vlp_sel",
+		vlp_noc_vlp_parents, VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET,
+		VLP_CLK_CFG_8_CLR, 24, 2,
+		VLP_CLK_CFG_UPDATE1, TOP_MUX_NOC_VLP_SHIFT),
+	/* VLP_CLK_CFG_9 */
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_AUDIO_H_SEL, "vlp_audio_h_sel", vlp_audio_h_parents,
+		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
+		0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUDIO_H_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 27),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_AUD_ENGEN1_SEL, "vlp_aud_engen1_sel", vlp_aud_engen1_parents,
+		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
+		8, 2, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN1_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 26),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_AUD_ENGEN2_SEL, "vlp_aud_engen2_sel", vlp_aud_engen2_parents,
+		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
+		16, 2, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN2_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 25),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_CK_AUD_INTBUS_SEL, "vlp_aud_intbus_sel", vlp_aud_intbus_parents,
+		VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR,
+		24, 2, 31, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_INTBUS_SHIFT,
+		VLP_OCIC_FENC_STATUS_MON_1, 24),
+	/* VLP_CLK_CFG_10 */
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPVLP_26M_SEL, "vlp_spvlp_26m_sel",
+		vlp_spvlp_26m_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
+		VLP_CLK_CFG_10_CLR, 0, 1,
+		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU_VLP_26M_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPU0_VLP_SEL, "vlp_spu0_vlp_sel",
+		vlp_spu0_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
+		VLP_CLK_CFG_10_CLR, 8, 3,
+		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU0_VLP_SHIFT),
+	MUX_CLR_SET_UPD(CLK_VLP_CK_SPU1_VLP_SEL, "vlp_spu1_vlp_sel",
+		vlp_spu1_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET,
+		VLP_CLK_CFG_10_CLR, 16, 3,
+		VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU1_VLP_SHIFT),
+};
+
+static const struct mtk_pll_data vlp_ck_plls[] = {
+	PLL_FENC(CLK_VLP_CK_VLP_APLL1, "vlp_apll1", VLP_APLL1_CON0,
+		 0x0358, 1, 0,
+		 VLP_APLL1_CON1, 24,
+		 VLP_APLL1_CON2, 0, 32),
+	PLL_FENC(CLK_VLP_CK_VLP_APLL2, "vlp_apll2", VLP_APLL2_CON0,
+		 0x0358, 0, 0,
+		 VLP_APLL2_CON1, 24,
+		 VLP_APLL2_CON2, 0, 32),
+};
+
+static int clk_mt8196_vlp_ck_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_VLP_CK_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
+
+	r = mtk_clk_register_factors(vlp_ck_divs, ARRAY_SIZE(vlp_ck_divs), clk_data);
+	if (r)
+		goto free_clk_data;
+
+	r = mtk_clk_register_muxes(&pdev->dev, vlp_ck_muxes, ARRAY_SIZE(vlp_ck_muxes), node,
+				   &mt8196_clk_vlp_ck_lock, clk_data);
+	if (r)
+		goto unregister_factors;
+
+	r = mtk_clk_register_plls(node, vlp_ck_plls, ARRAY_SIZE(vlp_ck_plls), clk_data);
+	if (r)
+		goto unregister_muxes;
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r)
+		goto unregister_plls;
+
+	return 0;
+
+unregister_plls:
+	mtk_clk_unregister_plls(vlp_ck_plls, ARRAY_SIZE(vlp_ck_plls), clk_data);
+unregister_muxes:
+	mtk_clk_unregister_muxes(vlp_ck_muxes, ARRAY_SIZE(vlp_ck_muxes), clk_data);
+unregister_factors:
+	mtk_clk_unregister_factors(vlp_ck_divs, ARRAY_SIZE(vlp_ck_divs), clk_data);
+free_clk_data:
+	mtk_free_clk_data(clk_data);
+
+	return r;
+}
+
+static void clk_mt8196_vlp_ck_remove(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_plls(vlp_ck_plls, ARRAY_SIZE(vlp_ck_plls), clk_data);
+	mtk_clk_unregister_muxes(vlp_ck_muxes, ARRAY_SIZE(vlp_ck_muxes), clk_data);
+	mtk_clk_unregister_factors(vlp_ck_divs, ARRAY_SIZE(vlp_ck_divs), clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8196_vlp_ck[] = {
+	{ .compatible = "mediatek,mt8196-vlp_cksys", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_vlp_ck_drv = {
+	.probe = clk_mt8196_vlp_ck_probe,
+	.remove = clk_mt8196_vlp_ck_remove,
+	.driver = {
+		.name = "clk-mt8196-vlp_ck",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_vlp_ck,
+	},
+};
+
+module_platform_driver(clk_mt8196_vlp_ck_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:06 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:06 +0800
Subject: [PATCH 10/26] clk: mediatek: Add MT8196 topckgen2 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-11-guangjie.song@mediatek.com>

Add MT8196 topckgen2 clock controller which provides muxes and dividers
to handle variety clock selection in other IP blocks.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile               |   2 +-
 drivers/clk/mediatek/clk-mt8196-topckgen2.c | 701 ++++++++++++++++++++
 2 files changed, 702 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-topckgen2.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index cd6f42a6fd10..5c058b64ff56 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -151,7 +151,7 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
 obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o \
-				   clk-mt8196-topckgen.o
+				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-topckgen2.c b/drivers/clk/mediatek/clk-mt8196-topckgen2.c
new file mode 100644
index 000000000000..ae858498db17
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-topckgen2.c
@@ -0,0 +1,701 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+/* MUX SEL REG */
+#define CKSYS2_CLK_CFG_UPDATE		0x0004
+#define CKSYS2_CLK_CFG_0		0x0010
+#define CKSYS2_CLK_CFG_0_SET		0x0014
+#define CKSYS2_CLK_CFG_0_CLR		0x0018
+#define CKSYS2_CLK_CFG_1		0x0020
+#define CKSYS2_CLK_CFG_1_SET		0x0024
+#define CKSYS2_CLK_CFG_1_CLR		0x0028
+#define CKSYS2_CLK_CFG_2		0x0030
+#define CKSYS2_CLK_CFG_2_SET		0x0034
+#define CKSYS2_CLK_CFG_2_CLR		0x0038
+#define CKSYS2_CLK_CFG_3		0x0040
+#define CKSYS2_CLK_CFG_3_SET		0x0044
+#define CKSYS2_CLK_CFG_3_CLR		0x0048
+#define CKSYS2_CLK_CFG_4		0x0050
+#define CKSYS2_CLK_CFG_4_SET		0x0054
+#define CKSYS2_CLK_CFG_4_CLR		0x0058
+#define CKSYS2_CLK_CFG_5		0x0060
+#define CKSYS2_CLK_CFG_5_SET		0x0064
+#define CKSYS2_CLK_CFG_5_CLR		0x0068
+#define CKSYS2_CLK_CFG_6		0x0070
+#define CKSYS2_CLK_CFG_6_SET		0x0074
+#define CKSYS2_CLK_CFG_6_CLR		0x0078
+#define CKSYS2_CLK_FENC_STATUS_MON_0	0x0174
+
+/* MUX SHIFT */
+#define TOP_MUX_SENINF0_SHIFT		0
+#define TOP_MUX_SENINF1_SHIFT		1
+#define TOP_MUX_SENINF2_SHIFT		2
+#define TOP_MUX_SENINF3_SHIFT		3
+#define TOP_MUX_SENINF4_SHIFT		4
+#define TOP_MUX_SENINF5_SHIFT		5
+#define TOP_MUX_IMG1_SHIFT		6
+#define TOP_MUX_IPE_SHIFT		7
+#define TOP_MUX_CAM_SHIFT		8
+#define TOP_MUX_CAMTM_SHIFT		9
+#define TOP_MUX_DPE_SHIFT		10
+#define TOP_MUX_VDEC_SHIFT		11
+#define TOP_MUX_CCUSYS_SHIFT		12
+#define TOP_MUX_CCUTM_SHIFT		13
+#define TOP_MUX_VENC_SHIFT		14
+#define TOP_MUX_DVO_SHIFT		15
+#define TOP_MUX_DVO_FAVT_SHIFT		16
+#define TOP_MUX_DP1_SHIFT		17
+#define TOP_MUX_DP0_SHIFT		18
+#define TOP_MUX_DISP_SHIFT		19
+#define TOP_MUX_MDP_SHIFT		20
+#define TOP_MUX_MMINFRA_SHIFT		21
+#define TOP_MUX_MMINFRA_SNOC_SHIFT	22
+#define TOP_MUX_MMUP_SHIFT		23
+#define TOP_MUX_MMINFRA_AO_SHIFT	26
+
+/* HW Voter REG */
+#define VOTE_CG_30_SET		0x0058
+#define VOTE_CG_30_CLR		0x005c
+#define VOTE_CG_30_DONE		0x2c2c
+
+#define MM_VOTE_CG_30_SET	0x00f0
+#define MM_VOTE_CG_30_CLR	0x00f4
+#define MM_VOTE_CG_30_DONE	0x2c78
+#define MM_VOTE_CG_31_SET	0x00f8
+#define MM_VOTE_CG_31_CLR	0x00fc
+#define MM_VOTE_CG_31_DONE	0x2c7c
+#define MM_VOTE_CG_32_SET	0x0100
+#define MM_VOTE_CG_32_CLR	0x0104
+#define MM_VOTE_CG_32_DONE	0x2c80
+#define MM_VOTE_CG_33_SET	0x0108
+#define MM_VOTE_CG_33_CLR	0x010c
+#define MM_VOTE_CG_33_DONE	0x2c84
+#define MM_VOTE_CG_34_SET	0x0110
+#define MM_VOTE_CG_34_CLR	0x0114
+#define MM_VOTE_CG_34_DONE	0x2c88
+#define MM_VOTE_CG_35_SET	0x0118
+#define MM_VOTE_CG_35_CLR	0x011c
+#define MM_VOTE_CG_35_DONE	0x2c8c
+#define MM_VOTE_CG_36_SET	0x0120
+#define MM_VOTE_CG_36_CLR	0x0124
+#define MM_VOTE_CG_36_DONE	0x2c90
+#define MM_VOTE_MUX_UPDATE_31_0	0x0240
+
+static DEFINE_SPINLOCK(mt8196_clk_ck2_lock);
+
+static const struct mtk_fixed_factor ck2_divs[] = {
+	FACTOR(CLK_CK2_MAINPLL2_D2, "ck2_mainpll2_d2", "mainpll2", 1, 2),
+	FACTOR(CLK_CK2_MAINPLL2_D3, "ck2_mainpll2_d3", "mainpll2", 1, 3),
+	FACTOR(CLK_CK2_MAINPLL2_D4, "ck2_mainpll2_d4", "mainpll2", 1, 4),
+	FACTOR(CLK_CK2_MAINPLL2_D4_D2, "ck2_mainpll2_d4_d2", "mainpll2", 1, 8),
+	FACTOR(CLK_CK2_MAINPLL2_D4_D4, "ck2_mainpll2_d4_d4", "mainpll2", 1, 16),
+	FACTOR(CLK_CK2_MAINPLL2_D5, "ck2_mainpll2_d5", "mainpll2", 1, 5),
+	FACTOR(CLK_CK2_MAINPLL2_D5_D2, "ck2_mainpll2_d5_d2", "mainpll2", 1, 10),
+	FACTOR(CLK_CK2_MAINPLL2_D6, "ck2_mainpll2_d6", "mainpll2", 1, 6),
+	FACTOR(CLK_CK2_MAINPLL2_D6_D2, "ck2_mainpll2_d6_d2", "mainpll2", 1, 12),
+	FACTOR(CLK_CK2_MAINPLL2_D7, "ck2_mainpll2_d7", "mainpll2", 1, 7),
+	FACTOR(CLK_CK2_MAINPLL2_D7_D2, "ck2_mainpll2_d7_d2", "mainpll2", 1, 14),
+	FACTOR(CLK_CK2_MAINPLL2_D9, "ck2_mainpll2_d9", "mainpll2", 1, 9),
+	FACTOR(CLK_CK2_UNIVPLL2_D3, "ck2_univpll2_d3", "univpll2", 1, 3),
+	FACTOR(CLK_CK2_UNIVPLL2_D4, "ck2_univpll2_d4", "univpll2", 1, 4),
+	FACTOR(CLK_CK2_UNIVPLL2_D4_D2, "ck2_univpll2_d4_d2", "univpll2", 1, 8),
+	FACTOR(CLK_CK2_UNIVPLL2_D5, "ck2_univpll2_d5", "univpll2", 1, 5),
+	FACTOR(CLK_CK2_UNIVPLL2_D5_D2, "ck2_univpll2_d5_d2", "univpll2", 1, 10),
+	FACTOR(CLK_CK2_UNIVPLL2_D6, "ck2_univpll2_d6", "univpll2", 1, 6),
+	FACTOR(CLK_CK2_UNIVPLL2_D6_D2, "ck2_univpll2_d6_d2", "univpll2", 1, 12),
+	FACTOR(CLK_CK2_UNIVPLL2_D6_D4, "ck2_univpll2_d6_d4", "univpll2", 1, 24),
+	FACTOR(CLK_CK2_UNIVPLL2_D7, "ck2_univpll2_d7", "univpll2", 1, 7),
+	FACTOR(CLK_CK2_IMGPLL_D2, "ck2_imgpll_d2", "imgpll", 1, 2),
+	FACTOR(CLK_CK2_IMGPLL_D4, "ck2_imgpll_d4", "imgpll", 1, 4),
+	FACTOR(CLK_CK2_IMGPLL_D5, "ck2_imgpll_d5", "imgpll", 1, 5),
+	FACTOR(CLK_CK2_IMGPLL_D5_D2, "ck2_imgpll_d5_d2", "imgpll", 1, 10),
+	FACTOR(CLK_CK2_MMPLL2_D3, "ck2_mmpll2_d3", "mmpll2", 1, 3),
+	FACTOR(CLK_CK2_MMPLL2_D4, "ck2_mmpll2_d4", "mmpll2", 1, 4),
+	FACTOR(CLK_CK2_MMPLL2_D4_D2, "ck2_mmpll2_d4_d2", "mmpll2", 1, 8),
+	FACTOR(CLK_CK2_MMPLL2_D5, "ck2_mmpll2_d5", "mmpll2", 1, 5),
+	FACTOR(CLK_CK2_MMPLL2_D5_D2, "ck2_mmpll2_d5_d2", "mmpll2", 1, 10),
+	FACTOR(CLK_CK2_MMPLL2_D6, "ck2_mmpll2_d6", "mmpll2", 1, 6),
+	FACTOR(CLK_CK2_MMPLL2_D6_D2, "ck2_mmpll2_d6_d2", "mmpll2", 1, 12),
+	FACTOR(CLK_CK2_MMPLL2_D7, "ck2_mmpll2_d7", "mmpll2", 1, 7),
+	FACTOR(CLK_CK2_MMPLL2_D9, "ck2_mmpll2_d9", "mmpll2", 1, 9),
+	FACTOR(CLK_CK2_TVDPLL1_D4, "ck2_tvdpll1_d4", "tvdpll1", 1, 4),
+	FACTOR(CLK_CK2_TVDPLL1_D8, "ck2_tvdpll1_d8", "tvdpll1", 1, 8),
+	FACTOR(CLK_CK2_TVDPLL1_D16, "ck2_tvdpll1_d16", "tvdpll1", 1, 16),
+	FACTOR(CLK_CK2_TVDPLL2_D2, "ck2_tvdpll2_d2", "tvdpll2", 1, 2),
+	FACTOR(CLK_CK2_TVDPLL2_D4, "ck2_tvdpll2_d4", "tvdpll2", 1, 4),
+	FACTOR(CLK_CK2_TVDPLL2_D8, "ck2_tvdpll2_d8", "tvdpll2", 1, 8),
+	FACTOR(CLK_CK2_TVDPLL2_D16, "ck2_tvdpll2_d16", "tvdpll2", 92, 1473),
+	FACTOR(CLK_CK2_CCUSYS, "ck2_ccusys_ck", "ck2_ccusys_sel", 1, 1),
+	FACTOR(CLK_CK2_VENC, "ck2_venc_ck", "ck2_venc_sel", 1, 1),
+	FACTOR(CLK_CK2_MMINFRA, "ck2_mminfra_ck", "ck2_mminfra_sel", 1, 1),
+	FACTOR(CLK_CK2_IMG1, "ck2_img1_ck", "ck2_img1_sel", 1, 1),
+	FACTOR(CLK_CK2_IPE, "ck2_ipe_ck", "ck2_ipe_sel", 1, 1),
+	FACTOR(CLK_CK2_CAM, "ck2_cam_ck", "ck2_cam_sel", 1, 1),
+	FACTOR(CLK_CK2_CAMTM, "ck2_camtm_ck", "ck2_camtm_sel", 1, 1),
+	FACTOR(CLK_CK2_DPE, "ck2_dpe_ck", "ck2_dpe_sel", 1, 1),
+	FACTOR(CLK_CK2_VDEC, "ck2_vdec_ck", "ck2_vdec_sel", 1, 1),
+	FACTOR(CLK_CK2_DP1, "ck2_dp1_ck", "ck2_dp1_sel", 1, 1),
+	FACTOR(CLK_CK2_DP0, "ck2_dp0_ck", "ck2_dp0_sel", 1, 1),
+	FACTOR(CLK_CK2_DISP, "ck2_disp_ck", "ck2_disp_sel", 1, 1),
+	FACTOR(CLK_CK2_MDP, "ck2_mdp_ck", "ck2_mdp_sel", 1, 1),
+	FACTOR(CLK_CK2_AVS_IMG, "ck2_avs_img_ck", "ck_tck_26m_mx9_ck", 1, 1),
+	FACTOR(CLK_CK2_AVS_VDEC, "ck2_avs_vdec_ck", "ck_tck_26m_mx9_ck", 1, 1),
+	FACTOR(CLK_CK2_TVDPLL3_D2, "ck2_tvdpll3_d2", "tvdpll3", 1, 2),
+	FACTOR(CLK_CK2_TVDPLL3_D4, "ck2_tvdpll3_d4", "tvdpll3", 1, 4),
+	FACTOR(CLK_CK2_TVDPLL3_D8, "ck2_tvdpll3_d8", "tvdpll3", 1, 8),
+	FACTOR(CLK_CK2_TVDPLL3_D16, "ck2_tvdpll3_d16", "tvdpll3", 92, 1473),
+};
+
+static const char * const ck2_seninf0_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_seninf1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_seninf2_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_seninf3_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_seninf4_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_seninf5_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d8",
+	"ck_osc_d5",
+	"ck_osc_d4",
+	"ck2_univpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck_osc_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_univpll2_d5"
+};
+
+static const char * const ck2_img1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck2_mmpll2_d6_d2",
+	"ck_osc_d2",
+	"ck2_imgpll_d5_d2",
+	"ck2_mmpll2_d5_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mmpll2_d5",
+	"ck2_univpll2_d4",
+	"ck2_imgpll_d4"
+};
+
+static const char * const ck2_ipe_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck_osc_d2",
+	"ck2_univpll2_d6",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_imgpll_d5",
+	"ck_mainpll_d4",
+	"ck2_mmpll2_d5",
+	"ck2_imgpll_d4"
+};
+
+static const char * const ck2_cam_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d10",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck_osc_d2",
+	"ck2_mmpll2_d5_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_univpll2_d7",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mmpll2_d5",
+	"ck2_univpll2_d4",
+	"ck2_imgpll_d4",
+	"ck2_mmpll2_d4"
+};
+
+static const char * const ck2_camtm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_univpll2_d6_d4",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck2_univpll2_d6_d2"
+};
+
+static const char * const ck2_dpe_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_mmpll2_d5_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mmpll2_d5",
+	"ck2_imgpll_d4",
+	"ck2_mmpll2_d4"
+};
+
+static const char * const ck2_vdec_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d2",
+	"ck2_mainpll2_d4_d4",
+	"ck2_mainpll2_d7_d2",
+	"ck2_mainpll2_d6_d2",
+	"ck2_mainpll2_d5_d2",
+	"ck2_mainpll2_d9",
+	"ck2_mainpll2_d4_d2",
+	"ck2_mainpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_univpll2_d6",
+	"ck2_mainpll2_d5",
+	"ck2_mainpll2_d4",
+	"ck2_imgpll_d2"
+};
+
+static const char * const ck2_ccusys_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck_osc_d2",
+	"ck2_mmpll2_d5_d2",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d7",
+	"ck2_univpll2_d6",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mainpll2_d4",
+	"ck2_mainpll2_d3",
+	"ck2_univpll2_d3"
+};
+
+static const char * const ck2_ccutm_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_univpll2_d6_d4",
+	"ck_osc_d4",
+	"ck_osc_d3",
+	"ck2_univpll2_d6_d2"
+};
+
+static const char * const ck2_venc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_mainpll2_d5_d2",
+	"ck2_univpll2_d5_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck2_mmpll2_d9",
+	"ck2_univpll2_d4_d2",
+	"ck2_mmpll2_d4_d2",
+	"ck2_mainpll2_d6",
+	"ck2_univpll2_d6",
+	"ck2_mainpll2_d5",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mainpll2_d4",
+	"ck2_univpll2_d4",
+	"ck2_univpll2_d3"
+};
+
+static const char * const ck2_dp1_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_tvdpll2_d16",
+	"ck2_tvdpll2_d8",
+	"ck2_tvdpll2_d4",
+	"ck2_tvdpll2_d2"
+};
+
+static const char * const ck2_dp0_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_tvdpll1_d16",
+	"ck2_tvdpll1_d8",
+	"ck2_tvdpll1_d4",
+	"ck_tvdpll1_d2"
+};
+
+static const char * const ck2_disp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d4_d2",
+	"ck_mainpll_d6",
+	"ck2_mainpll2_d5",
+	"ck2_mmpll2_d6",
+	"ck2_mainpll2_d4",
+	"ck2_univpll2_d4",
+	"ck2_mainpll2_d3"
+};
+
+static const char * const ck2_mdp_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_mainpll_d5_d2",
+	"ck2_mainpll2_d5_d2",
+	"ck2_mmpll2_d6_d2",
+	"ck2_mainpll2_d9",
+	"ck2_mainpll2_d4_d2",
+	"ck2_mainpll2_d7",
+	"ck2_mainpll2_d6",
+	"ck2_mainpll2_d5",
+	"ck2_mmpll2_d6",
+	"ck2_mainpll2_d4",
+	"ck2_univpll2_d4",
+	"ck2_mainpll2_d3"
+};
+
+static const char * const ck2_mminfra_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d5_d2",
+	"ck_mainpll_d9",
+	"ck2_mmpll2_d6_d2",
+	"ck2_mainpll2_d4_d2",
+	"ck_mainpll_d6",
+	"ck2_univpll2_d6",
+	"ck2_mainpll2_d5",
+	"ck2_mmpll2_d6",
+	"ck2_univpll2_d5",
+	"ck2_mainpll2_d4",
+	"ck2_univpll2_d4",
+	"ck2_mainpll2_d3",
+	"ck2_univpll2_d3"
+};
+
+static const char * const ck2_mminfra_snoc_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d7_d2",
+	"ck_mainpll_d9",
+	"ck_mainpll_d7",
+	"ck_mainpll_d6",
+	"ck2_mmpll2_d4_d2",
+	"ck_mainpll_d5",
+	"ck_mainpll_d4",
+	"ck2_univpll2_d4",
+	"ck2_mmpll2_d4",
+	"ck2_mainpll2_d3",
+	"ck2_univpll2_d3",
+	"ck2_mmpll2_d3",
+	"ck2_mainpll2_d2"
+};
+
+static const char * const ck2_mmup_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_mainpll2_d6",
+	"ck2_mainpll2_d5",
+	"ck_osc_d2",
+	"ck_osc",
+	"ck_mainpll_d4",
+	"ck2_univpll2_d4",
+	"ck2_mainpll2_d3"
+};
+
+static const char * const ck2_mminfra_ao_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck_osc_d4",
+	"ck_mainpll_d3"
+};
+
+static const char * const ck2_dvo_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_tvdpll3_d16",
+	"ck2_tvdpll3_d8",
+	"ck2_tvdpll3_d4",
+	"ck2_tvdpll3_d2"
+};
+
+static const char * const ck2_dvo_favt_parents[] = {
+	"ck_tck_26m_mx9_ck",
+	"ck2_tvdpll3_d16",
+	"ck2_tvdpll3_d8",
+	"ck2_tvdpll3_d4",
+	"ck_apll1_ck",
+	"ck_apll2_ck",
+	"ck2_tvdpll3_d2"
+};
+
+static const struct mtk_mux ck2_muxes[] = {
+	/* CKSYS2_CLK_CFG_0 */
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF0_SEL, "ck2_seninf0_sel", ck2_seninf0_parents,
+		CKSYS2_CLK_CFG_0, CKSYS2_CLK_CFG_0_SET, CKSYS2_CLK_CFG_0_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_30_DONE, MM_VOTE_CG_30_SET, MM_VOTE_CG_30_CLR,
+		0, 4, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF0_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 31),
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF1_SEL, "ck2_seninf1_sel", ck2_seninf1_parents,
+		CKSYS2_CLK_CFG_0, CKSYS2_CLK_CFG_0_SET, CKSYS2_CLK_CFG_0_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_30_DONE, MM_VOTE_CG_30_SET, MM_VOTE_CG_30_CLR,
+		8, 4, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF1_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 30),
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF2_SEL, "ck2_seninf2_sel", ck2_seninf2_parents,
+		CKSYS2_CLK_CFG_0, CKSYS2_CLK_CFG_0_SET, CKSYS2_CLK_CFG_0_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_30_DONE, MM_VOTE_CG_30_SET, MM_VOTE_CG_30_CLR,
+		16, 4, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF2_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 29),
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF3_SEL, "ck2_seninf3_sel", ck2_seninf3_parents,
+		CKSYS2_CLK_CFG_0, CKSYS2_CLK_CFG_0_SET, CKSYS2_CLK_CFG_0_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_30_DONE, MM_VOTE_CG_30_SET, MM_VOTE_CG_30_CLR,
+		24, 4, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF3_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 28),
+	/* CKSYS2_CLK_CFG_1 */
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF4_SEL, "ck2_seninf4_sel", ck2_seninf4_parents,
+		CKSYS2_CLK_CFG_1, CKSYS2_CLK_CFG_1_SET, CKSYS2_CLK_CFG_1_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_31_DONE, MM_VOTE_CG_31_SET, MM_VOTE_CG_31_CLR,
+		0, 4, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF4_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 27),
+	MUX_MULT_VOTE_FENC(CLK_CK2_SENINF5_SEL, "ck2_seninf5_sel", ck2_seninf5_parents,
+		CKSYS2_CLK_CFG_1, CKSYS2_CLK_CFG_1_SET, CKSYS2_CLK_CFG_1_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_31_DONE, MM_VOTE_CG_31_SET, MM_VOTE_CG_31_CLR,
+		8, 4, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_SENINF5_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 26),
+	MUX_MULT_VOTE_FENC(CLK_CK2_IMG1_SEL, "ck2_img1_sel", ck2_img1_parents,
+		CKSYS2_CLK_CFG_1, CKSYS2_CLK_CFG_1_SET, CKSYS2_CLK_CFG_1_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_31_DONE, MM_VOTE_CG_31_SET, MM_VOTE_CG_31_CLR,
+		16, 4, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_IMG1_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 25),
+	MUX_MULT_VOTE_FENC(CLK_CK2_IPE_SEL, "ck2_ipe_sel", ck2_ipe_parents,
+		CKSYS2_CLK_CFG_1, CKSYS2_CLK_CFG_1_SET, CKSYS2_CLK_CFG_1_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_31_DONE, MM_VOTE_CG_31_SET, MM_VOTE_CG_31_CLR,
+		24, 4, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_IPE_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 24),
+	/* CKSYS2_CLK_CFG_2 */
+	MUX_MULT_VOTE_FENC(CLK_CK2_CAM_SEL, "ck2_cam_sel", ck2_cam_parents,
+		CKSYS2_CLK_CFG_2, CKSYS2_CLK_CFG_2_SET, CKSYS2_CLK_CFG_2_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_32_DONE, MM_VOTE_CG_32_SET, MM_VOTE_CG_32_CLR,
+		0, 4, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_CAM_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 23),
+	MUX_MULT_VOTE_FENC(CLK_CK2_CAMTM_SEL, "ck2_camtm_sel", ck2_camtm_parents,
+		CKSYS2_CLK_CFG_2, CKSYS2_CLK_CFG_2_SET, CKSYS2_CLK_CFG_2_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_32_DONE, MM_VOTE_CG_32_SET, MM_VOTE_CG_32_CLR,
+		8, 3, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_CAMTM_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 22),
+	MUX_MULT_VOTE_FENC(CLK_CK2_DPE_SEL, "ck2_dpe_sel", ck2_dpe_parents,
+		CKSYS2_CLK_CFG_2, CKSYS2_CLK_CFG_2_SET, CKSYS2_CLK_CFG_2_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_32_DONE, MM_VOTE_CG_32_SET, MM_VOTE_CG_32_CLR,
+		16, 4, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DPE_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 21),
+	MUX_MULT_VOTE_FENC(CLK_CK2_VDEC_SEL, "ck2_vdec_sel", ck2_vdec_parents,
+		CKSYS2_CLK_CFG_2, CKSYS2_CLK_CFG_2_SET, CKSYS2_CLK_CFG_2_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_32_DONE, MM_VOTE_CG_32_SET, MM_VOTE_CG_32_CLR,
+		24, 4, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_VDEC_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 20),
+	/* CKSYS2_CLK_CFG_3 */
+	MUX_MULT_VOTE_FENC(CLK_CK2_CCUSYS_SEL, "ck2_ccusys_sel", ck2_ccusys_parents,
+		CKSYS2_CLK_CFG_3, CKSYS2_CLK_CFG_3_SET, CKSYS2_CLK_CFG_3_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_33_DONE, MM_VOTE_CG_33_SET, MM_VOTE_CG_33_CLR,
+		0, 4, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_CCUSYS_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 19),
+	MUX_MULT_VOTE_FENC(CLK_CK2_CCUTM_SEL, "ck2_ccutm_sel", ck2_ccutm_parents,
+		CKSYS2_CLK_CFG_3, CKSYS2_CLK_CFG_3_SET, CKSYS2_CLK_CFG_3_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_33_DONE, MM_VOTE_CG_33_SET, MM_VOTE_CG_33_CLR,
+		8, 3, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_CCUTM_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 18),
+	MUX_MULT_VOTE_FENC(CLK_CK2_VENC_SEL, "ck2_venc_sel", ck2_venc_parents,
+		CKSYS2_CLK_CFG_3, CKSYS2_CLK_CFG_3_SET, CKSYS2_CLK_CFG_3_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_33_DONE, MM_VOTE_CG_33_SET, MM_VOTE_CG_33_CLR,
+		16, 4, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_VENC_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 17),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK2_DVO_SEL, "ck2_dvo_sel", ck2_dvo_parents,
+		CKSYS2_CLK_CFG_3, CKSYS2_CLK_CFG_3_SET, CKSYS2_CLK_CFG_3_CLR,
+		24, 3, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DVO_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 16),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK2_DVO_FAVT_SEL, "ck2_dvo_favt_sel", ck2_dvo_favt_parents,
+		CKSYS2_CLK_CFG_4, CKSYS2_CLK_CFG_4_SET, CKSYS2_CLK_CFG_4_CLR,
+		0, 3, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DVO_FAVT_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 15),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK2_DP1_SEL, "ck2_dp1_sel", ck2_dp1_parents,
+		CKSYS2_CLK_CFG_4, CKSYS2_CLK_CFG_4_SET, CKSYS2_CLK_CFG_4_CLR,
+		8, 3, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DP1_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 14),
+	MUX_GATE_FENC_CLR_SET_UPD(CLK_CK2_DP0_SEL, "ck2_dp0_sel", ck2_dp0_parents,
+		CKSYS2_CLK_CFG_4, CKSYS2_CLK_CFG_4_SET, CKSYS2_CLK_CFG_4_CLR,
+		16, 3, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DP0_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 13),
+	MUX_MULT_VOTE_FENC(CLK_CK2_DISP_SEL, "ck2_disp_sel", ck2_disp_parents,
+		CKSYS2_CLK_CFG_4, CKSYS2_CLK_CFG_4_SET, CKSYS2_CLK_CFG_4_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_34_DONE, MM_VOTE_CG_34_SET, MM_VOTE_CG_34_CLR,
+		24, 4, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_DISP_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 12),
+	/* CKSYS2_CLK_CFG_5 */
+	MUX_MULT_VOTE_FENC(CLK_CK2_MDP_SEL, "ck2_mdp_sel", ck2_mdp_parents,
+		CKSYS2_CLK_CFG_5, CKSYS2_CLK_CFG_5_SET, CKSYS2_CLK_CFG_5_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_35_DONE, MM_VOTE_CG_35_SET, MM_VOTE_CG_35_CLR,
+		0, 4, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_MDP_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 11),
+	MUX_MULT_VOTE_FENC(CLK_CK2_MMINFRA_SEL, "ck2_mminfra_sel", ck2_mminfra_parents,
+		CKSYS2_CLK_CFG_5, CKSYS2_CLK_CFG_5_SET, CKSYS2_CLK_CFG_5_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_35_DONE, MM_VOTE_CG_35_SET, MM_VOTE_CG_35_CLR,
+		8, 4, 15, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_MMINFRA_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 10),
+	MUX_MULT_VOTE_FENC(CLK_CK2_MMINFRA_SNOC_SEL, "ck2_mminfra_snoc_sel", ck2_mminfra_snoc_parents,
+		CKSYS2_CLK_CFG_5, CKSYS2_CLK_CFG_5_SET, CKSYS2_CLK_CFG_5_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_35_DONE, MM_VOTE_CG_35_SET, MM_VOTE_CG_35_CLR,
+		16, 4, 23, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_MMINFRA_SNOC_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 9),
+	MUX_MULT_VOTE_FENC(CLK_CK2_MMUP_SEL, "ck2_mmup_sel", ck2_mmup_parents,
+		CKSYS2_CLK_CFG_5, CKSYS2_CLK_CFG_5_SET, CKSYS2_CLK_CFG_5_CLR, "vote-regmap",
+		VOTE_CG_30_DONE, VOTE_CG_30_SET, VOTE_CG_30_CLR,
+		24, 3, 31, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_MMUP_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 8),
+	MUX_MULT_VOTE_FENC(CLK_CK2_MMINFRA_AO_SEL, "ck2_mminfra_ao_sel", ck2_mminfra_ao_parents,
+		CKSYS2_CLK_CFG_6, CKSYS2_CLK_CFG_6_SET, CKSYS2_CLK_CFG_6_CLR, "mm-vote-regmap",
+		MM_VOTE_CG_36_DONE, MM_VOTE_CG_36_SET, MM_VOTE_CG_36_CLR,
+		16, 2, 7, CKSYS2_CLK_CFG_UPDATE, TOP_MUX_MMINFRA_AO_SHIFT,
+		CKSYS2_CLK_FENC_STATUS_MON_0, 5),
+};
+
+static int clk_mt8196_ck2_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_CK2_NR_CLK);
+
+	mtk_clk_register_factors(ck2_divs, ARRAY_SIZE(ck2_divs), clk_data);
+
+	mtk_clk_register_muxes(&pdev->dev, ck2_muxes, ARRAY_SIZE(ck2_muxes), node,
+			       &mt8196_clk_ck2_lock, clk_data);
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev, "%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static void clk_mt8196_ck2_remove(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_muxes(ck2_muxes, ARRAY_SIZE(ck2_muxes), clk_data);
+	mtk_clk_unregister_factors(ck2_divs, ARRAY_SIZE(ck2_divs), clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8196_ck2[] = {
+	{ .compatible = "mediatek,mt8196-cksys_gp2", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_ck2_drv = {
+	.probe = clk_mt8196_ck2_probe,
+	.remove = clk_mt8196_ck2_remove,
+	.driver = {
+		.name = "clk-mt8196-ck2",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_ck2,
+	},
+};
+
+module_platform_driver(clk_mt8196_ck2_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:08 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:08 +0800
Subject: [PATCH 12/26] clk: mediatek: Add MT8196 peripheral clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-13-guangjie.song@mediatek.com>

Add MT8196 peripheral clock controller which provides clock gate control
for dma/flashif/msdc/pwm/spi/uart.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile             |   3 +-
 drivers/clk/mediatek/clk-mt8196-peri_ao.c | 218 ++++++++++++++++++++++
 2 files changed, 220 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-peri_ao.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 583e5b9a7d40..c95e45356b78 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -151,7 +151,8 @@ obj-$(CONFIG_COMMON_CLK_MT8195_VENCSYS) += clk-mt8195-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
 obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o \
-				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o
+				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o \
+				   clk-mt8196-peri_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-peri_ao.c b/drivers/clk/mediatek/clk-mt8196-peri_ao.c
new file mode 100644
index 000000000000..775d77159641
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-peri_ao.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs perao0_cg_regs = {
+	.set_ofs = 0x24,
+	.clr_ofs = 0x28,
+	.sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs perao1_cg_regs = {
+	.set_ofs = 0x2c,
+	.clr_ofs = 0x30,
+	.sta_ofs = 0x14,
+};
+
+static const struct mtk_gate_regs perao1_vote_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x000c,
+	.sta_ofs = 0x2c04,
+};
+
+static const struct mtk_gate_regs perao2_cg_regs = {
+	.set_ofs = 0x34,
+	.clr_ofs = 0x38,
+	.sta_ofs = 0x18,
+};
+
+#define GATE_PERAO0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &perao0_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERAO0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_PERAO1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &perao1_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERAO1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_PERAO1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "vote-regmap",		\
+		.regs = &perao1_cg_regs,		\
+		.vote_regs = &perao1_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_PERAO2(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &perao2_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERAO2_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate perao_clks[] = {
+	/* PERAO0 */
+	GATE_PERAO0(CLK_PERAO_UART0_BCLK, "perao_uart0_bclk", "ck_uart_ck", 0),
+	GATE_PERAO0_V(CLK_PERAO_UART0_BCLK_UART, "perao_uart0_bclk_uart", "perao_uart0_bclk"),
+	GATE_PERAO0(CLK_PERAO_UART1_BCLK, "perao_uart1_bclk", "ck_uart_ck", 1),
+	GATE_PERAO0_V(CLK_PERAO_UART1_BCLK_UART, "perao_uart1_bclk_uart", "perao_uart1_bclk"),
+	GATE_PERAO0(CLK_PERAO_UART2_BCLK, "perao_uart2_bclk", "ck_uart_ck", 2),
+	GATE_PERAO0_V(CLK_PERAO_UART2_BCLK_UART, "perao_uart2_bclk_uart", "perao_uart2_bclk"),
+	GATE_PERAO0(CLK_PERAO_UART3_BCLK, "perao_uart3_bclk", "ck_uart_ck", 3),
+	GATE_PERAO0_V(CLK_PERAO_UART3_BCLK_UART, "perao_uart3_bclk_uart", "perao_uart3_bclk"),
+	GATE_PERAO0(CLK_PERAO_UART4_BCLK, "perao_uart4_bclk", "ck_uart_ck", 4),
+	GATE_PERAO0_V(CLK_PERAO_UART4_BCLK_UART, "perao_uart4_bclk_uart", "perao_uart4_bclk"),
+	GATE_PERAO0(CLK_PERAO_UART5_BCLK, "perao_uart5_bclk", "ck_uart_ck", 5),
+	GATE_PERAO0_V(CLK_PERAO_UART5_BCLK_UART, "perao_uart5_bclk_uart", "perao_uart5_bclk"),
+	GATE_PERAO0(CLK_PERAO_PWM_X16W_HCLK, "perao_pwm_x16w", "ck_p_axi_ck", 12),
+	GATE_PERAO0_V(CLK_PERAO_PWM_X16W_HCLK_PWM, "perao_pwm_x16w_pwm", "perao_pwm_x16w"),
+	GATE_PERAO0(CLK_PERAO_PWM_X16W_BCLK, "perao_pwm_x16w_bclk", "ck_pwm_ck", 13),
+	GATE_PERAO0_V(CLK_PERAO_PWM_X16W_BCLK_PWM, "perao_pwm_x16w_bclk_pwm",
+		      "perao_pwm_x16w_bclk"),
+	GATE_PERAO0(CLK_PERAO_PWM_PWM_BCLK0, "perao_pwm_pwm_bclk0", "ck_pwm_ck", 14),
+	GATE_PERAO0_V(CLK_PERAO_PWM_PWM_BCLK0_PWM, "perao_pwm_pwm_bclk0_pwm",
+		      "perao_pwm_pwm_bclk0"),
+	GATE_PERAO0(CLK_PERAO_PWM_PWM_BCLK1, "perao_pwm_pwm_bclk1", "ck_pwm_ck", 15),
+	GATE_PERAO0_V(CLK_PERAO_PWM_PWM_BCLK1_PWM, "perao_pwm_pwm_bclk1_pwm",
+		      "perao_pwm_pwm_bclk1"),
+	GATE_PERAO0(CLK_PERAO_PWM_PWM_BCLK2, "perao_pwm_pwm_bclk2", "ck_pwm_ck", 16),
+	GATE_PERAO0_V(CLK_PERAO_PWM_PWM_BCLK2_PWM, "perao_pwm_pwm_bclk2_pwm",
+		      "perao_pwm_pwm_bclk2"),
+	GATE_PERAO0(CLK_PERAO_PWM_PWM_BCLK3, "perao_pwm_pwm_bclk3", "ck_pwm_ck", 17),
+	GATE_PERAO0_V(CLK_PERAO_PWM_PWM_BCLK3_PWM, "perao_pwm_pwm_bclk3_pwm",
+		      "perao_pwm_pwm_bclk3"),
+	/* PERAO1 */
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI0_BCLK, "perao_spi0_bclk", "ck_spi0_b_ck", 0),
+	GATE_PERAO1_V(CLK_PERAO_SPI0_BCLK_SPI, "perao_spi0_bclk_spi", "perao_spi0_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI1_BCLK, "perao_spi1_bclk", "ck_spi1_b_ck", 2),
+	GATE_PERAO1_V(CLK_PERAO_SPI1_BCLK_SPI, "perao_spi1_bclk_spi", "perao_spi1_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI2_BCLK, "perao_spi2_bclk", "ck_spi2_b_ck", 3),
+	GATE_PERAO1_V(CLK_PERAO_SPI2_BCLK_SPI, "perao_spi2_bclk_spi", "perao_spi2_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI3_BCLK, "perao_spi3_bclk", "ck_spi3_b_ck", 4),
+	GATE_PERAO1_V(CLK_PERAO_SPI3_BCLK_SPI, "perao_spi3_bclk_spi", "perao_spi3_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI4_BCLK, "perao_spi4_bclk", "ck_spi4_b_ck", 5),
+	GATE_PERAO1_V(CLK_PERAO_SPI4_BCLK_SPI, "perao_spi4_bclk_spi", "perao_spi4_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI5_BCLK, "perao_spi5_bclk", "ck_spi5_b_ck", 6),
+	GATE_PERAO1_V(CLK_PERAO_SPI5_BCLK_SPI, "perao_spi5_bclk_spi", "perao_spi5_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI6_BCLK, "perao_spi6_bclk", "ck_spi6_b_ck", 7),
+	GATE_PERAO1_V(CLK_PERAO_SPI6_BCLK_SPI, "perao_spi6_bclk_spi", "perao_spi6_bclk"),
+	GATE_VOTE_PERAO1(CLK_PERAO_SPI7_BCLK, "perao_spi7_bclk", "ck_spi7_b_ck", 8),
+	GATE_PERAO1_V(CLK_PERAO_SPI7_BCLK_SPI, "perao_spi7_bclk_spi", "perao_spi7_bclk"),
+	GATE_PERAO1(CLK_PERAO_FLASHIF_FLASH, "perao_flashif_flash", "ck_sflash_ck", 18),
+	GATE_PERAO1_V(CLK_PERAO_FLASHIF_FLASH_FLASHIF, "perao_flashif_flash_flashif",
+		      "perao_flashif_flash"),
+	GATE_PERAO1(CLK_PERAO_FLASHIF_27M, "perao_flashif_27m", "ck_sflash_ck", 19),
+	GATE_PERAO1_V(CLK_PERAO_FLASHIF_27M_FLASHIF, "perao_flashif_27m_flashif",
+		      "perao_flashif_27m"),
+	GATE_PERAO1(CLK_PERAO_FLASHIF_DRAM, "perao_flashif_dram", "ck_p_axi_ck", 20),
+	GATE_PERAO1_V(CLK_PERAO_FLASHIF_DRAM_FLASHIF, "perao_flashif_dram_flashif",
+		      "perao_flashif_dram"),
+	GATE_PERAO1(CLK_PERAO_FLASHIF_AXI, "perao_flashif_axi", "ck_p_axi_ck", 21),
+	GATE_PERAO1_V(CLK_PERAO_FLASHIF_AXI_FLASHIF, "perao_flashif_axi_flashif",
+		      "perao_flashif_axi"),
+	GATE_PERAO1(CLK_PERAO_FLASHIF_BCLK, "perao_flashif_bclk", "ck_p_axi_ck", 22),
+	GATE_PERAO1_V(CLK_PERAO_FLASHIF_BCLK_FLASHIF, "perao_flashif_bclk_flashif",
+		      "perao_flashif_bclk"),
+	GATE_PERAO1(CLK_PERAO_AP_DMA_X32W_BCLK, "perao_ap_dma_x32w_bclk", "ck_p_axi_ck", 26),
+	GATE_PERAO1_V(CLK_PERAO_AP_DMA_X32W_BCLK_UART, "perao_ap_dma_x32w_bclk_uart",
+		      "perao_ap_dma_x32w_bclk"),
+	GATE_PERAO1_V(CLK_PERAO_AP_DMA_X32W_BCLK_I2C, "perao_ap_dma_x32w_bclk_i2c",
+		      "perao_ap_dma_x32w_bclk"),
+	/* PERAO2 */
+	GATE_PERAO2(CLK_PERAO_MSDC1_MSDC_SRC, "perao_msdc1_msdc_src", "ck_msdc30_1_ck", 1),
+	GATE_PERAO2_V(CLK_PERAO_MSDC1_MSDC_SRC_MSDC1, "perao_msdc1_msdc_src_msdc1",
+		      "perao_msdc1_msdc_src"),
+	GATE_PERAO2(CLK_PERAO_MSDC1_HCLK, "perao_msdc1", "ck_msdc30_1_ck", 2),
+	GATE_PERAO2_V(CLK_PERAO_MSDC1_HCLK_MSDC1, "perao_msdc1_msdc1", "perao_msdc1"),
+	GATE_PERAO2(CLK_PERAO_MSDC1_AXI, "perao_msdc1_axi", "ck_p_axi_ck", 3),
+	GATE_PERAO2_V(CLK_PERAO_MSDC1_AXI_MSDC1, "perao_msdc1_axi_msdc1", "perao_msdc1_axi"),
+	GATE_PERAO2(CLK_PERAO_MSDC1_HCLK_WRAP, "perao_msdc1_h_wrap", "ck_p_axi_ck", 4),
+	GATE_PERAO2_V(CLK_PERAO_MSDC1_HCLK_WRAP_MSDC1, "perao_msdc1_h_wrap_msdc1",
+		      "perao_msdc1_h_wrap"),
+	GATE_PERAO2(CLK_PERAO_MSDC2_MSDC_SRC, "perao_msdc2_msdc_src", "ck_msdc30_2_ck", 10),
+	GATE_PERAO2_V(CLK_PERAO_MSDC2_MSDC_SRC_MSDC2, "perao_msdc2_msdc_src_msdc2",
+		      "perao_msdc2_msdc_src"),
+	GATE_PERAO2(CLK_PERAO_MSDC2_HCLK, "perao_msdc2", "ck_msdc30_2_ck", 11),
+	GATE_PERAO2_V(CLK_PERAO_MSDC2_HCLK_MSDC2, "perao_msdc2_msdc2", "perao_msdc2"),
+	GATE_PERAO2(CLK_PERAO_MSDC2_AXI, "perao_msdc2_axi", "ck_p_axi_ck", 12),
+	GATE_PERAO2_V(CLK_PERAO_MSDC2_AXI_MSDC2, "perao_msdc2_axi_msdc2", "perao_msdc2_axi"),
+	GATE_PERAO2(CLK_PERAO_MSDC2_HCLK_WRAP, "perao_msdc2_h_wrap", "ck_p_axi_ck", 13),
+	GATE_PERAO2_V(CLK_PERAO_MSDC2_HCLK_WRAP_MSDC2, "perao_msdc2_h_wrap_msdc2",
+		      "perao_msdc2_h_wrap"),
+};
+
+static const struct mtk_clk_desc perao_mcd = {
+	.clks = perao_clks,
+	.num_clks = ARRAY_SIZE(perao_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8196_peri_ao[] = {
+	{ .compatible = "mediatek,mt8196-pericfg_ao", .data = &perao_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_peri_ao_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-peri_ao",
+		.of_match_table = of_match_clk_mt8196_peri_ao,
+	},
+};
+
+module_platform_driver(clk_mt8196_peri_ao_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:16 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:16 +0800
Subject: [PATCH 20/26] clk: mediatek: Add MT8196 disp-ao clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-21-guangjie.song@mediatek.com>

Add MT8196 disp-ao clock controller which provides clock gate control in
display system. This is integrated with mtk-mmsys driver which will
populate device by platform_device_register_data to start disp-ao clock
driver.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile              |   2 +-
 drivers/clk/mediatek/clk-mt8196-vdisp_ao.c | 100 +++++++++++++++++++++
 2 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vdisp_ao.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 7eb4af39029c..fab6a0944501 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -158,7 +158,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
-obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-vdisp_ao.c b/drivers/clk/mediatek/clk-mt8196-vdisp_ao.c
new file mode 100644
index 000000000000..6965c30dad4c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-vdisp_ao.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs mm_v_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm_v_vote_regs = {
+	.set_ofs = 0x0030,
+	.clr_ofs = 0x0034,
+	.sta_ofs = 0x2c18,
+};
+
+#define GATE_MM_V(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mm_v_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MM_V_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_MM_AO_V(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mm_v_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_enable,	\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VOTE_MM_V(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &mm_v_cg_regs,			\
+		.vote_regs = &mm_v_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate mm_v_clks[] = {
+	GATE_VOTE_MM_V(CLK_MM_V_DISP_VDISP_AO_CONFIG, "mm_v_disp_vdisp_ao_config", "ck2_disp_ck", 0),
+	GATE_MM_V_V(CLK_MM_V_DISP_VDISP_AO_CONFIG_DISP, "mm_v_disp_vdisp_ao_config_disp",
+		    "mm_v_disp_vdisp_ao_config"),
+	GATE_VOTE_MM_V(CLK_MM_V_DISP_DPC, "mm_v_disp_dpc", "ck2_disp_ck", 16),
+	GATE_MM_V_V(CLK_MM_V_DISP_DPC_DISP, "mm_v_disp_dpc_disp", "mm_v_disp_dpc"),
+	GATE_MM_AO_V(CLK_MM_V_SMI_SUB_SOMM0, "mm_v_smi_sub_somm0", "ck2_disp_ck", 2),
+	GATE_MM_V_V(CLK_MM_V_SMI_SUB_SOMM0_SMI, "mm_v_smi_sub_somm0_smi", "mm_v_smi_sub_somm0"),
+};
+
+static const struct mtk_clk_desc mm_v_mcd = {
+	.clks = mm_v_clks,
+	.num_clks = ARRAY_SIZE(mm_v_clks),
+};
+
+static const struct platform_device_id clk_mt8196_vdisp_ao_id_table[] = {
+	{ .name = "clk-mt8196-vdisp_ao", .driver_data = (kernel_ulong_t)&mm_v_mcd },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, clk_mt8196_vdisp_ao_id_table);
+
+static struct platform_driver clk_mt8196_vdisp_ao_drv = {
+	.probe = mtk_clk_pdev_probe,
+	.remove = mtk_clk_pdev_remove,
+	.driver = {
+		.name = "clk-mt8196-vdisp_ao",
+	},
+	.id_table = clk_mt8196_vdisp_ao_id_table,
+};
+
+module_platform_driver(clk_mt8196_vdisp_ao_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:20 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:20 +0800
Subject: [PATCH 24/26] clk: mediatek: Add MT8196 ufssys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-25-guangjie.song@mediatek.com>

Add MT8196 ufssys clock controller which provides clock gate control
for ufs.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig             |   7 ++
 drivers/clk/mediatek/Makefile            |   1 +
 drivers/clk/mediatek/clk-mt8196-ufs_ao.c | 107 +++++++++++++++++++++++
 3 files changed, 115 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ufs_ao.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 2aafba083835..5fc24f52762a 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1059,6 +1059,13 @@ config COMMON_CLK_MT8196_PEXTPSYS
 	help
 	  This driver supports MediaTek MT8196 pextpsys clocks.
 
+config COMMON_CLK_MT8196_UFSSYS
+	tristate "Clock driver for MediaTek MT8196 ufssys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 ufssys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 3058e7855ff3..e5b4a3a61ef7 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -161,6 +161,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o \
 					 clk-mt8196-ovl0.o clk-mt8196-ovl1.o
 obj-$(CONFIG_COMMON_CLK_MT8196_PEXTPSYS) += clk-mt8196-pextp.o
+obj-$(CONFIG_COMMON_CLK_MT8196_UFSSYS) += clk-mt8196-ufs_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-ufs_ao.c b/drivers/clk/mediatek/clk-mt8196-ufs_ao.c
new file mode 100644
index 000000000000..107522759bd2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-ufs_ao.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs ufsao0_cg_regs = {
+	.set_ofs = 0x108,
+	.clr_ofs = 0x10c,
+	.sta_ofs = 0x104,
+};
+
+static const struct mtk_gate_regs ufsao1_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0xc,
+	.sta_ofs = 0x4,
+};
+
+#define GATE_UFSAO0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ufsao0_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_UFSAO0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_UFSAO1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ufsao1_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_UFSAO1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate ufsao_clks[] = {
+	/* UFSAO0 */
+	GATE_UFSAO0(CLK_UFSAO_UFSHCI_UFS, "ufsao_ufshci_ufs", "ck_ck", 0),
+	GATE_UFSAO0_V(CLK_UFSAO_UFSHCI_UFS_UFS, "ufsao_ufshci_ufs_ufs", "ufsao_ufshci_ufs"),
+	GATE_UFSAO0(CLK_UFSAO_UFSHCI_AES, "ufsao_ufshci_aes", "ck_aes_ufsfde_ck", 1),
+	GATE_UFSAO0_V(CLK_UFSAO_UFSHCI_AES_UFS, "ufsao_ufshci_aes_ufs", "ufsao_ufshci_aes"),
+	/* UFSAO1 */
+	GATE_UFSAO1(CLK_UFSAO_UNIPRO_TX_SYM, "ufsao_unipro_tx_sym", "ck_f26m_ck", 0),
+	GATE_UFSAO1_V(CLK_UFSAO_UNIPRO_TX_SYM_UFS, "ufsao_unipro_tx_sym_ufs",
+		      "ufsao_unipro_tx_sym"),
+	GATE_UFSAO1(CLK_UFSAO_UNIPRO_RX_SYM0, "ufsao_unipro_rx_sym0", "ck_f26m_ck", 1),
+	GATE_UFSAO1_V(CLK_UFSAO_UNIPRO_RX_SYM0_UFS, "ufsao_unipro_rx_sym0_ufs",
+		      "ufsao_unipro_rx_sym0"),
+	GATE_UFSAO1(CLK_UFSAO_UNIPRO_RX_SYM1, "ufsao_unipro_rx_sym1", "ck_f26m_ck", 2),
+	GATE_UFSAO1_V(CLK_UFSAO_UNIPRO_RX_SYM1_UFS, "ufsao_unipro_rx_sym1_ufs",
+		      "ufsao_unipro_rx_sym1"),
+	GATE_UFSAO1(CLK_UFSAO_UNIPRO_SYS, "ufsao_unipro_sys", "ck_ck", 3),
+	GATE_UFSAO1_V(CLK_UFSAO_UNIPRO_SYS_UFS, "ufsao_unipro_sys_ufs", "ufsao_unipro_sys"),
+	GATE_UFSAO1(CLK_UFSAO_UNIPRO_SAP, "ufsao_unipro_sap", "ck_f26m_ck", 4),
+	GATE_UFSAO1_V(CLK_UFSAO_UNIPRO_SAP_UFS, "ufsao_unipro_sap_ufs", "ufsao_unipro_sap"),
+	GATE_UFSAO1(CLK_UFSAO_PHY_SAP, "ufsao_phy_sap", "ck_f26m_ck", 8),
+	GATE_UFSAO1_V(CLK_UFSAO_PHY_SAP_UFS, "ufsao_phy_sap_ufs", "ufsao_phy_sap"),
+};
+
+static const struct mtk_clk_desc ufsao_mcd = {
+	.clks = ufsao_clks,
+	.num_clks = ARRAY_SIZE(ufsao_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8196_ufs_ao[] = {
+	{ .compatible = "mediatek,mt8196-ufscfg_ao", .data = &ufsao_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_ufs_ao_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-ufs_ao",
+		.of_match_table = of_match_clk_mt8196_ufs_ao,
+	},
+};
+
+module_platform_driver(clk_mt8196_ufs_ao_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:17 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:17 +0800
Subject: [PATCH 21/26] clk: mediatek: Add MT8196 ovl0 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-22-guangjie.song@mediatek.com>

Add MT8196 ovl0 clock controller which provides clock gate control in
display system. This is integrated with mtk-mmsys driver which will
populate device by platform_device_register_data to start ovl0 clock
driver.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile          |   3 +-
 drivers/clk/mediatek/clk-mt8196-ovl0.c | 256 +++++++++++++++++++++++++
 2 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ovl0.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index fab6a0944501..6766811e67d9 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -158,7 +158,8 @@ obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
-obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o \
+					 clk-mt8196-ovl0.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-ovl0.c b/drivers/clk/mediatek/clk-mt8196-ovl0.c
new file mode 100644
index 000000000000..5a9ae157ec35
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-ovl0.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+static const struct mtk_gate_regs ovl0_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs ovl0_vote_regs = {
+	.set_ofs = 0x0060,
+	.clr_ofs = 0x0064,
+	.sta_ofs = 0x2c30,
+};
+
+static const struct mtk_gate_regs ovl1_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs ovl1_vote_regs = {
+	.set_ofs = 0x0068,
+	.clr_ofs = 0x006c,
+	.sta_ofs = 0x2c34,
+};
+
+#define GATE_OVL0(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &ovl0_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_OVL0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_OVL0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ovl0_cg_regs,			\
+		.vote_regs = &ovl0_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_OVL1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ovl1_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_OVL1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_OVL1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ovl1_cg_regs,			\
+		.vote_regs = &ovl1_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate ovl_clks[] = {
+	/* OVL0 */
+	GATE_VOTE_OVL0(CLK_OVLSYS_CONFIG, "ovlsys_config", "ck2_disp_ck", 0),
+	GATE_OVL0_V(CLK_OVLSYS_CONFIG_DISP, "ovlsys_config_disp", "ovlsys_config"),
+	GATE_VOTE_OVL0(CLK_OVL_FAKE_ENG0, "ovl_fake_eng0", "ck2_disp_ck", 1),
+	GATE_OVL0_V(CLK_OVL_FAKE_ENG0_DISP, "ovl_fake_eng0_disp", "ovl_fake_eng0"),
+	GATE_VOTE_OVL0(CLK_OVL_FAKE_ENG1, "ovl_fake_eng1", "ck2_disp_ck", 2),
+	GATE_OVL0_V(CLK_OVL_FAKE_ENG1_DISP, "ovl_fake_eng1_disp", "ovl_fake_eng1"),
+	GATE_VOTE_OVL0(CLK_OVL_MUTEX0, "ovl_mutex0", "ck2_disp_ck", 3),
+	GATE_OVL0_V(CLK_OVL_MUTEX0_DISP, "ovl_mutex0_disp", "ovl_mutex0"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA0, "ovl_exdma0", "ck2_disp_ck", 4),
+	GATE_OVL0_V(CLK_OVL_EXDMA0_DISP, "ovl_exdma0_disp", "ovl_exdma0"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA1, "ovl_exdma1", "ck2_disp_ck", 5),
+	GATE_OVL0_V(CLK_OVL_EXDMA1_DISP, "ovl_exdma1_disp", "ovl_exdma1"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA2, "ovl_exdma2", "ck2_disp_ck", 6),
+	GATE_OVL0_V(CLK_OVL_EXDMA2_DISP, "ovl_exdma2_disp", "ovl_exdma2"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA3, "ovl_exdma3", "ck2_disp_ck", 7),
+	GATE_OVL0_V(CLK_OVL_EXDMA3_DISP, "ovl_exdma3_disp", "ovl_exdma3"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA4, "ovl_exdma4", "ck2_disp_ck", 8),
+	GATE_OVL0_V(CLK_OVL_EXDMA4_DISP, "ovl_exdma4_disp", "ovl_exdma4"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA5, "ovl_exdma5", "ck2_disp_ck", 9),
+	GATE_OVL0_V(CLK_OVL_EXDMA5_DISP, "ovl_exdma5_disp", "ovl_exdma5"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA6, "ovl_exdma6", "ck2_disp_ck", 10),
+	GATE_OVL0_V(CLK_OVL_EXDMA6_DISP, "ovl_exdma6_disp", "ovl_exdma6"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA7, "ovl_exdma7", "ck2_disp_ck", 11),
+	GATE_OVL0_V(CLK_OVL_EXDMA7_DISP, "ovl_exdma7_disp", "ovl_exdma7"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA8, "ovl_exdma8", "ck2_disp_ck", 12),
+	GATE_OVL0_V(CLK_OVL_EXDMA8_DISP, "ovl_exdma8_disp", "ovl_exdma8"),
+	GATE_VOTE_OVL0(CLK_OVL_EXDMA9, "ovl_exdma9", "ck2_disp_ck", 13),
+	GATE_OVL0_V(CLK_OVL_EXDMA9_DISP, "ovl_exdma9_disp", "ovl_exdma9"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER0, "ovl_blender0", "ck2_disp_ck", 14),
+	GATE_OVL0_V(CLK_OVL_BLENDER0_DISP, "ovl_blender0_disp", "ovl_blender0"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER1, "ovl_blender1", "ck2_disp_ck", 15),
+	GATE_OVL0_V(CLK_OVL_BLENDER1_DISP, "ovl_blender1_disp", "ovl_blender1"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER2, "ovl_blender2", "ck2_disp_ck", 16),
+	GATE_OVL0_V(CLK_OVL_BLENDER2_DISP, "ovl_blender2_disp", "ovl_blender2"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER3, "ovl_blender3", "ck2_disp_ck", 17),
+	GATE_OVL0_V(CLK_OVL_BLENDER3_DISP, "ovl_blender3_disp", "ovl_blender3"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER4, "ovl_blender4", "ck2_disp_ck", 18),
+	GATE_OVL0_V(CLK_OVL_BLENDER4_DISP, "ovl_blender4_disp", "ovl_blender4"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER5, "ovl_blender5", "ck2_disp_ck", 19),
+	GATE_OVL0_V(CLK_OVL_BLENDER5_DISP, "ovl_blender5_disp", "ovl_blender5"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER6, "ovl_blender6", "ck2_disp_ck", 20),
+	GATE_OVL0_V(CLK_OVL_BLENDER6_DISP, "ovl_blender6_disp", "ovl_blender6"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER7, "ovl_blender7", "ck2_disp_ck", 21),
+	GATE_OVL0_V(CLK_OVL_BLENDER7_DISP, "ovl_blender7_disp", "ovl_blender7"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER8, "ovl_blender8", "ck2_disp_ck", 22),
+	GATE_OVL0_V(CLK_OVL_BLENDER8_DISP, "ovl_blender8_disp", "ovl_blender8"),
+	GATE_VOTE_OVL0(CLK_OVL_BLENDER9, "ovl_blender9", "ck2_disp_ck", 23),
+	GATE_OVL0_V(CLK_OVL_BLENDER9_DISP, "ovl_blender9_disp", "ovl_blender9"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC0, "ovl_outproc0", "ck2_disp_ck", 24),
+	GATE_OVL0_V(CLK_OVL_OUTPROC0_DISP, "ovl_outproc0_disp", "ovl_outproc0"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC1, "ovl_outproc1", "ck2_disp_ck", 25),
+	GATE_OVL0_V(CLK_OVL_OUTPROC1_DISP, "ovl_outproc1_disp", "ovl_outproc1"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC2, "ovl_outproc2", "ck2_disp_ck", 26),
+	GATE_OVL0_V(CLK_OVL_OUTPROC2_DISP, "ovl_outproc2_disp", "ovl_outproc2"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC3, "ovl_outproc3", "ck2_disp_ck", 27),
+	GATE_OVL0_V(CLK_OVL_OUTPROC3_DISP, "ovl_outproc3_disp", "ovl_outproc3"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC4, "ovl_outproc4", "ck2_disp_ck", 28),
+	GATE_OVL0_V(CLK_OVL_OUTPROC4_DISP, "ovl_outproc4_disp", "ovl_outproc4"),
+	GATE_VOTE_OVL0(CLK_OVL_OUTPROC5, "ovl_outproc5", "ck2_disp_ck", 29),
+	GATE_OVL0_V(CLK_OVL_OUTPROC5_DISP, "ovl_outproc5_disp", "ovl_outproc5"),
+	GATE_VOTE_OVL0(CLK_OVL_MDP_RSZ0, "ovl_mdp_rsz0", "ck2_disp_ck", 30),
+	GATE_OVL0_V(CLK_OVL_MDP_RSZ0_DISP, "ovl_mdp_rsz0_disp", "ovl_mdp_rsz0"),
+	GATE_VOTE_OVL0(CLK_OVL_MDP_RSZ1, "ovl_mdp_rsz1", "ck2_disp_ck", 31),
+	GATE_OVL0_V(CLK_OVL_MDP_RSZ1_DISP, "ovl_mdp_rsz1_disp", "ovl_mdp_rsz1"),
+	/* OVL1 */
+	GATE_VOTE_OVL1(CLK_OVL_DISP_WDMA0, "ovl_disp_wdma0", "ck2_disp_ck", 0),
+	GATE_OVL1_V(CLK_OVL_DISP_WDMA0_DISP, "ovl_disp_wdma0_disp", "ovl_disp_wdma0"),
+	GATE_VOTE_OVL1(CLK_OVL_DISP_WDMA1, "ovl_disp_wdma1", "ck2_disp_ck", 1),
+	GATE_OVL1_V(CLK_OVL_DISP_WDMA1_DISP, "ovl_disp_wdma1_disp", "ovl_disp_wdma1"),
+	GATE_VOTE_OVL1(CLK_OVL_UFBC_WDMA0, "ovl_ufbc_wdma0", "ck2_disp_ck", 2),
+	GATE_OVL1_V(CLK_OVL_UFBC_WDMA0_DISP, "ovl_ufbc_wdma0_disp", "ovl_ufbc_wdma0"),
+	GATE_VOTE_OVL1(CLK_OVL_MDP_RDMA0, "ovl_mdp_rdma0", "ck2_disp_ck", 3),
+	GATE_OVL1_V(CLK_OVL_MDP_RDMA0_DISP, "ovl_mdp_rdma0_disp", "ovl_mdp_rdma0"),
+	GATE_VOTE_OVL1(CLK_OVL_MDP_RDMA1, "ovl_mdp_rdma1", "ck2_disp_ck", 4),
+	GATE_OVL1_V(CLK_OVL_MDP_RDMA1_DISP, "ovl_mdp_rdma1_disp", "ovl_mdp_rdma1"),
+	GATE_VOTE_OVL1(CLK_OVL_BWM0, "ovl_bwm0", "ck2_disp_ck", 5),
+	GATE_OVL1_V(CLK_OVL_BWM0_DISP, "ovl_bwm0_disp", "ovl_bwm0"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI0, "ovl_dli0", "ck2_disp_ck", 6),
+	GATE_OVL1_V(CLK_OVL_DLI0_DISP, "ovl_dli0_disp", "ovl_dli0"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI1, "ovl_dli1", "ck2_disp_ck", 7),
+	GATE_OVL1_V(CLK_OVL_DLI1_DISP, "ovl_dli1_disp", "ovl_dli1"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI2, "ovl_dli2", "ck2_disp_ck", 8),
+	GATE_OVL1_V(CLK_OVL_DLI2_DISP, "ovl_dli2_disp", "ovl_dli2"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI3, "ovl_dli3", "ck2_disp_ck", 9),
+	GATE_OVL1_V(CLK_OVL_DLI3_DISP, "ovl_dli3_disp", "ovl_dli3"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI4, "ovl_dli4", "ck2_disp_ck", 10),
+	GATE_OVL1_V(CLK_OVL_DLI4_DISP, "ovl_dli4_disp", "ovl_dli4"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI5, "ovl_dli5", "ck2_disp_ck", 11),
+	GATE_OVL1_V(CLK_OVL_DLI5_DISP, "ovl_dli5_disp", "ovl_dli5"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI6, "ovl_dli6", "ck2_disp_ck", 12),
+	GATE_OVL1_V(CLK_OVL_DLI6_DISP, "ovl_dli6_disp", "ovl_dli6"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI7, "ovl_dli7", "ck2_disp_ck", 13),
+	GATE_OVL1_V(CLK_OVL_DLI7_DISP, "ovl_dli7_disp", "ovl_dli7"),
+	GATE_VOTE_OVL1(CLK_OVL_DLI8, "ovl_dli8", "ck2_disp_ck", 14),
+	GATE_OVL1_V(CLK_OVL_DLI8_DISP, "ovl_dli8_disp", "ovl_dli8"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO0, "ovl_dlo0", "ck2_disp_ck", 15),
+	GATE_OVL1_V(CLK_OVL_DLO0_DISP, "ovl_dlo0_disp", "ovl_dlo0"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO1, "ovl_dlo1", "ck2_disp_ck", 16),
+	GATE_OVL1_V(CLK_OVL_DLO1_DISP, "ovl_dlo1_disp", "ovl_dlo1"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO2, "ovl_dlo2", "ck2_disp_ck", 17),
+	GATE_OVL1_V(CLK_OVL_DLO2_DISP, "ovl_dlo2_disp", "ovl_dlo2"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO3, "ovl_dlo3", "ck2_disp_ck", 18),
+	GATE_OVL1_V(CLK_OVL_DLO3_DISP, "ovl_dlo3_disp", "ovl_dlo3"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO4, "ovl_dlo4", "ck2_disp_ck", 19),
+	GATE_OVL1_V(CLK_OVL_DLO4_DISP, "ovl_dlo4_disp", "ovl_dlo4"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO5, "ovl_dlo5", "ck2_disp_ck", 20),
+	GATE_OVL1_V(CLK_OVL_DLO5_DISP, "ovl_dlo5_disp", "ovl_dlo5"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO6, "ovl_dlo6", "ck2_disp_ck", 21),
+	GATE_OVL1_V(CLK_OVL_DLO6_DISP, "ovl_dlo6_disp", "ovl_dlo6"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO7, "ovl_dlo7", "ck2_disp_ck", 22),
+	GATE_OVL1_V(CLK_OVL_DLO7_DISP, "ovl_dlo7_disp", "ovl_dlo7"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO8, "ovl_dlo8", "ck2_disp_ck", 23),
+	GATE_OVL1_V(CLK_OVL_DLO8_DISP, "ovl_dlo8_disp", "ovl_dlo8"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO9, "ovl_dlo9", "ck2_disp_ck", 24),
+	GATE_OVL1_V(CLK_OVL_DLO9_DISP, "ovl_dlo9_disp", "ovl_dlo9"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO10, "ovl_dlo10", "ck2_disp_ck", 25),
+	GATE_OVL1_V(CLK_OVL_DLO10_DISP, "ovl_dlo10_disp", "ovl_dlo10"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO11, "ovl_dlo11", "ck2_disp_ck", 26),
+	GATE_OVL1_V(CLK_OVL_DLO11_DISP, "ovl_dlo11_disp", "ovl_dlo11"),
+	GATE_VOTE_OVL1(CLK_OVL_DLO12, "ovl_dlo12", "ck2_disp_ck", 27),
+	GATE_OVL1_V(CLK_OVL_DLO12_DISP, "ovl_dlo12_disp", "ovl_dlo12"),
+	GATE_VOTE_OVL1(CLK_OVLSYS_RELAY0, "ovlsys_relay0", "ck2_disp_ck", 28),
+	GATE_OVL1_V(CLK_OVLSYS_RELAY0_DISP, "ovlsys_relay0_disp", "ovlsys_relay0"),
+	GATE_VOTE_OVL1(CLK_OVL_INLINEROT0, "ovl_inlinerot0", "ck2_disp_ck", 29),
+	GATE_OVL1_V(CLK_OVL_INLINEROT0_DISP, "ovl_inlinerot0_disp", "ovl_inlinerot0"),
+	GATE_VOTE_OVL1(CLK_OVL_SMI, "ovl_smi", "ck2_disp_ck", 30),
+	GATE_OVL1_V(CLK_OVL_SMI_SMI, "ovl_smi_smi", "ovl_smi"),
+};
+
+static const struct mtk_clk_desc ovl_mcd = {
+	.clks = ovl_clks,
+	.num_clks = ARRAY_SIZE(ovl_clks),
+};
+
+static const struct platform_device_id clk_mt8196_ovl0_id_table[] = {
+	{ .name = "clk-mt8196-ovl0", .driver_data = (kernel_ulong_t)&ovl_mcd },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, clk_mt8196_ovl0_id_table);
+
+static struct platform_driver clk_mt8196_ovl0_drv = {
+	.probe = mtk_clk_pdev_probe,
+	.remove = mtk_clk_pdev_remove,
+	.driver = {
+		.name = "clk-mt8196-ovl0",
+	},
+	.id_table = clk_mt8196_ovl0_id_table,
+};
+
+module_platform_driver(clk_mt8196_ovl0_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:14 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:14 +0800
Subject: [PATCH 18/26] clk: mediatek: Add MT8196 disp0 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-19-guangjie.song@mediatek.com>

Add MT8196 disp0 clock controller which provides clock gate control in
display system. This is integrated with mtk-mmsys driver which will
populate device by platform_device_register_data to start disp0 clock
driver.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig            |   7 +
 drivers/clk/mediatek/Makefile           |   1 +
 drivers/clk/mediatek/clk-mt8196-disp0.c | 247 ++++++++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-disp0.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 042de08e0bb1..dcb660d45bcf 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1045,6 +1045,13 @@ config COMMON_CLK_MT8196_MFGCFG
 	help
 	  This driver supports MediaTek MT8196 mfgcfg clocks.
 
+config COMMON_CLK_MT8196_MMSYS
+	tristate "Clock driver for MediaTek MT8196 mmsys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 mmsys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index ad2de9ee6d15..881061f1e259 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -158,6 +158,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-disp0.c b/drivers/clk/mediatek/clk-mt8196-disp0.c
new file mode 100644
index 000000000000..07237a51358f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-disp0.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm0_vote_regs = {
+	.set_ofs = 0x0020,
+	.clr_ofs = 0x0024,
+	.sta_ofs = 0x2c10,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mm1_vote_regs = {
+	.set_ofs = 0x0028,
+	.clr_ofs = 0x002c,
+	.sta_ofs = 0x2c14,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mm0_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MM0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_MM0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &mm0_cg_regs,			\
+		.vote_regs = &mm0_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE		\
+	}
+
+#define GATE_MM1(_id, _name, _parent, _shift) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mm1_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MM1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_MM1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &mm1_cg_regs,			\
+		.vote_regs = &mm1_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate mm_clks[] = {
+	/* MM0 */
+	GATE_VOTE_MM0(CLK_MM_CONFIG, "mm_config", "ck2_disp_ck", 0),
+	GATE_MM0_V(CLK_MM_CONFIG_DISP, "mm_config_disp", "mm_config"),
+	GATE_VOTE_MM0(CLK_MM_DISP_MUTEX0, "mm_disp_mutex0", "ck2_disp_ck", 1),
+	GATE_MM0_V(CLK_MM_DISP_MUTEX0_DISP, "mm_disp_mutex0_disp", "mm_disp_mutex0"),
+	GATE_VOTE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "ck2_disp_ck", 2),
+	GATE_MM0_V(CLK_MM_DISP_AAL0_PQ, "mm_disp_aal0_pq", "mm_disp_aal0"),
+	GATE_VOTE_MM0(CLK_MM_DISP_AAL1, "mm_disp_aal1", "ck2_disp_ck", 3),
+	GATE_MM0_V(CLK_MM_DISP_AAL1_PQ, "mm_disp_aal1_pq", "mm_disp_aal1"),
+	GATE_MM0(CLK_MM_DISP_C3D0, "mm_disp_c3d0", "ck2_disp_ck", 4),
+	GATE_MM0_V(CLK_MM_DISP_C3D0_PQ, "mm_disp_c3d0_pq", "mm_disp_c3d0"),
+	GATE_MM0(CLK_MM_DISP_C3D1, "mm_disp_c3d1", "ck2_disp_ck", 5),
+	GATE_MM0_V(CLK_MM_DISP_C3D1_PQ, "mm_disp_c3d1_pq", "mm_disp_c3d1"),
+	GATE_MM0(CLK_MM_DISP_C3D2, "mm_disp_c3d2", "ck2_disp_ck", 6),
+	GATE_MM0_V(CLK_MM_DISP_C3D2_PQ, "mm_disp_c3d2_pq", "mm_disp_c3d2"),
+	GATE_MM0(CLK_MM_DISP_C3D3, "mm_disp_c3d3", "ck2_disp_ck", 7),
+	GATE_MM0_V(CLK_MM_DISP_C3D3_PQ, "mm_disp_c3d3_pq", "mm_disp_c3d3"),
+	GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "ck2_disp_ck", 8),
+	GATE_MM0_V(CLK_MM_DISP_CCORR0_PQ, "mm_disp_ccorr0_pq", "mm_disp_ccorr0"),
+	GATE_MM0(CLK_MM_DISP_CCORR1, "mm_disp_ccorr1", "ck2_disp_ck", 9),
+	GATE_MM0_V(CLK_MM_DISP_CCORR1_PQ, "mm_disp_ccorr1_pq", "mm_disp_ccorr1"),
+	GATE_MM0(CLK_MM_DISP_CCORR2, "mm_disp_ccorr2", "ck2_disp_ck", 10),
+	GATE_MM0_V(CLK_MM_DISP_CCORR2_PQ, "mm_disp_ccorr2_pq", "mm_disp_ccorr2"),
+	GATE_MM0(CLK_MM_DISP_CCORR3, "mm_disp_ccorr3", "ck2_disp_ck", 11),
+	GATE_MM0_V(CLK_MM_DISP_CCORR3_PQ, "mm_disp_ccorr3_pq", "mm_disp_ccorr3"),
+	GATE_MM0(CLK_MM_DISP_CHIST0, "mm_disp_chist0", "ck2_disp_ck", 12),
+	GATE_MM0_V(CLK_MM_DISP_CHIST0_PQ, "mm_disp_chist0_pq", "mm_disp_chist0"),
+	GATE_MM0(CLK_MM_DISP_CHIST1, "mm_disp_chist1", "ck2_disp_ck", 13),
+	GATE_MM0_V(CLK_MM_DISP_CHIST1_PQ, "mm_disp_chist1_pq", "mm_disp_chist1"),
+	GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "ck2_disp_ck", 14),
+	GATE_MM0_V(CLK_MM_DISP_COLOR0_PQ, "mm_disp_color0_pq", "mm_disp_color0"),
+	GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "ck2_disp_ck", 15),
+	GATE_MM0_V(CLK_MM_DISP_COLOR1_PQ, "mm_disp_color1_pq", "mm_disp_color1"),
+	GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "ck2_disp_ck", 16),
+	GATE_MM0_V(CLK_MM_DISP_DITHER0_PQ, "mm_disp_dither0_pq", "mm_disp_dither0"),
+	GATE_MM0(CLK_MM_DISP_DITHER1, "mm_disp_dither1", "ck2_disp_ck", 17),
+	GATE_MM0_V(CLK_MM_DISP_DITHER1_PQ, "mm_disp_dither1_pq", "mm_disp_dither1"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC0, "mm_disp_dli_async0", "ck2_disp_ck", 18),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC0_DISP, "mm_disp_dli_async0_disp", "mm_disp_dli_async0"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC1, "mm_disp_dli_async1", "ck2_disp_ck", 19),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC1_DISP, "mm_disp_dli_async1_disp", "mm_disp_dli_async1"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC2, "mm_disp_dli_async2", "ck2_disp_ck", 20),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC2_DISP, "mm_disp_dli_async2_disp", "mm_disp_dli_async2"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC3, "mm_disp_dli_async3", "ck2_disp_ck", 21),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC3_DISP, "mm_disp_dli_async3_disp", "mm_disp_dli_async3"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC4, "mm_disp_dli_async4", "ck2_disp_ck", 22),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC4_DISP, "mm_disp_dli_async4_disp", "mm_disp_dli_async4"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC5, "mm_disp_dli_async5", "ck2_disp_ck", 23),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC5_DISP, "mm_disp_dli_async5_disp", "mm_disp_dli_async5"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC6, "mm_disp_dli_async6", "ck2_disp_ck", 24),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC6_DISP, "mm_disp_dli_async6_disp", "mm_disp_dli_async6"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC7, "mm_disp_dli_async7", "ck2_disp_ck", 25),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC7_DISP, "mm_disp_dli_async7_disp", "mm_disp_dli_async7"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC8, "mm_disp_dli_async8", "ck2_disp_ck", 26),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC8_DISP, "mm_disp_dli_async8_disp", "mm_disp_dli_async8"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC9, "mm_disp_dli_async9", "ck2_disp_ck", 27),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC9_DISP, "mm_disp_dli_async9_disp", "mm_disp_dli_async9"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC10, "mm_disp_dli_async10", "ck2_disp_ck", 28),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC10_DISP, "mm_disp_dli_async10_disp", "mm_disp_dli_async10"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC11, "mm_disp_dli_async11", "ck2_disp_ck", 29),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC11_DISP, "mm_disp_dli_async11_disp", "mm_disp_dli_async11"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC12, "mm_disp_dli_async12", "ck2_disp_ck", 30),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC12_DISP, "mm_disp_dli_async12_disp", "mm_disp_dli_async12"),
+	GATE_VOTE_MM0(CLK_MM_DISP_DLI_ASYNC13, "mm_disp_dli_async13", "ck2_disp_ck", 31),
+	GATE_MM0_V(CLK_MM_DISP_DLI_ASYNC13_DISP, "mm_disp_dli_async13_disp", "mm_disp_dli_async13"),
+	/* MM1 */
+	GATE_VOTE_MM1(CLK_MM_DISP_DLI_ASYNC14, "mm_disp_dli_async14", "ck2_disp_ck", 0),
+	GATE_MM1_V(CLK_MM_DISP_DLI_ASYNC14_DISP, "mm_disp_dli_async14_disp", "mm_disp_dli_async14"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLI_ASYNC15, "mm_disp_dli_async15", "ck2_disp_ck", 1),
+	GATE_MM1_V(CLK_MM_DISP_DLI_ASYNC15_DISP, "mm_disp_dli_async15_disp", "mm_disp_dli_async15"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC0, "mm_disp_dlo_async0", "ck2_disp_ck", 2),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC0_DISP, "mm_disp_dlo_async0_disp", "mm_disp_dlo_async0"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC1, "mm_disp_dlo_async1", "ck2_disp_ck", 3),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC1_DISP, "mm_disp_dlo_async1_disp", "mm_disp_dlo_async1"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC2, "mm_disp_dlo_async2", "ck2_disp_ck", 4),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC2_DISP, "mm_disp_dlo_async2_disp", "mm_disp_dlo_async2"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC3, "mm_disp_dlo_async3", "ck2_disp_ck", 5),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC3_DISP, "mm_disp_dlo_async3_disp", "mm_disp_dlo_async3"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC4, "mm_disp_dlo_async4", "ck2_disp_ck", 6),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC4_DISP, "mm_disp_dlo_async4_disp", "mm_disp_dlo_async4"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC5, "mm_disp_dlo_async5", "ck2_disp_ck", 7),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC5_DISP, "mm_disp_dlo_async5_disp", "mm_disp_dlo_async5"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC6, "mm_disp_dlo_async6", "ck2_disp_ck", 8),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC6_DISP, "mm_disp_dlo_async6_disp", "mm_disp_dlo_async6"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC7, "mm_disp_dlo_async7", "ck2_disp_ck", 9),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC7_DISP, "mm_disp_dlo_async7_disp", "mm_disp_dlo_async7"),
+	GATE_VOTE_MM1(CLK_MM_DISP_DLO_ASYNC8, "mm_disp_dlo_async8", "ck2_disp_ck", 10),
+	GATE_MM1_V(CLK_MM_DISP_DLO_ASYNC8_DISP, "mm_disp_dlo_async8_disp", "mm_disp_dlo_async8"),
+	GATE_MM1(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "ck2_disp_ck", 11),
+	GATE_MM1_V(CLK_MM_DISP_GAMMA0_PQ, "mm_disp_gamma0_pq", "mm_disp_gamma0"),
+	GATE_MM1(CLK_MM_DISP_GAMMA1, "mm_disp_gamma1", "ck2_disp_ck", 12),
+	GATE_MM1_V(CLK_MM_DISP_GAMMA1_PQ, "mm_disp_gamma1_pq", "mm_disp_gamma1"),
+	GATE_MM1(CLK_MM_MDP_AAL0, "mm_mdp_aal0", "ck2_disp_ck", 13),
+	GATE_MM1_V(CLK_MM_MDP_AAL0_PQ, "mm_mdp_aal0_pq", "mm_mdp_aal0"),
+	GATE_MM1(CLK_MM_MDP_AAL1, "mm_mdp_aal1", "ck2_disp_ck", 14),
+	GATE_MM1_V(CLK_MM_MDP_AAL1_PQ, "mm_mdp_aal1_pq", "mm_mdp_aal1"),
+	GATE_VOTE_MM1(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "ck2_disp_ck", 15),
+	GATE_MM1_V(CLK_MM_MDP_RDMA0_DISP, "mm_mdp_rdma0_disp", "mm_mdp_rdma0"),
+	GATE_VOTE_MM1(CLK_MM_DISP_POSTMASK0, "mm_disp_postmask0", "ck2_disp_ck", 16),
+	GATE_MM1_V(CLK_MM_DISP_POSTMASK0_DISP, "mm_disp_postmask0_disp", "mm_disp_postmask0"),
+	GATE_VOTE_MM1(CLK_MM_DISP_POSTMASK1, "mm_disp_postmask1", "ck2_disp_ck", 17),
+	GATE_MM1_V(CLK_MM_DISP_POSTMASK1_DISP, "mm_disp_postmask1_disp", "mm_disp_postmask1"),
+	GATE_VOTE_MM1(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "ck2_disp_ck", 18),
+	GATE_MM1_V(CLK_MM_MDP_RSZ0_DISP, "mm_mdp_rsz0_disp", "mm_mdp_rsz0"),
+	GATE_VOTE_MM1(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "ck2_disp_ck", 19),
+	GATE_MM1_V(CLK_MM_MDP_RSZ1_DISP, "mm_mdp_rsz1_disp", "mm_mdp_rsz1"),
+	GATE_VOTE_MM1(CLK_MM_DISP_SPR0, "mm_disp_spr0", "ck2_disp_ck", 20),
+	GATE_MM1_V(CLK_MM_DISP_SPR0_DISP, "mm_disp_spr0_disp", "mm_disp_spr0"),
+	GATE_MM1(CLK_MM_DISP_TDSHP0, "mm_disp_tdshp0", "ck2_disp_ck", 21),
+	GATE_MM1_V(CLK_MM_DISP_TDSHP0_PQ, "mm_disp_tdshp0_pq", "mm_disp_tdshp0"),
+	GATE_MM1(CLK_MM_DISP_TDSHP1, "mm_disp_tdshp1", "ck2_disp_ck", 22),
+	GATE_MM1_V(CLK_MM_DISP_TDSHP1_PQ, "mm_disp_tdshp1_pq", "mm_disp_tdshp1"),
+	GATE_VOTE_MM1(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "ck2_disp_ck", 23),
+	GATE_MM1_V(CLK_MM_DISP_WDMA0_DISP, "mm_disp_wdma0_disp", "mm_disp_wdma0"),
+	GATE_VOTE_MM1(CLK_MM_DISP_Y2R0, "mm_disp_y2r0", "ck2_disp_ck", 24),
+	GATE_MM1_V(CLK_MM_DISP_Y2R0_DISP, "mm_disp_y2r0_disp", "mm_disp_y2r0"),
+	GATE_VOTE_MM1(CLK_MM_SMI_SUB_COMM0, "mm_ssc", "ck2_disp_ck", 25),
+	GATE_MM1_V(CLK_MM_SMI_SUB_COMM0_SMI, "mm_ssc_smi", "mm_ssc"),
+	GATE_VOTE_MM1(CLK_MM_DISP_FAKE_ENG0, "mm_disp_fake_eng0", "ck2_disp_ck", 26),
+	GATE_MM1_V(CLK_MM_DISP_FAKE_ENG0_DISP, "mm_disp_fake_eng0_disp", "mm_disp_fake_eng0"),
+};
+
+static const struct mtk_clk_desc mm_mcd = {
+	.clks = mm_clks,
+	.num_clks = ARRAY_SIZE(mm_clks),
+};
+
+static const struct platform_device_id clk_mt8196_disp0_id_table[] = {
+	{ .name = "clk-mt8196-disp0", .driver_data = (kernel_ulong_t)&mm_mcd },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, clk_mt8196_disp0_id_table);
+
+static struct platform_driver clk_mt8196_disp0_drv = {
+	.probe = mtk_clk_pdev_probe,
+	.remove = mtk_clk_pdev_remove,
+	.driver = {
+		.name = "clk-mt8196-disp0",
+	},
+	.id_table = clk_mt8196_disp0_id_table,
+};
+
+module_platform_driver(clk_mt8196_disp0_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:15 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:15 +0800
Subject: [PATCH 19/26] clk: mediatek: Add MT8196 disp1 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-20-guangjie.song@mediatek.com>

Add MT8196 disp1 clock controller which provides clock gate control in
display system. This is integrated with mtk-mmsys driver which will
populate device by platform_device_register_data to start disp1 clock
driver.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile           |   2 +-
 drivers/clk/mediatek/clk-mt8196-disp1.c | 260 ++++++++++++++++++++++++
 2 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-disp1.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 881061f1e259..7eb4af39029c 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -158,7 +158,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
-obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-disp1.c b/drivers/clk/mediatek/clk-mt8196-disp1.c
new file mode 100644
index 000000000000..5acc589812be
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-disp1.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs mm10_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm10_vote_regs = {
+	.set_ofs = 0x0010,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x2c08,
+};
+
+static const struct mtk_gate_regs mm11_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mm11_vote_regs = {
+	.set_ofs = 0x0018,
+	.clr_ofs = 0x001c,
+	.sta_ofs = 0x2c0c,
+};
+
+#define GATE_MM10(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mm10_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MM10_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_MM10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &mm10_cg_regs,			\
+		.vote_regs = &mm10_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_MM11(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mm11_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MM11_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_MM11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &mm11_cg_regs,			\
+		.vote_regs = &mm11_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate mm1_clks[] = {
+	/* MM10 */
+	GATE_VOTE_MM10(CLK_MM1_DISPSYS1_CONFIG, "mm1_dispsys1_config", "ck2_disp_ck", 0),
+	GATE_MM10_V(CLK_MM1_DISPSYS1_CONFIG_DISP, "mm1_dispsys1_config_disp",
+		    "mm1_dispsys1_config"),
+	GATE_VOTE_MM10(CLK_MM1_DISPSYS1_S_CONFIG, "mm1_dispsys1_s_config", "ck2_disp_ck", 1),
+	GATE_MM10_V(CLK_MM1_DISPSYS1_S_CONFIG_DISP, "mm1_dispsys1_s_config_disp",
+		    "mm1_dispsys1_s_config"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_MUTEX0, "mm1_disp_mutex0", "ck2_disp_ck", 2),
+	GATE_MM10_V(CLK_MM1_DISP_MUTEX0_DISP, "mm1_disp_mutex0_disp", "mm1_disp_mutex0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC20, "mm1_disp_dli_async20", "ck2_disp_ck", 3),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC20_DISP, "mm1_disp_dli_async20_disp",
+		    "mm1_disp_dli_async20"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC21, "mm1_disp_dli_async21", "ck2_disp_ck", 4),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC21_DISP, "mm1_disp_dli_async21_disp",
+		    "mm1_disp_dli_async21"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC22, "mm1_disp_dli_async22", "ck2_disp_ck", 5),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC22_DISP, "mm1_disp_dli_async22_disp",
+		    "mm1_disp_dli_async22"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC23, "mm1_disp_dli_async23", "ck2_disp_ck", 6),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC23_DISP, "mm1_disp_dli_async23_disp",
+		    "mm1_disp_dli_async23"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC24, "mm1_disp_dli_async24", "ck2_disp_ck", 7),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC24_DISP, "mm1_disp_dli_async24_disp",
+		    "mm1_disp_dli_async24"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC25, "mm1_disp_dli_async25", "ck2_disp_ck", 8),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC25_DISP, "mm1_disp_dli_async25_disp",
+		    "mm1_disp_dli_async25"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC26, "mm1_disp_dli_async26", "ck2_disp_ck", 9),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC26_DISP, "mm1_disp_dli_async26_disp",
+		    "mm1_disp_dli_async26"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC27, "mm1_disp_dli_async27", "ck2_disp_ck", 10),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC27_DISP, "mm1_disp_dli_async27_disp",
+		    "mm1_disp_dli_async27"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DLI_ASYNC28, "mm1_disp_dli_async28", "ck2_disp_ck", 11),
+	GATE_MM10_V(CLK_MM1_DISP_DLI_ASYNC28_DISP, "mm1_disp_dli_async28_disp",
+		    "mm1_disp_dli_async28"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_RELAY0, "mm1_disp_relay0", "ck2_disp_ck", 12),
+	GATE_MM10_V(CLK_MM1_DISP_RELAY0_DISP, "mm1_disp_relay0_disp", "mm1_disp_relay0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_RELAY1, "mm1_disp_relay1", "ck2_disp_ck", 13),
+	GATE_MM10_V(CLK_MM1_DISP_RELAY1_DISP, "mm1_disp_relay1_disp", "mm1_disp_relay1"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_RELAY2, "mm1_disp_relay2", "ck2_disp_ck", 14),
+	GATE_MM10_V(CLK_MM1_DISP_RELAY2_DISP, "mm1_disp_relay2_disp", "mm1_disp_relay2"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_RELAY3, "mm1_disp_relay3", "ck2_disp_ck", 15),
+	GATE_MM10_V(CLK_MM1_DISP_RELAY3_DISP, "mm1_disp_relay3_disp", "mm1_disp_relay3"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DP_INTF0, "mm1_DP_CLK", "ck2_disp_ck", 16),
+	GATE_MM10_V(CLK_MM1_DISP_DP_INTF0_DISP, "mm1_dp_clk_disp", "mm1_DP_CLK"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DP_INTF1, "mm1_disp_dp_intf1", "ck2_disp_ck", 17),
+	GATE_MM10_V(CLK_MM1_DISP_DP_INTF1_DISP, "mm1_disp_dp_intf1_disp", "mm1_disp_dp_intf1"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSC_WRAP0, "mm1_disp_dsc_wrap0", "ck2_disp_ck", 18),
+	GATE_MM10_V(CLK_MM1_DISP_DSC_WRAP0_DISP, "mm1_disp_dsc_wrap0_disp", "mm1_disp_dsc_wrap0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSC_WRAP1, "mm1_disp_dsc_wrap1", "ck2_disp_ck", 19),
+	GATE_MM10_V(CLK_MM1_DISP_DSC_WRAP1_DISP, "mm1_disp_dsc_wrap1_disp", "mm1_disp_dsc_wrap1"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSC_WRAP2, "mm1_disp_dsc_wrap2", "ck2_disp_ck", 20),
+	GATE_MM10_V(CLK_MM1_DISP_DSC_WRAP2_DISP, "mm1_disp_dsc_wrap2_disp", "mm1_disp_dsc_wrap2"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSC_WRAP3, "mm1_disp_dsc_wrap3", "ck2_disp_ck", 21),
+	GATE_MM10_V(CLK_MM1_DISP_DSC_WRAP3_DISP, "mm1_disp_dsc_wrap3_disp", "mm1_disp_dsc_wrap3"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSI0, "mm1_CLK0", "ck2_disp_ck", 22),
+	GATE_MM10_V(CLK_MM1_DISP_DSI0_DISP, "mm1_clk0_disp", "mm1_CLK0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSI1, "mm1_CLK1", "ck2_disp_ck", 23),
+	GATE_MM10_V(CLK_MM1_DISP_DSI1_DISP, "mm1_clk1_disp", "mm1_CLK1"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DSI2, "mm1_CLK2", "ck2_disp_ck", 24),
+	GATE_MM10_V(CLK_MM1_DISP_DSI2_DISP, "mm1_clk2_disp", "mm1_CLK2"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_DVO0, "mm1_disp_dvo0", "ck2_disp_ck", 25),
+	GATE_MM10_V(CLK_MM1_DISP_DVO0_DISP, "mm1_disp_dvo0_disp", "mm1_disp_dvo0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_GDMA0, "mm1_disp_gdma0", "ck2_disp_ck", 26),
+	GATE_MM10_V(CLK_MM1_DISP_GDMA0_DISP, "mm1_disp_gdma0_disp", "mm1_disp_gdma0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_MERGE0, "mm1_disp_merge0", "ck2_disp_ck", 27),
+	GATE_MM10_V(CLK_MM1_DISP_MERGE0_DISP, "mm1_disp_merge0_disp", "mm1_disp_merge0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_MERGE1, "mm1_disp_merge1", "ck2_disp_ck", 28),
+	GATE_MM10_V(CLK_MM1_DISP_MERGE1_DISP, "mm1_disp_merge1_disp", "mm1_disp_merge1"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_MERGE2, "mm1_disp_merge2", "ck2_disp_ck", 29),
+	GATE_MM10_V(CLK_MM1_DISP_MERGE2_DISP, "mm1_disp_merge2_disp", "mm1_disp_merge2"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_ODDMR0, "mm1_disp_oddmr0", "ck2_disp_ck", 30),
+	GATE_MM10_V(CLK_MM1_DISP_ODDMR0_PQ, "mm1_disp_oddmr0_pq", "mm1_disp_oddmr0"),
+	GATE_VOTE_MM10(CLK_MM1_DISP_POSTALIGN0, "mm1_disp_postalign0", "ck2_disp_ck", 31),
+	GATE_MM10_V(CLK_MM1_DISP_POSTALIGN0_PQ, "mm1_disp_postalign0_pq", "mm1_disp_postalign0"),
+	/* MM11 */
+	GATE_VOTE_MM11(CLK_MM1_DISP_DITHER2, "mm1_disp_dither2", "ck2_disp_ck", 0),
+	GATE_MM11_V(CLK_MM1_DISP_DITHER2_PQ, "mm1_disp_dither2_pq", "mm1_disp_dither2"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_R2Y0, "mm1_disp_r2y0", "ck2_disp_ck", 1),
+	GATE_MM11_V(CLK_MM1_DISP_R2Y0_DISP, "mm1_disp_r2y0_disp", "mm1_disp_r2y0"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_SPLITTER0, "mm1_disp_splitter0", "ck2_disp_ck", 2),
+	GATE_MM11_V(CLK_MM1_DISP_SPLITTER0_DISP, "mm1_disp_splitter0_disp", "mm1_disp_splitter0"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_SPLITTER1, "mm1_disp_splitter1", "ck2_disp_ck", 3),
+	GATE_MM11_V(CLK_MM1_DISP_SPLITTER1_DISP, "mm1_disp_splitter1_disp", "mm1_disp_splitter1"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_SPLITTER2, "mm1_disp_splitter2", "ck2_disp_ck", 4),
+	GATE_MM11_V(CLK_MM1_DISP_SPLITTER2_DISP, "mm1_disp_splitter2_disp", "mm1_disp_splitter2"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_SPLITTER3, "mm1_disp_splitter3", "ck2_disp_ck", 5),
+	GATE_MM11_V(CLK_MM1_DISP_SPLITTER3_DISP, "mm1_disp_splitter3_disp", "mm1_disp_splitter3"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_VDCM0, "mm1_disp_vdcm0", "ck2_disp_ck", 6),
+	GATE_MM11_V(CLK_MM1_DISP_VDCM0_DISP, "mm1_disp_vdcm0_disp", "mm1_disp_vdcm0"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_WDMA1, "mm1_disp_wdma1", "ck2_disp_ck", 7),
+	GATE_MM11_V(CLK_MM1_DISP_WDMA1_DISP, "mm1_disp_wdma1_disp", "mm1_disp_wdma1"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_WDMA2, "mm1_disp_wdma2", "ck2_disp_ck", 8),
+	GATE_MM11_V(CLK_MM1_DISP_WDMA2_DISP, "mm1_disp_wdma2_disp", "mm1_disp_wdma2"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_WDMA3, "mm1_disp_wdma3", "ck2_disp_ck", 9),
+	GATE_MM11_V(CLK_MM1_DISP_WDMA3_DISP, "mm1_disp_wdma3_disp", "mm1_disp_wdma3"),
+	GATE_VOTE_MM11(CLK_MM1_DISP_WDMA4, "mm1_disp_wdma4", "ck2_disp_ck", 10),
+	GATE_MM11_V(CLK_MM1_DISP_WDMA4_DISP, "mm1_disp_wdma4_disp", "mm1_disp_wdma4"),
+	GATE_VOTE_MM11(CLK_MM1_MDP_RDMA1, "mm1_mdp_rdma1", "ck2_disp_ck", 11),
+	GATE_MM11_V(CLK_MM1_MDP_RDMA1_DISP, "mm1_mdp_rdma1_disp", "mm1_mdp_rdma1"),
+	GATE_VOTE_MM11(CLK_MM1_SMI_LARB0, "mm1_smi_larb0", "ck2_disp_ck", 12),
+	GATE_MM11_V(CLK_MM1_SMI_LARB0_SMI, "mm1_smi_larb0_smi", "mm1_smi_larb0"),
+	GATE_VOTE_MM11(CLK_MM1_MOD1, "mm1_mod1", "ck_f26m_ck", 13),
+	GATE_MM11_V(CLK_MM1_MOD1_DISP, "mm1_mod1_disp", "mm1_mod1"),
+	GATE_VOTE_MM11(CLK_MM1_MOD2, "mm1_mod2", "ck_f26m_ck", 14),
+	GATE_MM11_V(CLK_MM1_MOD2_DISP, "mm1_mod2_disp", "mm1_mod2"),
+	GATE_VOTE_MM11(CLK_MM1_MOD3, "mm1_mod3", "ck_f26m_ck", 15),
+	GATE_MM11_V(CLK_MM1_MOD3_DISP, "mm1_mod3_disp", "mm1_mod3"),
+	GATE_VOTE_MM11(CLK_MM1_MOD4, "mm1_mod4", "ck2_dp0_ck", 16),
+	GATE_MM11_V(CLK_MM1_MOD4_DISP, "mm1_mod4_disp", "mm1_mod4"),
+	GATE_VOTE_MM11(CLK_MM1_MOD5, "mm1_mod5", "ck2_dp1_ck", 17),
+	GATE_MM11_V(CLK_MM1_MOD5_DISP, "mm1_mod5_disp", "mm1_mod5"),
+	GATE_VOTE_MM11(CLK_MM1_MOD6, "mm1_mod6", "ck2_dp1_ck", 18),
+	GATE_MM11_V(CLK_MM1_MOD6_DISP, "mm1_mod6_disp", "mm1_mod6"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG0, "mm1_cg0", "ck2_disp_ck", 20),
+	GATE_MM11_V(CLK_MM1_CK_CG0_DISP, "mm1_cg0_disp", "mm1_cg0"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG1, "mm1_cg1", "ck2_disp_ck", 21),
+	GATE_MM11_V(CLK_MM1_CK_CG1_DISP, "mm1_cg1_disp", "mm1_cg1"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG2, "mm1_cg2", "ck2_disp_ck", 22),
+	GATE_MM11_V(CLK_MM1_CK_CG2_DISP, "mm1_cg2_disp", "mm1_cg2"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG3, "mm1_cg3", "ck2_disp_ck", 23),
+	GATE_MM11_V(CLK_MM1_CK_CG3_DISP, "mm1_cg3_disp", "mm1_cg3"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG4, "mm1_cg4", "ck2_disp_ck", 24),
+	GATE_MM11_V(CLK_MM1_CK_CG4_DISP, "mm1_cg4_disp", "mm1_cg4"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG5, "mm1_cg5", "ck2_disp_ck", 25),
+	GATE_MM11_V(CLK_MM1_CK_CG5_DISP, "mm1_cg5_disp", "mm1_cg5"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG6, "mm1_cg6", "ck2_disp_ck", 26),
+	GATE_MM11_V(CLK_MM1_CK_CG6_DISP, "mm1_cg6_disp", "mm1_cg6"),
+	GATE_VOTE_MM11(CLK_MM1_CK_CG7, "mm1_cg7", "ck2_disp_ck", 27),
+	GATE_MM11_V(CLK_MM1_CK_CG7_DISP, "mm1_cg7_disp", "mm1_cg7"),
+	GATE_VOTE_MM11(CLK_MM1_F26M, "mm1_f26m_ck", "ck_f26m_ck", 28),
+	GATE_MM11_V(CLK_MM1_F26M_DISP, "mm1_f26m_ck_disp", "mm1_f26m_ck"),
+};
+
+static const struct mtk_clk_desc mm1_mcd = {
+	.clks = mm1_clks,
+	.num_clks = ARRAY_SIZE(mm1_clks),
+};
+
+static const struct platform_device_id clk_mt8196_disp1_id_table[] = {
+	{ .name = "clk-mt8196-disp1", .driver_data = (kernel_ulong_t)&mm1_mcd },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, clk_mt8196_disp1_id_table);
+
+static struct platform_driver clk_mt8196_disp1_drv = {
+	.probe = mtk_clk_pdev_probe,
+	.remove = mtk_clk_pdev_remove,
+	.driver = {
+		.name = "clk-mt8196-disp1",
+	},
+	.id_table = clk_mt8196_disp1_id_table,
+};
+
+module_platform_driver(clk_mt8196_disp1_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:19 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:19 +0800
Subject: [PATCH 23/26] clk: mediatek: Add MT8196 pextpsys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-24-guangjie.song@mediatek.com>

Add MT8196 pextpsys clock controller which provides clock gate control
for pcie.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig            |   7 +
 drivers/clk/mediatek/Makefile           |   1 +
 drivers/clk/mediatek/clk-mt8196-pextp.c | 162 ++++++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-pextp.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index dcb660d45bcf..2aafba083835 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1052,6 +1052,13 @@ config COMMON_CLK_MT8196_MMSYS
 	help
 	  This driver supports MediaTek MT8196 mmsys clocks.
 
+config COMMON_CLK_MT8196_PEXTPSYS
+	tristate "Clock driver for MediaTek MT8196 pextpsys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 pextpsys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 472462cd8711..3058e7855ff3 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -160,6 +160,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o \
 					 clk-mt8196-ovl0.o clk-mt8196-ovl1.o
+obj-$(CONFIG_COMMON_CLK_MT8196_PEXTPSYS) += clk-mt8196-pextp.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-pextp.c b/drivers/clk/mediatek/clk-mt8196-pextp.c
new file mode 100644
index 000000000000..8b394e18d0eb
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-pextp.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs pext_cg_regs = {
+	.set_ofs = 0x18,
+	.clr_ofs = 0x1c,
+	.sta_ofs = 0x14,
+};
+
+#define GATE_PEXT(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &pext_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_PEXT_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate pext_clks[] = {
+	GATE_PEXT(CLK_PEXT_PEXTP_MAC_P0_TL, "pext_pm0_tl", "ck_tl_ck", 0),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_MAC_P0_TL_PCIE, "pext_pm0_tl_pcie", "pext_pm0_tl"),
+	GATE_PEXT(CLK_PEXT_PEXTP_MAC_P0_REF, "pext_pm0_ref", "ck_f26m_ck", 1),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_MAC_P0_REF_PCIE, "pext_pm0_ref_pcie", "pext_pm0_ref"),
+	GATE_PEXT(CLK_PEXT_PEXTP_PHY_P0_MCU_BUS, "pext_pp0_mcu_bus", "ck_f26m_ck", 6),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_PHY_P0_MCU_BUS_PCIE, "pext_pp0_mcu_bus_pcie",
+		    "pext_pp0_mcu_bus"),
+	GATE_PEXT(CLK_PEXT_PEXTP_PHY_P0_PEXTP_REF, "pext_pp0_pextp_ref", "ck_f26m_ck", 7),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_PHY_P0_PEXTP_REF_PCIE, "pext_pp0_pextp_ref_pcie",
+		    "pext_pp0_pextp_ref"),
+	GATE_PEXT(CLK_PEXT_PEXTP_MAC_P0_AXI_250, "pext_pm0_axi_250", "ck_pexpt0_mem_sub_ck", 12),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_MAC_P0_AXI_250_PCIE, "pext_pm0_axi_250_pcie",
+		    "pext_pm0_axi_250"),
+	GATE_PEXT(CLK_PEXT_PEXTP_MAC_P0_AHB_APB, "pext_pm0_ahb_apb", "ck_pextp0_axi_ck", 13),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_MAC_P0_AHB_APB_PCIE, "pext_pm0_ahb_apb_pcie",
+		    "pext_pm0_ahb_apb"),
+	GATE_PEXT(CLK_PEXT_PEXTP_MAC_P0_PL_P, "pext_pm0_pl_p", "ck_f26m_ck", 14),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_MAC_P0_PL_P_PCIE, "pext_pm0_pl_p_pcie", "pext_pm0_pl_p"),
+	GATE_PEXT(CLK_PEXT_PEXTP_VLP_AO_P0_LP, "pext_pextp_vlp_ao_p0_lp", "ck_f26m_ck", 19),
+	GATE_PEXT_V(CLK_PEXT_PEXTP_VLP_AO_P0_LP_PCIE, "pext_pextp_vlp_ao_p0_lp_pcie",
+		    "pext_pextp_vlp_ao_p0_lp"),
+};
+
+static const struct mtk_clk_desc pext_mcd = {
+	.clks = pext_clks,
+	.num_clks = ARRAY_SIZE(pext_clks),
+};
+
+static const struct mtk_gate_regs pext1_cg_regs = {
+	.set_ofs = 0x18,
+	.clr_ofs = 0x1c,
+	.sta_ofs = 0x14,
+};
+
+#define GATE_PEXT1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &pext1_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PEXT1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate pext1_clks[] = {
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P1_TL, "pext1_pm1_tl", "ck_tl_p1_ck", 0),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P1_TL_PCIE, "pext1_pm1_tl_pcie", "pext1_pm1_tl"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P1_REF, "pext1_pm1_ref", "ck_f26m_ck", 1),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P1_REF_PCIE, "pext1_pm1_ref_pcie", "pext1_pm1_ref"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P2_TL, "pext1_pm2_tl", "ck_tl_p2_ck", 2),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P2_TL_PCIE, "pext1_pm2_tl_pcie", "pext1_pm2_tl"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P2_REF, "pext1_pm2_ref", "ck_f26m_ck", 3),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P2_REF_PCIE, "pext1_pm2_ref_pcie", "pext1_pm2_ref"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_PHY_P1_MCU_BUS, "pext1_pp1_mcu_bus", "ck_f26m_ck", 8),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_PHY_P1_MCU_BUS_PCIE, "pext1_pp1_mcu_bus_pcie",
+		     "pext1_pp1_mcu_bus"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_PHY_P1_PEXTP_REF, "pext1_pp1_pextp_ref", "ck_f26m_ck", 9),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_PHY_P1_PEXTP_REF_PCIE, "pext1_pp1_pextp_ref_pcie",
+		     "pext1_pp1_pextp_ref"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_PHY_P2_MCU_BUS, "pext1_pp2_mcu_bus", "ck_f26m_ck", 10),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_PHY_P2_MCU_BUS_PCIE, "pext1_pp2_mcu_bus_pcie",
+		     "pext1_pp2_mcu_bus"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_PHY_P2_PEXTP_REF, "pext1_pp2_pextp_ref", "ck_f26m_ck", 11),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_PHY_P2_PEXTP_REF_PCIE, "pext1_pp2_pextp_ref_pcie",
+		     "pext1_pp2_pextp_ref"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P1_AXI_250, "pext1_pm1_axi_250",
+		   "ck_pextp1_usb_axi_ck", 16),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P1_AXI_250_PCIE, "pext1_pm1_axi_250_pcie",
+		     "pext1_pm1_axi_250"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P1_AHB_APB, "pext1_pm1_ahb_apb",
+		   "ck_pextp1_usb_mem_sub_ck", 17),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P1_AHB_APB_PCIE, "pext1_pm1_ahb_apb_pcie",
+		     "pext1_pm1_ahb_apb"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P1_PL_P, "pext1_pm1_pl_p", "ck_f26m_ck", 18),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P1_PL_P_PCIE, "pext1_pm1_pl_p_pcie", "pext1_pm1_pl_p"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P2_AXI_250, "pext1_pm2_axi_250",
+		   "ck_pextp1_usb_axi_ck", 19),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P2_AXI_250_PCIE, "pext1_pm2_axi_250_pcie",
+		     "pext1_pm2_axi_250"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P2_AHB_APB, "pext1_pm2_ahb_apb",
+		   "ck_pextp1_usb_mem_sub_ck", 20),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P2_AHB_APB_PCIE, "pext1_pm2_ahb_apb_pcie",
+		     "pext1_pm2_ahb_apb"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_MAC_P2_PL_P, "pext1_pm2_pl_p", "ck_f26m_ck", 21),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_MAC_P2_PL_P_PCIE, "pext1_pm2_pl_p_pcie", "pext1_pm2_pl_p"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_VLP_AO_P1_LP, "pext1_pextp_vlp_ao_p1_lp", "ck_f26m_ck", 26),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_VLP_AO_P1_LP_PCIE, "pext1_pextp_vlp_ao_p1_lp_pcie",
+		     "pext1_pextp_vlp_ao_p1_lp"),
+	GATE_PEXT1(CLK_PEXT1_PEXTP_VLP_AO_P2_LP, "pext1_pextp_vlp_ao_p2_lp", "ck_f26m_ck", 27),
+	GATE_PEXT1_V(CLK_PEXT1_PEXTP_VLP_AO_P2_LP_PCIE, "pext1_pextp_vlp_ao_p2_lp_pcie",
+		     "pext1_pextp_vlp_ao_p2_lp"),
+};
+
+static const struct mtk_clk_desc pext1_mcd = {
+	.clks = pext1_clks,
+	.num_clks = ARRAY_SIZE(pext1_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8196_pextp[] = {
+	{ .compatible = "mediatek,mt8196-pextp0cfg_ao", .data = &pext_mcd, },
+	{ .compatible = "mediatek,mt8196-pextp1cfg_ao", .data = &pext1_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_pextp_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-pextp",
+		.of_match_table = of_match_clk_mt8196_pextp,
+	},
+};
+
+module_platform_driver(clk_mt8196_pextp_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:18 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:18 +0800
Subject: [PATCH 22/26] clk: mediatek: Add MT8196 ovl1 clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-23-guangjie.song@mediatek.com>

Add MT8196 ovl1 clock controller which provides clock gate control in
display system. This is integrated with mtk-mmsys driver which will
populate device by platform_device_register_data to start ovl1 clock
driver.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Makefile          |   2 +-
 drivers/clk/mediatek/clk-mt8196-ovl1.c | 255 +++++++++++++++++++++++++
 2 files changed, 256 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-ovl1.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 6766811e67d9..472462cd8711 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -159,7 +159,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o clk-mt8196-vdisp_ao.o \
-					 clk-mt8196-ovl0.o
+					 clk-mt8196-ovl0.o clk-mt8196-ovl1.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-ovl1.c b/drivers/clk/mediatek/clk-mt8196-ovl1.c
new file mode 100644
index 000000000000..ca590be53199
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-ovl1.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs ovl10_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs ovl10_vote_regs = {
+	.set_ofs = 0x0050,
+	.clr_ofs = 0x0054,
+	.sta_ofs = 0x2c28,
+};
+
+static const struct mtk_gate_regs ovl11_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs ovl11_vote_regs = {
+	.set_ofs = 0x0058,
+	.clr_ofs = 0x005c,
+	.sta_ofs = 0x2c2c,
+};
+
+#define GATE_OVL10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ovl10_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_OVL10_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_OVL10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ovl10_cg_regs,			\
+		.vote_regs = &ovl10_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_OVL11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ovl11_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_OVL11_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_OVL11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ovl11_cg_regs,			\
+		.vote_regs = &ovl11_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate ovl1_clks[] = {
+	/* OVL10 */
+	GATE_VOTE_OVL10(CLK_OVL1_OVLSYS_CONFIG, "ovl1_ovlsys_config", "ck2_disp_ck", 0),
+	GATE_OVL10_V(CLK_OVL1_OVLSYS_CONFIG_DISP, "ovl1_ovlsys_config_disp", "ovl1_ovlsys_config"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_FAKE_ENG0, "ovl1_ovl_fake_eng0", "ck2_disp_ck", 1),
+	GATE_OVL10_V(CLK_OVL1_OVL_FAKE_ENG0_DISP, "ovl1_ovl_fake_eng0_disp", "ovl1_ovl_fake_eng0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_FAKE_ENG1, "ovl1_ovl_fake_eng1", "ck2_disp_ck", 2),
+	GATE_OVL10_V(CLK_OVL1_OVL_FAKE_ENG1_DISP, "ovl1_ovl_fake_eng1_disp", "ovl1_ovl_fake_eng1"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_MUTEX0, "ovl1_ovl_mutex0", "ck2_disp_ck", 3),
+	GATE_OVL10_V(CLK_OVL1_OVL_MUTEX0_DISP, "ovl1_ovl_mutex0_disp", "ovl1_ovl_mutex0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA0, "ovl1_ovl_exdma0", "ck2_disp_ck", 4),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA0_DISP, "ovl1_ovl_exdma0_disp", "ovl1_ovl_exdma0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA1, "ovl1_ovl_exdma1", "ck2_disp_ck", 5),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA1_DISP, "ovl1_ovl_exdma1_disp", "ovl1_ovl_exdma1"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA2, "ovl1_ovl_exdma2", "ck2_disp_ck", 6),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA2_DISP, "ovl1_ovl_exdma2_disp", "ovl1_ovl_exdma2"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA3, "ovl1_ovl_exdma3", "ck2_disp_ck", 7),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA3_DISP, "ovl1_ovl_exdma3_disp", "ovl1_ovl_exdma3"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA4, "ovl1_ovl_exdma4", "ck2_disp_ck", 8),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA4_DISP, "ovl1_ovl_exdma4_disp", "ovl1_ovl_exdma4"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA5, "ovl1_ovl_exdma5", "ck2_disp_ck", 9),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA5_DISP, "ovl1_ovl_exdma5_disp", "ovl1_ovl_exdma5"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA6, "ovl1_ovl_exdma6", "ck2_disp_ck", 10),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA6_DISP, "ovl1_ovl_exdma6_disp", "ovl1_ovl_exdma6"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA7, "ovl1_ovl_exdma7", "ck2_disp_ck", 11),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA7_DISP, "ovl1_ovl_exdma7_disp", "ovl1_ovl_exdma7"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA8, "ovl1_ovl_exdma8", "ck2_disp_ck", 12),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA8_DISP, "ovl1_ovl_exdma8_disp", "ovl1_ovl_exdma8"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_EXDMA9, "ovl1_ovl_exdma9", "ck2_disp_ck", 13),
+	GATE_OVL10_V(CLK_OVL1_OVL_EXDMA9_DISP, "ovl1_ovl_exdma9_disp", "ovl1_ovl_exdma9"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER0, "ovl1_ovl_blender0", "ck2_disp_ck", 14),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER0_DISP, "ovl1_ovl_blender0_disp", "ovl1_ovl_blender0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER1, "ovl1_ovl_blender1", "ck2_disp_ck", 15),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER1_DISP, "ovl1_ovl_blender1_disp", "ovl1_ovl_blender1"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER2, "ovl1_ovl_blender2", "ck2_disp_ck", 16),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER2_DISP, "ovl1_ovl_blender2_disp", "ovl1_ovl_blender2"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER3, "ovl1_ovl_blender3", "ck2_disp_ck", 17),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER3_DISP, "ovl1_ovl_blender3_disp", "ovl1_ovl_blender3"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER4, "ovl1_ovl_blender4", "ck2_disp_ck", 18),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER4_DISP, "ovl1_ovl_blender4_disp", "ovl1_ovl_blender4"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER5, "ovl1_ovl_blender5", "ck2_disp_ck", 19),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER5_DISP, "ovl1_ovl_blender5_disp", "ovl1_ovl_blender5"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER6, "ovl1_ovl_blender6", "ck2_disp_ck", 20),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER6_DISP, "ovl1_ovl_blender6_disp", "ovl1_ovl_blender6"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER7, "ovl1_ovl_blender7", "ck2_disp_ck", 21),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER7_DISP, "ovl1_ovl_blender7_disp", "ovl1_ovl_blender7"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER8, "ovl1_ovl_blender8", "ck2_disp_ck", 22),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER8_DISP, "ovl1_ovl_blender8_disp", "ovl1_ovl_blender8"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_BLENDER9, "ovl1_ovl_blender9", "ck2_disp_ck", 23),
+	GATE_OVL10_V(CLK_OVL1_OVL_BLENDER9_DISP, "ovl1_ovl_blender9_disp", "ovl1_ovl_blender9"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC0, "ovl1_ovl_outproc0", "ck2_disp_ck", 24),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC0_DISP, "ovl1_ovl_outproc0_disp", "ovl1_ovl_outproc0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC1, "ovl1_ovl_outproc1", "ck2_disp_ck", 25),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC1_DISP, "ovl1_ovl_outproc1_disp", "ovl1_ovl_outproc1"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC2, "ovl1_ovl_outproc2", "ck2_disp_ck", 26),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC2_DISP, "ovl1_ovl_outproc2_disp", "ovl1_ovl_outproc2"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC3, "ovl1_ovl_outproc3", "ck2_disp_ck", 27),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC3_DISP, "ovl1_ovl_outproc3_disp", "ovl1_ovl_outproc3"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC4, "ovl1_ovl_outproc4", "ck2_disp_ck", 28),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC4_DISP, "ovl1_ovl_outproc4_disp", "ovl1_ovl_outproc4"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_OUTPROC5, "ovl1_ovl_outproc5", "ck2_disp_ck", 29),
+	GATE_OVL10_V(CLK_OVL1_OVL_OUTPROC5_DISP, "ovl1_ovl_outproc5_disp", "ovl1_ovl_outproc5"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_MDP_RSZ0, "ovl1_ovl_mdp_rsz0", "ck2_disp_ck", 30),
+	GATE_OVL10_V(CLK_OVL1_OVL_MDP_RSZ0_DISP, "ovl1_ovl_mdp_rsz0_disp", "ovl1_ovl_mdp_rsz0"),
+	GATE_VOTE_OVL10(CLK_OVL1_OVL_MDP_RSZ1, "ovl1_ovl_mdp_rsz1", "ck2_disp_ck", 31),
+	GATE_OVL10_V(CLK_OVL1_OVL_MDP_RSZ1_DISP, "ovl1_ovl_mdp_rsz1_disp", "ovl1_ovl_mdp_rsz1"),
+	/* OVL11 */
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_DISP_WDMA0, "ovl1_ovl_disp_wdma0", "ck2_disp_ck", 0),
+	GATE_OVL11_V(CLK_OVL1_OVL_DISP_WDMA0_DISP, "ovl1_ovl_disp_wdma0_disp", "ovl1_ovl_disp_wdma0"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_DISP_WDMA1, "ovl1_ovl_disp_wdma1", "ck2_disp_ck", 1),
+	GATE_OVL11_V(CLK_OVL1_OVL_DISP_WDMA1_DISP, "ovl1_ovl_disp_wdma1_disp", "ovl1_ovl_disp_wdma1"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_UFBC_WDMA0, "ovl1_ovl_ufbc_wdma0", "ck2_disp_ck", 2),
+	GATE_OVL11_V(CLK_OVL1_OVL_UFBC_WDMA0_DISP, "ovl1_ovl_ufbc_wdma0_disp", "ovl1_ovl_ufbc_wdma0"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_MDP_RDMA0, "ovl1_ovl_mdp_rdma0", "ck2_disp_ck", 3),
+	GATE_OVL11_V(CLK_OVL1_OVL_MDP_RDMA0_DISP, "ovl1_ovl_mdp_rdma0_disp", "ovl1_ovl_mdp_rdma0"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_MDP_RDMA1, "ovl1_ovl_mdp_rdma1", "ck2_disp_ck", 4),
+	GATE_OVL11_V(CLK_OVL1_OVL_MDP_RDMA1_DISP, "ovl1_ovl_mdp_rdma1_disp", "ovl1_ovl_mdp_rdma1"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_BWM0, "ovl1_ovl_bwm0", "ck2_disp_ck", 5),
+	GATE_OVL11_V(CLK_OVL1_OVL_BWM0_DISP, "ovl1_ovl_bwm0_disp", "ovl1_ovl_bwm0"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI0, "ovl1_dli0", "ck2_disp_ck", 6),
+	GATE_OVL11_V(CLK_OVL1_DLI0_DISP, "ovl1_dli0_disp", "ovl1_dli0"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI1, "ovl1_dli1", "ck2_disp_ck", 7),
+	GATE_OVL11_V(CLK_OVL1_DLI1_DISP, "ovl1_dli1_disp", "ovl1_dli1"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI2, "ovl1_dli2", "ck2_disp_ck", 8),
+	GATE_OVL11_V(CLK_OVL1_DLI2_DISP, "ovl1_dli2_disp", "ovl1_dli2"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI3, "ovl1_dli3", "ck2_disp_ck", 9),
+	GATE_OVL11_V(CLK_OVL1_DLI3_DISP, "ovl1_dli3_disp", "ovl1_dli3"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI4, "ovl1_dli4", "ck2_disp_ck", 10),
+	GATE_OVL11_V(CLK_OVL1_DLI4_DISP, "ovl1_dli4_disp", "ovl1_dli4"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI5, "ovl1_dli5", "ck2_disp_ck", 11),
+	GATE_OVL11_V(CLK_OVL1_DLI5_DISP, "ovl1_dli5_disp", "ovl1_dli5"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI6, "ovl1_dli6", "ck2_disp_ck", 12),
+	GATE_OVL11_V(CLK_OVL1_DLI6_DISP, "ovl1_dli6_disp", "ovl1_dli6"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI7, "ovl1_dli7", "ck2_disp_ck", 13),
+	GATE_OVL11_V(CLK_OVL1_DLI7_DISP, "ovl1_dli7_disp", "ovl1_dli7"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLI8, "ovl1_dli8", "ck2_disp_ck", 14),
+	GATE_OVL11_V(CLK_OVL1_DLI8_DISP, "ovl1_dli8_disp", "ovl1_dli8"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO0, "ovl1_dlo0", "ck2_disp_ck", 15),
+	GATE_OVL11_V(CLK_OVL1_DLO0_DISP, "ovl1_dlo0_disp", "ovl1_dlo0"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO1, "ovl1_dlo1", "ck2_disp_ck", 16),
+	GATE_OVL11_V(CLK_OVL1_DLO1_DISP, "ovl1_dlo1_disp", "ovl1_dlo1"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO2, "ovl1_dlo2", "ck2_disp_ck", 17),
+	GATE_OVL11_V(CLK_OVL1_DLO2_DISP, "ovl1_dlo2_disp", "ovl1_dlo2"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO3, "ovl1_dlo3", "ck2_disp_ck", 18),
+	GATE_OVL11_V(CLK_OVL1_DLO3_DISP, "ovl1_dlo3_disp", "ovl1_dlo3"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO4, "ovl1_dlo4", "ck2_disp_ck", 19),
+	GATE_OVL11_V(CLK_OVL1_DLO4_DISP, "ovl1_dlo4_disp", "ovl1_dlo4"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO5, "ovl1_dlo5", "ck2_disp_ck", 20),
+	GATE_OVL11_V(CLK_OVL1_DLO5_DISP, "ovl1_dlo5_disp", "ovl1_dlo5"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO6, "ovl1_dlo6", "ck2_disp_ck", 21),
+	GATE_OVL11_V(CLK_OVL1_DLO6_DISP, "ovl1_dlo6_disp", "ovl1_dlo6"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO7, "ovl1_dlo7", "ck2_disp_ck", 22),
+	GATE_OVL11_V(CLK_OVL1_DLO7_DISP, "ovl1_dlo7_disp", "ovl1_dlo7"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO8, "ovl1_dlo8", "ck2_disp_ck", 23),
+	GATE_OVL11_V(CLK_OVL1_DLO8_DISP, "ovl1_dlo8_disp", "ovl1_dlo8"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO9, "ovl1_dlo9", "ck2_disp_ck", 24),
+	GATE_OVL11_V(CLK_OVL1_DLO9_DISP, "ovl1_dlo9_disp", "ovl1_dlo9"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO10, "ovl1_dlo10", "ck2_disp_ck", 25),
+	GATE_OVL11_V(CLK_OVL1_DLO10_DISP, "ovl1_dlo10_disp", "ovl1_dlo10"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO11, "ovl1_dlo11", "ck2_disp_ck", 26),
+	GATE_OVL11_V(CLK_OVL1_DLO11_DISP, "ovl1_dlo11_disp", "ovl1_dlo11"),
+	GATE_VOTE_OVL11(CLK_OVL1_DLO12, "ovl1_dlo12", "ck2_disp_ck", 27),
+	GATE_OVL11_V(CLK_OVL1_DLO12_DISP, "ovl1_dlo12_disp", "ovl1_dlo12"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVLSYS_RELAY0, "ovl1_ovlsys_relay0", "ck2_disp_ck", 28),
+	GATE_OVL11_V(CLK_OVL1_OVLSYS_RELAY0_DISP, "ovl1_ovlsys_relay0_disp", "ovl1_ovlsys_relay0"),
+	GATE_VOTE_OVL11(CLK_OVL1_OVL_INLINEROT0, "ovl1_ovl_inlinerot0", "ck2_disp_ck", 29),
+	GATE_OVL11_V(CLK_OVL1_OVL_INLINEROT0_DISP, "ovl1_ovl_inlinerot0_disp", "ovl1_ovl_inlinerot0"),
+	GATE_VOTE_OVL11(CLK_OVL1_SMI, "ovl1_smi", "ck2_disp_ck", 30),
+	GATE_OVL11_V(CLK_OVL1_SMI_SMI, "ovl1_smi_smi", "ovl1_smi"),
+};
+
+static const struct mtk_clk_desc ovl1_mcd = {
+	.clks = ovl1_clks,
+	.num_clks = ARRAY_SIZE(ovl1_clks),
+};
+
+static const struct platform_device_id clk_mt8196_ovl1_id_table[] = {
+	{ .name = "clk-mt8196-ovl1", .driver_data = (kernel_ulong_t)&ovl1_mcd },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, clk_mt8196_ovl1_id_table);
+
+static struct platform_driver clk_mt8196_ovl1_drv = {
+	.probe = mtk_clk_pdev_probe,
+	.remove = mtk_clk_pdev_remove,
+	.driver = {
+		.name = "clk-mt8196-ovl1",
+	},
+	.id_table = clk_mt8196_ovl1_id_table,
+};
+
+module_platform_driver(clk_mt8196_ovl1_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:22 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:22 +0800
Subject: [PATCH 26/26] clk: mediatek: Add MT8196 vencsys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-27-guangjie.song@mediatek.com>

Add MT8196 vencsys clock controller which provides clock gate control
for video encoder.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig           |   7 +
 drivers/clk/mediatek/Makefile          |   1 +
 drivers/clk/mediatek/clk-mt8196-venc.c | 413 +++++++++++++++++++++++++
 3 files changed, 421 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-venc.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 0c508a8a9959..3184b2186561 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1073,6 +1073,13 @@ config COMMON_CLK_MT8196_VDECSYS
 	help
 	  This driver supports MediaTek MT8196 vdecsys clocks.
 
+config COMMON_CLK_MT8196_VENCSYS
+	tristate "Clock driver for MediaTek MT8196 vencsys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 vencsys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index b8bf3f5f8530..7bded296d0ca 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o c
 obj-$(CONFIG_COMMON_CLK_MT8196_PEXTPSYS) += clk-mt8196-pextp.o
 obj-$(CONFIG_COMMON_CLK_MT8196_UFSSYS) += clk-mt8196-ufs_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8196_VDECSYS) += clk-mt8196-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT8196_VENCSYS) += clk-mt8196-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-venc.c b/drivers/clk/mediatek/clk-mt8196-venc.c
new file mode 100644
index 000000000000..f8fcdf7b47df
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-venc.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs ven10_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs ven10_vote_regs = {
+	.set_ofs = 0x00b8,
+	.clr_ofs = 0x00bc,
+	.sta_ofs = 0x2c5c,
+};
+
+static const struct mtk_gate_regs ven11_cg_regs = {
+	.set_ofs = 0x10,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs ven11_vote_regs = {
+	.set_ofs = 0x00c0,
+	.clr_ofs = 0x00c4,
+	.sta_ofs = 0x2c60,
+};
+
+#define GATE_VEN10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven10_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VEN10_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN10_FLAGS(_id, _name, _parent, _shift, _flags) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven10_cg_regs,			\
+		.vote_regs = &ven10_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = (_flags) |			\
+			 CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VOTE_VEN10(_id, _name, _parent, _shift)	\
+	GATE_VOTE_VEN10_FLAGS(_id, _name, _parent, _shift, 0)
+
+#define GATE_VEN11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven11_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_VEN11_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven11_cg_regs,			\
+		.vote_regs = &ven11_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE		\
+	}
+
+static const struct mtk_gate ven1_clks[] = {
+	/* VEN10 */
+	GATE_VOTE_VEN10(CLK_VEN1_CKE0_LARB, "ven1_larb", "ck2_venc_ck", 0),
+	GATE_VEN10_V(CLK_VEN1_CKE0_LARB_VENC, "ven1_larb_venc", "ven1_larb"),
+	GATE_VEN10_V(CLK_VEN1_CKE0_LARB_JPGENC, "ven1_larb_jpgenc", "ven1_larb"),
+	GATE_VEN10_V(CLK_VEN1_CKE0_LARB_JPGDEC, "ven1_larb_jpgdec", "ven1_larb"),
+	GATE_VEN10_V(CLK_VEN1_CKE0_LARB_SMI, "ven1_larb_smi", "ven1_larb"),
+	GATE_VOTE_VEN10(CLK_VEN1_CKE1_VENC, "ven1_venc", "ck2_venc_ck", 4),
+	GATE_VEN10_V(CLK_VEN1_CKE1_VENC_VENC, "ven1_venc_venc", "ven1_venc"),
+	GATE_VEN10_V(CLK_VEN1_CKE1_VENC_SMI, "ven1_venc_smi", "ven1_venc"),
+	GATE_VEN10(CLK_VEN1_CKE2_JPGENC, "ven1_jpgenc", "ck2_venc_ck", 8),
+	GATE_VEN10_V(CLK_VEN1_CKE2_JPGENC_JPGENC, "ven1_jpgenc_jpgenc", "ven1_jpgenc"),
+	GATE_VEN10(CLK_VEN1_CKE3_JPGDEC, "ven1_jpgdec", "ck2_venc_ck", 12),
+	GATE_VEN10_V(CLK_VEN1_CKE3_JPGDEC_JPGDEC, "ven1_jpgdec_jpgdec", "ven1_jpgdec"),
+	GATE_VEN10(CLK_VEN1_CKE4_JPGDEC_C1, "ven1_jpgdec_c1", "ck2_venc_ck", 16),
+	GATE_VEN10_V(CLK_VEN1_CKE4_JPGDEC_C1_JPGDEC, "ven1_jpgdec_c1_jpgdec", "ven1_jpgdec_c1"),
+	GATE_VOTE_VEN10(CLK_VEN1_CKE5_GALS, "ven1_gals", "ck2_venc_ck", 28),
+	GATE_VEN10_V(CLK_VEN1_CKE5_GALS_VENC, "ven1_gals_venc", "ven1_gals"),
+	GATE_VEN10_V(CLK_VEN1_CKE5_GALS_JPGENC, "ven1_gals_jpgenc", "ven1_gals"),
+	GATE_VEN10_V(CLK_VEN1_CKE5_GALS_JPGDEC, "ven1_gals_jpgdec", "ven1_gals"),
+	GATE_VOTE_VEN10(CLK_VEN1_CKE29_VENC_ADAB_CTRL, "ven1_venc_adab_ctrl", "ck2_venc_ck", 29),
+	GATE_VEN10_V(CLK_VEN1_CKE29_VENC_ADAB_CTRL_VENC, "ven1_venc_adab_ctrl_venc",
+		     "ven1_venc_adab_ctrl"),
+	GATE_VOTE_VEN10_FLAGS(CLK_VEN1_CKE29_VENC_XPC_CTRL, "ven1_venc_xpc_ctrl",
+			      "ck2_venc_ck", 30, CLK_IGNORE_UNUSED),
+	GATE_VEN10_V(CLK_VEN1_CKE29_VENC_XPC_CTRL_VENC, "ven1_venc_xpc_ctrl_venc",
+		     "ven1_venc_xpc_ctrl"),
+	GATE_VEN10_V(CLK_VEN1_CKE29_VENC_XPC_CTRL_JPGENC, "ven1_venc_xpc_ctrl_jpgenc",
+		     "ven1_venc_xpc_ctrl"),
+	GATE_VEN10_V(CLK_VEN1_CKE29_VENC_XPC_CTRL_JPGDEC, "ven1_venc_xpc_ctrl_jpgdec",
+		     "ven1_venc_xpc_ctrl"),
+	GATE_VOTE_VEN10(CLK_VEN1_CKE6_GALS_SRAM, "ven1_gals_sram", "ck2_venc_ck", 31),
+	GATE_VEN10_V(CLK_VEN1_CKE6_GALS_SRAM_VENC, "ven1_gals_sram_venc", "ven1_gals_sram"),
+	/* VEN11 */
+	GATE_VOTE_VEN11(CLK_VEN1_RES_FLAT, "ven1_res_flat", "ck2_venc_ck", 0),
+	GATE_VEN11_V(CLK_VEN1_RES_FLAT_VENC, "ven1_res_flat_venc", "ven1_res_flat"),
+	GATE_VEN11_V(CLK_VEN1_RES_FLAT_JPGENC, "ven1_res_flat_jpgenc", "ven1_res_flat"),
+	GATE_VEN11_V(CLK_VEN1_RES_FLAT_JPGDEC, "ven1_res_flat_jpgdec", "ven1_res_flat"),
+};
+
+static const struct mtk_clk_desc ven1_mcd = {
+	.clks = ven1_clks,
+	.num_clks = ARRAY_SIZE(ven1_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct mtk_gate_regs ven20_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs ven20_vote_regs = {
+	.set_ofs = 0x00c8,
+	.clr_ofs = 0x00cc,
+	.sta_ofs = 0x2c64,
+};
+
+static const struct mtk_gate_regs ven21_cg_regs = {
+	.set_ofs = 0x10,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs ven21_vote_regs = {
+	.set_ofs = 0x00d0,
+	.clr_ofs = 0x00d4,
+	.sta_ofs = 0x2c68,
+};
+
+#define GATE_VEN20(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven20_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VEN20_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN20(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven20_cg_regs,			\
+		.vote_regs = &ven20_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VEN21(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven21_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_VEN21_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN21(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven21_cg_regs,			\
+		.vote_regs = &ven21_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE		\
+	}
+
+static const struct mtk_gate ven2_clks[] = {
+	/* VEN20 */
+	GATE_VOTE_VEN20(CLK_VEN2_CKE0_LARB, "ven2_larb", "ck2_venc_ck", 0),
+	GATE_VEN20_V(CLK_VEN2_CKE0_LARB_VENC, "ven2_larb_venc", "ven2_larb"),
+	GATE_VEN20_V(CLK_VEN2_CKE0_LARB_JPGENC, "ven2_larb_jpgenc", "ven2_larb"),
+	GATE_VEN20_V(CLK_VEN2_CKE0_LARB_JPGDEC, "ven2_larb_jpgdec", "ven2_larb"),
+	GATE_VEN20_V(CLK_VEN2_CKE0_LARB_SMI, "ven2_larb_smi", "ven2_larb"),
+	GATE_VOTE_VEN20(CLK_VEN2_CKE1_VENC, "ven2_venc", "ck2_venc_ck", 4),
+	GATE_VEN20_V(CLK_VEN2_CKE1_VENC_VENC, "ven2_venc_venc", "ven2_venc"),
+	GATE_VEN20_V(CLK_VEN2_CKE1_VENC_SMI, "ven2_venc_smi", "ven2_venc"),
+	GATE_VEN20(CLK_VEN2_CKE2_JPGENC, "ven2_jpgenc", "ck2_venc_ck", 8),
+	GATE_VEN20_V(CLK_VEN2_CKE2_JPGENC_JPGENC, "ven2_jpgenc_jpgenc", "ven2_jpgenc"),
+	GATE_VEN20(CLK_VEN2_CKE3_JPGDEC, "ven2_jpgdec", "ck2_venc_ck", 12),
+	GATE_VEN20_V(CLK_VEN2_CKE3_JPGDEC_JPGDEC, "ven2_jpgdec_jpgdec", "ven2_jpgdec"),
+	GATE_VOTE_VEN20(CLK_VEN2_CKE5_GALS, "ven2_gals", "ck2_venc_ck", 28),
+	GATE_VEN20_V(CLK_VEN2_CKE5_GALS_VENC, "ven2_gals_venc", "ven2_gals"),
+	GATE_VEN20_V(CLK_VEN2_CKE5_GALS_JPGENC, "ven2_gals_jpgenc", "ven2_gals"),
+	GATE_VEN20_V(CLK_VEN2_CKE5_GALS_JPGDEC, "ven2_gals_jpgdec", "ven2_gals"),
+	GATE_VOTE_VEN20(CLK_VEN2_CKE29_VENC_XPC_CTRL, "ven2_venc_xpc_ctrl", "ck2_venc_ck", 30),
+	GATE_VEN20_V(CLK_VEN2_CKE29_VENC_XPC_CTRL_VENC, "ven2_venc_xpc_ctrl_venc",
+		     "ven2_venc_xpc_ctrl"),
+	GATE_VEN20_V(CLK_VEN2_CKE29_VENC_XPC_CTRL_JPGENC, "ven2_venc_xpc_ctrl_jpgenc",
+		     "ven2_venc_xpc_ctrl"),
+	GATE_VEN20_V(CLK_VEN2_CKE29_VENC_XPC_CTRL_JPGDEC, "ven2_venc_xpc_ctrl_jpgdec",
+		     "ven2_venc_xpc_ctrl"),
+	GATE_VOTE_VEN20(CLK_VEN2_CKE6_GALS_SRAM, "ven2_gals_sram", "ck2_venc_ck", 31),
+	GATE_VEN20_V(CLK_VEN2_CKE6_GALS_SRAM_VENC, "ven2_gals_sram_venc", "ven2_gals_sram"),
+	/* VEN21 */
+	GATE_VOTE_VEN21(CLK_VEN2_RES_FLAT, "ven2_res_flat", "ck2_venc_ck", 0),
+	GATE_VEN21_V(CLK_VEN2_RES_FLAT_VENC, "ven2_res_flat_venc", "ven2_res_flat"),
+	GATE_VEN21_V(CLK_VEN2_RES_FLAT_JPGENC, "ven2_res_flat_jpgenc", "ven2_res_flat"),
+	GATE_VEN21_V(CLK_VEN2_RES_FLAT_JPGDEC, "ven2_res_flat_jpgdec", "ven2_res_flat"),
+};
+
+static const struct mtk_clk_desc ven2_mcd = {
+	.clks = ven2_clks,
+	.num_clks = ARRAY_SIZE(ven2_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct mtk_gate_regs ven_c20_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs ven_c20_vote_regs = {
+	.set_ofs = 0x00d8,
+	.clr_ofs = 0x00dc,
+	.sta_ofs = 0x2c6c,
+};
+
+static const struct mtk_gate_regs ven_c21_cg_regs = {
+	.set_ofs = 0x10,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs ven_c21_vote_regs = {
+	.set_ofs = 0x00e0,
+	.clr_ofs = 0x00e4,
+	.sta_ofs = 0x2c70,
+};
+
+#define GATE_VEN_C20(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven_c20_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VEN_C20_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN_C20(_id, _name, _parent, _shift) {\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven_c20_cg_regs,		\
+		.vote_regs = &ven_c20_vote_regs,	\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VEN_C21(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &ven_c21_cg_regs,		\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_VEN_C21_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VEN_C21(_id, _name, _parent, _shift) {\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &ven_c21_cg_regs,		\
+		.vote_regs = &ven_c21_vote_regs,	\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote,		\
+		.dma_ops = &mtk_clk_gate_ops_setclr,	\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+static const struct mtk_gate ven_c2_clks[] = {
+	/* VEN_C20 */
+	GATE_VOTE_VEN_C20(CLK_VEN_C2_CKE0_LARB, "ven_c2_larb", "ck2_venc_ck", 0),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE0_LARB_VENC, "ven_c2_larb_venc", "ven_c2_larb"),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE0_LARB_SMI, "ven_c2_larb_smi", "ven_c2_larb"),
+	GATE_VOTE_VEN_C20(CLK_VEN_C2_CKE1_VENC, "ven_c2_venc", "ck2_venc_ck", 4),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE1_VENC_VENC, "ven_c2_venc_venc", "ven_c2_venc"),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE1_VENC_SMI, "ven_c2_venc_smi", "ven_c2_venc"),
+	GATE_VOTE_VEN_C20(CLK_VEN_C2_CKE5_GALS, "ven_c2_gals", "ck2_venc_ck", 28),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE5_GALS_VENC, "ven_c2_gals_venc", "ven_c2_gals"),
+	GATE_VOTE_VEN_C20(CLK_VEN_C2_CKE29_VENC_XPC_CTRL, "ven_c2_venc_xpc_ctrl",
+			  "ck2_venc_ck", 30),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE29_VENC_XPC_CTRL_VENC, "ven_c2_venc_xpc_ctrl_venc",
+		       "ven_c2_venc_xpc_ctrl"),
+	GATE_VOTE_VEN_C20(CLK_VEN_C2_CKE6_GALS_SRAM, "ven_c2_gals_sram", "ck2_venc_ck", 31),
+	GATE_VEN_C20_V(CLK_VEN_C2_CKE6_GALS_SRAM_VENC, "ven_c2_gals_sram_venc", "ven_c2_gals_sram"),
+	/* VEN_C21 */
+	GATE_VOTE_VEN_C21(CLK_VEN_C2_RES_FLAT, "ven_c2_res_flat", "ck2_venc_ck", 0),
+	GATE_VEN_C21_V(CLK_VEN_C2_RES_FLAT_VENC, "ven_c2_res_flat_venc", "ven_c2_res_flat"),
+};
+
+static const struct mtk_clk_desc ven_c2_mcd = {
+	.clks = ven_c2_clks,
+	.num_clks = ARRAY_SIZE(ven_c2_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct of_device_id of_match_clk_mt8196_venc[] = {
+	{ .compatible = "mediatek,mt8196-vencsys", .data = &ven1_mcd, },
+	{ .compatible = "mediatek,mt8196-vencsys_c1", .data = &ven2_mcd, },
+	{ .compatible = "mediatek,mt8196-vencsys_c2", .data = &ven_c2_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_venc_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-venc",
+		.of_match_table = of_match_clk_mt8196_venc,
+	},
+};
+
+module_platform_driver(clk_mt8196_venc_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:21 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:21 +0800
Subject: [PATCH 25/26] clk: mediatek: Add MT8196 vdecsys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-26-guangjie.song@mediatek.com>

Add MT8196 vdecsys clock controller which provides clock gate control
for video decoder.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig           |   7 +
 drivers/clk/mediatek/Makefile          |   1 +
 drivers/clk/mediatek/clk-mt8196-vdec.c | 449 +++++++++++++++++++++++++
 3 files changed, 457 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-vdec.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 5fc24f52762a..0c508a8a9959 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1066,6 +1066,13 @@ config COMMON_CLK_MT8196_UFSSYS
 	help
 	  This driver supports MediaTek MT8196 ufssys clocks.
 
+config COMMON_CLK_MT8196_VDECSYS
+	tristate "Clock driver for MediaTek MT8196 vdecsys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 vdecsys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index e5b4a3a61ef7..b8bf3f5f8530 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_MMSYS) += clk-mt8196-disp0.o clk-mt8196-disp1.o c
 					 clk-mt8196-ovl0.o clk-mt8196-ovl1.o
 obj-$(CONFIG_COMMON_CLK_MT8196_PEXTPSYS) += clk-mt8196-pextp.o
 obj-$(CONFIG_COMMON_CLK_MT8196_UFSSYS) += clk-mt8196-ufs_ao.o
+obj-$(CONFIG_COMMON_CLK_MT8196_VDECSYS) += clk-mt8196-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-vdec.c b/drivers/clk/mediatek/clk-mt8196-vdec.c
new file mode 100644
index 000000000000..52accb5b4fb8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-vdec.c
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+static const struct mtk_gate_regs vde20_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs vde20_vote_regs = {
+	.set_ofs = 0x0088,
+	.clr_ofs = 0x008c,
+	.sta_ofs = 0x2c44,
+};
+
+static const struct mtk_gate_regs vde21_cg_regs = {
+	.set_ofs = 0x200,
+	.clr_ofs = 0x204,
+	.sta_ofs = 0x200,
+};
+
+static const struct mtk_gate_regs vde21_vote_regs = {
+	.set_ofs = 0x0080,
+	.clr_ofs = 0x0084,
+	.sta_ofs = 0x2c40,
+};
+
+static const struct mtk_gate_regs vde22_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0xc,
+	.sta_ofs = 0x8,
+};
+
+static const struct mtk_gate_regs vde22_vote_regs = {
+	.set_ofs = 0x0078,
+	.clr_ofs = 0x007c,
+	.sta_ofs = 0x2c3c,
+};
+
+#define GATE_VDE20(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde20_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE20_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE20(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde20_cg_regs,			\
+		.vote_regs = &vde20_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VDE21(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde21_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE21_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE21(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde21_cg_regs,			\
+		.vote_regs = &vde21_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VDE22(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde22_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE22_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE22(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde22_cg_regs,			\
+		.vote_regs = &vde22_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+	}
+
+static const struct mtk_gate vde2_clks[] = {
+	/* VDE20 */
+	GATE_VOTE_VDE20(CLK_VDE2_VDEC_CKEN, "vde2_vdec_cken", "ck2_vdec_ck", 0),
+	GATE_VDE20_V(CLK_VDE2_VDEC_CKEN_VDEC, "vde2_vdec_cken_vdec", "vde2_vdec_cken"),
+	GATE_VOTE_VDE20(CLK_VDE2_VDEC_ACTIVE, "vde2_vdec_active", "ck2_vdec_ck", 4),
+	GATE_VDE20_V(CLK_VDE2_VDEC_ACTIVE_VDEC, "vde2_vdec_active_vdec", "vde2_vdec_active"),
+	GATE_VOTE_VDE20(CLK_VDE2_VDEC_CKEN_ENG, "vde2_vdec_cken_eng", "ck2_vdec_ck", 8),
+	GATE_VDE20_V(CLK_VDE2_VDEC_CKEN_ENG_VDEC, "vde2_vdec_cken_eng_vdec", "vde2_vdec_cken_eng"),
+	/* VDE21 */
+	GATE_VOTE_VDE21(CLK_VDE2_LAT_CKEN, "vde2_lat_cken", "ck2_vdec_ck", 0),
+	GATE_VDE21_V(CLK_VDE2_LAT_CKEN_VDEC, "vde2_lat_cken_vdec", "vde2_lat_cken"),
+	GATE_VOTE_VDE21(CLK_VDE2_LAT_ACTIVE, "vde2_lat_active", "ck2_vdec_ck", 4),
+	GATE_VDE21_V(CLK_VDE2_LAT_ACTIVE_VDEC, "vde2_lat_active_vdec", "vde2_lat_active"),
+	GATE_VOTE_VDE21(CLK_VDE2_LAT_CKEN_ENG, "vde2_lat_cken_eng", "ck2_vdec_ck", 8),
+	GATE_VDE21_V(CLK_VDE2_LAT_CKEN_ENG_VDEC, "vde2_lat_cken_eng_vdec", "vde2_lat_cken_eng"),
+	/* VDE22 */
+	GATE_VOTE_VDE22(CLK_VDE2_LARB1_CKEN, "vde2_larb1_cken", "ck2_vdec_ck", 0),
+	GATE_VDE22_V(CLK_VDE2_LARB1_CKEN_VDEC, "vde2_larb1_cken_vdec", "vde2_larb1_cken"),
+	GATE_VDE22_V(CLK_VDE2_LARB1_CKEN_SMI, "vde2_larb1_cken_smi", "vde2_larb1_cken"),
+};
+
+static const struct mtk_clk_desc vde2_mcd = {
+	.clks = vde2_clks,
+	.num_clks = ARRAY_SIZE(vde2_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct mtk_gate_regs vde10_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs vde10_vote_regs = {
+	.set_ofs = 0x00a0,
+	.clr_ofs = 0x00a4,
+	.sta_ofs = 0x2c50,
+};
+
+static const struct mtk_gate_regs vde11_cg_regs = {
+	.set_ofs = 0x1e0,
+	.clr_ofs = 0x1e0,
+	.sta_ofs = 0x1e0,
+};
+
+static const struct mtk_gate_regs vde11_vote_regs = {
+	.set_ofs = 0x00b0,
+	.clr_ofs = 0x00b4,
+	.sta_ofs = 0x2c58,
+};
+
+static const struct mtk_gate_regs vde12_cg_regs = {
+	.set_ofs = 0x1ec,
+	.clr_ofs = 0x1ec,
+	.sta_ofs = 0x1ec,
+};
+
+static const struct mtk_gate_regs vde12_vote_regs = {
+	.set_ofs = 0x00a8,
+	.clr_ofs = 0x00ac,
+	.sta_ofs = 0x2c54,
+};
+
+static const struct mtk_gate_regs vde13_cg_regs = {
+	.set_ofs = 0x200,
+	.clr_ofs = 0x204,
+	.sta_ofs = 0x200,
+};
+
+static const struct mtk_gate_regs vde13_vote_regs = {
+	.set_ofs = 0x0098,
+	.clr_ofs = 0x009c,
+	.sta_ofs = 0x2c4c,
+};
+
+static const struct mtk_gate_regs vde14_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0xc,
+	.sta_ofs = 0x8,
+};
+
+static const struct mtk_gate_regs vde14_vote_regs = {
+	.set_ofs = 0x0090,
+	.clr_ofs = 0x0094,
+	.sta_ofs = 0x2c48,
+};
+
+#define GATE_VDE10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde10_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE10_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde10_cg_regs,			\
+		.vote_regs = &vde10_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VDE11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde11_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE		\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+#define GATE_VDE11_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE11(_id, _name, _parent, _shift) {		\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.vote_comp = "mm-vote-regmap",			\
+		.regs = &vde11_cg_regs,				\
+		.vote_regs = &vde11_vote_regs,			\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_vote_inv,		\
+		.dma_ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+		.flags = CLK_USE_VOTE |				\
+			 CLK_OPS_PARENT_ENABLE,			\
+	}
+
+#define GATE_VDE12(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde12_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+#define GATE_VDE12_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE12(_id, _name, _parent, _shift) {		\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.vote_comp = "mm-vote-regmap",			\
+		.regs = &vde12_cg_regs,				\
+		.vote_regs = &vde12_vote_regs,			\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_vote_inv,		\
+		.dma_ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+		.flags = CLK_USE_VOTE |				\
+			 CLK_OPS_PARENT_ENABLE			\
+	}
+
+#define GATE_VDE13(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde13_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE13_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE13(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde13_cg_regs,			\
+		.vote_regs = &vde13_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE,		\
+	}
+
+#define GATE_VDE14(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vde14_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE		\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDE14_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_VOTE_VDE14(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.vote_comp = "mm-vote-regmap",		\
+		.regs = &vde14_cg_regs,			\
+		.vote_regs = &vde14_vote_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_vote_inv,	\
+		.dma_ops = &mtk_clk_gate_ops_setclr_inv,\
+		.flags = CLK_USE_VOTE |			\
+			 CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+	}
+
+static const struct mtk_gate vde1_clks[] = {
+	/* VDE10 */
+	GATE_VOTE_VDE10(CLK_VDE1_VDEC_CKEN, "vde1_vdec_cken", "ck2_vdec_ck", 0),
+	GATE_VDE10_V(CLK_VDE1_VDEC_CKEN_VDEC, "vde1_vdec_cken_vdec", "vde1_vdec_cken"),
+	GATE_VOTE_VDE10(CLK_VDE1_VDEC_ACTIVE, "vde1_vdec_active", "ck2_vdec_ck", 4),
+	GATE_VDE10_V(CLK_VDE1_VDEC_ACTIVE_VDEC, "vde1_vdec_active_vdec", "vde1_vdec_active"),
+	GATE_VOTE_VDE10(CLK_VDE1_VDEC_CKEN_ENG, "vde1_vdec_cken_eng", "ck2_vdec_ck", 8),
+	GATE_VDE10_V(CLK_VDE1_VDEC_CKEN_ENG_VDEC, "vde1_vdec_cken_eng_vdec", "vde1_vdec_cken_eng"),
+	/* VDE11 */
+	GATE_VOTE_VDE11(CLK_VDE1_VDEC_SOC_IPS_EN, "vde1_vdec_soc_ips_en", "ck2_vdec_ck", 0),
+	GATE_VDE11_V(CLK_VDE1_VDEC_SOC_IPS_EN_VDEC, "vde1_vdec_soc_ips_en_vdec",
+		     "vde1_vdec_soc_ips_en"),
+	/* VDE12 */
+	GATE_VOTE_VDE12(CLK_VDE1_VDEC_SOC_APTV_EN, "vde1_aptv_en", "ck2_avs_vdec_ck", 0),
+	GATE_VDE12_V(CLK_VDE1_VDEC_SOC_APTV_EN_VDEC, "vde1_aptv_en_vdec", "vde1_aptv_en"),
+	GATE_VOTE_VDE12(CLK_VDE1_VDEC_SOC_APTV_TOP_EN, "vde1_aptv_topen", "ck2_avs_vdec_ck", 1),
+	GATE_VDE12_V(CLK_VDE1_VDEC_SOC_APTV_TOP_EN_VDEC, "vde1_aptv_topen_vdec", "vde1_aptv_topen"),
+	/* VDE13 */
+	GATE_VOTE_VDE13(CLK_VDE1_LAT_CKEN, "vde1_lat_cken", "ck2_vdec_ck", 0),
+	GATE_VDE13_V(CLK_VDE1_LAT_CKEN_VDEC, "vde1_lat_cken_vdec", "vde1_lat_cken"),
+	GATE_VOTE_VDE13(CLK_VDE1_LAT_ACTIVE, "vde1_lat_active", "ck2_vdec_ck", 4),
+	GATE_VDE13_V(CLK_VDE1_LAT_ACTIVE_VDEC, "vde1_lat_active_vdec", "vde1_lat_active"),
+	GATE_VOTE_VDE13(CLK_VDE1_LAT_CKEN_ENG, "vde1_lat_cken_eng", "ck2_vdec_ck", 8),
+	GATE_VDE13_V(CLK_VDE1_LAT_CKEN_ENG_VDEC, "vde1_lat_cken_eng_vdec", "vde1_lat_cken_eng"),
+	/* VDE14 */
+	GATE_VOTE_VDE14(CLK_VDE1_LARB1_CKEN, "vde1_larb1_cken", "ck2_vdec_ck", 0),
+	GATE_VDE14_V(CLK_VDE1_LARB1_CKEN_VDEC, "vde1_larb1_cken_vdec", "vde1_larb1_cken"),
+	GATE_VDE14_V(CLK_VDE1_LARB1_CKEN_SMI, "vde1_larb1_cken_smi", "vde1_larb1_cken"),
+};
+
+static const struct mtk_clk_desc vde1_mcd = {
+	.clks = vde1_clks,
+	.num_clks = ARRAY_SIZE(vde1_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct of_device_id of_match_clk_mt8196_vdec[] = {
+	{ .compatible = "mediatek,mt8196-vdecsys", .data = &vde2_mcd, },
+	{ .compatible = "mediatek,mt8196-vdecsys_soc", .data = &vde1_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_vdec_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-vdec",
+		.of_match_table = of_match_clk_mt8196_vdec,
+	},
+};
+
+module_platform_driver(clk_mt8196_vdec_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From amadeus at jmu.edu.cn  Thu Mar  6 19:35:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 11:35:08 +0800
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <20250305194638.47187-1-ziyao@disroot.org>
References: <20250305194638.47187-1-ziyao@disroot.org>
Message-ID: <20250307033508.656479-1-amadeus@jmu.edu.cn>

Hi,

> +&sdmmc {
> +	bus-width = <4>;
> +	cap-mmc-highspeed;
> +	cap-sd-highspeed;
> +	disable-wp;
> +	no-sdio;

With 'no-sdio' property:
[  129.608986] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
[  130.711168] mmc1: Card stuck being busy! __mmc_poll_for_busy
[  130.725536] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
[  131.751240] mmc1: Card stuck being busy! __mmc_poll_for_busy
[  131.765608] mmc_host mmc1: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
[  132.825083] mmc1: Card stuck being busy! __mmc_poll_for_busy
[  132.839413] mmc_host mmc1: Bus speed (slot 0) = 187500Hz (slot req 187500Hz, actual 187500HZ div = 0)
[  133.960141] mmc1: Card stuck being busy! __mmc_poll_for_busy

Without 'no-sdio' property:
[  105.224019] mmc1: error -22 whilst initialising SDIO card
[  106.290838] mmc1: Card stuck being busy! __mmc_poll_for_busy
[  106.801931] dwmmc_rockchip ffc30000.mmc: Busy; trying anyway
[  107.385835] mmc_host mmc1: Timeou sending command (cmd 0x202000 arg 0x0 status 0x80202000)
[  107.400425] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
[  107.431561] mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 50000000Hz, actual 49800000HZ div = 0)
[  107.433107] mmc1: new high speed SDIO card at address 0001

# cat /sys/kernel/debug/mmc1/ios
clock:          50000000 Hz
vdd:            21 (3.3 ~ 3.4 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    2 (sd high-speed)
signal voltage: 0 (3.30 V)
driver type:    0 (driver type B)

Thanks,
Chukun

-- 
2.25.1



From guangjie.song at mediatek.com  Thu Mar  6 19:44:24 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:24 +0800
Subject: [PATCH 00/13] pmdomain: mediatek: Add MT8196 power domain
Message-ID: <20250307034454.12243-1-guangjie.song@mediatek.com>

This series is based on linux-next, tag: next-20250306.

Changes:
- Update mtk-scpsys driver for MT8196
- Add MT8196 power domain support

Guangjie Song (13):
  pmdomain: mediatek: Support sram isolation
  pmdomain: mediatek: Support sram low power
  pmdomain: mediatek: Support power on bypass
  pmdomain: mediatek: Support check power on/off ack
  pmdomain: mediatek: Support voting for power domain
  pmdomain: mediatek: Support trigger subsys save/restore regesters
  pmdomain: mediatek: Support power domain irq safe
  pmdomain: mediatek: Support power domain always on
  pmdomain: mediatek: Refactor parameters of init_scp
  pmdomain: mediatek: Support bus protect with table
  pmdomain: mediatek: Add post init callback
  dt-bindings: power: mediatek: Add new MT8196 power domain
  pmdomain: mediatek: Add MT8196 power domain support

 .../mediatek,mt8196-power-controller.yaml     |   74 +
 drivers/pmdomain/mediatek/mt8196-scpsys.h     |  114 ++
 drivers/pmdomain/mediatek/mtk-scpsys.c        | 1276 ++++++++++++++++-
 include/dt-bindings/power/mt8196-power.h      |   57 +
 4 files changed, 1483 insertions(+), 38 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
 create mode 100644 drivers/pmdomain/mediatek/mt8196-scpsys.h
 create mode 100644 include/dt-bindings/power/mt8196-power.h

-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:28 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:28 +0800
Subject: [PATCH 04/13] pmdomain: mediatek: Support check power on/off ack
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-5-guangjie.song@mediatek.com>

Support check ack bits for pmdomain on/off.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 50 +++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 3c8b5d8e7ee9..2f75c606f7ba 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -22,12 +22,14 @@
 
 #define MTK_POLL_DELAY_US   10
 #define MTK_POLL_TIMEOUT    USEC_PER_SEC
+#define MTK_ACK_DELAY_US		50
 
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
 #define MTK_SCPD_SRAM_ISO		BIT(2)
 #define MTK_SCPD_SRAM_SLP		BIT(3)
 #define MTK_SCPD_BYPASS_INIT_ON		BIT(4)
+#define MTK_SCPD_IS_PWR_CON_ON		BIT(5)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -61,6 +63,8 @@
 #define PWR_CLK_DIS_BIT			BIT(4)
 #define PWR_SRAM_CLKISO_BIT		BIT(5)
 #define PWR_SRAM_ISOINT_B_BIT		BIT(6)
+#define PWR_ACK				BIT(30)
+#define PWR_ACK_2ND			BIT(31)
 
 #define PWR_STATUS_CONN			BIT(1)
 #define PWR_STATUS_DISP			BIT(3)
@@ -200,6 +204,20 @@ static int scpsys_domain_is_on(struct scp_domain *scpd)
 	return -EINVAL;
 }
 
+static int scpsys_pwr_ack_is_on(struct scp_domain *scpd)
+{
+	u32 status = readl(scpd->scp->base + scpd->data->ctl_offs) & PWR_ACK;
+
+	return status ? true : false;
+}
+
+static int scpsys_pwr_ack_2nd_is_on(struct scp_domain *scpd)
+{
+	u32 status = readl(scpd->scp->base + scpd->data->ctl_offs) & PWR_ACK_2ND;
+
+	return status ? true : false;
+}
+
 static int scpsys_regulator_enable(struct scp_domain *scpd)
 {
 	if (!scpd->supply)
@@ -360,12 +378,25 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	val = readl(ctl_addr);
 	val |= PWR_ON_BIT;
 	writel(val, ctl_addr);
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IS_PWR_CON_ON)) {
+		ret = readx_poll_timeout_atomic(scpsys_pwr_ack_is_on, scpd, tmp, tmp > 0,
+						MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+		if (ret < 0)
+			goto err_pwr_ack;
+
+		udelay(MTK_ACK_DELAY_US);
+	}
+
 	val |= PWR_ON_2ND_BIT;
 	writel(val, ctl_addr);
 
 	/* wait until PWR_ACK = 1 */
-	ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
-				 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IS_PWR_CON_ON))
+		ret = readx_poll_timeout_atomic(scpsys_pwr_ack_2nd_is_on, scpd, tmp, tmp > 0,
+						MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	else
+		ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
+					 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 	if (ret < 0)
 		goto err_pwr_ack;
 
@@ -428,12 +459,23 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	val &= ~PWR_ON_BIT;
 	writel(val, ctl_addr);
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IS_PWR_CON_ON)) {
+		ret = readx_poll_timeout_atomic(scpsys_pwr_ack_is_on, scpd, tmp, tmp == 0,
+						MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+		if (ret < 0)
+			goto out;
+	}
+
 	val &= ~PWR_ON_2ND_BIT;
 	writel(val, ctl_addr);
 
 	/* wait until PWR_ACK = 0 */
-	ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
-				 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IS_PWR_CON_ON))
+		ret = readx_poll_timeout_atomic(scpsys_pwr_ack_2nd_is_on, scpd, tmp, tmp == 0,
+						MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	else
+		ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
+					 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 	if (ret < 0)
 		goto out;
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:25 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:25 +0800
Subject: [PATCH 01/13] pmdomain: mediatek: Support sram isolation
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-2-guangjie.song@mediatek.com>

Support sram isolation to isolate signals and prevent current leakage.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 1a80c1537a43..d53bd07a6804 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -25,6 +25,7 @@
 
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
+#define MTK_SCPD_SRAM_ISO		BIT(2)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -56,6 +57,8 @@
 #define PWR_ON_BIT			BIT(2)
 #define PWR_ON_2ND_BIT			BIT(3)
 #define PWR_CLK_DIS_BIT			BIT(4)
+#define PWR_SRAM_CLKISO_BIT		BIT(5)
+#define PWR_SRAM_ISOINT_B_BIT		BIT(6)
 
 #define PWR_STATUS_CONN			BIT(1)
 #define PWR_STATUS_DISP			BIT(3)
@@ -257,6 +260,14 @@ static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
 			return ret;
 	}
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_SRAM_ISO)) {
+		val = readl(ctl_addr) | PWR_SRAM_ISOINT_B_BIT;
+		writel(val, ctl_addr);
+		udelay(1);
+		val &= ~PWR_SRAM_CLKISO_BIT;
+		writel(val, ctl_addr);
+	}
+
 	return 0;
 }
 
@@ -266,6 +277,14 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
 	int tmp;
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_SRAM_ISO)) {
+		val = readl(ctl_addr) | PWR_SRAM_CLKISO_BIT;
+		writel(val, ctl_addr);
+		val &= ~PWR_SRAM_ISOINT_B_BIT;
+		writel(val, ctl_addr);
+		udelay(1);
+	}
+
 	val = readl(ctl_addr);
 	val |= scpd->data->sram_pdn_bits;
 	writel(val, ctl_addr);
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:27 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:27 +0800
Subject: [PATCH 03/13] pmdomain: mediatek: Support power on bypass
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-4-guangjie.song@mediatek.com>

Support power on bypass in pmdomain driver probe.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 9d03249284d6..3c8b5d8e7ee9 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -27,6 +27,7 @@
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
 #define MTK_SCPD_SRAM_ISO		BIT(2)
 #define MTK_SCPD_SRAM_SLP		BIT(3)
+#define MTK_SCPD_BYPASS_INIT_ON		BIT(4)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -569,7 +570,10 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 		 * software.  The unused domains will be switched off during
 		 * late_init time.
 		 */
-		on = !WARN_ON(genpd->power_on(genpd) < 0);
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_BYPASS_INIT_ON))
+			on = false;
+		else
+			on = !WARN_ON(genpd->power_on(genpd) < 0);
 
 		pm_genpd_init(genpd, NULL, !on);
 	}
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:26 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:26 +0800
Subject: [PATCH 02/13] pmdomain: mediatek: Support sram low power
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-3-guangjie.song@mediatek.com>

Support sram enter/exit low power mode.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 36 ++++++++++++++++++++------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index d53bd07a6804..9d03249284d6 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -26,6 +26,7 @@
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
 #define MTK_SCPD_SRAM_ISO		BIT(2)
+#define MTK_SCPD_SRAM_SLP		BIT(3)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -118,6 +119,8 @@ static const char * const clk_names[] = {
  * @ctl_offs: The offset for main power control register.
  * @sram_pdn_bits: The mask for sram power control bits.
  * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @sram_slp_bits: The mask for sram low power control bits.
+ * @sram_slp_ack_bits: The mask for sram low power control acked bits.
  * @bus_prot_mask: The mask for single step bus protection.
  * @clk_id: The basic clocks required by this power domain.
  * @caps: The flag for active wake-up action.
@@ -128,6 +131,8 @@ struct scp_domain_data {
 	int ctl_offs;
 	u32 sram_pdn_bits;
 	u32 sram_pdn_ack_bits;
+	u32 sram_slp_bits;
+	u32 sram_slp_ack_bits;
 	u32 bus_prot_mask;
 	enum clk_id clk_id[MAX_CLKS];
 	u8 caps;
@@ -236,11 +241,19 @@ static int scpsys_clk_enable(struct clk *clk[], int max_num)
 static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
 {
 	u32 val;
-	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+	u32 ack_mask, ack_sta;
 	int tmp;
 
-	val = readl(ctl_addr);
-	val &= ~scpd->data->sram_pdn_bits;
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_SRAM_SLP)) {
+		ack_mask = scpd->data->sram_slp_ack_bits;
+		ack_sta = ack_mask;
+		val = readl(ctl_addr) | scpd->data->sram_slp_bits;
+	} else {
+		ack_mask = scpd->data->sram_pdn_ack_bits;
+		ack_sta = 0;
+		val = readl(ctl_addr) & ~scpd->data->sram_pdn_bits;
+	}
+
 	writel(val, ctl_addr);
 
 	/* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
@@ -254,7 +267,7 @@ static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
 	} else {
 		/* Either wait until SRAM_PDN_ACK all 1 or 0 */
 		int ret = readl_poll_timeout(ctl_addr, tmp,
-				(tmp & pdn_ack) == 0,
+				(tmp & ack_mask) == ack_sta,
 				MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 		if (ret < 0)
 			return ret;
@@ -274,7 +287,7 @@ static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
 static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 {
 	u32 val;
-	u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+	u32 ack_mask, ack_sta;
 	int tmp;
 
 	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_SRAM_ISO)) {
@@ -285,13 +298,20 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 		udelay(1);
 	}
 
-	val = readl(ctl_addr);
-	val |= scpd->data->sram_pdn_bits;
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_SRAM_SLP)) {
+		ack_mask = scpd->data->sram_slp_ack_bits;
+		ack_sta = 0;
+		val = readl(ctl_addr) & ~scpd->data->sram_slp_bits;
+	} else {
+		ack_mask = scpd->data->sram_pdn_ack_bits;
+		ack_sta = ack_mask;
+		val = readl(ctl_addr) | scpd->data->sram_pdn_bits;
+	}
 	writel(val, ctl_addr);
 
 	/* Either wait until SRAM_PDN_ACK all 1 or 0 */
 	return readl_poll_timeout(ctl_addr, tmp,
-			(tmp & pdn_ack) == pdn_ack,
+			(tmp & ack_mask) == ack_sta,
 			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 }
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:29 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:29 +0800
Subject: [PATCH 05/13] pmdomain: mediatek: Support voting for power domain
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-6-guangjie.song@mediatek.com>

Power domain supports voting mechanism. If any xPU votes power domain
on, the power domain keep on.
Add power domain vote support.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 207 ++++++++++++++++++++++++-
 1 file changed, 205 insertions(+), 2 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 2f75c606f7ba..df9cd012006c 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -10,6 +10,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/soc/mediatek/infracfg.h>
 
@@ -22,7 +23,12 @@
 
 #define MTK_POLL_DELAY_US   10
 #define MTK_POLL_TIMEOUT    USEC_PER_SEC
+#define MTK_POLL_TIMEOUT_300MS		(300 * USEC_PER_MSEC)
+#define MTK_POLL_IRQ_TIMEOUT		USEC_PER_SEC
+#define MTK_POLL_VOTE_PREPARE_CNT	2500
+#define MTK_POLL_VOTE_PREPARE_US	2
 #define MTK_ACK_DELAY_US		50
+#define MTK_STABLE_DELAY_US		100
 
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
@@ -30,6 +36,7 @@
 #define MTK_SCPD_SRAM_SLP		BIT(3)
 #define MTK_SCPD_BYPASS_INIT_ON		BIT(4)
 #define MTK_SCPD_IS_PWR_CON_ON		BIT(5)
+#define MTK_SCPD_VOTE_OPS		BIT(6)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -120,8 +127,18 @@ static const char * const clk_names[] = {
 /**
  * struct scp_domain_data - scp domain data for power on/off flow
  * @name: The domain name.
+ * @vote_comp: The vote name.
  * @sta_mask: The mask for power on/off status bit.
  * @ctl_offs: The offset for main power control register.
+ * @vote_done_ofs: The offset for vote done register.
+ * @vote_ofs: The offset for vote register.
+ * @vote_set_ofs: The offset for vote set register.
+ * @vote_clr_ofs: The offset for vote clear register.
+ * @vote_en_ofs: The offset for voted register.
+ * @vote_set_sta_ofs: The offset for vote set status register.
+ * @vote_clr_sta_ofs: The offset for vote clear status register.
+ * @vote_ack_ofs: The offset for power control ack register.
+ * @vote_shift: The bit of vote.
  * @sram_pdn_bits: The mask for sram power control bits.
  * @sram_pdn_ack_bits: The mask for sram power control acked bits.
  * @sram_slp_bits: The mask for sram low power control bits.
@@ -132,8 +149,18 @@ static const char * const clk_names[] = {
  */
 struct scp_domain_data {
 	const char *name;
+	const char *vote_comp;
 	u32 sta_mask;
 	int ctl_offs;
+	u32 vote_done_ofs;
+	u32 vote_ofs;
+	u32 vote_set_ofs;
+	u32 vote_clr_ofs;
+	u32 vote_en_ofs;
+	u32 vote_set_sta_ofs;
+	u32 vote_clr_sta_ofs;
+	u32 vote_ack_ofs;
+	u8 vote_shift;
 	u32 sram_pdn_bits;
 	u32 sram_pdn_ack_bits;
 	u32 sram_slp_bits;
@@ -151,6 +178,7 @@ struct scp_domain {
 	struct clk *clk[MAX_CLKS];
 	const struct scp_domain_data *data;
 	struct regulator *supply;
+	struct regmap *vote_regmap;
 };
 
 struct scp_ctrl_reg {
@@ -493,6 +521,154 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 	return ret;
 }
 
+static int mtk_vote_is_done(struct scp_domain *scpd)
+{
+	u32 val = 0, mask = 0;
+
+	regmap_read(scpd->vote_regmap, scpd->data->vote_done_ofs, &val);
+	mask = BIT(scpd->data->vote_shift);
+	if ((val & mask) == mask)
+		return 1;
+
+	return 0;
+}
+
+static int mtk_vote_is_enable_done(struct scp_domain *scpd)
+{
+	u32 done = 0, en = 0, set_sta = 0, mask = 0, ack = 0;
+
+	regmap_read(scpd->vote_regmap, scpd->data->vote_done_ofs, &done);
+	regmap_read(scpd->vote_regmap, scpd->data->vote_en_ofs, &en);
+	regmap_read(scpd->vote_regmap, scpd->data->vote_set_sta_ofs, &set_sta);
+	mask = BIT(scpd->data->vote_shift);
+
+	if ((done & mask) && (en & mask) && !(set_sta & mask)) {
+		if (scpd->data->vote_ack_ofs) {
+			regmap_read(scpd->vote_regmap, scpd->data->vote_ack_ofs, &ack);
+			if (!(ack & mask))
+				return 0;
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mtk_vote_is_disable_done(struct scp_domain *scpd)
+{
+	u32 val = 0, val2 = 0;
+
+	regmap_read(scpd->vote_regmap, scpd->data->vote_done_ofs, &val);
+	regmap_read(scpd->vote_regmap, scpd->data->vote_clr_sta_ofs, &val2);
+
+	if ((val & BIT(scpd->data->vote_shift)) &&
+	    ((val2 & BIT(scpd->data->vote_shift)) == 0x0))
+		return 1;
+
+	return 0;
+}
+
+static int scpsys_vote_power_on(struct generic_pm_domain *genpd)
+{
+	struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+	struct scp *scp = scpd->scp;
+	u32 val = 0;
+	int ret = 0;
+	int tmp;
+	int i = 0;
+
+	ret = scpsys_regulator_enable(scpd);
+	if (ret < 0)
+		goto out;
+
+	ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
+	if (ret)
+		goto out;
+
+	ret = readx_poll_timeout_atomic(mtk_vote_is_done, scpd, tmp, tmp > 0,
+					MTK_POLL_DELAY_US, MTK_POLL_IRQ_TIMEOUT);
+	if (ret < 0)
+		goto out;
+
+	val = BIT(scpd->data->vote_shift);
+	regmap_write(scpd->vote_regmap, scpd->data->vote_set_ofs, val);
+	do {
+		regmap_read(scpd->vote_regmap, scpd->data->vote_set_ofs, &val);
+		if ((val & BIT(scpd->data->vote_shift)) != 0)
+			break;
+
+		if (i > MTK_POLL_VOTE_PREPARE_CNT)
+			goto out;
+
+		udelay(MTK_POLL_VOTE_PREPARE_US);
+		i++;
+	} while (1);
+
+	/* add debounce time */
+	udelay(1);
+
+	/* wait until VOTER_ACK = 1 */
+	ret = readx_poll_timeout_atomic(mtk_vote_is_enable_done, scpd, tmp, tmp > 0,
+					MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT_300MS);
+	if (ret < 0)
+		goto out;
+
+	return 0;
+out:
+	dev_err(scp->dev, "Failed to power on domain %s(%d)\n", genpd->name, ret);
+	return ret;
+}
+
+static int scpsys_vote_power_off(struct generic_pm_domain *genpd)
+{
+	struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+	struct scp *scp = scpd->scp;
+	u32 val = 0;
+	int ret = 0;
+	int tmp;
+	int i = 0;
+
+	ret = readx_poll_timeout_atomic(mtk_vote_is_done, scpd, tmp, tmp > 0,
+					MTK_POLL_DELAY_US, MTK_POLL_IRQ_TIMEOUT);
+	if (ret < 0)
+		goto out;
+
+	val = BIT(scpd->data->vote_shift);
+	regmap_write(scpd->vote_regmap, scpd->data->vote_clr_ofs, val);
+	do {
+		regmap_read(scpd->vote_regmap, scpd->data->vote_clr_ofs, &val);
+		if ((val & BIT(scpd->data->vote_shift)) == 0)
+			break;
+
+		if (i > MTK_POLL_VOTE_PREPARE_CNT)
+			goto out;
+
+		i++;
+		udelay(MTK_POLL_VOTE_PREPARE_US);
+	} while (1);
+
+	/* delay 100us for stable status */
+	udelay(MTK_STABLE_DELAY_US);
+
+	/* wait until VOTER_ACK = 0 */
+	ret = readx_poll_timeout_atomic(mtk_vote_is_disable_done, scpd, tmp, tmp > 0,
+					MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT_300MS);
+	if (ret < 0)
+		goto out;
+
+	scpsys_clk_disable(scpd->clk, MAX_CLKS);
+
+	ret = scpsys_regulator_disable(scpd);
+	if (ret < 0)
+		goto out;
+
+	return 0;
+out:
+	dev_err(scp->dev, "Failed to power off domain %s(%d)\n", genpd->name, ret);
+	return ret;
+}
+
 static void init_clks(struct platform_device *pdev, struct clk **clk)
 {
 	int i;
@@ -501,6 +677,21 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
 		clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
 }
 
+static int mtk_pd_get_regmap(struct platform_device *pdev, struct regmap **regmap,
+			     const char *name)
+{
+	*regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, name);
+	if (PTR_ERR(*regmap) == -ENODEV) {
+		dev_notice(&pdev->dev, "%s regmap is null(%ld)\n", name, PTR_ERR(*regmap));
+		*regmap = NULL;
+	} else if (IS_ERR(*regmap)) {
+		dev_notice(&pdev->dev, "Cannot find %s controller: %ld\n", name, PTR_ERR(*regmap));
+		return PTR_ERR(*regmap);
+	}
+
+	return 0;
+}
+
 static struct scp *init_scp(struct platform_device *pdev,
 			const struct scp_domain_data *scp_domain_data, int num,
 			const struct scp_ctrl_reg *scp_ctrl_reg,
@@ -510,6 +701,7 @@ static struct scp *init_scp(struct platform_device *pdev,
 	int i, j;
 	struct scp *scp;
 	struct clk *clk[CLK_MAX];
+	int ret;
 
 	scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
 	if (!scp)
@@ -585,9 +777,20 @@ static struct scp *init_scp(struct platform_device *pdev,
 			scpd->clk[j] = c;
 		}
 
+		if (data->vote_comp) {
+			ret = mtk_pd_get_regmap(pdev, &scpd->vote_regmap, data->vote_comp);
+			if (ret)
+				return ERR_PTR(ret);
+		}
+
 		genpd->name = data->name;
-		genpd->power_off = scpsys_power_off;
-		genpd->power_on = scpsys_power_on;
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_VOTE_OPS)) {
+			genpd->power_on = scpsys_vote_power_on;
+			genpd->power_off = scpsys_vote_power_off;
+		} else {
+			genpd->power_off = scpsys_power_off;
+			genpd->power_on = scpsys_power_on;
+		}
 		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
 			genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
 	}
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:30 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:30 +0800
Subject: [PATCH 06/13] pmdomain: mediatek: Support trigger subsys save/restore regesters
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-7-guangjie.song@mediatek.com>

Support trigger subsys save/restore registers during power domain
on/off.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 106 ++++++++++++++++++++++++-
 1 file changed, 105 insertions(+), 1 deletion(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index df9cd012006c..0ae4c617b5a6 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -28,6 +28,7 @@
 #define MTK_POLL_VOTE_PREPARE_CNT	2500
 #define MTK_POLL_VOTE_PREPARE_US	2
 #define MTK_ACK_DELAY_US		50
+#define MTK_RTFF_DELAY_US		10
 #define MTK_STABLE_DELAY_US		100
 
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
@@ -37,6 +38,10 @@
 #define MTK_SCPD_BYPASS_INIT_ON		BIT(4)
 #define MTK_SCPD_IS_PWR_CON_ON		BIT(5)
 #define MTK_SCPD_VOTE_OPS		BIT(6)
+#define MTK_SCPD_NON_CPU_RTFF		BIT(7)
+#define MTK_SCPD_PEXTP_PHY_RTFF		BIT(8)
+#define MTK_SCPD_UFS_RTFF		BIT(9)
+#define MTK_SCPD_RTFF_DELAY		BIT(10)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -70,6 +75,11 @@
 #define PWR_CLK_DIS_BIT			BIT(4)
 #define PWR_SRAM_CLKISO_BIT		BIT(5)
 #define PWR_SRAM_ISOINT_B_BIT		BIT(6)
+#define PWR_RTFF_SAVE			BIT(24)
+#define PWR_RTFF_NRESTORE		BIT(25)
+#define PWR_RTFF_CLK_DIS		BIT(26)
+#define PWR_RTFF_SAVE_FLAG		BIT(27)
+#define PWR_RTFF_UFS_CLK_DIS		BIT(28)
 #define PWR_ACK				BIT(30)
 #define PWR_ACK_2ND			BIT(31)
 
@@ -167,7 +177,7 @@ struct scp_domain_data {
 	u32 sram_slp_ack_bits;
 	u32 bus_prot_mask;
 	enum clk_id clk_id[MAX_CLKS];
-	u8 caps;
+	u32 caps;
 };
 
 struct scp;
@@ -179,6 +189,7 @@ struct scp_domain {
 	const struct scp_domain_data *data;
 	struct regulator *supply;
 	struct regmap *vote_regmap;
+	bool rtff_flag;
 };
 
 struct scp_ctrl_reg {
@@ -428,15 +439,72 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 	if (ret < 0)
 		goto err_pwr_ack;
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_PEXTP_PHY_RTFF) && scpd->rtff_flag) {
+		val |= PWR_RTFF_CLK_DIS;
+		writel(val, ctl_addr);
+	}
+
 	val &= ~PWR_CLK_DIS_BIT;
 	writel(val, ctl_addr);
 
 	val &= ~PWR_ISO_BIT;
 	writel(val, ctl_addr);
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_RTFF_DELAY) && scpd->rtff_flag)
+		udelay(MTK_RTFF_DELAY_US);
+
 	val |= PWR_RST_B_BIT;
 	writel(val, ctl_addr);
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_NON_CPU_RTFF)) {
+		val = readl(ctl_addr);
+		if (val & PWR_RTFF_SAVE_FLAG) {
+			val &= ~PWR_RTFF_SAVE_FLAG;
+			writel(val, ctl_addr);
+
+			val |= PWR_RTFF_CLK_DIS;
+			writel(val, ctl_addr);
+
+			val &= ~PWR_RTFF_NRESTORE;
+			writel(val, ctl_addr);
+
+			val |= PWR_RTFF_NRESTORE;
+			writel(val, ctl_addr);
+
+			val &= ~PWR_RTFF_CLK_DIS;
+			writel(val, ctl_addr);
+		}
+	} else if (MTK_SCPD_CAPS(scpd, MTK_SCPD_PEXTP_PHY_RTFF)) {
+		val = readl(ctl_addr);
+		if (val & PWR_RTFF_SAVE_FLAG) {
+			val &= ~PWR_RTFF_SAVE_FLAG;
+			writel(val, ctl_addr);
+
+			val &= ~PWR_RTFF_NRESTORE;
+			writel(val, ctl_addr);
+
+			val |= PWR_RTFF_NRESTORE;
+			writel(val, ctl_addr);
+
+			val &= ~PWR_RTFF_CLK_DIS;
+			writel(val, ctl_addr);
+		}
+	} else if (MTK_SCPD_CAPS(scpd, MTK_SCPD_UFS_RTFF) && scpd->rtff_flag) {
+		val |= PWR_RTFF_UFS_CLK_DIS;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_NRESTORE;
+		writel(val, ctl_addr);
+
+		val |= PWR_RTFF_NRESTORE;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_UFS_CLK_DIS;
+		writel(val, ctl_addr);
+
+		scpd->rtff_flag = false;
+	}
+
 	ret = scpsys_sram_enable(scpd, ctl_addr);
 	if (ret < 0)
 		goto err_pwr_ack;
@@ -475,9 +543,45 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 
 	/* subsys power off */
 	val = readl(ctl_addr);
+
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_NON_CPU_RTFF) ||
+	    MTK_SCPD_CAPS(scpd, MTK_SCPD_PEXTP_PHY_RTFF)) {
+		val |= PWR_RTFF_CLK_DIS;
+		writel(val, ctl_addr);
+
+		val |= PWR_RTFF_SAVE;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_SAVE;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_CLK_DIS;
+		writel(val, ctl_addr);
+
+		val |= PWR_RTFF_SAVE_FLAG;
+		writel(val, ctl_addr);
+	} else if (MTK_SCPD_CAPS(scpd, MTK_SCPD_UFS_RTFF)) {
+		val |= PWR_RTFF_UFS_CLK_DIS;
+		writel(val, ctl_addr);
+
+		val |= PWR_RTFF_SAVE;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_SAVE;
+		writel(val, ctl_addr);
+
+		val &= ~PWR_RTFF_UFS_CLK_DIS;
+		writel(val, ctl_addr);
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_UFS_RTFF))
+			scpd->rtff_flag = true;
+	}
+
 	val |= PWR_ISO_BIT;
 	writel(val, ctl_addr);
 
+	if (MTK_SCPD_CAPS(scpd, MTK_SCPD_RTFF_DELAY) && scpd->rtff_flag)
+		udelay(1);
+
 	val &= ~PWR_RST_B_BIT;
 	writel(val, ctl_addr);
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:33 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:33 +0800
Subject: [PATCH 09/13] pmdomain: mediatek: Refactor parameters of init_scp
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-10-guangjie.song@mediatek.com>

Refactor parameters of init_scp which will use other fields of soc data.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 28 +++++++++++---------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index f0a5e1653b5f..47d5d5abcaee 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -798,10 +798,7 @@ static int mtk_pd_get_regmap(struct platform_device *pdev, struct regmap **regma
 	return 0;
 }
 
-static struct scp *init_scp(struct platform_device *pdev,
-			const struct scp_domain_data *scp_domain_data, int num,
-			const struct scp_ctrl_reg *scp_ctrl_reg,
-			bool bus_prot_reg_update)
+static struct scp *init_scp(struct platform_device *pdev, const struct scp_soc_data *soc)
 {
 	struct genpd_onecell_data *pd_data;
 	int i, j;
@@ -813,10 +810,10 @@ static struct scp *init_scp(struct platform_device *pdev,
 	if (!scp)
 		return ERR_PTR(-ENOMEM);
 
-	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
-	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
+	scp->ctrl_reg.pwr_sta_offs = soc->regs.pwr_sta_offs;
+	scp->ctrl_reg.pwr_sta2nd_offs = soc->regs.pwr_sta2nd_offs;
 
-	scp->bus_prot_reg_update = bus_prot_reg_update;
+	scp->bus_prot_reg_update = soc->bus_prot_reg_update;
 
 	scp->dev = &pdev->dev;
 
@@ -825,14 +822,14 @@ static struct scp *init_scp(struct platform_device *pdev,
 		return ERR_CAST(scp->base);
 
 	scp->domains = devm_kcalloc(&pdev->dev,
-				num, sizeof(*scp->domains), GFP_KERNEL);
+				soc->num_domains, sizeof(*scp->domains), GFP_KERNEL);
 	if (!scp->domains)
 		return ERR_PTR(-ENOMEM);
 
 	pd_data = &scp->pd_data;
 
 	pd_data->domains = devm_kcalloc(&pdev->dev,
-			num, sizeof(*pd_data->domains), GFP_KERNEL);
+			soc->num_domains, sizeof(*pd_data->domains), GFP_KERNEL);
 	if (!pd_data->domains)
 		return ERR_PTR(-ENOMEM);
 
@@ -844,9 +841,9 @@ static struct scp *init_scp(struct platform_device *pdev,
 		return ERR_CAST(scp->infracfg);
 	}
 
-	for (i = 0; i < num; i++) {
+	for (i = 0; i < soc->num_domains; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
-		const struct scp_domain_data *data = &scp_domain_data[i];
+		const struct scp_domain_data *data = &soc->domains[i];
 
 		scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
 		if (IS_ERR(scpd->supply)) {
@@ -857,14 +854,14 @@ static struct scp *init_scp(struct platform_device *pdev,
 		}
 	}
 
-	pd_data->num_domains = num;
+	pd_data->num_domains = soc->num_domains;
 
 	init_clks(pdev, clk);
 
-	for (i = 0; i < num; i++) {
+	for (i = 0; i < soc->num_domains; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		struct generic_pm_domain *genpd = &scpd->genpd;
-		const struct scp_domain_data *data = &scp_domain_data[i];
+		const struct scp_domain_data *data = &soc->domains[i];
 
 		pd_data->domains[i] = genpd;
 		scpd->scp = scp;
@@ -1511,8 +1508,7 @@ static int scpsys_probe(struct platform_device *pdev)
 
 	soc = of_device_get_match_data(&pdev->dev);
 
-	scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
-			soc->bus_prot_reg_update);
+	scp = init_scp(pdev, soc);
 	if (IS_ERR(scp))
 		return PTR_ERR(scp);
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:32 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:32 +0800
Subject: [PATCH 08/13] pmdomain: mediatek: Support power domain always on
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-9-guangjie.song@mediatek.com>

Support power domain always on with MTK_SCPD_ALWAYS_ON.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 467c54e24bea..f0a5e1653b5f 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -43,6 +43,7 @@
 #define MTK_SCPD_UFS_RTFF		BIT(9)
 #define MTK_SCPD_RTFF_DELAY		BIT(10)
 #define MTK_SCPD_IRQ_SAFE		BIT(11)
+#define MTK_SCPD_ALWAYS_ON		BIT(12)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -900,6 +901,8 @@ static struct scp *init_scp(struct platform_device *pdev,
 			genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
 		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IRQ_SAFE))
 			genpd->flags |= GENPD_FLAG_IRQ_SAFE;
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ALWAYS_ON))
+			genpd->flags |= GENPD_FLAG_ALWAYS_ON;
 	}
 
 	return scp;
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:31 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:31 +0800
Subject: [PATCH 07/13] pmdomain: mediatek: Support power domain irq safe
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-8-guangjie.song@mediatek.com>

Support power domain is irq safe with MTK_SCPD_IRQ_SAFE.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 0ae4c617b5a6..467c54e24bea 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -42,6 +42,7 @@
 #define MTK_SCPD_PEXTP_PHY_RTFF		BIT(8)
 #define MTK_SCPD_UFS_RTFF		BIT(9)
 #define MTK_SCPD_RTFF_DELAY		BIT(10)
+#define MTK_SCPD_IRQ_SAFE		BIT(11)
 #define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -897,6 +898,8 @@ static struct scp *init_scp(struct platform_device *pdev,
 		}
 		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
 			genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_IRQ_SAFE))
+			genpd->flags |= GENPD_FLAG_IRQ_SAFE;
 	}
 
 	return scp;
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:34 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:34 +0800
Subject: [PATCH 10/13] pmdomain: mediatek: Support bus protect with table
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-11-guangjie.song@mediatek.com>

Support bus protect with table which can contain multiple items.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 179 ++++++++++++++++++++++++-
 1 file changed, 173 insertions(+), 6 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 47d5d5abcaee..c10756fa1685 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -31,6 +31,8 @@
 #define MTK_RTFF_DELAY_US		10
 #define MTK_STABLE_DELAY_US		100
 
+#define MTK_BUS_PROTECTION_RETY_TIMES	10
+
 #define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
 #define MTK_SCPD_FWAIT_SRAM		BIT(1)
 #define MTK_SCPD_SRAM_ISO		BIT(2)
@@ -106,6 +108,24 @@
 #define PWR_STATUS_HIF1			BIT(26)	/* MT7622 */
 #define PWR_STATUS_WB			BIT(27)	/* MT7622 */
 
+#define _BUS_PROT(_type, _set_ofs, _clr_ofs,			\
+		_en_ofs, _sta_ofs, _mask, _ack_mask,		\
+		_ignore_clr_ack) {				\
+		.type = _type,					\
+		.set_ofs = _set_ofs,				\
+		.clr_ofs = _clr_ofs,				\
+		.en_ofs = _en_ofs,				\
+		.sta_ofs = _sta_ofs,				\
+		.mask = _mask,					\
+		.ack_mask = _ack_mask,				\
+		.ignore_clr_ack = _ignore_clr_ack,		\
+	}
+
+#define BUS_PROT_IGN(_type, _set_ofs, _clr_ofs,	\
+		_en_ofs, _sta_ofs, _mask)		\
+		_BUS_PROT(_type, _set_ofs, _clr_ofs,	\
+		_en_ofs, _sta_ofs, _mask, _mask, true)
+
 enum clk_id {
 	CLK_NONE,
 	CLK_MM,
@@ -135,6 +155,18 @@ static const char * const clk_names[] = {
 };
 
 #define MAX_CLKS	3
+#define MAX_STEPS	3
+
+struct bus_prot {
+	u32 type;
+	u32 set_ofs;
+	u32 clr_ofs;
+	u32 en_ofs;
+	u32 sta_ofs;
+	u32 mask;
+	u32 ack_mask;
+	bool ignore_clr_ack;
+};
 
 /**
  * struct scp_domain_data - scp domain data for power on/off flow
@@ -157,6 +189,7 @@ static const char * const clk_names[] = {
  * @sram_slp_ack_bits: The mask for sram low power control acked bits.
  * @bus_prot_mask: The mask for single step bus protection.
  * @clk_id: The basic clocks required by this power domain.
+ * @bp_table: The bus protect configs for the power domain.
  * @caps: The flag for active wake-up action.
  */
 struct scp_domain_data {
@@ -179,6 +212,7 @@ struct scp_domain_data {
 	u32 sram_slp_ack_bits;
 	u32 bus_prot_mask;
 	enum clk_id clk_id[MAX_CLKS];
+	struct bus_prot bp_table[MAX_STEPS];
 	u32 caps;
 };
 
@@ -207,6 +241,8 @@ struct scp {
 	struct regmap *infracfg;
 	struct scp_ctrl_reg ctrl_reg;
 	bool bus_prot_reg_update;
+	struct regmap **bp_regmap;
+	int num_bp;
 };
 
 struct scp_subdomain {
@@ -221,6 +257,8 @@ struct scp_soc_data {
 	int num_subdomains;
 	const struct scp_ctrl_reg regs;
 	bool bus_prot_reg_update;
+	const char **bp_list;
+	int num_bp;
 };
 
 static int scpsys_domain_is_on(struct scp_domain *scpd)
@@ -375,10 +413,121 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
 			MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
 }
 
+static int set_bus_protection(struct regmap *map, struct bus_prot *bp)
+{
+	u32 val = 0;
+	int retry = 0;
+	int ret = 0;
+
+	while (retry <= MTK_BUS_PROTECTION_RETY_TIMES) {
+		if (bp->set_ofs)
+			regmap_write(map,  bp->set_ofs, bp->mask);
+		else
+			regmap_update_bits(map, bp->en_ofs, bp->mask, bp->mask);
+
+		/* check bus protect enable setting */
+		regmap_read(map, bp->en_ofs, &val);
+		if ((val & bp->mask) == bp->mask)
+			break;
+
+		retry++;
+	}
+
+	ret = regmap_read_poll_timeout_atomic(map, bp->sta_ofs, val,
+					      (val & bp->ack_mask) == bp->ack_mask,
+					      MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	if (ret < 0) {
+		pr_err("%s val=0x%x, mask=0x%x, (val & mask)=0x%x\n",
+		       __func__, val, bp->ack_mask, (val & bp->ack_mask));
+	}
+
+	return ret;
+}
+
+static int clear_bus_protection(struct regmap *map, struct bus_prot *bp)
+{
+	u32 val = 0;
+	int ret = 0;
+
+	if (bp->clr_ofs)
+		regmap_write(map, bp->clr_ofs, bp->mask);
+	else
+		regmap_update_bits(map, bp->en_ofs, bp->mask, 0);
+
+	if (bp->ignore_clr_ack)
+		return 0;
+
+	ret = regmap_read_poll_timeout_atomic(map, bp->sta_ofs, val,
+					      !(val & bp->ack_mask),
+					      MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	if (ret < 0) {
+		pr_err("%s val=0x%x, mask=0x%x, (val & mask)=0x%x\n",
+		       __func__, val, bp->ack_mask, (val & bp->ack_mask));
+	}
+	return ret;
+}
+
+static int scpsys_bus_protect_table_disable(struct scp_domain *scpd, unsigned int index)
+{
+	struct scp *scp = scpd->scp;
+	const struct bus_prot *bp_table = scpd->data->bp_table;
+	int ret = 0;
+	int i;
+
+	for (i = index; i >= 0; i--) {
+		struct regmap *map;
+		struct bus_prot bp = bp_table[i];
+
+		if (bp.type == 0 || bp.type >= scp->num_bp)
+			continue;
+
+		map = scp->bp_regmap[bp.type];
+		if (!map)
+			continue;
+
+		ret = clear_bus_protection(map, &bp);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int scpsys_bus_protect_table_enable(struct scp_domain *scpd)
+{
+	struct scp *scp = scpd->scp;
+	const struct bus_prot *bp_table = scpd->data->bp_table;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < MAX_STEPS; i++) {
+		struct regmap *map;
+		struct bus_prot bp = bp_table[i];
+
+		if (bp.type == 0 || bp.type >= scp->num_bp)
+			continue;
+
+		map = scp->bp_regmap[bp.type];
+		if (!map)
+			continue;
+
+		ret = set_bus_protection(map, &bp);
+		if (ret) {
+			scpsys_bus_protect_table_disable(scpd, i);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
 static int scpsys_bus_protect_enable(struct scp_domain *scpd)
 {
 	struct scp *scp = scpd->scp;
 
+	if (scp->bp_regmap && scp->num_bp > 0)
+		return scpsys_bus_protect_table_enable(scpd);
+
 	if (!scpd->data->bus_prot_mask)
 		return 0;
 
@@ -391,6 +540,9 @@ static int scpsys_bus_protect_disable(struct scp_domain *scpd)
 {
 	struct scp *scp = scpd->scp;
 
+	if (scp->bp_regmap && scp->num_bp > 0)
+		return scpsys_bus_protect_table_disable(scpd, MAX_STEPS - 1);
+
 	if (!scpd->data->bus_prot_mask)
 		return 0;
 
@@ -833,12 +985,27 @@ static struct scp *init_scp(struct platform_device *pdev, const struct scp_soc_d
 	if (!pd_data->domains)
 		return ERR_PTR(-ENOMEM);
 
-	scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-			"infracfg");
-	if (IS_ERR(scp->infracfg)) {
-		dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
-				PTR_ERR(scp->infracfg));
-		return ERR_CAST(scp->infracfg);
+	if (soc->bp_list && soc->num_bp > 0) {
+		scp->num_bp = soc->num_bp;
+		scp->bp_regmap = devm_kcalloc(&pdev->dev, scp->num_bp,
+					      sizeof(*scp->bp_regmap), GFP_KERNEL);
+		if (!scp->bp_regmap)
+			return ERR_PTR(-ENOMEM);
+
+		/* get bus prot regmap from dts node, 0 means invalid bus type */
+		for (i = 1; i < scp->num_bp; i++) {
+			ret = mtk_pd_get_regmap(pdev, &scp->bp_regmap[i], soc->bp_list[i]);
+			if (ret)
+				return ERR_PTR(ret);
+		}
+	} else {
+		scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+				"infracfg");
+		if (IS_ERR(scp->infracfg)) {
+			dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
+					PTR_ERR(scp->infracfg));
+			return ERR_CAST(scp->infracfg);
+		}
 	}
 
 	for (i = 0; i < soc->num_domains; i++) {
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:35 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:35 +0800
Subject: [PATCH 11/13] pmdomain: mediatek: Add post init callback
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-12-guangjie.song@mediatek.com>

Add post init callback.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mtk-scpsys.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index c10756fa1685..7bfe36c1a1ae 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -250,6 +250,9 @@ struct scp_subdomain {
 	int subdomain;
 };
 
+typedef int (*scp_soc_post_probe_fn)(struct platform_device *pdev,
+		struct scp *scp);
+
 struct scp_soc_data {
 	const struct scp_domain_data *domains;
 	int num_domains;
@@ -259,6 +262,7 @@ struct scp_soc_data {
 	bool bus_prot_reg_update;
 	const char **bp_list;
 	int num_bp;
+	scp_soc_post_probe_fn post_probe;
 };
 
 static int scpsys_domain_is_on(struct scp_domain *scpd)
@@ -1691,6 +1695,12 @@ static int scpsys_probe(struct platform_device *pdev)
 				ret);
 	}
 
+	if (soc->post_probe) {
+		ret = soc->post_probe(pdev, scp);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:36 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:36 +0800
Subject: [PATCH 12/13] dt-bindings: power: mediatek: Add new MT8196 power domain
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-13-guangjie.song@mediatek.com>

Add the binding documentation for power domain on MediaTek MT8196.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 .../mediatek,mt8196-power-controller.yaml     | 74 +++++++++++++++++++
 include/dt-bindings/power/mt8196-power.h      | 57 ++++++++++++++
 2 files changed, 131 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
 create mode 100644 include/dt-bindings/power/mt8196-power.h

diff --git a/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
new file mode 100644
index 000000000000..6c2867b25967
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/mediatek,mt8196-power-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8196 Power Domains Controller
+
+maintainers:
+  - Guangjie Song <guangjie.song at mediatek.com>
+
+description: |
+  Mediatek processors include support for multiple power domains which can be
+  powered up/down by software based on different application scenes to save power.
+
+properties:
+  $nodename:
+    pattern: '^power-controller(@[0-9a-f]+)?$'
+
+  compatible:
+    enum:
+      - mediatek,mt8196-scpsys
+      - mediatek,mt8196-hfrpsys
+
+  '#power-domain-cells':
+    const: 1
+
+  reg:
+    description: Address range of the power controller.
+
+  clocks:
+    description: |
+      A number of phandles to clocks that need to be enabled during domain
+      power-up sequencing.
+
+  clock-names:
+    description: |
+      List of names of clock.
+
+  domain-supply:
+    description: domain regulator supply.
+
+  spm:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the device containing the spm register range.
+
+  mmpc:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the device containing the mmpc register range.
+
+  vote-regmap:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the device containing the vote register range.
+
+  mm-vote-regmap:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the device containing the mm-vote register range.
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/power/mt8196-power.h>
+
+    scpsys: power-controller at 1c004000 {
+      compatible = "mediatek,mt8196-scpsys", "syscon";
+      reg = <0 0x1c004000 0 0x1000>;
+      #power-domain-cells = <1>;
+      spm = <&scpsys_bus>;
+      vote-regmap = <&vote>;
+    };
diff --git a/include/dt-bindings/power/mt8196-power.h b/include/dt-bindings/power/mt8196-power.h
new file mode 100644
index 000000000000..b0db89cc435d
--- /dev/null
+++ b/include/dt-bindings/power/mt8196-power.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Chong-ming Wei <chong-ming.wei at mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT8196_POWER_H
+#define _DT_BINDINGS_POWER_MT8196_POWER_H
+
+/* SPM */
+#define MT8196_POWER_DOMAIN_CONN			0
+#define MT8196_POWER_DOMAIN_SSUSB_P0			1
+#define MT8196_POWER_DOMAIN_SSUSB_DP_PHY_P0		2
+#define MT8196_POWER_DOMAIN_SSUSB_P1			3
+#define MT8196_POWER_DOMAIN_SSUSB_P23			4
+#define MT8196_POWER_DOMAIN_SSUSB_PHY_P2		5
+#define MT8196_POWER_DOMAIN_PEXTP_MAC0			6
+#define MT8196_POWER_DOMAIN_PEXTP_MAC1			7
+#define MT8196_POWER_DOMAIN_PEXTP_MAC2			8
+#define MT8196_POWER_DOMAIN_PEXTP_PHY0			9
+#define MT8196_POWER_DOMAIN_PEXTP_PHY1			10
+#define MT8196_POWER_DOMAIN_PEXTP_PHY2			11
+#define MT8196_POWER_DOMAIN_ADSP_AO			12
+#define MT8196_POWER_DOMAIN_ADSP_INFRA			13
+#define MT8196_POWER_DOMAIN_AUDIO			14
+#define MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT		15
+#define MT8196_POWER_DOMAIN_MM_PROC_DORMANT		16
+#define MT8196_POWER_DOMAIN_SSR				17
+#define MT8196_SPM_POWER_DOMAIN_NR			18
+
+/* MMPC */
+#define MT8196_POWER_DOMAIN_MM_INFRA_AO			0
+#define MT8196_POWER_DOMAIN_MM_INFRA0			1
+#define MT8196_POWER_DOMAIN_MM_INFRA1			2
+#define MT8196_POWER_DOMAIN_VDE_VCORE0			3
+#define MT8196_POWER_DOMAIN_VDE0			4
+#define MT8196_POWER_DOMAIN_VDE1			5
+#define MT8196_POWER_DOMAIN_VEN0			6
+#define MT8196_POWER_DOMAIN_VEN1			7
+#define MT8196_POWER_DOMAIN_VEN2			8
+#define MT8196_POWER_DOMAIN_DISP_VCORE			9
+#define MT8196_POWER_DOMAIN_DIS0_DORMANT		10
+#define MT8196_POWER_DOMAIN_DIS1_DORMANT		11
+#define MT8196_POWER_DOMAIN_OVL0_DORMANT		12
+#define MT8196_POWER_DOMAIN_OVL1_DORMANT		13
+#define MT8196_POWER_DOMAIN_DISP_EDPTX_DORMANT		14
+#define MT8196_POWER_DOMAIN_DISP_DPTX_DORMANT		15
+#define MT8196_POWER_DOMAIN_MML0_SHUTDOWN		16
+#define MT8196_POWER_DOMAIN_MML1_SHUTDOWN		17
+#define MT8196_POWER_DOMAIN_CSI_BS_RX			18
+#define MT8196_POWER_DOMAIN_CSI_LS_RX			19
+#define MT8196_POWER_DOMAIN_DSI_PHY0			20
+#define MT8196_POWER_DOMAIN_DSI_PHY1			21
+#define MT8196_POWER_DOMAIN_DSI_PHY2			22
+#define MT8196_MMPC_POWER_DOMAIN_NR			23
+
+#endif /* _DT_BINDINGS_POWER_MT8196_POWER_H */
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:44:37 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:44:37 +0800
Subject: [PATCH 13/13] pmdomain: mediatek: Add MT8196 power domain support
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <20250307034454.12243-14-guangjie.song@mediatek.com>

Add power domain support for MT8196.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/pmdomain/mediatek/mt8196-scpsys.h | 114 ++++
 drivers/pmdomain/mediatek/mtk-scpsys.c    | 629 ++++++++++++++++++++++
 2 files changed, 743 insertions(+)
 create mode 100644 drivers/pmdomain/mediatek/mt8196-scpsys.h

diff --git a/drivers/pmdomain/mediatek/mt8196-scpsys.h b/drivers/pmdomain/mediatek/mt8196-scpsys.h
new file mode 100644
index 000000000000..07cb08eaa920
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8196-scpsys.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#ifndef __PMDOMAIN_MEDIATEK_MT8196_SCPSYS_H
+#define __PMDOMAIN_MEDIATEK_MT8196_SCPSYS_H
+
+#define MT8196_SPM_CONN_PWR_CON			0xe04
+#define MT8196_SPM_SSUSB_DP_PHY_P0_PWR_CON	0xe18
+#define MT8196_SPM_SSUSB_P0_PWR_CON		0xe1c
+#define MT8196_SPM_SSUSB_P1_PWR_CON		0xe20
+#define MT8196_SPM_SSUSB_P23_PWR_CON		0xe24
+#define MT8196_SPM_SSUSB_PHY_P2_PWR_CON		0xe28
+#define MT8196_SPM_PEXTP_MAC0_PWR_CON		0xe34
+#define MT8196_SPM_PEXTP_MAC1_PWR_CON		0xe38
+#define MT8196_SPM_PEXTP_MAC2_PWR_CON		0xe3c
+#define MT8196_SPM_PEXTP_PHY0_PWR_CON		0xe40
+#define MT8196_SPM_PEXTP_PHY1_PWR_CON		0xe44
+#define MT8196_SPM_PEXTP_PHY2_PWR_CON		0xe48
+#define MT8196_SPM_AUDIO_PWR_CON		0xe4c
+#define MT8196_SPM_ADSP_TOP_PWR_CON		0xe54
+#define MT8196_SPM_ADSP_INFRA_PWR_CON		0xe58
+#define MT8196_SPM_ADSP_AO_PWR_CON		0xe5c
+#define MT8196_SPM_PWR_STATUS			0xf14
+#define MT8196_SPM_PWR_STATUS_2ND		0xf18
+
+#define MT8196_SPM_BUS_PROTECT_EN		0xd8
+#define MT8196_SPM_BUS_PROTECT_EN_SET		0xdc
+#define MT8196_SPM_BUS_PROTECT_EN_CLR		0xe0
+#define MT8196_SPM_BUS_PROTECT_RDY		0x208
+
+#define MT8196_MM_PWR_STATUS			0x100
+#define MT8196_MM_PWR_STATUS_2ND		0x104
+
+#define MT8196_VOTE_MTCMOS_SET0			0x218
+#define MT8196_VOTE_MTCMOS_CLR0			0x21c
+#define MT8196_VOTE_MTCMOS_ENABLE0		0x1410
+#define MT8196_VOTE_MTCMOS_DONE0		0x141c
+#define MT8196_VOTE_MTCMOS_SET_STATUS0		0x146c
+#define MT8196_VOTE_MTCMOS_CLR_STATUS0		0x1470
+
+#define MT8196_MM_VOTE_MTCMOS_SET0		0x218
+#define MT8196_MM_VOTE_MTCMOS_CLR0		0x21c
+#define MT8196_MM_VOTE_MTCMOS_SET1		0x220
+#define MT8196_MM_VOTE_MTCMOS_CLR1		0x224
+#define MT8196_MM_VOTE_MTCMOS_ENABLE0		0x1410
+#define MT8196_MM_VOTE_MTCMOS_DONE0		0x141c
+#define MT8196_MM_VOTE_MTCMOS_ENABLE1		0x1420
+#define MT8196_MM_VOTE_MTCMOS_DONE1		0x142c
+#define MT8196_MM_VOTE_MTCMOS_SET_STATUS0	0x146c
+#define MT8196_MM_VOTE_MTCMOS_CLR_STATUS0	0x1470
+#define MT8196_MM_VOTE_MTCMOS_SET_STATUS1	0x1474
+#define MT8196_MM_VOTE_MTCMOS_CLR_STATUS1	0x1478
+#define MT8196_MM_VOTE_MTCMOS_PM_ACK0		0x5514
+#define MT8196_MM_VOTE_MTCMOS_PM_ACK1		0x5518
+
+#define MT8196_SPM_PROT_EN_BUS_CONN		BIT(1)
+#define MT8196_SPM_PROT_EN_BUS_SSUSB_DP_PHY_P0	BIT(6)
+#define MT8196_SPM_PROT_EN_BUS_SSUSB_P0		BIT(7)
+#define MT8196_SPM_PROT_EN_BUS_SSUSB_P1		BIT(8)
+#define MT8196_SPM_PROT_EN_BUS_SSUSB_P23	BIT(9)
+#define MT8196_SPM_PROT_EN_BUS_SSUSB_PHY_P2	BIT(10)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC0	BIT(13)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC1	BIT(14)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC2	BIT(15)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY0	BIT(16)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY1	BIT(17)
+#define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY2	BIT(18)
+#define MT8196_SPM_PROT_EN_BUS_AUDIO		BIT(19)
+#define MT8196_SPM_PROT_EN_BUS_ADSP_TOP		BIT(21)
+#define MT8196_SPM_PROT_EN_BUS_ADSP_INFRA	BIT(22)
+#define MT8196_SPM_PROT_EN_BUS_ADSP_AO		BIT(23)
+
+#define MT8196_VOTE_MM_PROC_SHIFT		0
+#define MT8196_VOTE_SSR_SHIFT			1
+
+#define MT8196_MM_VOTE_VDE0_SHIFT		7
+#define MT8196_MM_VOTE_VDE1_SHIFT		8
+#define MT8196_MM_VOTE_VDE_VCORE0_SHIFT		9
+#define MT8196_MM_VOTE_VEN0_SHIFT		10
+#define MT8196_MM_VOTE_VEN1_SHIFT		11
+#define MT8196_MM_VOTE_VEN2_SHIFT		12
+#define MT8196_MM_VOTE_DISP_VCORE_SHIFT		24
+#define MT8196_MM_VOTE_DIS0_SHIFT		25
+#define MT8196_MM_VOTE_DIS1_SHIFT		26
+#define MT8196_MM_VOTE_OVL0_SHIFT		27
+#define MT8196_MM_VOTE_OVL1_SHIFT		28
+#define MT8196_MM_VOTE_DISP_EDPTX_SHIFT		29
+#define MT8196_MM_VOTE_DISP_DPTX_SHIFT		30
+#define MT8196_MM_VOTE_MML0_SHIFT		31
+#define MT8196_MM_VOTE_MML1_SHIFT		0
+#define MT8196_MM_VOTE_MM_INFRA0_SHIFT		1
+#define MT8196_MM_VOTE_MM_INFRA1_SHIFT		2
+#define MT8196_MM_VOTE_MM_INFRA_AO_SHIFT	3
+#define MT8196_MM_VOTE_CSI_BS_RX_SHIFT		5
+#define MT8196_MM_VOTE_CSI_LS_RX_SHIFT		6
+#define MT8196_MM_VOTE_DSI_PHY0_SHIFT		7
+#define MT8196_MM_VOTE_DSI_PHY1_SHIFT		8
+#define MT8196_MM_VOTE_DSI_PHY2_SHIFT		9
+
+enum {
+	MT8196_SPM_BP_INVALID = 0,
+	MT8196_SPM_BP_SPM,
+	MT8196_SPM_BP_NR
+};
+
+enum {
+	MT8196_MMPC_BP_INVALID = 0,
+	MT8196_MMPC_BP_MMPC,
+	MT8196_MMPC_BP_NR,
+};
+
+#endif /* __PMDOMAIN_MEDIATEK_MT8196_SCPSYS_H */
diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
index 7bfe36c1a1ae..667e69ada125 100644
--- a/drivers/pmdomain/mediatek/mtk-scpsys.c
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -20,6 +20,9 @@
 #include <dt-bindings/power/mt7622-power.h>
 #include <dt-bindings/power/mt7623a-power.h>
 #include <dt-bindings/power/mt8173-power.h>
+#include <dt-bindings/power/mt8196-power.h>
+
+#include "mt8196-scpsys.h"
 
 #define MTK_POLL_DELAY_US   10
 #define MTK_POLL_TIMEOUT    USEC_PER_SEC
@@ -137,6 +140,8 @@ enum clk_id {
 	CLK_HIFSEL,
 	CLK_JPGDEC,
 	CLK_AUDIO,
+	CLK_DISP_AO_CONFIG,
+	CLK_DISP_DPC,
 	CLK_MAX,
 };
 
@@ -151,6 +156,8 @@ static const char * const clk_names[] = {
 	"hif_sel",
 	"jpgdec",
 	"audio",
+	"disp_ao_config",
+	"disp_dpc",
 	NULL,
 };
 
@@ -1575,6 +1582,594 @@ static const struct scp_subdomain scp_subdomain_mt8173[] = {
 	{MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
 };
 
+/*
+ * MT8196 power domain support
+ */
+static const char *mt8196_spm_bp_list[MT8196_SPM_BP_NR] = {
+	[MT8196_SPM_BP_SPM] = "spm",
+};
+
+static const struct scp_domain_data scp_domain_mt8196_spm_vote_data[] = {
+	[MT8196_POWER_DOMAIN_CONN] = {
+		.name = "conn",
+		.ctl_offs = MT8196_SPM_CONN_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_CONN),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_BYPASS_INIT_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSUSB_DP_PHY_P0] = {
+		.name = "ssusb-dp-phy-p0",
+		.ctl_offs = MT8196_SPM_SSUSB_DP_PHY_P0_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY,
+				     MT8196_SPM_PROT_EN_BUS_SSUSB_DP_PHY_P0),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSUSB_P0] = {
+		.name = "ssusb-p0",
+		.ctl_offs = MT8196_SPM_SSUSB_P0_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_SSUSB_P0),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSUSB_P1] = {
+		.name = "ssusb-p1",
+		.ctl_offs = MT8196_SPM_SSUSB_P1_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_SSUSB_P1),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSUSB_P23] = {
+		.name = "ssusb-p23",
+		.ctl_offs = MT8196_SPM_SSUSB_P23_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_SSUSB_P23),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_BYPASS_INIT_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSUSB_PHY_P2] = {
+		.name = "ssusb-phy-p2",
+		.ctl_offs = MT8196_SPM_SSUSB_PHY_P2_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY,
+				     MT8196_SPM_PROT_EN_BUS_SSUSB_PHY_P2),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_BYPASS_INIT_ON,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_MAC0] = {
+		.name = "pextp-mac0",
+		.ctl_offs = MT8196_SPM_PEXTP_MAC0_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC0),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_MAC1] = {
+		.name = "pextp-mac1",
+		.ctl_offs = MT8196_SPM_PEXTP_MAC1_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC1),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_MAC2] = {
+		.name = "pextp-mac2",
+		.ctl_offs = MT8196_SPM_PEXTP_MAC2_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC2),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_PHY0] = {
+		.name = "pextp-phy0",
+		.ctl_offs = MT8196_SPM_PEXTP_PHY0_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY0),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_PHY1] = {
+		.name = "pextp-phy1",
+		.ctl_offs = MT8196_SPM_PEXTP_PHY1_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY1),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_PEXTP_PHY2] = {
+		.name = "pextp-phy2",
+		.ctl_offs = MT8196_SPM_PEXTP_PHY2_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY2),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_PEXTP_PHY_RTFF | MTK_SCPD_RTFF_DELAY,
+	},
+	[MT8196_POWER_DOMAIN_AUDIO] = {
+		.name = "audio",
+		.ctl_offs = MT8196_SPM_AUDIO_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_AUDIO),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF,
+	},
+	[MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT] = {
+		.name = "adsp-top-dormant",
+		.ctl_offs = MT8196_SPM_ADSP_TOP_PWR_CON,
+		.sram_slp_bits = GENMASK(9, 9),
+		.sram_slp_ack_bits = GENMASK(13, 13),
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_ADSP_TOP),
+		},
+		.caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_SRAM_SLP | MTK_SCPD_IS_PWR_CON_ON,
+	},
+	[MT8196_POWER_DOMAIN_ADSP_INFRA] = {
+		.name = "adsp-infra",
+		.ctl_offs = MT8196_SPM_ADSP_INFRA_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_ADSP_INFRA),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_ADSP_AO] = {
+		.name = "adsp-ao",
+		.ctl_offs = MT8196_SPM_ADSP_AO_PWR_CON,
+		.bp_table = {
+			BUS_PROT_IGN(MT8196_SPM_BP_SPM, MT8196_SPM_BUS_PROTECT_EN_SET,
+				     MT8196_SPM_BUS_PROTECT_EN_CLR, MT8196_SPM_BUS_PROTECT_EN,
+				     MT8196_SPM_BUS_PROTECT_RDY, MT8196_SPM_PROT_EN_BUS_ADSP_AO),
+		},
+		.caps = MTK_SCPD_IS_PWR_CON_ON | MTK_SCPD_NON_CPU_RTFF | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_MM_PROC_DORMANT] = {
+		.name = "mm-proc-dormant",
+		.vote_comp = "vote-regmap",
+		.vote_set_ofs = MT8196_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_VOTE_MTCMOS_ENABLE0,
+		.vote_set_sta_ofs = MT8196_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_shift = MT8196_VOTE_MM_PROC_SHIFT,
+		/* TODO: drop MTK_SCPD_ALWAYS_ON after fixing suspend issue. */
+		.caps = MTK_SCPD_VOTE_OPS |  MTK_SCPD_IRQ_SAFE | MTK_SCPD_ALWAYS_ON,
+	},
+	[MT8196_POWER_DOMAIN_SSR] = {
+		.name = "ssrsys",
+		.vote_comp = "vote-regmap",
+		.vote_set_ofs = MT8196_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_VOTE_MTCMOS_ENABLE0,
+		.vote_set_sta_ofs = MT8196_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_shift = MT8196_VOTE_SSR_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+};
+
+static const struct scp_subdomain scp_subdomain_mt8196_spm[] = {
+	{MT8196_POWER_DOMAIN_SSUSB_P0, MT8196_POWER_DOMAIN_SSUSB_DP_PHY_P0},
+	{MT8196_POWER_DOMAIN_SSUSB_P23, MT8196_POWER_DOMAIN_SSUSB_PHY_P2},
+	{MT8196_POWER_DOMAIN_PEXTP_MAC0, MT8196_POWER_DOMAIN_PEXTP_PHY0},
+	{MT8196_POWER_DOMAIN_PEXTP_MAC1, MT8196_POWER_DOMAIN_PEXTP_PHY1},
+	{MT8196_POWER_DOMAIN_PEXTP_MAC2, MT8196_POWER_DOMAIN_PEXTP_PHY2},
+	{MT8196_POWER_DOMAIN_ADSP_INFRA, MT8196_POWER_DOMAIN_AUDIO},
+	{MT8196_POWER_DOMAIN_ADSP_INFRA, MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT},
+	{MT8196_POWER_DOMAIN_ADSP_AO, MT8196_POWER_DOMAIN_ADSP_INFRA},
+};
+
+static struct generic_pm_domain *mt8196_mm_proc_domain;
+
+static int mt8196_spm_post_probe(struct platform_device *pdev, struct scp *scp)
+{
+	mt8196_mm_proc_domain = scp->pd_data.domains[MT8196_POWER_DOMAIN_MM_PROC_DORMANT];
+
+	return 0;
+}
+
+static const char *mt8196_mmpc_bp_list[MT8196_MMPC_BP_NR] = {
+	[MT8196_MMPC_BP_MMPC] = "mmpc",
+};
+
+static const struct scp_domain_data scp_domain_mt8196_mmpc_vote_data[] = {
+	[MT8196_POWER_DOMAIN_VDE0] = {
+		.name = "vde0",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VDE0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_VDE1] = {
+		.name = "vde1",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VDE1_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_VDE_VCORE0] = {
+		.name = "vde-vcore0",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VDE_VCORE0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_VEN0] = {
+		.name = "ven0",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VEN0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_VEN1] = {
+		.name = "ven1",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VEN1_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_VEN2] = {
+		.name = "ven2",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_VEN2_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DISP_VCORE] = {
+		.name = "disp-vcore",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_DISP_VCORE_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DIS0_DORMANT] = {
+		.name = "dis0-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_DIS0_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DIS1_DORMANT] = {
+		.name = "dis1-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_DIS1_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_OVL0_DORMANT] = {
+		.name = "ovl0-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_OVL0_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_OVL1_DORMANT] = {
+		.name = "ovl1-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_OVL1_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DISP_EDPTX_DORMANT] = {
+		.name = "disp-edptx-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_DISP_EDPTX_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DISP_DPTX_DORMANT] = {
+		.name = "disp-dptx-dormant",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_DISP_DPTX_SHIFT,
+		.clk_id = {CLK_DISP_AO_CONFIG, CLK_DISP_DPC},
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_MML0_SHUTDOWN] = {
+		.name = "mml0-shutdown",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET0,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE0,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_CLR0,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS0,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS0,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK0,
+		.vote_shift = MT8196_MM_VOTE_MML0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_MML1_SHUTDOWN] = {
+		.name = "mml1-shutdown",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_MML0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_MM_INFRA0] = {
+		.name = "mm-infra0",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_MM_INFRA0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS |  MTK_SCPD_IRQ_SAFE,
+	},
+	[MT8196_POWER_DOMAIN_MM_INFRA1] = {
+		.name = "mm-infra1",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_MM_INFRA1_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS |  MTK_SCPD_IRQ_SAFE,
+	},
+	[MT8196_POWER_DOMAIN_MM_INFRA_AO] = {
+		.name = "mm-infra-ao",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_MM_INFRA_AO_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS |  MTK_SCPD_IRQ_SAFE,
+	},
+	[MT8196_POWER_DOMAIN_CSI_BS_RX] = {
+		.name = "csi-bs-rx",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_CSI_BS_RX_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_CSI_LS_RX] = {
+		.name = "csi-ls-rx",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_CSI_LS_RX_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DSI_PHY0] = {
+		.name = "dsi-phy0",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_DSI_PHY0_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DSI_PHY1] = {
+		.name = "dsi-phy1",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_DSI_PHY1_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+	[MT8196_POWER_DOMAIN_DSI_PHY2] = {
+		.name = "dsi-phy2",
+		.vote_comp = "mm-vote-regmap",
+		.vote_set_ofs = MT8196_MM_VOTE_MTCMOS_SET1,
+		.vote_clr_ofs = MT8196_MM_VOTE_MTCMOS_CLR1,
+		.vote_done_ofs = MT8196_MM_VOTE_MTCMOS_DONE1,
+		.vote_en_ofs = MT8196_MM_VOTE_MTCMOS_ENABLE1,
+		.vote_set_sta_ofs = MT8196_MM_VOTE_MTCMOS_SET_STATUS1,
+		.vote_clr_sta_ofs = MT8196_MM_VOTE_MTCMOS_CLR_STATUS1,
+		.vote_ack_ofs = MT8196_MM_VOTE_MTCMOS_PM_ACK1,
+		.vote_shift = MT8196_MM_VOTE_DSI_PHY2_SHIFT,
+		.caps = MTK_SCPD_VOTE_OPS,
+	},
+};
+
+static const struct scp_subdomain scp_subdomain_mt8196_mmpc[] = {
+	{MT8196_POWER_DOMAIN_VDE_VCORE0, MT8196_POWER_DOMAIN_VDE0},
+	{MT8196_POWER_DOMAIN_VDE_VCORE0, MT8196_POWER_DOMAIN_VDE1},
+	{MT8196_POWER_DOMAIN_VEN0, MT8196_POWER_DOMAIN_VEN1},
+	{MT8196_POWER_DOMAIN_VEN1, MT8196_POWER_DOMAIN_VEN2},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_DIS0_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_DIS1_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_OVL0_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_OVL1_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_DISP_EDPTX_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_DISP_DPTX_DORMANT},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_MML0_SHUTDOWN},
+	{MT8196_POWER_DOMAIN_DISP_VCORE, MT8196_POWER_DOMAIN_MML1_SHUTDOWN},
+	{MT8196_POWER_DOMAIN_MM_INFRA1, MT8196_POWER_DOMAIN_DISP_VCORE},
+	{MT8196_POWER_DOMAIN_MM_INFRA1, MT8196_POWER_DOMAIN_VDE_VCORE0},
+	{MT8196_POWER_DOMAIN_MM_INFRA1, MT8196_POWER_DOMAIN_VEN0},
+	{MT8196_POWER_DOMAIN_MM_INFRA0, MT8196_POWER_DOMAIN_MM_INFRA1},
+	{MT8196_POWER_DOMAIN_MM_INFRA_AO, MT8196_POWER_DOMAIN_MM_INFRA0},
+};
+
+static int mt8196_mmpc_post_probe(struct platform_device *pdev, struct scp *scp)
+{
+	int ret, i;
+	int subdomain[] = {
+		MT8196_POWER_DOMAIN_MM_INFRA_AO,
+		MT8196_POWER_DOMAIN_CSI_BS_RX,
+		MT8196_POWER_DOMAIN_CSI_LS_RX,
+		MT8196_POWER_DOMAIN_DSI_PHY0,
+		MT8196_POWER_DOMAIN_DSI_PHY1,
+		MT8196_POWER_DOMAIN_DSI_PHY2
+	};
+
+	for (i = 0; i < ARRAY_SIZE(subdomain); i++) {
+		ret = pm_genpd_add_subdomain(mt8196_mm_proc_domain, scp->pd_data.domains[subdomain[i]]);
+		if (ret && IS_ENABLED(CONFIG_PM)) {
+			dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static const struct scp_soc_data mt2701_data = {
 	.domains = scp_domain_data_mt2701,
 	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
@@ -1641,6 +2236,34 @@ static const struct scp_soc_data mt8173_data = {
 	.bus_prot_reg_update = true,
 };
 
+static const struct scp_soc_data mt8196_spm_vote_data = {
+	.domains = scp_domain_mt8196_spm_vote_data,
+	.num_domains = MT8196_SPM_POWER_DOMAIN_NR,
+	.subdomains = scp_subdomain_mt8196_spm,
+	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8196_spm),
+	.regs = {
+		.pwr_sta_offs = MT8196_SPM_PWR_STATUS,
+		.pwr_sta2nd_offs = MT8196_SPM_PWR_STATUS_2ND,
+	},
+	.bp_list = mt8196_spm_bp_list,
+	.num_bp = MT8196_SPM_BP_NR,
+	.post_probe = mt8196_spm_post_probe,
+};
+
+static const struct scp_soc_data mt8196_mmpc_vote_data = {
+	.domains = scp_domain_mt8196_mmpc_vote_data,
+	.num_domains = MT8196_MMPC_POWER_DOMAIN_NR,
+	.subdomains = scp_subdomain_mt8196_mmpc,
+	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8196_mmpc),
+	.regs = {
+		.pwr_sta_offs = MT8196_MM_PWR_STATUS,
+		.pwr_sta2nd_offs = MT8196_MM_PWR_STATUS_2ND,
+	},
+	.bp_list = mt8196_mmpc_bp_list,
+	.num_bp = MT8196_MMPC_BP_NR,
+	.post_probe = mt8196_mmpc_post_probe,
+};
+
 /*
  * scpsys driver init
  */
@@ -1664,6 +2287,12 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
 	}, {
 		.compatible = "mediatek,mt8173-scpsys",
 		.data = &mt8173_data,
+	}, {
+		.compatible = "mediatek,mt8196-scpsys",
+		.data = &mt8196_spm_vote_data,
+	}, {
+		.compatible = "mediatek,mt8196-hfrpsys",
+		.data = &mt8196_mmpc_vote_data,
 	}, {
 		/* sentinel */
 	}
-- 
2.45.2



From cki-project at redhat.com  Thu Mar  6 20:13:07 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 04:13:07 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <04467.125030623130900365@us-mta-590.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704151736

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704151736-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From robh at kernel.org  Thu Mar  6 20:16:26 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 06 Mar 2025 22:16:26 -0600
Subject: [PATCH 06/26] dt-bindings: clock: mediatek: Add new MT8196
 clock
In-Reply-To: <20250307032942.10447-7-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
 <20250307032942.10447-7-guangjie.song@mediatek.com>
Message-ID: <174132098632.2770289.10803747794522136743.robh@kernel.org>


On Fri, 07 Mar 2025 11:27:02 +0800, Guangjie Song wrote:
> Add the new binding documentation for system clock and functional clock
> on Mediatek MT8196.
> 
> Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
> ---
>  .../bindings/clock/mediatek,mt8196-clock.yaml |   66 +
>  .../clock/mediatek,mt8196-sys-clock.yaml      |   63 +
>  include/dt-bindings/clock/mt8196-clk.h        | 1503 +++++++++++++++++
>  3 files changed, 1632 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-clock.yaml
>  create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.yaml
>  create mode 100644 include/dt-bindings/clock/mt8196-clk.h
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/mediatek,mt8196-sys-clock.example.dtb: clock-controller at 10000800: reg: [[0, 268437504], [0, 4096]] is too long
	from schema $id: http://devicetree.org/schemas/mfd/syscon-common.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250307032942.10447-7-guangjie.song at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From guangjie.song at mediatek.com  Thu Mar  6 19:27:09 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:09 +0800
Subject: [PATCH 13/26] clk: mediatek: Add MT8196 adsp clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-14-guangjie.song@mediatek.com>

Add MT8196 adsp clock controller which provides clock gate control for
Audio DSP.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig           |   7 +
 drivers/clk/mediatek/Makefile          |   1 +
 drivers/clk/mediatek/clk-mt8196-adsp.c | 291 +++++++++++++++++++++++++
 3 files changed, 299 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-adsp.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 1e0c6f177ecd..fe54dca0062e 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1010,6 +1010,13 @@ config COMMON_CLK_MT8196
 	help
 	  This driver supports MediaTek MT8196 basic clocks.
 
+config COMMON_CLK_MT8196_ADSP
+	tristate "Clock driver for MediaTek MT8196 adsp"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 adsp clocks
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index c95e45356b78..c0d676930a80 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o
 obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys_gp2.o \
 				   clk-mt8196-topckgen.o clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o \
 				   clk-mt8196-peri_ao.o
+obj-$(CONFIG_COMMON_CLK_MT8196_ADSP) += clk-mt8196-adsp.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-adsp.c b/drivers/clk/mediatek/clk-mt8196-adsp.c
new file mode 100644
index 000000000000..8272fc481cb1
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-adsp.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs afe0_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x0,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs afe1_cg_regs = {
+	.set_ofs = 0x10,
+	.clr_ofs = 0x10,
+	.sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs afe2_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x4,
+};
+
+static const struct mtk_gate_regs afe3_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x8,
+};
+
+static const struct mtk_gate_regs afe4_cg_regs = {
+	.set_ofs = 0xc,
+	.clr_ofs = 0xc,
+	.sta_ofs = 0xc,
+};
+
+#define GATE_AFE0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &afe0_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+#define GATE_AFE0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_AFE1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &afe1_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+#define GATE_AFE1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_AFE2(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &afe2_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+#define GATE_AFE2_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_AFE3(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &afe3_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+#define GATE_AFE3_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_AFE4(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &afe4_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE |	\
+			 CLK_IGNORE_UNUSED,		\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+#define GATE_AFE4_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate afe_clks[] = {
+	/* AFE0 */
+	GATE_AFE0(CLK_AFE_PCM1, "afe_pcm1", "vlp_aud_clksq_ck", 13),
+	GATE_AFE0_V(CLK_AFE_PCM1_AFE, "afe_pcm1_afe", "afe_pcm1"),
+	GATE_AFE0(CLK_AFE_PCM0, "afe_pcm0", "vlp_aud_clksq_ck", 14),
+	GATE_AFE0_V(CLK_AFE_PCM0_AFE, "afe_pcm0_afe", "afe_pcm0"),
+	GATE_AFE0(CLK_AFE_CM2, "afe_cm2", "vlp_aud_clksq_ck", 16),
+	GATE_AFE0_V(CLK_AFE_CM2_AFE, "afe_cm2_afe", "afe_cm2"),
+	GATE_AFE0(CLK_AFE_CM1, "afe_cm1", "vlp_aud_clksq_ck", 17),
+	GATE_AFE0_V(CLK_AFE_CM1_AFE, "afe_cm1_afe", "afe_cm1"),
+	GATE_AFE0(CLK_AFE_CM0, "afe_cm0", "vlp_aud_clksq_ck", 18),
+	GATE_AFE0_V(CLK_AFE_CM0_AFE, "afe_cm0_afe", "afe_cm0"),
+	GATE_AFE0(CLK_AFE_STF, "afe_stf", "vlp_aud_clksq_ck", 19),
+	GATE_AFE0_V(CLK_AFE_STF_AFE, "afe_stf_afe", "afe_stf"),
+	GATE_AFE0(CLK_AFE_HW_GAIN23, "afe_hw_gain23", "vlp_aud_clksq_ck", 20),
+	GATE_AFE0_V(CLK_AFE_HW_GAIN23_AFE, "afe_hw_gain23_afe", "afe_hw_gain23"),
+	GATE_AFE0(CLK_AFE_HW_GAIN01, "afe_hw_gain01", "vlp_aud_clksq_ck", 21),
+	GATE_AFE0_V(CLK_AFE_HW_GAIN01_AFE, "afe_hw_gain01_afe", "afe_hw_gain01"),
+	GATE_AFE0(CLK_AFE_FM_I2S, "afe_fm_i2s", "vlp_aud_clksq_ck", 24),
+	GATE_AFE0_V(CLK_AFE_FM_I2S_AFE, "afe_fm_i2s_afe", "afe_fm_i2s"),
+	GATE_AFE0(CLK_AFE_MTKAIFV4, "afe_mtkaifv4", "vlp_aud_clksq_ck", 25),
+	GATE_AFE0_V(CLK_AFE_MTKAIFV4_AFE, "afe_mtkaifv4_afe", "afe_mtkaifv4"),
+	/* AFE1 */
+	GATE_AFE1(CLK_AFE_AUDIO_HOPPING, "afe_audio_hopping_ck", "vlp_aud_clksq_ck", 0),
+	GATE_AFE1_V(CLK_AFE_AUDIO_HOPPING_AFE, "afe_audio_hopping_ck_afe", "afe_audio_hopping_ck"),
+	GATE_AFE1(CLK_AFE_AUDIO_F26M, "afe_audio_f26m_ck", "vlp_aud_clksq_ck", 1),
+	GATE_AFE1_V(CLK_AFE_AUDIO_F26M_AFE, "afe_audio_f26m_ck_afe", "afe_audio_f26m_ck"),
+	GATE_AFE1(CLK_AFE_APLL1, "afe_apll1_ck", "ck_aud_1_ck", 2),
+	GATE_AFE1_V(CLK_AFE_APLL1_AFE, "afe_apll1_ck_afe", "afe_apll1_ck"),
+	GATE_AFE1(CLK_AFE_APLL2, "afe_apll2_ck", "ck_aud_2_ck", 3),
+	GATE_AFE1_V(CLK_AFE_APLL2_AFE, "afe_apll2_ck_afe", "afe_apll2_ck"),
+	GATE_AFE1(CLK_AFE_H208M, "afe_h208m_ck", "vlp_audio_h_ck", 4),
+	GATE_AFE1_V(CLK_AFE_H208M_AFE, "afe_h208m_ck_afe", "afe_h208m_ck"),
+	GATE_AFE1(CLK_AFE_APLL_TUNER2, "afe_apll_tuner2", "vlp_aud_engen2_ck", 12),
+	GATE_AFE1_V(CLK_AFE_APLL_TUNER2_AFE, "afe_apll_tuner2_afe", "afe_apll_tuner2"),
+	GATE_AFE1(CLK_AFE_APLL_TUNER1, "afe_apll_tuner1", "vlp_aud_engen1_ck", 13),
+	GATE_AFE1_V(CLK_AFE_APLL_TUNER1_AFE, "afe_apll_tuner1_afe", "afe_apll_tuner1"),
+	/* AFE2 */
+	GATE_AFE2(CLK_AFE_UL2_ADC_HIRES_TML, "afe_ul2_aht", "vlp_audio_h_ck", 12),
+	GATE_AFE2_V(CLK_AFE_UL2_ADC_HIRES_TML_AFE, "afe_ul2_aht_afe", "afe_ul2_aht"),
+	GATE_AFE2(CLK_AFE_UL2_ADC_HIRES, "afe_ul2_adc_hires", "vlp_audio_h_ck", 13),
+	GATE_AFE2_V(CLK_AFE_UL2_ADC_HIRES_AFE, "afe_ul2_adc_hires_afe", "afe_ul2_adc_hires"),
+	GATE_AFE2(CLK_AFE_UL2_TML, "afe_ul2_tml", "vlp_aud_clksq_ck", 14),
+	GATE_AFE2_V(CLK_AFE_UL2_TML_AFE, "afe_ul2_tml_afe", "afe_ul2_tml"),
+	GATE_AFE2(CLK_AFE_UL2_ADC, "afe_ul2_adc", "vlp_aud_clksq_ck", 15),
+	GATE_AFE2_V(CLK_AFE_UL2_ADC_AFE, "afe_ul2_adc_afe", "afe_ul2_adc"),
+	GATE_AFE2(CLK_AFE_UL1_ADC_HIRES_TML, "afe_ul1_aht", "vlp_audio_h_ck", 16),
+	GATE_AFE2_V(CLK_AFE_UL1_ADC_HIRES_TML_AFE, "afe_ul1_aht_afe", "afe_ul1_aht"),
+	GATE_AFE2(CLK_AFE_UL1_ADC_HIRES, "afe_ul1_adc_hires", "vlp_audio_h_ck", 17),
+	GATE_AFE2_V(CLK_AFE_UL1_ADC_HIRES_AFE, "afe_ul1_adc_hires_afe", "afe_ul1_adc_hires"),
+	GATE_AFE2(CLK_AFE_UL1_TML, "afe_ul1_tml", "vlp_aud_clksq_ck", 18),
+	GATE_AFE2_V(CLK_AFE_UL1_TML_AFE, "afe_ul1_tml_afe", "afe_ul1_tml"),
+	GATE_AFE2(CLK_AFE_UL1_ADC, "afe_ul1_adc", "vlp_aud_clksq_ck", 19),
+	GATE_AFE2_V(CLK_AFE_UL1_ADC_AFE, "afe_ul1_adc_afe", "afe_ul1_adc"),
+	GATE_AFE2(CLK_AFE_UL0_ADC_HIRES_TML, "afe_ul0_aht", "vlp_audio_h_ck", 20),
+	GATE_AFE2_V(CLK_AFE_UL0_ADC_HIRES_TML_AFE, "afe_ul0_aht_afe", "afe_ul0_aht"),
+	GATE_AFE2(CLK_AFE_UL0_ADC_HIRES, "afe_ul0_adc_hires", "vlp_audio_h_ck", 21),
+	GATE_AFE2_V(CLK_AFE_UL0_ADC_HIRES_AFE, "afe_ul0_adc_hires_afe", "afe_ul0_adc_hires"),
+	GATE_AFE2(CLK_AFE_UL0_TML, "afe_ul0_tml", "vlp_aud_clksq_ck", 22),
+	GATE_AFE2_V(CLK_AFE_UL0_TML_AFE, "afe_ul0_tml_afe", "afe_ul0_tml"),
+	GATE_AFE2(CLK_AFE_UL0_ADC, "afe_ul0_adc", "vlp_aud_clksq_ck", 23),
+	GATE_AFE2_V(CLK_AFE_UL0_ADC_AFE, "afe_ul0_adc_afe", "afe_ul0_adc"),
+	/* AFE3 */
+	GATE_AFE3(CLK_AFE_ETDM_IN6, "afe_etdm_in6", "vlp_aud_clksq_ck", 7),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN6_AFE, "afe_etdm_in6_afe", "afe_etdm_in6"),
+	GATE_AFE3(CLK_AFE_ETDM_IN5, "afe_etdm_in5", "vlp_aud_clksq_ck", 8),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN5_AFE, "afe_etdm_in5_afe", "afe_etdm_in5"),
+	GATE_AFE3(CLK_AFE_ETDM_IN4, "afe_etdm_in4", "vlp_aud_clksq_ck", 9),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN4_AFE, "afe_etdm_in4_afe", "afe_etdm_in4"),
+	GATE_AFE3(CLK_AFE_ETDM_IN3, "afe_etdm_in3", "vlp_aud_clksq_ck", 10),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN3_AFE, "afe_etdm_in3_afe", "afe_etdm_in3"),
+	GATE_AFE3(CLK_AFE_ETDM_IN2, "afe_etdm_in2", "vlp_aud_clksq_ck", 11),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN2_AFE, "afe_etdm_in2_afe", "afe_etdm_in2"),
+	GATE_AFE3(CLK_AFE_ETDM_IN1, "afe_etdm_in1", "vlp_aud_clksq_ck", 12),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN1_AFE, "afe_etdm_in1_afe", "afe_etdm_in1"),
+	GATE_AFE3(CLK_AFE_ETDM_IN0, "afe_etdm_in0", "vlp_aud_clksq_ck", 13),
+	GATE_AFE3_V(CLK_AFE_ETDM_IN0_AFE, "afe_etdm_in0_afe", "afe_etdm_in0"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT6, "afe_etdm_out6", "vlp_aud_clksq_ck", 15),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT6_AFE, "afe_etdm_out6_afe", "afe_etdm_out6"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT5, "afe_etdm_out5", "vlp_aud_clksq_ck", 16),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT5_AFE, "afe_etdm_out5_afe", "afe_etdm_out5"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT4, "afe_etdm_out4", "vlp_aud_clksq_ck", 17),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT4_AFE, "afe_etdm_out4_afe", "afe_etdm_out4"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT3, "afe_etdm_out3", "vlp_aud_clksq_ck", 18),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT3_AFE, "afe_etdm_out3_afe", "afe_etdm_out3"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT2, "afe_etdm_out2", "vlp_aud_clksq_ck", 19),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT2_AFE, "afe_etdm_out2_afe", "afe_etdm_out2"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT1, "afe_etdm_out1", "vlp_aud_clksq_ck", 20),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT1_AFE, "afe_etdm_out1_afe", "afe_etdm_out1"),
+	GATE_AFE3(CLK_AFE_ETDM_OUT0, "afe_etdm_out0", "vlp_aud_clksq_ck", 21),
+	GATE_AFE3_V(CLK_AFE_ETDM_OUT0_AFE, "afe_etdm_out0_afe", "afe_etdm_out0"),
+	GATE_AFE3(CLK_AFE_TDM_OUT, "afe_tdm_out", "ck_aud_1_ck", 24),
+	GATE_AFE3_V(CLK_AFE_TDM_OUT_AFE, "afe_tdm_out_afe", "afe_tdm_out"),
+	/* AFE4 */
+	GATE_AFE4(CLK_AFE_GENERAL15_ASRC, "afe_general15_asrc", "vlp_aud_clksq_ck", 9),
+	GATE_AFE4_V(CLK_AFE_GENERAL15_ASRC_AFE, "afe_general15_asrc_afe", "afe_general15_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL14_ASRC, "afe_general14_asrc", "vlp_aud_clksq_ck", 10),
+	GATE_AFE4_V(CLK_AFE_GENERAL14_ASRC_AFE, "afe_general14_asrc_afe", "afe_general14_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL13_ASRC, "afe_general13_asrc", "vlp_aud_clksq_ck", 11),
+	GATE_AFE4_V(CLK_AFE_GENERAL13_ASRC_AFE, "afe_general13_asrc_afe", "afe_general13_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL12_ASRC, "afe_general12_asrc", "vlp_aud_clksq_ck", 12),
+	GATE_AFE4_V(CLK_AFE_GENERAL12_ASRC_AFE, "afe_general12_asrc_afe", "afe_general12_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL11_ASRC, "afe_general11_asrc", "vlp_aud_clksq_ck", 13),
+	GATE_AFE4_V(CLK_AFE_GENERAL11_ASRC_AFE, "afe_general11_asrc_afe", "afe_general11_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL10_ASRC, "afe_general10_asrc", "vlp_aud_clksq_ck", 14),
+	GATE_AFE4_V(CLK_AFE_GENERAL10_ASRC_AFE, "afe_general10_asrc_afe", "afe_general10_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL9_ASRC, "afe_general9_asrc", "vlp_aud_clksq_ck", 15),
+	GATE_AFE4_V(CLK_AFE_GENERAL9_ASRC_AFE, "afe_general9_asrc_afe", "afe_general9_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL8_ASRC, "afe_general8_asrc", "vlp_aud_clksq_ck", 16),
+	GATE_AFE4_V(CLK_AFE_GENERAL8_ASRC_AFE, "afe_general8_asrc_afe", "afe_general8_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL7_ASRC, "afe_general7_asrc", "vlp_aud_clksq_ck", 17),
+	GATE_AFE4_V(CLK_AFE_GENERAL7_ASRC_AFE, "afe_general7_asrc_afe", "afe_general7_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL6_ASRC, "afe_general6_asrc", "vlp_aud_clksq_ck", 18),
+	GATE_AFE4_V(CLK_AFE_GENERAL6_ASRC_AFE, "afe_general6_asrc_afe", "afe_general6_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL5_ASRC, "afe_general5_asrc", "vlp_aud_clksq_ck", 19),
+	GATE_AFE4_V(CLK_AFE_GENERAL5_ASRC_AFE, "afe_general5_asrc_afe", "afe_general5_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL4_ASRC, "afe_general4_asrc", "vlp_aud_clksq_ck", 20),
+	GATE_AFE4_V(CLK_AFE_GENERAL4_ASRC_AFE, "afe_general4_asrc_afe", "afe_general4_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL3_ASRC, "afe_general3_asrc", "vlp_aud_clksq_ck", 21),
+	GATE_AFE4_V(CLK_AFE_GENERAL3_ASRC_AFE, "afe_general3_asrc_afe", "afe_general3_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL2_ASRC, "afe_general2_asrc", "vlp_aud_clksq_ck", 22),
+	GATE_AFE4_V(CLK_AFE_GENERAL2_ASRC_AFE, "afe_general2_asrc_afe", "afe_general2_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL1_ASRC, "afe_general1_asrc", "vlp_aud_clksq_ck", 23),
+	GATE_AFE4_V(CLK_AFE_GENERAL1_ASRC_AFE, "afe_general1_asrc_afe", "afe_general1_asrc"),
+	GATE_AFE4(CLK_AFE_GENERAL0_ASRC, "afe_general0_asrc", "vlp_aud_clksq_ck", 24),
+	GATE_AFE4_V(CLK_AFE_GENERAL0_ASRC_AFE, "afe_general0_asrc_afe", "afe_general0_asrc"),
+	GATE_AFE4(CLK_AFE_CONNSYS_I2S_ASRC, "afe_connsys_i2s_asrc", "vlp_aud_clksq_ck", 25),
+	GATE_AFE4_V(CLK_AFE_CONNSYS_I2S_ASRC_AFE, "afe_connsys_i2s_asrc_afe", "afe_connsys_i2s_asrc"),
+};
+
+static const struct mtk_clk_desc afe_mcd = {
+	.clks = afe_clks,
+	.num_clks = ARRAY_SIZE(afe_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct of_device_id of_match_clk_mt8196_adsp[] = {
+	{ .compatible = "mediatek,mt8196-audiosys", .data = &afe_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_adsp_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-adsp",
+		.of_match_table = of_match_clk_mt8196_adsp,
+	},
+};
+
+module_platform_driver(clk_mt8196_adsp_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:13 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:13 +0800
Subject: [PATCH 17/26] clk: mediatek: Add MT8196 mfg clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-18-guangjie.song@mediatek.com>

Add MT8196 mfg clock controller which provides pll control for GPU.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig          |   7 ++
 drivers/clk/mediatek/Makefile         |   1 +
 drivers/clk/mediatek/clk-mt8196-mfg.c | 143 ++++++++++++++++++++++++++
 3 files changed, 151 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mfg.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 8763cc1480a3..042de08e0bb1 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1038,6 +1038,13 @@ config COMMON_CLK_MT8196_MDPSYS
 	help
 	  This driver supports MediaTek MT8196 mdpsys clocks.
 
+config COMMON_CLK_MT8196_MFGCFG
+	tristate "Clock driver for MediaTek MT8196 mfgcfg"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 mfgcfg clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index dccc6d84941c..ad2de9ee6d15 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196_ADSP) += clk-mt8196-adsp.o
 obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MFGCFG) += clk-mt8196-mfg.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-mfg.c b/drivers/clk/mediatek/clk-mt8196-mfg.c
new file mode 100644
index 000000000000..7e87530ef68d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-mfg.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+#define MFGPLL_CON0	0x008
+#define MFGPLL_CON1	0x00c
+#define MFGPLL_CON2	0x010
+#define MFGPLL_CON3	0x014
+#define MFGPLL_SC0_CON0	0x008
+#define MFGPLL_SC0_CON1	0x00c
+#define MFGPLL_SC0_CON2	0x010
+#define MFGPLL_SC0_CON3	0x014
+#define MFGPLL_SC1_CON0	0x008
+#define MFGPLL_SC1_CON1	0x00c
+#define MFGPLL_SC1_CON2	0x010
+#define MFGPLL_SC1_CON3	0x014
+
+#define MT8196_PLL_FMAX		(3800UL * MHZ)
+#define MT8196_PLL_FMIN		(1500UL * MHZ)
+#define MT8196_INTEGER_BITS	8
+
+#define PLL(_id, _name, _reg, _en_reg, _en_mask, _pll_en_bit,	\
+	    _flags, _rst_bar_mask,				\
+	    _pd_reg, _pd_shift, _tuner_reg,			\
+	    _tuner_en_reg, _tuner_en_bit,			\
+	    _pcw_reg, _pcw_shift, _pcwbits) {			\
+		.id = _id,					\
+		.name = _name,					\
+		.reg = _reg,					\
+		.en_reg = _en_reg,				\
+		.en_mask = _en_mask,				\
+		.pll_en_bit = _pll_en_bit,			\
+		.flags = (_flags) | CLK_FENC_ENABLE,		\
+		.rst_bar_mask = _rst_bar_mask,			\
+		.fmax = MT8196_PLL_FMAX,			\
+		.fmin = MT8196_PLL_FMIN,			\
+		.pd_reg = _pd_reg,				\
+		.pd_shift = _pd_shift,				\
+		.tuner_reg = _tuner_reg,			\
+		.tuner_en_reg = _tuner_en_reg,			\
+		.tuner_en_bit = _tuner_en_bit,			\
+		.pcw_reg = _pcw_reg,				\
+		.pcw_shift = _pcw_shift,			\
+		.pcwbits = _pcwbits,				\
+		.pcwibits = MT8196_INTEGER_BITS,		\
+	}
+
+static const struct mtk_pll_data mfg_ao_plls[] = {
+	PLL(CLK_MFG_AO_MFGPLL, "mfgpll", MFGPLL_CON0,
+	    MFGPLL_CON0, 0, 0, 0, BIT(0),
+	    MFGPLL_CON1, 24, 0, 0, 0,
+	    MFGPLL_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data mfgsc0_ao_plls[] = {
+	PLL(CLK_MFGSC0_AO_MFGPLL_SC0, "mfgpll-sc0", MFGPLL_SC0_CON0,
+	    MFGPLL_SC0_CON0, 0, 0, 0, BIT(0),
+	    MFGPLL_SC0_CON1, 24, 0, 0, 0,
+	    MFGPLL_SC0_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data mfgsc1_ao_plls[] = {
+	PLL(CLK_MFGSC1_AO_MFGPLL_SC1, "mfgpll-sc1", MFGPLL_SC1_CON0,
+	    MFGPLL_SC1_CON0, 0, 0, 0, BIT(0),
+	    MFGPLL_SC1_CON1, 24, 0, 0, 0,
+	    MFGPLL_SC1_CON1, 0, 22),
+};
+
+static const struct of_device_id of_match_clk_mt8196_mfg[] = {
+	{ .compatible = "mediatek,mt8196-mfgpll_pll_ctrl", .data = &mfg_ao_plls, },
+	{ .compatible = "mediatek,mt8196-mfgpll_sc0_pll_ctrl", .data = &mfgsc0_ao_plls, },
+	{ .compatible = "mediatek,mt8196-mfgpll_sc1_pll_ctrl", .data = &mfgsc1_ao_plls, },
+	{ /* sentinel */ }
+};
+
+static int clk_mt8196_mfg_probe(struct platform_device *pdev)
+{
+	const struct mtk_pll_data *plls;
+	struct clk_hw_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = 1;
+	int r;
+
+	plls = of_device_get_match_data(&pdev->dev);
+	if (!plls)
+		return -EINVAL;
+
+	clk_data = mtk_alloc_clk_data(num_plls);
+	if (!clk_data)
+		return -ENOMEM;
+
+	r = mtk_clk_register_plls(node, plls, num_plls, clk_data);
+	if (r) {
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r) {
+		mtk_clk_unregister_plls(plls, num_plls, clk_data);
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	return 0;
+}
+
+static void clk_mt8196_mfg_remove(struct platform_device *pdev)
+{
+	const struct mtk_pll_data *plls = of_device_get_match_data(&pdev->dev);
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = 1;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_plls(plls, num_plls, clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static struct platform_driver clk_mt8196_mfg_drv = {
+	.probe = clk_mt8196_mfg_probe,
+	.remove = clk_mt8196_mfg_remove,
+	.driver = {
+		.name = "clk-mt8196-mfg",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_mfg,
+	},
+};
+
+module_platform_driver(clk_mt8196_mfg_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:11 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:11 +0800
Subject: [PATCH 15/26] clk: mediatek: Add MT8196 mcu clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-16-guangjie.song@mediatek.com>

Add MT8196 mcu clock controller which provides pll control for mcu.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig          |   7 ++
 drivers/clk/mediatek/Makefile         |   1 +
 drivers/clk/mediatek/clk-mt8196-mcu.c | 167 ++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mcu.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index bc373e9ab589..4473feebae40 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1024,6 +1024,13 @@ config COMMON_CLK_MT8196_IMP_IIC_WRAP
 	help
 	  This driver supports MediaTek MT8196 i2c clocks.
 
+config COMMON_CLK_MT8196_MCUSYS
+	tristate "Clock driver for MediaTek MT8196 mcusys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 mcusys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index beea4d8eeebe..1f6717569609 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -155,6 +155,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys
 				   clk-mt8196-peri_ao.o
 obj-$(CONFIG_COMMON_CLK_MT8196_ADSP) += clk-mt8196-adsp.o
 obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-mcu.c b/drivers/clk/mediatek/clk-mt8196-mcu.c
new file mode 100644
index 000000000000..19d13156794c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-mcu.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+#define ARMPLL_LL_CON0	0x008
+#define ARMPLL_LL_CON1	0x00c
+#define ARMPLL_LL_CON2	0x010
+#define ARMPLL_LL_CON3	0x014
+#define ARMPLL_BL_CON0	0x008
+#define ARMPLL_BL_CON1	0x00c
+#define ARMPLL_BL_CON2	0x010
+#define ARMPLL_BL_CON3	0x014
+#define ARMPLL_B_CON0	0x008
+#define ARMPLL_B_CON1	0x00c
+#define ARMPLL_B_CON2	0x010
+#define ARMPLL_B_CON3	0x014
+#define CCIPLL_CON0	0x008
+#define CCIPLL_CON1	0x00c
+#define CCIPLL_CON2	0x010
+#define CCIPLL_CON3	0x014
+#define PTPPLL_CON0	0x008
+#define PTPPLL_CON1	0x00c
+#define PTPPLL_CON2	0x010
+#define PTPPLL_CON3	0x014
+
+#define MT8196_PLL_FMAX		(3800UL * MHZ)
+#define MT8196_PLL_FMIN		(1500UL * MHZ)
+#define MT8196_INTEGER_BITS	8
+
+#define PLL(_id, _name, _reg, _en_reg, _en_mask, _pll_en_bit,	\
+	    _flags, _rst_bar_mask,				\
+	    _pd_reg, _pd_shift, _tuner_reg,			\
+	    _tuner_en_reg, _tuner_en_bit,			\
+	    _pcw_reg, _pcw_shift, _pcwbits) {			\
+		.id = _id,					\
+		.name = _name,					\
+		.reg = _reg,					\
+		.en_reg = _en_reg,				\
+		.en_mask = _en_mask,				\
+		.pll_en_bit = _pll_en_bit,			\
+		.flags = (_flags) | CLK_FENC_ENABLE,		\
+		.rst_bar_mask = _rst_bar_mask,			\
+		.fmax = MT8196_PLL_FMAX,			\
+		.fmin = MT8196_PLL_FMIN,			\
+		.pd_reg = _pd_reg,				\
+		.pd_shift = _pd_shift,				\
+		.tuner_reg = _tuner_reg,			\
+		.tuner_en_reg = _tuner_en_reg,			\
+		.tuner_en_bit = _tuner_en_bit,			\
+		.pcw_reg = _pcw_reg,				\
+		.pcw_shift = _pcw_shift,			\
+		.pcwbits = _pcwbits,				\
+		.pcwibits = MT8196_INTEGER_BITS,		\
+	}
+
+static const struct mtk_pll_data cpu_bl_plls[] = {
+	PLL(CLK_CPBL_ARMPLL_BL, "armpll-bl", ARMPLL_BL_CON0,
+	    ARMPLL_BL_CON0, 0, 0, PLL_AO, BIT(0),
+	    ARMPLL_BL_CON1, 24, 0, 0, 0,
+	    ARMPLL_BL_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data cpu_b_plls[] = {
+	PLL(CLK_CPB_ARMPLL_B, "armpll-b", ARMPLL_B_CON0,
+	    ARMPLL_B_CON0, 0, 0, PLL_AO, BIT(0),
+	    ARMPLL_B_CON1, 24, 0, 0, 0,
+	    ARMPLL_B_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data cpu_ll_plls[] = {
+	PLL(CLK_CPLL_ARMPLL_LL, "armpll-ll", ARMPLL_LL_CON0,
+	    ARMPLL_LL_CON0, 0, 0, PLL_AO, BIT(0),
+	    ARMPLL_LL_CON1, 24, 0, 0, 0,
+	    ARMPLL_LL_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data cci_plls[] = {
+	PLL(CLK_CCIPLL, "ccipll", CCIPLL_CON0,
+	    CCIPLL_CON0, 0, 0, PLL_AO, BIT(0),
+	    CCIPLL_CON1, 24, 0, 0, 0,
+	    CCIPLL_CON1, 0, 22),
+};
+
+static const struct mtk_pll_data ptp_plls[] = {
+	PLL(CLK_PTPPLL, "ptppll", PTPPLL_CON0,
+	    PTPPLL_CON0, 0, 0, PLL_AO, BIT(0),
+	    PTPPLL_CON1, 24, 0, 0, 0,
+	    PTPPLL_CON1, 0, 22),
+};
+
+static const struct of_device_id of_match_clk_mt8196_mcu[] = {
+	{ .compatible = "mediatek,mt8196-armpll_bl_pll_ctrl", .data = &cpu_bl_plls, },
+	{ .compatible = "mediatek,mt8196-armpll_b_pll_ctrl", .data = &cpu_b_plls, },
+	{ .compatible = "mediatek,mt8196-armpll_ll_pll_ctrl", .data = &cpu_ll_plls, },
+	{ .compatible = "mediatek,mt8196-ccipll_pll_ctrl", .data = &cci_plls, },
+	{ .compatible = "mediatek,mt8196-ptppll_pll_ctrl", .data = &ptp_plls, },
+	{ /* sentinel */ }
+};
+
+static int clk_mt8196_mcu_probe(struct platform_device *pdev)
+{
+	const struct mtk_pll_data *plls;
+	struct clk_hw_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = 1;
+	int r;
+
+	plls = of_device_get_match_data(&pdev->dev);
+	if (!plls)
+		return -EINVAL;
+
+	clk_data = mtk_alloc_clk_data(num_plls);
+	if (!clk_data)
+		return -ENOMEM;
+
+	r = mtk_clk_register_plls(node, plls, num_plls, clk_data);
+	if (r) {
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r) {
+		mtk_clk_unregister_plls(plls, num_plls, clk_data);
+		mtk_free_clk_data(clk_data);
+		return r;
+	}
+
+	return 0;
+}
+
+static void clk_mt8196_mcu_remove(struct platform_device *pdev)
+{
+	const struct mtk_pll_data *plls = of_device_get_match_data(&pdev->dev);
+	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	int num_plls = 1;
+
+	of_clk_del_provider(node);
+	mtk_clk_unregister_plls(plls, num_plls, clk_data);
+	mtk_free_clk_data(clk_data);
+}
+
+static struct platform_driver clk_mt8196_mcu_drv = {
+	.probe = clk_mt8196_mcu_probe,
+	.remove = clk_mt8196_mcu_remove,
+	.driver = {
+		.name = "clk-mt8196-mcu",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt8196_mcu,
+	},
+};
+
+module_platform_driver(clk_mt8196_mcu_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From guangjie.song at mediatek.com  Thu Mar  6 19:27:12 2025
From: guangjie.song at mediatek.com (Guangjie Song)
Date: Fri, 7 Mar 2025 11:27:12 +0800
Subject: [PATCH 16/26] clk: mediatek: Add MT8196 mdpsys clock support
In-Reply-To: <20250307032942.10447-1-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
Message-ID: <20250307032942.10447-17-guangjie.song@mediatek.com>

Add MT8196 mdpsys clock controller which provides clock gate control
for media display.

Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
---
 drivers/clk/mediatek/Kconfig             |   7 +
 drivers/clk/mediatek/Makefile            |   1 +
 drivers/clk/mediatek/clk-mt8196-mdpsys.c | 357 +++++++++++++++++++++++
 3 files changed, 365 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8196-mdpsys.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 4473feebae40..8763cc1480a3 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -1031,6 +1031,13 @@ config COMMON_CLK_MT8196_MCUSYS
 	help
 	  This driver supports MediaTek MT8196 mcusys clocks.
 
+config COMMON_CLK_MT8196_MDPSYS
+	tristate "Clock driver for MediaTek MT8196 mdpsys"
+	depends on COMMON_CLK_MT8196
+	default COMMON_CLK_MT8196
+	help
+	  This driver supports MediaTek MT8196 mdpsys clocks.
+
 config COMMON_CLK_MT8365
 	tristate "Clock driver for MediaTek MT8365"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 1f6717569609..dccc6d84941c 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -156,6 +156,7 @@ obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-apmixedsys
 obj-$(CONFIG_COMMON_CLK_MT8196_ADSP) += clk-mt8196-adsp.o
 obj-$(CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP) += clk-mt8196-imp_iic_wrap.o
 obj-$(CONFIG_COMMON_CLK_MT8196_MCUSYS) += clk-mt8196-mcu.o
+obj-$(CONFIG_COMMON_CLK_MT8196_MDPSYS) += clk-mt8196-mdpsys.o
 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o
 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o
 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8196-mdpsys.c b/drivers/clk/mediatek/clk-mt8196-mdpsys.c
new file mode 100644
index 000000000000..ef591efa9fec
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8196-mdpsys.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Guangjie Song <guangjie.song at mediatek.com>
+ */
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mt8196-clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+static const struct mtk_gate_regs mdp10_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mdp11_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mdp12_cg_regs = {
+	.set_ofs = 0x124,
+	.clr_ofs = 0x128,
+	.sta_ofs = 0x120,
+};
+
+#define GATE_MDP10(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mdp10_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_MDP10_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_MDP11(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mdp11_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_MDP11_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_MDP12(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mdp12_cg_regs,			\
+		.shift = _shift,			\
+		.flags = CLK_OPS_PARENT_ENABLE,		\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_MDP12_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate mdp1_clks[] = {
+	/* MDP10 */
+	GATE_MDP10(CLK_MDP1_MDP_MUTEX0, "mdp1_mdp_mutex0", "ck2_mdp_ck", 0),
+	GATE_MDP10_V(CLK_MDP1_MDP_MUTEX0_MML, "mdp1_mdp_mutex0_mml", "mdp1_mdp_mutex0"),
+	GATE_MDP10(CLK_MDP1_SMI0, "mdp1_smi0", "ck2_mdp_ck", 1),
+	GATE_MDP10_V(CLK_MDP1_SMI0_SMI, "mdp1_smi0_smi", "mdp1_smi0"),
+	GATE_MDP10(CLK_MDP1_APB_BUS, "mdp1_apb_bus", "ck2_mdp_ck", 2),
+	GATE_MDP10_V(CLK_MDP1_APB_BUS_MML, "mdp1_apb_bus_mml", "mdp1_apb_bus"),
+	GATE_MDP10(CLK_MDP1_MDP_RDMA0, "mdp1_mdp_rdma0", "ck2_mdp_ck", 3),
+	GATE_MDP10_V(CLK_MDP1_MDP_RDMA0_MML, "mdp1_mdp_rdma0_mml", "mdp1_mdp_rdma0"),
+	GATE_MDP10(CLK_MDP1_MDP_RDMA1, "mdp1_mdp_rdma1", "ck2_mdp_ck", 4),
+	GATE_MDP10_V(CLK_MDP1_MDP_RDMA1_MML, "mdp1_mdp_rdma1_mml", "mdp1_mdp_rdma1"),
+	GATE_MDP10(CLK_MDP1_MDP_RDMA2, "mdp1_mdp_rdma2", "ck2_mdp_ck", 5),
+	GATE_MDP10_V(CLK_MDP1_MDP_RDMA2_MML, "mdp1_mdp_rdma2_mml", "mdp1_mdp_rdma2"),
+	GATE_MDP10(CLK_MDP1_MDP_BIRSZ0, "mdp1_mdp_birsz0", "ck2_mdp_ck", 6),
+	GATE_MDP10_V(CLK_MDP1_MDP_BIRSZ0_MML, "mdp1_mdp_birsz0_mml", "mdp1_mdp_birsz0"),
+	GATE_MDP10(CLK_MDP1_MDP_HDR0, "mdp1_mdp_hdr0", "ck2_mdp_ck", 7),
+	GATE_MDP10_V(CLK_MDP1_MDP_HDR0_MML, "mdp1_mdp_hdr0_mml", "mdp1_mdp_hdr0"),
+	GATE_MDP10(CLK_MDP1_MDP_AAL0, "mdp1_mdp_aal0", "ck2_mdp_ck", 8),
+	GATE_MDP10_V(CLK_MDP1_MDP_AAL0_MML, "mdp1_mdp_aal0_mml", "mdp1_mdp_aal0"),
+	GATE_MDP10(CLK_MDP1_MDP_RSZ0, "mdp1_mdp_rsz0", "ck2_mdp_ck", 9),
+	GATE_MDP10_V(CLK_MDP1_MDP_RSZ0_MML, "mdp1_mdp_rsz0_mml", "mdp1_mdp_rsz0"),
+	GATE_MDP10(CLK_MDP1_MDP_RSZ2, "mdp1_mdp_rsz2", "ck2_mdp_ck", 10),
+	GATE_MDP10_V(CLK_MDP1_MDP_RSZ2_MML, "mdp1_mdp_rsz2_mml", "mdp1_mdp_rsz2"),
+	GATE_MDP10(CLK_MDP1_MDP_TDSHP0, "mdp1_mdp_tdshp0", "ck2_mdp_ck", 11),
+	GATE_MDP10_V(CLK_MDP1_MDP_TDSHP0_MML, "mdp1_mdp_tdshp0_mml", "mdp1_mdp_tdshp0"),
+	GATE_MDP10(CLK_MDP1_MDP_COLOR0, "mdp1_mdp_color0", "ck2_mdp_ck", 12),
+	GATE_MDP10_V(CLK_MDP1_MDP_COLOR0_MML, "mdp1_mdp_color0_mml", "mdp1_mdp_color0"),
+	GATE_MDP10(CLK_MDP1_MDP_WROT0, "mdp1_mdp_wrot0", "ck2_mdp_ck", 13),
+	GATE_MDP10_V(CLK_MDP1_MDP_WROT0_MML, "mdp1_mdp_wrot0_mml", "mdp1_mdp_wrot0"),
+	GATE_MDP10(CLK_MDP1_MDP_WROT1, "mdp1_mdp_wrot1", "ck2_mdp_ck", 14),
+	GATE_MDP10_V(CLK_MDP1_MDP_WROT1_MML, "mdp1_mdp_wrot1_mml", "mdp1_mdp_wrot1"),
+	GATE_MDP10(CLK_MDP1_MDP_WROT2, "mdp1_mdp_wrot2", "ck2_mdp_ck", 15),
+	GATE_MDP10_V(CLK_MDP1_MDP_WROT2_MML, "mdp1_mdp_wrot2_mml", "mdp1_mdp_wrot2"),
+	GATE_MDP10(CLK_MDP1_MDP_FAKE_ENG0, "mdp1_mdp_fake_eng0", "ck2_mdp_ck", 16),
+	GATE_MDP10_V(CLK_MDP1_MDP_FAKE_ENG0_MML, "mdp1_mdp_fake_eng0_mml", "mdp1_mdp_fake_eng0"),
+	GATE_MDP10(CLK_MDP1_APB_DB, "mdp1_apb_db", "ck2_mdp_ck", 17),
+	GATE_MDP10_V(CLK_MDP1_APB_DB_MML, "mdp1_apb_db_mml", "mdp1_apb_db"),
+	GATE_MDP10(CLK_MDP1_MDP_DLI_ASYNC0, "mdp1_mdp_dli_async0", "ck2_mdp_ck", 18),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLI_ASYNC0_MML, "mdp1_mdp_dli_async0_mml", "mdp1_mdp_dli_async0"),
+	GATE_MDP10(CLK_MDP1_MDP_DLI_ASYNC1, "mdp1_mdp_dli_async1", "ck2_mdp_ck", 19),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLI_ASYNC1_MML, "mdp1_mdp_dli_async1_mml", "mdp1_mdp_dli_async1"),
+	GATE_MDP10(CLK_MDP1_MDP_DLO_ASYNC0, "mdp1_mdp_dlo_async0", "ck2_mdp_ck", 20),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLO_ASYNC0_MML, "mdp1_mdp_dlo_async0_mml", "mdp1_mdp_dlo_async0"),
+	GATE_MDP10(CLK_MDP1_MDP_DLO_ASYNC1, "mdp1_mdp_dlo_async1", "ck2_mdp_ck", 21),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLO_ASYNC1_MML, "mdp1_mdp_dlo_async1_mml", "mdp1_mdp_dlo_async1"),
+	GATE_MDP10(CLK_MDP1_MDP_DLI_ASYNC2, "mdp1_mdp_dli_async2", "ck2_mdp_ck", 22),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLI_ASYNC2_MML, "mdp1_mdp_dli_async2_mml", "mdp1_mdp_dli_async2"),
+	GATE_MDP10(CLK_MDP1_MDP_DLO_ASYNC2, "mdp1_mdp_dlo_async2", "ck2_mdp_ck", 23),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLO_ASYNC2_MML, "mdp1_mdp_dlo_async2_mml", "mdp1_mdp_dlo_async2"),
+	GATE_MDP10(CLK_MDP1_MDP_DLO_ASYNC3, "mdp1_mdp_dlo_async3", "ck2_mdp_ck", 24),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLO_ASYNC3_MML, "mdp1_mdp_dlo_async3_mml", "mdp1_mdp_dlo_async3"),
+	GATE_MDP10(CLK_MDP1_IMG_DL_ASYNC0, "mdp1_img_dl_async0", "ck2_mdp_ck", 25),
+	GATE_MDP10_V(CLK_MDP1_IMG_DL_ASYNC0_MML, "mdp1_img_dl_async0_mml", "mdp1_img_dl_async0"),
+	GATE_MDP10(CLK_MDP1_MDP_RROT0, "mdp1_mdp_rrot0", "ck2_mdp_ck", 26),
+	GATE_MDP10_V(CLK_MDP1_MDP_RROT0_MML, "mdp1_mdp_rrot0_mml", "mdp1_mdp_rrot0"),
+	GATE_MDP10(CLK_MDP1_MDP_MERGE0, "mdp1_mdp_merge0", "ck2_mdp_ck", 27),
+	GATE_MDP10_V(CLK_MDP1_MDP_MERGE0_MML, "mdp1_mdp_merge0_mml", "mdp1_mdp_merge0"),
+	GATE_MDP10(CLK_MDP1_MDP_C3D0, "mdp1_mdp_c3d0", "ck2_mdp_ck", 28),
+	GATE_MDP10_V(CLK_MDP1_MDP_C3D0_MML, "mdp1_mdp_c3d0_mml", "mdp1_mdp_c3d0"),
+	GATE_MDP10(CLK_MDP1_MDP_FG0, "mdp1_mdp_fg0", "ck2_mdp_ck", 29),
+	GATE_MDP10_V(CLK_MDP1_MDP_FG0_MML, "mdp1_mdp_fg0_mml", "mdp1_mdp_fg0"),
+	GATE_MDP10(CLK_MDP1_MDP_CLA2, "mdp1_mdp_cla2", "ck2_mdp_ck", 30),
+	GATE_MDP10_V(CLK_MDP1_MDP_CLA2_MML, "mdp1_mdp_cla2_mml", "mdp1_mdp_cla2"),
+	GATE_MDP10(CLK_MDP1_MDP_DLO_ASYNC4, "mdp1_mdp_dlo_async4", "ck2_mdp_ck", 31),
+	GATE_MDP10_V(CLK_MDP1_MDP_DLO_ASYNC4_MML, "mdp1_mdp_dlo_async4_mml", "mdp1_mdp_dlo_async4"),
+	/* MDP11 */
+	GATE_MDP11(CLK_MDP1_VPP_RSZ0, "mdp1_vpp_rsz0", "ck2_mdp_ck", 0),
+	GATE_MDP11_V(CLK_MDP1_VPP_RSZ0_MML, "mdp1_vpp_rsz0_mml", "mdp1_vpp_rsz0"),
+	GATE_MDP11(CLK_MDP1_VPP_RSZ1, "mdp1_vpp_rsz1", "ck2_mdp_ck", 1),
+	GATE_MDP11_V(CLK_MDP1_VPP_RSZ1_MML, "mdp1_vpp_rsz1_mml", "mdp1_vpp_rsz1"),
+	GATE_MDP11(CLK_MDP1_MDP_DLO_ASYNC5, "mdp1_mdp_dlo_async5", "ck2_mdp_ck", 2),
+	GATE_MDP11_V(CLK_MDP1_MDP_DLO_ASYNC5_MML, "mdp1_mdp_dlo_async5_mml", "mdp1_mdp_dlo_async5"),
+	GATE_MDP11(CLK_MDP1_IMG0, "mdp1_img0", "ck2_mdp_ck", 3),
+	GATE_MDP11_V(CLK_MDP1_IMG0_MML, "mdp1_img0_mml", "mdp1_img0"),
+	GATE_MDP11(CLK_MDP1_F26M, "mdp1_f26m", "ck_f26m_ck", 27),
+	GATE_MDP11_V(CLK_MDP1_F26M_MML, "mdp1_f26m_mml", "mdp1_f26m"),
+	/* MDP12 */
+	GATE_MDP12(CLK_MDP1_IMG_DL_RELAY0, "mdp1_img_dl_relay0", "ck2_mdp_ck", 0),
+	GATE_MDP12_V(CLK_MDP1_IMG_DL_RELAY0_MML, "mdp1_img_dl_relay0_mml", "mdp1_img_dl_relay0"),
+	GATE_MDP12(CLK_MDP1_IMG_DL_RELAY1, "mdp1_img_dl_relay1", "ck2_mdp_ck", 8),
+	GATE_MDP12_V(CLK_MDP1_IMG_DL_RELAY1_MML, "mdp1_img_dl_relay1_mml", "mdp1_img_dl_relay1"),
+};
+
+static const struct mtk_clk_desc mdp1_mcd = {
+	.clks = mdp1_clks,
+	.num_clks = ARRAY_SIZE(mdp1_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct mtk_gate_regs mdp0_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mdp1_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mdp2_cg_regs = {
+	.set_ofs = 0x124,
+	.clr_ofs = 0x128,
+	.sta_ofs = 0x120,
+};
+
+#define GATE_MDP0(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mdp0_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MDP0_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_MDP1(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mdp1_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MDP1_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+#define GATE_MDP2(_id, _name, _parent, _shift) {\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &mdp2_cg_regs,		\
+		.shift = _shift,		\
+		.flags = CLK_OPS_PARENT_ENABLE,	\
+		.ops = &mtk_clk_gate_ops_setclr,\
+	}
+
+#define GATE_MDP2_V(_id, _name, _parent) {	\
+		.id = _id,			\
+		.name = _name,			\
+		.parent_name = _parent,		\
+		.regs = &cg_regs_dummy,		\
+		.ops = &mtk_clk_dummy_ops,	\
+	}
+
+static const struct mtk_gate mdp_clks[] = {
+	/* MDP0 */
+	GATE_MDP0(CLK_MDP_MDP_MUTEX0, "mdp_mdp_mutex0", "ck2_mdp_ck", 0),
+	GATE_MDP0_V(CLK_MDP_MDP_MUTEX0_MML, "mdp_mdp_mutex0_mml", "mdp_mdp_mutex0"),
+	GATE_MDP0(CLK_MDP_SMI0, "mdp_smi0", "ck2_mdp_ck", 1),
+	GATE_MDP0_V(CLK_MDP_SMI0_MML, "mdp_smi0_mml", "mdp_smi0"),
+	GATE_MDP0_V(CLK_MDP_SMI0_SMI, "mdp_smi0_smi", "mdp_smi0"),
+	GATE_MDP0(CLK_MDP_APB_BUS, "mdp_apb_bus", "ck2_mdp_ck", 2),
+	GATE_MDP0_V(CLK_MDP_APB_BUS_MML, "mdp_apb_bus_mml", "mdp_apb_bus"),
+	GATE_MDP0(CLK_MDP_MDP_RDMA0, "mdp_mdp_rdma0", "ck2_mdp_ck", 3),
+	GATE_MDP0_V(CLK_MDP_MDP_RDMA0_MML, "mdp_mdp_rdma0_mml", "mdp_mdp_rdma0"),
+	GATE_MDP0(CLK_MDP_MDP_RDMA1, "mdp_mdp_rdma1", "ck2_mdp_ck", 4),
+	GATE_MDP0_V(CLK_MDP_MDP_RDMA1_MML, "mdp_mdp_rdma1_mml", "mdp_mdp_rdma1"),
+	GATE_MDP0(CLK_MDP_MDP_RDMA2, "mdp_mdp_rdma2", "ck2_mdp_ck", 5),
+	GATE_MDP0_V(CLK_MDP_MDP_RDMA2_MML, "mdp_mdp_rdma2_mml", "mdp_mdp_rdma2"),
+	GATE_MDP0(CLK_MDP_MDP_BIRSZ0, "mdp_mdp_birsz0", "ck2_mdp_ck", 6),
+	GATE_MDP0_V(CLK_MDP_MDP_BIRSZ0_MML, "mdp_mdp_birsz0_mml", "mdp_mdp_birsz0"),
+	GATE_MDP0(CLK_MDP_MDP_HDR0, "mdp_mdp_hdr0", "ck2_mdp_ck", 7),
+	GATE_MDP0_V(CLK_MDP_MDP_HDR0_MML, "mdp_mdp_hdr0_mml", "mdp_mdp_hdr0"),
+	GATE_MDP0(CLK_MDP_MDP_AAL0, "mdp_mdp_aal0", "ck2_mdp_ck", 8),
+	GATE_MDP0_V(CLK_MDP_MDP_AAL0_MML, "mdp_mdp_aal0_mml", "mdp_mdp_aal0"),
+	GATE_MDP0(CLK_MDP_MDP_RSZ0, "mdp_mdp_rsz0", "ck2_mdp_ck", 9),
+	GATE_MDP0_V(CLK_MDP_MDP_RSZ0_MML, "mdp_mdp_rsz0_mml", "mdp_mdp_rsz0"),
+	GATE_MDP0(CLK_MDP_MDP_RSZ2, "mdp_mdp_rsz2", "ck2_mdp_ck", 10),
+	GATE_MDP0_V(CLK_MDP_MDP_RSZ2_MML, "mdp_mdp_rsz2_mml", "mdp_mdp_rsz2"),
+	GATE_MDP0(CLK_MDP_MDP_TDSHP0, "mdp_mdp_tdshp0", "ck2_mdp_ck", 11),
+	GATE_MDP0_V(CLK_MDP_MDP_TDSHP0_MML, "mdp_mdp_tdshp0_mml", "mdp_mdp_tdshp0"),
+	GATE_MDP0(CLK_MDP_MDP_COLOR0, "mdp_mdp_color0", "ck2_mdp_ck", 12),
+	GATE_MDP0_V(CLK_MDP_MDP_COLOR0_MML, "mdp_mdp_color0_mml", "mdp_mdp_color0"),
+	GATE_MDP0(CLK_MDP_MDP_WROT0, "mdp_mdp_wrot0", "ck2_mdp_ck", 13),
+	GATE_MDP0_V(CLK_MDP_MDP_WROT0_MML, "mdp_mdp_wrot0_mml", "mdp_mdp_wrot0"),
+	GATE_MDP0(CLK_MDP_MDP_WROT1, "mdp_mdp_wrot1", "ck2_mdp_ck", 14),
+	GATE_MDP0_V(CLK_MDP_MDP_WROT1_MML, "mdp_mdp_wrot1_mml", "mdp_mdp_wrot1"),
+	GATE_MDP0(CLK_MDP_MDP_WROT2, "mdp_mdp_wrot2", "ck2_mdp_ck", 15),
+	GATE_MDP0_V(CLK_MDP_MDP_WROT2_MML, "mdp_mdp_wrot2_mml", "mdp_mdp_wrot2"),
+	GATE_MDP0(CLK_MDP_MDP_FAKE_ENG0, "mdp_mdp_fake_eng0", "ck2_mdp_ck", 16),
+	GATE_MDP0_V(CLK_MDP_MDP_FAKE_ENG0_MML, "mdp_mdp_fake_eng0_mml", "mdp_mdp_fake_eng0"),
+	GATE_MDP0(CLK_MDP_APB_DB, "mdp_apb_db", "ck2_mdp_ck", 17),
+	GATE_MDP0_V(CLK_MDP_APB_DB_MML, "mdp_apb_db_mml", "mdp_apb_db"),
+	GATE_MDP0(CLK_MDP_MDP_DLI_ASYNC0, "mdp_mdp_dli_async0", "ck2_mdp_ck", 18),
+	GATE_MDP0_V(CLK_MDP_MDP_DLI_ASYNC0_MML, "mdp_mdp_dli_async0_mml", "mdp_mdp_dli_async0"),
+	GATE_MDP0(CLK_MDP_MDP_DLI_ASYNC1, "mdp_mdp_dli_async1", "ck2_mdp_ck", 19),
+	GATE_MDP0_V(CLK_MDP_MDP_DLI_ASYNC1_MML, "mdp_mdp_dli_async1_mml", "mdp_mdp_dli_async1"),
+	GATE_MDP0(CLK_MDP_MDP_DLO_ASYNC0, "mdp_mdp_dlo_async0", "ck2_mdp_ck", 20),
+	GATE_MDP0_V(CLK_MDP_MDP_DLO_ASYNC0_MML, "mdp_mdp_dlo_async0_mml", "mdp_mdp_dlo_async0"),
+	GATE_MDP0(CLK_MDP_MDP_DLO_ASYNC1, "mdp_mdp_dlo_async1", "ck2_mdp_ck", 21),
+	GATE_MDP0_V(CLK_MDP_MDP_DLO_ASYNC1_MML, "mdp_mdp_dlo_async1_mml", "mdp_mdp_dlo_async1"),
+	GATE_MDP0(CLK_MDP_MDP_DLI_ASYNC2, "mdp_mdp_dli_async2", "ck2_mdp_ck", 22),
+	GATE_MDP0_V(CLK_MDP_MDP_DLI_ASYNC2_MML, "mdp_mdp_dli_async2_mml", "mdp_mdp_dli_async2"),
+	GATE_MDP0(CLK_MDP_MDP_DLO_ASYNC2, "mdp_mdp_dlo_async2", "ck2_mdp_ck", 23),
+	GATE_MDP0_V(CLK_MDP_MDP_DLO_ASYNC2_MML, "mdp_mdp_dlo_async2_mml", "mdp_mdp_dlo_async2"),
+	GATE_MDP0(CLK_MDP_MDP_DLO_ASYNC3, "mdp_mdp_dlo_async3", "ck2_mdp_ck", 24),
+	GATE_MDP0_V(CLK_MDP_MDP_DLO_ASYNC3_MML, "mdp_mdp_dlo_async3_mml", "mdp_mdp_dlo_async3"),
+	GATE_MDP0(CLK_MDP_IMG_DL_ASYNC0, "mdp_img_dl_async0", "ck2_mdp_ck", 25),
+	GATE_MDP0_V(CLK_MDP_IMG_DL_ASYNC0_MML, "mdp_img_dl_async0_mml", "mdp_img_dl_async0"),
+	GATE_MDP0(CLK_MDP_MDP_RROT0, "mdp_mdp_rrot0", "ck2_mdp_ck", 26),
+	GATE_MDP0_V(CLK_MDP_MDP_RROT0_MML, "mdp_mdp_rrot0_mml", "mdp_mdp_rrot0"),
+	GATE_MDP0(CLK_MDP_MDP_MERGE0, "mdp_mdp_merge0", "ck2_mdp_ck", 27),
+	GATE_MDP0_V(CLK_MDP_MDP_MERGE0_MML, "mdp_mdp_merge0_mml", "mdp_mdp_merge0"),
+	GATE_MDP0(CLK_MDP_MDP_C3D0, "mdp_mdp_c3d0", "ck2_mdp_ck", 28),
+	GATE_MDP0_V(CLK_MDP_MDP_C3D0_MML, "mdp_mdp_c3d0_mml", "mdp_mdp_c3d0"),
+	GATE_MDP0(CLK_MDP_MDP_FG0, "mdp_mdp_fg0", "ck2_mdp_ck", 29),
+	GATE_MDP0_V(CLK_MDP_MDP_FG0_MML, "mdp_mdp_fg0_mml", "mdp_mdp_fg0"),
+	GATE_MDP0(CLK_MDP_MDP_CLA2, "mdp_mdp_cla2", "ck2_mdp_ck", 30),
+	GATE_MDP0_V(CLK_MDP_MDP_CLA2_MML, "mdp_mdp_cla2_mml", "mdp_mdp_cla2"),
+	GATE_MDP0(CLK_MDP_MDP_DLO_ASYNC4, "mdp_mdp_dlo_async4", "ck2_mdp_ck", 31),
+	GATE_MDP0_V(CLK_MDP_MDP_DLO_ASYNC4_MML, "mdp_mdp_dlo_async4_mml", "mdp_mdp_dlo_async4"),
+	/* MDP1 */
+	GATE_MDP1(CLK_MDP_VPP_RSZ0, "mdp_vpp_rsz0", "ck2_mdp_ck", 0),
+	GATE_MDP1_V(CLK_MDP_VPP_RSZ0_MML, "mdp_vpp_rsz0_mml", "mdp_vpp_rsz0"),
+	GATE_MDP1(CLK_MDP_VPP_RSZ1, "mdp_vpp_rsz1", "ck2_mdp_ck", 1),
+	GATE_MDP1_V(CLK_MDP_VPP_RSZ1_MML, "mdp_vpp_rsz1_mml", "mdp_vpp_rsz1"),
+	GATE_MDP1(CLK_MDP_MDP_DLO_ASYNC5, "mdp_mdp_dlo_async5", "ck2_mdp_ck", 2),
+	GATE_MDP1_V(CLK_MDP_MDP_DLO_ASYNC5_MML, "mdp_mdp_dlo_async5_mml", "mdp_mdp_dlo_async5"),
+	GATE_MDP1(CLK_MDP_IMG0, "mdp_img0", "ck2_mdp_ck", 3),
+	GATE_MDP1_V(CLK_MDP_IMG0_MML, "mdp_img0_mml", "mdp_img0"),
+	GATE_MDP1(CLK_MDP_F26M, "mdp_f26m", "ck_f26m_ck", 27),
+	GATE_MDP1_V(CLK_MDP_F26M_MML, "mdp_f26m_mml", "mdp_f26m"),
+	/* MDP2 */
+	GATE_MDP2(CLK_MDP_IMG_DL_RELAY0, "mdp_img_dl_relay0", "ck2_mdp_ck", 0),
+	GATE_MDP2_V(CLK_MDP_IMG_DL_RELAY0_MML, "mdp_img_dl_relay0_mml", "mdp_img_dl_relay0"),
+	GATE_MDP2(CLK_MDP_IMG_DL_RELAY1, "mdp_img_dl_relay1", "ck2_mdp_ck", 8),
+	GATE_MDP2_V(CLK_MDP_IMG_DL_RELAY1_MML, "mdp_img_dl_relay1_mml", "mdp_img_dl_relay1"),
+};
+
+static const struct mtk_clk_desc mdp_mcd = {
+	.clks = mdp_clks,
+	.num_clks = ARRAY_SIZE(mdp_clks),
+	.need_runtime_pm = true,
+};
+
+static const struct of_device_id of_match_clk_mt8196_mdpsys[] = {
+	{ .compatible = "mediatek,mt8196-mdpsys1", .data = &mdp1_mcd, },
+	{ .compatible = "mediatek,mt8196-mdpsys", .data = &mdp_mcd, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8196_mdpsys_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8196-mdpsys",
+		.of_match_table = of_match_clk_mt8196_mdpsys,
+	},
+};
+
+module_platform_driver(clk_mt8196_mdpsys_drv);
+MODULE_LICENSE("GPL");
-- 
2.45.2



From cki-project at redhat.com  Thu Mar  6 20:23:03 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 04:23:03 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <25841.125030623230600141@us-mta-302.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704159050

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704159050-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From anshuman.khandual at arm.com  Thu Mar  6 21:08:51 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Fri,  7 Mar 2025 10:38:51 +0530
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
Message-ID: <20250307050851.4034393-1-anshuman.khandual@arm.com>

Address bytes shifted with a single 64 bit page table entry (any page table
level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
is not very readable or easy to reason about. Besides it is going to change
with D128, where each 128 bit page table entry will shift address bytes by
4 (aka 2^4 = 16) instead.

Let's just formalise this address bytes shift value into a new macro called
PTE_SHIFT establishing a logical abstraction, thus improving readability as
well. This does not cause any functional change.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
Cc: Alexander Potapenko <glider at google.com>
Cc: Andrey Konovalov <andreyknvl at gmail.com>
Cc: Dmitry Vyukov <dvyukov at google.com>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: kasan-dev at googlegroups.com
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
This patch applies on v6.14-rc5

 arch/arm64/Kconfig                      |  2 +-
 arch/arm64/include/asm/kernel-pgtable.h |  3 ++-
 arch/arm64/include/asm/pgtable-hwdef.h  | 26 +++++++++++++------------
 arch/arm64/kernel/pi/map_range.c        |  2 +-
 arch/arm64/mm/kasan_init.c              |  6 +++---
 5 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..fd3303f2ccda 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
 	default 18
 
 # max bits determined by the following formula:
-#  VA_BITS - PAGE_SHIFT - 3
+#  VA_BITS - PAGE_SHIFT - PTE_SHIFT
 config ARCH_MMAP_RND_BITS_MAX
 	default 19 if ARM64_VA_BITS=36
 	default 24 if ARM64_VA_BITS=39
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index fd5a08450b12..7150a7a10f00 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -49,7 +49,8 @@
 	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
 
 #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
-	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
+	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
+	lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)
 
 #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
 	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index a9136cc551cc..43f98eac7653 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -7,40 +7,42 @@
 
 #include <asm/memory.h>
 
+#define PTE_SHIFT 3
+
 /*
  * Number of page-table levels required to address 'va_bits' wide
  * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
- * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
+ * bits with (PAGE_SHIFT - PTE_SHIFT) bits at each page table level. Hence:
  *
- *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
+ *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTE_SHIFT))
  *
  * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
  *
  * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
  * due to build issues. So we open code DIV_ROUND_UP here:
  *
- *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
+ *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTE_SHIFT) - 1) / (PAGE_SHIFT - PTE_SHIFT))
  *
  * which gets simplified as :
  */
-#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
+#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - PTE_SHIFT - 1) / (PAGE_SHIFT - PTE_SHIFT))
 
 /*
  * Size mapped by an entry at level n ( -1 <= n <= 3)
- * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
+ * We map (PAGE_SHIFT - PTE_SHIFT) at all translation levels and PAGE_SHIFT bits
  * in the final page. The maximum number of translation levels supported by
  * the architecture is 5. Hence, starting at level n, we have further
  * ((4 - n) - 1) levels of translation excluding the offset within the page.
  * So, the total number of bits mapped by an entry at level n is :
  *
- *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
+ *  ((4 - n) - 1) * (PAGE_SHIFT - PTE_SHIFT) + PAGE_SHIFT
  *
  * Rearranging it a bit we get :
- *   (4 - n) * (PAGE_SHIFT - 3) + 3
+ *   (4 - n) * (PAGE_SHIFT - PTE_SHIFT) + PTE_SHIFT
  */
-#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
+#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTE_SHIFT) * (4 - (n)) + PTE_SHIFT)
 
-#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTE_SHIFT))
 
 /*
  * PMD_SHIFT determines the size a level 2 page table entry can map.
@@ -49,7 +51,7 @@
 #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
 #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE-1))
-#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTE_SHIFT))
 #endif
 
 /*
@@ -59,14 +61,14 @@
 #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
 #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
 #define PUD_MASK		(~(PUD_SIZE-1))
-#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTE_SHIFT))
 #endif
 
 #if CONFIG_PGTABLE_LEVELS > 4
 #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
 #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
 #define P4D_MASK		(~(P4D_SIZE-1))
-#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTE_SHIFT))
 #endif
 
 /*
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..3530a5427f57 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 {
 	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
 	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
-	int lshift = (3 - level) * (PAGE_SHIFT - 3);
+	int lshift = (3 - level) * (PAGE_SHIFT - PTE_SHIFT);
 	u64 lmask = (PAGE_SIZE << lshift) - 1;
 
 	start	&= PAGE_MASK;
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index b65a29440a0c..90548079b42e 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
  */
 static bool __init root_level_aligned(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTE_SHIFT);
 
 	return (addr % (PAGE_SIZE << shift)) == 0;
 }
@@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
 	 */
 	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
 							: vabits_actual;
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTE_SHIFT);
 
 	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
 }
@@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
  */
 static int __init next_level_idx(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTE_SHIFT);
 
 	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
 }
-- 
2.30.2



From victor.liu at nxp.com  Thu Mar  6 21:28:05 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Fri, 7 Mar 2025 13:28:05 +0800
Subject: [PATCH] drm/imx: legacy-bridge: fix inconsistent indenting
 warning
In-Reply-To: <20250305103042.3017-1-hanchunchao@inspur.com>
References: <20250305103042.3017-1-hanchunchao@inspur.com>
Message-ID: <2a24baaf-343b-442e-8d43-7238eaa01272@nxp.com>

On 03/05/2025, Charles Han wrote:
> Fix below inconsistent indenting smatch warning.
> smatch warnings:
> drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c:79 devm_imx_drm_legacy_bridge() warn: inconsistent indenting
> 
> Signed-off-by: Charles Han <hanchunchao at inspur.com>
> ---
>  drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Applied to misc/kernel.git (drm-misc-next).
Thanks!

-- 
Regards,
Liu Ying


From yong.liang.choong at linux.intel.com  Thu Mar  6 21:28:46 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Fri, 7 Mar 2025 13:28:46 +0800
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <257769403908de3ac6271059e1febee88654fbdc.camel@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain>
 <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
 <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>
 <d7c0094e-7fd3-4113-8d00-91b7a83ffd1f@linux.intel.com>
 <257769403908de3ac6271059e1febee88654fbdc.camel@linux.intel.com>
Message-ID: <19b78790-d4d3-45db-9b1f-fbe40f8ed795@linux.intel.com>



On 7/3/2025 4:52 am, David E. Box wrote:
> On Thu, 2025-03-06 at 20:56 +0800, Choong Yong Liang wrote:
>>
>>
>> On 6/3/2025 5:05 pm, Andy Shevchenko wrote:
>>> On Thu, Mar 6, 2025 at 10:39?AM Choong Yong Liang
>>> <yong.liang.choong at linux.intel.com> wrote:
>>>> On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
>>>>> Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:
>>> ...
>>>
>>>>>> config DWMAC_INTEL
>>>>>>  ????? default X86
>>>>>>  ????? depends on X86 && STMMAC_ETH && PCI
>>>>>>  ????? depends on COMMON_CLK
>>>>>> +??? depends on ACPI
>>>>> Stray and unexplained change. Please, fix it. We don't need the
>>>>> dependencies
>>>>> which are not realised in the compile time.
>>>> The dependency on ACPI is necessary because the intel_pmc_ipc.h header
>>>> relies on ACPI functionality to interact with the Intel PMC.
>>> So, that header has to be fixed as ACPI here is really unneeded
>>> dependency for the cases when somebody (for whatever reasons) want to
>>> build a kernel without ACPI support but with the driver enabled for
>>> let's say PCI device.
>>>
>>>
>>> -- With Best Regards, Andy Shevchenko
>>
>> Hi Andy,
>>
>> Thank you for your feedback, Andy.
>> I appreciate your insights regarding the ACPI dependency.
>> The intel_pmc_ipc.h header is under the ownership of David E Box, who
>> focuses on the platform code, while my focus is on the netdev.
>>
>> Hi David,
>>
>> if you could kindly look into making the ACPI dependency optional in the
>> intel_pmc_ipc.h header, it would be greatly appreciated.
>> I am more than willing to provide any support necessary to ensure a smooth
>> resolution.
> 
> Choong you only need put the function under a #if CONFIG_ACPI block and provide
> an alternative that returns an error when the code is not build. Like this,
> 
> #if CONFIG_ACPI
> static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
> *rbuf)
> {
>     ...
> }
> #else
> static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
> *rbuf) { return -ENODEV; }
> #endif
> 
> David
> 
>>
>> This patch series has already been accepted, but we recognize the
>> importance of addressing this issue in the next patch series for upstream.
>> Our goal is to ensure that the driver can be compiled and function
>> correctly in both ACPI and non-ACPI environments.
>>
>> Thank you both for your understanding and collaboration.
> 
> 
Hi Andy and David,

Thank you for the feedback.

The current ACPI dependency for the config DWMAC_INTEL is necessary, but I 
agree on making it optional.

Implementing the suggestion from David using the "#if CONFIG_ACPI" approach 
would address your concern about users who need to build a kernel without 
ACPI support.

If you are okay with this approach, then I will submit the solution for 
upstream.


From irogers at google.com  Thu Mar  6 21:30:13 2025
From: irogers at google.com (Ian Rogers)
Date: Thu, 6 Mar 2025 21:30:13 -0800
Subject: [PATCH v4 06/11] perf dso: Add support for reading the e_machine
 type for a dso
In-Reply-To: <Z8pKTE7tOqdqNUdA@google.com>
References: <20250304050305.901167-1-irogers@google.com> <20250304050305.901167-7-irogers@google.com>
 <Z8pKTE7tOqdqNUdA@google.com>
Message-ID: <CAP-5=fXdZZX=wa8EkN-dcpnDjA7J-cQ09BERufAQzoBeoNCT1g@mail.gmail.com>

On Thu, Mar 6, 2025 at 5:22?PM Namhyung Kim <namhyung at kernel.org> wrote:
>
> On Mon, Mar 03, 2025 at 09:03:00PM -0800, Ian Rogers wrote:
> > For ELF file dsos read the e_machine from the ELF header. For kernel
> > types assume the e_machine matches the perf tool. In other cases
> > return EM_NONE.
> >
> > Signed-off-by: Ian Rogers <irogers at google.com>
> > ---
> >  tools/perf/util/dso.c | 54 +++++++++++++++++++++++++++++++++++++++++++
> >  tools/perf/util/dso.h |  1 +
> >  2 files changed, 55 insertions(+)
> >
> > diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> > index 5c6e85fdae0d..7f2f1af4f73b 100644
> > --- a/tools/perf/util/dso.c
> > +++ b/tools/perf/util/dso.c
> > @@ -1170,6 +1170,60 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
> >       return data_read_write_offset(dso, machine, offset, data, size, true);
> >  }
> >
> > +uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
> > +{
> > +     uint16_t e_machine = EM_NONE;
> > +     int fd;
> > +
> > +     switch (dso__binary_type(dso)) {
> > +     case DSO_BINARY_TYPE__KALLSYMS:
> > +     case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> > +     case DSO_BINARY_TYPE__VMLINUX:
> > +     case DSO_BINARY_TYPE__GUEST_VMLINUX:
> > +     case DSO_BINARY_TYPE__GUEST_KMODULE:
> > +     case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
> > +     case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
> > +     case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
> > +     case DSO_BINARY_TYPE__KCORE:
> > +     case DSO_BINARY_TYPE__GUEST_KCORE:
> > +     case DSO_BINARY_TYPE__BPF_PROG_INFO:
> > +     case DSO_BINARY_TYPE__BPF_IMAGE:
> > +     case DSO_BINARY_TYPE__OOL:
> > +     case DSO_BINARY_TYPE__JAVA_JIT:
>
> I think some of them can be possible in recorded data.  But let's go
> simple with EM_HOST as we haven't supported cross-arch trace.

I think you are agreeing with the code, which I think is right :-) I
don't know a way to go from say /proc/kallsyms text file to an
e_machine number and inventing a way is getting beyond the scope of
this series.

> > +             return EM_HOST;
> > +     case DSO_BINARY_TYPE__DEBUGLINK:
> > +     case DSO_BINARY_TYPE__BUILD_ID_CACHE:
> > +     case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> > +     case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
> > +     case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
> > +     case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
> > +     case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
> > +     case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
> > +     case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
> > +             break;
> > +     case DSO_BINARY_TYPE__NOT_FOUND:
> > +     default:
> > +             return EM_NONE;
> > +     }
> > +
> > +     pthread_mutex_lock(&dso__data_open_lock);
>
> Hmm.. I'm afraid it'd slow down perf trace a bit more.  It sees
> occasional LOST events.  But it may be ok as it's cached in thread later.

Agreed, I think the caching will handle this. The lock is pre-existing
and is used to guard use of the dso_data->fd. The lock could be made
reader-writer, it could be placed within the dso_data it could also be
sharded. I've not done any of that here as I believe the processing is
all handled on a single thread anyway.

> > +
> > +     /*
> > +      * dso__data(dso)->fd might be closed if other thread opened another
> > +      * file (dso) due to open file limit (RLIMIT_NOFILE).
> > +      */
> > +     try_to_open_dso(dso, machine);
> > +     fd = dso__data(dso)->fd;
> > +     if (fd >= 0) {
> > +             _Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
> > +             _Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
> > +             if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
>
> I think it needs to check the endianess and swap the data.

Agreed. Will send a fix in v5.

Thanks,
Ian

> Thanks,
> Namhyung
>
>
> > +                     e_machine = EM_NONE;
> > +     }
> > +     pthread_mutex_unlock(&dso__data_open_lock);
> > +     return e_machine;
> > +}
> > +
> >  /**
> >   * dso__data_read_addr - Read data from dso address
> >   * @dso: dso object
> > diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> > index f3ca2a5e7670..ba9b83db061a 100644
> > --- a/tools/perf/util/dso.h
> > +++ b/tools/perf/util/dso.h
> > @@ -818,6 +818,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
> >  off_t dso__data_size(struct dso *dso, struct machine *machine);
> >  ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
> >                             u64 offset, u8 *data, ssize_t size);
> > +uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
> >  ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
> >                           struct machine *machine, u64 addr,
> >                           u8 *data, ssize_t size);
> > --
> > 2.48.1.711.g2feabab25a-goog
> >


From robh at kernel.org  Thu Mar  6 21:42:58 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 06 Mar 2025 23:42:58 -0600
Subject: [PATCH 12/13] dt-bindings: power: mediatek: Add new MT8196
 power domain
In-Reply-To: <20250307034454.12243-13-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
 <20250307034454.12243-13-guangjie.song@mediatek.com>
Message-ID: <174132617868.2934304.16819918690236058573.robh@kernel.org>


On Fri, 07 Mar 2025 11:44:36 +0800, Guangjie Song wrote:
> Add the binding documentation for power domain on MediaTek MT8196.
> 
> Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
> ---
>  .../mediatek,mt8196-power-controller.yaml     | 74 +++++++++++++++++++
>  include/dt-bindings/power/mt8196-power.h      | 57 ++++++++++++++
>  2 files changed, 131 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
>  create mode 100644 include/dt-bindings/power/mt8196-power.h
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.example.dtb: power-controller at 1c004000: compatible: ['mediatek,mt8196-scpsys', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/power/mediatek,mt8196-power-controller.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.example.dtb: power-controller at 1c004000: reg: [[0, 469778432], [0, 4096]] is too long
	from schema $id: http://devicetree.org/schemas/mfd/syscon-common.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250307034454.12243-13-guangjie.song at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From xueqi.zhang at mediatek.com  Thu Mar  6 21:45:08 2025
From: xueqi.zhang at mediatek.com (Xueqi Zhang)
Date: Fri, 7 Mar 2025 13:45:08 +0800
Subject: [PATCH] memory: mtk-smi: Add ostd setting for mt8192
Message-ID: <20250307054515.23455-1-xueqi.zhang@mediatek.com>

Add initial ostd setting for mt8192. All the settings come from DE.
These settings help adjust Multimedia HW's bandwidth limits to achieve
a balanced bandwidth requirement.
Without this, the VENC HW work abnormal while stress testing.

Fixes: 02c02ddce427 ("memory: mtk-smi: Add mt8192 support")
Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 5710348f72f6..a8f5467d6b31 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -332,6 +332,38 @@ static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
 	[25] = {0x01},
 };
 
+static const u8 mtk_smi_larb_mt8192_ostd[][SMI_LARB_PORT_NR_MAX] = {
+	[0] = {0x2, 0x2, 0x28, 0xa, 0xc, 0x28,},
+	[1] = {0x2, 0x2, 0x18, 0x18, 0x18, 0xa, 0xc, 0x28,},
+	[2] = {0x5, 0x5, 0x5, 0x5, 0x1,},
+	[3] = {},
+	[4] = {0x28, 0x19, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1,},
+	[5] = {0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x16,},
+	[6] = {},
+	[7] = {0x1, 0x3, 0x2, 0x1, 0x1, 0x5, 0x2, 0x12, 0x13, 0x4, 0x4, 0x1,
+	       0x4, 0x2, 0x1,},
+	[8] = {},
+	[9] = {0xa, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0x6, 0x7, 0x4,
+	       0xa, 0x3, 0x4, 0xe, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+	       0x1, 0x1, 0x1, 0x1, 0x1,},
+	[10] = {},
+	[11] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x1, 0x1, 0xe, 0x1, 0x7, 0x8, 0x7, 0x7, 0x1, 0x6, 0x2,
+		0xf, 0x8, 0x1, 0x1, 0x1,},
+	[12] = {},
+	[13] = {0x2, 0xc, 0xc, 0xe, 0x6, 0x6, 0x6, 0x6, 0x6, 0x12, 0x6, 0x28,
+		0x2, 0xc, 0xc, 0x28, 0x12, 0x6,},
+	[14] = {},
+	[15] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2,
+		0x4, 0x2, 0x8, 0x4, 0x4,},
+	[16] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2,
+		0x4, 0x2, 0x8, 0x4, 0x4,},
+	[17] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2,
+		0x4, 0x2, 0x8, 0x4, 0x4,},
+	[18] = {0x2, 0x2, 0x4, 0x2,},
+	[19] = {0x9, 0x9, 0x5, 0x5, 0x1, 0x1,},
+};
+
 static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
 	[0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */
 	[1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */
@@ -427,6 +459,7 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
 	.config_port                = mtk_smi_larb_config_port_gen2_general,
+	.ostd			    = mtk_smi_larb_mt8192_ostd,
 };
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = {
-- 
2.46.0



From ziyao at disroot.org  Thu Mar  6 21:52:42 2025
From: ziyao at disroot.org (Yao Zi)
Date: Fri, 7 Mar 2025 05:52:42 +0000
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <20250307033508.656479-1-amadeus@jmu.edu.cn>
References: <20250305194638.47187-1-ziyao@disroot.org>
 <20250307033508.656479-1-amadeus@jmu.edu.cn>
Message-ID: <Z8qJqpUwi7VV8tJk@pie>

On Fri, Mar 07, 2025 at 11:35:08AM +0800, Chukun Pan wrote:
> Hi,
> 
> > +&sdmmc {
> > +	bus-width = <4>;
> > +	cap-mmc-highspeed;
> > +	cap-sd-highspeed;
> > +	disable-wp;
> > +	no-sdio;
> 
> With 'no-sdio' property:
> [  129.608986] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
> [  130.711168] mmc1: Card stuck being busy! __mmc_poll_for_busy
> [  130.725536] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
> [  131.751240] mmc1: Card stuck being busy! __mmc_poll_for_busy
> [  131.765608] mmc_host mmc1: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
> [  132.825083] mmc1: Card stuck being busy! __mmc_poll_for_busy
> [  132.839413] mmc_host mmc1: Bus speed (slot 0) = 187500Hz (slot req 187500Hz, actual 187500HZ div = 0)
> [  133.960141] mmc1: Card stuck being busy! __mmc_poll_for_busy
> 
> Without 'no-sdio' property:
> [  105.224019] mmc1: error -22 whilst initialising SDIO card
> [  106.290838] mmc1: Card stuck being busy! __mmc_poll_for_busy
> [  106.801931] dwmmc_rockchip ffc30000.mmc: Busy; trying anyway
> [  107.385835] mmc_host mmc1: Timeou sending command (cmd 0x202000 arg 0x0 status 0x80202000)
> [  107.400425] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
> [  107.431561] mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 50000000Hz, actual 49800000HZ div = 0)
> [  107.433107] mmc1: new high speed SDIO card at address 0001

So it seems the sdmmc controller actually works with SDIO commands as
well? I don't expect that since the datasheet says RK3528 has only two
SDIO 3.0 controllers.

We could remove the "no-sdio" property if SDIO actually works. Will
apply it in the next version if there's no objection against this.

Further tests about the capabilities of the controller are welcome.

> # cat /sys/kernel/debug/mmc1/ios
> clock:          50000000 Hz
> vdd:            21 (3.3 ~ 3.4 V)
> bus mode:       2 (push-pull)
> chip select:    0 (don't care)
> power mode:     2 (on)
> bus width:      2 (4 bits)
> timing spec:    2 (sd high-speed)
> signal voltage: 0 (3.30 V)
> driver type:    0 (driver type B)
> 
> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Best regards,
Yao Zi


From ziyao at disroot.org  Thu Mar  6 21:54:27 2025
From: ziyao at disroot.org (Yao Zi)
Date: Fri, 7 Mar 2025 05:54:27 +0000
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers
 for RK3528
In-Reply-To: <3d3db030-26e6-4fe1-9158-85f8cebef89c@kwiboo.se>
References: <20250305194612.47171-1-ziyao@disroot.org>
 <20250306140009.384469-1-amadeus@jmu.edu.cn>
 <Z8nPjjbZvpRJ2R5B@pie.lan>
 <3d3db030-26e6-4fe1-9158-85f8cebef89c@kwiboo.se>
Message-ID: <Z8qKEzmTFxhHKApG@pie>

On Fri, Mar 07, 2025 at 12:05:16AM +0100, Jonas Karlman wrote:
> On 2025-03-06 17:43, Yao Zi wrote:
> > On Thu, Mar 06, 2025 at 10:00:09PM +0800, Chukun Pan wrote:
> >> Hi,
> >>
> >>> +		sdio0: mmc at ffc10000 {
> >>> +			compatible = "rockchip,rk3528-dw-mshc",
> >>> +				     "rockchip,rk3288-dw-mshc";
> >>> +			reg = <0x0 0xffc10000 0x0 0x4000>;
> >>> +			clocks = <&cru HCLK_SDIO0>,
> >>> +				 <&cru CCLK_SRC_SDIO0>,
> >>> +				 <&cru SCLK_SDIO0_DRV>,
> >>> +				 <&cru SCLK_SDIO0_SAMPLE>;
> >>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> >>> +			fifo-depth = <0x100>;
> >>> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> >>> +			max-frequency = <150000000>;
> >>> +			pinctrl-names = "default";
> >>> +			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
> >>> +				    <&sdio0_det>, <&sdio0_pwren>;
> >>
> >> The sdio module is usually "non-removable", no need det,
> >> and pwren may be other gpio (use mmc-pwrseq). So it should
> >> be `pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>;`
> > 
> > This doesn't affect the fact that these two pins are assigned as
> > functional pins for SDIO0, as pointed out by the datasheet[1].
> > 
> > But with more digging, I found the reference design[2] of Rockchip
> > actually uses the two pins as normal GPIOs. This is more obvious in
> > downstream devicetree of an EVB[3]. Most of the existing boards (Radxa
> > 2A, ArmSOM Sige 1) follow the reference design.
> > 
> > For me, it's kind of surprising that the SDIO IP functions with two
> > functional pins assigned as different modes. I'm not sure whether we
> > should apply pin configuration for these two pins in the SoC devicetree.
> > Jonas, what do you think about it?
> 
> I think it make sense to match the pins used by reference boards, i.e.
> the pinconf most likely to be used by majority of boards that will use
> the sdio interface.

Thanks, will take it.

> Of my RK3528 boards, only ArmSoM Sige1 use sdio for onboard wifi and
> there I currently have following in my work-in-progress board DT [4]:
> 
>   pinctrl-names = "default";
>   pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>, <&clkm1_32k_out>;
> 
> The Radxa ROCK 2A/2F seem to use USB for wifi/bt.
> 
> [4] https://github.com/Kwiboo/linux-rockchip/blob/next-20250305-rk3528/arch/arm64/boot/dts/rockchip/rk3528-armsom-sige1.dts
> 
> Regards,
> Jonas
> 
> > 
> >>> +			resets = <&cru SRST_H_SDIO0>;
> >>> +			reset-names = "reset";
> >>> +			status = "disabled";
> >>> +		};
> >>> +
> >>> +		sdio1: mmc at ffc20000 {
> >>> +			compatible = "rockchip,rk3528-dw-mshc",
> >>> +				     "rockchip,rk3288-dw-mshc";
> >>> +			reg = <0x0 0xffc20000 0x0 0x4000>;
> >>> +			clocks = <&cru HCLK_SDIO1>,
> >>> +				 <&cru CCLK_SRC_SDIO1>,
> >>> +				 <&cru SCLK_SDIO1_DRV>,
> >>> +				 <&cru SCLK_SDIO1_SAMPLE>;
> >>> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> >>> +			fifo-depth = <0x100>;
> >>> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> >>> +			max-frequency = <150000000>;
> >>> +			pinctrl-names = "default";
> >>> +			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
> >>> +				    <&sdio1_det>, <&sdio1_pwren>;
> >>
> >> Same here.
> >>
> >>> +			resets = <&cru SRST_H_SDIO1>;
> >>> +			reset-names = "reset";
> >>> +			status = "disabled";
> >>> +		};
> >>
> >> Thanks,
> >> Chukun
> >>
> >> -- 
> >> 2.25.1
> >>
> > 
> > Best regards,
> > Yao Zi
> > 
> > [1]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/Rockchip%C2%A0RK3528%C2%A0Datasheet%C2%A0V1.0-20230522.pdf
> > [2]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/RK3528_BOX_REF_V10_20230525.pdf
> > [3]: https://github.com/rockchip-linux/kernel/blob/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi#L128
> 

Best regards,
Yao Zi


From victor.liu at nxp.com  Thu Mar  6 22:33:37 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Fri, 7 Mar 2025 14:33:37 +0800
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
Message-ID: <f8df2b5e-b005-4ada-8108-159b2b94a72e@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> This warning notifies a clock was set to an inaccurate value. Modify the
> string to also show the clock name.
> 
> While doing that also rewrap the entire function call.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
> index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
> @@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
>  
>  	configured_link_freq = clk_get_rate(fsl_ldb->clk);
>  	if (configured_link_freq != requested_link_freq)
> -		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> -			 configured_link_freq,
> -			 requested_link_freq);
> +		dev_warn(fsl_ldb->dev,
> +			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> +			 fsl_ldb->clk, configured_link_freq, requested_link_freq);

Though this slightly changes the warning message userspace sees, I guess it is
acceptable.

Does it make sense to s/%pC/%pCn/ so that the clock name is printed in lower
case instead of upper case, since it seems that all i.MX specific clock names
are in lower case?

>  
>  	clk_prepare_enable(fsl_ldb->clk);
>  
> 

-- 
Regards,
Liu Ying


From victor.liu at nxp.com  Thu Mar  6 22:35:03 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Fri, 7 Mar 2025 14:35:03 +0800
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <Z8nizEsd0QbYgsI/@lizhi-Precision-Tower-5810>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
 <Z8nizEsd0QbYgsI/@lizhi-Precision-Tower-5810>
Message-ID: <5cf48c2a-40b2-470f-aadb-0710acd37084@nxp.com>

On 03/07/2025, Frank Li wrote:
> On Thu, Mar 06, 2025 at 06:28:41PM +0100, Luca Ceresoli wrote:
>> This warning notifies a clock was set to an inaccurate value. Modify the
>> string to also show the clock name.
>>
>> While doing that also rewrap the entire function call.
>>
>> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
>> ---
>>  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
>> index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
>> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
>> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
>> @@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
>>
>>  	configured_link_freq = clk_get_rate(fsl_ldb->clk);
>>  	if (configured_link_freq != requested_link_freq)
>> -		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
>> -			 configured_link_freq,
>> -			 requested_link_freq);
>> +		dev_warn(fsl_ldb->dev,
>> +			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
>> +			 fsl_ldb->clk, configured_link_freq, requested_link_freq);
> 
> commit message said show clock name, but %p is for pointer value. Are sure
> it show clock name?

%pC prints clock name.  Please see Documentation/core-api/printk-formats.rst.

> 
> Frank
> 
>>
>>  	clk_prepare_enable(fsl_ldb->clk);
>>
>>
>> --
>> 2.48.1
>>

-- 
Regards,
Liu Ying


From Friday.Yang at mediatek.com  Thu Mar  6 22:38:02 2025
From: Friday.Yang at mediatek.com (=?utf-8?B?RnJpZGF5IFlhbmcgKOadqOmYsyk=?=)
Date: Fri, 7 Mar 2025 06:38:02 +0000
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
	 <20250221074846.14105-2-friday.yang@mediatek.com>
	 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
	 <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
	 <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>
Message-ID: <9305a4fd6829e5e2ae6c3247d11b9f47ed277f8b.camel@mediatek.com>

On Thu, 2025-03-06 at 13:48 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 06/03/2025 13:45, Friday Yang (??) wrote:
> > > > +          const: mediatek,mt8188-smi-larb
> > > > +        mediatek,larb-id:
> > > > +          oneOf:
> > > 
> > > Are you really sure that you need 'oneOf' here? :-)
> > > 
> > > Regards,
> > > Angelo
> > 
> > Yes, I have tested it. If I try to modify the 'examples'
> > like this. That is:
> >   change the compatible to "mediatek,mt8188-smi-larb",
> >   add 'mediatek,larb-id = <10>;'
> > 
> > examples:
> >   - |+
> >     #include <dt-bindings/clock/mt8173-clk.h>
> >     #includ
> > e <dt-bindings/power/mt8173-power.h>
> > 
> >     larb1: larb at 16010000 {
> >       compatible = "mediatek,mt8188-smi-larb";
> >       reg = <0x16010000 0x1000>;
> >       mediatek,smi = <&smi_common>;
> >       mediatek,larb-id = <10>;
> >       power-domains = <&scpsys MT8188_POWER_DOMAIN_VDEC>;
> >       clocks = <&vdecsys CLK_VDEC_CKEN>,
> >                <&vdecsys CLK_VDEC_LARB_CKEN>;
> >       clock-names = "apb", "smi";
> >     };
> > 
> > The 'dt_binding_check' could give the following
> > errors:
> > 
> > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
> > larb.example.dtb: larb at 16010000: 'resets' is a required property
> > from schema $id:
> > 
https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
> > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
> > larb.example.dtb: larb at 16010000: 'reset-names' is a required
> > property
> > from schema $id:
> > 
https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
> > 
> > And this is what I want to achieve. On the MediaTek MT8188 SoC
> > platform, 'resets' and 'reset-names' are only required for SMI
> > LARBs
> > located in image, camera and ipe subsys. Others can be ignored. And
> > the
> > 'larb-id' of these SMI LARBs are shown in this array: [ 9, 10, 11,
> > 12,
> > 13, 16, 17, 18, 19, 20 ].
> > 
> > Please feel free to let me know if you have any doubts.
> 
> You did not really answer the question. Where is anything about oneOf
> in
> your reply?
> 
> I am dropping this patchset from my queue.
> 

In this SoC, we encountered power-off failures and SMI bus hang issues
during camera stress tests. SMI LARBs located in the image, IPE, and
camera subsystems need to implement a reset, while other LARBs do not
require it.

The 'mediatek,larb-id' for SMI LARBs in the image, IPE, and camera
subsystems are as follows:
- image subsystem: 9, 10, 11, 12, 16
- IPE subsystem: 13
- camera subsystem: 17, 18, 19, 20

Therefore, we believe that 'mediatek,larb-id' should be 'oneOf' the
values in the array. Could this answer the question, or is there
another property I should use in this situation?

> Best regards,
> Krzysztof

From victor.liu at nxp.com  Thu Mar  6 22:42:12 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Fri, 7 Mar 2025 14:42:12 +0800
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
Message-ID: <71c44221-b18b-4928-8faf-00893ec4a109@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
> ret;'. So return 0 for clarity.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
> --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> @@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
>  
>  	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
>  
> -	return ret;
> +	return 0;

I guess this is not the only place across the kernel tree where this cleanup
could be done.  So, maybe use some tools to cleanup them all?

>  }
>  
>  static void imx8qxp_ldb_remove(struct platform_device *pdev)
> 

-- 
Regards,
Liu Ying


From jonas at kwiboo.se  Thu Mar  6 22:45:00 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 07:45:00 +0100
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <Z8qJqpUwi7VV8tJk@pie>
References: <20250305194638.47187-1-ziyao@disroot.org>
 <20250307033508.656479-1-amadeus@jmu.edu.cn> <Z8qJqpUwi7VV8tJk@pie>
Message-ID: <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>

Hi Chukun,

On 2025-03-07 06:52, Yao Zi wrote:
> On Fri, Mar 07, 2025 at 11:35:08AM +0800, Chukun Pan wrote:
>> Hi,
>>
>>> +&sdmmc {
>>> +	bus-width = <4>;
>>> +	cap-mmc-highspeed;
>>> +	cap-sd-highspeed;
>>> +	disable-wp;
>>> +	no-sdio;
>>
>> With 'no-sdio' property:
>> [  129.608986] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
>> [  130.711168] mmc1: Card stuck being busy! __mmc_poll_for_busy
>> [  130.725536] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
>> [  131.751240] mmc1: Card stuck being busy! __mmc_poll_for_busy
>> [  131.765608] mmc_host mmc1: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
>> [  132.825083] mmc1: Card stuck being busy! __mmc_poll_for_busy
>> [  132.839413] mmc_host mmc1: Bus speed (slot 0) = 187500Hz (slot req 187500Hz, actual 187500HZ div = 0)
>> [  133.960141] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>
>> Without 'no-sdio' property:
>> [  105.224019] mmc1: error -22 whilst initialising SDIO card
>> [  106.290838] mmc1: Card stuck being busy! __mmc_poll_for_busy
>> [  106.801931] dwmmc_rockchip ffc30000.mmc: Busy; trying anyway
>> [  107.385835] mmc_host mmc1: Timeou sending command (cmd 0x202000 arg 0x0 status 0x80202000)
>> [  107.400425] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
>> [  107.431561] mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 50000000Hz, actual 49800000HZ div = 0)
>> [  107.433107] mmc1: new high speed SDIO card at address 0001
> 
> So it seems the sdmmc controller actually works with SDIO commands as
> well? I don't expect that since the datasheet says RK3528 has only two
> SDIO 3.0 controllers.
> 
> We could remove the "no-sdio" property if SDIO actually works. Will
> apply it in the next version if there's no objection against this.

On the E20C the sdmmc controller is routed to a microSD card slot mainly
intended for use with microSD-cards and should normally not need SDIO.

What card/adapter do you have inserted in the microSD card slot that
requires use of SDIO instead of just SD or MMC? What is the use case you
have that requires removal of no-sdio on E20C?

Regards,
Jonas

> 
> Further tests about the capabilities of the controller are welcome.
> 
>> # cat /sys/kernel/debug/mmc1/ios
>> clock:          50000000 Hz
>> vdd:            21 (3.3 ~ 3.4 V)
>> bus mode:       2 (push-pull)
>> chip select:    0 (don't care)
>> power mode:     2 (on)
>> bus width:      2 (4 bits)
>> timing spec:    2 (sd high-speed)
>> signal voltage: 0 (3.30 V)
>> driver type:    0 (driver type B)
>>
>> Thanks,
>> Chukun
>>
>> -- 
>> 2.25.1
>>
> 
> Best regards,
> Yao Zi



From amadeus at jmu.edu.cn  Thu Mar  6 22:50:15 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 14:50:15 +0800
Subject: [PATCH v2 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <281b8025-8288-4274-b863-f091c05cbabe@kwiboo.se>
References: <281b8025-8288-4274-b863-f091c05cbabe@kwiboo.se>
Message-ID: <20250307065015.697377-1-amadeus@jmu.edu.cn>

Hi,

> This is new compared to v1, please add operating-points instead.
> cpu_pvtpll is already initialized to 1.2 GHz by firmware, see e.g. [1].
> 
> [1] https://lore.kernel.org/u-boot/20250123224844.3104592-5-jonas at kwiboo.se/

Thanks for this information, I will remove assigned-clocks.
However, due to unknown reasons, the cpu opp-table does not
match the actual frequency at all.
e.g. set 2016MHz, actual 1610MHz

Thanks,
Chukun

-- 
2.25.1



From Axe.Yang at mediatek.com  Thu Mar  6 22:59:03 2025
From: Axe.Yang at mediatek.com (=?utf-8?B?QXhlIFlhbmcgKOadqOejiik=?=)
Date: Fri, 7 Mar 2025 06:59:03 +0000
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
	 <20250306085028.5024-2-axe.yang@mediatek.com>
	 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
Message-ID: <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>

On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
> > Add 'mediatek,disable-single-burst' setting. This property can be
> > used to switch bus burst type, from single burst to INCR, which is
> > determined by the bus type within the IP. Some versions of the IP
> > are using AXI bus, thus this switch is necessary as 'single' is not
> > the burst type supported by the bus.
> > 
> > Signed-off-by: Axe Yang <axe.yang at mediatek.com>
> 
> I am mostly sure that this is not something to put in devicetree, but
> as
> platform data for specific SoC(s), as much as I'm mostly sure that
> all of
> the instances of the MSDC IP in one SoC will be *all* using either
> single
> or INCR.

No, actually MSDC IPs in one SoC are using different versions.
Usually MSDC1 (index from 1) is used as eMMC host, the left hosts are
used as SD/SDIO hosts. They have similar designs, but there are still
difference.

> 
> So, I think I know the answer but I'll still ask just to be extremely
> sure:
> 
> is there any MediaTek SoC that has different IP versions for
> different MSDC
> instances, and that hence require single burst on one instance and
> INCR on
> another instance?

Yes. Actually every SoC has different IP versions for eMMC and SD/SDIO
host as I said.
e.g. For MT8168, signel burst bit should be set to 1 for eMMC Host, but
0 for SD/SDIO Host.

> 
> And if there is - is there a pattern? Is it always SDIO requiring
> INCR or
> always eMMC/SD requiring it?
> 
> 

No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
configured base on IP version. There is no binding relationship between
eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
single, same as SD/SDIO.


Regards,
Axe


> 
> > ---
> >   Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8 ++++++++
> >   1 file changed, 8 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > index 0debccbd6519..6076aff0a689 100644
> > --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > @@ -100,6 +100,14 @@ properties:
> >       minimum: 0
> >       maximum: 0xffffffff
> > 
> > +  mediatek,disable-single-burst:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description:
> > +      Burst type setting. For some versions of the IP that do not
> > use
> > +      AHB bus, the burst type need to be switched to INCR.
> > +      If present, use INCR burst type.
> > +      If not present, use single burst type.
> > +
> >     mediatek,hs200-cmd-int-delay:
> >       $ref: /schemas/types.yaml#/definitions/uint32
> >       description:
> 
> 
> 

From krzk at kernel.org  Thu Mar  6 23:04:49 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:04:49 +0100
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <9305a4fd6829e5e2ae6c3247d11b9f47ed277f8b.camel@mediatek.com>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
 <20250221074846.14105-2-friday.yang@mediatek.com>
 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
 <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
 <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>
 <9305a4fd6829e5e2ae6c3247d11b9f47ed277f8b.camel@mediatek.com>
Message-ID: <8d90731b-4b5a-45a8-83d1-4351044f59c7@kernel.org>

On 07/03/2025 07:38, Friday Yang (??) wrote:
> On Thu, 2025-03-06 at 13:48 +0100, Krzysztof Kozlowski wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> On 06/03/2025 13:45, Friday Yang (??) wrote:
>>>>> +          const: mediatek,mt8188-smi-larb
>>>>> +        mediatek,larb-id:
>>>>> +          oneOf:
>>>>
>>>> Are you really sure that you need 'oneOf' here? :-)
>>>>
>>>> Regards,
>>>> Angelo
>>>
>>> Yes, I have tested it. If I try to modify the 'examples'
>>> like this. That is:
>>>   change the compatible to "mediatek,mt8188-smi-larb",
>>>   add 'mediatek,larb-id = <10>;'
>>>
>>> examples:
>>>   - |+
>>>     #include <dt-bindings/clock/mt8173-clk.h>
>>>     #includ
>>> e <dt-bindings/power/mt8173-power.h>
>>>
>>>     larb1: larb at 16010000 {
>>>       compatible = "mediatek,mt8188-smi-larb";
>>>       reg = <0x16010000 0x1000>;
>>>       mediatek,smi = <&smi_common>;
>>>       mediatek,larb-id = <10>;
>>>       power-domains = <&scpsys MT8188_POWER_DOMAIN_VDEC>;
>>>       clocks = <&vdecsys CLK_VDEC_CKEN>,
>>>                <&vdecsys CLK_VDEC_LARB_CKEN>;
>>>       clock-names = "apb", "smi";
>>>     };
>>>
>>> The 'dt_binding_check' could give the following
>>> errors:
>>>
>>> Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
>>> larb.example.dtb: larb at 16010000: 'resets' is a required property
>>> from schema $id:
>>>
> https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
>>> Documentation/devicetree/bindings/memory-controllers/mediatek,smi-
>>> larb.example.dtb: larb at 16010000: 'reset-names' is a required
>>> property
>>> from schema $id:
>>>
> https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
>>>
>>> And this is what I want to achieve. On the MediaTek MT8188 SoC
>>> platform, 'resets' and 'reset-names' are only required for SMI
>>> LARBs
>>> located in image, camera and ipe subsys. Others can be ignored. And
>>> the
>>> 'larb-id' of these SMI LARBs are shown in this array: [ 9, 10, 11,
>>> 12,
>>> 13, 16, 17, 18, 19, 20 ].
>>>
>>> Please feel free to let me know if you have any doubts.
>>
>> You did not really answer the question. Where is anything about oneOf
>> in
>> your reply?
>>
>> I am dropping this patchset from my queue.
>>
> 
> In this SoC, we encountered power-off failures and SMI bus hang issues
> during camera stress tests. SMI LARBs located in the image, IPE, and
> camera subsystems need to implement a reset, while other LARBs do not
> require it.
> 
> The 'mediatek,larb-id' for SMI LARBs in the image, IPE, and camera
> subsystems are as follows:
> - image subsystem: 9, 10, 11, 12, 16
> - IPE subsystem: 13
> - camera subsystem: 17, 18, 19, 20
> 
> Therefore, we believe that 'mediatek,larb-id' should be 'oneOf' the


So explain me where is the second condition?

Best regards,
Krzysztof


From amadeus at jmu.edu.cn  Thu Mar  6 23:10:20 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 15:10:20 +0800
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>
References: <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>
Message-ID: <20250307071020.756277-1-amadeus@jmu.edu.cn>

Hi,

> On the E20C the sdmmc controller is routed to a microSD card slot mainly
> intended for use with microSD-cards and should normally not need SDIO.
> 
> What card/adapter do you have inserted in the microSD card slot that
> requires use of SDIO instead of just SD or MMC? What is the use case you
> have that requires removal of no-sdio on E20C?

I inserted an sdio wifi module (via sdcard adapter) for testing.
Just out of curiosity :)

Thanks,
Chukun

-- 
2.25.1



From krzk at kernel.org  Thu Mar  6 23:11:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:11:26 +0100
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <2fa6037d-b5e9-45b2-a5d5-dbc92fb3434b@notapiano>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
 <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>
 <2fa6037d-b5e9-45b2-a5d5-dbc92fb3434b@notapiano>
Message-ID: <0663e03e-e331-4a06-be95-ce8d9059ed6b@kernel.org>

On 06/03/2025 13:19, N?colas F. R. A. Prado wrote:
>>>    It is interfaced to host controller using SPI interface by a proprietary hardware
>>>    called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
>>> @@ -224,6 +225,30 @@ properties:
>>>      description:
>>>        Pin controller
>>>  
>>> +  accdet:
>>> +    type: object
>>> +    additionalProperties: false
>>> +    description:
>>> +      The Accessory Detection module found on the PMIC allows detecting audio
>>> +      jack insertion and removal, as well as identifying the type of events
>>> +      connected to the jack.
>>> +
>>> +    properties:
>>> +      compatible:
>>> +        const: mediatek,mt6359-accdet
>>
>> You just removed the other file, no folding happened here. Drop the
>> accdet node and fold this into parent.
> 
> Sorry, I'm still not sure what you mean by folding here then. Right now the
> accdet is a subnode of the PMIC. If you want me to remove the accdet node, where

Yes

> would its compatible and property go?

compatible: nowhere, because it is close to redundancy.

property: to the parent pmic node.

    pmic {
        compatible = "mediatek,mt6359";
        interrupt-controller;
        #interrupt-cells = <2>;

        mediatek,hp-eint-high;
    };


Best regards,
Krzysztof


From oliver.upton at linux.dev  Thu Mar  6 23:20:00 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Thu, 6 Mar 2025 23:20:00 -0800
Subject: [PATCH v2 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <20250304134347.369854-2-vdonnefort@google.com>
References: <20250304134347.369854-1-vdonnefort@google.com>
 <20250304134347.369854-2-vdonnefort@google.com>
Message-ID: <Z8qeIPfTOJU6w_8l@linux.dev>

Hi Vincent,

On Tue, Mar 04, 2025 at 01:43:44PM +0000, Vincent Donnefort wrote:
> Add flags to kvm_hyp_memcache and propagate them up to the allocation
> and free callbacks. This will later allow to account for memory, based
> on the memcache configuration.

It seems slightly more obvious to me if we pass a pointer to the
memcache instead, but that's just a minor nit.

Unless you have a preference on this, I can change it when I apply the
patch.

Thanks,
Oliver


From ziyao at disroot.org  Thu Mar  6 23:26:23 2025
From: ziyao at disroot.org (Yao Zi)
Date: Fri, 7 Mar 2025 07:26:23 +0000
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <20250307071020.756277-1-amadeus@jmu.edu.cn>
References: <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>
 <20250307071020.756277-1-amadeus@jmu.edu.cn>
Message-ID: <Z8qfn-OTgopD8YMO@pie>

On Fri, Mar 07, 2025 at 03:10:20PM +0800, Chukun Pan wrote:
> Hi,
> 
> > On the E20C the sdmmc controller is routed to a microSD card slot mainly
> > intended for use with microSD-cards and should normally not need SDIO.
> > 
> > What card/adapter do you have inserted in the microSD card slot that
> > requires use of SDIO instead of just SD or MMC? What is the use case you
> > have that requires removal of no-sdio on E20C?
> 
> I inserted an sdio wifi module (via sdcard adapter) for testing.
> Just out of curiosity :)

I doubt whether the module actually works, they usually require more
pins than a simple SDIO bus to function. Additionally, it really doesn't
sound like a real use case for me.

Have you tried transferring some data? The log you showed only indicates
the controller doesn't bail out or freeze when encountering SDIO command
sequences during initialization, but cannot prove the controller is
really in a good state and could transfer as normal.

Again, connecting SDIO WiFi modules to a SDcard slot doesn't seem an
usual case for me. I'll change my mind to keep SDIO sequence disabled if
you didn't get the module really working but only observed the
initialization didn't fail,

> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Best regards,
Yao Zi


From krzk at kernel.org  Thu Mar  6 23:29:01 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:29:01 +0100
Subject: [PATCH 06/26] dt-bindings: clock: mediatek: Add new MT8196 clock
In-Reply-To: <20250307032942.10447-7-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
 <20250307032942.10447-7-guangjie.song@mediatek.com>
Message-ID: <20250307-mindful-raspberry-cow-c112ce@krzk-bin>

On Fri, Mar 07, 2025 at 11:27:02AM +0800, Guangjie Song wrote:
> Add the new binding documentation for system clock and functional clock
> on Mediatek MT8196.
> 
> Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
> ---
>  .../bindings/clock/mediatek,mt8196-clock.yaml |   66 +
>  .../clock/mediatek,mt8196-sys-clock.yaml      |   63 +
>  include/dt-bindings/clock/mt8196-clk.h        | 1503 +++++++++++++++++

Filename matching binding, so mediatek,mt8196-clock.h

I would not even dream about people testing patches before sending
them...

Best regards,
Krzysztof



From krzk at kernel.org  Thu Mar  6 23:29:49 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:29:49 +0100
Subject: [PATCH 21/26] clk: mediatek: Add MT8196 ovl0 clock support
In-Reply-To: <20250307032942.10447-22-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
 <20250307032942.10447-22-guangjie.song@mediatek.com>
Message-ID: <20250307-godlike-quizzical-mayfly-dec36e@krzk-bin>

On Fri, Mar 07, 2025 at 11:27:17AM +0800, Guangjie Song wrote:
> +
> +static struct platform_driver clk_mt8196_ovl0_drv = {
> +	.probe = mtk_clk_pdev_probe,
> +	.remove = mtk_clk_pdev_remove,
> +	.driver = {
> +		.name = "clk-mt8196-ovl0",
> +	},
> +	.id_table = clk_mt8196_ovl0_id_table,
> +};
> +
> +module_platform_driver(clk_mt8196_ovl0_drv);
> +MODULE_LICENSE("GPL");

You have warnings here about missing description. Build your code with
W=1.

Best regards,
Krzysztof



From ardb at kernel.org  Thu Mar  6 23:38:28 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Fri, 7 Mar 2025 08:38:28 +0100
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <20250307050851.4034393-1-anshuman.khandual@arm.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
Message-ID: <CAMj1kXFufE9UPGMsqv1ARWm6SyUCcJL+m4F4mWa0jCyhJqf2Jg@mail.gmail.com>

Hi Anshuman,

On Fri, 7 Mar 2025 at 06:09, Anshuman Khandual
<anshuman.khandual at arm.com> wrote:
>
> Address bytes shifted with a single 64 bit page table entry (any page table
> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
> is not very readable or easy to reason about. Besides it is going to change
> with D128, where each 128 bit page table entry will shift address bytes by
> 4 (aka 2^4 = 16) instead.
>
> Let's just formalise this address bytes shift value into a new macro called
> PTE_SHIFT establishing a logical abstraction, thus improving readability as
> well. This does not cause any functional change.
>

I don't disagree with this goal, but PTE_SHIFT is really not the right
name. Given that PMD_SHIFT is the log2 of the area covered by a PMD,
PTE_SHIFT should be the log2 of the area covered by a PTE, and so
defining it to anything other than PAGE_SHIFT would be a mistake IMO.

Given that we are talking about the log2 of the size of the area
occupied by a descriptor, perhaps {PT}DESC_SIZE_ORDER would be a
better name?




> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
> Cc: Alexander Potapenko <glider at google.com>
> Cc: Andrey Konovalov <andreyknvl at gmail.com>
> Cc: Dmitry Vyukov <dvyukov at google.com>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Cc: kasan-dev at googlegroups.com
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
> This patch applies on v6.14-rc5
>
>  arch/arm64/Kconfig                      |  2 +-
>  arch/arm64/include/asm/kernel-pgtable.h |  3 ++-
>  arch/arm64/include/asm/pgtable-hwdef.h  | 26 +++++++++++++------------
>  arch/arm64/kernel/pi/map_range.c        |  2 +-
>  arch/arm64/mm/kasan_init.c              |  6 +++---
>  5 files changed, 21 insertions(+), 18 deletions(-)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..fd3303f2ccda 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
>         default 18
>
>  # max bits determined by the following formula:
> -#  VA_BITS - PAGE_SHIFT - 3
> +#  VA_BITS - PAGE_SHIFT - PTE_SHIFT
>  config ARCH_MMAP_RND_BITS_MAX
>         default 19 if ARM64_VA_BITS=36
>         default 24 if ARM64_VA_BITS=39
> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
> index fd5a08450b12..7150a7a10f00 100644
> --- a/arch/arm64/include/asm/kernel-pgtable.h
> +++ b/arch/arm64/include/asm/kernel-pgtable.h
> @@ -49,7 +49,8 @@
>         (SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
>
>  #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)      \
> -       (lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
> +       (lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
> +       lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)
>
>  #define EARLY_PAGES(lvls, vstart, vend, add) (1        /* PGDIR page */                                \
>         + EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */  \
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index a9136cc551cc..43f98eac7653 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -7,40 +7,42 @@
>
>  #include <asm/memory.h>
>
> +#define PTE_SHIFT 3
> +
>  /*
>   * Number of page-table levels required to address 'va_bits' wide
>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
> + * bits with (PAGE_SHIFT - PTE_SHIFT) bits at each page table level. Hence:
>   *
> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTE_SHIFT))
>   *
>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>   *
>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>   * due to build issues. So we open code DIV_ROUND_UP here:
>   *
> - *     ((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
> + *     ((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTE_SHIFT) - 1) / (PAGE_SHIFT - PTE_SHIFT))
>   *
>   * which gets simplified as :
>   */
> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - PTE_SHIFT - 1) / (PAGE_SHIFT - PTE_SHIFT))
>
>  /*
>   * Size mapped by an entry at level n ( -1 <= n <= 3)
> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
> + * We map (PAGE_SHIFT - PTE_SHIFT) at all translation levels and PAGE_SHIFT bits
>   * in the final page. The maximum number of translation levels supported by
>   * the architecture is 5. Hence, starting at level n, we have further
>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>   * So, the total number of bits mapped by an entry at level n is :
>   *
> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTE_SHIFT) + PAGE_SHIFT
>   *
>   * Rearranging it a bit we get :
> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
> + *   (4 - n) * (PAGE_SHIFT - PTE_SHIFT) + PTE_SHIFT
>   */
> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)        ((PAGE_SHIFT - 3) * (4 - (n)) + 3)
> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)        ((PAGE_SHIFT - PTE_SHIFT) * (4 - (n)) + PTE_SHIFT)
>
> -#define PTRS_PER_PTE           (1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PTE           (1 << (PAGE_SHIFT - PTE_SHIFT))
>
>  /*
>   * PMD_SHIFT determines the size a level 2 page table entry can map.
> @@ -49,7 +51,7 @@
>  #define PMD_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>  #define PMD_SIZE               (_AC(1, UL) << PMD_SHIFT)
>  #define PMD_MASK               (~(PMD_SIZE-1))
> -#define PTRS_PER_PMD           (1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PMD           (1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>
>  /*
> @@ -59,14 +61,14 @@
>  #define PUD_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>  #define PUD_SIZE               (_AC(1, UL) << PUD_SHIFT)
>  #define PUD_MASK               (~(PUD_SIZE-1))
> -#define PTRS_PER_PUD           (1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PUD           (1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>
>  #if CONFIG_PGTABLE_LEVELS > 4
>  #define P4D_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>  #define P4D_SIZE               (_AC(1, UL) << P4D_SHIFT)
>  #define P4D_MASK               (~(P4D_SIZE-1))
> -#define PTRS_PER_P4D           (1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_P4D           (1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>
>  /*
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..3530a5427f57 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  {
>         u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>         pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
> -       int lshift = (3 - level) * (PAGE_SHIFT - 3);
> +       int lshift = (3 - level) * (PAGE_SHIFT - PTE_SHIFT);
>         u64 lmask = (PAGE_SIZE << lshift) - 1;
>
>         start   &= PAGE_MASK;
> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> index b65a29440a0c..90548079b42e 100644
> --- a/arch/arm64/mm/kasan_init.c
> +++ b/arch/arm64/mm/kasan_init.c
> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>   */
>  static bool __init root_level_aligned(u64 addr)
>  {
> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>
>         return (addr % (PAGE_SIZE << shift)) == 0;
>  }
> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>          */
>         u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>                                                         : vabits_actual;
> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>
>         return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>  }
> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>   */
>  static int __init next_level_idx(u64 addr)
>  {
> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTE_SHIFT);
>
>         return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>  }
> --
> 2.30.2
>


From krzk at kernel.org  Thu Mar  6 23:41:28 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:41:28 +0100
Subject: [PATCH 12/13] dt-bindings: power: mediatek: Add new MT8196 power
 domain
In-Reply-To: <20250307034454.12243-13-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
 <20250307034454.12243-13-guangjie.song@mediatek.com>
Message-ID: <20250307-groovy-opalescent-spoonbill-cb569e@krzk-bin>

On Fri, Mar 07, 2025 at 11:44:36AM +0800, Guangjie Song wrote:
> Add the binding documentation for power domain on MediaTek MT8196.
> 
> Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
> ---
>  .../mediatek,mt8196-power-controller.yaml     | 74 +++++++++++++++++++
>  include/dt-bindings/power/mt8196-power.h      | 57 ++++++++++++++


You keep sending multiple patchsets and none of them are tested.


>  2 files changed, 131 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
>  create mode 100644 include/dt-bindings/power/mt8196-power.h

Comments from other patches apply.

> 
> diff --git a/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
> new file mode 100644
> index 000000000000..6c2867b25967
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
> @@ -0,0 +1,74 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/power/mediatek,mt8196-power-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Mediatek MT8196 Power Domains Controller
> +
> +maintainers:
> +  - Guangjie Song <guangjie.song at mediatek.com>
> +
> +description: |
> +  Mediatek processors include support for multiple power domains which can be
> +  powered up/down by software based on different application scenes to save power.
> +
> +properties:
> +  $nodename:
> +    pattern: '^power-controller(@[0-9a-f]+)?$'


How unit address can be optional?

> +
> +  compatible:
> +    enum:
> +      - mediatek,mt8196-scpsys
> +      - mediatek,mt8196-hfrpsys
> +
> +  '#power-domain-cells':
> +    const: 1
> +
> +  reg:
> +    description: Address range of the power controller.

No, look how other bindings do it.

> +
> +  clocks:
> +    description: |

Look at other bindings.

> +      A number of phandles to clocks that need to be enabled during domain
> +      power-up sequencing.

Look at other bindings.

> +
> +  clock-names:
> +    description: |
> +      List of names of clock.
> +
> +  domain-supply:
> +    description: domain regulator supply.
> +
> +  spm:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle to the device containing the spm register range.
> +
> +  mmpc:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle to the device containing the mmpc register range.
> +
> +  vote-regmap:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle to the device containing the vote register range.
> +
> +  mm-vote-regmap:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle to the device containing the mm-vote register range.

None of these are correct.

> +
> +required:
> +  - compatible

That's just incomplete.

This binding is really incomplete and with multiple issues. Considering
this was never tested, please first consult some internal folks to do
proper internal review.

> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/power/mt8196-power.h>
> +
> +    scpsys: power-controller at 1c004000 {
> +      compatible = "mediatek,mt8196-scpsys", "syscon";
> +      reg = <0 0x1c004000 0 0x1000>;
> +      #power-domain-cells = <1>;
> +      spm = <&scpsys_bus>;
> +      vote-regmap = <&vote>;
> +    };
> diff --git a/include/dt-bindings/power/mt8196-power.h b/include/dt-bindings/power/mt8196-power.h
> new file mode 100644
> index 000000000000..b0db89cc435d
> --- /dev/null
> +++ b/include/dt-bindings/power/mt8196-power.h
> @@ -0,0 +1,57 @@
> +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.

We have 2025.

Best regards,
Krzysztof



From krzk at kernel.org  Thu Mar  6 23:51:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:51:54 +0100
Subject: [PATCH v5 03/11] media: dt-bindings: media: add bindings for
 rockchip rk3568 vicap
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-3-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
 <20250306-v6-8-topic-rk3568-vicap-v5-3-f02152534f3c@wolfvision.net>
Message-ID: <20250307-pink-dalmatian-of-kindness-f87ad2@krzk-bin>

On Thu, Mar 06, 2025 at 05:56:04PM +0100, Michael Riesch wrote:
> Add documentation for the Rockchip RK3568 Video Capture (VICAP) unit.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>

subject: only one media prefix, the first

A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18

> ---
>  .../bindings/media/rockchip,rk3568-vicap.yaml      | 169 +++++++++++++++++++++
>  MAINTAINERS                                        |   1 +
>  2 files changed, 170 insertions(+)
> 

...

> +  clocks:
> +    items:
> +      - description: ACLK
> +      - description: HCLK
> +      - description: DCLK
> +      - description: ICLK
> +
> +  clock-names:
> +    items:
> +      - const: aclk
> +      - const: hclk
> +      - const: dclk
> +      - const: iclk
> +
> +  rockchip,cif-clk-delaynum:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 127
> +    description:
> +      Delay the DVP path clock input to align the sampling phase, only valid
> +      in dual edge sampling mode. Delay is zero by default and can be adjusted
> +      optionally.

default: 0

> +
> +  iommus:
> +    maxItems: 1
> +
> +  resets:
> +    items:
> +      - description: ARST
> +      - description: HRST
> +      - description: DRST
> +      - description: PRST
> +      - description: IRST
> +
> +  reset-names:
> +    items:
> +      - const: arst
> +      - const: hrst
> +      - const: drst
> +      - const: prst
> +      - const: irst
> +
> +  rockchip,grf:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Phandle to general register file used for video input block control.
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port at 0:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description: The digital video port (DVP, a parallel video interface).
> +
> +        properties:
> +          endpoint:
> +            $ref: video-interfaces.yaml#
> +            unevaluatedProperties: false
> +
> +            properties:
> +              bus-type:
> +                enum: [5, 6]
> +
> +            required:
> +              - bus-type
> +
> +      port at 1:
> +        $ref: /schemas/graph.yaml#/properties/port
> +        description: Internal port connected to a MIPI CSI-2 host.
> +
> +        properties:
> +          endpoint:
> +            $ref: video-interfaces.yaml#
> +            unevaluatedProperties: false

Hm, does it actually work? graph/port does not allow any other
properties. You should use graph/port-base and probably still narrow
lanes for both of port at 0 and port at 1.


> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - ports
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/rk3568-cru.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/power/rk3568-power.h>
> +    #include <dt-bindings/media/video-interfaces.h>
> +
> +    parent {

soc {

> +        #address-cells = <2>;
> +        #size-cells = <2>;

Best regards,
Krzysztof



From krzk at kernel.org  Thu Mar  6 23:53:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 08:53:26 +0100
Subject: [PATCH v5 04/11] media: dt-bindings: media: add bindings for
 rockchip mipi csi host
In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-4-f02152534f3c@wolfvision.net>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
 <20250306-v6-8-topic-rk3568-vicap-v5-4-f02152534f3c@wolfvision.net>
Message-ID: <20250307-cunning-glorious-pig-80a99a@krzk-bin>

On Thu, Mar 06, 2025 at 05:56:05PM +0100, Michael Riesch wrote:
> Add documentation for the Rockchip RK3568 MIPI CSI-2 Host unit.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  .../bindings/media/rockchip,rk3568-mipi-csi.yaml   | 114 +++++++++++++++++++++
>  MAINTAINERS                                        |   1 +
>  2 files changed, 115 insertions(+)
> 

Same comments about subject.

> diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
> new file mode 100644
> index 000000000000..900f5a32dab9
> --- /dev/null

...

> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/rk3568-cru.h>
> +    #include <dt-bindings/power/rk3568-power.h>
> +
> +    parent {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        csi: csi at fdfb0000 {
> +            compatible = "rockchip,rk3568-mipi-csi";
> +            reg = <0x0 0xfdfb0000 0x0 0x10000>;
> +            clocks = <&cru PCLK_CSI2HOST1>;
> +            phys = <&csi_dphy>;
> +            power-domains = <&power RK3568_PD_VI>;
> +            resets = <&cru SRST_P_CSI2HOST1>;
> +            status = "disabled";

Drop

> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;

Best regards,
Krzysztof



From daniel.lezcano at linaro.org  Thu Mar  6 23:54:01 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Fri, 7 Mar 2025 08:54:01 +0100
Subject: [PATCH v3] clocksource: stm32-lptimer: use wakeup capable instead
 of init wakeup
In-Reply-To: <20250306102501.2980153-1-fabrice.gasnier@foss.st.com>
References: <20250306102501.2980153-1-fabrice.gasnier@foss.st.com>
Message-ID: <b651acf3-ae10-4f70-a879-3b5d6ff39b02@linaro.org>

On 06/03/2025 11:25, Fabrice Gasnier wrote:
> From: Alexandre Torgue <alexandre.torgue at foss.st.com>
> 
> "wakeup-source" property describes a device which has wakeup capability
> but should not force this device as a wakeup source.
> 
> Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver")
> Cc: stable at vger.kernel.org
> Signed-off-by: Alexandre Torgue <alexandre.torgue at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---

Applied, thanks


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From tglx at linutronix.de  Fri Mar  7 00:01:41 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Fri, 07 Mar 2025 09:01:41 +0100
Subject: [PATCH v3 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <20250305-irqchip-gpio-a4-a5-v3-2-1eec70352fea@amlogic.com>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-2-1eec70352fea@amlogic.com>
Message-ID: <87h64546ca.ffs@tglx>

On Wed, Mar 05 2025 at 18:02, Xianwei Zhao via wrote:
> @@ -358,16 +385,19 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
>  {
>  	u32 val = 0;
>  	unsigned int idx;
> +	const struct meson_gpio_irq_params *params;
> +
> +	params = ctl->params;

Please fix up the variable declaration according to

  https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#variable-declarations

and initialize params right in the declaration. 

Thanks,

        tglx


From ping.bai at nxp.com  Fri Mar  7 00:03:03 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri,  7 Mar 2025 16:03:03 +0800
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
Message-ID: <20250307080303.2660506-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpuidle
in below cpuidle drivers:
  drivers/cpuidle/cpuidle-arm.c
  drivers/cpuidle/cpuidle-big_little.c
  drivers/cpuidle/cpuidle-psci.c
  drivers/cpuidle/cpuidle-riscv-sbi.c

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the failure:

  |  Failed to register cpuidle device for cpu1

Then rollback to cancel all CPUs' cpuidle registration.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpuidle drivers to ensure it only registers cpuidle devices
for CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Reviewed-by: Dhruva Gole <d-gole at ti.com>
Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v4 changes:
  - add changes for other cpuidle driver that has the similar issue
    as cpuidle-pcsi driver.

 - v3 changes:
  - improve the changelog as suggested by Sudeep
---
 drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
 drivers/cpuidle/cpuidle-big_little.c | 2 +-
 drivers/cpuidle/cpuidle-psci.c       | 4 ++--
 drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index caba6f4bb1b7..e044fefdb816 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -137,9 +137,9 @@ static int __init arm_idle_init_cpu(int cpu)
 /*
  * arm_idle_init - Initializes arm cpuidle driver
  *
- * Initializes arm cpuidle driver for all CPUs, if any CPU fails
- * to register cpuidle driver then rollback to cancel all CPUs
- * registration.
+ * Initializes arm cpuidle driver for all present CPUs, if any
+ * CPU fails to register cpuidle driver then rollback to cancel
+ * all CPUs registration.
  */
 static int __init arm_idle_init(void)
 {
@@ -147,7 +147,7 @@ static int __init arm_idle_init(void)
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = arm_idle_init_cpu(cpu);
 		if (ret)
 			goto out_fail;
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index 74972deda0ea..4abba42fcc31 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -148,7 +148,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
 	if (!cpumask)
 		return -ENOMEM;
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		if (smp_cpuid_part(cpu) == part_id)
 			cpumask_set_cpu(cpu, cpumask);
 
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index dd8d776d6e39..b46a83f5ffe4 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -403,7 +403,7 @@ static int psci_idle_init_cpu(struct device *dev, int cpu)
 /*
  * psci_idle_probe - Initializes PSCI cpuidle driver
  *
- * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails
+ * Initializes PSCI cpuidle driver for all present CPUs, if any CPU fails
  * to register cpuidle driver then rollback to cancel all CPUs
  * registration.
  */
@@ -413,7 +413,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = psci_idle_init_cpu(&pdev->dev, cpu);
 		if (ret)
 			goto out_fail;
diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
index 0c92a628bbd4..0fe1ece9fbdc 100644
--- a/drivers/cpuidle/cpuidle-riscv-sbi.c
+++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
@@ -529,8 +529,8 @@ static int sbi_cpuidle_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	/* Initialize CPU idle driver for each CPU */
-	for_each_possible_cpu(cpu) {
+	/* Initialize CPU idle driver for each present CPU */
+	for_each_present_cpu(cpu) {
 		ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu);
 		if (ret) {
 			pr_debug("HART%ld: idle driver init failed\n",
-- 
2.34.1



From krzysztof.kozlowski at linaro.org  Fri Mar  7 00:13:41 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri,  7 Mar 2025 09:13:41 +0100
Subject: [PATCH] dt-bindings: soc: samsung: exynos-usi: Drop unnecessary status from example
Message-ID: <20250307081341.35197-1-krzysztof.kozlowski@linaro.org>

Device nodes in the examples are supposed to be enabled, so the schema
will be validated against them.  Keeping them disabled hides potential
errors.  Only one child of Samsung Exynos USI device node should be
enabled.  The node in the example already selected 'USI_MODE_UART', so
enable the serial node while keeping second - I2C - disabled.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml
index f711e23c0686..cb22637091e8 100644
--- a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml
+++ b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml
@@ -191,7 +191,6 @@ examples:
             interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
             clocks = <&cmu_peri 32>, <&cmu_peri 31>;
             clock-names = "uart", "clk_uart_baud0";
-            status = "disabled";
         };
 
         hsi2c_0: i2c at 13820000 {
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Fri Mar  7 00:14:06 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri,  7 Mar 2025 09:14:06 +0100
Subject: [PATCH] dt-bindings: rng: rockchip,rk3588-rng.: Drop unnecessary status from example
Message-ID: <20250307081406.35242-1-krzysztof.kozlowski@linaro.org>

Device nodes are enabled by default, so no need for 'status = "okay"' in
the DTS example.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
index 757967212f55..ca71b400bcae 100644
--- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
@@ -53,7 +53,6 @@ examples:
         interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
         clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
         resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
-        status = "okay";
       };
     };
 
-- 
2.43.0



From Friday.Yang at mediatek.com  Fri Mar  7 00:14:52 2025
From: Friday.Yang at mediatek.com (=?utf-8?B?RnJpZGF5IFlhbmcgKOadqOmYsyk=?=)
Date: Fri, 7 Mar 2025 08:14:52 +0000
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <8d90731b-4b5a-45a8-83d1-4351044f59c7@kernel.org>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
	 <20250221074846.14105-2-friday.yang@mediatek.com>
	 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
	 <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
	 <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>
	 <9305a4fd6829e5e2ae6c3247d11b9f47ed277f8b.camel@mediatek.com>
	 <8d90731b-4b5a-45a8-83d1-4351044f59c7@kernel.org>
Message-ID: <b57f3a308dde77b26474cda349f61315ded51930.camel@mediatek.com>

On Fri, 2025-03-07 at 08:04 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 07/03/2025 07:38, Friday Yang (??) wrote:
> > On Thu, 2025-03-06 at 13:48 +0100, Krzysztof Kozlowski wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On 06/03/2025 13:45, Friday Yang (??) wrote:
> > > > > > +          const: mediatek,mt8188-smi-larb
> > > > > > +        mediatek,larb-id:
> > > > > > +          oneOf:
> > > > > 
> > > > > Are you really sure that you need 'oneOf' here? :-)
> > > > > 
> > > > > Regards,
> > > > > Angelo
> > > > 
> > > > Yes, I have tested it. If I try to modify the 'examples'
> > > > like this. That is:
> > > >   change the compatible to "mediatek,mt8188-smi-larb",
> > > >   add 'mediatek,larb-id = <10>;'
> > > > 
> > > > examples:
> > > >   - |+
> > > >     #include <dt-bindings/clock/mt8173-clk.h>
> > > >     #includ
> > > > e <dt-bindings/power/mt8173-power.h>
> > > > 
> > > >     larb1: larb at 16010000 {
> > > >       compatible = "mediatek,mt8188-smi-larb";
> > > >       reg = <0x16010000 0x1000>;
> > > >       mediatek,smi = <&smi_common>;
> > > >       mediatek,larb-id = <10>;
> > > >       power-domains = <&scpsys MT8188_POWER_DOMAIN_VDEC>;
> > > >       clocks = <&vdecsys CLK_VDEC_CKEN>,
> > > >                <&vdecsys CLK_VDEC_LARB_CKEN>;
> > > >       clock-names = "apb", "smi";
> > > >     };
> > > > 
> > > > The 'dt_binding_check' could give the following
> > > > errors:
> > > > 
> > > > Documentation/devicetree/bindings/memory-
> > > > controllers/mediatek,smi-
> > > > larb.example.dtb: larb at 16010000: 'resets' is a required
> > > > property
> > > > from schema $id:
> > > > 
> > 
> > 
https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
> > > > Documentation/devicetree/bindings/memory-
> > > > controllers/mediatek,smi-
> > > > larb.example.dtb: larb at 16010000: 'reset-names' is a required
> > > > property
> > > > from schema $id:
> > > > 
> > 
> > 
https://urldefense.com/v3/__http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml*__;Iw!!CTRNKA9wMg0ARbw!kEwWhxyfjVtuHKBHazZGRaFdlmrU2bcIsiVDcsUDzEIManMw2XIG9RgOzq773vtmqlR9_sWZDFhU09SV$
> > > > 
> > > > And this is what I want to achieve. On the MediaTek MT8188 SoC
> > > > platform, 'resets' and 'reset-names' are only required for SMI
> > > > LARBs
> > > > located in image, camera and ipe subsys. Others can be ignored.
> > > > And
> > > > the
> > > > 'larb-id' of these SMI LARBs are shown in this array: [ 9, 10,
> > > > 11,
> > > > 12,
> > > > 13, 16, 17, 18, 19, 20 ].
> > > > 
> > > > Please feel free to let me know if you have any doubts.
> > > 
> > > You did not really answer the question. Where is anything about
> > > oneOf
> > > in
> > > your reply?
> > > 
> > > I am dropping this patchset from my queue.
> > > 
> > 
> > In this SoC, we encountered power-off failures and SMI bus hang
> > issues
> > during camera stress tests. SMI LARBs located in the image, IPE,
> > and
> > camera subsystems need to implement a reset, while other LARBs do
> > not
> > require it.
> > 
> > The 'mediatek,larb-id' for SMI LARBs in the image, IPE, and camera
> > subsystems are as follows:
> > - image subsystem: 9, 10, 11, 12, 16
> > - IPE subsystem: 13
> > - camera subsystem: 17, 18, 19, 20
> > 
> > Therefore, we believe that 'mediatek,larb-id' should be 'oneOf' the
> 
> 
> So explain me where is the second condition?
> 

Sorry for the misunderstanding. I should fix it like this:
just delete 'oneOf' and use 'enum'

  - if:  # only for camera and image subsys
      properties:
        com
patible:
          const: mediatek,mt8188-smi-larb
        mediatek,larb-
id:
          enum:
            [ 9, 10, 11, 12, 13, 16, 17, 18, 19, 20 ]

    then:
      required:
        - resets
        - reset-names

> Best regards,
> Krzysztof

From anshuman.khandual at arm.com  Fri Mar  7 00:36:37 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Fri, 7 Mar 2025 14:06:37 +0530
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <CAMj1kXFufE9UPGMsqv1ARWm6SyUCcJL+m4F4mWa0jCyhJqf2Jg@mail.gmail.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
 <CAMj1kXFufE9UPGMsqv1ARWm6SyUCcJL+m4F4mWa0jCyhJqf2Jg@mail.gmail.com>
Message-ID: <ad54eb36-adfd-4182-bec3-fa73ee5a5778@arm.com>



On 3/7/25 13:08, Ard Biesheuvel wrote:
> Hi Anshuman,
> 
> On Fri, 7 Mar 2025 at 06:09, Anshuman Khandual
> <anshuman.khandual at arm.com> wrote:
>>
>> Address bytes shifted with a single 64 bit page table entry (any page table
>> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
>> is not very readable or easy to reason about. Besides it is going to change
>> with D128, where each 128 bit page table entry will shift address bytes by
>> 4 (aka 2^4 = 16) instead.
>>
>> Let's just formalise this address bytes shift value into a new macro called
>> PTE_SHIFT establishing a logical abstraction, thus improving readability as
>> well. This does not cause any functional change.
>>
> 
> I don't disagree with this goal, but PTE_SHIFT is really not the right
> name. Given that PMD_SHIFT is the log2 of the area covered by a PMD,
> PTE_SHIFT should be the log2 of the area covered by a PTE, and so
> defining it to anything other than PAGE_SHIFT would be a mistake IMO.

Makes sense.

> 
> Given that we are talking about the log2 of the size of the area
> occupied by a descriptor, perhaps {PT}DESC_SIZE_ORDER would be a
> better name?

Originally we had this as [ARM64]_TTD_SHIFT but being a generic
construct, a preceding ARM64_ probably does not make sense here.

How about PTDESC_ORDER instead just to keep it bit short ?

> 
> 
> 
> 
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
>> Cc: Alexander Potapenko <glider at google.com>
>> Cc: Andrey Konovalov <andreyknvl at gmail.com>
>> Cc: Dmitry Vyukov <dvyukov at google.com>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: kasan-dev at googlegroups.com
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>> This patch applies on v6.14-rc5
>>
>>  arch/arm64/Kconfig                      |  2 +-
>>  arch/arm64/include/asm/kernel-pgtable.h |  3 ++-
>>  arch/arm64/include/asm/pgtable-hwdef.h  | 26 +++++++++++++------------
>>  arch/arm64/kernel/pi/map_range.c        |  2 +-
>>  arch/arm64/mm/kasan_init.c              |  6 +++---
>>  5 files changed, 21 insertions(+), 18 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 940343beb3d4..fd3303f2ccda 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
>>         default 18
>>
>>  # max bits determined by the following formula:
>> -#  VA_BITS - PAGE_SHIFT - 3
>> +#  VA_BITS - PAGE_SHIFT - PTE_SHIFT
>>  config ARCH_MMAP_RND_BITS_MAX
>>         default 19 if ARM64_VA_BITS=36
>>         default 24 if ARM64_VA_BITS=39
>> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
>> index fd5a08450b12..7150a7a10f00 100644
>> --- a/arch/arm64/include/asm/kernel-pgtable.h
>> +++ b/arch/arm64/include/asm/kernel-pgtable.h
>> @@ -49,7 +49,8 @@
>>         (SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
>>
>>  #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)      \
>> -       (lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
>> +       (lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
>> +       lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)
>>
>>  #define EARLY_PAGES(lvls, vstart, vend, add) (1        /* PGDIR page */                                \
>>         + EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */  \
>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
>> index a9136cc551cc..43f98eac7653 100644
>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>> @@ -7,40 +7,42 @@
>>
>>  #include <asm/memory.h>
>>
>> +#define PTE_SHIFT 3
>> +
>>  /*
>>   * Number of page-table levels required to address 'va_bits' wide
>>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
>> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
>> + * bits with (PAGE_SHIFT - PTE_SHIFT) bits at each page table level. Hence:
>>   *
>> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
>> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTE_SHIFT))
>>   *
>>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>>   *
>>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>>   * due to build issues. So we open code DIV_ROUND_UP here:
>>   *
>> - *     ((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
>> + *     ((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTE_SHIFT) - 1) / (PAGE_SHIFT - PTE_SHIFT))
>>   *
>>   * which gets simplified as :
>>   */
>> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
>> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - PTE_SHIFT - 1) / (PAGE_SHIFT - PTE_SHIFT))
>>
>>  /*
>>   * Size mapped by an entry at level n ( -1 <= n <= 3)
>> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
>> + * We map (PAGE_SHIFT - PTE_SHIFT) at all translation levels and PAGE_SHIFT bits
>>   * in the final page. The maximum number of translation levels supported by
>>   * the architecture is 5. Hence, starting at level n, we have further
>>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>>   * So, the total number of bits mapped by an entry at level n is :
>>   *
>> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
>> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTE_SHIFT) + PAGE_SHIFT
>>   *
>>   * Rearranging it a bit we get :
>> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
>> + *   (4 - n) * (PAGE_SHIFT - PTE_SHIFT) + PTE_SHIFT
>>   */
>> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)        ((PAGE_SHIFT - 3) * (4 - (n)) + 3)
>> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)        ((PAGE_SHIFT - PTE_SHIFT) * (4 - (n)) + PTE_SHIFT)
>>
>> -#define PTRS_PER_PTE           (1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PTE           (1 << (PAGE_SHIFT - PTE_SHIFT))
>>
>>  /*
>>   * PMD_SHIFT determines the size a level 2 page table entry can map.
>> @@ -49,7 +51,7 @@
>>  #define PMD_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>>  #define PMD_SIZE               (_AC(1, UL) << PMD_SHIFT)
>>  #define PMD_MASK               (~(PMD_SIZE-1))
>> -#define PTRS_PER_PMD           (1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PMD           (1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>
>>  /*
>> @@ -59,14 +61,14 @@
>>  #define PUD_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>>  #define PUD_SIZE               (_AC(1, UL) << PUD_SHIFT)
>>  #define PUD_MASK               (~(PUD_SIZE-1))
>> -#define PTRS_PER_PUD           (1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PUD           (1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>
>>  #if CONFIG_PGTABLE_LEVELS > 4
>>  #define P4D_SHIFT              ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>>  #define P4D_SIZE               (_AC(1, UL) << P4D_SHIFT)
>>  #define P4D_MASK               (~(P4D_SIZE-1))
>> -#define PTRS_PER_P4D           (1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_P4D           (1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>
>>  /*
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 2b69e3beeef8..3530a5427f57 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>  {
>>         u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>>         pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
>> -       int lshift = (3 - level) * (PAGE_SHIFT - 3);
>> +       int lshift = (3 - level) * (PAGE_SHIFT - PTE_SHIFT);
>>         u64 lmask = (PAGE_SIZE << lshift) - 1;
>>
>>         start   &= PAGE_MASK;
>> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
>> index b65a29440a0c..90548079b42e 100644
>> --- a/arch/arm64/mm/kasan_init.c
>> +++ b/arch/arm64/mm/kasan_init.c
>> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>>   */
>>  static bool __init root_level_aligned(u64 addr)
>>  {
>> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
>> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>>
>>         return (addr % (PAGE_SIZE << shift)) == 0;
>>  }
>> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>>          */
>>         u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>>                                                         : vabits_actual;
>> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
>> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>>
>>         return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>>  }
>> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>>   */
>>  static int __init next_level_idx(u64 addr)
>>  {
>> -       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
>> +       int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTE_SHIFT);
>>
>>         return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>>  }
>> --
>> 2.30.2
>>


From krzk at kernel.org  Fri Mar  7 00:37:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 09:37:07 +0100
Subject: [PATCH v4 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <b57f3a308dde77b26474cda349f61315ded51930.camel@mediatek.com>
References: <20250221074846.14105-1-friday.yang@mediatek.com>
 <20250221074846.14105-2-friday.yang@mediatek.com>
 <0dcb2efd-6bbb-4701-960a-74930eb457e4@collabora.com>
 <264f78c1067e363c69e146543ebb77dbedfbd181.camel@mediatek.com>
 <463ca2df-a0ee-4b9e-a988-12f316ae7d1a@kernel.org>
 <9305a4fd6829e5e2ae6c3247d11b9f47ed277f8b.camel@mediatek.com>
 <8d90731b-4b5a-45a8-83d1-4351044f59c7@kernel.org>
 <b57f3a308dde77b26474cda349f61315ded51930.camel@mediatek.com>
Message-ID: <3795c10f-b9ca-45b1-88d3-4bf6b4eb6ecd@kernel.org>

On 07/03/2025 09:14, Friday Yang (??) wrote:
>>> The 'mediatek,larb-id' for SMI LARBs in the image, IPE, and camera
>>> subsystems are as follows:
>>> - image subsystem: 9, 10, 11, 12, 16
>>> - IPE subsystem: 13
>>> - camera subsystem: 17, 18, 19, 20
>>>
>>> Therefore, we believe that 'mediatek,larb-id' should be 'oneOf' the
>>
>>
>> So explain me where is the second condition?
>>
> 
> Sorry for the misunderstanding. I should fix it like this:
> just delete 'oneOf' and use 'enum'
> 
>   - if:  # only for camera and image subsys
>       properties:
>         com
> patible:
>           const: mediatek,mt8188-smi-larb
>         mediatek,larb-
> id:
>           enum:
>             [ 9, 10, 11, 12, 13, 16, 17, 18, 19, 20 ]
Yes

Best regards,
Krzysztof


From xianwei.zhao at amlogic.com  Fri Mar  7 00:39:36 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Fri, 7 Mar 2025 16:39:36 +0800
Subject: [PATCH v3 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <87h64546ca.ffs@tglx>
References: <20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea@amlogic.com>
 <20250305-irqchip-gpio-a4-a5-v3-2-1eec70352fea@amlogic.com>
 <87h64546ca.ffs@tglx>
Message-ID: <a7c5f76e-241e-486b-86c9-ae9b64f3d52d@amlogic.com>

Hi Thomas,
    Thanks for your advice.

On 2025/3/7 16:01, Thomas Gleixner wrote:
> [ EXTERNAL EMAIL ]
> 
> On Wed, Mar 05 2025 at 18:02, Xianwei Zhao via wrote:
>> @@ -358,16 +385,19 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
>>   {
>>        u32 val = 0;
>>        unsigned int idx;
>> +     const struct meson_gpio_irq_params *params;
>> +
>> +     params = ctl->params;
> 
> Please fix up the variable declaration according to
> 
>    https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#variable-declarations
> 
> and initialize params right in the declaration.
> 

Will fix.

> Thanks,
> 
>          tglx


From devnull+xianwei.zhao.amlogic.com at kernel.org  Fri Mar  7 00:49:21 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 07 Mar 2025 16:49:21 +0800
Subject: [PATCH v4 0/4] Add GPIO interrupt support for Amlogic A4 and A5
 SoCs
Message-ID: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>

This patch adds GPIO interrupt support for Amlogic A4 and A5 SoCs

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Changes in v4:
- Make minor changes for bindings as Conor and Rob suggest.
- Format adjustment of source code according to Thomas's suggestion.
- Link to v3: https://lore.kernel.org/r/20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea at amlogic.com

Changes in v3:
- Fix warning when run 'make ARCH=arm64 dtbs_check'.
- Fix warning when run 'make ARCH=arm64 Image W=1'.
- Rebase file amlogic-a4.dtsi.
- Link to v2: https://lore.kernel.org/r/20250226-irqchip-gpio-a4-a5-v2-0-c55b1050cb55 at amlogic.com

Changes in v2:
- Use if/then instead of direct modification minimum value for property 'amlogic,channel-interrupts'.
- Add register offsets to the parameter structure to reduce definition of a function.
- Link to v1: https://lore.kernel.org/r/20250219-irqchip-gpio-a4-a5-v1-0-3c8e44ae42df at amlogic.com

---
Xianwei Zhao (4):
      dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
      irqchip: Add support for Amlogic A4 and A5 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

 .../amlogic,meson-gpio-intc.yaml                   | 19 ++++++++-
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 19 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 ++++++
 drivers/irqchip/irq-meson-gpio.c                   | 45 +++++++++++++++++-----
 4 files changed, 85 insertions(+), 10 deletions(-)
---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20241213-irqchip-gpio-a4-a5-80c50a1456c4

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From devnull+xianwei.zhao.amlogic.com at kernel.org  Fri Mar  7 00:49:22 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 07 Mar 2025 16:49:22 +0800
Subject: [PATCH v4 1/4] dt-bindings: interrupt-controller: Add support for
 Amlogic A4 and A5 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
Message-ID: <20250307-irqchip-gpio-a4-a5-v4-1-d03a9424151b@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Update dt-binding document for GPIO interrupt controller
of Amlogic A4 and A5 SoCs

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 .../interrupt-controller/amlogic,meson-gpio-intc.yaml | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
index a93744763787..3d60d9e9e208 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
@@ -35,6 +35,9 @@ properties:
               - amlogic,meson-sm1-gpio-intc
               - amlogic,meson-a1-gpio-intc
               - amlogic,meson-s4-gpio-intc
+              - amlogic,a4-gpio-intc
+              - amlogic,a4-gpio-ao-intc
+              - amlogic,a5-gpio-intc
               - amlogic,c3-gpio-intc
               - amlogic,t7-gpio-intc
           - const: amlogic,meson-gpio-intc
@@ -49,7 +52,7 @@ properties:
 
   amlogic,channel-interrupts:
     description: Array with the upstream hwirq numbers
-    minItems: 8
+    minItems: 2
     maxItems: 12
     $ref: /schemas/types.yaml#/definitions/uint32-array
 
@@ -60,6 +63,20 @@ required:
   - "#interrupt-cells"
   - amlogic,channel-interrupts
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: amlogic,a4-gpio-ao-intc
+then:
+  properties:
+    amlogic,channel-interrupts:
+      maxItems: 2
+else:
+  properties:
+    amlogic,channel-interrupts:
+      minItems: 8
+
 additionalProperties: false
 
 examples:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Fri Mar  7 00:49:25 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 07 Mar 2025 16:49:25 +0800
Subject: [PATCH v4 4/4] arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
Message-ID: <20250307-irqchip-gpio-a4-a5-v4-4-d03a9424151b@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 17a6316de891..32ed1776891b 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -48,3 +48,15 @@ pwrc: power-controller {
 		};
 	};
 };
+
+&apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a5-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+};

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Fri Mar  7 00:49:23 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 07 Mar 2025 16:49:23 +0800
Subject: [PATCH v4 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
Message-ID: <20250307-irqchip-gpio-a4-a5-v4-2-d03a9424151b@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

The Amlogic A4 SoCs support 12 GPIO IRQ lines and 2 AO GPIO IRQ lines,
A5 SoCs support 12 GPIO IRQ lines, details are as below.

A4 IRQ Number:
- 72:55   18 pins on bank T
- 54:32   23 pins on bank X
- 31:16   16 pins on bank D
- 15:14    2 pins on bank E
- 13:0    14 pins on bank B

A4 AO IRQ Number:
- 7       1 pin  on bank TESTN
- 6:0     7 pins on bank AO

A5 IRQ Number:
- 98      1 pin  on bank TESTN
- 97:82   16 pins on bank Z
- 81:62   20 pins on bank X
- 61:48   14 pins on bank T
- 47:32   16 pins on bank D
- 31:27    5 pins on bank H
- 26:25    2 pins on bank E
- 24:14   11 pins on bank C
- 13:0    14 pins on bank B

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/irqchip/irq-meson-gpio.c | 45 ++++++++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index cd789fa51519..e0265d24e3e3 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -26,8 +26,6 @@
 
 /* use for A1 like chips */
 #define REG_PIN_A1_SEL	0x04
-/* Used for s4 chips */
-#define REG_EDGE_POL_S4	0x1c
 
 /*
  * Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
@@ -72,6 +70,7 @@ struct meson_gpio_irq_params {
 	bool support_edge_both;
 	unsigned int edge_both_offset;
 	unsigned int edge_single_offset;
+	unsigned int edge_pol_reg;
 	unsigned int pol_low_offset;
 	unsigned int pin_sel_mask;
 	struct irq_ctl_ops ops;
@@ -105,6 +104,18 @@ struct meson_gpio_irq_params {
 	.pin_sel_mask = 0x7f,					\
 	.nr_channels = 8,					\
 
+#define INIT_MESON_A4_AO_COMMON_DATA(irqs)			\
+	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
+			  meson_a1_gpio_irq_sel_pin,		\
+			  meson_s4_gpio_irq_set_type)		\
+	.support_edge_both = true,				\
+	.edge_both_offset = 0,					\
+	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x8,					\
+	.pol_low_offset = 0,					\
+	.pin_sel_mask = 0xff,					\
+	.nr_channels = 2,					\
+
 #define INIT_MESON_S4_COMMON_DATA(irqs)				\
 	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
 			  meson_a1_gpio_irq_sel_pin,		\
@@ -112,6 +123,7 @@ struct meson_gpio_irq_params {
 	.support_edge_both = true,				\
 	.edge_both_offset = 0,					\
 	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x1c,					\
 	.pol_low_offset = 0,					\
 	.pin_sel_mask = 0xff,					\
 	.nr_channels = 12,					\
@@ -146,6 +158,18 @@ static const struct meson_gpio_irq_params a1_params = {
 	INIT_MESON_A1_COMMON_DATA(62)
 };
 
+static const struct meson_gpio_irq_params a4_params = {
+	INIT_MESON_S4_COMMON_DATA(81)
+};
+
+static const struct meson_gpio_irq_params a4_ao_params = {
+	INIT_MESON_A4_AO_COMMON_DATA(8)
+};
+
+static const struct meson_gpio_irq_params a5_params = {
+	INIT_MESON_S4_COMMON_DATA(99)
+};
+
 static const struct meson_gpio_irq_params s4_params = {
 	INIT_MESON_S4_COMMON_DATA(82)
 };
@@ -168,6 +192,9 @@ static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
 	{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
 	{ .compatible = "amlogic,meson-a1-gpio-intc", .data = &a1_params },
 	{ .compatible = "amlogic,meson-s4-gpio-intc", .data = &s4_params },
+	{ .compatible = "amlogic,a4-gpio-ao-intc", .data = &a4_ao_params },
+	{ .compatible = "amlogic,a4-gpio-intc", .data = &a4_params },
+	{ .compatible = "amlogic,a5-gpio-intc", .data = &a5_params },
 	{ .compatible = "amlogic,c3-gpio-intc", .data = &c3_params },
 	{ .compatible = "amlogic,t7-gpio-intc", .data = &t7_params },
 	{ }
@@ -299,11 +326,10 @@ meson_gpio_irq_release_channel(struct meson_gpio_irq_controller *ctl,
 static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 				    unsigned int type, u32 *channel_hwirq)
 {
-	u32 val = 0;
+	const struct meson_gpio_irq_params *params = ctl->params;
 	unsigned int idx;
-	const struct meson_gpio_irq_params *params;
+	u32 val = 0;
 
-	params = ctl->params;
 	idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
 
 	/*
@@ -356,18 +382,19 @@ static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 				      unsigned int type, u32 *channel_hwirq)
 {
-	u32 val = 0;
+	const struct meson_gpio_irq_params *params = ctl->params;
 	unsigned int idx;
+	u32 val = 0;
 
 	idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
 
 	type &= IRQ_TYPE_SENSE_MASK;
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4, BIT(idx), 0);
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg, BIT(idx), 0);
 
 	if (type == IRQ_TYPE_EDGE_BOTH) {
 		val |= BIT(ctl->params->edge_both_offset + idx);
-		meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4,
+		meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
 					   BIT(ctl->params->edge_both_offset + idx), val);
 		return 0;
 	}
@@ -378,7 +405,7 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
 		val |= BIT(ctl->params->edge_single_offset + idx);
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
 				   BIT(idx) | BIT(12 + idx), val);
 	return 0;
 };

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Fri Mar  7 00:49:24 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 07 Mar 2025 16:49:24 +0800
Subject: [PATCH v4 3/4] arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
Message-ID: <20250307-irqchip-gpio-a4-a5-v4-3-d03a9424151b@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index efba8565af3c..fa80fa365f13 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -51,6 +51,25 @@ pwrc: power-controller {
 };
 
 &apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a4-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+
+	gpio_ao_intc: interrupt-controller at 8e72c {
+		compatible = "amlogic,a4-gpio-ao-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x8e72c 0x0 0x0c>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts = <140 141>;
+	};
+
 	periphs_pinctrl: pinctrl {
 		compatible = "amlogic,pinctrl-a4";
 		#address-cells = <2>;

-- 
2.37.1




From krzk at kernel.org  Fri Mar  7 00:56:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 09:56:56 +0100
Subject: [PATCH v3 1/3] dt-bindings: reset: Add Armada8K reset controller
In-Reply-To: <BY3PR18MB46734A2425361D8BE83E4282A7D52@BY3PR18MB4673.namprd18.prod.outlook.com>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-2-dingwei@marvell.com>
 <174068786548.161165.4348563654300627455.robh@kernel.org>
 <BY3PR18MB467346EB1FA7CEF0A3300350A7CD2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <d2929546-27de-4893-a611-dd4a3bca1a64@kernel.org>
 <BY3PR18MB46734A2425361D8BE83E4282A7D52@BY3PR18MB4673.namprd18.prod.outlook.com>
Message-ID: <f8e2091b-52dc-4b7a-b781-84588dd6b1ba@kernel.org>

On 07/03/2025 01:03, Wilson Ding wrote:
>> reset.example.dts
>>>   DTC [C]
>>> Documentation/devicetree/bindings/reset/marvell,armada8k-reset.example
>>> .dtb
>>>
>>
>> That's a bit odd but anyway warning is correct: you cannot have such
>> compatibles alone.
> 
> I understand I need to add one compatible here to resolve the
> warning. However, as we agreed, we keep the sud-nodes while
> there will be no new compatibles in parent node. So how shall
> I avoid this warning?
> 
> If we do want to add a compatible in parent node, what should
> be used for the compatible name? I think the most suitable name
> would be something like "marvell,cp110-system-controller0".

I don't know. I don't work in Marvell, I know nothing about Marvell
Armada and I was not involved in any Armada SoCs.

Read your datasheet and come up with some reasonable name based on
datasheet. Why do you ask people who do not have datasheet?

> However, it was already taken for in Armada clock controller to
> be compatible for legacy dt.
> 
> https://lore.kernel.org/all/bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-series.gregory.clement at free-electrons.com/

I don't understand what it means.

> 
> This is something about 8 years ago. I wonder if we do need to
> have the backward compatibility for the field devices at that
> time. Can we drop it now?

Drop what? You need to keep ABI.

> 
>     syscon0: system-controller at 440000 {
>         compatible = "marvell,cp110-system-controller0",
>                                 "syscon", "simple-mfd";
>         reg = <0x440000 0x2000>;
>         #address-cells = <1>;
>         #size-cells = <1>;
> 
>         swrst: reset-controller at 268 {
>             compatible = "marvell,armada8k-reset";
>             reg = <0x268 0x4>;
>             #reset-cells = <1>;
>         };
>     };
> 
Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar  7 00:59:40 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 09:59:40 +0100
Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
 reset controller node
In-Reply-To: <BY3PR18MB4673BD07048F8AF7EA55282CA7CA2@BY3PR18MB4673.namprd18.prod.outlook.com>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
 <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <03b14353-5d47-48de-99fd-9cc48bad5651@kernel.org>
 <BY3PR18MB4673BD07048F8AF7EA55282CA7CA2@BY3PR18MB4673.namprd18.prod.outlook.com>
Message-ID: <2f39acd2-e378-47cf-b852-bee1a38108c5@kernel.org>

On 06/03/2025 18:42, Wilson Ding wrote:
> 
> 
>> -----Original Message-----
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: Wednesday, March 5, 2025 11:29 PM
>> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
>> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>> robh at kernel.org
>> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
>> sebastian.hesselbarth at gmail.com; krzk+dt at kernel.org; conor+dt at kernel.org;
>> p.zabel at pengutronix.de; Sanghoon Lee <salee at marvell.com>;
>> Geethasowjanya Akula <gakula at marvell.com>
>> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset
>> controller node
>>
>> On 04/03/2025 20:08, Wilson Ding wrote:
>>>
>>> I did consider shrinking the syscon's register address range to make
>>> the reset-controller node to be independent from the syscon node.
>>> However, I found the syscon node is also referred by some devices for
>>> miscellaneous configurations . The reset configuration register
>>> happens to be located in between these registers and clock/GPIO
>>> registers.
>>>
>>>> drop offset in your patch or unify everything into 'reg'.
>>>>
>>>
>>> This is exactly what I proposed in v3 patch. Do I misunderstand you?
>>>
>>> CP11X_LABEL(swrst): reset-controller at 268 {
>>> 	compatible = "marvell,armada8k-reset";
>>> 	reg = <0x268 0x4>;
>>> 	#reset-cells = <1>;
>>> };
>>
>> I don't see the other device being fixed here. How did you unify them?
> 
> This patch series is about the proposal of Armada8K's reset controller
> dt-binding. The dt-bindings issues of clock/GPIO controllers have been
> there for years. Having to say, it is not just a simple patch to fix it. It


I understand, you just want to throw your patch here over the wall. It's
reasonable, I feel it. Just like previous cases for this binding -
everyone wanted one subnode at a time, ignoring bigger picture, each
time making it franken-node or franken-binding.

Please listen to Greg's talk from years ago about upstreaming. "I don't
want your code":
https://www.youtube.com/watch?v=fMeH7wqOwXA


Best regards,
Krzysztof


From ryan.roberts at arm.com  Fri Mar  7 01:07:11 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 7 Mar 2025 09:07:11 +0000
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <20250307050851.4034393-1-anshuman.khandual@arm.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
Message-ID: <17931f83-7142-4ca6-8bfe-466ec53b6e2c@arm.com>

On 07/03/2025 05:08, Anshuman Khandual wrote:
> Address bytes shifted with a single 64 bit page table entry (any page table
> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
> is not very readable or easy to reason about. Besides it is going to change
> with D128, where each 128 bit page table entry will shift address bytes by
> 4 (aka 2^4 = 16) instead.
> 
> Let's just formalise this address bytes shift value into a new macro called
> PTE_SHIFT establishing a logical abstraction, thus improving readability as
> well. This does not cause any functional change.
> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
> Cc: Alexander Potapenko <glider at google.com>
> Cc: Andrey Konovalov <andreyknvl at gmail.com>
> Cc: Dmitry Vyukov <dvyukov at google.com>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Cc: kasan-dev at googlegroups.com
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>


+1 for PTDESC_ORDER

Implementation looks good to me so:

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

one nit below.

> ---
> This patch applies on v6.14-rc5
> 
>  arch/arm64/Kconfig                      |  2 +-
>  arch/arm64/include/asm/kernel-pgtable.h |  3 ++-
>  arch/arm64/include/asm/pgtable-hwdef.h  | 26 +++++++++++++------------
>  arch/arm64/kernel/pi/map_range.c        |  2 +-
>  arch/arm64/mm/kasan_init.c              |  6 +++---
>  5 files changed, 21 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..fd3303f2ccda 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
>  	default 18
>  
>  # max bits determined by the following formula:
> -#  VA_BITS - PAGE_SHIFT - 3
> +#  VA_BITS - PAGE_SHIFT - PTE_SHIFT
>  config ARCH_MMAP_RND_BITS_MAX
>  	default 19 if ARM64_VA_BITS=36
>  	default 24 if ARM64_VA_BITS=39
> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
> index fd5a08450b12..7150a7a10f00 100644
> --- a/arch/arm64/include/asm/kernel-pgtable.h
> +++ b/arch/arm64/include/asm/kernel-pgtable.h
> @@ -49,7 +49,8 @@
>  	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
>  
>  #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
> -	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
> +	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
> +	lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)

nit: not sure what style guide says, but I would indent this continuation an
extra level.

Thanks,
Ryan

>  
>  #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
>  	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index a9136cc551cc..43f98eac7653 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -7,40 +7,42 @@
>  
>  #include <asm/memory.h>
>  
> +#define PTE_SHIFT 3
> +
>  /*
>   * Number of page-table levels required to address 'va_bits' wide
>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
> + * bits with (PAGE_SHIFT - PTE_SHIFT) bits at each page table level. Hence:
>   *
> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTE_SHIFT))
>   *
>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>   *
>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>   * due to build issues. So we open code DIV_ROUND_UP here:
>   *
> - *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
> + *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTE_SHIFT) - 1) / (PAGE_SHIFT - PTE_SHIFT))
>   *
>   * which gets simplified as :
>   */
> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - PTE_SHIFT - 1) / (PAGE_SHIFT - PTE_SHIFT))
>  
>  /*
>   * Size mapped by an entry at level n ( -1 <= n <= 3)
> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
> + * We map (PAGE_SHIFT - PTE_SHIFT) at all translation levels and PAGE_SHIFT bits
>   * in the final page. The maximum number of translation levels supported by
>   * the architecture is 5. Hence, starting at level n, we have further
>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>   * So, the total number of bits mapped by an entry at level n is :
>   *
> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTE_SHIFT) + PAGE_SHIFT
>   *
>   * Rearranging it a bit we get :
> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
> + *   (4 - n) * (PAGE_SHIFT - PTE_SHIFT) + PTE_SHIFT
>   */
> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTE_SHIFT) * (4 - (n)) + PTE_SHIFT)
>  
> -#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTE_SHIFT))
>  
>  /*
>   * PMD_SHIFT determines the size a level 2 page table entry can map.
> @@ -49,7 +51,7 @@
>  #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>  #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
>  #define PMD_MASK		(~(PMD_SIZE-1))
> -#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>  
>  /*
> @@ -59,14 +61,14 @@
>  #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>  #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
>  #define PUD_MASK		(~(PUD_SIZE-1))
> -#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>  
>  #if CONFIG_PGTABLE_LEVELS > 4
>  #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>  #define P4D_MASK		(~(P4D_SIZE-1))
> -#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTE_SHIFT))
>  #endif
>  
>  /*
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..3530a5427f57 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  {
>  	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>  	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
> -	int lshift = (3 - level) * (PAGE_SHIFT - 3);
> +	int lshift = (3 - level) * (PAGE_SHIFT - PTE_SHIFT);
>  	u64 lmask = (PAGE_SIZE << lshift) - 1;
>  
>  	start	&= PAGE_MASK;
> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> index b65a29440a0c..90548079b42e 100644
> --- a/arch/arm64/mm/kasan_init.c
> +++ b/arch/arm64/mm/kasan_init.c
> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>   */
>  static bool __init root_level_aligned(u64 addr)
>  {
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>  
>  	return (addr % (PAGE_SIZE << shift)) == 0;
>  }
> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>  	 */
>  	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>  							: vabits_actual;
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>  
>  	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>  }
> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>   */
>  static int __init next_level_idx(u64 addr)
>  {
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTE_SHIFT);
>  
>  	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>  }



From patrice.chotard at foss.st.com  Fri Mar  7 00:59:42 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Fri, 7 Mar 2025 09:59:42 +0100
Subject: [PATCH] spi: stm32: Fix a NULL vs IS_ERR() bug
In-Reply-To: <20250307032530.116837-1-hanchunchao@inspur.com>
References: <20250307032530.116837-1-hanchunchao@inspur.com>
Message-ID: <dfd831ec-e004-4132-94f0-3bdc755907cd@foss.st.com>



On 3/7/25 04:25, Charles Han wrote:
> The devm_ioremap() function doesn't return error pointers, it may
> returns NULL.  Update the error checking to match.
> 
> Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
> Signed-off-by: Charles Han <hanchunchao at inspur.com>
> ---
>  drivers/spi/spi-stm32-ospi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
> index 8eadcb64f34a..a544d7897edf 100644
> --- a/drivers/spi/spi-stm32-ospi.c
> +++ b/drivers/spi/spi-stm32-ospi.c
> @@ -835,10 +835,10 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
>  	if (rmem) {
>  		ospi->mm_size = rmem->size;
>  		ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size);
> -		if (IS_ERR(ospi->mm_base)) {
> +		if (!ospi->mm_base) {
>  			dev_err(dev, "unable to map memory region: %pa+%pa\n",
>  				&rmem->base, &rmem->size);
> -			ret = PTR_ERR(ospi->mm_base);
> +			ret = -ENOMEM;
>  			goto err_dma;
>  		}
>  

Hi

No need to copy/paste other contributor's patch by just swapping some 
words in title/commit message.

This fix has already sent By Dan Carpenter and merged.

Patrice


From jonas at kwiboo.se  Fri Mar  7 01:16:08 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 10:16:08 +0100
Subject: [PATCH 4/4] arm64: dts: rockchip: Enable Ethernet controller on
 Radxa E20C
In-Reply-To: <e0e8fa5e-07a2-4f4f-80b9-ddb2332c27ea@lunn.ch>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-5-jonas@kwiboo.se>
 <e0e8fa5e-07a2-4f4f-80b9-ddb2332c27ea@lunn.ch>
Message-ID: <cbd6d3ee-8ad1-443f-9506-e28240ffb09e@kwiboo.se>

Hi Andrew,

On 2025-03-06 23:49, Andrew Lunn wrote:
>> +&mdio1 {
>> +	rgmii_phy: ethernet-phy at 1 {
>> +		compatible = "ethernet-phy-ieee802.3-c22";
> 
> The compatible is not needed. That is the default.

Interesting, however I rather be explicit to not cause any issue for
U-Boot or any other user of the device trees beside Linux kernel.

Regards,
Jonas

> 
> 	Andrew



From swathi.ks at samsung.com  Thu Mar  6 20:49:02 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Fri,  7 Mar 2025 10:19:02 +0530
Subject: [PATCH v8 0/2] arm64: dts: fsd: Add Ethernet support for FSD SoC
References: <CGME20250307045516epcas5p3b4006a5e2005beda04170179dc92ad16@epcas5p3.samsung.com>
Message-ID: <20250307044904.59077-1-swathi.ks@samsung.com>

FSD platform has two instances of EQoS IP, one is in FSYS0 block and
another one is in PERIC block. This patch series add required DT file
modifications for the same.

Changes since v1:
1. Addressed the format related corrections.
2. Addressed the MAC address correction.

Changes since v2:
1. Corrected intendation issues.

Changes since v3:
1. Removed alias names of ethernet nodes

Changes since v4:
1. Added more details to the commit message as per review comment.

Changes since v5:
1. Avoided inserting node in the end and inserted it in between as per
address.
2. Changed the node label.
3. Separating DT patches from net patches and posting in different
branches.

Changes since v6:
1. Addressed Andrew's review comment and removed phy-mode from .dtsi to
.dts

Changes since v7:
1. Addressed Russell's review comment-Implemented clock tree setup in DT

Swathi K S (2):
  arm64: dts: fsd: Add Ethernet support for FSYS0 Block of FSD SoC
  arm64: dts: fsd: Add Ethernet support for PERIC Block of FSD SoC

 arch/arm64/boot/dts/tesla/fsd-evb.dts      |  20 ++++
 arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi | 112 +++++++++++++++++++++
 arch/arm64/boot/dts/tesla/fsd.dtsi         |  50 +++++++++
 3 files changed, 182 insertions(+)

-- 
2.17.1



From swathi.ks at samsung.com  Thu Mar  6 20:49:03 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Fri,  7 Mar 2025 10:19:03 +0530
Subject: [PATCH v8 1/2] arm64: dts: fsd: Add Ethernet support for FSYS0
 Block of FSD SoC
In-Reply-To: <20250307044904.59077-1-swathi.ks@samsung.com>
References: <20250307044904.59077-1-swathi.ks@samsung.com>
	<CGME20250307045520epcas5p489488a0876bdea0495577d23a8b73cc7@epcas5p4.samsung.com>
Message-ID: <20250307044904.59077-2-swathi.ks@samsung.com>

The FSD SoC contains two instances of Synopsys DWC QoS Ethernet IP, one
in FSYS0 block and other in PERIC block.
The ethernet interface is managed by a switch which is not managed by
Linux.

Adds device tree node for Ethernet in FSYS0 Block and enables the same for
FSD platform.

Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
Signed-off-by: Jayati Sahu <jayati.sahu at samsung.com>
Signed-off-by: Swathi K S <swathi.ks at samsung.com>
---
 arch/arm64/boot/dts/tesla/fsd-evb.dts      | 10 ++++
 arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi | 56 ++++++++++++++++++++++
 arch/arm64/boot/dts/tesla/fsd.dtsi         | 20 ++++++++
 3 files changed, 86 insertions(+)

diff --git a/arch/arm64/boot/dts/tesla/fsd-evb.dts b/arch/arm64/boot/dts/tesla/fsd-evb.dts
index 8d7794642900..321270a07651 100644
--- a/arch/arm64/boot/dts/tesla/fsd-evb.dts
+++ b/arch/arm64/boot/dts/tesla/fsd-evb.dts
@@ -64,6 +64,16 @@
 	};
 };
 
+&ethernet0 {
+	status = "okay";
+
+	phy-mode = "rgmii-id";
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
 &fin_pll {
 	clock-frequency = <24000000>;
 };
diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
index 3f898cf4874c..cb437483ff6e 100644
--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
@@ -64,6 +64,62 @@
 		samsung,pin-pud = <FSD_PIN_PULL_UP>;
 		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
 	};
+
+	eth0_tx_clk: eth0-tx-clk-pins {
+		samsung,pins = "gpf0-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_DOWN>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_tx_data: eth0-tx-data-pins {
+		samsung,pins = "gpf0-1", "gpf0-2", "gpf0-3", "gpf0-4";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_tx_ctrl: eth0-tx-ctrl-pins {
+		samsung,pins = "gpf0-5";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_phy_intr: eth0-phy-intr-pins {
+		samsung,pins = "gpf0-6";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_NONE>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	eth0_rx_clk: eth0-rx-clk-pins {
+		samsung,pins = "gpf1-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_rx_data: eth0-rx-data-pins {
+		samsung,pins = "gpf1-1", "gpf1-2", "gpf1-3", "gpf1-4";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_rx_ctrl: eth0-rx-ctrl-pins {
+		samsung,pins = "gpf1-5";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth0_mdio: eth0-mdio-pins {
+		samsung,pins = "gpf1-6", "gpf1-7";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_NONE>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
 };
 
 &pinctrl_peric {
diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi b/arch/arm64/boot/dts/tesla/fsd.dtsi
index 690b4ed9c29b..01850fbf761f 100644
--- a/arch/arm64/boot/dts/tesla/fsd.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
@@ -1007,6 +1007,26 @@
 			clocks = <&clock_fsys0 UFS0_MPHY_REFCLK_IXTAL26>;
 			clock-names = "ref_clk";
 		};
+
+		ethernet0: ethernet at 15300000 {
+			compatible = "tesla,fsd-ethqos";
+			reg = <0x0 0x15300000 0x0 0x10000>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			clocks = <&clock_fsys0 FSYS0_EQOS_TOP0_IPCLKPORT_CLK_PTP_REF_I>,
+				 <&clock_fsys0 FSYS0_EQOS_TOP0_IPCLKPORT_ACLK_I>,
+				 <&clock_fsys0 FSYS0_EQOS_TOP0_IPCLKPORT_HCLK_I>,
+				 <&clock_fsys0 FSYS0_EQOS_TOP0_IPCLKPORT_RGMII_CLK_I>,
+				 <&clock_fsys0 FSYS0_EQOS_TOP0_IPCLKPORT_CLK_RX_I>;
+			clock-names = "ptp_ref", "master_bus", "slave_bus", "tx", "rx";
+			pinctrl-names = "default";
+			pinctrl-0 = <&eth0_tx_clk>, <&eth0_tx_data>, <&eth0_tx_ctrl>,
+				    <&eth0_phy_intr>, <&eth0_rx_clk>, <&eth0_rx_data>,
+				    <&eth0_rx_ctrl>, <&eth0_mdio>;
+			local-mac-address = [00 00 00 00 00 00];
+			iommus = <&smmu_fsys0 0x0 0x1>;
+			status = "disabled";
+		};
 	};
 };
 
-- 
2.17.1



From anshuman.khandual at arm.com  Fri Mar  7 01:20:56 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Fri, 7 Mar 2025 14:50:56 +0530
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <17931f83-7142-4ca6-8bfe-466ec53b6e2c@arm.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
 <17931f83-7142-4ca6-8bfe-466ec53b6e2c@arm.com>
Message-ID: <c3dddb6f-dce1-45a6-b5f1-1fd247c510ab@arm.com>



On 3/7/25 14:37, Ryan Roberts wrote:
> On 07/03/2025 05:08, Anshuman Khandual wrote:
>> Address bytes shifted with a single 64 bit page table entry (any page table
>> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
>> is not very readable or easy to reason about. Besides it is going to change
>> with D128, where each 128 bit page table entry will shift address bytes by
>> 4 (aka 2^4 = 16) instead.
>>
>> Let's just formalise this address bytes shift value into a new macro called
>> PTE_SHIFT establishing a logical abstraction, thus improving readability as
>> well. This does not cause any functional change.
>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
>> Cc: Alexander Potapenko <glider at google.com>
>> Cc: Andrey Konovalov <andreyknvl at gmail.com>
>> Cc: Dmitry Vyukov <dvyukov at google.com>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: kasan-dev at googlegroups.com
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> 
> 
> +1 for PTDESC_ORDER

Alright.

> 
> Implementation looks good to me so:
> 
> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

Thanks !

> 
> one nit below.
> 
>> ---
>> This patch applies on v6.14-rc5
>>
>>  arch/arm64/Kconfig                      |  2 +-
>>  arch/arm64/include/asm/kernel-pgtable.h |  3 ++-
>>  arch/arm64/include/asm/pgtable-hwdef.h  | 26 +++++++++++++------------
>>  arch/arm64/kernel/pi/map_range.c        |  2 +-
>>  arch/arm64/mm/kasan_init.c              |  6 +++---
>>  5 files changed, 21 insertions(+), 18 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 940343beb3d4..fd3303f2ccda 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
>>  	default 18
>>  
>>  # max bits determined by the following formula:
>> -#  VA_BITS - PAGE_SHIFT - 3
>> +#  VA_BITS - PAGE_SHIFT - PTE_SHIFT
>>  config ARCH_MMAP_RND_BITS_MAX
>>  	default 19 if ARM64_VA_BITS=36
>>  	default 24 if ARM64_VA_BITS=39
>> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
>> index fd5a08450b12..7150a7a10f00 100644
>> --- a/arch/arm64/include/asm/kernel-pgtable.h
>> +++ b/arch/arm64/include/asm/kernel-pgtable.h
>> @@ -49,7 +49,8 @@
>>  	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
>>  
>>  #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
>> -	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
>> +	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
>> +	lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)
> 
> nit: not sure what style guide says, but I would indent this continuation an
> extra level.

IIUC - An indentation is not normally required with a line continuation although
the starting letter should match the starting letter in the line above but after
the '(' (if any).

> 
> Thanks,
> Ryan
> 
>>  
>>  #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
>>  	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
>> index a9136cc551cc..43f98eac7653 100644
>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>> @@ -7,40 +7,42 @@
>>  
>>  #include <asm/memory.h>
>>  
>> +#define PTE_SHIFT 3
>> +
>>  /*
>>   * Number of page-table levels required to address 'va_bits' wide
>>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
>> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
>> + * bits with (PAGE_SHIFT - PTE_SHIFT) bits at each page table level. Hence:
>>   *
>> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
>> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTE_SHIFT))
>>   *
>>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>>   *
>>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>>   * due to build issues. So we open code DIV_ROUND_UP here:
>>   *
>> - *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
>> + *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTE_SHIFT) - 1) / (PAGE_SHIFT - PTE_SHIFT))
>>   *
>>   * which gets simplified as :
>>   */
>> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
>> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - PTE_SHIFT - 1) / (PAGE_SHIFT - PTE_SHIFT))
>>  
>>  /*
>>   * Size mapped by an entry at level n ( -1 <= n <= 3)
>> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
>> + * We map (PAGE_SHIFT - PTE_SHIFT) at all translation levels and PAGE_SHIFT bits
>>   * in the final page. The maximum number of translation levels supported by
>>   * the architecture is 5. Hence, starting at level n, we have further
>>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>>   * So, the total number of bits mapped by an entry at level n is :
>>   *
>> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
>> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTE_SHIFT) + PAGE_SHIFT
>>   *
>>   * Rearranging it a bit we get :
>> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
>> + *   (4 - n) * (PAGE_SHIFT - PTE_SHIFT) + PTE_SHIFT
>>   */
>> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
>> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTE_SHIFT) * (4 - (n)) + PTE_SHIFT)
>>  
>> -#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTE_SHIFT))
>>  
>>  /*
>>   * PMD_SHIFT determines the size a level 2 page table entry can map.
>> @@ -49,7 +51,7 @@
>>  #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>>  #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
>>  #define PMD_MASK		(~(PMD_SIZE-1))
>> -#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>  
>>  /*
>> @@ -59,14 +61,14 @@
>>  #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>>  #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
>>  #define PUD_MASK		(~(PUD_SIZE-1))
>> -#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>  
>>  #if CONFIG_PGTABLE_LEVELS > 4
>>  #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>>  #define P4D_MASK		(~(P4D_SIZE-1))
>> -#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTE_SHIFT))
>>  #endif
>>  
>>  /*
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 2b69e3beeef8..3530a5427f57 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>  {
>>  	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>>  	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
>> -	int lshift = (3 - level) * (PAGE_SHIFT - 3);
>> +	int lshift = (3 - level) * (PAGE_SHIFT - PTE_SHIFT);
>>  	u64 lmask = (PAGE_SIZE << lshift) - 1;
>>  
>>  	start	&= PAGE_MASK;
>> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
>> index b65a29440a0c..90548079b42e 100644
>> --- a/arch/arm64/mm/kasan_init.c
>> +++ b/arch/arm64/mm/kasan_init.c
>> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>>   */
>>  static bool __init root_level_aligned(u64 addr)
>>  {
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>>  
>>  	return (addr % (PAGE_SIZE << shift)) == 0;
>>  }
>> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>>  	 */
>>  	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>>  							: vabits_actual;
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTE_SHIFT);
>>  
>>  	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>>  }
>> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>>   */
>>  static int __init next_level_idx(u64 addr)
>>  {
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTE_SHIFT);
>>  
>>  	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>>  }
> 


From swathi.ks at samsung.com  Thu Mar  6 20:49:04 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Fri,  7 Mar 2025 10:19:04 +0530
Subject: [PATCH v8 2/2] arm64: dts: fsd: Add Ethernet support for PERIC
 Block of FSD SoC
In-Reply-To: <20250307044904.59077-1-swathi.ks@samsung.com>
References: <20250307044904.59077-1-swathi.ks@samsung.com>
	<CGME20250307045524epcas5p3f4ef3398f70f8286ddd9903a4e1d68f4@epcas5p3.samsung.com>
Message-ID: <20250307044904.59077-3-swathi.ks@samsung.com>

The FSD SoC contains two instances of Synopsys DWC QoS Ethernet IP, one in
FSYS0 block and other in PERIC block.
The ethernet interface is connected to a switch which is not managed by
Linux.

Adds device tree node for Ethernet in PERIC Block and enables the same for
FSD platform.

Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
Signed-off-by: Jayati Sahu <jayati.sahu at samsung.com>
Signed-off-by: Swathi K S <swathi.ks at samsung.com>
---
 arch/arm64/boot/dts/tesla/fsd-evb.dts      | 10 ++++
 arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi | 56 ++++++++++++++++++++++
 arch/arm64/boot/dts/tesla/fsd.dtsi         | 30 ++++++++++++
 3 files changed, 96 insertions(+)

diff --git a/arch/arm64/boot/dts/tesla/fsd-evb.dts b/arch/arm64/boot/dts/tesla/fsd-evb.dts
index 321270a07651..9ff22e1c8723 100644
--- a/arch/arm64/boot/dts/tesla/fsd-evb.dts
+++ b/arch/arm64/boot/dts/tesla/fsd-evb.dts
@@ -74,6 +74,16 @@
 	};
 };
 
+&ethernet1 {
+	status = "okay";
+
+	phy-mode = "rgmii-id";
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
 &fin_pll {
 	clock-frequency = <24000000>;
 };
diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
index cb437483ff6e..6f4658f57453 100644
--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
@@ -437,6 +437,62 @@
 		samsung,pin-pud = <FSD_PIN_PULL_DOWN>;
 		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
 	};
+
+	eth1_tx_clk: eth1-tx-clk-pins {
+		samsung,pins = "gpf2-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_DOWN>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_tx_data: eth1-tx-data-pins {
+		samsung,pins = "gpf2-1", "gpf2-2", "gpf2-3", "gpf2-4";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_tx_ctrl: eth1-tx-ctrl-pins {
+		samsung,pins = "gpf2-5";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_phy_intr: eth1-phy-intr-pins {
+		samsung,pins = "gpf2-6";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	eth1_rx_clk: eth1-rx-clk-pins {
+		samsung,pins = "gpf3-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_rx_data: eth1-rx-data-pins {
+		samsung,pins = "gpf3-1", "gpf3-2", "gpf3-3", "gpf3-4";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_rx_ctrl: eth1-rx-ctrl-pins {
+		samsung,pins = "gpf3-5";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV6>;
+	};
+
+	eth1_mdio: eth1-mdio-pins {
+		samsung,pins = "gpf3-6", "gpf3-7";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
 };
 
 &pinctrl_pmu {
diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi b/arch/arm64/boot/dts/tesla/fsd.dtsi
index 01850fbf761f..0fb1b508be52 100644
--- a/arch/arm64/boot/dts/tesla/fsd.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
@@ -979,6 +979,36 @@
 			memory-region = <&mfc_left>;
 		};
 
+		ethernet1: ethernet at 14300000 {
+			compatible = "tesla,fsd-ethqos";
+			reg = <0x0 0x14300000 0x0 0x10000>;
+			interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			clocks = <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I>,
+				 <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_ACLK_I>,
+				 <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_HCLK_I>,
+				 <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_RGMII_CLK_I>,
+				 <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_RX_I>,
+				 <&clock_peric PERIC_BUS_D_PERIC_IPCLKPORT_EQOSCLK>,
+				 <&clock_peric PERIC_BUS_P_PERIC_IPCLKPORT_EQOSCLK>,
+				 <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
+				 <&clock_peric PERIC_EQOS_PHYRXCLK>,
+				 <&clock_peric PERIC_DOUT_RGMII_CLK>;
+			clock-names = "ptp_ref", "master_bus", "slave_bus", "tx", "rx",
+				      "master2_bus", "slave2_bus", "eqos_rxclk_mux",
+				      "eqos_phyrxclk", "dout_peric_rgmii_clk";
+			assigned-clocks = <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
+					  <&clock_peric PERIC_EQOS_PHYRXCLK>;
+			assigned-clock-parents = <&clock_peric PERIC_EQOS_PHYRXCLK>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&eth1_tx_clk>, <&eth1_tx_data>, <&eth1_tx_ctrl>,
+				    <&eth1_phy_intr>, <&eth1_rx_clk>, <&eth1_rx_data>,
+				    <&eth1_rx_ctrl>, <&eth1_mdio>;
+			local-mac-address = [00 00 00 00 00 00];
+			iommus = <&smmu_peric 0x0 0x1>;
+			status = "disabled";
+		};
+
 		ufs: ufs at 15120000 {
 			compatible = "tesla,fsd-ufs";
 			reg = <0x0 0x15120000 0x0 0x200>,  /* 0: HCI standard */
-- 
2.17.1



From krzysztof.kozlowski at linaro.org  Fri Mar  7 01:33:09 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri,  7 Mar 2025 10:33:09 +0100
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop unnecessary status from example
Message-ID: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>

Device nodes are enabled by default, so no need for 'status = "okay"' in
the DTS example.

Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

---

Changes in v2:
1. Drop unnecessary full stop in subject prefix after ':'.
2. Add Rb tag.
---
 Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
index 757967212f55..ca71b400bcae 100644
--- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
@@ -53,7 +53,6 @@ examples:
         interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
         clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
         resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
-        status = "okay";
       };
     };
 
-- 
2.43.0



From mike.leach at linaro.org  Fri Mar  7 01:28:29 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 7 Mar 2025 09:28:29 +0000
Subject: [PATCH v3 1/7] dt-bindings: arm: Add support for Coresight TGU trace
In-Reply-To: <20250304-certain-aboriginal-magpie-cade86@krzk-bin>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com>
 <20250227092640.2666894-2-quic_songchai@quicinc.com> <20250304-certain-aboriginal-magpie-cade86@krzk-bin>
Message-ID: <CAJ9a7VjOU2d0tGjvbMBWwWtjKp38hj_NptVYFHDy9Zrs-sdOeg@mail.gmail.com>

Hi,

On Tue, 4 Mar 2025 at 08:05, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On Thu, Feb 27, 2025 at 05:26:34PM +0800, songchai wrote:
> > From: Songwei Chai <quic_songchai at quicinc.com>
> >
> > The Trigger Generation Unit (TGU) is designed to detect patterns or
> > sequences within a specific region of the System on Chip (SoC). Once
> > configured and activated, it monitors sense inputs and can detect a
> > pre-programmed state or sequence across clock cycles, subsequently
> > producing a trigger.
> >
> >    TGU configuration space
> >         offset table
> >  x-------------------------x
> >  |                         |
> >  |                         |
> >  |                         |                           Step configuration
> >  |                         |                             space layout
> >  |   coresight management  |                           x-------------x
> >  |        registers        |                     |---> |             |
> >  |                         |                     |     |  reserve    |
> >  |                         |                     |     |             |
> >  |-------------------------|                     |     |-------------|
> >  |                         |                     |     | priority[3] |
> >  |         step[7]         |<--                  |     |-------------|
> >  |-------------------------|   |                 |     | priority[2] |
> >  |                         |   |                 |     |-------------|
> >  |           ...           |   |Steps region     |     | priority[1] |
> >  |                         |   |                 |     |-------------|
> >  |-------------------------|   |                 |     | priority[0] |
> >  |                         |<--                  |     |-------------|
> >  |         step[0]         |-------------------->      |             |
> >  |-------------------------|                           |  condition  |
> >  |                         |                           |             |
> >  |     control and status  |                           x-------------x
> >  |           space         |                           |             |
> >  x-------------------------x                           |Timer/Counter|
> >                                                        |             |
> >                                                      x-------------x
> > TGU Configuration in Hardware
> >
> > The TGU provides a step region for user configuration, similar
> > to a flow chart. Each step region consists of three register clusters:
> >
> > 1.Priority Region: Sets the required signals with priority.
> > 2.Condition Region: Defines specific requirements (e.g., signal A
> > reaches three times) and the subsequent action once the requirement is
> > met.
> > 3.Timer/Counter (Optional): Provides timing or counting functionality.
> >
> > Add a new coresight-tgu.yaml file to describe the bindings required to
> > define the TGU in the device trees.
> >
> > Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> > Signed-off-by: songchai <quic_songchai at quicinc.com>
>
> Don't duplicate yourself.
>
> Anyway, this is marked as v3, I cannot find previous versions, no
> changelog, no references.
>
> What happened here in this binding?
>
> > ---
> >  .../bindings/arm/qcom,coresight-tgu.yaml      | 135 ++++++++++++++++++
> >  1 file changed, 135 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> > new file mode 100644
> > index 000000000000..a41ac68a4fe7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> > @@ -0,0 +1,135 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> > +# Copyright (c) 2023-2025 Qualcomm Innovation Center, Inc. All rights reserved.
>
> 2023 and 2024? Where was it published in these years?
>
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/qcom,coresight-tgu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Trigger Generation Unit - TGU
> > +
> > +description: |
> > +  The Trigger Generation Unit (TGU) is a Data Engine which can be utilized
> > +  to sense a plurality of signals and create a trigger into the CTI or
> > +  generate interrupts to processors. The TGU is like the trigger circuit
> > +  of a Logic Analyzer. The corresponding trigger logic can be realized by
> > +  configuring the conditions for each step after sensing the signal.
> > +  Once setup and enabled, it will observe sense inputs and based upon
> > +  the activity of those inputs, even over clock cycles, may detect a
> > +  preprogrammed state/sequence and then produce a trigger or interrupt.
> > +
> > +  The primary use case of the TGU is to detect patterns or sequences on a
> > +  given set of signals within some region of the SoC.
> > +
> > +maintainers:
> > +  - Mao Jinlong <quic_jinlmao at quicinc.com>
> > +  - Sam Chai <quic_songchai at quicinc.com>
> > +
> > +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        enum:
> > +          - qcom,coresight-tgu
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - const: qcom,coresight-tgu
> > +      - const: arm,primecell
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    maxItems: 1
> > +
> > +  clock-names:
> > +    items:
> > +      - const: apb_pclk
> > +
> > +  qcom,tgu-steps:
> > +    description:
> > +      The trigger logic is realized by configuring each step after sensing
> > +      the signal. The parameter here is used to describe the maximum of steps
> > +      that could be configured in the current TGU.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 1
> > +    maximum: 8
> > +

Hardware features are usually defined by ID registers in coresight
devices. e.g. ETM has a number of ID registers that describe the
number of comparators / counters etc.
Does this device not have similar registers? Is there not a unique ID
for each hardware variant - hardware discoverablility is an
architecture requirement for coresight devices?

> > +  qcom,tgu-regs:
> > +    description:
> > +      There are some "groups" register clusters in each step, which are used to
> > +      configure the signal that we want to detect. Meanwhile, each group has its
> > +      own priority, and the priority increases with number of groups. For example,
> > +      group3 has a higher priority than group2, the signal configured in group3
> > +      will be sensed more preferentially than the signal which is configured in group2.
> > +      The parameter here is used to describe the signal number that each group
> > +      could be configured.
>
> And all groups are indexed by number? Or do they have names?
>
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 1
> > +    maximum: 18
> > +
> > +  qcom,tgu-conditions:
> > +    description:
> > +      A condition sets a specific requirement for a step and defines the subsequent
> > +      action once the requirement is met. For example, in step two, if signal A is
> > +      detected three times, the process jumps back to step one. The parameter describes
> > +      the register number for each functionality, whether it is setting a specific
> > +      requirement or defining a subsequent action.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 1
> > +    maximum: 4
> > +
> > +  qcom,tgu-timer-counters:
> > +    description:
> > +      TGU has timer and counter which are used to set some requirement on each step.
>
> Wrap according to Linux coding style, so at 80.
>
> > +      For example, we could use counter to create a trigger into CTI once TGU senses
> > +      the target signal three times.This parameter is used to describe the number of
> > +      Timers/Counters in TGU.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 0
>
> Drop
>
> > +    maximum: 2
> > +
> > +  in-ports:
> > +    $ref: /schemas/graph.yaml#/properties/ports
> > +    additionalProperties: false
> > +
> > +    properties:
> > +      port:
> > +        description: AXI Slave connected to another Coresight component
>
> So this TGU can be connected to anything in coresight graph, no
> restrictions?
>


Coresight uses APB for register access and ATB for moving trace from
source to sink. The only use of AXI is on the ETR/CATU output saving
trace data into system memory.

> > +        $ref: /schemas/graph.yaml#/properties/port
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
>
> Most likely you miss also: in-ports
>
>
> Best regards,
> Krzysztof
>

Regards

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From heiko at sntech.de  Fri Mar  7 01:28:55 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Fri, 07 Mar 2025 10:28:55 +0100
Subject: [PATCH] dt-bindings: rng: rockchip,rk3588-rng.: Drop unnecessary status
 from example
In-Reply-To: <20250307081406.35242-1-krzysztof.kozlowski@linaro.org>
References: <20250307081406.35242-1-krzysztof.kozlowski@linaro.org>
Message-ID: <5865714.DvuYhMxLoT@diego>

Am Freitag, 7. M?rz 2025, 09:14:06 MEZ schrieb Krzysztof Kozlowski:
> Device nodes are enabled by default, so no need for 'status = "okay"' in
> the DTS example.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> ---
>  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> index 757967212f55..ca71b400bcae 100644
> --- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> +++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> @@ -53,7 +53,6 @@ examples:
>          interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
>          clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
>          resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
> -        status = "okay";
>        };
>      };
>  
> 






From linyunsheng at huawei.com  Fri Mar  7 01:23:52 2025
From: linyunsheng at huawei.com (Yunsheng Lin)
Date: Fri, 7 Mar 2025 17:23:52 +0800
Subject: [PATCH net-next v11 1/4] page_pool: introduce page_pool_get_pp() API
In-Reply-To: <20250307092356.638242-1-linyunsheng@huawei.com>
References: <20250307092356.638242-1-linyunsheng@huawei.com>
Message-ID: <20250307092356.638242-2-linyunsheng@huawei.com>

Introduce page_pool_get_pp() API to avoid caller accessing
page->pp directly, in order to make the following patch more
reviewable as the following patch will change page->pp to
page->pp_item to fix the DMA API misuse problem.

Signed-off-by: Yunsheng Lin <linyunsheng at huawei.com>
---
 drivers/net/ethernet/freescale/fec_main.c          |  8 +++++---
 .../net/ethernet/google/gve/gve_buffer_mgmt_dqo.c  |  2 +-
 drivers/net/ethernet/intel/iavf/iavf_txrx.c        |  6 ++++--
 drivers/net/ethernet/intel/idpf/idpf_txrx.c        | 14 +++++++++-----
 drivers/net/ethernet/intel/libeth/rx.c             |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c   |  3 ++-
 drivers/net/netdevsim/netdev.c                     |  6 ++++--
 drivers/net/wireless/mediatek/mt76/mt76.h          |  2 +-
 include/net/libeth/rx.h                            |  3 ++-
 include/net/page_pool/helpers.h                    |  5 +++++
 10 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index a86cfebedaa8..4ade1553557a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1038,7 +1038,8 @@ static void fec_enet_bd_init(struct net_device *dev)
 				struct page *page = txq->tx_buf[i].buf_p;
 
 				if (page)
-					page_pool_put_page(page->pp, page, 0, false);
+					page_pool_put_page(page_pool_get_pp(page),
+							   page, 0, false);
 			}
 
 			txq->tx_buf[i].buf_p = NULL;
@@ -1576,7 +1577,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
 			xdp_return_frame_rx_napi(xdpf);
 		} else { /* recycle pages of XDP_TX frames */
 			/* The dma_sync_size = 0 as XDP_TX has already synced DMA for_device */
-			page_pool_put_page(page->pp, page, 0, true);
+			page_pool_put_page(page_pool_get_pp(page), page, 0, true);
 		}
 
 		txq->tx_buf[index].buf_p = NULL;
@@ -3343,7 +3344,8 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 			} else {
 				struct page *page = txq->tx_buf[i].buf_p;
 
-				page_pool_put_page(page->pp, page, 0, false);
+				page_pool_put_page(page_pool_get_pp(page),
+						   page, 0, false);
 			}
 
 			txq->tx_buf[i].buf_p = NULL;
diff --git a/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
index 403f0f335ba6..87422b8828ff 100644
--- a/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
@@ -210,7 +210,7 @@ void gve_free_to_page_pool(struct gve_rx_ring *rx,
 	if (!page)
 		return;
 
-	page_pool_put_full_page(page->pp, page, allow_direct);
+	page_pool_put_full_page(page_pool_get_pp(page), page, allow_direct);
 	buf_state->page_info.page = NULL;
 }
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
index 422312b8b54a..72f17eaac277 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -1197,7 +1197,8 @@ static void iavf_add_rx_frag(struct sk_buff *skb,
 			     const struct libeth_fqe *rx_buffer,
 			     unsigned int size)
 {
-	u32 hr = rx_buffer->page->pp->p.offset;
+	struct page_pool *pool = page_pool_get_pp(rx_buffer->page);
+	u32 hr = pool->p.offset;
 
 	skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page,
 			rx_buffer->offset + hr, size, rx_buffer->truesize);
@@ -1214,7 +1215,8 @@ static void iavf_add_rx_frag(struct sk_buff *skb,
 static struct sk_buff *iavf_build_skb(const struct libeth_fqe *rx_buffer,
 				      unsigned int size)
 {
-	u32 hr = rx_buffer->page->pp->p.offset;
+	struct page_pool *pool = page_pool_get_pp(rx_buffer->page);
+	u32 hr = pool->p.offset;
 	struct sk_buff *skb;
 	void *va;
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index bdf52cef3891..0ce77a5559aa 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -385,7 +385,8 @@ static void idpf_rx_page_rel(struct libeth_fqe *rx_buf)
 	if (unlikely(!rx_buf->page))
 		return;
 
-	page_pool_put_full_page(rx_buf->page->pp, rx_buf->page, false);
+	page_pool_put_full_page(page_pool_get_pp(rx_buf->page), rx_buf->page,
+				false);
 
 	rx_buf->page = NULL;
 	rx_buf->offset = 0;
@@ -3096,7 +3097,8 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb,
 void idpf_rx_add_frag(struct idpf_rx_buf *rx_buf, struct sk_buff *skb,
 		      unsigned int size)
 {
-	u32 hr = rx_buf->page->pp->p.offset;
+	struct page_pool *pool = page_pool_get_pp(rx_buf->page);
+	u32 hr = pool->p.offset;
 
 	skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buf->page,
 			rx_buf->offset + hr, size, rx_buf->truesize);
@@ -3128,8 +3130,10 @@ static u32 idpf_rx_hsplit_wa(const struct libeth_fqe *hdr,
 	if (!libeth_rx_sync_for_cpu(buf, copy))
 		return 0;
 
-	dst = page_address(hdr->page) + hdr->offset + hdr->page->pp->p.offset;
-	src = page_address(buf->page) + buf->offset + buf->page->pp->p.offset;
+	dst = page_address(hdr->page) + hdr->offset +
+		page_pool_get_pp(hdr->page)->p.offset;
+	src = page_address(buf->page) + buf->offset +
+		page_pool_get_pp(buf->page)->p.offset;
 	memcpy(dst, src, LARGEST_ALIGN(copy));
 
 	buf->offset += copy;
@@ -3147,7 +3151,7 @@ static u32 idpf_rx_hsplit_wa(const struct libeth_fqe *hdr,
  */
 struct sk_buff *idpf_rx_build_skb(const struct libeth_fqe *buf, u32 size)
 {
-	u32 hr = buf->page->pp->p.offset;
+	u32 hr = page_pool_get_pp(buf->page)->p.offset;
 	struct sk_buff *skb;
 	void *va;
 
diff --git a/drivers/net/ethernet/intel/libeth/rx.c b/drivers/net/ethernet/intel/libeth/rx.c
index 66d1d23b8ad2..8de0c3a3b146 100644
--- a/drivers/net/ethernet/intel/libeth/rx.c
+++ b/drivers/net/ethernet/intel/libeth/rx.c
@@ -207,7 +207,7 @@ EXPORT_SYMBOL_NS_GPL(libeth_rx_fq_destroy, "LIBETH");
  */
 void libeth_rx_recycle_slow(struct page *page)
 {
-	page_pool_recycle_direct(page->pp, page);
+	page_pool_recycle_direct(page_pool_get_pp(page), page);
 }
 EXPORT_SYMBOL_NS_GPL(libeth_rx_recycle_slow, "LIBETH");
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index 6f3094a479e1..b6bee95db994 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -709,7 +709,8 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq,
 				/* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE)
 				 * as we know this is a page_pool page.
 				 */
-				page_pool_recycle_direct(page->pp, page);
+				page_pool_recycle_direct(page_pool_get_pp(page),
+							 page);
 			} while (++n < num);
 
 			break;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 54d03b0628d2..769fbea8ccf0 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -847,7 +847,8 @@ nsim_pp_hold_write(struct file *file, const char __user *data,
 		if (!ns->page)
 			ret = -ENOMEM;
 	} else {
-		page_pool_put_full_page(ns->page->pp, ns->page, false);
+		page_pool_put_full_page(page_pool_get_pp(ns->page), ns->page,
+					false);
 		ns->page = NULL;
 	}
 
@@ -1059,7 +1060,8 @@ void nsim_destroy(struct netdevsim *ns)
 
 	/* Put this intentionally late to exercise the orphaning path */
 	if (ns->page) {
-		page_pool_put_full_page(ns->page->pp, ns->page, false);
+		page_pool_put_full_page(page_pool_get_pp(ns->page), ns->page,
+					false);
 		ns->page = NULL;
 	}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b107..11a88ecf8533 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1777,7 +1777,7 @@ static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
 {
 	struct page *page = virt_to_head_page(buf);
 
-	page_pool_put_full_page(page->pp, page, allow_direct);
+	page_pool_put_full_page(page_pool_get_pp(page), page, allow_direct);
 }
 
 static inline void *
diff --git a/include/net/libeth/rx.h b/include/net/libeth/rx.h
index ab05024be518..2a3991d5b7c0 100644
--- a/include/net/libeth/rx.h
+++ b/include/net/libeth/rx.h
@@ -137,7 +137,8 @@ static inline bool libeth_rx_sync_for_cpu(const struct libeth_fqe *fqe,
 		return false;
 	}
 
-	page_pool_dma_sync_for_cpu(page->pp, page, fqe->offset, len);
+	page_pool_dma_sync_for_cpu(page_pool_get_pp(page), page, fqe->offset,
+				   len);
 
 	return true;
 }
diff --git a/include/net/page_pool/helpers.h b/include/net/page_pool/helpers.h
index 582a3d00cbe2..ab91911af215 100644
--- a/include/net/page_pool/helpers.h
+++ b/include/net/page_pool/helpers.h
@@ -83,6 +83,11 @@ static inline u64 *page_pool_ethtool_stats_get(u64 *data, const void *stats)
 }
 #endif
 
+static inline struct page_pool *page_pool_get_pp(struct page *page)
+{
+	return page->pp;
+}
+
 /**
  * page_pool_dev_alloc_pages() - allocate a page.
  * @pool:	pool from which to allocate
-- 
2.33.0



From linyunsheng at huawei.com  Fri Mar  7 01:23:51 2025
From: linyunsheng at huawei.com (Yunsheng Lin)
Date: Fri, 7 Mar 2025 17:23:51 +0800
Subject: [PATCH net-next v11 0/4] fix the DMA API misuse problem for page_pool
Message-ID: <20250307092356.638242-1-linyunsheng@huawei.com>

This patchset fix the dma API misuse problem as below:
Networking driver with page_pool support may hand over page
still with dma mapping to network stack and try to reuse that
page after network stack is done with it and passes it back
to page_pool to avoid the penalty of dma mapping/unmapping.
With all the caching in the network stack, some pages may be
held in the network stack without returning to the page_pool
soon enough, and with VF disable causing the driver unbound,
the page_pool does not stop the driver from doing it's
unbounding work, instead page_pool uses workqueue to check
if there is some pages coming back from the network stack
periodically, if there is any, it will do the dma unmmapping
related cleanup work.

As mentioned in [1], attempting DMA unmaps after the driver
has already unbound may leak resources or at worst corrupt
memory. Fundamentally, the page pool code cannot allow DMA
mappings to outlive the driver they belong to.

By using the 'struct page_pool_item' referenced by page->pp_item,
page_pool is not only able to keep track of the inflight page to
do dma unmmaping if some pages are still handled in networking
stack when page_pool_destroy() is called, and networking stack is
also able to find the page_pool owning the page when returning
pages back into page_pool:
1. When a page is added to the page_pool, an item is deleted from
   pool->hold_items and set the 'pp_netmem' pointing to that page
   and set item->state and item->pp_netmem accordingly in order to
   keep track of that page, refill from pool->release_items when
   pool->hold_items is empty or use the item from pool->slow_items
   when fast items run out.
2. When a page is released from the page_pool, it is able to tell
   which page_pool this page belongs to by masking off the lower
   bits of the pointer to page_pool_item *item, as the 'struct
   page_pool_item_block' is stored in the top of a struct page.
   And after clearing the pp_item->state', the item for the
   released page is added back to pool->release_items so that it
   can be reused for new pages or just free it when it is from the
   pool->slow_items.
3. When page_pool_destroy() is called, item->state is used to tell
   if a specific item is being used/dma mapped or not by scanning
   all the item blocks in pool->item_blocks, then item->netmem can
   be used to do the dma unmmaping if the corresponding inflight
   page is dma mapped.

>From the below performance data, the overhead is not so obvious
due to performance variations in arm64 server and less than 1
ns in x86 server for time_bench_page_pool01_fast_path() and
time_bench_page_pool02_ptr_ring, and there is about 10~20ns
overhead for time_bench_page_pool03_slow(), see more detail in
[2].

arm64 server:
Before this patchset:
              fast_path              ptr_ring            slow
1.         31.171 ns               60.980 ns          164.917 ns
2.         28.824 ns               60.891 ns          170.241 ns
3.         14.236 ns               60.583 ns          164.355 ns

With patchset:
6.         26.163 ns               53.781 ns          189.450 ns
7.         26.189 ns               53.798 ns          189.466 ns

X86 server:
| Test name  |Cycles |   1-5 |    | Nanosec |    1-5 |        |      % |
| (tasklet_*)|Before | After |diff|  Before |  After |   diff | change |
|------------+-------+-------+----+---------+--------+--------+--------|
| fast_path  |    19 |    19 |   0|   5.399 |  5.492 |  0.093 |    1.7 |
| ptr_ring   |    54 |    57 |   3|  15.090 | 15.849 |  0.759 |    5.0 |
| slow       |   238 |   284 |  46|  66.134 | 78.909 | 12.775 |   19.3 |

And about 16 bytes of memory is also needed for each page_pool owned
page to fix the dma API misuse problem

1. https://lore.kernel.org/lkml/8067f204-1380-4d37-8ffd-007fc6f26738 at kernel.org/T/
2. https://lore.kernel.org/all/f558df7a-d983-4fc5-8358-faf251994d23 at kernel.org/

CC: Alexander Lobakin <aleksander.lobakin at intel.com>
CC: Robin Murphy <robin.murphy at arm.com>
CC: Alexander Duyck <alexander.duyck at gmail.com>
CC: Andrew Morton <akpm at linux-foundation.org>
CC: Gaurav Batra <gbatra at linux.ibm.com>
CC: Matthew Rosato <mjrosato at linux.ibm.com>
CC: IOMMU <iommu at lists.linux.dev>
CC: MM <linux-mm at kvack.org>

Change log:
V11:
  1. Rebase on the latest net-next.
  2. Fix two compiler errors reported by Jakub and Simon.
  3. Change to use __acquire() and __release() to avoid 'context
     imbalance' warning.

V10:
  1. Add nl API to dump item memory usage.
  2. Use __acquires() and __releases() to avoid 'context imbalance'
     warning.

V9.
  1. Drop the fix of a possible time window problem for NPAI recycling.
  2. Add design description for the fix in patch 2.

V8:
  1. Drop last 3 patch as it causes observable performance degradation
     for x86 system.
  2. Remove rcu read lock in page_pool_napi_local().
  3. Renaming item function more consistently.

V7:
  1. Fix a used-after-free bug reported by KASAN as mentioned by Jakub.
  2. Fix the 'netmem' variable not setting up correctly bug as mentioned
     by Simon.

V6:
  1. Repost based on latest net-next.
  2. Rename page_pool_to_pp() to page_pool_get_pp().

V5:
  1. Support unlimit inflight pages.
  2. Add some optimization to avoid the overhead of fixing bug.

V4:
  1. use scanning to do the unmapping
  2. spilt dma sync skipping into separate patch

V3:
  1. Target net-next tree instead of net tree.
  2. Narrow the rcu lock as the discussion in v2.
  3. Check the ummapping cnt against the inflight cnt.

V2:
  1. Add a item_full stat.
  2. Use container_of() for page_pool_to_pp().

Yunsheng Lin (4):
  page_pool: introduce page_pool_get_pp() API
  page_pool: fix IOMMU crash when driver has already unbound
  page_pool: support unlimited number of inflight pages
  page_pool: skip dma sync operation for inflight pages

 Documentation/netlink/specs/netdev.yaml       |  16 +
 drivers/net/ethernet/freescale/fec_main.c     |   8 +-
 .../ethernet/google/gve/gve_buffer_mgmt_dqo.c |   2 +-
 drivers/net/ethernet/intel/iavf/iavf_txrx.c   |   6 +-
 drivers/net/ethernet/intel/idpf/idpf_txrx.c   |  14 +-
 drivers/net/ethernet/intel/libeth/rx.c        |   2 +-
 .../marvell/octeontx2/nic/otx2_txrx.c         |   2 +-
 .../net/ethernet/mellanox/mlx5/core/en/xdp.c  |   3 +-
 drivers/net/netdevsim/netdev.c                |   6 +-
 drivers/net/wireless/mediatek/mt76/mt76.h     |   2 +-
 include/linux/mm_types.h                      |   2 +-
 include/linux/skbuff.h                        |   1 +
 include/net/libeth/rx.h                       |   3 +-
 include/net/netmem.h                          |  31 +-
 include/net/page_pool/helpers.h               |  15 +
 include/net/page_pool/memory_provider.h       |   2 +-
 include/net/page_pool/types.h                 |  46 +-
 include/uapi/linux/netdev.h                   |   2 +
 net/core/devmem.c                             |   6 +-
 net/core/netmem_priv.h                        |   5 +-
 net/core/page_pool.c                          | 426 ++++++++++++++++--
 net/core/page_pool_priv.h                     |  12 +-
 net/core/page_pool_user.c                     |  39 +-
 tools/include/uapi/linux/netdev.h             |   2 +
 tools/net/ynl/samples/page-pool.c             |  11 +
 25 files changed, 576 insertions(+), 88 deletions(-)

-- 
2.33.0



From aliceryhl at google.com  Fri Mar  7 01:34:15 2025
From: aliceryhl at google.com (Alice Ryhl)
Date: Fri, 7 Mar 2025 09:34:15 +0000
Subject: [PATCH] firmware: arm_scmi: Balance device refcount when
 destroying devices
In-Reply-To: <20250306185447.2039336-1-cristian.marussi@arm.com>
References: <20250306185447.2039336-1-cristian.marussi@arm.com>
Message-ID: <Z8q9l0vDTLpbo8UR@google.com>

On Thu, Mar 06, 2025 at 06:54:47PM +0000, Cristian Marussi wrote:
> Using device_find_child() to lookup the proper SCMI device to destroy
> causes an unbalance in device refcount, since device_find_child() calls an
> implicit get_device(): this, in turns, inhibits the call of the provided
> release methods upon devices destruction.
> 
> As a consequence, one of the structures that is not freed properly upon
> destruction is the internal struct device_private dev->p populated by the
> drivers subsystem core.
> 
> KMemleak detects this situation since loading/unloding some SCMI driver
> causes related devices to be created/destroyed without calling any
> device_release method.
> 
> unreferenced object 0xffff00000f583800 (size 512):
>   comm "insmod", pid 227, jiffies 4294912190
>   hex dump (first 32 bytes):
>     00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
>     ff ff ff ff ff ff ff ff 60 36 1d 8a 00 80 ff ff  ........`6......
>   backtrace (crc 114e2eed):
>     kmemleak_alloc+0xbc/0xd8
>     __kmalloc_cache_noprof+0x2dc/0x398
>     device_add+0x954/0x12d0
>     device_register+0x28/0x40
>     __scmi_device_create.part.0+0x1bc/0x380
>     scmi_device_create+0x2d0/0x390
>     scmi_create_protocol_devices+0x74/0xf8
>     scmi_device_request_notifier+0x1f8/0x2a8
>     notifier_call_chain+0x110/0x3b0
>     blocking_notifier_call_chain+0x70/0xb0
>     scmi_driver_register+0x350/0x7f0
>     0xffff80000a3b3038
>     do_one_initcall+0x12c/0x730
>     do_init_module+0x1dc/0x640
>     load_module+0x4b20/0x5b70
>     init_module_from_file+0xec/0x158
> 
> $ ./scripts/faddr2line ./vmlinux device_add+0x954/0x12d0
> device_add+0x954/0x12d0:
> kmalloc_noprof at include/linux/slab.h:901
> (inlined by) kzalloc_noprof at include/linux/slab.h:1037
> (inlined by) device_private_init at drivers/base/core.c:3510
> (inlined by) device_add at drivers/base/core.c:3561
> 
> Balance device refcount by issuing a put_device() on devices found via
> device_find_child().
> 
> Reported-by: Alice Ryhl <aliceryhl at google.com>
> Closes: https://lore.kernel.org/linux-arm-kernel/Z8nK3uFkspy61yjP at arm.com/T/#mc1f73a0ea5e41014fa145147b7b839fc988ada8f
> CC: Sudeep Holla <sudeep.holla at arm.com>
> CC: Catalin Marinas <catalin.marinas at arm.com>
> Fixes: d4f9dddd21f3 ("firmware: arm_scmi: Add dynamic scmi devices creation")
> Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>

I was not able to reproduce the memory leak after applying this patch.

Tested-by: Alice Ryhl <aliceryhl at google.com>


From cristian.marussi at arm.com  Fri Mar  7 01:39:34 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Fri, 7 Mar 2025 09:39:34 +0000
Subject: [PATCH] firmware: arm_scmi: Balance device refcount when
 destroying devices
In-Reply-To: <Z8q9l0vDTLpbo8UR@google.com>
References: <20250306185447.2039336-1-cristian.marussi@arm.com>
 <Z8q9l0vDTLpbo8UR@google.com>
Message-ID: <Z8q-1jOng_nYP445@pluto>

On Fri, Mar 07, 2025 at 09:34:15AM +0000, Alice Ryhl wrote:
> On Thu, Mar 06, 2025 at 06:54:47PM +0000, Cristian Marussi wrote:
> > Using device_find_child() to lookup the proper SCMI device to destroy
> > causes an unbalance in device refcount, since device_find_child() calls an
> > implicit get_device(): this, in turns, inhibits the call of the provided
> > release methods upon devices destruction.
> > 
> > As a consequence, one of the structures that is not freed properly upon
> > destruction is the internal struct device_private dev->p populated by the
> > drivers subsystem core.
> > 
> > KMemleak detects this situation since loading/unloding some SCMI driver
> > causes related devices to be created/destroyed without calling any
> > device_release method.
> > 
> > unreferenced object 0xffff00000f583800 (size 512):
> >   comm "insmod", pid 227, jiffies 4294912190
> >   hex dump (first 32 bytes):
> >     00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00  .....N..........
> >     ff ff ff ff ff ff ff ff 60 36 1d 8a 00 80 ff ff  ........`6......
> >   backtrace (crc 114e2eed):
> >     kmemleak_alloc+0xbc/0xd8
> >     __kmalloc_cache_noprof+0x2dc/0x398
> >     device_add+0x954/0x12d0
> >     device_register+0x28/0x40
> >     __scmi_device_create.part.0+0x1bc/0x380
> >     scmi_device_create+0x2d0/0x390
> >     scmi_create_protocol_devices+0x74/0xf8
> >     scmi_device_request_notifier+0x1f8/0x2a8
> >     notifier_call_chain+0x110/0x3b0
> >     blocking_notifier_call_chain+0x70/0xb0
> >     scmi_driver_register+0x350/0x7f0
> >     0xffff80000a3b3038
> >     do_one_initcall+0x12c/0x730
> >     do_init_module+0x1dc/0x640
> >     load_module+0x4b20/0x5b70
> >     init_module_from_file+0xec/0x158
> > 
> > $ ./scripts/faddr2line ./vmlinux device_add+0x954/0x12d0
> > device_add+0x954/0x12d0:
> > kmalloc_noprof at include/linux/slab.h:901
> > (inlined by) kzalloc_noprof at include/linux/slab.h:1037
> > (inlined by) device_private_init at drivers/base/core.c:3510
> > (inlined by) device_add at drivers/base/core.c:3561
> > 
> > Balance device refcount by issuing a put_device() on devices found via
> > device_find_child().
> > 
> > Reported-by: Alice Ryhl <aliceryhl at google.com>
> > Closes: https://lore.kernel.org/linux-arm-kernel/Z8nK3uFkspy61yjP at arm.com/T/#mc1f73a0ea5e41014fa145147b7b839fc988ada8f
> > CC: Sudeep Holla <sudeep.holla at arm.com>
> > CC: Catalin Marinas <catalin.marinas at arm.com>
> > Fixes: d4f9dddd21f3 ("firmware: arm_scmi: Add dynamic scmi devices creation")
> > Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
> 
> I was not able to reproduce the memory leak after applying this patch.
> 
> Tested-by: Alice Ryhl <aliceryhl at google.com>

Thanks a lot for testing (and for the report) !

Cristian



From sakari.ailus at linux.intel.com  Fri Mar  7 01:49:12 2025
From: sakari.ailus at linux.intel.com (Sakari Ailus)
Date: Fri, 7 Mar 2025 09:49:12 +0000
Subject: [PATCH v5 03/11] media: dt-bindings: media: add bindings for
 rockchip rk3568 vicap
In-Reply-To: <20250307-pink-dalmatian-of-kindness-f87ad2@krzk-bin>
References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net>
 <20250306-v6-8-topic-rk3568-vicap-v5-3-f02152534f3c@wolfvision.net>
 <20250307-pink-dalmatian-of-kindness-f87ad2@krzk-bin>
Message-ID: <Z8rBGHK9Tjx7D1D2@kekkonen.localdomain>

Hi Krzysztof, Michael,

On Fri, Mar 07, 2025 at 08:51:54AM +0100, Krzysztof Kozlowski wrote:
> On Thu, Mar 06, 2025 at 05:56:04PM +0100, Michael Riesch wrote:
> > Add documentation for the Rockchip RK3568 Video Capture (VICAP) unit.
> > 
> > Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> 
> subject: only one media prefix, the first
> 
> A nit, subject: drop second/last, redundant "bindings". The
> "dt-bindings" prefix is already stating that these are bindings.
> See also:
> https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
> 
> > ---
> >  .../bindings/media/rockchip,rk3568-vicap.yaml      | 169 +++++++++++++++++++++
> >  MAINTAINERS                                        |   1 +
> >  2 files changed, 170 insertions(+)
> > 
> 
> ...
> 
> > +  clocks:
> > +    items:
> > +      - description: ACLK
> > +      - description: HCLK
> > +      - description: DCLK
> > +      - description: ICLK
> > +
> > +  clock-names:
> > +    items:
> > +      - const: aclk
> > +      - const: hclk
> > +      - const: dclk
> > +      - const: iclk
> > +
> > +  rockchip,cif-clk-delaynum:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 0
> > +    maximum: 127
> > +    description:
> > +      Delay the DVP path clock input to align the sampling phase, only valid
> > +      in dual edge sampling mode. Delay is zero by default and can be adjusted
> > +      optionally.
> 
> default: 0

And this is technically specific to the DVP port (0). Should (or could?) it
be located there?

> 
> > +
> > +  iommus:
> > +    maxItems: 1
> > +
> > +  resets:
> > +    items:
> > +      - description: ARST
> > +      - description: HRST
> > +      - description: DRST
> > +      - description: PRST
> > +      - description: IRST
> > +
> > +  reset-names:
> > +    items:
> > +      - const: arst
> > +      - const: hrst
> > +      - const: drst
> > +      - const: prst
> > +      - const: irst
> > +
> > +  rockchip,grf:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: Phandle to general register file used for video input block control.
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +  ports:
> > +    $ref: /schemas/graph.yaml#/properties/ports
> > +
> > +    properties:
> > +      port at 0:
> > +        $ref: /schemas/graph.yaml#/$defs/port-base
> > +        unevaluatedProperties: false
> > +        description: The digital video port (DVP, a parallel video interface).
> > +
> > +        properties:
> > +          endpoint:
> > +            $ref: video-interfaces.yaml#
> > +            unevaluatedProperties: false
> > +
> > +            properties:
> > +              bus-type:
> > +                enum: [5, 6]
> > +
> > +            required:
> > +              - bus-type
> > +
> > +      port at 1:
> > +        $ref: /schemas/graph.yaml#/properties/port
> > +        description: Internal port connected to a MIPI CSI-2 host.
> > +
> > +        properties:
> > +          endpoint:
> > +            $ref: video-interfaces.yaml#
> > +            unevaluatedProperties: false
> 
> Hm, does it actually work? graph/port does not allow any other
> properties. You should use graph/port-base and probably still narrow
> lanes for both of port at 0 and port at 1.

I'd list the relevant properties for both DVP and CSI-2, either as
mandatory or with defaults (could be reasonable for DVP signal polarities
but not e.g. on number of CSI-2 lanes).

> 
> 
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +  - clocks
> > +  - ports
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/rk3568-cru.h>
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +    #include <dt-bindings/power/rk3568-power.h>
> > +    #include <dt-bindings/media/video-interfaces.h>
> > +
> > +    parent {
> 
> soc {
> 
> > +        #address-cells = <2>;
> > +        #size-cells = <2>;
> 
> Best regards,
> Krzysztof
> 

-- 
Kind regards,

Sakari Ailus


From sudeep.holla at arm.com  Fri Mar  7 01:50:26 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 7 Mar 2025 09:50:26 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <20250307080303.2660506-1-ping.bai@nxp.com>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
Message-ID: <Z8rBYuDiIyo8y6HT@bogus>

On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> for_each_possible_cpu() is currently used to initialize cpuidle
> in below cpuidle drivers:
>   drivers/cpuidle/cpuidle-arm.c
>   drivers/cpuidle/cpuidle-big_little.c
>   drivers/cpuidle/cpuidle-psci.c
>   drivers/cpuidle/cpuidle-riscv-sbi.c
> 
> However, in cpu_dev_register_generic(), for_each_present_cpu()
> is used to register CPU devices which means the CPU devices are
> only registered for present CPUs and not all possible CPUs.
> 
> With nosmp or maxcpus=0, only the boot CPU is present, lead
> to the failure:
> 
>   |  Failed to register cpuidle device for cpu1
> 
> Then rollback to cancel all CPUs' cpuidle registration.
> 
> Change for_each_possible_cpu() to for_each_present_cpu() in the
> above cpuidle drivers to ensure it only registers cpuidle devices
> for CPUs that are actually present.
> 
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Reviewed-by: Dhruva Gole <d-gole at ti.com>
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v4 changes:
>   - add changes for other cpuidle driver that has the similar issue
>     as cpuidle-pcsi driver.
> 
>  - v3 changes:
>   - improve the changelog as suggested by Sudeep
> ---
>  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
>  drivers/cpuidle/cpuidle-big_little.c | 2 +-
>  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
>  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--


Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC the issue
exists there as well.

-- 
Regards,
Sudeep


From amadeus at jmu.edu.cn  Fri Mar  7 02:00:07 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 18:00:07 +0800
Subject: [PATCH v3 0/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
Message-ID: <20250307100008.789129-1-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of standard ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

dmesg:
[    0.061333] scmi_core: SCMI protocol bus registered
[    0.125780] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
[    0.126628] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
[    0.127233] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0

CPU frequency: ~# mhz
count=611657 us50=19994 us250=99945 diff=79951 cpu_MHz=1530.080

Changes in v3:
  Remove unnecessary assigned-clocks

Changes in v2:
  Change sram to reserved-memory

Chukun Pan (1):
  arm64: dts: rockchip: enable SCMI clk for RK3528 SoC

Chukun Pan (1):
  arm64: dts: rockchip: enable SCMI clk for RK3528 SoC

 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 31 ++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

-- 
2.25.1



From ping.bai at nxp.com  Fri Mar  7 02:02:14 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri, 7 Mar 2025 10:02:14 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <Z8rBYuDiIyo8y6HT@bogus>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
 <Z8rBYuDiIyo8y6HT@bogus>
Message-ID: <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>

Hi Sudeep,

> Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> 
> On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> > for_each_possible_cpu() is currently used to initialize cpuidle in
> > below cpuidle drivers:
> >   drivers/cpuidle/cpuidle-arm.c
> >   drivers/cpuidle/cpuidle-big_little.c
> >   drivers/cpuidle/cpuidle-psci.c
> >   drivers/cpuidle/cpuidle-riscv-sbi.c
> >
> > However, in cpu_dev_register_generic(), for_each_present_cpu() is used
> > to register CPU devices which means the CPU devices are only
> > registered for present CPUs and not all possible CPUs.
> >
> > With nosmp or maxcpus=0, only the boot CPU is present, lead to the
> > failure:
> >
> >   |  Failed to register cpuidle device for cpu1
> >
> > Then rollback to cancel all CPUs' cpuidle registration.
> >
> > Change for_each_possible_cpu() to for_each_present_cpu() in the above
> > cpuidle drivers to ensure it only registers cpuidle devices for CPUs
> > that are actually present.
> >
> > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > GENERIC_CPU_DEVICES")
> > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v4 changes:
> >   - add changes for other cpuidle driver that has the similar issue
> >     as cpuidle-pcsi driver.
> >
> >  - v3 changes:
> >   - improve the changelog as suggested by Sudeep
> > ---
> >  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
> >  drivers/cpuidle/cpuidle-big_little.c | 2 +-
> >  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
> >  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
> 
> 
> Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC the issue
> exists there as well.
> 

For qcom-spm driver, it has below code logic to handle no cpu device case, and
no rollback to cancel the whole cpuidle registration. So I just leave it as it is.
Do we need to update it?

for_each_possible_cpu(cpu) {
        ret = spm_cpuidle_register(&pdev->dev, cpu);
        if (ret && ret != -ENODEV) {
                dev_err(&pdev->dev,
                        "Cannot register for CPU%d: %d\n", cpu, ret);
        }
}

BR
Jacky Bai
> --
> Regards,
> Sudeep


From amadeus at jmu.edu.cn  Fri Mar  7 02:00:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 18:00:08 +0800
Subject: [PATCH v3 1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250307100008.789129-1-amadeus@jmu.edu.cn>
References: <20250307100008.789129-1-amadeus@jmu.edu.cn>
Message-ID: <20250307100008.789129-2-amadeus@jmu.edu.cn>

Same as RK3568, RK3528 uses SCMI clk instead of ARMCLK.
Add SCMI clk for CPU, GPU and RNG will also use it.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 31 ++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 6403946e1700..e59a6eaff60c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -59,6 +59,7 @@ cpu0: cpu at 0 {
 			reg = <0x0>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu1: cpu at 1 {
@@ -66,6 +67,7 @@ cpu1: cpu at 1 {
 			reg = <0x1>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu2: cpu at 2 {
@@ -73,6 +75,7 @@ cpu2: cpu at 2 {
 			reg = <0x2>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
 		};
 
 		cpu3: cpu at 3 {
@@ -80,6 +83,22 @@ cpu3: cpu at 3 {
 			reg = <0x3>;
 			device_type = "cpu";
 			enable-method = "psci";
+			clocks = <&scmi_clk SCMI_CLK_CPU>;
+		};
+	};
+
+	firmware {
+		scmi: scmi {
+			compatible = "arm,scmi-smc";
+			arm,smc-id = <0x82000010>;
+			shmem = <&scmi_shmem>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_clk: protocol at 14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
 		};
 	};
 
@@ -88,6 +107,18 @@ psci {
 		method = "smc";
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		scmi_shmem: shmem at 10f000 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x0010f000 0x0 0x100>;
+			no-map;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-- 
2.25.1



From sudeep.holla at arm.com  Fri Mar  7 02:04:02 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 7 Mar 2025 10:04:02 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
 <Z8rBYuDiIyo8y6HT@bogus>
 <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
Message-ID: <Z8rEkgYoThJAJdPV@bogus>

On Fri, Mar 07, 2025 at 10:02:14AM +0000, Jacky Bai wrote:
> Hi Sudeep,
> 
> > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> > 
> > On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> > > for_each_possible_cpu() is currently used to initialize cpuidle in
> > > below cpuidle drivers:
> > >   drivers/cpuidle/cpuidle-arm.c
> > >   drivers/cpuidle/cpuidle-big_little.c
> > >   drivers/cpuidle/cpuidle-psci.c
> > >   drivers/cpuidle/cpuidle-riscv-sbi.c
> > >
> > > However, in cpu_dev_register_generic(), for_each_present_cpu() is used
> > > to register CPU devices which means the CPU devices are only
> > > registered for present CPUs and not all possible CPUs.
> > >
> > > With nosmp or maxcpus=0, only the boot CPU is present, lead to the
> > > failure:
> > >
> > >   |  Failed to register cpuidle device for cpu1
> > >
> > > Then rollback to cancel all CPUs' cpuidle registration.
> > >
> > > Change for_each_possible_cpu() to for_each_present_cpu() in the above
> > > cpuidle drivers to ensure it only registers cpuidle devices for CPUs
> > > that are actually present.
> > >
> > > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > > GENERIC_CPU_DEVICES")
> > > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > > ---
> > >  - v4 changes:
> > >   - add changes for other cpuidle driver that has the similar issue
> > >     as cpuidle-pcsi driver.
> > >
> > >  - v3 changes:
> > >   - improve the changelog as suggested by Sudeep
> > > ---
> > >  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
> > >  drivers/cpuidle/cpuidle-big_little.c | 2 +-
> > >  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
> > >  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
> > 
> > 
> > Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC the issue
> > exists there as well.
> > 
> 
> For qcom-spm driver, it has below code logic to handle no cpu device case, and
> no rollback to cancel the whole cpuidle registration. So I just leave it as it is.
> Do we need to update it?
> 
> for_each_possible_cpu(cpu) {
>         ret = spm_cpuidle_register(&pdev->dev, cpu);

Did you look into this function ?

-- 
Regards,
Sudeep


From ping.bai at nxp.com  Fri Mar  7 02:10:50 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri, 7 Mar 2025 10:10:50 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <Z8rEkgYoThJAJdPV@bogus>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
 <Z8rBYuDiIyo8y6HT@bogus>
 <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
 <Z8rEkgYoThJAJdPV@bogus>
Message-ID: <AS8PR04MB86425524495B3FEF19F32E6B87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> 
> On Fri, Mar 07, 2025 at 10:02:14AM +0000, Jacky Bai wrote:
> > Hi Sudeep,
> >
> > > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> > >
> > > On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> > > > for_each_possible_cpu() is currently used to initialize cpuidle in
> > > > below cpuidle drivers:
> > > >   drivers/cpuidle/cpuidle-arm.c
> > > >   drivers/cpuidle/cpuidle-big_little.c
> > > >   drivers/cpuidle/cpuidle-psci.c
> > > >   drivers/cpuidle/cpuidle-riscv-sbi.c
> > > >
> > > > However, in cpu_dev_register_generic(), for_each_present_cpu() is
> > > > used to register CPU devices which means the CPU devices are only
> > > > registered for present CPUs and not all possible CPUs.
> > > >
> > > > With nosmp or maxcpus=0, only the boot CPU is present, lead to the
> > > > failure:
> > > >
> > > >   |  Failed to register cpuidle device for cpu1
> > > >
> > > > Then rollback to cancel all CPUs' cpuidle registration.
> > > >
> > > > Change for_each_possible_cpu() to for_each_present_cpu() in the
> > > > above cpuidle drivers to ensure it only registers cpuidle devices
> > > > for CPUs that are actually present.
> > > >
> > > > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > > > GENERIC_CPU_DEVICES")
> > > > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > > > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > > > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > > > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > > > ---
> > > >  - v4 changes:
> > > >   - add changes for other cpuidle driver that has the similar issue
> > > >     as cpuidle-pcsi driver.
> > > >
> > > >  - v3 changes:
> > > >   - improve the changelog as suggested by Sudeep
> > > > ---
> > > >  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
> > > >  drivers/cpuidle/cpuidle-big_little.c | 2 +-
> > > >  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
> > > >  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
> > >
> > >
> > > Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC the
> > > issue exists there as well.
> > >
> >
> > For qcom-spm driver, it has below code logic to handle no cpu device
> > case, and no rollback to cancel the whole cpuidle registration. So I just leave
> it as it is.
> > Do we need to update it?
> >
> > for_each_possible_cpu(cpu) {
> >         ret = spm_cpuidle_register(&pdev->dev, cpu);
> 
> Did you look into this function ?

Yes, at the very beginning of this function it will check if the cpu device
is available, if not, directly return -ENODEV, something I misunderstood?

BR
> 
> --
> Regards,
> Sudeep


From Bo.Sun.CN at windriver.com  Fri Mar  7 02:14:26 2025
From: Bo.Sun.CN at windriver.com (Bo Sun)
Date: Fri, 7 Mar 2025 18:14:26 +0800
Subject: [PATCH] PCI: controller: Restore PCI_REASSIGN_ALL_BUS when
 PCI_PROBE_ONLY is enabled
In-Reply-To: <20250305060607.ygsafql53h2ujwjp@thinkpad>
References: <20250117082428.129353-1-Bo.Sun.CN@windriver.com>
 <20250210103707.c5ubeaowk7xwt6p5@thinkpad>
 <df5d3c54-d436-43bb-8b40-665c020d6bb5@windriver.com>
 <20250214170057.o3ffoiuxn4hxqqqe@thinkpad>
 <55a33534-bff0-488c-a2a2-2898d54bd62f@windriver.com>
 <20250305060607.ygsafql53h2ujwjp@thinkpad>
Message-ID: <416a2d7d-eeb6-4163-8805-3178476f5a8d@windriver.com>

On 3/5/25 14:06, Manivannan Sadhasivam wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
> 
> On Fri, Feb 28, 2025 at 07:58:10PM +0800, Bo Sun wrote:
>> On 2/15/25 1:00 AM, Manivannan Sadhasivam wrote:
>>> CAUTION: This email comes from a non Wind River email account!
>>> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>>>
>>> On Wed, Feb 12, 2025 at 03:07:56PM +0800, Bo Sun wrote:
>>>> On 2/10/25 18:37, Manivannan Sadhasivam wrote:
>>>>> CAUTION: This email comes from a non Wind River email account!
>>>>> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>>>>>
>>>>> On Fri, Jan 17, 2025 at 04:24:14PM +0800, Bo Sun wrote:
>>>>>> On our Marvell OCTEON CN96XX board, we observed the following panic on
>>>>>> the latest kernel:
>>>>>> Unable to handle kernel NULL pointer dereference at virtual address 0000000000000080
>>>>>> Mem abort info:
>>>>>>      ESR = 0x0000000096000005
>>>>>>      EC = 0x25: DABT (current EL), IL = 32 bits
>>>>>>      SET = 0, FnV = 0
>>>>>>      EA = 0, S1PTW = 0
>>>>>>      FSC = 0x05: level 1 translation fault
>>>>>> Data abort info:
>>>>>>      ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
>>>>>>      CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>>>>      GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>>>> [0000000000000080] user address but active_mm is swapper
>>>>>> Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
>>>>>> Modules linked in:
>>>>>> CPU: 9 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.13.0-rc7-00149-g9bffa1ad25b8 #1
>>>>>> Hardware name: Marvell OcteonTX CN96XX board (DT)
>>>>>> pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>>> pc : of_pci_add_properties+0x278/0x4c8
>>>>>> lr : of_pci_add_properties+0x258/0x4c8
>>>>>> sp : ffff8000822ef9b0
>>>>>> x29: ffff8000822ef9b0 x28: ffff000106dd8000 x27: ffff800081bc3b30
>>>>>> x26: ffff800081540118 x25: ffff8000813d2be0 x24: 0000000000000000
>>>>>> x23: ffff00010528a800 x22: ffff000107c50000 x21: ffff0001039c2630
>>>>>> x20: ffff0001039c2630 x19: 0000000000000000 x18: ffffffffffffffff
>>>>>> x17: 00000000a49c1b85 x16: 0000000084c07b58 x15: ffff000103a10f98
>>>>>> x14: ffffffffffffffff x13: ffff000103a10f96 x12: 0000000000000003
>>>>>> x11: 0101010101010101 x10: 000000000000002c x9 : ffff800080ca7acc
>>>>>> x8 : ffff0001038fd900 x7 : 0000000000000000 x6 : 0000000000696370
>>>>>> x5 : 0000000000000000 x4 : 0000000000000002 x3 : ffff8000822efa40
>>>>>> x2 : ffff800081341000 x1 : ffff000107c50000 x0 : 0000000000000000
>>>>>> Call trace:
>>>>>>     of_pci_add_properties+0x278/0x4c8 (P)
>>>>>>     of_pci_make_dev_node+0xe0/0x158
>>>>>>     pci_bus_add_device+0x158/0x210
>>>>>>     pci_bus_add_devices+0x40/0x98
>>>>>>     pci_host_probe+0x94/0x118
>>>>>>     pci_host_common_probe+0x120/0x1a0
>>>>>>     platform_probe+0x70/0xf0
>>>>>>     really_probe+0xb4/0x2a8
>>>>>>     __driver_probe_device+0x80/0x140
>>>>>>     driver_probe_device+0x48/0x170
>>>>>>     __driver_attach+0x9c/0x1b0
>>>>>>     bus_for_each_dev+0x7c/0xe8
>>>>>>     driver_attach+0x2c/0x40
>>>>>>     bus_add_driver+0xec/0x218
>>>>>>     driver_register+0x68/0x138
>>>>>>     __platform_driver_register+0x2c/0x40
>>>>>>     gen_pci_driver_init+0x24/0x38
>>>>>>     do_one_initcall+0x4c/0x278
>>>>>>     kernel_init_freeable+0x1f4/0x3d0
>>>>>>     kernel_init+0x28/0x1f0
>>>>>>     ret_from_fork+0x10/0x20
>>>>>> Code: aa1603e1 f0005522 d2800044 91000042 (f94040a0)
>>>>>>
>>>>>> This regression was introduced by commit 7246a4520b4b ("PCI: Use
>>>>>> preserve_config in place of pci_flags"). On our board, the 002:00:07.0
>>>>>> bridge is misconfigured by the bootloader. Both its secondary and
>>>>>> subordinate bus numbers are initialized to 0, while its fixed secondary
>>>>>> bus number is set to 8.
>>>>>
>>>>> What do you mean by 'fixed secondary bus number'?
>>>>>
>>>>
>>>> The 'fixed secondary bus number' refers to the value returned by the
>>>> function pci_ea_fixed_busnrs(), which reads the fixed Secondary and
>>>> Subordinate bus numbers from the EA (Extended Attributes) capability, if
>>>> present.
>>>
>>> Thanks! It'd be good to mention the EA capability.
>>>
>>>> In the code at drivers/pci/probe.c, line 1439, we have the
>>>> following:
>>>>
>>>>                 /* Read bus numbers from EA Capability (if present) */
>>>>                 fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
>>>>                 if (fixed_buses)
>>>>                         next_busnr = fixed_sec;
>>>>                 else
>>>>                         next_busnr = max + 1;
>>>>
>>>>>> However, bus number 8 is also assigned to another
>>>>>> bridge (0002:00:0f.0). Although this is a bootloader issue, before the
>>>>>> change in commit 7246a4520b4b, the PCI_REASSIGN_ALL_BUS flag was
>>>>>> set by default when PCI_PROBE_ONLY was enabled, ensuing that all the
>>>>>> bus number for these bridges were reassigned, avoiding any conflicts.
>>>>>>
>>>>>
>>>>> Isn't the opposite? PCI_REASSIGN_ALL_BUS was only added if the PCI_PROBE_ONLY
>>>>> flag was not set:
>>>>>
>>>>>            /* Do not reassign resources if probe only */
>>>>>            if (!pci_has_flag(PCI_PROBE_ONLY))
>>>>>                    pci_add_flags(PCI_REASSIGN_ALL_BUS);
>>>>>
>>>>
>>>> Yes, you are correct. It?s a typo; it should be "when PCI_PROBE_ONLY was not
>>>> enabled." I will fix this in v2.
>>>>
>>>>>
>>>>>> After the change introduced in commit 7246a4520b4b, the bus numbers
>>>>>> assigned by the bootloader are reused by all other bridges, except
>>>>>> the misconfigured 002:00:07.0 bridge. The kernel attempt to reconfigure
>>>>>> 002:00:07.0 by reusing the fixed secondary bus number 8 assigned by
>>>>>> bootloader. However, since a pci_bus has already been allocated for
>>>>>> bus 8 due to the probe of 0002:00:0f.0, no new pci_bus allocated for
>>>>>> 002:00:07.0.
>>>>>
>>>>> How come 0002:00:0f.0 is enumerated before 0002:00:07.0 in a depth first manner?
>>>>>
>>>>
>>>> The device 0002:00:07.0 is actually enumerated before 0002:00:0f.0, but it
>>>> appears misconfigured. The kernel attempts to reconfigure it during
>>>> initialization, which is where the issue arises.
>>>>
>>>
>>> Ok, thanks for the clarification. I think the bug is in this part of the code:
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/probe.c#n1451
>>>
>>> It just reuses the fixed bus number even if the bus already exists, which is
>>> wrong. I think this should be fixed by evaluating the bus number read from EA
>>> capability as below:
>>>
>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>> index b6536ed599c3..097e2a01faae 100644
>>> --- a/drivers/pci/probe.c
>>> +++ b/drivers/pci/probe.c
>>> @@ -1438,10 +1438,21 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
>>>
>>>                   /* Read bus numbers from EA Capability (if present) */
>>>                   fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
>>> -               if (fixed_buses)
>>> -                       next_busnr = fixed_sec;
>>> -               else
>>> +               if (fixed_buses) {
>>> +                       /*
>>> +                        * If the fixed bus number is already taken, use the
>>> +                        * next available bus number. This can happen if the
>>> +                        * bootloader has assigned a wrong bus number in EA
>>> +                        * capability of the bridge.
>>> +                        */
>>> +                       child = pci_find_bus(pci_domain_nr(bus), fixed_sec);
>>> +                       if (child)
>>> +                               next_busnr = max + 1;
>>> +                       else
>>> +                               next_busnr = fixed_sec;
>>> +               } else {
>>>                           next_busnr = max + 1;
>>> +               }
>>>
>>>                   /*
>>>                    * Prevent assigning a bus number that already exists.
>>
>> You proposed solution doesn't work on our Marvell OCTEON CN96XX board.
>>
>> When probing the bus 0002:00, the bus number preset by the bootloader for
>> the bridges under this bus start with 0xf9. Before configure of
>> 0002:00:07.0, the 'max' bus number has already reached 0xff. With your
>> proposed fix, the next_busnr is set to (0xff + 1), which evaluate to 0x100.
>> This results in a 0 being assigned to the secondary bus number of
>> 0002:00:07.0 bridge, causing a recursive bus probe.
>>
> 
> Oops. This is turning out to be too much of a problem.
> 
>> For reference, you can take a look at the code in probe.c and the
>> corresponding log.
>>
>>      pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
>>
>>      primary = buses & 0xFF;
>>
>>      secondary = (buses >> 8) & 0xFF;
>>
>>      subordinate = (buses >> 16) & 0xFF;
>>
>>
>>      pci_dbg(dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
>>
>>          secondary, subordinate, pass);
>>
>> pci_bus 0002:00: fixups for bus
>> pci 0002:00:00.0: scanning [bus f9-f9] behind bridge, pass 0
>> pci_bus 0002:f9: scanning bus
>> pci_bus 0002:f9: fixups for bus
>> pci_bus 0002:f9: bus scan returning with max=f9
>> ...
>> pci 0002:00:06.0: scanning [bus ff-ff] behind bridge, pass 0
>> pci_bus 0002:ff: scanning bus
>> pci_bus 0002:ff: fixups for bus
>> pci_bus 0002:ff: bus scan returning with max=ff
>> pci 0002:00:07.0: scanning [bus 00-00] behind bridge, pass 0
>> pci 0002:00:07.0: bridge configuration invalid ([bus 00-00]), reconfiguring
>> ...
>> Kernel panic - not syncing: kernel stack overflow
>> CPU: 12 UID: 0 PID: 1 Comm: swapper/0 Not tainted
>> 6.14.0-rc4-00091-ga58485af8826 #16
>> Hardware name: Marvell OcteonTX CN96XX board (DT)
>> Call trace:
>>   show_stack+0x20/0x38 (C)
>>   dump_stack_lvl+0x38/0x90
>>   dump_stack+0x18/0x28
>>   panic+0x3ac/0x3c8
>>   nmi_panic+0x48/0xa0
>>   panic_bad_stack+0x118/0x140
>>   handle_bad_stack+0x34/0x38
>>   __bad_stack+0x80/0x88
>>   format_decode+0x4/0x2e8 (P)
>>   va_format.constprop.0+0x74/0x130
>>   pointer+0x204/0x4f8
>>   vsnprintf+0x2c4/0x5a0
>>   vscnprintf+0x34/0x58
>>   printk_sprint+0x48/0x170
>>   vprintk_store+0x2d0/0x478
>>   vprintk_emit+0xb0/0x2b0
>>   dev_vprintk_emit+0xe0/0x1b0
>>   dev_printk_emit+0x60/0x90
>>   __dev_printk+0x44/0x98
>>   _dev_printk+0x5c/0x90
>>   pci_scan_child_bus_extend+0x5c/0x2c0
>>   pci_scan_bridge_extend+0x16c/0x630
>>   pci_scan_child_bus_extend+0xfc/0x2c0
>>   pci_scan_bridge_extend+0x320/0x630
>>   pci_scan_child_bus_extend+0x1b0/0x2c0
>>   pci_scan_bridge_extend+0x320/0x630
>>
>> So, I propose the following solution as a workaround to handle these edge
>> cases.
>>
>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>> index 82b21e34c545..af8efebc7e7d 100644
>> --- a/drivers/pci/quirks.c
>> +++ b/drivers/pci/quirks.c
>> @@ -6181,6 +6181,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1536,
>> rom_bar_overlap_defect);
>>   DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1537,
>> rom_bar_overlap_defect);
>>   DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1538,
>> rom_bar_overlap_defect);
>>
>> +static void quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr(struct pci_dev
>> *dev)
>> +{
>> +       if (!pci_has_flag(PCI_PROBE_ONLY))
>> +               pci_add_flags(PCI_REASSIGN_ALL_BUS);
>> +}
>> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CAVIUM, 0xa002,
>> quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr);
>> +
> 
> LGTM. Please add a comment about this quirk too.

OK, I'll add the comment. Should I send the v2 patch?

Thanks,
Bo



From sudeep.holla at arm.com  Fri Mar  7 02:19:03 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 7 Mar 2025 10:19:03 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <AS8PR04MB86425524495B3FEF19F32E6B87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
 <Z8rBYuDiIyo8y6HT@bogus>
 <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
 <Z8rEkgYoThJAJdPV@bogus>
 <AS8PR04MB86425524495B3FEF19F32E6B87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
Message-ID: <Z8rIF3fQr958cf8g@bogus>

On Fri, Mar 07, 2025 at 10:10:50AM +0000, Jacky Bai wrote:
> > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> > 
> > On Fri, Mar 07, 2025 at 10:02:14AM +0000, Jacky Bai wrote:
> > > Hi Sudeep,
> > >
> > > > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> > > >
> > > > On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> > > > > for_each_possible_cpu() is currently used to initialize cpuidle in
> > > > > below cpuidle drivers:
> > > > >   drivers/cpuidle/cpuidle-arm.c
> > > > >   drivers/cpuidle/cpuidle-big_little.c
> > > > >   drivers/cpuidle/cpuidle-psci.c
> > > > >   drivers/cpuidle/cpuidle-riscv-sbi.c
> > > > >
> > > > > However, in cpu_dev_register_generic(), for_each_present_cpu() is
> > > > > used to register CPU devices which means the CPU devices are only
> > > > > registered for present CPUs and not all possible CPUs.
> > > > >
> > > > > With nosmp or maxcpus=0, only the boot CPU is present, lead to the
> > > > > failure:
> > > > >
> > > > >   |  Failed to register cpuidle device for cpu1
> > > > >
> > > > > Then rollback to cancel all CPUs' cpuidle registration.
> > > > >
> > > > > Change for_each_possible_cpu() to for_each_present_cpu() in the
> > > > > above cpuidle drivers to ensure it only registers cpuidle devices
> > > > > for CPUs that are actually present.
> > > > >
> > > > > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > > > > GENERIC_CPU_DEVICES")
> > > > > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > > > > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > > > > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > > > > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > > > > ---
> > > > >  - v4 changes:
> > > > >   - add changes for other cpuidle driver that has the similar issue
> > > > >     as cpuidle-pcsi driver.
> > > > >
> > > > >  - v3 changes:
> > > > >   - improve the changelog as suggested by Sudeep
> > > > > ---
> > > > >  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
> > > > >  drivers/cpuidle/cpuidle-big_little.c | 2 +-
> > > > >  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
> > > > >  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
> > > >
> > > >
> > > > Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC the
> > > > issue exists there as well.
> > > >
> > >
> > > For qcom-spm driver, it has below code logic to handle no cpu device
> > > case, and no rollback to cancel the whole cpuidle registration. So I just leave
> > it as it is.
> > > Do we need to update it?
> > >
> > > for_each_possible_cpu(cpu) {
> > >         ret = spm_cpuidle_register(&pdev->dev, cpu);
> > 
> > Did you look into this function ?
> 
> Yes, at the very beginning of this function it will check if the cpu device
> is available, if not, directly return -ENODEV, something I misunderstood?
> 

So why do you think spm_cpuidle_register() does anything different than
psci_idle_init_cpu(). They do exactly same check and yet you apply the
change for psci_idle_init_cpu() but not for spm_cpuidle_register().
What am I missing ?

-- 
Regards,
Sudeep


From ernestvanhoecke at gmail.com  Fri Mar  7 02:17:47 2025
From: ernestvanhoecke at gmail.com (ernestvanhoecke at gmail.com)
Date: Fri,  7 Mar 2025 11:17:47 +0100
Subject: [PATCH v2 0/2] ARM: dts: apalis/colibri-imx6: Add support for v1.2
Message-ID: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>

From: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>

Apalis/Colibri iMX6 V1.2 replaced the STMPE811 ADC/touch controller,
which is EOL, with the TLA2024 ADC and AD7879 touch controller.

Accurately describe the new hardware.

v1.1 of these SoMs is still described by the following DTSI files:
imx6qdl-apalis.dtsi
imx6qdl-colibri.dtsi

The STMPE811 touchscreen controller is no longer disabled by default.
The STMPE811 is self contained within the SoM, therefore, disabling it
is not the correct default behavior.

v1.2 is now supported by a DTSI that modifies v1.1:
imx6qdl-apalis-v1.2.dtsi
imx6qdl-colibri-v1.2.dtsi

For each carrier board using these modules, a new DTS file was added
that includes the v1.1 DTS and modifies it with this v1.2 DTSI.

The original DTS can be used for modules up to and including v1.1.

v2: Fixed the "From" field
v1: https://lore.kernel.org/all/20250227170556.589668-1-ernest.vanhoecke at toradex.com/

Ernest Van Hoecke (2):
  ARM: dts: apalis/colibri-imx6: Enable STMPE811 TS
  ARM: dts: apalis/colibri-imx6: Add support for v1.2

 arch/arm/boot/dts/nxp/imx/Makefile            |  9 +++
 .../dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts | 11 ++++
 .../nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts   | 11 ++++
 .../nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts   | 11 ++++
 .../dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts  | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts   | 11 ++++
 .../dts/nxp/imx/imx6q-apalis-v1.2-eval.dts    | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts  | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts  | 11 ++++
 .../dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts   | 11 ++++
 .../boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi | 57 +++++++++++++++++++
 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi |  1 -
 .../dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi     | 57 +++++++++++++++++++
 .../arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi |  1 -
 14 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi

-- 
2.43.0



From ernestvanhoecke at gmail.com  Fri Mar  7 02:17:48 2025
From: ernestvanhoecke at gmail.com (ernestvanhoecke at gmail.com)
Date: Fri,  7 Mar 2025 11:17:48 +0100
Subject: [PATCH v2 1/2] ARM: dts: apalis/colibri-imx6: Enable STMPE811 TS
In-Reply-To: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
References: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
Message-ID: <20250307101758.27943-2-ernest.vanhoecke@toradex.com>

From: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>

Enable the STMPE811 touchscreen in the SOM dtsi files. The STMPE811 is
part of the SOM. It's self contained within it, therefore, disabling it
is not the correct default behavior.

Signed-off-by: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>
Reviewed-by: Francesco Dolcini <francesco.dolcini at toradex.com>
---
v2: Fixed the "From" field
v1: https://lore.kernel.org/all/20250227170556.589668-2-ernest.vanhoecke at toradex.com/
---
 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi  | 1 -
 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
index dffab5aa8b9c..23913f18586c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
@@ -664,7 +664,6 @@ stmpe_ts: stmpe_touchscreen {
 			st,settling = <3>;
 			/* 5 ms touch detect interrupt delay */
 			st,touch-det-delay = <5>;
-			status = "disabled";
 		};
 
 		stmpe_adc: stmpe_adc {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
index 9f33419c260b..9a9f9764dc65 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
@@ -588,7 +588,6 @@ stmpe_ts: stmpe_touchscreen {
 			st,settling = <3>;
 			/* 5 ms touch detect interrupt delay */
 			st,touch-det-delay = <5>;
-			status = "disabled";
 		};
 
 		stmpe_adc: stmpe_adc {
-- 
2.43.0



From ernestvanhoecke at gmail.com  Fri Mar  7 02:17:49 2025
From: ernestvanhoecke at gmail.com (ernestvanhoecke at gmail.com)
Date: Fri,  7 Mar 2025 11:17:49 +0100
Subject: [PATCH v2 2/2] ARM: dts: apalis/colibri-imx6: Add support for v1.2
In-Reply-To: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
References: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
Message-ID: <20250307101758.27943-3-ernest.vanhoecke@toradex.com>

From: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>

Apalis/Colibri iMX6 V1.2 replaced the STMPE811 ADC/touch controller,
which is EOL, with the TLA2024 ADC and AD7879 touch controller.

Accurately describe the new hardware.

v1.1 of these SoMs is still described by the following DTSI files:
imx6qdl-apalis.dtsi
imx6qdl-colibri.dtsi

v1.2 is now supported by a DTSI that modifies v1.1:
imx6qdl-apalis-v1.2.dtsi
imx6qdl-colibri-v1.2.dtsi

For each carrier board using these modules, a new DTS file was added
that includes the v1.1 DTS and modifies it with this v1.2 DTSI.

The original DTS can be used for modules up to and including v1.1.

Signed-off-by: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>
Reviewed-by: Francesco Dolcini <francesco.dolcini at toradex.com>
---
v2: Fixed the "From" field
v1: https://lore.kernel.org/all/20250227170556.589668-3-ernest.vanhoecke at toradex.com/
---
 arch/arm/boot/dts/nxp/imx/Makefile            |  9 +++
 .../dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts | 11 ++++
 .../nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts   | 11 ++++
 .../nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts   | 11 ++++
 .../dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts  | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts   | 11 ++++
 .../dts/nxp/imx/imx6q-apalis-v1.2-eval.dts    | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts  | 11 ++++
 .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts  | 11 ++++
 .../dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts   | 11 ++++
 .../boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi | 57 +++++++++++++++++++
 .../dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi     | 57 +++++++++++++++++++
 12 files changed, 222 insertions(+)
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi

diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 39a153536d2a..81b6a96e28da 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -69,6 +69,10 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-colibri-eval-v3.dtb \
 	imx6dl-colibri-iris.dtb \
 	imx6dl-colibri-iris-v2.dtb \
+	imx6dl-colibri-v1.2-aster.dtb \
+	imx6dl-colibri-v1.2-eval-v3.dtb \
+	imx6dl-colibri-v1.2-iris.dtb \
+	imx6dl-colibri-v1.2-iris-v2.dtb \
 	imx6dl-cubox-i.dtb \
 	imx6dl-cubox-i-emmc-som-v15.dtb \
 	imx6dl-cubox-i-som-v15.dtb \
@@ -158,6 +162,11 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-apalis-ixora.dtb \
 	imx6q-apalis-ixora-v1.1.dtb \
 	imx6q-apalis-ixora-v1.2.dtb \
+	imx6q-apalis-v1.2-eval.dtb \
+	imx6q-apalis-v1.2-eval-v1.2.dtb \
+	imx6q-apalis-v1.2-ixora.dtb \
+	imx6q-apalis-v1.2-ixora-v1.1.dtb \
+	imx6q-apalis-v1.2-ixora-v1.2.dtb \
 	imx6q-apf6dev.dtb \
 	imx6q-arm2.dtb \
 	imx6q-b450v3.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
new file mode 100644
index 000000000000..44c78c07f431
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6dl-colibri-aster.dts"
+#include "imx6qdl-colibri-v1.2.dtsi"
+
+/ {
+	model = "Toradex Colibri iMX6DL/S V1.2+ on Colibri Aster Board";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
new file mode 100644
index 000000000000..93fd0af53a3c
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6dl-colibri-eval-v3.dts"
+#include "imx6qdl-colibri-v1.2.dtsi"
+
+/ {
+	model = "Toradex Colibri iMX6DL/S V1.2+ on Colibri Evaluation Board V3";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
new file mode 100644
index 000000000000..92d41fc9a13f
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6dl-colibri-iris-v2.dts"
+#include "imx6qdl-colibri-v1.2.dtsi"
+
+/ {
+	model = "Toradex Colibri iMX6DL/S V1.2+ on Colibri Iris V2 Board";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
new file mode 100644
index 000000000000..c8957948c887
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6dl-colibri-iris.dts"
+#include "imx6qdl-colibri-v1.2.dtsi"
+
+/ {
+	model = "Toradex Colibri iMX6DL/S V1.2+ on Colibri Iris Board";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
new file mode 100644
index 000000000000..908dab57fd87
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6q-apalis-eval-v1.2.dts"
+#include "imx6qdl-apalis-v1.2.dtsi"
+
+/ {
+	model = "Toradex Apalis iMX6Q/D Module V1.2+ on Apalis Evaluation Board v1.2";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
new file mode 100644
index 000000000000..5463d4127382
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6q-apalis-eval.dts"
+#include "imx6qdl-apalis-v1.2.dtsi"
+
+/ {
+	model = "Toradex Apalis iMX6Q/D Module V1.2+ on Apalis Evaluation Board";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
new file mode 100644
index 000000000000..84eabf81ba84
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6q-apalis-ixora-v1.1.dts"
+#include "imx6qdl-apalis-v1.2.dtsi"
+
+/ {
+	model = "Toradex Apalis iMX6Q/D Module V1.2+ on Ixora Carrier Board V1.1";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
new file mode 100644
index 000000000000..d7cfab4de457
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6q-apalis-ixora-v1.2.dts"
+#include "imx6qdl-apalis-v1.2.dtsi"
+
+/ {
+	model = "Toradex Apalis iMX6Q/D Module V1.2+ on Ixora Carrier Board V1.2";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
new file mode 100644
index 000000000000..189b074e31ce
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+/dts-v1/;
+
+#include "imx6q-apalis-ixora.dts"
+#include "imx6qdl-apalis-v1.2.dtsi"
+
+/ {
+	model = "Toradex Apalis iMX6Q/D Module V1.2+ on Ixora Carrier Board";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
new file mode 100644
index 000000000000..83fa04fc9f18
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+&i2c2 {
+	/delete-node/ stmpe811 at 41;
+
+	ad7879_ts: touchscreen at 2c {
+		compatible = "adi,ad7879-1";
+		reg = <0x2c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touch_int>;
+		interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-parent = <&gpio4>;
+		touchscreen-max-pressure = <4096>;
+		adi,resistance-plate-x = <120>;
+		adi,first-conversion-delay = /bits/ 8 <3>;
+		adi,acquisition-time = /bits/ 8 <1>;
+		adi,median-filter-size = /bits/ 8 <2>;
+		adi,averaging = /bits/ 8 <1>;
+		adi,conversion-interval = /bits/ 8 <255>;
+	};
+
+	tla2024_adc: adc at 49 {
+		compatible = "ti,tla2024";
+		reg = <0x49>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* Apalis AN1_ADC0 */
+		channel at 4 {
+			reg = <4>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Apalis AN1_ADC1 */
+		channel at 5 {
+			reg = <5>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Apalis AN1_ADC2 */
+		channel at 6 {
+			reg = <6>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Apalis AN1_TSWIP_ADC3 */
+		channel at 7 {
+			reg = <7>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi
new file mode 100644
index 000000000000..d11bf911b728
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/* Copyright (c) 2025 Toradex */
+
+&i2c2 {
+	/delete-node/ stmpe811 at 41;
+
+	ad7879_ts: touchscreen at 2c {
+		compatible = "adi,ad7879-1";
+		reg = <0x2c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touch_int>;
+		interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-parent = <&gpio6>;
+		touchscreen-max-pressure = <4096>;
+		adi,resistance-plate-x = <120>;
+		adi,first-conversion-delay = /bits/ 8 <3>;
+		adi,acquisition-time = /bits/ 8 <1>;
+		adi,median-filter-size = /bits/ 8 <2>;
+		adi,averaging = /bits/ 8 <1>;
+		adi,conversion-interval = /bits/ 8 <255>;
+	};
+
+	tla2024_adc: adc at 49 {
+		compatible = "ti,tla2024";
+		reg = <0x49>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* Colibri AIN0 */
+		channel at 4 {
+			reg = <4>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Colibri AIN1 */
+		channel at 5 {
+			reg = <5>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Colibri AIN2 */
+		channel at 6 {
+			reg = <6>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+
+		/* Colibri AIN3 */
+		channel at 7 {
+			reg = <7>;
+			ti,datarate = <4>;
+			ti,gain = <1>;
+		};
+	};
+};
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Fri Mar  7 02:19:13 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Fri, 07 Mar 2025 11:19:13 +0100
Subject: [PATCH] arm64: dtsi: imx93: add alias id for bbnsm_rtc
In-Reply-To: <20250306193014.490091-1-Frank.Li@nxp.com>
References: <20250306193014.490091-1-Frank.Li@nxp.com>
Message-ID: <116096172.nniJfEyVGO@steina-w>

Hi,

Am Donnerstag, 6. M?rz 2025, 20:30:14 CET schrieb Frank Li:
> From: Joy Zou <joy.zou at nxp.com>
> 
> Add rtc0 alias to set bbnsm_rtc as the default rtc.
> 
> Signed-off-by: Joy Zou <joy.zou at nxp.com>
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx93.dtsi | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
> index 56766fdb0b1e5..7d9aa15ebf5d0 100644
> --- a/arch/arm64/boot/dts/freescale/imx93.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
> @@ -34,6 +34,7 @@ aliases {
>  		mmc0 = &usdhc1;
>  		mmc1 = &usdhc2;
>  		mmc2 = &usdhc3;
> +		rtc0 = &bbnsm_rtc;

IMHO this is a board property, not SoC property.

Best regards
Alexander

>  		serial0 = &lpuart1;
>  		serial1 = &lpuart2;
>  		serial2 = &lpuart3;
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From ping.bai at nxp.com  Fri Mar  7 02:26:33 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri, 7 Mar 2025 10:26:33 +0000
Subject: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <Z8rIF3fQr958cf8g@bogus>
References: <20250307080303.2660506-1-ping.bai@nxp.com>
 <Z8rBYuDiIyo8y6HT@bogus>
 <AS8PR04MB86425B7CEE7443F822A2DBCA87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
 <Z8rEkgYoThJAJdPV@bogus>
 <AS8PR04MB86425524495B3FEF19F32E6B87D52@AS8PR04MB8642.eurprd04.prod.outlook.com>
 <Z8rIF3fQr958cf8g@bogus>
Message-ID: <AS8PR04MB8642352392C6C54A1E60E5F387D52@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> 
> On Fri, Mar 07, 2025 at 10:10:50AM +0000, Jacky Bai wrote:
> > > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present CPUs
> > >
> > > On Fri, Mar 07, 2025 at 10:02:14AM +0000, Jacky Bai wrote:
> > > > Hi Sudeep,
> > > >
> > > > > Subject: Re: [PATCH v4] cpuidle: Init cpuidle only for present
> > > > > CPUs
> > > > >
> > > > > On Fri, Mar 07, 2025 at 04:03:03PM +0800, Jacky Bai wrote:
> > > > > > for_each_possible_cpu() is currently used to initialize
> > > > > > cpuidle in below cpuidle drivers:
> > > > > >   drivers/cpuidle/cpuidle-arm.c
> > > > > >   drivers/cpuidle/cpuidle-big_little.c
> > > > > >   drivers/cpuidle/cpuidle-psci.c
> > > > > >   drivers/cpuidle/cpuidle-riscv-sbi.c
> > > > > >
> > > > > > However, in cpu_dev_register_generic(), for_each_present_cpu()
> > > > > > is used to register CPU devices which means the CPU devices
> > > > > > are only registered for present CPUs and not all possible CPUs.
> > > > > >
> > > > > > With nosmp or maxcpus=0, only the boot CPU is present, lead to
> > > > > > the
> > > > > > failure:
> > > > > >
> > > > > >   |  Failed to register cpuidle device for cpu1
> > > > > >
> > > > > > Then rollback to cancel all CPUs' cpuidle registration.
> > > > > >
> > > > > > Change for_each_possible_cpu() to for_each_present_cpu() in
> > > > > > the above cpuidle drivers to ensure it only registers cpuidle
> > > > > > devices for CPUs that are actually present.
> > > > > >
> > > > > > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > > > > > GENERIC_CPU_DEVICES")
> > > > > > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > > > > > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > > > > > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > > > > > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > > > > > ---
> > > > > >  - v4 changes:
> > > > > >   - add changes for other cpuidle driver that has the similar issue
> > > > > >     as cpuidle-pcsi driver.
> > > > > >
> > > > > >  - v3 changes:
> > > > > >   - improve the changelog as suggested by Sudeep
> > > > > > ---
> > > > > >  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
> > > > > >  drivers/cpuidle/cpuidle-big_little.c | 2 +-
> > > > > >  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
> > > > > >  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
> > > > >
> > > > >
> > > > > Why have you spared drivers/cpuidle/cpuidle-qcom-spm.c ? IIUC
> > > > > the issue exists there as well.
> > > > >
> > > >
> > > > For qcom-spm driver, it has below code logic to handle no cpu
> > > > device case, and no rollback to cancel the whole cpuidle
> > > > registration. So I just leave
> > > it as it is.
> > > > Do we need to update it?
> > > >
> > > > for_each_possible_cpu(cpu) {
> > > >         ret = spm_cpuidle_register(&pdev->dev, cpu);
> > >
> > > Did you look into this function ?
> >
> > Yes, at the very beginning of this function it will check if the cpu
> > device is available, if not, directly return -ENODEV, something I
> misunderstood?
> >
> 
> So why do you think spm_cpuidle_register() does anything different than
> psci_idle_init_cpu(). They do exactly same check and yet you apply the
> change for psci_idle_init_cpu() but not for spm_cpuidle_register().
> What am I missing ?
> 

Thank you, I got your point now. let me update it in next version. :)

BR

> --
> Regards,
> Sudeep


From cki-project at redhat.com  Fri Mar  7 02:43:11 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 10:43:11 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <65441.125030705431300341@us-mta-365.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704603837

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704603837-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From akihiko.odaki at daynix.com  Fri Mar  7 02:55:27 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Fri, 07 Mar 2025 19:55:27 +0900
Subject: [PATCH v2 0/3] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Message-ID: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>

Prepare vPMC registers for user-initiated changes after first run. This
is important specifically for debugging Windows on QEMU with GDB; QEMU
tries to write back all visible registers when resuming the VM execution
with GDB, corrupting the PMU state. Windows always uses the PMU so this
can cause adverse effects on that particular OS.

This series also contains patch "KVM: arm64: PMU: Set raw values from
user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
changes made for the mentioned registers in the past. It is necessary
to migrate the PMU state properly on Firecracker, QEMU, and crosvm.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
Changes in v2:
- Changed to utilize KVM_REQ_RELOAD_PMU as suggested by Oliver Upton.
- Added patch "KVM: arm64: PMU: Reload when user modifies registers"
  to cover more registers.
- Added patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}".
- Link to v1: https://lore.kernel.org/r/20250302-pmc-v1-1-caff989093dc at daynix.com

---
Akihiko Odaki (3):
      KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
      KVM: arm64: PMU: Reload when user modifies registers
      KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}

 arch/arm64/kvm/pmu-emul.c | 19 ++++++++++++++++---
 arch/arm64/kvm/sys_regs.c | 44 ++++++++++++++++++++++++--------------------
 include/kvm/arm_pmu.h     |  1 +
 3 files changed, 41 insertions(+), 23 deletions(-)
---
base-commit: da2f480cb24d39d480b1e235eda0dd2d01f8765b
change-id: 20250302-pmc-b90a86af945c

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From akihiko.odaki at daynix.com  Fri Mar  7 02:55:28 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Fri, 07 Mar 2025 19:55:28 +0900
Subject: [PATCH v2 1/3] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
Message-ID: <20250307-pmc-v2-1-6c3375a5f1e4@daynix.com>

Reload the perf event when setting the vPMU counter (vPMC) registers
(PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

Fix this by releasing the current perf event and trigger recreating one
with KVM_REQ_RELOAD_PMU.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 16 ++++++++++++++++
 arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
 include/kvm/arm_pmu.h     |  1 +
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index e3e82b66e2268d37d5e2630e47ddf085a6846e1c..1402cce5625bffa706aabe5e6121d1f3817a0aaf 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -191,6 +191,22 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
+/**
+ * kvm_pmu_set_counter_value_user - set PMU counter value from user
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ * @val: The counter value
+ */
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+{
+	if (!kvm_vcpu_has_pmu(vcpu))
+		return;
+
+	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+}
+
 /**
  * kvm_pmu_release_perf_event - remove the perf event
  * @pmc: The PMU counter pointer
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 42791971f75887796afab905cc12f49fead39e10..27418dac791df9a89124f867879e899db175e506 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 	return 0;
 }
 
+static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+			  u64 val)
+{
+	u64 idx;
+
+	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+		/* PMCCNTR_EL0 */
+		idx = ARMV8_PMU_CYCLE_IDX;
+	else
+		/* PMEVCNTRn_EL0 */
+		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+	kvm_pmu_set_counter_value_user(vcpu, idx, val);
+	return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      const struct sys_reg_desc *r)
@@ -1328,6 +1344,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 #define PMU_PMEVCNTR_EL0(n)						\
 	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
 	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
+	  .set_user = set_pmu_evcntr,					\
 	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -2682,7 +2699,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  .access = access_pmceid, .reset = NULL },
 	{ PMU_SYS_REG(PMCCNTR_EL0),
 	  .access = access_pmu_evcntr, .reset = reset_unknown,
-	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
+	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
+	  .set_user = set_pmu_evcntr },
 	{ PMU_SYS_REG(PMXEVTYPER_EL0),
 	  .access = access_pmu_evtyper, .reset = NULL },
 	{ PMU_SYS_REG(PMXEVCNTR_EL0),
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 28b380ad8dfa942c4275e0c7ed3535d309b81b2f..9c062756ebfad5ea555362154459ffe9f8311c6d 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -41,6 +41,7 @@ bool kvm_supports_guest_pmuv3(void);
 #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);

-- 
2.48.1



From akihiko.odaki at daynix.com  Fri Mar  7 02:55:29 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Fri, 07 Mar 2025 19:55:29 +0900
Subject: [PATCH v2 2/3] KVM: arm64: PMU: Reload when user modifies
 registers
In-Reply-To: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
Message-ID: <20250307-pmc-v2-2-6c3375a5f1e4@daynix.com>

Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
run") added the code to reload the PMU configuration on first run.
Trigger the code when a user modifies a PMU register instead so that
PMU configuration changes made by users will be applied also after the
first run.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 3 ---
 arch/arm64/kvm/sys_regs.c | 5 +++++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 1402cce5625bffa706aabe5e6121d1f3817a0aaf..04eb3856b96576fad5afc8927c8916ff9738f9d7 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -888,9 +888,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 		   return -EINVAL;
 	}
 
-	/* One-off reload of the PMU on first run */
-	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 27418dac791df9a89124f867879e899db175e506..51054b7befc0b4bd822cecf717ee4a4740c4a685 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1162,6 +1162,8 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
 	else
 		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
 
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 
@@ -1322,6 +1324,8 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 		val |= ARMV8_PMU_PMCR_LC;
 
 	__vcpu_sys_reg(vcpu, r->reg) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 
@@ -4276,6 +4280,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 	}
 
 	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 }
 
 /**

-- 
2.48.1



From peter.griffin at linaro.org  Fri Mar  7 02:29:04 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 07 Mar 2025 10:29:04 +0000
Subject: [PATCH v4 0/4] samsung: pinctrl: Add support for
 eint_fltcon_offset and filter selection on gs101
Message-ID: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>

Hi folks,

This series fixes support for correctly saving and restoring fltcon0
and fltcon1 registers on gs101 for non-alive banks where the fltcon
register offset is not at a fixed offset (unlike previous SoCs).
This is done by adding a eint_fltcon_offset and providing GS101
specific pin macros that take an additional parameter (similar to
how exynosautov920 handles it's eint_con_offset).

Additionally the SoC specific suspend and resume callbacks are
re-factored so that each SoC variant has it's own callback containing
the peculiarities for that SoC.

Finally support for filter selection on alive banks is added, this is
currently only enabled for gs101. The code path can be excercised using
`echo mem > /sys/power/state`

regards,

Peter

To: Krzysztof Kozlowski <krzk at kernel.org>
To: Sylwester Nawrocki <s.nawrocki at samsung.com>
To: Alim Akhtar <alim.akhtar at samsung.com>
To: Linus Walleij <linus.walleij at linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-gpio at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: andre.draszik at linaro.org
Cc: tudor.ambarus at linaro.org
Cc: willmcvicker at google.com
Cc: semen.protsenko at linaro.org
Cc: kernel-team at android.com
Cc: jaewon02.kim at samsung.com

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes in v4:
- save->eint_fltcon1 is an argument to pr_debug(), not readl() change alignment accordingly (Andre)
- Link to v3: https://lore.kernel.org/r/20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e at linaro.org

Changes in v3:
- Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
- Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)
- Make it obvious exynos_set_wakeup() is conditional on bank type (Andre)
- Align style where the '+' is placed first (Andre)
- Remove unnecessary braces (Andre)
- Link to v2: https://lore.kernel.org/r/20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b at linaro.org

Changes in v2:
- Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
- Move filter config register comment to header file (Andre)
- Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
- Remove misleading old comment (Andre)
- Refactor exynos_eint_update_flt_reg() into a loop (Andre)
- Split refactor of suspend/resume callbacks & gs101 parts into separate patches (Andre)
- Link to v1: https://lore.kernel.org/r/20250120-pinctrl-fltcon-suspend-v1-0-e77900b2a854 at linaro.org

---
Peter Griffin (4):
      pinctrl: samsung: add support for eint_fltcon_offset
      pinctrl: samsung: add dedicated SoC eint suspend/resume callbacks
      pinctrl: samsung: add gs101 specific eint suspend/resume callbacks
      pinctrl: samsung: Add filter selection support for alive bank on gs101

 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 150 ++++++-------
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 294 +++++++++++++++----------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  50 ++++-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  12 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  12 +-
 5 files changed, 318 insertions(+), 200 deletions(-)
---
base-commit: 0761652a3b3b607787aebc386d412b1d0ae8008c
change-id: 20250120-pinctrl-fltcon-suspend-2333a137c4d4

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From peter.griffin at linaro.org  Fri Mar  7 02:29:05 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 07 Mar 2025 10:29:05 +0000
Subject: [PATCH v4 1/4] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
Message-ID: <20250307-pinctrl-fltcon-suspend-v4-1-2d775e486036@linaro.org>

On gs101 SoC the fltcon0 (filter configuration 0) offset
isn't at a fixed offset like previous SoCs as the fltcon1
register only exists when there are more than 4 pins in the
bank.

Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
macros that take an additional fltcon_offs variable.

This can then be used in suspend/resume callbacks to
save and restore the fltcon0 and fltcon1 registers.

Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 98 +++++++++++++-------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       | 22 ++++++
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  1 +
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  4 ++
 4 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 3ea7106ce5eae3c21f11790b5a40037042c1d407..e28fe81776466b693417c66bb15752d609b79eb1 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1370,83 +1370,83 @@ const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = {
 
 /* pin banks of gs101 pin-controller (ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10),
-	EXYNOS850_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14),
-	EXYNOS850_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18),
-	EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08, 0x10),
+	GS101_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c, 0x18),
+	GS101_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10, 0x1c),
+	GS101_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14, 0x20),
+	GS101_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18, 0x28),
+	GS101_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c, 0x30),
 };
 
 /* pin banks of gs101 pin-controller (FAR_ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_far_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c, 0x14),
 };
 
 /* pin banks of gs101 pin-controller (GSACORE) */
 static const struct samsung_pin_bank_data gs101_pin_gsacore[] = {
-	EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04, 0x04),
+	GS101_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08, 0x0c),
 };
 
 /* pin banks of gs101 pin-controller (GSACTRL) */
 static const struct samsung_pin_bank_data gs101_pin_gsactrl[] = {
-	EXYNOS850_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00),
+	GS101_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00, 0x00),
 };
 
 /* pin banks of gs101 pin-controller (PERIC0) */
 static const struct samsung_pin_bank_data gs101_pin_peric0[] = {
-	EXYNOS850_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c),
+	GS101_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10, 0x14),
+	GS101_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18, 0x1c),
+	GS101_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20, 0x24),
+	GS101_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24, 0x28),
+	GS101_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28, 0x2c),
+	GS101_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c, 0x30),
+	GS101_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30, 0x34),
+	GS101_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34, 0x38),
+	GS101_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38, 0x3c),
+	GS101_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c, 0x40),
+	GS101_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40, 0x44),
+	GS101_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44, 0x48),
+	GS101_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48, 0x4c),
+	GS101_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c, 0x50),
 };
 
 /* pin banks of gs101 pin-controller (PERIC1) */
 static const struct samsung_pin_bank_data gs101_pin_peric1[] = {
-	EXYNOS850_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c),
+	GS101_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14, 0x1c),
+	GS101_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c, 0x28),
 };
 
 /* pin banks of gs101 pin-controller (HSI1) */
 static const struct samsung_pin_bank_data gs101_pin_hsi1[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04, 0x08),
 };
 
 /* pin banks of gs101 pin-controller (HSI2) */
 static const struct samsung_pin_bank_data gs101_pin_hsi2[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08, 0x0c),
 };
 
 static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 7b7ff7ffeb56bdde2504ec90c8df13bdd1ace70e..33df21d5c9d61e852834031570d4a0ac0e51f6a4 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -175,6 +175,28 @@
 		.name			= id				\
 	}
 
+#define GS101_PIN_BANK_EINTG(pins, reg, id, offs, fltcon_offs) \
+	{							\
+		.type			= &exynos850_bank_type_off,	\
+		.pctl_offset		= reg,			\
+		.nr_pins		= pins,			\
+		.eint_type		= EINT_TYPE_GPIO,	\
+		.eint_offset		= offs,			\
+		.eint_fltcon_offset	= fltcon_offs,		\
+		.name			= id			\
+	}
+
+#define GS101_PIN_BANK_EINTW(pins, reg, id, offs, fltcon_offs) \
+	{								\
+		.type			= &exynos850_bank_type_alive,	\
+		.pctl_offset		= reg,				\
+		.nr_pins		= pins,				\
+		.eint_type		= EINT_TYPE_WKUP,		\
+		.eint_offset		= offs,				\
+		.eint_fltcon_offset	= fltcon_offs,			\
+		.name			= id				\
+	}
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index cfced7afd4ca6e99c7e72a588d780f0542990ed9..963060920301ec90affb2ee6d758d3d602ffb4a9 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1230,6 +1230,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
 		bank->eint_con_offset = bdata->eint_con_offset;
 		bank->eint_mask_offset = bdata->eint_mask_offset;
 		bank->eint_pend_offset = bdata->eint_pend_offset;
+		bank->eint_fltcon_offset = bdata->eint_fltcon_offset;
 		bank->name = bdata->name;
 
 		raw_spin_lock_init(&bank->slock);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index bb0689d52ea0b4392714fa9bcdcbae8d253c73a1..371e4f02bbfb375964b7833beb9bbc098a51f4a3 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -144,6 +144,7 @@ struct samsung_pin_bank_type {
  * @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  */
 struct samsung_pin_bank_data {
@@ -158,6 +159,7 @@ struct samsung_pin_bank_data {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 };
 
@@ -175,6 +177,7 @@ struct samsung_pin_bank_data {
  * @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  * @id: id of the bank, propagated to the pin range.
  * @pin_base: starting pin number of the bank.
@@ -201,6 +204,7 @@ struct samsung_pin_bank {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 	u32		id;
 

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Fri Mar  7 02:29:06 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 07 Mar 2025 10:29:06 +0000
Subject: [PATCH v4 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
Message-ID: <20250307-pinctrl-fltcon-suspend-v4-2-2d775e486036@linaro.org>

gs101 needs it's own suspend/resume callbacks to use the newly
added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
registers. It also differs to previous SoCs in that fltcon1
register doesn't always exist for each bank.

exynosautov920 also has dedicated logic for using eint_con_offset
and eint_mask_offset for saving & restoring it's registers.

Refactor the existing platform specific suspend/resume callback
so that each SoC variant has their own callback containing the
SoC specific logic.

Additionally we now call drvdata->suspend() & drvdata->resume()
from within the loop that iterates the banks in
samsung_pinctrl_suspend() and samsung_pinctrl_resume().

This simplifies the logic, and allows us to remove the
clk_enable() and clk_disable() from the callbacks.

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v3:
* save->eint_fltcon1 is an argument to pr_debug(), not readl()
  change alignment accordingly (Andre)

Changes since v2:
* Remove useless init (Andre)
* make it clear set_wakeup is conditional on bank->eint_type (Andre)

Changes since v1:
* Split code refactor & gs101 parts into separate patches (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |  28 ++--
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 201 ++++++++++---------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |   6 +-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  11 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |   8 +-
 5 files changed, 109 insertions(+), 145 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index e28fe81776466b693417c66bb15752d609b79eb1..57c98d2451b54b00d50e0e948e272ed53d386c34 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks0,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
 		.eint_wkup_init	= exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 		.retention_data	= &exynosautov920_retention_data,
 	}, {
 		/* pin-controller instance 1 AUD data */
@@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 3 HSI1 data */
 		.pin_banks	= exynosautov920_pin_banks3,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 4 HSI2 data */
 		.pin_banks	= exynosautov920_pin_banks4,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 5 HSI2UFS data */
 		.pin_banks	= exynosautov920_pin_banks5,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 6 PERIC0 data */
 		.pin_banks	= exynosautov920_pin_banks6,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 7 PERIC1 data */
 		.pin_banks	= exynosautov920_pin_banks7,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index ac6dc22b37c98ed5b7fca3335764f19abb2f71cc..75b9ab19e4e8f81bf85cd75573485b7f2e717e7b 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -761,153 +761,114 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	return 0;
 }
 
-static void exynos_pinctrl_suspend_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+static void exynos_set_wakeup(struct samsung_pin_bank *bank)
 {
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	const void __iomem *regs = bank->eint_base;
+	struct exynos_irq_chip *irq_chip;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
+	if (bank->irq_chip) {
+		irq_chip = bank->irq_chip;
+		irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
 	}
-
-	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
-	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
-					    struct samsung_pin_bank *bank)
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
-	}
-
-	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
-	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset);
+		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset + 4);
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		pr_debug("%s: save fltcon1 %#010x\n",
+			 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
 }
 
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	struct exynos_irq_chip *irq_chip = NULL;
-	int i;
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
 
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_suspend_bank(drvdata, bank);
-			else
-				exynos_pinctrl_suspend_bank(drvdata, bank);
-		}
-		else if (bank->eint_type == EINT_TYPE_WKUP) {
-			if (!irq_chip) {
-				irq_chip = bank->irq_chip;
-				irq_chip->set_eint_wakeup_mask(drvdata,
-							       irq_chip);
-			}
-		}
-	}
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + bank->pctl_offset +
+				       bank->eint_con_offset);
+		save->eint_mask = readl(regs + bank->pctl_offset +
+					bank->eint_mask_offset);
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
 }
 
-static void exynos_pinctrl_resume_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset), save->eint_fltcon0);
+		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset + 4),
+			 save->eint_fltcon1);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset);
+		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_ECON_OFFSET
-			+ bank->eint_offset), save->eint_con);
-	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset), save->eint_fltcon0);
-	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-			readl(regs + bank->irq_chip->eint_mask
-			+ bank->eint_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
 }
 
-static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
-					   struct samsung_pin_bank *bank)
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		/* exynosautov920 has eint_con_offset for all but one bank */
+		if (!bank->eint_con_offset)
+			exynos_pinctrl_resume(bank);
+
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
+			 save->eint_con);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset +
+			       bank->eint_mask_offset), save->eint_mask);
+
+		writel(save->eint_con,
+		       regs + bank->pctl_offset + bank->eint_con_offset);
+		writel(save->eint_mask,
+		       regs + bank->pctl_offset + bank->eint_mask_offset);
 	}
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
-	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	clk_disable(bank->drvdata->pclk);
-}
-
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	int i;
-
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_resume_bank(drvdata, bank);
-			else
-				exynos_pinctrl_resume_bank(drvdata, bank);
-		}
 }
 
 static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 33df21d5c9d61e852834031570d4a0ac0e51f6a4..35c2bc4ea488bda600ebfbda1492f5f49dbd9849 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -221,8 +221,10 @@ struct exynos_muxed_weint_data {
 
 int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
 int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 963060920301ec90affb2ee6d758d3d602ffb4a9..375634d8cc79d6533603e3eed562452181e2ee25 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->suspend)
+			drvdata->suspend(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
@@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 
 	clk_disable(drvdata->pclk);
 
-	if (drvdata->suspend)
-		drvdata->suspend(drvdata);
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
 		drvdata->retention_ctrl->enable(drvdata);
 
@@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		return ret;
 	}
 
-	if (drvdata->resume)
-		drvdata->resume(drvdata);
-
 	for (i = 0; i < drvdata->nr_banks; i++) {
 		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
 		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
@@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->resume)
+			drvdata->resume(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 371e4f02bbfb375964b7833beb9bbc098a51f4a3..e939e5bb0347458ae4a9014fd9657fc59c5c3994 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
 	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
 	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
 	void		(*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
-	void		(*suspend)(struct samsung_pinctrl_drv_data *);
-	void		(*resume)(struct samsung_pinctrl_drv_data *);
+	void		(*suspend)(struct samsung_pin_bank *bank);
+	void		(*resume)(struct samsung_pin_bank *bank);
 };
 
 /**
@@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
 
 	struct samsung_retention_ctrl	*retention_ctrl;
 
-	void (*suspend)(struct samsung_pinctrl_drv_data *);
-	void (*resume)(struct samsung_pinctrl_drv_data *);
+	void (*suspend)(struct samsung_pin_bank *bank);
+	void (*resume)(struct samsung_pin_bank *bank);
 };
 
 /**

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Fri Mar  7 02:29:07 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 07 Mar 2025 10:29:07 +0000
Subject: [PATCH v4 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
Message-ID: <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org>

gs101 differs to other SoCs in that fltcon1 register doesn't
always exist. Additionally the offset of fltcon0 is not fixed
and needs to use the newly added eint_fltcon_offset variable.

Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v2:
* make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
* align style where the '+' is placed (Andre)
* remove unnecessary braces (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 70 ++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  2 +
 3 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 57c98d2451b54b00d50e0e948e272ed53d386c34..fca447ebc5f5956b7e8d2f2d08f23622095b1ee6 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1455,15 +1455,15 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (FAR_ALIVE) */
 		.pin_banks	= gs101_pin_far_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_far_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (GSACORE) */
 		.pin_banks	= gs101_pin_gsacore,
@@ -1477,29 +1477,29 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_peric0,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric0),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (PERIC1) */
 		.pin_banks	= gs101_pin_peric1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume	= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI1) */
 		.pin_banks	= gs101_pin_hsi1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI2) */
 		.pin_banks	= gs101_pin_hsi2,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi2),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 75b9ab19e4e8f81bf85cd75573485b7f2e717e7b..5f0045d03346600557fa6735bad709897c71935c 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -798,6 +798,40 @@ void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 		exynos_set_wakeup(bank);
 }
 
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + bank->eint_fltcon_offset);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			save->eint_fltcon1 = readl(regs +
+						EXYNOS_GPIO_EFLTCON_OFFSET
+						+ bank->eint_fltcon_offset + 4);
+
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		if (bank->nr_pins > 4)
+			pr_debug("%s: save fltcon1 %#010x\n",
+				 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP)
+		exynos_set_wakeup(bank);
+}
+
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
@@ -816,6 +850,42 @@ void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 		exynos_set_wakeup(bank);
 }
 
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+
+	void __iomem *regs = bank->eint_base;
+	void __iomem *eint_fltcfg0 = regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		     + bank->eint_fltcon_offset;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(eint_fltcfg0), save->eint_fltcon0);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+				 readl(eint_fltcfg0 + 4), save->eint_fltcon1);
+
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, eint_fltcfg0);
+
+		if (bank->nr_pins > 4)
+			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
+	}
+}
+
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 35c2bc4ea488bda600ebfbda1492f5f49dbd9849..773f161a82a38cbaad05fcbc09a936300f5c7595 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -225,6 +225,8 @@ void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank);
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peter.griffin at linaro.org  Fri Mar  7 02:29:08 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 07 Mar 2025 10:29:08 +0000
Subject: [PATCH v4 4/4] pinctrl: samsung: Add filter selection support for
 alive bank on gs101
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
Message-ID: <20250307-pinctrl-fltcon-suspend-v4-4-2d775e486036@linaro.org>

Newer Exynos based SoCs have a filter selection bitfield in the filter
configuration registers on alive bank pins. This allows the selection of
a digital or analog delay filter for each pin. Add support for selecting
and enabling the filter.

On suspend we set the analog filter to all pins in the bank (as the
digital filter relies on a clock). On resume the digital filter is
reapplied to all pins in the bank. The digital filter is working via
a clock and has an adjustable filter delay flt_width bitfield, whereas
the analog filter uses a fixed delay.

The filter determines to what extent signal fluctuations received through
the pad are considered glitches.

The code path can be exercised using
echo mem > /sys/power/state
And then wake the device using a eint gpio

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---

Changes since v2:
* Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
* Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)

Changes since v1:
* Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
* Move filter config comment to header (Andre)
* Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
* Remove misleading old comment (Andre)
* Refactor exynos_eint_update_flt_reg() into a loop (Andre)

Note: this patch was previously sent as part of the initial gs101/ Pixel 6
series and was dropped in v6. This new version incorporates the review
feedback from Sam Protsenko here in v5.

Link: https://lore.kernel.org/all/20231201160925.3136868-1-peter.griffin at linaro.org/T/#m79ced98939e895c840d812c8b4c2b3f33ce604c8

Changes since previous version
* Drop fltcon_type enum and use bool eint_flt_selectable (Sam)
* Refactor and add exynos_eint_update_flt_reg() (Sam)
* Rename function to exynos_eint_set_filter() for easier readability (Sam)
* Remove comments and `if bank->fltcon_type != FLT_DEFAULT)` checks and indentation (Sam)
---
 drivers/pinctrl/samsung/pinctrl-exynos.c | 37 +++++++++++++++++++++++++++++++-
 drivers/pinctrl/samsung/pinctrl-exynos.h | 20 +++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 5f0045d03346600557fa6735bad709897c71935c..1d2a4f4b825fce4be3f3d337145f2a4128315f0b 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -369,6 +369,37 @@ struct exynos_eint_gpio_save {
 	u32 eint_mask;
 };
 
+static void exynos_eint_update_flt_reg(void __iomem *reg, int cnt, int con)
+{
+	unsigned int val, shift;
+	int i;
+
+	val = readl(reg);
+	for (i = 0; i < cnt; i++) {
+		shift = i * EXYNOS_FLTCON_LEN;
+		val &= ~(EXYNOS_FLTCON_DIGITAL << shift);
+		val |= con << shift;
+	}
+	writel(val, reg);
+}
+
+/*
+ * Set the desired filter (digital or analog delay) and enable it to
+ * every pin in the bank. Note the filter selection bitfield is only
+ * found on alive banks. The filter determines to what extent signal
+ * fluctuations received through the pad are considered glitches.
+ */
+static void exynos_eint_set_filter(struct samsung_pin_bank *bank, int filter)
+{
+	unsigned int off = EXYNOS_GPIO_EFLTCON_OFFSET + bank->eint_fltcon_offset;
+	void __iomem *reg = bank->drvdata->virt_base + off;
+	unsigned int con = EXYNOS_FLTCON_EN | filter;
+
+	for (int n = 0; n < bank->nr_pins; n += 4)
+		exynos_eint_update_flt_reg(reg + n,
+					   min(bank->nr_pins - n, 4), con);
+}
+
 /*
  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
  * @d: driver data of samsung pinctrl driver.
@@ -828,8 +859,10 @@ void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
 				 bank->name, save->eint_fltcon1);
 		pr_debug("%s: save    mask %#010x\n",
 			 bank->name, save->eint_mask);
-	} else if (bank->eint_type == EINT_TYPE_WKUP)
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
 		exynos_set_wakeup(bank);
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_ANALOG);
+	}
 }
 
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
@@ -883,6 +916,8 @@ void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
 			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
 		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 		       + bank->eint_offset);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_DIGITAL);
 	}
 }
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 773f161a82a38cbaad05fcbc09a936300f5c7595..66acbd08d3445ca6ee7358d3c4a6cb2be5d82842 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -52,6 +52,26 @@
 #define EXYNOS_EINT_MAX_PER_BANK	8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
+/*
+ * EINT filter configuration register (on alive banks) has
+ * the following layout.
+ *
+ * BitfieldName[PinNum][Bit:Bit]
+ * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24]
+ * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16]
+ * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8]
+ * FLT_EN[0][7]  FLT_SEL[0][6]  FLT_WIDTH[0][5:0]
+ *
+ * FLT_EN	0x0 = Disable, 0x1=Enable
+ * FLT_SEL	0x0 = Analog delay filter, 0x1 Digital filter (clock count)
+ * FLT_WIDTH	Filtering width. Valid when FLT_SEL is 0x1
+ */
+
+#define EXYNOS_FLTCON_EN		BIT(7)
+#define EXYNOS_FLTCON_DIGITAL		BIT(6)
+#define EXYNOS_FLTCON_ANALOG		(0 << 6)
+#define EXYNOS_FLTCON_LEN		8
+
 #define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
 	{						\
 		.type		= &bank_type_off,	\

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From danishanwar at ti.com  Fri Mar  7 02:30:40 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Fri, 7 Mar 2025 16:00:40 +0530
Subject: [PATCH net-next v2] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250306165513.541ff46e@kernel.org>
References: <20250305111608.520042-1-danishanwar@ti.com>
 <20250306165513.541ff46e@kernel.org>
Message-ID: <3931a391-3967-4260-a104-4eb313810c0d@ti.com>

Hi Jakub

On 07/03/25 6:25 am, Jakub Kicinski wrote:
> On Wed, 5 Mar 2025 16:46:08 +0530 MD Danish Anwar wrote:
>> + - ``FW_RTU_PKT_DROP``: Diagnostic error counter which increments when RTU drops a locally injected packet due to port being disabled or rule violation.
>> + - ``FW_Q0_OVERFLOW``: TX overflow counter for queue0
>> + - ``FW_Q1_OVERFLOW``: TX overflow counter for queue1
>> + - ``FW_Q2_OVERFLOW``: TX overflow counter for queue2
>> + - ``FW_Q3_OVERFLOW``: TX overflow counter for queue3
>> + - ``FW_Q4_OVERFLOW``: TX overflow counter for queue4
>> + - ``FW_Q5_OVERFLOW``: TX overflow counter for queue5
>> + - ``FW_Q6_OVERFLOW``: TX overflow counter for queue6
>> + - ``FW_Q7_OVERFLOW``: TX overflow counter for queue7
> ...
> 
> Thanks for the docs, it looks good. Now, do all of these get included
> in the standard stats returned by icssg_ndo_get_stats64 ?
> That's the primary source of information for the user regarding packet
> loss.

No, these are not reported via icssg_ndo_get_stats64.

.ndo_get_stats64 populates stats that are part of `struct
rtnl_link_stats64`. icssg_ndo_get_stats64 populates those stats wherever
applicable. These firmware stats are not same as the ones defined in
`icssg_ndo_get_stats64` hence they are not populated. They are not
standard stats, they will be dumped by `ethtool -S`. Wherever there is a
standard stats, I will make sure it gets dumped from the standard
interface instead of `ethtool -S`

Only below stats are included in the standard stats returned by
icssg_ndo_get_stats64
- rx_packets
- rx_bytes
- tx_packets
- tx_bytes
- rx_crc_errors
- rx_over_errors
- rx_multicast_frames

> 
>>  	if (prueth->pa_stats) {
>>  		for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) {
>> -			reg = ICSSG_FW_STATS_BASE +
>> -			      icssg_all_pa_stats[i].offset *
>> -			      PRUETH_NUM_MACS + slice * sizeof(u32);
>> +			reg = icssg_all_pa_stats[i].offset +
>> +			      slice * sizeof(u32);
>>  			regmap_read(prueth->pa_stats, reg, &val);
>>  			emac->pa_stats[i] += val;
> 
> This gets called by icssg_ndo_get_stats64() which is under RCU 

Yes, this does get called by icssg_ndo_get_stats64(). Apart from that
there is a workqueue (`icssg_stats_work_handler`) that calls this API
periodically and updates the emac->stats and emac->pa_stats arrays.

> protection and nothing else. I don't see any locking here, and

There is no locking here. I don't think this is related to the patch.
The API emac_update_hardware_stats() updates all the stats supported by
ICSSG not just standard stats.

> I hope the regmap doesn't sleep. cat /proc/net/dev to test.
> You probably need to send some fixes to net.

I checked cat /proc/net/dev and the stats shown there are not related to
the stats I am introducing in this series.

The fix could be to add a lock in this function, but we have close to 90
stats and this function is called not only from icssg_ndo_get_stats64()
but from emac_get_ethtool_stats(). The function also gets called
periodically (Every 25 Seconds for 1G Link). I think every time locking
90 regmap_reads() could result in performance degradation.

I only see couple of drivers acquiring spin lock before reading the
stats for .ndo_get_stats64. Most of the drivers are not using any lock.

I did some testing and did not see any discrepancy in the stats `cat
/proc/net/dev` without the lock.

Furthermore, the fix is independent of this patch. I can send out a
separate fix to net to add cpu locks to this function. But I don't think
there is any change needed in this patch.

Let me know what should be done here.

-- 
Thanks and Regards,
Danish


From s-vadapalli at ti.com  Fri Mar  7 02:31:24 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 7 Mar 2025 16:01:24 +0530
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
Message-ID: <20250307103128.3287497-1-s-vadapalli@ti.com>

Hello,

This series enables support to build the PCIe Cadence Controller drivers
and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
Modules. The motivation for this series is that PCIe is not a necessity
for booting the SoC, due to which it doesn't have to be a built-in
module. Additionally, the defconfig doesn't enable the PCIe Cadence
Controller drivers and the PCI J721E driver, due to which PCIe is not
supported by default. Enabling the configs as of now (i.e. without this
series) will result in built-in drivers i.e. a bloated Linux Image for
everyone who doesn't have the PCIe Controller. Therefore, with this
series, after enabling support for building the drivers as loadable
modules, the driver configs can be enabled in the defconfig to build
the drivers as loadable modules, thereby enabling PCIe.

Series is based on linux-next tagged next-20250306.

--------------------------
Series has been tested for
--------------------------
[1] Loading and Unloading the PCI J721E driver when operating in the
Root-Complex mode on J721E-EVM with an NVMe SSD connected to the PCIe
Connector. "hdparm" based reads of the NVMe SSD have been performed to
validated functionality before and after a module unload-load sequence
using modprobe. Logs:
https://gist.github.com/Siddharth-Vadapalli-at-TI/085fd24d416bab5dc7d798156ce130b3

[2] Loading and Unloading the PCI J721E driver when operating in the
Endpoint mode on J784S4-EVM with 6 Physical Functions configured in the
Endpoint and connected to the J721E-EVM as the Root-Complex. Logs:
https://gist.github.com/Siddharth-Vadapalli-at-TI/1ec568a76bc3ebc1082d434aab4ab00b

The following changes to arch/arm64/configs/defconfig were made to test
this series and will be posted as a patch after this series gets merged:
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3a3706db2982..0ca073141c3e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -209,6 +209,12 @@ CONFIG_NFC=m
 CONFIG_NFC_NCI=m
 CONFIG_NFC_S3FWRN5_I2C=m
 CONFIG_PCI=y
+CONFIG_PCI_J721E=m
+CONFIG_PCI_J721E_HOST=m
+CONFIG_PCI_J721E_EP=m
+CONFIG_PCIE_CADENCE=m
+CONFIG_PCIE_CADENCE_HOST=m
+CONFIG_PCIE_CADENCE_EP=m
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
 CONFIG_PCI_IOV=y

Regards,
Siddharth.

Kishon Vijay Abraham I (1):
  PCI: cadence: Add support to build pcie-cadence library as a kernel
    module

Siddharth Vadapalli (3):
  PCI: cadence-host: Introduce cdns_pcie_host_disable helper for cleanup
  PCI: cadence-ep: Introduce cdns_pcie_ep_disable helper for cleanup
  PCI: j721e: Add support to build as a loadable module

 drivers/pci/controller/cadence/Kconfig        |  12 +-
 drivers/pci/controller/cadence/pci-j721e.c    |  37 +++++-
 .../pci/controller/cadence/pcie-cadence-ep.c  |  16 +++
 .../controller/cadence/pcie-cadence-host.c    | 113 ++++++++++++++++++
 drivers/pci/controller/cadence/pcie-cadence.c |  12 ++
 drivers/pci/controller/cadence/pcie-cadence.h |  14 ++-
 6 files changed, 194 insertions(+), 10 deletions(-)

-- 
2.34.1



From s-vadapalli at ti.com  Fri Mar  7 02:31:26 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 7 Mar 2025 16:01:26 +0530
Subject: [PATCH 2/4] PCI: cadence-host: Introduce cdns_pcie_host_disable helper for cleanup
In-Reply-To: <20250307103128.3287497-1-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
Message-ID: <20250307103128.3287497-3-s-vadapalli@ti.com>

Introduce the helper function cdns_pcie_host_disable() which will undo
the configuration performed by cdns_pcie_host_setup(). Also, export it
for use by existing callers of cdns_pcie_host_setup(), thereby allowing
them to cleanup on their exit path.

Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---
 .../controller/cadence/pcie-cadence-host.c    | 104 ++++++++++++++++++
 drivers/pci/controller/cadence/pcie-cadence.h |   5 +
 2 files changed, 109 insertions(+)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 96055edeb099..741508738f88 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -152,6 +152,14 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie)
 	return ret;
 }
 
+static void cdns_pcie_host_disable_ptm_response(struct cdns_pcie *pcie)
+{
+	u32 val;
+
+	val = cdns_pcie_readl(pcie, CDNS_PCIE_LM_PTM_CTRL);
+	cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val & ~CDNS_PCIE_LM_TPM_CTRL_PTMRSEN);
+}
+
 static void cdns_pcie_host_enable_ptm_response(struct cdns_pcie *pcie)
 {
 	u32 val;
@@ -177,6 +185,26 @@ static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
 	return ret;
 }
 
+static void cdns_pcie_host_deinit_root_port(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+	u32 value, ctrl;
+
+	cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, 0xffff);
+	cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0xff);
+	cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0xff);
+	cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, 0xffffffff);
+	cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, 0xffff);
+	ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
+	value = ~(CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
+		CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
+		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
+		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
+		CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
+		CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS);
+	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
+}
+
 static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -393,6 +421,32 @@ static int cdns_pcie_host_dma_ranges_cmp(void *priv, const struct list_head *a,
         return resource_size(entry2->res) - resource_size(entry1->res);
 }
 
+static void cdns_pcie_host_unmap_dma_ranges(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+	enum cdns_pcie_rp_bar bar;
+	u32 value;
+
+	/* Reset inbound configuration for all BARs which were being used */
+	for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
+		if (rc->avail_ib_bar[bar])
+			continue;
+
+		cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), 0);
+		cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), 0);
+
+		if (bar == RP_NO_BAR)
+			continue;
+
+		value = ~(LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar) |
+			  LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar) |
+			  LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar) |
+			  LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar) |
+			  LM_RC_BAR_CFG_APERTURE(bar, bar_aperture_mask[bar] + 2));
+		cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
+	}
+}
+
 static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -430,6 +484,29 @@ static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
 	return 0;
 }
 
+static void cdns_pcie_host_deinit_address_translation(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
+	struct resource_entry *entry;
+	int r;
+
+	cdns_pcie_host_unmap_dma_ranges(rc);
+
+	/*
+	 * Reset outbound region 0 which was reserved for configuration space
+	 * accesses.
+	 */
+	cdns_pcie_reset_outbound_region(pcie, 0);
+
+	/* Reset rest of the outbound regions */
+	r = 1;
+	resource_list_for_each_entry(entry, &bridge->windows) {
+		cdns_pcie_reset_outbound_region(pcie, r);
+		r++;
+	}
+}
+
 static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -487,6 +564,12 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
 	return cdns_pcie_host_map_dma_ranges(rc);
 }
 
+static void cdns_pcie_host_deinit(struct cdns_pcie_rc *rc)
+{
+	cdns_pcie_host_deinit_address_translation(rc);
+	cdns_pcie_host_deinit_root_port(rc);
+}
+
 int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
 {
 	int err;
@@ -499,6 +582,14 @@ int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
 }
 EXPORT_SYMBOL_GPL(cdns_pcie_host_init);
 
+static void cdns_pcie_host_link_disable(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+
+	cdns_pcie_stop_link(pcie);
+	cdns_pcie_host_disable_ptm_response(pcie);
+}
+
 int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -524,6 +615,19 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 }
 EXPORT_SYMBOL_GPL(cdns_pcie_host_link_setup);
 
+void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
+{
+	struct pci_host_bridge *bridge;
+
+	bridge = pci_host_bridge_from_priv(rc);
+	pci_stop_root_bus(bridge->bus);
+	pci_remove_root_bus(bridge->bus);
+
+	cdns_pcie_host_deinit(rc);
+	cdns_pcie_host_link_disable(rc);
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_host_disable);
+
 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
 {
 	struct device *dev = rc->pcie.dev;
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index c671e25a481b..9068f140596a 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -523,6 +523,7 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
 int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc);
 int cdns_pcie_host_init(struct cdns_pcie_rc *rc);
 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
+void cdns_pcie_host_disable(struct cdns_pcie_rc *rc);
 void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 			       int where);
 #else
@@ -541,6 +542,10 @@ static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
 	return 0;
 }
 
+static inline void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
+{
+}
+
 static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 					     int where)
 {
-- 
2.34.1



From s-vadapalli at ti.com  Fri Mar  7 02:31:25 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 7 Mar 2025 16:01:25 +0530
Subject: [PATCH 1/4] PCI: cadence: Add support to build pcie-cadence library as a kernel module
In-Reply-To: <20250307103128.3287497-1-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
Message-ID: <20250307103128.3287497-2-s-vadapalli@ti.com>

From: Kishon Vijay Abraham I <kishon at ti.com>

Currently, the Cadence PCIe controller driver can be built as a built-in
module only. Since PCIe functionality is not a necessity for booting, add
support to build the Cadence PCIe driver as a loadable module as well.

Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---
 drivers/pci/controller/cadence/Kconfig             |  6 +++---
 drivers/pci/controller/cadence/pcie-cadence-ep.c   |  6 ++++++
 drivers/pci/controller/cadence/pcie-cadence-host.c |  9 +++++++++
 drivers/pci/controller/cadence/pcie-cadence.c      | 12 ++++++++++++
 drivers/pci/controller/cadence/pcie-cadence.h      |  4 ++--
 5 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
index 8a0044bb3989..82b58096eea0 100644
--- a/drivers/pci/controller/cadence/Kconfig
+++ b/drivers/pci/controller/cadence/Kconfig
@@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
 	depends on PCI
 
 config PCIE_CADENCE
-	bool
+	tristate
 
 config PCIE_CADENCE_HOST
-	bool
+	tristate
 	depends on OF
 	select IRQ_DOMAIN
 	select PCIE_CADENCE
 
 config PCIE_CADENCE_EP
-	bool
+	tristate
 	depends on OF
 	depends on PCI_ENDPOINT
 	select PCIE_CADENCE
diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index a4f7ed04d38b..eeb2afdd223e 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -6,6 +6,7 @@
 #include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pci-epc.h>
 #include <linux/platform_device.h>
@@ -752,3 +753,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_ep_setup);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence PCIe endpoint controller driver");
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen at free-electrons.com>");
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 8af95e9da7ce..96055edeb099 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -5,6 +5,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/list_sort.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -72,6 +73,7 @@ void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 
 	return rc->cfg_base + (where & 0xfff);
 }
+EXPORT_SYMBOL_GPL(cdns_pci_map_bus);
 
 static struct pci_ops cdns_pcie_host_ops = {
 	.map_bus	= cdns_pci_map_bus,
@@ -495,6 +497,7 @@ int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
 
 	return cdns_pcie_host_init_address_translation(rc);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_host_init);
 
 int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 {
@@ -519,6 +522,7 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_host_link_setup);
 
 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
 {
@@ -581,3 +585,8 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_host_setup);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence PCIe host controller driver");
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen at free-electrons.com>");
diff --git a/drivers/pci/controller/cadence/pcie-cadence.c b/drivers/pci/controller/cadence/pcie-cadence.c
index 204e045aed8c..70a19573440e 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.c
+++ b/drivers/pci/controller/cadence/pcie-cadence.c
@@ -4,6 +4,7 @@
 // Author: Cyrille Pitchen <cyrille.pitchen at free-electrons.com>
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 
 #include "pcie-cadence.h"
@@ -23,6 +24,7 @@ void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie)
 
 	cdns_pcie_writel(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP, ltssm_control_cap);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_detect_quiet_min_delay_set);
 
 void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
 				   u32 r, bool is_io,
@@ -100,6 +102,7 @@ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region);
 
 void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
 						  u8 busnr, u8 fn,
@@ -134,6 +137,7 @@ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region_for_normal_msg);
 
 void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
 {
@@ -146,6 +150,7 @@ void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_reset_outbound_region);
 
 void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
 {
@@ -156,6 +161,7 @@ void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
 		phy_exit(pcie->phy[i]);
 	}
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_disable_phy);
 
 int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
 {
@@ -184,6 +190,7 @@ int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_enable_phy);
 
 int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
 {
@@ -243,6 +250,7 @@ int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_init_phy);
 
 static int cdns_pcie_suspend_noirq(struct device *dev)
 {
@@ -271,3 +279,7 @@ const struct dev_pm_ops cdns_pcie_pm_ops = {
 	NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq,
 				  cdns_pcie_resume_noirq)
 };
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence PCIe controller driver");
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen at free-electrons.com>");
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index f5eeff834ec1..c671e25a481b 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -519,7 +519,7 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
 	return true;
 }
 
-#ifdef CONFIG_PCIE_CADENCE_HOST
+#if IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)
 int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc);
 int cdns_pcie_host_init(struct cdns_pcie_rc *rc);
 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
@@ -548,7 +548,7 @@ static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int d
 }
 #endif
 
-#ifdef CONFIG_PCIE_CADENCE_EP
+#if IS_ENABLED(CONFIG_PCIE_CADENCE_EP)
 int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep);
 #else
 static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
-- 
2.34.1



From s-vadapalli at ti.com  Fri Mar  7 02:31:27 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 7 Mar 2025 16:01:27 +0530
Subject: [PATCH 3/4] PCI: cadence-ep: Introduce cdns_pcie_ep_disable helper for cleanup
In-Reply-To: <20250307103128.3287497-1-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
Message-ID: <20250307103128.3287497-4-s-vadapalli@ti.com>

Introduce the helper function cdns_pcie_ep_disable() which will undo the
configuration performed by cdns_pcie_ep_setup(). Also, export it for use
by the existing callers of cdns_pcie_ep_setup(), thereby allowing them
to cleanup on their exit path.

Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++++++
 drivers/pci/controller/cadence/pcie-cadence.h    |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index eeb2afdd223e..85bec57fa5d9 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -646,6 +646,16 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
 	.get_features	= cdns_pcie_ep_get_features,
 };
 
+void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
+{
+	struct device *dev = ep->pcie.dev;
+	struct pci_epc *epc = to_pci_epc(dev);
+
+	pci_epc_mem_free_addr(epc, ep->irq_phys_addr, ep->irq_cpu_addr,
+			      SZ_128K);
+	pci_epc_mem_exit(epc);
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_ep_disable);
 
 int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 {
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 9068f140596a..c2b9dbb7e1db 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -555,11 +555,16 @@ static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int d
 
 #if IS_ENABLED(CONFIG_PCIE_CADENCE_EP)
 int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep);
+void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep);
 #else
 static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 {
 	return 0;
 }
+
+static inline void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
+{
+}
 #endif
 
 void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie);
-- 
2.34.1



From cki-project at redhat.com  Fri Mar  7 02:32:06 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 10:32:06 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <20477.125030705320900185@us-mta-100.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704576917

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704576917-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From s-vadapalli at ti.com  Fri Mar  7 02:31:28 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 7 Mar 2025 16:01:28 +0530
Subject: [PATCH 4/4] PCI: j721e: Add support to build as a loadable module
In-Reply-To: <20250307103128.3287497-1-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
Message-ID: <20250307103128.3287497-5-s-vadapalli@ti.com>

The 'pci-j721e.c' driver is the application/glue/wrapper driver for the
Cadence PCIe Controllers on TI SoCs. Implement support for building it as a
loadable module.

Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---
 drivers/pci/controller/cadence/Kconfig     |  6 ++--
 drivers/pci/controller/cadence/pci-j721e.c | 37 ++++++++++++++++++++--
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
index 82b58096eea0..72d7d264d6c3 100644
--- a/drivers/pci/controller/cadence/Kconfig
+++ b/drivers/pci/controller/cadence/Kconfig
@@ -43,10 +43,10 @@ config PCIE_CADENCE_PLAT_EP
 	  different vendors SoCs.
 
 config PCI_J721E
-	bool
+	tristate
 
 config PCI_J721E_HOST
-	bool "TI J721E PCIe controller (host mode)"
+	tristate "TI J721E PCIe controller (host mode)"
 	depends on ARCH_K3 || COMPILE_TEST
 	depends on OF
 	select PCIE_CADENCE_HOST
@@ -57,7 +57,7 @@ config PCI_J721E_HOST
 	  core.
 
 config PCI_J721E_EP
-	bool "TI J721E PCIe controller (endpoint mode)"
+	tristate "TI J721E PCIe controller (endpoint mode)"
 	depends on ARCH_K3 || COMPILE_TEST
 	depends on OF
 	depends on PCI_ENDPOINT
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index 0341d51d6aed..0900e7dd6ac7 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -15,6 +15,7 @@
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
@@ -27,6 +28,7 @@
 #define cdns_pcie_to_rc(p) container_of(p, struct cdns_pcie_rc, pcie)
 
 #define ENABLE_REG_SYS_2	0x108
+#define ENABLE_CLR_REG_SYS_2	0x308
 #define STATUS_REG_SYS_2	0x508
 #define STATUS_CLR_REG_SYS_2	0x708
 #define LINK_DOWN		BIT(1)
@@ -116,6 +118,15 @@ static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
+static void j721e_pcie_disable_link_irq(struct j721e_pcie *pcie)
+{
+	u32 reg;
+
+	reg = j721e_pcie_intd_readl(pcie, ENABLE_CLR_REG_SYS_2);
+	reg |= pcie->linkdown_irq_regfield;
+	j721e_pcie_intd_writel(pcie, ENABLE_CLR_REG_SYS_2, reg);
+}
+
 static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie)
 {
 	u32 reg;
@@ -632,9 +643,27 @@ static void j721e_pcie_remove(struct platform_device *pdev)
 	struct j721e_pcie *pcie = platform_get_drvdata(pdev);
 	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
 	struct device *dev = &pdev->dev;
+	struct cdns_pcie_ep *ep;
+	struct cdns_pcie_rc *rc;
+
+	if (pcie->mode == PCI_MODE_RC) {
+		rc = container_of(cdns_pcie, struct cdns_pcie_rc, pcie);
+		cdns_pcie_host_disable(rc);
+	} else {
+		ep = container_of(cdns_pcie, struct cdns_pcie_ep, pcie);
+		cdns_pcie_ep_disable(ep);
+	}
+
+	if (pcie->reset_gpio) {
+		msleep(PCIE_T_PVPERL_MS);
+		gpiod_set_value_cansleep(pcie->reset_gpio, 1);
+	}
+
+	if (pcie->refclk)
+		clk_disable_unprepare(pcie->refclk);
 
-	clk_disable_unprepare(pcie->refclk);
 	cdns_pcie_disable_phy(cdns_pcie);
+	j721e_pcie_disable_link_irq(pcie);
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
 }
@@ -729,4 +758,8 @@ static struct platform_driver j721e_pcie_driver = {
 		.pm	= pm_sleep_ptr(&j721e_pcie_pm_ops),
 	},
 };
-builtin_platform_driver(j721e_pcie_driver);
+module_platform_driver(j721e_pcie_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCIe controller driver for TI's J721E and related SoCs");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon at ti.com>");
-- 
2.34.1



From vigneshr at ti.com  Fri Mar  7 02:35:55 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Fri, 7 Mar 2025 16:05:55 +0530
Subject: [PATCH 1/2] arm64: dts: ti: k3-am62p: fix pinctrl settings
In-Reply-To: <20250221091447.595199-1-mwalle@kernel.org>
References: <20250221091447.595199-1-mwalle@kernel.org>
Message-ID: <174133309361.1072814.8037717583251450140.b4-ty@ti.com>

Hi Michael Walle,

On Fri, 21 Feb 2025 10:14:46 +0100, Michael Walle wrote:
> It appears that pinctrl-single is misused on this SoC to control both
> the mux and the input and output and bias settings. This results in
> non-working pinctrl configurations for GPIOs within the device tree.
> 
> This is what happens:
>  (1) During startup the pinctrl settings are applied according to the
>      device tree. I.e. the pin is configured as output and with
>      pull-ups enabled.
>  (2) During startup a device driver requests a GPIO.
>  (3) pinctrl-single is applying the default GPIO setting according to
>      the pinctrl-single,gpio-range property.
> 
> [...]

> Maybe one could also switch the pinctrl-single to a pinconf-single node
> which is able to control all the bias settings and restrict
> "pinctrl-single,function-mask" to just the actual function. Not
> sure

I agree, we should probably migrate to pinconf-single bindings in long
term. There is just too much legacy code and tools relying on current
bindings though. Something for look at for next SoC. Thanks for the
patch!


I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/2] arm64: dts: ti: k3-am62p: fix pinctrl settings
      commit: 33bab9d84e52188cf73c3573fd7cf3ec0e01d007
[2/2] arm64: dts: ti: k3-j722s: fix pinctrl settings
      commit: 06daad327d043c23bc1ab4cdb519f589094b9e98

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Fri Mar  7 02:36:15 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Fri, 7 Mar 2025 16:06:15 +0530
Subject: [PATCH 0/5] Add J722S CSI support
In-Reply-To: <20250218185452.600797-1-vaishnav.a@ti.com>
References: <20250218185452.600797-1-vaishnav.a@ti.com>
Message-ID: <174133309362.1072814.5440404016847301624.b4-ty@ti.com>

Hi Vaishnav Achath,

On Wed, 19 Feb 2025 00:24:47 +0530, Vaishnav Achath wrote:
> This series adds support for CSI2RX capture on J722S EVM
> and enables IMX219 and OV5640 overlays to enables
> 4 sensors on EVM, this provides a reference for a user to
> enable a different sensor on any of the ports.
> 
> Test logs:
> IMX219: https://gist.github.com/vaishnavachath/60cc2ef257601f27f28a315f8cf669c4
> OV5640: https://gist.github.com/vaishnavachath/648202286d4d34d4d25f7c8c9db8b8bd
> 
> [...]

I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/5] arm64: dts: ti: k3-j722s-main: Add BCDMA CSI overrides
      commit: fb1b230bf9c45f5d6579dc329c2aafcd1263b70a
[2/5] arm64: dts: ti: k3-j722s-main: Add CSI2RX nodes
      commit: 8fea4519f625e6c1b05078f2ecea252b7b28b06e
[3/5] arm64: dts: ti: k3-j722s-evm: Add camera peripherals
      commit: ce553288ad2368f0d27e47b39a23121a825a2b33
[4/5] arm64: dts: ti: k3-j722s-evm: Add overlay for quad IMX219
      commit: c24ccb1cd77fb44087b2f7008d99626796b33ca4
[5/5] arm64: dts: ti: k3-j722s-evm: Add overlay for TEVI OV5640
      commit: 938806652b0a3c90d67e7137c91708d06940b03d

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Fri Mar  7 02:36:36 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Fri, 7 Mar 2025 16:06:36 +0530
Subject: [PATCH v2 1/5] arm64: dts: ti: k3-am62x-phyboard-lyra: Add boot phase tags
In-Reply-To: <20250305085537.3976579-1-w.egorov@phytec.de>
References: <20250305085537.3976579-1-w.egorov@phytec.de>
Message-ID: <174133309362.1072814.1438889304366712802.b4-ty@ti.com>

Hi Wadim Egorov,

On Wed, 05 Mar 2025 09:55:33 +0100, Wadim Egorov wrote:
> The bootph-all and bootph-pre-ram tags were introduced in dt-schema
> (dtschema/schemas/bootph.yaml) to define node usage across different
> boot phases.
> 
> Add boot phase tags to all required nodes to ensure boot support from
> all sources, including UART, USB (DFU), Ethernet, uSD card, eMMC, and
> OSPI NOR Flash.
> 
> [...]

I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/5] arm64: dts: ti: k3-am62x-phyboard-lyra: Add boot phase tags
      commit: c2d18ec0ea4ce9d6d8be5a1a9b266f57a40b5e24
[2/5] arm64: dts: ti: k3-am62a-phycore-som: Add boot phase tags
      commit: a5965ee0107a37ca4c73f05f06f55dad759572d2
[3/5] arm64: dts: ti: k3-am642-phyboard-electra: Add boot phase tags
      commit: a9c8485cd13cdffee5bdcda6b625f678900994c4
[4/5] arm64: dts: ti: k3-am642-phyboard-electra: Reorder properties per DTS coding style
      commit: 61a12b5a9923e4beec5595fed3b9c3d5c0c25c32
[5/5] arm64: dts: ti: k3-am62a-phycore-som: Reorder properties per DTS coding style
      commit: a89d3f47b09c793d0454350739ee8695ff30fb5c

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Fri Mar  7 02:37:53 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Fri, 7 Mar 2025 16:07:53 +0530
Subject: [PATCH v2] arm64: dts: ti: k3-j784s4-j742s2-main-common: Fix serdes_ln_ctrl reg-masks
In-Reply-To: <20250228053850.506028-1-s-vadapalli@ti.com>
References: <20250228053850.506028-1-s-vadapalli@ti.com>
Message-ID: <174133309359.1072814.1136748837607533827.b4-ty@ti.com>

Hi Siddharth Vadapalli,

On Fri, 28 Feb 2025 11:08:50 +0530, Siddharth Vadapalli wrote:
> Commit under Fixes added the 'idle-states' property for SERDES4 lane muxes
> without defining the corresponding register offsets and masks for it in the
> 'mux-reg-masks' property within the 'serdes_ln_ctrl' node.
> 
> Fix this.
> 
> 
> [...]

I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-j784s4-j742s2-main-common: Fix serdes_ln_ctrl reg-masks
      commit: 38e7f9092efbbf2a4a67e4410b55b797f8d1e184

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From vigneshr at ti.com  Fri Mar  7 02:39:03 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Fri, 7 Mar 2025 16:09:03 +0530
Subject: [PATCH v2] arm64: dts: ti: am64-phyboard-electra: Add DT overlay for X27 connector
In-Reply-To: <20250128100356.462934-1-d.schultz@phytec.de>
References: <20250128100356.462934-1-d.schultz@phytec.de>
Message-ID: <174133309360.1072814.5781136460553851194.b4-ty@ti.com>

Hi Daniel Schultz,

On Tue, 28 Jan 2025 02:03:56 -0800, Daniel Schultz wrote:
> Add a device tree overlay for SPI1 , UART3 and GPIO1 on
> X27 connector.
> 
> By default, not all interfaces on the X27 connector are accessible
> due to being disabled or set to alternative pin mux configurations.
> This overlay activates and configures these interfaces to support
> connections with external devices.
> 
> [...]

I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/1] arm64: dts: ti: am64-phyboard-electra: Add DT overlay for X27 connector
      commit: 638ab30ce4c63edae4934dcaa7a61f37b96efe6c

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Vignesh



From akihiko.odaki at daynix.com  Fri Mar  7 02:55:30 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Fri, 07 Mar 2025 19:55:30 +0900
Subject: [PATCH v2 3/3] KVM: arm64: PMU: Set raw values from user to
 PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
In-Reply-To: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
Message-ID: <20250307-pmc-v2-3-6c3375a5f1e4@daynix.com>

Commit a45f41d754e0 ("KVM: arm64: Add {get,set}_user for
PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}") changed KVM_SET_ONE_REG to update
the mentioned registers in a way matching with the behavior of guest
register writes. This is a breaking change of a UAPI though the new
semantics looks cleaner and VMMs are not prepared for this.

Firecracker, QEMU, and crosvm perform migration by listing registers
with KVM_GET_REG_LIST, getting their values with KVM_GET_ONE_REG and
setting them with KVM_SET_ONE_REG. This algorithm assumes
KVM_SET_ONE_REG restores the values retrieved with KVM_GET_ONE_REG
without any alteration. However, bit operations added by the earlier
commit do not preserve the values retried with KVM_GET_ONE_REG and
potentially break migration.

Remove the bit operations that alter the values retrieved with
KVM_GET_ONE_REG.

Fixes: a45f41d754e0 ("KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/sys_regs.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 51054b7befc0b4bd822cecf717ee4a4740c4a685..2f44d4d4f54112787683dd75ea93fd60e92dd31f 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1142,26 +1142,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
-	bool set;
-
-	val &= kvm_pmu_valid_counter_mask(vcpu);
-
-	switch (r->reg) {
-	case PMOVSSET_EL0:
-		/* CRm[1] being set indicates a SET register, and CLR otherwise */
-		set = r->CRm & 2;
-		break;
-	default:
-		/* Op2[0] being set indicates a SET register, and CLR otherwise */
-		set = r->Op2 & 1;
-		break;
-	}
-
-	if (set)
-		__vcpu_sys_reg(vcpu, r->reg) |= val;
-	else
-		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
-
+	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
 	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 
 	return 0;

-- 
2.48.1



From mike.leach at linaro.org  Fri Mar  7 02:58:22 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 7 Mar 2025 10:58:22 +0000
Subject: [PATCH v3 4/7] coresight-tgu: Add TGU decode support
In-Reply-To: <20250227092640.2666894-5-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com> <20250227092640.2666894-5-quic_songchai@quicinc.com>
Message-ID: <CAJ9a7Vj3eaZB_i8B8ke4cu=Mz7PjB5Z8Gt=MWB13YXZ9MDZyFA@mail.gmail.com>

Hi,

On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>
> From: Songwei Chai <quic_songchai at quicinc.com>
>
> Decoding is when all the potential pieces for creating a trigger
> are brought together for a given step. Example - there may be a
> counter keeping track of some occurrences and a priority-group that
> is being used to detect a pattern on the sense inputs. These 2
> inputs to condition_decode must be programmed, for a given step,
> to establish the condition for the trigger, or movement to another
> step.
>
> Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> Signed-off-by: songchai <quic_songchai at quicinc.com>
> ---
>  .../testing/sysfs-bus-coresight-devices-tgu   |   7 ++
>  drivers/hwtracing/coresight/coresight-tgu.c   | 113 ++++++++++++++++--
>  drivers/hwtracing/coresight/coresight-tgu.h   |  29 ++++-
>  3 files changed, 136 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> index af7332153833..dd6cc1184d52 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> @@ -14,3 +14,10 @@ KernelVersion   6.15
>  Contact:        Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
>  Description:
>                  (RW) Set/Get the sensed siganal with specific step and priority for TGU.
> +
> +What:           /sys/bus/coresight/devices/<tgu-name>/step[0:7]_condition_decode/reg[0:3]
> +Date:           February 2025
> +KernelVersion   6.15
> +Contact:        Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
> +Description:
> +                (RW) Set/Get the decode mode with specific step for TGU.
> diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c
> index f28761619ebe..5eebf5eecbbb 100644
> --- a/drivers/hwtracing/coresight/coresight-tgu.c
> +++ b/drivers/hwtracing/coresight/coresight-tgu.c
> @@ -22,9 +22,21 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, int step_index,
>  {
>         int ret = -EINVAL;
>
> -       ret = operation_index * (drvdata->max_step) *
> -                     (drvdata->max_reg) + step_index * (drvdata->max_reg)
> -                               + reg_index;
> +       switch (operation_index) {
> +       case TGU_PRIORITY0:
> +       case TGU_PRIORITY1:
> +       case TGU_PRIORITY2:
> +       case TGU_PRIORITY3:
> +               ret = operation_index * (drvdata->max_step) *
> +                       (drvdata->max_reg) + step_index * (drvdata->max_reg)
> +                       + reg_index;
> +               break;
> +       case TGU_CONDITION_DECODE:
> +               ret = step_index * (drvdata->max_condition_decode) + reg_index;
> +               break;
> +       default:
> +               break;
> +       }
>
>         return ret;
>  }
> @@ -36,10 +48,23 @@ static ssize_t tgu_dataset_show(struct device *dev,
>         struct tgu_attribute *tgu_attr =
>                 container_of(attr, struct tgu_attribute, attr);
>
> -       return sysfs_emit(buf, "0x%x\n",
> -                         drvdata->value_table->priority[calculate_array_location(
> +       switch (tgu_attr->operation_index) {
> +       case TGU_PRIORITY0:
> +       case TGU_PRIORITY1:
> +       case TGU_PRIORITY2:
> +       case TGU_PRIORITY3:
> +               return sysfs_emit(buf, "0x%x\n",
> +                                 drvdata->value_table->priority[calculate_array_location(

calculate_array_location() can return -EINVAL - you could be
referencing array value drvdata->value_table->priority[-EINVAL] here.
Test the return before referencing the array.

Same for all following occurrences.


>                                   drvdata, tgu_attr->step_index,
>                                   tgu_attr->operation_index, tgu_attr->reg_num)]);
> +       case TGU_CONDITION_DECODE:
> +               return sysfs_emit(buf, "0x%x\n",
> +                                 drvdata->value_table->condition_decode[calculate_array_location(
> +                                 drvdata, tgu_attr->step_index, tgu_attr->operation_index,
> +                                 tgu_attr->reg_num)]);
> +

missing default - did this code compile without warnings?

> +       }
> +       return -EINVAL;
>
>  }
>
> @@ -58,11 +83,25 @@ static ssize_t tgu_dataset_store(struct device *dev,
>                 return ret;
>
>         guard(spinlock)(&tgu_drvdata->spinlock);
> -       tgu_drvdata->value_table->priority[calculate_array_location(
> -               tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
> -               tgu_attr->reg_num)] = val;
> -       ret = size;
> -
> +       switch (tgu_attr->operation_index) {
> +       case TGU_PRIORITY0:
> +       case TGU_PRIORITY1:
> +       case TGU_PRIORITY2:
> +       case TGU_PRIORITY3:
> +               tgu_drvdata->value_table->priority[calculate_array_location(
> +                       tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
> +                       tgu_attr->reg_num)] = val;
> +               ret = size;
> +               break;
> +       case TGU_CONDITION_DECODE:
> +               tgu_drvdata->value_table->condition_decode[calculate_array_location(
> +                       tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
> +                       tgu_attr->reg_num)] = val;
> +               ret = size;
> +               break;
> +       default:
> +               break;
> +       }
>         return ret;
>  }
>
> @@ -79,8 +118,23 @@ static umode_t tgu_node_visible(struct kobject *kobject, struct attribute *attr,
>                 container_of(dev_attr, struct tgu_attribute, attr);
>
>         if (tgu_attr->step_index < drvdata->max_step) {
> -               ret = (tgu_attr->reg_num < drvdata->max_reg) ?
> -                                           attr->mode : 0;
> +               switch (tgu_attr->operation_index) {
> +               case TGU_PRIORITY0:
> +               case TGU_PRIORITY1:
> +               case TGU_PRIORITY2:
> +               case TGU_PRIORITY3:
> +                       ret = (tgu_attr->reg_num < drvdata->max_reg) ?
> +                                     attr->mode : 0;
> +                       break;
> +               case TGU_CONDITION_DECODE:
> +                       ret = (tgu_attr->reg_num <
> +                                       drvdata->max_condition_decode) ?
> +                                               attr->mode : 0;
> +                       break;
> +               default:
> +                       break;
> +               }
> +
>                 return ret;
>         }
>         return SYSFS_GROUP_INVISIBLE;
> @@ -103,6 +157,17 @@ static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
>                 }
>         }
>
> +       for (i = 0; i < drvdata->max_step; i++) {
> +               for (j = 0; j < drvdata->max_condition_decode; j++) {
> +                       tgu_writel(drvdata,
> +                                  drvdata->value_table
> +                                          ->condition_decode[calculate_array_location(
> +                                                  drvdata, i,
> +                                                  TGU_CONDITION_DECODE, j)],
> +                                  CONDITION_DECODE_STEP(i, j));
> +               }
> +       }
> +
>         /* Enable TGU to program the triggers */
>         tgu_writel(drvdata, 1, TGU_CONTROL);
>         CS_LOCK(drvdata->base);
> @@ -245,6 +310,14 @@ static const struct attribute_group *tgu_attr_groups[] = {
>         PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1),
>         PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2),
>         PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(0),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(1),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(2),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(3),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(4),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6),
> +       CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7),
>         NULL,
>  };
>
> @@ -289,6 +362,13 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
>         if (ret)
>                 return -EINVAL;
>
> +       ret = of_property_read_u32(adev->dev.of_node, "tgu-conditions",
> +                                  &drvdata->max_condition);
> +       if (ret)
> +               return -EINVAL;
> +
> +       drvdata->max_condition_decode = drvdata->max_condition;
> +
>         drvdata->value_table =
>                 devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL);
>         if (!drvdata->value_table)
> @@ -303,6 +383,15 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
>         if (!drvdata->value_table->priority)
>                 return -ENOMEM;
>
> +       drvdata->value_table->condition_decode = devm_kzalloc(
> +               dev,
> +               drvdata->max_condition_decode * drvdata->max_step *
> +                       sizeof(*(drvdata->value_table->condition_decode)),
> +               GFP_KERNEL);
> +
> +       if (!drvdata->value_table->condition_decode)
> +               return -ENOMEM;
> +
>         drvdata->enable = false;
>         desc.type = CORESIGHT_DEV_TYPE_HELPER;
>         desc.pdata = adev->dev.platform_data;
> diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h
> index 6e5d465117df..c2a9ce38b44f 100644
> --- a/drivers/hwtracing/coresight/coresight-tgu.h
> +++ b/drivers/hwtracing/coresight/coresight-tgu.h
> @@ -46,6 +46,9 @@
>  #define PRIORITY_REG_STEP(step, priority, reg)\
>         (0x0074 + 0x60 * priority + 0x4 * reg + 0x1D8 * step)
>
> +#define CONDITION_DECODE_STEP(step, decode) \
> +       (0x0050 + 0x4 * decode + 0x1D8 * step)
> +

use #define constants with explanations of what they are rather than
arbitrary magic numbers.

>  #define tgu_dataset_ro(name, step_index, type, reg_num)     \
>         (&((struct tgu_attribute[]){ {                      \
>                 __ATTR(name, 0444, tgu_dataset_show, NULL), \
> @@ -66,6 +69,9 @@
>         tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \
>                        reg_num)
>
> +#define STEP_DECODE(step_index, reg_num) \
> +       tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num)
> +
>  #define STEP_PRIORITY_LIST(step_index, priority)  \
>         {STEP_PRIORITY(step_index, 0, priority),  \
>          STEP_PRIORITY(step_index, 1, priority),  \
> @@ -88,6 +94,14 @@
>          NULL                   \
>         }
>
> +#define STEP_DECODE_LIST(n) \
> +       {STEP_DECODE(n, 0), \
> +        STEP_DECODE(n, 1), \
> +        STEP_DECODE(n, 2), \
> +        STEP_DECODE(n, 3), \
> +        NULL           \
> +       }
> +
>  #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\
>         (&(const struct attribute_group){\
>                 .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\
> @@ -95,11 +109,19 @@
>                 .name = "step" #step "_priority" #priority \
>         })
>
> +#define CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(step)\
> +       (&(const struct attribute_group){\
> +               .attrs = (struct attribute*[])STEP_DECODE_LIST(step),\
> +               .is_visible = tgu_node_visible,\
> +               .name = "step" #step "_condition_decode" \
> +       })
> +
>  enum operation_index {
>         TGU_PRIORITY0,
>         TGU_PRIORITY1,
>         TGU_PRIORITY2,
> -       TGU_PRIORITY3
> +       TGU_PRIORITY3,
> +       TGU_CONDITION_DECODE
>
>  };
>
> @@ -115,6 +137,7 @@ struct tgu_attribute {
>
>  struct value_table {
>         unsigned int *priority;
> +       unsigned int *condition_decode;
>  };
>
>  /**
> @@ -127,6 +150,8 @@ struct value_table {
>   * @value_table: Store given value based on relevant parameters.
>   * @max_reg: Maximum number of registers
>   * @max_step: Maximum step size
> + * @max_condition: Maximum number of condition
> + * @max_condition_decode: Maximum number of condition_decode
>   *
>   * This structure defines the data associated with a TGU device, including its base
>   * address, device pointers, clock, spinlock for synchronization, trigger data pointers,
> @@ -141,6 +166,8 @@ struct tgu_drvdata {
>         struct value_table *value_table;
>         int max_reg;
>         int max_step;
> +       int max_condition;
> +       int max_condition_decode;
>  };
>
>  #endif
>

Regards

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From ardb at kernel.org  Fri Mar  7 03:16:34 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Fri, 7 Mar 2025 12:16:34 +0100
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <c3dddb6f-dce1-45a6-b5f1-1fd247c510ab@arm.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
 <17931f83-7142-4ca6-8bfe-466ec53b6e2c@arm.com> <c3dddb6f-dce1-45a6-b5f1-1fd247c510ab@arm.com>
Message-ID: <CAMj1kXE0mCPSKLyNUkLZXLntX-=aCGKdn5b3Zgme3PbyYFgFdg@mail.gmail.com>

On Fri, 7 Mar 2025 at 10:21, Anshuman Khandual
<anshuman.khandual at arm.com> wrote:
>
>
>
> On 3/7/25 14:37, Ryan Roberts wrote:
> > On 07/03/2025 05:08, Anshuman Khandual wrote:
> >> Address bytes shifted with a single 64 bit page table entry (any page table
> >> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
> >> is not very readable or easy to reason about. Besides it is going to change
> >> with D128, where each 128 bit page table entry will shift address bytes by
> >> 4 (aka 2^4 = 16) instead.
> >>
> >> Let's just formalise this address bytes shift value into a new macro called
> >> PTE_SHIFT establishing a logical abstraction, thus improving readability as
> >> well. This does not cause any functional change.
> >>
> >> Cc: Catalin Marinas <catalin.marinas at arm.com>
> >> Cc: Will Deacon <will at kernel.org>
> >> Cc: Mark Rutland <mark.rutland at arm.com>
> >> Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
> >> Cc: Alexander Potapenko <glider at google.com>
> >> Cc: Andrey Konovalov <andreyknvl at gmail.com>
> >> Cc: Dmitry Vyukov <dvyukov at google.com>
> >> Cc: Ard Biesheuvel <ardb at kernel.org>
> >> Cc: Ryan Roberts <ryan.roberts at arm.com>
> >> Cc: linux-arm-kernel at lists.infradead.org
> >> Cc: linux-kernel at vger.kernel.org
> >> Cc: kasan-dev at googlegroups.com
> >> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> >
> >
> > +1 for PTDESC_ORDER
>
> Alright.
>

Agreed.

> >
> > Implementation looks good to me so:
> >
> > Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
>

With PTDESC_ORDER used throughout,

Acked-by: Ard Biesheuvel <ardb at kernel.org>


From luca.ceresoli at bootlin.com  Fri Mar  7 03:19:07 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 07 Mar 2025 12:19:07 +0100
Subject: [PATCH 1/2] thermal: bcm2835: use %pC instead of %pCn
In-Reply-To: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
Message-ID: <20250307-vsprintf-pcn-v1-1-df0b2ccf610f@bootlin.com>

The %pC and %pCn printk format specifiers produce the exact same string. In
preparation for removing %pCn, use %pC.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
 drivers/thermal/broadcom/bcm2835_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index 7fbba2233c4c12e14090832a62784e1500c0ab79..685a5aee5e0dfb113638313a9086721beae09db3 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -192,7 +192,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
 	rate = clk_get_rate(data->clk);
 	if ((rate < 1920000) || (rate > 5000000))
 		dev_warn(dev,
-			 "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
+			 "Clock %pC running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
 			 data->clk, rate);
 
 	/* register of thermal sensor and get info from DT */

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar  7 03:19:06 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 07 Mar 2025 12:19:06 +0100
Subject: [PATCH 0/2] vsprintf: remove redundant %pCn format specifier
Message-ID: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>

There are two printk format specifiers for clocks: %pC and %pCn, and they
print exactly the same string. The reason for having two is not totally
clear (see discussion in patch 2), but there seem to be no advantage in
having two instead of one.

Definitely having two without properly documenting they do the same creates
misunderstandings [0].

Since %pCn is used in a single place, replace it with %pC and remove %pCn
to simplify such format specifiers implementation and avoid
misunderstandings.

[0] https://lore.kernel.org/dri-devel/71c44221-b18b-4928-8faf-00893ec4a109 at nxp.com/

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
Luca Ceresoli (2):
      thermal: bcm2835: use %pC instead of %pCn
      vsprintf: remove redundant and unused %pCn format specifier

 Documentation/core-api/printk-formats.rst  |  3 +--
 drivers/thermal/broadcom/bcm2835_thermal.c |  2 +-
 lib/vsprintf.c                             | 10 ++--------
 3 files changed, 4 insertions(+), 11 deletions(-)
---
base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
change-id: 20250307-vsprintf-pcn-8a43e3b0d43e

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From luca.ceresoli at bootlin.com  Fri Mar  7 03:22:17 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 7 Mar 2025 12:22:17 +0100
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <71c44221-b18b-4928-8faf-00893ec4a109@nxp.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
	<20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
	<71c44221-b18b-4928-8faf-00893ec4a109@nxp.com>
Message-ID: <20250307122217.158b24d6@booty>

Hello Liu,

On Fri, 7 Mar 2025 14:42:12 +0800
Liu Ying <victor.liu at nxp.com> wrote:

> On 03/07/2025, Luca Ceresoli wrote:
> > 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
> > ret;'. So return 0 for clarity.
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > ---
> >  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
> > --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > @@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
> >  
> >  	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
> >  
> > -	return ret;
> > +	return 0;  
> 
> I guess this is not the only place across the kernel tree where this cleanup
> could be done.  So, maybe use some tools to cleanup them all?

I had stumbled upon this as I was doing some changes to this function,
and needed to understand the code flow. Definitely 'ret 0' would have
made it  immediately clear that all the code between the last 'if (ret)
return ret;' and the final 'return ret' is not allowed to fail.

I think this change would (slightly, but still) improve future readers'
life.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From luca.ceresoli at bootlin.com  Fri Mar  7 03:19:08 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 07 Mar 2025 12:19:08 +0100
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
Message-ID: <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>

%pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
add %pC{,n,r} format specifiers for clocks") introducing them does not
clarify any intended difference. It can be assumed %pC is a default for
%pCn as some other specifiers do, but not all are consistent with this
policy. Moreover there is now no other suffix other than 'n', which makes a
default not really useful.

All users in the kernel were using %pC except for one which has been
converted. So now remove %pCn and all the unnecessary extra code and
documentation.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
 Documentation/core-api/printk-formats.rst |  3 +--
 lib/vsprintf.c                            | 10 ++--------
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index ecccc0473da9c10f45f2464566f690472c61401e..f3009e6ec80a864c330c8812efcd82c12f4066b3 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -571,9 +571,8 @@ struct clk
 ::
 
 	%pC	pll1
-	%pCn	pll1
 
-For printing struct clk structures. %pC and %pCn print the name of the clock
+For printing struct clk structures. %pC prints the name of the clock
 (Common Clock Framework) or a unique 32-bit ID (legacy clock framework).
 
 Passed by reference.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 56fe96319292674c9f79559cf78dd0d99d1a1f06..143d55cb1c12acac21a6c6bafd255437e878f280 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1969,15 +1969,11 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
 	if (check_pointer(&buf, end, clk, spec))
 		return buf;
 
-	switch (fmt[1]) {
-	case 'n':
-	default:
 #ifdef CONFIG_COMMON_CLK
-		return string(buf, end, __clk_get_name(clk), spec);
+	return string(buf, end, __clk_get_name(clk), spec);
 #else
-		return ptr_to_id(buf, end, clk, spec);
+	return ptr_to_id(buf, end, clk, spec);
 #endif
-	}
 }
 
 static
@@ -2382,8 +2378,6 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
  *      T    time64_t
  * - 'C' For a clock, it prints the name (Common Clock Framework) or address
  *       (legacy clock framework) of the clock
- * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
- *        (legacy clock framework) of the clock
  * - 'G' For flags to be printed as a collection of symbolic strings that would
  *       construct the specific value. Supported flags given by option:
  *       p page flags (see struct page) given as pointer to unsigned long

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar  7 03:22:12 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 7 Mar 2025 12:22:12 +0100
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <f8df2b5e-b005-4ada-8108-159b2b94a72e@nxp.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
	<20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
	<f8df2b5e-b005-4ada-8108-159b2b94a72e@nxp.com>
Message-ID: <20250307122212.18252ca6@booty>

Hello Liu,

thanks for your reviews.

On Fri, 7 Mar 2025 14:33:37 +0800
Liu Ying <victor.liu at nxp.com> wrote:

> On 03/07/2025, Luca Ceresoli wrote:
> > This warning notifies a clock was set to an inaccurate value. Modify the
> > string to also show the clock name.
> > 
> > While doing that also rewrap the entire function call.
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > ---
> >  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
> > index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
> > --- a/drivers/gpu/drm/bridge/fsl-ldb.c
> > +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
> > @@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
> >  
> >  	configured_link_freq = clk_get_rate(fsl_ldb->clk);
> >  	if (configured_link_freq != requested_link_freq)
> > -		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> > -			 configured_link_freq,
> > -			 requested_link_freq);
> > +		dev_warn(fsl_ldb->dev,
> > +			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
> > +			 fsl_ldb->clk, configured_link_freq, requested_link_freq);  
> 
> Though this slightly changes the warning message userspace sees, I guess it is
> acceptable.
> 
> Does it make sense to s/%pC/%pCn/ so that the clock name is printed in lower
> case instead of upper case, since it seems that all i.MX specific clock names
> are in lower case?

%pC and %pCn print the same string, as I just discovered at
https://elixir.bootlin.com/linux/v6.14-rc5/source/lib/vsprintf.c#L1972

I've pondering for a moment about whether we should document %pC and
%pCn produce the same output or rather %pCn. I decided to try the
latter and just sent a patch to do it [0].

FYI in my case the printed value is (with both %pC and %pCn)
"32ec0000.blk-ctrl:bridge at 5c".

[0] https://lore.kernel.org/20250307-vsprintf-pcn-v1-0-df0b2ccf610f at bootlin.com

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From faizal.abdul.rahim at linux.intel.com  Fri Mar  7 03:26:05 2025
From: faizal.abdul.rahim at linux.intel.com (Abdul Rahim, Faizal)
Date: Fri, 7 Mar 2025 19:26:05 +0800
Subject: [PATCH iwl-next v8 08/11] igc: add support to set
 tx-min-frag-size
In-Reply-To: <20250306004301.evw34gqoyll36mso@skbuf>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-9-faizal.abdul.rahim@linux.intel.com>
 <20250306004301.evw34gqoyll36mso@skbuf>
Message-ID: <152e48f6-e68d-4de4-8170-3f35df1ddd1d@linux.intel.com>



On 6/3/2025 8:43 am, Vladimir Oltean wrote:
>> diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
>> index ad9b40034003..4c395cd949ab 100644
>> --- a/net/ethtool/mm.c
>> +++ b/net/ethtool/mm.c
>> @@ -153,7 +153,7 @@ const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1] = {
>>   	[ETHTOOL_A_MM_VERIFY_TIME]	= NLA_POLICY_RANGE(NLA_U32, 1, 128),
>>   	[ETHTOOL_A_MM_TX_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
>>   	[ETHTOOL_A_MM_PMAC_ENABLED]	= NLA_POLICY_MAX(NLA_U8, 1),
>> -	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 252),
>> +	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]	= NLA_POLICY_RANGE(NLA_U32, 60, 256),
> 
> Please make this a separate patch with a reasonably convincing
> justification for any reader, and also state why it is a change that
> will not introduce regressions to the other drivers. It shows that
> you've done the due dilligence of checking that they all use
> ethtool_mm_frag_size_min_to_add(), which errors out on non-standard
> values.
> 
> To be clear, extending the policy from 252 to 256 is just to suppress
> the netlink warning which states that the driver rounds up the minimum
> fragment size, correct? Because even if you pass 252 (the current
> netlink maximum), the driver will still use 256.
> 
I originally changed 252 to 256 because our internal validation failed when 
setting 256 via ethtool. The test case was based on our old kernel OOT 
patches code, but this run was done on the upstreamed FPE framework plus 
this series. After thinking about it, it doesn?t seem right to change this 
just to accommodate the i226 quirk in a common layer when the IEEE standard 
and other devices use 252.

So, we?ll update our validation to use 252 instead. The driver already 
rounds up to 256 anyway. I?ll drop this change in the next revision.

Also, noted your point about being cautious with changes that impact other 
drivers.

Thanks.


From vdonnefort at google.com  Fri Mar  7 03:34:11 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Fri,  7 Mar 2025 11:34:11 +0000
Subject: [PATCH v3 3/3] KVM: arm64: Count pKVM stage-2 usage in secondary
 pagetable stats
In-Reply-To: <20250307113411.469018-1-vdonnefort@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
Message-ID: <20250307113411.469018-4-vdonnefort@google.com>

Count the pages used by pKVM for the guest stage-2 in memory stats under
secondary pagetable, similarly to what the VHE mode does.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ace3969e8106..51754a354b7a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,8 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+
+#define	HYP_MEMCACHE_ACCOUNT_STAGE2	BIT(1)
 	unsigned long flags;
 };
 
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index c01ad4430729..73b44f1200c7 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1088,12 +1088,24 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 
 static void hyp_mc_free_fn(void *addr, void *mc)
 {
+	struct kvm_hyp_memcache *memcache = mc;
+
+	if (memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, -1);
+
 	free_page((unsigned long)addr);
 }
 
 static void *hyp_mc_alloc_fn(void *mc)
 {
-	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+	struct kvm_hyp_memcache *memcache = mc;
+	void *addr;
+
+	addr = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+	if (addr && memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, 1);
+
+	return addr;
 }
 
 void free_hyp_memcache(struct kvm_hyp_memcache *mc)
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 19921ca407c6..7e6e3b0518f8 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -165,12 +165,16 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 	handle = ret;
 
 	host_kvm->arch.pkvm.handle = handle;
+	host_kvm->arch.pkvm.stage2_teardown_mc.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+	kvm_account_pgtable_pages(pgd, PAGE_ALIGN(pgd_sz) >> PAGE_SHIFT);
 
 	/* Donate memory for the vcpus at hyp and initialize it. */
 	hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
 	kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
 		void *hyp_vcpu;
 
+		host_vcpu->arch.pkvm_memcache.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+
 		/* Indexing of the vcpus to be sequential starting at 0. */
 		if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
 			ret = -EINVAL;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Fri Mar  7 03:34:08 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Fri,  7 Mar 2025 11:34:08 +0000
Subject: [PATCH v3 0/3] Count pKVM stage-2 usage in secondary pagetable stat
Message-ID: <20250307113411.469018-1-vdonnefort@google.com>

This series allows to count stage-2 related memory when using pKVM. The
value can be found in the /proc/meminfo field SecPageTables.

Changes since v2: https://lore.kernel.org/all/20250304134347.369854-1-vdonnefort at google.com/
  - Pass a pointer to kvm_hyp_memcache instead of just the flags
    (Oliver)

Changes since v1: https://lore.kernel.org/all/20250228121355.1377891-1-vdonnefort at google.com/
  - Flags to kvm_hyp_memcache
  - Separate stage-2 memcache
  - Account for PGD

Vincent Donnefort (3):
  KVM: arm64: Add flags to kvm_hyp_memcache
  KVM: arm64: Distinct pKVM teardown memcache for stage-2
  KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats

 arch/arm64/include/asm/kvm_host.h |  4 ++++
 arch/arm64/kvm/hyp/nvhe/pkvm.c    |  7 ++++---
 arch/arm64/kvm/mmu.c              | 22 +++++++++++++++++-----
 arch/arm64/kvm/pkvm.c             |  5 +++++
 4 files changed, 30 insertions(+), 8 deletions(-)


base-commit: d082ecbc71e9e0bf49883ee4afd435a77a5101b6
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Fri Mar  7 03:34:09 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Fri,  7 Mar 2025 11:34:09 +0000
Subject: [PATCH v3 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <20250307113411.469018-1-vdonnefort@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
Message-ID: <20250307113411.469018-2-vdonnefort@google.com>

Add flags to kvm_hyp_memcache and propagate the latter to the allocation
and free callbacks. This will later allow to account for memory, based
on the memcache configuration.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3a7ec98ef123..12691ae23d4c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,7 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+	unsigned long flags;
 };
 
 static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..c01ad4430729 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1086,12 +1086,12 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 	}
 }
 
-static void hyp_mc_free_fn(void *addr, void *unused)
+static void hyp_mc_free_fn(void *addr, void *mc)
 {
 	free_page((unsigned long)addr);
 }
 
-static void *hyp_mc_alloc_fn(void *unused)
+static void *hyp_mc_alloc_fn(void *mc)
 {
 	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
 }
@@ -1102,7 +1102,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
 		return;
 
 	kfree(mc->mapping);
-	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
+	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, (void *)mc);
 }
 
 int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
@@ -1117,7 +1117,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
 	}
 
 	return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
-				    kvm_host_pa, NULL);
+				    kvm_host_pa, (void *)mc);
 }
 
 /**
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Fri Mar  7 03:34:10 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Fri,  7 Mar 2025 11:34:10 +0000
Subject: [PATCH v3 2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
In-Reply-To: <20250307113411.469018-1-vdonnefort@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
Message-ID: <20250307113411.469018-3-vdonnefort@google.com>

In order to account for memory dedicated to the stage-2 page-tables, use
a separated memcache when tearing down the VM.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 12691ae23d4c..ace3969e8106 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
 struct kvm_protected_vm {
 	pkvm_handle_t handle;
 	struct kvm_hyp_memcache teardown_mc;
+	struct kvm_hyp_memcache stage2_teardown_mc;
 	bool enabled;
 };
 
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 3927fe52a3dd..15f8d5315959 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
 
 int __pkvm_teardown_vm(pkvm_handle_t handle)
 {
-	struct kvm_hyp_memcache *mc;
+	struct kvm_hyp_memcache *mc, *stage2_mc;
 	struct pkvm_hyp_vm *hyp_vm;
 	struct kvm *host_kvm;
 	unsigned int idx;
@@ -706,7 +706,8 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 
 	/* Reclaim guest pages (including page-table pages) */
 	mc = &host_kvm->arch.pkvm.teardown_mc;
-	reclaim_guest_pages(hyp_vm, mc);
+	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
+	reclaim_guest_pages(hyp_vm, stage2_mc);
 	unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->nr_vcpus);
 
 	/* Push the metadata pages to the teardown memcache */
@@ -717,7 +718,7 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 		while (vcpu_mc->nr_pages) {
 			void *addr = pop_hyp_memcache(vcpu_mc, hyp_phys_to_virt);
 
-			push_hyp_memcache(mc, addr, hyp_virt_to_phys);
+			push_hyp_memcache(stage2_mc, addr, hyp_virt_to_phys);
 			unmap_donated_memory_noclear(addr, PAGE_SIZE);
 		}
 
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..19921ca407c6 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -111,6 +111,7 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 
 	host_kvm->arch.pkvm.handle = 0;
 	free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
+	free_hyp_memcache(&host_kvm->arch.pkvm.stage2_teardown_mc);
 }
 
 /*
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Fri Mar  7 03:35:13 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Fri, 7 Mar 2025 11:35:13 +0000
Subject: [PATCH v2 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <Z8qeIPfTOJU6w_8l@linux.dev>
References: <20250304134347.369854-1-vdonnefort@google.com>
 <20250304134347.369854-2-vdonnefort@google.com>
 <Z8qeIPfTOJU6w_8l@linux.dev>
Message-ID: <Z8rZ8bBnSllaZCEs@google.com>

On Thu, Mar 06, 2025 at 11:20:00PM -0800, Oliver Upton wrote:
> Hi Vincent,
> 
> On Tue, Mar 04, 2025 at 01:43:44PM +0000, Vincent Donnefort wrote:
> > Add flags to kvm_hyp_memcache and propagate them up to the allocation
> > and free callbacks. This will later allow to account for memory, based
> > on the memcache configuration.
> 
> It seems slightly more obvious to me if we pass a pointer to the
> memcache instead, but that's just a minor nit.

That sounds good!

> 
> Unless you have a preference on this, I can change it when I apply the
> patch.

I have just sent a v3 to save you the trouble.

> 
> Thanks,
> Oliver


From faizal.abdul.rahim at linux.intel.com  Fri Mar  7 03:52:33 2025
From: faizal.abdul.rahim at linux.intel.com (Abdul Rahim, Faizal)
Date: Fri, 7 Mar 2025 19:52:33 +0800
Subject: [PATCH iwl-next v8 07/11] igc: add support for frame preemption
 verification
In-Reply-To: <20250306002825.rva7wjsymmms7kbd@skbuf>
References: <20250305130026.642219-1-faizal.abdul.rahim@linux.intel.com>
 <20250305130026.642219-8-faizal.abdul.rahim@linux.intel.com>
 <20250306002825.rva7wjsymmms7kbd@skbuf>
Message-ID: <43277258-7100-4230-82da-8a78ad341dde@linux.intel.com>



On 6/3/2025 8:28 am, Vladimir Oltean wrote:
> On Wed, Mar 05, 2025 at 08:00:22AM -0500, Faizal Rahim wrote:
>> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
>> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
>> Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
>> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
>> Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
>> Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
>> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
>> ---
>> +
>> +static inline bool igc_fpe_is_verify_or_response(union igc_adv_rx_desc *rx_desc,
>> +						 unsigned int size, void *pktbuf)
>> +{
>> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
>> +	static const u8 zero_payload[SMD_FRAME_SIZE] = {0};
>> +	int smd;
>> +
>> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
>> +
>> +	return (smd == IGC_RXD_STAT_SMD_TYPE_V || smd == IGC_RXD_STAT_SMD_TYPE_R) &&
>> +		size == SMD_FRAME_SIZE &&
>> +		!memcmp(pktbuf, zero_payload, SMD_FRAME_SIZE); /* Buffer is all zeros */
> 
> Using this definition...
> 
>> +}
>> +
>> +static inline void igc_fpe_lp_event_status(union igc_adv_rx_desc *rx_desc,
>> +					   struct ethtool_mmsv *mmsv)
>> +{
>> +	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
>> +	int smd;
>> +
>> +	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
>> +
>> +	if (smd == IGC_RXD_STAT_SMD_TYPE_V)
>> +		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
>> +	else if (smd == IGC_RXD_STAT_SMD_TYPE_R)
>> +		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
>> +}
>> @@ -2617,6 +2617,15 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
>>   			size -= IGC_TS_HDR_LEN;
>>   		}
>>   
>> +		if (igc_fpe_is_pmac_enabled(adapter) &&
>> +		    igc_fpe_is_verify_or_response(rx_desc, size, pktbuf)) {
> 
> ... invalid SMD-R and SMD-V frames will skip this code block altogether, and
> will be passed up the network stack, and visible at least in tcpdump, correct?
> Essentially, if the link partner would craft an ICMP request packet with
> an SMD-V or SMD-R, your station would respond to it, which is incorrect.
> 
> A bit strange, the behavior in this case seems a bit under-specified in
> the standard, and I don't see any counter that should be incremented.
> 
>> +			igc_fpe_lp_event_status(rx_desc, &adapter->fpe.mmsv);
>> +			/* Advance the ring next-to-clean */
>> +			igc_is_non_eop(rx_ring, rx_desc);
>> +			cleaned_count++;
>> +			continue;
>> +		}
> 
> To fix this, don't you want to merge the unnaturally split
> igc_fpe_is_verify_or_response() and igc_fpe_lp_event_status() into a
> single function, which returns true whenever the mPacket should be
> consumed by the driver, but decides whether to emit a mmsv event on its
> own? Merging the two would also avoid reading rx_desc->wb.upper.status_error
> twice.
> 
> Something like this:
> 
> static inline bool igc_fpe_handle_mpacket(struct igc_adapter *adapter,
> 					  union igc_adv_rx_desc *rx_desc,
> 					  unsigned int size, void *pktbuf)
> {
> 	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
> 	int smd;
> 
> 	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
> 	if (smd != IGC_RXD_STAT_SMD_TYPE_V && smd != IGC_RXD_STAT_SMD_TYPE_R)
> 		return false;
> 
> 	if (size == SMD_FRAME_SIZE && mem_is_zero(pktbuf, SMD_FRAME_SIZE)) {
> 		struct ethtool_mmsv *mmsv = &adapter->fpe.mmsv;
> 		enum ethtool_mmsv_event event;
> 
> 		if (smd == IGC_RXD_STAT_SMD_TYPE_V)
> 			event = ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET;
> 		else
> 			event = ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET;
> 
> 		ethtool_mmsv_event_handle(mmsv, event);
> 	}
> 
> 	return true;
> }
> 
> 		if (igc_fpe_is_pmac_enabled(adapter) &&
> 		    igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf)) {
> 			/* Advance the ring next-to-clean */
> 			igc_is_non_eop(rx_ring, rx_desc);
> 			cleaned_count++;
> 			continue;
> 		}
> 
> [ also remark the use of mem_is_zero() instead of memcmp() with a buffer
>    pre-filled with zeroes. It should be more efficient, for the simple
>    reason that it's accessing a single memory buffer and not two. Though
>    I'm surprised how widespread the memcmp() pattern is throughout the
>    kernel. ]

Thanks for the suggestion?it reads much better and flows smoothly. Got it 
on the driver needing to consume a non-zero packet buffer from SMD-V and SMD-R.


From amadeus at jmu.edu.cn  Fri Mar  7 04:00:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 20:00:02 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
Message-ID: <20250307120004.959980-1-amadeus@jmu.edu.cn>

Add pwm nodes for RK3528. Most rk3528 boards use pwm-regulator to
supply to CPU, add node to enable them. The PWM core on RK3528 is
the same as RK3328, but the driver doesn't support interrupts yet.

Unlike other SoCs, pinctrl-names need to be in "active" state,
I'm not sure about this, but otherwise the pwm-regulator will
not work properly.

---
vdd_arm: regulator-vdd-arm {
	compatible = "pwm-regulator";
	pwms = <&pwm1 0 5000 1>;
	pwm-supply = <&vcc5v0_sys>;
	regulator-name = "vdd_arm";
	regulator-min-microvolt = <746000>;
	regulator-max-microvolt = <1201000>;
	regulator-always-on;
	regulator-boot-on;
	regulator-settling-time-up-us = <250>;
};

&cpu0 {
	cpu-supply = <&vdd_arm>;
};

&pwm1 {
	status = "okay";
};
---

Chukun Pan (2):
  dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
  arm64: dts: rockchip: Add pwm nodes for RK3528

 .../devicetree/bindings/pwm/pwm-rockchip.yaml |  1 +
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 88 +++++++++++++++++++
 2 files changed, 89 insertions(+)

-- 
2.25.1



From amadeus at jmu.edu.cn  Fri Mar  7 04:00:03 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 20:00:03 +0800
Subject: [PATCH 1/2] dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
In-Reply-To: <20250307120004.959980-1-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
Message-ID: <20250307120004.959980-2-amadeus@jmu.edu.cn>

Document pwm compatible for rk3528 which is fallback compatible
of rk3328-pwm group.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
index e4e1976c542d..c8cdfb723336 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
@@ -30,6 +30,7 @@ properties:
           - enum:
               - rockchip,px30-pwm
               - rockchip,rk3308-pwm
+              - rockchip,rk3528-pwm
               - rockchip,rk3562-pwm
               - rockchip,rk3568-pwm
               - rockchip,rk3588-pwm
-- 
2.25.1



From amadeus at jmu.edu.cn  Fri Mar  7 04:00:04 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri,  7 Mar 2025 20:00:04 +0800
Subject: [PATCH 2/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250307120004.959980-1-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
Message-ID: <20250307120004.959980-3-amadeus@jmu.edu.cn>

Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
RK3328, but the driver does not support interrupts yet.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 88 ++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index b1713ed4d7e2..ab1ac3273611 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -264,6 +264,94 @@ uart7: serial at ffa28000 {
 			status = "disabled";
 		};
 
+		pwm0: pwm at ffa90000 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90000 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm0m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm1: pwm at ffa90010 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90010 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm1m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm2: pwm at ffa90020 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90020 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm2m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm3: pwm at ffa90030 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90030 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm3m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm4: pwm at ffa98000 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98000 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm4m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm5: pwm at ffa98010 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98010 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm5m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm6: pwm at ffa98020 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98020 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm6m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm7: pwm at ffa98030 {
+			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98030 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			pinctrl-0 = <&pwm7m0_pins>;
+			pinctrl-names = "active";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		pinctrl: pinctrl {
 			compatible = "rockchip,rk3528-pinctrl";
 			rockchip,grf = <&ioc_grf>;
-- 
2.25.1



From qun-wei.lin at mediatek.com  Fri Mar  7 04:01:03 2025
From: qun-wei.lin at mediatek.com (Qun-Wei Lin)
Date: Fri, 7 Mar 2025 20:01:03 +0800
Subject: [PATCH 1/2] mm: Split BLK_FEAT_SYNCHRONOUS and SWP_SYNCHRONOUS_IO into separate read and write flags
In-Reply-To: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
Message-ID: <20250307120141.1566673-2-qun-wei.lin@mediatek.com>

This patch splits the BLK_FEAT_SYNCHRONOUS feature flag into two
separate flags: BLK_FEAT_READ_SYNCHRONOUS and
BLK_FEAT_WRITE_SYNCHRONOUS. Similarly, the SWP_SYNCHRONOUS_IO flag is
split into SWP_READ_SYNCHRONOUS_IO and SWP_WRITE_SYNCHRONOUS_IO.

These changes are motivated by the need to better accommodate certain
swap devices that support synchronous read operations but asynchronous write
operations.

The existing BLK_FEAT_SYNCHRONOUS and SWP_SYNCHRONOUS_IO flags are not
sufficient for these devices, as they enforce synchronous behavior for
both read and write operations.

Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
---
 drivers/block/brd.c           |  3 ++-
 drivers/block/zram/zram_drv.c |  5 +++--
 drivers/nvdimm/btt.c          |  3 ++-
 drivers/nvdimm/pmem.c         |  5 +++--
 include/linux/blkdev.h        | 24 ++++++++++++++++--------
 include/linux/swap.h          | 31 ++++++++++++++++---------------
 mm/memory.c                   |  4 ++--
 mm/page_io.c                  |  6 +++---
 mm/swapfile.c                 |  7 +++++--
 9 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 292f127cae0a..66920b9d4701 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -370,7 +370,8 @@ static int brd_alloc(int i)
 		.max_hw_discard_sectors	= UINT_MAX,
 		.max_discard_segments	= 1,
 		.discard_granularity	= PAGE_SIZE,
-		.features		= BLK_FEAT_SYNCHRONOUS |
+		.features		= BLK_FEAT_READ_SYNCHRONOUS	|
+					  BLK_FEAT_WRITE_SYNCHRONOUS	|
 					  BLK_FEAT_NOWAIT,
 	};
 
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 3dee026988dc..2e1a70f2f4bd 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2535,8 +2535,9 @@ static int zram_add(void)
 #if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
 		.max_write_zeroes_sectors	= UINT_MAX,
 #endif
-		.features			= BLK_FEAT_STABLE_WRITES |
-						  BLK_FEAT_SYNCHRONOUS,
+		.features			= BLK_FEAT_STABLE_WRITES	|
+						  BLK_FEAT_READ_SYNCHRONOUS	|
+						  BLK_FEAT_WRITE_SYNCHRONOUS,
 	};
 	struct zram *zram;
 	int ret, device_id;
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 423dcd190906..1665d98f51af 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1501,7 +1501,8 @@ static int btt_blk_init(struct btt *btt)
 		.logical_block_size	= btt->sector_size,
 		.max_hw_sectors		= UINT_MAX,
 		.max_integrity_segments	= 1,
-		.features		= BLK_FEAT_SYNCHRONOUS,
+		.features		= BLK_FEAT_READ_SYNCHRONOUS |
+					  BLK_FEAT_WRITE_SYNCHRONOUS,
 	};
 	int rc;
 
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index d81faa9d89c9..81a57d7ca746 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -455,8 +455,9 @@ static int pmem_attach_disk(struct device *dev,
 		.logical_block_size	= pmem_sector_size(ndns),
 		.physical_block_size	= PAGE_SIZE,
 		.max_hw_sectors		= UINT_MAX,
-		.features		= BLK_FEAT_WRITE_CACHE |
-					  BLK_FEAT_SYNCHRONOUS,
+		.features		= BLK_FEAT_WRITE_CACHE		|
+					  BLK_FEAT_READ_SYNCHRONOUS	|
+					  BLK_FEAT_WRITE_SYNCHRONOUS,
 	};
 	int nid = dev_to_node(dev), fua;
 	struct resource *res = &nsio->res;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 08a727b40816..3070f2e9d862 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -305,20 +305,23 @@ typedef unsigned int __bitwise blk_features_t;
 /* don't modify data until writeback is done */
 #define BLK_FEAT_STABLE_WRITES		((__force blk_features_t)(1u << 5))
 
-/* always completes in submit context */
-#define BLK_FEAT_SYNCHRONOUS		((__force blk_features_t)(1u << 6))
+/* read operations always completes in submit context */
+#define BLK_FEAT_READ_SYNCHRONOUS	((__force blk_features_t)(1u << 6))
+
+/* write operations always completes in submit context */
+#define BLK_FEAT_WRITE_SYNCHRONOUS	((__force blk_features_t)(1u << 7))
 
 /* supports REQ_NOWAIT */
-#define BLK_FEAT_NOWAIT			((__force blk_features_t)(1u << 7))
+#define BLK_FEAT_NOWAIT			((__force blk_features_t)(1u << 8))
 
 /* supports DAX */
-#define BLK_FEAT_DAX			((__force blk_features_t)(1u << 8))
+#define BLK_FEAT_DAX			((__force blk_features_t)(1u << 9))
 
 /* supports I/O polling */
-#define BLK_FEAT_POLL			((__force blk_features_t)(1u << 9))
+#define BLK_FEAT_POLL			((__force blk_features_t)(1u << 10))
 
 /* is a zoned device */
-#define BLK_FEAT_ZONED			((__force blk_features_t)(1u << 10))
+#define BLK_FEAT_ZONED			((__force blk_features_t)(1u << 11))
 
 /* supports PCI(e) p2p requests */
 #define BLK_FEAT_PCI_P2PDMA		((__force blk_features_t)(1u << 12))
@@ -1321,9 +1324,14 @@ static inline bool bdev_nonrot(struct block_device *bdev)
 	return blk_queue_nonrot(bdev_get_queue(bdev));
 }
 
-static inline bool bdev_synchronous(struct block_device *bdev)
+static inline bool bdev_read_synchronous(struct block_device *bdev)
+{
+	return bdev->bd_disk->queue->limits.features & BLK_FEAT_READ_SYNCHRONOUS;
+}
+
+static inline bool bdev_write_synchronous(struct block_device *bdev)
 {
-	return bdev->bd_disk->queue->limits.features & BLK_FEAT_SYNCHRONOUS;
+	return bdev->bd_disk->queue->limits.features & BLK_FEAT_WRITE_SYNCHRONOUS;
 }
 
 static inline bool bdev_stable_writes(struct block_device *bdev)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index f3e0ac20c2e8..2068b6973648 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -205,21 +205,22 @@ struct swap_extent {
 	  offsetof(union swap_header, info.badpages)) / sizeof(int))
 
 enum {
-	SWP_USED	= (1 << 0),	/* is slot in swap_info[] used? */
-	SWP_WRITEOK	= (1 << 1),	/* ok to write to this swap?	*/
-	SWP_DISCARDABLE = (1 << 2),	/* blkdev support discard */
-	SWP_DISCARDING	= (1 << 3),	/* now discarding a free cluster */
-	SWP_SOLIDSTATE	= (1 << 4),	/* blkdev seeks are cheap */
-	SWP_CONTINUED	= (1 << 5),	/* swap_map has count continuation */
-	SWP_BLKDEV	= (1 << 6),	/* its a block device */
-	SWP_ACTIVATED	= (1 << 7),	/* set after swap_activate success */
-	SWP_FS_OPS	= (1 << 8),	/* swapfile operations go through fs */
-	SWP_AREA_DISCARD = (1 << 9),	/* single-time swap area discards */
-	SWP_PAGE_DISCARD = (1 << 10),	/* freed swap page-cluster discards */
-	SWP_STABLE_WRITES = (1 << 11),	/* no overwrite PG_writeback pages */
-	SWP_SYNCHRONOUS_IO = (1 << 12),	/* synchronous IO is efficient */
-					/* add others here before... */
-	SWP_SCANNING	= (1 << 14),	/* refcount in scan_swap_map */
+	SWP_USED	= (1 << 0),		/* is slot in swap_info[] used? */
+	SWP_WRITEOK	= (1 << 1),		/* ok to write to this swap?	*/
+	SWP_DISCARDABLE = (1 << 2),		/* blkdev support discard */
+	SWP_DISCARDING	= (1 << 3),		/* now discarding a free cluster */
+	SWP_SOLIDSTATE	= (1 << 4),		/* blkdev seeks are cheap */
+	SWP_CONTINUED	= (1 << 5),		/* swap_map has count continuation */
+	SWP_BLKDEV	= (1 << 6),		/* its a block device */
+	SWP_ACTIVATED	= (1 << 7),		/* set after swap_activate success */
+	SWP_FS_OPS	= (1 << 8),		/* swapfile operations go through fs */
+	SWP_AREA_DISCARD = (1 << 9),		/* single-time swap area discards */
+	SWP_PAGE_DISCARD = (1 << 10),		/* freed swap page-cluster discards */
+	SWP_STABLE_WRITES = (1 << 11),		/* no overwrite PG_writeback pages */
+	SWP_READ_SYNCHRONOUS_IO = (1 << 12),	/* synchronous read IO is efficient */
+	SWP_WRITE_SYNCHRONOUS_IO = (1 << 13),	/* synchronous write IO is efficient */
+	SWP_SCANNING	= (1 << 14),		/* refcount in scan_swap_map */
+						/* add others here before... */
 };
 
 #define SWAP_CLUSTER_MAX 32UL
diff --git a/mm/memory.c b/mm/memory.c
index 75c2dfd04f72..56c864d5d787 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4293,7 +4293,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
 	swapcache = folio;
 
 	if (!folio) {
-		if (data_race(si->flags & SWP_SYNCHRONOUS_IO) &&
+		if (data_race(si->flags & SWP_READ_SYNCHRONOUS_IO) &&
 		    __swap_count(entry) == 1) {
 			/* skip swapcache */
 			folio = alloc_swap_folio(vmf);
@@ -4430,7 +4430,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
 		goto out_nomap;
 	}
 
-	/* allocated large folios for SWP_SYNCHRONOUS_IO */
+	/* allocated large folios for SWP_READ_SYNCHRONOUS_IO */
 	if (folio_test_large(folio) && !folio_test_swapcache(folio)) {
 		unsigned long nr = folio_nr_pages(folio);
 		unsigned long folio_start = ALIGN_DOWN(vmf->address, nr * PAGE_SIZE);
diff --git a/mm/page_io.c b/mm/page_io.c
index 4b4ea8e49cf6..d692eafdd90c 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -465,10 +465,10 @@ void __swap_writepage(struct folio *folio, struct writeback_control *wbc)
 		swap_writepage_fs(folio, wbc);
 	/*
 	 * ->flags can be updated non-atomicially (scan_swap_map_slots),
-	 * but that will never affect SWP_SYNCHRONOUS_IO, so the data_race
+	 * but that will never affect SWP_WRITE_SYNCHRONOUS_IO, so the data_race
 	 * is safe.
 	 */
-	else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO))
+	else if (data_race(sis->flags & SWP_WRITE_SYNCHRONOUS_IO))
 		swap_writepage_bdev_sync(folio, wbc, sis);
 	else
 		swap_writepage_bdev_async(folio, wbc, sis);
@@ -616,7 +616,7 @@ static void swap_read_folio_bdev_async(struct folio *folio,
 void swap_read_folio(struct folio *folio, struct swap_iocb **plug)
 {
 	struct swap_info_struct *sis = swp_swap_info(folio->swap);
-	bool synchronous = sis->flags & SWP_SYNCHRONOUS_IO;
+	bool synchronous = sis->flags & SWP_READ_SYNCHRONOUS_IO;
 	bool workingset = folio_test_workingset(folio);
 	unsigned long pflags;
 	bool in_thrashing;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index b0a9071cfe1d..902e5698af44 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3488,8 +3488,11 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	if (si->bdev && bdev_stable_writes(si->bdev))
 		si->flags |= SWP_STABLE_WRITES;
 
-	if (si->bdev && bdev_synchronous(si->bdev))
-		si->flags |= SWP_SYNCHRONOUS_IO;
+	if (si->bdev && bdev_read_synchronous(si->bdev))
+		si->flags |= SWP_READ_SYNCHRONOUS_IO;
+
+	if (si->bdev && bdev_write_synchronous(si->bdev))
+		si->flags |= SWP_WRITE_SYNCHRONOUS_IO;
 
 	if (si->bdev && bdev_nonrot(si->bdev)) {
 		si->flags |= SWP_SOLIDSTATE;
-- 
2.45.2



From qun-wei.lin at mediatek.com  Fri Mar  7 04:01:04 2025
From: qun-wei.lin at mediatek.com (Qun-Wei Lin)
Date: Fri, 7 Mar 2025 20:01:04 +0800
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
Message-ID: <20250307120141.1566673-3-qun-wei.lin@mediatek.com>

Introduced Kcompressd to offload zram page compression, improving
system efficiency by handling compression separately from memory
reclaiming. Added necessary configurations and dependencies.

Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
---
 drivers/block/zram/Kconfig      |  11 ++
 drivers/block/zram/Makefile     |   3 +-
 drivers/block/zram/kcompressd.c | 340 ++++++++++++++++++++++++++++++++
 drivers/block/zram/kcompressd.h |  25 +++
 drivers/block/zram/zram_drv.c   |  22 ++-
 5 files changed, 397 insertions(+), 4 deletions(-)
 create mode 100644 drivers/block/zram/kcompressd.c
 create mode 100644 drivers/block/zram/kcompressd.h

diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 402b7b175863..f0a1b574f770 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
 	  re-compress pages using a potentially slower but more effective
 	  compression algorithm. Note, that IDLE page recompression
 	  requires ZRAM_TRACK_ENTRY_ACTIME.
+
+config KCOMPRESSD
+	tristate "Kcompressd: Accelerated zram compression"
+	depends on ZRAM
+	help
+	  Kcompressd creates multiple daemons to accelerate the compression of pages
+	  in zram, offloading this time-consuming task from the zram driver.
+
+	  This approach improves system efficiency by handling page compression separately,
+	  which was originally done by kswapd or direct reclaim.
+
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 0fdefd576691..23baa5dfceb9 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -9,4 +9,5 @@ zram-$(CONFIG_ZRAM_BACKEND_ZSTD)	+= backend_zstd.o
 zram-$(CONFIG_ZRAM_BACKEND_DEFLATE)	+= backend_deflate.o
 zram-$(CONFIG_ZRAM_BACKEND_842)		+= backend_842.o
 
-obj-$(CONFIG_ZRAM)	+=	zram.o
+obj-$(CONFIG_ZRAM)		+= zram.o
+obj-$(CONFIG_KCOMPRESSD)	+= kcompressd.o
diff --git a/drivers/block/zram/kcompressd.c b/drivers/block/zram/kcompressd.c
new file mode 100644
index 000000000000..195b7e386869
--- /dev/null
+++ b/drivers/block/zram/kcompressd.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bio.h>
+#include <linux/bitops.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/psi.h>
+#include <linux/kfifo.h>
+#include <linux/swap.h>
+#include <linux/delay.h>
+
+#include "kcompressd.h"
+
+#define INIT_QUEUE_SIZE		4096
+#define DEFAULT_NR_KCOMPRESSD	4
+
+static atomic_t enable_kcompressd;
+static unsigned int nr_kcompressd;
+static unsigned int queue_size_per_kcompressd;
+static struct kcompress *kcompress;
+
+enum run_state {
+	KCOMPRESSD_NOT_STARTED = 0,
+	KCOMPRESSD_RUNNING,
+	KCOMPRESSD_SLEEPING,
+};
+
+struct kcompressd_para {
+	wait_queue_head_t *kcompressd_wait;
+	struct kfifo *write_fifo;
+	atomic_t *running;
+};
+
+static struct kcompressd_para *kcompressd_para;
+static BLOCKING_NOTIFIER_HEAD(kcompressd_notifier_list);
+
+struct write_work {
+	void *mem;
+	struct bio *bio;
+	compress_callback cb;
+};
+
+int kcompressd_enabled(void)
+{
+	return likely(atomic_read(&enable_kcompressd));
+}
+EXPORT_SYMBOL(kcompressd_enabled);
+
+static void kcompressd_try_to_sleep(struct kcompressd_para *p)
+{
+	DEFINE_WAIT(wait);
+
+	if (!kfifo_is_empty(p->write_fifo))
+		return;
+
+	if (freezing(current) || kthread_should_stop())
+		return;
+
+	atomic_set(p->running, KCOMPRESSD_SLEEPING);
+	prepare_to_wait(p->kcompressd_wait, &wait, TASK_INTERRUPTIBLE);
+
+	/*
+	 * After a short sleep, check if it was a premature sleep. If not, then
+	 * go fully to sleep until explicitly woken up.
+	 */
+	if (!kthread_should_stop() && kfifo_is_empty(p->write_fifo))
+		schedule();
+
+	finish_wait(p->kcompressd_wait, &wait);
+	atomic_set(p->running, KCOMPRESSD_RUNNING);
+}
+
+static int kcompressd(void *para)
+{
+	struct task_struct *tsk = current;
+	struct kcompressd_para *p = (struct kcompressd_para *)para;
+
+	tsk->flags |= PF_MEMALLOC | PF_KSWAPD;
+	set_freezable();
+
+	while (!kthread_should_stop()) {
+		bool ret;
+
+		kcompressd_try_to_sleep(p);
+		ret = try_to_freeze();
+		if (kthread_should_stop())
+			break;
+
+		if (ret)
+			continue;
+
+		while (!kfifo_is_empty(p->write_fifo)) {
+			struct write_work entry;
+
+			if (sizeof(struct write_work) == kfifo_out(p->write_fifo,
+						&entry, sizeof(struct write_work))) {
+				entry.cb(entry.mem, entry.bio);
+				bio_put(entry.bio);
+			}
+		}
+
+	}
+
+	tsk->flags &= ~(PF_MEMALLOC | PF_KSWAPD);
+	atomic_set(p->running, KCOMPRESSD_NOT_STARTED);
+	return 0;
+}
+
+static int init_write_queue(void)
+{
+	int i;
+	unsigned int queue_len = queue_size_per_kcompressd * sizeof(struct write_work);
+
+	for (i = 0; i < nr_kcompressd; i++) {
+		if (kfifo_alloc(&kcompress[i].write_fifo,
+					queue_len, GFP_KERNEL)) {
+			pr_err("Failed to alloc kfifo %d\n", i);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static void clean_bio_queue(int idx)
+{
+	struct write_work entry;
+
+	while (sizeof(struct write_work) == kfifo_out(&kcompress[idx].write_fifo,
+				&entry, sizeof(struct write_work))) {
+		bio_put(entry.bio);
+		entry.cb(entry.mem, entry.bio);
+	}
+	kfifo_free(&kcompress[idx].write_fifo);
+}
+
+static int kcompress_update(void)
+{
+	int i;
+	int ret;
+
+	kcompress = kvmalloc_array(nr_kcompressd, sizeof(struct kcompress), GFP_KERNEL);
+	if (!kcompress)
+		return -ENOMEM;
+
+	kcompressd_para = kvmalloc_array(nr_kcompressd, sizeof(struct kcompressd_para), GFP_KERNEL);
+	if (!kcompressd_para)
+		return -ENOMEM;
+
+	ret = init_write_queue();
+	if (ret) {
+		pr_err("Initialization of writing to FIFOs failed!!\n");
+		return ret;
+	}
+
+	for (i = 0; i < nr_kcompressd; i++) {
+		init_waitqueue_head(&kcompress[i].kcompressd_wait);
+		kcompressd_para[i].kcompressd_wait = &kcompress[i].kcompressd_wait;
+		kcompressd_para[i].write_fifo = &kcompress[i].write_fifo;
+		kcompressd_para[i].running = &kcompress[i].running;
+	}
+
+	return 0;
+}
+
+static void stop_all_kcompressd_thread(void)
+{
+	int i;
+
+	for (i = 0; i < nr_kcompressd; i++) {
+		kthread_stop(kcompress[i].kcompressd);
+		kcompress[i].kcompressd = NULL;
+		clean_bio_queue(i);
+	}
+}
+
+static int do_nr_kcompressd_handler(const char *val,
+		const struct kernel_param *kp)
+{
+	int ret;
+
+	atomic_set(&enable_kcompressd, false);
+
+	stop_all_kcompressd_thread();
+
+	ret = param_set_int(val, kp);
+	if (!ret) {
+		pr_err("Invalid number of kcompressd.\n");
+		return -EINVAL;
+	}
+
+	ret = init_write_queue();
+	if (ret) {
+		pr_err("Initialization of writing to FIFOs failed!!\n");
+		return ret;
+	}
+
+	atomic_set(&enable_kcompressd, true);
+
+	return 0;
+}
+
+static const struct kernel_param_ops param_ops_change_nr_kcompressd = {
+	.set = &do_nr_kcompressd_handler,
+	.get = &param_get_uint,
+	.free = NULL,
+};
+
+module_param_cb(nr_kcompressd, &param_ops_change_nr_kcompressd,
+		&nr_kcompressd, 0644);
+MODULE_PARM_DESC(nr_kcompressd, "Number of pre-created daemon for page compression");
+
+static int do_queue_size_per_kcompressd_handler(const char *val,
+		const struct kernel_param *kp)
+{
+	int ret;
+
+	atomic_set(&enable_kcompressd, false);
+
+	stop_all_kcompressd_thread();
+
+	ret = param_set_int(val, kp);
+	if (!ret) {
+		pr_err("Invalid queue size for kcompressd.\n");
+		return -EINVAL;
+	}
+
+	ret = init_write_queue();
+	if (ret) {
+		pr_err("Initialization of writing to FIFOs failed!!\n");
+		return ret;
+	}
+
+	pr_info("Queue size for kcompressd was changed: %d\n", queue_size_per_kcompressd);
+
+	atomic_set(&enable_kcompressd, true);
+	return 0;
+}
+
+static const struct kernel_param_ops param_ops_change_queue_size_per_kcompressd = {
+	.set = &do_queue_size_per_kcompressd_handler,
+	.get = &param_get_uint,
+	.free = NULL,
+};
+
+module_param_cb(queue_size_per_kcompressd, &param_ops_change_queue_size_per_kcompressd,
+		&queue_size_per_kcompressd, 0644);
+MODULE_PARM_DESC(queue_size_per_kcompressd,
+		"Size of queue for kcompressd");
+
+int schedule_bio_write(void *mem, struct bio *bio, compress_callback cb)
+{
+	int i;
+	bool submit_success = false;
+	size_t sz_work = sizeof(struct write_work);
+
+	struct write_work entry = {
+		.mem = mem,
+		.bio = bio,
+		.cb = cb
+	};
+
+	if (unlikely(!atomic_read(&enable_kcompressd)))
+		return -EBUSY;
+
+	if (!nr_kcompressd || !current_is_kswapd())
+		return -EBUSY;
+
+	bio_get(bio);
+
+	for (i = 0; i < nr_kcompressd; i++) {
+		submit_success =
+			(kfifo_avail(&kcompress[i].write_fifo) >= sz_work) &&
+			(sz_work == kfifo_in(&kcompress[i].write_fifo, &entry, sz_work));
+
+		if (submit_success) {
+			switch (atomic_read(&kcompress[i].running)) {
+			case KCOMPRESSD_NOT_STARTED:
+				atomic_set(&kcompress[i].running, KCOMPRESSD_RUNNING);
+				kcompress[i].kcompressd = kthread_run(kcompressd,
+						&kcompressd_para[i], "kcompressd:%d", i);
+				if (IS_ERR(kcompress[i].kcompressd)) {
+					atomic_set(&kcompress[i].running, KCOMPRESSD_NOT_STARTED);
+					pr_warn("Failed to start kcompressd:%d\n", i);
+					clean_bio_queue(i);
+				}
+				break;
+			case KCOMPRESSD_RUNNING:
+				break;
+			case KCOMPRESSD_SLEEPING:
+				wake_up_interruptible(&kcompress[i].kcompressd_wait);
+				break;
+			}
+			return 0;
+		}
+	}
+
+	bio_put(bio);
+	return -EBUSY;
+}
+EXPORT_SYMBOL(schedule_bio_write);
+
+static int __init kcompressd_init(void)
+{
+	int ret;
+
+	nr_kcompressd = DEFAULT_NR_KCOMPRESSD;
+	queue_size_per_kcompressd = INIT_QUEUE_SIZE;
+
+	ret = kcompress_update();
+	if (ret) {
+		pr_err("Init kcompressd failed!\n");
+		return ret;
+	}
+
+	atomic_set(&enable_kcompressd, true);
+	blocking_notifier_call_chain(&kcompressd_notifier_list, 0, NULL);
+	return 0;
+}
+
+static void __exit kcompressd_exit(void)
+{
+	atomic_set(&enable_kcompressd, false);
+	stop_all_kcompressd_thread();
+
+	kvfree(kcompress);
+	kvfree(kcompressd_para);
+}
+
+module_init(kcompressd_init);
+module_exit(kcompressd_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Qun-Wei Lin <qun-wei.lin at mediatek.com>");
+MODULE_DESCRIPTION("Separate the page compression from the memory reclaiming");
+
diff --git a/drivers/block/zram/kcompressd.h b/drivers/block/zram/kcompressd.h
new file mode 100644
index 000000000000..2fe0b424a7af
--- /dev/null
+++ b/drivers/block/zram/kcompressd.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+
+#ifndef _KCOMPRESSD_H_
+#define _KCOMPRESSD_H_
+
+#include <linux/rwsem.h>
+#include <linux/kfifo.h>
+#include <linux/atomic.h>
+
+typedef void (*compress_callback)(void *mem, struct bio *bio);
+
+struct kcompress {
+	struct task_struct *kcompressd;
+	wait_queue_head_t kcompressd_wait;
+	struct kfifo write_fifo;
+	atomic_t running;
+};
+
+int kcompressd_enabled(void);
+int schedule_bio_write(void *mem, struct bio *bio, compress_callback cb);
+#endif
+
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 2e1a70f2f4bd..bcd63ecb6ff2 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -35,6 +35,7 @@
 #include <linux/part_stat.h>
 #include <linux/kernel_read_file.h>
 
+#include "kcompressd.h"
 #include "zram_drv.h"
 
 static DEFINE_IDR(zram_index_idr);
@@ -2240,6 +2241,15 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
 	bio_endio(bio);
 }
 
+#if IS_ENABLED(CONFIG_KCOMPRESSD)
+static void zram_bio_write_callback(void *mem, struct bio *bio)
+{
+	struct zram *zram = (struct zram *)mem;
+
+	zram_bio_write(zram, bio);
+}
+#endif
+
 /*
  * Handler function for all zram I/O requests.
  */
@@ -2252,6 +2262,10 @@ static void zram_submit_bio(struct bio *bio)
 		zram_bio_read(zram, bio);
 		break;
 	case REQ_OP_WRITE:
+#if IS_ENABLED(CONFIG_KCOMPRESSD)
+		if (kcompressd_enabled() && !schedule_bio_write(zram, bio, zram_bio_write_callback))
+			break;
+#endif
 		zram_bio_write(zram, bio);
 		break;
 	case REQ_OP_DISCARD:
@@ -2535,9 +2549,11 @@ static int zram_add(void)
 #if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
 		.max_write_zeroes_sectors	= UINT_MAX,
 #endif
-		.features			= BLK_FEAT_STABLE_WRITES	|
-						  BLK_FEAT_READ_SYNCHRONOUS	|
-						  BLK_FEAT_WRITE_SYNCHRONOUS,
+		.features			= BLK_FEAT_STABLE_WRITES
+						  | BLK_FEAT_READ_SYNCHRONOUS
+#if !IS_ENABLED(CONFIG_KCOMPRESSD)
+						  | BLK_FEAT_WRITE_SYNCHRONOUS,
+#endif
 	};
 	struct zram *zram;
 	int ret, device_id;
-- 
2.45.2



From qun-wei.lin at mediatek.com  Fri Mar  7 04:01:02 2025
From: qun-wei.lin at mediatek.com (Qun-Wei Lin)
Date: Fri, 7 Mar 2025 20:01:02 +0800
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
Message-ID: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>

This patch series introduces a new mechanism called kcompressd to
improve the efficiency of memory reclaiming in the operating system. The
main goal is to separate the tasks of page scanning and page compression
into distinct processes or threads, thereby reducing the load on the
kswapd thread and enhancing overall system performance under high memory
pressure conditions.

Problem:
 In the current system, the kswapd thread is responsible for both
 scanning the LRU pages and compressing pages into the ZRAM. This
 combined responsibility can lead to significant performance bottlenecks,
 especially under high memory pressure. The kswapd thread becomes a
 single point of contention, causing delays in memory reclaiming and
 overall system performance degradation.

Target:
 The target of this invention is to improve the efficiency of memory
 reclaiming. By separating the tasks of page scanning and page
 compression into distinct processes or threads, the system can handle
 memory pressure more effectively.

Patch 1:
- Introduces 2 new feature flags, BLK_FEAT_READ_SYNCHRONOUS and
  SWP_READ_SYNCHRONOUS_IO.

Patch 2:
- Implemented the core functionality of Kcompressd and made necessary
  modifications to the zram driver to support it.

In our handheld devices, we found that applying this mechanism under high
memory pressure scenarios can increase the rate of pgsteal_anon per second
by over 260% compared to the situation with only kswapd.

Qun-Wei Lin (2):
  mm: Split BLK_FEAT_SYNCHRONOUS and SWP_SYNCHRONOUS_IO into separate
    read and write flags
  kcompressd: Add Kcompressd for accelerated zram compression

 drivers/block/brd.c             |   3 +-
 drivers/block/zram/Kconfig      |  11 ++
 drivers/block/zram/Makefile     |   3 +-
 drivers/block/zram/kcompressd.c | 340 ++++++++++++++++++++++++++++++++
 drivers/block/zram/kcompressd.h |  25 +++
 drivers/block/zram/zram_drv.c   |  21 +-
 drivers/nvdimm/btt.c            |   3 +-
 drivers/nvdimm/pmem.c           |   5 +-
 include/linux/blkdev.h          |  24 ++-
 include/linux/swap.h            |  31 +--
 mm/memory.c                     |   4 +-
 mm/page_io.c                    |   6 +-
 mm/swapfile.c                   |   7 +-
 13 files changed, 446 insertions(+), 37 deletions(-)
 create mode 100644 drivers/block/zram/kcompressd.c
 create mode 100644 drivers/block/zram/kcompressd.h

-- 
2.45.2



From robh at kernel.org  Fri Mar  7 04:15:32 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 7 Mar 2025 06:15:32 -0600
Subject: [PATCH 5/5] arm64: dts: ti: k3-j722s-evm: Add overlay for TEVI OV5640
In-Reply-To: <20250218185452.600797-6-vaishnav.a@ti.com>
References: <20250218185452.600797-1-vaishnav.a@ti.com> <20250218185452.600797-6-vaishnav.a@ti.com>
Message-ID: <CAL_JsqLxHKdQujWdSkGe6_cUftdgNgJ2PyVZR41A_LJ241_D3g@mail.gmail.com>

On Tue, Feb 18, 2025 at 12:55?PM Vaishnav Achath <vaishnav.a at ti.com> wrote:
>
> TechNexion TEVI OV5640 camera is a 5MP camera that can be used with
> J722S EVM through the 22-pin CSI-RX connector. Add a reference overlay
> for quad TEVI OV5640 modules on J722S EVM.
>
> Signed-off-by: Vaishnav Achath <vaishnav.a at ti.com>
> ---
>  arch/arm64/boot/dts/ti/Makefile               |   4 +
>  .../k3-j722s-evm-csi2-quad-tevi-ov5640.dtso   | 319 ++++++++++++++++++
>  2 files changed, 323 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-tevi-ov5640.dtso
>
> diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
> index 9ae0917e5763..0370392abda8 100644
> --- a/arch/arm64/boot/dts/ti/Makefile
> +++ b/arch/arm64/boot/dts/ti/Makefile
> @@ -120,6 +120,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-pcie1-ep.dtbo
>  dtb-$(CONFIG_ARCH_K3) += k3-am67a-beagley-ai.dtb
>  dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb
>  dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtbo
> +dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm-csi2-quad-tevi-ov5640.dtbo
>
>  # Boards with J784s4 SoC
>  dtb-$(CONFIG_ARCH_K3) += k3-am69-sk.dtb
> @@ -212,6 +213,8 @@ k3-j721s2-evm-pcie1-ep-dtbs := k3-j721s2-common-proc-board.dtb \
>         k3-j721s2-evm-pcie1-ep.dtbo
>  k3-j722s-evm-csi2-quad-rpi-cam-imx219-dtbs := k3-j722s-evm.dtb \
>         k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtbo
> +k3-j722s-evm-csi2-quad-tevi-ov5640-dtbs := k3-j722s-evm.dtb \
> +       k3-j722s-evm-csi2-quad-tevi-ov5640.dtbo
>  k3-j784s4-evm-pcie0-pcie1-ep-dtbs := k3-j784s4-evm.dtb \
>         k3-j784s4-evm-pcie0-pcie1-ep.dtbo
>  k3-j784s4-evm-quad-port-eth-exp1-dtbs := k3-j784s4-evm.dtb \
> @@ -247,6 +250,7 @@ dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
>         k3-j721e-sk-csi2-dual-imx219.dtb \
>         k3-j721s2-evm-pcie1-ep.dtb \
>         k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtb \
> +       k3-j722s-evm-csi2-quad-tevi-ov5640.dtb \
>         k3-j784s4-evm-pcie0-pcie1-ep.dtb \
>         k3-j784s4-evm-quad-port-eth-exp1.dtb \
>         k3-j784s4-evm-usxgmii-exp1-exp2.dtb
> diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-tevi-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-tevi-ov5640.dtso
> new file mode 100644
> index 000000000000..f33f50465a07
> --- /dev/null
> +++ b/arch/arm64/boot/dts/ti/k3-j722s-evm-csi2-quad-tevi-ov5640.dtso
> @@ -0,0 +1,319 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * 4 x TEVI OV5640 MIPI Camera module on RPI camera connector.
> + *
> + * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include "k3-pinctrl.h"
> +
> +&{/} {
> +       clk_ov5640_fixed: ov5640-xclk {

clock-24000000 for the node name.

> +               compatible = "fixed-clock";
> +               #clock-cells = <0>;
> +               clock-frequency = <24000000>;
> +       };
> +};
> +
> +
> +&main_pmx0 {
> +       cam0_reset_pins_default: cam0-reset-pins-default {

Doesn't match the schema. Please test your changes:

pinctrl at f4000: 'cam0-reset-pins-default', 'cam1-reset-pins-default',
'cam2-reset-pins-default', 'cam3-reset-pins-default' do not match any
of the regexes: '-pins(-[0-9]+)?$|-pin$', 'pinctrl-[0-9]+'

> +               pinctrl-single,pins = <
> +                       J722S_IOPAD(0x03c, PIN_OUTPUT, 7)
> +               >;
> +       };
> +
> +       cam1_reset_pins_default: cam1-reset-pins-default {
> +               pinctrl-single,pins = <
> +                       J722S_IOPAD(0x044, PIN_OUTPUT, 7)
> +               >;
> +       };
> +
> +       cam2_reset_pins_default: cam2-reset-pins-default {
> +               pinctrl-single,pins = <
> +                       J722S_IOPAD(0x04c, PIN_OUTPUT, 7)
> +               >;
> +       };
> +
> +       cam3_reset_pins_default: cam3-reset-pins-default {
> +               pinctrl-single,pins = <
> +                       J722S_IOPAD(0x054, PIN_OUTPUT, 7)
> +               >;
> +       };
> +};
> +
> +&exp1 {
> +       p06-hog{
> +               /* P06 - CSI01_MUX_SEL_2 */
> +               gpio-hog;
> +               gpios = <6 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI01_MUX_SEL_2";
> +       };
> +
> +       p07-hog{
> +               /* P01 - CSI23_MUX_SEL_2 */
> +               gpio-hog;
> +               gpios = <7 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI23_MUX_SEL_2";
> +       };
> +};
> +
> +&main_gpio0 {
> +       p15-hog {
> +               /* P15 - CSI2_CAMERA_GPIO1 */
> +               gpio-hog;
> +               gpios = <15 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI2_CAMERA_GPIO1";
> +       };
> +
> +       p17-hog {
> +               /* P17 - CSI2_CAMERA_GPIO2 */
> +               gpio-hog;
> +               gpios = <17 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI2_CAMERA_GPIO2";
> +       };
> +
> +       p19-hog {
> +               /* P19 - CSI2_CAMERA_GPIO3 */
> +               gpio-hog;
> +               gpios = <19 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI2_CAMERA_GPIO3";
> +       };
> +
> +       p21-hog {
> +               /* P21 - CSI2_CAMERA_GPIO4 */
> +               gpio-hog;
> +               gpios = <21 GPIO_ACTIVE_HIGH>;
> +               output-high;
> +               line-name = "CSI2_CAMERA_GPIO4";
> +       };
> +};
> +
> +&pca9543_0 {
> +       #address-cells = <1>;
> +       #size-cells = <0>;
> +
> +       i2c-alias-pool = /bits/ 16 <0x3c 0x3d>;
> +
> +       i2c at 0 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <0>;
> +
> +               ov5640_0: camera at 3c {
> +                       compatible = "ovti,ov5640";
> +                       reg = <0x3c>;
> +                       clocks = <&clk_ov5640_fixed>;
> +                       clock-names = "xclk";
> +
> +                       pinctrl-names = "default";
> +                       pinctrl-0 = <&cam0_reset_pins_default>;
> +
> +                       port {
> +                               csi2_cam0: endpoint {
> +                                       remote-endpoint = <&csi2rx0_in_sensor>;
> +                                       clock-lanes = <0>;
> +                                       data-lanes = <1 2>;
> +                               };
> +                       };
> +               };
> +       };
> +
> +       i2c at 1 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <1>;
> +
> +               ov5640_1: camera at 3c {
> +                       compatible = "ovti,ov5640";
> +                       reg = <0x3c>;
> +                       clocks = <&clk_ov5640_fixed>;
> +                       clock-names = "xclk";
> +
> +                       pinctrl-names = "default";
> +                       pinctrl-0 = <&cam1_reset_pins_default>;
> +
> +                       port {
> +                               csi2_cam1: endpoint {
> +                                       remote-endpoint = <&csi2rx1_in_sensor>;
> +                                       clock-lanes = <0>;
> +                                       data-lanes = <1 2>;
> +                               };
> +                       };
> +               };
> +       };
> +};
> +
> +&pca9543_1 {
> +       #address-cells = <1>;
> +       #size-cells = <0>;
> +
> +       i2c-alias-pool = /bits/ 16 <0x3c 0x3d>;
> +
> +       i2c at 0 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <0>;
> +
> +               ov5640_2: camera at 3c {
> +                       compatible = "ovti,ov5640";
> +                       reg = <0x3c>;
> +                       clocks = <&clk_ov5640_fixed>;
> +                       clock-names = "xclk";
> +
> +                       pinctrl-names = "default";
> +                       pinctrl-0 = <&cam2_reset_pins_default>;
> +
> +                       port {
> +                               csi2_cam2: endpoint {
> +                                       remote-endpoint = <&csi2rx2_in_sensor>;
> +                                       clock-lanes = <0>;
> +                                       data-lanes = <1 2>;
> +                               };
> +                       };
> +               };
> +       };
> +
> +       i2c at 1 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <1>;
> +
> +               ov5640_3: camera at 3c {
> +                       compatible = "ovti,ov5640";
> +                       reg = <0x3c>;
> +                       clocks = <&clk_ov5640_fixed>;
> +                       clock-names = "xclk";
> +
> +                       pinctrl-names = "default";
> +                       pinctrl-0 = <&cam3_reset_pins_default>;
> +
> +                       port {
> +                               csi2_cam3: endpoint {
> +                                       remote-endpoint = <&csi2rx3_in_sensor>;
> +                                       clock-lanes = <0>;
> +                                       data-lanes = <1 2>;
> +                               };
> +                       };
> +               };
> +       };
> +};
> +
> +&cdns_csi2rx0 {
> +       ports {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               csi0_port0: port at 0 {
> +                       reg = <0>;
> +                       status = "okay";
> +
> +                       csi2rx0_in_sensor: endpoint {
> +                               remote-endpoint = <&csi2_cam0>;
> +                               bus-type = <4>; /* CSI2 DPHY */
> +                               clock-lanes = <0>;
> +                               data-lanes = <1 2>;
> +                       };
> +               };
> +       };
> +};
> +
> +&cdns_csi2rx1 {
> +       ports {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               csi1_port0: port at 0 {
> +                       reg = <0>;
> +                       status = "okay";
> +
> +                       csi2rx1_in_sensor: endpoint {
> +                               remote-endpoint = <&csi2_cam1>;
> +                               bus-type = <4>; /* CSI2 DPHY */
> +                               clock-lanes = <0>;
> +                               data-lanes = <1 2>;
> +                       };
> +               };
> +       };
> +};
> +
> +&cdns_csi2rx2 {
> +       ports {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               csi2_port0: port at 0 {
> +                       reg = <0>;
> +                       status = "okay";
> +
> +                       csi2rx2_in_sensor: endpoint {
> +                               remote-endpoint = <&csi2_cam2>;
> +                               bus-type = <4>; /* CSI2 DPHY */
> +                               clock-lanes = <0>;
> +                               data-lanes = <1 2>;
> +                       };
> +               };
> +       };
> +};
> +
> +&cdns_csi2rx3 {
> +       ports {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               csi3_port0: port at 0 {
> +                       reg = <0>;
> +                       status = "okay";
> +
> +                       csi2rx3_in_sensor: endpoint {
> +                               remote-endpoint = <&csi2_cam3>;
> +                               bus-type = <4>; /* CSI2 DPHY */
> +                               clock-lanes = <0>;
> +                               data-lanes = <1 2>;
> +                       };
> +               };
> +       };
> +};
> +
> +&ti_csi2rx0 {
> +       status = "okay";
> +};
> +
> +&dphy0 {
> +       status = "okay";
> +};
> +
> +&ti_csi2rx1 {
> +       status = "okay";
> +};
> +
> +&dphy1 {
> +       status = "okay";
> +};
> +
> +
> +&ti_csi2rx2 {
> +       status = "okay";
> +};
> +
> +&dphy2 {
> +       status = "okay";
> +};
> +
> +
> +&ti_csi2rx3 {
> +       status = "okay";
> +};
> +
> +&dphy3 {
> +       status = "okay";
> +};
> --
> 2.34.1
>


From geert at linux-m68k.org  Fri Mar  7 04:15:32 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 7 Mar 2025 13:15:32 +0100
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format specifier
In-Reply-To: <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com> <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
Message-ID: <CAMuHMdUzZ8GK1mqXw+YgvFZ5xhOy-v_oOeaVrCtFUhk=n+rF8g@mail.gmail.com>

Hi Luca,

On Fri, 7 Mar 2025 at 12:19, Luca Ceresoli <luca.ceresoli at bootlin.com> wrote:
> %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> add %pC{,n,r} format specifiers for clocks") introducing them does not
> clarify any intended difference. It can be assumed %pC is a default for
> %pCn as some other specifiers do, but not all are consistent with this
> policy. Moreover there is now no other suffix other than 'n', which makes a
> default not really useful.

The original intention was indeed to serve as a default, like some
other formats also have ("%pa[p]", %pOF[f]").

> All users in the kernel were using %pC except for one which has been
> converted. So now remove %pCn and all the unnecessary extra code and
> documentation.
>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

I guess this is a worthwhile cleanup.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From mike.leach at linaro.org  Fri Mar  7 04:17:05 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 7 Mar 2025 12:17:05 +0000
Subject: [PATCH v3 3/7] coresight-tgu: Add signal priority support
In-Reply-To: <20250227092640.2666894-4-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com> <20250227092640.2666894-4-quic_songchai@quicinc.com>
Message-ID: <CAJ9a7Vi9CWGKGYe6jBELFN_X6dSG4EfQQd5moju5ekbrLWxi2g@mail.gmail.com>

Hi

On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>
> From: Songwei Chai <quic_songchai at quicinc.com>
>
> Like circuit of a Logic analyzer, in TGU, the requirement could be
> configured in each step and the trigger will be created once the
> requirements are met. Add priority functionality here to sort the
> signals into different priorities. The signal which is wanted could
> be configured in each step's priority node, the larger number means
> the higher priority and the signal with higher priority will be sensed
> more preferentially.
>
> Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> Signed-off-by: songchai <quic_songchai at quicinc.com>
> ---
>  .../testing/sysfs-bus-coresight-devices-tgu   |   7 +
>  drivers/hwtracing/coresight/coresight-tgu.c   | 139 ++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-tgu.h   | 110 ++++++++++++++
>  3 files changed, 256 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> index 741bc9fd9df5..af7332153833 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> @@ -7,3 +7,10 @@ Description:
>                 Accepts only one of the 2 values -  0 or 1.
>                 0 : disable TGU.
>                 1 : enable TGU.
> +
> +What:           /sys/bus/coresight/devices/<tgu-name>/step[0:7]_priority[0:3]/reg[0:17]
> +Date:           February 2025
> +KernelVersion   6.15
> +Contact:        Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
> +Description:
> +                (RW) Set/Get the sensed siganal with specific step and priority for TGU.

sp/siganal/signal

> diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c
> index da4c04ac1097..f28761619ebe 100644
> --- a/drivers/hwtracing/coresight/coresight-tgu.c
> +++ b/drivers/hwtracing/coresight/coresight-tgu.c
> @@ -17,9 +17,92 @@
>
>  DEFINE_CORESIGHT_DEVLIST(tgu_devs, "tgu");
>
> +static int calculate_array_location(struct tgu_drvdata *drvdata, int step_index,
> +                         int operation_index, int reg_index)
> +{
> +       int ret = -EINVAL;
> +
> +       ret = operation_index * (drvdata->max_step) *
> +                     (drvdata->max_reg) + step_index * (drvdata->max_reg)
> +                               + reg_index;
> +
> +       return ret;
> +}
> +
> +static ssize_t tgu_dataset_show(struct device *dev,
> +                               struct device_attribute *attr, char *buf)
> +{
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +       struct tgu_attribute *tgu_attr =
> +               container_of(attr, struct tgu_attribute, attr);
> +
> +       return sysfs_emit(buf, "0x%x\n",
> +                         drvdata->value_table->priority[calculate_array_location(
> +                                 drvdata, tgu_attr->step_index,
> +                                 tgu_attr->operation_index, tgu_attr->reg_num)]);
> +
> +}
> +
> +static ssize_t tgu_dataset_store(struct device *dev,
> +                                struct device_attribute *attr, const char *buf,
> +                                size_t size)
> +{
> +       unsigned long val;
> +       ssize_t ret = -EINVAL;
> +
> +       struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev->parent);
> +       struct tgu_attribute *tgu_attr =
> +               container_of(attr, struct tgu_attribute, attr);
> +
> +       if (kstrtoul(buf, 0, &val))
> +               return ret;
> +
> +       guard(spinlock)(&tgu_drvdata->spinlock);
> +       tgu_drvdata->value_table->priority[calculate_array_location(
> +               tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
> +               tgu_attr->reg_num)] = val;
> +       ret = size;
> +
> +       return ret;

ret is unneeded - directly return either size or -EINVAL.

> +}
> +
> +static umode_t tgu_node_visible(struct kobject *kobject, struct attribute *attr,
> +                               int n)
> +{
> +       struct device *dev = kobj_to_dev(kobject);
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +       int ret = 0;
> +
> +       struct device_attribute *dev_attr =
> +               container_of(attr, struct device_attribute, attr);
> +       struct tgu_attribute *tgu_attr =
> +               container_of(dev_attr, struct tgu_attribute, attr);
> +
> +       if (tgu_attr->step_index < drvdata->max_step) {
> +               ret = (tgu_attr->reg_num < drvdata->max_reg) ?
> +                                           attr->mode : 0;
> +               return ret;
> +       }
> +       return SYSFS_GROUP_INVISIBLE;
> +}

default ret as SYSFS_GROUP_INVISIBLE, and returnret at end

> +
>  static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
>  {
> +       int i, j, k;
> +
>         CS_UNLOCK(drvdata->base);
> +
> +       for (i = 0; i < drvdata->max_step; i++) {
> +               for (j = 0; j < MAX_PRIORITY; j++) {
> +                       for (k = 0; k < drvdata->max_reg; k++) {
> +                               tgu_writel(drvdata,
> +                                          drvdata->value_table->priority
> +                                                  [calculate_array_location(drvdata, i, j, k)],
> +                                          PRIORITY_REG_STEP(i, j, k));
> +                       }
> +               }
> +       }
> +
>         /* Enable TGU to program the triggers */
>         tgu_writel(drvdata, 1, TGU_CONTROL);
>         CS_LOCK(drvdata->base);
> @@ -130,6 +213,38 @@ static const struct attribute_group tgu_common_grp = {
>
>  static const struct attribute_group *tgu_attr_groups[] = {
>         &tgu_common_grp,
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(0, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(0, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(0, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(0, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(1, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(1, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(1, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(1, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(2, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(2, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(2, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(2, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(3, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(3, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(3, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(3, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(4, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(4, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(4, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(4, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(5, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(5, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(5, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(5, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(6, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(6, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(6, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(6, 3),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(7, 0),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2),
> +       PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3),
>         NULL,
>  };
>
> @@ -164,6 +279,30 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
>
>         spin_lock_init(&drvdata->spinlock);
>
> +       ret = of_property_read_u32(adev->dev.of_node, "tgu-regs",
> +                                  &drvdata->max_reg);
> +       if (ret)
> +               return -EINVAL;
> +
> +       ret = of_property_read_u32(adev->dev.of_node, "tgu-steps",
> +                                  &drvdata->max_step);
> +       if (ret)
> +               return -EINVAL;
> +
> +       drvdata->value_table =
> +               devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL);
> +       if (!drvdata->value_table)
> +               return -ENOMEM;
> +
> +       drvdata->value_table->priority = devm_kzalloc(
> +               dev,
> +               MAX_PRIORITY * drvdata->max_reg * drvdata->max_step *
> +                       sizeof(*(drvdata->value_table->priority)),
> +               GFP_KERNEL);
> +
> +       if (!drvdata->value_table->priority)
> +               return -ENOMEM;
> +
>         drvdata->enable = false;
>         desc.type = CORESIGHT_DEV_TYPE_HELPER;
>         desc.pdata = adev->dev.platform_data;
> diff --git a/drivers/hwtracing/coresight/coresight-tgu.h b/drivers/hwtracing/coresight/coresight-tgu.h
> index 380686f94130..6e5d465117df 100644
> --- a/drivers/hwtracing/coresight/coresight-tgu.h
> +++ b/drivers/hwtracing/coresight/coresight-tgu.h
> @@ -13,6 +13,110 @@
>  #define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
>  #define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off)
>
> +/*
> + *  TGU configuration space                              Step configuration
> + *  offset table                                         space layout
> + * x-------------------------x$                          x-------------x$
> + * |                         |$                          |             |$
> + * |                         |                           |   reserve   |$
> + * |                         |                           |             |$
> + * |coresight management     |                           |-------------|base+n*0x1D8+0x1F4$
> + * |     registe             |                     |---> |prioroty[3]  |$
> + * |                         |                     |     |-------------|base+n*0x1D8+0x194$
> + * |                         |                     |     |prioroty[2]  |$
> + * |-------------------------|                     |     |-------------|base+n*0x1D8+0x134$
> + * |                         |                     |     |prioroty[1]  |$
> + * |         step[7]         |                     |     |-------------|base+n*0x1D8+0xD4$
> + * |-------------------------|->base+0x40+7*0x1D8  |     |prioroty[0]  |$
> + * |                         |                     |     |-------------|base+n*0x1D8+0x74$
> + * |         ...             |                     |     |  condition  |$
> + * |                         |                     |     |   select    |$
> + * |-------------------------|->base+0x40+1*0x1D8  |     |-------------|base+n*0x1D8+0x60$
> + * |                         |                     |     |  condition  |$
> + * |         step[0]         |-------------------->      |   decode    |$
> + * |-------------------------|-> base+0x40               |-------------|base+n*0x1D8+0x50$
> + * |                         |                           |             |$
> + * | Control and status space|                           |Timer/Counter|$
> + * |        space            |                           |             |$
> + * x-------------------------x->base                     x-------------x base+n*0x1D8+0x40$
> + *
> + */
> +
> +/* Calculate compare step addresses */
> +#define PRIORITY_REG_STEP(step, priority, reg)\
> +       (0x0074 + 0x60 * priority + 0x4 * reg + 0x1D8 * step)
> +

use #defines + explanation instead of arbitrary magic numbers

> +#define tgu_dataset_ro(name, step_index, type, reg_num)     \
> +       (&((struct tgu_attribute[]){ {                      \
> +               __ATTR(name, 0444, tgu_dataset_show, NULL), \
> +               step_index,                                 \
> +               type,                                       \
> +               reg_num,                                    \
> +       } })[0].attr.attr)
> +


This define unused in this patch, Drop till it is used.

> +#define tgu_dataset_rw(name, step_index, type, reg_num)                  \
> +       (&((struct tgu_attribute[]){ {                                   \
> +               __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \
> +               step_index,                                              \
> +               type,                                                    \
> +               reg_num,                                                 \
> +       } })[0].attr.attr)
> +
> +#define STEP_PRIORITY(step_index, reg_num, priority)                     \
> +       tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \
> +                      reg_num)
> +
> +#define STEP_PRIORITY_LIST(step_index, priority)  \
> +       {STEP_PRIORITY(step_index, 0, priority),  \
> +        STEP_PRIORITY(step_index, 1, priority),  \
> +        STEP_PRIORITY(step_index, 2, priority),  \
> +        STEP_PRIORITY(step_index, 3, priority),  \
> +        STEP_PRIORITY(step_index, 4, priority),  \
> +        STEP_PRIORITY(step_index, 5, priority),  \
> +        STEP_PRIORITY(step_index, 6, priority),  \
> +        STEP_PRIORITY(step_index, 7, priority),  \
> +        STEP_PRIORITY(step_index, 8, priority),  \
> +        STEP_PRIORITY(step_index, 9, priority),  \
> +        STEP_PRIORITY(step_index, 10, priority), \
> +        STEP_PRIORITY(step_index, 11, priority), \
> +        STEP_PRIORITY(step_index, 12, priority), \
> +        STEP_PRIORITY(step_index, 13, priority), \
> +        STEP_PRIORITY(step_index, 14, priority), \
> +        STEP_PRIORITY(step_index, 15, priority), \
> +        STEP_PRIORITY(step_index, 16, priority), \
> +        STEP_PRIORITY(step_index, 17, priority), \
> +        NULL                   \
> +       }
> +
> +#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\
> +       (&(const struct attribute_group){\
> +               .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\
> +               .is_visible = tgu_node_visible,\
> +               .name = "step" #step "_priority" #priority \
> +       })
> +
> +enum operation_index {
> +       TGU_PRIORITY0,
> +       TGU_PRIORITY1,
> +       TGU_PRIORITY2,
> +       TGU_PRIORITY3
> +
> +};
> +
> +/* Maximum priority that TGU supports */
> +#define MAX_PRIORITY 4
> +
> +struct tgu_attribute {
> +       struct device_attribute attr;
> +       u32 step_index;
> +       enum operation_index operation_index;
> +       u32 reg_num;
> +};
> +
> +struct value_table {
> +       unsigned int *priority;
> +};
> +
>  /**
>   * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) device
>   * @base: Memory-mapped base address of the TGU device
> @@ -20,6 +124,9 @@
>   * @csdev: Pointer to the associated coresight device
>   * @spinlock: Spinlock for handling concurrent access
>   * @enable: Flag indicating whether the TGU device is enabled
> + * @value_table: Store given value based on relevant parameters.
> + * @max_reg: Maximum number of registers
> + * @max_step: Maximum step size
>   *
>   * This structure defines the data associated with a TGU device, including its base
>   * address, device pointers, clock, spinlock for synchronization, trigger data pointers,
> @@ -31,6 +138,9 @@ struct tgu_drvdata {
>         struct coresight_device *csdev;
>         spinlock_t spinlock;
>         bool enable;
> +       struct value_table *value_table;
> +       int max_reg;
> +       int max_step;
>  };
>
>  #endif

Regards

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From horms at kernel.org  Fri Mar  7 04:21:19 2025
From: horms at kernel.org (Simon Horman)
Date: Fri, 7 Mar 2025 12:21:19 +0000
Subject: [PATCH net-next 1/7] net: ethtool: netlink: Allow per-netdevice
 DUMP operations
In-Reply-To: <20250305141938.319282-2-maxime.chevallier@bootlin.com>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
 <20250305141938.319282-2-maxime.chevallier@bootlin.com>
Message-ID: <20250307122119.GE3666230@kernel.org>

On Wed, Mar 05, 2025 at 03:19:31PM +0100, Maxime Chevallier wrote:
> We have a number of netlink commands in the ethnl family that may have
> multiple objects to dump even for a single net_device, including :
> 
>  - PLCA, PSE-PD, phy: one message per PHY device
>  - tsinfo: one message per timestamp source (netdev + phys)
>  - rss: One per RSS context
> 
> To get this behaviour, these netlink commands need to roll a custom
> ->dumpit().
> 
> To prepare making per-netdev DUMP more generic in ethnl, introduce a
> member in the ethnl ops to indicate if a given command may allow
> pernetdev DUMPs (also referred to as filtered DUMPs).
> 
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---
>  net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
>  net/ethtool/netlink.h |  1 +
>  2 files changed, 30 insertions(+), 16 deletions(-)
> 
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index 734849a57369..0815b28ba32f 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -578,21 +578,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
>  	int ret = 0;
>  
>  	rcu_read_lock();
> -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> -		dev_hold(dev);
> +	if (ctx->req_info->dev) {
> +		dev = ctx->req_info->dev;
>  		rcu_read_unlock();
> -
> -		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
> -
> +		/* Filtered DUMP request targeted to a single netdev. We already
> +		 * hold a ref to the netdev from ->start()
> +		 */
> +		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
> +						 genl_info_dump(cb));

Hi Maxime,

ethnl_default_dump_one_dev() is called here but it doesn't exist
until the following patch is applied, which breaks bisection.

>  		rcu_read_lock();
> -		dev_put(dev);
> -
> -		if (ret < 0 && ret != -EOPNOTSUPP) {
> -			if (likely(skb->len))
> -				ret = skb->len;
> -			break;
> +		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
> +	} else {
> +		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> +			dev_hold(dev);
> +			rcu_read_unlock();
> +
> +			ret = ethnl_default_dump_one(skb, dev, ctx,
> +						     genl_info_dump(cb));
> +
> +			rcu_read_lock();
> +			dev_put(dev);
> +
> +			if (ret < 0 && ret != -EOPNOTSUPP) {
> +				if (likely(skb->len))
> +					ret = skb->len;
> +				break;
> +			}
> +			ret = 0;
>  		}
> -		ret = 0;
>  	}
>  	rcu_read_unlock();
>  

...

> diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
> index ec6ab5443a6f..4db27182741f 100644
> --- a/net/ethtool/netlink.h
> +++ b/net/ethtool/netlink.h
> @@ -388,6 +388,7 @@ struct ethnl_request_ops {
>  	unsigned int		req_info_size;
>  	unsigned int		reply_data_size;
>  	bool			allow_nodev_do;
> +	bool			allow_pernetdev_dump;

nit: allow_pernetdev_dump should also be added to the Kernel doc for
     struct ethnl_request_ops

     Flagged by ./scripts/kernel-doc -none

     There also appear to be similar minor issues with subsequent
     patches in this series.

>  	u8			set_ntf_cmd;
>  
>  	int (*parse_request)(struct ethnl_req_info *req_info,
> -- 
> 2.48.1
> 


From geert at linux-m68k.org  Fri Mar  7 04:13:19 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 7 Mar 2025 13:13:19 +0100
Subject: [PATCH 0/2] vsprintf: remove redundant %pCn format specifier
In-Reply-To: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
Message-ID: <CAMuHMdUeThsk5tSaMnT-6BqO6XSMTTDo1Q9kRgJ_d5iC7MTdcw@mail.gmail.com>

Hi Luca,

On Fri, 7 Mar 2025 at 12:19, Luca Ceresoli <luca.ceresoli at bootlin.com> wrote:
> There are two printk format specifiers for clocks: %pC and %pCn, and they
> print exactly the same string. The reason for having two is not totally
> clear (see discussion in patch 2), but there seem to be no advantage in
> having two instead of one.
>
> Definitely having two without properly documenting they do the same creates
> misunderstandings [0].
>
> Since %pCn is used in a single place, replace it with %pC and remove %pCn
> to simplify such format specifiers implementation and avoid
> misunderstandings.
>
> [0] https://lore.kernel.org/dri-devel/71c44221-b18b-4928-8faf-00893ec4a109 at nxp.com/

The link looks unrelated?

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From geert at linux-m68k.org  Fri Mar  7 04:13:59 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 7 Mar 2025 13:13:59 +0100
Subject: [PATCH 1/2] thermal: bcm2835: use %pC instead of %pCn
In-Reply-To: <20250307-vsprintf-pcn-v1-1-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com> <20250307-vsprintf-pcn-v1-1-df0b2ccf610f@bootlin.com>
Message-ID: <CAMuHMdVzQfGUr-wyHW3z=KN65OFpXWgfqBru9e_z8MKtk3pmfA@mail.gmail.com>

On Fri, 7 Mar 2025 at 12:19, Luca Ceresoli <luca.ceresoli at bootlin.com> wrote:
> The %pC and %pCn printk format specifiers produce the exact same string. In
> preparation for removing %pCn, use %pC.
>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From cki-project at redhat.com  Fri Mar  7 04:22:07 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 12:22:07 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <08392.125030707221400751@us-mta-412.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704775335

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704775335-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From cassel at kernel.org  Fri Mar  7 04:29:50 2025
From: cassel at kernel.org (Niklas Cassel)
Date: Fri, 7 Mar 2025 13:29:50 +0100
Subject: [PATCH 2/2] PCI: dw-rockchip: hide broken ATS capability
In-Reply-To: <20250222160837.mropn3laiyv3acaa@thinkpad>
References: <20250221202646.395252-3-cassel@kernel.org>
 <20250221202646.395252-4-cassel@kernel.org>
 <20250222160837.mropn3laiyv3acaa@thinkpad>
Message-ID: <Z8rmviTHs92699jQ@ryzen>

Hello Mani,

On Sat, Feb 22, 2025 at 09:38:37PM +0530, Manivannan Sadhasivam wrote:
> On Fri, Feb 21, 2025 at 09:26:48PM +0100, Niklas Cassel wrote:
> > When running the rk3588 in endpoint mode, with an Intel host with IOMMU
> > enabled, the host side prints:
> > DMAR: VT-d detected Invalidation Time-out Error: SID 0
> > 
> > When running the rk3588 in endpoint mode, with an AMD host with IOMMU
> > enabled, the host side prints:
> > iommu ivhd0: AMD-Vi: Event logged [IOTLB_INV_TIMEOUT device=63:00.0 address=0x42b5b01a0]
> > 
> > Usually, to handle these issues, we add a quirk for the PCI vendor and
> > device ID in drivers/pci/quirks.c with quirk_no_ats(). That is because
> > we cannot usually modify the capabilities on the EP side.
> > 
> > In this case, we can modify the capabilties on the EP side. Thus, hide the
> > broken ATS capability on rk3588 when running in EP mode. That way,
> > we don't need any quirk on the host side, and we see no errors on the host
> > side, and we can run pci_endpoint_test successfully, with the IOMMU
> > enabled on the host side.
> > 
> > Signed-off-by: Niklas Cassel <cassel at kernel.org>
> > ---
> >  drivers/pci/controller/dwc/pcie-dw-rockchip.c | 46 +++++++++++++++++++
> >  1 file changed, 46 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > index 836ea10eafbb..2be005c1a161 100644
> > --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > @@ -242,6 +242,51 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
> >  	.init = rockchip_pcie_host_init,
> >  };
> >  
> > +/*
> > + * ATS does not work on rk3588 when running in EP mode.
> > + * After a host has enabled ATS on the EP side, it will send an IOTLB
> > + * invalidation request to the EP side. The rk3588 will never send a completion
> > + * back and eventually the host will print an IOTLB_INV_TIMEOUT error, and the
> > + * EP will not be operational. If we hide the ATS cap, things work as expected.
> > + */
> > +static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)
> > +{
> > +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > +	struct device *dev = pci->dev;
> > +	unsigned int spcie_cap_offset, next_cap_offset;
> > +	u32 spcie_cap_header, next_cap_header;
> > +
> > +	/* only hide the ATS cap for rk3588 running in EP mode */
> > +	if (!of_device_is_compatible(dev->of_node, "rockchip,rk3588-pcie-ep"))
> > +		return;
> 
> Compatible checks always tend to extend. So please use a boolean flag to
> identify the quirk in 'struct rockchip_pcie_of_data' and set it in
> 'rockchip_pcie_ep_of_data_rk3588'. This way, other SoCs could also reuse the
> flag if required.

I agree that in many cases, compatible checks tend to extend.

However, the ATS capability is broken only for rk3588, thus we need to provide
the ATS cap_id and the cap_id for the CAP immediately preceding the ATS cap_id.

The linked list of capabilities will be different for every SoC.
If we look at the only other SoC supported by this EPC, rk3568, it does not
even have the ATS cap in the linked list.

Thus, I think that creating a boolean flag for this is wrong.
Even in the unlikely scenario that there will come a Rockchip SoC in the
future with an identical linked list of capabilities, I think that what you
are proposing this is premature optimization (AKA the root of all evil :P)


> 
> > +
> > +	spcie_cap_offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI);
> > +	if (!spcie_cap_offset)
> > +		return;
> > +
> > +	spcie_cap_header = dw_pcie_readl_dbi(pci, spcie_cap_offset);
> > +	next_cap_offset = PCI_EXT_CAP_NEXT(spcie_cap_header);
> > +
> > +	next_cap_header = dw_pcie_readl_dbi(pci, next_cap_offset);
> > +	if (PCI_EXT_CAP_ID(next_cap_header) != PCI_EXT_CAP_ID_ATS)
> > +		return;
> > +
> > +	/* clear next ptr */
> > +	spcie_cap_header &= ~GENMASK(31, 20);
> > +
> > +	/* set next ptr to next ptr of ATS_CAP */
> > +	spcie_cap_header |= next_cap_header & GENMASK(31, 20);
> > +
> > +	dw_pcie_dbi_ro_wr_en(pci);
> > +	dw_pcie_writel_dbi(pci, spcie_cap_offset, spcie_cap_header);
> > +	dw_pcie_dbi_ro_wr_dis(pci);
> 
> This code is mostly generic. So please move it to pcie-designware-ep.c. The
> function should just accept two CAP IDs (prev and target) and hide the target
> capability. Like,
> 
> 	dw_pcie_hide_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI,
> 				    PCI_EXT_CAP_ID_ATS);

Sure, I will create a generic function in pcie-designware-ep.c.


> 
> Its too bad that we cannot traverse back from the target capability. We could
> open code dw_pcie_ep_find_ext_capability() to keep track of the prev_cap_offset
> though.

I'd rather skip this. Seems like too many special cases.
E.g. what should dw_pcie_ep_find_ext_capability() return if there is no prev?
It seems easier to just need to provide prev_cap_id as well.


Kind regards,
Niklas


From luca.ceresoli at bootlin.com  Fri Mar  7 04:30:03 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 7 Mar 2025 13:30:03 +0100
Subject: [PATCH 0/2] vsprintf: remove redundant %pCn format specifier
In-Reply-To: <CAMuHMdUeThsk5tSaMnT-6BqO6XSMTTDo1Q9kRgJ_d5iC7MTdcw@mail.gmail.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
	<CAMuHMdUeThsk5tSaMnT-6BqO6XSMTTDo1Q9kRgJ_d5iC7MTdcw@mail.gmail.com>
Message-ID: <20250307133003.09f1328f@booty>

On Fri, 7 Mar 2025 13:13:19 +0100
Geert Uytterhoeven <geert at linux-m68k.org> wrote:

> Hi Luca,
> 
> On Fri, 7 Mar 2025 at 12:19, Luca Ceresoli <luca.ceresoli at bootlin.com> wrote:
> > There are two printk format specifiers for clocks: %pC and %pCn, and they
> > print exactly the same string. The reason for having two is not totally
> > clear (see discussion in patch 2), but there seem to be no advantage in
> > having two instead of one.
> >
> > Definitely having two without properly documenting they do the same creates
> > misunderstandings [0].
> >
> > Since %pCn is used in a single place, replace it with %pC and remove %pCn
> > to simplify such format specifiers implementation and avoid
> > misunderstandings.
> >
> > [0] https://lore.kernel.org/dri-devel/71c44221-b18b-4928-8faf-00893ec4a109 at nxp.com/  
> 
> The link looks unrelated?

Wrong link, sorry. The correct one
is: https://lore.kernel.org/dri-devel/f8df2b5e-b005-4ada-8108-159b2b94a72e at nxp.com/

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From cki-project at redhat.com  Fri Mar  7 04:32:08 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 12:32:08 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <77654.125030707321001012@us-mta-483.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1704786487

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1704786487-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From cassel at kernel.org  Fri Mar  7 04:47:33 2025
From: cassel at kernel.org (Niklas Cassel)
Date: Fri,  7 Mar 2025 13:47:33 +0100
Subject: [PATCH v2 0/2] PCI: dw-rockchip: hide broken ATS cap in EP-mode
Message-ID: <20250307124732.704375-4-cassel@kernel.org>

Hello there,

Address Translation Services (ATS) is broken on rk3588 when running the
PCIe controller in Endpoint Mode.

This causes IOTLB invalidation timeout errors on the host side when using
and rk3588 in Endpoint Mode, and you are unable to run pci_endpoint_test.

Solve this by hiding the ATS capability.
With this, we do not get any IOTLB invalidation timeouts, and we can run
pci_endpoint_test successfully.


Changes since v1:
-Created a generic function to hide an extended capability.
-Picked up tags.
-Improved commit message.


Niklas Cassel (2):
  PCI: dwc: ep: Add dw_pcie_ep_hide_ext_capability()
  PCI: dw-rockchip: Hide broken ATS capability

 .../pci/controller/dwc/pcie-designware-ep.c   | 38 +++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h  |  7 ++++
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++
 3 files changed, 72 insertions(+)

-- 
2.48.1



From cassel at kernel.org  Fri Mar  7 04:47:35 2025
From: cassel at kernel.org (Niklas Cassel)
Date: Fri,  7 Mar 2025 13:47:35 +0100
Subject: [PATCH v2 2/2] PCI: dw-rockchip: Hide broken ATS capability
In-Reply-To: <20250307124732.704375-4-cassel@kernel.org>
References: <20250307124732.704375-4-cassel@kernel.org>
Message-ID: <20250307124732.704375-6-cassel@kernel.org>

When running the rk3588 in endpoint mode, with an Intel host with IOMMU
enabled, the host side prints:

  DMAR: VT-d detected Invalidation Time-out Error: SID 0

When running the rk3588 in endpoint mode, with an AMD host with IOMMU
enabled, the host side prints:

  iommu ivhd0: AMD-Vi: Event logged [IOTLB_INV_TIMEOUT device=63:00.0 address=0x42b5b01a0]

Rockchip has confirmed that the ATS support for rk3588 only works when
running the PCIe controller in RC mode [0].

Usually, to handle these issues, we add a quirk for the PCI vendor and
device ID in drivers/pci/quirks.c with quirk_no_ats(). That is because
we cannot usually modify the capabilities on the EP side.

In this case, we can modify the capabilities on the EP side. Thus, hide the
broken ATS capability on rk3588 when running in EP mode. That way,
we don't need any quirk on the host side, and we see no errors on the host
side, and we can run pci_endpoint_test successfully, with the IOMMU
enabled on the host side.

[0] https://lore.kernel.org/linux-pci/93cdce39-1ae6-4939-a3fc-db10be7564e5 at rock-chips.com/

Acked-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Niklas Cassel <cassel at kernel.org>
---
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 836ea10eafbb..bc4339252a03 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -242,6 +242,32 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
 	.init = rockchip_pcie_host_init,
 };
 
+/*
+ * ATS does not work on rk3588 when running in EP mode.
+ * After a host has enabled ATS on the EP side, it will send an IOTLB
+ * invalidation request to the EP side. The rk3588 will never send a completion
+ * back and eventually the host will print an IOTLB_INV_TIMEOUT error, and the
+ * EP will not be operational. If we hide the ATS cap, things work as expected.
+ */
+static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	struct device *dev = pci->dev;
+
+	/* Only hide the ATS cap for rk3588 running in EP mode */
+	if (!of_device_is_compatible(dev->of_node, "rockchip,rk3588-pcie-ep"))
+		return;
+
+	if (dw_pcie_ep_hide_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI,
+					   PCI_EXT_CAP_ID_ATS))
+		dev_err(dev, "failed to hide ATS cap\n");
+}
+
+static void rockchip_pcie_ep_pre_init(struct dw_pcie_ep *ep)
+{
+	rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
+}
+
 static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@ -314,6 +340,7 @@ rockchip_pcie_get_features(struct dw_pcie_ep *ep)
 
 static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = {
 	.init = rockchip_pcie_ep_init,
+	.pre_init = rockchip_pcie_ep_pre_init,
 	.raise_irq = rockchip_pcie_raise_irq,
 	.get_features = rockchip_pcie_get_features,
 };
-- 
2.48.1



From darren.ye at mediatek.com  Fri Mar  7 04:47:26 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:26 +0800
Subject: [PATCH 00/14] ASoC: mediatek: Add support for MT8196 SoC
Message-ID: <20250307124841.23777-1-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

This series of patches adds support for Mediatek AFE of MT8196 SoC.
Patches are based on broonie tree "for-next" branch.

---
This series patches dependent on:
[1]
https://lore.kernel.org/all/20250307032942.10447-1-guangjie.song at mediatek.com/

Darren Ye (14):
  ASoC: mediatek: common: modify mtk afe common driver for mt8196
  ASoC: mediatek: common: modify mtk afe platform driver for mt8196
  ASoC: mediatek: mt8196: add common header
  ASoC: mediatek: mt8196: add common interface for mt8196 DAI driver
  ASoC: mediatek: mt8196: support audio clock control
  ASoC: mediatek: mt8196: support audio GPIO control
  ASoC: mediatek: mt8196: support ADDA in platform driver
  ASoC: mediatek: mt8196: support I2S in platform driver
  ASoC: mediatek: mt8196: support TDM in platform driver
  ASoC: mediatek: mt8196: support CM in platform driver
  ASoC: mediatek: mt8196: add platform driver
  dt-bindings: mediatek: mt8196: add audio AFE document
  ASoC: mediatek: mt8196: add machine driver with mt6681
  dt-bindings: mediatek: mt8196: add mt8196-mt6681 document

 .../bindings/sound/mediatek,mt8196-afe.yaml   |   259 +
 .../sound/mediatek,mt8196-mt6681.yaml         |   122 +
 sound/soc/mediatek/Kconfig                    |    30 +
 sound/soc/mediatek/Makefile                   |     1 +
 sound/soc/mediatek/common/mtk-afe-fe-dai.c    |    30 +-
 sound/soc/mediatek/common/mtk-afe-fe-dai.h    |     6 +
 .../mediatek/common/mtk-afe-platform-driver.c |    63 +-
 .../mediatek/common/mtk-afe-platform-driver.h |     5 +
 sound/soc/mediatek/common/mtk-base-afe.h      |    13 +
 sound/soc/mediatek/mt8196/Makefile            |    19 +
 sound/soc/mediatek/mt8196/mt8196-afe-clk.c    |   698 +
 sound/soc/mediatek/mt8196/mt8196-afe-clk.h    |   313 +
 sound/soc/mediatek/mt8196/mt8196-afe-cm.c     |    94 +
 sound/soc/mediatek/mt8196/mt8196-afe-cm.h     |    23 +
 sound/soc/mediatek/mt8196/mt8196-afe-common.h |   290 +
 .../soc/mediatek/mt8196/mt8196-afe-control.c  |   109 +
 sound/soc/mediatek/mt8196/mt8196-afe-gpio.c   |   239 +
 sound/soc/mediatek/mt8196/mt8196-afe-gpio.h   |    58 +
 sound/soc/mediatek/mt8196/mt8196-afe-pcm.c    |  5134 +++++++
 sound/soc/mediatek/mt8196/mt8196-dai-adda.c   |  2207 +++
 sound/soc/mediatek/mt8196/mt8196-dai-i2s.c    |  4399 ++++++
 sound/soc/mediatek/mt8196/mt8196-dai-tdm.c    |   837 ++
 .../mediatek/mt8196/mt8196-interconnection.h  |   121 +
 sound/soc/mediatek/mt8196/mt8196-mt6681.c     |   879 ++
 sound/soc/mediatek/mt8196/mt8196-reg.h        | 12133 ++++++++++++++++
 25 files changed, 28055 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
 create mode 100644 sound/soc/mediatek/mt8196/Makefile
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.h
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-cm.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-cm.h
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-control.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-gpio.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-gpio.h
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-dai-adda.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-dai-i2s.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-dai-tdm.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-interconnection.h
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-mt6681.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-reg.h

-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:30 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:30 +0800
Subject: [PATCH 04/14] ASoC: mediatek: mt8196: add common interface for mt8196 DAI driver
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-5-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Implement sample rate conversion and set private data for mt8196.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 .../soc/mediatek/mt8196/mt8196-afe-control.c  | 109 ++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-control.c

diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-control.c b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
new file mode 100644
index 000000000000..bb85f4ad8585
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  MediaTek ALSA SoC Audio Control
+ *
+ *  Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include "mt8196-afe-common.h"
+#include <linux/pm_runtime.h>
+
+unsigned int mt8196_general_rate_transform(struct device *dev,
+					   unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_IPM2P0_RATE_8K;
+	case 11025:
+		return MTK_AFE_IPM2P0_RATE_11K;
+	case 12000:
+		return MTK_AFE_IPM2P0_RATE_12K;
+	case 16000:
+		return MTK_AFE_IPM2P0_RATE_16K;
+	case 22050:
+		return MTK_AFE_IPM2P0_RATE_22K;
+	case 24000:
+		return MTK_AFE_IPM2P0_RATE_24K;
+	case 32000:
+		return MTK_AFE_IPM2P0_RATE_32K;
+	case 44100:
+		return MTK_AFE_IPM2P0_RATE_44K;
+	case 48000:
+		return MTK_AFE_IPM2P0_RATE_48K;
+	case 88200:
+		return MTK_AFE_IPM2P0_RATE_88K;
+	case 96000:
+		return MTK_AFE_IPM2P0_RATE_96K;
+	case 176400:
+		return MTK_AFE_IPM2P0_RATE_176K;
+	case 192000:
+		return MTK_AFE_IPM2P0_RATE_192K;
+	/* not support 260K */
+	case 352800:
+		return MTK_AFE_IPM2P0_RATE_352K;
+	case 384000:
+		return MTK_AFE_IPM2P0_RATE_384K;
+	default:
+		dev_info(dev, "%s(), rate %u invalid, use %d!!!\n",
+			 __func__,
+			 rate, MTK_AFE_IPM2P0_RATE_48K);
+		return MTK_AFE_IPM2P0_RATE_48K;
+	}
+}
+
+static unsigned int pcm_rate_transform(struct device *dev,
+				       unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_PCM_RATE_8K;
+	case 16000:
+		return MTK_AFE_PCM_RATE_16K;
+	case 32000:
+		return MTK_AFE_PCM_RATE_32K;
+	case 48000:
+		return MTK_AFE_PCM_RATE_48K;
+	default:
+		dev_info(dev, "%s(), rate %u invalid, use %d!!!\n",
+			 __func__,
+			 rate, MTK_AFE_PCM_RATE_32K);
+		return MTK_AFE_PCM_RATE_32K;
+	}
+}
+
+unsigned int mt8196_rate_transform(struct device *dev,
+				   unsigned int rate, int aud_blk)
+{
+	switch (aud_blk) {
+	case MT8196_DAI_PCM_0:
+	case MT8196_DAI_PCM_1:
+		return pcm_rate_transform(dev, rate);
+	default:
+		return mt8196_general_rate_transform(dev, rate);
+	}
+}
+
+int mt8196_dai_set_priv(struct mtk_base_afe *afe, int id,
+			int priv_size, const void *priv_data)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	void *temp_data;
+
+	temp_data = devm_kzalloc(afe->dev,
+				 priv_size,
+				 GFP_KERNEL);
+	if (!temp_data)
+		return -ENOMEM;
+
+	if (priv_data)
+		memcpy(temp_data, priv_data, priv_size);
+
+	if (id >= MT8196_DAI_NUM || id < 0)
+		return -EINVAL;
+
+	afe_priv->dai_priv[id] = temp_data;
+
+	return 0;
+}
+
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:32 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:32 +0800
Subject: [PATCH 06/14] ASoC: mediatek: mt8196: support audio GPIO control
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-7-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Implement mode switching for audio GPIO.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/mt8196/mt8196-afe-gpio.c | 239 ++++++++++++++++++++
 sound/soc/mediatek/mt8196/mt8196-afe-gpio.h |  58 +++++
 2 files changed, 297 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-gpio.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-gpio.h

diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-gpio.c b/sound/soc/mediatek/mt8196/mt8196-afe-gpio.c
new file mode 100644
index 000000000000..17ba409af7c4
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-gpio.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  mt8196-afe-gpio.c  --  Mediatek 8196 afe gpio ctrl
+ *
+ *  Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "mt8196-afe-common.h"
+#include "mt8196-afe-gpio.h"
+
+struct pinctrl *aud_pinctrl;
+struct audio_gpio_attr {
+	const char *name;
+	bool gpio_prepare;
+	struct pinctrl_state *gpioctrl;
+};
+
+static struct audio_gpio_attr aud_gpios[MT8196_AFE_GPIO_GPIO_NUM] = {
+	[MT8196_AFE_GPIO_DAT_MISO0_OFF] = {"aud-dat-miso0-off", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MISO0_ON] = {"aud-dat-miso0-on", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MISO1_OFF] = {"aud-dat-miso1-off", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MISO1_ON] = {"aud-dat-miso1-on", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MOSI_OFF] = {"aud-dat-mosi-off", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MOSI_ON] = {"aud-dat-mosi-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT0_OFF] = {"aud-gpio-i2sout0-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT0_ON] = {"aud-gpio-i2sout0-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN0_OFF] = {"aud-gpio-i2sin0-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN0_ON] = {"aud-gpio-i2sin0-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT1_OFF] = {"aud-gpio-i2sout1-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT1_ON] = {"aud-gpio-i2sout1-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN1_OFF] = {"aud-gpio-i2sin1-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN1_ON] = {"aud-gpio-i2sin1-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT4_OFF] = {"aud-gpio-i2sout4-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT4_ON] = {"aud-gpio-i2sout4-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN4_OFF] = {"aud-gpio-i2sin4-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN4_ON] = {"aud-gpio-i2sin4-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT6_OFF] = {"aud-gpio-i2sout6-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT6_ON] = {"aud-gpio-i2sout6-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN6_OFF] = {"aud-gpio-i2sin6-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN6_ON] = {"aud-gpio-i2sin6-on", false, NULL},
+	[MT8196_AFE_GPIO_AP_DMIC_OFF] = {"aud-gpio-ap-dmic-off", false, NULL},
+	[MT8196_AFE_GPIO_AP_DMIC_ON] = {"aud-gpio-ap-dmic-on", false, NULL},
+	[MT8196_AFE_GPIO_AP_DMIC1_OFF] = {"aud-gpio-ap-dmic1-off", false, NULL},
+	[MT8196_AFE_GPIO_AP_DMIC1_ON] = {"aud-gpio-ap-dmic1-on", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MOSI_CH34_OFF] = {"aud-dat-mosi-ch34-off", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MOSI_CH34_ON] = {"aud-dat-mosi-ch34-on", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MISO_ONLY_OFF] = {"aud-dat-miso-only-off", false, NULL},
+	[MT8196_AFE_GPIO_DAT_MISO_ONLY_ON] = {"aud-dat-miso-only-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT3_OFF] = {"aud-gpio-i2sout3-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SOUT3_ON] = {"aud-gpio-i2sout3-on", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN3_OFF] = {"aud-gpio-i2sin3-off", false, NULL},
+	[MT8196_AFE_GPIO_I2SIN3_ON] = {"aud-gpio-i2sin3-on", false, NULL},
+};
+
+static DEFINE_MUTEX(gpio_request_mutex);
+
+int mt8196_afe_gpio_init(struct mtk_base_afe *afe)
+{
+	int ret;
+	int i = 0;
+
+	aud_pinctrl = devm_pinctrl_get(afe->dev);
+	if (IS_ERR(aud_pinctrl)) {
+		ret = PTR_ERR(aud_pinctrl);
+		dev_info(afe->dev, "%s(), ret %d, cannot get aud_pinctrl!\n",
+			 __func__, ret);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < MT8196_AFE_GPIO_GPIO_NUM; i++) {
+		if (!aud_gpios[i].name) {
+			dev_info(afe->dev, "%s(), gpio id %d not define!!!\n",
+				 __func__, i);
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
+		aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl,
+							     aud_gpios[i].name);
+		if (IS_ERR(aud_gpios[i].gpioctrl)) {
+			ret = PTR_ERR(aud_gpios[i].gpioctrl);
+			dev_info(afe->dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n",
+				 __func__, aud_gpios[i].name, ret);
+		} else {
+			aud_gpios[i].gpio_prepare = true;
+		}
+	}
+
+	/* gpio status init */
+	mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA, 0);
+	mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA, 1);
+
+	return 0;
+}
+
+static int mt8196_afe_gpio_select(struct mtk_base_afe *afe,
+				  enum mt8196_afe_gpio type)
+{
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s(), type: %d.\n", __func__, type);
+
+	if (type >= MT8196_AFE_GPIO_GPIO_NUM) {
+		dev_info(afe->dev, "%s(), error, invalid gpio type %d\n",
+			 __func__, type);
+		return -EINVAL;
+	}
+
+	if (!aud_gpios[type].gpio_prepare) {
+		dev_info(afe->dev, "%s(), error, gpio type %d not prepared\n",
+			 __func__, type);
+		return -EIO;
+	}
+
+	ret = pinctrl_select_state(aud_pinctrl,
+				   aud_gpios[type].gpioctrl);
+	if (ret)
+		dev_info(afe->dev, "%s(), error, can not set gpio type %d\n",
+			 __func__, type);
+
+	return ret;
+}
+
+int mt8196_afe_gpio_request(struct mtk_base_afe *afe, bool enable,
+			    int dai, int uplink)
+{
+	dev_dbg(afe->dev, "%s(), enable: %d, dai: %d, uplink: %d.\n", __func__,
+		enable, dai, uplink);
+
+	mutex_lock(&gpio_request_mutex);
+	switch (dai) {
+	case MT8196_DAI_ADDA:
+		break;
+	case MT8196_DAI_ADDA_CH34:
+		break;
+	case MT8196_DAI_ADDA_CH56:
+		break;
+	case MT8196_DAI_I2S_IN0:
+	case MT8196_DAI_I2S_OUT0:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN0_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT0_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN0_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT0_OFF);
+		}
+		break;
+	case MT8196_DAI_I2S_IN1:
+	case MT8196_DAI_I2S_OUT1:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN1_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT1_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN1_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT1_OFF);
+		}
+		break;
+	case MT8196_DAI_I2S_IN3:
+	case MT8196_DAI_I2S_OUT3:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN3_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT3_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN3_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT3_OFF);
+		}
+		break;
+	case MT8196_DAI_I2S_IN4:
+	case MT8196_DAI_I2S_OUT4:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN4_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT4_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN4_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT4_OFF);
+		}
+		break;
+	case MT8196_DAI_I2S_IN6:
+	case MT8196_DAI_I2S_OUT6:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN6_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT6_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SIN6_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_I2SOUT6_OFF);
+		}
+		break;
+	case MT8196_DAI_VOW:
+		break;
+	case MT8196_DAI_VOW_SCP_DMIC:
+		break;
+	case MT8196_DAI_MTKAIF:
+		if (enable) {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO1_ON);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO0_ON);
+		} else {
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO1_OFF);
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO0_OFF);
+		}
+		break;
+	case MT8196_DAI_MISO_ONLY:
+		if (enable)
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO_ONLY_ON);
+		else
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_DAT_MISO_ONLY_OFF);
+		break;
+	case MT8196_DAI_AP_DMIC:
+		if (enable)
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_AP_DMIC_ON);
+		else
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_AP_DMIC_OFF);
+		break;
+	case MT8196_DAI_AP_DMIC_CH34:
+		if (enable)
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_AP_DMIC1_ON);
+		else
+			mt8196_afe_gpio_select(afe, MT8196_AFE_GPIO_AP_DMIC1_OFF);
+		break;
+	default:
+		mutex_unlock(&gpio_request_mutex);
+		dev_info(afe->dev, "%s(), invalid dai %d\n", __func__, dai);
+		return -EINVAL;
+	}
+	mutex_unlock(&gpio_request_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mt8196_afe_gpio_request);
+
+bool mt8196_afe_gpio_is_prepared(enum mt8196_afe_gpio type)
+{
+	return aud_gpios[type].gpio_prepare;
+}
+EXPORT_SYMBOL(mt8196_afe_gpio_is_prepared);
+
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-gpio.h b/sound/soc/mediatek/mt8196/mt8196-afe-gpio.h
new file mode 100644
index 000000000000..b36a8201d649
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-gpio.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8196-afe-gpio.h  --  Mediatek 8196 afe gpio ctrl definition
+ *
+ *  Copyright (c) 2023 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#ifndef _MT8196_AFE_GPIO_H_
+#define _MT8196_AFE_GPIO_H_
+#include "mt8196-afe-common.h"
+
+enum mt8196_afe_gpio {
+	MT8196_AFE_GPIO_DAT_MISO0_OFF,
+	MT8196_AFE_GPIO_DAT_MISO0_ON,
+	MT8196_AFE_GPIO_DAT_MISO1_OFF,
+	MT8196_AFE_GPIO_DAT_MISO1_ON,
+	MT8196_AFE_GPIO_DAT_MOSI_OFF,
+	MT8196_AFE_GPIO_DAT_MOSI_ON,
+	MT8196_AFE_GPIO_DAT_MOSI_CH34_OFF,
+	MT8196_AFE_GPIO_DAT_MOSI_CH34_ON,
+	MT8196_AFE_GPIO_DAT_MISO_ONLY_OFF,
+	MT8196_AFE_GPIO_DAT_MISO_ONLY_ON,
+	MT8196_AFE_GPIO_I2SIN0_OFF,
+	MT8196_AFE_GPIO_I2SIN0_ON,
+	MT8196_AFE_GPIO_I2SOUT0_OFF,
+	MT8196_AFE_GPIO_I2SOUT0_ON,
+	MT8196_AFE_GPIO_I2SIN1_OFF,
+	MT8196_AFE_GPIO_I2SIN1_ON,
+	MT8196_AFE_GPIO_I2SOUT1_OFF,
+	MT8196_AFE_GPIO_I2SOUT1_ON,
+	MT8196_AFE_GPIO_I2SIN4_OFF,
+	MT8196_AFE_GPIO_I2SIN4_ON,
+	MT8196_AFE_GPIO_I2SOUT4_OFF,
+	MT8196_AFE_GPIO_I2SOUT4_ON,
+	MT8196_AFE_GPIO_I2SIN6_OFF,
+	MT8196_AFE_GPIO_I2SIN6_ON,
+	MT8196_AFE_GPIO_I2SOUT6_OFF,
+	MT8196_AFE_GPIO_I2SOUT6_ON,
+	MT8196_AFE_GPIO_AP_DMIC_OFF,
+	MT8196_AFE_GPIO_AP_DMIC_ON,
+	MT8196_AFE_GPIO_AP_DMIC1_OFF,
+	MT8196_AFE_GPIO_AP_DMIC1_ON,
+	MT8196_AFE_GPIO_I2SIN3_OFF,
+	MT8196_AFE_GPIO_I2SIN3_ON,
+	MT8196_AFE_GPIO_I2SOUT3_OFF,
+	MT8196_AFE_GPIO_I2SOUT3_ON,
+	MT8196_AFE_GPIO_GPIO_NUM
+};
+
+struct mtk_base_afe;
+
+int mt8196_afe_gpio_init(struct mtk_base_afe *afe);
+int mt8196_afe_gpio_request(struct mtk_base_afe *afe, bool enable,
+			    int dai, int uplink);
+bool mt8196_afe_gpio_is_prepared(enum mt8196_afe_gpio type);
+
+#endif
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:31 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:31 +0800
Subject: [PATCH 05/14] ASoC: mediatek: mt8196: support audio clock control
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-6-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add audio clock wrapper and audio tuner control.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/mt8196/mt8196-afe-clk.c | 698 +++++++++++++++++++++
 sound/soc/mediatek/mt8196/mt8196-afe-clk.h | 313 +++++++++
 2 files changed, 1011 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.h

diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.c b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
new file mode 100644
index 000000000000..d1407d7bf775
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
@@ -0,0 +1,698 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  mt8196-afe-clk.c  --  Mediatek 8196 afe clock ctrl
+ *
+ *  Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include "mt8196-afe-common.h"
+#include "mt8196-afe-clk.h"
+
+static DEFINE_MUTEX(mutex_request_dram);
+
+static const char *aud_clks[CLK_NUM] = {
+	[CLK_HOPPING] = "aud_hopping_clk",
+	[CLK_F26M] = "aud_f26m_clk",
+	[CLK_UL0_ADC_CLK] = "aud_ul0_adc_clk",
+	[CLK_UL0_ADC_HIRES_CLK] = "aud_ul0_adc_hires_clk",
+	[CLK_UL1_ADC_CLK] = "aud_ul1_adc_clk",
+	[CLK_UL1_ADC_HIRES_CLK] = "aud_ul1_adc_hires_clk",
+	[CLK_APLL1] = "aud_apll1_clk",
+	[CLK_APLL2] = "aud_apll2_clk",
+	[CLK_APLL1_TUNER] = "aud_apll_tuner1_clk",
+	[CLK_APLL2_TUNER] = "aud_apll_tuner2_clk",
+	[CLK_VLP_MUX_AUDIOINTBUS] = "vlp_mux_audio_int",
+	[CLK_VLP_MUX_AUD_ENG1] = "vlp_mux_aud_eng1",
+	[CLK_VLP_MUX_AUD_ENG2] = "vlp_mux_aud_eng2",
+	[CLK_VLP_MUX_AUDIO_H] = "vlp_mux_audio_h",
+	[CLK_VLP_CLK26M] = "vlp_clk26m_clk",
+	[CLK_CK_MAINPLL_D4_D4] = "ck_mainpll_d4_d4",
+	[CLK_CK_MUX_AUD_1] = "ck_mux_aud_1",
+	[CLK_CK_APLL1_CK] = "ck_apll1_ck",
+	[CLK_CK_MUX_AUD_2] = "ck_mux_aud_2",
+	[CLK_CK_APLL2_CK] = "ck_apll2_ck",
+	[CLK_CK_APLL1_D4] = "ck_apll1_d4",
+	[CLK_CK_APLL2_D4] = "ck_apll2_d4",
+	[CLK_CK_I2SIN0_M_SEL] = "ck_i2sin0_m_sel",
+	[CLK_CK_I2SIN1_M_SEL] = "ck_i2sin1_m_sel",
+	[CLK_CK_FMI2S_M_SEL] = "ck_fmi2s_m_sel",
+	[CLK_CK_TDMOUT_M_SEL] = "ck_tdmout_m_sel",
+	[CLK_CK_APLL12_DIV_I2SIN0] = "ck_apll12_div_i2sin0",
+	[CLK_CK_APLL12_DIV_I2SIN1] = "ck_apll12_div_i2sin1",
+	[CLK_CK_APLL12_DIV_FMI2S] = "ck_apll12_div_fmi2s",
+	[CLK_CK_APLL12_DIV_TDMOUT_M] = "ck_apll12_div_tdmout_m",
+	[CLK_CK_APLL12_DIV_TDMOUT_B] = "ck_apll12_div_tdmout_b",
+	[CLK_CK_ADSP_SEL] = "ck_adsp_sel",
+	[CLK_CLK26M] = "ck_clk26m_clk",
+};
+
+int mt8196_set_audio_int_bus_parent(struct mtk_base_afe *afe,
+				    int clk_id, bool int_bus)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct clk *clk;
+	int ret;
+
+	if (clk_id >= CLK_NUM || clk_id < 0)
+		return -EINVAL;
+
+	clk = int_bus ? afe_priv->clk[CLK_VLP_MUX_AUDIOINTBUS] :
+			afe_priv->clk[CLK_VLP_MUX_AUDIO_H];
+	ret = clk_set_parent(clk, afe_priv->clk[clk_id]);
+	if (ret)
+		dev_err(afe->dev, "%s() clk_set_parent %s fail %d, int_bus %d\n",
+			__func__, aud_clks[clk_id], ret, int_bus);
+
+	return ret;
+}
+
+static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s(), enable: %d\n", __func__, enable);
+
+	if (enable) {
+		ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_1]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_1], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_1],
+				     afe_priv->clk[CLK_CK_APLL1_CK]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_1],
+				aud_clks[CLK_CK_APLL1_CK], ret);
+			goto EXIT;
+		}
+
+		/* 180.6336 / 4 = 45.1584MHz */
+		ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUD_ENG1]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG1], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_VLP_MUX_AUD_ENG1],
+				     afe_priv->clk[CLK_CK_APLL1_D4]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG1],
+				aud_clks[CLK_CK_APLL1_D4], ret);
+			goto EXIT;
+		}
+		ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUDIO_H], ret);
+			goto EXIT;
+		}
+
+		mt8196_set_audio_int_bus_parent(afe, CLK_CK_APLL1_CK, false);
+	} else {
+		ret = clk_set_parent(afe_priv->clk[CLK_VLP_MUX_AUD_ENG1],
+				     afe_priv->clk[CLK_VLP_CLK26M]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG1],
+				aud_clks[CLK_VLP_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUD_ENG1]);
+
+		ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_1],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_1],
+				aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_1]);
+
+		mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
+		clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+	}
+
+EXIT:
+	return 0;
+}
+
+static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s(), enable: %d\n", __func__, enable);
+
+	if (enable) {
+		ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_2]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_2], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_2],
+				     afe_priv->clk[CLK_CK_APLL2_CK]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_2],
+				aud_clks[CLK_CK_APLL2_CK], ret);
+			goto EXIT;
+		}
+
+		/* 196.608 / 4 = 49.152MHz */
+		ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUD_ENG2]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG2], ret);
+			goto EXIT;
+		}
+		ret = clk_set_parent(afe_priv->clk[CLK_VLP_MUX_AUD_ENG2],
+				     afe_priv->clk[CLK_CK_APLL2_D4]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG2],
+				aud_clks[CLK_CK_APLL2_D4], ret);
+			goto EXIT;
+		}
+		ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUDIO_H], ret);
+			goto EXIT;
+		}
+
+		mt8196_set_audio_int_bus_parent(afe, CLK_CK_APLL2_CK, false);
+	} else {
+		ret = clk_set_parent(afe_priv->clk[CLK_VLP_MUX_AUD_ENG2],
+				     afe_priv->clk[CLK_VLP_CLK26M]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_VLP_MUX_AUD_ENG2],
+				aud_clks[CLK_VLP_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUD_ENG2]);
+
+		ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_2],
+				     afe_priv->clk[CLK_CLK26M]);
+		if (ret) {
+			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[CLK_CK_MUX_AUD_2],
+				aud_clks[CLK_CLK26M], ret);
+			goto EXIT;
+		}
+		clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_2]);
+
+		mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
+		clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+	}
+EXIT:
+	return 0;
+}
+
+int mt8196_afe_disable_apll(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s() successfully start\n", __func__);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_VLP_MUX_AUDIO_H], ret);
+		goto EXIT;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_1]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_CK_MUX_AUD_1], ret);
+		goto EXIT;
+	}
+
+	ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_1],
+			     afe_priv->clk[CLK_CLK26M]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+			__func__, aud_clks[CLK_CK_MUX_AUD_1],
+			aud_clks[CLK_CLK26M], ret);
+		goto EXIT;
+	}
+	ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_2]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_CK_MUX_AUD_2], ret);
+		goto EXIT;
+	}
+
+	ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_2],
+			     afe_priv->clk[CLK_CLK26M]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
+			__func__, aud_clks[CLK_CK_MUX_AUD_2],
+			aud_clks[CLK_CLK26M], ret);
+		goto EXIT;
+	}
+
+	clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_1]);
+	clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_2]);
+	mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
+	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+
+	return 0;
+EXIT:
+	return ret;
+}
+
+static int mt8196_afe_apll_init(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	/* VLP_APLL1_CON0 = 0x6f28bd4c
+	 * VLP_APLL2_CON2 = 0x78FD5264
+	 * VLP_APLL1_TUNER_CON0 = 0x6f28bd4d
+	 * VLP_APLL2_TUNER_CON0 = 0x78fd5265
+	 */
+	if (afe_priv->vlp_ck) {
+		regmap_write(afe_priv->vlp_ck, VLP_APLL1_TUNER_CON0, 0x6f28bd4d);
+		regmap_write(afe_priv->vlp_ck, VLP_APLL2_TUNER_CON0, 0x78fd5265);
+	} else {
+		dev_warn(afe->dev, "%s vlp_ck regmap is null ptr\n", __func__);
+	}
+	return 0;
+}
+
+int mt8196_afe_enable_clock(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret = 0;
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_CK_ADSP_SEL]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_CK_ADSP_SEL], ret);
+		goto CLK_CK_ADSP_SEL_ERR;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIOINTBUS]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_VLP_MUX_AUDIOINTBUS], ret);
+		goto CLK_MUX_AUDIO_INTBUS_ERR;
+	}
+	ret = mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, true);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_VLP_MUX_AUDIO_H], ret);
+		goto CLK_AUDIO_H_ERR;
+	}
+	mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
+
+	/* IPM2.0: USE HOPPING & 26M */
+	ret = clk_prepare_enable(afe_priv->clk[CLK_HOPPING]);
+	if (ret) {
+		dev_err(afe->dev, "%s() clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_HOPPING], ret);
+		goto CLK_AFE_ERR;
+	}
+	ret = clk_prepare_enable(afe_priv->clk[CLK_F26M]);
+	if (ret) {
+		dev_err(afe->dev, "%s() clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_F26M], ret);
+		goto CLK_AFE_ERR;
+	}
+
+	return 0;
+
+CLK_AFE_ERR:
+	/* IPM2.0: Use HOPPING & 26M */
+	clk_disable_unprepare(afe_priv->clk[CLK_HOPPING]);
+	clk_disable_unprepare(afe_priv->clk[CLK_F26M]);
+CLK_AUDIO_H_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+CLK_MUX_AUDIO_INTBUS_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIOINTBUS]);
+CLK_CK_ADSP_SEL_ERR:
+	clk_disable_unprepare(afe_priv->clk[CLK_CK_ADSP_SEL]);
+	return ret;
+}
+
+void mt8196_afe_disable_clock(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(afe->dev, "%s() successfully start\n", __func__);
+
+	/* IPM2.0: Use HOPPING & 26M */
+	clk_disable_unprepare(afe_priv->clk[CLK_HOPPING]);
+	clk_disable_unprepare(afe_priv->clk[CLK_F26M]);
+	mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
+	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
+	mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, true);
+	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIOINTBUS]);
+	clk_disable_unprepare(afe_priv->clk[CLK_CK_ADSP_SEL]);
+}
+
+int mt8196_afe_dram_request(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(dev, "%s(), dram_resource_counter %d\n",
+		__func__, afe_priv->dram_resource_counter);
+
+	mutex_lock(&mutex_request_dram);
+
+	afe_priv->dram_resource_counter++;
+	mutex_unlock(&mutex_request_dram);
+
+	return 0;
+}
+
+int mt8196_afe_dram_release(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(dev, "%s(), dram_resource_counter %d\n",
+		__func__, afe_priv->dram_resource_counter);
+
+	mutex_lock(&mutex_request_dram);
+	afe_priv->dram_resource_counter--;
+
+	if (afe_priv->dram_resource_counter < 0) {
+		dev_warn(dev, "%s(), dram_resource_counter %d\n",
+			 __func__, afe_priv->dram_resource_counter);
+		afe_priv->dram_resource_counter = 0;
+	}
+	mutex_unlock(&mutex_request_dram);
+	return 0;
+}
+
+int mt8196_apll1_enable(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* setting for APLL */
+	apll1_mux_setting(afe, true);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_APLL1], ret);
+		goto ERR_CLK_APLL1;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_APLL1_TUNER], ret);
+		goto ERR_CLK_APLL1_TUNER;
+	}
+
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+			   0x0000FFF7, 0x00000372);
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
+
+	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
+			   AUDIO_APLL1_EN_ON_MASK_SFT,
+			   0x1 << AUDIO_APLL1_EN_ON_SFT);
+	return 0;
+
+ERR_CLK_APLL1_TUNER:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
+ERR_CLK_APLL1:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1]);
+
+	return ret;
+}
+
+void mt8196_apll1_disable(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
+			   AUDIO_APLL1_EN_ON_MASK_SFT,
+			   0x0 << AUDIO_APLL1_EN_ON_SFT);
+
+	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);
+
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL1]);
+
+	apll1_mux_setting(afe, false);
+}
+
+int mt8196_apll2_enable(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	/* setting for APLL */
+	apll2_mux_setting(afe, true);
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_APLL2], ret);
+		goto ERR_CLK_APLL2;
+	}
+
+	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
+	if (ret) {
+		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[CLK_APLL2_TUNER], ret);
+		goto ERR_CLK_APLL2_TUNER;
+	}
+
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+			   0x0000FFF7, 0x00000374);
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
+
+	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
+			   AUDIO_APLL2_EN_ON_MASK_SFT,
+			   0x1 << AUDIO_APLL2_EN_ON_SFT);
+
+	return 0;
+
+ERR_CLK_APLL2_TUNER:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
+ERR_CLK_APLL2:
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2]);
+
+	return ret;
+
+	return 0;
+}
+
+void mt8196_apll2_disable(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
+			   AUDIO_APLL2_EN_ON_MASK_SFT,
+			   0x0 << AUDIO_APLL2_EN_ON_SFT);
+
+	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
+
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
+	clk_disable_unprepare(afe_priv->clk[CLK_APLL2]);
+
+	apll2_mux_setting(afe, false);
+}
+
+int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll)
+{
+	return (apll == MT8196_APLL1) ? 180633600 : 196608000;
+}
+
+int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
+{
+	return ((rate % 8000) == 0) ? MT8196_APLL2 : MT8196_APLL1;
+}
+
+int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
+{
+	if (strcmp(name, APLL1_W_NAME) == 0)
+		return MT8196_APLL1;
+	else
+		return MT8196_APLL2;
+}
+
+/* mck */
+struct mt8196_mck_div {
+	int m_sel_id;
+	int div_clk_id;
+};
+
+static const struct mt8196_mck_div mck_div[MT8196_MCK_NUM] = {
+	[MT8196_I2SIN0_MCK] = {
+		.m_sel_id = CLK_CK_I2SIN0_M_SEL,
+		.div_clk_id = CLK_CK_APLL12_DIV_I2SIN0,
+	},
+	[MT8196_I2SIN1_MCK] = {
+		.m_sel_id = CLK_CK_I2SIN1_M_SEL,
+		.div_clk_id = CLK_CK_APLL12_DIV_I2SIN1,
+	},
+	[MT8196_FMI2S_MCK] = {
+		.m_sel_id = CLK_CK_FMI2S_M_SEL,
+		.div_clk_id = CLK_CK_APLL12_DIV_FMI2S,
+	},
+	[MT8196_TDMOUT_MCK] = {
+		.m_sel_id = CLK_CK_TDMOUT_M_SEL,
+		.div_clk_id = CLK_CK_APLL12_DIV_TDMOUT_M,
+	},
+	[MT8196_TDMOUT_BCK] = {
+		.m_sel_id = -1,
+		.div_clk_id = CLK_CK_APLL12_DIV_TDMOUT_B,
+	},
+};
+
+int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int apll = mt8196_get_apll_by_rate(afe, rate);
+	int apll_clk_id = apll == MT8196_APLL1 ?
+			  CLK_CK_MUX_AUD_1 : CLK_CK_MUX_AUD_2;
+	int m_sel_id = 0;
+	int div_clk_id = 0;
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s(), mck_id: %d\n", __func__, mck_id);
+
+	if (mck_id >= MT8196_MCK_NUM || mck_id < 0)
+		return -EINVAL;
+
+	m_sel_id = mck_div[mck_id].m_sel_id;
+	div_clk_id = mck_div[mck_id].div_clk_id;
+
+	/* select apll */
+	if (m_sel_id >= 0) {
+		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
+		if (ret) {
+			dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
+				__func__, aud_clks[m_sel_id], ret);
+			return ret;
+		}
+		ret = clk_set_parent(afe_priv->clk[m_sel_id],
+				     afe_priv->clk[apll_clk_id]);
+		if (ret) {
+			dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
+				__func__, aud_clks[m_sel_id],
+				aud_clks[apll_clk_id], ret);
+			return ret;
+		}
+	}
+
+	/* enable div, set rate */
+	if (div_clk_id < 0) {
+		dev_err(afe->dev, "%s(), invalid div_clk_id %d\n", __func__, div_clk_id);
+		return -EINVAL;
+	}
+	if (div_clk_id == CLK_CK_APLL12_DIV_TDMOUT_B)
+		rate = rate * 16;
+	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
+	if (ret) {
+		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
+			__func__, aud_clks[div_clk_id], ret);
+		return ret;
+	}
+	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
+	if (ret) {
+		dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
+			__func__, aud_clks[div_clk_id],
+			rate, ret);
+		return ret;
+	}
+	return 0;
+}
+
+int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int m_sel_id = 0;
+	int div_clk_id = 0;
+
+	dev_dbg(afe->dev, "%s(), mck_id: %d.\n", __func__, mck_id);
+
+	if (mck_id < 0) {
+		dev_err(afe->dev, "%s(), mck_id = %d < 0\n",
+			__func__, mck_id);
+		return -EINVAL;
+	}
+
+	m_sel_id = mck_div[mck_id].m_sel_id;
+	div_clk_id = mck_div[mck_id].div_clk_id;
+
+	if (div_clk_id < 0) {
+		dev_err(afe->dev, "%s(), div_clk_id = %d < 0\n",
+			__func__, div_clk_id);
+		return -EINVAL;
+	}
+	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
+
+	if (m_sel_id >= 0)
+		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
+
+	return 0;
+}
+
+int mt8196_init_clock(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int i = 0;
+
+	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
+				     GFP_KERNEL);
+	if (!afe_priv->clk)
+		return -ENOMEM;
+
+	for (i = 0; i < CLK_NUM; i++) {
+		if (!aud_clks[i]) {
+			dev_err(afe->dev, "%s(), clk id %d not define!!!\n",
+				__func__, i);
+		}
+
+		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
+		if (IS_ERR(afe_priv->clk[i])) {
+			dev_err(afe->dev, "%s devm_clk_get %s fail, ret %ld\n",
+				__func__,
+				aud_clks[i], PTR_ERR(afe_priv->clk[i]));
+			afe_priv->clk[i] = NULL;
+		}
+	}
+
+	afe_priv->vlp_ck = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
+							   "vlpcksys");
+	if (IS_ERR(afe_priv->vlp_ck)) {
+		dev_err(afe->dev, "%s() Cannot find vlpcksys: %ld\n",
+			__func__, PTR_ERR(afe_priv->vlp_ck));
+		afe_priv->vlp_ck = NULL;
+	}
+
+	afe_priv->cksys_ck = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
+							     "cksys");
+	if (IS_ERR(afe_priv->cksys_ck)) {
+		dev_err(afe->dev, "%s() Cannot find cksys controller: %ld\n",
+			__func__, PTR_ERR(afe_priv->cksys_ck));
+		afe_priv->cksys_ck  = NULL;
+	}
+
+	mt8196_afe_apll_init(afe);
+	mt8196_afe_disable_apll(afe);
+
+	return 0;
+}
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.h b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
new file mode 100644
index 000000000000..0094aebc8bba
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8196-afe-clk.h  --  Mediatek 8196 afe clock ctrl definition
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#ifndef _MT8196_AFE_CLOCK_CTRL_H_
+#define _MT8196_AFE_CLOCK_CTRL_H_
+
+// vlp_cksys_clk: 0x1c016000
+#define VLP_AP_PLL_CON3 0x0264
+#define VLP_APLL1_CON0 0x0274
+#define VLP_APLL1_CON1 0x0278
+#define VLP_APLL1_CON2 0x027c
+#define VLP_APLL1_CON4 0x0284
+#define VLP_APLL1_TUNER_CON0 0x02a4
+
+#define VLP_APLL2_CON0 0x028c
+#define VLP_APLL2_CON1 0x0290
+#define VLP_APLL2_CON2 0x0294
+#define VLP_APLL2_CON4 0x029c
+#define VLP_APLL2_TUNER_CON0 0x02a8
+#define VLP_CLK_CFG_UPDATE1 0x0008
+
+// cksys_clk: 0x10000000
+#define CLK_CFG_13 0x00e0
+#define CLK_CFG_UPDATE1 0x0008
+
+#define CLK_AUDDIV_0 0x020c
+#define CLK_AUDDIV_2 0x0214
+#define CLK_AUDDIV_5 0x0228
+
+#define CKSYS_AUD_TOP_CFG 0x0218
+
+/* CLK_AUDDIV_0 */
+#define APLL12_DIV_I2SIN0_PDN_SFT               0
+#define APLL12_DIV_I2SIN0_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN0_PDN_MASK_SFT          (0x1 << 0)
+#define APLL12_DIV_I2SIN1_PDN_SFT               1
+#define APLL12_DIV_I2SIN1_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN1_PDN_MASK_SFT          (0x1 << 1)
+#define APLL12_DIV_I2SIN2_PDN_SFT               2
+#define APLL12_DIV_I2SIN2_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN2_PDN_MASK_SFT          (0x1 << 2)
+#define APLL12_DIV_I2SIN3_PDN_SFT               3
+#define APLL12_DIV_I2SIN3_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN3_PDN_MASK_SFT          (0x1 << 3)
+#define APLL12_DIV_I2SIN4_PDN_SFT               4
+#define APLL12_DIV_I2SIN4_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN4_PDN_MASK_SFT          (0x1 << 4)
+#define APLL12_DIV_I2SIN6_PDN_SFT               5
+#define APLL12_DIV_I2SIN6_PDN_MASK              0x1
+#define APLL12_DIV_I2SIN6_PDN_MASK_SFT          (0x1 << 5)
+#define APLL12_DIV_I2SOUT0_PDN_SFT              6
+#define APLL12_DIV_I2SOUT0_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT0_PDN_MASK_SFT         (0x1 << 6)
+#define APLL12_DIV_I2SOUT1_PDN_SFT              7
+#define APLL12_DIV_I2SOUT1_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT1_PDN_MASK_SFT         (0x1 << 7)
+#define APLL12_DIV_I2SOUT2_PDN_SFT              8
+#define APLL12_DIV_I2SOUT2_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT2_PDN_MASK_SFT         (0x1 << 8)
+#define APLL12_DIV_I2SOUT3_PDN_SFT              9
+#define APLL12_DIV_I2SOUT3_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT3_PDN_MASK_SFT         (0x1 << 9)
+#define APLL12_DIV_I2SOUT4_PDN_SFT              10
+#define APLL12_DIV_I2SOUT4_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT4_PDN_MASK_SFT         (0x1 << 10)
+#define APLL12_DIV_I2SOUT6_PDN_SFT              11
+#define APLL12_DIV_I2SOUT6_PDN_MASK             0x1
+#define APLL12_DIV_I2SOUT6_PDN_MASK_SFT         (0x1 << 11)
+#define APLL12_DIV_FMI2S_PDN_SFT                12
+#define APLL12_DIV_FMI2S_PDN_MASK               0x1
+#define APLL12_DIV_FMI2S_PDN_MASK_SFT           (0x1 << 12)
+#define APLL12_DIV_TDMOUT_M_PDN_SFT             13
+#define APLL12_DIV_TDMOUT_M_PDN_MASK            0x1
+#define APLL12_DIV_TDMOUT_M_PDN_MASK_SFT        (0x1 << 13)
+#define APLL12_DIV_TDMOUT_B_PDN_SFT             14
+#define APLL12_DIV_TDMOUT_B_PDN_MASK            0x1
+#define APLL12_DIV_TDMOUT_B_PDN_MASK_SFT        (0x1 << 14)
+#define APLL_I2SIN0_MCK_SEL_SFT                 16
+#define APLL_I2SIN0_MCK_SEL_MASK                0x1
+#define APLL_I2SIN0_MCK_SEL_MASK_SFT            (0x1 << 16)
+#define APLL_I2SIN1_MCK_SEL_SFT                 17
+#define APLL_I2SIN1_MCK_SEL_MASK                0x1
+#define APLL_I2SIN1_MCK_SEL_MASK_SFT            (0x1 << 17)
+#define APLL_I2SIN2_MCK_SEL_SFT                 18
+#define APLL_I2SIN2_MCK_SEL_MASK                0x1
+#define APLL_I2SIN2_MCK_SEL_MASK_SFT            (0x1 << 18)
+#define APLL_I2SIN3_MCK_SEL_SFT                 19
+#define APLL_I2SIN3_MCK_SEL_MASK                0x1
+#define APLL_I2SIN3_MCK_SEL_MASK_SFT            (0x1 << 19)
+#define APLL_I2SIN4_MCK_SEL_SFT                 20
+#define APLL_I2SIN4_MCK_SEL_MASK                0x1
+#define APLL_I2SIN4_MCK_SEL_MASK_SFT            (0x1 << 20)
+#define APLL_I2SIN6_MCK_SEL_SFT                 21
+#define APLL_I2SIN6_MCK_SEL_MASK                0x1
+#define APLL_I2SIN6_MCK_SEL_MASK_SFT            (0x1 << 21)
+#define APLL_I2SOUT0_MCK_SEL_SFT                22
+#define APLL_I2SOUT0_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT0_MCK_SEL_MASK_SFT           (0x1 << 22)
+#define APLL_I2SOUT1_MCK_SEL_SFT                23
+#define APLL_I2SOUT1_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT1_MCK_SEL_MASK_SFT           (0x1 << 23)
+#define APLL_I2SOUT2_MCK_SEL_SFT                24
+#define APLL_I2SOUT2_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT2_MCK_SEL_MASK_SFT           (0x1 << 24)
+#define APLL_I2SOUT3_MCK_SEL_SFT                25
+#define APLL_I2SOUT3_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT3_MCK_SEL_MASK_SFT           (0x1 << 25)
+#define APLL_I2SOUT4_MCK_SEL_SFT                26
+#define APLL_I2SOUT4_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT4_MCK_SEL_MASK_SFT           (0x1 << 26)
+#define APLL_I2SOUT6_MCK_SEL_SFT                27
+#define APLL_I2SOUT6_MCK_SEL_MASK               0x1
+#define APLL_I2SOUT6_MCK_SEL_MASK_SFT           (0x1 << 27)
+#define APLL_FMI2S_MCK_SEL_SFT                  28
+#define APLL_FMI2S_MCK_SEL_MASK                 0x1
+#define APLL_FMI2S_MCK_SEL_MASK_SFT             (0x1 << 28)
+#define APLL_TDMOUT_MCK_SEL_SFT                 29
+#define APLL_TDMOUT_MCK_SEL_MASK                0x1
+#define APLL_TDMOUT_MCK_SEL_MASK_SFT            (0x1 << 29)
+
+/* CLK_AUDDIV_1 */
+#define APLL12_DIV_I2SIN0_INV_SFT               0
+#define APLL12_DIV_I2SIN0_INV_MASK              0x1
+#define APLL12_DIV_I2SIN0_INV_MASK_SFT          (0x1 << 0)
+#define APLL12_DIV_I2SIN1_INV_SFT               1
+#define APLL12_DIV_I2SIN1_INV_MASK              0x1
+#define APLL12_DIV_I2SIN1_INV_MASK_SFT          (0x1 << 1)
+#define APLL12_DIV_I2SIN2_INV_SFT               2
+#define APLL12_DIV_I2SIN2_INV_MASK              0x1
+#define APLL12_DIV_I2SIN2_INV_MASK_SFT          (0x1 << 2)
+#define APLL12_DIV_I2SIN3_INV_SFT               3
+#define APLL12_DIV_I2SIN3_INV_MASK              0x1
+#define APLL12_DIV_I2SIN3_INV_MASK_SFT          (0x1 << 3)
+#define APLL12_DIV_I2SIN4_INV_SFT               4
+#define APLL12_DIV_I2SIN4_INV_MASK              0x1
+#define APLL12_DIV_I2SIN4_INV_MASK_SFT          (0x1 << 4)
+#define APLL12_DIV_I2SIN6_INV_SFT               5
+#define APLL12_DIV_I2SIN6_INV_MASK              0x1
+#define APLL12_DIV_I2SIN6_INV_MASK_SFT          (0x1 << 5)
+#define APLL12_DIV_I2SOUT0_INV_SFT              6
+#define APLL12_DIV_I2SOUT0_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT0_INV_MASK_SFT         (0x1 << 6)
+#define APLL12_DIV_I2SOUT1_INV_SFT              7
+#define APLL12_DIV_I2SOUT1_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT1_INV_MASK_SFT         (0x1 << 7)
+#define APLL12_DIV_I2SOUT2_INV_SFT              8
+#define APLL12_DIV_I2SOUT2_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT2_INV_MASK_SFT         (0x1 << 8)
+#define APLL12_DIV_I2SOUT3_INV_SFT              9
+#define APLL12_DIV_I2SOUT3_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT3_INV_MASK_SFT         (0x1 << 9)
+#define APLL12_DIV_I2SOUT4_INV_SFT              10
+#define APLL12_DIV_I2SOUT4_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT4_INV_MASK_SFT         (0x1 << 10)
+#define APLL12_DIV_I2SOUT6_INV_SFT              11
+#define APLL12_DIV_I2SOUT6_INV_MASK             0x1
+#define APLL12_DIV_I2SOUT6_INV_MASK_SFT         (0x1 << 11)
+#define APLL12_DIV_FMI2S_INV_SFT                12
+#define APLL12_DIV_FMI2S_INV_MASK               0x1
+#define APLL12_DIV_FMI2S_INV_MASK_SFT           (0x1 << 12)
+#define APLL12_DIV_TDMOUT_M_INV_SFT             13
+#define APLL12_DIV_TDMOUT_M_INV_MASK            0x1
+#define APLL12_DIV_TDMOUT_M_INV_MASK_SFT        (0x1 << 13)
+#define APLL12_DIV_TDMOUT_B_INV_SFT             14
+#define APLL12_DIV_TDMOUT_B_INV_MASK            0x1
+#define APLL12_DIV_TDMOUT_B_INV_MASK_SFT        (0x1 << 14)
+
+/* CLK_AUDDIV_2 */
+#define APLL12_CK_DIV_I2SIN0_SFT                0
+#define APLL12_CK_DIV_I2SIN0_MASK               0xff
+#define APLL12_CK_DIV_I2SIN0_MASK_SFT           (0xff << 0)
+#define APLL12_CK_DIV_I2SIN1_SFT                8
+#define APLL12_CK_DIV_I2SIN1_MASK               0xff
+#define APLL12_CK_DIV_I2SIN1_MASK_SFT           (0xff << 8)
+#define APLL12_CK_DIV_I2SIN2_SFT                16
+#define APLL12_CK_DIV_I2SIN2_MASK               0xff
+#define APLL12_CK_DIV_I2SIN2_MASK_SFT           (0xff << 16)
+#define APLL12_CK_DIV_I2SIN3_SFT                24
+#define APLL12_CK_DIV_I2SIN3_MASK               0xff
+#define APLL12_CK_DIV_I2SIN3_MASK_SFT           (0xff << 24)
+
+/* AUD_TOP_CFG */
+#define AUD_TOP_CFG_SFT                         0
+#define AUD_TOP_CFG_MASK                        0xffffffff
+#define AUD_TOP_CFG_MASK_SFT                    (0xffffffff << 0)
+
+/* AUD_TOP_MON */
+#define AUD_TOP_MON_SFT                         0
+#define AUD_TOP_MON_MASK                        0xffffffff
+#define AUD_TOP_MON_MASK_SFT                    (0xffffffff << 0)
+
+/* CLK_AUDDIV_3 */
+#define APLL12_CK_DIV_I2SIN4_SFT                0
+#define APLL12_CK_DIV_I2SIN4_MASK               0xff
+#define APLL12_CK_DIV_I2SIN4_MASK_SFT           (0xff << 0)
+#define APLL12_CK_DIV_I2SIN6_SFT                8
+#define APLL12_CK_DIV_I2SIN6_MASK               0xff
+#define APLL12_CK_DIV_I2SIN6_MASK_SFT           (0xff << 8)
+#define APLL12_CK_DIV_I2SOUT0_SFT               16
+#define APLL12_CK_DIV_I2SOUT0_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT0_MASK_SFT          (0xff << 16)
+#define APLL12_CK_DIV_I2SOUT1_SFT               24
+#define APLL12_CK_DIV_I2SOUT1_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT1_MASK_SFT          (0xff << 24)
+
+/* CLK_AUDDIV_4 */
+#define APLL12_CK_DIV_I2SOUT2_SFT               0
+#define APLL12_CK_DIV_I2SOUT2_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT2_MASK_SFT          (0xff << 0)
+#define APLL12_CK_DIV_I2SOUT3_SFT               8
+#define APLL12_CK_DIV_I2SOUT3_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT3_MASK_SFT          (0xff << 8)
+#define APLL12_CK_DIV_I2SOUT4_SFT               16
+#define APLL12_CK_DIV_I2SOUT4_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT4_MASK_SFT          (0xff << 16)
+#define APLL12_CK_DIV_I2SOUT6_SFT               24
+#define APLL12_CK_DIV_I2SOUT6_MASK              0xff
+#define APLL12_CK_DIV_I2SOUT6_MASK_SFT          (0xff << 24)
+
+/* CLK_AUDDIV_5 */
+#define APLL12_CK_DIV_FMI2S_SFT                 0
+#define APLL12_CK_DIV_FMI2S_MASK                0xff
+#define APLL12_CK_DIV_FMI2S_MASK_SFT            (0xff << 0)
+#define APLL12_CK_DIV_TDMOUT_M_SFT              8
+#define APLL12_CK_DIV_TDMOUT_M_MASK             0xff
+#define APLL12_CK_DIV_TDMOUT_M_MASK_SFT         (0xff << 8)
+#define APLL12_CK_DIV_TDMOUT_B_SFT              16
+#define APLL12_CK_DIV_TDMOUT_B_MASK             0xff
+#define APLL12_CK_DIV_TDMOUT_B_MASK_SFT         (0xff << 16)
+
+/* APLL */
+#define APLL1_W_NAME "APLL1"
+#define APLL2_W_NAME "APLL2"
+enum {
+	MT8196_APLL1 = 0,
+	MT8196_APLL2,
+};
+
+enum {
+	/* afe clk */
+	CLK_HOPPING = 0,
+	CLK_F26M,
+	CLK_UL0_ADC_CLK,
+	CLK_UL0_ADC_HIRES_CLK,
+	CLK_UL1_ADC_CLK,
+	CLK_UL1_ADC_HIRES_CLK,
+	CLK_APLL1,
+	CLK_APLL2,
+	CLK_APLL1_TUNER,
+	CLK_APLL2_TUNER,
+	/* vlp clk */
+	CLK_VLP_MUX_AUDIOINTBUS,
+	CLK_VLP_MUX_AUD_ENG1,
+	CLK_VLP_MUX_AUD_ENG2,
+	CLK_VLP_MUX_AUDIO_H,
+	CLK_VLP_CLK26M,
+	/* ck clk */
+	CLK_CK_MAINPLL_D4_D4,
+	CLK_CK_MUX_AUD_1,
+	CLK_CK_APLL1_CK,
+	CLK_CK_MUX_AUD_2,
+	CLK_CK_APLL2_CK,
+	CLK_CK_APLL1_D4,
+	CLK_CK_APLL2_D4,
+	CLK_CK_I2SIN0_M_SEL,
+	CLK_CK_I2SIN1_M_SEL,
+	CLK_CK_FMI2S_M_SEL,
+	CLK_CK_TDMOUT_M_SEL,
+	CLK_CK_APLL12_DIV_I2SIN0,
+	CLK_CK_APLL12_DIV_I2SIN1,
+	CLK_CK_APLL12_DIV_FMI2S,
+	CLK_CK_APLL12_DIV_TDMOUT_M,
+	CLK_CK_APLL12_DIV_TDMOUT_B,
+	CLK_CK_ADSP_SEL,
+	CLK_CLK26M,
+	CLK_NUM
+};
+
+struct mtk_base_afe;
+
+int mt8196_init_clock(struct mtk_base_afe *afe);
+int mt8196_afe_enable_clock(struct mtk_base_afe *afe);
+void mt8196_afe_disable_clock(struct mtk_base_afe *afe);
+int mt8196_afe_disable_apll(struct mtk_base_afe *afe);
+
+int mt8196_afe_dram_request(struct device *dev);
+int mt8196_afe_dram_release(struct device *dev);
+
+int mt8196_apll1_enable(struct mtk_base_afe *afe);
+void mt8196_apll1_disable(struct mtk_base_afe *afe);
+
+int mt8196_apll2_enable(struct mtk_base_afe *afe);
+void mt8196_apll2_disable(struct mtk_base_afe *afe);
+
+int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll);
+int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
+int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
+
+void aud_intbus_mux_sel(unsigned int aud_idx);
+
+/* these will be replaced by using CCF */
+int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
+int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id);
+
+int mt8196_set_audio_int_bus_parent(struct mtk_base_afe *afe,
+				    int clk_id, bool int_bus);
+
+#endif
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:33 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:33 +0800
Subject: [PATCH 07/14] ASoC: mediatek: mt8196: support ADDA in platform driver
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-8-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add mt8196 ADDA DAI driver support.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/mt8196/mt8196-dai-adda.c | 2207 +++++++++++++++++++
 1 file changed, 2207 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-dai-adda.c

diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-adda.c b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c
new file mode 100644
index 000000000000..2934b3ba9d71
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c
@@ -0,0 +1,2207 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  MediaTek ALSA SoC Audio DAI ADDA Control
+ *
+ *  Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-afe-gpio.h"
+#include "mt8196-interconnection.h"
+
+#define MTKAIF4 //for  mt6338
+/* mt6363 vs1 voter */
+#define RG_BUCK_VS1_VOTER_EN_LO                 0x189a
+#define RG_BUCK_VS1_VOTER_EN_LO_SET             0x189b
+#define RG_BUCK_VS1_VOTER_EN_LO_CLR             0x189c
+
+#define VS1_MT6338_MSK                    (0x1 << 0)
+
+enum {
+	UL_IIR_SW = 0,
+	UL_IIR_5HZ,
+	UL_IIR_10HZ,
+	UL_IIR_25HZ,
+	UL_IIR_50HZ,
+	UL_IIR_75HZ,
+};
+
+enum {
+	AUDIO_SDM_LEVEL_MUTE = 0,
+	AUDIO_SDM_LEVEL_NORMAL = 0x1d,
+	/* if you change level normal */
+	/* you need to change formula of hp impedance and dc trim too */
+};
+
+enum {
+	AUDIO_SDM_2ND = 0,
+	AUDIO_SDM_3RD,
+};
+
+enum {
+	DELAY_DATA_MISO1 = 0,
+	DELAY_DATA_MISO2,
+};
+
+enum {
+	MTK_AFE_ADDA_DL_RATE_8K = 0,
+	MTK_AFE_ADDA_DL_RATE_11K = 1,
+	MTK_AFE_ADDA_DL_RATE_12K = 2,
+	MTK_AFE_ADDA_DL_RATE_16K = 4,
+	MTK_AFE_ADDA_DL_RATE_22K = 5,
+	MTK_AFE_ADDA_DL_RATE_24K = 6,
+	MTK_AFE_ADDA_DL_RATE_32K = 8,
+	MTK_AFE_ADDA_DL_RATE_44K = 9,
+	MTK_AFE_ADDA_DL_RATE_48K = 10,
+	MTK_AFE_ADDA_DL_RATE_88K = 13,
+	MTK_AFE_ADDA_DL_RATE_96K = 14,
+	MTK_AFE_ADDA_DL_RATE_176K = 17,
+	MTK_AFE_ADDA_DL_RATE_192K = 18,
+	MTK_AFE_ADDA_DL_RATE_352K = 21,
+	MTK_AFE_ADDA_DL_RATE_384K = 22,
+};
+
+enum {
+	MTK_AFE_ADDA_UL_RATE_8K = 0,
+	MTK_AFE_ADDA_UL_RATE_16K = 1,
+	MTK_AFE_ADDA_UL_RATE_32K = 2,
+	MTK_AFE_ADDA_UL_RATE_48K = 3,
+	MTK_AFE_ADDA_UL_RATE_96K = 4,
+	MTK_AFE_ADDA_UL_RATE_192K = 5,
+	MTK_AFE_ADDA_UL_RATE_48K_HD = 6,
+};
+
+#ifdef MTKAIF4
+enum {
+	MTK_AFE_MTKAIF_RATE_8K = 0x0,
+	MTK_AFE_MTKAIF_RATE_12K = 0x1,
+	MTK_AFE_MTKAIF_RATE_16K = 0x2,
+	MTK_AFE_MTKAIF_RATE_24K = 0x3,
+	MTK_AFE_MTKAIF_RATE_32K = 0x4,
+	MTK_AFE_MTKAIF_RATE_48K = 0x5,
+	MTK_AFE_MTKAIF_RATE_64K = 0x6,
+	MTK_AFE_MTKAIF_RATE_96K = 0x7,
+	MTK_AFE_MTKAIF_RATE_128K = 0x8,
+	MTK_AFE_MTKAIF_RATE_192K = 0x9,
+	MTK_AFE_MTKAIF_RATE_256K = 0xa,
+	MTK_AFE_MTKAIF_RATE_384K = 0xb,
+	MTK_AFE_MTKAIF_RATE_11K = 0x10,
+	MTK_AFE_MTKAIF_RATE_22K = 0x11,
+	MTK_AFE_MTKAIF_RATE_44K = 0x12,
+	MTK_AFE_MTKAIF_RATE_88K = 0x13,
+	MTK_AFE_MTKAIF_RATE_176K = 0x14,
+	MTK_AFE_MTKAIF_RATE_352K = 0x15,
+};
+#endif
+
+#define SDM_AUTO_RESET_THRESHOLD 0x190000
+
+struct mtk_afe_adda_priv {
+	int dl_rate;
+	int ul_rate;
+};
+
+static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+						       const char *name)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int dai_id;
+
+	if (strncmp(name, "aud_dl0_dac_hires_clk", 21) == 0 ||
+	    strncmp(name, "aud_ul0_adc_hires_clk", 21) == 0)
+		dai_id = MT8196_DAI_ADDA;
+	else if (strncmp(name, "aud_dl1_dac_hires_clk", 21) == 0 ||
+		 strncmp(name, "aud_ul1_adc_hires_clk", 21) == 0)
+		dai_id = MT8196_DAI_ADDA_CH34;
+	else
+		return NULL;
+
+	return afe_priv->dai_priv[dai_id];
+}
+
+static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe,
+					   unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_ADDA_UL_RATE_8K;
+	case 16000:
+		return MTK_AFE_ADDA_UL_RATE_16K;
+	case 32000:
+		return MTK_AFE_ADDA_UL_RATE_32K;
+	case 48000:
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	case 96000:
+		return MTK_AFE_ADDA_UL_RATE_96K;
+	case 192000:
+		return MTK_AFE_ADDA_UL_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	}
+}
+
+#ifdef MTKAIF4
+static unsigned int mtkaif_rate_transform(struct mtk_base_afe *afe,
+					  unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_MTKAIF_RATE_8K;
+	case 11025:
+		return MTK_AFE_MTKAIF_RATE_11K;
+	case 12000:
+		return MTK_AFE_MTKAIF_RATE_12K;
+	case 16000:
+		return MTK_AFE_MTKAIF_RATE_16K;
+	case 22050:
+		return MTK_AFE_MTKAIF_RATE_22K;
+	case 24000:
+		return MTK_AFE_MTKAIF_RATE_24K;
+	case 32000:
+		return MTK_AFE_MTKAIF_RATE_32K;
+	case 44100:
+		return MTK_AFE_MTKAIF_RATE_44K;
+	case 48000:
+		return MTK_AFE_MTKAIF_RATE_48K;
+	case 96000:
+		return MTK_AFE_MTKAIF_RATE_96K;
+	case 192000:
+		return MTK_AFE_MTKAIF_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_MTKAIF_RATE_48K;
+	}
+}
+#endif
+
+/* dai component */
+static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN014_1, I_DL0_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN014_1, I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN014_1, I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN014_1, I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN014_1, I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN014_1, I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN014_1, I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN014_1, I_DL7_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN014_1, I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN014_1, I_DL_24CH_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH1", AFE_CONN014_2, I_DL24_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN014_0,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN014_0,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN014_0,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN014_0,
+				    I_GAIN0_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN014_4,
+				    I_PCM_0_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN014_4,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_0_OUT_CH1", AFE_CONN014_6,
+				    I_SRC_0_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH1", AFE_CONN014_6,
+				    I_SRC_1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN014_6,
+				    I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN015_1, I_DL0_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN015_1, I_DL0_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN015_1, I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN015_1, I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN015_1, I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN015_1, I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN015_1, I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN015_1, I_DL6_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN015_1, I_DL7_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN015_1, I_DL8_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN015_1, I_DL_24CH_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH2", AFE_CONN015_2, I_DL24_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN015_0,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN015_0,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN015_0,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN015_0,
+				    I_GAIN0_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN015_4,
+				    I_PCM_0_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN015_4,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN015_4,
+				    I_PCM_0_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN015_4,
+				    I_PCM_1_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_0_OUT_CH2", AFE_CONN015_6,
+				    I_SRC_0_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH2", AFE_CONN015_6,
+				    I_SRC_1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN015_6,
+				    I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch3_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN016_1, I_DL0_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN016_1, I_DL1_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN016_1, I_DL2_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN016_1, I_DL3_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN016_1, I_DL4_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN016_1, I_DL5_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN016_1, I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN016_1, I_DL7_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN016_1, I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN016_1, I_DL_24CH_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH3", AFE_CONN016_1, I_DL_24CH_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN016_0,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN016_0,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN016_0,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN016_0,
+				    I_GAIN0_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN016_4,
+				    I_PCM_0_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN016_4,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_0_OUT_CH1", AFE_CONN016_6,
+				    I_SRC_0_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH1", AFE_CONN016_6,
+				    I_SRC_1_OUT_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN016_6,
+				    I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch4_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN017_1, I_DL0_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN017_1, I_DL1_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN017_1, I_DL2_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN017_1, I_DL3_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN017_1, I_DL4_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN017_1, I_DL5_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN017_1, I_DL6_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN017_1, I_DL7_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN017_1, I_DL8_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN017_1, I_DL_24CH_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH4", AFE_CONN017_1, I_DL_24CH_CH4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN017_0,
+				    I_ADDA_UL_CH3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN017_0,
+				    I_ADDA_UL_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN017_0,
+				    I_ADDA_UL_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN017_0,
+				    I_GAIN0_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN017_4,
+				    I_PCM_0_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN017_4,
+				    I_PCM_1_CAP_CH1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN017_4,
+				    I_PCM_0_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN017_4,
+				    I_PCM_1_CAP_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_0_OUT_CH2", AFE_CONN017_6,
+				    I_SRC_0_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH2", AFE_CONN017_6,
+				    I_SRC_1_OUT_CH2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN017_6,
+				    I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_stf_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN012_0,
+				    I_ADDA_UL_CH1, 1, 0),
+};
+
+// Luke: dummy BE for codec fail
+static const char * const adda_mux_map[] = {
+	"Normal", "Dummy_Widget",
+};
+
+static int adda_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(adda_mux_map_enum,
+					      SND_SOC_NOPM,
+					      0,
+					      1,
+					      adda_mux_map,
+					      adda_mux_map_value);
+static const struct snd_kcontrol_new adda_out_mux_control =
+	SOC_DAPM_ENUM("ADDA Out Select", adda_mux_map_enum);
+static const struct snd_kcontrol_new adda_in_mux_control =
+	SOC_DAPM_ENUM("ADDA In Select", adda_mux_map_enum);
+// Luke: dummy BE for codec fail
+
+enum {
+	SUPPLY_SEQ_ADDA_AFE_ON,
+	SUPPLY_SEQ_ADDA_DL_ON,
+	SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
+	SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+	SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
+	SUPPLY_SEQ_ADDA_FIFO,
+	SUPPLY_SEQ_ADDA_AP_DMIC,
+	SUPPLY_SEQ_ADDA_UL_ON,
+};
+
+static int mtk_adda_ul_src_dmic_phase_sync(struct mtk_base_afe *afe)
+{
+	dev_dbg(afe->dev, "%s() set dmic phase sync\n", __func__);
+	// ul0~1
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   UL0_PHASE_SYNC_HCLK_SET_MASK_SFT,
+			   0x1 << UL0_PHASE_SYNC_HCLK_SET_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   UL0_PHASE_SYNC_FCLK_SET_MASK_SFT,
+			   0x1 << UL0_PHASE_SYNC_FCLK_SET_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   UL1_PHASE_SYNC_HCLK_SET_MASK_SFT,
+			   0x1 << UL1_PHASE_SYNC_HCLK_SET_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   UL1_PHASE_SYNC_FCLK_SET_MASK_SFT,
+			   0x1 << UL1_PHASE_SYNC_FCLK_SET_SFT);
+	// dmic 0
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   DMIC0_PHASE_SYNC_FCLK_SET_MASK_SFT,
+			   0x1 << DMIC0_PHASE_SYNC_FCLK_SET_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   DMIC0_PHASE_SYNC_HCLK_SET_MASK_SFT,
+			   0x1 << DMIC0_PHASE_SYNC_HCLK_SET_SFT);
+	// dmic 1
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   DMIC1_PHASE_SYNC_FCLK_SET_MASK_SFT,
+			   0x1 << DMIC1_PHASE_SYNC_FCLK_SET_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+			   DMIC1_PHASE_SYNC_HCLK_SET_MASK_SFT,
+			   0x1 << DMIC1_PHASE_SYNC_HCLK_SET_SFT);
+	// ul0~1 phase sync clock
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   DMIC1_PHASE_HCLK_SEL_MASK_SFT,
+			   0x1 << DMIC1_PHASE_HCLK_SEL_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   DMIC1_PHASE_FCLK_SEL_MASK_SFT,
+			   0x1 << DMIC1_PHASE_FCLK_SEL_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   DMIC0_PHASE_HCLK_SEL_MASK_SFT,
+			   0x1 << DMIC0_PHASE_HCLK_SEL_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   DMIC0_PHASE_FCLK_SEL_MASK_SFT,
+			   0x1 << DMIC0_PHASE_FCLK_SEL_SFT);
+	// dmic 0
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL1_PHASE_HCLK_SEL_MASK_SFT,
+			   0x2 << UL1_PHASE_HCLK_SEL_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL1_PHASE_FCLK_SEL_MASK_SFT,
+			   0x2 << UL1_PHASE_FCLK_SEL_SFT);
+	// dmic 1
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL0_PHASE_HCLK_SEL_MASK_SFT,
+			   0x2 << UL0_PHASE_HCLK_SEL_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL0_PHASE_FCLK_SEL_MASK_SFT,
+			   0x2 << UL0_PHASE_FCLK_SEL_SFT);
+
+	return 0;
+}
+
+static int mtk_adda_ul_src_dmic_phase_sync_clock(struct mtk_base_afe *afe)
+{
+	dev_dbg(afe->dev, "%s(), dmic turn on phase sync clk\n", __func__);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL_PHASE_SYNC_HCLK_1_ON_MASK_SFT,
+			   0x1 << UL_PHASE_SYNC_HCLK_1_ON_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL_PHASE_SYNC_HCLK_0_ON_MASK_SFT,
+			   0x1 << UL_PHASE_SYNC_HCLK_0_ON_SFT);
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL_PHASE_SYNC_FCLK_1_ON_MASK_SFT,
+			   0x1 << UL_PHASE_SYNC_FCLK_1_ON_SFT);
+	regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+			   UL_PHASE_SYNC_FCLK_0_ON_MASK_SFT,
+			   0x1 << UL_PHASE_SYNC_FCLK_0_ON_SFT);
+
+	return 0;
+}
+
+static int mtk_adda_ul_src_dmic(struct mtk_base_afe *afe, int id)
+{
+	unsigned int reg_con0 = 0, reg_con1 = 0;
+
+	dev_dbg(afe->dev, "%s(), id: %d\n", __func__, id);
+
+	switch (id) {
+	case MT8196_DAI_ADDA:
+	case MT8196_DAI_AP_DMIC:
+		reg_con0 = AFE_ADDA_UL0_SRC_CON0;
+		reg_con1 = AFE_ADDA_UL0_SRC_CON1;
+		break;
+	case MT8196_DAI_ADDA_CH34:
+	case MT8196_DAI_AP_DMIC_CH34:
+		reg_con0 = AFE_ADDA_UL1_SRC_CON0;
+		reg_con1 = AFE_ADDA_UL1_SRC_CON1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (id) {
+	case MT8196_DAI_AP_DMIC:
+		dev_dbg(afe->dev, "%s(), clear mtkaifv4 ul ch1ch2 mux\n", __func__);
+		regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+				   MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+				   0x0 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+		break;
+	case MT8196_DAI_AP_DMIC_CH34:
+		dev_dbg(afe->dev, "%s(), clear mtkaifv4 ul ch3ch4 mux\n", __func__);
+		regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+				   MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+				   0x0 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* choose Phase */
+	regmap_update_bits(afe->regmap, reg_con0,
+			   UL_DMIC_PHASE_SEL_CH1_MASK_SFT,
+			   0x0 << UL_DMIC_PHASE_SEL_CH1_SFT);
+	regmap_update_bits(afe->regmap, reg_con0,
+			   UL_DMIC_PHASE_SEL_CH2_MASK_SFT,
+			   0x4 << UL_DMIC_PHASE_SEL_CH2_SFT);
+
+	/* dmic mode, 3.25M*/
+	regmap_update_bits(afe->regmap, reg_con0,
+			   DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT,
+			   0x0);
+	regmap_update_bits(afe->regmap, reg_con0,
+			   DMIC_LOW_POWER_MODE_CTL_MASK_SFT,
+			   0x0);
+
+	/* turn on dmic, ch1, ch2 */
+	regmap_update_bits(afe->regmap, reg_con0,
+			   UL_SDM_3_LEVEL_CTL_MASK_SFT,
+			   0x1 << UL_SDM_3_LEVEL_CTL_SFT);
+	regmap_update_bits(afe->regmap, reg_con0,
+			   UL_MODE_3P25M_CH1_CTL_MASK_SFT,
+			   0x1 << UL_MODE_3P25M_CH1_CTL_SFT);
+	regmap_update_bits(afe->regmap, reg_con0,
+			   UL_MODE_3P25M_CH2_CTL_MASK_SFT,
+			   0x1 << UL_MODE_3P25M_CH2_CTL_SFT);
+
+	/* ul gain:  gain = 0x7fff/positive_gain = 0x0/gain_mode = 0x10 */
+	regmap_update_bits(afe->regmap, reg_con1,
+			   ADDA_UL_GAIN_VALUE_MASK_SFT,
+			   0x7fff << ADDA_UL_GAIN_VALUE_SFT);
+	regmap_update_bits(afe->regmap, reg_con1,
+			   ADDA_UL_POSTIVEGAIN_MASK_SFT,
+			   0x0 << ADDA_UL_POSTIVEGAIN_SFT);
+	/* gain_mode = 0x10: Add 0.5 gain at CIC output */
+	regmap_update_bits(afe->regmap, reg_con1,
+			   GAIN_MODE_MASK_SFT,
+			   0x02 << GAIN_MODE_SFT);
+	return 0;
+}
+
+static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int mtkaif_dmic = afe_priv->mtkaif_dmic;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n",
+		__func__, w->name, event, mtkaif_dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA, 1);
+
+		/* update setting to dmic */
+		if (mtkaif_dmic) {
+			/* mtkaif_rxif_data_mode = 1, dmic */
+			regmap_update_bits(afe->regmap, AFE_MTKAIF0_RX_CFG0,
+					   0x1, 0x1);
+
+			/* dmic mode, 3.25M*/
+			regmap_update_bits(afe->regmap, AFE_MTKAIF0_RX_CFG0,
+					   RG_MTKAIF0_RXIF_VOICE_MODE_MASK_SFT,
+					   0x0);
+			mtk_adda_ul_src_dmic(afe, MT8196_DAI_ADDA);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA, 1);
+
+		/* reset dmic */
+		afe_priv->mtkaif_dmic = 0;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_ch34_ul_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int mtkaif_dmic = afe_priv->mtkaif_dmic_ch34;
+	int mtkaif_adda6_only = afe_priv->mtkaif_adda6_only;
+
+	dev_dbg(afe->dev,
+		"%s(), name %s, event 0x%x, mtkaif_dmic %d, mtkaif_adda6_only %d\n",
+		__func__, w->name, event, mtkaif_dmic, mtkaif_adda6_only);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA_CH34, 1);
+
+		/* update setting to dmic */
+		if (mtkaif_dmic) {
+			/* mtkaif_rxif_data_mode = 1, dmic */
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG0,
+					   0x1, 0x1);
+
+			/* dmic mode, 3.25M*/
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG0,
+					   RG_MTKAIF1_RXIF_VOICE_MODE_MASK_SFT,
+					   0x0);
+			mtk_adda_ul_src_dmic(afe, MT8196_DAI_ADDA_CH34);
+		}
+
+		/* when using adda6 without adda enabled,
+		 * RG_ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE_SFT need to be set or
+		 * data cannot be received.
+		 */
+		if (mtkaif_adda6_only) {
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG2,
+					   RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK_SFT,
+					   0x1);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA_CH34, 1);
+
+		/* reset dmic */
+		afe_priv->mtkaif_dmic_ch34 = 0;
+
+		if (mtkaif_adda6_only) {
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG2,
+					   RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK_SFT,
+					   0x0);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_ch56_ul_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int mtkaif_dmic = afe_priv->mtkaif_dmic;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n",
+		__func__, w->name, event, mtkaif_dmic);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA_CH56, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA_CH56, 1);
+
+		/* reset dmic */
+		afe_priv->mtkaif_dmic = 0;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_ul_ap_dmic_event(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA, 1);
+		//mtk_adda_ul_src_dmic(afe, MT8196_DAI_AP_DMIC);
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_AP_DMIC, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA, 1);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_AP_DMIC, 1);
+
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_ch34_ul_ap_dmic_event(struct snd_soc_dapm_widget *w,
+					  struct snd_kcontrol *kcontrol,
+					  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int mtkaif_adda6_only = afe_priv->mtkaif_adda6_only;
+
+	dev_dbg(afe->dev,
+		"%s(), name %s, event 0x%x, mtkaif_adda6_only %d\n",
+		__func__, w->name, event, mtkaif_adda6_only);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA_CH34, 1);
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_AP_DMIC_CH34, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA_CH34, 1);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_AP_DMIC_CH34, 1);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_pad_top_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2)
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP_CFG0, 0xB8);
+		else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2)
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP_CFG0, 0xB0);
+		else
+			regmap_write(afe->regmap, AFE_AUD_PAD_TOP_CFG0, 0xB0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static bool is_adda_mtkaif_need_phase_delay(struct mt8196_afe_private *afe_priv)
+{
+	if (mt8196_afe_gpio_is_prepared(MT8196_AFE_GPIO_DAT_MISO0_ON) &&
+	    afe_priv->mtkaif_chosen_phase[0] < 0) {
+		return false;
+	}
+
+	if (mt8196_afe_gpio_is_prepared(MT8196_AFE_GPIO_DAT_MISO1_ON) &&
+	    afe_priv->mtkaif_chosen_phase[1] < 0) {
+		return false;
+	}
+
+	return true;
+}
+
+static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int delay_data;
+	int delay_cycle;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+#ifdef MTKAIF4
+		/* mtkaif_rxif_clkinv_adc inverse for calibration */
+		regmap_update_bits(afe->regmap, AFE_MTKAIF0_CFG0,
+				   RG_MTKAIF0_RXIF_CLKINV_MASK_SFT,
+				   0x1 << RG_MTKAIF0_RXIF_CLKINV_SFT);
+		regmap_update_bits(afe->regmap, AFE_MTKAIF1_CFG0,
+				   RG_MTKAIF1_RXIF_CLKINV_ADC_MASK_SFT,
+				   0x1 << RG_MTKAIF1_RXIF_CLKINV_ADC_SFT);
+#endif
+
+		if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) {
+			/* set protocol 2 */
+			regmap_write(afe->regmap, AFE_MTKAIF0_CFG0,
+				     0x00010000);
+			regmap_write(afe->regmap, AFE_MTKAIF1_CFG0,
+				     0x00010000);
+
+		/* mtkaif_rxif_clkinv_adc inverse for calibration */
+		regmap_update_bits(afe->regmap, AFE_MTKAIF0_CFG0,
+				   RG_MTKAIF0_RXIF_CLKINV_MASK_SFT,
+				   0x1 << RG_MTKAIF0_RXIF_CLKINV_SFT);
+		regmap_update_bits(afe->regmap, AFE_MTKAIF1_CFG0,
+				   RG_MTKAIF1_RXIF_CLKINV_ADC_MASK_SFT,
+				   0x1 << RG_MTKAIF1_RXIF_CLKINV_ADC_SFT);
+
+		/* This event align the phase of every miso pin */
+		/* If only 1 miso is used, there is no need to do phase delay. */
+		if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0 &&
+		    !is_adda_mtkaif_need_phase_delay(afe_priv)) {
+			dev_dbg(afe->dev,
+				"%s(), check adda mtkaif_chosen_phase[0/1]:%d/%d\n",
+				__func__,
+				afe_priv->mtkaif_chosen_phase[0],
+				afe_priv->mtkaif_chosen_phase[1]);
+			break;
+		}
+
+		/* set delay for ch12 to align phase of miso0 and miso1 */
+		if (afe_priv->mtkaif_phase_cycle[0] >=
+		    afe_priv->mtkaif_phase_cycle[1]) {
+			delay_data = DELAY_DATA_MISO1;
+			delay_cycle = afe_priv->mtkaif_phase_cycle[0] -
+				      afe_priv->mtkaif_phase_cycle[1];
+		} else {
+			delay_data = DELAY_DATA_MISO2;
+			delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
+				      afe_priv->mtkaif_phase_cycle[0];
+		}
+
+		regmap_update_bits(afe->regmap,
+				   AFE_MTKAIF0_RX_CFG2,
+				   RG_MTKAIF0_RXIF_DELAY_DATA_MASK_SFT,
+				   delay_data <<
+				   RG_MTKAIF0_RXIF_DELAY_DATA_SFT);
+
+		regmap_update_bits(afe->regmap,
+				   AFE_MTKAIF0_RX_CFG2,
+				   RG_MTKAIF0_RXIF_DELAY_CYCLE_MASK_SFT,
+				   delay_cycle <<
+				   RG_MTKAIF0_RXIF_DELAY_CYCLE_SFT);
+
+		/* set delay between ch3 and ch2 */
+		if (afe_priv->mtkaif_phase_cycle[2] >=
+		    afe_priv->mtkaif_phase_cycle[1]) {
+			delay_data = DELAY_DATA_MISO1;  /* ch3 */
+			delay_cycle = afe_priv->mtkaif_phase_cycle[2] -
+				      afe_priv->mtkaif_phase_cycle[1];
+		} else {
+			delay_data = DELAY_DATA_MISO2;  /* ch2 */
+			delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
+				      afe_priv->mtkaif_phase_cycle[2];
+		}
+
+		regmap_update_bits(afe->regmap,
+				   AFE_MTKAIF1_RX_CFG2,
+				   RG_MTKAIF1_RXIF_DELAY_DATA_MASK_SFT,
+				   delay_data <<
+				   RG_MTKAIF1_RXIF_DELAY_DATA_SFT);
+		regmap_update_bits(afe->regmap,
+				   AFE_MTKAIF1_RX_CFG2,
+				   RG_MTKAIF1_RXIF_DELAY_CYCLE_MASK_SFT,
+				   delay_cycle <<
+				   RG_MTKAIF1_RXIF_DELAY_CYCLE_SFT);
+		} else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) {
+			regmap_write(afe->regmap, AFE_MTKAIF0_CFG0,
+				     0x00010000);
+			regmap_write(afe->regmap, AFE_MTKAIF1_CFG0,
+				     0x00010000);
+		} else {
+			regmap_write(afe->regmap, AFE_MTKAIF0_CFG0, 0x0);
+			regmap_write(afe->regmap, AFE_MTKAIF1_CFG0, 0x0);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_ch34_dl_event(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_afe_gpio_request(afe, true, MT8196_DAI_ADDA_CH34, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(120, 130);
+		mt8196_afe_gpio_request(afe, false, MT8196_DAI_ADDA_CH34, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static void mt6363_vs1_vote(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	bool pre_enable = afe_priv->is_mt6363_vote;
+	bool enable = false;
+
+	if (!afe_priv->pmic_regmap)
+		return;
+	enable = (afe_priv->is_adda_dl_on && afe_priv->is_adda_dl_max_vol) ||
+		  afe_priv->is_adda_ul_on ||
+		  afe_priv->is_vow_enable;
+	if (enable == pre_enable) {
+		dev_dbg(afe->dev, "%s() enable == pre_enable = %d\n",
+			__func__, enable);
+		return;
+	}
+	afe_priv->is_mt6363_vote = enable;
+	dev_dbg(afe->dev, "%s() enable = %d\n",
+		__func__, enable);
+	if (enable) {
+		regmap_update_bits(afe_priv->pmic_regmap, RG_BUCK_VS1_VOTER_EN_LO_SET,
+				   VS1_MT6338_MSK, VS1_MT6338_MSK);
+	} else {
+		regmap_update_bits(afe_priv->pmic_regmap, RG_BUCK_VS1_VOTER_EN_LO_CLR,
+				   VS1_MT6338_MSK, VS1_MT6338_MSK);
+	}
+}
+
+static int mt_vs1_voter_dl_event(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(afe->dev, "%s(), event = 0x%x\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		afe_priv->is_adda_dl_on = true;
+		mt6363_vs1_vote(afe);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		afe_priv->is_adda_dl_on = false;
+		mt6363_vs1_vote(afe);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mt_vs1_voter_ul_event(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(afe->dev, "%s(), event = 0x%x\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		afe_priv->is_adda_ul_on = true;
+		mt6363_vs1_vote(afe);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		afe_priv->is_adda_ul_on = false;
+		mt6363_vs1_vote(afe);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* stf */
+static int stf_positive_gain_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->stf_positive_gain_db;
+	return 0;
+}
+
+static int stf_positive_gain_set(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int gain_db = ucontrol->value.integer.value[0];
+
+	afe_priv->stf_positive_gain_db = gain_db;
+
+	if (gain_db >= 0 && gain_db <= 24) {
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_GAIN,
+				   SIDE_TONE_POSITIVE_GAIN_MASK_SFT,
+				   (gain_db / 6) << SIDE_TONE_POSITIVE_GAIN_SFT);
+	} else {
+		dev_info(afe->dev, "%s(), gain_db %d invalid\n",
+			 __func__, gain_db);
+	}
+	return 0;
+}
+
+/* mtkaif dmic */
+static const char *const mt8196_adda_off_on_str[] = {
+	"Off", "On"
+};
+
+static const struct soc_enum mt8196_adda_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8196_adda_off_on_str),
+			    mt8196_adda_off_on_str),
+};
+
+static int mt8196_adda_ap_dmic_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->ap_dmic;
+	return 0;
+}
+
+static int mt8196_adda_ap_dmic_set(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int ap_dmic_on;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	ap_dmic_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(afe->dev, "%s(), kcontrol name %s, ap_dmic_on %d\n",
+		__func__, kcontrol->id.name, ap_dmic_on);
+
+	afe_priv->ap_dmic = ap_dmic_on;
+	return 0;
+}
+
+static int mt8196_adda_dmic_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic;
+	return 0;
+}
+
+static int mt8196_adda_dmic_set(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int dmic_on;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	dmic_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
+		__func__, kcontrol->id.name, dmic_on);
+
+	afe_priv->mtkaif_dmic = dmic_on;
+	afe_priv->mtkaif_dmic_ch34 = dmic_on;
+	return 0;
+}
+
+static int mt8196_adda6_only_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->mtkaif_adda6_only;
+	return 0;
+}
+
+static int mt8196_adda6_only_set(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int mtkaif_adda6_only;
+
+	if (ucontrol->value.enumerated.item[0] >= e->items)
+		return -EINVAL;
+
+	mtkaif_adda6_only = ucontrol->value.integer.value[0];
+
+	dev_dbg(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
+		__func__, kcontrol->id.name, mtkaif_adda6_only);
+
+	afe_priv->mtkaif_adda6_only = mtkaif_adda6_only;
+	return 0;
+}
+
+static int mt8196_adda_dl_max_vol_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->is_adda_dl_max_vol;
+
+	return 0;
+}
+
+static int mt8196_adda_dl_max_vol_set(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	bool is_adda_dl_max_vol = ucontrol->value.integer.value[0];
+
+	afe_priv->is_adda_dl_max_vol = is_adda_dl_max_vol;
+	mt6363_vs1_vote(afe);
+
+	return 0;
+}
+
+static int mt8196_vow_enable_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	ucontrol->value.integer.value[0] = afe_priv->is_vow_enable;
+
+	return 0;
+}
+
+static int mt8196_vow_enable_set(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	bool is_vow_enable = ucontrol->value.integer.value[0];
+
+	afe_priv->is_vow_enable = is_vow_enable;
+	mt6363_vs1_vote(afe);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new mtk_adda_controls[] = {
+	SOC_SINGLE("Sidetone_Gain", AFE_STF_GAIN,
+		   SIDE_TONE_GAIN_SFT, SIDE_TONE_GAIN_MASK, 0),
+	SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 100, 0,
+		       stf_positive_gain_get, stf_positive_gain_set),
+	SOC_ENUM_EXT("MTKAIF_DMIC", mt8196_adda_enum[0],
+		     mt8196_adda_dmic_get, mt8196_adda_dmic_set),
+	SOC_ENUM_EXT("MTKAIF_ADDA6_ONLY", mt8196_adda_enum[0],
+		     mt8196_adda6_only_get, mt8196_adda6_only_set),
+	SOC_SINGLE_EXT("ADDA_DL_MAX_VOL",
+		       SND_SOC_NOPM, 0, 0x1, 0,
+		       mt8196_adda_dl_max_vol_get,
+		       mt8196_adda_dl_max_vol_set),
+	SOC_SINGLE_EXT("VOW_ENABLE",
+		       SND_SOC_NOPM, 0, 0x1, 0,
+		       mt8196_vow_enable_get,
+		       mt8196_vow_enable_set),
+	SOC_ENUM_EXT("AP DMIC Used", mt8196_adda_enum[0],
+		     mt8196_adda_ap_dmic_get, mt8196_adda_ap_dmic_set),
+};
+
+static const struct snd_kcontrol_new stf_ctl =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
+
+static const u16 stf_coeff_table_16k[] = {
+	0x049C, 0x09E8, 0x09E0, 0x089C,
+	0xFF54, 0xF488, 0xEAFC, 0xEBAC,
+	0xfA40, 0x17AC, 0x3D1C, 0x6028,
+	0x7538
+};
+
+static const u16 stf_coeff_table_32k[] = {
+	0xFE52, 0x0042, 0x00C5, 0x0194,
+	0x029A, 0x03B7, 0x04BF, 0x057D,
+	0x05BE, 0x0555, 0x0426, 0x0230,
+	0xFF92, 0xFC89, 0xF973, 0xF6C6,
+	0xF500, 0xF49D, 0xF603, 0xF970,
+	0xFEF3, 0x065F, 0x0F4F, 0x1928,
+	0x2329, 0x2C80, 0x345E, 0x3A0D,
+	0x3D08
+};
+
+static const u16 stf_coeff_table_48k[] = {
+	0x0401, 0xFFB0, 0xFF5A, 0xFECE,
+	0xFE10, 0xFD28, 0xFC21, 0xFB08,
+	0xF9EF, 0xF8E8, 0xF80A, 0xF76C,
+	0xF724, 0xF746, 0xF7E6, 0xF90F,
+	0xFACC, 0xFD1E, 0xFFFF, 0x0364,
+	0x0737, 0x0B62, 0x0FC1, 0x1431,
+	0x188A, 0x1CA4, 0x2056, 0x237D,
+	0x25F9, 0x27B0, 0x2890
+};
+
+static int mtk_stf_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol,
+			 int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	size_t half_tap_num;
+	const u16 *stf_coeff_table;
+	unsigned int ul_rate;
+
+	u32 reg_value;
+	size_t coef_addr;
+
+	regmap_read(afe->regmap, AFE_ADDA_UL0_SRC_CON0, &ul_rate);
+	ul_rate = ul_rate >> UL_VOICE_MODE_CH1_CH2_CTL_SFT;
+	ul_rate = ul_rate & UL_VOICE_MODE_CH1_CH2_CTL_MASK;
+
+	if (ul_rate == MTK_AFE_ADDA_UL_RATE_48K) {
+		half_tap_num = ARRAY_SIZE(stf_coeff_table_48k);
+		stf_coeff_table = stf_coeff_table_48k;
+	} else if (ul_rate == MTK_AFE_ADDA_UL_RATE_32K) {
+		half_tap_num = ARRAY_SIZE(stf_coeff_table_32k);
+		stf_coeff_table = stf_coeff_table_32k;
+	} else {
+		half_tap_num = ARRAY_SIZE(stf_coeff_table_16k);
+		stf_coeff_table = stf_coeff_table_16k;
+	}
+
+	regmap_read(afe->regmap, AFE_STF_CON0, &reg_value);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x, ul_rate 0x%x, AFE_STF_CON0 0x%x\n",
+		__func__, w->name, event, ul_rate, reg_value);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* set side tone gain = 0 */
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_GAIN,
+				   SIDE_TONE_GAIN_MASK_SFT,
+				   0);
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_GAIN,
+				   SIDE_TONE_POSITIVE_GAIN_MASK_SFT,
+				   0);
+		/* set stf half tap num */
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_CON0,
+				   SIDE_TONE_HALF_TAP_NUM_MASK_SFT,
+				   half_tap_num << SIDE_TONE_HALF_TAP_NUM_SFT);
+
+		/* set side tone coefficient */
+		regmap_read(afe->regmap, AFE_STF_MON, &reg_value);
+		for (coef_addr = 0; coef_addr < half_tap_num; coef_addr++) {
+			bool old_w_ready = (reg_value >> SIDE_TONE_W_RDY_SFT) & 0x1;
+			bool new_w_ready = 0;
+			int try_cnt = 0;
+
+			regmap_update_bits(afe->regmap,
+					   AFE_STF_COEFF,
+					   0x11FFFFF,
+					   (1 << SIDE_TONE_COEFFICIENT_R_W_SEL_SFT) |
+					   (coef_addr <<
+					    SIDE_TONE_COEFFICIENT_ADDR_SFT) |
+					   stf_coeff_table[coef_addr]);
+
+			/* wait until flag write_ready changed */
+			for (try_cnt = 0; try_cnt < 10; try_cnt++) {
+				regmap_read(afe->regmap,
+					    AFE_STF_MON, &reg_value);
+				new_w_ready = (reg_value >> SIDE_TONE_W_RDY_SFT) & 0x1;
+
+				/* flip => ok */
+				if (new_w_ready == old_w_ready) {
+					usleep_range(1, 5);
+					if (try_cnt == 9) {
+						dev_info(afe->dev,
+							 "%s(), write coeff not ready",
+							 __func__);
+					}
+				} else {
+					break;
+				}
+			}
+
+			/* need write -> read -> write to write next coeff */
+			regmap_update_bits(afe->regmap,
+					   AFE_STF_COEFF,
+					   SIDE_TONE_COEFFICIENT_R_W_SEL_SFT,
+					   0x0);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* set side tone gain = 0 */
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_GAIN,
+				   SIDE_TONE_GAIN_MASK_SFT,
+				   0);
+		regmap_update_bits(afe->regmap,
+				   AFE_STF_GAIN,
+				   SIDE_TONE_POSITIVE_GAIN_MASK_SFT,
+				   0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* ADDA UL MUX */
+#define ADDA_UL_MUX_MASK 0x3
+enum {
+	ADDA_UL_MUX_MTKAIF = 0,
+	ADDA_UL_MUX_AP_DMIC,
+	ADDA_UL_MUX_AP_DMIC_MULTICH,
+};
+
+static const char *const adda_ul_mux_map[] = {
+	"MTKAIF", "AP_DMIC", "AP_DMIC_MULTI_CH",
+};
+
+static int adda_ul_map_value[] = {
+	ADDA_UL_MUX_MTKAIF,
+	ADDA_UL_MUX_AP_DMIC,
+	ADDA_UL_MUX_AP_DMIC_MULTICH,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum,
+				  SND_SOC_NOPM,
+				  0,
+				  ADDA_UL_MUX_MASK,
+				  adda_ul_mux_map,
+				  adda_ul_map_value);
+
+static const struct snd_kcontrol_new adda_ul_mux_control =
+	SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_kcontrol_new adda_ch34_ul_mux_control =
+	SOC_DAPM_ENUM("ADDA_CH34_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_kcontrol_new adda_ch56_ul_mux_control =
+	SOC_DAPM_ENUM("ADDA_CH56_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch1_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch2_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
+
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH3", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch3_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch3_mix)),
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH4", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch4_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch4_mix)),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+			      AUDIO_ENGEN_CON0, AUDIO_F3P25M_EN_ON_SFT, 0,
+			      NULL, 0),
+
+	/*AFE_ADDA_MTKAIFV4_TX_CFG0 control by PAD_CLK*/
+	SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_adda_dl_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Playback Enable",
+			      SUPPLY_SEQ_ADDA_DL_ON,
+			      AFE_ADDA6_MTKAIFV4_TX_CFG0,
+			      ADDA6_MTKAIFV4_TXIF_AFE_ON_SFT, 0,
+			      mtk_adda_ch34_dl_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA_UL0_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SFT, 0,
+			      mtk_adda_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA_UL1_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SFT, 0,
+			      mtk_adda_ch34_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("ADDA CH56 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA_UL1_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SFT, 0,
+			      mtk_adda_ch56_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("AUD_PAD_TOP", SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
+			      AFE_AUD_PAD_TOP_CFG0,
+			      RG_RX_FIFO_ON_SFT, 0,
+			      mtk_adda_pad_top_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("AUD_PAD_CLK", SUPPLY_SEQ_ADDA_AUD_PAD_TOP,
+			      AFE_ADDA_MTKAIFV4_TX_CFG0,
+			      MTKAIFV4_TXIF_AFE_ON_SFT, 0,
+			      NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIFV4_RX", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+			      AFE_ADDA_MTKAIFV4_RX_CFG0,
+			      MTKAIFV4_RXIF_AFE_ON_SFT, 0,
+			      NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADDA6_MTKAIFV4_RX", SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
+			      AFE_ADDA6_MTKAIFV4_RX_CFG0,
+			      ADDA6_MTKAIFV4_RXIF_AFE_ON_SFT, 0,
+			      NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_adda_mtkaif_cfg_event,
+			      SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY_S("ADDA6_MTKAIF_CFG", SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_adda_mtkaif_cfg_event,
+			      SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY_S("ADDA7_MTKAIF_CFG", SUPPLY_SEQ_ADDA6_MTKAIF_CFG,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_adda_mtkaif_cfg_event,
+			      SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
+			      AFE_ADDA_UL0_SRC_CON0,
+			      UL_AP_DMIC_ON_SFT, 0,
+			      mtk_adda_ul_ap_dmic_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY_S("AP_DMIC_CH34_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
+			      AFE_ADDA_UL1_SRC_CON0,
+			      UL_AP_DMIC_ON_SFT, 0,
+			      mtk_adda_ch34_ul_ap_dmic_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO,
+			      AFE_ADDA_UL0_SRC_CON1,
+			      FIFO_SOFT_RST_SFT, 1,
+			      NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADDA_CH34_FIFO", SUPPLY_SEQ_ADDA_FIFO,
+			      AFE_ADDA_UL1_SRC_CON1,
+			      FIFO_SOFT_RST_SFT, 1,
+			      NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("VS1_VOTER_DL", SUPPLY_SEQ_ADDA_AFE_ON,
+			      SND_SOC_NOPM, 0, 0,
+			      mt_vs1_voter_dl_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VS1_VOTER_UL", SUPPLY_SEQ_ADDA_AFE_ON,
+			      SND_SOC_NOPM, 0, 0,
+			      mt_vs1_voter_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0,
+			 &adda_ul_mux_control),
+	SND_SOC_DAPM_MUX("ADDA_CH34_UL_Mux", SND_SOC_NOPM, 0, 0,
+			 &adda_ch34_ul_mux_control),
+	SND_SOC_DAPM_MUX("ADDA_CH56_UL_Mux", SND_SOC_NOPM, 0, 0,
+			 &adda_ch56_ul_mux_control),
+
+	SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"),
+	SND_SOC_DAPM_INPUT("AP_DMIC_CH34_INPUT"),
+
+	/* stf */
+	SND_SOC_DAPM_SWITCH_E("Sidetone Filter",
+			      AFE_STF_CON0, SIDE_TONE_ON_SFT, 0,
+			      &stf_ctl,
+			      mtk_stf_event,
+			      SND_SOC_DAPM_PRE_PMU |
+			      SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER("STF_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_stf_ch1_mix,
+			   ARRAY_SIZE(mtk_stf_ch1_mix)),
+	SND_SOC_DAPM_OUTPUT("STF_OUTPUT"),
+
+	/* allow i2s on without codec on */
+	SND_SOC_DAPM_OUTPUT("ADDA_DUMMY_OUT"),
+	SND_SOC_DAPM_MUX("ADDA_Out_Mux",
+			 SND_SOC_NOPM, 0, 0, &adda_out_mux_control),
+	SND_SOC_DAPM_INPUT("ADDA_DUMMY_IN"),
+	SND_SOC_DAPM_MUX("ADDA_In_Mux",
+			 SND_SOC_NOPM, 0, 0, &adda_in_mux_control),
+
+	/* clock */
+	SND_SOC_DAPM_CLOCK_SUPPLY("vlp_mux_audio_h"),
+
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_ul0_adc_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_ul0_adc_hires_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_ul1_adc_clk"),
+	SND_SOC_DAPM_CLOCK_SUPPLY("aud_ul1_adc_hires_clk"),
+};
+
+#define HIRES_THRESHOLD 48000
+static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source,
+				     struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_afe_adda_priv *adda_priv;
+
+	adda_priv = get_adda_priv_by_name(afe, w->name);
+
+	if (!adda_priv) {
+		AUDIO_AEE("adda_priv == NULL");
+		return 0;
+	}
+
+	return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0;
+}
+
+static int mtk_afe_record_miso1(struct snd_soc_dapm_widget *source,
+				struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	return (afe_priv->audio_r_miso1_enable) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+	/* playback */
+	{"ADDA_DL_CH1", "DL0_CH1", "DL0"},
+	{"ADDA_DL_CH2", "DL0_CH1", "DL0"},
+	{"ADDA_DL_CH2", "DL0_CH2", "DL0"},
+
+	{"ADDA_DL_CH1", "DL1_CH1", "DL1"},
+	{"ADDA_DL_CH2", "DL1_CH2", "DL1"},
+
+	{"ADDA_DL_CH1", "DL2_CH1", "DL2"},
+	{"ADDA_DL_CH2", "DL2_CH2", "DL2"},
+
+	{"ADDA_DL_CH1", "DL3_CH1", "DL3"},
+	{"ADDA_DL_CH2", "DL3_CH2", "DL3"},
+
+	{"ADDA_DL_CH1", "DL4_CH1", "DL4"},
+	{"ADDA_DL_CH2", "DL4_CH2", "DL4"},
+
+	{"ADDA_DL_CH1", "DL5_CH1", "DL5"},
+	{"ADDA_DL_CH2", "DL5_CH2", "DL5"},
+
+	{"ADDA_DL_CH1", "DL6_CH1", "DL6"},
+	{"ADDA_DL_CH2", "DL6_CH2", "DL6"},
+
+	{"ADDA_DL_CH1", "DL7_CH1", "DL7"},
+	{"ADDA_DL_CH2", "DL7_CH2", "DL7"},
+
+	{"ADDA_DL_CH1", "DL8_CH1", "DL8"},
+	{"ADDA_DL_CH2", "DL8_CH2", "DL8"},
+
+	{"ADDA_DL_CH1", "DL_24CH_CH1", "DL_24CH"},
+	{"ADDA_DL_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+	{"ADDA_DL_CH1", "DL24_CH1", "DL24"},
+	{"ADDA_DL_CH2", "DL24_CH2", "DL24"},
+
+	{"ADDA Playback", NULL, "ADDA_DL_CH1"},
+	{"ADDA Playback", NULL, "ADDA_DL_CH2"},
+
+	{"ADDA Playback", NULL, "ADDA Enable"},
+	{"ADDA Playback", NULL, "ADDA Playback Enable"},
+	{"ADDA Playback", NULL, "AUD_PAD_CLK"},
+	{"ADDA Playback", NULL, "AUD_PAD_TOP"},
+	{"ADDA Playback", NULL, "VS1_VOTER_DL"},
+
+	{"ADDA_DL_CH3", "DL0_CH1", "DL0"},
+	{"ADDA_DL_CH4", "DL0_CH2", "DL0"},
+
+	{"ADDA_DL_CH3", "DL1_CH1", "DL1"},
+	{"ADDA_DL_CH4", "DL1_CH2", "DL1"},
+
+	{"ADDA_DL_CH3", "DL2_CH1", "DL2"},
+	{"ADDA_DL_CH4", "DL2_CH2", "DL2"},
+
+	{"ADDA_DL_CH3", "DL3_CH1", "DL3"},
+	{"ADDA_DL_CH4", "DL3_CH2", "DL3"},
+
+	{"ADDA_DL_CH3", "DL4_CH1", "DL4"},
+	{"ADDA_DL_CH4", "DL4_CH2", "DL4"},
+
+	{"ADDA_DL_CH3", "DL5_CH1", "DL5"},
+	{"ADDA_DL_CH4", "DL5_CH2", "DL5"},
+
+	{"ADDA_DL_CH3", "DL6_CH1", "DL6"},
+	{"ADDA_DL_CH4", "DL6_CH2", "DL6"},
+
+	{"ADDA_DL_CH3", "DL7_CH1", "DL7"},
+	{"ADDA_DL_CH4", "DL7_CH2", "DL7"},
+
+	{"ADDA_DL_CH3", "DL8_CH1", "DL8"},
+	{"ADDA_DL_CH4", "DL8_CH2", "DL8"},
+
+	{"ADDA_DL_CH3", "DL_24CH_CH1", "DL_24CH"},
+	{"ADDA_DL_CH4", "DL_24CH_CH2", "DL_24CH"},
+	{"ADDA_DL_CH3", "DL_24CH_CH3", "DL_24CH"},
+	{"ADDA_DL_CH4", "DL_24CH_CH4", "DL_24CH"},
+
+	{"ADDA CH34 Playback", NULL, "ADDA_DL_CH3"},
+	{"ADDA CH34 Playback", NULL, "ADDA_DL_CH4"},
+
+	{"ADDA CH34 Playback", NULL, "ADDA Enable"},
+	{"ADDA CH34 Playback", NULL, "ADDA CH34 Playback Enable"},
+	{"ADDA CH34 Playback", NULL, "AUD_PAD_CLK"},
+	{"ADDA CH34 Playback", NULL, "AUD_PAD_TOP"},
+	{"ADDA CH34 Playback", NULL, "VS1_VOTER_DL"},
+
+	/* capture */
+	{"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"},
+	{"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"},
+	{"ADDA_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"},
+
+	{"ADDA_CH34_UL_Mux", "MTKAIF", "ADDA CH34 Capture"},
+	{"ADDA_CH34_UL_Mux", "AP_DMIC", "AP DMIC CH34 Capture"},
+	{"ADDA_CH34_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"},
+
+	{"ADDA_CH56_UL_Mux", "MTKAIF", "ADDA CH56 Capture"},
+
+	{"ADDA Capture", NULL, "ADDA Enable"},
+	{"ADDA Capture", NULL, "ADDA Capture Enable"},
+	{"ADDA Capture", NULL, "AUD_PAD_CLK"},
+	{"ADDA Capture", NULL, "AUD_PAD_TOP"},
+	{"ADDA Capture", NULL, "ADDA_MTKAIFV4_RX"},
+	{"ADDA Capture", NULL, "ADDA6_MTKAIFV4_RX", mtk_afe_record_miso1},
+	{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
+	{"ADDA Capture", NULL, "VS1_VOTER_UL"},
+
+	{"AP DMIC Capture", NULL, "ADDA Enable"},
+	{"AP DMIC Capture", NULL, "ADDA Capture Enable"},
+	{"AP DMIC Capture", NULL, "ADDA_FIFO"},
+	{"AP DMIC Capture", NULL, "AP_DMIC_EN"},
+
+	{"ADDA CH34 Capture", NULL, "ADDA Enable"},
+	{"ADDA CH34 Capture", NULL, "ADDA CH34 Capture Enable"},
+	{"ADDA CH34 Capture", NULL, "AUD_PAD_CLK"},
+	{"ADDA CH34 Capture", NULL, "AUD_PAD_TOP"},
+	{"ADDA CH34 Capture", NULL, "ADDA_MTKAIFV4_RX"},
+	{"ADDA CH34 Capture", NULL, "ADDA6_MTKAIFV4_RX", mtk_afe_record_miso1},
+	{"ADDA CH34 Capture", NULL, "ADDA6_MTKAIF_CFG"},
+	{"ADDA CH34 Capture", NULL, "VS1_VOTER_UL"},
+
+	{"AP DMIC CH34 Capture", NULL, "ADDA Enable"},
+	{"AP DMIC CH34 Capture", NULL, "ADDA CH34 Capture Enable"},
+	{"AP DMIC CH34 Capture", NULL, "ADDA_CH34_FIFO"},
+	{"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_EN"},
+
+	{"AP DMIC MULTICH Capture", NULL, "ADDA Enable"},
+	{"AP DMIC MULTICH Capture", NULL, "ADDA Capture Enable"},
+	{"AP DMIC MULTICH Capture", NULL, "ADDA CH34 Capture Enable"},
+	{"AP DMIC MULTICH Capture", NULL, "ADDA_FIFO"},
+	{"AP DMIC MULTICH Capture", NULL, "ADDA_CH34_FIFO"},
+	{"AP DMIC MULTICH Capture", NULL, "AP_DMIC_EN"},
+	{"AP DMIC MULTICH Capture", NULL, "AP_DMIC_CH34_EN"},
+
+	{"ADDA CH56 Capture", NULL, "ADDA Enable"},
+	{"ADDA CH56 Capture", NULL, "ADDA CH56 Capture Enable"},
+	{"ADDA CH56 Capture", NULL, "AUD_PAD_CLK"},
+	{"ADDA CH56 Capture", NULL, "AUD_PAD_TOP"},
+	{"ADDA CH56 Capture", NULL, "ADDA6_MTKAIFV4_RX"},
+	{"ADDA CH56 Capture", NULL, "ADDA7_MTKAIF_CFG"},
+	{"ADDA CH56 Capture", NULL, "VS1_VOTER_UL"},
+
+	{"AP DMIC Capture", NULL, "AP_DMIC_INPUT"},
+	{"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_INPUT"},
+	{"AP DMIC MULTICH Capture", NULL, "AP_DMIC_INPUT"},
+
+	/* sidetone filter */
+	{"Sidetone Filter", "Switch", "STF_CH1"},
+
+	{"STF_OUTPUT", NULL, "Sidetone Filter"},
+	{"ADDA Playback", NULL, "Sidetone Filter"},
+	{"ADDA CH34 Playback", NULL, "Sidetone Filter"},
+
+	/* allow i2s on without codec on */
+	{"ADDA Capture", NULL, "ADDA_In_Mux"},
+	{"ADDA_In_Mux", "Dummy_Widget", "ADDA_DUMMY_IN"},
+	{"ADDA_Out_Mux", "Dummy_Widget", "ADDA Playback"},
+	{"ADDA_DUMMY_OUT", NULL, "ADDA_Out_Mux"},
+
+	/* clk */
+	{"ADDA Capture Enable", NULL, "aud_ul0_adc_clk"},
+	{"ADDA Capture Enable", NULL, "aud_ul0_adc_hires_clk",
+	 mtk_afe_adc_hires_connect},
+	{"ADDA CH34 Capture Enable", NULL, "aud_ul1_adc_clk"},
+	{"ADDA CH34 Capture Enable", NULL, "aud_ul1_adc_hires_clk",
+	 mtk_afe_adc_hires_connect},
+
+	{"aud_ul0_adc_hires_clk", NULL, "vlp_mux_audio_h"},
+	{"aud_ul1_adc_hires_clk", NULL, "vlp_mux_audio_h"},
+};
+
+/* dai ops */
+static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	unsigned int rate = params_rate(params);
+#ifdef MTKAIF4
+	unsigned int mtkaif_rate = 0;
+#endif
+	int id = dai->id;
+	struct mtk_afe_adda_priv *adda_priv;
+
+	if (id >= MT8196_DAI_NUM || id < 0)
+		return -EINVAL;
+
+	adda_priv = afe_priv->dai_priv[id];
+
+	dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		 __func__,
+		 id,
+		 substream->stream,
+		 rate);
+
+	if (!adda_priv) {
+		AUDIO_AEE("adda_priv == NULL");
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		adda_priv->dl_rate = rate;
+
+#ifdef MTKAIF4
+		/* get mtkaif dl rate */
+		mtkaif_rate =
+			mtkaif_rate_transform(afe, adda_priv->dl_rate);
+#endif
+		if (id == MT8196_DAI_ADDA) {
+#ifdef MTKAIF4
+			/* MTKAIF sample rate config */
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT,
+					   mtkaif_rate << MTKAIFV4_TXIF_INPUT_MODE_SFT);
+			/* AFE_ADDA_MTKAIFV4_TX_CFG0 */
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT,
+					   0x0 << MTKAIFV4_TXIF_FOUR_CHANNEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_ADDA_OUT_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_ADDA_OUT_EN_SEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_ADDA6_OUT_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_ADDA6_OUT_EN_SEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_TXIF_V4_MASK_SFT,
+					   0x1 << MTKAIFV4_TXIF_V4_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+					   MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+					   0x0 << MTKAIFV4_TXIF_EN_SEL_SFT);
+#endif
+			/* clean predistortion */
+		} else {
+#ifdef MTKAIF4
+			/* MTKAIF sample rate config */
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+					   ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT,
+					   mtkaif_rate << ADDA6_MTKAIFV4_TXIF_INPUT_MODE_SFT);
+			/* AFE_ADDA6_MTKAIFV4_TX_CFG0 */
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+					   ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT,
+					   0x0 << ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+					   ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+					   0x1 << ADDA6_MTKAIFV4_TXIF_EN_SEL_SFT);
+#endif
+		}
+	} else {
+		unsigned int voice_mode = 0;
+		unsigned int ul_src_con0 = 0;   /* default value */
+
+		adda_priv->ul_rate = rate;
+
+#ifdef MTKAIF4
+		/* get mtkaif dl rate */
+		mtkaif_rate =
+			mtkaif_rate_transform(afe, adda_priv->ul_rate);
+#endif
+
+		voice_mode = adda_ul_rate_transform(afe, rate);
+
+		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
+
+		/* enable iir */
+		ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
+				UL_IIR_ON_TMP_CTL_MASK_SFT;
+		ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
+				UL_IIRMODE_CTL_MASK_SFT;
+
+		regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+				   MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+				   mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT);
+
+		regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+				   ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+				   mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT);
+
+		switch (id) {
+		case MT8196_DAI_ADDA:
+		case MT8196_DAI_AP_DMIC:
+		case MT8196_DAI_AP_DMIC_MULTICH:
+#ifdef MTKAIF4
+			if (afe_priv->audio_r_miso1_enable == 1) {
+				/* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+						   0x0 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+						   0x1 << MTKAIFV4_RXIF_EN_SEL_SFT);
+
+				/* AFE_ADDA6_MTKAIFV4_RX_CFG0 */
+				regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+						   ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+						   0x1 << ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+				regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+						   ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+						   0x1 << ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT);
+			} else {
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+						   mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT);
+				/* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+						   0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+						   0x0 << MTKAIFV4_RXIF_EN_SEL_SFT);
+				/* [28] loopback mode
+				 * 0: loopback adda tx to adda rx
+				 * 1: loopback adda6 tx to adda rx
+				 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+						   0x0 << MTKAIFV4_TXIF_EN_SEL_SFT);
+			}
+
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+					   MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+					   MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+#endif
+			/* 35Hz @ 48k */
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048);
+
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_SRC_CON0, ul_src_con0);
+
+			/* mtkaif_rxif_data_mode = 0, amic */
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG0,
+					   0x1 << 0,
+					   0x0 << 0);
+
+			/* 35Hz @ 48k */
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_IIR_COEF_02_01, 0x00000000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_IIR_COEF_04_03, 0x00003FB8);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_IIR_COEF_06_05, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_IIR_COEF_08_07, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_IIR_COEF_10_09, 0x0000C048);
+
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL0_SRC_CON0, ul_src_con0);
+
+			/* mtkaif_rxif_data_mode = 0, amic */
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF0_RX_CFG0,
+					   0x1 << 0,
+					   0x0 << 0);
+			break;
+		case MT8196_DAI_ADDA_CH34:
+		case MT8196_DAI_AP_DMIC_CH34:
+#ifdef MTKAIF4
+			if (afe_priv->audio_r_miso1_enable == 0) {
+				/* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+						   0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+						   0x0 << MTKAIFV4_RXIF_EN_SEL_SFT);
+			}
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+					   MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+					   MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+
+#endif
+			/* 35Hz @ 48k */
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000);
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048);
+
+			regmap_write(afe->regmap,
+				     AFE_ADDA_UL1_SRC_CON0, ul_src_con0);
+
+			/* mtkaif_rxif_data_mode = 0, amic */
+			regmap_update_bits(afe->regmap,
+					   AFE_MTKAIF1_RX_CFG0,
+					   0x1 << 0,
+					   0x0 << 0);
+
+			break;
+		case MT8196_DAI_ADDA_CH56:
+			if (afe_priv->audio_r_miso1_enable == 1) {
+				/* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+						   0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+						   0x0 << MTKAIFV4_RXIF_EN_SEL_SFT);
+				/* [28] loopback mode
+				 * 0: loopback adda tx to adda rx
+				 * 1: loopback adda6 tx to adda rx
+				 */
+				regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+						   MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+						   0x0 << MTKAIFV4_TXIF_EN_SEL_SFT);
+			}
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+					   ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+					   mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT);
+			/* AFE_ADDA6_MTKAIFV4_RX_CFG0 */
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+					   ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+					   0x1 << ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+					   MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK_SFT,
+					   0x1 << MTKAIFV4_UL_CH5CH6_IN_EN_SEL_SFT);
+			regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+					   ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+					   0x1 << ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT);
+			break;
+		default:
+			break;
+		}
+
+		/* ap dmic */
+		switch (id) {
+		case MT8196_DAI_AP_DMIC:
+		case MT8196_DAI_AP_DMIC_CH34:
+			mtk_adda_ul_src_dmic(afe, id);
+			break;
+		case MT8196_DAI_AP_DMIC_MULTICH:
+			regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+					   DMIC_CLK_PHASE_SYNC_SET_MASK_SFT,
+					   0x1 << DMIC_CLK_PHASE_SYNC_SET_SFT);
+			mtk_adda_ul_src_dmic_phase_sync(afe);
+			mtk_adda_ul_src_dmic(afe, MT8196_DAI_AP_DMIC);
+			mtk_adda_ul_src_dmic(afe, MT8196_DAI_AP_DMIC_CH34);
+			mtk_adda_ul_src_dmic_phase_sync_clock(afe);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+	.hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+				 SNDRV_PCM_RATE_96000 |\
+				 SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+				SNDRV_PCM_RATE_16000 |\
+				SNDRV_PCM_RATE_32000 |\
+				SNDRV_PCM_RATE_48000 |\
+				SNDRV_PCM_RATE_96000 |\
+				SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			  SNDRV_PCM_FMTBIT_S24_LE |\
+			  SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+	{
+		.name = "ADDA",
+		.id = MT8196_DAI_ADDA,
+		.playback = {
+			.stream_name = "ADDA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_PLAYBACK_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.capture = {
+			.stream_name = "ADDA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "ADDA_CH34",
+		.id = MT8196_DAI_ADDA_CH34,
+		.playback = {
+			.stream_name = "ADDA CH34 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_PLAYBACK_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.capture = {
+			.stream_name = "ADDA CH34 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "ADDA_CH56",
+		.id = MT8196_DAI_ADDA_CH56,
+		.capture = {
+			.stream_name = "ADDA CH56 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "AP_DMIC",
+		.id = MT8196_DAI_AP_DMIC,
+		.capture = {
+			.stream_name = "AP DMIC Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "AP_DMIC_CH34",
+		.id = MT8196_DAI_AP_DMIC_CH34,
+		.capture = {
+			.stream_name = "AP DMIC CH34 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "AP_DMIC_MULTICH",
+		.id = MT8196_DAI_AP_DMIC_MULTICH,
+		.capture = {
+			.stream_name = "AP DMIC MULTICH Capture",
+			.channels_min = 1,
+			.channels_max = 4,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+};
+
+int mt8196_dai_adda_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	dev_dbg(afe->dev, "%s() successfully start\n", __func__);
+
+	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	list_add(&dai->list, &afe->sub_dais);
+
+	dai->dai_drivers = mtk_dai_adda_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+
+	dai->controls = mtk_adda_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_adda_controls);
+	dai->dapm_widgets = mtk_dai_adda_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+	dai->dapm_routes = mtk_dai_adda_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+
+	/* set dai priv */
+	ret = mt8196_dai_set_priv(afe, MT8196_DAI_ADDA,
+				  sizeof(struct mtk_afe_adda_priv), NULL);
+	if (ret)
+		return ret;
+
+	ret = mt8196_dai_set_priv(afe, MT8196_DAI_ADDA_CH34,
+				  sizeof(struct mtk_afe_adda_priv), NULL);
+	if (ret)
+		return ret;
+
+	ret = mt8196_dai_set_priv(afe, MT8196_DAI_ADDA_CH56,
+				  sizeof(struct mtk_afe_adda_priv), NULL);
+	if (ret)
+		return ret;
+
+	ret = mt8196_dai_set_priv(afe, MT8196_DAI_AP_DMIC_MULTICH,
+				  sizeof(struct mtk_afe_adda_priv), NULL);
+	if (ret)
+		return ret;
+
+	/* get ap mic type */
+	ret = of_property_read_u32(afe->dev->of_node, "mediatek,ap-dmic",
+				   &afe_priv->ap_dmic);
+	if (ret)
+		afe_priv->ap_dmic = 0;
+
+	/* ap dmic priv share with adda */
+	afe_priv->dai_priv[MT8196_DAI_AP_DMIC] =
+		afe_priv->dai_priv[MT8196_DAI_ADDA];
+	afe_priv->dai_priv[MT8196_DAI_AP_DMIC_CH34] =
+		afe_priv->dai_priv[MT8196_DAI_ADDA_CH34];
+
+	return 0;
+}
+
-- 
2.45.2



From krzk at kernel.org  Fri Mar  7 04:49:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 13:49:02 +0100
Subject: [PATCH] ARM64: dts: imx8mp-evk: add ecspi2 support
In-Reply-To: <20250306222359.797855-1-Frank.Li@nxp.com>
References: <20250306222359.797855-1-Frank.Li@nxp.com>
Message-ID: <2090b241-8780-4897-b898-4c55e4f80028@kernel.org>

On 06/03/2025 23:23, Frank Li wrote:
> +&ecspi2 {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	num-cs = <1>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;
> +	cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +
> +	spidev1: spi at 0 {
> +		compatible = "rohm,dh2228fv";

NAK, not true. You do not have there DH2228FV.

Stop sending blindly your downstream commits.

Best regards,
Krzysztof


From darren.ye at mediatek.com  Fri Mar  7 04:47:36 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:36 +0800
Subject: [PATCH 10/14] ASoC: mediatek: mt8196: support CM in platform driver
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-11-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add mt8196 CM driver support for ADDA multi-channel.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/mt8196/mt8196-afe-cm.c | 94 +++++++++++++++++++++++
 sound/soc/mediatek/mt8196/mt8196-afe-cm.h | 23 ++++++
 2 files changed, 117 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-cm.c
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-cm.h

diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-cm.c b/sound/soc/mediatek/mt8196/mt8196-afe-cm.c
new file mode 100644
index 000000000000..b923844a76f8
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-cm.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 MediaTek Inc.
+ * Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+
+#include "mtk-afe-fe-dai.h"
+#include "mtk-base-afe.h"
+
+#include "mt8196-afe-cm.h"
+#include "mt8196-afe-common.h"
+
+void mt8196_set_cm_rate(struct mtk_base_afe *afe, int id, unsigned int rate)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	afe_priv->cm_rate[id] = rate;
+}
+EXPORT_SYMBOL_GPL(mt8196_set_cm_rate);
+
+static int mt8196_convert_cm_ch(unsigned int ch)
+{
+	return ch - 1;
+}
+
+static unsigned int calculate_cm_update(int rate, int ch)
+{
+	unsigned int update_val;
+
+	update_val = 26000000 / rate / (ch / 2);
+	update_val = update_val * 10 / 7;
+	if (update_val > 100)
+		update_val = 100;
+	if (update_val < 7)
+		update_val = 7;
+
+	return update_val;
+}
+
+int mt8196_set_cm(struct mtk_base_afe *afe, int id,
+		  bool update, bool swap, unsigned int ch)
+{
+	unsigned int rate = 0;
+	unsigned int update_val = 0;
+	int reg;
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+	dev_dbg(afe->dev, "%s()-0, CM%d, rate %d, update %d, swap %d, ch %d\n",
+		__func__, id, rate, update, swap, ch);
+
+	rate = afe_priv->cm_rate[id];
+	update_val = update ? calculate_cm_update(rate, (int)ch) : 0x64;
+
+	reg = AFE_CM0_CON0 + 0x10 * id;
+	/* update cnt */
+	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_UPDATE_CNT_MASK,
+			       update_val, AFE_CM_UPDATE_CNT_SFT);
+
+	/* rate */
+	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_1X_EN_SEL_FS_MASK,
+			       rate, AFE_CM_1X_EN_SEL_FS_SFT);
+
+	/* ch num */
+	ch = mt8196_convert_cm_ch(ch);
+	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_CH_NUM_MASK,
+			       ch, AFE_CM_CH_NUM_SFT);
+
+	/* swap */
+	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_BYTE_SWAP_MASK,
+			       swap, AFE_CM_BYTE_SWAP_SFT);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mt8196_set_cm);
+
+int mt8196_enable_cm_bypass(struct mtk_base_afe *afe, int id, bool en)
+{
+	int reg = AFE_CM0_CON0 + 0x10 * id;
+
+	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_BYPASS_MODE_MASK,
+			       en, AFE_CM_BYPASS_MODE_SFT);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mt8196_enable_cm_bypass);
+
+MODULE_DESCRIPTION("Mediatek afe cm");
+MODULE_AUTHOR("darren ye <darren.ye at mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-cm.h b/sound/soc/mediatek/mt8196/mt8196-afe-cm.h
new file mode 100644
index 000000000000..18115ec8fa70
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-cm.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 MediaTek Inc.
+ * Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#ifndef MTK_AFE_CM_H_
+#define MTK_AFE_CM_H_
+enum {
+	CM0,
+	CM1,
+	CM2,
+	CM_NUM,
+};
+
+void mt8196_set_cm_rate(struct mtk_base_afe *afe, int id, unsigned int rate);
+
+int mt8196_set_cm(struct mtk_base_afe *afe, int id, bool update,
+		  bool swap, unsigned int ch);
+int mt8196_enable_cm_bypass(struct mtk_base_afe *afe, int id, bool en);
+
+#endif /* MTK_AFE_CM_H_ */
+
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:35 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:35 +0800
Subject: [PATCH 09/14] ASoC: mediatek: mt8196: support TDM in platform driver
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-10-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add mt8196 TDM DAI driver support.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/mt8196/mt8196-dai-tdm.c | 837 +++++++++++++++++++++
 1 file changed, 837 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-dai-tdm.c

diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c
new file mode 100644
index 000000000000..465134b234bd
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c
@@ -0,0 +1,837 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  MediaTek ALSA SoC Audio DAI TDM Control
+ *
+ *  Copyright (c) 2024 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-interconnection.h"
+
+struct mtk_afe_tdm_priv {
+	int bck_id;
+	int bck_rate;
+
+	int mclk_id;
+	int mclk_multiple; /* according to sample rate */
+	int mclk_rate;
+	int mclk_apll;
+};
+
+enum {
+	TDM_WLEN_16_BIT = 1,
+	TDM_WLEN_32_BIT = 2,
+};
+
+enum {
+	TDM_CHANNEL_BCK_16 = 0,
+	TDM_CHANNEL_BCK_24 = 1,
+	TDM_CHANNEL_BCK_32 = 2,
+};
+
+enum {
+	TDM_CHANNEL_NUM_2 = 0,
+	TDM_CHANNEL_NUM_4 = 1,
+	TDM_CHANNEL_NUM_8 = 2,
+};
+
+enum  {
+	TDM_CH_START_O30_O31 = 0,
+	TDM_CH_START_O32_O33,
+	TDM_CH_START_O34_O35,
+	TDM_CH_START_O36_O37,
+	TDM_CH_ZERO,
+};
+
+enum {
+	DPTX_CHANNEL_2,
+	DPTX_CHANNEL_8,
+};
+
+enum {
+	DPTX_WLEN_24_BIT,
+	DPTX_WLEN_16_BIT,
+};
+
+enum {
+	DPTX_CH_EN_MASK_2CH = 0x3,
+	DPTX_CH_EN_MASK_4CH = 0xf,
+	DPTX_CH_EN_MASK_6CH = 0x3f,
+	DPTX_CH_EN_MASK_8CH = 0xff,
+};
+
+static unsigned int get_tdm_wlen(snd_pcm_format_t format)
+{
+	return snd_pcm_format_physical_width(format) <= 16 ?
+	       TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
+}
+
+static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
+{
+	return snd_pcm_format_physical_width(format) <= 16 ?
+	       TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
+}
+
+static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
+{
+	return snd_pcm_format_physical_width(format) - 1;
+}
+
+static unsigned int get_tdm_ch(unsigned int ch)
+{
+	switch (ch) {
+	case 1:
+	case 2:
+		return TDM_CHANNEL_NUM_2;
+	case 3:
+	case 4:
+		return TDM_CHANNEL_NUM_4;
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	default:
+		return TDM_CHANNEL_NUM_8;
+	}
+}
+
+static unsigned int get_dptx_ch_enable_mask(unsigned int ch)
+{
+	switch (ch) {
+	case 1:
+	case 2:
+		return DPTX_CH_EN_MASK_2CH;
+	case 3:
+	case 4:
+		return DPTX_CH_EN_MASK_4CH;
+	case 5:
+	case 6:
+		return DPTX_CH_EN_MASK_6CH;
+	case 7:
+	case 8:
+		return DPTX_CH_EN_MASK_8CH;
+	default:
+		pr_info("%s(), invalid channel num, default use 2ch\n",
+			__func__);
+		return DPTX_CH_EN_MASK_2CH;
+	}
+}
+
+static unsigned int get_dptx_ch(unsigned int ch)
+{
+	if (ch == 2)
+		return DPTX_CHANNEL_2;
+	else
+		return DPTX_CHANNEL_8;
+}
+
+static unsigned int get_dptx_wlen(snd_pcm_format_t format)
+{
+	return snd_pcm_format_physical_width(format) <= 16 ?
+	       DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT;
+}
+
+/* interconnection */
+enum {
+	HDMI_CONN_CH0 = 0,
+	HDMI_CONN_CH1,
+	HDMI_CONN_CH2,
+	HDMI_CONN_CH3,
+	HDMI_CONN_CH4,
+	HDMI_CONN_CH5,
+	HDMI_CONN_CH6,
+	HDMI_CONN_CH7,
+};
+
+static const char *const hdmi_conn_mux_map[] = {
+	"CH0", "CH1", "CH2", "CH3",
+	"CH4", "CH5", "CH6", "CH7",
+};
+
+static int hdmi_conn_mux_map_value[] = {
+	HDMI_CONN_CH0,
+	HDMI_CONN_CH1,
+	HDMI_CONN_CH2,
+	HDMI_CONN_CH3,
+	HDMI_CONN_CH4,
+	HDMI_CONN_CH5,
+	HDMI_CONN_CH6,
+	HDMI_CONN_CH7,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_0_SFT,
+				  HDMI_O_0_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch0_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_1_SFT,
+				  HDMI_O_1_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch1_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_2_SFT,
+				  HDMI_O_2_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch2_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_3_SFT,
+				  HDMI_O_3_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch3_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_4_SFT,
+				  HDMI_O_4_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch4_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_5_SFT,
+				  HDMI_O_5_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch5_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_6_SFT,
+				  HDMI_O_6_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch6_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
+				  AFE_HDMI_CONN0,
+				  HDMI_O_7_SFT,
+				  HDMI_O_7_MASK,
+				  hdmi_conn_mux_map,
+				  hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch7_mux_control =
+	SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
+
+static const char *const tdm_out_mux_map[] = {
+	"Disconnect", "Connect",
+};
+
+static int tdm_out_mux_map_value[] = {
+	0, 1,
+};
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(hdmi_out_mux_map_enum,
+		SND_SOC_NOPM,
+		0,
+		1,
+		tdm_out_mux_map,
+		tdm_out_mux_map_value);
+static const struct snd_kcontrol_new hdmi_out_mux_control =
+	SOC_DAPM_ENUM("HDMI_OUT_MUX", hdmi_out_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(dptx_out_mux_map_enum,
+		SND_SOC_NOPM,
+		0,
+		1,
+		tdm_out_mux_map,
+		tdm_out_mux_map_value);
+static const struct snd_kcontrol_new dptx_out_mux_control =
+	SOC_DAPM_ENUM("DPTX_OUT_MUX", dptx_out_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(dptx_virtual_out_mux_map_enum,
+		SND_SOC_NOPM,
+		0,
+		1,
+		tdm_out_mux_map,
+		tdm_out_mux_map_value);
+
+static const struct snd_kcontrol_new dptx_virtual_out_mux_control =
+	SOC_DAPM_ENUM("DPTX_VIRTUAL_OUT_MUX", dptx_virtual_out_mux_map_enum);
+
+enum {
+	SUPPLY_SEQ_APLL,
+	SUPPLY_SEQ_TDM_MCK_EN,
+	SUPPLY_SEQ_TDM_BCK_EN,
+	SUPPLY_SEQ_TDM_DPTX_MCK_EN,
+	SUPPLY_SEQ_TDM_DPTX_BCK_EN,
+};
+
+static int get_tdm_id_by_name(const char *name)
+{
+	if (strstr(name, "DPTX"))
+		return MT8196_DAI_TDM_DPTX;
+	else
+		return MT8196_DAI_TDM;
+}
+
+static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_tdm_id_by_name(w->name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
+		__func__, w->name, event, dai_id);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		mt8196_mck_disable(afe, tdm_priv->bck_id);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_tdm_id_by_name(w->name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+
+	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
+		__func__, w->name, event, dai_id);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8196_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		tdm_priv->mclk_rate = 0;
+		mt8196_mck_disable(afe, tdm_priv->mclk_id);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
+	SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch0_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch1_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch2_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch3_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch4_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch5_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch6_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_ch7_mux_control),
+	SND_SOC_DAPM_MUX("HDMI_OUT_MUX", SND_SOC_NOPM, 0, 0,
+			 &hdmi_out_mux_control),
+	SND_SOC_DAPM_MUX("DPTX_OUT_MUX", SND_SOC_NOPM, 0, 0,
+			 &dptx_out_mux_control),
+
+	SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_tdm_bck_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_tdm_mck_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_tdm_bck_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_MCK_EN,
+			      SND_SOC_NOPM, 0, 0,
+			      mtk_tdm_mck_en_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("DPTX_VIRTUAL_OUT_MUX",
+			 SND_SOC_NOPM, 0, 0, &dptx_virtual_out_mux_control),
+	SND_SOC_DAPM_OUTPUT("DPTX_VIRTUAL_OUT"),
+};
+
+static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
+				    struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = sink;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = get_tdm_id_by_name(w->name);
+	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+	int cur_apll;
+
+	/* which apll */
+	cur_apll = mt8196_get_apll_by_name(afe, source->name);
+
+	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
+	{"HDMI_CH0_MUX", "CH0", "HDMI"},
+	{"HDMI_CH0_MUX", "CH1", "HDMI"},
+	{"HDMI_CH0_MUX", "CH2", "HDMI"},
+	{"HDMI_CH0_MUX", "CH3", "HDMI"},
+	{"HDMI_CH0_MUX", "CH4", "HDMI"},
+	{"HDMI_CH0_MUX", "CH5", "HDMI"},
+	{"HDMI_CH0_MUX", "CH6", "HDMI"},
+	{"HDMI_CH0_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH1_MUX", "CH0", "HDMI"},
+	{"HDMI_CH1_MUX", "CH1", "HDMI"},
+	{"HDMI_CH1_MUX", "CH2", "HDMI"},
+	{"HDMI_CH1_MUX", "CH3", "HDMI"},
+	{"HDMI_CH1_MUX", "CH4", "HDMI"},
+	{"HDMI_CH1_MUX", "CH5", "HDMI"},
+	{"HDMI_CH1_MUX", "CH6", "HDMI"},
+	{"HDMI_CH1_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH2_MUX", "CH0", "HDMI"},
+	{"HDMI_CH2_MUX", "CH1", "HDMI"},
+	{"HDMI_CH2_MUX", "CH2", "HDMI"},
+	{"HDMI_CH2_MUX", "CH3", "HDMI"},
+	{"HDMI_CH2_MUX", "CH4", "HDMI"},
+	{"HDMI_CH2_MUX", "CH5", "HDMI"},
+	{"HDMI_CH2_MUX", "CH6", "HDMI"},
+	{"HDMI_CH2_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH3_MUX", "CH0", "HDMI"},
+	{"HDMI_CH3_MUX", "CH1", "HDMI"},
+	{"HDMI_CH3_MUX", "CH2", "HDMI"},
+	{"HDMI_CH3_MUX", "CH3", "HDMI"},
+	{"HDMI_CH3_MUX", "CH4", "HDMI"},
+	{"HDMI_CH3_MUX", "CH5", "HDMI"},
+	{"HDMI_CH3_MUX", "CH6", "HDMI"},
+	{"HDMI_CH3_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH4_MUX", "CH0", "HDMI"},
+	{"HDMI_CH4_MUX", "CH1", "HDMI"},
+	{"HDMI_CH4_MUX", "CH2", "HDMI"},
+	{"HDMI_CH4_MUX", "CH3", "HDMI"},
+	{"HDMI_CH4_MUX", "CH4", "HDMI"},
+	{"HDMI_CH4_MUX", "CH5", "HDMI"},
+	{"HDMI_CH4_MUX", "CH6", "HDMI"},
+	{"HDMI_CH4_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH5_MUX", "CH0", "HDMI"},
+	{"HDMI_CH5_MUX", "CH1", "HDMI"},
+	{"HDMI_CH5_MUX", "CH2", "HDMI"},
+	{"HDMI_CH5_MUX", "CH3", "HDMI"},
+	{"HDMI_CH5_MUX", "CH4", "HDMI"},
+	{"HDMI_CH5_MUX", "CH5", "HDMI"},
+	{"HDMI_CH5_MUX", "CH6", "HDMI"},
+	{"HDMI_CH5_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH6_MUX", "CH0", "HDMI"},
+	{"HDMI_CH6_MUX", "CH1", "HDMI"},
+	{"HDMI_CH6_MUX", "CH2", "HDMI"},
+	{"HDMI_CH6_MUX", "CH3", "HDMI"},
+	{"HDMI_CH6_MUX", "CH4", "HDMI"},
+	{"HDMI_CH6_MUX", "CH5", "HDMI"},
+	{"HDMI_CH6_MUX", "CH6", "HDMI"},
+	{"HDMI_CH6_MUX", "CH7", "HDMI"},
+
+	{"HDMI_CH7_MUX", "CH0", "HDMI"},
+	{"HDMI_CH7_MUX", "CH1", "HDMI"},
+	{"HDMI_CH7_MUX", "CH2", "HDMI"},
+	{"HDMI_CH7_MUX", "CH3", "HDMI"},
+	{"HDMI_CH7_MUX", "CH4", "HDMI"},
+	{"HDMI_CH7_MUX", "CH5", "HDMI"},
+	{"HDMI_CH7_MUX", "CH6", "HDMI"},
+	{"HDMI_CH7_MUX", "CH7", "HDMI"},
+
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+	{"HDMI_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+	{"DPTX_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+	{"TDM", NULL, "HDMI_OUT_MUX"},
+	{"TDM", NULL, "TDM_BCK"},
+
+	{"TDM_DPTX", NULL, "DPTX_OUT_MUX"},
+	{"TDM_DPTX", NULL, "TDM_DPTX_BCK"},
+
+	{"TDM_BCK", NULL, "TDM_MCK"},
+	{"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"},
+	{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
+	{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
+	{"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
+	{"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
+
+	{"DPTX_VIRTUAL_OUT_MUX", "Connect", "TDM_DPTX"},
+	{"DPTX_VIRTUAL_OUT", NULL, "DPTX_VIRTUAL_OUT_MUX"},
+};
+
+/* dai ops */
+static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
+				struct mtk_afe_tdm_priv *tdm_priv,
+				int freq)
+{
+	int apll;
+	int apll_rate;
+
+	apll = mt8196_get_apll_by_rate(afe, freq);
+	apll_rate = mt8196_get_apll_rate(afe, apll);
+
+	if (freq > apll_rate) {
+		AUDIO_AEE("freq > apll rate");
+		return -EINVAL;
+	}
+
+	if (apll_rate % freq != 0) {
+		AUDIO_AEE("APLL cannot generate freq Hz");
+		return -EINVAL;
+	}
+
+	tdm_priv->mclk_rate = freq;
+	tdm_priv->mclk_apll = apll;
+
+	return 0;
+}
+
+static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	int tdm_id = dai->id;
+	struct mtk_afe_tdm_priv *tdm_priv;
+	unsigned int rate = params_rate(params);
+	unsigned int channels = params_channels(params);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int tdm_con = 0;
+
+	if (tdm_id >= MT8196_DAI_NUM || tdm_id < 0)
+		return -EINVAL;
+
+	tdm_priv = afe_priv->dai_priv[tdm_id];
+
+	/* calculate mclk_rate, if not set explicitly */
+	if (!tdm_priv->mclk_rate) {
+		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
+		mtk_dai_tdm_cal_mclk(afe,
+				     tdm_priv,
+				     tdm_priv->mclk_rate);
+	}
+
+	/* calculate bck */
+	tdm_priv->bck_rate = rate *
+			     channels *
+			     snd_pcm_format_physical_width(format);
+
+	if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
+		AUDIO_AEE("bck_rate > mclk_rate rate");
+
+	if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
+		AUDIO_AEE("bck cannot generate");
+
+	dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
+		 __func__,
+		 tdm_id, rate, channels, format,
+		 tdm_priv->mclk_rate, tdm_priv->bck_rate);
+
+	/* set tdm */
+	tdm_con = 0 << BCK_INVERSE_SFT;
+	tdm_con |= 0 << LRCK_INVERSE_SFT;
+	tdm_con |= 0 << DELAY_DATA_SFT;
+	tdm_con |= 1 << LEFT_ALIGN_SFT;
+	tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
+	tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT;
+	tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
+	tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
+	regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
+
+	/* set dptx */
+	if (tdm_id == MT8196_DAI_TDM_DPTX) {
+		regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+				   DPTX_CHANNEL_ENABLE_MASK_SFT,
+				   get_dptx_ch_enable_mask(channels) <<
+				   DPTX_CHANNEL_ENABLE_SFT);
+		regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+				   DPTX_CHANNEL_NUMBER_MASK_SFT,
+				   get_dptx_ch(channels) <<
+				   DPTX_CHANNEL_NUMBER_SFT);
+		regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+				   DPTX_16BIT_MASK_SFT,
+				   get_dptx_wlen(format) << DPTX_16BIT_SFT);
+	}
+		switch (channels) {
+		case 1:
+		case 2:
+			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+			break;
+		case 3:
+		case 4:
+			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+			break;
+		case 5:
+		case 6:
+			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
+			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+			break;
+		case 7:
+		case 8:
+			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
+			tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
+			break;
+		default:
+			tdm_con = 0;
+		}
+	regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
+	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+			   HDMI_CH_NUM_MASK_SFT,
+			   channels << HDMI_CH_NUM_SFT);
+
+	return 0;
+}
+
+static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
+			       int cmd,
+			       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	int tdm_id = dai->id;
+
+	dev_dbg(afe->dev, "%s(), cmd %d, tdm_id %d\n", __func__, cmd, tdm_id);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* enable Out control */
+		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+				   HDMI_OUT_ON_MASK_SFT,
+				   0x1 << HDMI_OUT_ON_SFT);
+
+		/* enable dptx */
+		if (tdm_id == MT8196_DAI_TDM_DPTX) {
+			regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+					   DPTX_ON_MASK_SFT, 0x1 <<
+					   DPTX_ON_SFT);
+		}
+
+		/* enable tdm */
+		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
+				   TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		/* disable tdm */
+		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
+				   TDM_EN_MASK_SFT, 0);
+
+		/* disable dptx */
+		if (tdm_id == MT8196_DAI_TDM_DPTX) {
+			regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+					   DPTX_ON_MASK_SFT, 0);
+		}
+
+		/* disable Out control */
+		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+				   HDMI_OUT_ON_MASK_SFT, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_tdm_priv *tdm_priv;
+
+	if (dai->id >= MT8196_DAI_NUM || dai->id < 0)
+		return -EINVAL;
+
+	tdm_priv = afe_priv->dai_priv[dai->id];
+
+	if (!tdm_priv) {
+		AUDIO_AEE("tdm_priv == NULL");
+		return -EINVAL;
+	}
+
+	if (dir != SND_SOC_CLOCK_OUT) {
+		AUDIO_AEE("dir != SND_SOC_CLOCK_OUT");
+		return -EINVAL;
+	}
+
+	dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);
+
+	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
+}
+
+static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
+	.hw_params = mtk_dai_tdm_hw_params,
+	.trigger = mtk_dai_tdm_trigger,
+	.set_sysclk = mtk_dai_tdm_set_sysclk,
+};
+
+/* dai driver */
+#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+		       SNDRV_PCM_RATE_88200 |\
+		       SNDRV_PCM_RATE_96000 |\
+		       SNDRV_PCM_RATE_176400 |\
+		       SNDRV_PCM_RATE_192000)
+
+#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE |\
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
+	{
+		.name = "TDM",
+		.id = MT8196_DAI_TDM,
+		.playback = {
+			.stream_name = "TDM",
+			.channels_min = 2,
+			.channels_max = 8,
+			.rates = MTK_TDM_RATES,
+			.formats = MTK_TDM_FORMATS,
+		},
+		.ops = &mtk_dai_tdm_ops,
+	},
+	{
+		.name = "TDM_DPTX",
+		.id = MT8196_DAI_TDM_DPTX,
+		.playback = {
+			.stream_name = "TDM_DPTX",
+			.channels_min = 2,
+			.channels_max = 8,
+			.rates = MTK_TDM_RATES,
+			.formats = MTK_TDM_FORMATS,
+		},
+		.ops = &mtk_dai_tdm_ops,
+	},
+};
+
+static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe,
+						   int id)
+{
+	struct mtk_afe_tdm_priv *tdm_priv;
+
+	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
+				GFP_KERNEL);
+	if (!tdm_priv)
+		return NULL;
+
+	if (id == MT8196_DAI_TDM_DPTX)
+		tdm_priv->mclk_multiple = 256;
+	else
+		tdm_priv->mclk_multiple = 128;
+
+	tdm_priv->bck_id = MT8196_TDMOUT_BCK;
+	tdm_priv->mclk_id = MT8196_TDMOUT_MCK;
+
+	return tdm_priv;
+}
+
+int mt8196_dai_tdm_register(struct mtk_base_afe *afe)
+{
+	struct mt8196_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv;
+	struct mtk_base_afe_dai *dai;
+
+	dev_dbg(afe->dev, "%s() successfully start\n", __func__);
+
+	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	list_add(&dai->list, &afe->sub_dais);
+
+	dai->dai_drivers = mtk_dai_tdm_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
+
+	dai->dapm_widgets = mtk_dai_tdm_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
+	dai->dapm_routes = mtk_dai_tdm_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
+
+	tdm_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM);
+	if (!tdm_priv)
+		return -ENOMEM;
+
+	tdm_dptx_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM_DPTX);
+	if (!tdm_dptx_priv)
+		return -ENOMEM;
+
+	afe_priv->dai_priv[MT8196_DAI_TDM] = tdm_priv;
+	afe_priv->dai_priv[MT8196_DAI_TDM_DPTX] = tdm_dptx_priv;
+
+	return 0;
+}
+
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:38 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:38 +0800
Subject: [PATCH 12/14] dt-bindings: mediatek: mt8196: add audio AFE document
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-13-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add mt8196 audio AFE document.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 .../bindings/sound/mediatek,mt8196-afe.yaml   | 259 ++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
new file mode 100644
index 000000000000..59f8fdf3167c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
@@ -0,0 +1,259 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8196-afe.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Audio Front End PCM controller for MT8196
+
+maintainers:
+  - Darren Ye <darren.ye at mediatek.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8196-afe-pcm
+
+  reg:
+    maxItems: 1
+
+  "#sound-dai-cells":
+    const: 0
+
+  clocks:
+    items:
+      - description: audio hopping clock
+      - description: audio f26m clock
+      - description: audio ul0 adc clock
+      - description: audio ul0 adc hires clock
+      - description: audio ul1 adc clock
+      - description: audio ul1 adc hires clock
+      - description: audio apll1 clock
+      - description: audio apll2 clock
+      - description: audio apll tuner1 clock
+      - description: audio apll tuner2 clock
+      - description: vlp mux audio int
+      - description: vlp mux aud engen1
+      - description: vlp mux aud engen2
+      - description: vlp mux audio h
+      - description: vlp clock 26m
+      - description: ck mainpll d4 d4
+      - description: ck mux aud 1
+      - description: ck apll1
+      - description: ck mux aud 2
+      - description: ck apll2
+      - description: ck apll1 d4
+      - description: ck apll2 d4
+      - description: ck i2sin0 m sel
+      - description: ck i2sin1 m sel
+      - description: ck fmi2s m sel
+      - description: ck tdmout m sel
+      - description: ck apll12 div i2sin0
+      - description: ck apll12 div i2sin1
+      - description: ck apll12 div fmi2s
+      - description: ck apll12 div tdmout m
+      - description: ck apll12 div tdmout b
+      - description: ck adsp sel
+      - description: ck clock 26m
+
+  clock-names:
+    items:
+      - const: aud_hopping_clk
+      - const: aud_f26m_clk
+      - const: aud_ul0_adc_clk
+      - const: aud_ul0_adc_hires_clk
+      - const: aud_ul1_adc_clk
+      - const: aud_ul1_adc_hires_clk
+      - const: aud_apll1_clk
+      - const: aud_apll2_clk
+      - const: aud_apll_tuner1_clk
+      - const: aud_apll_tuner2_clk
+      - const: vlp_mux_audio_int
+      - const: vlp_mux_aud_eng1
+      - const: vlp_mux_aud_eng2
+      - const: vlp_mux_audio_h
+      - const: vlp_clk26m_clk
+      - const: ck_mainpll_d4_d4
+      - const: ck_mux_aud_1
+      - const: ck_apll1_ck
+      - const: ck_mux_aud_2
+      - const: ck_apll2_ck
+      - const: ck_apll1_d4
+      - const: ck_apll2_d4
+      - const: ck_i2sin0_m_sel
+      - const: ck_i2sin1_m_sel
+      - const: ck_fmi2s_m_sel
+      - const: ck_tdmout_m_sel
+      - const: ck_apll12_div_i2sin0
+      - const: ck_apll12_div_i2sin1
+      - const: ck_apll12_div_fmi2s
+      - const: ck_apll12_div_tdmout_m
+      - const: ck_apll12_div_tdmout_b
+      - const: ck_adsp_sel
+      - const: ck_clk26m_clk
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  cksys:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the cksys clock controller.
+
+  vlpcksys:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the vlpcksys clock controller.
+
+  memory-region:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the reserved memory region for AFE DMA.
+
+  pinctrl-names:
+    items:
+      - const: default
+
+  pinctrl-0:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the pin control group for default state.
+
+  mediatek,etdm-out-ch:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Number of ETDM output channels.
+    enum: [2]
+
+  mediatek,etdm-in-ch:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Number of ETDM input channels.
+    enum: [2]
+
+  mediatek,etdm-out-sync:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: ETDM output synchronization.
+    enum: [0, 1]
+
+  mediatek,etdm-in-sync:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: ETDM input synchronization.
+    enum: [0, 1]
+
+  mediatek,etdm-ip-mode:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: ETDM IP mode.
+    enum: [0, 1]
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - power-domains
+  - cksys
+  - vlpcksys
+  - memory-region
+  - pinctrl-names
+  - pinctrl-0
+  - mediatek,etdm-out-ch
+  - mediatek,etdm-in-ch
+  - mediatek,etdm-out-sync
+  - mediatek,etdm-in-sync
+  - mediatek,etdm-ip-mode
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt8196-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/mt8196-power.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        afe: mt8196-afe-pcm at 1a110000 {
+            compatible = "mediatek,mt8196-afe-pcm";
+            reg = <0 0x1a110000 0 0x9000>;
+            interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH 0>;
+            cksys = <&cksys_clk>;
+            vlpcksys = <&vlp_cksys_clk>;
+            power-domains = <&scpsys MT8196_POWER_DOMAIN_AUDIO>;
+            memory-region = <&afe_dma_mem_reserved>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&aud_pins_default>;
+            /* Only for ETDM in/out 4 */
+            mediatek,etdm-out-ch = <2>;
+            mediatek,etdm-in-ch = <2>;
+            mediatek,etdm-out-sync = <0>;
+            mediatek,etdm-in-sync = <1>;
+            mediatek,etdm-ip-mode = <0>;
+            clocks = <&afe_clk CLK_AFE_AUDIO_HOPPING_AFE>,
+                     <&afe_clk CLK_AFE_AUDIO_F26M_AFE>,
+                     <&afe_clk CLK_AFE_UL0_ADC_AFE>,
+                     <&afe_clk CLK_AFE_UL0_ADC_HIRES_AFE>,
+                     <&afe_clk CLK_AFE_UL1_ADC_AFE>,
+                     <&afe_clk CLK_AFE_UL1_ADC_HIRES_AFE>,
+                     <&afe_clk CLK_AFE_APLL1_AFE>,
+                     <&afe_clk CLK_AFE_APLL2_AFE>,
+                     <&afe_clk CLK_AFE_APLL_TUNER1_AFE>,
+                     <&afe_clk CLK_AFE_APLL_TUNER2_AFE>,
+                     <&vlp_cksys_clk CLK_VLP_CK_AUD_INTBUS_SEL>,
+                     <&vlp_cksys_clk CLK_VLP_CK_AUD_ENGEN1_SEL>,
+                     <&vlp_cksys_clk CLK_VLP_CK_AUD_ENGEN2_SEL>,
+                     <&vlp_cksys_clk CLK_VLP_CK_AUDIO_H_SEL>,
+                     <&vlp_cksys_clk CLK_VLP_CK_CLKSQ>,
+                     <&cksys_clk CLK_CK_MAINPLL_D4_D4>,
+                     <&cksys_clk CLK_CK_AUD_1_SEL>,
+                     <&cksys_clk CLK_CK_APLL1>,
+                     <&cksys_clk CLK_CK_AUD_2_SEL>,
+                     <&cksys_clk CLK_CK_APLL2>,
+                     <&cksys_clk CLK_CK_APLL1_D4>,
+                     <&cksys_clk CLK_CK_APLL2_D4>,
+                     <&cksys_clk CLK_CK_APLL_I2SIN0_MCK_SEL>,
+                     <&cksys_clk CLK_CK_APLL_I2SIN1_MCK_SEL>,
+                     <&cksys_clk CLK_CK_APLL_FMI2S_MCK_SEL>,
+                     <&cksys_clk CLK_CK_APLL_TDMOUT_MCK_SEL>,
+                     <&cksys_clk CLK_CK_APLL12_CK_DIV_I2SIN0>,
+                     <&cksys_clk CLK_CK_APLL12_CK_DIV_I2SIN1>,
+                     <&cksys_clk CLK_CK_APLL12_CK_DIV_FMI2S>,
+                     <&cksys_clk CLK_CK_APLL12_CK_DIV_TDMOUT_M>,
+                     <&cksys_clk CLK_CK_APLL12_CK_DIV_TDMOUT_B>,
+                     <&cksys_clk CLK_CK_ADSP_SEL>,
+                     <&cksys_clk CLK_CK_TCK_26M_MX9>;
+            clock-names = "aud_hopping_clk",
+                          "aud_f26m_clk",
+                          "aud_ul0_adc_clk",
+                          "aud_ul0_adc_hires_clk",
+                          "aud_ul1_adc_clk",
+                          "aud_ul1_adc_hires_clk",
+                          "aud_apll1_clk",
+                          "aud_apll2_clk",
+                          "aud_apll_tuner1_clk",
+                          "aud_apll_tuner2_clk",
+                          "vlp_mux_audio_int",
+                          "vlp_mux_aud_eng1",
+                          "vlp_mux_aud_eng2",
+                          "vlp_mux_audio_h",
+                          "vlp_clk26m_clk",
+                          "ck_mainpll_d4_d4",
+                          "ck_mux_aud_1",
+                          "ck_apll1_ck",
+                          "ck_mux_aud_2",
+                          "ck_apll2_ck",
+                          "ck_apll1_d4",
+                          "ck_apll2_d4",
+                          "ck_i2sin0_m_sel",
+                          "ck_i2sin1_m_sel",
+                          "ck_fmi2s_m_sel",
+                          "ck_tdmout_m_sel",
+                          "ck_apll12_div_i2sin0",
+                          "ck_apll12_div_i2sin1",
+                          "ck_apll12_div_fmi2s",
+                          "ck_apll12_div_tdmout_m",
+                          "ck_apll12_div_tdmout_b",
+                          "ck_adsp_sel",
+                          "ck_clk26m_clk";
+        };
+    };
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:40 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:40 +0800
Subject: [PATCH 14/14] dt-bindings: mediatek: mt8196: add mt8196-mt6681 document
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-15-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add document for mt8196 board with mt6681.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 .../sound/mediatek,mt8196-mt6681.yaml         | 122 ++++++++++++++++++
 1 file changed, 122 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
new file mode 100644
index 000000000000..b144ba748c23
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
@@ -0,0 +1,122 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8196-mt6681.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT8196 ASoC sound card
+
+maintainers:
+  - Darren Ye <darren.ye at mediatek.com>
+
+allOf:
+  - $ref: sound-card-common.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - mediatek,mt8196-mt6681-sound
+          - mediatek,mt8196-nau8825-sound
+          - mediatek,mt8196-rt5682s-sound
+          - mediatek,mt8196-rt5650-sound
+      - items:
+          - const: mediatek,mt8196-mt6681-sound
+          - const: mediatek,mt8196-nau8825-sound
+
+  audio-routing:
+    description:
+      Valid names could be the input or output widgets of audio components,
+      power supplies, MicBias of codec and the software switch.
+
+  mediatek,platform:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of MT8188 ASoC platform.
+
+  mediatek,adsp:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      The phandle of the MT8188 ADSP platform, which is the optional Audio DSP
+      hardware that provides additional audio functionalities if present.
+      The AFE will link to ADSP when the phandle is provided.
+
+patternProperties:
+  "^dai-link-[0-9]+$":
+    type: object
+    description:
+      Container for dai-link level properties and CODEC sub-nodes.
+
+    properties:
+      link-name:
+        description:
+          This property corresponds to the name of the BE dai-link to which
+          we are going to update parameters in this node.
+        items:
+          enum:
+            - TDM_DPTX_BE
+            - I2SOUT6_BE
+            - I2SIN6_BE
+            - I2SOUT4_BE
+            - I2SOUT3_BE
+
+      codec:
+        description: Holds subnode which indicates codec dai.
+        type: object
+        additionalProperties: false
+        properties:
+          sound-dai:
+            minItems: 1
+            maxItems: 2
+        required:
+          - sound-dai
+
+      dai-format:
+        description: audio format.
+        items:
+          enum:
+            - i2s
+            - right_j
+            - left_j
+            - dsp_a
+            - dsp_b
+
+      mediatek,clk-provider:
+        $ref: /schemas/types.yaml#/definitions/string
+        description: Indicates dai-link clock master.
+        items:
+          enum:
+            - cpu
+            - codec
+
+    additionalProperties: false
+
+    required:
+      - link-name
+
+unevaluatedProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+
+examples:
+  - |
+    sound {
+        compatible = "mediatek,mt8196-mt6681-sound";
+        model = "mt8196-mt6681";
+        mediatek,platform = <&afe>;
+        audio-routing = "I2SOUT4", "I2SIN4_GPIO",
+                        "I2SOUT4", "I2OUT4_GPIO",
+                        "I2SOUT6", "I2SIN6_GPIO",
+                        "I2SOUT6", "I2SOUT6_GPIO";
+
+        dai-link-0 {
+            link-name = "I2SOUT6_BE";
+            dai-format = "i2s";
+            mediatek,clk-provider = "cpu";
+            codec {
+                sound-dai = <&nau8825>;
+            };
+        };
+    };
+
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:39 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:39 +0800
Subject: [PATCH 13/14] ASoC: mediatek: mt8196: add machine driver with mt6681
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-14-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Add support for mt8196 board with mt6681.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/Kconfig                |  20 +
 sound/soc/mediatek/mt8196/Makefile        |   2 +
 sound/soc/mediatek/mt8196/mt8196-mt6681.c | 879 ++++++++++++++++++++++
 3 files changed, 901 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8196/mt8196-mt6681.c

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 606f221e238c..55f9397fce91 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -214,6 +214,26 @@ config SND_SOC_MT8196
 	  Select Y if you have such device.
 	  If unsure select "N".
 
+config SND_SOC_MT8196_MT6681
+	tristate "ASoc Audio driver for MT8196 with I2S codec"
+	depends on SND_SOC_MT8196
+	depends on I2C
+	select SND_SOC_HDMI_CODEC
+	select SND_SOC_DMIC
+	select SND_SOC_NAU8315
+	select SND_SOC_NAU8825
+	select SND_SOC_RT5645
+	select SND_SOC_RT5682_I2C
+	select SND_SOC_RT5682S
+	select SND_SOC_TAS2781_COMLIB
+	select SND_SOC_TAS2781_FMWLIB
+	select SND_SOC_TAS2781_I2C
+	help
+	  This adds support for ASoC machine driver for MediaTek MT8196
+	  boards with the other I2S audio codecs.
+	  Select Y if you have such device.
+	  If unsure select "N".
+
 config SND_SOC_MTK_BTCVSD
 	tristate "ALSA BT SCO CVSD/MSBC Driver"
 	help
diff --git a/sound/soc/mediatek/mt8196/Makefile b/sound/soc/mediatek/mt8196/Makefile
index 312cdfb5205b..ba5922736a59 100644
--- a/sound/soc/mediatek/mt8196/Makefile
+++ b/sound/soc/mediatek/mt8196/Makefile
@@ -15,3 +15,5 @@ snd-soc-mt8196-afe-objs += \
 	mt8196-dai-tdm.o \
 	mt8196-afe-cm.o
 
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8196_MT6681) += mt8196-mt6681.o
diff --git a/sound/soc/mediatek/mt8196/mt8196-mt6681.c b/sound/soc/mediatek/mt8196/mt8196-mt6681.c
new file mode 100644
index 000000000000..9053e96fd193
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-mt6681.c
@@ -0,0 +1,879 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  mt8196-mt6681.c  --  mt8196 mt6681 ALSA SoC machine driver
+ *
+ *  Copyright (c) 2023 MediaTek Inc.
+ *  Author: Darren Ye <darren.ye at mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <linux/input.h>
+#include <linux/of_device.h>
+
+#include "mtk-afe-platform-driver.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-gpio.h"
+
+#include "../../codecs/nau8825.h"
+#include "../../codecs/rt5682s.h"
+
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-soundcard-driver.h"
+#include "../common/mtk-dsp-sof-common.h"
+#include "../common/mtk-soc-card.h"
+
+#define NAU8825_HS_PRESENT	BIT(0)
+#define RT5682S_HS_PRESENT	BIT(1)
+#define RT5650_HS_PRESENT	BIT(2)
+
+/*
+ * Nau88l25
+ */
+#define NAU8825_CODEC_DAI  "nau8825-hifi"
+
+/*
+ * Rt5682s
+ */
+#define RT5682S_CODEC_DAI     "rt5682s-aif1"
+
+/*
+ * Rt5650
+ */
+#define RT5650_CODEC_DAI     "rt5645-aif1"
+
+#define SOF_DMA_DL1 "SOF_DMA_DL1"
+#define SOF_DMA_DL_24CH "SOF_DMA_DL_24CH"
+#define SOF_DMA_UL0 "SOF_DMA_UL0"
+#define SOF_DMA_UL1 "SOF_DMA_UL1"
+#define SOF_DMA_UL2 "SOF_DMA_UL2"
+
+enum mt8196_jacks {
+	MT8196_JACK_HEADSET,
+	MT8196_JACK_DP,
+	MT8196_JACK_HDMI,
+	MT8196_JACK_MAX,
+};
+
+static struct snd_soc_jack_pin mt8196_dp_jack_pins[] = {
+	{
+		.pin = "DP",
+		.mask = SND_JACK_LINEOUT,
+	},
+};
+
+static struct snd_soc_jack_pin mt8196_hdmi_jack_pins[] = {
+	{
+		.pin = "HDMI",
+		.mask = SND_JACK_LINEOUT,
+	},
+};
+
+static struct snd_soc_jack_pin nau8825_jack_pins[] = {
+	{
+		.pin    = "Headphone Jack",
+		.mask   = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin    = "Headset Mic",
+		.mask   = SND_JACK_MICROPHONE,
+	},
+};
+
+static const struct snd_kcontrol_new mt8196_dumb_spk_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Ext Spk"),
+};
+
+static const struct snd_soc_dapm_widget mt8196_dumb_spk_widgets[] = {
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_widget mt8196_nau8825_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_SINK("DP"),
+};
+
+static const struct snd_kcontrol_new mt8196_nau8825_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+/*
+ * if need additional control for the ext spk amp that is connected
+ * after Lineout Buffer / HP Buffer on the codec, put the control in
+ * mt8196_mt6681_spk_amp_event()
+ */
+#define EXT_SPK_AMP_W_NAME "Ext_Speaker_Amp"
+
+static struct snd_soc_card mt8196_mt6681_soc_card;
+
+static const struct snd_soc_dapm_widget mt8196_mt6681_widgets[] = {
+};
+
+static const struct snd_soc_dapm_route mt8196_mt6681_routes[] = {
+};
+
+static const struct snd_kcontrol_new mt8196_mt6681_controls[] = {
+	SOC_DAPM_PIN_SWITCH(EXT_SPK_AMP_W_NAME),
+};
+
+/*
+ * define mtk_spk_i2s_mck node in dts when need mclk,
+ * BE i2s need assign snd_soc_ops = mt8196_mt6681_i2s_ops
+ */
+static int mt8196_mt6681_i2s_hw_params(struct snd_pcm_substream *substream,
+				       struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	unsigned int rate = params_rate(params);
+	unsigned int mclk_fs_ratio = 128;
+	unsigned int mclk_fs = rate * mclk_fs_ratio;
+	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+
+	return snd_soc_dai_set_sysclk(cpu_dai,
+				      0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_mt6681_i2s_ops = {
+	.hw_params = mt8196_mt6681_i2s_hw_params,
+};
+
+static int mt8196_dptx_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	unsigned int rate = params_rate(params);
+	unsigned int mclk_fs_ratio = 256;
+	unsigned int mclk_fs = rate * mclk_fs_ratio;
+	struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
+
+	return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_dptx_ops = {
+	.hw_params = mt8196_dptx_hw_params,
+};
+
+static int mt8196_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				       struct snd_pcm_hw_params *params)
+{
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s format to 32bit, clean param mask first */
+	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+			     0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+	params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
+
+	return 0;
+}
+
+static int mt8196_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				      struct snd_pcm_hw_params *params)
+{
+	dev_info(rtd->dev, "%s(), fix format to 32bit\n", __func__);
+
+	/* fix BE i2s format to 32bit, clean param mask first */
+	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+			     0, SNDRV_PCM_FORMAT_LAST);
+
+	params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
+	return 0;
+}
+
+static int mt8196_sof_be_hw_params(struct snd_pcm_substream *substream,
+				   struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct snd_soc_component *cmpnt_afe = NULL;
+	struct snd_soc_pcm_runtime *runtime;
+
+	/* find afe component */
+	for_each_card_rtds(rtd->card, runtime) {
+		cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME);
+		if (cmpnt_afe) {
+			dev_info(rtd->dev, "component->name: %s\n", cmpnt_afe->name);
+			break;
+		}
+	}
+
+	if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) {
+		dev_err(rtd->dev, "afe pm runtime is not active!!\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_ops mt8196_sof_be_ops = {
+	.hw_params = mt8196_sof_be_hw_params,
+};
+
+static const struct sof_conn_stream g_sof_conn_streams[] = {
+	{
+		.sof_link = "AFE_SOF_DL1",
+		.sof_dma = SOF_DMA_DL1,
+		.stream_dir = SNDRV_PCM_STREAM_PLAYBACK
+	},
+	{
+		.sof_link = "AFE_SOF_DL_24CH",
+		.sof_dma = SOF_DMA_DL_24CH,
+		.stream_dir = SNDRV_PCM_STREAM_PLAYBACK
+	},
+	{
+		.sof_link = "AFE_SOF_UL0",
+		.sof_dma = SOF_DMA_UL0,
+		.stream_dir = SNDRV_PCM_STREAM_CAPTURE
+	},
+	{
+		.sof_link = "AFE_SOF_UL1",
+		.sof_dma = SOF_DMA_UL1,
+		.stream_dir = SNDRV_PCM_STREAM_CAPTURE
+	},
+	{
+		.sof_link = "AFE_SOF_UL2",
+		.sof_dma = SOF_DMA_UL2,
+		.stream_dir = SNDRV_PCM_STREAM_CAPTURE
+	},
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(playback1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback_24ch,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL_24CH")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture0,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL0")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture2,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback_hdmi,
+		     DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback2,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture_cm0,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL_CM0")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+/* BE */
+SND_SOC_DAILINK_DEFS(ap_dmic,
+		     DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(ap_dmic_ch34,
+		     DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(ap_dmic_multich,
+		     DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_MULTICH")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sin6,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2SIN6")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout3,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT3")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout4,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT4")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout6,
+		     DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT6")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(tdm_dptx,
+		     DAILINK_COMP_ARRAY(COMP_CPU("TDM_DPTX")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_DL_24CH,
+		     DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL_24CH")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_DL1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL0,
+		     DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL0")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL2,
+		     DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt8196_mt6681_dai_links[] = {
+	/*
+	 * The SOF topology expects PCM streams 0~4 to be available
+	 * for the SOF PCM streams. Put the SOF BE definitions here
+	 * so that the PCM device numbers are skipped over.
+	 * (BE dailinks do not have PCM devices created.)
+	 */
+	{
+		.name = "AFE_SOF_DL_24CH",
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ops = &mt8196_sof_be_ops,
+		SND_SOC_DAILINK_REG(AFE_SOF_DL_24CH),
+	},
+	{
+		.name = "AFE_SOF_DL1",
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ops = &mt8196_sof_be_ops,
+		SND_SOC_DAILINK_REG(AFE_SOF_DL1),
+	},
+	{
+		.name = "AFE_SOF_UL0",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ops = &mt8196_sof_be_ops,
+		SND_SOC_DAILINK_REG(AFE_SOF_UL0),
+	},
+	{
+		.name = "AFE_SOF_UL1",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ops = &mt8196_sof_be_ops,
+		SND_SOC_DAILINK_REG(AFE_SOF_UL1),
+	},
+	{
+		.name = "AFE_SOF_UL2",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ops = &mt8196_sof_be_ops,
+		SND_SOC_DAILINK_REG(AFE_SOF_UL2),
+	},
+	/* Front End DAI links */
+	{
+		.name = "HDMI_FE",
+		.stream_name = "HDMI Playback",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+			    SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.playback_only = 1,
+		SND_SOC_DAILINK_REG(playback_hdmi),
+	},
+	{
+		.name = "DL2_FE",
+		.stream_name = "DL2 Playback",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+			    SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.playback_only = 1,
+		SND_SOC_DAILINK_REG(playback2),
+	},
+	{
+		.name = "UL_CM0_FE",
+		.stream_name = "UL_CM0 Capture",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+			    SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.capture_only = 1,
+		SND_SOC_DAILINK_REG(capture_cm0),
+	},
+	{
+		.name = "DL_24CH_FE",
+		.stream_name = "DL_24CH Playback",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+				SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.playback_only = 1,
+		SND_SOC_DAILINK_REG(playback_24ch),
+	},
+	{
+		.name = "DL1_FE",
+		.stream_name = "DL1 Playback",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+				SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.playback_only = 1,
+		SND_SOC_DAILINK_REG(playback1),
+	},
+	{
+		.name = "UL0_FE",
+		.stream_name = "UL0 Capture",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+				SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.capture_only = 1,
+		SND_SOC_DAILINK_REG(capture0),
+	},
+	{
+		.name = "UL1_FE",
+		.stream_name = "UL1 Capture",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+				SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.capture_only = 1,
+		SND_SOC_DAILINK_REG(capture1),
+	},
+	{
+		.name = "UL2_FE",
+		.stream_name = "UL2 Capture",
+		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+				SND_SOC_DPCM_TRIGGER_PRE},
+		.dynamic = 1,
+		.capture_only = 1,
+		SND_SOC_DAILINK_REG(capture2),
+	},
+	/* Back End DAI links */
+	{
+		.name = "I2SIN6_BE",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
+			| SND_SOC_DAIFMT_GATED,
+		.ops = &mt8196_mt6681_i2s_ops,
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		.be_hw_params_fixup = mt8196_i2s_hw_params_fixup,
+		SND_SOC_DAILINK_REG(i2sin6),
+	},
+	{
+		.name = "I2SOUT4_BE",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
+			| SND_SOC_DAIFMT_GATED,
+		.ops = &mt8196_mt6681_i2s_ops,
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.be_hw_params_fixup = mt8196_i2s_hw_params_fixup,
+		SND_SOC_DAILINK_REG(i2sout4),
+	},
+	{
+		.name = "I2SOUT6_BE",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
+			| SND_SOC_DAIFMT_GATED,
+		.ops = &mt8196_mt6681_i2s_ops,
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ignore_suspend = 1,
+		.be_hw_params_fixup = mt8196_i2s_hw_params_fixup,
+		SND_SOC_DAILINK_REG(i2sout6),
+	},
+	{
+		.name = "AP_DMIC_BE",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(ap_dmic),
+	},
+	{
+		.name = "AP_DMIC_CH34_BE",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(ap_dmic_ch34),
+	},
+	{
+		.name = "AP_DMIC_MULTICH_BE",
+		.no_pcm = 1,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(ap_dmic_multich),
+	},
+	{
+		.name = "TDM_DPTX_BE",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
+			| SND_SOC_DAIFMT_GATED,
+		.ops = &mt8196_dptx_ops,
+		.be_hw_params_fixup = mt8196_dptx_hw_params_fixup,
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tdm_dptx),
+	},
+	{
+		.name = "I2SOUT3_BE",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
+			| SND_SOC_DAIFMT_GATED,
+		.ops = &mt8196_mt6681_i2s_ops,
+		.no_pcm = 1,
+		.playback_only = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(i2sout3),
+	},
+};
+
+static int mt8196_dumb_amp_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	int ret = 0;
+
+	ret = snd_soc_dapm_new_controls(&card->dapm, mt8196_dumb_spk_widgets,
+					ARRAY_SIZE(mt8196_dumb_spk_widgets));
+	if (ret) {
+		dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_add_card_controls(card, mt8196_dumb_spk_controls,
+					ARRAY_SIZE(mt8196_dumb_spk_controls));
+	if (ret) {
+		dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt8196_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_DP];
+	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+	int ret = 0;
+
+	ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT,
+					 jack, mt8196_dp_jack_pins,
+					 ARRAY_SIZE(mt8196_dp_jack_pins));
+	if (ret) {
+		dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = snd_soc_component_set_jack(component, jack, NULL);
+	if (ret) {
+		dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
+			__func__, component->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt8196_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HDMI];
+	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+	int ret = 0;
+
+	ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
+					 jack, mt8196_hdmi_jack_pins,
+					 ARRAY_SIZE(mt8196_hdmi_jack_pins));
+	if (ret) {
+		dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = snd_soc_component_set_jack(component, jack, NULL);
+	if (ret) {
+		dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
+			__func__, component->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt8196_headset_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
+	struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HEADSET];
+	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+	int ret;
+	int type;
+
+	ret = snd_soc_dapm_new_controls(&card->dapm, mt8196_nau8825_widgets,
+					ARRAY_SIZE(mt8196_nau8825_widgets));
+	if (ret) {
+		dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_add_card_controls(card, mt8196_nau8825_controls,
+					ARRAY_SIZE(mt8196_nau8825_controls));
+	if (ret) {
+		dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
+					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+					 SND_JACK_BTN_3,
+					 jack,
+					 nau8825_jack_pins,
+					 ARRAY_SIZE(nau8825_jack_pins));
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+	type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3;
+	ret = snd_soc_component_set_jack(component, jack, (void *)&type);
+
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+};
+
+static void mt8196_headset_codec_exit(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+
+	snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+static int mt8196_nau8825_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+	unsigned int rate = params_rate(params);
+	unsigned int bit_width = params_width(params);
+	int clk_freq, ret;
+
+	clk_freq = rate * 2 * bit_width;
+
+	/* Configure clock for codec */
+	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret);
+		return ret;
+	}
+
+	/* Configure pll for codec */
+	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq,
+				  params_rate(params) * 256);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_ops mt8196_nau8825_ops = {
+	.hw_params = mt8196_nau8825_hw_params,
+};
+
+static int mt8196_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+	unsigned int rate = params_rate(params);
+	int bitwidth;
+	int ret;
+
+	bitwidth = snd_pcm_format_width(params_format(params));
+	if (bitwidth < 0) {
+		dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+		return bitwidth;
+	}
+
+	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+	if (ret) {
+		dev_err(card->dev, "failed to set tdm slot\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1,
+				  rate * 32, rate * 512);
+	if (ret) {
+		dev_err(card->dev, "failed to set pll\n");
+		return ret;
+	}
+
+	dev_info(card->dev, "%s set mclk rate: %d\n", __func__, rate * 512);
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_MCLK,
+				     rate * 512, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(card->dev, "failed to set sysclk\n");
+		return ret;
+	}
+
+	return snd_soc_dai_set_sysclk(cpu_dai, 0, rate * 512,
+				      SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_rt5682s_i2s_ops = {
+	.hw_params = mt8196_rt5682s_i2s_hw_params,
+};
+
+static int mt8196_mt6681_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
+{
+	struct snd_soc_card *card = soc_card_data->card_data->card;
+	struct snd_soc_dai_link *dai_link;
+	bool init_nau8825 = false;
+	bool init_rt5682s = false;
+	bool init_rt5650 = false;
+	bool init_dumb = false;
+	int i;
+
+	dev_info(card->dev, "%s(), legacy: %d\n", __func__, legacy);
+
+	for_each_card_prelinks(card, i, dai_link) {
+		if (strcmp(dai_link->name, "TDM_DPTX_BE") == 0) {
+			if (dai_link->num_codecs &&
+			    strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+				dai_link->init = mt8196_dptx_codec_init;
+		} else if (strcmp(dai_link->name, "I2SOUT3_BE") == 0) {
+			if (dai_link->num_codecs &&
+			    strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+				dai_link->init = mt8196_hdmi_codec_init;
+		} else if (strcmp(dai_link->name, "I2SOUT6_BE") == 0 ||
+			   strcmp(dai_link->name, "I2SIN6_BE") == 0) {
+			if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) {
+				dai_link->ops = &mt8196_nau8825_ops;
+				if (!init_nau8825) {
+					dai_link->init = mt8196_headset_codec_init;
+					dai_link->exit = mt8196_headset_codec_exit;
+					init_nau8825 = true;
+				}
+			} else if (!strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) {
+				dai_link->ops = &mt8196_rt5682s_i2s_ops;
+				if (!init_rt5682s) {
+					dai_link->init = mt8196_headset_codec_init;
+					dai_link->exit = mt8196_headset_codec_exit;
+					init_rt5682s = true;
+				}
+			} else if (!strcmp(dai_link->codecs->dai_name, RT5650_CODEC_DAI)) {
+				dai_link->ops = &mt8196_rt5682s_i2s_ops;
+				if (!init_rt5650) {
+					dai_link->init = mt8196_headset_codec_init;
+					dai_link->exit = mt8196_headset_codec_exit;
+					init_rt5650 = true;
+				}
+			} else {
+				if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) {
+					if (!init_dumb) {
+						dai_link->init = mt8196_dumb_amp_init;
+						init_dumb = true;
+					}
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+static const struct mtk_sof_priv mt8196_sof_priv = {
+	.conn_streams = g_sof_conn_streams,
+	.num_streams = ARRAY_SIZE(g_sof_conn_streams),
+};
+
+static struct snd_soc_card mt8196_mt6681_soc_card = {
+	.owner = THIS_MODULE,
+	.dai_link = mt8196_mt6681_dai_links,
+	.num_links = ARRAY_SIZE(mt8196_mt6681_dai_links),
+	.dapm_widgets = mt8196_mt6681_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(mt8196_mt6681_widgets),
+	.dapm_routes = mt8196_mt6681_routes,
+	.num_dapm_routes = ARRAY_SIZE(mt8196_mt6681_routes),
+	.controls = mt8196_mt6681_controls,
+	.num_controls = ARRAY_SIZE(mt8196_mt6681_controls),
+};
+
+static const struct mtk_soundcard_pdata mt8196_evb_card = {
+	.card_name = "mt8196_mt6681",
+	.card_data = &(struct mtk_platform_card_data) {
+		.card = &mt8196_mt6681_soc_card,
+		.num_jacks = MT8196_JACK_MAX,
+	},
+	.sof_priv = &mt8196_sof_priv,
+	.soc_probe = mt8196_mt6681_soc_card_probe,
+};
+
+static const struct mtk_soundcard_pdata mt8196_nau8825_card = {
+	.card_name = "mt8196_nau8825",
+	.card_data = &(struct mtk_platform_card_data) {
+		.card = &mt8196_mt6681_soc_card,
+		.num_jacks = MT8196_JACK_MAX,
+		.flags = NAU8825_HS_PRESENT
+	},
+	.sof_priv = &mt8196_sof_priv,
+	.soc_probe = mt8196_mt6681_soc_card_probe,
+};
+
+static const struct mtk_soundcard_pdata mt8196_rt5682s_card = {
+	.card_name = "mt8196_rt5682s",
+	.card_data = &(struct mtk_platform_card_data) {
+		.card = &mt8196_mt6681_soc_card,
+		.num_jacks = MT8196_JACK_MAX,
+		.flags = RT5682S_HS_PRESENT
+	},
+	.sof_priv = &mt8196_sof_priv,
+	.soc_probe = mt8196_mt6681_soc_card_probe,
+};
+
+static const struct mtk_soundcard_pdata mt8196_rt5650_card = {
+	.card_name = "mt8196_rt5650",
+	.card_data = &(struct mtk_platform_card_data) {
+		.card = &mt8196_mt6681_soc_card,
+		.num_jacks = MT8196_JACK_MAX,
+		.flags = RT5650_HS_PRESENT
+	},
+	.sof_priv = &mt8196_sof_priv,
+	.soc_probe = mt8196_mt6681_soc_card_probe,
+};
+
+static const struct of_device_id mt8196_mt6681_dt_match[] = {
+	{.compatible = "mediatek,mt8196-mt6681-sound", .data = &mt8196_evb_card,},
+	{.compatible = "mediatek,mt8196-nau8825-sound", .data = &mt8196_nau8825_card,},
+	{.compatible = "mediatek,mt8196-rt5682s-sound", .data = &mt8196_rt5682s_card,},
+	{.compatible = "mediatek,mt8196-rt5650-sound", .data = &mt8196_rt5650_card,},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mt8196_mt6681_dt_match);
+
+static struct platform_driver mt8196_mt6681_driver = {
+	.driver = {
+		.name = "mt8196-mt6681",
+		.of_match_table = mt8196_mt6681_dt_match,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = mtk_soundcard_common_probe,
+};
+module_platform_driver(mt8196_mt6681_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8196 mt6681 ALSA SoC machine driver");
+MODULE_AUTHOR("Darren Ye <darren.ye at mediatek.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("mt8196 mt6681 soc card");
+
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:28 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:28 +0800
Subject: [PATCH 02/14] ASoC: mediatek: common: modify mtk afe platform driver for mt8196
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-3-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Mofify the pcm pointer interface to support 64-bit address access.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 .../mediatek/common/mtk-afe-platform-driver.c | 63 ++++++++++++++-----
 .../mediatek/common/mtk-afe-platform-driver.h |  5 ++
 2 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
index 6b6330583941..5d8f4421e665 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
@@ -77,6 +77,16 @@ int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)
 }
 EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);
 
+int mtk_afe_pcm_open(struct snd_soc_component *component,
+		     struct snd_pcm_substream *substream)
+{
+	/* set the wait_for_avail to 2 sec*/
+	substream->wait_time = msecs_to_jiffies(2 * 1000);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_afe_pcm_open);
+
 snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
 				      struct snd_pcm_substream *substream)
 {
@@ -86,29 +96,44 @@ snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
 	const struct mtk_base_memif_data *memif_data = memif->data;
 	struct regmap *regmap = afe->regmap;
 	struct device *dev = afe->dev;
-	int reg_ofs_base = memif_data->reg_ofs_base;
-	int reg_ofs_cur = memif_data->reg_ofs_cur;
-	unsigned int hw_ptr = 0, hw_base = 0;
-	int ret, pcm_ptr_bytes;
-
-	ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr);
-	if (ret || hw_ptr == 0) {
-		dev_err(dev, "%s hw_ptr err\n", __func__);
-		pcm_ptr_bytes = 0;
+	unsigned int hw_ptr_lower32 = 0, hw_ptr_upper32 = 0;
+	unsigned int hw_base_lower32 = 0, hw_base_upper32 = 0;
+	unsigned long long hw_ptr = 0, hw_base = 0;
+	int ret;
+	unsigned long long pcm_ptr_bytes = 0;
+
+	ret = regmap_read(regmap, memif_data->reg_ofs_cur, &hw_ptr_lower32);
+	if (ret || hw_ptr_lower32 == 0) {
+		dev_err(dev, "%s hw_ptr_lower32 err\n", __func__);
 		goto POINTER_RETURN_FRAMES;
 	}
 
-	ret = regmap_read(regmap, reg_ofs_base, &hw_base);
-	if (ret || hw_base == 0) {
-		dev_err(dev, "%s hw_ptr err\n", __func__);
-		pcm_ptr_bytes = 0;
-		goto POINTER_RETURN_FRAMES;
+	if (memif_data->reg_ofs_cur_msb) {
+		ret = regmap_read(regmap, memif_data->reg_ofs_cur_msb, &hw_ptr_upper32);
+		if (ret) {
+			dev_err(dev, "%s hw_ptr_upper32 err\n", __func__);
+			goto POINTER_RETURN_FRAMES;
+		}
 	}
 
-	pcm_ptr_bytes = hw_ptr - hw_base;
+	ret = regmap_read(regmap, memif_data->reg_ofs_base, &hw_base_lower32);
+	if (ret || hw_base_lower32 == 0) {
+		dev_err(dev, "%s hw_base_lower32 err\n", __func__);
+		goto POINTER_RETURN_FRAMES;
+	}
+	if (memif_data->reg_ofs_base_msb) {
+		ret = regmap_read(regmap, memif_data->reg_ofs_base_msb, &hw_base_upper32);
+		if (ret) {
+			dev_err(dev, "%s hw_base_upper32 err\n", __func__);
+			goto POINTER_RETURN_FRAMES;
+		}
+	}
+	hw_ptr = ((unsigned long long)hw_ptr_upper32 << 32) + hw_ptr_lower32;
+	hw_base = ((unsigned long long)hw_base_upper32 << 32) + hw_base_lower32;
 
 POINTER_RETURN_FRAMES:
-	return bytes_to_frames(substream->runtime, pcm_ptr_bytes);
+	pcm_ptr_bytes = MTK_WORD_SIZE_ALIGN(hw_ptr - hw_base);
+	return bytes_to_frames(substream->runtime, (ssize_t)pcm_ptr_bytes);
 }
 EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);
 
@@ -143,6 +168,12 @@ static int mtk_afe_component_probe(struct snd_soc_component *component)
 	return 0;
 }
 
+void mtk_afe_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
+{
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+EXPORT_SYMBOL_GPL(mtk_afe_pcm_free);
+
 const struct snd_soc_component_driver mtk_afe_pcm_platform = {
 	.name		= AFE_PCM_NAME,
 	.pointer	= mtk_afe_pcm_pointer,
diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.h b/sound/soc/mediatek/common/mtk-afe-platform-driver.h
index fcc923b88f12..948998968a45 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.h
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.h
@@ -12,15 +12,20 @@
 #define AFE_PCM_NAME "mtk-afe-pcm"
 extern const struct snd_soc_component_driver mtk_afe_pcm_platform;
 
+#define MTK_WORD_SIZE_ALIGN(x) ((x) & (0xfffffffff0))
+
 struct mtk_base_afe;
 struct snd_pcm;
 struct snd_soc_component;
 struct snd_soc_pcm_runtime;
 
+int mtk_afe_pcm_open(struct snd_soc_component *component,
+		     struct snd_pcm_substream *substream);
 snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
 				      struct snd_pcm_substream *substream);
 int mtk_afe_pcm_new(struct snd_soc_component *component,
 		    struct snd_soc_pcm_runtime *rtd);
+void mtk_afe_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm);
 
 int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe);
 int mtk_afe_add_sub_dai_control(struct snd_soc_component *component);
-- 
2.45.2



From darren.ye at mediatek.com  Fri Mar  7 04:47:27 2025
From: darren.ye at mediatek.com (Darren.Ye)
Date: Fri, 7 Mar 2025 20:47:27 +0800
Subject: [PATCH 01/14] ASoC: mediatek: common: modify mtk afe common driver for mt8196
In-Reply-To: <20250307124841.23777-1-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
Message-ID: <20250307124841.23777-2-darren.ye@mediatek.com>

From: Darren Ye <darren.ye at mediatek.com>

Export register read and write interface, add sample reate interface, and
update the mtk_memif_set_channel interface for the mt8196 platform.

Signed-off-by: Darren Ye <darren.ye at mediatek.com>
---
 sound/soc/mediatek/common/mtk-afe-fe-dai.c | 30 ++++++++++++++--------
 sound/soc/mediatek/common/mtk-afe-fe-dai.h |  6 +++++
 sound/soc/mediatek/common/mtk-base-afe.h   | 13 ++++++++++
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index 3809068f5620..c36dae520f04 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -18,7 +18,7 @@
 
 #define AFE_BASE_END_OFFSET 8
 
-static int mtk_regmap_update_bits(struct regmap *map, int reg,
+int mtk_regmap_update_bits(struct regmap *map, int reg,
 			   unsigned int mask,
 			   unsigned int val, int shift)
 {
@@ -26,13 +26,16 @@ static int mtk_regmap_update_bits(struct regmap *map, int reg,
 		return 0;
 	return regmap_update_bits(map, reg, mask << shift, val << shift);
 }
+EXPORT_SYMBOL(mtk_regmap_update_bits);
+
+int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
 
-static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
 {
 	if (reg < 0)
 		return 0;
 	return regmap_write(map, reg, val);
 }
+EXPORT_SYMBOL(mtk_regmap_write);
 
 int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
 		       struct snd_soc_dai *dai)
@@ -459,8 +462,12 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
 	struct mtk_base_afe_memif *memif = &afe->memif[id];
 	unsigned int mono;
 
-	if (memif->data->mono_shift < 0)
-		return 0;
+	dev_info(afe->dev, "%s(), id: %d, channel: %d\n", __func__, id, channel);
+	mono = memif->data->mono_invert ^ (channel == 1);
+
+	if (memif->data->mono_shift > 0)
+		mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
+				       0x1, mono, memif->data->mono_shift);
 
 	if (memif->data->quad_ch_mask) {
 		unsigned int quad_ch = (channel == 4) ? 1 : 0;
@@ -470,11 +477,6 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
 				       quad_ch, memif->data->quad_ch_shift);
 	}
 
-	if (memif->data->mono_invert)
-		mono = (channel == 1) ? 0 : 1;
-	else
-		mono = (channel == 1) ? 1 : 0;
-
 	/* for specific configuration of memif mono mode */
 	if (memif->data->int_odd_flag_reg)
 		mtk_regmap_update_bits(afe->regmap,
@@ -482,8 +484,14 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
 				       1, mono,
 				       memif->data->int_odd_flag_shift);
 
-	return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
-				      1, mono, memif->data->mono_shift);
+	if (memif->data->ch_num_maskbit) {
+		dev_info(afe->dev, "%s(), set ch num id: %d, channel: %d\n", __func__, id, channel);
+		mtk_regmap_update_bits(afe->regmap, memif->data->ch_num_reg,
+				       memif->data->ch_num_maskbit,
+				       channel, memif->data->ch_num_shift);
+	}
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(mtk_memif_set_channel);
 
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.h b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
index b6d0f2b27e86..64b10ccba291 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
@@ -12,7 +12,13 @@
 struct snd_soc_dai_ops;
 struct mtk_base_afe;
 struct mtk_base_afe_memif;
+struct mtk_base_irq_data;
 
+int mtk_regmap_update_bits(struct regmap *map, int reg,
+			   unsigned int mask, unsigned int val,
+			   int shift);
+int mtk_regmap_write(struct regmap *map, int reg,
+		     unsigned int val);
 int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
 		       struct snd_soc_dai *dai);
 void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h
index f51578b6c50a..01c27fe92e2f 100644
--- a/sound/soc/mediatek/common/mtk-base-afe.h
+++ b/sound/soc/mediatek/common/mtk-base-afe.h
@@ -53,9 +53,11 @@ struct mtk_base_memif_data {
 	int enable_reg;
 	int enable_shift;
 	int hd_reg;
+	int hd_mask;
 	int hd_shift;
 	int hd_align_reg;
 	int hd_align_mshift;
+	int hd_msb_shift;
 	int msb_reg;
 	int msb_shift;
 	int msb_end_reg;
@@ -65,6 +67,10 @@ struct mtk_base_memif_data {
 	int ch_num_reg;
 	int ch_num_shift;
 	int ch_num_maskbit;
+	/* VUL 24~26 only for CM2 */
+	int out_on_use_reg;
+	int out_on_use_mask;
+	int out_on_use_shift;
 	/* playback memif only */
 	int pbuf_reg;
 	int pbuf_mask;
@@ -72,6 +78,9 @@ struct mtk_base_memif_data {
 	int minlen_reg;
 	int minlen_mask;
 	int minlen_shift;
+	int maxlen_reg;
+	int maxlen_mask;
+	int maxlen_shift;
 };
 
 struct mtk_base_irq_data {
@@ -87,6 +96,10 @@ struct mtk_base_irq_data {
 	int irq_clr_reg;
 	int irq_clr_shift;
 	int irq_status_shift;
+	int irq_ap_en_reg;
+	int irq_ap_en_shift;
+	int irq_scp_en_reg;
+	int irq_scp_en_shift;
 };
 
 struct device;
-- 
2.45.2



From maxime.chevallier at bootlin.com  Fri Mar  7 05:18:19 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri, 7 Mar 2025 14:18:19 +0100
Subject: [PATCH net-next 1/7] net: ethtool: netlink: Allow per-netdevice
 DUMP operations
In-Reply-To: <20250307122119.GE3666230@kernel.org>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
	<20250305141938.319282-2-maxime.chevallier@bootlin.com>
	<20250307122119.GE3666230@kernel.org>
Message-ID: <20250307141819.55e42ccd@fedora.home>

Hi Simon,

On Fri, 7 Mar 2025 12:21:19 +0000
Simon Horman <horms at kernel.org> wrote:

> On Wed, Mar 05, 2025 at 03:19:31PM +0100, Maxime Chevallier wrote:
> > We have a number of netlink commands in the ethnl family that may have
> > multiple objects to dump even for a single net_device, including :
> > 
> >  - PLCA, PSE-PD, phy: one message per PHY device
> >  - tsinfo: one message per timestamp source (netdev + phys)
> >  - rss: One per RSS context
> > 
> > To get this behaviour, these netlink commands need to roll a custom  
> > ->dumpit().  
> > 
> > To prepare making per-netdev DUMP more generic in ethnl, introduce a
> > member in the ethnl ops to indicate if a given command may allow
> > pernetdev DUMPs (also referred to as filtered DUMPs).
> > 
> > Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> > ---
> >  net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
> >  net/ethtool/netlink.h |  1 +
> >  2 files changed, 30 insertions(+), 16 deletions(-)
> > 
> > diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> > index 734849a57369..0815b28ba32f 100644
> > --- a/net/ethtool/netlink.c
> > +++ b/net/ethtool/netlink.c
> > @@ -578,21 +578,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
> >  	int ret = 0;
> >  
> >  	rcu_read_lock();
> > -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> > -		dev_hold(dev);
> > +	if (ctx->req_info->dev) {
> > +		dev = ctx->req_info->dev;
> >  		rcu_read_unlock();
> > -
> > -		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
> > -
> > +		/* Filtered DUMP request targeted to a single netdev. We already
> > +		 * hold a ref to the netdev from ->start()
> > +		 */
> > +		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
> > +						 genl_info_dump(cb));  
> 
> Hi Maxime,
> 
> ethnl_default_dump_one_dev() is called here but it doesn't exist
> until the following patch is applied, which breaks bisection.

Yeah I messed-up in my rebase and bisection broke :(

I'll send a new version in a few days, as Jakub said, let's give some
time for the netdev_lock series to move forward and go through CI, I'll
need to rebase on it at some point.

> 
> >  		rcu_read_lock();
> > -		dev_put(dev);
> > -
> > -		if (ret < 0 && ret != -EOPNOTSUPP) {
> > -			if (likely(skb->len))
> > -				ret = skb->len;
> > -			break;
> > +		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
> > +	} else {
> > +		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> > +			dev_hold(dev);
> > +			rcu_read_unlock();
> > +
> > +			ret = ethnl_default_dump_one(skb, dev, ctx,
> > +						     genl_info_dump(cb));
> > +
> > +			rcu_read_lock();
> > +			dev_put(dev);
> > +
> > +			if (ret < 0 && ret != -EOPNOTSUPP) {
> > +				if (likely(skb->len))
> > +					ret = skb->len;
> > +				break;
> > +			}
> > +			ret = 0;
> >  		}
> > -		ret = 0;
> >  	}
> >  	rcu_read_unlock();
> >    
> 
> ...
> 
> > diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
> > index ec6ab5443a6f..4db27182741f 100644
> > --- a/net/ethtool/netlink.h
> > +++ b/net/ethtool/netlink.h
> > @@ -388,6 +388,7 @@ struct ethnl_request_ops {
> >  	unsigned int		req_info_size;
> >  	unsigned int		reply_data_size;
> >  	bool			allow_nodev_do;
> > +	bool			allow_pernetdev_dump;  
> 
> nit: allow_pernetdev_dump should also be added to the Kernel doc for
>      struct ethnl_request_ops
> 
>      Flagged by ./scripts/kernel-doc -none
> 
>      There also appear to be similar minor issues with subsequent
>      patches in this series.

Ack, I'll make sure the doc is up to date and properly formatted :)

Thanks,

Maxime

> >  	u8			set_ntf_cmd;
> >  
> >  	int (*parse_request)(struct ethnl_req_info *req_info,
> > -- 
> > 2.48.1
> >   



From broonie at kernel.org  Fri Mar  7 05:24:03 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 7 Mar 2025 13:24:03 +0000
Subject: [PATCH] spi: stm32: Fix a NULL vs IS_ERR() bug
In-Reply-To: <dfd831ec-e004-4132-94f0-3bdc755907cd@foss.st.com>
References: <20250307032530.116837-1-hanchunchao@inspur.com>
 <dfd831ec-e004-4132-94f0-3bdc755907cd@foss.st.com>
Message-ID: <Z8rzc8suhKPr5SHV@finisterre.sirena.org.uk>

On Fri, Mar 07, 2025 at 09:59:42AM +0100, Patrice CHOTARD wrote:
> On 3/7/25 04:25, Charles Han wrote:

> > The devm_ioremap() function doesn't return error pointers, it may
> > returns NULL.  Update the error checking to match.

> No need to copy/paste other contributor's patch by just swapping some 
> words in title/commit message.

> This fix has already sent By Dan Carpenter and merged.

No idea if it applies here or not but since a lot of Dan's work is based
on static checker results it's quite common to see duplicates of his
patches when someone else runs the same or similar checkers - I think
all the people running these checkers are aware this happens but often
figure it's easier to send the duplicates than to check -next.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/6a5d94e5/attachment.sig>

From robh at kernel.org  Fri Mar  7 05:25:59 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 07 Mar 2025 07:25:59 -0600
Subject: [PATCH v2 0/2] ARM: dts: apalis/colibri-imx6: Add support for
 v1.2
In-Reply-To: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
References: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
Message-ID: <174135385275.4031184.1416379470522159928.robh@kernel.org>


On Fri, 07 Mar 2025 11:17:47 +0100, ernestvanhoecke at gmail.com wrote:
> From: Ernest Van Hoecke <ernest.vanhoecke at toradex.com>
> 
> Apalis/Colibri iMX6 V1.2 replaced the STMPE811 ADC/touch controller,
> which is EOL, with the TLA2024 ADC and AD7879 touch controller.
> 
> Accurately describe the new hardware.
> 
> v1.1 of these SoMs is still described by the following DTSI files:
> imx6qdl-apalis.dtsi
> imx6qdl-colibri.dtsi
> 
> The STMPE811 touchscreen controller is no longer disabled by default.
> The STMPE811 is self contained within the SoM, therefore, disabling it
> is not the correct default behavior.
> 
> v1.2 is now supported by a DTSI that modifies v1.1:
> imx6qdl-apalis-v1.2.dtsi
> imx6qdl-colibri-v1.2.dtsi
> 
> For each carrier board using these modules, a new DTS file was added
> that includes the v1.1 DTS and modifies it with this v1.2 DTSI.
> 
> The original DTS can be used for modules up to and including v1.1.
> 
> v2: Fixed the "From" field
> v1: https://lore.kernel.org/all/20250227170556.589668-1-ernest.vanhoecke at toradex.com/
> 
> Ernest Van Hoecke (2):
>   ARM: dts: apalis/colibri-imx6: Enable STMPE811 TS
>   ARM: dts: apalis/colibri-imx6: Add support for v1.2
> 
>  arch/arm/boot/dts/nxp/imx/Makefile            |  9 +++
>  .../dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts | 11 ++++
>  .../nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts   | 11 ++++
>  .../nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts   | 11 ++++
>  .../dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts  | 11 ++++
>  .../nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts   | 11 ++++
>  .../dts/nxp/imx/imx6q-apalis-v1.2-eval.dts    | 11 ++++
>  .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts  | 11 ++++
>  .../nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts  | 11 ++++
>  .../dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts   | 11 ++++
>  .../boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi | 57 +++++++++++++++++++
>  arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi |  1 -
>  .../dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi     | 57 +++++++++++++++++++
>  .../arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi |  1 -
>  14 files changed, 222 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
>  create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi
> 
> --
> 2.43.0
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/nxp/' for 20250307101758.27943-1-ernest.vanhoecke at toradex.com:

arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu2_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu2_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu2_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /soc/bus at 2100000/i2c at 21a0000/pcie-switch at 58: failed to match any schema with compatible: ['plx,pex8605']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu1_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /soc/ipu at 2800000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: panel-lvds: compatible:0: 'panel-lvds' is not one of ['admatec,9904379', 'auo,b101ew05', 'auo,g084sn05', 'chunghwa,claa070wp03xg', 'edt,etml0700z9ndha', 'hannstar,hsd101pww2', 'hydis,hv070wx2-1e0', 'jenson,bl-jt60050-01a', 'tbs,a711-panel']
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dtb: panel-lvds: compatible: ['panel-lvds'] is too short
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /soc/ipu at 2800000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: panel-lvds: compatible:0: 'panel-lvds' is not one of ['admatec,9904379', 'auo,b101ew05', 'auo,g084sn05', 'chunghwa,claa070wp03xg', 'edt,etml0700z9ndha', 'hannstar,hsd101pww2', 'hydis,hv070wx2-1e0', 'jenson,bl-jt60050-01a', 'tbs,a711-panel']
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dtb: panel-lvds: compatible: ['panel-lvds'] is too short
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /soc/ipu at 2800000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: panel-lvds: compatible:0: 'panel-lvds' is not one of ['admatec,9904379', 'auo,b101ew05', 'auo,g084sn05', 'chunghwa,claa070wp03xg', 'edt,etml0700z9ndha', 'hannstar,hsd101pww2', 'hydis,hv070wx2-1e0', 'jenson,bl-jt60050-01a', 'tbs,a711-panel']
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dtb: panel-lvds: compatible: ['panel-lvds'] is too short
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu2_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /soc/ipu at 2800000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: panel-lvds: compatible:0: 'panel-lvds' is not one of ['admatec,9904379', 'auo,b101ew05', 'auo,g084sn05', 'chunghwa,claa070wp03xg', 'edt,etml0700z9ndha', 'hannstar,hsd101pww2', 'hydis,hv070wx2-1e0', 'jenson,bl-jt60050-01a', 'tbs,a711-panel']
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dtb: panel-lvds: compatible: ['panel-lvds'] is too short
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /ldb: failed to match any schema with compatible: ['fsl,imx6q-ldb', 'fsl,imx53-ldb']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu2_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu1_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu1_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: iomuxc-gpr at 20e0000: 'ipu1_csi0_mux', 'ipu1_csi1_mux' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/imx/fsl,imx-iomuxc-gpr.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /soc/ipu at 2800000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: panel-lvds: compatible:0: 'panel-lvds' is not one of ['admatec,9904379', 'auo,b101ew05', 'auo,g084sn05', 'chunghwa,claa070wp03xg', 'edt,etml0700z9ndha', 'hannstar,hsd101pww2', 'hydis,hv070wx2-1e0', 'jenson,bl-jt60050-01a', 'tbs,a711-panel']
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dtb: panel-lvds: compatible: ['panel-lvds'] is too short
	from schema $id: http://devicetree.org/schemas/display/panel/panel-lvds.yaml#
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /soc/bus at 2100000/mipi at 21dc000: failed to match any schema with compatible: ['fsl,imx6-mipi-csi2']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /soc/bus at 2100000/vdoa at 21e4000: failed to match any schema with compatible: ['fsl,imx6q-vdoa']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /soc/ipu at 2400000: failed to match any schema with compatible: ['fsl,imx6q-ipu']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /capture-subsystem: failed to match any schema with compatible: ['fsl,imx-capture-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /display-subsystem: failed to match any schema with compatible: ['fsl,imx-display-subsystem']
arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dtb: /disp0: failed to match any schema with compatible: ['fsl,imx-parallel-display']







From nfraprado at collabora.com  Fri Mar  7 05:22:36 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Fri, 7 Mar 2025 10:22:36 -0300
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <0663e03e-e331-4a06-be95-ce8d9059ed6b@kernel.org>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
 <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>
 <2fa6037d-b5e9-45b2-a5d5-dbc92fb3434b@notapiano>
 <0663e03e-e331-4a06-be95-ce8d9059ed6b@kernel.org>
Message-ID: <cb2820d8-84e8-49ca-b497-1ea815679a3d@notapiano>

On Fri, Mar 07, 2025 at 08:11:26AM +0100, Krzysztof Kozlowski wrote:
> On 06/03/2025 13:19, N?colas F. R. A. Prado wrote:
> >>>    It is interfaced to host controller using SPI interface by a proprietary hardware
> >>>    called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
> >>> @@ -224,6 +225,30 @@ properties:
> >>>      description:
> >>>        Pin controller
> >>>  
> >>> +  accdet:
> >>> +    type: object
> >>> +    additionalProperties: false
> >>> +    description:
> >>> +      The Accessory Detection module found on the PMIC allows detecting audio
> >>> +      jack insertion and removal, as well as identifying the type of events
> >>> +      connected to the jack.
> >>> +
> >>> +    properties:
> >>> +      compatible:
> >>> +        const: mediatek,mt6359-accdet
> >>
> >> You just removed the other file, no folding happened here. Drop the
> >> accdet node and fold this into parent.
> > 
> > Sorry, I'm still not sure what you mean by folding here then. Right now the
> > accdet is a subnode of the PMIC. If you want me to remove the accdet node, where
> 
> Yes
> 
> > would its compatible and property go?
> 
> compatible: nowhere, because it is close to redundancy.
> 
> property: to the parent pmic node.
> 
>     pmic {
>         compatible = "mediatek,mt6359";
>         interrupt-controller;
>         #interrupt-cells = <2>;
> 
>         mediatek,hp-eint-high;
>     };

I'm not sure that's right. The ACCDET submodule does have some resources, IRQs,
that it registers in its mfd cell, see patch 2 of this series [1]. It also has
its own driver (sound/soc/codecs/mt6359-accdet.c) that probes based on this
compatible and handles those interrupts. Why would it not get its own node like
the other MFD cells?

[1] https://lore.kernel.org/all/20250305-mt6359-accdet-dts-v4-2-e5ffa5ee9991 at collabora.com

Thanks,
N?colas


From andrew at lunn.ch  Fri Mar  7 05:25:58 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 7 Mar 2025 14:25:58 +0100
Subject: [PATCH 4/4] arm64: dts: rockchip: Enable Ethernet controller on
 Radxa E20C
In-Reply-To: <cbd6d3ee-8ad1-443f-9506-e28240ffb09e@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-5-jonas@kwiboo.se>
 <e0e8fa5e-07a2-4f4f-80b9-ddb2332c27ea@lunn.ch>
 <cbd6d3ee-8ad1-443f-9506-e28240ffb09e@kwiboo.se>
Message-ID: <c7fe0371-76bc-4cb4-ade8-e22112c1475d@lunn.ch>

On Fri, Mar 07, 2025 at 10:16:08AM +0100, Jonas Karlman wrote:
> Hi Andrew,
> 
> On 2025-03-06 23:49, Andrew Lunn wrote:
> >> +&mdio1 {
> >> +	rgmii_phy: ethernet-phy at 1 {
> >> +		compatible = "ethernet-phy-ieee802.3-c22";
> > 
> > The compatible is not needed. That is the default.
> 
> Interesting, however I rather be explicit to not cause any issue for
> U-Boot or any other user of the device trees beside Linux kernel.

O.K.  But any system using Linux .dts files should be happy with no
compatible, since that is how the majority are. Because PHYs have ID
registers, generally there is no need for a compatible. The only time
you do need a compatible is:

* The ID registers are wrong
* The ID registers cannot be read, chicken/egg problems the driver needs to solve
* The Clause 22 address space is not implemented and you need to indicate C45
  should be used to get the ID registers.

None of this is specific to Linux.

	Andrew


From mike.leach at linaro.org  Fri Mar  7 05:33:38 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 7 Mar 2025 13:33:38 +0000
Subject: [PATCH v3 7/7] coresight-tgu: add reset node to initialize
In-Reply-To: <20250227092640.2666894-8-quic_songchai@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com> <20250227092640.2666894-8-quic_songchai@quicinc.com>
Message-ID: <CAJ9a7Vh4OTZdbEygtwc7BxRJSLgkALoaNRPEiQLJQgZvFtnTtw@mail.gmail.com>

Hi,

On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>
> From: Songwei Chai <quic_songchai at quicinc.com>
>
> Add reset node to initialize the value of
> priority/condition_decode/condition_select/timer/counter nodes
>
> Signed-off-by: Songwei Chai <quic_songchai at quicinc.com>
> Signed-off-by: songchai <quic_songchai at quicinc.com>
> ---
>  .../testing/sysfs-bus-coresight-devices-tgu   |  7 ++
>  drivers/hwtracing/coresight/coresight-tgu.c   | 79 +++++++++++++++++++
>  2 files changed, 86 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> index d88d05fbff43..8fb5afd7c655 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> @@ -42,3 +42,10 @@ KernelVersion   6.15
>  Contact:        Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
>  Description:
>                  (RW) Set/Get the counter value with specific step for TGU.
> +
> +What:           /sys/bus/coresight/devices/<tgu-name>/reset_tgu
> +Date:           February 2025
> +KernelVersion   6.15
> +Contact:        Jinlong Mao (QUIC) <quic_jinlmao at quicinc.com>, Sam Chai (QUIC) <quic_songchai at quicinc.com>
> +Description:
> +                (Write) Reset the dataset for TGU.

Document the value needed to initiate the reset.

> diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c
> index 693d632fb079..b36ced761c0d 100644
> --- a/drivers/hwtracing/coresight/coresight-tgu.c
> +++ b/drivers/hwtracing/coresight/coresight-tgu.c
> @@ -343,6 +343,84 @@ static ssize_t enable_tgu_store(struct device *dev,
>  }
>  static DEVICE_ATTR_RW(enable_tgu);
>
> +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */
> +static ssize_t reset_tgu_store(struct device *dev,
> +                              struct device_attribute *attr, const char *buf,
> +                              size_t size)
> +{
> +       unsigned long value;
> +       struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +       int i, j, ret;
> +
> +       if (kstrtoul(buf, 0, &value))
> +               return -EINVAL;
> +

Check "value" here and bail out with an error code if 0.

> +       if (!drvdata->enable) {
> +               ret = pm_runtime_get_sync(drvdata->dev);
> +               if (ret < 0) {
> +                       pm_runtime_put(drvdata->dev);
> +                       return ret;
> +               }
> +       }
> +
> +       spin_lock(&drvdata->spinlock);
> +       CS_UNLOCK(drvdata->base);
> +
> +       if (value) {
drop this line

> +               tgu_writel(drvdata, 0, TGU_CONTROL);
> +
> +               if (drvdata->value_table->priority)
> +                       memset(drvdata->value_table->priority, 0,
> +                              MAX_PRIORITY * drvdata->max_step *
> +                                      drvdata->max_reg * sizeof(unsigned int));
> +
> +               if (drvdata->value_table->condition_decode)
> +                       memset(drvdata->value_table->condition_decode, 0,
> +                              drvdata->max_condition_decode * drvdata->max_step *
> +                                      sizeof(unsigned int));
> +
> +               /* Initialize all condition registers to NOT(value=0x1000000) */
> +               for (i = 0; i < drvdata->max_step; i++) {
> +                       for (j = 0; j < drvdata->max_condition_decode; j++) {
> +                               drvdata->value_table
> +                                       ->condition_decode[calculate_array_location(
> +                                               drvdata, i, TGU_CONDITION_DECODE, j)] =
> +                                       0x1000000;
> +                       }
> +               }
> +
> +               if (drvdata->value_table->condition_select)
> +                       memset(drvdata->value_table->condition_select, 0,
> +                              drvdata->max_condition_select * drvdata->max_step *
> +                                      sizeof(unsigned int));
> +
> +               if (drvdata->value_table->timer)
> +                       memset(drvdata->value_table->timer, 0,
> +                              (drvdata->max_step) *
> +                                      (drvdata->max_timer_counter) *
> +                                      sizeof(unsigned int));
> +
> +               if (drvdata->value_table->counter)
> +                       memset(drvdata->value_table->counter, 0,
> +                              (drvdata->max_step) *
> +                                      (drvdata->max_timer_counter) *
> +                                      sizeof(unsigned int));
> +
> +               dev_dbg(dev, "Coresight-TGU reset complete\n");
> +       } else {
> +               dev_dbg(dev, "Coresight-TGU invalid input\n");

not needed if early exit on input errror

> +       }
> +
> +       CS_LOCK(drvdata->base);
> +
> +       drvdata->enable = false;
> +       spin_unlock(&drvdata->spinlock);
> +       pm_runtime_put(drvdata->dev);
> +
> +       return size;
> +}
> +static DEVICE_ATTR_WO(reset_tgu);
> +
>  static const struct coresight_ops_helper tgu_helper_ops = {
>         .enable = tgu_enable,
>         .disable = tgu_disable,
> @@ -354,6 +432,7 @@ static const struct coresight_ops tgu_ops = {
>
>  static struct attribute *tgu_common_attrs[] = {
>         &dev_attr_enable_tgu.attr,
> +       &dev_attr_reset_tgu.attr,
>         NULL,
>  };
>
>


Regards

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From mathis.foerst at mt.com  Fri Mar  7 05:38:29 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 7 Mar 2025 14:38:29 +0100
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
 <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
Message-ID: <Z8r21Z2HthBwGDSq@mt.com>

Hi Sakari, Hi Dan,

thanks a lot for your feedback.

On Thu, Mar 06, 2025 at 09:13:46PM +0000, Sakari Ailus wrote:
> Hi Dan,
> 
> On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> > On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > > Hi Mathis,
> > > 
> > > Thanks for the patch.
> > > 
> > > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > > The imx-media-csi driver requires upstream camera drivers to implement
> > > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > > implement this function are not usable on the i.MX6.
> > > > 
> > > > The docs for get_mbus_config [1] say:
> > > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > > >             The media bus configuration is usually retrieved from the
> > > >             firmware interface at sub-device probe time, immediately
> > > >             applied to the hardware and eventually adjusted by the
> > > >             driver.
> > > > 
> > > > Currently, the imx-media-csi driver is not incorporating the information
> > > > from the firmware interface and therefore relies on the implementation of
> > > > get_mbus_config by the camera driver.
> > > > 
> > > > To be compatible with camera drivers not implementing get_mbus_config
> > > > (which is the usual case), use the bus information from the fw interface:
> > > > 
> > > > The camera does not necessarily has a direct media bus link to the CSI as
> > > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > > between them on the media pipeline.
> > > > The CSI driver already implements the functionality to find the connected
> > > > camera sub-device to call get_mbus_config on it.
> > > > 
> > > > At this point the driver is modified as follows:
> > > > In the case that get_mbus_config is not implemented by the upstream
> > > > camera, try to get its endpoint configuration from the firmware interface
> > > > usign v4l2_fwnode_endpoint_parse.
> > > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > > configuration.
> > > > For all other mbus_types, return an error.
> > > > 
> > > > Note that parsing the mbus_config from the fw interface is not done during
> > > > probing because the camera that's connected to the CSI can change based on
> > > > the selected input of the video-mux at runtime.
> > > > 
> > > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > > [1] include/media/v4l2-subdev.h - line 814
> > > > 
> > > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > > ---
> > > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > > 
> > > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > > index 3edbc57be2ca..394a9321a10b 100644
> > > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > >  {
> > > >  	struct v4l2_subdev *sd, *remote_sd;
> > > >  	struct media_pad *remote_pad;
> > > > +	struct fwnode_handle *ep_node;
> > > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > > 
> > > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > > field to zero this way is redundant, just use {}.
> > > 
> > 
> > I was going to respond in much the same way.  This is equivalen to:
> > 
> > struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
> 
> Thinking about this in a context of parsing the endpoint, in fact the
> bus_type should be specified. Presumably the hardware is D-PHY, so the
> correct value would be V4L2_MBUS_CSI2_DPHY. This way
> v4l2_fwnode_endpoint_parse() doesn't need to guess.

I think we must use "bus_type = V4L2_MBUS_UNKNOWN" here:

The i.MX6 has two types of camera interfaces: Parallel and MIPI CSI-2.
They are connected either directly or via a video-mux to the CSIs
(See IMX6DQRM.pdf - Figure 9-3 for the connection diagram)

Pre-defining V4L2_MBUS_CSI2_DPHY here would let
v4l2_fwnode_endpoint_parse() fail if the camera uses the parallel bus.

We could distinguish between MIPI CSI-2 and Parallel input by checking
the grp_id of the upstream device like it's already done in
csi_get_upstream_mbus_config().
But for the Parallel case we still can't know if we should set bus_type
to V4L2_MBUS_PARALLEL or to V4L2_MBUS_BT656 - the i.MX6 supports both
formats on the parallel interface.

That's why I would argue that v4l2_fwnode_endpoint_parse() must figure
out the bus_type from the fw node.

> 
> > 
> > > >  	int ret;
> > > >  
> > > >  	if (!priv->src_sd)
> > > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > >  
> > > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > > >  			       remote_pad->index, mbus_cfg);
> > > > -	if (ret == -ENOIOCTLCMD)
> > > > -		v4l2_err(&priv->sd,
> > > > -			 "entity %s does not implement get_mbus_config()\n",
> > > > -			 remote_pad->entity->name);
> > > > +	if (ret == -ENOIOCTLCMD) {
> > > 
> > > 	if (!ret)
> > > 		return 0;
> > > 
> > > And you can unindent the rest.
> > 
> > I was going to say this too but then I thought actually this needs to
> > be:
> > 
> > 	if (ret != -ENOIOCTLCMD)
> > 		return ret;
> > 
> > Which is weird.  Better to break all the new code into a separate
> > helper function.
> > 
> > 	if (ret == -ENOIOCTLCMD)
> > 		ret = parse_fw_link_config_stuff();
> > 
> > 	return ret;

Good point. I factored out a helper function as suggested.

> 
> Indeed. get_mbus_config() presumably wouldn't return an error but
> correctness is usually a good idea.
> 
> -- 
> Regards,
> 
> Sakari Ailus


Best regards,
Mathis Foerst



From andrew at lunn.ch  Fri Mar  7 05:52:13 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 7 Mar 2025 14:52:13 +0100
Subject: [PATCH 1/3] net: stmmac: dwmac-rk: Use DELAY_ENABLE macro for
 RK3328
In-Reply-To: <624f2474-9a39-46a3-a6e5-f9966471bf3d@kwiboo.se>
References: <20250306203858.1677595-1-jonas@kwiboo.se>
 <20250306203858.1677595-2-jonas@kwiboo.se>
 <d6b15dc2-f6b2-4703-a4da-07618eaed4db@lunn.ch>
 <624f2474-9a39-46a3-a6e5-f9966471bf3d@kwiboo.se>
Message-ID: <f5f397bb-476a-429a-9d1e-1c1a9beb8f89@lunn.ch>

On Fri, Mar 07, 2025 at 12:28:42AM +0100, Jonas Karlman wrote:
> Hi Andrew,
> 
> On 2025-03-06 23:25, Andrew Lunn wrote:
> > On Thu, Mar 06, 2025 at 08:38:52PM +0000, Jonas Karlman wrote:
> >> Support for Rockchip RK3328 GMAC and addition of the DELAY_ENABLE macro
> >> was merged in the same merge window. This resulted in RK3328 not being
> >> converted to use the new DELAY_ENABLE macro.
> >>
> >> Change to use the DELAY_ENABLE macro to help disable MAC delay when
> >> RGMII_ID/RXID/TXID is used.
> >>
> >> Fixes: eaf70ad14cbb ("net: stmmac: dwmac-rk: Add handling for RGMII_ID/RXID/TXID")
> > 
> > Please add a description of the broken behaviour. How would i know i
> > need this fix? What would i see?
> 
> Based on my layman testing I have not seen any real broken behaviour
> with current enablement of a zero rx/tx MAC delay for RGMII_ID/RXID/TXID.
> 
> The driver ops is called with a rx/tx_delay=0 for RGMII_ID/RXID/TXID
> modes, what the MAC does with enable=true and rx/tx_delay=0 is unclear
> to me.
> 
> > 
> > We also need to be careful with backwards compatibility. Is there the
> > potential for double bugs cancelling each other out? A board which has
> > the wrong phy-mode in DT, but because of this bug, the wrong register
> > is written and it actually works because of reset defaults?
> 
> To my knowledge this should have very limited effect, however I am no
> network expert and after doing very basic testing on several different
> rk3328/rk3566/rk3568/rk3588 I could not see any real affect with/without
> this change.
> 
> The use of Fixes-tag was more to have a reference to the commit that
> first should have used the DELAY_ENABLE macro.

https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html

  It must either fix a real bug that bothers people or just add a device ID.

It does not sound like this meets the stable requirements. Plus there
is the potential for breakage. So i suggest you drop the Fixes: tag
and we merge this via net-next.

Please take a look at:

https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html

    Andrew

---
pw-bot: cr


From andrew at lunn.ch  Fri Mar  7 06:02:52 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 7 Mar 2025 15:02:52 +0100
Subject: [PATCH 3/4] arm64: dts: rockchip: Add GMAC nodes for RK3528
In-Reply-To: <003d3726-680a-4e91-89cd-d127bc3b5609@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-4-jonas@kwiboo.se>
 <a827e7e9-882a-40c6-9f2c-03d8181dff88@lunn.ch>
 <003d3726-680a-4e91-89cd-d127bc3b5609@kwiboo.se>
Message-ID: <f6c6aeb5-bdec-4283-87c8-e870f59008c8@lunn.ch>

So this is a bit more complicated than i first guessed...

> 	phy-mode = "rmii";
> 	clock_in_out = "input";

Probably will not get passed the DT maintainers. The clocking needs
investigating.

> 	phy-handle = <&rmii0_phy>;
> 
> 	mdio0: mdio {
> 		compatible = "snps,dwmac-mdio";
> 		#address-cells = <0x1>;
> 		#size-cells = <0x0>;
> 
> 		rmii0_phy: ethernet-phy at 2 {
> 			compatible = "ethernet-phy-id0044.1400", "ethernet-phy-ieee802.3-c22";
> 			reg = <2>;
> 			clocks = <&cru CLK_MACPHY>;
> 			resets = <&cru SRST_MACPHY>;

Using the ID suggests there might be a chicken/egg with the reset and
clock. The ID registers cannot be read from the PHY?

> 			phy-is-integrated;

This suggests the possibility exists to route the RMII interface to the
outside world:

  phy-is-integrated:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      If set, indicates that the PHY is integrated into the same
      physical package as the Ethernet MAC. If needed, muxers
      should be configured to ensure the integrated PHY is
      used. The absence of this property indicates the muxers
      should be configured so that the external PHY is used.

Given these issues, i suggest you keep with the DT as you have it
now. Adding the PHY node will require access to hardware and some
investigations.

	Andrew


From nicolas.frattaroli at collabora.com  Fri Mar  7 06:05:50 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Fri, 07 Mar 2025 15:05:50 +0100
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop unnecessary status
 from example
In-Reply-To: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
References: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
Message-ID: <5417098.31r3eYUQgx@workhorse>

On Friday, 7 March 2025 10:33:09 Central European Standard Time Krzysztof 
Kozlowski wrote:
> Device nodes are enabled by default, so no need for 'status = "okay"' in
> the DTS example.
> 
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> ---
> 
> Changes in v2:
> 1. Drop unnecessary full stop in subject prefix after ':'.
> 2. Add Rb tag.
> ---
>  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml index
> 757967212f55..ca71b400bcae 100644
> --- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> +++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> @@ -53,7 +53,6 @@ examples:
>          interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
>          clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
>          resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
> -        status = "okay";
>        };
>      };

Hi,

is there the possibility we could make dtschema as invoked by `make 
dt_binding_check W=1` (or W=2) add a warning for examples that have disabled 
or explicitly listed status properties when not needed? Or is this something 
better handled in, say, checkpatch.pl?

The question arises because dumb mistakes by me like this should ideally be 
caught before they waste precious maintainer time.

If it's best handled in dtschema, I can look into working on that so you guys 
don't have to do even more work due to me.

Cheers,
Nicolas Frattaroli




From andrew at lunn.ch  Fri Mar  7 06:08:04 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 7 Mar 2025 15:08:04 +0100
Subject: [PATCH net-next] net: stmmac: remove write-only priv->speed
In-Reply-To: <E1tqLJJ-005aQm-Mv@rmk-PC.armlinux.org.uk>
References: <E1tqLJJ-005aQm-Mv@rmk-PC.armlinux.org.uk>
Message-ID: <eef38dd5-63f6-4771-bf43-a55ba3ce98e0@lunn.ch>

On Fri, Mar 07, 2025 at 12:11:29AM +0000, Russell King (Oracle) wrote:
> priv->speed is only ever written to in two locations, but never
> read. Therefore, it serves no useful purpose. Remove this unnecessary
> struct member.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From peter.griffin at linaro.org  Fri Mar  7 06:12:44 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 7 Mar 2025 14:12:44 +0000
Subject: [PATCH v2 1/2] clk: samsung: Add missing mod_devicetable.h header
In-Reply-To: <20250305-clk-samsung-headers-cleanup-v2-1-ea1ae8e9e2bf@linaro.org>
References: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
 <20250305-clk-samsung-headers-cleanup-v2-1-ea1ae8e9e2bf@linaro.org>
Message-ID: <CADrjBPqxTiy8D8PVpZBzYnes-hxqKX+gd6a4WgJeDE=x7YQKAA@mail.gmail.com>

On Wed, 5 Mar 2025 at 20:03, Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
>
> Add an include for <mod_devicetable.h> in the drivers which use
> of_device_id table to bring its declaration directly, not through some
> other headers.
>
> Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---

Reviewed-by: Peter Griffin <peter.griffin at linaro.org>


From toke at redhat.com  Fri Mar  7 06:15:22 2025
From: toke at redhat.com (Toke =?utf-8?Q?H=C3=B8iland-J=C3=B8rgensen?=)
Date: Fri, 07 Mar 2025 15:15:22 +0100
Subject: [PATCH net-next v11 0/4] fix the DMA API misuse problem for
 page_pool
In-Reply-To: <20250307092356.638242-1-linyunsheng@huawei.com>
References: <20250307092356.638242-1-linyunsheng@huawei.com>
Message-ID: <87v7slvsed.fsf@toke.dk>

Yunsheng Lin <linyunsheng at huawei.com> writes:

> This patchset fix the dma API misuse problem as below:
> Networking driver with page_pool support may hand over page
> still with dma mapping to network stack and try to reuse that
> page after network stack is done with it and passes it back
> to page_pool to avoid the penalty of dma mapping/unmapping.
> With all the caching in the network stack, some pages may be
> held in the network stack without returning to the page_pool
> soon enough, and with VF disable causing the driver unbound,
> the page_pool does not stop the driver from doing it's
> unbounding work, instead page_pool uses workqueue to check
> if there is some pages coming back from the network stack
> periodically, if there is any, it will do the dma unmmapping
> related cleanup work.
>
> As mentioned in [1], attempting DMA unmaps after the driver
> has already unbound may leak resources or at worst corrupt
> memory. Fundamentally, the page pool code cannot allow DMA
> mappings to outlive the driver they belong to.
>
> By using the 'struct page_pool_item' referenced by page->pp_item,
> page_pool is not only able to keep track of the inflight page to
> do dma unmmaping if some pages are still handled in networking
> stack when page_pool_destroy() is called, and networking stack is
> also able to find the page_pool owning the page when returning
> pages back into page_pool:
> 1. When a page is added to the page_pool, an item is deleted from
>    pool->hold_items and set the 'pp_netmem' pointing to that page
>    and set item->state and item->pp_netmem accordingly in order to
>    keep track of that page, refill from pool->release_items when
>    pool->hold_items is empty or use the item from pool->slow_items
>    when fast items run out.
> 2. When a page is released from the page_pool, it is able to tell
>    which page_pool this page belongs to by masking off the lower
>    bits of the pointer to page_pool_item *item, as the 'struct
>    page_pool_item_block' is stored in the top of a struct page.
>    And after clearing the pp_item->state', the item for the
>    released page is added back to pool->release_items so that it
>    can be reused for new pages or just free it when it is from the
>    pool->slow_items.
> 3. When page_pool_destroy() is called, item->state is used to tell
>    if a specific item is being used/dma mapped or not by scanning
>    all the item blocks in pool->item_blocks, then item->netmem can
>    be used to do the dma unmmaping if the corresponding inflight
>    page is dma mapped.

You are making this incredibly complicated. You've basically implemented
a whole new slab allocator for those page_pool_item objects, and you're
tracking every page handed out by the page pool instead of just the ones
that are DMA-mapped. None of this is needed.

I took a stab at implementing the xarray-based tracking first suggested
by Mina[0]:

https://git.kernel.org/toke/c/e87e0edf9520

And, well, it's 50 lines of extra code, none of which are in the fast
path.

Jesper has kindly helped with testing that it works for normal packet
processing, but I haven't yet verified that it resolves the original
crash. Will post the patch to the list once I have verified this (help
welcome!).

-Toke

[0] https://lore.kernel.org/all/CAHS8izPg7B5DwKfSuzz-iOop_YRbk3Sd6Y4rX7KBG9DcVJcyWg at mail.gmail.com/



From lpieralisi at kernel.org  Fri Mar  7 06:24:59 2025
From: lpieralisi at kernel.org (Lorenzo Pieralisi)
Date: Fri, 7 Mar 2025 15:24:59 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
Message-ID: <Z8sBuzx6sGq24n0g@lpieralisi>

On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
> In hindsight, there were some crucial subtleties overlooked when moving
> {of,acpi}_dma_configure() to driver probe time to allow waiting for
> IOMMU drivers with -EPROBE_DEFER, and these have become an
> ever-increasing source of problems. The IOMMU API has some fundamental
> assumptions that iommu_probe_device() is called for every device added
> to the system, in the order in which they are added. Calling it in a
> random order or not at all dependent on driver binding leads to
> malformed groups, a potential lack of isolation for devices with no
> driver, and all manner of unexpected concurrency and race conditions.
> We've attempted to mitigate the latter with point-fix bodges like
> iommu_probe_device_lock, but it's a losing battle and the time has come
> to bite the bullet and address the true source of the problem instead.
> 
> The crux of the matter is that the firmware parsing actually serves two
> distinct purposes; one is identifying the IOMMU instance associated with
> a device so we can check its availability, the second is actually
> telling that instance about the relevant firmware-provided data for the
> device. However the latter also depends on the former, and at the time
> there was no good place to defer and retry that separately from the
> availability check we also wanted for client driver probe.
> 
> Nowadays, though, we have a proper notion of multiple IOMMU instances in
> the core API itself, and each one gets a chance to probe its own devices
> upon registration, so we can finally make that work as intended for
> DT/IORT/VIOT platforms too. All we need is for iommu_probe_device() to
> be able to run the iommu_fwspec machinery currently buried deep in the
> wrong end of {of,acpi}_dma_configure(). Luckily it turns out to be
> surprisingly straightforward to bootstrap this transformation by pretty
> much just calling the same path twice. At client driver probe time,
> dev->driver is obviously set; conversely at device_add(), or a
> subsequent bus_iommu_probe(), any device waiting for an IOMMU really
> should *not* have a driver already, so we can use that as a condition to
> disambiguate the two cases, and avoid recursing back into the IOMMU core
> at the wrong times.
> 
> Obviously this isn't the nicest thing, but for now it gives us a
> functional baseline to then unpick the layers in between without many
> more awkward cross-subsystem patches. There are some minor side-effects
> like dma_range_map potentially being created earlier, and some debug
> prints being repeated, but these aren't significantly detrimental. Let's
> make things work first, then deal with making them nice.
> 
> With the basic flow finally in the right order again, the next step is
> probably turning the bus->dma_configure paths inside-out, since all we
> really need from bus code is its notion of which device and input ID(s)
> to parse the common firmware properties with...
> 
> Acked-by: Bjorn Helgaas <bhelgaas at google.com> # pci-driver.c
> Acked-by: Rob Herring (Arm) <robh at kernel.org> # of/device.c
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> 
> v2:
>  - Comment bus driver changes for clarity
>  - Use dev->iommu as the now-robust replay condition
>  - Drop the device_iommu_mapped() checks in the firmware paths as they
>    weren't doing much - we can't replace probe_device_lock just yet...
>  
>  drivers/acpi/arm64/dma.c        |  5 +++++
>  drivers/acpi/scan.c             |  7 -------
>  drivers/amba/bus.c              |  3 ++-
>  drivers/base/platform.c         |  3 ++-
>  drivers/bus/fsl-mc/fsl-mc-bus.c |  3 ++-
>  drivers/cdx/cdx.c               |  3 ++-
>  drivers/iommu/iommu.c           | 24 +++++++++++++++++++++---
>  drivers/iommu/of_iommu.c        |  7 ++++++-
>  drivers/of/device.c             |  7 ++++++-
>  drivers/pci/pci-driver.c        |  3 ++-
>  10 files changed, 48 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/dma.c b/drivers/acpi/arm64/dma.c
> index 52b2abf88689..f30f138352b7 100644
> --- a/drivers/acpi/arm64/dma.c
> +++ b/drivers/acpi/arm64/dma.c
> @@ -26,6 +26,11 @@ void acpi_arch_dma_setup(struct device *dev)
>  	else
>  		end = (1ULL << 32) - 1;
>  
> +	if (dev->dma_range_map) {
> +		dev_dbg(dev, "dma_range_map already set\n");
> +		return;
> +	}
> +

Why are we checking that dev->dma_range_map exists here rather than
at function entry ? Is that because we want to run the previous code
for some reasons even if dev->dma_range_map is already set ?

Just noticed, the OF counterpart does not seem to take the same
approach, so I am just flagging this up if it matters at all.

Other than that, for acpi/arm64:

Reviewed-by: Lorenzo Pieralisi <lpieralisi at kernel.org>

>  	ret = acpi_dma_get_range(dev, &map);
>  	if (!ret && map) {
>  		end = dma_range_map_max(map);
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 9f4efa8f75a6..fb1fe9f3b1a3 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1632,13 +1632,6 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
>  		err = viot_iommu_configure(dev);
>  	mutex_unlock(&iommu_probe_device_lock);
>  
> -	/*
> -	 * If we have reason to believe the IOMMU driver missed the initial
> -	 * iommu_probe_device() call for dev, replay it to get things in order.
> -	 */
> -	if (!err && dev->bus)
> -		err = iommu_probe_device(dev);
> -
>  	return err;
>  }
>  
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 8ef259b4d037..71482d639a6d 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -364,7 +364,8 @@ static int amba_dma_configure(struct device *dev)
>  		ret = acpi_dma_configure(dev, attr);
>  	}
>  
> -	if (!ret && !drv->driver_managed_dma) {
> +	/* @drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !drv->driver_managed_dma) {
>  		ret = iommu_device_use_default_domain(dev);
>  		if (ret)
>  			arch_teardown_dma_ops(dev);
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index 6f2a33722c52..1813cfd0c4bd 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -1451,7 +1451,8 @@ static int platform_dma_configure(struct device *dev)
>  		attr = acpi_get_dma_attr(to_acpi_device_node(fwnode));
>  		ret = acpi_dma_configure(dev, attr);
>  	}
> -	if (ret || drv->driver_managed_dma)
> +	/* @drv may not be valid when we're called from the IOMMU layer */
> +	if (ret || !dev->driver || drv->driver_managed_dma)
>  		return ret;
>  
>  	ret = iommu_device_use_default_domain(dev);
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index d1f3d327ddd1..a8be8cf246fb 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -153,7 +153,8 @@ static int fsl_mc_dma_configure(struct device *dev)
>  	else
>  		ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id);
>  
> -	if (!ret && !mc_drv->driver_managed_dma) {
> +	/* @mc_drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !mc_drv->driver_managed_dma) {
>  		ret = iommu_device_use_default_domain(dev);
>  		if (ret)
>  			arch_teardown_dma_ops(dev);
> diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
> index c573ed2ee71a..780fb0c4adba 100644
> --- a/drivers/cdx/cdx.c
> +++ b/drivers/cdx/cdx.c
> @@ -360,7 +360,8 @@ static int cdx_dma_configure(struct device *dev)
>  		return ret;
>  	}
>  
> -	if (!ret && !cdx_drv->driver_managed_dma) {
> +	/* @cdx_drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !cdx_drv->driver_managed_dma) {
>  		ret = iommu_device_use_default_domain(dev);
>  		if (ret)
>  			arch_teardown_dma_ops(dev);
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index a3b45b84f42b..1cec7074367a 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -414,9 +414,21 @@ static int iommu_init_device(struct device *dev)
>  	if (!dev_iommu_get(dev))
>  		return -ENOMEM;
>  	/*
> -	 * For FDT-based systems and ACPI IORT/VIOT, drivers register IOMMU
> -	 * instances with non-NULL fwnodes, and client devices should have been
> -	 * identified with a fwspec by this point. Otherwise, we can currently
> +	 * For FDT-based systems and ACPI IORT/VIOT, the common firmware parsing
> +	 * is buried in the bus dma_configure path. Properly unpicking that is
> +	 * still a big job, so for now just invoke the whole thing. The device
> +	 * already having a driver bound means dma_configure has already run and
> +	 * either found no IOMMU to wait for, or we're in its replay call right
> +	 * now, so either way there's no point calling it again.
> +	 */
> +	if (!dev->driver && dev->bus->dma_configure) {
> +		mutex_unlock(&iommu_probe_device_lock);
> +		dev->bus->dma_configure(dev);
> +		mutex_lock(&iommu_probe_device_lock);
> +	}
> +	/*
> +	 * At this point, relevant devices either now have a fwspec which will
> +	 * match ops registered with a non-NULL fwnode, or we can reasonably
>  	 * assume that only one of Intel, AMD, s390, PAMU or legacy SMMUv2 can
>  	 * be present, and that any of their registered instances has suitable
>  	 * ops for probing, and thus cheekily co-opt the same mechanism.
> @@ -426,6 +438,12 @@ static int iommu_init_device(struct device *dev)
>  		ret = -ENODEV;
>  		goto err_free;
>  	}
> +	/*
> +	 * And if we do now see any replay calls, they would indicate someone
> +	 * misusing the dma_configure path outside bus code.
> +	 */
> +	if (dev->driver)
> +		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
>  
>  	if (!try_module_get(ops->owner)) {
>  		ret = -EINVAL;
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e10a68b5ffde..6b989a62def2 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -155,7 +155,12 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
>  		dev_iommu_free(dev);
>  	mutex_unlock(&iommu_probe_device_lock);
>  
> -	if (!err && dev->bus)
> +	/*
> +	 * If we're not on the iommu_probe_device() path (as indicated by the
> +	 * initial dev->iommu) then try to simulate it. This should no longer
> +	 * happen unless of_dma_configure() is being misused outside bus code.
> +	 */
> +	if (!err && dev->bus && !dev_iommu_present)
>  		err = iommu_probe_device(dev);
>  
>  	if (err && err != -EPROBE_DEFER)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index edf3be197265..5053e5d532cc 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -99,6 +99,11 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>  	bool coherent, set_map = false;
>  	int ret;
>  
> +	if (dev->dma_range_map) {
> +		dev_dbg(dev, "dma_range_map already set\n");
> +		goto skip_map;
> +	}
> +
>  	if (np == dev->of_node)
>  		bus_np = __of_get_dma_parent(np);
>  	else
> @@ -119,7 +124,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>  		end = dma_range_map_max(map);
>  		set_map = true;
>  	}
> -
> +skip_map:
>  	/*
>  	 * If @dev is expected to be DMA-capable then the bus code that created
>  	 * it should have initialised its dma_mask pointer by this point. For
> diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> index f57ea36d125d..4468b7327cab 100644
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
> @@ -1653,7 +1653,8 @@ static int pci_dma_configure(struct device *dev)
>  
>  	pci_put_host_bridge_device(bridge);
>  
> -	if (!ret && !driver->driver_managed_dma) {
> +	/* @driver may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !driver->driver_managed_dma) {
>  		ret = iommu_device_use_default_domain(dev);
>  		if (ret)
>  			arch_teardown_dma_ops(dev);
> -- 
> 2.39.2.101.g768bb238c484.dirty
> 


From andre.draszik at linaro.org  Fri Mar  7 06:29:18 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Fri, 07 Mar 2025 14:29:18 +0000
Subject: [PATCH RFC/RFT 00/12] clk: samsung: Use platform_driver_probe()
 to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
Message-ID: <01cdf3a68e120d30bdcf4fc225bb236dba47fdff.camel@linaro.org>

Hi Krzysztof,

Nice idea!

On Wed, 2025-03-05 at 22:43 +0100, Krzysztof Kozlowski wrote:
> RFT/RFC because testing needed. I tried to do the same on exynos5-subcmu
> and it caused weird oopses which even KASAN did not narrow. Probably
> because of multiple exynos5-subcmu devices?

I've tried this on top of next-20250225, and it doesn't work on gs101
either and OOPSes several times during boot in different places, but
I can not dig deeper right now.

[   11.502919][   T58] Unable to handle kernel paging request at virtual address ffffbfe2ab25cc30
[   11.503128][   T58] Mem abort info:
[   11.503202][   T58]   ESR = 0x0000000096000007
[   11.503295][   T58]   EC = 0x25: DABT (current EL), IL = 32 bits
[   11.503419][   T58]   SET = 0, FnV = 0
[   11.503498][   T58]   EA = 0, S1PTW = 0
[   11.503579][   T58]   FSC = 0x07: level 3 translation fault
[   11.503695][   T58] Data abort info:
[   11.503769][   T58]   ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000
[   11.503896][   T58]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[   11.504058][   T58]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[   11.504288][   T58] swapper pgtable: 4k pages, 48-bit VAs, pgdp=000000008208c000
[   11.504570][   T58] [ffffbfe2ab25cc30] pgd=0000000000000000, p4d=1000000082a58003, pud=1000000082a59003, pmd=1000000082a5d003,
pte=0000000000000000
[   11.505079][   T58] Internal error: Oops: 0000000096000007 [#1] PREEMPT SMP
[   11.505346][   T58] Modules linked in:
[   11.505495][   T58] CPU: 6 UID: 0 PID: 58 Comm: kworker/u32:1 Tainted: G                T  6.14.0-rc4-next-20250225+ #12
[   11.505902][   T58] Tainted: [T]=RANDSTRUCT
[   11.506061][   T58] Hardware name: Raven (DT)
[   11.506230][   T58] Workqueue: events_unbound deferred_probe_work_func
[   11.506477][   T58] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   11.506768][   T58] pc : __device_attach_driver+0x18/0x254
[   11.506978][   T58] lr : bus_for_each_drv+0xfc/0x154
[   11.507168][   T58] sp : ffff8000803abc00
[   11.507321][   T58] x29: ffff8000803abc10 x28: ffff00ed403363d0 x27: ffff00ed40336400
[   11.507620][   T58] x26: 0000000000000000 x25: ffff00ed4002380d x24: ffff00ed40028000
[   11.507919][   T58] x23: ffffbfe2aba26000 x22: 0000000000000000 x21: ffff00ed409f8400
[   11.508219][   T58] x20: ffff8000803abca8 x19: ffffbfe2a9a4cf4c x18: 0000000000000040
[   11.508518][   T58] x17: 0000000000000001 x16: 0000000000000001 x15: 0000000000000010
[   11.508817][   T58] x14: 0000000000000010 x13: 0000000000000093 x12: 0000000000000002
[   11.509117][   T58] x11: ffffffffff6070d2 x10: 0000bef56a420260 x9 : 0000000100000000
[   11.509416][   T58] x8 : 0000000100000000 x7 : ff7f7f7f7f7f7f7f x6 : 455242436f53531d
[   11.509715][   T58] x5 : 1d53536f43425245 x4 : 0000000000000000 x3 : e8c6e6e4bec6c65a
[   11.510015][   T58] x2 : 0000000000000062 x1 : ffff8000803abca8 x0 : ffffbfe2ab25cc28
[   11.510315][   T58] Call trace:
[   11.510436][   T58]  __device_attach_driver+0x18/0x254 (P)
[   11.510644][   T58]  bus_for_each_drv+0xfc/0x154
[   11.510819][   T58]  __device_attach+0x100/0x1cc
[   11.510996][   T58]  device_initial_probe+0x14/0x20
[   11.511182][   T58]  bus_probe_device+0x94/0x100
[   11.511359][   T58]  deferred_probe_work_func+0xa0/0xfc
[   11.511558][   T58]  process_scheduled_works+0x194/0x2c4
[   11.511761][   T58]  worker_thread+0x28c/0x394
[   11.511930][   T58]  kthread+0x1c0/0x204
[   11.512081][   T58]  ret_from_fork+0x10/0x20
[   11.512248][   T58] Code: a9017bfd f90013f5 a9034ff4 910043fd (f9400408) 
[   11.512506][   T58] ---[ end trace 0000000000000000 ]---

and

+ udevadm trigger '--action=add'
[  390.387986][  T394] Unable to handle kernel paging request at virtual address ffffbfe2ab25cc28
[  390.388207][  T394] Mem abort info:
[  390.388282][  T394]   ESR = 0x0000000096000007
[  390.388378][  T394]   EC = 0x25: DABT (current EL), IL = 32 bits
[  390.388506][  T394]   SET = 0, FnV = 0
[  390.388586][  T394]   EA = 0, S1PTW = 0
[  390.388669][  T394]   FSC = 0x07: level 3 translation fault
[  390.388787][  T394] Data abort info:
[  390.388862][  T394]   ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000
[  390.388990][  T394]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[  390.389137][  T394]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[  390.389367][  T394] swapper pgtable: 4k pages, 48-bit VAs, pgdp=000000008208c000
[  390.389650][  T394] [ffffbfe2ab25cc28] pgd=0000000000000000, p4d=1000000082a58003, pud=1000000082a59003, pmd=1000000082a5d003,
pte=0000000000000000
[  390.390173][  T394] Internal error: Oops: 0000000096000007 [#2] PREEMPT SMP
[  390.390426][  T394] Modules linked in:
[  390.390580][  T394] CPU: 7 UID: 0 PID: 394 Comm: udevadm Tainted: G      D         T  6.14.0-rc4-next-20250225+ #12
[  390.390969][  T394] Tainted: [D]=DIE, [T]=RANDSTRUCT
[  390.391153][  T394] Hardware name: Raven (DT)
[  390.391322][  T394] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  390.391612][  T394] pc : dev_uevent+0x144/0x2d8
[  390.391785][  T394] lr : kobject_uevent_env+0x1e0/0x3a8
[  390.391985][  T394] sp : ffff8000810fbb40
[  390.392137][  T394] x29: ffff8000810fbb60 x28: 0000000000000002 x27: ffffbfe2aa859240
[  390.392437][  T394] x26: ffffbfe2aae1ca12 x25: 0000000000000000 x24: ffff00ed41167540
[  390.392736][  T394] x23: ffff00ed41070000 x22: ffff8000810fbbf8 x21: 0000000000000000
[  390.393035][  T394] x20: ffff00ed41070000 x19: ffff00ed41083010 x18: 0000000000000000
[  390.393335][  T394] x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffc7e40360
[  390.393634][  T394] x14: 00000000ffffffd0 x13: aaaaaaaaaaaaaaaa x12: aaaaaaaaaaaa0000
[  390.393933][  T394] x11: 0000000000000000 x10: 0000000000000004 x9 : 3bc04d1231e6a100
[  390.394233][  T394] x8 : ffffbfe2ab25cc28 x7 : 3d4d455453595342 x6 : 4554535953425553
[  390.394532][  T394] x5 : ffff00ed4107026b x4 : ffffbfe2aae64508 x3 : ffffffffffff0a00
[  390.394831][  T394] x2 : 0000000000000000 x1 : ffff00ed41070000 x0 : ffff00ed41083010
[  390.395132][  T394] Call trace:
[  390.395252][  T394]  dev_uevent+0x144/0x2d8 (P)
[  390.395425][  T394]  kobject_uevent_env+0x1e0/0x3a8
[  390.395610][  T394]  kobject_synth_uevent+0x3ec/0x440
[  390.395802][  T394]  uevent_store+0x28/0x64
[  390.395962][  T394]  dev_attr_store+0x18/0x2c
[  390.396128][  T394]  sysfs_kf_write+0x80/0xa0
[  390.396295][  T394]  kernfs_fop_write_iter+0xdc/0x178
[  390.396488][  T394]  vfs_write+0x344/0x3a0
[  390.396644][  T394]  ksys_write+0x7c/0xe8
[  390.396797][  T394]  __arm64_sys_write+0x1c/0x28
[  390.396973][  T394]  invoke_syscall+0x40/0xf8
[  390.397139][  T394]  el0_svc_common+0xac/0xdc
[  390.397306][  T394]  do_el0_svc+0x1c/0x28
[  390.397459][  T394]  el0_svc+0x34/0x9c
[  390.397602][  T394]  el0t_64_sync_handler+0x84/0x108
[  390.397791][  T394]  el0t_64_sync+0x1a4/0x1a8
[  390.397963][  T394] Code: aa1403e0 94232d4d f9403668 b40000c8 (f9400102) 
[  390.398221][  T394] ---[ end trace 0000000000000000 ]---


Cheers,
Andre'



From peter.griffin at linaro.org  Fri Mar  7 06:29:38 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 7 Mar 2025 14:29:38 +0000
Subject: [PATCH v2 2/2] clk: samsung: Drop unused clk.h and of.h headers
In-Reply-To: <20250305-clk-samsung-headers-cleanup-v2-2-ea1ae8e9e2bf@linaro.org>
References: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
 <20250305-clk-samsung-headers-cleanup-v2-2-ea1ae8e9e2bf@linaro.org>
Message-ID: <CADrjBPq3CA97cGopuCFD5BrPH8KnM-rsi7vMC3w285ihNDm40Q@mail.gmail.com>

On Wed, 5 Mar 2025 at 20:04, Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
>
> <clk.h> header is for clock consumers, so drop its include from the
> Samsung clock controller drivers which do not use the consumer API
> (there are few which do, so leave it there).
>
> Drop including of <of.h> and <of_address.h> headers for all drivers
> which do not use anything from generic OF API or of_iomap().
>
> Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---

Reviewed-by: Peter Griffin <peter.griffin at linaro.org>


From robh at kernel.org  Fri Mar  7 06:35:22 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 07 Mar 2025 08:35:22 -0600
Subject: [PATCH 12/14] dt-bindings: mediatek: mt8196: add audio AFE
 document
In-Reply-To: <20250307124841.23777-13-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-13-darren.ye@mediatek.com>
Message-ID: <174135812164.4140447.14223699212791655529.robh@kernel.org>


On Fri, 07 Mar 2025 20:47:38 +0800, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Add mt8196 audio AFE document.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  .../bindings/sound/mediatek,mt8196-afe.yaml   | 259 ++++++++++++++++++
>  1 file changed, 259 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.example.dts:24:18: fatal error: dt-bindings/clock/mt8196-clk.h: No such file or directory
   24 |         #include <dt-bindings/clock/mt8196-clk.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.dtbs:131: Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1511: dt_binding_check] Error 2
make: *** [Makefile:251: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250307124841.23777-13-darren.ye at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From robh at kernel.org  Fri Mar  7 06:35:24 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 07 Mar 2025 08:35:24 -0600
Subject: [PATCH 14/14] dt-bindings: mediatek: mt8196: add mt8196-mt6681
 document
In-Reply-To: <20250307124841.23777-15-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-15-darren.ye@mediatek.com>
Message-ID: <174135812256.4140479.2757707814425375416.robh@kernel.org>


On Fri, 07 Mar 2025 20:47:40 +0800, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Add document for mt8196 board with mt6681.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  .../sound/mediatek,mt8196-mt6681.yaml         | 122 ++++++++++++++++++
>  1 file changed, 122 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:


doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250307124841.23777-15-darren.ye at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From m.felsch at pengutronix.de  Fri Mar  7 06:39:56 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Fri, 7 Mar 2025 15:39:56 +0100
Subject: [PATCH v2 0/5] imx8mp: add support for the IMX AIPSTZ bridge
In-Reply-To: <541539db-0015-41de-837f-aabbea68486a@gmail.com>
References: <20250226165314.34205-1-laurentiumihalcea111@gmail.com>
 <20250226212219.lthoofw7nrs3gtg6@pengutronix.de>
 <20250227112856.aylsurbt3uqm4ivw@pengutronix.de>
 <541539db-0015-41de-837f-aabbea68486a@gmail.com>
Message-ID: <20250307143956.aft3xolakts3nlja@pengutronix.de>

On 25-03-05, Laurentiu Mihalcea wrote:
> 
> On 2/27/2025 1:28 PM, Marco Felsch wrote:
> > Hi Laurentiu,
> >
> > On 25-02-26, Marco Felsch wrote:
> >> Hi,
> >>
> >> On 25-02-26, Laurentiu Mihalcea wrote:
> >>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> >>>
> >>> The AIPSTZ bridge offers some security-related configurations which can
> >>> be used to restrict master access to certain peripherals on the bridge.
> >>>
> >>> Normally, this could be done from a secure environment such as ATF before
> >>> Linux boots but the configuration of AIPSTZ5 is lost each time the power
> >>> domain is powered off and then powered on. Because of this, it has to be
> >>> configured each time the power domain is turned on and before any master
> >>> tries to access the peripherals (e.g: AP, CM7, DSP, on i.MX8MP).
> >> My question still stands:
> >>
> >> Setting these bits requires very often that the core is running at EL3
> >> (e.g. secure-monitor) which is not the case for Linux. Can you please
> >> provide more information how Linux can set these bits?
> > Sorry I didn't noticed your response:
> >
> > https://lore.kernel.org/all/a62ab860-5e0e-4ebc-af1f-6fb7ac621e2b at gmail.com/
> >
> > If EL1 is allowed to set the security access configuration of the IP
> > cores doesn't this mean that a backdoor can be opened? E.g. your
> > secure-boot system configures one I2C IP core to be accessible only from
> > secure-world S-EL1 (OP-TEE) and after the power-domain was power-cycled
> > it's accessible from EL1 again. This doesn't seem right. Why should a
> > user be able to limit the access permissions to an IP core to only be
> > accessible from secure-world if the IP core is accessible from
> > normal-world after the power-domain was power-cycled.
> >
> > Regards,
> >   Marco
> 
> I'm no security expert so please feel free to correct me if I get
> something wrong.
> 
> This isn't about S/NS world. The bridge AC doesn't offer any
> configurations for denying access to peripherals based on S/NS world.

It does, please see the AIPSTZ_OPACR register definition. The imx-atf of
sets OPACR registers to 0 (of course), which means that the S/NS is not
checked _but_ it can be configured.

Also please see chapter 4.7.6.1 Security Block:

The AIPSTZ contains a security block that is connected to each
off-platform peripheral. This block filters accesses based on
write/read, non-secure, and supervisor signals.

> AFAIK that's the job of the CSU (central security unit), which is a
> different IP.

Please see above.

> Perhaps I shouldn't have used the term "trusted" as it might have
> ended up creating more confusion? If so, please do let me know so I
> can maybe add a comment about it in one of the commit messages. In
> this context, "master X is trusted for read/writes" means "master X is
> allowed to perform read/write transactions".

No you didn't confused me but you triggered my interest :) and I started
to check the (S)TRM.

> Even if the bridge is configured to allow read/write transactions from
> a master (i.e: master is marked as trusted for read/writes) that
> wouldn't be very helpful.

We're talking about the IP access permissions, right. If the
"secure-I2C" is accessible from NS world this would make a difference of
course.

> You'd still have to bypass the CSU configuration which as far as I
> understand is also used by the bridge to deny access to peripherals
> (e.g: if transaction is secure+privileged then forward to peripheral,
> otherwise abort it). See the "4.7.6.1 Security Block" and "4.7.4?
> Access Protections" chapters from the IMX8MP RM.

I have read this too, also that the AIPSTZ can force the mode into
user_mode regardless of the CSU settings, if I get this correct.

What I don't understand as of now is the interaction of the AIPSTZ and
the CSU. You can configure different bus-masters within the CSU to be
S/NS as well as the pheripherals. Now the part which I don't understand
right now: According the OPACx register description:

x0xx SP0 ? This peripheral does not require supervisor privilege level
           for accesses.
x1xx SP1 ? This peripheral requires supervisor privilege level for
           accesses. The master privilege level must indicate supervisor
	   via the hprot[1] access attribute, and the MPROTx[MPL] control
	   bit for the master must be set. If not, the access is
	   terminated with an error response and no peripheral access is
	   initiated on the IPS bus.

The peripheral can be configured via the AIPSTZ as well. So which IP
(CSU or AIPSTZ) override the other if the settings don't match, e.g. if
CSU says: "this I2C controller for secure-world" and the AIPSTZ says:
"this I2C is for non-secure-world".

> Given all of this, I think the purpose of this IP's AC is to add some
> extra, light, security features on top of the CSU.

Or to override the CSU settings like the MPROTOx values:

xxx0 MPL0 ? Accesses from this master are forced to user-mode
           (ips_supervisor_access is forced to zero) regardless of the
	   hprot[1] access attribute.
xxx1 MPL1 ? Accesses from this master are not forced to user-mode. The
            hprot[1] access attribute is used directly to determine
	    ips_supervisor_access.

Can you pleae elaborate a bit more how NXP designed the interaction
between both the AIPSTZ and the CSU?

Regards,
  Marco


From Markus.Elfring at web.de  Fri Mar  7 06:48:37 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Fri, 7 Mar 2025 15:48:37 +0100
Subject: [PATCH] drm/exynos/vidi: Remove redundant error handling in
 vidi_get_modes()
In-Reply-To: <20250306042720.2296-1-vulab@iscas.ac.cn>
References: <20250306042720.2296-1-vulab@iscas.ac.cn>
Message-ID: <c29a5d6e-335b-463e-a318-e8d78d176a9f@web.de>

?
> drm_edid_alloc() fails, the function will immediately return 0,
?

                   failed?


?
> the event of failure in these two functions, it is still necessary
> to call the subsequent drm_edid_connector_update() function with
?

You may occasionally put more than 66 characters into text lines
of such a change description.


>                                    ? To maintain the integrity of
> the operation, redundant error handling needs to be removed.

How do you think about to add any tags (like ?Fixes? and ?Cc?) accordingly?
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc5#n145

Regards,
Markus


From ping.bai at nxp.com  Fri Mar  7 06:55:47 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Fri,  7 Mar 2025 22:55:47 +0800
Subject: [PATCH v5] cpuidle: Init cpuidle only for present CPUs
Message-ID: <20250307145547.2784821-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpuidle
in below cpuidle drivers:
  drivers/cpuidle/cpuidle-arm.c
  drivers/cpuidle/cpuidle-big_little.c
  drivers/cpuidle/cpuidle-psci.c
  drivers/cpuidle/cpuidle-qcom-spm.c
  drivers/cpuidle/cpuidle-riscv-sbi.c

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the failure:

  |  Failed to register cpuidle device for cpu1

Then rollback to cancel all CPUs' cpuidle registration.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpuidle drivers to ensure it only registers cpuidle devices
for CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Reviewed-by: Dhruva Gole <d-gole at ti.com>
Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v5 changes:
   - add changes for cpuidle-qcom-spm

 - v4 changes:
  - add changes for other cpuidle driver that has the similar issue
    as cpuidle-pcsi driver.

 - v3 changes:
  - improve the changelog as suggested by Sudeep
---
 drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
 drivers/cpuidle/cpuidle-big_little.c | 2 +-
 drivers/cpuidle/cpuidle-psci.c       | 4 ++--
 drivers/cpuidle/cpuidle-qcom-spm.c   | 2 +-
 drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index caba6f4bb1b7..e044fefdb816 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -137,9 +137,9 @@ static int __init arm_idle_init_cpu(int cpu)
 /*
  * arm_idle_init - Initializes arm cpuidle driver
  *
- * Initializes arm cpuidle driver for all CPUs, if any CPU fails
- * to register cpuidle driver then rollback to cancel all CPUs
- * registration.
+ * Initializes arm cpuidle driver for all present CPUs, if any
+ * CPU fails to register cpuidle driver then rollback to cancel
+ * all CPUs registration.
  */
 static int __init arm_idle_init(void)
 {
@@ -147,7 +147,7 @@ static int __init arm_idle_init(void)
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = arm_idle_init_cpu(cpu);
 		if (ret)
 			goto out_fail;
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index 74972deda0ea..4abba42fcc31 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -148,7 +148,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
 	if (!cpumask)
 		return -ENOMEM;
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		if (smp_cpuid_part(cpu) == part_id)
 			cpumask_set_cpu(cpu, cpumask);
 
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index dd8d776d6e39..b46a83f5ffe4 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -403,7 +403,7 @@ static int psci_idle_init_cpu(struct device *dev, int cpu)
 /*
  * psci_idle_probe - Initializes PSCI cpuidle driver
  *
- * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails
+ * Initializes PSCI cpuidle driver for all present CPUs, if any CPU fails
  * to register cpuidle driver then rollback to cancel all CPUs
  * registration.
  */
@@ -413,7 +413,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = psci_idle_init_cpu(&pdev->dev, cpu);
 		if (ret)
 			goto out_fail;
diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c
index 3ab240e0e122..5f386761b156 100644
--- a/drivers/cpuidle/cpuidle-qcom-spm.c
+++ b/drivers/cpuidle/cpuidle-qcom-spm.c
@@ -135,7 +135,7 @@ static int spm_cpuidle_drv_probe(struct platform_device *pdev)
 	if (ret)
 		return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed");
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = spm_cpuidle_register(&pdev->dev, cpu);
 		if (ret && ret != -ENODEV) {
 			dev_err(&pdev->dev,
diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
index 0c92a628bbd4..0fe1ece9fbdc 100644
--- a/drivers/cpuidle/cpuidle-riscv-sbi.c
+++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
@@ -529,8 +529,8 @@ static int sbi_cpuidle_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	/* Initialize CPU idle driver for each CPU */
-	for_each_possible_cpu(cpu) {
+	/* Initialize CPU idle driver for each present CPU */
+	for_each_present_cpu(cpu) {
 		ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu);
 		if (ret) {
 			pr_debug("HART%ld: idle driver init failed\n",
-- 
2.34.1



From krzysztof.kozlowski at linaro.org  Fri Mar  7 07:00:53 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:00:53 +0100
Subject: [PATCH RFC/RFT 00/12] clk: samsung: Use platform_driver_probe()
 to avoid __refdata
In-Reply-To: <01cdf3a68e120d30bdcf4fc225bb236dba47fdff.camel@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org>
 <01cdf3a68e120d30bdcf4fc225bb236dba47fdff.camel@linaro.org>
Message-ID: <ceb3be8e-8f5c-43a8-a4b9-3ee62e67dfd6@linaro.org>

On 07/03/2025 15:29, Andr? Draszik wrote:
> Hi Krzysztof,
> 
> Nice idea!
> 
> On Wed, 2025-03-05 at 22:43 +0100, Krzysztof Kozlowski wrote:
>> RFT/RFC because testing needed. I tried to do the same on exynos5-subcmu
>> and it caused weird oopses which even KASAN did not narrow. Probably
>> because of multiple exynos5-subcmu devices?
> 
> I've tried this on top of next-20250225, and it doesn't work on gs101
> either and OOPSes several times during boot in different places, but
> I can not dig deeper right now.
> 
> [   11.502919][   T58] Unable to handle kernel paging request at virtual address ffffbfe2ab25cc30

Thanks. I'll dig more once have a bit more time. The calltrace is
exactly what I saw with exynos5-subcmu and it puzzles me.

Best regards,
Krzysztof


From krzysztof.kozlowski at linaro.org  Fri Mar  7 07:04:05 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri, 07 Mar 2025 16:04:05 +0100
Subject: [PATCH v2 0/2] clk: samsung: Two header cleanups
In-Reply-To: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
References: <20250305-clk-samsung-headers-cleanup-v2-0-ea1ae8e9e2bf@linaro.org>
Message-ID: <174135984582.202251.7619477733984588971.b4-ty@linaro.org>


On Wed, 05 Mar 2025 21:03:42 +0100, Krzysztof Kozlowski wrote:
> Changes in v2:
> - mod_devicetable.h: also clk.c, clk.h, clk-exynos4.c,
>   clk-exynos5-subcmu.c, clk-exynos2200.c and clk-exynos7870.c (Tudor)
> - cleanup: clk-exynos2200.c and clk-exynos7870.c (Tudor)
> - Rb tags
> - Link to v1: https://lore.kernel.org/r/20250304-clk-samsung-headers-cleanup-v1-0-81718e38246e at linaro.org
> 
> [...]

Applied, thanks!

[1/2] clk: samsung: Add missing mod_devicetable.h header
      https://git.kernel.org/krzk/linux/c/f32f5b0ec0f6eec0186de0607ab12f9cb1ecab73
[2/2] clk: samsung: Drop unused clk.h and of.h headers
      https://git.kernel.org/krzk/linux/c/017bbc922a09630579ff7b5b314fb186b8c0efcf

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From krzysztof.kozlowski at linaro.org  Fri Mar  7 07:06:26 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Fri, 07 Mar 2025 16:06:26 +0100
Subject: [PATCH 1/2] arm64: dts: exynos: gs101: Change labels to
 lower-case
In-Reply-To: <20250219085726.70824-1-krzysztof.kozlowski@linaro.org>
References: <20250219085726.70824-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174135998630.202917.16887190642980215810.b4-ty@linaro.org>


On Wed, 19 Feb 2025 09:57:25 +0100, Krzysztof Kozlowski wrote:
> DTS coding style expects labels to be lowercase.  No functional impact.
> Verified with comparing decompiled DTB (dtx_diff and fdtdump+diff).
> 
> 

Applied, thanks!

[1/2] arm64: dts: exynos: gs101: Change labels to lower-case
      https://git.kernel.org/krzk/linux/c/73fd2bb607387a77b2dde43a2c47db2b71c65a96
[2/2] arm64: dts: tesla: Change labels to lower-case
      https://git.kernel.org/krzk/linux/c/056106b030b73c7d53749469bd1cdbc89b4d2daf

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From linux at armlinux.org.uk  Fri Mar  7 07:06:35 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 7 Mar 2025 15:06:35 +0000
Subject: [PATCH net-next v7 4/4] net: stmmac: Add glue layer for Sophgo
 SG2044 SoC
In-Reply-To: <20250307011623.440792-5-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
 <20250307011623.440792-5-inochiama@gmail.com>
Message-ID: <Z8sLeyixPzH60mJ_@shell.armlinux.org.uk>

On Fri, Mar 07, 2025 at 09:16:17AM +0800, Inochi Amaoto wrote:
> Adds Sophgo dwmac driver support on the Sophgo SG2044 SoC.
> 
> Signed-off-by: Inochi Amaoto <inochiama at gmail.com>

Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From krzk at kernel.org  Fri Mar  7 07:21:59 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:21:59 +0100
Subject: [PATCH 02/14] ASoC: mediatek: common: modify mtk afe platform
 driver for mt8196
In-Reply-To: <20250307124841.23777-3-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-3-darren.ye@mediatek.com>
Message-ID: <7b967651-1368-42f1-af23-adc3c94c88ca@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Mofify the pcm pointer interface to support 64-bit address access.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  .../mediatek/common/mtk-afe-platform-driver.c | 63 ++++++++++++++-----
>  .../mediatek/common/mtk-afe-platform-driver.h |  5 ++
>  2 files changed, 52 insertions(+), 16 deletions(-)
> 
> diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
> index 6b6330583941..5d8f4421e665 100644
> --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
> +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
> @@ -77,6 +77,16 @@ int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)
>  }
>  EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);
>  
> +int mtk_afe_pcm_open(struct snd_soc_component *component,

How adding this is related with 64-bit addresses? It's not even used here.

> +		     struct snd_pcm_substream *substream)
> +{
> +	/* set the wait_for_avail to 2 sec*/
> +	substream->wait_time = msecs_to_jiffies(2 * 1000);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(mtk_afe_pcm_open);


Best regards,
Krzysztof


From m.felsch at pengutronix.de  Fri Mar  7 07:22:36 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Fri, 7 Mar 2025 16:22:36 +0100
Subject: [PATCH 4/5] arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
In-Reply-To: <bfe3c719-f1c5-4ae5-9a40-45ad75cd5855@gmail.com>
References: <20250221191909.31874-1-laurentiumihalcea111@gmail.com>
 <20250221191909.31874-5-laurentiumihalcea111@gmail.com>
 <Z7jahtO3bxjkMfnc@lizhi-Precision-Tower-5810>
 <cd6a84cd-ff17-45df-becc-9bfc74522f73@gmail.com>
 <20250227-monumental-whale-of-security-b1c84e-mkl@pengutronix.de>
 <Z8CWsI/DKZtDBkzE@lizhi-Precision-Tower-5810>
 <20250228101952.g6tae3ni5xrhjk3y@pengutronix.de>
 <bfe3c719-f1c5-4ae5-9a40-45ad75cd5855@gmail.com>
Message-ID: <20250307152236.3ayulbjqnu3vn7mf@pengutronix.de>

On 25-03-04, Laurentiu Mihalcea wrote:
> 
> On 2/28/2025 12:19 PM, Marco Felsch wrote:
> > Hi,
> >
> > On 25-02-27, Frank Li wrote:
> >> On Thu, Feb 27, 2025 at 11:57:54AM +0100, Marc Kleine-Budde wrote:
> >>> On 25.02.2025 16:14:34, Mihalcea Laurentiu wrote:
> >>>> On 21.02.2025 21:56, Frank Li wrote:
> >>>>> On Fri, Feb 21, 2025 at 02:19:08PM -0500, Laurentiu Mihalcea wrote:
> >>>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> >>>>>>
> >>>>>> AIPS5 is actually AIPSTZ5 as it offers some security-related
> >>>>>> configurations. Since these configurations need to be applied before
> >>>>>> accessing any of the peripherals on the bus, it's better to make AIPSTZ5
> >>>>>> be their parent instead of keeping AIPS5 and adding a child node for
> >>>>>> AIPSTZ5. Also, because of the security configurations, the address space
> >>>>>> of the bus has to be changed to that of the configuration registers.
> >>>>> The orginal 0x30c0_0000..0x31200000 include 0x30df0000, why not map only
> >>>>> config address part in your drivers.
> >>>>>
> >>>>> Frank
> >>>> Any concerns/anything wrong with current approach?
> >>>>
> >>>>
> >>>> I find it a bit awkward to have the whole bus address space
> >>>> in the DT given that we're only interested in using the access
> >>>> controller register space.
> >>>>
> >>>>
> >>>> I'm fine with the approach you suggested but I don't see a
> >>>> reason for using it?
> >>> Looking at the "AIPS5 Memory Map" (page 34/35 in i.MX 8M Plus
> >>> Applications Processor Reference Manual, Rev. 3, 08/2024), the
> >>> AIPS5_Configuration is part of the AIPS5 bus. IMHO the bus is something
> >>> different than the bus configuration. Why not model it as part of the
> >>> bus?
> >>>
> >>>>>> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>> index e0d3b8cba221..a1d9b834d2da 100644
> >>>>>> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>> @@ -1399,11 +1399,13 @@ eqos: ethernet at 30bf0000 {
> >>>>>>  			};
> >>>>>>  		};
> >>>>>>
> >>>>>> -		aips5: bus at 30c00000 {
> >>>>>> -			compatible = "fsl,aips-bus", "simple-bus";
> >>>>>> -			reg = <0x30c00000 0x400000>;
> >>>>>> +		aips5: bus at 30df0000 {
> >>>                        ^^^^^^^^^^^^
> >>>>>> +			compatible = "fsl,imx8mp-aipstz", "simple-bus";
> >>>>>> +			reg = <0x30df0000 0x10000>;
> >>>>>> +			power-domains = <&pgc_audio>;
> >>>>>>  			#address-cells = <1>;
> >>>>>>  			#size-cells = <1>;
> >>>>>> +			#access-controller-cells = <0>;
> >>>>>>  			ranges;
> >>>>>>
> >>>>>>  			spba-bus at 30c00000 {
> >>>                         ^^^^^^^^^^^^^^^^^
> >>>
> >>> This looks very strange: The aips5 bus starts at 0x30df0000 and has a
> >>> child bus starting at 0x30c00000?
> >> @30df0000 should match controller reg's address.
> >>
> >> subnode address 0x30c00000,  should be descript in "ranges", which 1:1 map.
> >>
> >> So it should be reasonable. another example:
> >> i2c at 1000 {
> >>
> >> 	device at 1c <- which use difference address space.
> >> }
> >>
> >> The similar case also happen at pcie.
> > I'm not really convinced that pcie and i2c are good examples here. I2C
> > does have an other addressing scheme by nature and the hotplug-able pcie
> > is dependeds on the pcie device memory map of course.
> >
> > Here we're talking about an access control IP core on a bus which is
> > static.
> >
> > But.. it looks like from DT abstraction it's fine because STM did
> > something similiar with their st,stm32mp25-rifsc or st,stm32-etzpc
> > albeit it does look strange and I don't know why we have to limit the
> > address space since it was already mapped but used by the fsl,aips-bus
> > driver.
> >
> > Regards,
> >   Marco
> 
> The address space of the bridge was changed to that of the bridge's
> configuration space because I think it's very awkward from the
> software's point of view to have to hardcode the offset and size of
> the configuration space inside the driver. 

You mean the access-controller IP core. I could also arguee that it's
akward to put the bridge access-controller IP core into the middle of
the bridge address-space instead of placing it at the very beginning of
the bridge. But this doesn't help here :)

I see what you mean but from DT abstraction POV it seems more reasonable
to keep it as it is and just adapt the compatible. The current driver
maps the whole address space too, so I don't see why we need to change
it if we change it to the aipstz driver. If you see the
access-controller IP core as part of the bus I don't see any problem and
would argue that the offset detail needs to be handled within the
driver.

> I also looked at what STM did with "st,stm32-etzpc" so I thought this
> would be acceptable from the DT's POV.
>
> Regarding why I chose not to model the access controller part as a subnode of the
> bus:
> 
> ??? 1) The access controller is part of the bridge itself (not a separate module accessible
> ? ? via the bridge like it's the case for its children) so I think the current approach
> ??? should also make sense if we take the hardware into consideration.

I don't like this approach if you see the controller as part of the
bridge because the offset could be handled within the bridge driver.
I also that the register offset needs to be supplied else we can't reuse
the driver and we don't want to adapt the driver for each SoC.

What came into my mind is the following:

	spba-bus at 30c00000 {
		compatible = "nxp,imx8mp-aiptz-bus", "nxp,aiptz-bus";
		reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;
		reg-names = "bus", "aipstz";

		child-nodes {};
		child-nodes {};
		child-nodes {};
	}

This way we can abstract the access-controller register space and the
whole bus register space and a generic driver could be written just by
making use two reg fields.

> ??? 2) The access controller configuration also impacts the AP. As such, we needed a way to
> ??? enforce a dependency between the children of the aips5 bus and the access controller
> ??? (we could have used the 'access-controllers' property like we did with the DSP but having
> ??? to do that for all children of the bus is not ideal I'd say.
> 
> Of course, argument no. 2 is somewhat brittle in the context of i.MX8MP as the reset
> values of the AC's registers already allow the AP to access said peripherals. Despite this,
> I think the current approach would be more scalable given that the IP offers some more
> configuration bits which we might want to toggle. For that to work, we need to make sure
> the bits are toggled before the AP accesses the peripherals on the bridge.

Please have a look on my suggestion above.

Regards,
  Marco

> Note that we don't do this for aips1-aips4 because it's really not needed. If I'm not mistaken,
> they're not really attached to a PD so we don't need to re-configure them each time the domain
> is power cycled (which is why we can just do it once from ATF during the boot process)


From krzk at kernel.org  Fri Mar  7 07:22:50 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:22:50 +0100
Subject: [PATCH 04/14] ASoC: mediatek: mt8196: add common interface for
 mt8196 DAI driver
In-Reply-To: <20250307124841.23777-5-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-5-darren.ye@mediatek.com>
Message-ID: <a4f94987-90d1-4966-a95d-8a2b15c77996@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Implement sample rate conversion and set private data for mt8196.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  .../soc/mediatek/mt8196/mt8196-afe-control.c  | 109 ++++++++++++++++++
>  1 file changed, 109 insertions(+)
>  create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-control.c
> 
> diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-control.c b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
> new file mode 100644
> index 000000000000..bb85f4ad8585
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *  MediaTek ALSA SoC Audio Control
> + *
> + *  Copyright (c) 2024 MediaTek Inc.
> + *  Author: Darren Ye <darren.ye at mediatek.com>
> + */
> +
> +#include "mt8196-afe-common.h"
> +#include <linux/pm_runtime.h>
> +
> +unsigned int mt8196_general_rate_transform(struct device *dev,
> +					   unsigned int rate)
These are not static, so you miss header for all of these changes.

Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar  7 07:24:36 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:24:36 +0100
Subject: [PATCH 08/14] ASoC: mediatek: mt8196: support I2S in platform
 driver
In-Reply-To: <20250307124841.23777-9-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-9-darren.ye@mediatek.com>
Message-ID: <934d740a-f382-411a-b769-4f9f21a53257@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> +
> +static int etdm_parse_dt(struct mtk_base_afe *afe)
> +{
> +	int ret;
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	struct mtk_afe_i2s_priv *i2sin4_priv = afe_priv->dai_priv[MT8196_DAI_I2S_IN4];
> +	struct mtk_afe_i2s_priv *i2sout4_priv = afe_priv->dai_priv[MT8196_DAI_I2S_OUT4];
> +	unsigned int ch_num_in;
> +	unsigned int ch_num_out;
> +	unsigned int sync_in;
> +	unsigned int sync_out;
> +	unsigned int ip_mode;
> +
> +	/* get etdm ch */
> +	ret = of_property_read_u32(afe->dev->of_node, "mediatek,etdm-out-ch", &ch_num_out);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() failed to read mediatek,etdm-out-ch\n", __func__);
> +		return -EINVAL;
> +	}
> +	i2sout4_priv->ch_num = ch_num_out;
> +	dev_dbg(afe->dev, "%s() mediatek,etdm-out-ch: %d\n", __func__, ch_num_out);
> +
> +	ret = of_property_read_u32(afe->dev->of_node, "mediatek,etdm-in-ch", &ch_num_in);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() failed to read mediatek,etdm-in-ch\n", __func__);
> +		return -EINVAL;
> +	}
> +	i2sin4_priv->ch_num = ch_num_in;
> +	dev_dbg(afe->dev, "%s() mediatek,etdm-in-ch: %d\n", __func__, ch_num_in);
> +
> +	/* get etdm sync */
> +	ret = of_property_read_u32(afe->dev->of_node, "mediatek,etdm-out-sync", &sync_out);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() failed to read mediatek,etdm-out-sync\n", __func__);
> +		return -EINVAL;
> +	}
> +	i2sout4_priv->sync = sync_out;
> +	dev_dbg(afe->dev, "%s() mediatek,etdm-out-sync: %d\n", __func__, sync_out);
> +
> +	ret = of_property_read_u32(afe->dev->of_node, "mediatek,etdm-in-sync", &sync_in);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() failed to read mediatek,etdm-in-sync\n", __func__);
> +		return -EINVAL;
> +	}
> +	i2sin4_priv->sync = sync_in;
> +	dev_dbg(afe->dev, "%s() mediatek,etdm-in-sync: %d\n", __func__, sync_in);
> +
> +	/* get etdm ip mode */
> +	ret = of_property_read_u32(afe->dev->of_node, "mediatek,etdm-ip-mode", &ip_mode);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() failed to read mediatek,etdm-ip-mode\n", __func__);
> +		return -EINVAL;
> +	}
> +	i2sin4_priv->ip_mode = ip_mode;
> +	dev_dbg(afe->dev, "%s() mediatek,etdm-ip-mode: %d\n", __func__, ip_mode);
> +
> +	return 0;
> +}
> +
> +static int mt8196_dai_i2s_get_share(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	const struct device_node *of_node = afe->dev->of_node;
> +	const char *of_str;
> +	const char *property_name;
> +	struct mtk_afe_i2s_priv *i2s_priv;
> +	int i;
> +
> +	for (i = 0; i < DAI_I2S_NUM; i++) {
> +		i2s_priv = afe_priv->dai_priv[mt8196_i2s_priv[i].id];
> +		property_name = mt8196_i2s_priv[i].share_property_name;
> +		if (of_property_read_string(of_node, property_name, &of_str))
> +			continue;
> +		i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str);
> +	}
> +	return 0;
> +}
> +
> +static int mt8196_dai_i2s_set_priv(struct mtk_base_afe *afe)
> +{
> +	int i;
> +	int ret;
> +
> +	for (i = 0; i < DAI_I2S_NUM; i++) {
> +		ret = mt8196_dai_set_priv(afe, mt8196_i2s_priv[i].id,
> +					  sizeof(struct mtk_afe_i2s_priv),
> +					  &mt8196_i2s_priv[i]);
> +		if (ret)
> +			return ret;
> +	}
> +	return 0;
> +}
> +
> +int mt8196_dai_i2s_register(struct mtk_base_afe *afe)
> +{
> +	struct mtk_base_afe_dai *dai;
> +	int ret;
> +
> +	dev_dbg(afe->dev, "%s() successfully start\n", __func__);

Well, no. Tracing is for debugging entry/exit of functions. Say
something useful or just drop such entry/exist success messages.

> +
> +	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
> +	if (!dai)
> +		return -ENOMEM;
> +
> +	list_add(&dai->list, &afe->sub_dais);
> +
> +	dai->dai_drivers = mtk_dai_i2s_driver;
> +	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
> +
> +	dai->controls = mtk_dai_i2s_controls;
> +	dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);
> +	dai->dapm_widgets = mtk_dai_i2s_widgets;
> +	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
> +	dai->dapm_routes = mtk_dai_i2s_routes;
> +	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
> +
> +	/* set all dai i2s private data */
> +	ret = mt8196_dai_i2s_set_priv(afe);
> +	if (ret)
> +		return ret;
> +
> +	/* parse share i2s */
> +	ret = mt8196_dai_i2s_get_share(afe);
> +	if (ret)
> +		return ret;
> +
> +	/* for customer to change ch_num & sync & ipmode from dts */
> +	ret = etdm_parse_dt(afe);
> +	if (ret) {
> +		dev_info(afe->dev, "%s() fail to parse dts: %d\n", __func__, ret);

Why do you print errors twice?

> +		return ret;
> +	}
> +
> +	return 0;
> +}


Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar  7 07:32:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:32:02 +0100
Subject: [PATCH 05/14] ASoC: mediatek: mt8196: support audio clock control
In-Reply-To: <20250307124841.23777-6-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-6-darren.ye@mediatek.com>
Message-ID: <13f286c5-fce6-44d9-8965-c6422cd43b30@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> +
> +int mt8196_init_clock(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	int i = 0;
> +
> +	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
> +				     GFP_KERNEL);
> +	if (!afe_priv->clk)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < CLK_NUM; i++) {
> +		if (!aud_clks[i]) {
> +			dev_err(afe->dev, "%s(), clk id %d not define!!!\n",
> +				__func__, i);
> +		}
> +
> +		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
> +		if (IS_ERR(afe_priv->clk[i])) {
> +			dev_err(afe->dev, "%s devm_clk_get %s fail, ret %ld\n",
> +				__func__,

dev_err_probe() and drop __func__ and ret.


> +				aud_clks[i], PTR_ERR(afe_priv->clk[i]));
> +			afe_priv->clk[i] = NULL;
> +		}
> +	}
> +
> +	afe_priv->vlp_ck = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
> +							   "vlpcksys");
> +	if (IS_ERR(afe_priv->vlp_ck)) {
> +		dev_err(afe->dev, "%s() Cannot find vlpcksys: %ld\n",
> +			__func__, PTR_ERR(afe_priv->vlp_ck));
> +		afe_priv->vlp_ck = NULL;
> +	}
> +
> +	afe_priv->cksys_ck = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
> +							     "cksys");
> +	if (IS_ERR(afe_priv->cksys_ck)) {
> +		dev_err(afe->dev, "%s() Cannot find cksys controller: %ld\n",
> +			__func__, PTR_ERR(afe_priv->cksys_ck));
Eeach of my comments apply to entier code to all patches. You keep
repeating same patterns from downstream. You should rather take upstream
drivers as your base.

Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar  7 07:32:39 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:32:39 +0100
Subject: [PATCH 11/14] ASoC: mediatek: mt8196: add platform driver
In-Reply-To: <20250307124841.23777-12-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-12-darren.ye@mediatek.com>
Message-ID: <92ecfdc3-3feb-41ec-8cc9-0379e3c951bb@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> +
> +static int mt8196_afe_runtime_suspend(struct device *dev)
> +{
> +	struct mtk_base_afe *afe = dev_get_drvdata(dev);
> +	unsigned int value = 0;
> +	unsigned int tmp_reg = 0;
> +	int ret = 0, i;
> +
> +	dev_dbg(afe->dev, "%s() ready to stop\n", __func__);

Core already provides this. Drop.

> +
> +	if (!afe->regmap) {
> +		dev_info(afe->dev, "%s() skip regmap\n", __func__);
> +		goto skip_regmap;
> +	}
> +
> +	/* Add to be off for free run*/
> +	/* disable AFE */
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, 0x1, 0x0);
> +
> +	ret = regmap_read_poll_timeout(afe->regmap,
> +				       AUDIO_ENGEN_CON0_MON,
> +				       value,
> +				       (value & AUDIO_ENGEN_MON_SFT) == 0,
> +				       20,
> +				       1 * 1000 * 1000);
> +	dev_dbg(afe->dev, "%s() read_poll ret %d\n", __func__, ret);
> +	if (ret)
> +		dev_info(afe->dev, "%s(), ret %d\n", __func__, ret);
> +
> +	/* make sure all irq status are cleared */
> +	for (i = 0; i < MT8196_IRQ_NUM; ++i) {
> +		regmap_read(afe->regmap, irq_data[i].irq_clr_reg, &tmp_reg);
> +		regmap_update_bits(afe->regmap, irq_data[i].irq_clr_reg,
> +				   AFE_IRQ_CLR_CFG_MASK_SFT | AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT,
> +				   tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT |
> +				   AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT));
> +	}
> +
> +	/* reset sgen */
> +	regmap_write(afe->regmap, AFE_SINEGEN_CON0, 0x0);
> +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON1,
> +			   SINE_DOMAIN_MASK_SFT,
> +			   0x0 << SINE_DOMAIN_SFT);
> +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON1,
> +			   SINE_MODE_MASK_SFT,
> +			   0x0 << SINE_MODE_SFT);
> +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON1,
> +			   INNER_LOOP_BACKI_SEL_MASK_SFT,
> +			   0x0 << INNER_LOOP_BACKI_SEL_SFT);
> +	regmap_update_bits(afe->regmap, AFE_SINEGEN_CON1,
> +			   INNER_LOOP_BACK_MODE_MASK_SFT,
> +			   0xff << INNER_LOOP_BACK_MODE_SFT);
> +
> +	regmap_write(afe->regmap, AUDIO_TOP_CON4, 0x3fff);
> +
> +	/* reset audio 26M request */
> +	regmap_update_bits(afe->regmap,
> +			   AFE_SPM_CONTROL_REQ, 0x1, 0x0);
> +
> +	/* cache only */
> +	regcache_cache_only(afe->regmap, true);
> +	regcache_mark_dirty(afe->regmap);
> +
> +skip_regmap:
> +	mt8196_afe_disable_clock(afe);
> +	return 0;
> +}
> +
> +static int mt8196_afe_runtime_resume(struct device *dev)
> +{
> +	struct mtk_base_afe *afe = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = mt8196_afe_enable_clock(afe);
> +	dev_dbg(afe->dev, "%s(), enable_clock ret %d\n", __func__, ret);

So you are debugging every call. I think you do not trust your code, right?

> +
> +	if (ret)
> +		return ret;
> +
> +	if (!afe->regmap) {
> +		dev_info(afe->dev, "%s() skip regmap\n", __func__);

Why dev_info? How is this condition even possible?


> +		goto skip_regmap;
> +	}
> +	regcache_cache_only(afe->regmap, false);
> +	regcache_sync(afe->regmap);
> +
> +	/* set audio 26M request */
> +	regmap_update_bits(afe->regmap, AFE_SPM_CONTROL_REQ, 0x1, 0x1);
> +
> +	/* IPM2.0: Clear AUDIO_TOP_CON4 for enabling AP side module clk */
> +	regmap_write(afe->regmap, AUDIO_TOP_CON4, 0x0);
> +
> +	/* Add to be on for free run */
> +	regmap_write(afe->regmap, AUDIO_TOP_CON0, 0x0);
> +	regmap_write(afe->regmap, AUDIO_TOP_CON1, 0x0);
> +	regmap_write(afe->regmap, AUDIO_TOP_CON2, 0x0);
> +
> +	/* Can't set AUDIO_TOP_CON3 to be 0x0, it will hang in FPGA env */
> +	regmap_write(afe->regmap, AUDIO_TOP_CON3, 0x0);
> +
> +	regmap_update_bits(afe->regmap, AFE_CBIP_CFG0, 0x1, 0x1);
> +
> +	/* force cpu use 8_24 format when writing 32bit data */
> +	regmap_update_bits(afe->regmap, AFE_MEMIF_CON0,
> +			   CPU_HD_ALIGN_MASK_SFT, 0 << CPU_HD_ALIGN_SFT);
> +
> +	/* enable AFE */
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, 0x1, 0x1);
> +
> +skip_regmap:
> +	return 0;


...

> +
> +typedef int (*dai_register_cb)(struct mtk_base_afe *);
> +static const dai_register_cb dai_register_cbs[] = {
> +	mt8196_dai_adda_register,
> +	mt8196_dai_i2s_register,
> +	mt8196_dai_tdm_register,
> +	mt8196_dai_memif_register,
> +};
> +
> +static int mt8196_afe_pcm_dev_probe(struct platform_device *pdev)
> +{
> +	int ret, i;
> +	unsigned int tmp_reg = 0;
> +	int irq_id;
> +	struct mtk_base_afe *afe;
> +	struct mt8196_afe_private *afe_priv;
> +	struct resource *res;
> +	struct device *dev;
> +
> +	pr_info("+%s()\n", __func__);

No, drop.

> +
> +	ret = of_reserved_mem_device_init(&pdev->dev);
> +	if (ret)
> +		dev_dbg(&pdev->dev, "failed to assign memory region: %d\n", ret);
> +
> +	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
> +	if (ret)
> +		return ret;
> +
> +	afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
> +	if (!afe)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, afe);
> +
> +	afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
> +					  GFP_KERNEL);
> +	if (!afe->platform_priv)
> +		return -ENOMEM;
> +
> +	afe_priv = afe->platform_priv;
> +
> +	afe->dev = &pdev->dev;
> +	dev = afe->dev;
> +
> +	/* init audio related clock */
> +	ret = mt8196_init_clock(afe);
> +	if (ret) {
> +		dev_info(dev, "init clock error: %d\n", ret);

How are you handling deferred probe? Why aren't you using dev_err_probe?

But more important - why do you keep printing errors multiple times,
including ENOMEM?

This is really poor coding style.

> +		return ret;
> +	}
> +
> +	pm_runtime_enable(&pdev->dev);
> +	if (!pm_runtime_enabled(&pdev->dev))
> +		goto err_pm_disable;
> +
> +	/* Audio device is part of genpd.
> +	 * Set audio as syscore device to prevent
> +	 * genpd automatically power off audio
> +	 * device when suspend
> +	 */
> +	dev_pm_syscore_device(&pdev->dev, true);
> +
> +	/* regmap init */
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(afe->base_addr))
> +		return PTR_ERR(afe->base_addr);
> +
> +	/* enable clock for regcache get default value from hw */
> +	pm_runtime_get_sync(&pdev->dev);
> +
> +	afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
> +					    &mt8196_afe_regmap_config);
> +	if (IS_ERR(afe->regmap))
> +		return PTR_ERR(afe->regmap);
> +
> +	/* IPM2.0 clock flow, need debug */
> +
> +	regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
> +	regmap_write(afe->regmap, AFE_IRQ_MCU_EN, 0xffffffff);
> +	regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
> +	/* IPM2.0 clock flow, need debug */
> +
> +	pm_runtime_put_sync(&pdev->dev);
> +
> +	regcache_cache_only(afe->regmap, true);
> +	regcache_mark_dirty(afe->regmap);
> +
> +	/* init gpio */
> +	ret = mt8196_afe_gpio_init(afe);
> +	if (ret)
> +		dev_info(dev, "init gpio error\n");

Do not print errors twice.

> +
> +	/* init memif */
> +	/* IPM2.0 no need banding */
> +	afe->memif_32bit_supported = 1;
> +	afe->memif_size = MT8196_MEMIF_NUM;
> +	afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
> +				  GFP_KERNEL);
> +
> +	if (!afe->memif)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < afe->memif_size; i++) {
> +		afe->memif[i].data = &memif_data[i];
> +		afe->memif[i].irq_usage = memif_irq_usage[i];
> +		afe->memif[i].const_irq = 1;
> +	}
> +
> +	mutex_init(&afe->irq_alloc_lock);       /* needed when dynamic irq */
> +
> +	/* init irq */
> +	afe->irqs_size = MT8196_IRQ_NUM;
> +	afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
> +				 GFP_KERNEL);
> +

Drop blank line

> +	if (!afe->irqs)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < afe->irqs_size; i++)
> +		afe->irqs[i].irq_data = &irq_data[i];
> +
> +	/* request irq */
> +	irq_id = platform_get_irq(pdev, 0);
> +	if (irq_id <= 0) {

Please read documentation of platform_get_irq().

> +		dev_info(dev, "%pOFn no irq found\n", dev->of_node);

Why dev_info?

> +		return irq_id < 0 ? irq_id : -ENXIO;
> +	}
> +	ret = devm_request_irq(dev, irq_id, mt8196_afe_irq_handler,
> +			       IRQF_TRIGGER_NONE,
> +			       "Afe_ISR_Handle", (void *)afe);
> +	if (ret) {
> +		dev_info(dev, "could not request_irq for Afe_ISR_Handle\n");
> +		return ret;
> +	}
> +	ret = enable_irq_wake(irq_id);
> +	if (ret < 0)
> +		dev_info(dev, "enable_irq_wake %d err: %d\n", irq_id, ret);
> +
> +	/* init sub_dais */
> +	INIT_LIST_HEAD(&afe->sub_dais);
> +
> +	for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
> +		ret = dai_register_cbs[i](afe);
> +		if (ret) {
> +			dev_info(afe->dev, "dai register i %d fail, ret %d\n",
> +				 i, ret);
> +			goto err_pm_disable;
> +		}
> +	}
> +
> +	/* init dai_driver and component_driver */
> +	ret = mtk_afe_combine_sub_dai(afe);
> +	if (ret) {
> +		dev_info(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
> +			 ret);
> +		goto err_pm_disable;
> +	}
> +
> +	/* others */
> +	afe->mtk_afe_hardware = &mt8196_afe_hardware;
> +	afe->memif_fs = mt8196_memif_fs;
> +	afe->irq_fs = mt8196_irq_fs;
> +	afe->get_dai_fs = mt8196_get_dai_fs;
> +	afe->get_memif_pbuf_size = mt8196_get_memif_pbuf_size;
> +
> +	afe->runtime_resume = mt8196_afe_runtime_resume;
> +	afe->runtime_suspend = mt8196_afe_runtime_suspend;
> +
> +	afe->request_dram_resource = mt8196_afe_dram_request;
> +	afe->release_dram_resource = mt8196_afe_dram_release;
> +
> +	/* register component */
> +	ret = devm_snd_soc_register_component(&pdev->dev,
> +					      &mt8196_afe_component,
> +					      afe->dai_drivers,
> +					      afe->num_dai_drivers);
> +	if (ret) {
> +		dev_info(dev, "afe component err: %d\n", ret);

Why not dev_err? You have this unusual pattern all over your code.

> +		goto err_pm_disable;
> +	}
> +	return 0;
> +
> +err_pm_disable:
> +	pm_runtime_disable(&pdev->dev);
> +	return ret;
> +}



Best regards,
Krzysztof


From Frank.li at nxp.com  Fri Mar  7 07:32:39 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 7 Mar 2025 10:32:39 -0500
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <Z8d96Qbggv117LlO@lizhi-Precision-Tower-5810>
References: <Z8YlySM6Xtr0beo1@lizhi-Precision-Tower-5810>
 <20250304175010.GA207565@bhelgaas>
 <Z8d6qpNaL4eJRQI1@lizhi-Precision-Tower-5810>
 <Z8d96Qbggv117LlO@lizhi-Precision-Tower-5810>
Message-ID: <Z8sRl1c//SZXKhB+@lizhi-Precision-Tower-5810>

On Tue, Mar 04, 2025 at 05:25:45PM -0500, Frank Li wrote:
> On Tue, Mar 04, 2025 at 05:11:54PM -0500, Frank Li wrote:
> > On Tue, Mar 04, 2025 at 11:50:10AM -0600, Bjorn Helgaas wrote:
> > > On Mon, Mar 03, 2025 at 04:57:29PM -0500, Frank Li wrote:
> > > > On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> > > > > On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > > > > > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > > > > > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > > > > > for PCI controllers with address translation units.
> > > > > >
> > > > > > Typical PCI data flow involves:
> > > > > >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> > > > > >   PCI Controller (PCI bus address) -> PCI Bus.
> > > > > >
> > > > > > While most bus fabrics preserve address consistency, some modify addresses
> > > > > > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > > > > > translate these intermediate addresses correctly to PCI bus addresses.
> > > > > >
> > > > > > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > > > > > PCI controller drivers.
> > > > > > ...
> > > > >
> > > > > > +++ b/drivers/pci/of.c
> > > > > > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> > > > > >  			res->flags &= ~IORESOURCE_MEM_64;
> > > > > >  		}
> > > > > >
> > > > > > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > > > > > +		/*
> > > > > > +		 * IORESOURCE_IO res->start is io space start address.
> > > > > > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > > > > > +		 * same as range.cpu_addr.
> > > > > > +		 *
> > > > > > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > > > > > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > > > > > +		 */
> > > > > > +
> > > > > > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > > > > > +						   range.cpu_addr - range.parent_bus_addr);
> > > > >
> > > > > I don't know exactly where it needs to go, but I think we can call
> > > > > .cpu_addr_fixup() once at startup on the base of the region.  This
> > > > > will tell us the offset that applies to the entire region, i.e.,
> > > > > parent_bus_offset.
> > > > >
> > > > > Then we can remove all the .cpu_addr_fixup() calls in
> > > > > cdns_pcie_host_init_address_translation(),
> > > > > cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
> > > > >
> > > > > Until we can get rid of all the .cpu_addr_fixup() implementations,
> > > > > We'll still have that single call at startup (I guess once for cadence
> > > > > and another for designware), but it should simplify the current
> > > > > callers quite a bit.
> > > >
> > > > I don't think it can simple code. cdns_pcie_set_outbound_region() and
> > > > dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
> > > > "resource" to manage outbound windows.
> > >
> > > Let's ignore cadence for now.  I don't think we need to solve that
> > > until later.
> > >
> > > dw_pcie_prog_outbound_atu() is called by:
> > >
> > >   - dw_pcie_other_conf_map_bus(): atu.parent_bus_addr = pp->cfg0_base
> > >
> > >     I think dw_pcie_host_init() can set pp->cfg0_base with the correct
> > >     intermediate address, either via the the of_property_read_reg() or
> > >     .cpu_addr_fixup().
>
> And chicken and egg problem here for artpec6_pcie_cpu_addr_fixup(), which
> need cfg0_base. But try to use .cpu_addr_fixup() to get cfg0_base's
> intermediate address.

Bjorn:
	Do you have chance to check my reply? some dwc platform driver
.cpu_addr_fixup() implement have dependence with old initilize sequency.

	Can I use original method? If change each driver's .cpu_addr_fixup()
implement, it will involve more risk, even more than directly clean it as
my RFC patch.

Frank
>
> Frank
>
> > >
> > >     If dw_pcie_host_init() does this, then we don't need
> > >     .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
> > >
> > >   - dw_pcie_rd_other_conf(): atu.parent_bus_addr = pp->io_base
> > >
> > >     Similarly, dw_pcie_host_init() should be able to set pp->io_base
> > >     to the intermediate address, so we don't need .cpu_addr_fixup() in
> > >     dw_pcie_prog_outbound_atu().
> >
> > I found some driver's cpu_addr_fixup()'s implement depend on the
> > initilize sequence.
> >
> > for example:
> > 	pcie-artpec6.c
> >
> > static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
> > {
> >         struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
> >         struct dw_pcie_rp *pp = &pci->pp;
> >         struct dw_pcie_ep *ep = &pci->ep;
> >
> >         switch (artpec6_pcie->mode) {
> >         case DW_PCIE_RC_TYPE:
> >                 return cpu_addr - pp->cfg0_base;
> >         case DW_PCIE_EP_TYPE:
> >                 return cpu_addr - ep->phys_base;
> >         default:
> >                 dev_err(pci->dev, "UNKNOWN device type\n");
> >         }
> >         return cpu_addr;
> > }
> >
> > This implement require *cfg0_base* and *phys_base*, pp/ep, need set before
> > call artpec6_pcie_cpu_addr_fixup().
> >
> > static u64 visconti_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
> > {
> >         struct dw_pcie_rp *pp = &pci->pp;
> >
> >         return cpu_addr & ~pp->io_base;
> > }
> >
> > this one require *io_base* and *pp* need be set before call
> > visconti_pcie_cpu_addr_fixup()
> >
> > Because I have not such hardware platform, it is not trivial change and
> > it is hard to involve bugs.
> >
> > If move .cpu_addr_fixup() too early, it will cause kernel dump.
> >
> > I suggest keep current overall sequent and try to clean up these driver's
> > cpu_addr_fixup() firstly.
> >
> > Frank
> >
> > >
> > >   - dw_pcie_iatu_setup(): atu.parent_bus_addr = entry->res->start
> > >
> > >     Here "entry" iterates through bridge->windows, and we should be
> > >     able to set entry->parent_bus_offset at init-time, using
> > >     .cpu_addr_fixup() if necessary, so we can apply that offset
> > >     unconditionally, regardless of use_parent_dt_ranges, and we won't
> > >     need .cpu_addr_fixup() in dw_pcie_prog_outbound_atu().
> > >
> > >   - dw_pcie_pme_turn_off:
> > >     atu.parent_bus_addr = pci->pp.msg_res->start - pci->pp.msg_parent_bus_offset
> > >
> > >     This should be the same as dw_pcie_iatu_setup() since
> > >     msg_parent_bus_offset comes from the window iteration in
> > >     dw_pcie_host_request_msg_tlp_res().  As long as the windows have
> > >     the correct parent_bus_offset at init-time, we should be all set.


From conor at kernel.org  Fri Mar  7 07:33:05 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:33:05 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
Message-ID: <20250307-everyone-ragweed-e05a10a9646b@spud>

On Fri, Mar 07, 2025 at 03:14:05PM +0000, John Madieu wrote:
> Hi Conor,
> 
> Thanks for your review!
> 
> > -----Original Message-----
> > From: Conor Dooley <conor at kernel.org>
> > Sent: Friday, February 28, 2025 8:03 PM
> > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> > the TSU unit
> > 
> > On Thu, Feb 27, 2025 at 01:24:39PM +0100, John Madieu wrote:
> > > The Renesas RZ/G3E SoC includes a Thermal Sensor Unit (TSU) block
> > > designed to measure the junction temperature. The device provides
> > > real-time temperature measurements for thermal management, utilizing a
> > > single dedicated channel (channel 1) for temperature sensing.
> > >
> > > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > > ---
> > > v1 -> v2:
> > >  * Fix reg property specifier to get rid of yamlint warnings
> > >  * Fix IRQ name to reflect TSU expectations
> > >
> > >  .../thermal/renesas,r9a09g047-tsu.yaml        | 123 ++++++++++++++++++
> > >  1 file changed, 123 insertions(+)
> > >  create mode 100644
> > > Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> > > b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> > > new file mode 100644
> > > index 000000000000..e786561ddbe3
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.
> > > +++ yaml
> > > @@ -0,0 +1,123 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> > > +---
> > > +$id:
> > > +http://devicetree.org/schemas/thermal/renesas,r9a09g047-tsu.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Renesas RZ/G3E Temperature Sensor Unit (TSU)
> > > +
> > > +maintainers:
> > > +  - John Madieu <john.madieu.xa at bp.renesas.com>
> > > +
> > > +description:
> > > +  The Temperature Sensor Unit (TSU) is an integrated thermal sensor
> > > +that
> > > +  monitors the chip temperature on the Renesas RZ/G3E SoC. The TSU
> > > +provides
> > > +  real-time temperature measurements for thermal management.
> > > +
> > > +properties:
> > > +  compatible:
> > > +    const: renesas,r9a09g047-tsu
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  clocks:
> > > +    maxItems: 1
> > > +
> > > +  resets:
> > > +    maxItems: 1
> > > +
> > > +  power-domains:
> > > +    maxItems: 1
> > > +
> > > +  interrupts:
> > > +    description: |
> > > +      Interrupt specifiers for the TSU:
> > > +      - S12TSUADI1: Conversion complete interrupt signal (pulse)
> > > +      - S12TSUADCMPI1: Comparison result interrupt signal (level)
> > > +
> > > +  interrupt-names:
> > > +    items:
> > > +      - const: adi
> > > +      - const: adcmpi
> > > +
> > > +  "#thermal-sensor-cells":
> > > +    const: 0
> > > +
> > > +  renesas,tsu-calibration-sys:
> > > +    $ref: /schemas/types.yaml#/definitions/phandle
> > > +    description: |
> > > +      Phandle to the system controller (sys) that contains the TSU
> > > +      calibration values used for temperature calculations.
> > > +
> > > +  renesas,tsu-operating-mode:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > +    enum: [0, 1]
> > > +    description: |
> > > +      TSU operating mode:
> > > +      0: Mode 0 - Conversion started by software
> > > +      1: Mode 1 - Conversion started by ELC trigger
> > 
> > Can you make this "software" and "elc" or something please, unless people
> > will genuinely find "0" and 1" to be more informative.
> > And why doesn't the property have a default?
> 
> Sorry for miss-specifying.
> ELC is an external event trigger. May be should I specify it like that ?

If "elc trigger" is meaningful to people using hte device (IOW, it
matches datasheet wording) then that's fine I think.

> To make sure I got your point, do you mean specifying a default value in
> bindings ?

The property doesn't actually need to be required, it could easily have
a default (say software) and only be set in the case of using the elc
trigger - which brings you to Rob's comment that it can just be a
boolean, setting the property if elc and leaving it out of software.

Rob's other comment was

| Who/what decides the mode? If a user is going to want to change this, 
| then it should be a runtime control, not a DT property.

which I think needs an answer ;)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/bc777dc6/attachment.sig>

From krzk at kernel.org  Fri Mar  7 07:33:22 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:33:22 +0100
Subject: [PATCH 10/14] ASoC: mediatek: mt8196: support CM in platform
 driver
In-Reply-To: <20250307124841.23777-11-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-11-darren.ye@mediatek.com>
Message-ID: <40bb42ca-52f5-4579-a9c7-58e6ff5dbbb5@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> +int mt8196_enable_cm_bypass(struct mtk_base_afe *afe, int id, bool en)
> +{
> +	int reg = AFE_CM0_CON0 + 0x10 * id;
> +
> +	mtk_regmap_update_bits(afe->regmap, reg, AFE_CM_BYPASS_MODE_MASK,
> +			       en, AFE_CM_BYPASS_MODE_SFT);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(mt8196_enable_cm_bypass);
> +
> +MODULE_DESCRIPTION("Mediatek afe cm");
> +MODULE_AUTHOR("darren ye <darren.ye at mediatek.com>");
> +MODULE_LICENSE("GPL");

If this is module, where is Makefile and Kconfig?

All previous comments about missing kerneldoc also apply.

Best regards,
Krzysztof


From acme at kernel.org  Fri Mar  7 07:34:48 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Fri,  7 Mar 2025 12:34:48 -0300
Subject: [PATCH 1/1 next] perf libunwind: Fixup conversion perf_sample->user_regs to a pointer
Message-ID: <20250307153448.250871-1-acme@kernel.org>

From: Arnaldo Carvalho de Melo <acme at redhat.com>

The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
the changes to a file, resulting in this problem:

  $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
  <SNIP>
    CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
    CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
  <SNIP>
  util/unwind-libunwind-local.c: In function ?access_mem?:
  util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
    582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
        |                                                        ^
        |                                                        ->
  util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
    587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
        |                                      ^~~~~~~~~~~~~~~~~~~~~~
        |                                      |
        |                                      struct regs_dump **
<SNIP>
  ? [acme at toolbox perf-tools-next]$ git bisect bad
  dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
  commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
  Author: Ian Rogers <irogers at google.com>
  Date:   Mon Jan 13 11:43:45 2025 -0800

      perf sample: Make user_regs and intr_regs optional

Detected using:

  make -C tools/perf build-test

Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Charlie Jenkins <charlie at rivosinc.com>
Cc: Ian Rogers <irogers at google.com>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: James Clark <james.clark at linaro.org>
Cc: John Garry <john.g.garry at oracle.com>
Cc: Kan Liang <kan.liang at linux.intel.com>
Cc: Leo Yan <leo.yan at linux.dev>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Michael Petlan <mpetlan at redhat.com>
Cc: Namhyung Kim <namhyung at kernel.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Tavian Barnes <tavianator at tavianator.com>
Cc: Veronika Molnarova <vmolnaro at redhat.com>
Cc: coresight at lists.linaro.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>
---
 tools/perf/util/unwind-libunwind-local.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 16c2b03831f39afc..cc0e41f2c2f2ef10 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -579,12 +579,12 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
 	int ret;
 
 	/* Don't support write, probably not needed. */
-	if (__write || !stack || !ui->sample->user_regs.regs) {
+	if (__write || !stack || !ui->sample->user_regs->regs) {
 		*valp = 0;
 		return 0;
 	}
 
-	ret = perf_reg_value(&start, &ui->sample->user_regs,
+	ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample),
 			     perf_arch_reg_sp(arch));
 	if (ret)
 		return ret;
@@ -628,7 +628,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
 		return 0;
 	}
 
-	if (!ui->sample->user_regs.regs) {
+	if (!ui->sample->user_regs->regs) {
 		*valp = 0;
 		return 0;
 	}
@@ -637,7 +637,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
 	if (id < 0)
 		return -EINVAL;
 
-	ret = perf_reg_value(&val, &ui->sample->user_regs, id);
+	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id);
 	if (ret) {
 		if (!ui->best_effort)
 			pr_err("unwind: can't read reg %d\n", regnum);
@@ -741,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
 	unw_cursor_t c;
 	int ret, i = 0;
 
-	ret = perf_reg_value(&val, &ui->sample->user_regs,
+	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample),
 			     perf_arch_reg_ip(arch));
 	if (ret)
 		return ret;
@@ -808,7 +808,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 		.best_effort  = best_effort
 	};
 
-	if (!data->user_regs.regs)
+	if (!data->user_regs->regs)
 		return -EINVAL;
 
 	if (max_stack <= 0)
-- 
2.47.0



From conor at kernel.org  Fri Mar  7 07:35:24 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:35:24 +0000
Subject: [PATCH 1/2] dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
In-Reply-To: <20250307120004.959980-2-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <20250307120004.959980-2-amadeus@jmu.edu.cn>
Message-ID: <20250307-paddle-zoology-89858b29061d@spud>

On Fri, Mar 07, 2025 at 08:00:03PM +0800, Chukun Pan wrote:
> Document pwm compatible for rk3528 which is fallback compatible
> of rk3328-pwm group.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
> index e4e1976c542d..c8cdfb723336 100644
> --- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
> +++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
> @@ -30,6 +30,7 @@ properties:
>            - enum:
>                - rockchip,px30-pwm
>                - rockchip,rk3308-pwm
> +              - rockchip,rk3528-pwm
>                - rockchip,rk3562-pwm
>                - rockchip,rk3568-pwm
>                - rockchip,rk3588-pwm
> -- 
> 2.25.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/4d5b530c/attachment.sig>

From conor at kernel.org  Fri Mar  7 07:37:54 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:37:54 +0000
Subject: [PATCH v4 1/4] dt-bindings: interrupt-controller: Add support
 for Amlogic A4 and A5 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-1-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
 <20250307-irqchip-gpio-a4-a5-v4-1-d03a9424151b@amlogic.com>
Message-ID: <20250307-villain-blustery-8668e70cc005@spud>

On Fri, Mar 07, 2025 at 04:49:22PM +0800, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> 
> Update dt-binding document for GPIO interrupt controller
> of Amlogic A4 and A5 SoCs
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  .../interrupt-controller/amlogic,meson-gpio-intc.yaml | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> index a93744763787..3d60d9e9e208 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
> @@ -35,6 +35,9 @@ properties:
>                - amlogic,meson-sm1-gpio-intc
>                - amlogic,meson-a1-gpio-intc
>                - amlogic,meson-s4-gpio-intc
> +              - amlogic,a4-gpio-intc
> +              - amlogic,a4-gpio-ao-intc
> +              - amlogic,a5-gpio-intc
>                - amlogic,c3-gpio-intc
>                - amlogic,t7-gpio-intc
>            - const: amlogic,meson-gpio-intc
> @@ -49,7 +52,7 @@ properties:
>  
>    amlogic,channel-interrupts:
>      description: Array with the upstream hwirq numbers
> -    minItems: 8
> +    minItems: 2
>      maxItems: 12
>      $ref: /schemas/types.yaml#/definitions/uint32-array
>  
> @@ -60,6 +63,20 @@ required:
>    - "#interrupt-cells"
>    - amlogic,channel-interrupts
>  
> +if:
> +  properties:
> +    compatible:
> +      contains:
> +        const: amlogic,a4-gpio-ao-intc
> +then:
> +  properties:
> +    amlogic,channel-interrupts:
> +      maxItems: 2
> +else:
> +  properties:
> +    amlogic,channel-interrupts:
> +      minItems: 8
> +
>  additionalProperties: false
>  
>  examples:
> 
> -- 
> 2.37.1
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/a3ef9139/attachment.sig>

From conor at kernel.org  Fri Mar  7 07:42:36 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:42:36 +0000
Subject: [PATCH 1/4] dt-bindings: net: rockchip-dwmac: Add compatible
 string for RK3528
In-Reply-To: <20250306221402.1704196-2-jonas@kwiboo.se>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-2-jonas@kwiboo.se>
Message-ID: <20250307-tipping-womanlike-a1ce2370d8d3@spud>

On Thu, Mar 06, 2025 at 10:13:54PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
> Ethernet QoS IP.
> 
> Add compatible string for the RK3528 variant.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
> I was not able to restrict the minItems change to only apply to the new
> compatible, please advise on how to properly restrict the minItems
> change if needed.

What do you mean by that? As in, what did you try and did not work?
Usually you do something like
if:
  not:
    compatible:
      contains:
        rockchip,rk3528-gmac
then:
  properties:
    clocks:
      minItems: 5

> 
> Also, because snps,dwmac-4.20a is already listed in snps,dwmac.yaml
> adding the rockchip,rk3528-gmac compatible did not seem necessary.
> ---
>  Documentation/devicetree/bindings/net/rockchip-dwmac.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
> index 05a5605f1b51..3c25b49bd78e 100644
> --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
> @@ -24,6 +24,7 @@ select:
>            - rockchip,rk3366-gmac
>            - rockchip,rk3368-gmac
>            - rockchip,rk3399-gmac
> +          - rockchip,rk3528-gmac
>            - rockchip,rk3568-gmac
>            - rockchip,rk3576-gmac
>            - rockchip,rk3588-gmac
> @@ -49,6 +50,7 @@ properties:
>                - rockchip,rv1108-gmac
>        - items:
>            - enum:
> +              - rockchip,rk3528-gmac
>                - rockchip,rk3568-gmac
>                - rockchip,rk3576-gmac
>                - rockchip,rk3588-gmac
> @@ -56,7 +58,7 @@ properties:
>            - const: snps,dwmac-4.20a
>  
>    clocks:
> -    minItems: 5
> +    minItems: 4
>      maxItems: 8
>  
>    clock-names:
> -- 
> 2.48.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/8a70bf54/attachment.sig>

From steven.price at arm.com  Fri Mar  7 07:43:51 2025
From: steven.price at arm.com (Steven Price)
Date: Fri, 7 Mar 2025 15:43:51 +0000
Subject: [PATCH v7 12/45] arm64: RME: Allocate/free RECs to match vCPUs
In-Reply-To: <7639eca7-8fd8-491c-90bd-1be084fbd710@redhat.com>
References: <20250213161426.102987-1-steven.price@arm.com>
 <20250213161426.102987-13-steven.price@arm.com>
 <7639eca7-8fd8-491c-90bd-1be084fbd710@redhat.com>
Message-ID: <4566d2d1-1f59-49e3-ad75-45c27ac4dfda@arm.com>

Hi Gavin,

On 03/03/2025 07:08, Gavin Shan wrote:
> On 2/14/25 2:13 AM, Steven Price wrote:
>> The RMM maintains a data structure known as the Realm Execution Context
>> (or REC). It is similar to struct kvm_vcpu and tracks the state of the
>> virtual CPUs. KVM must delegate memory and request the structures are
>> created when vCPUs are created, and suitably tear down on destruction.
>>
>> RECs must also be supplied with addition pages - auxiliary (or AUX)
>> granules - for storing the larger registers state (e.g. for SVE). The
>> number of AUX granules for a REC depends on the parameters with which
>> the Realm was created - the RMM makes this information available via the
>> RMI_REC_AUX_COUNT call performed after creating the Realm Descriptor
>> (RD).
>>
>> Note that only some of register state for the REC can be set by KVM, the
>> rest is defined by the RMM (zeroed). The register state then cannot be
>> changed by KVM after the REC is created (except when the guest
>> explicitly requests this e.g. by performing a PSCI call). The RMM also
>> requires that the VMM creates RECs in ascending order of the MPIDR.
>>
>> See Realm Management Monitor specification (DEN0137) for more
>> information:
>> https://developer.arm.com/documentation/den0137/
>>
>> Signed-off-by: Steven Price <steven.price at arm.com>
>> ---
>> Changes since v6:
>> ? * Avoid reporting the KVM_ARM_VCPU_REC feature if the guest isn't a
>> ??? realm guest.
>> ? * Support host page size being larger than RMM's granule size when
>> ??? allocating/freeing aux granules.
>> Changes since v5:
>> ? * Separate the concept of vcpu_is_rec() and
>> ??? kvm_arm_vcpu_rec_finalized() by using the KVM_ARM_VCPU_REC feature as
>> ??? the indication that the VCPU is a REC.
>> Changes since v2:
>> ? * Free rec->run earlier in kvm_destroy_realm() and adapt to previous
>> patches.
>> ---
>> ? arch/arm64/include/asm/kvm_emulate.h |?? 7 ++
>> ? arch/arm64/include/asm/kvm_host.h??? |?? 3 +
>> ? arch/arm64/include/asm/kvm_rme.h???? |? 18 +++
>> ? arch/arm64/kvm/arm.c???????????????? |? 13 +-
>> ? arch/arm64/kvm/reset.c?????????????? |? 11 ++
>> ? arch/arm64/kvm/rme.c???????????????? | 179 +++++++++++++++++++++++++++
>> ? 6 files changed, 229 insertions(+), 2 deletions(-)
>>
> 
> With the following one comment addressed:
> 
> Reviewed-by: Gavin Shan <gshan at redhat.com>
> 
> [...]
> 
>> ? ? /*
>> diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/
>> asm/kvm_rme.h
>> index 698bb48a8ae1..5db377943db4 100644
>> --- a/arch/arm64/include/asm/kvm_rme.h
>> +++ b/arch/arm64/include/asm/kvm_rme.h
>> @@ -6,6 +6,7 @@
>> ? #ifndef __ASM_KVM_RME_H
>> ? #define __ASM_KVM_RME_H
>> ? +#include <asm/rmi_smc.h>
>> ? #include <uapi/linux/kvm.h>
>> ? ? /**
>> @@ -65,6 +66,21 @@ struct realm {
>> ????? unsigned int ia_bits;
>> ? };
>> ? +/**
>> + * struct realm_rec - Additional per VCPU data for a Realm
>> + *
>> + * @mpidr: MPIDR (Multiprocessor Affinity Register) value to identify
>> this VCPU
>> + * @rec_page: Kernel VA of the RMM's private page for this REC
>> + * @aux_pages: Additional pages private to the RMM for this REC
>> + * @run: Kernel VA of the RmiRecRun structure shared with the RMM
>> + */
>> +struct realm_rec {
>> +??? unsigned long mpidr;
>> +??? void *rec_page;
>> +??? struct page *aux_pages[REC_PARAMS_AUX_GRANULES];
>> +??? struct rec_run *run;
>> +};
>> +
> 
> REC_PARAMS_AUX_GRANULES represents the maximal number of the auxiliary
> granules.
> Since the base page size is always larger than or equal to granule size
> (4KB).
> The capacity of array @aux_pages[] needs to be REC_PARAMS_AUX_GRANULES.
> Ideally,
> the array's size can be computed dynamically and it's allocated in
> kvm_create_rec().

This is indeed another example of where pages and granules have got
mixed. The RMM specification provides a maximum number of granules (and
there's a similar array in struct rec_params). Here the use of
REC_PARAMS_AUX_GRANULES is just to keep the structure more simple (no
dynamic allocation) with the cost of ~128bytes. Obviously if
PAGE_SIZE>4k then this array could be smaller.

> Alternatively, to keep the code simple, a comment is needed here to
> explain why
> the array's size has been set to REC_PARAMS_AUX_GRANULES.

Definitely a valid point - this could do with a comment explaining the
situation.

> An relevant question: Do we plan to support differentiated sizes between
> page
> and granule? I had the assumption this feature will be supported in the
> future
> after the base model (equal page and granule size) gets merged first.

Yes I do plan to support it. This series actually has the basic support
in it already, with an experimental patch at the end enabling that
support. It "works" but I haven't tested it well and I think some of the
error handling isn't quite right yet.

But there's also a bunch more work to be done (like here) to avoid
over-allocating memory when PAGE_SIZE>4k. E.g. RTTs need an
sub-allocator so that we don't waste an entire (larger) page on each RTT.

Steve



From Frank.Li at nxp.com  Fri Mar  7 07:44:24 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Fri,  7 Mar 2025 10:44:24 -0500
Subject: [PATCH v2 1/1] dt-bindings: watchdog: fsl-imx7ulp-wdt: Add i.MX94 support
Message-ID: <20250307154424.2613795-1-Frank.Li@nxp.com>

Add compatible string "fsl,imx94-wdt" for the i.MX94 chip, which is
backward compatible with i.MX93. Set it to fall back to "fsl,imx93-wdt".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v1 to v2
- fix typo im94 in compatible string
---
 .../devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
index a09686b3030db..6ec391b9723a5 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
@@ -22,6 +22,10 @@ properties:
           - const: fsl,imx8ulp-wdt
           - const: fsl,imx7ulp-wdt
       - const: fsl,imx93-wdt
+      - items:
+          - enum:
+              - fsl,imx94-wdt
+          - const: fsl,imx93-wdt
 
   reg:
     maxItems: 1
-- 
2.34.1



From linux at armlinux.org.uk  Fri Mar  7 07:08:51 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 7 Mar 2025 15:08:51 +0000
Subject: [PATCH net-next v7 2/4] net: stmmac: platform: Group GMAC4
 compatible check
In-Reply-To: <20250307011623.440792-3-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
 <20250307011623.440792-3-inochiama@gmail.com>
Message-ID: <Z8sMAyH0qsMyXmjX@shell.armlinux.org.uk>

On Fri, Mar 07, 2025 at 09:16:15AM +0800, Inochi Amaoto wrote:
> Use of_device_compatible_match to group existing compatible
> check of GMAC4 device.
> 
> Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
> Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>

Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From linux at armlinux.org.uk  Fri Mar  7 07:09:10 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 7 Mar 2025 15:09:10 +0000
Subject: [PATCH net-next v7 3/4] net: stmmac: platform: Add
 snps,dwmac-5.30a IP compatible string
In-Reply-To: <20250307011623.440792-4-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
 <20250307011623.440792-4-inochiama@gmail.com>
Message-ID: <Z8sMFh7yAUTZ9GRN@shell.armlinux.org.uk>

On Fri, Mar 07, 2025 at 09:16:16AM +0800, Inochi Amaoto wrote:
> Add "snps,dwmac-5.30a" compatible string for 5.30a version that can avoid
> to define some platform data in the glue layer.
> 
> Signed-off-by: Inochi Amaoto <inochiama at gmail.com>
> Reviewed-by: Romain Gantois <romain.gantois at bootlin.com>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>

Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Thanks!
-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From daniel.lezcano at linaro.org  Fri Mar  7 07:12:16 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Fri, 7 Mar 2025 16:12:16 +0100
Subject: [PATCH v3 4/8] clocksource: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250305094935.595667-5-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-5-fabrice.gasnier@foss.st.com>
Message-ID: <83283a94-6833-4d7d-8d89-6ba42b43b96c@linaro.org>

On 05/03/2025 10:49, Fabrice Gasnier wrote:
> On stm32mp25, DIER (former IER) must only be modified when the lptimer
> is enabled. On earlier SoCs, it must be only be modified when it is
> disabled. Read the LPTIM_VERR register to properly manage the enable
> state, before accessing IER.
> 
> Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
> Changes in V2:
> - rely on fallback compatible as no specific .data is associated to the
>    driver. Use version data from MFD core.
> - Added interrupt enable register access update in (missed in V1)
> ---
>   drivers/clocksource/timer-stm32-lp.c | 26 ++++++++++++++++++++++----
>   1 file changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
> index a4c95161cb22..96d975adf7a4 100644
> --- a/drivers/clocksource/timer-stm32-lp.c
> +++ b/drivers/clocksource/timer-stm32-lp.c
> @@ -25,6 +25,7 @@ struct stm32_lp_private {
>   	struct clock_event_device clkevt;
>   	unsigned long period;
>   	struct device *dev;
> +	bool ier_wr_enabled;	/* Enables LPTIMER before writing into IER register */
>   };
>   
>   static struct stm32_lp_private*
> @@ -37,8 +38,15 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
>   {
>   	struct stm32_lp_private *priv = to_priv(clkevt);
>   
> -	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> +	/* Disable LPTIMER either before or after writing IER register (else, keep it enabled) */
> +	if (!priv->ier_wr_enabled)
> +		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> +
>   	regmap_write(priv->reg, STM32_LPTIM_IER, 0);
> +

Why not encapsulate the function ?

	regmap_write_ier(struct stm32_lp_private *priv, int value)
	{

		/* A comment ... */
		if (!priv->ier_wr_enabled)
			regmap_write(priv->reg, STM32_LPTIM_CR, 0);

		regmap_write(priv->reg, STM32_LPTIM_IER, value);

		if (!priv->ier_wr_enabled)
			regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
	}


> +	if (priv->ier_wr_enabled)
> +		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> +

>   	/* clear pending flags */
>   	regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
>   
> @@ -51,12 +59,21 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
>   {
>   	struct stm32_lp_private *priv = to_priv(clkevt);
>   
> -	/* disable LPTIMER to be able to write into IER register*/
> -	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> +	if (!priv->ier_wr_enabled) {
> +		/* Disable LPTIMER to be able to write into IER register */
> +		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> +	} else {
> +		/* Enable LPTIMER to be able to write into IER register */
> +		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
> +	}
> +
>   	/* enable ARR interrupt */
>   	regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
> +
>   	/* enable LPTIMER to be able to write into ARR register */
> -	regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
> +	if (!priv->ier_wr_enabled)
> +		regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
> +
>   	/* set next event counter */
>   	regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
>   
> @@ -151,6 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
>   		return -ENOMEM;
>   
>   	priv->reg = ddata->regmap;
> +	priv->ier_wr_enabled = ddata->version == STM32_LPTIM_VERR_23;
>   	ret = clk_prepare_enable(ddata->clk);
>   	if (ret)
>   		return -EINVAL;


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From john.madieu.xa at bp.renesas.com  Fri Mar  7 07:14:05 2025
From: john.madieu.xa at bp.renesas.com (John Madieu)
Date: Fri, 7 Mar 2025 15:14:05 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <20250228-shampoo-uprising-44ae0d3bd68b@spud>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
Message-ID: <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>

Hi Conor,

Thanks for your review!

> -----Original Message-----
> From: Conor Dooley <conor at kernel.org>
> Sent: Friday, February 28, 2025 8:03 PM
> To: John Madieu <john.madieu.xa at bp.renesas.com>
> Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> the TSU unit
> 
> On Thu, Feb 27, 2025 at 01:24:39PM +0100, John Madieu wrote:
> > The Renesas RZ/G3E SoC includes a Thermal Sensor Unit (TSU) block
> > designed to measure the junction temperature. The device provides
> > real-time temperature measurements for thermal management, utilizing a
> > single dedicated channel (channel 1) for temperature sensing.
> >
> > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > ---
> > v1 -> v2:
> >  * Fix reg property specifier to get rid of yamlint warnings
> >  * Fix IRQ name to reflect TSU expectations
> >
> >  .../thermal/renesas,r9a09g047-tsu.yaml        | 123 ++++++++++++++++++
> >  1 file changed, 123 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> > b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
> > new file mode 100644
> > index 000000000000..e786561ddbe3
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.
> > +++ yaml
> > @@ -0,0 +1,123 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> > +---
> > +$id:
> > +http://devicetree.org/schemas/thermal/renesas,r9a09g047-tsu.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Renesas RZ/G3E Temperature Sensor Unit (TSU)
> > +
> > +maintainers:
> > +  - John Madieu <john.madieu.xa at bp.renesas.com>
> > +
> > +description:
> > +  The Temperature Sensor Unit (TSU) is an integrated thermal sensor
> > +that
> > +  monitors the chip temperature on the Renesas RZ/G3E SoC. The TSU
> > +provides
> > +  real-time temperature measurements for thermal management.
> > +
> > +properties:
> > +  compatible:
> > +    const: renesas,r9a09g047-tsu
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    maxItems: 1
> > +
> > +  resets:
> > +    maxItems: 1
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    description: |
> > +      Interrupt specifiers for the TSU:
> > +      - S12TSUADI1: Conversion complete interrupt signal (pulse)
> > +      - S12TSUADCMPI1: Comparison result interrupt signal (level)
> > +
> > +  interrupt-names:
> > +    items:
> > +      - const: adi
> > +      - const: adcmpi
> > +
> > +  "#thermal-sensor-cells":
> > +    const: 0
> > +
> > +  renesas,tsu-calibration-sys:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: |
> > +      Phandle to the system controller (sys) that contains the TSU
> > +      calibration values used for temperature calculations.
> > +
> > +  renesas,tsu-operating-mode:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    enum: [0, 1]
> > +    description: |
> > +      TSU operating mode:
> > +      0: Mode 0 - Conversion started by software
> > +      1: Mode 1 - Conversion started by ELC trigger
> 
> Can you make this "software" and "elc" or something please, unless people
> will genuinely find "0" and 1" to be more informative.
> And why doesn't the property have a default?

Sorry for miss-specifying.
ELC is an external event trigger. May be should I specify it like that ?

To make sure I got your point, do you mean specifying a default value in
bindings ?

> 
> cheers,
> Conor.

Regards,
John

> 
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - resets
> > +  - power-domains
> > +  - interrupts
> > +  - interrupt-names
> > +  - "#thermal-sensor-cells"
> > +  - renesas,tsu-operating-mode
> > +  - renesas,tsu-calibration-sys
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/renesas,r9a09g047-cpg.h>
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +
> > +    tsu: thermal at 14002000 {
> > +        compatible = "renesas,r9a09g047-tsu";
> > +        reg = <0x14002000 0x1000>;
> > +        clocks = <&cpg CPG_MOD 0x10a>;
> > +        resets = <&cpg 0xf8>;
> > +        power-domains = <&cpg>;
> > +        interrupts = <GIC_SPI 250 IRQ_TYPE_EDGE_RISING>,
> > +                     <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>;
> > +        interrupt-names = "adi", "adcmpi";
> > +        #thermal-sensor-cells = <0>;
> > +        renesas,tsu-operating-mode = <0>;
> > +        renesas,tsu-calibration-sys = <&sys>;
> > +    };
> > +
> > +    thermal-zones {
> > +        cpu-thermal {
> > +            polling-delay = <1000>;
> > +            polling-delay-passive = <250>;
> > +            thermal-sensors = <&tsu>;
> > +
> > +            cooling-maps {
> > +                map0 {
> > +                    trip = <&target>;
> > +                    cooling-device = <&cpu0 0 3>, <&cpu1 0 3>,
> > +                                     <&cpu2 0 3>, <&cpu3 0 3>;
> > +                    contribution = <1024>;
> > +                };
> > +            };
> > +
> > +            trips {
> > +                target: trip-point {
> > +                    temperature = <95000>;
> > +                    hysteresis = <1000>;
> > +                    type = "passive";
> > +                };
> > +
> > +                sensor_crit: sensor-crit {
> > +                    temperature = <120000>;
> > +                    hysteresis = <1000>;
> > +                    type = "critical";
> > +                };
> > +            };
> > +        };
> > +    };
> > --
> > 2.25.1
> >


From horms at kernel.org  Fri Mar  7 07:14:09 2025
From: horms at kernel.org (Simon Horman)
Date: Fri, 7 Mar 2025 15:14:09 +0000
Subject: [PATCH net-next 1/7] net: ethtool: netlink: Allow per-netdevice
 DUMP operations
In-Reply-To: <20250307141819.55e42ccd@fedora.home>
References: <20250305141938.319282-1-maxime.chevallier@bootlin.com>
 <20250305141938.319282-2-maxime.chevallier@bootlin.com>
 <20250307122119.GE3666230@kernel.org>
 <20250307141819.55e42ccd@fedora.home>
Message-ID: <20250307151409.GJ3666230@kernel.org>

On Fri, Mar 07, 2025 at 02:18:19PM +0100, Maxime Chevallier wrote:
> Hi Simon,
> 
> On Fri, 7 Mar 2025 12:21:19 +0000
> Simon Horman <horms at kernel.org> wrote:
> 
> > On Wed, Mar 05, 2025 at 03:19:31PM +0100, Maxime Chevallier wrote:
> > > We have a number of netlink commands in the ethnl family that may have
> > > multiple objects to dump even for a single net_device, including :
> > > 
> > >  - PLCA, PSE-PD, phy: one message per PHY device
> > >  - tsinfo: one message per timestamp source (netdev + phys)
> > >  - rss: One per RSS context
> > > 
> > > To get this behaviour, these netlink commands need to roll a custom  
> > > ->dumpit().  
> > > 
> > > To prepare making per-netdev DUMP more generic in ethnl, introduce a
> > > member in the ethnl ops to indicate if a given command may allow
> > > pernetdev DUMPs (also referred to as filtered DUMPs).
> > > 
> > > Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> > > ---
> > >  net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
> > >  net/ethtool/netlink.h |  1 +
> > >  2 files changed, 30 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> > > index 734849a57369..0815b28ba32f 100644
> > > --- a/net/ethtool/netlink.c
> > > +++ b/net/ethtool/netlink.c
> > > @@ -578,21 +578,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
> > >  	int ret = 0;
> > >  
> > >  	rcu_read_lock();
> > > -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> > > -		dev_hold(dev);
> > > +	if (ctx->req_info->dev) {
> > > +		dev = ctx->req_info->dev;
> > >  		rcu_read_unlock();
> > > -
> > > -		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
> > > -
> > > +		/* Filtered DUMP request targeted to a single netdev. We already
> > > +		 * hold a ref to the netdev from ->start()
> > > +		 */
> > > +		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
> > > +						 genl_info_dump(cb));  
> > 
> > Hi Maxime,
> > 
> > ethnl_default_dump_one_dev() is called here but it doesn't exist
> > until the following patch is applied, which breaks bisection.
> 
> Yeah I messed-up in my rebase and bisection broke :(
> 
> I'll send a new version in a few days, as Jakub said, let's give some
> time for the netdev_lock series to move forward and go through CI, I'll
> need to rebase on it at some point.

Thanks. Apologies for duplicating Jakub's comments to some extent.
I only saw them after I'd sent my previous email to you.

...


From krzk at kernel.org  Fri Mar  7 07:15:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:15:34 +0100
Subject: [PATCH 12/14] dt-bindings: mediatek: mt8196: add audio AFE
 document
In-Reply-To: <20250307124841.23777-13-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-13-darren.ye@mediatek.com>
Message-ID: <cfd05cd7-4541-476f-aafd-9e3239d88048@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Add mt8196 audio AFE document.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>

Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

> ---
>  .../bindings/sound/mediatek,mt8196-afe.yaml   | 259 ++++++++++++++++++
>  1 file changed, 259 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
> new file mode 100644
> index 000000000000..59f8fdf3167c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
> @@ -0,0 +1,259 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mediatek,mt8196-afe.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek Audio Front End PCM controller for MT8196
> +
> +maintainers:
> +  - Darren Ye <darren.ye at mediatek.com>
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8196-afe-pcm
> +
> +  reg:
> +    maxItems: 1
> +
> +  "#sound-dai-cells":
> +    const: 0
> +
> +  clocks:
> +    items:
> +      - description: audio hopping clock
> +      - description: audio f26m clock
> +      - description: audio ul0 adc clock
> +      - description: audio ul0 adc hires clock
> +      - description: audio ul1 adc clock
> +      - description: audio ul1 adc hires clock
> +      - description: audio apll1 clock
> +      - description: audio apll2 clock
> +      - description: audio apll tuner1 clock
> +      - description: audio apll tuner2 clock
> +      - description: vlp mux audio int
> +      - description: vlp mux aud engen1
> +      - description: vlp mux aud engen2
> +      - description: vlp mux audio h
> +      - description: vlp clock 26m
> +      - description: ck mainpll d4 d4
> +      - description: ck mux aud 1
> +      - description: ck apll1
> +      - description: ck mux aud 2
> +      - description: ck apll2
> +      - description: ck apll1 d4
> +      - description: ck apll2 d4
> +      - description: ck i2sin0 m sel
> +      - description: ck i2sin1 m sel
> +      - description: ck fmi2s m sel
> +      - description: ck tdmout m sel
> +      - description: ck apll12 div i2sin0
> +      - description: ck apll12 div i2sin1
> +      - description: ck apll12 div fmi2s
> +      - description: ck apll12 div tdmout m
> +      - description: ck apll12 div tdmout b
> +      - description: ck adsp sel
> +      - description: ck clock 26m
> +
> +  clock-names:
> +    items:
> +      - const: aud_hopping_clk

Look how other bindings call it. s/_clk//

> +      - const: aud_f26m_clk
> +      - const: aud_ul0_adc_clk
> +      - const: aud_ul0_adc_hires_clk
> +      - const: aud_ul1_adc_clk
> +      - const: aud_ul1_adc_hires_clk
> +      - const: aud_apll1_clk
> +      - const: aud_apll2_clk
> +      - const: aud_apll_tuner1_clk
> +      - const: aud_apll_tuner2_clk
> +      - const: vlp_mux_audio_int
> +      - const: vlp_mux_aud_eng1
> +      - const: vlp_mux_aud_eng2
> +      - const: vlp_mux_audio_h
> +      - const: vlp_clk26m_clk
> +      - const: ck_mainpll_d4_d4

What does ck stand for? You should name and explain the clocks based on
this block, not the source.


> +      - const: ck_mux_aud_1
> +      - const: ck_apll1_ck
> +      - const: ck_mux_aud_2
> +      - const: ck_apll2_ck
> +      - const: ck_apll1_d4
> +      - const: ck_apll2_d4
> +      - const: ck_i2sin0_m_sel
> +      - const: ck_i2sin1_m_sel
> +      - const: ck_fmi2s_m_sel
> +      - const: ck_tdmout_m_sel
> +      - const: ck_apll12_div_i2sin0
> +      - const: ck_apll12_div_i2sin1
> +      - const: ck_apll12_div_fmi2s
> +      - const: ck_apll12_div_tdmout_m
> +      - const: ck_apll12_div_tdmout_b
> +      - const: ck_adsp_sel
> +      - const: ck_clk26m_clk

s/ck//
s/clk// and this goes probably first. Look at other bindings.

> +
> +  interrupts:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  cksys:

Again, open existing bindings.

> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Phandle to the cksys clock controller.

This tell me not much. Why do you need it?

Drop redundant 'Phandle to' and explain how it is used.

> +
> +  vlpcksys:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Phandle to the vlpcksys clock controller.

No, because you keep encoding clock information via non-clock API.

> +
> +  memory-region:
> +    $ref: /schemas/types.yaml#/definitions/phandle

Drop, see other bindings.


> +    description: Phandle to the reserved memory region for AFE DMA.
> +
> +  pinctrl-names:

Drop

> +    items:
> +      - const: default
> +
> +  pinctrl-0:

Drop

> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Phandle to the pin control group for default state.
> +
> +  mediatek,etdm-out-ch:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Number of ETDM output channels.
> +    enum: [2]

That's pointless.

> +
> +  mediatek,etdm-in-ch:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Number of ETDM input channels.
> +    enum: [2]
> +
> +  mediatek,etdm-out-sync:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: ETDM output synchronization.
> +    enum: [0, 1]
> +
> +  mediatek,etdm-in-sync:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: ETDM input synchronization.
> +    enum: [0, 1]
> +
> +  mediatek,etdm-ip-mode:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: ETDM IP mode.
> +    enum: [0, 1]

Drop all above properties or explain why they make any sense in the
terms of board configuration.


> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - power-domains
> +  - cksys
> +  - vlpcksys
> +  - memory-region

> +  - pinctrl-names
> +  - pinctrl-0

Why?

> +  - mediatek,etdm-out-ch
> +  - mediatek,etdm-in-ch
> +  - mediatek,etdm-out-sync
> +  - mediatek,etdm-in-sync
> +  - mediatek,etdm-ip-mode
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/mt8196-clk.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/power/mt8196-power.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        afe: mt8196-afe-pcm at 1a110000 {

Again... look at other bindings.


Best regards,
Krzysztof


From peter.griffin at linaro.org  Fri Mar  7 07:10:33 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 7 Mar 2025 15:10:33 +0000
Subject: [PATCH 4/6] scsi: ufs: exynos: Enable PRDT pre-fetching with UFSHCD_CAP_CRYPTO
In-Reply-To: <20250305024020.GC20133@sol.localdomain>
References: <20250226220414.343659-1-peter.griffin@linaro.org>
 <20250226220414.343659-5-peter.griffin@linaro.org> <20250305024020.GC20133@sol.localdomain>
Message-ID: <CADrjBPpju3MmZbNy1uaPzAWTWrmNHx0nT+03DmkM3p5qFEUHdA@mail.gmail.com>

Hi Eric,

Thanks for your review feedback.

On Wed, 5 Mar 2025 at 02:40, Eric Biggers <ebiggers at kernel.org> wrote:
>
> On Wed, Feb 26, 2025 at 10:04:12PM +0000, Peter Griffin wrote:
> > PRDT_PREFETCH_ENABLE[31] bit should be set when desctype field of
> > fmpsecurity0 register is type2 (double file encryption) or type3
> > (file and disk excryption). Setting this bit enables PRDT
> > pre-fetching on both TXPRDT and RXPRDT.
> >
> > Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
>
> I assume you mean that desctype 3 provides "support for file and disk
> encryption"?

Yes, the PRDT_PREFETCH_ENABLE description in the commit message I
copied from the datasheet. But I can re-word it like you suggest if
you think that it's clearer? I notice now there is also a typo with
the word 'encryption' which I can also fix.

This patch came about whilst comparing UFS SFR register dumps of
upstream and downstream drivers. I noticed that PRDT_PREFETCH_ENABLE
is enabled downstream but not upstream, and after checking the
datasheet description it seemed like we should set this if
exynos_ufs_fmp_init() completed and set CFG_DESCTYPE_3.

> The driver does use desctype 3, but it only uses the "file
> encryption".  So this confused me a bit.  (BTW, in FMP terminology, "file
> encryption" seems to mean "use the key provided in the I/O request", and "disk
> encryption" seems to mean "use some key the firmware provided somehow".  They
> can be cascaded, and the intended use cases are clearly file and disk encryption
> respectively, but they don't necessarily have to be used that way.)

Thanks for the additional context :)

Peter


From krzk at kernel.org  Fri Mar  7 07:19:42 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:19:42 +0100
Subject: [PATCH 14/14] dt-bindings: mediatek: mt8196: add mt8196-mt6681
 document
In-Reply-To: <20250307124841.23777-15-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-15-darren.ye@mediatek.com>
Message-ID: <d795e657-1723-499c-8a0f-d5b2f24c4f92@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Add document for mt8196 board with mt6681.


Why do you add bindings after its users? Fix the order (see DT
submitting patches).


Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  .../sound/mediatek,mt8196-mt6681.yaml         | 122 ++++++++++++++++++
>  1 file changed, 122 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
> new file mode 100644
> index 000000000000..b144ba748c23
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-mt6681.yaml
> @@ -0,0 +1,122 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mediatek,mt8196-mt6681.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT8196 ASoC sound card
> +
> +maintainers:
> +  - Darren Ye <darren.ye at mediatek.com>
> +
> +allOf:
> +  - $ref: sound-card-common.yaml#
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - mediatek,mt8196-mt6681-sound
> +          - mediatek,mt8196-nau8825-sound
> +          - mediatek,mt8196-rt5682s-sound
> +          - mediatek,mt8196-rt5650-sound

So this is not compatible with nau8825?

> +      - items:
> +          - const: mediatek,mt8196-mt6681-sound

This makes no sense. Either it is or it is not compatible with nau8825.

> +          - const: mediatek,mt8196-nau8825-sound
> +
> +  audio-routing:
> +    description:
> +      Valid names could be the input or output widgets of audio components,
> +      power supplies, MicBias of codec and the software switch.

Drop property, not needed.

> +
Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar  7 07:20:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 7 Mar 2025 16:20:48 +0100
Subject: [PATCH 01/14] ASoC: mediatek: common: modify mtk afe common
 driver for mt8196
In-Reply-To: <20250307124841.23777-2-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-2-darren.ye@mediatek.com>
Message-ID: <8a855e37-b7cf-41ef-8d97-f2ff506a5750@kernel.org>

On 07/03/2025 13:47, Darren.Ye wrote:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Export register read and write interface, add sample reate interface, and
> update the mtk_memif_set_channel interface for the mt8196 platform.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>  sound/soc/mediatek/common/mtk-afe-fe-dai.c | 30 ++++++++++++++--------
>  sound/soc/mediatek/common/mtk-afe-fe-dai.h |  6 +++++
>  sound/soc/mediatek/common/mtk-base-afe.h   | 13 ++++++++++
>  3 files changed, 38 insertions(+), 11 deletions(-)
> 
> diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> index 3809068f5620..c36dae520f04 100644
> --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> @@ -18,7 +18,7 @@
>  
>  #define AFE_BASE_END_OFFSET 8
>  
> -static int mtk_regmap_update_bits(struct regmap *map, int reg,
> +int mtk_regmap_update_bits(struct regmap *map, int reg,

You need kerneldoc for all exported functions.

>  			   unsigned int mask,
>  			   unsigned int val, int shift)
>  {
> @@ -26,13 +26,16 @@ static int mtk_regmap_update_bits(struct regmap *map, int reg,
>  		return 0;
>  	return regmap_update_bits(map, reg, mask << shift, val << shift);
>  }
> +EXPORT_SYMBOL(mtk_regmap_update_bits);

GPL


> +
> +int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
>  

Why blank line?

> -static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)

Missing kerneldoc

>  {
>  	if (reg < 0)
>  		return 0;
>  	return regmap_write(map, reg, val);
>  }
> +EXPORT_SYMBOL(mtk_regmap_write);

GPL


Best regards,
Krzysztof


From Frank.li at nxp.com  Fri Mar  7 07:21:14 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 7 Mar 2025 10:21:14 -0500
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250307122217.158b24d6@booty>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
 <71c44221-b18b-4928-8faf-00893ec4a109@nxp.com>
 <20250307122217.158b24d6@booty>
Message-ID: <Z8sO6vQLPTd2KClD@lizhi-Precision-Tower-5810>

On Fri, Mar 07, 2025 at 12:22:17PM +0100, Luca Ceresoli wrote:
> Hello Liu,
>
> On Fri, 7 Mar 2025 14:42:12 +0800
> Liu Ying <victor.liu at nxp.com> wrote:
>
> > On 03/07/2025, Luca Ceresoli wrote:
> > > 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
> > > ret;'. So return 0 for clarity.
> > >
> > > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > > ---
> > >  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > > index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
> > > --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > > +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
> > > @@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
> > >
> > >  	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
> > >
> > > -	return ret;
> > > +	return 0;
> >
> > I guess this is not the only place across the kernel tree where this cleanup
> > could be done.  So, maybe use some tools to cleanup them all?
>
> I had stumbled upon this as I was doing some changes to this function,
> and needed to understand the code flow. Definitely 'ret 0' would have
> made it  immediately clear that all the code between the last 'if (ret)
> return ret;' and the final 'return ret' is not allowed to fail.
>
> I think this change would (slightly, but still) improve future readers'
> life.

I think "return ret" at probe already become common sense for developer.
No value to take efforts to clean up this.

Frank

>
> Luca
>
> --
> Luca Ceresoli, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com


From geert+renesas at glider.be  Fri Mar  7 07:47:25 2025
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri,  7 Mar 2025 16:47:25 +0100
Subject: [GIT PULL] Renesas DTS updates for v6.15 (take two)
Message-ID: <cover.1741362039.git.geert+renesas@glider.be>

	Hi SoC folks,

This is my second pull request for the inclusion of Renesas SoC updates
for v6.15.

The following changes since commit 5f7ebb81112c3f50ffbb8e576e4d35cedd8aabb1:

  ARM: dts: renesas: r9a06g032: Fix UART dma channel order (2025-02-21 16:23:01 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-dts-for-v6.15-tag2

for you to fetch changes up to 8bf8ad268e46403c7140ea5aaa85e9c659117dbc:

  arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Enable Mali-G31 (2025-03-06 16:36:08 +0100)

----------------------------------------------------------------
Renesas DTS updates for v6.15 (take two)

  - Add GPU support for the RZ/V2H(P) SoC and the RZ/V2H EVK board.

Thanks for pulling!

----------------------------------------------------------------
Lad Prabhakar (2):
      arm64: dts: renesas: r9a09g057: Add Mali-G31 GPU node
      arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Enable Mali-G31

 arch/arm64/boot/dts/renesas/r9a09g057.dtsi         | 51 ++++++++++++++++++++++
 .../boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts    | 15 +++++++
 2 files changed, 66 insertions(+)

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


From conor at kernel.org  Fri Mar  7 07:48:44 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:48:44 +0000
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
 <20250306085028.5024-2-axe.yang@mediatek.com>
 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
Message-ID: <20250307-bust-diving-a57644a51543@spud>

On Fri, Mar 07, 2025 at 06:59:03AM +0000, Axe Yang (??) wrote:
> On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
> > > Add 'mediatek,disable-single-burst' setting. This property can be
> > > used to switch bus burst type, from single burst to INCR, which is
> > > determined by the bus type within the IP. Some versions of the IP
> > > are using AXI bus, thus this switch is necessary as 'single' is not
> > > the burst type supported by the bus.
> > > 
> > > Signed-off-by: Axe Yang <axe.yang at mediatek.com>
> > 
> > I am mostly sure that this is not something to put in devicetree, but
> > as
> > platform data for specific SoC(s), as much as I'm mostly sure that
> > all of
> > the instances of the MSDC IP in one SoC will be *all* using either
> > single
> > or INCR.
> 
> No, actually MSDC IPs in one SoC are using different versions.
> Usually MSDC1 (index from 1) is used as eMMC host, the left hosts are
> used as SD/SDIO hosts. They have similar designs, but there are still
> difference.
> 
> > 
> > So, I think I know the answer but I'll still ask just to be extremely
> > sure:
> > 
> > is there any MediaTek SoC that has different IP versions for
> > different MSDC
> > instances, and that hence require single burst on one instance and
> > INCR on
> > another instance?
> 
> Yes. Actually every SoC has different IP versions for eMMC and SD/SDIO
> host as I said.
> e.g. For MT8168, signel burst bit should be set to 1 for eMMC Host, but
> 0 for SD/SDIO Host.
> 

Sounds like two different IPs that really should have different
compatibles to me...

> > 
> > And if there is - is there a pattern? Is it always SDIO requiring
> > INCR or
> > always eMMC/SD requiring it?
> > 
> > 
> 
> No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
> configured base on IP version. There is no binding relationship between
> eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
> single, same as SD/SDIO.
> 
> 
> Regards,
> Axe
> 
> 
> > 
> > > ---
> > >   Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8 ++++++++
> > >   1 file changed, 8 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > index 0debccbd6519..6076aff0a689 100644
> > > --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > @@ -100,6 +100,14 @@ properties:
> > >       minimum: 0
> > >       maximum: 0xffffffff
> > > 
> > > +  mediatek,disable-single-burst:
> > > +    $ref: /schemas/types.yaml#/definitions/flag
> > > +    description:
> > > +      Burst type setting. For some versions of the IP that do not
> > > use
> > > +      AHB bus, the burst type need to be switched to INCR.
> > > +      If present, use INCR burst type.
> > > +      If not present, use single burst type.
> > > +
> > >     mediatek,hs200-cmd-int-delay:
> > >       $ref: /schemas/types.yaml#/definitions/uint32
> > >       description:
> > 
> > 
> > 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/4a7f78f1/attachment.sig>

From conor at kernel.org  Fri Mar  7 07:55:19 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:55:19 +0000
Subject: [PATCH v2 1/1] dt-bindings: watchdog: fsl-imx7ulp-wdt: Add
 i.MX94 support
In-Reply-To: <20250307154424.2613795-1-Frank.Li@nxp.com>
References: <20250307154424.2613795-1-Frank.Li@nxp.com>
Message-ID: <20250307-violator-marmalade-87886dc56c83@spud>

On Fri, Mar 07, 2025 at 10:44:24AM -0500, Frank Li wrote:
> Add compatible string "fsl,imx94-wdt" for the i.MX94 chip, which is
> backward compatible with i.MX93. Set it to fall back to "fsl,imx93-wdt".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Acked-by: Conor Dooley <conor.dooley at microchip.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/fb3e828c/attachment.sig>

From john.madieu.xa at bp.renesas.com  Fri Mar  7 07:55:27 2025
From: john.madieu.xa at bp.renesas.com (John Madieu)
Date: Fri, 7 Mar 2025 15:55:27 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <20250307-everyone-ragweed-e05a10a9646b@spud>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
Message-ID: <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>

Hi Conor,

> -----Original Message-----
> From: Conor Dooley <conor at kernel.org>
> Sent: Friday, March 7, 2025 4:33 PM
> To: John Madieu <john.madieu.xa at bp.renesas.com>
> Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> the TSU unit
> 
> On Fri, Mar 07, 2025 at 03:14:05PM +0000, John Madieu wrote:
> > Hi Conor,
> >
> > Thanks for your review!
> >
> > > -----Original Message-----
> > > From: Conor Dooley <conor at kernel.org>
> > > Sent: Friday, February 28, 2025 8:03 PM
> > > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu:
> > > Document the TSU unit
> > >
> > > On Thu, Feb 27, 2025 at 01:24:39PM +0100, John Madieu wrote:
> > > > The Renesas RZ/G3E SoC includes a Thermal Sensor Unit (TSU) block
> > > > designed to measure the junction temperature. The device provides
> > > > real-time temperature measurements for thermal management,
> > > > utilizing a single dedicated channel (channel 1) for temperature
> sensing.
> > > >
> > > > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > > > ---
> > > > v1 -> v2:
> > > >  * Fix reg property specifier to get rid of yamlint warnings
> > > >  * Fix IRQ name to reflect TSU expectations
> > > >
> > > > +    enum: [0, 1]
> > > > +    description: |
> > > > +      TSU operating mode:
> > > > +      0: Mode 0 - Conversion started by software
> > > > +      1: Mode 1 - Conversion started by ELC trigger
> > >
> > > Can you make this "software" and "elc" or something please, unless
> > > people will genuinely find "0" and 1" to be more informative.
> > > And why doesn't the property have a default?
> >
> > Sorry for miss-specifying.
> > ELC is an external event trigger. May be should I specify it like that ?
> 
> If "elc trigger" is meaningful to people using hte device (IOW, it matches
> datasheet wording) then that's fine I think.

"elc trigger" matches datasheet wording.

> 
> > To make sure I got your point, do you mean specifying a default value
> > in bindings ?
> 
> The property doesn't actually need to be required, it could easily have a
> default (say software) and only be set in the case of using the elc
> trigger - which brings you to Rob's comment that it can just be a boolean,
> setting the property if elc and leaving it out of software.

Got the point now. I can make it default to software trigger, and add optional
Boolean property to ELC trigger. Let's say "renesas,elc-trigger;"

> 
> Rob's other comment was
> 
> | Who/what decides the mode? If a user is going to want to change this,
> | then it should be a runtime control, not a DT property.

Changes are not possible at runtime. Some customers may want software,
while other may want the external trigger, and this is immutable 
configuration.

> 
> which I think needs an answer ;)

Regards,
John


From conor at kernel.org  Fri Mar  7 07:57:07 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:57:07 +0000
Subject: [PATCH] dt-bindings: mmc: fsl-imx-esdhc: Add i.MX94 support
In-Reply-To: <20250306170937.242183-1-Frank.Li@nxp.com>
References: <20250306170937.242183-1-Frank.Li@nxp.com>
Message-ID: <20250307-darling-alto-4ad82d5dd20c@spud>

On Thu, Mar 06, 2025 at 12:09:37PM -0500, Frank Li wrote:
> Add compatible string "fsl,imx94-usdhc" for the i.MX94 chip, which is
> backward compatible with i.MX8mm. Set it to fall back to
> "fsl,imx8mm-usdhc".

Acked-by: Conor Dooley <conor.dooley at microchip.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/569b6c51/attachment.sig>

From conor at kernel.org  Fri Mar  7 07:58:12 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:58:12 +0000
Subject: [PATCH] dt-bindings: pwm: imx: Add i.MX93, i.MX94 and i.MX95
 support
In-Reply-To: <20250306170845.240555-1-Frank.Li@nxp.com>
References: <20250306170845.240555-1-Frank.Li@nxp.com>
Message-ID: <20250307-scion-comprised-03e8ea95abed@spud>

On Thu, Mar 06, 2025 at 12:08:45PM -0500, Frank Li wrote:
> Add compatible string "fsl,imx93-pwm", "fsl,imx94-pwm" and "fsl,imx95-pwm",
> which is backward compatible with i.MX7ULP. Set it to fall back to
> "fsl,imx7ulp-pwm".

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  .../devicetree/bindings/pwm/imx-tpm-pwm.yaml          | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
> index ac0a35bf8648c..d5a9340ff9209 100644
> --- a/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
> +++ b/Documentation/devicetree/bindings/pwm/imx-tpm-pwm.yaml
> @@ -23,8 +23,15 @@ properties:
>      const: 3
>  
>    compatible:
> -    enum:
> -      - fsl,imx7ulp-pwm
> +    oneOf:
> +      - enum:
> +          - fsl,imx7ulp-pwm
> +      - items:
> +          - enum:
> +              - fsl,imx93-pwm
> +              - fsl,imx94-pwm
> +              - fsl,imx95-pwm
> +          - const: fsl,imx7ulp-pwm
>  
>    reg:
>      maxItems: 1
> -- 
> 2.34.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/98cc3e37/attachment.sig>

From conor at kernel.org  Fri Mar  7 07:58:34 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 15:58:34 +0000
Subject: [PATCH] dt-bindings: iio: adc: Add i.MX94 and i.MX95 support
In-Reply-To: <20250306170825.239933-1-Frank.Li@nxp.com>
References: <20250306170825.239933-1-Frank.Li@nxp.com>
Message-ID: <20250307-county-dissuade-eed621016369@spud>

On Thu, Mar 06, 2025 at 12:08:25PM -0500, Frank Li wrote:
> Add compatible string "nxp,imx94-adc" and "nxp,imx95-adc", which is
> backward compatible with i.MX93. Set it to fall back to "nxp,imx93-adc".
> 

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  .../devicetree/bindings/iio/adc/nxp,imx93-adc.yaml       | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml b/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
> index dfc3f512918f6..c2e5ff418920c 100644
> --- a/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml
> @@ -19,7 +19,14 @@ description:
>  
>  properties:
>    compatible:
> -    const: nxp,imx93-adc
> +    oneOf:
> +      - enum:
> +          - nxp,imx93-adc
> +      - items:
> +          - enum:
> +              - nxp,imx94-adc
> +              - nxp,imx95-adc
> +          - const: nxp,imx93-adc
>  
>    reg:
>      maxItems: 1
> -- 
> 2.34.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/61f9fb0e/attachment.sig>

From jonas at kwiboo.se  Fri Mar  7 08:01:54 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 17:01:54 +0100
Subject: [PATCH 1/4] dt-bindings: net: rockchip-dwmac: Add compatible
 string for RK3528
In-Reply-To: <20250307-tipping-womanlike-a1ce2370d8d3@spud>
References: <20250306221402.1704196-1-jonas@kwiboo.se>
 <20250306221402.1704196-2-jonas@kwiboo.se>
 <20250307-tipping-womanlike-a1ce2370d8d3@spud>
Message-ID: <de2fb6c6-b053-4be9-8c44-2476c5eb26a6@kwiboo.se>

Hi Conor,

On 2025-03-07 16:42, Conor Dooley wrote:
> On Thu, Mar 06, 2025 at 10:13:54PM +0000, Jonas Karlman wrote:
>> Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
>> Ethernet QoS IP.
>>
>> Add compatible string for the RK3528 variant.
>>
>> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
>> ---
>> I was not able to restrict the minItems change to only apply to the new
>> compatible, please advise on how to properly restrict the minItems
>> change if needed.
> 
> What do you mean by that? As in, what did you try and did not work?
> Usually you do something like
> if:
>   not:
>     compatible:
>       contains:
>         rockchip,rk3528-gmac
> then:
>   properties:
>     clocks:
>       minItems: 5
> 

Thanks, this seem to work, will use in a v2.

I tried to do something opposite and instead set minItems: 4 when
compatible contains rockchip,rk3528-gmac:

if:
  compatible:
    contains:
      rockchip,rk3528-gmac
then:
  properties:
    clocks:
      minItems: 4

but that resulted in something like:

  rockchip/rk3528-radxa-e20c.dtb: ethernet at ffbe0000: clocks: [[7, 173], [7, 172], [7, 171], [7, 170]] is too short

Regards,
Jonas

>>
>> Also, because snps,dwmac-4.20a is already listed in snps,dwmac.yaml
>> adding the rockchip,rk3528-gmac compatible did not seem necessary.
>> ---
>>  Documentation/devicetree/bindings/net/rockchip-dwmac.yaml | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
>> index 05a5605f1b51..3c25b49bd78e 100644
>> --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
>> +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
>> @@ -24,6 +24,7 @@ select:
>>            - rockchip,rk3366-gmac
>>            - rockchip,rk3368-gmac
>>            - rockchip,rk3399-gmac
>> +          - rockchip,rk3528-gmac
>>            - rockchip,rk3568-gmac
>>            - rockchip,rk3576-gmac
>>            - rockchip,rk3588-gmac
>> @@ -49,6 +50,7 @@ properties:
>>                - rockchip,rv1108-gmac
>>        - items:
>>            - enum:
>> +              - rockchip,rk3528-gmac
>>                - rockchip,rk3568-gmac
>>                - rockchip,rk3576-gmac
>>                - rockchip,rk3588-gmac
>> @@ -56,7 +58,7 @@ properties:
>>            - const: snps,dwmac-4.20a
>>  
>>    clocks:
>> -    minItems: 5
>> +    minItems: 4
>>      maxItems: 8
>>  
>>    clock-names:
>> -- 
>> 2.48.1
>>



From linux at roeck-us.net  Fri Mar  7 08:02:27 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 7 Mar 2025 08:02:27 -0800
Subject: [PATCH v2 1/1] dt-bindings: watchdog: fsl-imx7ulp-wdt: Add i.MX94
 support
In-Reply-To: <20250307154424.2613795-1-Frank.Li@nxp.com>
References: <20250307154424.2613795-1-Frank.Li@nxp.com>
Message-ID: <64d7d06b-337e-498a-87dd-03ae41e6a2de@roeck-us.net>

On 3/7/25 07:44, Frank Li wrote:
> Add compatible string "fsl,imx94-wdt" for the i.MX94 chip, which is
> backward compatible with i.MX93. Set it to fall back to "fsl,imx93-wdt".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Reviewed-by: Guenter Roeck <linux at roeck-us.net>

> ---
> change from v1 to v2
> - fix typo im94 in compatible string
> ---
>   .../devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml         | 4 ++++
>   1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
> index a09686b3030db..6ec391b9723a5 100644
> --- a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
> +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
> @@ -22,6 +22,10 @@ properties:
>             - const: fsl,imx8ulp-wdt
>             - const: fsl,imx7ulp-wdt
>         - const: fsl,imx93-wdt
> +      - items:
> +          - enum:
> +              - fsl,imx94-wdt
> +          - const: fsl,imx93-wdt
>   
>     reg:
>       maxItems: 1



From conor at kernel.org  Fri Mar  7 08:03:46 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 7 Mar 2025 16:03:46 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
 <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
Message-ID: <20250307-barbell-pretzel-368d6a4d1336@spud>

On Fri, Mar 07, 2025 at 03:55:27PM +0000, John Madieu wrote:
> Hi Conor,
> 
> > -----Original Message-----
> > From: Conor Dooley <conor at kernel.org>
> > Sent: Friday, March 7, 2025 4:33 PM
> > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> > the TSU unit
> > 
> > On Fri, Mar 07, 2025 at 03:14:05PM +0000, John Madieu wrote:
> > > Hi Conor,
> > >
> > > Thanks for your review!
> > >
> > > > -----Original Message-----
> > > > From: Conor Dooley <conor at kernel.org>
> > > > Sent: Friday, February 28, 2025 8:03 PM
> > > > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > > > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu:
> > > > Document the TSU unit
> > > >
> > > > On Thu, Feb 27, 2025 at 01:24:39PM +0100, John Madieu wrote:
> > > > > The Renesas RZ/G3E SoC includes a Thermal Sensor Unit (TSU) block
> > > > > designed to measure the junction temperature. The device provides
> > > > > real-time temperature measurements for thermal management,
> > > > > utilizing a single dedicated channel (channel 1) for temperature
> > sensing.
> > > > >
> > > > > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > > > > ---
> > > > > v1 -> v2:
> > > > >  * Fix reg property specifier to get rid of yamlint warnings
> > > > >  * Fix IRQ name to reflect TSU expectations
> > > > >
> > > > > +    enum: [0, 1]
> > > > > +    description: |
> > > > > +      TSU operating mode:
> > > > > +      0: Mode 0 - Conversion started by software
> > > > > +      1: Mode 1 - Conversion started by ELC trigger
> > > >
> > > > Can you make this "software" and "elc" or something please, unless
> > > > people will genuinely find "0" and 1" to be more informative.
> > > > And why doesn't the property have a default?
> > >
> > > Sorry for miss-specifying.
> > > ELC is an external event trigger. May be should I specify it like that ?
> > 
> > If "elc trigger" is meaningful to people using hte device (IOW, it matches
> > datasheet wording) then that's fine I think.
> 
> "elc trigger" matches datasheet wording.
> 
> > 
> > > To make sure I got your point, do you mean specifying a default value
> > > in bindings ?
> > 
> > The property doesn't actually need to be required, it could easily have a
> > default (say software) and only be set in the case of using the elc
> > trigger - which brings you to Rob's comment that it can just be a boolean,
> > setting the property if elc and leaving it out of software.
> 
> Got the point now. I can make it default to software trigger, and add optional
> Boolean property to ELC trigger. Let's say "renesas,elc-trigger;"

Yah, that works.

> 
> > 
> > Rob's other comment was
> > 
> > | Who/what decides the mode? If a user is going to want to change this,
> > | then it should be a runtime control, not a DT property.
> 
> Changes are not possible at runtime. Some customers may want software,
> while other may want the external trigger, and this is immutable 
> configuration.

What makes it immutable? Set by some wiring on the board? I couldn't
find the user in your driver patches to better understand how you were
using it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/8990a6fd/attachment.sig>

From mark.rutland at arm.com  Fri Mar  7 08:09:23 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 7 Mar 2025 16:09:23 +0000
Subject: [PATCH] arm64/mm: Define PTE_SHIFT
In-Reply-To: <c3dddb6f-dce1-45a6-b5f1-1fd247c510ab@arm.com>
References: <20250307050851.4034393-1-anshuman.khandual@arm.com>
 <17931f83-7142-4ca6-8bfe-466ec53b6e2c@arm.com>
 <c3dddb6f-dce1-45a6-b5f1-1fd247c510ab@arm.com>
Message-ID: <Z8saM94ixmDNjZzV@J2N7QTR9R3.cambridge.arm.com>

On Fri, Mar 07, 2025 at 02:50:56PM +0530, Anshuman Khandual wrote:
> On 3/7/25 14:37, Ryan Roberts wrote:
> > On 07/03/2025 05:08, Anshuman Khandual wrote:

> >>  #define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
> >> -	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
> >> +	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + \
> >> +	lvl * (PAGE_SHIFT - PTE_SHIFT), add) : 0)
> > 
> > nit: not sure what style guide says, but I would indent this continuation an
> > extra level.
> 
> IIUC - An indentation is not normally required with a line continuation although
> the starting letter should match the starting letter in the line above but after
> the '(' (if any).

Regardless of indenttation, the existing code is fairly hard to read,
and I reckon it'd be better to split up, e.g.

| /* Number of VA bits resolved by a single translation table level */
| #define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)
| 
| #define __EARLY_LEVEL(lvl, vstart, vend, add) \
| 	EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT, add)
| 
| #define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
| 	((lvls) > (lvl) ? __EARLY_LEVEL(lvl, vstart, vend, add) : 0)

... and ignoring the use of _SHIFT vs _ORDER, I think that structure is
far more legible.

With that, we can fold EARLY_ENTRIES() and __EARLY_LEVEL() together and
move the 'add' into EARLY_LEVEL(), e.g.

| /* Number of VA bits resolved by a single translation table level */
| #define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)
| 
| #define EARLY_ENTRIES(lvl, vstart, vend) \
| 	(SPAN_NR_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT))
| 
| #define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
| 	((lvls) > (lvl) ? EARLY_ENTRIES(lvl, vstart, vend) + (add) : 0)

... which I think makes the 'add' a bit easier to understand too.

Mark.


From jonathanh at nvidia.com  Fri Mar  7 08:11:19 2025
From: jonathanh at nvidia.com (Jon Hunter)
Date: Fri, 7 Mar 2025 16:11:19 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
Message-ID: <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>

Hi Russell,

On 06/03/2025 15:23, Russell King (Oracle) wrote:
> Hi,
> 
> This is a second approach to solving the STMMAC reset issues caused by
> the lack of receive clock from the PHY where the media is in low power
> mode with a PHY that supports receive clock-stop.
> 
> The first approach centred around only addressing the issue in the
> resume path, but it seems to also happen when the platform glue module
> is removed and re-inserted (Jon - can you check whether that's also
> the case for you please?)
> 
> As this is more targetted, I've dropped the patches from this series
> which move the call to phylink_resume(), so the link may still come
> up too early on resume - but that's something I also intend to fix.
> 
> This is experimental - so I value test reports for this change.


The subject indicates 3 patches, but I only see 2 patches? Can you 
confirm if there are 2 or 3?

So far I have only tested to resume case with the 2 patches to make that 
that is working but on Tegra186, which has been the most problematic, it 
is not working reliably on top of next-20250305.

Cheers,
Jon

-- 
nvpublic



From cki-project at redhat.com  Fri Mar  7 08:12:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 16:12:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <77413.125030711120800859@us-mta-168.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1705137995

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1705137995-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From lkp at intel.com  Fri Mar  7 08:11:48 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 00:11:48 +0800
Subject: [soc:arm/fixes] BUILD SUCCESS
 98f3ab18a0a55aa1ff2cd6b74bd0c02c8f76f17e
Message-ID: <202503080042.qBbdAnTj-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git arm/fixes
branch HEAD: 98f3ab18a0a55aa1ff2cd6b74bd0c02c8f76f17e  ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP

elapsed time: 1454m

configs tested: 64
configs skipped: 1

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
arc                  randconfig-001-20250307    gcc-13.2.0
arc                  randconfig-002-20250307    gcc-13.2.0
arm                  randconfig-001-20250307    clang-21
arm                  randconfig-002-20250307    gcc-14.2.0
arm                  randconfig-003-20250307    clang-19
arm                  randconfig-004-20250307    clang-21
arm64                randconfig-001-20250307    gcc-14.2.0
arm64                randconfig-002-20250307    clang-15
arm64                randconfig-003-20250307    gcc-14.2.0
arm64                randconfig-004-20250307    clang-15
csky                 randconfig-001-20250307    gcc-14.2.0
csky                 randconfig-002-20250307    gcc-14.2.0
hexagon              randconfig-001-20250307    clang-21
hexagon              randconfig-002-20250307    clang-21
i386       buildonly-randconfig-001-20250307    clang-19
i386       buildonly-randconfig-002-20250307    clang-19
i386       buildonly-randconfig-003-20250307    gcc-11
i386       buildonly-randconfig-004-20250307    clang-19
i386       buildonly-randconfig-005-20250307    gcc-12
i386       buildonly-randconfig-006-20250307    clang-19
loongarch            randconfig-001-20250307    gcc-14.2.0
loongarch            randconfig-002-20250307    gcc-14.2.0
m68k                             allnoconfig    gcc-14.2.0
nios2                randconfig-001-20250307    gcc-14.2.0
nios2                randconfig-002-20250307    gcc-14.2.0
openrisc                         allnoconfig    gcc-14.2.0
parisc                           allnoconfig    gcc-14.2.0
parisc               randconfig-001-20250307    gcc-14.2.0
parisc               randconfig-002-20250307    gcc-14.2.0
powerpc                          allnoconfig    gcc-14.2.0
powerpc              randconfig-001-20250307    gcc-14.2.0
powerpc              randconfig-002-20250307    clang-21
powerpc              randconfig-003-20250307    clang-19
powerpc64            randconfig-001-20250307    clang-21
powerpc64            randconfig-002-20250307    gcc-14.2.0
powerpc64            randconfig-003-20250307    gcc-14.2.0
riscv                            allnoconfig    gcc-14.2.0
riscv                randconfig-001-20250307    gcc-14.2.0
riscv                randconfig-002-20250307    clang-19
s390                            allmodconfig    clang-19
s390                             allnoconfig    clang-15
s390                            allyesconfig    gcc-14.2.0
s390                 randconfig-001-20250307    gcc-14.2.0
s390                 randconfig-002-20250307    gcc-14.2.0
sh                              allmodconfig    gcc-14.2.0
sh                              allyesconfig    gcc-14.2.0
sh                   randconfig-001-20250307    gcc-14.2.0
sh                   randconfig-002-20250307    gcc-14.2.0
sparc                           allmodconfig    gcc-14.2.0
sparc                randconfig-001-20250307    gcc-14.2.0
sparc                randconfig-002-20250307    gcc-14.2.0
sparc64              randconfig-001-20250307    gcc-14.2.0
sparc64              randconfig-002-20250307    gcc-14.2.0
um                               allnoconfig    clang-18
um                   randconfig-001-20250307    clang-17
um                   randconfig-002-20250307    clang-21
x86_64     buildonly-randconfig-001-20250307    clang-19
x86_64     buildonly-randconfig-002-20250307    gcc-12
x86_64     buildonly-randconfig-003-20250307    clang-19
x86_64     buildonly-randconfig-004-20250307    clang-19
x86_64     buildonly-randconfig-005-20250307    clang-19
x86_64     buildonly-randconfig-006-20250307    gcc-12
xtensa               randconfig-001-20250307    gcc-14.2.0
xtensa               randconfig-002-20250307    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From maz at kernel.org  Fri Mar  7 08:18:24 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri,  7 Mar 2025 16:18:24 +0000
Subject: [GIT PULL] KVM/arm64 fixes for 6.14, take #4
Message-ID: <20250307161824.2373079-1-maz@kernel.org>

Paolo,

Here's what I hope to be the last set of 6.14 fixes for
KVM/arm64. This time, two patches addressing the two side of the same
bug, where pKVM's PSCI relay wasn't correctly setting up the CPUs when
in the hVHE mode. Thanks to Ahmed and Mark for fixing it.

Please pull,

	M.

The following changes since commit fa808ed4e199ed17d878eb75b110bda30dd52434:

  KVM: arm64: Ensure a VMID is allocated before programming VTTBR_EL2 (2025-02-20 16:29:28 +0000)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvmarm-fixes-6.14-4

for you to fetch changes up to 3855a7b91d42ebf3513b7ccffc44807274978b3d:

  KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu() (2025-03-02 08:36:52 +0000)

----------------------------------------------------------------
KVM/arm64 fixes for 6.14, take #4

- Fix a couple of bugs affecting pKVM's PSCI relay implementation
  when running in the hVHE mode, resulting in the host being entered
  with the MMU in an unknown state, and EL2 being in the wrong mode.

----------------------------------------------------------------
Ahmed Genidi (1):
      KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu()

Mark Rutland (1):
      KVM: arm64: Initialize HCR_EL2.E2H early

 arch/arm64/include/asm/el2_setup.h   | 31 ++++++++++++++++++++++++++-----
 arch/arm64/kernel/head.S             | 22 +++-------------------
 arch/arm64/kvm/hyp/nvhe/hyp-init.S   | 10 +++++++---
 arch/arm64/kvm/hyp/nvhe/psci-relay.c |  3 +++
 4 files changed, 39 insertions(+), 27 deletions(-)


From thierry.reding at gmail.com  Fri Mar  7 08:23:29 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 17:23:29 +0100
Subject: [GIT PULL 3/5] dt-bindings: Changes for v6.15-rc1
In-Reply-To: <20250307162332.3451523-1-thierry.reding@gmail.com>
References: <20250307162332.3451523-1-thierry.reding@gmail.com>
Message-ID: <20250307162332.3451523-3-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-dt-bindings

for you to fetch changes up to 294630d81ad65333e5d4ad3efcb82dcad6177e6b:

  dt-bindings: Document Tegra114 HDA support (2025-03-07 17:08:33 +0100)

Thanks,
Thierry

----------------------------------------------------------------
dt-bindings: Changes for v6.15-rc1

This adds compatible strings for Tegra114 HDA and Tegra124 MIPI.

----------------------------------------------------------------
Thierry Reding (2):
      dt-bindings: display: tegra: Document Tegra124 MIPI
      dt-bindings: Document Tegra114 HDA support

 .../devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml          | 1 +
 Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml          | 1 +
 2 files changed, 2 insertions(+)


From thierry.reding at gmail.com  Fri Mar  7 08:23:27 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 17:23:27 +0100
Subject: [GIT PULL 1/5] soc/tegra: Changes for v6.15-rc1
Message-ID: <20250307162332.3451523-1-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-soc

for you to fetch changes up to 5e63dfe213d01cdf0bb2786ae3d5ac613182a433:

  soc/tegra: pmc: Use str_enable_disable-like helpers (2025-03-06 19:12:37 +0100)

Thanks,
Thierry

----------------------------------------------------------------
soc/tegra: Changes for v6.15-rc1

A simple cleanup patch to use str_yes_no() instead of an open-coded
version.

----------------------------------------------------------------
Krzysztof Kozlowski (1):
      soc/tegra: pmc: Use str_enable_disable-like helpers

 drivers/soc/tegra/pmc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


From thierry.reding at gmail.com  Fri Mar  7 08:23:28 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 17:23:28 +0100
Subject: [GIT PULL 2/5] firmware: tegra: Changes for v6.15-rc1
In-Reply-To: <20250307162332.3451523-1-thierry.reding@gmail.com>
References: <20250307162332.3451523-1-thierry.reding@gmail.com>
Message-ID: <20250307162332.3451523-2-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-firmware

for you to fetch changes up to 27321c788b3aa238af3c3234dc722a30b62d8dcd:

  firmware: tegra: bpmp: Fix typo in bpmp-abi.h (2025-03-06 20:02:26 +0100)

Thanks,
Thierry

----------------------------------------------------------------
firmware: tegra: Changes for v6.15-rc1

Not much to this except for a simple typofix.

----------------------------------------------------------------
Zhu Jun (1):
      firmware: tegra: bpmp: Fix typo in bpmp-abi.h

 include/soc/tegra/bpmp-abi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


From thierry.reding at gmail.com  Fri Mar  7 08:23:30 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 17:23:30 +0100
Subject: [GIT PULL 4/5] ARM: tegra: Device tree changes for v6.15-rc1
In-Reply-To: <20250307162332.3451523-1-thierry.reding@gmail.com>
References: <20250307162332.3451523-1-thierry.reding@gmail.com>
Message-ID: <20250307162332.3451523-4-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-arm-dt

for you to fetch changes up to 237a868d30e7a744b64479ff98ad86b2e3008943:

  ARM: tegra: tf101: Add al3000a illuminance sensor node (2025-03-06 19:02:23 +0100)

Thanks,
Thierry

----------------------------------------------------------------
ARM: tegra: Device tree changes for v6.15-rc1

This contains a few patches that add some missing, display-related nodes
on Tegra114 and Tegra124, as well as a small fix in the display clock
used for DSI on Tegra114 and the addition of a light sensor found on the
ASUS TF101.

----------------------------------------------------------------
Svyatoslav Ryhel (5):
      ARM: tegra: Switch DSI-B clock parent to PLLD on Tegra114
      ARM: tegra: Add ARM PMU node on Tegra114
      ARM: tegra: Add HDA node on Tegra114
      ARM: tegra: Add DSI-A and DSI-B nodes on Tegra124
      ARM: tegra: tf101: Add al3000a illuminance sensor node

 arch/arm/boot/dts/nvidia/tegra114.dtsi          | 34 +++++++++++++++++----
 arch/arm/boot/dts/nvidia/tegra124.dtsi          | 40 +++++++++++++++++++++++++
 arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts | 11 +++++++
 3 files changed, 80 insertions(+), 5 deletions(-)


From thierry.reding at gmail.com  Fri Mar  7 08:23:31 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 17:23:31 +0100
Subject: [GIT PULL 5/5] arm64: tegra: Device tree changes for v6.15-rc1
In-Reply-To: <20250307162332.3451523-1-thierry.reding@gmail.com>
References: <20250307162332.3451523-1-thierry.reding@gmail.com>
Message-ID: <20250307162332.3451523-5-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-arm64-dt

for you to fetch changes up to c33a71fd0e3644520af7b5926926c06597d6d355:

  arm64: tegra: p2180: Add TMP451 temperature sensor node (2025-03-06 20:35:53 +0100)

Thanks,
Thierry

----------------------------------------------------------------
arm64: tegra: Device tree changes for v6.15-rc1

This contains some cleanup patches that remove unused properties and an
unusable key that was erroneously exposed. A fix to support GPUs with a
large amount of video memory on IGX Orin is also included.

Finally, some additional devices, such as a temperature sensor, are
enabled on Jetson TX1, and the output voltage of some pins is adjusted.
A fix for the VDD_LCD_1V8_DIS power supply is also included.

----------------------------------------------------------------
Diogo Ivo (4):
      arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator
      arm64: tegra: Define pinmuxing for gpio pads on Tegra210
      arm64: tegra: p2597: Enable TCA9539 as IRQ controllers
      arm64: tegra: p2180: Add TMP451 temperature sensor node

Jon Hunter (1):
      arm64: tegra: Resize aperture for the IGX PCIe C5 slot

Ninad Malwade (1):
      arm64: tegra: Remove the Orin NX/Nano suspend key

Rob Herring (Arm) (1):
      arm64: tegra: Remove unused and undocumented "regulator-ramp-delay-scale" property

 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi       | 13 +++++++++++++
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi       | 20 +++++++++++++++++++-
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts   | 10 ----------
 arch/arm64/boot/dts/nvidia/tegra210.dtsi             | 10 ++++++++++
 .../dts/nvidia/tegra234-p3740-0002+p3701-0008.dts    | 10 ++++++++++
 .../boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi   |  7 -------
 6 files changed, 52 insertions(+), 18 deletions(-)


From kuba at kernel.org  Fri Mar  7 08:39:59 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Fri, 7 Mar 2025 08:39:59 -0800
Subject: [PATCH net-next v2] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <3931a391-3967-4260-a104-4eb313810c0d@ti.com>
References: <20250305111608.520042-1-danishanwar@ti.com>
	<20250306165513.541ff46e@kernel.org>
	<3931a391-3967-4260-a104-4eb313810c0d@ti.com>
Message-ID: <20250307083959.33098949@kernel.org>

On Fri, 7 Mar 2025 16:00:40 +0530 MD Danish Anwar wrote:
> > Thanks for the docs, it looks good. Now, do all of these get included
> > in the standard stats returned by icssg_ndo_get_stats64 ?
> > That's the primary source of information for the user regarding packet
> > loss.  
> 
> No, these are not reported via icssg_ndo_get_stats64.
> 
> .ndo_get_stats64 populates stats that are part of `struct
> rtnl_link_stats64`. icssg_ndo_get_stats64 populates those stats wherever
> applicable. These firmware stats are not same as the ones defined in
> `icssg_ndo_get_stats64` hence they are not populated. They are not
> standard stats, they will be dumped by `ethtool -S`. Wherever there is a
> standard stats, I will make sure it gets dumped from the standard
> interface instead of `ethtool -S`
> 
> Only below stats are included in the standard stats returned by
> icssg_ndo_get_stats64
> - rx_packets
> - rx_bytes
> - tx_packets
> - tx_bytes
> - rx_crc_errors
> - rx_over_errors
> - rx_multicast_frames

Yes, but if the stats you're adding here relate to packets sent /
destined to the host which were lost you should include them
in the aggregate rx_errors / rx_dropped / tx_errors / tx_dropped.
I understand that there's unlikely to be a 1:1 match with specific
stats.

> > This gets called by icssg_ndo_get_stats64() which is under RCU   
> 
> Yes, this does get called by icssg_ndo_get_stats64(). Apart from that
> there is a workqueue (`icssg_stats_work_handler`) that calls this API
> periodically and updates the emac->stats and emac->pa_stats arrays.
>
> > protection and nothing else. I don't see any locking here, and  
> 
> There is no locking here. I don't think this is related to the patch.
> The API emac_update_hardware_stats() updates all the stats supported by
> ICSSG not just standard stats.

Yes, I'm saying you should send a separate fix, not really related or
blocking this patch (unless they conflict)

> > I hope the regmap doesn't sleep. cat /proc/net/dev to test.
> > You probably need to send some fixes to net.  
> 
> I checked cat /proc/net/dev and the stats shown there are not related to
> the stats I am introducing in this series.

You misunderstood. I pointed that you so you can check on a debug
kernel if there are any warnings (e.g. something tries to sleep
since /proc/net/dev read is under RCU lock).

> The fix could be to add a lock in this function, but we have close to 90
> stats and this function is called not only from icssg_ndo_get_stats64()
> but from emac_get_ethtool_stats(). The function also gets called
> periodically (Every 25 Seconds for 1G Link). I think every time locking
> 90 regmap_reads() could result in performance degradation.

Correctness comes first.


From cki-project at redhat.com  Fri Mar  7 08:42:07 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 07 Mar 2025 16:42:07 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc5,
 upstream-arm-next, 14d05f12)
Message-ID: <85056.125030711421000917@us-mta-125.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1705185320

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1705185320-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From dianders at chromium.org  Fri Mar  7 08:53:37 2025
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 7 Mar 2025 08:53:37 -0800
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <20250307021811.46981-3-yangyicong@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com> <20250307021811.46981-3-yangyicong@huawei.com>
Message-ID: <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>

Hi,

On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
>
> From: Yicong Yang <yangyicong at hisilicon.com>
>
> arm64 depends on the cpufreq driver to gain the maximum cpu frequency
> to convert the watchdog_thresh to perf event period. cpufreq drivers
> like cppc_cpufreq will be initialized lately after the initializing of
> the hard lockup detector so just use a safe cpufreq which will be
> inaccurency. Use a cpufreq notifier to adjust the event's period to
> a more accurate one.
>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> ---
>  arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
>
> diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
> index dcd25322127c..719ae39e8bc0 100644
> --- a/arch/arm64/kernel/watchdog_hld.c
> +++ b/arch/arm64/kernel/watchdog_hld.c
> @@ -34,3 +34,37 @@ bool __init arch_perf_nmi_is_available(void)
>          */
>         return arm_pmu_irq_is_nmi();
>  }
> +
> +static int watchdog_freq_notifier_callback(struct notifier_block *nb,
> +                                          unsigned long val, void *data)
> +{
> +       struct cpufreq_policy *policy = data;
> +       unsigned long max_cpu_freq;

Feels like max_cpu_freq should be a u64. It probably should have been
u64 in hw_nmi_get_sample_period() as well. Otherwise you could end up
with a problem if the max CPU frequency is above ~4.3GHz and "unsigned
long" is 32-bits (I think it technically could be?)


> +       u64 new_period;
> +       int cpu;
> +
> +       if (val != CPUFREQ_CREATE_POLICY)
> +               return 0;

nit: maybe better documenting to return "NOTIFY_DONE" instead of 0?


> +       for_each_cpu(cpu, policy->cpus) {
> +               max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> +               if (!max_cpu_freq)
> +                       continue;
> +
> +               new_period = watchdog_thresh * max_cpu_freq;
> +               hardlockup_detector_perf_adjust_period(cpu, new_period);
> +       }
> +
> +       return 0;
> +}
> +
> +static struct notifier_block watchdog_freq_notifier = {
> +       .notifier_call = watchdog_freq_notifier_callback,
> +};
> +
> +static int __init init_watchdog_freq_notifier(void)
> +{
> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
> +                                        CPUFREQ_POLICY_NOTIFIER);
> +}
> +core_initcall(init_watchdog_freq_notifier);

I haven't dug into everything, but don't you have a potential blind
spot, though? What if the order is this:

1. hw_nmi_get_sample_period() is called
2. cpufreq driver probes
3. init_watchdog_freq_notifier() initcall runs

Since the cpufreq driver proved before you registered for the
notifier, won't you miss the creation of the policy? Maybe instead of
registering for an initcall you should somehow trigger off the first
call to hw_nmi_get_sample_period() and register at that point in time?

-Doug


From kuba at kernel.org  Fri Mar  7 08:55:58 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Fri, 7 Mar 2025 08:55:58 -0800
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
	<20250306210950.1686713-3-jonas@kwiboo.se>
	<bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
	<1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>
Message-ID: <20250307085558.5f8fcb90@kernel.org>

On Fri, 7 Mar 2025 00:49:38 +0100 Jonas Karlman wrote:
> Subject: Re: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
> 
> [encrypted.asc  application/octet-stream (3384 bytes)] 

Is it just me or does anyone else get blobs from Jonas?
The list gets text, according to lore.


From gregory.clement at bootlin.com  Fri Mar  7 08:49:55 2025
From: gregory.clement at bootlin.com (Gregory CLEMENT)
Date: Fri, 07 Mar 2025 17:49:55 +0100
Subject: ***SPAM*** [PATCH 1/2] arm64: dts: marvell: armada-8040: Align
 GPIO hog name with bindings
In-Reply-To: <20250115211727.194142-1-krzysztof.kozlowski@linaro.org>
References: <20250115211727.194142-1-krzysztof.kozlowski@linaro.org>
Message-ID: <87v7sk23bg.fsf@BLaptop.bootlin.com>

Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org> writes:

> Bindings expect GPIO hog names to end with 'hog' suffix, so correct it
> to fix dtbs_check warning:
>
>   armada-8040-clearfog-gt-8k.dtb: sata_reset: $nodename:0: 'sata_reset' does not match '^.+-hog(-[0-9]+)?$'
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


Applied on mvebu/dt64

Thanks,

Gregory

> ---
>  .../arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
> index 225a54ab688d..90ae93274a16 100644
> --- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
> +++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
> @@ -371,25 +371,25 @@ &cp0_pcie0 {
>  };
>  
>  &cp0_gpio2 {
> -	sata_reset {
> +	sata-reset-hog {
>  		gpio-hog;
>  		gpios = <1 GPIO_ACTIVE_HIGH>;
>  		output-high;
>  	};
>  
> -	lte_reset {
> +	lte-reset-hog {
>  		gpio-hog;
>  		gpios = <2 GPIO_ACTIVE_LOW>;
>  		output-low;
>  	};
>  
> -	wlan_disable {
> +	wlan_disable-hog {
>  		gpio-hog;
>  		gpios = <19 GPIO_ACTIVE_LOW>;
>  		output-low;
>  	};
>  
> -	lte_disable {
> +	lte-disable-hog {
>  		gpio-hog;
>  		gpios = <21 GPIO_ACTIVE_LOW>;
>  		output-low;
> -- 
> 2.43.0
>

-- 
Gr?gory CLEMENT, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From gregory.clement at bootlin.com  Fri Mar  7 08:50:06 2025
From: gregory.clement at bootlin.com (Gregory CLEMENT)
Date: Fri, 07 Mar 2025 17:50:06 +0100
Subject: [PATCH 2/2] ARM: dts: marvell: kirkwood-openrd: Align GPIO hog
 name with bindings
In-Reply-To: <20250115211727.194142-2-krzysztof.kozlowski@linaro.org>
References: <20250115211727.194142-1-krzysztof.kozlowski@linaro.org>
 <20250115211727.194142-2-krzysztof.kozlowski@linaro.org>
Message-ID: <87seno23b5.fsf@BLaptop.bootlin.com>

Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org> writes:

> Bindings expect GPIO hog names to end with 'hog' suffix, so correct it
> to fix dtbs_check warning:
>
>   kirkwood-openrd-ultimate.dtb: p28: $nodename:0: 'p28' does not match '^.+-hog(-[0-9]+)?$'
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Applied on mvebu/dt64

Thanks,

Gregory

> ---
>  arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi b/arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi
> index 47f03c69c55a..9d7cff4feada 100644
> --- a/arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi
> +++ b/arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi
> @@ -53,7 +53,7 @@ mvsdio at 90000 {
>  			cd-gpios = <&gpio0 29 9>;
>  		};
>  		gpio at 10100 {
> -			p28 {
> +			p28-hog {
>  				gpio-hog;
>  				gpios = <28 GPIO_ACTIVE_HIGH>;
>  				/*
> @@ -71,7 +71,7 @@ p28 {
>  			};
>  		};
>  		gpio at 10140 {
> -			p2 {
> +			p2-hog {
>  				gpio-hog;
>  				gpios = <2 GPIO_ACTIVE_HIGH>;
>  				/*
> -- 
> 2.43.0
>

-- 
Gr?gory CLEMENT, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From gregory.clement at bootlin.com  Fri Mar  7 08:50:36 2025
From: gregory.clement at bootlin.com (Gregory CLEMENT)
Date: Fri, 07 Mar 2025 17:50:36 +0100
Subject: [PATCH] ARM: dts: marvell: armada: Align GPIO hog name with
 bindings
In-Reply-To: <6bed3249-9905-4949-8031-52217f123f2e@lunn.ch>
References: <20250116085947.87241-1-krzysztof.kozlowski@linaro.org>
 <6bed3249-9905-4949-8031-52217f123f2e@lunn.ch>
Message-ID: <87plis23ab.fsf@BLaptop.bootlin.com>

Andrew Lunn <andrew at lunn.ch> writes:

> On Thu, Jan 16, 2025 at 09:59:47AM +0100, Krzysztof Kozlowski wrote:
>> Bindings expect GPIO hog names to end with 'hog' suffix, so correct it
>> to fix dtbs_check warnings like:
>> 
>>   armada-385-clearfog-gtr-s4.dtb: wifi-disable: $nodename:0: 'wifi-disable' does not match '^.+-hog(-[0-9]+)?$'
>  

Applied on mvebu/dt64

Thanks,

Gregory

> Hi Krzysztof
>
> I believe the mvebu pull request for the next merge window has already
> been sent to arm-soc. So please repost after -rc1.
>
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
>
>     Andrew

-- 
Gr?gory CLEMENT, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From dianders at chromium.org  Fri Mar  7 08:53:18 2025
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 7 Mar 2025 08:53:18 -0800
Subject: [PATCH 1/2] watchdog/perf: Provide function for adjusting the
 event period
In-Reply-To: <20250307021811.46981-2-yangyicong@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com> <20250307021811.46981-2-yangyicong@huawei.com>
Message-ID: <CAD=FV=WfB6inJPuwfhbw4mtFBYpr+3ot2J+SJAZ3pT3t4fW7cw@mail.gmail.com>

Hi,

On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
>
> @@ -211,6 +211,27 @@ void hardlockup_detector_perf_cleanup(void)
>         cpumask_clear(&dead_events_mask);
>  }
>
> +/**
> + * hardlockup_detector_perf_adjust_period - Adjust the events period due
> + *                                          to cpu frequency change
> + */
> +void hardlockup_detector_perf_adjust_period(int cpu, u64 period)

Running `scripts/kernel-doc -v kernel/watchdog_perf.c > /dev/null`
after your patch shows:

kernel/watchdog_perf.c:219: warning: Function parameter or struct
member 'cpu' not described in 'hardlockup_detector_perf_adjust_period'
kernel/watchdog_perf.c:219: warning: Function parameter or struct
member 'period' not described in
'hardlockup_detector_perf_adjust_period'


Other than that, this seems reasonable to me.

...but I'd also have to ask: is there a reason you're using the "perf"
hard-lockup detector instead of the buddy one? In my mind, the "buddy"
watchdog is better in almost all ways (I believe it's lower power,
doesn't waste a "perf" controller, and doesn't suffer from frequency
issues). It's even crossed my mind whether the "perf" lockup detector
should be deprecated. ;-)


From catalin.marinas at arm.com  Fri Mar  7 08:57:28 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 7 Mar 2025 16:57:28 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <03dc25a3-c8a6-443b-ade7-2d3f69f2d0f4@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
 <03dc25a3-c8a6-443b-ade7-2d3f69f2d0f4@arm.com>
Message-ID: <Z8sleC_1d1ozYdOO@arm.com>

On Thu, Mar 06, 2025 at 03:28:26PM +0000, Robin Murphy wrote:
> On 28/02/2025 5:00 pm, Kristina Mart?enko wrote:
> > A subsequent patch will use CPY* instructions to copy between user and
> > kernel memory. Add handling for PAN faults caused by an intended kernel
> > memory access erroneously accessing user memory, in order to make it
> > easier to debug kernel bugs and to keep the same behavior as with
> > regular loads/stores.
> 
> I'd be tempted to fold the search_exception_tables() call into
> insn_may_access_user() itself, but either way,

Yeah, I think it looks better folded in. I did it locally.

> Reviewed-by: Robin Murphy <robin.murphy at arm.com>

Thanks.

-- 
Catalin


From mhklinux at outlook.com  Fri Mar  7 09:02:35 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 17:02:35 +0000
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
> SynIC event ring buffer for each SINT.
> 
> This will be used by the mshv driver, but must be tracked independently
> since the driver module could be removed and re-inserted.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> ---
>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 252fd66ad4db..2763cb6d3678 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
> 
>  static struct ctl_table_header *hv_ctl_table_hdr;
> 
> +/*
> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
> + * for each SINT.
> + *
> + * We cannot maintain this in mshv driver because the tail pointer should
> + * persist even if the mshv driver is unloaded.
> + */
> +u8 __percpu **hv_synic_eventring_tail;

I think the "__percpu" is in the wrong place here. This placement
is likely to cause errors from the "sparse" tool.  It should be

u8 * __percpu *hv_synic_eventring_tail;

See the way hyperv_pcpu_input_arg, for example, is defined.  And
see commit db3c65bc3a13 where I fixed hyperv_pcpu_input_arg.

> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);

The "extern" declaration for this variable is in Patch 10 of the series
in drivers/hv/mshv_root.h. I guess that's OK, but I would normally
expect to find such a declaration in the header file associated with
where the variable is defined, which in this case is mshyperv.h.
Perhaps you are trying to restrict its usage to just mshv?

> +
>  /*
>   * Hyper-V specific initialization and shutdown code that is
>   * common across all architectures.  Called from architecture
> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
> 
>  	free_percpu(hyperv_pcpu_input_arg);
>  	hyperv_pcpu_input_arg = NULL;
> +
> +	free_percpu(hv_synic_eventring_tail);
> +	hv_synic_eventring_tail = NULL;
>  }
> 
>  /*
> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
>  		BUG_ON(!hyperv_pcpu_output_arg);
>  	}
> 
> +	if (hv_root_partition()) {
> +		hv_synic_eventring_tail = alloc_percpu(u8 *);
> +		BUG_ON(hv_synic_eventring_tail == NULL);
> +	}
> +
>  	hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
>  				    GFP_KERNEL);
>  	if (!hv_vp_index) {
> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
>  int hv_common_cpu_init(unsigned int cpu)
>  {
>  	void **inputarg, **outputarg;
> +	u8 **synic_eventring_tail;
>  	u64 msr_vp_index;
>  	gfp_t flags;
>  	const int pgcount = hv_output_page_exists() ? 2 : 1;
> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
>  	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
> 
>  	/*
> -	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
> -	 * allocated if this CPU was previously online and then taken offline
> +	 * The per-cpu memory is already allocated if this CPU was previously
> +	 * online and then taken offline
>  	 */
>  	if (!*inputarg) {
>  		mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
>  			*outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
>  		}
> 
> +		if (hv_root_partition()) {
> +			synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> +			*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
> +							sizeof(u8), flags);
> +
> +			if (unlikely(!*synic_eventring_tail)) {
> +				kfree(mem);
> +				return -ENOMEM;
> +			}
> +		}
> +

Adding this code under the "if(!*inputarg)" implicitly ties the lifecycle of
synic_eventring_tail to the lifecycle of hyperv_pcpu_input_arg and
hyperv_pcpu_output_arg. Is there some logical relationship between the
two that warrants tying the lifecycles together (other than just both being
per-cpu)?  hyperv_pcpu_input_arg and hyperv_pcpu_output_arg have an
unusual lifecycle management in that they aren't freed when a CPU goes
offline, as described in the comment in hv_common_cpu_die(). Does
synic_eventring_tail also need that same unusual lifecycle?

Assuming there's no logical relationship, I'm thinking synic_eventring_tail
should be managed independent of the other two. If it does need the
unusual lifecycle, make sure to add a comment in hv_common_cpu_die()
explaining why. If it doesn't need the unusual lifecycle, maybe just do
the normal thing of allocating it in hv_common_cpu_init() and freeing
it in hv_common_cpu_die().

The code as written in your patch isn't wrong and would work OK. But
the structure implies a relationship with hyperv_pcpu_*_arg that I
suspect doesn't exist.

Michael

>  		if (!ms_hyperv.paravisor_present &&
>  		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
>  			ret = set_memory_decrypted((unsigned long)mem, pgcount);
> --
> 2.34.1



From ukleinek at kernel.org  Fri Mar  7 09:07:47 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Fri, 7 Mar 2025 18:07:47 +0100
Subject: [PATCH 1/2] dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
In-Reply-To: <20250307120004.959980-2-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <20250307120004.959980-2-amadeus@jmu.edu.cn>
Message-ID: <pnlkcc2rl7fegltovgtvp4xdxhonw72rclvhn7qmvb7xyuullm@xf5x6lcigji3>

Hello,

On Fri, Mar 07, 2025 at 08:00:03PM +0800, Chukun Pan wrote:
> Document pwm compatible for rk3528 which is fallback compatible
> of rk3328-pwm group.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>

to prevent binding warnings it's probably sensible to let both patches
go in via the same tree at the same time. Feel free to take the binding
patch via rockchip/arm-soc.

Acked-by: Uwe Kleine-K?nig <ukleinek at kernel.org>

Thanks
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/5b578ac9/attachment.sig>

From linux at armlinux.org.uk  Fri Mar  7 09:07:57 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 7 Mar 2025 17:07:57 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
 <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
Message-ID: <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>

On Fri, Mar 07, 2025 at 04:11:19PM +0000, Jon Hunter wrote:
> Hi Russell,
> 
> On 06/03/2025 15:23, Russell King (Oracle) wrote:
> > Hi,
> > 
> > This is a second approach to solving the STMMAC reset issues caused by
> > the lack of receive clock from the PHY where the media is in low power
> > mode with a PHY that supports receive clock-stop.
> > 
> > The first approach centred around only addressing the issue in the
> > resume path, but it seems to also happen when the platform glue module
> > is removed and re-inserted (Jon - can you check whether that's also
> > the case for you please?)
> > 
> > As this is more targetted, I've dropped the patches from this series
> > which move the call to phylink_resume(), so the link may still come
> > up too early on resume - but that's something I also intend to fix.
> > 
> > This is experimental - so I value test reports for this change.
> 
> 
> The subject indicates 3 patches, but I only see 2 patches? Can you confirm
> if there are 2 or 3?

Yes, 2 patches is correct.

> So far I have only tested to resume case with the 2 patches to make that
> that is working but on Tegra186, which has been the most problematic, it is
> not working reliably on top of next-20250305.

To confirm, you're seeing stmmac_reset() sporadically timing out on
resume even with these patches appled? That's rather disappointing.

Do either of the two attached diffs make any difference?

Thanks for testing!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: stmmac-block-rx-clk-stop.diff
Type: text/x-diff
Size: 1098 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/b020d520/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: stmmac-block-rx-clk-stop-2.diff
Type: text/x-diff
Size: 1303 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/b020d520/attachment-0001.bin>

From lorenzo at kernel.org  Fri Mar  7 09:08:18 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 07 Mar 2025 18:08:18 +0100
Subject: [PATCH 0/2] Add gpio-ranges property for EN7581 gpio controller
Message-ID: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>

Introduce missing gpio-ranges property for Airoha EN7581 evaluation
board

---
Lorenzo Bianconi (2):
      dt-bindings: pinctrl: airoha: Add missing gpio-ranges property
      arm64: dts: airoha: en7581: Add gpio-ranges property for gpio controller

 Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml | 3 +++
 arch/arm64/boot/dts/airoha/en7581-evb.dts                            | 4 ++++
 2 files changed, 7 insertions(+)
---
base-commit: a8a297e8bb3dd304cac77f7c435a4983d885a657
change-id: 20250307-en7581-gpio-range-fceb30c7e2c9

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From lorenzo at kernel.org  Fri Mar  7 09:08:19 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 07 Mar 2025 18:08:19 +0100
Subject: [PATCH 1/2] dt-bindings: pinctrl: airoha: Add missing gpio-ranges
 property
In-Reply-To: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
Message-ID: <20250307-en7581-gpio-range-v1-1-de1262105428@kernel.org>

Introduce leftover gpio-ranges property for Airoha EN7581 pinctrl binding

Fixes: d0c15cb96b74 ("dt-bindings: pinctrl: airoha: Add EN7581 pinctrl")
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
index b2601d698dcd41c3ef32af547ea41be0d6904ae6..21fd4f1ba78b05e5347b4ffe578656c8a4dc5636 100644
--- a/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
@@ -24,6 +24,9 @@ properties:
   '#gpio-cells':
     const: 2
 
+  gpio-ranges:
+    maxItems: 1
+
   interrupt-controller: true
 
   '#interrupt-cells':

-- 
2.48.1



From lorenzo at kernel.org  Fri Mar  7 09:08:20 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 07 Mar 2025 18:08:20 +0100
Subject: [PATCH 2/2] arm64: dts: airoha: en7581: Add gpio-ranges property
 for gpio controller
In-Reply-To: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
Message-ID: <20250307-en7581-gpio-range-v1-2-de1262105428@kernel.org>

Introduce missing gpio-ranges property for Airoha EN7581 gpio controller

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 arch/arm64/boot/dts/airoha/en7581-evb.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/airoha/en7581-evb.dts b/arch/arm64/boot/dts/airoha/en7581-evb.dts
index d53b72d18242e3cee8b37c7b1b719d662fd6db8d..a8f8a9f0b807a2ee4fd11f8418b8e810a6945d73 100644
--- a/arch/arm64/boot/dts/airoha/en7581-evb.dts
+++ b/arch/arm64/boot/dts/airoha/en7581-evb.dts
@@ -65,6 +65,10 @@ reserved_bmt at 7e00000 {
 	};
 };
 
+&en7581_pinctrl {
+	gpio-ranges = <&en7581_pinctrl 0 13 47>;
+};
+
 &i2c0 {
 	status = "okay";
 };

-- 
2.48.1



From andrew at lunn.ch  Fri Mar  7 09:15:02 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 7 Mar 2025 18:15:02 +0100
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <20250307085558.5f8fcb90@kernel.org>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
 <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
 <1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>
 <20250307085558.5f8fcb90@kernel.org>
Message-ID: <1995782a-0a1c-46dc-8929-7fa3428a5ca3@lunn.ch>

On Fri, Mar 07, 2025 at 08:55:58AM -0800, Jakub Kicinski wrote:
> On Fri, 7 Mar 2025 00:49:38 +0100 Jonas Karlman wrote:
> > Subject: Re: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
> > 
> > [encrypted.asc  application/octet-stream (3384 bytes)] 
> 
> Is it just me or does anyone else get blobs from Jonas?
> The list gets text, according to lore.

Sorry, already deleted, but i was able to read the contents, so either
they are plain text, or mutt is clever enough to make sense of the
blob.

	Andrew


From andriy.shevchenko at linux.intel.com  Fri Mar  7 09:17:26 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri, 7 Mar 2025 19:17:26 +0200
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
 <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
Message-ID: <Z8sqJhbqEBla_Ch7@smile.fi.intel.com>

On Fri, Mar 07, 2025 at 12:19:08PM +0100, Luca Ceresoli wrote:
> %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> add %pC{,n,r} format specifiers for clocks") introducing them does not
> clarify any intended difference. It can be assumed %pC is a default for
> %pCn as some other specifiers do, but not all are consistent with this
> policy. Moreover there is now no other suffix other than 'n', which makes a
> default not really useful.
> 
> All users in the kernel were using %pC except for one which has been
> converted. So now remove %pCn and all the unnecessary extra code and
> documentation.

You seem forgot to update translation(s) of the documentation.

-- 
With Best Regards,
Andy Shevchenko




From srinivas.kandagatla at linaro.org  Fri Mar  7 09:22:23 2025
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Fri, 7 Mar 2025 17:22:23 +0000
Subject: [PATCH v2 1/3] dt-bindings: nvmem: rockchip,otp: Add support for
 rk3562 and rk3568
In-Reply-To: <20250227110804.2342976-1-kever.yang@rock-chips.com>
References: <20250227110804.2342976-1-kever.yang@rock-chips.com>
Message-ID: <f662da0e-431f-4e04-b8ee-e8b04a08337d@linaro.org>

Hi Kever,


On 27/02/2025 11:08, Kever Yang wrote:
> Add compatible entry for the otp controller in rk3562 and rk3568, add schema
> for different clock names for new entry.
> 
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---

Am unable to apply this patch, Could you rebase it on top of linux-next 
or 
https://web.git.kernel.org/pub/scm/linux/kernel/git/srini/nvmem.git/log/?h=for-next


--srini

> 
> Changes in v2:
> - Update the commit message and add maxItems in schema.
> 
>   .../bindings/nvmem/rockchip,otp.yaml          | 53 ++++++++++++++++---
>   1 file changed, 46 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> index a44d44b32809..7572f4a1d73b 100644
> --- a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> +++ b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> @@ -14,6 +14,8 @@ properties:
>       enum:
>         - rockchip,px30-otp
>         - rockchip,rk3308-otp
> +      - rockchip,rk3562-otp
> +      - rockchip,rk3568-otp
>         - rockchip,rk3588-otp
>   
>     reg:
> @@ -25,19 +27,15 @@ properties:
>   
>     clock-names:
>       minItems: 3
> -    items:
> -      - const: otp
> -      - const: apb_pclk
> -      - const: phy
> -      - const: arb
> +    maxItems: 4
>   
>     resets:
>       minItems: 1
> -    maxItems: 3
> +    maxItems: 4
>   
>     reset-names:
>       minItems: 1
> -    maxItems: 3
> +    maxItems: 4
>   
>   required:
>     - compatible
> @@ -62,12 +60,45 @@ allOf:
>         properties:
>           clocks:
>             maxItems: 3
> +        clock-names:
> +          items:
> +            - const: otp
> +            - const: apb_pclk
> +            - const: phy
>           resets:
>             maxItems: 1
>           reset-names:
>             items:
>               - const: phy
>   
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - rockchip,rk3562-otp
> +              - rockchip,rk3568-otp
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 4
> +          maxItems: 4
> +        clock-names:
> +          items:
> +            - const: usr
> +            - const: sbpi
> +            - const: apb_pclk
> +            - const: phy
> +        resets:
> +          minItems: 4
> +          maxItems: 4
> +        reset-names:
> +          items:
> +            - const: usr
> +            - const: sbpi
> +            - const: apb
> +            - const: phy
> +
>     - if:
>         properties:
>           compatible:
> @@ -78,8 +109,16 @@ allOf:
>         properties:
>           clocks:
>             minItems: 4
> +          maxItems: 4
> +        clock-names:
> +          items:
> +            - const: otp
> +            - const: apb_pclk
> +            - const: phy
> +            - const: arb
>           resets:
>             minItems: 3
> +          maxItems: 3
>           reset-names:
>             items:
>               - const: otp


From mhklinux at outlook.com  Fri Mar  7 09:26:39 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 17:26:39 +0000
Subject: [PATCH v5 09/10] hyperv: Add definitions for root partition
 driver to hv headers
In-Reply-To: <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB41575301E96B82BF3813828BD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
> A few additional definitions are required for the mshv driver code
> (to follow). Introduce those here and clean up a little bit while
> at it.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---
>  include/hyperv/hvgdk_mini.h |  64 ++++++++++++++++-
>  include/hyperv/hvhdk.h      | 132 ++++++++++++++++++++++++++++++++++--
>  include/hyperv/hvhdk_mini.h |  91 +++++++++++++++++++++++++
>  3 files changed, 280 insertions(+), 7 deletions(-)
> 
> diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
> index 58895883f636..e4a3cca0cbce 100644
> --- a/include/hyperv/hvgdk_mini.h
> +++ b/include/hyperv/hvgdk_mini.h
> @@ -13,7 +13,7 @@ struct hv_u128 {
>  	u64 high_part;
>  } __packed;
> 
> -/* NOTE: when adding below, update hv_status_to_string() */
> +/* NOTE: when adding below, update hv_result_to_string() */
>  #define HV_STATUS_SUCCESS			    0x0
>  #define HV_STATUS_INVALID_HYPERCALL_CODE	    0x2
>  #define HV_STATUS_INVALID_HYPERCALL_INPUT	    0x3
> @@ -51,6 +51,7 @@ struct hv_u128 {
>  #define HV_HYP_PAGE_SHIFT		12
>  #define HV_HYP_PAGE_SIZE		BIT(HV_HYP_PAGE_SHIFT)
>  #define HV_HYP_PAGE_MASK		(~(HV_HYP_PAGE_SIZE - 1))
> +#define HV_HYP_LARGE_PAGE_SHIFT		21
> 
>  #define HV_PARTITION_ID_INVALID		((u64)0)
>  #define HV_PARTITION_ID_SELF		((u64)-1)
> @@ -374,6 +375,10 @@ union hv_hypervisor_version_info {
>  #define HV_SHARED_GPA_BOUNDARY_ACTIVE			BIT(5)
>  #define HV_SHARED_GPA_BOUNDARY_BITS			GENMASK(11, 6)
> 
> +/* HYPERV_CPUID_FEATURES.ECX bits. */
> +#define HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE	BIT(9)
> +#define HV_VP_GHCB_ROOT_MAPPING_AVAILABLE		BIT(10)
> +
>  enum hv_isolation_type {
>  	HV_ISOLATION_TYPE_NONE	= 0,	/*
> HV_PARTITION_ISOLATION_TYPE_NONE */
>  	HV_ISOLATION_TYPE_VBS	= 1,
> @@ -437,9 +442,12 @@ union hv_vp_assist_msr_contents {	 /*
> HV_REGISTER_VP_ASSIST_PAGE */
>  #define HVCALL_MAP_GPA_PAGES				0x004b
>  #define HVCALL_UNMAP_GPA_PAGES				0x004c
>  #define HVCALL_CREATE_VP				0x004e
> +#define HVCALL_INSTALL_INTERCEPT			0x004d

This is numerically out-of-order.  Should be before HVCALL_CREATE_VP.

>  #define HVCALL_DELETE_VP				0x004f
>  #define HVCALL_GET_VP_REGISTERS				0x0050
>  #define HVCALL_SET_VP_REGISTERS				0x0051
> +#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS		0x0052
> +#define HVCALL_CLEAR_VIRTUAL_INTERRUPT			0x0056
>  #define HVCALL_DELETE_PORT				0x0058
>  #define HVCALL_DISCONNECT_PORT				0x005b
>  #define HVCALL_POST_MESSAGE				0x005c
> @@ -447,12 +455,15 @@ union hv_vp_assist_msr_contents {	 /*
> HV_REGISTER_VP_ASSIST_PAGE */
>  #define HVCALL_POST_DEBUG_DATA				0x0069
>  #define HVCALL_RETRIEVE_DEBUG_DATA			0x006a
>  #define HVCALL_RESET_DEBUG_SESSION			0x006b
> +#define HVCALL_MAP_STATS_PAGE				0x006c
> +#define HVCALL_UNMAP_STATS_PAGE				0x006d
>  #define HVCALL_ADD_LOGICAL_PROCESSOR			0x0076
>  #define HVCALL_GET_SYSTEM_PROPERTY			0x007b
>  #define HVCALL_MAP_DEVICE_INTERRUPT			0x007c
>  #define HVCALL_UNMAP_DEVICE_INTERRUPT			0x007d
>  #define HVCALL_RETARGET_INTERRUPT			0x007e
>  #define HVCALL_NOTIFY_PORT_RING_EMPTY			0x008b
> +#define HVCALL_REGISTER_INTERCEPT_RESULT		0x0091
>  #define HVCALL_ASSERT_VIRTUAL_INTERRUPT			0x0094
>  #define HVCALL_CREATE_PORT				0x0095
>  #define HVCALL_CONNECT_PORT				0x0096
> @@ -460,12 +471,18 @@ union hv_vp_assist_msr_contents {	 /*
> HV_REGISTER_VP_ASSIST_PAGE */
>  #define HVCALL_GET_VP_ID_FROM_APIC_ID			0x009a
>  #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE	0x00af
>  #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST	0x00b0
> +#define HVCALL_SIGNAL_EVENT_DIRECT			0x00c0
> +#define HVCALL_POST_MESSAGE_DIRECT			0x00c1
>  #define HVCALL_DISPATCH_VP				0x00c2
> +#define HVCALL_GET_GPA_PAGES_ACCESS_STATES		0x00c9
> +#define HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d7
> +#define HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d8
>  #define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY	0x00db
>  #define HVCALL_MAP_VP_STATE_PAGE			0x00e1
>  #define HVCALL_UNMAP_VP_STATE_PAGE			0x00e2
>  #define HVCALL_GET_VP_STATE				0x00e3
>  #define HVCALL_SET_VP_STATE				0x00e4
> +#define HVCALL_GET_VP_CPUID_VALUES			0x00f4
>  #define HVCALL_MMIO_READ				0x0106
>  #define HVCALL_MMIO_WRITE				0x0107
> 
> @@ -807,6 +824,8 @@ struct hv_x64_table_register {
>  	u64 base;
>  } __packed;
> 
> +#define HV_NORMAL_VTL	0
> +
>  union hv_input_vtl {
>  	u8 as_uint8;
>  	struct {
> @@ -1325,6 +1344,49 @@ struct hv_retarget_device_interrupt {	 /*
> HV_INPUT_RETARGET_DEVICE_INTERRUPT */
>  	struct hv_device_interrupt_target int_target;
>  } __packed __aligned(8);
> 
> +enum hv_intercept_type {
> +#if defined(CONFIG_X86_64)
> +	HV_INTERCEPT_TYPE_X64_IO_PORT			= 0x00000000,
> +	HV_INTERCEPT_TYPE_X64_MSR			= 0x00000001,
> +	HV_INTERCEPT_TYPE_X64_CPUID			= 0x00000002,
> +#endif
> +	HV_INTERCEPT_TYPE_EXCEPTION			= 0x00000003,
> +	/* Used to be HV_INTERCEPT_TYPE_REGISTER */
> +	HV_INTERCEPT_TYPE_RESERVED0			= 0x00000004,
> +	HV_INTERCEPT_TYPE_MMIO				= 0x00000005,
> +#if defined(CONFIG_X86_64)
> +	HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID		= 0x00000006,
> +	HV_INTERCEPT_TYPE_X64_APIC_SMI			= 0x00000007,
> +#endif
> +	HV_INTERCEPT_TYPE_HYPERCALL			= 0x00000008,
> +#if defined(CONFIG_X86_64)
> +	HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI		= 0x00000009,
> +	HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ	= 0x0000000A,
> +	HV_INTERCEPT_TYPE_X64_APIC_WRITE		= 0x0000000B,
> +	HV_INTERCEPT_TYPE_X64_MSR_INDEX			= 0x0000000C,
> +#endif
> +	HV_INTERCEPT_TYPE_MAX,
> +	HV_INTERCEPT_TYPE_INVALID			= 0xFFFFFFFF,
> +};
> +
> +union hv_intercept_parameters {
> +	/*  HV_INTERCEPT_PARAMETERS is defined to be an 8-byte field. */
> +	__u64 as_uint64;
> +#if defined(CONFIG_X86_64)
> +	/* HV_INTERCEPT_TYPE_X64_IO_PORT */
> +	__u16 io_port;
> +	/* HV_INTERCEPT_TYPE_X64_CPUID */
> +	__u32 cpuid_index;
> +	/* HV_INTERCEPT_TYPE_X64_APIC_WRITE */
> +	__u32 apic_write_mask;
> +	/* HV_INTERCEPT_TYPE_EXCEPTION */
> +	__u16 exception_vector;
> +	/* HV_INTERCEPT_TYPE_X64_MSR_INDEX */
> +	__u32 msr_index;
> +#endif
> +	/* N.B. Other intercept types do not have any parameters. */
> +};
> +
>  /* Data structures for HVCALL_MMIO_READ and HVCALL_MMIO_WRITE */
>  #define HV_HYPERCALL_MMIO_MAX_DATA_LENGTH 64
> 
> diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
> index 64407c2a3809..1b447155c338 100644
> --- a/include/hyperv/hvhdk.h
> +++ b/include/hyperv/hvhdk.h
> @@ -19,11 +19,24 @@
> 
>  #define HV_VP_REGISTER_PAGE_VERSION_1	1u
> 
> +#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT		7
> +
> +union hv_vp_register_page_interrupt_vectors {
> +	u64 as_uint64;
> +	struct {
> +		u8 vector_count;
> +		u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
> +	} __packed;
> +} __packed;
> +
>  struct hv_vp_register_page {
>  	u16 version;
>  	u8 isvalid;
>  	u8 rsvdz;
>  	u32 dirty;
> +
> +#if IS_ENABLED(CONFIG_X86)
> +
>  	union {
>  		struct {
>  			/* General purpose registers
> @@ -95,6 +108,22 @@ struct hv_vp_register_page {
>  	union hv_x64_pending_interruption_register pending_interruption;
>  	union hv_x64_interrupt_state_register interrupt_state;
>  	u64 instruction_emulation_hints;
> +	u64 xfem;
> +
> +	/*
> +	 * Fields from this point are not included in the register page save chunk.
> +	 * The reserved field is intended to maintain alignment for unsaved fields.
> +	 */
> +	u8 reserved1[0x100];
> +
> +	/*
> +	 * Interrupts injected as part of HvCallDispatchVp.
> +	 */
> +	union hv_vp_register_page_interrupt_vectors interrupt_vectors;
> +
> +#elif IS_ENABLED(CONFIG_ARM64)
> +	/* Not yet supported in ARM */
> +#endif
>  } __packed;
> 
>  #define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
> @@ -299,10 +328,11 @@ union hv_partition_isolation_properties {
>  #define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED   0x2
> 
>  /* Note: Exo partition is enabled by default */
> -#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION                    BIT(8)
> -#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED                    BIT(13)
> -#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED   BIT(19)
> -#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE                   BIT(22)
> +#define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED		BIT(4)
> +#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION			BIT(8)
> +#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED			BIT(13)
> +#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED	BIT(19)
> +#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE			BIT(22)
> 
>  struct hv_input_create_partition {
>  	u64 flags;
> @@ -349,13 +379,23 @@ struct hv_input_set_partition_property {
>  enum hv_vp_state_page_type {
>  	HV_VP_STATE_PAGE_REGISTERS = 0,
>  	HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1,
> +	HV_VP_STATE_PAGE_GHCB,

Seems like this enum member should have an explicit value assigned
since it is part of the contract with the hypervisor.

>  	HV_VP_STATE_PAGE_COUNT
>  };
> 
>  struct hv_input_map_vp_state_page {
>  	u64 partition_id;
>  	u32 vp_index;
> -	u32 type; /* enum hv_vp_state_page_type */
> +	u16 type; /* enum hv_vp_state_page_type */
> +	union hv_input_vtl input_vtl;
> +	union {
> +		u8 as_uint8;
> +		struct {
> +			u8 map_location_provided : 1;
> +			u8 reserved : 7;
> +		};
> +	} flags;
> +	u64 requested_map_location;
>  } __packed;
> 
>  struct hv_output_map_vp_state_page {
> @@ -365,7 +405,14 @@ struct hv_output_map_vp_state_page {
>  struct hv_input_unmap_vp_state_page {
>  	u64 partition_id;
>  	u32 vp_index;
> -	u32 type; /* enum hv_vp_state_page_type */
> +	u16 type; /* enum hv_vp_state_page_type */
> +	union hv_input_vtl input_vtl;
> +	u8 reserved0;
> +} __packed;
> +
> +struct hv_x64_apic_eoi_message {
> +	__u32 vp_index;
> +	__u32 interrupt_vector;
>  } __packed;
> 
>  struct hv_opaque_intercept_message {
> @@ -515,6 +562,13 @@ struct hv_synthetic_timers_state {
>  	u64 reserved[5];
>  } __packed;
> 
> +struct hv_async_completion_message_payload {
> +	__u64 partition_id;
> +	__u32 status;
> +	__u32 completion_count;
> +	__u64 sub_status;
> +} __packed;
> +
>  union hv_input_delete_vp {
>  	u64 as_uint64[2];
>  	struct {
> @@ -649,6 +703,57 @@ struct hv_input_set_vp_state {
>  	union hv_input_set_vp_state_data data[];
>  } __packed;
> 
> +union hv_x64_vp_execution_state {
> +	__u16 as_uint16;
> +	struct {
> +		__u16 cpl:2;
> +		__u16 cr0_pe:1;
> +		__u16 cr0_am:1;
> +		__u16 efer_lma:1;
> +		__u16 debug_active:1;
> +		__u16 interruption_pending:1;
> +		__u16 vtl:4;
> +		__u16 enclave_mode:1;
> +		__u16 interrupt_shadow:1;
> +		__u16 virtualization_fault_active:1;
> +		__u16 reserved:2;
> +	} __packed;
> +};
> +
> +struct hv_x64_intercept_message_header {
> +	__u32 vp_index;
> +	__u8 instruction_length:4;
> +	__u8 cr8:4; /* Only set for exo partitions */
> +	__u8 intercept_access_type;
> +	union hv_x64_vp_execution_state execution_state;
> +	struct hv_x64_segment_register cs_segment;
> +	__u64 rip;
> +	__u64 rflags;
> +} __packed;
> +
> +union hv_x64_memory_access_info {
> +	__u8 as_uint8;
> +	struct {
> +		__u8 gva_valid:1;
> +		__u8 gva_gpa_valid:1;
> +		__u8 hypercall_output_pending:1;
> +		__u8 tlb_locked_no_overlay:1;
> +		__u8 reserved:4;
> +	} __packed;
> +};
> +
> +struct hv_x64_memory_intercept_message {
> +	struct hv_x64_intercept_message_header header;
> +	__u32 cache_type; /* enum hv_cache_type */
> +	__u8 instruction_byte_count;
> +	union hv_x64_memory_access_info memory_access_info;
> +	__u8 tpr_priority;
> +	__u8 reserved1;
> +	__u64 guest_virtual_address;
> +	__u64 guest_physical_address;
> +	__u8 instruction_bytes[16];
> +} __packed;
> +
>  /*
>   * Dispatch state for the VP communicated by the hypervisor to the
>   * VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
> @@ -716,6 +821,7 @@ static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message)
> ==
>  #define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH		0x8
>  #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH	0x10
>  #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH	0x20
> +#define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION	0x40
> 
>  struct hv_input_dispatch_vp {
>  	u64 partition_id;
> @@ -730,4 +836,18 @@ struct hv_output_dispatch_vp {
>  	u32 dispatch_event; /* enum hv_vp_dispatch_event */
>  } __packed;
> 
> +struct hv_input_modify_sparse_spa_page_host_access {
> +	u32 host_access : 2;
> +	u32 reserved : 30;
> +	u32 flags;
> +	u64 partition_id;
> +	u64 spa_page_list[];
> +} __packed;
> +
> +/* hv_input_modify_sparse_spa_page_host_access flags */
> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE  0x1
> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED     0x2
> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE      0x4
> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE       0x8
> +
>  #endif /* _HV_HVHDK_H */
> diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h
> index f8a39d3e9ce6..42e7876455b5 100644
> --- a/include/hyperv/hvhdk_mini.h
> +++ b/include/hyperv/hvhdk_mini.h
> @@ -36,6 +36,52 @@ enum hv_scheduler_type {
>  	HV_SCHEDULER_TYPE_MAX
>  };
> 
> +/* HV_STATS_AREA_TYPE */
> +enum hv_stats_area_type {
> +	HV_STATS_AREA_SELF = 0,
> +	HV_STATS_AREA_PARENT = 1,
> +	HV_STATS_AREA_INTERNAL = 2,
> +	HV_STATS_AREA_COUNT
> +};
> +
> +enum hv_stats_object_type {
> +	HV_STATS_OBJECT_HYPERVISOR		= 0x00000001,
> +	HV_STATS_OBJECT_LOGICAL_PROCESSOR	= 0x00000002,
> +	HV_STATS_OBJECT_PARTITION		= 0x00010001,
> +	HV_STATS_OBJECT_VP			= 0x00010002
> +};
> +
> +union hv_stats_object_identity {
> +	/* hv_stats_hypervisor */
> +	struct {
> +		u8 reserved[15];
> +		u8 stats_area_type;
> +	} __packed hv;
> +
> +	/* hv_stats_logical_processor */
> +	struct {
> +		u32 lp_index;
> +		u8 reserved[11];
> +		u8 stats_area_type;
> +	} __packed lp;
> +
> +	/* hv_stats_partition */
> +	struct {
> +		u64 partition_id;
> +		u8  reserved[7];
> +		u8  stats_area_type;
> +	} __packed partition;
> +
> +	/* hv_stats_vp */
> +	struct {
> +		u64 partition_id;
> +		u32 vp_index;
> +		u16 flags;
> +		u8  reserved;
> +		u8  stats_area_type;
> +	} __packed vp;
> +};
> +
>  enum hv_partition_property_code {
>  	/* Privilege properties */
>  	HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS			= 0x00010000,
> @@ -47,19 +93,45 @@ enum hv_partition_property_code {
> 
>  	/* Compatibility properties */
>  	HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES		=
> 0x00060002,
> +	HV_PARTITION_PROPERTY_XSAVE_STATES                      = 0x00060007,
>  	HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE		= 0x00060008,
>  	HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY		=
> 0x00060009,
>  };
> 
> +enum hv_snp_status {
> +	HV_SNP_STATUS_NONE = 0,
> +	HV_SNP_STATUS_AVAILABLE = 1,
> +	HV_SNP_STATUS_INCOMPATIBLE = 2,
> +	HV_SNP_STATUS_PSP_UNAVAILABLE = 3,
> +	HV_SNP_STATUS_PSP_INIT_FAILED = 4,
> +	HV_SNP_STATUS_PSP_BAD_FW_VERSION = 5,
> +	HV_SNP_STATUS_BAD_CONFIGURATION = 6,
> +	HV_SNP_STATUS_PSP_FW_UPDATE_IN_PROGRESS = 7,
> +	HV_SNP_STATUS_PSP_RB_INIT_FAILED = 8,
> +	HV_SNP_STATUS_PSP_PLATFORM_STATUS_FAILED = 9,
> +	HV_SNP_STATUS_PSP_INIT_LATE_FAILED = 10,
> +};
> +
>  enum hv_system_property {
>  	/* Add more values when needed */
>  	HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15,
> +	HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21,
> +};
> +
> +enum hv_dynamic_processor_feature_property {
> +	/* Add more values when needed */
> +	HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13,
> +	HV_X64_DYNAMIC_PROCESSOR_FEATURE_SNP_STATUS = 16,
>  };
> 
>  struct hv_input_get_system_property {
>  	u32 property_id; /* enum hv_system_property */
>  	union {
>  		u32 as_uint32;
> +#if IS_ENABLED(CONFIG_X86)
> +		/* enum hv_dynamic_processor_feature_property */
> +		u32 hv_processor_feature;
> +#endif
>  		/* More fields to be filled in when needed */
>  	};
>  } __packed;
> @@ -67,9 +139,28 @@ struct hv_input_get_system_property {
>  struct hv_output_get_system_property {
>  	union {
>  		u32 scheduler_type; /* enum hv_scheduler_type */
> +#if IS_ENABLED(CONFIG_X86)
> +		u64 hv_processor_feature_value;
> +#endif
>  	};
>  } __packed;
> 
> +struct hv_input_map_stats_page {
> +	u32 type; /* enum hv_stats_object_type */
> +	u32 padding;
> +	union hv_stats_object_identity identity;
> +} __packed;
> +
> +struct hv_output_map_stats_page {
> +	u64 map_location;
> +} __packed;
> +
> +struct hv_input_unmap_stats_page {
> +	u32 type; /* enum hv_stats_object_type */
> +	u32 padding;
> +	union hv_stats_object_identity identity;
> +} __packed;
> +
>  struct hv_proximity_domain_flags {
>  	u32 proximity_preferred : 1;
>  	u32 reserved : 30;
> --
> 2.34.1



From thierry.reding at gmail.com  Fri Mar  7 09:49:12 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri, 7 Mar 2025 18:49:12 +0100
Subject: [GIT PULL 5/5] arm64: tegra: Device tree changes for v6.15-rc1
In-Reply-To: <20250307162332.3451523-5-thierry.reding@gmail.com>
References: <20250307162332.3451523-1-thierry.reding@gmail.com>
 <20250307162332.3451523-5-thierry.reding@gmail.com>
Message-ID: <ei5lzgdpckb23la7xdsyyaeru32whrgyb6zdzzp6srawfi7obc@4mb35lgik26a>

On Fri, Mar 07, 2025 at 05:23:31PM +0100, Thierry Reding wrote:
> Hi ARM SoC maintainers,
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-arm64-dt
> 
> for you to fetch changes up to c33a71fd0e3644520af7b5926926c06597d6d355:
> 
>   arm64: tegra: p2180: Add TMP451 temperature sensor node (2025-03-06 20:35:53 +0100)
> 
> Thanks,
> Thierry
> 
> ----------------------------------------------------------------
> arm64: tegra: Device tree changes for v6.15-rc1
> 
> This contains some cleanup patches that remove unused properties and an
> unusable key that was erroneously exposed. A fix to support GPUs with a
> large amount of video memory on IGX Orin is also included.
> 
> Finally, some additional devices, such as a temperature sensor, are
> enabled on Jetson TX1, and the output voltage of some pins is adjusted.
> A fix for the VDD_LCD_1V8_DIS power supply is also included.
> 
> ----------------------------------------------------------------
> Diogo Ivo (4):
>       arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator
>       arm64: tegra: Define pinmuxing for gpio pads on Tegra210
>       arm64: tegra: p2597: Enable TCA9539 as IRQ controllers
>       arm64: tegra: p2180: Add TMP451 temperature sensor node
> 
> Jon Hunter (1):
>       arm64: tegra: Resize aperture for the IGX PCIe C5 slot
> 
> Ninad Malwade (1):
>       arm64: tegra: Remove the Orin NX/Nano suspend key
> 
> Rob Herring (Arm) (1):
>       arm64: tegra: Remove unused and undocumented "regulator-ramp-delay-scale" property

Sorry, I missed that you already pulled this into the ARM SoC tree. I've
dropped it from the Tegra tree and I've sent out an updated pull
request.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250307/84c9acc7/attachment.sig>

From thierry.reding at gmail.com  Fri Mar  7 09:49:37 2025
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri,  7 Mar 2025 18:49:37 +0100
Subject: [GIT PULL v2] arm64: tegra: Device tree changes for v6.15-rc1
Message-ID: <20250307174938.3456275-1-thierry.reding@gmail.com>

Hi ARM SoC maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-6.15-arm64-dt-v2

for you to fetch changes up to 65d691a4400e111e8bb2422a5f4f28de34298be7:

  arm64: tegra: p2180: Add TMP451 temperature sensor node (2025-03-07 18:38:29 +0100)

Thanks,
Thierry

----------------------------------------------------------------
arm64: tegra: Device tree changes for v6.15-rc1

This contains a patch to remove an unusable key that was erroneously
exposed as well as a fix to support GPUs with a large amount of video
memory on IGX Orin.

Finally, some additional devices, such as a temperature sensor, are
enabled on Jetson TX1, the output voltage of some pins is adjusted and
the VDD_LCD_1V8_DIS power supply now uses the correct enable GPIO.

----------------------------------------------------------------
Diogo Ivo (4):
      arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator
      arm64: tegra: Define pinmuxing for gpio pads on Tegra210
      arm64: tegra: p2597: Enable TCA9539 as IRQ controllers
      arm64: tegra: p2180: Add TMP451 temperature sensor node

Jon Hunter (1):
      arm64: tegra: Resize aperture for the IGX PCIe C5 slot

Ninad Malwade (1):
      arm64: tegra: Remove the Orin NX/Nano suspend key

 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi       | 13 +++++++++++++
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi       | 20 +++++++++++++++++++-
 arch/arm64/boot/dts/nvidia/tegra210.dtsi             | 10 ++++++++++
 .../dts/nvidia/tegra234-p3740-0002+p3701-0008.dts    | 10 ++++++++++
 .../boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi   |  7 -------
 5 files changed, 52 insertions(+), 8 deletions(-)


From m.felsch at pengutronix.de  Fri Mar  7 09:53:09 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Fri, 7 Mar 2025 18:53:09 +0100
Subject: [PATCH v4 1/3] ASoC: dt-bindings: support imx95's CM7 core
In-Reply-To: <88584d8f-e1cd-4b56-8906-461e1e6d9cc9@gmail.com>
References: <20250211225808.3050-1-laurentiumihalcea111@gmail.com>
 <20250211225808.3050-2-laurentiumihalcea111@gmail.com>
 <20250212093610.x4ixrackmn3u2xrf@pengutronix.de>
 <CAEnQRZBeQdnC+K92+Udb5awTmom10YHHNt7Ld-pYK4A1i8sr3Q@mail.gmail.com>
 <d66996eb-f49b-448b-9743-d19a3c3eba52@sirena.org.uk>
 <e45411df-1b8b-4f21-878d-d52e1112e62d@gmail.com>
 <20250213064724.kbmxsk5szpxwclj6@pengutronix.de>
 <88584d8f-e1cd-4b56-8906-461e1e6d9cc9@gmail.com>
Message-ID: <20250307175309.od3grjzr63dxp6ec@pengutronix.de>

On 25-03-04, Laurentiu Mihalcea wrote:
> On 2/13/2025 8:47 AM, Marco Felsch wrote:
> > Hi Laurentiu, Daniel,
> >
> > On 25-02-12, Laurentiu Mihalcea wrote:
> >> On 2/12/2025 2:38 PM, Mark Brown wrote:
> >>> On Wed, Feb 12, 2025 at 12:11:49PM +0200, Daniel Baluta wrote:
> >>>> On Wed, Feb 12, 2025 at 11:38?AM Marco Felsch <m.felsch at pengutronix.de> wrote:
> >>>>> On 25-02-11, Laurentiu Mihalcea wrote:
> >>>>>> +    const: fsl,imx95-cm7-sof
> >>>>> Albeit Krzysztof already add his Reviewed-by, can I ask why we need to
> >>>>> add the -sof suffix instead of -audio or so? SOF is a software project
> >>>>> but you can clearly run different software on the audio-copro as well.
> >>>> Sure you can run a different software project on the audio DSP but
> >>>> you will need a way to distinguish between the different projects.
> >>>> There might be different mailbox, memory configurations. So you will  need
> >>>> to invent another suffix specific to the new project.
> >>>> We can make  const: fsl,imx95-cm7-audio as the one used with SOF
> >>>> and think about a different name later for when another project will
> >>>> want to use the DSP.
> >>> I think the point here was that the DT should stay the same even if the
> >>> DSP firwmare changes, just as how changing the main OS shouldn't affect
> >>> the DT.
> >> It's rather unfortunate but based on the experience from the 8 series
> >> (imx8qm, imx8qxp, imx8mp), the programming model can differ quite
> >> a bit (e.g: remoteproc vs SOF) even if the core is the same (i.e: DSP core).
> >>
> >> The different programming models also required different DT configurations
> >> (e.g: dif. mboxes as Daniel mentioned, some extra properties (i.e: reg-names), etc...)
> >>
> >> The "-sof" suffix was chosen here instead of the more generic "-audio" (or whatever else
> >> alternative) because the DT configuration is specific to SOF's programming model. Other
> >> audio applications running on the same core may have dif. configurations (e.g: use
> >> DTCM/ITCM for memory instead of DDR, dif. mbox count, etc...). I suppose this kind of thing
> >> is bound to happen to some degree since the DT node doesn't just describe the CM7 core
> >> (but, rather, it also encompasses information on the memory, mboxes, etc. used)
> >> but perhaps I'm wrong?
> > Time will tell if there will be any other user except for SOF for the
> > DSP but and this is what I wanted to point out: the DTS should abstract
> > the HW. IMHO The CM7-Audio node should contain all properties required
> > to turn power and reset the core (e.g. clocks, reset, pm-domains). I get
> > your point regarding different configs but please have a look at
> > mt8183-kukui.dtsi. Here the rpmsg config is a subnode of the actual
> > system-control-proc. This makes much more sense to me since the HW part
> > is part of the generic core-node and all the software config goes into a
> > separate subnode.
> >
> > Regards,
> >   Marco
> 
> I understand your point but we're dealing with 2 different programming
> models here: SOF and remoteproc as opposed to just remoteproc as it's
> the case for Mediatek.

The idea is exactly to decouple the CM7 HW config from the
software/firmware running on it and this is what MediaTek did.

Of course they are only interested in teh RPMsg part but this approach
could be used to decouple the HW and the FW part which is your use-case
(different FWs running on the CM7).

> Going for a similar approach would also mean quite a bit of software
> changes as we'd need to factor out the common bits (most importantly here:
> core operations like start/stop) and placing them in a common driver. 

Exactly but shouldn't be to hard to implement. Of course it is more work
than just adapting the compatible.

> This is not trivial and I'm not sure it's worth the effort right now
> given that:
> 
> ??? 1) The current way we model the hardware inside the DT is not exactly inaccurate.
> ??? The core does physically use those memory regions, mailboxes, etc.
> 
> ??? 2) Whatever we do, the information in the DT will still depend on the programming model.
> ??? It's just that you're placing it in a child node, instead of the parent, which is arguably not that
> ??? big of an improvement?

The benefit is to have different configs in place and a board can choose
between them, e.g.:

	sof_cpu: cm7-cpu at 80000000 {
		compatible = "fsl,imx95-cm7";
		reg = <0x0 0x80000000 0x0 0x6100000>;
		reg-names = "sram";
		clocks = <...>;
		resets = <...>;
		access-controllers = <...>;

		firmware-name = "nxp/foo";
		firmware-config = <&cm7_sof>;

		cm7_sof: cm7-sof {
			compatible = "fsl,imx95-sof";
			memory-region = <&adma_res>;
			memory-region-names = "dma";
			mboxes = <&mu7 2 0>, <&mu7 2 1>, <&mu7 3 0>, <&mu7 3 1>;
			mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";

			cpu: port {
				cpu_ep: endpoint {
					remote-endpoint = <&codec_ep>;
				};
			};
		};

		cm7_rpmsg: cm7-rpmsg {
			compatible = "fsl,imx95-rpmsg";
		};

		cm7_foo: cm7-foo {
			compatible = "fsl,imx95-foo";
		};
	};

I get your point and I'm not against your patchset. Just IMHO the above
example would make more sense to me since the CM7 hardware handling
(en-/disable/access/reset/clock) can be done by a common driver and must
not be done by each subsystem driver: sof, rpmsg, etc. Also the since
the driver would be common it could be reused by other CoProcessors
within the system as well since there are now more and more CoProcessors
on a SoC.

Regards,
  Marco


From romank at linux.microsoft.com  Fri Mar  7 10:06:47 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 7 Mar 2025 10:06:47 -0800
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <Z8ncFkwzxi9qJFD3@liuwe-devbox-debian-v2>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <f332b77a-940f-4007-a44a-de64878d5201@linux.microsoft.com>
 <Z8ncFkwzxi9qJFD3@liuwe-devbox-debian-v2>
Message-ID: <efb43459-4136-43cd-adac-2179d9985e9d@linux.microsoft.com>



On 3/6/2025 9:32 AM, Wei Liu wrote:
> On Thu, Feb 27, 2025 at 10:50:30AM -0800, Roman Kisel wrote:

[...]

>> 2. Scheduling. Here, there is the mature KVM and Xen code to find
>>     inspiration in. Xen being the Type 1 hypervisor should likely be
>>     closer to MSHV in my understanding.
> 
> Yes and no.
> 
> When a hypervisor-based scheduler (either classic or core) is used, the
> scheduling model is the same as Xen. In this model, the hypervisor makes
> the scheduling decisions.
> 
> There is a second scheduler model. In that model, the hypervisor
> delegates scheduling to the Linux kernel. The Linux scheduler makes the
> scheduling decisions. It is similar to KVM.
> 
> We support both. Which model to use largely depends on the workload and
> the desired behaviors of the system.
> 
> This is purely informational in case people wonder why the run vp
> function branches off to two different code paths.
> 

Thanks, now I understand that better :)

[...]

>> -- 
>> Thank you,
>> Roman
>>

-- 
Thank you,
Roman



From andy.shevchenko at gmail.com  Fri Mar  7 10:06:30 2025
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Fri, 7 Mar 2025 20:06:30 +0200
Subject: [PATCH net-next v9 5/6] net: stmmac: configure SerDes according
 to the interface mode
In-Reply-To: <19b78790-d4d3-45db-9b1f-fbe40f8ed795@linux.intel.com>
References: <20250227121522.1802832-1-yong.liang.choong@linux.intel.com>
 <20250227121522.1802832-6-yong.liang.choong@linux.intel.com>
 <Z8lLm9Ze9VAx3cE_@surfacebook.localdomain> <601c88fb-8ec8-4866-a45d-f28dea6d9625@linux.intel.com>
 <CAHp75VeOKbAsvSuf5+VQnGFmUcN92TNnR2eF1+70h3PjaMdMqA@mail.gmail.com>
 <d7c0094e-7fd3-4113-8d00-91b7a83ffd1f@linux.intel.com> <257769403908de3ac6271059e1febee88654fbdc.camel@linux.intel.com>
 <19b78790-d4d3-45db-9b1f-fbe40f8ed795@linux.intel.com>
Message-ID: <CAHp75VcXtwe3zutnZUDNXBPe1qgwP+GbBF9KSFHOPioEvSk3Pw@mail.gmail.com>

On Fri, Mar 7, 2025 at 7:28?AM Choong Yong Liang
<yong.liang.choong at linux.intel.com> wrote:
> On 7/3/2025 4:52 am, David E. Box wrote:
> > On Thu, 2025-03-06 at 20:56 +0800, Choong Yong Liang wrote:
> >> On 6/3/2025 5:05 pm, Andy Shevchenko wrote:
> >>> On Thu, Mar 6, 2025 at 10:39?AM Choong Yong Liang
> >>> <yong.liang.choong at linux.intel.com> wrote:
> >>>> On 6/3/2025 3:15 pm, Andy Shevchenko wrote:
> >>>>> Thu, Feb 27, 2025 at 08:15:21PM +0800, Choong Yong Liang kirjoitti:

...

> >>>>>> config DWMAC_INTEL
> >>>>>>        default X86
> >>>>>>        depends on X86 && STMMAC_ETH && PCI
> >>>>>>        depends on COMMON_CLK
> >>>>>> +    depends on ACPI
> >>>>> Stray and unexplained change. Please, fix it. We don't need the
> >>>>> dependencies
> >>>>> which are not realised in the compile time.
> >>>> The dependency on ACPI is necessary because the intel_pmc_ipc.h header
> >>>> relies on ACPI functionality to interact with the Intel PMC.
> >>> So, that header has to be fixed as ACPI here is really unneeded
> >>> dependency for the cases when somebody (for whatever reasons) want to
> >>> build a kernel without ACPI support but with the driver enabled for
> >>> let's say PCI device.

> >> Thank you for your feedback, Andy.
> >> I appreciate your insights regarding the ACPI dependency.
> >> The intel_pmc_ipc.h header is under the ownership of David E Box, who
> >> focuses on the platform code, while my focus is on the netdev.
> >>
> >> if you could kindly look into making the ACPI dependency optional in the
> >> intel_pmc_ipc.h header, it would be greatly appreciated.
> >> I am more than willing to provide any support necessary to ensure a smooth
> >> resolution.
> >
> > Choong you only need put the function under a #if CONFIG_ACPI block and provide
> > an alternative that returns an error when the code is not build. Like this,
> >
> > #if CONFIG_ACPI
> > static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
> > *rbuf)
> > {
> >     ...
> > }
> > #else
> > static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
> > *rbuf) { return -ENODEV; }
> > #endif
> >
> >> This patch series has already been accepted, but we recognize the
> >> importance of addressing this issue in the next patch series for upstream.
> >> Our goal is to ensure that the driver can be compiled and function
> >> correctly in both ACPI and non-ACPI environments.
> >>
> >> Thank you both for your understanding and collaboration.

> The current ACPI dependency for the config DWMAC_INTEL is necessary,

I can argue on this. The driver worked without problems on the cases I
explained, so the dependency introduced very recently and only for a
subset of the cases. What you probably wanted to say is that "the
dependency is needed to avoid compilation errors in CONFIG_ACPI=n
cases since the used API doesn't (yet) provide the necessary stubs".
With that being assumed I agree.

> but I
> agree on making it optional.
>
> Implementing the suggestion from David using the "#if CONFIG_ACPI" approach
> would address your concern about users who need to build a kernel without
> ACPI support.
>
> If you are okay with this approach, then I will submit the solution for
> upstream.

Yes, please do it as the ACPI dependency brings a few hundreds of
kilobytes into the kernel with a lot of possible unneeded stuff.

-- 
With Best Regards,
Andy Shevchenko


From helgaas at kernel.org  Fri Mar  7 10:10:32 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri, 7 Mar 2025 12:10:32 -0600
Subject: [PATCH] PCI: controller: Restore PCI_REASSIGN_ALL_BUS when
 PCI_PROBE_ONLY is enabled
In-Reply-To: <20250117082428.129353-1-Bo.Sun.CN@windriver.com>
Message-ID: <20250307181032.GA416164@bhelgaas>

On Fri, Jan 17, 2025 at 04:24:14PM +0800, Bo Sun wrote:
> On our Marvell OCTEON CN96XX board, we observed the following panic on
> the latest kernel:
> Unable to handle kernel NULL pointer dereference at virtual address 0000000000000080
> Mem abort info:
>   ESR = 0x0000000096000005
>   EC = 0x25: DABT (current EL), IL = 32 bits
>   SET = 0, FnV = 0
>   EA = 0, S1PTW = 0
>   FSC = 0x05: level 1 translation fault
> Data abort info:
>   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
>   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [0000000000000080] user address but active_mm is swapper
> Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 9 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.13.0-rc7-00149-g9bffa1ad25b8 #1
> Hardware name: Marvell OcteonTX CN96XX board (DT)
> pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : of_pci_add_properties+0x278/0x4c8
> lr : of_pci_add_properties+0x258/0x4c8
> sp : ffff8000822ef9b0
> x29: ffff8000822ef9b0 x28: ffff000106dd8000 x27: ffff800081bc3b30
> x26: ffff800081540118 x25: ffff8000813d2be0 x24: 0000000000000000
> x23: ffff00010528a800 x22: ffff000107c50000 x21: ffff0001039c2630
> x20: ffff0001039c2630 x19: 0000000000000000 x18: ffffffffffffffff
> x17: 00000000a49c1b85 x16: 0000000084c07b58 x15: ffff000103a10f98
> x14: ffffffffffffffff x13: ffff000103a10f96 x12: 0000000000000003
> x11: 0101010101010101 x10: 000000000000002c x9 : ffff800080ca7acc
> x8 : ffff0001038fd900 x7 : 0000000000000000 x6 : 0000000000696370
> x5 : 0000000000000000 x4 : 0000000000000002 x3 : ffff8000822efa40
> x2 : ffff800081341000 x1 : ffff000107c50000 x0 : 0000000000000000
> Call trace:
>  of_pci_add_properties+0x278/0x4c8 (P)
>  of_pci_make_dev_node+0xe0/0x158
>  pci_bus_add_device+0x158/0x210
>  pci_bus_add_devices+0x40/0x98
>  pci_host_probe+0x94/0x118
>  pci_host_common_probe+0x120/0x1a0
>  platform_probe+0x70/0xf0
>  really_probe+0xb4/0x2a8
>  __driver_probe_device+0x80/0x140
>  driver_probe_device+0x48/0x170
>  __driver_attach+0x9c/0x1b0
>  bus_for_each_dev+0x7c/0xe8
>  driver_attach+0x2c/0x40
>  bus_add_driver+0xec/0x218
>  driver_register+0x68/0x138
>  __platform_driver_register+0x2c/0x40
>  gen_pci_driver_init+0x24/0x38
>  do_one_initcall+0x4c/0x278
>  kernel_init_freeable+0x1f4/0x3d0
>  kernel_init+0x28/0x1f0
>  ret_from_fork+0x10/0x20
> Code: aa1603e1 f0005522 d2800044 91000042 (f94040a0)
> 
> This regression was introduced by commit 7246a4520b4b ("PCI: Use
> preserve_config in place of pci_flags"). On our board, the 002:00:07.0
> bridge is misconfigured by the bootloader. Both its secondary and
> subordinate bus numbers are initialized to 0, while its fixed secondary
> bus number is set to 8. However, bus number 8 is also assigned to another
> bridge (0002:00:0f.0). Although this is a bootloader issue, before the
> change in commit 7246a4520b4b, the PCI_REASSIGN_ALL_BUS flag was
> set by default when PCI_PROBE_ONLY was enabled, ensuing that all the
> bus number for these bridges were reassigned, avoiding any conflicts.
> 
> After the change introduced in commit 7246a4520b4b, the bus numbers
> assigned by the bootloader are reused by all other bridges, except
> the misconfigured 002:00:07.0 bridge. The kernel attempt to reconfigure
> 002:00:07.0 by reusing the fixed secondary bus number 8 assigned by
> bootloader. However, since a pci_bus has already been allocated for
> bus 8 due to the probe of 0002:00:0f.0, no new pci_bus allocated for
> 002:00:07.0. This results in a pci bridge device without a pci_bus
> attached (pdev->subordinate == NULL). Consequently, accessing
> pdev->subordinate in of_pci_prop_bus_range() leads to a NULL pointer
> dereference.
> 
> To summarize, we need to restore the PCI_REASSIGN_ALL_BUS flag when
> PCI_PROBE_ONLY is enabled in order to work around issue like the one
> described above.

When you send v2,

  - Thanks for including the panic info above, but I think you can
    remove most of it while preserving the essential details.  E.g., I
    think the "NULL pointer dereference", kernel version, pc, and a
    couple call trace entries would be enough.

  - "002:00:07.0" is not a valid address (in dmesg log, domain would
    be 4 hex digits).  Perhaps quote relevant dmesg lines directly,
    showing the secondary bus info for these bridges.

  - I think it's a little sketchy that of_pci_add_properties() and
    of_pci_prop_bus_range() assume a valid secondary bus, even if this
    patch avoids that situation in this case.  There are always
    potential cases where we don't have bus numbers to assign for a
    secondary bus.  I think we should check, maybe by omitting
    'bus-range' if there is no secondary bus.

  - This might lead to two patches: (1) to fix the regression that we
    used to set PCI_REASSIGN_ALL_BUS but 7246a4520b4b broke that, and
    (2) avoid the of_pci_prop_bus_range() NULL pointer dereference in
    all cases.

> Cc: stable at vger.kernel.org
> Fixes: 7246a4520b4b ("PCI: Use preserve_config in place of pci_flags")
> Signed-off-by: Bo Sun <Bo.Sun.CN at windriver.com>
> ---
>  drivers/pci/controller/pci-host-common.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
> index cf5f59a745b3..615923acbc3e 100644
> --- a/drivers/pci/controller/pci-host-common.c
> +++ b/drivers/pci/controller/pci-host-common.c
> @@ -73,6 +73,10 @@ int pci_host_common_probe(struct platform_device *pdev)
>  	if (IS_ERR(cfg))
>  		return PTR_ERR(cfg);
>  
> +	/* Do not reassign resources if probe only */
> +	if (!pci_has_flag(PCI_PROBE_ONLY))
> +		pci_add_flags(PCI_REASSIGN_ALL_BUS);
> +
>  	bridge->sysdata = cfg;
>  	bridge->ops = (struct pci_ops *)&ops->pci_ops;
>  	bridge->msi_domain = true;
> -- 
> 2.48.1
> 


From lkp at intel.com  Fri Mar  7 09:31:24 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:31:24 +0800
Subject: [soc:soc/defconfig] BUILD SUCCESS
 da3c926ca8482b5c7fab6f017a7a3dbe9df86385
Message-ID: <202503080118.wa8GozRi-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/defconfig
branch HEAD: da3c926ca8482b5c7fab6f017a7a3dbe9df86385  Merge tag 'renesas-arm-defconfig-for-v6.15-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/defconfig

elapsed time: 1450m

configs tested: 4
configs skipped: 119

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
arm  randconfig-001-20250307    clang-21
arm  randconfig-002-20250307    gcc-14.2.0
arm  randconfig-003-20250307    clang-19
arm  randconfig-004-20250307    clang-21

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Fri Mar  7 09:31:03 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:31:03 +0800
Subject: [soc:mediatek/drivers] BUILD SUCCESS
 1e12efbee8f3fe09d23ad75d2e38a6335ca2d159
Message-ID: <202503080157.vg9WxpEw-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git mediatek/drivers
branch HEAD: 1e12efbee8f3fe09d23ad75d2e38a6335ca2d159  soc: mediatek: mtk-socinfo: Add extra entry for MT8395AV/ZA Genio 1200

elapsed time: 1820m

configs tested: 86
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
arc                               allnoconfig    gcc-13.2.0
arc                   randconfig-001-20250307    gcc-13.2.0
arc                   randconfig-002-20250307    gcc-13.2.0
arm                               allnoconfig    clang-17
arm                            dove_defconfig    gcc-14.2.0
arm                   randconfig-001-20250307    clang-21
arm                   randconfig-002-20250307    gcc-14.2.0
arm                   randconfig-003-20250307    clang-19
arm                   randconfig-004-20250307    clang-21
arm                         s5pv210_defconfig    gcc-14.2.0
arm64                             allnoconfig    gcc-14.2.0
arm64                 randconfig-001-20250307    gcc-14.2.0
arm64                 randconfig-002-20250307    clang-15
arm64                 randconfig-003-20250307    gcc-14.2.0
arm64                 randconfig-004-20250307    clang-15
csky                              allnoconfig    gcc-14.2.0
csky                  randconfig-001-20250307    gcc-14.2.0
csky                  randconfig-002-20250307    gcc-14.2.0
hexagon                           allnoconfig    clang-21
hexagon               randconfig-001-20250307    clang-21
hexagon               randconfig-002-20250307    clang-21
i386        buildonly-randconfig-001-20250307    clang-19
i386        buildonly-randconfig-002-20250307    clang-19
i386        buildonly-randconfig-003-20250307    gcc-11
i386        buildonly-randconfig-004-20250307    clang-19
i386        buildonly-randconfig-005-20250307    gcc-12
i386        buildonly-randconfig-006-20250307    clang-19
loongarch                         allnoconfig    gcc-14.2.0
loongarch             randconfig-001-20250307    gcc-14.2.0
loongarch             randconfig-002-20250307    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
mips                         bigsur_defconfig    gcc-14.2.0
mips                           xway_defconfig    clang-21
nios2                         3c120_defconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250307    gcc-14.2.0
nios2                 randconfig-002-20250307    gcc-14.2.0
openrisc                          allnoconfig    gcc-14.2.0
openrisc                            defconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                              defconfig    gcc-14.2.0
parisc                randconfig-001-20250307    gcc-14.2.0
parisc                randconfig-002-20250307    gcc-14.2.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc               randconfig-001-20250307    gcc-14.2.0
powerpc               randconfig-002-20250307    clang-21
powerpc               randconfig-003-20250307    clang-19
powerpc64             randconfig-001-20250307    clang-21
powerpc64             randconfig-002-20250307    gcc-14.2.0
powerpc64             randconfig-003-20250307    gcc-14.2.0
riscv                             allnoconfig    gcc-14.2.0
riscv                 randconfig-001-20250307    gcc-14.2.0
riscv                 randconfig-002-20250307    clang-19
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250307    gcc-14.2.0
s390                  randconfig-002-20250307    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250307    gcc-14.2.0
sh                    randconfig-002-20250307    gcc-14.2.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250307    gcc-14.2.0
sparc                 randconfig-002-20250307    gcc-14.2.0
sparc64               randconfig-001-20250307    gcc-14.2.0
sparc64               randconfig-002-20250307    gcc-14.2.0
um                                allnoconfig    clang-18
um                    randconfig-001-20250307    clang-17
um                    randconfig-002-20250307    clang-21
x86_64                            allnoconfig    clang-19
x86_64      buildonly-randconfig-001-20250307    clang-19
x86_64      buildonly-randconfig-002-20250307    gcc-12
x86_64      buildonly-randconfig-003-20250307    clang-19
x86_64      buildonly-randconfig-004-20250307    clang-19
x86_64      buildonly-randconfig-005-20250307    clang-19
x86_64      buildonly-randconfig-006-20250307    gcc-12
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250307    gcc-14.2.0
xtensa                randconfig-002-20250307    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From irogers at google.com  Fri Mar  7 09:32:14 2025
From: irogers at google.com (Ian Rogers)
Date: Fri, 7 Mar 2025 09:32:14 -0800
Subject: [PATCH 1/1 next] perf libunwind: Fixup conversion
 perf_sample->user_regs to a pointer
In-Reply-To: <20250307153448.250871-1-acme@kernel.org>
References: <20250307153448.250871-1-acme@kernel.org>
Message-ID: <CAP-5=fUHozmMFVCX1Sn+4gsSkXQicLqYWHLrN2DSJgAGdnd0gA@mail.gmail.com>

On Fri, Mar 7, 2025 at 7:35?AM Arnaldo Carvalho de Melo <acme at kernel.org> wrote:
>
> From: Arnaldo Carvalho de Melo <acme at redhat.com>
>
> The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
> the changes to a file, resulting in this problem:
>
>   $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
>   <SNIP>
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
>   <SNIP>
>   util/unwind-libunwind-local.c: In function ?access_mem?:
>   util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
>     582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
>         |                                                        ^
>         |                                                        ->
>   util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
>     587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
>         |                                      ^~~~~~~~~~~~~~~~~~~~~~
>         |                                      |
>         |                                      struct regs_dump **
> <SNIP>
>   ? [acme at toolbox perf-tools-next]$ git bisect bad
>   dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
>   commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
>   Author: Ian Rogers <irogers at google.com>
>   Date:   Mon Jan 13 11:43:45 2025 -0800
>
>       perf sample: Make user_regs and intr_regs optional
>
> Detected using:
>
>   make -C tools/perf build-test
>
> Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
> Cc: Adrian Hunter <adrian.hunter at intel.com>
> Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
> Cc: Andi Kleen <ak at linux.intel.com>
> Cc: Charlie Jenkins <charlie at rivosinc.com>
> Cc: Ian Rogers <irogers at google.com>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: James Clark <james.clark at linaro.org>
> Cc: John Garry <john.g.garry at oracle.com>
> Cc: Kan Liang <kan.liang at linux.intel.com>
> Cc: Leo Yan <leo.yan at linux.dev>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Michael Petlan <mpetlan at redhat.com>
> Cc: Namhyung Kim <namhyung at kernel.org>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Tavian Barnes <tavianator at tavianator.com>
> Cc: Veronika Molnarova <vmolnaro at redhat.com>
> Cc: coresight at lists.linaro.org
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>

Sorry for the breakage, thanks for fixing this!

Reviewed-by: Ian Rogers <irogers at google.com>

Thanks,
Ian

> ---
>  tools/perf/util/unwind-libunwind-local.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
> index 16c2b03831f39afc..cc0e41f2c2f2ef10 100644
> --- a/tools/perf/util/unwind-libunwind-local.c
> +++ b/tools/perf/util/unwind-libunwind-local.c
> @@ -579,12 +579,12 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
>         int ret;
>
>         /* Don't support write, probably not needed. */
> -       if (__write || !stack || !ui->sample->user_regs.regs) {
> +       if (__write || !stack || !ui->sample->user_regs->regs) {
>                 *valp = 0;
>                 return 0;
>         }
>
> -       ret = perf_reg_value(&start, &ui->sample->user_regs,
> +       ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample),
>                              perf_arch_reg_sp(arch));
>         if (ret)
>                 return ret;
> @@ -628,7 +628,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>                 return 0;
>         }
>
> -       if (!ui->sample->user_regs.regs) {
> +       if (!ui->sample->user_regs->regs) {
>                 *valp = 0;
>                 return 0;
>         }
> @@ -637,7 +637,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>         if (id < 0)
>                 return -EINVAL;
>
> -       ret = perf_reg_value(&val, &ui->sample->user_regs, id);
> +       ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id);
>         if (ret) {
>                 if (!ui->best_effort)
>                         pr_err("unwind: can't read reg %d\n", regnum);
> @@ -741,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
>         unw_cursor_t c;
>         int ret, i = 0;
>
> -       ret = perf_reg_value(&val, &ui->sample->user_regs,
> +       ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample),
>                              perf_arch_reg_ip(arch));
>         if (ret)
>                 return ret;
> @@ -808,7 +808,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
>                 .best_effort  = best_effort
>         };
>
> -       if (!data->user_regs.regs)
> +       if (!data->user_regs->regs)
>                 return -EINVAL;
>
>         if (max_stack <= 0)
> --
> 2.47.0
>


From lkp at intel.com  Fri Mar  7 09:31:59 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:31:59 +0800
Subject: [soc:soc/arm] BUILD SUCCESS
 f03f6e276bdd332a53118ed51b325c3367814267
Message-ID: <202503080154.xbfEQg8H-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/arm
branch HEAD: f03f6e276bdd332a53118ed51b325c3367814267  Merge tag 'renesas-arm-soc-for-v6.15-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/arm

elapsed time: 1450m

configs tested: 4
configs skipped: 119

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
arm  randconfig-001-20250307    clang-21
arm  randconfig-002-20250307    gcc-14.2.0
arm  randconfig-003-20250307    clang-19
arm  randconfig-004-20250307    clang-21

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Fri Mar  7 09:33:56 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:33:56 +0800
Subject: [soc:soc/dt] BUILD SUCCESS
 c4991aabc1f90359970c17db38342adf2678a181
Message-ID: <202503080150.dE6lt6Jz-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/dt
branch HEAD: c4991aabc1f90359970c17db38342adf2678a181  Merge tag 'mtk-dts64-for-v6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux into soc/dt

elapsed time: 1452m

configs tested: 88
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
arc                               allnoconfig    gcc-13.2.0
arc                   randconfig-001-20250307    gcc-13.2.0
arc                   randconfig-002-20250307    gcc-13.2.0
arm                               allnoconfig    clang-17
arm                           imxrt_defconfig    clang-19
arm                   randconfig-001-20250307    clang-21
arm                   randconfig-002-20250307    gcc-14.2.0
arm                   randconfig-003-20250307    clang-19
arm                   randconfig-004-20250307    clang-21
arm64                             allnoconfig    gcc-14.2.0
arm64                 randconfig-001-20250307    gcc-14.2.0
arm64                 randconfig-002-20250307    clang-15
arm64                 randconfig-003-20250307    gcc-14.2.0
arm64                 randconfig-004-20250307    clang-15
csky                              allnoconfig    gcc-14.2.0
csky                  randconfig-001-20250307    gcc-14.2.0
csky                  randconfig-002-20250307    gcc-14.2.0
hexagon                           allnoconfig    clang-21
hexagon               randconfig-001-20250307    clang-21
hexagon               randconfig-002-20250307    clang-21
i386        buildonly-randconfig-001-20250307    clang-19
i386        buildonly-randconfig-002-20250307    clang-19
i386        buildonly-randconfig-003-20250307    gcc-11
i386        buildonly-randconfig-004-20250307    clang-19
i386        buildonly-randconfig-005-20250307    gcc-12
i386        buildonly-randconfig-006-20250307    clang-19
loongarch                         allnoconfig    gcc-14.2.0
loongarch             randconfig-001-20250307    gcc-14.2.0
loongarch             randconfig-002-20250307    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                        m5307c3_defconfig    gcc-14.2.0
m68k                        mvme16x_defconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250307    gcc-14.2.0
nios2                 randconfig-002-20250307    gcc-14.2.0
openrisc                          allnoconfig    gcc-14.2.0
openrisc                            defconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                randconfig-001-20250307    gcc-14.2.0
parisc                randconfig-002-20250307    gcc-14.2.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc                      arches_defconfig    gcc-14.2.0
powerpc                        fsp2_defconfig    gcc-14.2.0
powerpc               randconfig-001-20250307    gcc-14.2.0
powerpc               randconfig-002-20250307    clang-21
powerpc               randconfig-003-20250307    clang-19
powerpc64             randconfig-001-20250307    clang-21
powerpc64             randconfig-002-20250307    gcc-14.2.0
powerpc64             randconfig-003-20250307    gcc-14.2.0
riscv                             allnoconfig    gcc-14.2.0
riscv                 randconfig-001-20250307    gcc-14.2.0
riscv                 randconfig-002-20250307    clang-19
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250307    gcc-14.2.0
s390                  randconfig-002-20250307    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                               j2_defconfig    gcc-14.2.0
sh                          polaris_defconfig    gcc-14.2.0
sh                    randconfig-001-20250307    gcc-14.2.0
sh                    randconfig-002-20250307    gcc-14.2.0
sh                           se7705_defconfig    gcc-14.2.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250307    gcc-14.2.0
sparc                 randconfig-002-20250307    gcc-14.2.0
sparc64               randconfig-001-20250307    gcc-14.2.0
sparc64               randconfig-002-20250307    gcc-14.2.0
um                                allnoconfig    clang-18
um                    randconfig-001-20250307    clang-17
um                    randconfig-002-20250307    clang-21
x86_64                            allnoconfig    clang-19
x86_64      buildonly-randconfig-001-20250307    clang-19
x86_64      buildonly-randconfig-002-20250307    gcc-12
x86_64      buildonly-randconfig-003-20250307    clang-19
x86_64      buildonly-randconfig-004-20250307    clang-19
x86_64      buildonly-randconfig-005-20250307    clang-19
x86_64      buildonly-randconfig-006-20250307    gcc-12
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250307    gcc-14.2.0
xtensa                randconfig-002-20250307    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Fri Mar  7 09:34:07 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:34:07 +0800
Subject: [soc:soc/drivers] BUILD SUCCESS
 7d5a549a08de5b0f9914fb76f6b06d99d331daed
Message-ID: <202503080101.rj7PBvUH-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
branch HEAD: 7d5a549a08de5b0f9914fb76f6b06d99d331daed  Merge tag 'mtk-soc-for-v6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux into soc/drivers

elapsed time: 1452m

configs tested: 65
configs skipped: 0

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                            allnoconfig    gcc-14.2.0
arc                              allnoconfig    gcc-13.2.0
arc                  randconfig-001-20250307    gcc-13.2.0
arc                  randconfig-002-20250307    gcc-13.2.0
arm                              allnoconfig    clang-17
arm                  randconfig-001-20250307    clang-21
arm                  randconfig-002-20250307    gcc-14.2.0
arm                  randconfig-003-20250307    clang-19
arm                  randconfig-004-20250307    clang-21
arm64                            allnoconfig    gcc-14.2.0
arm64                randconfig-001-20250307    gcc-14.2.0
arm64                randconfig-002-20250307    clang-15
arm64                randconfig-003-20250307    gcc-14.2.0
arm64                randconfig-004-20250307    clang-15
csky                             allnoconfig    gcc-14.2.0
csky                 randconfig-001-20250307    gcc-14.2.0
csky                 randconfig-002-20250307    gcc-14.2.0
hexagon              randconfig-001-20250307    clang-21
hexagon              randconfig-002-20250307    clang-21
i386       buildonly-randconfig-001-20250307    clang-19
i386       buildonly-randconfig-002-20250307    clang-19
i386       buildonly-randconfig-003-20250307    gcc-11
i386       buildonly-randconfig-004-20250307    clang-19
i386       buildonly-randconfig-005-20250307    gcc-12
i386       buildonly-randconfig-006-20250307    clang-19
loongarch            randconfig-001-20250307    gcc-14.2.0
loongarch            randconfig-002-20250307    gcc-14.2.0
m68k                      m5208evb_defconfig    gcc-14.2.0
nios2                randconfig-001-20250307    gcc-14.2.0
nios2                randconfig-002-20250307    gcc-14.2.0
parisc               randconfig-001-20250307    gcc-14.2.0
parisc               randconfig-002-20250307    gcc-14.2.0
powerpc              randconfig-001-20250307    gcc-14.2.0
powerpc              randconfig-002-20250307    clang-21
powerpc              randconfig-003-20250307    clang-19
powerpc64            randconfig-001-20250307    clang-21
powerpc64            randconfig-002-20250307    gcc-14.2.0
powerpc64            randconfig-003-20250307    gcc-14.2.0
riscv                randconfig-001-20250307    gcc-14.2.0
riscv                randconfig-002-20250307    clang-19
s390                            allmodconfig    clang-19
s390                            allyesconfig    gcc-14.2.0
s390                 randconfig-001-20250307    gcc-14.2.0
s390                 randconfig-002-20250307    gcc-14.2.0
sh                              allmodconfig    gcc-14.2.0
sh                              allyesconfig    gcc-14.2.0
sh                   randconfig-001-20250307    gcc-14.2.0
sh                   randconfig-002-20250307    gcc-14.2.0
sparc                           allmodconfig    gcc-14.2.0
sparc                randconfig-001-20250307    gcc-14.2.0
sparc                randconfig-002-20250307    gcc-14.2.0
sparc64              randconfig-001-20250307    gcc-14.2.0
sparc64              randconfig-002-20250307    gcc-14.2.0
um                   randconfig-001-20250307    clang-17
um                   randconfig-002-20250307    clang-21
x86_64                           allnoconfig    clang-19
x86_64     buildonly-randconfig-001-20250307    clang-19
x86_64     buildonly-randconfig-002-20250307    gcc-12
x86_64     buildonly-randconfig-003-20250307    clang-19
x86_64     buildonly-randconfig-004-20250307    clang-19
x86_64     buildonly-randconfig-005-20250307    clang-19
x86_64     buildonly-randconfig-006-20250307    gcc-12
x86_64                             defconfig    gcc-11
xtensa               randconfig-001-20250307    gcc-14.2.0
xtensa               randconfig-002-20250307    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From maxime.chevallier at bootlin.com  Fri Mar  7 09:35:57 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:35:57 +0100
Subject: [PATCH net-next v5 00/13] net: phy: Rework linkmodes handling in a dedicated file
Message-ID: <20250307173611.129125-1-maxime.chevallier@bootlin.com>

Hello everyone,

This is V5 of the phy_caps series. In a nutshell, this series reworks the way
we maintain the list of speed/duplex capablities for each linkmode so that we
no longer have multiple definition of these associations.

That will help making sure that when people add new linkmodes in
include/uapi/linux/ethtool.h, they don't have to update phylib and phylink as
well, making the process more straightforward and less error-prone.

It also generalises the phy_caps interface to be able to lookup linkmodes
from phy_interface_t, which is needed for the multi-port work I've been working
on for a while.

This V5 addresse Russell's and Paolo's reviews, namely :

 - Error out when encountering an unknown SPEED_XXX setting

   It prints an error and fails to initialize phylib. I've tested by
   introducing a dummy 1.6T speed, I guess it's only a matter of time
   before that actually happens :)

 - Deal more gracefully with the fixed-link settings, keeping some level of
   compatibility with what we had before by making sure we report a
   single BaseT mode like before.

V1 : https://lore.kernel.org/netdev/20250222142727.894124-1-maxime.chevallier at bootlin.com/
V2 : https://lore.kernel.org/netdev/20250226100929.1646454-1-maxime.chevallier at bootlin.com/
V3 : https://lore.kernel.org/netdev/20250228145540.2209551-1-maxime.chevallier at bootlin.com/
V4 : https://lore.kernel.org/netdev/20250303090321.805785-1-maxime.chevallier at bootlin.com/

Maxime Chevallier (13):
  net: ethtool: Export the link_mode_params definitions
  net: phy: Use an internal, searchable storage for the linkmodes
  net: phy: phy_caps: Move phy_speeds to phy_caps
  net: phy: phy_caps: Move __set_linkmode_max_speed to phy_caps
  net: phy: phy_caps: Introduce phy_caps_valid
  net: phy: phy_caps: Implement link_capabilities lookup by linkmode
  net: phy: phy_caps: Allow looking-up link caps based on speed and
    duplex
  net: phy: phy_device: Use link_capabilities lookup for PHY aneg config
  net: phylink: Use phy_caps_lookup for fixed-link configuration
  net: phy: drop phy_settings and the associated lookup helpers
  net: phylink: Add a mapping between MAC_CAPS and LINK_CAPS
  net: phylink: Convert capabilities to linkmodes using phy_caps
  net: phylink: Use phy_caps to get an interface's capabilities and
    modes

 drivers/net/phy/Makefile     |   2 +-
 drivers/net/phy/phy-caps.h   |  63 ++++++
 drivers/net/phy/phy-core.c   | 253 ++----------------------
 drivers/net/phy/phy.c        |  37 +---
 drivers/net/phy/phy_caps.c   | 359 +++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c |  16 +-
 drivers/net/phy/phylink.c    | 355 ++++++++++------------------------
 include/linux/ethtool.h      |   8 +
 include/linux/phy.h          |  15 --
 net/ethtool/common.c         |   1 +
 net/ethtool/common.h         |   7 -
 11 files changed, 571 insertions(+), 545 deletions(-)
 create mode 100644 drivers/net/phy/phy-caps.h
 create mode 100644 drivers/net/phy/phy_caps.c

-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:35:58 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:35:58 +0100
Subject: [PATCH net-next v5 01/13] net: ethtool: Export the link_mode_params definitions
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-2-maxime.chevallier@bootlin.com>

link_mode_params contains a lookup table of all 802.3 link modes that
are currently supported with structured data about each mode's speed,
duplex, number of lanes and mediums.

As a preparation for a port representation, export that table for the
rest of the net stack to use.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 include/linux/ethtool.h | 8 ++++++++
 net/ethtool/common.c    | 1 +
 net/ethtool/common.h    | 7 -------
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 7f222dccc7d1..8210ece94fa6 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -210,6 +210,14 @@ static inline u8 *ethtool_rxfh_context_key(struct ethtool_rxfh_context *ctx)
 
 void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id);
 
+struct link_mode_info {
+	int                             speed;
+	u8                              lanes;
+	u8                              duplex;
+};
+
+extern const struct link_mode_info link_mode_params[];
+
 /* declare a link mode bitmap */
 #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name)		\
 	DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS)
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index ac8b6107863e..c9d6302e88c9 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -423,6 +423,7 @@ const struct link_mode_info link_mode_params[] = {
 	__DEFINE_LINK_MODE_PARAMS(800000, VR4, Full),
 };
 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS);
+EXPORT_SYMBOL_GPL(link_mode_params);
 
 const char netif_msg_class_names[][ETH_GSTRING_LEN] = {
 	[NETIF_MSG_DRV_BIT]		= "drv",
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index a1088c2441d0..b4683d286a5a 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -15,12 +15,6 @@
 #define __SOF_TIMESTAMPING_CNT (const_ilog2(SOF_TIMESTAMPING_LAST) + 1)
 #define __HWTSTAMP_FLAG_CNT (const_ilog2(HWTSTAMP_FLAG_LAST) + 1)
 
-struct link_mode_info {
-	int				speed;
-	u8				lanes;
-	u8				duplex;
-};
-
 struct genl_info;
 struct hwtstamp_provider_desc;
 
@@ -33,7 +27,6 @@ tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
 extern const char
 phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
 extern const char link_mode_names[][ETH_GSTRING_LEN];
-extern const struct link_mode_info link_mode_params[];
 extern const char netif_msg_class_names[][ETH_GSTRING_LEN];
 extern const char wol_mode_names[][ETH_GSTRING_LEN];
 extern const char sof_timestamping_names[][ETH_GSTRING_LEN];
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:35:59 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:35:59 +0100
Subject: [PATCH net-next v5 02/13] net: phy: Use an internal, searchable storage for the linkmodes
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-3-maxime.chevallier@bootlin.com>

The canonical definition for all the link modes is in linux/ethtool.h,
which is complemented by the link_mode_params array stored in
net/ethtool/common.h . That array contains all the metadata about each
of these modes, including the Speed and Duplex information.

Phylib and phylink needs that information as well for internal
management of the link, which was done by duplicating that information
in locally-stored arrays and lookup functions. This makes it easy for
developpers adding new modes to forget modifying phylib and phylink
accordingly.

However, the link_mode_params array in net/ethtool/common.c is fairly
inefficient to search through, as it isn't sorted in any manner. Phylib
and phylink perform a lot of lookup operations, mostly to filter modes
by speed and/or duplex.

We therefore introduce the link_caps private array in phy_caps.c, that
indexes linkmodes in a more efficient manner. Each element associated a
tuple <speed, duplex> to a bitfield of all the linkmodes runs at these
speed/duplex.

We end-up with an array that's fairly short, easily addressable and that
it optimised for the typical use-cases of phylib/phylink.

That array is initialized at the same time as phylib. As the
link_mode_params array is part of the net stack, which phylink depends
on, it should always be accessible from phylib.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V5: Fail on unknown speed

 drivers/net/phy/Makefile     |  2 +-
 drivers/net/phy/phy-caps.h   | 43 +++++++++++++++++
 drivers/net/phy/phy_caps.c   | 90 ++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c |  5 ++
 4 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/phy/phy-caps.h
 create mode 100644 drivers/net/phy/phy_caps.c

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 8f9ba5e8290d..23ce205ae91d 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -3,7 +3,7 @@
 
 libphy-y			:= phy.o phy-c45.o phy-core.o phy_device.o \
 				   linkmode.o phy_link_topology.o \
-				   phy_package.o
+				   phy_package.o phy_caps.o
 mdio-bus-y			+= mdio_bus.o mdio_device.o
 
 ifdef CONFIG_MDIO_DEVICE
diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
new file mode 100644
index 000000000000..6024f1d11a93
--- /dev/null
+++ b/drivers/net/phy/phy-caps.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * link caps internal header, for link modes <-> capabilities <-> interfaces
+ * conversions.
+ */
+
+#ifndef __PHY_CAPS_H
+#define __PHY_CAPS_H
+
+#include <linux/ethtool.h>
+
+enum {
+	LINK_CAPA_10HD = 0,
+	LINK_CAPA_10FD,
+	LINK_CAPA_100HD,
+	LINK_CAPA_100FD,
+	LINK_CAPA_1000HD,
+	LINK_CAPA_1000FD,
+	LINK_CAPA_2500FD,
+	LINK_CAPA_5000FD,
+	LINK_CAPA_10000FD,
+	LINK_CAPA_20000FD,
+	LINK_CAPA_25000FD,
+	LINK_CAPA_40000FD,
+	LINK_CAPA_50000FD,
+	LINK_CAPA_56000FD,
+	LINK_CAPA_100000FD,
+	LINK_CAPA_200000FD,
+	LINK_CAPA_400000FD,
+	LINK_CAPA_800000FD,
+
+	__LINK_CAPA_MAX,
+};
+
+struct link_capabilities {
+	int speed;
+	unsigned int duplex;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(linkmodes);
+};
+
+int phy_caps_init(void);
+
+#endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
new file mode 100644
index 000000000000..6cb18e216d97
--- /dev/null
+++ b/drivers/net/phy/phy_caps.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/ethtool.h>
+#include <linux/linkmode.h>
+#include <linux/phy.h>
+
+#include "phy-caps.h"
+
+static struct link_capabilities link_caps[__LINK_CAPA_MAX] __ro_after_init = {
+	{ SPEED_10, DUPLEX_HALF, {0} }, /* LINK_CAPA_10HD */
+	{ SPEED_10, DUPLEX_FULL, {0} }, /* LINK_CAPA_10FD */
+	{ SPEED_100, DUPLEX_HALF, {0} }, /* LINK_CAPA_100HD */
+	{ SPEED_100, DUPLEX_FULL, {0} }, /* LINK_CAPA_100FD */
+	{ SPEED_1000, DUPLEX_HALF, {0} }, /* LINK_CAPA_1000HD */
+	{ SPEED_1000, DUPLEX_FULL, {0} }, /* LINK_CAPA_1000FD */
+	{ SPEED_2500, DUPLEX_FULL, {0} }, /* LINK_CAPA_2500FD */
+	{ SPEED_5000, DUPLEX_FULL, {0} }, /* LINK_CAPA_5000FD */
+	{ SPEED_10000, DUPLEX_FULL, {0} }, /* LINK_CAPA_10000FD */
+	{ SPEED_20000, DUPLEX_FULL, {0} }, /* LINK_CAPA_20000FD */
+	{ SPEED_25000, DUPLEX_FULL, {0} }, /* LINK_CAPA_25000FD */
+	{ SPEED_40000, DUPLEX_FULL, {0} }, /* LINK_CAPA_40000FD */
+	{ SPEED_50000, DUPLEX_FULL, {0} }, /* LINK_CAPA_50000FD */
+	{ SPEED_56000, DUPLEX_FULL, {0} }, /* LINK_CAPA_56000FD */
+	{ SPEED_100000, DUPLEX_FULL, {0} }, /* LINK_CAPA_100000FD */
+	{ SPEED_200000, DUPLEX_FULL, {0} }, /* LINK_CAPA_200000FD */
+	{ SPEED_400000, DUPLEX_FULL, {0} }, /* LINK_CAPA_400000FD */
+	{ SPEED_800000, DUPLEX_FULL, {0} }, /* LINK_CAPA_800000FD */
+};
+
+static int speed_duplex_to_capa(int speed, unsigned int duplex)
+{
+	if (duplex == DUPLEX_UNKNOWN ||
+	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
+		return -EINVAL;
+
+	switch (speed) {
+	case SPEED_10: return duplex == DUPLEX_FULL ?
+			      LINK_CAPA_10FD : LINK_CAPA_10HD;
+	case SPEED_100: return duplex == DUPLEX_FULL ?
+			       LINK_CAPA_100FD : LINK_CAPA_100HD;
+	case SPEED_1000: return duplex == DUPLEX_FULL ?
+				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
+	case SPEED_2500: return LINK_CAPA_2500FD;
+	case SPEED_5000: return LINK_CAPA_5000FD;
+	case SPEED_10000: return LINK_CAPA_10000FD;
+	case SPEED_20000: return LINK_CAPA_20000FD;
+	case SPEED_25000: return LINK_CAPA_25000FD;
+	case SPEED_40000: return LINK_CAPA_40000FD;
+	case SPEED_50000: return LINK_CAPA_50000FD;
+	case SPEED_56000: return LINK_CAPA_56000FD;
+	case SPEED_100000: return LINK_CAPA_100000FD;
+	case SPEED_200000: return LINK_CAPA_200000FD;
+	case SPEED_400000: return LINK_CAPA_400000FD;
+	case SPEED_800000: return LINK_CAPA_800000FD;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
+ *
+ * Returns: 0 if phy caps init was successful, -EINVAL if we found an
+ *	    unexpected linkmode setting that requires LINK_CAPS update.
+ *
+ */
+int phy_caps_init(void)
+{
+	const struct link_mode_info *linkmode;
+	int i, capa;
+
+	/* Fill the caps array from net/ethtool/common.c */
+	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
+		linkmode = &link_mode_params[i];
+		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
+
+		if (capa < 0) {
+			if (linkmode->speed != SPEED_UNKNOWN) {
+				pr_err("Unknown speed %d, please update LINK_CAPS\n",
+				       linkmode->speed);
+				return -EINVAL;
+			}
+			continue;
+		}
+
+		__set_bit(i, link_caps[capa].linkmodes);
+	}
+
+	return 0;
+}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b2d32fbc8c85..4980862398d0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -42,6 +42,7 @@
 #include <linux/unistd.h>
 
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 MODULE_DESCRIPTION("PHY library");
 MODULE_AUTHOR("Andy Fleming");
@@ -3558,6 +3559,10 @@ static int __init phy_init(void)
 	if (rc)
 		goto err_ethtool_phy_ops;
 
+	rc = phy_caps_init();
+	if (rc)
+		goto err_mdio_bus;
+
 	features_init();
 
 	rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:00 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:00 +0100
Subject: [PATCH net-next v5 03/13] net: phy: phy_caps: Move phy_speeds to phy_caps
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-4-maxime.chevallier@bootlin.com>

Use the newly introduced link_capabilities array to derive the list of
possible speeds when given a combination of linkmodes. As
link_capabilities is indexed by speed, we don't have to iterate the
whole phy_settings array.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |  3 +++
 drivers/net/phy/phy-core.c | 15 ---------------
 drivers/net/phy/phy.c      |  3 ++-
 drivers/net/phy/phy_caps.c | 33 +++++++++++++++++++++++++++++++++
 include/linux/phy.h        |  2 --
 5 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 6024f1d11a93..5a5f4ee3006b 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -40,4 +40,7 @@ struct link_capabilities {
 
 int phy_caps_init(void);
 
+size_t phy_caps_speeds(unsigned int *speeds, size_t size,
+		       unsigned long *linkmodes);
+
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 154d29be6293..542e9284d207 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -340,21 +340,6 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
 }
 EXPORT_SYMBOL_GPL(phy_lookup_setting);
 
-size_t phy_speeds(unsigned int *speeds, size_t size,
-		  unsigned long *mask)
-{
-	size_t count;
-	int i;
-
-	for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
-		if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
-		    test_bit(settings[i].bit, mask) &&
-		    (count == 0 || speeds[count - 1] != settings[i].speed))
-			speeds[count++] = settings[i].speed;
-
-	return count;
-}
-
 static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
 {
 	const struct phy_setting *p;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 16ffc00b419c..3128df03feda 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -37,6 +37,7 @@
 #include <net/sock.h>
 
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 #define PHY_STATE_TIME	HZ
 
@@ -245,7 +246,7 @@ unsigned int phy_supported_speeds(struct phy_device *phy,
 				  unsigned int *speeds,
 				  unsigned int size)
 {
-	return phy_speeds(speeds, size, phy->supported);
+	return phy_caps_speeds(speeds, size, phy->supported);
 }
 
 /**
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 6cb18e216d97..8ce91257160f 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -57,6 +57,9 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex)
 	return -EINVAL;
 }
 
+#define for_each_link_caps_asc_speed(cap) \
+	for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
+
 /**
  * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
  *
@@ -88,3 +91,33 @@ int phy_caps_init(void)
 
 	return 0;
 }
+
+/**
+ * phy_caps_speeds() - Fill an array of supported SPEED_* values for given modes
+ * @speeds: Output array to store the speeds list into
+ * @size: Size of the output array
+ * @linkmodes: Linkmodes to get the speeds from
+ *
+ * Fills the speeds array with all possible speeds that can be achieved with
+ * the specified linkmodes.
+ *
+ * Returns: The number of speeds filled into the array. If the input array isn't
+ *	    big enough to store all speeds, fill it as much as possible.
+ */
+size_t phy_caps_speeds(unsigned int *speeds, size_t size,
+		       unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+	size_t count = 0;
+
+	for_each_link_caps_asc_speed(lcap) {
+		if (linkmode_intersects(lcap->linkmodes, linkmodes) &&
+		    (count == 0 || speeds[count - 1] != lcap->speed)) {
+			speeds[count++] = lcap->speed;
+			if (count >= size)
+				break;
+		}
+	}
+
+	return count;
+}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c4a6385faf41..99c195fa3695 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1287,8 +1287,6 @@ struct phy_setting {
 const struct phy_setting *
 phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 		   bool exact);
-size_t phy_speeds(unsigned int *speeds, size_t size,
-		  unsigned long *mask);
 
 /**
  * phy_is_started - Convenience function to check whether PHY is started
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:01 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:01 +0100
Subject: [PATCH net-next v5 04/13] net: phy: phy_caps: Move __set_linkmode_max_speed to phy_caps
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-5-maxime.chevallier@bootlin.com>

Convert the __set_linkmode_max_speed to use the link_capabilities array.
This makes it easy to clamp the linkmodes to a given max speed.
Introduce a new helper phy_caps_linkmode_max_speed to replace the
previous one that used phy_settings.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |  2 ++
 drivers/net/phy/phy-core.c | 18 +++---------------
 drivers/net/phy/phy_caps.c | 19 +++++++++++++++++++
 3 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 5a5f4ee3006b..1bef9cca62c5 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -42,5 +42,7 @@ int phy_caps_init(void);
 
 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
+void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
+
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 542e9284d207..af2463e67cea 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -8,6 +8,7 @@
 
 #include "phylib.h"
 #include "phylib-internal.h"
+#include "phy-caps.h"
 
 /**
  * phy_speed_to_str - Return a string representing the PHY link speed
@@ -340,22 +341,9 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
 }
 EXPORT_SYMBOL_GPL(phy_lookup_setting);
 
-static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
-{
-	const struct phy_setting *p;
-	int i;
-
-	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
-		if (p->speed > max_speed)
-			linkmode_clear_bit(p->bit, addr);
-		else
-			break;
-	}
-}
-
 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
-	__set_linkmode_max_speed(max_speed, phydev->supported);
+	phy_caps_linkmode_max_speed(max_speed, phydev->supported);
 }
 
 /**
@@ -558,7 +546,7 @@ int phy_speed_down_core(struct phy_device *phydev)
 	if (min_common_speed == SPEED_UNKNOWN)
 		return -EINVAL;
 
-	__set_linkmode_max_speed(min_common_speed, phydev->advertising);
+	phy_caps_linkmode_max_speed(min_common_speed, phydev->advertising);
 
 	return 0;
 }
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 8ce91257160f..d43493884ff7 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -60,6 +60,9 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex)
 #define for_each_link_caps_asc_speed(cap) \
 	for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
 
+#define for_each_link_caps_desc_speed(cap) \
+	for (cap = &link_caps[__LINK_CAPA_MAX - 1]; cap >= link_caps; cap--)
+
 /**
  * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
  *
@@ -121,3 +124,19 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 
 	return count;
 }
+
+/**
+ * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
+ * @max_speed: Speed limit for the linkmode set
+ * @linkmodes: Linkmodes to limit
+ */
+void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_desc_speed(lcap)
+		if (lcap->speed > max_speed)
+			linkmode_andnot(linkmodes, linkmodes, lcap->linkmodes);
+		else
+			break;
+}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:02 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:02 +0100
Subject: [PATCH net-next v5 05/13] net: phy: phy_caps: Introduce phy_caps_valid
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-6-maxime.chevallier@bootlin.com>

With the link_capabilities array, it's trivial to validate a given mask
againts a <speed, duplex> tuple. Create a helper for that purpose, and
use it to replace a phy_settings lookup in phy_check_valid();

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |  1 +
 drivers/net/phy/phy.c      |  2 +-
 drivers/net/phy/phy_caps.c | 19 +++++++++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 1bef9cca62c5..1217686f1f91 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -43,6 +43,7 @@ int phy_caps_init(void);
 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
+bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3128df03feda..8df37d221fba 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -260,7 +260,7 @@ unsigned int phy_supported_speeds(struct phy_device *phy,
  */
 bool phy_check_valid(int speed, int duplex, unsigned long *features)
 {
-	return !!phy_lookup_setting(speed, duplex, features, true);
+	return phy_caps_valid(speed, duplex, features);
 }
 EXPORT_SYMBOL(phy_check_valid);
 
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index d43493884ff7..4ee8c25c8521 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -140,3 +140,22 @@ void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
 		else
 			break;
 }
+
+/**
+ * phy_caps_valid() - Validate a linkmodes set agains given speed and duplex
+ * @speed: input speed to validate
+ * @duplex: input duplex to validate. Passing DUPLEX_UNKNOWN is always not valid
+ * @linkmodes: The linkmodes to validate
+ *
+ * Returns: True if at least one of the linkmodes in @linkmodes can function at
+ *          the given speed and duplex, false otherwise.
+ */
+bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
+{
+	int capa = speed_duplex_to_capa(speed, duplex);
+
+	if (capa < 0)
+		return false;
+
+	return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
+}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:03 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:03 +0100
Subject: [PATCH net-next v5 06/13] net: phy: phy_caps: Implement link_capabilities lookup by linkmode
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-7-maxime.chevallier@bootlin.com>

In several occasions, phylib needs to lookup a set of matching speed and
duplex against a given linkmode set. Instead of relying on the
phy_settings array and thus iterate over the whole linkmodes list, use
the link_capabilities array to lookup these matches, as we aren't
interested in the actual link setting that matches but rather the speed
and duplex for that setting.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |  5 +++++
 drivers/net/phy/phy-core.c | 36 +++++++++++++-----------------
 drivers/net/phy/phy_caps.c | 45 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 1217686f1f91..8833798f141f 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -45,5 +45,10 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
+
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only);
 
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index af2463e67cea..bfba03f208fd 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -469,16 +469,15 @@ EXPORT_SYMBOL_GPL(phy_resolve_aneg_pause);
 void phy_resolve_aneg_linkmode(struct phy_device *phydev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i;
+	const struct link_capabilities *c;
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	for (i = 0; i < ARRAY_SIZE(settings); i++)
-		if (test_bit(settings[i].bit, common)) {
-			phydev->speed = settings[i].speed;
-			phydev->duplex = settings[i].duplex;
-			break;
-		}
+	c = phy_caps_lookup_by_linkmode(common);
+	if (c) {
+		phydev->speed = c->speed;
+		phydev->duplex = c->duplex;
+	}
 
 	phy_resolve_aneg_pause(phydev);
 }
@@ -496,7 +495,8 @@ EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
 void phy_check_downshift(struct phy_device *phydev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i, speed = SPEED_UNKNOWN;
+	const struct link_capabilities *c;
+	int speed = SPEED_UNKNOWN;
 
 	phydev->downshifted_rate = 0;
 
@@ -506,11 +506,9 @@ void phy_check_downshift(struct phy_device *phydev)
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	for (i = 0; i < ARRAY_SIZE(settings); i++)
-		if (test_bit(settings[i].bit, common)) {
-			speed = settings[i].speed;
-			break;
-		}
+	c = phy_caps_lookup_by_linkmode(common);
+	if (c)
+		speed = c->speed;
 
 	if (speed == SPEED_UNKNOWN || phydev->speed >= speed)
 		return;
@@ -524,17 +522,13 @@ void phy_check_downshift(struct phy_device *phydev)
 static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
-	int i = ARRAY_SIZE(settings);
+	const struct link_capabilities *c;
 
 	linkmode_and(common, phydev->lp_advertising, phydev->advertising);
 
-	while (--i >= 0) {
-		if (test_bit(settings[i].bit, common)) {
-			if (fdx_only && settings[i].duplex != DUPLEX_FULL)
-				continue;
-			return settings[i].speed;
-		}
-	}
+	c = phy_caps_lookup_by_linkmode_rev(common, fdx_only);
+	if (c)
+		return c->speed;
 
 	return SPEED_UNKNOWN;
 }
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 4ee8c25c8521..c39f38c12ef2 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -125,6 +125,51 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 	return count;
 }
 
+/**
+ * phy_caps_lookup_by_linkmode() - Lookup the fastest matching link_capabilities
+ * @linkmodes: Linkmodes to match against
+ *
+ * Returns: The highest-speed link_capabilities that intersects the given
+ *	    linkmodes. In case several DUPLEX_ options exist at that speed,
+ *	    DUPLEX_FULL is matched first. NULL is returned if no match.
+ */
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode(const unsigned long *linkmodes)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_desc_speed(lcap)
+		if (linkmode_intersects(lcap->linkmodes, linkmodes))
+			return lcap;
+
+	return NULL;
+}
+
+/**
+ * phy_caps_lookup_by_linkmode_rev() - Lookup the slowest matching link_capabilities
+ * @linkmodes: Linkmodes to match against
+ * @fdx_only: Full duplex match only when set
+ *
+ * Returns: The lowest-speed link_capabilities that intersects the given
+ *	    linkmodes. When set, fdx_only will ignore half-duplex matches.
+ *	    NULL is returned if no match.
+ */
+const struct link_capabilities *
+phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
+{
+	struct link_capabilities *lcap;
+
+	for_each_link_caps_asc_speed(lcap) {
+		if (fdx_only && lcap->duplex != DUPLEX_FULL)
+			continue;
+
+		if (linkmode_intersects(lcap->linkmodes, linkmodes))
+			return lcap;
+	}
+
+	return NULL;
+}
+
 /**
  * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
  * @max_speed: Speed limit for the linkmode set
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:04 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:04 +0100
Subject: [PATCH net-next v5 07/13] net: phy: phy_caps: Allow looking-up link caps based on speed and duplex
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-8-maxime.chevallier@bootlin.com>

As the link_caps array is efficient for <speed,duplex> lookups,
implement a function for speed/duplex lookups that matches a given
mask. This replicates to some extent the phy_lookup_settings()
behaviour, matching full link_capabilities instead of a single linkmode.

phy.c's phy_santize_settings() and phylink's
phylink_ethtool_ksettings_set() performs such lookup using the
phy_settings table, but are only interested in the actual speed/duplex
that were matched, rathet than the individual linkmode.

Similar to phy_lookup_settings(), the newly introduced phy_caps_lookup()
will run through the link_caps[] array by descending speed/duplex order.

If the link_capabilities for a given <speed/duplex> tuple intersects the
passed linkmodes, we consider that a match.

Similar to phy_lookup_settings(), we also allow passing an 'exact'
boolean, allowing non-exact match. Here, we MUST always match the
linkmodes mask, but we allow matching on lower speed settings.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |  4 ++++
 drivers/net/phy/phy.c      | 32 ++++++--------------------
 drivers/net/phy/phy_caps.c | 47 ++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phylink.c  | 17 +++++++-------
 4 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 8833798f141f..aef4b54a8429 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -51,4 +51,8 @@ phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only);
 
+const struct link_capabilities *
+phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
+		bool exact);
+
 #endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8df37d221fba..562acde89224 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -213,25 +213,6 @@ int phy_aneg_done(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_aneg_done);
 
-/**
- * phy_find_valid - find a PHY setting that matches the requested parameters
- * @speed: desired speed
- * @duplex: desired duplex
- * @supported: mask of supported link modes
- *
- * Locate a supported phy setting that is, in priority order:
- * - an exact match for the specified speed and duplex mode
- * - a match for the specified speed, or slower speed
- * - the slowest supported speed
- * Returns the matched phy_setting entry, or %NULL if no supported phy
- * settings were found.
- */
-static const struct phy_setting *
-phy_find_valid(int speed, int duplex, unsigned long *supported)
-{
-	return phy_lookup_setting(speed, duplex, supported, false);
-}
-
 /**
  * phy_supported_speeds - return all speeds currently supported by a phy device
  * @phy: The phy device to return supported speeds of.
@@ -274,13 +255,14 @@ EXPORT_SYMBOL(phy_check_valid);
  */
 static void phy_sanitize_settings(struct phy_device *phydev)
 {
-	const struct phy_setting *setting;
+	const struct link_capabilities *c;
+
+	c = phy_caps_lookup(phydev->speed, phydev->duplex, phydev->supported,
+			    false);
 
-	setting = phy_find_valid(phydev->speed, phydev->duplex,
-				 phydev->supported);
-	if (setting) {
-		phydev->speed = setting->speed;
-		phydev->duplex = setting->duplex;
+	if (c) {
+		phydev->speed = c->speed;
+		phydev->duplex = c->duplex;
 	} else {
 		/* We failed to find anything (no supported speeds?) */
 		phydev->speed = SPEED_UNKNOWN;
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index c39f38c12ef2..0366feee2912 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -170,6 +170,53 @@ phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
 	return NULL;
 }
 
+/**
+ * phy_caps_lookup() - Lookup capabilities by speed/duplex that matches a mask
+ * @speed: Speed to match
+ * @duplex: Duplex to match
+ * @supported: Mask of linkmodes to match
+ * @exact: Perform an exact match or not.
+ *
+ * Lookup a link_capabilities entry that intersect the supported linkmodes mask,
+ * and that matches the passed speed and duplex.
+ *
+ * When @exact is set, an exact match is performed on speed and duplex, meaning
+ * that if the linkmodes for the given speed and duplex intersect the supported
+ * mask, this capability is returned, otherwise we don't have a match and return
+ * NULL.
+ *
+ * When @exact is not set, we return either an exact match, or matching capabilities
+ * at lower speed, or the lowest matching speed, or NULL.
+ *
+ * Returns: a matched link_capabilities according to the above process, NULL
+ *	    otherwise.
+ */
+const struct link_capabilities *
+phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
+		bool exact)
+{
+	const struct link_capabilities *lcap, *last = NULL;
+
+	for_each_link_caps_desc_speed(lcap) {
+		if (linkmode_intersects(lcap->linkmodes, supported)) {
+			last = lcap;
+			/* exact match on speed and duplex*/
+			if (lcap->speed == speed && lcap->duplex == duplex) {
+				return lcap;
+			} else if (!exact) {
+				if (lcap->speed <= speed)
+					return lcap;
+			}
+		}
+	}
+
+	if (!exact)
+		return last;
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(phy_caps_lookup);
+
 /**
  * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
  * @max_speed: Speed limit for the linkmode set
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a3f64b6d2d34..cf9f019382ad 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
+#include "phy-caps.h"
 #include "sfp.h"
 #include "swphy.h"
 
@@ -2852,8 +2853,8 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 				  const struct ethtool_link_ksettings *kset)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
+	const struct link_capabilities *c;
 	struct phylink_link_state config;
-	const struct phy_setting *s;
 
 	ASSERT_RTNL();
 
@@ -2896,23 +2897,23 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 		/* Autonegotiation disabled, select a suitable speed and
 		 * duplex.
 		 */
-		s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
-				       pl->supported, false);
-		if (!s)
+		c = phy_caps_lookup(kset->base.speed, kset->base.duplex,
+				    pl->supported, false);
+		if (!c)
 			return -EINVAL;
 
 		/* If we have a fixed link, refuse to change link parameters.
 		 * If the link parameters match, accept them but do nothing.
 		 */
 		if (pl->req_link_an_mode == MLO_AN_FIXED) {
-			if (s->speed != pl->link_config.speed ||
-			    s->duplex != pl->link_config.duplex)
+			if (c->speed != pl->link_config.speed ||
+			    c->duplex != pl->link_config.duplex)
 				return -EINVAL;
 			return 0;
 		}
 
-		config.speed = s->speed;
-		config.duplex = s->duplex;
+		config.speed = c->speed;
+		config.duplex = c->duplex;
 		break;
 
 	case AUTONEG_ENABLE:
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:05 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:05 +0100
Subject: [PATCH net-next v5 08/13] net: phy: phy_device: Use link_capabilities lookup for PHY aneg config
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-9-maxime.chevallier@bootlin.com>

When configuring PHY advertising with autoneg disabled, we lookd for an
exact linkmode to advertise and configure for the requested Speed and
Duplex, specially at or over 1G.

Using phy_caps_lookup allows us to build a list of the supported
linkmodes at that speed that we can advertise instead of the first mode
that matches.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy_device.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 4980862398d0..3f734e847e8e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2120,7 +2120,7 @@ EXPORT_SYMBOL(genphy_check_and_restart_aneg);
 int __genphy_config_aneg(struct phy_device *phydev, bool changed)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(fixed_advert);
-	const struct phy_setting *set;
+	const struct link_capabilities *c;
 	unsigned long *advert;
 	int err;
 
@@ -2146,10 +2146,11 @@ int __genphy_config_aneg(struct phy_device *phydev, bool changed)
 	} else {
 		linkmode_zero(fixed_advert);
 
-		set = phy_lookup_setting(phydev->speed, phydev->duplex,
-					 phydev->supported, true);
-		if (set)
-			linkmode_set_bit(set->bit, fixed_advert);
+		c = phy_caps_lookup(phydev->speed, phydev->duplex,
+				    phydev->supported, true);
+		if (c)
+			linkmode_and(fixed_advert, phydev->supported,
+				     c->linkmodes);
 
 		advert = fixed_advert;
 	}
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:06 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:06 +0100
Subject: [PATCH net-next v5 09/13] net: phylink: Use phy_caps_lookup for fixed-link configuration
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-10-maxime.chevallier@bootlin.com>

When phylink creates a fixed-link configuration, it finds a matching
linkmode to set as the advertised, lp_advertising and supported modes
based on the speed and duplex of the fixed link.

Use the newly introduced phy_caps_lookup to get these modes instead of
phy_lookup_settings(). This has the side effect that the matched
settings and configured linkmodes may now contain several linkmodes (the
intersection of supported linkmodes from the phylink settings and the
linkmodes that match speed/duplex) instead of the one from
phy_lookup_settings().

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phylink.c | 44 +++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index cf9f019382ad..8e2b7d647a92 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -802,12 +802,26 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
 	return phylink_validate_mac_and_pcs(pl, supported, state);
 }
 
+static void phylink_fill_fixedlink_supported(unsigned long *supported)
+{
+	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, supported);
+}
+
 static int phylink_parse_fixedlink(struct phylink *pl,
 				   const struct fwnode_handle *fwnode)
 {
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(match) = { 0, };
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+	const struct link_capabilities *c;
 	struct fwnode_handle *fixed_node;
-	const struct phy_setting *s;
 	struct gpio_desc *desc;
 	u32 speed;
 	int ret;
@@ -875,12 +889,16 @@ static int phylink_parse_fixedlink(struct phylink *pl,
 		phylink_warn(pl, "fixed link specifies half duplex for %dMbps link?\n",
 			     pl->link_config.speed);
 
-	linkmode_fill(pl->supported);
+	linkmode_zero(pl->supported);
+	phylink_fill_fixedlink_supported(pl->supported);
+
 	linkmode_copy(pl->link_config.advertising, pl->supported);
 	phylink_validate(pl, pl->supported, &pl->link_config);
 
-	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
-			       pl->supported, true);
+	c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex,
+			    pl->supported, true);
+	if (c)
+		linkmode_and(match, pl->supported, c->linkmodes);
 
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask);
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask);
@@ -889,9 +907,10 @@ static int phylink_parse_fixedlink(struct phylink *pl,
 
 	phylink_set(pl->supported, MII);
 
-	if (s) {
-		__set_bit(s->bit, pl->supported);
-		__set_bit(s->bit, pl->link_config.lp_advertising);
+	if (c) {
+		linkmode_or(pl->supported, pl->supported, match);
+		linkmode_or(pl->link_config.lp_advertising,
+			    pl->link_config.lp_advertising, match);
 	} else {
 		phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n",
 			     pl->link_config.duplex == DUPLEX_FULL ? "full" : "half",
@@ -1879,21 +1898,20 @@ static int phylink_register_sfp(struct phylink *pl,
 int phylink_set_fixed_link(struct phylink *pl,
 			   const struct phylink_link_state *state)
 {
-	const struct phy_setting *s;
+	const struct link_capabilities *c;
 	unsigned long *adv;
 
 	if (pl->cfg_link_an_mode != MLO_AN_PHY || !state ||
 	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
 		return -EINVAL;
 
-	s = phy_lookup_setting(state->speed, state->duplex,
-			       pl->supported, true);
-	if (!s)
+	c = phy_caps_lookup(state->speed, state->duplex,
+			    pl->supported, true);
+	if (!c)
 		return -EINVAL;
 
 	adv = pl->link_config.advertising;
-	linkmode_zero(adv);
-	linkmode_set_bit(s->bit, adv);
+	linkmode_and(adv, pl->supported, c->linkmodes);
 	linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv);
 
 	pl->link_config.speed = state->speed;
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:07 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:07 +0100
Subject: [PATCH net-next v5 10/13] net: phy: drop phy_settings and the associated lookup helpers
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-11-maxime.chevallier@bootlin.com>

The phy_settings array is no longer relevant as it has now been replaced
by the link_caps array and associated phy_caps helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-core.c | 184 -------------------------------------
 include/linux/phy.h        |  13 ---
 2 files changed, 197 deletions(-)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index bfba03f208fd..c064c49f971c 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -157,190 +157,6 @@ int phy_interface_num_ports(phy_interface_t interface)
 }
 EXPORT_SYMBOL_GPL(phy_interface_num_ports);
 
-/* A mapping of all SUPPORTED settings to speed/duplex.  This table
- * must be grouped by speed and sorted in descending match priority
- * - iow, descending speed.
- */
-
-#define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \
-			       .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}
-
-static const struct phy_setting settings[] = {
-	/* 800G */
-	PHY_SETTING( 800000, FULL, 800000baseCR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseKR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR8_2_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseSR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseVR8_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseCR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseKR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseDR4_2_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseSR4_Full		),
-	PHY_SETTING( 800000, FULL, 800000baseVR4_Full		),
-	/* 400G */
-	PHY_SETTING( 400000, FULL, 400000baseCR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full	),
-	PHY_SETTING( 400000, FULL, 400000baseDR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR8_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseCR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseLR4_ER4_FR4_Full	),
-	PHY_SETTING( 400000, FULL, 400000baseDR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR4_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseCR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseKR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseDR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseDR2_2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseSR2_Full		),
-	PHY_SETTING( 400000, FULL, 400000baseVR2_Full		),
-	/* 200G */
-	PHY_SETTING( 200000, FULL, 200000baseCR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full	),
-	PHY_SETTING( 200000, FULL, 200000baseDR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR4_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseCR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseLR2_ER2_FR2_Full	),
-	PHY_SETTING( 200000, FULL, 200000baseDR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseCR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseKR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseDR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseDR_2_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseSR_Full		),
-	PHY_SETTING( 200000, FULL, 200000baseVR_Full		),
-	/* 100G */
-	PHY_SETTING( 100000, FULL, 100000baseCR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseSR4_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseCR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseDR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseSR2_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseCR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseKR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseLR_ER_FR_Full	),
-	PHY_SETTING( 100000, FULL, 100000baseDR_Full		),
-	PHY_SETTING( 100000, FULL, 100000baseSR_Full		),
-	/* 56G */
-	PHY_SETTING(  56000, FULL,  56000baseCR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseKR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseLR4_Full	  	),
-	PHY_SETTING(  56000, FULL,  56000baseSR4_Full	  	),
-	/* 50G */
-	PHY_SETTING(  50000, FULL,  50000baseCR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseKR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseSR2_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseCR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseKR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseLR_ER_FR_Full	),
-	PHY_SETTING(  50000, FULL,  50000baseDR_Full		),
-	PHY_SETTING(  50000, FULL,  50000baseSR_Full		),
-	/* 40G */
-	PHY_SETTING(  40000, FULL,  40000baseCR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseKR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseLR4_Full		),
-	PHY_SETTING(  40000, FULL,  40000baseSR4_Full		),
-	/* 25G */
-	PHY_SETTING(  25000, FULL,  25000baseCR_Full		),
-	PHY_SETTING(  25000, FULL,  25000baseKR_Full		),
-	PHY_SETTING(  25000, FULL,  25000baseSR_Full		),
-	/* 20G */
-	PHY_SETTING(  20000, FULL,  20000baseKR2_Full		),
-	PHY_SETTING(  20000, FULL,  20000baseMLD2_Full		),
-	/* 10G */
-	PHY_SETTING(  10000, FULL,  10000baseCR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseER_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseKR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseKX4_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseLR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseLRM_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseR_FEC		),
-	PHY_SETTING(  10000, FULL,  10000baseSR_Full		),
-	PHY_SETTING(  10000, FULL,  10000baseT_Full		),
-	/* 5G */
-	PHY_SETTING(   5000, FULL,   5000baseT_Full		),
-	/* 2.5G */
-	PHY_SETTING(   2500, FULL,   2500baseT_Full		),
-	PHY_SETTING(   2500, FULL,   2500baseX_Full		),
-	/* 1G */
-	PHY_SETTING(   1000, FULL,   1000baseT_Full		),
-	PHY_SETTING(   1000, HALF,   1000baseT_Half		),
-	PHY_SETTING(   1000, FULL,   1000baseT1_Full		),
-	PHY_SETTING(   1000, FULL,   1000baseX_Full		),
-	PHY_SETTING(   1000, FULL,   1000baseKX_Full		),
-	/* 100M */
-	PHY_SETTING(    100, FULL,    100baseT_Full		),
-	PHY_SETTING(    100, FULL,    100baseT1_Full		),
-	PHY_SETTING(    100, HALF,    100baseT_Half		),
-	PHY_SETTING(    100, HALF,    100baseFX_Half		),
-	PHY_SETTING(    100, FULL,    100baseFX_Full		),
-	/* 10M */
-	PHY_SETTING(     10, FULL,     10baseT_Full		),
-	PHY_SETTING(     10, HALF,     10baseT_Half		),
-	PHY_SETTING(     10, FULL,     10baseT1L_Full		),
-	PHY_SETTING(     10, FULL,     10baseT1S_Full		),
-	PHY_SETTING(     10, HALF,     10baseT1S_Half		),
-	PHY_SETTING(     10, HALF,     10baseT1S_P2MP_Half	),
-	PHY_SETTING(     10, FULL,     10baseT1BRR_Full		),
-};
-#undef PHY_SETTING
-
-/**
- * phy_lookup_setting - lookup a PHY setting
- * @speed: speed to match
- * @duplex: duplex to match
- * @mask: allowed link modes
- * @exact: an exact match is required
- *
- * Search the settings array for a setting that matches the speed and
- * duplex, and which is supported.
- *
- * If @exact is unset, either an exact match or %NULL for no match will
- * be returned.
- *
- * If @exact is set, an exact match, the fastest supported setting at
- * or below the specified speed, the slowest supported setting, or if
- * they all fail, %NULL will be returned.
- */
-const struct phy_setting *
-phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
-{
-	const struct phy_setting *p, *match = NULL, *last = NULL;
-	int i;
-
-	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
-		if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
-		    test_bit(p->bit, mask)) {
-			last = p;
-			if (p->speed == speed && p->duplex == duplex) {
-				/* Exact match for speed and duplex */
-				match = p;
-				break;
-			} else if (!exact) {
-				if (!match && p->speed <= speed)
-					/* Candidate */
-					match = p;
-
-				if (p->speed < speed)
-					break;
-			}
-		}
-	}
-
-	if (!match && !exact)
-		match = last;
-
-	return match;
-}
-EXPORT_SYMBOL_GPL(phy_lookup_setting);
-
 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
 	phy_caps_linkmode_max_speed(max_speed, phydev->supported);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 99c195fa3695..ee4cc6a4ac3f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1275,19 +1275,6 @@ const char *phy_rate_matching_to_str(int rate_matching);
 
 int phy_interface_num_ports(phy_interface_t interface);
 
-/* A structure for mapping a particular speed and duplex
- * combination to a particular SUPPORTED and ADVERTISED value
- */
-struct phy_setting {
-	u32 speed;
-	u8 duplex;
-	u8 bit;
-};
-
-const struct phy_setting *
-phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
-		   bool exact);
-
 /**
  * phy_is_started - Convenience function to check whether PHY is started
  * @phydev: The phy_device struct
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:08 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:08 +0100
Subject: [PATCH net-next v5 11/13] net: phylink: Add a mapping between MAC_CAPS and LINK_CAPS
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-12-maxime.chevallier@bootlin.com>

phylink allows MAC drivers to report the capabilities in terms of speed,
duplex and pause support. This is done through a dedicated set of enum
values in the form of the MAC_ capabilities. They are very close to what
the LINK_CAPA_xxx can express, with the difference that LINK_CAPA don't
have any information about Pause/Asym Pause support.

To prepare converting phylink to using the phy_caps, add the mapping
between MAC capabilities and phy_caps. While doing so, we move the
phylink_caps_params array up a bit to simplify future commits.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phylink.c | 49 ++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 8e2b7d647a92..c6fa3f003833 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -292,6 +292,31 @@ static int phylink_interface_max_speed(phy_interface_t interface)
 	return SPEED_UNKNOWN;
 }
 
+static struct {
+	unsigned long mask;
+	int speed;
+	unsigned int duplex;
+	unsigned int caps_bit;
+} phylink_caps_params[] = {
+	{ MAC_400000FD, SPEED_400000, DUPLEX_FULL, BIT(LINK_CAPA_400000FD) },
+	{ MAC_200000FD, SPEED_200000, DUPLEX_FULL, BIT(LINK_CAPA_200000FD) },
+	{ MAC_100000FD, SPEED_100000, DUPLEX_FULL, BIT(LINK_CAPA_100000FD) },
+	{ MAC_56000FD,  SPEED_56000,  DUPLEX_FULL, BIT(LINK_CAPA_56000FD) },
+	{ MAC_50000FD,  SPEED_50000,  DUPLEX_FULL, BIT(LINK_CAPA_50000FD) },
+	{ MAC_40000FD,  SPEED_40000,  DUPLEX_FULL, BIT(LINK_CAPA_40000FD) },
+	{ MAC_25000FD,  SPEED_25000,  DUPLEX_FULL, BIT(LINK_CAPA_25000FD) },
+	{ MAC_20000FD,  SPEED_20000,  DUPLEX_FULL, BIT(LINK_CAPA_20000FD) },
+	{ MAC_10000FD,  SPEED_10000,  DUPLEX_FULL, BIT(LINK_CAPA_10000FD) },
+	{ MAC_5000FD,   SPEED_5000,   DUPLEX_FULL, BIT(LINK_CAPA_5000FD) },
+	{ MAC_2500FD,   SPEED_2500,   DUPLEX_FULL, BIT(LINK_CAPA_2500FD) },
+	{ MAC_1000FD,   SPEED_1000,   DUPLEX_FULL, BIT(LINK_CAPA_1000FD) },
+	{ MAC_1000HD,   SPEED_1000,   DUPLEX_HALF, BIT(LINK_CAPA_1000HD) },
+	{ MAC_100FD,    SPEED_100,    DUPLEX_FULL, BIT(LINK_CAPA_100FD) },
+	{ MAC_100HD,    SPEED_100,    DUPLEX_HALF, BIT(LINK_CAPA_100HD) },
+	{ MAC_10FD,     SPEED_10,     DUPLEX_FULL, BIT(LINK_CAPA_10FD) },
+	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF, BIT(LINK_CAPA_10HD) },
+};
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -445,30 +470,6 @@ static void phylink_caps_to_linkmodes(unsigned long *linkmodes,
 	}
 }
 
-static struct {
-	unsigned long mask;
-	int speed;
-	unsigned int duplex;
-} phylink_caps_params[] = {
-	{ MAC_400000FD, SPEED_400000, DUPLEX_FULL },
-	{ MAC_200000FD, SPEED_200000, DUPLEX_FULL },
-	{ MAC_100000FD, SPEED_100000, DUPLEX_FULL },
-	{ MAC_56000FD,  SPEED_56000,  DUPLEX_FULL },
-	{ MAC_50000FD,  SPEED_50000,  DUPLEX_FULL },
-	{ MAC_40000FD,  SPEED_40000,  DUPLEX_FULL },
-	{ MAC_25000FD,  SPEED_25000,  DUPLEX_FULL },
-	{ MAC_20000FD,  SPEED_20000,  DUPLEX_FULL },
-	{ MAC_10000FD,  SPEED_10000,  DUPLEX_FULL },
-	{ MAC_5000FD,   SPEED_5000,   DUPLEX_FULL },
-	{ MAC_2500FD,   SPEED_2500,   DUPLEX_FULL },
-	{ MAC_1000FD,   SPEED_1000,   DUPLEX_FULL },
-	{ MAC_1000HD,   SPEED_1000,   DUPLEX_HALF },
-	{ MAC_100FD,    SPEED_100,    DUPLEX_FULL },
-	{ MAC_100HD,    SPEED_100,    DUPLEX_HALF },
-	{ MAC_10FD,     SPEED_10,     DUPLEX_FULL },
-	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF },
-};
-
 /**
  * phylink_limit_mac_speed - limit the phylink_config to a maximum speed
  * @config: pointer to a &struct phylink_config
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:09 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:09 +0100
Subject: [PATCH net-next v5 12/13] net: phylink: Convert capabilities to linkmodes using phy_caps
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-13-maxime.chevallier@bootlin.com>

phylink_caps_to_linkmodes() is used to derive a list of linkmodes that
can be conceivably exposed using a given set of speeds and duplex
through phylink's MAC capabilities.

This list can be derived from the link_caps array in phy_caps, provided
we convert the MAC capabilities into a LINK_CAPA bitmask first.

Introduce an internal phylink helper phylink_caps_to_link_caps() to
convert from MAC capabilities into phy_caps, then  phy_caps_linkmodes()
to do the link_caps -> linkmodes conversion.

This avoids having to update phylink for every new linkmode.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 drivers/net/phy/phy-caps.h |   1 +
 drivers/net/phy/phy_caps.c |  14 ++++
 drivers/net/phy/phylink.c  | 155 +++++--------------------------------
 3 files changed, 36 insertions(+), 134 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index aef4b54a8429..7fc930876e33 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -44,6 +44,7 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 		       unsigned long *linkmodes);
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
+void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes);
 
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index 0366feee2912..fc1568f83c1a 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -251,3 +251,17 @@ bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
 
 	return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
 }
+
+/**
+ * phy_caps_linkmodes() - Convert a bitfield of capabilities into linkmodes
+ * @caps: The list of caps, each bit corresponding to a LINK_CAPA value
+ * @linkmodes: The set of linkmodes to fill. Must be previously initialized.
+ */
+void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
+{
+	unsigned long capa;
+
+	for_each_set_bit(capa, &caps, __LINK_CAPA_MAX)
+		linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
+}
+EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index c6fa3f003833..a75aad5e4563 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -317,6 +317,24 @@ static struct {
 	{ MAC_10HD,     SPEED_10,     DUPLEX_HALF, BIT(LINK_CAPA_10HD) },
 };
 
+/**
+ * phylink_caps_to_link_caps() - Convert a set of MAC capabilities LINK caps
+ * @caps: A set of MAC capabilities
+ *
+ * Returns: The corresponding set of LINK_CAPA as defined in phy-caps.h
+ */
+static unsigned long phylink_caps_to_link_caps(unsigned long caps)
+{
+	unsigned long link_caps = 0;
+	int i;
+
+	for (i = 0; i <  ARRAY_SIZE(phylink_caps_params); i++)
+		if (caps & phylink_caps_params[i].mask)
+			link_caps |= phylink_caps_params[i].caps_bit;
+
+	return link_caps;
+}
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -328,146 +346,15 @@ static struct {
 static void phylink_caps_to_linkmodes(unsigned long *linkmodes,
 				      unsigned long caps)
 {
+	unsigned long link_caps = phylink_caps_to_link_caps(caps);
+
 	if (caps & MAC_SYM_PAUSE)
 		__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes);
 
 	if (caps & MAC_ASYM_PAUSE)
 		__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes);
 
-	if (caps & MAC_10HD) {
-		__set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT, linkmodes);
-	}
-
-	if (caps & MAC_10FD) {
-		__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10baseT1S_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100HD) {
-		__set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100FD) {
-		__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_1000HD)
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, linkmodes);
-
-	if (caps & MAC_1000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_2500FD) {
-		__set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_5000FD)
-		__set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, linkmodes);
-
-	if (caps & MAC_10000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_25000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_40000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_50000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_56000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_100000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_100000baseDR_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_200000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, linkmodes);
-	}
-
-	if (caps & MAC_400000FD) {
-		__set_bit(ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
-			  linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, linkmodes);
-		__set_bit(ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, linkmodes);
-	}
+	phy_caps_linkmodes(link_caps, linkmodes);
 }
 
 /**
-- 
2.48.1



From maxime.chevallier at bootlin.com  Fri Mar  7 09:36:10 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri,  7 Mar 2025 18:36:10 +0100
Subject: [PATCH net-next v5 13/13] net: phylink: Use phy_caps to get an interface's capabilities and modes
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <20250307173611.129125-14-maxime.chevallier@bootlin.com>

Phylink has internal code to get the MAC capabilities of a given PHY
interface (what are the supported speed and duplex).

Extract that into phy_caps, but use the link_capa for conversion. Add an
internal phylink helper for the link caps -> mac caps conversion, and
use this in phylink_caps_to_linkmodes().

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V5: Rename the patch with the phylink prefix

 drivers/net/phy/phy-caps.h |  4 ++
 drivers/net/phy/phy_caps.c | 92 ++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/phylink.c  | 90 ++++++-------------------------------
 3 files changed, 110 insertions(+), 76 deletions(-)

diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index 7fc930876e33..157759966650 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -8,6 +8,7 @@
 #define __PHY_CAPS_H
 
 #include <linux/ethtool.h>
+#include <linux/phy.h>
 
 enum {
 	LINK_CAPA_10HD = 0,
@@ -32,6 +33,8 @@ enum {
 	__LINK_CAPA_MAX,
 };
 
+#define LINK_CAPA_ALL	GENMASK((__LINK_CAPA_MAX - 1), 0)
+
 struct link_capabilities {
 	int speed;
 	unsigned int duplex;
@@ -45,6 +48,7 @@ size_t phy_caps_speeds(unsigned int *speeds, size_t size,
 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
 void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes);
+unsigned long phy_caps_from_interface(phy_interface_t interface);
 
 const struct link_capabilities *
 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index fc1568f83c1a..703321689726 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -265,3 +265,95 @@ void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
 		linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
 }
 EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
+
+/**
+ * phy_caps_from_interface() - Get the link capa from a given PHY interface
+ * @interface: The PHY interface we want to get the possible Speed/Duplex from
+ *
+ * Returns: A bitmask of LINK_CAPA_xxx values that can be achieved with the
+ *          provided interface.
+ */
+unsigned long phy_caps_from_interface(phy_interface_t interface)
+{
+	unsigned long link_caps = 0;
+
+	switch (interface) {
+	case PHY_INTERFACE_MODE_USXGMII:
+		link_caps |= BIT(LINK_CAPA_10000FD) | BIT(LINK_CAPA_5000FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_10G_QXGMII:
+		link_caps |= BIT(LINK_CAPA_2500FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+	case PHY_INTERFACE_MODE_QUSGMII:
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_GMII:
+		link_caps |= BIT(LINK_CAPA_1000HD) | BIT(LINK_CAPA_1000FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_REVRMII:
+	case PHY_INTERFACE_MODE_RMII:
+	case PHY_INTERFACE_MODE_SMII:
+	case PHY_INTERFACE_MODE_REVMII:
+	case PHY_INTERFACE_MODE_MII:
+		link_caps |= BIT(LINK_CAPA_10HD) | BIT(LINK_CAPA_10FD);
+		fallthrough;
+
+	case PHY_INTERFACE_MODE_100BASEX:
+		link_caps |= BIT(LINK_CAPA_100HD) | BIT(LINK_CAPA_100FD);
+		break;
+
+	case PHY_INTERFACE_MODE_TBI:
+	case PHY_INTERFACE_MODE_MOCA:
+	case PHY_INTERFACE_MODE_RTBI:
+	case PHY_INTERFACE_MODE_1000BASEX:
+		link_caps |= BIT(LINK_CAPA_1000HD);
+		fallthrough;
+	case PHY_INTERFACE_MODE_1000BASEKX:
+	case PHY_INTERFACE_MODE_TRGMII:
+		link_caps |= BIT(LINK_CAPA_1000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_2500BASEX:
+		link_caps |= BIT(LINK_CAPA_2500FD);
+		break;
+
+	case PHY_INTERFACE_MODE_5GBASER:
+		link_caps |= BIT(LINK_CAPA_5000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_XGMII:
+	case PHY_INTERFACE_MODE_RXAUI:
+	case PHY_INTERFACE_MODE_XAUI:
+	case PHY_INTERFACE_MODE_10GBASER:
+	case PHY_INTERFACE_MODE_10GKR:
+		link_caps |= BIT(LINK_CAPA_10000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_25GBASER:
+		link_caps |= BIT(LINK_CAPA_25000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_XLGMII:
+		link_caps |= BIT(LINK_CAPA_40000FD);
+		break;
+
+	case PHY_INTERFACE_MODE_INTERNAL:
+		link_caps |= LINK_CAPA_ALL;
+		break;
+
+	case PHY_INTERFACE_MODE_NA:
+	case PHY_INTERFACE_MODE_MAX:
+		break;
+	}
+
+	return link_caps;
+}
+EXPORT_SYMBOL_GPL(phy_caps_from_interface);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a75aad5e4563..08a2f0f7c08e 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -335,6 +335,18 @@ static unsigned long phylink_caps_to_link_caps(unsigned long caps)
 	return link_caps;
 }
 
+static unsigned long phylink_link_caps_to_mac_caps(unsigned long link_caps)
+{
+	unsigned long caps = 0;
+	int i;
+
+	for (i = 0; i <  ARRAY_SIZE(phylink_caps_params); i++)
+		if (link_caps & phylink_caps_params[i].caps_bit)
+			caps |= phylink_caps_params[i].mask;
+
+	return caps;
+}
+
 /**
  * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes
  * @linkmodes: ethtool linkmode mask (must be already initialised)
@@ -412,86 +424,12 @@ static unsigned long phylink_get_capabilities(phy_interface_t interface,
 					      unsigned long mac_capabilities,
 					      int rate_matching)
 {
+	unsigned long link_caps = phy_caps_from_interface(interface);
 	int max_speed = phylink_interface_max_speed(interface);
 	unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
 	unsigned long matched_caps = 0;
 
-	switch (interface) {
-	case PHY_INTERFACE_MODE_USXGMII:
-		caps |= MAC_10000FD | MAC_5000FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_10G_QXGMII:
-		caps |= MAC_2500FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_PSGMII:
-	case PHY_INTERFACE_MODE_QSGMII:
-	case PHY_INTERFACE_MODE_QUSGMII:
-	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_GMII:
-		caps |= MAC_1000HD | MAC_1000FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_REVRMII:
-	case PHY_INTERFACE_MODE_RMII:
-	case PHY_INTERFACE_MODE_SMII:
-	case PHY_INTERFACE_MODE_REVMII:
-	case PHY_INTERFACE_MODE_MII:
-		caps |= MAC_10HD | MAC_10FD;
-		fallthrough;
-
-	case PHY_INTERFACE_MODE_100BASEX:
-		caps |= MAC_100HD | MAC_100FD;
-		break;
-
-	case PHY_INTERFACE_MODE_TBI:
-	case PHY_INTERFACE_MODE_MOCA:
-	case PHY_INTERFACE_MODE_RTBI:
-	case PHY_INTERFACE_MODE_1000BASEX:
-		caps |= MAC_1000HD;
-		fallthrough;
-	case PHY_INTERFACE_MODE_1000BASEKX:
-	case PHY_INTERFACE_MODE_TRGMII:
-		caps |= MAC_1000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_2500BASEX:
-		caps |= MAC_2500FD;
-		break;
-
-	case PHY_INTERFACE_MODE_5GBASER:
-		caps |= MAC_5000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_XGMII:
-	case PHY_INTERFACE_MODE_RXAUI:
-	case PHY_INTERFACE_MODE_XAUI:
-	case PHY_INTERFACE_MODE_10GBASER:
-	case PHY_INTERFACE_MODE_10GKR:
-		caps |= MAC_10000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_25GBASER:
-		caps |= MAC_25000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_XLGMII:
-		caps |= MAC_40000FD;
-		break;
-
-	case PHY_INTERFACE_MODE_INTERNAL:
-		caps |= ~0;
-		break;
-
-	case PHY_INTERFACE_MODE_NA:
-	case PHY_INTERFACE_MODE_MAX:
-		break;
-	}
+	caps |= phylink_link_caps_to_mac_caps(link_caps);
 
 	switch (rate_matching) {
 	case RATE_MATCH_OPEN_LOOP:
-- 
2.48.1



From lkp at intel.com  Fri Mar  7 09:36:38 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 08 Mar 2025 01:36:38 +0800
Subject: [soc:for-next] BUILD SUCCESS
 a84db892511ab79e7a817a171fb4765daccffb88
Message-ID: <202503080132.BdRVQJNr-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
branch HEAD: a84db892511ab79e7a817a171fb4765daccffb88  soc: document merges

elapsed time: 1457m

configs tested: 74
configs skipped: 0

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
arc                               allnoconfig    gcc-13.2.0
arc                   randconfig-001-20250307    gcc-13.2.0
arc                   randconfig-002-20250307    gcc-13.2.0
arm                               allnoconfig    clang-17
arm                         assabet_defconfig    clang-21
arm                   randconfig-001-20250307    clang-21
arm                   randconfig-002-20250307    gcc-14.2.0
arm                   randconfig-003-20250307    clang-19
arm                   randconfig-004-20250307    clang-21
arm64                             allnoconfig    gcc-14.2.0
arm64                 randconfig-001-20250307    gcc-14.2.0
arm64                 randconfig-002-20250307    clang-15
arm64                 randconfig-003-20250307    gcc-14.2.0
arm64                 randconfig-004-20250307    clang-15
csky                  randconfig-001-20250307    gcc-14.2.0
csky                  randconfig-002-20250307    gcc-14.2.0
hexagon               randconfig-001-20250307    clang-21
hexagon               randconfig-002-20250307    clang-21
i386                              allnoconfig    gcc-12
i386        buildonly-randconfig-001-20250307    clang-19
i386        buildonly-randconfig-002-20250307    clang-19
i386        buildonly-randconfig-003-20250307    gcc-11
i386        buildonly-randconfig-004-20250307    clang-19
i386        buildonly-randconfig-005-20250307    gcc-12
i386        buildonly-randconfig-006-20250307    clang-19
loongarch             randconfig-001-20250307    gcc-14.2.0
loongarch             randconfig-002-20250307    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                          amiga_defconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250307    gcc-14.2.0
nios2                 randconfig-002-20250307    gcc-14.2.0
parisc                randconfig-001-20250307    gcc-14.2.0
parisc                randconfig-002-20250307    gcc-14.2.0
powerpc                  mpc885_ads_defconfig    clang-18
powerpc               randconfig-001-20250307    gcc-14.2.0
powerpc               randconfig-002-20250307    clang-21
powerpc               randconfig-003-20250307    clang-19
powerpc64             randconfig-001-20250307    clang-21
powerpc64             randconfig-002-20250307    gcc-14.2.0
powerpc64             randconfig-003-20250307    gcc-14.2.0
riscv                 randconfig-001-20250307    gcc-14.2.0
riscv                 randconfig-002-20250307    clang-19
s390                             allmodconfig    clang-19
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250307    gcc-14.2.0
s390                  randconfig-002-20250307    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250307    gcc-14.2.0
sh                    randconfig-002-20250307    gcc-14.2.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250307    gcc-14.2.0
sparc                 randconfig-002-20250307    gcc-14.2.0
sparc64               randconfig-001-20250307    gcc-14.2.0
sparc64               randconfig-002-20250307    gcc-14.2.0
um                    randconfig-001-20250307    clang-17
um                    randconfig-002-20250307    clang-21
x86_64                            allnoconfig    clang-19
x86_64      buildonly-randconfig-001-20250307    clang-19
x86_64      buildonly-randconfig-002-20250307    gcc-12
x86_64      buildonly-randconfig-003-20250307    clang-19
x86_64      buildonly-randconfig-004-20250307    clang-19
x86_64      buildonly-randconfig-005-20250307    clang-19
x86_64      buildonly-randconfig-006-20250307    gcc-12
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250307    gcc-14.2.0
xtensa                randconfig-002-20250307    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From mhklinux at outlook.com  Fri Mar  7 09:38:28 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 17:38:28 +0000
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <7de9b06d-9a32-48b5-beda-2e19b36ae9c9@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
 <Z7-nDUe41XHyZ8RJ@skinsburskii.>
 <7de9b06d-9a32-48b5-beda-2e19b36ae9c9@linux.microsoft.com>
Message-ID: <SN6PR02MB41573673D5F786E6C47FC08ED4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, February 28, 2025 4:38 PM
> 
> On 2/26/2025 3:43 PM, Stanislav Kinsburskii wrote:
> > On Wed, Feb 26, 2025 at 03:08:02PM -0800, Nuno Das Neves wrote:
> >> This will handle SYNIC interrupts such as intercepts, doorbells, and
> >> scheduling messages intended for the mshv driver.
> >>
> >> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> >> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
> >> ---
> >>  arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
> >>  drivers/hv/hv_common.c         | 5 +++++
> >>  include/asm-generic/mshyperv.h | 1 +
> >>  3 files changed, 15 insertions(+)
> >>
> >> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> >> index 0116d0e96ef9..616e9a5d77b4 100644
> >> --- a/arch/x86/kernel/cpu/mshyperv.c
> >> +++ b/arch/x86/kernel/cpu/mshyperv.c
> >> @@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
> >>  }
> >>  EXPORT_SYMBOL_GPL(hv_set_msr);
> >>
> >> +static void (*mshv_handler)(void);
> >>  static void (*vmbus_handler)(void);
> >>  static void (*hv_stimer0_handler)(void);
> >>  static void (*hv_kexec_handler)(void);
> >> @@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
> >>  	struct pt_regs *old_regs = set_irq_regs(regs);
> >>
> >>  	inc_irq_stat(irq_hv_callback_count);
> >> +	if (mshv_handler)
> >> +		mshv_handler();
> >
> > Can mshv_handler be defined as a weak symbol doing nothing instead
> > of defining it a null pointer?
> > This should allow to simplify this code and get rid of
> > hv_setup_mshv_handler, which looks redundant.
> >
> Interesting, I tested this and it does seems to work! It seems like
> a good change, thanks.

Just be a bit careful. When CONFIG_HYPERV=n, mshyperv.c still gets
built even through none of the other Hyper-V related files do.  There
are #ifdef CONFIG_HYPERV in mshyperv.c to eliminate references to
Hyper-V files that wouldn't be built. I'd suggest doing a test build with
that configuration to make sure it's all clean.

Michael

> 
> > Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> >
> >> +
> >>  	if (vmbus_handler)
> >>  		vmbus_handler();
> >>
> >> @@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
> >>  	set_irq_regs(old_regs);
> >>  }
> >>
> >> +void hv_setup_mshv_handler(void (*handler)(void))
> >> +{
> >> +	mshv_handler = handler;
> >> +}
> >> +
> >>  void hv_setup_vmbus_handler(void (*handler)(void))
> >>  {
> >>  	vmbus_handler = handler;
> >> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> >> index 2763cb6d3678..f5a07fd9a03b 100644
> >> --- a/drivers/hv/hv_common.c
> >> +++ b/drivers/hv/hv_common.c
> >> @@ -677,6 +677,11 @@ void __weak hv_remove_vmbus_handler(void)
> >>  }
> >>  EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
> >>
> >> +void __weak hv_setup_mshv_handler(void (*handler)(void))
> >> +{
> >> +}
> >> +EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
> >> +
> >>  void __weak hv_setup_kexec_handler(void (*handler)(void))
> >>  {
> >>  }
> >> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> >> index 1f46d19a16aa..a05f12e63ccd 100644
> >> --- a/include/asm-generic/mshyperv.h
> >> +++ b/include/asm-generic/mshyperv.h
> >> @@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
> >>  void hv_remove_kexec_handler(void);
> >>  void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
> >>  void hv_remove_crash_handler(void);
> >> +void hv_setup_mshv_handler(void (*handler)(void));
> >>
> >>  extern int vmbus_interrupt;
> >>  extern int vmbus_irq;
> >> --
> >> 2.34.1
> >>


From dan.carpenter at linaro.org  Fri Mar  7 09:38:48 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 7 Mar 2025 20:38:48 +0300
Subject: [PATCH v2 4/8] phy: move phy-qcom-snps-eusb2 out of its vendor
 sub-directory
In-Reply-To: <20250223122227.725233-5-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <551a7b8d-1f2d-429f-b7fd-c8ea1afdcf25@stanley.mountain>

Hi Ivaylo,

kernel test robot noticed the following build warnings:

https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ivaylo-Ivanov/dt-bindings-phy-rename-qcom-snps-eusb2-phy-binding-to-snps-eusb2-phy/20250223-202709
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250223122227.725233-5-ivo.ivanov.ivanov1%40gmail.com
patch subject: [PATCH v2 4/8] phy: move phy-qcom-snps-eusb2 out of its vendor sub-directory
config: sh-randconfig-r073-20250307 (https://download.01.org/0day-ci/archive/20250307/202503072305.Osodtcnk-lkp at intel.com/config)
compiler: sh4-linux-gcc (GCC) 14.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Reported-by: Dan Carpenter <dan.carpenter at linaro.org>
| Closes: https://lore.kernel.org/r/202503072305.Osodtcnk-lkp at intel.com/

smatch warnings:
drivers/phy/phy-snps-eusb2.c:452 snps_eusb2_hsphy_probe() warn: passing zero to 'PTR_ERR'

vim +/PTR_ERR +452 drivers/phy/phy-snps-eusb2.c

15a1981f608b0f Ivaylo Ivanov 2025-02-23  399  static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  400  {
15a1981f608b0f Ivaylo Ivanov 2025-02-23  401  	struct device *dev = &pdev->dev;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  402  	struct device_node *np = dev->of_node;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  403  	struct snps_eusb2_hsphy *phy;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  404  	struct phy_provider *phy_provider;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  405  	struct phy *generic_phy;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  406  	const struct snps_eusb2_phy_drvdata *drv_data;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  407  	int ret, i;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  408  	int num;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  409  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  410  	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  411  	if (!phy)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  412  		return -ENOMEM;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  413  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  414  	drv_data = of_device_get_match_data(dev);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  415  	if (!drv_data)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  416  		return -EINVAL;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  417  	phy->data = drv_data;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  418  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  419  	phy->base = devm_platform_ioremap_resource(pdev, 0);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  420  	if (IS_ERR(phy->base))
15a1981f608b0f Ivaylo Ivanov 2025-02-23  421  		return PTR_ERR(phy->base);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  422  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  423  	phy->phy_reset = devm_reset_control_get_exclusive(dev, NULL);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  424  	if (IS_ERR(phy->phy_reset))
15a1981f608b0f Ivaylo Ivanov 2025-02-23  425  		return PTR_ERR(phy->phy_reset);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  426  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  427  	phy->clks = devm_kcalloc(dev,
15a1981f608b0f Ivaylo Ivanov 2025-02-23  428  				 phy->data->num_clks,
15a1981f608b0f Ivaylo Ivanov 2025-02-23  429  				 sizeof(*phy->clks),
15a1981f608b0f Ivaylo Ivanov 2025-02-23  430  				 GFP_KERNEL);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  431  	if (!phy->clks)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  432  		return -ENOMEM;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  433  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  434  	for (int i = 0; i < phy->data->num_clks; ++i)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  435  		phy->clks[i].id = phy->data->clk_names[i];
15a1981f608b0f Ivaylo Ivanov 2025-02-23  436  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  437  	ret = devm_clk_bulk_get(dev, phy->data->num_clks,
15a1981f608b0f Ivaylo Ivanov 2025-02-23  438  				phy->clks);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  439  	if (ret)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  440  		return dev_err_probe(dev, ret,
15a1981f608b0f Ivaylo Ivanov 2025-02-23  441  				     "failed to get phy clock(s)\n");
15a1981f608b0f Ivaylo Ivanov 2025-02-23  442  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  443  	phy->ref_clk = NULL;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  444  	for (int i = 0; i < phy->data->num_clks; ++i) {
15a1981f608b0f Ivaylo Ivanov 2025-02-23  445  		if (!strcmp(phy->clks[i].id, "ref")) {
15a1981f608b0f Ivaylo Ivanov 2025-02-23  446  			phy->ref_clk = phy->clks[i].clk;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  447  			break;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  448  		}
15a1981f608b0f Ivaylo Ivanov 2025-02-23  449  	}
15a1981f608b0f Ivaylo Ivanov 2025-02-23  450  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  451  	if (IS_ERR_OR_NULL(phy->ref_clk))
15a1981f608b0f Ivaylo Ivanov 2025-02-23 @452  		return dev_err_probe(dev, PTR_ERR(phy->ref_clk),

PTR_ERR(phy->ref_clk) is success.

15a1981f608b0f Ivaylo Ivanov 2025-02-23  453  				     "failed to get ref clk\n");
15a1981f608b0f Ivaylo Ivanov 2025-02-23  454  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  455  	num = ARRAY_SIZE(phy->vregs);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  456  	for (i = 0; i < num; i++)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  457  		phy->vregs[i].supply = eusb2_hsphy_vreg_names[i];
15a1981f608b0f Ivaylo Ivanov 2025-02-23  458  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  459  	ret = devm_regulator_bulk_get(dev, num, phy->vregs);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  460  	if (ret)
15a1981f608b0f Ivaylo Ivanov 2025-02-23  461  		return dev_err_probe(dev, ret,
15a1981f608b0f Ivaylo Ivanov 2025-02-23  462  				     "failed to get regulator supplies\n");
15a1981f608b0f Ivaylo Ivanov 2025-02-23  463  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  464  	phy->repeater = devm_of_phy_get_by_index(dev, np, 0);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  465  	if (IS_ERR(phy->repeater))
15a1981f608b0f Ivaylo Ivanov 2025-02-23  466  		return dev_err_probe(dev, PTR_ERR(phy->repeater),
15a1981f608b0f Ivaylo Ivanov 2025-02-23  467  				     "failed to get repeater\n");
15a1981f608b0f Ivaylo Ivanov 2025-02-23  468  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  469  	generic_phy = devm_phy_create(dev, NULL, &snps_eusb2_hsphy_ops);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  470  	if (IS_ERR(generic_phy)) {
15a1981f608b0f Ivaylo Ivanov 2025-02-23  471  		dev_err(dev, "failed to create phy %d\n", ret);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  472  		return PTR_ERR(generic_phy);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  473  	}
15a1981f608b0f Ivaylo Ivanov 2025-02-23  474  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  475  	dev_set_drvdata(dev, phy);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  476  	phy_set_drvdata(generic_phy, phy);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  477  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  478  	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  479  	if (IS_ERR(phy_provider))
15a1981f608b0f Ivaylo Ivanov 2025-02-23  480  		return PTR_ERR(phy_provider);
15a1981f608b0f Ivaylo Ivanov 2025-02-23  481  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  482  	dev_info(dev, "Registered Snps-eUSB2 phy\n");
15a1981f608b0f Ivaylo Ivanov 2025-02-23  483  
15a1981f608b0f Ivaylo Ivanov 2025-02-23  484  	return 0;
15a1981f608b0f Ivaylo Ivanov 2025-02-23  485  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki



From mhklinux at outlook.com  Fri Mar  7 09:44:50 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 17:44:50 +0000
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB415730AA9A9BFFBB9A62F195D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM

> 
> This will handle SYNIC interrupts such as intercepts, doorbells, and
> scheduling messages intended for the mshv driver.

Could you provide a bit more detailed commit message? How does
the mshv_handler() relate to the vmbus_handler()? From the code
mshv_handler() goes first, and I'm assuming it processes what it
knows about (intercepts, doorbells, scheduling messages?) and
then hands off control to the vmbus_handler() to handle the usual
VMbus-related message and channel interrupts. But it would be
nice to have the commit message or code comments describe the
overall intent and any obscure aspects of the relationship.

And avoid references to "This" or "This patch". :-)

> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
> ---
>  arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
>  drivers/hv/hv_common.c         | 5 +++++
>  include/asm-generic/mshyperv.h | 1 +
>  3 files changed, 15 insertions(+)
> 
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 0116d0e96ef9..616e9a5d77b4 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
>  }
>  EXPORT_SYMBOL_GPL(hv_set_msr);
> 
> +static void (*mshv_handler)(void);
>  static void (*vmbus_handler)(void);
>  static void (*hv_stimer0_handler)(void);
>  static void (*hv_kexec_handler)(void);
> @@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>  	struct pt_regs *old_regs = set_irq_regs(regs);
> 
>  	inc_irq_stat(irq_hv_callback_count);
> +	if (mshv_handler)
> +		mshv_handler();
> +
>  	if (vmbus_handler)
>  		vmbus_handler();
> 
> @@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>  	set_irq_regs(old_regs);
>  }
> 
> +void hv_setup_mshv_handler(void (*handler)(void))
> +{
> +	mshv_handler = handler;
> +}
> +
>  void hv_setup_vmbus_handler(void (*handler)(void))
>  {
>  	vmbus_handler = handler;
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 2763cb6d3678..f5a07fd9a03b 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -677,6 +677,11 @@ void __weak hv_remove_vmbus_handler(void)
>  }
>  EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
> 
> +void __weak hv_setup_mshv_handler(void (*handler)(void))
> +{
> +}
> +EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
> +
>  void __weak hv_setup_kexec_handler(void (*handler)(void))
>  {
>  }
> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> index 1f46d19a16aa..a05f12e63ccd 100644
> --- a/include/asm-generic/mshyperv.h
> +++ b/include/asm-generic/mshyperv.h
> @@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
>  void hv_remove_kexec_handler(void);
>  void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
>  void hv_remove_crash_handler(void);
> +void hv_setup_mshv_handler(void (*handler)(void));
> 
>  extern int vmbus_interrupt;
>  extern int vmbus_irq;
> --
> 2.34.1



From manivannan.sadhasivam at linaro.org  Fri Mar  7 09:48:39 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Fri, 7 Mar 2025 23:18:39 +0530
Subject: [PATCH] PCI: controller: Restore PCI_REASSIGN_ALL_BUS when
 PCI_PROBE_ONLY is enabled
In-Reply-To: <416a2d7d-eeb6-4163-8805-3178476f5a8d@windriver.com>
References: <20250117082428.129353-1-Bo.Sun.CN@windriver.com>
 <20250210103707.c5ubeaowk7xwt6p5@thinkpad>
 <df5d3c54-d436-43bb-8b40-665c020d6bb5@windriver.com>
 <20250214170057.o3ffoiuxn4hxqqqe@thinkpad>
 <55a33534-bff0-488c-a2a2-2898d54bd62f@windriver.com>
 <20250305060607.ygsafql53h2ujwjp@thinkpad>
 <416a2d7d-eeb6-4163-8805-3178476f5a8d@windriver.com>
Message-ID: <20250307174839.7nd7mhc5ebmokumu@thinkpad>

On Fri, Mar 07, 2025 at 06:14:26PM +0800, Bo Sun wrote:

[...]

> > > So, I propose the following solution as a workaround to handle these edge
> > > cases.
> > > 
> > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > index 82b21e34c545..af8efebc7e7d 100644
> > > --- a/drivers/pci/quirks.c
> > > +++ b/drivers/pci/quirks.c
> > > @@ -6181,6 +6181,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1536,
> > > rom_bar_overlap_defect);
> > >   DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1537,
> > > rom_bar_overlap_defect);
> > >   DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1538,
> > > rom_bar_overlap_defect);
> > > 
> > > +static void quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr(struct pci_dev
> > > *dev)
> > > +{
> > > +       if (!pci_has_flag(PCI_PROBE_ONLY))
> > > +               pci_add_flags(PCI_REASSIGN_ALL_BUS);
> > > +}
> > > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CAVIUM, 0xa002,
> > > quirk_marvell_cn96xx_cn10xxx_reassign_all_busnr);
> > > +
> > 
> > LGTM. Please add a comment about this quirk too.
> 
> OK, I'll add the comment. Should I send the v2 patch?
> 

Yes, ofc. You should send v2 with the quirk change.

- Mani

-- 
????????? ????????


From wiagn233 at outlook.com  Fri Mar  7 10:13:31 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Sat,  8 Mar 2025 02:13:31 +0800
Subject: [PATCH v9] wifi: mt76: mt7915: add wds support when wed is enabled
Message-ID: <TYCPR01MB8437EEEB9227381FAB0BD7D998D52@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The current WED only supports 256 wcid, whereas mt7986 can support up to
512 entries, so firmware provides a rule to get sta_info by DA when wcid
is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
to 0xff by host driver.

However, firmware is unable to get sta_info from DA as DA != RA for
4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
and (768 ~ 783) for sync up to get correct sta_info.

Currently WDS+WED config is completely broken on MT7986/7981 devices if
without this patch.

Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  9 ++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 51 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
 drivers/net/wireless/mediatek/mt76/util.c     | 37 ++++++++++++--
 drivers/net/wireless/mediatek/mt76/util.h     |  7 ++-
 6 files changed, 112 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b1070..638ee9fae0c73 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -28,6 +28,9 @@
 
 #define MT76_TOKEN_FREE_THR	64
 
+#define MT76_WED_WDS_MIN    256
+#define MT76_WED_WDS_MAX    272
+
 #define MT_QFLAG_WED_RING	GENMASK(1, 0)
 #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
 #define MT_QFLAG_WED		BIT(5)
@@ -73,6 +76,12 @@ enum mt76_wed_type {
 	MT76_WED_RRO_Q_IND,
 };
 
+enum mt76_wed_state {
+	MT76_WED_DEFAULT,
+	MT76_WED_ACTIVE,
+	MT76_WED_WDS_ACTIVE,
+};
+
 struct mt76_bus_ops {
 	u32 (*rr)(struct mt76_dev *dev, u32 offset);
 	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 3aa31c5cefa6a..c951675f907b8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: ISC
 /* Copyright (C) 2020 MediaTek Inc. */
 
+#include "linux/fortify-string.h"
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
@@ -745,8 +746,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
 	bool ext_phy = mvif->phy != &dev->phy;
 	int idx;
+	u8 flags = MT76_WED_DEFAULT;
 
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76)) {
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+	}
+
+	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
 	if (idx < 0)
 		return -ENOSPC;
 
@@ -1271,6 +1279,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 {
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
+	struct ieee80211_sta *pre_sta;
+	struct mt7915_sta *pre_msta;
+	u8 flags = MT76_WED_DEFAULT;
+	int tmp_idx;
 
 	if (enabled)
 		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
@@ -1280,6 +1293,34 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 	if (!msta->wcid.sta)
 		return;
 
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76) &&
+	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
+		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
+
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+
+		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
+		if (tmp_idx == -1)
+			goto error;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
+
+		tmp_idx = msta->wcid.idx;
+		msta->wcid.idx = pre_msta->wcid.idx;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
+
+		synchronize_rcu();
+		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
+
+error:
+		kfree(pre_sta);
+	}
+
 	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
 }
 
@@ -1726,15 +1767,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
 	path->mtk_wdma.queue = phy != &dev->phy;
+	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
+	    is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = msta->wcid.idx;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
 
 	ctx->dev = NULL;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9d790f234e82c..32c5aa1a361e8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
 
 	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
 
-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-	     is_mt7915(&dev->mt76)) ||
-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+		if (is_mt7915(&dev->mt76) ||
+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+						0, 0, 0);
+		else
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+						MCU_WA_PARAM_WED_VERSION,
+						dev->mt76.mmio.wed.rev_id, 0);
+		if (ret)
+			return ret;
+	}
+#endif
 
 	ret = mt7915_mcu_set_mwds(dev, 1);
 	if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 49476a4182fd1..c3dd0cb4a5d38 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
 	MCU_WA_PARAM_PDMA_RX = 0x04,
 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
 	MCU_WA_PARAM_RED = 0x0e,
+	MCU_WA_PARAM_WED_VERSION = 0x32,
 	MCU_WA_PARAM_RED_SETTING = 0x40,
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 95b3dc96e4c45..7fac9c79ebdf3 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 }
 EXPORT_SYMBOL_GPL(____mt76_poll_msec);
 
-int mt76_wcid_alloc(u32 *mask, int size)
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
 {
 	int i, idx = 0, cur;
+	int min = MT76_WED_WDS_MIN;
+	int max = MT76_WED_WDS_MAX;
 
 	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
 		idx = ffs(~mask[i]);
@@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
 
 		idx--;
 		cur = i * 32 + idx;
-		if (cur >= size)
+
+		switch (flag) {
+		case MT76_WED_ACTIVE:
+			if (cur >= min && cur < max)
+				continue;
+
+			if (cur >= size) {
+				u32 end = max - min - 1;
+
+				i = min / 32;
+				idx = ffs(~mask[i] & GENMASK(end, 0));
+				if (!idx)
+					goto error;
+				idx--;
+				cur = min + idx;
+			}
+
 			break;
+		case MT76_WED_WDS_ACTIVE:
+			if (cur < min)
+				continue;
+			if (cur >= max)
+				goto error;
+
+			break;
+		default:
+			if (cur >= size)
+				goto error;
+			break;
+		}
 
 		mask[i] |= BIT(idx);
 		return cur;
 	}
 
+error:
 	return -1;
 }
-EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
 
 int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94cf..99b7263c0a205 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -27,7 +27,12 @@ enum {
 #define MT76_INCR(_var, _size) \
 	(_var = (((_var) + 1) % (_size)))
 
-int mt76_wcid_alloc(u32 *mask, int size);
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+	return __mt76_wcid_alloc(mask, size, 0);
+}
 
 static inline void
 mt76_wcid_mask_set(u32 *mask, int idx)
-- 
2.48.1



From wiagn233 at outlook.com  Fri Mar  7 10:18:05 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Sat, 8 Mar 2025 02:18:05 +0800
Subject: [PATCH v9] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <TYCPR01MB8437EEEB9227381FAB0BD7D998D52@TYCPR01MB8437.jpnprd01.prod.outlook.com>
References: <TYCPR01MB8437EEEB9227381FAB0BD7D998D52@TYCPR01MB8437.jpnprd01.prod.outlook.com>
Message-ID: <TYCPR01MB84370EDD86F8EA76F79F1DE898D52@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Seems I forgot to add the changelist:
Changes since v1:
  - Drop duplicate setting in mmio
  - Reduce the patch size by redefining mt76_wcid_alloc
Changes since v2:
  - Rework wds wcid getting flow
Changes since v3:
  - Rebase to next-20240703
  - Sync with downstream patch
Changes since v4:
  - Rebase to next-20240802
Changes since v5:
  - Fixed build test error reported by robot
  - Rebase to next-20240805
Changes since v6:
  - Fix potential race conditions on tx/rx packets during the transition
  - Rebase to Felix's newest codebase
Changes since v7:
  - Fix build fail
Changes since v8:
  - Changed code as Shih advised

Best regards,
Shengyu

? 2025/3/8 02:13, Shengyu Qu ??:
> The current WED only supports 256 wcid, whereas mt7986 can support up to
> 512 entries, so firmware provides a rule to get sta_info by DA when wcid
> is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
> wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
> to 0xff by host driver.
> 
> However, firmware is unable to get sta_info from DA as DA != RA for
> 4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
> and (768 ~ 783) for sync up to get correct sta_info.
> 
> Currently WDS+WED config is completely broken on MT7986/7981 devices if
> without this patch.
> 
> Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
> Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
> Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
> Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
> Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
> ---
>   drivers/net/wireless/mediatek/mt76/mt76.h     |  9 ++++
>   .../net/wireless/mediatek/mt76/mt7915/main.c  | 51 +++++++++++++++++--
>   .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
>   .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
>   drivers/net/wireless/mediatek/mt76/util.c     | 37 ++++++++++++--
>   drivers/net/wireless/mediatek/mt76/util.h     |  7 ++-
>   6 files changed, 112 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 132148f7b1070..638ee9fae0c73 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -28,6 +28,9 @@
>   
>   #define MT76_TOKEN_FREE_THR	64
>   
> +#define MT76_WED_WDS_MIN    256
> +#define MT76_WED_WDS_MAX    272
> +
>   #define MT_QFLAG_WED_RING	GENMASK(1, 0)
>   #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
>   #define MT_QFLAG_WED		BIT(5)
> @@ -73,6 +76,12 @@ enum mt76_wed_type {
>   	MT76_WED_RRO_Q_IND,
>   };
>   
> +enum mt76_wed_state {
> +	MT76_WED_DEFAULT,
> +	MT76_WED_ACTIVE,
> +	MT76_WED_WDS_ACTIVE,
> +};
> +
>   struct mt76_bus_ops {
>   	u32 (*rr)(struct mt76_dev *dev, u32 offset);
>   	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> index 3aa31c5cefa6a..c951675f907b8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> @@ -1,6 +1,7 @@
>   // SPDX-License-Identifier: ISC
>   /* Copyright (C) 2020 MediaTek Inc. */
>   
> +#include "linux/fortify-string.h"
>   #include <linux/etherdevice.h>
>   #include <linux/platform_device.h>
>   #include <linux/pci.h>
> @@ -745,8 +746,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>   	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
>   	bool ext_phy = mvif->phy != &dev->phy;
>   	int idx;
> +	u8 flags = MT76_WED_DEFAULT;
>   
> -	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> +	    !is_mt7915(&dev->mt76)) {
> +		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
> +		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
> +	}
> +
> +	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
>   	if (idx < 0)
>   		return -ENOSPC;
>   
> @@ -1271,6 +1279,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>   {
>   	struct mt7915_dev *dev = mt7915_hw_dev(hw);
>   	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
> +	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
> +	struct ieee80211_sta *pre_sta;
> +	struct mt7915_sta *pre_msta;
> +	u8 flags = MT76_WED_DEFAULT;
> +	int tmp_idx;
>   
>   	if (enabled)
>   		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
> @@ -1280,6 +1293,34 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>   	if (!msta->wcid.sta)
>   		return;
>   
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> +	    !is_mt7915(&dev->mt76) &&
> +	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
> +		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
> +		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
> +
> +		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
> +			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
> +
> +		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
> +		if (tmp_idx == -1)
> +			goto error;
> +		pre_msta->wcid.idx = (u16)tmp_idx;
> +		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
> +		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
> +
> +		tmp_idx = msta->wcid.idx;
> +		msta->wcid.idx = pre_msta->wcid.idx;
> +		pre_msta->wcid.idx = (u16)tmp_idx;
> +		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
> +
> +		synchronize_rcu();
> +		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
> +
> +error:
> +		kfree(pre_sta);
> +	}
> +
>   	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
>   }
>   
> @@ -1726,15 +1767,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
>   	if (!mtk_wed_device_active(wed))
>   		return -ENODEV;
>   
> -	if (msta->wcid.idx > 0xff)
> +	if (msta->wcid.idx > MT7915_WTBL_STA)
>   		return -EIO;
>   
>   	path->type = DEV_PATH_MTK_WDMA;
>   	path->dev = ctx->dev;
>   	path->mtk_wdma.wdma_idx = wed->wdma_idx;
>   	path->mtk_wdma.bss = mvif->mt76.idx;
> -	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
>   	path->mtk_wdma.queue = phy != &dev->phy;
> +	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
> +	    is_mt7915(&dev->mt76))
> +		path->mtk_wdma.wcid = msta->wcid.idx;
> +	else
> +		path->mtk_wdma.wcid = 0x3ff;
>   
>   	ctx->dev = NULL;
>   
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> index 9d790f234e82c..32c5aa1a361e8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> @@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
>   
>   	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
>   
> -	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> -	     is_mt7915(&dev->mt76)) ||
> -	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
> -		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
> +#ifdef CONFIG_NET_MEDIATEK_SOC_WED
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
> +		if (is_mt7915(&dev->mt76) ||
> +		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
> +						0, 0, 0);
> +		else
> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
> +						MCU_WA_PARAM_WED_VERSION,
> +						dev->mt76.mmio.wed.rev_id, 0);
> +		if (ret)
> +			return ret;
> +	}
> +#endif
>   
>   	ret = mt7915_mcu_set_mwds(dev, 1);
>   	if (ret)
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> index 49476a4182fd1..c3dd0cb4a5d38 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> @@ -278,6 +278,7 @@ enum {
>   	MCU_WA_PARAM_PDMA_RX = 0x04,
>   	MCU_WA_PARAM_CPU_UTIL = 0x0b,
>   	MCU_WA_PARAM_RED = 0x0e,
> +	MCU_WA_PARAM_WED_VERSION = 0x32,
>   	MCU_WA_PARAM_RED_SETTING = 0x40,
>   };
>   
> diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
> index 95b3dc96e4c45..7fac9c79ebdf3 100644
> --- a/drivers/net/wireless/mediatek/mt76/util.c
> +++ b/drivers/net/wireless/mediatek/mt76/util.c
> @@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
>   }
>   EXPORT_SYMBOL_GPL(____mt76_poll_msec);
>   
> -int mt76_wcid_alloc(u32 *mask, int size)
> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
>   {
>   	int i, idx = 0, cur;
> +	int min = MT76_WED_WDS_MIN;
> +	int max = MT76_WED_WDS_MAX;
>   
>   	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
>   		idx = ffs(~mask[i]);
> @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
>   
>   		idx--;
>   		cur = i * 32 + idx;
> -		if (cur >= size)
> +
> +		switch (flag) {
> +		case MT76_WED_ACTIVE:
> +			if (cur >= min && cur < max)
> +				continue;
> +
> +			if (cur >= size) {
> +				u32 end = max - min - 1;
> +
> +				i = min / 32;
> +				idx = ffs(~mask[i] & GENMASK(end, 0));
> +				if (!idx)
> +					goto error;
> +				idx--;
> +				cur = min + idx;
> +			}
> +
>   			break;
> +		case MT76_WED_WDS_ACTIVE:
> +			if (cur < min)
> +				continue;
> +			if (cur >= max)
> +				goto error;
> +
> +			break;
> +		default:
> +			if (cur >= size)
> +				goto error;
> +			break;
> +		}
>   
>   		mask[i] |= BIT(idx);
>   		return cur;
>   	}
>   
> +error:
>   	return -1;
>   }
> -EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
> +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
>   
>   int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
>   {
> diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
> index 260965dde94cf..99b7263c0a205 100644
> --- a/drivers/net/wireless/mediatek/mt76/util.h
> +++ b/drivers/net/wireless/mediatek/mt76/util.h
> @@ -27,7 +27,12 @@ enum {
>   #define MT76_INCR(_var, _size) \
>   	(_var = (((_var) + 1) % (_size)))
>   
> -int mt76_wcid_alloc(u32 *mask, int size);
> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
> +
> +static inline int mt76_wcid_alloc(u32 *mask, int size)
> +{
> +	return __mt76_wcid_alloc(mask, size, 0);
> +}
>   
>   static inline void
>   mt76_wcid_mask_set(u32 *mask, int idx)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250308/2cde2669/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250308/2cde2669/attachment.sig>

From linux at armlinux.org.uk  Fri Mar  7 10:22:29 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 7 Mar 2025 18:22:29 +0000
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <20250307085558.5f8fcb90@kernel.org>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
 <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
 <1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>
 <20250307085558.5f8fcb90@kernel.org>
Message-ID: <Z8s5ZZyTCpS9xHlA@shell.armlinux.org.uk>

On Fri, Mar 07, 2025 at 08:55:58AM -0800, Jakub Kicinski wrote:
> On Fri, 7 Mar 2025 00:49:38 +0100 Jonas Karlman wrote:
> > Subject: Re: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
> > 
> > [encrypted.asc  application/octet-stream (3384 bytes)] 
> 
> Is it just me or does anyone else get blobs from Jonas?
> The list gets text, according to lore.

Looking at the emails I've received, some which were via the list, some
which were direct, I don't see anything out of the ordinary - seems to
just be text/plain here.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From catalin.marinas at arm.com  Fri Mar  7 10:33:07 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 7 Mar 2025 18:33:07 +0000
Subject: =?utf-8?Q?=E2=9C=85_PASS=3A_Test_repor?= =?utf-8?Q?t?= for
 for-kernelci (6.14.0-rc5, upstream-arm-next, 14d05f12)
In-Reply-To: <77413.125030711120800859@us-mta-168.us.mimecast.lan>
References: <77413.125030711120800859@us-mta-168.us.mimecast.lan>
Message-ID: <Z8s746JHlqXt7TSo@arm.com>

On Fri, Mar 07, 2025 at 04:12:05PM -0000, cki-project at redhat.com wrote:
> Hi, we tested your kernel and here are the results:
> 
>     Overall result: PASSED
>              Merge: OK
>            Compile: OK
> 
> Tested-by: CKI Project <cki-project at redhat.com>
> 
> Kernel information:
>     Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

Something wrong with CKI? In the past we used to get reports only after
updating the for-kernelci but now it seems to send several emails a day.
Is it related to the build error below? The above message implies that
it compiled successfully.

Thanks.

> You can find all the details about the test run at
>     https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1705137995
> 
> One or more kernel builds failed:
>     We also see the following known issues which are not related to your changes:
>          aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1705137995-aarch64-kernel
>                    Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
>                           https://gitlab.com/cki-project/infrastructure/-/issues/473
> 
> 
> If you find a failure unrelated to your changes, please ask the test maintainer to review it.
> This will prevent the failures from being incorrectly reported in the future.
> 
> Please reply to this email if you have any questions about the tests that we
> ran or if you have any suggestions on how to make future tests more effective.

-- 
Catalin


From catalin.marinas at arm.com  Fri Mar  7 10:45:52 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 7 Mar 2025 18:45:52 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <20250228170006.390100-3-kristina.martsenko@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
Message-ID: <Z8s-4OPE2DNSogwB@arm.com>

On Fri, Feb 28, 2025 at 05:00:05PM +0000, Kristina Martsenko wrote:
> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> +				  unsigned long esr)
> +{
> +	switch (ex->type) {
> +	case EX_TYPE_UACCESS_CPY:
> +		return cpy_faulted_on_uaccess(ex, esr);
> +	default:
> +		return true;
> +	}
> +}

Not a problem with this patch but I wonder whether we should return
false for EX_TYPE_LOAD_UNALIGNED_ZEROPAD for completeness (and remove
the EX_TYPE_KACCESS_ERR_ZERO, it's no longer used.

-- 
Catalin


From jonas at kwiboo.se  Fri Mar  7 10:50:10 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Fri, 7 Mar 2025 19:50:10 +0100
Subject: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and
 php-grf during probe
In-Reply-To: <Z8s5ZZyTCpS9xHlA@shell.armlinux.org.uk>
References: <20250306210950.1686713-1-jonas@kwiboo.se>
 <20250306210950.1686713-3-jonas@kwiboo.se>
 <bab793bb-1cbe-4df6-ba6b-7ac8bfef989d@lunn.ch>
 <1dd9e663-561e-4d6c-b9d9-6ded22b9f81b@kwiboo.se>
 <20250307085558.5f8fcb90@kernel.org> <Z8s5ZZyTCpS9xHlA@shell.armlinux.org.uk>
Message-ID: <67294dfc-a816-4828-9e45-6a897c5710d5@kwiboo.se>

On 2025-03-07 19:22, Russell King (Oracle) wrote:
> On Fri, Mar 07, 2025 at 08:55:58AM -0800, Jakub Kicinski wrote:
>> On Fri, 7 Mar 2025 00:49:38 +0100 Jonas Karlman wrote:
>>> Subject: Re: [PATCH 2/2] net: stmmac: dwmac-rk: Validate rockchip,grf and php-grf during probe
>>>
>>> [encrypted.asc  application/octet-stream (3384 bytes)] 
>>
>> Is it just me or does anyone else get blobs from Jonas?
>> The list gets text, according to lore.
> 
> Looking at the emails I've received, some which were via the list, some
> which were direct, I don't see anything out of the ordinary - seems to
> just be text/plain here.
> 

I just learned that my outgoing email provider will automatically
attempt to PGP encrypt messages on a per-recipient basis using Web Key
Directory ("WKD"), and Jakub Kicinski seem to have an openpgpkey
published at [1].

Should I reach out to my outgoing email provider and ask if they can
disable the automatic encryption feature?

[1] https://kernel.org/.well-known/openpgpkey/hu/k5mqwn6xdasq745xgzbqu7eq3p5ysxjz?l=kuba

Regards,
Jonas


From robin.murphy at arm.com  Fri Mar  7 10:53:37 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 7 Mar 2025 18:53:37 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <Z8s-4OPE2DNSogwB@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
 <Z8s-4OPE2DNSogwB@arm.com>
Message-ID: <4c621070-688a-4a75-9134-ea19b6d20f04@arm.com>

On 2025-03-07 6:45 pm, Catalin Marinas wrote:
> On Fri, Feb 28, 2025 at 05:00:05PM +0000, Kristina Martsenko wrote:
>> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
>> +				  unsigned long esr)
>> +{
>> +	switch (ex->type) {
>> +	case EX_TYPE_UACCESS_CPY:
>> +		return cpy_faulted_on_uaccess(ex, esr);
>> +	default:
>> +		return true;
>> +	}
>> +}
> 
> Not a problem with this patch but I wonder whether we should return
> false for EX_TYPE_LOAD_UNALIGNED_ZEROPAD for completeness

Or maybe rather, true for EX_TYPE_UACCESS_ERR_ZERO and then false in the 
default case?

> (and remove
> the EX_TYPE_KACCESS_ERR_ZERO, it's no longer used. 

I think that's just hidden in the macro swamp of 
__get_mem_asm()/__put_mem_asm()...

Cheers,
Robin.


From sboyd at kernel.org  Fri Mar  7 11:04:23 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Fri, 07 Mar 2025 11:04:23 -0800
Subject: [PATCH RFC/RFT 00/12] clk: samsung: Use platform_driver_probe() to avoid __refdata
In-Reply-To: <01cdf3a68e120d30bdcf4fc225bb236dba47fdff.camel@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org> <01cdf3a68e120d30bdcf4fc225bb236dba47fdff.camel@linaro.org>
Message-ID: <725811bfa06a86f47a90f84ade2d1461.sboyd@kernel.org>

Quoting Andr? Draszik (2025-03-07 06:29:18)
> 
> I've tried this on top of next-20250225, and it doesn't work on gs101
> either and OOPSes several times during boot in different places, but
> I can not dig deeper right now.
> 
> [   11.502919][   T58] Unable to handle kernel paging request at virtual address ffffbfe2ab25cc30
> [   11.503128][   T58] Mem abort info:
> [   11.503202][   T58]   ESR = 0x0000000096000007
> [   11.503295][   T58]   EC = 0x25: DABT (current EL), IL = 32 bits
> [   11.503419][   T58]   SET = 0, FnV = 0
> [   11.503498][   T58]   EA = 0, S1PTW = 0
> [   11.503579][   T58]   FSC = 0x07: level 3 translation fault
> [   11.503695][   T58] Data abort info:
> [   11.503769][   T58]   ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000
> [   11.503896][   T58]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [   11.504058][   T58]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [   11.504288][   T58] swapper pgtable: 4k pages, 48-bit VAs, pgdp=000000008208c000
> [   11.504570][   T58] [ffffbfe2ab25cc30] pgd=0000000000000000, p4d=1000000082a58003, pud=1000000082a59003, pmd=1000000082a5d003,
> pte=0000000000000000
> [   11.505079][   T58] Internal error: Oops: 0000000096000007 [#1] PREEMPT SMP
> [   11.505346][   T58] Modules linked in:
> [   11.505495][   T58] CPU: 6 UID: 0 PID: 58 Comm: kworker/u32:1 Tainted: G                T  6.14.0-rc4-next-20250225+ #12
> [   11.505902][   T58] Tainted: [T]=RANDSTRUCT
> [   11.506061][   T58] Hardware name: Raven (DT)
> [   11.506230][   T58] Workqueue: events_unbound deferred_probe_work_func
> [   11.506477][   T58] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [   11.506768][   T58] pc : __device_attach_driver+0x18/0x254
> [   11.506978][   T58] lr : bus_for_each_drv+0xfc/0x154
> [   11.507168][   T58] sp : ffff8000803abc00
> [   11.507321][   T58] x29: ffff8000803abc10 x28: ffff00ed403363d0 x27: ffff00ed40336400
> [   11.507620][   T58] x26: 0000000000000000 x25: ffff00ed4002380d x24: ffff00ed40028000
> [   11.507919][   T58] x23: ffffbfe2aba26000 x22: 0000000000000000 x21: ffff00ed409f8400
> [   11.508219][   T58] x20: ffff8000803abca8 x19: ffffbfe2a9a4cf4c x18: 0000000000000040
> [   11.508518][   T58] x17: 0000000000000001 x16: 0000000000000001 x15: 0000000000000010
> [   11.508817][   T58] x14: 0000000000000010 x13: 0000000000000093 x12: 0000000000000002
> [   11.509117][   T58] x11: ffffffffff6070d2 x10: 0000bef56a420260 x9 : 0000000100000000
> [   11.509416][   T58] x8 : 0000000100000000 x7 : ff7f7f7f7f7f7f7f x6 : 455242436f53531d
> [   11.509715][   T58] x5 : 1d53536f43425245 x4 : 0000000000000000 x3 : e8c6e6e4bec6c65a
> [   11.510015][   T58] x2 : 0000000000000062 x1 : ffff8000803abca8 x0 : ffffbfe2ab25cc28
> [   11.510315][   T58] Call trace:
> [   11.510436][   T58]  __device_attach_driver+0x18/0x254 (P)
> [   11.510644][   T58]  bus_for_each_drv+0xfc/0x154
> [   11.510819][   T58]  __device_attach+0x100/0x1cc
> [   11.510996][   T58]  device_initial_probe+0x14/0x20
> [   11.511182][   T58]  bus_probe_device+0x94/0x100
> [   11.511359][   T58]  deferred_probe_work_func+0xa0/0xfc

platform_driver_probe() is incompatible with deferred probe. It
should have set drv->prevent_deferred_probe to true so the driver must
have gotten onto the deferred probe list somehow when it shouldn't have.


From catalin.marinas at arm.com  Fri Mar  7 11:23:33 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri,  7 Mar 2025 19:23:33 +0000
Subject: [PATCH v2 0/3] arm64: Use memory copy instructions in usercopy routines
In-Reply-To: <20250228170006.390100-1-kristina.martsenko@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
Message-ID: <174137535825.2374539.7217911399539478873.b4-ty@arm.com>

On Fri, 28 Feb 2025 17:00:03 +0000, Kristina Mart?enko wrote:
> This is a follow-up to the series using CPY/SET instructions in the kernel's
> memory copy routines [1]. This series extends that to the usercopy routines.
> This required some additions to exception fixups since a CPY instruction
> accesses both user and kernel memory.
> 
> Changes in v2:
>  - Improved readability of cpy_faulted_on_uaccess()
>  - v1: https://lore.kernel.org/all/20250218171430.28227-1-kristina.martsenko at arm.com/
> 
> [...]

Applied to arm64 (for-next/uaccess-mops), thanks!

I made some modifications to patch 2 as per Robin's suggestion.

[1/3] arm64: extable: Add fixup handling for uaccess CPY* instructions
      https://git.kernel.org/arm64/c/653884f88777
[2/3] arm64: mm: Handle PAN faults on uaccess CPY* instructions
      https://git.kernel.org/arm64/c/04a9f771d81c
[3/3] arm64: lib: Use MOPS for usercopy routines
      https://git.kernel.org/arm64/c/fe59e0358d9b

-- 
Catalin



From 21cnbao at gmail.com  Fri Mar  7 11:34:17 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Sat, 8 Mar 2025 08:34:17 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
Message-ID: <CAGsJ_4z4yKRQiqMtGRr2bjvgVY6mmujdqyKyVgid=RUXr_9TbQ@mail.gmail.com>

On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
>
> This patch series introduces a new mechanism called kcompressd to
> improve the efficiency of memory reclaiming in the operating system. The
> main goal is to separate the tasks of page scanning and page compression
> into distinct processes or threads, thereby reducing the load on the
> kswapd thread and enhancing overall system performance under high memory
> pressure conditions.
>
> Problem:
>  In the current system, the kswapd thread is responsible for both
>  scanning the LRU pages and compressing pages into the ZRAM. This
>  combined responsibility can lead to significant performance bottlenecks,
>  especially under high memory pressure. The kswapd thread becomes a
>  single point of contention, causing delays in memory reclaiming and
>  overall system performance degradation.
>
> Target:
>  The target of this invention is to improve the efficiency of memory
>  reclaiming. By separating the tasks of page scanning and page
>  compression into distinct processes or threads, the system can handle
>  memory pressure more effectively.

Sounds great. However, we also have a time window where folios under
writeback are kept, whereas previously, writeback was done synchronously
without your patch. This may temporarily increase memory usage until the
kept folios are re-scanned.

So, you?ve observed that folio_rotate_reclaimable() runs shortly while the
async thread completes compression? Then the kept folios are shortly
re-scanned?

>
> Patch 1:
> - Introduces 2 new feature flags, BLK_FEAT_READ_SYNCHRONOUS and
>   SWP_READ_SYNCHRONOUS_IO.
>
> Patch 2:
> - Implemented the core functionality of Kcompressd and made necessary
>   modifications to the zram driver to support it.
>
> In our handheld devices, we found that applying this mechanism under high
> memory pressure scenarios can increase the rate of pgsteal_anon per second
> by over 260% compared to the situation with only kswapd.

Sounds really great.

What compression algorithm is being used? I assume that after switching to a
different compression algorithms, the benefits will change significantly. For
example, Zstd might not show as much improvement.
How was the CPU usage ratio between page scan/unmap and compression
observed before applying this patch?

>
> Qun-Wei Lin (2):
>   mm: Split BLK_FEAT_SYNCHRONOUS and SWP_SYNCHRONOUS_IO into separate
>     read and write flags
>   kcompressd: Add Kcompressd for accelerated zram compression
>
>  drivers/block/brd.c             |   3 +-
>  drivers/block/zram/Kconfig      |  11 ++
>  drivers/block/zram/Makefile     |   3 +-
>  drivers/block/zram/kcompressd.c | 340 ++++++++++++++++++++++++++++++++
>  drivers/block/zram/kcompressd.h |  25 +++
>  drivers/block/zram/zram_drv.c   |  21 +-
>  drivers/nvdimm/btt.c            |   3 +-
>  drivers/nvdimm/pmem.c           |   5 +-
>  include/linux/blkdev.h          |  24 ++-
>  include/linux/swap.h            |  31 +--
>  mm/memory.c                     |   4 +-
>  mm/page_io.c                    |   6 +-
>  mm/swapfile.c                   |   7 +-
>  13 files changed, 446 insertions(+), 37 deletions(-)
>  create mode 100644 drivers/block/zram/kcompressd.c
>  create mode 100644 drivers/block/zram/kcompressd.h
>
> --
> 2.45.2
>

Thanks
Barry


From nunodasneves at linux.microsoft.com  Fri Mar  7 11:38:23 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 11:38:23 -0800
Subject: [PATCH v5 01/10] hyperv: Convert Hyper-V status codes to strings
In-Reply-To: <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-2-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB41577560030C55503D1BAFDCD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <44f2032c-557d-4b11-aab8-1dd93646b05f@linux.microsoft.com>

On 3/6/2025 9:57 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
>> Introduce hv_result_to_string() for this purpose. This allows
>> hypercall failures to be debugged more easily with dmesg.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> ---
>>  drivers/hv/hv_common.c         | 65 ++++++++++++++++++++++++++++++++++
>>  drivers/hv/hv_proc.c           | 13 ++++---
>>  include/asm-generic/mshyperv.h |  1 +
>>  3 files changed, 74 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>> index 9804adb4cc56..ce20818688fe 100644
>> --- a/drivers/hv/hv_common.c
>> +++ b/drivers/hv/hv_common.c
>> @@ -740,3 +740,68 @@ void hv_identify_partition_type(void)
>>  			pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
>>  	}
>>  }
>> +
>> +const char *hv_result_to_string(u64 hv_status)
>> +{
>> +	switch (hv_result(hv_status)) {
>> +	case HV_STATUS_SUCCESS:
>> +		return "HV_STATUS_SUCCESS";
>> +	case HV_STATUS_INVALID_HYPERCALL_CODE:
>> +		return "HV_STATUS_INVALID_HYPERCALL_CODE";
>> +	case HV_STATUS_INVALID_HYPERCALL_INPUT:
>> +		return "HV_STATUS_INVALID_HYPERCALL_INPUT";
>> +	case HV_STATUS_INVALID_ALIGNMENT:
>> +		return "HV_STATUS_INVALID_ALIGNMENT";
>> +	case HV_STATUS_INVALID_PARAMETER:
>> +		return "HV_STATUS_INVALID_PARAMETER";
>> +	case HV_STATUS_ACCESS_DENIED:
>> +		return "HV_STATUS_ACCESS_DENIED";
>> +	case HV_STATUS_INVALID_PARTITION_STATE:
>> +		return "HV_STATUS_INVALID_PARTITION_STATE";
>> +	case HV_STATUS_OPERATION_DENIED:
>> +		return "HV_STATUS_OPERATION_DENIED";
>> +	case HV_STATUS_UNKNOWN_PROPERTY:
>> +		return "HV_STATUS_UNKNOWN_PROPERTY";
>> +	case HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE:
>> +		return "HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE";
>> +	case HV_STATUS_INSUFFICIENT_MEMORY:
>> +		return "HV_STATUS_INSUFFICIENT_MEMORY";
>> +	case HV_STATUS_INVALID_PARTITION_ID:
>> +		return "HV_STATUS_INVALID_PARTITION_ID";
>> +	case HV_STATUS_INVALID_VP_INDEX:
>> +		return "HV_STATUS_INVALID_VP_INDEX";
>> +	case HV_STATUS_NOT_FOUND:
>> +		return "HV_STATUS_NOT_FOUND";
>> +	case HV_STATUS_INVALID_PORT_ID:
>> +		return "HV_STATUS_INVALID_PORT_ID";
>> +	case HV_STATUS_INVALID_CONNECTION_ID:
>> +		return "HV_STATUS_INVALID_CONNECTION_ID";
>> +	case HV_STATUS_INSUFFICIENT_BUFFERS:
>> +		return "HV_STATUS_INSUFFICIENT_BUFFERS";
>> +	case HV_STATUS_NOT_ACKNOWLEDGED:
>> +		return "HV_STATUS_NOT_ACKNOWLEDGED";
>> +	case HV_STATUS_INVALID_VP_STATE:
>> +		return "HV_STATUS_INVALID_VP_STATE";
>> +	case HV_STATUS_NO_RESOURCES:
>> +		return "HV_STATUS_NO_RESOURCES";
>> +	case HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED:
>> +		return "HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED";
>> +	case HV_STATUS_INVALID_LP_INDEX:
>> +		return "HV_STATUS_INVALID_LP_INDEX";
>> +	case HV_STATUS_INVALID_REGISTER_VALUE:
>> +		return "HV_STATUS_INVALID_REGISTER_VALUE";
>> +	case HV_STATUS_OPERATION_FAILED:
>> +		return "HV_STATUS_OPERATION_FAILED";
>> +	case HV_STATUS_TIME_OUT:
>> +		return "HV_STATUS_TIME_OUT";
>> +	case HV_STATUS_CALL_PENDING:
>> +		return "HV_STATUS_CALL_PENDING";
>> +	case HV_STATUS_VTL_ALREADY_ENABLED:
>> +		return "HV_STATUS_VTL_ALREADY_ENABLED";
>> +	default:
>> +		return "Unknown";
>> +	};
>> +	return "Unknown";
>> +}
>> +EXPORT_SYMBOL_GPL(hv_result_to_string);
>> +
>> diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
>> index 2fae18e4f7d2..8fc30f509fa7 100644
>> --- a/drivers/hv/hv_proc.c
>> +++ b/drivers/hv/hv_proc.c
>> @@ -87,7 +87,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32
>> num_pages)
>>  				     page_count, 0, input_page, NULL);
>>  	local_irq_restore(flags);
>>  	if (!hv_result_success(status)) {
>> -		pr_err("Failed to deposit pages: %lld\n", status);
>> +		pr_err("%s: Failed to deposit pages: %s\n", __func__,
>> +		       hv_result_to_string(status));
>>  		ret = hv_result_to_errno(status);
>>  		goto err_free_allocations;
>>  	}
>> @@ -137,8 +138,9 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
>>
>>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>>  			if (!hv_result_success(status)) {
>> -				pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
>> -				       lp_index, apic_id, status);
>> +				pr_err("%s: cpu %u apic ID %u, %s\n",
>> +				       __func__, lp_index, apic_id,
>> +				       hv_result_to_string(status));
>>  				ret = hv_result_to_errno(status);
>>  			}
>>  			break;
>> @@ -179,8 +181,9 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index,
>> u32 flags)
>>
>>  		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
>>  			if (!hv_result_success(status)) {
>> -				pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
>> -				       vp_index, flags, status);
>> +				pr_err("%s: vcpu %u, lp %u, %s\n",
>> +				       __func__, vp_index, flags,
>> +				       hv_result_to_string(status));
>>  				ret = hv_result_to_errno(status);
>>  			}
>>  			break;
>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>> index b13b0cda4ac8..dc4729dba9ef 100644
>> --- a/include/asm-generic/mshyperv.h
>> +++ b/include/asm-generic/mshyperv.h
>> @@ -298,6 +298,7 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
>>  	return __cpumask_to_vpset(vpset, cpus, func);
>>  }
>>
>> +const char *hv_result_to_string(u64 hv_status);
>>  int hv_result_to_errno(u64 status);
>>  void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
>>  bool hv_is_hyperv_initialized(void);
>> --
>> 2.34.1
> 
> I've read through the other comments on this patch. I definitely vote
> for outputting both the hex code along with a string translation, which
> could be empty if the hex code is unrecognized by the translation code.
> 
> I can see providing something like hv_hvcall_err() as Nuno proposed, since
> that standardizes the text output. But I wonder if it would be too limiting.
> For example, in the changes above, both hv_call_add_logical_proc() and
> hv_call_create_vp() output additional debugging values, which we probably
> don't want to give up.
> 

Good point - that is easy though, I'll add a __VA_ARGS__ to the macro so any
custom message can be printed alongside the other info.

> Lastly, from an implementation standpoint, rather than using a big
> switch statement, build a static array of entries that each have the
> hex code and string equivalent. Then hv_result_to_string() loops through
> the array looking for a match. This won't be any slower than the big switch
> statement. I've seen other places in the kernel where string names are
> output, and looking up the strings in a static array is the typical approach.
> You'll have to work through the details and see if avoids being too clumsy,
> but I think it will be OK.

I'll try it out, agree the perf difference probably won't be significant or
even matter much.

Thanks
Nuno

> 
> Michael



From 21cnbao at gmail.com  Fri Mar  7 11:41:17 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Sat, 8 Mar 2025 08:41:17 +1300
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com> <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
Message-ID: <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>

On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
>
> Introduced Kcompressd to offload zram page compression, improving
> system efficiency by handling compression separately from memory
> reclaiming. Added necessary configurations and dependencies.
>
> Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> ---
>  drivers/block/zram/Kconfig      |  11 ++
>  drivers/block/zram/Makefile     |   3 +-
>  drivers/block/zram/kcompressd.c | 340 ++++++++++++++++++++++++++++++++
>  drivers/block/zram/kcompressd.h |  25 +++
>  drivers/block/zram/zram_drv.c   |  22 ++-
>  5 files changed, 397 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/block/zram/kcompressd.c
>  create mode 100644 drivers/block/zram/kcompressd.h
>
> diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
> index 402b7b175863..f0a1b574f770 100644
> --- a/drivers/block/zram/Kconfig
> +++ b/drivers/block/zram/Kconfig
> @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
>           re-compress pages using a potentially slower but more effective
>           compression algorithm. Note, that IDLE page recompression
>           requires ZRAM_TRACK_ENTRY_ACTIME.
> +
> +config KCOMPRESSD
> +       tristate "Kcompressd: Accelerated zram compression"
> +       depends on ZRAM
> +       help
> +         Kcompressd creates multiple daemons to accelerate the compression of pages
> +         in zram, offloading this time-consuming task from the zram driver.
> +
> +         This approach improves system efficiency by handling page compression separately,
> +         which was originally done by kswapd or direct reclaim.

For direct reclaim, we were previously able to compress using multiple CPUs
with multi-threading.
After your patch, it seems that only a single thread/CPU is used for compression
so it won't necessarily improve direct reclaim performance?

Even for kswapd, we used to have multiple threads like [kswapd0], [kswapd1],
and [kswapd2] for different nodes. Now, are we also limited to just one thread?
I also wonder if this could be handled at the vmscan level instead of the zram
level. then it might potentially help other sync devices or even zswap later.

But I agree that for phones, modifying zram seems like an easier starting
point. However, relying on a single thread isn't always the best approach.


> +
> diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
> index 0fdefd576691..23baa5dfceb9 100644
> --- a/drivers/block/zram/Makefile
> +++ b/drivers/block/zram/Makefile
> @@ -9,4 +9,5 @@ zram-$(CONFIG_ZRAM_BACKEND_ZSTD)        += backend_zstd.o
>  zram-$(CONFIG_ZRAM_BACKEND_DEFLATE)    += backend_deflate.o
>  zram-$(CONFIG_ZRAM_BACKEND_842)                += backend_842.o
>
> -obj-$(CONFIG_ZRAM)     +=      zram.o
> +obj-$(CONFIG_ZRAM)             += zram.o
> +obj-$(CONFIG_KCOMPRESSD)       += kcompressd.o
> diff --git a/drivers/block/zram/kcompressd.c b/drivers/block/zram/kcompressd.c
> new file mode 100644
> index 000000000000..195b7e386869
> --- /dev/null
> +++ b/drivers/block/zram/kcompressd.c
> @@ -0,0 +1,340 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2024 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/bio.h>
> +#include <linux/bitops.h>
> +#include <linux/freezer.h>
> +#include <linux/kernel.h>
> +#include <linux/psi.h>
> +#include <linux/kfifo.h>
> +#include <linux/swap.h>
> +#include <linux/delay.h>
> +
> +#include "kcompressd.h"
> +
> +#define INIT_QUEUE_SIZE                4096
> +#define DEFAULT_NR_KCOMPRESSD  4
> +
> +static atomic_t enable_kcompressd;
> +static unsigned int nr_kcompressd;
> +static unsigned int queue_size_per_kcompressd;
> +static struct kcompress *kcompress;
> +
> +enum run_state {
> +       KCOMPRESSD_NOT_STARTED = 0,
> +       KCOMPRESSD_RUNNING,
> +       KCOMPRESSD_SLEEPING,
> +};
> +
> +struct kcompressd_para {
> +       wait_queue_head_t *kcompressd_wait;
> +       struct kfifo *write_fifo;
> +       atomic_t *running;
> +};
> +
> +static struct kcompressd_para *kcompressd_para;
> +static BLOCKING_NOTIFIER_HEAD(kcompressd_notifier_list);
> +
> +struct write_work {
> +       void *mem;
> +       struct bio *bio;
> +       compress_callback cb;
> +};
> +
> +int kcompressd_enabled(void)
> +{
> +       return likely(atomic_read(&enable_kcompressd));
> +}
> +EXPORT_SYMBOL(kcompressd_enabled);
> +
> +static void kcompressd_try_to_sleep(struct kcompressd_para *p)
> +{
> +       DEFINE_WAIT(wait);
> +
> +       if (!kfifo_is_empty(p->write_fifo))
> +               return;
> +
> +       if (freezing(current) || kthread_should_stop())
> +               return;
> +
> +       atomic_set(p->running, KCOMPRESSD_SLEEPING);
> +       prepare_to_wait(p->kcompressd_wait, &wait, TASK_INTERRUPTIBLE);
> +
> +       /*
> +        * After a short sleep, check if it was a premature sleep. If not, then
> +        * go fully to sleep until explicitly woken up.
> +        */
> +       if (!kthread_should_stop() && kfifo_is_empty(p->write_fifo))
> +               schedule();
> +
> +       finish_wait(p->kcompressd_wait, &wait);
> +       atomic_set(p->running, KCOMPRESSD_RUNNING);
> +}
> +
> +static int kcompressd(void *para)
> +{
> +       struct task_struct *tsk = current;
> +       struct kcompressd_para *p = (struct kcompressd_para *)para;
> +
> +       tsk->flags |= PF_MEMALLOC | PF_KSWAPD;
> +       set_freezable();
> +
> +       while (!kthread_should_stop()) {
> +               bool ret;
> +
> +               kcompressd_try_to_sleep(p);
> +               ret = try_to_freeze();
> +               if (kthread_should_stop())
> +                       break;
> +
> +               if (ret)
> +                       continue;
> +
> +               while (!kfifo_is_empty(p->write_fifo)) {
> +                       struct write_work entry;
> +
> +                       if (sizeof(struct write_work) == kfifo_out(p->write_fifo,
> +                                               &entry, sizeof(struct write_work))) {
> +                               entry.cb(entry.mem, entry.bio);
> +                               bio_put(entry.bio);
> +                       }
> +               }
> +
> +       }
> +
> +       tsk->flags &= ~(PF_MEMALLOC | PF_KSWAPD);
> +       atomic_set(p->running, KCOMPRESSD_NOT_STARTED);
> +       return 0;
> +}
> +
> +static int init_write_queue(void)
> +{
> +       int i;
> +       unsigned int queue_len = queue_size_per_kcompressd * sizeof(struct write_work);
> +
> +       for (i = 0; i < nr_kcompressd; i++) {
> +               if (kfifo_alloc(&kcompress[i].write_fifo,
> +                                       queue_len, GFP_KERNEL)) {
> +                       pr_err("Failed to alloc kfifo %d\n", i);
> +                       return -ENOMEM;
> +               }
> +       }
> +       return 0;
> +}
> +
> +static void clean_bio_queue(int idx)
> +{
> +       struct write_work entry;
> +
> +       while (sizeof(struct write_work) == kfifo_out(&kcompress[idx].write_fifo,
> +                               &entry, sizeof(struct write_work))) {
> +               bio_put(entry.bio);
> +               entry.cb(entry.mem, entry.bio);
> +       }
> +       kfifo_free(&kcompress[idx].write_fifo);
> +}
> +
> +static int kcompress_update(void)
> +{
> +       int i;
> +       int ret;
> +
> +       kcompress = kvmalloc_array(nr_kcompressd, sizeof(struct kcompress), GFP_KERNEL);
> +       if (!kcompress)
> +               return -ENOMEM;
> +
> +       kcompressd_para = kvmalloc_array(nr_kcompressd, sizeof(struct kcompressd_para), GFP_KERNEL);
> +       if (!kcompressd_para)
> +               return -ENOMEM;
> +
> +       ret = init_write_queue();
> +       if (ret) {
> +               pr_err("Initialization of writing to FIFOs failed!!\n");
> +               return ret;
> +       }
> +
> +       for (i = 0; i < nr_kcompressd; i++) {
> +               init_waitqueue_head(&kcompress[i].kcompressd_wait);
> +               kcompressd_para[i].kcompressd_wait = &kcompress[i].kcompressd_wait;
> +               kcompressd_para[i].write_fifo = &kcompress[i].write_fifo;
> +               kcompressd_para[i].running = &kcompress[i].running;
> +       }
> +
> +       return 0;
> +}
> +
> +static void stop_all_kcompressd_thread(void)
> +{
> +       int i;
> +
> +       for (i = 0; i < nr_kcompressd; i++) {
> +               kthread_stop(kcompress[i].kcompressd);
> +               kcompress[i].kcompressd = NULL;
> +               clean_bio_queue(i);
> +       }
> +}
> +
> +static int do_nr_kcompressd_handler(const char *val,
> +               const struct kernel_param *kp)
> +{
> +       int ret;
> +
> +       atomic_set(&enable_kcompressd, false);
> +
> +       stop_all_kcompressd_thread();
> +
> +       ret = param_set_int(val, kp);
> +       if (!ret) {
> +               pr_err("Invalid number of kcompressd.\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = init_write_queue();
> +       if (ret) {
> +               pr_err("Initialization of writing to FIFOs failed!!\n");
> +               return ret;
> +       }
> +
> +       atomic_set(&enable_kcompressd, true);
> +
> +       return 0;
> +}
> +
> +static const struct kernel_param_ops param_ops_change_nr_kcompressd = {
> +       .set = &do_nr_kcompressd_handler,
> +       .get = &param_get_uint,
> +       .free = NULL,
> +};
> +
> +module_param_cb(nr_kcompressd, &param_ops_change_nr_kcompressd,
> +               &nr_kcompressd, 0644);
> +MODULE_PARM_DESC(nr_kcompressd, "Number of pre-created daemon for page compression");
> +
> +static int do_queue_size_per_kcompressd_handler(const char *val,
> +               const struct kernel_param *kp)
> +{
> +       int ret;
> +
> +       atomic_set(&enable_kcompressd, false);
> +
> +       stop_all_kcompressd_thread();
> +
> +       ret = param_set_int(val, kp);
> +       if (!ret) {
> +               pr_err("Invalid queue size for kcompressd.\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = init_write_queue();
> +       if (ret) {
> +               pr_err("Initialization of writing to FIFOs failed!!\n");
> +               return ret;
> +       }
> +
> +       pr_info("Queue size for kcompressd was changed: %d\n", queue_size_per_kcompressd);
> +
> +       atomic_set(&enable_kcompressd, true);
> +       return 0;
> +}
> +
> +static const struct kernel_param_ops param_ops_change_queue_size_per_kcompressd = {
> +       .set = &do_queue_size_per_kcompressd_handler,
> +       .get = &param_get_uint,
> +       .free = NULL,
> +};
> +
> +module_param_cb(queue_size_per_kcompressd, &param_ops_change_queue_size_per_kcompressd,
> +               &queue_size_per_kcompressd, 0644);
> +MODULE_PARM_DESC(queue_size_per_kcompressd,
> +               "Size of queue for kcompressd");
> +
> +int schedule_bio_write(void *mem, struct bio *bio, compress_callback cb)
> +{
> +       int i;
> +       bool submit_success = false;
> +       size_t sz_work = sizeof(struct write_work);
> +
> +       struct write_work entry = {
> +               .mem = mem,
> +               .bio = bio,
> +               .cb = cb
> +       };
> +
> +       if (unlikely(!atomic_read(&enable_kcompressd)))
> +               return -EBUSY;
> +
> +       if (!nr_kcompressd || !current_is_kswapd())
> +               return -EBUSY;
> +
> +       bio_get(bio);
> +
> +       for (i = 0; i < nr_kcompressd; i++) {
> +               submit_success =
> +                       (kfifo_avail(&kcompress[i].write_fifo) >= sz_work) &&
> +                       (sz_work == kfifo_in(&kcompress[i].write_fifo, &entry, sz_work));
> +
> +               if (submit_success) {
> +                       switch (atomic_read(&kcompress[i].running)) {
> +                       case KCOMPRESSD_NOT_STARTED:
> +                               atomic_set(&kcompress[i].running, KCOMPRESSD_RUNNING);
> +                               kcompress[i].kcompressd = kthread_run(kcompressd,
> +                                               &kcompressd_para[i], "kcompressd:%d", i);
> +                               if (IS_ERR(kcompress[i].kcompressd)) {
> +                                       atomic_set(&kcompress[i].running, KCOMPRESSD_NOT_STARTED);
> +                                       pr_warn("Failed to start kcompressd:%d\n", i);
> +                                       clean_bio_queue(i);
> +                               }
> +                               break;
> +                       case KCOMPRESSD_RUNNING:
> +                               break;
> +                       case KCOMPRESSD_SLEEPING:
> +                               wake_up_interruptible(&kcompress[i].kcompressd_wait);
> +                               break;
> +                       }
> +                       return 0;
> +               }
> +       }
> +
> +       bio_put(bio);
> +       return -EBUSY;
> +}
> +EXPORT_SYMBOL(schedule_bio_write);
> +
> +static int __init kcompressd_init(void)
> +{
> +       int ret;
> +
> +       nr_kcompressd = DEFAULT_NR_KCOMPRESSD;
> +       queue_size_per_kcompressd = INIT_QUEUE_SIZE;
> +
> +       ret = kcompress_update();
> +       if (ret) {
> +               pr_err("Init kcompressd failed!\n");
> +               return ret;
> +       }
> +
> +       atomic_set(&enable_kcompressd, true);
> +       blocking_notifier_call_chain(&kcompressd_notifier_list, 0, NULL);
> +       return 0;
> +}
> +
> +static void __exit kcompressd_exit(void)
> +{
> +       atomic_set(&enable_kcompressd, false);
> +       stop_all_kcompressd_thread();
> +
> +       kvfree(kcompress);
> +       kvfree(kcompressd_para);
> +}
> +
> +module_init(kcompressd_init);
> +module_exit(kcompressd_exit);
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_AUTHOR("Qun-Wei Lin <qun-wei.lin at mediatek.com>");
> +MODULE_DESCRIPTION("Separate the page compression from the memory reclaiming");
> +
> diff --git a/drivers/block/zram/kcompressd.h b/drivers/block/zram/kcompressd.h
> new file mode 100644
> index 000000000000..2fe0b424a7af
> --- /dev/null
> +++ b/drivers/block/zram/kcompressd.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2024 MediaTek Inc.
> + */
> +
> +#ifndef _KCOMPRESSD_H_
> +#define _KCOMPRESSD_H_
> +
> +#include <linux/rwsem.h>
> +#include <linux/kfifo.h>
> +#include <linux/atomic.h>
> +
> +typedef void (*compress_callback)(void *mem, struct bio *bio);
> +
> +struct kcompress {
> +       struct task_struct *kcompressd;
> +       wait_queue_head_t kcompressd_wait;
> +       struct kfifo write_fifo;
> +       atomic_t running;
> +};
> +
> +int kcompressd_enabled(void);
> +int schedule_bio_write(void *mem, struct bio *bio, compress_callback cb);
> +#endif
> +
> diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> index 2e1a70f2f4bd..bcd63ecb6ff2 100644
> --- a/drivers/block/zram/zram_drv.c
> +++ b/drivers/block/zram/zram_drv.c
> @@ -35,6 +35,7 @@
>  #include <linux/part_stat.h>
>  #include <linux/kernel_read_file.h>
>
> +#include "kcompressd.h"
>  #include "zram_drv.h"
>
>  static DEFINE_IDR(zram_index_idr);
> @@ -2240,6 +2241,15 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
>         bio_endio(bio);
>  }
>
> +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> +static void zram_bio_write_callback(void *mem, struct bio *bio)
> +{
> +       struct zram *zram = (struct zram *)mem;
> +
> +       zram_bio_write(zram, bio);
> +}
> +#endif
> +
>  /*
>   * Handler function for all zram I/O requests.
>   */
> @@ -2252,6 +2262,10 @@ static void zram_submit_bio(struct bio *bio)
>                 zram_bio_read(zram, bio);
>                 break;
>         case REQ_OP_WRITE:
> +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> +               if (kcompressd_enabled() && !schedule_bio_write(zram, bio, zram_bio_write_callback))
> +                       break;
> +#endif
>                 zram_bio_write(zram, bio);
>                 break;
>         case REQ_OP_DISCARD:
> @@ -2535,9 +2549,11 @@ static int zram_add(void)
>  #if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
>                 .max_write_zeroes_sectors       = UINT_MAX,
>  #endif
> -               .features                       = BLK_FEAT_STABLE_WRITES        |
> -                                                 BLK_FEAT_READ_SYNCHRONOUS     |
> -                                                 BLK_FEAT_WRITE_SYNCHRONOUS,
> +               .features                       = BLK_FEAT_STABLE_WRITES
> +                                                 | BLK_FEAT_READ_SYNCHRONOUS
> +#if !IS_ENABLED(CONFIG_KCOMPRESSD)
> +                                                 | BLK_FEAT_WRITE_SYNCHRONOUS,
> +#endif
>         };
>         struct zram *zram;
>         int ret, device_id;
> --
> 2.45.2
>

Thanks
Barry


From nm at ti.com  Fri Mar  7 11:47:17 2025
From: nm at ti.com (Nishanth Menon)
Date: Fri, 7 Mar 2025 13:47:17 -0600
Subject: [PATCH net-next v3 00/10] PRU-ICSSM Ethernet Driver
In-Reply-To: <1229872038.768025.1741268586173.JavaMail.zimbra@couthit.local>
References: <20250214054702.1073139-1-parvathi@couthit.com>
 <20250226184408.d4gpr3uu2dm7oxa2@handwork>
 <506678778.717678.1740740287558.JavaMail.zimbra@couthit.local>
 <1229872038.768025.1741268586173.JavaMail.zimbra@couthit.local>
Message-ID: <20250307194717.isd2yv5qvuwe6jgp@strongly>

On 19:13-20250306, Parvathi Pudi wrote:
> Hi,
> 
> >> On 11:16-20250214, parvathi wrote:
> >> [...]
> >>> The patches presented in this series have gone through the patch verification
> >>> tools and no warnings or errors are reported. Sample test logs verifying the
> >>> functionality on Linux next kernel are available here:
> >>> 
> >>> [Interface up
> >>> Testing](https://gist.github.com/ParvathiPudi/f481837cc6994e400284cb4b58972804)
> >>> 
> >>> [Ping
> >>> Testing](https://gist.github.com/ParvathiPudi/a121aad402defcef389e93f303d79317)
> >>> 
> >>> [Iperf
> >>> Testing](https://gist.github.com/ParvathiPudi/581db46b0e9814ddb5903bdfee73fc6f)
> >>> 
> >> 
> >> 
> >> I am looking at
> >> https://lore.kernel.org/all/20250214085315.1077108-11-parvathi at couthit.com/
> >> and wondering if i can see the test log for am335x and am47xx to make
> >> sure that PRUs are functional on those two?
> >> 
> > 
> > In this patch series we have added support for PRU-ICSS on the AM57x SOC.
> > Hence the test log was only included for the AM57x SOC. We are working in
> > parallel
> > to add support for PRU-ICSS on the AM33x and AM43x SOC's as well. We will send
> > it as
> > a separate patch series at a later time.
> > 
> 
> Further update:
> 
> We have successfully cross compiled the kernel (linux-next) with this patch series
> for AM335x and AM437x SOC respectively.
> 
> Kernel is booting well on both the SOCs and we have verified PRU functionality by
> loading simple example application (pru_addition.elf) on the PRU cores, by using
> "remoteproc" driver from mainline kernel.
> 
> Below are the logs for the SOCs with boot log and running PRU with elf file specified
> above:
> 
> AM335x test log: <https://gist.github.com/ParvathiPudi/87d7ddf949913b80f022ed99706337ac>
> AM437x test log: <https://gist.github.com/ParvathiPudi/b2d556829cb4a9e3b6b4c5656dbdd594>


Thanks for testing this, I just got some time to dig further, I will
respond on the standalone patch
https://lore.kernel.org/all/20250108125937.10604-2-basharath at couthit.com/

-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D


From jgg at nvidia.com  Fri Mar  7 12:03:48 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Fri, 7 Mar 2025 16:03:48 -0400
Subject: [PATCH] iommufd: Set domain->iommufd_hwpt in all hwpt->domain
 allocators
In-Reply-To: <20250305211800.229465-1-nicolinc@nvidia.com>
References: <20250305211800.229465-1-nicolinc@nvidia.com>
Message-ID: <20250307200348.GV354511@nvidia.com>

On Wed, Mar 05, 2025 at 01:18:00PM -0800, Nicolin Chen wrote:
> Setting domain->iommufd_hwpt in iommufd_hwpt_alloc() only covers the HWPT
> allocations from user space, but not for an auto domain. This resulted in
> a NULL pointer access in the auto domain pathway:
>  Unable to handle kernel NULL pointer dereference at
>  	virtual address 0000000000000008
>  pc : iommufd_sw_msi+0x54/0x2b0
>  lr : iommufd_sw_msi+0x40/0x2b0
>  Call trace:
>   iommufd_sw_msi+0x54/0x2b0 (P)
>   iommu_dma_prepare_msi+0x64/0xa8
>   its_irq_domain_alloc+0xf0/0x2c0
>   irq_domain_alloc_irqs_parent+0x2c/0xa8
>   msi_domain_alloc+0xa0/0x1a8
> 
> Since iommufd_sw_msi() requires to access the domain->iommufd_hwpt, it is
> better to set that explicitly prior to calling iommu_domain_set_sw_msi().
> 
> Fixes: 748706d7ca06 ("iommu: Turn fault_data to iommufd private pointer")
> Reported-by: Ankit Agrawal <ankita at nvidia.com>
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/iommufd/hw_pagetable.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Applied thanks

Jason


From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:07:46 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:07:46 +0100
Subject: [PATCH v3 2/2] iommu: apple-dart: Allow mismatched bypass support
In-Reply-To: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
References: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
Message-ID: <20250307-isp-dart-v3-2-684fe4489591@gmail.com>

From: Hector Martin <marcan at marcan.st>

This is needed by ISP, which has DART0 with bypass and DART1/2 without.

Signed-off-by: Hector Martin <marcan at marcan.st>
Reviewed-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 drivers/iommu/apple-dart.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index edb2fb22333506d7c64ad1b6321df00ebfd07747..13ccb801f52a4d34f6653f78e92787af7dfed1bc 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -277,6 +277,9 @@ struct apple_dart_domain {
  * @streams: streams for this device
  */
 struct apple_dart_master_cfg {
+	/* Intersection of DART capabilitles */
+	u32 supports_bypass : 1;
+
 	struct apple_dart_stream_map stream_maps[MAX_DARTS_PER_DEVICE];
 };
 
@@ -684,7 +687,7 @@ static int apple_dart_attach_dev_identity(struct iommu_domain *domain,
 	struct apple_dart_stream_map *stream_map;
 	int i;
 
-	if (!cfg->stream_maps[0].dart->supports_bypass)
+	if (!cfg->supports_bypass)
 		return -EINVAL;
 
 	for_each_stream_map(i, cfg, stream_map)
@@ -792,20 +795,24 @@ static int apple_dart_of_xlate(struct device *dev,
 		return -EINVAL;
 	sid = args->args[0];
 
-	if (!cfg)
+	if (!cfg) {
 		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+
+		/* Will be ANDed with DART capabilities */
+		cfg->supports_bypass = true;
+	}
 	if (!cfg)
 		return -ENOMEM;
 	dev_iommu_priv_set(dev, cfg);
 
 	cfg_dart = cfg->stream_maps[0].dart;
 	if (cfg_dart) {
-		if (cfg_dart->supports_bypass != dart->supports_bypass)
-			return -EINVAL;
 		if (cfg_dart->pgsize != dart->pgsize)
 			return -EINVAL;
 	}
 
+	cfg->supports_bypass &= dart->supports_bypass;
+
 	for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
 		if (cfg->stream_maps[i].dart == dart) {
 			set_bit(sid, cfg->stream_maps[i].sidmap);
@@ -945,7 +952,7 @@ static int apple_dart_def_domain_type(struct device *dev)
 
 	if (cfg->stream_maps[0].dart->pgsize > PAGE_SIZE)
 		return IOMMU_DOMAIN_IDENTITY;
-	if (!cfg->stream_maps[0].dart->supports_bypass)
+	if (!cfg->supports_bypass)
 		return IOMMU_DOMAIN_DMA;
 
 	return 0;

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:08:58 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:08:58 +0100
Subject: [PATCH v2 0/3] Driver for the Apple SPMI controller
Message-ID: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>

Hi.

This patch series adds support for the SPMI controller persent in most
Apple SoCs. The drivers for the attached PMU and subdevices will be in
further patch series.

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
Changes in v2:
- Removed redundant error prints
- Various style fixes
- Better explanation of why the driver is needed
- Link to v1: https://lore.kernel.org/r/20250305-spmi-v1-0-c98f561fa99f at gmail.com

---
Jean-Francois Bortolotti (1):
      spmi: add a spmi driver for Apple SoC

Sasha Finkelstein (2):
      dt-bindings: spmi: Add Apple SPMI controller
      arm64: dts: apple: Add SPMI controller nodes

 .../devicetree/bindings/spmi/apple,spmi.yaml       |  49 ++++++
 MAINTAINERS                                        |   2 +
 arch/arm64/boot/dts/apple/t600x-die0.dtsi          |   7 +
 arch/arm64/boot/dts/apple/t8103.dtsi               |   8 +
 arch/arm64/boot/dts/apple/t8112.dtsi               |   7 +
 drivers/spmi/Kconfig                               |   8 +
 drivers/spmi/Makefile                              |   1 +
 drivers/spmi/spmi-apple-controller.c               | 178 +++++++++++++++++++++
 8 files changed, 260 insertions(+)
---
base-commit: 48a5eed9ad584315c30ed35204510536235ce402
change-id: 20250304-spmi-6d3c24b9027a




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:09:00 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:09:00 +0100
Subject: [PATCH v2 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
Message-ID: <20250307-spmi-v2-2-eccdb06afb99@gmail.com>

From: Jean-Francois Bortolotti <jeff at borto.fr>

The connected PMU contains several useful nvmem cells such as RTC offset,
boot failure counters, reboot/shutdown selector, and a few others.
In addition M3+ machines have their USB-PD controller connected via SPMI.

Signed-off-by: Jean-Francois Bortolotti <jeff at borto.fr>
Co-developed-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 MAINTAINERS                          |   1 +
 drivers/spmi/Kconfig                 |   8 ++
 drivers/spmi/Makefile                |   1 +
 drivers/spmi/spmi-apple-controller.c | 178 +++++++++++++++++++++++++++++++++++
 4 files changed, 188 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 271ff8110df83c2d4fe7fbbfffc0a72259460bc5..9006695261d29fbc1e15659c2b43d7afeee0b656 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2254,6 +2254,7 @@ F:	drivers/nvmem/apple-efuses.c
 F:	drivers/pinctrl/pinctrl-apple-gpio.c
 F:	drivers/pwm/pwm-apple.c
 F:	drivers/soc/apple/*
+F:	drivers/spmi/spmi-apple-controller.c
 F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 73780204631463631cabcbad5bf83e8dbbee94ce..9005fa91d9f4e541403ccc7bf84e0592402ac41e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,14 @@ menuconfig SPMI
 
 if SPMI
 
+config SPMI_APPLE
+	tristate "Apple SoC SPMI Controller platform driver"
+	depends on ARCH_APPLE || COMPILE_TEST
+	help
+	  If you say yes to this option, support will be included for the
+	  SPMI controller present on many Apple SoCs, including the
+	  t8103 (M1) and t600x (M1 Pro/Max).
+
 config SPMI_HISI3670
 	tristate "Hisilicon 3670 SPMI Controller"
 	select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 7f152167bb05b2c24a0f9669f60278152898eebb..38ac635645ba65aa46cb5e8a50072ed9771e229b 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,6 +4,7 @@
 #
 obj-$(CONFIG_SPMI)	+= spmi.o spmi-devres.o
 
+obj-$(CONFIG_SPMI_APPLE)	+= spmi-apple-controller.o
 obj-$(CONFIG_SPMI_HISI3670)	+= hisi-spmi-controller.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
 obj-$(CONFIG_SPMI_MTK_PMIF)	+= spmi-mtk-pmif.o
diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d4a677aaff6b10fce80f7eacc330605674ea495
--- /dev/null
+++ b/drivers/spmi/spmi-apple-controller.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple SoC SPMI device driver
+ *
+ * Copyright The Asahi Linux Contributors
+ *
+ * Inspired by:
+ *		OpenBSD support Copyright (c) 2021 Mark Kettenis <kettenis at openbsd.org>
+ *		Correllium support Copyright (C) 2021 Corellium LLC
+ *		hisi-spmi-controller.c
+ *		spmi-pmic-arb.c Copyright (c) 2021, The Linux Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+/* SPMI Controller Registers */
+#define SPMI_STATUS_REG 0
+#define SPMI_CMD_REG 0x4
+#define SPMI_RSP_REG 0x8
+
+#define SPMI_RX_FIFO_EMPTY BIT(24)
+
+#define REG_POLL_INTERVAL 10000
+#define REG_POLL_TIMEOUT (REG_POLL_INTERVAL * 5)
+
+struct apple_spmi {
+	void __iomem *regs;
+};
+
+#define poll_reg(spmi, reg, val, cond) \
+	readl_poll_timeout((spmi)->regs + (reg), (val), (cond), \
+			   REG_POLL_INTERVAL, REG_POLL_TIMEOUT)
+
+static inline u32 read_reg(struct apple_spmi *spmi, int offset)
+{
+	return readl(spmi->regs + offset);
+}
+
+static inline void write_reg(u32 value, struct apple_spmi *spmi, int offset)
+{
+	writel(value, spmi->regs + offset);
+}
+
+static inline u32 apple_spmi_pack_cmd(u8 opc, u8 sid, u16 saddr, size_t len)
+{
+	return opc | sid << 8 | saddr << 16 | (len - 1) | (1 << 15);
+}
+
+/* Wait for Rx FIFO to have something */
+static int apple_spmi_wait_rx_not_empty(struct spmi_controller *ctrl)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	int ret;
+	u32 status;
+
+	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
+	if (ret) {
+		dev_err(&ctrl->dev,
+			"%s: Failed to wait for RX FIFO not empty\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			 u16 saddr, u8 *buf, size_t len)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
+	u32 rsp;
+	size_t len_read = 0;
+	u8 i;
+	int ret;
+
+	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+
+	ret = apple_spmi_wait_rx_not_empty(ctrl);
+	if (ret)
+		return ret;
+
+	/* Discard SPMI reply status */
+	read_reg(spmi, SPMI_RSP_REG);
+
+	/* Read SPMI data reply */
+	while (len_read < len) {
+		rsp = read_reg(spmi, SPMI_RSP_REG);
+		i = 0;
+		while ((len_read < len) && (i < 4)) {
+			buf[len_read++] = ((0xff << (8 * i)) & rsp) >> (8 * i);
+			i += 1;
+		}
+	}
+
+	return 0;
+}
+
+static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			  u16 saddr, const u8 *buf, size_t len)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
+	size_t i = 0, j;
+	int ret;
+
+	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+
+	while (i < len) {
+		j = 0;
+		spmi_cmd = 0;
+		while ((j < 4) & (i < len))
+			spmi_cmd |= buf[i++] << (j++ * 8);
+
+		write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
+	}
+
+	ret = apple_spmi_wait_rx_not_empty(ctrl);
+	if (ret)
+		return ret;
+
+	/* Discard */
+	read_reg(spmi, SPMI_RSP_REG);
+
+	return 0;
+}
+
+static int apple_spmi_probe(struct platform_device *pdev)
+{
+	struct apple_spmi *spmi;
+	struct spmi_controller *ctrl;
+	int ret;
+
+	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
+	if (IS_ERR(ctrl))
+		return -ENOMEM;
+
+	spmi = spmi_controller_get_drvdata(ctrl);
+
+	spmi->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(spmi->regs))
+		return PTR_ERR(spmi->regs);
+
+	ctrl->dev.of_node = pdev->dev.of_node;
+
+	ctrl->read_cmd = spmi_read_cmd;
+	ctrl->write_cmd = spmi_write_cmd;
+
+	ret = devm_spmi_controller_add(&pdev->dev, ctrl);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "spmi_controller_add failed\n");
+
+	return 0;
+}
+
+static const struct of_device_id apple_spmi_match_table[] = {
+	{ .compatible = "apple,spmi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, apple_spmi_match_table);
+
+static struct platform_driver apple_spmi_driver = {
+	.probe		= apple_spmi_probe,
+	.driver		= {
+		.name	= "apple-spmi",
+		.of_match_table = apple_spmi_match_table,
+	},
+};
+module_platform_driver(apple_spmi_driver);
+
+MODULE_AUTHOR("Jean-Francois Bortolotti <jeff at borto.fr>");
+MODULE_DESCRIPTION("Apple SoC SPMI driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:09:01 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:09:01 +0100
Subject: [PATCH v2 3/3] arm64: dts: apple: Add SPMI controller nodes
In-Reply-To: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
Message-ID: <20250307-spmi-v2-3-eccdb06afb99@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add device tree entries for the SPMI controller

Reviewed-by: Nick Chan <towinchenmi at gmail.com>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 arch/arm64/boot/dts/apple/t600x-die0.dtsi | 7 +++++++
 arch/arm64/boot/dts/apple/t8103.dtsi      | 8 ++++++++
 arch/arm64/boot/dts/apple/t8112.dtsi      | 7 +++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index b1c875e692c8fb9c0af46a23568a7b0cd720141b..d544a35c8af414c583d38b040e1aa753902f1c93 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -53,6 +53,13 @@ wdt: watchdog at 2922b0000 {
 		interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	nub_spmi0: spmi at 2920a1300 {
+		compatible = "apple,t6000-spmi", "apple,spmi";
+		reg = <0x2 0x920a1300 0x0 0x100>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+	};
+
 	sio_dart_0: iommu at 39b004000 {
 		compatible = "apple,t6000-dart";
 		reg = <0x3 0x9b004000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 9b0dad6b618444ac6b1c9735c50cccfc3965f947..0f03dc808cf7c6b7d71afc79dd29d368f957f979 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/interrupt-controller/apple-aic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
 
 / {
 	compatible = "apple,t8103", "apple,arm-platform";
@@ -604,6 +605,13 @@ pcie_pins: pcie-pins {
 			};
 		};
 
+		nub_spmi: spmi at 23d0d9300 {
+			compatible = "apple,t8103-spmi", "apple,spmi";
+			reg = <0x2 0x3d0d9300 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_nub: pinctrl at 23d1f0000 {
 			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3d1f0000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 1666e6ab250bc0be9b8318e3c8fc903ccd3f3760..fecf70eba255c668757e2edfe25a4e9e7c0d0bad 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -641,6 +641,13 @@ pcie_pins: pcie-pins {
 			};
 		};
 
+		nub_spmi: spmi at 23d714000 {
+			compatible = "apple,t8112-spmi", "apple,spmi";
+			reg = <0x2 0x3d714000 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_nub: pinctrl at 23d1f0000 {
 			compatible = "apple,t8112-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3d1f0000 0x0 0x4000>;

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:07:45 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:07:45 +0100
Subject: [PATCH v3 1/2] iommu: apple-dart: Increase MAX_DARTS_PER_DEVICE to
 3
In-Reply-To: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
References: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
Message-ID: <20250307-isp-dart-v3-1-684fe4489591@gmail.com>

From: Hector Martin <marcan at marcan.st>

ISP needs this.

Signed-off-by: Hector Martin <marcan at marcan.st>
Reviewed-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 drivers/iommu/apple-dart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 95ba3caeb40177901086076416874b9905a1f40a..edb2fb22333506d7c64ad1b6321df00ebfd07747 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -36,7 +36,7 @@
 
 #define DART_MAX_STREAMS 256
 #define DART_MAX_TTBR 4
-#define MAX_DARTS_PER_DEVICE 2
+#define MAX_DARTS_PER_DEVICE 3
 
 /* Common registers */
 

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:07:44 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:07:44 +0100
Subject: [PATCH v3 0/2] iommu: apple-dart: Support the ISP DART
Message-ID: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>

The ISP block has 3 linked DARTs with mismatched bypass support.
This series adds support for this setup.

(The ISP driver itself is sent as a separate series
https://lore.kernel.org/asahi/20250219-isp-v1-0-6d3e89b67c31 at gmail.com/T/ )

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
Changes in v3:
- Just added r-b, effectively a resend
- Link to v2: https://lore.kernel.org/r/20250228-isp-dart-v2-0-0ead81a90e2d at gmail.com

Changes in v2:
- Made comments and code a closer match for each other
- Link to v1: https://lore.kernel.org/r/20250227-isp-dart-v1-0-161e91ef4f46 at gmail.com

---
Hector Martin (2):
      iommu: apple-dart: Increase MAX_DARTS_PER_DEVICE to 3
      iommu: apple-dart: Allow mismatched bypass support

 drivers/iommu/apple-dart.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
---
base-commit: dd83757f6e686a2188997cb58b5975f744bb7786
change-id: 20250227-isp-dart-f8369baaecb1




From devnull+fnkl.kernel.gmail.com at kernel.org  Fri Mar  7 12:08:59 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Fri, 07 Mar 2025 21:08:59 +0100
Subject: [PATCH v2 1/3] dt-bindings: spmi: Add Apple SPMI controller
In-Reply-To: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
Message-ID: <20250307-spmi-v2-1-eccdb06afb99@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add bindings for the SPMI controller present on most Apple SoCs

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 .../devicetree/bindings/spmi/apple,spmi.yaml       | 49 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 50 insertions(+)

diff --git a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..16bd7eb2b7af2c0b176f0e5b1970f4670af691da
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SPMI controller
+
+maintainers:
+  - Sasha Finkelstein <fnkl.kernel at gmail.com>
+
+description: A SPMI controller present on most Apple SoCs
+
+allOf:
+  - $ref: spmi.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - apple,t8103-spmi
+          - apple,t6000-spmi
+          - apple,t8112-spmi
+      - const: apple,spmi
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+
+    spmi at 920a1300 {
+        compatible = "apple,t6000-spmi", "apple,spmi";
+        reg = <0x920a1300 0x100>;
+        #address-cells = <2>;
+        #size-cells = <0>;
+
+        pmic at f {
+            reg = <0xf SPMI_USID>;
+            /* PMIC-specific properties */
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0e33544fa373a4978b7dae18c040c..271ff8110df83c2d4fe7fbbfffc0a72259460bc5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2236,6 +2236,7 @@ F:	Documentation/devicetree/bindings/pci/apple,pcie.yaml
 F:	Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
 F:	Documentation/devicetree/bindings/power/apple*
 F:	Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
+F:	Documentation/devicetree/bindings/spmi/apple,spmi.yaml
 F:	Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
 F:	arch/arm64/boot/dts/apple/
 F:	drivers/bluetooth/hci_bcm4377.c

-- 
2.48.1




From robin.murphy at arm.com  Fri Mar  7 12:20:15 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 7 Mar 2025 20:20:15 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <Z8sBuzx6sGq24n0g@lpieralisi>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <Z8sBuzx6sGq24n0g@lpieralisi>
Message-ID: <ea78c21b-db4a-4144-b1b5-b1a37e1ed51c@arm.com>

On 2025-03-07 2:24 pm, Lorenzo Pieralisi wrote:
[...]
>> diff --git a/drivers/acpi/arm64/dma.c b/drivers/acpi/arm64/dma.c
>> index 52b2abf88689..f30f138352b7 100644
>> --- a/drivers/acpi/arm64/dma.c
>> +++ b/drivers/acpi/arm64/dma.c
>> @@ -26,6 +26,11 @@ void acpi_arch_dma_setup(struct device *dev)
>>   	else
>>   		end = (1ULL << 32) - 1;
>>   
>> +	if (dev->dma_range_map) {
>> +		dev_dbg(dev, "dma_range_map already set\n");
>> +		return;
>> +	}
>> +
> 
> Why are we checking that dev->dma_range_map exists here rather than
> at function entry ? Is that because we want to run the previous code
> for some reasons even if dev->dma_range_map is already set ?
> 
> Just noticed, the OF counterpart does not seem to take the same
> approach, so I am just flagging this up if it matters at all.

The intent is just to ensure it's safe to come through this path more 
than once for the time being - it doesn't really matter whether or not 
we repeat anything apart from allocating and assigning dma_range_map, 
since that leaks the previous allocation. Thus this check is logically 
guarding the acpi_dma_get_range() call in this path, and the 
of_dma_get_range() call in the other.

> Other than that, for acpi/arm64:
> 
> Reviewed-by: Lorenzo Pieralisi <lpieralisi at kernel.org>

Thanks!

Robin.


From mark.barnett at arm.com  Fri Mar  7 12:22:44 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:44 +0000
Subject: [PATCH v3 2/5] perf: Allow periodic events to alternate between two sample periods
In-Reply-To: <20250307202247.648633-1-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
Message-ID: <20250307202247.648633-3-mark.barnett@arm.com>

From: Ben Gainey <ben.gainey at arm.com>

This change modifies perf_event_attr to add a second, alternative
sample period field, and modifies the core perf overflow handling
such that when specified an event will alternate between two sample
periods.

Currently, perf does not provide a  mechanism for decoupling the period
over which counters are counted from the period between samples. This is
problematic for building a tool to measure per-function metrics derived
from a sampled counter group. Ideally such a tool wants a very small
sample window in order to correctly attribute the metrics to a given
function, but prefers a larger sample period that provides representative
coverage without excessive probe effect, triggering throttling, or
generating excessive amounts of data.

By alternating between a long and short sample_period and subsequently
discarding the long samples, tools may decouple the period between
samples that the tool cares about from the window of time over which
interesting counts are collected.

It is expected that typically tools would use this feature with the
cycles or instructions events as an approximation for time, but no
restrictions are applied to which events this can be applied to.

Signed-off-by: Ben Gainey <ben.gainey at arm.com>
Signed-off-by: Mark Barnett <mark.barnett at arm.com>
---
 include/linux/perf_event.h      |  5 +++++
 include/uapi/linux/perf_event.h |  3 +++
 kernel/events/core.c            | 39 ++++++++++++++++++++++++++++++++-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 8333f132f4a9..99ba72c8fb6d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -276,6 +276,11 @@ struct hw_perf_event {
 	 */
 	u64				freq_time_stamp;
 	u64				freq_count_stamp;
+
+	/*
+	 * Indicates that the alternative sample period is used
+	 */
+	bool				using_alt_sample_period;
 #endif
 };
 
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 0524d541d4e3..499a8673df8e 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -379,6 +379,7 @@ enum perf_event_read_format {
 #define PERF_ATTR_SIZE_VER6	120	/* add: aux_sample_size */
 #define PERF_ATTR_SIZE_VER7	128	/* add: sig_data */
 #define PERF_ATTR_SIZE_VER8	136	/* add: config3 */
+#define PERF_ATTR_SIZE_VER9	144	/* add: alt_sample_period */
 
 /*
  * Hardware event_id to monitor via a performance monitoring event:
@@ -531,6 +532,8 @@ struct perf_event_attr {
 	__u64	sig_data;
 
 	__u64	config3; /* extension of config2 */
+
+	__u64	alt_sample_period;
 };
 
 /*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index bcb09e011e9e..7ec8ec6ba7ef 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4178,6 +4178,8 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bo
 	s64 period, sample_period;
 	s64 delta;
 
+	WARN_ON_ONCE(hwc->using_alt_sample_period);
+
 	period = perf_calculate_period(event, nsec, count);
 
 	delta = (s64)(period - hwc->sample_period);
@@ -9894,6 +9896,7 @@ static int __perf_event_overflow(struct perf_event *event,
 				 int throttle, struct perf_sample_data *data,
 				 struct pt_regs *regs)
 {
+	struct hw_perf_event *hwc = &event->hw;
 	int events = atomic_read(&event->event_limit);
 	int ret = 0;
 
@@ -9913,6 +9916,18 @@ static int __perf_event_overflow(struct perf_event *event,
 	    !bpf_overflow_handler(event, data, regs))
 		goto out;
 
+	/*
+	 * Swap the sample period to the alternative period
+	 */
+	if (event->attr.alt_sample_period) {
+		bool using_alt = hwc->using_alt_sample_period;
+		u64 sample_period = (using_alt ? event->attr.sample_period
+					       : event->attr.alt_sample_period);
+
+		hwc->sample_period = sample_period;
+		hwc->using_alt_sample_period = !using_alt;
+	}
+
 	/*
 	 * XXX event_limit might not quite work as expected on inherited
 	 * events
@@ -12335,9 +12350,19 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 	if (attr->freq && attr->sample_freq)
 		hwc->sample_period = 1;
 	hwc->last_period = hwc->sample_period;
-
 	local64_set(&hwc->period_left, hwc->sample_period);
 
+	/*
+	 * alt_sample_period cannot be used with freq
+	 */
+	if (attr->freq && attr->alt_sample_period)
+		goto err_ns;
+
+	if (attr->alt_sample_period) {
+		hwc->sample_period = attr->alt_sample_period;
+		hwc->using_alt_sample_period = true;
+	}
+
 	/*
 	 * We do not support PERF_SAMPLE_READ on inherited events unless
 	 * PERF_SAMPLE_TID is also selected, which allows inherited events to
@@ -12807,9 +12832,21 @@ SYSCALL_DEFINE5(perf_event_open,
 	if (attr.freq) {
 		if (attr.sample_freq > sysctl_perf_event_sample_rate)
 			return -EINVAL;
+		if (attr.alt_sample_period)
+			return -EINVAL;
 	} else {
 		if (attr.sample_period & (1ULL << 63))
 			return -EINVAL;
+		if (attr.alt_sample_period) {
+			if (!attr.sample_period)
+				return -EINVAL;
+			if (attr.alt_sample_period & (1ULL << 63))
+				return -EINVAL;
+			if (attr.alt_sample_period > attr.sample_period)
+				return -EINVAL;
+			if (attr.alt_sample_period == attr.sample_period)
+				attr.alt_sample_period = 0;
+		}
 	}
 
 	/* Only privileged users can get physical addresses */
-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:22:45 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:45 +0000
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the alternate sampling period
In-Reply-To: <20250307202247.648633-1-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
Message-ID: <20250307202247.648633-4-mark.barnett@arm.com>

From: Ben Gainey <ben.gainey at arm.com>

This change modifies the core perf overflow handler, adding some small
random jitter to each sample period whenever an event switches between the
two alternate sample periods. A new flag is added to perf_event_attr to
opt into this behaviour.

This change follows the discussion in [1], where it is recognized that it
may be possible for certain patterns of execution to end up with biased
results.

[1] https://lore.kernel.org/linux-perf-users/Zc24eLqZycmIg3d2 at tassilo/

Signed-off-by: Ben Gainey <ben.gainey at arm.com>
Signed-off-by: Mark Barnett <mark.barnett at arm.com>
---
 include/uapi/linux/perf_event.h | 7 ++++++-
 kernel/events/core.c            | 9 ++++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 499a8673df8e..c0076ce8f80a 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -461,7 +461,12 @@ struct perf_event_attr {
 				inherit_thread :  1, /* children only inherit if cloned with CLONE_THREAD */
 				remove_on_exec :  1, /* event is removed from task on exec */
 				sigtrap        :  1, /* send synchronous SIGTRAP on event */
-				__reserved_1   : 26;
+				/*
+				 * Add a limited amount of jitter on each alternate period, where
+				 * the jitter is between [0, (2<<jitter_alt_period) - 1]
+				 */
+				jitter_alt_period : 3,
+				__reserved_1   : 23;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 7ec8ec6ba7ef..be271e21cd06 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -15,6 +15,7 @@
 #include <linux/idr.h>
 #include <linux/file.h>
 #include <linux/poll.h>
+#include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/hash.h>
 #include <linux/tick.h>
@@ -9922,7 +9923,10 @@ static int __perf_event_overflow(struct perf_event *event,
 	if (event->attr.alt_sample_period) {
 		bool using_alt = hwc->using_alt_sample_period;
 		u64 sample_period = (using_alt ? event->attr.sample_period
-					       : event->attr.alt_sample_period);
+					       : event->attr.alt_sample_period)
+				  + (event->attr.jitter_alt_period
+					? get_random_u32_below(2 << event->attr.jitter_alt_period)
+					: 0);
 
 		hwc->sample_period = sample_period;
 		hwc->using_alt_sample_period = !using_alt;
@@ -12849,6 +12853,9 @@ SYSCALL_DEFINE5(perf_event_open,
 		}
 	}
 
+	if (attr.jitter_alt_period && !attr.alt_sample_period)
+		return -EINVAL;
+
 	/* Only privileged users can get physical addresses */
 	if ((attr.sample_type & PERF_SAMPLE_PHYS_ADDR)) {
 		err = perf_allow_kernel(&attr);
-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:22:46 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:46 +0000
Subject: [PATCH v3 4/5] tools/perf: Modify event parser to support alt-period term
In-Reply-To: <20250307202247.648633-1-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
Message-ID: <20250307202247.648633-5-mark.barnett@arm.com>

From: Ben Gainey <ben.gainey at arm.com>

parse-events is modified, adding the "alt-period" term which can be used
to specify the alternative sampling period.

Signed-off-by: Ben Gainey <ben.gainey at arm.com>
Signed-off-by: Mark Barnett <mark.barnett at arm.com>
---
 tools/include/uapi/linux/perf_event.h             |  3 +++
 tools/perf/tests/shell/attr/base-record           |  3 ++-
 tools/perf/tests/shell/attr/base-record-spe       |  1 +
 tools/perf/tests/shell/attr/base-stat             |  3 ++-
 tools/perf/tests/shell/attr/system-wide-dummy     |  3 ++-
 .../tests/shell/attr/test-record-alt-period-term  | 12 ++++++++++++
 tools/perf/tests/shell/attr/test-record-dummy-C0  |  3 ++-
 tools/perf/tests/shell/lib/attr.py                |  1 +
 tools/perf/util/evsel.c                           |  1 +
 tools/perf/util/parse-events.c                    | 15 +++++++++++++++
 tools/perf/util/parse-events.h                    |  3 ++-
 tools/perf/util/parse-events.l                    |  1 +
 tools/perf/util/perf_event_attr_fprintf.c         |  1 +
 tools/perf/util/pmu.c                             |  1 +
 14 files changed, 46 insertions(+), 5 deletions(-)
 create mode 100644 tools/perf/tests/shell/attr/test-record-alt-period-term

diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 0524d541d4e3..499a8673df8e 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -379,6 +379,7 @@ enum perf_event_read_format {
 #define PERF_ATTR_SIZE_VER6	120	/* add: aux_sample_size */
 #define PERF_ATTR_SIZE_VER7	128	/* add: sig_data */
 #define PERF_ATTR_SIZE_VER8	136	/* add: config3 */
+#define PERF_ATTR_SIZE_VER9	144	/* add: alt_sample_period */
 
 /*
  * Hardware event_id to monitor via a performance monitoring event:
@@ -531,6 +532,8 @@ struct perf_event_attr {
 	__u64	sig_data;
 
 	__u64	config3; /* extension of config2 */
+
+	__u64	alt_sample_period;
 };
 
 /*
diff --git a/tools/perf/tests/shell/attr/base-record b/tools/perf/tests/shell/attr/base-record
index b44e4e6e4443..28a7233f7bc1 100644
--- a/tools/perf/tests/shell/attr/base-record
+++ b/tools/perf/tests/shell/attr/base-record
@@ -5,7 +5,7 @@ group_fd=-1
 flags=0|8
 cpu=*
 type=0|1
-size=136
+size=144
 config=0|1
 sample_period=*
 sample_type=263
@@ -39,3 +39,4 @@ config2=0
 branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
+alt_sample_period=0
diff --git a/tools/perf/tests/shell/attr/base-record-spe b/tools/perf/tests/shell/attr/base-record-spe
index 08fa96b59240..ad8eb72e655a 100644
--- a/tools/perf/tests/shell/attr/base-record-spe
+++ b/tools/perf/tests/shell/attr/base-record-spe
@@ -38,3 +38,4 @@ config2=*
 branch_sample_type=*
 sample_regs_user=*
 sample_stack_user=*
+alt_sample_period=0
diff --git a/tools/perf/tests/shell/attr/base-stat b/tools/perf/tests/shell/attr/base-stat
index fccd8ec4d1b0..2de92c5c300d 100644
--- a/tools/perf/tests/shell/attr/base-stat
+++ b/tools/perf/tests/shell/attr/base-stat
@@ -5,7 +5,7 @@ group_fd=-1
 flags=0|8
 cpu=*
 type=0
-size=136
+size=144
 config=0
 sample_period=0
 sample_type=65536
@@ -39,3 +39,4 @@ config2=0
 branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
+alt_sample_period=0
diff --git a/tools/perf/tests/shell/attr/system-wide-dummy b/tools/perf/tests/shell/attr/system-wide-dummy
index a1e1d6a263bf..c0a17bb3c022 100644
--- a/tools/perf/tests/shell/attr/system-wide-dummy
+++ b/tools/perf/tests/shell/attr/system-wide-dummy
@@ -7,7 +7,7 @@ cpu=*
 pid=-1
 flags=8
 type=1
-size=136
+size=144
 config=9
 sample_period=1
 # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
@@ -50,3 +50,4 @@ config2=0
 branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
+alt_sample_period=0
diff --git a/tools/perf/tests/shell/attr/test-record-alt-period-term b/tools/perf/tests/shell/attr/test-record-alt-period-term
new file mode 100644
index 000000000000..fcdb790adcd3
--- /dev/null
+++ b/tools/perf/tests/shell/attr/test-record-alt-period-term
@@ -0,0 +1,12 @@
+[config]
+command = record
+args    = --no-bpf-event -e cycles/period=3,alt-period=2/ -- kill >/dev/null 2>&1
+ret     = 1
+kernel_since = 6.11
+
+[event-10:base-record]
+sample_period=3
+alt_sample_period=2
+
+freq=0
+sample_type=7
diff --git a/tools/perf/tests/shell/attr/test-record-dummy-C0 b/tools/perf/tests/shell/attr/test-record-dummy-C0
index 91499405fff4..e6315918a95e 100644
--- a/tools/perf/tests/shell/attr/test-record-dummy-C0
+++ b/tools/perf/tests/shell/attr/test-record-dummy-C0
@@ -10,7 +10,7 @@ cpu=0
 pid=-1
 flags=8
 type=1
-size=136
+size=144
 config=9
 sample_period=4000
 # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
@@ -53,3 +53,4 @@ config2=0
 branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
+alt_sample_period=0
diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 3db9a7d78715..04e95f76005a 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -91,6 +91,7 @@ class Event(dict):
         'branch_sample_type',
         'sample_regs_user',
         'sample_stack_user',
+        'alt_sample_period',
     ]
 
     def add(self, data):
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 4a0ef095db92..0657e580ea13 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -180,6 +180,7 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, struct perf_cpu
 	WRITE_ASS(branch_sample_type, "llu");
 	WRITE_ASS(sample_regs_user,   "llu");
 	WRITE_ASS(sample_stack_user,  PRIu32);
+	WRITE_ASS(alt_sample_period,  "llu");
 
 	fclose(file);
 	return 0;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 35e48fe56dfa..653d84080bc7 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -805,6 +805,7 @@ const char *parse_events__term_type_str(enum parse_events__term_type term_type)
 		[PARSE_EVENTS__TERM_TYPE_RAW]                   = "raw",
 		[PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE]          = "legacy-cache",
 		[PARSE_EVENTS__TERM_TYPE_HARDWARE]              = "hardware",
+		[PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD]	= "alt-period",
 	};
 	if ((unsigned int)term_type >= __PARSE_EVENTS__TERM_TYPE_NR)
 		return "unknown term";
@@ -833,6 +834,7 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er
 	case PARSE_EVENTS__TERM_TYPE_NAME:
 	case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
+	case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
 	case PARSE_EVENTS__TERM_TYPE_PERCORE:
 		return true;
 	case PARSE_EVENTS__TERM_TYPE_USER:
@@ -981,6 +983,16 @@ do {									   \
 			return -EINVAL;
 		}
 		break;
+	case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
+		CHECK_TYPE_VAL(NUM);
+		if (term->val.num == 0) {
+			parse_events_error__handle(err, term->err_val,
+						strdup("expected a non-zero value"),
+						NULL);
+			return -EINVAL;
+		}
+		attr->alt_sample_period = term->val.num;
+		break;
 	case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
 	case PARSE_EVENTS__TERM_TYPE_USER:
 	case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
@@ -1108,6 +1120,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
 	case PARSE_EVENTS__TERM_TYPE_RAW:
 	case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 	case PARSE_EVENTS__TERM_TYPE_HARDWARE:
+	case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
 	default:
 		if (err) {
 			parse_events_error__handle(err, term->err_term,
@@ -1242,6 +1255,7 @@ do {								\
 		case PARSE_EVENTS__TERM_TYPE_RAW:
 		case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 		case PARSE_EVENTS__TERM_TYPE_HARDWARE:
+		case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
 		default:
 			break;
 		}
@@ -1296,6 +1310,7 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head
 		case PARSE_EVENTS__TERM_TYPE_RAW:
 		case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 		case PARSE_EVENTS__TERM_TYPE_HARDWARE:
+		case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
 		default:
 			break;
 		}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e176a34ab088..d00bb6c5d9ab 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -80,7 +80,8 @@ enum parse_events__term_type {
 	PARSE_EVENTS__TERM_TYPE_RAW,
 	PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
 	PARSE_EVENTS__TERM_TYPE_HARDWARE,
-#define	__PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_HARDWARE + 1)
+	PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD,
+#define	__PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD + 1)
 };
 
 struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 7ed86e3e34e3..9c64434167b7 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -335,6 +335,7 @@ aux-output		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
 aux-action		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_ACTION); }
 aux-sample-size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
 metric-id		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
+alt-period		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD); }
 cpu-cycles|cycles				{ return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
 stalled-cycles-frontend|idle-cycles-frontend	{ return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
 stalled-cycles-backend|idle-cycles-backend	{ return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c
index c7f3543b9921..e823240b7dd8 100644
--- a/tools/perf/util/perf_event_attr_fprintf.c
+++ b/tools/perf/util/perf_event_attr_fprintf.c
@@ -334,6 +334,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
 	PRINT_ATTRf(aux_start_paused, p_unsigned);
 	PRINT_ATTRf(aux_pause, p_unsigned);
 	PRINT_ATTRf(aux_resume, p_unsigned);
+	PRINT_ATTRf(alt_sample_period, p_unsigned);
 
 	return ret;
 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57450c73fb63..7576fe35a869 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1804,6 +1804,7 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call
 		"aux-output",
 		"aux-action=(pause|resume|start-paused)",
 		"aux-sample-size=number",
+		"alt-period=number",
 	};
 	struct perf_pmu_format *format;
 	int ret;
-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:22:47 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:47 +0000
Subject: [PATCH v3 5/5] tools/perf: Modify event parser to support alt-period-jitter term
In-Reply-To: <20250307202247.648633-1-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
Message-ID: <20250307202247.648633-6-mark.barnett@arm.com>

From: Ben Gainey <ben.gainey at arm.com>

parse-events is modified, adding the "alt-period-jitter" term which
can be used to enable random jitter of the alternative sample
period.

Signed-off-by: Ben Gainey <ben.gainey at arm.com>
Signed-off-by: Mark Barnett <mark.barnett at arm.com>
---
 tools/include/uapi/linux/perf_event.h             |  7 ++++++-
 tools/perf/tests/shell/attr/base-record           |  1 +
 tools/perf/tests/shell/attr/base-record-spe       |  1 +
 tools/perf/tests/shell/attr/base-stat             |  1 +
 tools/perf/tests/shell/attr/system-wide-dummy     |  1 +
 .../shell/attr/test-record-alt-period-jitter-term | 13 +++++++++++++
 tools/perf/tests/shell/attr/test-record-dummy-C0  |  1 +
 tools/perf/tests/shell/lib/attr.py                |  1 +
 tools/perf/util/evsel.c                           |  1 +
 tools/perf/util/parse-events.c                    | 15 +++++++++++++++
 tools/perf/util/parse-events.h                    |  3 ++-
 tools/perf/util/parse-events.l                    |  1 +
 tools/perf/util/pmu.c                             |  3 ++-
 13 files changed, 46 insertions(+), 3 deletions(-)
 create mode 100644 tools/perf/tests/shell/attr/test-record-alt-period-jitter-term

diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 499a8673df8e..c0076ce8f80a 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -461,7 +461,12 @@ struct perf_event_attr {
 				inherit_thread :  1, /* children only inherit if cloned with CLONE_THREAD */
 				remove_on_exec :  1, /* event is removed from task on exec */
 				sigtrap        :  1, /* send synchronous SIGTRAP on event */
-				__reserved_1   : 26;
+				/*
+				 * Add a limited amount of jitter on each alternate period, where
+				 * the jitter is between [0, (2<<jitter_alt_period) - 1]
+				 */
+				jitter_alt_period : 3,
+				__reserved_1   : 23;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
diff --git a/tools/perf/tests/shell/attr/base-record b/tools/perf/tests/shell/attr/base-record
index 28a7233f7bc1..1f5ab125c78d 100644
--- a/tools/perf/tests/shell/attr/base-record
+++ b/tools/perf/tests/shell/attr/base-record
@@ -40,3 +40,4 @@ branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
 alt_sample_period=0
+jitter_alt_period=0
diff --git a/tools/perf/tests/shell/attr/base-record-spe b/tools/perf/tests/shell/attr/base-record-spe
index ad8eb72e655a..b35ca04b2ce4 100644
--- a/tools/perf/tests/shell/attr/base-record-spe
+++ b/tools/perf/tests/shell/attr/base-record-spe
@@ -39,3 +39,4 @@ branch_sample_type=*
 sample_regs_user=*
 sample_stack_user=*
 alt_sample_period=0
+jitter_alt_period=0
diff --git a/tools/perf/tests/shell/attr/base-stat b/tools/perf/tests/shell/attr/base-stat
index 2de92c5c300d..2d90a055686a 100644
--- a/tools/perf/tests/shell/attr/base-stat
+++ b/tools/perf/tests/shell/attr/base-stat
@@ -40,3 +40,4 @@ branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
 alt_sample_period=0
+jitter_alt_period=0
diff --git a/tools/perf/tests/shell/attr/system-wide-dummy b/tools/perf/tests/shell/attr/system-wide-dummy
index c0a17bb3c022..527707b505e0 100644
--- a/tools/perf/tests/shell/attr/system-wide-dummy
+++ b/tools/perf/tests/shell/attr/system-wide-dummy
@@ -51,3 +51,4 @@ branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
 alt_sample_period=0
+jitter_alt_period=0
diff --git a/tools/perf/tests/shell/attr/test-record-alt-period-jitter-term b/tools/perf/tests/shell/attr/test-record-alt-period-jitter-term
new file mode 100644
index 000000000000..6b31c898c905
--- /dev/null
+++ b/tools/perf/tests/shell/attr/test-record-alt-period-jitter-term
@@ -0,0 +1,13 @@
+[config]
+command = record
+args    = --no-bpf-event -e cycles/period=3,alt-period=2,alt-period-jitter=7/ -- kill >/dev/null 2>&1
+ret     = 1
+kernel_since = 6.11
+
+[event-10:base-record]
+sample_period=3
+alt_sample_period=2
+jitter_alt_period=7
+
+freq=0
+sample_type=7
diff --git a/tools/perf/tests/shell/attr/test-record-dummy-C0 b/tools/perf/tests/shell/attr/test-record-dummy-C0
index e6315918a95e..436534df0434 100644
--- a/tools/perf/tests/shell/attr/test-record-dummy-C0
+++ b/tools/perf/tests/shell/attr/test-record-dummy-C0
@@ -54,3 +54,4 @@ branch_sample_type=0
 sample_regs_user=0
 sample_stack_user=0
 alt_sample_period=0
+jitter_alt_period=0
diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 04e95f76005a..d15363e925fe 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -92,6 +92,7 @@ class Event(dict):
         'sample_regs_user',
         'sample_stack_user',
         'alt_sample_period',
+        'jitter_alt_period',
     ]
 
     def add(self, data):
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0657e580ea13..2bb3e346f2b9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -181,6 +181,7 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, struct perf_cpu
 	WRITE_ASS(sample_regs_user,   "llu");
 	WRITE_ASS(sample_stack_user,  PRIu32);
 	WRITE_ASS(alt_sample_period,  "llu");
+	WRITE_ASS(jitter_alt_period,  "d");
 
 	fclose(file);
 	return 0;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 653d84080bc7..2e0ecfb77af3 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -806,6 +806,7 @@ const char *parse_events__term_type_str(enum parse_events__term_type term_type)
 		[PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE]          = "legacy-cache",
 		[PARSE_EVENTS__TERM_TYPE_HARDWARE]              = "hardware",
 		[PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD]	= "alt-period",
+		[PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER]	= "alt-period-jitter",
 	};
 	if ((unsigned int)term_type >= __PARSE_EVENTS__TERM_TYPE_NR)
 		return "unknown term";
@@ -835,6 +836,7 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er
 	case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
 	case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
+	case PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
 	case PARSE_EVENTS__TERM_TYPE_PERCORE:
 		return true;
 	case PARSE_EVENTS__TERM_TYPE_USER:
@@ -993,6 +995,16 @@ do {									   \
 		}
 		attr->alt_sample_period = term->val.num;
 		break;
+	case PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
+		CHECK_TYPE_VAL(NUM);
+		if ((unsigned int)term->val.num > 7) {
+			parse_events_error__handle(err, term->err_val,
+						strdup("expected a value between 0-7"),
+						NULL);
+			return -EINVAL;
+		}
+		attr->jitter_alt_period = (unsigned int)term->val.num;
+		break;
 	case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
 	case PARSE_EVENTS__TERM_TYPE_USER:
 	case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
@@ -1121,6 +1133,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
 	case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 	case PARSE_EVENTS__TERM_TYPE_HARDWARE:
 	case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
+	case PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
 	default:
 		if (err) {
 			parse_events_error__handle(err, term->err_term,
@@ -1256,6 +1269,7 @@ do {								\
 		case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 		case PARSE_EVENTS__TERM_TYPE_HARDWARE:
 		case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
+		case PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
 		default:
 			break;
 		}
@@ -1311,6 +1325,7 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head
 		case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
 		case PARSE_EVENTS__TERM_TYPE_HARDWARE:
 		case PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD:
+		case PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
 		default:
 			break;
 		}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d00bb6c5d9ab..dafd4b4d0f0e 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -81,7 +81,8 @@ enum parse_events__term_type {
 	PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
 	PARSE_EVENTS__TERM_TYPE_HARDWARE,
 	PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD,
-#define	__PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD + 1)
+	PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER,
+#define	__PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER + 1)
 };
 
 struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 9c64434167b7..91d312a23769 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -336,6 +336,7 @@ aux-action		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_ACTION); }
 aux-sample-size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
 metric-id		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
 alt-period		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_ALT_SAMPLE_PERIOD); }
+alt-period-jitter	{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER); }
 cpu-cycles|cycles				{ return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
 stalled-cycles-frontend|idle-cycles-frontend	{ return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
 stalled-cycles-backend|idle-cycles-backend	{ return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7576fe35a869..c665dc35ad6b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1429,7 +1429,7 @@ static int pmu_config_term(const struct perf_pmu *pmu,
 			break;
 		case PARSE_EVENTS__TERM_TYPE_USER: /* Not hardcoded. */
 			return -EINVAL;
-		case PARSE_EVENTS__TERM_TYPE_NAME ... PARSE_EVENTS__TERM_TYPE_HARDWARE:
+		case PARSE_EVENTS__TERM_TYPE_NAME ... PARSE_EVENTS__TERM_TYPE_ALT_PERIOD_JITTER:
 			/* Skip non-config terms. */
 			break;
 		default:
@@ -1805,6 +1805,7 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call
 		"aux-action=(pause|resume|start-paused)",
 		"aux-sample-size=number",
 		"alt-period=number",
+		"alt-period-jitter=number",
 	};
 	struct perf_pmu_format *format;
 	int ret;
-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:22:42 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:42 +0000
Subject: [PATCH v3 0/5] A mechanism for efficient support for per-function metrics
Message-ID: <20250307202247.648633-1-mark.barnett@arm.com>

From: Mark Barnett <mark.barnett at arm.com>


This patch introduces the concept of an alternating sample rate to perf
core and provides the necessary basic changes in the tools to activate
that option.

The primary use case for this change is to be able to enable collecting
per-function performance metrics using the Arm PMU, as per the following 
approach:

 * Starting with a simple periodic sampling (hotspot) profile,
   augment each sample with PMU counters accumulated over a short window
   up to the point the sample was taken.
 * For each sample, perform some filtering to improve attribution of
   the accumulated PMU counters (ensure they are attributed to a single
   function)
 * For each function accumulate a total for each PMU counter so that
   metrics may be derived.

Without modification, and sampling at a typical rate associated
with hotspot profiling (~1mS) leads to poor results. Such an
approach gives you a reasonable estimation of where the profiled
application is spending time for relatively low overhead, but the
PMU counters cannot easily be attributed to a single function as the
window over which they are collected is too large. A modern CPU may
execute many millions of instructions over many thousands of functions
within 1mS window. With this approach, the per-function metrics tend
to trend to some average value across the top N functions in the
profile.

In order to ensure a reasonable likelihood that the counters are
attributed to a single function, the sampling window must be rather
short; typically something in the order of a few hundred cycles proves
well as tested on a range of aarch64 Cortex and Neoverse cores.

As it stands, it is possible to achieve this with perf using a very high
sampling rate (e.g ~300cy), but there are at least three major concerns
with this approach:

 * For speculatively executing, out of order cores, can the results be
   accurately attributed to a give function or the given sample window?
 * A short sample window is not guaranteed to cover a single function.
 * The overhead of sampling every few hundred cycles is very high and
   is highly likely to cause throttling which is undesirable as it leads
   to patchy results; i.e. the profile alternates between periods of 
   high frequency samples followed by longer periods of no samples. 

This patch does not address the first two points directly. Some means
to address those are discussed on the RFC v2 cover letter. The patch
focuses on addressing the final point, though happily this approach
gives us a way to perform basic filtering on the second point.

The alternating sample period allows us to do two things:

 * We can control the risk of throttling and reduce overhead by
   alternating between a long and short period. This allows us to
   decouple the "periodic" sampling rate (as might be used for hotspot
   profiling) from the short sampling window needed for collecting
   the PMU counters.
 * The sample taken at the end of the long period can be otherwise 
   discarded (as the PMU data is not useful), but the
   PERF_RECORD_CALLCHAIN information can be used to identify the current
   function at the start of the short sample window. This is useful
   for filtering samples where the PMU counter data cannot be attributed
   to a single function.

There are several reasons why it is desirable to reduce the overhead and
risk of throttling:

  * PMU counter overflow typically causes an interrupt into the kernel;
    this affects program runtime, and can affect things like branch
    prediction, cache locality and so on which can skew the metrics.
  * The very high sample rate produces significant amounts of data.
    Depending on the configuration of the profiling session and machine,
    it is easily possible to produce many orders of magnitude more data
    which is costly for tools to post-process and increases the chance
    of data loss. This is especially relevant on larger core count
    systems where it is very easy to produce massive recordings.
    Whilst the kernel will throttle such a configuration,
    which helps to mitigate a large portion of the bandwidth and capture
    overhead, it is not something that can be controlled for on a per
    event basis, or for non-root users, and because throttling is
    controlled as a percentage of time its affects vary from machine to
    machine. AIUI throttling may also produce an uneven temporal
    distribution of samples. Finally, whilst throttling does a good job
    at reducing the overall amount of data produced, it still leads to
    much larger captures than with this method; typically we have
    observed 1-2 orders of magnitude larger captures.

This patch set modifies perf core to support alternating between two
sample_period values, providing a simple and inexpensive way for tools
to separate out the sample window (time over which events are
counted) from the sample period (time between interesting samples). 

It is expected to be used with the cycle counter event, alternating
between a long and short period and subsequently discarding the counter
data for samples with the long period. The combined long and short
period gives the overall sampling period, and the short sample period 
gives the sample window. The symbol taken from the sample at the end of
the long period can be used by tools to ensure correct attribution as
described previously. The cycle counter is recommended as it provides
fair temporal distribution of samples as would be required for the
per-symbol sample count mentioned previously, and because the PMU can
be programmed to overflow after a sufficiently short window (which may
not be possible with software timer, for example). This patch does not
restrict to only the cycle counter, it is possible there could be other
novel uses based on different events, or more appropriate counters on
other architectures. This patch set does not modify or otherwise disable
the kernel's existing throttling behaviour; if a configuration is given
that would lead high CPU usage, then throttling still occurs.


To test this a simple `perf script` based python script was developed.
For a limited set of Arm PMU events it will post process a
`perf record`-ing and generate a table of metrics. Along side this a
benchmark application was developed that rotates through a sequence
of different classes of behaviour that can be detected by the Arm PMU
(eg. mispredicts, cache misses, different instruction mixes). The path
through the benchmark can be rotated after each iteration so as to
ensure the results don't land on some lucky harmonic with the sample
period. The script can be used with and without this patch allowing
comparison of the results. Testing was on Juno (A53+A57), N1SDP,
Gravaton 2 and 3. In addition this approach has been applied to a few
of Arm's tools projects and has correctly identified improvements and
regressions.

Headline results from testing indicate that ~300 cycles sample window
gives good results with or without this patch. Typical output on N1SDP (Neoverse-N1)
for the provided benchmark when run as:

    perf record -T --sample-cpu --call-graph fp,4 --user-callchains \
        -k CLOCK_MONOTONIC_RAW \
        -e '{cycles/period=999700,alt-period=300/,instructions,branch-misses,cache-references,cache-misses}:uS' \
        benchmark 0 1

    perf script -s generate-function-metrics.py -- -s discard

Looks like (reformatted for email brevity):

    Symbol              #     CPI   BM/KI  CM/KI  %CM   %CY   %I    %BM   %L1DA  %L1DM
    fp_divider_stalls   6553   4.9   0.0     0.0   0.0  41.8  22.9   0.1   0.6    0.0
    int_divider_stalls  4741   3.5   0.0     0.0   1.1  28.3  21.5   0.1   1.9    0.2
    isb                 3414  20.1   0.2     0.0   0.4  17.6   2.3   0.1   0.8    0.0
    branch_mispredicts  1234   1.1  33.0     0.0   0.0   6.1  15.2  99.0  71.6    0.1
    double_to_int        694   0.5   0.0     0.0   0.6   3.4  19.1   0.1   1.2    0.1
    nops                 417   0.3   0.2     0.0   2.8   1.9  18.3   0.6   0.4    0.1
    dcache_miss          185   3.6   0.4   184.7  53.8   0.7   0.5   0.0  18.4   99.1

(CPI = Cycles/Instruction, BM/KI = Branch Misses per 1000 Instruction,
 CM/KI = Cache Misses per 1000 Instruction, %CM = Percent of Cache
 accesses that miss, %CY = Percentage of total cycles, %I = Percentage
 of total instructions, %BM = Percentage of total branch mispredicts,
 %L1DA = Percentage of total cache accesses, %L1DM = Percentage of total
 cache misses)

When the patch is used, the resulting `perf.data` files are typically
between 25-50x smaller than without, and take ~25x less time for the
python script to post-process. For example, running the following:

    perf record -i -vvv -e '{cycles/period=1000000/,instructions}:uS' benchmark 0 1
    perf record -i -vvv -e '{cycles/period=1000/,instructions}:uS' benchmark 0 1
    perf record -i -vvv -e '{cycles/period=300/,instructions}:uS' benchmark 0 1

produces captures on N1SDP (Neoverse-N1) of the following sizes:

    * period=1000000: 2.601 MB perf.data (55780 samples), script time = 0m0.362s
    * period=1000: 283.749 MB perf.data (6162932 samples), script time = 0m33.100s
    * period=300: 304.281 MB perf.data (6614182 samples), script time = 0m35.826s

The "script time" is the user time from running "time perf script -s generate-function-metrics.py"
on the recording. Similar processing times were observed for "time perf report --stdio|cat"
as well.

By comparison, with the patch active:

    perf record -i -vvv -e '{cycles/period=999700,alt-period=300/,instructions}:uS' benchmark 0 1

produces 4.923 MB perf.data (107512 samples), and script time = 0m0.578s.
Which is as expected ~2x the size and ~2x the number of samples as per
the period=1000000 recording. When compared to the period=300 recording,
the results from the provided post-processing script are (within margin
of error) the same, but the data file is ~62x smaller. The same affect
is seen for the post-processing script runtime.

Notably, without the patch enable, L1D cache miss rates are often higher
than with, which we attribute to increased impact on the cache that
trapping into the kernel every 300 cycles has.

These results are given with `perf_cpu_time_max_percent=25`. When tested
with `perf_cpu_time_max_percent=100` the size and time comparisons are
more significant. Disabling throttling did not lead to obvious
improvements in the collected metrics, suggesting that the sampling
approach is sufficient to collect representative metrics.

Cursory testing on a Xeon(R) W-2145 with a 300 *instruction* sample
window (with and without the patch) suggests this approach might work
for some counters. Using the same test script, it was possible to identify
branch mispredicts correctly. However, whilst the patch is functionally 
correct, differences in the architectures may mean that this approach it
enables does not apply as a means to collect per-function metrics on x86.

Changes since v2:
 - Rebased onto latest perf-tools-next.
 - Reordered patch series so that "Record sample last_period before updating"
   applies first.
 - Addressed issue reported by LKP tests.
 - Addressed review comments from Leo Yan.

Changes since v1:
 - Rebased onto perf-tools-next, as per request from Ian Rogers.
 - Removed unnecessary code that truncated period_left to 0 and restarted
   the PMU.
 - Renamed variables to use the shorter 'alt_period' instead of 
   'alterantive_period'.
 - Addressed review comments from Leo Yan.
 - Added patch #5 that addresses an issue in the x86 and PowerPC drivers that
   caused the opposite period to be reported in the sample record.
   
Changes since RFC v2:
 - Rebased on v6.12-rc6.

Changes since RFC v1:
 - Rebased on v6.9-rc1.
 - Refactored from arm_pmu based extension to core feature
 - Added the ability to jitter the sample window based on feedback
   from Andi Kleen.
 - Modified perf tool to parse the "alt-period" and "alt-period-jitter"
   terms in the event specification.

Ben Gainey (4):
  perf: Allow periodic events to alternate between two sample periods
  perf: Allow adding fixed random jitter to the alternate sampling
    period
  tools/perf: Modify event parser to support alt-period term
  tools/perf: Modify event parser to support alt-period-jitter term

Mark Barnett (1):
  perf: Record sample last_period before updating

 arch/powerpc/perf/core-book3s.c               |  3 +-
 arch/powerpc/perf/core-fsl-emb.c              |  3 +-
 arch/x86/events/core.c                        |  4 +-
 arch/x86/events/intel/core.c                  |  5 ++-
 arch/x86/events/intel/knc.c                   |  4 +-
 include/linux/perf_event.h                    |  5 +++
 include/uapi/linux/perf_event.h               | 10 ++++-
 kernel/events/core.c                          | 44 ++++++++++++++++++-
 tools/include/uapi/linux/perf_event.h         | 10 ++++-
 tools/perf/tests/shell/attr/base-record       |  4 +-
 tools/perf/tests/shell/attr/base-record-spe   |  2 +
 tools/perf/tests/shell/attr/base-stat         |  4 +-
 tools/perf/tests/shell/attr/system-wide-dummy |  4 +-
 .../attr/test-record-alt-period-jitter-term   | 13 ++++++
 .../shell/attr/test-record-alt-period-term    | 12 +++++
 .../tests/shell/attr/test-record-dummy-C0     |  4 +-
 tools/perf/tests/shell/lib/attr.py            |  2 +
 tools/perf/util/evsel.c                       |  2 +
 tools/perf/util/parse-events.c                | 30 +++++++++++++
 tools/perf/util/parse-events.h                |  4 +-
 tools/perf/util/parse-events.l                |  2 +
 tools/perf/util/perf_event_attr_fprintf.c     |  1 +
 tools/perf/util/pmu.c                         |  4 +-
 23 files changed, 162 insertions(+), 14 deletions(-)
 create mode 100644 tools/perf/tests/shell/attr/test-record-alt-period-jitter-term
 create mode 100644 tools/perf/tests/shell/attr/test-record-alt-period-term

-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:22:43 2025
From: mark.barnett at arm.com (mark.barnett at arm.com)
Date: Fri,  7 Mar 2025 20:22:43 +0000
Subject: [PATCH v3 1/5] perf: Record sample last_period before updating
In-Reply-To: <20250307202247.648633-1-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
Message-ID: <20250307202247.648633-2-mark.barnett@arm.com>

From: Mark Barnett <mark.barnett at arm.com>

This change alters the PowerPC and x86 driver implementations to record
the last sample period before the event is updated for the next period.

A common pattern in PMU driver implementations is to have a
"*_event_set_period" function which takes care of updating the various
period-related fields in a perf_event structure. In most cases, the
drivers choose to call this function after initializing a sample data
structure with perf_sample_data_init. The x86 and PowerPC drivers
deviate from this, choosing to update the period before initializing the
sample data. When using an event with an alternate sample period, this
causes an incorrect period to be written to the sample data that gets
reported to userspace.

Link: https://lore.kernel.org/r/20240515193610.2350456-4-yabinc at google.com
Signed-off-by: Mark Barnett <mark.barnett at arm.com>
---
 arch/powerpc/perf/core-book3s.c  | 3 ++-
 arch/powerpc/perf/core-fsl-emb.c | 3 ++-
 arch/x86/events/core.c           | 4 +++-
 arch/x86/events/intel/core.c     | 5 ++++-
 arch/x86/events/intel/knc.c      | 4 +++-
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 2b79171ee185..234803441caa 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2231,6 +2231,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 			       struct pt_regs *regs)
 {
 	u64 period = event->hw.sample_period;
+	const u64 last_period = event->hw.last_period;
 	s64 prev, delta, left;
 	int record = 0;
 
@@ -2296,7 +2297,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 	if (record) {
 		struct perf_sample_data data;
 
-		perf_sample_data_init(&data, ~0ULL, event->hw.last_period);
+		perf_sample_data_init(&data, ~0ULL, last_period);
 
 		if (event->attr.sample_type & PERF_SAMPLE_ADDR_TYPE)
 			perf_get_data_addr(event, regs, &data.addr);
diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c
index 1a53ab08447c..d2ffcc7021c5 100644
--- a/arch/powerpc/perf/core-fsl-emb.c
+++ b/arch/powerpc/perf/core-fsl-emb.c
@@ -590,6 +590,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 			       struct pt_regs *regs)
 {
 	u64 period = event->hw.sample_period;
+	const u64 last_period = event->hw.last_period;
 	s64 prev, delta, left;
 	int record = 0;
 
@@ -632,7 +633,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 	if (record) {
 		struct perf_sample_data data;
 
-		perf_sample_data_init(&data, 0, event->hw.last_period);
+		perf_sample_data_init(&data, 0, last_period);
 
 		if (perf_event_overflow(event, &data, regs))
 			fsl_emb_pmu_stop(event, 0);
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 8f218ac0d445..a78a8f3244ef 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1673,6 +1673,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
 	struct cpu_hw_events *cpuc;
 	struct perf_event *event;
 	int idx, handled = 0;
+	u64 last_period;
 	u64 val;
 
 	cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1692,6 +1693,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
 			continue;
 
 		event = cpuc->events[idx];
+		last_period = event->hw.last_period;
 
 		val = static_call(x86_pmu_update)(event);
 		if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
@@ -1705,7 +1707,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
 		if (!static_call(x86_pmu_set_period)(event))
 			continue;
 
-		perf_sample_data_init(&data, 0, event->hw.last_period);
+		perf_sample_data_init(&data, 0, last_period);
 
 		perf_sample_save_brstack(&data, event, &cpuc->lbr_stack, NULL);
 
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 7601196d1d18..add791c6e3d9 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3116,16 +3116,19 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
 
 	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
 		struct perf_event *event = cpuc->events[bit];
+		u64 last_period;
 
 		handled++;
 
 		if (!test_bit(bit, cpuc->active_mask))
 			continue;
 
+		last_period = event->hw.last_period;
+
 		if (!intel_pmu_save_and_restart(event))
 			continue;
 
-		perf_sample_data_init(&data, 0, event->hw.last_period);
+		perf_sample_data_init(&data, 0, last_period);
 
 		if (has_branch_stack(event))
 			intel_pmu_lbr_save_brstack(&data, cpuc, event);
diff --git a/arch/x86/events/intel/knc.c b/arch/x86/events/intel/knc.c
index 034a1f6a457c..3e8ec049b46d 100644
--- a/arch/x86/events/intel/knc.c
+++ b/arch/x86/events/intel/knc.c
@@ -241,16 +241,18 @@ static int knc_pmu_handle_irq(struct pt_regs *regs)
 
 	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
 		struct perf_event *event = cpuc->events[bit];
+		u64 last_period;
 
 		handled++;
 
 		if (!test_bit(bit, cpuc->active_mask))
 			continue;
 
+		last_period = event->hw.last_period;
 		if (!intel_pmu_save_and_restart(event))
 			continue;
 
-		perf_sample_data_init(&data, 0, event->hw.last_period);
+		perf_sample_data_init(&data, 0, last_period);
 
 		if (perf_event_overflow(event, &data, regs))
 			x86_pmu_stop(event, 0);
-- 
2.43.0



From mark.barnett at arm.com  Fri Mar  7 12:28:13 2025
From: mark.barnett at arm.com (Mark Barnett)
Date: Fri, 7 Mar 2025 20:28:13 +0000
Subject: [PATCH v2 1/5] perf: Allow periodic events to alternate between
 two sample periods
In-Reply-To: <20250121130154.GA416913@e132581.arm.com>
References: <20250106120156.227273-1-mark.barnett@arm.com>
 <20250106120156.227273-2-mark.barnett@arm.com>
 <20250121130154.GA416913@e132581.arm.com>
Message-ID: <c62a9f8a-312d-4f9e-9022-265e53564101@arm.com>

On 1/21/25 13:01, Leo Yan wrote:
>>   	local64_set(&hwc->period_left, hwc->sample_period);
>>   
>> +	if (attr->alt_sample_period) {
>> +		hwc->sample_period = attr->alt_sample_period;
>> +		hwc->using_alt_sample_period = true;
>> +	}
> 
> My understanding it sets a short sample window for the first period.
> Would it initialize the `hwc->period_left` with the updated sample
> period?
> 

It sets the long period first: hwc->period_left is used to program the 
PMU when setting up the event, and hwc->sample_period is queued up as 
the next period to switch to.

>> +
>> +	/*
>> +	 * alt_sample_period cannot be used with freq
>> +	 */
>> +	if (attr->freq && attr->alt_sample_period)
>> +		goto err_ns;
>> +
> 
> It is good to validate parameters first. So move the checking before
> the adjustment for the alt sample period.
> 

Ack. Done.

>>   	/*
>>   	 * We do not support PERF_SAMPLE_READ on inherited events unless
>>   	 * PERF_SAMPLE_TID is also selected, which allows inherited events to
>> @@ -12763,9 +12788,19 @@ SYSCALL_DEFINE5(perf_event_open,
>>   	if (attr.freq) {
>>   		if (attr.sample_freq > sysctl_perf_event_sample_rate)
>>   			return -EINVAL;
>> +		if (attr.alt_sample_period)
>> +			return -EINVAL;
>>   	} else {
>>   		if (attr.sample_period & (1ULL << 63))
>>   			return -EINVAL;
>> +		if (attr.alt_sample_period) {
>> +			if (!attr.sample_period)
>> +				return -EINVAL;
>> +			if (attr.alt_sample_period & (1ULL << 63))
>> +				return -EINVAL;
>> +			if (attr.alt_sample_period == attr.sample_period)
>> +				attr.alt_sample_period = 0;
> 
> In theory, the attr.alt_sample_period should be less than
> attr.sample_period, right?
> 

Added some validation for this.



From robh at kernel.org  Fri Mar  7 12:56:38 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 7 Mar 2025 14:56:38 -0600
Subject: [PATCH 3/7] ASoC: dt-bindings: add schema for rockchip SAI
 controllers
In-Reply-To: <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
References: <20250305-rk3576-sai-v1-0-64e6cf863e9a@collabora.com>
 <20250305-rk3576-sai-v1-3-64e6cf863e9a@collabora.com>
Message-ID: <20250307205638.GA595584-robh@kernel.org>

On Wed, Mar 05, 2025 at 10:24:23PM +0100, Nicolas Frattaroli wrote:
> Rockchip introduced a new audio controller called the "Serial Audio
> Interface", or "SAI" for short, on some of their newer SoCs. In
> particular, this controller is used several times on the RK3576 SoC.
> 
> Add a schema for it, with only an RK3576 compatible for now. Other SoCs
> may follow as mainline support for them lands.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
>  .../devicetree/bindings/sound/rockchip,sai.yaml    | 151 +++++++++++++++++++++
>  MAINTAINERS                                        |   6 +
>  2 files changed, 157 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/rockchip,sai.yaml b/Documentation/devicetree/bindings/sound/rockchip,sai.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..8f5a292a7f2a6c737d983d00cbe40ec45bfa6249
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/rockchip,sai.yaml
> @@ -0,0 +1,151 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/rockchip,sai.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Rockchip Serial Audio Interface Controller
> +
> +description:
> +  The Rockchip Serial Audio Interface (SAI) controller is a flexible audio
> +  controller that implements the I2S, I2S/TDM and the PDM standards.
> +
> +maintainers:
> +  - Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> +
> +allOf:
> +  - $ref: dai-common.yaml#
> +
> +properties:
> +  compatible:
> +    const: rockchip,rk3576-sai
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  dmas:
> +    minItems: 1
> +    maxItems: 2
> +
> +  dma-names:
> +    minItems: 1
> +    maxItems: 2
> +    oneOf:
> +      - const: tx
> +      - const: rx
> +      - items:
> +          - const: tx
> +          - const: rx

You can simplify this to:

minItems: 1
items:
  - enum: [tx, rx]
  - const: rx

(By default, we require unique items, so '"rx", "rx"' won't be allowed.

Rob


From nm at ti.com  Fri Mar  7 13:05:17 2025
From: nm at ti.com (Nishanth Menon)
Date: Fri, 7 Mar 2025 15:05:17 -0600
Subject: [PATCH v2 1/1] soc: ti: PRUSS OCP configuration
In-Reply-To: <20250108125937.10604-2-basharath@couthit.com>
References: <20250108125937.10604-1-basharath@couthit.com>
 <20250108125937.10604-2-basharath@couthit.com>
Message-ID: <20250307210517.5xjfc6wntcbj3s4k@precision>

On 18:29-20250108, Basharath Hussain Khaja wrote:
> From: Roger Quadros <rogerq at ti.com>
> 
> Updates OCP master port configuration to enable memory access outside
> of the PRU-ICSS subsystem.
> 
> This set of changes configures PRUSS_SYSCFG.STANDBY_INIT bit either
> to enable or disable the OCP master ports (applicable only on SoCs
> using OCP interconnect like the OMAP family).
> 
> Signed-off-by: Roger Quadros <rogerq at ti.com>
> Signed-off-by: Andrew F. Davis <afd at ti.com>
> Signed-off-by: Parvathi Pudi <parvathi at couthit.com>
> Signed-off-by: Basharath Hussain Khaja <basharath at couthit.com>

On the verge of applying this patch, looking deeper, I noticed
drivers/bus/ti-sysc.c managing the sysc controls. infact, I wonder if
b2745d92bb015cc4454d4195c4ce6e2852db397e ("bus: ti-sysc: Add support
for PRUSS SYSC type") could be merged with this?


Could you say why drivers/bus/ti-sysc.c would'nt be the right solution?

Ccying Kevin if he has any ideas about this.

-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D


From robh at kernel.org  Fri Mar  7 13:16:27 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 7 Mar 2025 15:16:27 -0600
Subject: [PATCH] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph
 port
In-Reply-To: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
References: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
Message-ID: <174138218697.627767.13339354154836355271.robh@kernel.org>


On Thu, 06 Mar 2025 13:31:38 +0800, Shengjiu Wang wrote:
> This device can be used in conjunction with audio-graph-card to provide
> an endpoint for binding with the other side of the audio link.
> 
> Signed-off-by: Shengjiu Wang <shengjiu.wang at nxp.com>
> ---
>  .../devicetree/bindings/sound/fsl,imx-asrc.yaml      | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From slavine at d3embedded.com  Fri Mar  7 13:21:09 2025
From: slavine at d3embedded.com (Sebastian LaVine)
Date: Fri, 07 Mar 2025 16:21:09 -0500
Subject: [PATCH 2/4] media: i2c: Add driver for Sony IMX728
In-Reply-To: <f18d5d31-09ab-4422-b56d-3361e4d3b9c8@kernel.org>
References: <20250212195656.69528-1-slavine@d3embedded.com>
 <20250212195656.69528-3-slavine@d3embedded.com>
 <f18d5d31-09ab-4422-b56d-3361e4d3b9c8@kernel.org>
Message-ID: <D8ACKEK4QS1G.2QTKXG691PVZY@d3embedded.com>

On Thu Feb 13, 2025 at 1:19 PM EST, Krzysztof Kozlowski wrote:
>
> ...
>
>> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
>> index c62831e61586..0ff578bb4645 100644
>> --- a/arch/arm64/configs/defconfig
>> +++ b/arch/arm64/configs/defconfig
>> @@ -852,6 +852,7 @@ CONFIG_VIDEO_TI_J721E_CSI2RX=m
>>  CONFIG_VIDEO_HANTRO=m
>>  CONFIG_VIDEO_IMX219=m
>>  CONFIG_VIDEO_IMX412=m
>> +CONFIG_VIDEO_IMX728=m
>>  CONFIG_VIDEO_OV5640=m
>
> This is not related to this patch and should target different subsystem
> with its own explanation why you thing this should be in common defconfig.

Thanks, I will remove this in v4.

-Sebastian
Please be aware that this email includes email addresses outside of the organization.


From nunodasneves at linux.microsoft.com  Fri Mar  7 13:36:48 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 13:36:48 -0800
Subject: [PATCH v5 03/10] arm64/hyperv: Add some missing functions to
 arm64
In-Reply-To: <SN6PR02MB41579F4147561B96A2C1C057D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-4-git-send-email-nunodasneves@linux.microsoft.com>
 <5f3d660d-fe2e-4ac1-94a7-66d6c8ffe579@linux.microsoft.com>
 <2fee888a-4f81-40aa-9545-617a49a7fb30@linux.microsoft.com>
 <SN6PR02MB41579F4147561B96A2C1C057D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <7f689725-f676-4465-974d-ca2477d445f7@linux.microsoft.com>

On 3/6/2025 11:05 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Thursday, February 27, 2025 4:21 PM
>>
>> On 2/26/2025 9:56 PM, Easwar Hariharan wrote:
>>> On 2/26/2025 3:07 PM, Nuno Das Neves wrote:
>>>> These non-nested msr and fast hypercall functions are present in x86,
>>>> but they must be available in both architetures for the root partition
>>>
>>> nit: *architectures*
>>>
>>>
>> Thanks!
>>
>>>> driver code.
>>>>
>>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>>> ---
>>>>  arch/arm64/hyperv/hv_core.c       | 17 +++++++++++++++++
>>>>  arch/arm64/include/asm/mshyperv.h | 12 ++++++++++++
>>>>  include/asm-generic/mshyperv.h    |  2 ++
>>>>  3 files changed, 31 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
>>>> index 69004f619c57..e33a9e3c366a 100644
>>>> --- a/arch/arm64/hyperv/hv_core.c
>>>> +++ b/arch/arm64/hyperv/hv_core.c
>>>> @@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
>>>>  }
>>>>  EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
>>>>
>>>> +/*
>>>> + * hv_do_fast_hypercall16 -- Invoke the specified hypercall
>>>> + * with arguments in registers instead of physical memory.
>>>> + * Avoids the overhead of virt_to_phys for simple hypercalls.
>>>> + */
>>>> +u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
>>>> +{
>>>> +	struct arm_smccc_res	res;
>>>> +	u64			control;
>>>> +
>>>> +	control = (u64)code | HV_HYPERCALL_FAST_BIT;
>>>> +
>>>> +	arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
>>>> +	return res.a0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
>>>> +
>>>
>>> I'd like this to have been in arch/arm64/include/asm/mshyperv.h like its x86
>>> counterpart, but that's just my personal liking of symmetry. I see why it's here
>>> with its slow and 8-byte brethren.
>>>
>> Good point, I don't see a good reason this can't be in the header.
> 
> I was trying to remember if there was some reason I originally put
> hv_do_hypercall() and hv_do_fast_hypercall8() in the .c file instead of
> the header like on x86. But I don't remember a reason. During
> development, the code changed several times, and there might have
> been a reason that didn't persistent in the version that was finally
> accepted upstream.
> 
> My only comment is that hv_do_hypercall() and the 8 and 16 "fast"
> versions should probably stay together one place on the arm64 side,
> even if it doesn't match x86.
> 

I think I'll just keep them together here for now then. They
could be moved to the header in future if it seems worth doing.

>>
>>>>  /*
>>>>   * Set a single VP register to a 64-bit value.
>>>>   */
>>>> diff --git a/arch/arm64/include/asm/mshyperv.h
>> b/arch/arm64/include/asm/mshyperv.h
>>>> index 2e2f83bafcfb..2a900ba00622 100644
>>>> --- a/arch/arm64/include/asm/mshyperv.h
>>>> +++ b/arch/arm64/include/asm/mshyperv.h
>>>> @@ -40,6 +40,18 @@ static inline u64 hv_get_msr(unsigned int reg)
>>>>  	return hv_get_vpreg(reg);
>>>>  }
>>>>
>>>> +/*
>>>> + * Nested is not supported on arm64
>>>> + */
>>>> +static inline void hv_set_non_nested_msr(unsigned int reg, u64 value)
>>>> +{
>>>> +	hv_set_msr(reg, value);
>>>> +}
>>>
>>> empty line preferred here, also reported by checkpatch
>>>
>> Good point, missed that one...
>>
>>>> +static inline u64 hv_get_non_nested_msr(unsigned int reg)
>>>> +{
>>>> +	return hv_get_msr(reg);
>>>> +}
>>>> +
>>>>  /* SMCCC hypercall parameters */
>>>>  #define HV_SMCCC_FUNC_NUMBER	1
>>>>  #define HV_FUNC_ID	ARM_SMCCC_CALL_VAL(			\
>>>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>>>> index c020d5d0ec2a..258034dfd829 100644
>>>> --- a/include/asm-generic/mshyperv.h
>>>> +++ b/include/asm-generic/mshyperv.h
>>>> @@ -72,6 +72,8 @@ extern void * __percpu *hyperv_pcpu_output_arg;
>>>>
>>>>  extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
>>>>  extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
>>>> +extern u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
>>>> +
>>>
>>> checkpatch warns against putting externs in header files, and FWIW, if
>> hv_do_fast_hypercall16()
>>> for arm64 were in arch/arm64/include/asm/mshyperv.h like its x86 counterpart, you
>> probably
>>> wouldn't need this?
>>>
>> Yes I wondered about that warning. That's true, if I just put it in the arm64 header
>> then this won't be needed at all, so I might just do that!
> 
> I always thought the checkpatch warning was simply that "extern" on a function
> declaration is superfluous. You can omit "extern" and nothing changes. Of
> course, the same is not true for data items.
> Good point, I think I'll clean up these "extern"s in the next version.

Nuno

> Michael
> 
>>
>>>>  bool hv_isolation_type_snp(void);
>>>>  bool hv_isolation_type_tdx(void);
>>>>
> 



From catalin.marinas at arm.com  Fri Mar  7 13:37:05 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 7 Mar 2025 21:37:05 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <4c621070-688a-4a75-9134-ea19b6d20f04@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
 <Z8s-4OPE2DNSogwB@arm.com>
 <4c621070-688a-4a75-9134-ea19b6d20f04@arm.com>
Message-ID: <Z8tnARR2jSJEruLw@arm.com>

On Fri, Mar 07, 2025 at 06:53:37PM +0000, Robin Murphy wrote:
> On 2025-03-07 6:45 pm, Catalin Marinas wrote:
> > On Fri, Feb 28, 2025 at 05:00:05PM +0000, Kristina Martsenko wrote:
> > > +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> > > +				  unsigned long esr)
> > > +{
> > > +	switch (ex->type) {
> > > +	case EX_TYPE_UACCESS_CPY:
> > > +		return cpy_faulted_on_uaccess(ex, esr);
> > > +	default:
> > > +		return true;
> > > +	}
> > > +}
> > 
> > Not a problem with this patch but I wonder whether we should return
> > false for EX_TYPE_LOAD_UNALIGNED_ZEROPAD for completeness
> 
> Or maybe rather, true for EX_TYPE_UACCESS_ERR_ZERO and then false in the
> default case?

Yes.

> > (and remove
> > the EX_TYPE_KACCESS_ERR_ZERO, it's no longer used.
> 
> I think that's just hidden in the macro swamp of
> __get_mem_asm()/__put_mem_asm()...

Ah, you are right. I now recall I found them about a year ago but forgot
since.

-- 
Catalin


From nunodasneves at linux.microsoft.com  Fri Mar  7 13:38:42 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 13:38:42 -0800
Subject: [PATCH v5 06/10] Drivers/hv: Export some functions for use by
 root partition module
In-Reply-To: <SN6PR02MB415706E75693B821FAF0A231D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-7-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB415706E75693B821FAF0A231D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <bed778c5-4642-4429-914d-7ef2e6ecccc6@linux.microsoft.com>

On 3/6/2025 11:23 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
> 
> Nit: For the patch Subject line, use prefix "Drivers: hv:" instead of with a slash.
> That's what we usually use and what you have used for other patches in this
> series.
> 
Thanks, I thought I checked these but I guess I missed this! I'll update for v6.

>> get_hypervisor_version, hv_call_deposit_pages, hv_call_create_vp,
>> hv_call_deposit_pages, and hv_call_create_vp are all needed in module
>> with CONFIG_MSHV_ROOT=m.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> 
> Modulo the nit:
> 
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> 
>> ---
>>  arch/arm64/hyperv/mshyperv.c   | 1 +
>>  arch/x86/kernel/cpu/mshyperv.c | 1 +
>>  drivers/hv/hv_common.c         | 1 +
>>  drivers/hv/hv_proc.c           | 3 ++-
>>  4 files changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
>> index 2265ea5ce5ad..4e27cc29c79e 100644
>> --- a/arch/arm64/hyperv/mshyperv.c
>> +++ b/arch/arm64/hyperv/mshyperv.c
>> @@ -26,6 +26,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info
>> *info)
>>
>>  	return 0;
>>  }
>> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
>>
>>  static int __init hyperv_init(void)
>>  {
>> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
>> index 2c29dfd6de19..0116d0e96ef9 100644
>> --- a/arch/x86/kernel/cpu/mshyperv.c
>> +++ b/arch/x86/kernel/cpu/mshyperv.c
>> @@ -420,6 +420,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info
>> *info)
>>
>>  	return 0;
>>  }
>> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
>>
>>  static void __init ms_hyperv_init_platform(void)
>>  {
>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>> index ce20818688fe..252fd66ad4db 100644
>> --- a/drivers/hv/hv_common.c
>> +++ b/drivers/hv/hv_common.c
>> @@ -717,6 +717,7 @@ int hv_result_to_errno(u64 status)
>>  	}
>>  	return -EIO;
>>  }
>> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
>>
>>  void hv_identify_partition_type(void)
>>  {
>> diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
>> index 8fc30f509fa7..20c8cee81e2b 100644
>> --- a/drivers/hv/hv_proc.c
>> +++ b/drivers/hv/hv_proc.c
>> @@ -108,6 +108,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
>>  	kfree(counts);
>>  	return ret;
>>  }
>> +EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
>>
>>  int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
>>  {
>> @@ -194,4 +195,4 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
>>
>>  	return ret;
>>  }
>> -
>> +EXPORT_SYMBOL_GPL(hv_call_create_vp);
>> --
>> 2.34.1



From Frank.Li at nxp.com  Fri Mar  7 13:50:59 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Fri,  7 Mar 2025 16:50:59 -0500
Subject: [PATCH] dt-bindings: dma: fsl-mxs-dma: Add compatible string for i.MX8 chips
Message-ID: <20250307215100.3257649-1-Frank.Li@nxp.com>

Add compatible string for all i.MX8 chips, which is backward compatible
with i.MX28. Set it to fall back to "fsl,imx28-dma-apbh".

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml b/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
index a17cf2360dd4a..75a7d9556699c 100644
--- a/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
@@ -31,6 +31,12 @@ properties:
               - fsl,imx6q-dma-apbh
               - fsl,imx6sx-dma-apbh
               - fsl,imx7d-dma-apbh
+              - fsl,imx8dxl-dma-apbh
+              - fsl,imx8mm-dma-apbh
+              - fsl,imx8mn-dma-apbh
+              - fsl,imx8mp-dma-apbh
+              - fsl,imx8mq-dma-apbh
+              - fsl,imx8qm-dma-apbh
               - fsl,imx8qxp-dma-apbh
           - const: fsl,imx28-dma-apbh
       - enum:
-- 
2.34.1



From dingwei at marvell.com  Fri Mar  7 13:52:32 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Fri, 7 Mar 2025 21:52:32 +0000
Subject: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add reset controller
 node
In-Reply-To: <2f39acd2-e378-47cf-b852-bee1a38108c5@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-4-dingwei@marvell.com>
 <d085c34a-fdbf-4950-a2e3-b3d25a1c0145@kernel.org>
 <BY3PR18MB46730C150D4CB9619B3B05FBA7CC2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <050ae833-10b5-4d80-9856-8bc2f434a74f@kernel.org>
 <BY3PR18MB46739700B533630D65C60808A7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <87b9e9c3-87db-4ebe-96b0-4f04705ef6f8@kernel.org>
 <BY3PR18MB4673B4CEB60D3D21AB17B01DA7C82@BY3PR18MB4673.namprd18.prod.outlook.com>
 <03b14353-5d47-48de-99fd-9cc48bad5651@kernel.org>
 <BY3PR18MB4673BD07048F8AF7EA55282CA7CA2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <2f39acd2-e378-47cf-b852-bee1a38108c5@kernel.org>
Message-ID: <BY3PR18MB4673E368B0A8D83755ACBDBCA7D52@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Friday, March 7, 2025 1:00 AM
> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> robh at kernel.org
> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> sebastian.hesselbarth at gmail.com; krzk+dt at kernel.org; conor+dt at kernel.org;
> p.zabel at pengutronix.de; Sanghoon Lee <salee at marvell.com>;
> Geethasowjanya Akula <gakula at marvell.com>
> Subject: Re: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x: Add
> reset controller node
> 
> On 06/03/2025 18:42, Wilson Ding wrote:
> >
> >
> >> -----Original Message-----
> >> From: Krzysztof Kozlowski <krzk at kernel.org>
> >> Sent: Wednesday, March 5, 2025 11:29 PM
> >> To: Wilson Ding <dingwei at marvell.com>; linux-kernel at vger.kernel.org;
> >> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> >> robh at kernel.org
> >> Cc: andrew at lunn.ch; gregory.clement at bootlin.com;
> >> sebastian.hesselbarth at gmail.com; krzk+dt at kernel.org;
> >> conor+dt at kernel.org; p.zabel at pengutronix.de; Sanghoon Lee
> >> <salee at marvell.com>; Geethasowjanya Akula <gakula at marvell.com>
> >> Subject: [EXTERNAL] Re: [PATCH v3 3/3] arm64: dts: marvell: cp11x:
> >> Add reset controller node
> >>
> >> On 04/03/2025 20:08, Wilson Ding wrote:
> >>>
> >>> I did consider shrinking the syscon's register address range to make
> >>> the reset-controller node to be independent from the syscon node.
> >>> However, I found the syscon node is also referred by some devices
> >>> for miscellaneous configurations . The reset configuration register
> >>> happens to be located in between these registers and clock/GPIO
> >>> registers.
> >>>
> >>>> drop offset in your patch or unify everything into 'reg'.
> >>>>
> >>>
> >>> This is exactly what I proposed in v3 patch. Do I misunderstand you?
> >>>
> >>> CP11X_LABEL(swrst): reset-controller at 268 {
> >>> 	compatible = "marvell,armada8k-reset";
> >>> 	reg = <0x268 0x4>;
> >>> 	#reset-cells = <1>;
> >>> };
> >>
> >> I don't see the other device being fixed here. How did you unify them?
> >
> > This patch series is about the proposal of Armada8K's reset controller
> > dt-binding. The dt-bindings issues of clock/GPIO controllers have been
> > there for years. Having to say, it is not just a simple patch to fix
> > it. It
> 
> 
> I understand, you just want to throw your patch here over the wall. It's
> reasonable, I feel it. Just like previous cases for this binding - everyone wanted
> one subnode at a time, ignoring bigger picture, each time making it franken-
> node or franken-binding.
> 
> Please listen to Greg's talk from years ago about upstreaming. "I don't want
> your code":
> https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__www.youtube.com_watch-3Fv-
> 3DfMeH7wqOwXA&d=DwICaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=sXDQZu4G
> yqNVDlFUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=JlqowP3KS_dAuPARdfHNUE
> mdfiBr1kVd2ia1atnDNxBMMB5ccqNUuU1qtNhJMhzE&s=WpwrGxdqS7L0Bz-
> fKr_AdTuLBD2v-0OEKSRBOG05wKs&e=
> 

Sorry, I will fix them in next version.

> 
> Best regards,
> Krzysztof

From eahariha at linux.microsoft.com  Fri Mar  7 13:55:22 2025
From: eahariha at linux.microsoft.com (Easwar Hariharan)
Date: Fri, 7 Mar 2025 13:55:22 -0800
Subject: [PATCH v5 03/10] arm64/hyperv: Add some missing functions to
 arm64
In-Reply-To: <7f689725-f676-4465-974d-ca2477d445f7@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-4-git-send-email-nunodasneves@linux.microsoft.com>
 <5f3d660d-fe2e-4ac1-94a7-66d6c8ffe579@linux.microsoft.com>
 <2fee888a-4f81-40aa-9545-617a49a7fb30@linux.microsoft.com>
 <SN6PR02MB41579F4147561B96A2C1C057D4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <7f689725-f676-4465-974d-ca2477d445f7@linux.microsoft.com>
Message-ID: <9cd97b0e-dfd3-4923-961e-00ba09eb6cef@linux.microsoft.com>

On 3/7/2025 1:36 PM, Nuno Das Neves wrote:
> On 3/6/2025 11:05 AM, Michael Kelley wrote:
>> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Thursday, February 27, 2025 4:21 PM
>>>
>>> On 2/26/2025 9:56 PM, Easwar Hariharan wrote:
>>>> On 2/26/2025 3:07 PM, Nuno Das Neves wrote:
>>>>> These non-nested msr and fast hypercall functions are present in x86,
>>>>> but they must be available in both architetures for the root partition
>>>>
>>>> nit: *architectures*
>>>>
>>>>
>>> Thanks!
>>>
>>>>> driver code.
>>>>>
>>>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>>>> ---
>>>>>  arch/arm64/hyperv/hv_core.c       | 17 +++++++++++++++++
>>>>>  arch/arm64/include/asm/mshyperv.h | 12 ++++++++++++
>>>>>  include/asm-generic/mshyperv.h    |  2 ++
>>>>>  3 files changed, 31 insertions(+)
>>>>>
>>>>> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
>>>>> index 69004f619c57..e33a9e3c366a 100644
>>>>> --- a/arch/arm64/hyperv/hv_core.c
>>>>> +++ b/arch/arm64/hyperv/hv_core.c
>>>>> @@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
>>>>>  }
>>>>>  EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
>>>>>
>>>>> +/*
>>>>> + * hv_do_fast_hypercall16 -- Invoke the specified hypercall
>>>>> + * with arguments in registers instead of physical memory.
>>>>> + * Avoids the overhead of virt_to_phys for simple hypercalls.
>>>>> + */
>>>>> +u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
>>>>> +{
>>>>> +	struct arm_smccc_res	res;
>>>>> +	u64			control;
>>>>> +
>>>>> +	control = (u64)code | HV_HYPERCALL_FAST_BIT;
>>>>> +
>>>>> +	arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
>>>>> +	return res.a0;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
>>>>> +
>>>>
>>>> I'd like this to have been in arch/arm64/include/asm/mshyperv.h like its x86
>>>> counterpart, but that's just my personal liking of symmetry. I see why it's here
>>>> with its slow and 8-byte brethren.
>>>>
>>> Good point, I don't see a good reason this can't be in the header.
>>
>> I was trying to remember if there was some reason I originally put
>> hv_do_hypercall() and hv_do_fast_hypercall8() in the .c file instead of
>> the header like on x86. But I don't remember a reason. During
>> development, the code changed several times, and there might have
>> been a reason that didn't persistent in the version that was finally
>> accepted upstream.
>>
>> My only comment is that hv_do_hypercall() and the 8 and 16 "fast"
>> versions should probably stay together one place on the arm64 side,
>> even if it doesn't match x86.
>>
> 
> I think I'll just keep them together here for now then. They
> could be moved to the header in future if it seems worth doing.
> 

I was really hoping the answer here would be to move all of them together to the header,
but oh well.

<snip>


From alyssa at rosenzweig.io  Fri Mar  7 13:59:20 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Fri, 7 Mar 2025 16:59:20 -0500
Subject: [PATCH v2 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250307-spmi-v2-2-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
 <20250307-spmi-v2-2-eccdb06afb99@gmail.com>
Message-ID: <Z8tsOKbxVOXmOicF@blossom>

> +static inline u32 read_reg(struct apple_spmi *spmi, int offset)
> +{
> +	return readl(spmi->regs + offset);
> +}
> +
> +static inline void write_reg(u32 value, struct apple_spmi *spmi, int offset)
> +{
> +	writel(value, spmi->regs + offset);
> +}

At this point I don't think these are gaining us anything. Can we inline
them?


From romank at linux.microsoft.com  Fri Mar  7 14:02:54 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:54 -0800
Subject: [PATCH hyperv-next v5 02/11] arm64: hyperv: Use SMCCC to detect hypervisor presence
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-3-romank@linux.microsoft.com>

The arm64 Hyper-V startup path relies on ACPI to detect
running under a Hyper-V compatible hypervisor. That
doesn't work on non-ACPI systems.

Hoist the ACPI detection logic into a separate function. Then
use the vendor-specific hypervisor service call (implemented
recently in Hyper-V) via SMCCC in the non-ACPI case.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 29fcfd595f48..c647db56fd6b 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
 	return 0;
 }
 
+static bool __init hyperv_detect_via_acpi(void)
+{
+	if (acpi_disabled)
+		return false;
+#if IS_ENABLED(CONFIG_ACPI)
+	/*
+	 * Hypervisor ID is only available in ACPI v6+, and the
+	 * structure layout was extended in v6 to accommodate that
+	 * new field.
+	 *
+	 * At the very minimum, this check makes sure not to read
+	 * past the FADT structure.
+	 *
+	 * It is also needed to catch running in some unknown
+	 * non-Hyper-V environment that has ACPI 5.x or less.
+	 * In such a case, it can't be Hyper-V.
+	 */
+	if (acpi_gbl_FADT.header.revision < 6)
+		return false;
+	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
+#else
+	return false;
+#endif
+}
+
+static bool __init hyperv_detect_via_smccc(void)
+{
+	uuid_t hyperv_uuid = UUID_INIT(
+		0x4d32ba58, 0x4764, 0xcd24,
+		0x75, 0x6c, 0xef, 0x8e,
+		0x24, 0x70, 0x59, 0x16);
+
+	return arm_smccc_hyp_present(&hyperv_uuid);
+}
+
 static int __init hyperv_init(void)
 {
 	struct hv_get_vp_registers_output	result;
@@ -35,13 +70,11 @@ static int __init hyperv_init(void)
 
 	/*
 	 * Allow for a kernel built with CONFIG_HYPERV to be running in
-	 * a non-Hyper-V environment, including on DT instead of ACPI.
+	 * a non-Hyper-V environment.
+	 *
 	 * In such cases, do nothing and return success.
 	 */
-	if (acpi_disabled)
-		return 0;
-
-	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
+	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
 		return 0;
 
 	/* Setup the guest ID */
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:55 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:55 -0800
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for arm64
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-4-romank@linux.microsoft.com>

Kconfig dependencies for arm64 guests on Hyper-V require that be
ACPI enabled, and limit VTL mode to x86/x64. To enable VTL mode
on arm64 as well, update the dependencies. Since VTL mode requires
DeviceTree instead of ACPI, don?t require arm64 guests on Hyper-V
to have ACPI unconditionally.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/hv/Kconfig | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 862c47b191af..c37b1a44e580 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -5,18 +5,20 @@ menu "Microsoft Hyper-V guest support"
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
 	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
-		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
+		|| (ARM64 && !CPU_BIG_ENDIAN)
+	depends on (ACPI || HYPERV_VTL_MODE)
 	select PARAVIRT
 	select X86_HV_CALLBACK_VECTOR if X86
-	select OF_EARLY_FLATTREE if OF
 	help
 	  Select this option to run Linux as a Hyper-V client operating
 	  system.
 
 config HYPERV_VTL_MODE
 	bool "Enable Linux to boot in VTL context"
-	depends on X86_64 && HYPERV
+	depends on (X86_64 || ARM64)
 	depends on SMP
+	select OF_EARLY_FLATTREE
+	select OF
 	default n
 	help
 	  Virtual Secure Mode (VSM) is a set of hypervisor capabilities and
@@ -31,7 +33,7 @@ config HYPERV_VTL_MODE
 
 	  Select this option to build a Linux kernel to run at a VTL other than
 	  the normal VTL0, which currently is only VTL2.  This option
-	  initializes the x86 platform for VTL2, and adds the ability to boot
+	  initializes the kernel to run in VTL2, and adds the ability to boot
 	  secondary CPUs directly into 64-bit context as required for VTLs other
 	  than 0.  A kernel built with this option must run at VTL2, and will
 	  not run as a normal guest.
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:56 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:56 -0800
Subject: [PATCH hyperv-next v5 04/11] Drivers: hv: Provide arch-neutral implementation of get_vtl()
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-5-romank@linux.microsoft.com>

To run in the VTL mode, Hyper-V drivers have to know what
VTL the system boots in, and the arm64/hyperv code does not
have the means to compute that.

Refactor the code to hoist the function that detects VTL,
make it arch-neutral to be able to employ it to get the VTL
on arm64.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 arch/x86/hyperv/hv_init.c      | 34 ----------------------------------
 drivers/hv/hv_common.c         | 31 +++++++++++++++++++++++++++++++
 include/asm-generic/mshyperv.h |  6 ++++++
 include/hyperv/hvgdk_mini.h    |  2 +-
 4 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 9be1446f5bd3..e204cb9d41af 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -390,40 +390,6 @@ static void __init hv_stimer_setup_percpu_clockev(void)
 		old_setup_percpu_clockev();
 }
 
-#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
-static u8 __init get_vtl(void)
-{
-	u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
-	struct hv_input_get_vp_registers *input;
-	struct hv_output_get_vp_registers *output;
-	unsigned long flags;
-	u64 ret;
-
-	local_irq_save(flags);
-	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
-	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
-
-	memset(input, 0, struct_size(input, names, 1));
-	input->partition_id = HV_PARTITION_ID_SELF;
-	input->vp_index = HV_VP_INDEX_SELF;
-	input->input_vtl.as_uint8 = 0;
-	input->names[0] = HV_REGISTER_VSM_VP_STATUS;
-
-	ret = hv_do_hypercall(control, input, output);
-	if (hv_result_success(ret)) {
-		ret = output->values[0].reg8 & HV_X64_VTL_MASK;
-	} else {
-		pr_err("Failed to get VTL(error: %lld) exiting...\n", ret);
-		BUG();
-	}
-
-	local_irq_restore(flags);
-	return ret;
-}
-#else
-static inline u8 get_vtl(void) { return 0; }
-#endif
-
 /*
  * This function is to be invoked early in the boot sequence after the
  * hypervisor has been detected.
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index ee3083937b4f..10983e854a4d 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -304,6 +304,37 @@ void __init hv_get_partition_id(void)
 		pr_err("Hyper-V: failed to get partition ID: %#x\n",
 		       hv_result(status));
 }
+#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
+u8 __init get_vtl(void)
+{
+	u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
+	struct hv_input_get_vp_registers *input;
+	struct hv_output_get_vp_registers *output;
+	unsigned long flags;
+	u64 ret;
+
+	local_irq_save(flags);
+	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
+	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
+
+	memset(input, 0, struct_size(input, names, 1));
+	input->partition_id = HV_PARTITION_ID_SELF;
+	input->vp_index = HV_VP_INDEX_SELF;
+	input->input_vtl.as_uint8 = 0;
+	input->names[0] = HV_REGISTER_VSM_VP_STATUS;
+
+	ret = hv_do_hypercall(control, input, output);
+	if (hv_result_success(ret)) {
+		ret = output->values[0].reg8 & HV_VTL_MASK;
+	} else {
+		pr_err("Failed to get VTL(error: %lld) exiting...\n", ret);
+		BUG();
+	}
+
+	local_irq_restore(flags);
+	return ret;
+}
+#endif
 
 int __init hv_common_init(void)
 {
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 7adc10a4fa3e..bf897c528976 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -320,4 +320,10 @@ static inline enum hv_isolation_type hv_get_isolation_type(void)
 }
 #endif /* CONFIG_HYPERV */
 
+#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
+u8 __init get_vtl(void);
+#else
+static inline u8 get_vtl(void) { return 0; }
+#endif
+
 #endif
diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
index 58895883f636..98aa64e8844c 100644
--- a/include/hyperv/hvgdk_mini.h
+++ b/include/hyperv/hvgdk_mini.h
@@ -1202,7 +1202,7 @@ struct hv_send_ipi {	 /* HV_INPUT_SEND_SYNTHETIC_CLUSTER_IPI */
 	u64 cpu_mask;
 } __packed;
 
-#define	HV_X64_VTL_MASK			GENMASK(3, 0)
+#define	HV_VTL_MASK			GENMASK(3, 0)
 
 /* Hyper-V memory host visibility */
 enum hv_mem_host_visibility {
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:57 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:57 -0800
Subject: [PATCH hyperv-next v5 05/11] arm64: hyperv: Initialize the Virtual Trust Level field
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-6-romank@linux.microsoft.com>

Various parts of the hyperv code need to know what VTL
the kernel runs at, most notably VMBus needs that to
establish communication with the host.

Initialize the Virtual Trust Level field to enable
booting in the Virtual Trust Level.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/hyperv/mshyperv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index c647db56fd6b..a7db03f5413d 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -107,6 +107,7 @@ static int __init hyperv_init(void)
 
 	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
 		hv_get_partition_id();
+	ms_hyperv.vtl = get_vtl();
 
 	ms_hyperv_late_init();
 
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:58 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:58 -0800
Subject: [PATCH hyperv-next v5 06/11] arm64, x86: hyperv: Report the VTL the system boots in
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-7-romank@linux.microsoft.com>

The hyperv guest code might run in various Virtual Trust Levels.

Report the level when the kernel boots in the non-default (0)
one.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/hyperv/mshyperv.c | 2 ++
 arch/x86/hyperv/hv_vtl.c     | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index a7db03f5413d..3bc16dbee758 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -108,6 +108,8 @@ static int __init hyperv_init(void)
 	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
 		hv_get_partition_id();
 	ms_hyperv.vtl = get_vtl();
+	if (ms_hyperv.vtl > 0) /* non default VTL */
+		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
 
 	ms_hyperv_late_init();
 
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 4e1b1e3b5658..c21bee7e8ff3 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -24,7 +24,7 @@ static bool __init hv_vtl_msi_ext_dest_id(void)
 
 void __init hv_vtl_init_platform(void)
 {
-	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
+	pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
 
 	x86_platform.realmode_reserve = x86_init_noop;
 	x86_platform.realmode_init = x86_init_noop;
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:59 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:59 -0800
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add interrupts and DMA coherence
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-8-romank@linux.microsoft.com>

To boot on ARM64, VMBus requires configuring interrupts. Missing
DMA coherence property is sub-optimal as the VMBus transations are
cache-coherent.

Add interrupts to be able to boot on ARM64. Add DMA coherence to
avoid doing extra work on maintaining caches on ARM64.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 .../devicetree/bindings/bus/microsoft,vmbus.yaml          | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
index a8d40c766dcd..3ab7d0116626 100644
--- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
+++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
@@ -28,13 +28,16 @@ properties:
 required:
   - compatible
   - ranges
+  - interrupts
   - '#address-cells'
   - '#size-cells'
 
-additionalProperties: false
+additionalProperties: true
 
 examples:
   - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
     soc {
         #address-cells = <2>;
         #size-cells = <1>;
@@ -49,6 +52,9 @@ examples:
                 #address-cells = <2>;
                 #size-cells = <1>;
                 ranges = <0x0f 0xf0000000 0x0f 0xf0000000 0x10000000>;
+                dma-coherent;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_PPI 2 IRQ_TYPE_EDGE_RISING>;
             };
         };
     };
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:03:00 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:03:00 -0800
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ number from DeviceTree
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-9-romank@linux.microsoft.com>

The VMBus driver uses ACPI for interrupt assignment on
arm64 hence it won't function in the VTL mode where only
DeviceTree can be used.

Update the VMBus driver to discover interrupt configuration
from DT.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 drivers/hv/vmbus_drv.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 75eb1390b45c..c8474b48dcd2 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2345,6 +2345,36 @@ static int vmbus_acpi_add(struct platform_device *pdev)
 }
 #endif
 
+static int __maybe_unused vmbus_set_irq(struct platform_device *pdev)
+{
+	struct irq_data *data;
+	int irq;
+	irq_hw_number_t hwirq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq == 0) {
+		pr_err("VMBus interrupt mapping failure\n");
+		return -EINVAL;
+	}
+	if (irq < 0) {
+		pr_err("VMBus interrupt data can't be read from DeviceTree, error %d\n", irq);
+		return irq;
+	}
+
+	data = irq_get_irq_data(irq);
+	if (!data) {
+		pr_err("No interrupt data for VMBus virq %d\n", irq);
+		return -ENODEV;
+	}
+	hwirq = irqd_to_hwirq(data);
+
+	vmbus_irq = irq;
+	vmbus_interrupt = hwirq;
+	pr_debug("VMBus virq %d, hwirq %d\n", vmbus_irq, vmbus_interrupt);
+
+	return 0;
+}
+
 static int vmbus_device_add(struct platform_device *pdev)
 {
 	struct resource **cur_res = &hyperv_mmio;
@@ -2359,6 +2389,12 @@ static int vmbus_device_add(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+#ifndef HYPERVISOR_CALLBACK_VECTOR
+	ret = vmbus_set_irq(pdev);
+	if (ret)
+		return ret;
+#endif
+
 	for_each_of_range(&parser, &range) {
 		struct resource *res;
 
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:03:01 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:03:01 -0800
Subject: [PATCH hyperv-next v5 09/11] Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-10-romank@linux.microsoft.com>

The ARM64 PCI code for hyperv needs to know the VMBus root
device, and it is private.

Provide a function that returns it. Rename it from "hv_dev"
as "hv_dev" as a symbol is very overloaded. No functional
changes.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/hv/vmbus_drv.c | 23 +++++++++++++++--------
 include/linux/hyperv.h |  2 ++
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index c8474b48dcd2..7bfafe702963 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -45,7 +45,8 @@ struct vmbus_dynid {
 	struct hv_vmbus_device_id id;
 };
 
-static struct device  *hv_dev;
+/* VMBus Root Device */
+static struct device  *vmbus_root_device;
 
 static int hyperv_cpuhp_online;
 
@@ -80,9 +81,15 @@ static struct resource *fb_mmio;
 static struct resource *hyperv_mmio;
 static DEFINE_MUTEX(hyperv_mmio_lock);
 
+struct device *hv_get_vmbus_root_device(void)
+{
+	return vmbus_root_device;
+}
+EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
+
 static int vmbus_exists(void)
 {
-	if (hv_dev == NULL)
+	if (vmbus_root_device == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -861,7 +868,7 @@ static int vmbus_dma_configure(struct device *child_device)
 	 * On x86/x64 coherence is assumed and these calls have no effect.
 	 */
 	hv_setup_dma_ops(child_device,
-		device_get_dma_attr(hv_dev) == DEV_DMA_COHERENT);
+		device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
 	return 0;
 }
 
@@ -1930,7 +1937,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
 		     &child_device_obj->channel->offermsg.offer.if_instance);
 
 	child_device_obj->device.bus = &hv_bus;
-	child_device_obj->device.parent = hv_dev;
+	child_device_obj->device.parent = vmbus_root_device;
 	child_device_obj->device.release = vmbus_device_release;
 
 	child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
@@ -2292,7 +2299,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
 	struct acpi_device *ancestor;
 	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
 
-	hv_dev = &device->dev;
+	vmbus_root_device = &device->dev;
 
 	/*
 	 * Older versions of Hyper-V for ARM64 fail to include the _CCA
@@ -2383,7 +2390,7 @@ static int vmbus_device_add(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	int ret;
 
-	hv_dev = &pdev->dev;
+	vmbus_root_device = &pdev->dev;
 
 	ret = of_range_parser_init(&parser, np);
 	if (ret)
@@ -2702,7 +2709,7 @@ static int __init hv_acpi_init(void)
 	if (ret)
 		return ret;
 
-	if (!hv_dev) {
+	if (!vmbus_root_device) {
 		ret = -ENODEV;
 		goto cleanup;
 	}
@@ -2733,7 +2740,7 @@ static int __init hv_acpi_init(void)
 
 cleanup:
 	platform_driver_unregister(&vmbus_platform_driver);
-	hv_dev = NULL;
+	vmbus_root_device = NULL;
 	return ret;
 }
 
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 7f4f8d8bdf43..1f0851fde041 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1333,6 +1333,8 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
 	return dev_get_drvdata(&dev->device);
 }
 
+struct device *hv_get_vmbus_root_device(void);
+
 struct hv_ring_buffer_debug_info {
 	u32 current_interrupt_mask;
 	u32 current_read_index;
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:03:02 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:03:02 -0800
Subject: [PATCH hyperv-next v5 10/11] ACPI: irq: Introduce acpi_get_gsi_dispatcher()
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-11-romank@linux.microsoft.com>

Using acpi_irq_create_hierarchy() in the cases where the code
also handles OF leads to code duplication as the ACPI subsystem
doesn't provide means to compute the IRQ domain parent whereas
the OF does.

Introduce acpi_get_gsi_dispatcher() so that the drivers relying
on both ACPI and OF may use irq_domain_create_hierarchy() in the
common code paths.

No functional changes.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/acpi/irq.c   | 14 ++++++++++++--
 include/linux/acpi.h |  5 ++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 1687483ff319..6243db610137 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -12,7 +12,7 @@
 
 enum acpi_irq_model_id acpi_irq_model;
 
-static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi);
+static acpi_gsi_domain_disp_fn acpi_get_gsi_domain_id;
 static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi);
 
 /**
@@ -307,12 +307,22 @@ EXPORT_SYMBOL_GPL(acpi_irq_get);
  *	for a given GSI
  */
 void __init acpi_set_irq_model(enum acpi_irq_model_id model,
-			       struct fwnode_handle *(*fn)(u32))
+	acpi_gsi_domain_disp_fn fn)
 {
 	acpi_irq_model = model;
 	acpi_get_gsi_domain_id = fn;
 }
 
+/**
+ * acpi_get_gsi_dispatcher - Returns dispatcher function that
+ *                           computes the domain fwnode for a
+ *                           given GSI.
+ */
+acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void)
+{
+	return acpi_get_gsi_domain_id;
+}
+
 /**
  * acpi_set_gsi_to_irq_fallback - Register a GSI transfer
  * callback to fallback to arch specified implementation.
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4e495b29c640..abc51288e867 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -336,8 +336,11 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
+typedef struct fwnode_handle *(*acpi_gsi_domain_disp_fn)(u32);
+
 void acpi_set_irq_model(enum acpi_irq_model_id model,
-			struct fwnode_handle *(*)(u32));
+	acpi_gsi_domain_disp_fn fn);
+acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void);
 void acpi_set_gsi_to_irq_fallback(u32 (*)(u32));
 
 struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:03:03 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:03:03 -0800
Subject: [PATCH hyperv-next v5 11/11] PCI: hv: Get vPCI MSI IRQ domain from DeviceTree
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-12-romank@linux.microsoft.com>

The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
arm64. It won't be able to do that in the VTL mode where only DeviceTree
can be used.

Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
case, too.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/pci/controller/pci-hyperv.c | 79 ++++++++++++++++++++++++++---
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 6084b38bdda1..9740006a8c73 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -50,6 +50,7 @@
 #include <linux/irqdomain.h>
 #include <linux/acpi.h>
 #include <linux/sizes.h>
+#include <linux/of_irq.h>
 #include <asm/mshyperv.h>
 
 /*
@@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
 	int ret;
 
 	fwspec.fwnode = domain->parent->fwnode;
-	fwspec.param_count = 2;
-	fwspec.param[0] = hwirq;
-	fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+	if (is_of_node(fwspec.fwnode)) {
+		/* SPI lines for OF translations start at offset 32 */
+		fwspec.param_count = 3;
+		fwspec.param[0] = 0;
+		fwspec.param[1] = hwirq - 32;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		fwspec.param_count = 2;
+		fwspec.param[0] = hwirq;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+	}
 
 	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (ret)
@@ -887,10 +896,53 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
 	.activate = hv_pci_vec_irq_domain_activate,
 };
 
+#ifdef CONFIG_OF
+
+static struct irq_domain *hv_pci_of_irq_domain_parent(void)
+{
+	struct device_node *parent;
+	struct irq_domain *domain;
+
+	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
+	domain = NULL;
+	if (parent) {
+		domain = irq_find_host(parent);
+		of_node_put(parent);
+	}
+
+	return domain;
+}
+
+#endif
+
+#ifdef CONFIG_ACPI
+
+static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
+{
+	struct irq_domain *domain;
+	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
+
+	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
+		return NULL;
+	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
+	if (!gsi_domain_disp_fn)
+		return NULL;
+	domain = irq_find_matching_fwnode(gsi_domain_disp_fn(0),
+				     DOMAIN_BUS_ANY);
+
+	if (!domain)
+		return NULL;
+
+	return domain;
+}
+
+#endif
+
 static int hv_pci_irqchip_init(void)
 {
 	static struct hv_pci_chip_data *chip_data;
 	struct fwnode_handle *fn = NULL;
+	struct irq_domain *irq_domain_parent = NULL;
 	int ret = -ENOMEM;
 
 	chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
@@ -907,9 +959,24 @@ static int hv_pci_irqchip_init(void)
 	 * way to ensure that all the corresponding devices are also gone and
 	 * no interrupts will be generated.
 	 */
-	hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
-							  fn, &hv_pci_domain_ops,
-							  chip_data);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled)
+		irq_domain_parent = hv_pci_acpi_irq_domain_parent();
+#endif
+#if defined(CONFIG_OF)
+	if (!irq_domain_parent)
+		irq_domain_parent = hv_pci_of_irq_domain_parent();
+#endif
+	if (!irq_domain_parent) {
+		WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
+		ret = -EINVAL;
+		goto free_chip;
+	}
+
+	hv_msi_gic_irq_domain = irq_domain_create_hierarchy(
+		irq_domain_parent, 0, HV_PCI_MSI_SPI_NR,
+		fn, &hv_pci_domain_ops,
+		chip_data);
 
 	if (!hv_msi_gic_irq_domain) {
 		pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:53 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:53 -0800
Subject: [PATCH hyperv-next v5 01/11] arm64: kvm, smccc: Introduce and use API for detectting hypervisor presence
In-Reply-To: <20250307220304.247725-1-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
Message-ID: <20250307220304.247725-2-romank@linux.microsoft.com>

The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
private, and it follows the SMCCC specification. Other existing and
emerging hypervisor guest implementations can and should use that
standard approach as well.

Factor out a common infrastructure that the guests can use, update KVM
to employ the new API. The cenrtal notion of the SMCCC method is the
UUID of the hypervisor, and the API follows that.

No functional changes. Validated with a KVM/arm64 guest.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/kvm/hypercalls.c        |  5 +--
 drivers/firmware/smccc/kvm_guest.c | 10 ++----
 drivers/firmware/smccc/smccc.c     | 19 +++++++++++
 include/linux/arm-smccc.h          | 55 +++++++++++++++++++++++++++---
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 27ce4cb44904..92b9bc1ea8e8 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -353,10 +353,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
 			val[0] = gpa;
 		break;
 	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
-		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
-		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
-		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
-		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
+		UUID_TO_SMCCC_RES(ARM_SMCCC_VENDOR_HYP_UID_KVM, val);
 		break;
 	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
 		val[0] = smccc_feat->vendor_hyp_bmap;
diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
index f3319be20b36..b5084b309ea0 100644
--- a/drivers/firmware/smccc/kvm_guest.c
+++ b/drivers/firmware/smccc/kvm_guest.c
@@ -14,17 +14,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
 
 void __init kvm_init_hyp_services(void)
 {
+	uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
 	struct arm_smccc_res res;
 	u32 val[4];
 
-	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
-		return;
-
-	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
-	if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
-	    res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
-	    res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
-	    res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
+	if (!arm_smccc_hyp_present(&kvm_uuid))
 		return;
 
 	memset(&res, 0, sizeof(res));
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
index a74600d9f2d7..7399f27d58e5 100644
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -67,6 +67,25 @@ s32 arm_smccc_get_soc_id_revision(void)
 }
 EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
 
+bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
+{
+	struct arm_smccc_res res = {};
+
+	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
+		return false;
+	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
+	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+		return false;
+
+	return ({
+		const uuid_t uuid = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
+		const bool present = uuid_equal(&uuid, hyp_uuid);
+
+		present;
+	});
+}
+EXPORT_SYMBOL_GPL(arm_smccc_hyp_present);
+
 static int __init smccc_devices_init(void)
 {
 	struct platform_device *pdev;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 67f6fdf2e7cd..726f18221f1c 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -7,6 +7,11 @@
 
 #include <linux/args.h>
 #include <linux/init.h>
+
+#ifndef __ASSEMBLER__
+#include <linux/uuid.h>
+#endif
+
 #include <uapi/linux/const.h>
 
 /*
@@ -107,10 +112,10 @@
 			   ARM_SMCCC_FUNC_QUERY_CALL_UID)
 
 /* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0	0xb66fb428U
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1	0xe911c52eU
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2	0x564bcaa9U
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3	0x743a004dU
+#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
+	0xb66fb428, 0xc52e, 0xe911, \
+	0xa9, 0xca, 0x4b, 0x56, \
+	0x4d, 0x00, 0x3a, 0x74)
 
 /* KVM "vendor specific" services */
 #define ARM_SMCCC_KVM_FUNC_FEATURES		0
@@ -333,6 +338,48 @@ s32 arm_smccc_get_soc_id_version(void);
  */
 s32 arm_smccc_get_soc_id_revision(void);
 
+#ifndef __ASSEMBLER__
+
+/**
+ * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
+ *
+ * Returns `true` if the hypervisor advertises its presence via SMCCC.
+ *
+ * When the function returns `false`, the caller shall not assume that
+ * there is no hypervisor running. Instead, the caller must fall back to
+ * other approaches if any are available.
+ */
+bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);
+
+#define SMCCC_RES_TO_UUID(r0, r1, r2, r3) \
+	UUID_INIT( \
+		cpu_to_le32(lower_32_bits(r0)), \
+		cpu_to_le32(lower_32_bits(r1)) & 0xffff, \
+		cpu_to_le32(lower_32_bits(r1)) >> 16, \
+		cpu_to_le32(lower_32_bits(r2)) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 8) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 16) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 24) & 0xff, \
+		cpu_to_le32(lower_32_bits(r3)) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 8) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 16) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 24) & 0xff \
+	)
+
+#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
+		const uuid_t uuid = uuid_init; \
+		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
+						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24)); \
+		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
+						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24)); \
+		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
+						((uuid.b[10]) << 16) | ((uuid.b[11]) << 24)); \
+		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
+						((uuid.b[14]) << 16) | ((uuid.b[15]) << 24)); \
+	} while (0)
+
+#endif /* !__ASSEMBLER__ */
+
 /**
  * struct arm_smccc_res - Result from SMC/HVC call
  * @a0-a3 result values from registers 0 to 3
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar  7 14:02:52 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri,  7 Mar 2025 14:02:52 -0800
Subject: [PATCH hyperv-next v5 00/11] arm64: hyperv: Support Virtual Trust Level Boot
Message-ID: <20250307220304.247725-1-romank@linux.microsoft.com>

This patch set allows the Hyper-V code to boot on ARM64 inside a Virtual Trust
Level. These levels are a part of the Virtual Secure Mode documented in the
Top-Level Functional Specification available at
https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm.

The OpenHCL paravisor https://github.com/microsoft/openvmm/tree/main/openhcl
can serve as a practical application of these patches on ARM64.

For validation, I built kernels for the {x86_64, ARM64} x {VTL0, VTL2} set with
a small initrd embedded into the kernel and booted VMs managed by Hyper-V and
OpenVMM off of that.

Starting from V5, the patch series includes a non-functional change to KVM on
arm64 which I tested as well.

[V5]
    - Provide and use a common SMCCC-based infra for the arm64 hypervisor guests
      to detect hypervisor presence.
    ** Thank you, Arnd! **

    - Fix line wraps to follow the rest of the code.
    - Open-code getting IRQ domain parent in the ACPI case to make the code
      better.
    ** Thank you, Bjorn! **

    - Test the binding with the latest dtschema.
    - Clean up the commit title and description.
    - Use proper defines for known constants.
    ** Thank you, Krzysztof! **

    - Extend comment on why ACPI v6 is checked for.
    - Reorder patches to make sure that even with partial series application
      the compilation succeeds.
    - Report VTL the kernel runs in.
    - Use "X86_64" in Kconfig rather than "X86".
    - Extract a non-functional change for hv_get_vmbus_root_device() into
      a separate patch.
    ** Thank you, Michael! **

[V4]
    https://lore.kernel.org/linux-hyperv/20250212014321.1108840-1-romank at linux.microsoft.com/
    - Fixed wording to match acronyms defined in the "Terms and Abbreviations"
      section of the SMCCC specification throughout the patch series.
      **Thank you, Michael!**

    - Replaced the hypervisor ID containing ASCII with an UUID as
      required by the specification.
      **Thank you, Michael!**

    - Added an explicit check for `SMCCC_RET_NOT_SUPPORTED` when discovering the
      hypervisor presence to make the backward compatibility obvious.
      **Thank you, Saurabh!**

    - Split the fix for `get_vtl(void)` out to make it easier to backport.
    - Refactored the configuration options as requested to eliminate the risk
      of building non-functional kernels with randomly selected options.
      **Thank you, Michael!**

    - Refactored the changes not to introduce an additional file with
      a one-line function.
      **Thank you, Wei!**

    - Fixed change description for the VMBus DeviceTree changes, used
      `scripts/get_maintainers.pl` on the latest kernel to get the up-to-date list
      of maintainers as requested.
      **Thank you, Krzysztof!**

    - Removed the added (paranoidal+superfluous) checks for DMA coherence in the
      VMBus driver and instead relied on the DMA and the OF subsystem code.
      **Thank you, Arnd, Krzysztof, Michael!**

    - Used another set of APIs for discovering the hardware interrupt number
      in the VMBus driver to be able to build the driver as a module.
      **Thank you, Michael, Saurabh!**

    - Renamed the newly introduced `get_vmbus_root_device(void)` function to
      `hv_get_vmbus_root_device(void)` as requested.
      **Thank you, Wei!**

    - Applied the suggested small-scale refactoring to simplify changes to the Hyper-V
      PCI driver. Taking the offered liberty of doing the large scale refactoring
      in another patch series.
      **Thank you, Michael!**

    - Added a fix for the issue discovered internally where the CPU would not
      get the interrupt from a PCI device attached to VTL2 as the shared peripheral
      interrupt number (SPI) was not offset by 32 (the first valid SPI number).
      **Thank you, Brian!**

[V3]
    https://lore.kernel.org/lkml/20240726225910.1912537-1-romank at linux.microsoft.com/
    - Employed the SMCCC function recently implemented in the Microsoft Hyper-V
      hypervisor to detect running on Hyper-V/arm64. No dependence on ACPI/DT is
      needed anymore although the source code still falls back to ACPI as the new
      hypervisor might be available only in the Windows Insiders channel just
      yet.
    - As a part of the above, refactored detecting the hypervisor via ACPI FADT.
    - There was a suggestion to explore whether it is feasible or not to express
      that ACPI must be absent for the VTL mode and present for the regular guests
      in the Hyper-V Kconfig file.
      My current conclusion is that this will require refactoring in many places.
      That becomes especially convoluted on x86_64 due to the MSI and APIC
      dependencies. I'd ask to let us tackle that in another patch series (or chalk
      up to nice-have's rather than fires to put out) to separate concerns and
      decrease chances of breakage.
    - While refactoring `get_vtl(void)` and the related code, fixed the hypercall
      output address not to overlap with the input as the Hyper-V TLFS mandates:
      "The input and output parameter lists cannot overlap or cross page boundaries."
      See https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercall-interface
      for more.
      Some might argue that should've been a topic for a separate patch series;
      I'd counter that the change is well-contained (one line), has no dependencies,
      and makes the code legal.
    - Made the VTL boot code (c)leaner as was suggested.
    - Set DMA cache coherency for the VMBus.
    - Updated DT bindings in the VMBus documentation (separated out into a new patch).
    - Fixed `vmbus_set_irq` to use the API that works both for the ACPI and OF.
    - Reworked setting up the vPCI MSI IRQ domain in the non-ACPI case. The logic
      looks a bit fiddly/ad-hoc as I couldn't find the API that would fit the bill.
      Added comments to explain myself.

[V2]
    https://lore.kernel.org/all/20240514224508.212318-1-romank at linux.microsoft.com/
    - Decreased number of #ifdef's
    - Updated the wording in the commit messages to adhere to the guidlines
    - Sending to the correct set of maintainers and mail lists

[V1]
    https://lore.kernel.org/all/20240510160602.1311352-1-romank at linux.microsoft.com/

Roman Kisel (11):
  arm64: kvm, smccc: Introduce and use API for detectting hypervisor
    presence
  arm64: hyperv: Use SMCCC to detect hypervisor presence
  Drivers: hv: Enable VTL mode for arm64
  Drivers: hv: Provide arch-neutral implementation of get_vtl()
  arm64: hyperv: Initialize the Virtual Trust Level field
  arm64, x86: hyperv: Report the VTL the system boots in
  dt-bindings: microsoft,vmbus: Add interrupts and DMA coherence
  Drivers: hv: vmbus: Get the IRQ number from DeviceTree
  Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
  ACPI: irq: Introduce acpi_get_gsi_dispatcher()
  PCI: hv: Get vPCI MSI IRQ domain from DeviceTree

 .../bindings/bus/microsoft,vmbus.yaml         |  8 +-
 arch/arm64/hyperv/mshyperv.c                  | 46 +++++++++--
 arch/arm64/kvm/hypercalls.c                   |  5 +-
 arch/x86/hyperv/hv_init.c                     | 34 --------
 arch/x86/hyperv/hv_vtl.c                      |  2 +-
 drivers/acpi/irq.c                            | 14 +++-
 drivers/firmware/smccc/kvm_guest.c            | 10 +--
 drivers/firmware/smccc/smccc.c                | 19 +++++
 drivers/hv/Kconfig                            | 10 ++-
 drivers/hv/hv_common.c                        | 31 ++++++++
 drivers/hv/vmbus_drv.c                        | 59 ++++++++++++--
 drivers/pci/controller/pci-hyperv.c           | 79 +++++++++++++++++--
 include/asm-generic/mshyperv.h                |  6 ++
 include/hyperv/hvgdk_mini.h                   |  2 +-
 include/linux/acpi.h                          |  5 +-
 include/linux/arm-smccc.h                     | 55 ++++++++++++-
 include/linux/hyperv.h                        |  2 +
 17 files changed, 308 insertions(+), 79 deletions(-)


base-commit: 3a7f7785eae7cf012af128ca9e383c91e4955354
-- 
2.43.0



From nunodasneves at linux.microsoft.com  Fri Mar  7 14:06:46 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 14:06:46 -0800
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <63437aa6-d45a-4b7a-b222-5901c03c48e0@linux.microsoft.com>

On 3/7/2025 9:02 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
>> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
>> SynIC event ring buffer for each SINT.
>>
>> This will be used by the mshv driver, but must be tracked independently
>> since the driver module could be removed and re-inserted.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
>> ---
>>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
>>  1 file changed, 32 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>> index 252fd66ad4db..2763cb6d3678 100644
>> --- a/drivers/hv/hv_common.c
>> +++ b/drivers/hv/hv_common.c
>> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
>>
>>  static struct ctl_table_header *hv_ctl_table_hdr;
>>
>> +/*
>> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
>> + * for each SINT.
>> + *
>> + * We cannot maintain this in mshv driver because the tail pointer should
>> + * persist even if the mshv driver is unloaded.
>> + */
>> +u8 __percpu **hv_synic_eventring_tail;
> 
> I think the "__percpu" is in the wrong place here. This placement
> is likely to cause errors from the "sparse" tool.  It should be
> 
> u8 * __percpu *hv_synic_eventring_tail;
> 
> See the way hyperv_pcpu_input_arg, for example, is defined.  And
> see commit db3c65bc3a13 where I fixed hyperv_pcpu_input_arg.
> 
Thanks. I'll fix it.

>> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
> 
> The "extern" declaration for this variable is in Patch 10 of the series
> in drivers/hv/mshv_root.h. I guess that's OK, but I would normally
> expect to find such a declaration in the header file associated with
> where the variable is defined, which in this case is mshyperv.h.
> Perhaps you are trying to restrict its usage to just mshv?
> 
Yes, that's the idea - it should only be used by the driver.

>> +
>>  /*
>>   * Hyper-V specific initialization and shutdown code that is
>>   * common across all architectures.  Called from architecture
>> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
>>
>>  	free_percpu(hyperv_pcpu_input_arg);
>>  	hyperv_pcpu_input_arg = NULL;
>> +
>> +	free_percpu(hv_synic_eventring_tail);
>> +	hv_synic_eventring_tail = NULL;
>>  }
>>
>>  /*
>> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
>>  		BUG_ON(!hyperv_pcpu_output_arg);
>>  	}
>>
>> +	if (hv_root_partition()) {
>> +		hv_synic_eventring_tail = alloc_percpu(u8 *);
>> +		BUG_ON(hv_synic_eventring_tail == NULL);
>> +	}
>> +
>>  	hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
>>  				    GFP_KERNEL);
>>  	if (!hv_vp_index) {
>> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
>>  int hv_common_cpu_init(unsigned int cpu)
>>  {
>>  	void **inputarg, **outputarg;
>> +	u8 **synic_eventring_tail;
>>  	u64 msr_vp_index;
>>  	gfp_t flags;
>>  	const int pgcount = hv_output_page_exists() ? 2 : 1;
>> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
>>  	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
>>
>>  	/*
>> -	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
>> -	 * allocated if this CPU was previously online and then taken offline
>> +	 * The per-cpu memory is already allocated if this CPU was previously
>> +	 * online and then taken offline
>>  	 */
>>  	if (!*inputarg) {
>>  		mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
>> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
>>  			*outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
>>  		}
>>
>> +		if (hv_root_partition()) {
>> +			synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
>> +			*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
>> +							sizeof(u8), flags);
>> +
>> +			if (unlikely(!*synic_eventring_tail)) {
>> +				kfree(mem);
>> +				return -ENOMEM;
>> +			}
>> +		}
>> +
> 
> Adding this code under the "if(!*inputarg)" implicitly ties the lifecycle of
> synic_eventring_tail to the lifecycle of hyperv_pcpu_input_arg and
> hyperv_pcpu_output_arg. Is there some logical relationship between the
> two that warrants tying the lifecycles together (other than just both being
> per-cpu)?  hyperv_pcpu_input_arg and hyperv_pcpu_output_arg have an
> unusual lifecycle management in that they aren't freed when a CPU goes
> offline, as described in the comment in hv_common_cpu_die(). Does
> synic_eventring_tail also need that same unusual lifecycle?
> 
I thought about it, and no I don't think it shares the same exact lifecycle.
It's only used by the mshv_root driver - it just needs to remain present
whenever there's a chance the module could be re-inserted and expect it to
be there.

> Assuming there's no logical relationship, I'm thinking synic_eventring_tail
> should be managed independent of the other two. If it does need the
> unusual lifecycle, make sure to add a comment in hv_common_cpu_die()
> explaining why. If it doesn't need the unusual lifecycle, maybe just do
> the normal thing of allocating it in hv_common_cpu_init() and freeing
> it in hv_common_cpu_die().
> 
Yep, I suppose it should just be freed normally then, assuming
hv_common_cpu_die() is only called when the hypervisor is going to reset
(or remove) the synic pages for this partition. Is that the case here?

Otherwise we'd want to retain it, in case mshv_root ever needs it again for
that CPU in the lifetime of this partition.

Nuno

> The code as written in your patch isn't wrong and would work OK. But
> the structure implies a relationship with hyperv_pcpu_*_arg that I
> suspect doesn't exist.
> 
> Michael
> 
>>  		if (!ms_hyperv.paravisor_present &&
>>  		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
>>  			ret = set_memory_decrypted((unsigned long)mem, pgcount);
>> --
>> 2.34.1



From jm at ti.com  Fri Mar  7 14:25:31 2025
From: jm at ti.com (Judith Mendez)
Date: Fri, 7 Mar 2025 16:25:31 -0600
Subject: [PATCH v5 00/10] Add R5F and C7xv device nodes
In-Reply-To: <20250210221530.1234009-1-jm@ti.com>
References: <20250210221530.1234009-1-jm@ti.com>
Message-ID: <df3842b2-7a7e-4c54-80dc-927c7eb55b3c@ti.com>

Hi Vignesh, all,

On 2/10/25 4:15 PM, Judith Mendez wrote:
> For am62x and am62ax devices, this patch series adds device nodes
> for the R5F subsystem and C7xv DSP subsystem found in their
> respective voltage domain, based on the device TRMs [0][1].
> 
> This patch series also includes patches for enabling IPC for am62x SK,
> am62ax SK, and am62px SK by reserving memory and binding the mailbox
> assignments for each remote core.
> 
> Also reserve timers used by C7x DSP for am62ax SK board and timers used
> by MCU FW for AM642 SK and EVM boards as per firmware requirements.
> 

Is it at all possible to only pick the first 4 patches of this series
that only enable the core nodes?

I will respin the rest of the series in a different patch series.

~ Judith




From nphamcs at gmail.com  Fri Mar  7 15:03:34 2025
From: nphamcs at gmail.com (Nhat Pham)
Date: Fri, 7 Mar 2025 15:03:34 -0800
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
Message-ID: <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>

On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
>
> This patch series introduces a new mechanism called kcompressd to
> improve the efficiency of memory reclaiming in the operating system. The
> main goal is to separate the tasks of page scanning and page compression
> into distinct processes or threads, thereby reducing the load on the
> kswapd thread and enhancing overall system performance under high memory
> pressure conditions.

Please excuse my ignorance, but from your cover letter I still don't
quite get what is the problem here? And how would decouple compression
and scanning help?

>
> Problem:
>  In the current system, the kswapd thread is responsible for both
>  scanning the LRU pages and compressing pages into the ZRAM. This
>  combined responsibility can lead to significant performance bottlenecks,

What bottleneck are we talking about? Is one stage slower than the other?

>  especially under high memory pressure. The kswapd thread becomes a
>  single point of contention, causing delays in memory reclaiming and
>  overall system performance degradation.
>
> Target:
>  The target of this invention is to improve the efficiency of memory
>  reclaiming. By separating the tasks of page scanning and page
>  compression into distinct processes or threads, the system can handle
>  memory pressure more effectively.

I'm not a zram maintainer, so I'm definitely not trying to stop this
patch. But whatever problem zram is facing will likely occur with
zswap too, so I'd like to learn more :)


From nphamcs at gmail.com  Fri Mar  7 15:13:12 2025
From: nphamcs at gmail.com (Nhat Pham)
Date: Fri, 7 Mar 2025 15:13:12 -0800
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <20250307120141.1566673-3-qun-wei.lin@mediatek.com> <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
Message-ID: <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>

On Fri, Mar 7, 2025 at 11:41?AM Barry Song <21cnbao at gmail.com> wrote:
>
> On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
> >
> > Introduced Kcompressd to offload zram page compression, improving
> > system efficiency by handling compression separately from memory
> > reclaiming. Added necessary configurations and dependencies.
> >
> > Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > ---
> >  drivers/block/zram/Kconfig      |  11 ++
> >  drivers/block/zram/Makefile     |   3 +-
> >  drivers/block/zram/kcompressd.c | 340 ++++++++++++++++++++++++++++++++
> >  drivers/block/zram/kcompressd.h |  25 +++
> >  drivers/block/zram/zram_drv.c   |  22 ++-
> >  5 files changed, 397 insertions(+), 4 deletions(-)
> >  create mode 100644 drivers/block/zram/kcompressd.c
> >  create mode 100644 drivers/block/zram/kcompressd.h
> >
> > diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
> > index 402b7b175863..f0a1b574f770 100644
> > --- a/drivers/block/zram/Kconfig
> > +++ b/drivers/block/zram/Kconfig
> > @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
> >           re-compress pages using a potentially slower but more effective
> >           compression algorithm. Note, that IDLE page recompression
> >           requires ZRAM_TRACK_ENTRY_ACTIME.
> > +
> > +config KCOMPRESSD
> > +       tristate "Kcompressd: Accelerated zram compression"
> > +       depends on ZRAM
> > +       help
> > +         Kcompressd creates multiple daemons to accelerate the compression of pages
> > +         in zram, offloading this time-consuming task from the zram driver.
> > +
> > +         This approach improves system efficiency by handling page compression separately,
> > +         which was originally done by kswapd or direct reclaim.
>
> For direct reclaim, we were previously able to compress using multiple CPUs
> with multi-threading.
> After your patch, it seems that only a single thread/CPU is used for compression
> so it won't necessarily improve direct reclaim performance?
>
> Even for kswapd, we used to have multiple threads like [kswapd0], [kswapd1],
> and [kswapd2] for different nodes. Now, are we also limited to just one thread?
> I also wonder if this could be handled at the vmscan level instead of the zram
> level. then it might potentially help other sync devices or even zswap later.

Agree. A shared solution would be much appreciated. We can keep the
kcompressd idea, but have it accept IO work from multiple sources
(zram, zswap, whatever) through a shared API.

Otherwise we would need to reinvent the wheel multiple times :)


From nphamcs at gmail.com  Fri Mar  7 15:14:29 2025
From: nphamcs at gmail.com (Nhat Pham)
Date: Fri, 7 Mar 2025 15:14:29 -0800
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <20250307120141.1566673-3-qun-wei.lin@mediatek.com> <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
 <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>
Message-ID: <CAKEwX=MtzM4Vw221pHTj8CZJ1NhLgo7Ls3xroxLRO399fzG98Q@mail.gmail.com>

On Fri, Mar 7, 2025 at 3:13?PM Nhat Pham <nphamcs at gmail.com> wrote:
>
>
> Agree. A shared solution would be much appreciated. We can keep the
> kcompressd idea, but have it accept IO work from multiple sources
> (zram, zswap, whatever) through a shared API.

by IO I meant compress work (should be double quoted "IO"). But you
get the idea :)


From dingwei at marvell.com  Fri Mar  7 15:15:57 2025
From: dingwei at marvell.com (Wilson Ding)
Date: Fri, 7 Mar 2025 23:15:57 +0000
Subject: [PATCH v3 1/3] dt-bindings: reset: Add Armada8K reset controller
In-Reply-To: <f8e2091b-52dc-4b7a-b781-84588dd6b1ba@kernel.org>
References: <20250227192536.2426490-1-dingwei@marvell.com>
 <20250227192536.2426490-2-dingwei@marvell.com>
 <174068786548.161165.4348563654300627455.robh@kernel.org>
 <BY3PR18MB467346EB1FA7CEF0A3300350A7CD2@BY3PR18MB4673.namprd18.prod.outlook.com>
 <d2929546-27de-4893-a611-dd4a3bca1a64@kernel.org>
 <BY3PR18MB46734A2425361D8BE83E4282A7D52@BY3PR18MB4673.namprd18.prod.outlook.com>
 <f8e2091b-52dc-4b7a-b781-84588dd6b1ba@kernel.org>
Message-ID: <BY3PR18MB46735010948BE323B9A8ED5BA7D52@BY3PR18MB4673.namprd18.prod.outlook.com>



> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Friday, March 7, 2025 12:57 AM
> To: Wilson Ding <dingwei at marvell.com>; Rob Herring (Arm)
> <robh at kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org; Sanghoon Lee <salee at marvell.com>;
> conor+dt at kernel.org; linux-kernel at vger.kernel.org;
> gregory.clement at bootlin.com; p.zabel at pengutronix.de; Geethasowjanya
> Akula <gakula at marvell.com>; devicetree at vger.kernel.org; andrew at lunn.ch;
> krzk+dt at kernel.org; sebastian.hesselbarth at gmail.com
> Subject: [EXTERNAL] Re: [PATCH v3 1/3] dt-bindings: reset: Add Armada8K
> reset controller
> 
> On 07/03/2025 01:03, Wilson Ding wrote:
> >> reset.example.dts
> >>>   DTC [C]
> >>> Documentation/devicetree/bindings/reset/marvell,armada8k-
> reset.examp
> >>> le
> >>> .dtb
> >>>
> >>
> >> That's a bit odd but anyway warning is correct: you cannot have such
> >> compatibles alone.
> >
> > I understand I need to add one compatible here to resolve the warning.
> > However, as we agreed, we keep the sud-nodes while there will be no
> > new compatibles in parent node. So how shall I avoid this warning?
> >
> > If we do want to add a compatible in parent node, what should be used
> > for the compatible name? I think the most suitable name would be
> > something like "marvell,cp110-system-controller0".
> 
> I don't know. I don't work in Marvell, I know nothing about Marvell Armada
> and I was not involved in any Armada SoCs.
> 
> Read your datasheet and come up with some reasonable name based on
> datasheet. Why do you ask people who do not have datasheet?
> 
> > However, it was already taken for in Armada clock controller to be
> > compatible for legacy dt.
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_a
> > ll_bb21ee9acc55efac884450ff710049b99b27f8bf.1496328934.git-
> 2Dseries.gr
> > egory.clement-40free-
> 2Delectrons.com_&d=DwICaQ&c=nKjWec2b6R0mOyPaz7xtf
> >
> Q&r=sXDQZu4GyqNVDlFUXakSGJl0Dh81ZIPlU26YS4KHGIA&m=nfrB1z6tgLEY
> 3BeUK8cH
> >
> 5CBEnUJhq1yHXS9xCDegRMGapzD2rOL7z092sJd1dzIo&s=LqUI_K0rnOXPmy
> dkE9n-hdK
> > KO2dmGhyN5H-raW6-6Dc&e=
> 
> I don't understand what it means.
> 
> >
> > This is something about 8 years ago. I wonder if we do need to have
> > the backward compatibility for the field devices at that time. Can we
> > drop it now?
> 
> Drop what? You need to keep ABI.

Do you mean once a compatible name was present in dt-binding, it
Should never be deleted in future (even these is no dts file using it)?

> 
> >
> >     syscon0: system-controller at 440000 {
> >         compatible = "marvell,cp110-system-controller0",
> >                                 "syscon", "simple-mfd";
> >         reg = <0x440000 0x2000>;
> >         #address-cells = <1>;
> >         #size-cells = <1>;
> >
> >         swrst: reset-controller at 268 {
> >             compatible = "marvell,armada8k-reset";
> >             reg = <0x268 0x4>;
> >             #reset-cells = <1>;
> >         };
> >     };
> >
> Best regards,
> Krzysztof

From mhklinux at outlook.com  Fri Mar  7 15:21:07 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 23:21:07 +0000
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <63437aa6-d45a-4b7a-b222-5901c03c48e0@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
 <63437aa6-d45a-4b7a-b222-5901c03c48e0@linux.microsoft.com>
Message-ID: <SN6PR02MB415710BED37BDD375B0D769AD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 7, 2025 2:07 PM
> 
> On 3/7/2025 9:02 AM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> >>
> >> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
> >> SynIC event ring buffer for each SINT.
> >>
> >> This will be used by the mshv driver, but must be tracked independently
> >> since the driver module could be removed and re-inserted.
> >>
> >> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> >> ---
> >>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
> >>  1 file changed, 32 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> >> index 252fd66ad4db..2763cb6d3678 100644
> >> --- a/drivers/hv/hv_common.c
> >> +++ b/drivers/hv/hv_common.c
> >> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
> >>
> >>  static struct ctl_table_header *hv_ctl_table_hdr;
> >>
> >> +/*
> >> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
> >> + * for each SINT.
> >> + *
> >> + * We cannot maintain this in mshv driver because the tail pointer should
> >> + * persist even if the mshv driver is unloaded.
> >> + */
> >> +u8 __percpu **hv_synic_eventring_tail;
> >
> > I think the "__percpu" is in the wrong place here. This placement
> > is likely to cause errors from the "sparse" tool.  It should be
> >
> > u8 * __percpu *hv_synic_eventring_tail;
> >
> > See the way hyperv_pcpu_input_arg, for example, is defined.  And
> > see commit db3c65bc3a13 where I fixed hyperv_pcpu_input_arg.
> >
> Thanks. I'll fix it.
> 
> >> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
> >
> > The "extern" declaration for this variable is in Patch 10 of the series
> > in drivers/hv/mshv_root.h. I guess that's OK, but I would normally
> > expect to find such a declaration in the header file associated with
> > where the variable is defined, which in this case is mshyperv.h.
> > Perhaps you are trying to restrict its usage to just mshv?
> >
> Yes, that's the idea - it should only be used by the driver.
> 
> >> +
> >>  /*
> >>   * Hyper-V specific initialization and shutdown code that is
> >>   * common across all architectures.  Called from architecture
> >> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
> >>
> >>  	free_percpu(hyperv_pcpu_input_arg);
> >>  	hyperv_pcpu_input_arg = NULL;
> >> +
> >> +	free_percpu(hv_synic_eventring_tail);
> >> +	hv_synic_eventring_tail = NULL;
> >>  }
> >>
> >>  /*
> >> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
> >>  		BUG_ON(!hyperv_pcpu_output_arg);
> >>  	}
> >>
> >> +	if (hv_root_partition()) {
> >> +		hv_synic_eventring_tail = alloc_percpu(u8 *);
> >> +		BUG_ON(hv_synic_eventring_tail == NULL);
> >> +	}
> >> +
> >>  	hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
> >>  				    GFP_KERNEL);
> >>  	if (!hv_vp_index) {
> >> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
> >>  int hv_common_cpu_init(unsigned int cpu)
> >>  {
> >>  	void **inputarg, **outputarg;
> >> +	u8 **synic_eventring_tail;
> >>  	u64 msr_vp_index;
> >>  	gfp_t flags;
> >>  	const int pgcount = hv_output_page_exists() ? 2 : 1;
> >> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
> >>  	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
> >>
> >>  	/*
> >> -	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
> >> -	 * allocated if this CPU was previously online and then taken offline
> >> +	 * The per-cpu memory is already allocated if this CPU was previously
> >> +	 * online and then taken offline
> >>  	 */
> >>  	if (!*inputarg) {
> >>  		mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
> >> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
> >>  			*outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
> >>  		}
> >>
> >> +		if (hv_root_partition()) {
> >> +			synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> >> +			*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
> >> +							sizeof(u8), flags);
> >> +
> >> +			if (unlikely(!*synic_eventring_tail)) {
> >> +				kfree(mem);
> >> +				return -ENOMEM;
> >> +			}
> >> +		}
> >> +
> >
> > Adding this code under the "if(!*inputarg)" implicitly ties the lifecycle of
> > synic_eventring_tail to the lifecycle of hyperv_pcpu_input_arg and
> > hyperv_pcpu_output_arg. Is there some logical relationship between the
> > two that warrants tying the lifecycles together (other than just both being
> > per-cpu)?  hyperv_pcpu_input_arg and hyperv_pcpu_output_arg have an
> > unusual lifecycle management in that they aren't freed when a CPU goes
> > offline, as described in the comment in hv_common_cpu_die(). Does
> > synic_eventring_tail also need that same unusual lifecycle?
> >
> I thought about it, and no I don't think it shares the same exact lifecycle.
> It's only used by the mshv_root driver - it just needs to remain present
> whenever there's a chance the module could be re-inserted and expect it to
> be there.
> 
> > Assuming there's no logical relationship, I'm thinking synic_eventring_tail
> > should be managed independent of the other two. If it does need the
> > unusual lifecycle, make sure to add a comment in hv_common_cpu_die()
> > explaining why. If it doesn't need the unusual lifecycle, maybe just do
> > the normal thing of allocating it in hv_common_cpu_init() and freeing
> > it in hv_common_cpu_die().
> >
> Yep, I suppose it should just be freed normally then, assuming
> hv_common_cpu_die() is only called when the hypervisor is going to reset
> (or remove) the synic pages for this partition. Is that the case here?
> 

Yes, it is the case here. A particular vCPU can be taken offline
independent of other vCPUs in the VM (such as by writing "0"
to /sys/devices/system/cpu/cpu<nn>/online). When that happens
the vCPU going offline runs hv_synic_cleanup() first, and then it
runs hv_cpu_die(), which calls hv_common_cpu_die(). So by the
time hv_common_cpu_die() runs, the synic_message_page and
synic_event_page will have been unmapped and the pointers set
to NULL.

On arm64, there is no hv_cpu_init()/die(), and the "common"
versions are called directly. Perhaps at some point in the future there
will be arm64 specific things to be done, and hv_cpu_init()/die()
will need to be added. But the ordering is the same and
hv_synic_cleanup() runs first.

So, yes, since synic_eventring_tail is tied to the synic, it sounds like
the normal lifecycle could be used, like with the VP assist page that
is handled in hv_cpu_init()/die() on x86.

> Otherwise we'd want to retain it, in case mshv_root ever needs it again for
> that CPU in the lifetime of this partition.
> 
> Nuno
> 
> > The code as written in your patch isn't wrong and would work OK. But
> > the structure implies a relationship with hyperv_pcpu_*_arg that I
> > suspect doesn't exist.
> >
> > Michael
> >
> >>  		if (!ms_hyperv.paravisor_present &&
> >>  		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
> >>  			ret = set_memory_decrypted((unsigned long)mem, pgcount);
> >> --
> >> 2.34.1


From jonas at kwiboo.se  Fri Mar  7 15:22:48 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 8 Mar 2025 00:22:48 +0100
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers
 for RK3528
In-Reply-To: <20250305194612.47171-1-ziyao@disroot.org>
References: <20250305194217.47052-1-ziyao@disroot.org>
 <20250305194612.47171-1-ziyao@disroot.org>
Message-ID: <56181131-3e48-4c76-87c7-2388a9964727@kwiboo.se>

Hi Yao Zi,

On 2025-03-05 20:46, Yao Zi wrote:
> RK3528 features two SDIO controllers and one SD/MMC controller, describe
> them in devicetree. Since their sample and drive clocks are located in
> the VO and VPU GRFs, corresponding syscons are added to make these
> clocks available.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 70 ++++++++++++++++++++++++
>  1 file changed, 70 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index d3e2a64ff2d5..363023314e9c 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -130,6 +130,16 @@ gic: interrupt-controller at fed01000 {
>  			#interrupt-cells = <3>;
>  		};
>  
> +		vpu_grf: syscon at ff340000 {
> +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
> +			reg = <0x0 0xff340000 0x0 0x8000>;
> +		};
> +
> +		vo_grf: syscon at ff360000 {
> +			compatible = "rockchip,rk3528-vo-grf", "syscon";
> +			reg = <0x0 0xff360000 0x0 0x10000>;
> +		};
> +
>  		cru: clock-controller at ff4a0000 {
>  			compatible = "rockchip,rk3528-cru";
>  			reg = <0x0 0xff4a0000 0x0 0x30000>;
> @@ -274,6 +284,66 @@ saradc: adc at ffae0000 {
>  			resets = <&cru SRST_P_SARADC>;
>  			reset-names = "saradc-apb";
>  			#io-channel-cells = <1>;
> +		};

Look like this patch accidentally drops status = "disabled" from the
adc at ffae0000 node.

Regards,
Jonas

> +
> +		sdio0: mmc at ffc10000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc10000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO0>,
> +				 <&cru CCLK_SRC_SDIO0>,
> +				 <&cru SCLK_SDIO0_DRV>,
> +				 <&cru SCLK_SDIO0_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>,
> +				    <&sdio0_det>, <&sdio0_pwren>;
> +			resets = <&cru SRST_H_SDIO0>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};
> +
> +		sdio1: mmc at ffc20000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc20000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDIO1>,
> +				 <&cru CCLK_SRC_SDIO1>,
> +				 <&cru SCLK_SDIO1_DRV>,
> +				 <&cru SCLK_SDIO1_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>,
> +				    <&sdio1_det>, <&sdio1_pwren>;
> +			resets = <&cru SRST_H_SDIO1>;
> +			reset-names = "reset";
> +			status = "disabled";
> +		};
> +
> +		sdmmc: mmc at ffc30000 {
> +			compatible = "rockchip,rk3528-dw-mshc",
> +				     "rockchip,rk3288-dw-mshc";
> +			reg = <0x0 0xffc30000 0x0 0x4000>;
> +			clocks = <&cru HCLK_SDMMC0>,
> +				 <&cru CCLK_SRC_SDMMC0>,
> +				 <&cru SCLK_SDMMC_DRV>,
> +				 <&cru SCLK_SDMMC_SAMPLE>;
> +			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> +			fifo-depth = <0x100>;
> +			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
> +			max-frequency = <150000000>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>,
> +				    <&sdmmc_det>;
> +			resets = <&cru SRST_H_SDMMC0>;
> +			reset-names = "reset";
> +			rockchip,default-sample-phase = <90>;
>  			status = "disabled";
>  		};
>  



From nunodasneves at linux.microsoft.com  Fri Mar  7 15:29:35 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 15:29:35 -0800
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <SN6PR02MB415730AA9A9BFFBB9A62F195D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB415730AA9A9BFFBB9A62F195D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <86bf7bae-9423-4413-8986-364d96243c82@linux.microsoft.com>

On 3/7/2025 9:44 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
>>
>> This will handle SYNIC interrupts such as intercepts, doorbells, and
>> scheduling messages intended for the mshv driver.
> 
> Could you provide a bit more detailed commit message? How does
> the mshv_handler() relate to the vmbus_handler()? From the code
> mshv_handler() goes first, and I'm assuming it processes what it
> knows about (intercepts, doorbells, scheduling messages?) and
> then hands off control to the vmbus_handler() to handle the usual
> VMbus-related message and channel interrupts. But it would be
> nice to have the commit message or code comments describe the
> overall intent and any obscure aspects of the relationship.
> 
> And avoid references to "This" or "This patch". :-)
> 

You've described it pretty well, I don't know if there's too much
more to say given this patch doesn't introduce the handler code.

I can try to improve it, something like:
"
mshv_handler() will be used to process messages related to managing
guest partitions such as intercepts, doorbells, and scheduling messages.

In a (non-nested) root partition, the same interrupt vector is shared
between the vmbus and mshv_root drivers.

Introduce a stub for mshv_handler() and call it in
sysvec_hyperv_callback alongside vmbus_handler().

Even though both handlers will be called for every Hyper-V interrupt,
the messages for each driver are delivered to different offsets within
the SYNIC message page, so they won't step on each other.
"

Does that work?

Nuno
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
>> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
>> ---
>>  arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
>>  drivers/hv/hv_common.c         | 5 +++++
>>  include/asm-generic/mshyperv.h | 1 +
>>  3 files changed, 15 insertions(+)
>>
>> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
>> index 0116d0e96ef9..616e9a5d77b4 100644
>> --- a/arch/x86/kernel/cpu/mshyperv.c
>> +++ b/arch/x86/kernel/cpu/mshyperv.c
>> @@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
>>  }
>>  EXPORT_SYMBOL_GPL(hv_set_msr);
>>
>> +static void (*mshv_handler)(void);
>>  static void (*vmbus_handler)(void);
>>  static void (*hv_stimer0_handler)(void);
>>  static void (*hv_kexec_handler)(void);
>> @@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>>  	struct pt_regs *old_regs = set_irq_regs(regs);
>>
>>  	inc_irq_stat(irq_hv_callback_count);
>> +	if (mshv_handler)
>> +		mshv_handler();
>> +
>>  	if (vmbus_handler)
>>  		vmbus_handler();
>>
>> @@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>>  	set_irq_regs(old_regs);
>>  }
>>
>> +void hv_setup_mshv_handler(void (*handler)(void))
>> +{
>> +	mshv_handler = handler;
>> +}
>> +
>>  void hv_setup_vmbus_handler(void (*handler)(void))
>>  {
>>  	vmbus_handler = handler;
>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>> index 2763cb6d3678..f5a07fd9a03b 100644
>> --- a/drivers/hv/hv_common.c
>> +++ b/drivers/hv/hv_common.c
>> @@ -677,6 +677,11 @@ void __weak hv_remove_vmbus_handler(void)
>>  }
>>  EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
>>
>> +void __weak hv_setup_mshv_handler(void (*handler)(void))
>> +{
>> +}
>> +EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
>> +
>>  void __weak hv_setup_kexec_handler(void (*handler)(void))
>>  {
>>  }
>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>> index 1f46d19a16aa..a05f12e63ccd 100644
>> --- a/include/asm-generic/mshyperv.h
>> +++ b/include/asm-generic/mshyperv.h
>> @@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
>>  void hv_remove_kexec_handler(void);
>>  void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
>>  void hv_remove_crash_handler(void);
>> +void hv_setup_mshv_handler(void (*handler)(void));
>>
>>  extern int vmbus_interrupt;
>>  extern int vmbus_irq;
>> --
>> 2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar  7 15:31:42 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 15:31:42 -0800
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <SN6PR02MB415710BED37BDD375B0D769AD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
 <63437aa6-d45a-4b7a-b222-5901c03c48e0@linux.microsoft.com>
 <SN6PR02MB415710BED37BDD375B0D769AD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <7de75d5a-c284-4ab8-b275-ec245608ed5c@linux.microsoft.com>

On 3/7/2025 3:21 PM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 7, 2025 2:07 PM
>>
>> On 3/7/2025 9:02 AM, Michael Kelley wrote:
>>> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>>>
>>>> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
>>>> SynIC event ring buffer for each SINT.
>>>>
>>>> This will be used by the mshv driver, but must be tracked independently
>>>> since the driver module could be removed and re-inserted.
>>>>
>>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
>>>> ---
>>>>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
>>>>  1 file changed, 32 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>>>> index 252fd66ad4db..2763cb6d3678 100644
>>>> --- a/drivers/hv/hv_common.c
>>>> +++ b/drivers/hv/hv_common.c
>>>> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
>>>>
>>>>  static struct ctl_table_header *hv_ctl_table_hdr;
>>>>
>>>> +/*
>>>> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
>>>> + * for each SINT.
>>>> + *
>>>> + * We cannot maintain this in mshv driver because the tail pointer should
>>>> + * persist even if the mshv driver is unloaded.
>>>> + */
>>>> +u8 __percpu **hv_synic_eventring_tail;
>>>
>>> I think the "__percpu" is in the wrong place here. This placement
>>> is likely to cause errors from the "sparse" tool.  It should be
>>>
>>> u8 * __percpu *hv_synic_eventring_tail;
>>>
>>> See the way hyperv_pcpu_input_arg, for example, is defined.  And
>>> see commit db3c65bc3a13 where I fixed hyperv_pcpu_input_arg.
>>>
>> Thanks. I'll fix it.
>>
>>>> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
>>>
>>> The "extern" declaration for this variable is in Patch 10 of the series
>>> in drivers/hv/mshv_root.h. I guess that's OK, but I would normally
>>> expect to find such a declaration in the header file associated with
>>> where the variable is defined, which in this case is mshyperv.h.
>>> Perhaps you are trying to restrict its usage to just mshv?
>>>
>> Yes, that's the idea - it should only be used by the driver.
>>
>>>> +
>>>>  /*
>>>>   * Hyper-V specific initialization and shutdown code that is
>>>>   * common across all architectures.  Called from architecture
>>>> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
>>>>
>>>>  	free_percpu(hyperv_pcpu_input_arg);
>>>>  	hyperv_pcpu_input_arg = NULL;
>>>> +
>>>> +	free_percpu(hv_synic_eventring_tail);
>>>> +	hv_synic_eventring_tail = NULL;
>>>>  }
>>>>
>>>>  /*
>>>> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
>>>>  		BUG_ON(!hyperv_pcpu_output_arg);
>>>>  	}
>>>>
>>>> +	if (hv_root_partition()) {
>>>> +		hv_synic_eventring_tail = alloc_percpu(u8 *);
>>>> +		BUG_ON(hv_synic_eventring_tail == NULL);
>>>> +	}
>>>> +
>>>>  	hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
>>>>  				    GFP_KERNEL);
>>>>  	if (!hv_vp_index) {
>>>> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
>>>>  int hv_common_cpu_init(unsigned int cpu)
>>>>  {
>>>>  	void **inputarg, **outputarg;
>>>> +	u8 **synic_eventring_tail;
>>>>  	u64 msr_vp_index;
>>>>  	gfp_t flags;
>>>>  	const int pgcount = hv_output_page_exists() ? 2 : 1;
>>>> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
>>>>  	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
>>>>
>>>>  	/*
>>>> -	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
>>>> -	 * allocated if this CPU was previously online and then taken offline
>>>> +	 * The per-cpu memory is already allocated if this CPU was previously
>>>> +	 * online and then taken offline
>>>>  	 */
>>>>  	if (!*inputarg) {
>>>>  		mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
>>>> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
>>>>  			*outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
>>>>  		}
>>>>
>>>> +		if (hv_root_partition()) {
>>>> +			synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
>>>> +			*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
>>>> +							sizeof(u8), flags);
>>>> +
>>>> +			if (unlikely(!*synic_eventring_tail)) {
>>>> +				kfree(mem);
>>>> +				return -ENOMEM;
>>>> +			}
>>>> +		}
>>>> +
>>>
>>> Adding this code under the "if(!*inputarg)" implicitly ties the lifecycle of
>>> synic_eventring_tail to the lifecycle of hyperv_pcpu_input_arg and
>>> hyperv_pcpu_output_arg. Is there some logical relationship between the
>>> two that warrants tying the lifecycles together (other than just both being
>>> per-cpu)?  hyperv_pcpu_input_arg and hyperv_pcpu_output_arg have an
>>> unusual lifecycle management in that they aren't freed when a CPU goes
>>> offline, as described in the comment in hv_common_cpu_die(). Does
>>> synic_eventring_tail also need that same unusual lifecycle?
>>>
>> I thought about it, and no I don't think it shares the same exact lifecycle.
>> It's only used by the mshv_root driver - it just needs to remain present
>> whenever there's a chance the module could be re-inserted and expect it to
>> be there.
>>
>>> Assuming there's no logical relationship, I'm thinking synic_eventring_tail
>>> should be managed independent of the other two. If it does need the
>>> unusual lifecycle, make sure to add a comment in hv_common_cpu_die()
>>> explaining why. If it doesn't need the unusual lifecycle, maybe just do
>>> the normal thing of allocating it in hv_common_cpu_init() and freeing
>>> it in hv_common_cpu_die().
>>>
>> Yep, I suppose it should just be freed normally then, assuming
>> hv_common_cpu_die() is only called when the hypervisor is going to reset
>> (or remove) the synic pages for this partition. Is that the case here?
>>
> 
> Yes, it is the case here. A particular vCPU can be taken offline
> independent of other vCPUs in the VM (such as by writing "0"
> to /sys/devices/system/cpu/cpu<nn>/online). When that happens
> the vCPU going offline runs hv_synic_cleanup() first, and then it
> runs hv_cpu_die(), which calls hv_common_cpu_die(). So by the
> time hv_common_cpu_die() runs, the synic_message_page and
> synic_event_page will have been unmapped and the pointers set
> to NULL.
> 
> On arm64, there is no hv_cpu_init()/die(), and the "common"
> versions are called directly. Perhaps at some point in the future there
> will be arm64 specific things to be done, and hv_cpu_init()/die()
> will need to be added. But the ordering is the same and
> hv_synic_cleanup() runs first.
> 
> So, yes, since synic_eventring_tail is tied to the synic, it sounds like
> the normal lifecycle could be used, like with the VP assist page that
> is handled in hv_cpu_init()/die() on x86.
> 
Great, thanks for the clarification! I'll fix it for v6.

Nuno

>> Otherwise we'd want to retain it, in case mshv_root ever needs it again for
>> that CPU in the lifetime of this partition.
>>
>> Nuno
>>
>>> The code as written in your patch isn't wrong and would work OK. But
>>> the structure implies a relationship with hyperv_pcpu_*_arg that I
>>> suspect doesn't exist.
>>>
>>> Michael
>>>
>>>>  		if (!ms_hyperv.paravisor_present &&
>>>>  		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
>>>>  			ret = set_memory_decrypted((unsigned long)mem, pgcount);
>>>> --
>>>> 2.34.1
> 



From luca.ceresoli at bootlin.com  Fri Mar  7 15:34:25 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Sat, 8 Mar 2025 00:34:25 +0100
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <Z8sqJhbqEBla_Ch7@smile.fi.intel.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
	<20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
	<Z8sqJhbqEBla_Ch7@smile.fi.intel.com>
Message-ID: <20250308003425.7b89bfb6@booty>

Hello Andy,

On Fri, 7 Mar 2025 19:17:26 +0200
Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:

> On Fri, Mar 07, 2025 at 12:19:08PM +0100, Luca Ceresoli wrote:
> > %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> > add %pC{,n,r} format specifiers for clocks") introducing them does not
> > clarify any intended difference. It can be assumed %pC is a default for
> > %pCn as some other specifiers do, but not all are consistent with this
> > policy. Moreover there is now no other suffix other than 'n', which makes a
> > default not really useful.
> > 
> > All users in the kernel were using %pC except for one which has been
> > converted. So now remove %pCn and all the unnecessary extra code and
> > documentation.  
> 
> You seem forgot to update translation(s) of the documentation.

I'm afraid I don't speak Chinese. :-)

For this specific change I think I could come up with an approximation
of it, but the both the docs and git log suggest this is not expected.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From mhklinux at outlook.com  Fri Mar  7 15:37:00 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 23:37:00 +0000
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <SN6PR02MB415710BED37BDD375B0D769AD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157107676CF415A464C2C25D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
 <63437aa6-d45a-4b7a-b222-5901c03c48e0@linux.microsoft.com>
 <SN6PR02MB415710BED37BDD375B0D769AD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <SN6PR02MB415798FCF9548B5CA596E625D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Michael Kelley <mhklinux at outlook.com> Sent: Friday, March 7, 2025 3:21 PM
> 
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 7, 2025
> 2:07 PM
> >

[snip]

> > >> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
> > >>  			*outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
> > >>  		}
> > >>
> > >> +		if (hv_root_partition()) {
> > >> +			synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> > >> +			*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
> > >> +							sizeof(u8), flags);
> > >> +
> > >> +			if (unlikely(!*synic_eventring_tail)) {
> > >> +				kfree(mem);
> > >> +				return -ENOMEM;
> > >> +			}
> > >> +		}
> > >> +
> > >
> > > Adding this code under the "if(!*inputarg)" implicitly ties the lifecycle of
> > > synic_eventring_tail to the lifecycle of hyperv_pcpu_input_arg and
> > > hyperv_pcpu_output_arg. Is there some logical relationship between the
> > > two that warrants tying the lifecycles together (other than just both being
> > > per-cpu)?  hyperv_pcpu_input_arg and hyperv_pcpu_output_arg have an
> > > unusual lifecycle management in that they aren't freed when a CPU goes
> > > offline, as described in the comment in hv_common_cpu_die(). Does
> > > synic_eventring_tail also need that same unusual lifecycle?
> > >
> > I thought about it, and no I don't think it shares the same exact lifecycle.
> > It's only used by the mshv_root driver - it just needs to remain present
> > whenever there's a chance the module could be re-inserted and expect it to
> > be there.
> >
> > > Assuming there's no logical relationship, I'm thinking synic_eventring_tail
> > > should be managed independent of the other two. If it does need the
> > > unusual lifecycle, make sure to add a comment in hv_common_cpu_die()
> > > explaining why. If it doesn't need the unusual lifecycle, maybe just do
> > > the normal thing of allocating it in hv_common_cpu_init() and freeing
> > > it in hv_common_cpu_die().
> > >
> > Yep, I suppose it should just be freed normally then, assuming
> > hv_common_cpu_die() is only called when the hypervisor is going to reset
> > (or remove) the synic pages for this partition. Is that the case here?
> >
> 
> Yes, it is the case here. A particular vCPU can be taken offline
> independent of other vCPUs in the VM (such as by writing "0"
> to /sys/devices/system/cpu/cpu<nn>/online). When that happens
> the vCPU going offline runs hv_synic_cleanup() first, and then it
> runs hv_cpu_die(), which calls hv_common_cpu_die(). So by the
> time hv_common_cpu_die() runs, the synic_message_page and
> synic_event_page will have been unmapped and the pointers set
> to NULL.
> 
> On arm64, there is no hv_cpu_init()/die(), and the "common"
> versions are called directly. Perhaps at some point in the future there
> will be arm64 specific things to be done, and hv_cpu_init()/die()
> will need to be added. But the ordering is the same and
> hv_synic_cleanup() runs first.
> 
> So, yes, since synic_eventring_tail is tied to the synic, it sounds like
> the normal lifecycle could be used, like with the VP assist page that
> is handled in hv_cpu_init()/die() on x86.
> 

One more thought:

Perhaps there's more affinity with synic code than with generic
per-cpu memory, and it would be even better to allocate and
free the synic_eventring_tail memory for each vCPU in
hv_synic_init()/cleanup(), or hv_synic_enable/disable_regs().
There's potentially some interaction with hibernate suspend/resume,
which I assume isn't a valid scenario for the root partition. But I
haven't thought through all the details.

Michael

From helgaas at kernel.org  Fri Mar  7 15:37:40 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri,  7 Mar 2025 17:37:40 -0600
Subject: [PATCH 0/4] PCI: dwc: .cpu_addr_fixup() sketch
Message-ID: <20250307233744.440476-1-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

This is not complete or ready to merge at all.  It's just a sketch to see
if this approach to moving away from the .cpu_addr_fixup() approach is
feasible.

This is based on Frank's series at
https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com,
and these apply on top of these patches from that series, which applies on
v6.15-rc1:

      PCI: dwc: Use resource start as iomap() input in dw_pcie_pme_turn_off()
      PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
      PCI: Add parent_bus_offset to resource_entry

The idea is that on some systems the PCI controller lives in a different
address space (an "intermediate" address space) than the CPU physical
address space.  Frank has a beautiful picture of this at
https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-4-3c4bb506f665 at nxp.com

The devicetree *should* describe the fabric address translation between the
CPU and intermediate address spaces, but historically we haven't taken
advantage of that and have used .cpu_addr_fixup() functions to convert CPU
to intermediate addresses each time we program the ATU.

What I tried to do here was to:

  - Try to extract the offset from devicetree using the 'reg' property
    (this is from Frank's patch at the link above)

  - If a .cpu_addr_fixup() function exists, run that as well and compare
    with the offset from devicetree

  - Save the offset in struct dw_pcie_rp and apply that instead of calling
    .cpu_addr_fixup() in the future

  - Emit messages about devicetree offsets that don't match what
    .cpu_addr_fixup() did, or about .cpu_addr_fixup() methods that are
    superfluous because they *do* match the devicetree offset

I only looked at the RC side and didn't do anything at all with the EP
side.

Bjorn Helgaas (4):
  PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup()
  PCI: dwc: Delay cfg0 setup until after discovering bridge windows
  PCI: dwc: Look up 'config' address
  PCI: dwc: Use parent_bus_offset

 .../pci/controller/dwc/pcie-designware-host.c | 88 +++++++++++++++----
 drivers/pci/controller/dwc/pcie-designware.c  |  3 -
 drivers/pci/controller/dwc/pcie-designware.h  |  1 +
 3 files changed, 72 insertions(+), 20 deletions(-)

-- 
2.34.1



From helgaas at kernel.org  Fri Mar  7 15:37:41 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri,  7 Mar 2025 17:37:41 -0600
Subject: [PATCH 1/4] PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup()
In-Reply-To: <20250307233744.440476-1-helgaas@kernel.org>
References: <20250307233744.440476-1-helgaas@kernel.org>
Message-ID: <20250307233744.440476-2-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

Move pp->cfg0 setup to dw_pcie_cfg0_setup().  No functional change
intended.
---
 .../pci/controller/dwc/pcie-designware-host.c | 34 +++++++++++++------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 1206b26bff3f..de2f2dcf5c40 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -418,22 +418,12 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 	}
 }
 
-int dw_pcie_host_init(struct dw_pcie_rp *pp)
+static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
-	struct device_node *np = dev->of_node;
 	struct platform_device *pdev = to_platform_device(dev);
-	struct resource_entry *win;
-	struct pci_host_bridge *bridge;
 	struct resource *res;
-	int ret;
-
-	raw_spin_lock_init(&pp->lock);
-
-	ret = dw_pcie_get_resources(pci);
-	if (ret)
-		return ret;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (!res) {
@@ -448,6 +438,28 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (IS_ERR(pp->va_cfg0_base))
 		return PTR_ERR(pp->va_cfg0_base);
 
+	return 0;
+}
+
+int dw_pcie_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	struct resource_entry *win;
+	struct pci_host_bridge *bridge;
+	int ret;
+
+	raw_spin_lock_init(&pp->lock);
+
+	ret = dw_pcie_get_resources(pci);
+	if (ret)
+		return ret;
+
+	ret = dw_pcie_cfg0_setup(pp);
+	if (ret)
+		return ret;
+
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)
 		return -ENOMEM;
-- 
2.34.1



From helgaas at kernel.org  Fri Mar  7 15:37:42 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri,  7 Mar 2025 17:37:42 -0600
Subject: [PATCH 2/4] PCI: dwc: Delay cfg0 setup until after discovering bridge windows
In-Reply-To: <20250307233744.440476-1-helgaas@kernel.org>
References: <20250307233744.440476-1-helgaas@kernel.org>
Message-ID: <20250307233744.440476-3-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

devm_pci_alloc_host_bridge() reads host bridge windows and any translation
offsets.  Some .cpu_addr_fixup() implementations depend on the window
offset, e.g., imx_pcie_cpu_addr_fixup() uses the offset of the first bridge
window.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index de2f2dcf5c40..b9eaba157dae 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -456,14 +456,14 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (ret)
 		return ret;
 
-	ret = dw_pcie_cfg0_setup(pp);
-	if (ret)
-		return ret;
-
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)
 		return -ENOMEM;
 
+	ret = dw_pcie_cfg0_setup(pp);
+	if (ret)
+		return ret;
+
 	pp->bridge = bridge;
 
 	/* Get the I/O range from DT */
-- 
2.34.1



From helgaas at kernel.org  Fri Mar  7 15:37:43 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri,  7 Mar 2025 17:37:43 -0600
Subject: [PATCH 3/4] PCI: dwc: Look up 'config' address
In-Reply-To: <20250307233744.440476-1-helgaas@kernel.org>
References: <20250307233744.440476-1-helgaas@kernel.org>
Message-ID: <20250307233744.440476-4-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

Set pp->parent_bus_offset based on the parent bus address from the "config"
reg entry if it exists.

.cpu_addr_fixup(res->start) (if implemented) should return the parent bus
address corresponding to res->start.

Sets pp->parent_bus_offset, but doesn't use it, so no functional change
intended yet.
---
 .../pci/controller/dwc/pcie-designware-host.c | 42 +++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h  |  1 +
 2 files changed, 43 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index b9eaba157dae..e22f650ada5a 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -423,7 +423,11 @@ static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
 	struct platform_device *pdev = to_platform_device(dev);
+	struct device_node *np = dev->of_node;
 	struct resource *res;
+	int index;
+	u64 reg_addr, fixup_addr;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (!res) {
@@ -434,6 +438,44 @@ static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
 	pp->cfg0_size = resource_size(res);
 	pp->cfg0_base = res->start;
 
+	/* [mem 0x7ff00000-] in example */
+	dev_info(dev, "%pR config CPU physical\n", res);
+
+	/* Look up "config" address on parent bus */
+	reg_addr = 0;
+	index = of_property_match_string(np, "reg-names", "config");
+	if (index >= 0) {
+		of_property_read_reg(np, index, &reg_addr, NULL);
+		/* [ia  0x8ff00000-] in example */
+		dev_info(dev, "%#010llx config reg[%d] parent bus addr\n",
+			 reg_addr, index);
+	} else {
+		reg_addr = res->start;
+		dev_warn(dev, "%#010llx assumed parent bus addr (no config reg-names entry)\n",
+			 reg_addr);
+	}
+
+	fixup = pci->ops->cpu_addr_fixup;
+	if (fixup) {
+		fixup_addr = fixup(pci, res->start);
+		dev_info(dev, "%#010llx result of %ps(%#010llx)\n",
+			 fixup_addr, fixup, res->start);
+		if (reg_addr == fixup_addr) {
+			dev_info(dev, "%#010llx config reg[%d] == %#010llx; %ps is redundant\n",
+				 reg_addr, index, fixup_addr, fixup);
+		} else {
+			dev_warn(dev, "%#010llx config reg[%d] != %#010llx fixed up addr; DT is broken\n",
+				 reg_addr, index, fixup_addr);
+			reg_addr = fixup_addr;
+		}
+	}
+
+	/* 0x7ff00000 - 0x8ff00000 == 0xf0000000 */
+	pp->parent_bus_offset = res->start - reg_addr;
+	dev_info(dev, "%#010llx config parent bus offset\n",
+		 pp->parent_bus_offset);
+
+
 	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
 	if (IS_ERR(pp->va_cfg0_base))
 		return PTR_ERR(pp->va_cfg0_base);
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index ac23604c829f..eeca38ec3a2b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -362,6 +362,7 @@ struct dw_pcie_rp {
 	u64			cfg0_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
+	u64			parent_bus_offset;
 	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
-- 
2.34.1



From helgaas at kernel.org  Fri Mar  7 15:37:44 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri,  7 Mar 2025 17:37:44 -0600
Subject: [PATCH 4/4] PCI: dwc: Use parent_bus_offset
In-Reply-To: <20250307233744.440476-1-helgaas@kernel.org>
References: <20250307233744.440476-1-helgaas@kernel.org>
Message-ID: <20250307233744.440476-5-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

We know the parent_bus_offset, either computed from a DT reg property (the
offset is the CPU physical addr - the 'config' address on the parent bus)
or from a .cpu_addr_fixup() (which may have used a host bridge window
offset).

Apply that parent_bus_offset instead of calling .cpu_addr_fixup() again.

This assumes that all intermediate addresses are at the same offset from
the CPU physical addresses.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 drivers/pci/controller/dwc/pcie-designware.c      |  3 ---
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index e22f650ada5a..3378f905b3bd 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -670,7 +670,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.parent_bus_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base - pp->parent_bus_offset;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -695,7 +695,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pp->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -721,7 +721,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pp->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -790,7 +790,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.parent_bus_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start - pp->parent_bus_offset;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -812,7 +812,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.parent_bus_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base - pp->parent_bus_offset;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -956,7 +956,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.parent_bus_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start - pci->pp.parent_bus_offset;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 9d0a5f75effc..640caf4a084f 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -474,9 +474,6 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 	u32 retries, val;
 	u64 limit_addr;
 
-	if (pci->ops && pci->ops->cpu_addr_fixup)
-		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
-
 	limit_addr = parent_bus_addr + atu->size - 1;
 
 	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar  7 15:35:58 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 7 Mar 2025 15:35:58 -0800
Subject: [PATCH v5 09/10] hyperv: Add definitions for root partition
 driver to hv headers
In-Reply-To: <SN6PR02MB41575301E96B82BF3813828BD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB41575301E96B82BF3813828BD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <5ffb92c5-2133-4b47-a1eb-b1acca2c4388@linux.microsoft.com>

On 3/7/2025 9:26 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
>> A few additional definitions are required for the mshv driver code
>> (to follow). Introduce those here and clean up a little bit while
>> at it.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> ---
>>  include/hyperv/hvgdk_mini.h |  64 ++++++++++++++++-
>>  include/hyperv/hvhdk.h      | 132 ++++++++++++++++++++++++++++++++++--
>>  include/hyperv/hvhdk_mini.h |  91 +++++++++++++++++++++++++
>>  3 files changed, 280 insertions(+), 7 deletions(-)
>>
>> diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
>> index 58895883f636..e4a3cca0cbce 100644
>> --- a/include/hyperv/hvgdk_mini.h
>> +++ b/include/hyperv/hvgdk_mini.h
>> @@ -13,7 +13,7 @@ struct hv_u128 {
>>  	u64 high_part;
>>  } __packed;
>>
>> -/* NOTE: when adding below, update hv_status_to_string() */
>> +/* NOTE: when adding below, update hv_result_to_string() */
>>  #define HV_STATUS_SUCCESS			    0x0
>>  #define HV_STATUS_INVALID_HYPERCALL_CODE	    0x2
>>  #define HV_STATUS_INVALID_HYPERCALL_INPUT	    0x3
>> @@ -51,6 +51,7 @@ struct hv_u128 {
>>  #define HV_HYP_PAGE_SHIFT		12
>>  #define HV_HYP_PAGE_SIZE		BIT(HV_HYP_PAGE_SHIFT)
>>  #define HV_HYP_PAGE_MASK		(~(HV_HYP_PAGE_SIZE - 1))
>> +#define HV_HYP_LARGE_PAGE_SHIFT		21
>>
>>  #define HV_PARTITION_ID_INVALID		((u64)0)
>>  #define HV_PARTITION_ID_SELF		((u64)-1)
>> @@ -374,6 +375,10 @@ union hv_hypervisor_version_info {
>>  #define HV_SHARED_GPA_BOUNDARY_ACTIVE			BIT(5)
>>  #define HV_SHARED_GPA_BOUNDARY_BITS			GENMASK(11, 6)
>>
>> +/* HYPERV_CPUID_FEATURES.ECX bits. */
>> +#define HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE	BIT(9)
>> +#define HV_VP_GHCB_ROOT_MAPPING_AVAILABLE		BIT(10)
>> +
>>  enum hv_isolation_type {
>>  	HV_ISOLATION_TYPE_NONE	= 0,	/*
>> HV_PARTITION_ISOLATION_TYPE_NONE */
>>  	HV_ISOLATION_TYPE_VBS	= 1,
>> @@ -437,9 +442,12 @@ union hv_vp_assist_msr_contents {	 /*
>> HV_REGISTER_VP_ASSIST_PAGE */
>>  #define HVCALL_MAP_GPA_PAGES				0x004b
>>  #define HVCALL_UNMAP_GPA_PAGES				0x004c
>>  #define HVCALL_CREATE_VP				0x004e
>> +#define HVCALL_INSTALL_INTERCEPT			0x004d
> 
> This is numerically out-of-order.  Should be before HVCALL_CREATE_VP.
> 
Oops! Thanks for spotting that.

>>  #define HVCALL_DELETE_VP				0x004f
>>  #define HVCALL_GET_VP_REGISTERS				0x0050
>>  #define HVCALL_SET_VP_REGISTERS				0x0051
>> +#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS		0x0052
>> +#define HVCALL_CLEAR_VIRTUAL_INTERRUPT			0x0056
>>  #define HVCALL_DELETE_PORT				0x0058
>>  #define HVCALL_DISCONNECT_PORT				0x005b
>>  #define HVCALL_POST_MESSAGE				0x005c
>> @@ -447,12 +455,15 @@ union hv_vp_assist_msr_contents {	 /*
>> HV_REGISTER_VP_ASSIST_PAGE */
>>  #define HVCALL_POST_DEBUG_DATA				0x0069
>>  #define HVCALL_RETRIEVE_DEBUG_DATA			0x006a
>>  #define HVCALL_RESET_DEBUG_SESSION			0x006b
>> +#define HVCALL_MAP_STATS_PAGE				0x006c
>> +#define HVCALL_UNMAP_STATS_PAGE				0x006d
>>  #define HVCALL_ADD_LOGICAL_PROCESSOR			0x0076
>>  #define HVCALL_GET_SYSTEM_PROPERTY			0x007b
>>  #define HVCALL_MAP_DEVICE_INTERRUPT			0x007c
>>  #define HVCALL_UNMAP_DEVICE_INTERRUPT			0x007d
>>  #define HVCALL_RETARGET_INTERRUPT			0x007e
>>  #define HVCALL_NOTIFY_PORT_RING_EMPTY			0x008b
>> +#define HVCALL_REGISTER_INTERCEPT_RESULT		0x0091
>>  #define HVCALL_ASSERT_VIRTUAL_INTERRUPT			0x0094
>>  #define HVCALL_CREATE_PORT				0x0095
>>  #define HVCALL_CONNECT_PORT				0x0096
>> @@ -460,12 +471,18 @@ union hv_vp_assist_msr_contents {	 /*
>> HV_REGISTER_VP_ASSIST_PAGE */
>>  #define HVCALL_GET_VP_ID_FROM_APIC_ID			0x009a
>>  #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE	0x00af
>>  #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST	0x00b0
>> +#define HVCALL_SIGNAL_EVENT_DIRECT			0x00c0
>> +#define HVCALL_POST_MESSAGE_DIRECT			0x00c1
>>  #define HVCALL_DISPATCH_VP				0x00c2
>> +#define HVCALL_GET_GPA_PAGES_ACCESS_STATES		0x00c9
>> +#define HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d7
>> +#define HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d8
>>  #define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY	0x00db
>>  #define HVCALL_MAP_VP_STATE_PAGE			0x00e1
>>  #define HVCALL_UNMAP_VP_STATE_PAGE			0x00e2
>>  #define HVCALL_GET_VP_STATE				0x00e3
>>  #define HVCALL_SET_VP_STATE				0x00e4
>> +#define HVCALL_GET_VP_CPUID_VALUES			0x00f4
>>  #define HVCALL_MMIO_READ				0x0106
>>  #define HVCALL_MMIO_WRITE				0x0107
>>
>> @@ -807,6 +824,8 @@ struct hv_x64_table_register {
>>  	u64 base;
>>  } __packed;
>>
>> +#define HV_NORMAL_VTL	0
>> +
>>  union hv_input_vtl {
>>  	u8 as_uint8;
>>  	struct {
>> @@ -1325,6 +1344,49 @@ struct hv_retarget_device_interrupt {	 /*
>> HV_INPUT_RETARGET_DEVICE_INTERRUPT */
>>  	struct hv_device_interrupt_target int_target;
>>  } __packed __aligned(8);
>>
>> +enum hv_intercept_type {
>> +#if defined(CONFIG_X86_64)
>> +	HV_INTERCEPT_TYPE_X64_IO_PORT			= 0x00000000,
>> +	HV_INTERCEPT_TYPE_X64_MSR			= 0x00000001,
>> +	HV_INTERCEPT_TYPE_X64_CPUID			= 0x00000002,
>> +#endif
>> +	HV_INTERCEPT_TYPE_EXCEPTION			= 0x00000003,
>> +	/* Used to be HV_INTERCEPT_TYPE_REGISTER */
>> +	HV_INTERCEPT_TYPE_RESERVED0			= 0x00000004,
>> +	HV_INTERCEPT_TYPE_MMIO				= 0x00000005,
>> +#if defined(CONFIG_X86_64)
>> +	HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID		= 0x00000006,
>> +	HV_INTERCEPT_TYPE_X64_APIC_SMI			= 0x00000007,
>> +#endif
>> +	HV_INTERCEPT_TYPE_HYPERCALL			= 0x00000008,
>> +#if defined(CONFIG_X86_64)
>> +	HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI		= 0x00000009,
>> +	HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ	= 0x0000000A,
>> +	HV_INTERCEPT_TYPE_X64_APIC_WRITE		= 0x0000000B,
>> +	HV_INTERCEPT_TYPE_X64_MSR_INDEX			= 0x0000000C,
>> +#endif
>> +	HV_INTERCEPT_TYPE_MAX,
>> +	HV_INTERCEPT_TYPE_INVALID			= 0xFFFFFFFF,
>> +};
>> +
>> +union hv_intercept_parameters {
>> +	/*  HV_INTERCEPT_PARAMETERS is defined to be an 8-byte field. */
>> +	__u64 as_uint64;
>> +#if defined(CONFIG_X86_64)
>> +	/* HV_INTERCEPT_TYPE_X64_IO_PORT */
>> +	__u16 io_port;
>> +	/* HV_INTERCEPT_TYPE_X64_CPUID */
>> +	__u32 cpuid_index;
>> +	/* HV_INTERCEPT_TYPE_X64_APIC_WRITE */
>> +	__u32 apic_write_mask;
>> +	/* HV_INTERCEPT_TYPE_EXCEPTION */
>> +	__u16 exception_vector;
>> +	/* HV_INTERCEPT_TYPE_X64_MSR_INDEX */
>> +	__u32 msr_index;
>> +#endif
>> +	/* N.B. Other intercept types do not have any parameters. */
>> +};
>> +
>>  /* Data structures for HVCALL_MMIO_READ and HVCALL_MMIO_WRITE */
>>  #define HV_HYPERCALL_MMIO_MAX_DATA_LENGTH 64
>>
>> diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
>> index 64407c2a3809..1b447155c338 100644
>> --- a/include/hyperv/hvhdk.h
>> +++ b/include/hyperv/hvhdk.h
>> @@ -19,11 +19,24 @@
>>
>>  #define HV_VP_REGISTER_PAGE_VERSION_1	1u
>>
>> +#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT		7
>> +
>> +union hv_vp_register_page_interrupt_vectors {
>> +	u64 as_uint64;
>> +	struct {
>> +		u8 vector_count;
>> +		u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
>> +	} __packed;
>> +} __packed;
>> +
>>  struct hv_vp_register_page {
>>  	u16 version;
>>  	u8 isvalid;
>>  	u8 rsvdz;
>>  	u32 dirty;
>> +
>> +#if IS_ENABLED(CONFIG_X86)
>> +
>>  	union {
>>  		struct {
>>  			/* General purpose registers
>> @@ -95,6 +108,22 @@ struct hv_vp_register_page {
>>  	union hv_x64_pending_interruption_register pending_interruption;
>>  	union hv_x64_interrupt_state_register interrupt_state;
>>  	u64 instruction_emulation_hints;
>> +	u64 xfem;
>> +
>> +	/*
>> +	 * Fields from this point are not included in the register page save chunk.
>> +	 * The reserved field is intended to maintain alignment for unsaved fields.
>> +	 */
>> +	u8 reserved1[0x100];
>> +
>> +	/*
>> +	 * Interrupts injected as part of HvCallDispatchVp.
>> +	 */
>> +	union hv_vp_register_page_interrupt_vectors interrupt_vectors;
>> +
>> +#elif IS_ENABLED(CONFIG_ARM64)
>> +	/* Not yet supported in ARM */
>> +#endif
>>  } __packed;
>>
>>  #define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
>> @@ -299,10 +328,11 @@ union hv_partition_isolation_properties {
>>  #define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED   0x2
>>
>>  /* Note: Exo partition is enabled by default */
>> -#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION                    BIT(8)
>> -#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED                    BIT(13)
>> -#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED   BIT(19)
>> -#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE                   BIT(22)
>> +#define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED		BIT(4)
>> +#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION			BIT(8)
>> +#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED			BIT(13)
>> +#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED	BIT(19)
>> +#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE			BIT(22)
>>
>>  struct hv_input_create_partition {
>>  	u64 flags;
>> @@ -349,13 +379,23 @@ struct hv_input_set_partition_property {
>>  enum hv_vp_state_page_type {
>>  	HV_VP_STATE_PAGE_REGISTERS = 0,
>>  	HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1,
>> +	HV_VP_STATE_PAGE_GHCB,
> 
> Seems like this enum member should have an explicit value assigned
> since it is part of the contract with the hypervisor.
> 
Fair enough. They are just 0, 1, 2, but I agree it's better to be
explicit with the ABI values.

>>  	HV_VP_STATE_PAGE_COUNT
>>  };
>>
>>  struct hv_input_map_vp_state_page {
>>  	u64 partition_id;
>>  	u32 vp_index;
>> -	u32 type; /* enum hv_vp_state_page_type */
>> +	u16 type; /* enum hv_vp_state_page_type */
>> +	union hv_input_vtl input_vtl;
>> +	union {
>> +		u8 as_uint8;
>> +		struct {
>> +			u8 map_location_provided : 1;
>> +			u8 reserved : 7;
>> +		};
>> +	} flags;
>> +	u64 requested_map_location;
>>  } __packed;
>>
>>  struct hv_output_map_vp_state_page {
>> @@ -365,7 +405,14 @@ struct hv_output_map_vp_state_page {
>>  struct hv_input_unmap_vp_state_page {
>>  	u64 partition_id;
>>  	u32 vp_index;
>> -	u32 type; /* enum hv_vp_state_page_type */
>> +	u16 type; /* enum hv_vp_state_page_type */
>> +	union hv_input_vtl input_vtl;
>> +	u8 reserved0;
>> +} __packed;
>> +
>> +struct hv_x64_apic_eoi_message {
>> +	__u32 vp_index;
>> +	__u32 interrupt_vector;
>>  } __packed;
>>
>>  struct hv_opaque_intercept_message {
>> @@ -515,6 +562,13 @@ struct hv_synthetic_timers_state {
>>  	u64 reserved[5];
>>  } __packed;
>>
>> +struct hv_async_completion_message_payload {
>> +	__u64 partition_id;
>> +	__u32 status;
>> +	__u32 completion_count;
>> +	__u64 sub_status;
>> +} __packed;
>> +
>>  union hv_input_delete_vp {
>>  	u64 as_uint64[2];
>>  	struct {
>> @@ -649,6 +703,57 @@ struct hv_input_set_vp_state {
>>  	union hv_input_set_vp_state_data data[];
>>  } __packed;
>>
>> +union hv_x64_vp_execution_state {
>> +	__u16 as_uint16;
>> +	struct {
>> +		__u16 cpl:2;
>> +		__u16 cr0_pe:1;
>> +		__u16 cr0_am:1;
>> +		__u16 efer_lma:1;
>> +		__u16 debug_active:1;
>> +		__u16 interruption_pending:1;
>> +		__u16 vtl:4;
>> +		__u16 enclave_mode:1;
>> +		__u16 interrupt_shadow:1;
>> +		__u16 virtualization_fault_active:1;
>> +		__u16 reserved:2;
>> +	} __packed;
>> +};
>> +
>> +struct hv_x64_intercept_message_header {
>> +	__u32 vp_index;
>> +	__u8 instruction_length:4;
>> +	__u8 cr8:4; /* Only set for exo partitions */
>> +	__u8 intercept_access_type;
>> +	union hv_x64_vp_execution_state execution_state;
>> +	struct hv_x64_segment_register cs_segment;
>> +	__u64 rip;
>> +	__u64 rflags;
>> +} __packed;
>> +
>> +union hv_x64_memory_access_info {
>> +	__u8 as_uint8;
>> +	struct {
>> +		__u8 gva_valid:1;
>> +		__u8 gva_gpa_valid:1;
>> +		__u8 hypercall_output_pending:1;
>> +		__u8 tlb_locked_no_overlay:1;
>> +		__u8 reserved:4;
>> +	} __packed;
>> +};
>> +
>> +struct hv_x64_memory_intercept_message {
>> +	struct hv_x64_intercept_message_header header;
>> +	__u32 cache_type; /* enum hv_cache_type */
>> +	__u8 instruction_byte_count;
>> +	union hv_x64_memory_access_info memory_access_info;
>> +	__u8 tpr_priority;
>> +	__u8 reserved1;
>> +	__u64 guest_virtual_address;
>> +	__u64 guest_physical_address;
>> +	__u8 instruction_bytes[16];
>> +} __packed;
>> +
>>  /*
>>   * Dispatch state for the VP communicated by the hypervisor to the
>>   * VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
>> @@ -716,6 +821,7 @@ static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message)
>> ==
>>  #define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH		0x8
>>  #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH	0x10
>>  #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH	0x20
>> +#define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION	0x40
>>
>>  struct hv_input_dispatch_vp {
>>  	u64 partition_id;
>> @@ -730,4 +836,18 @@ struct hv_output_dispatch_vp {
>>  	u32 dispatch_event; /* enum hv_vp_dispatch_event */
>>  } __packed;
>>
>> +struct hv_input_modify_sparse_spa_page_host_access {
>> +	u32 host_access : 2;
>> +	u32 reserved : 30;
>> +	u32 flags;
>> +	u64 partition_id;
>> +	u64 spa_page_list[];
>> +} __packed;
>> +
>> +/* hv_input_modify_sparse_spa_page_host_access flags */
>> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE  0x1
>> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED     0x2
>> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE      0x4
>> +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE       0x8
>> +
>>  #endif /* _HV_HVHDK_H */
>> diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h
>> index f8a39d3e9ce6..42e7876455b5 100644
>> --- a/include/hyperv/hvhdk_mini.h
>> +++ b/include/hyperv/hvhdk_mini.h
>> @@ -36,6 +36,52 @@ enum hv_scheduler_type {
>>  	HV_SCHEDULER_TYPE_MAX
>>  };
>>
>> +/* HV_STATS_AREA_TYPE */
>> +enum hv_stats_area_type {
>> +	HV_STATS_AREA_SELF = 0,
>> +	HV_STATS_AREA_PARENT = 1,
>> +	HV_STATS_AREA_INTERNAL = 2,
>> +	HV_STATS_AREA_COUNT
>> +};
>> +
>> +enum hv_stats_object_type {
>> +	HV_STATS_OBJECT_HYPERVISOR		= 0x00000001,
>> +	HV_STATS_OBJECT_LOGICAL_PROCESSOR	= 0x00000002,
>> +	HV_STATS_OBJECT_PARTITION		= 0x00010001,
>> +	HV_STATS_OBJECT_VP			= 0x00010002
>> +};
>> +
>> +union hv_stats_object_identity {
>> +	/* hv_stats_hypervisor */
>> +	struct {
>> +		u8 reserved[15];
>> +		u8 stats_area_type;
>> +	} __packed hv;
>> +
>> +	/* hv_stats_logical_processor */
>> +	struct {
>> +		u32 lp_index;
>> +		u8 reserved[11];
>> +		u8 stats_area_type;
>> +	} __packed lp;
>> +
>> +	/* hv_stats_partition */
>> +	struct {
>> +		u64 partition_id;
>> +		u8  reserved[7];
>> +		u8  stats_area_type;
>> +	} __packed partition;
>> +
>> +	/* hv_stats_vp */
>> +	struct {
>> +		u64 partition_id;
>> +		u32 vp_index;
>> +		u16 flags;
>> +		u8  reserved;
>> +		u8  stats_area_type;
>> +	} __packed vp;
>> +};
>> +
>>  enum hv_partition_property_code {
>>  	/* Privilege properties */
>>  	HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS			= 0x00010000,
>> @@ -47,19 +93,45 @@ enum hv_partition_property_code {
>>
>>  	/* Compatibility properties */
>>  	HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES		=
>> 0x00060002,
>> +	HV_PARTITION_PROPERTY_XSAVE_STATES                      = 0x00060007,
>>  	HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE		= 0x00060008,
>>  	HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY		=
>> 0x00060009,
>>  };
>>
>> +enum hv_snp_status {
>> +	HV_SNP_STATUS_NONE = 0,
>> +	HV_SNP_STATUS_AVAILABLE = 1,
>> +	HV_SNP_STATUS_INCOMPATIBLE = 2,
>> +	HV_SNP_STATUS_PSP_UNAVAILABLE = 3,
>> +	HV_SNP_STATUS_PSP_INIT_FAILED = 4,
>> +	HV_SNP_STATUS_PSP_BAD_FW_VERSION = 5,
>> +	HV_SNP_STATUS_BAD_CONFIGURATION = 6,
>> +	HV_SNP_STATUS_PSP_FW_UPDATE_IN_PROGRESS = 7,
>> +	HV_SNP_STATUS_PSP_RB_INIT_FAILED = 8,
>> +	HV_SNP_STATUS_PSP_PLATFORM_STATUS_FAILED = 9,
>> +	HV_SNP_STATUS_PSP_INIT_LATE_FAILED = 10,
>> +};
>> +
>>  enum hv_system_property {
>>  	/* Add more values when needed */
>>  	HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15,
>> +	HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21,
>> +};
>> +
>> +enum hv_dynamic_processor_feature_property {
>> +	/* Add more values when needed */
>> +	HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13,
>> +	HV_X64_DYNAMIC_PROCESSOR_FEATURE_SNP_STATUS = 16,
>>  };
>>
>>  struct hv_input_get_system_property {
>>  	u32 property_id; /* enum hv_system_property */
>>  	union {
>>  		u32 as_uint32;
>> +#if IS_ENABLED(CONFIG_X86)
>> +		/* enum hv_dynamic_processor_feature_property */
>> +		u32 hv_processor_feature;
>> +#endif
>>  		/* More fields to be filled in when needed */
>>  	};
>>  } __packed;
>> @@ -67,9 +139,28 @@ struct hv_input_get_system_property {
>>  struct hv_output_get_system_property {
>>  	union {
>>  		u32 scheduler_type; /* enum hv_scheduler_type */
>> +#if IS_ENABLED(CONFIG_X86)
>> +		u64 hv_processor_feature_value;
>> +#endif
>>  	};
>>  } __packed;
>>
>> +struct hv_input_map_stats_page {
>> +	u32 type; /* enum hv_stats_object_type */
>> +	u32 padding;
>> +	union hv_stats_object_identity identity;
>> +} __packed;
>> +
>> +struct hv_output_map_stats_page {
>> +	u64 map_location;
>> +} __packed;
>> +
>> +struct hv_input_unmap_stats_page {
>> +	u32 type; /* enum hv_stats_object_type */
>> +	u32 padding;
>> +	union hv_stats_object_identity identity;
>> +} __packed;
>> +
>>  struct hv_proximity_domain_flags {
>>  	u32 proximity_preferred : 1;
>>  	u32 reserved : 30;
>> --
>> 2.34.1



From sboyd at kernel.org  Fri Mar  7 15:38:46 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Fri, 07 Mar 2025 15:38:46 -0800
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format specifier
In-Reply-To: <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com> <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
Message-ID: <8e6c0123099039c2f69715f57ef7ba42.sboyd@kernel.org>

Quoting Luca Ceresoli (2025-03-07 03:19:08)
> %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> add %pC{,n,r} format specifiers for clocks") introducing them does not
> clarify any intended difference. It can be assumed %pC is a default for
> %pCn as some other specifiers do, but not all are consistent with this
> policy. Moreover there is now no other suffix other than 'n', which makes a
> default not really useful.
> 
> All users in the kernel were using %pC except for one which has been
> converted. So now remove %pCn and all the unnecessary extra code and
> documentation.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---

Acked-by: Stephen Boyd <sboyd at kernel.org>


From helgaas at kernel.org  Fri Mar  7 15:41:31 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri, 7 Mar 2025 17:41:31 -0600
Subject: [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
In-Reply-To: <Z8sRl1c//SZXKhB+@lizhi-Precision-Tower-5810>
Message-ID: <20250307234131.GA440690@bhelgaas>

On Fri, Mar 07, 2025 at 10:32:39AM -0500, Frank Li wrote:
> On Tue, Mar 04, 2025 at 05:25:45PM -0500, Frank Li wrote:
> > On Tue, Mar 04, 2025 at 05:11:54PM -0500, Frank Li wrote:
> > > On Tue, Mar 04, 2025 at 11:50:10AM -0600, Bjorn Helgaas wrote:
> > > > On Mon, Mar 03, 2025 at 04:57:29PM -0500, Frank Li wrote:
> > > > > On Wed, Feb 26, 2025 at 06:23:26PM -0600, Bjorn Helgaas wrote:
> > > > > > On Tue, Jan 28, 2025 at 05:07:36PM -0500, Frank Li wrote:
> > > > > > > Introduce `parent_bus_offset` in `resource_entry` and a new API,
> > > > > > > `pci_add_resource_parent_bus_offset()`, to provide necessary information
> > > > > > > for PCI controllers with address translation units.
> > > > > > >
> > > > > > > Typical PCI data flow involves:
> > > > > > >   CPU (CPU address) -> Bus Fabric (Intermediate address) ->
> > > > > > >   PCI Controller (PCI bus address) -> PCI Bus.
> > > > > > >
> > > > > > > While most bus fabrics preserve address consistency, some modify addresses
> > > > > > > to intermediate values. The `parent_bus_offset` enables PCI controllers to
> > > > > > > translate these intermediate addresses correctly to PCI bus addresses.
> > > > > > >
> > > > > > > Pave the road to remove hardcoded cpu_addr_fixup() and similar patterns in
> > > > > > > PCI controller drivers.
> > > > > > > ...
> > > > > >
> > > > > > > +++ b/drivers/pci/of.c
> > > > > > > @@ -402,7 +402,17 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev,
> > > > > > >  			res->flags &= ~IORESOURCE_MEM_64;
> > > > > > >  		}
> > > > > > >
> > > > > > > -		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> > > > > > > +		/*
> > > > > > > +		 * IORESOURCE_IO res->start is io space start address.
> > > > > > > +		 * IORESOURCE_MEM res->start is cpu start address, which is the
> > > > > > > +		 * same as range.cpu_addr.
> > > > > > > +		 *
> > > > > > > +		 * Use (range.cpu_addr - range.parent_bus_addr) to align both
> > > > > > > +		 * IO and MEM's parent_bus_offset always offset to cpu address.
> > > > > > > +		 */
> > > > > > > +
> > > > > > > +		pci_add_resource_parent_bus_offset(resources, res, res->start - range.pci_addr,
> > > > > > > +						   range.cpu_addr - range.parent_bus_addr);
> > > > > >
> > > > > > I don't know exactly where it needs to go, but I think we can call
> > > > > > .cpu_addr_fixup() once at startup on the base of the region.  This
> > > > > > will tell us the offset that applies to the entire region, i.e.,
> > > > > > parent_bus_offset.
> > > > > >
> > > > > > Then we can remove all the .cpu_addr_fixup() calls in
> > > > > > cdns_pcie_host_init_address_translation(),
> > > > > > cdns_pcie_set_outbound_region(), and dw_pcie_prog_outbound_atu().
> > > > > >
> > > > > > Until we can get rid of all the .cpu_addr_fixup() implementations,
> > > > > > We'll still have that single call at startup (I guess once for cadence
> > > > > > and another for designware), but it should simplify the current
> > > > > > callers quite a bit.
> > > > >
> > > > > I don't think it can simple code. cdns_pcie_set_outbound_region() and
> > > > > dw_pcie_prog_outbound_atu() are called by EP functions, which have not use
> > > > > "resource" to manage outbound windows.
> > > >
> > > > Let's ignore cadence for now.  I don't think we need to solve that
> > > > until later.
> > > >
> > > > dw_pcie_prog_outbound_atu() is called by:
> > > >
> > > >   - dw_pcie_other_conf_map_bus(): atu.parent_bus_addr = pp->cfg0_base
> > > >
> > > >     I think dw_pcie_host_init() can set pp->cfg0_base with the correct
> > > >     intermediate address, either via the the of_property_read_reg() or
> > > >     .cpu_addr_fixup().
> >
> > And chicken and egg problem here for artpec6_pcie_cpu_addr_fixup(), which
> > need cfg0_base. But try to use .cpu_addr_fixup() to get cfg0_base's
> > intermediate address.
> 
> Bjorn:
> 	Do you have chance to check my reply? some dwc platform driver
> .cpu_addr_fixup() implement have dependence with old initilize sequency.

Yes, I tried to sketch out what I was thinking to make it more
concrete.  I posted it and sent to you, but just for other readers of
this thread, it's at:

https://lore.kernel.org/linux-pci/20250307233744.440476-1-helgaas at kernel.org/T/#t

Bjorn


From mhklinux at outlook.com  Fri Mar  7 15:45:10 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 7 Mar 2025 23:45:10 +0000
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <86bf7bae-9423-4413-8986-364d96243c82@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB415730AA9A9BFFBB9A62F195D4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
 <86bf7bae-9423-4413-8986-364d96243c82@linux.microsoft.com>
Message-ID: <SN6PR02MB4157F84C1CE53A12F042C71BD4D52@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 7, 2025 3:30 PM
> 
> On 3/7/2025 9:44 AM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> >
> >>
> >> This will handle SYNIC interrupts such as intercepts, doorbells, and
> >> scheduling messages intended for the mshv driver.
> >
> > Could you provide a bit more detailed commit message? How does
> > the mshv_handler() relate to the vmbus_handler()? From the code
> > mshv_handler() goes first, and I'm assuming it processes what it
> > knows about (intercepts, doorbells, scheduling messages?) and
> > then hands off control to the vmbus_handler() to handle the usual
> > VMbus-related message and channel interrupts. But it would be
> > nice to have the commit message or code comments describe the
> > overall intent and any obscure aspects of the relationship.
> >
> > And avoid references to "This" or "This patch". :-)
> >
> 
> You've described it pretty well, I don't know if there's too much
> more to say given this patch doesn't introduce the handler code.
> 
> I can try to improve it, something like:
> "
> mshv_handler() will be used to process messages related to managing
> guest partitions such as intercepts, doorbells, and scheduling messages.
> 
> In a (non-nested) root partition, the same interrupt vector is shared
> between the vmbus and mshv_root drivers.
> 
> Introduce a stub for mshv_handler() and call it in
> sysvec_hyperv_callback alongside vmbus_handler().
> 
> Even though both handlers will be called for every Hyper-V interrupt,
> the messages for each driver are delivered to different offsets within
> the SYNIC message page, so they won't step on each other.
> "
> 
> Does that work?

Yes, that works. I was going to ask how the two handlers could
Both be used on the same interrupt, and you've provided the
explanation, which is perfect. ;-)

Minor tweak: Start the first sentence as an imperative:

   Add mshv_handler() to process messages related .....

Michael


From jacob.e.keller at intel.com  Fri Mar  7 15:48:27 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Fri, 7 Mar 2025 15:48:27 -0800
Subject: Plan to validate supported flags in PTP core (Was: Re: [PATCH net v2
 0/2] Fixes for perout configuration in IEP driver)
In-Reply-To: <a7e434a5-b5f6-4736-98e4-e671f88d1873@intel.com>
References: <20250219062701.995955-1-m-malladi@ti.com>
 <415f755d-18a6-4c81-a1a7-b75d54a5886a@intel.com>
 <20250220172410.025b96d6@kernel.org>
 <a7e434a5-b5f6-4736-98e4-e671f88d1873@intel.com>
Message-ID: <f7072ca6-47a7-4278-be5d-7cbd240fcd35@intel.com>



On 2/21/2025 2:22 PM, Jacob Keller wrote:
> 
> 
> On 2/20/2025 5:24 PM, Jakub Kicinski wrote:
>> On Wed, 19 Feb 2025 15:37:16 -0800 Jacob Keller wrote:
>>> On 2/18/2025 10:26 PM, Meghana Malladi wrote:
>>>> IEP driver supports both pps and perout signal generation using testptp
>>>> application. Currently the driver is missing to incorporate the perout
>>>> signal configuration. This series introduces fixes in the driver to
>>>> configure perout signal based on the arguments passed by the perout
>>>> request.
>>>>   
>>>
>>> This could be interpreted as a feature implementation rather than a fix.
>>>
>>> Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
>>
>> Agreed, ideally we should get a patch for net which rejects
>> all currently (as in - in Linus's tree) unsupported settings.
>> That would be a fix.
>>
>> Then once that's merged add support for the new settings in net-next.
>>
>> Hope that makes sense?
> 
> +1 on this direction, its important that the driver does not accept
> configuration which is incorrect.
> 
> Reminds me of my backlog to refactor this whole mess into a
> supported_flags field in the PTP ops structure. Maybe it is again time
> to revive that.
> 
I've been looking into this the last week or so and I have what i think
is a workable plan, but I'd like to get some feedback before continuing.

I believe we ought to add .supported_extts_flags and
.supported_perout_flags to the ptp_info struct. These will get checked
by the core, to reject commands which set flags not specified here.

For PTP_EXTTS_REQUEST, the PTP_ENABLE_FEATURE flag is always accepted.

The behavior of PTP_RISING_EDGE and PTP_FALLING_EDGE is somewhat
complicated. I think the best way to handle it is to check the
PTP_STRICT_FLAGS. If the driver sets this, then assume they will
validate the flags properly and only enable strict matching modes. In
that case, check against all flags as.

If the driver does not set PTP_STRICT_FLAGS, (For example, drivers which
don't set anything because they forgot), we only allow ENABLE,
RISING_EDGE, and FALLING_EDGE, but not STRICT. This essentially disables
the v2 ioctl, and prevents users from getting strict behavior, (since
the driver did not say it would handle strict behavior!)

For periodic output, its easy, since all the flags are present only with
the v2 ioctl, so we can do a simple & ~supported_flags check.

The bigger question I have is.. what should we do about the existing
drivers which do not bother to check flags at all?

In my search I found these driver files set the n_ext_ts field to a
non-zero value but do not have any flag checks:

>      ? drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
>      ? drivers/net/ethernet/freescale/enetc/enetc_ptp.c
>      ? drivers/net/ethernet/intel/i40e/i40e_ptp.c
>      ? drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
>      ? drivers/net/ethernet/renesas/rtsn.c
>      ? drivers/net/ethernet/renesas/rtsn.h
>      ? drivers/net/ethernet/ti/am65-cpts.c
>      ? drivers/net/ethernet/ti/cpts.h
>      ? drivers/net/ethernet/ti/icssg/icss_iep.c
>      ? drivers/net/ethernet/xscale/ptp_ixp46x.c
>      ? drivers/net/phy/bcm-phy-ptp.c
>      ? drivers/ptp/ptp_ocp.c
>      ? drivers/ptp/ptp_pch.c
>      ? drivers/ptp/ptp_qoriq.c

If a user sends the V2 ioctl, they'll happily ignore strict checks and
do who knows what.

With my changes applied, the core would now automatically reject the v2
ioctl.

I believe this is an improvement, but I'm not sure whether we should
just make this change with a net-next feature improvement.

Should I prepare a patch for net which updates the drivers to manually
check and reject requests with flags other than PTP_EXT_TS_V1_FLAGS
first, before sending my changes to the core?

Worse, there are a couple of drivers including one hardware in igb, the
renesas driver, and the lan743x driver which do some checks but which
ultimately don't properly honor the PTP_STRICT_FLAGS.

If I send these all together as separate patches, I end up with more
than 15 patches total, and thats before I've finished investigating the
PTP_PEROUT_REQUEST, which I believe is likely to have a similar number
of issues.

Would a series with individual patches for the 3 special cases + one
patch to handle all the drivers that have no explicit flag check be
acceptable? Or should I do individual patches for each driver and just
break the series up? Or are we ok with just fixing this in next with the
.supported_extts_flags change?

Thanks,
Jake


From wbg at kernel.org  Fri Mar  7 16:17:04 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Sat,  8 Mar 2025 09:17:04 +0900
Subject: [PATCH v8 0/2] microchip-tcb-capture: Add Capture, Compare, Overflow etc. events
In-Reply-To: <20250306134441.582819-1-csokas.bence@prolan.hu>
References: <20250306134441.582819-1-csokas.bence@prolan.hu>
Message-ID: <174139258236.459919.5227805319293627161.b4-ty@kernel.org>


On Thu, 06 Mar 2025 14:44:35 +0100, Bence Cs?k?s wrote:
> The TCB has three R/W-able "general purpose" hardware registers:
> RA, RB and RC. The hardware is capable of:
> * sampling Counter Value Register (CV) to RA/RB on a trigger edge
> * sending an interrupt of this change
> * sending an interrupt on CV change due to trigger
> * triggering an interrupt on CV compare to RC
> * stop counting after sampling to RB
> 
> [...]

Applied to counter-next, thanks!

[1/2] counter: microchip-tcb-capture: Add IRQ handling
      commit: e5d5813968217b99ef2b83f13353967b218e3841
[2/2] counter: microchip-tcb-capture: Add capture extensions for registers RA/RB
      commit: 1adc6240a80278c613f655b71c6c0d447b2d5932

Bence, I've submitted a patchset adding support for the RC Compare as a
new 'compare' Count extension.[^1] If it works for you, please Ack that
series and we can hopefully get everything picked up by the 6.15 merge
window.

William Breathitt Gray <wbg at kernel.org>

[^1] https://lore.kernel.org/linux-iio/20250306-introduce-compare-component-v1-0-93993b3dca9c at kernel.org/


From irogers at google.com  Fri Mar  7 16:32:00 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:00 -0800
Subject: [PATCH v5 02/11] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-3-irogers@google.com>

There are many and non-obvious meanings to the dso_binary_type enum
values. Add kernel-doc to speed interpretting their meanings.

Acked-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 53 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index dfd763a0bd9d..4aa8c3d36566 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -20,30 +20,83 @@ struct perf_env;
 #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
 #define DSO__NAME_KCORE		"[kernel.kcore]"
 
+/**
+ * enum dso_binary_type - The kind of DSO generally associated with a memory
+ *                        region (struct map).
+ */
 enum dso_binary_type {
+	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
 	DSO_BINARY_TYPE__KALLSYMS = 0,
+	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
 	DSO_BINARY_TYPE__GUEST_KALLSYMS,
+	/** @DSO_BINARY_TYPE__VMLINUX: Path to kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__VMLINUX,
+	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to guest kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__GUEST_VMLINUX,
+	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
 	DSO_BINARY_TYPE__JAVA_JIT,
+	/**
+	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
+	 * in the .gnu_debuglink ELF section of the dso.
+	 */
 	DSO_BINARY_TYPE__DEBUGLINK,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
+	 * the buildid cache with an elf filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
+	 * located in the buildid cache with a debug filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
+	 * with .debug suffix.
+	 */
 	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
 	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
+	 * file in /usr/lib/debug/lib rather than the expected
+	 * /usr/lib/debug/usr/lib.
+	 */
 	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
+	 * in /usr/lib/debug/.build-id/.
+	 */
 	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
 	DSO_BINARY_TYPE__KCORE,
+	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
 	DSO_BINARY_TYPE__GUEST_KCORE,
+	/**
+	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
+	 * package debug info.
+	 */
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
 	DSO_BINARY_TYPE__BPF_PROG_INFO,
+	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
 	DSO_BINARY_TYPE__BPF_IMAGE,
+	/**
+	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
+	 * instructions or optimized kprobes or ftrace trampolines.
+	 */
 	DSO_BINARY_TYPE__OOL,
+	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:01 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:01 -0800
Subject: [PATCH v5 03/11] perf syscalltbl: Remove syscall_table.h
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-4-irogers@google.com>

The definition of "static const char *const syscalltbl[] = {" is done
in a generated syscalls_32.h or syscalls_64.h that is architecture
dependent. In order to include the appropriate file a syscall_table.h
is found via the perf include path and it includes the syscalls_32.h
or syscalls_64.h as appropriate.

To support having multiple syscall tables, one for 32-bit and one for
64-bit, or for different architectures, an include path cannot be
used. Remove syscall_table.h because of this and inline what it does
into syscalltbl.c.

For architectures without a syscall_table.h this will cause a failure
to include either syscalls_32.h or syscalls_64.h rather than a failure
to include syscall_table.h. For architectures that only included one
or other, the behavior matches BITS_PER_LONG as previously done on
architectures supporting both syscalls_32.h and syscalls_64.h.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/arch/alpha/include/syscall_table.h     | 2 --
 tools/perf/arch/arc/include/syscall_table.h       | 2 --
 tools/perf/arch/arm/include/syscall_table.h       | 2 --
 tools/perf/arch/arm64/include/syscall_table.h     | 8 --------
 tools/perf/arch/csky/include/syscall_table.h      | 2 --
 tools/perf/arch/loongarch/include/syscall_table.h | 2 --
 tools/perf/arch/mips/include/syscall_table.h      | 2 --
 tools/perf/arch/parisc/include/syscall_table.h    | 8 --------
 tools/perf/arch/powerpc/include/syscall_table.h   | 8 --------
 tools/perf/arch/riscv/include/syscall_table.h     | 8 --------
 tools/perf/arch/s390/include/syscall_table.h      | 2 --
 tools/perf/arch/sh/include/syscall_table.h        | 2 --
 tools/perf/arch/sparc/include/syscall_table.h     | 8 --------
 tools/perf/arch/x86/include/syscall_table.h       | 8 --------
 tools/perf/arch/xtensa/include/syscall_table.h    | 2 --
 tools/perf/util/syscalltbl.c                      | 8 +++++++-
 16 files changed, 7 insertions(+), 67 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h

diff --git a/tools/perf/arch/alpha/include/syscall_table.h b/tools/perf/arch/alpha/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/alpha/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/arc/include/syscall_table.h b/tools/perf/arch/arc/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arc/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm/include/syscall_table.h b/tools/perf/arch/arm/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arm/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm64/include/syscall_table.h b/tools/perf/arch/arm64/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/arm64/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/csky/include/syscall_table.h b/tools/perf/arch/csky/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/csky/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/loongarch/include/syscall_table.h b/tools/perf/arch/loongarch/include/syscall_table.h
deleted file mode 100644
index 9d0646d3455c..000000000000
--- a/tools/perf/arch/loongarch/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscall_table_64.h>
diff --git a/tools/perf/arch/mips/include/syscall_table.h b/tools/perf/arch/mips/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/mips/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/parisc/include/syscall_table.h b/tools/perf/arch/parisc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/parisc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/powerpc/include/syscall_table.h b/tools/perf/arch/powerpc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/powerpc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/riscv/include/syscall_table.h b/tools/perf/arch/riscv/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/riscv/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/s390/include/syscall_table.h b/tools/perf/arch/s390/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/s390/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/sh/include/syscall_table.h b/tools/perf/arch/sh/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/sh/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/sparc/include/syscall_table.h b/tools/perf/arch/sparc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/sparc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/x86/include/syscall_table.h b/tools/perf/arch/x86/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/x86/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/xtensa/include/syscall_table.h b/tools/perf/arch/xtensa/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/xtensa/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 928aca4cd6e9..2f76241494c8 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -7,13 +7,19 @@
 
 #include "syscalltbl.h"
 #include <stdlib.h>
+#include <asm/bitsperlong.h>
 #include <linux/compiler.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
 #include "string2.h"
 
-#include <syscall_table.h>
+#if __BITS_PER_LONG == 64
+  #include <asm/syscalls_64.h>
+#else
+  #include <asm/syscalls_32.h>
+#endif
+
 const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
 static const char *const *syscalltbl_native = syscalltbl;
 
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:02 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:02 -0800
Subject: [PATCH v5 04/11] perf trace: Reorganize syscalls
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-5-irogers@google.com>

Identify struct syscall information in the syscalls table by a machine
type and syscall number, not just system call number. Having the
machine type means that 32-bit system calls can be differentiated from
64-bit ones on a machine capable of both. Having a table for all
machine types and all system call numbers would be too large, so
maintain a sorted array of system calls as they are encountered.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c | 177 ++++++++++++++++++++++++-------------
 1 file changed, 118 insertions(+), 59 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 092c5f6404ba..f7d035dc0e00 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -66,6 +66,7 @@
 #include "syscalltbl.h"
 #include "../perf.h"
 #include "trace_augment.h"
+#include "dwarf-regs.h"
 
 #include <errno.h>
 #include <inttypes.h>
@@ -86,6 +87,7 @@
 
 #include <linux/ctype.h>
 #include <perf/mmap.h>
+#include <tools/libc_compat.h>
 
 #ifdef HAVE_LIBTRACEEVENT
 #include <event-parse.h>
@@ -149,7 +151,10 @@ struct trace {
 	struct perf_tool	tool;
 	struct syscalltbl	*sctbl;
 	struct {
+		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
+		/** Size of table. */
+		size_t		table_size;
 		struct {
 			struct evsel *sys_enter,
 				*sys_exit,
@@ -1454,22 +1459,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
 	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
 }
 
-/*
- * is_exit: is this "exit" or "exit_group"?
- * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
- * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
- * nonexistent: Just a hole in the syscall table, syscall id not allocated
+/**
+ * struct syscall
  */
 struct syscall {
+	/** @e_machine: The ELF machine associated with the entry. */
+	int e_machine;
+	/** @id: id value from the tracepoint, the system call number. */
+	int id;
 	struct tep_event    *tp_format;
 	int		    nr_args;
+	/**
+	 * @args_size: sum of the sizes of the syscall arguments, anything
+	 * after that is augmented stuff: pathname for openat, etc.
+	 */
+
 	int		    args_size;
 	struct {
 		struct bpf_program *sys_enter,
 				   *sys_exit;
 	}		    bpf_prog;
+	/** @is_exit: is this "exit" or "exit_group"? */
 	bool		    is_exit;
+	/**
+	 * @is_open: is this "open" or "openat"? To associate the fd returned in
+	 * sys_exit with the pathname in sys_enter.
+	 */
 	bool		    is_open;
+	/**
+	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
+	 * syscall id not allocated.
+	 */
 	bool		    nonexistent;
 	bool		    use_btf;
 	struct tep_format_field *args;
@@ -2107,22 +2127,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
 	return 0;
 }
 
-static int trace__read_syscall_info(struct trace *trace, int id)
+static int syscall__read_info(struct syscall *sc, struct trace *trace)
 {
 	char tp_name[128];
-	struct syscall *sc;
-	const char *name = syscalltbl__name(trace->sctbl, id);
+	const char *name;
 	int err;
 
-	if (trace->syscalls.table == NULL) {
-		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
-		if (trace->syscalls.table == NULL)
-			return -ENOMEM;
-	}
-	sc = trace->syscalls.table + id;
 	if (sc->nonexistent)
 		return -EEXIST;
 
+	if (sc->name) {
+		/* Info already read. */
+		return 0;
+	}
+
+	name = syscalltbl__name(trace->sctbl, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2145,15 +2164,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 	 */
 	if (IS_ERR(sc->tp_format)) {
 		sc->nonexistent = true;
-		return PTR_ERR(sc->tp_format);
+		err = PTR_ERR(sc->tp_format);
+		sc->tp_format = NULL;
+		return err;
 	}
 
 	/*
 	 * The tracepoint format contains __syscall_nr field, so it's one more
 	 * than the actual number of syscall arguments.
 	 */
-	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
-					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
+	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
 		return -ENOMEM;
 
 	sc->args = sc->tp_format->format.fields;
@@ -2442,13 +2462,67 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
+static void syscall__init(struct syscall *sc, int e_machine, int id)
+{
+	memset(sc, 0, sizeof(*sc));
+	sc->e_machine = e_machine;
+	sc->id = id;
+}
+
+static void syscall__exit(struct syscall *sc)
+{
+	if (!sc)
+		return;
+
+	zfree(&sc->arg_fmt);
+}
+
+static int syscall__cmp(const void *va, const void *vb)
+{
+	const struct syscall *a = va, *b = vb;
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
+}
+
+static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
+{
+	struct syscall key = {
+		.e_machine = e_machine,
+		.id = id,
+	};
+	struct syscall *sc, *tmp;
+
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	if (sc)
+		return sc;
+
+	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
+			   sizeof(struct syscall));
+	if (!tmp)
+		return NULL;
+
+	trace->syscalls.table = tmp;
+	sc = &trace->syscalls.table[trace->syscalls.table_size++];
+	syscall__init(sc, e_machine, id);
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	      syscall__cmp);
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	return sc;
+}
+
 typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
 				  union perf_event *event,
 				  struct perf_sample *sample);
 
-static struct syscall *trace__syscall_info(struct trace *trace,
-					   struct evsel *evsel, int id)
+static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
+					   int e_machine, int id)
 {
+	struct syscall *sc;
 	int err = 0;
 
 	if (id < 0) {
@@ -2473,28 +2547,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
 
 	err = -EINVAL;
 
-	if (id > trace->sctbl->syscalls.max_id) {
-		goto out_cant_read;
-	}
-
-	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
-	    (err = trace__read_syscall_info(trace, id)) != 0)
-		goto out_cant_read;
+	sc = trace__find_syscall(trace, e_machine, id);
+	if (sc)
+		err = syscall__read_info(sc, trace);
 
-	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
-		goto out_cant_read;
-
-	return &trace->syscalls.table[id];
-
-out_cant_read:
-	if (verbose > 0) {
+	if (err && verbose > 0) {
 		char sbuf[STRERR_BUFSIZE];
-		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
-		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
-			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
+
+		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
+			str_error_r(-err, sbuf, sizeof(sbuf)));
+		if (sc && sc->name)
+			fprintf(trace->output, "(%s)", sc->name);
 		fputs(" information\n", trace->output);
 	}
-	return NULL;
+	return err ? NULL : sc;
 }
 
 struct syscall_stats {
@@ -2643,14 +2709,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
 	return NULL;
 }
 
-static void syscall__exit(struct syscall *sc)
-{
-	if (!sc)
-		return;
-
-	zfree(&sc->arg_fmt);
-}
-
 static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 			    union perf_event *event __maybe_unused,
 			    struct perf_sample *sample)
@@ -2662,7 +2720,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -2736,7 +2794,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
 	int augmented_args_size;
@@ -2811,7 +2869,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -3164,7 +3222,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		struct syscall *sc = trace__syscall_info(trace, evsel, id);
+		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -3673,7 +3731,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 
 static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 
 	if (sc == NULL)
 		return;
@@ -3684,20 +3742,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 
 static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3795,7 +3853,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 try_to_find_pair:
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, id);
+		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
@@ -3945,7 +4003,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 */
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, key);
+		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4761,7 +4819,10 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = &trace->syscalls.table[entry->syscall];
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			if (!sc)
+				continue;
+
 			printed += fprintf(fp, "   %-15s", sc->name);
 			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
 					   n, stats->nr_failures, entry->msecs, min, avg);
@@ -5218,12 +5279,10 @@ static int trace__config(const char *var, const char *value, void *arg)
 
 static void trace__exit(struct trace *trace)
 {
-	int i;
-
 	strlist__delete(trace->ev_qualifier);
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
-		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
+		for (size_t i = 0; i < trace->syscalls.table_size; i++)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:03 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:03 -0800
Subject: [PATCH v5 05/11] perf syscalltbl: Remove struct syscalltbl
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-6-irogers@google.com>

The syscalltbl held entries of system call name and number pairs,
generated from a native syscalltbl at start up. As there are gaps in
the system call number there is a notion of index into the
table. Going forward we want the system call table to be identifiable
by a machine type, for example, i386 vs x86-64. Change the interface
to the syscalltbl so (1) a (currently unused machine type of EM_HOST)
is passed (2) the index to syscall number and system call name mapping
is computed at build time.

Two tables are used for this, an array of system call number to name,
an array of system call numbers sorted by the system call name. The
sorted array doesn't store strings in part to save memory and
relocations. The index notion is carried forward and is an index into
the sorted array of system call numbers, the data structures are
opaque (held only in syscalltbl.c), and so the number of indices for a
machine type is exposed as a new API.

The arrays are computed in the syscalltbl.sh script and so no start-up
time computation and storage is necessary.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c       | 106 +++++++++++++++++------------
 tools/perf/scripts/syscalltbl.sh |  36 ++++------
 tools/perf/util/syscalltbl.c     | 113 ++++++++++---------------------
 tools/perf/util/syscalltbl.h     |  22 ++----
 4 files changed, 117 insertions(+), 160 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index f7d035dc0e00..cfc8cb8cbef8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -149,7 +149,6 @@ enum summary_mode {
 
 struct trace {
 	struct perf_tool	tool;
-	struct syscalltbl	*sctbl;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
@@ -188,6 +187,14 @@ struct trace {
 		pid_t		*entries;
 		struct bpf_map  *map;
 	}			filter_pids;
+	/*
+	 * TODO: The map is from an ID (aka system call number) to struct
+	 * syscall_stats. If there is >1 e_machine, such as i386 and x86-64
+	 * processes, then the stats here will gather wrong the statistics for
+	 * the non EM_HOST system calls. A fix would be to add the e_machine
+	 * into the key, but this would make the code inconsistent with the
+	 * per-thread version.
+	 */
 	struct hashmap		*syscall_stats;
 	double			duration_filter;
 	double			runtime_ms;
@@ -2141,7 +2148,7 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace)
 		return 0;
 	}
 
-	name = syscalltbl__name(trace->sctbl, sc->id);
+	name = syscalltbl__name(sc->e_machine, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2241,10 +2248,14 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 
 	strlist__for_each_entry(pos, trace->ev_qualifier) {
 		const char *sc = pos->s;
-		int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
+		/*
+		 * TODO: Assume more than the validation/warnings are all for
+		 * the same binary type as perf.
+		 */
+		int id = syscalltbl__id(EM_HOST, sc), match_next = -1;
 
 		if (id < 0) {
-			id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_first(EM_HOST, sc, &match_next);
 			if (id >= 0)
 				goto matches;
 
@@ -2264,7 +2275,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 			continue;
 
 		while (1) {
-			id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_next(EM_HOST, sc, &match_next);
 			if (id < 0)
 				break;
 			if (nr_allocated == nr_used) {
@@ -2720,6 +2731,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -2794,6 +2806,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
@@ -2869,6 +2882,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -3222,6 +3236,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+		/* TODO: get e_machine from thread. */
 		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
@@ -3729,9 +3744,9 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 	return trace->skel->progs.syscall_unaugmented;
 }
 
-static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
+static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 
 	if (sc == NULL)
 		return;
@@ -3740,22 +3755,22 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 	sc->bpf_prog.sys_exit  = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit  : NULL,  "exit");
 }
 
-static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
+static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3851,9 +3866,9 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc->e_machine, i);
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
@@ -3937,7 +3952,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 }
 
-static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
 {
 	int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
 	int map_exit_fd  = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
@@ -3945,27 +3960,27 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	int err = 0;
 	unsigned int beauty_array[6];
 
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int prog_fd, key = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int prog_fd, key = syscalltbl__id_at_idx(e_machine, i);
 
 		if (!trace__syscall_enabled(trace, key))
 			continue;
 
-		trace__init_syscall_bpf_progs(trace, key);
+		trace__init_syscall_bpf_progs(trace, e_machine, key);
 
 		// It'll get at least the "!raw_syscalls:unaugmented"
-		prog_fd = trace__bpf_prog_sys_enter_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_enter_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
-		prog_fd = trace__bpf_prog_sys_exit_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_exit_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
 
 		/* use beauty_map to tell BPF how many bytes to collect, set beauty_map's value here */
 		memset(beauty_array, 0, sizeof(beauty_array));
-		err = trace__bpf_sys_enter_beauty_map(trace, key, (unsigned int *)beauty_array);
+		err = trace__bpf_sys_enter_beauty_map(trace, e_machine, key, (unsigned int *)beauty_array);
 		if (err)
 			continue;
 		err = bpf_map_update_elem(beauty_map_fd, &key, beauty_array, BPF_ANY);
@@ -4001,9 +4016,9 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 * first and second arg (this one on the raw_syscalls:sys_exit prog
 	 * array tail call, then that one will be used.
 	 */
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int key = syscalltbl__id_at_idx(e_machine, i);
+		struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4449,8 +4464,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 		goto out_error_mem;
 
 #ifdef HAVE_BPF_SKEL
-	if (trace->skel && trace->skel->progs.sys_enter)
-		trace__init_syscalls_bpf_prog_array_maps(trace);
+	if (trace->skel && trace->skel->progs.sys_enter) {
+		/*
+		 * TODO: Initialize for all host binary machine types, not just
+		 * those matching the perf binary.
+		 */
+		trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
+	}
 #endif
 
 	if (trace->ev_qualifier_ids.nr > 0) {
@@ -4475,7 +4495,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	 *  So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is
 	 *  not in use.
 	 */
-	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close"));
+	/* TODO: support for more than just perf binary machine type close. */
+	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(EM_HOST, "close"));
 
 	err = trace__expand_filters(trace, &evsel);
 	if (err)
@@ -4788,7 +4809,7 @@ static struct syscall_entry *syscall__sort_stats(struct hashmap *syscall_stats)
 	return entry;
 }
 
-static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
+static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
 				  struct hashmap *syscall_stats)
 {
 	size_t printed = 0;
@@ -4819,7 +4840,7 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, e_machine, entry->syscall);
 			if (!sc)
 				continue;
 
@@ -4846,14 +4867,14 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 }
 
 static size_t thread__dump_stats(struct thread_trace *ttrace,
-				 struct trace *trace, FILE *fp)
+				 struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, ttrace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, ttrace->syscall_stats);
 }
 
-static size_t system__dump_stats(struct trace *trace, FILE *fp)
+static size_t system__dump_stats(struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, trace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, trace->syscall_stats);
 }
 
 static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
@@ -4879,7 +4900,8 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += thread__dump_stats(ttrace, trace, fp);
+	/* TODO: get e_machine from thread. */
+	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -4940,7 +4962,8 @@ static size_t trace__fprintf_total_summary(struct trace *trace, FILE *fp)
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += system__dump_stats(trace, fp);
+	/* TODO: get all system e_machines. */
+	printed += system__dump_stats(trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -5132,8 +5155,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
 			*sep = '\0';
 
 		list = 0;
-		if (syscalltbl__id(trace->sctbl, s) >= 0 ||
-		    syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
+		/* TODO: support for more than just perf binary machine type syscalls. */
+		if (syscalltbl__id(EM_HOST, s) >= 0 ||
+		    syscalltbl__strglobmatch_first(EM_HOST, s, &idx) >= 0) {
 			list = 1;
 			goto do_concat;
 		}
@@ -5286,7 +5310,6 @@ static void trace__exit(struct trace *trace)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-	syscalltbl__delete(trace->sctbl);
 	zfree(&trace->perfconfig_events);
 }
 
@@ -5435,9 +5458,8 @@ int cmd_trace(int argc, const char **argv)
 	sigaction(SIGCHLD, &sigchld_act, NULL);
 
 	trace.evlist = evlist__new();
-	trace.sctbl = syscalltbl__new();
 
-	if (trace.evlist == NULL || trace.sctbl == NULL) {
+	if (trace.evlist == NULL) {
 		pr_err("Not enough memory to run!\n");
 		err = -ENOMEM;
 		goto out;
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
index 1ce0d5aa8b50..a39b3013b103 100755
--- a/tools/perf/scripts/syscalltbl.sh
+++ b/tools/perf/scripts/syscalltbl.sh
@@ -50,37 +50,27 @@ fi
 infile="$1"
 outfile="$2"
 
-nxt=0
-
-syscall_macro() {
-    nr="$1"
-    name="$2"
-
-    echo "	[$nr] = \"$name\","
-}
-
-emit() {
-    nr="$1"
-    entry="$2"
-
-    syscall_macro "$nr" "$entry"
-}
-
-echo "static const char *const syscalltbl[] = {" > $outfile
-
 sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
 grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
 
-max_nr=0
+echo "static const char *const syscall_num_to_name[] = {" > $outfile
 # the params are: nr abi name entry compat
 # use _ for intentionally unused variables according to SC2034
 while read nr _ name _ _; do
-    emit "$nr" "$name" >> $outfile
-    max_nr=$nr
+	echo "	[$nr] = \"$name\"," >> $outfile
 done < $sorted_table
+echo "};" >> $outfile
 
-rm -f $sorted_table
+echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
 
+# When sorting by name, add a suffix of 0s upto 20 characters so that system
+# calls that differ with a numerical suffix don't sort before those
+# without. This default behavior of sort differs from that of strcmp used at
+# runtime. Use sed to strip the trailing 0s suffix afterwards.
+grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
+while read name nr; do
+	echo "	$nr,	/* $name */" >> $outfile
+done < $sorted_table
 echo "};" >> $outfile
 
-echo "#define SYSCALLTBL_MAX_ID ${max_nr}" >> $outfile
+rm -f $sorted_table
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 2f76241494c8..760ac4d0869f 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <asm/bitsperlong.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
@@ -20,112 +21,66 @@
   #include <asm/syscalls_32.h>
 #endif
 
-const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
-static const char *const *syscalltbl_native = syscalltbl;
+const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+{
+	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
+		return syscall_num_to_name[id];
+	return NULL;
+}
 
-struct syscall {
-	int id;
+struct syscall_cmp_key {
 	const char *name;
+	const char *const *tbl;
 };
 
 static int syscallcmpname(const void *vkey, const void *ventry)
 {
-	const char *key = vkey;
-	const struct syscall *entry = ventry;
+	const struct syscall_cmp_key *key = vkey;
+	const uint16_t *entry = ventry;
 
-	return strcmp(key, entry->name);
+	return strcmp(key->name, key->tbl[*entry]);
 }
 
-static int syscallcmp(const void *va, const void *vb)
+int syscalltbl__id(int e_machine __maybe_unused, const char *name)
 {
-	const struct syscall *a = va, *b = vb;
-
-	return strcmp(a->name, b->name);
+	struct syscall_cmp_key key = {
+		.name = name,
+		.tbl = syscall_num_to_name,
+	};
+	const int *id = bsearch(&key, syscall_sorted_names,
+				ARRAY_SIZE(syscall_sorted_names),
+				sizeof(syscall_sorted_names[0]),
+				syscallcmpname);
+
+	return id ? *id : -1;
 }
 
-static int syscalltbl__init_native(struct syscalltbl *tbl)
+int syscalltbl__num_idx(int e_machine __maybe_unused)
 {
-	int nr_entries = 0, i, j;
-	struct syscall *entries;
-
-	for (i = 0; i <= syscalltbl_native_max_id; ++i)
-		if (syscalltbl_native[i])
-			++nr_entries;
-
-	entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
-	if (tbl->syscalls.entries == NULL)
-		return -1;
-
-	for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
-		if (syscalltbl_native[i]) {
-			entries[j].name = syscalltbl_native[i];
-			entries[j].id = i;
-			++j;
-		}
-	}
-
-	qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
-	tbl->syscalls.nr_entries = nr_entries;
-	tbl->syscalls.max_id	 = syscalltbl_native_max_id;
-	return 0;
+	return ARRAY_SIZE(syscall_sorted_names);
 }
 
-struct syscalltbl *syscalltbl__new(void)
+int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
 {
-	struct syscalltbl *tbl = malloc(sizeof(*tbl));
-	if (tbl) {
-		if (syscalltbl__init_native(tbl)) {
-			free(tbl);
-			return NULL;
-		}
-	}
-	return tbl;
-}
-
-void syscalltbl__delete(struct syscalltbl *tbl)
-{
-	zfree(&tbl->syscalls.entries);
-	free(tbl);
-}
-
-const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
-{
-	return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
-}
-
-int syscalltbl__id(struct syscalltbl *tbl, const char *name)
-{
-	struct syscall *sc = bsearch(name, tbl->syscalls.entries,
-				     tbl->syscalls.nr_entries, sizeof(*sc),
-				     syscallcmpname);
-
-	return sc ? sc->id : -1;
-}
-
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx)
-{
-	struct syscall *syscalls = tbl->syscalls.entries;
-
-	return idx < tbl->syscalls.nr_entries ? syscalls[idx].id : -1;
+	return syscall_sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
 {
-	int i;
-	struct syscall *syscalls = tbl->syscalls.entries;
+	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
+		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
 
-	for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
-		if (strglobmatch(syscalls[i].name, syscall_glob)) {
+		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscalls[i].id;
+			return syscall_sorted_names[i];
 		}
 	}
 
 	return -1;
 }
 
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx)
 {
 	*idx = -1;
-	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+	return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx);
 }
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index 362411a6d849..2bb628eff367 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -2,22 +2,12 @@
 #ifndef __PERF_SYSCALLTBL_H
 #define __PERF_SYSCALLTBL_H
 
-struct syscalltbl {
-	struct {
-		int max_id;
-		int nr_entries;
-		void *entries;
-	} syscalls;
-};
+const char *syscalltbl__name(int e_machine, int id);
+int syscalltbl__id(int e_machine, const char *name);
+int syscalltbl__num_idx(int e_machine);
+int syscalltbl__id_at_idx(int e_machine, int idx);
 
-struct syscalltbl *syscalltbl__new(void);
-void syscalltbl__delete(struct syscalltbl *tbl);
-
-const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
-int syscalltbl__id(struct syscalltbl *tbl, const char *name);
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx);
-
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx);
 
 #endif /* __PERF_SYSCALLTBL_H */
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:04 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:04 -0800
Subject: [PATCH v5 06/11] perf dso: Add support for reading the e_machine type
 for a dso
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-7-irogers@google.com>

For ELF file dsos read the e_machine from the ELF header. For kernel
types assume the e_machine matches the perf tool. In other cases
return EM_NONE.

When reading from the ELF header use DSO__SWAP that may need
dso->needs_swap initializing. Factor out dso__swap_init to allow this.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.c        | 88 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/dso.h        |  3 ++
 tools/perf/util/symbol-elf.c | 27 -----------
 3 files changed, 91 insertions(+), 27 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 5c6e85fdae0d..00fec1bc32bc 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1170,6 +1170,67 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 	return data_read_write_offset(dso, machine, offset, data, size, true);
 }
 
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
+{
+	uint16_t e_machine = EM_NONE;
+	int fd;
+
+	switch (dso__binary_type(dso)) {
+	case DSO_BINARY_TYPE__KALLSYMS:
+	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
+	case DSO_BINARY_TYPE__VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_KMODULE:
+	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
+	case DSO_BINARY_TYPE__KCORE:
+	case DSO_BINARY_TYPE__GUEST_KCORE:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
+	case DSO_BINARY_TYPE__BPF_IMAGE:
+	case DSO_BINARY_TYPE__OOL:
+	case DSO_BINARY_TYPE__JAVA_JIT:
+		return EM_HOST;
+	case DSO_BINARY_TYPE__DEBUGLINK:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
+	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
+	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+		break;
+	case DSO_BINARY_TYPE__NOT_FOUND:
+	default:
+		return EM_NONE;
+	}
+
+	pthread_mutex_lock(&dso__data_open_lock);
+
+	/*
+	 * dso__data(dso)->fd might be closed if other thread opened another
+	 * file (dso) due to open file limit (RLIMIT_NOFILE).
+	 */
+	try_to_open_dso(dso, machine);
+	fd = dso__data(dso)->fd;
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
+			unsigned char eidata;
+
+			if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
+				dso__swap_init(dso, eidata);
+		}
+		if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
+		    pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
+			e_machine = DSO__SWAP(dso, uint16_t, e_machine);
+	}
+	pthread_mutex_unlock(&dso__data_open_lock);
+	return e_machine;
+}
+
 /**
  * dso__data_read_addr - Read data from dso address
  * @dso: dso object
@@ -1525,6 +1586,33 @@ void dso__put(struct dso *dso)
 		RC_CHK_PUT(dso);
 }
 
+int dso__swap_init(struct dso *dso, unsigned char eidata)
+{
+	static unsigned int const endian = 1;
+
+	dso__set_needs_swap(dso, DSO_SWAP__NO);
+
+	switch (eidata) {
+	case ELFDATA2LSB:
+		/* We are big endian, DSO is little endian. */
+		if (*(unsigned char const *)&endian != 1)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	case ELFDATA2MSB:
+		/* We are little endian, DSO is big endian. */
+		if (*(unsigned char const *)&endian != 0)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	default:
+		pr_err("unrecognized DSO data encoding %d\n", eidata);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid)
 {
 	RC_CHK_ACCESS(dso)->bid = *bid;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 4aa8c3d36566..38d9e3eac501 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -730,6 +730,8 @@ bool dso__sorted_by_name(const struct dso *dso);
 void dso__set_sorted_by_name(struct dso *dso);
 void dso__sort_by_name(struct dso *dso);
 
+int dso__swap_init(struct dso *dso, unsigned char eidata);
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid);
 bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
 void dso__read_running_kernel_build_id(struct dso *dso,
@@ -818,6 +820,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
 off_t dso__data_size(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 			      u64 offset, u8 *data, ssize_t size);
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
 			    struct machine *machine, u64 addr,
 			    u8 *data, ssize_t size);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 66fd1249660a..71df13a5722a 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1173,33 +1173,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
 
 #endif
 
-static int dso__swap_init(struct dso *dso, unsigned char eidata)
-{
-	static unsigned int const endian = 1;
-
-	dso__set_needs_swap(dso, DSO_SWAP__NO);
-
-	switch (eidata) {
-	case ELFDATA2LSB:
-		/* We are big endian, DSO is little endian. */
-		if (*(unsigned char const *)&endian != 1)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	case ELFDATA2MSB:
-		/* We are little endian, DSO is big endian. */
-		if (*(unsigned char const *)&endian != 0)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	default:
-		pr_err("unrecognized DSO data encoding %d\n", eidata);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 bool symsrc__possibly_runtime(struct symsrc *ss)
 {
 	return ss->dynsym || ss->opdsec;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:05 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:05 -0800
Subject: [PATCH v5 07/11] perf thread: Add support for reading the e_machine
 type for a thread
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-8-irogers@google.com>

First try to read the e_machine from the dsos associated with the
thread's maps. If live use the executable from /proc/pid/exe and read
the e_machine from the ELF header. On failure use EM_HOST. Change
builtin-trace syscall functions to pass e_machine from the thread
rather than EM_HOST, so that in later patches when syscalltbl can use
the e_machine the system calls are specific to the architecture.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 43 ++++++++++----------
 tools/perf/util/thread.c   | 80 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/thread.h   | 14 ++++++-
 3 files changed, 115 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index cfc8cb8cbef8..49199d753b7c 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2729,16 +2729,16 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int printed = 0;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	int augmented_args_size = 0;
+	int augmented_args_size = 0, e_machine;
 	void *augmented_args = NULL;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -2806,17 +2806,18 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	char msg[1024];
 	void *args, *augmented_args = NULL;
-	int augmented_args_size;
+	int augmented_args_size, e_machine;
 	size_t printed = 0;
 
-	if (sc == NULL)
-		return -1;
 
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		return -1;
 	ttrace = thread__trace(thread, trace);
 	/*
 	 * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
@@ -2881,15 +2882,15 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	bool duration_calculated = false;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
-	int alignment = trace->args_alignment;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	int alignment = trace->args_alignment, e_machine;
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -3236,8 +3237,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		/* TODO: get e_machine from thread. */
-		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+		int e_machine = thread ? thread__e_machine(thread, trace->host) : EM_HOST;
+		struct syscall *sc = trace__syscall_info(trace, evsel, e_machine, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -4881,6 +4882,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 {
 	size_t printed = 0;
 	struct thread_trace *ttrace = thread__priv(thread);
+	int e_machine = thread__e_machine(thread, trace->host);
 	double ratio;
 
 	if (ttrace == NULL)
@@ -4900,8 +4902,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	/* TODO: get e_machine from thread. */
-	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
+	printed += thread__dump_stats(ttrace, trace, e_machine, fp);
 
 	return printed;
 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0ffdd52d86d7..89585f53c1d5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <elf.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,6 +18,7 @@
 #include "symbol.h"
 #include "unwind.h"
 #include "callchain.h"
+#include "dwarf-regs.h"
 
 #include <api/fs/fs.h>
 
@@ -51,6 +54,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		thread__set_ppid(thread, -1);
 		thread__set_cpu(thread, -1);
 		thread__set_guest_cpu(thread, -1);
+		thread__set_e_machine(thread, EM_NONE);
 		thread__set_lbr_stitch_enable(thread, false);
 		INIT_LIST_HEAD(thread__namespaces_list(thread));
 		INIT_LIST_HEAD(thread__comm_list(thread));
@@ -423,6 +427,82 @@ void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
 	}
 }
 
+static uint16_t read_proc_e_machine_for_pid(pid_t pid)
+{
+	char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */];
+	int fd;
+	uint16_t e_machine = EM_NONE;
+
+	snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+	fd = open(path, O_RDONLY);
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
+			e_machine = EM_NONE;
+		close(fd);
+	}
+	return e_machine;
+}
+
+static int thread__e_machine_callback(struct map *map, void *machine)
+{
+	struct dso *dso = map__dso(map);
+
+	_Static_assert(0 == EM_NONE, "Unexpected EM_NONE");
+	if (!dso)
+		return EM_NONE;
+
+	return dso__e_machine(dso, machine);
+}
+
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine)
+{
+	pid_t tid, pid;
+	uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine;
+
+	if (e_machine != EM_NONE)
+		return e_machine;
+
+	tid = thread__tid(thread);
+	pid = thread__pid(thread);
+	if (pid != tid) {
+		struct thread *parent = machine__findnew_thread(machine, pid, pid);
+
+		if (parent) {
+			e_machine = thread__e_machine(parent, machine);
+			thread__set_e_machine(thread, e_machine);
+			return e_machine;
+		}
+		/* Something went wrong, fallback. */
+	}
+	/* Reading on the PID thread. First try to find from the maps. */
+	e_machine = maps__for_each_map(thread__maps(thread),
+				       thread__e_machine_callback,
+				       machine);
+	if (e_machine == EM_NONE) {
+		/* Maps failed, perhaps we're live with map events disabled. */
+		bool is_live = machine->machines == NULL;
+
+		if (!is_live) {
+			/* Check if the session has a data file. */
+			struct perf_session *session = container_of(machine->machines,
+								    struct perf_session,
+								    machines);
+
+			is_live = !!session->data;
+		}
+		/* Read from /proc/pid/exe if live. */
+		if (is_live)
+			e_machine = read_proc_e_machine_for_pid(pid);
+	}
+	if (e_machine != EM_NONE)
+		thread__set_e_machine(thread, e_machine);
+	else
+		e_machine = EM_HOST;
+	return e_machine;
+}
+
 struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
 {
 	if (thread__pid(thread) == thread__tid(thread))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 6cbf6eb2812e..cd574a896418 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -60,7 +60,11 @@ DECLARE_RC_STRUCT(thread) {
 	struct srccode_state	srccode_state;
 	bool			filter;
 	int			filter_entry_depth;
-
+	/**
+	 * @e_machine: The ELF EM_* associated with the thread. EM_NONE if not
+	 * computed.
+	 */
+	uint16_t		e_machine;
 	/* LBR call stack stitch */
 	bool			lbr_stitch_enable;
 	struct lbr_stitch	*lbr_stitch;
@@ -302,6 +306,14 @@ static inline void thread__set_filter_entry_depth(struct thread *thread, int dep
 	RC_CHK_ACCESS(thread)->filter_entry_depth = depth;
 }
 
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine);
+
+static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine)
+{
+	RC_CHK_ACCESS(thread)->e_machine = e_machine;
+}
+
+
 static inline bool thread__lbr_stitch_enable(const struct thread *thread)
 {
 	return RC_CHK_ACCESS(thread)->lbr_stitch_enable;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:06 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:06 -0800
Subject: [PATCH v5 08/11] perf trace beauty: Add syscalltbl.sh generating all
 system call tables
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-9-irogers@google.com>

Rather than generating individual syscall header files generate a
single trace/beauty/generated/syscalltbl.c. In a syscalltbls array
have references to each architectures tables along with the
corresponding e_machine. When the 32-bit or 64-bit table is ambiguous,
match the perf binary's type. For ARM32 don't use the arm64 32-bit
table which is smaller. EM_NONE is present for is no machine matches.

Conditionally compile the tables, only having the appropriate 32 and
64-bit table. If ALL_SYSCALLTBL is defined all tables can be
compiled.

Add comment for noreturn column suggested by Arnd Bergmann:
https://lore.kernel.org/lkml/d47c35dd-9c52-48e7-a00d-135572f11fbb at app.fastmail.com/
and added in commit 9142be9e6443 ("x86/syscall: Mark exit[_group]
syscall handlers __noreturn").

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf              |   9 +
 tools/perf/trace/beauty/syscalltbl.sh | 274 ++++++++++++++++++++++++++
 2 files changed, 283 insertions(+)
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d0b50ccc9d7b..f949ec72f3d2 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -559,6 +559,14 @@ beauty_ioctl_outdir := $(beauty_outdir)/ioctl
 # Create output directory if not already present
 $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
 
+syscall_array := $(beauty_outdir)/syscalltbl.c
+syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh
+syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \
+	$(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl)
+
+$(syscall_array): $(syscall_tbl) $(syscall_tbl_data)
+	$(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@
+
 fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c
 fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh
 
@@ -878,6 +886,7 @@ build-dir   = $(or $(__build-dir),.)
 
 prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders \
 	arm64-sysreg-defs \
+	$(syscall_array) \
 	$(fs_at_flags_array) \
 	$(clone_flags_array) \
 	$(drm_ioctl_array) \
diff --git a/tools/perf/trace/beauty/syscalltbl.sh b/tools/perf/trace/beauty/syscalltbl.sh
new file mode 100755
index 000000000000..1199618dc178
--- /dev/null
+++ b/tools/perf/trace/beauty/syscalltbl.sh
@@ -0,0 +1,274 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate all syscall tables.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT [noreturn]]
+#
+# NR       syscall number
+# ABI      ABI name
+# NAME     syscall name
+# NATIVE   native entry point (optional)
+# COMPAT   compat entry point (optional)
+# noreturn system call doesn't return (optional)
+set -e
+
+usage() {
+       cat >&2 <<EOF
+usage: $0 <TOOLS DIRECTORY> <OUTFILE>
+
+  <TOOLS DIRECTORY>    path to kernel tools directory
+  <OUTFILE>            output header file
+EOF
+       exit 1
+}
+
+if [ $# -ne 2 ]; then
+       usage
+fi
+tools_dir=$1
+outfile=$2
+
+build_tables() {
+	infile="$1"
+	outfile="$2"
+	abis=$(echo "($3)" | tr ',' '|')
+	e_machine="$4"
+
+	if [ ! -f "$infile" ]
+	then
+		echo "Missing file $infile"
+		exit 1
+	fi
+	sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > "$sorted_table"
+
+	echo "static const char *const syscall_num_to_name_${e_machine}[] = {" >> "$outfile"
+	# the params are: nr abi name entry compat
+	# use _ for intentionally unused variables according to SC2034
+	while read -r nr _ name _ _; do
+		echo "	[$nr] = \"$name\"," >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	echo "static const uint16_t syscall_sorted_names_${e_machine}[] = {" >> "$outfile"
+
+	# When sorting by name, add a suffix of 0s upto 20 characters so that
+	# system calls that differ with a numerical suffix don't sort before
+	# those without. This default behavior of sort differs from that of
+	# strcmp used at runtime. Use sed to strip the trailing 0s suffix
+	# afterwards.
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > "$sorted_table"
+	while read -r name nr; do
+		echo "	$nr,	/* $name */" >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	rm -f "$sorted_table"
+}
+
+rm -f "$outfile"
+cat >> "$outfile" <<EOF
+#include <elf.h>
+#include <stdint.h>
+#include <asm/bitsperlong.h>
+#include <linux/kernel.h>
+
+struct syscalltbl {
+       const char *const *num_to_name;
+       const uint16_t *sorted_names;
+       uint16_t e_machine;
+       uint16_t num_to_name_len;
+       uint16_t sorted_names_len;
+};
+
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_tables "$tools_dir/perf/arch/alpha/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_ALPHA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_tables "$tools_dir/perf/arch/arm/entry/syscalls/syscall.tbl" "$outfile" common,32,oabi EM_ARM
+build_tables "$tools_dir/perf/arch/arm64/entry/syscalls/syscall_64.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_AARCH64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,csky,time32,stat64,rlimit EM_CSKY
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_tables "$tools_dir/perf/arch/mips/entry/syscalls/syscall_n64.tbl" "$outfile" common,64,n64 EM_MIPS
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_PARISC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_PARISC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,32,nospu EM_PPC
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,64,nospu EM_PPC64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,riscv,memfd_secret EM_RISCV
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64,riscv,rlimit,memfd_secret EM_RISCV
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_tables "$tools_dir/perf/arch/s390/entry/syscalls/syscall.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_S390
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_tables "$tools_dir/perf/arch/sh/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SH
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SPARC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_SPARC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_32.tbl" "$outfile" common,32,i386 EM_386
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_64.tbl" "$outfile" common,64 EM_X86_64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_tables "$tools_dir/perf/arch/xtensa/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_XTENSA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32 EM_NONE
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64 EM_NONE
+echo "#endif //__BITS_PER_LONG != 64" >> "$outfile"
+
+build_outer_table() {
+       e_machine=$1
+       outfile="$2"
+       cat >> "$outfile" <<EOF
+       {
+	      .num_to_name = syscall_num_to_name_$e_machine,
+	      .sorted_names = syscall_sorted_names_$e_machine,
+	      .e_machine = $e_machine,
+	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_$e_machine),
+	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_$e_machine),
+       },
+EOF
+}
+
+cat >> "$outfile" <<EOF
+static const struct syscalltbl syscalltbls[] = {
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_outer_table EM_ALPHA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_outer_table EM_ARM "$outfile"
+build_outer_table EM_AARCH64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_outer_table EM_CSKY "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_outer_table EM_MIPS "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+EOF
+build_outer_table EM_PARISC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_outer_table EM_PPC "$outfile"
+build_outer_table EM_PPC64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+EOF
+build_outer_table EM_RISCV "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_outer_table EM_S390 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_outer_table EM_SH "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+EOF
+build_outer_table EM_SPARC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_outer_table EM_386 "$outfile"
+build_outer_table EM_X86_64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_XTENSA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_NONE "$outfile"
+cat >> "$outfile" <<EOF
+};
+EOF
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:07 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:07 -0800
Subject: [PATCH v5 09/11] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-10-irogers@google.com>

Switch to use the lookup table containing all architectures rather
than tables matching the perf binary.

This fixes perf trace when executed on a 32-bit i386 binary on an
x86-64 machine. Note in the following the system call names of the
32-bit i386 binary as seen by an x86-64 perf.

Before:
```
         ? (         ): a.out/447296  ... [continued]: munmap())                                           = 0
     0.024 ( 0.001 ms): a.out/447296 recvfrom(ubuf: 0x2, size: 4160585708, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|NOSIGNAL|WAITFORONE|BATCH|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f80000, addr: 0xe30, addr_len: 0xffce438c) = 1475198976
     0.042 ( 0.003 ms): a.out/447296 lgetxattr(name: "", value: 0x3, size: 34)                             = 4160344064
     0.054 ( 0.003 ms): a.out/447296 dup2(oldfd: -134422744, newfd: 4)                                     = -1 ENOENT (No such file or directory)
     0.060 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x2e646c2f6374652f,.iov_len = (__kernel_size_t)7307199665335594867,}, vlen: 557056, pos_h: 4160585708) = 3
     0.074 ( 0.004 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2)                              = 4160237568
     0.080 ( 0.001 ms): a.out/447296 lstat(filename: "", statbuf: 0x193f6)                                 = 0
     0.089 ( 0.007 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x3833692f62696c2f,.iov_len = (__kernel_size_t)3276497845987585334,}, vlen: 557056, pos_h: 4160585708) = 3
     0.097 ( 0.002 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 512
     0.103 ( 0.002 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2050)                           = 4157935616
     0.107 ( 0.007 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x5, size: 2066)             = 4158078976
     0.116 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x1, size: 2066)             = 4159639552
     0.121 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 2066)             = 4160184320
     0.129 ( 0.002 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 50)               = 4160196608
     0.138 ( 0.001 ms): a.out/447296 lstat(filename: "")                                                   = 0
     0.145 ( 0.002 ms): a.out/447296 mq_timedreceive(mqdes: 4291706800, u_msg_ptr: 0xf7f9ea48, msg_len: 134616640, u_msg_prio: 0xf7fd7fec, u_abs_timeout: (struct __kernel_timespec){.tv_sec = (__kernel_time64_t)-578174027777317696,.tv_nsec = (long long int)4160349376,}) = 0
     0.148 ( 0.001 ms): a.out/447296 mkdirat(dfd: -134617816, pathname: " ??? ???????????", mode: IFREG|ISUID|IRUSR|IWGRP|0xf7fd0000) = 447296
     0.150 ( 0.001 ms): a.out/447296 process_vm_writev(pid: -134617812, lvec: (struct iovec){.iov_base = (void *)0xf7f9e9c8f7f9e4c0,.iov_len = (__kernel_size_t)4160349376,}, liovcnt: 4160588048, rvec: (struct iovec){}, riovcnt: 4160585708, flags: 4291707352) = 0
     0.197 ( 0.004 ms): a.out/447296 capget(header: 4160184320, dataptr: 8192)                             = 0
     0.202 ( 0.002 ms): a.out/447296 capget(header: 1448669184, dataptr: 4096)                             = 0
     0.208 ( 0.002 ms): a.out/447296 capget(header: 4160577536, dataptr: 8192)                             = 0
     0.220 ( 0.001 ms): a.out/447296 getxattr(pathname: "", name: "c??????", value: 0xf7f77e34, size: 1)  = 0
     0.228 ( 0.005 ms): a.out/447296 fchmod(fd: -134729728, mode: IRUGO|IWUGO|IFREG|IFIFO|ISVTX|IXUSR|0x10000) = 0
     0.240 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: 0x5658e008, pos_h: 4160192052)            = 3
     0.250 ( 0.008 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 1436
     0.260 ( 0.018 ms): a.out/447296 stat(filename: "", statbuf: 0xffce32ac)                               = 1436
     0.288 (1000.213 ms): a.out/447296 readlinkat(buf: 0xffce31d4, bufsiz: 4291703244)                       = 0
```

After:
```
         ? (         ): a.out/442930  ... [continued]: execve())                                           = 0
     0.023 ( 0.002 ms): a.out/442930 brk()                                                                 = 0x57760000
     0.052 ( 0.003 ms): a.out/442930 access(filename: 0xf7f5af28, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.059 ( 0.009 ms): a.out/442930 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.078 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.087 ( 0.007 ms): a.out/442930 openat(dfd: CWD, filename: "/lib/i386-linux-", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.095 ( 0.002 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdbb70, count: 512)         = 512
     0.135 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.148 ( 0.001 ms): a.out/442930 set_tid_address(tidptr: 0xf7f2b528)                                   = 442930 (a.out)
     0.150 ( 0.001 ms): a.out/442930 set_robust_list(head: 0xf7f2b52c, len: 12)                            =
     0.196 ( 0.004 ms): a.out/442930 mprotect(start: 0xf7f03000, len: 8192, prot: READ)                    = 0
     0.202 ( 0.002 ms): a.out/442930 mprotect(start: 0x5658e000, len: 4096, prot: READ)                    = 0
     0.207 ( 0.002 ms): a.out/442930 mprotect(start: 0xf7f63000, len: 8192, prot: READ)                    = 0
     0.230 ( 0.005 ms): a.out/442930 munmap(addr: 0xf7f10000, len: 103414)                                 = 0
     0.244 ( 0.010 ms): a.out/442930 openat(dfd: CWD, filename: 0x5658d008)                                = 3
     0.255 ( 0.007 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdb67c, count: 4096)        = 1436
     0.264 ( 0.018 ms): a.out/442930 write(fd: 1</dev/pts/4>, buf: , count: 1436)                          = 1436
     0.292 (1000.173 ms): a.out/442930 clock_nanosleep(rqtp: { .tv_sec: 17866546940376776704, .tv_nsec: 4159878336 }, rmtp: 0xffbdb59c) = 0
  1000.478 (         ): a.out/442930 exit_group()                                                          = ?
```

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/util/syscalltbl.c | 89 ++++++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 760ac4d0869f..db0d2b81aed1 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,16 +15,39 @@
 #include <string.h>
 #include "string2.h"
 
-#if __BITS_PER_LONG == 64
-  #include <asm/syscalls_64.h>
-#else
-  #include <asm/syscalls_32.h>
-#endif
+#include "trace/beauty/generated/syscalltbl.c"
 
-const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+static const struct syscalltbl *find_table(int e_machine)
 {
-	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
-		return syscall_num_to_name[id];
+	static const struct syscalltbl *last_table;
+	static int last_table_machine = EM_NONE;
+
+	/* Tables only exist for EM_SPARC. */
+	if (e_machine == EM_SPARCV9)
+		e_machine = EM_SPARC;
+
+	if (last_table_machine == e_machine && last_table != NULL)
+		return last_table;
+
+	for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) {
+		const struct syscalltbl *entry = &syscalltbls[i];
+
+		if (entry->e_machine != e_machine && entry->e_machine != EM_NONE)
+			continue;
+
+		last_table = entry;
+		last_table_machine = e_machine;
+		return entry;
+	}
+	return NULL;
+}
+
+const char *syscalltbl__name(int e_machine, int id)
+{
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (table && id >= 0 && id < table->num_to_name_len)
+		return table->num_to_name[id];
 	return NULL;
 }
 
@@ -41,38 +64,54 @@ static int syscallcmpname(const void *vkey, const void *ventry)
 	return strcmp(key->name, key->tbl[*entry]);
 }
 
-int syscalltbl__id(int e_machine __maybe_unused, const char *name)
+int syscalltbl__id(int e_machine, const char *name)
 {
-	struct syscall_cmp_key key = {
-		.name = name,
-		.tbl = syscall_num_to_name,
-	};
-	const int *id = bsearch(&key, syscall_sorted_names,
-				ARRAY_SIZE(syscall_sorted_names),
-				sizeof(syscall_sorted_names[0]),
-				syscallcmpname);
+	const struct syscalltbl *table = find_table(e_machine);
+	struct syscall_cmp_key key;
+	const int *id;
+
+	if (!table)
+		return -1;
+
+	key.name = name;
+	key.tbl = table->num_to_name;
+	id = bsearch(&key, table->sorted_names, table->sorted_names_len,
+		     sizeof(table->sorted_names[0]), syscallcmpname);
 
 	return id ? *id : -1;
 }
 
-int syscalltbl__num_idx(int e_machine __maybe_unused)
+int syscalltbl__num_idx(int e_machine)
 {
-	return ARRAY_SIZE(syscall_sorted_names);
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return 0;
+
+	return table->sorted_names_len;
 }
 
-int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
+int syscalltbl__id_at_idx(int e_machine, int idx)
 {
-	return syscall_sorted_names[idx];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return -1;
+
+	assert(idx >= 0 && idx < table->sorted_names_len);
+	return table->sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx)
 {
-	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
-		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) {
+		const char *name = table->num_to_name[table->sorted_names[i]];
 
 		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscall_sorted_names[i];
+			return table->sorted_names[i];
 		}
 	}
 
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:08 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:08 -0800
Subject: [PATCH v5 10/11] perf build: Remove Makefile.syscalls
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-11-irogers@google.com>

Now a single beauty file is generated and used by all architectures,
remove the per-architecture Makefiles, Kbuild files and previous
generator script.

Note: there was conversation with Charlie Jenkins
<charlie at rivosinc.com> and they'd written an alternate approach to
support multiple architectures:
https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
It would have been better to have helped Charlie fix their series (my
apologies) but they agreed that the approach taken here was likely
best for longer term maintainability:
https://lore.kernel.org/lkml/Z6Jk_UN9i69QGqUj at ghost/

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf                      |  1 -
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |  2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/arc/entry/syscalls/Kbuild     |  2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |  3 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |  4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |  2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |  3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |  6 --
 tools/perf/arch/csky/entry/syscalls/Kbuild    |  2 -
 .../csky/entry/syscalls/Makefile.syscalls     |  3 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |  2 -
 .../entry/syscalls/Makefile.syscalls          |  3 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |  2 -
 .../mips/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |  3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |  6 --
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |  3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |  6 --
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |  2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |  4 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |  2 -
 .../s390/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/sh/entry/syscalls/Kbuild      |  2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |  4 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |  3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/x86/entry/syscalls/Kbuild     |  3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |  6 --
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |  2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |  4 -
 tools/perf/scripts/Makefile.syscalls          | 61 ---------------
 tools/perf/scripts/syscalltbl.sh              | 76 -------------------
 33 files changed, 242 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index f949ec72f3d2..f3cd8de15d1a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -339,7 +339,6 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
 FEATURE_TESTS := all
 endif
 endif
-include $(srctree)/tools/perf/scripts/Makefile.syscalls
 include Makefile.config
 endif
 
diff --git a/tools/perf/arch/alpha/entry/syscalls/Kbuild b/tools/perf/arch/alpha/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls b/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 690168aac34d..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/alpha/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arc/entry/syscalls/Kbuild b/tools/perf/arch/arc/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 391d30ab7a83..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += arc time32 renameat stat64 rlimit
diff --git a/tools/perf/arch/arm/entry/syscalls/Kbuild b/tools/perf/arch/arm/entry/syscalls/Kbuild
deleted file mode 100644
index 9d777540f089..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += oabi
-syscalltbl = $(srctree)/tools/perf/arch/arm/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Kbuild b/tools/perf/arch/arm64/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e7e78c2d1c02..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/arm64/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/csky/entry/syscalls/Kbuild b/tools/perf/arch/csky/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls b/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ea2dd10d0571..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += csky time32 stat64 rlimit
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Kbuild b/tools/perf/arch/loongarch/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls b/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 47d32da2aed8..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 +=
diff --git a/tools/perf/arch/mips/entry/syscalls/Kbuild b/tools/perf/arch/mips/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls b/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9ee914bdfb05..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += n64
-
-syscalltbl = $(srctree)/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
diff --git a/tools/perf/arch/parisc/entry/syscalls/Kbuild b/tools/perf/arch/parisc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ae326fecb83b..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/parisc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Kbuild b/tools/perf/arch/powerpc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e35afbc57c79..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += nospu
-syscall_abis_64 += nospu
-
-syscalltbl = $(srctree)/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/riscv/entry/syscalls/Kbuild b/tools/perf/arch/riscv/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls b/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9668fd1faf60..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += riscv memfd_secret
-syscall_abis_64 += riscv rlimit memfd_secret
diff --git a/tools/perf/arch/s390/entry/syscalls/Kbuild b/tools/perf/arch/s390/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls b/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9762d7abf17c..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/s390/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sh/entry/syscalls/Kbuild b/tools/perf/arch/sh/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 25080390e4ed..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscalltbl = $(srctree)/tools/perf/arch/sh/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sparc/entry/syscalls/Kbuild b/tools/perf/arch/sparc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 212c1800b644..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-syscalltbl = $(srctree)/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/x86/entry/syscalls/Kbuild b/tools/perf/arch/x86/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls b/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index db3d5d6d4e56..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += i386
-syscall_abis_64 +=
-
-syscalltbl = $(srctree)/tools/perf/arch/x86/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Kbuild b/tools/perf/arch/xtensa/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls b/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index d4aa2358460c..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscalltbl = $(srctree)/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
diff --git a/tools/perf/scripts/Makefile.syscalls b/tools/perf/scripts/Makefile.syscalls
deleted file mode 100644
index 8bf55333262e..000000000000
--- a/tools/perf/scripts/Makefile.syscalls
+++ /dev/null
@@ -1,61 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# This Makefile generates headers in
-# tools/perf/arch/$(SRCARCH)/include/generated/asm from the architecture's
-# syscall table. This will either be from the generic syscall table, or from a
-# table that is specific to that architecture.
-
-PHONY := all
-all:
-
-obj := $(OUTPUT)arch/$(SRCARCH)/include/generated/asm
-
-syscall_abis_32  := common,32
-syscall_abis_64  := common,64
-syscalltbl := $(srctree)/tools/scripts/syscall.tbl
-
-# let architectures override $(syscall_abis_%) and $(syscalltbl)
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Makefile.syscalls
-include $(srctree)/tools/build/Build.include
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Kbuild
-
-systbl := $(srctree)/tools/perf/scripts/syscalltbl.sh
-
-syscall-y   := $(addprefix $(obj)/, $(syscall-y))
-
-# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
-unwanted    := $(filter-out $(syscall-y),$(old-headers))
-
-quiet_cmd_remove = REMOVE  $(unwanted)
-      cmd_remove = rm -f $(unwanted)
-
-quiet_cmd_systbl = SYSTBL  $@
-      cmd_systbl = $(CONFIG_SHELL) $(systbl) \
-		   $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \
-		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
-		   $< $@
-
-all: $(syscall-y)
-	$(if $(unwanted),$(call cmd,remove))
-	@:
-
-$(obj)/syscalls_%.h: $(syscalltbl) $(systbl) FORCE
-	$(call if_changed,systbl)
-
-targets := $(syscall-y)
-
-# Create output directory. Skip it if at least one old header exists
-# since we know the output directory already exists.
-ifeq ($(old-headers),)
-$(shell mkdir -p $(obj))
-endif
-
-PHONY += FORCE
-
-FORCE:
-
-existing-targets := $(wildcard $(sort $(targets)))
-
--include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-
-.PHONY: $(PHONY)
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
deleted file mode 100755
index a39b3013b103..000000000000
--- a/tools/perf/scripts/syscalltbl.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Generate a syscall table header.
-#
-# Each line of the syscall table should have the following format:
-#
-# NR ABI NAME [NATIVE] [COMPAT]
-#
-# NR       syscall number
-# ABI      ABI name
-# NAME     syscall name
-# NATIVE   native entry point (optional)
-# COMPAT   compat entry point (optional)
-
-set -e
-
-usage() {
-	echo >&2 "usage: $0 [--abis ABIS] INFILE OUTFILE" >&2
-	echo >&2
-	echo >&2 "  INFILE    input syscall table"
-	echo >&2 "  OUTFILE   output header file"
-	echo >&2
-	echo >&2 "options:"
-	echo >&2 "  --abis ABIS        ABI(s) to handle (By default, all lines are handled)"
-	exit 1
-}
-
-# default unless specified by options
-abis=
-
-while [ $# -gt 0 ]
-do
-	case $1 in
-	--abis)
-		abis=$(echo "($2)" | tr ',' '|')
-		shift 2;;
-	-*)
-		echo "$1: unknown option" >&2
-		usage;;
-	*)
-		break;;
-	esac
-done
-
-if [ $# -ne 2 ]; then
-	usage
-fi
-
-infile="$1"
-outfile="$2"
-
-sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
-
-echo "static const char *const syscall_num_to_name[] = {" > $outfile
-# the params are: nr abi name entry compat
-# use _ for intentionally unused variables according to SC2034
-while read nr _ name _ _; do
-	echo "	[$nr] = \"$name\"," >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
-
-# When sorting by name, add a suffix of 0s upto 20 characters so that system
-# calls that differ with a numerical suffix don't sort before those
-# without. This default behavior of sort differs from that of strcmp used at
-# runtime. Use sed to strip the trailing 0s suffix afterwards.
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
-while read name nr; do
-	echo "	$nr,	/* $name */" >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-rm -f $sorted_table
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:32:09 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:32:09 -0800
Subject: [PATCH v5 11/11] perf syscalltbl: Mask off ABI type for MIPS system calls
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-12-irogers@google.com>

Arnd Bergmann described that MIPS system calls don't necessarily start
from 0 as an ABI prefix is applied:
https://lore.kernel.org/lkml/8ed7dfb2-1e4d-4aa4-a04b-0397a89365d1 at app.fastmail.com/
When decoding the "id" (aka system call number) for MIPS ignore values
greater-than 1000.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/syscalltbl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index db0d2b81aed1..ace66e69c1bc 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -46,6 +46,14 @@ const char *syscalltbl__name(int e_machine, int id)
 {
 	const struct syscalltbl *table = find_table(e_machine);
 
+	if (e_machine == EM_MIPS && id > 1000) {
+		/*
+		 * MIPS may encode the N32/64/O32 type in the high part of
+		 * syscall number. Mask this off if present. See the values of
+		 * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux.
+		 */
+		id = id % 1000;
+	}
 	if (table && id >= 0 && id < table->num_to_name_len)
 		return table->num_to_name[id];
 	return NULL;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:31:58 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:31:58 -0800
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in the build
Message-ID: <20250308003209.234114-1-irogers@google.com>

This work builds on the clean up of system call tables and removal of
libaudit by Charlie Jenkins <charlie at rivosinc.com>.

The system call table in perf trace is used to map system call numbers
to names and vice versa. Prior to these changes, a single table
matching the perf binary's build was present. The table would be
incorrect if tracing say a 32-bit binary from a 64-bit version of
perf, the names and numbers wouldn't match.

Change the build so that a single system call file is built and the
potentially multiple tables are identifiable from the ELF machine type
of the process being examined. To determine the ELF machine type, the
executable's maps are searched and the associated DSOs ELF headers are
read. When this fails and when live, /proc/pid/exe's ELF header is
read. Fallback to using the perf's binary type when unknown.

Remove some runtime types used by the system call tables and make
equivalents generated at build time.

v5: Add byte swap to dso__e_machine and fix comment as suggested by
    Namhyung.

v4: Add reading the e_machine from the thread's maps dsos, only read
    from /proc/pid/exe on failure and when live as requested by
    Namhyung. Add patches to add dso comments and remove unused
    dso_data variables that are unused without libunwind.

v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
    Bergmann <arnd at arndb.de> on additional optional column and MIPS
    system call numbering. Rebase past Namhyung's global system call
    statistics and add comments that they don't yet support an
    e_machine other than EM_HOST.

v2: Change the 1 element cache for the last table as suggested by
    Howard Chu, add Howard's reviewed-by tags.
    Add a comment and apology to Charlie for not doing better in
    guiding:
    https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
    After discussion on v1 and he agreed this patch series would be
    the better direction.

Ian Rogers (11):
  perf dso: Move libunwind dso_data variables into ifdef
  perf dso: kernel-doc for enum dso_binary_type
  perf syscalltbl: Remove syscall_table.h
  perf trace: Reorganize syscalls
  perf syscalltbl: Remove struct syscalltbl
  perf dso: Add support for reading the e_machine type for a dso
  perf thread: Add support for reading the e_machine type for a thread
  perf trace beauty: Add syscalltbl.sh generating all system call tables
  perf syscalltbl: Use lookup table containing multiple architectures
  perf build: Remove Makefile.syscalls
  perf syscalltbl: Mask off ABI type for MIPS system calls

 tools/perf/Makefile.perf                      |  10 +-
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/alpha/include/syscall_table.h |   2 -
 tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
 tools/perf/arch/arc/include/syscall_table.h   |   2 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
 tools/perf/arch/arm/include/syscall_table.h   |   2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
 tools/perf/arch/arm64/include/syscall_table.h |   8 -
 tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
 .../csky/entry/syscalls/Makefile.syscalls     |   3 -
 tools/perf/arch/csky/include/syscall_table.h  |   2 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
 .../entry/syscalls/Makefile.syscalls          |   3 -
 .../arch/loongarch/include/syscall_table.h    |   2 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
 .../mips/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/mips/include/syscall_table.h  |   2 -
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
 .../perf/arch/parisc/include/syscall_table.h  |   8 -
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
 .../perf/arch/powerpc/include/syscall_table.h |   8 -
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
 tools/perf/arch/riscv/include/syscall_table.h |   8 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
 .../s390/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/s390/include/syscall_table.h  |   2 -
 tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
 tools/perf/arch/sh/include/syscall_table.h    |   2 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/sparc/include/syscall_table.h |   8 -
 tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
 tools/perf/arch/x86/include/syscall_table.h   |   8 -
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
 .../perf/arch/xtensa/include/syscall_table.h  |   2 -
 tools/perf/builtin-trace.c                    | 290 +++++++++++-------
 tools/perf/scripts/Makefile.syscalls          |  61 ----
 tools/perf/scripts/syscalltbl.sh              |  86 ------
 tools/perf/trace/beauty/syscalltbl.sh         | 274 +++++++++++++++++
 tools/perf/util/dso.c                         |  88 ++++++
 tools/perf/util/dso.h                         |  58 ++++
 tools/perf/util/symbol-elf.c                  |  27 --
 tools/perf/util/syscalltbl.c                  | 148 ++++-----
 tools/perf/util/syscalltbl.h                  |  22 +-
 tools/perf/util/thread.c                      |  80 +++++
 tools/perf/util/thread.h                      |  14 +-
 57 files changed, 792 insertions(+), 536 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From irogers at google.com  Fri Mar  7 16:31:59 2025
From: irogers at google.com (Ian Rogers)
Date: Fri,  7 Mar 2025 16:31:59 -0800
Subject: [PATCH v5 01/11] perf dso: Move libunwind dso_data variables into ifdef
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <20250308003209.234114-2-irogers@google.com>

The variables elf_base_addr, debug_frame_offset, eh_frame_hdr_addr and
eh_frame_hdr_offset are only accessed in unwind-libunwind-local.c
which is conditionally built on having libunwind support. Make the
variables conditional on libunwind support too.

Reviewed-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb8e8f444054..dfd763a0bd9d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -154,10 +154,12 @@ struct dso_data {
 	int		 status;
 	u32		 status_seen;
 	u64		 file_size;
+#ifdef HAVE_LIBUNWIND_SUPPORT
 	u64		 elf_base_addr;
 	u64		 debug_frame_offset;
 	u64		 eh_frame_hdr_addr;
 	u64		 eh_frame_hdr_offset;
+#endif
 };
 
 struct dso_bpf_prog {
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From sebastian.reichel at collabora.com  Fri Mar  7 16:38:16 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Sat, 08 Mar 2025 01:38:16 +0100
Subject: (subset) [PATCH v3 00/21] Enable Power Modes Support for
 SAMA7D65 SoC
In-Reply-To: <cover.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <174139429652.169744.15334502728005076193.b4-ty@collabora.com>


On Thu, 27 Feb 2025 08:51:47 -0700, Ryan.Wanner at microchip.com wrote:
> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> This patch set adds support for low power modes for the SAMA7D65 SoC and
> the required components and changes for low power modes.
> 
> The series includes changes in the asm code to account for the addtional
> clocks that are in this SoC.
> 
> [...]

Applied, thanks!

[13/21] power: reset: at91-sama5d2_shdwc: Add sama7d65 PMC
        commit: 2fc78cd0a3c3013543e5f540eff61e9696138f83

Best regards,
-- 
Sebastian Reichel <sebastian.reichel at collabora.com>



From song at kernel.org  Fri Mar  7 17:27:40 2025
From: song at kernel.org (Song Liu)
Date: Fri,  7 Mar 2025 17:27:40 -0800
Subject: [PATCH 0/2] arm64: livepatch: Enable livepatch without sframe
Message-ID: <20250308012742.3208215-1-song@kernel.org>

There are recent efforts to enable livepatch for arm64, with sframe [1] or
without sframe [2]. This set tries to enable livepatch without sframe. Some
of the code, however, are from [1].

Although the sframe implementation is more promising in longer term, it
suffers from the following issues:

  1. sframe is not yet supported in llvm;
  2. There is still bug in binutil [3], so that we cannot yet use sframe
     with gcc;
  3. sframe unwinder hasn't been fully verified in the kernel.

On the other hand, arm64 processors have become more and more important in
the data center world. Therefore, it is getting critical to support
livepatching of arm64 kernels.

With recent change in arm64 unwinder [4], it is possible to reliably
livepatch arm64 kernels without sframe. This is because we do not need
arch_stack_walk_reliable() to get reliable stack trace in all scenarios.
Instead, we only need arch_stack_walk_reliable() to detect when the
stack trace is not reliable, then the livepatch logic can retry the patch
transition at a later time.

Given the increasing need of livepatching, and relatively long time before
sframe is fully ready (for both gcc and clang), we would like to enable
livepatch without sframe.

Thanks!

[1] https://lore.kernel.org/live-patching/20250127213310.2496133-1-wnliu at google.com/
[2] https://lore.kernel.org/live-patching/20250129232936.1795412-1-song at kernel.org/
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=32589
[4] https://lore.kernel.org/linux-arm-kernel/20241017092538.1859841-1-mark.rutland at arm.com/

Song Liu (2):
  arm64: Implement arch_stack_walk_reliable
  arm64: Implement HAVE_LIVEPATCH

 arch/arm64/Kconfig                         |  3 ++
 arch/arm64/include/asm/stacktrace/common.h |  1 +
 arch/arm64/include/asm/thread_info.h       |  4 +-
 arch/arm64/kernel/entry-common.c           |  4 ++
 arch/arm64/kernel/stacktrace.c             | 44 +++++++++++++++++++++-
 5 files changed, 54 insertions(+), 2 deletions(-)

--
2.43.5


From song at kernel.org  Fri Mar  7 17:27:41 2025
From: song at kernel.org (Song Liu)
Date: Fri,  7 Mar 2025 17:27:41 -0800
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250308012742.3208215-1-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org>
Message-ID: <20250308012742.3208215-2-song@kernel.org>

With proper exception boundary detection, it is possible to implment
arch_stack_walk_reliable without sframe.

Note that, arch_stack_walk_reliable does not guarantee getting reliable
stack in all scenarios. Instead, it can reliably detect when the stack
trace is not reliable, which is enough to provide reliable livepatching.

This version has been inspired by Weinan Liu's patch [1].

[1] https://lore.kernel.org/live-patching/20250127213310.2496133-7-wnliu at google.com/
Signed-off-by: Song Liu <song at kernel.org>
---
 arch/arm64/Kconfig                         |  2 +-
 arch/arm64/include/asm/stacktrace/common.h |  1 +
 arch/arm64/kernel/stacktrace.c             | 44 +++++++++++++++++++++-
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..ed4f7bf4a879 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -275,6 +275,7 @@ config ARM64
 	select HAVE_SOFTIRQ_ON_OWN_STACK
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
+	select HAVE_RELIABLE_STACKTRACE
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2499,4 +2500,3 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
-
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 821a8fdd31af..072469fd91b7 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -33,6 +33,7 @@ struct unwind_state {
 	struct stack_info stack;
 	struct stack_info *stacks;
 	int nr_stacks;
+	bool unreliable;
 };
 
 static inline struct stack_info stackinfo_get_unknown(void)
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 1d9d51d7627f..69d0567a0c38 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -230,8 +230,14 @@ kunwind_next_frame_record(struct kunwind_state *state)
 	new_fp = READ_ONCE(record->fp);
 	new_pc = READ_ONCE(record->lr);
 
-	if (!new_fp && !new_pc)
+	if (!new_fp && !new_pc) {
+		/*
+		 * Searching across exception boundaries. The stack is now
+		 * unreliable.
+		 */
+		state->common.unreliable = true;
 		return kunwind_next_frame_record_meta(state);
+	}
 
 	unwind_consume_stack(&state->common, info, fp, sizeof(*record));
 
@@ -347,6 +353,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 		.common = {
 			.stacks = stacks,
 			.nr_stacks = ARRAY_SIZE(stacks),
+			.unreliable = false,
 		},
 	};
 
@@ -387,6 +394,41 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
 }
 
+struct kunwind_reliable_consume_entry_data {
+	stack_trace_consume_fn consume_entry;
+	void *cookie;
+	bool unreliable;
+};
+
+static __always_inline bool
+arch_kunwind_reliable_consume_entry(const struct kunwind_state *state, void *cookie)
+{
+	struct kunwind_reliable_consume_entry_data *data = cookie;
+
+	if (state->common.unreliable) {
+		data->unreliable = true;
+		return false;
+	}
+	return data->consume_entry(data->cookie, state->common.pc);
+}
+
+noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
+			void *cookie, struct task_struct *task)
+{
+	struct kunwind_reliable_consume_entry_data data = {
+		.consume_entry = consume_entry,
+		.cookie = cookie,
+		.unreliable = false,
+	};
+
+	kunwind_stack_walk(arch_kunwind_reliable_consume_entry, &data, task, NULL);
+
+	if (data.unreliable)
+		return -EINVAL;
+
+	return 0;
+}
+
 struct bpf_unwind_consume_entry_data {
 	bool (*consume_entry)(void *cookie, u64 ip, u64 sp, u64 fp);
 	void *cookie;
-- 
2.43.5



From song at kernel.org  Fri Mar  7 17:27:42 2025
From: song at kernel.org (Song Liu)
Date: Fri,  7 Mar 2025 17:27:42 -0800
Subject: [PATCH 2/2] arm64: Implement HAVE_LIVEPATCH
In-Reply-To: <20250308012742.3208215-1-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org>
Message-ID: <20250308012742.3208215-3-song@kernel.org>

This is largely based on [1] by Suraj Jitindar Singh.

Test coverage:

- Passed manual tests with samples/livepatch.
- Passed all but test-kprobe.sh in selftests/livepatch.
  test-kprobe.sh is expected to fail, because arm64 doesn't have
  KPROBES_ON_FTRACE.
- Passed tests with kpatch-build [2]. (This version includes commits that
  are not merged to upstream kpatch yet).

[1] https://lore.kernel.org/all/20210604235930.603-1-surajjs at amazon.com/
[2] https://github.com/liu-song-6/kpatch/tree/fb-6.13
Cc: Suraj Jitindar Singh <surajjs at amazon.com>
Cc: Torsten Duwe <duwe at suse.de>
Signed-off-by: Song Liu <song at kernel.org>
---
 arch/arm64/Kconfig                   | 3 +++
 arch/arm64/include/asm/thread_info.h | 4 +++-
 arch/arm64/kernel/entry-common.c     | 4 ++++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index ed4f7bf4a879..bc9edba6171a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -276,6 +276,7 @@ config ARM64
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
 	select HAVE_RELIABLE_STACKTRACE
+	select HAVE_LIVEPATCH
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2500,3 +2501,5 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
+
+source "kernel/livepatch/Kconfig"
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 1114c1c3300a..4ac42e13032b 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -64,6 +64,7 @@ void arch_setup_new_exec(void);
 #define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
 #define TIF_MTE_ASYNC_FAULT	5	/* MTE Asynchronous Tag Check Fault */
 #define TIF_NOTIFY_SIGNAL	6	/* signal notifications exist */
+#define TIF_PATCH_PENDING	7	/* pending live patching update */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing */
 #define TIF_SYSCALL_TRACEPOINT	10	/* syscall tracepoint for ftrace */
@@ -92,6 +93,7 @@ void arch_setup_new_exec(void);
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
+#define _TIF_PATCH_PENDING	(1 << TIF_PATCH_PENDING)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
@@ -103,7 +105,7 @@ void arch_setup_new_exec(void);
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
 				 _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
-				 _TIF_NOTIFY_SIGNAL)
+				 _TIF_NOTIFY_SIGNAL | _TIF_PATCH_PENDING)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index b260ddc4d3e9..b537af333b42 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -8,6 +8,7 @@
 #include <linux/context_tracking.h>
 #include <linux/kasan.h>
 #include <linux/linkage.h>
+#include <linux/livepatch.h>
 #include <linux/lockdep.h>
 #include <linux/ptrace.h>
 #include <linux/resume_user_mode.h>
@@ -144,6 +145,9 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 				       (void __user *)NULL, current);
 		}
 
+		if (thread_flags & _TIF_PATCH_PENDING)
+			klp_update_patch_state(current);
+
 		if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
 			do_signal(regs);
 
-- 
2.43.5



From lumag at kernel.org  Fri Mar  7 17:42:26 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:26 +0200
Subject: [PATCH 08/10] drm/msm/dpu: add catalog entry for SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-8-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add DPU driver support for the Qualcomm SAR2130P platform. It is mostly
the same as SM8550, minor differences in the CDP configuration.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 .../drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h   | 434 +++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c     |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h     |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c            |   1 +
 4 files changed, 437 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
new file mode 100644
index 0000000000000000000000000000000000000000..22dd16c6e210e9520ecb7a851bee402032fa1ee2
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_9_1_SAR2130P_H
+#define _DPU_9_1_SAR2130P_H
+
+static const struct dpu_caps sar2130p_dpu_caps = {
+	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+	.max_mixer_blendstages = 0xb,
+	.has_src_split = true,
+	.has_dim_layer = true,
+	.has_idle_pc = true,
+	.has_3d_merge = true,
+	.max_linewidth = 5120,
+	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg sar2130p_mdp = {
+	.name = "top_0",
+	.base = 0, .len = 0x494,
+	.features = BIT(DPU_MDP_PERIPH_0_REMOVED),
+	.clk_ctrls = {
+		[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+	},
+};
+
+/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */
+static const struct dpu_ctl_cfg sar2130p_ctl[] = {
+	{
+		.name = "ctl_0", .id = CTL_0,
+		.base = 0x15000, .len = 0x290,
+		.features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+	}, {
+		.name = "ctl_1", .id = CTL_1,
+		.base = 0x16000, .len = 0x290,
+		.features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+	}, {
+		.name = "ctl_2", .id = CTL_2,
+		.base = 0x17000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+	}, {
+		.name = "ctl_3", .id = CTL_3,
+		.base = 0x18000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+	}, {
+		.name = "ctl_4", .id = CTL_4,
+		.base = 0x19000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+	}, {
+		.name = "ctl_5", .id = CTL_5,
+		.base = 0x1a000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+	},
+};
+
+static const struct dpu_sspp_cfg sar2130p_sspp[] = {
+	{
+		.name = "sspp_0", .id = SSPP_VIG0,
+		.base = 0x4000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 0,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_1", .id = SSPP_VIG1,
+		.base = 0x6000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 4,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_2", .id = SSPP_VIG2,
+		.base = 0x8000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 8,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_3", .id = SSPP_VIG3,
+		.base = 0xa000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 12,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_8", .id = SSPP_DMA0,
+		.base = 0x24000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 1,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_9", .id = SSPP_DMA1,
+		.base = 0x26000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 5,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_10", .id = SSPP_DMA2,
+		.base = 0x28000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 9,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_11", .id = SSPP_DMA3,
+		.base = 0x2a000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 13,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_12", .id = SSPP_DMA4,
+		.base = 0x2c000, .len = 0x344,
+		.features = DMA_CURSOR_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 14,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_13", .id = SSPP_DMA5,
+		.base = 0x2e000, .len = 0x344,
+		.features = DMA_CURSOR_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 15,
+		.type = SSPP_TYPE_DMA,
+	},
+};
+
+static const struct dpu_lm_cfg sar2130p_lm[] = {
+	{
+		.name = "lm_0", .id = LM_0,
+		.base = 0x44000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_1,
+		.pingpong = PINGPONG_0,
+		.dspp = DSPP_0,
+	}, {
+		.name = "lm_1", .id = LM_1,
+		.base = 0x45000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_0,
+		.pingpong = PINGPONG_1,
+		.dspp = DSPP_1,
+	}, {
+		.name = "lm_2", .id = LM_2,
+		.base = 0x46000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_3,
+		.pingpong = PINGPONG_2,
+		.dspp = DSPP_2,
+	}, {
+		.name = "lm_3", .id = LM_3,
+		.base = 0x47000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_2,
+		.pingpong = PINGPONG_3,
+		.dspp = DSPP_3,
+	}, {
+		.name = "lm_4", .id = LM_4,
+		.base = 0x48000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_5,
+		.pingpong = PINGPONG_4,
+	}, {
+		.name = "lm_5", .id = LM_5,
+		.base = 0x49000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_4,
+		.pingpong = PINGPONG_5,
+	},
+};
+
+static const struct dpu_dspp_cfg sar2130p_dspp[] = {
+	{
+		.name = "dspp_0", .id = DSPP_0,
+		.base = 0x54000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_1", .id = DSPP_1,
+		.base = 0x56000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_2", .id = DSPP_2,
+		.base = 0x58000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_3", .id = DSPP_3,
+		.base = 0x5a000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	},
+};
+static const struct dpu_pingpong_cfg sar2130p_pp[] = {
+	{
+		.name = "pingpong_0", .id = PINGPONG_0,
+		.base = 0x69000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_0,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+	}, {
+		.name = "pingpong_1", .id = PINGPONG_1,
+		.base = 0x6a000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_0,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+	}, {
+		.name = "pingpong_2", .id = PINGPONG_2,
+		.base = 0x6b000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_1,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+	}, {
+		.name = "pingpong_3", .id = PINGPONG_3,
+		.base = 0x6c000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_1,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+	}, {
+		.name = "pingpong_4", .id = PINGPONG_4,
+		.base = 0x6d000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_2,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
+	}, {
+		.name = "pingpong_5", .id = PINGPONG_5,
+		.base = 0x6e000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_2,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
+	}, {
+		.name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
+		.base = 0x66000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_3,
+	}, {
+		.name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
+		.base = 0x66400, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_3,
+	},
+};
+
+static const struct dpu_merge_3d_cfg sar2130p_merge_3d[] = {
+	{
+		.name = "merge_3d_0", .id = MERGE_3D_0,
+		.base = 0x4e000, .len = 0x8,
+	}, {
+		.name = "merge_3d_1", .id = MERGE_3D_1,
+		.base = 0x4f000, .len = 0x8,
+	}, {
+		.name = "merge_3d_2", .id = MERGE_3D_2,
+		.base = 0x50000, .len = 0x8,
+	}, {
+		.name = "merge_3d_3", .id = MERGE_3D_3,
+		.base = 0x66700, .len = 0x8,
+	},
+};
+
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sar2130p_dsc[] = {
+	{
+		.name = "dce_0_0", .id = DSC_0,
+		.base = 0x80000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2),
+		.sblk = &dsc_sblk_0,
+	}, {
+		.name = "dce_0_1", .id = DSC_1,
+		.base = 0x80000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2),
+		.sblk = &dsc_sblk_1,
+	}, {
+		.name = "dce_1_0", .id = DSC_2,
+		.base = 0x81000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+		.sblk = &dsc_sblk_0,
+	}, {
+		.name = "dce_1_1", .id = DSC_3,
+		.base = 0x81000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+		.sblk = &dsc_sblk_1,
+	},
+};
+
+static const struct dpu_wb_cfg sar2130p_wb[] = {
+	{
+		.name = "wb_2", .id = WB_2,
+		.base = 0x65000, .len = 0x2c8,
+		.features = WB_SM8250_MASK,
+		.format_list = wb2_formats_rgb_yuv,
+		.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
+		.xin_id = 6,
+		.vbif_idx = VBIF_RT,
+		.maxlinewidth = 4096,
+		.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
+	},
+};
+
+static const struct dpu_intf_cfg sar2130p_intf[] = {
+	{
+		.name = "intf_0", .id = INTF_0,
+		.base = 0x34000, .len = 0x280,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DP,
+		.controller_id = MSM_DP_CONTROLLER_0,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+	}, {
+		.name = "intf_1", .id = INTF_1,
+		.base = 0x35000, .len = 0x300,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DSI,
+		.controller_id = MSM_DSI_CONTROLLER_0,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+		.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2),
+	}, {
+		.name = "intf_2", .id = INTF_2,
+		.base = 0x36000, .len = 0x300,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DSI,
+		.controller_id = MSM_DSI_CONTROLLER_1,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+		.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2),
+	}, {
+		.name = "intf_3", .id = INTF_3,
+		.base = 0x37000, .len = 0x280,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DP,
+		.controller_id = MSM_DP_CONTROLLER_1,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
+	},
+};
+
+static const struct dpu_perf_cfg sar2130p_perf_data = {
+	.max_bw_low = 13600000,
+	.max_bw_high = 18200000,
+	.min_core_ib = 2500000,
+	.min_llcc_ib = 0,
+	.min_dram_ib = 800000,
+	.min_prefill_lines = 35,
+	/* FIXME: lut tables */
+	.danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0},
+	.safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
+	.qos_lut_tbl = {
+		{.nentry = ARRAY_SIZE(sc7180_qos_linear),
+		.entries = sc7180_qos_linear
+		},
+		{.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+		.entries = sc7180_qos_macrotile
+		},
+		{.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+		.entries = sc7180_qos_nrt
+		},
+		/* TODO: macrotile-qseed is different from macrotile */
+	},
+	.cdp_cfg = {
+		{.rd_enable = 0, .wr_enable = 0},
+		{.rd_enable = 0, .wr_enable = 0}
+	},
+	.clk_inefficiency_factor = 105,
+	.bw_inefficiency_factor = 120,
+};
+
+static const struct dpu_mdss_version sar2130p_mdss_ver = {
+	.core_major_ver = 9,
+	.core_minor_ver = 1,
+};
+
+const struct dpu_mdss_cfg dpu_sar2130p_cfg = {
+	.mdss_ver = &sar2130p_mdss_ver,
+	.caps = &sar2130p_dpu_caps,
+	.mdp = &sar2130p_mdp,
+	.cdm = &dpu_cdm_5_x,
+	.ctl_count = ARRAY_SIZE(sar2130p_ctl),
+	.ctl = sar2130p_ctl,
+	.sspp_count = ARRAY_SIZE(sar2130p_sspp),
+	.sspp = sar2130p_sspp,
+	.mixer_count = ARRAY_SIZE(sar2130p_lm),
+	.mixer = sar2130p_lm,
+	.dspp_count = ARRAY_SIZE(sar2130p_dspp),
+	.dspp = sar2130p_dspp,
+	.pingpong_count = ARRAY_SIZE(sar2130p_pp),
+	.pingpong = sar2130p_pp,
+	.dsc_count = ARRAY_SIZE(sar2130p_dsc),
+	.dsc = sar2130p_dsc,
+	.merge_3d_count = ARRAY_SIZE(sar2130p_merge_3d),
+	.merge_3d = sar2130p_merge_3d,
+	.wb_count = ARRAY_SIZE(sar2130p_wb),
+	.wb = sar2130p_wb,
+	.intf_count = ARRAY_SIZE(sar2130p_intf),
+	.intf = sar2130p_intf,
+	.vbif_count = ARRAY_SIZE(sm8550_vbif),
+	.vbif = sm8550_vbif,
+	.perf = &sar2130p_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 64265ca4656a04d8c5a1d9582d7124c7eb897099..ce8d88e1d8b8bc6dea893f13a0449315ac8d2841 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -759,7 +759,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
 #include "catalog/dpu_8_4_sa8775p.h"
 
 #include "catalog/dpu_9_0_sm8550.h"
-
+#include "catalog/dpu_9_1_sar2130p.h"
 #include "catalog/dpu_9_2_x1e80100.h"
 
 #include "catalog/dpu_10_0_sm8650.h"
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 4cea19e1a20380c56ae014f2d33a6884a72e0ca0..e9b627e02c8996c8fb611e8e333a35e7ce9b8373 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -841,6 +841,7 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8953_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8996_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8998_cfg;
+extern const struct dpu_mdss_cfg dpu_sar2130p_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm630_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm660_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm845_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 3305ad0623ca41882db0172e65a9beb7ebe00b6c..1fd82b6747e9058ce11dc2620729921492d5ebdd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1512,6 +1512,7 @@ static const struct of_device_id dpu_dt_match[] = {
 	{ .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, },
 	{ .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, },
 	{ .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, },
+	{ .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, },
 	{ .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, },
 	{ .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, },
 	{ .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, },

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:27 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:27 +0200
Subject: [PATCH 09/10] iommu/arm-smmu-qcom: Add SAR2130P MDSS compatible
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-9-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add the SAR2130P compatible to clients compatible list, the device
require identity domain.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 59d02687280e8d37b5e944619fcfe4ebd1bd6926..ecc4a1bc9477b766f317a58ef8b5dbcfe448afa9 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -356,6 +356,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
 	{ .compatible = "qcom,mdp4" },
 	{ .compatible = "qcom,mdss" },
 	{ .compatible = "qcom,qcm2290-mdss" },
+	{ .compatible = "qcom,sar2130p-mdss" },
 	{ .compatible = "qcom,sc7180-mdss" },
 	{ .compatible = "qcom,sc7180-mss-pil" },
 	{ .compatible = "qcom,sc7280-mdss" },

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:28 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:28 +0200
Subject: [PATCH 10/10] arm64: dts: qcom: sar2130p: add display nodes
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-10-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add display controller, two DSI hosts, two DSI PHYs and a single DP
controller. Link DP to the QMP Combo PHY.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 arch/arm64/boot/dts/qcom/sar2130p.dtsi | 394 +++++++++++++++++++++++++++++++++
 1 file changed, 394 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sar2130p.dtsi b/arch/arm64/boot/dts/qcom/sar2130p.dtsi
index dd832e6816be85817fd1ecc853f8d4c800826bc4..4e1816fcda8168e98e27b8bc0f8b5150c03276d2 100644
--- a/arch/arm64/boot/dts/qcom/sar2130p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sar2130p.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/clock/qcom,sar2130p-gcc.h>
 #include <dt-bindings/clock/qcom,sar2130p-gpucc.h>
+#include <dt-bindings/clock/qcom,sm8550-dispcc.h>
 #include <dt-bindings/clock/qcom,sm8550-tcsr.h>
 #include <dt-bindings/dma/qcom-gpi.h>
 #include <dt-bindings/interconnect/qcom,icc.h>
@@ -1854,6 +1855,7 @@ port at 2 {
 					reg = <2>;
 
 					usb_dp_qmpphy_dp_in: endpoint {
+						remote-endpoint = <&mdss_dp0_out>;
 					};
 				};
 			};
@@ -1951,6 +1953,398 @@ usb_1_dwc3_ss: endpoint {
 			};
 		};
 
+		mdss: display-subsystem at ae00000 {
+			compatible = "qcom,sar2130p-mdss";
+			reg = <0x0 0x0ae00000 0x0 0x1000>;
+			reg-names = "mdss";
+
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+
+			clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+				 <&gcc GCC_DISP_AHB_CLK>,
+				 <&gcc GCC_DISP_HF_AXI_CLK>,
+				 <&dispcc DISP_CC_MDSS_MDP_CLK>;
+
+			resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
+
+			power-domains = <&dispcc MDSS_GDSC>;
+
+			interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ACTIVE_ONLY
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>,
+					<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+					 &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+			interconnect-names = "mdp0-mem", "cpu-cfg";
+
+			iommus = <&apps_smmu 0x2000 0x402>;
+
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			status = "disabled";
+
+			mdss_mdp: display-controller at ae01000 {
+				compatible = "qcom,sar2130p-dpu";
+				reg = <0x0 0x0ae01000 0x0 0x8f000>,
+				      <0x0 0x0aeb0000 0x0 0x2008>;
+				reg-names = "mdp",
+					    "vbif";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <0>;
+
+				clocks = <&gcc GCC_DISP_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+					 <&dispcc DISP_CC_MDSS_MDP_CLK>,
+					 <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+				clock-names = "bus",
+					      "nrt_bus",
+					      "iface",
+					      "lut",
+					      "core",
+					      "vsync";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+				assigned-clock-rates = <19200000>;
+
+				operating-points-v2 = <&mdp_opp_table>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						dpu_intf1_out: endpoint {
+							remote-endpoint = <&mdss_dsi0_in>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						dpu_intf2_out: endpoint {
+							remote-endpoint = <&mdss_dsi1_in>;
+						};
+					};
+
+					port at 2 {
+						reg = <2>;
+
+						dpu_intf0_out: endpoint {
+							remote-endpoint = <&mdss_dp0_in>;
+						};
+					};
+				};
+
+				mdp_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-200000000 {
+						opp-hz = /bits/ 64 <200000000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-325000000 {
+						opp-hz = /bits/ 64 <325000000>;
+						required-opps = <&rpmhpd_opp_svs>;
+					};
+
+					opp-514000000 {
+						opp-hz = /bits/ 64 <514000000>;
+						required-opps = <&rpmhpd_opp_turbo>;
+					};
+				};
+			};
+
+			mdss_dp0: displayport-controller at ae90000 {
+				compatible = "qcom,sar2130p-dp",
+					     "qcom,sm8350-dp";
+				reg = <0x0 0xae90000 0x0 0x200>,
+				      <0x0 0xae90200 0x0 0x200>,
+				      <0x0 0xae90400 0x0 0xc00>,
+				      <0x0 0xae91000 0x0 0x400>,
+				      <0x0 0xae91400 0x0 0x400>;
+				interrupt-parent = <&mdss>;
+				interrupts = <12>;
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_AUX_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK>;
+				clock-names = "core_iface",
+					      "core_aux",
+					      "ctrl_link",
+					      "ctrl_link_iface",
+					      "stream_pixel";
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>;
+				assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+							 <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+
+				phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
+				phy-names = "dp";
+
+				#sound-dai-cells = <0>;
+
+				operating-points-v2 = <&dp_opp_table>;
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						mdss_dp0_in: endpoint {
+							remote-endpoint = <&dpu_intf0_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						mdss_dp0_out: endpoint {
+							remote-endpoint = <&usb_dp_qmpphy_dp_in>;
+						};
+					};
+				};
+
+				dp_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-162000000 {
+						opp-hz = /bits/ 64 <162000000>;
+						required-opps = <&rpmhpd_opp_low_svs_d1>;
+					};
+
+					opp-270000000 {
+						opp-hz = /bits/ 64 <270000000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-540000000 {
+						opp-hz = /bits/ 64 <540000000>;
+						required-opps = <&rpmhpd_opp_svs_l1>;
+					};
+
+					opp-810000000 {
+						opp-hz = /bits/ 64 <810000000>;
+						required-opps = <&rpmhpd_opp_nom>;
+					};
+				};
+			};
+
+			mdss_dsi0: dsi at ae94000 {
+				compatible = "qcom,sar2130p-dsi-ctrl",
+					     "qcom,mdss-dsi-ctrl";
+				reg = <0x0 0x0ae94000 0x0 0x400>;
+				reg-names = "dsi_ctrl";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <4>;
+
+				clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+					 <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+					 <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>;
+				clock-names = "byte",
+					      "byte_intf",
+					      "pixel",
+					      "core",
+					      "iface",
+					      "bus";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+				assigned-clock-parents = <&mdss_dsi0_phy 0>,
+							 <&mdss_dsi0_phy 1>;
+
+				operating-points-v2 = <&mdss_dsi_opp_table>;
+
+				phys = <&mdss_dsi0_phy>;
+				phy-names = "dsi";
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+						mdss_dsi0_in: endpoint {
+							remote-endpoint = <&dpu_intf1_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+						mdss_dsi0_out: endpoint {
+						};
+					};
+				};
+
+				mdss_dsi_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-187500000 {
+						opp-hz = /bits/ 64 <187500000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-300000000 {
+						opp-hz = /bits/ 64 <300000000>;
+						required-opps = <&rpmhpd_opp_svs>;
+					};
+
+					opp-358000000 {
+						opp-hz = /bits/ 64 <358000000>;
+						required-opps = <&rpmhpd_opp_nom>;
+					};
+				};
+			};
+
+			mdss_dsi0_phy: phy at ae95000 {
+				compatible = "qcom,sar2130p-dsi-phy-5nm";
+				reg = <0x0 0x0ae95000 0x0 0x200>,
+				      <0x0 0x0ae95200 0x0 0x280>,
+				      <0x0 0x0ae95500 0x0 0x400>;
+				reg-names = "dsi_phy",
+					    "dsi_phy_lane",
+					    "dsi_pll";
+
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&rpmhcc RPMH_CXO_CLK>;
+				clock-names = "iface", "ref";
+
+				#clock-cells = <1>;
+				#phy-cells = <0>;
+
+				status = "disabled";
+			};
+
+			mdss_dsi1: dsi at ae96000 {
+				compatible = "qcom,sar2130p-dsi-ctrl",
+					     "qcom,mdss-dsi-ctrl";
+				reg = <0x0 0x0ae96000 0x0 0x400>;
+				reg-names = "dsi_ctrl";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <5>;
+
+				clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
+					 <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_PCLK1_CLK>,
+					 <&dispcc DISP_CC_MDSS_ESC1_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>;
+				clock-names = "byte",
+					      "byte_intf",
+					      "pixel",
+					      "core",
+					      "iface",
+					      "bus";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+				assigned-clock-parents = <&mdss_dsi1_phy 0>,
+							 <&mdss_dsi1_phy 1>;
+
+				operating-points-v2 = <&mdss_dsi_opp_table>;
+
+				phys = <&mdss_dsi1_phy>;
+				phy-names = "dsi";
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+						mdss_dsi1_in: endpoint {
+							remote-endpoint = <&dpu_intf2_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+						mdss_dsi1_out: endpoint {
+						};
+					};
+				};
+			};
+
+			mdss_dsi1_phy: phy at ae97000 {
+				compatible = "qcom,sar2130p-dsi-phy-5nm";
+				reg = <0x0 0x0ae97000 0x0 0x200>,
+				      <0x0 0x0ae97200 0x0 0x280>,
+				      <0x0 0x0ae97500 0x0 0x400>;
+				reg-names = "dsi_phy",
+					    "dsi_phy_lane",
+					    "dsi_pll";
+
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&rpmhcc RPMH_CXO_CLK>;
+				clock-names = "iface", "ref";
+
+				#clock-cells = <1>;
+				#phy-cells = <0>;
+
+				status = "disabled";
+			};
+		};
+
+		dispcc: clock-controller at af00000 {
+			compatible = "qcom,sar2130p-dispcc";
+			reg = <0x0 0x0af00000 0x0 0x20000>;
+			clocks = <&rpmhcc RPMH_CXO_CLK>,
+				 <&rpmhcc RPMH_CXO_CLK_A>,
+				 <&gcc GCC_DISP_AHB_CLK>,
+				 <&sleep_clk>,
+				 <&mdss_dsi0_phy 0>,
+				 <&mdss_dsi0_phy 1>,
+				 <&mdss_dsi1_phy 0>,
+				 <&mdss_dsi1_phy 1>,
+				 <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+				 <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
+				 <0>, /* dp1 */
+				 <0>,
+				 <0>, /* dp2 */
+				 <0>,
+				 <0>, /* dp3 */
+				 <0>;
+			power-domains = <&rpmhpd RPMHPD_MMCX>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#power-domain-cells = <1>;
+		};
+
 		pdc: interrupt-controller at b220000 {
 			compatible = "qcom,sar2130p-pdc", "qcom,pdc";
 			reg = <0x0 0x0b220000 0x0 0x30000>, <0x0 0x174000f0 0x0 0x64>;

-- 
2.39.5



From lkp at intel.com  Fri Mar  7 17:53:05 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 8 Mar 2025 09:53:05 +0800
Subject: [v3 PATCH 4/6] arm64: mm: support large block mapping when
 rodata=full
In-Reply-To: <20250304222018.615808-5-yang@os.amperecomputing.com>
References: <20250304222018.615808-5-yang@os.amperecomputing.com>
Message-ID: <202503080930.7ZetfmFz-lkp@intel.com>

Hi Yang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on linus/master v6.14-rc5 next-20250307]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yang-Shi/arm64-Add-BBM-Level-2-cpu-feature/20250305-062252
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20250304222018.615808-5-yang%40os.amperecomputing.com
patch subject: [v3 PATCH 4/6] arm64: mm: support large block mapping when rodata=full
config: arm64-randconfig-002-20250308 (https://download.01.org/0day-ci/archive/20250308/202503080930.7ZetfmFz-lkp at intel.com/config)
compiler: aarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250308/202503080930.7ZetfmFz-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503080930.7ZetfmFz-lkp at intel.com/

All warnings (new ones prefixed by >>):

   arch/arm64/mm/mmu.c: In function 'alloc_init_pud':
>> arch/arm64/mm/mmu.c:511:35: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
     511 |                 pud_clear_fixmap();
         |                                   ^
   arch/arm64/mm/mmu.c: In function 'alloc_init_p4d':
   arch/arm64/mm/mmu.c:570:35: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
     570 |                 p4d_clear_fixmap();
         |                                   ^


vim +/if +511 arch/arm64/mm/mmu.c

d27cfa1fc823d3 Ard Biesheuvel    2017-03-09  428  
2451145c9a60e0 Yang Shi          2025-03-04  429  static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
da141706aea52c Laura Abbott      2015-01-21  430  			  phys_addr_t phys, pgprot_t prot,
90292aca9854a2 Yu Zhao           2019-03-11  431  			  phys_addr_t (*pgtable_alloc)(int),
c0951366d4b7e0 Ard Biesheuvel    2017-03-09  432  			  int flags)
c1cc1552616d0f Catalin Marinas   2012-03-05  433  {
c1cc1552616d0f Catalin Marinas   2012-03-05  434  	unsigned long next;
2451145c9a60e0 Yang Shi          2025-03-04  435  	int ret = 0;
e9f6376858b979 Mike Rapoport     2020-06-04  436  	p4d_t p4d = READ_ONCE(*p4dp);
6ed8a3a094b43a Ard Biesheuvel    2024-02-14  437  	pud_t *pudp;
6fad683b9a5c21 Yang Shi          2025-03-04  438  	bool split = flags & SPLIT_MAPPINGS;
6fad683b9a5c21 Yang Shi          2025-03-04  439  
6fad683b9a5c21 Yang Shi          2025-03-04  440  	if (split) {
6fad683b9a5c21 Yang Shi          2025-03-04  441  		BUG_ON(p4d_none(p4d));
6fad683b9a5c21 Yang Shi          2025-03-04  442  		pudp = pud_offset(p4dp, addr);
6fad683b9a5c21 Yang Shi          2025-03-04  443  		goto split_pgtable;
6fad683b9a5c21 Yang Shi          2025-03-04  444  	}
c1cc1552616d0f Catalin Marinas   2012-03-05  445  
e9f6376858b979 Mike Rapoport     2020-06-04  446  	if (p4d_none(p4d)) {
efe72541355d4d Yicong Yang       2024-11-02  447  		p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
132233a759580f Laura Abbott      2016-02-05  448  		phys_addr_t pud_phys;
87143f404f338d Ard Biesheuvel    2021-03-10  449  
87143f404f338d Ard Biesheuvel    2021-03-10  450  		if (flags & NO_EXEC_MAPPINGS)
87143f404f338d Ard Biesheuvel    2021-03-10  451  			p4dval |= P4D_TABLE_PXN;
132233a759580f Laura Abbott      2016-02-05  452  		BUG_ON(!pgtable_alloc);
90292aca9854a2 Yu Zhao           2019-03-11  453  		pud_phys = pgtable_alloc(PUD_SHIFT);
2451145c9a60e0 Yang Shi          2025-03-04  454  		if (!pud_phys)
2451145c9a60e0 Yang Shi          2025-03-04  455  			return -ENOMEM;
0e9df1c905d829 Ryan Roberts      2024-04-12  456  		pudp = pud_set_fixmap(pud_phys);
0e9df1c905d829 Ryan Roberts      2024-04-12  457  		init_clear_pgtable(pudp);
0e9df1c905d829 Ryan Roberts      2024-04-12  458  		pudp += pud_index(addr);
87143f404f338d Ard Biesheuvel    2021-03-10  459  		__p4d_populate(p4dp, pud_phys, p4dval);
0e9df1c905d829 Ryan Roberts      2024-04-12  460  	} else {
e9f6376858b979 Mike Rapoport     2020-06-04  461  		BUG_ON(p4d_bad(p4d));
e9f6376858b979 Mike Rapoport     2020-06-04  462  		pudp = pud_set_fixmap_offset(p4dp, addr);
0e9df1c905d829 Ryan Roberts      2024-04-12  463  	}
0e9df1c905d829 Ryan Roberts      2024-04-12  464  
6fad683b9a5c21 Yang Shi          2025-03-04  465  split_pgtable:
c1cc1552616d0f Catalin Marinas   2012-03-05  466  	do {
20a004e7b017cc Will Deacon       2018-02-15  467  		pud_t old_pud = READ_ONCE(*pudp);
e98216b52176ba Ard Biesheuvel    2016-10-21  468  
c1cc1552616d0f Catalin Marinas   2012-03-05  469  		next = pud_addr_end(addr, end);
206a2a73a62d37 Steve Capper      2014-05-06  470  
6fad683b9a5c21 Yang Shi          2025-03-04  471  		if (split) {
6fad683b9a5c21 Yang Shi          2025-03-04  472  			ret = split_pud(pudp, old_pud, pgtable_alloc);
6fad683b9a5c21 Yang Shi          2025-03-04  473  			if (ret)
6fad683b9a5c21 Yang Shi          2025-03-04  474  				break;
6fad683b9a5c21 Yang Shi          2025-03-04  475  
6fad683b9a5c21 Yang Shi          2025-03-04  476  			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
6fad683b9a5c21 Yang Shi          2025-03-04  477  						  pgtable_alloc, flags);
6fad683b9a5c21 Yang Shi          2025-03-04  478  			if (ret)
6fad683b9a5c21 Yang Shi          2025-03-04  479  				break;
6fad683b9a5c21 Yang Shi          2025-03-04  480  
6fad683b9a5c21 Yang Shi          2025-03-04  481  			continue;
6fad683b9a5c21 Yang Shi          2025-03-04  482  		}
6fad683b9a5c21 Yang Shi          2025-03-04  483  
206a2a73a62d37 Steve Capper      2014-05-06  484  		/*
206a2a73a62d37 Steve Capper      2014-05-06  485  		 * For 4K granule only, attempt to put down a 1GB block
206a2a73a62d37 Steve Capper      2014-05-06  486  		 */
1310222c276b79 Anshuman Khandual 2022-02-16  487  		if (pud_sect_supported() &&
1310222c276b79 Anshuman Khandual 2022-02-16  488  		   ((addr | next | phys) & ~PUD_MASK) == 0 &&
c0951366d4b7e0 Ard Biesheuvel    2017-03-09  489  		    (flags & NO_BLOCK_MAPPINGS) == 0) {
20a004e7b017cc Will Deacon       2018-02-15  490  			pud_set_huge(pudp, phys, prot);
206a2a73a62d37 Steve Capper      2014-05-06  491  
206a2a73a62d37 Steve Capper      2014-05-06  492  			/*
e98216b52176ba Ard Biesheuvel    2016-10-21  493  			 * After the PUD entry has been populated once, we
e98216b52176ba Ard Biesheuvel    2016-10-21  494  			 * only allow updates to the permission attributes.
206a2a73a62d37 Steve Capper      2014-05-06  495  			 */
e98216b52176ba Ard Biesheuvel    2016-10-21  496  			BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
20a004e7b017cc Will Deacon       2018-02-15  497  						      READ_ONCE(pud_val(*pudp))));
206a2a73a62d37 Steve Capper      2014-05-06  498  		} else {
2451145c9a60e0 Yang Shi          2025-03-04  499  			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
c0951366d4b7e0 Ard Biesheuvel    2017-03-09  500  					    pgtable_alloc, flags);
2451145c9a60e0 Yang Shi          2025-03-04  501  			if (ret)
2451145c9a60e0 Yang Shi          2025-03-04  502  				break;
e98216b52176ba Ard Biesheuvel    2016-10-21  503  
e98216b52176ba Ard Biesheuvel    2016-10-21  504  			BUG_ON(pud_val(old_pud) != 0 &&
20a004e7b017cc Will Deacon       2018-02-15  505  			       pud_val(old_pud) != READ_ONCE(pud_val(*pudp)));
206a2a73a62d37 Steve Capper      2014-05-06  506  		}
c1cc1552616d0f Catalin Marinas   2012-03-05  507  		phys += next - addr;
20a004e7b017cc Will Deacon       2018-02-15  508  	} while (pudp++, addr = next, addr != end);
f4710445458c0a Mark Rutland      2016-01-25  509  
6fad683b9a5c21 Yang Shi          2025-03-04  510  	if (!split)
f4710445458c0a Mark Rutland      2016-01-25 @511  		pud_clear_fixmap();
2451145c9a60e0 Yang Shi          2025-03-04  512  
2451145c9a60e0 Yang Shi          2025-03-04  513  	return ret;
c1cc1552616d0f Catalin Marinas   2012-03-05  514  }
c1cc1552616d0f Catalin Marinas   2012-03-05  515  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lumag at kernel.org  Fri Mar  7 17:42:18 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:18 +0200
Subject: [PATCH 00/10] drm/msm: add support for SAR2130P
Message-ID: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>

Add support for the Mobile Display SubSystem (MDSS) device present on
the Qualcomm SAR2130P platform. The MDSS device is similar to SM8550, it
features two MIPI DSI controllers, two MIPI DSI PHYs and one DisplayPort
controller.

Note, due to the technical limitations DP controller wasn't completely
evaluated.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
Dmitry Baryshkov (10):
      dt-bindings: display/msm: dp-controller: describe SAR2130P
      dt-bindings: display/msm: dsi-controller-main: describe SAR2130P
      dt-bindings: display/msm: dsi-phy-7nm: describe SAR2130P
      dt-bindings: display/msm: qcom,sc7280-dpu: describe SAR2130P
      dt-bindings: display/msm: Add Qualcomm SAR2130P
      drm/msm/mdss: add SAR2130P device configuration
      drm/msm/dsi/phy: add configuration for SAR2130P
      drm/msm/dpu: add catalog entry for SAR2130P
      iommu/arm-smmu-qcom: Add SAR2130P MDSS compatible
      arm64: dts: qcom: sar2130p: add display nodes

 .../bindings/display/msm/dp-controller.yaml        |   1 +
 .../bindings/display/msm/dsi-controller-main.yaml  |   2 +
 .../bindings/display/msm/dsi-phy-7nm.yaml          |   1 +
 .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 +++++++++++++++++++++
 .../bindings/display/msm/qcom,sc7280-dpu.yaml      |   1 +
 arch/arm64/boot/dts/qcom/sar2130p.dtsi             | 394 ++++++++++++++++++
 .../drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h   | 434 ++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c     |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h     |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c            |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c              |   2 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h              |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c          |  23 ++
 drivers/gpu/drm/msm/msm_mdss.c                     |  11 +
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c         |   1 +
 15 files changed, 1319 insertions(+), 1 deletion(-)
---
base-commit: 0a2f889128969dab41861b6e40111aa03dc57014
change-id: 20250308-sar2130p-display-b0601fcfeb30
prerequisite-patch-id: bafc6ced2462f729333f18ff2c7d086a72b10744
prerequisite-patch-id: 63f7a35baf213cb869f0dbc9c06cd543b7ca3f32

Best regards,
-- 
Dmitry Baryshkov <dmitry.baryshkov at linaro.org>



From lumag at kernel.org  Fri Mar  7 17:42:19 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:19 +0200
Subject: [PATCH 01/10] dt-bindings: display/msm: dp-controller: describe
 SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-1-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe DisplayPort controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index e00b88332f2fed2fc33f6d72c5cc3d827cd7594e..246bbb509bea18bed32e3a442d0926a24498c960 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -31,6 +31,7 @@ properties:
           - qcom,sm8650-dp
       - items:
           - enum:
+              - qcom,sar2130p-dp
               - qcom,sm6350-dp
               - qcom,sm8150-dp
               - qcom,sm8250-dp

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:20 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:20 +0200
Subject: [PATCH 02/10] dt-bindings: display/msm: dsi-controller-main:
 describe SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-2-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe MIPI DSI controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 2aab33cd0017cd4a0c915b7297bb3952e62561fa..a3e05e34bf14dd5802fc538ca8b69846384f8742 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -23,6 +23,7 @@ properties:
               - qcom,msm8996-dsi-ctrl
               - qcom,msm8998-dsi-ctrl
               - qcom,qcm2290-dsi-ctrl
+              - qcom,sar2130p-dsi-ctrl
               - qcom,sc7180-dsi-ctrl
               - qcom,sc7280-dsi-ctrl
               - qcom,sdm660-dsi-ctrl
@@ -314,6 +315,7 @@ allOf:
           contains:
             enum:
               - qcom,msm8998-dsi-ctrl
+              - qcom,sar2130p-dsi-ctrl
               - qcom,sc7180-dsi-ctrl
               - qcom,sc7280-dsi-ctrl
               - qcom,sdm845-dsi-ctrl

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:21 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:21 +0200
Subject: [PATCH 03/10] dt-bindings: display/msm: dsi-phy-7nm: describe
 SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-3-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe MIPI DSI PHY present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
index 321470435e654f1d569fc54f6a810e3f70fb168c..f79be422b8892484216b407f7385789764c2de1b 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
@@ -17,6 +17,7 @@ properties:
     enum:
       - qcom,dsi-phy-7nm
       - qcom,dsi-phy-7nm-8150
+      - qcom,sar2130p-dsi-phy-5nm
       - qcom,sc7280-dsi-phy-7nm
       - qcom,sm6375-dsi-phy-7nm
       - qcom,sm8350-dsi-phy-5nm

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:22 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:22 +0200
Subject: [PATCH 04/10] dt-bindings: display/msm: qcom,sc7280-dpu: describe
 SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-4-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe DPU controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
index 6902795b4e2c249c2b543c1c5350f739a30553f2..df9ec15ad6c3ca1f77bebaab19ffa3adb985733d 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
@@ -17,6 +17,7 @@ $ref: /schemas/display/msm/dpu-common.yaml#
 properties:
   compatible:
     enum:
+      - qcom,sar2130p-dpu
       - qcom,sc7280-dpu
       - qcom,sc8280xp-dpu
       - qcom,sm8350-dpu

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:23 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:23 +0200
Subject: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe the Mobile Display SubSystem (MDSS) device present on the
Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
system level. SAR2130P features two DSI hosts and single DisplayPort
controller.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 +++++++++++++++++++++
 1 file changed, 445 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0dbf6704c44dc6a752a22e83dc7a4f8c70665390
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml
@@ -0,0 +1,445 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sar2130p-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SAR2130P Display MDSS
+
+maintainers:
+  - Dmitry Baryshkov <lumag at kernel.org>
+
+description:
+  SAR2310P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
+  DPU display controller, DSI and DP interfaces etc.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+  compatible:
+    const: qcom,sar2130p-mdss
+
+  clocks:
+    items:
+      - description: Display MDSS AHB
+      - description: Display AHB
+      - description: Display hf AXI
+      - description: Display core
+
+  iommus:
+    maxItems: 1
+
+  interconnects:
+    items:
+      - description: Interconnect path from mdp0 port to the data bus
+      - description: Interconnect path from CPU to the reg bus
+
+  interconnect-names:
+    items:
+      - const: mdp0-mem
+      - const: cpu-cfg
+
+patternProperties:
+  "^display-controller@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+
+    properties:
+      compatible:
+        const: qcom,sar2130p-dpu
+
+  "^displayport-controller@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+
+    properties:
+      compatible:
+        items:
+          - const: qcom,sar2130p-dp
+          - const: qcom,sm8350-dp
+
+  "^dsi@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+
+    properties:
+      compatible:
+        items:
+          - const: qcom,sar2130p-dsi-ctrl
+          - const: qcom,mdss-dsi-ctrl
+
+  "^phy@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+
+    properties:
+      compatible:
+        const: qcom,sar2130p-dsi-phy-5nm
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/qcom,rpmhpd.h>
+    #include <dt-bindings/phy/phy-qcom-qmp.h>
+
+    display-subsystem at ae00000 {
+        compatible = "qcom,sar2130p-mdss";
+        reg = <0x0ae00000 0x1000>;
+        reg-names = "mdss";
+
+        interconnects = <&mmss_noc_master_mdp &mc_virt_slave_ebi1>,
+                        <&gem_noc_master_appss_proc &config_noc_slave_display_cfg>;
+        interconnect-names = "mdp0-mem", "cpu-cfg";
+
+        resets = <&dispcc_disp_cc_mdss_core_bcr>;
+
+        power-domains = <&dispcc_mdss_gdsc>;
+
+        clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                 <&gcc_gcc_disp_ahb_clk>,
+                 <&gcc_gcc_disp_hf_axi_clk>,
+                 <&dispcc_disp_cc_mdss_mdp_clk>;
+        clock-names = "iface", "bus", "nrt_bus", "core";
+
+        interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-controller;
+        #interrupt-cells = <1>;
+
+        iommus = <&apps_smmu 0x1c00 0x2>;
+
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        display-controller at ae01000 {
+            compatible = "qcom,sar2130p-dpu";
+            reg = <0x0ae01000 0x8f000>,
+                  <0x0aeb0000 0x2008>;
+            reg-names = "mdp", "vbif";
+
+            clocks = <&gcc_gcc_disp_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&dispcc_disp_cc_mdss_mdp_lut_clk>,
+                     <&dispcc_disp_cc_mdss_mdp_clk>,
+                     <&dispcc_disp_cc_mdss_vsync_clk>;
+            clock-names = "bus",
+                          "nrt_bus",
+                          "iface",
+                          "lut",
+                          "core",
+                          "vsync";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_vsync_clk>;
+            assigned-clock-rates = <19200000>;
+
+            operating-points-v2 = <&mdp_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            interrupt-parent = <&mdss>;
+            interrupts = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    dpu_intf0_out: endpoint {
+                        remote-endpoint = <&mdss_dp0_in>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    dpu_intf1_out: endpoint {
+                        remote-endpoint = <&mdss_dsi0_in>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <2>;
+
+                    dpu_intf2_out: endpoint {
+                        remote-endpoint = <&mdss_dsi1_in>;
+                    };
+                };
+            };
+
+            mdp_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-200000000 {
+                    opp-hz = /bits/ 64 <200000000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-325000000 {
+                    opp-hz = /bits/ 64 <325000000>;
+                    required-opps = <&rpmhpd_opp_svs>;
+                };
+
+                opp-375000000 {
+                    opp-hz = /bits/ 64 <375000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+
+                opp-514000000 {
+                    opp-hz = /bits/ 64 <514000000>;
+                    required-opps = <&rpmhpd_opp_nom>;
+                };
+            };
+        };
+
+        displayport-controller at ae90000 {
+            compatible = "qcom,sar2130p-dp",
+                         "qcom,sm8350-dp";
+            reg = <0xae90000 0x200>,
+                  <0xae90200 0x200>,
+                  <0xae90400 0xc00>,
+                  <0xae91000 0x400>,
+                  <0xae91400 0x400>;
+
+            interrupt-parent = <&mdss>;
+            interrupts = <12>;
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_aux_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_link_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_pixel0_clk>;
+            clock-names = "core_iface",
+                          "core_aux",
+                          "ctrl_link",
+                          "ctrl_link_iface",
+                          "stream_pixel";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
+                              <&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>;
+            assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
+                                     <&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
+
+            phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
+            phy-names = "dp";
+
+            #sound-dai-cells = <0>;
+
+            operating-points-v2 = <&dp_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+                    mdss_dp0_in: endpoint {
+                        remote-endpoint = <&dpu_intf0_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+                    mdss_dp0_out: endpoint {
+                        remote-endpoint = <&usb_dp_qmpphy_dp_in>;
+                    };
+                };
+        };
+
+        dp_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-162000000 {
+                    opp-hz = /bits/ 64 <162000000>;
+                    required-opps = <&rpmhpd_opp_low_svs_d1>;
+                };
+
+                opp-270000000 {
+                    opp-hz = /bits/ 64 <270000000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-540000000 {
+                    opp-hz = /bits/ 64 <540000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+
+                opp-810000000 {
+                    opp-hz = /bits/ 64 <810000000>;
+                    required-opps = <&rpmhpd_opp_nom>;
+                };
+            };
+        };
+
+        dsi at ae94000 {
+            compatible = "qcom,sar2130p-dsi-ctrl",
+                         "qcom,mdss-dsi-ctrl";
+            reg = <0x0ae94000 0x400>;
+            reg-names = "dsi_ctrl";
+
+            interrupt-parent = <&mdss>;
+            interrupts = <4>;
+
+            clocks = <&dispcc_disp_cc_mdss_byte0_clk>,
+                     <&dispcc_disp_cc_mdss_byte0_intf_clk>,
+                     <&dispcc_disp_cc_mdss_pclk0_clk>,
+                     <&dispcc_disp_cc_mdss_esc0_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>;
+            clock-names = "byte",
+                          "byte_intf",
+                          "pixel",
+                          "core",
+                          "iface",
+                          "bus";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_byte0_clk_src>,
+                              <&dispcc_disp_cc_mdss_pclk0_clk_src>;
+            assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>;
+
+            operating-points-v2 = <&dsi_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            phys = <&mdss_dsi0_phy>;
+            phy-names = "dsi";
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    mdss_dsi0_in: endpoint {
+                        remote-endpoint = <&dpu_intf1_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    mdss_dsi0_out: endpoint {
+                    };
+                };
+            };
+
+            dsi_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-187500000 {
+                    opp-hz = /bits/ 64 <187500000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-300000000 {
+                    opp-hz = /bits/ 64 <300000000>;
+                    required-opps = <&rpmhpd_opp_svs>;
+                };
+
+                opp-358000000 {
+                    opp-hz = /bits/ 64 <358000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+            };
+        };
+
+        mdss_dsi0_phy: phy at ae94400 {
+            compatible = "qcom,sar2130p-dsi-phy-5nm";
+            reg = <0x0ae95000 0x200>,
+                  <0x0ae95200 0x280>,
+                  <0x0ae95500 0x400>;
+            reg-names = "dsi_phy",
+                        "dsi_phy_lane",
+                        "dsi_pll";
+
+            #clock-cells = <1>;
+            #phy-cells = <0>;
+
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&rpmhcc_rpmh_cxo_clk>;
+            clock-names = "iface", "ref";
+        };
+
+        dsi at ae96000 {
+            compatible = "qcom,sar2130p-dsi-ctrl",
+                         "qcom,mdss-dsi-ctrl";
+            reg = <0x0ae96000 0x400>;
+            reg-names = "dsi_ctrl";
+
+            interrupt-parent = <&mdss>;
+            interrupts = <5>;
+
+            clocks = <&dispcc_disp_cc_mdss_byte1_clk>,
+                     <&dispcc_disp_cc_mdss_byte1_intf_clk>,
+                     <&dispcc_disp_cc_mdss_pclk1_clk>,
+                     <&dispcc_disp_cc_mdss_esc1_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>;
+            clock-names = "byte",
+                          "byte_intf",
+                          "pixel",
+                          "core",
+                          "iface",
+                          "bus";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_byte1_clk_src>,
+                              <&dispcc_disp_cc_mdss_pclk1_clk_src>;
+            assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>;
+
+            operating-points-v2 = <&dsi_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            phys = <&mdss_dsi1_phy>;
+            phy-names = "dsi";
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    mdss_dsi1_in: endpoint {
+                        remote-endpoint = <&dpu_intf2_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    mdss_dsi1_out: endpoint {
+                    };
+                };
+            };
+        };
+
+        mdss_dsi1_phy: phy at ae97000 {
+            compatible = "qcom,sar2130p-dsi-phy-5nm";
+            reg = <0x0ae97000 0x200>,
+                  <0x0ae97200 0x280>,
+                  <0x0ae97500 0x400>;
+            reg-names = "dsi_phy",
+                        "dsi_phy_lane",
+                        "dsi_pll";
+
+            #clock-cells = <1>;
+            #phy-cells = <0>;
+
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&rpmhcc_rpmh_cxo_clk>;
+            clock-names = "iface", "ref";
+        };
+    };
+...

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:24 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:24 +0200
Subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add compatible and device configuration for the Qualcomm SAR2130P
platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/gpu/drm/msm/msm_mdss.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index dcb49fd30402b80edd2cb5971f95a78eaad6081f..3e82ba0885d03107d54eab9569bb4c5395454c7a 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -592,6 +592,16 @@ static const struct msm_mdss_data sa8775p_data = {
 	.reg_bus_bw = 74000,
 };
 
+static const struct msm_mdss_data sar2130p_data = {
+	.ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */
+	.ubwc_dec_version = UBWC_4_3,
+	.ubwc_swizzle = 6,
+	.ubwc_static = 1,
+	.highest_bank_bit = 0,
+	.macrotile_mode = 1,
+	.reg_bus_bw = 74000,
+};
+
 static const struct msm_mdss_data sc7180_data = {
 	.ubwc_enc_version = UBWC_2_0,
 	.ubwc_dec_version = UBWC_2_0,
@@ -738,6 +748,7 @@ static const struct of_device_id mdss_dt_match[] = {
 	{ .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
 	{ .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
 	{ .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data },
+	{ .compatible = "qcom,sar2130p-mdss", .data = &sar2130p_data },
 	{ .compatible = "qcom,sdm670-mdss", .data = &sdm670_data },
 	{ .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
 	{ .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },

-- 
2.39.5



From lumag at kernel.org  Fri Mar  7 17:42:25 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Sat, 08 Mar 2025 03:42:25 +0200
Subject: [PATCH 07/10] drm/msm/dsi/phy: add configuration for SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
Message-ID: <20250308-sar2130p-display-v1-7-1d4c30f43822@linaro.org>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Qualcomm SAR2130P requires slightly different setup for the DSI PHY. It
is a 5nm PHY (like SM8450), so supplies are the same, but the rest of
the configuration is the same as SM8550 DSI PHY.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c     |  2 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h     |  1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 23 +++++++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index c0bcc68289633fd7506ce4f1f963655d862e8f08..a58bafe9fe8635730cb82e8c82ec1ded394988cd 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
 	  .data = &dsi_phy_7nm_cfgs },
 	{ .compatible = "qcom,dsi-phy-7nm-8150",
 	  .data = &dsi_phy_7nm_8150_cfgs },
+	{ .compatible = "qcom,sar2130p-dsi-phy-5nm",
+	  .data = &dsi_phy_5nm_sar2130p_cfgs },
 	{ .compatible = "qcom,sc7280-dsi-phy-7nm",
 	  .data = &dsi_phy_7nm_7280_cfgs },
 	{ .compatible = "qcom,sm6375-dsi-phy-7nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 1925418d9999a24263d6621299cae78f1fb9455c..1ed08b56e056094bc0096d07d4470b89d9824060 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index a92decbee5b5433853ed973747f7705d9079068d..cad55702746b8d35949d22090796cca60f03b9e1 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -1289,6 +1289,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = {
 	.quirks = DSI_PHY_7NM_QUIRK_V4_3,
 };
 
+const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = {
+	.has_phy_lane = true,
+	.regulator_data = dsi_phy_7nm_97800uA_regulators,
+	.num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators),
+	.ops = {
+		.enable = dsi_7nm_phy_enable,
+		.disable = dsi_7nm_phy_disable,
+		.pll_init = dsi_pll_7nm_init,
+		.save_pll_state = dsi_7nm_pll_save_state,
+		.restore_pll_state = dsi_7nm_pll_restore_state,
+		.set_continuous_clock = dsi_7nm_set_continuous_clock,
+	},
+	.min_pll_rate = 600000000UL,
+#ifdef CONFIG_64BIT
+	.max_pll_rate = 5000000000UL,
+#else
+	.max_pll_rate = ULONG_MAX,
+#endif
+	.io_start = { 0xae95000, 0xae97000 },
+	.num_dsi_phy = 2,
+	.quirks = DSI_PHY_7NM_QUIRK_V5_2,
+};
+
 const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = {
 	.has_phy_lane = true,
 	.regulator_data = dsi_phy_7nm_98400uA_regulators,

-- 
2.39.5



From dmitry.baryshkov at linaro.org  Fri Mar  7 18:00:15 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat, 8 Mar 2025 04:00:15 +0200
Subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
In-Reply-To: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
Message-ID: <kifzy754m7zygspknsk4a4aeuqxkt4bkyp5jbu6ul43gon7je3@yleqikfmh4lp>

On Sat, Mar 08, 2025 at 03:42:24AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Add compatible and device configuration for the Qualcomm SAR2130P
> platform.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  drivers/gpu/drm/msm/msm_mdss.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
> index dcb49fd30402b80edd2cb5971f95a78eaad6081f..3e82ba0885d03107d54eab9569bb4c5395454c7a 100644
> --- a/drivers/gpu/drm/msm/msm_mdss.c
> +++ b/drivers/gpu/drm/msm/msm_mdss.c
> @@ -592,6 +592,16 @@ static const struct msm_mdss_data sa8775p_data = {
>  	.reg_bus_bw = 74000,
>  };
>  
> +static const struct msm_mdss_data sar2130p_data = {
> +	.ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */
> +	.ubwc_dec_version = UBWC_4_3,
> +	.ubwc_swizzle = 6,
> +	.ubwc_static = 1,

This should have been .ubwc_bank_spread = true.
I have been rebasing the series from the earlier kernel and I'm not sure
why this didn't show up during the build phase.

> +	.highest_bank_bit = 0,
> +	.macrotile_mode = 1,
> +	.reg_bus_bw = 74000,
> +};
> +
>  static const struct msm_mdss_data sc7180_data = {
>  	.ubwc_enc_version = UBWC_2_0,
>  	.ubwc_dec_version = UBWC_2_0,
> @@ -738,6 +748,7 @@ static const struct of_device_id mdss_dt_match[] = {
>  	{ .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
>  	{ .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
>  	{ .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data },
> +	{ .compatible = "qcom,sar2130p-mdss", .data = &sar2130p_data },
>  	{ .compatible = "qcom,sdm670-mdss", .data = &sdm670_data },
>  	{ .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
>  	{ .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },
> 
> -- 
> 2.39.5
> 

-- 
With best wishes
Dmitry


From wei.fang at nxp.com  Fri Mar  7 18:05:35 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Sat, 8 Mar 2025 02:05:35 +0000
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <PAXPR04MB85107A1E5990FBB63F12C3B888D52@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-2-wei.fang@nxp.com>
 <20250306142842.476db52c@kernel.org>
 <PAXPR04MB85107A1E5990FBB63F12C3B888D52@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <PAXPR04MB8510771650890E8B7395B2DA88D42@PAXPR04MB8510.eurprd04.prod.outlook.com>

> > On Tue,  4 Mar 2025 15:21:49 +0800 Wei Fang wrote:
> > > +config NXP_NETC_LIB
> > > +	tristate "NETC Library"
> >
> > Remove the string after "tristate", the user should not be prompted
> > to make a choice for this, since the consumers "select" this config
> > directly.
> >
> 
> Okay, I will remove it.
> 
> > > +	help
> > > +	  This module provides common functionalities for both ENETC and NETC
> > > +	  Switch, such as NETC Table Management Protocol (NTMP) 2.0,
> common
> > tc
> > > +	  flower and debugfs interfaces and so on.
> > > +
> > > +	  If compiled as module (M), the module name is nxp-netc-lib.
> >
> > Not sure if the help makes sense for an invisible symbol either.
> 
> Yes, I think it can also be removed. Thanks.
> >
> > >  config FSL_ENETC
> > >  	tristate "ENETC PF driver"
> > >  	depends on PCI_MSI
> > > @@ -40,6 +50,7 @@ config NXP_ENETC4
> > >  	select FSL_ENETC_CORE
> > >  	select FSL_ENETC_MDIO
> > >  	select NXP_ENETC_PF_COMMON
> > > +	select NXP_NETC_LIB
> > >  	select PHYLINK
> > >  	select DIMLIB
> > >  	help
> >
> > > +#pragma pack(1)
> >
> > please don't blindly pack all structs, only if they are misaligned
> > or will otherwise have holes.
> 
> Because these structures are in hardware buffer format and need
> to be aligned, so for convenience, I simply used pack(1). You are right,
> I should use pack() for structures with holes. Thanks.
> >
> > > +#if IS_ENABLED(CONFIG_NXP_NETC_LIB)
> >
> > why the ifdef, all callers select the config option
> 
> hm..., there are some interfaces of netc-lib are used in common .c files
> in downstream, so I used "ifdef" in downstream. Now for the upstream,
> I'm going to separate them from the common .c files. So yes, we can
> remove it now.

Sorry, I misread the header file. The ifdef in ntmp.h is needed because
the interfaces in this header file will be used by the enetc-core and
enetc-vf drivers. For the ENETC v1 (LS1028A platform), it will not select
NXP_NETC_LIB.


From pcc at google.com  Fri Mar  7 18:33:13 2025
From: pcc at google.com (Peter Collingbourne)
Date: Fri,  7 Mar 2025 18:33:13 -0800
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if kernel
 MTE is enabled
Message-ID: <20250308023314.3981455-1-pcc@google.com>

The optimized strscpy() and dentry_string_cmp() routines will read 8
unaligned bytes at a time via the function read_word_at_a_time(), but
this is incompatible with MTE which will fault on a partially invalid
read. The attributes on read_word_at_a_time() that disable KASAN are
invisible to the CPU so they have no effect on MTE. Let's fix the
bug for now by disabling the optimizations if the kernel is built
with HW tag-based KASAN and consider improvements for followup changes.

Signed-off-by: Peter Collingbourne <pcc at google.com>
Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
Cc: stable at vger.kernel.org
---
 fs/dcache.c  | 2 +-
 lib/string.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index e3634916ffb93..71f0830ac5e69 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -223,7 +223,7 @@ fs_initcall(init_fs_dcache_sysctls);
  * Compare 2 name strings, return 0 if they match, otherwise non-zero.
  * The strings are both count bytes long, and count is non-zero.
  */
-#ifdef CONFIG_DCACHE_WORD_ACCESS
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && !defined(CONFIG_KASAN_HW_TAGS)
 
 #include <asm/word-at-a-time.h>
 /*
diff --git a/lib/string.c b/lib/string.c
index eb4486ed40d25..9a43a3824d0d7 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -119,7 +119,8 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
 		return -E2BIG;
 
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \
+	!defined(CONFIG_KASAN_HW_TAGS)
 	/*
 	 * If src is unaligned, don't cross a page boundary,
 	 * since we don't know if the next page is mapped.
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From kuba at kernel.org  Fri Mar  7 18:59:02 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Fri, 7 Mar 2025 18:59:02 -0800
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <PAXPR04MB8510771650890E8B7395B2DA88D42@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-2-wei.fang@nxp.com>
	<20250306142842.476db52c@kernel.org>
	<PAXPR04MB85107A1E5990FBB63F12C3B888D52@PAXPR04MB8510.eurprd04.prod.outlook.com>
	<PAXPR04MB8510771650890E8B7395B2DA88D42@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250307185902.384554a5@kernel.org>

On Sat, 8 Mar 2025 02:05:35 +0000 Wei Fang wrote:
> > > On Tue,  4 Mar 2025 15:21:49 +0800 Wei Fang wrote:  
> > hm..., there are some interfaces of netc-lib are used in common .c files
> > in downstream, so I used "ifdef" in downstream. Now for the upstream,
> > I'm going to separate them from the common .c files. So yes, we can
> > remove it now.  
> 
> Sorry, I misread the header file. The ifdef in ntmp.h is needed because
> the interfaces in this header file will be used by the enetc-core and
> enetc-vf drivers. For the ENETC v1 (LS1028A platform), it will not select
> NXP_NETC_LIB.

Meaning FSL_ENETC ? And the calls are in FSL_ENETC_CORE ?


From kees at kernel.org  Fri Mar  7 19:36:31 2025
From: kees at kernel.org (Kees Cook)
Date: Fri, 7 Mar 2025 19:36:31 -0800
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <20250308023314.3981455-1-pcc@google.com>
References: <20250308023314.3981455-1-pcc@google.com>
Message-ID: <202503071927.1A795821A@keescook>

On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> The optimized strscpy() and dentry_string_cmp() routines will read 8
> unaligned bytes at a time via the function read_word_at_a_time(), but
> this is incompatible with MTE which will fault on a partially invalid
> read. The attributes on read_word_at_a_time() that disable KASAN are
> invisible to the CPU so they have no effect on MTE. Let's fix the
> bug for now by disabling the optimizations if the kernel is built
> with HW tag-based KASAN and consider improvements for followup changes.

Why is faulting on a partially invalid read a problem? It's still
invalid, so ... it should fault, yes? What am I missing?

> 
> Signed-off-by: Peter Collingbourne <pcc at google.com>
> Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> Cc: stable at vger.kernel.org
> ---
>  fs/dcache.c  | 2 +-
>  lib/string.c | 3 ++-
>  2 files changed, 3 insertions(+), 2 deletions(-)

Why are DCACHE_WORD_ACCESS and HAVE_EFFICIENT_UNALIGNED_ACCESS separate
things? I can see at least one place where it's directly tied:

arch/arm/Kconfig:58:    select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS

Would it make sense to sort this out so that KASAN_HW_TAGS can be taken
into account at the Kconfig level instead?

> diff --git a/fs/dcache.c b/fs/dcache.c
> index e3634916ffb93..71f0830ac5e69 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -223,7 +223,7 @@ fs_initcall(init_fs_dcache_sysctls);
>   * Compare 2 name strings, return 0 if they match, otherwise non-zero.
>   * The strings are both count bytes long, and count is non-zero.
>   */
> -#ifdef CONFIG_DCACHE_WORD_ACCESS
> +#if defined(CONFIG_DCACHE_WORD_ACCESS) && !defined(CONFIG_KASAN_HW_TAGS)

Why not also the word_at_a_time use in fs/namei.c and lib/siphash.c?

For reference, here are the DCACHE_WORD_ACCESS places:

arch/arm/Kconfig:58:    select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/arm64/Kconfig:137: select DCACHE_WORD_ACCESS
arch/powerpc/Kconfig:192:       select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN
arch/riscv/Kconfig:934: select DCACHE_WORD_ACCESS if MMU
arch/s390/Kconfig:154:  select DCACHE_WORD_ACCESS if !KMSAN
arch/x86/Kconfig:160:   select DCACHE_WORD_ACCESS if !KMSAN
arch/x86/um/Kconfig:12: select DCACHE_WORD_ACCESS

>  
>  #include <asm/word-at-a-time.h>
>  /*
> diff --git a/lib/string.c b/lib/string.c
> index eb4486ed40d25..9a43a3824d0d7 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -119,7 +119,8 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
>  		return -E2BIG;
>  
> -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
> +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \
> +	!defined(CONFIG_KASAN_HW_TAGS)

There are lots more places checking CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS...
Why only here?

And the Kconfigs since I was comparing these against DCACHE_WORD_ACCESS

arch/arc/Kconfig:352:   select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/arm/Kconfig:107:   select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
arch/arm64/Kconfig:222: select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/loongarch/Kconfig:140:     select HAVE_EFFICIENT_UNALIGNED_ACCESS if !ARCH_STRICT_ALIGN
arch/m68k/Kconfig:33:   select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_HAS_NO_UNALIGNED
arch/powerpc/Kconfig:246:       select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/riscv/Kconfig:935: select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/s390/Kconfig:197:  select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/x86/Kconfig:238:   select HAVE_EFFICIENT_UNALIGNED_ACCESS
arch/x86/um/Kconfig:13: select HAVE_EFFICIENT_UNALIGNED_ACCESS

>  	/*
>  	 * If src is unaligned, don't cross a page boundary,
>  	 * since we don't know if the next page is mapped.
> -- 
> 2.49.0.rc0.332.g42c0ae87b1-goog
> 

-Kees

-- 
Kees Cook


From Jjian.Zhou at mediatek.com  Fri Mar  7 19:39:28 2025
From: Jjian.Zhou at mediatek.com (=?utf-8?B?SmppYW4gWmhvdSAo5ZGo5bu6KQ==?=)
Date: Sat, 8 Mar 2025 03:39:28 +0000
Subject: [PATCH RFC 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <20250305164627.GA2117924-robh@kernel.org>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
	 <20250305082047.15746-4-jjian.zhou@mediatek.com>
	 <20250305164627.GA2117924-robh@kernel.org>
Message-ID: <f1cc982deb9770f386b7320cfc75969daef09538.camel@mediatek.com>

On Wed, 2025-03-05 at 10:46 -0600, Rob Herring wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Wed, Mar 05, 2025 at 04:20:40PM +0800, Jjian Zhou wrote:
> > This patch adds document for mediatek vcp mbox.
> > 
> > Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> > ---
> >  .../bindings/mailbox/mtk,vcp-mbox.yaml        | 49
> > +++++++++++++++++++
> >  1 file changed, 49 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/mailbox/mtk,vcp-
> > mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,vcp-
> > mbox.yaml
> > new file mode 100644
> > index 000000000000..d5afe295af14
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> > @@ -0,0 +1,49 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: 
> > https://urldefense.com/v3/__http://devicetree.org/schemas/mailbox/mtk,vcp-mbox.yaml*__;Iw!!CTRNKA9wMg0ARbw!htNQU7pv2prgWsEynW_fNKiBzXFsvuzVqq3plpilj-I6ntUDcorXT7c-aSh8ulpfXX4MyEaMLa_NNu15$
> > +$schema: 
> > https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!htNQU7pv2prgWsEynW_fNKiBzXFsvuzVqq3plpilj-I6ntUDcorXT7c-aSh8ulpfXX4MyEaMLfOSittN$
> > +
> > +title: MediaTek Video Companion Processor (VCP) mailbox
> > +
> > +maintainers:
> > +  - Jjian Zhou <Jjian.Zhou at mediatek.com>
> > +
> > +description: |
> 
> Don't need '|' if no formatting
  I will remove it in version-two. Thanks for your help.
> 
> > +  The MTK VCP mailbox enables the SoC to communicate with the VCP
> > by passing
> > +  messages through 64 32-bit wide registers. It has 32 interrupt
> > vectors in
> > +  either direction for signalling purposes.
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - mediatek,mt8196-vcp-mbox
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  "#mbox-cells":
> > +    const: 0
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +  - "#mbox-cells"
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +
> > +    vcp_mailbox0: mailbox at 31b80000 {
> > +        compatible = "mediatek,mt8196-vcp-mbox";
> > +        reg = <0x31b80000 0x1000>;
> > +        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
> > +        #mbox-cells = <0>;
> > +    };
> > --
> > 2.45.2
> > 

From patchwork-bot+netdevbpf at kernel.org  Fri Mar  7 19:40:41 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Sat, 08 Mar 2025 03:40:41 +0000
Subject: [PATCH net-next v7 0/4] riscv: sophgo: Add ethernet support for
 SG2044
In-Reply-To: <20250307011623.440792-1-inochiama@gmail.com>
References: <20250307011623.440792-1-inochiama@gmail.com>
Message-ID: <174140524199.2565853.4357984309163755989.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Fri,  7 Mar 2025 09:16:13 +0800 you wrote:
> The ethernet controller of SG2044 is Synopsys DesignWare IP with
> custom clock. Add glue layer for it.
> 
> Changed from v6:
> - https://lore.kernel.org/netdev/20250305063920.803601-1-inochiama at gmail.com/
> 1. rebase against latest net-next/main
> 
> [...]

Here is the summary with links:
  - [net-next,v7,1/4] dt-bindings: net: Add support for Sophgo SG2044 dwmac
    https://git.kernel.org/netdev/net-next/c/114508a89ddc
  - [net-next,v7,2/4] net: stmmac: platform: Group GMAC4 compatible check
    https://git.kernel.org/netdev/net-next/c/f8add6654d3c
  - [net-next,v7,3/4] net: stmmac: platform: Add snps,dwmac-5.30a IP compatible string
    https://git.kernel.org/netdev/net-next/c/9ef17cafc36b
  - [net-next,v7,4/4] net: stmmac: Add glue layer for Sophgo SG2044 SoC
    https://git.kernel.org/netdev/net-next/c/a22221ef5dee

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Fri Mar  7 19:40:47 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Sat, 08 Mar 2025 03:40:47 +0000
Subject: [PATCH net-next] net: stmmac: remove write-only priv->speed
In-Reply-To: <E1tqLJJ-005aQm-Mv@rmk-PC.armlinux.org.uk>
References: <E1tqLJJ-005aQm-Mv@rmk-PC.armlinux.org.uk>
Message-ID: <174140524774.2565853.6497124340077503983.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Fri, 07 Mar 2025 00:11:29 +0000 you wrote:
> priv->speed is only ever written to in two locations, but never
> read. Therefore, it serves no useful purpose. Remove this unnecessary
> struct member.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac.h      | 1 -
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ---
>  2 files changed, 4 deletions(-)

Here is the summary with links:
  - [net-next] net: stmmac: remove write-only priv->speed
    https://git.kernel.org/netdev/net-next/c/64fdb808660d

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From robh at kernel.org  Fri Mar  7 19:40:56 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 07 Mar 2025 21:40:56 -0600
Subject: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>
Message-ID: <174140525677.1770282.3232695979994091275.robh@kernel.org>


On Sat, 08 Mar 2025 03:42:23 +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Describe the Mobile Display SubSystem (MDSS) device present on the
> Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
> system level. SAR2130P features two DSI hosts and single DisplayPort
> controller.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 +++++++++++++++++++++
>  1 file changed, 445 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae94000: compatible: 'oneOf' conditional failed, one must be fixed:
	['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 'qcom,sm8650-dsi-ctrl']
	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 'qcom,mdss-dsi-ctrl']
	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae94000: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae96000: compatible: 'oneOf' conditional failed, one must be fixed:
	['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 'qcom,sm8650-dsi-ctrl']
	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 'qcom,mdss-dsi-ctrl']
	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae96000: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308-sar2130p-display-v1-5-1d4c30f43822 at linaro.org

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From Jjian.Zhou at mediatek.com  Fri Mar  7 19:46:30 2025
From: Jjian.Zhou at mediatek.com (=?utf-8?B?SmppYW4gWmhvdSAo5ZGo5bu6KQ==?=)
Date: Sat, 8 Mar 2025 03:46:30 +0000
Subject: [PATCH RFC 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <20250305-chewing-henchman-aea98c18b412@spud>
References: <20250305082047.15746-1-jjian.zhou@mediatek.com>
	 <20250305082047.15746-4-jjian.zhou@mediatek.com>
	 <20250305-chewing-henchman-aea98c18b412@spud>
Message-ID: <a37826597bd6e7889d191163865e49a06f70fca4.camel@mediatek.com>

On Wed, 2025-03-05 at 16:31 +0000, Conor Dooley wrote:
> On Wed, Mar 05, 2025 at 04:20:40PM +0800, Jjian Zhou wrote:
> > This patch adds document for mediatek vcp mbox.
> > 
> > Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> > ---
> >  .../bindings/mailbox/mtk,vcp-mbox.yaml        | 49
> > +++++++++++++++++++
> >  1 file changed, 49 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/mailbox/mtk,vcp-
> > mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,vcp-
> > mbox.yaml
> > new file mode 100644
> > index 000000000000..d5afe295af14
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mailbox/mtk,vcp-mbox.yaml
> 
> When you go !RFC, filename matching compatible please.
  I will rename the yaml file to mtk,mt8196-vcp-mbox.yaml.
  Thanks for your review.
> 
> > @@ -0,0 +1,49 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/mailbox/mtk,vcp-mbox.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: MediaTek Video Companion Processor (VCP) mailbox
> > +
> > +maintainers:
> > +  - Jjian Zhou <Jjian.Zhou at mediatek.com>
> > +
> > +description: |
> > +  The MTK VCP mailbox enables the SoC to communicate with the VCP
> > by passing
> > +  messages through 64 32-bit wide registers. It has 32 interrupt
> > vectors in
> > +  either direction for signalling purposes.
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - mediatek,mt8196-vcp-mbox
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  "#mbox-cells":
> > +    const: 0
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +  - "#mbox-cells"
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +
> > +    vcp_mailbox0: mailbox at 31b80000 {
> 
> label here is unused, please drop it.
> 
> Cheers,
> Conor.

   OK. I will drop it in version-two.
> 
> > +        compatible = "mediatek,mt8196-vcp-mbox";
> > +        reg = <0x31b80000 0x1000>;
> > +        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
> > +        #mbox-cells = <0>;
> > +    };
> > -- 
> > 2.45.2
> > 

From honyuenkwun at gmail.com  Fri Mar  7 20:34:48 2025
From: honyuenkwun at gmail.com (Jimmy Hon)
Date: Fri, 7 Mar 2025 22:34:48 -0600
Subject: [PATCH UNTESTED 3/4] arm64: dts: rockchip: Enable HDMI1 on Orange
 Pi 5 Plus
In-Reply-To: <5qi24bxuamu3agtldyxhrnlefao6zy2mw2qmx62ycsdg3v6sbz@2jeawstukcyd>
References: <20250227235623.1624-1-honyuenkwun@gmail.com> <20250227235623.1624-4-honyuenkwun@gmail.com>
 <5qi24bxuamu3agtldyxhrnlefao6zy2mw2qmx62ycsdg3v6sbz@2jeawstukcyd>
Message-ID: <CALWfF7LcUUFUnESrGTE10VS7S1+G=sXWkD7iZjbufpgGWQnFbg@mail.gmail.com>

On Fri, Feb 28, 2025 at 5:15?AM Ond?ej Jirman <megi at xff.cz> wrote:
>
> Hello Jimmy,
>
> On Thu, Feb 27, 2025 at 05:56:22PM -0600, Jimmy Hon wrote:
> > Enable the second HDMI output port on the Orange Pi 5 Plus
>
> RK3588 hardware design guide states that:
>
>   - When working in HDMI2.1 mode, HDMI0_TX_ON_H is configured as low level,
>     Q1700, Q1701, Q1702, and Q1703 are not turned on.
>
>   - When working in HDMI2.0 and below modes, HDMI0_TX_ON_H is configured as high
>     level, Q5007, Q5004, Q5005, and Q5006 are turned on, and the 499ohm resistor
>     to ground and the 50ohm pull-up resistor at the Sink end form a DC bias of
>     about 3V.
>
>   If you only need to support HDMI2.0 and below modes, Q5007, Q5004, Q5005, and
>   Q5006 cannot be omitted. It is necessary to ensure that the tube is not turned
>   on when the machine is not turned on, because the HDMI CTS Test ID 7-3 TMDS
>   Voff test item requires that the Voff voltage must be within AVcc+-10mV when
>   the DUT is not powered on, otherwise this test item cannot pass. 2: The Coss
>   of the control MOS tube cannot be too large, otherwise it will affect the
>   signal quality. It is recommended to follow the reference figure model or the
>   corresponding Coss value.
>
> And Orange Pi 5 schematic (which has almost the same circuit as Plus variant)
> states this explicitely too:
>
>   https://megous.com/dl/tmp/5dc98e91dfee3b5a.png
>
> The same applies to HDMI1.
>
> Maybe it would be better to pull up HDMI1_TX_ON_H more explicitely for now via:
>
> &hdmi1 {
> + pinctrl-0 = <&hdmim2_tx1_cec &hdmim0_tx1_hpd
> +              &hdmim1_tx1_scl &hdmim1_tx1_sda
> +              &hdmi1_tx_on_h>;
> };
>
> &pinctrl {
> ...
> + hdmi {
> +         hdmi1_tx_on_h: hdmi1-tx-on-h {
> +                 rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
> +         };
> + };
> ...
> };
>
> AFAIK FRL is not supported, yet, so this may be a better default for HDMI1_TX_ON_H.
I am going to defer adding a temporary workaround and keep hdmi1
behavior the same as hdmi0. [1] I don't want to introduce something
that will hinder the upcoming FRL development when it tries to support
an old DTB. I'm hoping Cristian could start adding the HDMI0_TX_ON_H
to the dt-bindings, even before the full FRL support is added, so at
least all the DTS could have "enable-gpios" property defined [2], and
then the DTSs be ready to go when FRL support is ready. That way the
HDMI0_TX_ON_H will be pulled correctly depending what mode is being
used.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts?h=v6.14-rc1#n113
[2] https://github.com/radxa/kernel/blob/linux-6.1-stan-rkr4.1/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts#L564

>
> In any case,
>
> Reviewed-by: Ondrej Jirman <megi at xff.cz>
>
>
> And I've also tested and used identical patch for a few weeks already on my
> Orange Pi 5+. :)
>
> Kind regards,
>         o.
>
> > Signed-off-by: Jimmy Hon <honyuenkwun at gmail.com>
> > ---
> >  .../dts/rockchip/rk3588-orangepi-5-plus.dts   | 38 +++++++++++++++++++
> >  1 file changed, 38 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
> > index 0f874b87b47e..53797f633d3a 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
> > @@ -26,6 +26,17 @@ hdmi0_con_in: endpoint {
> >               };
> >       };
> >
> > +     hdmi1-con {
> > +             compatible = "hdmi-connector";
> > +             type = "a";
> > +
> > +             port {
> > +                     hdmi1_con_in: endpoint {
> > +                             remote-endpoint = <&hdmi1_out_con>;
> > +                     };
> > +             };
> > +     };
> > +
> >       ir-receiver {
> >               compatible = "gpio-ir-receiver";
> >               gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
> > @@ -125,10 +136,30 @@ hdmi0_out_con: endpoint {
> >       };
> >  };
> >
> > +&hdmi1 {
> > +     status = "okay";
> > +};
> > +
> > +&hdmi1_in {
> > +     hdmi1_in_vp1: endpoint {
> > +             remote-endpoint = <&vp1_out_hdmi1>;
> > +     };
> > +};
> > +
> > +&hdmi1_out {
> > +     hdmi1_out_con: endpoint {
> > +             remote-endpoint = <&hdmi1_con_in>;
> > +     };
> > +};
> > +
> >  &hdptxphy0 {
> >       status = "okay";
> >  };
> >
> > +&hdptxphy1 {
> > +     status = "okay";
> > +};
> > +
> >  &hym8563 {
> >       interrupt-parent = <&gpio0>;
> >       interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
> > @@ -342,3 +373,10 @@ vp0_out_hdmi0: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
> >               remote-endpoint = <&hdmi0_in_vp0>;
> >       };
> >  };
> > +
> > +&vp1 {
> > +     vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
> > +             reg = <ROCKCHIP_VOP2_EP_HDMI1>;
> > +             remote-endpoint = <&hdmi1_in_vp1>;
> > +     };
> > +};
> > --
> > 2.48.1
> >


From dmitry.baryshkov at linaro.org  Fri Mar  7 21:09:11 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat, 8 Mar 2025 07:09:11 +0200
Subject: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <174140525677.1770282.3232695979994091275.robh@kernel.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>
 <174140525677.1770282.3232695979994091275.robh@kernel.org>
Message-ID: <nddxntwmiyurqew75gc6yoj2dcinhjqu36cdujhruqyrz62ry5@4e2y76ghmo4h>

On Fri, Mar 07, 2025 at 09:40:56PM -0600, Rob Herring (Arm) wrote:
> 
> On Sat, 08 Mar 2025 03:42:23 +0200, Dmitry Baryshkov wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > 
> > Describe the Mobile Display SubSystem (MDSS) device present on the
> > Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
> > system level. SAR2130P features two DSI hosts and single DisplayPort
> > controller.
> > 
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > ---
> >  .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 +++++++++++++++++++++
> >  1 file changed, 445 insertions(+)
> > 
> 
> My bot found errors running 'make dt_binding_check' on your patch:
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae94000: compatible: 'oneOf' conditional failed, one must be fixed:
> 	['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
> 	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 'qcom,sm8650-dsi-ctrl']
> 	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 'qcom,mdss-dsi-ctrl']
> 	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#

It looks like the patch 2 could not be applied and was skipped. Is the
bot parsing the dependencies from the cover letter?

> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae94000: Unevaluated properties are not allowed ('compatible' was unexpected)
> 	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae96000: compatible: 'oneOf' conditional failed, one must be fixed:
> 	['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
> 	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 'qcom,sm8650-dsi-ctrl']
> 	'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 'qcom,mdss-dsi-ctrl']
> 	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae96000: Unevaluated properties are not allowed ('compatible' was unexpected)
> 	from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
> 
> doc reference errors (make refcheckdocs):
> 
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308-sar2130p-display-v1-5-1d4c30f43822 at linaro.org
> 
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.
> 
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.
> 

-- 
With best wishes
Dmitry


From 21cnbao at gmail.com  Fri Mar  7 21:41:33 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Sat, 8 Mar 2025 18:41:33 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com> <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
Message-ID: <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>

On Sat, Mar 8, 2025 at 12:03?PM Nhat Pham <nphamcs at gmail.com> wrote:
>
> On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
> >
> > This patch series introduces a new mechanism called kcompressd to
> > improve the efficiency of memory reclaiming in the operating system. The
> > main goal is to separate the tasks of page scanning and page compression
> > into distinct processes or threads, thereby reducing the load on the
> > kswapd thread and enhancing overall system performance under high memory
> > pressure conditions.
>
> Please excuse my ignorance, but from your cover letter I still don't
> quite get what is the problem here? And how would decouple compression
> and scanning help?

My understanding is as follows:

When kswapd attempts to reclaim M anonymous folios and N file folios,
the process involves the following steps:

* t1: Time to scan and unmap anonymous folios
* t2: Time to compress anonymous folios
* t3: Time to reclaim file folios

Currently, these steps are executed sequentially, meaning the total time
required to reclaim M + N folios is t1 + t2 + t3.

However, Qun-Wei's patch enables t1 + t3 and t2 to run in parallel,
reducing the total time to max(t1 + t3, t2). This likely improves the
reclamation speed, potentially reducing allocation stalls.

I don?t have concrete data on this. Does Qun-Wei have detailed
performance data?

>
> >
> > Problem:
> >  In the current system, the kswapd thread is responsible for both
> >  scanning the LRU pages and compressing pages into the ZRAM. This
> >  combined responsibility can lead to significant performance bottlenecks,
>
> What bottleneck are we talking about? Is one stage slower than the other?
>
> >  especially under high memory pressure. The kswapd thread becomes a
> >  single point of contention, causing delays in memory reclaiming and
> >  overall system performance degradation.
> >
> > Target:
> >  The target of this invention is to improve the efficiency of memory
> >  reclaiming. By separating the tasks of page scanning and page
> >  compression into distinct processes or threads, the system can handle
> >  memory pressure more effectively.
>
> I'm not a zram maintainer, so I'm definitely not trying to stop this
> patch. But whatever problem zram is facing will likely occur with
> zswap too, so I'd like to learn more :)

Right, this is likely something that could be addressed more generally
for zswap and zram.

Thanks
Barry


From wei.fang at nxp.com  Fri Mar  7 22:58:29 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Sat, 8 Mar 2025 06:58:29 +0000
Subject: [PATCH v3 net-next 01/13] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250307185902.384554a5@kernel.org>
References: <20250304072201.1332603-1-wei.fang@nxp.com>
	<20250304072201.1332603-2-wei.fang@nxp.com>
	<20250306142842.476db52c@kernel.org>
	<PAXPR04MB85107A1E5990FBB63F12C3B888D52@PAXPR04MB8510.eurprd04.prod.outlook.com>
	<PAXPR04MB8510771650890E8B7395B2DA88D42@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250307185902.384554a5@kernel.org>
Message-ID: <PAXPR04MB851024A8448430F298831ADD88D42@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Sat, 8 Mar 2025 02:05:35 +0000 Wei Fang wrote:
> > > > On Tue,  4 Mar 2025 15:21:49 +0800 Wei Fang wrote:
> > > hm..., there are some interfaces of netc-lib are used in common .c
> > > files in downstream, so I used "ifdef" in downstream. Now for the
> > > upstream, I'm going to separate them from the common .c files. So
> > > yes, we can remove it now.
> >
> > Sorry, I misread the header file. The ifdef in ntmp.h is needed
> > because the interfaces in this header file will be used by the
> > enetc-core and enetc-vf drivers. For the ENETC v1 (LS1028A platform),
> > it will not select NXP_NETC_LIB.
> 
> Meaning FSL_ENETC ? And the calls are in FSL_ENETC_CORE ?

Yes, ENETC v1 uses FSL_ENETC, and some of the functions in ntmp.h
are called in FSL_ENETC_CORE, enetc-core is common driver which
provides interfaces to ENETC (v1 and v4) PF and VF drivers.


From yunfei.dong at mediatek.com  Fri Mar  7 23:47:54 2025
From: yunfei.dong at mediatek.com (Yunfei Dong)
Date: Sat, 8 Mar 2025 15:47:54 +0800
Subject: [PATCH v8 0/3] media: mediatek: vcodec: support h264 extend vsi
Message-ID: <20250308074802.18929-1-yunfei.dong@mediatek.com>

The working buffer address start and end are calculated in kernel
side currently, the address end can't be calculated if the driver
only getting the address file handle, not the real physical address.
Need to send the extended vsi to firmware to calculate the address
end.

Re-construct some interface and add configuration to support extend
and non extend driver at the same time. Needn't to parse nal info for
extended architecture.
---
compared with v7:
- fix smatch warning for patch 2

compared with v6:
- fix the coding style for patch 2
- rewrite commit message for patch 2/3

compared with v5:
- add some parameters comment for patch 2

compared with v4:
- rebase this patch series with latest vcodec driver

compared with v3:
- change code logic with callback to decode for patch 2

compared with v2:
- squash patch 2/3/4 together
- re-write commit message for patch 1

compared with v1:
- combine some pathes together for patch 2
- re-write patch 4
---
Yunfei Dong (3):
  media: mediatek: vcodec: remove vsi operation in common interface
  media: mediatek: vcodec: support extended h264 decode
  media: mediatek: vcodec: add description for vsi struct

 .../vcodec/decoder/mtk_vcodec_dec_drv.h       |   2 +
 .../decoder/vdec/vdec_h264_req_multi_if.c     | 652 +++++++++++++++---
 2 files changed, 562 insertions(+), 92 deletions(-)

-- 
2.46.0



From yunfei.dong at mediatek.com  Fri Mar  7 23:47:55 2025
From: yunfei.dong at mediatek.com (Yunfei Dong)
Date: Sat, 8 Mar 2025 15:47:55 +0800
Subject: [PATCH v8 1/3] media: mediatek: vcodec: remove vsi operation in common interface
In-Reply-To: <20250308074802.18929-1-yunfei.dong@mediatek.com>
References: <20250308074802.18929-1-yunfei.dong@mediatek.com>
Message-ID: <20250308074802.18929-2-yunfei.dong@mediatek.com>

Extend the VSI (video shared information) struct to allow sending slice
parameters to SCP, as the parameters have changed on MT8188 architecture.
Remove VSI related information from the common interface to ensure, that
the interface is usable by architectures with and without the extended
parameters. The new VSI extensions will be introduced in later patches.

Signed-off-by: Yunfei Dong <yunfei.dong at mediatek.com>
Reviewed-by: Chen-Yu Tsai <wenst at chromium.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c    | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
index 1ed0ccec5665..ab192ce0b851 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
@@ -171,9 +171,9 @@ struct vdec_h264_slice_inst {
 };
 
 static int vdec_h264_slice_fill_decode_parameters(struct vdec_h264_slice_inst *inst,
-						  struct vdec_h264_slice_share_info *share_info)
+						  struct vdec_h264_slice_share_info *share_info,
+						  struct vdec_h264_slice_lat_dec_param *slice_param)
 {
-	struct vdec_h264_slice_lat_dec_param *slice_param = &inst->vsi->h264_slice_params;
 	const struct v4l2_ctrl_h264_decode_params *dec_params;
 	const struct v4l2_ctrl_h264_scaling_matrix *src_matrix;
 	const struct v4l2_ctrl_h264_sps *sps;
@@ -266,9 +266,6 @@ static int get_vdec_sig_decode_parameters(struct vdec_h264_slice_inst *inst)
 	mtk_vdec_h264_get_ref_list(b0_reflist, v4l2_b0_reflist, reflist_builder.num_valid);
 	mtk_vdec_h264_get_ref_list(b1_reflist, v4l2_b1_reflist, reflist_builder.num_valid);
 
-	memcpy(&inst->vsi_ctx.h264_slice_params, slice_param,
-	       sizeof(inst->vsi_ctx.h264_slice_params));
-
 	return 0;
 }
 
@@ -608,7 +605,8 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 	lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
 	v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true);
 
-	err = vdec_h264_slice_fill_decode_parameters(inst, share_info);
+	err = vdec_h264_slice_fill_decode_parameters(inst, share_info,
+						     &inst->vsi->h264_slice_params);
 	if (err)
 		goto err_free_fb_out;
 
@@ -749,6 +747,9 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
 	if (err)
 		goto err_free_fb_out;
 
+	memcpy(&inst->vsi_ctx.h264_slice_params, &inst->h264_slice_param,
+	       sizeof(inst->vsi_ctx.h264_slice_params));
+
 	buf = (unsigned char *)bs->va;
 	nal_start_idx = mtk_vdec_h264_find_start_code(buf, bs->size);
 	if (nal_start_idx < 0) {
-- 
2.46.0



From yunfei.dong at mediatek.com  Fri Mar  7 23:47:57 2025
From: yunfei.dong at mediatek.com (Yunfei Dong)
Date: Sat, 8 Mar 2025 15:47:57 +0800
Subject: [PATCH v8 3/3] media: mediatek: vcodec: add description for vsi struct
In-Reply-To: <20250308074802.18929-1-yunfei.dong@mediatek.com>
References: <20250308074802.18929-1-yunfei.dong@mediatek.com>
Message-ID: <20250308074802.18929-4-yunfei.dong@mediatek.com>

The vsi (video shared information) struct needs to be synchronized
between firmware and host, as a change that is only done in the host
version of the struct but isn't synchronized to the firmware can lead
to decoding issues with H264 bitstreams. Highlight this requirement
within the struct descriptions.

Signed-off-by: Yunfei Dong <yunfei.dong at mediatek.com>
Reviewed-by: Chen-Yu Tsai <wenst at chromium.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 .../mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c    | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
index 13d14187e4f5..5b25e1679b51 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
@@ -30,6 +30,7 @@ enum vdec_h264_core_dec_err_type {
 
 /**
  * struct vdec_h264_slice_lat_dec_param  - parameters for decode current frame
+ *	(shared data between host and firmware)
  *
  * @sps:		h264 sps syntax parameters
  * @pps:		h264 pps syntax parameters
@@ -48,7 +49,7 @@ struct vdec_h264_slice_lat_dec_param {
 };
 
 /**
- * struct vdec_h264_slice_info - decode information
+ * struct vdec_h264_slice_info - decode information (shared data between host and firmware)
  *
  * @nal_info:		nal info of current picture
  * @timeout:		Decode timeout: 1 timeout, 0 no timeout
@@ -72,7 +73,7 @@ struct vdec_h264_slice_info {
 
 /**
  * struct vdec_h264_slice_vsi - shared memory for decode information exchange
- *        between SCP and Host.
+ *        between SCP and Host (shared data between host and firmware).
  *
  * @wdma_err_addr:        wdma error dma address
  * @wdma_start_addr:      wdma start dma address
-- 
2.46.0



From yunfei.dong at mediatek.com  Fri Mar  7 23:47:56 2025
From: yunfei.dong at mediatek.com (Yunfei Dong)
Date: Sat, 8 Mar 2025 15:47:56 +0800
Subject: [PATCH v8 2/3] media: mediatek: vcodec: support extended h264 decode
In-Reply-To: <20250308074802.18929-1-yunfei.dong@mediatek.com>
References: <20250308074802.18929-1-yunfei.dong@mediatek.com>
Message-ID: <20250308074802.18929-3-yunfei.dong@mediatek.com>

Add a new extended vsi_ext struct besides the existing vsi struct, to
enable calculating the end of the address range of the current working
buffer for architectures, where simply adding the buffer size to the
start of the address range isn't sufficient.
Additionally, on extended architectures, the NAL information can be
fetched directly from the firmware, which allows skipping the parsing
step within the kernel.

Signed-off-by: Yunfei Dong <yunfei.dong at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 .../vcodec/decoder/mtk_vcodec_dec_drv.h       |   2 +
 .../decoder/vdec/vdec_h264_req_multi_if.c     | 634 +++++++++++++++---
 2 files changed, 552 insertions(+), 84 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
index ac568ed14fa2..aececca7ecf8 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
@@ -17,6 +17,7 @@
 
 #define IS_VDEC_LAT_ARCH(hw_arch) ((hw_arch) >= MTK_VDEC_LAT_SINGLE_CORE)
 #define IS_VDEC_INNER_RACING(capability) ((capability) & MTK_VCODEC_INNER_RACING)
+#define IS_VDEC_SUPPORT_EXT(capability) ((capability) & MTK_VDEC_IS_SUPPORT_EXT)
 
 enum mtk_vcodec_dec_chip_name {
 	MTK_VDEC_INVAL = 0,
@@ -42,6 +43,7 @@ enum mtk_vdec_format_types {
 	MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000,
 	MTK_VCODEC_INNER_RACING = 0x20000,
 	MTK_VDEC_IS_SUPPORT_10BIT = 0x40000,
+	MTK_VDEC_IS_SUPPORT_EXT = 0x80000,
 };
 
 /*
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
index ab192ce0b851..13d14187e4f5 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c
@@ -74,21 +74,20 @@ struct vdec_h264_slice_info {
  * struct vdec_h264_slice_vsi - shared memory for decode information exchange
  *        between SCP and Host.
  *
- * @wdma_err_addr:		wdma error dma address
- * @wdma_start_addr:		wdma start dma address
- * @wdma_end_addr:		wdma end dma address
- * @slice_bc_start_addr:	slice bc start dma address
- * @slice_bc_end_addr:		slice bc end dma address
- * @row_info_start_addr:	row info start dma address
- * @row_info_end_addr:		row info end dma address
- * @trans_start:		trans start dma address
- * @trans_end:			trans end dma address
- * @wdma_end_addr_offset:	wdma end address offset
+ * @wdma_err_addr:        wdma error dma address
+ * @wdma_start_addr:      wdma start dma address
+ * @wdma_end_addr:        wdma end dma address
+ * @slice_bc_start_addr:  slice bc start dma address
+ * @slice_bc_end_addr:    slice bc end dma address
+ * @row_info_start_addr:  row info start dma address
+ * @row_info_end_addr:    row info end dma address
+ * @trans_start:          trans start dma address
+ * @trans_end:            trans end dma address
+ * @wdma_end_addr_offset: wdma end address offset
  *
- * @mv_buf_dma:		HW working motion vector buffer
- *				dma address (AP-W, VPU-R)
- * @dec:			decode information (AP-R, VPU-W)
- * @h264_slice_params:		decode parameters for hw used
+ * @mv_buf_dma:           HW working motion vector buffer
+ * @dec:                  decode information (AP-R, VPU-W)
+ * @h264_slice_params:    decode parameters for hw used
  */
 struct vdec_h264_slice_vsi {
 	/* LAT dec addr */
@@ -112,12 +111,12 @@ struct vdec_h264_slice_vsi {
  * struct vdec_h264_slice_share_info - shared information used to exchange
  *                                     message between lat and core
  *
- * @sps:		sequence header information from user space
- * @dec_params:	decoder params from user space
- * @h264_slice_params:	decoder params used for hardware
- * @trans_start:	trans start dma address
- * @trans_end:		trans end dma address
- * @nal_info:		nal info of current picture
+ * @sps:               sequence header information from user space
+ * @dec_params:        decoder params from user space
+ * @h264_slice_params: decoder params used for hardware
+ * @trans_start:       trans start dma address
+ * @trans_end:         trans end dma address
+ * @nal_info:          nal info of current picture
  */
 struct vdec_h264_slice_share_info {
 	struct v4l2_ctrl_h264_sps sps;
@@ -128,6 +127,86 @@ struct vdec_h264_slice_share_info {
 	u16 nal_info;
 };
 
+/*
+ * struct vdec_h264_slice_mem - memory address and size
+ *        (shared data between host and firmware)
+ */
+struct vdec_h264_slice_mem {
+	union {
+		u64 buf;
+		u64 dma_addr;
+	};
+	union {
+		size_t size;
+		u64 dma_addr_end;
+	};
+};
+
+/**
+ * struct vdec_h264_slice_fb - frame buffer for decoding
+ *        (shared data between host and firmware)
+ *
+ * @y:  current luma buffer address info
+ * @c:  current chroma buffer address info
+ */
+struct vdec_h264_slice_fb {
+	struct vdec_h264_slice_mem y;
+	struct vdec_h264_slice_mem c;
+};
+
+/**
+ * struct vdec_h264_slice_info_ext - extend decode information
+ *        (shared data between host and firmware)
+ *
+ * @wdma_end_addr_offset: offset from buffer start
+ * @nal_info:             nal info of current picture
+ * @timeout:              toggles whether a decode operation is timeout
+ * @reserved:             reserved
+ * @vdec_fb_va:           vdec frame buffer struct virtual address
+ * @crc:                  displays the hardware status
+ */
+struct vdec_h264_slice_info_ext {
+	u64 wdma_end_addr_offset;
+	u16 nal_info;
+	u16 timeout;
+	u32 reserved;
+	u64 vdec_fb_va;
+	u32 crc[8];
+};
+
+/**
+ * struct vdec_h264_slice_vsi_ext - extend shared memory for decode information exchange
+ *        between SCP and Host (shared data between host and firmware).
+ *
+ * @bs:                input buffer info
+ * @fb:                current y/c buffer
+ *
+ * @ube:               buffer used to share date between lat and core
+ * @trans:             transcoded buffer used for core decode
+ * @row_info:          row info buffer
+ * @err_map:           error map buffer
+ * @slice_bc:          slice buffer
+ *
+ * @mv_buf_dma:        store hardware motion vector data
+ * @dec:               decode information (AP-R, VPU-W)
+ * @h264_slice_params: decode parameters used for the hw
+ */
+struct vdec_h264_slice_vsi_ext {
+	/* LAT dec addr */
+	struct vdec_h264_slice_mem bs;
+	struct vdec_h264_slice_fb fb;
+
+	struct vdec_h264_slice_mem ube;
+	struct vdec_h264_slice_mem trans;
+	struct vdec_h264_slice_mem row_info;
+	struct vdec_h264_slice_mem err_map;
+	struct vdec_h264_slice_mem slice_bc;
+
+	struct vdec_h264_slice_mem mv_buf_dma[H264_MAX_MV_NUM];
+	struct vdec_h264_slice_info_ext dec;
+	struct vdec_h264_slice_lat_dec_param h264_slice_params;
+};
+
 /**
  * struct vdec_h264_slice_inst - h264 decoder instance
  *
@@ -138,17 +217,21 @@ struct vdec_h264_slice_share_info {
  * @vpu:		VPU instance
  * @vsi:		vsi used for lat
  * @vsi_core:		vsi used for core
- *
- * @vsi_ctx:		Local VSI data for this decoding context
+ * @vsi_ctx:		vsi data for this decoding context
+ * @vsi_ext:		extended vsi used for lat
+ * @vsi_core_ext:	extended vsi used for core
+ * @vsi_ctx_ext:	extended vsi data for this decoding context
  * @h264_slice_param:	the parameters that hardware use to decode
  *
- * @resolution_changed:resolution changed
+ * @resolution_changed: resolution changed
  * @realloc_mv_buf:	reallocate mv buffer
  * @cap_num_planes:	number of capture queue plane
  *
  * @dpb:		decoded picture buffer used to store reference
  *			buffer information
- *@is_field_bitstream:	is field bitstream
+ * @is_field_bitstream: not support field bitstream, only support frame
+ *
+ * @decode:		lat decoder pointer for different architectures
  */
 struct vdec_h264_slice_inst {
 	unsigned int slice_dec_num;
@@ -156,10 +239,18 @@ struct vdec_h264_slice_inst {
 	struct mtk_vcodec_mem pred_buf;
 	struct mtk_vcodec_mem mv_buf[H264_MAX_MV_NUM];
 	struct vdec_vpu_inst vpu;
-	struct vdec_h264_slice_vsi *vsi;
-	struct vdec_h264_slice_vsi *vsi_core;
-
-	struct vdec_h264_slice_vsi vsi_ctx;
+	union {
+		struct {
+			struct vdec_h264_slice_vsi *vsi;
+			struct vdec_h264_slice_vsi *vsi_core;
+			struct vdec_h264_slice_vsi vsi_ctx;
+		};
+		struct {
+			struct vdec_h264_slice_vsi_ext *vsi_ext;
+			struct vdec_h264_slice_vsi_ext *vsi_core_ext;
+			struct vdec_h264_slice_vsi_ext vsi_ctx_ext;
+		};
+	};
 	struct vdec_h264_slice_lat_dec_param h264_slice_param;
 
 	unsigned int resolution_changed;
@@ -168,6 +259,9 @@ struct vdec_h264_slice_inst {
 
 	struct v4l2_h264_dpb_entry dpb[16];
 	bool is_field_bitstream;
+
+	int (*decode)(void *h_vdec, struct mtk_vcodec_mem *bs,
+		      struct vdec_fb *unused, bool *res_chg);
 };
 
 static int vdec_h264_slice_fill_decode_parameters(struct vdec_h264_slice_inst *inst,
@@ -389,68 +483,148 @@ static void vdec_h264_slice_get_crop_info(struct vdec_h264_slice_inst *inst,
 		       cr->left, cr->top, cr->width, cr->height);
 }
 
-static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
+static void vdec_h264_slice_setup_lat_buffer_ext(struct vdec_h264_slice_inst *inst,
+						 struct mtk_vcodec_mem *bs,
+						 struct vdec_lat_buf *lat_buf)
 {
-	struct vdec_h264_slice_inst *inst;
-	int err, vsi_size;
+	struct mtk_vcodec_mem *mem;
+	int i;
 
-	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
-	if (!inst)
-		return -ENOMEM;
+	inst->vsi_ext->bs.dma_addr = (u64)bs->dma_addr;
+	inst->vsi_ext->bs.size = bs->size;
 
-	inst->ctx = ctx;
+	for (i = 0; i < H264_MAX_MV_NUM; i++) {
+		mem = &inst->mv_buf[i];
+		inst->vsi_ext->mv_buf_dma[i].dma_addr = mem->dma_addr;
+		inst->vsi_ext->mv_buf_dma[i].size = mem->size;
+	}
+	inst->vsi_ext->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+	inst->vsi_ext->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
 
-	inst->vpu.id = SCP_IPI_VDEC_LAT;
-	inst->vpu.core_id = SCP_IPI_VDEC_CORE;
-	inst->vpu.ctx = ctx;
-	inst->vpu.codec_type = ctx->current_codec;
-	inst->vpu.capture_type = ctx->capture_fourcc;
+	inst->vsi_ext->row_info.dma_addr = 0;
+	inst->vsi_ext->row_info.size = 0;
 
-	err = vpu_dec_init(&inst->vpu);
-	if (err) {
-		mtk_vdec_err(ctx, "vdec_h264 init err=%d", err);
-		goto error_free_inst;
+	inst->vsi_ext->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+	inst->vsi_ext->err_map.size = lat_buf->wdma_err_addr.size;
+
+	inst->vsi_ext->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+	inst->vsi_ext->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+	inst->vsi_ext->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+	inst->vsi_ext->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+}
+
+static int vdec_h264_slice_setup_core_buffer_ext(struct vdec_h264_slice_inst *inst,
+						 struct vdec_h264_slice_share_info *share_info,
+						 struct vdec_lat_buf *lat_buf)
+{
+	struct mtk_vcodec_mem *mem;
+	struct mtk_vcodec_dec_ctx *ctx = inst->ctx;
+	struct vb2_v4l2_buffer *vb2_v4l2;
+	struct vdec_fb *fb;
+	u64 y_fb_dma, c_fb_dma = 0;
+	int i;
+
+	fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
+	if (!fb) {
+		mtk_vdec_err(ctx, "Unable to get a CAPTURE buffer for CAPTURE queue is empty.");
+		return -EBUSY;
 	}
 
-	vsi_size = round_up(sizeof(struct vdec_h264_slice_vsi), VCODEC_DEC_ALIGNED_64);
-	inst->vsi = inst->vpu.vsi;
-	inst->vsi_core =
-		(struct vdec_h264_slice_vsi *)(((char *)inst->vpu.vsi) + vsi_size);
-	inst->resolution_changed = true;
-	inst->realloc_mv_buf = true;
+	y_fb_dma = (u64)fb->base_y.dma_addr;
+	if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
+		c_fb_dma = y_fb_dma + ctx->picinfo.fb_sz[0];
+	else
+		c_fb_dma = (u64)fb->base_c.dma_addr;
 
-	mtk_vdec_debug(ctx, "lat struct size = %d,%d,%d,%d vsi: %d\n",
-		       (int)sizeof(struct mtk_h264_sps_param),
-		       (int)sizeof(struct mtk_h264_pps_param),
-		       (int)sizeof(struct vdec_h264_slice_lat_dec_param),
-		       (int)sizeof(struct mtk_h264_dpb_info),
-		       vsi_size);
-	mtk_vdec_debug(ctx, "lat H264 instance >> %p, codec_type = 0x%x",
-		       inst, inst->vpu.codec_type);
+	mtk_vdec_debug(ctx, "[h264-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, c_fb_dma);
 
-	ctx->drv_handle = inst;
-	return 0;
+	inst->vsi_core_ext->fb.y.dma_addr = y_fb_dma;
+	inst->vsi_core_ext->fb.y.size = ctx->picinfo.fb_sz[0];
+	inst->vsi_core_ext->fb.c.dma_addr = c_fb_dma;
+	inst->vsi_core_ext->fb.c.size = ctx->picinfo.fb_sz[1];
 
-error_free_inst:
-	kfree(inst);
-	return err;
+	inst->vsi_core_ext->dec.vdec_fb_va = (unsigned long)fb;
+	inst->vsi_core_ext->dec.nal_info = share_info->nal_info;
+
+	inst->vsi_core_ext->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+	inst->vsi_core_ext->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+	inst->vsi_core_ext->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+	inst->vsi_core_ext->err_map.size = lat_buf->wdma_err_addr.size;
+
+	inst->vsi_core_ext->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+	inst->vsi_core_ext->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+	inst->vsi_core_ext->row_info.dma_addr = 0;
+	inst->vsi_core_ext->row_info.size = 0;
+
+	inst->vsi_core_ext->trans.dma_addr = share_info->trans_start;
+	inst->vsi_core_ext->trans.dma_addr_end = share_info->trans_end;
+
+	for (i = 0; i < H264_MAX_MV_NUM; i++) {
+		mem = &inst->mv_buf[i];
+		inst->vsi_core_ext->mv_buf_dma[i].dma_addr = mem->dma_addr;
+		inst->vsi_core_ext->mv_buf_dma[i].size = mem->size;
+	}
+
+	vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
+
+	return 0;
 }
 
-static void vdec_h264_slice_deinit(void *h_vdec)
+static int vdec_h264_slice_core_decode_ext(struct vdec_lat_buf *lat_buf)
 {
-	struct vdec_h264_slice_inst *inst = h_vdec;
+	int err, timeout;
+	struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
+	struct vdec_h264_slice_inst *inst = ctx->drv_handle;
+	struct vdec_h264_slice_share_info *share_info = lat_buf->private_data;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
 
-	vpu_dec_deinit(&inst->vpu);
-	vdec_h264_slice_free_mv_buf(inst);
-	vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx);
+	memcpy(&inst->vsi_core_ext->h264_slice_params, &share_info->h264_slice_params,
+	       sizeof(share_info->h264_slice_params));
 
-	kfree(inst);
+	err = vdec_h264_slice_setup_core_buffer_ext(inst, share_info, lat_buf);
+	if (err)
+		goto vdec_dec_end;
+
+	vdec_h264_slice_fill_decode_reflist(inst, &inst->vsi_core_ext->h264_slice_params,
+					    share_info);
+	err = vpu_dec_core(vpu);
+	if (err) {
+		mtk_vdec_err(ctx, "core decode err=%d", err);
+		goto vdec_dec_end;
+	}
+
+	/* wait decoder done interrupt */
+	timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+					       WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
+	if (timeout)
+		mtk_vdec_err(ctx, "core decode timeout: pic_%d", ctx->decoded_frame_cnt);
+	inst->vsi_core_ext->dec.timeout = !!timeout;
+
+	vpu_dec_core_end(vpu);
+
+	/* crc is hardware checksum, can be used to check whether the decoder result is right.*/
+	mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+		       ctx->decoded_frame_cnt,
+		       inst->vsi_core_ext->dec.crc[0], inst->vsi_core_ext->dec.crc[1],
+		       inst->vsi_core_ext->dec.crc[2], inst->vsi_core_ext->dec.crc[3],
+		       inst->vsi_core_ext->dec.crc[4], inst->vsi_core_ext->dec.crc[5],
+		       inst->vsi_core_ext->dec.crc[6], inst->vsi_core_ext->dec.crc[7]);
+
+vdec_dec_end:
+	vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue, share_info->trans_end);
+	ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req);
+	mtk_vdec_debug(ctx, "core decode done err=%d", err);
+	ctx->decoded_frame_cnt++;
+	return 0;
 }
 
 static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
 {
 	struct vdec_fb *fb;
-	u64 vdec_fb_va;
 	u64 y_fb_dma, c_fb_dma;
 	int err, timeout, i;
 	struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
@@ -460,22 +634,19 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
 	struct mtk_vcodec_mem *mem;
 	struct vdec_vpu_inst *vpu = &inst->vpu;
 
-	mtk_vdec_debug(ctx, "[h264-core] vdec_h264 core decode");
 	memcpy(&inst->vsi_core->h264_slice_params, &share_info->h264_slice_params,
 	       sizeof(share_info->h264_slice_params));
 
 	fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
 	if (!fb) {
 		err = -EBUSY;
-		mtk_vdec_err(ctx, "fb buffer is NULL");
+		mtk_vdec_err(ctx, "Unable to get a CAPTURE buffer for CAPTURE queue is empty.");
 		goto vdec_dec_end;
 	}
 
-	vdec_fb_va = (unsigned long)fb;
 	y_fb_dma = (u64)fb->base_y.dma_addr;
 	if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
-		c_fb_dma =
-			y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h;
+		c_fb_dma = y_fb_dma + ctx->picinfo.fb_sz[0];
 	else
 		c_fb_dma = (u64)fb->base_c.dma_addr;
 
@@ -483,7 +654,7 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
 
 	inst->vsi_core->dec.y_fb_dma = y_fb_dma;
 	inst->vsi_core->dec.c_fb_dma = c_fb_dma;
-	inst->vsi_core->dec.vdec_fb_va = vdec_fb_va;
+	inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
 	inst->vsi_core->dec.nal_info = share_info->nal_info;
 	inst->vsi_core->wdma_start_addr =
 		lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
@@ -521,6 +692,8 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
 	inst->vsi_core->dec.timeout = !!timeout;
 
 	vpu_dec_core_end(vpu);
+
+	/* crc is hardware checksum, can be used to check whether the decoder result is right.*/
 	mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
 		       ctx->decoded_frame_cnt,
 		       inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1],
@@ -533,6 +706,7 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
 	ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req);
 	mtk_vdec_debug(ctx, "core decode done err=%d", err);
 	ctx->decoded_frame_cnt++;
+
 	return 0;
 }
 
@@ -559,6 +733,128 @@ static void vdec_h264_insert_startcode(struct mtk_vcodec_dec_dev *vcodec_dev, un
 	(*bs_size) += 4;
 }
 
+static int vdec_h264_slice_lat_decode_ext(void *h_vdec, struct mtk_vcodec_mem *bs,
+					  struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_h264_slice_inst *inst = h_vdec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	struct mtk_video_dec_buf *src_buf_info;
+	int err, timeout = 0;
+	unsigned int data[2];
+	struct vdec_lat_buf *lat_buf;
+	struct vdec_h264_slice_share_info *share_info;
+
+	if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
+				vdec_h264_slice_core_decode_ext,
+				sizeof(*share_info)))
+		return -ENOMEM;
+
+	/* bs NULL means flush decoder */
+	if (!bs) {
+		vdec_msg_queue_wait_lat_buf_full(&inst->ctx->msg_queue);
+		return vpu_dec_reset(vpu);
+	}
+
+	if (inst->is_field_bitstream)
+		return -EINVAL;
+
+	lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx);
+	if (!lat_buf) {
+		mtk_vdec_debug(inst->ctx, "failed to get lat buffer");
+		return -EAGAIN;
+	}
+	share_info = lat_buf->private_data;
+	src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
+
+	lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
+	v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true);
+
+	err = vdec_h264_slice_fill_decode_parameters(inst, share_info,
+						     &inst->vsi_ext->h264_slice_params);
+	if (err)
+		goto err_free_fb_out;
+
+	vdec_h264_insert_startcode(inst->ctx->dev, bs->va, &bs->size,
+				   &share_info->h264_slice_params.pps);
+
+	*res_chg = inst->resolution_changed;
+	if (inst->resolution_changed) {
+		mtk_vdec_debug(inst->ctx, "- resolution changed -");
+		if (inst->realloc_mv_buf) {
+			err = vdec_h264_slice_alloc_mv_buf(inst, &inst->ctx->picinfo);
+			inst->realloc_mv_buf = false;
+			if (err)
+				goto err_free_fb_out;
+		}
+		inst->resolution_changed = false;
+	}
+
+	vdec_h264_slice_setup_lat_buffer_ext(inst, bs, lat_buf);
+	mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%lx) err:0x%llx",
+		       inst->vsi_ext->ube.dma_addr, (unsigned long)inst->vsi_ext->ube.size,
+		       inst->vsi_ext->err_map.dma_addr);
+
+	mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%lx) rprt((0x%llx 0x%llx))",
+		       inst->vsi_ext->slice_bc.dma_addr,
+		       (unsigned long)inst->vsi_ext->slice_bc.size,
+		       inst->vsi_ext->trans.dma_addr, inst->vsi_ext->trans.dma_addr_end);
+
+	err = vpu_dec_start(vpu, data, 2);
+	if (err) {
+		mtk_vdec_debug(inst->ctx, "lat decode err: %d", err);
+		goto err_free_fb_out;
+	}
+
+	share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+		inst->vsi_ext->dec.wdma_end_addr_offset;
+
+	share_info->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
+	share_info->nal_info = inst->vsi_ext->dec.nal_info;
+
+	if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
+		memcpy(&share_info->h264_slice_params, &inst->vsi_ext->h264_slice_params,
+		       sizeof(share_info->h264_slice_params));
+		vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
+	}
+
+	/* wait decoder done interrupt */
+	timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+					       WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
+	if (timeout)
+		mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
+	inst->vsi_ext->dec.timeout = !!timeout;
+
+	err = vpu_dec_end(vpu);
+	if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
+		if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability))
+			vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
+		inst->slice_dec_num++;
+		mtk_vdec_err(inst->ctx, "lat dec fail: pic_%d err:%d", inst->slice_dec_num, err);
+		return -EINVAL;
+	}
+
+	share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+		inst->vsi_ext->dec.wdma_end_addr_offset;
+
+	vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans_end);
+
+	if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
+		memcpy(&share_info->h264_slice_params, &inst->vsi_ext->h264_slice_params,
+		       sizeof(share_info->h264_slice_params));
+		vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
+	}
+	mtk_vdec_debug(inst->ctx, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
+		       inst->vsi_ext->dec.crc[0], inst->vsi_ext->dec.crc[1],
+		       inst->vsi_ext->dec.crc[2]);
+
+	inst->slice_dec_num++;
+	return 0;
+err_free_fb_out:
+	vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
+	mtk_vdec_err(inst->ctx, "slice dec number: %d err: %d", inst->slice_dec_num, err);
+	return err;
+}
+
 static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 				      struct vdec_fb *fb, bool *res_chg)
 {
@@ -704,6 +1000,101 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 	return err;
 }
 
+static int vdec_h264_slice_single_decode_ext(void *h_vdec, struct mtk_vcodec_mem *bs,
+					     struct vdec_fb *unused, bool *res_chg)
+{
+	struct vdec_h264_slice_inst *inst = h_vdec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	struct mtk_video_dec_buf *src_buf_info, *dst_buf_info;
+	struct vdec_fb *fb;
+	unsigned int data[2], i;
+	u64 y_fb_dma, c_fb_dma;
+	struct mtk_vcodec_mem *mem;
+	int err;
+
+	/* bs NULL means flush decoder */
+	if (!bs)
+		return vpu_dec_reset(vpu);
+
+	fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
+	if (!fb) {
+		mtk_vdec_err(inst->ctx,
+			     "Unable to get a CAPTURE buffer for CAPTURE queue is empty.");
+		return -ENOMEM;
+	}
+
+	src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
+	dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
+
+	y_fb_dma = fb->base_y.dma_addr;
+	c_fb_dma = fb->base_c.dma_addr;
+	mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx",
+		       inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma);
+
+	inst->vsi_ctx_ext.bs.dma_addr = (u64)bs->dma_addr;
+	inst->vsi_ctx_ext.bs.size = bs->size;
+	inst->vsi_ctx_ext.fb.y.dma_addr = y_fb_dma;
+	inst->vsi_ctx_ext.fb.c.dma_addr = c_fb_dma;
+	inst->vsi_ctx_ext.dec.vdec_fb_va = (u64)(uintptr_t)fb;
+
+	v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
+				   &dst_buf_info->m2m_buf.vb, true);
+	err = get_vdec_sig_decode_parameters(inst);
+	if (err)
+		goto err_free_fb_out;
+
+	memcpy(&inst->vsi_ctx_ext.h264_slice_params, &inst->h264_slice_param,
+	       sizeof(inst->vsi_ctx_ext.h264_slice_params));
+
+	*res_chg = inst->resolution_changed;
+	if (inst->resolution_changed) {
+		mtk_vdec_debug(inst->ctx, "- resolution changed -");
+		if (inst->realloc_mv_buf) {
+			err = vdec_h264_slice_alloc_mv_buf(inst, &inst->ctx->picinfo);
+			inst->realloc_mv_buf = false;
+			if (err)
+				goto err_free_fb_out;
+		}
+		inst->resolution_changed = false;
+
+		for (i = 0; i < H264_MAX_MV_NUM; i++) {
+			mem = &inst->mv_buf[i];
+			inst->vsi_ctx_ext.mv_buf_dma[i].dma_addr = mem->dma_addr;
+		}
+	}
+
+	memcpy(inst->vpu.vsi, &inst->vsi_ctx_ext, sizeof(inst->vsi_ctx_ext));
+	err = vpu_dec_start(vpu, data, 2);
+	if (err)
+		goto err_free_fb_out;
+
+	/* wait decoder done interrupt */
+	err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+					   WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
+	if (err)
+		mtk_vdec_err(inst->ctx, "decode timeout: pic_%d", inst->ctx->decoded_frame_cnt);
+
+	inst->vsi_ext->dec.timeout = !!err;
+	err = vpu_dec_end(vpu);
+	if (err)
+		goto err_free_fb_out;
+
+	memcpy(&inst->vsi_ctx_ext, inst->vpu.vsi, sizeof(inst->vsi_ctx_ext));
+	mtk_vdec_debug(inst->ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+		       inst->ctx->decoded_frame_cnt,
+		       inst->vsi_ctx_ext.dec.crc[0], inst->vsi_ctx_ext.dec.crc[1],
+		       inst->vsi_ctx_ext.dec.crc[2], inst->vsi_ctx_ext.dec.crc[3],
+		       inst->vsi_ctx_ext.dec.crc[4], inst->vsi_ctx_ext.dec.crc[5],
+		       inst->vsi_ctx_ext.dec.crc[6], inst->vsi_ctx_ext.dec.crc[7]);
+
+	inst->ctx->decoded_frame_cnt++;
+	return 0;
+
+err_free_fb_out:
+	mtk_vdec_err(inst->ctx, "dec frame number: %d err: %d", inst->ctx->decoded_frame_cnt, err);
+	return err;
+}
+
 static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 					 struct vdec_fb *unused, bool *res_chg)
 {
@@ -723,7 +1114,8 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
 
 	fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
 	if (!fb) {
-		mtk_vdec_err(inst->ctx, "fb buffer is NULL");
+		mtk_vdec_err(inst->ctx,
+			     "Unable to get a CAPTURE buffer for CAPTURE queue is empty.");
 		return -ENOMEM;
 	}
 
@@ -807,21 +1199,95 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
 	return err;
 }
 
+static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
+{
+	struct vdec_h264_slice_inst *inst;
+	int err, vsi_size;
+	unsigned char *temp;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = SCP_IPI_VDEC_LAT;
+	inst->vpu.core_id = SCP_IPI_VDEC_CORE;
+	inst->vpu.ctx = ctx;
+	inst->vpu.codec_type = ctx->current_codec;
+	inst->vpu.capture_type = ctx->capture_fourcc;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vdec_err(ctx, "vdec_h264 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	if (IS_VDEC_SUPPORT_EXT(ctx->dev->dec_capability)) {
+		vsi_size = sizeof(struct vdec_h264_slice_vsi_ext);
+
+		vsi_size = round_up(vsi_size, VCODEC_DEC_ALIGNED_64);
+		inst->vsi_ext = inst->vpu.vsi;
+		temp = (unsigned char *)inst->vsi_ext;
+		inst->vsi_core_ext = (struct vdec_h264_slice_vsi_ext *)(temp + vsi_size);
+
+		if (inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE)
+			inst->decode = vdec_h264_slice_single_decode_ext;
+		else
+			inst->decode = vdec_h264_slice_lat_decode_ext;
+	} else {
+		vsi_size = sizeof(struct vdec_h264_slice_vsi);
+
+		vsi_size = round_up(vsi_size, VCODEC_DEC_ALIGNED_64);
+		inst->vsi = inst->vpu.vsi;
+		temp = (unsigned char *)inst->vsi;
+		inst->vsi_core = (struct vdec_h264_slice_vsi *)(temp + vsi_size);
+
+		if (inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE)
+			inst->decode = vdec_h264_slice_single_decode;
+		else
+			inst->decode = vdec_h264_slice_lat_decode;
+	}
+	inst->resolution_changed = true;
+	inst->realloc_mv_buf = true;
+
+	mtk_vdec_debug(ctx, "lat struct size = %d,%d,%d,%d vsi: %d\n",
+		       (int)sizeof(struct mtk_h264_sps_param),
+		       (int)sizeof(struct mtk_h264_pps_param),
+		       (int)sizeof(struct vdec_h264_slice_lat_dec_param),
+		       (int)sizeof(struct mtk_h264_dpb_info),
+		       vsi_size);
+	mtk_vdec_debug(ctx, "lat H264 instance >> %p, codec_type = 0x%x",
+		       inst, inst->vpu.codec_type);
+
+	ctx->drv_handle = inst;
+	return 0;
+
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static void vdec_h264_slice_deinit(void *h_vdec)
+{
+	struct vdec_h264_slice_inst *inst = h_vdec;
+
+	vpu_dec_deinit(&inst->vpu);
+	vdec_h264_slice_free_mv_buf(inst);
+	vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx);
+
+	kfree(inst);
+}
+
 static int vdec_h264_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 				  struct vdec_fb *unused, bool *res_chg)
 {
 	struct vdec_h264_slice_inst *inst = h_vdec;
-	int ret;
 
 	if (!h_vdec)
 		return -EINVAL;
 
-	if (inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE)
-		ret = vdec_h264_slice_single_decode(h_vdec, bs, unused, res_chg);
-	else
-		ret = vdec_h264_slice_lat_decode(h_vdec, bs, unused, res_chg);
-
-	return ret;
+	return inst->decode(h_vdec, bs, unused, res_chg);
 }
 
 static int vdec_h264_slice_get_param(void *h_vdec, enum vdec_get_param_type type,
-- 
2.46.0



From amadeus at jmu.edu.cn  Sat Mar  8 01:30:07 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Sat,  8 Mar 2025 17:30:07 +0800
Subject: [PATCH 0/1] arm64: dts: rockchip: rk3568: Move PCIe3 MSI to use GIC ITS
Message-ID: <20250308093008.568437-1-amadeus@jmu.edu.cn>

For a long time, rk3568's MSI-X had bugs and could only work on one node.
e.g. [    7.250882] r8125 0002:01:00.0: no MSI/MSI-X. Back to INTx.

Now the ITS of GICv3 on rk3568 has been fixed by commit b08e2f42e86b
("irqchip/gic-v3-its: Share ITS tables with a non-trusted hypervisor")
and commit 2d81e1bb6252 ("irqchip/gic-v3: Add Rockchip 3568002 erratum
workaround").

Following commit b956c9de9175 ("arm64: dts: rockchip: rk356x: Move
PCIe MSI to use GIC ITS instead of MBI"), change the PCIe3 controller's
MSI on rk3568 to use ITS, so that all MSI-X can work properly.

~# dmesg | grep -E 'GIC|ITS'
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] GIC: enabling workaround for GICv3: non-coherent attribute
[    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[    0.000000] GICv3: 320 SPIs implemented
[    0.000000] GICv3: 0 Extended SPIs implemented
[    0.000000] GICv3: MBI range [296:319]
[    0.000000] GICv3: Using MBI frame 0x00000000fd410000
[    0.000000] GICv3: GICv3 features: 16 PPIs
[    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x00000000fd460000
[    0.000000] ITS [mem 0xfd440000-0xfd45ffff]
[    0.000000] GIC: enabling workaround for ITS: Rockchip erratum RK3568002
[    0.000000] GIC: enabling workaround for ITS: non-coherent attribute
[    0.000000] ITS at 0x00000000fd440000: allocated 8192 Devices @210000 (indirect, esz 8, psz 64K, shr 0)
[    0.000000] ITS at 0x00000000fd440000: allocated 32768 Interrupt Collections @220000 (flat, esz 2, psz 64K, shr 0)
[    0.000000] ITS: using cache flushing for cmd queue
[    0.000000] GICv3: using LPI property table @0x0000000000230000
[    0.000000] GIC: using cache flushing for LPI property table
[    0.000000] GICv3: CPU0: using allocated LPI pending table @0x0000000000240000
[    0.013946] GICv3: CPU1: found redistributor 100 region 0:0x00000000fd480000
[    0.013968] GICv3: CPU1: using allocated LPI pending table @0x0000000000250000
[    0.014948] GICv3: CPU2: found redistributor 200 region 0:0x00000000fd4a0000
[    0.014968] GICv3: CPU2: using allocated LPI pending table @0x0000000000260000
[    0.015904] GICv3: CPU3: found redistributor 300 region 0:0x00000000fd4c0000
[    0.015923] GICv3: CPU3: using allocated LPI pending table @0x0000000000270000

~# lspci -v | grep MSI-X
        Capabilities: [b0] MSI-X: Enable- Count=1 Masked-
        Capabilities: [b0] MSI-X: Enable- Count=128 Masked-
        Capabilities: [b0] MSI-X: Enable+ Count=32 Masked-
        Capabilities: [b0] MSI-X: Enable- Count=128 Masked-
        Capabilities: [b0] MSI-X: Enable+ Count=32 Masked-

Chukun Pan (1):
  arm64: dts: rockchip: rk3568: Move PCIe3 MSI to use GIC ITS

 arch/arm64/boot/dts/rockchip/rk3568.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

-- 
2.25.1



From amadeus at jmu.edu.cn  Sat Mar  8 01:30:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Sat,  8 Mar 2025 17:30:08 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: rk3568: Move PCIe3 MSI to use GIC ITS
In-Reply-To: <20250308093008.568437-1-amadeus@jmu.edu.cn>
References: <20250308093008.568437-1-amadeus@jmu.edu.cn>
Message-ID: <20250308093008.568437-2-amadeus@jmu.edu.cn>

Following commit b956c9de9175 ("arm64: dts: rockchip: rk356x: Move
PCIe MSI to use GIC ITS instead of MBI"), change the PCIe3 controller's
MSI on rk3568 to use ITS, so that all MSI-X can work properly.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3568.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index 695cccbdab0f..e719a3df126c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -152,7 +152,7 @@ pcie3x1: pcie at fe270000 {
 		compatible = "rockchip,rk3568-pcie";
 		#address-cells = <3>;
 		#size-cells = <2>;
-		bus-range = <0x0 0xf>;
+		bus-range = <0x10 0x1f>;
 		clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>,
 			 <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>,
 			 <&cru CLK_PCIE30X1_AUX_NDFT>;
@@ -175,7 +175,7 @@ pcie3x1: pcie at fe270000 {
 		num-ib-windows = <6>;
 		num-ob-windows = <2>;
 		max-link-speed = <3>;
-		msi-map = <0x0 &gic 0x1000 0x1000>;
+		msi-map = <0x1000 &its 0x1000 0x1000>;
 		num-lanes = <1>;
 		phys = <&pcie30phy>;
 		phy-names = "pcie-phy";
@@ -205,7 +205,7 @@ pcie3x2: pcie at fe280000 {
 		compatible = "rockchip,rk3568-pcie";
 		#address-cells = <3>;
 		#size-cells = <2>;
-		bus-range = <0x0 0xf>;
+		bus-range = <0x20 0x2f>;
 		clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>,
 			 <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>,
 			 <&cru CLK_PCIE30X2_AUX_NDFT>;
@@ -228,7 +228,7 @@ pcie3x2: pcie at fe280000 {
 		num-ib-windows = <6>;
 		num-ob-windows = <2>;
 		max-link-speed = <3>;
-		msi-map = <0x0 &gic 0x2000 0x1000>;
+		msi-map = <0x2000 &its 0x2000 0x1000>;
 		num-lanes = <2>;
 		phys = <&pcie30phy>;
 		phy-names = "pcie-phy";
-- 
2.25.1



From sven at svenpeter.dev  Sat Mar  8 01:43:23 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 08 Mar 2025 10:43:23 +0100
Subject: [PATCH v2 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250307-spmi-v2-2-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
 <20250307-spmi-v2-2-eccdb06afb99@gmail.com>
Message-ID: <b0a29727-6569-4213-a679-21116b39b95b@app.fastmail.com>

Hi,

On Fri, Mar 7, 2025, at 21:09, Sasha Finkelstein via B4 Relay wrote:
> From: Jean-Francois Bortolotti <jeff at borto.fr>
>
> The connected PMU contains several useful nvmem cells such as RTC offset,
> boot failure counters, reboot/shutdown selector, and a few others.
> In addition M3+ machines have their USB-PD controller connected via SPMI.
>
> Signed-off-by: Jean-Francois Bortolotti <jeff at borto.fr>
> Co-developed-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
>  MAINTAINERS                          |   1 +
>  drivers/spmi/Kconfig                 |   8 ++
>  drivers/spmi/Makefile                |   1 +
>  drivers/spmi/spmi-apple-controller.c | 178 +++++++++++++++++++++++++++++++++++
>  4 files changed, 188 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 
> 271ff8110df83c2d4fe7fbbfffc0a72259460bc5..9006695261d29fbc1e15659c2b43d7afeee0b656 
> 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2254,6 +2254,7 @@ F:	drivers/nvmem/apple-efuses.c
>  F:	drivers/pinctrl/pinctrl-apple-gpio.c
>  F:	drivers/pwm/pwm-apple.c
>  F:	drivers/soc/apple/*
> +F:	drivers/spmi/spmi-apple-controller.c
>  F:	drivers/watchdog/apple_wdt.c
>  F:	include/dt-bindings/interrupt-controller/apple-aic.h
>  F:	include/dt-bindings/pinctrl/apple.h
> diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
> index 
> 73780204631463631cabcbad5bf83e8dbbee94ce..9005fa91d9f4e541403ccc7bf84e0592402ac41e 
> 100644
> --- a/drivers/spmi/Kconfig
> +++ b/drivers/spmi/Kconfig
> @@ -11,6 +11,14 @@ menuconfig SPMI
> 
>  if SPMI
> 
> +config SPMI_APPLE
> +	tristate "Apple SoC SPMI Controller platform driver"
> +	depends on ARCH_APPLE || COMPILE_TEST
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  SPMI controller present on many Apple SoCs, including the
> +	  t8103 (M1) and t600x (M1 Pro/Max).
> +
>  config SPMI_HISI3670
>  	tristate "Hisilicon 3670 SPMI Controller"
>  	select IRQ_DOMAIN_HIERARCHY
> diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
> index 
> 7f152167bb05b2c24a0f9669f60278152898eebb..38ac635645ba65aa46cb5e8a50072ed9771e229b 
> 100644
> --- a/drivers/spmi/Makefile
> +++ b/drivers/spmi/Makefile
> @@ -4,6 +4,7 @@
>  #
>  obj-$(CONFIG_SPMI)	+= spmi.o spmi-devres.o
> 
> +obj-$(CONFIG_SPMI_APPLE)	+= spmi-apple-controller.o
>  obj-$(CONFIG_SPMI_HISI3670)	+= hisi-spmi-controller.o
>  obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
>  obj-$(CONFIG_SPMI_MTK_PMIF)	+= spmi-mtk-pmif.o
> diff --git a/drivers/spmi/spmi-apple-controller.c 
> b/drivers/spmi/spmi-apple-controller.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..2d4a677aaff6b10fce80f7eacc330605674ea495
> --- /dev/null
> +++ b/drivers/spmi/spmi-apple-controller.c
> @@ -0,0 +1,178 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Apple SoC SPMI device driver
> + *
> + * Copyright The Asahi Linux Contributors
> + *
> + * Inspired by:
> + *		OpenBSD support Copyright (c) 2021 Mark Kettenis 
> <kettenis at openbsd.org>
> + *		Correllium support Copyright (C) 2021 Corellium LLC
> + *		hisi-spmi-controller.c
> + *		spmi-pmic-arb.c Copyright (c) 2021, The Linux Foundation.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +#include <linux/spmi.h>
> +
> +/* SPMI Controller Registers */
> +#define SPMI_STATUS_REG 0
> +#define SPMI_CMD_REG 0x4
> +#define SPMI_RSP_REG 0x8
> +
> +#define SPMI_RX_FIFO_EMPTY BIT(24)
> +
> +#define REG_POLL_INTERVAL 10000
> +#define REG_POLL_TIMEOUT (REG_POLL_INTERVAL * 5)

I'd either add a comment that these are in us or add a _US suffix

> +
> +struct apple_spmi {
> +	void __iomem *regs;
> +};
> +
> +#define poll_reg(spmi, reg, val, cond) \
> +	readl_poll_timeout((spmi)->regs + (reg), (val), (cond), \
> +			   REG_POLL_INTERVAL, REG_POLL_TIMEOUT)
> +
> +static inline u32 read_reg(struct apple_spmi *spmi, int offset)
> +{
> +	return readl(spmi->regs + offset);
> +}
> +
> +static inline void write_reg(u32 value, struct apple_spmi *spmi, int 
> offset)
> +{
> +	writel(value, spmi->regs + offset);
> +}
> +
> +static inline u32 apple_spmi_pack_cmd(u8 opc, u8 sid, u16 saddr, 
> size_t len)
> +{
> +	return opc | sid << 8 | saddr << 16 | (len - 1) | (1 << 15);
> +}
> +
> +/* Wait for Rx FIFO to have something */
> +static int apple_spmi_wait_rx_not_empty(struct spmi_controller *ctrl)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	int ret;
> +	u32 status;
> +
> +	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & 
> SPMI_RX_FIFO_EMPTY));
> +	if (ret) {
> +		dev_err(&ctrl->dev,
> +			"%s: Failed to wait for RX FIFO not empty\n", __func__);

__func__ is always the same here now. I'd just drop that prefix.

With that and Alyssa's remark addressed: 

Reviewed-by: Sven Peter <sven at svenpeter.dev>

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +			 u16 saddr, u8 *buf, size_t len)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
> +	u32 rsp;
> +	size_t len_read = 0;
> +	u8 i;
> +	int ret;
> +
> +	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +
> +	ret = apple_spmi_wait_rx_not_empty(ctrl);
> +	if (ret)
> +		return ret;
> +
> +	/* Discard SPMI reply status */
> +	read_reg(spmi, SPMI_RSP_REG);
> +
> +	/* Read SPMI data reply */
> +	while (len_read < len) {
> +		rsp = read_reg(spmi, SPMI_RSP_REG);
> +		i = 0;
> +		while ((len_read < len) && (i < 4)) {
> +			buf[len_read++] = ((0xff << (8 * i)) & rsp) >> (8 * i);
> +			i += 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +			  u16 saddr, const u8 *buf, size_t len)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
> +	size_t i = 0, j;
> +	int ret;
> +
> +	write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +
> +	while (i < len) {
> +		j = 0;
> +		spmi_cmd = 0;
> +		while ((j < 4) & (i < len))
> +			spmi_cmd |= buf[i++] << (j++ * 8);
> +
> +		write_reg(spmi_cmd, spmi, SPMI_CMD_REG);
> +	}
> +
> +	ret = apple_spmi_wait_rx_not_empty(ctrl);
> +	if (ret)
> +		return ret;
> +
> +	/* Discard */
> +	read_reg(spmi, SPMI_RSP_REG);
> +
> +	return 0;
> +}
> +
> +static int apple_spmi_probe(struct platform_device *pdev)
> +{
> +	struct apple_spmi *spmi;
> +	struct spmi_controller *ctrl;
> +	int ret;
> +
> +	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
> +	if (IS_ERR(ctrl))
> +		return -ENOMEM;
> +
> +	spmi = spmi_controller_get_drvdata(ctrl);
> +
> +	spmi->regs = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(spmi->regs))
> +		return PTR_ERR(spmi->regs);
> +
> +	ctrl->dev.of_node = pdev->dev.of_node;
> +
> +	ctrl->read_cmd = spmi_read_cmd;
> +	ctrl->write_cmd = spmi_write_cmd;
> +
> +	ret = devm_spmi_controller_add(&pdev->dev, ctrl);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "spmi_controller_add failed\n");
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id apple_spmi_match_table[] = {
> +	{ .compatible = "apple,spmi", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, apple_spmi_match_table);
> +
> +static struct platform_driver apple_spmi_driver = {
> +	.probe		= apple_spmi_probe,
> +	.driver		= {
> +		.name	= "apple-spmi",
> +		.of_match_table = apple_spmi_match_table,
> +	},
> +};
> +module_platform_driver(apple_spmi_driver);
> +
> +MODULE_AUTHOR("Jean-Francois Bortolotti <jeff at borto.fr>");
> +MODULE_DESCRIPTION("Apple SoC SPMI driver");
> +MODULE_LICENSE("GPL");
>
> -- 
> 2.48.1


Sven


From sven at svenpeter.dev  Sat Mar  8 01:47:18 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 08 Mar 2025 10:47:18 +0100
Subject: [PATCH v2 3/3] arm64: dts: apple: Add SPMI controller nodes
In-Reply-To: <20250307-spmi-v2-3-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
 <20250307-spmi-v2-3-eccdb06afb99@gmail.com>
Message-ID: <e7a253bf-8e8b-4845-a38f-51bc00ad677c@app.fastmail.com>

Hi,


On Fri, Mar 7, 2025, at 21:09, Sasha Finkelstein via B4 Relay wrote:
> From: Sasha Finkelstein <fnkl.kernel at gmail.com>
>
> Add device tree entries for the SPMI controller
>
> Reviewed-by: Nick Chan <towinchenmi at gmail.com>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
>  arch/arm64/boot/dts/apple/t600x-die0.dtsi | 7 +++++++
>  arch/arm64/boot/dts/apple/t8103.dtsi      | 8 ++++++++
>  arch/arm64/boot/dts/apple/t8112.dtsi      | 7 +++++++
>  3 files changed, 22 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi 
> b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> index 
> b1c875e692c8fb9c0af46a23568a7b0cd720141b..d544a35c8af414c583d38b040e1aa753902f1c93 
> 100644
> --- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> +++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
> @@ -53,6 +53,13 @@ wdt: watchdog at 2922b0000 {
>  		interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
>  	};
> 
> +	nub_spmi0: spmi at 2920a1300 {
> +		compatible = "apple,t6000-spmi", "apple,spmi";
> +		reg = <0x2 0x920a1300 0x0 0x100>;
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +	};
> +

Please keep the nodes ordered by their MMIO address.
The watchdog node above is at 2922b0000 and should come after
spmi at 2920a1300. Please also check the other nodes you're adding
here.

>  	sio_dart_0: iommu at 39b004000 {
>  		compatible = "apple,t6000-dart";
>  		reg = <0x3 0x9b004000 0x0 0x4000>;
> diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi 
> b/arch/arm64/boot/dts/apple/t8103.dtsi
> index 
> 9b0dad6b618444ac6b1c9735c50cccfc3965f947..0f03dc808cf7c6b7d71afc79dd29d368f957f979 
> 100644
> --- a/arch/arm64/boot/dts/apple/t8103.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8103.dtsi
> @@ -11,6 +11,7 @@
>  #include <dt-bindings/interrupt-controller/apple-aic.h>
>  #include <dt-bindings/interrupt-controller/irq.h>
>  #include <dt-bindings/pinctrl/apple.h>
> +#include <dt-bindings/spmi/spmi.h>
> 
>  / {
>  	compatible = "apple,t8103", "apple,arm-platform";
> @@ -604,6 +605,13 @@ pcie_pins: pcie-pins {
>  			};
>  		};
> 
> +		nub_spmi: spmi at 23d0d9300 {
> +			compatible = "apple,t8103-spmi", "apple,spmi";
> +			reg = <0x2 0x3d0d9300 0x0 0x100>;
> +			#address-cells = <2>;
> +			#size-cells = <0>;
> +		};
> +
>  		pinctrl_nub: pinctrl at 23d1f0000 {
>  			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
>  			reg = <0x2 0x3d1f0000 0x0 0x4000>;
> diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi 
> b/arch/arm64/boot/dts/apple/t8112.dtsi
> index 
> 1666e6ab250bc0be9b8318e3c8fc903ccd3f3760..fecf70eba255c668757e2edfe25a4e9e7c0d0bad 
> 100644
> --- a/arch/arm64/boot/dts/apple/t8112.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8112.dtsi
> @@ -641,6 +641,13 @@ pcie_pins: pcie-pins {
>  			};
>  		};
> 
> +		nub_spmi: spmi at 23d714000 {
> +			compatible = "apple,t8112-spmi", "apple,spmi";
> +			reg = <0x2 0x3d714000 0x0 0x100>;
> +			#address-cells = <2>;
> +			#size-cells = <0>;
> +		};
> +
>  		pinctrl_nub: pinctrl at 23d1f0000 {
>  			compatible = "apple,t8112-pinctrl", "apple,pinctrl";
>  			reg = <0x2 0x3d1f0000 0x0 0x4000>;
>
> -- 
> 2.48.1


thanks,


Sven


From sven at svenpeter.dev  Sat Mar  8 01:50:43 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 08 Mar 2025 10:50:43 +0100
Subject: [PATCH v2 1/3] dt-bindings: spmi: Add Apple SPMI controller
In-Reply-To: <20250307-spmi-v2-1-eccdb06afb99@gmail.com>
References: <20250307-spmi-v2-0-eccdb06afb99@gmail.com>
 <20250307-spmi-v2-1-eccdb06afb99@gmail.com>
Message-ID: <ff7dec26-5bf8-4c0b-af7c-76064f3386b7@app.fastmail.com>

On Fri, Mar 7, 2025, at 21:08, Sasha Finkelstein via B4 Relay wrote:
> From: Sasha Finkelstein <fnkl.kernel at gmail.com>
>
> Add bindings for the SPMI controller present on most Apple SoCs
>
> Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---

Reviewed-by: Sven Peter <sven at svenpeter.dev>



Thanks,


Sven


From sven at svenpeter.dev  Sat Mar  8 01:54:26 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 08 Mar 2025 10:54:26 +0100
Subject: [PATCH v3 0/2] iommu: apple-dart: Support the ISP DART
In-Reply-To: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
References: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
Message-ID: <baaf111d-78ff-445a-bad0-277895b34144@app.fastmail.com>

Hi,


On Fri, Mar 7, 2025, at 21:07, Sasha Finkelstein via B4 Relay wrote:
> The ISP block has 3 linked DARTs with mismatched bypass support.
> This series adds support for this setup.
>
> (The ISP driver itself is sent as a separate series
> https://lore.kernel.org/asahi/20250219-isp-v1-0-6d3e89b67c31 at gmail.com/T/ )
>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---

For the entire series:

Reviewed-by: Sven Peter <sven at svenpeter.dev>


Thanks,

Sven


From amadeus at jmu.edu.cn  Sat Mar  8 02:00:00 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Sat,  8 Mar 2025 18:00:00 +0800
Subject: [PATCH 0/1] arm64: dts: rockchip: rk356x: Move SHMEM memory to reserved memory
Message-ID: <20250308100001.572657-1-amadeus@jmu.edu.cn>

Inspired by recent rk3528 thread:
https://lore.kernel.org/lkml/20250306131016.281290-1-amadeus at jmu.edu.cn/

Nothing seems wrong:
/# dmesg | grep scmi
[    0.086456] scmi_core: SCMI protocol bus registered
[    1.519045] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
[    1.520074] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
[    1.520772] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0

Chukun Pan (1):
  arm64: dts: rockchip: rk356x: Move SHMEM memory to reserved memory

 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 25 +++++++++----------
 1 file changed, 12 insertions(+), 13 deletions(-)

-- 
2.25.1



From amadeus at jmu.edu.cn  Sat Mar  8 02:00:01 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Sat,  8 Mar 2025 18:00:01 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: rk356x: Move SHMEM memory to reserved memory
In-Reply-To: <20250308100001.572657-1-amadeus@jmu.edu.cn>
References: <20250308100001.572657-1-amadeus@jmu.edu.cn>
Message-ID: <20250308100001.572657-2-amadeus@jmu.edu.cn>

0x0 to 0xf0000000 are SDRAM memory areas where 0x10f000 is located.
So move the SHMEM memory of arm_scmi to the reserved memory node.

Fixes: a3adc0b9071d ("arm64: dts: rockchip: add core dtsi for RK3568 SoC")
Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 25 +++++++++----------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
index 4f11141ea146..fd2214b6fad4 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
@@ -174,6 +174,18 @@ psci {
 		method = "smc";
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		scmi_shmem: shmem at 10f000 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x0010f000 0x0 0x100>;
+			no-map;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
@@ -199,19 +211,6 @@ xin32k: xin32k {
 		#clock-cells = <0>;
 	};
 
-	sram at 10f000 {
-		compatible = "mmio-sram";
-		reg = <0x0 0x0010f000 0x0 0x100>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0 0x0 0x0010f000 0x100>;
-
-		scmi_shmem: sram at 0 {
-			compatible = "arm,scmi-shmem";
-			reg = <0x0 0x100>;
-		};
-	};
-
 	sata1: sata at fc400000 {
 		compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
 		reg = <0 0xfc400000 0 0x1000>;
-- 
2.25.1



From dan.carpenter at linaro.org  Sat Mar  8 03:17:00 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Sat, 8 Mar 2025 14:17:00 +0300
Subject: [bug report] net: stmmac: configure SerDes according to the
 interface mode
Message-ID: <677ffce5-0d76-4b97-abd3-1ac7608417f3@stanley.mountain>

Hello Choong Yong Liang,

Commit a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the
interface mode") from Feb 27, 2025 (linux-next), leads to the
following Smatch static checker warning:

	drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c:497 intel_tsn_lane_is_available()
	warn: missing error code? 'ret'

drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
    472 static int intel_tsn_lane_is_available(struct net_device *ndev,
    473                                        struct intel_priv_data *intel_priv)
    474 {
    475         struct stmmac_priv *priv = netdev_priv(ndev);
    476         struct pmc_ipc_cmd tmp = {};
    477         struct pmc_ipc_rbuf rbuf = {};
    478         int ret = 0, i, j;

Better to avoid initializing ret so that bug show up as uninitialized
variables.

    479         const int max_fia_regs = 5;
    480 
    481         tmp.cmd = IPC_SOC_REGISTER_ACCESS;
    482         tmp.sub_cmd = IPC_SOC_SUB_CMD_READ;
    483 
    484         for (i = 0; i < max_fia_regs; i++) {
    485                 tmp.wbuf[0] = R_PCH_FIA_15_PCR_LOS1_REG_BASE + i;
    486 
    487                 ret = intel_pmc_ipc(&tmp, &rbuf);
    488                 if (ret < 0) {
    489                         netdev_info(priv->dev, "Failed to read from PMC.\n");
    490                         return ret;
    491                 }
    492 
    493                 for (j = 0; j <= intel_priv->max_tsn_lane_regs; j++)
    494                         if ((rbuf.buf[0] >>
    495                                 (4 * (intel_priv->tsn_lane_regs[j] % 8)) &
    496                                         B_PCH_FIA_PCR_L0O) == 0xB)
--> 497                                 return ret;

This should probably be return -EINVAL, right?

    498         }
    499 
    500         return ret;

It's more clear to just return 0 for the success path.  Otherwise you
have to read the code a bit.

    501 }

regards,
dan carpenter


From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:16 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:16 +0200
Subject: [PATCH v5 07/12] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit
 conversion overhead
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>

The ropll_tmds_cfg table used to identify the configuration params for
the supported rates expects the search key, i.e. bit_rate member of
struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
Hz).  This requires multiple conversions between these units being
performed at runtime.

Improve implementation clarity and efficiency by consistently using the
Hz unit throughout driver's internal data structures and functions.
Also rename the rather misleading struct member.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
 1 file changed, 39 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 2bf525514c1991a1299265d12e1e85f66333c604..e58a01bdb3ce82d66acdcb02c06de2816288b574 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -330,7 +330,7 @@ enum dp_link_rate {
 };
 
 struct ropll_config {
-	u32 bit_rate;
+	u32 rate;
 	u8 pms_mdiv;
 	u8 pms_mdiv_afc;
 	u8 pms_pdiv;
@@ -410,45 +410,45 @@ struct rk_hdptx_phy {
 };
 
 static const struct ropll_config ropll_tmds_cfg[] = {
-	{ 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 594000000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 371250000, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 297000000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
+	{ 162000000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 185625000, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
+	{ 154000000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
+	{ 148500000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
 	  0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
+	{ 146250000, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
+	{ 119000000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
+	{ 106500000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 108000000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
+	{ 85500000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
+	{ 83500000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 92812500, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 74250000, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
+	{ 65000000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
+	{ 33750000, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
 	  1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 40000000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 27000000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
+	{ 25175000, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
 };
 
@@ -894,10 +894,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
 	regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
 }
 
-static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
+static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,
 				      struct ropll_config *cfg)
 {
-	const unsigned int fout = data_rate / 2, fref = 24000;
+	const unsigned int fout = rate / 200, fref = 24000;
 	unsigned long k = 0, lc, k_sub, lc_sub;
 	unsigned int fvco, sdc;
 	u32 mdiv, sdiv, n = 8;
@@ -967,16 +967,16 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
 }
 
 static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
-					  unsigned int rate)
+					  unsigned long rate)
 {
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
 	int i;
 
-	hdptx->rate = rate * 100;
+	hdptx->rate = rate;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].bit_rate) {
+		if (rate == ropll_tmds_cfg[i].rate) {
 			cfg = &ropll_tmds_cfg[i];
 			break;
 		}
@@ -990,8 +990,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 		}
 	}
 
-	dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
-		cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
+	dev_dbg(hdptx->dev, "%s rate=%lu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
+		__func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
 		cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
 
 	rk_hdptx_pre_power_up(hdptx);
@@ -1032,13 +1032,13 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 }
 
 static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
-					   unsigned int rate)
+					   unsigned long rate)
 {
 	rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate > HDMI14_MAX_RATE / 100) {
+	if (rate > HDMI14_MAX_RATE) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {
@@ -1091,7 +1091,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
 }
 
 static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
-				     unsigned int rate)
+				     unsigned long rate)
 {
 	enum phy_mode mode = phy_get_mode(hdptx->phy);
 	u32 status;
@@ -1409,8 +1409,8 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
 static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
-	int bus_width = phy_get_bus_width(hdptx->phy);
 	enum phy_mode mode = phy_get_mode(phy);
+	unsigned long rate;
 	int ret, lane;
 
 	/*
@@ -1418,10 +1418,10 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 	 * from the HDMI bridge driver until phy_configure_opts_hdmi
 	 * becomes available in the PHY API.
 	 */
-	unsigned int rate = bus_width & 0xfffffff;
+	rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+	rate *= 100;
 
-	dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
-		__func__, bus_width, rate);
+	dev_dbg(hdptx->dev, "%s rate=%lu\n", __func__, rate);
 
 	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
 	if (ret)
@@ -1783,7 +1783,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
+	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1804,18 +1804,17 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate)
 {
-	u32 bit_rate = rate / 100;
 	int i;
 
 	if (rate > HDMI20_MAX_RATE)
 		return rate;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+		if (rate == ropll_tmds_cfg[i].rate)
 			break;
 
 	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+	    !rk_hdptx_phy_clk_pll_calc(rate, NULL))
 		return -EINVAL;
 
 	return rate;
@@ -1826,7 +1825,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
 }
 
 static const struct clk_ops hdptx_phy_clk_ops = {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:10 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:10 +0200
Subject: [PATCH v5 01/12] phy: Add HDMI configuration options
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-1-35087287f9d1@collabora.com>

From: Sandor Yu <Sandor.yu at nxp.com>

Allow HDMI PHYs to be configured through the generic
functions through a custom structure added to the generic union.

The parameters added here are based on HDMI PHY
implementation practices.  The current set of parameters
should cover the potential users.

Signed-off-by: Sandor Yu <Sandor.yu at nxp.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Acked-by: Vinod Koul <vkoul at kernel.org>
Link: https://lore.kernel.org/r/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 19 +++++++++++++++++++
 include/linux/phy/phy.h      |  7 ++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a696922bc7f29af63d88646701b2c0fcee5c885
--- /dev/null
+++ b/include/linux/phy/phy-hdmi.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2022,2024 NXP
+ */
+
+#ifndef __PHY_HDMI_H_
+#define __PHY_HDMI_H_
+
+/**
+ * struct phy_configure_opts_hdmi - HDMI configuration set
+ * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ *
+ * This structure is used to represent the configuration state of a HDMI phy.
+ */
+struct phy_configure_opts_hdmi {
+	unsigned long long tmds_char_rate;
+};
+
+#endif /* __PHY_HDMI_H_ */
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 03cd5bae92d3f189d739c453fe4c160dd2a5063e..4ac486b101fe4023b8f2a84e907e65a0ff0a5ede 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <linux/phy/phy-dp.h>
+#include <linux/phy/phy-hdmi.h>
 #include <linux/phy/phy-lvds.h>
 #include <linux/phy/phy-mipi-dphy.h>
 
@@ -42,7 +43,8 @@ enum phy_mode {
 	PHY_MODE_MIPI_DPHY,
 	PHY_MODE_SATA,
 	PHY_MODE_LVDS,
-	PHY_MODE_DP
+	PHY_MODE_DP,
+	PHY_MODE_HDMI,
 };
 
 enum phy_media {
@@ -60,11 +62,14 @@ enum phy_media {
  *		the DisplayPort protocol.
  * @lvds:	Configuration set applicable for phys supporting
  *		the LVDS phy mode.
+ * @hdmi:	Configuration set applicable for phys supporting
+ *		the HDMI phy mode.
  */
 union phy_configure_opts {
 	struct phy_configure_opts_mipi_dphy	mipi_dphy;
 	struct phy_configure_opts_dp		dp;
 	struct phy_configure_opts_lvds		lvds;
+	struct phy_configure_opts_hdmi		hdmi;
 };
 
 /**

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:11 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:11 +0200
Subject: [PATCH v5 02/12] phy: hdmi: Add color depth configuration
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-2-35087287f9d1@collabora.com>

Extend the HDMI configuration options to allow managing bits per color
channel.  This is required by some PHY drivers such as
rockchip-samsung-hdptx.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
index 6a696922bc7f29af63d88646701b2c0fcee5c885..f0ec963c6e84f1b7728acafc824dff191c6b873d 100644
--- a/include/linux/phy/phy-hdmi.h
+++ b/include/linux/phy/phy-hdmi.h
@@ -9,11 +9,13 @@
 /**
  * struct phy_configure_opts_hdmi - HDMI configuration set
  * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ * @bpc: Bits per color channel.
  *
  * This structure is used to represent the configuration state of a HDMI phy.
  */
 struct phy_configure_opts_hdmi {
 	unsigned long long tmds_char_rate;
+	unsigned int bpc;
 };
 
 #endif /* __PHY_HDMI_H_ */

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:09 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:09 +0200
Subject: [PATCH v5 00/12] phy: rockchip: samsung-hdptx: Support high color
 depth management
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>

This series relies on the new HDMI PHY configuration options [1] (patch
included here for convenience) to provide high color depth management
for rockchip-samsung-hdptx, and to introduce a proper solution to setup
the TMDS character rate on this PHY.

[1] https://lore.kernel.org/lkml/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com/

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
Changes in v5:
- Moved the patch eliminating the unnecessary and rather confusing
  Hz<->hHz unit conversion before all the others adding new content
- Moved the patch adding high color depth management to the last
  position, so that it follows the internal rate handling optimization
- Amended description for a few patches to improve clarity
- Performed some trivial refactoring in some cases while dealing with
  rebase conflicts
- Link to v4: https://lore.kernel.org/r/20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7 at collabora.com

Changes in v4:
- Added patches to drop unnecessary phy_cfg & cfgs driver data
- Embedded struct phy_configure_opts_hdmi in driver data (Dmitry)
- Added new patch to provide config params validation support
- Provided a patch to restrict altering TMDS char rate via CCF (Dmitry)
- Made a bunch of small tweaks here and there
- Link to v3: https://lore.kernel.org/r/20250223-phy-sam-hdptx-bpc-v3-0-66a5c8e68327 at collabora.com

Changes in v3:
- Rebased series onto next-20250221 and fixed several conflicts due to
  the recently introduced eDP support
- Link to v2: https://lore.kernel.org/r/20241212-phy-sam-hdptx-bpc-v2-0-57e672c7c7c4 at collabora.com

Changes in v2:
- Added new patches providing a bug fix and several driver cleanups and
  improvements
- Link to v1: https://lore.kernel.org/r/20241207-phy-sam-hdptx-bpc-v1-0-03c2e4d6d797 at collabora.com

---
Cristian Ciocaltea (11):
      phy: hdmi: Add color depth configuration
      phy: rockchip: samsung-hdptx: Fix clock ratio setup
      phy: rockchip: samsung-hdptx: Drop unused struct lcpll_config
      phy: rockchip: samsung-hdptx: Drop unused phy_cfg driver data
      phy: rockchip: samsung-hdptx: Drop superfluous cfgs driver data
      phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit conversion overhead
      phy: rockchip: samsung-hdptx: Setup TMDS char rate via phy_configure_opts_hdmi
      phy: rockchip: samsung-hdptx: Provide config params validation support
      phy: rockchip: samsung-hdptx: Restrict altering TMDS char rate via CCF
      phy: rockchip: samsung-hdptx: Optimize internal rate handling
      phy: rockchip: samsung-hdptx: Add high color depth management

Sandor Yu (1):
      phy: Add HDMI configuration options

 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 292 +++++++++++++---------
 include/linux/phy/phy-hdmi.h                      |  21 ++
 include/linux/phy/phy.h                           |   7 +-
 3 files changed, 202 insertions(+), 118 deletions(-)
---
base-commit: cd3215bbcb9d4321def93fea6cfad4d5b42b9d1d
change-id: 20241206-phy-sam-hdptx-bpc-3b05c6276fd7



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:12 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:12 +0200
Subject: [PATCH v5 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>

The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
and not before.

While at it, introduce a define for this rate limit constant.

Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -320,6 +320,7 @@
 #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
 #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
 
+#define HDMI14_MAX_RATE			340000000
 #define HDMI20_MAX_RATE			600000000
 
 enum dp_link_rate {
@@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate >= 3400000) {
+	if (rate > HDMI14_MAX_RATE / 100) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:13 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:13 +0200
Subject: [PATCH v5 04/12] phy: rockchip: samsung-hdptx: Drop unused struct
 lcpll_config
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-4-35087287f9d1@collabora.com>

This is just a leftover from downstream support for HDMI 2.1.
Remove the unused struct for now.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -----------------------
 1 file changed, 31 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index cf2c3a46604cb9d8c26fe5ec8346904e0b62848f..f9b5c96d6c789e435657e224032d35b5a6950945 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -329,37 +329,6 @@ enum dp_link_rate {
 	DP_BW_HBR2,
 };
 
-struct lcpll_config {
-	u32 bit_rate;
-	u8 lcvco_mode_en;
-	u8 pi_en;
-	u8 clk_en_100m;
-	u8 pms_mdiv;
-	u8 pms_mdiv_afc;
-	u8 pms_pdiv;
-	u8 pms_refdiv;
-	u8 pms_sdiv;
-	u8 pi_cdiv_rstn;
-	u8 pi_cdiv_sel;
-	u8 sdm_en;
-	u8 sdm_rstn;
-	u8 sdc_frac_en;
-	u8 sdc_rstn;
-	u8 sdm_deno;
-	u8 sdm_num_sign;
-	u8 sdm_num;
-	u8 sdc_n;
-	u8 sdc_n2;
-	u8 sdc_num;
-	u8 sdc_deno;
-	u8 sdc_ndiv_rstn;
-	u8 ssc_en;
-	u8 ssc_fm_dev;
-	u8 ssc_fm_freq;
-	u8 ssc_clk_div_sel;
-	u8 cd_tx_ser_rate_sel;
-};
-
 struct ropll_config {
 	u32 bit_rate;
 	u8 pms_mdiv;

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:14 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:14 +0200
Subject: [PATCH v5 05/12] phy: rockchip: samsung-hdptx: Drop unused phy_cfg
 driver data
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-5-35087287f9d1@collabora.com>

There is no usage of phy_cfg in the upstream driver data, nor in the
downstream one, hence remove it.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index f9b5c96d6c789e435657e224032d35b5a6950945..06644c3d98d3f8b697fc704704df5acdd3c85bad 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -397,7 +397,6 @@ struct rk_hdptx_phy {
 	int phy_id;
 
 	struct phy *phy;
-	struct phy_config *phy_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:15 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:15 +0200
Subject: [PATCH v5 06/12] phy: rockchip: samsung-hdptx: Drop superfluous
 cfgs driver data
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-6-35087287f9d1@collabora.com>

The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
but it is only used during probe() in order to setup ->phy_id.

Use a probe() local variable to store device match data and remove the
now unnecessary member from struct rk_hdptx_phy.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 06644c3d98d3f8b697fc704704df5acdd3c85bad..2bf525514c1991a1299265d12e1e85f66333c604 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -392,10 +392,7 @@ struct rk_hdptx_phy {
 	struct regmap *regmap;
 	struct regmap *grf;
 
-	/* PHY const config */
-	const struct rk_hdptx_phy_cfg *cfgs;
 	int phy_id;
-
 	struct phy *phy;
 	struct clk_bulk_data *clks;
 	int nr_clks;
@@ -1892,6 +1889,7 @@ static int rk_hdptx_phy_runtime_resume(struct device *dev)
 
 static int rk_hdptx_phy_probe(struct platform_device *pdev)
 {
+	const struct rk_hdptx_phy_cfg *cfgs;
 	struct phy_provider *phy_provider;
 	struct device *dev = &pdev->dev;
 	struct rk_hdptx_phy *hdptx;
@@ -1910,14 +1908,14 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(regs),
 				     "Failed to ioremap resource\n");
 
-	hdptx->cfgs = device_get_match_data(dev);
-	if (!hdptx->cfgs)
+	cfgs = device_get_match_data(dev);
+	if (!cfgs)
 		return dev_err_probe(dev, -EINVAL, "missing match data\n");
 
 	/* find the phy-id from the io address */
 	hdptx->phy_id = -ENODEV;
-	for (id = 0; id < hdptx->cfgs->num_phys; id++) {
-		if (res->start == hdptx->cfgs->phy_ids[id]) {
+	for (id = 0; id < cfgs->num_phys; id++) {
+		if (res->start == cfgs->phy_ids[id]) {
 			hdptx->phy_id = id;
 			break;
 		}

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:17 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:17 +0200
Subject: [PATCH v5 08/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-8-35087287f9d1@collabora.com>

The current workaround to setup the TMDS character rate relies on the
unconventional usage of phy_set_bus_width().

Make use of the recently introduced HDMI PHY configuration API to
properly handle the setup.  The workaround will be dropped as soon as
the switch has been completed on both ends.

Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
HDMI parameters during phy_configure().

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 +++++++++++++++++------
 1 file changed, 47 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index e58a01bdb3ce82d66acdcb02c06de2816288b574..04c344394cbea89150bc4432cf26530fa9d71678 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -394,6 +394,7 @@ struct rk_hdptx_phy {
 
 	int phy_id;
 	struct phy *phy;
+	struct phy_configure_opts_hdmi hdmi_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];
@@ -1410,20 +1411,24 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
 	enum phy_mode mode = phy_get_mode(phy);
-	unsigned long rate;
 	int ret, lane;
 
-	/*
-	 * FIXME: Temporary workaround to pass pixel_clk_rate
-	 * from the HDMI bridge driver until phy_configure_opts_hdmi
-	 * becomes available in the PHY API.
-	 */
-	rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
-	rate *= 100;
+	if (mode != PHY_MODE_DP) {
+		if (!hdptx->hdmi_cfg.tmds_char_rate) {
+			/*
+			 * FIXME: Temporary workaround to setup TMDS char rate
+			 * from the RK DW HDMI QP bridge driver.
+			 * Will be removed as soon the switch to the HDMI PHY
+			 * configuration API has been completed on both ends.
+			 */
+			hdptx->hdmi_cfg.tmds_char_rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+			hdptx->hdmi_cfg.tmds_char_rate *= 100;
+		}
 
-	dev_dbg(hdptx->dev, "%s rate=%lu\n", __func__, rate);
+		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+	}
 
-	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
+	ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
 	if (ret)
 		return ret;
 
@@ -1454,7 +1459,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		regmap_write(hdptx->grf, GRF_HDPTX_CON0,
 			     HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
 
-		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
 		if (ret)
 			rk_hdptx_phy_consumer_put(hdptx, true);
 	}
@@ -1469,8 +1474,27 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
 	return rk_hdptx_phy_consumer_put(hdptx, false);
 }
 
-static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
-				      struct phy_configure_opts_dp *dp)
+static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
+					   struct phy_configure_opts_hdmi *hdmi)
+{
+	int i;
+
+	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+		if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
+			break;
+
+	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
+	    !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rk_hdptx_phy_verify_dp_config(struct rk_hdptx_phy *hdptx,
+					 struct phy_configure_opts_dp *dp)
 {
 	int i;
 
@@ -1730,12 +1754,18 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	enum phy_mode mode = phy_get_mode(phy);
 	int ret;
 
-	if (mode != PHY_MODE_DP)
-		return 0;
+	if (mode != PHY_MODE_DP) {
+		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+		if (ret)
+			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
+		else
+			hdptx->hdmi_cfg = opts->hdmi;
+		return ret;
+	}
 
-	ret = rk_hdptx_phy_verify_config(hdptx, &opts->dp);
+	ret = rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
 	if (ret) {
-		dev_err(hdptx->dev, "invalid params for phy configure\n");
+		dev_err(hdptx->dev, "invalid dp params for phy configure\n");
 		return ret;
 	}
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:21 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:21 +0200
Subject: [PATCH v5 12/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-12-35087287f9d1@collabora.com>

Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 98f831c3704f5cd65dcf29a4f0a12862a4aa0482..d115a026f013fdbcd025626bccaa30639856fad7 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1028,6 +1028,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
 			   FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
 
+	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+			   FIELD_PREP(PLL_PCG_CLK_SEL_MASK, (hdptx->hdmi_cfg.bpc - 8) >> 1));
+
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
@@ -1427,7 +1430,8 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 			hdptx->hdmi_cfg.tmds_char_rate *= 100;
 		}
 
-		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+		dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 	}
 
 	ret = rk_hdptx_phy_consumer_get(hdptx);
@@ -1492,6 +1496,19 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 	    !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
 		return -EINVAL;
 
+	if (!hdmi->bpc)
+		hdmi->bpc = 8;
+
+	switch (hdmi->bpc) {
+	case 8:
+	case 10:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	};
+
 	return 0;
 }
 
@@ -1764,6 +1781,9 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 			hdptx->hdmi_cfg = opts->hdmi;
 			hdptx->restrict_rate_change = true;
 		}
+
+		dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 		return ret;
 	}
 
@@ -1972,6 +1992,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hdptx->dev = dev;
+	hdptx->hdmi_cfg.bpc = 8;
 
 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(regs))

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:18 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:18 +0200
Subject: [PATCH v5 09/12] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-9-35087287f9d1@collabora.com>

Implement the phy_ops.validate() callback to allow checking the PHY
configuration parameters without actually applying them.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 04c344394cbea89150bc4432cf26530fa9d71678..0e1391b4c8bdb9cd0facfc80999929700579d667 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1797,10 +1797,22 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	return 0;
 }
 
+static int rk_hdptx_phy_validate(struct phy *phy, enum phy_mode mode,
+				 int submode, union phy_configure_opts *opts)
+{
+	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+
+	if (mode != PHY_MODE_DP)
+		return rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+
+	return rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
+}
+
 static const struct phy_ops rk_hdptx_phy_ops = {
 	.power_on  = rk_hdptx_phy_power_on,
 	.power_off = rk_hdptx_phy_power_off,
 	.configure = rk_hdptx_phy_configure,
+	.validate  = rk_hdptx_phy_validate,
 	.owner	   = THIS_MODULE,
 };
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:19 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:19 +0200
Subject: [PATCH v5 10/12] phy: rockchip: samsung-hdptx: Restrict altering
 TMDS char rate via CCF
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-10-35087287f9d1@collabora.com>

Although, in theory, the clock provider functionality could be enabled
as a standalone driver feature, in practice it is unlikely that it would
be ever needed separately from the common PHY related features, i.e.
making use of the PHY PLL as an alternative and more accurate clock
source for display modes handling.  Which means the PLL will be always
programmed according to the TMDS char rate set via the HDMI PHY
configuration API.

Currently it's possible to freely adjust the rate via the clock API as
well, that is through clk_set_rate().  Making the clock read-only is not
feasible since we need to ensure any rate update done via the PHY
configuration API has been actually programmed into the hardware before
CCF accesses it.  This would be normally done during phy_ops.power_on()
or clk_ops.prepare() callbacks, but it might happen that the former gets
fired too late and the latter only once, hence we need to keep handle it
via clk_ops.set_rate() as a fallback approach.

Prevent changing the TMDS character rate via CCF by letting
rk_hdptx_phy_clk_round_rate() always return the value set via
phy_configure().  To avoid breaking existing users, i.e. RK DW HDMI QP
bridge driver, until the switch to the HDMI PHY config based approach is
completed, introduce a temporary exception to the rule, toggled via the
new ->restrict_rate_change flag, which indicates whether phy_configure()
has been called or not.

Additionally, revert any unlikely rate change that might have occurred
between the calls to ->round_rate() and ->set_rate().

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 52 +++++++++++++++++------
 1 file changed, 40 insertions(+), 12 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 0e1391b4c8bdb9cd0facfc80999929700579d667..a62c634f5254e742088515c3b21c05f95acbaded 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -402,6 +402,7 @@ struct rk_hdptx_phy {
 	/* clk provider */
 	struct clk_hw hw;
 	unsigned long rate;
+	bool restrict_rate_change;
 
 	atomic_t usage_count;
 
@@ -1756,10 +1757,12 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 
 	if (mode != PHY_MODE_DP) {
 		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
-		if (ret)
+		if (ret) {
 			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
-		else
+		} else {
 			hdptx->hdmi_cfg = opts->hdmi;
+			hdptx->restrict_rate_change = true;
+		}
 		return ret;
 	}
 
@@ -1846,20 +1849,31 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate)
 {
-	int i;
+	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	if (rate > HDMI20_MAX_RATE)
-		return rate;
+	/*
+	 * FIXME: Temporarily allow altering TMDS char rate via CCF.
+	 * To be dropped as soon as the RK DW HDMI QP bridge driver
+	 * switches to make use of phy_configure().
+	 */
+	if (!hdptx->restrict_rate_change && rate != hdptx->hdmi_cfg.tmds_char_rate) {
+		struct phy_configure_opts_hdmi hdmi = {
+			.tmds_char_rate = rate,
+		};
+		int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi);
 
-	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].rate)
-			break;
+		if (ret)
+			return ret;
 
-	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(rate, NULL))
-		return -EINVAL;
+		hdptx->hdmi_cfg = hdmi;
+	}
 
-	return rate;
+	/*
+	 * The TMDS char rate shall be adjusted via phy_configure() only,
+	 * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
+	 * a different rate argument.
+	 */
+	return hdptx->hdmi_cfg.tmds_char_rate;
 }
 
 static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1867,6 +1881,20 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
+	/* Revert any unlikely TMDS char rate change since round_rate() */
+	if (hdptx->hdmi_cfg.tmds_char_rate != rate) {
+		dev_warn(hdptx->dev, "Reverting unexpected rate change from %lu to %llu\n",
+			 rate, hdptx->hdmi_cfg.tmds_char_rate);
+		hdptx->hdmi_cfg.tmds_char_rate = rate;
+	}
+
+	/*
+	 * The TMDS char rate would be normally programmed in HW during
+	 * phy_ops.power_on() or clk_ops.prepare() callbacks, but it might
+	 * happen that the former gets fired too late, i.e. after this call,
+	 * while the latter being executed only once, i.e. when clock remains
+	 * in the prepared state during rate changes.
+	 */
 	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
 }
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Sat Mar  8 04:21:20 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sat, 08 Mar 2025 14:21:20 +0200
Subject: [PATCH v5 11/12] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
Message-ID: <20250308-phy-sam-hdptx-bpc-v5-11-35087287f9d1@collabora.com>

Drop the rate parameter from a bunch of internal helpers and, instead,
make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
data.

Additionally, rename the rather ambiguous ->rate member of struct
rk_hdptx_phy to ->hw_rate and ensure rk_hdptx_ropll_tmds_cmn_config()
updates it only after all the other operations have been successful.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 59 ++++++++++++-----------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index a62c634f5254e742088515c3b21c05f95acbaded..98f831c3704f5cd65dcf29a4f0a12862a4aa0482 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -401,7 +401,7 @@ struct rk_hdptx_phy {
 
 	/* clk provider */
 	struct clk_hw hw;
-	unsigned long rate;
+	unsigned long hw_rate;
 	bool restrict_rate_change;
 
 	atomic_t usage_count;
@@ -968,33 +968,34 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,
 	return true;
 }
 
-static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
-					  unsigned long rate)
+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 {
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
-	int i;
+	int ret, i;
 
-	hdptx->rate = rate;
+	if (!hdptx->hdmi_cfg.tmds_char_rate)
+		return 0;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].rate) {
+		if (hdptx->hdmi_cfg.tmds_char_rate == ropll_tmds_cfg[i].rate) {
 			cfg = &ropll_tmds_cfg[i];
 			break;
 		}
 
 	if (!cfg) {
-		if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
-			cfg = &rc;
-		} else {
-			dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+		if (!rk_hdptx_phy_clk_pll_calc(hdptx->hdmi_cfg.tmds_char_rate, &rc)) {
+			dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%llu\n",
+				__func__, hdptx->hdmi_cfg.tmds_char_rate);
 			return -EINVAL;
 		}
+
+		cfg = &rc;
 	}
 
-	dev_dbg(hdptx->dev, "%s rate=%lu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
-		__func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
-		cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
+	dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
+		__func__, hdptx->hdmi_cfg.tmds_char_rate, cfg->pms_mdiv, cfg->pms_sdiv + 1,
+		cfg->sdm_en, cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
 
 	rk_hdptx_pre_power_up(hdptx);
 
@@ -1030,17 +1031,20 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
-	return rk_hdptx_post_enable_pll(hdptx);
+	ret = rk_hdptx_post_enable_pll(hdptx);
+	if (!ret)
+		hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate;
+
+	return ret;
 }
 
-static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
-					   unsigned long rate)
+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx)
 {
 	rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate > HDMI14_MAX_RATE) {
+	if (hdptx->hdmi_cfg.tmds_char_rate > HDMI14_MAX_RATE) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {
@@ -1092,8 +1096,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
 		     HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
 }
 
-static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
-				     unsigned long rate)
+static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
 {
 	enum phy_mode mode = phy_get_mode(hdptx->phy);
 	u32 status;
@@ -1112,11 +1115,9 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
 	if (mode == PHY_MODE_DP) {
 		rk_hdptx_dp_reset(hdptx);
 	} else {
-		if (rate) {
-			ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
-			if (ret)
-				goto dec_usage;
-		}
+		ret = rk_hdptx_ropll_tmds_cmn_config(hdptx);
+		if (ret)
+			goto dec_usage;
 	}
 
 	return 0;
@@ -1429,7 +1430,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
 	}
 
-	ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+	ret = rk_hdptx_phy_consumer_get(hdptx);
 	if (ret)
 		return ret;
 
@@ -1460,7 +1461,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		regmap_write(hdptx->grf, GRF_HDPTX_CON0,
 			     HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
 
-		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+		ret = rk_hdptx_ropll_tmds_mode_config(hdptx);
 		if (ret)
 			rk_hdptx_phy_consumer_put(hdptx, true);
 	}
@@ -1828,7 +1829,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
+	return rk_hdptx_phy_consumer_get(hdptx);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1843,7 +1844,7 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return hdptx->rate;
+	return hdptx->hw_rate;
 }
 
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -1895,7 +1896,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	 * while the latter being executed only once, i.e. when clock remains
 	 * in the prepared state during rate changes.
 	 */
-	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
+	return rk_hdptx_ropll_tmds_cmn_config(hdptx);
 }
 
 static const struct clk_ops hdptx_phy_clk_ops = {

-- 
2.48.1



From yunshenglin0825 at gmail.com  Sat Mar  8 04:33:44 2025
From: yunshenglin0825 at gmail.com (Yunsheng Lin)
Date: Sat, 8 Mar 2025 20:33:44 +0800
Subject: [PATCH net-next v11 0/4] fix the DMA API misuse problem for
 page_pool
In-Reply-To: <87v7slvsed.fsf@toke.dk>
References: <20250307092356.638242-1-linyunsheng@huawei.com>
 <87v7slvsed.fsf@toke.dk>
Message-ID: <40b33879-509a-4c4a-873b-b5d3573b6e14@gmail.com>

On 3/7/2025 10:15 PM, Toke H?iland-J?rgensen wrote:

...

> 
> You are making this incredibly complicated. You've basically implemented
> a whole new slab allocator for those page_pool_item objects, and you're
> tracking every page handed out by the page pool instead of just the ones
> that are DMA-mapped. None of this is needed.
 > > I took a stab at implementing the xarray-based tracking first suggested
> by Mina[0]:

I did discuss Mina' suggestion with Ilias below in case you didn't
notice:
https://lore.kernel.org/all/0ef315df-e8e9-41e8-9ba8-dcb69492c616 at huawei.com/

Anyway, It is great that you take the effort to actually implement
the idea to have some more concrete comparison here.

> 
> https://git.kernel.org/toke/c/e87e0edf9520
> 
> And, well, it's 50 lines of extra code, none of which are in the fast
> path.

I wonder what is the overhead for the xarray idea regarding the
time_bench_page_pool03_slow() testcase before we begin to discuss
if xarray idea is indeed possible.

> 
> Jesper has kindly helped with testing that it works for normal packet
> processing, but I haven't yet verified that it resolves the original
> crash. Will post the patch to the list once I have verified this (help
> welcome!).

RFC seems like a good way to show and discuss the basic idea.

I only took a glance at git code above, it seems reusing the
_pp_mapping_pad for pp_dma_index seems like a wrong direction
as mentioned in discussion with Ilias above as the field might
be used when a page is mmap'ed to user space, and reusing that
field in 'struct page' seems to disable the tcp_zerocopy feature,
see the below commit from Eric:
https://github.com/torvalds/linux/commit/577e4432f3ac810049cb7e6b71f4d96ec7c6e894

Also, I am not sure if a page_pool owned page can be spliced into the fs
subsystem yet, but if it does, I am not sure how is reusing the
page->mapping possible if that page is called in __filemap_add_folio()?

https://elixir.bootlin.com/linux/v6.14-rc5/source/mm/filemap.c#L882

> 
> -Toke
> 
> [0] https://lore.kernel.org/all/CAHS8izPg7B5DwKfSuzz-iOop_YRbk3Sd6Y4rX7KBG9DcVJcyWg at mail.gmail.com/
> 
> 



From ziyao at disroot.org  Sat Mar  8 06:05:53 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat, 8 Mar 2025 14:05:53 +0000
Subject: [PATCH v2 7/8] arm64: dts: rockchip: Add SDMMC/SDIO controllers
 for RK3528
In-Reply-To: <56181131-3e48-4c76-87c7-2388a9964727@kwiboo.se>
References: <20250305194217.47052-1-ziyao@disroot.org>
 <20250305194612.47171-1-ziyao@disroot.org>
 <56181131-3e48-4c76-87c7-2388a9964727@kwiboo.se>
Message-ID: <Z8xOwbfNqBfkRAi6@pie>

On Sat, Mar 08, 2025 at 12:22:48AM +0100, Jonas Karlman wrote:
> Hi Yao Zi,
> 
> On 2025-03-05 20:46, Yao Zi wrote:
> > RK3528 features two SDIO controllers and one SD/MMC controller, describe
> > them in devicetree. Since their sample and drive clocks are located in
> > the VO and VPU GRFs, corresponding syscons are added to make these
> > clocks available.
> > 
> > Signed-off-by: Yao Zi <ziyao at disroot.org>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 70 ++++++++++++++++++++++++
> >  1 file changed, 70 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > index d3e2a64ff2d5..363023314e9c 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > @@ -130,6 +130,16 @@ gic: interrupt-controller at fed01000 {
> >  			#interrupt-cells = <3>;
> >  		};
> >  
> > +		vpu_grf: syscon at ff340000 {
> > +			compatible = "rockchip,rk3528-vpu-grf", "syscon";
> > +			reg = <0x0 0xff340000 0x0 0x8000>;
> > +		};
> > +
> > +		vo_grf: syscon at ff360000 {
> > +			compatible = "rockchip,rk3528-vo-grf", "syscon";
> > +			reg = <0x0 0xff360000 0x0 0x10000>;
> > +		};
> > +
> >  		cru: clock-controller at ff4a0000 {
> >  			compatible = "rockchip,rk3528-cru";
> >  			reg = <0x0 0xff4a0000 0x0 0x30000>;
> > @@ -274,6 +284,66 @@ saradc: adc at ffae0000 {
> >  			resets = <&cru SRST_P_SARADC>;
> >  			reset-names = "saradc-apb";
> >  			#io-channel-cells = <1>;
> > +		};
> 
> Look like this patch accidentally drops status = "disabled" from the
> adc at ffae0000 node.

It's a mistake during rebasing, I'll fix it in v3.

> Regards,
> Jonas

Thanks,
Yao Zi


From konrad.dybcio at oss.qualcomm.com  Sat Mar  8 06:17:23 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Sat, 8 Mar 2025 15:17:23 +0100
Subject: [PATCH 07/10] drm/msm/dsi/phy: add configuration for SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-7-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-7-1d4c30f43822@linaro.org>
Message-ID: <53c3d2c3-2bfb-43f9-ad25-0d1fdd96f19f@oss.qualcomm.com>

On 8.03.2025 2:42 AM, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Qualcomm SAR2130P requires slightly different setup for the DSI PHY. It
> is a 5nm PHY (like SM8450), so supplies are the same, but the rest of
> the configuration is the same as SM8550 DSI PHY.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c     |  2 ++
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h     |  1 +
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 23 +++++++++++++++++++++++
>  3 files changed, 26 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> index c0bcc68289633fd7506ce4f1f963655d862e8f08..a58bafe9fe8635730cb82e8c82ec1ded394988cd 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> @@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
>  	  .data = &dsi_phy_7nm_cfgs },
>  	{ .compatible = "qcom,dsi-phy-7nm-8150",
>  	  .data = &dsi_phy_7nm_8150_cfgs },
> +	{ .compatible = "qcom,sar2130p-dsi-phy-5nm",
> +	  .data = &dsi_phy_5nm_sar2130p_cfgs },
>  	{ .compatible = "qcom,sc7280-dsi-phy-7nm",
>  	  .data = &dsi_phy_7nm_7280_cfgs },
>  	{ .compatible = "qcom,sm6375-dsi-phy-7nm",
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> index 1925418d9999a24263d6621299cae78f1fb9455c..1ed08b56e056094bc0096d07d4470b89d9824060 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> @@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
>  extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
>  extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
>  extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
> +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
>  extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
>  extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
>  
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index a92decbee5b5433853ed973747f7705d9079068d..cad55702746b8d35949d22090796cca60f03b9e1 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -1289,6 +1289,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = {
>  	.quirks = DSI_PHY_7NM_QUIRK_V4_3,
>  };
>  
> +const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = {
> +	.has_phy_lane = true,
> +	.regulator_data = dsi_phy_7nm_97800uA_regulators,
> +	.num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators),
> +	.ops = {
> +		.enable = dsi_7nm_phy_enable,
> +		.disable = dsi_7nm_phy_disable,
> +		.pll_init = dsi_pll_7nm_init,
> +		.save_pll_state = dsi_7nm_pll_save_state,
> +		.restore_pll_state = dsi_7nm_pll_restore_state,
> +		.set_continuous_clock = dsi_7nm_set_continuous_clock,
> +	},
> +	.min_pll_rate = 600000000UL,
> +#ifdef CONFIG_64BIT
> +	.max_pll_rate = 5000000000UL,
> +#else
> +	.max_pll_rate = ULONG_MAX,
> +#endif
> +	.io_start = { 0xae95000, 0xae97000 },
> +	.num_dsi_phy = 2,
> +	.quirks = DSI_PHY_7NM_QUIRK_V5_2,
> +};

I'm squinting very very hard and can't tell how this is different from
dsi_phy_4nm_8550_cfgs

Konrad


From jic23 at kernel.org  Sat Mar  8 06:32:14 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 8 Mar 2025 14:32:14 +0000
Subject: [PATCH] dt-bindings: iio: adc: Add i.MX94 and i.MX95 support
In-Reply-To: <20250307-county-dissuade-eed621016369@spud>
References: <20250306170825.239933-1-Frank.Li@nxp.com>
	<20250307-county-dissuade-eed621016369@spud>
Message-ID: <20250308143214.6dcc41ac@jic23-huawei>

On Fri, 7 Mar 2025 15:58:34 +0000
Conor Dooley <conor at kernel.org> wrote:

> On Thu, Mar 06, 2025 at 12:08:25PM -0500, Frank Li wrote:
> > Add compatible string "nxp,imx94-adc" and "nxp,imx95-adc", which is
> > backward compatible with i.MX93. Set it to fall back to "nxp,imx93-adc".
> >   
> 
> Acked-by: Conor Dooley <conor.dooley at microchip.com>
Applied - thanks,


From konrad.dybcio at oss.qualcomm.com  Sat Mar  8 06:33:34 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Sat, 8 Mar 2025 15:33:34 +0100
Subject: [PATCH v2 5/9] phy: qcom: Update description for QCOM based eUSB2
 repeater
In-Reply-To: <20250304-sm8750_usb_master-v2-5-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-5-a698a2e68e06@quicinc.com>
Message-ID: <d1fdbbcf-f3dc-4233-b2b8-af5102c1feb1@oss.qualcomm.com>

On 4.03.2025 10:56 PM, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> The eUSB2 repeater that exists in the QCOM PMICs are utilized for several
> different eUSB2 PHY vendors, such as M31 or Synopsys.  Hence, the wording
> needs to be updated to remove associations to a specific vendor.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---
>  drivers/phy/qualcomm/Kconfig | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
> index 846f8c99547fd5132feaa1e41093b8eab51714f9..f281e3b7f3f20b4a4bb1602be94b8a1b041a876f 100644
> --- a/drivers/phy/qualcomm/Kconfig
> +++ b/drivers/phy/qualcomm/Kconfig
> @@ -135,12 +135,12 @@ config PHY_QCOM_SNPS_EUSB2
>  	  on Qualcomm SOCs.
>  
>  config PHY_QCOM_EUSB2_REPEATER
> -	tristate "Qualcomm SNPS eUSB2 Repeater Driver"
> +	tristate "Qualcomm PMIC eUSB2 Repeater Driver"
>  	depends on OF && (ARCH_QCOM || COMPILE_TEST)
>  	select GENERIC_PHY
>  	help
> -	  Enable support for the USB high-speed SNPS eUSB2 repeater on Qualcomm
> -	  PMICs. The repeater is paired with a Synopsys eUSB2 Phy
> +	  Enable support for the USB high-speed eUSB2 repeater on Qualcomm
> +	  PMICs. The repeater can be paired with a Synopsys or M31 eUSB2 Phy
>  	  on Qualcomm SOCs.

I guess the repeater doesn't really check the vendor of the PHY, i.e. if
someone took a SMB2360 and hooked it up to any other eUSB signal, it would
happily crunch through them..

That said, I'm just spitting out words and this is probably good to inform
the user about the actual real-world usage

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>

Konrad


From toke at redhat.com  Sat Mar  8 06:40:51 2025
From: toke at redhat.com (Toke =?utf-8?Q?H=C3=B8iland-J=C3=B8rgensen?=)
Date: Sat, 08 Mar 2025 15:40:51 +0100
Subject: [PATCH net-next v11 0/4] fix the DMA API misuse problem for
 page_pool
In-Reply-To: <40b33879-509a-4c4a-873b-b5d3573b6e14@gmail.com>
References: <20250307092356.638242-1-linyunsheng@huawei.com>
 <87v7slvsed.fsf@toke.dk> <40b33879-509a-4c4a-873b-b5d3573b6e14@gmail.com>
Message-ID: <875xkj1t70.fsf@toke.dk>

Yunsheng Lin <yunshenglin0825 at gmail.com> writes:

> On 3/7/2025 10:15 PM, Toke H?iland-J?rgensen wrote:
>
> ...
>
>> 
>> You are making this incredibly complicated. You've basically implemented
>> a whole new slab allocator for those page_pool_item objects, and you're
>> tracking every page handed out by the page pool instead of just the ones
>> that are DMA-mapped. None of this is needed.
>  > > I took a stab at implementing the xarray-based tracking first suggested
>> by Mina[0]:
>
> I did discuss Mina' suggestion with Ilias below in case you didn't
> notice:
> https://lore.kernel.org/all/0ef315df-e8e9-41e8-9ba8-dcb69492c616 at huawei.com/

I didn't; thanks for the pointer. See below.

> Anyway, It is great that you take the effort to actually implement
> the idea to have some more concrete comparison here.

:)

>> 
>> https://git.kernel.org/toke/c/e87e0edf9520
>> 
>> And, well, it's 50 lines of extra code, none of which are in the fast
>> path.
>
> I wonder what is the overhead for the xarray idea regarding the
> time_bench_page_pool03_slow() testcase before we begin to discuss
> if xarray idea is indeed possible.

Well, just running that benchmark shows no impact:

|                               |      Baseline     |     xarray      |
|                               |   Cycles |     ns | Cycles |     ns |
|-------------------------------+----------+--------+--------+--------|
| no-softirq-page_pool01        |       20 |  5.713 |     19 |  5.516 |
| no-softirq-page_pool02        |       56 | 15.560 |     57 | 15.864 |
| no-softirq-page_pool03        |      225 | 62.763 |    222 | 61.728 |
| tasklet_page_pool01_fast_path |       19 |  5.399 |     19 |  5.505 |
| tasklet_page_pool02_ptr_ring  |       54 | 15.090 |     54 | 15.018 |
| tasklet_page_pool03_slow      |      238 | 66.134 |    239 | 66.498 |

...however, the benchmark doesn't actually do any DMA mapping, so it's
not super surprising that it doesn't show any difference: it's not
exercising any of the xarray code. Your series shows a difference on
this benchmark only because it does the page_pool_item allocation
regardless of whether DMA is used or not.

I guess we should try to come up with a micro-benchmark that does
exercise the DMA code. Or just hack up the xarray patch to do the
tracking regardless, for benchmarking purposes.

>> Jesper has kindly helped with testing that it works for normal packet
>> processing, but I haven't yet verified that it resolves the original
>> crash. Will post the patch to the list once I have verified this (help
>> welcome!).
>
> RFC seems like a good way to show and discuss the basic idea.

Sure, I can send it as an RFC straight away if you prefer. Note that I'm
on my way to netdevconf, though, so will probably have limited time to
pay attention to this for the next week or so.

> I only took a glance at git code above, it seems reusing the
> _pp_mapping_pad for pp_dma_index seems like a wrong direction
> as mentioned in discussion with Ilias above as the field might
> be used when a page is mmap'ed to user space, and reusing that
> field in 'struct page' seems to disable the tcp_zerocopy feature,
> see the below commit from Eric:
> https://github.com/torvalds/linux/commit/577e4432f3ac810049cb7e6b71f4d96ec7c6e894
>
> Also, I am not sure if a page_pool owned page can be spliced into the fs
> subsystem yet, but if it does, I am not sure how is reusing the
> page->mapping possible if that page is called in __filemap_add_folio()?
>
> https://elixir.bootlin.com/linux/v6.14-rc5/source/mm/filemap.c#L882

Hmm, so I did look at the mapping field, but concluded using it wouldn't
interfere with anything relevant as long as it's reset back to zero
before the page is returned to the page allocator. However, I definitely
missed the TCP zero-copy thing, and other things as well, it would seem
(cf the discussion you referred to above).

However, I did consider alternatives: AFAICT there should be space in
the pp_magic field (used for the PP_SIGNATURE), so that with a bit of
care we can stick an ID into the upper bits and still avoid ending up
with a value that could look like a valid pointer.

I didn't implement that initially because I wasn't sure it was
necessary, but seeing as it is, I will take another look at it. I have
one or two other ideas if this turns out not to pan out.

-Toke



From arturas.moskvinas at gmail.com  Sat Mar  8 06:53:56 2025
From: arturas.moskvinas at gmail.com (Arturas Moskvinas)
Date: Sat, 8 Mar 2025 16:53:56 +0200
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add Xunlong Orange Pi 3B
In-Reply-To: <20240626230319.1425316-3-jonas@kwiboo.se>
References: <20240626230319.1425316-1-jonas@kwiboo.se>
 <20240626230319.1425316-3-jonas@kwiboo.se>
Message-ID: <d1c600f1-a874-4bb8-8b9f-22a3414edfcc@gmail.com>

On 6/27/24 2:03 AM, Jonas Karlman wrote:

> The Xunlong Orange Pi 3B is a single-board computer based on the
> Rockchip RK3566 SoC.
...> +
> +&gmac1 {
> +	phy-handle = <&rgmii_phy1>;
> +	status = "okay";
> +};
> +
> +&mdio1 {
> +	rgmii_phy1: ethernet-phy at 1 {
> +		compatible = "ethernet-phy-ieee802.3-c22";
> +		reg = <1>;

Jonas, were you able to test V1.1 board's Ethernet?

Whenever I start the board - Ethernet initialization fails with:
```
[   21.140055] rk_gmac-dwmac fe010000.ethernet eth0: __stmmac_open: 
Cannot attach to PHY (error: -19)
```

But if reset is performed inside gmac - initialization succeeds.

Eg. patch:
```
--- 
linux-6.12.17.orig/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
+++ linux-6.12.17/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
@@ -16,14 +16,14 @@
  &gmac1 {
  	phy-handle = <&rgmii_phy1>;
  	status = "okay";
+	snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 50000 200000>;
  };

  &mdio1 {
  	rgmii_phy1: ethernet-phy at 1 {
  		compatible = "ethernet-phy-ieee802.3-c22";
  		reg = <1>;
-		reset-assert-us = <20000>;
-		reset-deassert-us = <50000>;
-		reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
  	};
  };
```
> +		reset-assert-us = <20000>;
> +		reset-deassert-us = <50000>;
> +		reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
> +	};
> +};


Arturas Moskvinas


From florian.fainelli at broadcom.com  Sat Mar  8 07:05:28 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Sat,  8 Mar 2025 07:05:28 -0800
Subject: [GIT PULL] Broadcom devicetree fixes for 6.14 part 2
Message-ID: <20250308150528.1900822-1-florian.fainelli@broadcom.com>

The following changes since commit 7eb172143d5508b4da468ed59ee857c6e5e01da6:

  Linux 6.14-rc5 (2025-03-02 11:48:20 -0800)

are available in the Git repository at:

  https://github.com/Broadcom/stblinux.git tags/arm-soc/for-6.14/devicetree-fixes-part2

for you to fetch changes up to 24d4c56dd68906bf55ff8fc2e2d36760f97dce5f:

  ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC3200 (2025-03-08 07:03:46 -0800)

----------------------------------------------------------------
This pull request contains Broadcom ARM-based SoCs Device Tree fixes for
6.14, please pull the following:

- Chester fixes the switch port assignments on the ASUS RT-AC3200 and
  RT-AC5300 routers

- Phil removes a Device Tree property flagging the BCM2711 ARM timers as
  not being configured which would have prevented the use of vDSO on the
  Pi 4 running a 32-bit kernel

----------------------------------------------------------------
Chester A. Unal (2):
      ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC5300
      ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC3200

Phil Elwell (1):
      ARM: dts: bcm2711: Don't mark timer regs unconfigured

 arch/arm/boot/dts/broadcom/bcm2711.dtsi                | 2 --
 arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts  | 8 ++++----
 arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts | 8 ++++----
 3 files changed, 8 insertions(+), 10 deletions(-)


From konrad.dybcio at oss.qualcomm.com  Sat Mar  8 07:05:40 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Sat, 8 Mar 2025 16:05:40 +0100
Subject: [PATCH v2 8/9] arm64: dts: qcom: sm8750: Add USB support for
 SM8750 MTP and QRD platforms
In-Reply-To: <20250304-sm8750_usb_master-v2-8-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-8-a698a2e68e06@quicinc.com>
Message-ID: <687a23e2-7822-4d68-8b4c-f8816cce3cc9@oss.qualcomm.com>

On 4.03.2025 10:56 PM, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> Enable USB support on SM8750 MTP and QRD variants.  The current definition
> will start the USB controller in peripheral mode by default until
> dependencies are added, such as USB role detection.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---

Please separate these two indeed. With that:

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Tested-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com> # SM8750 QRD

(make sure the latter one only goes to the QRD commit)

Konrad


From konrad.dybcio at oss.qualcomm.com  Sat Mar  8 07:07:26 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Sat, 8 Mar 2025 16:07:26 +0100
Subject: [PATCH v2 7/9] arm64: dts: qcom: sm8750: Add USB support to
 SM8750 SoCs
In-Reply-To: <20250304-sm8750_usb_master-v2-7-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-7-a698a2e68e06@quicinc.com>
Message-ID: <aca09e7c-53e2-45a3-8281-7df9951549eb@oss.qualcomm.com>

On 4.03.2025 10:56 PM, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> Add the base USB devicetree definitions for SM8750 platforms.  The overall
> chipset contains a single DWC3 USB3 controller (rev. 200a), SS QMP PHY
> (rev. v8) and M31 eUSB2 PHY.  The major difference for SM8750 is the
> transition to using the M31 eUSB2 PHY compared to previous SoCs.
> 
> Enable USB support on SM8750 MTP and QRD variants. SM8750 has a QMP combo
> PHY for the SSUSB path, and a M31 eUSB2 PHY for the HSUSB path.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---

[...]

> +		usb_1: usb at a6f8800 {
> +			compatible = "qcom,sm8750-dwc3", "qcom,dwc3";
> +			reg = <0x0 0x0a6f8800 0x0 0x400>;
> +			status = "disabled";
> +			#address-cells = <2>;
> +			#size-cells = <2>;
> +			ranges;

Please follow property order / general style found in x1e80100.dtsi

> +
> +			clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
> +				 <&gcc GCC_USB30_PRIM_MASTER_CLK>,
> +				 <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
> +				 <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
> +				 <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
> +				 <&tcsrcc TCSR_USB3_CLKREF_EN>;
> +			clock-names = "cfg_noc",
> +				      "core",
> +				      "iface",
> +				      "sleep",
> +				      "mock_utmi",
> +				      "xo";
> +
> +			assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
> +					  <&gcc GCC_USB30_PRIM_MASTER_CLK>;
> +			assigned-clock-rates = <19200000>, <200000000>;
> +
> +			interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
> +						  <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
> +					      <&pdc 14 IRQ_TYPE_EDGE_BOTH>,
> +					      <&pdc 15 IRQ_TYPE_EDGE_BOTH>,
> +					      <&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "pwr_event",
> +					  "hs_phy_irq",
> +					  "dp_hs_phy_irq",
> +					  "dm_hs_phy_irq",
> +					  "ss_phy_irq";
> +
> +			power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
> +			required-opps = <&rpmhpd_opp_nom>;
> +
> +			resets = <&gcc GCC_USB30_PRIM_BCR>;
> +
> +			interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>,

QCOM_ICC_TAG_ALWAYS

> +					<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;

QCOM_ICC_TAG_ACTIVE_ONLY

Konrad


From dmitry.baryshkov at linaro.org  Sat Mar  8 07:25:15 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sat, 8 Mar 2025 17:25:15 +0200
Subject: [PATCH 07/10] drm/msm/dsi/phy: add configuration for SAR2130P
In-Reply-To: <53c3d2c3-2bfb-43f9-ad25-0d1fdd96f19f@oss.qualcomm.com>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-7-1d4c30f43822@linaro.org>
 <53c3d2c3-2bfb-43f9-ad25-0d1fdd96f19f@oss.qualcomm.com>
Message-ID: <qextyfjeniihulyilehcldd5x5pdpaxo3etstlcq4a43cka3a4@4n3mqkjjysqt>

On Sat, Mar 08, 2025 at 03:17:23PM +0100, Konrad Dybcio wrote:
> On 8.03.2025 2:42 AM, Dmitry Baryshkov wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > 
> > Qualcomm SAR2130P requires slightly different setup for the DSI PHY. It
> > is a 5nm PHY (like SM8450), so supplies are the same, but the rest of
> > the configuration is the same as SM8550 DSI PHY.
> > 
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > ---
> >  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c     |  2 ++
> >  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h     |  1 +
> >  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 23 +++++++++++++++++++++++
> >  3 files changed, 26 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> > index c0bcc68289633fd7506ce4f1f963655d862e8f08..a58bafe9fe8635730cb82e8c82ec1ded394988cd 100644
> > --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> > +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
> > @@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
> >  	  .data = &dsi_phy_7nm_cfgs },
> >  	{ .compatible = "qcom,dsi-phy-7nm-8150",
> >  	  .data = &dsi_phy_7nm_8150_cfgs },
> > +	{ .compatible = "qcom,sar2130p-dsi-phy-5nm",
> > +	  .data = &dsi_phy_5nm_sar2130p_cfgs },
> >  	{ .compatible = "qcom,sc7280-dsi-phy-7nm",
> >  	  .data = &dsi_phy_7nm_7280_cfgs },
> >  	{ .compatible = "qcom,sm6375-dsi-phy-7nm",
> > diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> > index 1925418d9999a24263d6621299cae78f1fb9455c..1ed08b56e056094bc0096d07d4470b89d9824060 100644
> > --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> > +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
> > @@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
> >  extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
> >  extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
> >  extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
> > +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
> >  extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
> >  extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
> >  
> > diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> > index a92decbee5b5433853ed973747f7705d9079068d..cad55702746b8d35949d22090796cca60f03b9e1 100644
> > --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> > +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> > @@ -1289,6 +1289,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = {
> >  	.quirks = DSI_PHY_7NM_QUIRK_V4_3,
> >  };
> >  
> > +const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = {
> > +	.has_phy_lane = true,
> > +	.regulator_data = dsi_phy_7nm_97800uA_regulators,
> > +	.num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators),
> > +	.ops = {
> > +		.enable = dsi_7nm_phy_enable,
> > +		.disable = dsi_7nm_phy_disable,
> > +		.pll_init = dsi_pll_7nm_init,
> > +		.save_pll_state = dsi_7nm_pll_save_state,
> > +		.restore_pll_state = dsi_7nm_pll_restore_state,
> > +		.set_continuous_clock = dsi_7nm_set_continuous_clock,
> > +	},
> > +	.min_pll_rate = 600000000UL,
> > +#ifdef CONFIG_64BIT
> > +	.max_pll_rate = 5000000000UL,
> > +#else
> > +	.max_pll_rate = ULONG_MAX,
> > +#endif
> > +	.io_start = { 0xae95000, 0xae97000 },
> > +	.num_dsi_phy = 2,
> > +	.quirks = DSI_PHY_7NM_QUIRK_V5_2,
> > +};
> 
> I'm squinting very very hard and can't tell how this is different from
> dsi_phy_4nm_8550_cfgs

97800 uA vs 98400 uA is the only difference AFAIK.

-- 
With best wishes
Dmitry


From ziyao at disroot.org  Sat Mar  8 07:27:22 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sat, 8 Mar 2025 15:27:22 +0000
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>
References: <20250305194638.47187-1-ziyao@disroot.org>
 <20250307033508.656479-1-amadeus@jmu.edu.cn>
 <Z8qJqpUwi7VV8tJk@pie>
 <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se>
Message-ID: <Z8xh2mE1BTE4co43@pie>

Hi Jonas,

On Fri, Mar 07, 2025 at 07:45:00AM +0100, Jonas Karlman wrote:
> Hi Chukun,
> 
> On 2025-03-07 06:52, Yao Zi wrote:
> > On Fri, Mar 07, 2025 at 11:35:08AM +0800, Chukun Pan wrote:
> >> Hi,
> >>
> >>> +&sdmmc {
> >>> +	bus-width = <4>;
> >>> +	cap-mmc-highspeed;
> >>> +	cap-sd-highspeed;
> >>> +	disable-wp;
> >>> +	no-sdio;
> >>
> >> With 'no-sdio' property:
> >> [  129.608986] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
> >> [  130.711168] mmc1: Card stuck being busy! __mmc_poll_for_busy
> >> [  130.725536] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
> >> [  131.751240] mmc1: Card stuck being busy! __mmc_poll_for_busy
> >> [  131.765608] mmc_host mmc1: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
> >> [  132.825083] mmc1: Card stuck being busy! __mmc_poll_for_busy
> >> [  132.839413] mmc_host mmc1: Bus speed (slot 0) = 187500Hz (slot req 187500Hz, actual 187500HZ div = 0)
> >> [  133.960141] mmc1: Card stuck being busy! __mmc_poll_for_busy
> >>
> >> Without 'no-sdio' property:
> >> [  105.224019] mmc1: error -22 whilst initialising SDIO card
> >> [  106.290838] mmc1: Card stuck being busy! __mmc_poll_for_busy
> >> [  106.801931] dwmmc_rockchip ffc30000.mmc: Busy; trying anyway
> >> [  107.385835] mmc_host mmc1: Timeou sending command (cmd 0x202000 arg 0x0 status 0x80202000)
> >> [  107.400425] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
> >> [  107.431561] mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 50000000Hz, actual 49800000HZ div = 0)
> >> [  107.433107] mmc1: new high speed SDIO card at address 0001
> > 
> > So it seems the sdmmc controller actually works with SDIO commands as
> > well? I don't expect that since the datasheet says RK3528 has only two
> > SDIO 3.0 controllers.
> > 
> > We could remove the "no-sdio" property if SDIO actually works. Will
> > apply it in the next version if there's no objection against this.
> 
> On the E20C the sdmmc controller is routed to a microSD card slot mainly
> intended for use with microSD-cards and should normally not need SDIO.

As pointed out by Chukun, I found the hardware design guide for
RK3528[1] (in Chinese) does claim that SDIO 3.0 is supported on all
these three controllers in Chapter 2.3.1 (SDMMC/SDIO),

  RK3528 ??? 1 ? SDMMC ???? 2 ? SDIO ???????? SDIO3.0 ?
  ???? MMC V4.51 ????? SDIO0 ? SDIO1 ????? 200MHz?SDMMC
  ?????? 150MHz

translated to English,

  RK3528 integrates one SDMMC controller and two SDIO controllers, all
  support SDIO3.0 protocol and MMC V4.51 protocol. Among them SDIO0 and
  SDIO1 support 200MHz frequency at maximum, and SDMMC supports up to
  150MHz.

So I think there's no reason to explicitly deny SDIO initialization
sequence for the controller on Radxa E20C. imho this won't break
anything even for a sdcard slot, will it?

Additionally, this piece of information points out that wrong
max-frequency is set for SDIO{0,1}. Rockchip overrides the frequency in
devicetrees for the demo boards[2], I'm not sure whether it's for some
speical reason or not.

Since I don't have a SDIO-capable board on hand, could you please test
whether 200MHz actually works? If so I'll correct the SoC devicetree in
v3.

> What card/adapter do you have inserted in the microSD card slot that
> requires use of SDIO instead of just SD or MMC? What is the use case you
> have that requires removal of no-sdio on E20C?
> 
> Regards,
> Jonas
> 
> > 
> > Further tests about the capabilities of the controller are welcome.
> > 
> >> # cat /sys/kernel/debug/mmc1/ios
> >> clock:          50000000 Hz
> >> vdd:            21 (3.3 ~ 3.4 V)
> >> bus mode:       2 (push-pull)
> >> chip select:    0 (don't care)
> >> power mode:     2 (on)
> >> bus width:      2 (4 bits)
> >> timing spec:    2 (sd high-speed)
> >> signal voltage: 0 (3.30 V)
> >> driver type:    0 (driver type B)
> >>
> >> Thanks,
> >> Chukun
> >>
> >> -- 
> >> 2.25.1
> >>
> > 
> > Best regards,
> > Yao Zi
> 

Thanks,
Yao Zi

[1]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/RK3528%20Hardware%20Design%20Guide-CN-V1.0-20230525.pdf
[2]: https://github.com/rockchip-linux/kernel/blob/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3528-demo1-lp4-v10.dtsi#L47


From wiagn233 at outlook.com  Sat Mar  8 07:35:21 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Sat,  8 Mar 2025 23:35:21 +0800
Subject: [PATCH v9 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled
Message-ID: <TYCPR01MB84376C7074C566865654F05098D42@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The current WED only supports 256 wcid, whereas mt7986 can support up to
512 entries, so firmware provides a rule to get sta_info by DA when wcid
is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
to 0xff by host driver.

However, firmware is unable to get sta_info from DA as DA != RA for
4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
and (768 ~ 783) for sync up to get correct sta_info.

Currently WDS+WED config is completely broken on MT7986/7981 devices if
without this patch.

Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
For unknown reason, the v9 patch has added a strange include header,
causing it fail to compile. So I resent it with that include removed.

Changes since v1:
 - Drop duplicate setting in mmio
 - Reduce the patch size by redefining mt76_wcid_alloc
Changes since v2:
 - Rework wds wcid getting flow
Changes since v3:
 - Rebase to next-20240703
 - Sync with downstream patch
Changes since v4:
 - Rebase to next-20240802
Changes since v5:
 - Fixed build test error reported by robot
 - Rebase to next-20240805
Changes since v6:
 - Fix potential race conditions on tx/rx packets during the transition
 - Rebase to Felix's newest codebase
Changes since v7:
 - Fix build fail
Changes since v8:
 - Changed code as Shih advised
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  9 ++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 50 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
 drivers/net/wireless/mediatek/mt76/util.c     | 37 ++++++++++++--
 drivers/net/wireless/mediatek/mt76/util.h     |  7 ++-
 6 files changed, 111 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b107..638ee9fae0c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -28,6 +28,9 @@
 
 #define MT76_TOKEN_FREE_THR	64
 
+#define MT76_WED_WDS_MIN    256
+#define MT76_WED_WDS_MAX    272
+
 #define MT_QFLAG_WED_RING	GENMASK(1, 0)
 #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
 #define MT_QFLAG_WED		BIT(5)
@@ -73,6 +76,12 @@ enum mt76_wed_type {
 	MT76_WED_RRO_Q_IND,
 };
 
+enum mt76_wed_state {
+	MT76_WED_DEFAULT,
+	MT76_WED_ACTIVE,
+	MT76_WED_WDS_ACTIVE,
+};
+
 struct mt76_bus_ops {
 	u32 (*rr)(struct mt76_dev *dev, u32 offset);
 	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 3aa31c5cefa6..9be5937727cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
 	bool ext_phy = mvif->phy != &dev->phy;
 	int idx;
+	u8 flags = MT76_WED_DEFAULT;
 
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76)) {
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+	}
+
+	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
 	if (idx < 0)
 		return -ENOSPC;
 
@@ -1271,6 +1278,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 {
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
+	struct ieee80211_sta *pre_sta;
+	struct mt7915_sta *pre_msta;
+	u8 flags = MT76_WED_DEFAULT;
+	int tmp_idx;
 
 	if (enabled)
 		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
@@ -1280,6 +1292,34 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 	if (!msta->wcid.sta)
 		return;
 
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76) &&
+	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
+		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
+
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+
+		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
+		if (tmp_idx == -1)
+			goto error;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
+
+		tmp_idx = msta->wcid.idx;
+		msta->wcid.idx = pre_msta->wcid.idx;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
+
+		synchronize_rcu();
+		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
+
+error:
+		kfree(pre_sta);
+	}
+
 	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
 }
 
@@ -1726,15 +1766,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
 	path->mtk_wdma.queue = phy != &dev->phy;
+	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
+	    is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = msta->wcid.idx;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
 
 	ctx->dev = NULL;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9d790f234e82..32c5aa1a361e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
 
 	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
 
-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-	     is_mt7915(&dev->mt76)) ||
-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+		if (is_mt7915(&dev->mt76) ||
+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+						0, 0, 0);
+		else
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+						MCU_WA_PARAM_WED_VERSION,
+						dev->mt76.mmio.wed.rev_id, 0);
+		if (ret)
+			return ret;
+	}
+#endif
 
 	ret = mt7915_mcu_set_mwds(dev, 1);
 	if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 49476a4182fd..c3dd0cb4a5d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
 	MCU_WA_PARAM_PDMA_RX = 0x04,
 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
 	MCU_WA_PARAM_RED = 0x0e,
+	MCU_WA_PARAM_WED_VERSION = 0x32,
 	MCU_WA_PARAM_RED_SETTING = 0x40,
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 95b3dc96e4c4..7fac9c79ebdf 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 }
 EXPORT_SYMBOL_GPL(____mt76_poll_msec);
 
-int mt76_wcid_alloc(u32 *mask, int size)
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
 {
 	int i, idx = 0, cur;
+	int min = MT76_WED_WDS_MIN;
+	int max = MT76_WED_WDS_MAX;
 
 	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
 		idx = ffs(~mask[i]);
@@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
 
 		idx--;
 		cur = i * 32 + idx;
-		if (cur >= size)
+
+		switch (flag) {
+		case MT76_WED_ACTIVE:
+			if (cur >= min && cur < max)
+				continue;
+
+			if (cur >= size) {
+				u32 end = max - min - 1;
+
+				i = min / 32;
+				idx = ffs(~mask[i] & GENMASK(end, 0));
+				if (!idx)
+					goto error;
+				idx--;
+				cur = min + idx;
+			}
+
 			break;
+		case MT76_WED_WDS_ACTIVE:
+			if (cur < min)
+				continue;
+			if (cur >= max)
+				goto error;
+
+			break;
+		default:
+			if (cur >= size)
+				goto error;
+			break;
+		}
 
 		mask[i] |= BIT(idx);
 		return cur;
 	}
 
+error:
 	return -1;
 }
-EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
 
 int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94c..99b7263c0a20 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -27,7 +27,12 @@ enum {
 #define MT76_INCR(_var, _size) \
 	(_var = (((_var) + 1) % (_size)))
 
-int mt76_wcid_alloc(u32 *mask, int size);
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+	return __mt76_wcid_alloc(mask, size, 0);
+}
 
 static inline void
 mt76_wcid_mask_set(u32 *mask, int idx)
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:32 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:32 +0100
Subject: [PATCH net-next v2 0/7] net: ethtool: Introduce ethnl dump helpers
Message-ID: <20250308155440.267782-1-maxime.chevallier@bootlin.com>

Hi everyone,

This is V2 for the ethnl dump support, allowing better handling of
per-phy dump but also any other dump operation that needs to dump more
than one message per netdev.

Changes in V2:
 - Rebased on the netdev_lock work by Stanislav and the fixes from Eric
 - Fixed a bissectability issue
 - Fixed kdoc for the new ethnl ops and fields

V1: https://lore.kernel.org/netdev/20250305141938.319282-1-maxime.chevallier at bootlin.com/

As of today when using ethnl's default ops, the DUMP requests will
simply perform a GET for each netdev.

That hits limitations for commands that may return multiple messages for
a single netdev, such as :

 - RSS (listing contexts)
 - All PHY-specific commands (PLCA, PSE-PD, phy)
 - tsinfo (one item for the netdev +  one per phy)

 Commands that need a non-default DUMP support have to re-implement
 ->dumpit() themselves, which prevents using most of ethnl's internal
 circuitry.

This series therefore introduces a better support for dump operations in
ethnl.

The patches 1 and 2 introduce the support for filtered DUMPs, where an
ifindex/ifname can be passed in the request header for the DUMP
operation. This is for when we want to dump everything a netdev
supports, but without doing so for every single netdev. ethtool's
"--show-phys ethX" option for example performs a filtered dump.

Patch 3 introduces 3 new ethnl ops : 
 ->dump_start() to initialize a dump context
 ->dump_one_dev(), that can be implemented per-command to dump
 everything on a given netdev
 ->dump_done() to release the context

The default behaviour for dumps remains the same, calling the whole
->doit() path for each netdev.

Patch 4 introduces a set of ->dump_start(), ->dump_one_dev() and
->dump_done() callback implementations that can simply be plugged into
the existing commands that list objects per-phy, making the 
phy-targeting command behaviour more coherent.

Patch 5 uses that new set of helpers to rewrite the phy.c support, which
now uses the regulat ethnl_ops instead of fully custom genl ops. This
one is the hardest to review, sorry about that, I couldn't really manage
to incrementally rework that file :(

Patches 6 and 7 are where the new dump infra shines, adding per-netdev
per-phy dump support for PLCA and PSE-PD.

We could also consider converting tsinfo/tsconfig, rss and tunnels to
these new ->dump_***() operations as well, but that's out of this
series' scope.

Maxime Chevallier (7):
  net: ethtool: netlink: Allow per-netdevice DUMP operations
  net: ethtool: netlink: Rename ethnl_default_dump_one
  net: ethtool: netlink: Introduce command-specific dump_one_dev
  net: ethtool: netlink: Introduce per-phy DUMP helpers
  net: ethtool: phy: Convert the PHY_GET command to generic phy dump
  net: ethtool: plca: Use per-PHY DUMP operations
  net: ethtool: pse-pd: Use per-PHY DUMP operations

 net/ethtool/netlink.c | 165 ++++++++++++++------
 net/ethtool/netlink.h |  47 +++++-
 net/ethtool/phy.c     | 343 ++++++++++++------------------------------
 net/ethtool/plca.c    |  12 ++
 net/ethtool/pse-pd.c  |   6 +
 5 files changed, 280 insertions(+), 293 deletions(-)

-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:33 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:33 +0100
Subject: [PATCH net-next v2 1/7] net: ethtool: netlink: Allow per-netdevice DUMP operations
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-2-maxime.chevallier@bootlin.com>

We have a number of netlink commands in the ethnl family that may have
multiple objects to dump even for a single net_device, including :

 - PLCA, PSE-PD, phy: one message per PHY device
 - tsinfo: one message per timestamp source (netdev + phys)
 - rss: One per RSS context

To get this behaviour, these netlink commands need to roll a custom
->dumpit().

To prepare making per-netdev DUMP more generic in ethnl, introduce a
member in the ethnl ops to indicate if a given command may allow
pernetdev DUMPs (also referred to as filtered DUMPs).

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: - Rebase
    - Fix kdoc
    - Fix bissectabilitu by using the right function names

 net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
 net/ethtool/netlink.h |  2 ++
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 70834947f474..11e4122b7707 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -586,21 +586,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 	int ret = 0;
 
 	rcu_read_lock();
-	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
-		dev_hold(dev);
+	if (ctx->req_info->dev) {
+		dev = ctx->req_info->dev;
 		rcu_read_unlock();
-
-		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
-
+		/* Filtered DUMP request targeted to a single netdev. We already
+		 * hold a ref to the netdev from ->start()
+		 */
+		ret = ethnl_default_dump_one(skb, dev, ctx,
+					     genl_info_dump(cb));
 		rcu_read_lock();
-		dev_put(dev);
-
-		if (ret < 0 && ret != -EOPNOTSUPP) {
-			if (likely(skb->len))
-				ret = skb->len;
-			break;
+		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
+	} else {
+		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
+			dev_hold(dev);
+			rcu_read_unlock();
+
+			ret = ethnl_default_dump_one(skb, dev, ctx,
+						     genl_info_dump(cb));
+
+			rcu_read_lock();
+			dev_put(dev);
+
+			if (ret < 0 && ret != -EOPNOTSUPP) {
+				if (likely(skb->len))
+					ret = skb->len;
+				break;
+			}
+			ret = 0;
 		}
-		ret = 0;
 	}
 	rcu_read_unlock();
 
@@ -634,10 +647,10 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	}
 
 	ret = ethnl_default_parse(req_info, &info->info, ops, false);
-	if (req_info->dev) {
-		/* We ignore device specification in dump requests but as the
-		 * same parser as for non-dump (doit) requests is used, it
-		 * would take reference to the device if it finds one
+	if (req_info->dev && !ops->allow_pernetdev_dump) {
+		/* We ignore device specification in unfiltered dump requests
+		 * but as the same parser as for non-dump (doit) requests is
+		 * used, it would take reference to the device if it finds one
 		 */
 		netdev_put(req_info->dev, &req_info->dev_tracker);
 		req_info->dev = NULL;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index ec6ab5443a6f..4aaa73282d6a 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -331,6 +331,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  * @req_info_size:    size of request info
  * @reply_data_size:  size of reply data
  * @allow_nodev_do:   allow non-dump request with no device identification
+ * @allow_pernetdev_dump: allow filtering dump requests with ifname/ifindex
  * @set_ntf_cmd:      notification to generate on changes (SET)
  * @parse_request:
  *	Parse request except common header (struct ethnl_req_info). Common
@@ -388,6 +389,7 @@ struct ethnl_request_ops {
 	unsigned int		req_info_size;
 	unsigned int		reply_data_size;
 	bool			allow_nodev_do;
+	bool			allow_pernetdev_dump;
 	u8			set_ntf_cmd;
 
 	int (*parse_request)(struct ethnl_req_info *req_info,
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:34 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:34 +0100
Subject: [PATCH net-next v2 2/7] net: ethtool: netlink: Rename ethnl_default_dump_one
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-3-maxime.chevallier@bootlin.com>

As we work on getting more objects out of a per-netdev DUMP, rename
ethnl_default_dump_one() into ethnl_default_dump_one_dev(), making it
explicit that this dumps everything for one netdev.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: Rebase, Fix whitespace issue.

 net/ethtool/netlink.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 11e4122b7707..f391a11242de 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -539,9 +539,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
-				  const struct ethnl_dump_ctx *ctx,
-				  const struct genl_info *info)
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      const struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -592,8 +592,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 		/* Filtered DUMP request targeted to a single netdev. We already
 		 * hold a ref to the netdev from ->start()
 		 */
-		ret = ethnl_default_dump_one(skb, dev, ctx,
-					     genl_info_dump(cb));
+		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+						 genl_info_dump(cb));
 		rcu_read_lock();
 		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
 	} else {
@@ -601,8 +601,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
-			ret = ethnl_default_dump_one(skb, dev, ctx,
-						     genl_info_dump(cb));
+			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+							 genl_info_dump(cb));
 
 			rcu_read_lock();
 			dev_put(dev);
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:36 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:36 +0100
Subject: [PATCH net-next v2 4/7] net: ethtool: netlink: Introduce per-phy DUMP helpers
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-5-maxime.chevallier@bootlin.com>

As there are multiple ethnl commands that report messages based on
phy_device information, let's introduce a set of ethnl generic dump
helpers to allow DUMP support for each PHY on a given netdev.

This logic iterates over the phy_link_topology of each netdev (or a
single netdev for filtered DUMP), and call ethnl_default_dump_one() with
the req_info populated with ifindex + phyindex.

This allows re-using all the existing infra for phy-targetting commands
that already use ethnl generic helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: Rebase

 net/ethtool/netlink.c | 53 +++++++++++++++++++++++++++++++++++++++++++
 net/ethtool/netlink.h |  6 +++++
 2 files changed, 59 insertions(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index ae06b72239a8..a09bcd67b38f 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -559,6 +559,59 @@ static int ethnl_default_dump_one(struct sk_buff *skb,
 	return ret;
 }
 
+/* Specific context for phy-targeting command DUMP operatins. We keep in context
+ * the latest phy_index we dumped, in case of an interrupted DUMP.
+ */
+struct ethnl_dump_ctx_perphy {
+	unsigned long phy_index;
+};
+
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx;
+
+	dump_ctx = kzalloc(sizeof(*dump_ctx), GFP_KERNEL);
+	if (!dump_ctx)
+		return -ENOMEM;
+
+	ctx->cmd_ctx = dump_ctx;
+
+	return 0;
+}
+
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx)
+{
+	kfree(ctx->cmd_ctx);
+}
+
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb,
+			      struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx = ctx->cmd_ctx;
+	struct net_device *dev = ctx->reply_data->dev;
+	struct phy_device_node *pdn;
+	int ret = 0;
+
+	if (!dev->link_topo)
+		return 0;
+
+	xa_for_each_start(&dev->link_topo->phys, dump_ctx->phy_index,
+			  pdn, dump_ctx->phy_index) {
+		ctx->req_info->phy_index = dump_ctx->phy_index;
+
+		/* We can re-use the original dump_one as ->prepare_data in
+		 * commands use ethnl_req_get_phydev(), which gets the PHY from
+		 * what's in req_info
+		 */
+		ret = ethnl_default_dump_one(skb, ctx, info);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
 				      struct ethnl_dump_ctx *ctx,
 				      const struct genl_info *info)
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 79fe98190c64..530a9b5c8b39 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -327,6 +327,12 @@ struct ethnl_dump_ctx {
 	void				*cmd_ctx;
 };
 
+/* Generic callbacks to be used by PHY targeting commands */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx);
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb, struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info);
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx);
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:37 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:37 +0100
Subject: [PATCH net-next v2 5/7] net: ethtool: phy: Convert the PHY_GET command to generic phy dump
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-6-maxime.chevallier@bootlin.com>

Now that we have an infrastructure in ethnl for perphy DUMPs, we can get
rid of the custom ->doit and ->dumpit to deal with PHY listing commands.

As most of the code was custom, this basically means re-writing how we
deal with PHY listing.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: Rebase

 net/ethtool/netlink.c |   9 +-
 net/ethtool/netlink.h |   4 -
 net/ethtool/phy.c     | 343 ++++++++++++------------------------------
 3 files changed, 103 insertions(+), 253 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index a09bcd67b38f..dcc2b84095ea 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -381,6 +381,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_MM_SET]		= &ethnl_mm_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_GET]	= &ethnl_tsconfig_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_SET]	= &ethnl_tsconfig_request_ops,
+	[ETHTOOL_MSG_PHY_GET]		= &ethnl_phy_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1344,10 +1345,10 @@ static const struct genl_ops ethtool_genl_ops[] = {
 	},
 	{
 		.cmd	= ETHTOOL_MSG_PHY_GET,
-		.doit	= ethnl_phy_doit,
-		.start	= ethnl_phy_start,
-		.dumpit	= ethnl_phy_dumpit,
-		.done	= ethnl_phy_done,
+		.doit	= ethnl_default_doit,
+		.start	= ethnl_default_start,
+		.dumpit	= ethnl_default_dumpit,
+		.done	= ethnl_default_done,
 		.policy = ethnl_phy_get_policy,
 		.maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1,
 	},
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 530a9b5c8b39..60f16090640f 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -542,10 +542,6 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info);
 int ethnl_rss_dump_start(struct netlink_callback *cb);
 int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_start(struct netlink_callback *cb);
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_done(struct netlink_callback *cb);
 int ethnl_tsinfo_start(struct netlink_callback *cb);
 int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_tsinfo_done(struct netlink_callback *cb);
diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c
index 1a6b725d1f14..90c27dd1a5c6 100644
--- a/net/ethtool/phy.c
+++ b/net/ethtool/phy.c
@@ -11,304 +11,157 @@
 #include <linux/sfp.h>
 
 struct phy_req_info {
-	struct ethnl_req_info		base;
-	struct phy_device_node		*pdn;
+	struct ethnl_req_info base;
 };
 
-#define PHY_REQINFO(__req_base) \
-	container_of(__req_base, struct phy_req_info, base)
+struct phy_reply_data {
+	struct ethnl_reply_data	base;
+	u32 phyindex;
+	char *drvname;
+	char *name;
+	unsigned int upstream_type;
+	char *upstream_sfp_name;
+	unsigned int upstream_index;
+	char *downstream_sfp_name;
+};
+
+#define PHY_REPDATA(__reply_base) \
+	container_of(__reply_base, struct phy_reply_data, base)
 
 const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1] = {
 	[ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
-/* Caller holds rtnl */
-static ssize_t
-ethnl_phy_reply_size(const struct ethnl_req_info *req_base,
-		     struct netlink_ext_ack *extack)
+static int phy_reply_size(const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 	size_t size = 0;
 
-	ASSERT_RTNL();
-
 	/* ETHTOOL_A_PHY_INDEX */
 	size += nla_total_size(sizeof(u32));
 
 	/* ETHTOOL_A_DRVNAME */
-	if (phydev->drv)
-		size += nla_total_size(strlen(phydev->drv->name) + 1);
+	if (rep_data->drvname)
+		size += nla_total_size(strlen(rep_data->drvname) + 1);
 
 	/* ETHTOOL_A_NAME */
-	size += nla_total_size(strlen(dev_name(&phydev->mdio.dev)) + 1);
+	size += nla_total_size(strlen(rep_data->name) + 1);
 
 	/* ETHTOOL_A_PHY_UPSTREAM_TYPE */
 	size += nla_total_size(sizeof(u32));
 
-	if (phy_on_sfp(phydev)) {
-		const char *upstream_sfp_name = sfp_get_name(pdn->parent_sfp_bus);
-
-		/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
-		if (upstream_sfp_name)
-			size += nla_total_size(strlen(upstream_sfp_name) + 1);
+	if (rep_data->upstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->upstream_sfp_name) + 1);
 
-		/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	if (rep_data->upstream_index)
 		size += nla_total_size(sizeof(u32));
-	}
-
-	/* ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME */
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
 
-		if (sfp_name)
-			size += nla_total_size(strlen(sfp_name) + 1);
-	}
+	if (rep_data->downstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->downstream_sfp_name) + 1);
 
 	return size;
 }
 
-static int
-ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff *skb)
+static int phy_prepare_data(const struct ethnl_req_info *req_info,
+			    struct ethnl_reply_data *reply_data,
+			    const struct genl_info *info)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
-	enum phy_upstream ptype;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
+	struct phy_link_topology *topo = reply_data->dev->link_topo;
+	struct nlattr **tb = info->attrs;
+	struct phy_device_node *pdn;
+	struct phy_device *phydev;
 
-	ptype = pdn->upstream_type;
+	/* RTNL is held by th caller */
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
+				      info->extack);
+	if (IS_ERR_OR_NULL(phydev))
+		return -EOPNOTSUPP;
 
-	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, phydev->phyindex) ||
-	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, dev_name(&phydev->mdio.dev)) ||
-	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, ptype))
-		return -EMSGSIZE;
+	pdn = xa_load(&topo->phys, phydev->phyindex);
+	if (!pdn)
+		return -EOPNOTSUPP;
 
-	if (phydev->drv &&
-	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, phydev->drv->name))
-		return -EMSGSIZE;
+	rep_data->phyindex = phydev->phyindex;
+	rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
+	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+	rep_data->upstream_type = pdn->upstream_type;
 
-	if (ptype == PHY_UPSTREAM_PHY) {
+	if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
 		struct phy_device *upstream = pdn->upstream.phydev;
-		const char *sfp_upstream_name;
-
-		/* Parent index */
-		if (nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX, upstream->phyindex))
-			return -EMSGSIZE;
-
-		if (pdn->parent_sfp_bus) {
-			sfp_upstream_name = sfp_get_name(pdn->parent_sfp_bus);
-			if (sfp_upstream_name &&
-			    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
-					   sfp_upstream_name))
-				return -EMSGSIZE;
-		}
+		rep_data->upstream_index = upstream->phyindex;
 	}
 
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
+	if (pdn->parent_sfp_bus)
+		rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
+						      GFP_KERNEL);
 
-		if (sfp_name &&
-		    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
-				   sfp_name))
-			return -EMSGSIZE;
-	}
+	if (phydev->sfp_bus)
+		rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
+							GFP_KERNEL);
 
 	return 0;
 }
 
-static int ethnl_phy_parse_request(struct ethnl_req_info *req_base,
-				   struct nlattr **tb,
-				   struct netlink_ext_ack *extack)
+static int phy_fill_reply(struct sk_buff *skb,
+			  const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_link_topology *topo = req_base->dev->link_topo;
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device *phydev;
-
-	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PHY_HEADER,
-				      extack);
-	if (!phydev)
-		return 0;
-
-	if (IS_ERR(phydev))
-		return PTR_ERR(phydev);
-
-	if (!topo)
-		return 0;
-
-	req_info->pdn = xa_load(&topo->phys, phydev->phyindex);
-
-	return 0;
-}
-
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info)
-{
-	struct phy_req_info req_info = {};
-	struct nlattr **tb = info->attrs;
-	struct sk_buff *rskb;
-	void *reply_payload;
-	int reply_len;
-	int ret;
-
-	ret = ethnl_parse_header_dev_get(&req_info.base,
-					 tb[ETHTOOL_A_PHY_HEADER],
-					 genl_info_net(info), info->extack,
-					 true);
-	if (ret < 0)
-		return ret;
-
-	rtnl_lock();
-	netdev_lock_ops(req_info.base.dev);
-
-	ret = ethnl_phy_parse_request(&req_info.base, tb, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-
-	/* No PHY, return early */
-	if (!req_info.pdn)
-		goto err_unlock;
-
-	ret = ethnl_phy_reply_size(&req_info.base, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-	reply_len = ret + ethnl_reply_header_size();
-
-	rskb = ethnl_reply_init(reply_len, req_info.base.dev,
-				ETHTOOL_MSG_PHY_GET_REPLY,
-				ETHTOOL_A_PHY_HEADER,
-				info, &reply_payload);
-	if (!rskb) {
-		ret = -ENOMEM;
-		goto err_unlock;
-	}
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	ret = ethnl_phy_fill_reply(&req_info.base, rskb);
-	if (ret)
-		goto err_free_msg;
-
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	genlmsg_end(rskb, reply_payload);
-
-	return genlmsg_reply(rskb, info);
-
-err_free_msg:
-	nlmsg_free(rskb);
-err_unlock:
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	return ret;
-}
-
-struct ethnl_phy_dump_ctx {
-	struct phy_req_info	*phy_req_info;
-	unsigned long ifindex;
-	unsigned long phy_index;
-};
-
-int ethnl_phy_start(struct netlink_callback *cb)
-{
-	const struct genl_info *info = genl_info_dump(cb);
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	int ret;
+	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, rep_data->phyindex) ||
+	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, rep_data->name) ||
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, rep_data->upstream_type))
+		return -EMSGSIZE;
 
-	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+	if (rep_data->drvname &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, rep_data->drvname))
+		return -EMSGSIZE;
 
-	ctx->phy_req_info = kzalloc(sizeof(*ctx->phy_req_info), GFP_KERNEL);
-	if (!ctx->phy_req_info)
-		return -ENOMEM;
+	if (rep_data->upstream_index &&
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX,
+			rep_data->upstream_index))
+		return -EMSGSIZE;
 
-	ret = ethnl_parse_header_dev_get(&ctx->phy_req_info->base,
-					 info->attrs[ETHTOOL_A_PHY_HEADER],
-					 sock_net(cb->skb->sk), cb->extack,
-					 false);
-	ctx->ifindex = 0;
-	ctx->phy_index = 0;
+	if (rep_data->upstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+			   rep_data->upstream_sfp_name))
+		return -EMSGSIZE;
 
-	if (ret)
-		kfree(ctx->phy_req_info);
+	if (rep_data->downstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+			   rep_data->downstream_sfp_name))
+		return -EMSGSIZE;
 
-	return ret;
+	return 0;
 }
 
-int ethnl_phy_done(struct netlink_callback *cb)
+static void phy_cleanup_data(struct ethnl_reply_data *reply_data)
 {
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-
-	if (ctx->phy_req_info->base.dev)
-		ethnl_parse_header_dev_put(&ctx->phy_req_info->base);
-
-	kfree(ctx->phy_req_info);
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	return 0;
+	kfree(rep_data->drvname);
+	kfree(rep_data->name);
+	kfree(rep_data->upstream_sfp_name);
+	kfree(rep_data->downstream_sfp_name);
 }
 
-static int ethnl_phy_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				  struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct phy_req_info *pri = ctx->phy_req_info;
-	struct phy_device_node *pdn;
-	int ret = 0;
-	void *ehdr;
-
-	if (!dev->link_topo)
-		return 0;
-
-	xa_for_each_start(&dev->link_topo->phys, ctx->phy_index, pdn, ctx->phy_index) {
-		ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_PHY_GET_REPLY);
-		if (!ehdr) {
-			ret = -EMSGSIZE;
-			break;
-		}
-
-		ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_PHY_HEADER);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		pri->pdn = pdn;
-		ret = ethnl_phy_fill_reply(&pri->base, skb);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		genlmsg_end(skb, ehdr);
-	}
+const struct ethnl_request_ops ethnl_phy_request_ops = {
+	.request_cmd		= ETHTOOL_MSG_PHY_GET,
+	.reply_cmd		= ETHTOOL_MSG_PHY_GET_REPLY,
+	.hdr_attr		= ETHTOOL_A_PHY_HEADER,
+	.req_info_size		= sizeof(struct phy_req_info),
+	.reply_data_size	= sizeof(struct phy_reply_data),
 
-	return ret;
-}
+	.prepare_data		= phy_prepare_data,
+	.reply_size		= phy_reply_size,
+	.fill_reply		= phy_fill_reply,
+	.cleanup_data		= phy_cleanup_data,
 
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct net *net = sock_net(skb->sk);
-	struct net_device *dev;
-	int ret = 0;
-
-	rtnl_lock();
-
-	if (ctx->phy_req_info->base.dev) {
-		dev = ctx->phy_req_info->base.dev;
-		netdev_lock_ops(dev);
-		ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-		netdev_unlock_ops(dev);
-	} else {
-		for_each_netdev_dump(net, dev, ctx->ifindex) {
-			netdev_lock_ops(dev);
-			ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-			netdev_unlock_ops(dev);
-			if (ret)
-				break;
-
-			ctx->phy_index = 0;
-		}
-	}
-	rtnl_unlock();
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
 
-	return ret;
-}
+	.allow_pernetdev_dump	= true,
+};
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:38 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:38 +0100
Subject: [PATCH net-next v2 6/7] net: ethtool: plca: Use per-PHY DUMP operations
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-7-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PLCA-able PHY on the link.

This is done for both PLCA status and PLCA config.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: No changes

 net/ethtool/plca.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c
index e1f7820a6158..2148ff607561 100644
--- a/net/ethtool/plca.c
+++ b/net/ethtool/plca.c
@@ -191,6 +191,12 @@ const struct ethnl_request_ops ethnl_plca_cfg_request_ops = {
 
 	.set			= ethnl_set_plca,
 	.set_ntf_cmd		= ETHTOOL_MSG_PLCA_NTF,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
 
 // PLCA get status message -------------------------------------------------- //
@@ -268,4 +274,10 @@ const struct ethnl_request_ops ethnl_plca_status_request_ops = {
 	.prepare_data		= plca_get_status_prepare_data,
 	.reply_size		= plca_get_status_reply_size,
 	.fill_reply		= plca_get_status_fill_reply,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From v.pavani at samsung.com  Fri Mar  7 01:24:03 2025
From: v.pavani at samsung.com (Varada Pavani)
Date: Fri,  7 Mar 2025 14:54:03 +0530
Subject: [PATCH v3] clk: samsung: Use samsung CCF common function
References: <CGME20250307093024epcas5p1e0be921d3f3445c67daf399e451bb203@epcas5p1.samsung.com>
Message-ID: <20250307092403.19742-1-v.pavani@samsung.com>

Use samsung CCF function which registers multiple clock providers using
single function call samsung_cmu_register_clocks().

Signed-off-by: Varada Pavani <v.pavani at samsung.com>
---

Changes in V3:
-Addressed checkpatch warning identified when run with --strict option, as per
review comment from Krzysztof. Below is the warning from checkpatch.
"CHECK: Unbalanced braces around else statement"
-Here is the link for V2 https://patchwork.kernel.org/project/linux-clk/patch/20250225131918.50925-2-v.pavani at samsung.com/

Changes in V2:
-No review comments in V1.

 drivers/clk/samsung/clk-exynos4.c | 74 ++++++++++++++++++-------------
 1 file changed, 42 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 16be0c53903c..8fc89bde0d24 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1269,6 +1269,45 @@ static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = {
 		CPUCLK_LAYOUT_E4210, e4412_armclk_d),
 };
 
+static const struct samsung_cmu_info cmu_info_exynos4 __initconst = {
+	.mux_clks		= exynos4_mux_clks,
+	.nr_mux_clks		= ARRAY_SIZE(exynos4_mux_clks),
+	.div_clks		= exynos4_div_clks,
+	.nr_div_clks		= ARRAY_SIZE(exynos4_div_clks),
+	.gate_clks		= exynos4_gate_clks,
+	.nr_gate_clks		= ARRAY_SIZE(exynos4_gate_clks),
+	.fixed_factor_clks	= exynos4_fixed_factor_clks,
+	.nr_fixed_factor_clks	= ARRAY_SIZE(exynos4_fixed_factor_clks),
+	.fixed_clks	= exynos4_fixed_rate_clks,
+	.nr_fixed_clks	= ARRAY_SIZE(exynos4_fixed_rate_clks),
+};
+
+static const struct samsung_cmu_info cmu_info_exynos4210 __initconst = {
+	.mux_clks		= exynos4210_mux_clks,
+	.nr_mux_clks		= ARRAY_SIZE(exynos4210_mux_clks),
+	.div_clks		= exynos4210_div_clks,
+	.nr_div_clks		= ARRAY_SIZE(exynos4210_div_clks),
+	.gate_clks		= exynos4210_gate_clks,
+	.nr_gate_clks		= ARRAY_SIZE(exynos4210_gate_clks),
+	.fixed_factor_clks	= exynos4210_fixed_factor_clks,
+	.nr_fixed_factor_clks	= ARRAY_SIZE(exynos4210_fixed_factor_clks),
+	.fixed_clks	= exynos4210_fixed_rate_clks,
+	.nr_fixed_clks	= ARRAY_SIZE(exynos4210_fixed_rate_clks),
+	.cpu_clks		= exynos4210_cpu_clks,
+	.nr_cpu_clks		= ARRAY_SIZE(exynos4210_cpu_clks),
+};
+
+static const struct samsung_cmu_info cmu_info_exynos4x12 __initconst = {
+	.mux_clks		= exynos4x12_mux_clks,
+	.nr_mux_clks		= ARRAY_SIZE(exynos4x12_mux_clks),
+	.div_clks		= exynos4x12_div_clks,
+	.nr_div_clks		= ARRAY_SIZE(exynos4x12_div_clks),
+	.gate_clks		= exynos4x12_gate_clks,
+	.nr_gate_clks		= ARRAY_SIZE(exynos4x12_gate_clks),
+	.fixed_factor_clks	= exynos4x12_fixed_factor_clks,
+	.nr_fixed_factor_clks	= ARRAY_SIZE(exynos4x12_fixed_factor_clks),
+};
+
 /* register exynos4 clocks */
 static void __init exynos4_clk_init(struct device_node *np,
 				    enum exynos4_soc soc)
@@ -1322,41 +1361,12 @@ static void __init exynos4_clk_init(struct device_node *np,
 					ARRAY_SIZE(exynos4x12_plls));
 	}
 
-	samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
-			ARRAY_SIZE(exynos4_fixed_rate_clks));
-	samsung_clk_register_mux(ctx, exynos4_mux_clks,
-			ARRAY_SIZE(exynos4_mux_clks));
-	samsung_clk_register_div(ctx, exynos4_div_clks,
-			ARRAY_SIZE(exynos4_div_clks));
-	samsung_clk_register_gate(ctx, exynos4_gate_clks,
-			ARRAY_SIZE(exynos4_gate_clks));
-	samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
-			ARRAY_SIZE(exynos4_fixed_factor_clks));
+	samsung_cmu_register_clocks(ctx, &cmu_info_exynos4);
 
 	if (exynos4_soc == EXYNOS4210) {
-		samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
-			ARRAY_SIZE(exynos4210_fixed_rate_clks));
-		samsung_clk_register_mux(ctx, exynos4210_mux_clks,
-			ARRAY_SIZE(exynos4210_mux_clks));
-		samsung_clk_register_div(ctx, exynos4210_div_clks,
-			ARRAY_SIZE(exynos4210_div_clks));
-		samsung_clk_register_gate(ctx, exynos4210_gate_clks,
-			ARRAY_SIZE(exynos4210_gate_clks));
-		samsung_clk_register_fixed_factor(ctx,
-			exynos4210_fixed_factor_clks,
-			ARRAY_SIZE(exynos4210_fixed_factor_clks));
-		samsung_clk_register_cpu(ctx, exynos4210_cpu_clks,
-				ARRAY_SIZE(exynos4210_cpu_clks));
+		samsung_cmu_register_clocks(ctx, &cmu_info_exynos4210);
 	} else {
-		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
-			ARRAY_SIZE(exynos4x12_mux_clks));
-		samsung_clk_register_div(ctx, exynos4x12_div_clks,
-			ARRAY_SIZE(exynos4x12_div_clks));
-		samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
-			ARRAY_SIZE(exynos4x12_gate_clks));
-		samsung_clk_register_fixed_factor(ctx,
-			exynos4x12_fixed_factor_clks,
-			ARRAY_SIZE(exynos4x12_fixed_factor_clks));
+		samsung_cmu_register_clocks(ctx, &cmu_info_exynos4x12);
 		if (soc == EXYNOS4412)
 			samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
 					ARRAY_SIZE(exynos4412_cpu_clks));
-- 
2.17.1



From shradha.t at samsung.com  Fri Mar  7 01:37:20 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Fri, 7 Mar 2025 15:07:20 +0530
Subject: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
In-Reply-To: <20250306090234.GA390800@rocinante>
References: <20250304171154.njoygsvfd567pb66@thinkpad>
	<20250305173826.GA303920@bhelgaas>
	<20250305182833.cgrwbrcwzjscxmku@thinkpad>
	<20250305190955.GK847772@rocinante>
	<CAMuHMdVRSjkss3gPnocXpfPQ=mEo4AevpaU=fdGvm=kb3RTmcQ@mail.gmail.com>
	<CGME20250306090240epcas5p4f5ce09cf67a116dd3c976bfc846f1b14@epcas5p4.samsung.com>
	<20250306090234.GA390800@rocinante>
Message-ID: <075401db8f44$88861bc0$99925340$@samsung.com>



> -----Original Message-----
> From: Krzysztof Wilczy?ski <kw at linux.com>
> Sent: 06 March 2025 14:33
> To: Geert Uytterhoeven <geert at linux-m68k.org>
> Cc: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>; Bjorn Helgaas <helgaas at kernel.org>; Fan Ni
> <nifan.cxl at gmail.com>; Shradha Todi <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com;
> jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com; a.manzanares at samsung.com; pankaj.dubey at samsung.com;
> cassel at kernel.org; 18255117159 at 163.com; xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com; will at kernel.org;
> mark.rutland at arm.com; Yoshihiro Shimoda <yoshihiro.shimoda.uh at renesas.com>; Linux-Renesas <linux-renesas-
> soc at vger.kernel.org>
> Subject: Re: [PATCH v7 3/5] Add debugfs based silicon debug support in DWC
> 
> Hello,
> 
> [...]
> > Another issue is that the caller does not handle failures correctly,
> > given (A) the irqdomain WARNING I got, and (B) the half-registered PCI
> > bus, oopsing on "lspci"...
> 
> This is something we will look into.  A more robust DesignWare core is something we would definitely want to have.
> 

The issue here was that " pci_host_probe(bridge)" was being called right before doing the debugfs init.
So upon failure, the cleanup path should have included:
        pci_stop_root_bus(pp->bridge->bus);
        pci_remove_root_bus(pp->bridge->bus);

I missed that, which was probably causing the half-registered PCI bus. Since we are going with no error
propagation now, there is no issue anymore. Sorry for missing that.

> Sorry about the issues with this...
> 
> [...]
> > > -int dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > > +void dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > >  {
> > >         char dirname[DWC_DEBUGFS_BUF_MAX];
> > >         struct device *dev = pci->dev; @@ -174,17 +174,15 @@ int
> > > dwc_pcie_debugfs_init(struct dw_pcie *pci)
> > >         snprintf(dirname, DWC_DEBUGFS_BUF_MAX, "dwc_pcie_%s", dev_name(dev));
> > >         dir = debugfs_create_dir(dirname, NULL);
> > >         debugfs = devm_kzalloc(dev, sizeof(*debugfs), GFP_KERNEL);
> > > -       if (!debugfs)
> > > -               return -ENOMEM;
> > > +       if (!debugfs) {
> > > +               dev_err(dev, "failed to allocate memory for
> > > + debugfs\n");
> >
> > There is no need to print an error message when a memory allocation
> > fails, as the memory allocation core already takes care of that.
> > So please drop the dev_err() call.
> 
> Done.  Thank you!
> 
> 	Krzysztof




From shradha.t at samsung.com  Fri Mar  7 01:47:50 2025
From: shradha.t at samsung.com (Shradha Todi)
Date: Fri, 7 Mar 2025 15:17:50 +0530
Subject: [PATCH v7 5/5] Add debugfs based statistical counter support in
 DWC
In-Reply-To: <Z8fSWcR_aXyxmFEZ@debian>
References: <20250221131548.59616-1-shradha.t@samsung.com>
	<CGME20250221132043epcas5p27fde98558b13b3311cdc467e8f246380@epcas5p2.samsung.com>
	<20250221131548.59616-6-shradha.t@samsung.com> <Z8XuuNb6TRevUlHH@debian>
	<20250303194228.GB1552306@rocinante> <Z8YZEALV71PUkXpF@debian>
	<061401db8d28$5f0a4b40$1d1ee1c0$@samsung.com> <Z8fSWcR_aXyxmFEZ@debian>
Message-ID: <075501db8f45$ff6f9620$fe4ec260$@samsung.com>



> -----Original Message-----
> From: Fan Ni <nifan.cxl at gmail.com>
> Sent: 05 March 2025 09:56
> To: Shradha Todi <shradha.t at samsung.com>
> Cc: 'Fan Ni' <nifan.cxl at gmail.com>; 'Krzysztof Wilczy?ski' <kw at linux.com>; linux-kernel at vger.kernel.org; linux-pci at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org; lpieralisi at kernel.org;
> robh at kernel.org; bhelgaas at google.com; jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com; a.manzanares at samsung.com;
> pankaj.dubey at samsung.com; cassel at kernel.org; 18255117159 at 163.com; xueshuai at linux.alibaba.com; renyu.zj at linux.alibaba.com;
> will at kernel.org; mark.rutland at arm.com
> Subject: Re: [PATCH v7 5/5] Add debugfs based statistical counter support in DWC
> 
> On Tue, Mar 04, 2025 at 10:40:43PM +0530, Shradha Todi wrote:
> >
> >
> > > -----Original Message-----
> > > From: Fan Ni <nifan.cxl at gmail.com>
> > > Sent: 04 March 2025 02:33
> > > To: Krzysztof Wilczy?ski <kw at linux.com>
> > > Cc: Fan Ni <nifan.cxl at gmail.com>; Shradha Todi
> > > <shradha.t at samsung.com>; linux-kernel at vger.kernel.org; linux-
> > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > linux-perf-users at vger.kernel.org; manivannan.sadhasivam at linaro.org;
> > > lpieralisi at kernel.org; robh at kernel.org; bhelgaas at google.com;
> > > jingoohan1 at gmail.com; Jonathan.Cameron at huawei.com;
> > > a.manzanares at samsung.com; pankaj.dubey at samsung.com;
> > > cassel at kernel.org; 18255117159 at 163.com; xueshuai at linux.alibaba.com;
> > > renyu.zj at linux.alibaba.com; will at kernel.org; mark.rutland at arm.com
> > > Subject: Re: [PATCH v7 5/5] Add debugfs based statistical counter
> > > support in DWC
> > >
> > > On Tue, Mar 04, 2025 at 04:42:28AM +0900, Krzysztof Wilczy?ski wrote:
> > > > Hello,
> > > >
> > > > [...]
> > > > > > +static ssize_t counter_value_read(struct file *file, char
> > > > > > +__user *buf, size_t count, loff_t *ppos) {
> > > > > > +	struct dwc_pcie_rasdes_priv *pdata = file->private_data;
> > > > > > +	struct dw_pcie *pci = pdata->pci;
> > > > > > +	struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
> > > > > > +	char debugfs_buf[DWC_DEBUGFS_BUF_MAX];
> > > > > > +	ssize_t pos;
> > > > > > +	u32 val;
> > > > > > +
> > > > > > +	mutex_lock(&rinfo->reg_event_lock);
> > > > > > +	set_event_number(pdata, pci, rinfo);
> > > > > > +	val = dw_pcie_readl_dbi(pci, rinfo->ras_cap_offset + RAS_DES_EVENT_COUNTER_DATA_REG);
> > > > > > +	mutex_unlock(&rinfo->reg_event_lock);
> > > > > > +	pos = scnprintf(debugfs_buf, DWC_DEBUGFS_BUF_MAX, "Counter
> > > > > > +value: %d\n", val);
> > > > > > +
> > > > > > +	return simple_read_from_buffer(buf, count, ppos,
> > > > > > +debugfs_buf, pos); }
> > > > >
> > > > > Do we need to check whether the counter is enabled or not for
> > > > > the event before retrieving the counter value?
> > > >
> > > > I believe, we have a patch that aims to address, have a look at:
> > > >
> > > >
> > > > https://lore.kernel.org/linux-pci/20250225171239.19574-1-manivanna
> > > > n.sa
> > > > dhasivam at linaro.org
> > >
> > > Maybe I missed something, that seems to fix counter_enable_read(), but here is to retrieve counter value.
> > > How dw_pcie_readl_dbi() can return something like "Counter Disabled"?
> > >
> > > Fan
> >
> > Hey Fan,
> > So the counter value will show 0 in case it is disabled so there will
> > not be any issues as per say. We could add the check here but I feel I
> > have already exposed the functionality to check if a counter is enabled or disabled, (by reading the counter_enable debugfs entry)
> so this could be handled in user space to only read the counter if it's enabled.
> Ok.
> Returning 0 when the counter is disabled makes sense to me.
> 
> Just some thought.
> 
> It seems natural to me if we make "counter_value" only visiable to users when the counter is enabled.
> 

Hey Fan,

This looks like a good suggestion to me. I have implemented this and in the process of testing. Since there is no support in the
debugfs framework for conditionally hiding certain files from user, the custom implementation is a little tricky and will need some
discussion before taking in. So let's take this up as a top up patch and live with returning 0 when the counter is disabled for now?

Thanks a lot for the suggestion.
Shradha 

> Fan
> >
> > > >
> > > > Thank you!
> > > >
> > > > 	Krzysztof
> >
> >




From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:35 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:35 +0100
Subject: [PATCH net-next v2 3/7] net: ethtool: netlink: Introduce command-specific dump_one_dev
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-4-maxime.chevallier@bootlin.com>

Prepare more generic ethnl DUMP hanldling, by allowing netlink commands
to register their own dump_one_dev() callback. This avoids having to
roll with a fully custom genl ->dumpit callback, allowing the re-use of some
ethnl plumbing.

Fallback to the default dump_one_dev behaviour when no custom callback
is found.

The command dump context is maintained within the ethnl_dump_ctx, that
we move in netlink.h so that command handlers can access it.

This context can be allocated/freed in new ->dump_start() and
->dump_done() callbacks.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: - Fix kdoc

 net/ethtool/netlink.c | 62 +++++++++++++++++++++++++------------------
 net/ethtool/netlink.h | 35 ++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index f391a11242de..ae06b72239a8 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -338,24 +338,6 @@ int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
 
 /* GET request helpers */
 
-/**
- * struct ethnl_dump_ctx - context structure for generic dumpit() callback
- * @ops:        request ops of currently processed message type
- * @req_info:   parsed request header of processed request
- * @reply_data: data needed to compose the reply
- * @pos_ifindex: saved iteration position - ifindex
- *
- * These parameters are kept in struct netlink_callback as context preserved
- * between iterations. They are initialized by ethnl_default_start() and used
- * in ethnl_default_dumpit() and ethnl_default_done().
- */
-struct ethnl_dump_ctx {
-	const struct ethnl_request_ops	*ops;
-	struct ethnl_req_info		*req_info;
-	struct ethnl_reply_data		*reply_data;
-	unsigned long			pos_ifindex;
-};
-
 static const struct ethnl_request_ops *
 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_STRSET_GET]	= &ethnl_strset_request_ops,
@@ -539,9 +521,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				      const struct ethnl_dump_ctx *ctx,
-				      const struct genl_info *info)
+static int ethnl_default_dump_one(struct sk_buff *skb,
+				  const struct ethnl_dump_ctx *ctx,
+				  const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -552,15 +534,15 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 	if (!ehdr)
 		return -EMSGSIZE;
 
-	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
 	rtnl_lock();
-	netdev_lock_ops(dev);
+	netdev_lock_ops(ctx->reply_data->dev);
 	ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
-	netdev_unlock_ops(dev);
+	netdev_unlock_ops(ctx->reply_data->dev);
 	rtnl_unlock();
 	if (ret < 0)
 		goto out;
-	ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
+	ret = ethnl_fill_reply_header(skb, ctx->reply_data->dev,
+				      ctx->ops->hdr_attr);
 	if (ret < 0)
 		goto out;
 	ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data);
@@ -568,11 +550,29 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 out:
 	if (ctx->ops->cleanup_data)
 		ctx->ops->cleanup_data(ctx->reply_data);
-	ctx->reply_data->dev = NULL;
+
 	if (ret < 0)
 		genlmsg_cancel(skb, ehdr);
 	else
 		genlmsg_end(skb, ehdr);
+
+	return ret;
+}
+
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
+{
+	int ret;
+
+	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
+
+	if (ctx->ops->dump_one_dev)
+		ret = ctx->ops->dump_one_dev(skb, ctx, info);
+	else
+		ret = ethnl_default_dump_one(skb, ctx, info);
+
+	ctx->reply_data->dev = NULL;
 	return ret;
 }
 
@@ -601,6 +601,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
+			ctx->req_info->dev = dev;
 			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
 							 genl_info_dump(cb));
 
@@ -663,6 +664,12 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	ctx->reply_data = reply_data;
 	ctx->pos_ifindex = 0;
 
+	if (ctx->ops->dump_start) {
+		ret = ctx->ops->dump_start(ctx);
+		if (ret)
+			goto free_reply_data;
+	}
+
 	return 0;
 
 free_reply_data:
@@ -678,6 +685,9 @@ static int ethnl_default_done(struct netlink_callback *cb)
 {
 	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
 
+	if (ctx->ops->dump_done)
+		ctx->ops->dump_done(ctx);
+
 	kfree(ctx->reply_data);
 	kfree(ctx->req_info);
 
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 4aaa73282d6a..79fe98190c64 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -307,6 +307,26 @@ struct ethnl_reply_data {
 	struct net_device		*dev;
 };
 
+/**
+ * struct ethnl_dump_ctx - context structure for generic dumpit() callback
+ * @ops:        request ops of currently processed message type
+ * @req_info:   parsed request header of processed request
+ * @reply_data: data needed to compose the reply
+ * @pos_ifindex: saved iteration position - ifindex
+ * @cmd_ctx: command-specific context to maintain across the dump.
+ *
+ * These parameters are kept in struct netlink_callback as context preserved
+ * between iterations. They are initialized by ethnl_default_start() and used
+ * in ethnl_default_dumpit() and ethnl_default_done().
+ */
+struct ethnl_dump_ctx {
+	const struct ethnl_request_ops	*ops;
+	struct ethnl_req_info		*req_info;
+	struct ethnl_reply_data		*reply_data;
+	unsigned long			pos_ifindex;
+	void				*cmd_ctx;
+};
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
@@ -373,6 +393,15 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  *	 - 0 if no configuration has changed
  *	 - 1 if configuration changed and notification should be generated
  *	 - negative errno on errors
+ * @dump_start:
+ *	Optional callback to prepare a dump operation, should there be a need
+ *	to maintain some context across the dump.
+ * @dump_one_dev:
+ *	Optional callback to generate all messages for a given netdev. This
+ *	is relevant only when a request can produce different results for the
+ *	same netdev depending on command-specific attributes.
+ * @dump_done:
+ *	Optional callback to cleanup any context allocated in ->dump_start()
  *
  * Description of variable parts of GET request handling when using the
  * unified infrastructure. When used, a pointer to an instance of this
@@ -409,6 +438,12 @@ struct ethnl_request_ops {
 			    struct genl_info *info);
 	int (*set)(struct ethnl_req_info *req_info,
 		   struct genl_info *info);
+
+	int (*dump_start)(struct ethnl_dump_ctx *ctx);
+	int (*dump_one_dev)(struct sk_buff *skb,
+			    struct ethnl_dump_ctx *ctx,
+			    const struct genl_info *info);
+	void (*dump_done)(struct ethnl_dump_ctx *ctx);
 };
 
 /* request handlers */
-- 
2.48.1



From maxime.chevallier at bootlin.com  Sat Mar  8 07:54:39 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Sat,  8 Mar 2025 16:54:39 +0100
Subject: [PATCH net-next v2 7/7] net: ethtool: pse-pd: Use per-PHY DUMP operations
In-Reply-To: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
Message-ID: <20250308155440.267782-8-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PSE PHY on the link.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V2: No changes

 net/ethtool/pse-pd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
index 4f6b99eab2a6..f3d14be8bdd9 100644
--- a/net/ethtool/pse-pd.c
+++ b/net/ethtool/pse-pd.c
@@ -314,4 +314,10 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
 
 	.set			= ethnl_set_pse,
 	/* PSE has no notification */
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From heiko at sntech.de  Sat Mar  8 08:25:09 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 08 Mar 2025 17:25:09 +0100
Subject: [PATCH 1/2] dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
In-Reply-To: <pnlkcc2rl7fegltovgtvp4xdxhonw72rclvhn7qmvb7xyuullm@xf5x6lcigji3>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <20250307120004.959980-2-amadeus@jmu.edu.cn>
 <pnlkcc2rl7fegltovgtvp4xdxhonw72rclvhn7qmvb7xyuullm@xf5x6lcigji3>
Message-ID: <5942715.DvuYhMxLoT@phil>

Hi Uwe,

Am Freitag, 7. M?rz 2025, 18:07:47 MEZ schrieb Uwe Kleine-K?nig:
> On Fri, Mar 07, 2025 at 08:00:03PM +0800, Chukun Pan wrote:
> > Document pwm compatible for rk3528 which is fallback compatible
> > of rk3328-pwm group.
> > 
> > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> 
> to prevent binding warnings it's probably sensible to let both patches
> go in via the same tree at the same time. Feel free to take the binding
> patch via rockchip/arm-soc.
> 
> Acked-by: Uwe Kleine-K?nig <ukleinek at kernel.org>

You already have the rk3562 binding in your for-next branch [0], which
could create merge-conflicts later on.

This patch already contains it, so should fit neatly onto your branch.

And binding warnings only come from linux-next, so won't trigger as the
pwm will feed the binding there too :-)

So I guess it might be better to take the binding through the pwm tree
and me then picking up the dts patch.

For the binding
Reviewed-by: Heiko Stuebner <heiko at sntech.de>


[0] https://web.git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git/commit/?h=pwm/for-next&id=058210e84b48dbb670a6bf72afaed6fbd8043a37




From jic23 at kernel.org  Sat Mar  8 08:29:28 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 8 Mar 2025 16:29:28 +0000
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <54a031d0-df47-4baa-a23a-1a79c0922542@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
	<e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
	<CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
	<54a031d0-df47-4baa-a23a-1a79c0922542@gmail.com>
Message-ID: <20250308162928.72bd1d1b@jic23-huawei>

On Wed, 5 Mar 2025 12:54:33 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> Thanks for the review David.
> 
> On 04/03/2025 11:25, David Lechner wrote:
> > On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
> > <mazziesaccount at gmail.com> wrote:  
> >>
> >> There are ADC ICs which may have some of the AIN pins usable for other
> >> functions. These ICs may have some of the AIN pins wired so that they
> >> should not be used for ADC.
> >>
> >> (Preferred?) way for marking pins which can be used as ADC inputs is to
> >> add corresponding channels at N nodes in the device tree as described in
> >> the ADC binding yaml.
> >>
> >> Add couple of helper functions which can be used to retrieve the channel
> >> information from the device node.
> >>
> >> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>
> >> ---  
> 
> >> + *
> >> + * Return:     Number of found channels on succes. Negative value to indicate  
> > 
> > s/succes/success/  
> 
> Thanks!
> 
> >> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> >> +                                         const struct iio_chan_spec *template,
> >> +                                         int max_chan_id,
> >> +                                         struct iio_chan_spec **cs)
> >> +{
> >> +       struct iio_chan_spec *chan_array, *chan;
> >> +       int num_chan = 0, ret;
> >> +
> >> +       num_chan = iio_adc_device_num_channels(dev);
> >> +       if (num_chan < 1)
> >> +               return num_chan;
> >> +
> >> +       chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
> >> +                                 GFP_KERNEL);
> >> +       if (!chan_array)
> >> +               return -ENOMEM;
> >> +
> >> +       chan = &chan_array[0];
> >> +
> >> +       device_for_each_child_node_scoped(dev, child) {
> >> +               u32 ch;
> >> +
> >> +               if (!fwnode_name_eq(child, "channel"))
> >> +                       continue;
> >> +
> >> +               ret = fwnode_property_read_u32(child, "reg", &ch);
> >> +               if (ret)
> >> +                       return ret;
> >> +
> >> +               if (max_chan_id != -1 && ch > max_chan_id)
> >> +                       return -ERANGE;
> >> +  
> > 
> > Should we use return dev_err_probe() on these to help with debugging a bad dtb?
> >   
> 
> I am not fan of using dev_err_probe() in a 'library code'. This is 
> because we never know if there'll be some odd use-case where this is not 
> called from the probe.
> 
> All in all, I'd leave adding most of the debugs to the callers - 
> especially because we do not expect to have bad device-trees after the 
> initial 'development stage' of a board. The board 'development stage' 
> should really reveal bugs which prevent the channels from being 
> registered - and after the DT is correct, these debug prints become 
> unnecessary (albeit minor) binary bloat.
> 
> >> +               *chan = *template;
> >> +               chan->channel = ch;
> >> +               chan++;
> >> +       }
> >> +
> >> +       *cs = chan_array;
> >> +
> >> +       return num_chan;
> >> +}
> >> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");  
> > 
> > We can make this less verbose by setting #define
> > DEFAULT_SYMBOL_NAMESPACE at the start of the file. Then we can just do
> > EXPORT_SYMBOL_GPL() throughout the rest of the file.  
> 
> I am not sure what to think of this. I use the good old 'ctrl + ]' in my 
> editor when I need to check how a function was supposed to be used. That 
> jumps to the spot of code where the function is. I'd like to see the 
> namespace mentioned there in order to not accidentally miss the fact the 
> function belongs to one.
> 
> OTOH, I do like simplifications. Yet, the added simplification might not 
> warrant the namespace not being visible in the function definition.
> 
> > Also, I would prefer if the namespace matched config name (IIO_ADC_HELPER).  
> 
> I had some lengthy discussion about this with Andy and Jonathan during 
> earlier review versions. In short, I don't like the idea of very 
> fragmented namespaces in IIO, which will just complicate the drivers 
> without providing any obvious benefit.
> 
> https://lore.kernel.org/all/20250222174842.57c091c5 at jic23-huawei/
> 
> >> +
> >> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> >> +                                         const struct iio_chan_spec *template,
> >> +                                         int max_chan_id,
> >> +                                         struct iio_chan_spec **cs);
> >> +  
> > 
> > There are some different opinions on this, but on the last patch I did
> > introducing a new namespace, the consensus seems to be that putting
> > the MODULE_IMPORT_NS() in the header file was convenient so that users
> > of the API don't have to remember to both include the header and add
> > the import macro.
> >   
> 
> I do like this suggestion, and I believe this would be the balance 
> between getting the benefit of hiding part of the symbols - while not 
> unnecessarily complicating the callers. I know some people are opposing 
> it though. My personal opinion is that having the MODULE_IMPORT_NS() in 
> a header would be neatly simplifying the calling code with very little 
> harm, especially here where including the header hardly has use-cases 
> outside the IIO ADC.
> 
> Unfortunately, the "safety" seems to often be a synonym for just "making 
> it intentionally hard". As Finnish people say: "K?rsi, k?rsi, 
> kirkkaamman kruunun saat". :)
> (Roughly translated as "Suffer, suffer, you will get a brighter crown").
> 
> Let's hear what Jonathan thinks of your suggestion.

For this particular case my intent was that all the IIO exports that
are suitable for use in simple IIO drives will be in this namespace,
we just haven't started that conversion yet.

As such, having it defined from a header for this helper isn't a good
thing to do.  Generally I prefer to see in driver code what namespaces
are involved but do understand the other viewpoint. In this case I
definitely don't think it is appropriate unless we go for a specific namespace
for just this helper.

Jonathan

> 
> Thanks!
> 	-- Matti
> 



From jonas at kwiboo.se  Sat Mar  8 08:34:29 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 8 Mar 2025 17:34:29 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add Xunlong Orange Pi 3B
In-Reply-To: <d1c600f1-a874-4bb8-8b9f-22a3414edfcc@gmail.com>
References: <20240626230319.1425316-1-jonas@kwiboo.se>
 <20240626230319.1425316-3-jonas@kwiboo.se>
 <d1c600f1-a874-4bb8-8b9f-22a3414edfcc@gmail.com>
Message-ID: <29739e60-15f5-4361-a57a-2e6b93fba09c@kwiboo.se>

Hi Arturas,

On 2025-03-08 15:53, Arturas Moskvinas wrote:
> On 6/27/24 2:03 AM, Jonas Karlman wrote:
> 
>> The Xunlong Orange Pi 3B is a single-board computer based on the
>> Rockchip RK3566 SoC.
> ...> +
>> +&gmac1 {
>> +	phy-handle = <&rgmii_phy1>;
>> +	status = "okay";
>> +};
>> +
>> +&mdio1 {
>> +	rgmii_phy1: ethernet-phy at 1 {
>> +		compatible = "ethernet-phy-ieee802.3-c22";
>> +		reg = <1>;
> 
> Jonas, were you able to test V1.1 board's Ethernet?

Yes, I have both a v1.1.1 and v2.1 hw revision of this board and
Ethernet should be working on both hw revisions.

> 
> Whenever I start the board - Ethernet initialization fails with:
> ```
> [   21.140055] rk_gmac-dwmac fe010000.ethernet eth0: __stmmac_open: 
> Cannot attach to PHY (error: -19)
> ```

This is because of a reset issue with Ethernet PHYs in Linux, see [1].

Two workarounds:
1. Let boot firmware reset the PHY before Linux, i.e. use U-Boot
   v2024.10 or newer.
2. Use a ethernet-phy-id compatible with correct phy-id to force Linux
   to attach the PHY.

I suggest you try to wipe U-Boot from SPI flash on your board and update
to use U-Boot v2025.01 and try again.

> 
> But if reset is performed inside gmac - initialization succeeds.

Use of deprecated snps,reset- props is not a proper fix for this issue,
instead Linux could use an improve Ethernet PHY initialization handling
and ensuring the PHY is reset before it tries to read a phy-id from it.

[1] https://lore.kernel.org/r/47d55aca-bee6-810f-379f-9431649fefa6 at kwiboo.se/

Regards,
Jonas

> 
> Eg. patch:
> ```
> --- 
> linux-6.12.17.orig/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
> +++ linux-6.12.17/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
> @@ -16,14 +16,14 @@
>   &gmac1 {
>   	phy-handle = <&rgmii_phy1>;
>   	status = "okay";
> +	snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
> +	snps,reset-active-low;
> +	snps,reset-delays-us = <0 50000 200000>;
>   };
> 
>   &mdio1 {
>   	rgmii_phy1: ethernet-phy at 1 {
>   		compatible = "ethernet-phy-ieee802.3-c22";
>   		reg = <1>;
> -		reset-assert-us = <20000>;
> -		reset-deassert-us = <50000>;
> -		reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
>   	};
>   };
> ```
>> +		reset-assert-us = <20000>;
>> +		reset-deassert-us = <50000>;
>> +		reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
>> +	};
>> +};
> 
> 
> Arturas Moskvinas



From jic23 at kernel.org  Sat Mar  8 08:35:05 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 8 Mar 2025 16:35:05 +0000
Subject: [PATCH v5 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <aabd8836dbe54ef54730d1cd112edb52a57cd353.1740993491.git.mazziesaccount@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
	<aabd8836dbe54ef54730d1cd112edb52a57cd353.1740993491.git.mazziesaccount@gmail.com>
Message-ID: <20250308163505.200135cc@jic23-huawei>

On Mon, 3 Mar 2025 13:33:02 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
> drivers avoid open-coding the for_each_node -loop for getting the
> channel IDs. The helper provides standard way to detect the ADC channel
> nodes (by the node name), and a standard way to convert the "reg"
> -propereties to channel identification numbers, used in the struct

same typo.

> iio_chan_spec. Furthermore, the helper can optionally check the found
> channel IDs are smaller than given maximum. This is useful for callers
> which later use the IDs for example for indexing a channel data array.
> 
> The original driver treated all found child nodes as channel nodes. The
> new helper requires channel nodes to be named channel[@N]. This should
> help avoid problems with devices which may contain also other but ADC
> child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
> string didn't reveal any in-tree .dts with channel nodes named
> otherwise. Also, same grep shows all the in-tree .dts seem to have
> channel IDs between 0..num of channels.
> 
> Use the new helper.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> 
Otherwise LGTM


From heiko at sntech.de  Sat Mar  8 08:51:50 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 08 Mar 2025 17:51:50 +0100
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
In-Reply-To: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
References: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
Message-ID: <5069079.31r3eYUQgx@phil>

Am Donnerstag, 6. M?rz 2025, 20:29:23 MEZ schrieb Nicolas Frattaroli:
> Despite the compatible already being listed in the bindings, the PHY
> driver never gained explicit support for it. This is especially a
> problem because the explicitly listed PHY addresses need to be specified
> for each SoC.
> 
> To solve this, add the compatible, and a PHY config, with the address
> gleaned from rk3576.dtsi.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>




From jonas at kwiboo.se  Sat Mar  8 09:23:32 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 8 Mar 2025 18:23:32 +0100
Subject: [PATCH v2 8/8] arm64: dts: rockchip: Enable SD-card interface on
 Radxa E20C
In-Reply-To: <Z8xh2mE1BTE4co43@pie>
References: <20250305194638.47187-1-ziyao@disroot.org>
 <20250307033508.656479-1-amadeus@jmu.edu.cn> <Z8qJqpUwi7VV8tJk@pie>
 <5a0a7ce1-1dfb-4d19-8a1e-0d89d177f5b8@kwiboo.se> <Z8xh2mE1BTE4co43@pie>
Message-ID: <8af199e4-90bb-4ad9-b0d3-84cf443b04bb@kwiboo.se>

On 2025-03-08 16:27, Yao Zi wrote:
> Hi Jonas,
> 
> On Fri, Mar 07, 2025 at 07:45:00AM +0100, Jonas Karlman wrote:
>> Hi Chukun,
>>
>> On 2025-03-07 06:52, Yao Zi wrote:
>>> On Fri, Mar 07, 2025 at 11:35:08AM +0800, Chukun Pan wrote:
>>>> Hi,
>>>>
>>>>> +&sdmmc {
>>>>> +	bus-width = <4>;
>>>>> +	cap-mmc-highspeed;
>>>>> +	cap-sd-highspeed;
>>>>> +	disable-wp;
>>>>> +	no-sdio;
>>>>
>>>> With 'no-sdio' property:
>>>> [  129.608986] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
>>>> [  130.711168] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>>> [  130.725536] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
>>>> [  131.751240] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>>> [  131.765608] mmc_host mmc1: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
>>>> [  132.825083] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>>> [  132.839413] mmc_host mmc1: Bus speed (slot 0) = 187500Hz (slot req 187500Hz, actual 187500HZ div = 0)
>>>> [  133.960141] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>>>
>>>> Without 'no-sdio' property:
>>>> [  105.224019] mmc1: error -22 whilst initialising SDIO card
>>>> [  106.290838] mmc1: Card stuck being busy! __mmc_poll_for_busy
>>>> [  106.801931] dwmmc_rockchip ffc30000.mmc: Busy; trying anyway
>>>> [  107.385835] mmc_host mmc1: Timeou sending command (cmd 0x202000 arg 0x0 status 0x80202000)
>>>> [  107.400425] mmc_host mmc1: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
>>>> [  107.431561] mmc_host mmc1: Bus speed (slot 0) = 49800000Hz (slot req 50000000Hz, actual 49800000HZ div = 0)
>>>> [  107.433107] mmc1: new high speed SDIO card at address 0001
>>>
>>> So it seems the sdmmc controller actually works with SDIO commands as
>>> well? I don't expect that since the datasheet says RK3528 has only two
>>> SDIO 3.0 controllers.
>>>
>>> We could remove the "no-sdio" property if SDIO actually works. Will
>>> apply it in the next version if there's no objection against this.
>>
>> On the E20C the sdmmc controller is routed to a microSD card slot mainly
>> intended for use with microSD-cards and should normally not need SDIO.
> 
> As pointed out by Chukun, I found the hardware design guide for
> RK3528[1] (in Chinese) does claim that SDIO 3.0 is supported on all
> these three controllers in Chapter 2.3.1 (SDMMC/SDIO),
> 
>   RK3528 ??? 1 ? SDMMC ???? 2 ? SDIO ???????? SDIO3.0 ?
>   ???? MMC V4.51 ????? SDIO0 ? SDIO1 ????? 200MHz?SDMMC
>   ?????? 150MHz
> 
> translated to English,
> 
>   RK3528 integrates one SDMMC controller and two SDIO controllers, all
>   support SDIO3.0 protocol and MMC V4.51 protocol. Among them SDIO0 and
>   SDIO1 support 200MHz frequency at maximum, and SDMMC supports up to
>   150MHz.
> 
> So I think there's no reason to explicitly deny SDIO initialization
> sequence for the controller on Radxa E20C. imho this won't break
> anything even for a sdcard slot, will it?

I have no strong opinion on this, just something I have done on a few
boards recently.

When sd/sdio/mmc controller is attached to a microSD card slot I add
no-sdio, when my uSD to eMMC adapter is not working I also add no-mmc.

Similar if the controller is attached to emmc, I add no-sd and no-sdio,
and if used for sdio wifi, I add no-sd and no-mmc.

Mostly to minimize initialization time when slot is unpopulated or card
or module is faulty.

Not sure how common it is to use a microSD to SDIO adapter, sound like
an uncommon edge case, possible by someone who would know how to create
and use a dt-overlay. I also do not think there will be a common use
case with a uSD to eMMC adapter, however that is something this board
vendor sell themself [3], so may be a slightly more likely use case.

[3] https://radxa.com/products/accessories/emmc-to-usd

Use of these no- props could possible be considered configuration
and not information about the board hw design, so I am torn and as
mentioned above, I have no strong opinion about keeping no-sdio or not.

> 
> Additionally, this piece of information points out that wrong
> max-frequency is set for SDIO{0,1}. Rockchip overrides the frequency in
> devicetrees for the demo boards[2], I'm not sure whether it's for some
> speical reason or not.
> 
> Since I don't have a SDIO-capable board on hand, could you please test
> whether 200MHz actually works? If so I'll correct the SoC devicetree in
> v3.

I would change to use default 200MHz as stated in the HW design guide.

Did a short boot test on my Sige1 board and the SDIO module can at
least be identified using 200 MHz:

  dwmmc_rockchip ffc10000.mmc: IDMAC supports 32-bit address mode.
  dwmmc_rockchip ffc10000.mmc: Using internal DMA controller.
  dwmmc_rockchip ffc10000.mmc: Version ID is 270a
  dwmmc_rockchip ffc10000.mmc: DW MMC controller at irq 35,32 bit host data width,256 deep fifo
  mmc_host mmc2: card is non-removable.
  mmc_host mmc2: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
  mmc_host mmc2: Bus speed (slot 0) = 198000000Hz (slot req 200000000Hz, actual 198000000HZ div = 0)
  dwmmc_rockchip ffc10000.mmc: Successfully tuned phase to 30
  mmc2: new UHS-I speed SDR104 SDIO card at address 0001
  brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43752-sdio for chip BCM43752/2
  brcmfmac mmc2:0001:1: Direct firmware load for brcm/brcmfmac43752-sdio.armsom,sige1.bin failed with error -2
  brcmfmac mmc2:0001:1: Direct firmware load for brcm/brcmfmac43752-sdio.bin failed with error -2
  brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50

  ~ # cat /sys/kernel/debug/mmc2/ios
  clock:          200000000 Hz
  actual clock:   198000000 Hz
  vdd:            21 (3.3 ~ 3.4 V)
  bus mode:       2 (push-pull)
  chip select:    0 (don't care)
  power mode:     2 (on)
  bus width:      2 (4 bits)
  timing spec:    6 (sd uhs SDR104)
  signal voltage: 1 (1.80 V)
  driver type:    0 (driver type B)

If it turns out to be any instability issues for a specific board using
default 200 MHz, such board can always define a lower max-frequency in
its board .dts-file.

Regards,
Jonas

> 
>> What card/adapter do you have inserted in the microSD card slot that
>> requires use of SDIO instead of just SD or MMC? What is the use case you
>> have that requires removal of no-sdio on E20C?
>>
>> Regards,
>> Jonas
>>
>>>
>>> Further tests about the capabilities of the controller are welcome.
>>>
>>>> # cat /sys/kernel/debug/mmc1/ios
>>>> clock:          50000000 Hz
>>>> vdd:            21 (3.3 ~ 3.4 V)
>>>> bus mode:       2 (push-pull)
>>>> chip select:    0 (don't care)
>>>> power mode:     2 (on)
>>>> bus width:      2 (4 bits)
>>>> timing spec:    2 (sd high-speed)
>>>> signal voltage: 0 (3.30 V)
>>>> driver type:    0 (driver type B)
>>>>
>>>> Thanks,
>>>> Chukun
>>>>
>>>> -- 
>>>> 2.25.1
>>>>
>>>
>>> Best regards,
>>> Yao Zi
>>
> 
> Thanks,
> Yao Zi
> 
> [1]: https://github.com/DeciHD/rockchip_docs/blob/main/rk3528/RK3528%20Hardware%20Design%20Guide-CN-V1.0-20230525.pdf
> [2]: https://github.com/rockchip-linux/kernel/blob/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3528-demo1-lp4-v10.dtsi#L47



From heiko at sntech.de  Sat Mar  8 09:32:07 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:07 +0100
Subject: [PATCH v2] arm64: dts: rockchip: Enable ufshc on rk3576 evb1 board
In-Reply-To: <1741180586-140422-1-git-send-email-shawn.lin@rock-chips.com>
References: <1741180586-140422-1-git-send-email-shawn.lin@rock-chips.com>
Message-ID: <174145503576.101861.18242365156337250993.b4-ty@sntech.de>


On Wed, 05 Mar 2025 21:16:26 +0800, Shawn Lin wrote:
> RK3576 evb1 board supports UFS, so enable it.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Enable ufshc on rk3576 evb1 board
      (no commit info)

The base ufs controller node seems to have gone together with the
driver patch into the tree containing the ufs stuff, so this
does not build right now.

I've added it to a temporary branch and will try to get this in
after 6.15-rc1.


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:05 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:05 +0100
Subject: [PATCH v2 0/4] rockchip: Add support for leds and buttons on Radxa E20C
In-Reply-To: <20250304201642.831218-1-jonas@kwiboo.se>
References: <20250304201642.831218-1-jonas@kwiboo.se>
Message-ID: <174145503577.101861.8733087252860398696.b4-ty@sntech.de>


On Tue, 04 Mar 2025 20:16:33 +0000, Jonas Karlman wrote:
> The Radxa E20C has three GPIO leds, one SARADC maskrom button and one
> GPIO user button.
> 
> This series add leds, gpio-keys and adc-keys nodes to board DT to
> describe the leds and buttons found on Radxa E20C.
> 
> Changes in v2:
> - Change gpio-leds node name to leds
> - Drop patches already applied
> - Merge saradc and gpio button series
> - Reorder patches
> 
> [...]

Applied, thanks!

[1/4] arm64: dts: rockchip: Add leds node to Radxa E20C
      commit: 6a709e003492e9878d5f1357be0b2e1162e1e6a6
[2/4] arm64: dts: rockchip: Add user button to Radxa E20C
      commit: ad8afc8813567994164f2720189c819da8c22b99
[3/4] arm64: dts: rockchip: Add SARADC node for RK3528
      commit: 6e58302c84ce90aadbecd41efe1f69098a6f91e5
[4/4] arm64: dts: rockchip: Add maskrom button to Radxa E20C
      commit: 3a2819ee9c71d1c6388e456cc4eb042914d15d7e

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:01 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:01 +0100
Subject: [PATCH v3 0/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
In-Reply-To: <20250307100008.789129-1-amadeus@jmu.edu.cn>
References: <20250307100008.789129-1-amadeus@jmu.edu.cn>
Message-ID: <174145503573.101861.9257226762854268898.b4-ty@sntech.de>


On Fri, 07 Mar 2025 18:00:07 +0800, Chukun Pan wrote:
> Same as RK3568, RK3528 uses SCMI clk instead of standard ARMCLK.
> Add SCMI clk for CPU, GPU and RNG will also use it.
> 
> dmesg:
> [    0.061333] scmi_core: SCMI protocol bus registered
> [    0.125780] scmi_protocol scmi_dev.1: Enabled polling mode TX channel - prot_id:16
> [    0.126628] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
> [    0.127233] arm-scmi firmware:scmi: SCMI Protocol v2.0 'rockchip:' Firmware version 0x0
> 
> [...]

Applied, thanks!

[1/1] arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
      commit: fbcbc1fb93e14729bd87ab386b7f62694dcc8b51

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:00 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:00 +0100
Subject: [PATCH v2 0/2] arm64: dts: rockchip: Add rk3528 QoS register node
In-Reply-To: <20250306123809.273655-1-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
Message-ID: <174145503569.101861.837767867349168886.b4-ty@sntech.de>


On Thu, 06 Mar 2025 20:38:07 +0800, Chukun Pan wrote:
> Changes in v2:
>   Improve commit message
>   Add missing QoS compatible in DT
> 
> Chukun Pan (2):
>   dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
>   arm64: dts: rockchip: Add rk3528 QoS register node
> 
> [...]

Applied, thanks!

[1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
      commit: 19a634195c1abe498798b564cd6b81e6dd4533f7
[2/2] arm64: dts: rockchip: Add rk3528 QoS register node
      commit: 61a05d8ca3030a544175671f5fab7a8f29c24085

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:06 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:06 +0100
Subject: [PATCH] arm64: dts: rockchip: slow down emmc freq for rock 5 itx
In-Reply-To: <20250228143341.70244-1-liujianfeng1994@gmail.com>
References: <20250228143341.70244-1-liujianfeng1994@gmail.com>
Message-ID: <174145503579.101861.2973510887051189420.b4-ty@sntech.de>


On Fri, 28 Feb 2025 22:33:08 +0800, Jianfeng Liu wrote:
> The current max-frequency 200000000 of emmc is not stable. When doing
> heavy write there will be I/O Error. After setting max-frequency to
> 150000000 the emmc is stable under write.
> 
> Also remove property mmc-hs200-1_8v because we are already running at
> HS400 mode.
> 
> [...]

Applied, thanks!

[1/1] arm64: dts: rockchip: slow down emmc freq for rock 5 itx
      commit: b36402e4a0772d1b3da06a4f5fbd1cfe4d6f1cc0

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:03 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:03 +0100
Subject: [PATCH v2] arm64: dts: rockchip: Add HDMI support for rock-4d
In-Reply-To: <20250306180737.127726-1-detlev.casanova@collabora.com>
References: <20250306180737.127726-1-detlev.casanova@collabora.com>
Message-ID: <174145503575.101861.8670068937049575401.b4-ty@sntech.de>


On Thu, 06 Mar 2025 13:06:31 -0500, Detlev Casanova wrote:
> Enable HDMI and VOP nodes for the rock-4d board.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Add HDMI support for rock-4d
      commit: 4e4f54aaec204a27d51386a9dd0d3a805fea57f4

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:32:02 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat,  8 Mar 2025 18:32:02 +0100
Subject: [PATCH 0/2] Add SPI support for Radxa ROCK 4D
In-Reply-To: <20250228145304.581349-1-detlev.casanova@collabora.com>
References: <20250228145304.581349-1-detlev.casanova@collabora.com>
Message-ID: <174145503578.101861.6708020460490531029.b4-ty@sntech.de>


On Fri, 28 Feb 2025 09:50:46 -0500, Detlev Casanova wrote:
> The board comes with a SPI NOR chip connected on the FSPI0 interface.
> 
> Add the SFC nodes for the rk3576 SoC and enable sfc0 for the Radxa ROCK
> 4D.
> 
> Detlev Casanova (2):
>   arm64: dts: rockchip: Add SFC nodes for rk3576
>   arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D
> 
> [...]

Applied, thanks!

[1/2] arm64: dts: rockchip: Add SFC nodes for rk3576
      commit: 36299757129c897ef8c7ace6981070d367d89f89
[2/2] arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D
      commit: ba82f56bbf20e4166c988621cd0507509872848e

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Sat Mar  8 09:39:45 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 08 Mar 2025 18:39:45 +0100
Subject: [GIT PULL] Rockchip dts fixes for 6.14 #2
Message-ID: <1990830.tdWV9SEqCh@phil>

Hi Arnd, Kevin, Olof,

please find a below some additional fixes for the current
release 6.14 cycle.


Please pull

Thanks
Heiko


The following changes since commit 8546cfd08aa4b982acd2357403a1f15495d622ec:

  arm64: dts: rockchip: adjust SMMU interrupt type on rk3588 (2025-02-11 21:28:13 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.14-rockchip-dtsfixes2

for you to fetch changes up to b36402e4a0772d1b3da06a4f5fbd1cfe4d6f1cc0:

  arm64: dts: rockchip: slow down emmc freq for rock 5 itx (2025-03-08 18:21:11 +0100)

----------------------------------------------------------------
A number of emmc fixes (removing CQE from Theobroma boards and slower
freq on Rock-5-ITX) as well as some pinmux fixes and missing supplies.

----------------------------------------------------------------
Dragan Simic (2):
      arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board dtsi
      arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 board dtsi

Heiko Stuebner (2):
      arm64: dts: rockchip: remove supports-cqe from rk3588 jaguar
      arm64: dts: rockchip: remove supports-cqe from rk3588 tiger

Jianfeng Liu (1):
      arm64: dts: rockchip: slow down emmc freq for rock 5 itx

Justin Klaassen (1):
      arm64: dts: rockchip: fix u2phy1_host status for NanoPi R4S

Quentin Schulz (2):
      arm64: dts: rockchip: fix pinmux of UART0 for PX30 Ringneck on Haikou
      arm64: dts: rockchip: fix pinmux of UART5 for PX30 Ringneck on Haikou

Yao Zi (1):
      arm64: dts: rockchip: Remove undocumented sdmmc property from lubancat-1

 arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts | 12 ++++++++++++
 arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi   |  2 +-
 arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi    | 14 ++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts    |  1 -
 arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts        |  1 -
 arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts    |  3 +--
 arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi        |  1 -
 7 files changed, 28 insertions(+), 6 deletions(-)





From heiko at sntech.de  Sat Mar  8 10:21:59 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 08 Mar 2025 19:21:59 +0100
Subject: [GIT PULL] Rockchip dts64 changes for 6.15 #1
Message-ID: <13791512.uLZWGnKmhe@phil>

Hi soc maintainers,

please find below and in a subsequent pull-requests
Rockchip changes for for 6.15 .

It looks like the new year caused a flurry of activity, because
I don't remember having this much changes :-) .

Again, there haven't been arm32 changes this time around (so far)


Please pull.
Thanks
Heiko



The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.15-rockchip-dts64-1

for you to fetch changes up to ba82f56bbf20e4166c988621cd0507509872848e:

  arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D (2025-03-08 18:19:59 +0100)

----------------------------------------------------------------
New boards: MNT-Reform2 laptop (rk3588), OrangePi5-Ultra (rk3588),
Radxa Rock 4D (rk3576), Firefly ROC-RK3576-PC, Photonicat (rk3568)

New overlays: Video-adapters for Theobroma boards and one adapter used
in hw test scenarios.

Interesting bigger changes contain clock support for rk3528; support for
the hdmi1 controller as well as hdmi-audio support on both controllers on
rk3588; the hdmi-receiver of the rk3588 landed, and rk3576 got basic
graphics support and can now do hdmi output.

Another big block is that we're now doing overlays way better and are
including build-testing for applied overlays to the base dtb - similar
to how other arches already do this.

Of cours a big list of more controllers for rk3576 (nvmem, sfc), rk3588
(rng, spdif, regulator for gpu power-domain) and rk3528 (saradc, pinctrl)

And a huge number of board-level improvements and additions.

----------------------------------------------------------------
Alexey Charkov (5):
      arm64: dts: rockchip: Add finer-grained PWM states for the fan on Rock 5C
      arm64: dts: rockchip: Enable automatic fan control on Radxa Rock 5C
      arm64: dts: rockchip: switch Rock 5C to PMIC-based TSHUT reset
      arm64: dts: rockchip: Add SPDIF nodes to RK3588(s) device trees
      arm64: dts: rockchip: Enable SPDIF output on H96 Max V58

Andy Yan (5):
      arm64: dts: rockchip: Enable USB3 OTG on rk3588s Cool Pi 4B
      arm64: dts: rockchip: Add vop for rk3576
      arm64: dts: rockchip: Add hdmi for rk3576
      arm64: dts: rockchip: Enable hdmi display on sige5
      arm64: dts: rockchip: Enable hdmi out display for rk3576-evb-v10

Chris Morgan (1):
      arm64: dts: rockchip: remove rk3588 optee node

Chukun Pan (3):
      dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
      arm64: dts: rockchip: Add rk3528 QoS register node
      arm64: dts: rockchip: enable SCMI clk for RK3528 SoC

Cristian Ciocaltea (8):
      arm64: dts: rockchip: Enable HDMI0 PHY clk provider on RK3588
      arm64: dts: rockchip: Add HDMI0 PHY PLL clock source to VOP2 on RK3588
      arm64: dts: rockchip: Add PHY node for HDMI1 TX port on RK3588
      arm64: dts: rockchip: Add HDMI1 node on RK3588
      arm64: dts: rockchip: Enable HDMI1 on rock-5b
      arm64: dts: rockchip: Enable HDMI1 PHY clk provider on RK3588
      arm64: dts: rockchip: Add HDMI1 PHY PLL clock source to VOP2 on RK3588
      arm64: dts: rockchip: Enable HDMI1 on rk3588-evb1

Damon Ding (1):
      arm64: dts: rockchip: Fix label name of hdptxphy for RK3588

Detlev Casanova (6):
      dt-bindings: arm: rockchip: Add Radxa ROCK 4D board
      arm64: dts: rockchip: Add HDMI audio outputs for rk3588
      arm64: dts: rockchip: Enable HDMI audio outputs for Rock 5B
      arm64: dts: rockchip: Add HDMI support for rock-4d
      arm64: dts: rockchip: Add SFC nodes for rk3576
      arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D

Diederik de Haas (1):
      arm64: dts: rockchip: add 'chassis-type' property on PineNote

Dragan Simic (3):
      arm64: dts: rockchip: Describe why is HWRNG disabled in RK356x base dtsi
      arm64: dts: rockchip: Use "dma-noncoherent" in base RK3588 SoC dtsi
      arm64: dts: rockchip: linewrap gmac assigned-clocks on Quartz64 Model A/B files a bit

FUKAUMI Naoki (1):
      arm64: dts: rockchip: Enable USB OTG for Radxa ROCK Pi E

Heiko Stuebner (5):
      dt-bindings: arm: rockchip: Add Firefly ROC-RK3576-PC binding
      arm64: dts: rockchip: Add devicetree for the ROC-RK3576-PC
      arm64: dts: rockchip: add rk3576 otp node
      Merge branch 'v6.15-shared/clkids' into v6.15-armsoc/dts64
      arm64: dts: rockchip: add usb typec host support to rk3588-jaguar

Jagan Teki (1):
      arm64: dts: rockchip: Enable HDMI1 out for Edgeble-6TOPS Modules

Jianfeng Liu (2):
      arm64: dts: rockchip: Enable HDMI on armsom-sige7
      arm64: dts: rockchip: add hdmi1 support to ROCK 5 ITX

Jimmy Hon (6):
      arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Max
      arm64: dts: rockchip: Adapt to differences between Orange Pi 5 Max and Ultra
      dt-bindings: arm: rockchip: Add Xunlong Orange Pi 5 Ultra
      arm64: dts: rockchip: Add Orange Pi 5 Ultra board
      arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Ultra
      arm64: dts: rockchip: Enable HDMI1 audio output for Orange Pi 5 Ultra

Jonas Karlman (7):
      dt-bindings: soc: rockchip: Add RK3528 ioc grf syscon
      arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
      arm64: dts: rockchip: Add uart0 pinctrl to Radxa E20C
      arm64: dts: rockchip: Add leds node to Radxa E20C
      arm64: dts: rockchip: Add user button to Radxa E20C
      arm64: dts: rockchip: Add SARADC node for RK3528
      arm64: dts: rockchip: Add maskrom button to Radxa E20C

Junhao Xie (3):
      dt-bindings: vendor-prefixes: Add prefix for Ariaboard
      dt-bindings: arm: rockchip: Add Ariaboard Photonicat RK3568
      arm64: dts: rockchip: add dts for Ariaboard Photonicat RK3568

Kever Yang (1):
      dt-bindings: vendor-prefixes: Update rockchip company name

Krzysztof Kozlowski (2):
      arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3399 ROC PC PLUS
      arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3588 boards

Nicolas Frattaroli (1):
      arm64: dts: rockchip: Add rng node to RK3588

Patrick Wildt (2):
      dt-bindings: arm: rockchip: Add MNT Reform 2 (RCORE)
      arm64: dts: rockchip: add MNT Reform 2 laptop

Quentin Schulz (17):
      arm64: dts: rockchip: add support for sound output over HDMI on RK3399 Puma Haikou
      arm64: dts: rockchip: add overlay test for WolfVision PF5
      arm64: dts: rockchip: add overlay test for Edgeble NCM6A/NCM6B
      arm64: dts: rockchip: add overlay tests for Rock 5B PCIe overlays
      arm64: dts: rockchip: minimal support for Pre-ICT tester adapter for RK3588 Jaguar
      arm64: dts: rockchip: add support for HAIKOU-LVDS-9904379 adapter for PX30 Ringneck
      arm64: dts: rockchip: add overlay for PX30 Ringneck Haikou Video Demo adapter
      arm64: dts: rockchip: add overlay for RK3399 Puma Haikou Video Demo adapter
      arm64: dts: rockchip: enable UART5 on RK3588 Tiger Haikou
      arm64: dts: rockchip: move DDC bus from Haikou carrierboard to RK3399 Puma DTSI
      arm64: dts: rockchip: move I2C6 from Haikou carrierboard to Puma DTSI
      arm64: dts: rockchip: disable I2C6 on Puma DTSI
      arm64: dts: rockchip: enable I2S0 in Haikou carrierboard, not Puma DTSI
      arm64: dts: rockchip: add EEPROM found on RK3399 Puma Haikou
      arm64: dts: rockchip: enable Ethernet in Haikou carrierboard, not Puma DTSI
      arm64: dts: rockchip: enable I2C3 in Haikou carrierboard, not Ringneck DTSI
      arm64: dts: rockchip: disable I2C2 bus by default on RK3588 Tiger

Sebastian Reichel (2):
      arm64: dts: rockchip: Add GPU power domain regulator dependency for RK3588
      arm64: dts: rockchip: Enable HDMI receiver on rock-5b

Shreeya Patel (1):
      arm64: dts: rockchip: Add device tree support for HDMI RX Controller

Stephen Chen (1):
      arm64: dts: rockchip: Add Radxa ROCK 4D device tree

Yao Zi (5):
      dt-bindings: clock: Document clock and reset unit of RK3528
      arm64: dts: rockchip: Add clock generators for RK3528 SoC
      arm64: dts: rockchip: Add UART clocks for RK3528 SoC
      dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
      dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon

 .../devicetree/bindings/arm/rockchip.yaml          |   25 +-
 .../bindings/clock/rockchip,rk3528-cru.yaml        |   64 +
 Documentation/devicetree/bindings/mfd/syscon.yaml  |    2 +
 .../devicetree/bindings/soc/rockchip/grf.yaml      |    3 +
 .../devicetree/bindings/vendor-prefixes.yaml       |    4 +-
 arch/arm64/boot/dts/rockchip/Makefile              |   63 +
 .../px30-ringneck-haikou-lvds-9904379.dtso         |  130 ++
 .../rockchip/px30-ringneck-haikou-video-demo.dtso  |  190 +++
 .../boot/dts/rockchip/px30-ringneck-haikou.dts     |    2 +
 arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi    |    4 -
 arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts  |    8 +
 .../rockchip/rk3399-puma-haikou-video-demo.dtso    |  166 +++
 .../arm64/boot/dts/rockchip/rk3399-puma-haikou.dts |   26 +-
 arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi      |   10 +-
 .../arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts |    2 +-
 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi   | 1397 ++++++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts |  118 ++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi           |  354 ++++-
 arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi  |    2 +
 arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts |    8 +-
 arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts |    8 +-
 arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts |  588 ++++++++
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi      |    5 +
 .../boot/dts/rockchip/rk3576-armsom-sige5.dts      |   47 +
 arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts   |   47 +
 arch/arm64/boot/dts/rockchip/rk3576-roc-pc.dts     |  736 +++++++++++
 arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts    |  751 +++++++++++
 arch/arm64/boot/dts/rockchip/rk3576.dtsi           |  187 +++
 .../arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi |    4 +
 .../boot/dts/rockchip/rk3588-armsom-sige7.dts      |   51 +
 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi      |  110 +-
 .../boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts    |    2 +-
 .../dts/rockchip/rk3588-coolpi-cm5-genbook.dts     |    2 +-
 .../arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi |    4 +
 .../dts/rockchip/rk3588-edgeble-neu6a-common.dtsi  |    4 +
 .../boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi |   47 +
 arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts   |   50 +-
 arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi     |  186 +++
 arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi |    4 +
 .../dts/rockchip/rk3588-firefly-core-3588j.dtsi    |    4 +
 .../dts/rockchip/rk3588-firefly-icore-3588q.dtsi   |  443 +++++++
 .../boot/dts/rockchip/rk3588-firefly-itx-3588j.dts |    2 +-
 .../rockchip/rk3588-friendlyelec-cm3588-nas.dts    |    2 +-
 .../dts/rockchip/rk3588-friendlyelec-cm3588.dtsi   |    4 +
 .../arm64/boot/dts/rockchip/rk3588-h96-max-v58.dts |   30 +-
 .../dts/rockchip/rk3588-jaguar-pre-ict-tester.dtso |  171 +++
 arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts     |  224 +++-
 .../arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts |  336 +++++
 arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi |    6 +-
 arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts   |    4 +
 .../dts/rockchip/rk3588-orangepi-5-compact.dtsi    |    9 -
 .../boot/dts/rockchip/rk3588-orangepi-5-max.dts    |   51 +-
 .../boot/dts/rockchip/rk3588-orangepi-5-plus.dts   |    2 +-
 .../boot/dts/rockchip/rk3588-orangepi-5-ultra.dts  |   83 ++
 .../arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi |    6 +-
 .../arm64/boot/dts/rockchip/rk3588-quartzpro64.dts |    6 +-
 arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts |   53 +
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts    |   83 +-
 .../boot/dts/rockchip/rk3588-tiger-haikou.dts      |    4 +-
 arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi     |    5 +-
 .../arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts |    4 +
 .../arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi |    4 +
 arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts |   29 +-
 arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts  |    6 +-
 .../boot/dts/rockchip/rk3588s-gameforce-ace.dts    |    6 +-
 .../boot/dts/rockchip/rk3588s-indiedroid-nova.dts  |    8 +-
 .../boot/dts/rockchip/rk3588s-khadas-edge2.dts     |    4 +
 .../arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi |    6 +-
 arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts |    6 +-
 .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi      |    8 +-
 arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts   |    6 +-
 arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts   |   42 +-
 include/dt-bindings/clock/rockchip,rk3528-cru.h    |  453 +++++++
 include/dt-bindings/reset/rockchip,rk3528-cru.h    |  241 ++++
 74 files changed, 7693 insertions(+), 69 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3528-cru.yaml
 create mode 100644 arch/arm64/boot/dts/rockchip/px30-ringneck-haikou-lvds-9904379.dtso
 create mode 100644 arch/arm64/boot/dts/rockchip/px30-ringneck-haikou-video-demo.dtso
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-puma-haikou-video-demo.dtso
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-roc-pc.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-jaguar-pre-ict-tester.dtso
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-ultra.dts
 create mode 100644 include/dt-bindings/clock/rockchip,rk3528-cru.h
 create mode 100644 include/dt-bindings/reset/rockchip,rk3528-cru.h





From heiko at sntech.de  Sat Mar  8 10:22:34 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 08 Mar 2025 19:22:34 +0100
Subject: [GIT PULL] Rockchip defconfig64 changes for 6.15 #1
Message-ID: <3415370.aeNJFYEL58@phil>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.15-rockchip-defconfig64-1

for you to fetch changes up to 97d8fe4b7722104b9abdb9cbeb0e884f864c6477:

  arm64: defconfig: Enable Synopsys HDMI receiver (2025-03-06 14:08:26 +0100)

----------------------------------------------------------------
Enabling of the HDMI-receiver driver and new UFS storage driver.

----------------------------------------------------------------
Sebastian Reichel (1):
      arm64: defconfig: Enable Synopsys HDMI receiver

Shawn Lin (1):
      arm64: defconfig: Enable Rockchip UFS host driver

 arch/arm64/configs/defconfig | 3 +++
 1 file changed, 3 insertions(+)





From demonsingur at gmail.com  Sat Mar  8 10:33:46 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:46 +0200
Subject: [RFC PATCH 17/24] dt-bindings: media: i2c: max96712: increase number of output ports
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-18-demonsingur@gmail.com>

The MAX96712 and MAX96724 support up to 4 separate PHYs, depending on
the selected PHY configuration.

Document this possibility by increasing the number of output ports.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96712.yaml        | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 148d196b9acc..52b5603c2f53 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -45,10 +45,10 @@ properties:
         $ref: /schemas/graph.yaml#/properties/port
         description: GMSL Input port
 
-      port at 4:
+      port@[4-7]:
         $ref: /schemas/graph.yaml#/$defs/port-base
         unevaluatedProperties: false
-        description: CSI-2 Output
+        description: CSI-2 Output port
 
         properties:
           endpoint:
@@ -66,8 +66,15 @@ properties:
               - data-lanes
               - bus-type
 
-    required:
-      - port at 4
+    anyOf:
+      - required:
+          - port at 4
+      - required:
+          - port at 5
+      - required:
+          - port at 6
+      - required:
+          - port at 7
 
 required:
   - compatible
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:47 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:47 +0200
Subject: [RFC PATCH 18/24] dt-bindings: media: i2c: max96712: add support for I2C MUX
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-19-demonsingur@gmail.com>

MAX96712 and MAX96724 have more than one GMSL2 link, and each link is
capable of connecting to a separate serializer. If these serializers
have the same CFG pins configuration, they will also have the same I2C
address, causing conflicts unless the deserializer muxes the I2C
channels. Moreover, the serializers can have the same hardware attached
to their respective I2C bus.

The MAX96712 and MAX96724 suppot I2C channel muxing via the GMSL2 link
to facilitate communication to each of the connected serializers.

Document this capability.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96712.yaml | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 52b5603c2f53..4c4542d041cd 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -37,6 +37,17 @@ properties:
 
   enable-gpios: true
 
+  i2c-mux:
+    $ref: /schemas/i2c/i2c-mux.yaml#
+    patternProperties:
+      '^i2c@[0-3]$':
+        $ref: /schemas/i2c/i2c-controller.yaml#
+        properties:
+          reg:
+            items:
+              min: 0
+              max: 3
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:48 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:48 +0200
Subject: [RFC PATCH 19/24] dt-bindings: media: i2c: max96712: add support for POC supplies
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-20-demonsingur@gmail.com>

The GMSL links can carry power to the serializer when using coaxial
cables.

Document this capability.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96712.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 4c4542d041cd..1680d99b1f36 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -87,6 +87,10 @@ properties:
       - required:
           - port at 7
 
+patternProperties:
+  port[0-3]-poc-supply:
+    description: Regulator providing Power over Coax for GMSL ports
+
 required:
   - compatible
   - reg
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:50 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:50 +0200
Subject: [RFC PATCH 21/24] arm64: defconfig: disable deprecated MAX96712 driver
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-22-demonsingur@gmail.com>

The staging MAX96712 driver will be removed as its functionality has
been moved to the MAX96724 driver which makes use of the Maxim
GMSL2/3 deserializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 arch/arm64/configs/defconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..6e9bd9072d11 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1272,7 +1272,6 @@ CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
-CONFIG_VIDEO_MAX96712=m
 CONFIG_VIDEO_MESON_VDEC=m
 CONFIG_SND_BCM2835=m
 CONFIG_CHROME_PLATFORMS=y
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:51 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:51 +0200
Subject: [RFC PATCH 22/24] staging: media: remove MAX96712 driver
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-23-demonsingur@gmail.com>

Remove the staging MAX96712 driver.
Its functionality has been moved to the MAX96724 driver which makes use
of the Maxim GMSL2/3 deserializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                               |   1 -
 drivers/staging/media/Kconfig             |   2 -
 drivers/staging/media/Makefile            |   1 -
 drivers/staging/media/max96712/Kconfig    |  14 -
 drivers/staging/media/max96712/Makefile   |   2 -
 drivers/staging/media/max96712/max96712.c | 487 ----------------------
 6 files changed, 507 deletions(-)
 delete mode 100644 drivers/staging/media/max96712/Kconfig
 delete mode 100644 drivers/staging/media/max96712/Makefile
 delete mode 100644 drivers/staging/media/max96712/max96712.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1bc0ef81a1f0..7bc80ed9ba00 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14188,7 +14188,6 @@ M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
-F:	drivers/staging/media/max96712/max96712.c
 
 MAX96714 GMSL2 DESERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index b44214854399..fe29821f64a3 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -28,8 +28,6 @@ source "drivers/staging/media/imx/Kconfig"
 
 source "drivers/staging/media/ipu3/Kconfig"
 
-source "drivers/staging/media/max96712/Kconfig"
-
 source "drivers/staging/media/meson/vdec/Kconfig"
 
 source "drivers/staging/media/rkvdec/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index ad4e9619a9e0..1a562b3b6881 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -2,7 +2,6 @@
 obj-$(CONFIG_VIDEO_ATMEL_ISC_BASE)	+= deprecated/atmel/
 obj-$(CONFIG_INTEL_ATOMISP)     += atomisp/
 obj-$(CONFIG_VIDEO_IMX_MEDIA)	+= imx/
-obj-$(CONFIG_VIDEO_MAX96712)	+= max96712/
 obj-$(CONFIG_VIDEO_MESON_VDEC)	+= meson/vdec/
 obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC)	+= rkvdec/
 obj-$(CONFIG_VIDEO_STARFIVE_CAMSS)	+= starfive/
diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig
deleted file mode 100644
index 117fadf81bd0..000000000000
--- a/drivers/staging/media/max96712/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VIDEO_MAX96712
-	tristate "Maxim MAX96712 Quad GMSL2 Deserializer support"
-	depends on I2C
-	depends on OF_GPIO
-	depends on VIDEO_DEV
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	select MEDIA_CONTROLLER
-	help
-	  This driver supports the Maxim MAX96712 Quad GMSL2 Deserializer.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96712.
diff --git a/drivers/staging/media/max96712/Makefile b/drivers/staging/media/max96712/Makefile
deleted file mode 100644
index 70c1974ce3f0..000000000000
--- a/drivers/staging/media/max96712/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_VIDEO_MAX96712) += max96712.o
diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c
deleted file mode 100644
index 0751b2e04895..000000000000
--- a/drivers/staging/media/max96712/max96712.c
+++ /dev/null
@@ -1,487 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim MAX96712 Quad GMSL2 Deserializer Driver
- *
- * Copyright (C) 2021 Renesas Electronics Corporation
- * Copyright (C) 2021 Niklas S?derlund
- */
-
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/of_graph.h>
-#include <linux/regmap.h>
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define DEBUG_EXTRA_REG			0x09
-#define DEBUG_EXTRA_PCLK_25MHZ		0x00
-#define DEBUG_EXTRA_PCLK_75MHZ		0x01
-
-enum max96712_pattern {
-	MAX96712_PATTERN_CHECKERBOARD = 0,
-	MAX96712_PATTERN_GRADIENT,
-};
-
-struct max96712_info {
-	unsigned int dpllfreq;
-	bool have_debug_extra;
-};
-
-struct max96712_priv {
-	struct i2c_client *client;
-	struct regmap *regmap;
-	struct gpio_desc *gpiod_pwdn;
-
-	const struct max96712_info *info;
-
-	bool cphy;
-	struct v4l2_mbus_config_mipi_csi2 mipi;
-
-	struct v4l2_subdev sd;
-	struct v4l2_ctrl_handler ctrl_handler;
-	struct media_pad pads[1];
-
-	enum max96712_pattern pattern;
-};
-
-static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val)
-{
-	int ret;
-
-	ret = regmap_write(priv->regmap, reg, val);
-	if (ret)
-		dev_err(&priv->client->dev, "write 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg,
-				u8 mask, u8 val)
-{
-	int ret;
-
-	ret = regmap_update_bits(priv->regmap, reg, mask, val);
-	if (ret)
-		dev_err(&priv->client->dev, "update 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg,
-			       const void *val, size_t val_count)
-{
-	int ret;
-
-	ret = regmap_bulk_write(priv->regmap, reg, val, val_count);
-	if (ret)
-		dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_write_bulk_value(struct max96712_priv *priv,
-				     unsigned int reg, unsigned int val,
-				     size_t val_count)
-{
-	unsigned int i;
-	u8 values[4];
-
-	for (i = 1; i <= val_count; i++)
-		values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff;
-
-	return max96712_write_bulk(priv, reg, &values, val_count);
-}
-
-static void max96712_reset(struct max96712_priv *priv)
-{
-	max96712_update_bits(priv, 0x13, 0x40, 0x40);
-	msleep(20);
-}
-
-static void max96712_mipi_enable(struct max96712_priv *priv, bool enable)
-{
-	if (enable) {
-		max96712_update_bits(priv, 0x40b, 0x02, 0x02);
-		max96712_update_bits(priv, 0x8a0, 0x80, 0x80);
-	} else {
-		max96712_update_bits(priv, 0x8a0, 0x80, 0x00);
-		max96712_update_bits(priv, 0x40b, 0x02, 0x00);
-	}
-}
-
-static void max96712_mipi_configure(struct max96712_priv *priv)
-{
-	unsigned int i;
-	u8 phy5 = 0;
-
-	max96712_mipi_enable(priv, false);
-
-	/* Select 2x4 mode. */
-	max96712_write(priv, 0x8a0, 0x04);
-
-	/* TODO: Add support for 2-lane and 1-lane configurations. */
-	if (priv->cphy) {
-		/* Configure a 3-lane C-PHY using PHY0 and PHY1. */
-		max96712_write(priv, 0x94a, 0xa0);
-
-		/* Configure C-PHY timings. */
-		max96712_write(priv, 0x8ad, 0x3f);
-		max96712_write(priv, 0x8ae, 0x7d);
-	} else {
-		/* Configure a 4-lane D-PHY using PHY0 and PHY1. */
-		max96712_write(priv, 0x94a, 0xc0);
-	}
-
-	/* Configure lane mapping for PHY0 and PHY1. */
-	/* TODO: Add support for lane swapping. */
-	max96712_write(priv, 0x8a3, 0xe4);
-
-	/* Configure lane polarity for PHY0 and PHY1. */
-	for (i = 0; i < priv->mipi.num_data_lanes + 1; i++)
-		if (priv->mipi.lane_polarities[i])
-			phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i);
-	max96712_write(priv, 0x8a5, phy5);
-
-	/* Set link frequency for PHY0 and PHY1. */
-	max96712_update_bits(priv, 0x415, 0x3f,
-			     ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5));
-	max96712_update_bits(priv, 0x418, 0x3f,
-			     ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5));
-
-	/* Enable PHY0 and PHY1 */
-	max96712_update_bits(priv, 0x8a2, 0xf0, 0x30);
-}
-
-static void max96712_pattern_enable(struct max96712_priv *priv, bool enable)
-{
-	const u32 h_active = 1920;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	const u32 h_tot = h_active + h_fp + h_sw + h_bp;
-
-	const u32 v_active = 1080;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	const u32 v_tot = v_active + v_fp + v_sw + v_bp;
-
-	if (!enable) {
-		max96712_write(priv, 0x1051, 0x00);
-		return;
-	}
-
-	/* Set PCLK to 75MHz if device have DEBUG_EXTRA register. */
-	if (priv->info->have_debug_extra)
-		max96712_write(priv, DEBUG_EXTRA_REG, DEBUG_EXTRA_PCLK_75MHZ);
-
-	/* Configure Video Timing Generator for 1920x1080 @ 30 fps. */
-	max96712_write_bulk_value(priv, 0x1052, 0, 3);
-	max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3);
-	max96712_write_bulk_value(priv, 0x1058,
-				  (v_active + v_fp + + v_bp) * h_tot, 3);
-	max96712_write_bulk_value(priv, 0x105b, 0, 3);
-	max96712_write_bulk_value(priv, 0x105e, h_sw, 2);
-	max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2);
-	max96712_write_bulk_value(priv, 0x1062, v_tot, 2);
-	max96712_write_bulk_value(priv, 0x1064,
-				  h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3);
-	max96712_write_bulk_value(priv, 0x1067, h_active, 2);
-	max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2);
-	max96712_write_bulk_value(priv, 0x106b, v_active, 2);
-
-	/* Generate VS, HS and DE in free-running mode. */
-	max96712_write(priv, 0x1050, 0xfb);
-
-	/* Configure Video Pattern Generator. */
-	if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) {
-		/* Set checkerboard pattern size. */
-		max96712_write(priv, 0x1074, 0x3c);
-		max96712_write(priv, 0x1075, 0x3c);
-		max96712_write(priv, 0x1076, 0x3c);
-
-		/* Set checkerboard pattern colors. */
-		max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3);
-		max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3);
-
-		/* Generate checkerboard pattern. */
-		max96712_write(priv, 0x1051, 0x10);
-	} else {
-		/* Set gradient increment. */
-		max96712_write(priv, 0x106d, 0x10);
-
-		/* Generate gradient pattern. */
-		max96712_write(priv, 0x1051, 0x20);
-	}
-}
-
-static int max96712_s_stream(struct v4l2_subdev *sd, int enable)
-{
-	struct max96712_priv *priv = v4l2_get_subdevdata(sd);
-
-	if (enable) {
-		max96712_pattern_enable(priv, true);
-		max96712_mipi_enable(priv, true);
-	} else {
-		max96712_mipi_enable(priv, false);
-		max96712_pattern_enable(priv, false);
-	}
-
-	return 0;
-}
-
-static const struct v4l2_subdev_video_ops max96712_video_ops = {
-	.s_stream = max96712_s_stream,
-};
-
-static int max96712_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	static const struct v4l2_mbus_framefmt default_fmt = {
-		.width          = 1920,
-		.height         = 1080,
-		.code           = MEDIA_BUS_FMT_RGB888_1X24,
-		.colorspace     = V4L2_COLORSPACE_SRGB,
-		.field          = V4L2_FIELD_NONE,
-		.ycbcr_enc      = V4L2_YCBCR_ENC_DEFAULT,
-		.quantization   = V4L2_QUANTIZATION_DEFAULT,
-		.xfer_func      = V4L2_XFER_FUNC_DEFAULT,
-	};
-	struct v4l2_mbus_framefmt *fmt;
-
-	fmt = v4l2_subdev_state_get_format(state, 0);
-	*fmt = default_fmt;
-
-	return 0;
-}
-
-static const struct v4l2_subdev_internal_ops max96712_internal_ops = {
-	.init_state = max96712_init_state,
-};
-
-static const struct v4l2_subdev_pad_ops max96712_pad_ops = {
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = v4l2_subdev_get_fmt,
-};
-
-static const struct v4l2_subdev_ops max96712_subdev_ops = {
-	.video = &max96712_video_ops,
-	.pad = &max96712_pad_ops,
-};
-
-static const char * const max96712_test_pattern[] = {
-	"Checkerboard",
-	"Gradient",
-};
-
-static int max96712_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96712_priv *priv =
-		container_of(ctrl->handler, struct max96712_priv, ctrl_handler);
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		priv->pattern = ctrl->val ?
-			MAX96712_PATTERN_GRADIENT :
-			MAX96712_PATTERN_CHECKERBOARD;
-		break;
-	}
-	return 0;
-}
-
-static const struct v4l2_ctrl_ops max96712_ctrl_ops = {
-	.s_ctrl = max96712_s_ctrl,
-};
-
-static int max96712_v4l2_register(struct max96712_priv *priv)
-{
-	long pixel_rate;
-	int ret;
-
-	priv->sd.internal_ops = &max96712_internal_ops;
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops);
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 2);
-
-	/*
-	 * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an
-	 * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE.
-	 */
-	pixel_rate = priv->info->dpllfreq / priv->mipi.num_data_lanes * 1000000;
-	v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE,
-			  pixel_rate, pixel_rate, 1, pixel_rate);
-
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96712_test_pattern) - 1,
-				     0, 0, max96712_test_pattern);
-
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-	ret = priv->ctrl_handler.error;
-	if (ret)
-		goto error;
-
-	priv->pads[0].flags = MEDIA_PAD_FL_SOURCE;
-	ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads);
-	if (ret)
-		goto error;
-
-	v4l2_set_subdevdata(&priv->sd, priv);
-
-	priv->sd.state_lock = priv->ctrl_handler.lock;
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret)
-		goto error;
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret < 0) {
-		dev_err(&priv->client->dev, "Unable to register subdevice\n");
-		goto error;
-	}
-
-	return 0;
-error:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-}
-
-static int max96712_parse_dt(struct max96712_priv *priv)
-{
-	struct fwnode_handle *ep;
-	struct v4l2_fwnode_endpoint v4l2_ep = {
-		.bus_type = V4L2_MBUS_UNKNOWN,
-	};
-	unsigned int supported_lanes;
-	int ret;
-
-	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4,
-					     0, 0);
-	if (!ep) {
-		dev_err(&priv->client->dev, "Not connected to subdevice\n");
-		return -EINVAL;
-	}
-
-	ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
-	fwnode_handle_put(ep);
-	if (ret) {
-		dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n");
-		return -EINVAL;
-	}
-
-	switch (v4l2_ep.bus_type) {
-	case V4L2_MBUS_CSI2_DPHY:
-		supported_lanes = 4;
-		priv->cphy = false;
-		break;
-	case V4L2_MBUS_CSI2_CPHY:
-		supported_lanes = 3;
-		priv->cphy = true;
-		break;
-	default:
-		dev_err(&priv->client->dev, "Unsupported bus-type %u\n",
-			v4l2_ep.bus_type);
-		return -EINVAL;
-	}
-
-	if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) {
-		dev_err(&priv->client->dev, "Only %u data lanes supported\n",
-			supported_lanes);
-		return -EINVAL;
-	}
-
-	priv->mipi = v4l2_ep.bus.mipi_csi2;
-
-	return 0;
-}
-
-static const struct regmap_config max96712_i2c_regmap = {
-	.reg_bits = 16,
-	.val_bits = 8,
-	.max_register = 0x1f00,
-};
-
-static int max96712_probe(struct i2c_client *client)
-{
-	struct max96712_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->info = of_device_get_match_data(&client->dev);
-
-	priv->client = client;
-
-	priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap);
-	if (IS_ERR(priv->regmap))
-		return PTR_ERR(priv->regmap);
-
-	priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
-						   GPIOD_OUT_HIGH);
-	if (IS_ERR(priv->gpiod_pwdn))
-		return PTR_ERR(priv->gpiod_pwdn);
-
-	gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn");
-	gpiod_set_value_cansleep(priv->gpiod_pwdn, 1);
-
-	if (priv->gpiod_pwdn)
-		usleep_range(4000, 5000);
-
-	max96712_reset(priv);
-
-	ret = max96712_parse_dt(priv);
-	if (ret)
-		return ret;
-
-	max96712_mipi_configure(priv);
-
-	return max96712_v4l2_register(priv);
-}
-
-static void max96712_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96712_priv *priv = container_of(sd, struct max96712_priv, sd);
-
-	v4l2_async_unregister_subdev(&priv->sd);
-
-	gpiod_set_value_cansleep(priv->gpiod_pwdn, 0);
-}
-
-static const struct max96712_info max96712_info_max96712 = {
-	.dpllfreq = 1000,
-	.have_debug_extra = true,
-};
-
-static const struct max96712_info max96712_info_max96724 = {
-	.dpllfreq = 1200,
-};
-
-static const struct of_device_id max96712_of_table[] = {
-	{ .compatible = "maxim,max96712", .data = &max96712_info_max96712 },
-	{ .compatible = "maxim,max96724", .data = &max96712_info_max96724 },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, max96712_of_table);
-
-static struct i2c_driver max96712_i2c_driver = {
-	.driver	= {
-		.name = "max96712",
-		.of_match_table	= of_match_ptr(max96712_of_table),
-	},
-	.probe = max96712_probe,
-	.remove = max96712_remove,
-};
-
-module_i2c_driver(max96712_i2c_driver);
-
-MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver");
-MODULE_AUTHOR("Niklas S?derlund <niklas.soderlund at ragnatech.se>");
-MODULE_LICENSE("GPL");
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:52 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:52 +0200
Subject: [RFC PATCH 23/24] media: i2c: remove MAX96717 driver
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-24-demonsingur@gmail.com>

The previous MAX96717 driver has been removed and its functionality has
been moved to a MAX96717 driver which makes use of the Maxim GMSL2/3
serializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                  |    1 -
 drivers/media/i2c/Kconfig    |   17 -
 drivers/media/i2c/Makefile   |    1 -
 drivers/media/i2c/max96717.c | 1103 ----------------------------------
 4 files changed, 1122 deletions(-)
 delete mode 100644 drivers/media/i2c/max96717.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7bc80ed9ba00..12078126f478 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14204,7 +14204,6 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
-F:	drivers/media/i2c/max96717.c
 
 MAX9860 MONO AUDIO VOICE CODEC DRIVER
 M:	Peter Rosin <peda at axentia.se>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index e24c84962c92..6c595dffb280 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1636,23 +1636,6 @@ config VIDEO_MAX96714
 	  To compile this driver as a module, choose M here: the
 	  module will be called max96714.
 
-config VIDEO_MAX96717
-	tristate "Maxim MAX96717 GMSL2 Serializer support"
-	depends on OF && I2C && VIDEO_DEV && COMMON_CLK
-	select I2C_MUX
-	select MEDIA_CONTROLLER
-	select GPIOLIB
-	select V4L2_CCI_I2C
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	help
-	  Device driver for the Maxim MAX96717 GMSL2 Serializer.
-	  MAX96717 serializers convert video on a MIPI CSI-2
-	  input to a GMSL2 output.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96717.
-
 source "drivers/media/i2c/maxim-serdes/Kconfig"
 
 endmenu
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index b24e7cf7bb2f..de0680ebf190 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_VIDEO_M52790) += m52790.o
 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
 obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
-obj-$(CONFIG_VIDEO_MAX96717) += max96717.o
 obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/
 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
diff --git a/drivers/media/i2c/max96717.c b/drivers/media/i2c/max96717.c
deleted file mode 100644
index 9259d58ba734..000000000000
--- a/drivers/media/i2c/max96717.c
+++ /dev/null
@@ -1,1103 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim GMSL2 Serializer Driver
- *
- * Copyright (C) 2024 Collabora Ltd.
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/fwnode.h>
-#include <linux/gpio/driver.h>
-#include <linux/i2c-mux.h>
-#include <linux/i2c.h>
-#include <linux/regmap.h>
-
-#include <media/v4l2-cci.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define MAX96717_DEVICE_ID  0xbf
-#define MAX96717F_DEVICE_ID 0xc8
-#define MAX96717_PORTS      2
-#define MAX96717_PAD_SINK   0
-#define MAX96717_PAD_SOURCE 1
-#define MAX96717_CSI_NLANES 4
-
-#define MAX96717_DEFAULT_CLKOUT_RATE	24000000UL
-
-/* DEV */
-#define MAX96717_REG3    CCI_REG8(0x3)
-#define MAX96717_RCLKSEL GENMASK(1, 0)
-#define RCLKSEL_REF_PLL  CCI_REG8(0x3)
-#define MAX96717_REG6    CCI_REG8(0x6)
-#define RCLKEN           BIT(5)
-#define MAX96717_DEV_ID  CCI_REG8(0xd)
-#define MAX96717_DEV_REV CCI_REG8(0xe)
-#define MAX96717_DEV_REV_MASK GENMASK(3, 0)
-
-/* VID_TX Z */
-#define MAX96717_VIDEO_TX0 CCI_REG8(0x110)
-#define MAX96717_VIDEO_AUTO_BPP BIT(3)
-#define MAX96717_VIDEO_TX2 CCI_REG8(0x112)
-#define MAX96717_VIDEO_PCLKDET BIT(7)
-
-/* VTX_Z */
-#define MAX96717_VTX0                  CCI_REG8(0x24e)
-#define MAX96717_VTX1                  CCI_REG8(0x24f)
-#define MAX96717_PATTERN_CLK_FREQ      GENMASK(3, 1)
-#define MAX96717_VTX_VS_DLY            CCI_REG24(0x250)
-#define MAX96717_VTX_VS_HIGH           CCI_REG24(0x253)
-#define MAX96717_VTX_VS_LOW            CCI_REG24(0x256)
-#define MAX96717_VTX_V2H               CCI_REG24(0x259)
-#define MAX96717_VTX_HS_HIGH           CCI_REG16(0x25c)
-#define MAX96717_VTX_HS_LOW            CCI_REG16(0x25e)
-#define MAX96717_VTX_HS_CNT            CCI_REG16(0x260)
-#define MAX96717_VTX_V2D               CCI_REG24(0x262)
-#define MAX96717_VTX_DE_HIGH           CCI_REG16(0x265)
-#define MAX96717_VTX_DE_LOW            CCI_REG16(0x267)
-#define MAX96717_VTX_DE_CNT            CCI_REG16(0x269)
-#define MAX96717_VTX29                 CCI_REG8(0x26b)
-#define MAX96717_VTX_MODE              GENMASK(1, 0)
-#define MAX96717_VTX_GRAD_INC          CCI_REG8(0x26c)
-#define MAX96717_VTX_CHKB_COLOR_A      CCI_REG24(0x26d)
-#define MAX96717_VTX_CHKB_COLOR_B      CCI_REG24(0x270)
-#define MAX96717_VTX_CHKB_RPT_CNT_A    CCI_REG8(0x273)
-#define MAX96717_VTX_CHKB_RPT_CNT_B    CCI_REG8(0x274)
-#define MAX96717_VTX_CHKB_ALT          CCI_REG8(0x275)
-
-/* GPIO */
-#define MAX96717_NUM_GPIO         11
-#define MAX96717_GPIO_REG_A(gpio) CCI_REG8(0x2be + (gpio) * 3)
-#define MAX96717_GPIO_OUT         BIT(4)
-#define MAX96717_GPIO_IN          BIT(3)
-#define MAX96717_GPIO_RX_EN       BIT(2)
-#define MAX96717_GPIO_TX_EN       BIT(1)
-#define MAX96717_GPIO_OUT_DIS     BIT(0)
-
-/* FRONTTOP */
-/* MAX96717 only have CSI port 'B' */
-#define MAX96717_FRONTOP0     CCI_REG8(0x308)
-#define MAX96717_START_PORT_B BIT(5)
-
-/* MIPI_RX */
-#define MAX96717_MIPI_RX1       CCI_REG8(0x331)
-#define MAX96717_MIPI_LANES_CNT GENMASK(5, 4)
-#define MAX96717_MIPI_RX2       CCI_REG8(0x332) /* phy1 Lanes map */
-#define MAX96717_PHY2_LANES_MAP GENMASK(7, 4)
-#define MAX96717_MIPI_RX3       CCI_REG8(0x333) /* phy2 Lanes map */
-#define MAX96717_PHY1_LANES_MAP GENMASK(3, 0)
-#define MAX96717_MIPI_RX4       CCI_REG8(0x334) /* phy1 lane polarities */
-#define MAX96717_PHY1_LANES_POL GENMASK(6, 4)
-#define MAX96717_MIPI_RX5       CCI_REG8(0x335) /* phy2 lane polarities */
-#define MAX96717_PHY2_LANES_POL GENMASK(2, 0)
-
-/* MIPI_RX_EXT */
-#define MAX96717_MIPI_RX_EXT11 CCI_REG8(0x383)
-#define MAX96717_TUN_MODE      BIT(7)
-
-/* REF_VTG */
-#define REF_VTG0                CCI_REG8(0x3f0)
-#define REFGEN_PREDEF_EN        BIT(6)
-#define REFGEN_PREDEF_FREQ_MASK GENMASK(5, 4)
-#define REFGEN_PREDEF_FREQ_ALT  BIT(3)
-#define REFGEN_RST              BIT(1)
-#define REFGEN_EN               BIT(0)
-
-/* MISC */
-#define PIO_SLEW_1 CCI_REG8(0x570)
-
-enum max96717_vpg_mode {
-	MAX96717_VPG_DISABLED = 0,
-	MAX96717_VPG_CHECKERBOARD = 1,
-	MAX96717_VPG_GRADIENT = 2,
-};
-
-struct max96717_priv {
-	struct i2c_client		  *client;
-	struct regmap			  *regmap;
-	struct i2c_mux_core		  *mux;
-	struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
-	struct v4l2_subdev                sd;
-	struct media_pad                  pads[MAX96717_PORTS];
-	struct v4l2_ctrl_handler          ctrl_handler;
-	struct v4l2_async_notifier        notifier;
-	struct v4l2_subdev                *source_sd;
-	u16                               source_sd_pad;
-	u64			          enabled_source_streams;
-	u8                                pll_predef_index;
-	struct clk_hw                     clk_hw;
-	struct gpio_chip                  gpio_chip;
-	enum max96717_vpg_mode            pattern;
-};
-
-static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct max96717_priv, sd);
-}
-
-static inline struct max96717_priv *clk_hw_to_max96717(struct clk_hw *hw)
-{
-	return container_of(hw, struct max96717_priv, clk_hw);
-}
-
-static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
-{
-	return 0;
-}
-
-static int max96717_i2c_mux_init(struct max96717_priv *priv)
-{
-	priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
-				  1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
-				  max96717_i2c_mux_select, NULL);
-	if (!priv->mux)
-		return -ENOMEM;
-
-	return i2c_mux_add_adapter(priv->mux, 0, 0);
-}
-
-static inline int max96717_start_csi(struct max96717_priv *priv, bool start)
-{
-	return cci_update_bits(priv->regmap, MAX96717_FRONTOP0,
-			       MAX96717_START_PORT_B,
-			       start ? MAX96717_START_PORT_B : 0, NULL);
-}
-
-static int max96717_apply_patgen_timing(struct max96717_priv *priv,
-					struct v4l2_subdev_state *state)
-{
-	struct v4l2_mbus_framefmt *fmt =
-		v4l2_subdev_state_get_format(state, MAX96717_PAD_SOURCE);
-	const u32 h_active = fmt->width;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	u32 h_tot;
-	const u32 v_active = fmt->height;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	u32 v_tot;
-	int ret = 0;
-
-	h_tot = h_active + h_fp + h_sw + h_bp;
-	v_tot = v_active + v_fp + v_sw + v_bp;
-
-	/* 75 Mhz pixel clock */
-	cci_update_bits(priv->regmap, MAX96717_VTX1,
-			MAX96717_PATTERN_CLK_FREQ, 0xa, &ret);
-
-	dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height,
-		 fmt->width);
-
-	cci_write(priv->regmap, MAX96717_VTX_VS_DLY, 0, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_VS_HIGH, v_sw * h_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_VS_LOW,
-		  (v_active + v_fp + v_bp) * h_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_HIGH, h_sw, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_LOW, h_active + h_fp + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96717_VTX_V2D,
-		  h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_CNT, v_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_HIGH, h_active, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_LOW, h_fp + h_sw + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_CNT, v_active, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_A, 0xfecc00, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_B, 0x006aa7, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_A, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_B, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_ALT, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_GRAD_INC, 0x10, &ret);
-
-	return ret;
-}
-
-static int max96717_apply_patgen(struct max96717_priv *priv,
-				 struct v4l2_subdev_state *state)
-{
-	unsigned int val;
-	int ret = 0;
-
-	if (priv->pattern)
-		ret = max96717_apply_patgen_timing(priv, state);
-
-	cci_write(priv->regmap, MAX96717_VTX0, priv->pattern ? 0xfb : 0,
-		  &ret);
-
-	val = FIELD_PREP(MAX96717_VTX_MODE, priv->pattern);
-	cci_update_bits(priv->regmap, MAX96717_VTX29, MAX96717_VTX_MODE,
-			val, &ret);
-	return ret;
-}
-
-static int max96717_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96717_priv *priv =
-		container_of(ctrl->handler, struct max96717_priv, ctrl_handler);
-	int ret;
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		if (priv->enabled_source_streams)
-			return -EBUSY;
-		priv->pattern = ctrl->val;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Use bpp from bpp register */
-	ret = cci_update_bits(priv->regmap, MAX96717_VIDEO_TX0,
-			      MAX96717_VIDEO_AUTO_BPP,
-			      priv->pattern ? 0 : MAX96717_VIDEO_AUTO_BPP,
-			      NULL);
-
-	/*
-	 * Pattern generator doesn't work with tunnel mode.
-	 * Needs RGB color format and deserializer tunnel mode must be disabled.
-	 */
-	return cci_update_bits(priv->regmap, MAX96717_MIPI_RX_EXT11,
-			       MAX96717_TUN_MODE,
-			       priv->pattern ? 0 : MAX96717_TUN_MODE, &ret);
-}
-
-static const char * const max96717_test_pattern[] = {
-	"Disabled",
-	"Checkerboard",
-	"Gradient"
-};
-
-static const struct v4l2_ctrl_ops max96717_ctrl_ops = {
-	.s_ctrl = max96717_s_ctrl,
-};
-
-static int max96717_gpiochip_get(struct gpio_chip *gpiochip,
-				 unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-	u64 val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset),
-		       &val, NULL);
-	if (ret)
-		return ret;
-
-	if (val & MAX96717_GPIO_OUT_DIS)
-		return !!(val & MAX96717_GPIO_IN);
-	else
-		return !!(val & MAX96717_GPIO_OUT);
-}
-
-static void max96717_gpiochip_set(struct gpio_chip *gpiochip,
-				  unsigned int offset, int value)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			MAX96717_GPIO_OUT, MAX96717_GPIO_OUT, NULL);
-}
-
-static int max96717_gpio_get_direction(struct gpio_chip *gpiochip,
-				       unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-	u64 val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), &val, NULL);
-	if (ret < 0)
-		return ret;
-
-	return !!(val & MAX96717_GPIO_OUT_DIS);
-}
-
-static int max96717_gpio_direction_out(struct gpio_chip *gpiochip,
-				       unsigned int offset, int value)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			       MAX96717_GPIO_OUT_DIS | MAX96717_GPIO_OUT,
-			       value ? MAX96717_GPIO_OUT : 0, NULL);
-}
-
-static int max96717_gpio_direction_in(struct gpio_chip *gpiochip,
-				      unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			       MAX96717_GPIO_OUT_DIS, MAX96717_GPIO_OUT_DIS,
-			       NULL);
-}
-
-static int max96717_gpiochip_probe(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct gpio_chip *gc = &priv->gpio_chip;
-	int i, ret = 0;
-
-	gc->label = dev_name(dev);
-	gc->parent = dev;
-	gc->owner = THIS_MODULE;
-	gc->ngpio = MAX96717_NUM_GPIO;
-	gc->base = -1;
-	gc->can_sleep = true;
-	gc->get_direction = max96717_gpio_get_direction;
-	gc->direction_input = max96717_gpio_direction_in;
-	gc->direction_output = max96717_gpio_direction_out;
-	gc->set = max96717_gpiochip_set;
-	gc->get = max96717_gpiochip_get;
-	gc->of_gpio_n_cells = 2;
-
-	/* Disable GPIO forwarding */
-	for (i = 0; i < gc->ngpio; i++)
-		cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(i),
-				MAX96717_GPIO_RX_EN | MAX96717_GPIO_TX_EN,
-				0, &ret);
-
-	if (ret)
-		return ret;
-
-	ret = devm_gpiochip_add_data(dev, gc, priv);
-	if (ret) {
-		dev_err(dev, "Unable to create gpio_chip\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int _max96717_set_routing(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_state *state,
-				 struct v4l2_subdev_krouting *routing)
-{
-	static const struct v4l2_mbus_framefmt format = {
-		.width = 1280,
-		.height = 1080,
-		.code = MEDIA_BUS_FMT_Y8_1X8,
-		.field = V4L2_FIELD_NONE,
-	};
-	int ret;
-
-	ret = v4l2_subdev_routing_validate(sd, routing,
-					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
-	if (ret)
-		return ret;
-
-	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int max96717_set_routing(struct v4l2_subdev *sd,
-				struct v4l2_subdev_state *state,
-				enum v4l2_subdev_format_whence which,
-				struct v4l2_subdev_krouting *routing)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-
-	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
-		return -EBUSY;
-
-	return _max96717_set_routing(sd, state, routing);
-}
-
-static int max96717_set_fmt(struct v4l2_subdev *sd,
-			    struct v4l2_subdev_state *state,
-			    struct v4l2_subdev_format *format)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	struct v4l2_mbus_framefmt *fmt;
-	u64 stream_source_mask;
-
-	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
-	    priv->enabled_source_streams)
-		return -EBUSY;
-
-	/* No transcoding, source and sink formats must match. */
-	if (format->pad == MAX96717_PAD_SOURCE)
-		return v4l2_subdev_get_fmt(sd, state, format);
-
-	/* Set sink format */
-	fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	/* Propagate to source format */
-	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
-							   format->stream);
-	if (!fmt)
-		return -EINVAL;
-	*fmt = format->format;
-
-	stream_source_mask = BIT(format->stream);
-
-	return v4l2_subdev_state_xlate_streams(state, MAX96717_PAD_SOURCE,
-					       MAX96717_PAD_SINK,
-					       &stream_source_mask);
-}
-
-static int max96717_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	struct v4l2_subdev_route routes[] = {
-		{
-			.sink_pad = MAX96717_PAD_SINK,
-			.sink_stream = 0,
-			.source_pad = MAX96717_PAD_SOURCE,
-			.source_stream = 0,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
-		},
-	};
-	struct v4l2_subdev_krouting routing = {
-		.num_routes = ARRAY_SIZE(routes),
-		.routes = routes,
-	};
-
-	return _max96717_set_routing(sd, state, &routing);
-}
-
-static bool max96717_pipe_pclkdet(struct max96717_priv *priv)
-{
-	u64 val = 0;
-
-	cci_read(priv->regmap, MAX96717_VIDEO_TX2, &val, NULL);
-
-	return val & MAX96717_VIDEO_PCLKDET;
-}
-
-static int max96717_log_status(struct v4l2_subdev *sd)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Serializer: max96717\n");
-	dev_info(dev, "Pipe: pclkdet:%d\n", max96717_pipe_pclkdet(priv));
-
-	return 0;
-}
-
-static int max96717_enable_streams(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_state *state, u32 pad,
-				   u64 streams_mask)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	u64 sink_streams;
-	int ret;
-
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, true);
-
-	ret = max96717_apply_patgen(priv, state);
-	if (ret)
-		goto stop_csi;
-
-	if (!priv->pattern) {
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96717_PAD_SOURCE,
-							MAX96717_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_enable_streams(priv->source_sd,
-						 priv->source_sd_pad,
-						 sink_streams);
-		if (ret)
-			goto stop_csi;
-	}
-
-	priv->enabled_source_streams |= streams_mask;
-
-	return 0;
-
-stop_csi:
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, false);
-
-	return ret;
-}
-
-static int max96717_disable_streams(struct v4l2_subdev *sd,
-				    struct v4l2_subdev_state *state, u32 pad,
-				    u64 streams_mask)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	u64 sink_streams;
-
-	/*
-	 * Stop the CSI receiver first then the source,
-	 * otherwise the device may become unresponsive
-	 * while holding the I2C bus low.
-	 */
-	priv->enabled_source_streams &= ~streams_mask;
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, false);
-
-	if (!priv->pattern) {
-		int ret;
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96717_PAD_SOURCE,
-							MAX96717_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_disable_streams(priv->source_sd,
-						  priv->source_sd_pad,
-						  sink_streams);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_subdev_pad_ops max96717_pad_ops = {
-	.enable_streams = max96717_enable_streams,
-	.disable_streams = max96717_disable_streams,
-	.set_routing = max96717_set_routing,
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = max96717_set_fmt,
-};
-
-static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = {
-	.log_status = max96717_log_status,
-};
-
-static const struct v4l2_subdev_internal_ops max96717_internal_ops = {
-	.init_state = max96717_init_state,
-};
-
-static const struct v4l2_subdev_ops max96717_subdev_ops = {
-	.core = &max96717_subdev_core_ops,
-	.pad = &max96717_pad_ops,
-};
-
-static const struct media_entity_operations max96717_entity_ops = {
-	.link_validate = v4l2_subdev_link_validate,
-};
-
-static int max96717_notify_bound(struct v4l2_async_notifier *notifier,
-				 struct v4l2_subdev *source_subdev,
-				 struct v4l2_async_connection *asd)
-{
-	struct max96717_priv *priv = sd_to_max96717(notifier->sd);
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	ret = media_entity_get_fwnode_pad(&source_subdev->entity,
-					  source_subdev->fwnode,
-					  MEDIA_PAD_FL_SOURCE);
-	if (ret < 0) {
-		dev_err(dev, "Failed to find pad for %s\n",
-			source_subdev->name);
-		return ret;
-	}
-
-	priv->source_sd = source_subdev;
-	priv->source_sd_pad = ret;
-
-	ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
-				    &priv->sd.entity, 0,
-				    MEDIA_LNK_FL_ENABLED |
-				    MEDIA_LNK_FL_IMMUTABLE);
-	if (ret) {
-		dev_err(dev, "Unable to link %s:%u -> %s:0\n",
-			source_subdev->name, priv->source_sd_pad,
-			priv->sd.name);
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_async_notifier_operations max96717_notify_ops = {
-	.bound = max96717_notify_bound,
-};
-
-static int max96717_v4l2_notifier_register(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_async_connection *asd;
-	struct fwnode_handle *ep_fwnode;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96717_PAD_SINK, 0, 0);
-	if (!ep_fwnode) {
-		dev_err(dev, "No graph endpoint\n");
-		return -ENODEV;
-	}
-
-	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
-
-	asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
-					      struct v4l2_async_connection);
-
-	fwnode_handle_put(ep_fwnode);
-
-	if (IS_ERR(asd)) {
-		dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return PTR_ERR(asd);
-	}
-
-	priv->notifier.ops = &max96717_notify_ops;
-
-	ret = v4l2_async_nf_register(&priv->notifier);
-	if (ret) {
-		dev_err(dev, "Failed to register subdev_notifier");
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max96717_subdev_init(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96717_subdev_ops);
-	priv->sd.internal_ops = &max96717_internal_ops;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler,
-				     &max96717_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96717_test_pattern) - 1,
-				     0, 0, max96717_test_pattern);
-	if (priv->ctrl_handler.error) {
-		ret = priv->ctrl_handler.error;
-		goto err_free_ctrl;
-	}
-
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-	priv->sd.entity.ops = &max96717_entity_ops;
-
-	priv->pads[MAX96717_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-
-	ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
-	if (ret) {
-		dev_err_probe(dev, ret, "Failed to init pads\n");
-		goto err_free_ctrl;
-	}
-
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret) {
-		dev_err_probe(dev, ret,
-			      "v4l2 subdev init finalized failed\n");
-		goto err_entity_cleanup;
-	}
-	ret = max96717_v4l2_notifier_register(priv);
-	if (ret) {
-		dev_err_probe(dev, ret,
-			      "v4l2 subdev notifier register failed\n");
-		goto err_free_state;
-	}
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret) {
-		dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
-		goto err_unreg_notif;
-	}
-
-	return 0;
-
-err_unreg_notif:
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-err_free_state:
-	v4l2_subdev_cleanup(&priv->sd);
-err_entity_cleanup:
-	media_entity_cleanup(&priv->sd.entity);
-err_free_ctrl:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-}
-
-static void max96717_subdev_uninit(struct max96717_priv *priv)
-{
-	v4l2_async_unregister_subdev(&priv->sd);
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-	v4l2_subdev_cleanup(&priv->sd);
-	media_entity_cleanup(&priv->sd.entity);
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-}
-
-struct max96717_pll_predef_freq {
-	unsigned long freq;
-	bool is_alt;
-	u8 val;
-};
-
-static const struct max96717_pll_predef_freq max96717_predef_freqs[] = {
-	{ 13500000, true,  0 }, { 19200000, false, 0 },
-	{ 24000000, true,  1 }, { 27000000, false, 1 },
-	{ 37125000, false, 2 }, { 74250000, false, 3 },
-};
-
-static unsigned long
-max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	return max96717_predef_freqs[priv->pll_predef_index].freq;
-}
-
-static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv,
-						 unsigned long rate)
-{
-	unsigned int i, idx = 0;
-	unsigned long diff_new, diff_old = U32_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) {
-		diff_new = abs(rate - max96717_predef_freqs[i].freq);
-		if (diff_new < diff_old) {
-			diff_old = diff_new;
-			idx = i;
-		}
-	}
-
-	return idx;
-}
-
-static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				    unsigned long *parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-	struct device *dev = &priv->client->dev;
-	unsigned int idx;
-
-	idx = max96717_clk_find_best_index(priv, rate);
-
-	if (rate != max96717_predef_freqs[idx].freq) {
-		dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n",
-			 rate, max96717_predef_freqs[idx].freq);
-	}
-
-	return max96717_predef_freqs[idx].freq;
-}
-
-static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-				 unsigned long parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-	unsigned int val, idx;
-	int ret = 0;
-
-	idx = max96717_clk_find_best_index(priv, rate);
-
-	val = FIELD_PREP(REFGEN_PREDEF_FREQ_MASK,
-			 max96717_predef_freqs[idx].val);
-
-	if (max96717_predef_freqs[idx].is_alt)
-		val |= REFGEN_PREDEF_FREQ_ALT;
-
-	val |= REFGEN_RST | REFGEN_PREDEF_EN;
-
-	cci_write(priv->regmap, REF_VTG0, val, &ret);
-	cci_update_bits(priv->regmap, REF_VTG0, REFGEN_RST | REFGEN_EN,
-			REFGEN_EN, &ret);
-	if (ret)
-		return ret;
-
-	priv->pll_predef_index = idx;
-
-	return 0;
-}
-
-static int max96717_clk_prepare(struct clk_hw *hw)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	return cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN,
-			       RCLKEN, NULL);
-}
-
-static void max96717_clk_unprepare(struct clk_hw *hw)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, 0, NULL);
-}
-
-static const struct clk_ops max96717_clk_ops = {
-	.prepare     = max96717_clk_prepare,
-	.unprepare   = max96717_clk_unprepare,
-	.set_rate    = max96717_clk_set_rate,
-	.recalc_rate = max96717_clk_recalc_rate,
-	.round_rate  = max96717_clk_round_rate,
-};
-
-static int max96717_register_clkout(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct clk_init_data init = { .ops = &max96717_clk_ops };
-	int ret;
-
-	init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out", dev_name(dev));
-	if (!init.name)
-		return -ENOMEM;
-
-	/* RCLKSEL Reference PLL output */
-	ret = cci_update_bits(priv->regmap, MAX96717_REG3, MAX96717_RCLKSEL,
-			      MAX96717_RCLKSEL, NULL);
-	/* MFP4 fastest slew rate */
-	cci_update_bits(priv->regmap, PIO_SLEW_1, BIT(5) | BIT(4), 0, &ret);
-	if (ret)
-		goto free_init_name;
-
-	priv->clk_hw.init = &init;
-
-	/* Initialize to 24 MHz */
-	ret = max96717_clk_set_rate(&priv->clk_hw,
-				    MAX96717_DEFAULT_CLKOUT_RATE, 0);
-	if (ret < 0)
-		goto free_init_name;
-
-	ret = devm_clk_hw_register(dev, &priv->clk_hw);
-	kfree(init.name);
-	if (ret)
-		return dev_err_probe(dev, ret, "Cannot register clock HW\n");
-
-	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
-					  &priv->clk_hw);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Cannot add OF clock provider\n");
-
-	return 0;
-
-free_init_name:
-	kfree(init.name);
-	return ret;
-}
-
-static int max96717_init_csi_lanes(struct max96717_priv *priv)
-{
-	struct v4l2_mbus_config_mipi_csi2 *mipi = &priv->mipi_csi2;
-	unsigned long lanes_used = 0;
-	unsigned int nlanes, lane, val = 0;
-	int ret;
-
-	nlanes = mipi->num_data_lanes;
-
-	ret = cci_update_bits(priv->regmap, MAX96717_MIPI_RX1,
-			      MAX96717_MIPI_LANES_CNT,
-			      FIELD_PREP(MAX96717_MIPI_LANES_CNT,
-					 nlanes - 1), NULL);
-
-	/* lanes polarity */
-	for (lane = 0; lane < nlanes + 1; lane++) {
-		if (!mipi->lane_polarities[lane])
-			continue;
-		/* Clock lane */
-		if (lane == 0)
-			val |= BIT(2);
-		else if (lane < 3)
-			val |= BIT(lane - 1);
-		else
-			val |= BIT(lane);
-	}
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX5,
-			MAX96717_PHY2_LANES_POL,
-			FIELD_PREP(MAX96717_PHY2_LANES_POL, val), &ret);
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX4,
-			MAX96717_PHY1_LANES_POL,
-			FIELD_PREP(MAX96717_PHY1_LANES_POL,
-				   val >> 3), &ret);
-	/* lanes mapping */
-	for (lane = 0, val = 0; lane < nlanes; lane++) {
-		val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
-		lanes_used |= BIT(mipi->data_lanes[lane] - 1);
-	}
-
-	/*
-	 * Unused lanes need to be mapped as well to not have
-	 * the same lanes mapped twice.
-	 */
-	for (; lane < MAX96717_CSI_NLANES; lane++) {
-		unsigned int idx = find_first_zero_bit(&lanes_used,
-						       MAX96717_CSI_NLANES);
-
-		val |= idx << (lane * 2);
-		lanes_used |= BIT(idx);
-	}
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX3,
-			MAX96717_PHY1_LANES_MAP,
-			FIELD_PREP(MAX96717_PHY1_LANES_MAP, val), &ret);
-
-	return cci_update_bits(priv->regmap, MAX96717_MIPI_RX2,
-			       MAX96717_PHY2_LANES_MAP,
-			       FIELD_PREP(MAX96717_PHY2_LANES_MAP, val >> 4),
-			       &ret);
-}
-
-static int max96717_hw_init(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 dev_id, val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_DEV_ID, &dev_id, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read the device id\n");
-
-	if (dev_id != MAX96717_DEVICE_ID && dev_id != MAX96717F_DEVICE_ID)
-		return dev_err_probe(dev, -EOPNOTSUPP,
-				     "Unsupported device id got %x\n", (u8)dev_id);
-
-	ret = cci_read(priv->regmap, MAX96717_DEV_REV, &val, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read device revision");
-
-	dev_dbg(dev, "Found %x (rev %lx)\n", (u8)dev_id,
-		(u8)val & MAX96717_DEV_REV_MASK);
-
-	ret = cci_read(priv->regmap, MAX96717_MIPI_RX_EXT11, &val, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read mipi rx extension");
-
-	if (!(val & MAX96717_TUN_MODE))
-		return dev_err_probe(dev, -EOPNOTSUPP,
-				     "Only supporting tunnel mode");
-
-	return max96717_init_csi_lanes(priv);
-}
-
-static int max96717_parse_dt(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
-	struct fwnode_handle *ep_fwnode;
-	unsigned char num_data_lanes;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96717_PAD_SINK, 0, 0);
-	if (!ep_fwnode)
-		return dev_err_probe(dev, -ENOENT, "no endpoint found\n");
-
-	ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
-
-	fwnode_handle_put(ep_fwnode);
-
-	if (ret < 0)
-		return dev_err_probe(dev, ret, "Failed to parse sink endpoint");
-
-	num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
-	if (num_data_lanes < 1 || num_data_lanes > MAX96717_CSI_NLANES)
-		return dev_err_probe(dev, -EINVAL,
-				     "Invalid data lanes must be 1 to 4\n");
-
-	priv->mipi_csi2 = vep.bus.mipi_csi2;
-
-	return 0;
-}
-
-static int max96717_probe(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-	struct max96717_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->client = client;
-	priv->regmap = devm_cci_regmap_init_i2c(client, 16);
-	if (IS_ERR(priv->regmap)) {
-		ret = PTR_ERR(priv->regmap);
-		return dev_err_probe(dev, ret, "Failed to init regmap\n");
-	}
-
-	ret = max96717_parse_dt(priv);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to parse the dt\n");
-
-	ret = max96717_hw_init(priv);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Failed to initialize the hardware\n");
-
-	ret = max96717_gpiochip_probe(priv);
-	if (ret)
-		return dev_err_probe(&client->dev, ret,
-				     "Failed to init gpiochip\n");
-
-	ret = max96717_register_clkout(priv);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to register clkout\n");
-
-	ret = max96717_subdev_init(priv);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Failed to initialize v4l2 subdev\n");
-
-	ret = max96717_i2c_mux_init(priv);
-	if (ret) {
-		dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
-		max96717_subdev_uninit(priv);
-	}
-
-	return ret;
-}
-
-static void max96717_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96717_priv *priv = sd_to_max96717(sd);
-
-	max96717_subdev_uninit(priv);
-	i2c_mux_del_adapters(priv->mux);
-}
-
-static const struct of_device_id max96717_of_ids[] = {
-	{ .compatible = "maxim,max96717f" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, max96717_of_ids);
-
-static struct i2c_driver max96717_i2c_driver = {
-	.driver	= {
-		.name		= "max96717",
-		.of_match_table	= max96717_of_ids,
-	},
-	.probe		= max96717_probe,
-	.remove		= max96717_remove,
-};
-
-module_i2c_driver(max96717_i2c_driver);
-
-MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver");
-MODULE_AUTHOR("Julien Massot <julien.massot at collabora.com>");
-MODULE_LICENSE("GPL");
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:29 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:29 +0200
Subject: [RFC PATCH 00/24] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
Message-ID: <20250308183410.3013996-1-demonsingur@gmail.com>

This series adds new drivers for multiple Maxim GMSL2 and GMSL3 devices,
replacing the few GMSL2 drivers already in upstream, and introducing a
common framework that can be used to implement such GMSL chips, which
avoids code duplication while also adding support for previously
unsupported features.

While the normally acceptable and polite way would be to extend the
current mainline drivers, the choice was made here to add a totally new
set of drivers. The current drivers support only a small subset of the
possible features, and only a few devices, so the end result after
extending them would in any case be essentially fully rewritten, new
drivers.

This series depends on these two series:
 * https://lore.kernel.org/lkml/20250306-fpc202-v9-0-2779af6780f6 at bootlin.com
 * https://lore.kernel.org/lkml/20250228151730.1874916-1-demonsingur at gmail.com

The following deserializers are supported:
 * MAX96712 (already exists in staging)
 * MAX96714 (already exists)
 * MAX96716 (GMSL2)
 * MAX96724 (part of existing MAX96712 driver)
 * MAX9296A (GMSL2)
 * MAX96792A (GMSL3)

The following serializers are supported:
 * MAX96717 (already exists)
 * MAX9295A (GMSL2)
 * MAX96793 (GMSL3)

Missing features:
 * The current TPG implementation makes use of the V4L2_CID_TEST_PATTERN
   V4L2 control. With V4L2 streams support added, we would like to hook
   up TPG using the internal pad feature which has not been accepted
   upstream yet. We decided to leave TPG out for the moment and add it
   back after internal pads have been accepted.

Known backward compatibility breakages:
 * No default routing. Default routing has been intentionally ommitted
   as the devices support quite complex routing and it would be
   unfeasible to provide sane defaults for multi-link deserialziers.
   It is expected that userspace programs would set appropritate
   routing. 

The following list enumerates new features that are supported by the
common framework and their respective chip-specific drivers:
 * Full Streams API support. Most deserializers have support for more
   than one link, and more than one PHY. Streams support allows
   configuration of routing between these links and PHYs.

 * .get_frame_desc() support. Both the serializers and deserializers
   implement this to query and provide frame descriptor data. This is
   used in features explained in-depth below.

 * .get_mbus_config() support. The deserializers implement this to allow
   upstream devices to query the link frequency of its pads.

 * Address translation with I2C ATR for the serializers.

 * I2C MUX where supported by the hardware for deserializers, otherwise
   I2C ATR translation - some deserializers cannot do muxing since I2C
   communication channel masking is not available per-link, and the only
   other way to select links is to turn them off, causing link resets.
   For such cases, I2C ATR is used to change the address of
   the serializers at probe time.

 * Automatic VC remapping on the deserializers. VCs are picked so that
   if they were unique on the sink pad, they will end up as unique on
   the source pad they are routed to too, prioritizing using the same
   VC ID as the sink pad, to facilitate the possibility of using tunnel
   mode.

 * Automatic pixel mode / tunnel mode selection. Tunnel mode is used
   when VC IDs do not need to be changed and all hardware supports
   tunnel mode, otherwise, pixel mode is used. The serializers are
   automatically switched between the two by using a private API.

 * Automatic double mode selection. In pixel mode, double mode can be
   used to pack two pixels into a single data unit, optimizing bandwidth
   usage. The serializers are automatically set up to support the double
   modes determined by the deserializers using a private API.

 * Automatic data padding. In pixel mode, if the data being transferred
   uses two different BPPs, data needs to be padded. The serializers
   automatically set this up depending on the configured double mode
   settings and incoming data types.

 * Logging. Both the deserializers and serializers implement the V4L2
   .log_status() ops to allow debugging of the internal state and
   important chip status registers.

 * PHY modes. Deserializer chips commonly have more than a single PHY.
   The firmware ports are parsed to determine the modes in which to
   configure the PHYs (2x4, 4x2, 1x4+2x2, 2x2+1x4, and variations using
   fewer lanes).

 * Serializer pinctrl. Serializers implement pinctrl to allow setting
   configs which would otherwise be inaccessible through GPIO: TX/RX via
   GMSL link, pull-up & pull-down (with strength), open-drain &
   push-pull, slew rate, RCLK pin selection.

The drivers have been tested on the following hardware combinations, but
further testing is welcome to ensure no / minimal breakage:
 * Raspberry Pi 5 + MAX96724 + 4xMAX96717 + 4xIMX219
 * Raspberry Pi 5 + MAX96792A + 1xMAX96793 + 1xMAX96717 + 2xIMX219
 * Raspberry Pi 5 + MAX96792A + 2xMAX96717 + 2xIMX219
 * Renesas V4H + MAX96712 + 2xMAX96717 + 2xIMX219 

Analog Devices is taking responsibility for the maintenance of these
drivers and common framework, and plans to add support for new
broad-market chips on top of them.

Special thanks go to Tomi Valkeinen <tomi.valkeinen+renesas at ideasonboard.com>
for testing the drivers, helping debug and coming up with ideas /
implementations for various features.

Cosmin Tanislav (24):
  dt-bindings: media: i2c: max96717: add myself as maintainer
  dt-bindings: media: i2c: max96717: reflow text
  dt-bindings: media: i2c: max96717: add support for I2C ATR
  dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf
  dt-bindings: media: i2c: max96717: add support for MAX9295A
  dt-bindings: media: i2c: max96717: add support for MAX96793
  dt-bindings: media: i2c: max96714: add myself as maintainer
  dt-bindings: media: i2c: max96714: reflow text
  dt-bindings: media: i2c: max96714: make i2c-gate conditional on
    compatible
  dt-bindings: media: i2c: max96714: make ports conditional on
    compatible
  dt-bindings: media: i2c: max96714: make supply conditional on
    compatible
  dt-bindings: media: i2c: max96714: add support for MAX9296A
  dt-bindings: media: i2c: max96714: add support for MAX96716A
  dt-bindings: media: i2c: max96714: add support for MAX96792A
  dt-bindings: media: i2c: max96712: add myself as maintainer
  dt-bindings: media: i2c: max96712: use pattern properties for input
    ports
  dt-bindings: media: i2c: max96712: increase number of output ports
  dt-bindings: media: i2c: max96712: add support for I2C MUX
  dt-bindings: media: i2c: max96712: add support for POC supplies
  media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
  arm64: defconfig: disable deprecated MAX96712 driver
  staging: media: remove MAX96712 driver
  media: i2c: remove MAX96717 driver
  media: i2c: remove MAX96714 driver

 .../bindings/media/i2c/maxim,max96712.yaml    |   49 +-
 .../bindings/media/i2c/maxim,max96714.yaml    |  245 +-
 .../media/i2c/maxim,max96717-pinctrl.yaml     |   71 +
 .../bindings/media/i2c/maxim,max96717.yaml    |   75 +-
 MAINTAINERS                                   |   13 +-
 arch/arm64/configs/defconfig                  |    1 -
 drivers/media/i2c/Kconfig                     |   34 +-
 drivers/media/i2c/Makefile                    |    3 +-
 drivers/media/i2c/max96714.c                  | 1024 --------
 drivers/media/i2c/max96717.c                  | 1103 --------
 drivers/media/i2c/maxim-serdes/Kconfig        |   53 +
 drivers/media/i2c/maxim-serdes/Makefile       |    6 +
 drivers/media/i2c/maxim-serdes/max9296a.c     | 1146 ++++++++
 drivers/media/i2c/maxim-serdes/max96717.c     | 1500 +++++++++++
 drivers/media/i2c/maxim-serdes/max96724.c     |  905 +++++++
 drivers/media/i2c/maxim-serdes/max_des.c      | 2321 +++++++++++++++++
 drivers/media/i2c/maxim-serdes/max_des.h      |  135 +
 drivers/media/i2c/maxim-serdes/max_ser.c      | 1584 +++++++++++
 drivers/media/i2c/maxim-serdes/max_ser.h      |  132 +
 drivers/media/i2c/maxim-serdes/max_serdes.c   |  302 +++
 drivers/media/i2c/maxim-serdes/max_serdes.h   |   88 +
 drivers/staging/media/Kconfig                 |    2 -
 drivers/staging/media/Makefile                |    1 -
 drivers/staging/media/max96712/Kconfig        |   14 -
 drivers/staging/media/max96712/Makefile       |    2 -
 drivers/staging/media/max96712/max96712.c     |  487 ----
 26 files changed, 8523 insertions(+), 2773 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 delete mode 100644 drivers/media/i2c/max96714.c
 delete mode 100644 drivers/media/i2c/max96717.c
 create mode 100644 drivers/media/i2c/maxim-serdes/Kconfig
 create mode 100644 drivers/media/i2c/maxim-serdes/Makefile
 create mode 100644 drivers/media/i2c/maxim-serdes/max9296a.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max96717.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max96724.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_des.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_des.h
 create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.h
 create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.h
 delete mode 100644 drivers/staging/media/max96712/Kconfig
 delete mode 100644 drivers/staging/media/max96712/Makefile
 delete mode 100644 drivers/staging/media/max96712/max96712.c

-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:30 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:30 +0200
Subject: [RFC PATCH 01/24] dt-bindings: media: i2c: max96717: add myself as maintainer
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-2-demonsingur@gmail.com>

Analog Devices is taking responsability for the maintenance of the Maxim
GMSL2/3 devices.
Add myself to the maintainers list and to the device tree bindings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 1 +
 MAINTAINERS                                                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index d1e8ba6e368e..15ab37702a92 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -9,6 +9,7 @@ title: MAX96717 CSI-2 to GMSL2 Serializer
 
 maintainers:
   - Julien Massot <julien.massot at collabora.com>
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
   The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
diff --git a/MAINTAINERS b/MAINTAINERS
index 1916d0636408..8f463ebca056 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14198,6 +14198,7 @@ F:	drivers/media/i2c/max96714.c
 
 MAX96717 GMSL2 SERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:31 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:31 +0200
Subject: [RFC PATCH 02/24] dt-bindings: media: i2c: max96717: reflow text
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-3-demonsingur@gmail.com>

This text is using weird line lengths. Fix it.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96717.yaml    | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 15ab37702a92..1026678a17a7 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -12,16 +12,15 @@ maintainers:
   - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
-  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
-  into GMSL2 serial outputs. The device allows the GMSL2 link to
-  simultaneously transmit bidirectional control-channel data while forward
-  video transmissions are in progress. The MAX96717 can connect to one
-  remotely located deserializer using industry-standard coax or STP
-  interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
-  the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI
-  data received by the serializer.
-  The MAX96717 supports Reference Over Reverse (channel),
-  to generate a clock output for the sensor from the GMSL reverse channel.
+  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input into GMSL2
+  serial outputs. The device allows the GMSL2 link to simultaneously transmit
+  bidirectional control-channel data while forward video transmissions are in
+  progress. The MAX96717 can connect to one remotely located deserializer using
+  industry-standard coax or STP interconnects. The device cans operate in pixel
+  or tunnel mode. In pixel mode the MAX96717 can select the MIPI datatype, while
+  the tunnel mode forward all the MIPI data received by the serializer.
+  The MAX96717 supports Reference Over Reverse (channel), to generate a clock
+  output for the sensor from the GMSL reverse channel.
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:32 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:32 +0200
Subject: [RFC PATCH 03/24] dt-bindings: media: i2c: max96717: add support for I2C ATR
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-4-demonsingur@gmail.com>

MAX96717 is capable of address translation for the connected I2C slaves.

Add support for I2C ATR while keeping I2C gate for compatibility to
support this usecase.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96717.yaml    | 34 ++++++++++++++-----
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 1026678a17a7..7d77cc9dcd96 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -83,14 +83,6 @@ properties:
     required:
       - port at 1
 
-  i2c-gate:
-    $ref: /schemas/i2c/i2c-gate.yaml
-    unevaluatedProperties: false
-    description:
-      The MAX96717 will forward the I2C requests from the
-      incoming GMSL2 link. Therefore, it supports an i2c-gate
-      subnode to configure a sensor.
-
 required:
   - compatible
   - reg
@@ -98,6 +90,32 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - $ref: /schemas/i2c/i2c-atr.yaml#
+
+  - oneOf:
+      - properties:
+          i2c-gate:
+            $ref: /schemas/i2c/i2c-gate.yaml
+            unevaluatedProperties: false
+            description:
+              The MAX96717 will forward the I2C requests from the
+              incoming GMSL2 link. Therefore, it supports an i2c-gate
+              subnode to configure a sensor.
+
+      - properties:
+          i2c-alias-pool:
+            maxItems: 2
+
+          i2c-atr:
+            patternProperties:
+              '^i2c at 0':
+                $ref: /schemas/i2c/i2c-controller.yaml#
+                properties:
+                  reg:
+                    items:
+                      max: 0
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:33 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:33 +0200
Subject: [RFC PATCH 04/24] dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-5-demonsingur@gmail.com>

MAX96717 is capable of configuring various pin properties.

Add pinctrl/pinconf properties to support this usecase.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../media/i2c/maxim,max96717-pinctrl.yaml     | 71 +++++++++++++++++++
 .../bindings/media/i2c/maxim,max96717.yaml    | 16 ++++-
 MAINTAINERS                                   |  1 +
 3 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
new file mode 100644
index 000000000000..9480d3127643
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2025 Analog Devices Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim GMSL2 Serializer Pinctrl
+
+maintainers:
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
+
+allOf:
+  - $ref: /schemas/pinctrl/pincfg-node.yaml#
+  - $ref: /schemas/pinctrl/pinmux-node.yaml#
+
+unevaluatedProperties: false
+
+properties:
+  function: true
+  pins: true
+  drive-open-drain: true
+  drive-push-pull: true
+  bias-disable: true
+  bias-pull-up: true
+  bias-pull-down: true
+  output-disable: true
+  output-enable: true
+  output-low: true
+  output-high: true
+  slew-rate: true
+  input-enable: true
+
+  maxim,jitter-compensation:
+    type: boolean
+    description: Enables jitter compensation.
+
+  maxim,gmsl-tx:
+    type: boolean
+    description: Enable transmitting pin value to GMSL link.
+
+  maxim,gmsl-rx:
+    type: boolean
+    description: Enable receiving pin value from GMSL link.
+
+  maxim,gmsl-tx-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Identifier used while transmitting value to GMSL link.
+      Default value matches the pin number.
+    min: 0
+    max: 31
+
+  maxim,gmsl-rx-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Identifier used while receiving value from GMSL link.
+      Default value matches the pin number.
+    min: 0
+    max: 31
+
+  maxim,rclkout-clock:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Clock value.
+      0 - XTAL / 1 = 25MHz
+      1 - XTAL / 2 = 12.5MHz
+      2 - XTAL / 4 = 6.25MHz
+      3 - Reference PLL output
+    min: 0
+    max: 3
diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 7d77cc9dcd96..20114c252e01 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -88,7 +88,21 @@ required:
   - reg
   - ports
 
-additionalProperties: false
+additionalProperties:
+  anyOf:
+    - type: object
+      allOf:
+        - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+
+      unevaluatedProperties: false
+
+    - type: object
+      additionalProperties:
+        type: object
+        allOf:
+          - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+
+        unevaluatedProperties: false
 
 allOf:
   - $ref: /schemas/i2c/i2c-atr.yaml#
diff --git a/MAINTAINERS b/MAINTAINERS
index 8f463ebca056..f8ffb7cff9c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14201,6 +14201,7 @@ M:	Julien Massot <julien.massot at collabora.com>
 M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
 F:	drivers/media/i2c/max96717.c
 
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:34 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:34 +0200
Subject: [RFC PATCH 05/24] dt-bindings: media: i2c: max96717: add support for MAX9295A
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-6-demonsingur@gmail.com>

MAX9295A is an older variant of the MAX96717 which does not support
tunnel mode.

Document the compatibility.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96717.yaml          | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 20114c252e01..1e5b85167d0e 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -24,11 +24,14 @@ description:
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
+
   MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
+  MAX9295A only supports pixel mode.
 
 properties:
   compatible:
     oneOf:
+      - const: maxim,max9295a
       - const: maxim,max96717f
       - items:
           - enum:
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:35 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:35 +0200
Subject: [RFC PATCH 06/24] dt-bindings: media: i2c: max96717: add support for MAX96793
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-7-demonsingur@gmail.com>

MAX96793 is a newer variant of the MAX96717 which also supports GMSL3
links.

Document this compatibility.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 1e5b85167d0e..2d7440049318 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -27,6 +27,7 @@ description:
 
   MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
   MAX9295A only supports pixel mode.
+  MAX96793 also supports GMSL3 mode.
 
 properties:
   compatible:
@@ -36,6 +37,7 @@ properties:
       - items:
           - enum:
               - maxim,max96717
+              - maxim,max96793
           - const: maxim,max96717f
 
   '#gpio-cells':
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:36 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:36 +0200
Subject: [RFC PATCH 07/24] dt-bindings: media: i2c: max96714: add myself as maintainer
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-8-demonsingur@gmail.com>

Analog Devices is taking responsability for the maintenance of the Maxim
GMSL2/3 devices.
Add myself to the maintainers list and to the device tree bindings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml | 1 +
 MAINTAINERS                                                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index 3ace50e11921..44667b74296c 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -9,6 +9,7 @@ title: Maxim MAX96714 GMSL2 to CSI-2 Deserializer
 
 maintainers:
   - Julien Massot <julien.massot at collabora.com>
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
   The MAX96714 deserializer converts GMSL2 serial inputs into MIPI
diff --git a/MAINTAINERS b/MAINTAINERS
index f8ffb7cff9c5..7fcdcc57c8ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14191,6 +14191,7 @@ F:	drivers/staging/media/max96712/max96712.c
 
 MAX96714 GMSL2 DESERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:37 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:37 +0200
Subject: [RFC PATCH 08/24] dt-bindings: media: i2c: max96714: reflow text
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-9-demonsingur@gmail.com>

This text is using weird line lengths. Fix it.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96714.yaml        | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index 44667b74296c..2f453189338f 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -12,14 +12,13 @@ maintainers:
   - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
-  The MAX96714 deserializer converts GMSL2 serial inputs into MIPI
-  CSI-2 D-PHY formatted output. The device allows the GMSL2 link to
-  simultaneously transmit bidirectional control-channel data while forward
-  video transmissions are in progress. The MAX96714 can connect to one
-  remotely located serializer using industry-standard coax or STP
-  interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
-  the MAX96714 can select individual video stream, while the tunnel mode forward all
-  the MIPI data received by the serializer.
+  The MAX96714 deserializer converts GMSL2 serial inputs into MIPI CSI-2 D-PHY
+  formatted output. The device allows the GMSL2 link to simultaneously transmit
+  bidirectional control-channel data while forward video transmissions are in
+  progress. The MAX96714 can connect to one remotely located serializer using
+  industry-standard coax or STP interconnects. The device cans operate in pixel
+  or tunnel mode. In pixel mode the MAX96714 can select individual video stream,
+  while the tunnel mode forward all the MIPI data received by the serializer.
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:38 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:38 +0200
Subject: [RFC PATCH 09/24] dt-bindings: media: i2c: max96714: make i2c-gate conditional on compatible
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-10-demonsingur@gmail.com>

Devices to be added in following patches don't use I2C gate.

Make this property conditional on the compatible strings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96714.yaml    | 21 ++++++++++++-------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index 2f453189338f..d0a2aaf7df9c 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -84,14 +84,6 @@ properties:
     required:
       - port at 1
 
-  i2c-gate:
-    $ref: /schemas/i2c/i2c-gate.yaml
-    unevaluatedProperties: false
-    description:
-      The MAX96714 will pass through and forward the I2C requests from the
-      incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate
-      subnode to configure a serializer.
-
   port0-poc-supply:
     description: Regulator providing Power over Coax for the GMSL port
 
@@ -101,6 +93,19 @@ required:
   - ports
 
 additionalProperties: false
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - maxim,max96714
+              - maxim,max96714f
+    then:
+      properties:
+        i2c-gate:
+          $ref: /schemas/i2c/i2c-gate.yaml
+          unevaluatedProperties: false
 
 examples:
   - |
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:39 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:39 +0200
Subject: [RFC PATCH 10/24] dt-bindings: media: i2c: max96714: make ports conditional on compatible
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-11-demonsingur@gmail.com>

Devices to be added in following patches have more input/output ports.

Make this property conditional on the compatible strings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96714.yaml    | 90 ++++++++++---------
 1 file changed, 46 insertions(+), 44 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index d0a2aaf7df9c..f0ae069c93b5 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -41,56 +41,12 @@ properties:
     description:
       Specifier for the GPIO connected to the PWDNB pin.
 
-  ports:
-    $ref: /schemas/graph.yaml#/properties/ports
-
-    properties:
-      port at 0:
-        $ref: /schemas/graph.yaml#/properties/port
-        unevaluatedProperties: false
-        description: GMSL Input
-        properties:
-          endpoint:
-            $ref: /schemas/media/video-interfaces.yaml#
-            unevaluatedProperties: false
-            description:
-              Endpoint for GMSL2-Link port.
-
-      port at 1:
-        $ref: /schemas/graph.yaml#/$defs/port-base
-        unevaluatedProperties: false
-        description: CSI-2 Output port
-
-        properties:
-          endpoint:
-            $ref: /schemas/media/video-interfaces.yaml#
-            unevaluatedProperties: false
-
-            properties:
-              data-lanes:
-                minItems: 1
-                maxItems: 4
-
-              lane-polarities:
-                minItems: 1
-                maxItems: 5
-
-              link-frequencies:
-                maxItems: 1
-
-            required:
-              - data-lanes
-
-    required:
-      - port at 1
-
   port0-poc-supply:
     description: Regulator providing Power over Coax for the GMSL port
 
 required:
   - compatible
   - reg
-  - ports
 
 additionalProperties: false
 allOf:
@@ -102,11 +58,57 @@ allOf:
               - maxim,max96714
               - maxim,max96714f
     then:
+      required:
+        - ports
+
       properties:
         i2c-gate:
           $ref: /schemas/i2c/i2c-gate.yaml
           unevaluatedProperties: false
 
+        ports:
+          $ref: /schemas/graph.yaml#/properties/ports
+
+          properties:
+            port at 0:
+              $ref: /schemas/graph.yaml#/properties/port
+              unevaluatedProperties: false
+              description: GMSL Input
+              properties:
+                endpoint:
+                  $ref: /schemas/media/video-interfaces.yaml#
+                  unevaluatedProperties: false
+                  description:
+                    Endpoint for GMSL2-Link port.
+
+            port at 1:
+              $ref: /schemas/graph.yaml#/$defs/port-base
+              unevaluatedProperties: false
+              description: CSI-2 Output port
+
+              properties:
+                endpoint:
+                  $ref: /schemas/media/video-interfaces.yaml#
+                  unevaluatedProperties: false
+
+                  properties:
+                    data-lanes:
+                      minItems: 1
+                      maxItems: 4
+
+                    lane-polarities:
+                      minItems: 1
+                      maxItems: 5
+
+                    link-frequencies:
+                      maxItems: 1
+
+                  required:
+                    - data-lanes
+
+          required:
+            - port at 1
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:40 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:40 +0200
Subject: [RFC PATCH 11/24] dt-bindings: media: i2c: max96714: make supply conditional on compatible
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-12-demonsingur@gmail.com>

Devices to be added in following patches have more input ports, and,
implicitly, more POC supplies.

Make this property conditional on the compatible strings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96714.yaml       | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index f0ae069c93b5..5bbd36c55ab4 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -41,9 +41,6 @@ properties:
     description:
       Specifier for the GPIO connected to the PWDNB pin.
 
-  port0-poc-supply:
-    description: Regulator providing Power over Coax for the GMSL port
-
 required:
   - compatible
   - reg
@@ -62,6 +59,9 @@ allOf:
         - ports
 
       properties:
+        port0-poc-supply:
+          description: Regulator providing Power over Coax for the GMSL port
+
         i2c-gate:
           $ref: /schemas/i2c/i2c-gate.yaml
           unevaluatedProperties: false
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:41 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:41 +0200
Subject: [RFC PATCH 12/24] dt-bindings: media: i2c: max96714: add support for MAX9296A
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-13-demonsingur@gmail.com>

MAX9296A is an older variant of the MAX96714 which doesn't support
tunnel mode, but has two GMSL2 links.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96714.yaml    | 87 +++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index 5bbd36c55ab4..9c6c79a770ed 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -22,11 +22,14 @@ description:
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
+
   MAX96714F only supports a fixed rate of 3Gbps in the forward direction.
+  MAX9296A only supports pixel mode, and has two GMSL2 links.
 
 properties:
   compatible:
     oneOf:
+      - const: maxim,max9296a
       - const: maxim,max96714f
       - items:
           - enum:
@@ -109,6 +112,90 @@ allOf:
           required:
             - port at 1
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - maxim,max9296a
+    then:
+      allOf:
+        - $ref: /schemas/i2c/i2c-atr.yaml#
+
+      properties:
+        i2c-alias-pool:
+          maxItems: 2
+
+        i2c-atr:
+          patternProperties:
+            '^i2c@[0-1]$':
+              $ref: /schemas/i2c/i2c-controller.yaml#
+              properties:
+                reg:
+                  items:
+                    min: 0
+                    max: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - maxim,max9296a
+    then:
+      properties:
+        port0-poc-supply:
+          description: Regulator providing Power over Coax for GMSL port 0
+
+        port1-poc-supply:
+          description: Regulator providing Power over Coax for GMSL port 1
+
+        ports:
+          $ref: /schemas/graph.yaml#/properties/ports
+
+          patternProperties:
+            port@[0-1]:
+              $ref: /schemas/graph.yaml#/properties/port
+              unevaluatedProperties: false
+              description: GMSL Input
+              properties:
+                endpoint:
+                  $ref: /schemas/media/video-interfaces.yaml#
+                  unevaluatedProperties: false
+                  description:
+                    Endpoint for GMSL2-Link port.
+
+            port@[2-3]:
+              $ref: /schemas/graph.yaml#/$defs/port-base
+              unevaluatedProperties: false
+              description: CSI-2 Output port
+
+              properties:
+                endpoint:
+                  $ref: /schemas/media/video-interfaces.yaml#
+                  unevaluatedProperties: false
+
+                  properties:
+                    data-lanes:
+                      minItems: 1
+                      maxItems: 4
+
+                    lane-polarities:
+                      minItems: 1
+                      maxItems: 5
+
+                    link-frequencies:
+                      maxItems: 1
+
+                  required:
+                    - data-lanes
+
+          anyOf:
+            - required:
+                - port at 2
+            - required:
+                - port at 3
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:42 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:42 +0200
Subject: [RFC PATCH 13/24] dt-bindings: media: i2c: max96714: add support for MAX96716A
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-14-demonsingur@gmail.com>

MAX96716A is a newer variant of the MAX9296A which supports both pixel
and tunnel mode.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96714.yaml    | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index 9c6c79a770ed..d4055ecf673f 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -25,12 +25,14 @@ description:
 
   MAX96714F only supports a fixed rate of 3Gbps in the forward direction.
   MAX9296A only supports pixel mode, and has two GMSL2 links.
+  MAX96716A supports both tunnel and pixel mode, and has two GMSL2 links.
 
 properties:
   compatible:
     oneOf:
       - const: maxim,max9296a
       - const: maxim,max96714f
+      - const: maxim,max96716a
       - items:
           - enum:
               - maxim,max96714
@@ -136,12 +138,31 @@ allOf:
                     min: 0
                     max: 1
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: maxim,max96716a
+    then:
+      properties:
+        i2c-mux:
+          $ref: /schemas/i2c/i2c-mux.yaml#
+          patternProperties:
+            '^i2c@[0-1]$':
+              $ref: /schemas/i2c/i2c-controller.yaml#
+              properties:
+                reg:
+                  items:
+                    min: 0
+                    max: 1
+
   - if:
       properties:
         compatible:
           contains:
             enum:
               - maxim,max9296a
+              - maxim,max96716a
     then:
       properties:
         port0-poc-supply:
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:43 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:43 +0200
Subject: [RFC PATCH 14/24] dt-bindings: media: i2c: max96714: add support for MAX96792A
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-15-demonsingur@gmail.com>

MAX96792A is a newer variant of the MAX96716A, which supports GMSL3
links.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96714.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
index d4055ecf673f..a392da39c154 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
@@ -26,6 +26,7 @@ description:
   MAX96714F only supports a fixed rate of 3Gbps in the forward direction.
   MAX9296A only supports pixel mode, and has two GMSL2 links.
   MAX96716A supports both tunnel and pixel mode, and has two GMSL2 links.
+  MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
 
 properties:
   compatible:
@@ -33,6 +34,7 @@ properties:
       - const: maxim,max9296a
       - const: maxim,max96714f
       - const: maxim,max96716a
+      - const: maxim,max96792a
       - items:
           - enum:
               - maxim,max96714
@@ -120,6 +122,7 @@ allOf:
           contains:
             enum:
               - maxim,max9296a
+              - maxim,max96792a
     then:
       allOf:
         - $ref: /schemas/i2c/i2c-atr.yaml#
@@ -163,6 +166,7 @@ allOf:
             enum:
               - maxim,max9296a
               - maxim,max96716a
+              - maxim,max96792a
     then:
       properties:
         port0-poc-supply:
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:44 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:44 +0200
Subject: [RFC PATCH 15/24] dt-bindings: media: i2c: max96712: add myself as maintainer
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-16-demonsingur@gmail.com>

Analog Devices is taking responsability for the maintenance of the Maxim
GMSL2/3 devices.
Add myself to the maintainers list and to the device tree bindings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml | 1 +
 MAINTAINERS                                                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 26f85151afbd..efdece2b33b9 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -9,6 +9,7 @@ title: Quad GMSL2 to CSI-2 Deserializer with GMSL1 Compatibility
 
 maintainers:
   - Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description: |
   The MAX96712 deserializer converts GMSL2 or GMSL1 serial inputs into MIPI
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fcdcc57c8ba..84078626ed5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14184,6 +14184,7 @@ F:	drivers/media/i2c/max9286.c
 
 MAX96712 QUAD GMSL2 DESERIALIZER DRIVER
 M:	Niklas S?derlund <niklas.soderlund at ragnatech.se>
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:45 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:45 +0200
Subject: [RFC PATCH 16/24] dt-bindings: media: i2c: max96712: use pattern properties for input ports
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-17-demonsingur@gmail.com>

The input ports are all the same, use patternProperties for them.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96712.yaml     | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index efdece2b33b9..148d196b9acc 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -40,22 +40,10 @@ properties:
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
-    properties:
-      port at 0:
+    patternProperties:
+      port@[0-3]:
         $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 0
-
-      port at 1:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 1
-
-      port at 2:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 2
-
-      port at 3:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 3
+        description: GMSL Input port
 
       port at 4:
         $ref: /schemas/graph.yaml#/$defs/port-base
-- 
2.48.1



From demonsingur at gmail.com  Sat Mar  8 10:33:53 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sat,  8 Mar 2025 20:33:53 +0200
Subject: [RFC PATCH 24/24] media: i2c: remove MAX96714 driver
In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
Message-ID: <20250308183410.3013996-25-demonsingur@gmail.com>

The previous MAX96714 driver has been removed and its functionality has
been moved to the MAX9296A driver which makes use of the Maxim GMSL2/3
serializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                  |    1 -
 drivers/media/i2c/Kconfig    |   17 -
 drivers/media/i2c/Makefile   |    1 -
 drivers/media/i2c/max96714.c | 1024 ----------------------------------
 4 files changed, 1043 deletions(-)
 delete mode 100644 drivers/media/i2c/max96714.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 12078126f478..eae3a888e3fa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14195,7 +14195,6 @@ M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
-F:	drivers/media/i2c/max96714.c
 
 MAX96717 GMSL2 SERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 6c595dffb280..aa0a67b7da47 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1619,23 +1619,6 @@ config VIDEO_DS90UB960
 	  Device driver for the Texas Instruments DS90UB960
 	  FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
 
-config VIDEO_MAX96714
-	tristate "Maxim MAX96714 GMSL2 deserializer"
-	depends on OF && I2C && VIDEO_DEV
-	select I2C_MUX
-	select MEDIA_CONTROLLER
-	select GPIOLIB
-	select V4L2_CCI_I2C
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	help
-	  Device driver for the Maxim MAX96714 GMSL2 Deserializer.
-	  MAX96714 deserializers convert a GMSL2 input to MIPI CSI-2
-	  output.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96714.
-
 source "drivers/media/i2c/maxim-serdes/Kconfig"
 
 endmenu
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index de0680ebf190..065e728f54ce 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_VIDEO_LT6911UXE) += lt6911uxe.o
 obj-$(CONFIG_VIDEO_M52790) += m52790.o
 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
-obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
 obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/
 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
diff --git a/drivers/media/i2c/max96714.c b/drivers/media/i2c/max96714.c
deleted file mode 100644
index 159753b13777..000000000000
--- a/drivers/media/i2c/max96714.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim GMSL2 Deserializer Driver
- *
- * Copyright (C) 2024 Collabora Ltd.
- */
-
-#include <linux/bitfield.h>
-#include <linux/bitops.h>
-#include <linux/fwnode.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/i2c-mux.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-#include <media/v4l2-cci.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define MAX96714_DEVICE_ID  0xc9
-#define MAX96714F_DEVICE_ID 0xca
-#define MAX96714_NPORTS     2
-#define MAX96714_PAD_SINK   0
-#define MAX96714_PAD_SOURCE 1
-#define MAX96714_CSI_NLANES 4
-
-/* DEV */
-#define MAX96714_REG13                 CCI_REG8(0x0d)
-#define MAX96714_DEV_REV               CCI_REG8(0x0e)
-#define MAX96714_DEV_REV_MASK          GENMASK(3, 0)
-#define MAX96714_LINK_LOCK             CCI_REG8(0x13)
-#define MAX96714_LINK_LOCK_BIT         BIT(3)
-#define MAX96714_IO_CHK0               CCI_REG8(0x38)
-#define MAX96714_PATTERN_CLK_FREQ      GENMASK(1, 0)
-/* VID_RX */
-#define MAX96714_VIDEO_RX8             CCI_REG8(0x11a)
-#define MAX96714_VID_LOCK              BIT(6)
-
-/* VRX_PATGEN_0 */
-#define MAX96714_PATGEN_0              CCI_REG8(0x240)
-#define MAX96714_PATGEN_1              CCI_REG8(0x241)
-#define MAX96714_PATGEN_MODE           GENMASK(5, 4)
-#define MAX96714_PATGEN_VS_DLY         CCI_REG24(0x242)
-#define MAX96714_PATGEN_VS_HIGH        CCI_REG24(0x245)
-#define MAX96714_PATGEN_VS_LOW         CCI_REG24(0x248)
-#define MAX96714_PATGEN_V2H            CCI_REG24(0x24b)
-#define MAX96714_PATGEN_HS_HIGH        CCI_REG16(0x24e)
-#define MAX96714_PATGEN_HS_LOW         CCI_REG16(0x250)
-#define MAX96714_PATGEN_HS_CNT         CCI_REG16(0x252)
-#define MAX96714_PATGEN_V2D            CCI_REG24(0x254)
-#define MAX96714_PATGEN_DE_HIGH        CCI_REG16(0x257)
-#define MAX96714_PATGEN_DE_LOW         CCI_REG16(0x259)
-#define MAX96714_PATGEN_DE_CNT         CCI_REG16(0x25b)
-#define MAX96714_PATGEN_GRAD_INC       CCI_REG8(0x25d)
-#define MAX96714_PATGEN_CHKB_COLOR_A   CCI_REG24(0x25e)
-#define MAX96714_PATGEN_CHKB_COLOR_B   CCI_REG24(0x261)
-#define MAX96714_PATGEN_CHKB_RPT_CNT_A CCI_REG8(0x264)
-#define MAX96714_PATGEN_CHKB_RPT_CNT_B CCI_REG8(0x265)
-#define MAX96714_PATGEN_CHKB_ALT       CCI_REG8(0x266)
-/* BACKTOP */
-#define MAX96714_BACKTOP25             CCI_REG8(0x320)
-#define CSI_DPLL_FREQ_MASK             GENMASK(4, 0)
-
-/* MIPI_PHY */
-#define MAX96714_MIPI_PHY0             CCI_REG8(0x330)
-#define MAX96714_FORCE_CSI_OUT         BIT(7)
-#define MAX96714_MIPI_STDBY_N          CCI_REG8(0x332)
-#define MAX96714_MIPI_STDBY_MASK       GENMASK(5, 4)
-#define MAX96714_MIPI_LANE_MAP         CCI_REG8(0x333)
-#define MAX96714_MIPI_POLARITY         CCI_REG8(0x335)
-#define MAX96714_MIPI_POLARITY_MASK    GENMASK(5, 0)
-
-/* MIPI_TX */
-#define MAX96714_MIPI_LANE_CNT         CCI_REG8(0x44a)
-#define MAX96714_CSI2_LANE_CNT_MASK    GENMASK(7, 6)
-#define MAX96714_MIPI_TX52             CCI_REG8(0x474)
-#define MAX96714_TUN_EN                BIT(0)
-
-#define MHZ(v) ((u32)((v)  * 1000000U))
-
-enum max96714_vpg_mode {
-	MAX96714_VPG_DISABLED = 0,
-	MAX96714_VPG_CHECKERBOARD = 1,
-	MAX96714_VPG_GRADIENT = 2,
-};
-
-struct max96714_rxport {
-	struct {
-		struct v4l2_subdev   *sd;
-		u16                  pad;
-		struct fwnode_handle *ep_fwnode;
-	} source;
-	struct regulator	     *poc;
-};
-
-struct max96714_txport {
-	struct v4l2_fwnode_endpoint vep;
-};
-
-struct max96714_priv {
-	struct i2c_client                 *client;
-	struct regmap                     *regmap;
-	struct gpio_desc                  *pd_gpio;
-	struct max96714_rxport            rxport;
-	struct i2c_mux_core               *mux;
-	u64                               enabled_source_streams;
-	struct v4l2_subdev		  sd;
-	struct media_pad		  pads[MAX96714_NPORTS];
-	struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
-	struct v4l2_ctrl_handler          ctrl_handler;
-	struct v4l2_async_notifier        notifier;
-	s64                               tx_link_freq;
-	enum max96714_vpg_mode            pattern;
-};
-
-static inline struct max96714_priv *sd_to_max96714(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct max96714_priv, sd);
-}
-
-static int max96714_enable_tx_port(struct max96714_priv *priv)
-{
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
-			       MAX96714_MIPI_STDBY_MASK,
-			       MAX96714_MIPI_STDBY_MASK, NULL);
-}
-
-static int max96714_disable_tx_port(struct max96714_priv *priv)
-{
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
-			       MAX96714_MIPI_STDBY_MASK, 0, NULL);
-}
-
-static bool max96714_tx_port_enabled(struct max96714_priv *priv)
-{
-	u64 val;
-
-	cci_read(priv->regmap, MAX96714_MIPI_STDBY_N, &val, NULL);
-
-	return val & MAX96714_MIPI_STDBY_MASK;
-}
-
-static int max96714_apply_patgen_timing(struct max96714_priv *priv,
-					struct v4l2_subdev_state *state)
-{
-	struct v4l2_mbus_framefmt *fmt =
-		v4l2_subdev_state_get_format(state, MAX96714_PAD_SOURCE);
-	const u32 h_active = fmt->width;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	u32 h_tot;
-	const u32 v_active = fmt->height;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	u32 v_tot;
-	int ret = 0;
-
-	h_tot = h_active + h_fp + h_sw + h_bp;
-	v_tot = v_active + v_fp + v_sw + v_bp;
-
-	/* 75 Mhz pixel clock */
-	cci_update_bits(priv->regmap, MAX96714_IO_CHK0,
-			MAX96714_PATTERN_CLK_FREQ, 1, &ret);
-
-	dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height,
-		 fmt->width);
-
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_DLY, 0, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_HIGH, v_sw * h_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_LOW,
-		  (v_active + v_fp + v_bp) * h_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_HIGH, h_sw, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_LOW, h_active + h_fp + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_V2D,
-		  h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_CNT, v_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_HIGH, h_active, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_LOW, h_fp + h_sw + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_CNT, v_active, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_A, 0xfecc00, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_B, 0x006aa7, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_A, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_B, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_ALT, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_GRAD_INC, 0x10, &ret);
-
-	return ret;
-}
-
-static int max96714_apply_patgen(struct max96714_priv *priv,
-				 struct v4l2_subdev_state *state)
-{
-	unsigned int val;
-	int ret = 0;
-
-	if (priv->pattern)
-		ret = max96714_apply_patgen_timing(priv, state);
-
-	cci_write(priv->regmap, MAX96714_PATGEN_0, priv->pattern ? 0xfb : 0,
-		  &ret);
-
-	val = FIELD_PREP(MAX96714_PATGEN_MODE, priv->pattern);
-	cci_update_bits(priv->regmap, MAX96714_PATGEN_1, MAX96714_PATGEN_MODE,
-			val, &ret);
-	return ret;
-}
-
-static int max96714_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96714_priv *priv =
-		container_of(ctrl->handler, struct max96714_priv, ctrl_handler);
-	int ret;
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		if (priv->enabled_source_streams)
-			return -EBUSY;
-		priv->pattern = ctrl->val;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	ret = cci_update_bits(priv->regmap, MAX96714_MIPI_PHY0,
-			      MAX96714_FORCE_CSI_OUT,
-			      priv->pattern ? MAX96714_FORCE_CSI_OUT : 0, NULL);
-
-	/* Pattern generator doesn't work with tunnel mode */
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_TX52,
-			       MAX96714_TUN_EN,
-			       priv->pattern ? 0 : MAX96714_TUN_EN, &ret);
-}
-
-static const char * const max96714_test_pattern[] = {
-	"Disabled",
-	"Checkerboard",
-	"Gradient"
-};
-
-static const struct v4l2_ctrl_ops max96714_ctrl_ops = {
-	.s_ctrl = max96714_s_ctrl,
-};
-
-static int max96714_enable_streams(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_state *state,
-				   u32 source_pad, u64 streams_mask)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	u64 sink_streams;
-	int ret;
-
-	if (!priv->enabled_source_streams)
-		max96714_enable_tx_port(priv);
-
-	ret = max96714_apply_patgen(priv, state);
-	if (ret)
-		goto err;
-
-	if (!priv->pattern) {
-		if (!priv->rxport.source.sd) {
-			ret = -ENODEV;
-			goto err;
-		}
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96714_PAD_SOURCE,
-							MAX96714_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_enable_streams(priv->rxport.source.sd,
-						 priv->rxport.source.pad,
-						 sink_streams);
-		if (ret)
-			goto err;
-	}
-
-	priv->enabled_source_streams |= streams_mask;
-
-	return 0;
-
-err:
-	if (!priv->enabled_source_streams)
-		max96714_disable_tx_port(priv);
-
-	return ret;
-}
-
-static int max96714_disable_streams(struct v4l2_subdev *sd,
-				    struct v4l2_subdev_state *state,
-				    u32 source_pad, u64 streams_mask)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	u64 sink_streams;
-
-	if (!priv->pattern) {
-		int ret;
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96714_PAD_SOURCE,
-							MAX96714_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_disable_streams(priv->rxport.source.sd,
-						  priv->rxport.source.pad,
-						  sink_streams);
-		if (ret)
-			return ret;
-	}
-
-	priv->enabled_source_streams &= ~streams_mask;
-
-	if (!priv->enabled_source_streams)
-		max96714_disable_tx_port(priv);
-
-	return 0;
-}
-
-static int max96714_set_fmt(struct v4l2_subdev *sd,
-			    struct v4l2_subdev_state *state,
-			    struct v4l2_subdev_format *format)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	struct v4l2_mbus_framefmt *fmt;
-
-	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
-	    priv->enabled_source_streams)
-		return -EBUSY;
-
-	/* No transcoding, source and sink formats must match. */
-	if (format->pad == MAX96714_PAD_SOURCE)
-		return v4l2_subdev_get_fmt(sd, state, format);
-
-	fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
-							   format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	return 0;
-}
-
-static int _max96714_set_routing(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_state *state,
-				 enum v4l2_subdev_format_whence which,
-				 struct v4l2_subdev_krouting *routing)
-{
-	static const struct v4l2_mbus_framefmt format = {
-		.width = 1280,
-		.height = 1080,
-		.code = MEDIA_BUS_FMT_Y8_1X8,
-		.field = V4L2_FIELD_NONE,
-	};
-	int ret;
-
-	/*
-	 * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
-	 * frame desc is made dynamically allocated.
-	 */
-	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
-		return -EINVAL;
-
-	ret = v4l2_subdev_routing_validate(sd, routing,
-					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
-	if (ret)
-		return ret;
-
-	return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
-}
-
-static int max96714_set_routing(struct v4l2_subdev *sd,
-				struct v4l2_subdev_state *state,
-				enum v4l2_subdev_format_whence which,
-				struct v4l2_subdev_krouting *routing)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-
-	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
-		return -EBUSY;
-
-	return _max96714_set_routing(sd, state, which, routing);
-}
-
-static int max96714_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	struct v4l2_subdev_route routes[] = {
-		{
-			.sink_pad = MAX96714_PAD_SINK,
-			.sink_stream = 0,
-			.source_pad = MAX96714_PAD_SOURCE,
-			.source_stream = 0,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
-		}
-	};
-	struct v4l2_subdev_krouting routing = {
-		.num_routes = ARRAY_SIZE(routes),
-		.routes = routes,
-	};
-
-	return _max96714_set_routing(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE,
-				     &routing);
-}
-
-static const struct v4l2_subdev_pad_ops max96714_pad_ops = {
-	.enable_streams = max96714_enable_streams,
-	.disable_streams = max96714_disable_streams,
-
-	.set_routing = max96714_set_routing,
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = max96714_set_fmt,
-};
-
-static bool max96714_link_locked(struct max96714_priv *priv)
-{
-	u64 val = 0;
-
-	cci_read(priv->regmap, MAX96714_LINK_LOCK, &val, NULL);
-
-	return val & MAX96714_LINK_LOCK_BIT;
-}
-
-static void max96714_link_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Link locked:%d\n", max96714_link_locked(priv));
-}
-
-static bool max96714_pipe_locked(struct max96714_priv *priv)
-{
-	u64 val;
-
-	cci_read(priv->regmap, MAX96714_VIDEO_RX8, &val, NULL);
-
-	return val & MAX96714_VID_LOCK;
-}
-
-static void max96714_pipe_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Pipe vidlock:%d\n", max96714_pipe_locked(priv));
-}
-
-static void max96714_csi_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 freq = 0;
-
-	cci_read(priv->regmap, MAX96714_BACKTOP25, &freq, NULL);
-	freq = FIELD_GET(CSI_DPLL_FREQ_MASK, freq);
-
-	dev_info(dev, "CSI controller DPLL freq:%u00MHz CSIPHY enabled:%d\n",
-		 (u8)freq, max96714_tx_port_enabled(priv));
-}
-
-static int max96714_log_status(struct v4l2_subdev *sd)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Deserializer: max96714\n");
-
-	max96714_link_status(priv);
-	max96714_pipe_status(priv);
-	max96714_csi_status(priv);
-
-	return 0;
-}
-
-static const struct v4l2_subdev_core_ops max96714_subdev_core_ops = {
-	.log_status = max96714_log_status,
-};
-
-static const struct v4l2_subdev_video_ops max96714_video_ops = {
-	.s_stream	= v4l2_subdev_s_stream_helper,
-};
-
-static const struct v4l2_subdev_internal_ops max96714_internal_ops = {
-	.init_state = max96714_init_state,
-};
-
-static const struct v4l2_subdev_ops max96714_subdev_ops = {
-	.video = &max96714_video_ops,
-	.core = &max96714_subdev_core_ops,
-	.pad = &max96714_pad_ops,
-};
-
-static const struct media_entity_operations max96714_entity_ops = {
-	.link_validate = v4l2_subdev_link_validate,
-};
-
-static int max96714_notify_bound(struct v4l2_async_notifier *notifier,
-				 struct v4l2_subdev *subdev,
-				 struct v4l2_async_connection *asd)
-{
-	struct max96714_priv *priv = sd_to_max96714(notifier->sd);
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	ret = media_entity_get_fwnode_pad(&subdev->entity,
-					  priv->rxport.source.ep_fwnode,
-					  MEDIA_PAD_FL_SOURCE);
-	if (ret < 0) {
-		dev_err(dev, "Failed to find pad for %s\n", subdev->name);
-		return ret;
-	}
-
-	priv->rxport.source.sd = subdev;
-	priv->rxport.source.pad = ret;
-
-	ret = media_create_pad_link(&priv->rxport.source.sd->entity,
-				    priv->rxport.source.pad, &priv->sd.entity,
-				    MAX96714_PAD_SINK,
-				    MEDIA_LNK_FL_ENABLED |
-				    MEDIA_LNK_FL_IMMUTABLE);
-	if (ret) {
-		dev_err(dev, "Unable to link %s:%u -> %s:%u\n",
-			priv->rxport.source.sd->name, priv->rxport.source.pad,
-			priv->sd.name, MAX96714_PAD_SINK);
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_async_notifier_operations max96714_notify_ops = {
-	.bound = max96714_notify_bound,
-};
-
-static int max96714_v4l2_notifier_register(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct max96714_rxport *rxport = &priv->rxport;
-	struct v4l2_async_connection *asd;
-	int ret;
-
-	if (!rxport->source.ep_fwnode)
-		return 0;
-
-	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
-
-	asd = v4l2_async_nf_add_fwnode(&priv->notifier,
-				       rxport->source.ep_fwnode,
-				       struct v4l2_async_connection);
-	if (IS_ERR(asd)) {
-		dev_err(dev, "Failed to add subdev: %pe", asd);
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return PTR_ERR(asd);
-	}
-
-	priv->notifier.ops = &max96714_notify_ops;
-
-	ret = v4l2_async_nf_register(&priv->notifier);
-	if (ret) {
-		dev_err(dev, "Failed to register subdev_notifier");
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max96714_create_subdev(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96714_subdev_ops);
-	priv->sd.internal_ops = &max96714_internal_ops;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-
-	v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ,
-			       0, 0, &priv->tx_link_freq);
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler,
-				     &max96714_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96714_test_pattern) - 1,
-				     0, 0, max96714_test_pattern);
-	if (priv->ctrl_handler.error) {
-		ret = priv->ctrl_handler.error;
-		goto err_free_ctrl;
-	}
-
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-	priv->sd.entity.ops = &max96714_entity_ops;
-
-	priv->pads[MAX96714_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	priv->pads[MAX96714_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-
-	ret = media_entity_pads_init(&priv->sd.entity,
-				     MAX96714_NPORTS,
-				     priv->pads);
-	if (ret)
-		goto err_free_ctrl;
-
-	priv->sd.state_lock = priv->sd.ctrl_handler->lock;
-
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret)
-		goto err_entity_cleanup;
-
-	ret = max96714_v4l2_notifier_register(priv);
-	if (ret) {
-		dev_err(dev, "v4l2 subdev notifier register failed: %d\n", ret);
-		goto err_subdev_cleanup;
-	}
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret) {
-		dev_err(dev, "v4l2_async_register_subdev error: %d\n", ret);
-		goto err_unreg_notif;
-	}
-
-	return 0;
-
-err_unreg_notif:
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-err_subdev_cleanup:
-	v4l2_subdev_cleanup(&priv->sd);
-err_entity_cleanup:
-	media_entity_cleanup(&priv->sd.entity);
-err_free_ctrl:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-};
-
-static void max96714_destroy_subdev(struct max96714_priv *priv)
-{
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-	v4l2_async_unregister_subdev(&priv->sd);
-
-	v4l2_subdev_cleanup(&priv->sd);
-
-	media_entity_cleanup(&priv->sd.entity);
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-}
-
-static int max96714_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
-{
-	return 0;
-}
-
-static int max96714_i2c_mux_init(struct max96714_priv *priv)
-{
-	priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
-				  1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
-				  max96714_i2c_mux_select, NULL);
-	if (!priv->mux)
-		return -ENOMEM;
-
-	return i2c_mux_add_adapter(priv->mux, 0, 0);
-}
-
-static int max96714_init_tx_port(struct max96714_priv *priv)
-{
-	struct v4l2_mbus_config_mipi_csi2 *mipi;
-	unsigned long lanes_used = 0;
-	unsigned int val, lane;
-	int ret;
-
-	ret = max96714_disable_tx_port(priv);
-
-	mipi = &priv->mipi_csi2;
-	val = div_u64(priv->tx_link_freq * 2, MHZ(100));
-
-	cci_update_bits(priv->regmap, MAX96714_BACKTOP25,
-			CSI_DPLL_FREQ_MASK, val, &ret);
-
-	val = FIELD_PREP(MAX96714_CSI2_LANE_CNT_MASK, mipi->num_data_lanes - 1);
-	cci_update_bits(priv->regmap, MAX96714_MIPI_LANE_CNT,
-			MAX96714_CSI2_LANE_CNT_MASK, val, &ret);
-
-	/* lanes polarity */
-	val = 0;
-	for (lane = 0; lane < mipi->num_data_lanes + 1; lane++) {
-		if (!mipi->lane_polarities[lane])
-			continue;
-		if (lane == 0)
-			/* clock lane */
-			val |= BIT(5);
-		else if (lane < 3)
-			/* Lane D0 and D1 */
-			val |= BIT(lane - 1);
-		else
-			/* D2 and D3 */
-			val |= BIT(lane);
-	}
-
-	cci_update_bits(priv->regmap, MAX96714_MIPI_POLARITY,
-			MAX96714_MIPI_POLARITY_MASK, val, &ret);
-
-	/* lanes mapping */
-	val = 0;
-	for (lane = 0; lane < mipi->num_data_lanes; lane++) {
-		val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
-		lanes_used |= BIT(mipi->data_lanes[lane] - 1);
-	}
-
-	/*
-	 * Unused lanes need to be mapped as well to not have
-	 * the same lanes mapped twice.
-	 */
-	for (; lane < MAX96714_CSI_NLANES; lane++) {
-		unsigned int idx = find_first_zero_bit(&lanes_used,
-						       MAX96714_CSI_NLANES);
-
-		val |= idx << (lane * 2);
-		lanes_used |= BIT(idx);
-	}
-
-	return cci_write(priv->regmap, MAX96714_MIPI_LANE_MAP, val, &ret);
-}
-
-static int max96714_rxport_enable_poc(struct max96714_priv *priv)
-{
-	struct max96714_rxport *rxport = &priv->rxport;
-
-	if (!rxport->poc)
-		return 0;
-
-	return regulator_enable(rxport->poc);
-}
-
-static int max96714_rxport_disable_poc(struct max96714_priv *priv)
-{
-	struct max96714_rxport *rxport = &priv->rxport;
-
-	if (!rxport->poc)
-		return 0;
-
-	return regulator_disable(rxport->poc);
-}
-
-static int max96714_parse_dt_txport(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
-	struct fwnode_handle *ep_fwnode;
-	u32 num_data_lanes;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96714_PAD_SOURCE, 0, 0);
-	if (!ep_fwnode)
-		return -EINVAL;
-
-	ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &vep);
-	fwnode_handle_put(ep_fwnode);
-	if (ret) {
-		dev_err(dev, "tx: failed to parse endpoint data\n");
-		return -EINVAL;
-	}
-
-	if (vep.nr_of_link_frequencies != 1) {
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	priv->tx_link_freq = vep.link_frequencies[0];
-	/* Min 50MHz, Max 1250MHz, 50MHz step */
-	if (priv->tx_link_freq < MHZ(50) || priv->tx_link_freq > MHZ(1250) ||
-	    (u32)priv->tx_link_freq % MHZ(50)) {
-		dev_err(dev, "tx: invalid link frequency\n");
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
-	if (num_data_lanes < 1 || num_data_lanes > MAX96714_CSI_NLANES) {
-		dev_err(dev,
-			"tx: invalid number of data lanes must be 1 to 4\n");
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	priv->mipi_csi2 = vep.bus.mipi_csi2;
-
-err_free_vep:
-	v4l2_fwnode_endpoint_free(&vep);
-
-	return ret;
-}
-
-static int max96714_parse_dt_rxport(struct max96714_priv *priv)
-{
-	static const char *poc_name = "port0-poc";
-	struct max96714_rxport *rxport = &priv->rxport;
-	struct device *dev = &priv->client->dev;
-	struct fwnode_handle *ep_fwnode;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96714_PAD_SINK, 0, 0);
-	if (!ep_fwnode)
-		return -ENOENT;
-
-	rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode);
-	fwnode_handle_put(ep_fwnode);
-
-	if (!rxport->source.ep_fwnode) {
-		dev_err(dev, "rx: no remote endpoint\n");
-		return -EINVAL;
-	}
-
-	rxport->poc = devm_regulator_get_optional(dev, poc_name);
-	if (IS_ERR(rxport->poc)) {
-		ret = PTR_ERR(rxport->poc);
-		if (ret == -ENODEV) {
-			rxport->poc = NULL;
-		} else {
-			dev_err(dev, "rx: failed to get POC supply: %d\n", ret);
-			goto err_put_source_ep_fwnode;
-		}
-	}
-
-	return 0;
-
-err_put_source_ep_fwnode:
-	fwnode_handle_put(rxport->source.ep_fwnode);
-	return ret;
-}
-
-static int max96714_parse_dt(struct max96714_priv *priv)
-{
-	int ret;
-
-	ret = max96714_parse_dt_txport(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_parse_dt_rxport(priv);
-	/*
-	 * The deserializer can create a test pattern even if the
-	 * rx port is not connected to a serializer.
-	 */
-	if (ret && ret == -ENOENT)
-		ret = 0;
-
-	return ret;
-}
-
-static int max96714_enable_core_hw(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 val;
-	int ret;
-
-	if (priv->pd_gpio) {
-		/* wait min 2 ms for reset to complete */
-		gpiod_set_value_cansleep(priv->pd_gpio, 1);
-		fsleep(2000);
-		gpiod_set_value_cansleep(priv->pd_gpio, 0);
-		/* wait min 2 ms for power up to finish */
-		fsleep(2000);
-	}
-
-	ret = cci_read(priv->regmap, MAX96714_REG13, &val, NULL);
-	if (ret) {
-		dev_err_probe(dev, ret, "Cannot read first register, abort\n");
-		goto err_pd_gpio;
-	}
-
-	if (val != MAX96714_DEVICE_ID && val != MAX96714F_DEVICE_ID) {
-		dev_err(dev, "Unsupported device id expected %x got %x\n",
-			MAX96714F_DEVICE_ID, (u8)val);
-		ret = -EOPNOTSUPP;
-		goto err_pd_gpio;
-	}
-
-	ret = cci_read(priv->regmap, MAX96714_DEV_REV, &val, NULL);
-	if (ret)
-		goto err_pd_gpio;
-
-	dev_dbg(dev, "Found %x (rev %lx)\n", MAX96714F_DEVICE_ID,
-		(u8)val & MAX96714_DEV_REV_MASK);
-
-	ret = cci_read(priv->regmap, MAX96714_MIPI_TX52, &val, NULL);
-	if (ret)
-		goto err_pd_gpio;
-
-	if (!(val & MAX96714_TUN_EN)) {
-		dev_err(dev, "Only supporting tunnel mode");
-		ret = -EOPNOTSUPP;
-		goto err_pd_gpio;
-	}
-
-	return 0;
-
-err_pd_gpio:
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-	return ret;
-}
-
-static void max96714_disable_core_hw(struct max96714_priv *priv)
-{
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-}
-
-static int max96714_get_hw_resources(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	priv->regmap = devm_cci_regmap_init_i2c(priv->client, 16);
-	if (IS_ERR(priv->regmap))
-		return PTR_ERR(priv->regmap);
-
-	priv->pd_gpio =
-		devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
-	if (IS_ERR(priv->pd_gpio))
-		return dev_err_probe(dev, PTR_ERR(priv->pd_gpio),
-				     "Cannot get powerdown GPIO\n");
-	return 0;
-}
-
-static int max96714_probe(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-	struct max96714_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->client = client;
-
-	ret = max96714_get_hw_resources(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_enable_core_hw(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_parse_dt(priv);
-	if (ret)
-		goto err_disable_core_hw;
-
-	max96714_init_tx_port(priv);
-
-	ret = max96714_rxport_enable_poc(priv);
-	if (ret)
-		goto err_free_ports;
-
-	ret = max96714_i2c_mux_init(priv);
-	if (ret)
-		goto err_disable_poc;
-
-	ret = max96714_create_subdev(priv);
-	if (ret)
-		goto err_del_mux;
-
-	return 0;
-
-err_del_mux:
-	i2c_mux_del_adapters(priv->mux);
-err_disable_poc:
-	max96714_rxport_disable_poc(priv);
-err_free_ports:
-	fwnode_handle_put(priv->rxport.source.ep_fwnode);
-err_disable_core_hw:
-	max96714_disable_core_hw(priv);
-
-	return ret;
-}
-
-static void max96714_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96714_priv *priv = sd_to_max96714(sd);
-
-	max96714_destroy_subdev(priv);
-	i2c_mux_del_adapters(priv->mux);
-	max96714_rxport_disable_poc(priv);
-	fwnode_handle_put(priv->rxport.source.ep_fwnode);
-	max96714_disable_core_hw(priv);
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-}
-
-static const struct of_device_id max96714_of_ids[] = {
-	{ .compatible = "maxim,max96714f" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, max96714_of_ids);
-
-static struct i2c_driver max96714_i2c_driver = {
-	.driver	= {
-		.name		= "max96714",
-		.of_match_table	= max96714_of_ids,
-	},
-	.probe		= max96714_probe,
-	.remove		= max96714_remove,
-};
-
-module_i2c_driver(max96714_i2c_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Maxim Integrated GMSL2 Deserializers Driver");
-MODULE_AUTHOR("Julien Massot <julien.massot at collabora.com>");
-- 
2.48.1



From arturas.moskvinas at gmail.com  Sat Mar  8 11:03:59 2025
From: arturas.moskvinas at gmail.com (Arturas Moskvinas)
Date: Sat, 8 Mar 2025 21:03:59 +0200
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add Xunlong Orange Pi 3B
In-Reply-To: <29739e60-15f5-4361-a57a-2e6b93fba09c@kwiboo.se>
References: <20240626230319.1425316-1-jonas@kwiboo.se>
 <20240626230319.1425316-3-jonas@kwiboo.se>
 <d1c600f1-a874-4bb8-8b9f-22a3414edfcc@gmail.com>
 <29739e60-15f5-4361-a57a-2e6b93fba09c@kwiboo.se>
Message-ID: <5bb045fe-89c3-46dd-bd9a-dee8800a6d58@gmail.com>


On 3/8/25 6:34 PM, Jonas Karlman wrote:
> This is because of a reset issue with Ethernet PHYs in Linux, see [1].
>
> Two workarounds:
> 1. Let boot firmware reset the PHY before Linux, i.e. use U-Boot
>     v2024.10 or newer.
> 2. Use a ethernet-phy-id compatible with correct phy-id to force Linux
>     to attach the PHY.
>
> I suggest you try to wipe U-Boot from SPI flash on your board and update
> to use U-Boot v2025.01 and try again.
Wiping board SPI flash which contained old U-boot and using 2025.01 from 
SD card fixed issue hence DTS is OK.
Though I do not remember that I ever wrote anything into SPI flash in 
first place (I touched board almost year ago so potentially forgot about 
it) maybe it was shipped like that with the board...

Arturas Moskvinas


From robh at kernel.org  Sat Mar  8 11:44:30 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sat, 08 Mar 2025 13:44:30 -0600
Subject: [RFC PATCH 18/24] dt-bindings: media: i2c: max96712: add
 support for I2C MUX
In-Reply-To: <20250308183410.3013996-19-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-19-demonsingur@gmail.com>
Message-ID: <174146307027.3480579.7919845264276459579.robh@kernel.org>


On Sat, 08 Mar 2025 20:33:47 +0200, Cosmin Tanislav wrote:
> MAX96712 and MAX96724 have more than one GMSL2 link, and each link is
> capable of connecting to a separate serializer. If these serializers
> have the same CFG pins configuration, they will also have the same I2C
> address, causing conflicts unless the deserializer muxes the I2C
> channels. Moreover, the serializers can have the same hardware attached
> to their respective I2C bus.
> 
> The MAX96712 and MAX96724 suppot I2C channel muxing via the GMSL2 link
> to facilitate communication to each of the connected serializers.
> 
> Document this capability.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../devicetree/bindings/media/i2c/maxim,max96712.yaml | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg:items: 'oneOf' conditional failed, one must be fixed:
	/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg:items: 'anyOf' conditional failed, one must be fixed:
		'min' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
		'type' was expected
		from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
	/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg:items: 'anyOf' conditional failed, one must be fixed:
		'max' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
		'type' was expected
		from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
	{'min': 0, 'max': 3} is not of type 'array'
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg: 'anyOf' conditional failed, one must be fixed:
	'maxItems' is a required property
		hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
	'items' is not one of ['maxItems', 'description', 'deprecated']
		hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
	'items' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
	/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg:items: 'oneOf' conditional failed, one must be fixed:
		/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: properties:i2c-mux:patternProperties:^i2c@[0-3]$:properties:reg:items: 'anyOf' conditional failed, one must be fixed:
			'maxItems' is a required property
				hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
			'min' is not one of ['maxItems', 'description', 'deprecated']
				hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
			'max' is not one of ['maxItems', 'description', 'deprecated']
				hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
			Additional properties are not allowed ('max', 'min' were unexpected)
				hint: Arrays must be described with a combination of minItems/maxItems/items
			'min' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
				hint: "items" can be a list defining each entry or a schema applying to all items. A list has an implicit size. A schema requires minItems/maxItems to define the size.
			'max' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
				hint: "items" can be a list defining each entry or a schema applying to all items. A list has an implicit size. A schema requires minItems/maxItems to define the size.
			hint: cell array properties must define how many entries and what the entries are when there is more than one entry.
			from schema $id: http://devicetree.org/meta-schemas/core.yaml#
		{'min': 0, 'max': 3} is not of type 'array'
		hint: "items" can be a list defining each entry or a schema applying to all items. A list has an implicit size. A schema requires minItems/maxItems to define the size.
		from schema $id: http://devicetree.org/meta-schemas/core.yaml#
	hint: cell array properties must define how many entries and what the entries are when there is more than one entry.
	from schema $id: http://devicetree.org/meta-schemas/core.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: i2c-mux: Missing additionalProperties/unevaluatedProperties constraint

/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: ^i2c@[0-3]$: Missing additionalProperties/unevaluatedProperties constraint

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308183410.3013996-19-demonsingur at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From robh at kernel.org  Sat Mar  8 11:59:37 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sat, 08 Mar 2025 13:59:37 -0600
Subject: [RFC PATCH 19/24] dt-bindings: media: i2c: max96712: add
 support for POC supplies
In-Reply-To: <20250308183410.3013996-20-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-20-demonsingur@gmail.com>
Message-ID: <174146397700.3496940.17285353944853657369.robh@kernel.org>


On Sat, 08 Mar 2025 20:33:48 +0200, Cosmin Tanislav wrote:
> The GMSL links can carry power to the serializer when using coaxial
> cables.
> 
> Document this capability.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../devicetree/bindings/media/i2c/maxim,max96712.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml: patternProperties: 'port[0-3]-poc-supply' does not match '[\\^$()*@]'
	hint: Fixed strings belong in 'properties', not 'patternProperties'
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308183410.3013996-20-demonsingur at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From robh at kernel.org  Sat Mar  8 12:44:57 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sat, 08 Mar 2025 14:44:57 -0600
Subject: [RFC PATCH 04/24] dt-bindings: media: i2c: max96717: add
 support for pinctrl/pinconf
In-Reply-To: <20250308183410.3013996-5-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-5-demonsingur@gmail.com>
Message-ID: <174146669680.3550268.1623859001392058870.robh@kernel.org>


On Sat, 08 Mar 2025 20:33:33 +0200, Cosmin Tanislav wrote:
> MAX96717 is capable of configuring various pin properties.
> 
> Add pinctrl/pinconf properties to support this usecase.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../media/i2c/maxim,max96717-pinctrl.yaml     | 71 +++++++++++++++++++
>  .../bindings/media/i2c/maxim,max96717.yaml    | 16 ++++-
>  MAINTAINERS                                   |  1 +
>  3 files changed, 87 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,gmsl-rx-id: 'anyOf' conditional failed, one must be fixed:
	'min' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,gmsl-rx-id: 'anyOf' conditional failed, one must be fixed:
	'max' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,rclkout-clock: 'anyOf' conditional failed, one must be fixed:
	'min' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,rclkout-clock: 'anyOf' conditional failed, one must be fixed:
	'max' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,gmsl-tx-id: 'anyOf' conditional failed, one must be fixed:
	'min' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml: properties:maxim,gmsl-tx-id: 'anyOf' conditional failed, one must be fixed:
	'max' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96717.example.dtb: serializer at 40: i2c-gate: 'anyOf' conditional failed, one must be fixed:
	Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'sensor at 10' were unexpected)
	1 is not of type 'object'
	0 is not of type 'object'
	Unevaluated properties are not allowed ('VANA-supply', 'VCORE-supply', 'VDDIO-supply', 'clocks', 'compatible', 'port', 'reg', 'reset-gpios' were unexpected)
	from schema $id: http://devicetree.org/schemas/media/i2c/maxim,max96717.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308183410.3013996-5-demonsingur at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From robh at kernel.org  Sat Mar  8 12:44:59 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sat, 08 Mar 2025 14:44:59 -0600
Subject: [RFC PATCH 09/24] dt-bindings: media: i2c: max96714: make
 i2c-gate conditional on compatible
In-Reply-To: <20250308183410.3013996-10-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-10-demonsingur@gmail.com>
Message-ID: <174146669769.3550313.9537741171612632999.robh@kernel.org>


On Sat, 08 Mar 2025 20:33:38 +0200, Cosmin Tanislav wrote:
> Devices to be added in following patches don't use I2C gate.
> 
> Make this property conditional on the compatible strings.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96714.yaml    | 21 ++++++++++++-------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/maxim,max96714.example.dtb: deserializer at 28: 'i2c-gate' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/media/i2c/maxim,max96714.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250308183410.3013996-10-demonsingur at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From arnd at arndb.de  Sat Mar  8 13:05:24 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Sat, 08 Mar 2025 22:05:24 +0100
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for arm64
In-Reply-To: <20250307220304.247725-4-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
Message-ID: <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>

On Fri, Mar 7, 2025, at 23:02, Roman Kisel wrote:
> @@ -5,18 +5,20 @@ menu "Microsoft Hyper-V guest support"
>  config HYPERV
>  	tristate "Microsoft Hyper-V client drivers"
>  	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
> -		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
> +		|| (ARM64 && !CPU_BIG_ENDIAN)
> +	depends on (ACPI || HYPERV_VTL_MODE)
>  	select PARAVIRT
>  	select X86_HV_CALLBACK_VECTOR if X86
> -	select OF_EARLY_FLATTREE if OF
>  	help
>  	  Select this option to run Linux as a Hyper-V client operating
>  	  system.
> 
>  config HYPERV_VTL_MODE
>  	bool "Enable Linux to boot in VTL context"
> -	depends on X86_64 && HYPERV
> +	depends on (X86_64 || ARM64)
>  	depends on SMP
> +	select OF_EARLY_FLATTREE
> +	select OF
>  	default n
>  	help

Having the dependency below the top-level Kconfig entry feels a little
counterintuitive. You could flip that back as it was before by doing

      select HYPERV_VTL_MODE if !ACPI
      depends on ACPI || SMP

in the HYPERV option, leaving the dependency on HYPERV in
HYPERV_VTL_MODE.

Is OF_EARLY_FLATTREE actually needed on x86?

      Arnd


From arnd at arndb.de  Sat Mar  8 13:08:39 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Sat, 08 Mar 2025 22:08:39 +0100
Subject: [PATCH hyperv-next v5 01/11] arm64: kvm, smccc: Introduce and use API for
 detectting hypervisor presence
In-Reply-To: <20250307220304.247725-2-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-2-romank@linux.microsoft.com>
Message-ID: <d15274c2-6d61-4db3-ab0f-90591d28bc34@app.fastmail.com>

On Fri, Mar 7, 2025, at 23:02, Roman Kisel wrote:
> The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
> private, and it follows the SMCCC specification. Other existing and
> emerging hypervisor guest implementations can and should use that
> standard approach as well.
>
> Factor out a common infrastructure that the guests can use, update KVM
> to employ the new API. The cenrtal notion of the SMCCC method is the
> UUID of the hypervisor, and the API follows that.
>
> No functional changes. Validated with a KVM/arm64 guest.
>
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>

Acked-by: Arnd Bergmann <arnd at arndb.de>



From arnd at arndb.de  Sat Mar  8 13:11:32 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Sat, 08 Mar 2025 22:11:32 +0100
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ number from
 DeviceTree
In-Reply-To: <20250307220304.247725-9-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-9-romank@linux.microsoft.com>
Message-ID: <29bb5b7a-b31f-4b32-92c6-e2588a0f965a@app.fastmail.com>

On Fri, Mar 7, 2025, at 23:03, Roman Kisel wrote:
> 
> +static int __maybe_unused vmbus_set_irq(struct platform_device *pdev)

Instead of the __maybe_unused annotation here

> 
> +#ifndef HYPERVISOR_CALLBACK_VECTOR
> +	ret = vmbus_set_irq(pdev);
> +	if (ret)
> +		return ret;
> +#endif
> +

you can use 

       if (!__is_defined(HYPERVISOR_CALLBACK_VECTOR))
                  ret = vmbus_set_irq(pdev);

and make it a little more readable.

    Arnd


From jonas at kwiboo.se  Sat Mar  8 13:37:13 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat,  8 Mar 2025 21:37:13 +0000
Subject: [PATCH v2 1/3] dt-bindings: net: rockchip-dwmac: Require rockchip,grf and rockchip,php-grf
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <20250308213720.2517944-2-jonas@kwiboo.se>

All Rockchip GMAC variants typically write to GRF regs to control e.g.
interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3562,
RK3576 and RK3588 use a mix of GRF and peripheral GRF regs.

Prior to the commit b331b8ef86f0 ("dt-bindings: net: convert
rockchip-dwmac to json-schema") the property rockchip,grf was listed
under "Required properties". During the conversion this was lost and
rockchip,grf has since then incorrectly been treated as optional and
not as required.

Similarly, when rockchip,php-grf was added to the schema in the
commit a2b77831427c ("dt-bindings: net: rockchip-dwmac: add rk3588 gmac
compatible") it also incorrectly has been treated as optional for all
GMAC variants, when it should have been required for RK3588, and later
also for RK3576.

Update this binding to require rockchip,grf and rockchip,php-grf to
properly reflect that GRF (and peripheral GRF for RK3576/RK3588) is
required to control part of GMAC.

This should not introduce any breakage as all Rockchip GMAC nodes have
been added together with a rockchip,grf phandle (and rockchip,php-grf
where required) in their initial commit.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Reword the commit message
- Disable rockchip,php-grf for other GMACs than RK3576 and RK3588

The pending rockchip,rk3562-gmac compatible [1] must also be added to
the list of compatible that require rockchip,php-grf.

[1] https://lore.kernel.org/r/20250227110652.2342729-1-kever.yang at rock-chips.com/
---
 .../bindings/net/rockchip-dwmac.yaml          | 21 ++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
index f8a576611d6c..8dd870f0214d 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
@@ -32,9 +32,6 @@ select:
   required:
     - compatible
 
-allOf:
-  - $ref: snps,dwmac.yaml#
-
 properties:
   compatible:
     oneOf:
@@ -114,6 +111,24 @@ required:
   - compatible
   - clocks
   - clock-names
+  - rockchip,grf
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,rk3576-gmac
+              - rockchip,rk3588-gmac
+    then:
+      required:
+        - rockchip,php-grf
+    else:
+      properties:
+        rockchip,php-grf: false
 
 unevaluatedProperties: false
 
-- 
2.48.1



From jonas at kwiboo.se  Sat Mar  8 13:37:14 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat,  8 Mar 2025 21:37:14 +0000
Subject: [PATCH v2 2/3] net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <20250308213720.2517944-3-jonas@kwiboo.se>

All Rockchip GMAC variants typically write to GRF regs to control e.g.
interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
located with help of a rockchip,grf and rockchip,php-grf phandle.

However, validating the rockchip,grf and rockchip,php-grf syscon regmap
is deferred until e.g. interface mode or speed is configured, inside the
individual SoC specific operations.

Change to validate the rockchip,grf and rockchip,php-grf syscon regmap
at probe time to simplify all SoC specific operations.

This should not introduce any backward compatibility issues as all
GMAC nodes have been added together with a rockchip,grf phandle (and
rockchip,php-grf where required) in their initial commit.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Split removal of the IS_ERR() check in each SoC specific operation to
  a separate patch
- Add a php_grf_required flag to indicate when peripheral GRF is
  required
- Only lookup rockchip,php-grf phandle when php_grf_required is true
- Use ERR_CAST() instead of ERR_PTR()

The pending addition of RK3562 support [1] must be adjusted to set
.php_grf_required = true, or this will break RK3562 support.

[1] https://lore.kernel.org/r/20250227110652.2342729-2-kever.yang at rock-chips.com/
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 21 +++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..5615f015c5fe 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,6 +33,7 @@ struct rk_gmac_ops {
 	void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
 				    bool enable);
 	void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
+	bool php_grf_required;
 	bool regs_valid;
 	u32 regs[];
 };
@@ -1254,6 +1255,7 @@ static const struct rk_gmac_ops rk3576_ops = {
 	.set_rgmii_speed = rk3576_set_gmac_speed,
 	.set_rmii_speed = rk3576_set_gmac_speed,
 	.set_clock_selection = rk3576_set_clock_selection,
+	.php_grf_required = true,
 	.regs_valid = true,
 	.regs = {
 		0x2a220000, /* gmac0 */
@@ -1401,6 +1403,7 @@ static const struct rk_gmac_ops rk3588_ops = {
 	.set_rgmii_speed = rk3588_set_gmac_speed,
 	.set_rmii_speed = rk3588_set_gmac_speed,
 	.set_clock_selection = rk3588_set_clock_selection,
+	.php_grf_required = true,
 	.regs_valid = true,
 	.regs = {
 		0xfe1b0000, /* gmac0 */
@@ -1812,8 +1815,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 
 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
 							"rockchip,grf");
-	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
-							    "rockchip,php-grf");
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err_probe(dev, PTR_ERR(bsp_priv->grf),
+			      "failed to lookup rockchip,grf\n");
+		return ERR_CAST(bsp_priv->grf);
+	}
+
+	if (ops->php_grf_required) {
+		bsp_priv->php_grf =
+			syscon_regmap_lookup_by_phandle(dev->of_node,
+							"rockchip,php-grf");
+		if (IS_ERR(bsp_priv->php_grf)) {
+			dev_err_probe(dev, PTR_ERR(bsp_priv->php_grf),
+				      "failed to lookup rockchip,php-grf\n");
+			return ERR_CAST(bsp_priv->php_grf);
+		}
+	}
 
 	if (plat->phy_node) {
 		bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
-- 
2.48.1



From jonas at kwiboo.se  Sat Mar  8 13:37:14 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat,  8 Mar 2025 21:37:14 +0000
Subject: [PATCH v2 2/3] net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <20250308213720.2517944-3-jonas@kwiboo.se>

All Rockchip GMAC variants typically write to GRF regs to control e.g.
interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
located with help of a rockchip,grf and rockchip,php-grf phandle.

However, validating the rockchip,grf and rockchip,php-grf syscon regmap
is deferred until e.g. interface mode or speed is configured, inside the
individual SoC specific operations.

Change to validate the rockchip,grf and rockchip,php-grf syscon regmap
at probe time to simplify all SoC specific operations.

This should not introduce any backward compatibility issues as all
GMAC nodes have been added together with a rockchip,grf phandle (and
rockchip,php-grf where required) in their initial commit.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Split removal of the IS_ERR() check in each SoC specific operation to
  a separate patch
- Add a php_grf_required flag to indicate when peripheral GRF is
  required
- Only lookup rockchip,php-grf phandle when php_grf_required is true
- Use ERR_CAST() instead of ERR_PTR()

The pending addition of RK3562 support [1] must be adjusted to set
.php_grf_required = true, or this will break RK3562 support.

[1] https://lore.kernel.org/r/20250227110652.2342729-2-kever.yang at rock-chips.com/
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 21 +++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..5615f015c5fe 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,6 +33,7 @@ struct rk_gmac_ops {
 	void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
 				    bool enable);
 	void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
+	bool php_grf_required;
 	bool regs_valid;
 	u32 regs[];
 };
@@ -1254,6 +1255,7 @@ static const struct rk_gmac_ops rk3576_ops = {
 	.set_rgmii_speed = rk3576_set_gmac_speed,
 	.set_rmii_speed = rk3576_set_gmac_speed,
 	.set_clock_selection = rk3576_set_clock_selection,
+	.php_grf_required = true,
 	.regs_valid = true,
 	.regs = {
 		0x2a220000, /* gmac0 */
@@ -1401,6 +1403,7 @@ static const struct rk_gmac_ops rk3588_ops = {
 	.set_rgmii_speed = rk3588_set_gmac_speed,
 	.set_rmii_speed = rk3588_set_gmac_speed,
 	.set_clock_selection = rk3588_set_clock_selection,
+	.php_grf_required = true,
 	.regs_valid = true,
 	.regs = {
 		0xfe1b0000, /* gmac0 */
@@ -1812,8 +1815,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 
 	bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
 							"rockchip,grf");
-	bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
-							    "rockchip,php-grf");
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err_probe(dev, PTR_ERR(bsp_priv->grf),
+			      "failed to lookup rockchip,grf\n");
+		return ERR_CAST(bsp_priv->grf);
+	}
+
+	if (ops->php_grf_required) {
+		bsp_priv->php_grf =
+			syscon_regmap_lookup_by_phandle(dev->of_node,
+							"rockchip,php-grf");
+		if (IS_ERR(bsp_priv->php_grf)) {
+			dev_err_probe(dev, PTR_ERR(bsp_priv->php_grf),
+				      "failed to lookup rockchip,php-grf\n");
+			return ERR_CAST(bsp_priv->php_grf);
+		}
+	}
 
 	if (plat->phy_node) {
 		bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
-- 
2.48.1



From jonas at kwiboo.se  Sat Mar  8 13:37:12 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat,  8 Mar 2025 21:37:12 +0000
Subject: [PATCH v2 0/3] net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
Message-ID: <20250308213720.2517944-1-jonas@kwiboo.se>

All Rockchip GMAC variants typically write to GRF regs to control e.g.
interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
located with help of a rockchip,grf and rockchip,php-grf phandle.

However, validating the rockchip,grf and rockchip,php-grf syscon regmap
is deferred until e.g. interface mode or speed is configured.

This series change to validate the GRF and peripheral GRF syscon regmap
at probe time to help simplify the SoC specific operations.

This should not introduce any backward compatibility issues as all
GMAC nodes have been added together with a rockchip,grf phandle (and
rockchip,php-grf where required) in their initial commit.

Changes in v2:
- Split removal of the IS_ERR() check in each SoC specific operation to
  a separate patch
- Disable rockchip,php-grf in schema for GMAC not requiring it
- Add a php_grf_required flag to indicate when peripheral GRF is
  required
- Only lookup rockchip,php-grf phandle when php_grf_required is true
- Use ERR_CAST() instead of ERR_PTR()

Jonas Karlman (3):
  dt-bindings: net: rockchip-dwmac: Require rockchip,grf and
    rockchip,php-grf
  net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
  net: stmmac: dwmac-rk: Remove unneeded GRF and peripheral GRF checks

 .../bindings/net/rockchip-dwmac.yaml          |  21 +-
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 270 ++----------------
 2 files changed, 37 insertions(+), 254 deletions(-)

-- 
2.48.1



From jonas at kwiboo.se  Sat Mar  8 13:37:15 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat,  8 Mar 2025 21:37:15 +0000
Subject: [PATCH v2 3/3] net: stmmac: dwmac-rk: Remove unneeded GRF and peripheral GRF checks
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <20250308213720.2517944-4-jonas@kwiboo.se>

Now that GRF, and peripheral GRF where needed, is validated at probe
time there is no longer any need to check and log an error in each SoC
specific operation.

Remove unneeded IS_ERR() checks and early bail out from each SoC
specific operation.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Split removal of IS_ERR() checks to its own patch
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 249 ------------------
 1 file changed, 249 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 5615f015c5fe..342463587d06 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -102,13 +102,6 @@ struct rk_priv_data {
 
 static void px30_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
 		     PX30_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -182,13 +175,6 @@ static const struct rk_gmac_ops px30_ops = {
 static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 		     RK3128_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3128_GMAC_RMII_MODE_CLR);
@@ -200,13 +186,6 @@ static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 		     RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE);
 }
@@ -215,11 +194,6 @@ static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 			     RK3128_GMAC_CLK_2_5M);
@@ -237,11 +211,6 @@ static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
 			     RK3128_GMAC_RMII_CLK_2_5M |
@@ -298,13 +267,6 @@ static const struct rk_gmac_ops rk3128_ops = {
 static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 		     RK3228_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3228_GMAC_RMII_MODE_CLR |
@@ -317,13 +279,6 @@ static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 		     RK3228_GMAC_PHY_INTF_SEL_RMII |
 		     RK3228_GMAC_RMII_MODE);
@@ -336,11 +291,6 @@ static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 			     RK3228_GMAC_CLK_2_5M);
@@ -358,11 +308,6 @@ static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
 			     RK3228_GMAC_RMII_CLK_2_5M |
@@ -420,13 +365,6 @@ static const struct rk_gmac_ops rk3228_ops = {
 static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3288_GMAC_RMII_MODE_CLR);
@@ -438,13 +376,6 @@ static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
 }
@@ -453,11 +384,6 @@ static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 			     RK3288_GMAC_CLK_2_5M);
@@ -475,11 +401,6 @@ static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
 			     RK3288_GMAC_RMII_CLK_2_5M |
@@ -512,13 +433,6 @@ static const struct rk_gmac_ops rk3288_ops = {
 
 static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
 		     RK3308_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -527,11 +441,6 @@ static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
 			     RK3308_GMAC_SPEED_10M);
@@ -584,13 +493,6 @@ static const struct rk_gmac_ops rk3308_ops = {
 static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
 		     RK3328_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3328_GMAC_RMII_MODE_CLR |
@@ -604,14 +506,8 @@ static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int reg;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
 		  RK3328_GRF_MAC_CON1;
 
@@ -624,11 +520,6 @@ static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
 			     RK3328_GMAC_CLK_2_5M);
@@ -647,11 +538,6 @@ static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int reg;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
 		  RK3328_GRF_MAC_CON1;
 
@@ -712,13 +598,6 @@ static const struct rk_gmac_ops rk3328_ops = {
 static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 		     RK3366_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3366_GMAC_RMII_MODE_CLR);
@@ -730,13 +609,6 @@ static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 		     RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE);
 }
@@ -745,11 +617,6 @@ static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 			     RK3366_GMAC_CLK_2_5M);
@@ -767,11 +634,6 @@ static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
 			     RK3366_GMAC_RMII_CLK_2_5M |
@@ -823,13 +685,6 @@ static const struct rk_gmac_ops rk3366_ops = {
 static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3368_GMAC_RMII_MODE_CLR);
@@ -841,13 +696,6 @@ static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
 }
@@ -856,11 +704,6 @@ static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 			     RK3368_GMAC_CLK_2_5M);
@@ -878,11 +721,6 @@ static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
 			     RK3368_GMAC_RMII_CLK_2_5M |
@@ -934,13 +772,6 @@ static const struct rk_gmac_ops rk3368_ops = {
 static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 		     RK3399_GMAC_PHY_INTF_SEL_RGMII |
 		     RK3399_GMAC_RMII_MODE_CLR);
@@ -952,13 +783,6 @@ static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 		     RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE);
 }
@@ -967,11 +791,6 @@ static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10)
 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 			     RK3399_GMAC_CLK_2_5M);
@@ -989,11 +808,6 @@ static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
 			     RK3399_GMAC_RMII_CLK_2_5M |
@@ -1038,14 +852,8 @@ static const struct rk_gmac_ops rk3399_ops = {
 static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 con0, con1;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	con0 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON0 :
 				     RK3568_GRF_GMAC0_CON0;
 	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
@@ -1063,14 +871,8 @@ static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 con1;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
 				     RK3568_GRF_GMAC0_CON1;
 	regmap_write(bsp_priv->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
@@ -1148,14 +950,8 @@ static const struct rk_gmac_ops rk3568_ops = {
 static void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int offset_con;
 
-	if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "Missing rockchip,grf or rockchip,php-grf property\n");
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 					 RK3576_GRF_GMAC_CON0;
 
@@ -1181,14 +977,8 @@ static void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3576_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	unsigned int offset_con;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 					 RK3576_GRF_GMAC_CON0;
 
@@ -1308,14 +1098,8 @@ static const struct rk_gmac_ops rk3576_ops = {
 static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
 	u32 offset_con, id = bsp_priv->id;
 
-	if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "Missing rockchip,grf or rockchip,php_grf property\n");
-		return;
-	}
-
 	offset_con = bsp_priv->id == 1 ? RK3588_GRF_GMAC_CON9 :
 					 RK3588_GRF_GMAC_CON8;
 
@@ -1336,13 +1120,6 @@ static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rk3588_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->php_grf)) {
-		dev_err(dev, "%s: Missing rockchip,php_grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
 		     RK3588_GMAC_PHY_INTF_SEL_RMII(bsp_priv->id));
 
@@ -1426,13 +1203,6 @@ static const struct rk_gmac_ops rk3588_ops = {
 
 static void rv1108_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
 		     RV1108_GMAC_PHY_INTF_SEL_RMII);
 }
@@ -1441,11 +1211,6 @@ static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
 			     RV1108_GMAC_RMII_CLK_2_5M |
@@ -1494,13 +1259,6 @@ static const struct rk_gmac_ops rv1108_ops = {
 static void rv1126_set_to_rgmii(struct rk_priv_data *bsp_priv,
 				int tx_delay, int rx_delay)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "Missing rockchip,grf property\n");
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
 		     RV1126_GMAC_PHY_INTF_SEL_RGMII |
 		     RV1126_GMAC_M0_RXCLK_DLY_ENABLE |
@@ -1519,13 +1277,6 @@ static void rv1126_set_to_rgmii(struct rk_priv_data *bsp_priv,
 
 static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
-	struct device *dev = &bsp_priv->pdev->dev;
-
-	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-		return;
-	}
-
 	regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
 		     RV1126_GMAC_PHY_INTF_SEL_RMII);
 }
-- 
2.48.1



From ukleinek at kernel.org  Sat Mar  8 16:24:46 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Sun, 9 Mar 2025 01:24:46 +0100
Subject: [PATCH 1/2] dt-bindings: pwm: rockchip: Add rockchip,rk3528-pwm
In-Reply-To: <5942715.DvuYhMxLoT@phil>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <20250307120004.959980-2-amadeus@jmu.edu.cn>
 <pnlkcc2rl7fegltovgtvp4xdxhonw72rclvhn7qmvb7xyuullm@xf5x6lcigji3>
 <5942715.DvuYhMxLoT@phil>
Message-ID: <dit7oqsrs2g5rxor6aakprqw22yyovvcel5tnd2cteydtpt7zg@ndf4cmiamoit>

Hey Heiko,

On Sat, Mar 08, 2025 at 05:25:09PM +0100, Heiko Stuebner wrote:
> Am Freitag, 7. M?rz 2025, 18:07:47 MEZ schrieb Uwe Kleine-K?nig:
> > On Fri, Mar 07, 2025 at 08:00:03PM +0800, Chukun Pan wrote:
> > > Document pwm compatible for rk3528 which is fallback compatible
> > > of rk3328-pwm group.
> > > 
> > > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> > 
> > to prevent binding warnings it's probably sensible to let both patches
> > go in via the same tree at the same time. Feel free to take the binding
> > patch via rockchip/arm-soc.
> > 
> > Acked-by: Uwe Kleine-K?nig <ukleinek at kernel.org>
> 
> You already have the rk3562 binding in your for-next branch [0], which
> could create merge-conflicts later on.

Oh indeed.

> This patch already contains it, so should fit neatly onto your branch.
> 
> And binding warnings only come from linux-next, so won't trigger as the
> pwm will feed the binding there too :-)
> 
> So I guess it might be better to take the binding through the pwm tree
> and me then picking up the dts patch.

Fine for me, so I applied the first patch to

https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/for-next

.

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250309/ed5c084d/attachment.sig>

From lkp at intel.com  Sat Mar  8 19:01:06 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 9 Mar 2025 11:01:06 +0800
Subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
In-Reply-To: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
Message-ID: <202503091011.Kwbj8DQz-lkp@intel.com>

Hi Dmitry,

kernel test robot noticed the following build errors:

[auto build test ERROR on 0a2f889128969dab41861b6e40111aa03dc57014]

url:    https://github.com/intel-lab-lkp/linux/commits/Dmitry-Baryshkov/dt-bindings-display-msm-dp-controller-describe-SAR2130P/20250308-094544
base:   0a2f889128969dab41861b6e40111aa03dc57014
patch link:    https://lore.kernel.org/r/20250308-sar2130p-display-v1-6-1d4c30f43822%40linaro.org
patch subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
config: arm64-randconfig-001-20250309 (https://download.01.org/0day-ci/archive/20250309/202503091011.Kwbj8DQz-lkp at intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250309/202503091011.Kwbj8DQz-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503091011.Kwbj8DQz-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/msm/msm_mdss.c:599:3: error: field designator 'ubwc_static' does not refer to any field in type 'const struct msm_mdss_data'
           .ubwc_static = 1,
            ^
   1 error generated.


vim +599 drivers/gpu/drm/msm/msm_mdss.c

   594	
   595	static const struct msm_mdss_data sar2130p_data = {
   596		.ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */
   597		.ubwc_dec_version = UBWC_4_3,
   598		.ubwc_swizzle = 6,
 > 599		.ubwc_static = 1,
   600		.highest_bank_bit = 0,
   601		.macrotile_mode = 1,
   602		.reg_bus_bw = 74000,
   603	};
   604	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar  8 19:12:14 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 9 Mar 2025 11:12:14 +0800
Subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
In-Reply-To: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-6-1d4c30f43822@linaro.org>
Message-ID: <202503091045.4UVScL8t-lkp@intel.com>

Hi Dmitry,

kernel test robot noticed the following build errors:

[auto build test ERROR on 0a2f889128969dab41861b6e40111aa03dc57014]

url:    https://github.com/intel-lab-lkp/linux/commits/Dmitry-Baryshkov/dt-bindings-display-msm-dp-controller-describe-SAR2130P/20250308-094544
base:   0a2f889128969dab41861b6e40111aa03dc57014
patch link:    https://lore.kernel.org/r/20250308-sar2130p-display-v1-6-1d4c30f43822%40linaro.org
patch subject: [PATCH 06/10] drm/msm/mdss: add SAR2130P device configuration
config: arm-randconfig-004-20250309 (https://download.01.org/0day-ci/archive/20250309/202503091045.4UVScL8t-lkp at intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250309/202503091045.4UVScL8t-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503091045.4UVScL8t-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/msm/msm_mdss.c:599:10: error: 'const struct msm_mdss_data' has no member named 'ubwc_static'
     599 |         .ubwc_static = 1,
         |          ^~~~~~~~~~~
   drivers/gpu/drm/msm/msm_mdss.c:600:29: warning: initialized field overwritten [-Woverride-init]
     600 |         .highest_bank_bit = 0,
         |                             ^
   drivers/gpu/drm/msm/msm_mdss.c:600:29: note: (near initialization for 'sar2130p_data.highest_bank_bit')


vim +599 drivers/gpu/drm/msm/msm_mdss.c

   594	
   595	static const struct msm_mdss_data sar2130p_data = {
   596		.ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */
   597		.ubwc_dec_version = UBWC_4_3,
   598		.ubwc_swizzle = 6,
 > 599		.ubwc_static = 1,
   600		.highest_bank_bit = 0,
   601		.macrotile_mode = 1,
   602		.reg_bus_bw = 74000,
   603	};
   604	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From ankur.a.arora at oracle.com  Sat Mar  8 19:26:16 2025
From: ankur.a.arora at oracle.com (Ankur Arora)
Date: Sat, 08 Mar 2025 19:26:16 -0800
Subject: [PATCH 1/4] asm-generic: barrier: Add
 smp_cond_load_relaxed_timewait()
In-Reply-To: <Z8dRalfxYcJIcLGj@arm.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-2-ankur.a.arora@oracle.com>
 <Z8dRalfxYcJIcLGj@arm.com>
Message-ID: <874j02rijr.fsf@oracle.com>


Catalin Marinas <catalin.marinas at arm.com> writes:

> On Mon, Feb 03, 2025 at 01:49:08PM -0800, Ankur Arora wrote:
>> Add smp_cond_load_relaxed_timewait(), a timed variant of
>> smp_cond_load_relaxed(). This is useful for cases where we want to
>> wait on a conditional variable but don't want to wait indefinitely.

[ ... ]

> What I don't particularly like about this interface is (1) no idea of
> what time granularity it offers, how much it can slip past the deadline,
> even though there's some nanoseconds implied and (2) time_expr_ns leaves
> the caller to figure out why time function to use for tracking the time.
> Well, I can be ok with (2) if we make it a bit more generic.

So I thought about it some more, and on (1), I still feel that a too
specific value of granularity might not be ideal:

Consider that in cpuidle_poll_time() gives 110us, and we derive a
minimum granularity argument of 100us from that.

On arm64, with an event stream period of 100us, that might mean that we
spend part of the time taking the WFE path, and the remaining in the
cpu_relax() portion.

Now, depending on how this call aligns with the event-stream, this
this might mean we spend anywhere from say 100us to 10us in WFE and
10us to 100us in the cpu_relax() loop.

At least for the poll_idle() power consumption, this seems bad.

If, however, the granularity did not depend on an actual time value,
but just a representation of what the caller can tolerate (as I argue
in the other mail), then poll_idle() could just specify granularity=coarse
and we would always take the WFE path.

But, maybe you were thinking of other cases where a integer value
of granularity might be useful?

[...]
> We could add a slack range argument like the
> delta_ns for some of the hrtimer API and let the arch code decide
> whether to honour it.

If there are cases like that, then a slack range could serve both
purposes with slack tolerant cases like idle/resilient spilocks
specifying a large value and more constrained users specifying a
lower value.

However, I don't see how arch code can choose not to honour this.


Thanks

--
ankur


From ziyao at disroot.org  Sat Mar  8 21:53:43 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:43 +0000
Subject: [PATCH v3 1/6] dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-2-ziyao@disroot.org>

Add RK3528 compatible string for SD/SDIO interface.

Signed-off-by: Yao Zi <ziyao at disroot.org>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
index 06df1269f247..ea0feb733e32 100644
--- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
@@ -38,6 +38,7 @@ properties:
               - rockchip,rk3328-dw-mshc
               - rockchip,rk3368-dw-mshc
               - rockchip,rk3399-dw-mshc
+              - rockchip,rk3528-dw-mshc
               - rockchip,rk3568-dw-mshc
               - rockchip,rk3588-dw-mshc
               - rockchip,rv1108-dw-mshc
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:44 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:44 +0000
Subject: [PATCH v3 2/6] dt-bindings: clock: Add GRF clock definition for RK3528
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-3-ziyao@disroot.org>

These clocks are for SD/SDIO tuning purpose and come with registers
in GRF syscon.

Signed-off-by: Yao Zi <ziyao at disroot.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 include/dt-bindings/clock/rockchip,rk3528-cru.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h
index 55a448f5ed6d..0245a53fc334 100644
--- a/include/dt-bindings/clock/rockchip,rk3528-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h
@@ -414,6 +414,12 @@
 #define MCLK_I2S2_2CH_SAI_SRC_PRE	402
 #define MCLK_I2S3_8CH_SAI_SRC_PRE	403
 #define MCLK_SDPDIF_SRC_PRE		404
+#define SCLK_SDMMC_DRV			405
+#define SCLK_SDMMC_SAMPLE		406
+#define SCLK_SDIO0_DRV			407
+#define SCLK_SDIO0_SAMPLE		408
+#define SCLK_SDIO1_DRV			409
+#define SCLK_SDIO1_SAMPLE		410
 
 /* scmi-clocks indices */
 #define SCMI_PCLK_KEYREADER		0
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:45 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:45 +0000
Subject: [PATCH v3 3/6] clk: rockchip: Support MMC clocks in GRF region
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-4-ziyao@disroot.org>

Registers of MMC drive/sample clocks in Rockchip RV1106 and RK3528
locate in GRF regions. Adjust MMC clock code to support register
operations through regmap. Also add a helper to ease registration of GRF
clocks.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-mmc-phase.c | 24 +++++++++++++---
 drivers/clk/rockchip/clk.c           | 42 ++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h           | 20 ++++++++++++-
 3 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 91012078681b..b3ed8e7523e5 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -9,11 +9,14 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	struct regmap	*grf;
+	int		grf_reg;
 	int		shift;
 	int		cached_phase;
 	struct notifier_block clk_rate_change_nb;
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
 	if (!rate)
 		return 0;
 
-	raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
+	if (mmc_clock->grf)
+		regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
+	else
+		raw_value = readl(mmc_clock->reg);
+
+	raw_value >>= mmc_clock->shift;
 
 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
 
@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
 	raw_value |= nineties;
-	writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
-	       mmc_clock->reg);
+	raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
+
+	if (mmc_clock->grf)
+		regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
+	else
+		writel(raw_value, mmc_clock->reg);
 
 	pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
 		clk_hw_get_name(hw), degrees, delay_num,
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift)
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift)
 {
 	struct clk_init_data init;
 	struct rockchip_mmc_clock *mmc_clock;
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 
 	mmc_clock->hw.init = &init;
 	mmc_clock->reg = reg;
+	mmc_clock->grf = grf;
+	mmc_clock->grf_reg = grf_reg;
 	mmc_clock->shift = shift;
 
 	clk = clk_register(NULL, &mmc_clock->hw);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index cbf93ea119a9..ce2f3323d84e 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -590,6 +590,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 				list->name,
 				list->parent_names, list->num_parents,
 				ctx->reg_base + list->muxdiv_offset,
+				NULL, 0,
 				list->div_shift
 			);
 			break;
@@ -619,6 +620,11 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
 			break;
 		case branch_linked_gate:
 			/* must be registered late, fall-through for error message */
+		case branch_mmc_grf:
+			/*
+			 * must be registered through rockchip_clk_register_grf_branches,
+			 * fall-through for error message
+			 */
 			break;
 		}
 
@@ -665,6 +671,42 @@ void rockchip_clk_register_late_branches(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(rockchip_clk_register_late_branches);
 
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk)
+{
+	unsigned int idx;
+	struct clk *clk;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = NULL;
+
+		switch (list->branch_type) {
+		case branch_mmc_grf:
+			clk = rockchip_clk_register_mmc(
+				list->name,
+				list->parent_names, list->num_parents,
+				NULL,
+				grf, list->muxdiv_offset,
+				list->div_shift
+			);
+			break;
+		default:
+			pr_err("%s: unknown clock type %d\n",
+			       __func__, list->branch_type);
+			break;
+		}
+
+		if (!clk)
+			pr_err("%s: failed to register clock %s: %ld\n",
+			       __func__, list->name, PTR_ERR(clk));
+		else
+			rockchip_clk_set_lookup(ctx, clk, list->id);
+	}
+}
+EXPORT_SYMBOL_GPL(rockchip_clk_register_grf_branches);
+
 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
 				  unsigned int lookup_id,
 				  const char *name, const char *const *parent_names,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index df2b2d706450..ec86ba1dd38c 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -594,7 +594,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
-				void __iomem *reg, int shift);
+				void __iomem *reg,
+				struct regmap *grf, int grf_reg,
+				int shift);
 
 /*
  * DDRCLK flags, including method of setting the rate
@@ -633,6 +635,7 @@ enum rockchip_clk_branch_type {
 	branch_gate,
 	branch_linked_gate,
 	branch_mmc,
+	branch_mmc_grf,
 	branch_inverter,
 	branch_factor,
 	branch_ddrclk,
@@ -983,6 +986,17 @@ struct rockchip_clk_branch {
 		.div_shift	= shift,			\
 	}
 
+#define MMC_GRF(_id, cname, pname, offset, shift)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_mmc_grf,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.muxdiv_offset	= offset,			\
+		.div_shift	= shift,			\
+	}
+
 #define INVERTER(_id, cname, pname, io, is, if)			\
 	{							\
 		.id		= _id,				\
@@ -1132,6 +1146,10 @@ void rockchip_clk_register_late_branches(struct device *dev,
 					 struct rockchip_clk_provider *ctx,
 					 struct rockchip_clk_branch *list,
 					 unsigned int nr_clk);
+void rockchip_clk_register_grf_branches(struct rockchip_clk_provider *ctx,
+					struct rockchip_clk_branch *list,
+					struct regmap *grf,
+					unsigned int nr_clk);
 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
 				struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:46 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:46 +0000
Subject: [PATCH v3 4/6] clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-5-ziyao@disroot.org>

These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
tuning purpose. Add their definitions and register them in driver if
corresponding GRF is available.

GRFs are looked up by compatible to simplify devicetree binding.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 drivers/clk/rockchip/clk-rk3528.c | 61 ++++++++++++++++++++++++++++---
 drivers/clk/rockchip/clk.h        |  3 ++
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3528.c b/drivers/clk/rockchip/clk-rk3528.c
index b8b577b902a0..5c133a642ff9 100644
--- a/drivers/clk/rockchip/clk-rk3528.c
+++ b/drivers/clk/rockchip/clk-rk3528.c
@@ -10,6 +10,8 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/minmax.h>
 
 #include <dt-bindings/clock/rockchip,rk3528-cru.h>
 
@@ -1061,23 +1063,64 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = {
 			0, 1, 1),
 };
 
+static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(0), 1),
+	MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0",
+			RK3528_SDMMC_CON(1), 1),
+};
+
+static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = {
+	MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(0), 1),
+	MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0",
+			RK3528_SDIO0_CON(1), 1),
+	MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(0), 1),
+	MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1",
+			RK3528_SDIO1_CON(1), 1),
+};
+
 static int __init clk_rk3528_probe(struct platform_device *pdev)
 {
-	struct rockchip_clk_provider *ctx;
+	unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
+	unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
+	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
+	unsigned long nr_clks, nr_vo_clks, nr_vpu_clks;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
-	unsigned long nr_clks;
+	struct rockchip_clk_provider *ctx;
+	struct regmap *vo_grf, *vpu_grf;
 	void __iomem *reg_base;
 
-	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
-					       nr_branches) + 1;
-
 	reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(reg_base))
 		return dev_err_probe(dev, PTR_ERR(reg_base),
 				     "could not map cru region");
 
+	nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
+					       nr_branches) + 1;
+
+	vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
+	if (!IS_ERR(vo_grf)) {
+		nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
+							  nr_vo_branches) + 1;
+		nr_clks = max(nr_clks, nr_vo_clks);
+	} else if (PTR_ERR(vo_grf) != -ENODEV) {
+		return dev_err_probe(dev, PTR_ERR(vo_grf),
+				     "failed to look up VO GRF\n");
+	}
+
+	vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
+	if (!IS_ERR(vpu_grf)) {
+		nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
+							   nr_vpu_branches) + 1;
+		nr_clks = max(nr_clks, nr_vpu_clks);
+	} else if (PTR_ERR(vpu_grf) != -ENODEV) {
+		return dev_err_probe(dev, PTR_ERR(vpu_grf),
+				     "failed to look up VPU GRF\n");
+	}
+
 	ctx = rockchip_clk_init(np, reg_base, nr_clks);
 	if (IS_ERR(ctx))
 		return dev_err_probe(dev, PTR_ERR(ctx),
@@ -1091,6 +1134,12 @@ static int __init clk_rk3528_probe(struct platform_device *pdev)
 				     &rk3528_cpuclk_data, rk3528_cpuclk_rates,
 				     ARRAY_SIZE(rk3528_cpuclk_rates));
 	rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches);
+	if (!IS_ERR(vo_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vo_clk_branches,
+						   vo_grf, nr_vo_branches);
+	if (!IS_ERR(vpu_grf))
+		rockchip_clk_register_grf_branches(ctx, rk3528_vpu_clk_branches,
+						   vpu_grf, nr_vpu_branches);
 
 	rk3528_rst_init(np, reg_base);
 
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index ec86ba1dd38c..f07cd1bb8952 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -217,6 +217,9 @@ struct clk;
 #define RK3528_CLKSEL_CON(x)		((x) * 0x4 + 0x300)
 #define RK3528_CLKGATE_CON(x)		((x) * 0x4 + 0x800)
 #define RK3528_SOFTRST_CON(x)		((x) * 0x4 + 0xa00)
+#define RK3528_SDMMC_CON(x)		((x) * 0x4 + 0x24)
+#define RK3528_SDIO0_CON(x)		((x) * 0x4 + 0x4)
+#define RK3528_SDIO1_CON(x)		((x) * 0x4 + 0xc)
 #define RK3528_PMU_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE)
 #define RK3528_PMU_CLKGATE_CON(x)	((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE)
 #define RK3528_PCIE_CLKSEL_CON(x)	((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE)
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:47 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:47 +0000
Subject: [PATCH v3 5/6] arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-6-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller, describe
them in devicetree. Since their sample and drive clocks are located in
the VO and VPU GRFs, corresponding syscons are added to make these
clocks available.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 69 ++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index c2eaa0c6ea90..04ca2e2b3e9b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -321,6 +321,16 @@ qos_vpu: qos at ff280400 {
 			reg = <0x0 0xff280400 0x0 0x20>;
 		};
 
+		vpu_grf: syscon at ff340000 {
+			compatible = "rockchip,rk3528-vpu-grf", "syscon";
+			reg = <0x0 0xff340000 0x0 0x8000>;
+		};
+
+		vo_grf: syscon at ff360000 {
+			compatible = "rockchip,rk3528-vo-grf", "syscon";
+			reg = <0x0 0xff360000 0x0 0x10000>;
+		};
+
 		cru: clock-controller at ff4a0000 {
 			compatible = "rockchip,rk3528-cru";
 			reg = <0x0 0xff4a0000 0x0 0x30000>;
@@ -468,6 +478,65 @@ saradc: adc at ffae0000 {
 			status = "disabled";
 		};
 
+		sdio0: mmc at ffc10000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc10000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO0>,
+				 <&cru CCLK_SRC_SDIO0>,
+				 <&cru SCLK_SDIO0_DRV>,
+				 <&cru SCLK_SDIO0_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <200000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdio0_bus4>, <&sdio0_clk>, <&sdio0_cmd>;
+			resets = <&cru SRST_H_SDIO0>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdio1: mmc at ffc20000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc20000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDIO1>,
+				 <&cru CCLK_SRC_SDIO1>,
+				 <&cru SCLK_SDIO1_DRV>,
+				 <&cru SCLK_SDIO1_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <200000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdio1_bus4>, <&sdio1_clk>, <&sdio1_cmd>;
+			resets = <&cru SRST_H_SDIO1>;
+			reset-names = "reset";
+			status = "disabled";
+		};
+
+		sdmmc: mmc at ffc30000 {
+			compatible = "rockchip,rk3528-dw-mshc",
+				     "rockchip,rk3288-dw-mshc";
+			reg = <0x0 0xffc30000 0x0 0x4000>;
+			clocks = <&cru HCLK_SDMMC0>,
+				 <&cru CCLK_SRC_SDMMC0>,
+				 <&cru SCLK_SDMMC_DRV>,
+				 <&cru SCLK_SDMMC_SAMPLE>;
+			clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdmmc_bus4>, <&sdmmc_clk>, <&sdmmc_cmd>,
+				    <&sdmmc_det>;
+			resets = <&cru SRST_H_SDMMC0>;
+			reset-names = "reset";
+			rockchip,default-sample-phase = <90>;
+			status = "disabled";
+		};
+
 		pinctrl: pinctrl {
 			compatible = "rockchip,rk3528-pinctrl";
 			rockchip,grf = <&ioc_grf>;
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:42 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:42 +0000
Subject: [PATCH v3 0/6] Support SD/SDIO controllers on RK3528
Message-ID: <20250309055348.9299-1-ziyao@disroot.org>

RK3528 features two SDIO controllers and one SD/MMC controller. This
series adds essential support for their tuning clocks, document the
controller in dt-bindings and bring the SD/MMC one up on Radxa E20C
board. Both HS and SDR104 mode are verified.

- Changed from v2
  - Apply review tags
  - Rebase on top of linux-rockchip/for-next and drop applied patches
  - RK3528 devicetree
    - Fix accidentally dropped status property of saradc node
    - drop det and pwren pinctrls for SDIO{0,1} according to the
      reference design
    - Correct max-frequency for SDIO{0,1}
  - rk3528-radxa-e20c devicetree
    - Don't disable sdio for sdmmc as claimed in the hw design guide
  - Link to v2: https://lore.kernel.org/all/20250305194217.47052-1-ziyao at disroot.org/
- Changed from v1
  - Apply review tags
  - Rebase on top of linux-rockchip/for-next and saradc v2 series
  - rk3528 clock driver:
    - explicitly include minmax.h, replace MAX() with more robust max()
    - readability improvements
    - fix error checks: ERR_PTR(-ENODEV), instead of ERR_PTR(ENODEV), is
      returned when syscon_regmap_lookup_by_compatible() fails for missing
      such syscon
  - RK3528 devicetree
    - Add default pinctrl
    - Move the per-SoC property, rockchip,default-sample-phase, into the
      SoC devicetree
  - rk3528-radxa-e20c devicetree
    - Assign sdcard to mmc1
    - Add missing regulators
    - Apply no-sdio for the sdmmc controller
    - Sort nodes
  - Link to v1: https://lore.kernel.org/all/20250301104250.36295-1-ziyao at disroot.org/

Thanks for your time and review.

Yao Zi (6):
  dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528
  dt-bindings: clock: Add GRF clock definition for RK3528
  clk: rockchip: Support MMC clocks in GRF region
  clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region
  arm64: dts: rockchip: Add SDMMC/SDIO controllers for RK3528
  arm64: dts: rockchip: Enable SD-card interface on Radxa E20C

 .../bindings/mmc/rockchip-dw-mshc.yaml        |  1 +
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 33 +++++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 69 +++++++++++++++++++
 drivers/clk/rockchip/clk-mmc-phase.c          | 24 +++++--
 drivers/clk/rockchip/clk-rk3528.c             | 61 ++++++++++++++--
 drivers/clk/rockchip/clk.c                    | 42 +++++++++++
 drivers/clk/rockchip/clk.h                    | 23 ++++++-
 .../dt-bindings/clock/rockchip,rk3528-cru.h   |  6 ++
 8 files changed, 248 insertions(+), 11 deletions(-)

-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 21:53:48 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 05:53:48 +0000
Subject: [PATCH v3 6/6] arm64: dts: rockchip: Enable SD-card interface on Radxa E20C
In-Reply-To: <20250309055348.9299-1-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org>
Message-ID: <20250309055348.9299-7-ziyao@disroot.org>

SD-card is available on Radxa E20C board.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 5346ef457c2a..b74e605a5a82 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -15,6 +15,10 @@ / {
 	model = "Radxa E20C";
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
+	aliases {
+		mmc1 = &sdmmc;
+	};
+
 	chosen {
 		stdout-path = "serial0:1500000n8";
 	};
@@ -104,6 +108,18 @@ vcc5v0_sys: regulator-5v0-vcc-sys {
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
 	};
+
+	vccio_sd: regulator-vccio-sd {
+		compatible = "regulator-gpio";
+		gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_vol_ctrl_h>;
+		regulator-name = "vccio_sd";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		states = <1800000 0x0>, <3300000 0x1>;
+		vin-supply = <&vcc5v0_sys>;
+	};
 };
 
 &pinctrl {
@@ -126,6 +142,12 @@ wan_led_g: wan-led-g {
 			rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
+
+	sdmmc {
+		sdmmc_vol_ctrl_h: sdmmc-vol-ctrl-h {
+			rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
 };
 
 &saradc {
@@ -133,6 +155,17 @@ &saradc {
 	status = "okay";
 };
 
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0m0_xfer>;
-- 
2.48.1



From naoki at radxa.com  Sat Mar  8 22:35:46 2025
From: naoki at radxa.com (FUKAUMI Naoki)
Date: Sun, 9 Mar 2025 15:35:46 +0900
Subject: [PATCH 6/6] arm64: dts: rockchip: Enable DisplayPort for rk3588s
 Cool Pi 4B
In-Reply-To: <20250223113036.74252-7-andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-7-andyshrk@163.com>
Message-ID: <3605ABCB7EF60115+2de06a28-1b3d-4a0e-b960-9e0a74c6e19d@radxa.com>

Hi Andy,

On 2/23/25 20:30, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Enable the Mini DisplayPort on this board.
> Note that ROCKCHIP_VOP2_EP_DP0 is defined as 10 in dt-binding header,
> but it will trigger a dtc warning like "graph node unit address error,
> expected "a"" if we use it directly after endpoint, so we use "a"
> instead here.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
>   .../boot/dts/rockchip/rk3588s-coolpi-4b.dts   | 37 +++++++++++++++++++
>   1 file changed, 37 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
> index e892dd7c91aa..0f58eb56557f 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
> @@ -39,6 +39,18 @@ chosen {
>   		stdout-path = "serial2:1500000n8";
>   	};
>   
> +	dp-con {
> +		compatible = "dp-connector";
> +		label = "DP OUT";
> +		type = "mini";
> +
> +		port {
> +			dp_con_in: endpoint {
> +				remote-endpoint = <&dp0_out_con>;
> +			};
> +		};
> +	};
> +
>   	hdmi-con {
>   		compatible = "hdmi-connector";
>   		type = "d";
> @@ -220,6 +232,24 @@ &gpu {
>   	status = "okay";
>   };
>   
> +&dp0 {
> +	status = "okay";
> +	pinctrl-0 = <&dp0m0_pins>;
> +	pinctrl-names = "default";
> +};
> +
> +&dp0_in {
> +	dp0_in_vp2: endpoint {
> +		remote-endpoint = <&vp2_out_dp0>;
> +	};
> +};
> +
> +&dp0_out {
> +	dp0_out_con: endpoint {
> +		remote-endpoint = <&dp_con_in>;
> +	};
> +};
> +

These three nodes should be placed above the &gpu node.

Best regards,

--
FUKAUMI Naoki
Radxa Computer (Shenzhen) Co., Ltd.

>   &hdmi0 {
>   	status = "okay";
>   };
> @@ -889,3 +919,10 @@ vp0_out_hdmi0: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
>   		remote-endpoint = <&hdmi0_in_vp0>;
>   	};
>   };
> +
> +&vp2 {
> +	vp2_out_dp0: endpoint at a {
> +		reg = <ROCKCHIP_VOP2_EP_DP0>;
> +		remote-endpoint = <&dp0_in_vp2>;
> +	};
> +};



From jernej.skrabec at gmail.com  Sat Mar  8 22:38:04 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:38:04 +0100
Subject: [PATCH v4 02/14] clk: sunxi-ng: mp: provide wrappers for setting feature
 flags
In-Reply-To: <20250307002628.10684-3-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-3-andre.przywara@arm.com>
Message-ID: <5865232.DvuYhMxLoT@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:16 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> So far our sunxi clock instantiation macros set the required clock
> features depending on the clock type, but the new "dual divider MP
> clock" requires us to pass that piece of information in by the user.
> 
> Add new wrapper macros that allow to specify a "features" field, to
> allow marking those dual-divider clocks accordingly. Also add two
> convenience macros that deal with the most common cases.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 22:43:38 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:43:38 +0100
Subject: [PATCH v4 05/14] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
In-Reply-To: <20250307002628.10684-6-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-6-andre.przywara@arm.com>
Message-ID: <4633243.LvFx2qVVIh@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:19 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the PLL clocks of the main CCU of the Allwinner A523 and T527 SoCs.
> The clocks were modelled after the A523 and T527 manual, and double
> checked by writing all 1's into the respective register, to spot all
> implemented bits.
> 
> The PLL and mod clocks for the two CPU clusters and the DSU are part of
> a separate CCU, also most audio clocks are collected in a DSP CCU, so
> both of these clock groups are missing from this driver.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From yuehaibing at huawei.com  Sat Mar  8 23:07:23 2025
From: yuehaibing at huawei.com (Yue Haibing)
Date: Sun, 9 Mar 2025 15:07:23 +0800
Subject: [PATCH -next] arm64/fpsimd: Remove unused declaration fpsimd_kvm_prepare()
Message-ID: <20250309070723.1390958-1-yuehaibing@huawei.com>

Commit fbc7e61195e2 ("KVM: arm64: Unconditionally save+flush host
FPSIMD/SVE/SME state") removed the implementation but leave declaration.

Signed-off-by: Yue Haibing <yuehaibing at huawei.com>
---
 arch/arm64/include/asm/fpsimd.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index f2a84efc3618..564bc09b3e06 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -80,7 +80,6 @@ extern void fpsimd_signal_preserve_current_state(void);
 extern void fpsimd_preserve_current_state(void);
 extern void fpsimd_restore_current_state(void);
 extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
-extern void fpsimd_kvm_prepare(void);
 
 struct cpu_fp_state {
 	struct user_fpsimd_state *st;
-- 
2.34.1



From jernej.skrabec at gmail.com  Sat Mar  8 22:57:47 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:57:47 +0100
Subject: [PATCH v4 12/14] clk: sunxi-ng: a523: add bus clock gates
In-Reply-To: <20250307002628.10684-13-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-13-andre.przywara@arm.com>
Message-ID: <10620511.nUPlyArG6x@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:26 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the various bus clock gates that control access to the devices'
> register interface.
> These clocks are each just one bit, typically the lower bits in some "BGR"
> (Bus Gate / Reset) registers, for each device group: one for all UARTs,
> one for all SPI interfaces, and so on.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 22:49:36 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:49:36 +0100
Subject: [PATCH v4 07/14] clk: sunxi-ng: a523: add video mod clocks
In-Reply-To: <20250307002628.10684-8-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-8-andre.przywara@arm.com>
Message-ID: <4963134.GXAFRqVoOG@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:21 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the clocks driving the various video subsystems of the SoC: the "DE"
> display engine, the "DI" deinterlacer, the "G2D" 2D graphics system, the
> Mali "GPU", the "VE" video engine, its associated IOMMU, as well as the
> clocks for the various video output drivers (HDMI, DP, LCDs).
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 22:50:50 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:50:50 +0100
Subject: [PATCH v4 08/14] clk: sunxi-ng: a523: add system mod clocks
In-Reply-To: <20250307002628.10684-9-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-9-andre.przywara@arm.com>
Message-ID: <2214425.irdbgypaU6@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:22 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the clocks driving some core system related subsystems of the SoC:
> the "CE" crypto engine, the high speed timers, the DRAM and the associated
> MBUS clock, and the PCIe clock.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From naoki at radxa.com  Sat Mar  8 22:51:24 2025
From: naoki at radxa.com (FUKAUMI Naoki)
Date: Sun, 9 Mar 2025 15:51:24 +0900
Subject: [PATCH 2/6] drm/bridge: synopsys: Add DW DPTX Controller support
 library
In-Reply-To: <20250223113036.74252-3-andyshrk@163.com>
References: <20250223113036.74252-1-andyshrk@163.com>
 <20250223113036.74252-3-andyshrk@163.com>
Message-ID: <4F8F58DC9699ED12+95e301f9-a9f1-4f6b-8b8f-21c6c1df5cc2@radxa.com>

Hi Andy,

On 2/23/25 20:30, Andy Yan wrote:
(snip)
> +struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> +			 const struct dw_dp_plat_data *plat_data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct dw_dp *dp;
> +	struct drm_bridge *bridge;
> +	void __iomem *res;
> +	int ret;
> +
> +	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
> +	if (!dp)
> +		return ERR_PTR(-ENOMEM);
> +
> +	dp->dev = dev;
> +	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
> +
> +	dp->plat_data = plat_data;
> +	bridge = &dp->bridge;
> +	mutex_init(&dp->irq_lock);
> +	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
> +	init_completion(&dp->complete);
> +
> +	res = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(res))
> +		return ERR_CAST(res);
> +
> +	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
> +	if (IS_ERR(dp->regmap)) {
> +		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
> +		return ERR_CAST(dp->regmap);
> +	}
> +
> +	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
> +	if (IS_ERR(dp->phy)) {
> +		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
> +		return ERR_CAST(dp->phy);
> +	}
> +
> +	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
> +	if (IS_ERR(dp->apb_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
> +		return ERR_CAST(dp->apb_clk);
> +	}
> +
> +	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
> +	if (IS_ERR(dp->aux_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
> +		return ERR_CAST(dp->aux_clk);
> +	}
> +
> +	dp->i2s_clk = devm_clk_get(dev, "i2s");
> +	if (IS_ERR(dp->i2s_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
> +		return ERR_CAST(dp->i2s_clk);
> +	}
> +
> +	dp->spdif_clk = devm_clk_get(dev, "spdif");
> +	if (IS_ERR(dp->spdif_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
> +		return ERR_CAST(dp->spdif_clk);
> +	}
> +
> +	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
> +	if (IS_ERR(dp->hdcp_clk)) {
> +		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
> +		return ERR_CAST(dp->hdcp_clk);
> +	}
> +
> +	dp->rstc = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(dp->rstc)) {
> +		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
> +		return ERR_CAST(dp->rstc);
> +	}
> +
> +	dp->irq = platform_get_irq(pdev, 0);
> +	if (dp->irq < 0)
> +		return ERR_PTR(ret);
> +
> +	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
> +					IRQF_ONESHOT, dev_name(dev), dp);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "failed to request irq\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	bridge->of_node = dev->of_node;
> +	bridge->funcs = &dw_dp_bridge_funcs;
> +	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> +	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
> +	bridge->ycbcr_420_allowed = true;
> +	bridge->vendor = "Synopsys";
> +	bridge->product = "DW DP TX";
> +
> +	platform_set_drvdata(pdev, dp);
> +
> +	dp->aux.dev = dev;
> +	dp->aux.drm_dev = encoder->dev;
> +	dp->aux.name = dev_name(dev);
> +	dp->aux.transfer = dw_dp_aux_transfer;
> +	ret = drm_dp_aux_register(&dp->aux);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "Aux register failed\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		dev_err_probe(dev, ret, "Failed to attach bridge\n");
> +
> +	dw_dp_init_hw(dp);
> +
> +	return dp;
> +}

EXPORT_SYMBOL_GPL(dw_dp_bind);

is required to build it as a module.

Best regards,

--
FUKAUMI Naoki
Radxa Computer (Shenzhen) Co., Ltd.


From jernej.skrabec at gmail.com  Sat Mar  8 22:53:05 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:53:05 +0100
Subject: [PATCH v4 09/14] clk: sunxi-ng: a523: add interface mod clocks
In-Reply-To: <20250307002628.10684-10-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-10-andre.przywara@arm.com>
Message-ID: <2978516.e9J7NaK4W3@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:23 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the clocks driving what the user manual summarises under "interface"
> devices: raw NAND flash, MMC, SPI, EMAC, "IR" infrared, and the "GPADC"
> general purpose analogue/digital converter.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 22:54:44 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 07:54:44 +0100
Subject: [PATCH v4 11/14] clk: sunxi-ng: a523: remaining mod clocks
In-Reply-To: <20250307002628.10684-12-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-12-andre.przywara@arm.com>
Message-ID: <3344204.44csPzL39Z@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:25 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Add the remaining mod clocks, driving various parts of the SoC: the "LEDC"
> LED controller, the "CSI" camera interface, the "ISP" image processor,
> the DSP clock, and the "fanout" clocks, which allow to put clock signals
> on external pins.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 23:00:20 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 08:00:20 +0100
Subject: [PATCH v4 13/14] clk: sunxi-ng: a523: add reset lines
In-Reply-To: <20250307002628.10684-14-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-14-andre.przywara@arm.com>
Message-ID: <1994155.PYKUYFuaPT@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:27 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> Allwinner SoCs do not contain a separate reset controller, instead the
> reset lines for the various devices are integrated into the "BGR" (Bus
> Gate / Reset) registers, for each device group: one for all UARTs, one
> for all SPI interfaces, and so on.
> The Allwinner CCU driver also doubles as a reset provider, and since the
> reset lines are indeed just single bits in those BGR register, we can
> represent them easily in an array of structs, just containing the
> register offset and the bit number.
> 
> Add the location of the reset bits for all devices in the A523/T527
> SoCs, using the existing sunxi CCU infrastructure.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From jernej.skrabec at gmail.com  Sat Mar  8 23:03:38 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sun, 09 Mar 2025 08:03:38 +0100
Subject: [PATCH v4 14/14] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
In-Reply-To: <20250307002628.10684-15-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-15-andre.przywara@arm.com>
Message-ID: <7776158.EvYhyI6sBW@jernej-laptop>

Dne petek, 7. marec 2025 ob 01:26:28 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The A523/T527 SoCs have clock/reset controls in the PRCM part, like many
> previous SoCs. For a change, the whole PRCM is documented in the A523
> manual, including the system bus tree, so we can describe all those
> clocks correctly based on that. There layout seems to be derived from
> the H6 and H616 PRCM CCUs, though there are more clocks, and many clocks
> have subtly changed.
> 
> Describe all the mod and gate clocks, including the three bus clocks
> (R_AHB, R_APB0, and R_APB1).
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From ziyao at disroot.org  Sat Mar  8 23:06:01 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 07:06:01 +0000
Subject: [PATCH 1/3] dt-bindings: i2c: i2c-rk3x: Add compatible string for RK3528
In-Reply-To: <20250309070603.35254-1-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
Message-ID: <20250309070603.35254-2-ziyao@disroot.org>

Document I2C controllers integrated in RK3528, which are compatible with
the RK3399 variant.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
index a9dae5b52f28..259770b1aa08 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
@@ -37,6 +37,7 @@ properties:
               - rockchip,px30-i2c
               - rockchip,rk3308-i2c
               - rockchip,rk3328-i2c
+              - rockchip,rk3528-i2c
               - rockchip,rk3568-i2c
               - rockchip,rk3576-i2c
               - rockchip,rk3588-i2c
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 23:06:03 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 07:06:03 +0000
Subject: [PATCH 3/3] arm64: dts: rockchip: Add onboard EEPROM for Radxa E20C
In-Reply-To: <20250309070603.35254-1-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
Message-ID: <20250309070603.35254-4-ziyao@disroot.org>

Radxa E20C ships an onboard I2C EEPROM for storing production
information. Enable it in devicetree.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index b74e605a5a82..ddcf690eb513 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -122,6 +122,19 @@ vccio_sd: regulator-vccio-sd {
 	};
 };
 
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1m0_xfer>;
+	status = "okay";
+
+	eeprom at 50 {
+		compatible = "belling,bl24c16a", "atmel,24c16";
+		reg = <0x50>;
+		pagesize = <16>;
+		vcc-supply = <&vcc_3v3>;
+	};
+};
+
 &pinctrl {
 	gpio-keys {
 		user_key: user-key {
-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 23:06:00 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 07:06:00 +0000
Subject: [PATCH 0/3] Support I2C controllers in RK3528
Message-ID: <20250309070603.35254-1-ziyao@disroot.org>

RK3528 integrates eight I2C controllers which are compatible with the
RK3399 variant of i2c-rk3x. This series documents the controllers in
dt-bindings, describe them in SoC devicetree and enable the onboard
EEPROM of Radxa E20C which is connected to the second I2C controller.

This series is based on linux-rockchip/for-next and may depend on the
v3 of SD/SDIO series for a clean apply[1].

[1]: https://lore.kernel.org/all/20250309055348.9299-1-ziyao at disroot.org/

Yao Zi (3):
  dt-bindings: i2c: i2c-rk3x: Add compatible string for RK3528
  arm64: dts: rockchip: Add I2C controllers for RK3528
  arm64: dts: rockchip: Add onboard EEPROM for Radxa E20C

 .../devicetree/bindings/i2c/i2c-rk3x.yaml     |   1 +
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   |  13 +++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 104 ++++++++++++++++++
 3 files changed, 118 insertions(+)

-- 
2.48.1



From ziyao at disroot.org  Sat Mar  8 23:06:02 2025
From: ziyao at disroot.org (Yao Zi)
Date: Sun,  9 Mar 2025 07:06:02 +0000
Subject: [PATCH 2/3] arm64: dts: rockchip: Add I2C controllers for RK3528
In-Reply-To: <20250309070603.35254-1-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
Message-ID: <20250309070603.35254-3-ziyao@disroot.org>

Describe I2C controllers shipped by RK3528 in devicetree.

Signed-off-by: Yao Zi <ziyao at disroot.org>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 104 +++++++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 04ca2e2b3e9b..860b6057e5c2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -19,6 +19,14 @@ / {
 	#size-cells = <2>;
 
 	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
 		gpio0 = &gpio0;
 		gpio1 = &gpio1;
 		gpio2 = &gpio2;
@@ -466,6 +474,102 @@ uart7: serial at ffa28000 {
 			status = "disabled";
 		};
 
+		i2c0: i2c at ffa50000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa50000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c at ffa58000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa58000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c2: i2c at ffa60000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa60000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c3: i2c at ffa68000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa68000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c4: i2c at ffa70000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa70000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c5: i2c at ffa78000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa78000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c6: i2c at ffa80000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa80000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C6>, <&cru PCLK_I2C6>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c7: i2c at ffa88000 {
+			compatible = "rockchip,rk3528-i2c",
+				     "rockchip,rk3399-i2c";
+			reg = <0x0 0xffa88000 0x0 0x1000>;
+			clocks = <&cru CLK_I2C7>, <&cru PCLK_I2C7>;
+			clock-names = "i2c", "pclk";
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		saradc: adc at ffae0000 {
 			compatible = "rockchip,rk3528-saradc";
 			reg = <0x0 0xffae0000 0x0 0x10000>;
-- 
2.48.1



From amadeus at jmu.edu.cn  Sun Mar  9 00:00:25 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Sun,  9 Mar 2025 16:00:25 +0800
Subject: [PATCH 2/3] arm64: dts: rockchip: Add I2C controllers for RK3528
In-Reply-To: <20250309070603.35254-3-ziyao@disroot.org>
References: <20250309070603.35254-3-ziyao@disroot.org>
Message-ID: <20250309080025.15825-1-amadeus@jmu.edu.cn>

Hi,

> +		i2c0: i2c at ffa50000 {
> +			compatible = "rockchip,rk3528-i2c",
> +				     "rockchip,rk3399-i2c";
> +			reg = <0x0 0xffa50000 0x0 0x1000>;
> +			clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
> +			clock-names = "i2c", "pclk";
> +			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;

It would be better to add default pinctrl for all i2c nodes
using m0 group. (Only 1 group of pinctrl for i2c4 and i2c7)

Thanks,
Chukun

-- 
2.25.1



From pbonzini at redhat.com  Sun Mar  9 00:11:13 2025
From: pbonzini at redhat.com (Paolo Bonzini)
Date: Sun, 9 Mar 2025 09:11:13 +0100
Subject: [GIT PULL] KVM/arm64 fixes for 6.14, take #4
In-Reply-To: <20250307161824.2373079-1-maz@kernel.org>
References: <20250307161824.2373079-1-maz@kernel.org>
Message-ID: <CABgObfaZQsPLvyYsuFzYJOwgEaJ40=yZ+TS29Lt_xZyT9oSKpg@mail.gmail.com>

On Fri, Mar 7, 2025 at 5:18?PM Marc Zyngier <maz at kernel.org> wrote:
>
> Paolo,
>
> Here's what I hope to be the last set of 6.14 fixes for
> KVM/arm64. This time, two patches addressing the two side of the same
> bug, where pKVM's PSCI relay wasn't correctly setting up the CPUs when
> in the hVHE mode. Thanks to Ahmed and Mark for fixing it.
>
> Please pull,

Done, thanks.

Paolo

>         M.
>
> The following changes since commit fa808ed4e199ed17d878eb75b110bda30dd52434:
>
>   KVM: arm64: Ensure a VMID is allocated before programming VTTBR_EL2 (2025-02-20 16:29:28 +0000)
>
> are available in the Git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvmarm-fixes-6.14-4
>
> for you to fetch changes up to 3855a7b91d42ebf3513b7ccffc44807274978b3d:
>
>   KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu() (2025-03-02 08:36:52 +0000)
>
> ----------------------------------------------------------------
> KVM/arm64 fixes for 6.14, take #4
>
> - Fix a couple of bugs affecting pKVM's PSCI relay implementation
>   when running in the hVHE mode, resulting in the host being entered
>   with the MMU in an unknown state, and EL2 being in the wrong mode.
>
> ----------------------------------------------------------------
> Ahmed Genidi (1):
>       KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu()
>
> Mark Rutland (1):
>       KVM: arm64: Initialize HCR_EL2.E2H early
>
>  arch/arm64/include/asm/el2_setup.h   | 31 ++++++++++++++++++++++++++-----
>  arch/arm64/kernel/head.S             | 22 +++-------------------
>  arch/arm64/kvm/hyp/nvhe/hyp-init.S   | 10 +++++++---
>  arch/arm64/kvm/hyp/nvhe/psci-relay.c |  3 +++
>  4 files changed, 39 insertions(+), 27 deletions(-)
>



From demonsingur at gmail.com  Sun Mar  9 00:48:07 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:07 +0200
Subject: [RFC PATCH v2 15/16] media: i2c: remove MAX96717 driver
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-16-demonsingur@gmail.com>

The previous MAX96717 driver has been removed and its functionality has
been moved to a MAX96717 driver which makes use of the Maxim GMSL2/3
serializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                  |    1 -
 drivers/media/i2c/Kconfig    |   17 -
 drivers/media/i2c/Makefile   |    1 -
 drivers/media/i2c/max96717.c | 1103 ----------------------------------
 4 files changed, 1122 deletions(-)
 delete mode 100644 drivers/media/i2c/max96717.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4d1ff8cf537b..e9fe6e9856d8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14203,7 +14203,6 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
-F:	drivers/media/i2c/max96717.c
 
 MAX9860 MONO AUDIO VOICE CODEC DRIVER
 M:	Peter Rosin <peda at axentia.se>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index e24c84962c92..6c595dffb280 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1636,23 +1636,6 @@ config VIDEO_MAX96714
 	  To compile this driver as a module, choose M here: the
 	  module will be called max96714.
 
-config VIDEO_MAX96717
-	tristate "Maxim MAX96717 GMSL2 Serializer support"
-	depends on OF && I2C && VIDEO_DEV && COMMON_CLK
-	select I2C_MUX
-	select MEDIA_CONTROLLER
-	select GPIOLIB
-	select V4L2_CCI_I2C
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	help
-	  Device driver for the Maxim MAX96717 GMSL2 Serializer.
-	  MAX96717 serializers convert video on a MIPI CSI-2
-	  input to a GMSL2 output.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96717.
-
 source "drivers/media/i2c/maxim-serdes/Kconfig"
 
 endmenu
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index b24e7cf7bb2f..de0680ebf190 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_VIDEO_M52790) += m52790.o
 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
 obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
-obj-$(CONFIG_VIDEO_MAX96717) += max96717.o
 obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/
 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
diff --git a/drivers/media/i2c/max96717.c b/drivers/media/i2c/max96717.c
deleted file mode 100644
index 9259d58ba734..000000000000
--- a/drivers/media/i2c/max96717.c
+++ /dev/null
@@ -1,1103 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim GMSL2 Serializer Driver
- *
- * Copyright (C) 2024 Collabora Ltd.
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/fwnode.h>
-#include <linux/gpio/driver.h>
-#include <linux/i2c-mux.h>
-#include <linux/i2c.h>
-#include <linux/regmap.h>
-
-#include <media/v4l2-cci.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define MAX96717_DEVICE_ID  0xbf
-#define MAX96717F_DEVICE_ID 0xc8
-#define MAX96717_PORTS      2
-#define MAX96717_PAD_SINK   0
-#define MAX96717_PAD_SOURCE 1
-#define MAX96717_CSI_NLANES 4
-
-#define MAX96717_DEFAULT_CLKOUT_RATE	24000000UL
-
-/* DEV */
-#define MAX96717_REG3    CCI_REG8(0x3)
-#define MAX96717_RCLKSEL GENMASK(1, 0)
-#define RCLKSEL_REF_PLL  CCI_REG8(0x3)
-#define MAX96717_REG6    CCI_REG8(0x6)
-#define RCLKEN           BIT(5)
-#define MAX96717_DEV_ID  CCI_REG8(0xd)
-#define MAX96717_DEV_REV CCI_REG8(0xe)
-#define MAX96717_DEV_REV_MASK GENMASK(3, 0)
-
-/* VID_TX Z */
-#define MAX96717_VIDEO_TX0 CCI_REG8(0x110)
-#define MAX96717_VIDEO_AUTO_BPP BIT(3)
-#define MAX96717_VIDEO_TX2 CCI_REG8(0x112)
-#define MAX96717_VIDEO_PCLKDET BIT(7)
-
-/* VTX_Z */
-#define MAX96717_VTX0                  CCI_REG8(0x24e)
-#define MAX96717_VTX1                  CCI_REG8(0x24f)
-#define MAX96717_PATTERN_CLK_FREQ      GENMASK(3, 1)
-#define MAX96717_VTX_VS_DLY            CCI_REG24(0x250)
-#define MAX96717_VTX_VS_HIGH           CCI_REG24(0x253)
-#define MAX96717_VTX_VS_LOW            CCI_REG24(0x256)
-#define MAX96717_VTX_V2H               CCI_REG24(0x259)
-#define MAX96717_VTX_HS_HIGH           CCI_REG16(0x25c)
-#define MAX96717_VTX_HS_LOW            CCI_REG16(0x25e)
-#define MAX96717_VTX_HS_CNT            CCI_REG16(0x260)
-#define MAX96717_VTX_V2D               CCI_REG24(0x262)
-#define MAX96717_VTX_DE_HIGH           CCI_REG16(0x265)
-#define MAX96717_VTX_DE_LOW            CCI_REG16(0x267)
-#define MAX96717_VTX_DE_CNT            CCI_REG16(0x269)
-#define MAX96717_VTX29                 CCI_REG8(0x26b)
-#define MAX96717_VTX_MODE              GENMASK(1, 0)
-#define MAX96717_VTX_GRAD_INC          CCI_REG8(0x26c)
-#define MAX96717_VTX_CHKB_COLOR_A      CCI_REG24(0x26d)
-#define MAX96717_VTX_CHKB_COLOR_B      CCI_REG24(0x270)
-#define MAX96717_VTX_CHKB_RPT_CNT_A    CCI_REG8(0x273)
-#define MAX96717_VTX_CHKB_RPT_CNT_B    CCI_REG8(0x274)
-#define MAX96717_VTX_CHKB_ALT          CCI_REG8(0x275)
-
-/* GPIO */
-#define MAX96717_NUM_GPIO         11
-#define MAX96717_GPIO_REG_A(gpio) CCI_REG8(0x2be + (gpio) * 3)
-#define MAX96717_GPIO_OUT         BIT(4)
-#define MAX96717_GPIO_IN          BIT(3)
-#define MAX96717_GPIO_RX_EN       BIT(2)
-#define MAX96717_GPIO_TX_EN       BIT(1)
-#define MAX96717_GPIO_OUT_DIS     BIT(0)
-
-/* FRONTTOP */
-/* MAX96717 only have CSI port 'B' */
-#define MAX96717_FRONTOP0     CCI_REG8(0x308)
-#define MAX96717_START_PORT_B BIT(5)
-
-/* MIPI_RX */
-#define MAX96717_MIPI_RX1       CCI_REG8(0x331)
-#define MAX96717_MIPI_LANES_CNT GENMASK(5, 4)
-#define MAX96717_MIPI_RX2       CCI_REG8(0x332) /* phy1 Lanes map */
-#define MAX96717_PHY2_LANES_MAP GENMASK(7, 4)
-#define MAX96717_MIPI_RX3       CCI_REG8(0x333) /* phy2 Lanes map */
-#define MAX96717_PHY1_LANES_MAP GENMASK(3, 0)
-#define MAX96717_MIPI_RX4       CCI_REG8(0x334) /* phy1 lane polarities */
-#define MAX96717_PHY1_LANES_POL GENMASK(6, 4)
-#define MAX96717_MIPI_RX5       CCI_REG8(0x335) /* phy2 lane polarities */
-#define MAX96717_PHY2_LANES_POL GENMASK(2, 0)
-
-/* MIPI_RX_EXT */
-#define MAX96717_MIPI_RX_EXT11 CCI_REG8(0x383)
-#define MAX96717_TUN_MODE      BIT(7)
-
-/* REF_VTG */
-#define REF_VTG0                CCI_REG8(0x3f0)
-#define REFGEN_PREDEF_EN        BIT(6)
-#define REFGEN_PREDEF_FREQ_MASK GENMASK(5, 4)
-#define REFGEN_PREDEF_FREQ_ALT  BIT(3)
-#define REFGEN_RST              BIT(1)
-#define REFGEN_EN               BIT(0)
-
-/* MISC */
-#define PIO_SLEW_1 CCI_REG8(0x570)
-
-enum max96717_vpg_mode {
-	MAX96717_VPG_DISABLED = 0,
-	MAX96717_VPG_CHECKERBOARD = 1,
-	MAX96717_VPG_GRADIENT = 2,
-};
-
-struct max96717_priv {
-	struct i2c_client		  *client;
-	struct regmap			  *regmap;
-	struct i2c_mux_core		  *mux;
-	struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
-	struct v4l2_subdev                sd;
-	struct media_pad                  pads[MAX96717_PORTS];
-	struct v4l2_ctrl_handler          ctrl_handler;
-	struct v4l2_async_notifier        notifier;
-	struct v4l2_subdev                *source_sd;
-	u16                               source_sd_pad;
-	u64			          enabled_source_streams;
-	u8                                pll_predef_index;
-	struct clk_hw                     clk_hw;
-	struct gpio_chip                  gpio_chip;
-	enum max96717_vpg_mode            pattern;
-};
-
-static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct max96717_priv, sd);
-}
-
-static inline struct max96717_priv *clk_hw_to_max96717(struct clk_hw *hw)
-{
-	return container_of(hw, struct max96717_priv, clk_hw);
-}
-
-static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
-{
-	return 0;
-}
-
-static int max96717_i2c_mux_init(struct max96717_priv *priv)
-{
-	priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
-				  1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
-				  max96717_i2c_mux_select, NULL);
-	if (!priv->mux)
-		return -ENOMEM;
-
-	return i2c_mux_add_adapter(priv->mux, 0, 0);
-}
-
-static inline int max96717_start_csi(struct max96717_priv *priv, bool start)
-{
-	return cci_update_bits(priv->regmap, MAX96717_FRONTOP0,
-			       MAX96717_START_PORT_B,
-			       start ? MAX96717_START_PORT_B : 0, NULL);
-}
-
-static int max96717_apply_patgen_timing(struct max96717_priv *priv,
-					struct v4l2_subdev_state *state)
-{
-	struct v4l2_mbus_framefmt *fmt =
-		v4l2_subdev_state_get_format(state, MAX96717_PAD_SOURCE);
-	const u32 h_active = fmt->width;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	u32 h_tot;
-	const u32 v_active = fmt->height;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	u32 v_tot;
-	int ret = 0;
-
-	h_tot = h_active + h_fp + h_sw + h_bp;
-	v_tot = v_active + v_fp + v_sw + v_bp;
-
-	/* 75 Mhz pixel clock */
-	cci_update_bits(priv->regmap, MAX96717_VTX1,
-			MAX96717_PATTERN_CLK_FREQ, 0xa, &ret);
-
-	dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height,
-		 fmt->width);
-
-	cci_write(priv->regmap, MAX96717_VTX_VS_DLY, 0, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_VS_HIGH, v_sw * h_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_VS_LOW,
-		  (v_active + v_fp + v_bp) * h_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_HIGH, h_sw, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_LOW, h_active + h_fp + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96717_VTX_V2D,
-		  h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret);
-	cci_write(priv->regmap, MAX96717_VTX_HS_CNT, v_tot, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_HIGH, h_active, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_LOW, h_fp + h_sw + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96717_VTX_DE_CNT, v_active, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_A, 0xfecc00, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_B, 0x006aa7, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_A, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_B, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_CHKB_ALT, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96717_VTX_GRAD_INC, 0x10, &ret);
-
-	return ret;
-}
-
-static int max96717_apply_patgen(struct max96717_priv *priv,
-				 struct v4l2_subdev_state *state)
-{
-	unsigned int val;
-	int ret = 0;
-
-	if (priv->pattern)
-		ret = max96717_apply_patgen_timing(priv, state);
-
-	cci_write(priv->regmap, MAX96717_VTX0, priv->pattern ? 0xfb : 0,
-		  &ret);
-
-	val = FIELD_PREP(MAX96717_VTX_MODE, priv->pattern);
-	cci_update_bits(priv->regmap, MAX96717_VTX29, MAX96717_VTX_MODE,
-			val, &ret);
-	return ret;
-}
-
-static int max96717_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96717_priv *priv =
-		container_of(ctrl->handler, struct max96717_priv, ctrl_handler);
-	int ret;
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		if (priv->enabled_source_streams)
-			return -EBUSY;
-		priv->pattern = ctrl->val;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Use bpp from bpp register */
-	ret = cci_update_bits(priv->regmap, MAX96717_VIDEO_TX0,
-			      MAX96717_VIDEO_AUTO_BPP,
-			      priv->pattern ? 0 : MAX96717_VIDEO_AUTO_BPP,
-			      NULL);
-
-	/*
-	 * Pattern generator doesn't work with tunnel mode.
-	 * Needs RGB color format and deserializer tunnel mode must be disabled.
-	 */
-	return cci_update_bits(priv->regmap, MAX96717_MIPI_RX_EXT11,
-			       MAX96717_TUN_MODE,
-			       priv->pattern ? 0 : MAX96717_TUN_MODE, &ret);
-}
-
-static const char * const max96717_test_pattern[] = {
-	"Disabled",
-	"Checkerboard",
-	"Gradient"
-};
-
-static const struct v4l2_ctrl_ops max96717_ctrl_ops = {
-	.s_ctrl = max96717_s_ctrl,
-};
-
-static int max96717_gpiochip_get(struct gpio_chip *gpiochip,
-				 unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-	u64 val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset),
-		       &val, NULL);
-	if (ret)
-		return ret;
-
-	if (val & MAX96717_GPIO_OUT_DIS)
-		return !!(val & MAX96717_GPIO_IN);
-	else
-		return !!(val & MAX96717_GPIO_OUT);
-}
-
-static void max96717_gpiochip_set(struct gpio_chip *gpiochip,
-				  unsigned int offset, int value)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			MAX96717_GPIO_OUT, MAX96717_GPIO_OUT, NULL);
-}
-
-static int max96717_gpio_get_direction(struct gpio_chip *gpiochip,
-				       unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-	u64 val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), &val, NULL);
-	if (ret < 0)
-		return ret;
-
-	return !!(val & MAX96717_GPIO_OUT_DIS);
-}
-
-static int max96717_gpio_direction_out(struct gpio_chip *gpiochip,
-				       unsigned int offset, int value)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			       MAX96717_GPIO_OUT_DIS | MAX96717_GPIO_OUT,
-			       value ? MAX96717_GPIO_OUT : 0, NULL);
-}
-
-static int max96717_gpio_direction_in(struct gpio_chip *gpiochip,
-				      unsigned int offset)
-{
-	struct max96717_priv *priv = gpiochip_get_data(gpiochip);
-
-	return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
-			       MAX96717_GPIO_OUT_DIS, MAX96717_GPIO_OUT_DIS,
-			       NULL);
-}
-
-static int max96717_gpiochip_probe(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct gpio_chip *gc = &priv->gpio_chip;
-	int i, ret = 0;
-
-	gc->label = dev_name(dev);
-	gc->parent = dev;
-	gc->owner = THIS_MODULE;
-	gc->ngpio = MAX96717_NUM_GPIO;
-	gc->base = -1;
-	gc->can_sleep = true;
-	gc->get_direction = max96717_gpio_get_direction;
-	gc->direction_input = max96717_gpio_direction_in;
-	gc->direction_output = max96717_gpio_direction_out;
-	gc->set = max96717_gpiochip_set;
-	gc->get = max96717_gpiochip_get;
-	gc->of_gpio_n_cells = 2;
-
-	/* Disable GPIO forwarding */
-	for (i = 0; i < gc->ngpio; i++)
-		cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(i),
-				MAX96717_GPIO_RX_EN | MAX96717_GPIO_TX_EN,
-				0, &ret);
-
-	if (ret)
-		return ret;
-
-	ret = devm_gpiochip_add_data(dev, gc, priv);
-	if (ret) {
-		dev_err(dev, "Unable to create gpio_chip\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int _max96717_set_routing(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_state *state,
-				 struct v4l2_subdev_krouting *routing)
-{
-	static const struct v4l2_mbus_framefmt format = {
-		.width = 1280,
-		.height = 1080,
-		.code = MEDIA_BUS_FMT_Y8_1X8,
-		.field = V4L2_FIELD_NONE,
-	};
-	int ret;
-
-	ret = v4l2_subdev_routing_validate(sd, routing,
-					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
-	if (ret)
-		return ret;
-
-	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int max96717_set_routing(struct v4l2_subdev *sd,
-				struct v4l2_subdev_state *state,
-				enum v4l2_subdev_format_whence which,
-				struct v4l2_subdev_krouting *routing)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-
-	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
-		return -EBUSY;
-
-	return _max96717_set_routing(sd, state, routing);
-}
-
-static int max96717_set_fmt(struct v4l2_subdev *sd,
-			    struct v4l2_subdev_state *state,
-			    struct v4l2_subdev_format *format)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	struct v4l2_mbus_framefmt *fmt;
-	u64 stream_source_mask;
-
-	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
-	    priv->enabled_source_streams)
-		return -EBUSY;
-
-	/* No transcoding, source and sink formats must match. */
-	if (format->pad == MAX96717_PAD_SOURCE)
-		return v4l2_subdev_get_fmt(sd, state, format);
-
-	/* Set sink format */
-	fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	/* Propagate to source format */
-	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
-							   format->stream);
-	if (!fmt)
-		return -EINVAL;
-	*fmt = format->format;
-
-	stream_source_mask = BIT(format->stream);
-
-	return v4l2_subdev_state_xlate_streams(state, MAX96717_PAD_SOURCE,
-					       MAX96717_PAD_SINK,
-					       &stream_source_mask);
-}
-
-static int max96717_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	struct v4l2_subdev_route routes[] = {
-		{
-			.sink_pad = MAX96717_PAD_SINK,
-			.sink_stream = 0,
-			.source_pad = MAX96717_PAD_SOURCE,
-			.source_stream = 0,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
-		},
-	};
-	struct v4l2_subdev_krouting routing = {
-		.num_routes = ARRAY_SIZE(routes),
-		.routes = routes,
-	};
-
-	return _max96717_set_routing(sd, state, &routing);
-}
-
-static bool max96717_pipe_pclkdet(struct max96717_priv *priv)
-{
-	u64 val = 0;
-
-	cci_read(priv->regmap, MAX96717_VIDEO_TX2, &val, NULL);
-
-	return val & MAX96717_VIDEO_PCLKDET;
-}
-
-static int max96717_log_status(struct v4l2_subdev *sd)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Serializer: max96717\n");
-	dev_info(dev, "Pipe: pclkdet:%d\n", max96717_pipe_pclkdet(priv));
-
-	return 0;
-}
-
-static int max96717_enable_streams(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_state *state, u32 pad,
-				   u64 streams_mask)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	u64 sink_streams;
-	int ret;
-
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, true);
-
-	ret = max96717_apply_patgen(priv, state);
-	if (ret)
-		goto stop_csi;
-
-	if (!priv->pattern) {
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96717_PAD_SOURCE,
-							MAX96717_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_enable_streams(priv->source_sd,
-						 priv->source_sd_pad,
-						 sink_streams);
-		if (ret)
-			goto stop_csi;
-	}
-
-	priv->enabled_source_streams |= streams_mask;
-
-	return 0;
-
-stop_csi:
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, false);
-
-	return ret;
-}
-
-static int max96717_disable_streams(struct v4l2_subdev *sd,
-				    struct v4l2_subdev_state *state, u32 pad,
-				    u64 streams_mask)
-{
-	struct max96717_priv *priv = sd_to_max96717(sd);
-	u64 sink_streams;
-
-	/*
-	 * Stop the CSI receiver first then the source,
-	 * otherwise the device may become unresponsive
-	 * while holding the I2C bus low.
-	 */
-	priv->enabled_source_streams &= ~streams_mask;
-	if (!priv->enabled_source_streams)
-		max96717_start_csi(priv, false);
-
-	if (!priv->pattern) {
-		int ret;
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96717_PAD_SOURCE,
-							MAX96717_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_disable_streams(priv->source_sd,
-						  priv->source_sd_pad,
-						  sink_streams);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_subdev_pad_ops max96717_pad_ops = {
-	.enable_streams = max96717_enable_streams,
-	.disable_streams = max96717_disable_streams,
-	.set_routing = max96717_set_routing,
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = max96717_set_fmt,
-};
-
-static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = {
-	.log_status = max96717_log_status,
-};
-
-static const struct v4l2_subdev_internal_ops max96717_internal_ops = {
-	.init_state = max96717_init_state,
-};
-
-static const struct v4l2_subdev_ops max96717_subdev_ops = {
-	.core = &max96717_subdev_core_ops,
-	.pad = &max96717_pad_ops,
-};
-
-static const struct media_entity_operations max96717_entity_ops = {
-	.link_validate = v4l2_subdev_link_validate,
-};
-
-static int max96717_notify_bound(struct v4l2_async_notifier *notifier,
-				 struct v4l2_subdev *source_subdev,
-				 struct v4l2_async_connection *asd)
-{
-	struct max96717_priv *priv = sd_to_max96717(notifier->sd);
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	ret = media_entity_get_fwnode_pad(&source_subdev->entity,
-					  source_subdev->fwnode,
-					  MEDIA_PAD_FL_SOURCE);
-	if (ret < 0) {
-		dev_err(dev, "Failed to find pad for %s\n",
-			source_subdev->name);
-		return ret;
-	}
-
-	priv->source_sd = source_subdev;
-	priv->source_sd_pad = ret;
-
-	ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
-				    &priv->sd.entity, 0,
-				    MEDIA_LNK_FL_ENABLED |
-				    MEDIA_LNK_FL_IMMUTABLE);
-	if (ret) {
-		dev_err(dev, "Unable to link %s:%u -> %s:0\n",
-			source_subdev->name, priv->source_sd_pad,
-			priv->sd.name);
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_async_notifier_operations max96717_notify_ops = {
-	.bound = max96717_notify_bound,
-};
-
-static int max96717_v4l2_notifier_register(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_async_connection *asd;
-	struct fwnode_handle *ep_fwnode;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96717_PAD_SINK, 0, 0);
-	if (!ep_fwnode) {
-		dev_err(dev, "No graph endpoint\n");
-		return -ENODEV;
-	}
-
-	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
-
-	asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
-					      struct v4l2_async_connection);
-
-	fwnode_handle_put(ep_fwnode);
-
-	if (IS_ERR(asd)) {
-		dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return PTR_ERR(asd);
-	}
-
-	priv->notifier.ops = &max96717_notify_ops;
-
-	ret = v4l2_async_nf_register(&priv->notifier);
-	if (ret) {
-		dev_err(dev, "Failed to register subdev_notifier");
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max96717_subdev_init(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96717_subdev_ops);
-	priv->sd.internal_ops = &max96717_internal_ops;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler,
-				     &max96717_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96717_test_pattern) - 1,
-				     0, 0, max96717_test_pattern);
-	if (priv->ctrl_handler.error) {
-		ret = priv->ctrl_handler.error;
-		goto err_free_ctrl;
-	}
-
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-	priv->sd.entity.ops = &max96717_entity_ops;
-
-	priv->pads[MAX96717_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-
-	ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
-	if (ret) {
-		dev_err_probe(dev, ret, "Failed to init pads\n");
-		goto err_free_ctrl;
-	}
-
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret) {
-		dev_err_probe(dev, ret,
-			      "v4l2 subdev init finalized failed\n");
-		goto err_entity_cleanup;
-	}
-	ret = max96717_v4l2_notifier_register(priv);
-	if (ret) {
-		dev_err_probe(dev, ret,
-			      "v4l2 subdev notifier register failed\n");
-		goto err_free_state;
-	}
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret) {
-		dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
-		goto err_unreg_notif;
-	}
-
-	return 0;
-
-err_unreg_notif:
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-err_free_state:
-	v4l2_subdev_cleanup(&priv->sd);
-err_entity_cleanup:
-	media_entity_cleanup(&priv->sd.entity);
-err_free_ctrl:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-}
-
-static void max96717_subdev_uninit(struct max96717_priv *priv)
-{
-	v4l2_async_unregister_subdev(&priv->sd);
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-	v4l2_subdev_cleanup(&priv->sd);
-	media_entity_cleanup(&priv->sd.entity);
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-}
-
-struct max96717_pll_predef_freq {
-	unsigned long freq;
-	bool is_alt;
-	u8 val;
-};
-
-static const struct max96717_pll_predef_freq max96717_predef_freqs[] = {
-	{ 13500000, true,  0 }, { 19200000, false, 0 },
-	{ 24000000, true,  1 }, { 27000000, false, 1 },
-	{ 37125000, false, 2 }, { 74250000, false, 3 },
-};
-
-static unsigned long
-max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	return max96717_predef_freqs[priv->pll_predef_index].freq;
-}
-
-static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv,
-						 unsigned long rate)
-{
-	unsigned int i, idx = 0;
-	unsigned long diff_new, diff_old = U32_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) {
-		diff_new = abs(rate - max96717_predef_freqs[i].freq);
-		if (diff_new < diff_old) {
-			diff_old = diff_new;
-			idx = i;
-		}
-	}
-
-	return idx;
-}
-
-static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				    unsigned long *parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-	struct device *dev = &priv->client->dev;
-	unsigned int idx;
-
-	idx = max96717_clk_find_best_index(priv, rate);
-
-	if (rate != max96717_predef_freqs[idx].freq) {
-		dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n",
-			 rate, max96717_predef_freqs[idx].freq);
-	}
-
-	return max96717_predef_freqs[idx].freq;
-}
-
-static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-				 unsigned long parent_rate)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-	unsigned int val, idx;
-	int ret = 0;
-
-	idx = max96717_clk_find_best_index(priv, rate);
-
-	val = FIELD_PREP(REFGEN_PREDEF_FREQ_MASK,
-			 max96717_predef_freqs[idx].val);
-
-	if (max96717_predef_freqs[idx].is_alt)
-		val |= REFGEN_PREDEF_FREQ_ALT;
-
-	val |= REFGEN_RST | REFGEN_PREDEF_EN;
-
-	cci_write(priv->regmap, REF_VTG0, val, &ret);
-	cci_update_bits(priv->regmap, REF_VTG0, REFGEN_RST | REFGEN_EN,
-			REFGEN_EN, &ret);
-	if (ret)
-		return ret;
-
-	priv->pll_predef_index = idx;
-
-	return 0;
-}
-
-static int max96717_clk_prepare(struct clk_hw *hw)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	return cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN,
-			       RCLKEN, NULL);
-}
-
-static void max96717_clk_unprepare(struct clk_hw *hw)
-{
-	struct max96717_priv *priv = clk_hw_to_max96717(hw);
-
-	cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, 0, NULL);
-}
-
-static const struct clk_ops max96717_clk_ops = {
-	.prepare     = max96717_clk_prepare,
-	.unprepare   = max96717_clk_unprepare,
-	.set_rate    = max96717_clk_set_rate,
-	.recalc_rate = max96717_clk_recalc_rate,
-	.round_rate  = max96717_clk_round_rate,
-};
-
-static int max96717_register_clkout(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct clk_init_data init = { .ops = &max96717_clk_ops };
-	int ret;
-
-	init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out", dev_name(dev));
-	if (!init.name)
-		return -ENOMEM;
-
-	/* RCLKSEL Reference PLL output */
-	ret = cci_update_bits(priv->regmap, MAX96717_REG3, MAX96717_RCLKSEL,
-			      MAX96717_RCLKSEL, NULL);
-	/* MFP4 fastest slew rate */
-	cci_update_bits(priv->regmap, PIO_SLEW_1, BIT(5) | BIT(4), 0, &ret);
-	if (ret)
-		goto free_init_name;
-
-	priv->clk_hw.init = &init;
-
-	/* Initialize to 24 MHz */
-	ret = max96717_clk_set_rate(&priv->clk_hw,
-				    MAX96717_DEFAULT_CLKOUT_RATE, 0);
-	if (ret < 0)
-		goto free_init_name;
-
-	ret = devm_clk_hw_register(dev, &priv->clk_hw);
-	kfree(init.name);
-	if (ret)
-		return dev_err_probe(dev, ret, "Cannot register clock HW\n");
-
-	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
-					  &priv->clk_hw);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Cannot add OF clock provider\n");
-
-	return 0;
-
-free_init_name:
-	kfree(init.name);
-	return ret;
-}
-
-static int max96717_init_csi_lanes(struct max96717_priv *priv)
-{
-	struct v4l2_mbus_config_mipi_csi2 *mipi = &priv->mipi_csi2;
-	unsigned long lanes_used = 0;
-	unsigned int nlanes, lane, val = 0;
-	int ret;
-
-	nlanes = mipi->num_data_lanes;
-
-	ret = cci_update_bits(priv->regmap, MAX96717_MIPI_RX1,
-			      MAX96717_MIPI_LANES_CNT,
-			      FIELD_PREP(MAX96717_MIPI_LANES_CNT,
-					 nlanes - 1), NULL);
-
-	/* lanes polarity */
-	for (lane = 0; lane < nlanes + 1; lane++) {
-		if (!mipi->lane_polarities[lane])
-			continue;
-		/* Clock lane */
-		if (lane == 0)
-			val |= BIT(2);
-		else if (lane < 3)
-			val |= BIT(lane - 1);
-		else
-			val |= BIT(lane);
-	}
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX5,
-			MAX96717_PHY2_LANES_POL,
-			FIELD_PREP(MAX96717_PHY2_LANES_POL, val), &ret);
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX4,
-			MAX96717_PHY1_LANES_POL,
-			FIELD_PREP(MAX96717_PHY1_LANES_POL,
-				   val >> 3), &ret);
-	/* lanes mapping */
-	for (lane = 0, val = 0; lane < nlanes; lane++) {
-		val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
-		lanes_used |= BIT(mipi->data_lanes[lane] - 1);
-	}
-
-	/*
-	 * Unused lanes need to be mapped as well to not have
-	 * the same lanes mapped twice.
-	 */
-	for (; lane < MAX96717_CSI_NLANES; lane++) {
-		unsigned int idx = find_first_zero_bit(&lanes_used,
-						       MAX96717_CSI_NLANES);
-
-		val |= idx << (lane * 2);
-		lanes_used |= BIT(idx);
-	}
-
-	cci_update_bits(priv->regmap, MAX96717_MIPI_RX3,
-			MAX96717_PHY1_LANES_MAP,
-			FIELD_PREP(MAX96717_PHY1_LANES_MAP, val), &ret);
-
-	return cci_update_bits(priv->regmap, MAX96717_MIPI_RX2,
-			       MAX96717_PHY2_LANES_MAP,
-			       FIELD_PREP(MAX96717_PHY2_LANES_MAP, val >> 4),
-			       &ret);
-}
-
-static int max96717_hw_init(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 dev_id, val;
-	int ret;
-
-	ret = cci_read(priv->regmap, MAX96717_DEV_ID, &dev_id, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read the device id\n");
-
-	if (dev_id != MAX96717_DEVICE_ID && dev_id != MAX96717F_DEVICE_ID)
-		return dev_err_probe(dev, -EOPNOTSUPP,
-				     "Unsupported device id got %x\n", (u8)dev_id);
-
-	ret = cci_read(priv->regmap, MAX96717_DEV_REV, &val, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read device revision");
-
-	dev_dbg(dev, "Found %x (rev %lx)\n", (u8)dev_id,
-		(u8)val & MAX96717_DEV_REV_MASK);
-
-	ret = cci_read(priv->regmap, MAX96717_MIPI_RX_EXT11, &val, NULL);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Fail to read mipi rx extension");
-
-	if (!(val & MAX96717_TUN_MODE))
-		return dev_err_probe(dev, -EOPNOTSUPP,
-				     "Only supporting tunnel mode");
-
-	return max96717_init_csi_lanes(priv);
-}
-
-static int max96717_parse_dt(struct max96717_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
-	struct fwnode_handle *ep_fwnode;
-	unsigned char num_data_lanes;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96717_PAD_SINK, 0, 0);
-	if (!ep_fwnode)
-		return dev_err_probe(dev, -ENOENT, "no endpoint found\n");
-
-	ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
-
-	fwnode_handle_put(ep_fwnode);
-
-	if (ret < 0)
-		return dev_err_probe(dev, ret, "Failed to parse sink endpoint");
-
-	num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
-	if (num_data_lanes < 1 || num_data_lanes > MAX96717_CSI_NLANES)
-		return dev_err_probe(dev, -EINVAL,
-				     "Invalid data lanes must be 1 to 4\n");
-
-	priv->mipi_csi2 = vep.bus.mipi_csi2;
-
-	return 0;
-}
-
-static int max96717_probe(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-	struct max96717_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->client = client;
-	priv->regmap = devm_cci_regmap_init_i2c(client, 16);
-	if (IS_ERR(priv->regmap)) {
-		ret = PTR_ERR(priv->regmap);
-		return dev_err_probe(dev, ret, "Failed to init regmap\n");
-	}
-
-	ret = max96717_parse_dt(priv);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to parse the dt\n");
-
-	ret = max96717_hw_init(priv);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Failed to initialize the hardware\n");
-
-	ret = max96717_gpiochip_probe(priv);
-	if (ret)
-		return dev_err_probe(&client->dev, ret,
-				     "Failed to init gpiochip\n");
-
-	ret = max96717_register_clkout(priv);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to register clkout\n");
-
-	ret = max96717_subdev_init(priv);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "Failed to initialize v4l2 subdev\n");
-
-	ret = max96717_i2c_mux_init(priv);
-	if (ret) {
-		dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
-		max96717_subdev_uninit(priv);
-	}
-
-	return ret;
-}
-
-static void max96717_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96717_priv *priv = sd_to_max96717(sd);
-
-	max96717_subdev_uninit(priv);
-	i2c_mux_del_adapters(priv->mux);
-}
-
-static const struct of_device_id max96717_of_ids[] = {
-	{ .compatible = "maxim,max96717f" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, max96717_of_ids);
-
-static struct i2c_driver max96717_i2c_driver = {
-	.driver	= {
-		.name		= "max96717",
-		.of_match_table	= max96717_of_ids,
-	},
-	.probe		= max96717_probe,
-	.remove		= max96717_remove,
-};
-
-module_i2c_driver(max96717_i2c_driver);
-
-MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver");
-MODULE_AUTHOR("Julien Massot <julien.massot at collabora.com>");
-MODULE_LICENSE("GPL");
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:08 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:08 +0200
Subject: [RFC PATCH v2 16/16] media: i2c: remove MAX96714 driver
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-17-demonsingur@gmail.com>

The previous MAX96714 driver has been removed and its functionality has
been moved to the MAX9296A driver which makes use of the Maxim GMSL2/3
serializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                  |    1 -
 drivers/media/i2c/Kconfig    |   17 -
 drivers/media/i2c/Makefile   |    1 -
 drivers/media/i2c/max96714.c | 1024 ----------------------------------
 4 files changed, 1043 deletions(-)
 delete mode 100644 drivers/media/i2c/max96714.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e9fe6e9856d8..395de7a7da92 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14194,7 +14194,6 @@ M:	Julien Massot <julien.massot at collabora.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
-F:	drivers/media/i2c/max96714.c
 
 MAX96717 GMSL2 SERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 6c595dffb280..aa0a67b7da47 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1619,23 +1619,6 @@ config VIDEO_DS90UB960
 	  Device driver for the Texas Instruments DS90UB960
 	  FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
 
-config VIDEO_MAX96714
-	tristate "Maxim MAX96714 GMSL2 deserializer"
-	depends on OF && I2C && VIDEO_DEV
-	select I2C_MUX
-	select MEDIA_CONTROLLER
-	select GPIOLIB
-	select V4L2_CCI_I2C
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	help
-	  Device driver for the Maxim MAX96714 GMSL2 Deserializer.
-	  MAX96714 deserializers convert a GMSL2 input to MIPI CSI-2
-	  output.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96714.
-
 source "drivers/media/i2c/maxim-serdes/Kconfig"
 
 endmenu
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index de0680ebf190..065e728f54ce 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_VIDEO_LT6911UXE) += lt6911uxe.o
 obj-$(CONFIG_VIDEO_M52790) += m52790.o
 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
-obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
 obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/
 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
diff --git a/drivers/media/i2c/max96714.c b/drivers/media/i2c/max96714.c
deleted file mode 100644
index 159753b13777..000000000000
--- a/drivers/media/i2c/max96714.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim GMSL2 Deserializer Driver
- *
- * Copyright (C) 2024 Collabora Ltd.
- */
-
-#include <linux/bitfield.h>
-#include <linux/bitops.h>
-#include <linux/fwnode.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/i2c-mux.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-#include <media/v4l2-cci.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define MAX96714_DEVICE_ID  0xc9
-#define MAX96714F_DEVICE_ID 0xca
-#define MAX96714_NPORTS     2
-#define MAX96714_PAD_SINK   0
-#define MAX96714_PAD_SOURCE 1
-#define MAX96714_CSI_NLANES 4
-
-/* DEV */
-#define MAX96714_REG13                 CCI_REG8(0x0d)
-#define MAX96714_DEV_REV               CCI_REG8(0x0e)
-#define MAX96714_DEV_REV_MASK          GENMASK(3, 0)
-#define MAX96714_LINK_LOCK             CCI_REG8(0x13)
-#define MAX96714_LINK_LOCK_BIT         BIT(3)
-#define MAX96714_IO_CHK0               CCI_REG8(0x38)
-#define MAX96714_PATTERN_CLK_FREQ      GENMASK(1, 0)
-/* VID_RX */
-#define MAX96714_VIDEO_RX8             CCI_REG8(0x11a)
-#define MAX96714_VID_LOCK              BIT(6)
-
-/* VRX_PATGEN_0 */
-#define MAX96714_PATGEN_0              CCI_REG8(0x240)
-#define MAX96714_PATGEN_1              CCI_REG8(0x241)
-#define MAX96714_PATGEN_MODE           GENMASK(5, 4)
-#define MAX96714_PATGEN_VS_DLY         CCI_REG24(0x242)
-#define MAX96714_PATGEN_VS_HIGH        CCI_REG24(0x245)
-#define MAX96714_PATGEN_VS_LOW         CCI_REG24(0x248)
-#define MAX96714_PATGEN_V2H            CCI_REG24(0x24b)
-#define MAX96714_PATGEN_HS_HIGH        CCI_REG16(0x24e)
-#define MAX96714_PATGEN_HS_LOW         CCI_REG16(0x250)
-#define MAX96714_PATGEN_HS_CNT         CCI_REG16(0x252)
-#define MAX96714_PATGEN_V2D            CCI_REG24(0x254)
-#define MAX96714_PATGEN_DE_HIGH        CCI_REG16(0x257)
-#define MAX96714_PATGEN_DE_LOW         CCI_REG16(0x259)
-#define MAX96714_PATGEN_DE_CNT         CCI_REG16(0x25b)
-#define MAX96714_PATGEN_GRAD_INC       CCI_REG8(0x25d)
-#define MAX96714_PATGEN_CHKB_COLOR_A   CCI_REG24(0x25e)
-#define MAX96714_PATGEN_CHKB_COLOR_B   CCI_REG24(0x261)
-#define MAX96714_PATGEN_CHKB_RPT_CNT_A CCI_REG8(0x264)
-#define MAX96714_PATGEN_CHKB_RPT_CNT_B CCI_REG8(0x265)
-#define MAX96714_PATGEN_CHKB_ALT       CCI_REG8(0x266)
-/* BACKTOP */
-#define MAX96714_BACKTOP25             CCI_REG8(0x320)
-#define CSI_DPLL_FREQ_MASK             GENMASK(4, 0)
-
-/* MIPI_PHY */
-#define MAX96714_MIPI_PHY0             CCI_REG8(0x330)
-#define MAX96714_FORCE_CSI_OUT         BIT(7)
-#define MAX96714_MIPI_STDBY_N          CCI_REG8(0x332)
-#define MAX96714_MIPI_STDBY_MASK       GENMASK(5, 4)
-#define MAX96714_MIPI_LANE_MAP         CCI_REG8(0x333)
-#define MAX96714_MIPI_POLARITY         CCI_REG8(0x335)
-#define MAX96714_MIPI_POLARITY_MASK    GENMASK(5, 0)
-
-/* MIPI_TX */
-#define MAX96714_MIPI_LANE_CNT         CCI_REG8(0x44a)
-#define MAX96714_CSI2_LANE_CNT_MASK    GENMASK(7, 6)
-#define MAX96714_MIPI_TX52             CCI_REG8(0x474)
-#define MAX96714_TUN_EN                BIT(0)
-
-#define MHZ(v) ((u32)((v)  * 1000000U))
-
-enum max96714_vpg_mode {
-	MAX96714_VPG_DISABLED = 0,
-	MAX96714_VPG_CHECKERBOARD = 1,
-	MAX96714_VPG_GRADIENT = 2,
-};
-
-struct max96714_rxport {
-	struct {
-		struct v4l2_subdev   *sd;
-		u16                  pad;
-		struct fwnode_handle *ep_fwnode;
-	} source;
-	struct regulator	     *poc;
-};
-
-struct max96714_txport {
-	struct v4l2_fwnode_endpoint vep;
-};
-
-struct max96714_priv {
-	struct i2c_client                 *client;
-	struct regmap                     *regmap;
-	struct gpio_desc                  *pd_gpio;
-	struct max96714_rxport            rxport;
-	struct i2c_mux_core               *mux;
-	u64                               enabled_source_streams;
-	struct v4l2_subdev		  sd;
-	struct media_pad		  pads[MAX96714_NPORTS];
-	struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
-	struct v4l2_ctrl_handler          ctrl_handler;
-	struct v4l2_async_notifier        notifier;
-	s64                               tx_link_freq;
-	enum max96714_vpg_mode            pattern;
-};
-
-static inline struct max96714_priv *sd_to_max96714(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct max96714_priv, sd);
-}
-
-static int max96714_enable_tx_port(struct max96714_priv *priv)
-{
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
-			       MAX96714_MIPI_STDBY_MASK,
-			       MAX96714_MIPI_STDBY_MASK, NULL);
-}
-
-static int max96714_disable_tx_port(struct max96714_priv *priv)
-{
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
-			       MAX96714_MIPI_STDBY_MASK, 0, NULL);
-}
-
-static bool max96714_tx_port_enabled(struct max96714_priv *priv)
-{
-	u64 val;
-
-	cci_read(priv->regmap, MAX96714_MIPI_STDBY_N, &val, NULL);
-
-	return val & MAX96714_MIPI_STDBY_MASK;
-}
-
-static int max96714_apply_patgen_timing(struct max96714_priv *priv,
-					struct v4l2_subdev_state *state)
-{
-	struct v4l2_mbus_framefmt *fmt =
-		v4l2_subdev_state_get_format(state, MAX96714_PAD_SOURCE);
-	const u32 h_active = fmt->width;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	u32 h_tot;
-	const u32 v_active = fmt->height;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	u32 v_tot;
-	int ret = 0;
-
-	h_tot = h_active + h_fp + h_sw + h_bp;
-	v_tot = v_active + v_fp + v_sw + v_bp;
-
-	/* 75 Mhz pixel clock */
-	cci_update_bits(priv->regmap, MAX96714_IO_CHK0,
-			MAX96714_PATTERN_CLK_FREQ, 1, &ret);
-
-	dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height,
-		 fmt->width);
-
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_DLY, 0, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_HIGH, v_sw * h_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_VS_LOW,
-		  (v_active + v_fp + v_bp) * h_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_HIGH, h_sw, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_LOW, h_active + h_fp + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_V2D,
-		  h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_HS_CNT, v_tot, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_HIGH, h_active, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_LOW, h_fp + h_sw + h_bp,
-		  &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_DE_CNT, v_active, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_A, 0xfecc00, &ret);
-	/* B G R */
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_B, 0x006aa7, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_A, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_B, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_CHKB_ALT, 0x3c, &ret);
-	cci_write(priv->regmap, MAX96714_PATGEN_GRAD_INC, 0x10, &ret);
-
-	return ret;
-}
-
-static int max96714_apply_patgen(struct max96714_priv *priv,
-				 struct v4l2_subdev_state *state)
-{
-	unsigned int val;
-	int ret = 0;
-
-	if (priv->pattern)
-		ret = max96714_apply_patgen_timing(priv, state);
-
-	cci_write(priv->regmap, MAX96714_PATGEN_0, priv->pattern ? 0xfb : 0,
-		  &ret);
-
-	val = FIELD_PREP(MAX96714_PATGEN_MODE, priv->pattern);
-	cci_update_bits(priv->regmap, MAX96714_PATGEN_1, MAX96714_PATGEN_MODE,
-			val, &ret);
-	return ret;
-}
-
-static int max96714_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96714_priv *priv =
-		container_of(ctrl->handler, struct max96714_priv, ctrl_handler);
-	int ret;
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		if (priv->enabled_source_streams)
-			return -EBUSY;
-		priv->pattern = ctrl->val;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	ret = cci_update_bits(priv->regmap, MAX96714_MIPI_PHY0,
-			      MAX96714_FORCE_CSI_OUT,
-			      priv->pattern ? MAX96714_FORCE_CSI_OUT : 0, NULL);
-
-	/* Pattern generator doesn't work with tunnel mode */
-	return cci_update_bits(priv->regmap, MAX96714_MIPI_TX52,
-			       MAX96714_TUN_EN,
-			       priv->pattern ? 0 : MAX96714_TUN_EN, &ret);
-}
-
-static const char * const max96714_test_pattern[] = {
-	"Disabled",
-	"Checkerboard",
-	"Gradient"
-};
-
-static const struct v4l2_ctrl_ops max96714_ctrl_ops = {
-	.s_ctrl = max96714_s_ctrl,
-};
-
-static int max96714_enable_streams(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_state *state,
-				   u32 source_pad, u64 streams_mask)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	u64 sink_streams;
-	int ret;
-
-	if (!priv->enabled_source_streams)
-		max96714_enable_tx_port(priv);
-
-	ret = max96714_apply_patgen(priv, state);
-	if (ret)
-		goto err;
-
-	if (!priv->pattern) {
-		if (!priv->rxport.source.sd) {
-			ret = -ENODEV;
-			goto err;
-		}
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96714_PAD_SOURCE,
-							MAX96714_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_enable_streams(priv->rxport.source.sd,
-						 priv->rxport.source.pad,
-						 sink_streams);
-		if (ret)
-			goto err;
-	}
-
-	priv->enabled_source_streams |= streams_mask;
-
-	return 0;
-
-err:
-	if (!priv->enabled_source_streams)
-		max96714_disable_tx_port(priv);
-
-	return ret;
-}
-
-static int max96714_disable_streams(struct v4l2_subdev *sd,
-				    struct v4l2_subdev_state *state,
-				    u32 source_pad, u64 streams_mask)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	u64 sink_streams;
-
-	if (!priv->pattern) {
-		int ret;
-
-		sink_streams =
-			v4l2_subdev_state_xlate_streams(state,
-							MAX96714_PAD_SOURCE,
-							MAX96714_PAD_SINK,
-							&streams_mask);
-
-		ret = v4l2_subdev_disable_streams(priv->rxport.source.sd,
-						  priv->rxport.source.pad,
-						  sink_streams);
-		if (ret)
-			return ret;
-	}
-
-	priv->enabled_source_streams &= ~streams_mask;
-
-	if (!priv->enabled_source_streams)
-		max96714_disable_tx_port(priv);
-
-	return 0;
-}
-
-static int max96714_set_fmt(struct v4l2_subdev *sd,
-			    struct v4l2_subdev_state *state,
-			    struct v4l2_subdev_format *format)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	struct v4l2_mbus_framefmt *fmt;
-
-	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
-	    priv->enabled_source_streams)
-		return -EBUSY;
-
-	/* No transcoding, source and sink formats must match. */
-	if (format->pad == MAX96714_PAD_SOURCE)
-		return v4l2_subdev_get_fmt(sd, state, format);
-
-	fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
-							   format->stream);
-	if (!fmt)
-		return -EINVAL;
-
-	*fmt = format->format;
-
-	return 0;
-}
-
-static int _max96714_set_routing(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_state *state,
-				 enum v4l2_subdev_format_whence which,
-				 struct v4l2_subdev_krouting *routing)
-{
-	static const struct v4l2_mbus_framefmt format = {
-		.width = 1280,
-		.height = 1080,
-		.code = MEDIA_BUS_FMT_Y8_1X8,
-		.field = V4L2_FIELD_NONE,
-	};
-	int ret;
-
-	/*
-	 * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
-	 * frame desc is made dynamically allocated.
-	 */
-	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
-		return -EINVAL;
-
-	ret = v4l2_subdev_routing_validate(sd, routing,
-					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
-	if (ret)
-		return ret;
-
-	return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
-}
-
-static int max96714_set_routing(struct v4l2_subdev *sd,
-				struct v4l2_subdev_state *state,
-				enum v4l2_subdev_format_whence which,
-				struct v4l2_subdev_krouting *routing)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-
-	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
-		return -EBUSY;
-
-	return _max96714_set_routing(sd, state, which, routing);
-}
-
-static int max96714_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	struct v4l2_subdev_route routes[] = {
-		{
-			.sink_pad = MAX96714_PAD_SINK,
-			.sink_stream = 0,
-			.source_pad = MAX96714_PAD_SOURCE,
-			.source_stream = 0,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
-		}
-	};
-	struct v4l2_subdev_krouting routing = {
-		.num_routes = ARRAY_SIZE(routes),
-		.routes = routes,
-	};
-
-	return _max96714_set_routing(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE,
-				     &routing);
-}
-
-static const struct v4l2_subdev_pad_ops max96714_pad_ops = {
-	.enable_streams = max96714_enable_streams,
-	.disable_streams = max96714_disable_streams,
-
-	.set_routing = max96714_set_routing,
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = max96714_set_fmt,
-};
-
-static bool max96714_link_locked(struct max96714_priv *priv)
-{
-	u64 val = 0;
-
-	cci_read(priv->regmap, MAX96714_LINK_LOCK, &val, NULL);
-
-	return val & MAX96714_LINK_LOCK_BIT;
-}
-
-static void max96714_link_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Link locked:%d\n", max96714_link_locked(priv));
-}
-
-static bool max96714_pipe_locked(struct max96714_priv *priv)
-{
-	u64 val;
-
-	cci_read(priv->regmap, MAX96714_VIDEO_RX8, &val, NULL);
-
-	return val & MAX96714_VID_LOCK;
-}
-
-static void max96714_pipe_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Pipe vidlock:%d\n", max96714_pipe_locked(priv));
-}
-
-static void max96714_csi_status(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 freq = 0;
-
-	cci_read(priv->regmap, MAX96714_BACKTOP25, &freq, NULL);
-	freq = FIELD_GET(CSI_DPLL_FREQ_MASK, freq);
-
-	dev_info(dev, "CSI controller DPLL freq:%u00MHz CSIPHY enabled:%d\n",
-		 (u8)freq, max96714_tx_port_enabled(priv));
-}
-
-static int max96714_log_status(struct v4l2_subdev *sd)
-{
-	struct max96714_priv *priv = sd_to_max96714(sd);
-	struct device *dev = &priv->client->dev;
-
-	dev_info(dev, "Deserializer: max96714\n");
-
-	max96714_link_status(priv);
-	max96714_pipe_status(priv);
-	max96714_csi_status(priv);
-
-	return 0;
-}
-
-static const struct v4l2_subdev_core_ops max96714_subdev_core_ops = {
-	.log_status = max96714_log_status,
-};
-
-static const struct v4l2_subdev_video_ops max96714_video_ops = {
-	.s_stream	= v4l2_subdev_s_stream_helper,
-};
-
-static const struct v4l2_subdev_internal_ops max96714_internal_ops = {
-	.init_state = max96714_init_state,
-};
-
-static const struct v4l2_subdev_ops max96714_subdev_ops = {
-	.video = &max96714_video_ops,
-	.core = &max96714_subdev_core_ops,
-	.pad = &max96714_pad_ops,
-};
-
-static const struct media_entity_operations max96714_entity_ops = {
-	.link_validate = v4l2_subdev_link_validate,
-};
-
-static int max96714_notify_bound(struct v4l2_async_notifier *notifier,
-				 struct v4l2_subdev *subdev,
-				 struct v4l2_async_connection *asd)
-{
-	struct max96714_priv *priv = sd_to_max96714(notifier->sd);
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	ret = media_entity_get_fwnode_pad(&subdev->entity,
-					  priv->rxport.source.ep_fwnode,
-					  MEDIA_PAD_FL_SOURCE);
-	if (ret < 0) {
-		dev_err(dev, "Failed to find pad for %s\n", subdev->name);
-		return ret;
-	}
-
-	priv->rxport.source.sd = subdev;
-	priv->rxport.source.pad = ret;
-
-	ret = media_create_pad_link(&priv->rxport.source.sd->entity,
-				    priv->rxport.source.pad, &priv->sd.entity,
-				    MAX96714_PAD_SINK,
-				    MEDIA_LNK_FL_ENABLED |
-				    MEDIA_LNK_FL_IMMUTABLE);
-	if (ret) {
-		dev_err(dev, "Unable to link %s:%u -> %s:%u\n",
-			priv->rxport.source.sd->name, priv->rxport.source.pad,
-			priv->sd.name, MAX96714_PAD_SINK);
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_async_notifier_operations max96714_notify_ops = {
-	.bound = max96714_notify_bound,
-};
-
-static int max96714_v4l2_notifier_register(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct max96714_rxport *rxport = &priv->rxport;
-	struct v4l2_async_connection *asd;
-	int ret;
-
-	if (!rxport->source.ep_fwnode)
-		return 0;
-
-	v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
-
-	asd = v4l2_async_nf_add_fwnode(&priv->notifier,
-				       rxport->source.ep_fwnode,
-				       struct v4l2_async_connection);
-	if (IS_ERR(asd)) {
-		dev_err(dev, "Failed to add subdev: %pe", asd);
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return PTR_ERR(asd);
-	}
-
-	priv->notifier.ops = &max96714_notify_ops;
-
-	ret = v4l2_async_nf_register(&priv->notifier);
-	if (ret) {
-		dev_err(dev, "Failed to register subdev_notifier");
-		v4l2_async_nf_cleanup(&priv->notifier);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max96714_create_subdev(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	int ret;
-
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96714_subdev_ops);
-	priv->sd.internal_ops = &max96714_internal_ops;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-
-	v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ,
-			       0, 0, &priv->tx_link_freq);
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler,
-				     &max96714_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96714_test_pattern) - 1,
-				     0, 0, max96714_test_pattern);
-	if (priv->ctrl_handler.error) {
-		ret = priv->ctrl_handler.error;
-		goto err_free_ctrl;
-	}
-
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-	priv->sd.entity.ops = &max96714_entity_ops;
-
-	priv->pads[MAX96714_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	priv->pads[MAX96714_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-
-	ret = media_entity_pads_init(&priv->sd.entity,
-				     MAX96714_NPORTS,
-				     priv->pads);
-	if (ret)
-		goto err_free_ctrl;
-
-	priv->sd.state_lock = priv->sd.ctrl_handler->lock;
-
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret)
-		goto err_entity_cleanup;
-
-	ret = max96714_v4l2_notifier_register(priv);
-	if (ret) {
-		dev_err(dev, "v4l2 subdev notifier register failed: %d\n", ret);
-		goto err_subdev_cleanup;
-	}
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret) {
-		dev_err(dev, "v4l2_async_register_subdev error: %d\n", ret);
-		goto err_unreg_notif;
-	}
-
-	return 0;
-
-err_unreg_notif:
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-err_subdev_cleanup:
-	v4l2_subdev_cleanup(&priv->sd);
-err_entity_cleanup:
-	media_entity_cleanup(&priv->sd.entity);
-err_free_ctrl:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-};
-
-static void max96714_destroy_subdev(struct max96714_priv *priv)
-{
-	v4l2_async_nf_unregister(&priv->notifier);
-	v4l2_async_nf_cleanup(&priv->notifier);
-	v4l2_async_unregister_subdev(&priv->sd);
-
-	v4l2_subdev_cleanup(&priv->sd);
-
-	media_entity_cleanup(&priv->sd.entity);
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-}
-
-static int max96714_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
-{
-	return 0;
-}
-
-static int max96714_i2c_mux_init(struct max96714_priv *priv)
-{
-	priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
-				  1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
-				  max96714_i2c_mux_select, NULL);
-	if (!priv->mux)
-		return -ENOMEM;
-
-	return i2c_mux_add_adapter(priv->mux, 0, 0);
-}
-
-static int max96714_init_tx_port(struct max96714_priv *priv)
-{
-	struct v4l2_mbus_config_mipi_csi2 *mipi;
-	unsigned long lanes_used = 0;
-	unsigned int val, lane;
-	int ret;
-
-	ret = max96714_disable_tx_port(priv);
-
-	mipi = &priv->mipi_csi2;
-	val = div_u64(priv->tx_link_freq * 2, MHZ(100));
-
-	cci_update_bits(priv->regmap, MAX96714_BACKTOP25,
-			CSI_DPLL_FREQ_MASK, val, &ret);
-
-	val = FIELD_PREP(MAX96714_CSI2_LANE_CNT_MASK, mipi->num_data_lanes - 1);
-	cci_update_bits(priv->regmap, MAX96714_MIPI_LANE_CNT,
-			MAX96714_CSI2_LANE_CNT_MASK, val, &ret);
-
-	/* lanes polarity */
-	val = 0;
-	for (lane = 0; lane < mipi->num_data_lanes + 1; lane++) {
-		if (!mipi->lane_polarities[lane])
-			continue;
-		if (lane == 0)
-			/* clock lane */
-			val |= BIT(5);
-		else if (lane < 3)
-			/* Lane D0 and D1 */
-			val |= BIT(lane - 1);
-		else
-			/* D2 and D3 */
-			val |= BIT(lane);
-	}
-
-	cci_update_bits(priv->regmap, MAX96714_MIPI_POLARITY,
-			MAX96714_MIPI_POLARITY_MASK, val, &ret);
-
-	/* lanes mapping */
-	val = 0;
-	for (lane = 0; lane < mipi->num_data_lanes; lane++) {
-		val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
-		lanes_used |= BIT(mipi->data_lanes[lane] - 1);
-	}
-
-	/*
-	 * Unused lanes need to be mapped as well to not have
-	 * the same lanes mapped twice.
-	 */
-	for (; lane < MAX96714_CSI_NLANES; lane++) {
-		unsigned int idx = find_first_zero_bit(&lanes_used,
-						       MAX96714_CSI_NLANES);
-
-		val |= idx << (lane * 2);
-		lanes_used |= BIT(idx);
-	}
-
-	return cci_write(priv->regmap, MAX96714_MIPI_LANE_MAP, val, &ret);
-}
-
-static int max96714_rxport_enable_poc(struct max96714_priv *priv)
-{
-	struct max96714_rxport *rxport = &priv->rxport;
-
-	if (!rxport->poc)
-		return 0;
-
-	return regulator_enable(rxport->poc);
-}
-
-static int max96714_rxport_disable_poc(struct max96714_priv *priv)
-{
-	struct max96714_rxport *rxport = &priv->rxport;
-
-	if (!rxport->poc)
-		return 0;
-
-	return regulator_disable(rxport->poc);
-}
-
-static int max96714_parse_dt_txport(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
-	struct fwnode_handle *ep_fwnode;
-	u32 num_data_lanes;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96714_PAD_SOURCE, 0, 0);
-	if (!ep_fwnode)
-		return -EINVAL;
-
-	ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &vep);
-	fwnode_handle_put(ep_fwnode);
-	if (ret) {
-		dev_err(dev, "tx: failed to parse endpoint data\n");
-		return -EINVAL;
-	}
-
-	if (vep.nr_of_link_frequencies != 1) {
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	priv->tx_link_freq = vep.link_frequencies[0];
-	/* Min 50MHz, Max 1250MHz, 50MHz step */
-	if (priv->tx_link_freq < MHZ(50) || priv->tx_link_freq > MHZ(1250) ||
-	    (u32)priv->tx_link_freq % MHZ(50)) {
-		dev_err(dev, "tx: invalid link frequency\n");
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
-	if (num_data_lanes < 1 || num_data_lanes > MAX96714_CSI_NLANES) {
-		dev_err(dev,
-			"tx: invalid number of data lanes must be 1 to 4\n");
-		ret = -EINVAL;
-		goto err_free_vep;
-	}
-
-	priv->mipi_csi2 = vep.bus.mipi_csi2;
-
-err_free_vep:
-	v4l2_fwnode_endpoint_free(&vep);
-
-	return ret;
-}
-
-static int max96714_parse_dt_rxport(struct max96714_priv *priv)
-{
-	static const char *poc_name = "port0-poc";
-	struct max96714_rxport *rxport = &priv->rxport;
-	struct device *dev = &priv->client->dev;
-	struct fwnode_handle *ep_fwnode;
-	int ret;
-
-	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
-						    MAX96714_PAD_SINK, 0, 0);
-	if (!ep_fwnode)
-		return -ENOENT;
-
-	rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode);
-	fwnode_handle_put(ep_fwnode);
-
-	if (!rxport->source.ep_fwnode) {
-		dev_err(dev, "rx: no remote endpoint\n");
-		return -EINVAL;
-	}
-
-	rxport->poc = devm_regulator_get_optional(dev, poc_name);
-	if (IS_ERR(rxport->poc)) {
-		ret = PTR_ERR(rxport->poc);
-		if (ret == -ENODEV) {
-			rxport->poc = NULL;
-		} else {
-			dev_err(dev, "rx: failed to get POC supply: %d\n", ret);
-			goto err_put_source_ep_fwnode;
-		}
-	}
-
-	return 0;
-
-err_put_source_ep_fwnode:
-	fwnode_handle_put(rxport->source.ep_fwnode);
-	return ret;
-}
-
-static int max96714_parse_dt(struct max96714_priv *priv)
-{
-	int ret;
-
-	ret = max96714_parse_dt_txport(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_parse_dt_rxport(priv);
-	/*
-	 * The deserializer can create a test pattern even if the
-	 * rx port is not connected to a serializer.
-	 */
-	if (ret && ret == -ENOENT)
-		ret = 0;
-
-	return ret;
-}
-
-static int max96714_enable_core_hw(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-	u64 val;
-	int ret;
-
-	if (priv->pd_gpio) {
-		/* wait min 2 ms for reset to complete */
-		gpiod_set_value_cansleep(priv->pd_gpio, 1);
-		fsleep(2000);
-		gpiod_set_value_cansleep(priv->pd_gpio, 0);
-		/* wait min 2 ms for power up to finish */
-		fsleep(2000);
-	}
-
-	ret = cci_read(priv->regmap, MAX96714_REG13, &val, NULL);
-	if (ret) {
-		dev_err_probe(dev, ret, "Cannot read first register, abort\n");
-		goto err_pd_gpio;
-	}
-
-	if (val != MAX96714_DEVICE_ID && val != MAX96714F_DEVICE_ID) {
-		dev_err(dev, "Unsupported device id expected %x got %x\n",
-			MAX96714F_DEVICE_ID, (u8)val);
-		ret = -EOPNOTSUPP;
-		goto err_pd_gpio;
-	}
-
-	ret = cci_read(priv->regmap, MAX96714_DEV_REV, &val, NULL);
-	if (ret)
-		goto err_pd_gpio;
-
-	dev_dbg(dev, "Found %x (rev %lx)\n", MAX96714F_DEVICE_ID,
-		(u8)val & MAX96714_DEV_REV_MASK);
-
-	ret = cci_read(priv->regmap, MAX96714_MIPI_TX52, &val, NULL);
-	if (ret)
-		goto err_pd_gpio;
-
-	if (!(val & MAX96714_TUN_EN)) {
-		dev_err(dev, "Only supporting tunnel mode");
-		ret = -EOPNOTSUPP;
-		goto err_pd_gpio;
-	}
-
-	return 0;
-
-err_pd_gpio:
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-	return ret;
-}
-
-static void max96714_disable_core_hw(struct max96714_priv *priv)
-{
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-}
-
-static int max96714_get_hw_resources(struct max96714_priv *priv)
-{
-	struct device *dev = &priv->client->dev;
-
-	priv->regmap = devm_cci_regmap_init_i2c(priv->client, 16);
-	if (IS_ERR(priv->regmap))
-		return PTR_ERR(priv->regmap);
-
-	priv->pd_gpio =
-		devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
-	if (IS_ERR(priv->pd_gpio))
-		return dev_err_probe(dev, PTR_ERR(priv->pd_gpio),
-				     "Cannot get powerdown GPIO\n");
-	return 0;
-}
-
-static int max96714_probe(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-	struct max96714_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->client = client;
-
-	ret = max96714_get_hw_resources(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_enable_core_hw(priv);
-	if (ret)
-		return ret;
-
-	ret = max96714_parse_dt(priv);
-	if (ret)
-		goto err_disable_core_hw;
-
-	max96714_init_tx_port(priv);
-
-	ret = max96714_rxport_enable_poc(priv);
-	if (ret)
-		goto err_free_ports;
-
-	ret = max96714_i2c_mux_init(priv);
-	if (ret)
-		goto err_disable_poc;
-
-	ret = max96714_create_subdev(priv);
-	if (ret)
-		goto err_del_mux;
-
-	return 0;
-
-err_del_mux:
-	i2c_mux_del_adapters(priv->mux);
-err_disable_poc:
-	max96714_rxport_disable_poc(priv);
-err_free_ports:
-	fwnode_handle_put(priv->rxport.source.ep_fwnode);
-err_disable_core_hw:
-	max96714_disable_core_hw(priv);
-
-	return ret;
-}
-
-static void max96714_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96714_priv *priv = sd_to_max96714(sd);
-
-	max96714_destroy_subdev(priv);
-	i2c_mux_del_adapters(priv->mux);
-	max96714_rxport_disable_poc(priv);
-	fwnode_handle_put(priv->rxport.source.ep_fwnode);
-	max96714_disable_core_hw(priv);
-	gpiod_set_value_cansleep(priv->pd_gpio, 1);
-}
-
-static const struct of_device_id max96714_of_ids[] = {
-	{ .compatible = "maxim,max96714f" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, max96714_of_ids);
-
-static struct i2c_driver max96714_i2c_driver = {
-	.driver	= {
-		.name		= "max96714",
-		.of_match_table	= max96714_of_ids,
-	},
-	.probe		= max96714_probe,
-	.remove		= max96714_remove,
-};
-
-module_i2c_driver(max96714_i2c_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Maxim Integrated GMSL2 Deserializers Driver");
-MODULE_AUTHOR("Julien Massot <julien.massot at collabora.com>");
-- 
2.48.1



From rmk+kernel at armlinux.org.uk  Sun Mar  9 00:53:54 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 08:53:54 +0000
Subject: [PATCH net-next] net: stmmac: allow platforms to use PHY tx clock
 stop capability
In-Reply-To: <20250308200921.1089980-4-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20250308200921.1089980-4-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <E1trCPy-005jZf-Ou@rmk-PC.armlinux.org.uk>

Allow platform glue to instruct stmmac to make use of the PHY transmit
clock stop capability when deciding whether to allow the transmit clock
from the DWMAC core to be stopped.

Cc: "Lad, Prabhakar" <prabhakar.csengg at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h     |  1 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 ++++++++++++----
 include/linux/stmmac.h                           |  3 ++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index d87275c1cf23..bddfa0f4aa21 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -306,6 +306,7 @@ struct stmmac_priv {
 	struct timer_list eee_ctrl_timer;
 	int lpi_irq;
 	u32 tx_lpi_timer;
+	bool tx_lpi_clk_stop;
 	bool eee_enabled;
 	bool eee_active;
 	bool eee_sw_timer_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4e0e72428e29..982b7d82fd53 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -460,8 +460,7 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
 	/* Check and enter in LPI mode */
 	if (!priv->tx_path_in_lpi_mode)
 		stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_FORCED,
-			priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-			0);
+				    priv->tx_lpi_clk_stop, 0);
 }
 
 /**
@@ -1107,13 +1106,18 @@ static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
 
 	priv->eee_enabled = true;
 
+	/* Update the transmit clock stop according to PHY capability if
+	 * the platform allows
+	 */
+	if (priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP)
+		priv->tx_lpi_clk_stop = tx_clk_stop;
+
 	stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
 			     STMMAC_DEFAULT_TWT_LS);
 
 	/* Try to cnfigure the hardware timer. */
 	ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
-				  priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-				  priv->tx_lpi_timer);
+				  priv->tx_lpi_clk_stop, priv->tx_lpi_timer);
 
 	if (ret) {
 		/* Hardware timer mode not supported, or value out of range.
@@ -1272,6 +1276,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	if (!(priv->plat->flags & STMMAC_FLAG_RX_CLK_RUNS_IN_LPI))
 		priv->phylink_config.eee_rx_clk_stop_enable = true;
 
+	/* Set the default transmit clock stop bit based on the platform glue */
+	priv->tx_lpi_clk_stop = priv->plat->flags &
+				STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+
 	mdio_bus_data = priv->plat->mdio_bus_data;
 	if (mdio_bus_data)
 		priv->phylink_config.default_an_inband =
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index b6f03ab12595..c4ec8bb8144e 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -183,7 +183,8 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_INT_SNAPSHOT_EN		BIT(9)
 #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
-#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
+#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP	BIT(12)
+#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.30.2



From dmitry.baryshkov at linaro.org  Sun Mar  9 01:16:00 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:16:00 +0200
Subject: [PATCH v5 02/12] phy: hdmi: Add color depth configuration
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-2-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-2-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpqYE1drM6=C0AwPZ-e5RkWqjMTpWQiwhA64qby1mmVL1Q@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> Extend the HDMI configuration options to allow managing bits per color
> channel.  This is required by some PHY drivers such as
> rockchip-samsung-hdptx.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  include/linux/phy/phy-hdmi.h | 2 ++
>  1 file changed, 2 insertions(+)
>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Just to confirm, are you passing TMDS char rate or pixel clock for
DeepColor (bpc > 8) modes?


-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:17:46 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:17:46 +0200
Subject: [PATCH v5 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio setup
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>
Message-ID: <CAA8EJprBcGz0tZ5SDVC_WK2bzjXZAtOj+LfGnSxmwktvaQw=VQ@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
> and not before.

Am I correct that the only functional change is a switch from
greater-or-equal to simple greater?

>
> While at it, introduce a define for this rate limit constant.
>
> Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index f88369864c50e4563834ccbb26f1f9f440e99271..cf2c3a46604cb9d8c26fe5ec8346904e0b62848f 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -320,6 +320,7 @@
>  #define LN3_TX_SER_RATE_SEL_HBR2_MASK  BIT(3)
>  #define LN3_TX_SER_RATE_SEL_HBR3_MASK  BIT(2)
>
> +#define HDMI14_MAX_RATE                        340000000
>  #define HDMI20_MAX_RATE                        600000000
>
>  enum dp_link_rate {
> @@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
>
>         regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
>
> -       if (rate >= 3400000) {
> +       if (rate > HDMI14_MAX_RATE / 100) {
>                 /* For 1/40 bitrate clk */
>                 rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
>         } else {
>
> --
> 2.48.1
>


-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:18:14 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:18:14 +0200
Subject: [PATCH v5 04/12] phy: rockchip: samsung-hdptx: Drop unused struct lcpll_config
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-4-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-4-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpo0073Ub-WNdQoAq0=Zvet8M9aan3e6v9cnKORCTkqMKw@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> This is just a leftover from downstream support for HDMI 2.1.
> Remove the unused struct for now.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -----------------------
>  1 file changed, 31 deletions(-)
>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:18:34 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:18:34 +0200
Subject: [PATCH v5 05/12] phy: rockchip: samsung-hdptx: Drop unused
 phy_cfg driver data
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-5-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-5-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpoqRbTgkvQz8E2PpgC9QAsQBHvedY8=xH4haMVMjNbSuA@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> There is no usage of phy_cfg in the upstream driver data, nor in the
> downstream one, hence remove it.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
>  1 file changed, 1 deletion(-)
>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From demonsingur at gmail.com  Sun Mar  9 00:47:52 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:52 +0200
Subject: [RFC PATCH v2 00/16]  media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
Message-ID: <20250309084814.3114794-1-demonsingur@gmail.com>

This series adds new drivers for multiple Maxim GMSL2 and GMSL3 devices,
replacing the few GMSL2 drivers already in upstream, and introducing a
common framework that can be used to implement such GMSL chips, which
avoids code duplication while also adding support for previously
unsupported features.

While the normally acceptable and polite way would be to extend the
current mainline drivers, the choice was made here to add a totally new
set of drivers. The current drivers support only a small subset of the
possible features, and only a few devices, so the end result after
extending them would in any case be essentially fully rewritten, new
drivers.

This series depends on these two series:
 * https://lore.kernel.org/lkml/20250306-fpc202-v9-0-2779af6780f6 at bootlin.com
 * https://lore.kernel.org/lkml/20250228151730.1874916-1-demonsingur at gmail.com

The following deserializers are supported:
 * MAX96712 (already exists in staging)
 * MAX96714 (already exists)
 * MAX96716 (GMSL2)
 * MAX96724 (part of existing MAX96712 driver)
 * MAX9296A (GMSL2)
 * MAX96792A (GMSL3)

The following serializers are supported:
 * MAX96717 (already exists)
 * MAX9295A (GMSL2)
 * MAX96793 (GMSL3)

Missing features:
 * The current TPG implementation makes use of the V4L2_CID_TEST_PATTERN
   V4L2 control. With V4L2 streams support added, we would like to hook
   up TPG using the internal pad feature which has not been accepted
   upstream yet. We decided to leave TPG out for the moment and add it
   back after internal pads have been accepted.

Known backward compatibility breakages:
 * No default routing. Default routing has been intentionally ommitted
   as the devices support quite complex routing and it would be
   unfeasible to provide sane defaults for multi-link deserialziers.
   It is expected that userspace programs would set appropritate
   routing. 

The following list enumerates new features that are supported by the
common framework and their respective chip-specific drivers:
 * Full Streams API support. Most deserializers have support for more
   than one link, and more than one PHY. Streams support allows
   configuration of routing between these links and PHYs.

 * .get_frame_desc() support. Both the serializers and deserializers
   implement this to query and provide frame descriptor data. This is
   used in features explained in-depth below.

 * .get_mbus_config() support. The deserializers implement this to allow
   upstream devices to query the link frequency of its pads.

 * Address translation with I2C ATR for the serializers.

 * I2C MUX where supported by the hardware for deserializers, otherwise
   I2C ATR translation - some deserializers cannot do muxing since I2C
   communication channel masking is not available per-link, and the only
   other way to select links is to turn them off, causing link resets.
   For such cases, I2C ATR is used to change the address of
   the serializers at probe time.

 * Automatic VC remapping on the deserializers. VCs are picked so that
   if they were unique on the sink pad, they will end up as unique on
   the source pad they are routed to too, prioritizing using the same
   VC ID as the sink pad, to facilitate the possibility of using tunnel
   mode.

 * Automatic pixel mode / tunnel mode selection. Tunnel mode is used
   when VC IDs do not need to be changed and all hardware supports
   tunnel mode, otherwise, pixel mode is used. The serializers are
   automatically switched between the two by using a private API.

 * Automatic double mode selection. In pixel mode, double mode can be
   used to pack two pixels into a single data unit, optimizing bandwidth
   usage. The serializers are automatically set up to support the double
   modes determined by the deserializers using a private API.

 * Automatic data padding. In pixel mode, if the data being transferred
   uses two different BPPs, data needs to be padded. The serializers
   automatically set this up depending on the configured double mode
   settings and incoming data types.

 * Logging. Both the deserializers and serializers implement the V4L2
   .log_status() ops to allow debugging of the internal state and
   important chip status registers.

 * PHY modes. Deserializer chips commonly have more than a single PHY.
   The firmware ports are parsed to determine the modes in which to
   configure the PHYs (2x4, 4x2, 1x4+2x2, 2x2+1x4, and variations using
   fewer lanes).

 * Serializer pinctrl. Serializers implement pinctrl to allow setting
   configs which would otherwise be inaccessible through GPIO: TX/RX via
   GMSL link, pull-up & pull-down (with strength), open-drain &
   push-pull, slew rate, RCLK pin selection.

The drivers have been tested on the following hardware combinations, but
further testing is welcome to ensure no / minimal breakage:
 * Raspberry Pi 5 + MAX96724 + 4xMAX96717 + 4xIMX219
 * Raspberry Pi 5 + MAX96792A + 1xMAX96793 + 1xMAX96717 + 2xIMX219
 * Raspberry Pi 5 + MAX96792A + 2xMAX96717 + 2xIMX219
 * Renesas V4H + MAX96712 + 2xMAX96717 + 2xIMX219 

Analog Devices is taking responsibility for the maintenance of these
drivers and common framework, and plans to add support for new
broad-market chips on top of them.

Special thanks go to Tomi Valkeinen <tomi.valkeinen+renesas at ideasonboard.com>
for testing the drivers, helping debug and coming up with ideas /
implementations for various features.

V2:
 * add missing compatible for MAX96717F
 * fix embarrassing dt-bindings mistakes
 * move MAX9296A/MAX96716/MAX96792A to a separate file as they have two
   links / PHYs, and adding those conditionally seems impossible

Cosmin Tanislav (16):
  dt-bindings: media: i2c: max96717: add myself as maintainer
  dt-bindings: media: i2c: max96717: reflow text
  dt-bindings: media: i2c: max96717: add support for I2C ATR
  dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf
  dt-bindings: media: i2c: max96717: add support for MAX9295A
  dt-bindings: media: i2c: max96717: add support for MAX96793
  dt-bindings: media: i2c: max96712: add myself as maintainer
  dt-bindings: media: i2c: max96712: use pattern properties for ports
  dt-bindings: media: i2c: max96712: add support for I2C MUX
  dt-bindings: media: i2c: max96712: add support for POC supplies
  dt-bindings: media: i2c: add MAX9296A, MAX96716A, MAX96792A
  media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
  arm64: defconfig: disable deprecated MAX96712 driver
  staging: media: remove MAX96712 driver
  media: i2c: remove MAX96717 driver
  media: i2c: remove MAX96714 driver

 .../bindings/media/i2c/maxim,max9296a.yaml    |  281 ++
 .../bindings/media/i2c/maxim,max96712.yaml    |   47 +-
 .../media/i2c/maxim,max96717-pinctrl.yaml     |   71 +
 .../bindings/media/i2c/maxim,max96717.yaml    |   80 +-
 MAINTAINERS                                   |   13 +-
 arch/arm64/configs/defconfig                  |    1 -
 drivers/media/i2c/Kconfig                     |   34 +-
 drivers/media/i2c/Makefile                    |    3 +-
 drivers/media/i2c/max96714.c                  | 1024 --------
 drivers/media/i2c/max96717.c                  | 1103 --------
 drivers/media/i2c/maxim-serdes/Kconfig        |   53 +
 drivers/media/i2c/maxim-serdes/Makefile       |    6 +
 drivers/media/i2c/maxim-serdes/max9296a.c     | 1146 ++++++++
 drivers/media/i2c/maxim-serdes/max96717.c     | 1501 +++++++++++
 drivers/media/i2c/maxim-serdes/max96724.c     |  905 +++++++
 drivers/media/i2c/maxim-serdes/max_des.c      | 2321 +++++++++++++++++
 drivers/media/i2c/maxim-serdes/max_des.h      |  135 +
 drivers/media/i2c/maxim-serdes/max_ser.c      | 1584 +++++++++++
 drivers/media/i2c/maxim-serdes/max_ser.h      |  132 +
 drivers/media/i2c/maxim-serdes/max_serdes.c   |  302 +++
 drivers/media/i2c/maxim-serdes/max_serdes.h   |   88 +
 drivers/staging/media/Kconfig                 |    2 -
 drivers/staging/media/Makefile                |    1 -
 drivers/staging/media/max96712/Kconfig        |   14 -
 drivers/staging/media/max96712/Makefile       |    2 -
 drivers/staging/media/max96712/max96712.c     |  487 ----
 26 files changed, 8634 insertions(+), 2702 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 delete mode 100644 drivers/media/i2c/max96714.c
 delete mode 100644 drivers/media/i2c/max96717.c
 create mode 100644 drivers/media/i2c/maxim-serdes/Kconfig
 create mode 100644 drivers/media/i2c/maxim-serdes/Makefile
 create mode 100644 drivers/media/i2c/maxim-serdes/max9296a.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max96717.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max96724.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_des.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_des.h
 create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.h
 create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.c
 create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.h
 delete mode 100644 drivers/staging/media/max96712/Kconfig
 delete mode 100644 drivers/staging/media/max96712/Makefile
 delete mode 100644 drivers/staging/media/max96712/max96712.c

-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:53 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:53 +0200
Subject: [RFC PATCH v2 01/16] dt-bindings: media: i2c: max96717: add myself as maintainer
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-2-demonsingur@gmail.com>

Analog Devices is taking responsability for the maintenance of the Maxim
GMSL2/3 devices.
Add myself to the maintainers list and to the device tree bindings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 1 +
 MAINTAINERS                                                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index d1e8ba6e368e..15ab37702a92 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -9,6 +9,7 @@ title: MAX96717 CSI-2 to GMSL2 Serializer
 
 maintainers:
   - Julien Massot <julien.massot at collabora.com>
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
   The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
diff --git a/MAINTAINERS b/MAINTAINERS
index 1916d0636408..8f463ebca056 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14198,6 +14198,7 @@ F:	drivers/media/i2c/max96714.c
 
 MAX96717 GMSL2 SERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:54 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:54 +0200
Subject: [RFC PATCH v2 02/16] dt-bindings: media: i2c: max96717: reflow text
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-3-demonsingur@gmail.com>

This text is using weird line lengths. Fix it.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96717.yaml    | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 15ab37702a92..1026678a17a7 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -12,16 +12,15 @@ maintainers:
   - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description:
-  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
-  into GMSL2 serial outputs. The device allows the GMSL2 link to
-  simultaneously transmit bidirectional control-channel data while forward
-  video transmissions are in progress. The MAX96717 can connect to one
-  remotely located deserializer using industry-standard coax or STP
-  interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
-  the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI
-  data received by the serializer.
-  The MAX96717 supports Reference Over Reverse (channel),
-  to generate a clock output for the sensor from the GMSL reverse channel.
+  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input into GMSL2
+  serial outputs. The device allows the GMSL2 link to simultaneously transmit
+  bidirectional control-channel data while forward video transmissions are in
+  progress. The MAX96717 can connect to one remotely located deserializer using
+  industry-standard coax or STP interconnects. The device cans operate in pixel
+  or tunnel mode. In pixel mode the MAX96717 can select the MIPI datatype, while
+  the tunnel mode forward all the MIPI data received by the serializer.
+  The MAX96717 supports Reference Over Reverse (channel), to generate a clock
+  output for the sensor from the GMSL reverse channel.
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:55 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:55 +0200
Subject: [RFC PATCH v2 03/16] dt-bindings: media: i2c: max96717: add support for I2C ATR
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-4-demonsingur@gmail.com>

MAX96717 is capable of address translation for the connected I2C slaves.

Add support for I2C ATR while keeping I2C gate for compatibility to
support this usecase.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96717.yaml    | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 1026678a17a7..dd28cc397674 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -91,6 +91,30 @@ properties:
       incoming GMSL2 link. Therefore, it supports an i2c-gate
       subnode to configure a sensor.
 
+  i2c-alias-pool:
+    maxItems: 2
+
+  i2c-atr:
+    type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 1
+
+      '#size-cells':
+        const: 0
+
+    patternProperties:
+      '^i2c at 0':
+        $ref: /schemas/i2c/i2c-controller.yaml#
+        unevaluatedProperties: false
+        properties:
+          reg:
+            items:
+              minimum: 0
+              maximum: 1
+
 required:
   - compatible
   - reg
@@ -98,6 +122,21 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - $ref: /schemas/i2c/i2c-atr.yaml#
+
+  - anyOf:
+      - oneOf:
+          - required: [i2c-atr]
+          - required: [i2c-gate]
+
+      - not:
+          required: [i2c-atr, i2c-gate]
+
+dependentRequired:
+  i2c-atr: [i2c-alias-pool]
+  i2c-alias-pool: [i2c-atr]
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:56 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:56 +0200
Subject: [RFC PATCH v2 04/16] dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-5-demonsingur@gmail.com>

MAX96717 is capable of configuring various pin properties.

Add pinctrl/pinconf properties to support this usecase.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../media/i2c/maxim,max96717-pinctrl.yaml     | 71 +++++++++++++++++++
 .../bindings/media/i2c/maxim,max96717.yaml    | 16 ++++-
 MAINTAINERS                                   |  1 +
 3 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
new file mode 100644
index 000000000000..347e66a5320c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2025 Analog Devices Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim GMSL2 Serializer Pinctrl
+
+maintainers:
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
+
+allOf:
+  - $ref: /schemas/pinctrl/pincfg-node.yaml#
+  - $ref: /schemas/pinctrl/pinmux-node.yaml#
+
+unevaluatedProperties: false
+
+properties:
+  function: true
+  pins: true
+  drive-open-drain: true
+  drive-push-pull: true
+  bias-disable: true
+  bias-pull-up: true
+  bias-pull-down: true
+  output-disable: true
+  output-enable: true
+  output-low: true
+  output-high: true
+  slew-rate: true
+  input-enable: true
+
+  maxim,jitter-compensation:
+    type: boolean
+    description: Enables jitter compensation.
+
+  maxim,gmsl-tx:
+    type: boolean
+    description: Enable transmitting pin value to GMSL link.
+
+  maxim,gmsl-rx:
+    type: boolean
+    description: Enable receiving pin value from GMSL link.
+
+  maxim,gmsl-tx-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Identifier used while transmitting value to GMSL link.
+      Default value matches the pin number.
+    minimum: 0
+    maximum: 31
+
+  maxim,gmsl-rx-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Identifier used while receiving value from GMSL link.
+      Default value matches the pin number.
+    minimum: 0
+    maximum: 31
+
+  maxim,rclkout-clock:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Clock value.
+      0 - XTAL / 1 = 25MHz
+      1 - XTAL / 2 = 12.5MHz
+      2 - XTAL / 4 = 6.25MHz
+      3 - Reference PLL output
+    minimum: 0
+    maximum: 3
diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index dd28cc397674..0a43582168a8 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -120,7 +120,21 @@ required:
   - reg
   - ports
 
-additionalProperties: false
+additionalProperties:
+  anyOf:
+    - type: object
+      allOf:
+        - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+
+      unevaluatedProperties: false
+
+    - type: object
+      additionalProperties:
+        type: object
+        allOf:
+          - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#
+
+        unevaluatedProperties: false
 
 allOf:
   - $ref: /schemas/i2c/i2c-atr.yaml#
diff --git a/MAINTAINERS b/MAINTAINERS
index 8f463ebca056..f8ffb7cff9c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14201,6 +14201,7 @@ M:	Julien Massot <julien.massot at collabora.com>
 M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
 F:	drivers/media/i2c/max96717.c
 
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:57 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:57 +0200
Subject: [RFC PATCH v2 05/16] dt-bindings: media: i2c: max96717: add support for MAX9295A
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-6-demonsingur@gmail.com>

MAX9295A is an older variant of the MAX96717 which does not support
tunnel mode.

Document the compatibility.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96717.yaml          | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 0a43582168a8..31fb62debdc7 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -24,11 +24,14 @@ description:
 
   The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
   forward direction and 187.5Mbps in the reverse direction.
+
   MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
+  MAX9295A only supports pixel mode.
 
 properties:
   compatible:
     oneOf:
+      - const: maxim,max9295a
       - const: maxim,max96717f
       - items:
           - enum:
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:58 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:58 +0200
Subject: [RFC PATCH v2 06/16] dt-bindings: media: i2c: max96717: add support for MAX96793
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-7-demonsingur@gmail.com>

MAX96793 is a newer variant of the MAX96717 which also supports GMSL3
links.

Document this compatibility.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
index 31fb62debdc7..02857f0364c4 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
@@ -27,6 +27,7 @@ description:
 
   MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
   MAX9295A only supports pixel mode.
+  MAX96793 also supports GMSL3 mode.
 
 properties:
   compatible:
@@ -36,6 +37,7 @@ properties:
       - items:
           - enum:
               - maxim,max96717
+              - maxim,max96793
           - const: maxim,max96717f
 
   '#gpio-cells':
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:47:59 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:47:59 +0200
Subject: [RFC PATCH v2 07/16] dt-bindings: media: i2c: max96712: add myself as maintainer
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-8-demonsingur@gmail.com>

Analog Devices is taking responsability for the maintenance of the Maxim
GMSL2/3 devices.
Add myself to the maintainers list and to the device tree bindings.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml | 1 +
 MAINTAINERS                                                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 26f85151afbd..efdece2b33b9 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -9,6 +9,7 @@ title: Quad GMSL2 to CSI-2 Deserializer with GMSL1 Compatibility
 
 maintainers:
   - Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
 
 description: |
   The MAX96712 deserializer converts GMSL2 or GMSL1 serial inputs into MIPI
diff --git a/MAINTAINERS b/MAINTAINERS
index f8ffb7cff9c5..abf3afc95fc9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14184,6 +14184,7 @@ F:	drivers/media/i2c/max9286.c
 
 MAX96712 QUAD GMSL2 DESERIALIZER DRIVER
 M:	Niklas S?derlund <niklas.soderlund at ragnatech.se>
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:00 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:00 +0200
Subject: [RFC PATCH v2 08/16] dt-bindings: media: i2c: max96712: use pattern properties for ports
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-9-demonsingur@gmail.com>

The MAX96712 and MAX96724 support up to 4 separate PHYs, depending on
the selected PHY configuration. Use patternProperties to document this.

The input ports are all the same, use patternProperties for them.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96712.yaml    | 29 +++++++------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index efdece2b33b9..bf8c861c836b 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -40,27 +40,15 @@ properties:
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
-    properties:
-      port at 0:
+    patternProperties:
+      '^port@[0-3]$':
         $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 0
+        description: GMSL Input port
 
-      port at 1:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 1
-
-      port at 2:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 2
-
-      port at 3:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: GMSL Input 3
-
-      port at 4:
+      '^port@[4-7]$':
         $ref: /schemas/graph.yaml#/$defs/port-base
         unevaluatedProperties: false
-        description: CSI-2 Output
+        description: CSI-2 Output port
 
         properties:
           endpoint:
@@ -78,8 +66,11 @@ properties:
               - data-lanes
               - bus-type
 
-    required:
-      - port at 4
+    anyOf:
+      - required: [port at 4]
+      - required: [port at 5]
+      - required: [port at 6]
+      - required: [port at 7]
 
 required:
   - compatible
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:01 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:01 +0200
Subject: [RFC PATCH v2 09/16] dt-bindings: media: i2c: max96712: add support for I2C MUX
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-10-demonsingur@gmail.com>

MAX96712 and MAX96724 have more than one GMSL2 link, and each link is
capable of connecting to a separate serializer. If these serializers
have the same CFG pins configuration, they will also have the same I2C
address, causing conflicts unless the deserializer muxes the I2C
channels. Moreover, the serializers can have the same hardware attached
to their respective I2C bus.

The MAX96712 and MAX96724 suppot I2C channel muxing via the GMSL2 link
to facilitate communication to each of the connected serializers.

Document this capability.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max96712.yaml          | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index bf8c861c836b..9e27568e0105 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -37,6 +37,19 @@ properties:
 
   enable-gpios: true
 
+  i2c-mux:
+    $ref: /schemas/i2c/i2c-mux.yaml#
+    unevaluatedProperties: false
+    patternProperties:
+      '^i2c@[0-3]$':
+        $ref: /schemas/i2c/i2c-controller.yaml#
+        unevaluatedProperties: false
+        properties:
+          reg:
+            items:
+              minimum: 0
+              maximum: 3
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:02 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:02 +0200
Subject: [RFC PATCH v2 10/16] dt-bindings: media: i2c: max96712: add support for POC supplies
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-11-demonsingur@gmail.com>

The GMSL links can carry power to the serializer when using coaxial
cables.

Document this capability.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../devicetree/bindings/media/i2c/maxim,max96712.yaml         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 9e27568e0105..a497c7af645e 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -85,6 +85,10 @@ properties:
       - required: [port at 6]
       - required: [port at 7]
 
+patternProperties:
+  '^port[0-3]-poc-supply$':
+    description: Regulator providing Power over Coax for GMSL ports
+
 required:
   - compatible
   - reg
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:03 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:03 +0200
Subject: [RFC PATCH v2 11/16] dt-bindings: media: i2c: add MAX9296A, MAX96716A, MAX96792A
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-12-demonsingur@gmail.com>

The MAX9296A deserializer converts single or dual serial inputs to MIPI
CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps or 6Gbps
in the forward direction and 187.5Mbps in the reverse direction.
In GMSL1 mode, each serial link can be paired with 3.12Gbps or 1.5Gbps
GMSL1 serializers or operate up to 4.5Gbps with GMSL2 serializers with
GMSL1 backward compatibility. The MAX9296A supports mixed GMSL2 and
GMSL1 links. The serial inputs operate independently, allowing videos
with different timings and resolutions to be received on each input.

MAX96716A supports both tunnel and pixel mode.
MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 .../bindings/media/i2c/maxim,max9296a.yaml    | 281 ++++++++++++++++++
 MAINTAINERS                                   |   6 +
 2 files changed, 287 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml

diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
new file mode 100644
index 000000000000..97731549d161
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
@@ -0,0 +1,281 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024 Collabora Ltd.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/maxim,max9296a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX9296A GMSL2 to CSI-2 Deserializer
+
+maintainers:
+  - Cosmin Tanislav <cosmin.tanislav at analog.com>
+
+description:
+  The MAX9296A deserializer converts single or dual serial inputs to
+  MIPI CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps
+  or 6Gbps in the forward direction and 187.5Mbps in the reverse
+  direction. In GMSL1 mode, each serial link can be paired with 3.12Gbps
+  or 1.5Gbps GMSL1 serializers or operate up to 4.5Gbps with GMSL2
+  serializers with GMSL1 backward compatibility. The MAX9296A supports
+  mixed GMSL2 and GMSL1 links. The serial inputs operate independently,
+  allowing videos with different timings and resolutions to be received
+  on each input.
+
+  MAX96716A supports both tunnel and pixel mode.
+  MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
+
+properties:
+  compatible:
+    enum:
+      - maxim,max9296a
+      - maxim,max96716a
+      - maxim,max96792a
+
+  reg:
+    maxItems: 1
+
+  powerdown-gpios:
+    maxItems: 1
+    description: Specifier for the GPIO connected to the PWDNB pin.
+
+  port0-poc-supply:
+    description: Regulator providing Power over Coax for GMSL port 0
+
+  port1-poc-supply:
+    description: Regulator providing Power over Coax for GMSL port 1
+
+  i2c-mux:
+    $ref: /schemas/i2c/i2c-mux.yaml#
+    unevaluatedProperties: false
+    patternProperties:
+      '^i2c@[0-1]$':
+        $ref: /schemas/i2c/i2c-controller.yaml#
+        unevaluatedProperties: false
+        properties:
+          reg:
+            items:
+              minimum: 0
+              maximum: 1
+
+  i2c-alias-pool:
+    maxItems: 2
+
+  i2c-atr:
+    type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 1
+
+      '#size-cells':
+        const: 0
+
+    patternProperties:
+      '^i2c@[0-1]$':
+        $ref: /schemas/i2c/i2c-controller.yaml#
+        unevaluatedProperties: false
+        properties:
+          reg:
+            items:
+              minimum: 0
+              maximum: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    patternProperties:
+      '^port@[0-1]$':
+        $ref: /schemas/graph.yaml#/properties/port
+        unevaluatedProperties: false
+        description: GMSL Input
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description: Endpoint for GMSL2-Link port.
+
+      '^port@[2-3]$':
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: CSI-2 Output port
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+
+              lane-polarities:
+                minItems: 1
+                maxItems: 5
+
+              link-frequencies:
+                maxItems: 1
+
+            required:
+              - data-lanes
+
+    anyOf:
+      - required:
+          - port at 2
+      - required:
+          - port at 3
+
+required:
+  - compatible
+  - reg
+  - ports
+
+additionalProperties: false
+
+allOf:
+  - $ref: /schemas/i2c/i2c-atr.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - maxim,max9296a
+              - maxim,max96792a
+    then:
+      not:
+        required: [i2c-mux]
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - maxim,max96716a
+    then:
+      not:
+        required: [i2c-atr]
+
+dependentRequired:
+  i2c-atr: [i2c-alias-pool]
+  i2c-alias-pool: [i2c-atr]
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/media/video-interfaces.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        deserializer at 28 {
+            compatible = "maxim,max9296a";
+            reg = <0x28>;
+            powerdown-gpios = <&main_gpio0 37 GPIO_ACTIVE_LOW>;
+
+            i2c-alias-pool = <0x40 0x41>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+                    des_gmsl_in_0: endpoint {
+                        remote-endpoint = <&ser_0_gmsl_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+                    des_gmsl_in_1: endpoint {
+                        remote-endpoint = <&ser_1_gmsl_out>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <2>;
+                    des_csi_out: endpoint {
+                        data-lanes = <1 2 3 4>;
+                        link-frequencies = /bits/ 64 <400000000>;
+                        remote-endpoint = <&csi_in>;
+                    };
+                };
+            };
+
+            i2c-atr {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                i2c at 0 {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+                    reg = <0>;
+
+                    serializer at 40 {
+                        compatible = "maxim,max96717";
+                        reg = <0x40>;
+                        gpio-controller;
+                        #gpio-cells = <2>;
+                        #clock-cells = <0>;
+
+                        ports {
+                            #address-cells = <1>;
+                            #size-cells = <0>;
+
+                            port at 0 {
+                                reg = <0>;
+                                ser_0_csi_in: endpoint {
+                                    data-lanes = <1 2>;
+                                    remote-endpoint = <&sensor_0_out>;
+                                };
+                            };
+
+                            port at 1 {
+                                reg = <1>;
+                                ser_0_gmsl_out: endpoint {
+                                    remote-endpoint = <&des_gmsl_in_0>;
+                                };
+                            };
+                        };
+                    };
+                };
+
+                i2c at 1 {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+                    reg = <1>;
+
+                    serializer at 40 {
+                        compatible = "maxim,max96717";
+                        reg = <0x40>;
+                        gpio-controller;
+                        #gpio-cells = <2>;
+                        #clock-cells = <0>;
+
+                        ports {
+                            #address-cells = <1>;
+                            #size-cells = <0>;
+
+                            port at 0 {
+                                reg = <0>;
+                                ser_1_csi_in: endpoint {
+                                    data-lanes = <1 2>;
+                                    remote-endpoint = <&sensor_1_out>;
+                                };
+                            };
+
+                            port at 1 {
+                                reg = <1>;
+                                ser_1_gmsl_out: endpoint {
+                                    remote-endpoint = <&des_gmsl_in_1>;
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index abf3afc95fc9..c1e01668e81a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14220,6 +14220,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml
 F:	drivers/iio/proximity/mb1232.c
 
+MAXIM GMSL2 SERIALIZERS AND DESERIALIZERS
+M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
+L:	linux-media at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
+
 MAXIM MAX11205 DRIVER
 M:	Ramona Bolboaca <ramona.bolboaca at analog.com>
 L:	linux-iio at vger.kernel.org
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:05 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:05 +0200
Subject: [RFC PATCH v2 13/16] arm64: defconfig: disable deprecated MAX96712 driver
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-14-demonsingur@gmail.com>

The staging MAX96712 driver will be removed as its functionality has
been moved to the MAX96724 driver which makes use of the Maxim
GMSL2/3 deserializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 arch/arm64/configs/defconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..6e9bd9072d11 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1272,7 +1272,6 @@ CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
-CONFIG_VIDEO_MAX96712=m
 CONFIG_VIDEO_MESON_VDEC=m
 CONFIG_SND_BCM2835=m
 CONFIG_CHROME_PLATFORMS=y
-- 
2.48.1



From demonsingur at gmail.com  Sun Mar  9 00:48:06 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Sun,  9 Mar 2025 10:48:06 +0200
Subject: [RFC PATCH v2 14/16] staging: media: remove MAX96712 driver
In-Reply-To: <20250309084814.3114794-1-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
Message-ID: <20250309084814.3114794-15-demonsingur@gmail.com>

Remove the staging MAX96712 driver.
Its functionality has been moved to the MAX96724 driver which makes use
of the Maxim GMSL2/3 deserializer framework.

Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
---
 MAINTAINERS                               |   1 -
 drivers/staging/media/Kconfig             |   2 -
 drivers/staging/media/Makefile            |   1 -
 drivers/staging/media/max96712/Kconfig    |  14 -
 drivers/staging/media/max96712/Makefile   |   2 -
 drivers/staging/media/max96712/max96712.c | 487 ----------------------
 6 files changed, 507 deletions(-)
 delete mode 100644 drivers/staging/media/max96712/Kconfig
 delete mode 100644 drivers/staging/media/max96712/Makefile
 delete mode 100644 drivers/staging/media/max96712/max96712.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e97c4f55bc2f..4d1ff8cf537b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14188,7 +14188,6 @@ M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
 L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
-F:	drivers/staging/media/max96712/max96712.c
 
 MAX96714 GMSL2 DESERIALIZER DRIVER
 M:	Julien Massot <julien.massot at collabora.com>
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index b44214854399..fe29821f64a3 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -28,8 +28,6 @@ source "drivers/staging/media/imx/Kconfig"
 
 source "drivers/staging/media/ipu3/Kconfig"
 
-source "drivers/staging/media/max96712/Kconfig"
-
 source "drivers/staging/media/meson/vdec/Kconfig"
 
 source "drivers/staging/media/rkvdec/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index ad4e9619a9e0..1a562b3b6881 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -2,7 +2,6 @@
 obj-$(CONFIG_VIDEO_ATMEL_ISC_BASE)	+= deprecated/atmel/
 obj-$(CONFIG_INTEL_ATOMISP)     += atomisp/
 obj-$(CONFIG_VIDEO_IMX_MEDIA)	+= imx/
-obj-$(CONFIG_VIDEO_MAX96712)	+= max96712/
 obj-$(CONFIG_VIDEO_MESON_VDEC)	+= meson/vdec/
 obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC)	+= rkvdec/
 obj-$(CONFIG_VIDEO_STARFIVE_CAMSS)	+= starfive/
diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig
deleted file mode 100644
index 117fadf81bd0..000000000000
--- a/drivers/staging/media/max96712/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VIDEO_MAX96712
-	tristate "Maxim MAX96712 Quad GMSL2 Deserializer support"
-	depends on I2C
-	depends on OF_GPIO
-	depends on VIDEO_DEV
-	select V4L2_FWNODE
-	select VIDEO_V4L2_SUBDEV_API
-	select MEDIA_CONTROLLER
-	help
-	  This driver supports the Maxim MAX96712 Quad GMSL2 Deserializer.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called max96712.
diff --git a/drivers/staging/media/max96712/Makefile b/drivers/staging/media/max96712/Makefile
deleted file mode 100644
index 70c1974ce3f0..000000000000
--- a/drivers/staging/media/max96712/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_VIDEO_MAX96712) += max96712.o
diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c
deleted file mode 100644
index 0751b2e04895..000000000000
--- a/drivers/staging/media/max96712/max96712.c
+++ /dev/null
@@ -1,487 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Maxim MAX96712 Quad GMSL2 Deserializer Driver
- *
- * Copyright (C) 2021 Renesas Electronics Corporation
- * Copyright (C) 2021 Niklas S?derlund
- */
-
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/of_graph.h>
-#include <linux/regmap.h>
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-subdev.h>
-
-#define DEBUG_EXTRA_REG			0x09
-#define DEBUG_EXTRA_PCLK_25MHZ		0x00
-#define DEBUG_EXTRA_PCLK_75MHZ		0x01
-
-enum max96712_pattern {
-	MAX96712_PATTERN_CHECKERBOARD = 0,
-	MAX96712_PATTERN_GRADIENT,
-};
-
-struct max96712_info {
-	unsigned int dpllfreq;
-	bool have_debug_extra;
-};
-
-struct max96712_priv {
-	struct i2c_client *client;
-	struct regmap *regmap;
-	struct gpio_desc *gpiod_pwdn;
-
-	const struct max96712_info *info;
-
-	bool cphy;
-	struct v4l2_mbus_config_mipi_csi2 mipi;
-
-	struct v4l2_subdev sd;
-	struct v4l2_ctrl_handler ctrl_handler;
-	struct media_pad pads[1];
-
-	enum max96712_pattern pattern;
-};
-
-static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val)
-{
-	int ret;
-
-	ret = regmap_write(priv->regmap, reg, val);
-	if (ret)
-		dev_err(&priv->client->dev, "write 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg,
-				u8 mask, u8 val)
-{
-	int ret;
-
-	ret = regmap_update_bits(priv->regmap, reg, mask, val);
-	if (ret)
-		dev_err(&priv->client->dev, "update 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg,
-			       const void *val, size_t val_count)
-{
-	int ret;
-
-	ret = regmap_bulk_write(priv->regmap, reg, val, val_count);
-	if (ret)
-		dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg);
-
-	return ret;
-}
-
-static int max96712_write_bulk_value(struct max96712_priv *priv,
-				     unsigned int reg, unsigned int val,
-				     size_t val_count)
-{
-	unsigned int i;
-	u8 values[4];
-
-	for (i = 1; i <= val_count; i++)
-		values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff;
-
-	return max96712_write_bulk(priv, reg, &values, val_count);
-}
-
-static void max96712_reset(struct max96712_priv *priv)
-{
-	max96712_update_bits(priv, 0x13, 0x40, 0x40);
-	msleep(20);
-}
-
-static void max96712_mipi_enable(struct max96712_priv *priv, bool enable)
-{
-	if (enable) {
-		max96712_update_bits(priv, 0x40b, 0x02, 0x02);
-		max96712_update_bits(priv, 0x8a0, 0x80, 0x80);
-	} else {
-		max96712_update_bits(priv, 0x8a0, 0x80, 0x00);
-		max96712_update_bits(priv, 0x40b, 0x02, 0x00);
-	}
-}
-
-static void max96712_mipi_configure(struct max96712_priv *priv)
-{
-	unsigned int i;
-	u8 phy5 = 0;
-
-	max96712_mipi_enable(priv, false);
-
-	/* Select 2x4 mode. */
-	max96712_write(priv, 0x8a0, 0x04);
-
-	/* TODO: Add support for 2-lane and 1-lane configurations. */
-	if (priv->cphy) {
-		/* Configure a 3-lane C-PHY using PHY0 and PHY1. */
-		max96712_write(priv, 0x94a, 0xa0);
-
-		/* Configure C-PHY timings. */
-		max96712_write(priv, 0x8ad, 0x3f);
-		max96712_write(priv, 0x8ae, 0x7d);
-	} else {
-		/* Configure a 4-lane D-PHY using PHY0 and PHY1. */
-		max96712_write(priv, 0x94a, 0xc0);
-	}
-
-	/* Configure lane mapping for PHY0 and PHY1. */
-	/* TODO: Add support for lane swapping. */
-	max96712_write(priv, 0x8a3, 0xe4);
-
-	/* Configure lane polarity for PHY0 and PHY1. */
-	for (i = 0; i < priv->mipi.num_data_lanes + 1; i++)
-		if (priv->mipi.lane_polarities[i])
-			phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i);
-	max96712_write(priv, 0x8a5, phy5);
-
-	/* Set link frequency for PHY0 and PHY1. */
-	max96712_update_bits(priv, 0x415, 0x3f,
-			     ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5));
-	max96712_update_bits(priv, 0x418, 0x3f,
-			     ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5));
-
-	/* Enable PHY0 and PHY1 */
-	max96712_update_bits(priv, 0x8a2, 0xf0, 0x30);
-}
-
-static void max96712_pattern_enable(struct max96712_priv *priv, bool enable)
-{
-	const u32 h_active = 1920;
-	const u32 h_fp = 88;
-	const u32 h_sw = 44;
-	const u32 h_bp = 148;
-	const u32 h_tot = h_active + h_fp + h_sw + h_bp;
-
-	const u32 v_active = 1080;
-	const u32 v_fp = 4;
-	const u32 v_sw = 5;
-	const u32 v_bp = 36;
-	const u32 v_tot = v_active + v_fp + v_sw + v_bp;
-
-	if (!enable) {
-		max96712_write(priv, 0x1051, 0x00);
-		return;
-	}
-
-	/* Set PCLK to 75MHz if device have DEBUG_EXTRA register. */
-	if (priv->info->have_debug_extra)
-		max96712_write(priv, DEBUG_EXTRA_REG, DEBUG_EXTRA_PCLK_75MHZ);
-
-	/* Configure Video Timing Generator for 1920x1080 @ 30 fps. */
-	max96712_write_bulk_value(priv, 0x1052, 0, 3);
-	max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3);
-	max96712_write_bulk_value(priv, 0x1058,
-				  (v_active + v_fp + + v_bp) * h_tot, 3);
-	max96712_write_bulk_value(priv, 0x105b, 0, 3);
-	max96712_write_bulk_value(priv, 0x105e, h_sw, 2);
-	max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2);
-	max96712_write_bulk_value(priv, 0x1062, v_tot, 2);
-	max96712_write_bulk_value(priv, 0x1064,
-				  h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3);
-	max96712_write_bulk_value(priv, 0x1067, h_active, 2);
-	max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2);
-	max96712_write_bulk_value(priv, 0x106b, v_active, 2);
-
-	/* Generate VS, HS and DE in free-running mode. */
-	max96712_write(priv, 0x1050, 0xfb);
-
-	/* Configure Video Pattern Generator. */
-	if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) {
-		/* Set checkerboard pattern size. */
-		max96712_write(priv, 0x1074, 0x3c);
-		max96712_write(priv, 0x1075, 0x3c);
-		max96712_write(priv, 0x1076, 0x3c);
-
-		/* Set checkerboard pattern colors. */
-		max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3);
-		max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3);
-
-		/* Generate checkerboard pattern. */
-		max96712_write(priv, 0x1051, 0x10);
-	} else {
-		/* Set gradient increment. */
-		max96712_write(priv, 0x106d, 0x10);
-
-		/* Generate gradient pattern. */
-		max96712_write(priv, 0x1051, 0x20);
-	}
-}
-
-static int max96712_s_stream(struct v4l2_subdev *sd, int enable)
-{
-	struct max96712_priv *priv = v4l2_get_subdevdata(sd);
-
-	if (enable) {
-		max96712_pattern_enable(priv, true);
-		max96712_mipi_enable(priv, true);
-	} else {
-		max96712_mipi_enable(priv, false);
-		max96712_pattern_enable(priv, false);
-	}
-
-	return 0;
-}
-
-static const struct v4l2_subdev_video_ops max96712_video_ops = {
-	.s_stream = max96712_s_stream,
-};
-
-static int max96712_init_state(struct v4l2_subdev *sd,
-			       struct v4l2_subdev_state *state)
-{
-	static const struct v4l2_mbus_framefmt default_fmt = {
-		.width          = 1920,
-		.height         = 1080,
-		.code           = MEDIA_BUS_FMT_RGB888_1X24,
-		.colorspace     = V4L2_COLORSPACE_SRGB,
-		.field          = V4L2_FIELD_NONE,
-		.ycbcr_enc      = V4L2_YCBCR_ENC_DEFAULT,
-		.quantization   = V4L2_QUANTIZATION_DEFAULT,
-		.xfer_func      = V4L2_XFER_FUNC_DEFAULT,
-	};
-	struct v4l2_mbus_framefmt *fmt;
-
-	fmt = v4l2_subdev_state_get_format(state, 0);
-	*fmt = default_fmt;
-
-	return 0;
-}
-
-static const struct v4l2_subdev_internal_ops max96712_internal_ops = {
-	.init_state = max96712_init_state,
-};
-
-static const struct v4l2_subdev_pad_ops max96712_pad_ops = {
-	.get_fmt = v4l2_subdev_get_fmt,
-	.set_fmt = v4l2_subdev_get_fmt,
-};
-
-static const struct v4l2_subdev_ops max96712_subdev_ops = {
-	.video = &max96712_video_ops,
-	.pad = &max96712_pad_ops,
-};
-
-static const char * const max96712_test_pattern[] = {
-	"Checkerboard",
-	"Gradient",
-};
-
-static int max96712_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct max96712_priv *priv =
-		container_of(ctrl->handler, struct max96712_priv, ctrl_handler);
-
-	switch (ctrl->id) {
-	case V4L2_CID_TEST_PATTERN:
-		priv->pattern = ctrl->val ?
-			MAX96712_PATTERN_GRADIENT :
-			MAX96712_PATTERN_CHECKERBOARD;
-		break;
-	}
-	return 0;
-}
-
-static const struct v4l2_ctrl_ops max96712_ctrl_ops = {
-	.s_ctrl = max96712_s_ctrl,
-};
-
-static int max96712_v4l2_register(struct max96712_priv *priv)
-{
-	long pixel_rate;
-	int ret;
-
-	priv->sd.internal_ops = &max96712_internal_ops;
-	v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops);
-	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-
-	v4l2_ctrl_handler_init(&priv->ctrl_handler, 2);
-
-	/*
-	 * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an
-	 * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE.
-	 */
-	pixel_rate = priv->info->dpllfreq / priv->mipi.num_data_lanes * 1000000;
-	v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE,
-			  pixel_rate, pixel_rate, 1, pixel_rate);
-
-	v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(max96712_test_pattern) - 1,
-				     0, 0, max96712_test_pattern);
-
-	priv->sd.ctrl_handler = &priv->ctrl_handler;
-	ret = priv->ctrl_handler.error;
-	if (ret)
-		goto error;
-
-	priv->pads[0].flags = MEDIA_PAD_FL_SOURCE;
-	ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads);
-	if (ret)
-		goto error;
-
-	v4l2_set_subdevdata(&priv->sd, priv);
-
-	priv->sd.state_lock = priv->ctrl_handler.lock;
-	ret = v4l2_subdev_init_finalize(&priv->sd);
-	if (ret)
-		goto error;
-
-	ret = v4l2_async_register_subdev(&priv->sd);
-	if (ret < 0) {
-		dev_err(&priv->client->dev, "Unable to register subdevice\n");
-		goto error;
-	}
-
-	return 0;
-error:
-	v4l2_ctrl_handler_free(&priv->ctrl_handler);
-
-	return ret;
-}
-
-static int max96712_parse_dt(struct max96712_priv *priv)
-{
-	struct fwnode_handle *ep;
-	struct v4l2_fwnode_endpoint v4l2_ep = {
-		.bus_type = V4L2_MBUS_UNKNOWN,
-	};
-	unsigned int supported_lanes;
-	int ret;
-
-	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4,
-					     0, 0);
-	if (!ep) {
-		dev_err(&priv->client->dev, "Not connected to subdevice\n");
-		return -EINVAL;
-	}
-
-	ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
-	fwnode_handle_put(ep);
-	if (ret) {
-		dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n");
-		return -EINVAL;
-	}
-
-	switch (v4l2_ep.bus_type) {
-	case V4L2_MBUS_CSI2_DPHY:
-		supported_lanes = 4;
-		priv->cphy = false;
-		break;
-	case V4L2_MBUS_CSI2_CPHY:
-		supported_lanes = 3;
-		priv->cphy = true;
-		break;
-	default:
-		dev_err(&priv->client->dev, "Unsupported bus-type %u\n",
-			v4l2_ep.bus_type);
-		return -EINVAL;
-	}
-
-	if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) {
-		dev_err(&priv->client->dev, "Only %u data lanes supported\n",
-			supported_lanes);
-		return -EINVAL;
-	}
-
-	priv->mipi = v4l2_ep.bus.mipi_csi2;
-
-	return 0;
-}
-
-static const struct regmap_config max96712_i2c_regmap = {
-	.reg_bits = 16,
-	.val_bits = 8,
-	.max_register = 0x1f00,
-};
-
-static int max96712_probe(struct i2c_client *client)
-{
-	struct max96712_priv *priv;
-	int ret;
-
-	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->info = of_device_get_match_data(&client->dev);
-
-	priv->client = client;
-
-	priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap);
-	if (IS_ERR(priv->regmap))
-		return PTR_ERR(priv->regmap);
-
-	priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
-						   GPIOD_OUT_HIGH);
-	if (IS_ERR(priv->gpiod_pwdn))
-		return PTR_ERR(priv->gpiod_pwdn);
-
-	gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn");
-	gpiod_set_value_cansleep(priv->gpiod_pwdn, 1);
-
-	if (priv->gpiod_pwdn)
-		usleep_range(4000, 5000);
-
-	max96712_reset(priv);
-
-	ret = max96712_parse_dt(priv);
-	if (ret)
-		return ret;
-
-	max96712_mipi_configure(priv);
-
-	return max96712_v4l2_register(priv);
-}
-
-static void max96712_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-	struct max96712_priv *priv = container_of(sd, struct max96712_priv, sd);
-
-	v4l2_async_unregister_subdev(&priv->sd);
-
-	gpiod_set_value_cansleep(priv->gpiod_pwdn, 0);
-}
-
-static const struct max96712_info max96712_info_max96712 = {
-	.dpllfreq = 1000,
-	.have_debug_extra = true,
-};
-
-static const struct max96712_info max96712_info_max96724 = {
-	.dpllfreq = 1200,
-};
-
-static const struct of_device_id max96712_of_table[] = {
-	{ .compatible = "maxim,max96712", .data = &max96712_info_max96712 },
-	{ .compatible = "maxim,max96724", .data = &max96712_info_max96724 },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, max96712_of_table);
-
-static struct i2c_driver max96712_i2c_driver = {
-	.driver	= {
-		.name = "max96712",
-		.of_match_table	= of_match_ptr(max96712_of_table),
-	},
-	.probe = max96712_probe,
-	.remove = max96712_remove,
-};
-
-module_i2c_driver(max96712_i2c_driver);
-
-MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver");
-MODULE_AUTHOR("Niklas S?derlund <niklas.soderlund at ragnatech.se>");
-MODULE_LICENSE("GPL");
-- 
2.48.1



From dmitry.baryshkov at linaro.org  Sun Mar  9 01:19:06 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:19:06 +0200
Subject: [PATCH v5 06/12] phy: rockchip: samsung-hdptx: Drop superfluous
 cfgs driver data
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-6-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-6-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpo_AF6BHCDThNncuH36VHZy1ZJX-=Qj8mj7-UZY41rCuA@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
> phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
> but it is only used during probe() in order to setup ->phy_id.
>
> Use a probe() local variable to store device match data and remove the
> now unnecessary member from struct rk_hdptx_phy.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:22:50 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:22:50 +0200
Subject: [PATCH v5 07/12] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz
 unit conversion overhead
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpoQbvFbNXQ2RB1qY2gHnwZaU-PT-DMLnZkrxkqs2wkXqQ@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> The ropll_tmds_cfg table used to identify the configuration params for
> the supported rates expects the search key, i.e. bit_rate member of
> struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
> Hz).  This requires multiple conversions between these units being
> performed at runtime.
>
> Improve implementation clarity and efficiency by consistently using the
> Hz unit throughout driver's internal data structures and functions.
> Also rename the rather misleading struct member.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
>  1 file changed, 39 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 2bf525514c1991a1299265d12e1e85f66333c604..e58a01bdb3ce82d66acdcb02c06de2816288b574 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -330,7 +330,7 @@ enum dp_link_rate {
>  };
>
>  struct ropll_config {
> -       u32 bit_rate;
> +       u32 rate;

unsigned long long, please, to match the tmds_char_rate type.

>         u8 pms_mdiv;
>         u8 pms_mdiv_afc;
>         u8 pms_pdiv;
> @@ -410,45 +410,45 @@ struct rk_hdptx_phy {
>  };
>
>  static const struct ropll_config ropll_tmds_cfg[] = {
> -       { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 594000000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,

Use ULL suffix

>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 371250000, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 297000000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
> +       { 162000000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 185625000, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
> +       { 154000000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
> +       { 148500000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
>           0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
> +       { 146250000, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
> +       { 119000000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
> +       { 106500000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> +       { 108000000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
> +       { 85500000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
> +       { 83500000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 92812500, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> +       { 74250000, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
> +       { 65000000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
> +       { 33750000, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
>           1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> +       { 40000000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> +       { 27000000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> -       { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
> +       { 25175000, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>  };
>
> @@ -894,10 +894,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
>         regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
>  }
>
> -static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
> +static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,

here and further, unsigned long long
Also, is it tmds_char_rate?

>                                       struct ropll_config *cfg)
>  {
> -       const unsigned int fout = data_rate / 2, fref = 24000;
> +       const unsigned int fout = rate / 200, fref = 24000;
>         unsigned long k = 0, lc, k_sub, lc_sub;
>         unsigned int fvco, sdc;
>         u32 mdiv, sdiv, n = 8;

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:26:32 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:26:32 +0200
Subject: [PATCH v5 08/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-8-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-8-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpoGu4Tq-wt09Jj+b+=eJ3dNXhPWVOg4DyCQxrJbFNFfYw@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> The current workaround to setup the TMDS character rate relies on the
> unconventional usage of phy_set_bus_width().
>
> Make use of the recently introduced HDMI PHY configuration API to
> properly handle the setup.  The workaround will be dropped as soon as
> the switch has been completed on both ends.
>
> Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
> and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
> HDMI parameters during phy_configure().
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 +++++++++++++++++------
>  1 file changed, 47 insertions(+), 17 deletions(-)
>

> @@ -1469,8 +1474,27 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
>         return rk_hdptx_phy_consumer_put(hdptx, false);
>  }
>
> -static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
> -                                     struct phy_configure_opts_dp *dp)
> +static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
> +                                          struct phy_configure_opts_hdmi *hdmi)
> +{
> +       int i;
> +
> +       if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
> +               return -EINVAL;
> +
> +       for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
> +               if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
> +                       break;

return 0;

> +
> +       if (i == ARRAY_SIZE(ropll_tmds_cfg) &&

Then you can drop the first clause in the if

> +           !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int rk_hdptx_phy_verify_dp_config(struct rk_hdptx_phy *hdptx,
> +                                        struct phy_configure_opts_dp *dp)
>  {
>         int i;
>



-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 01:27:00 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 11:27:00 +0200
Subject: [PATCH v5 09/12] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-9-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-9-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpoCMp1Hk7K=OTgR8BW=tncRFTYBKndw9UG-rS3JYyO3gg@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> Implement the phy_ops.validate() callback to allow checking the PHY
> configuration parameters without actually applying them.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From cristian.ciocaltea at collabora.com  Sun Mar  9 03:13:32 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:13:32 +0200
Subject: [PATCH v5 07/12] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz
 unit conversion overhead
In-Reply-To: <CAA8EJpoQbvFbNXQ2RB1qY2gHnwZaU-PT-DMLnZkrxkqs2wkXqQ@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>
 <CAA8EJpoQbvFbNXQ2RB1qY2gHnwZaU-PT-DMLnZkrxkqs2wkXqQ@mail.gmail.com>
Message-ID: <a1a3e86a-1906-4797-932d-8e1aadafedde@collabora.com>

On 3/9/25 11:22 AM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> The ropll_tmds_cfg table used to identify the configuration params for
>> the supported rates expects the search key, i.e. bit_rate member of
>> struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
>> Hz).  This requires multiple conversions between these units being
>> performed at runtime.
>>
>> Improve implementation clarity and efficiency by consistently using the
>> Hz unit throughout driver's internal data structures and functions.
>> Also rename the rather misleading struct member.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
>>  1 file changed, 39 insertions(+), 40 deletions(-)
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 2bf525514c1991a1299265d12e1e85f66333c604..e58a01bdb3ce82d66acdcb02c06de2816288b574 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -330,7 +330,7 @@ enum dp_link_rate {
>>  };
>>
>>  struct ropll_config {
>> -       u32 bit_rate;
>> +       u32 rate;
> 
> unsigned long long, please, to match the tmds_char_rate type.
> 
>>         u8 pms_mdiv;
>>         u8 pms_mdiv_afc;
>>         u8 pms_pdiv;
>> @@ -410,45 +410,45 @@ struct rk_hdptx_phy {
>>  };
>>
>>  static const struct ropll_config ropll_tmds_cfg[] = {
>> -       { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 594000000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> 
> Use ULL suffix
> 
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 371250000, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 297000000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
>> +       { 162000000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
>>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 185625000, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
>> +       { 154000000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
>> +       { 148500000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
>>           0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
>> +       { 146250000, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
>>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
>> +       { 119000000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
>>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
>> +       { 106500000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
>>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>> +       { 108000000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
>> +       { 85500000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
>> +       { 83500000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 92812500, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>> +       { 74250000, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
>> +       { 65000000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
>>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
>> +       { 33750000, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
>>           1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>> +       { 40000000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>> +       { 27000000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
>>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>> -       { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
>> +       { 25175000, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
>>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
>>  };
>>
>> @@ -894,10 +894,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
>>         regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
>>  }
>>
>> -static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
>> +static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,
> 
> here and further, unsigned long long
> Also, is it tmds_char_rate?

Yes, will do the suggested changes in v6.

Thanks,
Cristian


From sdl at nppct.ru  Sun Mar  9 03:14:51 2025
From: sdl at nppct.ru (SDL)
Date: Sun, 9 Mar 2025 13:14:51 +0300
Subject: [PATCH 1/2] arm64: efi: Execute runtime services from a dedicated
 stack
In-Reply-To: <Y8bTM3cbL3x9nhKa@google.com>
Message-ID: <c315940b-dbdb-4acb-b319-d3b0fd53eb0d@nppct.ru>

Dear Linux Kernel Developers,
I have reason to believe that the commit 
4012603cbd469223f225637d265a233f034c567a, which was backported to the 
linux-5.10 branch, is introducing a bug that leads to a kernel crash.

Environment Details:

Kernel Version: linux-5.10.234
Architecture: aarch64
Kernel Configuration: Available at
https://syzkaller.appspot.com/bug?extid=75dc11b3aa0369757b7c
QEMU Version: 8.2.2

QEMU Launch Command:

qemu-system-aarch64 \
     -m 4G \
     -smp 4,sockets=1,cores=4,threads=1 \
     -cpu cortex-a57 \
     -machine virt,accel=tcg \
     -kernel /home/user/lvc/linux-stable/arch/arm64/boot/Image \
     -append "console=ttyS0 root=/dev/vda2 earlyprintk=serial 
net.ifnames=0 rw debug loglevel=8" \
     -drive 
file=/home/user/lvc/image/disk.raw,format=raw,if=virtio,index=1 \
     -bios /usr/share/AAVMF/AAVMF_CODE.fd \
     -netdev user,id=net0,hostfwd=tcp::10022-:22 \
     -device virtio-net-device,netdev=net0 \
     -nographic

Steps to Reproduce:

mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t efivarfs efivarfs /sys/firmware/efi/efivars
tools/testing/selftests/efivarfs/efivarfs.sh

Crash log:

[  101.403235][   T38] Unable to handle kernel paging request at virtual 
address ffffa00023b20000
[  101.403905][   T38] Mem abort info:
[  101.404159][   T38]   ESR = 0x96000047
[  101.404448][   T38]   EC = 0x25: DABT (current EL), IL = 32 bits
[  101.404748][   T38]   SET = 0, FnV = 0
[  101.404988][   T38]   EA = 0, S1PTW = 0
[  101.405233][   T38] Data abort info:
[  101.405469][   T38]   ISV = 0, ISS = 0x00000047
[  101.405721][   T38]   CM = 0, WnR = 1
[  101.406070][   T38] swapper pgtable: 4k pages, 48-bit VAs, 
pgdp=0000000103336000
[  101.406415][   T38] [ffffa00023b20000] pgd=000000013ffff003, 
p4d=000000013ffff003, pud=000000013fffe003, pmd=000000013fff9003, 
pte=0000000000000000
[  101.407997][   T38] Internal error: Oops: 0000000096000047 [#1] 
PREEMPT SMP
[  101.408446][   T38] Modules linked in:
[  101.409010][   T38] CPU: 1 PID: 38 Comm: kworker/u8:2 Not tainted 
5.10.234 #61
[  101.409376][   T38] Hardware name: QEMU QEMU Virtual Machine, BIOS 
2024.02-2ubuntu0.1 10/25/2024
[  101.410689][   T38] Workqueue: efi_rts_wq efi_call_rts
[  101.411219][   T38] pstate: 000003c5 (nzcv DAIF -PAN -UAO -TCO BTYPE=--)
[  101.411574][   T38] pc : el1_sync+0xc/0x140
[  101.411930][   T38] lr : 0x0
[  101.412132][   T38] sp : ffffa00023b1ffd0
[  101.412363][   T38] x29: 0000000000000000 x28: ffff0000cc741a80
[  101.412761][   T38] x27: 0000000000000001 x26: 0000000000e800e8
[  101.413117][   T38] x25: 0000000000800080 x24: ffff940004765298
[  101.413465][   T38] x23: 00000000100003c5 x22: ffffa00018c95600
[  101.413809][   T38] x21: ffffa0001923a980 x20: ffffa00018d30380
[  101.414170][   T38] x19: ffffa0001bab8008 x18: 1fffe000198e8491
[  101.414515][   T38] x17: 0000000000000000 x16: ffffa000102a26c0
[  101.414882][   T38] x15: 0000000000000001 x14: ffff0000ccf34400
[  101.415277][   T38] x13: 000000000000003c x12: ffff0000ccf34000
[  101.415656][   T38] x11: 0000000000000018 x10: 0000000000000054
[  101.416072][   T38] x9 : 4fc79849210be57c x8 : 11d293ca8be4df61
[  101.416446][   T38] x7 : 0000000041b58ab3 x6 : ffff94000476522a
[  101.416820][   T38] x5 : 0000002200000000 x4 : 0000000200000000
[  101.417190][   T38] x3 : 1fffe000198e8352 x2 : ffffa0001923a820
[  101.417560][   T38] x1 : ffff0000cc741a80 x0 : 0000000000000000
[  101.418109][   T38] Call trace:
[  101.418601][   T38] Code: d503201f a90007e0 a9010fe2 a90217e4 (a9031fe6)
[  101.419579][   T38] ---[ end trace 61316cddfdbbcb95 ]---
[  103.623221][   T38] Kernel panic - not syncing: Oops: Fatal exception
[  103.623723][   T38] SMP: stopping secondary CPUs
[  105.221708][   T38] SMP: failed to stop secondary CPUs 0-3
[  105.222306][   T38] Kernel Offset: disabled
[  105.222711][   T38] CPU features: 0x28240022,61002082
[  105.222969][   T38] Memory Limit: none

I identified this commit as the potential cause of the crash using git 
bisect. The issue is reproducible with the above setup and 
configuration. If you need more details or logs, I am more than willing 
to provide them. Thank you for your attention to this matter.

Best regards,

Alexey Nepomnyashih


From cristian.ciocaltea at collabora.com  Sun Mar  9 03:15:24 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:15:24 +0200
Subject: [PATCH v5 08/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <CAA8EJpoGu4Tq-wt09Jj+b+=eJ3dNXhPWVOg4DyCQxrJbFNFfYw@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-8-35087287f9d1@collabora.com>
 <CAA8EJpoGu4Tq-wt09Jj+b+=eJ3dNXhPWVOg4DyCQxrJbFNFfYw@mail.gmail.com>
Message-ID: <6caefe9f-1b15-41c1-94f2-9a2a92aeec67@collabora.com>

On 3/9/25 11:26 AM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> The current workaround to setup the TMDS character rate relies on the
>> unconventional usage of phy_set_bus_width().
>>
>> Make use of the recently introduced HDMI PHY configuration API to
>> properly handle the setup.  The workaround will be dropped as soon as
>> the switch has been completed on both ends.
>>
>> Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
>> and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
>> HDMI parameters during phy_configure().
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 +++++++++++++++++------
>>  1 file changed, 47 insertions(+), 17 deletions(-)
>>
> 
>> @@ -1469,8 +1474,27 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
>>         return rk_hdptx_phy_consumer_put(hdptx, false);
>>  }
>>
>> -static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
>> -                                     struct phy_configure_opts_dp *dp)
>> +static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>> +                                          struct phy_configure_opts_hdmi *hdmi)
>> +{
>> +       int i;
>> +
>> +       if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>> +               return -EINVAL;
>> +
>> +       for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
>> +               if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
>> +                       break;
> 
> return 0;
> 
>> +
>> +       if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
> 
> Then you can drop the first clause in the if

Sure, will do!

Thanks,
Cristian


From dmitry.baryshkov at linaro.org  Sun Mar  9 03:17:20 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 12:17:20 +0200
Subject: [PATCH v5 11/12] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-11-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-11-35087287f9d1@collabora.com>
Message-ID: <CAA8EJpqzZaRoQ5mDeKUHpNhYsegC=V6c2SQpKaQn4FYhozQn1A@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> Drop the rate parameter from a bunch of internal helpers and, instead,
> make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
> data.
>
> Additionally, rename the rather ambiguous ->rate member of struct
> rk_hdptx_phy to ->hw_rate and ensure rk_hdptx_ropll_tmds_cmn_config()

Would it be better to name it tmds_char_rate?

> updates it only after all the other operations have been successful.

Please don't mix refactoring / renames and the actual code changes.

>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 59 ++++++++++++-----------
>  1 file changed, 30 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index a62c634f5254e742088515c3b21c05f95acbaded..98f831c3704f5cd65dcf29a4f0a12862a4aa0482 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -401,7 +401,7 @@ struct rk_hdptx_phy {
>
>         /* clk provider */
>         struct clk_hw hw;
> -       unsigned long rate;
> +       unsigned long hw_rate;
>         bool restrict_rate_change;
>
>         atomic_t usage_count;
> @@ -968,33 +968,34 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,
>         return true;
>  }
>
> -static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
> -                                         unsigned long rate)
> +static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
>  {
>         const struct ropll_config *cfg = NULL;
>         struct ropll_config rc = {0};
> -       int i;
> +       int ret, i;
>
> -       hdptx->rate = rate;
> +       if (!hdptx->hdmi_cfg.tmds_char_rate)
> +               return 0;
>
>         for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
> -               if (rate == ropll_tmds_cfg[i].rate) {
> +               if (hdptx->hdmi_cfg.tmds_char_rate == ropll_tmds_cfg[i].rate) {
>                         cfg = &ropll_tmds_cfg[i];
>                         break;
>                 }
>
>         if (!cfg) {
> -               if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
> -                       cfg = &rc;
> -               } else {
> -                       dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
> +               if (!rk_hdptx_phy_clk_pll_calc(hdptx->hdmi_cfg.tmds_char_rate, &rc)) {
> +                       dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%llu\n",
> +                               __func__, hdptx->hdmi_cfg.tmds_char_rate);
>                         return -EINVAL;
>                 }
> +
> +               cfg = &rc;
>         }
>
> -       dev_dbg(hdptx->dev, "%s rate=%lu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
> -               __func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
> -               cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
> +       dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
> +               __func__, hdptx->hdmi_cfg.tmds_char_rate, cfg->pms_mdiv, cfg->pms_sdiv + 1,
> +               cfg->sdm_en, cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
>
>         rk_hdptx_pre_power_up(hdptx);
>
> @@ -1030,17 +1031,20 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
>         regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
>                            FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
>
> -       return rk_hdptx_post_enable_pll(hdptx);
> +       ret = rk_hdptx_post_enable_pll(hdptx);
> +       if (!ret)
> +               hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate;
> +
> +       return ret;
>  }
>
> -static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
> -                                          unsigned long rate)
> +static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx)
>  {
>         rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
>
>         regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
>
> -       if (rate > HDMI14_MAX_RATE) {
> +       if (hdptx->hdmi_cfg.tmds_char_rate > HDMI14_MAX_RATE) {
>                 /* For 1/40 bitrate clk */
>                 rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
>         } else {
> @@ -1092,8 +1096,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
>                      HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
>  }
>
> -static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
> -                                    unsigned long rate)
> +static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
>  {
>         enum phy_mode mode = phy_get_mode(hdptx->phy);
>         u32 status;
> @@ -1112,11 +1115,9 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
>         if (mode == PHY_MODE_DP) {
>                 rk_hdptx_dp_reset(hdptx);
>         } else {
> -               if (rate) {
> -                       ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
> -                       if (ret)
> -                               goto dec_usage;
> -               }
> +               ret = rk_hdptx_ropll_tmds_cmn_config(hdptx);
> +               if (ret)
> +                       goto dec_usage;
>         }
>
>         return 0;
> @@ -1429,7 +1430,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
>                 dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
>         }
>
> -       ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
> +       ret = rk_hdptx_phy_consumer_get(hdptx);
>         if (ret)
>                 return ret;
>
> @@ -1460,7 +1461,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
>                 regmap_write(hdptx->grf, GRF_HDPTX_CON0,
>                              HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
>
> -               ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
> +               ret = rk_hdptx_ropll_tmds_mode_config(hdptx);
>                 if (ret)
>                         rk_hdptx_phy_consumer_put(hdptx, true);
>         }
> @@ -1828,7 +1829,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
>  {
>         struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
>
> -       return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
> +       return rk_hdptx_phy_consumer_get(hdptx);
>  }
>
>  static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
> @@ -1843,7 +1844,7 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
>  {
>         struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
>
> -       return hdptx->rate;
> +       return hdptx->hw_rate;
>  }
>
>  static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> @@ -1895,7 +1896,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
>          * while the latter being executed only once, i.e. when clock remains
>          * in the prepared state during rate changes.
>          */
> -       return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
> +       return rk_hdptx_ropll_tmds_cmn_config(hdptx);
>  }
>
>  static const struct clk_ops hdptx_phy_clk_ops = {
>
> --
> 2.48.1
>


-- 
With best wishes
Dmitry


From cristian.ciocaltea at collabora.com  Sun Mar  9 03:17:36 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:17:36 +0200
Subject: [PATCH v5 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <CAA8EJprNTUuOwu__GcRhYmNi5rT0+3r16fs+n7Gdy3sjgTp+nw@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>
 <CAA8EJprBcGz0tZ5SDVC_WK2bzjXZAtOj+LfGnSxmwktvaQw=VQ@mail.gmail.com>
 <f1e33b02-5646-4219-98ac-c09e31d8215b@collabora.com>
 <CAA8EJprNTUuOwu__GcRhYmNi5rT0+3r16fs+n7Gdy3sjgTp+nw@mail.gmail.com>
Message-ID: <f7fdf5de-90aa-4753-9500-c30339545adf@collabora.com>

On 3/9/25 12:12 PM, Dmitry Baryshkov wrote:
> On Sun, 9 Mar 2025 at 12:11, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> On 3/9/25 11:17 AM, Dmitry Baryshkov wrote:
>>> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
>>> <cristian.ciocaltea at collabora.com> wrote:
>>>>
>>>> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
>>>> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
>>>> and not before.
>>>
>>> Am I correct that the only functional change is a switch from
>>> greater-or-equal to simple greater?
>>
>> Yes.
> 
> If you were to repost the series for any reason, could you please
> spell that explicitly in the commit message. If not, it's fine.

Sure, I'll handle it in v6.

> 
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Thanks,
Cristian
 



From cristian.ciocaltea at collabora.com  Sun Mar  9 03:10:06 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:10:06 +0200
Subject: [PATCH v5 02/12] phy: hdmi: Add color depth configuration
In-Reply-To: <CAA8EJpqYE1drM6=C0AwPZ-e5RkWqjMTpWQiwhA64qby1mmVL1Q@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-2-35087287f9d1@collabora.com>
 <CAA8EJpqYE1drM6=C0AwPZ-e5RkWqjMTpWQiwhA64qby1mmVL1Q@mail.gmail.com>
Message-ID: <22142c86-c8b5-4427-9764-a7daa4a005b1@collabora.com>

Hi Dmitry,

On 3/9/25 11:16 AM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> Extend the HDMI configuration options to allow managing bits per color
>> channel.  This is required by some PHY drivers such as
>> rockchip-samsung-hdptx.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  include/linux/phy/phy-hdmi.h | 2 ++
>>  1 file changed, 2 insertions(+)
>>
> 
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Just to confirm, are you passing TMDS char rate or pixel clock for
> DeepColor (bpc > 8) modes?

It's the TMDS char rate, but we still need the bpc info to program
CMN_REG(0086) in PATCH 12.

Thanks for reviewing,
Cristian


From dmitry.baryshkov at linaro.org  Sun Mar  9 03:10:43 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 12:10:43 +0200
Subject: [PATCH v5 02/12] phy: hdmi: Add color depth configuration
In-Reply-To: <22142c86-c8b5-4427-9764-a7daa4a005b1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-2-35087287f9d1@collabora.com>
 <CAA8EJpqYE1drM6=C0AwPZ-e5RkWqjMTpWQiwhA64qby1mmVL1Q@mail.gmail.com> <22142c86-c8b5-4427-9764-a7daa4a005b1@collabora.com>
Message-ID: <CAA8EJpqCUWH95Ew57K_HKmPGhf40G_2n09SWKTonvyUn2vE4oQ@mail.gmail.com>

On Sun, 9 Mar 2025 at 12:10, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> Hi Dmitry,
>
> On 3/9/25 11:16 AM, Dmitry Baryshkov wrote:
> > On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> > <cristian.ciocaltea at collabora.com> wrote:
> >>
> >> Extend the HDMI configuration options to allow managing bits per color
> >> channel.  This is required by some PHY drivers such as
> >> rockchip-samsung-hdptx.
> >>
> >> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> >> ---
> >>  include/linux/phy/phy-hdmi.h | 2 ++
> >>  1 file changed, 2 insertions(+)
> >>
> >
> > Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> >
> > Just to confirm, are you passing TMDS char rate or pixel clock for
> > DeepColor (bpc > 8) modes?
>
> It's the TMDS char rate, but we still need the bpc info to program
> CMN_REG(0086) in PATCH 12.

Thanks for the confirmation.

-- 
With best wishes
Dmitry


From cristian.ciocaltea at collabora.com  Sun Mar  9 03:11:13 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:11:13 +0200
Subject: [PATCH v5 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <CAA8EJprBcGz0tZ5SDVC_WK2bzjXZAtOj+LfGnSxmwktvaQw=VQ@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>
 <CAA8EJprBcGz0tZ5SDVC_WK2bzjXZAtOj+LfGnSxmwktvaQw=VQ@mail.gmail.com>
Message-ID: <f1e33b02-5646-4219-98ac-c09e31d8215b@collabora.com>

On 3/9/25 11:17 AM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
>> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
>> and not before.
> 
> Am I correct that the only functional change is a switch from
> greater-or-equal to simple greater?

Yes.


From dmitry.baryshkov at linaro.org  Sun Mar  9 03:12:21 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 12:12:21 +0200
Subject: [PATCH v5 03/12] phy: rockchip: samsung-hdptx: Fix clock ratio setup
In-Reply-To: <f1e33b02-5646-4219-98ac-c09e31d8215b@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-3-35087287f9d1@collabora.com>
 <CAA8EJprBcGz0tZ5SDVC_WK2bzjXZAtOj+LfGnSxmwktvaQw=VQ@mail.gmail.com> <f1e33b02-5646-4219-98ac-c09e31d8215b@collabora.com>
Message-ID: <CAA8EJprNTUuOwu__GcRhYmNi5rT0+3r16fs+n7Gdy3sjgTp+nw@mail.gmail.com>

On Sun, 9 Mar 2025 at 12:11, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> On 3/9/25 11:17 AM, Dmitry Baryshkov wrote:
> > On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> > <cristian.ciocaltea at collabora.com> wrote:
> >>
> >> The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
> >> 340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
> >> and not before.
> >
> > Am I correct that the only functional change is a switch from
> > greater-or-equal to simple greater?
>
> Yes.

If you were to repost the series for any reason, could you please
spell that explicitly in the commit message. If not, it's fine.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Sun Mar  9 03:18:04 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 12:18:04 +0200
Subject: [PATCH v5 12/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250308-phy-sam-hdptx-bpc-v5-12-35087287f9d1@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com> <20250308-phy-sam-hdptx-bpc-v5-12-35087287f9d1@collabora.com>
Message-ID: <CAA8EJppo29p+8a5VUbr6dwaE9ywgS+-VcuUH_sF+NdA0xGU1Zw@mail.gmail.com>

On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>

Reviewed-by: Dmitry Baryshkov <dmtiry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From cristian.ciocaltea at collabora.com  Sun Mar  9 03:32:41 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Sun, 9 Mar 2025 12:32:41 +0200
Subject: [PATCH v5 11/12] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <CAA8EJpqzZaRoQ5mDeKUHpNhYsegC=V6c2SQpKaQn4FYhozQn1A@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-11-35087287f9d1@collabora.com>
 <CAA8EJpqzZaRoQ5mDeKUHpNhYsegC=V6c2SQpKaQn4FYhozQn1A@mail.gmail.com>
Message-ID: <884acd6e-4936-4b00-88ed-cbccc10efc9c@collabora.com>

On 3/9/25 12:17 PM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> Drop the rate parameter from a bunch of internal helpers and, instead,
>> make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
>> data.
>>
>> Additionally, rename the rather ambiguous ->rate member of struct
>> rk_hdptx_phy to ->hw_rate and ensure rk_hdptx_ropll_tmds_cmn_config()
> 
> Would it be better to name it tmds_char_rate?

This is only used in rk_hdptx_phy_clk_recalc_rate() to provide the
actual rate programmed in hardware, hence the "hw_rate" naming.
Renaming it to tmds_char_rate might add some confusion with the similar
one in ->hdmi_cfg, but I don't really have any strong preference here.

>> updates it only after all the other operations have been successful.
> 
> Please don't mix refactoring / renames and the actual code changes.

Right, I should have moved that to a dedicated patch.  Will handle in
the next revision.

Thanks,
Cristian


From dmitry.baryshkov at linaro.org  Sun Mar  9 03:33:26 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Sun, 9 Mar 2025 12:33:26 +0200
Subject: [PATCH v5 11/12] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <884acd6e-4936-4b00-88ed-cbccc10efc9c@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-11-35087287f9d1@collabora.com>
 <CAA8EJpqzZaRoQ5mDeKUHpNhYsegC=V6c2SQpKaQn4FYhozQn1A@mail.gmail.com> <884acd6e-4936-4b00-88ed-cbccc10efc9c@collabora.com>
Message-ID: <CAA8EJpqDiK37uLid2ap0E=Sa+DU9vOmSf6WBUe4ZeVKj9mVODg@mail.gmail.com>

On Sun, 9 Mar 2025 at 12:32, Cristian Ciocaltea
<cristian.ciocaltea at collabora.com> wrote:
>
> On 3/9/25 12:17 PM, Dmitry Baryshkov wrote:
> > On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> > <cristian.ciocaltea at collabora.com> wrote:
> >>
> >> Drop the rate parameter from a bunch of internal helpers and, instead,
> >> make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
> >> data.
> >>
> >> Additionally, rename the rather ambiguous ->rate member of struct
> >> rk_hdptx_phy to ->hw_rate and ensure rk_hdptx_ropll_tmds_cmn_config()
> >
> > Would it be better to name it tmds_char_rate?
>
> This is only used in rk_hdptx_phy_clk_recalc_rate() to provide the
> actual rate programmed in hardware, hence the "hw_rate" naming.

Ack

> Renaming it to tmds_char_rate might add some confusion with the similar
> one in ->hdmi_cfg, but I don't really have any strong preference here.
>
> >> updates it only after all the other operations have been successful.
> >
> > Please don't mix refactoring / renames and the actual code changes.
>
> Right, I should have moved that to a dedicated patch.  Will handle in
> the next revision.
>
> Thanks,
> Cristian



-- 
With best wishes
Dmitry


From john.madieu.xa at bp.renesas.com  Sun Mar  9 03:39:27 2025
From: john.madieu.xa at bp.renesas.com (John Madieu)
Date: Sun, 9 Mar 2025 10:39:27 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <20250307-barbell-pretzel-368d6a4d1336@spud>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
 <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-barbell-pretzel-368d6a4d1336@spud>
Message-ID: <OSBPR01MB2775D121B55A0C543F251BAEFFD72@OSBPR01MB2775.jpnprd01.prod.outlook.com>

Hi Conor,

> -----Original Message-----
> From: Conor Dooley <conor at kernel.org>
> Sent: Friday, March 7, 2025 5:04 PM
> To: John Madieu <john.madieu.xa at bp.renesas.com>
> Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> the TSU unit
> 
> On Fri, Mar 07, 2025 at 03:55:27PM +0000, John Madieu wrote:
> > Hi Conor,
> >
> > > > > > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > > > > > ---
> > > > > > v1 -> v2:
> > > > > >  * Fix reg property specifier to get rid of yamlint warnings
> > > > > >  * Fix IRQ name to reflect TSU expectations
> > > > > >
> > > > > > +    enum: [0, 1]
> > > > > > +    description: |
> > > > > > +      TSU operating mode:
> > > > > > +      0: Mode 0 - Conversion started by software
> > > > > > +      1: Mode 1 - Conversion started by ELC trigger
> > > > >
> > > > > Can you make this "software" and "elc" or something please,
> > > > > unless people will genuinely find "0" and 1" to be more
> informative.
> > > > > And why doesn't the property have a default?
> > > >
> > > > Sorry for miss-specifying.
> > > > ELC is an external event trigger. May be should I specify it like
> that ?
> > >
> > > If "elc trigger" is meaningful to people using hte device (IOW, it
> > > matches datasheet wording) then that's fine I think.
> >
> > "elc trigger" matches datasheet wording.
> >
> > >
> > > > To make sure I got your point, do you mean specifying a default
> > > > value in bindings ?
> > >
> > > The property doesn't actually need to be required, it could easily
> > > have a default (say software) and only be set in the case of using
> > > the elc trigger - which brings you to Rob's comment that it can just
> > > be a boolean, setting the property if elc and leaving it out of
> software.
> >
> > Got the point now. I can make it default to software trigger, and add
> > optional Boolean property to ELC trigger. Let's say "renesas,elc-
> trigger;"
> 
> Yah, that works.
> 
> >
> > >
> > > Rob's other comment was
> > >
> > > | Who/what decides the mode? If a user is going to want to change
> > > | this, then it should be a runtime control, not a DT property.
> >
> > Changes are not possible at runtime. Some customers may want software,
> > while other may want the external trigger, and this is immutable
> > configuration.
> 
> What makes it immutable? Set by some wiring on the board? I couldn't find
> the user in your driver patches to better understand how you were using
> it.

I haven't prototyped ELC trigger yet. Since the hardware manual
describes about ELC trigger, I have documented it in bindings. If you
think, it is not needed at this stage, then I can drop it now and
revisit later.

Regards,
John


From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:42 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:42 -0400
Subject: [PATCH iwl-next v9 08/14] igc: use FIELD_PREP and GENMASK for existing RX packet buffer size
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-9-faizal.abdul.rahim@linux.intel.com>

Prepare for an upcoming patch that modifies the RX buffer size in TSN mode.
Refactor IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN using
FIELD_PREP and GENMASK to improve clarity and maintainability. Refactor
both macros for consistency, even though the upcoming patch only use
IGC_RXPBSIZE_EXP_BMC_DEFAULT.

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

I've tested IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN before
and after the refactoring, and their values remain unchanged.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index db937931c646..3564d15df57b 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -396,9 +396,20 @@
 #define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
 #define IGC_RCTL_SECRC		0x04000000 /* Strip Ethernet CRC */
 
-/* RXPBSIZE default value for Express and BMC buffer */
-#define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
-#define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
+/* Mask for RX packet buffer size */
+#define IGC_RXPBSIZE_EXP_MASK		GENMASK(5, 0)
+#define IGC_BMC2OSPBSIZE_MASK		GENMASK(11, 6)
+/* Mask for timestamp in RX buffer */
+#define IGC_RXPBS_CFG_TS_EN_MASK	GENMASK(31, 31)
+/* High-priority RX packet buffer size (KB). Used for Express traffic when preemption is enabled */
+#define IGC_RXPBSIZE_EXP(x)		FIELD_PREP(IGC_RXPBSIZE_EXP_MASK, (x))
+/* BMC to OS packet buffer size in KB */
+#define IGC_BMC2OSPBSIZE(x)		FIELD_PREP(IGC_BMC2OSPBSIZE_MASK, (x))
+/* Enable RX packet buffer for timestamp descriptor, saving 16 bytes per packet if set */
+#define IGC_RXPBS_CFG_TS_EN		FIELD_PREP(IGC_RXPBS_CFG_TS_EN_MASK, 1)
+/* Default value following I225/I226 SW User Manual Section 8.3.1 */
+#define IGC_RXPBSIZE_EXP_BMC_DEFAULT ( \
+	IGC_RXPBSIZE_EXP(34) | IGC_BMC2OSPBSIZE(2))
 
 /* Mask for TX packet buffer size */
 #define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:43 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:43 -0400
Subject: [PATCH iwl-next v9 09/14] igc: set the RX packet buffer size for TSN mode
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-10-faizal.abdul.rahim@linux.intel.com>

In preparation for supporting frame preemption, when entering TSN mode,
set the receive packet buffer to 15KB for the Express MAC, 15KB for
the Preemptible MAC and 2KB for the BMC.

References:
I225/I226 SW User Manual, Section 4.7.9, Section 7.1.3.2, Section 8.3.1

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h |  5 ++++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 25 ++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 3564d15df57b..d753a8ec36ae 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -399,17 +399,22 @@
 /* Mask for RX packet buffer size */
 #define IGC_RXPBSIZE_EXP_MASK		GENMASK(5, 0)
 #define IGC_BMC2OSPBSIZE_MASK		GENMASK(11, 6)
+#define IGC_RXPBSIZE_BE_MASK		GENMASK(17, 12)
 /* Mask for timestamp in RX buffer */
 #define IGC_RXPBS_CFG_TS_EN_MASK	GENMASK(31, 31)
 /* High-priority RX packet buffer size (KB). Used for Express traffic when preemption is enabled */
 #define IGC_RXPBSIZE_EXP(x)		FIELD_PREP(IGC_RXPBSIZE_EXP_MASK, (x))
 /* BMC to OS packet buffer size in KB */
 #define IGC_BMC2OSPBSIZE(x)		FIELD_PREP(IGC_BMC2OSPBSIZE_MASK, (x))
+/* Low-priority RX packet buffer size (KB). Used for BE traffic when preemption is enabled */
+#define IGC_RXPBSIZE_BE(x)		FIELD_PREP(IGC_RXPBSIZE_BE_MASK, (x))
 /* Enable RX packet buffer for timestamp descriptor, saving 16 bytes per packet if set */
 #define IGC_RXPBS_CFG_TS_EN		FIELD_PREP(IGC_RXPBS_CFG_TS_EN_MASK, 1)
 /* Default value following I225/I226 SW User Manual Section 8.3.1 */
 #define IGC_RXPBSIZE_EXP_BMC_DEFAULT ( \
 	IGC_RXPBSIZE_EXP(34) | IGC_BMC2OSPBSIZE(2))
+#define IGC_RXPBSIZE_EXP_BMC_BE_TSN ( \
+	IGC_RXPBSIZE_EXP(15) | IGC_BMC2OSPBSIZE(2) | IGC_RXPBSIZE_BE(15))
 
 /* Mask for TX packet buffer size */
 #define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 498741d83ca6..5b3b1bc0b64a 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -125,6 +125,27 @@ static void igc_tsn_tx_arb(struct igc_adapter *adapter, u16 *queue_per_tc)
 	wr32(IGC_TXARB, txarb);
 }
 
+/**
+ * igc_tsn_set_rxpbsize - Set the receive packet buffer size
+ * @adapter: Pointer to the igc_adapter structure
+ * @rxpbs_exp_bmc_be: Value to set the receive packet buffer size, including
+ *                    express buffer, BMC buffer, and Best Effort buffer
+ *
+ * The IGC_RXPBS register value may include allocations for the Express buffer,
+ * BMC buffer, Best Effort buffer, and the timestamp descriptor buffer (IGC_RXPBS_CFG_TS_EN).
+ */
+static void igc_tsn_set_rxpbsize(struct igc_adapter *adapter, u32 rxpbs_exp_bmc_be)
+{
+	struct igc_hw *hw = &adapter->hw;
+	u32 rxpbs = rd32(IGC_RXPBS);
+
+	rxpbs &= ~(IGC_RXPBSIZE_EXP_MASK | IGC_BMC2OSPBSIZE_MASK |
+		   IGC_RXPBSIZE_BE_MASK);
+	rxpbs |= rxpbs_exp_bmc_be;
+
+	wr32(IGC_RXPBS, rxpbs);
+}
+
 /* Returns the TSN specific registers to their default values after
  * the adapter is reset.
  */
@@ -139,6 +160,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
+	igc_tsn_set_rxpbsize(adapter, IGC_RXPBSIZE_EXP_BMC_DEFAULT);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_restore_retx_default(adapter);
 
@@ -202,6 +225,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
 
+	igc_tsn_set_rxpbsize(adapter, IGC_RXPBSIZE_EXP_BMC_BE_TSN);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_set_retx_qbvfullthreshold(adapter);
 
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:44 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:44 -0400
Subject: [PATCH iwl-next v9 10/14] igc: add support for frame preemption verification
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-11-faizal.abdul.rahim@linux.intel.com>

This patch implements the "ethtool --set-mm" callback to trigger the
frame preemption verification handshake.

Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool
to perform the verification handshake for igc.
The structure fpe.mmsv is set by mmsv in ethtool and should remain
read-only for the driver.

Other mmsv callbacks:
a) configure_tx() -> not used yet at this point
   - igc lacks registers to configure FPE in the transmit direction, so
     this API is not utilized for now. When igc supports preemptible queue,
     driver will use this API to manage its configuration.

b) configure_pmac() -> not used
   - this callback dynamically controls pmac_enabled at runtime. For
     example, mmsv calls configure_pmac() and disables pmac_enabled when
     the link partner goes down, even if the user previously enabled it.
     The intention is to save power but it is not feasible in igc
     because it causes an endless adapter reset loop:

   1) Board A and Board B complete the verification handshake. Tx mode
      register for both boards are in TSN mode.
   2) Board B link goes down.

   On Board A:
   3) mmsv calls configure_pmac() with pmac_enabled = false.
   4) configure_pmac() in igc updates a new field based on pmac_enabled.
      Driver uses this field in igc_tsn_new_flags() to indicate that the
      user enabled/disabled FPE.
   5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
      whether an adapter reset is needed. Calls existing logic in
      igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
   6) Since pmac_enabled is now disabled and no other TSN feature is
      active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
      mode will switch from TSN to Legacy.
   7) Driver resets the adapter.
   8) Registers are set, and Tx mode switches to Legacy.
   9) When link partner is up, steps 3?8 repeat, but this time with
      pmac_enabled = true, reactivating TSN.
      igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
      mode will switch from Legacy to TSN.
  10) Driver resets the adapter.
  11) Adapter reset completes, registers are set, and Tx mode switches to
      TSN.

  On Board B:
  12) Adapter reset on Board A at step 10 causes it to detect its link
      partner as down.
  13) Repeats steps 3?8.
  14) Once reset adapter on Board A is completed at step 11, it detects
      its link partner as up.
  15) Repeats steps 9?11.

   - this cycle repeats indefinitely. To avoid this issue, igc only uses
     mmsv.pmac_enabled to track whether FPE is enabled or disabled.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  12 +-
 drivers/net/ethernet/intel/igc/igc_base.h    |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |   8 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  21 +++
 drivers/net/ethernet/intel/igc/igc_main.c    |  52 ++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 146 ++++++++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  50 +++++++
 7 files changed, 285 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index ba7c55d2dc85..d970968f3233 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -40,6 +40,10 @@ void igc_ethtool_set_ops(struct net_device *);
 
 #define IGC_MAX_TX_TSTAMP_REGS		4
 
+struct igc_fpe_t {
+	struct ethtool_mmsv mmsv;
+};
+
 enum igc_mac_filter_type {
 	IGC_MAC_FILTER_TYPE_DST = 0,
 	IGC_MAC_FILTER_TYPE_SRC
@@ -332,6 +336,8 @@ struct igc_adapter {
 		struct timespec64 period;
 	} perout[IGC_N_PEROUT];
 
+	struct igc_fpe_t fpe;
+
 	/* LEDs */
 	struct mutex led_mutex;
 	struct igc_led_classdev *leds;
@@ -389,10 +395,11 @@ extern char igc_driver_name[];
 #define IGC_FLAG_TSN_QBV_ENABLED	BIT(17)
 #define IGC_FLAG_TSN_QAV_ENABLED	BIT(18)
 #define IGC_FLAG_TSN_LEGACY_ENABLED	BIT(19)
+#define IGC_FLAG_TSN_PREEMPT_ENABLED	BIT(20)
 
 #define IGC_FLAG_TSN_ANY_ENABLED				\
 	(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED |	\
-	 IGC_FLAG_TSN_LEGACY_ENABLED)
+	 IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)
 
 #define IGC_FLAG_RSS_FIELD_IPV4_UDP	BIT(6)
 #define IGC_FLAG_RSS_FIELD_IPV6_UDP	BIT(7)
@@ -737,7 +744,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter);
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter);
 struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
+void igc_flush_tx_descriptors(struct igc_ring *ring);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h
index bf8cdfbba9ff..6320eabb72fe 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.h
+++ b/drivers/net/ethernet/intel/igc/igc_base.h
@@ -49,6 +49,7 @@ struct igc_adv_tx_context_desc {
 #define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
 #define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
 #define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
+#define IGC_ADVTXD_PAYLEN_MASK	0XFFFFC000 /* Adv desc PAYLEN mask */
 #define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */
 
 #define IGC_RAR_ENTRIES		16
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index d753a8ec36ae..542c7c8802a0 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -308,6 +308,8 @@
 #define IGC_TXD_DTYP_C		0x00000000 /* Context Descriptor */
 #define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
 #define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
+#define IGC_TXD_POPTS_SMD_MASK	0x3000     /* Indicates whether it's SMD-V or SMD-R */
+
 #define IGC_TXD_CMD_EOP		0x01000000 /* End of Packet */
 #define IGC_TXD_CMD_IC		0x04000000 /* Insert Checksum */
 #define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
@@ -363,6 +365,8 @@
 #define IGC_SRRCTL_TIMER0SEL(timer)	(((timer) & 0x3) << 17)
 
 /* Receive Descriptor bit definitions */
+#define IGC_RXD_STAT_SMD_TYPE_V	0x01	/* SMD-V Packet */
+#define IGC_RXD_STAT_SMD_TYPE_R	0x02	/* SMD-R Packet */
 #define IGC_RXD_STAT_EOP	0x02	/* End of Packet */
 #define IGC_RXD_STAT_IXSM	0x04	/* Ignore checksum */
 #define IGC_RXD_STAT_UDPCS	0x10	/* UDP xsum calculated */
@@ -372,7 +376,8 @@
 #define IGC_RXDEXT_STATERR_LB	0x00040000
 
 /* Advanced Receive Descriptor bit definitions */
-#define IGC_RXDADV_STAT_TSIP	0x08000 /* timestamp in packet */
+#define IGC_RXDADV_STAT_SMD_TYPE_MASK	0x06000
+#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */
 
 #define IGC_RXDEXT_STATERR_L4E		0x20000000
 #define IGC_RXDEXT_STATERR_IPE		0x40000000
@@ -575,6 +580,7 @@
 
 /* Transmit Scheduling */
 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
+#define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
 
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 817838677817..b64d5c6c1d20 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -8,6 +8,7 @@
 
 #include "igc.h"
 #include "igc_diag.h"
+#include "igc_tsn.h"
 
 /* forward declaration */
 struct igc_stats {
@@ -1781,6 +1782,25 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_set_mm(struct net_device *netdev,
+			      struct ethtool_mm_cfg *cmd,
+			      struct netlink_ext_ack *extack)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
+		if (cmd->pmac_enabled)
+			static_branch_inc(&igc_fpe_enabled);
+		else
+			static_branch_dec(&igc_fpe_enabled);
+	}
+
+	ethtool_mmsv_set_mm(&fpe->mmsv, cmd);
+
+	return igc_tsn_offload_apply(adapter);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2076,6 +2096,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.set_mm			= igc_ethtool_set_mm,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 6f0110e3ac22..71c377cb7a88 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2548,7 +2548,7 @@ static int igc_xdp_run_prog(struct igc_adapter *adapter, struct xdp_buff *xdp)
 }
 
 /* This function assumes __netif_tx_lock is held by the caller. */
-static void igc_flush_tx_descriptors(struct igc_ring *ring)
+void igc_flush_tx_descriptors(struct igc_ring *ring)
 {
 	/* Once tail pointer is updated, hardware can fetch the descriptors
 	 * any time so we issue a write membar here to ensure all memory
@@ -2637,6 +2637,14 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
 			size -= IGC_TS_HDR_LEN;
 		}
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf)) {
+			/* Advance the ring next-to-clean */
+			igc_is_non_eop(rx_ring, rx_desc);
+			cleaned_count++;
+			continue;
+		}
+
 		if (!skb) {
 			xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
 			xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
@@ -3144,6 +3152,11 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
 		if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD)))
 			break;
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_transmitted_smd_v(tx_desc))
+			ethtool_mmsv_event_handle(&adapter->fpe.mmsv,
+						  ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
+
 		/* Hold the completions while there's a pending tx hardware
 		 * timestamp request from XDP Tx metadata.
 		 */
@@ -4035,6 +4048,30 @@ static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr)
 	return 0;
 }
 
+/**
+ * igc_enable_empty_addr_recv - Enable Rx of packets with all-zeroes MAC address
+ * @adapter: Pointer to the igc_adapter structure.
+ *
+ * Frame preemption verification requires that packets with the all-zeroes
+ * MAC address are allowed to be received by the driver. This function adds the
+ * all-zeroes destination address to the list of acceptable addresses.
+ *
+ * Return: 0 on success, negative value otherwise.
+ */
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty, -1);
+}
+
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty);
+}
+
 /**
  * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
  * @netdev: network interface device structure
@@ -5310,6 +5347,9 @@ void igc_down(struct igc_adapter *adapter)
 	igc_disable_all_tx_rings_hw(adapter);
 	igc_clean_all_tx_rings(adapter);
 	igc_clean_all_rx_rings(adapter);
+
+	if (adapter->fpe.mmsv.pmac_enabled)
+		ethtool_mmsv_stop(&adapter->fpe.mmsv);
 }
 
 void igc_reinit_locked(struct igc_adapter *adapter)
@@ -5834,6 +5874,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			 */
 			igc_tsn_adjust_txtime_offset(adapter);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       true);
+
 			if (adapter->link_speed != SPEED_1000)
 				goto no_wait;
 
@@ -5869,6 +5913,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			netdev_info(netdev, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       false);
+
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGC_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
@@ -7189,6 +7237,8 @@ static int igc_probe(struct pci_dev *pdev,
 
 	igc_tsn_clear_schedule(adapter);
 
+	igc_fpe_init(adapter);
+
 	/* reset the hardware with the new settings */
 	igc_reset(adapter);
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 5b3b1bc0b64a..8a1725688381 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -2,9 +2,135 @@
 /* Copyright (c)  2019 Intel Corporation */
 
 #include "igc.h"
+#include "igc_base.h"
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+static int igc_fpe_init_smd_frame(struct igc_ring *ring,
+				  struct igc_tx_buffer *buffer,
+				  struct sk_buff *skb)
+{
+	dma_addr_t dma = dma_map_single(ring->dev, skb->data, skb->len,
+					DMA_TO_DEVICE);
+
+	if (dma_mapping_error(ring->dev, dma)) {
+		netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
+		return -ENOMEM;
+	}
+
+	buffer->skb = skb;
+	buffer->protocol = 0;
+	buffer->bytecount = skb->len;
+	buffer->gso_segs = 1;
+	buffer->time_stamp = jiffies;
+	dma_unmap_len_set(buffer, len, skb->len);
+	dma_unmap_addr_set(buffer, dma, dma);
+
+	return 0;
+}
+
+static int igc_fpe_init_tx_descriptor(struct igc_ring *ring,
+				      struct sk_buff *skb,
+				      enum igc_txd_popts_type type)
+{
+	u32 cmd_type, olinfo_status = 0;
+	struct igc_tx_buffer *buffer;
+	union igc_adv_tx_desc *desc;
+	int err;
+
+	if (!igc_desc_unused(ring))
+		return -EBUSY;
+
+	buffer = &ring->tx_buffer_info[ring->next_to_use];
+	err = igc_fpe_init_smd_frame(ring, buffer, skb);
+	if (err)
+		return err;
+
+	cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
+		   IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
+		   buffer->bytecount;
+
+	olinfo_status |= FIELD_PREP(IGC_ADVTXD_PAYLEN_MASK, buffer->bytecount);
+
+	switch (type) {
+	case SMD_V:
+	case SMD_R:
+		olinfo_status |= FIELD_PREP(IGC_TXD_POPTS_SMD_MASK, type);
+		break;
+	}
+
+	desc = IGC_TX_DESC(ring, ring->next_to_use);
+	desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+	desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+	desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
+
+	netdev_tx_sent_queue(txring_txq(ring), skb->len);
+
+	buffer->next_to_watch = desc;
+	ring->next_to_use = (ring->next_to_use + 1) % ring->count;
+
+	return 0;
+}
+
+static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
+				  enum igc_txd_popts_type type)
+{
+	int cpu = smp_processor_id();
+	struct netdev_queue *nq;
+	struct igc_ring *ring;
+	struct sk_buff *skb;
+	int err;
+
+	ring = igc_get_tx_ring(adapter, cpu);
+	nq = txring_txq(ring);
+
+	skb = alloc_skb(SMD_FRAME_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put_zero(skb, SMD_FRAME_SIZE);
+
+	__netif_tx_lock(nq, cpu);
+
+	err = igc_fpe_init_tx_descriptor(ring, skb, type);
+	igc_flush_tx_descriptors(ring);
+
+	__netif_tx_unlock(nq);
+
+	return err;
+}
+
+static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				 enum ethtool_mpacket type)
+{
+	struct igc_fpe_t *fpe = container_of(mmsv, struct igc_fpe_t, mmsv);
+	struct igc_adapter *adapter;
+	int err;
+
+	adapter = container_of(fpe, struct igc_adapter, fpe);
+
+	if (type == ETHTOOL_MPACKET_VERIFY) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_V);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-V\n");
+	} else if (type == ETHTOOL_MPACKET_RESPONSE) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_R);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-R frame\n");
+	}
+}
+
+static const struct ethtool_mmsv_ops igc_mmsv_ops = {
+	.send_mpacket = igc_fpe_send_mpacket,
+};
+
+void igc_fpe_init(struct igc_adapter *adapter)
+{
+	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
+}
+
 static bool is_any_launchtime(struct igc_adapter *adapter)
 {
 	int i;
@@ -49,6 +175,9 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
 	if (adapter->strict_priority_enable)
 		new_flags |= IGC_FLAG_TSN_LEGACY_ENABLED;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		new_flags |= IGC_FLAG_TSN_PREEMPT_ENABLED;
+
 	return new_flags;
 }
 
@@ -167,7 +296,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
-		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
+		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
+		      IGC_TQAVCTRL_PREEMPT_ENA);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -386,10 +516,14 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 		wr32(IGC_TXQCTL(i), txqctl);
 	}
 
-	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
+	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
+		   IGC_TQAVCTRL_PREEMPT_ENA);
 
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
@@ -450,6 +584,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)
 	unsigned int new_flags;
 	int err = 0;
 
+	if (adapter->fpe.mmsv.pmac_enabled) {
+		err = igc_enable_empty_addr_recv(adapter);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error adding empty address to MAC filter\n");
+	} else {
+		igc_disable_empty_addr_recv(adapter);
+	}
+
 	new_flags = igc_tsn_new_flags(adapter);
 
 	if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 98ec845a86bf..bb30d15cec76 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,9 +4,59 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define SMD_FRAME_SIZE			60
+
+enum igc_txd_popts_type {
+	SMD_V = 0x01,
+	SMD_R = 0x02,
+};
+
+DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+void igc_fpe_init(struct igc_adapter *adapter);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
 bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter);
 
+static inline bool igc_fpe_is_pmac_enabled(struct igc_adapter *adapter)
+{
+	return static_branch_unlikely(&igc_fpe_enabled) &&
+	       adapter->fpe.mmsv.pmac_enabled;
+}
+
+static inline bool igc_fpe_handle_mpacket(struct igc_adapter *adapter,
+					  union igc_adv_rx_desc *rx_desc,
+					  unsigned int size, void *pktbuf)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+	if (smd != IGC_RXD_STAT_SMD_TYPE_V && smd != IGC_RXD_STAT_SMD_TYPE_R)
+		return false;
+
+	if (size == SMD_FRAME_SIZE && mem_is_zero(pktbuf, SMD_FRAME_SIZE)) {
+		struct ethtool_mmsv *mmsv = &adapter->fpe.mmsv;
+		enum ethtool_mmsv_event event;
+
+		if (smd == IGC_RXD_STAT_SMD_TYPE_V)
+			event = ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET;
+		else
+			event = ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET;
+
+		ethtool_mmsv_event_handle(mmsv, event);
+	}
+
+	return true;
+}
+
+static inline bool igc_fpe_transmitted_smd_v(union igc_adv_tx_desc *tx_desc)
+{
+	u32 olinfo_status = le32_to_cpu(tx_desc->read.olinfo_status);
+	u8 smd = FIELD_GET(IGC_TXD_POPTS_SMD_MASK, olinfo_status);
+
+	return smd == SMD_V;
+}
+
 #endif /* _IGC_BASE_H */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:45 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:45 -0400
Subject: [PATCH iwl-next v9 11/14] igc: add support to set tx-min-frag-size
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-12-faizal.abdul.rahim@linux.intel.com>

Add support for setting tx-min-frag-size via the set_mm callback in igc.
If the requested value is unsupported, round it up to the smallest
supported i226 size (64, 128, 192, 256) and send a netlink message to
inform the user.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |  1 +
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  5 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 38 ++++++++++++++++++--
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 5 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index d970968f3233..d61e2915ccb4 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *);
 
 struct igc_fpe_t {
 	struct ethtool_mmsv mmsv;
+	u32 tx_min_frag_size;
 };
 
 enum igc_mac_filter_type {
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 542c7c8802a0..80e0b5ed8b1a 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -583,6 +583,7 @@
 #define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
+#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000
 
 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
 #define IGC_TXQCTL_STRICT_CYCLE		0x00000002
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index b64d5c6c1d20..529654ccd83f 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_fpe_t *fpe = &adapter->fpe;
 
+	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
+	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");
+
 	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
 		if (cmd->pmac_enabled)
 			static_branch_inc(&igc_fpe_enabled);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 8a1725688381..215bf8e38328 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -6,6 +6,12 @@
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+#define MIN_MULTPLIER_TX_MIN_FRAG	0
+#define MAX_MULTPLIER_TX_MIN_FRAG	3
+/* Frag size is based on the Section 8.12.2 of the SW User Manual */
+#define TX_MIN_FRAG_SIZE		64
+#define TX_MAX_FRAG_SIZE	(TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1))
+
 DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 static int igc_fpe_init_smd_frame(struct igc_ring *ring,
@@ -128,6 +134,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = {
 
 void igc_fpe_init(struct igc_adapter *adapter)
 {
+	adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
 	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
 }
 
@@ -297,7 +304,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
 		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
-		      IGC_TQAVCTRL_PREEMPT_ENA);
+		      IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -343,12 +350,35 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
 	wr32(IGC_RETX_CTL, retxctl);
 }
 
+static u8 igc_fpe_get_frag_size_mult(const struct igc_fpe_t *fpe)
+{
+	u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1;
+
+	return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG,
+		       MAX_MULTPLIER_TX_MIN_FRAG);
+}
+
+u32 igc_fpe_get_supported_frag_size(u32 frag_size)
+{
+	const u32 supported_sizes[] = {64, 128, 192, 256};
+
+	/* Find the smallest supported size that is >= frag_size */
+	for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) {
+		if (frag_size <= supported_sizes[i])
+			return supported_sizes[i];
+	}
+
+	/* Should not happen */
+	return TX_MAX_FRAG_SIZE;
+}
+
 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
 	u32 sec, nsec, cycle;
 	ktime_t base_time, systim;
+	u32 frag_size_mult;
 	int i;
 
 	wr32(IGC_TSAUXC, 0);
@@ -517,13 +547,15 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	}
 
 	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
-		   IGC_TQAVCTRL_PREEMPT_ENA);
-
+		   IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
 	if (adapter->fpe.mmsv.pmac_enabled)
 		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
 
+	frag_size_mult = igc_fpe_get_frag_size_mult(&adapter->fpe);
+	tqavctrl |= FIELD_PREP(IGC_TQAVCTRL_MIN_FRAG_MASK, frag_size_mult);
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index bb30d15cec76..58fe5f0773d7 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -14,6 +14,7 @@ enum igc_txd_popts_type {
 DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 void igc_fpe_init(struct igc_adapter *adapter);
+u32 igc_fpe_get_supported_frag_size(u32 frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:46 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:46 -0400
Subject: [PATCH iwl-next v9 12/14] igc: block setting preemptible traffic class in taprio
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-13-faizal.abdul.rahim@linux.intel.com>

Since preemptible tc implementation is not ready yet, block it from being
set in taprio. The existing code already blocks it in mqprio.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 71c377cb7a88..fc945c5b7c70 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6486,6 +6486,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 	if (!validate_schedule(adapter, qopt))
 		return -EINVAL;
 
+	/* preemptible isn't supported yet */
+	if (qopt->mqprio.preemptible_tcs)
+		return -EOPNOTSUPP;
+
 	igc_ptp_read(adapter, &now);
 
 	if (igc_tsn_is_taprio_activated_by_user(adapter) &&
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:47 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:47 -0400
Subject: [PATCH iwl-next v9 13/14] igc: add support to get MAC Merge data via ethtool
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-14-faizal.abdul.rahim@linux.intel.com>

Implement "ethtool --show-mm" callback for IGC.

Tested with command:
$ ethtool --show-mm enp1s0.
  MAC Merge layer state for enp1s0:
  pMAC enabled: on
  TX enabled: on
  TX active: on
  TX minimum fragment size: 64
  RX minimum fragment size: 60
  Verify enabled: on
  Verify time: 128
  Max verify time: 128
  Verification status: SUCCEEDED

Verified that the fields value are retrieved correctly.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 14 ++++++++++++++
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 529654ccd83f..fd4b4b332309 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1782,6 +1782,19 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_get_mm(struct net_device *netdev,
+			      struct ethtool_mm_state *cmd)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	ethtool_mmsv_get_mm(&fpe->mmsv, cmd);
+	cmd->tx_min_frag_size = fpe->tx_min_frag_size;
+	cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE;
+
+	return 0;
+}
+
 static int igc_ethtool_set_mm(struct net_device *netdev,
 			      struct ethtool_mm_cfg *cmd,
 			      struct netlink_ext_ack *extack)
@@ -2101,6 +2114,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 58fe5f0773d7..c2a77229207b 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,6 +4,7 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define IGC_RX_MIN_FRAG_SIZE		60
 #define SMD_FRAME_SIZE			60
 
 enum igc_txd_popts_type {
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:34 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:34 -0400
Subject: [PATCH iwl-next v9 00/14] igc: Add support for Frame Preemption feature in IGC
Message-ID: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>

Introduces support for the FPE feature in the IGC driver.

The patches aligns with the upstream FPE API:
https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.oltean at nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.oltean at nxp.com/

It builds upon earlier work:
https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.1098888-1-vinicius.gomes at intel.com/

The patch series adds the following functionalities to the IGC driver:
a) Configure FPE using `ethtool --set-mm`.
b) Display FPE settings via `ethtool --show-mm`.
c) View FPE statistics using `ethtool --include-statistics --show-mm'.
e) Block setting preemptible tc in taprio since it is not supported yet.
   Existing code already blocks it in mqprio.

Tested:
Enabled CONFIG_PROVE_LOCKING, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_DMA_API_DEBUG, and CONFIG_KASAN
1) selftests
2) netdev down/up cycles
3) suspend/resume cycles
4) fpe verification

No bugs or unusual dmesg logs were observed.
Ran 1), 2) and 3) with and without the patch series, compared dmesg and selftest logs ? no differences found.

Change Log:
v8 -> v9:
- Add Vladimir and Fu Rong Reviewed-by, patch 1
- Remove Faizal Co-developed-by for patch 2
- Remove code that reset verification state when link is down, patch 2 (Vladimir)
- Refactor TX buffer and RX buffer magic constants with macro for each field. patch 5-9 (Vladimir)
- s/Rest adapter/Adapter reset/ in commit description, patch 10 (Vladimir)
- Replace igc_fpe_is_verify_or_response() and igc_fpe_lp_event_status() with igc_fpe_handle_mpacket(), patch 10 (Vladimir)
- Comments on separate lines from code in igc_fpe_get_supported_frag_size(), patch 11 (Vladimir)
- Remove mistakenly added igc_fpe_get_supported_frag_size(), patch 10 (Vladimir)
- Remove max limit 256 of tx-min-size changes, patch 11 (Vladimir)

v7 -> v8:
- Reject SMD-V and SMD-R if the payload contains non-zero values (Vladimir, Chwee Lin)
- Move resetting verification state when link is down to a new patch 3/11 (Vladimir)
- Move frag_size related handling outside of spin_lock_irq_save(), patch 1/11 (Vladimir)
- Renamed IGC_PRMEXPRCNT to IGC_PRMEXCPRCNT, to align with i226 SW User Manual, patch 11/11 (Chwee Lin)
- Use IGC_PRMEXPRCNT_OOO_SMDC for frame smd errors instead of frame assembly errors, 11/11 (Chwee Lin)

v6 -> v7:
- Squash the cpu param to the prev line (Przemek Kitszel)
- Use igc_ prefix for fpe_t (Przemek Kitszel)
- Move new ops to different line in igc_ethtool_ops (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): rx -> Rx (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): s/IGC/the driver/ (Przemek Kitszel)
- Change preferred style of init, from { }, to {} (Przemek Kitszel)
- Remove inclusion of umbrella header <linux/kernel.h> in igc_tsn.c (Przemek Kitszel)
- End enum with "," in igc_txd_popts_type (Przemek Kitszel)
- Remove unnecessary braces in igc_fpe_is_verify_or_response() (Przemek Kitszel)

v5 -> v6:
- Added Tested-by: Furong Xu for patch 1/9 (Vladimir, Furong Xu)
- Updated logic in ethtool_mmsv_link_state_handle() (Vladimir, Furong Xu)
- Swap sequence of function call in stmmac_set_mm() (Furong Xu)
- Log an error if igc_enable_empty_addr_recv() fails (Vladimir)
- Move the patch ".. Block setting preemptible traffic .." before ".. Add support to get MAC Merge data .." (Vladimir)
- Move mmsv function kernel-doc from .h to .c file (Vladimir)

v4 -> v5:
- Remove "igc: Add support for preemptible traffic class in taprio" patch (Vladimir)
- Add a new patch "igc: Block setting preemptible traffic classes in taprio" (Vladimir)
- Add kernel-doc for mmsv api (Vladimir)
- olininfo_status to use host byte order (Simon)
- status_error should host byte type (Simon)
- Some code was misplaced in the wrong patch (Vladimir)
- Mix of tabs and spaces in patch description (Vladimir)
- Created igc_is_pmac_enabled() to reduce code repetition (Vladimir)

v3 -> v4:
- Fix compilation warnings introduced by this patch series

v2 -> v3:
- Implement configure_tx() mmsv callback (Vladimir)
- Use static_branch_inc() and static_branch_dec() (Vladimir)
- Add adapter->fpe.mmsv.pmac_enabled as extra check (Vladimir)
- Remove unnecessary error check in igc_fpe_init_tx_descriptor() (Vladimir)
- Additional places to use FIELD_PREP() instead of manual bit manipulation (Vladimir)
- IGC_TXD_POPTS_SMD_V and IGC_TXD_POPTS_SMD_R type change to enum (Vladimir)
- Remove unnecessary netif_running() check in igc_fpe_xmit_frame (Vladimir)
- Rate limit print in igc_fpe_send_mpacket (Vladimir)

v1 -> v2:
- Extract the stmmac verification logic into a common library (Vladimir)
- igc to use common library for verification (Vladimir)
- Fix syntax for kernel-doc to use "Return:" (Vladimir)
- Use FIELD_GET instead of manual bit masking (Vladimir)
- Don't assign 0 to statistics counter in igc_ethtool_get_mm_stats() (Vladimir)
- Use pmac-enabled as a condition to allow MAC address value 0 (Vladimir)
- Define macro register value in increasing value order (Vladimir)
- Fix tx-min-frag-size handling for igc (Vladimir)
- Handle link state changes with verification in igc (Vladimir)
- Add static key for fast path code (Vladimir)
- rx_min_frag_size get from constant (Vladimir)

v1: https://patchwork.kernel.org/project/netdevbpf/cover/20241216064720.931522-1-faizal.abdul.rahim at linux.intel.com/
v2: https://patchwork.kernel.org/project/netdevbpf/cover/20250205100524.1138523-1-faizal.abdul.rahim at linux.intel.com/
v3: https://patchwork.kernel.org/project/netdevbpf/cover/20250207165649.2245320-1-faizal.abdul.rahim at linux.intel.com/
v4: https://patchwork.kernel.org/project/netdevbpf/cover/20250210070207.2615418-1-faizal.abdul.rahim at linux.intel.com/
v5: https://patchwork.kernel.org/project/netdevbpf/cover/20250220025349.3007793-1-faizal.abdul.rahim at linux.intel.com/
v6: https://patchwork.kernel.org/project/netdevbpf/cover/20250227140158.2129988-1-faizal.abdul.rahim at linux.intel.com/
v7: https://patchwork.kernel.org/project/netdevbpf/cover/20250303102658.3580232-1-faizal.abdul.rahim at linux.intel.com/
v8: https://patchwork.kernel.org/project/netdevbpf/cover/20250305130026.642219-1-faizal.abdul.rahim at linux.intel.com/

Faizal Rahim (13):
  net: stmmac: move frag_size handling out of spin_lock
  net: ethtool: mm: reset verification status when link is down
  igc: rename xdp_get_tx_ring() for non-xdp usage
  igc: rename I225_RXPBSIZE_DEFAULT and I225_TXPBSIZE_DEFAULT
  igc: use FIELD_PREP and GENMASK for existing TX packet buffer size
  igc: optimize TX packet buffer utilization for TSN mode
  igc: use FIELD_PREP and GENMASK for existing RX packet buffer size
  igc: set the RX packet buffer size for TSN mode
  igc: add support for frame preemption verification
  igc: add support to set tx-min-frag-size
  igc: block setting preemptible traffic class in taprio
  igc: add support to get MAC Merge data via ethtool
  igc: add support to get frame preemption statistics via ethtool

Vladimir Oltean (1):
  net: ethtool: mm: extract stmmac verification logic into common
    library

 drivers/net/ethernet/intel/igc/igc.h          |  15 +-
 drivers/net/ethernet/intel/igc/igc_base.h     |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h  |  55 +++-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |  80 +++++
 drivers/net/ethernet/intel/igc/igc_main.c     |  69 ++++-
 drivers/net/ethernet/intel/igc/igc_regs.h     |  16 +
 drivers/net/ethernet/intel/igc/igc_tsn.c      | 207 ++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h      |  52 ++++
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  41 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 279 +++++++++++++++++-
 15 files changed, 870 insertions(+), 221 deletions(-)

--
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:35 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:35 -0400
Subject: [PATCH iwl-next v9 01/14] net: stmmac: move frag_size handling out of spin_lock
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-2-faizal.abdul.rahim@linux.intel.com>

The upcoming patch will extract verification logic into a new module,
MMSV (MAC Merge Software Verification). MMSV will handle most FPE fields,
except frag_size. It introduces its own lock (mmsv->lock), replacing
fpe_cfg->lock.

Since frag_size handling remains in the driver, the existing rtnl_lock()
is sufficient. Move frag_size handling out of spin_lock_irq_save() to keep
the upcoming patch a pure refactoring without behavior changes.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Reviewed-by: Furong Xu <0x1207 at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 918a32f8fda8..cfe5aea24549 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1216,6 +1216,10 @@ static int stmmac_get_mm(struct net_device *ndev,
 	if (!stmmac_fpe_supported(priv))
 		return -EOPNOTSUPP;
 
+	state->rx_min_frag_size = ETH_ZLEN;
+	frag_size = stmmac_fpe_get_add_frag_size(priv);
+	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
+
 	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
 
 	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
@@ -1224,7 +1228,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	state->verify_time = priv->fpe_cfg.verify_time;
 	state->tx_enabled = priv->fpe_cfg.tx_enabled;
 	state->verify_status = priv->fpe_cfg.status;
-	state->rx_min_frag_size = ETH_ZLEN;
 
 	/* FPE active if common tx_enabled and
 	 * (verification success or disabled(forced))
@@ -1236,9 +1239,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	else
 		state->tx_active = false;
 
-	frag_size = stmmac_fpe_get_add_frag_size(priv);
-	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
-
 	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
 
 	return 0;
@@ -1258,6 +1258,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (err)
 		return err;
 
+	stmmac_fpe_set_add_frag_size(priv, frag_size);
+
 	/* Wait for the verification that's currently in progress to finish */
 	timer_shutdown_sync(&fpe_cfg->verify_timer);
 
@@ -1271,7 +1273,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (!cfg->verify_enabled)
 		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
 
-	stmmac_fpe_set_add_frag_size(priv, frag_size);
 	stmmac_fpe_apply(priv);
 
 	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:36 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:36 -0400
Subject: [PATCH iwl-next v9 02/14] net: ethtool: mm: extract stmmac verification logic into common library
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>

From: Vladimir Oltean <vladimir.oltean at nxp.com>

It appears that stmmac is not the only hardware which requires a
software-driven verification state machine for the MAC Merge layer.

While on the one hand it's good to encourage hardware implementations,
on the other hand it's quite difficult to tolerate multiple drivers
implementing independently fairly non-trivial logic.

Extract the hardware-independent logic from stmmac into library code and
put it in ethtool. Name the state structure "mmsv" for MAC Merge
Software Verification. Let this expose an operations structure for
executing the hardware stuff: sync hardware with the tx_active boolean
(result of verification process), enable/disable the pMAC, send mPackets,
notify library of external events (reception of mPackets), as well as
link state changes.

Note that it is assumed that the external events are received in hardirq
context. If they are not, it is probably a good idea to disable hardirqs
when calling ethtool_mmsv_event_handle(), because the library does not
do so.

Also, the MM software verification process has no business with the
tx_min_frag_size, that is all the driver's to handle.

Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Furong Xu <0x1207 at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  42 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 275 +++++++++++++++++-
 7 files changed, 391 insertions(+), 202 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 3a00a988cb36..283607eee128 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -149,21 +149,9 @@ struct stmmac_channel {
 };
 
 struct stmmac_fpe_cfg {
-	/* Serialize access to MAC Merge state between ethtool requests
-	 * and link state updates.
-	 */
-	spinlock_t lock;
-
+	struct ethtool_mmsv mmsv;
 	const struct stmmac_fpe_reg *reg;
-	u32 fpe_csr;				/* MAC_FPE_CTRL_STS reg cache */
-
-	enum ethtool_mm_verify_status status;
-	struct timer_list verify_timer;
-	bool verify_enabled;
-	int verify_retries;
-	bool pmac_enabled;
-	u32 verify_time;
-	bool tx_enabled;
+	u32 fpe_csr;	/* MAC_FPE_CTRL_STS reg cache */
 };
 
 struct stmmac_tc_entry {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index cfe5aea24549..44ee73569cb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1210,7 +1210,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 			 struct ethtool_mm_state *state)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long flags;
 	u32 frag_size;
 
 	if (!stmmac_fpe_supported(priv))
@@ -1220,26 +1219,7 @@ static int stmmac_get_mm(struct net_device *ndev,
 	frag_size = stmmac_fpe_get_add_frag_size(priv);
 	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
 
-	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
-
-	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	state->verify_enabled = priv->fpe_cfg.verify_enabled;
-	state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
-	state->verify_time = priv->fpe_cfg.verify_time;
-	state->tx_enabled = priv->fpe_cfg.tx_enabled;
-	state->verify_status = priv->fpe_cfg.status;
-
-	/* FPE active if common tx_enabled and
-	 * (verification success or disabled(forced))
-	 */
-	if (state->tx_enabled &&
-	    (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
-	     state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
-		state->tx_active = true;
-	else
-		state->tx_active = false;
-
-	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
+	ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
 
 	return 0;
 }
@@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 			 struct netlink_ext_ack *extack)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
 	u32 frag_size;
 	int err;
 
@@ -1259,23 +1237,7 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 		return err;
 
 	stmmac_fpe_set_add_frag_size(priv, frag_size);
-
-	/* Wait for the verification that's currently in progress to finish */
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	fpe_cfg->verify_enabled = cfg->verify_enabled;
-	fpe_cfg->pmac_enabled = cfg->pmac_enabled;
-	fpe_cfg->verify_time = cfg->verify_time;
-	fpe_cfg->tx_enabled = cfg->tx_enabled;
-
-	if (!cfg->verify_enabled)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-
-	stmmac_fpe_apply(priv);
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+	ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index 3a4bee029c7f..75b470ee621a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -27,12 +27,6 @@
 #define STMMAC_MAC_FPE_CTRL_STS_SVER	BIT(1)
 #define STMMAC_MAC_FPE_CTRL_STS_EFPE	BIT(0)
 
-/* FPE link-partner hand-shaking mPacket type */
-enum stmmac_mpacket_type {
-	MPACKET_VERIFY = 0,
-	MPACKET_RESPONSE = 1,
-};
-
 struct stmmac_fpe_reg {
 	const u32 mac_fpe_reg;		/* offset of MAC_FPE_CTRL_STS */
 	const u32 mtl_fpe_reg;		/* offset of MTL_FPE_CTRL_STS */
@@ -48,10 +42,10 @@ bool stmmac_fpe_supported(struct stmmac_priv *priv)
 		priv->hw->mac->fpe_map_preemption_class;
 }
 
-static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
-				 bool pmac_enable)
+static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
 {
-	struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
 	const struct stmmac_fpe_reg *reg = cfg->reg;
 	u32 num_rxq = priv->plat->rx_queues_to_use;
 	void __iomem *ioaddr = priv->ioaddr;
@@ -68,6 +62,15 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 		cfg->fpe_csr = 0;
 	}
 	writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
+}
+
+static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
+{
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
+	void __iomem *ioaddr = priv->ioaddr;
+	u32 value;
 
 	value = readl(ioaddr + reg->int_en_reg);
 
@@ -85,47 +88,45 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 	writel(value, ioaddr + reg->int_en_reg);
 }
 
-static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
-				    enum stmmac_mpacket_type type)
+static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				    enum ethtool_mpacket type)
 {
-	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
 	void __iomem *ioaddr = priv->ioaddr;
-	u32 value = priv->fpe_cfg.fpe_csr;
+	u32 value = cfg->fpe_csr;
 
-	if (type == MPACKET_VERIFY)
+	if (type == ETHTOOL_MPACKET_VERIFY)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
-	else if (type == MPACKET_RESPONSE)
+	else if (type == ETHTOOL_MPACKET_RESPONSE)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
 
 	writel(value, ioaddr + reg->mac_fpe_reg);
 }
 
+static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
+	.configure_tx = stmmac_fpe_configure_tx,
+	.configure_pmac = stmmac_fpe_configure_pmac,
+	.send_mpacket = stmmac_fpe_send_mpacket,
+};
+
 static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
 {
 	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+	struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv;
 
-	/* This is interrupt context, just spin_lock() */
-	spin_lock(&fpe_cfg->lock);
-
-	if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
-		goto unlock_out;
+	if (status == FPE_EVENT_UNKNOWN)
+		return;
 
-	/* LP has sent verify mPacket */
 	if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
-		stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
 
-	/* Local has sent verify mPacket */
-	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
 
-	/* LP has sent response mPacket */
-	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
-	    fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
-
-unlock_out:
-	spin_unlock(&fpe_cfg->lock);
+	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
 }
 
 void stmmac_fpe_irq_status(struct stmmac_priv *priv)
@@ -164,119 +165,16 @@ void stmmac_fpe_irq_status(struct stmmac_priv *priv)
 	stmmac_fpe_event_status(priv, status);
 }
 
-/**
- * stmmac_fpe_verify_timer - Timer for MAC Merge verification
- * @t:  timer_list struct containing private info
- *
- * Verify the MAC Merge capability in the local TX direction, by
- * transmitting Verify mPackets up to 3 times. Wait until link
- * partner responds with a Response mPacket, otherwise fail.
- */
-static void stmmac_fpe_verify_timer(struct timer_list *t)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
-	struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
-						fpe_cfg);
-	unsigned long flags;
-	bool rearm = false;
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	switch (fpe_cfg->status) {
-	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
-	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
-		if (fpe_cfg->verify_retries != 0) {
-			stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
-			rearm = true;
-		} else {
-			fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
-		}
-
-		fpe_cfg->verify_retries--;
-		break;
-
-	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
-		stmmac_fpe_configure(priv, true, true);
-		break;
-
-	default:
-		break;
-	}
-
-	if (rearm) {
-		mod_timer(&fpe_cfg->verify_timer,
-			  jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
-static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
-{
-	if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
-	    fpe_cfg->verify_enabled &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
-		timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
-		mod_timer(&fpe_cfg->verify_timer, jiffies);
-	}
-}
-
 void stmmac_fpe_init(struct stmmac_priv *priv)
 {
-	priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-	priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-	timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
-	spin_lock_init(&priv->fpe_cfg.lock);
+	ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev,
+			  &stmmac_mmsv_ops);
 
 	if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
 	    priv->dma_cap.fpesel)
 		dev_info(priv->device, "FPE is not supported by driver.\n");
 }
 
-void stmmac_fpe_apply(struct stmmac_priv *priv)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
-	/* If verification is disabled, configure FPE right away.
-	 * Otherwise let the timer code do it.
-	 */
-	if (!fpe_cfg->verify_enabled) {
-		stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
-				     fpe_cfg->pmac_enabled);
-	} else {
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
-		fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-
-		if (netif_running(priv->dev))
-			stmmac_fpe_verify_timer_arm(fpe_cfg);
-	}
-}
-
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
-
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	if (is_up && fpe_cfg->pmac_enabled) {
-		/* VERIFY process requires pmac enabled when NIC comes up */
-		stmmac_fpe_configure(priv, false, true);
-
-		/* New link => maybe new partner => new verification process */
-		stmmac_fpe_apply(priv);
-	} else {
-		/* No link => turn off EFPE */
-		stmmac_fpe_configure(priv, false, false);
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
 {
 	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
index b884eac7142d..3fc46acf7001 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
@@ -9,15 +9,10 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 
-#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES	3
-#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS	128
-
 struct stmmac_priv;
 
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
 bool stmmac_fpe_supported(struct stmmac_priv *priv);
 void stmmac_fpe_init(struct stmmac_priv *priv);
-void stmmac_fpe_apply(struct stmmac_priv *priv);
 void stmmac_fpe_irq_status(struct stmmac_priv *priv);
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
 void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a3accab213b0..b34ae61d7a6d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -947,7 +947,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, false);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, false);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, false);
 }
 
 static void stmmac_mac_link_up(struct phylink_config *config,
@@ -1067,7 +1067,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, true);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, true);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, true);
 
 	if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
 		stmmac_hwtstamp_correct_latency(priv, priv);
@@ -4141,7 +4141,7 @@ static int stmmac_release(struct net_device *dev)
 	stmmac_release_ptp(priv);
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	pm_runtime_put(priv->device);
 
@@ -7850,7 +7850,7 @@ int stmmac_suspend(struct device *dev)
 	rtnl_unlock();
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	priv->speed = SPEED_UNKNOWN;
 	return 0;
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 7f222dccc7d1..624e49c9fbf7 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -17,9 +17,13 @@
 #include <linux/compat.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
+#include <linux/timer_types.h>
 #include <uapi/linux/ethtool.h>
 #include <uapi/linux/net_tstamp.h>
 
+#define ETHTOOL_MM_MAX_VERIFY_TIME_MS		128
+#define ETHTOOL_MM_MAX_VERIFY_RETRIES		3
+
 struct compat_ethtool_rx_flow_spec {
 	u32		flow_type;
 	union ethtool_flow_union h_u;
@@ -710,6 +714,75 @@ struct ethtool_mm_stats {
 	u64 MACMergeHoldCount;
 };
 
+enum ethtool_mmsv_event {
+	ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET,
+};
+
+/* MAC Merge verification mPacket type */
+enum ethtool_mpacket {
+	ETHTOOL_MPACKET_VERIFY,
+	ETHTOOL_MPACKET_RESPONSE,
+};
+
+struct ethtool_mmsv;
+
+/**
+ * struct ethtool_mmsv_ops - Operations for MAC Merge Software Verification
+ * @configure_tx: Driver callback for the event where the preemptible TX
+ *		  becomes active or inactive. Preemptible traffic
+ *		  classes must be committed to hardware only while
+ *		  preemptible TX is active.
+ * @configure_pmac: Driver callback for the event where the pMAC state
+ *		    changes as result of an administrative setting
+ *		    (ethtool) or a call to ethtool_mmsv_link_state_handle().
+ * @send_mpacket: Driver-provided method for sending a Verify or a Response
+ *		  mPacket.
+ */
+struct ethtool_mmsv_ops {
+	void (*configure_tx)(struct ethtool_mmsv *mmsv, bool tx_active);
+	void (*configure_pmac)(struct ethtool_mmsv *mmsv, bool pmac_enabled);
+	void (*send_mpacket)(struct ethtool_mmsv *mmsv, enum ethtool_mpacket mpacket);
+};
+
+/**
+ * struct ethtool_mmsv - MAC Merge Software Verification
+ * @ops: operations for MAC Merge Software Verification
+ * @dev: pointer to net_device structure
+ * @lock: serialize access to MAC Merge state between
+ *	  ethtool requests and link state updates.
+ * @status: current verification FSM state
+ * @verify_timer: timer for verification in local TX direction
+ * @verify_enabled: indicates if verification is enabled
+ * @verify_retries: number of retries for verification
+ * @pmac_enabled: indicates if the preemptible MAC is enabled
+ * @verify_time: time for verification in milliseconds
+ * @tx_enabled: indicates if transmission is enabled
+ */
+struct ethtool_mmsv {
+	const struct ethtool_mmsv_ops *ops;
+	struct net_device *dev;
+	spinlock_t lock;
+	enum ethtool_mm_verify_status status;
+	struct timer_list verify_timer;
+	bool verify_enabled;
+	int verify_retries;
+	bool pmac_enabled;
+	u32 verify_time;
+	bool tx_enabled;
+};
+
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv);
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up);
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event);
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state);
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg);
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops);
+
 /**
  * struct ethtool_rxfh_param - RXFH (RSS) parameters
  * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index 2816bb23c3ad..bfd988464d7d 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright 2022-2023 NXP
+ * Copyright 2022-2025 NXP
+ * Copyright 2024 Furong Xu <0x1207 at gmail.com>
  */
 #include "common.h"
 #include "netlink.h"
@@ -282,3 +283,275 @@ bool ethtool_dev_mm_supported(struct net_device *dev)
 	return supported;
 }
 EXPORT_SYMBOL_GPL(ethtool_dev_mm_supported);
+
+static void ethtool_mmsv_configure_tx(struct ethtool_mmsv *mmsv,
+				      bool tx_active)
+{
+	if (mmsv->ops->configure_tx)
+		mmsv->ops->configure_tx(mmsv, tx_active);
+}
+
+static void ethtool_mmsv_configure_pmac(struct ethtool_mmsv *mmsv,
+					bool pmac_enabled)
+{
+	if (mmsv->ops->configure_pmac)
+		mmsv->ops->configure_pmac(mmsv, pmac_enabled);
+}
+
+static void ethtool_mmsv_send_mpacket(struct ethtool_mmsv *mmsv,
+				      enum ethtool_mpacket mpacket)
+{
+	if (mmsv->ops->send_mpacket)
+		mmsv->ops->send_mpacket(mmsv, mpacket);
+}
+
+/**
+ * ethtool_mmsv_verify_timer - Timer for MAC Merge verification
+ * @t: timer_list struct containing private info
+ *
+ * Verify the MAC Merge capability in the local TX direction, by
+ * transmitting Verify mPackets up to 3 times. Wait until link
+ * partner responds with a Response mPacket, otherwise fail.
+ */
+static void ethtool_mmsv_verify_timer(struct timer_list *t)
+{
+	struct ethtool_mmsv *mmsv = from_timer(mmsv, t, verify_timer);
+	unsigned long flags;
+	bool rearm = false;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	switch (mmsv->status) {
+	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+		if (mmsv->verify_retries != 0) {
+			ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_VERIFY);
+			rearm = true;
+		} else {
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+		}
+
+		mmsv->verify_retries--;
+		break;
+
+	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+		ethtool_mmsv_configure_tx(mmsv, true);
+		break;
+
+	default:
+		break;
+	}
+
+	if (rearm) {
+		mod_timer(&mmsv->verify_timer,
+			  jiffies + msecs_to_jiffies(mmsv->verify_time));
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+
+static void ethtool_mmsv_verify_timer_arm(struct ethtool_mmsv *mmsv)
+{
+	if (mmsv->pmac_enabled && mmsv->tx_enabled && mmsv->verify_enabled &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
+		timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+		mod_timer(&mmsv->verify_timer, jiffies);
+	}
+}
+
+static void ethtool_mmsv_apply(struct ethtool_mmsv *mmsv)
+{
+	/* If verification is disabled, configure FPE right away.
+	 * Otherwise let the timer code do it.
+	 */
+	if (!mmsv->verify_enabled) {
+		ethtool_mmsv_configure_pmac(mmsv, mmsv->pmac_enabled);
+		ethtool_mmsv_configure_tx(mmsv, mmsv->tx_enabled);
+	} else {
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+
+		if (netif_running(mmsv->dev))
+			ethtool_mmsv_verify_timer_arm(mmsv);
+	}
+}
+
+/**
+ * ethtool_mmsv_stop() - Stop MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ *
+ * Drivers should call this method in a state where the hardware is
+ * about to lose state, like ndo_stop() or suspend(), and turning off
+ * MAC Merge features would be superfluous. Otherwise, prefer
+ * ethtool_mmsv_link_state_handle() with up=false.
+ */
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv)
+{
+	timer_shutdown_sync(&mmsv->verify_timer);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_stop);
+
+/**
+ * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification
+ *				      of link state changes
+ * @mmsv: MAC Merge Software Verification state
+ * @up: True if device carrier is up and able to pass verification packets
+ *
+ * Calling context is expected to be from a task, interrupts enabled.
+ */
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
+{
+	unsigned long flags;
+
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	if (up && mmsv->pmac_enabled) {
+		/* VERIFY process requires pMAC enabled when NIC comes up */
+		ethtool_mmsv_configure_pmac(mmsv, true);
+
+		/* New link => maybe new partner => new verification process */
+		ethtool_mmsv_apply(mmsv);
+	} else {
+		/* No link or pMAC not enabled */
+		ethtool_mmsv_configure_pmac(mmsv, false);
+		ethtool_mmsv_configure_tx(mmsv, false);
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle);
+
+/**
+ * ethtool_mmsv_event_handle() - Inform MAC Merge Software Verification
+ *				 of interrupt-based events
+ * @mmsv: MAC Merge Software Verification state
+ * @event: Event which took place (packet transmission or reception)
+ *
+ * Calling context expects to have interrupts disabled.
+ */
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event)
+{
+	/* This is interrupt context, just spin_lock() */
+	spin_lock(&mmsv->lock);
+
+	if (!mmsv->pmac_enabled)
+		goto unlock;
+
+	switch (event) {
+	case ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET:
+		/* Link partner has sent verify mPacket */
+		ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_RESPONSE);
+		break;
+	case ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET:
+		/* Local device has sent verify mPacket */
+		if (mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+		break;
+	case ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET:
+		/* Link partner has sent response mPacket */
+		if (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+		break;
+	}
+
+unlock:
+	spin_unlock(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_event_handle);
+
+static bool ethtool_mmsv_is_tx_active(struct ethtool_mmsv *mmsv)
+{
+	/* TX is active if administratively enabled, and verification either
+	 * succeeded, or was administratively disabled.
+	 */
+	return mmsv->tx_enabled &&
+	       (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
+	       mmsv->status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
+}
+
+/**
+ * ethtool_mmsv_get_mm() - get_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @state: see struct ethtool_mm_state
+ *
+ * Drivers are expected to call this from their ethtool_ops :: get_mm()
+ * method.
+ */
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	state->verify_enabled = mmsv->verify_enabled;
+	state->pmac_enabled = mmsv->pmac_enabled;
+	state->verify_time = mmsv->verify_time;
+	state->tx_enabled = mmsv->tx_enabled;
+	state->verify_status = mmsv->status;
+	state->tx_active = ethtool_mmsv_is_tx_active(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_get_mm);
+
+/**
+ * ethtool_mmsv_set_mm() - set_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @cfg: see struct ethtool_mm_cfg
+ *
+ * Drivers are expected to call this from their ethtool_ops :: set_mm()
+ * method.
+ */
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg)
+{
+	unsigned long flags;
+
+	/* Wait for the verification that's currently in progress to finish */
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	mmsv->verify_enabled = cfg->verify_enabled;
+	mmsv->pmac_enabled = cfg->pmac_enabled;
+	mmsv->verify_time = cfg->verify_time;
+	mmsv->tx_enabled = cfg->tx_enabled;
+
+	if (!cfg->verify_enabled)
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+
+	ethtool_mmsv_apply(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_set_mm);
+
+/**
+ * ethtool_mmsv_init() - Initialize MAC Merge Software Verification state
+ * @mmsv: MAC Merge Software Verification state
+ * @dev: Pointer to network interface
+ * @ops: Methods for implementing the generic functionality
+ *
+ * The MAC Merge Software Verification is a timer- and event-based state
+ * machine intended for network interfaces which lack a hardware-based
+ * TX verification process (as per IEEE 802.3 clause 99.4.3). The timer
+ * is managed by the core code, whereas events are supplied by the
+ * driver explicitly calling one of the other API functions.
+ */
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops)
+{
+	mmsv->ops = ops;
+	mmsv->dev = dev;
+	mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+	mmsv->verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+	timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+	spin_lock_init(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_init);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:37 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:37 -0400
Subject: [PATCH iwl-next v9 03/14] net: ethtool: mm: reset verification status when link is down
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-4-faizal.abdul.rahim@linux.intel.com>

When the link partner goes down, "ethtool --show-mm" still displays
"Verification status: SUCCEEDED," reflecting a previous state that is
no longer valid.

Reset the verification status to ensure it reflects the current state.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 net/ethtool/mm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index bfd988464d7d..ad9b40034003 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -415,6 +415,10 @@ void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
 		/* New link => maybe new partner => new verification process */
 		ethtool_mmsv_apply(mmsv);
 	} else {
+		/* Reset the reported verification state while the link is down */
+		if (mmsv->verify_enabled)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+
 		/* No link or pMAC not enabled */
 		ethtool_mmsv_configure_pmac(mmsv, false);
 		ethtool_mmsv_configure_tx(mmsv, false);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:38 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:38 -0400
Subject: [PATCH iwl-next v9 04/14] igc: rename xdp_get_tx_ring() for non-xdp usage
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-5-faizal.abdul.rahim@linux.intel.com>

Renamed xdp_get_tx_ring() function to a more generic name for use in
upcoming frame preemption patches.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h      | 2 +-
 drivers/net/ethernet/intel/igc/igc_main.c | 9 ++++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index cd1d7b6c1782..ba7c55d2dc85 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -737,7 +737,7 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
-
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 472f009630c9..99123eef610b 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2464,8 +2464,7 @@ static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
 	return -ENOMEM;
 }
 
-static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
-					    int cpu)
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu)
 {
 	int index = cpu;
 
@@ -2489,7 +2488,7 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
 	if (unlikely(!xdpf))
 		return -EFAULT;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
@@ -2566,7 +2565,7 @@ static void igc_finalize_xdp(struct igc_adapter *adapter, int status)
 	struct igc_ring *ring;
 
 	if (status & IGC_XDP_TX) {
-		ring = igc_xdp_get_tx_ring(adapter, cpu);
+		ring = igc_get_tx_ring(adapter, cpu);
 		nq = txring_txq(ring);
 
 		__netif_tx_lock(nq, cpu);
@@ -6779,7 +6778,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
 	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
 		return -EINVAL;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:39 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:39 -0400
Subject: [PATCH iwl-next v9 05/14] igc: rename I225_RXPBSIZE_DEFAULT and I225_TXPBSIZE_DEFAULT
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-6-faizal.abdul.rahim@linux.intel.com>

Rename RX and TX packet buffer size macros in preparation for an
upcoming patch that will refactor buffer size handling using FIELD_PREP
and GENMASK.

Changes:
- Rename I225_RXPBSIZE_DEFAULT to IGC_RXPBSIZE_EXP_BMC_DEFAULT.
  The EXP_BMC suffix explicitly indicates Express and BMC buffer
  default values, improving readability and reusability for the
  upcoming changes, while also better reflecting the current buffer
  allocations.
- Rename I225_TXPBSIZE_DEFAULT to IGC_TXPBSIZE_DEFAULT.

These registers apply to both i225 and i226, so using the IGC prefix
aligns with existing macro naming conventions.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 7 ++++---
 drivers/net/ethernet/intel/igc/igc_main.c    | 4 ++--
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 8e449904aa7d..b6744ece64f0 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -396,9 +396,10 @@
 #define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
 #define IGC_RCTL_SECRC		0x04000000 /* Strip Ethernet CRC */
 
-#define I225_RXPBSIZE_DEFAULT	0x000000A2 /* RXPBSIZE default */
-#define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
-#define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */
+/* RXPBSIZE default value for Express and BMC buffer */
+#define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
+#define IGC_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
+#define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
 
 #define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
 
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 99123eef610b..6f0110e3ac22 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -7156,8 +7156,8 @@ static int igc_probe(struct pci_dev *pdev,
 	}
 
 	/* configure RXPBSIZE and TXPBSIZE */
-	wr32(IGC_RXPBS, I225_RXPBSIZE_DEFAULT);
-	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
+	wr32(IGC_RXPBS, IGC_RXPBSIZE_EXP_BMC_DEFAULT);
+	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 
 	timer_setup(&adapter->watchdog_timer, igc_watchdog, 0);
 	timer_setup(&adapter->phy_info_timer, igc_update_phy_info, 0);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 1e44374ca1ff..498741d83ca6 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -136,7 +136,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	int i;
 
 	wr32(IGC_GTXOFFSET, 0);
-	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
+	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
 	if (igc_is_device_id_i226(hw))
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:40 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:40 -0400
Subject: [PATCH iwl-next v9 06/14] igc: use FIELD_PREP and GENMASK for existing TX packet buffer size
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-7-faizal.abdul.rahim@linux.intel.com>

In preparation for an upcoming patch that will modify the TX buffer size
in  TSN mode, replace IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT
implementation with new macros that utilizes FIELD_PREP and GENMASK for
clarity.

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

I've tested IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT before and after the
refactoring, and their values remain unchanged.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 23 ++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b6744ece64f0..b180e1497cc5 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -398,10 +398,29 @@
 
 /* RXPBSIZE default value for Express and BMC buffer */
 #define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
-#define IGC_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
 #define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
 
-#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
+/* Mask for TX packet buffer size */
+#define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
+#define IGC_TXPB1SIZE_MASK		GENMASK(11, 6)
+#define IGC_TXPB2SIZE_MASK		GENMASK(17, 12)
+#define IGC_TXPB3SIZE_MASK		GENMASK(23, 18)
+/* Mask for OS to BMC packet buffer size */
+#define IGC_OS2BMCPBSIZE_MASK		GENMASK(29, 24)
+/* TX Packet buffer size in KB */
+#define IGC_TXPB0SIZE(x)		FIELD_PREP(IGC_TXPB0SIZE_MASK, (x))
+#define IGC_TXPB1SIZE(x)		FIELD_PREP(IGC_TXPB1SIZE_MASK, (x))
+#define IGC_TXPB2SIZE(x)		FIELD_PREP(IGC_TXPB2SIZE_MASK, (x))
+#define IGC_TXPB3SIZE(x)		FIELD_PREP(IGC_TXPB3SIZE_MASK, (x))
+/* OS to BMC packet buffer size in KB */
+#define IGC_OS2BMCPBSIZE(x)		FIELD_PREP(IGC_OS2BMCPBSIZE_MASK, (x))
+/* Default value following I225/I226 SW User Manual Section 8.3.2 */
+#define IGC_TXPBSIZE_DEFAULT ( \
+	IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
+	IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
+#define IGC_TXPBSIZE_TSN ( \
+	IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \
+	IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4))
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:41 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:41 -0400
Subject: [PATCH iwl-next v9 07/14] igc: optimize TX packet buffer utilization for TSN mode
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-8-faizal.abdul.rahim@linux.intel.com>

In preparation for upcoming frame preemption patches, optimize the TX
packet buffer size. The total packet buffer size (RX + TX) is 64KB, with
a maximum of 34KB for either RX or TX. Split the buffer evenly,
allocating 32KB to each.

For TX, assign 7KB to each of the four TX packet buffers (total 28KB)
and reserve 4KB for BMC.

References:
I225/I226 SW User Manual Section 4.7.9, Section 8.3.2

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b180e1497cc5..db937931c646 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -419,8 +419,8 @@
 	IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
 	IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
 #define IGC_TXPBSIZE_TSN ( \
-	IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \
-	IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4))
+	IGC_TXPB0SIZE(7) | IGC_TXPB1SIZE(7) | IGC_TXPB2SIZE(7) | \
+	IGC_TXPB3SIZE(7) | IGC_OS2BMCPBSIZE(4))
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Sun Mar  9 03:46:48 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Sun,  9 Mar 2025 06:46:48 -0400
Subject: [PATCH iwl-next v9 14/14] igc: add support to get frame preemption statistics via ethtool
In-Reply-To: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250309104648.3895551-15-faizal.abdul.rahim@linux.intel.com>

Implemented "ethtool --include-statistics --show-mm" callback for IGC.

Tested preemption scenario to check preemption statistics:
1) Trigger verification handshake on both boards:
    $ sudo ethtool --set-mm enp1s0 pmac-enabled on
    $ sudo ethtool --set-mm enp1s0 tx-enabled on
    $ sudo ethtool --set-mm enp1s0 verify-enabled on
2) Set preemptible or express queue in taprio for tx board:
    $ sudo tc qdisc replace dev enp1s0 parent root handle 100 taprio \
      num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
      queues 1 at 0 1 at 1 1 at 2 1 at 3 base-time 0 sched-entry S F 100000 \
      fp E E P P
3) Send large size packets on preemptible queue
4) Send small size packets on express queue to preempt packets in
   preemptible queue
5) Show preemption statistics on the receiving board:
   $ ethtool --include-statistics --show-mm enp1s0
     MAC Merge layer state for enp1s0:
     pMAC enabled: on
     TX enabled: on
     TX active: on
     TX minimum fragment size: 64
     RX minimum fragment size: 60
     Verify enabled: on
     Verify time: 128
     Max verify time: 128
     Verification status: SUCCEEDED
     Statistics:
      MACMergeFrameAssErrorCount: 0
      MACMergeFrameSmdErrorCount: 0
      MACMergeFrameAssOkCount: 511
      MACMergeFragCountRx: 764
      MACMergeFragCountTx: 0
      MACMergeHoldCount: 0

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 40 ++++++++++++++++++++
 drivers/net/ethernet/intel/igc/igc_regs.h    | 16 ++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index fd4b4b332309..324a27a5bef9 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1819,6 +1819,45 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	return igc_tsn_offload_apply(adapter);
 }
 
+/**
+ * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
+ * @reg_value: Register value for IGC_PRMEXCPRCNT
+ * Return: The count of frame assembly errors.
+ */
+static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
+{
+	/* Out of order statistics */
+	u32 ooo_frame_cnt, ooo_frag_cnt;
+	u32 miss_frame_frag_cnt;
+
+	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
+	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
+	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
+
+	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
+}
+
+static u64 igc_ethtool_get_frame_smd_error(u32 reg_value)
+{
+	return FIELD_GET(IGC_PRMEXCPRCNT_OOO_SMDC, reg_value);
+}
+
+static void igc_ethtool_get_mm_stats(struct net_device *dev,
+				     struct ethtool_mm_stats *stats)
+{
+	struct igc_adapter *adapter = netdev_priv(dev);
+	struct igc_hw *hw = &adapter->hw;
+	u32 reg_value;
+
+	reg_value = rd32(IGC_PRMEXCPRCNT);
+
+	stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(reg_value);
+	stats->MACMergeFrameSmdErrorCount = igc_ethtool_get_frame_smd_error(reg_value);
+	stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT);
+	stats->MACMergeFragCountRx = rd32(IGC_PRMEVNTRCNT);
+	stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2115,6 +2154,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
 	.get_mm			= igc_ethtool_get_mm,
+	.get_mm_stats		= igc_ethtool_get_mm_stats,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index 12ddc5793651..f343c6bfc6be 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -222,6 +222,22 @@
 
 #define IGC_FTQF(_n)	(0x059E0 + (4 * (_n)))  /* 5-tuple Queue Fltr */
 
+/* Time sync registers - preemption statistics */
+#define IGC_PRMPTDRCNT		0x04284	/* Good RX Preempted Packets */
+#define IGC_PRMEVNTTCNT		0x04298	/* TX Preemption event counter */
+#define IGC_PRMEVNTRCNT		0x0429C	/* RX Preemption event counter */
+
+ /* Preemption Exception Counter */
+ #define IGC_PRMEXCPRCNT				0x42A0
+/* Received out of order packets with SMD-C */
+#define IGC_PRMEXCPRCNT_OOO_SMDC			0x000000FF
+/* Received out of order packets with SMD-C and wrong Frame CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAME_CNT			0x0000FF00
+/* Received out of order packets with SMD-C and wrong Frag CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAG_CNT			0x00FF0000
+/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
+#define IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
+
 /* Transmit Scheduling Registers */
 #define IGC_TQAVCTRL		0x3570
 #define IGC_TXQCTL(_n)		(0x3344 + 0x4 * (_n))
-- 
2.34.1



From sven at svenpeter.dev  Sun Mar  9 04:32:12 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sun,  9 Mar 2025 12:32:12 +0100
Subject: [GIT PULL] Third and final batch of Apple SoC DT updates for v6.15
Message-ID: <20250309113212.48137-1-sven@svenpeter.dev>

Hi,

This is our final pull request for Apple SoC device tree updates for v6.15
based on the previous one [1].
Drivers for the M1/M2 touchbar screen and pre-M1 (iPhone, etc.) backlight
have been merged since then and this batch includes the required device tree
nodes. Both drivers and these commits have been part of -next for at least a
few days. The corresponding drivers are scheduled to be included in the 6.15
merge window as well.



Best,

Sven


[1] https://lore.kernel.org/soc/20250302115808.59172-1-sven at svenpeter.dev/

The following changes since commit 44db68dee1f77260d7037319e911e9883a6ffe0e:

  arm64: dts: apple: Add touchbar digitizer nodes (2025-02-26 15:33:46 +0000)

are available in the Git repository at:

  https://github.com/AsahiLinux/linux.git tags/asahi-soc-dt-6.15-v3

for you to fetch changes up to e1bc21d8f8fde47173073a2d6233f5faa4864cfc:

  arm64: dts: apple: t8015: Add backlight nodes (2025-03-06 20:54:28 +0100)

----------------------------------------------------------------
Apple SoC DT updates for 6.15, final batch:

- Added touchbar screen nodes for M1/M2 platforms
- Added backlight nodes for iPhone, iPad and iPod touch

----------------------------------------------------------------
Nick Chan (5):
      arm64: dts: apple: s5l8960x: Add backlight nodes
      arm64: dts: apple: t7000: Add backlight nodes
      arm64: dts: apple: s800-0-3: Add backlight nodes
      arm64: dts: apple: t8010: Add backlight nodes
      arm64: dts: apple: t8015: Add backlight nodes

Sasha Finkelstein (1):
      arm64: dts: apple: Add touchbar screen nodes

 arch/arm64/boot/dts/apple/s5l8960x-5s.dtsi     |  4 ++
 arch/arm64/boot/dts/apple/s5l8960x.dtsi        |  7 +++
 arch/arm64/boot/dts/apple/s800-0-3-common.dtsi |  4 ++
 arch/arm64/boot/dts/apple/s800-0-3.dtsi        |  7 +++
 arch/arm64/boot/dts/apple/t7000-handheld.dtsi  |  4 ++
 arch/arm64/boot/dts/apple/t7000.dtsi           |  7 +++
 arch/arm64/boot/dts/apple/t8010-common.dtsi    |  4 ++
 arch/arm64/boot/dts/apple/t8010.dtsi           |  7 +++
 arch/arm64/boot/dts/apple/t8015-8.dtsi         |  4 ++
 arch/arm64/boot/dts/apple/t8015.dtsi           |  7 +++
 arch/arm64/boot/dts/apple/t8103-j293.dts       | 31 +++++++++++++
 arch/arm64/boot/dts/apple/t8103.dtsi           | 61 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/apple/t8112-j493.dts       | 31 +++++++++++++
 arch/arm64/boot/dts/apple/t8112.dtsi           | 61 ++++++++++++++++++++++++++
 14 files changed, 239 insertions(+)


From wahrenst at gmx.net  Sun Mar  9 05:50:11 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:11 +0100
Subject: [PATCH 2/5] staging: vchiq_arm: Fix possible NPR of keep-alive thread
In-Reply-To: <20250309125014.37166-1-wahrenst@gmx.net>
References: <20250309125014.37166-1-wahrenst@gmx.net>
Message-ID: <20250309125014.37166-3-wahrenst@gmx.net>

In case vchiq_platform_conn_state_changed() is never called or fails before
driver removal, ka_thread won't be a valid pointer to a task_struct. So
do the necessary checks before calling kthread_stop to avoid a crash.

Fixes: 863a756aaf49 ("staging: vc04_services: vchiq_core: Stop kthreads on vchiq module unload")
Signed-off-by: Stefan Wahren <wahrenst at gmx.net>
---
 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index e2e80e90b555..d3b7d1227d7d 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -1422,7 +1422,8 @@ static void vchiq_remove(struct platform_device *pdev)
 	kthread_stop(mgmt->state.slot_handler_thread);

 	arm_state = vchiq_platform_get_arm_state(&mgmt->state);
-	kthread_stop(arm_state->ka_thread);
+	if (!IS_ERR_OR_NULL(arm_state->ka_thread))
+		kthread_stop(arm_state->ka_thread);
 }

 static struct platform_driver vchiq_driver = {
--
2.34.1



From wahrenst at gmx.net  Sun Mar  9 05:50:09 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:09 +0100
Subject: [PATCH 0/5] staging: vchiq_arm: Fix & improve resource handling
Message-ID: <20250309125014.37166-1-wahrenst@gmx.net>

VCHIQ driver probe und remove have some resource release issues regarding
kthread and debugfs handling.

Stefan Wahren (5):
  staging: vchiq_arm: Register debugfs after cdev
  staging: vchiq_arm: Fix possible NPR of keep-alive thread
  staging: vchiq_arm: Stop kthreads if vchiq cdev register fails
  staging: vchiq_arm: Create keep-alive thread during probe
  staging: vchiq_arm: Improve initial VCHIQ connect

 .../interface/vchiq_arm/vchiq_arm.c           | 121 +++++++++---------
 .../interface/vchiq_arm/vchiq_core.c          |   1 +
 .../interface/vchiq_arm/vchiq_core.h          |   2 +
 3 files changed, 60 insertions(+), 64 deletions(-)

--
2.34.1



From wahrenst at gmx.net  Sun Mar  9 05:50:13 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:13 +0100
Subject: [PATCH 4/5] staging: vchiq_arm: Create keep-alive thread during probe
In-Reply-To: <20250309125014.37166-1-wahrenst@gmx.net>
References: <20250309125014.37166-1-wahrenst@gmx.net>
Message-ID: <20250309125014.37166-5-wahrenst@gmx.net>

Creating the keep-alive thread in vchiq_platform_init_state have
the following advantages:
- abort driver probe if kthread_create fails (more consistent behavior)
- make resource release process easier

Since vchiq_keepalive_thread_func is defined below
vchiq_platform_init_state, the latter must be moved.

Signed-off-by: Stefan Wahren <wahrenst at gmx.net>
---
 .../interface/vchiq_arm/vchiq_arm.c           | 69 +++++++++----------
 1 file changed, 34 insertions(+), 35 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 0c7ea2d0ee85..64f9536f1232 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -280,29 +280,6 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state
 	return 0;
 }

-int
-vchiq_platform_init_state(struct vchiq_state *state)
-{
-	struct vchiq_arm_state *platform_state;
-
-	platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL);
-	if (!platform_state)
-		return -ENOMEM;
-
-	rwlock_init(&platform_state->susp_res_lock);
-
-	init_completion(&platform_state->ka_evt);
-	atomic_set(&platform_state->ka_use_count, 0);
-	atomic_set(&platform_state->ka_use_ack_count, 0);
-	atomic_set(&platform_state->ka_release_count, 0);
-
-	platform_state->state = state;
-
-	state->platform_state = (struct opaque_platform_state *)platform_state;
-
-	return 0;
-}
-
 static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state)
 {
 	return (struct vchiq_arm_state *)state->platform_state;
@@ -1011,6 +988,39 @@ vchiq_keepalive_thread_func(void *v)
 	return 0;
 }

+int
+vchiq_platform_init_state(struct vchiq_state *state)
+{
+	struct vchiq_arm_state *platform_state;
+	char threadname[16];
+
+	platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL);
+	if (!platform_state)
+		return -ENOMEM;
+
+	snprintf(threadname, sizeof(threadname), "vchiq-keep/%d",
+		 state->id);
+	platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func,
+						   (void *)state, threadname);
+	if (IS_ERR(platform_state->ka_thread)) {
+		dev_err(state->dev, "couldn't create thread %s\n", threadname);
+		return PTR_ERR(platform_state->ka_thread);
+	}
+
+	rwlock_init(&platform_state->susp_res_lock);
+
+	init_completion(&platform_state->ka_evt);
+	atomic_set(&platform_state->ka_use_count, 0);
+	atomic_set(&platform_state->ka_use_ack_count, 0);
+	atomic_set(&platform_state->ka_release_count, 0);
+
+	platform_state->state = state;
+
+	state->platform_state = (struct opaque_platform_state *)platform_state;
+
+	return 0;
+}
+
 int
 vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
 		   enum USE_TYPE_E use_type)
@@ -1331,7 +1341,6 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state,
 				       enum vchiq_connstate newstate)
 {
 	struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
-	char threadname[16];

 	dev_dbg(state->dev, "suspend: %d: %s->%s\n",
 		state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate));
@@ -1346,17 +1355,7 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state,

 	arm_state->first_connect = 1;
 	write_unlock_bh(&arm_state->susp_res_lock);
-	snprintf(threadname, sizeof(threadname), "vchiq-keep/%d",
-		 state->id);
-	arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func,
-					      (void *)state,
-					      threadname);
-	if (IS_ERR(arm_state->ka_thread)) {
-		dev_err(state->dev, "suspend: Couldn't create thread %s\n",
-			threadname);
-	} else {
-		wake_up_process(arm_state->ka_thread);
-	}
+	wake_up_process(arm_state->ka_thread);
 }

 static const struct of_device_id vchiq_of_match[] = {
--
2.34.1



From wahrenst at gmx.net  Sun Mar  9 05:50:12 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:12 +0100
Subject: [PATCH 3/5] staging: vchiq_arm: Stop kthreads if vchiq cdev register fails
In-Reply-To: <20250309125014.37166-1-wahrenst@gmx.net>
References: <20250309125014.37166-1-wahrenst@gmx.net>
Message-ID: <20250309125014.37166-4-wahrenst@gmx.net>

In case the vchiq character device cannot be registered during probe,
all kthreads needs to be stopped to avoid resource leaks.

Fixes: 863a756aaf49 ("staging: vc04_services: vchiq_core: Stop kthreads on vchiq module unload")
Signed-off-by: Stefan Wahren <wahrenst at gmx.net>
---
 .../interface/vchiq_arm/vchiq_arm.c           | 25 ++++++++++++-------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index d3b7d1227d7d..0c7ea2d0ee85 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -308,6 +308,20 @@ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *
 	return (struct vchiq_arm_state *)state->platform_state;
 }

+static void
+vchiq_platform_uninit(struct vchiq_drv_mgmt *mgmt)
+{
+	struct vchiq_arm_state *arm_state;
+
+	kthread_stop(mgmt->state.sync_thread);
+	kthread_stop(mgmt->state.recycle_thread);
+	kthread_stop(mgmt->state.slot_handler_thread);
+
+	arm_state = vchiq_platform_get_arm_state(&mgmt->state);
+	if (!IS_ERR_OR_NULL(arm_state->ka_thread))
+		kthread_stop(arm_state->ka_thread);
+}
+
 void vchiq_dump_platform_state(struct seq_file *f)
 {
 	seq_puts(f, "  Platform: 2835 (VC master)\n");
@@ -1396,6 +1410,7 @@ static int vchiq_probe(struct platform_device *pdev)
 	ret = vchiq_register_chrdev(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n");
+		vchiq_platform_uninit(mgmt);
 		return ret;
 	}

@@ -1410,20 +1425,12 @@ static int vchiq_probe(struct platform_device *pdev)
 static void vchiq_remove(struct platform_device *pdev)
 {
 	struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(&pdev->dev);
-	struct vchiq_arm_state *arm_state;

 	vchiq_device_unregister(bcm2835_audio);
 	vchiq_device_unregister(bcm2835_camera);
 	vchiq_debugfs_deinit();
 	vchiq_deregister_chrdev();
-
-	kthread_stop(mgmt->state.sync_thread);
-	kthread_stop(mgmt->state.recycle_thread);
-	kthread_stop(mgmt->state.slot_handler_thread);
-
-	arm_state = vchiq_platform_get_arm_state(&mgmt->state);
-	if (!IS_ERR_OR_NULL(arm_state->ka_thread))
-		kthread_stop(arm_state->ka_thread);
+	vchiq_platform_uninit(mgmt);
 }

 static struct platform_driver vchiq_driver = {
--
2.34.1



From wahrenst at gmx.net  Sun Mar  9 05:50:10 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:10 +0100
Subject: [PATCH 1/5] staging: vchiq_arm: Register debugfs after cdev
In-Reply-To: <20250309125014.37166-1-wahrenst@gmx.net>
References: <20250309125014.37166-1-wahrenst@gmx.net>
Message-ID: <20250309125014.37166-2-wahrenst@gmx.net>

The commit 2a4d15a4ae98 ("staging: vchiq: Refactor vchiq cdev code")
moved the debugfs directory creation before vchiq character device
registration. In case the latter fails, the debugfs directory won't
be cleaned up.

Fixes: 2a4d15a4ae98 ("staging: vchiq: Refactor vchiq cdev code")
Signed-off-by: Stefan Wahren <wahrenst at gmx.net>
---
 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index a4e83e5d619b..e2e80e90b555 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -1386,8 +1386,6 @@ static int vchiq_probe(struct platform_device *pdev)
 		return ret;
 	}

-	vchiq_debugfs_init(&mgmt->state);
-
 	dev_dbg(&pdev->dev, "arm: platform initialised - version %d (min %d)\n",
 		VCHIQ_VERSION, VCHIQ_VERSION_MIN);

@@ -1401,6 +1399,8 @@ static int vchiq_probe(struct platform_device *pdev)
 		return ret;
 	}

+	vchiq_debugfs_init(&mgmt->state);
+
 	bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio");
 	bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera");

--
2.34.1



From wahrenst at gmx.net  Sun Mar  9 05:50:14 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun,  9 Mar 2025 13:50:14 +0100
Subject: [PATCH 5/5] staging: vchiq_arm: Improve initial VCHIQ connect
In-Reply-To: <20250309125014.37166-1-wahrenst@gmx.net>
References: <20250309125014.37166-1-wahrenst@gmx.net>
Message-ID: <20250309125014.37166-6-wahrenst@gmx.net>

The code to start the keep-alive thread on initial VCHIQ connect
within vchiq_platform_conn_state_changed is unnecessary complex.
Move the keep-alive thread wake-up into a separate function and call it
during VCHIQ connect.

Signed-off-by: Stefan Wahren <wahrenst at gmx.net>
---
 .../interface/vchiq_arm/vchiq_arm.c           | 28 +++++--------------
 .../interface/vchiq_arm/vchiq_core.c          |  1 +
 .../interface/vchiq_arm/vchiq_core.h          |  2 ++
 3 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 64f9536f1232..be0c2bf9561a 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -97,13 +97,6 @@ struct vchiq_arm_state {
 	 * tracked separately with the state.
 	 */
 	int peer_use_count;
-
-	/*
-	 * Flag to indicate that the first vchiq connect has made it through.
-	 * This means that both sides should be fully ready, and we should
-	 * be able to suspend after this point.
-	 */
-	int first_connect;
 };

 static int
@@ -1336,26 +1329,19 @@ vchiq_check_service(struct vchiq_service *service)
 	return ret;
 }

+void vchiq_platform_connected(struct vchiq_state *state)
+{
+	struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
+
+	wake_up_process(arm_state->ka_thread);
+}
+
 void vchiq_platform_conn_state_changed(struct vchiq_state *state,
 				       enum vchiq_connstate oldstate,
 				       enum vchiq_connstate newstate)
 {
-	struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
-
 	dev_dbg(state->dev, "suspend: %d: %s->%s\n",
 		state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate));
-	if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED)
-		return;
-
-	write_lock_bh(&arm_state->susp_res_lock);
-	if (arm_state->first_connect) {
-		write_unlock_bh(&arm_state->susp_res_lock);
-		return;
-	}
-
-	arm_state->first_connect = 1;
-	write_unlock_bh(&arm_state->susp_res_lock);
-	wake_up_process(arm_state->ka_thread);
 }

 static const struct of_device_id vchiq_of_match[] = {
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 8d5795db4f39..5e38609aad06 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -3343,6 +3343,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
 			return -EAGAIN;

 		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
+		vchiq_platform_connected(state);
 		complete(&state->connect);
 	}

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
index 9b4e766990a4..3b5c0618e567 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -575,6 +575,8 @@ int vchiq_send_remote_use(struct vchiq_state *state);

 int vchiq_send_remote_use_active(struct vchiq_state *state);

+void vchiq_platform_connected(struct vchiq_state *state);
+
 void vchiq_platform_conn_state_changed(struct vchiq_state *state,
 				       enum vchiq_connstate oldstate,
 				  enum vchiq_connstate newstate);
--
2.34.1



From devnull+j.ne.posteo.net at kernel.org  Sun Mar  9 06:16:19 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 09 Mar 2025 14:16:19 +0100
Subject: [PATCH 0/2] arm64: Device Tree for Ugoos AM3 board
Message-ID: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>

This patchset adds a device tree for Ugoos AM3, an Android TV box from
2018. Most hardware functionality has been tested, as noted in patch 2/2.

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
J. Neusch?fer (2):
      dt-bindings: arm: amlogic: Add Ogoos AM3
      arm64: dts: amlogic: Add Ogoos AM3

 Documentation/devicetree/bindings/arm/amlogic.yaml |  1 +
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 +-
 .../arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts | 95 ++++++++++++++++++++++
 4 files changed, 98 insertions(+), 1 deletion(-)
---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20250222-ugoos-am3-f67413860434

Best regards,
-- 
J. Neusch?fer <j.ne at posteo.net>




From devnull+j.ne.posteo.net at kernel.org  Sun Mar  9 06:16:20 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 09 Mar 2025 14:16:20 +0100
Subject: [PATCH 1/2] dt-bindings: arm: amlogic: Add Ogoos AM3
In-Reply-To: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>
References: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>
Message-ID: <20250309-ugoos-am3-v1-1-38cab5a4725b@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC.

  https://ugoos.com/ugoos-am3-16g

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 0647851ae1f55a27bfb148252532bcf15ca905bf..779568f158ce985e1d12fbee73418549cfc58705 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -127,6 +127,7 @@ properties:
               - minix,neo-u9h
               - nexbox,a1
               - tronsmart,vega-s96
+              - ugoos,am3
               - videostrong,gxm-kiii-pro
               - wetek,core2
           - const: amlogic,s912

-- 
2.48.0.rc1.219.gb6b6757d772




From devnull+j.ne.posteo.net at kernel.org  Sun Mar  9 06:16:21 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 09 Mar 2025 14:16:21 +0100
Subject: [PATCH 2/2] arm64: dts: amlogic: Add Ogoos AM3
In-Reply-To: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>
References: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>
Message-ID: <20250309-ugoos-am3-v1-2-38cab5a4725b@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC,
with a board design that is very close to the Q20x development boards.
The MMC max-frequency properties are copied from the downstream device
tree.

  https://ugoos.com/ugoos-am3-16g

The following functionality has been tested and is known to work:
 - debug serial port
 - "update" button inside the case
 - USB host mode, on all three ports
 - HDMI video/audio output
 - eMMC, MicroSD, and SDIO WLAN
 - S/PDIF audio output
 - Ethernet
 - Infrared remote control input

The following functionality doesn't seem to work:
 - USB role switching and device mode on the "OTG" port
 - case LED

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 +-
 .../arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts | 95 ++++++++++++++++++++++
 3 files changed, 97 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 2fbda8419c65a3056410ac45ca3ddaceb69ea4f5..bf2bc14528bfa27e8d6ae2730085fc356d6c6dd8 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -76,6 +76,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-libretech-pc.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
index 45ccddd1aaf0546632c81a52c8917a923beae883..4223b26f7d0f3aa47e42e9434d24f73b20441981 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
@@ -97,7 +97,7 @@ sdio_pwrseq: sdio-pwrseq {
 		clock-names = "ext_clock";
 	};
 
-	cvbs-connector {
+	cvbs_connector: cvbs-connector {
 		compatible = "composite-video-connector";
 
 		port {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
new file mode 100644
index 0000000000000000000000000000000000000000..c413736f4096df8727311844de352debd89cdfb9
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 J. Neusch?fer <j.ne at posteo.net>
+ *
+ * Debug UART (3.3V, 115200 baud) at the corner of the board:
+ *   (4) (3) (2) [1]
+ *   Vcc RXD TXD GND
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/amlogic,meson-g12a-gpio-intc.h>
+
+#include "meson-gxm.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "ugoos,am3", "amlogic,s912", "amlogic,meson-gxm";
+	model = "Ugoos AM3";
+
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 0>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1710000>;
+
+		button-function {
+			label = "Update";
+			linux,code = <KEY_VENDOR>;
+			press-threshold-microvolt = <10000>;
+		};
+	};
+};
+
+&cvbs_connector {
+	/* Not used on this board */
+	status = "disabled";
+};
+
+&ethmac {
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+
+	/* Select external PHY by default */
+	phy-handle = <&external_phy>;
+
+	amlogic,tx-delay-ns = <2>;
+
+	/* External PHY is in RGMII */
+	phy-mode = "rgmii";
+
+	status = "okay";
+};
+
+&external_mdio {
+	external_phy: ethernet-phy at 0 {
+		/* Realtek RTL8211F (0x001cc916) */
+		reg = <0>;
+
+		reset-assert-us = <10000>;
+		reset-deassert-us = <80000>;
+		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
+
+		interrupt-parent = <&gpio_intc>;
+		/* MAC_INTR on GPIOZ_15 */
+		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c_B {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c_b_pins>;
+
+	rtc: rtc at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+	};
+};
+
+/* WLAN: Atheros 10k (QCA9377) */
+&sd_emmc_a {
+	max-frequency = <200000000>;
+};
+
+&sdio_pwrseq {
+	reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	max-frequency = <100000000>;
+};

-- 
2.48.0.rc1.219.gb6b6757d772




From ansuelsmth at gmail.com  Sun Mar  9 06:29:31 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:31 +0100
Subject: [PATCH 00/13] airoha: en7581: clk cleanup + USB support
Message-ID: <20250309132959.19045-1-ansuelsmth@gmail.com>

This series implement all the changes required to correctly handle
USB support for the Airoha EN7581 SoC.

The first few patch are cleanup for the clock driver and the
introduction of the SCU SSR SoC driver.

The SoC always support USB 2.0 but for USB 3.0 it needs additional
configuration for the Serdes port. Such port can be either configured
for USB usage or for PCIe lines or HSGMII and these are configured
in the SCU space.

To correctly handle this, the SCU is changed to a simple-mfd
implemenetation and the clock controller updated to follow this new
node structure. Both implementation are supported to handle old
binding.

The xHCI USB is based on the Mediatek implementation but the PHY
handling although conceptually similar, is indded different compared
to Mediatek due to SSR checks and different port power up.

The SSR driver expose an API to poll the current status of the Serdes
port and the USB PHY driver validates it. Refer to the specific commit
for additional info.

Consider that there is currently an inconsistency as AN7581 and
EN7581 refer to the same thing. This is due to the fact that
the SoC born under EcoNet but then was acquired by Airoha.

Christian Marangi (13):
  clk: en7523: convert driver to regmap API
  clk: en7523: generalize register clocks function
  dt-bindings: soc: airoha: add SCU SSR Serdes port binding
  dt-bindings: soc: airoha: add Documentation for Airoha AN7581 SCU SSR
  dt-bindings: mfd: add Documentation for Airoha EN7581 SCU
  dt-bindings: clock: airoha: make reg optional for Airoha EN7581
  clk: en7523: support getting regmap from parent node for EN7581
  soc: airoha: add support for configuring SCU SSR Serdes port
  dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
  phy: airoha: Add support for Airoha AN7581 USB PHY
  usb: host: add ARCH_AIROHA in XHCI MTK dependency
  arm64: dts: airoha: en7581: convert SCU clock node to MFD
    implementation
  arm64: dts: airoha: en7581: add USB and SCU SSR nodes

 .../bindings/clock/airoha,en7523-scu.yaml     |  13 +-
 .../mfd/airoha,en7581-scu-sysctl.yaml         |  68 +++
 .../bindings/phy/airoha,an7581-usb-phy.yaml   | 106 ++++
 .../soc/airoha/airoha,an7581-scu-ssr.yaml     | 106 ++++
 MAINTAINERS                                   |  15 +
 arch/arm64/boot/dts/airoha/en7581.dtsi        |  74 ++-
 drivers/clk/clk-en7523.c                      | 258 ++++----
 drivers/phy/Kconfig                           |   1 +
 drivers/phy/Makefile                          |   3 +-
 drivers/phy/airoha/Kconfig                    |  13 +
 drivers/phy/airoha/Makefile                   |   3 +
 drivers/phy/airoha/phy-airoha-usb.c           | 554 ++++++++++++++++++
 drivers/soc/Kconfig                           |   1 +
 drivers/soc/Makefile                          |   1 +
 drivers/soc/airoha/Kconfig                    |  18 +
 drivers/soc/airoha/Makefile                   |   3 +
 drivers/soc/airoha/airoha-scu-ssr.c           | 195 ++++++
 drivers/usb/host/Kconfig                      |   2 +-
 include/dt-bindings/soc/airoha,scu-ssr.h      |  24 +
 include/linux/soc/airoha/airoha-scu-ssr.h     |  17 +
 include/linux/soc/soc/airoha-scu-ssr.h        |  17 +
 21 files changed, 1355 insertions(+), 137 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
 create mode 100644 Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
 create mode 100644 drivers/soc/airoha/Kconfig
 create mode 100644 drivers/soc/airoha/Makefile
 create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
 create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
 create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h
 create mode 100644 include/linux/soc/soc/airoha-scu-ssr.h

-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:33 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:33 +0100
Subject: [PATCH 02/13] clk: en7523: generalize register clocks function
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-3-ansuelsmth@gmail.com>

Generalize register clocks function for Airoha EN7523 and EN7581 clocks
driver. The same logic is applied for both clock hence code can be
reduced and simplified by putting the base_clocks struct in the soc_data
and passing that to a generic register clocks function.

There is always the pattern where the last clock is always the PCIe one.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c | 130 ++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 77 deletions(-)

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 314e7450313f..2a74bc8fed24 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -78,8 +78,10 @@ struct en_rst_data {
 
 struct en_clk_soc_data {
 	u32 num_clocks;
+	const struct en_clk_desc *base_clks;
 	const struct clk_ops pcie_ops;
 	int (*hw_init)(struct platform_device *pdev,
+		       const struct en_clk_soc_data *soc_data,
 		       struct clk_hw_onecell_data *clk_data);
 };
 
@@ -467,6 +469,50 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
 	return &cg->hw;
 }
 
+static void en75xx_register_clocks(struct device *dev,
+				   const struct en_clk_soc_data *soc_data,
+				   struct clk_hw_onecell_data *clk_data,
+				   struct regmap *map, struct regmap *clk_map)
+{
+	struct clk_hw *hw;
+	u32 rate;
+	int i;
+
+	for (i = 0; i < soc_data->num_clocks - 1; i++) {
+		const struct en_clk_desc *desc = &soc_data->base_clks[i];
+		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+		int err;
+
+		err = regmap_read(map, desc->base_reg, &val);
+		if (err) {
+			pr_err("Failed reading fixed clk rate %s: %d\n",
+			       desc->name, err);
+			continue;
+		}
+		rate = en7523_get_base_rate(desc, val);
+
+		err = regmap_read(map, reg, &val);
+		if (err) {
+			pr_err("Failed reading fixed clk div %s: %d\n",
+			       desc->name, err);
+			continue;
+		}
+		rate /= en7523_get_div(desc, val);
+
+		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register clk %s: %ld\n",
+			       desc->name, PTR_ERR(hw));
+			continue;
+		}
+
+		clk_data->hws[desc->id] = hw;
+	}
+
+	hw = en7523_register_pcie_clk(dev, clk_map);
+	clk_data->hws[soc_data->num_clocks] = hw;
+}
+
 static int en7581_pci_is_enabled(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
@@ -504,38 +550,6 @@ static void en7581_pci_disable(struct clk_hw *hw)
 	usleep_range(1000, 2000);
 }
 
-static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, struct regmap *clk_map)
-{
-	struct clk_hw *hw;
-	u32 rate;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7523_base_clks[i];
-		u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		u32 val;
-
-		regmap_read(map, desc->base_reg, &val);
-
-		rate = en7523_get_base_rate(desc, val);
-		regmap_read(map, reg, &val);
-		rate /= en7523_get_div(desc, val);
-
-		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
-		if (IS_ERR(hw)) {
-			pr_err("Failed to register clk %s: %ld\n",
-			       desc->name, PTR_ERR(hw));
-			continue;
-		}
-
-		clk_data->hws[desc->id] = hw;
-	}
-
-	hw = en7523_register_pcie_clk(dev, clk_map);
-	clk_data->hws[EN7523_CLK_PCIE] = hw;
-}
-
 static const struct regmap_config en7523_clk_regmap_config = {
 	.reg_bits = 32,
 	.val_bits = 32,
@@ -543,6 +557,7 @@ static const struct regmap_config en7523_clk_regmap_config = {
 };
 
 static int en7523_clk_hw_init(struct platform_device *pdev,
+			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	void __iomem *base, *np_base;
@@ -566,53 +581,11 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(clk_map))
 		return PTR_ERR(clk_map);
 
-	en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
+	en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
 
 	return 0;
 }
 
-static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, struct regmap *clk_map)
-{
-	struct clk_hw *hw;
-	u32 rate;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7581_base_clks[i];
-		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		int err;
-
-		err = regmap_read(map, desc->base_reg, &val);
-		if (err) {
-			pr_err("Failed reading fixed clk rate %s: %d\n",
-			       desc->name, err);
-			continue;
-		}
-		rate = en7523_get_base_rate(desc, val);
-
-		err = regmap_read(map, reg, &val);
-		if (err) {
-			pr_err("Failed reading fixed clk div %s: %d\n",
-			       desc->name, err);
-			continue;
-		}
-		rate /= en7523_get_div(desc, val);
-
-		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
-		if (IS_ERR(hw)) {
-			pr_err("Failed to register clk %s: %ld\n",
-			       desc->name, PTR_ERR(hw));
-			continue;
-		}
-
-		clk_data->hws[desc->id] = hw;
-	}
-
-	hw = en7523_register_pcie_clk(dev, clk_map);
-	clk_data->hws[EN7523_CLK_PCIE] = hw;
-}
-
 static int en7523_reset_update(struct reset_controller_dev *rcdev,
 			       unsigned long id, bool assert)
 {
@@ -689,6 +662,7 @@ static int en7581_reset_register(struct device *dev, struct regmap *map)
 }
 
 static int en7581_clk_hw_init(struct platform_device *pdev,
+			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	struct regmap *map, *clk_map;
@@ -706,7 +680,7 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(clk_map))
 		return PTR_ERR(clk_map);
 
-	en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
+	en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
 
 	regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
 			  REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
@@ -732,7 +706,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	clk_data->num = soc_data->num_clocks;
-	r = soc_data->hw_init(pdev, clk_data);
+	r = soc_data->hw_init(pdev, soc_data, clk_data);
 	if (r)
 		return r;
 
@@ -740,6 +714,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
 }
 
 static const struct en_clk_soc_data en7523_data = {
+	.base_clks = en7523_base_clks,
 	.num_clocks = ARRAY_SIZE(en7523_base_clks) + 1,
 	.pcie_ops = {
 		.is_enabled = en7523_pci_is_enabled,
@@ -750,6 +725,7 @@ static const struct en_clk_soc_data en7523_data = {
 };
 
 static const struct en_clk_soc_data en7581_data = {
+	.base_clks = en7581_base_clks,
 	/* We increment num_clocks by 1 to account for additional PCIe clock */
 	.num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
 	.pcie_ops = {
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:32 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:32 +0100
Subject: [PATCH 01/13] clk: en7523: convert driver to regmap API
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-2-ansuelsmth@gmail.com>

Convert driver to regmap API, in preparation for support of Airoha
AN7583 as the SCU will be an MFD and the regmap will be provided in the
parent node. Also Airoha EN7581 benefits from this in preparation of USB
support that required checking and configuring SCU SSR bits.

While at it also cleanup some register mask and use bitfield macro.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c | 137 ++++++++++++++++++++++-----------------
 1 file changed, 76 insertions(+), 61 deletions(-)

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 15bbdeb60b8e..314e7450313f 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
@@ -34,6 +35,7 @@
 #define   REG_RESET_CONTROL_PCIE2	BIT(26)
 /* EN7581 */
 #define REG_NP_SCU_PCIC			0x88
+#define REG_PCIE_CTRL			GENMASK(7, 0)
 #define REG_NP_SCU_SSTR			0x9c
 #define REG_PCIE_XSI0_SEL_MASK		GENMASK(14, 13)
 #define REG_PCIE_XSI1_SEL_MASK		GENMASK(12, 11)
@@ -63,14 +65,14 @@ struct en_clk_desc {
 };
 
 struct en_clk_gate {
-	void __iomem *base;
+	struct regmap *map;
 	struct clk_hw hw;
 };
 
 struct en_rst_data {
 	const u16 *bank_ofs;
 	const u16 *idx_map;
-	void __iomem *base;
+	struct regmap *map;
 	struct reset_controller_dev rcdev;
 };
 
@@ -388,44 +390,44 @@ static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
 static int en7523_pci_is_enabled(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+	u32 val;
 
-	return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
+	regmap_read(cg->map, REG_PCI_CONTROL, &val);
+	return !!(val & REG_PCI_CONTROL_REFCLK_EN1);
 }
 
 static int en7523_pci_prepare(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	/* Need to pull device low before reset */
-	val = readl(np_base + REG_PCI_CONTROL);
-	val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL,
+			  REG_PCI_CONTROL_PERSTOUT1 |
+			  REG_PCI_CONTROL_PERSTOUT);
 	usleep_range(1000, 2000);
 
 	/* Enable PCIe port 1 */
-	val |= REG_PCI_CONTROL_REFCLK_EN1;
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL,
+			REG_PCI_CONTROL_REFCLK_EN1);
 	usleep_range(1000, 2000);
 
 	/* Reset to default */
-	val = readl(np_base + REG_RESET_CONTROL1);
 	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
 	       REG_RESET_CONTROL_PCIEHB;
-	writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+	regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
 	usleep_range(1000, 2000);
-	writel(val | mask, np_base + REG_RESET_CONTROL1);
+	regmap_set_bits(map, REG_RESET_CONTROL1, mask);
 	msleep(100);
-	writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+	regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
 	usleep_range(5000, 10000);
 
 	/* Release device */
 	mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val & ~mask, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, mask);
 	usleep_range(1000, 2000);
-	writel(val | mask, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL, mask);
 	msleep(250);
 
 	return 0;
@@ -434,16 +436,13 @@ static int en7523_pci_prepare(struct clk_hw *hw)
 static void en7523_pci_unprepare(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val;
+	struct regmap *map = cg->map;
 
-	val = readl(np_base + REG_PCI_CONTROL);
-	val &= ~REG_PCI_CONTROL_REFCLK_EN1;
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, REG_PCI_CONTROL_REFCLK_EN1);
 }
 
 static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
-					       void __iomem *np_base)
+					       struct regmap *clk_map)
 {
 	const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
 	struct clk_init_data init = {
@@ -456,7 +455,7 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
 	if (!cg)
 		return NULL;
 
-	cg->base = np_base;
+	cg->map = clk_map;
 	cg->hw.init = &init;
 
 	if (init.ops->unprepare)
@@ -474,21 +473,20 @@ static int en7581_pci_is_enabled(struct clk_hw *hw)
 	u32 val, mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
-	val = readl(cg->base + REG_PCI_CONTROL);
+	regmap_read(cg->map, REG_PCI_CONTROL, &val);
 	return (val & mask) == mask;
 }
 
 static int en7581_pci_enable(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
 	       REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
 	       REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val | mask, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL, mask);
 
 	return 0;
 }
@@ -496,19 +494,18 @@ static int en7581_pci_enable(struct clk_hw *hw)
 static void en7581_pci_disable(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
 	       REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
 	       REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val & ~mask, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, mask);
 	usleep_range(1000, 2000);
 }
 
 static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   void __iomem *base, void __iomem *np_base)
+				   struct regmap *map, struct regmap *clk_map)
 {
 	struct clk_hw *hw;
 	u32 rate;
@@ -517,10 +514,12 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
 		const struct en_clk_desc *desc = &en7523_base_clks[i];
 		u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		u32 val = readl(base + desc->base_reg);
+		u32 val;
+
+		regmap_read(map, desc->base_reg, &val);
 
 		rate = en7523_get_base_rate(desc, val);
-		val = readl(base + reg);
+		regmap_read(map, reg, &val);
 		rate /= en7523_get_div(desc, val);
 
 		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
@@ -533,30 +532,47 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 		clk_data->hws[desc->id] = hw;
 	}
 
-	hw = en7523_register_pcie_clk(dev, np_base);
+	hw = en7523_register_pcie_clk(dev, clk_map);
 	clk_data->hws[EN7523_CLK_PCIE] = hw;
 }
 
+static const struct regmap_config en7523_clk_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
 static int en7523_clk_hw_init(struct platform_device *pdev,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	void __iomem *base, *np_base;
+	struct regmap *map, *clk_map;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	map = devm_regmap_init_mmio(&pdev->dev, base,
+				    &en7523_clk_regmap_config);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
 	np_base = devm_platform_ioremap_resource(pdev, 1);
 	if (IS_ERR(np_base))
 		return PTR_ERR(np_base);
 
-	en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
+	clk_map = devm_regmap_init_mmio(&pdev->dev, np_base,
+					&en7523_clk_regmap_config);
+	if (IS_ERR(clk_map))
+		return PTR_ERR(clk_map);
+
+	en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
 
 	return 0;
 }
 
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, void __iomem *base)
+				   struct regmap *map, struct regmap *clk_map)
 {
 	struct clk_hw *hw;
 	u32 rate;
@@ -593,7 +609,7 @@ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 		clk_data->hws[desc->id] = hw;
 	}
 
-	hw = en7523_register_pcie_clk(dev, base);
+	hw = en7523_register_pcie_clk(dev, clk_map);
 	clk_data->hws[EN7523_CLK_PCIE] = hw;
 }
 
@@ -601,15 +617,10 @@ static int en7523_reset_update(struct reset_controller_dev *rcdev,
 			       unsigned long id, bool assert)
 {
 	struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
-	void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
-	u32 val;
+	u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
 
-	val = readl(addr);
-	if (assert)
-		val |= BIT(id % RST_NR_PER_BANK);
-	else
-		val &= ~BIT(id % RST_NR_PER_BANK);
-	writel(val, addr);
+	regmap_update_bits(rst_data->map, addr, BIT(id % RST_NR_PER_BANK),
+			   assert ? BIT(id % RST_NR_PER_BANK) : 0);
 
 	return 0;
 }
@@ -630,9 +641,11 @@ static int en7523_reset_status(struct reset_controller_dev *rcdev,
 			       unsigned long id)
 {
 	struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
-	void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
+	u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
+	u32 val;
 
-	return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
+	regmap_read(rst_data->map, addr, &val);
+	return !!(val & BIT(id % RST_NR_PER_BANK));
 }
 
 static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
@@ -652,7 +665,7 @@ static const struct reset_control_ops en7581_reset_ops = {
 	.status = en7523_reset_status,
 };
 
-static int en7581_reset_register(struct device *dev, void __iomem *base)
+static int en7581_reset_register(struct device *dev, struct regmap *map)
 {
 	struct en_rst_data *rst_data;
 
@@ -662,7 +675,7 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
 
 	rst_data->bank_ofs = en7581_rst_ofs;
 	rst_data->idx_map = en7581_rst_map;
-	rst_data->base = base;
+	rst_data->map = map;
 
 	rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
 	rst_data->rcdev.of_xlate = en7523_reset_xlate;
@@ -678,9 +691,8 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
 static int en7581_clk_hw_init(struct platform_device *pdev,
 			      struct clk_hw_onecell_data *clk_data)
 {
-	struct regmap *map;
+	struct regmap *map, *clk_map;
 	void __iomem *base;
-	u32 val;
 
 	map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
 	if (IS_ERR(map))
@@ -690,15 +702,18 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	en7581_register_clocks(&pdev->dev, clk_data, map, base);
+	clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
+	if (IS_ERR(clk_map))
+		return PTR_ERR(clk_map);
+
+	en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
 
-	val = readl(base + REG_NP_SCU_SSTR);
-	val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
-	writel(val, base + REG_NP_SCU_SSTR);
-	val = readl(base + REG_NP_SCU_PCIC);
-	writel(val | 3, base + REG_NP_SCU_PCIC);
+	regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
+			  REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+	regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
+			   FIELD_PREP(REG_PCIE_CTRL, 3));
 
-	return en7581_reset_register(&pdev->dev, base);
+	return en7581_reset_register(&pdev->dev, clk_map);
 }
 
 static int en7523_clk_probe(struct platform_device *pdev)
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:34 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:34 +0100
Subject: [PATCH 03/13] dt-bindings: soc: airoha: add SCU SSR Serdes port binding
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-4-ansuelsmth@gmail.com>

Add Airoha AN7581 SCU SSR Serdes port binding to define what mode is
supported by each Serdes port. These special binding are needed to
identify and provide the port mode from any user driver.

These modes are mutually exclusive and driver needs to correctly
validate the current mode for the Serdes port in use.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                              |  6 ++++++
 include/dt-bindings/soc/airoha,scu-ssr.h | 24 ++++++++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 3eee238c2ea2..d3125268d63f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -736,6 +736,12 @@ F:	Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
 F:	drivers/phy/phy-airoha-pcie-regs.h
 F:	drivers/phy/phy-airoha-pcie.c
 
+AIROHA SCU SSR DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	include/dt-bindings/soc/airoha,scu-ssr.h
+
 AIROHA SPI SNFI DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
 M:	Ray Liu <ray.liu at airoha.com>
diff --git a/include/dt-bindings/soc/airoha,scu-ssr.h b/include/dt-bindings/soc/airoha,scu-ssr.h
new file mode 100644
index 000000000000..b14457c10d77
--- /dev/null
+++ b/include/dt-bindings/soc/airoha,scu-ssr.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef __DT_BINDINGS_AIROHA_SCU_SSR_H
+#define __DT_BINDINGS_AIROHA_SCU_SSR_H
+
+/* WiFi1 port can be PCIe0 2 line, PCIe0 1 line or Ethernet (USXGMII/HSGMII) */
+#define AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE	0
+#define AIROHA_SCU_SSR_WIFI1_PCIE0		1
+#define AIROHA_SCU_SSR_WIFI1_ETHERNET		2
+
+/* WiFi2 port can be PCIe0 2 line, PCIe1 1 line or Ethernet (USXGMII/HSGMII) */
+#define AIROHA_SCU_SSR_WIFI2_PCIE0_2LINE	0
+#define AIROHA_SCU_SSR_WIFI2_PCIE1		1
+#define AIROHA_SCU_SSR_WIFI2_ETHERNET		2
+
+/* USB1 port can be USB 3.0 port or Ethernet (HSGMII) */
+#define AIROHA_SCU_SSR_USB1_USB			0
+#define AIROHA_SCU_SSR_USB1_ETHERNET		1
+
+/* USB2 port can be USB 3.0 port or PCIe2 1 line */
+#define AIROHA_SCU_SSR_USB2_USB			0
+#define AIROHA_SCU_SSR_USB2_PCIE2		1
+
+#endif /* __DT_BINDINGS_AIROHA_SCU_SSR_H */
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:35 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:35 +0100
Subject: [PATCH 04/13] dt-bindings: soc: airoha: add Documentation for Airoha AN7581 SCU SSR
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-5-ansuelsmth@gmail.com>

The Airoha AN7581 SoC have in the SCU register space particular
address that control how some peripheral are configured.

These are toggeled in the System Status Register and are used to
toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).

Modes are mutually exclusive and selecting one mode cause the
other feature to not work (example a mode in USB 3.0 cause PCIe
port 2 to not work) This depends also on what is physically
connected to the Hardware and needs to correctly reflect the
System Status Register bits.

Special care is needed for PCIe port 0 in 2 line mode that
requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
mode.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../soc/airoha/airoha,an7581-scu-ssr.yaml     | 106 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 107 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml

diff --git a/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
new file mode 100644
index 000000000000..4bbf6e3b79a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/airoha/airoha,an7581-scu-ssr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7581 SCU System Status Register
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  The Airoha AN7581 SoC have in the SCU register space particular
+  address that control how some peripheral are configured.
+
+  These are toggeled in the System Status Register and are used to
+  toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
+  or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).
+
+  Modes are mutually exclusive and selecting one mode cause the
+  other feature to not work (example a mode in USB 3.0 cause PCIe
+  port 2 to not work) This depends also on what is physically
+  connected to the Hardware and needs to correctly reflect the
+  System Status Register bits.
+
+  Special care is needed for PCIe port 0 in 2 line mode that
+  requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
+  mode.
+
+properties:
+  compatible:
+    const: airoha,an7581-scu-ssr
+
+  airoha,serdes-wifi1:
+    description: |
+      Configure the Wifi1 Serdes port for:
+      - 0: PCIe0 2 Line
+      - 1: PCIe0 1 Line
+      - 2: Ethernet modes (HSGMII/USXGMII)
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2]
+    default: 1
+
+  airoha,serdes-wifi2:
+    description: |
+      Configure the Wifi2 Serdes port for:
+      - 0: PCIe0 2 Line
+      - 1: PCIe1 1 Line
+      - 2: Ethernet modes (HSGMII/USXGMII)
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2]
+    default: 1
+
+  airoha,serdes-usb1:
+    description: |
+      Configure the USB1 Serdes port for:
+      - 0: USB 3.0
+      - 1: Ethernet modes (HSGMII)
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+    default: 0
+
+  airoha,serdes-usb2:
+    description: |
+      Configure the USB2 Serdes port for:
+      - 0: USB 3.0
+      - 1: PCIe2 1 Line
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+    default: 0
+
+required:
+  - compatible
+
+allOf:
+  - if:
+      properties:
+        airoha,serdes-wifi1:
+          const: 0
+    then:
+      properties:
+        airoha,serdes-wifi2:
+          const: 0
+
+  - if:
+      properties:
+        airoha,serdes-wifi2:
+          const: 0
+    then:
+      properties:
+        airoha,serdes-wifi1:
+          const: 0
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/airoha,scu-ssr.h>
+
+    system-controller {
+      compatible = "airoha,an7581-scu-ssr";
+
+      airoha,serdes-wifi1 = <AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE>;
+      airoha,serdes-wifi2 = <AIROHA_SCU_SSR_WIFI2_PCIE0_2LINE>;
+      airoha,serdes-usb2 = <AIROHA_SCU_SSR_USB2_PCIE2>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index d3125268d63f..9944845ae9f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -740,6 +740,7 @@ AIROHA SCU SSR DRIVER
 M:	Christian Marangi <ansuelsmth at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
 F:	include/dt-bindings/soc/airoha,scu-ssr.h
 
 AIROHA SPI SNFI DRIVER
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:36 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:36 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha EN7581 SCU
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-6-ansuelsmth@gmail.com>

Add Documentation for Airoha EN7581 SCU.

Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
via the SCU (System Controller Unit).

Example of these pheriperals are reset-controller, clock-controller,
PCIe line speed controller and bits to configure different Serdes ports
for USB or Ethernet usage.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml

diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
new file mode 100644
index 000000000000..d7dc66f912c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7581 SCU (System Controller Unit)
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description:
+  Airoha EN7581 SoC expose registers to control miscellaneous
+  pheriperals via the SCU (System Controller Unit).
+
+  Example of these pheriperals are reset-controller, clock-controller,
+  PCIe line speed controller and bits to configure different Serdes ports
+  for USB or Ethernet usage.
+
+properties:
+  compatible:
+    items:
+      - const: airoha,en7581-scu-sysctl
+      - const: syscon
+      - const: simple-mfd
+
+  reg:
+    maxItems: 1
+
+  clock-controller:
+    type: object
+    $ref: /schemas/clock/airoha,en7523-scu.yaml
+    description:
+      Child node definition for EN7581 Clock controller
+
+  system-controller:
+    type: object
+    $ref: /schemas/soc/airoha/airoha,an7581-scu-ssr.yaml
+    description:
+      Child node definition for EN7581 System Status Register
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/airoha,scu-ssr.h>
+
+    system-controller at 1fb00000 {
+        compatible = "airoha,en7581-scu-sysctl", "syscon", "simple-mfd";
+        reg = <0x1fb00000 0x970>;
+
+        clock-controller {
+            compatible = "airoha,en7581-scu";
+
+            #clock-cells = <1>;
+            #reset-cells = <1>;
+        };
+
+        system-controller {
+            compatible = "airoha,an7581-scu-ssr";
+
+            airoha,serdes-usb2 = <AIROHA_SCU_SSR_USB2_PCIE2>;
+        };
+    };
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:37 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:37 +0100
Subject: [PATCH 06/13] dt-bindings: clock: airoha: make reg optional for Airoha EN7581
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-7-ansuelsmth@gmail.com>

The Airoha EN7581 clock-controller registers are placed in the SCU
(System Controller Unit). Now that additional pheriperals are supported
for the SCU, a dedicated SCU node is created and the clock-controller is
moved as a child of such node hence the register property is taken from
the parent node.

To support this, make the reg property optional and provide an
additional example for this case.

Driver supports both old and new implementation by checking the presence
of the reg property and parsing the register accordingly.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/clock/airoha,en7523-scu.yaml           | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
index fe2c5c1baf43..84e6c3d43868 100644
--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
@@ -51,7 +51,6 @@ properties:
 
 required:
   - compatible
-  - reg
   - '#clock-cells'
 
 allOf:
@@ -66,6 +65,9 @@ allOf:
 
         '#reset-cells': false
 
+      required:
+        - reg
+
   - if:
       properties:
         compatible:
@@ -99,3 +101,12 @@ examples:
               #reset-cells = <1>;
       };
     };
+
+  # Example with clock-controller in SCU MFD
+  - |
+    clock-controller {
+      compatible = "airoha,en7581-scu";
+
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+    };
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:38 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:38 +0100
Subject: [PATCH 07/13] clk: en7523: support getting regmap from parent node for EN7581
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-8-ansuelsmth@gmail.com>

Add support for getting clock regmap from parent node for Airoha EN7581.

This is needed to support new implementation with SCU (System Controller
Unit) as an MFD and clock-controller node as a child node of it.

In such implementation the register regmap is provided as a syscon from
the parent node.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 2a74bc8fed24..29cb7ccea29a 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -665,6 +665,7 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
+	struct device *dev = &pdev->dev;
 	struct regmap *map, *clk_map;
 	void __iomem *base;
 
@@ -672,22 +673,28 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
-	if (IS_ERR(clk_map))
-		return PTR_ERR(clk_map);
+	if (of_property_present(dev->of_node, "reg")) {
+		base = devm_platform_ioremap_resource(pdev, 0);
+		if (IS_ERR(base))
+			return PTR_ERR(base);
+
+		clk_map = devm_regmap_init_mmio(dev, base, &en7523_clk_regmap_config);
+		if (IS_ERR(clk_map))
+			return PTR_ERR(clk_map);
+	} else {
+		clk_map = device_node_to_regmap(dev->parent->of_node);
+		if (IS_ERR(clk_map))
+			return PTR_ERR(clk_map);
+	}
 
-	en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
+	en75xx_register_clocks(dev, soc_data, clk_data, map, clk_map);
 
 	regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
 			  REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
 	regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
 			   FIELD_PREP(REG_PCIE_CTRL, 3));
 
-	return en7581_reset_register(&pdev->dev, clk_map);
+	return en7581_reset_register(dev, clk_map);
 }
 
 static int en7523_clk_probe(struct platform_device *pdev)
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:39 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:39 +0100
Subject: [PATCH 08/13] soc: airoha: add support for configuring SCU SSR Serdes port
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-9-ansuelsmth@gmail.com>

Add support for configuring SCU SSR Serdes port. Airoha AN7581 SoC can
configure the different Serdes port by toggling bits in the SCU register
space.

Port Serdes mode are mutually exclusive, force example the USB2 Serdes port
can either used for USB 3.0 or PCIe 2 port. Enabling USB 3.0 makes the
PCIe 2 to not work.

The current supported Serdes port are:
- WiFi 1 and defaults to PCIe0 1 line mode
- Wifi 2 and defaults to PCIe1 1 line mode
- USB 1 and defaults to USB 3.0 mode
- USB 2 and defaults to USB 3.0 mode

WiFi 1, WiFi 2 and USB 1 also support a particular Ethernet mode that
can toggle between USXGMII or HSGMII mode (USB 1 only to HSGMII)
Such mode doesn't configure bits as specific Ethernet PCS driver will
take care of configuring the Serdes mode based on what is required.

This driver is to correctly setup these bits and provide an API to read
the current status of the Serdes port. Single driver can't independently
set the Serdes port mode as that would cause a conflict if someone
declare, for example, in DT (and enable) PCIe 2 port and USB2 3.0 port.

Drivers will use the airoha_scu_ssr_get_serdes_mode function and will
validate the Serdes port is the expected one and fail if it's not.

Each driver will have to define in DT the phandle airoha,scu-ssr
pointing to the SCU SSR node.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                               |   1 +
 drivers/soc/Kconfig                       |   1 +
 drivers/soc/Makefile                      |   1 +
 drivers/soc/airoha/Kconfig                |  18 ++
 drivers/soc/airoha/Makefile               |   3 +
 drivers/soc/airoha/airoha-scu-ssr.c       | 195 ++++++++++++++++++++++
 include/linux/soc/airoha/airoha-scu-ssr.h |  17 ++
 include/linux/soc/soc/airoha-scu-ssr.h    |  17 ++
 8 files changed, 253 insertions(+)
 create mode 100644 drivers/soc/airoha/Kconfig
 create mode 100644 drivers/soc/airoha/Makefile
 create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
 create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h
 create mode 100644 include/linux/soc/soc/airoha-scu-ssr.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9944845ae9f5..fe34c80b8d52 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -741,6 +741,7 @@ M:	Christian Marangi <ansuelsmth at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
+F:	drivers/soc/airoha/airoha-scu-ssr.c
 F:	include/dt-bindings/soc/airoha,scu-ssr.h
 
 AIROHA SPI SNFI DRIVER
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 6a8daeb8c4b9..21bacefd2e06 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/airoha/Kconfig"
 source "drivers/soc/amlogic/Kconfig"
 source "drivers/soc/apple/Kconfig"
 source "drivers/soc/aspeed/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 2037a8695cb2..4338730af0aa 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_AIROHA)	+= airoha/
 obj-y				+= apple/
 obj-y				+= aspeed/
 obj-$(CONFIG_ARCH_AT91)		+= atmel/
diff --git a/drivers/soc/airoha/Kconfig b/drivers/soc/airoha/Kconfig
new file mode 100644
index 000000000000..56c677f8238d
--- /dev/null
+++ b/drivers/soc/airoha/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config AIROHA_SCU_SSR
+	tristate "Airoha SCU SSR Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	help
+	  Say 'Y' here to add support for Airoha SCU SSR driver.
+
+	  Airoha SoC pheriperal (like USB/PCIe/Ethernet port) are
+	  selected by toggling specific bit. Serdes Port line
+	  are mutually exclusive such as selecting PCIe port 2
+	  disable support for USB port 2 3.0 mode.
+
+	  This driver is used to configure such bit and expose
+	  an API to read the current status from a user of such
+	  Serdes lines.
+
diff --git a/drivers/soc/airoha/Makefile b/drivers/soc/airoha/Makefile
new file mode 100644
index 000000000000..530825251ae9
--- /dev/null
+++ b/drivers/soc/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_AIROHA_SCU_SSR)		+= airoha-scu-ssr.o
diff --git a/drivers/soc/airoha/airoha-scu-ssr.c b/drivers/soc/airoha/airoha-scu-ssr.c
new file mode 100644
index 000000000000..fe65b5b91146
--- /dev/null
+++ b/drivers/soc/airoha/airoha-scu-ssr.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <dt-bindings/soc/airoha,scu-ssr.h>
+#include <linux/bitfield.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/airoha/airoha-scu-ssr.h>
+
+#define AIROHA_SCU_PCIC			0x88
+#define   AIROHA_SCU_PCIE_2LANE_MODE	BIT(14)
+
+#define AIROHA_SCU_SSR3			0x94
+#define   AIROHA_SCU_SSUSB_HSGMII_SEL	BIT(29)
+
+#define AIROHA_SCU_SSTR			0x9c
+#define   AIROHA_SCU_PCIE_XSI0_SEL	GENMASK(14, 13)
+#define   AIROHA_SCU_PCIE_XSI0_SEL_PCIE	FIELD_PREP_CONST(AIROHA_SCU_PCIE_XSI0_SEL, 0x0)
+#define   AIROHA_SCU_PCIE_XSI1_SEL	GENMASK(12, 11)
+#define   AIROHA_SCU_PCIE_XSI1_SEL_PCIE	FIELD_PREP_CONST(AIROHA_SCU_PCIE_XSI0_SEL, 0x0)
+#define   AIROHA_SCU_USB_PCIE_SEL	BIT(3)
+
+struct airoha_scu_ssr_priv {
+	struct device *dev;
+	struct regmap *regmap;
+
+	u32 serdes_port[AIROHA_SCU_MAX_SERDES_PORT];
+};
+
+int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+				   enum airoha_scu_serdes_port port)
+{
+	struct airoha_scu_ssr_priv *priv;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	np = of_parse_phandle(dev->of_node, "airoha,scu-ssr", 0);
+	if (!np)
+		return -ENODEV;
+
+	if (!of_device_is_available(np)) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(np);
+	of_node_put(np);
+	if (!pdev || !platform_get_drvdata(pdev)) {
+		if (pdev)
+			put_device(&pdev->dev);
+		return -EPROBE_DEFER;
+	}
+
+	priv = platform_get_drvdata(pdev);
+
+	return priv->serdes_port[port];
+}
+EXPORT_SYMBOL_GPL(airoha_scu_ssr_get_serdes_mode);
+
+static int airoha_scu_ssr_apply_modes(struct airoha_scu_ssr_priv *priv)
+{
+	int ret;
+
+	/*
+	 * This is a very bad scenario and needs to be correctly warned
+	 * as it cause PCIe malfunction
+	 */
+	if ((priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE &&
+	     priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] != AIROHA_SCU_SSR_WIFI2_PCIE0_2LINE) ||
+	    (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] != AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE &&
+	     priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SSR_WIFI2_PCIE0_2LINE)) {
+		WARN(true, "Wrong Serdes configuration for PCIe0 2 Line mode. Please check DT.\n");
+		return -EINVAL;
+	}
+
+	/* PCS driver takes case of setting the SCU bit for HSGMII or USXGMII */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE ||
+	    priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SSR_WIFI1_PCIE0) {
+		ret = regmap_update_bits(priv->regmap, AIROHA_SCU_SSTR,
+					 AIROHA_SCU_PCIE_XSI0_SEL,
+					 AIROHA_SCU_PCIE_XSI0_SEL_PCIE);
+		if (ret)
+			return ret;
+	}
+
+	/* PCS driver takes case of setting the SCU bit for HSGMII or USXGMII */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SSR_WIFI2_PCIE0_2LINE ||
+	    priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SSR_WIFI2_PCIE1) {
+		ret = regmap_update_bits(priv->regmap, AIROHA_SCU_SSTR,
+					 AIROHA_SCU_PCIE_XSI1_SEL,
+					 AIROHA_SCU_PCIE_XSI1_SEL_PCIE);
+		if (ret)
+			return ret;
+	}
+
+	/* Toggle PCIe0 2 Line mode if enabled or not */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SSR_WIFI1_PCIE0_2LINE)
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_PCIC,
+				      AIROHA_SCU_PCIE_2LANE_MODE);
+	else
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_PCIC,
+					AIROHA_SCU_PCIE_2LANE_MODE);
+	if (ret)
+		return ret;
+
+	if (priv->serdes_port[AIROHA_SCU_SERDES_USB1] == AIROHA_SCU_SSR_USB1_ETHERNET)
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_SSR3,
+					AIROHA_SCU_SSUSB_HSGMII_SEL);
+	else
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_SSR3,
+				      AIROHA_SCU_SSUSB_HSGMII_SEL);
+	if (ret)
+		return ret;
+
+	if (priv->serdes_port[AIROHA_SCU_SERDES_USB2] == AIROHA_SCU_SSR_USB2_PCIE2)
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_SSTR,
+					AIROHA_SCU_USB_PCIE_SEL);
+	else
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_SSTR,
+				      AIROHA_SCU_USB_PCIE_SEL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int airoha_scu_ssr_probe(struct platform_device *pdev)
+{
+	struct airoha_scu_ssr_priv *priv;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	/* Get regmap from MFD */
+	priv->regmap = dev_get_regmap(dev->parent, NULL);
+	if (!priv->regmap)
+		return -EINVAL;
+
+	/* If not set, default to PCIE0 1 line */
+	if (of_property_read_u32(dev->of_node, "airoha,serdes-wifi1",
+				 &priv->serdes_port[AIROHA_SCU_SERDES_WIFI1]))
+		priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] = AIROHA_SCU_SSR_WIFI1_PCIE0;
+
+	/* If not set, default to PCIE1 1 line */
+	if (of_property_read_u32(dev->of_node, "airoha,serdes-wifi2",
+				 &priv->serdes_port[AIROHA_SCU_SERDES_WIFI2]))
+		priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] = AIROHA_SCU_SSR_WIFI2_PCIE1;
+
+	/* If not set, default to USB1 USB 3.0 */
+	if (of_property_read_u32(dev->of_node, "airoha,serdes-usb1",
+				 &priv->serdes_port[AIROHA_SCU_SERDES_USB1]))
+		priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] = AIROHA_SCU_SSR_USB1_USB;
+
+	/* If not set, default to USB2 USB 3.0 */
+	if (of_property_read_u32(dev->of_node, "airoha,serdes-usb2",
+				 &priv->serdes_port[AIROHA_SCU_SERDES_USB2]))
+		priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] = AIROHA_SCU_SSR_USB2_USB;
+
+	ret = airoha_scu_ssr_apply_modes(priv);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static const struct of_device_id airoha_phy_id_table[] = {
+	{ .compatible = "airoha,an7581-scu-ssr" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
+
+static struct platform_driver airoha_scu_ssr_driver = {
+	.probe		= airoha_scu_ssr_probe,
+	.driver		= {
+		.name	= "airoha-scu-ssr",
+		.of_match_table = airoha_phy_id_table,
+	},
+};
+
+module_platform_driver(airoha_scu_ssr_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Airoha SCU SSR/STR driver");
diff --git a/include/linux/soc/airoha/airoha-scu-ssr.h b/include/linux/soc/airoha/airoha-scu-ssr.h
new file mode 100644
index 000000000000..d5ff50dc224f
--- /dev/null
+++ b/include/linux/soc/airoha/airoha-scu-ssr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __AIROHA_SCU_SSR__
+#define __AIROHA_SCU_SSR__
+
+enum airoha_scu_serdes_port {
+	AIROHA_SCU_SERDES_WIFI1 = 0,
+	AIROHA_SCU_SERDES_WIFI2,
+	AIROHA_SCU_SERDES_USB1,
+	AIROHA_SCU_SERDES_USB2,
+
+	AIROHA_SCU_MAX_SERDES_PORT,
+};
+
+int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+				   enum airoha_scu_serdes_port port);
+
+#endif
diff --git a/include/linux/soc/soc/airoha-scu-ssr.h b/include/linux/soc/soc/airoha-scu-ssr.h
new file mode 100644
index 000000000000..d5ff50dc224f
--- /dev/null
+++ b/include/linux/soc/soc/airoha-scu-ssr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __AIROHA_SCU_SSR__
+#define __AIROHA_SCU_SSR__
+
+enum airoha_scu_serdes_port {
+	AIROHA_SCU_SERDES_WIFI1 = 0,
+	AIROHA_SCU_SERDES_WIFI2,
+	AIROHA_SCU_SERDES_USB1,
+	AIROHA_SCU_SERDES_USB2,
+
+	AIROHA_SCU_MAX_SERDES_PORT,
+};
+
+int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+				   enum airoha_scu_serdes_port port);
+
+#endif
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:40 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:40 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-10-ansuelsmth@gmail.com>

Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
for the USB controller.

Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
always supported. The USB 3.0 mode is optional and depends on the Serdes
mode currently configured on the system for the USB port. If USB 3.0 node
is defined, then airoha,scu-ssr property is required for Serdes mode
validation.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/phy/airoha,an7581-usb-phy.yaml   | 106 ++++++++++++++++++
 MAINTAINERS                                   |   6 +
 2 files changed, 112 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
new file mode 100644
index 000000000000..39127cfb63a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7581 SoC USB PHY
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
+
+  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
+  always supported. The USB 3.0 mode is optional and depends on the Serdes
+  mode currently configured on the system for the USB port. If USB 3.0 node
+  is defined, then airoha,scu-ssr property is required for Serdes mode
+  validation.
+
+properties:
+  compatible:
+    const: airoha,an7581-usb-phy
+
+  reg:
+    maxItems: 1
+
+  airoha,port-id:
+    description: Describe the physical port this USB PHY refer to. A dedicated
+      osciallator is used for each port for the USB 2.0 Slew Rate calibration.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+  airoha,scu-ssr:
+    description: Phandle to the SCU SSR node for USB 3.0 Serdes mode validation.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  usb2-phy:
+    type: object
+
+    properties:
+      '#phy-cells':
+        const: 1
+
+    required:
+      - '#phy-cells'
+
+    additionalProperties: false
+
+  usb3-phy:
+    type: object
+
+    properties:
+      '#phy-cells':
+        const: 1
+
+    required:
+      - '#phy-cells'
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - airoha,port-id
+  - usb2-phy
+
+if:
+  required:
+    - usb3-phy
+then:
+  required:
+    - airoha,scu-ssr
+
+additionalProperties: false
+
+examples:
+  - |
+    phy at 1fac0000 {
+        compatible = "airoha,an7581-usb-phy";
+        reg = <0x1fac0000 0x10000>;
+
+        airoha,port-id = <0>;
+        airoha,scu-ssr = <&scu_ssr>;
+
+        usb0_u2: usb2-phy {
+            #phy-cells = <1>;
+        };
+
+        usb0_u3: usb3-phy {
+            #phy-cells = <1>;
+        };
+    };
+
+  - |
+    phy at 1fae0000 {
+        compatible = "airoha,an7581-usb-phy";
+        reg = <0x1fae0000 0x10000>;
+
+        airoha,port-id = <1>;
+
+        usb1_u2: usb2-phy {
+            #phy-cells = <1>;
+        };
+    };
+
diff --git a/MAINTAINERS b/MAINTAINERS
index fe34c80b8d52..c2dd385e9165 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -753,6 +753,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
 F:	drivers/spi/spi-airoha-snfi.c
 
+AIROHA USB PHY DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam
+
 AIRSPY MEDIA DRIVER
 L:	linux-media at vger.kernel.org
 S:	Orphan
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:41 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:41 +0100
Subject: [PATCH 10/13] phy: airoha: Add support for Airoha AN7581 USB PHY
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-11-ansuelsmth@gmail.com>

Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
USB port with USB 2.0 mode always supported and USB 3.0 mode available
only if the Serdes port is correctly configured for USB 3.0.

On xLate probe, the Serdes mode is validated and the driver return error
if the Serdes mode doesn't reflect the expected mode. This is required
as Serdes mode are controlled by the SCU SSR bits and can be either USB
3.0 mode or HSGMII or PCIe 2. In such case USB 3.0 won't work.

If the USB 3.0 mode is not supported, the modes needs to be also
disabled in the xHCI node or the driver will report unsable clock and
fail probe.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                         |   1 +
 drivers/phy/Kconfig                 |   1 +
 drivers/phy/Makefile                |   3 +-
 drivers/phy/airoha/Kconfig          |  13 +
 drivers/phy/airoha/Makefile         |   3 +
 drivers/phy/airoha/phy-airoha-usb.c | 554 ++++++++++++++++++++++++++++
 6 files changed, 574 insertions(+), 1 deletion(-)
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-airoha-usb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c2dd385e9165..1835e488ccaa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -758,6 +758,7 @@ M:	Christian Marangi <ansuelsmth at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam
+F:	drivers/phy/airoha/phy-airoha-usb.c
 
 AIRSPY MEDIA DRIVER
 L:	linux-media at vger.kernel.org
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d58efe998ec..19c9c518fc3d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -93,6 +93,7 @@ config PHY_NXP_PTN3222
 	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
 	  Speed and High Speed.
 
+source "drivers/phy/airoha/Kconfig"
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/broadcom/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e281442acc75..71708c6865b8 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -12,7 +12,8 @@ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
 obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
 obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
-obj-y					+= allwinner/	\
+obj-y					+= airoha/	\
+					   allwinner/	\
 					   amlogic/	\
 					   broadcom/	\
 					   cadence/	\
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
new file mode 100644
index 000000000000..5a2bc2e5d397
--- /dev/null
+++ b/drivers/phy/airoha/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Phy drivers for Mediatek devices
+#
+config PHY_AIROHA_USB
+	tristate "Airoha USB PHY Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Say 'Y' here to add support for Airoha USB PHY driver.
+	  This driver create the basic PHY instance and provides initialize
+	  callback for USB port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
new file mode 100644
index 000000000000..deddab0bbc81
--- /dev/null
+++ b/drivers/phy/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PHY_AIROHA_USB)		+= phy-airoha-usb.o
diff --git a/drivers/phy/airoha/phy-airoha-usb.c b/drivers/phy/airoha/phy-airoha-usb.c
new file mode 100644
index 000000000000..efc89c674342
--- /dev/null
+++ b/drivers/phy/airoha/phy-airoha-usb.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
+#include <linux/bitfield.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/airoha/airoha-scu-ssr.h>
+
+/* U2PHY */
+#define AIROHA_USB_PHY_FMCR0			0x100
+#define   AIROHA_USB_PHY_MONCLK_SEL		GENMASK(27, 26)
+#define   AIROHA_USB_PHY_MONCLK_SEL0		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x0)
+#define   AIROHA_USB_PHY_MONCLK_SEL1		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x1)
+#define   AIROHA_USB_PHY_MONCLK_SEL2		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x2)
+#define   AIROHA_USB_PHY_MONCLK_SEL3		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x3)
+#define   AIROHA_USB_PHY_FREQDET_EN		BIT(24)
+#define   AIROHA_USB_PHY_CYCLECNT		GENMASK(23, 0)
+#define AIROHA_USB_PHY_FMMONR0			0x10c
+#define   AIROHA_USB_PHY_USB_FM_OUT		GENMASK(31, 0)
+#define AIROHA_USB_PHY_FMMONR1			0x110
+#define   AIROHA_USB_PHY_FRCK_EN		BIT(8)
+
+#define AIROHA_USB_PHY_USBPHYACR4		0x310
+#define   AIROHA_USB_PHY_USB20_FS_CR		GENMASK(10, 8)
+#define   AIROHA_USB_PHY_USB20_FS_CR_MAX	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x0)
+#define   AIROHA_USB_PHY_USB20_FS_CR_NORMAL	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x2)
+#define   AIROHA_USB_PHY_USB20_FS_CR_SMALLER	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x4)
+#define   AIROHA_USB_PHY_USB20_FS_CR_MIN	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x6)
+#define   AIROHA_USB_PHY_USB20_FS_SR		GENMASK(2, 0)
+#define   AIROHA_USB_PHY_USB20_FS_SR_MAX	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x0)
+#define   AIROHA_USB_PHY_USB20_FS_SR_NORMAL	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x2)
+#define   AIROHA_USB_PHY_USB20_FS_SR_SMALLER	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x4)
+#define   AIROHA_USB_PHY_USB20_FS_SR_MIN	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x6)
+#define AIROHA_USB_PHY_USBPHYACR5		0x314
+#define   AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN	BIT(15)
+#define   AIROHA_USB_PHY_USB20_HSTX_SRCTRL	GENMASK(14, 12)
+#define AIROHA_USB_PHY_USBPHYACR6		0x318
+#define   AIROHA_USB_PHY_USB20_BC11_SW_EN	BIT(23)
+#define   AIROHA_USB_PHY_USB20_DISCTH		GENMASK(7, 4)
+#define   AIROHA_USB_PHY_USB20_DISCTH_400	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x0)
+#define   AIROHA_USB_PHY_USB20_DISCTH_420	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x1)
+#define   AIROHA_USB_PHY_USB20_DISCTH_440	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x2)
+#define   AIROHA_USB_PHY_USB20_DISCTH_460	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x3)
+#define   AIROHA_USB_PHY_USB20_DISCTH_480	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x4)
+#define   AIROHA_USB_PHY_USB20_DISCTH_500	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x5)
+#define   AIROHA_USB_PHY_USB20_DISCTH_520	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x6)
+#define   AIROHA_USB_PHY_USB20_DISCTH_540	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x7)
+#define   AIROHA_USB_PHY_USB20_DISCTH_560	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x8)
+#define   AIROHA_USB_PHY_USB20_DISCTH_580	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x9)
+#define   AIROHA_USB_PHY_USB20_DISCTH_600	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xa)
+#define   AIROHA_USB_PHY_USB20_DISCTH_620	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xb)
+#define   AIROHA_USB_PHY_USB20_DISCTH_640	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xc)
+#define   AIROHA_USB_PHY_USB20_DISCTH_660	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xd)
+#define   AIROHA_USB_PHY_USB20_DISCTH_680	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xe)
+#define   AIROHA_USB_PHY_USB20_DISCTH_700	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xf)
+#define   AIROHA_USB_PHY_USB20_SQTH		GENMASK(3, 0)
+#define   AIROHA_USB_PHY_USB20_SQTH_85		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x0)
+#define   AIROHA_USB_PHY_USB20_SQTH_90		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x1)
+#define   AIROHA_USB_PHY_USB20_SQTH_95		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x2)
+#define   AIROHA_USB_PHY_USB20_SQTH_100		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x3)
+#define   AIROHA_USB_PHY_USB20_SQTH_105		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x4)
+#define   AIROHA_USB_PHY_USB20_SQTH_110		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x5)
+#define   AIROHA_USB_PHY_USB20_SQTH_115		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x6)
+#define   AIROHA_USB_PHY_USB20_SQTH_120		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x7)
+#define   AIROHA_USB_PHY_USB20_SQTH_125		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x8)
+#define   AIROHA_USB_PHY_USB20_SQTH_130		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x9)
+#define   AIROHA_USB_PHY_USB20_SQTH_135		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xa)
+#define   AIROHA_USB_PHY_USB20_SQTH_140		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xb)
+#define   AIROHA_USB_PHY_USB20_SQTH_145		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xc)
+#define   AIROHA_USB_PHY_USB20_SQTH_150		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xd)
+#define   AIROHA_USB_PHY_USB20_SQTH_155		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xe)
+#define   AIROHA_USB_PHY_USB20_SQTH_160		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xf)
+
+#define AIROHA_USB_PHY_U2PHYDTM1		0x36c
+#define   AIROHA_USB_PHY_FORCE_IDDIG		BIT(9)
+#define   AIROHA_USB_PHY_IDDIG			BIT(1)
+
+#define AIROHA_USB_PHY_GPIO_CTLD		0x80c
+#define   AIROHA_USB_PHY_C60802_GPIO_CTLD	GENMASK(31, 0)
+#define     AIROHA_USB_PHY_SSUSB_IP_SW_RST	BIT(31)
+#define     AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN	BIT(30)
+#define     AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29)
+#define     AIROHA_USB_PHY_SSUSB_SW_RST		BIT(28)
+
+#define AIROHA_USB_PHY_U3_PHYA_REG0		0xb00
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV		GENMASK(29, 28)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_2		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x0)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_4		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x1)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_8		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x2)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_16	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x3)
+#define AIROHA_USB_PHY_U3_PHYA_REG1		0xb04
+#define   AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE	GENMASK(25, 10)
+#define AIROHA_USB_PHY_U3_PHYA_REG6		0xb18
+#define   AIROHA_USB_PHY_SSUSB_CDR_RESERVE	GENMASK(31, 24)
+#define AIROHA_USB_PHY_U3_PHYA_REG8		0xb20
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY	GENMASK(7, 6)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x0)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x1)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x2)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x3)
+
+#define AIROHA_USB_PHY_U3_PHYA_DA_REG19		0xc38
+#define   AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0)
+
+#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT	1024
+#define AIROHA_USB_PHY_REF_CK			20
+#define AIROHA_USB_PHY_U2_SR_COEF		28
+#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR	1000
+
+#define AIROHA_USB_PHY_FREQDET_SLEEP		1000 /* 1ms */
+#define AIROHA_USB_PHY_FREQDET_TIMEOUT		(AIROHA_USB_PHY_FREQDET_SLEEP * 10)
+
+#define AIROHA_USB_PHY_MAX_INSTANCE		2
+
+struct airoha_usb_phy_instance {
+	struct phy *phy;
+	u32 type;
+};
+
+struct airoha_usb_phy_priv {
+	struct device *dev;
+
+	struct regmap *regmap;
+
+	unsigned int id;
+
+	struct airoha_usb_phy_instance *phys[AIROHA_USB_PHY_MAX_INSTANCE];
+};
+
+static int airoha_usb_phy_u2_slew_rate_calibration(struct airoha_usb_phy_priv *priv)
+{
+	u32 fm_out;
+	u32 srctrl;
+
+	/* Enable HS TX SR calibration */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Enable Free run clock */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+			AIROHA_USB_PHY_FRCK_EN);
+
+	/* Select Monitor Clock */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			   AIROHA_USB_PHY_MONCLK_SEL,
+			   priv->id == 0 ? AIROHA_USB_PHY_MONCLK_SEL0 :
+					   AIROHA_USB_PHY_MONCLK_SEL1);
+
+	/* Set cyclecnt */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			   AIROHA_USB_PHY_CYCLECNT,
+			   FIELD_PREP(AIROHA_USB_PHY_CYCLECNT,
+				      AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT));
+
+	/* Enable Frequency meter */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Timeout can happen and we will apply workaround at the end */
+	regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out,
+				 fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
+				 AIROHA_USB_PHY_FREQDET_TIMEOUT);
+
+	/* Disable Frequency meter */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			  AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Disable Free run clock */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+			  AIROHA_USB_PHY_FRCK_EN);
+
+	/* Disable HS TX SR calibration */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			  AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Frequency was not detected, use default SR calibration value */
+	if (!fm_out) {
+		srctrl = 0x5;
+		dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n");
+	/* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
+	} else {
+		srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF;
+		srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out;
+		srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR);
+		dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl);
+	}
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			   AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
+			   FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
+
+	return 0;
+}
+
+static int airoha_usb_phy_u2_init(struct airoha_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+			   AIROHA_USB_PHY_USB20_FS_CR,
+			   AIROHA_USB_PHY_USB20_FS_CR_MIN);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+			   AIROHA_USB_PHY_USB20_FS_SR,
+			   AIROHA_USB_PHY_USB20_FS_SR_NORMAL);
+
+	/* FIXME: evaluate if needed */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			   AIROHA_USB_PHY_USB20_SQTH,
+			   AIROHA_USB_PHY_USB20_SQTH_130);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			   AIROHA_USB_PHY_USB20_DISCTH,
+			   AIROHA_USB_PHY_USB20_DISCTH_600);
+
+	/* Enable the USB port and then disable after calibration */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	airoha_usb_phy_u2_slew_rate_calibration(priv);
+
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+/*
+ * USB 3.0 mode can only work if USB serdes is correctly set.
+ * This is validated in xLate function.
+ */
+static int airoha_usb_phy_u3_init(struct airoha_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8,
+			   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY,
+			   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6,
+			   AIROHA_USB_PHY_SSUSB_CDR_RESERVE,
+			   FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe));
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0,
+			   AIROHA_USB_PHY_SSUSB_BG_DIV,
+			   AIROHA_USB_PHY_SSUSB_BG_DIV_4);
+
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1,
+			FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600));
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19,
+			   AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3,
+			   FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43));
+
+	return 0;
+}
+
+static int airoha_usb_phy_init(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	if (instance->type == PHY_TYPE_USB2)
+		return airoha_usb_phy_u2_init(priv);
+
+	return airoha_usb_phy_u3_init(priv);
+}
+
+static int airoha_usb_phy_exit(struct phy *phy)
+{
+	return 0;
+}
+
+static int airoha_usb_phy_u2_power_on(struct airoha_usb_phy_priv *priv)
+{
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_u3_power_on(struct airoha_usb_phy_priv *priv)
+{
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+			  AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+			  AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN |
+			  AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST |
+			  AIROHA_USB_PHY_SSUSB_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_power_on(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	if (instance->type == PHY_TYPE_USB2)
+		return airoha_usb_phy_u2_power_on(priv);
+
+	return airoha_usb_phy_u3_power_on(priv);
+}
+
+static int airoha_usb_phy_u2_power_off(struct airoha_usb_phy_priv *priv)
+{
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_u3_power_off(struct airoha_usb_phy_priv *priv)
+{
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+			AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+			AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_power_off(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	if (instance->type == PHY_TYPE_USB2)
+		return airoha_usb_phy_u2_power_off(priv);
+
+	return airoha_usb_phy_u3_power_off(priv);
+}
+
+static int airoha_usb_phy_u2_set_mode(struct airoha_usb_phy_priv *priv,
+				      enum phy_mode mode)
+{
+	u32 val = 0;
+
+	/*
+	 * For Device and Host mode, enable force IDDIG.
+	 * For Device set IDDIG, for Host clear IDDIG.
+	 * For OTG disable force and clear IDDIG bit while at it.
+	 */
+	switch (mode) {
+	case PHY_MODE_USB_DEVICE:
+		val |= AIROHA_USB_PHY_IDDIG;
+		fallthrough;
+	case PHY_MODE_USB_HOST:
+		val |= AIROHA_USB_PHY_FORCE_IDDIG;
+		break;
+	case PHY_MODE_USB_OTG:
+		break;
+	default:
+		return 0;
+	}
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1,
+			   AIROHA_USB_PHY_FORCE_IDDIG |
+			   AIROHA_USB_PHY_IDDIG, val);
+
+	return 0;
+}
+
+static int airoha_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	if (instance->type == PHY_TYPE_USB2)
+		return airoha_usb_phy_u2_set_mode(priv, mode);
+
+	return 0;
+}
+
+static struct phy *airoha_usb_phy_xlate(struct device *dev,
+					const struct of_phandle_args *args)
+{
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(dev);
+	struct airoha_usb_phy_instance *instance = NULL;
+	struct device_node *phy_np = args->np;
+	int index;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < AIROHA_USB_PHY_MAX_INSTANCE; index++)
+		if (phy_np == priv->phys[index]->phy->dev.of_node) {
+			instance = priv->phys[index];
+			break;
+		}
+
+	if (!instance) {
+		dev_err(dev, "failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	instance->type = args->args[0];
+	if (!(instance->type == PHY_TYPE_USB2 || instance->type == PHY_TYPE_USB3)) {
+		dev_err(dev, "unsupported device type: %d\n", instance->type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Validate Serdes for USB 3.0 */
+	if (instance->type == PHY_TYPE_USB3) {
+		enum airoha_scu_serdes_port serdes_port;
+		int serdes_mode, expcted_mode;
+
+		switch (priv->id) {
+		case 0:
+			serdes_port = AIROHA_SCU_SERDES_USB1;
+			expcted_mode = AIROHA_SCU_SSR_USB1_USB;
+			break;
+		case 1:
+			serdes_port = AIROHA_SCU_SERDES_USB2;
+			expcted_mode = AIROHA_SCU_SSR_USB2_USB;
+			break;
+		default: /* Impossible already validated */
+			return ERR_PTR(-EINVAL);
+		}
+
+		serdes_mode = airoha_scu_ssr_get_serdes_mode(dev, serdes_port);
+		if (serdes_mode < 0) {
+			dev_err(dev, "failed validating serdes mode for port %d: %d\n",
+				priv->id, serdes_mode);
+			return ERR_PTR(serdes_mode);
+		}
+
+		if (serdes_mode != expcted_mode) {
+			dev_err(dev, "wrong serdes mode for port %d\n",
+				priv->id);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return instance->phy;
+}
+
+static const struct phy_ops airoha_phy = {
+	.init		= airoha_usb_phy_init,
+	.exit		= airoha_usb_phy_exit,
+	.power_on	= airoha_usb_phy_power_on,
+	.power_off	= airoha_usb_phy_power_off,
+	.set_mode	= airoha_usb_phy_set_mode,
+	.owner		= THIS_MODULE,
+};
+
+static const struct regmap_config airoha_usb_phy_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int airoha_usb_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct airoha_usb_phy_priv *priv;
+	struct device *dev = &pdev->dev;
+	struct device_node *child_np;
+	void *base;
+	int port;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	ret = of_property_read_u32(dev->of_node, "airoha,port-id", &priv->id);
+	if (ret)
+		return dev_err_probe(dev, ret, "port ID is mandatory for USB PHY calibration.\n");
+
+	if (priv->id > 1)
+		return dev_err_probe(dev, -EINVAL, "only 2 USB port are supported on the SoC.\n");
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	priv->regmap = devm_regmap_init_mmio(dev, base, &airoha_usb_phy_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	platform_set_drvdata(pdev, priv);
+
+	port = 0;
+	for_each_child_of_node(dev->of_node, child_np) {
+		struct airoha_usb_phy_instance  *instance;
+
+		instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+		if (!instance) {
+			ret = -ENOMEM;
+			goto put_child;
+		}
+
+		priv->phys[port] = instance;
+
+		instance->phy = devm_phy_create(dev, child_np, &airoha_phy);
+		if (IS_ERR(instance->phy)) {
+			dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n");
+			ret = PTR_ERR(instance->phy);
+			goto put_child;
+		}
+
+		phy_set_drvdata(instance->phy, instance);
+
+		port++;
+	}
+
+	phy_provider = devm_of_phy_provider_register(&pdev->dev, airoha_usb_phy_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+
+put_child:
+	of_node_put(child_np);
+	return ret;
+}
+
+static const struct of_device_id airoha_phy_id_table[] = {
+	{ .compatible = "airoha,an7581-usb-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
+
+static struct platform_driver airoha_usb_driver = {
+	.probe		= airoha_usb_phy_probe,
+	.driver		= {
+		.name	= "airoha-usb-phy",
+		.of_match_table = airoha_phy_id_table,
+	},
+};
+
+module_platform_driver(airoha_usb_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Airoha USB PHY driver");
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:42 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:42 +0100
Subject: [PATCH 11/13] usb: host: add ARCH_AIROHA in XHCI MTK dependency
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-12-ansuelsmth@gmail.com>

Airoha SoC use the same register map a logic of the Mediatek xHCI
driver, hence add it to the dependency list to permit compilation also
on this ARCH.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/usb/host/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d011d6c753ed..9d8626f36ca6 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -71,7 +71,7 @@ config USB_XHCI_HISTB
 config USB_XHCI_MTK
 	tristate "xHCI support for MediaTek SoCs"
 	select MFD_SYSCON
-	depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST
+	depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || ARCH_AIROHA || COMPILE_TEST
 	help
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in MediaTek SoCs.
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:43 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:43 +0100
Subject: [PATCH 12/13] arm64: dts: airoha: en7581: convert SCU clock node to MFD implementation
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-13-ansuelsmth@gmail.com>

Convert SCU clock node for Airoha EN7581 to MFD implementation in
preparation for USB support.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 arch/arm64/boot/dts/airoha/en7581.dtsi | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/airoha/en7581.dtsi b/arch/arm64/boot/dts/airoha/en7581.dtsi
index 26b136940917..dfc12fa99748 100644
--- a/arch/arm64/boot/dts/airoha/en7581.dtsi
+++ b/arch/arm64/boot/dts/airoha/en7581.dtsi
@@ -173,11 +173,16 @@ spi_nand: nand at 0 {
 			};
 		};
 
-		scuclk: clock-controller at 1fb00000 {
-			compatible = "airoha,en7581-scu";
+		system-controller at 1fb00000 {
+			compatible = "airoha,en7581-scu-sysctl", "syscon", "simple-mfd";
 			reg = <0x0 0x1fb00000 0x0 0x970>;
-			#clock-cells = <1>;
-			#reset-cells = <1>;
+
+			scuclk: clock-controller {
+				compatible = "airoha,en7581-scu";
+
+				#clock-cells = <1>;
+				#reset-cells = <1>;
+			};
 		};
 
 		uart1: serial at 1fbf0000 {
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 06:29:44 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 14:29:44 +0100
Subject: [PATCH 13/13] arm64: dts: airoha: en7581: add USB and SCU SSR nodes
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <20250309132959.19045-14-ansuelsmth@gmail.com>

Add SCU SSR and USB nodes required for USB support of Airoha EN7581. SCU
SSR node is required to read and configure the current Serdes mode of
the USB PHYs.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 arch/arm64/boot/dts/airoha/en7581.dtsi | 61 ++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arm64/boot/dts/airoha/en7581.dtsi b/arch/arm64/boot/dts/airoha/en7581.dtsi
index dfc12fa99748..5975da11ace0 100644
--- a/arch/arm64/boot/dts/airoha/en7581.dtsi
+++ b/arch/arm64/boot/dts/airoha/en7581.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/en7523-clk.h>
+#include <dt-bindings/phy/phy.h>
 #include <dt-bindings/reset/airoha,en7581-reset.h>
 
 / {
@@ -183,6 +184,10 @@ scuclk: clock-controller {
 				#clock-cells = <1>;
 				#reset-cells = <1>;
 			};
+
+			scu_ssr: system-controller {
+				compatible = "airoha,an7581-scu-ssr";
+			};
 		};
 
 		uart1: serial at 1fbf0000 {
@@ -200,6 +205,62 @@ rng at 1faa1000 {
 			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		usb0: usb at 1fab0000 {
+			compatible = "mediatek,mtk-xhci";
+			reg = <0x0 0x1fab0000 0x0 0x3e00>,
+				<0x0 0x1fab3e00 0x0 0x100>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+
+			phys = <&usb0_u2 PHY_TYPE_USB2>, <&usb0_u3 PHY_TYPE_USB3>;
+
+			status = "disabled";
+		};
+
+		phy at 1fac0000 {
+			compatible = "airoha,an7581-usb-phy";
+			reg = <0x0 0x1fac0000 0x0 0x10000>;
+
+			airoha,port-id = <0>;
+			airoha,scu-ssr = <&scu_ssr>;
+
+			usb0_u2: usb2-phy {
+				#phy-cells = <1>;
+			};
+
+			usb0_u3: usb3-phy {
+				#phy-cells = <1>;
+			};
+		};
+
+		usb1: usb at 1fad0000 {
+			compatible = "mediatek,mtk-xhci";
+			reg = <0x0 0x1fad0000 0x0 0x3e00>,
+				<0x0 0x1fad3e00 0x0 0x100>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+
+			phys = <&usb1_u2 PHY_TYPE_USB2>, <&usb0_u3 PHY_TYPE_USB3>;
+
+			status = "disabled";
+		};
+
+		phy at 1fae0000 {
+			compatible = "airoha,an7581-usb-phy";
+			reg = <0x0 0x1fae0000 0x0 0x10000>;
+
+			airoha,port-id = <1>;
+			airoha,scu-ssr = <&scu_ssr>;
+
+			usb1_u2: usb2-phy {
+				#phy-cells = <1>;
+			};
+
+			usb1_u3: usb3-phy {
+				#phy-cells = <1>;
+			};
+		};
+
 		system-controller at 1fbf0200 {
 			compatible = "airoha,en7581-gpio-sysctl", "syscon",
 				     "simple-mfd";
-- 
2.48.1



From igor.belwon at mentallysanemainliners.org  Sun Mar  9 06:49:32 2025
From: igor.belwon at mentallysanemainliners.org (Igor Belwon)
Date: Sun, 09 Mar 2025 14:49:32 +0100
Subject: [PATCH RFC/RFT 08/12] clk: samsung: exynos990: Use
 platform_driver_probe() to avoid __refdata
In-Reply-To: <20250305-clk-samsung-ref-init-data-v1-8-a4e03a019306@linaro.org>
References: <20250305-clk-samsung-ref-init-data-v1-0-a4e03a019306@linaro.org> <20250305-clk-samsung-ref-init-data-v1-8-a4e03a019306@linaro.org>
Message-ID: <D8BS7PJ6LNYY.28AK1FF2MR85S@mentallysanemainliners.org>

On Wed Mar 5, 2025 at 10:43 PM CET, Krzysztof Kozlowski wrote:
> Switch registering platform driver to platform_driver_probe(), so the
> 'struct platform_driver' can be properly discarded after init and there
> won't be need of __refdata to silence DEBUG_SECTION_MISMATCH.
>
> The change requires using subsys_initcall instead of core_initcall,
> because no device drivers would bound in the latter, as required by
> platform_driver_probe().
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Hi Krzysztof and apologies for the delay in testing.

On my Exynos990 platforms this patch causes similar oopses to those
sent by Andr? (different places each boot). I am unable to get the logs from
UART right now though (refactoring my testing setup). Apologies.

So this bug seems to be platformwide :(

Best regards,
Igor


From indu.bhagat at oracle.com  Sun Mar  9 07:43:51 2025
From: indu.bhagat at oracle.com (Indu Bhagat)
Date: Sun, 9 Mar 2025 07:43:51 -0700
Subject: [PATCH 0/8] unwind, arm64: add sframe unwinder for kernel
In-Reply-To: <9debc20e-1460-4400-a9ca-50b407948976@oracle.com>
References: <4356c17a-8dba-4da0-86dd-f65afb8145e2@oracle.com>
 <20250225235455.655634-1-wnliu@google.com>
 <da6aad99-3461-47fd-b9d8-65f8bb446ae1@oracle.com>
 <mb61ph64h9f8m.fsf@kernel.org>
 <91fae2dc-4f52-4f38-9135-66935a421322@oracle.com>
 <mb61peczjybg7.fsf@kernel.org>
 <9debc20e-1460-4400-a9ca-50b407948976@oracle.com>
Message-ID: <ed1bf8ce-6685-48d0-bf48-7db943fc8c13@oracle.com>

On 2/27/25 10:47 PM, Indu Bhagat wrote:
> On 2/27/25 1:38 AM, Puranjay Mohan wrote:
>> Indu Bhagat <indu.bhagat at oracle.com> writes:
>>
>>> On 2/26/25 2:23 AM, Puranjay Mohan wrote:
>>>> Indu Bhagat <indu.bhagat at oracle.com> writes:
>>>>
>>>>> On 2/25/25 3:54 PM, Weinan Liu wrote:
>>>>>> On Tue, Feb 25, 2025 at 11:38?AM Indu Bhagat 
>>>>>> <indu.bhagat at oracle.com> wrote:
>>>>>>>
>>>>>>> On Mon, Feb 10, 2025 at 12:30?AM Weinan Liu <wnliu at google.com> 
>>>>>>> wrote:
>>>>>>>>> I already have a WIP patch to add sframe support to the kernel 
>>>>>>>>> module.
>>>>>>>>> However, it is not yet working. I had trouble unwinding frames 
>>>>>>>>> for the
>>>>>>>>> kernel module using the current algorithm.
>>>>>>>>>
>>>>>>>>> Indu has likely identified the issue and will be addressing it 
>>>>>>>>> from the
>>>>>>>>> toolchain side.
>>>>>>>>>
>>>>>>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=32666
>>>>>>>>
>>>>>>>> I have a working in progress patch that adds sframe support for 
>>>>>>>> kernel
>>>>>>>> module.
>>>>>>>> https://github.com/heuza/linux/tree/sframe_unwinder.rfc
>>>>>>>>
>>>>>>>> According to the sframe table values I got during runtime 
>>>>>>>> testing, looks
>>>>>>>> like the offsets are not correct .
>>>>>>>>
>>>>>>>
>>>>>>> I hope to sanitize the fix for 32666 and post upstream soon (I 
>>>>>>> had to
>>>>>>> address other related issues). ?Unless fixed, relocating .sframe
>>>>>>> sections using the .rela.sframe is expected to generate incorrect 
>>>>>>> output.
>>>>>>>
>>>>>>>> When unwind symbols init_module(0xffff80007b155048) from the kernel
>>>>>>>> module(livepatch-sample.ko), the start_address of the FDE 
>>>>>>>> entries in the
>>>>>>>> sframe table of the kernel modules appear incorrect.
>>>>>>>
>>>>>>> init_module will apply the relocations on the .sframe section, 
>>>>>>> isnt it ?
>>>>>>>
>>>>>>>> For instance, the first FDE's start_addr is reported as -20564. 
>>>>>>>> Adding
>>>>>>>> this offset to the module's sframe section address 
>>>>>>>> (0xffff80007b15a040)
>>>>>>>> yields 0xffff80007b154fec, which is not within the livepatch- 
>>>>>>>> sample.ko
>>>>>>>> memory region(It should be larger than 0xffff80007b155000).
>>>>>>>>
>>>>>>>
>>>>>>> Hmm..something seems off here. ?Having tested a potential fix for 
>>>>>>> 32666
>>>>>>> locally, I do not expect the first FDE to show this symptom.
>>>>>>>
>>>>>>
>>>>
>>>> Hi,
>>>>
>>>> Sorry for not responding in the past few days.? I was on PTO and was
>>>> trying to improve my snowboarding technique, I am back now!!
>>>>
>>>> I think what we are seeing is expected behaviour:
>>>>
>>>> ?? | For instance, the first FDE's start_addr is reported as -20564. 
>>>> Adding
>>>> ?? | this offset to the module's sframe section address 
>>>> (0xffff80007b15a040)
>>>> ?? | yields 0xffff80007b154fec, which is not within the livepatch- 
>>>> sample.ko
>>>> ?? | memory region(It should be larger than 0xffff80007b155000).
>>>>
>>>>
>>>> Let me explain using a __dummy__ example.
>>>>
>>>> Assume Memory layout before relocation:
>>>>
>>>> ?? | Address | Element???????????????????????????????? | Relocation
>>>> ?? |? ....?? | ....??????????????????????????????????? |
>>>> ?? |?? 60??? | init_module (start address)???????????? |
>>>> ?? |?? 72??? | init_module (end address)?????????????? |
>>>> ?? |? ....?? | .....?????????????????????????????????? |
>>>> ?? |?? 100?? | Sframe section header start address???? |
>>>> ?? |?? 128?? | First FDE's start address?????????????? | 
>>>> RELOC_OP_PREL -> Put init_module address (60) - current address (128)
>>>>
>>>> So, after relocation First FDE's start address has value 60 - 128 = -68
>>>>
>>>
>>> For SFrame FDE function start address is :
>>>
>>> "Signed 32-bit integral field denoting the virtual memory address of the
>>> described function, for which the SFrame FDE applies.? The value encoded
>>> in the ?sfde_func_start_address? field is the offset in bytes of the
>>> function?s start address, from the SFrame section."
>>>
>>> So, in your case, after applying the relocations, you will get:
>>> S + A - P = 60 - 128 = -68
>>>
>>> This is the distance of the function start address (60) from the current
>>> location in SFrame section (128)
>>>
>>> But what we intend to store is the distance of the function start
>>> address from the start of the SFrame section.? So we need to do an
>>> additional step for SFrame FDE:? Value += r_offset
>>
>> Thanks for the explaination, now it makes sense.
>>
>> But I couldn't find a relocation type in AARCH64 that does this extra +=
>> r_offset along with PREL32.
>>
>> The kernel's module loader is only doing the R_AARCH64_PREL32 which is
>> why we see this issue.
>>
>> How is this working even for the kernel itself? or for that matter, any
>> other binary compiled with sframe?
>>
> 
> For the usual executables or shared objects, the calculations are 
> applied by ld.bfd at this time.? Hence, the issue manifests in 
> relocatable files.
> 
>> ?From my limited undestanding, the way to fix this would be to hack the
>> relocator to do this additional step while relocating .sframe sections.
>> Or the 'addend' values in .rela.sframe should already have the +r_offset
>> added to it, then no change to the relocator would be needed.
>>
> 
> Of the two, adjusting the addend values in .rela.sframe may be a 
> reasonable way to go about it.? Let me try it out in GAS and ld.bfd.
> 

A fix for this is in the works (being discussed on the 
binutils at sourceware list).  I will keep you posted.

Thanks
Indu


From david.laight.linux at gmail.com  Sun Mar  9 07:47:47 2025
From: david.laight.linux at gmail.com (David Laight)
Date: Sun, 9 Mar 2025 14:47:47 +0000
Subject: [PATCH v5 07/12] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz
 unit conversion overhead
In-Reply-To: <a1a3e86a-1906-4797-932d-8e1aadafedde@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
	<20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>
	<CAA8EJpoQbvFbNXQ2RB1qY2gHnwZaU-PT-DMLnZkrxkqs2wkXqQ@mail.gmail.com>
	<a1a3e86a-1906-4797-932d-8e1aadafedde@collabora.com>
Message-ID: <20250309144747.744e5197@pumpkin>

On Sun, 9 Mar 2025 12:13:32 +0200
Cristian Ciocaltea <cristian.ciocaltea at collabora.com> wrote:

> On 3/9/25 11:22 AM, Dmitry Baryshkov wrote:
> > On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> > <cristian.ciocaltea at collabora.com> wrote:  
> >>
> >> The ropll_tmds_cfg table used to identify the configuration params for
> >> the supported rates expects the search key, i.e. bit_rate member of
> >> struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
> >> Hz).  This requires multiple conversions between these units being
> >> performed at runtime.
> >>
> >> Improve implementation clarity and efficiency by consistently using the
> >> Hz unit throughout driver's internal data structures and functions.
> >> Also rename the rather misleading struct member.
> >>
> >> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> >> ---
> >>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
> >>  1 file changed, 39 insertions(+), 40 deletions(-)
> >>
> >> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> index 2bf525514c1991a1299265d12e1e85f66333c604..e58a01bdb3ce82d66acdcb02c06de2816288b574 100644
> >> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> >> @@ -330,7 +330,7 @@ enum dp_link_rate {
> >>  };
> >>
> >>  struct ropll_config {
> >> -       u32 bit_rate;
> >> +       u32 rate;  
> > 
> > unsigned long long, please, to match the tmds_char_rate type.

Isn't 'bit_rate' more descriptive?
But maybe rate_hz to make the units more obvious.

If the max frequency might get near 4Gz then the you need something
bigger that u32 - which might it used hectaHz (a prefix that is pretty much only
used with areas of land!)
Being more explicit with u64 (rather than 'long long') may be better.
Certainly less typing.

	David



> >   
> >>         u8 pms_mdiv;
> >>         u8 pms_mdiv_afc;
> >>         u8 pms_pdiv;
> >> @@ -410,45 +410,45 @@ struct rk_hdptx_phy {
> >>  };
> >>
> >>  static const struct ropll_config ropll_tmds_cfg[] = {
> >> -       { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 594000000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,  
> > 
> > Use ULL suffix
> >   
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 371250000, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 297000000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
> >> +       { 162000000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
> >>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 185625000, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
> >> +       { 154000000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
> >> +       { 148500000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
> >>           0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
> >> +       { 146250000, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
> >>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
> >> +       { 119000000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
> >>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
> >> +       { 106500000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
> >>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >> +       { 108000000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
> >> +       { 85500000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
> >> +       { 83500000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 92812500, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >> +       { 74250000, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
> >> +       { 65000000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
> >>           1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
> >> +       { 33750000, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
> >>           1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >> +       { 40000000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >> +       { 27000000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
> >>           0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >> -       { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
> >> +       { 25175000, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
> >>           1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
> >>  };
> >>
> >> @@ -894,10 +894,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
> >>         regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
> >>  }
> >>
> >> -static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
> >> +static bool rk_hdptx_phy_clk_pll_calc(unsigned long rate,  
> > 
> > here and further, unsigned long long
> > Also, is it tmds_char_rate?  
> 
> Yes, will do the suggested changes in v6.
> 
> Thanks,
> Cristian
> 



From robh at kernel.org  Sun Mar  9 07:49:08 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sun, 09 Mar 2025 09:49:08 -0500
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <20250309132959.19045-6-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
Message-ID: <174153174798.1107714.11562627501354617614.robh@kernel.org>


On Sun, 09 Mar 2025 14:29:36 +0100, Christian Marangi wrote:
> Add Documentation for Airoha EN7581 SCU.
> 
> Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
> via the SCU (System Controller Unit).
> 
> Example of these pheriperals are reset-controller, clock-controller,
> PCIe line speed controller and bits to configure different Serdes ports
> for USB or Ethernet usage.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.example.dtb: system-controller at 1fb00000: clock-controller: 'reg' is a required property
	from schema $id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.example.dtb: clock-controller: 'reg' is a required property
	from schema $id: http://devicetree.org/schemas/clock/airoha,en7523-scu.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250309132959.19045-6-ansuelsmth at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:02:14 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:02:14 +0000
Subject: [PATCH net-next 6/7] dt-bindings: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIAQ-005nto-3w@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Therefore, snps,en-tx-lpi-clockgating is technically incorrect, so this
commit deprecates the property in the binding.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 Documentation/devicetree/bindings/net/snps,dwmac.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 3f0aa46d798e..78b3030dc56d 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -494,6 +494,7 @@ title: Synopsys DesignWare MAC
 
   snps,en-tx-lpi-clockgating:
     $ref: /schemas/types.yaml#/definitions/flag
+    deprecated: true
     description:
       Enable gating of the MAC TX clock during TX low-power mode
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:01:48 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:01:48 +0000
Subject: [PATCH net-next 1/7] net: stmmac: allow platforms to use PHY tx clock
 stop capability
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIA0-005ntK-FS@rmk-PC.armlinux.org.uk>

Allow platform glue to instruct stmmac to make use of the PHY transmit
clock stop capability when deciding whether to allow the transmit clock
from the DWMAC core to be stopped.

Cc: "Lad, Prabhakar" <prabhakar.csengg at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h     |  1 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 ++++++++++++----
 include/linux/stmmac.h                           |  3 ++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index d87275c1cf23..bddfa0f4aa21 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -306,6 +306,7 @@ struct stmmac_priv {
 	struct timer_list eee_ctrl_timer;
 	int lpi_irq;
 	u32 tx_lpi_timer;
+	bool tx_lpi_clk_stop;
 	bool eee_enabled;
 	bool eee_active;
 	bool eee_sw_timer_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fa1d7d3a2f43..6f29804148b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -457,8 +457,7 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
 	/* Check and enter in LPI mode */
 	if (!priv->tx_path_in_lpi_mode)
 		stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_FORCED,
-			priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-			0);
+				    priv->tx_lpi_clk_stop, 0);
 }
 
 /**
@@ -1104,13 +1103,18 @@ static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
 
 	priv->eee_enabled = true;
 
+	/* Update the transmit clock stop according to PHY capability if
+	 * the platform allows
+	 */
+	if (priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP)
+		priv->tx_lpi_clk_stop = tx_clk_stop;
+
 	stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
 			     STMMAC_DEFAULT_TWT_LS);
 
 	/* Try to cnfigure the hardware timer. */
 	ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
-				  priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-				  priv->tx_lpi_timer);
+				  priv->tx_lpi_clk_stop, priv->tx_lpi_timer);
 
 	if (ret) {
 		/* Hardware timer mode not supported, or value out of range.
@@ -1269,6 +1273,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	if (!(priv->plat->flags & STMMAC_FLAG_RX_CLK_RUNS_IN_LPI))
 		priv->phylink_config.eee_rx_clk_stop_enable = true;
 
+	/* Set the default transmit clock stop bit based on the platform glue */
+	priv->tx_lpi_clk_stop = priv->plat->flags &
+				STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+
 	mdio_bus_data = priv->plat->mdio_bus_data;
 	if (mdio_bus_data)
 		priv->phylink_config.default_an_inband =
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index b6f03ab12595..c4ec8bb8144e 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -183,7 +183,8 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_INT_SNAPSHOT_EN		BIT(9)
 #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
-#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
+#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP	BIT(12)
+#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:01:53 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:01:53 +0000
Subject: [PATCH net-next 2/7] net: stmmac: starfive: use PHY capability for TX
 clock stop
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIA5-005ntQ-KM@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Add the flag to allow the stmmac core to use the PHY capability.

Cc: Samin Guo <samin.guo at starfivetech.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 5e31cb3bb4b8..2013d7477eb7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -124,6 +124,7 @@ static int starfive_dwmac_probe(struct platform_device *pdev)
 		plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
 
 	dwmac->dev = &pdev->dev;
+	plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
 	plat_dat->bsp_priv = dwmac;
 	plat_dat->dma_cfg->dche = true;
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:01:58 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:01:58 +0000
Subject: [PATCH net-next 3/7] net: stmmac: stm32: use PHY capability for TX
 clock stop
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIAA-005ntW-OZ@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Add the flag to allow the stmmac core to use the PHY capability.

Cc: Christophe Roullier <christophe.roullier at st.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 1fcb74e9e3ff..c3d321192581 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -538,6 +538,7 @@ static int stm32_dwmac_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
 	plat_dat->bsp_priv = dwmac;
 
 	ret = stm32_dwmac_init(plat_dat, false);
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:02:03 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:02:03 +0000
Subject: [PATCH net-next 4/7] riscv: dts: starfive: remove
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIAF-005ntc-S5@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

As commit "net: stmmac: starfive: use PHY capability for TX clock stop"
adds the flag to use the PHY capability, remove the DT property that is
now unecessary.

Cc: Samin Guo <samin.guo at starfivetech.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 arch/riscv/boot/dts/starfive/jh7110.dtsi | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 0d8339357bad..a7aed4a21b65 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -1022,7 +1022,6 @@ gmac0: ethernet at 16030000 {
 			snps,force_thresh_dma_mode;
 			snps,axi-config = <&stmmac_axi_setup>;
 			snps,tso;
-			snps,en-tx-lpi-clockgating;
 			snps,txpbl = <16>;
 			snps,rxpbl = <16>;
 			starfive,syscon = <&aon_syscon 0xc 0x12>;
@@ -1053,7 +1052,6 @@ gmac1: ethernet at 16040000 {
 			snps,force_thresh_dma_mode;
 			snps,axi-config = <&stmmac_axi_setup>;
 			snps,tso;
-			snps,en-tx-lpi-clockgating;
 			snps,txpbl = <16>;
 			snps,rxpbl = <16>;
 			starfive,syscon = <&sys_syscon 0x90 0x2>;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:02:08 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:02:08 +0000
Subject: [PATCH net-next 5/7] ARM: dts: stm32: remove
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIAK-005nti-W5@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

As commit "net: stmmac: stm32: use PHY capability for TX clock stop"
adds the flag to use the PHY capability, remove the DT property that is
now unecessary.

Cc: Samin Guo <samin.guo at starfivetech.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 arch/arm/boot/dts/st/stm32mp151.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi
index b9a87fbe971d..0daa8ffe2ff5 100644
--- a/arch/arm/boot/dts/st/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp151.dtsi
@@ -1781,7 +1781,6 @@ ethernet0: ethernet at 5800a000 {
 				st,syscon = <&syscfg 0x4>;
 				snps,mixed-burst;
 				snps,pbl = <2>;
-				snps,en-tx-lpi-clockgating;
 				snps,axi-config = <&stmmac_axi_config_0>;
 				snps,tso;
 				access-controllers = <&etzpc 94>;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Sun Mar  9 08:02:19 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 09 Mar 2025 15:02:19 +0000
Subject: [PATCH net-next 7/7] net: stmmac: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
Message-ID: <E1trIAV-005ntu-7r@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Therefore, snps,en-tx-lpi-clockgating is technically incorrect, and
this commit adds a warning should a DT be encountered with the property
present.

However, we keep backwards compatibility.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 8dc3bd6946c6..c73eff6a56b8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -497,8 +497,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
 	plat->force_sf_dma_mode =
 		of_property_read_bool(np, "snps,force_sf_dma_mode");
 
-	if (of_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+	if (of_property_read_bool(np, "snps,en-tx-lpi-clockgating")) {
+		dev_warn(&pdev->dev,
+			 "OF property snps,en-tx-lpi-clockgating is deprecated, please convert driver to use STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP\n");
 		plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+	}
 
 	/* Set the maxmtu to a default of JUMBO_LEN in case the
 	 * parameter is not present in the device tree.
-- 
2.30.2



From lkp at intel.com  Sun Mar  9 08:50:11 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 9 Mar 2025 23:50:11 +0800
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <20250309132959.19045-10-ansuelsmth@gmail.com>
References: <20250309132959.19045-10-ansuelsmth@gmail.com>
Message-ID: <202503092318.xReLDuUG-lkp@intel.com>

Hi Christian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on next-20250307]
[also build test WARNING on v6.14-rc5]
[cannot apply to clk/clk-next robh/for-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.14-rc5 v6.14-rc4 v6.14-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Marangi/clk-en7523-convert-driver-to-regmap-API/20250309-213623
base:   next-20250307
patch link:    https://lore.kernel.org/r/20250309132959.19045-10-ansuelsmth%40gmail.com
patch subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
reproduce: (https://download.01.org/0day-ci/archive/20250309/202503092318.xReLDuUG-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503092318.xReLDuUG-lkp at intel.com/

All warnings (new ones prefixed by >>):

   Warning: Documentation/translations/ja_JP/process/submit-checklist.rst references a file that doesn't exist: Documentation/translations/ja_JP/SubmitChecklist
   Warning: Documentation/translations/zh_CN/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
   Warning: Documentation/translations/zh_TW/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/leds/backlight/ti,lp8864.yaml
   Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 984.
   make[2]: *** [Documentation/Makefile:121: htmldocs] Error 255
   make[1]: *** [Makefile:1792: htmldocs] Error 2

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From krzysztof.kozlowski at linaro.org  Sun Mar  9 10:54:36 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun, 09 Mar 2025 18:54:36 +0100
Subject: [PATCH] dt-bindings: soc: samsung: exynos-usi: Drop
 unnecessary status from example
In-Reply-To: <20250307081341.35197-1-krzysztof.kozlowski@linaro.org>
References: <20250307081341.35197-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174154287672.7465.7756190815598140333.b4-ty@linaro.org>


On Fri, 07 Mar 2025 09:13:41 +0100, Krzysztof Kozlowski wrote:
> Device nodes in the examples are supposed to be enabled, so the schema
> will be validated against them.  Keeping them disabled hides potential
> errors.  Only one child of Samsung Exynos USI device node should be
> enabled.  The node in the example already selected 'USI_MODE_UART', so
> enable the serial node while keeping second - I2C - disabled.
> 
> 
> [...]

Applied, thanks!

[1/1] dt-bindings: soc: samsung: exynos-usi: Drop unnecessary status from example
      https://git.kernel.org/krzk/linux/c/8f299df1b75ad0939f1340182c265de019eab438

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From linux at armlinux.org.uk  Sun Mar  9 10:57:20 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 9 Mar 2025 17:57:20 +0000
Subject: [net-next PATCH v12 12/13] net: dsa: Add Airoha AN8855 5-Port
 Gigabit DSA Switch driver
In-Reply-To: <20250309172717.9067-13-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-13-ansuelsmth@gmail.com>
Message-ID: <Z83WgMeg_IxgbxhO@shell.armlinux.org.uk>

On Sun, Mar 09, 2025 at 06:26:57PM +0100, Christian Marangi wrote:
> +static int an8855_port_enable(struct dsa_switch *ds, int port,
> +			      struct phy_device *phy)
> +{
> +	struct an8855_priv *priv = ds->priv;
> +
> +	return regmap_set_bits(priv->regmap, AN8855_PMCR_P(port),
> +			       AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);

Shouldn't you wait for phylink to call your mac_link_up() method?

> +}
> +
> +static void an8855_port_disable(struct dsa_switch *ds, int port)
> +{
> +	struct an8855_priv *priv = ds->priv;
> +	int ret;
> +
> +	ret = regmap_clear_bits(priv->regmap, AN8855_PMCR_P(port),
> +				AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
> +	if (ret)
> +		dev_err(priv->ds->dev, "failed to disable port: %d\n", ret);

Doesn't the link get set down before this is called? IOW, doesn't
phylink call your mac_link_down() method first?

...

> +static void an8855_phylink_mac_link_up(struct phylink_config *config,
> +				       struct phy_device *phydev, unsigned int mode,
> +				       phy_interface_t interface, int speed,
> +				       int duplex, bool tx_pause, bool rx_pause)
> +{
> +	struct dsa_port *dp = dsa_phylink_to_port(config);
> +	struct an8855_priv *priv = dp->ds->priv;
> +	int port = dp->index;
> +	u32 reg;
> +
> +	reg = regmap_read(priv->regmap, AN8855_PMCR_P(port), &reg);
> +	if (phylink_autoneg_inband(mode)) {
> +		reg &= ~AN8855_PMCR_FORCE_MODE;
> +	} else {
> +		reg |= AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK;
> +
> +		reg &= ~AN8855_PMCR_FORCE_SPEED;
> +		switch (speed) {
> +		case SPEED_10:
> +			reg |= AN8855_PMCR_FORCE_SPEED_10;
> +			break;
> +		case SPEED_100:
> +			reg |= AN8855_PMCR_FORCE_SPEED_100;
> +			break;
> +		case SPEED_1000:
> +			reg |= AN8855_PMCR_FORCE_SPEED_1000;
> +			break;
> +		case SPEED_2500:
> +			reg |= AN8855_PMCR_FORCE_SPEED_2500;
> +			break;
> +		case SPEED_5000:
> +			dev_err(priv->ds->dev, "Missing support for 5G speed. Aborting...\n");
> +			return;
> +		}
> +
> +		reg &= ~AN8855_PMCR_FORCE_FDX;
> +		if (duplex == DUPLEX_FULL)
> +			reg |= AN8855_PMCR_FORCE_FDX;
> +
> +		reg &= ~AN8855_PMCR_RX_FC_EN;
> +		if (rx_pause || dsa_port_is_cpu(dp))
> +			reg |= AN8855_PMCR_RX_FC_EN;
> +
> +		reg &= ~AN8855_PMCR_TX_FC_EN;
> +		if (rx_pause || dsa_port_is_cpu(dp))
> +			reg |= AN8855_PMCR_TX_FC_EN;
> +
> +		/* Disable any EEE options */
> +		reg &= ~(AN8855_PMCR_FORCE_EEE5G | AN8855_PMCR_FORCE_EEE2P5G |
> +			 AN8855_PMCR_FORCE_EEE1G | AN8855_PMCR_FORCE_EEE100);

Why? Maybe consider implementing the phylink tx_lpi functions for EEE
support.

> +	}
> +
> +	reg |= AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN;
> +
> +	regmap_write(priv->regmap, AN8855_PMCR_P(port), reg);
> +}
> +
> +static unsigned int an8855_pcs_inband_caps(struct phylink_pcs *pcs,
> +					   phy_interface_t interface)
> +{
> +	/* SGMII can be configured to use inband with AN result */
> +	if (interface == PHY_INTERFACE_MODE_SGMII)
> +		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
> +
> +	/* inband is not supported in 2500-baseX and must be disabled */
> +	return  LINK_INBAND_DISABLE;

Spurious double space.

> +}
> +
> +static void an8855_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
> +				 struct phylink_link_state *state)
> +{
> +	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
> +	u32 val;
> +	int ret;
> +
> +	ret = regmap_read(priv->regmap, AN8855_PMSR_P(AN8855_CPU_PORT), &val);
> +	if (ret < 0) {
> +		state->link = false;
> +		return;
> +	}
> +
> +	state->link = !!(val & AN8855_PMSR_LNK);
> +	state->an_complete = state->link;
> +	state->duplex = (val & AN8855_PMSR_DPX) ? DUPLEX_FULL :
> +						  DUPLEX_HALF;
> +
> +	switch (val & AN8855_PMSR_SPEED) {
> +	case AN8855_PMSR_SPEED_10:
> +		state->speed = SPEED_10;
> +		break;
> +	case AN8855_PMSR_SPEED_100:
> +		state->speed = SPEED_100;
> +		break;
> +	case AN8855_PMSR_SPEED_1000:
> +		state->speed = SPEED_1000;
> +		break;
> +	case AN8855_PMSR_SPEED_2500:
> +		state->speed = SPEED_2500;
> +		break;
> +	case AN8855_PMSR_SPEED_5000:
> +		dev_err(priv->ds->dev, "Missing support for 5G speed. Setting Unknown.\n");
> +		fallthrough;

Which is wrong now, we have SPEED_5000.

> +	default:
> +		state->speed = SPEED_UNKNOWN;
> +		break;
> +	}
> +
> +	if (val & AN8855_PMSR_RX_FC)
> +		state->pause |= MLO_PAUSE_RX;
> +	if (val & AN8855_PMSR_TX_FC)
> +		state->pause |= MLO_PAUSE_TX;
> +}
> +
> +static int an8855_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
> +			     phy_interface_t interface,
> +			     const unsigned long *advertising,
> +			     bool permit_pause_to_mac)
> +{
> +	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
> +	u32 val;
> +	int ret;
> +
> +	/*                   !!! WELCOME TO HELL !!!                   */
> +
[... hell ...]
> +	ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_2,
> +			   AN8855_RG_RXFC_AN_BYPASS_P3 |
> +			   AN8855_RG_RXFC_AN_BYPASS_P2 |
> +			   AN8855_RG_RXFC_AN_BYPASS_P1 |
> +			   AN8855_RG_TXFC_AN_BYPASS_P3 |
> +			   AN8855_RG_TXFC_AN_BYPASS_P2 |
> +			   AN8855_RG_TXFC_AN_BYPASS_P1 |
> +			   AN8855_RG_DPX_AN_BYPASS_P3 |
> +			   AN8855_RG_DPX_AN_BYPASS_P2 |
> +			   AN8855_RG_DPX_AN_BYPASS_P1 |
> +			   AN8855_RG_DPX_AN_BYPASS_P0);
> +	if (ret)
> +		return ret;
> +
> +	return 0;

Is this disruptive to the link if the link is up, and this is called
(e.g. to change the advertisement rather than switch interface mode).
If so, please do something about that - e.g. only doing the bulk of
the configuration if the interface mode has changed.

I guess, however, that as you're only using SGMII with in-band, it
probably doesn't make much difference, but having similar behaviour
in the various drivers helps with ongoing maintenance.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From pchelkin at ispras.ru  Sun Mar  9 10:57:56 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun,  9 Mar 2025 20:57:56 +0300
Subject: [PATCH 0/3] usb: chipidea: ci_hdrc_imx: fix some issues in probe/remove
Message-ID: <20250309175805.661684-1-pchelkin@ispras.ru>

The first patch fixes a rather recently introduced bug leading to the
driver oopsing on removal in case of non-usbmisc devices.

The other ones perform error path improvements in the probe function.

Fedor Pchelkin (3):
  usb: chipidea: ci_hdrc_imx: fix usbmisc handling
  usb: chipidea: ci_hdrc_imx: disable regulator on error path in probe
  usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling

 drivers/usb/chipidea/ci_hdrc_imx.c | 34 +++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 12 deletions(-)

-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar  9 10:57:59 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun,  9 Mar 2025 20:57:59 +0300
Subject: [PATCH 3/3] usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling
In-Reply-To: <20250309175805.661684-1-pchelkin@ispras.ru>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
Message-ID: <20250309175805.661684-4-pchelkin@ispras.ru>

usb_phy_init() may return an error code if e.g. its implementation fails
to prepare/enable some clocks. Detect this early. Trying to disable it
later on driver removal would result in a WARNING splat.

And properly rollback on probe error path by calling the counterpart
usb_phy_shutdown().

Found by Linux Verification Center (linuxtesting.org).

Fixes: be9cae2479f4 ("usb: chipidea: imx: Fix ULPI on imx53")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 3f11ae071c7f..720b998376b9 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -470,7 +470,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	    of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
 		pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
 		data->override_phy_control = true;
-		usb_phy_init(pdata.usb_phy);
+		ret = usb_phy_init(pdata.usb_phy);
+		if (ret) {
+			dev_err(dev, "Failed to init phy\n");
+			goto err_clk;
+		}
 	}
 
 	if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
@@ -479,7 +483,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	ret = imx_usbmisc_init(data->usbmisc_data);
 	if (ret) {
 		dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
-		goto err_clk;
+		goto phy_shutdown;
 	}
 
 	data->ci_pdev = ci_hdrc_add_device(dev,
@@ -488,7 +492,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(data->ci_pdev)) {
 		ret = PTR_ERR(data->ci_pdev);
 		dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
-		goto err_clk;
+		goto phy_shutdown;
 	}
 
 	if (data->usbmisc_data) {
@@ -522,6 +526,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
 disable_device:
 	ci_hdrc_remove_device(data->ci_pdev);
+phy_shutdown:
+	if (data->override_phy_control)
+		usb_phy_shutdown(data->phy);
 err_clk:
 	clk_disable_unprepare(data->clk_wakeup);
 err_wakeup_clk:
-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar  9 10:57:58 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun,  9 Mar 2025 20:57:58 +0300
Subject: [PATCH 2/3] usb: chipidea: ci_hdrc_imx: disable regulator on error path in probe
In-Reply-To: <20250309175805.661684-1-pchelkin@ispras.ru>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
Message-ID: <20250309175805.661684-3-pchelkin@ispras.ru>

Upon encountering errors during the HSIC pinctrl handling section the
regulator should be disabled.

After the above-stated changes it is possible to jump onto
"disable_hsic_regulator" label without having added the CPU latency QoS
request previously. This would result in cpu_latency_qos_remove_request()
yielding a WARNING.

So rearrange the error handling path to follow the reverse order of
different probing phases.

Found by Linux Verification Center (linuxtesting.org).

Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 619779eef333..3f11ae071c7f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -407,13 +407,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 				"pinctrl_hsic_idle lookup failed, err=%ld\n",
 					PTR_ERR(pinctrl_hsic_idle));
 			ret = PTR_ERR(pinctrl_hsic_idle);
-			goto err_put;
+			goto disable_hsic_regulator;
 		}
 
 		ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle);
 		if (ret) {
 			dev_err(dev, "hsic_idle select failed, err=%d\n", ret);
-			goto err_put;
+			goto disable_hsic_regulator;
 		}
 
 		data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
@@ -423,7 +423,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 				"pinctrl_hsic_active lookup failed, err=%ld\n",
 					PTR_ERR(data->pinctrl_hsic_active));
 			ret = PTR_ERR(data->pinctrl_hsic_active);
-			goto err_put;
+			goto disable_hsic_regulator;
 		}
 	}
 
@@ -432,11 +432,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
 	ret = imx_get_clks(dev);
 	if (ret)
-		goto disable_hsic_regulator;
+		goto qos_remove_request;
 
 	ret = imx_prepare_enable_clks(dev);
 	if (ret)
-		goto disable_hsic_regulator;
+		goto qos_remove_request;
 
 	ret = clk_prepare_enable(data->clk_wakeup);
 	if (ret)
@@ -526,12 +526,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	clk_disable_unprepare(data->clk_wakeup);
 err_wakeup_clk:
 	imx_disable_unprepare_clks(dev);
+qos_remove_request:
+	if (pdata.flags & CI_HDRC_PMQOS)
+		cpu_latency_qos_remove_request(&data->pm_qos_req);
 disable_hsic_regulator:
 	if (data->hsic_pad_regulator)
 		/* don't overwrite original ret (cf. EPROBE_DEFER) */
 		regulator_disable(data->hsic_pad_regulator);
-	if (pdata.flags & CI_HDRC_PMQOS)
-		cpu_latency_qos_remove_request(&data->pm_qos_req);
 	data->ci_pdev = NULL;
 err_put:
 	if (data->usbmisc_data)
-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar  9 10:57:57 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun,  9 Mar 2025 20:57:57 +0300
Subject: [PATCH 1/3] usb: chipidea: ci_hdrc_imx: fix usbmisc handling
In-Reply-To: <20250309175805.661684-1-pchelkin@ispras.ru>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
Message-ID: <20250309175805.661684-2-pchelkin@ispras.ru>

usbmisc is an optional device property so it is totally valid for the
corresponding data->usbmisc_data to have a NULL value.

Check that before dereferencing the pointer.

Found by Linux Verification Center (linuxtesting.org) with Svace static
analysis tool.

Fixes: 74adad500346 ("usb: chipidea: ci_hdrc_imx: decrement device's refcount in .remove() and in the error path of .probe()")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 1a7fc638213e..619779eef333 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -534,7 +534,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 		cpu_latency_qos_remove_request(&data->pm_qos_req);
 	data->ci_pdev = NULL;
 err_put:
-	put_device(data->usbmisc_data->dev);
+	if (data->usbmisc_data)
+		put_device(data->usbmisc_data->dev);
 	return ret;
 }
 
@@ -559,7 +560,8 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
 		if (data->hsic_pad_regulator)
 			regulator_disable(data->hsic_pad_regulator);
 	}
-	put_device(data->usbmisc_data->dev);
+	if (data->usbmisc_data)
+		put_device(data->usbmisc_data->dev);
 }
 
 static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
-- 
2.48.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 10:58:36 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 20:58:36 +0300
Subject: [PATCH v6 2/4] dt-bindings: clock: axg-audio: document A1 SoC audio clock controller driver
In-Reply-To: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
References: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309175838.1322014-2-jan.dakinevich@salutedevices.com>

Add device tree bindings for A1 SoC audio clock and reset controllers.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../clock/amlogic,axg-audio-clkc.yaml         |   4 +
 .../dt-bindings/clock/amlogic,a1-audio-clkc.h | 139 ++++++++++++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 include/dt-bindings/clock/amlogic,a1-audio-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
index fd7982dd4cea..10202b749001 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
+++ b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
@@ -18,6 +18,8 @@ description:
 properties:
   compatible:
     enum:
+      - amlogic,a1-audio-clkc
+      - amlogic,a1-audio-vad-clkc
       - amlogic,axg-audio-clkc
       - amlogic,g12a-audio-clkc
       - amlogic,sm1-audio-clkc
@@ -114,6 +116,8 @@ allOf:
         compatible:
           contains:
             enum:
+              - amlogic,a1-audio-clkc
+              - amlogic,a1-audio-vad-clkc
               - amlogic,g12a-audio-clkc
               - amlogic,sm1-audio-clkc
     then:
diff --git a/include/dt-bindings/clock/amlogic,a1-audio-clkc.h b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
new file mode 100644
index 000000000000..78e7a432d439
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Jan Dakinevich <jan.dakinevich at salutedevices.com>
+ */
+
+#ifndef __A1_AUDIO_CLKC_BINDINGS_H
+#define __A1_AUDIO_CLKC_BINDINGS_H
+
+#define AUD_CLKID_DDR_ARB			1
+#define AUD_CLKID_TDMIN_A			2
+#define AUD_CLKID_TDMIN_B			3
+#define AUD_CLKID_TDMIN_LB			4
+#define AUD_CLKID_LOOPBACK			5
+#define AUD_CLKID_TDMOUT_A			6
+#define AUD_CLKID_TDMOUT_B			7
+#define AUD_CLKID_FRDDR_A			8
+#define AUD_CLKID_FRDDR_B			9
+#define AUD_CLKID_TODDR_A			10
+#define AUD_CLKID_TODDR_B			11
+#define AUD_CLKID_SPDIFIN			12
+#define AUD_CLKID_RESAMPLE			13
+#define AUD_CLKID_EQDRC				14
+#define AUD_CLKID_LOCKER			15
+#define AUD_CLKID_MST_A_MCLK_SEL		16
+#define AUD_CLKID_MST_A_MCLK_DIV		17
+#define AUD_CLKID_MST_A_MCLK			18
+#define AUD_CLKID_MST_B_MCLK_SEL		19
+#define AUD_CLKID_MST_B_MCLK_DIV		20
+#define AUD_CLKID_MST_B_MCLK			21
+#define AUD_CLKID_MST_C_MCLK_SEL		22
+#define AUD_CLKID_MST_C_MCLK_DIV		23
+#define AUD_CLKID_MST_C_MCLK			24
+#define AUD_CLKID_MST_D_MCLK_SEL		25
+#define AUD_CLKID_MST_D_MCLK_DIV		26
+#define AUD_CLKID_MST_D_MCLK			27
+#define AUD_CLKID_MST_A_SCLK_PRE_EN		28
+#define AUD_CLKID_MST_A_SCLK_DIV		29
+#define AUD_CLKID_MST_A_SCLK_POST_EN		30
+#define AUD_CLKID_MST_A_SCLK			31
+#define AUD_CLKID_MST_B_SCLK_PRE_EN		32
+#define AUD_CLKID_MST_B_SCLK_DIV		33
+#define AUD_CLKID_MST_B_SCLK_POST_EN		34
+#define AUD_CLKID_MST_B_SCLK			35
+#define AUD_CLKID_MST_C_SCLK_PRE_EN		36
+#define AUD_CLKID_MST_C_SCLK_DIV		37
+#define AUD_CLKID_MST_C_SCLK_POST_EN		38
+#define AUD_CLKID_MST_C_SCLK			39
+#define AUD_CLKID_MST_D_SCLK_PRE_EN		40
+#define AUD_CLKID_MST_D_SCLK_DIV		41
+#define AUD_CLKID_MST_D_SCLK_POST_EN		42
+#define AUD_CLKID_MST_D_SCLK			43
+#define AUD_CLKID_MST_A_LRCLK_DIV		44
+#define AUD_CLKID_MST_A_LRCLK			45
+#define AUD_CLKID_MST_B_LRCLK_DIV		46
+#define AUD_CLKID_MST_B_LRCLK			47
+#define AUD_CLKID_MST_C_LRCLK_DIV		48
+#define AUD_CLKID_MST_C_LRCLK			49
+#define AUD_CLKID_MST_D_LRCLK_DIV		50
+#define AUD_CLKID_MST_D_LRCLK			51
+#define AUD_CLKID_TDMIN_A_SCLK_SEL		52
+#define AUD_CLKID_TDMIN_A_SCLK_PRE_EN		53
+#define AUD_CLKID_TDMIN_A_SCLK_POST_EN		54
+#define AUD_CLKID_TDMIN_A_SCLK			55
+#define AUD_CLKID_TDMIN_A_LRCLK			56
+#define AUD_CLKID_TDMIN_B_SCLK_SEL		57
+#define AUD_CLKID_TDMIN_B_SCLK_PRE_EN		58
+#define AUD_CLKID_TDMIN_B_SCLK_POST_EN		59
+#define AUD_CLKID_TDMIN_B_SCLK			60
+#define AUD_CLKID_TDMIN_B_LRCLK			61
+#define AUD_CLKID_TDMIN_LB_SCLK_SEL		62
+#define AUD_CLKID_TDMIN_LB_SCLK_PRE_EN		63
+#define AUD_CLKID_TDMIN_LB_SCLK_POST_EN		64
+#define AUD_CLKID_TDMIN_LB_SCLK			65
+#define AUD_CLKID_TDMIN_LB_LRCLK		66
+#define AUD_CLKID_TDMOUT_A_SCLK_SEL		67
+#define AUD_CLKID_TDMOUT_A_SCLK_PRE_EN		68
+#define AUD_CLKID_TDMOUT_A_SCLK_POST_EN		69
+#define AUD_CLKID_TDMOUT_A_SCLK			70
+#define AUD_CLKID_TDMOUT_A_LRCLK		71
+#define AUD_CLKID_TDMOUT_B_SCLK_SEL		72
+#define AUD_CLKID_TDMOUT_B_SCLK_PRE_EN		73
+#define AUD_CLKID_TDMOUT_B_SCLK_POST_EN		74
+#define AUD_CLKID_TDMOUT_B_SCLK			75
+#define AUD_CLKID_TDMOUT_B_LRCLK		76
+#define AUD_CLKID_SPDIFIN_CLK_SEL		77
+#define AUD_CLKID_SPDIFIN_CLK_DIV		78
+#define AUD_CLKID_SPDIFIN_CLK			79
+#define AUD_CLKID_RESAMPLE_CLK_SEL		80
+#define AUD_CLKID_RESAMPLE_CLK_DIV		81
+#define AUD_CLKID_RESAMPLE_CLK			82
+#define AUD_CLKID_EQDRC_CLK_SEL			83
+#define AUD_CLKID_EQDRC_CLK_DIV			84
+#define AUD_CLKID_EQDRC_CLK			85
+#define AUD_CLKID_LOCKER_IN_CLK_SEL		86
+#define AUD_CLKID_LOCKER_IN_CLK_DIV		87
+#define AUD_CLKID_LOCKER_IN_CLK			88
+#define AUD_CLKID_LOCKER_OUT_CLK_SEL		89
+#define AUD_CLKID_LOCKER_OUT_CLK_DIV		90
+#define AUD_CLKID_LOCKER_OUT_CLK		91
+
+#define AUD_VAD_CLKID_CLK81			1
+#define AUD_VAD_CLKID_SYSCLK_A_DIV		2
+#define AUD_VAD_CLKID_SYSCLK_A			3
+#define AUD_VAD_CLKID_SYSCLK_B_DIV		4
+#define AUD_VAD_CLKID_SYSCLK_B			5
+#define AUD_VAD_CLKID_SYSCLK			6
+#define AUD_VAD_CLKID_DDR_ARB			7
+#define AUD_VAD_CLKID_PDM			8
+#define AUD_VAD_CLKID_TDMIN_VAD			9
+#define AUD_VAD_CLKID_TODDR_VAD			10
+#define AUD_VAD_CLKID_TOVAD			11
+#define AUD_VAD_CLKID_TOAUDIOTOP		12
+#define AUD_VAD_CLKID_MST_VAD_MCLK_SEL		13
+#define AUD_VAD_CLKID_MST_VAD_MCLK_DIV		14
+#define AUD_VAD_CLKID_MST_VAD_MCLK		15
+#define AUD_VAD_CLKID_MST_VAD_SCLK_PRE_EN	16
+#define AUD_VAD_CLKID_MST_VAD_SCLK_DIV		17
+#define AUD_VAD_CLKID_MST_VAD_SCLK_POST_EN	18
+#define AUD_VAD_CLKID_MST_VAD_SCLK		19
+#define AUD_VAD_CLKID_MST_VAD_LRCLK_DIV		20
+#define AUD_VAD_CLKID_MST_VAD_LRCLK		21
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_SEL	22
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_PRE_EN	23
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_POST_EN	24
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK		25
+#define AUD_VAD_CLKID_TDMIN_VAD_LRCLK		26
+#define AUD_VAD_CLKID_PDM_DCLK_SEL		27
+#define AUD_VAD_CLKID_PDM_DCLK_DIV		28
+#define AUD_VAD_CLKID_PDM_DCLK			29
+#define AUD_VAD_CLKID_PDM_SYSCLK_SEL		30
+#define AUD_VAD_CLKID_PDM_SYSCLK_DIV		31
+#define AUD_VAD_CLKID_PDM_SYSCLK		32
+#define AUD_VAD_CLKID_VAD_CLK_SEL		33
+#define AUD_VAD_CLKID_VAD_CLK_DIV		34
+#define AUD_VAD_CLKID_VAD_CLK			35
+
+#endif /* __A1_AUDIO_CLKC_BINDINGS_H */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 10:58:38 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 20:58:38 +0300
Subject: [PATCH v6 4/4] arm64: dts: meson: a1: add the audio clock controller
In-Reply-To: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
References: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309175838.1322014-4-jan.dakinevich@salutedevices.com>

Add the bus and audio clock controllers' device tree nodes.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi | 49 +++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index 1eba0afb3fd9..cf0247fce740 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -5,6 +5,7 @@
 
 #include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
 #include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
+#include <dt-bindings/clock/amlogic,a1-audio-clkc.h>
 #include <dt-bindings/gpio/meson-a1-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -664,6 +665,54 @@ sd_emmc: mmc at 10000 {
 				power-domains = <&pwrc PWRC_SD_EMMC_ID>;
 				status = "disabled";
 			};
+
+			audio: bus at 50000 {
+				compatible = "simple-bus";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges = <0x0 0x0 0x0 0x50000 0 0x4980>;
+				power-domains = <&pwrc PWRC_AUDIO_ID>;
+
+				clkc_audio: clock-controller at 0 {
+					compatible = "amlogic,a1-audio-clkc";
+					reg = <0x0 0x0 0x0 0xb0>;
+					#clock-cells = <1>;
+					#reset-cells = <1>;
+					clocks = <&clkc_audio_vad AUD_VAD_CLKID_TOAUDIOTOP>,
+						 <&clkc_periphs CLKID_DDS_IN>,
+						 <&clkc_pll CLKID_FCLK_DIV2>,
+						 <&clkc_pll CLKID_FCLK_DIV3>,
+						 <&clkc_pll CLKID_HIFI_PLL>,
+						 <&xtal>;
+					clock-names = "pclk",
+						      "mst_in0",
+						      "mst_in1",
+						      "mst_in2",
+						      "mst_in3",
+						      "mst_in4";
+					resets = <&reset RESET_AUDIO>;
+				};
+
+				clkc_audio_vad: clock-controller at 4800 {
+					compatible = "amlogic,a1-audio-vad-clkc";
+					reg = <0x0 0x4800 0x0 0x20>;
+					#clock-cells = <1>;
+					#reset-cells = <1>;
+					clocks = <&clkc_periphs CLKID_SYS>,
+						 <&clkc_periphs CLKID_DDS_IN>,
+						 <&clkc_pll CLKID_FCLK_DIV2>,
+						 <&clkc_pll CLKID_FCLK_DIV3>,
+						 <&clkc_pll CLKID_HIFI_PLL>,
+						 <&xtal>;
+					clock-names = "pclk",
+						      "mst_in0",
+						      "mst_in1",
+						      "mst_in2",
+						      "mst_in3",
+						      "mst_in4";
+					resets = <&reset RESET_AUDIO_VAD>;
+				};
+			};
 		};
 
 		usb: usb at fe004400 {
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 10:58:35 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 20:58:35 +0300
Subject: [PATCH v6 1/4] clk: meson: axg: share the set of audio helper macros
Message-ID: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>

 - These macros will be used in upcoming audio clock controller
    for A1 SoC;

 - AUD_PCLK_GATE() macro got an extra parameter to be more flexible.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 drivers/clk/meson/axg-audio.c   | 215 ++++++--------------------------
 drivers/clk/meson/meson-audio.h | 156 +++++++++++++++++++++++
 2 files changed, 191 insertions(+), 180 deletions(-)
 create mode 100644 drivers/clk/meson/meson-audio.h

diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 3948f5d0faca..7c4b0c722a94 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 
 #include "meson-clkc-utils.h"
+#include "meson-audio.h"
 #include "axg-audio.h"
 #include "clk-regmap.h"
 #include "clk-phase.h"
@@ -23,155 +24,9 @@
 
 #include <dt-bindings/clock/axg-audio-clkc.h>
 
-#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
-	.data = &(struct clk_regmap_gate_data){				\
-		.offset = (_reg),					\
-		.bit_idx = (_bit),					\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_gate_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
-	.data = &(struct clk_regmap_mux_data){				\
-		.offset = (_reg),					\
-		.mask = (_mask),					\
-		.shift = (_shift),					\
-		.flags = (_dflags),					\
-	},								\
-	.hw.init = &(struct clk_init_data){				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_mux_ops,				\
-		.parent_data = _pdata,					\
-		.num_parents = ARRAY_SIZE(_pdata),			\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
-	.data = &(struct clk_regmap_div_data){				\
-		.offset = (_reg),					\
-		.shift = (_shift),					\
-		.width = (_width),					\
-		.flags = (_dflags),					\
-	},								\
-	.hw.init = &(struct clk_init_data){				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_divider_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_PCLK_GATE(_name, _reg, _bit) {				\
-	.data = &(struct clk_regmap_gate_data){				\
-		.offset = (_reg),					\
-		.bit_idx = (_bit),					\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_gate_ops,				\
-		.parent_names = (const char *[]){ "aud_top" },		\
-		.num_parents = 1,					\
-	},								\
-}
-
-#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
-		     _hi_shift, _hi_width, _pname, _iflags) {		\
-	.data = &(struct meson_sclk_div_data) {				\
-		.div = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_div_shift),			\
-			.width   = (_div_width),			\
-		},							\
-		.hi = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_hi_shift),				\
-			.width   = (_hi_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_sclk_div_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
-		     _pname, _iflags) {					\
-	.data = &(struct meson_clk_triphase_data) {			\
-		.ph0 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift0),				\
-			.width   = (_width),				\
-		},							\
-		.ph1 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift1),				\
-			.width   = (_width),				\
-		},							\
-		.ph2 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift2),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_triphase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
-	.data = &(struct meson_clk_phase_data) {			\
-		.ph = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_phase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
-		    _iflags) {						\
-	.data = &(struct meson_sclk_ws_inv_data) {			\
-		.ph = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift_ph),				\
-			.width   = (_width),				\
-		},							\
-		.ws = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift_ws),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_phase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
+static const struct clk_parent_data pclk_parent_data[] = {
+	{ .name = "aud_top" },
+};
 
 /* Audio Master Clocks */
 static const struct clk_parent_data mst_mux_parent_data[] = {
@@ -325,45 +180,45 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
 
 /* Common Clocks */
 static struct clk_regmap ddr_arb =
-	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
+	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0, pclk_parent_data);
 static struct clk_regmap pdm =
-	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1);
+	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1, pclk_parent_data);
 static struct clk_regmap tdmin_a =
-	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2);
+	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2, pclk_parent_data);
 static struct clk_regmap tdmin_b =
-	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3);
+	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3, pclk_parent_data);
 static struct clk_regmap tdmin_c =
-	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4);
+	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4, pclk_parent_data);
 static struct clk_regmap tdmin_lb =
-	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5);
+	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5, pclk_parent_data);
 static struct clk_regmap tdmout_a =
-	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6);
+	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6, pclk_parent_data);
 static struct clk_regmap tdmout_b =
-	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7);
+	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7, pclk_parent_data);
 static struct clk_regmap tdmout_c =
-	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8);
+	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8, pclk_parent_data);
 static struct clk_regmap frddr_a =
-	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9);
+	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9, pclk_parent_data);
 static struct clk_regmap frddr_b =
-	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10);
+	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10, pclk_parent_data);
 static struct clk_regmap frddr_c =
-	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11);
+	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11, pclk_parent_data);
 static struct clk_regmap toddr_a =
-	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12);
+	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12, pclk_parent_data);
 static struct clk_regmap toddr_b =
-	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13);
+	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13, pclk_parent_data);
 static struct clk_regmap toddr_c =
-	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14);
+	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14, pclk_parent_data);
 static struct clk_regmap loopback =
-	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15);
+	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15, pclk_parent_data);
 static struct clk_regmap spdifin =
-	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16);
+	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16, pclk_parent_data);
 static struct clk_regmap spdifout =
-	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17);
+	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17, pclk_parent_data);
 static struct clk_regmap resample =
-	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18);
+	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18, pclk_parent_data);
 static struct clk_regmap power_detect =
-	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19);
+	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19, pclk_parent_data);
 
 static struct clk_regmap spdifout_clk_sel =
 	AUD_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
@@ -631,11 +486,11 @@ static struct clk_regmap g12a_tdmout_c_sclk =
 	AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
 
 static struct clk_regmap toram =
-	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20);
+	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20, pclk_parent_data);
 static struct clk_regmap spdifout_b =
-	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21);
+	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21, pclk_parent_data);
 static struct clk_regmap eqdrc =
-	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22);
+	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22, pclk_parent_data);
 
 /* SM1 Clocks */
 static struct clk_regmap sm1_clk81_en = {
@@ -740,21 +595,21 @@ static struct clk_regmap sm1_aud_top = {
 };
 
 static struct clk_regmap resample_b =
-	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26);
+	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26, pclk_parent_data);
 static struct clk_regmap tovad =
-	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27);
+	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27, pclk_parent_data);
 static struct clk_regmap locker =
-	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28);
+	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28, pclk_parent_data);
 static struct clk_regmap spdifin_lb =
-	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29);
+	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29, pclk_parent_data);
 static struct clk_regmap frddr_d =
-	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0);
+	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0, pclk_parent_data);
 static struct clk_regmap toddr_d =
-	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1);
+	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1, pclk_parent_data);
 static struct clk_regmap loopback_b =
-	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2);
+	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2, pclk_parent_data);
 static struct clk_regmap earcrx =
-	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6);
+	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6, pclk_parent_data);
 
 
 static struct clk_regmap sm1_mst_a_mclk_sel =
diff --git a/drivers/clk/meson/meson-audio.h b/drivers/clk/meson/meson-audio.h
new file mode 100644
index 000000000000..16dd044d52bd
--- /dev/null
+++ b/drivers/clk/meson/meson-audio.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+
+#ifndef __MESON_AUDIO_H__
+#define __MESON_AUDIO_H__
+
+#define AUD_PCLK_GATE(_name, _reg, _bit, _pdata) {			\
+	.data = &(struct clk_regmap_gate_data){				\
+		.offset = (_reg),					\
+		.bit_idx = (_bit),					\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_gate_ops,				\
+		.parent_data = (_pdata),				\
+		.num_parents = 1,					\
+	},								\
+}
+
+#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
+	.data = &(struct clk_regmap_gate_data){				\
+		.offset = (_reg),					\
+		.bit_idx = (_bit),					\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_gate_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
+	.data = &(struct clk_regmap_mux_data){				\
+		.offset = (_reg),					\
+		.mask = (_mask),					\
+		.shift = (_shift),					\
+		.flags = (_dflags),					\
+	},								\
+	.hw.init = &(struct clk_init_data){				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_mux_ops,				\
+		.parent_data = _pdata,					\
+		.num_parents = ARRAY_SIZE(_pdata),			\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
+	.data = &(struct clk_regmap_div_data){				\
+		.offset = (_reg),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.flags = (_dflags),					\
+	},								\
+	.hw.init = &(struct clk_init_data){				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_divider_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
+		     _hi_shift, _hi_width, _pname, _iflags) {		\
+	.data = &(struct meson_sclk_div_data) {				\
+		.div = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_div_shift),			\
+			.width   = (_div_width),			\
+		},							\
+		.hi = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_hi_shift),				\
+			.width   = (_hi_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_sclk_div_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
+		     _pname, _iflags) {					\
+	.data = &(struct meson_clk_triphase_data) {			\
+		.ph0 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift0),				\
+			.width   = (_width),				\
+		},							\
+		.ph1 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift1),				\
+			.width   = (_width),				\
+		},							\
+		.ph2 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift2),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_triphase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
+	.data = &(struct meson_clk_phase_data) {			\
+		.ph = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_phase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
+		    _iflags) {						\
+	.data = &(struct meson_sclk_ws_inv_data) {			\
+		.ph = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift_ph),				\
+			.width   = (_width),				\
+		},							\
+		.ws = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift_ws),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_phase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#endif /* __MESON_AUDIO_H__ */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 10:58:37 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 20:58:37 +0300
Subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller driver
In-Reply-To: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
References: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309175838.1322014-3-jan.dakinevich@salutedevices.com>

This controller provides clocks and reset functionality for audio
peripherals on Amlogic A1 SoC family.

The driver is almost identical to 'axg-audio', however it would be
better to keep it separate to avoid a mess of new defines with A1_
prefixes (significant amount of bits has another definition comparing
to AXG/SM1/G12A).

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 drivers/clk/meson/Kconfig    |  14 +
 drivers/clk/meson/Makefile   |   1 +
 drivers/clk/meson/a1-audio.c | 856 +++++++++++++++++++++++++++++++++++
 3 files changed, 871 insertions(+)
 create mode 100644 drivers/clk/meson/a1-audio.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 7cb21fc223b0..49f2086bc773 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -133,6 +133,20 @@ config COMMON_CLK_A1_PERIPHERALS
 	  device, A1 SoC Family. Say Y if you want A1 Peripherals clock
 	  controller to work.
 
+config COMMON_CLK_A1_AUDIO
+	tristate "Amlogic A1 SoC Audio clock controller support"
+	depends on ARM64
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_PHASE
+	select COMMON_CLK_MESON_SCLK_DIV
+	select COMMON_CLK_MESON_CLKC_UTILS
+	select REGMAP_MMIO
+	imply RESET_MESON_AUX
+	help
+	  Support for the Audio clock controller on Amlogic A113L based
+	  device, A1 SoC Family. Say Y if you want A1 Audio clock controller
+	  to work.
+
 config COMMON_CLK_C3_PLL
 	tristate "Amlogic C3 PLL clock controller"
 	depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index bc56a47931c1..f3d8f6545f59 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
 obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
 obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
+obj-$(CONFIG_COMMON_CLK_A1_AUDIO) += a1-audio.o
 obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
 obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/a1-audio.c b/drivers/clk/meson/a1-audio.c
new file mode 100644
index 000000000000..e87b578417bf
--- /dev/null
+++ b/drivers/clk/meson/a1-audio.c
@@ -0,0 +1,856 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Jan Dakinevich <jan.dakinevich at salutedevices.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/clock/amlogic,a1-audio-clkc.h>
+
+#include "clk-phase.h"
+#include "clk-regmap.h"
+#include "meson-audio.h"
+#include "meson-clkc-utils.h"
+#include "sclk-div.h"
+
+#define AUDIO_CLK_GATE_EN0		0x000
+#define AUDIO_MCLK_A_CTRL		0x008
+#define AUDIO_MCLK_B_CTRL		0x00c
+#define AUDIO_MCLK_C_CTRL		0x010
+#define AUDIO_MCLK_D_CTRL		0x014
+#define AUDIO_SW_RESET0			0x028
+#define AUDIO_MST_A_SCLK_CTRL0		0x040
+#define AUDIO_MST_A_SCLK_CTRL1		0x044
+#define AUDIO_MST_B_SCLK_CTRL0		0x048
+#define AUDIO_MST_B_SCLK_CTRL1		0x04c
+#define AUDIO_MST_C_SCLK_CTRL0		0x050
+#define AUDIO_MST_C_SCLK_CTRL1		0x054
+#define AUDIO_MST_D_SCLK_CTRL0		0x058
+#define AUDIO_MST_D_SCLK_CTRL1		0x05c
+#define AUDIO_CLK_TDMIN_A_CTRL		0x080
+#define AUDIO_CLK_TDMIN_B_CTRL		0x084
+#define AUDIO_CLK_TDMIN_LB_CTRL		0x08c
+#define AUDIO_CLK_TDMOUT_A_CTRL		0x090
+#define AUDIO_CLK_TDMOUT_B_CTRL		0x094
+#define AUDIO_CLK_SPDIFIN_CTRL		0x09c
+#define AUDIO_CLK_RESAMPLEA_CTRL	0x0a4
+#define AUDIO_CLK_LOCKER_CTRL		0x0a8
+#define AUDIO_CLK_EQDRC_CTRL		0x0c0
+
+#define AUDIO2_CLK81_CTRL		0x000
+#define AUDIO2_CLK81_EN			0x004
+#define AUDIO2_CLK_GATE_EN0		0x00c
+#define AUDIO2_MCLK_VAD_CTRL		0x040
+#define AUDIO2_CLK_VAD_CTRL		0x044
+#define AUDIO2_MST_VAD_SCLK_CTRL0	0x04c
+#define AUDIO2_MST_VAD_SCLK_CTRL1	0x050
+#define AUDIO2_CLK_TDMIN_VAD_CTRL	0x054
+#define AUDIO2_CLK_PDMIN_CTRL0		0x058
+#define AUDIO2_CLK_PDMIN_CTRL1		0x05c
+
+#define AUD_MST_MCLK_MUX(_name, _reg)					\
+	AUD_MUX(_name##_sel, (_reg), 0x7, 24, CLK_MUX_ROUND_CLOSEST,	\
+		a1_mst_pdata, 0)
+#define AUD_MST_MCLK_DIV(_name, _reg)					\
+	AUD_DIV(_name##_div, (_reg), 0, 16, CLK_DIVIDER_ROUND_CLOSEST,	\
+		aud_##_name##_sel, CLK_SET_RATE_PARENT)
+#define AUD_MST_MCLK_GATE(_name, _reg)					\
+	AUD_GATE(_name, (_reg), 31,					\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+
+#define AUD_MST_SCLK_PRE_EN(_name, _reg, _pname)			\
+	AUD_GATE(_name##_pre_en, (_reg), 31,				\
+		aud_##_pname, 0)
+#define AUD_MST_SCLK_DIV(_name, _reg)					\
+	AUD_SCLK_DIV(_name##_div, (_reg), 20, 10, 0, 0,			\
+		aud_##_name##_pre_en, CLK_SET_RATE_PARENT)
+#define AUD_MST_SCLK_POST_EN(_name, _reg)				\
+	AUD_GATE(_name##_post_en, (_reg), 30,				\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+#define AUD_MST_SCLK(_name, _reg)					\
+	AUD_TRIPHASE(_name, (_reg), 1, 0, 2, 4,				\
+		aud_##_name##_post_en, CLK_SET_RATE_PARENT)
+
+#define AUD_MST_LRCLK_DIV(_name, _reg, _pname)				\
+	AUD_SCLK_DIV(_name##_div, (_reg), 0, 10, 10, 10,		\
+		aud_##_pname, 0)
+#define AUD_MST_LRCLK(_name, _reg)					\
+	AUD_TRIPHASE(_name, (_reg), 1, 1, 3, 5,				\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+
+#define AUD_TDM_SCLK_MUX(_name, _reg, _pdata)				\
+	AUD_MUX(_name##_sel, (_reg), 0xf, 24, CLK_MUX_ROUND_CLOSEST,	\
+		(_pdata), 0)
+#define AUD_TDM_SCLK_PRE_EN(_name, _reg)				\
+	AUD_GATE(_name##_pre_en, (_reg), 31,				\
+		aud_##_name##_sel, CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK_POST_EN(_name, _reg)				\
+	AUD_GATE(_name##_post_en, (_reg), 30,				\
+		aud_##_name##_pre_en, CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK(_name, _reg)					\
+	AUD_PHASE(_name, (_reg), 1, 29,					\
+		aud_##_name##_post_en,					\
+		CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK_WS(_name, _reg)					\
+	AUD_SCLK_WS(_name, (_reg), 1, 29, 28,				\
+		aud_##_name##_post_en,					\
+		CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
+
+#define AUD_TDM_LRLCK(_name, _reg, _pdata)				\
+	AUD_MUX(_name, (_reg), 0xf, 20, CLK_MUX_ROUND_CLOSEST,		\
+		(_pdata), CLK_SET_RATE_PARENT)
+
+static const struct clk_parent_data a1_mst_pdata[] = {
+	{ .fw_name = "mst_in0" },
+	{ .fw_name = "mst_in1" },
+	{ .fw_name = "mst_in2" },
+	{ .fw_name = "mst_in3" },
+	{ .fw_name = "mst_in4" },
+};
+
+static const struct clk_parent_data aud_pclk_pdata[] = {
+	{ .fw_name = "pclk" },
+};
+
+struct clk_regmap aud_ddr_arb =
+	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN0, 0, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_a =
+	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN0, 1, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_b =
+	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN0, 2, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_lb =
+	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN0, 3, aud_pclk_pdata);
+struct clk_regmap aud_loopback =
+	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN0, 4, aud_pclk_pdata);
+struct clk_regmap aud_tdmout_a =
+	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN0, 5, aud_pclk_pdata);
+struct clk_regmap aud_tdmout_b =
+	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN0, 6, aud_pclk_pdata);
+struct clk_regmap aud_frddr_a =
+	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN0, 7, aud_pclk_pdata);
+struct clk_regmap aud_frddr_b =
+	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN0, 8, aud_pclk_pdata);
+struct clk_regmap aud_toddr_a =
+	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN0, 9, aud_pclk_pdata);
+struct clk_regmap aud_toddr_b =
+	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN0, 10, aud_pclk_pdata);
+struct clk_regmap aud_spdifin =
+	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN0, 11, aud_pclk_pdata);
+struct clk_regmap aud_resample =
+	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN0, 12, aud_pclk_pdata);
+struct clk_regmap aud_eqdrc =
+	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN0, 13, aud_pclk_pdata);
+struct clk_regmap aud_audiolocker =
+	AUD_PCLK_GATE(audiolocker, AUDIO_CLK_GATE_EN0, 14, aud_pclk_pdata);
+
+struct clk_regmap aud_mst_a_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+struct clk_regmap aud_mst_a_mclk_div =
+	AUD_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+struct clk_regmap aud_mst_a_mclk =
+	AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+
+struct clk_regmap aud_mst_b_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+struct clk_regmap aud_mst_b_mclk_div =
+	AUD_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+struct clk_regmap aud_mst_b_mclk =
+	AUD_MST_MCLK_GATE(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+
+struct clk_regmap aud_mst_c_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+struct clk_regmap aud_mst_c_mclk_div =
+	AUD_MST_MCLK_DIV(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+struct clk_regmap aud_mst_c_mclk =
+	AUD_MST_MCLK_GATE(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+
+struct clk_regmap aud_mst_d_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+struct clk_regmap aud_mst_d_mclk_div =
+	AUD_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+struct clk_regmap aud_mst_d_mclk =
+	AUD_MST_MCLK_GATE(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+
+struct clk_regmap aud_mst_a_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0, mst_a_mclk);
+struct clk_regmap aud_mst_a_sclk_div =
+	AUD_MST_SCLK_DIV(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0);
+struct clk_regmap aud_mst_a_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0);
+struct clk_regmap aud_mst_a_sclk =
+	AUD_MST_SCLK(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_b_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0, mst_b_mclk);
+struct clk_regmap aud_mst_b_sclk_div =
+	AUD_MST_SCLK_DIV(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0);
+struct clk_regmap aud_mst_b_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0);
+struct clk_regmap aud_mst_b_sclk =
+	AUD_MST_SCLK(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_c_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0, mst_c_mclk);
+struct clk_regmap aud_mst_c_sclk_div =
+	AUD_MST_SCLK_DIV(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0);
+struct clk_regmap aud_mst_c_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0);
+struct clk_regmap aud_mst_c_sclk =
+	AUD_MST_SCLK(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_d_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0, mst_d_mclk);
+struct clk_regmap aud_mst_d_sclk_div =
+	AUD_MST_SCLK_DIV(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0);
+struct clk_regmap aud_mst_d_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0);
+struct clk_regmap aud_mst_d_sclk =
+	AUD_MST_SCLK(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_a_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_a_lrclk, AUDIO_MST_A_SCLK_CTRL0,
+			  mst_a_sclk_post_en);
+struct clk_regmap aud_mst_a_lrclk =
+	AUD_MST_LRCLK(mst_a_lrclk, AUDIO_MST_A_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_b_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_b_lrclk, AUDIO_MST_B_SCLK_CTRL0,
+			  mst_b_sclk_post_en);
+struct clk_regmap aud_mst_b_lrclk =
+	AUD_MST_LRCLK(mst_b_lrclk, AUDIO_MST_B_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_c_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_c_lrclk, AUDIO_MST_C_SCLK_CTRL0,
+			  mst_c_sclk_post_en);
+struct clk_regmap aud_mst_c_lrclk =
+	AUD_MST_LRCLK(mst_c_lrclk, AUDIO_MST_C_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_d_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_d_lrclk, AUDIO_MST_D_SCLK_CTRL0,
+			  mst_d_sclk_post_en);
+struct clk_regmap aud_mst_d_lrclk =
+	AUD_MST_LRCLK(mst_d_lrclk, AUDIO_MST_D_SCLK_CTRL1);
+
+static const struct clk_parent_data aud_mst_sclk_pdata[] = {
+	{ .hw = &aud_mst_a_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_b_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_c_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_d_sclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ .fw_name = "slv_sclk0" },
+	{ .fw_name = "slv_sclk1" },
+	{ .fw_name = "slv_sclk2" },
+	{ .fw_name = "slv_sclk3" },
+	{ .fw_name = "slv_sclk4" },
+	{ .fw_name = "slv_sclk5" },
+	{ .fw_name = "slv_sclk6" },
+	{ .fw_name = "slv_sclk7" },
+	{ .fw_name = "slv_sclk8" },
+	{ .fw_name = "slv_sclk9" },
+};
+
+static const struct clk_parent_data aud_mst_lrclk_pdata[] = {
+	{ .hw = &aud_mst_a_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_b_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_c_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_d_lrclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ .fw_name = "slv_lrclk0" },
+	{ .fw_name = "slv_lrclk1" },
+	{ .fw_name = "slv_lrclk2" },
+	{ .fw_name = "slv_lrclk3" },
+	{ .fw_name = "slv_lrclk4" },
+	{ .fw_name = "slv_lrclk5" },
+	{ .fw_name = "slv_lrclk6" },
+	{ .fw_name = "slv_lrclk7" },
+	{ .fw_name = "slv_lrclk8" },
+	{ .fw_name = "slv_lrclk9" },
+};
+
+struct clk_regmap aud_tdmin_a_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_a_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_sclk =
+	AUD_TDM_SCLK(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_lrclk =
+	AUD_TDM_LRLCK(tdmin_a_lrclk, AUDIO_CLK_TDMIN_A_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmin_b_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_b_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_sclk =
+	AUD_TDM_SCLK(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_lrclk =
+	AUD_TDM_LRLCK(tdmin_b_lrclk, AUDIO_CLK_TDMIN_B_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmin_lb_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_lb_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_sclk =
+	AUD_TDM_SCLK(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_lrclk =
+	AUD_TDM_LRLCK(tdmin_lb_lrclk, AUDIO_CLK_TDMIN_LB_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmout_a_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmout_a_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_sclk =
+	AUD_TDM_SCLK_WS(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_lrclk =
+	AUD_TDM_LRLCK(tdmout_a_lrclk, AUDIO_CLK_TDMOUT_A_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmout_b_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmout_b_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_sclk =
+	AUD_TDM_SCLK_WS(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_lrclk =
+	AUD_TDM_LRLCK(tdmout_b_lrclk, AUDIO_CLK_TDMOUT_B_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_spdifin_clk_sel =
+	AUD_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+struct clk_regmap aud_spdifin_clk_div =
+	AUD_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+struct clk_regmap aud_spdifin_clk =
+	AUD_MST_MCLK_GATE(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+
+struct clk_regmap aud_resample_clk_sel =
+	AUD_MUX(resample_clk_sel, AUDIO_CLK_RESAMPLEA_CTRL, 0xf, 24,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_resample_clk_div =
+	AUD_DIV(resample_clk_div, AUDIO_CLK_RESAMPLEA_CTRL, 0, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_resample_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_resample_clk =
+	AUD_GATE(resample_clk, AUDIO_CLK_RESAMPLEA_CTRL, 31,
+		 aud_resample_clk_div, CLK_SET_RATE_PARENT);
+
+struct clk_regmap aud_eqdrc_clk_sel =
+	AUD_MST_MCLK_MUX(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+struct clk_regmap aud_eqdrc_clk_div =
+	AUD_MST_MCLK_DIV(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+struct clk_regmap aud_eqdrc_clk =
+	AUD_MST_MCLK_GATE(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+
+struct clk_regmap aud_locker_in_clk_sel =
+	AUD_MUX(locker_in_clk_sel, AUDIO_CLK_LOCKER_CTRL, 0xf, 8,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_locker_in_clk_div =
+	AUD_DIV(locker_in_clk_div, AUDIO_CLK_LOCKER_CTRL, 0, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_locker_in_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_locker_in_clk =
+	AUD_GATE(locker_in_clk, AUDIO_CLK_LOCKER_CTRL, 15,
+		 aud_locker_in_clk_div, CLK_SET_RATE_PARENT);
+
+struct clk_regmap aud_locker_out_clk_sel =
+	AUD_MUX(locker_out_clk_sel, AUDIO_CLK_LOCKER_CTRL, 0xf, 24,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_locker_out_clk_div =
+	AUD_DIV(locker_out_clk_div, AUDIO_CLK_LOCKER_CTRL, 16, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_locker_out_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_locker_out_clk =
+	AUD_GATE(locker_out_clk, AUDIO_CLK_LOCKER_CTRL, 31,
+		 aud_locker_out_clk_div, CLK_SET_RATE_PARENT);
+
+static struct clk_hw *a1_audio_clkc_hws[] = {
+	[AUD_CLKID_DDR_ARB]		= &aud_ddr_arb.hw,
+	[AUD_CLKID_TDMIN_A]		= &aud_tdmin_a.hw,
+	[AUD_CLKID_TDMIN_B]		= &aud_tdmin_b.hw,
+	[AUD_CLKID_TDMIN_LB]		= &aud_tdmin_lb.hw,
+	[AUD_CLKID_LOOPBACK]		= &aud_loopback.hw,
+	[AUD_CLKID_TDMOUT_A]		= &aud_tdmout_a.hw,
+	[AUD_CLKID_TDMOUT_B]		= &aud_tdmout_b.hw,
+	[AUD_CLKID_FRDDR_A]		= &aud_frddr_a.hw,
+	[AUD_CLKID_FRDDR_B]		= &aud_frddr_b.hw,
+	[AUD_CLKID_TODDR_A]		= &aud_toddr_a.hw,
+	[AUD_CLKID_TODDR_B]		= &aud_toddr_b.hw,
+	[AUD_CLKID_SPDIFIN]		= &aud_spdifin.hw,
+	[AUD_CLKID_RESAMPLE]		= &aud_resample.hw,
+	[AUD_CLKID_EQDRC]		= &aud_eqdrc.hw,
+	[AUD_CLKID_LOCKER]		= &aud_audiolocker.hw,
+	[AUD_CLKID_MST_A_MCLK_SEL]	= &aud_mst_a_mclk_sel.hw,
+	[AUD_CLKID_MST_A_MCLK_DIV]	= &aud_mst_a_mclk_div.hw,
+	[AUD_CLKID_MST_A_MCLK]		= &aud_mst_a_mclk.hw,
+	[AUD_CLKID_MST_B_MCLK_SEL]	= &aud_mst_b_mclk_sel.hw,
+	[AUD_CLKID_MST_B_MCLK_DIV]	= &aud_mst_b_mclk_div.hw,
+	[AUD_CLKID_MST_B_MCLK]		= &aud_mst_b_mclk.hw,
+	[AUD_CLKID_MST_C_MCLK_SEL]	= &aud_mst_c_mclk_sel.hw,
+	[AUD_CLKID_MST_C_MCLK_DIV]	= &aud_mst_c_mclk_div.hw,
+	[AUD_CLKID_MST_C_MCLK]		= &aud_mst_c_mclk.hw,
+	[AUD_CLKID_MST_D_MCLK_SEL]	= &aud_mst_d_mclk_sel.hw,
+	[AUD_CLKID_MST_D_MCLK_DIV]	= &aud_mst_d_mclk_div.hw,
+	[AUD_CLKID_MST_D_MCLK]		= &aud_mst_d_mclk.hw,
+	[AUD_CLKID_MST_A_SCLK_PRE_EN]	= &aud_mst_a_sclk_pre_en.hw,
+	[AUD_CLKID_MST_A_SCLK_DIV]	= &aud_mst_a_sclk_div.hw,
+	[AUD_CLKID_MST_A_SCLK_POST_EN]	= &aud_mst_a_sclk_post_en.hw,
+	[AUD_CLKID_MST_A_SCLK]		= &aud_mst_a_sclk.hw,
+	[AUD_CLKID_MST_B_SCLK_PRE_EN]	= &aud_mst_b_sclk_pre_en.hw,
+	[AUD_CLKID_MST_B_SCLK_DIV]	= &aud_mst_b_sclk_div.hw,
+	[AUD_CLKID_MST_B_SCLK_POST_EN]	= &aud_mst_b_sclk_post_en.hw,
+	[AUD_CLKID_MST_B_SCLK]		= &aud_mst_b_sclk.hw,
+	[AUD_CLKID_MST_C_SCLK_PRE_EN]	= &aud_mst_c_sclk_pre_en.hw,
+	[AUD_CLKID_MST_C_SCLK_DIV]	= &aud_mst_c_sclk_div.hw,
+	[AUD_CLKID_MST_C_SCLK_POST_EN]	= &aud_mst_c_sclk_post_en.hw,
+	[AUD_CLKID_MST_C_SCLK]		= &aud_mst_c_sclk.hw,
+	[AUD_CLKID_MST_D_SCLK_PRE_EN]	= &aud_mst_d_sclk_pre_en.hw,
+	[AUD_CLKID_MST_D_SCLK_DIV]	= &aud_mst_d_sclk_div.hw,
+	[AUD_CLKID_MST_D_SCLK_POST_EN]	= &aud_mst_d_sclk_post_en.hw,
+	[AUD_CLKID_MST_D_SCLK]		= &aud_mst_d_sclk.hw,
+	[AUD_CLKID_MST_A_LRCLK_DIV]	= &aud_mst_a_lrclk_div.hw,
+	[AUD_CLKID_MST_A_LRCLK]		= &aud_mst_a_lrclk.hw,
+	[AUD_CLKID_MST_B_LRCLK_DIV]	= &aud_mst_b_lrclk_div.hw,
+	[AUD_CLKID_MST_B_LRCLK]		= &aud_mst_b_lrclk.hw,
+	[AUD_CLKID_MST_C_LRCLK_DIV]	= &aud_mst_c_lrclk_div.hw,
+	[AUD_CLKID_MST_C_LRCLK]		= &aud_mst_c_lrclk.hw,
+	[AUD_CLKID_MST_D_LRCLK_DIV]	= &aud_mst_d_lrclk_div.hw,
+	[AUD_CLKID_MST_D_LRCLK]		= &aud_mst_d_lrclk.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_SEL]	= &aud_tdmin_a_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_PRE_EN]	= &aud_tdmin_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &aud_tdmin_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK]	= &aud_tdmin_a_sclk.hw,
+	[AUD_CLKID_TDMIN_A_LRCLK]	= &aud_tdmin_a_lrclk.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_SEL]	= &aud_tdmin_b_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_PRE_EN]	= &aud_tdmin_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &aud_tdmin_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK]	= &aud_tdmin_b_sclk.hw,
+	[AUD_CLKID_TDMIN_B_LRCLK]	= &aud_tdmin_b_lrclk.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_SEL]	= &aud_tdmin_lb_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &aud_tdmin_lb_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &aud_tdmin_lb_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK]	= &aud_tdmin_lb_sclk.hw,
+	[AUD_CLKID_TDMIN_LB_LRCLK]	= &aud_tdmin_lb_lrclk.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_SEL]	= &aud_tdmout_a_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &aud_tdmout_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &aud_tdmout_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK]	= &aud_tdmout_a_sclk.hw,
+	[AUD_CLKID_TDMOUT_A_LRCLK]	= &aud_tdmout_a_lrclk.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_SEL]	= &aud_tdmout_b_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &aud_tdmout_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &aud_tdmout_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK]	= &aud_tdmout_b_sclk.hw,
+	[AUD_CLKID_TDMOUT_B_LRCLK]	= &aud_tdmout_b_lrclk.hw,
+	[AUD_CLKID_SPDIFIN_CLK_SEL]	= &aud_spdifin_clk_sel.hw,
+	[AUD_CLKID_SPDIFIN_CLK_DIV]	= &aud_spdifin_clk_div.hw,
+	[AUD_CLKID_SPDIFIN_CLK]		= &aud_spdifin_clk.hw,
+	[AUD_CLKID_RESAMPLE_CLK_SEL]	= &aud_resample_clk_sel.hw,
+	[AUD_CLKID_RESAMPLE_CLK_DIV]	= &aud_resample_clk_div.hw,
+	[AUD_CLKID_RESAMPLE_CLK]	= &aud_resample_clk.hw,
+	[AUD_CLKID_EQDRC_CLK_SEL]	= &aud_eqdrc_clk_sel.hw,
+	[AUD_CLKID_EQDRC_CLK_DIV]	= &aud_eqdrc_clk_div.hw,
+	[AUD_CLKID_EQDRC_CLK]		= &aud_eqdrc_clk.hw,
+	[AUD_CLKID_LOCKER_IN_CLK_SEL]	= &aud_locker_in_clk_sel.hw,
+	[AUD_CLKID_LOCKER_IN_CLK_DIV]	= &aud_locker_in_clk_div.hw,
+	[AUD_CLKID_LOCKER_IN_CLK]	= &aud_locker_in_clk.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK_SEL]	= &aud_locker_out_clk_sel.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK_DIV]	= &aud_locker_out_clk_div.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK]	= &aud_locker_out_clk.hw,
+};
+
+static struct clk_regmap aud_vad_clk81 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_EN,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_clk81",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "pclk",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_clk81.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_sysclk_a_div.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.shift = 16,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_clk81.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_sysclk_b_div.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct clk_parent_data aud_vad_sysclk_pdata[] = {
+	{ .hw = &aud_vad_sysclk_a.hw },
+	{ .hw = &aud_vad_sysclk_b.hw },
+};
+
+static struct clk_regmap aud_vad_sysclk = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "aud_vad_sysclk",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = aud_vad_sysclk_pdata,
+		.num_parents = ARRAY_SIZE(aud_vad_sysclk_pdata),
+		.flags = CLK_SET_RATE_NO_REPARENT,
+	},
+};
+
+static const struct clk_parent_data aud_vad_pclk_pdata[] = {
+	{ .hw = &aud_vad_sysclk.hw },
+};
+
+struct clk_regmap aud_vad_ddr_arb =
+	AUD_PCLK_GATE(vad_ddr_arb, AUDIO2_CLK_GATE_EN0, 0, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_pdm =
+	AUD_PCLK_GATE(vad_pdm, AUDIO2_CLK_GATE_EN0, 1, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_tdmin_vad =
+	AUD_PCLK_GATE(vad_tdmin_vad, AUDIO2_CLK_GATE_EN0, 2, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_toddr_vad =
+	AUD_PCLK_GATE(vad_toddr_vad, AUDIO2_CLK_GATE_EN0, 3, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_tovad =
+	AUD_PCLK_GATE(tovad, AUDIO2_CLK_GATE_EN0, 4, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_toaudiotop =
+	AUD_PCLK_GATE(vad_toaudiotop, AUDIO2_CLK_GATE_EN0, 7, aud_vad_pclk_pdata);
+
+struct clk_regmap aud_vad_mst_vad_mclk_sel =
+	AUD_MST_MCLK_MUX(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+struct clk_regmap aud_vad_mst_vad_mclk_div =
+	AUD_MST_MCLK_DIV(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+struct clk_regmap aud_vad_mst_vad_mclk =
+	AUD_MST_MCLK_GATE(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+
+struct clk_regmap aud_vad_mst_vad_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0,
+			    vad_mst_vad_mclk);
+struct clk_regmap aud_vad_mst_vad_sclk_div =
+	AUD_MST_SCLK_DIV(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0);
+struct clk_regmap aud_vad_mst_vad_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0);
+struct clk_regmap aud_vad_mst_vad_sclk =
+	AUD_MST_SCLK(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL1);
+
+struct clk_regmap aud_vad_mst_vad_lrclk_div =
+	AUD_MST_LRCLK_DIV(vad_mst_vad_lrclk, AUDIO2_MST_VAD_SCLK_CTRL0,
+			  vad_mst_vad_sclk_post_en);
+struct clk_regmap aud_vad_mst_vad_lrclk =
+	AUD_MST_LRCLK(vad_mst_vad_lrclk, AUDIO2_MST_VAD_SCLK_CTRL1);
+
+struct clk_regmap aud_vad_pdm_dclk_sel =
+	AUD_MST_MCLK_MUX(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+struct clk_regmap aud_vad_pdm_dclk_div =
+	AUD_MST_MCLK_DIV(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+struct clk_regmap aud_vad_pdm_dclk =
+	AUD_MST_MCLK_GATE(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+
+struct clk_regmap aud_vad_pdm_sysclk_sel =
+	AUD_MST_MCLK_MUX(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+struct clk_regmap aud_vad_pdm_sysclk_div =
+	AUD_MST_MCLK_DIV(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+struct clk_regmap aud_vad_pdm_sysclk =
+	AUD_MST_MCLK_GATE(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+
+struct clk_regmap aud_vad_vad_clk_sel =
+	AUD_MST_MCLK_MUX(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+struct clk_regmap aud_vad_vad_clk_div =
+	AUD_MST_MCLK_DIV(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+struct clk_regmap aud_vad_vad_clk =
+	AUD_MST_MCLK_GATE(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+
+static const struct clk_parent_data aud_vad_mst_sclk_pdata[] = {
+	{ .hw = &aud_vad_mst_vad_sclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ .fw_name = "slv_sclk0" },
+	{ .fw_name = "slv_sclk1" },
+	{ .fw_name = "slv_sclk2" },
+	{ .fw_name = "slv_sclk3" },
+	{ .fw_name = "slv_sclk4" },
+	{ .fw_name = "slv_sclk5" },
+	{ .fw_name = "slv_sclk6" },
+	{ .fw_name = "slv_sclk7" },
+	{ .fw_name = "slv_sclk8" },
+	{ .fw_name = "slv_sclk9" },
+	};
+
+static const struct clk_parent_data aud_vad_mst_lrclk_pdata[] = {
+	{ .hw = &aud_vad_mst_vad_lrclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ .fw_name = "slv_lrclk0" },
+	{ .fw_name = "slv_lrclk1" },
+	{ .fw_name = "slv_lrclk2" },
+	{ .fw_name = "slv_lrclk3" },
+	{ .fw_name = "slv_lrclk4" },
+	{ .fw_name = "slv_lrclk5" },
+	{ .fw_name = "slv_lrclk6" },
+	{ .fw_name = "slv_lrclk7" },
+	{ .fw_name = "slv_lrclk8" },
+	{ .fw_name = "slv_lrclk9" },
+};
+
+struct clk_regmap aud_vad_tdmin_vad_sclk_sel =
+	AUD_TDM_SCLK_MUX(vad_tdmin_vad_a_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL,
+			 aud_vad_mst_sclk_pdata);
+struct clk_regmap aud_vad_tdmin_vad_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_sclk =
+	AUD_TDM_SCLK(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_lrclk =
+	AUD_TDM_LRLCK(tdmin_vad_lrclk, AUDIO2_CLK_TDMIN_VAD_CTRL,
+		      aud_vad_mst_lrclk_pdata);
+
+static struct clk_hw *a1_audio_vad_clkc_hws[] = {
+	[AUD_VAD_CLKID_CLK81]		= &aud_vad_clk81.hw,
+	[AUD_VAD_CLKID_SYSCLK_A_DIV]	= &aud_vad_sysclk_a_div.hw,
+	[AUD_VAD_CLKID_SYSCLK_A]	= &aud_vad_sysclk_a.hw,
+	[AUD_VAD_CLKID_SYSCLK_B_DIV]	= &aud_vad_sysclk_b_div.hw,
+	[AUD_VAD_CLKID_SYSCLK_B]	= &aud_vad_sysclk_b.hw,
+	[AUD_VAD_CLKID_SYSCLK]		= &aud_vad_sysclk.hw,
+	[AUD_VAD_CLKID_DDR_ARB]		= &aud_vad_ddr_arb.hw,
+	[AUD_VAD_CLKID_PDM]		= &aud_vad_pdm.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD]	= &aud_vad_tdmin_vad.hw,
+	[AUD_VAD_CLKID_TODDR_VAD]	= &aud_vad_toddr_vad.hw,
+	[AUD_VAD_CLKID_TOVAD]		= &aud_vad_tovad.hw,
+	[AUD_VAD_CLKID_TOAUDIOTOP]	= &aud_vad_toaudiotop.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK_SEL] = &aud_vad_mst_vad_mclk_sel.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK_DIV] = &aud_vad_mst_vad_mclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK]	= &aud_vad_mst_vad_mclk.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_PRE_EN] = &aud_vad_mst_vad_sclk_pre_en.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_DIV] = &aud_vad_mst_vad_sclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_POST_EN] = &aud_vad_mst_vad_sclk_post_en.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK]	= &aud_vad_mst_vad_sclk.hw,
+	[AUD_VAD_CLKID_MST_VAD_LRCLK_DIV] = &aud_vad_mst_vad_lrclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_LRCLK]	= &aud_vad_mst_vad_lrclk.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_SEL] = &aud_vad_tdmin_vad_sclk_sel.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_PRE_EN] = &aud_vad_tdmin_vad_sclk_pre_en.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_POST_EN] = &aud_vad_tdmin_vad_sclk_post_en.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK]	= &aud_vad_tdmin_vad_sclk.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_LRCLK]	= &aud_vad_tdmin_vad_lrclk.hw,
+	[AUD_VAD_CLKID_PDM_DCLK_SEL]	= &aud_vad_pdm_dclk_sel.hw,
+	[AUD_VAD_CLKID_PDM_DCLK_DIV]	= &aud_vad_pdm_dclk_div.hw,
+	[AUD_VAD_CLKID_PDM_DCLK]	= &aud_vad_pdm_dclk.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK_SEL]	= &aud_vad_pdm_sysclk_sel.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK_DIV]	= &aud_vad_pdm_sysclk_div.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK]	= &aud_vad_pdm_sysclk.hw,
+	[AUD_VAD_CLKID_VAD_CLK_SEL]	= &aud_vad_vad_clk_sel.hw,
+	[AUD_VAD_CLKID_VAD_CLK_DIV]	= &aud_vad_vad_clk_div.hw,
+	[AUD_VAD_CLKID_VAD_CLK]		= &aud_vad_vad_clk.hw,
+};
+
+struct a1_audio_data {
+	struct meson_clk_hw_data hw_clks;
+	const char *rst_drvname;
+};
+
+static const struct regmap_config a1_audio_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int a1_audio_clkc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct a1_audio_data *data;
+	struct auxiliary_device *auxdev;
+	struct regmap *map;
+	void __iomem *base;
+	struct clk *clk;
+	unsigned int i;
+	int ret;
+
+	data = device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	clk = devm_clk_get_enabled(dev, "pclk");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	map = devm_regmap_init_mmio(dev, base, &a1_audio_regmap_cfg);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	ret = device_reset(dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < data->hw_clks.num; i++) {
+		struct clk_hw *hw = data->hw_clks.hws[i];
+		struct clk_regmap *clk_regmap = to_clk_regmap(hw);
+
+		if (!hw)
+			continue;
+
+		clk_regmap->map = map;
+	}
+
+	for (i = 0; i < data->hw_clks.num; i++) {
+		struct clk_hw *hw;
+
+		hw = data->hw_clks.hws[i];
+		if (!hw)
+			continue;
+
+		ret = devm_clk_hw_register(dev, hw);
+		if (ret)
+			return ret;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
+					  (void *)&data->hw_clks);
+	if (ret)
+		return ret;
+
+	auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
+						data->rst_drvname, NULL, 0);
+	if (!auxdev)
+		return -ENODEV;
+
+	return 0;
+}
+
+struct a1_audio_data a1_audio_clkc = {
+	.hw_clks = {
+		.hws = a1_audio_clkc_hws,
+		.num = ARRAY_SIZE(a1_audio_clkc_hws),
+	},
+	.rst_drvname = "rst-a1",
+};
+
+struct a1_audio_data a1_audio_vad_clkc = {
+	.hw_clks = {
+		.hws = a1_audio_vad_clkc_hws,
+		.num = ARRAY_SIZE(a1_audio_vad_clkc_hws),
+	},
+	.rst_drvname = "rst-a1-vad",
+};
+
+static const struct of_device_id a1_audio_clkc_match_table[] = {
+	{
+		.compatible = "amlogic,a1-audio-clkc",
+		.data = &a1_audio_clkc,
+	},
+	{
+		.compatible = "amlogic,a1-audio-vad-clkc",
+		.data = &a1_audio_vad_clkc,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, a1_audio_clkc_match_table);
+
+static struct platform_driver a1_audio_clkc_driver = {
+	.probe = a1_audio_clkc_probe,
+	.driver = {
+		.name = "a1-audio-clkc",
+		.of_match_table = a1_audio_clkc_match_table,
+	},
+};
+module_platform_driver(a1_audio_clkc_driver);
+
+MODULE_DESCRIPTION("Amlogic A1 Audio Clock driver");
+MODULE_AUTHOR("Jan Dakinevich <jan.dakinevich at salutedevices.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:01:15 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:01:15 +0300
Subject: [PATCH v6 0/4] Add A1 Soc audio clock controller driver
In-Reply-To: <20250309174322.1321201-1-jan.dakinevich@salutedevices.com>
References: <20250309174322.1321201-1-jan.dakinevich@salutedevices.com>
Message-ID: <7dffb0fb-13a0-4c52-8588-647e63761b9e@salutedevices.com>

Please, ignore it.

On 3/9/25 20:43, Jan Dakinevich wrote:
> This series adds support for audio clock and reset controllers on A1 SoC family.
> 
> Depends on [7]
> 
> Changes v5 [5] -> v6
>  - use __devm_auxiliary_device_create() helper that is being introduced in [7]
> 
> Changes v4 [4] -> v5
>  - moved changes of aux reset driver to series [6]
>  - added reset controller on top of audio-vad
>  - merged into single file
>  - reworked variables/defines naming
>  - added clk81 clock hierarchy
>  - added TDMIN_VAD-related clocks
>  - excluded DT patch (it will submitted separately)
> 
> Changes v3 [3] -> v4
>  - Use auxiliary reset device implemented in [4]
>  - Split the driver into files
>  - Use common with axg-audio yaml schema
>  - Unify clock-names with axg-audio
> 
> Changes v2 [2] -> v3
>  - reset:
>    * added auxiliary device
>  - yaml:
>    * added declaration of optional clocks
>    * fixed names in example and another cosmetics
>  - clocks:
>    * reworked naming
>    * stop using of "core" clock name
>    * fixed wrong parenting
> 
> Changes v1 [1] -> v2:
>  - Detached from v1's series (patch 2, 3, 4, 25)
>  - Reuse some of defines from axg-audio
>  - Split the controller into two memory regions
> 
> Links:
>  [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/
>  [2] https://lore.kernel.org/lkml/20240328010831.884487-1-jan.dakinevich at salutedevices.com/
>  [3] https://lore.kernel.org/lkml/20240419125812.983409-1-jan.dakinevich at salutedevices.com/
>  [4] https://lore.kernel.org/all/20240913121152.817575-1-jan.dakinevich at salutedevices.com/
>  [5] https://lore.kernel.org/all/20241112230443.1406460-1-jan.dakinevich at salutedevices.com/
>  [6] https://lore.kernel.org/all/20241112230056.1406222-1-jan.dakinevich at salutedevices.com/
>  [7] https://lore.kernel.org/all/20250218-aux-device-create-helper-v4-0-c3d7dfdea2e6 at baylibre.com/
> 
> Jan Dakinevich (4):
>   clk: meson: axg: share the set of audio helper macros
>   dt-bindings: clock: axg-audio: document A1 SoC audio clock controller
>     driver
>   clk: meson: a1: add the audio clock controller driver
>   arm64: dts: meson: a1: add the audio clock controller
> 
>  .../clock/amlogic,axg-audio-clkc.yaml         |   4 +
>  arch/arm64/boot/dts/amlogic/meson-a1.dtsi     |  49 +
>  drivers/clk/meson/Kconfig                     |  14 +
>  drivers/clk/meson/Makefile                    |   1 +
>  drivers/clk/meson/a1-audio.c                  | 856 ++++++++++++++++++
>  drivers/clk/meson/axg-audio.c                 | 215 +----
>  drivers/clk/meson/meson-audio.h               | 156 ++++
>  .../dt-bindings/clock/amlogic,a1-audio-clkc.h | 139 +++
>  8 files changed, 1254 insertions(+), 180 deletions(-)
>  create mode 100644 drivers/clk/meson/a1-audio.c
>  create mode 100644 drivers/clk/meson/meson-audio.h
>  create mode 100644 include/dt-bindings/clock/amlogic,a1-audio-clkc.h
> 

-- 
Best regards
Jan Dakinevich


From jan.dakinevich at salutedevices.com  Sun Mar  9 11:01:44 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:01:44 +0300
Subject: [PATCH v6 1/4] clk: meson: axg: share the set of audio helper
 macros
In-Reply-To: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
References: <20250309175838.1322014-1-jan.dakinevich@salutedevices.com>
Message-ID: <5a5353e0-e49a-4b6b-b007-ea6cfcb2f827@salutedevices.com>

Please, ignore the series.

On 3/9/25 20:58, Jan Dakinevich wrote:
>  - These macros will be used in upcoming audio clock controller
>     for A1 SoC;
> 
>  - AUD_PCLK_GATE() macro got an extra parameter to be more flexible.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  drivers/clk/meson/axg-audio.c   | 215 ++++++--------------------------
>  drivers/clk/meson/meson-audio.h | 156 +++++++++++++++++++++++
>  2 files changed, 191 insertions(+), 180 deletions(-)
>  create mode 100644 drivers/clk/meson/meson-audio.h
> 
> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
> index 3948f5d0faca..7c4b0c722a94 100644
> --- a/drivers/clk/meson/axg-audio.c
> +++ b/drivers/clk/meson/axg-audio.c
> @@ -16,6 +16,7 @@
>  #include <linux/slab.h>
>  
>  #include "meson-clkc-utils.h"
> +#include "meson-audio.h"
>  #include "axg-audio.h"
>  #include "clk-regmap.h"
>  #include "clk-phase.h"
> @@ -23,155 +24,9 @@
>  
>  #include <dt-bindings/clock/axg-audio-clkc.h>
>  
> -#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
> -	.data = &(struct clk_regmap_gate_data){				\
> -		.offset = (_reg),					\
> -		.bit_idx = (_bit),					\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &clk_regmap_gate_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> -	},								\
> -}
> -
> -#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
> -	.data = &(struct clk_regmap_mux_data){				\
> -		.offset = (_reg),					\
> -		.mask = (_mask),					\
> -		.shift = (_shift),					\
> -		.flags = (_dflags),					\
> -	},								\
> -	.hw.init = &(struct clk_init_data){				\
> -		.name = "aud_"#_name,					\
> -		.ops = &clk_regmap_mux_ops,				\
> -		.parent_data = _pdata,					\
> -		.num_parents = ARRAY_SIZE(_pdata),			\
> -		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> -	},								\
> -}
> -
> -#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
> -	.data = &(struct clk_regmap_div_data){				\
> -		.offset = (_reg),					\
> -		.shift = (_shift),					\
> -		.width = (_width),					\
> -		.flags = (_dflags),					\
> -	},								\
> -	.hw.init = &(struct clk_init_data){				\
> -		.name = "aud_"#_name,					\
> -		.ops = &clk_regmap_divider_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = (_iflags),					\
> -	},								\
> -}
> -
> -#define AUD_PCLK_GATE(_name, _reg, _bit) {				\
> -	.data = &(struct clk_regmap_gate_data){				\
> -		.offset = (_reg),					\
> -		.bit_idx = (_bit),					\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &clk_regmap_gate_ops,				\
> -		.parent_names = (const char *[]){ "aud_top" },		\
> -		.num_parents = 1,					\
> -	},								\
> -}
> -
> -#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
> -		     _hi_shift, _hi_width, _pname, _iflags) {		\
> -	.data = &(struct meson_sclk_div_data) {				\
> -		.div = {						\
> -			.reg_off = (_reg),				\
> -			.shift   = (_div_shift),			\
> -			.width   = (_div_width),			\
> -		},							\
> -		.hi = {							\
> -			.reg_off = (_reg),				\
> -			.shift   = (_hi_shift),				\
> -			.width   = (_hi_width),				\
> -		},							\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &meson_sclk_div_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = (_iflags),					\
> -	},								\
> -}
> -
> -#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
> -		     _pname, _iflags) {					\
> -	.data = &(struct meson_clk_triphase_data) {			\
> -		.ph0 = {						\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift0),				\
> -			.width   = (_width),				\
> -		},							\
> -		.ph1 = {						\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift1),				\
> -			.width   = (_width),				\
> -		},							\
> -		.ph2 = {						\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift2),				\
> -			.width   = (_width),				\
> -		},							\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &meson_clk_triphase_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> -	},								\
> -}
> -
> -#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
> -	.data = &(struct meson_clk_phase_data) {			\
> -		.ph = {							\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift),				\
> -			.width   = (_width),				\
> -		},							\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &meson_clk_phase_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = (_iflags),					\
> -	},								\
> -}
> -
> -#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
> -		    _iflags) {						\
> -	.data = &(struct meson_sclk_ws_inv_data) {			\
> -		.ph = {							\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift_ph),				\
> -			.width   = (_width),				\
> -		},							\
> -		.ws = {							\
> -			.reg_off = (_reg),				\
> -			.shift   = (_shift_ws),				\
> -			.width   = (_width),				\
> -		},							\
> -	},								\
> -	.hw.init = &(struct clk_init_data) {				\
> -		.name = "aud_"#_name,					\
> -		.ops = &meson_clk_phase_ops,				\
> -		.parent_names = (const char *[]){ #_pname },		\
> -		.num_parents = 1,					\
> -		.flags = (_iflags),					\
> -	},								\
> -}
> +static const struct clk_parent_data pclk_parent_data[] = {
> +	{ .name = "aud_top" },
> +};
>  
>  /* Audio Master Clocks */
>  static const struct clk_parent_data mst_mux_parent_data[] = {
> @@ -325,45 +180,45 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
>  
>  /* Common Clocks */
>  static struct clk_regmap ddr_arb =
> -	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
> +	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0, pclk_parent_data);
>  static struct clk_regmap pdm =
> -	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1);
> +	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1, pclk_parent_data);
>  static struct clk_regmap tdmin_a =
> -	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2);
> +	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2, pclk_parent_data);
>  static struct clk_regmap tdmin_b =
> -	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3);
> +	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3, pclk_parent_data);
>  static struct clk_regmap tdmin_c =
> -	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4);
> +	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4, pclk_parent_data);
>  static struct clk_regmap tdmin_lb =
> -	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5);
> +	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5, pclk_parent_data);
>  static struct clk_regmap tdmout_a =
> -	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6);
> +	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6, pclk_parent_data);
>  static struct clk_regmap tdmout_b =
> -	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7);
> +	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7, pclk_parent_data);
>  static struct clk_regmap tdmout_c =
> -	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8);
> +	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8, pclk_parent_data);
>  static struct clk_regmap frddr_a =
> -	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9);
> +	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9, pclk_parent_data);
>  static struct clk_regmap frddr_b =
> -	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10);
> +	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10, pclk_parent_data);
>  static struct clk_regmap frddr_c =
> -	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11);
> +	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11, pclk_parent_data);
>  static struct clk_regmap toddr_a =
> -	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12);
> +	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12, pclk_parent_data);
>  static struct clk_regmap toddr_b =
> -	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13);
> +	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13, pclk_parent_data);
>  static struct clk_regmap toddr_c =
> -	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14);
> +	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14, pclk_parent_data);
>  static struct clk_regmap loopback =
> -	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15);
> +	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15, pclk_parent_data);
>  static struct clk_regmap spdifin =
> -	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16);
> +	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16, pclk_parent_data);
>  static struct clk_regmap spdifout =
> -	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17);
> +	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17, pclk_parent_data);
>  static struct clk_regmap resample =
> -	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18);
> +	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18, pclk_parent_data);
>  static struct clk_regmap power_detect =
> -	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19);
> +	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19, pclk_parent_data);
>  
>  static struct clk_regmap spdifout_clk_sel =
>  	AUD_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
> @@ -631,11 +486,11 @@ static struct clk_regmap g12a_tdmout_c_sclk =
>  	AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
>  
>  static struct clk_regmap toram =
> -	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20);
> +	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20, pclk_parent_data);
>  static struct clk_regmap spdifout_b =
> -	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21);
> +	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21, pclk_parent_data);
>  static struct clk_regmap eqdrc =
> -	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22);
> +	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22, pclk_parent_data);
>  
>  /* SM1 Clocks */
>  static struct clk_regmap sm1_clk81_en = {
> @@ -740,21 +595,21 @@ static struct clk_regmap sm1_aud_top = {
>  };
>  
>  static struct clk_regmap resample_b =
> -	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26);
> +	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26, pclk_parent_data);
>  static struct clk_regmap tovad =
> -	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27);
> +	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27, pclk_parent_data);
>  static struct clk_regmap locker =
> -	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28);
> +	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28, pclk_parent_data);
>  static struct clk_regmap spdifin_lb =
> -	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29);
> +	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29, pclk_parent_data);
>  static struct clk_regmap frddr_d =
> -	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0);
> +	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0, pclk_parent_data);
>  static struct clk_regmap toddr_d =
> -	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1);
> +	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1, pclk_parent_data);
>  static struct clk_regmap loopback_b =
> -	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2);
> +	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2, pclk_parent_data);
>  static struct clk_regmap earcrx =
> -	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6);
> +	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6, pclk_parent_data);
>  
>  
>  static struct clk_regmap sm1_mst_a_mclk_sel =
> diff --git a/drivers/clk/meson/meson-audio.h b/drivers/clk/meson/meson-audio.h
> new file mode 100644
> index 000000000000..16dd044d52bd
> --- /dev/null
> +++ b/drivers/clk/meson/meson-audio.h
> @@ -0,0 +1,156 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
> +
> +#ifndef __MESON_AUDIO_H__
> +#define __MESON_AUDIO_H__
> +
> +#define AUD_PCLK_GATE(_name, _reg, _bit, _pdata) {			\
> +	.data = &(struct clk_regmap_gate_data){				\
> +		.offset = (_reg),					\
> +		.bit_idx = (_bit),					\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &clk_regmap_gate_ops,				\
> +		.parent_data = (_pdata),				\
> +		.num_parents = 1,					\
> +	},								\
> +}
> +
> +#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
> +	.data = &(struct clk_regmap_gate_data){				\
> +		.offset = (_reg),					\
> +		.bit_idx = (_bit),					\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &clk_regmap_gate_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> +	},								\
> +}
> +
> +#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
> +	.data = &(struct clk_regmap_mux_data){				\
> +		.offset = (_reg),					\
> +		.mask = (_mask),					\
> +		.shift = (_shift),					\
> +		.flags = (_dflags),					\
> +	},								\
> +	.hw.init = &(struct clk_init_data){				\
> +		.name = "aud_"#_name,					\
> +		.ops = &clk_regmap_mux_ops,				\
> +		.parent_data = _pdata,					\
> +		.num_parents = ARRAY_SIZE(_pdata),			\
> +		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> +	},								\
> +}
> +
> +#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
> +	.data = &(struct clk_regmap_div_data){				\
> +		.offset = (_reg),					\
> +		.shift = (_shift),					\
> +		.width = (_width),					\
> +		.flags = (_dflags),					\
> +	},								\
> +	.hw.init = &(struct clk_init_data){				\
> +		.name = "aud_"#_name,					\
> +		.ops = &clk_regmap_divider_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = (_iflags),					\
> +	},								\
> +}
> +
> +#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
> +		     _hi_shift, _hi_width, _pname, _iflags) {		\
> +	.data = &(struct meson_sclk_div_data) {				\
> +		.div = {						\
> +			.reg_off = (_reg),				\
> +			.shift   = (_div_shift),			\
> +			.width   = (_div_width),			\
> +		},							\
> +		.hi = {							\
> +			.reg_off = (_reg),				\
> +			.shift   = (_hi_shift),				\
> +			.width   = (_hi_width),				\
> +		},							\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &meson_sclk_div_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = (_iflags),					\
> +	},								\
> +}
> +
> +#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
> +		     _pname, _iflags) {					\
> +	.data = &(struct meson_clk_triphase_data) {			\
> +		.ph0 = {						\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift0),				\
> +			.width   = (_width),				\
> +		},							\
> +		.ph1 = {						\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift1),				\
> +			.width   = (_width),				\
> +		},							\
> +		.ph2 = {						\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift2),				\
> +			.width   = (_width),				\
> +		},							\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &meson_clk_triphase_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
> +	},								\
> +}
> +
> +#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
> +	.data = &(struct meson_clk_phase_data) {			\
> +		.ph = {							\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift),				\
> +			.width   = (_width),				\
> +		},							\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &meson_clk_phase_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = (_iflags),					\
> +	},								\
> +}
> +
> +#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
> +		    _iflags) {						\
> +	.data = &(struct meson_sclk_ws_inv_data) {			\
> +		.ph = {							\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift_ph),				\
> +			.width   = (_width),				\
> +		},							\
> +		.ws = {							\
> +			.reg_off = (_reg),				\
> +			.shift   = (_shift_ws),				\
> +			.width   = (_width),				\
> +		},							\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = "aud_"#_name,					\
> +		.ops = &meson_clk_phase_ops,				\
> +		.parent_names = (const char *[]){ #_pname },		\
> +		.num_parents = 1,					\
> +		.flags = (_iflags),					\
> +	},								\
> +}
> +
> +#endif /* __MESON_AUDIO_H__ */

-- 
Best regards
Jan Dakinevich


From jan.dakinevich at salutedevices.com  Sun Mar  9 11:09:38 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:09:38 +0300
Subject: [PATCH v6 2/4] dt-bindings: clock: axg-audio: document A1 SoC audio clock controller driver
In-Reply-To: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309180940.1322531-3-jan.dakinevich@salutedevices.com>

Add device tree bindings for A1 SoC audio clock and reset controllers.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../clock/amlogic,axg-audio-clkc.yaml         |   4 +
 .../dt-bindings/clock/amlogic,a1-audio-clkc.h | 139 ++++++++++++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 include/dt-bindings/clock/amlogic,a1-audio-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
index fd7982dd4cea..10202b749001 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
+++ b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
@@ -18,6 +18,8 @@ description:
 properties:
   compatible:
     enum:
+      - amlogic,a1-audio-clkc
+      - amlogic,a1-audio-vad-clkc
       - amlogic,axg-audio-clkc
       - amlogic,g12a-audio-clkc
       - amlogic,sm1-audio-clkc
@@ -114,6 +116,8 @@ allOf:
         compatible:
           contains:
             enum:
+              - amlogic,a1-audio-clkc
+              - amlogic,a1-audio-vad-clkc
               - amlogic,g12a-audio-clkc
               - amlogic,sm1-audio-clkc
     then:
diff --git a/include/dt-bindings/clock/amlogic,a1-audio-clkc.h b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
new file mode 100644
index 000000000000..78e7a432d439
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a1-audio-clkc.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Jan Dakinevich <jan.dakinevich at salutedevices.com>
+ */
+
+#ifndef __A1_AUDIO_CLKC_BINDINGS_H
+#define __A1_AUDIO_CLKC_BINDINGS_H
+
+#define AUD_CLKID_DDR_ARB			1
+#define AUD_CLKID_TDMIN_A			2
+#define AUD_CLKID_TDMIN_B			3
+#define AUD_CLKID_TDMIN_LB			4
+#define AUD_CLKID_LOOPBACK			5
+#define AUD_CLKID_TDMOUT_A			6
+#define AUD_CLKID_TDMOUT_B			7
+#define AUD_CLKID_FRDDR_A			8
+#define AUD_CLKID_FRDDR_B			9
+#define AUD_CLKID_TODDR_A			10
+#define AUD_CLKID_TODDR_B			11
+#define AUD_CLKID_SPDIFIN			12
+#define AUD_CLKID_RESAMPLE			13
+#define AUD_CLKID_EQDRC				14
+#define AUD_CLKID_LOCKER			15
+#define AUD_CLKID_MST_A_MCLK_SEL		16
+#define AUD_CLKID_MST_A_MCLK_DIV		17
+#define AUD_CLKID_MST_A_MCLK			18
+#define AUD_CLKID_MST_B_MCLK_SEL		19
+#define AUD_CLKID_MST_B_MCLK_DIV		20
+#define AUD_CLKID_MST_B_MCLK			21
+#define AUD_CLKID_MST_C_MCLK_SEL		22
+#define AUD_CLKID_MST_C_MCLK_DIV		23
+#define AUD_CLKID_MST_C_MCLK			24
+#define AUD_CLKID_MST_D_MCLK_SEL		25
+#define AUD_CLKID_MST_D_MCLK_DIV		26
+#define AUD_CLKID_MST_D_MCLK			27
+#define AUD_CLKID_MST_A_SCLK_PRE_EN		28
+#define AUD_CLKID_MST_A_SCLK_DIV		29
+#define AUD_CLKID_MST_A_SCLK_POST_EN		30
+#define AUD_CLKID_MST_A_SCLK			31
+#define AUD_CLKID_MST_B_SCLK_PRE_EN		32
+#define AUD_CLKID_MST_B_SCLK_DIV		33
+#define AUD_CLKID_MST_B_SCLK_POST_EN		34
+#define AUD_CLKID_MST_B_SCLK			35
+#define AUD_CLKID_MST_C_SCLK_PRE_EN		36
+#define AUD_CLKID_MST_C_SCLK_DIV		37
+#define AUD_CLKID_MST_C_SCLK_POST_EN		38
+#define AUD_CLKID_MST_C_SCLK			39
+#define AUD_CLKID_MST_D_SCLK_PRE_EN		40
+#define AUD_CLKID_MST_D_SCLK_DIV		41
+#define AUD_CLKID_MST_D_SCLK_POST_EN		42
+#define AUD_CLKID_MST_D_SCLK			43
+#define AUD_CLKID_MST_A_LRCLK_DIV		44
+#define AUD_CLKID_MST_A_LRCLK			45
+#define AUD_CLKID_MST_B_LRCLK_DIV		46
+#define AUD_CLKID_MST_B_LRCLK			47
+#define AUD_CLKID_MST_C_LRCLK_DIV		48
+#define AUD_CLKID_MST_C_LRCLK			49
+#define AUD_CLKID_MST_D_LRCLK_DIV		50
+#define AUD_CLKID_MST_D_LRCLK			51
+#define AUD_CLKID_TDMIN_A_SCLK_SEL		52
+#define AUD_CLKID_TDMIN_A_SCLK_PRE_EN		53
+#define AUD_CLKID_TDMIN_A_SCLK_POST_EN		54
+#define AUD_CLKID_TDMIN_A_SCLK			55
+#define AUD_CLKID_TDMIN_A_LRCLK			56
+#define AUD_CLKID_TDMIN_B_SCLK_SEL		57
+#define AUD_CLKID_TDMIN_B_SCLK_PRE_EN		58
+#define AUD_CLKID_TDMIN_B_SCLK_POST_EN		59
+#define AUD_CLKID_TDMIN_B_SCLK			60
+#define AUD_CLKID_TDMIN_B_LRCLK			61
+#define AUD_CLKID_TDMIN_LB_SCLK_SEL		62
+#define AUD_CLKID_TDMIN_LB_SCLK_PRE_EN		63
+#define AUD_CLKID_TDMIN_LB_SCLK_POST_EN		64
+#define AUD_CLKID_TDMIN_LB_SCLK			65
+#define AUD_CLKID_TDMIN_LB_LRCLK		66
+#define AUD_CLKID_TDMOUT_A_SCLK_SEL		67
+#define AUD_CLKID_TDMOUT_A_SCLK_PRE_EN		68
+#define AUD_CLKID_TDMOUT_A_SCLK_POST_EN		69
+#define AUD_CLKID_TDMOUT_A_SCLK			70
+#define AUD_CLKID_TDMOUT_A_LRCLK		71
+#define AUD_CLKID_TDMOUT_B_SCLK_SEL		72
+#define AUD_CLKID_TDMOUT_B_SCLK_PRE_EN		73
+#define AUD_CLKID_TDMOUT_B_SCLK_POST_EN		74
+#define AUD_CLKID_TDMOUT_B_SCLK			75
+#define AUD_CLKID_TDMOUT_B_LRCLK		76
+#define AUD_CLKID_SPDIFIN_CLK_SEL		77
+#define AUD_CLKID_SPDIFIN_CLK_DIV		78
+#define AUD_CLKID_SPDIFIN_CLK			79
+#define AUD_CLKID_RESAMPLE_CLK_SEL		80
+#define AUD_CLKID_RESAMPLE_CLK_DIV		81
+#define AUD_CLKID_RESAMPLE_CLK			82
+#define AUD_CLKID_EQDRC_CLK_SEL			83
+#define AUD_CLKID_EQDRC_CLK_DIV			84
+#define AUD_CLKID_EQDRC_CLK			85
+#define AUD_CLKID_LOCKER_IN_CLK_SEL		86
+#define AUD_CLKID_LOCKER_IN_CLK_DIV		87
+#define AUD_CLKID_LOCKER_IN_CLK			88
+#define AUD_CLKID_LOCKER_OUT_CLK_SEL		89
+#define AUD_CLKID_LOCKER_OUT_CLK_DIV		90
+#define AUD_CLKID_LOCKER_OUT_CLK		91
+
+#define AUD_VAD_CLKID_CLK81			1
+#define AUD_VAD_CLKID_SYSCLK_A_DIV		2
+#define AUD_VAD_CLKID_SYSCLK_A			3
+#define AUD_VAD_CLKID_SYSCLK_B_DIV		4
+#define AUD_VAD_CLKID_SYSCLK_B			5
+#define AUD_VAD_CLKID_SYSCLK			6
+#define AUD_VAD_CLKID_DDR_ARB			7
+#define AUD_VAD_CLKID_PDM			8
+#define AUD_VAD_CLKID_TDMIN_VAD			9
+#define AUD_VAD_CLKID_TODDR_VAD			10
+#define AUD_VAD_CLKID_TOVAD			11
+#define AUD_VAD_CLKID_TOAUDIOTOP		12
+#define AUD_VAD_CLKID_MST_VAD_MCLK_SEL		13
+#define AUD_VAD_CLKID_MST_VAD_MCLK_DIV		14
+#define AUD_VAD_CLKID_MST_VAD_MCLK		15
+#define AUD_VAD_CLKID_MST_VAD_SCLK_PRE_EN	16
+#define AUD_VAD_CLKID_MST_VAD_SCLK_DIV		17
+#define AUD_VAD_CLKID_MST_VAD_SCLK_POST_EN	18
+#define AUD_VAD_CLKID_MST_VAD_SCLK		19
+#define AUD_VAD_CLKID_MST_VAD_LRCLK_DIV		20
+#define AUD_VAD_CLKID_MST_VAD_LRCLK		21
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_SEL	22
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_PRE_EN	23
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK_POST_EN	24
+#define AUD_VAD_CLKID_TDMIN_VAD_SCLK		25
+#define AUD_VAD_CLKID_TDMIN_VAD_LRCLK		26
+#define AUD_VAD_CLKID_PDM_DCLK_SEL		27
+#define AUD_VAD_CLKID_PDM_DCLK_DIV		28
+#define AUD_VAD_CLKID_PDM_DCLK			29
+#define AUD_VAD_CLKID_PDM_SYSCLK_SEL		30
+#define AUD_VAD_CLKID_PDM_SYSCLK_DIV		31
+#define AUD_VAD_CLKID_PDM_SYSCLK		32
+#define AUD_VAD_CLKID_VAD_CLK_SEL		33
+#define AUD_VAD_CLKID_VAD_CLK_DIV		34
+#define AUD_VAD_CLKID_VAD_CLK			35
+
+#endif /* __A1_AUDIO_CLKC_BINDINGS_H */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:09:36 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:09:36 +0300
Subject: [PATCH v6 0/4] Add A1 Soc audio clock controller driver
Message-ID: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>

This series adds support for audio clock and reset controllers on A1 SoC family.

Depends on [7]

Changes v5 [5] -> v6
 - use __devm_auxiliary_device_create() helper that is being introduced in [7]

Changes v4 [4] -> v5
 - moved changes of aux reset driver to series [6]
 - added reset controller on top of audio-vad
 - merged into single file
 - reworked variables/defines naming
 - added clk81 clock hierarchy
 - added TDMIN_VAD-related clocks
 - excluded DT patch (it will submitted separately)

Changes v3 [3] -> v4
 - Use auxiliary reset device implemented in [4]
 - Split the driver into files
 - Use common with axg-audio yaml schema
 - Unify clock-names with axg-audio

Changes v2 [2] -> v3
 - reset:
   * added auxiliary device
 - yaml:
   * added declaration of optional clocks
   * fixed names in example and another cosmetics
 - clocks:
   * reworked naming
   * stop using of "core" clock name
   * fixed wrong parenting

Changes v1 [1] -> v2:
 - Detached from v1's series (patch 2, 3, 4, 25)
 - Reuse some of defines from axg-audio
 - Split the controller into two memory regions

Links:
 [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/
 [2] https://lore.kernel.org/lkml/20240328010831.884487-1-jan.dakinevich at salutedevices.com/
 [3] https://lore.kernel.org/lkml/20240419125812.983409-1-jan.dakinevich at salutedevices.com/
 [4] https://lore.kernel.org/all/20240913121152.817575-1-jan.dakinevich at salutedevices.com/
 [5] https://lore.kernel.org/all/20241112230443.1406460-1-jan.dakinevich at salutedevices.com/
 [6] https://lore.kernel.org/all/20241112230056.1406222-1-jan.dakinevich at salutedevices.com/
 [7] https://lore.kernel.org/all/20250218-aux-device-create-helper-v4-0-c3d7dfdea2e6 at baylibre.com/

Jan Dakinevich (4):
  clk: meson: axg: share the set of audio helper macros
  dt-bindings: clock: axg-audio: document A1 SoC audio clock controller
    driver
  clk: meson: a1: add the audio clock controller driver
  arm64: dts: meson: a1: add the audio clock controller

 .../clock/amlogic,axg-audio-clkc.yaml         |   4 +
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi     |  49 +
 drivers/clk/meson/Kconfig                     |  14 +
 drivers/clk/meson/Makefile                    |   1 +
 drivers/clk/meson/a1-audio.c                  | 856 ++++++++++++++++++
 drivers/clk/meson/axg-audio.c                 | 215 +----
 drivers/clk/meson/meson-audio.h               | 156 ++++
 .../dt-bindings/clock/amlogic,a1-audio-clkc.h | 139 +++
 8 files changed, 1254 insertions(+), 180 deletions(-)
 create mode 100644 drivers/clk/meson/a1-audio.c
 create mode 100644 drivers/clk/meson/meson-audio.h
 create mode 100644 include/dt-bindings/clock/amlogic,a1-audio-clkc.h

-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:09:37 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:09:37 +0300
Subject: [PATCH v6 1/4] clk: meson: axg: share the set of audio helper macros
In-Reply-To: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309180940.1322531-2-jan.dakinevich@salutedevices.com>

 - These macros will be used in upcoming audio clock controller
    for A1 SoC;

 - AUD_PCLK_GATE() macro got an extra parameter to be more flexible.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 drivers/clk/meson/axg-audio.c   | 215 ++++++--------------------------
 drivers/clk/meson/meson-audio.h | 156 +++++++++++++++++++++++
 2 files changed, 191 insertions(+), 180 deletions(-)
 create mode 100644 drivers/clk/meson/meson-audio.h

diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 3948f5d0faca..7c4b0c722a94 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 
 #include "meson-clkc-utils.h"
+#include "meson-audio.h"
 #include "axg-audio.h"
 #include "clk-regmap.h"
 #include "clk-phase.h"
@@ -23,155 +24,9 @@
 
 #include <dt-bindings/clock/axg-audio-clkc.h>
 
-#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
-	.data = &(struct clk_regmap_gate_data){				\
-		.offset = (_reg),					\
-		.bit_idx = (_bit),					\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_gate_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
-	.data = &(struct clk_regmap_mux_data){				\
-		.offset = (_reg),					\
-		.mask = (_mask),					\
-		.shift = (_shift),					\
-		.flags = (_dflags),					\
-	},								\
-	.hw.init = &(struct clk_init_data){				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_mux_ops,				\
-		.parent_data = _pdata,					\
-		.num_parents = ARRAY_SIZE(_pdata),			\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
-	.data = &(struct clk_regmap_div_data){				\
-		.offset = (_reg),					\
-		.shift = (_shift),					\
-		.width = (_width),					\
-		.flags = (_dflags),					\
-	},								\
-	.hw.init = &(struct clk_init_data){				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_divider_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_PCLK_GATE(_name, _reg, _bit) {				\
-	.data = &(struct clk_regmap_gate_data){				\
-		.offset = (_reg),					\
-		.bit_idx = (_bit),					\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &clk_regmap_gate_ops,				\
-		.parent_names = (const char *[]){ "aud_top" },		\
-		.num_parents = 1,					\
-	},								\
-}
-
-#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
-		     _hi_shift, _hi_width, _pname, _iflags) {		\
-	.data = &(struct meson_sclk_div_data) {				\
-		.div = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_div_shift),			\
-			.width   = (_div_width),			\
-		},							\
-		.hi = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_hi_shift),				\
-			.width   = (_hi_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_sclk_div_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
-		     _pname, _iflags) {					\
-	.data = &(struct meson_clk_triphase_data) {			\
-		.ph0 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift0),				\
-			.width   = (_width),				\
-		},							\
-		.ph1 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift1),				\
-			.width   = (_width),				\
-		},							\
-		.ph2 = {						\
-			.reg_off = (_reg),				\
-			.shift   = (_shift2),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_triphase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
-	},								\
-}
-
-#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
-	.data = &(struct meson_clk_phase_data) {			\
-		.ph = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_phase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
-
-#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
-		    _iflags) {						\
-	.data = &(struct meson_sclk_ws_inv_data) {			\
-		.ph = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift_ph),				\
-			.width   = (_width),				\
-		},							\
-		.ws = {							\
-			.reg_off = (_reg),				\
-			.shift   = (_shift_ws),				\
-			.width   = (_width),				\
-		},							\
-	},								\
-	.hw.init = &(struct clk_init_data) {				\
-		.name = "aud_"#_name,					\
-		.ops = &meson_clk_phase_ops,				\
-		.parent_names = (const char *[]){ #_pname },		\
-		.num_parents = 1,					\
-		.flags = (_iflags),					\
-	},								\
-}
+static const struct clk_parent_data pclk_parent_data[] = {
+	{ .name = "aud_top" },
+};
 
 /* Audio Master Clocks */
 static const struct clk_parent_data mst_mux_parent_data[] = {
@@ -325,45 +180,45 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
 
 /* Common Clocks */
 static struct clk_regmap ddr_arb =
-	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
+	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0, pclk_parent_data);
 static struct clk_regmap pdm =
-	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1);
+	AUD_PCLK_GATE(pdm, AUDIO_CLK_GATE_EN, 1, pclk_parent_data);
 static struct clk_regmap tdmin_a =
-	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2);
+	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN, 2, pclk_parent_data);
 static struct clk_regmap tdmin_b =
-	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3);
+	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN, 3, pclk_parent_data);
 static struct clk_regmap tdmin_c =
-	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4);
+	AUD_PCLK_GATE(tdmin_c, AUDIO_CLK_GATE_EN, 4, pclk_parent_data);
 static struct clk_regmap tdmin_lb =
-	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5);
+	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN, 5, pclk_parent_data);
 static struct clk_regmap tdmout_a =
-	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6);
+	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN, 6, pclk_parent_data);
 static struct clk_regmap tdmout_b =
-	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7);
+	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN, 7, pclk_parent_data);
 static struct clk_regmap tdmout_c =
-	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8);
+	AUD_PCLK_GATE(tdmout_c, AUDIO_CLK_GATE_EN, 8, pclk_parent_data);
 static struct clk_regmap frddr_a =
-	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9);
+	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN, 9, pclk_parent_data);
 static struct clk_regmap frddr_b =
-	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10);
+	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN, 10, pclk_parent_data);
 static struct clk_regmap frddr_c =
-	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11);
+	AUD_PCLK_GATE(frddr_c, AUDIO_CLK_GATE_EN, 11, pclk_parent_data);
 static struct clk_regmap toddr_a =
-	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12);
+	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN, 12, pclk_parent_data);
 static struct clk_regmap toddr_b =
-	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13);
+	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN, 13, pclk_parent_data);
 static struct clk_regmap toddr_c =
-	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14);
+	AUD_PCLK_GATE(toddr_c, AUDIO_CLK_GATE_EN, 14, pclk_parent_data);
 static struct clk_regmap loopback =
-	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15);
+	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN, 15, pclk_parent_data);
 static struct clk_regmap spdifin =
-	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16);
+	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN, 16, pclk_parent_data);
 static struct clk_regmap spdifout =
-	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17);
+	AUD_PCLK_GATE(spdifout, AUDIO_CLK_GATE_EN, 17, pclk_parent_data);
 static struct clk_regmap resample =
-	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18);
+	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN, 18, pclk_parent_data);
 static struct clk_regmap power_detect =
-	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19);
+	AUD_PCLK_GATE(power_detect, AUDIO_CLK_GATE_EN, 19, pclk_parent_data);
 
 static struct clk_regmap spdifout_clk_sel =
 	AUD_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
@@ -631,11 +486,11 @@ static struct clk_regmap g12a_tdmout_c_sclk =
 	AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
 
 static struct clk_regmap toram =
-	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20);
+	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20, pclk_parent_data);
 static struct clk_regmap spdifout_b =
-	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21);
+	AUD_PCLK_GATE(spdifout_b, AUDIO_CLK_GATE_EN, 21, pclk_parent_data);
 static struct clk_regmap eqdrc =
-	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22);
+	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN, 22, pclk_parent_data);
 
 /* SM1 Clocks */
 static struct clk_regmap sm1_clk81_en = {
@@ -740,21 +595,21 @@ static struct clk_regmap sm1_aud_top = {
 };
 
 static struct clk_regmap resample_b =
-	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26);
+	AUD_PCLK_GATE(resample_b, AUDIO_CLK_GATE_EN, 26, pclk_parent_data);
 static struct clk_regmap tovad =
-	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27);
+	AUD_PCLK_GATE(tovad, AUDIO_CLK_GATE_EN, 27, pclk_parent_data);
 static struct clk_regmap locker =
-	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28);
+	AUD_PCLK_GATE(locker, AUDIO_CLK_GATE_EN, 28, pclk_parent_data);
 static struct clk_regmap spdifin_lb =
-	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29);
+	AUD_PCLK_GATE(spdifin_lb, AUDIO_CLK_GATE_EN, 29, pclk_parent_data);
 static struct clk_regmap frddr_d =
-	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0);
+	AUD_PCLK_GATE(frddr_d, AUDIO_CLK_GATE_EN1, 0, pclk_parent_data);
 static struct clk_regmap toddr_d =
-	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1);
+	AUD_PCLK_GATE(toddr_d, AUDIO_CLK_GATE_EN1, 1, pclk_parent_data);
 static struct clk_regmap loopback_b =
-	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2);
+	AUD_PCLK_GATE(loopback_b, AUDIO_CLK_GATE_EN1, 2, pclk_parent_data);
 static struct clk_regmap earcrx =
-	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6);
+	AUD_PCLK_GATE(earcrx, AUDIO_CLK_GATE_EN1, 6, pclk_parent_data);
 
 
 static struct clk_regmap sm1_mst_a_mclk_sel =
diff --git a/drivers/clk/meson/meson-audio.h b/drivers/clk/meson/meson-audio.h
new file mode 100644
index 000000000000..16dd044d52bd
--- /dev/null
+++ b/drivers/clk/meson/meson-audio.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+
+#ifndef __MESON_AUDIO_H__
+#define __MESON_AUDIO_H__
+
+#define AUD_PCLK_GATE(_name, _reg, _bit, _pdata) {			\
+	.data = &(struct clk_regmap_gate_data){				\
+		.offset = (_reg),					\
+		.bit_idx = (_bit),					\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_gate_ops,				\
+		.parent_data = (_pdata),				\
+		.num_parents = 1,					\
+	},								\
+}
+
+#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) {			\
+	.data = &(struct clk_regmap_gate_data){				\
+		.offset = (_reg),					\
+		.bit_idx = (_bit),					\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_gate_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) {	\
+	.data = &(struct clk_regmap_mux_data){				\
+		.offset = (_reg),					\
+		.mask = (_mask),					\
+		.shift = (_shift),					\
+		.flags = (_dflags),					\
+	},								\
+	.hw.init = &(struct clk_init_data){				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_mux_ops,				\
+		.parent_data = _pdata,					\
+		.num_parents = ARRAY_SIZE(_pdata),			\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) { \
+	.data = &(struct clk_regmap_div_data){				\
+		.offset = (_reg),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.flags = (_dflags),					\
+	},								\
+	.hw.init = &(struct clk_init_data){				\
+		.name = "aud_"#_name,					\
+		.ops = &clk_regmap_divider_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,		\
+		     _hi_shift, _hi_width, _pname, _iflags) {		\
+	.data = &(struct meson_sclk_div_data) {				\
+		.div = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_div_shift),			\
+			.width   = (_div_width),			\
+		},							\
+		.hi = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_hi_shift),				\
+			.width   = (_hi_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_sclk_div_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2,	\
+		     _pname, _iflags) {					\
+	.data = &(struct meson_clk_triphase_data) {			\
+		.ph0 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift0),				\
+			.width   = (_width),				\
+		},							\
+		.ph1 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift1),				\
+			.width   = (_width),				\
+		},							\
+		.ph2 = {						\
+			.reg_off = (_reg),				\
+			.shift   = (_shift2),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_triphase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = CLK_DUTY_CYCLE_PARENT | (_iflags),		\
+	},								\
+}
+
+#define AUD_PHASE(_name, _reg, _width, _shift, _pname, _iflags) {	\
+	.data = &(struct meson_clk_phase_data) {			\
+		.ph = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_phase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
+		    _iflags) {						\
+	.data = &(struct meson_sclk_ws_inv_data) {			\
+		.ph = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift_ph),				\
+			.width   = (_width),				\
+		},							\
+		.ws = {							\
+			.reg_off = (_reg),				\
+			.shift   = (_shift_ws),				\
+			.width   = (_width),				\
+		},							\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = "aud_"#_name,					\
+		.ops = &meson_clk_phase_ops,				\
+		.parent_names = (const char *[]){ #_pname },		\
+		.num_parents = 1,					\
+		.flags = (_iflags),					\
+	},								\
+}
+
+#endif /* __MESON_AUDIO_H__ */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:09:40 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:09:40 +0300
Subject: [PATCH v6 4/4] arm64: dts: meson: a1: add the audio clock controller
In-Reply-To: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309180940.1322531-5-jan.dakinevich@salutedevices.com>

Add the bus and audio clock controllers' device tree nodes.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi | 49 +++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index 1eba0afb3fd9..cf0247fce740 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -5,6 +5,7 @@
 
 #include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
 #include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
+#include <dt-bindings/clock/amlogic,a1-audio-clkc.h>
 #include <dt-bindings/gpio/meson-a1-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -664,6 +665,54 @@ sd_emmc: mmc at 10000 {
 				power-domains = <&pwrc PWRC_SD_EMMC_ID>;
 				status = "disabled";
 			};
+
+			audio: bus at 50000 {
+				compatible = "simple-bus";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges = <0x0 0x0 0x0 0x50000 0 0x4980>;
+				power-domains = <&pwrc PWRC_AUDIO_ID>;
+
+				clkc_audio: clock-controller at 0 {
+					compatible = "amlogic,a1-audio-clkc";
+					reg = <0x0 0x0 0x0 0xb0>;
+					#clock-cells = <1>;
+					#reset-cells = <1>;
+					clocks = <&clkc_audio_vad AUD_VAD_CLKID_TOAUDIOTOP>,
+						 <&clkc_periphs CLKID_DDS_IN>,
+						 <&clkc_pll CLKID_FCLK_DIV2>,
+						 <&clkc_pll CLKID_FCLK_DIV3>,
+						 <&clkc_pll CLKID_HIFI_PLL>,
+						 <&xtal>;
+					clock-names = "pclk",
+						      "mst_in0",
+						      "mst_in1",
+						      "mst_in2",
+						      "mst_in3",
+						      "mst_in4";
+					resets = <&reset RESET_AUDIO>;
+				};
+
+				clkc_audio_vad: clock-controller at 4800 {
+					compatible = "amlogic,a1-audio-vad-clkc";
+					reg = <0x0 0x4800 0x0 0x20>;
+					#clock-cells = <1>;
+					#reset-cells = <1>;
+					clocks = <&clkc_periphs CLKID_SYS>,
+						 <&clkc_periphs CLKID_DDS_IN>,
+						 <&clkc_pll CLKID_FCLK_DIV2>,
+						 <&clkc_pll CLKID_FCLK_DIV3>,
+						 <&clkc_pll CLKID_HIFI_PLL>,
+						 <&xtal>;
+					clock-names = "pclk",
+						      "mst_in0",
+						      "mst_in1",
+						      "mst_in2",
+						      "mst_in3",
+						      "mst_in4";
+					resets = <&reset RESET_AUDIO_VAD>;
+				};
+			};
 		};
 
 		usb: usb at fe004400 {
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:09:39 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:09:39 +0300
Subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller driver
In-Reply-To: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309180940.1322531-4-jan.dakinevich@salutedevices.com>

This controller provides clocks and reset functionality for audio
peripherals on Amlogic A1 SoC family.

The driver is almost identical to 'axg-audio', however it would be
better to keep it separate to avoid a mess of new defines with A1_
prefixes (significant amount of bits has another definition comparing
to AXG/SM1/G12A).

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 drivers/clk/meson/Kconfig    |  14 +
 drivers/clk/meson/Makefile   |   1 +
 drivers/clk/meson/a1-audio.c | 856 +++++++++++++++++++++++++++++++++++
 3 files changed, 871 insertions(+)
 create mode 100644 drivers/clk/meson/a1-audio.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 7cb21fc223b0..49f2086bc773 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -133,6 +133,20 @@ config COMMON_CLK_A1_PERIPHERALS
 	  device, A1 SoC Family. Say Y if you want A1 Peripherals clock
 	  controller to work.
 
+config COMMON_CLK_A1_AUDIO
+	tristate "Amlogic A1 SoC Audio clock controller support"
+	depends on ARM64
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_PHASE
+	select COMMON_CLK_MESON_SCLK_DIV
+	select COMMON_CLK_MESON_CLKC_UTILS
+	select REGMAP_MMIO
+	imply RESET_MESON_AUX
+	help
+	  Support for the Audio clock controller on Amlogic A113L based
+	  device, A1 SoC Family. Say Y if you want A1 Audio clock controller
+	  to work.
+
 config COMMON_CLK_C3_PLL
 	tristate "Amlogic C3 PLL clock controller"
 	depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index bc56a47931c1..f3d8f6545f59 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
 obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
 obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
+obj-$(CONFIG_COMMON_CLK_A1_AUDIO) += a1-audio.o
 obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
 obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/a1-audio.c b/drivers/clk/meson/a1-audio.c
new file mode 100644
index 000000000000..e87b578417bf
--- /dev/null
+++ b/drivers/clk/meson/a1-audio.c
@@ -0,0 +1,856 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Jan Dakinevich <jan.dakinevich at salutedevices.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/clock/amlogic,a1-audio-clkc.h>
+
+#include "clk-phase.h"
+#include "clk-regmap.h"
+#include "meson-audio.h"
+#include "meson-clkc-utils.h"
+#include "sclk-div.h"
+
+#define AUDIO_CLK_GATE_EN0		0x000
+#define AUDIO_MCLK_A_CTRL		0x008
+#define AUDIO_MCLK_B_CTRL		0x00c
+#define AUDIO_MCLK_C_CTRL		0x010
+#define AUDIO_MCLK_D_CTRL		0x014
+#define AUDIO_SW_RESET0			0x028
+#define AUDIO_MST_A_SCLK_CTRL0		0x040
+#define AUDIO_MST_A_SCLK_CTRL1		0x044
+#define AUDIO_MST_B_SCLK_CTRL0		0x048
+#define AUDIO_MST_B_SCLK_CTRL1		0x04c
+#define AUDIO_MST_C_SCLK_CTRL0		0x050
+#define AUDIO_MST_C_SCLK_CTRL1		0x054
+#define AUDIO_MST_D_SCLK_CTRL0		0x058
+#define AUDIO_MST_D_SCLK_CTRL1		0x05c
+#define AUDIO_CLK_TDMIN_A_CTRL		0x080
+#define AUDIO_CLK_TDMIN_B_CTRL		0x084
+#define AUDIO_CLK_TDMIN_LB_CTRL		0x08c
+#define AUDIO_CLK_TDMOUT_A_CTRL		0x090
+#define AUDIO_CLK_TDMOUT_B_CTRL		0x094
+#define AUDIO_CLK_SPDIFIN_CTRL		0x09c
+#define AUDIO_CLK_RESAMPLEA_CTRL	0x0a4
+#define AUDIO_CLK_LOCKER_CTRL		0x0a8
+#define AUDIO_CLK_EQDRC_CTRL		0x0c0
+
+#define AUDIO2_CLK81_CTRL		0x000
+#define AUDIO2_CLK81_EN			0x004
+#define AUDIO2_CLK_GATE_EN0		0x00c
+#define AUDIO2_MCLK_VAD_CTRL		0x040
+#define AUDIO2_CLK_VAD_CTRL		0x044
+#define AUDIO2_MST_VAD_SCLK_CTRL0	0x04c
+#define AUDIO2_MST_VAD_SCLK_CTRL1	0x050
+#define AUDIO2_CLK_TDMIN_VAD_CTRL	0x054
+#define AUDIO2_CLK_PDMIN_CTRL0		0x058
+#define AUDIO2_CLK_PDMIN_CTRL1		0x05c
+
+#define AUD_MST_MCLK_MUX(_name, _reg)					\
+	AUD_MUX(_name##_sel, (_reg), 0x7, 24, CLK_MUX_ROUND_CLOSEST,	\
+		a1_mst_pdata, 0)
+#define AUD_MST_MCLK_DIV(_name, _reg)					\
+	AUD_DIV(_name##_div, (_reg), 0, 16, CLK_DIVIDER_ROUND_CLOSEST,	\
+		aud_##_name##_sel, CLK_SET_RATE_PARENT)
+#define AUD_MST_MCLK_GATE(_name, _reg)					\
+	AUD_GATE(_name, (_reg), 31,					\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+
+#define AUD_MST_SCLK_PRE_EN(_name, _reg, _pname)			\
+	AUD_GATE(_name##_pre_en, (_reg), 31,				\
+		aud_##_pname, 0)
+#define AUD_MST_SCLK_DIV(_name, _reg)					\
+	AUD_SCLK_DIV(_name##_div, (_reg), 20, 10, 0, 0,			\
+		aud_##_name##_pre_en, CLK_SET_RATE_PARENT)
+#define AUD_MST_SCLK_POST_EN(_name, _reg)				\
+	AUD_GATE(_name##_post_en, (_reg), 30,				\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+#define AUD_MST_SCLK(_name, _reg)					\
+	AUD_TRIPHASE(_name, (_reg), 1, 0, 2, 4,				\
+		aud_##_name##_post_en, CLK_SET_RATE_PARENT)
+
+#define AUD_MST_LRCLK_DIV(_name, _reg, _pname)				\
+	AUD_SCLK_DIV(_name##_div, (_reg), 0, 10, 10, 10,		\
+		aud_##_pname, 0)
+#define AUD_MST_LRCLK(_name, _reg)					\
+	AUD_TRIPHASE(_name, (_reg), 1, 1, 3, 5,				\
+		aud_##_name##_div, CLK_SET_RATE_PARENT)
+
+#define AUD_TDM_SCLK_MUX(_name, _reg, _pdata)				\
+	AUD_MUX(_name##_sel, (_reg), 0xf, 24, CLK_MUX_ROUND_CLOSEST,	\
+		(_pdata), 0)
+#define AUD_TDM_SCLK_PRE_EN(_name, _reg)				\
+	AUD_GATE(_name##_pre_en, (_reg), 31,				\
+		aud_##_name##_sel, CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK_POST_EN(_name, _reg)				\
+	AUD_GATE(_name##_post_en, (_reg), 30,				\
+		aud_##_name##_pre_en, CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK(_name, _reg)					\
+	AUD_PHASE(_name, (_reg), 1, 29,					\
+		aud_##_name##_post_en,					\
+		CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
+#define AUD_TDM_SCLK_WS(_name, _reg)					\
+	AUD_SCLK_WS(_name, (_reg), 1, 29, 28,				\
+		aud_##_name##_post_en,					\
+		CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
+
+#define AUD_TDM_LRLCK(_name, _reg, _pdata)				\
+	AUD_MUX(_name, (_reg), 0xf, 20, CLK_MUX_ROUND_CLOSEST,		\
+		(_pdata), CLK_SET_RATE_PARENT)
+
+static const struct clk_parent_data a1_mst_pdata[] = {
+	{ .fw_name = "mst_in0" },
+	{ .fw_name = "mst_in1" },
+	{ .fw_name = "mst_in2" },
+	{ .fw_name = "mst_in3" },
+	{ .fw_name = "mst_in4" },
+};
+
+static const struct clk_parent_data aud_pclk_pdata[] = {
+	{ .fw_name = "pclk" },
+};
+
+struct clk_regmap aud_ddr_arb =
+	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN0, 0, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_a =
+	AUD_PCLK_GATE(tdmin_a, AUDIO_CLK_GATE_EN0, 1, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_b =
+	AUD_PCLK_GATE(tdmin_b, AUDIO_CLK_GATE_EN0, 2, aud_pclk_pdata);
+struct clk_regmap aud_tdmin_lb =
+	AUD_PCLK_GATE(tdmin_lb, AUDIO_CLK_GATE_EN0, 3, aud_pclk_pdata);
+struct clk_regmap aud_loopback =
+	AUD_PCLK_GATE(loopback, AUDIO_CLK_GATE_EN0, 4, aud_pclk_pdata);
+struct clk_regmap aud_tdmout_a =
+	AUD_PCLK_GATE(tdmout_a, AUDIO_CLK_GATE_EN0, 5, aud_pclk_pdata);
+struct clk_regmap aud_tdmout_b =
+	AUD_PCLK_GATE(tdmout_b, AUDIO_CLK_GATE_EN0, 6, aud_pclk_pdata);
+struct clk_regmap aud_frddr_a =
+	AUD_PCLK_GATE(frddr_a, AUDIO_CLK_GATE_EN0, 7, aud_pclk_pdata);
+struct clk_regmap aud_frddr_b =
+	AUD_PCLK_GATE(frddr_b, AUDIO_CLK_GATE_EN0, 8, aud_pclk_pdata);
+struct clk_regmap aud_toddr_a =
+	AUD_PCLK_GATE(toddr_a, AUDIO_CLK_GATE_EN0, 9, aud_pclk_pdata);
+struct clk_regmap aud_toddr_b =
+	AUD_PCLK_GATE(toddr_b, AUDIO_CLK_GATE_EN0, 10, aud_pclk_pdata);
+struct clk_regmap aud_spdifin =
+	AUD_PCLK_GATE(spdifin, AUDIO_CLK_GATE_EN0, 11, aud_pclk_pdata);
+struct clk_regmap aud_resample =
+	AUD_PCLK_GATE(resample, AUDIO_CLK_GATE_EN0, 12, aud_pclk_pdata);
+struct clk_regmap aud_eqdrc =
+	AUD_PCLK_GATE(eqdrc, AUDIO_CLK_GATE_EN0, 13, aud_pclk_pdata);
+struct clk_regmap aud_audiolocker =
+	AUD_PCLK_GATE(audiolocker, AUDIO_CLK_GATE_EN0, 14, aud_pclk_pdata);
+
+struct clk_regmap aud_mst_a_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+struct clk_regmap aud_mst_a_mclk_div =
+	AUD_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+struct clk_regmap aud_mst_a_mclk =
+	AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
+
+struct clk_regmap aud_mst_b_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+struct clk_regmap aud_mst_b_mclk_div =
+	AUD_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+struct clk_regmap aud_mst_b_mclk =
+	AUD_MST_MCLK_GATE(mst_b_mclk, AUDIO_MCLK_B_CTRL);
+
+struct clk_regmap aud_mst_c_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+struct clk_regmap aud_mst_c_mclk_div =
+	AUD_MST_MCLK_DIV(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+struct clk_regmap aud_mst_c_mclk =
+	AUD_MST_MCLK_GATE(mst_c_mclk, AUDIO_MCLK_C_CTRL);
+
+struct clk_regmap aud_mst_d_mclk_sel =
+	AUD_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+struct clk_regmap aud_mst_d_mclk_div =
+	AUD_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+struct clk_regmap aud_mst_d_mclk =
+	AUD_MST_MCLK_GATE(mst_d_mclk, AUDIO_MCLK_D_CTRL);
+
+struct clk_regmap aud_mst_a_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0, mst_a_mclk);
+struct clk_regmap aud_mst_a_sclk_div =
+	AUD_MST_SCLK_DIV(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0);
+struct clk_regmap aud_mst_a_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL0);
+struct clk_regmap aud_mst_a_sclk =
+	AUD_MST_SCLK(mst_a_sclk, AUDIO_MST_A_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_b_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0, mst_b_mclk);
+struct clk_regmap aud_mst_b_sclk_div =
+	AUD_MST_SCLK_DIV(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0);
+struct clk_regmap aud_mst_b_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL0);
+struct clk_regmap aud_mst_b_sclk =
+	AUD_MST_SCLK(mst_b_sclk, AUDIO_MST_B_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_c_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0, mst_c_mclk);
+struct clk_regmap aud_mst_c_sclk_div =
+	AUD_MST_SCLK_DIV(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0);
+struct clk_regmap aud_mst_c_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL0);
+struct clk_regmap aud_mst_c_sclk =
+	AUD_MST_SCLK(mst_c_sclk, AUDIO_MST_C_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_d_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0, mst_d_mclk);
+struct clk_regmap aud_mst_d_sclk_div =
+	AUD_MST_SCLK_DIV(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0);
+struct clk_regmap aud_mst_d_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL0);
+struct clk_regmap aud_mst_d_sclk =
+	AUD_MST_SCLK(mst_d_sclk, AUDIO_MST_D_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_a_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_a_lrclk, AUDIO_MST_A_SCLK_CTRL0,
+			  mst_a_sclk_post_en);
+struct clk_regmap aud_mst_a_lrclk =
+	AUD_MST_LRCLK(mst_a_lrclk, AUDIO_MST_A_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_b_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_b_lrclk, AUDIO_MST_B_SCLK_CTRL0,
+			  mst_b_sclk_post_en);
+struct clk_regmap aud_mst_b_lrclk =
+	AUD_MST_LRCLK(mst_b_lrclk, AUDIO_MST_B_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_c_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_c_lrclk, AUDIO_MST_C_SCLK_CTRL0,
+			  mst_c_sclk_post_en);
+struct clk_regmap aud_mst_c_lrclk =
+	AUD_MST_LRCLK(mst_c_lrclk, AUDIO_MST_C_SCLK_CTRL1);
+
+struct clk_regmap aud_mst_d_lrclk_div =
+	AUD_MST_LRCLK_DIV(mst_d_lrclk, AUDIO_MST_D_SCLK_CTRL0,
+			  mst_d_sclk_post_en);
+struct clk_regmap aud_mst_d_lrclk =
+	AUD_MST_LRCLK(mst_d_lrclk, AUDIO_MST_D_SCLK_CTRL1);
+
+static const struct clk_parent_data aud_mst_sclk_pdata[] = {
+	{ .hw = &aud_mst_a_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_b_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_c_sclk.hw, .index = -1 },
+	{ .hw = &aud_mst_d_sclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ .fw_name = "slv_sclk0" },
+	{ .fw_name = "slv_sclk1" },
+	{ .fw_name = "slv_sclk2" },
+	{ .fw_name = "slv_sclk3" },
+	{ .fw_name = "slv_sclk4" },
+	{ .fw_name = "slv_sclk5" },
+	{ .fw_name = "slv_sclk6" },
+	{ .fw_name = "slv_sclk7" },
+	{ .fw_name = "slv_sclk8" },
+	{ .fw_name = "slv_sclk9" },
+};
+
+static const struct clk_parent_data aud_mst_lrclk_pdata[] = {
+	{ .hw = &aud_mst_a_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_b_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_c_lrclk.hw, .index = -1 },
+	{ .hw = &aud_mst_d_lrclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ .fw_name = "slv_lrclk0" },
+	{ .fw_name = "slv_lrclk1" },
+	{ .fw_name = "slv_lrclk2" },
+	{ .fw_name = "slv_lrclk3" },
+	{ .fw_name = "slv_lrclk4" },
+	{ .fw_name = "slv_lrclk5" },
+	{ .fw_name = "slv_lrclk6" },
+	{ .fw_name = "slv_lrclk7" },
+	{ .fw_name = "slv_lrclk8" },
+	{ .fw_name = "slv_lrclk9" },
+};
+
+struct clk_regmap aud_tdmin_a_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_a_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_sclk =
+	AUD_TDM_SCLK(tdmin_a_sclk, AUDIO_CLK_TDMIN_A_CTRL);
+struct clk_regmap aud_tdmin_a_lrclk =
+	AUD_TDM_LRLCK(tdmin_a_lrclk, AUDIO_CLK_TDMIN_A_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmin_b_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_b_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_sclk =
+	AUD_TDM_SCLK(tdmin_b_sclk, AUDIO_CLK_TDMIN_B_CTRL);
+struct clk_regmap aud_tdmin_b_lrclk =
+	AUD_TDM_LRLCK(tdmin_b_lrclk, AUDIO_CLK_TDMIN_B_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmin_lb_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmin_lb_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_sclk =
+	AUD_TDM_SCLK(tdmin_lb_sclk, AUDIO_CLK_TDMIN_LB_CTRL);
+struct clk_regmap aud_tdmin_lb_lrclk =
+	AUD_TDM_LRLCK(tdmin_lb_lrclk, AUDIO_CLK_TDMIN_LB_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmout_a_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmout_a_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_sclk =
+	AUD_TDM_SCLK_WS(tdmout_a_sclk, AUDIO_CLK_TDMOUT_A_CTRL);
+struct clk_regmap aud_tdmout_a_lrclk =
+	AUD_TDM_LRLCK(tdmout_a_lrclk, AUDIO_CLK_TDMOUT_A_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_tdmout_b_sclk_sel =
+	AUD_TDM_SCLK_MUX(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL,
+			 aud_mst_sclk_pdata);
+struct clk_regmap aud_tdmout_b_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_sclk =
+	AUD_TDM_SCLK_WS(tdmout_b_sclk, AUDIO_CLK_TDMOUT_B_CTRL);
+struct clk_regmap aud_tdmout_b_lrclk =
+	AUD_TDM_LRLCK(tdmout_b_lrclk, AUDIO_CLK_TDMOUT_B_CTRL,
+		      aud_mst_lrclk_pdata);
+
+struct clk_regmap aud_spdifin_clk_sel =
+	AUD_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+struct clk_regmap aud_spdifin_clk_div =
+	AUD_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+struct clk_regmap aud_spdifin_clk =
+	AUD_MST_MCLK_GATE(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+
+struct clk_regmap aud_resample_clk_sel =
+	AUD_MUX(resample_clk_sel, AUDIO_CLK_RESAMPLEA_CTRL, 0xf, 24,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_resample_clk_div =
+	AUD_DIV(resample_clk_div, AUDIO_CLK_RESAMPLEA_CTRL, 0, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_resample_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_resample_clk =
+	AUD_GATE(resample_clk, AUDIO_CLK_RESAMPLEA_CTRL, 31,
+		 aud_resample_clk_div, CLK_SET_RATE_PARENT);
+
+struct clk_regmap aud_eqdrc_clk_sel =
+	AUD_MST_MCLK_MUX(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+struct clk_regmap aud_eqdrc_clk_div =
+	AUD_MST_MCLK_DIV(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+struct clk_regmap aud_eqdrc_clk =
+	AUD_MST_MCLK_GATE(eqdrc_clk, AUDIO_CLK_EQDRC_CTRL);
+
+struct clk_regmap aud_locker_in_clk_sel =
+	AUD_MUX(locker_in_clk_sel, AUDIO_CLK_LOCKER_CTRL, 0xf, 8,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_locker_in_clk_div =
+	AUD_DIV(locker_in_clk_div, AUDIO_CLK_LOCKER_CTRL, 0, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_locker_in_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_locker_in_clk =
+	AUD_GATE(locker_in_clk, AUDIO_CLK_LOCKER_CTRL, 15,
+		 aud_locker_in_clk_div, CLK_SET_RATE_PARENT);
+
+struct clk_regmap aud_locker_out_clk_sel =
+	AUD_MUX(locker_out_clk_sel, AUDIO_CLK_LOCKER_CTRL, 0xf, 24,
+		CLK_MUX_ROUND_CLOSEST, a1_mst_pdata, 0);
+struct clk_regmap aud_locker_out_clk_div =
+	AUD_DIV(locker_out_clk_div, AUDIO_CLK_LOCKER_CTRL, 16, 8,
+		CLK_DIVIDER_ROUND_CLOSEST, aud_locker_out_clk_sel,
+		CLK_SET_RATE_PARENT);
+struct clk_regmap aud_locker_out_clk =
+	AUD_GATE(locker_out_clk, AUDIO_CLK_LOCKER_CTRL, 31,
+		 aud_locker_out_clk_div, CLK_SET_RATE_PARENT);
+
+static struct clk_hw *a1_audio_clkc_hws[] = {
+	[AUD_CLKID_DDR_ARB]		= &aud_ddr_arb.hw,
+	[AUD_CLKID_TDMIN_A]		= &aud_tdmin_a.hw,
+	[AUD_CLKID_TDMIN_B]		= &aud_tdmin_b.hw,
+	[AUD_CLKID_TDMIN_LB]		= &aud_tdmin_lb.hw,
+	[AUD_CLKID_LOOPBACK]		= &aud_loopback.hw,
+	[AUD_CLKID_TDMOUT_A]		= &aud_tdmout_a.hw,
+	[AUD_CLKID_TDMOUT_B]		= &aud_tdmout_b.hw,
+	[AUD_CLKID_FRDDR_A]		= &aud_frddr_a.hw,
+	[AUD_CLKID_FRDDR_B]		= &aud_frddr_b.hw,
+	[AUD_CLKID_TODDR_A]		= &aud_toddr_a.hw,
+	[AUD_CLKID_TODDR_B]		= &aud_toddr_b.hw,
+	[AUD_CLKID_SPDIFIN]		= &aud_spdifin.hw,
+	[AUD_CLKID_RESAMPLE]		= &aud_resample.hw,
+	[AUD_CLKID_EQDRC]		= &aud_eqdrc.hw,
+	[AUD_CLKID_LOCKER]		= &aud_audiolocker.hw,
+	[AUD_CLKID_MST_A_MCLK_SEL]	= &aud_mst_a_mclk_sel.hw,
+	[AUD_CLKID_MST_A_MCLK_DIV]	= &aud_mst_a_mclk_div.hw,
+	[AUD_CLKID_MST_A_MCLK]		= &aud_mst_a_mclk.hw,
+	[AUD_CLKID_MST_B_MCLK_SEL]	= &aud_mst_b_mclk_sel.hw,
+	[AUD_CLKID_MST_B_MCLK_DIV]	= &aud_mst_b_mclk_div.hw,
+	[AUD_CLKID_MST_B_MCLK]		= &aud_mst_b_mclk.hw,
+	[AUD_CLKID_MST_C_MCLK_SEL]	= &aud_mst_c_mclk_sel.hw,
+	[AUD_CLKID_MST_C_MCLK_DIV]	= &aud_mst_c_mclk_div.hw,
+	[AUD_CLKID_MST_C_MCLK]		= &aud_mst_c_mclk.hw,
+	[AUD_CLKID_MST_D_MCLK_SEL]	= &aud_mst_d_mclk_sel.hw,
+	[AUD_CLKID_MST_D_MCLK_DIV]	= &aud_mst_d_mclk_div.hw,
+	[AUD_CLKID_MST_D_MCLK]		= &aud_mst_d_mclk.hw,
+	[AUD_CLKID_MST_A_SCLK_PRE_EN]	= &aud_mst_a_sclk_pre_en.hw,
+	[AUD_CLKID_MST_A_SCLK_DIV]	= &aud_mst_a_sclk_div.hw,
+	[AUD_CLKID_MST_A_SCLK_POST_EN]	= &aud_mst_a_sclk_post_en.hw,
+	[AUD_CLKID_MST_A_SCLK]		= &aud_mst_a_sclk.hw,
+	[AUD_CLKID_MST_B_SCLK_PRE_EN]	= &aud_mst_b_sclk_pre_en.hw,
+	[AUD_CLKID_MST_B_SCLK_DIV]	= &aud_mst_b_sclk_div.hw,
+	[AUD_CLKID_MST_B_SCLK_POST_EN]	= &aud_mst_b_sclk_post_en.hw,
+	[AUD_CLKID_MST_B_SCLK]		= &aud_mst_b_sclk.hw,
+	[AUD_CLKID_MST_C_SCLK_PRE_EN]	= &aud_mst_c_sclk_pre_en.hw,
+	[AUD_CLKID_MST_C_SCLK_DIV]	= &aud_mst_c_sclk_div.hw,
+	[AUD_CLKID_MST_C_SCLK_POST_EN]	= &aud_mst_c_sclk_post_en.hw,
+	[AUD_CLKID_MST_C_SCLK]		= &aud_mst_c_sclk.hw,
+	[AUD_CLKID_MST_D_SCLK_PRE_EN]	= &aud_mst_d_sclk_pre_en.hw,
+	[AUD_CLKID_MST_D_SCLK_DIV]	= &aud_mst_d_sclk_div.hw,
+	[AUD_CLKID_MST_D_SCLK_POST_EN]	= &aud_mst_d_sclk_post_en.hw,
+	[AUD_CLKID_MST_D_SCLK]		= &aud_mst_d_sclk.hw,
+	[AUD_CLKID_MST_A_LRCLK_DIV]	= &aud_mst_a_lrclk_div.hw,
+	[AUD_CLKID_MST_A_LRCLK]		= &aud_mst_a_lrclk.hw,
+	[AUD_CLKID_MST_B_LRCLK_DIV]	= &aud_mst_b_lrclk_div.hw,
+	[AUD_CLKID_MST_B_LRCLK]		= &aud_mst_b_lrclk.hw,
+	[AUD_CLKID_MST_C_LRCLK_DIV]	= &aud_mst_c_lrclk_div.hw,
+	[AUD_CLKID_MST_C_LRCLK]		= &aud_mst_c_lrclk.hw,
+	[AUD_CLKID_MST_D_LRCLK_DIV]	= &aud_mst_d_lrclk_div.hw,
+	[AUD_CLKID_MST_D_LRCLK]		= &aud_mst_d_lrclk.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_SEL]	= &aud_tdmin_a_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_PRE_EN]	= &aud_tdmin_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &aud_tdmin_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK]	= &aud_tdmin_a_sclk.hw,
+	[AUD_CLKID_TDMIN_A_LRCLK]	= &aud_tdmin_a_lrclk.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_SEL]	= &aud_tdmin_b_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_PRE_EN]	= &aud_tdmin_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &aud_tdmin_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK]	= &aud_tdmin_b_sclk.hw,
+	[AUD_CLKID_TDMIN_B_LRCLK]	= &aud_tdmin_b_lrclk.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_SEL]	= &aud_tdmin_lb_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &aud_tdmin_lb_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &aud_tdmin_lb_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK]	= &aud_tdmin_lb_sclk.hw,
+	[AUD_CLKID_TDMIN_LB_LRCLK]	= &aud_tdmin_lb_lrclk.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_SEL]	= &aud_tdmout_a_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &aud_tdmout_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &aud_tdmout_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK]	= &aud_tdmout_a_sclk.hw,
+	[AUD_CLKID_TDMOUT_A_LRCLK]	= &aud_tdmout_a_lrclk.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_SEL]	= &aud_tdmout_b_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &aud_tdmout_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &aud_tdmout_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK]	= &aud_tdmout_b_sclk.hw,
+	[AUD_CLKID_TDMOUT_B_LRCLK]	= &aud_tdmout_b_lrclk.hw,
+	[AUD_CLKID_SPDIFIN_CLK_SEL]	= &aud_spdifin_clk_sel.hw,
+	[AUD_CLKID_SPDIFIN_CLK_DIV]	= &aud_spdifin_clk_div.hw,
+	[AUD_CLKID_SPDIFIN_CLK]		= &aud_spdifin_clk.hw,
+	[AUD_CLKID_RESAMPLE_CLK_SEL]	= &aud_resample_clk_sel.hw,
+	[AUD_CLKID_RESAMPLE_CLK_DIV]	= &aud_resample_clk_div.hw,
+	[AUD_CLKID_RESAMPLE_CLK]	= &aud_resample_clk.hw,
+	[AUD_CLKID_EQDRC_CLK_SEL]	= &aud_eqdrc_clk_sel.hw,
+	[AUD_CLKID_EQDRC_CLK_DIV]	= &aud_eqdrc_clk_div.hw,
+	[AUD_CLKID_EQDRC_CLK]		= &aud_eqdrc_clk.hw,
+	[AUD_CLKID_LOCKER_IN_CLK_SEL]	= &aud_locker_in_clk_sel.hw,
+	[AUD_CLKID_LOCKER_IN_CLK_DIV]	= &aud_locker_in_clk_div.hw,
+	[AUD_CLKID_LOCKER_IN_CLK]	= &aud_locker_in_clk.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK_SEL]	= &aud_locker_out_clk_sel.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK_DIV]	= &aud_locker_out_clk_div.hw,
+	[AUD_CLKID_LOCKER_OUT_CLK]	= &aud_locker_out_clk.hw,
+};
+
+static struct clk_regmap aud_vad_clk81 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_EN,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_clk81",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "pclk",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_clk81.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_sysclk_a_div.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.shift = 16,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_clk81.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap aud_vad_sysclk_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "aud_vad_sysclk_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &aud_vad_sysclk_b_div.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct clk_parent_data aud_vad_sysclk_pdata[] = {
+	{ .hw = &aud_vad_sysclk_a.hw },
+	{ .hw = &aud_vad_sysclk_b.hw },
+};
+
+static struct clk_regmap aud_vad_sysclk = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = AUDIO2_CLK81_CTRL,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "aud_vad_sysclk",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = aud_vad_sysclk_pdata,
+		.num_parents = ARRAY_SIZE(aud_vad_sysclk_pdata),
+		.flags = CLK_SET_RATE_NO_REPARENT,
+	},
+};
+
+static const struct clk_parent_data aud_vad_pclk_pdata[] = {
+	{ .hw = &aud_vad_sysclk.hw },
+};
+
+struct clk_regmap aud_vad_ddr_arb =
+	AUD_PCLK_GATE(vad_ddr_arb, AUDIO2_CLK_GATE_EN0, 0, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_pdm =
+	AUD_PCLK_GATE(vad_pdm, AUDIO2_CLK_GATE_EN0, 1, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_tdmin_vad =
+	AUD_PCLK_GATE(vad_tdmin_vad, AUDIO2_CLK_GATE_EN0, 2, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_toddr_vad =
+	AUD_PCLK_GATE(vad_toddr_vad, AUDIO2_CLK_GATE_EN0, 3, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_tovad =
+	AUD_PCLK_GATE(tovad, AUDIO2_CLK_GATE_EN0, 4, aud_vad_pclk_pdata);
+struct clk_regmap aud_vad_toaudiotop =
+	AUD_PCLK_GATE(vad_toaudiotop, AUDIO2_CLK_GATE_EN0, 7, aud_vad_pclk_pdata);
+
+struct clk_regmap aud_vad_mst_vad_mclk_sel =
+	AUD_MST_MCLK_MUX(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+struct clk_regmap aud_vad_mst_vad_mclk_div =
+	AUD_MST_MCLK_DIV(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+struct clk_regmap aud_vad_mst_vad_mclk =
+	AUD_MST_MCLK_GATE(vad_mst_vad_mclk, AUDIO2_MCLK_VAD_CTRL);
+
+struct clk_regmap aud_vad_mst_vad_sclk_pre_en =
+	AUD_MST_SCLK_PRE_EN(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0,
+			    vad_mst_vad_mclk);
+struct clk_regmap aud_vad_mst_vad_sclk_div =
+	AUD_MST_SCLK_DIV(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0);
+struct clk_regmap aud_vad_mst_vad_sclk_post_en =
+	AUD_MST_SCLK_POST_EN(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL0);
+struct clk_regmap aud_vad_mst_vad_sclk =
+	AUD_MST_SCLK(vad_mst_vad_sclk, AUDIO2_MST_VAD_SCLK_CTRL1);
+
+struct clk_regmap aud_vad_mst_vad_lrclk_div =
+	AUD_MST_LRCLK_DIV(vad_mst_vad_lrclk, AUDIO2_MST_VAD_SCLK_CTRL0,
+			  vad_mst_vad_sclk_post_en);
+struct clk_regmap aud_vad_mst_vad_lrclk =
+	AUD_MST_LRCLK(vad_mst_vad_lrclk, AUDIO2_MST_VAD_SCLK_CTRL1);
+
+struct clk_regmap aud_vad_pdm_dclk_sel =
+	AUD_MST_MCLK_MUX(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+struct clk_regmap aud_vad_pdm_dclk_div =
+	AUD_MST_MCLK_DIV(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+struct clk_regmap aud_vad_pdm_dclk =
+	AUD_MST_MCLK_GATE(vad_pdm_dclk, AUDIO2_CLK_PDMIN_CTRL0);
+
+struct clk_regmap aud_vad_pdm_sysclk_sel =
+	AUD_MST_MCLK_MUX(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+struct clk_regmap aud_vad_pdm_sysclk_div =
+	AUD_MST_MCLK_DIV(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+struct clk_regmap aud_vad_pdm_sysclk =
+	AUD_MST_MCLK_GATE(vad_pdm_sysclk, AUDIO2_CLK_PDMIN_CTRL1);
+
+struct clk_regmap aud_vad_vad_clk_sel =
+	AUD_MST_MCLK_MUX(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+struct clk_regmap aud_vad_vad_clk_div =
+	AUD_MST_MCLK_DIV(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+struct clk_regmap aud_vad_vad_clk =
+	AUD_MST_MCLK_GATE(vad_vad_clk, AUDIO2_CLK_VAD_CTRL);
+
+static const struct clk_parent_data aud_vad_mst_sclk_pdata[] = {
+	{ .hw = &aud_vad_mst_vad_sclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ .fw_name = "slv_sclk0" },
+	{ .fw_name = "slv_sclk1" },
+	{ .fw_name = "slv_sclk2" },
+	{ .fw_name = "slv_sclk3" },
+	{ .fw_name = "slv_sclk4" },
+	{ .fw_name = "slv_sclk5" },
+	{ .fw_name = "slv_sclk6" },
+	{ .fw_name = "slv_sclk7" },
+	{ .fw_name = "slv_sclk8" },
+	{ .fw_name = "slv_sclk9" },
+	};
+
+static const struct clk_parent_data aud_vad_mst_lrclk_pdata[] = {
+	{ .hw = &aud_vad_mst_vad_lrclk.hw, .index = -1 },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ },
+	{ .fw_name = "slv_lrclk0" },
+	{ .fw_name = "slv_lrclk1" },
+	{ .fw_name = "slv_lrclk2" },
+	{ .fw_name = "slv_lrclk3" },
+	{ .fw_name = "slv_lrclk4" },
+	{ .fw_name = "slv_lrclk5" },
+	{ .fw_name = "slv_lrclk6" },
+	{ .fw_name = "slv_lrclk7" },
+	{ .fw_name = "slv_lrclk8" },
+	{ .fw_name = "slv_lrclk9" },
+};
+
+struct clk_regmap aud_vad_tdmin_vad_sclk_sel =
+	AUD_TDM_SCLK_MUX(vad_tdmin_vad_a_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL,
+			 aud_vad_mst_sclk_pdata);
+struct clk_regmap aud_vad_tdmin_vad_sclk_pre_en =
+	AUD_TDM_SCLK_PRE_EN(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_sclk_post_en =
+	AUD_TDM_SCLK_POST_EN(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_sclk =
+	AUD_TDM_SCLK(tdmin_vad_sclk, AUDIO2_CLK_TDMIN_VAD_CTRL);
+struct clk_regmap aud_vad_tdmin_vad_lrclk =
+	AUD_TDM_LRLCK(tdmin_vad_lrclk, AUDIO2_CLK_TDMIN_VAD_CTRL,
+		      aud_vad_mst_lrclk_pdata);
+
+static struct clk_hw *a1_audio_vad_clkc_hws[] = {
+	[AUD_VAD_CLKID_CLK81]		= &aud_vad_clk81.hw,
+	[AUD_VAD_CLKID_SYSCLK_A_DIV]	= &aud_vad_sysclk_a_div.hw,
+	[AUD_VAD_CLKID_SYSCLK_A]	= &aud_vad_sysclk_a.hw,
+	[AUD_VAD_CLKID_SYSCLK_B_DIV]	= &aud_vad_sysclk_b_div.hw,
+	[AUD_VAD_CLKID_SYSCLK_B]	= &aud_vad_sysclk_b.hw,
+	[AUD_VAD_CLKID_SYSCLK]		= &aud_vad_sysclk.hw,
+	[AUD_VAD_CLKID_DDR_ARB]		= &aud_vad_ddr_arb.hw,
+	[AUD_VAD_CLKID_PDM]		= &aud_vad_pdm.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD]	= &aud_vad_tdmin_vad.hw,
+	[AUD_VAD_CLKID_TODDR_VAD]	= &aud_vad_toddr_vad.hw,
+	[AUD_VAD_CLKID_TOVAD]		= &aud_vad_tovad.hw,
+	[AUD_VAD_CLKID_TOAUDIOTOP]	= &aud_vad_toaudiotop.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK_SEL] = &aud_vad_mst_vad_mclk_sel.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK_DIV] = &aud_vad_mst_vad_mclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_MCLK]	= &aud_vad_mst_vad_mclk.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_PRE_EN] = &aud_vad_mst_vad_sclk_pre_en.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_DIV] = &aud_vad_mst_vad_sclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK_POST_EN] = &aud_vad_mst_vad_sclk_post_en.hw,
+	[AUD_VAD_CLKID_MST_VAD_SCLK]	= &aud_vad_mst_vad_sclk.hw,
+	[AUD_VAD_CLKID_MST_VAD_LRCLK_DIV] = &aud_vad_mst_vad_lrclk_div.hw,
+	[AUD_VAD_CLKID_MST_VAD_LRCLK]	= &aud_vad_mst_vad_lrclk.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_SEL] = &aud_vad_tdmin_vad_sclk_sel.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_PRE_EN] = &aud_vad_tdmin_vad_sclk_pre_en.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK_POST_EN] = &aud_vad_tdmin_vad_sclk_post_en.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_SCLK]	= &aud_vad_tdmin_vad_sclk.hw,
+	[AUD_VAD_CLKID_TDMIN_VAD_LRCLK]	= &aud_vad_tdmin_vad_lrclk.hw,
+	[AUD_VAD_CLKID_PDM_DCLK_SEL]	= &aud_vad_pdm_dclk_sel.hw,
+	[AUD_VAD_CLKID_PDM_DCLK_DIV]	= &aud_vad_pdm_dclk_div.hw,
+	[AUD_VAD_CLKID_PDM_DCLK]	= &aud_vad_pdm_dclk.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK_SEL]	= &aud_vad_pdm_sysclk_sel.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK_DIV]	= &aud_vad_pdm_sysclk_div.hw,
+	[AUD_VAD_CLKID_PDM_SYSCLK]	= &aud_vad_pdm_sysclk.hw,
+	[AUD_VAD_CLKID_VAD_CLK_SEL]	= &aud_vad_vad_clk_sel.hw,
+	[AUD_VAD_CLKID_VAD_CLK_DIV]	= &aud_vad_vad_clk_div.hw,
+	[AUD_VAD_CLKID_VAD_CLK]		= &aud_vad_vad_clk.hw,
+};
+
+struct a1_audio_data {
+	struct meson_clk_hw_data hw_clks;
+	const char *rst_drvname;
+};
+
+static const struct regmap_config a1_audio_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int a1_audio_clkc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct a1_audio_data *data;
+	struct auxiliary_device *auxdev;
+	struct regmap *map;
+	void __iomem *base;
+	struct clk *clk;
+	unsigned int i;
+	int ret;
+
+	data = device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	clk = devm_clk_get_enabled(dev, "pclk");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	map = devm_regmap_init_mmio(dev, base, &a1_audio_regmap_cfg);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	ret = device_reset(dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < data->hw_clks.num; i++) {
+		struct clk_hw *hw = data->hw_clks.hws[i];
+		struct clk_regmap *clk_regmap = to_clk_regmap(hw);
+
+		if (!hw)
+			continue;
+
+		clk_regmap->map = map;
+	}
+
+	for (i = 0; i < data->hw_clks.num; i++) {
+		struct clk_hw *hw;
+
+		hw = data->hw_clks.hws[i];
+		if (!hw)
+			continue;
+
+		ret = devm_clk_hw_register(dev, hw);
+		if (ret)
+			return ret;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
+					  (void *)&data->hw_clks);
+	if (ret)
+		return ret;
+
+	auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
+						data->rst_drvname, NULL, 0);
+	if (!auxdev)
+		return -ENODEV;
+
+	return 0;
+}
+
+struct a1_audio_data a1_audio_clkc = {
+	.hw_clks = {
+		.hws = a1_audio_clkc_hws,
+		.num = ARRAY_SIZE(a1_audio_clkc_hws),
+	},
+	.rst_drvname = "rst-a1",
+};
+
+struct a1_audio_data a1_audio_vad_clkc = {
+	.hw_clks = {
+		.hws = a1_audio_vad_clkc_hws,
+		.num = ARRAY_SIZE(a1_audio_vad_clkc_hws),
+	},
+	.rst_drvname = "rst-a1-vad",
+};
+
+static const struct of_device_id a1_audio_clkc_match_table[] = {
+	{
+		.compatible = "amlogic,a1-audio-clkc",
+		.data = &a1_audio_clkc,
+	},
+	{
+		.compatible = "amlogic,a1-audio-vad-clkc",
+		.data = &a1_audio_vad_clkc,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, a1_audio_clkc_match_table);
+
+static struct platform_driver a1_audio_clkc_driver = {
+	.probe = a1_audio_clkc_probe,
+	.driver = {
+		.name = "a1-audio-clkc",
+		.of_match_table = a1_audio_clkc_match_table,
+	},
+};
+module_platform_driver(a1_audio_clkc_driver);
+
+MODULE_DESCRIPTION("Amlogic A1 Audio Clock driver");
+MODULE_AUTHOR("Jan Dakinevich <jan.dakinevich at salutedevices.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:15:56 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:15:56 +0300
Subject: [PATCH v2 0/4] ASoC: meson: g12a-toacodec: add support for A1 SoC
Message-ID: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>

This series adds support for A1 SoC family in g12a-toacodec driver. The main
change is that the driver now supports capture streams which are suitable for
ADC found on A1's internal audio codec.

Changes v1 [1] -> v2
 - detached from v1's series (patch 6, 7, 8, 9)
 - reworked the definition of bits

Links:
 [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/

Jan Dakinevich (4):
  ASoC: meson: codec-glue: add support for capture stream
  ASoC: meson: g12a-toacodec: drop the definition of bits
  ASoC: dt-bindings: meson: g12a-toacodec: add support for A1 SoC family
  ASoC: meson: g12a-toacodec: add support for A1 SoC family

 .../bindings/sound/amlogic,g12a-toacodec.yaml |   1 +
 .../dt-bindings/sound/meson-g12a-toacodec.h   |   5 +
 sound/soc/meson/g12a-toacodec.c               | 242 ++++++++++++++----
 sound/soc/meson/meson-codec-glue.c            | 174 ++++++++++---
 sound/soc/meson/meson-codec-glue.h            |  23 ++
 5 files changed, 358 insertions(+), 87 deletions(-)

-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:15:57 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:15:57 +0300
Subject: [PATCH v2 1/4] ASoC: meson: codec-glue: add support for capture stream
In-Reply-To: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181600.1322701-2-jan.dakinevich@salutedevices.com>

The glue saves stream's private data in front-end dai and then backend
dai can reach them searching backward from sink to source. For capture
stream everything left the same, but searching should be performed from
source to sink.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
Hope, I haven't misinterpreted the terminology and codec-glue's behavior
too much.
---
 sound/soc/meson/meson-codec-glue.c | 174 ++++++++++++++++++++++-------
 sound/soc/meson/meson-codec-glue.h |  23 ++++
 2 files changed, 158 insertions(+), 39 deletions(-)

diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c
index f8c5643f3cfe..da6d65e58d90 100644
--- a/sound/soc/meson/meson-codec-glue.c
+++ b/sound/soc/meson/meson-codec-glue.c
@@ -11,65 +11,94 @@
 #include "meson-codec-glue.h"
 
 static struct snd_soc_dapm_widget *
-meson_codec_glue_get_input(struct snd_soc_dapm_widget *w)
+meson_codec_glue_get_data_widget(struct snd_soc_dapm_widget *w, bool playback)
 {
 	struct snd_soc_dapm_path *p;
-	struct snd_soc_dapm_widget *in;
-
-	snd_soc_dapm_widget_for_each_source_path(w, p) {
+	struct snd_soc_dapm_widget *node;
+	enum snd_soc_dapm_type id = playback ? snd_soc_dapm_dai_in
+					     : snd_soc_dapm_dai_out;
+	enum snd_soc_dapm_direction dir = playback ? SND_SOC_DAPM_DIR_IN
+						   : SND_SOC_DAPM_DIR_OUT;
+	enum snd_soc_dapm_direction rdir = playback ? SND_SOC_DAPM_DIR_OUT
+						    : SND_SOC_DAPM_DIR_IN;
+
+	snd_soc_dapm_widget_for_each_path(w, rdir, p) {
 		if (!p->connect)
 			continue;
 
 		/* Check that we still are in the same component */
 		if (snd_soc_dapm_to_component(w->dapm) !=
-		    snd_soc_dapm_to_component(p->source->dapm))
+		    snd_soc_dapm_to_component(p->node[dir]->dapm))
 			continue;
 
-		if (p->source->id == snd_soc_dapm_dai_in)
-			return p->source;
+		if (p->node[dir]->id == id)
+			return p->node[dir];
 
-		in = meson_codec_glue_get_input(p->source);
-		if (in)
-			return in;
+		node = meson_codec_glue_get_data_widget(p->node[dir], playback);
+		if (node)
+			return node;
 	}
 
 	return NULL;
 }
 
-static void meson_codec_glue_input_set_data(struct snd_soc_dai *dai,
-					    struct meson_codec_glue_input *data)
+static void meson_codec_glue_set_data(struct snd_soc_dai *dai,
+				      struct meson_codec_glue_input *data,
+				      bool playback)
+{
+	int stream = playback ? SNDRV_PCM_STREAM_PLAYBACK
+			      : SNDRV_PCM_STREAM_CAPTURE;
+
+	snd_soc_dai_dma_data_set(dai, stream, data);
+}
+
+static struct meson_codec_glue_input *
+meson_codec_glue_get_data(struct snd_soc_dai *dai, bool playback)
 {
-	snd_soc_dai_dma_data_set_playback(dai, data);
+	int stream = playback ? SNDRV_PCM_STREAM_PLAYBACK
+			      : SNDRV_PCM_STREAM_CAPTURE;
+
+	return snd_soc_dai_dma_data_get(dai, stream);
 }
 
 struct meson_codec_glue_input *
 meson_codec_glue_input_get_data(struct snd_soc_dai *dai)
 {
-	return snd_soc_dai_dma_data_get_playback(dai);
+	return meson_codec_glue_get_data(dai, true);
 }
 EXPORT_SYMBOL_GPL(meson_codec_glue_input_get_data);
 
+struct meson_codec_glue_input *
+meson_codec_glue_capture_output_get_data(struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_get_data(dai, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_output_get_data);
+
 static struct meson_codec_glue_input *
-meson_codec_glue_output_get_input_data(struct snd_soc_dapm_widget *w)
+meson_codec_glue_data(struct snd_soc_dapm_widget *w, bool playback)
 {
-	struct snd_soc_dapm_widget *in =
-		meson_codec_glue_get_input(w);
+	struct snd_soc_dapm_widget *node =
+		meson_codec_glue_get_data_widget(w, playback);
 	struct snd_soc_dai *dai;
 
-	if (WARN_ON(!in))
+	if (WARN_ON(!node))
 		return NULL;
 
-	dai = in->priv;
+	dai = node->priv;
 
-	return meson_codec_glue_input_get_data(dai);
+	return meson_codec_glue_get_data(dai, playback);
 }
 
-int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
-				     struct snd_pcm_hw_params *params,
-				     struct snd_soc_dai *dai)
+static int meson_codec_glue_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params,
+				      struct snd_soc_dai *dai,
+				      bool playback)
 {
 	struct meson_codec_glue_input *data =
-		meson_codec_glue_input_get_data(dai);
+		meson_codec_glue_get_data(dai, playback);
+	struct snd_soc_pcm_stream *stream = playback ? &dai->driver->playback
+						     : &dai->driver->capture;
 
 	data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params));
 	data->params.rate_min = params_rate(params);
@@ -77,32 +106,64 @@ int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
 	data->params.formats = 1ULL << (__force int) params_format(params);
 	data->params.channels_min = params_channels(params);
 	data->params.channels_max = params_channels(params);
-	data->params.sig_bits = dai->driver->playback.sig_bits;
+	data->params.sig_bits = stream->sig_bits;
 
 	return 0;
 }
+
+int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_hw_params(substream, params, dai, true);
+}
 EXPORT_SYMBOL_GPL(meson_codec_glue_input_hw_params);
 
-int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai,
-				   unsigned int fmt)
+int meson_codec_glue_capture_output_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_hw_params(substream, params, dai, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_output_hw_params);
+
+static int meson_codec_glue_set_fmt(struct snd_soc_dai *dai,
+				    unsigned int fmt,
+				    bool playback)
 {
 	struct meson_codec_glue_input *data =
-		meson_codec_glue_input_get_data(dai);
+		meson_codec_glue_get_data(dai, playback);
 
 	/* Save the source stream format for the downstream link */
 	data->fmt = fmt;
 	return 0;
 }
+
+int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai,
+				   unsigned int fmt)
+{
+	return meson_codec_glue_set_fmt(dai, fmt, true);
+}
 EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt);
 
-int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
-				    struct snd_soc_dai *dai)
+int meson_codec_glue_capture_output_set_fmt(struct snd_soc_dai *dai,
+				    unsigned int fmt)
+{
+	return meson_codec_glue_set_fmt(dai, fmt, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_output_set_fmt);
+
+static int meson_codec_glue_startup(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai,
+				    bool playback)
 {
+	int stream = playback ? SNDRV_PCM_STREAM_CAPTURE
+			      : SNDRV_PCM_STREAM_PLAYBACK;
 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget_capture(dai);
-	struct meson_codec_glue_input *in_data = meson_codec_glue_output_get_input_data(w);
+	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, stream);
+	struct meson_codec_glue_input *data = meson_codec_glue_data(w, playback);
 
-	if (!in_data)
+	if (!data)
 		return -ENODEV;
 
 	if (WARN_ON(!rtd->dai_link->c2c_params)) {
@@ -111,14 +172,27 @@ int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
 	}
 
 	/* Replace link params with the input params */
-	rtd->dai_link->c2c_params = &in_data->params;
+	rtd->dai_link->c2c_params = &data->params;
 	rtd->dai_link->num_c2c_params = 1;
 
-	return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt);
+	return snd_soc_runtime_set_dai_fmt(rtd, data->fmt);
+}
+
+int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_startup(substream, dai, true);
 }
 EXPORT_SYMBOL_GPL(meson_codec_glue_output_startup);
 
-int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai)
+int meson_codec_glue_capture_input_startup(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_startup(substream, dai, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_input_startup);
+
+static int meson_codec_glue_dai_probe(struct snd_soc_dai *dai, bool playback)
 {
 	struct meson_codec_glue_input *data;
 
@@ -126,21 +200,43 @@ int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai)
 	if (!data)
 		return -ENOMEM;
 
-	meson_codec_glue_input_set_data(dai, data);
+	meson_codec_glue_set_data(dai, data, playback);
 	return 0;
 }
+
+int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_dai_probe(dai, true);
+}
 EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_probe);
 
-int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai)
+int meson_codec_glue_capture_output_dai_probe(struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_dai_probe(dai, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_output_dai_probe);
+
+static int meson_codec_glue_dai_remove(struct snd_soc_dai *dai, bool playback)
 {
 	struct meson_codec_glue_input *data =
-		meson_codec_glue_input_get_data(dai);
+		meson_codec_glue_get_data(dai, playback);
 
 	kfree(data);
 	return 0;
 }
+
+int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_dai_remove(dai, true);
+}
 EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_remove);
 
+int meson_codec_glue_capture_output_dai_remove(struct snd_soc_dai *dai)
+{
+	return meson_codec_glue_dai_remove(dai, false);
+}
+EXPORT_SYMBOL_GPL(meson_codec_glue_capture_output_dai_remove);
+
 MODULE_AUTHOR("Jerome Brunet <jbrunet at baylibre.com>");
 MODULE_DESCRIPTION("Amlogic Codec Glue Helpers");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/meson/meson-codec-glue.h b/sound/soc/meson/meson-codec-glue.h
index 07f99446c0c6..75d20aa75638 100644
--- a/sound/soc/meson/meson-codec-glue.h
+++ b/sound/soc/meson/meson-codec-glue.h
@@ -14,6 +14,10 @@ struct meson_codec_glue_input {
 	unsigned int fmt;
 };
 
+/*
+ * Playback stream
+ */
+
 /* Input helpers */
 struct meson_codec_glue_input *
 meson_codec_glue_input_get_data(struct snd_soc_dai *dai);
@@ -29,4 +33,23 @@ int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai);
 int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai);
 
+/*
+ * Capture stream
+ */
+
+/* Output helpers */
+struct meson_codec_glue_input *
+meson_codec_glue_capture_output_get_data(struct snd_soc_dai *dai);
+int meson_codec_glue_capture_output_hw_params(struct snd_pcm_substream *substream,
+					      struct snd_pcm_hw_params *params,
+					      struct snd_soc_dai *dai);
+int meson_codec_glue_capture_output_set_fmt(struct snd_soc_dai *dai,
+					    unsigned int fmt);
+int meson_codec_glue_capture_output_dai_probe(struct snd_soc_dai *dai);
+int meson_codec_glue_capture_output_dai_remove(struct snd_soc_dai *dai);
+
+/* Input helpers */
+int meson_codec_glue_capture_input_startup(struct snd_pcm_substream *substream,
+					   struct snd_soc_dai *dai);
+
 #endif /* _MESON_CODEC_GLUE_H */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:15:59 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:15:59 +0300
Subject: [PATCH v2 3/4] ASoC: dt-bindings: meson: g12a-toacodec: add support for A1 SoC family
In-Reply-To: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181600.1322701-4-jan.dakinevich@salutedevices.com>

Add support for "toacodec" audio component found A1 SoC family. On this
SoC the component supports capture streams, additional DAI ids are added
to configure this feature.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../devicetree/bindings/sound/amlogic,g12a-toacodec.yaml     | 1 +
 include/dt-bindings/sound/meson-g12a-toacodec.h              | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
index 23f82bb89750..c47604aa590f 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
@@ -26,6 +26,7 @@ properties:
       - items:
           - enum:
               - amlogic,sm1-toacodec
+              - amlogic,a1-toacodec
           - const: amlogic,g12a-toacodec
 
   reg:
diff --git a/include/dt-bindings/sound/meson-g12a-toacodec.h b/include/dt-bindings/sound/meson-g12a-toacodec.h
index 69d7a75592a2..f726e2c6064d 100644
--- a/include/dt-bindings/sound/meson-g12a-toacodec.h
+++ b/include/dt-bindings/sound/meson-g12a-toacodec.h
@@ -7,4 +7,9 @@
 #define TOACODEC_IN_C	2
 #define TOACODEC_OUT	3
 
+#define TOACODEC_CAPTURE_OUT_A	4
+#define TOACODEC_CAPTURE_OUT_B	5
+#define TOACODEC_CAPTURE_OUT_C	6
+#define TOACODEC_CAPTURE_IN	7
+
 #endif /* __DT_MESON_G12A_TOACODEC_H */
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:15:58 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:15:58 +0300
Subject: [PATCH v2 2/4] ASoC: meson: g12a-toacodec: drop the definition of bits
In-Reply-To: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181600.1322701-3-jan.dakinevich@salutedevices.com>

There are many of defines, but several of them are unused, other are
used once. It would easier to read if these values would occure in the
place of their usage.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
Also, there was an another attempt to rework bits' definition:

    https://lore.kernel.org/all/20240325235311.411920-1-jan.dakinevich at salutedevices.com/
---
 sound/soc/meson/g12a-toacodec.c | 45 ++++++++-------------------------
 1 file changed, 10 insertions(+), 35 deletions(-)

diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
index 531bb8707a3e..03bde8d8d192 100644
--- a/sound/soc/meson/g12a-toacodec.c
+++ b/sound/soc/meson/g12a-toacodec.c
@@ -20,26 +20,6 @@
 #define G12A_TOACODEC_DRV_NAME "g12a-toacodec"
 
 #define TOACODEC_CTRL0			0x0
-#define  CTRL0_ENABLE_SHIFT		31
-#define  CTRL0_DAT_SEL_SM1_MSB		19
-#define  CTRL0_DAT_SEL_SM1_LSB		18
-#define  CTRL0_DAT_SEL_MSB		15
-#define  CTRL0_DAT_SEL_LSB		14
-#define  CTRL0_LANE_SEL_SM1		16
-#define  CTRL0_LANE_SEL			12
-#define  CTRL0_LRCLK_SEL_SM1_MSB	14
-#define  CTRL0_LRCLK_SEL_SM1_LSB	12
-#define  CTRL0_LRCLK_SEL_MSB		9
-#define  CTRL0_LRCLK_SEL_LSB		8
-#define  CTRL0_LRCLK_INV_SM1		BIT(10)
-#define  CTRL0_BLK_CAP_INV_SM1		BIT(9)
-#define  CTRL0_BLK_CAP_INV		BIT(7)
-#define  CTRL0_BCLK_O_INV_SM1		BIT(8)
-#define  CTRL0_BCLK_O_INV		BIT(6)
-#define  CTRL0_BCLK_SEL_SM1_MSB		6
-#define  CTRL0_BCLK_SEL_MSB		5
-#define  CTRL0_BCLK_SEL_LSB		4
-#define  CTRL0_MCLK_SEL			GENMASK(2, 0)
 
 #define TOACODEC_OUT_CHMAX		2
 
@@ -69,6 +49,7 @@ static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol,
 	struct snd_soc_dapm_context *dapm =
 		snd_soc_dapm_kcontrol_dapm(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int mclk_sel = GENMASK(2, 0);
 	unsigned int mux, reg;
 
 	if (ucontrol->value.enumerated.item[0] >= e->items)
@@ -98,21 +79,18 @@ static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol,
 	 * source. For that, we will need regmap backed clock mux which
 	 * is a work in progress
 	 */
-	snd_soc_component_update_bits(component, e->reg,
-				      CTRL0_MCLK_SEL,
-				      FIELD_PREP(CTRL0_MCLK_SEL, mux));
+	snd_soc_component_update_bits(component, e->reg, mclk_sel,
+				      FIELD_PREP(mclk_sel, mux));
 
 	snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
 
 	return 1;
 }
 
-static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0,
-			    CTRL0_DAT_SEL_LSB,
+static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0, 14,
 			    g12a_toacodec_mux_texts);
 
-static SOC_ENUM_SINGLE_DECL(sm1_toacodec_mux_enum, TOACODEC_CTRL0,
-			    CTRL0_DAT_SEL_SM1_LSB,
+static SOC_ENUM_SINGLE_DECL(sm1_toacodec_mux_enum, TOACODEC_CTRL0, 18,
 			    g12a_toacodec_mux_texts);
 
 static const struct snd_kcontrol_new g12a_toacodec_mux =
@@ -126,8 +104,7 @@ static const struct snd_kcontrol_new sm1_toacodec_mux =
 			  g12a_toacodec_mux_put_enum);
 
 static const struct snd_kcontrol_new g12a_toacodec_out_enable =
-	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
-				    CTRL0_ENABLE_SHIFT, 1, 0);
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0, 31, 1, 0);
 
 static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
 	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
@@ -209,15 +186,13 @@ static struct snd_soc_dai_driver g12a_toacodec_dai_drv[] = {
 static int g12a_toacodec_component_probe(struct snd_soc_component *c)
 {
 	/* Initialize the static clock parameters */
-	return snd_soc_component_write(c, TOACODEC_CTRL0,
-				       CTRL0_BLK_CAP_INV);
+	return snd_soc_component_write(c, TOACODEC_CTRL0, BIT(7));
 }
 
 static int sm1_toacodec_component_probe(struct snd_soc_component *c)
 {
 	/* Initialize the static clock parameters */
-	return snd_soc_component_write(c, TOACODEC_CTRL0,
-				       CTRL0_BLK_CAP_INV_SM1);
+	return snd_soc_component_write(c, TOACODEC_CTRL0, BIT(9));
 }
 
 static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
@@ -229,11 +204,11 @@ static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
 };
 
 static const struct snd_kcontrol_new g12a_toacodec_controls[] = {
-	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL, 3, 0),
+	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, 12, 3, 0),
 };
 
 static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
-	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
+	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, 16, 3, 0),
 };
 
 static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:16:00 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:16:00 +0300
Subject: [PATCH v2 4/4] ASoC: meson: g12a-toacodec: add support for A1 SoC family
In-Reply-To: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181600.1322701-5-jan.dakinevich@salutedevices.com>

Internal codec on A1 SoC has ADC and this commit adds support for
capturing from it.

Also, regmap now uses caching for all platforms. Values that are written
to toacodec's register on A1 SoC can not be read back, that breaks
regmap_update_bits() functionality. Let's hope the caching will not
break anything on other platforms. Since .max_register now is explicitly
equal to 0, .reg_stride is also removed.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 sound/soc/meson/g12a-toacodec.c | 197 +++++++++++++++++++++++++++++---
 1 file changed, 184 insertions(+), 13 deletions(-)

diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
index 03bde8d8d192..431fcd364001 100644
--- a/sound/soc/meson/g12a-toacodec.c
+++ b/sound/soc/meson/g12a-toacodec.c
@@ -31,6 +31,8 @@ struct g12a_toacodec {
 
 struct g12a_toacodec_match_data {
 	const struct snd_soc_component_driver *component_drv;
+	struct snd_soc_dai_driver *dai_drv;
+	int num_dai_drv;
 	struct reg_field field_dat_sel;
 	struct reg_field field_lrclk_sel;
 	struct reg_field field_bclk_sel;
@@ -40,6 +42,10 @@ static const char * const g12a_toacodec_mux_texts[] = {
 	"I2S A", "I2S B", "I2S C",
 };
 
+static const char * const a1_toacodec_mux_texts[] = {
+	"I2S A", "I2S B",
+};
+
 static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
@@ -93,8 +99,11 @@ static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0, 14,
 static SOC_ENUM_SINGLE_DECL(sm1_toacodec_mux_enum, TOACODEC_CTRL0, 18,
 			    g12a_toacodec_mux_texts);
 
-static const struct snd_kcontrol_new g12a_toacodec_mux =
-	SOC_DAPM_ENUM_EXT("Source", g12a_toacodec_mux_enum,
+static SOC_ENUM_SINGLE_DECL(a1_toacodec_mux_enum, TOACODEC_CTRL0, 19,
+			    a1_toacodec_mux_texts);
+
+static const struct snd_kcontrol_new a1_toacodec_mux =
+	SOC_DAPM_ENUM_EXT("Source", a1_toacodec_mux_enum,
 			  snd_soc_dapm_get_enum_double,
 			  g12a_toacodec_mux_put_enum);
 
@@ -103,9 +112,20 @@ static const struct snd_kcontrol_new sm1_toacodec_mux =
 			  snd_soc_dapm_get_enum_double,
 			  g12a_toacodec_mux_put_enum);
 
+static const struct snd_kcontrol_new g12a_toacodec_mux =
+	SOC_DAPM_ENUM_EXT("Source", g12a_toacodec_mux_enum,
+			  snd_soc_dapm_get_enum_double,
+			  g12a_toacodec_mux_put_enum);
+
 static const struct snd_kcontrol_new g12a_toacodec_out_enable =
 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0, 31, 1, 0);
 
+/* Don't use AUTODISABLE unlike G12A. On A1 it causes noise after playback
+ * is stopped.
+ */
+static const struct snd_kcontrol_new a1_toacodec_enable =
+	SOC_DAPM_SINGLE("Switch", TOACODEC_CTRL0, 31, 1, 0);
+
 static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
 	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
 			 &g12a_toacodec_mux),
@@ -120,19 +140,34 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
 			    &g12a_toacodec_out_enable),
 };
 
-static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
-					 struct snd_pcm_hw_params *params,
-					 struct snd_soc_dai *dai)
+static const struct snd_soc_dapm_widget a1_toacodec_widgets[] = {
+	SND_SOC_DAPM_SWITCH("EN", SND_SOC_NOPM, 0, 0,
+			    &a1_toacodec_enable),
+	SND_SOC_DAPM_MUX("Playback SRC", SND_SOC_NOPM, 0, 0,
+			 &a1_toacodec_mux),
+	SND_SOC_DAPM_MUX("Capture SRC A", SND_SOC_NOPM, 0, 0,
+			 &a1_toacodec_mux),
+	SND_SOC_DAPM_MUX("Capture SRC B", SND_SOC_NOPM, 0, 0,
+			 &a1_toacodec_mux),
+};
+
+static int g12a_toacodec_hw_params(struct snd_pcm_substream *substream,
+				   struct snd_pcm_hw_params *params,
+				   struct snd_soc_dai *dai,
+				   bool playback)
 {
 	struct meson_codec_glue_input *data;
 	int ret;
 
-	ret = meson_codec_glue_input_hw_params(substream, params, dai);
+	ret = playback ? meson_codec_glue_input_hw_params(substream, params, dai)
+		       : meson_codec_glue_capture_output_hw_params(substream,
+								   params, dai);
 	if (ret)
 		return ret;
 
 	/* The glue will provide 1 lane out of the 4 to the output */
-	data = meson_codec_glue_input_get_data(dai);
+	data = playback ? meson_codec_glue_input_get_data(dai)
+			: meson_codec_glue_capture_output_get_data(dai);
 	data->params.channels_min = min_t(unsigned int, TOACODEC_OUT_CHMAX,
 					data->params.channels_min);
 	data->params.channels_max = min_t(unsigned int, TOACODEC_OUT_CHMAX,
@@ -141,6 +176,21 @@ static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
+					 struct snd_pcm_hw_params *params,
+					 struct snd_soc_dai *dai)
+{
+	return g12a_toacodec_hw_params(substream, params, dai, true);
+}
+
+static int
+g12a_toacodec_capture_output_hw_params(struct snd_pcm_substream *substream,
+				       struct snd_pcm_hw_params *params,
+				       struct snd_soc_dai *dai)
+{
+	return g12a_toacodec_hw_params(substream, params, dai, false);
+}
+
 static const struct snd_soc_dai_ops g12a_toacodec_input_ops = {
 	.probe		= meson_codec_glue_input_dai_probe,
 	.remove		= meson_codec_glue_input_dai_remove,
@@ -152,6 +202,17 @@ static const struct snd_soc_dai_ops g12a_toacodec_output_ops = {
 	.startup	= meson_codec_glue_output_startup,
 };
 
+static const struct snd_soc_dai_ops g12a_toacodec_capture_output_ops = {
+	.probe		= meson_codec_glue_capture_output_dai_probe,
+	.remove		= meson_codec_glue_capture_output_dai_remove,
+	.hw_params	= g12a_toacodec_capture_output_hw_params,
+	.set_fmt	= meson_codec_glue_capture_output_set_fmt,
+};
+
+static const struct snd_soc_dai_ops g12a_toacodec_capture_input_ops = {
+	.startup	= meson_codec_glue_capture_input_startup,
+};
+
 #define TOACODEC_STREAM(xname, xsuffix, xchmax)			\
 {								\
 	.stream_name	= xname " " xsuffix,			\
@@ -176,6 +237,20 @@ static const struct snd_soc_dai_ops g12a_toacodec_output_ops = {
 	.ops = &g12a_toacodec_output_ops,				\
 }
 
+#define TOACODEC_CAPTURE_INPUT(xname, xid) {				\
+	.name = xname,							\
+	.id = (xid),							\
+	.playback = TOACODEC_STREAM(xname, "Playback", 2),		\
+	.ops = &g12a_toacodec_capture_input_ops,			\
+}
+
+#define TOACODEC_CAPTURE_OUTPUT(xname, xid) {				\
+	.name = xname,							\
+	.id = (xid),							\
+	.capture = TOACODEC_STREAM(xname, "Capture", 2),		\
+	.ops = &g12a_toacodec_capture_output_ops,			\
+}
+
 static struct snd_soc_dai_driver g12a_toacodec_dai_drv[] = {
 	TOACODEC_INPUT("IN A", TOACODEC_IN_A),
 	TOACODEC_INPUT("IN B", TOACODEC_IN_B),
@@ -183,6 +258,16 @@ static struct snd_soc_dai_driver g12a_toacodec_dai_drv[] = {
 	TOACODEC_OUTPUT("OUT", TOACODEC_OUT),
 };
 
+static struct snd_soc_dai_driver a1_toacodec_dai_drv[] = {
+	TOACODEC_INPUT("IN A", TOACODEC_IN_A),
+	TOACODEC_INPUT("IN B", TOACODEC_IN_B),
+	TOACODEC_OUTPUT("OUT", TOACODEC_OUT),
+
+	TOACODEC_CAPTURE_OUTPUT("OUT A", TOACODEC_CAPTURE_OUT_A),
+	TOACODEC_CAPTURE_OUTPUT("OUT B", TOACODEC_CAPTURE_OUT_B),
+	TOACODEC_CAPTURE_INPUT("IN", TOACODEC_CAPTURE_IN),
+};
+
 static int g12a_toacodec_component_probe(struct snd_soc_component *c)
 {
 	/* Initialize the static clock parameters */
@@ -195,6 +280,31 @@ static int sm1_toacodec_component_probe(struct snd_soc_component *c)
 	return snd_soc_component_write(c, TOACODEC_CTRL0, BIT(9));
 }
 
+static int a1_toacodec_component_probe(struct snd_soc_component *c)
+{
+	/* Initialize the static clock parameters */
+	return snd_soc_component_write(c, TOACODEC_CTRL0, BIT(9));
+}
+
+static int a1_toacodec_of_xlate_dai_name(struct snd_soc_component *component,
+					 const struct of_phandle_args *args,
+					 const char **dai_name)
+{
+	struct snd_soc_dai *dai;
+
+	if (args->args_count != 1)
+		return -EINVAL;
+
+	for_each_component_dais(component, dai) {
+		if (dai->id == args->args[0]) {
+			*dai_name = dai->driver->name;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
 	{ "SRC", "I2S A", "IN A Playback" },
 	{ "SRC", "I2S B", "IN B Playback" },
@@ -203,6 +313,19 @@ static const struct snd_soc_dapm_route g12a_toacodec_routes[] = {
 	{ "OUT Capture", NULL, "OUT EN" },
 };
 
+static const struct snd_soc_dapm_route a1_toacodec_routes[] = {
+	{ "Playback SRC", "I2S A", "IN A Playback" },
+	{ "Playback SRC", "I2S B", "IN B Playback" },
+	{ "EN", "Switch", "Playback SRC" },
+	{ "OUT Capture", NULL, "Playback SRC" },
+
+	{ "EN", "Switch", "IN Playback" },
+	{ "Capture SRC A", "I2S A", "EN" },
+	{ "Capture SRC B", "I2S B", "EN" },
+	{ "OUT A Capture", NULL, "Capture SRC A" },
+	{ "OUT B Capture", NULL, "Capture SRC B" },
+};
+
 static const struct snd_kcontrol_new g12a_toacodec_controls[] = {
 	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, 12, 3, 0),
 };
@@ -211,6 +334,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
 	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, 16, 3, 0),
 };
 
+static const struct snd_kcontrol_new a1_toacodec_controls[] = {
+	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, 16, 3, 0),
+};
+
 static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
 	.probe			= g12a_toacodec_component_probe,
 	.controls		= g12a_toacodec_controls,
@@ -233,14 +360,43 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
 	.endianness		= 1,
 };
 
+static const struct snd_soc_component_driver a1_toacodec_component_drv = {
+	.probe			= a1_toacodec_component_probe,
+	.of_xlate_dai_name	= a1_toacodec_of_xlate_dai_name,
+	.controls		= a1_toacodec_controls,
+	.num_controls		= ARRAY_SIZE(a1_toacodec_controls),
+	.dapm_widgets		= a1_toacodec_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(a1_toacodec_widgets),
+	.dapm_routes		= a1_toacodec_routes,
+	.num_dapm_routes	= ARRAY_SIZE(a1_toacodec_routes),
+	.endianness		= 1,
+};
+
+static const struct reg_default g12a_toacodec_reg_default[] = {
+	{ TOACODEC_CTRL0, 0x0 },
+};
+
+static bool g12_toacodec_readable_reg(struct device *dev, unsigned int reg)
+{
+	/* There are no readable registers */
+	return false;
+}
+
 static const struct regmap_config g12a_toacodec_regmap_cfg = {
-	.reg_bits	= 32,
-	.val_bits	= 32,
-	.reg_stride	= 4,
+	.reg_bits		= 32,
+	.val_bits		= 32,
+	.max_register		= TOACODEC_CTRL0,
+	.max_register_is_0	= true,
+	.cache_type		= REGCACHE_FLAT,
+	.reg_defaults		= g12a_toacodec_reg_default,
+	.num_reg_defaults	= ARRAY_SIZE(g12a_toacodec_reg_default),
+	.readable_reg		= g12_toacodec_readable_reg,
 };
 
 static const struct g12a_toacodec_match_data g12a_toacodec_match_data = {
 	.component_drv	= &g12a_toacodec_component_drv,
+	.dai_drv	= g12a_toacodec_dai_drv,
+	.num_dai_drv	= ARRAY_SIZE(g12a_toacodec_dai_drv),
 	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 14, 15),
 	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 8, 9),
 	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 5),
@@ -248,11 +404,22 @@ static const struct g12a_toacodec_match_data g12a_toacodec_match_data = {
 
 static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
 	.component_drv	= &sm1_toacodec_component_drv,
+	.dai_drv	= g12a_toacodec_dai_drv,
+	.num_dai_drv	= ARRAY_SIZE(g12a_toacodec_dai_drv),
 	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 18, 19),
 	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
 	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
 };
 
+static const struct g12a_toacodec_match_data a1_toacodec_match_data = {
+	.component_drv	= &a1_toacodec_component_drv,
+	.dai_drv	= a1_toacodec_dai_drv,
+	.num_dai_drv	= ARRAY_SIZE(a1_toacodec_dai_drv),
+	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 19, 19),
+	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
+	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
+};
+
 static const struct of_device_id g12a_toacodec_of_match[] = {
 	{
 		.compatible = "amlogic,g12a-toacodec",
@@ -262,6 +429,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
 		.compatible = "amlogic,sm1-toacodec",
 		.data = &sm1_toacodec_match_data,
 	},
+	{
+		.compatible = "amlogic,a1-toacodec",
+		.data = &a1_toacodec_match_data,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);
@@ -314,9 +485,9 @@ static int g12a_toacodec_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->field_bclk_sel))
 		return PTR_ERR(priv->field_bclk_sel);
 
-	return devm_snd_soc_register_component(dev,
-			data->component_drv, g12a_toacodec_dai_drv,
-			ARRAY_SIZE(g12a_toacodec_dai_drv));
+	return devm_snd_soc_register_component(dev, data->component_drv,
+					       data->dai_drv,
+					       data->num_dai_drv);
 }
 
 static struct platform_driver g12a_toacodec_pdrv = {
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:16:27 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:16:27 +0300
Subject: [PATCH v2 0/3] ASoC: meson: t9015: add support for A1 SoC family
Message-ID: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>

This series adds support for internal audio codec found on A1 SoC family
extending existing t9015 driver.

Changes v1 [1] -> v2
 - detached from v1's series (patches 10, 11, 12)
 - configuration of linein/lineout/micbias is moved to device tree

Links:
 [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/

Jan Dakinevich (3):
  ASoC: meson: t9015: prepare to adding new platforms
  ASoC: dt-bindings: meson: t9015: add support for A1 SoC family
  ASoC: meson: t9015: add support for A1 SoC family

 .../bindings/sound/amlogic,t9015.yaml         |  69 +++-
 sound/soc/meson/t9015.c                       | 379 +++++++++++++++++-
 2 files changed, 423 insertions(+), 25 deletions(-)

-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:16:28 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:16:28 +0300
Subject: [PATCH v2 1/3] ASoC: meson: t9015: prepare to adding new platforms
In-Reply-To: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
References: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181630.1322745-2-jan.dakinevich@salutedevices.com>

Move platform specific code to make the reading of upcoming commit
easier.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 sound/soc/meson/t9015.c | 71 ++++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 23 deletions(-)

diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c
index a80e9c9d6288..919a2413038d 100644
--- a/sound/soc/meson/t9015.c
+++ b/sound/soc/meson/t9015.c
@@ -51,6 +51,12 @@ struct t9015 {
 	struct regulator *avdd;
 };
 
+struct t9015_match_data {
+	const struct snd_soc_component_driver *component_drv;
+	struct snd_soc_dai_driver *dai_drv;
+	unsigned int max_register;
+};
+
 static int t9015_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
@@ -112,6 +118,11 @@ static SOC_ENUM_SINGLE_DECL(dacl_in_enum, BLOCK_EN, DACL_SRC, dacl_in_txt);
 static const char * const mono_txt[] = { "Stereo", "Mono"};
 static SOC_ENUM_SINGLE_DECL(mono_enum, VOL_CTRL1, DAC_MONO, mono_txt);
 
+static const struct snd_kcontrol_new t9015_right_dac_mux =
+	SOC_DAPM_ENUM("Right DAC Source", dacr_in_enum);
+static const struct snd_kcontrol_new t9015_left_dac_mux =
+	SOC_DAPM_ENUM("Left DAC Source", dacl_in_enum);
+
 static const struct snd_kcontrol_new t9015_snd_controls[] = {
 	/* Volume Controls */
 	SOC_ENUM("Playback Channel Mode", mono_enum),
@@ -126,11 +137,6 @@ static const struct snd_kcontrol_new t9015_snd_controls[] = {
 	SOC_SINGLE("Unmute Ramp Switch", VOL_CTRL1, UNMUTE_MODE, 1, 0),
 };
 
-static const struct snd_kcontrol_new t9015_right_dac_mux =
-	SOC_DAPM_ENUM("Right DAC Source", dacr_in_enum);
-static const struct snd_kcontrol_new t9015_left_dac_mux =
-	SOC_DAPM_ENUM("Left DAC Source", dacl_in_enum);
-
 static const struct snd_soc_dapm_widget t9015_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN("Right IN", NULL, 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("Left IN", NULL, 0, SND_SOC_NOPM, 0, 0),
@@ -223,7 +229,20 @@ static int t9015_set_bias_level(struct snd_soc_component *component,
 	return 0;
 }
 
+static int t9015_component_probe(struct snd_soc_component *component)
+{
+	/*
+	 * Initialize output polarity:
+	 * ATM the output polarity is fixed but in the future it might useful
+	 * to add DT property to set this depending on the platform needs
+	 */
+	snd_soc_component_write(component, LINEOUT_CFG, 0x1111);
+
+	return 0;
+}
+
 static const struct snd_soc_component_driver t9015_codec_driver = {
+	.probe			= t9015_component_probe,
 	.set_bias_level		= t9015_set_bias_level,
 	.controls		= t9015_snd_controls,
 	.num_controls		= ARRAY_SIZE(t9015_snd_controls),
@@ -235,22 +254,25 @@ static const struct snd_soc_component_driver t9015_codec_driver = {
 	.endianness		= 1,
 };
 
-static const struct regmap_config t9015_regmap_config = {
-	.reg_bits		= 32,
-	.reg_stride		= 4,
-	.val_bits		= 32,
-	.max_register		= POWER_CFG,
-};
-
 static int t9015_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct t9015_match_data *data;
 	struct t9015 *priv;
 	void __iomem *regs;
+	struct regmap_config config = {
+		.reg_bits = 32,
+		.reg_stride = 4,
+		.val_bits = 32,
+	};
 	struct regmap *regmap;
 	struct clk *pclk;
 	int ret;
 
+	data = device_get_match_data(dev);
+	if (!data)
+		dev_err_probe(dev, -ENODEV, "failed to match device\n");
+
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -276,25 +298,28 @@ static int t9015_probe(struct platform_device *pdev)
 		return PTR_ERR(regs);
 	}
 
-	regmap = devm_regmap_init_mmio(dev, regs, &t9015_regmap_config);
+	config.max_register = data->max_register;
+	regmap = devm_regmap_init_mmio(dev, regs, &config);
 	if (IS_ERR(regmap)) {
 		dev_err(dev, "regmap init failed\n");
 		return PTR_ERR(regmap);
 	}
 
-	/*
-	 * Initialize output polarity:
-	 * ATM the output polarity is fixed but in the future it might useful
-	 * to add DT property to set this depending on the platform needs
-	 */
-	regmap_write(regmap, LINEOUT_CFG, 0x1111);
-
-	return devm_snd_soc_register_component(dev, &t9015_codec_driver,
-					       &t9015_dai, 1);
+	return devm_snd_soc_register_component(dev, data->component_drv,
+					       data->dai_drv, 1);
 }
 
+static const struct t9015_match_data t9015_match_data = {
+	.component_drv = &t9015_codec_driver,
+	.dai_drv = &t9015_dai,
+	.max_register = POWER_CFG,
+};
+
 static const struct of_device_id t9015_ids[] __maybe_unused = {
-	{ .compatible = "amlogic,t9015", },
+	{
+		.compatible = "amlogic,t9015",
+		.data = &t9015_match_data,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, t9015_ids);
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:16:29 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:16:29 +0300
Subject: [PATCH v2 2/3] ASoC: dt-bindings: meson: t9015: add support for A1 SoC family
In-Reply-To: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
References: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181630.1322745-3-jan.dakinevich@salutedevices.com>

Add support for internal audio codec found A1 SoC family. On this SoC
the component supports capturing from ADC and has specific configuration
of input/output lines.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../bindings/sound/amlogic,t9015.yaml         | 69 +++++++++++++++++--
 1 file changed, 65 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
index 5f5cccdbeb34..962795470601 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
@@ -9,9 +9,6 @@ title: Amlogic T9015 Internal Audio DAC
 maintainers:
   - Jerome Brunet <jbrunet at baylibre.com>
 
-allOf:
-  - $ref: dai-common.yaml#
-
 properties:
   $nodename:
     pattern: "^audio-controller at .*"
@@ -21,7 +18,9 @@ properties:
 
   compatible:
     items:
-      - const: amlogic,t9015
+      - enum:
+          - amlogic,t9015
+          - amlogic,t9015-a1
 
   clocks:
     items:
@@ -43,6 +42,17 @@ properties:
 
   sound-name-prefix: true
 
+  lineout-left:
+    $ref: /schemas/types.yaml#/definitions/string
+  lineout-right:
+    $ref: /schemas/types.yaml#/definitions/string
+  linein-left:
+    $ref: /schemas/types.yaml#/definitions/string
+  linein-right:
+    $ref: /schemas/types.yaml#/definitions/string
+  micbias:
+    $ref: /schemas/types.yaml#/definitions/string
+
 required:
   - "#sound-dai-cells"
   - compatible
@@ -52,6 +62,57 @@ required:
   - resets
   - AVDD-supply
 
+
+allOf:
+  - $ref: dai-common.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: amlogic,t9015-a1
+    then:
+      properties:
+        lineout-left:
+          items:
+            - enum:
+                - none
+                - right
+                - left-inverted
+        lineout-right:
+          items:
+            - enum:
+                - none
+                - left
+                - right-inverted
+        linein-left:
+          items:
+            - enum:
+                - none
+                - differential
+                - positive
+                - negative
+        linein-right:
+          items:
+            - enum:
+                - none
+                - differential
+                - positive
+                - negative
+        micbias:
+          items:
+            - enum:
+                - 2.0V
+                - 2.1V
+                - 2.3V
+                - 2.5V
+                - 2.8V
+    else:
+      lineout-left: false
+      lineout-right: false
+      linein-left: false
+      linein-right: false
+      micbias: false
+
 additionalProperties: false
 
 examples:
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:16:30 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:16:30 +0300
Subject: [PATCH v2 3/3] ASoC: meson: t9015: add support for A1 SoC family
In-Reply-To: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
References: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309181630.1322745-4-jan.dakinevich@salutedevices.com>

A1's internal codec is very close to t9015. The main difference, that it
has ADC. This commit introduces support for capturing from it.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 sound/soc/meson/t9015.c | 312 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 312 insertions(+)

diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c
index 919a2413038d..fe3e62d94fa3 100644
--- a/sound/soc/meson/t9015.c
+++ b/sound/soc/meson/t9015.c
@@ -19,16 +19,33 @@
 #define  LOLP_EN	3
 #define  DACR_EN	4
 #define  DACL_EN	5
+#define  ADCR_EN	6
+#define  ADCL_EN	7
+#define  PGAR_ZCD_EN	8
+#define  PGAL_ZCD_EN	9
+#define  PGAR_EN	10
+#define  PGAL_EN	11
+#define  ADCR_INV	16
+#define  ADCL_INV	17
+#define  ADCR_SRC	18
+#define  ADCL_SRC	19
 #define  DACR_INV	20
 #define  DACL_INV	21
 #define  DACR_SRC	22
 #define  DACL_SRC	23
+#define  ADC_DEM_EN	26
+#define  ADC_FILTER_MODE 28
+#define  ADC_FILTER_EN	29
 #define  REFP_BUF_EN	BIT(12)
 #define  BIAS_CURRENT_EN BIT(13)
 #define  VMID_GEN_FAST	BIT(14)
 #define  VMID_GEN_EN	BIT(15)
 #define  I2S_MODE	BIT(30)
 #define VOL_CTRL0	0x04
+#define  PGAR_VC	0
+#define  PGAL_VC	8
+#define  ADCR_VC	16
+#define  ADCL_VC	24
 #define  GAIN_H		31
 #define  GAIN_L		23
 #define VOL_CTRL1	0x08
@@ -46,6 +63,28 @@
 #define  LOLN_POL	8
 #define  LOLP_POL	12
 #define POWER_CFG	0x10
+#define LINEIN_CFG	0x14
+#define  MICBIAS_LEVEL	0
+#define  MICBIAS_EN	3
+#define  PGAR_CTVMN	8
+#define  PGAR_CTVMP	9
+#define  PGAL_CTVMN	10
+#define  PGAL_CTVMP	11
+#define  PGAR_CTVIN	12
+#define  PGAR_CTVIP	13
+#define  PGAL_CTVIN	14
+#define  PGAL_CTVIP	15
+
+#define PGAR_MASK	(BIT(PGAR_CTVMP) | BIT(PGAR_CTVMN) | \
+			 BIT(PGAR_CTVIP) | BIT(PGAR_CTVIN))
+#define PGAR_DIFF	(BIT(PGAR_CTVIP) | BIT(PGAR_CTVIN))
+#define PGAR_POSITIVE	(BIT(PGAR_CTVIP) | BIT(PGAR_CTVMN))
+#define PGAR_NEGATIVE	(BIT(PGAR_CTVIN) | BIT(PGAR_CTVMP))
+#define PGAL_MASK	(BIT(PGAL_CTVMP) | BIT(PGAL_CTVMN) | \
+			 BIT(PGAL_CTVIP) | BIT(PGAL_CTVIN))
+#define PGAL_DIFF	(BIT(PGAL_CTVIP) | BIT(PGAL_CTVIN))
+#define PGAL_POSITIVE	(BIT(PGAL_CTVIP) | BIT(PGAL_CTVMN))
+#define PGAL_NEGATIVE	(BIT(PGAL_CTVIN) | BIT(PGAL_CTVMP))
 
 struct t9015 {
 	struct regulator *avdd;
@@ -103,6 +142,31 @@ static struct snd_soc_dai_driver t9015_dai = {
 	.ops = &t9015_dai_ops,
 };
 
+static struct snd_soc_dai_driver a1_t9015_dai = {
+	.name = "t9015-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = (SNDRV_PCM_FMTBIT_S8 |
+			    SNDRV_PCM_FMTBIT_S16_LE |
+			    SNDRV_PCM_FMTBIT_S20_LE |
+			    SNDRV_PCM_FMTBIT_S24_LE),
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = (SNDRV_PCM_FMTBIT_S8 |
+			    SNDRV_PCM_FMTBIT_S16_LE |
+			    SNDRV_PCM_FMTBIT_S20_LE |
+			    SNDRV_PCM_FMTBIT_S24_LE),
+	},
+	.ops = &t9015_dai_ops,
+};
+
 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -9525, 0);
 
 static const char * const ramp_rate_txt[] = { "Fast", "Slow" };
@@ -179,6 +243,103 @@ static const struct snd_soc_dapm_route t9015_dapm_routes[] = {
 	{ "LOLP", NULL, "Left+ Driver",  },
 };
 
+static const DECLARE_TLV_DB_MINMAX_MUTE(a1_adc_vol_tlv, -29625, 0);
+static const DECLARE_TLV_DB_MINMAX_MUTE(a1_adc_pga_vol_tlv, -1200, 0);
+
+static const char * const a1_adc_right_txt[] = { "Right", "Left" };
+static SOC_ENUM_SINGLE_DECL(a1_adc_right, BLOCK_EN, ADCR_SRC, a1_adc_right_txt);
+
+static const char * const a1_adc_left_txt[] = { "Left", "Right" };
+static SOC_ENUM_SINGLE_DECL(a1_adc_left, BLOCK_EN, ADCL_SRC, a1_adc_left_txt);
+
+static const struct snd_kcontrol_new a1_adc_right_mux =
+	SOC_DAPM_ENUM("ADC Right Source", a1_adc_right);
+static const struct snd_kcontrol_new a1_adc_left_mux =
+	SOC_DAPM_ENUM("ADC Left Source", a1_adc_left);
+
+static const char * const a1_adc_filter_mode_txt[] = { "Voice", "HiFi"};
+static SOC_ENUM_SINGLE_DECL(a1_adc_filter_mode, BLOCK_EN, ADC_FILTER_MODE,
+			    a1_adc_filter_mode_txt);
+
+static const struct snd_kcontrol_new a1_t9015_snd_controls[] = {
+	/* Volume Controls */
+	SOC_ENUM("Playback Channel Mode", mono_enum),
+	SOC_SINGLE("Playback Switch", VOL_CTRL1, DAC_SOFT_MUTE, 1, 1),
+	SOC_DOUBLE_TLV("Playback Volume", VOL_CTRL1, DACL_VC, DACR_VC,
+		       0xff, 0, dac_vol_tlv),
+
+	/* Ramp Controls */
+	SOC_ENUM("Ramp Rate", ramp_rate_enum),
+	SOC_SINGLE("Volume Ramp Switch", VOL_CTRL1, VC_RAMP_MODE, 1, 0),
+	SOC_SINGLE("Mute Ramp Switch", VOL_CTRL1, MUTE_MODE, 1, 0),
+	SOC_SINGLE("Unmute Ramp Switch", VOL_CTRL1, UNMUTE_MODE, 1, 0),
+
+	/* ADC Controls */
+	SOC_DOUBLE_TLV("ADC Volume", VOL_CTRL0, ADCL_VC, ADCR_VC,
+		       0x7f, 0, a1_adc_vol_tlv),
+	SOC_SINGLE("ADC Filter Switch", BLOCK_EN, ADC_FILTER_EN, 1, 0),
+	SOC_ENUM("ADC Filter Mode", a1_adc_filter_mode),
+	SOC_SINGLE("ADC DEM Switch", BLOCK_EN, ADC_DEM_EN, 1, 0),
+	SOC_DOUBLE_TLV("ADC PGA Volume", VOL_CTRL0, PGAR_VC, PGAL_VC,
+		       0x1f, 0, a1_adc_pga_vol_tlv),
+	SOC_DOUBLE("ADC PGA Zero Cross-detection Switch", BLOCK_EN,
+		   PGAL_ZCD_EN, PGAR_ZCD_EN, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget a1_t9015_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("Right IN", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("Left IN", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MUX("Right DAC Sel", SND_SOC_NOPM, 0, 0,
+			 &t9015_right_dac_mux),
+	SND_SOC_DAPM_MUX("Left DAC Sel", SND_SOC_NOPM, 0, 0,
+			 &t9015_left_dac_mux),
+	SND_SOC_DAPM_DAC("Right DAC", NULL, BLOCK_EN, DACR_EN, 0),
+	SND_SOC_DAPM_DAC("Left DAC",  NULL, BLOCK_EN, DACL_EN, 0),
+	SND_SOC_DAPM_OUT_DRV("Right+ Driver", BLOCK_EN, LORP_EN, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("Left+ Driver",  BLOCK_EN, LOLP_EN, 0, NULL, 0),
+	SND_SOC_DAPM_OUTPUT("LORP"),
+	SND_SOC_DAPM_OUTPUT("LOLP"),
+
+	SND_SOC_DAPM_INPUT("ADC IN Right"),
+	SND_SOC_DAPM_INPUT("ADC IN Left"),
+	SND_SOC_DAPM_PGA("ADC PGA Right", BLOCK_EN, PGAR_EN, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("ADC PGA Left", BLOCK_EN, PGAL_EN, 0, NULL, 0),
+	SND_SOC_DAPM_ADC("ADC Right", NULL, BLOCK_EN, ADCR_EN, 0),
+	SND_SOC_DAPM_ADC("ADC Left", NULL, BLOCK_EN, ADCL_EN, 0),
+	SND_SOC_DAPM_MUX("ADC Right Sel", SND_SOC_NOPM, 0, 0, &a1_adc_right_mux),
+	SND_SOC_DAPM_MUX("ADC Left Sel", SND_SOC_NOPM, 0, 0, &a1_adc_left_mux),
+	SND_SOC_DAPM_AIF_OUT("ADC OUT Right", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("ADC OUT Left", NULL, 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route a1_t9015_dapm_routes[] = {
+	{ "Right IN", NULL, "Playback" },
+	{ "Left IN", NULL, "Playback" },
+	{ "Right DAC Sel", "Right", "Right IN" },
+	{ "Right DAC Sel", "Left", "Left IN" },
+	{ "Left DAC Sel", "Right", "Right IN" },
+	{ "Left DAC Sel", "Left", "Left IN" },
+	{ "Right DAC", NULL, "Right DAC Sel" },
+	{ "Left DAC", NULL, "Left DAC Sel" },
+	{ "Right+ Driver", NULL, "Right DAC" },
+	{ "Left+ Driver", NULL, "Left DAC" },
+	{ "LORP", NULL, "Right+ Driver", },
+	{ "LOLP", NULL, "Left+ Driver", },
+
+	{ "ADC PGA Right", NULL, "ADC IN Right" },
+	{ "ADC PGA Left", NULL, "ADC IN Left" },
+	{ "ADC Right", NULL, "ADC PGA Right" },
+	{ "ADC Left", NULL, "ADC PGA Left" },
+	{ "ADC Right Sel", "Right", "ADC Right" },
+	{ "ADC Right Sel", "Left", "ADC Left" },
+	{ "ADC Left Sel", "Right", "ADC Right" },
+	{ "ADC Left Sel", "Left", "ADC Left" },
+	{ "ADC OUT Right", NULL, "ADC Right Sel" },
+	{ "ADC OUT Left", NULL, "ADC Left Sel" },
+	{ "Capture", NULL, "ADC OUT Right" },
+	{ "Capture", NULL, "ADC OUT Left" },
+};
+
 static int t9015_set_bias_level(struct snd_soc_component *component,
 				enum snd_soc_bias_level level)
 {
@@ -241,6 +402,134 @@ static int t9015_component_probe(struct snd_soc_component *component)
 	return 0;
 }
 
+static int a1_t9015_line_cfg(struct snd_soc_component *component,
+			     const char *propname, unsigned int reg,
+			     unsigned int mask, const char **names,
+			     const unsigned int *values, unsigned int count)
+{
+	const char *propval;
+	unsigned int i;
+	int ret;
+
+	ret = device_property_read_string(component->dev, propname, &propval);
+	if (ret)
+		propval = names[0];
+
+	for (i = 0; i < count; i++) {
+		if (strcmp(propval, names[i]))
+			continue;
+
+		snd_soc_component_update_bits(component, reg, mask, values[i]);
+		return 0;
+	}
+
+	dev_err(component->dev, "wrong '%s' property value: '%s'",
+		 propname, propval);
+	return -EINVAL;
+}
+
+static int a1_t9015_lineout_cfg(struct snd_soc_component *component)
+{
+	const char *right_names[] = { "none", "right", "left-inverted" };
+	unsigned int right_values[] = { 0, 0x2000, 0x4000, };
+	const char *left_names[] = { "none", "left", "right-inverted" };
+	unsigned int left_values[] = { 0, 0x20, 0x40, };
+	int ret;
+
+	ret = a1_t9015_line_cfg(component, "lineout-right", LINEOUT_CFG, 0x7000,
+				right_names, right_values, ARRAY_SIZE(right_names));
+	if (ret)
+		return ret;
+
+	ret = a1_t9015_line_cfg(component, "lineout-left", LINEOUT_CFG, 0x70,
+				left_names, left_values, ARRAY_SIZE(left_names));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int a1_t9015_linein_cfg(struct snd_soc_component *component)
+{
+	const char *names[] = { "none", "differential", "positive",
+		"negative" };
+	unsigned int right_values[] = { 0, PGAR_DIFF, PGAR_POSITIVE,
+		PGAR_NEGATIVE };
+	unsigned int left_values[] = { 0, PGAL_DIFF, PGAL_POSITIVE,
+		PGAL_NEGATIVE };
+	int ret;
+
+	ret = a1_t9015_line_cfg(component, "linein-right", LINEIN_CFG, PGAR_MASK,
+				names, right_values, ARRAY_SIZE(names));
+	if (ret)
+		return ret;
+
+	ret = a1_t9015_line_cfg(component, "linein-left", LINEIN_CFG, PGAL_MASK,
+				names, left_values, ARRAY_SIZE(names));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int a1_t9015_micbias_cfg(struct snd_soc_component *component)
+{
+	const char *names[] = { "2.0V", "2.1V", "2.3V", "2.5V", "2.8V" };
+	const unsigned int values[] = { 0, 1, 2, 3, 7 };
+	const char *propname = "micbias";
+	const char *propval;
+	unsigned int i;
+	int ret;
+
+	ret = device_property_read_string(component->dev, propname, &propval);
+	if (ret) {
+		snd_soc_component_update_bits(component, LINEIN_CFG,
+					      BIT(MICBIAS_EN), 0);
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(names); i++) {
+		if (strcmp(propval, names[i]))
+			continue;
+
+		snd_soc_component_update_bits(component, LINEIN_CFG, 0x7,
+					      values[i]);
+		snd_soc_component_update_bits(component, LINEIN_CFG,
+					      BIT(MICBIAS_EN), BIT(MICBIAS_EN));
+		return 0;
+	}
+
+	dev_err(component->dev, "wrong '%s' property value: '%s'",
+		 propname, propval);
+	return -EINVAL;
+}
+
+static int a1_t9015_component_probe(struct snd_soc_component *component)
+{
+	int ret;
+
+	ret = a1_t9015_lineout_cfg(component);
+	if (ret)
+		return ret;
+
+	ret = a1_t9015_linein_cfg(component);
+	if (ret)
+		return ret;
+
+	ret = a1_t9015_micbias_cfg(component);
+	if (ret)
+		return ret;
+
+	/*
+	 * This configuration was stealed from original Amlogic's driver to
+	 * reproduce the behavior of the driver more accurately. However, it is
+	 * not known for certain what it actually affects.
+	 */
+	snd_soc_component_write(component, POWER_CFG, 0x00010000);
+
+	return 0;
+}
+
 static const struct snd_soc_component_driver t9015_codec_driver = {
 	.probe			= t9015_component_probe,
 	.set_bias_level		= t9015_set_bias_level,
@@ -254,6 +543,19 @@ static const struct snd_soc_component_driver t9015_codec_driver = {
 	.endianness		= 1,
 };
 
+static const struct snd_soc_component_driver a1_t9015_codec_driver = {
+	.probe			= a1_t9015_component_probe,
+	.set_bias_level		= t9015_set_bias_level,
+	.controls		= a1_t9015_snd_controls,
+	.num_controls		= ARRAY_SIZE(a1_t9015_snd_controls),
+	.dapm_widgets		= a1_t9015_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(a1_t9015_dapm_widgets),
+	.dapm_routes		= a1_t9015_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(a1_t9015_dapm_routes),
+	.suspend_bias_off	= 1,
+	.endianness		= 1,
+};
+
 static int t9015_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -315,11 +617,21 @@ static const struct t9015_match_data t9015_match_data = {
 	.max_register = POWER_CFG,
 };
 
+static const struct t9015_match_data a1_t9015_match_data = {
+	.component_drv = &a1_t9015_codec_driver,
+	.dai_drv = &a1_t9015_dai,
+	.max_register = LINEIN_CFG,
+};
+
 static const struct of_device_id t9015_ids[] __maybe_unused = {
 	{
 		.compatible = "amlogic,t9015",
 		.data = &t9015_match_data,
 	},
+	{
+		.compatible = "amlogic,t9015-a1",
+		.data = &a1_t9015_match_data,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, t9015_ids);
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:23 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:23 +0300
Subject: [PATCH v2 2/6] ASoC: dt-bindings: meson: axg-fifo: claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-3-jan.dakinevich@salutedevices.com>

Add "amlogic,a1-toddr" and "amlogic,a1-frddr" compatible string aliases
to "amlogic,sm1-toddr" and "amlogic,sm1-frddr" respectevely.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../devicetree/bindings/sound/amlogic,axg-fifo.yaml       | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.yaml b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.yaml
index b1b48d683101..1e809c7c2179 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.yaml
@@ -25,6 +25,14 @@ properties:
               - amlogic,g12a-frddr
               - amlogic,sm1-frddr
           - const: amlogic,axg-frddr
+      - items:
+          - const: amlogic,a1-toddr
+          - const: amlogic,sm1-toddr
+          - const: amlogic,axg-toddr
+      - items:
+          - const: amlogic,a1-frddr
+          - const: amlogic,sm1-frddr
+          - const: amlogic,axg-frddr
 
   reg:
     maxItems: 1
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:21 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:21 +0300
Subject: [PATCH v2 0/6] Enable audio on Amlogic A1 SoC family
Message-ID: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>

This series brings up the audio on Amlogic A1 SoC family and on Amlogic AD402
reference board.

Depends on [2][3][4]

Changes v1 [1] -> v2
 - detached from v1's series (patches 16, 17, 18, 19, 20, 21, 23, 24, 25)
 - use new names from updated clock controller
 - don't use A1-specific compatibe for pure software components
 - don't use link-name property

Links:
 [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/
 [2] https://lore.kernel.org/all/20250309180940.1322531-1-jan.dakinevich at salutedevices.com/
 [3] https://lore.kernel.org/all/20250309181600.1322701-1-jan.dakinevich at salutedevices.com/
 [4] https://lore.kernel.org/all/20250309181630.1322745-1-jan.dakinevich at salutedevices.com/

Jan Dakinevich (6):
  ASoC: dt-bindings: meson: meson-axg-audio-arb: claim support of A1 SoC
    family
  ASoC: dt-bindings: meson: axg-fifo: claim support of A1 SoC family
  ASoC: dt-bindings: meson: axg-pdm: claim support of A1 SoC family
  ASoC: dt-bindings: meson: axg-tdm-formatters: claim support of A1 SoC
    family
  arm64: dts: meson: a1: add audio devices
  arm64: dts: ad402: enable audio

 .../reset/amlogic,meson-axg-audio-arb.yaml    |  10 +-
 .../bindings/sound/amlogic,axg-fifo.yaml      |   8 +
 .../bindings/sound/amlogic,axg-pdm.yaml       |   1 +
 .../sound/amlogic,axg-tdm-formatters.yaml     |  22 +-
 .../arm64/boot/dts/amlogic/meson-a1-ad402.dts | 110 +++++
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi     | 443 ++++++++++++++++++
 6 files changed, 583 insertions(+), 11 deletions(-)

-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:22 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:22 +0300
Subject: [PATCH v2 1/6] ASoC: dt-bindings: meson: meson-axg-audio-arb: claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-2-jan.dakinevich@salutedevices.com>

Add "amlogic,meson-a1-audio-arb" compatible string alias to
"amlogic,meson-sm1-audio-arb".

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../bindings/reset/amlogic,meson-axg-audio-arb.yaml    | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.yaml
index bc1d284785e1..57e977db029f 100644
--- a/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.yaml
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.yaml
@@ -15,9 +15,13 @@ description: The Amlogic Audio ARB is a simple device which enables or disables
 
 properties:
   compatible:
-    enum:
-      - amlogic,meson-axg-audio-arb
-      - amlogic,meson-sm1-audio-arb
+    oneOf:
+      - enum:
+          - amlogic,meson-axg-audio-arb
+          - amlogic,meson-sm1-audio-arb
+      - items:
+          - const: amlogic,meson-a1-audio-arb
+          - const: amlogic,meson-sm1-audio-arb
 
   reg:
     maxItems: 1
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:25 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:25 +0300
Subject: [PATCH v2 4/6] ASoC: dt-bindings: meson: axg-tdm-formatters: claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-5-jan.dakinevich@salutedevices.com>

Add "amlogic,a1-tdmout" and "amlogic,a1-tdmin" compatible string aliases
to "amlogic,sm1-tdmout" and "amlogic,sm1-tdmin" respectevely.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 .../sound/amlogic,axg-tdm-formatters.yaml     | 22 ++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.yaml b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.yaml
index 719ca8fc98c7..154522488020 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.yaml
@@ -11,14 +11,20 @@ maintainers:
 
 properties:
   compatible:
-    enum:
-      - amlogic,g12a-tdmout
-      - amlogic,sm1-tdmout
-      - amlogic,axg-tdmout
-      - amlogic,g12a-tdmin
-      - amlogic,sm1-tdmin
-      - amlogic,axg-tdmin
-
+    oneOf:
+      - enum:
+          - amlogic,g12a-tdmout
+          - amlogic,sm1-tdmout
+          - amlogic,axg-tdmout
+          - amlogic,g12a-tdmin
+          - amlogic,sm1-tdmin
+          - amlogic,axg-tdmin
+      - items:
+          - const: amlogic,a1-tdmout
+          - const: amlogic,sm1-tdmout
+      - items:
+          - const: amlogic,a1-tdmin
+          - const: amlogic,sm1-tdmin
   clocks:
     items:
       - description: Peripheral clock
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:27 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:27 +0300
Subject: [PATCH v2 6/6] arm64: dts: ad402: enable audio
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-7-jan.dakinevich@salutedevices.com>

 * playback to speaker

   - setup:
     $ amixer set "FRDDR_A SINK 1 SEL" "OUT 0"
     $ amixer set "FRDDR_A SRC 1 EN" "on"
     $ amixer set "TDMOUT_A SRC SEL" "IN 0"
     $ amixer set "TOACODEC Source" "I2S A"
     $ amixer set "TOACODEC Lane Select" "0"
     $ amixer set "TOACODEC EN" "on"
     $ amixer set "ACODEC" "70%"
     $ amixer set "ACODEC Playback Channel Mode" "Mono"

   - usage:
     $ aplay -D hw:0,0 -f S16_LE -r 48000 /path/to/sample.wav

 * capture from digital mics

   - setup:
     $ amixer set "TODDR_B SRC SEL" "IN 4"

   - usage:
     $ arecord -D hw:0,1 -f S32_LE -r 48000 -c 2 -t wav /path/to/sample.wav

 * capture from analog mics

   - setup:
     $ amixer set "TDMIN_A SRC SEL" "IN 3"
     $ amixer set "TODDR_A SRC SEL" "IN 0"
     $ amixer set "TOACODEC Source" "I2S A"
     $ amixer set "TOACODEC Lane Select" "0"
     $ amixer set "TOACODEC EN" "on"
     $ amixer set "ACODEC ADC" "70%"
     $ amixer set "ACODEC ADC Filter" "on"
     $ amixer set "ACODEC ADC Filter Mode" "HiFi"
     $ amixer set "ACODEC ADC PGA" "50%"

   - usage:
     $ arecord -D hw:0,2 -f S16_LE -r 48000 -c 2 -t wav /path/to/sample.wav

 * capture from TDM loopback

   - setup:
     $ amixer set "TDMIN_LB SRC SEL" "IN 0"
     $ amixer set "TODDR_B SRC SEL" "IN 6"

   - usage:
     $ arecord -D hw:0,1 -f S16_LE -r 48000 -c 2 -t wav /path/to/sample.wav

   or

   - setup:
     $ amixer set "TDMIN_LB SRC SEL" "IN 0"
     $ amixer set "TODDR_A SRC SEL" "IN 6"

   - usage:
     $ arecord -D hw:0,2 -f S16_LE -r 48000 -c 2 -t wav /path/to/sample.wav

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
Signed-off-by: Dmitry Rokosov <ddrokosov at salutedevices.com>
---
 .../arm64/boot/dts/amlogic/meson-a1-ad402.dts | 110 ++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
index 0d92f5253b64..09a5732f0981 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
@@ -9,6 +9,8 @@
 #include "meson-a1.dtsi"
 #include <dt-bindings/thermal/thermal.h>
 
+#include <dt-bindings/gpio/gpio.h>
+
 / {
 	compatible = "amlogic,ad402", "amlogic,a1";
 	model = "Amlogic Meson A1 AD402 Development Board";
@@ -128,6 +130,98 @@ map1 {
 			};
 		};
 	};
+
+	amplifier: amplifier {
+		compatible = "simple-audio-amplifier";
+		sound-name-prefix = "AMPLIFIER";
+		enable-gpios = <&gpio GPIOF_4 GPIO_ACTIVE_HIGH>;
+		VCC-supply = <&battery_4v2>;
+	};
+
+	dmics: dmics {
+		compatible = "dmic-codec";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "MIC";
+		num-channels = <4>;
+		wakeup-delay-ms = <50>;
+	};
+
+	sound {
+		compatible = "amlogic,axg-sound-card";
+		model = "AD402";
+		audio-aux-devs = <&tdmout_a>,
+				 <&amplifier>,
+				 <&tdmin_lb>,
+				 <&tdmin_a>;
+		audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+				"TDM_A Playback", "TDMOUT_A OUT",
+				"AMPLIFIER INL", "ACODEC LOLP",
+				"AMPLIFIER INR", "ACODEC LORP",
+
+				"TODDR_B IN 4", "PDM Capture",
+
+				"TDMIN_LB IN 0", "TDM_A Loopback",
+				"TODDR_A IN 6", "TDMIN_LB OUT",
+				"TODDR_B IN 6", "TDMIN_LB OUT",
+
+				"TDMIN_A IN 3", "TDM_A Capture",
+				"TODDR_A IN 0", "TDMIN_A OUT";
+		assigned-clocks = <&clkc_pll CLKID_HIFI_PLL>;
+		assigned-clock-parents = <0>;
+		assigned-clock-rates = <1536000000>;
+
+		dai-link-0 {
+			sound-dai = <&frddr_a>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&toddr_b>;
+		};
+
+		dai-link-2 {
+			sound-dai = <&toddr_a>;
+		};
+
+		dai-link-3 {
+			sound-dai = <&tdmif_a>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			dai-tdm-slot-rx-mask-0 = <1 1>;
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&toacodec TOACODEC_IN_A>;
+			};
+
+			codec-1 {
+				sound-dai = <&toacodec TOACODEC_CAPTURE_OUT_A>;
+			};
+		};
+
+		dai-link-4 {
+			sound-dai = <&toacodec TOACODEC_OUT>;
+
+			codec {
+				sound-dai = <&acodec>;
+			};
+		};
+
+		dai-link-5 {
+			sound-dai = <&toacodec TOACODEC_CAPTURE_IN>;
+
+			codec {
+				sound-dai = <&acodec>;
+			};
+		};
+
+		dai-link-6 {
+			sound-dai = <&pdm>;
+
+			codec {
+				sound-dai = <&dmics>;
+			};
+		};
+	};
 };
 
 /* Bluetooth HCI H4 */
@@ -190,3 +284,19 @@ &sd_emmc {
 	vmmc-supply = <&vddao_3v3>;
 	vqmmc-supply = <&vddio_1v8>;
 };
+
+&acodec {
+	AVDD-supply = <&vddio_1v8>;
+	lineout-left = "right-inverted";
+	lineout-right = "right";
+	linein-left = "differential";
+	linein-right = "differential";
+	micbias = "2.5V";
+};
+
+&pdm {
+	pinctrl-0 = <&pdm_din0_a_pins>,
+		    <&pdm_din1_a_pins>,
+		    <&pdm_dclk_a_pins>;
+	pinctrl-names = "default";
+};
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:26 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:26 +0300
Subject: [PATCH v2 5/6] arm64: dts: meson: a1: add audio devices
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-6-jan.dakinevich@salutedevices.com>

This commit adds the declarartion of currently supported audio devices
and their pins found Amlog A1 SoC family. SPDIF declaration is missing
here becase there are no publicly available boards with it.

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi | 443 ++++++++++++++++++++++
 1 file changed, 443 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index cf0247fce740..b09df1da81c3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -11,6 +11,9 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/power/meson-a1-power.h>
 #include <dt-bindings/reset/amlogic,meson-a1-reset.h>
+#include <dt-bindings/reset/amlogic,meson-a1-audio-reset.h>
+#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
 
 / {
 	compatible = "amlogic,a1";
@@ -465,6 +468,250 @@ mux {
 						function = "spif";
 					};
 				};
+
+				tdm_a_din0_pins: tdm-a-din0 {
+					mux {
+						groups = "tdm_a_din0";
+						function = "tdm_a";
+						bias-disable;
+					};
+				};
+
+				tdm_a_din1_pins: tdm-a-din1 {
+					mux {
+						groups = "tdm_a_din1";
+						function = "tdm_a";
+						bias-disable;
+					};
+				};
+
+				tdm_a_dout0_pins: tdm-a-dout0 {
+					mux {
+						groups = "tdm_a_dout0";
+						function = "tdm_a";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_a_dout1_pins: tdm-a-dout1 {
+					mux {
+						groups = "tdm_a_dout1";
+						function = "tdm_a";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_a_fs_pins: tdm-a-fs {
+					mux {
+						groups = "tdm_a_fs";
+						function = "tdm_a";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_a_sclk_pins: tdm-a-sclk {
+					mux {
+						groups = "tdm_a_sclk";
+						function = "tdm_a";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_a_slv_fs_pins: tdm-a-slv-fs {
+					mux {
+						groups = "tdm_a_slv_fs";
+						function = "tdm_a";
+						bias-disable;
+					};
+				};
+
+				tdm_a_slv_sclk_pins: tdm-a-slv-sclk {
+					mux {
+						groups = "tdm_a_slv_sclk";
+						function = "tdm_a";
+						bias-disable;
+					};
+				};
+
+				tdm_b_din0_pins: tdm-b-din0 {
+					mux {
+						groups = "tdm_b_din0";
+						function = "tdm_b";
+						bias-disable;
+					};
+				};
+
+				tdm_b_din1_pins: tdm-b-din1 {
+					mux {
+						groups = "tdm_b_din1";
+						function = "tdm_b";
+						bias-disable;
+					};
+				};
+
+				tdm_b_din2_pins: tdm-b-din2 {
+					mux {
+						groups = "tdm_b_din2";
+						function = "tdm_b";
+						bias-disable;
+					};
+				};
+
+				tdm_b_dout0_pins: tdm-b-dout0 {
+					mux {
+						groups = "tdm_b_dout0";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_dout1_pins: tdm-b-dout1 {
+					mux {
+						groups = "tdm_b_dout1";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_dout2_pins: tdm-b-dout2 {
+					mux {
+						groups = "tdm_b_dout2";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_dout3_pins: tdm-b-dout3 {
+					mux {
+						groups = "tdm_b_dout3";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_dout4_pins: tdm-b-dout4 {
+					mux {
+						groups = "tdm_b_dout4";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_dout5_pins: tdm-b-dout5 {
+					mux {
+						groups = "tdm_b_dout5";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_fs_pins: tdm-b-fs {
+					mux {
+						groups = "tdm_b_fs";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_sclk_pins: tdm-b-sclk {
+					mux {
+						groups = "tdm_b_sclk";
+						function = "tdm_b";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
+				tdm_b_slv_fs_pins: tdm-b-slv-fs {
+					mux {
+						groups = "tdm_b_slv_fs";
+						function = "tdm_b";
+						bias-disable;
+					};
+				};
+
+				tdm_b_slv_sclk_pins: tdm-b-slv-sclk {
+					mux {
+						groups = "tdm_b_slv_sclk";
+						function = "tdm_b";
+						bias-disable;
+					};
+				};
+
+				pdm_din0_a_pins: pdm-din0-a {
+					mux {
+						groups = "pdm_din0_a";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_din0_x_pins: pdm-din0-x {
+					mux {
+						groups = "pdm_din0_x";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_din1_a_pins: pdm-din1-a {
+					mux {
+						groups = "pdm_din1_a";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_din1_x_pins: pdm-din1-x {
+					mux {
+						groups = "pdm_din1_x";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_din2_a_pins: pdm-din2-a {
+					mux {
+						groups = "pdm_din2_a";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_din2_x_pins: pdm-din2-x {
+					mux {
+						groups = "pdm_din2_x";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_dclk_a_pins: pdm-dclk-a {
+					mux {
+						groups = "pdm_dclk_a";
+						function = "pdm";
+						bias-disable;
+					};
+				};
+
+				pdm_dclk_x_pins: pdm-dclk-x {
+					mux {
+						groups = "pdm_dclk_x";
+						function = "pdm";
+						bias-disable;
+					};
+				};
 			};
 
 			gpio_intc: interrupt-controller at 440 {
@@ -666,6 +913,17 @@ sd_emmc: mmc at 10000 {
 				status = "disabled";
 			};
 
+			acodec: audio-controller at 4800 {
+				compatible = "amlogic,t9015-a1";
+				reg = <0x0 0x4800 0x0 0x14>;
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "ACODEC";
+				clocks = <&clkc_periphs CLKID_AUDIO>;
+				clock-names = "pclk";
+				resets = <&reset RESET_ACODEC>;
+				power-domains = <&pwrc PWRC_ACODEC_ID>;
+			};
+
 			audio: bus at 50000 {
 				compatible = "simple-bus";
 				#address-cells = <2>;
@@ -712,6 +970,171 @@ clkc_audio_vad: clock-controller at 4800 {
 						      "mst_in4";
 					resets = <&reset RESET_AUDIO_VAD>;
 				};
+
+				toddr_a: audio-controller at 100 {
+					compatible = "amlogic,a1-toddr",
+						     "amlogic,sm1-toddr",
+						     "amlogic,axg-toddr";
+					reg = <0x0 0x100 0x0 0x2c>;
+					#sound-dai-cells = <0>;
+					sound-name-prefix = "TODDR_A";
+					interrupts = <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+					clocks = <&clkc_audio AUD_CLKID_TODDR_A>;
+					resets = <&arb AXG_ARB_TODDR_A>,
+						 <&clkc_audio AUD_RESET_TODDR_A>;
+					reset-names = "arb", "rst";
+					amlogic,fifo-depth = <128>;
+				};
+
+				toddr_b: audio-controller at 140 {
+					compatible = "amlogic,a1-toddr",
+						     "amlogic,sm1-toddr",
+						     "amlogic,axg-toddr";
+					reg = <0x0 0x140 0x0 0x2c>;
+					#sound-dai-cells = <0>;
+					sound-name-prefix = "TODDR_B";
+					interrupts = <GIC_SPI 38 IRQ_TYPE_EDGE_RISING>;
+					clocks = <&clkc_audio AUD_CLKID_TODDR_B>;
+					resets = <&arb AXG_ARB_TODDR_B>,
+						 <&clkc_audio AUD_RESET_TODDR_B>;
+					reset-names = "arb", "rst";
+					amlogic,fifo-depth = <128>;
+				};
+
+				frddr_a: audio-controller at 1c0 {
+					compatible = "amlogic,a1-frddr",
+						     "amlogic,sm1-frddr",
+						     "amlogic,axg-frddr";
+					reg = <0x0 0x1c0 0x0 0x2c>;
+					#sound-dai-cells = <0>;
+					sound-name-prefix = "FRDDR_A";
+					interrupts = <GIC_SPI 40 IRQ_TYPE_EDGE_RISING>;
+					clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
+					resets = <&arb AXG_ARB_FRDDR_A>,
+						 <&clkc_audio AUD_RESET_FRDDR_A>;
+					reset-names = "arb", "rst";
+					amlogic,fifo-depth = <128>;
+				};
+
+				frddr_b: audio-controller at 200 {
+					compatible = "amlogic,a1-frddr",
+						     "amlogic,sm1-frddr",
+						     "amlogic,axg-frddr";
+					reg = <0x0 0x200 0x0 0x2c>;
+					#sound-dai-cells = <0>;
+					sound-name-prefix = "FRDDR_B";
+					interrupts = <GIC_SPI 41 IRQ_TYPE_EDGE_RISING>;
+					clocks = <&clkc_audio AUD_CLKID_FRDDR_B>;
+					resets = <&arb AXG_ARB_FRDDR_B>,
+						 <&clkc_audio AUD_RESET_FRDDR_B>;
+					reset-names = "arb", "rst";
+					amlogic,fifo-depth = <128>;
+				};
+
+				arb: reset-controller at 280 {
+					compatible = "amlogic,meson-a1-audio-arb",
+						     "amlogic,meson-sm1-audio-arb";
+					reg = <0x0 0x280 0x0 0x4>;
+					#reset-cells = <1>;
+					clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
+				};
+
+				tdmin_a: audio-controller at 300 {
+					compatible = "amlogic,a1-tdmin",
+						     "amlogic,sm1-tdmin";
+					reg = <0x0 0x300 0x0 0x40>;
+					sound-name-prefix = "TDMIN_A";
+					clocks = <&clkc_audio AUD_CLKID_TDMIN_A>,
+						 <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>,
+						 <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>;
+					clock-names = "pclk", "sclk", "sclk_sel",
+						      "lrclk", "lrclk_sel";
+					resets = <&clkc_audio AUD_RESET_TDMIN_A>;
+				};
+
+				tdmin_b: audio-controller at 340 {
+					compatible = "amlogic,a1-tdmin",
+						     "amlogic,sm1-tdmin";
+					reg = <0x0 0x340 0x0 0x40>;
+					sound-name-prefix = "TDMIN_B";
+					clocks = <&clkc_audio AUD_CLKID_TDMIN_B>,
+						 <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>,
+						 <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>;
+					clock-names = "pclk", "sclk", "sclk_sel",
+						      "lrclk", "lrclk_sel";
+					resets = <&clkc_audio AUD_RESET_TDMIN_B>;
+				};
+
+				tdmin_lb: audio-controller at 3c0 {
+					compatible = "amlogic,a1-tdmin",
+						     "amlogic,sm1-tdmin";
+					reg = <0x0 0x3c0 0x0 0x40>;
+					sound-name-prefix = "TDMIN_LB";
+					clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>,
+						 <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>,
+						 <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>,
+						 <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>;
+					clock-names = "pclk", "sclk", "sclk_sel",
+						      "lrclk", "lrclk_sel";
+					resets = <&clkc_audio AUD_RESET_TDMIN_LB>;
+				};
+
+				tdmout_a: audio-controller at 500 {
+					compatible = "amlogic,a1-tdmout",
+						     "amlogic,sm1-tdmout";
+					reg = <0x0 0x500 0x0 0x40>;
+					sound-name-prefix = "TDMOUT_A";
+					clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
+					clock-names = "pclk", "sclk", "sclk_sel",
+						      "lrclk", "lrclk_sel";
+					resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
+				};
+
+				tdmout_b: audio-controller at 540 {
+					compatible = "amlogic,a1-tdmout",
+						     "amlogic,sm1-tdmout";
+					reg = <0x0 0x540 0x0 0x40>;
+					sound-name-prefix = "TDMOUT_B";
+					clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>,
+						 <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>;
+					clock-names = "pclk", "sclk", "sclk_sel",
+						      "lrclk", "lrclk_sel";
+					resets = <&clkc_audio AUD_RESET_TDMOUT_B>;
+				};
+
+				toacodec: audio-controller at 740 {
+					compatible = "amlogic,a1-toacodec",
+						     "amlogic,g12a-toacodec";
+					reg = <0x0 0x740 0x0 0x4>;
+					#sound-dai-cells = <1>;
+					sound-name-prefix = "TOACODEC";
+					resets = <&clkc_audio AUD_RESET_TOACODEC>;
+				};
+
+				pdm: audio-controller at 1000 {
+					compatible = "amlogic,a1-pdm",
+						     "amlogic,axg-pdm";
+					reg = <0x0 0x1000 0x0 0x34>;
+					#sound-dai-cells = <0>;
+					sound-name-prefix = "PDM";
+					clocks = <&clkc_audio_vad AUD_VAD_CLKID_PDM>,
+						 <&clkc_audio_vad AUD_VAD_CLKID_PDM_DCLK>,
+						 <&clkc_audio_vad AUD_VAD_CLKID_PDM_SYSCLK>;
+					clock-names = "pclk", "dclk", "sysclk";
+					power-domains = <&pwrc PWRC_PDMIN_ID>;
+				};
 			};
 		};
 
@@ -794,4 +1217,24 @@ xtal: xtal-clk {
 		clock-output-names = "xtal";
 		#clock-cells = <0>;
 	};
+
+	tdmif_a: audio-controller-0 {
+		compatible = "amlogic,axg-tdm-iface";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "TDM_A";
+		clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+			 <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
+			 <&clkc_audio AUD_CLKID_MST_A_MCLK>;
+		clock-names = "sclk", "lrclk", "mclk";
+	};
+
+	tdmif_b: audio-controller-1 {
+		compatible = "amlogic,axg-tdm-iface";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "TDM_B";
+		clocks = <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+			 <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
+			 <&clkc_audio AUD_CLKID_MST_B_MCLK>;
+		clock-names = "sclk", "lrclk", "mclk";
+	};
 };
-- 
2.34.1



From jan.dakinevich at salutedevices.com  Sun Mar  9 11:21:24 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 21:21:24 +0300
Subject: [PATCH v2 3/6] ASoC: dt-bindings: meson: axg-pdm: claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
Message-ID: <20250309182127.1322890-4-jan.dakinevich@salutedevices.com>

Add "amlogic,a1-pdm" compatible string alias to "amlogic,axg-pdm".

Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
---
 Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml
index df21dd72fc65..9b6cd9f03a0c 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml
@@ -16,6 +16,7 @@ properties:
           - enum:
               - amlogic,g12a-pdm
               - amlogic,sm1-pdm
+              - amlogic,a1-pdm
           - const: amlogic,axg-pdm
       - const: amlogic,axg-pdm
 
-- 
2.34.1



From jonas at kwiboo.se  Sun Mar  9 11:23:12 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 9 Mar 2025 19:23:12 +0100
Subject: [PATCH 2/3] arm64: dts: rockchip: Add I2C controllers for RK3528
In-Reply-To: <20250309070603.35254-3-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
 <20250309070603.35254-3-ziyao@disroot.org>
Message-ID: <0b679284-d427-4229-b008-e3e466f66a0f@kwiboo.se>

Hi Yao Zi,

On 2025-03-09 08:06, Yao Zi wrote:
> Describe I2C controllers shipped by RK3528 in devicetree.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 104 +++++++++++++++++++++++
>  1 file changed, 104 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 04ca2e2b3e9b..860b6057e5c2 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -19,6 +19,14 @@ / {
>  	#size-cells = <2>;
>  
>  	aliases {
> +		i2c0 = &i2c0;
> +		i2c1 = &i2c1;
> +		i2c2 = &i2c2;
> +		i2c3 = &i2c3;
> +		i2c4 = &i2c4;
> +		i2c5 = &i2c5;
> +		i2c6 = &i2c6;
> +		i2c7 = &i2c7;

nitpick: These should be ordered after the gpioX aliases.

Regards,
Jonas

>  		gpio0 = &gpio0;
>  		gpio1 = &gpio1;
>  		gpio2 = &gpio2;

[snip]


From maz at kernel.org  Sun Mar  9 11:24:40 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 09 Mar 2025 18:24:40 +0000
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
In-Reply-To: <20250306184013.30008-1-sebott@redhat.com>
References: <20250306184013.30008-1-sebott@redhat.com>
Message-ID: <868qpeoydz.wl-maz@kernel.org>

On Thu, 06 Mar 2025 18:40:13 +0000,
Sebastian Ott <sebott at redhat.com> wrote:
> 
> Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
> Disallow to change these fields for NV since kvm provides a sanitized view
> for them based on the PAGE_SIZE.
> Also add these bits to the set_id_regs selftest.
> 
> Signed-off-by: Sebastian Ott <sebott at redhat.com>

Acked-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From jonas at kwiboo.se  Sun Mar  9 11:28:53 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 9 Mar 2025 19:28:53 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250307120004.959980-3-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <20250307120004.959980-3-amadeus@jmu.edu.cn>
Message-ID: <8172efa9-2f67-4b98-9988-88b533028431@kwiboo.se>

Hi Chukun,

On 2025-03-07 13:00, Chukun Pan wrote:
> Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
> RK3328, but the driver does not support interrupts yet.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 88 ++++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index b1713ed4d7e2..ab1ac3273611 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -264,6 +264,94 @@ uart7: serial at ffa28000 {
>  			status = "disabled";
>  		};
>  
> +		pwm0: pwm at ffa90000 {
> +			compatible = "rockchip,rk3528-pwm", "rockchip,rk3328-pwm";

nitpick: This could be split in two lines to match similar >80 chars
long lines in this file:

			compatible = "rockchip,rk3528-pwm",
				     "rockchip,rk3328-pwm";

And similar for the remaining pwmX.

Regards,
Jonas

> +			reg = <0x0 0xffa90000 0x0 0x10>;
> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> +			clock-names = "pwm", "pclk";
> +			pinctrl-0 = <&pwm0m0_pins>;
> +			pinctrl-names = "active";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +

[snip]


From maz at kernel.org  Sun Mar  9 11:40:00 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 09 Mar 2025 18:40:00 +0000
Subject: [PATCH v2 1/3] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250307-pmc-v2-1-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
	<20250307-pmc-v2-1-6c3375a5f1e4@daynix.com>
Message-ID: <867c4yoxof.wl-maz@kernel.org>

On Fri, 07 Mar 2025 10:55:28 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> Reload the perf event when setting the vPMU counter (vPMC) registers
> (PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
> commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
> for vPMC regs to return the current value") but for SET_ONE_REG.
> 
> Values of vPMC registers are saved in sysreg files on certain occasions.
> These saved values don't represent the current values of the vPMC
> registers if the perf events for the vPMCs count events after the save.
> The current values of those registers are the sum of the sysreg file
> value and the current perf event counter value.  But, when userspace
> writes those registers (using KVM_SET_ONE_REG), KVM only updates the
> sysreg file value and leaves the current perf event counter value as is.
> 
> Fix this by releasing the current perf event and trigger recreating one
> with KVM_REQ_RELOAD_PMU.
> 
> Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
>  arch/arm64/kvm/pmu-emul.c | 16 ++++++++++++++++
>  arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
>  include/kvm/arm_pmu.h     |  1 +
>  3 files changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index e3e82b66e2268d37d5e2630e47ddf085a6846e1c..1402cce5625bffa706aabe5e6121d1f3817a0aaf 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -191,6 +191,22 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
>  	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
>  }
>  
> +/**
> + * kvm_pmu_set_counter_value_user - set PMU counter value from user
> + * @vcpu: The vcpu pointer
> + * @select_idx: The counter index
> + * @val: The counter value
> + */
> +void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
> +{
> +	if (!kvm_vcpu_has_pmu(vcpu))
> +		return;

How can this occur? It seems to me that we only get here from a
register that has .visibility == pmu_visibility().

Or is there another way to reach this function?

> +
> +	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
> +	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
> +	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> +}
> +
>  /**
>   * kvm_pmu_release_perf_event - remove the perf event
>   * @pmc: The PMU counter pointer
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 42791971f75887796afab905cc12f49fead39e10..27418dac791df9a89124f867879e899db175e506 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
>  	return 0;
>  }
>  
> +static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> +			  u64 val)
> +{
> +	u64 idx;
> +
> +	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
> +		/* PMCCNTR_EL0 */
> +		idx = ARMV8_PMU_CYCLE_IDX;
> +	else
> +		/* PMEVCNTRn_EL0 */
> +		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
> +
> +	kvm_pmu_set_counter_value_user(vcpu, idx, val);
> +	return 0;
> +}
> +
>  static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
>  			      struct sys_reg_params *p,
>  			      const struct sys_reg_desc *r)
> @@ -1328,6 +1344,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
>  #define PMU_PMEVCNTR_EL0(n)						\
>  	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
>  	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
> +	  .set_user = set_pmu_evcntr,					\
>  	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
>  
>  /* Macro to expand the PMEVTYPERn_EL0 register */
> @@ -2682,7 +2699,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  	  .access = access_pmceid, .reset = NULL },
>  	{ PMU_SYS_REG(PMCCNTR_EL0),
>  	  .access = access_pmu_evcntr, .reset = reset_unknown,
> -	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
> +	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
> +	  .set_user = set_pmu_evcntr },
>  	{ PMU_SYS_REG(PMXEVTYPER_EL0),
>  	  .access = access_pmu_evtyper, .reset = NULL },
>  	{ PMU_SYS_REG(PMXEVCNTR_EL0),
> diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
> index 28b380ad8dfa942c4275e0c7ed3535d309b81b2f..9c062756ebfad5ea555362154459ffe9f8311c6d 100644
> --- a/include/kvm/arm_pmu.h
> +++ b/include/kvm/arm_pmu.h
> @@ -41,6 +41,7 @@ bool kvm_supports_guest_pmuv3(void);
>  #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
>  u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
>  void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
> +void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
>  u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
>  u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
>  void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);

Other than the nit above, looks good to me.

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Sun Mar  9 11:50:02 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 09 Mar 2025 18:50:02 +0000
Subject: [PATCH v2 2/3] KVM: arm64: PMU: Reload when user modifies registers
In-Reply-To: <20250307-pmc-v2-2-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
	<20250307-pmc-v2-2-6c3375a5f1e4@daynix.com>
Message-ID: <865xkiox7p.wl-maz@kernel.org>

[dropping Shannon  from the list, as his Linaro email has been
bouncing for about 10 years, and updating Andrew's email]

On Fri, 07 Mar 2025 10:55:29 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
> run") added the code to reload the PMU configuration on first run.
> Trigger the code when a user modifies a PMU register instead so that
> PMU configuration changes made by users will be applied also after the
> first run.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
>  arch/arm64/kvm/pmu-emul.c | 3 ---
>  arch/arm64/kvm/sys_regs.c | 5 +++++
>  2 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index 1402cce5625bffa706aabe5e6121d1f3817a0aaf..04eb3856b96576fad5afc8927c8916ff9738f9d7 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -888,9 +888,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
>  		   return -EINVAL;
>  	}
>  
> -	/* One-off reload of the PMU on first run */
> -	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> -
>  	return 0;
>  }
>  
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 27418dac791df9a89124f867879e899db175e506..51054b7befc0b4bd822cecf717ee4a4740c4a685 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1162,6 +1162,8 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
>  	else
>  		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
>  
> +	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> +
>  	return 0;
>  }
>  
> @@ -1322,6 +1324,8 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
>  		val |= ARMV8_PMU_PMCR_LC;
>  
>  	__vcpu_sys_reg(vcpu, r->reg) = val;
> +	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> +
>  	return 0;
>  }
>  
> @@ -4276,6 +4280,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
>  	}
>  
>  	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
> +	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);

This should be restricted to cases where a PMU is actually available.

But I also wonder what the motivation is to move this from first run
to reset? Nothing explains it in the commit message.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From robh at kernel.org  Sun Mar  9 11:50:07 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sun, 09 Mar 2025 13:50:07 -0500
Subject: [net-next PATCH v12 05/13] dt-bindings: mfd: Document support
 for Airoha AN8855 Switch SoC
In-Reply-To: <20250309172717.9067-6-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-6-ansuelsmth@gmail.com>
Message-ID: <174154620758.1888708.16493498235993467665.robh@kernel.org>


On Sun, 09 Mar 2025 18:26:50 +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 Switch SoC. This SoC expose various
> peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> 
> It does also support i2c and timers but those are not currently
> supported/used.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/mfd/airoha,an8855.yaml           | 186 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 187 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 1: $nodename:0: 'phy at 1' does not match '^ethernet-phy(@[a-f0-9]+)?$'
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 1: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 2: $nodename:0: 'phy at 2' does not match '^ethernet-phy(@[a-f0-9]+)?$'
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 2: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#

doc reference errors (make refcheckdocs):
Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/mfd/airoha,an8855-mfd.yaml
MAINTAINERS: Documentation/devicetree/bindings/mfd/airoha,an8855-mfd.yaml

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250309172717.9067-6-ansuelsmth at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From krzysztof.kozlowski at linaro.org  Sun Mar  9 11:55:55 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 19:55:55 +0100
Subject: [GIT PULL 1/4] samsung: drivers for v6.15
Message-ID: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-drivers-6.15

for you to fetch changes up to 8f299df1b75ad0939f1340182c265de019eab438:

  dt-bindings: soc: samsung: exynos-usi: Drop unnecessary status from example (2025-03-09 18:53:34 +0100)

----------------------------------------------------------------
Samsung SoC drivers for v6.15

1. Add support for Exynos USI v1 serial engines.  Drivers already
   supported newer IP blocks - USI v2 - present in Exynos850 and newer.
   A bit older ARM64 designs, like Exynos8895 use older USI v1 block.

2. Add Exynos ACPM (Alive Clock and Power Manager) protocol driver
   for Google GS101 SoC.  ACPM protocol allows communication between the
   power management firmware and other embedded processors.

3. Exynos2200: Add PMU, ChipID and SYSREG Devicetree bindings.

4. Exynos7870: Add PMU and ChipID Devicetree bindings.

5. Various cleanups.

----------------------------------------------------------------
Arnd Bergmann (1):
      soc: samsung: include linux/array_size.h where needed

Colin Ian King (1):
      firmware: Exynos ACPM: Fix spelling mistake "Faile" -> "Failed"

Ivaylo Ivanov (7):
      dt-bindings: soc: samsung: usi: add USIv1 and samsung,exynos8895-usi
      soc: samsung: usi: add a routine for unconfiguring the ip
      soc: samsung: usi: implement support for USIv1 and exynos8895
      dt-bindings: soc: samsung: exynos-sysreg: add sysreg compatibles for exynos2200
      dt-bindings: soc: samsung: exynos-pmu: add exynos2200 compatible
      dt-bindings: hwinfo: samsung,exynos-chipid: add exynos2200 compatible
      soc: samsung: exynos-chipid: add exynos2200 SoC support

Kaustabh Chakraborty (3):
      dt-bindings: hwinfo: samsung,exynos-chipid: add exynos7870-chipid compatible
      dt-bindings: soc: samsung: exynos-pmu: add exynos7870-pmu compatible
      soc: samsung: exynos-chipid: add support for exynos7870

Krzysztof Kozlowski (3):
      soc: samsung: Use syscon_regmap_lookup_by_phandle_args
      Merge branch 'for-v6.15/samsung-soc-dt-bindings' into next/drivers
      dt-bindings: soc: samsung: exynos-usi: Drop unnecessary status from example

Tudor Ambarus (3):
      dt-bindings: firmware: add google,gs101-acpm-ipc
      firmware: add Exynos ACPM protocol driver
      MAINTAINERS: add entry for the Samsung Exynos ACPM mailbox protocol

 .../bindings/firmware/google,gs101-acpm-ipc.yaml   |  50 ++
 .../bindings/hwinfo/samsung,exynos-chipid.yaml     |   2 +
 .../bindings/soc/samsung/exynos-pmu.yaml           |   2 +
 .../bindings/soc/samsung/exynos-usi.yaml           | 100 ++-
 .../soc/samsung/samsung,exynos-sysreg.yaml         |   5 +
 MAINTAINERS                                        |  10 +
 drivers/firmware/Kconfig                           |   1 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/samsung/Kconfig                   |  14 +
 drivers/firmware/samsung/Makefile                  |   4 +
 drivers/firmware/samsung/exynos-acpm-pmic.c        | 224 ++++++
 drivers/firmware/samsung/exynos-acpm-pmic.h        |  29 +
 drivers/firmware/samsung/exynos-acpm.c             | 769 +++++++++++++++++++++
 drivers/firmware/samsung/exynos-acpm.h             |  23 +
 drivers/soc/samsung/exynos-asv.c                   |   1 +
 drivers/soc/samsung/exynos-chipid.c                |   3 +
 drivers/soc/samsung/exynos-pmu.c                   |   1 +
 drivers/soc/samsung/exynos-usi.c                   | 108 ++-
 drivers/soc/samsung/exynos3250-pmu.c               |   1 +
 drivers/soc/samsung/exynos5250-pmu.c               |   1 +
 drivers/soc/samsung/exynos5420-pmu.c               |   1 +
 include/dt-bindings/soc/samsung,exynos-usi.h       |  17 +-
 .../linux/firmware/samsung/exynos-acpm-protocol.h  |  49 ++
 23 files changed, 1359 insertions(+), 57 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
 create mode 100644 drivers/firmware/samsung/Kconfig
 create mode 100644 drivers/firmware/samsung/Makefile
 create mode 100644 drivers/firmware/samsung/exynos-acpm-pmic.c
 create mode 100644 drivers/firmware/samsung/exynos-acpm-pmic.h
 create mode 100644 drivers/firmware/samsung/exynos-acpm.c
 create mode 100644 drivers/firmware/samsung/exynos-acpm.h
 create mode 100644 include/linux/firmware/samsung/exynos-acpm-protocol.h


From krzysztof.kozlowski at linaro.org  Sun Mar  9 11:55:56 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 19:55:56 +0100
Subject: [GIT PULL 2/4] arm64: dts: samsung: DTS for v6.15
In-Reply-To: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
References: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250309185601.10616-2-krzysztof.kozlowski@linaro.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-dt64-6.15

for you to fetch changes up to 056106b030b73c7d53749469bd1cdbc89b4d2daf:

  arm64: dts: tesla: Change labels to lower-case (2025-03-07 16:05:35 +0100)

----------------------------------------------------------------
Samsung DTS ARM64 changes for v6.15

1. Google GS101:
 - Disable GSA core pinctrl because its registers are not available for
   normal world.
 - Add APM (Active Power Management) mailbox and the ACPM firmware nodes.
 - Add new boards: Google Pixel 6 Pro (Raven).
 - Enable framebuffer and reboot-mode.

2. Exynos990:
 - Add PERIS clock controller, MCT timer

3. Exynos8895:
 - Define all remaining serial engine (USI) and syscon nodes, add MMC.
 - Enable microSD and touchsreen on Samsung Galaxy S8 (dreamlte).

4. ExynosAutov920: Add UFS and CPU cache information.

5. Various cleanups.

This includes two topic branches with DT bindings, which might be shared
with other trees depending on needs:
1. for-v6.15/samsung-clk-dt-bindings with Exynos990 clock controller
   header constants.
2. for-v6.15/samsung-soc-dt-bindings with Exynos USI serial engines
   header constants rework.

----------------------------------------------------------------
Andr? Draszik (7):
      dt-bindings: arm: google: add gs101-raven
      arm64: dts: exynos: gs101-oriole: configure simple-framebuffer
      arm64: dts: exynos: gs101-oriole: move common Pixel6 & 6Pro parts into a .dtsi
      arm64: dts: exynos: gs101-raven: add new board file
      arm64: dts: exynos: gs101: drop explicit regmap from reboot nodes
      arm64: dts: exynos: gs101: align poweroff writes with downstream
      arm64: dts: exynos: gs101: add reboot-mode support (SYSIP_DAT0)

Devang Tailor (1):
      arm64: dts: exynosautov920: add CPU cache information

Igor Belwon (3):
      dt-bindings: clock: exynos990: Add CMU_PERIS block
      arm64: dts: exynos990: Add CMU_PERIS and MCT nodes
      arm64: dts: exynos990: Rename and sort PMU nodes

Ivaylo Ivanov (6):
      dt-bindings: soc: samsung: usi: add USIv1 and samsung,exynos8895-usi
      arm64: dts: exynos8895: add syscon nodes for peric0/1 and fsys0/1
      arm64: dts: exynos8895: define all usi nodes
      arm64: dts: exynos8895: add a node for mmc
      arm64: dts: exynos8895-dreamlte: enable support for microSD storage
      arm64: dts: exynos8895-dreamlte: enable support for the touchscreen

Krzysztof Kozlowski (5):
      Merge branch 'for-v6.15/samsung-clk-dt-bindings' into next/dt64
      Merge branch 'for-v6.15/samsung-soc-dt-bindings' into next/dt64
      arm64: dts: exynos8895: Rename PMU nodes to fixup sorting
      arm64: dts: exynos: gs101: Change labels to lower-case
      arm64: dts: tesla: Change labels to lower-case

Peter Griffin (1):
      arm64: dts: exynos: gs101: disable pinctrl_gsacore node

Sowon Na (1):
      arm64: dts: exynosautov920: add ufs phy for ExynosAutov920 SoC

Tudor Ambarus (3):
      arm64: dts: exynos: gs101: add SRAM node
      arm64: dts: exynos: gs101: add AP to APM mailbox node
      arm64: dts: exynos: gs101: add ACPM protocol node

 Documentation/devicetree/bindings/arm/google.yaml  |   3 +-
 .../bindings/clock/samsung,exynos990-clock.yaml    |  19 +
 .../bindings/soc/samsung/exynos-usi.yaml           |  99 ++-
 arch/arm64/boot/dts/exynos/exynos8895-dreamlte.dts |  72 ++
 arch/arm64/boot/dts/exynos/exynos8895.dtsi         | 956 ++++++++++++++++++++-
 arch/arm64/boot/dts/exynos/exynos990.dtsi          |  92 +-
 arch/arm64/boot/dts/exynos/exynosautov920.dtsi     | 138 +++
 arch/arm64/boot/dts/exynos/google/Makefile         |   1 +
 arch/arm64/boot/dts/exynos/google/gs101-oriole.dts | 267 +-----
 .../boot/dts/exynos/google/gs101-pixel-common.dtsi | 294 +++++++
 arch/arm64/boot/dts/exynos/google/gs101-raven.dts  |  29 +
 arch/arm64/boot/dts/exynos/google/gs101.dtsi       |  66 +-
 arch/arm64/boot/dts/tesla/fsd.dtsi                 |  26 +-
 include/dt-bindings/clock/samsung,exynos990.h      |  21 +
 include/dt-bindings/soc/samsung,exynos-usi.h       |  17 +-
 15 files changed, 1721 insertions(+), 379 deletions(-)
 create mode 100644 arch/arm64/boot/dts/exynos/google/gs101-pixel-common.dtsi
 create mode 100644 arch/arm64/boot/dts/exynos/google/gs101-raven.dts


From ansuelsmth at gmail.com  Sun Mar  9 10:26:45 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:45 +0100
Subject: [net-next PATCH v12 00/13] net: dsa: Add Airoha AN8855 support
Message-ID: <20250309172717.9067-1-ansuelsmth@gmail.com>

This small series add the initial support for the Airoha AN8855 Switch.

It's a 5 port Gigabit Switch with SGMII/HSGMII upstream port.

This is starting to get in the wild and there are already some router
having this switch chip.

It's conceptually similar to mediatek switch but register and bits
are different. And there is that massive Hell that is the PCS
configuration.
Saddly for that part we have absolutely NO documentation currently.

There is this special thing where PHY needs to be calibrated with values
from the switch efuse. (the thing have a whole cpu timer and MCU)

>From v8 Driver is now evaluated with Kernel selftest scripts for DSA:

Additional info about the test bridge_vlan_aware.sh.

It was discovered that the Airoha Switch (and probably the Mediatek one
that produce the same test results) hardcode checking for 802.1ad when
the port is configured in VLAN-Aware mode (aka Security mode).

In such mode, both 802.1q and 802.1ad TPID are checked, hence the
bridge_vlan_aware.sh test fails as packets with 802.1ad TPID are rejected
(in the case where a wrong VLAN ID is forwarded)

This was confirmed by Airoha and multiple try were done to try to
workaround this problem. No solution were found to this as ACL mechanism
can't work on receiving packets and the Switch doesn't support turning off
this.

The current driver is in use from 2 month on OpenWrt with all kind of
scenario confirming working in VLAN bridge. By tweaking the
bridge_vlan_aware.sh test with setting the TPID to 0x9100, the test
correctly pass as packets gets classified as untagged and the default PVID
applied. It's also confirmed that switch correctly parse the 802.1ad tag
and make the packet pass only when allowed by VLAN table rules.

Output local_termination.sh
TEST: lan2: Unicast IPv4 to primary MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to macvlan MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address, promisc            [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address, allmulti           [ OK ]
TEST: lan2: Multicast IPv4 to joined group                          [ OK ]
TEST: lan2: Multicast IPv4 to unknown group                         [XFAIL]
        reception succeeded, but should have failed
TEST: lan2: Multicast IPv4 to unknown group, promisc                [ OK ]
TEST: lan2: Multicast IPv4 to unknown group, allmulti               [ OK ]
TEST: lan2: Multicast IPv6 to joined group                          [ OK ]
TEST: lan2: Multicast IPv6 to unknown group                         [XFAIL]
        reception succeeded, but should have failed
TEST: lan2: Multicast IPv6 to unknown group, promisc                [ OK ]
TEST: lan2: Multicast IPv6 to unknown group, allmulti               [ OK ]
TEST: lan2: 1588v2 over L2 transport, Sync                          [ OK ]
TEST: lan2: 1588v2 over L2 transport, Follow-Up                     [ OK ]
TEST: lan2: 1588v2 over L2 transport, Peer Delay Request            [ OK ]
TEST: lan2: 1588v2 over IPv4, Sync                                  [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv4, Follow-Up                             [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv4, Peer Delay Request                    [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Sync                                  [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Follow-Up                             [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Peer Delay Request                    [FAIL]
        reception failed
TEST: vlan_filtering=0 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to joined group       [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to joined group       [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to joined group       [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to joined group       [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN upper: Unicast IPv4 to primary MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to macvlan MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address, promisc      [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address, allmulti     [ OK ]
TEST: VLAN upper: Multicast IPv4 to joined group                    [ OK ]
TEST: VLAN upper: Multicast IPv4 to unknown group                   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN upper: Multicast IPv4 to unknown group, promisc          [ OK ]
TEST: VLAN upper: Multicast IPv4 to unknown group, allmulti         [ OK ]
TEST: VLAN upper: Multicast IPv6 to joined group                    [ OK ]
TEST: VLAN upper: Multicast IPv6 to unknown group                   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN upper: Multicast IPv6 to unknown group, promisc          [ OK ]
TEST: VLAN upper: Multicast IPv6 to unknown group, allmulti         [ OK ]
TEST: VLAN upper: 1588v2 over L2 transport, Sync                    [ OK ]
TEST: VLAN upper: 1588v2 over L2 transport, Follow-Up               [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over L2 transport, Peer Delay Request      [ OK ]
TEST: VLAN upper: 1588v2 over IPv4, Sync                            [FAIL]
        reception failed
;TEST: VLAN upper: 1588v2 over IPv4, Follow-Up                       [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv4, Peer Delay Request              [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Sync                            [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Follow-Up                       [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Peer Delay Request              [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Sync   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Follow-Up   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Peer Delay Request   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address   [FAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address, allmulti   [FAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Sync   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Follow-Up   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Peer Delay Request   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]

Output bridge_vlan_unaware.sh
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: FDB learning                                                  [ OK ]
TEST: Unknown unicast flood                                         [ OK ]
TEST: Unregistered multicast flood                                  [ OK ]

Output bridge_vlan_aware.sh
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: FDB learning                                                  [ OK ]
TEST: Unknown unicast flood                                         [ OK ]
TEST: Unregistered multicast flood                                  [ OK ]
INFO: Add and delete a VLAN on bridge port lan2
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: Externally learned FDB entry - ageing & roaming               [ OK ]
TEST: FDB entry in PVID for VLAN-tagged with other TPID             [FAIL]
        FDB entry was not learned when it should
TEST: Reception of VLAN with other TPID as untagged                 [FAIL]
        Packet was not forwarded when it should
TEST: Reception of VLAN with other TPID as untagged (no PVID)       [FAIL]
        Packet was forwarded when should not

[ For Vladimir, I still have to implement fdb_isolation but posting to
start the ball rolling for the multiple subsystem this patch affect
and for the dubious DT schema ]

Changes v12:
- Update on top of net-next
- Add additional info on conver-letter about slefttests and HW limitation
- Introduce mdio-regmap generalization for multiple address
- Drop dev flags and define PHY calibration in PHY node directly
Changes v11:
- Address reviews from Christophe (spell mistake + dev_err_probe)
- Fix kconfig dependency for MFD driver (depends on MDIO_DEVICE instead of MDIO)
  (indirectly fix link error for mdio APIs)
- Fix copy-paste error for MFD driver of_table
- Fix compilation error for PHY (move NVMEM to .config)
- Drop unneeded NVMEM node from MDIO example schema (from Andrew)
- Adapt MFD example schema to MDIO reg property restrictions
Changes v10:
- Entire rework to MFD + split to MDIO, EFUSE, SWITCH separate drivers
- Drop EEE OPs (while Russell finish RFC for EEE changes)
- Use new pcs_inpand OPs
- Drop AN restart function and move to pcs_config
- Enable assisted_learning and disable CPU learn (preparation for fdb_isolation)
- Move EFUSE read in Internal PHY driver to .config to handle EPROBE_DEFER
  (needed now that NVMEM driver is register externally instead of internally to switch
   node)
Changes v9:
- Error out on using 5G speed as currently not supported
- Add missing MAC_2500FD in phylink mac_capabilities
- Add comment and improve if condition for an8855_phylink_mac_config
Changes v8:
- Add port Fast Age support
- Add support for Port Isolation
- Use correct register for Learning Disable
- Add support for Ageing Time OP
- Set default PVID to 0 by default
- Add mdb OPs
- Add port change MTU
- Fix support for Upper VLAN
Changes v7:
- Fix devm_dsa_register_switch wrong export symbol
Changes v6:
- Drop standard MIB and handle with ethtool OPs (as requested by Jakub)
- Cosmetic: use bool instead of 0 or 1
Changes v5:
- Add devm_dsa_register_switch() patch
- Add Reviewed-by tag for DT patch
Changes v4:
- Set regmap readable_table static (mute compilation warning)
- Add support for port_bridge flags (LEARNING, FLOOD)
- Reset fdb struct in fdb_dump
- Drop support_asym_pause in port_enable
- Add define for get_phy_flags
- Fix bug for port not inititially part of a bridge
  (in an8855_setup the port matrix was always cleared but
   the CPU port was never initially added)
- Disable learning and flood for user port by default
- Set CPU port to flood and learning by default
- Correctly AND force duplex and flow control in an8855_phylink_mac_link_up
- Drop RGMII from pcs_config
- Check ret in "Disable AN if not in autoneg"
- Use devm_mutex_init
- Fix typo for AN8855_PORT_CHECK_MODE
- Better define AN8855_STP_LISTENING = AN8855_STP_BLOCKING
- Fix typo in AN8855_PHY_EN_DOWN_SHIFT
- Use paged helper for PHY
- Skip calibration in config_init if priv not defined
Changes v3:
- Out of RFC
- Switch PHY code to select_page API
- Better describe masks and bits in PHY driver for ADC register
- Drop raw values and use define for mii read/write
- Switch to absolute PHY address
- Replace raw values with mask and bits for pcs_config
- Fix typo for ext-surge property name
- Drop support for relocating Switch base PHY address on the bus
Changes v2:
- Drop mutex guard patch
- Drop guard usage in DSA driver
- Use __mdiobus_write/read
- Check return condition and return errors for mii read/write
- Fix wrong logic for EEE
- Fix link_down (don't force link down with autoneg)
- Fix forcing speed on sgmii autoneg
- Better document link speed for sgmii reg
- Use standard define for sgmii reg
- Imlement nvmem support to expose switch EFUSE
- Rework PHY calibration with the use of NVMEM producer/consumer
- Update DT with new NVMEM property
- Move aneg validation for 2500-basex in pcs_config
- Move r50Ohm table and function to PHY driver

Christian Marangi (13):
  dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE
  dt-bindings: net: Document support for Airoha AN8855 Switch Virtual
    MDIO
  dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
  dt-bindings: net: Document support for AN8855 Switch Internal PHY
  dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
  net: mdio: regmap: prepare support for multiple valid addr
  net: mdio: regmap: add support for multiple valid addr
  net: mdio: regmap: add OF support
  mfd: an8855: Add support for Airoha AN8855 Switch MFD
  net: mdio: Add Airoha AN8855 Switch MDIO Passtrough
  nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE
  net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver
  net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY

 .../bindings/mfd/airoha,an8855.yaml           |  186 ++
 .../bindings/net/airoha,an8855-mdio.yaml      |   56 +
 .../bindings/net/airoha,an8855-phy.yaml       |   93 +
 .../net/dsa/airoha,an8855-switch.yaml         |  105 +
 .../bindings/nvmem/airoha,an8855-efuse.yaml   |  123 +
 MAINTAINERS                                   |   18 +
 drivers/mfd/Kconfig                           |   10 +
 drivers/mfd/Makefile                          |    1 +
 drivers/mfd/airoha-an8855.c                   |  445 ++++
 drivers/net/dsa/Kconfig                       |    9 +
 drivers/net/dsa/Makefile                      |    1 +
 drivers/net/dsa/an8855.c                      | 2296 +++++++++++++++++
 drivers/net/dsa/an8855.h                      |  771 ++++++
 drivers/net/mdio/Kconfig                      |   10 +
 drivers/net/mdio/Makefile                     |    1 +
 drivers/net/mdio/mdio-an8855.c                |   48 +
 drivers/net/mdio/mdio-regmap.c                |   24 +-
 drivers/net/phy/Kconfig                       |    5 +
 drivers/net/phy/Makefile                      |    1 +
 drivers/net/phy/air_an8855.c                  |  261 ++
 drivers/nvmem/Kconfig                         |   11 +
 drivers/nvmem/Makefile                        |    2 +
 drivers/nvmem/an8855-efuse.c                  |   63 +
 include/linux/mdio/mdio-regmap.h              |   10 +
 24 files changed, 4544 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 create mode 100644 drivers/mfd/airoha-an8855.c
 create mode 100644 drivers/net/dsa/an8855.c
 create mode 100644 drivers/net/dsa/an8855.h
 create mode 100644 drivers/net/mdio/mdio-an8855.c
 create mode 100644 drivers/net/phy/air_an8855.c
 create mode 100644 drivers/nvmem/an8855-efuse.c

-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:46 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:46 +0100
Subject: [net-next PATCH v12 01/13] dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-2-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Switch EFUSE used to calibrate
internal PHYs and store additional configuration info.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/nvmem/airoha,an8855-efuse.yaml   | 123 ++++++++++++++++++
 MAINTAINERS                                   |   8 ++
 2 files changed, 131 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml

diff --git a/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
new file mode 100644
index 000000000000..9802d9ea2176
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/airoha,an8855-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch EFUSE
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description:
+  Airoha AN8855 EFUSE used to calibrate internal PHYs and store additional
+  configuration info.
+
+$ref: nvmem.yaml#
+
+properties:
+  compatible:
+    const: airoha,an8855-efuse
+
+  '#nvmem-cell-cells':
+    const: 0
+
+required:
+  - compatible
+  - '#nvmem-cell-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    efuse {
+        compatible = "airoha,an8855-efuse";
+
+        #nvmem-cell-cells = <0>;
+
+        nvmem-layout {
+            compatible = "fixed-layout";
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            shift_sel_port0_tx_a: shift-sel-port0-tx-a at c {
+               reg = <0xc 0x4>;
+            };
+
+            shift_sel_port0_tx_b: shift-sel-port0-tx-b at 10 {
+                reg = <0x10 0x4>;
+            };
+
+            shift_sel_port0_tx_c: shift-sel-port0-tx-c at 14 {
+                reg = <0x14 0x4>;
+            };
+
+            shift_sel_port0_tx_d: shift-sel-port0-tx-d at 18 {
+               reg = <0x18 0x4>;
+            };
+
+            shift_sel_port1_tx_a: shift-sel-port1-tx-a at 1c {
+               reg = <0x1c 0x4>;
+            };
+
+            shift_sel_port1_tx_b: shift-sel-port1-tx-b at 20 {
+               reg = <0x20 0x4>;
+            };
+
+            shift_sel_port1_tx_c: shift-sel-port1-tx-c at 24 {
+               reg = <0x24 0x4>;
+            };
+
+            shift_sel_port1_tx_d: shift-sel-port1-tx-d at 28 {
+               reg = <0x28 0x4>;
+            };
+
+            shift_sel_port2_tx_a: shift-sel-port2-tx-a at 2c {
+                reg = <0x2c 0x4>;
+            };
+
+            shift_sel_port2_tx_b: shift-sel-port2-tx-b at 30 {
+                reg = <0x30 0x4>;
+            };
+
+            shift_sel_port2_tx_c: shift-sel-port2-tx-c at 34 {
+                reg = <0x34 0x4>;
+            };
+
+            shift_sel_port2_tx_d: shift-sel-port2-tx-d at 38 {
+                reg = <0x38 0x4>;
+            };
+
+            shift_sel_port3_tx_a: shift-sel-port3-tx-a at 4c {
+                reg = <0x4c 0x4>;
+            };
+
+            shift_sel_port3_tx_b: shift-sel-port3-tx-b at 50 {
+                reg = <0x50 0x4>;
+            };
+
+            shift_sel_port3_tx_c: shift-sel-port3-tx-c at 54 {
+               reg = <0x54 0x4>;
+            };
+
+            shift_sel_port3_tx_d: shift-sel-port3-tx-d at 58 {
+               reg = <0x58 0x4>;
+            };
+
+            shift_sel_port4_tx_a: shift-sel-port4-tx-a at 5c {
+                reg = <0x5c 0x4>;
+            };
+
+            shift_sel_port4_tx_b: shift-sel-port4-tx-b at 60 {
+                reg = <0x60 0x4>;
+            };
+
+            shift_sel_port4_tx_c: shift-sel-port4-tx-c at 64 {
+                reg = <0x64 0x4>;
+            };
+
+            shift_sel_port4_tx_d: shift-sel-port4-tx-d at 68 {
+                reg = <0x68 0x4>;
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index ffbcd072fb14..576fa7eb7b55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -719,6 +719,14 @@ S:	Supported
 F:	fs/aio.c
 F:	include/linux/*aio*.h
 
+AIROHA DSA DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
+L:	netdev at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:47 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:47 +0100
Subject: [net-next PATCH v12 02/13] dt-bindings: net: Document support for Airoha AN8855 Switch Virtual MDIO
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-3-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Virtual MDIO Passtrough. This is needed
as AN8855 require special handling as the same address on the MDIO bus is
shared for both Switch and PHY and special handling for the page
configuration is needed to switch accessing to Switch address space
or PHY.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/net/airoha,an8855-mdio.yaml      | 56 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml

diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
new file mode 100644
index 000000000000..3078277bf478
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-mdio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 MDIO Passtrough
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description:
+  Airoha AN8855 Virtual MDIO Passtrough. This is needed as AN8855
+  require special handling as the same address on the MDIO bus is
+  shared for both Switch and PHY and special handling for the page
+  configuration is needed to switch accessing to Switch address space
+  or PHY.
+
+$ref: /schemas/net/mdio.yaml#
+
+properties:
+  compatible:
+    const: airoha,an8855-mdio
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        compatible = "airoha,an8855-mdio";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        internal_phy1: phy at 1 {
+            reg = <1>;
+        };
+
+        internal_phy2: phy at 2 {
+            reg = <2>;
+        };
+
+        internal_phy3: phy at 3 {
+            reg = <3>;
+        };
+
+        internal_phy4: phy at 4 {
+            reg = <4>;
+        };
+
+        internal_phy5: phy at 5 {
+            reg = <5>;
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 576fa7eb7b55..1e8055b5e162 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -725,6 +725,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
 AIROHA ETHERNET DRIVER
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:48 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:48 +0100
Subject: [net-next PATCH v12 03/13] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-4-ansuelsmth@gmail.com>

Document support for Airoha AN8855 5-port Gigabit Switch.

It does expose the 5 Internal PHYs on the MDIO bus and each port
can access the Switch register space by configurting the PHY page.

Each internal PHY might require calibration with the fused EFUSE on
the switch exposed by the Airoha AN8855 SoC NVMEM.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../net/dsa/airoha,an8855-switch.yaml         | 105 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml

diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
new file mode 100644
index 000000000000..63bcbebd6a29
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Gigabit Switch
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 is a 5-port Gigabit Switch.
+
+  It does expose the 5 Internal PHYs on the MDIO bus and each port
+  can access the Switch register space by configurting the PHY page.
+
+  Each internal PHY might require calibration with the fused EFUSE on
+  the switch exposed by the Airoha AN8855 SoC NVMEM.
+
+$ref: dsa.yaml#
+
+properties:
+  compatible:
+    const: airoha,an8855-switch
+
+  reset-gpios:
+    description:
+      GPIO to be used to reset the whole device
+    maxItems: 1
+
+  airoha,ext-surge:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Calibrate the internal PHY with the calibration values stored in EFUSE
+      for the r50Ohm values.
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    ethernet-switch {
+        compatible = "airoha,an8855-switch";
+        reset-gpios = <&pio 39 0>;
+
+        airoha,ext-surge;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port at 0 {
+                reg = <0>;
+                label = "lan1";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy1>;
+            };
+
+            port at 1 {
+                reg = <1>;
+                label = "lan2";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy2>;
+            };
+
+            port at 2 {
+                reg = <2>;
+                label = "lan3";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy3>;
+            };
+
+            port at 3 {
+                reg = <3>;
+                label = "lan4";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy4>;
+            };
+
+            port at 4 {
+                reg = <4>;
+                label = "wan";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy5>;
+            };
+
+            port at 5 {
+                reg = <5>;
+                label = "cpu";
+                ethernet = <&gmac0>;
+                phy-mode = "2500base-x";
+
+                fixed-link {
+                    speed = <2500>;
+                    full-duplex;
+                    pause;
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 1e8055b5e162..696ad8465ea8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -726,6 +726,7 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
 AIROHA ETHERNET DRIVER
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:49 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:49 +0100
Subject: [net-next PATCH v12 04/13] dt-bindings: net: Document support for AN8855 Switch Internal PHY
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-5-ansuelsmth@gmail.com>

Document support for AN8855 Switch Internal PHY.

Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
PHYs on the MDIO bus.

Each PHY might need to be calibrated to correctly work with the
use of the eFUSE provided by the Switch SoC. This can be enabled by
defining in the PHY node the "airoha,ext-surge" property.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/net/airoha,an8855-phy.yaml       | 93 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 94 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml

diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
new file mode 100644
index 000000000000..301c46f84904
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch Internal PHY
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
+  PHYs on the MDIO bus.
+
+  Each PHY might need to be calibrated to correctly work with the
+  use of the eFUSE provided by the Switch SoC.
+
+allOf:
+  - $ref: ethernet-phy.yaml#
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - ethernet-phy-idc0ff.0410
+  required:
+    - compatible
+
+properties:
+  reg:
+    maxItems: 1
+
+  airoha,ext-surge:
+    description: enable PHY calibration with the use of SoC eFUSE.
+
+  nvmem-cells:
+    items:
+      - description: phandle to SoC eFUSE tx_a
+      - description: phandle to SoC eFUSE tx_b
+      - description: phandle to SoC eFUSE tx_c
+      - description: phandle to SoC eFUSE tx_d
+
+  nvmem-cell-names:
+    items:
+      - const: tx_a
+      - const: tx_b
+      - const: tx_c
+      - const: tx_d
+
+required:
+  - compatible
+  - reg
+
+if:
+  required:
+    - airoha,ext-surge
+then:
+  required:
+    - nvmem-cells
+    - nvmem-cell-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet-phy at 1 {
+            compatible = "ethernet-phy-idc0ff.0410",
+                         "ethernet-phy-ieee802.3-c45";
+
+            reg = <1>;
+        };
+
+        ethernet-phy at 2 {
+            compatible = "ethernet-phy-idc0ff.0410",
+                         "ethernet-phy-ieee802.3-c45";
+
+            reg = <2>;
+
+            airoha,ext-surge;
+
+            nvmem-cells = <&shift_sel_port0_tx_a>,
+                <&shift_sel_port0_tx_b>,
+                <&shift_sel_port0_tx_c>,
+                <&shift_sel_port0_tx_d>;
+            nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 696ad8465ea8..45f4bb8deb0d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -726,6 +726,7 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:50 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:50 +0100
Subject: [net-next PATCH v12 05/13] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-6-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Switch SoC. This SoC expose various
peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.

It does also support i2c and timers but those are not currently
supported/used.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/mfd/airoha,an8855.yaml           | 186 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 187 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml

diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
new file mode 100644
index 000000000000..4853f37eb855
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
@@ -0,0 +1,186 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch SoC
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 Switch is a SoC that expose various peripherals like an
+  Ethernet Switch, a NVMEM provider and Ethernet PHYs.
+
+  It does also support i2c and timers but those are not currently
+  supported/used.
+
+properties:
+  compatible:
+    const: airoha,an8855
+
+  reg:
+    maxItems: 1
+
+  efuse:
+    type: object
+    $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
+    description:
+      EFUSE exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+
+  ethernet-switch:
+    type: object
+    $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
+    description:
+      Switch exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
+
+  mdio:
+    type: object
+    $ref: /schemas/net/airoha,an8855-mdio.yaml
+    description:
+      MDIO exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        soc at 1 {
+            compatible = "airoha,an8855";
+            reg = <1>;
+
+            efuse {
+                compatible = "airoha,an8855-efuse";
+
+                #nvmem-cell-cells = <0>;
+
+                nvmem-layout {
+                    compatible = "fixed-layout";
+                    #address-cells = <1>;
+                    #size-cells = <1>;
+
+                    shift_sel_port0_tx_a: shift-sel-port0-tx-a at c {
+                       reg = <0xc 0x4>;
+                    };
+
+                    shift_sel_port0_tx_b: shift-sel-port0-tx-b at 10 {
+                        reg = <0x10 0x4>;
+                    };
+
+                    shift_sel_port0_tx_c: shift-sel-port0-tx-c at 14 {
+                        reg = <0x14 0x4>;
+                    };
+
+                    shift_sel_port0_tx_d: shift-sel-port0-tx-d at 18 {
+                       reg = <0x18 0x4>;
+                    };
+
+                    shift_sel_port1_tx_a: shift-sel-port1-tx-a at 1c {
+                        reg = <0x1c 0x4>;
+                    };
+
+                    shift_sel_port1_tx_b: shift-sel-port1-tx-b at 20 {
+                        reg = <0x20 0x4>;
+                    };
+
+                    shift_sel_port1_tx_c: shift-sel-port1-tx-c at 24 {
+                       reg = <0x24 0x4>;
+                    };
+
+                    shift_sel_port1_tx_d: shift-sel-port1-tx-d at 28 {
+                        reg = <0x28 0x4>;
+                    };
+                };
+            };
+
+            ethernet-switch {
+                compatible = "airoha,an8855-switch";
+
+                reset-gpios = <&pio 39 0>;
+
+                airoha,ext-surge;
+
+                ports {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
+                    port at 0 {
+                        reg = <0>;
+                        label = "lan1";
+                        phy-mode = "internal";
+                        phy-handle = <&internal_phy1>;
+                    };
+
+                    port at 1 {
+                        reg = <1>;
+                        label = "lan2";
+                        phy-mode = "internal";
+                        phy-handle = <&internal_phy2>;
+                    };
+
+                    port at 5 {
+                        reg = <5>;
+                        label = "cpu";
+                        ethernet = <&gmac0>;
+                        phy-mode = "2500base-x";
+
+                        fixed-link {
+                            speed = <2500>;
+                            full-duplex;
+                            pause;
+                        };
+                    };
+                };
+            };
+
+            mdio {
+                compatible = "airoha,an8855-mdio";
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                internal_phy1: phy at 1 {
+                  compatible = "ethernet-phy-idc0ff.0410",
+                               "ethernet-phy-ieee802.3-c45";
+                  reg = <1>;
+
+                  airoha,ext-surge;
+
+                  nvmem-cells = <&shift_sel_port0_tx_a>,
+                      <&shift_sel_port0_tx_b>,
+                      <&shift_sel_port0_tx_c>,
+                      <&shift_sel_port0_tx_d>;
+                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+                };
+
+                internal_phy2: phy at 2 {
+                  compatible = "ethernet-phy-idc0ff.0410",
+                               "ethernet-phy-ieee802.3-c45";
+                  reg = <2>;
+
+                  airoha,ext-surge;
+
+                  nvmem-cells = <&shift_sel_port1_tx_a>,
+                      <&shift_sel_port1_tx_b>,
+                      <&shift_sel_port1_tx_c>,
+                      <&shift_sel_port1_tx_d>;
+                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 45f4bb8deb0d..b7075425c94e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -725,6 +725,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/mfd/airoha,an8855-mfd.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:51 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:51 +0100
Subject: [net-next PATCH v12 06/13] net: mdio: regmap: prepare support for multiple valid addr
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-7-ansuelsmth@gmail.com>

Rework the valid_addr and convert it to a mask in preparation for mdio
regmap to support multiple valid addr in the case the regmap can support
it.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 8a742a8d6387..810ba0a736f0 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -19,7 +19,7 @@
 
 struct mdio_regmap_priv {
 	struct regmap *regmap;
-	u8 valid_addr;
+	u32 valid_addr_mask;
 };
 
 static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
@@ -28,7 +28,7 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
 	unsigned int val;
 	int ret;
 
-	if (ctx->valid_addr != addr)
+	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
 	ret = regmap_read(ctx->regmap, regnum, &val);
@@ -43,7 +43,7 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
 {
 	struct mdio_regmap_priv *ctx = bus->priv;
 
-	if (ctx->valid_addr != addr)
+	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
 	return regmap_write(ctx->regmap, regnum, val);
@@ -65,7 +65,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 
 	mr = mii->priv;
 	mr->regmap = config->regmap;
-	mr->valid_addr = config->valid_addr;
+	mr->valid_addr_mask = BIT(config->valid_addr);
 
 	mii->name = DRV_NAME;
 	strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
@@ -74,7 +74,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	mii->write = mdio_regmap_write_c22;
 
 	if (config->autoscan)
-		mii->phy_mask = ~BIT(config->valid_addr);
+		mii->phy_mask = ~mr->valid_addr_mask;
 	else
 		mii->phy_mask = ~0;
 
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:52 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:52 +0100
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-8-ansuelsmth@gmail.com>

Add support for multiple valid addr for mdio regmap. This can be done by
defining the new valid_addr_mask value in the mdio regmap config.

In such case, the PHY address is appended to the regmap regnum right
after the first 16 bit of the PHY register used for the read/write
operation.

The passed regmap will then extract the address from the passed regnum
and execute the needed operations accordingly.

Notice that if valid_addr_mask, the unique valid_addr in config is
ignored.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 14 +++++++++++++-
 include/linux/mdio/mdio-regmap.h |  9 +++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 810ba0a736f0..8bfcd9e415c8 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -20,6 +20,7 @@
 struct mdio_regmap_priv {
 	struct regmap *regmap;
 	u32 valid_addr_mask;
+	bool append_addr;
 };
 
 static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
@@ -31,6 +32,9 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	if (ctx->append_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_PHY_ADDR, addr);
+
 	ret = regmap_read(ctx->regmap, regnum, &val);
 	if (ret < 0)
 		return ret;
@@ -46,6 +50,9 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	if (ctx->append_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_PHY_ADDR, addr);
+
 	return regmap_write(ctx->regmap, regnum, val);
 }
 
@@ -65,7 +72,12 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 
 	mr = mii->priv;
 	mr->regmap = config->regmap;
-	mr->valid_addr_mask = BIT(config->valid_addr);
+	if (config->valid_addr_mask) {
+		mr->valid_addr_mask = config->valid_addr_mask;
+		mr->append_addr = true;
+	} else {
+		mr->valid_addr_mask = BIT(config->valid_addr);
+	}
 
 	mii->name = DRV_NAME;
 	strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 679d9069846b..8c7061e39ccb 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -12,11 +12,20 @@
 struct device;
 struct regmap;
 
+/* If a non empty valid_addr_mask is passed, PHY address and
+ * read/write register are encoded in the regmap register
+ * by placing the register in the first 16 bits and the PHY address
+ * right after.
+ */
+#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
+#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
+
 struct mdio_regmap_config {
 	struct device *parent;
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
+	u32 valid_addr_mask;
 	bool autoscan;
 };
 
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:53 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:53 +0100
Subject: [net-next PATCH v12 08/13] net: mdio: regmap: add OF support
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-9-ansuelsmth@gmail.com>

Permit to pass the device node pointer to mdio regmap config and permit
mdio registration with an OF node to support DT PHY probe.

With the device node pointer NULL, the normal mdio registration is used.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 2 +-
 include/linux/mdio/mdio-regmap.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 8bfcd9e415c8..329839ab68e6 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -90,7 +90,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	else
 		mii->phy_mask = ~0;
 
-	rc = devm_mdiobus_register(dev, mii);
+	rc = devm_of_mdiobus_register(dev, mii, config->np);
 	if (rc) {
 		dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc);
 		return ERR_PTR(rc);
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 8c7061e39ccb..23fc2dd9d752 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -22,6 +22,7 @@ struct regmap;
 
 struct mdio_regmap_config {
 	struct device *parent;
+	struct device_node *np;
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:54 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:54 +0100
Subject: [net-next PATCH v12 09/13] mfd: an8855: Add support for Airoha AN8855 Switch MFD
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-10-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Switch MFD that provide support for a DSA
switch and a NVMEM provider. Also provide support for a virtual MDIO
passthrough as the PHYs address for the switch are shared with the switch
address.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                 |   1 +
 drivers/mfd/Kconfig         |  10 +
 drivers/mfd/Makefile        |   1 +
 drivers/mfd/airoha-an8855.c | 445 ++++++++++++++++++++++++++++++++++++
 4 files changed, 457 insertions(+)
 create mode 100644 drivers/mfd/airoha-an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b7075425c94e..5844addbda2b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -730,6 +730,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+F:	drivers/mfd/airoha-an8855.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6b0682af6e32..1b5abe5e2694 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -53,6 +53,16 @@ config MFD_ALTERA_SYSMGR
 	  using regmap_mmio accesses for ARM32 parts and SMC calls to
 	  EL3 for ARM64 parts.
 
+config MFD_AIROHA_AN8855
+	tristate "Airoha AN8855 Switch MFD"
+	select MFD_CORE
+	select MDIO_DEVICE
+	depends on NETDEVICES && OF
+	help
+	  Support for the Airoha AN8855 Switch MFD. This is a SoC Switch
+	  that provides various peripherals. Currently it provides a
+	  DSA switch and a NVMEM provider.
+
 config MFD_ACT8945A
 	tristate "Active-semi ACT8945A"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9220eaf7cf12..37677f65a981 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
 obj-$(CONFIG_MFD_88PM800)	+= 88pm800.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM886_PMIC)	+= 88pm886.o
+obj-$(CONFIG_MFD_AIROHA_AN8855)	+= airoha-an8855.o
 obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835-pm.o
diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
new file mode 100644
index 000000000000..0a6440bd4118
--- /dev/null
+++ b/drivers/mfd/airoha-an8855.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MFD driver for Airoha AN8855 Switch
+ */
+
+#include <linux/bitfield.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/core.h>
+#include <linux/mdio.h>
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+
+/* Register for hw trap status */
+#define AN8855_HWTRAP			0x1000009c
+
+#define AN8855_CREV			0x10005000
+#define   AN8855_ID			0x8855
+
+#define AN8855_RG_GPHY_AFE_PWD		0x1028c840
+
+/* MII Registers */
+#define AN8855_PHY_SELECT_PAGE		0x1f
+#define   AN8855_PHY_PAGE		GENMASK(2, 0)
+#define   AN8855_PHY_PAGE_STANDARD	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define   AN8855_PHY_PAGE_EXTENDED_1	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+#define   AN8855_PHY_PAGE_EXTENDED_4	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
+
+/* MII Registers Page 4 */
+#define AN8855_PBUS_MODE		0x10
+#define   AN8855_PBUS_MODE_ADDR_FIXED	0x0
+#define AN8855_PBUS_MODE_ADDR_INCR	BIT(15)
+#define AN8855_PBUS_WR_ADDR_HIGH	0x11
+#define AN8855_PBUS_WR_ADDR_LOW		0x12
+#define AN8855_PBUS_WR_DATA_HIGH	0x13
+#define AN8855_PBUS_WR_DATA_LOW		0x14
+#define AN8855_PBUS_RD_ADDR_HIGH	0x15
+#define AN8855_PBUS_RD_ADDR_LOW		0x16
+#define AN8855_PBUS_RD_DATA_HIGH	0x17
+#define AN8855_PBUS_RD_DATA_LOW		0x18
+
+struct an8855_mfd_priv {
+	struct mii_bus *bus;
+
+	unsigned int switch_addr;
+	u16 current_page;
+};
+
+static const struct mfd_cell an8855_mfd_devs[] = {
+	{
+		.name = "an8855-efuse",
+		.of_compatible = "airoha,an8855-efuse",
+	}, {
+		.name = "an8855-switch",
+		.of_compatible = "airoha,an8855-switch",
+	}, {
+		.name = "an8855-mdio",
+		.of_compatible = "airoha,an8855-mdio",
+	}
+};
+
+static int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id,
+			       u8 page) __must_hold(&priv->bus->mdio_lock)
+{
+	struct mii_bus *bus = priv->bus;
+	int ret;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page);
+	if (ret < 0)
+		dev_err_ratelimited(&bus->dev,
+				    "failed to set an8855 mii page\n");
+
+	/* Cache current page if next mii read/write is for switch */
+	priv->current_page = page;
+	return ret < 0 ? ret : 0;
+}
+
+static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
+			     u32 *val) __must_hold(&bus->mdio_lock)
+{
+	int lo, hi, ret;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+			      AN8855_PBUS_MODE_ADDR_FIXED);
+	if (ret < 0)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
+			      upper_16_bits(reg));
+	if (ret < 0)
+		goto err;
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
+			      lower_16_bits(reg));
+	if (ret < 0)
+		goto err;
+
+	hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
+	if (hi < 0) {
+		ret = hi;
+		goto err;
+	}
+	lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
+	if (lo < 0) {
+		ret = lo;
+		goto err;
+	}
+
+	*val = ((u16)hi << 16) | ((u16)lo & 0xffff);
+
+	return 0;
+err:
+	dev_err_ratelimited(&bus->dev,
+			    "failed to read an8855 register\n");
+	return ret;
+}
+
+static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+	struct an8855_mfd_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret < 0)
+		goto exit;
+
+	ret = an8855_mii_read32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
+			      u32 val) __must_hold(&bus->mdio_lock)
+{
+	int ret;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+			      AN8855_PBUS_MODE_ADDR_FIXED);
+	if (ret < 0)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
+			      upper_16_bits(reg));
+	if (ret < 0)
+		goto err;
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
+			      lower_16_bits(reg));
+	if (ret < 0)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
+			      upper_16_bits(val));
+	if (ret < 0)
+		goto err;
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
+			      lower_16_bits(val));
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	dev_err_ratelimited(&bus->dev,
+			    "failed to write an8855 register\n");
+	return ret;
+}
+
+static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
+{
+	struct an8855_mfd_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret < 0)
+		goto exit;
+
+	ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
+				     uint32_t write_val)
+{
+	struct an8855_mfd_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	u32 val;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret < 0)
+		goto exit;
+
+	ret = an8855_mii_read32(bus, addr, reg, &val);
+	if (ret < 0)
+		goto exit;
+
+	val &= ~mask;
+	val |= write_val;
+	ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static const struct regmap_range an8855_readable_ranges[] = {
+	regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
+	regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
+	regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
+	regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
+	regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
+	regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
+	regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
+	regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
+	regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
+	regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
+	regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
+	regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
+	regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
+	regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
+	regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
+	regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
+	regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
+	regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
+	regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
+	regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
+	regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
+	regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
+	regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
+	regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
+	regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
+	regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
+	regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
+};
+
+static const struct regmap_access_table an8855_readable_table = {
+	.yes_ranges = an8855_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
+};
+
+static const struct regmap_config an8855_regmap_config = {
+	.name = "switch",
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0xbfffffff,
+	.reg_read = an8855_regmap_read,
+	.reg_write = an8855_regmap_write,
+	.reg_update_bits = an8855_regmap_update_bits,
+	.disable_locking = true,
+	.rd_table = &an8855_readable_table,
+};
+
+static int an855_regmap_phy_reset_page(struct an8855_mfd_priv *priv,
+				       int phy) __must_hold(&priv->bus->mdio_lock)
+{
+	/* Check PHY page only for addr shared with switch */
+	if (phy != priv->switch_addr)
+		return 0;
+
+	/* Don't restore page if it's not set to switch page */
+	if (priv->current_page != FIELD_GET(AN8855_PHY_PAGE,
+					    AN8855_PHY_PAGE_EXTENDED_4))
+		return 0;
+
+	/* Restore page to 0, PHY might change page right after but that
+	 * will be ignored as it won't be a switch page.
+	 */
+	return an8855_mii_set_page(priv, phy, AN8855_PHY_PAGE_STANDARD);
+}
+
+static int an8855_regmap_phy_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+	struct an8855_mfd_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 phy_id, addr;
+	int ret;
+
+	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
+	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an855_regmap_phy_reset_page(priv, phy_id);
+	if (ret)
+		goto exit;
+
+	ret = __mdiobus_read(priv->bus, phy_id, addr);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+	return 0;
+}
+
+static int an8855_regmap_phy_write(void *ctx, uint32_t reg, uint32_t val)
+{
+	struct an8855_mfd_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 phy_id, addr;
+	int ret;
+
+	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
+	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an855_regmap_phy_reset_page(priv, phy_id);
+	if (ret)
+		goto exit;
+
+	ret = __mdiobus_write(priv->bus, phy_id, addr, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret;
+}
+
+/* Regmap for MDIO Passtrough
+ * PHY Addr and PHY Reg are encoded in the regmap register.
+ */
+static const struct regmap_config an8855_regmap_phy_config = {
+	.name = "phy",
+	.reg_bits = 20,
+	.val_bits = 16,
+	.reg_stride = 1,
+	.max_register = MDIO_REGMAP_PHY_ADDR | MDIO_REGMAP_PHY_REG,
+	.reg_read = an8855_regmap_phy_read,
+	.reg_write = an8855_regmap_phy_write,
+	.disable_locking = true,
+};
+
+static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
+{
+	u32 id;
+	int ret;
+
+	ret = regmap_read(regmap, AN8855_CREV, &id);
+	if (ret)
+		return ret;
+
+	if (id != AN8855_ID) {
+		dev_err(dev, "Switch ID detected %x but expected %x\n",
+			id, AN8855_ID);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int an8855_mfd_probe(struct mdio_device *mdiodev)
+{
+	struct regmap *regmap, *regmap_phy;
+	struct device *dev = &mdiodev->dev;
+	struct an8855_mfd_priv *priv;
+	struct gpio_desc *reset_gpio;
+	u32 val;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->bus = mdiodev->bus;
+	priv->switch_addr = mdiodev->addr;
+	/* no DMA for mdiobus, mute warning for DMA mask not set */
+	dev->dma_mask = &dev->coherent_dma_mask;
+
+	regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "regmap initialization failed\n");
+
+	regmap_phy = devm_regmap_init(dev, NULL, priv, &an8855_regmap_phy_config);
+	if (IS_ERR(regmap_phy))
+		return dev_err_probe(dev, PTR_ERR(regmap_phy),
+				     "regmap phy initialization failed\n");
+
+	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(reset_gpio))
+		return PTR_ERR(reset_gpio);
+
+	if (reset_gpio) {
+		usleep_range(100000, 150000);
+		gpiod_set_value_cansleep(reset_gpio, 0);
+		usleep_range(100000, 150000);
+		gpiod_set_value_cansleep(reset_gpio, 1);
+
+		/* Poll HWTRAP reg to wait for Switch to fully Init */
+		ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
+					       val, 20, 200000);
+		if (ret)
+			return ret;
+	}
+
+	ret = an8855_read_switch_id(dev, regmap);
+	if (ret)
+		return ret;
+
+	/* Release global PHY power down */
+	ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
+	if (ret)
+		return ret;
+
+	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_mfd_devs,
+				    ARRAY_SIZE(an8855_mfd_devs), NULL, 0,
+				    NULL);
+}
+
+static const struct of_device_id an8855_mfd_of_match[] = {
+	{ .compatible = "airoha,an8855" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_mfd_of_match);
+
+static struct mdio_driver an8855_mfd_driver = {
+	.probe = an8855_mfd_probe,
+	.mdiodrv.driver = {
+		.name = "an8855",
+		.of_match_table = an8855_mfd_of_match,
+	},
+};
+mdio_module_driver(an8855_mfd_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:55 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:55 +0100
Subject: [net-next PATCH v12 10/13] net: mdio: Add Airoha AN8855 Switch MDIO Passtrough
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-11-ansuelsmth@gmail.com>

Add Airoha AN8855 Switch driver to register a MDIO passtrough as switch
address is shared with the internal PHYs and require additional page
handling.

This requires the upper Switch MFD to be probed and init to actually
work.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                    |  1 +
 drivers/net/mdio/Kconfig       | 10 +++++++
 drivers/net/mdio/Makefile      |  1 +
 drivers/net/mdio/mdio-an8855.c | 48 ++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+)
 create mode 100644 drivers/net/mdio/mdio-an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 5844addbda2b..8c83c446a69d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -731,6 +731,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 F:	drivers/mfd/airoha-an8855.c
+F:	drivers/net/mdio/mdio-an8855.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 4a7a303be2f7..e31a37064934 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -61,6 +61,16 @@ config MDIO_XGENE
 	  This module provides a driver for the MDIO busses found in the
 	  APM X-Gene SoC's.
 
+config MDIO_AN8855
+	tristate "Airoha AN8855 Switch MDIO bus controller"
+	depends on MFD_AIROHA_AN8855
+	depends on OF_MDIO
+	select MDIO_REGMAP
+	help
+	  This module provides a driver for the Airoha AN8855 Switch
+	  that requires a MDIO passtrough as switch address is shared
+	  with the internal PHYs and requires additional page handling.
+
 config MDIO_ASPEED
 	tristate "ASPEED MDIO bus controller"
 	depends on ARCH_ASPEED || COMPILE_TEST
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 1015f0db4531..546c4e55b475 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_ACPI_MDIO)		+= acpi_mdio.o
 obj-$(CONFIG_FWNODE_MDIO)	+= fwnode_mdio.o
 obj-$(CONFIG_OF_MDIO)		+= of_mdio.o
 
+obj-$(CONFIG_MDIO_AN8855)		+= mdio-an8855.o
 obj-$(CONFIG_MDIO_ASPEED)		+= mdio-aspeed.o
 obj-$(CONFIG_MDIO_BCM_IPROC)		+= mdio-bcm-iproc.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)		+= mdio-bcm-unimac.o
diff --git a/drivers/net/mdio/mdio-an8855.c b/drivers/net/mdio/mdio-an8855.c
new file mode 100644
index 000000000000..d45f71c4b0b1
--- /dev/null
+++ b/drivers/net/mdio/mdio-an8855.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MDIO passthrough driver for Airoha AN8855 Switch
+ */
+
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static int an8855_mdio_probe(struct platform_device *pdev)
+{
+	struct mdio_regmap_config mrc = { };
+	struct device *dev = &pdev->dev;
+	struct mii_bus *bus;
+
+	mrc.regmap = dev_get_regmap(dev->parent, "phy");
+	mrc.parent = dev;
+	mrc.valid_addr_mask = GENMASK(31, 0);
+	mrc.autoscan = true;
+	mrc.np = dev->of_node;
+	snprintf(mrc.name, MII_BUS_ID_SIZE, KBUILD_MODNAME);
+
+	bus = devm_mdio_regmap_register(dev, &mrc);
+	if (IS_ERR(bus))
+		return dev_err_probe(dev, PTR_ERR(bus), "failed to register MDIO bus\n");
+
+	return 0;
+}
+
+static const struct of_device_id an8855_mdio_of_match[] = {
+	{ .compatible = "airoha,an8855-mdio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_mdio_of_match);
+
+static struct platform_driver an8855_mdio_driver = {
+	.probe	= an8855_mdio_probe,
+	.driver = {
+		.name = "an8855-mdio",
+		.of_match_table = an8855_mdio_of_match,
+	},
+};
+module_platform_driver(an8855_mdio_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 MDIO passthrough");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:56 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:56 +0100
Subject: [net-next PATCH v12 11/13] nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-12-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Switch EFUSE. These EFUSE might be used
for calibration data for the internal switch PHYs.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                  |  1 +
 drivers/nvmem/Kconfig        | 11 +++++++
 drivers/nvmem/Makefile       |  2 ++
 drivers/nvmem/an8855-efuse.c | 63 ++++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+)
 create mode 100644 drivers/nvmem/an8855-efuse.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8c83c446a69d..938b81767862 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -732,6 +732,7 @@ F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 F:	drivers/mfd/airoha-an8855.c
 F:	drivers/net/mdio/mdio-an8855.c
+F:	drivers/nvmem/an8855-efuse.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 8671b7c974b9..ca96c6ea685a 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -28,6 +28,17 @@ source "drivers/nvmem/layouts/Kconfig"
 
 # Devices
 
+config NVMEM_AN8855_EFUSE
+	tristate "Airoha AN8855 eFuse support"
+	depends on MFD_AIROHA_AN8855 || COMPILE_TEST
+	help
+	  Say y here to enable support for reading eFuses on Airoha AN8855
+	  Switch. These are e.g. used to store factory programmed
+	  calibration data required for the PHY.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called nvmem-an8855-efuse.
+
 config NVMEM_APPLE_EFUSES
 	tristate "Apple eFuse support"
 	depends on ARCH_APPLE || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 5b77bbb6488b..c732132c0e45 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -10,6 +10,8 @@ nvmem_layouts-y			:= layouts.o
 obj-y				+= layouts/
 
 # Devices
+obj-$(CONFIG_NVMEM_AN8855_EFUSE)	+= nvmem-an8855-efuse.o
+nvmem-an8855-efuse-y 			:= an8855-efuse.o
 obj-$(CONFIG_NVMEM_APPLE_EFUSES)	+= nvmem-apple-efuses.o
 nvmem-apple-efuses-y 			:= apple-efuses.o
 obj-$(CONFIG_NVMEM_BCM_OCOTP)		+= nvmem-bcm-ocotp.o
diff --git a/drivers/nvmem/an8855-efuse.c b/drivers/nvmem/an8855-efuse.c
new file mode 100644
index 000000000000..cd1564379098
--- /dev/null
+++ b/drivers/nvmem/an8855-efuse.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Airoha AN8855 Switch EFUSE Driver
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define AN8855_EFUSE_CELL		50
+
+#define AN8855_EFUSE_DATA0		0x1000a500
+#define   AN8855_EFUSE_R50O		GENMASK(30, 24)
+
+static int an8855_efuse_read(void *context, unsigned int offset,
+			     void *val, size_t bytes)
+{
+	struct regmap *regmap = context;
+
+	return regmap_bulk_read(regmap, AN8855_EFUSE_DATA0 + offset,
+				val, bytes / sizeof(u32));
+}
+
+static int an8855_efuse_probe(struct platform_device *pdev)
+{
+	struct nvmem_config an8855_nvmem_config = {
+		.name = "an8855-efuse",
+		.size = AN8855_EFUSE_CELL * sizeof(u32),
+		.stride = sizeof(u32),
+		.word_size = sizeof(u32),
+		.reg_read = an8855_efuse_read,
+	};
+	struct device *dev = &pdev->dev;
+	struct nvmem_device *nvmem;
+
+	/* Assign NVMEM priv to MFD regmap */
+	an8855_nvmem_config.priv = dev_get_regmap(dev->parent, "switch");
+	an8855_nvmem_config.dev = dev;
+	nvmem = devm_nvmem_register(dev, &an8855_nvmem_config);
+
+	return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static const struct of_device_id an8855_efuse_of_match[] = {
+	{ .compatible = "airoha,an8855-efuse", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_efuse_of_match);
+
+static struct platform_driver an8855_efuse_driver = {
+	.probe = an8855_efuse_probe,
+	.driver = {
+		.name = "an8855-efuse",
+		.of_match_table = an8855_efuse_of_match,
+	},
+};
+module_platform_driver(an8855_efuse_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 Switch EFUSE");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:57 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:57 +0100
Subject: [net-next PATCH v12 12/13] net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-13-ansuelsmth@gmail.com>

Add Airoha AN8855 5-Port Gigabit DSA switch. Switch can support
10M, 100M, 1Gb, 2.5G and 5G Ethernet Speed but 5G is currently error out
as it's not currently supported as requires additional configuration for
the PCS.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS              |    2 +
 drivers/net/dsa/Kconfig  |    9 +
 drivers/net/dsa/Makefile |    1 +
 drivers/net/dsa/an8855.c | 2296 ++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/an8855.h |  771 +++++++++++++
 5 files changed, 3079 insertions(+)
 create mode 100644 drivers/net/dsa/an8855.c
 create mode 100644 drivers/net/dsa/an8855.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 938b81767862..bd95c684d480 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -731,6 +731,8 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 F:	drivers/mfd/airoha-an8855.c
+F:	drivers/net/dsa/an8855.c
+F:	drivers/net/dsa/an8855.h
 F:	drivers/net/mdio/mdio-an8855.c
 F:	drivers/nvmem/an8855-efuse.c
 
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index bb9812b3b0e8..5b02f0d74af3 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -24,6 +24,15 @@ config NET_DSA_LOOP
 	  This enables support for a fake mock-up switch chip which
 	  exercises the DSA APIs.
 
+config NET_DSA_AN8855
+	tristate "Airoha AN8855 Ethernet switch support"
+	depends on MFD_AIROHA_AN8855 || COMPILE_TEST
+	depends on NET_DSA
+	select NET_DSA_TAG_MTK
+	help
+	  This enables support for the Ethernet switch inside the
+	  Airoha AN8855 chip.
+
 source "drivers/net/dsa/hirschmann/Kconfig"
 
 config NET_DSA_LANTIQ_GSWIP
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index cb9a97340e58..a74afb41a491 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP)	+= dsa_loop.o
 ifdef CONFIG_NET_DSA_LOOP
 obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdinfo.o
 endif
+obj-$(CONFIG_NET_DSA_AN8855)	+= an8855.o
 obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
 obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530.o
 obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
diff --git a/drivers/net/dsa/an8855.c b/drivers/net/dsa/an8855.c
new file mode 100644
index 000000000000..95998c88cbd7
--- /dev/null
+++ b/drivers/net/dsa/an8855.c
@@ -0,0 +1,2296 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Airoha AN8855 DSA Switch driver
+ * Copyright (C) 2023 Min Yao <min.yao at airoha.com>
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth at gmail.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/if_bridge.h>
+#include <linux/iopoll.h>
+#include <linux/netdevice.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phylink.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <net/dsa.h>
+
+#include "an8855.h"
+
+static const struct an8855_mib_desc an8855_mib[] = {
+	MIB_DESC(1, AN8855_PORT_MIB_TX_DROP, "TxDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_TX_CRC_ERR, "TxCrcErr"),
+	MIB_DESC(1, AN8855_PORT_MIB_TX_COLLISION, "TxCollision"),
+	MIB_DESC(1, AN8855_PORT_MIB_TX_OVERSIZE_DROP, "TxOversizeDrop"),
+	MIB_DESC(2, AN8855_PORT_MIB_TX_BAD_PKT_BYTES, "TxBadPktBytes"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_DROP, "RxDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_FILTERING, "RxFiltering"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_CRC_ERR, "RxCrcErr"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_CTRL_DROP, "RxCtrlDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_INGRESS_DROP, "RxIngressDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_RX_ARL_DROP, "RxArlDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_FLOW_CONTROL_DROP, "FlowControlDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_WRED_DROP, "WredDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_MIRROR_DROP, "MirrorDrop"),
+	MIB_DESC(2, AN8855_PORT_MIB_RX_BAD_PKT_BYTES, "RxBadPktBytes"),
+	MIB_DESC(1, AN8855_PORT_MIB_RXS_FLOW_SAMPLING_PKT_DROP, "RxsFlowSamplingPktDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_RXS_FLOW_TOTAL_PKT_DROP, "RxsFlowTotalPktDrop"),
+	MIB_DESC(1, AN8855_PORT_MIB_PORT_CONTROL_DROP, "PortControlDrop"),
+};
+
+static int
+an8855_mib_init(struct an8855_priv *priv)
+{
+	int ret;
+
+	ret = regmap_write(priv->regmap, AN8855_MIB_CCR,
+			   AN8855_CCR_MIB_ENABLE);
+	if (ret)
+		return ret;
+
+	return regmap_write(priv->regmap, AN8855_MIB_CCR,
+			    AN8855_CCR_MIB_ACTIVATE);
+}
+
+static void an8855_fdb_write(struct an8855_priv *priv, u16 vid,
+			     u8 port_mask, const u8 *mac,
+			     bool add) __must_hold(&priv->reg_mutex)
+{
+	u32 mac_reg[2] = { };
+	u32 reg;
+	int ret;
+
+	mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC0, mac[0]);
+	mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC1, mac[1]);
+	mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC2, mac[2]);
+	mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC3, mac[3]);
+	mac_reg[1] |= FIELD_PREP(AN8855_ATA2_MAC4, mac[4]);
+	mac_reg[1] |= FIELD_PREP(AN8855_ATA2_MAC5, mac[5]);
+
+	ret = regmap_bulk_write(priv->regmap, AN8855_ATA1, mac_reg,
+				ARRAY_SIZE(mac_reg));
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to write FDB entry: %d\n", ret);
+		return;
+	}
+
+	reg = AN8855_ATWD_IVL;
+	if (add)
+		reg |= AN8855_ATWD_VLD;
+	reg |= FIELD_PREP(AN8855_ATWD_VID, vid);
+	reg |= FIELD_PREP(AN8855_ATWD_FID, AN8855_FID_BRIDGED);
+	ret = regmap_write(priv->regmap, AN8855_ATWD, reg);
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to write ATWD entry: %d\n", ret);
+		return;
+	}
+	ret = regmap_write(priv->regmap, AN8855_ATWD2,
+			   FIELD_PREP(AN8855_ATWD2_PORT, port_mask));
+	if (ret)
+		dev_err(priv->ds->dev, "failed to write ATWD2 entry: %d\n", ret);
+}
+
+static void an8855_fdb_read(struct an8855_priv *priv, struct an8855_fdb *fdb)
+{
+	u32 reg[4];
+	int ret;
+
+	ret = regmap_bulk_read(priv->regmap, AN8855_ATRD0, reg,
+			       ARRAY_SIZE(reg));
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to read FDB entry: %d\n", ret);
+		return;
+	}
+
+	fdb->live = FIELD_GET(AN8855_ATRD0_LIVE, reg[0]);
+	fdb->type = FIELD_GET(AN8855_ATRD0_TYPE, reg[0]);
+	fdb->ivl = FIELD_GET(AN8855_ATRD0_IVL, reg[0]);
+	fdb->vid = FIELD_GET(AN8855_ATRD0_VID, reg[0]);
+	fdb->fid = FIELD_GET(AN8855_ATRD0_FID, reg[0]);
+	fdb->aging = FIELD_GET(AN8855_ATRD1_AGING, reg[1]);
+	fdb->port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, reg[3]);
+	fdb->mac[0] = FIELD_GET(AN8855_ATRD2_MAC0, reg[2]);
+	fdb->mac[1] = FIELD_GET(AN8855_ATRD2_MAC1, reg[2]);
+	fdb->mac[2] = FIELD_GET(AN8855_ATRD2_MAC2, reg[2]);
+	fdb->mac[3] = FIELD_GET(AN8855_ATRD2_MAC3, reg[2]);
+	fdb->mac[4] = FIELD_GET(AN8855_ATRD1_MAC4, reg[1]);
+	fdb->mac[5] = FIELD_GET(AN8855_ATRD1_MAC5, reg[1]);
+	fdb->noarp = !!FIELD_GET(AN8855_ATRD0_ARP, reg[0]);
+}
+
+static int an8855_fdb_cmd(struct an8855_priv *priv, u32 cmd,
+			  u32 *rsp) __must_hold(&priv->reg_mutex)
+{
+	u32 val;
+	int ret;
+
+	/* Set the command operating upon the MAC address entries */
+	val = AN8855_ATC_BUSY | cmd;
+	ret = regmap_write(priv->regmap, AN8855_ATC, val);
+	if (ret)
+		return ret;
+
+	ret = regmap_read_poll_timeout(priv->regmap, AN8855_ATC, val,
+				       !(val & AN8855_ATC_BUSY), 20, 200000);
+	if (ret)
+		return ret;
+
+	if (rsp)
+		*rsp = val;
+
+	return 0;
+}
+
+static void
+an8855_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+	struct dsa_port *dp = dsa_to_port(ds, port);
+	struct an8855_priv *priv = ds->priv;
+	bool learning = false;
+	u32 stp_state;
+	int ret;
+
+	switch (state) {
+	case BR_STATE_DISABLED:
+		stp_state = AN8855_STP_DISABLED;
+		break;
+	case BR_STATE_BLOCKING:
+		stp_state = AN8855_STP_BLOCKING;
+		break;
+	case BR_STATE_LISTENING:
+		stp_state = AN8855_STP_LISTENING;
+		break;
+	case BR_STATE_LEARNING:
+		stp_state = AN8855_STP_LEARNING;
+		learning = dp->learning;
+		break;
+	case BR_STATE_FORWARDING:
+		learning = dp->learning;
+		fallthrough;
+	default:
+		stp_state = AN8855_STP_FORWARDING;
+		break;
+	}
+
+	ret = regmap_update_bits(priv->regmap, AN8855_SSP_P(port),
+				 AN8855_FID_PST_MASK(AN8855_FID_BRIDGED),
+				 AN8855_FID_PST_VAL(AN8855_FID_BRIDGED, stp_state));
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to update SSP reg: %d\n", ret);
+		return;
+	}
+
+	ret = regmap_update_bits(priv->regmap, AN8855_PSC_P(port), AN8855_SA_DIS,
+				 learning ? 0 : AN8855_SA_DIS);
+	if (ret)
+		dev_err(priv->ds->dev, "failed to update learn reg: %d\n", ret);
+}
+
+static void an8855_port_fast_age(struct dsa_switch *ds, int port)
+{
+	struct an8855_priv *priv = ds->priv;
+	int ret;
+
+	/* Set to clean Dynamic entry */
+	ret = regmap_write(priv->regmap, AN8855_ATA2, AN8855_ATA2_TYPE);
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to update ATA2 reg: %d\n", ret);
+		return;
+	}
+
+	/* Set Port */
+	ret = regmap_write(priv->regmap, AN8855_ATWD2,
+			   FIELD_PREP(AN8855_ATWD2_PORT, BIT(port)));
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to update ATWD2 reg: %d\n", ret);
+		return;
+	}
+
+	/* Flush Dynamic entry at port */
+	ret = an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_TYPE_PORT) |
+			     AN8855_FDB_FLUSH, NULL);
+	if (ret)
+		dev_err(priv->ds->dev, "failed to send FDB cmd: %d\n", ret);
+}
+
+static int an8855_update_port_member(struct dsa_switch *ds, int port,
+				     const struct net_device *bridge_dev,
+				     bool join)
+{
+	struct an8855_priv *priv = ds->priv;
+	bool isolated, other_isolated;
+	struct dsa_port *dp;
+	u32 port_mask = 0;
+	int ret;
+
+	isolated = !!(priv->port_isolated_map & BIT(port));
+
+	dsa_switch_for_each_user_port(dp, ds) {
+		if (dp->index == port)
+			continue;
+
+		if (!dsa_port_offloads_bridge_dev(dp, bridge_dev))
+			continue;
+
+		other_isolated = !!(priv->port_isolated_map & BIT(dp->index));
+		port_mask |= BIT(dp->index);
+		/* Add/remove this port to the portvlan mask of the other
+		 * ports in the bridge
+		 */
+		if (join && !(isolated && other_isolated))
+			ret = regmap_set_bits(priv->regmap,
+					      AN8855_PORTMATRIX_P(dp->index),
+					      FIELD_PREP(AN8855_USER_PORTMATRIX,
+							 BIT(port)));
+		else
+			ret = regmap_clear_bits(priv->regmap,
+						AN8855_PORTMATRIX_P(dp->index),
+						FIELD_PREP(AN8855_USER_PORTMATRIX,
+							   BIT(port)));
+		if (ret)
+			return ret;
+	}
+
+	/* Add/remove all other ports to this port's portvlan mask */
+	return regmap_update_bits(priv->regmap, AN8855_PORTMATRIX_P(port),
+				  AN8855_USER_PORTMATRIX,
+				  join ? port_mask : ~port_mask);
+}
+
+static int an8855_port_pre_bridge_flags(struct dsa_switch *ds, int port,
+					struct switchdev_brport_flags flags,
+					struct netlink_ext_ack *extack)
+{
+	if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
+			   BR_BCAST_FLOOD | BR_ISOLATED))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int an8855_port_bridge_flags(struct dsa_switch *ds, int port,
+				    struct switchdev_brport_flags flags,
+				    struct netlink_ext_ack *extack)
+{
+	struct an8855_priv *priv = ds->priv;
+	int ret;
+
+	if (flags.mask & BR_LEARNING) {
+		ret = regmap_update_bits(priv->regmap, AN8855_PSC_P(port), AN8855_SA_DIS,
+					 flags.val & BR_LEARNING ? 0 : AN8855_SA_DIS);
+		if (ret)
+			return ret;
+	}
+
+	if (flags.mask & BR_FLOOD) {
+		ret = regmap_update_bits(priv->regmap, AN8855_UNUF, BIT(port),
+					 flags.val & BR_FLOOD ? BIT(port) : 0);
+		if (ret)
+			return ret;
+	}
+
+	if (flags.mask & BR_MCAST_FLOOD) {
+		ret = regmap_update_bits(priv->regmap, AN8855_UNMF, BIT(port),
+					 flags.val & BR_MCAST_FLOOD ? BIT(port) : 0);
+		if (ret)
+			return ret;
+
+		ret = regmap_update_bits(priv->regmap, AN8855_UNIPMF, BIT(port),
+					 flags.val & BR_MCAST_FLOOD ? BIT(port) : 0);
+		if (ret)
+			return ret;
+	}
+
+	if (flags.mask & BR_BCAST_FLOOD) {
+		ret = regmap_update_bits(priv->regmap, AN8855_BCF, BIT(port),
+					 flags.val & BR_BCAST_FLOOD ? BIT(port) : 0);
+		if (ret)
+			return ret;
+	}
+
+	if (flags.mask & BR_ISOLATED) {
+		struct dsa_port *dp = dsa_to_port(ds, port);
+		struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp);
+
+		if (flags.val & BR_ISOLATED)
+			priv->port_isolated_map |= BIT(port);
+		else
+			priv->port_isolated_map &= ~BIT(port);
+
+		ret = an8855_update_port_member(ds, port, bridge_dev, true);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int an8855_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
+{
+	struct an8855_priv *priv = ds->priv;
+	u32 age_count, age_unit, val;
+
+	/* Convert msec in AN8855_L2_AGING_MS_CONSTANT counter */
+	val = msecs / AN8855_L2_AGING_MS_CONSTANT;
+	/* Derive the count unit */
+	age_unit = val / FIELD_MAX(AN8855_AGE_UNIT);
+	/* Get the count in unit, age_unit is always incremented by 1 internally */
+	age_count = val / (age_unit + 1);
+
+	return regmap_update_bits(priv->regmap, AN8855_AAC,
+				  AN8855_AGE_CNT | AN8855_AGE_UNIT,
+				  FIELD_PREP(AN8855_AGE_CNT, age_count) |
+				  FIELD_PREP(AN8855_AGE_UNIT, age_unit));
+}
+
+static int an8855_port_bridge_join(struct dsa_switch *ds, int port,
+				   struct dsa_bridge bridge,
+				   bool *tx_fwd_offload,
+				   struct netlink_ext_ack *extack)
+{
+	struct an8855_priv *priv = ds->priv;
+	int ret;
+
+	ret = an8855_update_port_member(ds, port, bridge.dev, true);
+	if (ret)
+		return ret;
+
+	/* Set to fallback mode for independent VLAN learning if in a bridge */
+	return regmap_update_bits(priv->regmap, AN8855_PCR_P(port),
+				  AN8855_PORT_VLAN,
+				  FIELD_PREP(AN8855_PORT_VLAN,
+					     AN8855_PORT_FALLBACK_MODE));
+}
+
+static void an8855_port_bridge_leave(struct dsa_switch *ds, int port,
+				     struct dsa_bridge bridge)
+{
+	struct an8855_priv *priv = ds->priv;
+	int ret;
+
+	ret = an8855_update_port_member(ds, port, bridge.dev, false);
+	if (ret) {
+		dev_err(priv->ds->dev, "failed to update port member: %d\n", ret);
+		return;
+	}
+
+	/* When a port is removed from the bridge, the port would be set up
+	 * back to the default as is at initial boot which is a VLAN-unaware
+	 * port.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_PCR_P(port),
+				 AN8855_PORT_VLAN,
+				 FIELD_PREP(AN8855_PORT_VLAN,
+					    AN8855_PORT_MATRIX_MODE));
+	if (ret)
+		dev_err(priv->ds->dev, "failed to update PCR reg: %d\n", ret);
+}
+
+static int an8855_port_fdb_add(struct dsa_switch *ds, int port,
+			       const unsigned char *addr, u16 vid,
+			       struct dsa_db db)
+{
+	struct an8855_priv *priv = ds->priv;
+	u8 port_mask = BIT(port);
+	int ret;
+
+	/* With VLAN-Unaware entry, set vid to default vid */
+	if (!vid)
+		vid = AN8855_PORT_VID_DEFAULT;
+
+	mutex_lock(&priv->reg_mutex);
+	an8855_fdb_write(priv, vid, port_mask, addr, true);
+	ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static int an8855_port_fdb_del(struct dsa_switch *ds, int port,
+			       const unsigned char *addr, u16 vid,
+			       struct dsa_db db)
+{
+	struct an8855_priv *priv = ds->priv;
+	u8 port_mask = BIT(port);
+	int ret;
+
+	/* With VLAN-Unaware entry, set vid to default vid */
+	if (!vid)
+		vid = AN8855_PORT_VID_DEFAULT;
+
+	mutex_lock(&priv->reg_mutex);
+	an8855_fdb_write(priv, vid, port_mask, addr, false);
+	ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static int an8855_port_fdb_dump(struct dsa_switch *ds, int port,
+				dsa_fdb_dump_cb_t *cb, void *data)
+{
+	struct an8855_priv *priv = ds->priv;
+	int banks, count = 0;
+	u32 rsp;
+	int ret;
+	int i;
+
+	mutex_lock(&priv->reg_mutex);
+
+	/* Load search port */
+	ret = regmap_write(priv->regmap, AN8855_ATWD2,
+			   FIELD_PREP(AN8855_ATWD2_PORT, BIT(port)));
+	if (ret)
+		goto exit;
+	ret = an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_PORT) |
+			     AN8855_FDB_START, &rsp);
+	if (ret < 0)
+		goto exit;
+
+	do {
+		/* From response get the number of banks to read, exit if 0 */
+		banks = FIELD_GET(AN8855_ATC_HIT, rsp);
+		if (!banks)
+			break;
+
+		/* Each banks have 4 entry */
+		for (i = 0; i < 4; i++) {
+			struct an8855_fdb _fdb = {  };
+
+			count++;
+
+			/* Check if bank is present */
+			if (!(banks & BIT(i)))
+				continue;
+
+			/* Select bank entry index */
+			ret = regmap_write(priv->regmap, AN8855_ATRDS,
+					   FIELD_PREP(AN8855_ATRD_SEL, i));
+			if (ret)
+				break;
+			/* wait 1ms for the bank entry to be filled */
+			usleep_range(1000, 1500);
+			an8855_fdb_read(priv, &_fdb);
+
+			if (!_fdb.live)
+				continue;
+			ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, data);
+			if (ret < 0)
+				break;
+		}
+
+		/* Stop if reached max FDB number */
+		if (count >= AN8855_NUM_FDB_RECORDS)
+			break;
+
+		/* Read next bank */
+		ret = an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_PORT) |
+				     AN8855_FDB_NEXT, &rsp);
+		if (ret < 0)
+			break;
+	} while (true);
+
+exit:
+	mutex_unlock(&priv->reg_mutex);
+	return ret;
+}
+
+static int an8855_vlan_cmd(struct an8855_priv *priv, enum an8855_vlan_cmd cmd,
+			   u16 vid) __must_hold(&priv->reg_mutex)
+{
+	u32 val;
+	int ret;
+
+	val = AN8855_VTCR_BUSY | FIELD_PREP(AN8855_VTCR_FUNC, cmd) |
+	      FIELD_PREP(AN8855_VTCR_VID, vid);
+	ret = regmap_write(priv->regmap, AN8855_VTCR, val);
+	if (ret)
+		return ret;
+
+	return regmap_read_poll_timeout(priv->regmap, AN8855_VTCR, val,
+					!(val & AN8855_VTCR_BUSY), 20, 200000);
+}
+
+static int an8855_vlan_add(struct an8855_priv *priv, u8 port, u16 vid,
+			   bool untagged) __must_hold(&priv->reg_mutex)
+{
+	u32 port_mask;
+	u32 val;
+	int ret;
+
+	/* Fetch entry */
+	ret = an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(priv->regmap, AN8855_VARD0, &val);
+	if (ret)
+		return ret;
+	port_mask = FIELD_GET(AN8855_VA0_PORT, val) | BIT(port);
+
+	/* Validate the entry with independent learning, create egress tag per
+	 * VLAN and joining the port as one of the port members.
+	 */
+	val = (val & AN8855_VA0_ETAG) | AN8855_VA0_IVL_MAC |
+	      AN8855_VA0_VTAG_EN | AN8855_VA0_VLAN_VALID |
+	      FIELD_PREP(AN8855_VA0_PORT, port_mask) |
+	      FIELD_PREP(AN8855_VA0_FID, AN8855_FID_BRIDGED);
+	ret = regmap_write(priv->regmap, AN8855_VAWD0, val);
+	if (ret)
+		return ret;
+	ret = regmap_write(priv->regmap, AN8855_VAWD1, 0);
+	if (ret)
+		return ret;
+
+	/* CPU port is always taken as a tagged port for serving more than one
+	 * VLANs across and also being applied with egress type stack mode for
+	 * that VLAN tags would be appended after hardware special tag used as
+	 * DSA tag.
+	 */
+	if (port == AN8855_CPU_PORT)
+		val = AN8855_VLAN_EGRESS_STACK;
+	/* Decide whether adding tag or not for those outgoing packets from the
+	 * port inside the VLAN.
+	 */
+	else
+		val = untagged ? AN8855_VLAN_EGRESS_UNTAG : AN8855_VLAN_EGRESS_TAG;
+	ret = regmap_update_bits(priv->regmap, AN8855_VAWD0,
+				 AN8855_VA0_ETAG_PORT_MASK(port),
+				 AN8855_VA0_ETAG_PORT_VAL(port, val));
+	if (ret)
+		return ret;
+
+	/* Flush result to hardware */
+	return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid);
+}
+
+static int an8855_vlan_del(struct an8855_priv *priv, u8 port,
+			   u16 vid) __must_hold(&priv->reg_mutex)
+{
+	u32 port_mask;
+	u32 val;
+	int ret;
+
+	/* Fetch entry */
+	ret = an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(priv->regmap, AN8855_VARD0, &val);
+	if (ret)
+		return ret;
+	port_mask = FIELD_GET(AN8855_VA0_PORT, val) & ~BIT(port);
+
+	if (!(val & AN8855_VA0_VLAN_VALID)) {
+		dev_err(priv->ds->dev, "Cannot be deleted due to invalid entry: %d\n", ret);
+		return -EINVAL;
+	}
+
+	if (port_mask) {
+		val = (val & AN8855_VA0_ETAG) | AN8855_VA0_IVL_MAC |
+		       AN8855_VA0_VTAG_EN | AN8855_VA0_VLAN_VALID |
+		       FIELD_PREP(AN8855_VA0_PORT, port_mask);
+		ret = regmap_write(priv->regmap, AN8855_VAWD0, val);
+		if (ret)
+			return ret;
+	} else {
+		ret = regmap_write(priv->regmap, AN8855_VAWD0, 0);
+		if (ret)
+			return ret;
+	}
+	ret = regmap_write(priv->regmap, AN8855_VAWD1, 0);
+	if (ret)
+		return ret;
+
+	/* Flush result to hardware */
+	return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid);
+}
+
+static int an8855_port_set_vlan_mode(struct an8855_priv *priv, int port,
+				     enum an8855_port_mode port_mode,
+				     enum an8855_vlan_port_eg_tag eg_tag,
+				     enum an8855_vlan_port_attr vlan_attr,
+				     enum an8855_vlan_port_acc_frm acc_frm)
+{
+	int ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_PCR_P(port),
+				 AN8855_PORT_VLAN,
+				 FIELD_PREP(AN8855_PORT_VLAN, port_mode));
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(priv->regmap, AN8855_PVC_P(port),
+				  AN8855_PVC_EG_TAG | AN8855_VLAN_ATTR | AN8855_ACC_FRM,
+				  FIELD_PREP(AN8855_PVC_EG_TAG, eg_tag) |
+				  FIELD_PREP(AN8855_VLAN_ATTR, vlan_attr) |
+				  FIELD_PREP(AN8855_ACC_FRM, acc_frm));
+}
+
+static int an8855_port_set_pvid(struct an8855_priv *priv, int port,
+				u16 pvid)
+{
+	int ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_PPBV1_P(port),
+				 AN8855_PPBV_G0_PORT_VID,
+				 FIELD_PREP(AN8855_PPBV_G0_PORT_VID, pvid));
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(priv->regmap, AN8855_PVID_P(port),
+				  AN8855_G0_PORT_VID,
+				  FIELD_PREP(AN8855_G0_PORT_VID, pvid));
+}
+
+static int an8855_port_enable_vlan_filtering(struct dsa_switch *ds, int port)
+{
+	struct an8855_priv *priv = ds->priv;
+	u32 acc_frm, val;
+	int ret;
+
+	/* CPU port is set to fallback mode to let untagged
+	 * frames pass through.
+	 */
+	ret = an8855_port_set_vlan_mode(priv, AN8855_CPU_PORT,
+					AN8855_PORT_FALLBACK_MODE,
+					AN8855_VLAN_EG_CONSISTENT,
+					AN8855_VLAN_USER,
+					AN8855_VLAN_ACC_ALL);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val);
+	if (ret)
+		return ret;
+
+	/* Only accept tagged frames if PVID is not set */
+	if (FIELD_GET(AN8855_G0_PORT_VID, val) != AN8855_PORT_VID_DEFAULT)
+		acc_frm = AN8855_VLAN_ACC_TAGGED;
+	else
+		acc_frm = AN8855_VLAN_ACC_ALL;
+
+	/* Trapped into security mode allows packet forwarding through VLAN
+	 * table lookup.
+	 * Set the port as a user port which is to be able to recognize VID
+	 * from incoming packets before fetching entry within the VLAN table.
+	 */
+	return an8855_port_set_vlan_mode(priv, port,
+					 AN8855_PORT_SECURITY_MODE,
+					 AN8855_VLAN_EG_DISABLED,
+					 AN8855_VLAN_USER,
+					 acc_frm);
+}
+
+static int an8855_port_disable_vlan_filtering(struct dsa_switch *ds, int port)
+{
+	struct an8855_priv *priv = ds->priv;
+	bool disable_cpu_vlan = true;
+	struct dsa_port *dp;
+	u32 port_mode;
+	int ret;
+
+	/* This is called after .port_bridge_leave when leaving a VLAN-aware
+	 * bridge. Don't set standalone ports to fallback mode.
+	 */
+	if (dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
+		port_mode = AN8855_PORT_FALLBACK_MODE;
+	else
+		port_mode = AN8855_PORT_MATRIX_MODE;
+
+	/* When a port is removed from the bridge, the port would be set up
+	 * back to the default as is at initial boot which is a VLAN-unaware
+	 * port.
+	 */
+	ret = an8855_port_set_vlan_mode(priv, port, port_mode,
+					AN8855_VLAN_EG_CONSISTENT,
+					AN8855_VLAN_TRANSPARENT,
+					AN8855_VLAN_ACC_ALL);
+	if (ret)
+		return ret;
+
+	/* Restore default PVID */
+	ret = an8855_port_set_pvid(priv, port, AN8855_PORT_VID_DEFAULT);
+	if (ret)
+		return ret;
+
+	dsa_switch_for_each_user_port(dp, ds) {
+		if (dsa_port_is_vlan_filtering(dp)) {
+			disable_cpu_vlan = false;
+			break;
+		}
+	}
+
+	if (disable_cpu_vlan) {
+		ret = an8855_port_set_vlan_mode(priv, AN8855_CPU_PORT,
+						AN8855_PORT_MATRIX_MODE,
+						AN8855_VLAN_EG_CONSISTENT,
+						AN8855_VLAN_USER,
+						AN8855_VLAN_ACC_ALL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int an8855_port_vlan_filtering(struct dsa_switch *ds, int port,
+				      bool vlan_filtering,
+				      struct netlink_ext_ack *extack)
+{
+	/* The port is being kept as VLAN-unaware port when bridge is
+	 * set up with vlan_filtering not being set, Otherwise, the
+	 * port and the corresponding CPU port is required the setup
+	 * for becoming a VLAN-aware port.
+	 */
+	if (vlan_filtering)
+		return an8855_port_enable_vlan_filtering(ds, port);
+
+	return an8855_port_disable_vlan_filtering(ds, port);
+}
+
+static int an8855_port_vlan_add(struct dsa_switch *ds, int port,
+				const struct switchdev_obj_port_vlan *vlan,
+				struct netlink_ext_ack *extack)
+{
+	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+	struct an8855_priv *priv = ds->priv;
+	u32 val;
+	int ret;
+
+	mutex_lock(&priv->reg_mutex);
+	ret = an8855_vlan_add(priv, port, vlan->vid, untagged);
+	mutex_unlock(&priv->reg_mutex);
+	if (ret)
+		return ret;
+
+	if (pvid) {
+		/* Accept all frames if PVID is set */
+		regmap_update_bits(priv->regmap, AN8855_PVC_P(port), AN8855_ACC_FRM,
+				   FIELD_PREP(AN8855_ACC_FRM, AN8855_VLAN_ACC_ALL));
+
+		/* Only configure PVID if VLAN filtering is enabled */
+		if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) {
+			ret = an8855_port_set_pvid(priv, port, vlan->vid);
+			if (ret)
+				return ret;
+		}
+	} else if (vlan->vid) {
+		ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val);
+		if (ret)
+			return ret;
+
+		if (FIELD_GET(AN8855_G0_PORT_VID, val) != vlan->vid)
+			return 0;
+
+		/* This VLAN is overwritten without PVID, so unset it */
+		if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) {
+			ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(port),
+						 AN8855_ACC_FRM,
+						 FIELD_PREP(AN8855_ACC_FRM,
+							    AN8855_VLAN_ACC_TAGGED));
+			if (ret)
+				return ret;
+		}
+
+		ret = an8855_port_set_pvid(priv, port, AN8855_PORT_VID_DEFAULT);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int an8855_port_vlan_del(struct dsa_switch *ds, int port,
+				const struct switchdev_obj_port_vlan *vlan)
+{
+	struct an8855_priv *priv = ds->priv;
+	u32 val;
+	int ret;
+
+	mutex_lock(&priv->reg_mutex);
+	ret = an8855_vlan_del(priv, port, vlan->vid);
+	mutex_unlock(&priv->reg_mutex);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val);
+	if (ret)
+		return ret;
+
+	/* PVID is being restored to the default whenever the PVID port
+	 * is being removed from the VLAN.
+	 */
+	if (FIELD_GET(AN8855_G0_PORT_VID, val) == vlan->vid) {
+		/* Only accept tagged frames if the port is VLAN-aware */
+		if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) {
+			ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(port),
+						 AN8855_ACC_FRM,
+						 FIELD_PREP(AN8855_ACC_FRM,
+							    AN8855_VLAN_ACC_TAGGED));
+			if (ret)
+				return ret;
+		}
+
+		ret = an8855_port_set_pvid(priv, port, AN8855_PORT_VID_DEFAULT);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int an8855_port_mdb_add(struct dsa_switch *ds, int port,
+			       const struct switchdev_obj_port_mdb *mdb,
+			       struct dsa_db db)
+{
+	struct an8855_priv *priv = ds->priv;
+	const u8 *addr = mdb->addr;
+	u16 vid = mdb->vid;
+	u8 port_mask = 0;
+	u32 val;
+	int ret;
+
+	/* With VLAN-Unaware entry, set vid to default vid */
+	if (!vid)
+		vid = AN8855_PORT_VID_DEFAULT;
+
+	mutex_lock(&priv->reg_mutex);
+
+	an8855_fdb_write(priv, vid, 0, addr, false);
+	if (!an8855_fdb_cmd(priv, AN8855_FDB_READ, NULL)) {
+		ret = regmap_read(priv->regmap, AN8855_ATRD3, &val);
+		if (ret)
+			goto exit;
+
+		port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, val);
+	}
+
+	port_mask |= BIT(port);
+	an8855_fdb_write(priv, vid, port_mask, addr, true);
+	ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+
+exit:
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static int an8855_port_mdb_del(struct dsa_switch *ds, int port,
+			       const struct switchdev_obj_port_mdb *mdb,
+			       struct dsa_db db)
+{
+	struct an8855_priv *priv = ds->priv;
+	const u8 *addr = mdb->addr;
+	u16 vid = mdb->vid;
+	u8 port_mask = 0;
+	u32 val;
+	int ret;
+
+	/* With VLAN-Unaware entry, set vid to default vid */
+	if (!vid)
+		vid = AN8855_PORT_VID_DEFAULT;
+
+	mutex_lock(&priv->reg_mutex);
+
+	an8855_fdb_write(priv, vid, 0, addr, 0);
+	if (!an8855_fdb_cmd(priv, AN8855_FDB_READ, NULL)) {
+		ret = regmap_read(priv->regmap, AN8855_ATRD3, &val);
+		if (ret)
+			goto exit;
+
+		port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, val);
+	}
+
+	port_mask &= ~BIT(port);
+	an8855_fdb_write(priv, vid, port_mask, addr, port_mask ? true : false);
+	ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+
+exit:
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static int an8855_port_change_mtu(struct dsa_switch *ds, int port,
+				  int new_mtu)
+{
+	struct an8855_priv *priv = ds->priv;
+	int length;
+	u32 val;
+
+	/* When a new MTU is set, DSA always set the CPU port's MTU to the
+	 * largest MTU of the slave ports. Because the switch only has a global
+	 * RX length register, only allowing CPU port here is enough.
+	 */
+	if (!dsa_is_cpu_port(ds, port))
+		return 0;
+
+	/* RX length also includes Ethernet header, MTK tag, and FCS length */
+	length = new_mtu + ETH_HLEN + MTK_TAG_LEN + ETH_FCS_LEN;
+	if (length <= 1522)
+		val = AN8855_MAX_RX_PKT_1518_1522;
+	else if (length <= 1536)
+		val = AN8855_MAX_RX_PKT_1536;
+	else if (length <= 1552)
+		val = AN8855_MAX_RX_PKT_1552;
+	else if (length <= 3072)
+		val = AN8855_MAX_RX_JUMBO_3K;
+	else if (length <= 4096)
+		val = AN8855_MAX_RX_JUMBO_4K;
+	else if (length <= 5120)
+		val = AN8855_MAX_RX_JUMBO_5K;
+	else if (length <= 6144)
+		val = AN8855_MAX_RX_JUMBO_6K;
+	else if (length <= 7168)
+		val = AN8855_MAX_RX_JUMBO_7K;
+	else if (length <= 8192)
+		val = AN8855_MAX_RX_JUMBO_8K;
+	else if (length <= 9216)
+		val = AN8855_MAX_RX_JUMBO_9K;
+	else if (length <= 12288)
+		val = AN8855_MAX_RX_JUMBO_12K;
+	else if (length <= 15360)
+		val = AN8855_MAX_RX_JUMBO_15K;
+	else
+		val = AN8855_MAX_RX_JUMBO_16K;
+
+	/* Enable JUMBO packet */
+	if (length > 1552)
+		val |= AN8855_MAX_RX_PKT_JUMBO;
+
+	return regmap_update_bits(priv->regmap, AN8855_GMACCR,
+				  AN8855_MAX_RX_JUMBO | AN8855_MAX_RX_PKT_LEN,
+				  val);
+}
+
+static int an8855_port_max_mtu(struct dsa_switch *ds, int port)
+{
+	return AN8855_MAX_MTU;
+}
+
+static void an8855_get_strings(struct dsa_switch *ds, int port,
+			       u32 stringset, uint8_t *data)
+{
+	int i;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(an8855_mib); i++)
+		ethtool_puts(&data, an8855_mib[i].name);
+}
+
+static void an8855_read_port_stats(struct an8855_priv *priv, int port,
+				   u32 offset, u8 size, uint64_t *data)
+{
+	u32 val, reg = AN8855_PORT_MIB_COUNTER(port) + offset;
+
+	regmap_read(priv->regmap, reg, &val);
+	*data = val;
+
+	if (size == 2) {
+		regmap_read(priv->regmap, reg + 4, &val);
+		*data |= (u64)val << 32;
+	}
+}
+
+static void an8855_get_ethtool_stats(struct dsa_switch *ds, int port,
+				     uint64_t *data)
+{
+	struct an8855_priv *priv = ds->priv;
+	const struct an8855_mib_desc *mib;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) {
+		mib = &an8855_mib[i];
+
+		an8855_read_port_stats(priv, port, mib->offset, mib->size,
+				       data + i);
+	}
+}
+
+static int an8855_get_sset_count(struct dsa_switch *ds, int port,
+				 int sset)
+{
+	if (sset != ETH_SS_STATS)
+		return 0;
+
+	return ARRAY_SIZE(an8855_mib);
+}
+
+static void an8855_get_eth_mac_stats(struct dsa_switch *ds, int port,
+				     struct ethtool_eth_mac_stats *mac_stats)
+{
+	struct an8855_priv *priv = ds->priv;
+
+	/* MIB counter doesn't provide a FramesTransmittedOK but instead
+	 * provide stats for Unicast, Broadcast and Multicast frames separately.
+	 * To simulate a global frame counter, read Unicast and addition Multicast
+	 * and Broadcast later
+	 */
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_UNICAST, 1,
+			       &mac_stats->FramesTransmittedOK);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_SINGLE_COLLISION, 1,
+			       &mac_stats->SingleCollisionFrames);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_MULTIPLE_COLLISION, 1,
+			       &mac_stats->MultipleCollisionFrames);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_UNICAST, 1,
+			       &mac_stats->FramesReceivedOK);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_BYTES, 2,
+			       &mac_stats->OctetsTransmittedOK);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_ALIGN_ERR, 1,
+			       &mac_stats->AlignmentErrors);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_DEFERRED, 1,
+			       &mac_stats->FramesWithDeferredXmissions);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_LATE_COLLISION, 1,
+			       &mac_stats->LateCollisions);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_EXCESSIVE_COLLISION, 1,
+			       &mac_stats->FramesAbortedDueToXSColls);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_BYTES, 2,
+			       &mac_stats->OctetsReceivedOK);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_MULTICAST, 1,
+			       &mac_stats->MulticastFramesXmittedOK);
+	mac_stats->FramesTransmittedOK += mac_stats->MulticastFramesXmittedOK;
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_BROADCAST, 1,
+			       &mac_stats->BroadcastFramesXmittedOK);
+	mac_stats->FramesTransmittedOK += mac_stats->BroadcastFramesXmittedOK;
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_MULTICAST, 1,
+			       &mac_stats->MulticastFramesReceivedOK);
+	mac_stats->FramesReceivedOK += mac_stats->MulticastFramesReceivedOK;
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_BROADCAST, 1,
+			       &mac_stats->BroadcastFramesReceivedOK);
+	mac_stats->FramesReceivedOK += mac_stats->BroadcastFramesReceivedOK;
+}
+
+static const struct ethtool_rmon_hist_range an8855_rmon_ranges[] = {
+	{ 0, 64 },
+	{ 65, 127 },
+	{ 128, 255 },
+	{ 256, 511 },
+	{ 512, 1023 },
+	{ 1024, 1518 },
+	{ 1519, AN8855_MAX_MTU },
+	{}
+};
+
+static void an8855_get_rmon_stats(struct dsa_switch *ds, int port,
+				  struct ethtool_rmon_stats *rmon_stats,
+				  const struct ethtool_rmon_hist_range **ranges)
+{
+	struct an8855_priv *priv = ds->priv;
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_UNDER_SIZE_ERR, 1,
+			       &rmon_stats->undersize_pkts);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_OVER_SZ_ERR, 1,
+			       &rmon_stats->oversize_pkts);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_FRAG_ERR, 1,
+			       &rmon_stats->fragments);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_JABBER_ERR, 1,
+			       &rmon_stats->jabbers);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_64, 1,
+			       &rmon_stats->hist[0]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_65_TO_127, 1,
+			       &rmon_stats->hist[1]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_128_TO_255, 1,
+			       &rmon_stats->hist[2]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_256_TO_511, 1,
+			       &rmon_stats->hist[3]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_512_TO_1023, 1,
+			       &rmon_stats->hist[4]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_1024_TO_1518, 1,
+			       &rmon_stats->hist[5]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_1519_TO_MAX, 1,
+			       &rmon_stats->hist[6]);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_64, 1,
+			       &rmon_stats->hist_tx[0]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_65_TO_127, 1,
+			       &rmon_stats->hist_tx[1]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_128_TO_255, 1,
+			       &rmon_stats->hist_tx[2]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_256_TO_511, 1,
+			       &rmon_stats->hist_tx[3]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_512_TO_1023, 1,
+			       &rmon_stats->hist_tx[4]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_1024_TO_1518, 1,
+			       &rmon_stats->hist_tx[5]);
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_1519_TO_MAX, 1,
+			       &rmon_stats->hist_tx[6]);
+
+	*ranges = an8855_rmon_ranges;
+}
+
+static void an8855_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
+				      struct ethtool_eth_ctrl_stats *ctrl_stats)
+{
+	struct an8855_priv *priv = ds->priv;
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PAUSE, 1,
+			       &ctrl_stats->MACControlFramesTransmitted);
+
+	an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PAUSE, 1,
+			       &ctrl_stats->MACControlFramesReceived);
+}
+
+static int an8855_port_mirror_add(struct dsa_switch *ds, int port,
+				  struct dsa_mall_mirror_tc_entry *mirror,
+				  bool ingress,
+				  struct netlink_ext_ack *extack)
+{
+	struct an8855_priv *priv = ds->priv;
+	int monitor_port;
+	u32 val;
+	int ret;
+
+	/* Check for existent entry */
+	if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Mirroring already set for port");
+		return -EEXIST;
+	}
+
+	ret = regmap_read(priv->regmap, AN8855_MIR, &val);
+	if (ret)
+		return ret;
+
+	/* AN8855 supports 4 monitor port, but only use first group */
+	monitor_port = FIELD_GET(AN8855_MIRROR_PORT, val);
+	if (val & AN8855_MIRROR_EN && monitor_port != mirror->to_local_port) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Mirror port already set for a different port");
+		return -EEXIST;
+	}
+
+	val = AN8855_MIRROR_EN;
+	val |= FIELD_PREP(AN8855_MIRROR_PORT, mirror->to_local_port);
+	ret = regmap_update_bits(priv->regmap, AN8855_MIR,
+				 AN8855_MIRROR_EN | AN8855_MIRROR_PORT,
+				 val);
+	if (ret)
+		return ret;
+
+	ret = regmap_set_bits(priv->regmap, AN8855_PCR_P(port),
+			      ingress ? AN8855_PORT_RX_MIR : AN8855_PORT_TX_MIR);
+	if (ret)
+		return ret;
+
+	if (ingress)
+		priv->mirror_rx |= BIT(port);
+	else
+		priv->mirror_tx |= BIT(port);
+
+	return 0;
+}
+
+static void an8855_port_mirror_del(struct dsa_switch *ds, int port,
+				   struct dsa_mall_mirror_tc_entry *mirror)
+{
+	struct an8855_priv *priv = ds->priv;
+
+	if (mirror->ingress)
+		priv->mirror_rx &= ~BIT(port);
+	else
+		priv->mirror_tx &= ~BIT(port);
+
+	regmap_clear_bits(priv->regmap, AN8855_PCR_P(port),
+			  mirror->ingress ? AN8855_PORT_RX_MIR :
+					    AN8855_PORT_TX_MIR);
+
+	if (!priv->mirror_rx && !priv->mirror_tx)
+		regmap_clear_bits(priv->regmap, AN8855_MIR, AN8855_MIRROR_EN);
+}
+
+static int an8855_port_enable(struct dsa_switch *ds, int port,
+			      struct phy_device *phy)
+{
+	struct an8855_priv *priv = ds->priv;
+
+	return regmap_set_bits(priv->regmap, AN8855_PMCR_P(port),
+			       AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
+}
+
+static void an8855_port_disable(struct dsa_switch *ds, int port)
+{
+	struct an8855_priv *priv = ds->priv;
+	int ret;
+
+	ret = regmap_clear_bits(priv->regmap, AN8855_PMCR_P(port),
+				AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
+	if (ret)
+		dev_err(priv->ds->dev, "failed to disable port: %d\n", ret);
+}
+
+static enum dsa_tag_protocol an8855_get_tag_protocol(struct dsa_switch *ds,
+						     int port,
+						     enum dsa_tag_protocol mp)
+{
+	return DSA_TAG_PROTO_MTK;
+}
+
+/* Similar to MT7530 also trap link local frame and special frame to CPU */
+static int an8855_trap_special_frames(struct an8855_priv *priv)
+{
+	int ret;
+
+	/* Trap BPDUs to the CPU port(s) and egress them
+	 * VLAN-untagged.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_BPC,
+				 AN8855_BPDU_BPDU_FR | AN8855_BPDU_EG_TAG |
+				 AN8855_BPDU_PORT_FW,
+				 AN8855_BPDU_BPDU_FR |
+				 FIELD_PREP(AN8855_BPDU_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				 FIELD_PREP(AN8855_BPDU_PORT_FW, AN8855_BPDU_CPU_ONLY));
+	if (ret)
+		return ret;
+
+	/* Trap 802.1X PAE frames to the CPU port(s) and egress them
+	 * VLAN-untagged.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_PAC,
+				 AN8855_PAE_BPDU_FR | AN8855_PAE_EG_TAG |
+				 AN8855_PAE_PORT_FW,
+				 AN8855_PAE_BPDU_FR |
+				 FIELD_PREP(AN8855_PAE_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				 FIELD_PREP(AN8855_PAE_PORT_FW, AN8855_BPDU_CPU_ONLY));
+	if (ret)
+		return ret;
+
+	/* Trap frames with :01 MAC DAs to the CPU port(s) and egress
+	 * them VLAN-untagged.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
+				 AN8855_R01_BPDU_FR | AN8855_R01_EG_TAG |
+				 AN8855_R01_PORT_FW,
+				 AN8855_R01_BPDU_FR |
+				 FIELD_PREP(AN8855_R01_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				 FIELD_PREP(AN8855_R01_PORT_FW, AN8855_BPDU_CPU_ONLY));
+	if (ret)
+		return ret;
+
+	/* Trap frames with :02 MAC DAs to the CPU port(s) and egress
+	 * them VLAN-untagged.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
+				 AN8855_R02_BPDU_FR | AN8855_R02_EG_TAG |
+				 AN8855_R02_PORT_FW,
+				 AN8855_R02_BPDU_FR |
+				 FIELD_PREP(AN8855_R02_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				 FIELD_PREP(AN8855_R02_PORT_FW, AN8855_BPDU_CPU_ONLY));
+	if (ret)
+		return ret;
+
+	/* Trap frames with :03 MAC DAs to the CPU port(s) and egress
+	 * them VLAN-untagged.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
+				 AN8855_R03_BPDU_FR | AN8855_R03_EG_TAG |
+				 AN8855_R03_PORT_FW,
+				 AN8855_R03_BPDU_FR |
+				 FIELD_PREP(AN8855_R03_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				 FIELD_PREP(AN8855_R03_PORT_FW, AN8855_BPDU_CPU_ONLY));
+	if (ret)
+		return ret;
+
+	/* Trap frames with :0E MAC DAs to the CPU port(s) and egress
+	 * them VLAN-untagged.
+	 */
+	return regmap_update_bits(priv->regmap, AN8855_RGAC1,
+				  AN8855_R0E_BPDU_FR | AN8855_R0E_EG_TAG |
+				  AN8855_R0E_PORT_FW,
+				  AN8855_R0E_BPDU_FR |
+				  FIELD_PREP(AN8855_R0E_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
+				  FIELD_PREP(AN8855_R0E_PORT_FW, AN8855_BPDU_CPU_ONLY));
+}
+
+static int an8855_setup_pvid_vlan(struct an8855_priv *priv)
+{
+	u32 val;
+	int ret;
+
+	/* Validate the entry with independent learning, keep the original
+	 * ingress tag attribute.
+	 */
+	val = AN8855_VA0_IVL_MAC | AN8855_VA0_EG_CON |
+	      FIELD_PREP(AN8855_VA0_FID, AN8855_FID_BRIDGED) |
+	      AN8855_VA0_PORT | AN8855_VA0_VLAN_VALID;
+	ret = regmap_write(priv->regmap, AN8855_VAWD0, val);
+	if (ret)
+		return ret;
+
+	return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID,
+			       AN8855_PORT_VID_DEFAULT);
+}
+
+static int an8855_setup(struct dsa_switch *ds)
+{
+	struct an8855_priv *priv = ds->priv;
+	struct dsa_port *dp;
+	int ret;
+
+	/* Enable and reset MIB counters */
+	ret = an8855_mib_init(priv);
+	if (ret)
+		return ret;
+
+	dsa_switch_for_each_user_port(dp, ds) {
+		/* Disable MAC by default on all user ports */
+		an8855_port_disable(ds, dp->index);
+
+		/* Individual user ports get connected to CPU port only */
+		ret = regmap_write(priv->regmap, AN8855_PORTMATRIX_P(dp->index),
+				   FIELD_PREP(AN8855_PORTMATRIX, BIT(AN8855_CPU_PORT)));
+		if (ret)
+			return ret;
+
+		/* Disable Broadcast Forward on user ports */
+		ret = regmap_clear_bits(priv->regmap, AN8855_BCF, BIT(dp->index));
+		if (ret)
+			return ret;
+
+		/* Disable Unknown Unicast Forward on user ports */
+		ret = regmap_clear_bits(priv->regmap, AN8855_UNUF, BIT(dp->index));
+		if (ret)
+			return ret;
+
+		/* Disable Unknown Multicast Forward on user ports */
+		ret = regmap_clear_bits(priv->regmap, AN8855_UNMF, BIT(dp->index));
+		if (ret)
+			return ret;
+
+		ret = regmap_clear_bits(priv->regmap, AN8855_UNIPMF, BIT(dp->index));
+		if (ret)
+			return ret;
+
+		/* Set default PVID to on all user ports */
+		ret = an8855_port_set_pvid(priv, dp->index, AN8855_PORT_VID_DEFAULT);
+		if (ret)
+			return ret;
+	}
+
+	/* Enable Airoha header mode on the cpu port */
+	ret = regmap_write(priv->regmap, AN8855_PVC_P(AN8855_CPU_PORT),
+			   AN8855_PORT_SPEC_REPLACE_MODE | AN8855_PORT_SPEC_TAG);
+	if (ret)
+		return ret;
+
+	/* Unknown multicast frame forwarding to the cpu port */
+	ret = regmap_write(priv->regmap, AN8855_UNMF, BIT(AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	/* Set CPU port number */
+	ret = regmap_update_bits(priv->regmap, AN8855_MFC,
+				 AN8855_CPU_EN | AN8855_CPU_PORT_IDX,
+				 AN8855_CPU_EN |
+				 FIELD_PREP(AN8855_CPU_PORT_IDX, AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	/* CPU port gets connected to all user ports of
+	 * the switch.
+	 */
+	ret = regmap_write(priv->regmap, AN8855_PORTMATRIX_P(AN8855_CPU_PORT),
+			   FIELD_PREP(AN8855_PORTMATRIX, dsa_user_ports(ds)));
+	if (ret)
+		return ret;
+
+	/* CPU port is set to fallback mode to let untagged
+	 * frames pass through.
+	 */
+	ret = regmap_update_bits(priv->regmap, AN8855_PCR_P(AN8855_CPU_PORT),
+				 AN8855_PORT_VLAN,
+				 FIELD_PREP(AN8855_PORT_VLAN, AN8855_PORT_FALLBACK_MODE));
+	if (ret)
+		return ret;
+
+	/* Enable Broadcast Forward on CPU port */
+	ret = regmap_set_bits(priv->regmap, AN8855_BCF, BIT(AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	/* Enable Unknown Unicast Forward on CPU port */
+	ret = regmap_set_bits(priv->regmap, AN8855_UNUF, BIT(AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	/* Enable Unknown Multicast Forward on CPU port */
+	ret = regmap_set_bits(priv->regmap, AN8855_UNMF, BIT(AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	ret = regmap_set_bits(priv->regmap, AN8855_UNIPMF, BIT(AN8855_CPU_PORT));
+	if (ret)
+		return ret;
+
+	/* Setup Trap special frame to CPU rules */
+	ret = an8855_trap_special_frames(priv);
+	if (ret)
+		return ret;
+
+	dsa_switch_for_each_port(dp, ds) {
+		/* Disable Learning on all ports.
+		 * Learning on CPU is disabled for fdb isolation and handled by
+		 * assisted_learning_on_cpu_port.
+		 */
+		ret = regmap_set_bits(priv->regmap, AN8855_PSC_P(dp->index),
+				      AN8855_SA_DIS);
+		if (ret)
+			return ret;
+
+		/* Enable consistent egress tag (for VLAN unware VLAN-passthrough) */
+		ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(dp->index),
+					 AN8855_PVC_EG_TAG,
+					 FIELD_PREP(AN8855_PVC_EG_TAG, AN8855_VLAN_EG_CONSISTENT));
+		if (ret)
+			return ret;
+	}
+
+	/* Setup VLAN for Default PVID */
+	ret = an8855_setup_pvid_vlan(priv);
+	if (ret)
+		return ret;
+
+	ret = regmap_clear_bits(priv->regmap, AN8855_CKGCR,
+				AN8855_CKG_LNKDN_GLB_STOP | AN8855_CKG_LNKDN_PORT_STOP);
+	if (ret)
+		return ret;
+
+	/* Flush the FDB table */
+	ret = an8855_fdb_cmd(priv, AN8855_FDB_FLUSH, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set min a max ageing value supported */
+	ds->ageing_time_min = AN8855_L2_AGING_MS_CONSTANT;
+	ds->ageing_time_max = FIELD_MAX(AN8855_AGE_CNT) *
+			      FIELD_MAX(AN8855_AGE_UNIT) *
+			      AN8855_L2_AGING_MS_CONSTANT;
+
+	/* User reported problem with WiFi roaming and
+	 * ethernet port. Enabling assisted learning fix
+	 * the issue.
+	 */
+	ds->assisted_learning_on_cpu_port = true;
+
+	return 0;
+}
+
+static struct phylink_pcs *an8855_phylink_mac_select_pcs(struct phylink_config *config,
+							 phy_interface_t interface)
+{
+	struct dsa_port *dp = dsa_phylink_to_port(config);
+	struct an8855_priv *priv = dp->ds->priv;
+
+	switch (interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_2500BASEX:
+		return &priv->pcs;
+	default:
+		return NULL;
+	}
+}
+
+static void an8855_phylink_mac_config(struct phylink_config *config,
+				      unsigned int mode,
+				      const struct phylink_link_state *state)
+{
+	struct dsa_port *dp = dsa_phylink_to_port(config);
+	struct dsa_switch *ds = dp->ds;
+	struct an8855_priv *priv;
+	int port = dp->index;
+
+	priv = ds->priv;
+
+	/* Nothing to configure for internal ports */
+	if (port != 5)
+		return;
+
+	regmap_update_bits(priv->regmap, AN8855_PMCR_P(port),
+			   AN8855_PMCR_IFG_XMIT | AN8855_PMCR_MAC_MODE |
+			   AN8855_PMCR_BACKOFF_EN | AN8855_PMCR_BACKPR_EN,
+			   FIELD_PREP(AN8855_PMCR_IFG_XMIT, 0x1) |
+			   AN8855_PMCR_MAC_MODE | AN8855_PMCR_BACKOFF_EN |
+			   AN8855_PMCR_BACKPR_EN);
+}
+
+static void an8855_phylink_get_caps(struct dsa_switch *ds, int port,
+				    struct phylink_config *config)
+{
+	switch (port) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		__set_bit(PHY_INTERFACE_MODE_GMII,
+			  config->supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_INTERNAL,
+			  config->supported_interfaces);
+		break;
+	case 5:
+		phy_interface_set_rgmii(config->supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_SGMII,
+			  config->supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_2500BASEX,
+			  config->supported_interfaces);
+		break;
+	}
+
+	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+				   MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;
+}
+
+static void an8855_phylink_mac_link_down(struct phylink_config *config,
+					 unsigned int mode,
+					 phy_interface_t interface)
+{
+	struct dsa_port *dp = dsa_phylink_to_port(config);
+	struct an8855_priv *priv = dp->ds->priv;
+
+	/* With autoneg just disable TX/RX else also force link down */
+	if (phylink_autoneg_inband(mode)) {
+		regmap_clear_bits(priv->regmap, AN8855_PMCR_P(dp->index),
+				  AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
+	} else {
+		regmap_update_bits(priv->regmap, AN8855_PMCR_P(dp->index),
+				   AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN |
+				   AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK,
+				   AN8855_PMCR_FORCE_MODE);
+	}
+}
+
+static void an8855_phylink_mac_link_up(struct phylink_config *config,
+				       struct phy_device *phydev, unsigned int mode,
+				       phy_interface_t interface, int speed,
+				       int duplex, bool tx_pause, bool rx_pause)
+{
+	struct dsa_port *dp = dsa_phylink_to_port(config);
+	struct an8855_priv *priv = dp->ds->priv;
+	int port = dp->index;
+	u32 reg;
+
+	reg = regmap_read(priv->regmap, AN8855_PMCR_P(port), &reg);
+	if (phylink_autoneg_inband(mode)) {
+		reg &= ~AN8855_PMCR_FORCE_MODE;
+	} else {
+		reg |= AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK;
+
+		reg &= ~AN8855_PMCR_FORCE_SPEED;
+		switch (speed) {
+		case SPEED_10:
+			reg |= AN8855_PMCR_FORCE_SPEED_10;
+			break;
+		case SPEED_100:
+			reg |= AN8855_PMCR_FORCE_SPEED_100;
+			break;
+		case SPEED_1000:
+			reg |= AN8855_PMCR_FORCE_SPEED_1000;
+			break;
+		case SPEED_2500:
+			reg |= AN8855_PMCR_FORCE_SPEED_2500;
+			break;
+		case SPEED_5000:
+			dev_err(priv->ds->dev, "Missing support for 5G speed. Aborting...\n");
+			return;
+		}
+
+		reg &= ~AN8855_PMCR_FORCE_FDX;
+		if (duplex == DUPLEX_FULL)
+			reg |= AN8855_PMCR_FORCE_FDX;
+
+		reg &= ~AN8855_PMCR_RX_FC_EN;
+		if (rx_pause || dsa_port_is_cpu(dp))
+			reg |= AN8855_PMCR_RX_FC_EN;
+
+		reg &= ~AN8855_PMCR_TX_FC_EN;
+		if (rx_pause || dsa_port_is_cpu(dp))
+			reg |= AN8855_PMCR_TX_FC_EN;
+
+		/* Disable any EEE options */
+		reg &= ~(AN8855_PMCR_FORCE_EEE5G | AN8855_PMCR_FORCE_EEE2P5G |
+			 AN8855_PMCR_FORCE_EEE1G | AN8855_PMCR_FORCE_EEE100);
+	}
+
+	reg |= AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN;
+
+	regmap_write(priv->regmap, AN8855_PMCR_P(port), reg);
+}
+
+static unsigned int an8855_pcs_inband_caps(struct phylink_pcs *pcs,
+					   phy_interface_t interface)
+{
+	/* SGMII can be configured to use inband with AN result */
+	if (interface == PHY_INTERFACE_MODE_SGMII)
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
+
+	/* inband is not supported in 2500-baseX and must be disabled */
+	return  LINK_INBAND_DISABLE;
+}
+
+static void an8855_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
+				 struct phylink_link_state *state)
+{
+	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
+	u32 val;
+	int ret;
+
+	ret = regmap_read(priv->regmap, AN8855_PMSR_P(AN8855_CPU_PORT), &val);
+	if (ret < 0) {
+		state->link = false;
+		return;
+	}
+
+	state->link = !!(val & AN8855_PMSR_LNK);
+	state->an_complete = state->link;
+	state->duplex = (val & AN8855_PMSR_DPX) ? DUPLEX_FULL :
+						  DUPLEX_HALF;
+
+	switch (val & AN8855_PMSR_SPEED) {
+	case AN8855_PMSR_SPEED_10:
+		state->speed = SPEED_10;
+		break;
+	case AN8855_PMSR_SPEED_100:
+		state->speed = SPEED_100;
+		break;
+	case AN8855_PMSR_SPEED_1000:
+		state->speed = SPEED_1000;
+		break;
+	case AN8855_PMSR_SPEED_2500:
+		state->speed = SPEED_2500;
+		break;
+	case AN8855_PMSR_SPEED_5000:
+		dev_err(priv->ds->dev, "Missing support for 5G speed. Setting Unknown.\n");
+		fallthrough;
+	default:
+		state->speed = SPEED_UNKNOWN;
+		break;
+	}
+
+	if (val & AN8855_PMSR_RX_FC)
+		state->pause |= MLO_PAUSE_RX;
+	if (val & AN8855_PMSR_TX_FC)
+		state->pause |= MLO_PAUSE_TX;
+}
+
+static int an8855_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+			     phy_interface_t interface,
+			     const unsigned long *advertising,
+			     bool permit_pause_to_mac)
+{
+	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
+	u32 val;
+	int ret;
+
+	/*                   !!! WELCOME TO HELL !!!                   */
+
+	/* TX FIR - improve TX EYE */
+	ret = regmap_update_bits(priv->regmap, AN8855_INTF_CTRL_10,
+				 AN8855_RG_DA_QP_TX_FIR_C2_SEL |
+				 AN8855_RG_DA_QP_TX_FIR_C2_FORCE |
+				 AN8855_RG_DA_QP_TX_FIR_C1_SEL |
+				 AN8855_RG_DA_QP_TX_FIR_C1_FORCE,
+				 AN8855_RG_DA_QP_TX_FIR_C2_SEL |
+				 FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C2_FORCE, 0x4) |
+				 AN8855_RG_DA_QP_TX_FIR_C1_SEL |
+				 FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C1_FORCE, 0x0));
+	if (ret)
+		return ret;
+
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x0;
+	else
+		val = 0xd;
+	ret = regmap_update_bits(priv->regmap, AN8855_INTF_CTRL_11,
+				 AN8855_RG_DA_QP_TX_FIR_C0B_SEL |
+				 AN8855_RG_DA_QP_TX_FIR_C0B_FORCE,
+				 AN8855_RG_DA_QP_TX_FIR_C0B_SEL |
+				 FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C0B_FORCE, val));
+	if (ret)
+		return ret;
+
+	/* RX CDR - improve RX Jitter Tolerance */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x5;
+	else
+		val = 0x6;
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_BOT_LIM,
+				 AN8855_RG_QP_CDR_LPF_KP_GAIN |
+				 AN8855_RG_QP_CDR_LPF_KI_GAIN,
+				 FIELD_PREP(AN8855_RG_QP_CDR_LPF_KP_GAIN, val) |
+				 FIELD_PREP(AN8855_RG_QP_CDR_LPF_KI_GAIN, val));
+	if (ret)
+		return ret;
+
+	/* PLL */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x1;
+	else
+		val = 0x0;
+	ret = regmap_update_bits(priv->regmap, AN8855_QP_DIG_MODE_CTRL_1,
+				 AN8855_RG_TPHY_SPEED,
+				 FIELD_PREP(AN8855_RG_TPHY_SPEED, val));
+	if (ret)
+		return ret;
+
+	/* PLL - LPF */
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				 AN8855_RG_DA_QP_PLL_RICO_SEL_INTF |
+				 AN8855_RG_DA_QP_PLL_FBKSEL_INTF |
+				 AN8855_RG_DA_QP_PLL_BR_INTF |
+				 AN8855_RG_DA_QP_PLL_BPD_INTF |
+				 AN8855_RG_DA_QP_PLL_BPA_INTF |
+				 AN8855_RG_DA_QP_PLL_BC_INTF,
+				 AN8855_RG_DA_QP_PLL_RICO_SEL_INTF |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_FBKSEL_INTF, 0x0) |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_BR_INTF, 0x3) |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_BPD_INTF, 0x0) |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_BPA_INTF, 0x5) |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_BC_INTF, 0x1));
+	if (ret)
+		return ret;
+
+	/* PLL - ICO */
+	ret = regmap_set_bits(priv->regmap, AN8855_PLL_CTRL_4,
+			      AN8855_RG_DA_QP_PLL_ICOLP_EN_INTF);
+	if (ret)
+		return ret;
+	ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				AN8855_RG_DA_QP_PLL_ICOIQ_EN_INTF);
+	if (ret)
+		return ret;
+
+	/* PLL - CHP */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x6;
+	else
+		val = 0x4;
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				 AN8855_RG_DA_QP_PLL_IR_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_IR_INTF, val));
+	if (ret)
+		return ret;
+
+	/* PLL - PFD */
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				 AN8855_RG_DA_QP_PLL_PFD_OFFSET_EN_INTRF |
+				 AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF |
+				 AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF, 0x1) |
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF, 0x1));
+	if (ret)
+		return ret;
+
+	/* PLL - POSTDIV */
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				 AN8855_RG_DA_QP_PLL_POSTDIV_EN_INTF |
+				 AN8855_RG_DA_QP_PLL_PHY_CK_EN_INTF |
+				 AN8855_RG_DA_QP_PLL_PCK_SEL_INTF,
+				 AN8855_RG_DA_QP_PLL_PCK_SEL_INTF);
+	if (ret)
+		return ret;
+
+	/* PLL - SDM */
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				 AN8855_RG_DA_QP_PLL_SDM_HREN_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_SDM_HREN_INTF, 0x0));
+	if (ret)
+		return ret;
+	ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CTRL_2,
+				AN8855_RG_DA_QP_PLL_SDM_IFM_INTF);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_SS_LCPLL_PWCTL_SETTING_2,
+				 AN8855_RG_NCPO_ANA_MSB,
+				 FIELD_PREP(AN8855_RG_NCPO_ANA_MSB, 0x1));
+	if (ret)
+		return ret;
+
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x7a000000;
+	else
+		val = 0x48000000;
+	ret = regmap_write(priv->regmap, AN8855_SS_LCPLL_TDC_FLT_2,
+			   FIELD_PREP(AN8855_RG_LCPLL_NCPO_VALUE, val));
+	if (ret)
+		return ret;
+	ret = regmap_write(priv->regmap, AN8855_SS_LCPLL_TDC_PCW_1,
+			   FIELD_PREP(AN8855_RG_LCPLL_PON_HRDDS_PCW_NCPO_GPON, val));
+	if (ret)
+		return ret;
+
+	ret = regmap_clear_bits(priv->regmap, AN8855_SS_LCPLL_TDC_FLT_5,
+				AN8855_RG_LCPLL_NCPO_CHG);
+	if (ret)
+		return ret;
+	ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CK_CTRL_0,
+				AN8855_RG_DA_QP_PLL_SDM_DI_EN_INTF);
+	if (ret)
+		return ret;
+
+	/* PLL - SS */
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_3,
+				 AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF, 0x0));
+	if (ret)
+		return ret;
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_4,
+				 AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF, 0x0));
+	if (ret)
+		return ret;
+	ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_3,
+				 AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF,
+				 FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF, 0x0));
+	if (ret)
+		return ret;
+
+	/* PLL - TDC */
+	ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CK_CTRL_0,
+				AN8855_RG_DA_QP_PLL_TDC_TXCK_SEL_INTF);
+	if (ret)
+		return ret;
+
+	ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_PLL_SDM_ORD,
+			      AN8855_RG_QP_PLL_SSC_TRI_EN);
+	if (ret)
+		return ret;
+	ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_PLL_SDM_ORD,
+			      AN8855_RG_QP_PLL_SSC_PHASE_INI);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_RX_DAC_EN,
+				 AN8855_RG_QP_SIGDET_HF,
+				 FIELD_PREP(AN8855_RG_QP_SIGDET_HF, 0x2));
+	if (ret)
+		return ret;
+
+	/* TCL Disable (only for Co-SIM) */
+	ret = regmap_clear_bits(priv->regmap, AN8855_PON_RXFEDIG_CTRL_0,
+				AN8855_RG_QP_EQ_RX500M_CK_SEL);
+	if (ret)
+		return ret;
+
+	/* TX Init */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x4;
+	else
+		val = 0x0;
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_TX_MODE,
+				 AN8855_RG_QP_TX_RESERVE |
+				 AN8855_RG_QP_TX_MODE_16B_EN,
+				 FIELD_PREP(AN8855_RG_QP_TX_RESERVE, val));
+	if (ret)
+		return ret;
+
+	/* RX Control/Init */
+	ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_RXAFE_RESERVE,
+			      AN8855_RG_QP_CDR_PD_10B_EN);
+	if (ret)
+		return ret;
+
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x1;
+	else
+		val = 0x2;
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_MJV_LIM,
+				 AN8855_RG_QP_CDR_LPF_RATIO,
+				 FIELD_PREP(AN8855_RG_QP_CDR_LPF_RATIO, val));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_SETVALUE,
+				 AN8855_RG_QP_CDR_PR_BUF_IN_SR |
+				 AN8855_RG_QP_CDR_PR_BETA_SEL,
+				 FIELD_PREP(AN8855_RG_QP_CDR_PR_BUF_IN_SR, 0x6) |
+				 FIELD_PREP(AN8855_RG_QP_CDR_PR_BETA_SEL, 0x1));
+	if (ret)
+		return ret;
+
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0xf;
+	else
+		val = 0xc;
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_CKREF_DIV1,
+				 AN8855_RG_QP_CDR_PR_DAC_BAND,
+				 FIELD_PREP(AN8855_RG_QP_CDR_PR_DAC_BAND, val));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE,
+				 AN8855_RG_QP_CDR_PR_KBAND_PCIE_MODE |
+				 AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK,
+				 FIELD_PREP(AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK, 0x19));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_FORCE_IBANDLPF_R_OFF,
+				 AN8855_RG_QP_CDR_PHYCK_SEL |
+				 AN8855_RG_QP_CDR_PHYCK_RSTB |
+				 AN8855_RG_QP_CDR_PHYCK_DIV,
+				 FIELD_PREP(AN8855_RG_QP_CDR_PHYCK_SEL, 0x2) |
+				 FIELD_PREP(AN8855_RG_QP_CDR_PHYCK_DIV, 0x21));
+	if (ret)
+		return ret;
+
+	ret = regmap_clear_bits(priv->regmap, AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE,
+				AN8855_RG_QP_CDR_PR_XFICK_EN);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_CKREF_DIV1,
+				 AN8855_RG_QP_CDR_PR_KBAND_DIV,
+				 FIELD_PREP(AN8855_RG_QP_CDR_PR_KBAND_DIV, 0x4));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_26,
+				 AN8855_RG_QP_EQ_RETRAIN_ONLY_EN |
+				 AN8855_RG_LINK_NE_EN |
+				 AN8855_RG_LINK_ERRO_EN,
+				 AN8855_RG_QP_EQ_RETRAIN_ONLY_EN |
+				 AN8855_RG_LINK_ERRO_EN);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_DLY_0,
+				 AN8855_RG_QP_RX_SAOSC_EN_H_DLY |
+				 AN8855_RG_QP_RX_PI_CAL_EN_H_DLY,
+				 FIELD_PREP(AN8855_RG_QP_RX_SAOSC_EN_H_DLY, 0x3f) |
+				 FIELD_PREP(AN8855_RG_QP_RX_PI_CAL_EN_H_DLY, 0x6f));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_42,
+				 AN8855_RG_QP_EQ_EN_DLY,
+				 FIELD_PREP(AN8855_RG_QP_EQ_EN_DLY, 0x150));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_2,
+				 AN8855_RG_QP_RX_EQ_EN_H_DLY,
+				 FIELD_PREP(AN8855_RG_QP_RX_EQ_EN_H_DLY, 0x150));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_PON_RXFEDIG_CTRL_9,
+				 AN8855_RG_QP_EQ_LEQOSC_DLYCNT,
+				 FIELD_PREP(AN8855_RG_QP_EQ_LEQOSC_DLYCNT, 0x1));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_8,
+				 AN8855_RG_DA_QP_SAOSC_DONE_TIME |
+				 AN8855_RG_DA_QP_LEQOS_EN_TIME,
+				 FIELD_PREP(AN8855_RG_DA_QP_SAOSC_DONE_TIME, 0x200) |
+				 FIELD_PREP(AN8855_RG_DA_QP_LEQOS_EN_TIME, 0xfff));
+	if (ret)
+		return ret;
+
+	/* Frequency meter */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+		val = 0x10;
+	else
+		val = 0x28;
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_5,
+				 AN8855_RG_FREDET_CHK_CYCLE,
+				 FIELD_PREP(AN8855_RG_FREDET_CHK_CYCLE, val));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_6,
+				 AN8855_RG_FREDET_GOLDEN_CYCLE,
+				 FIELD_PREP(AN8855_RG_FREDET_GOLDEN_CYCLE, 0x64));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_7,
+				 AN8855_RG_FREDET_TOLERATE_CYCLE,
+				 FIELD_PREP(AN8855_RG_FREDET_TOLERATE_CYCLE, 0x2710));
+	if (ret)
+		return ret;
+
+	ret = regmap_set_bits(priv->regmap, AN8855_PLL_CTRL_0,
+			      AN8855_RG_PHYA_AUTO_INIT);
+	if (ret)
+		return ret;
+
+	/* PCS Init */
+	if (interface == PHY_INTERFACE_MODE_SGMII &&
+	    neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED) {
+		ret = regmap_clear_bits(priv->regmap, AN8855_QP_DIG_MODE_CTRL_0,
+					AN8855_RG_SGMII_MODE | AN8855_RG_SGMII_AN_EN);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_clear_bits(priv->regmap, AN8855_RG_HSGMII_PCS_CTROL_1,
+				AN8855_RG_TBI_10B_MODE);
+	if (ret)
+		return ret;
+
+	if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
+		/* Set AN Ability - Interrupt */
+		ret = regmap_set_bits(priv->regmap, AN8855_SGMII_REG_AN_FORCE_CL37,
+				      AN8855_RG_FORCE_AN_DONE);
+		if (ret)
+			return ret;
+
+		ret = regmap_update_bits(priv->regmap, AN8855_SGMII_REG_AN_13,
+					 AN8855_SGMII_REMOTE_FAULT_DIS |
+					 AN8855_SGMII_IF_MODE,
+					 AN8855_SGMII_REMOTE_FAULT_DIS |
+					 FIELD_PREP(AN8855_SGMII_IF_MODE, 0xb));
+		if (ret)
+			return ret;
+	}
+
+	/* Rate Adaption - GMII path config. */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX) {
+		ret = regmap_clear_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0,
+					AN8855_RG_P0_DIS_MII_MODE);
+		if (ret)
+			return ret;
+	} else {
+		if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
+			ret = regmap_set_bits(priv->regmap, AN8855_MII_RA_AN_ENABLE,
+					      AN8855_RG_P0_RA_AN_EN);
+			if (ret)
+				return ret;
+		} else {
+			ret = regmap_update_bits(priv->regmap, AN8855_RG_AN_SGMII_MODE_FORCE,
+						 AN8855_RG_FORCE_CUR_SGMII_MODE |
+						 AN8855_RG_FORCE_CUR_SGMII_SEL,
+						 AN8855_RG_FORCE_CUR_SGMII_SEL);
+			if (ret)
+				return ret;
+
+			ret = regmap_clear_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0,
+						AN8855_RG_P0_MII_RA_RX_EN |
+						AN8855_RG_P0_MII_RA_TX_EN |
+						AN8855_RG_P0_MII_RA_RX_MODE |
+						AN8855_RG_P0_MII_RA_TX_MODE);
+			if (ret)
+				return ret;
+		}
+
+		ret = regmap_set_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0,
+				      AN8855_RG_P0_MII_MODE);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_set_bits(priv->regmap, AN8855_RG_RATE_ADAPT_CTRL_0,
+			      AN8855_RG_RATE_ADAPT_RX_BYPASS |
+			      AN8855_RG_RATE_ADAPT_TX_BYPASS |
+			      AN8855_RG_RATE_ADAPT_RX_EN |
+			      AN8855_RG_RATE_ADAPT_TX_EN);
+	if (ret)
+		return ret;
+
+	/* Disable AN if not in autoneg */
+	ret = regmap_update_bits(priv->regmap, AN8855_SGMII_REG_AN0, BMCR_ANENABLE,
+				 neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE :
+									      0);
+	if (ret)
+		return ret;
+
+	if (interface == PHY_INTERFACE_MODE_SGMII) {
+		/* Follow SDK init flow with restarting AN after AN enable */
+		if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
+			ret = regmap_set_bits(priv->regmap, AN8855_SGMII_REG_AN0,
+					      BMCR_ANRESTART);
+			if (ret)
+				return ret;
+		} else {
+			ret = regmap_set_bits(priv->regmap, AN8855_PHY_RX_FORCE_CTRL_0,
+					      AN8855_RG_FORCE_TXC_SEL);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Force Speed with fixed-link or 2500base-x as doesn't support aneg */
+	if (interface == PHY_INTERFACE_MODE_2500BASEX ||
+	    neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
+		if (interface == PHY_INTERFACE_MODE_2500BASEX)
+			val = AN8855_RG_LINK_MODE_P0_SPEED_2500;
+		else
+			val = AN8855_RG_LINK_MODE_P0_SPEED_1000;
+		ret = regmap_update_bits(priv->regmap, AN8855_SGMII_STS_CTRL_0,
+					 AN8855_RG_LINK_MODE_P0 |
+					 AN8855_RG_FORCE_SPD_MODE_P0,
+					 val | AN8855_RG_FORCE_SPD_MODE_P0);
+		if (ret)
+			return ret;
+	}
+
+	/* bypass flow control to MAC */
+	ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_0,
+			   AN8855_RG_DPX_STS_P3 | AN8855_RG_DPX_STS_P2 |
+			   AN8855_RG_DPX_STS_P1 | AN8855_RG_TXFC_STS_P0 |
+			   AN8855_RG_RXFC_STS_P0 | AN8855_RG_DPX_STS_P0);
+	if (ret)
+		return ret;
+	ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_2,
+			   AN8855_RG_RXFC_AN_BYPASS_P3 |
+			   AN8855_RG_RXFC_AN_BYPASS_P2 |
+			   AN8855_RG_RXFC_AN_BYPASS_P1 |
+			   AN8855_RG_TXFC_AN_BYPASS_P3 |
+			   AN8855_RG_TXFC_AN_BYPASS_P2 |
+			   AN8855_RG_TXFC_AN_BYPASS_P1 |
+			   AN8855_RG_DPX_AN_BYPASS_P3 |
+			   AN8855_RG_DPX_AN_BYPASS_P2 |
+			   AN8855_RG_DPX_AN_BYPASS_P1 |
+			   AN8855_RG_DPX_AN_BYPASS_P0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void an8855_pcs_an_restart(struct phylink_pcs *pcs)
+{
+	return;
+}
+
+static const struct phylink_pcs_ops an8855_pcs_ops = {
+	.pcs_inband_caps = an8855_pcs_inband_caps,
+	.pcs_get_state = an8855_pcs_get_state,
+	.pcs_config = an8855_pcs_config,
+	.pcs_an_restart = an8855_pcs_an_restart,
+};
+
+static const struct phylink_mac_ops an8855_phylink_mac_ops = {
+	.mac_select_pcs	= an8855_phylink_mac_select_pcs,
+	.mac_config	= an8855_phylink_mac_config,
+	.mac_link_down	= an8855_phylink_mac_link_down,
+	.mac_link_up	= an8855_phylink_mac_link_up,
+};
+
+static const struct dsa_switch_ops an8855_switch_ops = {
+	.get_tag_protocol = an8855_get_tag_protocol,
+	.setup = an8855_setup,
+	.phylink_get_caps = an8855_phylink_get_caps,
+	.get_strings = an8855_get_strings,
+	.get_ethtool_stats = an8855_get_ethtool_stats,
+	.get_sset_count = an8855_get_sset_count,
+	.get_eth_mac_stats = an8855_get_eth_mac_stats,
+	.get_eth_ctrl_stats = an8855_get_eth_ctrl_stats,
+	.get_rmon_stats = an8855_get_rmon_stats,
+	.port_enable = an8855_port_enable,
+	.port_disable = an8855_port_disable,
+	.set_ageing_time = an8855_set_ageing_time,
+	.port_bridge_join = an8855_port_bridge_join,
+	.port_bridge_leave = an8855_port_bridge_leave,
+	.port_fast_age = an8855_port_fast_age,
+	.port_stp_state_set = an8855_port_stp_state_set,
+	.port_pre_bridge_flags = an8855_port_pre_bridge_flags,
+	.port_bridge_flags = an8855_port_bridge_flags,
+	.port_vlan_filtering = an8855_port_vlan_filtering,
+	.port_vlan_add = an8855_port_vlan_add,
+	.port_vlan_del = an8855_port_vlan_del,
+	.port_fdb_add = an8855_port_fdb_add,
+	.port_fdb_del = an8855_port_fdb_del,
+	.port_fdb_dump = an8855_port_fdb_dump,
+	.port_mdb_add = an8855_port_mdb_add,
+	.port_mdb_del = an8855_port_mdb_del,
+	.port_change_mtu = an8855_port_change_mtu,
+	.port_max_mtu = an8855_port_max_mtu,
+	.port_mirror_add = an8855_port_mirror_add,
+	.port_mirror_del = an8855_port_mirror_del,
+};
+
+static int an8855_switch_probe(struct platform_device *pdev)
+{
+	struct an8855_priv *priv;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* Get regmap from MFD */
+	priv->regmap = dev_get_regmap(pdev->dev.parent, "switch");
+
+	priv->ds = devm_kzalloc(&pdev->dev, sizeof(*priv->ds), GFP_KERNEL);
+	if (!priv->ds)
+		return -ENOMEM;
+
+	priv->ds->dev = &pdev->dev;
+	priv->ds->num_ports = AN8855_NUM_PORTS;
+	priv->ds->priv = priv;
+	priv->ds->ops = &an8855_switch_ops;
+	devm_mutex_init(&pdev->dev, &priv->reg_mutex);
+	priv->ds->phylink_mac_ops = &an8855_phylink_mac_ops;
+
+	priv->pcs.ops = &an8855_pcs_ops;
+	priv->pcs.poll = true;
+
+	dev_set_drvdata(&pdev->dev, priv);
+
+	return dsa_register_switch(priv->ds);
+}
+
+static void an8855_switch_remove(struct platform_device *pdev)
+{
+	struct an8855_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return;
+
+	dsa_unregister_switch(priv->ds);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static void an8855_switch_shutdown(struct platform_device *pdev)
+{
+	struct an8855_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return;
+
+	dsa_switch_shutdown(priv->ds);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static const struct of_device_id an8855_switch_of_match[] = {
+	{ .compatible = "airoha,an8855-switch" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_switch_of_match);
+
+static struct platform_driver an8855_switch_driver = {
+	.probe = an8855_switch_probe,
+	.remove = an8855_switch_remove,
+	.shutdown = an8855_switch_shutdown,
+	.driver = {
+		.name = "an8855-switch",
+		.of_match_table = an8855_switch_of_match,
+	},
+};
+module_platform_driver(an8855_switch_driver);
+
+MODULE_AUTHOR("Min Yao <min.yao at airoha.com>");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 Switch");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/an8855.h b/drivers/net/dsa/an8855.h
new file mode 100644
index 000000000000..ccde07eab800
--- /dev/null
+++ b/drivers/net/dsa/an8855.h
@@ -0,0 +1,771 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 Min Yao <min.yao at airoha.com>
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#ifndef __AN8855_H
+#define __AN8855_H
+
+#include <linux/bitfield.h>
+
+#define AN8855_NUM_PORTS		6
+#define AN8855_CPU_PORT			5
+#define AN8855_NUM_FDB_RECORDS		2048
+#define AN8855_GPHY_SMI_ADDR_DEFAULT	1
+#define AN8855_PORT_VID_DEFAULT		0
+
+#define MTK_TAG_LEN			4
+#define AN8855_MAX_MTU			(15360 - ETH_HLEN - ETH_FCS_LEN - MTK_TAG_LEN)
+
+#define AN8855_L2_AGING_MS_CONSTANT	1024
+
+/*	AN8855_SCU			0x10000000 */
+#define AN8855_RG_GPIO_LED_MODE		0x10000054
+#define AN8855_RG_GPIO_LED_SEL(i)	(0x10000000 + (0x0058 + ((i) * 4)))
+#define AN8855_RG_INTB_MODE		0x10000080
+#define AN8855_RG_RGMII_TXCK_C		0x100001d0
+
+#define AN8855_PKG_SEL			0x10000094
+#define   AN8855_PAG_SEL_AN8855H	0x2
+
+#define AN8855_RG_GPIO_L_INV		0x10000010
+#define AN8855_RG_GPIO_CTRL		0x1000a300
+#define AN8855_RG_GPIO_DATA		0x1000a304
+#define AN8855_RG_GPIO_OE		0x1000a314
+
+/* Register for system reset */
+#define AN8855_RST_CTRL			0x100050c0
+#define   AN8855_SYS_CTRL_SYS_RST	BIT(31)
+
+#define AN8855_INT_MASK			0x100050f0
+#define   AN8855_INT_SYS		BIT(15)
+
+#define AN8855_RG_CLK_CPU_ICG		0x10005034
+#define   AN8855_MCU_ENABLE		BIT(3)
+
+#define AN8855_RG_TIMER_CTL		0x1000a100
+#define   AN8855_WDOG_ENABLE		BIT(25)
+
+#define AN8855_RG_GDMP_RAM		0x10010000
+
+/* Registers to mac forward control for unknown frames */
+#define AN8855_MFC			0x10200010
+#define   AN8855_CPU_EN			BIT(15)
+#define   AN8855_CPU_PORT_IDX		GENMASK(12, 8)
+
+#define AN8855_PAC			0x10200024
+#define   AN8855_TAG_PAE_MANG_FR	BIT(30)
+#define   AN8855_TAG_PAE_BPDU_FR	BIT(28)
+#define   AN8855_TAG_PAE_EG_TAG		GENMASK(27, 25)
+#define   AN8855_TAG_PAE_LKY_VLAN	BIT(24)
+#define   AN8855_TAG_PAE_PRI_HIGH	BIT(23)
+#define   AN8855_TAG_PAE_MIR		GENMASK(20, 19)
+#define   AN8855_TAG_PAE_PORT_FW	GENMASK(18, 16)
+#define   AN8855_PAE_MANG_FR		BIT(14)
+#define   AN8855_PAE_BPDU_FR		BIT(12)
+#define   AN8855_PAE_EG_TAG		GENMASK(11, 9)
+#define   AN8855_PAE_LKY_VLAN		BIT(8)
+#define   AN8855_PAE_PRI_HIGH		BIT(7)
+#define   AN8855_PAE_MIR		GENMASK(4, 3)
+#define   AN8855_PAE_PORT_FW		GENMASK(2, 0)
+
+#define AN8855_RGAC1			0x10200028
+#define   AN8855_R02_MANG_FR		BIT(30)
+#define   AN8855_R02_BPDU_FR		BIT(28)
+#define   AN8855_R02_EG_TAG		GENMASK(27, 25)
+#define   AN8855_R02_LKY_VLAN		BIT(24)
+#define   AN8855_R02_PRI_HIGH		BIT(23)
+#define   AN8855_R02_MIR		GENMASK(20, 19)
+#define   AN8855_R02_PORT_FW		GENMASK(18, 16)
+#define   AN8855_R01_MANG_FR		BIT(14)
+#define   AN8855_R01_BPDU_FR		BIT(12)
+#define   AN8855_R01_EG_TAG		GENMASK(11, 9)
+#define   AN8855_R01_LKY_VLAN		BIT(8)
+#define   AN8855_R01_PRI_HIGH		BIT(7)
+#define   AN8855_R01_MIR		GENMASK(4, 3)
+#define   AN8855_R01_PORT_FW		GENMASK(2, 0)
+
+#define AN8855_RGAC2			0x1020002c
+#define   AN8855_R0E_MANG_FR		BIT(30)
+#define   AN8855_R0E_BPDU_FR		BIT(28)
+#define   AN8855_R0E_EG_TAG		GENMASK(27, 25)
+#define   AN8855_R0E_LKY_VLAN		BIT(24)
+#define   AN8855_R0E_PRI_HIGH		BIT(23)
+#define   AN8855_R0E_MIR		GENMASK(20, 19)
+#define   AN8855_R0E_PORT_FW		GENMASK(18, 16)
+#define   AN8855_R03_MANG_FR		BIT(14)
+#define   AN8855_R03_BPDU_FR		BIT(12)
+#define   AN8855_R03_EG_TAG		GENMASK(11, 9)
+#define   AN8855_R03_LKY_VLAN		BIT(8)
+#define   AN8855_R03_PRI_HIGH		BIT(7)
+#define   AN8855_R03_MIR		GENMASK(4, 3)
+#define   AN8855_R03_PORT_FW		GENMASK(2, 0)
+
+#define AN8855_AAC			0x102000a0
+#define   AN8855_MAC_AUTO_FLUSH		BIT(28)
+/* Control Address Table Age time.
+ * (AN8855_AGE_CNT + 1) * ( AN8855_AGE_UNIT + 1 ) * AN8855_L2_AGING_MS_CONSTANT
+ */
+#define   AN8855_AGE_CNT		GENMASK(20, 12)
+/* Value in seconds. Value is always incremented of 1 */
+#define   AN8855_AGE_UNIT		GENMASK(10, 0)
+
+/* Registers for ARL Unknown Unicast Forward control */
+#define AN8855_UNUF			0x102000b4
+
+/* Registers for ARL Unknown Multicast Forward control */
+#define AN8855_UNMF			0x102000b8
+
+/* Registers for ARL Broadcast forward control */
+#define AN8855_BCF			0x102000bc
+
+/* Registers for port address age disable */
+#define AN8855_AGDIS			0x102000c0
+
+/* Registers for mirror port control */
+#define AN8855_MIR			0x102000cc
+#define   AN8855_MIRROR_EN		BIT(7)
+#define   AN8855_MIRROR_PORT		GENMASK(4, 0)
+
+/* Registers for BPDU and PAE frame control*/
+#define AN8855_BPC			0x102000d0
+#define   AN8855_BPDU_MANG_FR		BIT(14)
+#define   AN8855_BPDU_BPDU_FR		BIT(12)
+#define   AN8855_BPDU_EG_TAG		GENMASK(11, 9)
+#define   AN8855_BPDU_LKY_VLAN		BIT(8)
+#define   AN8855_BPDU_PRI_HIGH		BIT(7)
+#define   AN8855_BPDU_MIR		GENMASK(4, 3)
+#define   AN8855_BPDU_PORT_FW		GENMASK(2, 0)
+
+/* Registers for IP Unknown Multicast Forward control */
+#define AN8855_UNIPMF			0x102000dc
+
+enum an8855_bpdu_port_fw {
+	AN8855_BPDU_FOLLOW_MFC = 0,
+	AN8855_BPDU_CPU_EXCLUDE = 4,
+	AN8855_BPDU_CPU_INCLUDE = 5,
+	AN8855_BPDU_CPU_ONLY = 6,
+	AN8855_BPDU_DROP = 7,
+};
+
+/* Register for address table control */
+#define AN8855_ATC			0x10200300
+#define   AN8855_ATC_BUSY		BIT(31)
+#define   AN8855_ATC_HASH		GENMASK(24, 16)
+#define   AN8855_ATC_HIT		GENMASK(15, 12)
+#define   AN8855_ATC_MAT_MASK		GENMASK(11, 7)
+#define   AN8855_ATC_MAT(x)		FIELD_PREP(AN8855_ATC_MAT_MASK, x)
+#define   AN8855_ATC_SAT		GENMASK(5, 4)
+#define   AN8855_ATC_CMD		GENMASK(2, 0)
+
+enum an8855_fdb_mat_cmds {
+	AND8855_FDB_MAT_ALL = 0,
+	AND8855_FDB_MAT_MAC, /* All MAC address */
+	AND8855_FDB_MAT_DYNAMIC_MAC, /* All Dynamic MAC address */
+	AND8855_FDB_MAT_STATIC_MAC, /* All Static Mac Address */
+	AND8855_FDB_MAT_DIP, /* All DIP/GA address */
+	AND8855_FDB_MAT_DIP_IPV4, /* All DIP/GA IPv4 address */
+	AND8855_FDB_MAT_DIP_IPV6, /* All DIP/GA IPv6 address */
+	AND8855_FDB_MAT_DIP_SIP, /* All DIP_SIP address */
+	AND8855_FDB_MAT_DIP_SIP_IPV4, /* All DIP_SIP IPv4 address */
+	AND8855_FDB_MAT_DIP_SIP_IPV6, /* All DIP_SIP IPv6 address */
+	AND8855_FDB_MAT_MAC_CVID, /* All MAC address with CVID */
+	AND8855_FDB_MAT_MAC_FID, /* All MAC address with Filter ID */
+	AND8855_FDB_MAT_MAC_PORT, /* All MAC address with port */
+	AND8855_FDB_MAT_DIP_SIP_DIP_IPV4, /* All DIP_SIP address with DIP_IPV4 */
+	AND8855_FDB_MAT_DIP_SIP_SIP_IPV4, /* All DIP_SIP address with SIP_IPV4 */
+	AND8855_FDB_MAT_DIP_SIP_DIP_IPV6, /* All DIP_SIP address with DIP_IPV6 */
+	AND8855_FDB_MAT_DIP_SIP_SIP_IPV6, /* All DIP_SIP address with SIP_IPV6 */
+	/* All MAC address with MAC type (dynamic or static) with CVID */
+	AND8855_FDB_MAT_MAC_TYPE_CVID,
+	/* All MAC address with MAC type (dynamic or static) with Filter ID */
+	AND8855_FDB_MAT_MAC_TYPE_FID,
+	/* All MAC address with MAC type (dynamic or static) with port */
+	AND8855_FDB_MAT_MAC_TYPE_PORT,
+};
+
+enum an8855_fdb_cmds {
+	AN8855_FDB_READ = 0,
+	AN8855_FDB_WRITE = 1,
+	AN8855_FDB_FLUSH = 2,
+	AN8855_FDB_START = 4,
+	AN8855_FDB_NEXT = 5,
+};
+
+/* Registers for address table access */
+#define AN8855_ATA1			0x10200304
+#define   AN8855_ATA1_MAC0		GENMASK(31, 24)
+#define   AN8855_ATA1_MAC1		GENMASK(23, 16)
+#define   AN8855_ATA1_MAC2		GENMASK(15, 8)
+#define   AN8855_ATA1_MAC3		GENMASK(7, 0)
+#define AN8855_ATA2			0x10200308
+#define   AN8855_ATA2_MAC4		GENMASK(31, 24)
+#define   AN8855_ATA2_MAC5		GENMASK(23, 16)
+#define   AN8855_ATA2_UNAUTH		BIT(10)
+#define   AN8855_ATA2_TYPE		BIT(9) /* 1: dynamic, 0: static */
+#define   AN8855_ATA2_AGE		GENMASK(8, 0)
+
+/* Register for address table write data */
+#define AN8855_ATWD			0x10200324
+#define   AN8855_ATWD_FID		GENMASK(31, 28)
+#define   AN8855_ATWD_VID		GENMASK(27, 16)
+#define   AN8855_ATWD_IVL		BIT(15)
+#define   AN8855_ATWD_EG_TAG		GENMASK(14, 12)
+#define   AN8855_ATWD_SA_MIR		GENMASK(9, 8)
+#define   AN8855_ATWD_SA_FWD		GENMASK(7, 5)
+#define   AN8855_ATWD_UPRI		GENMASK(4, 2)
+#define   AN8855_ATWD_LEAKY		BIT(1)
+#define   AN8855_ATWD_VLD		BIT(0) /* vid LOAD */
+#define AN8855_ATWD2			0x10200328
+#define   AN8855_ATWD2_PORT		GENMASK(7, 0)
+
+/* Registers for table search read address */
+#define AN8855_ATRDS			0x10200330
+#define   AN8855_ATRD_SEL		GENMASK(1, 0)
+#define AN8855_ATRD0			0x10200334
+#define   AN8855_ATRD0_FID		GENMASK(28, 25)
+#define   AN8855_ATRD0_VID		GENMASK(21, 10)
+#define   AN8855_ATRD0_IVL		BIT(9)
+#define   AN8855_ATRD0_TYPE		GENMASK(4, 3)
+#define   AN8855_ATRD0_ARP		GENMASK(2, 1)
+#define   AN8855_ATRD0_LIVE		BIT(0)
+#define AN8855_ATRD1			0x10200338
+#define   AN8855_ATRD1_MAC4		GENMASK(31, 24)
+#define   AN8855_ATRD1_MAC5		GENMASK(23, 16)
+#define   AN8855_ATRD1_AGING		GENMASK(11, 3)
+#define AN8855_ATRD2			0x1020033c
+#define   AN8855_ATRD2_MAC0		GENMASK(31, 24)
+#define   AN8855_ATRD2_MAC1		GENMASK(23, 16)
+#define   AN8855_ATRD2_MAC2		GENMASK(15, 8)
+#define   AN8855_ATRD2_MAC3		GENMASK(7, 0)
+#define AN8855_ATRD3			0x10200340
+#define   AN8855_ATRD3_PORTMASK		GENMASK(7, 0)
+
+enum an8855_fdb_type {
+	AN8855_MAC_TB_TY_MAC = 0,
+	AN8855_MAC_TB_TY_DIP = 1,
+	AN8855_MAC_TB_TY_DIP_SIP = 2,
+};
+
+/* Register for vlan table control */
+#define AN8855_VTCR			0x10200600
+#define   AN8855_VTCR_BUSY		BIT(31)
+#define   AN8855_VTCR_FUNC		GENMASK(15, 12)
+#define   AN8855_VTCR_VID		GENMASK(11, 0)
+
+enum an8855_vlan_cmd {
+	/* Read/Write the specified VID entry from VAWD register based
+	 * on VID.
+	 */
+	AN8855_VTCR_RD_VID = 0,
+	AN8855_VTCR_WR_VID = 1,
+};
+
+/* Register for setup vlan write data */
+#define AN8855_VAWD0			0x10200604
+/* VLAN Member Control */
+#define   AN8855_VA0_PORT		GENMASK(31, 26)
+/* Egress Tag Control */
+#define   AN8855_VA0_ETAG		GENMASK(23, 12)
+#define   AN8855_VA0_ETAG_PORT		GENMASK(13, 12)
+#define   AN8855_VA0_ETAG_PORT_SHIFT(port) ((port) * 2)
+#define   AN8855_VA0_ETAG_PORT_MASK(port) (AN8855_VA0_ETAG_PORT << \
+						AN8855_VA0_ETAG_PORT_SHIFT(port))
+#define   AN8855_VA0_ETAG_PORT_VAL(port, val) (FIELD_PREP(AN8855_VA0_ETAG_PORT, (val)) << \
+						AN8855_VA0_ETAG_PORT_SHIFT(port))
+#define   AN8855_VA0_EG_CON		BIT(11)
+#define   AN8855_VA0_VTAG_EN		BIT(10) /* Per VLAN Egress Tag Control */
+#define   AN8855_VA0_IVL_MAC		BIT(5) /* Independent VLAN Learning */
+#define	  AN8855_VA0_FID		GENMASK(4, 1)
+#define   AN8855_VA0_VLAN_VALID		BIT(0) /* VLAN Entry Valid */
+#define AN8855_VAWD1			0x10200608
+#define   AN8855_VA1_PORT_STAG		BIT(1)
+
+enum an8855_fid {
+	AN8855_FID_STANDALONE = 0,
+	AN8855_FID_BRIDGED = 1,
+};
+
+/* Same register field of VAWD0 */
+#define AN8855_VARD0			0x10200618
+
+enum an8855_vlan_egress_attr {
+	AN8855_VLAN_EGRESS_UNTAG = 0,
+	AN8855_VLAN_EGRESS_TAG = 2,
+	AN8855_VLAN_EGRESS_STACK = 3,
+};
+
+/* Register for port STP state control */
+#define AN8855_SSP_P(x)			(0x10208000 + ((x) * 0x200))
+/* Up to 16 FID supported, each with the same mask */
+#define	  AN8855_FID_PST		GENMASK(1, 0)
+#define   AN8855_FID_PST_SHIFT(fid)	(2 * (fid))
+#define   AN8855_FID_PST_MASK(fid)	(AN8855_FID_PST << \
+						AN8855_FID_PST_SHIFT(fid))
+#define   AN8855_FID_PST_VAL(fid, val)	(FIELD_PREP(AN8855_FID_PST, (val)) << \
+						AN8855_FID_PST_SHIFT(fid))
+
+enum an8855_stp_state {
+	AN8855_STP_DISABLED = 0,
+	AN8855_STP_BLOCKING = 1,
+	AN8855_STP_LISTENING = AN8855_STP_BLOCKING,
+	AN8855_STP_LEARNING = 2,
+	AN8855_STP_FORWARDING = 3
+};
+
+/* Register for port control */
+#define AN8855_PCR_P(x)			(0x10208004 + ((x) * 0x200))
+#define   AN8855_EG_TAG			GENMASK(29, 28)
+#define   AN8855_PORT_PRI		GENMASK(26, 24)
+#define   AN8855_PORT_TX_MIR		BIT(20)
+#define   AN8855_PORT_RX_MIR		BIT(16)
+#define   AN8855_PORT_VLAN		GENMASK(1, 0)
+
+enum an8855_port_mode {
+	/* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */
+	AN8855_PORT_MATRIX_MODE = 0,
+
+	/* Fallback Mode: Forward received frames with ingress ports that do
+	 * not belong to the VLAN member. Frames whose VID is not listed on
+	 * the VLAN table are forwarded by the PCR_MATRIX members.
+	 */
+	AN8855_PORT_FALLBACK_MODE = 1,
+
+	/* Check Mode: Forward received frames whose ingress do not
+	 * belong to the VLAN member. Discard frames if VID ismiddes on the
+	 * VLAN table.
+	 */
+	AN8855_PORT_CHECK_MODE = 2,
+
+	/* Security Mode: Discard any frame due to ingress membership
+	 * violation or VID missed on the VLAN table.
+	 */
+	AN8855_PORT_SECURITY_MODE = 3,
+};
+
+/* Register for port security control */
+#define AN8855_PSC_P(x)			(0x1020800c + ((x) * 0x200))
+#define   AN8855_SA_DIS			BIT(4)
+
+/* Register for port vlan control */
+#define AN8855_PVC_P(x)			(0x10208010 + ((x) * 0x200))
+#define   AN8855_PORT_SPEC_REPLACE_MODE	BIT(11)
+#define   AN8855_PVC_EG_TAG		GENMASK(10, 8)
+#define   AN8855_VLAN_ATTR		GENMASK(7, 6)
+#define   AN8855_PORT_SPEC_TAG		BIT(5)
+#define   AN8855_ACC_FRM		GENMASK(1, 0)
+
+enum an8855_vlan_port_eg_tag {
+	AN8855_VLAN_EG_DISABLED = 0,
+	AN8855_VLAN_EG_CONSISTENT = 1,
+	AN8855_VLAN_EG_UNTAGGED = 4,
+	AN8855_VLAN_EG_SWAP = 5,
+	AN8855_VLAN_EG_TAGGED = 6,
+	AN8855_VLAN_EG_STACK = 7,
+};
+
+enum an8855_vlan_port_attr {
+	AN8855_VLAN_USER = 0,
+	AN8855_VLAN_STACK = 1,
+	AN8855_VLAN_TRANSPARENT = 3,
+};
+
+enum an8855_vlan_port_acc_frm {
+	AN8855_VLAN_ACC_ALL = 0,
+	AN8855_VLAN_ACC_TAGGED = 1,
+	AN8855_VLAN_ACC_UNTAGGED = 2,
+};
+
+#define AN8855_PPBV1_P(x)		(0x10208014 + ((x) * 0x200))
+#define   AN8855_PPBV_G0_PORT_VID	GENMASK(11, 0)
+
+#define AN8855_PORTMATRIX_P(x)		(0x10208044 + ((x) * 0x200))
+#define   AN8855_PORTMATRIX		GENMASK(5, 0)
+/* Port matrix without the CPU port that should never be removed */
+#define   AN8855_USER_PORTMATRIX	GENMASK(4, 0)
+
+/* Register for port PVID */
+#define AN8855_PVID_P(x)		(0x10208048 + ((x) * 0x200))
+#define   AN8855_G0_PORT_VID		GENMASK(11, 0)
+
+/* Register for port MAC control register */
+#define AN8855_PMCR_P(x)		(0x10210000 + ((x) * 0x200))
+#define   AN8855_PMCR_FORCE_MODE	BIT(31)
+#define   AN8855_PMCR_FORCE_SPEED	GENMASK(30, 28)
+#define   AN8855_PMCR_FORCE_SPEED_5000	FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x4)
+#define   AN8855_PMCR_FORCE_SPEED_2500	FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x3)
+#define   AN8855_PMCR_FORCE_SPEED_1000	FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x2)
+#define   AN8855_PMCR_FORCE_SPEED_100	FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1)
+#define   AN8855_PMCR_FORCE_SPEED_10	FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1)
+#define   AN8855_PMCR_FORCE_FDX		BIT(25)
+#define   AN8855_PMCR_FORCE_LNK		BIT(24)
+#define   AN8855_PMCR_IFG_XMIT		GENMASK(21, 20)
+#define   AN8855_PMCR_EXT_PHY		BIT(19)
+#define   AN8855_PMCR_MAC_MODE		BIT(18)
+#define   AN8855_PMCR_TX_EN		BIT(16)
+#define   AN8855_PMCR_RX_EN		BIT(15)
+#define   AN8855_PMCR_BACKOFF_EN	BIT(12)
+#define   AN8855_PMCR_BACKPR_EN		BIT(11)
+#define   AN8855_PMCR_FORCE_EEE5G	BIT(9)
+#define   AN8855_PMCR_FORCE_EEE2P5G	BIT(8)
+#define   AN8855_PMCR_FORCE_EEE1G	BIT(7)
+#define   AN8855_PMCR_FORCE_EEE100	BIT(6)
+#define   AN8855_PMCR_TX_FC_EN		BIT(5)
+#define   AN8855_PMCR_RX_FC_EN		BIT(4)
+
+#define AN8855_PMSR_P(x)		(0x10210010 + (x) * 0x200)
+#define   AN8855_PMSR_SPEED		GENMASK(30, 28)
+#define   AN8855_PMSR_SPEED_5000	FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x4)
+#define   AN8855_PMSR_SPEED_2500	FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x3)
+#define   AN8855_PMSR_SPEED_1000	FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x2)
+#define   AN8855_PMSR_SPEED_100		FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x1)
+#define   AN8855_PMSR_SPEED_10		FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x0)
+#define   AN8855_PMSR_DPX		BIT(25)
+#define   AN8855_PMSR_LNK		BIT(24)
+#define   AN8855_PMSR_EEE1G		BIT(7)
+#define   AN8855_PMSR_EEE100M		BIT(6)
+#define   AN8855_PMSR_RX_FC		BIT(5)
+#define   AN8855_PMSR_TX_FC		BIT(4)
+
+#define AN8855_PMEEECR_P(x)		(0x10210004 + (x) * 0x200)
+#define   AN8855_LPI_MODE_EN		BIT(31)
+#define   AN8855_WAKEUP_TIME_2500	GENMASK(23, 16)
+#define   AN8855_WAKEUP_TIME_1000	GENMASK(15, 8)
+#define   AN8855_WAKEUP_TIME_100	GENMASK(7, 0)
+#define AN8855_PMEEECR2_P(x)		(0x10210008 + (x) * 0x200)
+#define   AN8855_WAKEUP_TIME_5000	GENMASK(7, 0)
+
+#define AN8855_GMACCR			0x10213e00
+#define   AN8855_MAX_RX_JUMBO		GENMASK(7, 4)
+/* 2K for 0x0, 0x1, 0x2 */
+#define   AN8855_MAX_RX_JUMBO_2K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x0)
+#define   AN8855_MAX_RX_JUMBO_3K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x3)
+#define   AN8855_MAX_RX_JUMBO_4K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x4)
+#define   AN8855_MAX_RX_JUMBO_5K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x5)
+#define   AN8855_MAX_RX_JUMBO_6K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x6)
+#define   AN8855_MAX_RX_JUMBO_7K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x7)
+#define   AN8855_MAX_RX_JUMBO_8K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x8)
+#define   AN8855_MAX_RX_JUMBO_9K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x9)
+#define   AN8855_MAX_RX_JUMBO_12K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xa)
+#define   AN8855_MAX_RX_JUMBO_15K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xb)
+#define   AN8855_MAX_RX_JUMBO_16K	FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xc)
+#define   AN8855_MAX_RX_PKT_LEN		GENMASK(1, 0)
+#define   AN8855_MAX_RX_PKT_1518_1522	FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x0)
+#define   AN8855_MAX_RX_PKT_1536	FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x1)
+#define   AN8855_MAX_RX_PKT_1552	FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x2)
+#define   AN8855_MAX_RX_PKT_JUMBO	FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x3)
+
+#define AN8855_CKGCR			0x10213e1c
+#define   AN8855_LPI_TXIDLE_THD_MASK	GENMASK(31, 14)
+#define   AN8855_CKG_LNKDN_PORT_STOP	BIT(1)
+#define   AN8855_CKG_LNKDN_GLB_STOP	BIT(0)
+
+/* Register for MIB */
+#define AN8855_PORT_MIB_COUNTER(x)	(0x10214000 + (x) * 0x200)
+/* Each define is an offset of AN8855_PORT_MIB_COUNTER */
+#define   AN8855_PORT_MIB_TX_DROP	0x00
+#define   AN8855_PORT_MIB_TX_CRC_ERR	0x04
+#define   AN8855_PORT_MIB_TX_UNICAST	0x08
+#define   AN8855_PORT_MIB_TX_MULTICAST	0x0c
+#define   AN8855_PORT_MIB_TX_BROADCAST	0x10
+#define   AN8855_PORT_MIB_TX_COLLISION	0x14
+#define   AN8855_PORT_MIB_TX_SINGLE_COLLISION 0x18
+#define   AN8855_PORT_MIB_TX_MULTIPLE_COLLISION 0x1c
+#define   AN8855_PORT_MIB_TX_DEFERRED	0x20
+#define   AN8855_PORT_MIB_TX_LATE_COLLISION 0x24
+#define   AN8855_PORT_MIB_TX_EXCESSIVE_COLLISION 0x28
+#define   AN8855_PORT_MIB_TX_PAUSE	0x2c
+#define   AN8855_PORT_MIB_TX_PKT_SZ_64	0x30
+#define   AN8855_PORT_MIB_TX_PKT_SZ_65_TO_127 0x34
+#define   AN8855_PORT_MIB_TX_PKT_SZ_128_TO_255 0x38
+#define   AN8855_PORT_MIB_TX_PKT_SZ_256_TO_511 0x3
+#define   AN8855_PORT_MIB_TX_PKT_SZ_512_TO_1023 0x40
+#define   AN8855_PORT_MIB_TX_PKT_SZ_1024_TO_1518 0x44
+#define   AN8855_PORT_MIB_TX_PKT_SZ_1519_TO_MAX 0x48
+#define   AN8855_PORT_MIB_TX_BYTES	0x4c /* 64 bytes */
+#define   AN8855_PORT_MIB_TX_OVERSIZE_DROP 0x54
+#define   AN8855_PORT_MIB_TX_BAD_PKT_BYTES 0x58 /* 64 bytes */
+#define   AN8855_PORT_MIB_RX_DROP	0x80
+#define   AN8855_PORT_MIB_RX_FILTERING	0x84
+#define   AN8855_PORT_MIB_RX_UNICAST	0x88
+#define   AN8855_PORT_MIB_RX_MULTICAST	0x8c
+#define   AN8855_PORT_MIB_RX_BROADCAST	0x90
+#define   AN8855_PORT_MIB_RX_ALIGN_ERR	0x94
+#define   AN8855_PORT_MIB_RX_CRC_ERR	0x98
+#define   AN8855_PORT_MIB_RX_UNDER_SIZE_ERR 0x9c
+#define   AN8855_PORT_MIB_RX_FRAG_ERR	0xa0
+#define   AN8855_PORT_MIB_RX_OVER_SZ_ERR 0xa4
+#define   AN8855_PORT_MIB_RX_JABBER_ERR	0xa8
+#define   AN8855_PORT_MIB_RX_PAUSE	0xac
+#define   AN8855_PORT_MIB_RX_PKT_SZ_64	0xb0
+#define   AN8855_PORT_MIB_RX_PKT_SZ_65_TO_127 0xb4
+#define   AN8855_PORT_MIB_RX_PKT_SZ_128_TO_255 0xb8
+#define   AN8855_PORT_MIB_RX_PKT_SZ_256_TO_511 0xbc
+#define   AN8855_PORT_MIB_RX_PKT_SZ_512_TO_1023 0xc0
+#define   AN8855_PORT_MIB_RX_PKT_SZ_1024_TO_1518 0xc4
+#define   AN8855_PORT_MIB_RX_PKT_SZ_1519_TO_MAX 0xc8
+#define   AN8855_PORT_MIB_RX_BYTES	0xcc /* 64 bytes */
+#define   AN8855_PORT_MIB_RX_CTRL_DROP	0xd4
+#define   AN8855_PORT_MIB_RX_INGRESS_DROP 0xd8
+#define   AN8855_PORT_MIB_RX_ARL_DROP	0xdc
+#define   AN8855_PORT_MIB_FLOW_CONTROL_DROP 0xe0
+#define   AN8855_PORT_MIB_WRED_DROP	0xe4
+#define   AN8855_PORT_MIB_MIRROR_DROP	0xe8
+#define   AN8855_PORT_MIB_RX_BAD_PKT_BYTES 0xec /* 64 bytes */
+#define   AN8855_PORT_MIB_RXS_FLOW_SAMPLING_PKT_DROP 0xf4
+#define   AN8855_PORT_MIB_RXS_FLOW_TOTAL_PKT_DROP 0xf8
+#define   AN8855_PORT_MIB_PORT_CONTROL_DROP 0xfc
+#define AN8855_MIB_CCR			0x10213e30
+#define   AN8855_CCR_MIB_ENABLE		BIT(31)
+#define   AN8855_CCR_RX_OCT_CNT_GOOD	BIT(7)
+#define   AN8855_CCR_RX_OCT_CNT_BAD	BIT(6)
+#define   AN8855_CCR_TX_OCT_CNT_GOOD	BIT(5)
+#define   AN8855_CCR_TX_OCT_CNT_BAD	BIT(4)
+#define   AN8855_CCR_RX_OCT_CNT_GOOD_2	BIT(3)
+#define   AN8855_CCR_RX_OCT_CNT_BAD_2	BIT(2)
+#define   AN8855_CCR_TX_OCT_CNT_GOOD_2	BIT(1)
+#define   AN8855_CCR_TX_OCT_CNT_BAD_2	BIT(0)
+#define   AN8855_CCR_MIB_ACTIVATE	(AN8855_CCR_MIB_ENABLE | \
+					 AN8855_CCR_RX_OCT_CNT_GOOD | \
+					 AN8855_CCR_RX_OCT_CNT_BAD | \
+					 AN8855_CCR_TX_OCT_CNT_GOOD | \
+					 AN8855_CCR_TX_OCT_CNT_BAD | \
+					 AN8855_CCR_RX_OCT_CNT_BAD_2 | \
+					 AN8855_CCR_TX_OCT_CNT_BAD_2)
+#define AN8855_MIB_CLR			0x10213e34
+#define   AN8855_MIB_PORT6_CLR		BIT(6)
+#define   AN8855_MIB_PORT5_CLR		BIT(5)
+#define   AN8855_MIB_PORT4_CLR		BIT(4)
+#define   AN8855_MIB_PORT3_CLR		BIT(3)
+#define   AN8855_MIB_PORT2_CLR		BIT(2)
+#define   AN8855_MIB_PORT1_CLR		BIT(1)
+#define   AN8855_MIB_PORT0_CLR		BIT(0)
+
+/* HSGMII/SGMII Configuration register */
+/*	AN8855_HSGMII_AN_CSR_BASE	0x10220000 */
+#define AN8855_SGMII_REG_AN0		0x10220000
+/*        AN8855_SGMII_AN_ENABLE	BMCR_ANENABLE */
+/*        AN8855_SGMII_AN_RESTART	BMCR_ANRESTART */
+#define AN8855_SGMII_REG_AN_13		0x10220034
+#define   AN8855_SGMII_REMOTE_FAULT_DIS	BIT(8)
+#define   AN8855_SGMII_IF_MODE		GENMASK(5, 0)
+#define AN8855_SGMII_REG_AN_FORCE_CL37	0x10220060
+#define   AN8855_RG_FORCE_AN_DONE	BIT(0)
+
+/*	AN8855_HSGMII_CSR_PCS_BASE	0x10220000 */
+#define AN8855_RG_HSGMII_PCS_CTROL_1	0x10220a00
+#define   AN8855_RG_TBI_10B_MODE	BIT(30)
+#define AN8855_RG_AN_SGMII_MODE_FORCE	0x10220a24
+#define   AN8855_RG_FORCE_CUR_SGMII_MODE GENMASK(5, 4)
+#define   AN8855_RG_FORCE_CUR_SGMII_SEL	BIT(0)
+
+/*	AN8855_MULTI_SGMII_CSR_BASE	0x10224000 */
+#define AN8855_SGMII_STS_CTRL_0		0x10224018
+#define   AN8855_RG_LINK_MODE_P0	GENMASK(5, 4)
+#define   AN8855_RG_LINK_MODE_P0_SPEED_2500 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x3)
+#define   AN8855_RG_LINK_MODE_P0_SPEED_1000 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x2)
+#define   AN8855_RG_LINK_MODE_P0_SPEED_100 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x1)
+#define   AN8855_RG_LINK_MODE_P0_SPEED_10 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x0)
+#define   AN8855_RG_FORCE_SPD_MODE_P0	BIT(2)
+#define AN8855_MSG_RX_CTRL_0		0x10224100
+#define AN8855_MSG_RX_LIK_STS_0		0x10224514
+#define   AN8855_RG_DPX_STS_P3		BIT(24)
+#define   AN8855_RG_DPX_STS_P2		BIT(16)
+#define   AN8855_RG_EEE1G_STS_P1	BIT(12)
+#define   AN8855_RG_DPX_STS_P1		BIT(8)
+#define   AN8855_RG_TXFC_STS_P0		BIT(2)
+#define   AN8855_RG_RXFC_STS_P0		BIT(1)
+#define   AN8855_RG_DPX_STS_P0		BIT(0)
+#define AN8855_MSG_RX_LIK_STS_2		0x1022451c
+#define   AN8855_RG_RXFC_AN_BYPASS_P3	BIT(11)
+#define   AN8855_RG_RXFC_AN_BYPASS_P2	BIT(10)
+#define   AN8855_RG_RXFC_AN_BYPASS_P1	BIT(9)
+#define   AN8855_RG_TXFC_AN_BYPASS_P3	BIT(7)
+#define   AN8855_RG_TXFC_AN_BYPASS_P2	BIT(6)
+#define   AN8855_RG_TXFC_AN_BYPASS_P1	BIT(5)
+#define   AN8855_RG_DPX_AN_BYPASS_P3	BIT(3)
+#define   AN8855_RG_DPX_AN_BYPASS_P2	BIT(2)
+#define   AN8855_RG_DPX_AN_BYPASS_P1	BIT(1)
+#define   AN8855_RG_DPX_AN_BYPASS_P0	BIT(0)
+#define AN8855_PHY_RX_FORCE_CTRL_0	0x10224520
+#define   AN8855_RG_FORCE_TXC_SEL	BIT(4)
+
+/*	AN8855_XFI_CSR_PCS_BASE		0x10225000 */
+#define AN8855_RG_USXGMII_AN_CONTROL_0	0x10225bf8
+
+/*	AN8855_MULTI_PHY_RA_CSR_BASE	0x10226000 */
+#define AN8855_RG_RATE_ADAPT_CTRL_0	0x10226000
+#define   AN8855_RG_RATE_ADAPT_RX_BYPASS BIT(27)
+#define   AN8855_RG_RATE_ADAPT_TX_BYPASS BIT(26)
+#define   AN8855_RG_RATE_ADAPT_RX_EN	BIT(4)
+#define   AN8855_RG_RATE_ADAPT_TX_EN	BIT(0)
+#define AN8855_RATE_ADP_P0_CTRL_0	0x10226100
+#define   AN8855_RG_P0_DIS_MII_MODE	BIT(31)
+#define   AN8855_RG_P0_MII_MODE		BIT(28)
+#define   AN8855_RG_P0_MII_RA_RX_EN	BIT(3)
+#define   AN8855_RG_P0_MII_RA_TX_EN	BIT(2)
+#define   AN8855_RG_P0_MII_RA_RX_MODE	BIT(1)
+#define   AN8855_RG_P0_MII_RA_TX_MODE	BIT(0)
+#define AN8855_MII_RA_AN_ENABLE		0x10226300
+#define   AN8855_RG_P0_RA_AN_EN		BIT(0)
+
+/*	AN8855_QP_DIG_CSR_BASE		0x1022a000 */
+#define AN8855_QP_CK_RST_CTRL_4		0x1022a310
+#define AN8855_QP_DIG_MODE_CTRL_0	0x1022a324
+#define   AN8855_RG_SGMII_MODE		GENMASK(5, 4)
+#define   AN8855_RG_SGMII_AN_EN		BIT(0)
+#define AN8855_QP_DIG_MODE_CTRL_1	0x1022a330
+#define   AN8855_RG_TPHY_SPEED		GENMASK(3, 2)
+
+/*	AN8855_SERDES_WRAPPER_BASE	0x1022c000 */
+#define AN8855_USGMII_CTRL_0		0x1022c000
+
+/*	AN8855_QP_PMA_TOP_BASE		0x1022e000 */
+#define AN8855_PON_RXFEDIG_CTRL_0	0x1022e100
+#define   AN8855_RG_QP_EQ_RX500M_CK_SEL	BIT(12)
+#define AN8855_PON_RXFEDIG_CTRL_9	0x1022e124
+#define   AN8855_RG_QP_EQ_LEQOSC_DLYCNT	GENMASK(2, 0)
+
+#define AN8855_SS_LCPLL_PWCTL_SETTING_2	0x1022e208
+#define   AN8855_RG_NCPO_ANA_MSB	GENMASK(17, 16)
+#define AN8855_SS_LCPLL_TDC_FLT_2	0x1022e230
+#define   AN8855_RG_LCPLL_NCPO_VALUE	GENMASK(30, 0)
+#define AN8855_SS_LCPLL_TDC_FLT_5	0x1022e23c
+#define   AN8855_RG_LCPLL_NCPO_CHG	BIT(24)
+#define AN8855_SS_LCPLL_TDC_PCW_1	0x1022e248
+#define  AN8855_RG_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0)
+#define AN8855_INTF_CTRL_8		0x1022e320
+#define AN8855_INTF_CTRL_9		0x1022e324
+#define AN8855_INTF_CTRL_10		0x1022e328
+#define   AN8855_RG_DA_QP_TX_FIR_C2_SEL	BIT(29)
+#define   AN8855_RG_DA_QP_TX_FIR_C2_FORCE GENMASK(28, 24)
+#define   AN8855_RG_DA_QP_TX_FIR_C1_SEL	BIT(21)
+#define   AN8855_RG_DA_QP_TX_FIR_C1_FORCE GENMASK(20, 16)
+#define AN8855_INTF_CTRL_11		0x1022e32c
+#define   AN8855_RG_DA_QP_TX_FIR_C0B_SEL BIT(6)
+#define   AN8855_RG_DA_QP_TX_FIR_C0B_FORCE GENMASK(5, 0)
+#define AN8855_PLL_CTRL_0		0x1022e400
+#define   AN8855_RG_PHYA_AUTO_INIT	BIT(0)
+#define AN8855_PLL_CTRL_2		0x1022e408
+#define   AN8855_RG_DA_QP_PLL_SDM_IFM_INTF BIT(30)
+#define   AN8855_RG_DA_QP_PLL_RICO_SEL_INTF BIT(29)
+#define   AN8855_RG_DA_QP_PLL_POSTDIV_EN_INTF BIT(28)
+#define   AN8855_RG_DA_QP_PLL_PHY_CK_EN_INTF BIT(27)
+#define   AN8855_RG_DA_QP_PLL_PFD_OFFSET_EN_INTRF BIT(26)
+#define   AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF GENMASK(25, 24)
+#define   AN8855_RG_DA_QP_PLL_PCK_SEL_INTF BIT(22)
+#define   AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF GENMASK(21, 20)
+#define   AN8855_RG_DA_QP_PLL_IR_INTF	GENMASK(19, 16)
+#define   AN8855_RG_DA_QP_PLL_ICOIQ_EN_INTF BIT(14)
+#define   AN8855_RG_DA_QP_PLL_FBKSEL_INTF GENMASK(13, 12)
+#define   AN8855_RG_DA_QP_PLL_BR_INTF	GENMASK(10, 8)
+#define   AN8855_RG_DA_QP_PLL_BPD_INTF	GENMASK(7, 6)
+#define   AN8855_RG_DA_QP_PLL_BPA_INTF	GENMASK(4, 2)
+#define   AN8855_RG_DA_QP_PLL_BC_INTF	GENMASK(1, 0)
+#define AN8855_PLL_CTRL_3		0x1022e40c
+#define   AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF GENMASK(31, 16)
+#define   AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF GENMASK(15, 0)
+#define AN8855_PLL_CTRL_4		0x1022e410
+#define   AN8855_RG_DA_QP_PLL_SDM_HREN_INTF GENMASK(4, 3)
+#define   AN8855_RG_DA_QP_PLL_ICOLP_EN_INTF BIT(2)
+#define   AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF GENMASK(1, 0)
+#define AN8855_PLL_CK_CTRL_0		0x1022e414
+#define   AN8855_RG_DA_QP_PLL_TDC_TXCK_SEL_INTF BIT(9)
+#define   AN8855_RG_DA_QP_PLL_SDM_DI_EN_INTF BIT(8)
+#define AN8855_RX_DLY_0			0x1022e614
+#define   AN8855_RG_QP_RX_SAOSC_EN_H_DLY GENMASK(13, 8)
+#define   AN8855_RG_QP_RX_PI_CAL_EN_H_DLY GENMASK(7, 0)
+#define AN8855_RX_CTRL_2		0x1022e630
+#define   AN8855_RG_QP_RX_EQ_EN_H_DLY	GENMASK(28, 16)
+#define AN8855_RX_CTRL_5		0x1022e63c
+#define   AN8855_RG_FREDET_CHK_CYCLE	GENMASK(29, 10)
+#define AN8855_RX_CTRL_6		0x1022e640
+#define   AN8855_RG_FREDET_GOLDEN_CYCLE	GENMASK(19, 0)
+#define AN8855_RX_CTRL_7		0x1022e644
+#define   AN8855_RG_FREDET_TOLERATE_CYCLE GENMASK(19, 0)
+#define AN8855_RX_CTRL_8		0x1022e648
+#define   AN8855_RG_DA_QP_SAOSC_DONE_TIME GENMASK(27, 16)
+#define   AN8855_RG_DA_QP_LEQOS_EN_TIME	GENMASK(14, 0)
+#define AN8855_RX_CTRL_26		0x1022e690
+#define   AN8855_RG_QP_EQ_RETRAIN_ONLY_EN BIT(26)
+#define   AN8855_RG_LINK_NE_EN		BIT(24)
+#define   AN8855_RG_LINK_ERRO_EN	BIT(23)
+#define AN8855_RX_CTRL_42		0x1022e6d0
+#define   AN8855_RG_QP_EQ_EN_DLY	GENMASK(12, 0)
+
+/*	AN8855_QP_ANA_CSR_BASE		0x1022f000 */
+#define AN8855_RG_QP_RX_DAC_EN		0x1022f000
+#define   AN8855_RG_QP_SIGDET_HF	GENMASK(17, 16)
+#define AN8855_RG_QP_RXAFE_RESERVE	0x1022f004
+#define   AN8855_RG_QP_CDR_PD_10B_EN	BIT(11)
+#define AN8855_RG_QP_CDR_LPF_BOT_LIM	0x1022f008
+#define   AN8855_RG_QP_CDR_LPF_KP_GAIN	GENMASK(26, 24)
+#define   AN8855_RG_QP_CDR_LPF_KI_GAIN	GENMASK(22, 20)
+#define AN8855_RG_QP_CDR_LPF_MJV_LIM	0x1022f00c
+#define   AN8855_RG_QP_CDR_LPF_RATIO	GENMASK(5, 4)
+#define AN8855_RG_QP_CDR_LPF_SETVALUE	0x1022f014
+#define   AN8855_RG_QP_CDR_PR_BUF_IN_SR	GENMASK(31, 29)
+#define   AN8855_RG_QP_CDR_PR_BETA_SEL	GENMASK(28, 25)
+#define AN8855_RG_QP_CDR_PR_CKREF_DIV1	0x1022f018
+#define   AN8855_RG_QP_CDR_PR_KBAND_DIV	GENMASK(26, 24)
+#define   AN8855_RG_QP_CDR_PR_DAC_BAND	GENMASK(12, 8)
+#define AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE 0x1022f01c
+#define   AN8855_RG_QP_CDR_PR_XFICK_EN	BIT(30)
+#define   AN8855_RG_QP_CDR_PR_KBAND_PCIE_MODE BIT(6)
+#define   AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK GENMASK(5, 0)
+#define AN8855_RG_QP_CDR_FORCE_IBANDLPF_R_OFF 0x1022f020
+#define   AN8855_RG_QP_CDR_PHYCK_SEL	GENMASK(17, 16)
+#define   AN8855_RG_QP_CDR_PHYCK_RSTB	BIT(13)
+#define   AN8855_RG_QP_CDR_PHYCK_DIV	GENMASK(12, 6)
+#define AN8855_RG_QP_TX_MODE		0x1022f028
+#define   AN8855_RG_QP_TX_RESERVE	GENMASK(31, 16)
+#define   AN8855_RG_QP_TX_MODE_16B_EN	BIT(0)
+#define AN8855_RG_QP_PLL_IPLL_DIG_PWR_SEL 0x1022f03c
+#define AN8855_RG_QP_PLL_SDM_ORD	0x1022f040
+#define   AN8855_RG_QP_PLL_SSC_PHASE_INI BIT(4)
+#define   AN8855_RG_QP_PLL_SSC_TRI_EN	BIT(3)
+
+/*	AN8855_ETHER_SYS_BASE		0x1028c800 */
+#define AN8855_RG_GPHY_AFE_PWD		0x1028c840
+#define AN8855_RG_GPHY_SMI_ADDR		0x1028c848
+
+#define MIB_DESC(_s, _o, _n)	\
+	{			\
+		.size = (_s),	\
+		.offset = (_o),	\
+		.name = (_n),	\
+	}
+
+struct an8855_mib_desc {
+	unsigned int size;
+	unsigned int offset;
+	const char *name;
+};
+
+struct an8855_fdb {
+	u16 vid;
+	u8 port_mask;
+	u16 aging;
+	u8 mac[6];
+	bool noarp;
+	u8 live;
+	u8 type;
+	u8 fid;
+	u8 ivl;
+};
+
+struct an8855_priv {
+	struct dsa_switch *ds;
+	struct regmap *regmap;
+	/* Protect ATU or VLAN table access */
+	struct mutex reg_mutex;
+
+	struct phylink_pcs pcs;
+
+	u8 mirror_rx;
+	u8 mirror_tx;
+	u8 port_isolated_map;
+};
+
+#endif /* __AN8855_H */
-- 
2.48.1



From ansuelsmth at gmail.com  Sun Mar  9 10:26:58 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun,  9 Mar 2025 18:26:58 +0100
Subject: [net-next PATCH v12 13/13] net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY
In-Reply-To: <20250309172717.9067-1-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
Message-ID: <20250309172717.9067-14-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Internal Switch Gigabit PHY.

This is a simple PHY driver to configure and calibrate the PHY for the
AN8855 Switch with the use of NVMEM cells.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                  |   1 +
 drivers/net/phy/Kconfig      |   5 +
 drivers/net/phy/Makefile     |   1 +
 drivers/net/phy/air_an8855.c | 261 +++++++++++++++++++++++++++++++++++
 4 files changed, 268 insertions(+)
 create mode 100644 drivers/net/phy/air_an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bd95c684d480..97acec6fdd4b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -734,6 +734,7 @@ F:	drivers/mfd/airoha-an8855.c
 F:	drivers/net/dsa/an8855.c
 F:	drivers/net/dsa/an8855.h
 F:	drivers/net/mdio/mdio-an8855.c
+F:	drivers/net/phy/air_an8855.c
 F:	drivers/nvmem/an8855-efuse.c
 
 AIROHA ETHERNET DRIVER
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d29f9f7fd2e1..e96f61b8eaba 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -79,6 +79,11 @@ config SFP
 
 comment "MII PHY device drivers"
 
+config AIR_AN8855_PHY
+	tristate "Airoha AN8855 Internal Gigabit PHY"
+	help
+	  Currently supports the internal Airoha AN8855 Switch PHY.
+
 config AIR_EN8811H_PHY
 	tristate "Airoha EN8811H 2.5 Gigabit PHY"
 	help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 8f9ba5e8290d..d4f537ba006c 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -36,6 +36,7 @@ obj-y				+= $(sfp-obj-y) $(sfp-obj-m)
 
 obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
+obj-$(CONFIG_AIR_AN8855_PHY)   += air_an8855.o
 obj-$(CONFIG_AIR_EN8811H_PHY)   += air_en8811h.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_AMCC_QT2025_PHY)	+= qt2025.o
diff --git a/drivers/net/phy/air_an8855.c b/drivers/net/phy/air_an8855.c
new file mode 100644
index 000000000000..9c54c604690f
--- /dev/null
+++ b/drivers/net/phy/air_an8855.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+
+#define AN8855_PHY_SELECT_PAGE			0x1f
+#define   AN8855_PHY_PAGE			GENMASK(2, 0)
+#define   AN8855_PHY_PAGE_STANDARD		FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define   AN8855_PHY_PAGE_EXTENDED_1		FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+
+/* MII Registers Page 1 */
+#define AN8855_PHY_EXT_REG_14			0x14
+#define   AN8855_PHY_EN_DOWN_SHIFT		BIT(4)
+
+/* R50 Calibration regs in MDIO_MMD_VEND1 */
+#define AN8855_PHY_R500HM_RSEL_TX_AB		0x174
+#define AN8855_PHY_R50OHM_RSEL_TX_A_EN		BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_A		GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_B_EN		BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_B		GENMASK(6, 0)
+#define AN8855_PHY_R500HM_RSEL_TX_CD		0x175
+#define AN8855_PHY_R50OHM_RSEL_TX_C_EN		BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_C		GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_D_EN		BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_D		GENMASK(6, 0)
+
+#define AN8855_SWITCH_EFUSE_R50O		GENMASK(30, 24)
+
+/* PHY TX PAIR DELAY SELECT Register */
+#define AN8855_PHY_TX_PAIR_DLY_SEL_GBE		0x013
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE GENMASK(14, 12)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_B_GBE GENMASK(10, 8)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE GENMASK(6, 4)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_D_GBE GENMASK(2, 0)
+/* PHY ADC Register */
+#define AN8855_PHY_RXADC_CTRL			0x0d8
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A	BIT(12)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_B	BIT(8)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C	BIT(4)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_D	BIT(0)
+#define AN8855_PHY_RXADC_REV_0			0x0d9
+#define   AN8855_PHY_RG_AD_RESERVE0_A		GENMASK(15, 8)
+#define   AN8855_PHY_RG_AD_RESERVE0_B		GENMASK(7, 0)
+#define AN8855_PHY_RXADC_REV_1			0x0da
+#define   AN8855_PHY_RG_AD_RESERVE0_C		GENMASK(15, 8)
+#define   AN8855_PHY_RG_AD_RESERVE0_D		GENMASK(7, 0)
+
+#define AN8855_PHY_ID				0xc0ff0410
+
+struct air_an8855_priv {
+	bool needs_calibration;
+};
+
+static const u8 dsa_r50ohm_table[] = {
+	127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+	127, 127, 127, 127, 127, 127, 127, 126, 122, 117,
+	112, 109, 104, 101,  97,  94,  90,  88,  84,  80,
+	78,  74,  72,  68,  66,  64,  61,  58,  56,  53,
+	51,  48,  47,  44,  42,  40,  38,  36,  34,  32,
+	31,  28,  27,  24,  24,  22,  20,  18,  16,  16,
+	14,  12,  11,   9
+};
+
+static int en8855_get_r50ohm_val(struct device *dev, const char *calib_name,
+				 u8 *dest)
+{
+	u32 shift_sel, val;
+	int ret;
+	int i;
+
+	ret = nvmem_cell_read_u32(dev, calib_name, &val);
+	if (ret)
+		return ret;
+
+	shift_sel = FIELD_GET(AN8855_SWITCH_EFUSE_R50O, val);
+	for (i = 0; i < ARRAY_SIZE(dsa_r50ohm_table); i++)
+		if (dsa_r50ohm_table[i] == shift_sel)
+			break;
+
+	if (i < 8 || i >= ARRAY_SIZE(dsa_r50ohm_table))
+		*dest = dsa_r50ohm_table[25];
+	else
+		*dest = dsa_r50ohm_table[i - 8];
+
+	return 0;
+}
+
+static int an8855_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct air_an8855_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->needs_calibration = of_property_read_bool(dev->of_node,
+							"airoha,ext-surge");
+
+	phydev->priv = priv;
+
+	return 0;
+}
+
+static int an8855_get_downshift(struct phy_device *phydev, u8 *data)
+{
+	int val;
+
+	val = phy_read_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, AN8855_PHY_EXT_REG_14);
+	if (val < 0)
+		return val;
+
+	*data = val & AN8855_PHY_EN_DOWN_SHIFT ? DOWNSHIFT_DEV_DEFAULT_COUNT :
+						 DOWNSHIFT_DEV_DISABLE;
+
+	return 0;
+}
+
+static int an8855_set_downshift(struct phy_device *phydev, u8 cnt)
+{
+	u16 ds = cnt != DOWNSHIFT_DEV_DISABLE ? AN8855_PHY_EN_DOWN_SHIFT : 0;
+
+	return phy_modify_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1,
+				AN8855_PHY_EXT_REG_14, AN8855_PHY_EN_DOWN_SHIFT,
+				ds);
+}
+
+static int an8855_config_init(struct phy_device *phydev)
+{
+	struct air_an8855_priv *priv = phydev->priv;
+	struct device *dev = &phydev->mdio.dev;
+	int ret;
+
+	/* Enable HW auto downshift */
+	ret = an8855_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);
+	if (ret)
+		return ret;
+
+	if (priv->needs_calibration) {
+		u8 calibration_data[4];
+
+		ret = en8855_get_r50ohm_val(dev, "tx_a", &calibration_data[0]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_b", &calibration_data[1]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_c", &calibration_data[2]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_d", &calibration_data[3]);
+		if (ret)
+			return ret;
+
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_AB,
+				     AN8855_PHY_R50OHM_RSEL_TX_A | AN8855_PHY_R50OHM_RSEL_TX_B,
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_A, calibration_data[0]) |
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_B, calibration_data[1]));
+		if (ret)
+			return ret;
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_CD,
+				     AN8855_PHY_R50OHM_RSEL_TX_C | AN8855_PHY_R50OHM_RSEL_TX_D,
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_C, calibration_data[2]) |
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_D, calibration_data[3]));
+		if (ret)
+			return ret;
+	}
+
+	/* Apply values to reduce signal noise */
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_TX_PAIR_DLY_SEL_GBE,
+			    FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE, 0x4) |
+			    FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE, 0x4));
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_CTRL,
+			    AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A |
+			    AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C);
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_0,
+			    FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_A, 0x1));
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_1,
+			    FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_C, 0x1));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int an8855_get_tunable(struct phy_device *phydev,
+			      struct ethtool_tunable *tuna, void *data)
+{
+	switch (tuna->id) {
+	case ETHTOOL_PHY_DOWNSHIFT:
+		return an8855_get_downshift(phydev, data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int an8855_set_tunable(struct phy_device *phydev,
+			      struct ethtool_tunable *tuna, const void *data)
+{
+	switch (tuna->id) {
+	case ETHTOOL_PHY_DOWNSHIFT:
+		return an8855_set_downshift(phydev, *(const u8 *)data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int an8855_read_page(struct phy_device *phydev)
+{
+	return __phy_read(phydev, AN8855_PHY_SELECT_PAGE);
+}
+
+static int an8855_write_page(struct phy_device *phydev, int page)
+{
+	return __phy_write(phydev, AN8855_PHY_SELECT_PAGE, page);
+}
+
+static struct phy_driver an8855_driver[] = {
+{
+	PHY_ID_MATCH_EXACT(AN8855_PHY_ID),
+	.name			= "Airoha AN8855 internal PHY",
+	/* PHY_GBIT_FEATURES */
+	.flags			= PHY_IS_INTERNAL,
+	.probe			= an8855_probe,
+	.config_init		= an8855_config_init,
+	.soft_reset		= genphy_soft_reset,
+	.get_tunable		= an8855_get_tunable,
+	.set_tunable		= an8855_set_tunable,
+	.suspend		= genphy_suspend,
+	.resume			= genphy_resume,
+	.read_page		= an8855_read_page,
+	.write_page		= an8855_write_page,
+}, };
+
+module_phy_driver(an8855_driver);
+
+static struct mdio_device_id __maybe_unused an8855_tbl[] = {
+	{ PHY_ID_MATCH_EXACT(AN8855_PHY_ID) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(mdio, an8855_tbl);
+
+MODULE_DESCRIPTION("Airoha AN8855 PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From linux at armlinux.org.uk  Sun Mar  9 10:36:49 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 9 Mar 2025 17:36:49 +0000
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <20250309172717.9067-8-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
Message-ID: <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>

On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> +/* If a non empty valid_addr_mask is passed, PHY address and
> + * read/write register are encoded in the regmap register
> + * by placing the register in the first 16 bits and the PHY address
> + * right after.
> + */
> +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)

Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
and then 16 bits of register address - significant in that order. Can
we adjust the mask for the PHY address later to add the MMD between
the PHY address and register number?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From linux at armlinux.org.uk  Sun Mar  9 10:37:58 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Sun, 9 Mar 2025 17:37:58 +0000
Subject: [net-next PATCH v12 08/13] net: mdio: regmap: add OF support
In-Reply-To: <20250309172717.9067-9-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-9-ansuelsmth@gmail.com>
Message-ID: <Z83R9qVfGbSc8bJs@shell.armlinux.org.uk>

On Sun, Mar 09, 2025 at 06:26:53PM +0100, Christian Marangi wrote:
> Permit to pass the device node pointer to mdio regmap config and permit
> mdio registration with an OF node to support DT PHY probe.
> 
> With the device node pointer NULL, the normal mdio registration is used.

Should this be using a device node, or a fwnode?

It depends _why_ you're adding this, and you omit to state that in the
commit description (hint - it should say why!)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From jan.dakinevich at salutedevices.com  Sun Mar  9 10:43:18 2025
From: jan.dakinevich at salutedevices.com (Jan Dakinevich)
Date: Sun, 9 Mar 2025 20:43:18 +0300
Subject: [PATCH v6 0/4] Add A1 Soc audio clock controller driver
Message-ID: <20250309174322.1321201-1-jan.dakinevich@salutedevices.com>

This series adds support for audio clock and reset controllers on A1 SoC family.

Depends on [7]

Changes v5 [5] -> v6
 - use __devm_auxiliary_device_create() helper that is being introduced in [7]

Changes v4 [4] -> v5
 - moved changes of aux reset driver to series [6]
 - added reset controller on top of audio-vad
 - merged into single file
 - reworked variables/defines naming
 - added clk81 clock hierarchy
 - added TDMIN_VAD-related clocks
 - excluded DT patch (it will submitted separately)

Changes v3 [3] -> v4
 - Use auxiliary reset device implemented in [4]
 - Split the driver into files
 - Use common with axg-audio yaml schema
 - Unify clock-names with axg-audio

Changes v2 [2] -> v3
 - reset:
   * added auxiliary device
 - yaml:
   * added declaration of optional clocks
   * fixed names in example and another cosmetics
 - clocks:
   * reworked naming
   * stop using of "core" clock name
   * fixed wrong parenting

Changes v1 [1] -> v2:
 - Detached from v1's series (patch 2, 3, 4, 25)
 - Reuse some of defines from axg-audio
 - Split the controller into two memory regions

Links:
 [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich at salutedevices.com/
 [2] https://lore.kernel.org/lkml/20240328010831.884487-1-jan.dakinevich at salutedevices.com/
 [3] https://lore.kernel.org/lkml/20240419125812.983409-1-jan.dakinevich at salutedevices.com/
 [4] https://lore.kernel.org/all/20240913121152.817575-1-jan.dakinevich at salutedevices.com/
 [5] https://lore.kernel.org/all/20241112230443.1406460-1-jan.dakinevich at salutedevices.com/
 [6] https://lore.kernel.org/all/20241112230056.1406222-1-jan.dakinevich at salutedevices.com/
 [7] https://lore.kernel.org/all/20250218-aux-device-create-helper-v4-0-c3d7dfdea2e6 at baylibre.com/

Jan Dakinevich (4):
  clk: meson: axg: share the set of audio helper macros
  dt-bindings: clock: axg-audio: document A1 SoC audio clock controller
    driver
  clk: meson: a1: add the audio clock controller driver
  arm64: dts: meson: a1: add the audio clock controller

 .../clock/amlogic,axg-audio-clkc.yaml         |   4 +
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi     |  49 +
 drivers/clk/meson/Kconfig                     |  14 +
 drivers/clk/meson/Makefile                    |   1 +
 drivers/clk/meson/a1-audio.c                  | 856 ++++++++++++++++++
 drivers/clk/meson/axg-audio.c                 | 215 +----
 drivers/clk/meson/meson-audio.h               | 156 ++++
 .../dt-bindings/clock/amlogic,a1-audio-clkc.h | 139 +++
 8 files changed, 1254 insertions(+), 180 deletions(-)
 create mode 100644 drivers/clk/meson/a1-audio.c
 create mode 100644 drivers/clk/meson/meson-audio.h
 create mode 100644 include/dt-bindings/clock/amlogic,a1-audio-clkc.h

-- 
2.34.1



From krzysztof.kozlowski at linaro.org  Sun Mar  9 10:51:47 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 18:51:47 +0100
Subject: [GIT PULL] clk: samsung: drivers for v6.15
Message-ID: <20250309175147.6672-1-krzysztof.kozlowski@linaro.org>

Hi,

New clk drivers for Samsung SoC.  This pull includes drivers which you
commented later and pointed out few issues.  Pointed issues are in all Samsung
clk drivers and the ones here just copy existing patterns:

1. Headers: I fixed it for new and existing drivers and this pull request
includes the fixes.
2. device_get_match_data(): I still wait for contributors response. If they do
not respond, I will fix it for next cycle.
3. refdata and platform_driver_probe: I tried fixing it, but incomplete and
need to investigate more.

Best regards,
Krzysztof


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-clk-6.15

for you to fetch changes up to 017bbc922a09630579ff7b5b314fb186b8c0efcf:

  clk: samsung: Drop unused clk.h and of.h headers (2025-03-07 16:01:22 +0100)

----------------------------------------------------------------
Samsung SoC clock drivers changes for 6.15

1. Exynos990: Add support for the PERIS clock controller in existing
   driver.
2. Exynos2200: Add new driver for several clock controllers (Alive,
   CMGP, HSI, PERIC/PERIS, TOP, UFS and VFS).
3. Exynos7870: Add new driver for several clock controllers (Alive,
   MIF, DISP AUD, FSYS, G3D, ISP, MFC and PERI).
4. Correct undefined behavior / runtime array bounds check of flexible
   array member (last 'hws' element in 'struct clk_hw_onecell_data').
   The code was logically correct for normal case, but not for the
   clang/GCC runtime bounds checking of flexible array member.
5. Few cleanups: spelling, header inclusions.

----------------------------------------------------------------
Colin Ian King (1):
      clk: samsung: Fix spelling mistake "stablization" -> "stabilization"

Igor Belwon (2):
      dt-bindings: clock: exynos990: Add CMU_PERIS block
      clk: samsung: exynos990: Add CMU_PERIS block

Ivaylo Ivanov (3):
      dt-bindings: clock: add Exynos2200 SoC
      clk: samsung: clk-pll: add support for pll_4311
      clk: samsung: introduce Exynos2200 clock driver

Kaustabh Chakraborty (2):
      dt-bindings: clock: add clock definitions and documentation for exynos7870 CMU
      clk: samsung: add initial exynos7870 clock driver

Krzysztof Kozlowski (3):
      Merge branch 'for-v6.15/samsung-clk-dt-bindings' into next/clk
      clk: samsung: Add missing mod_devicetable.h header
      clk: samsung: Drop unused clk.h and of.h headers

Will McVicker (1):
      clk: samsung: Fix UBSAN panic in samsung_clk_init()

 .../bindings/clock/samsung,exynos2200-cmu.yaml     |  247 ++
 .../bindings/clock/samsung,exynos7870-cmu.yaml     |  227 ++
 .../bindings/clock/samsung,exynos990-clock.yaml    |   19 +
 drivers/clk/samsung/Makefile                       |    2 +
 drivers/clk/samsung/clk-cpu.c                      |    2 +-
 drivers/clk/samsung/clk-exynos-audss.c             |    1 +
 drivers/clk/samsung/clk-exynos-clkout.c            |    1 +
 drivers/clk/samsung/clk-exynos2200.c               | 3928 ++++++++++++++++++++
 drivers/clk/samsung/clk-exynos3250.c               |    4 +-
 drivers/clk/samsung/clk-exynos4.c                  |    2 +-
 drivers/clk/samsung/clk-exynos4412-isp.c           |    2 +-
 drivers/clk/samsung/clk-exynos5-subcmu.c           |    1 +
 drivers/clk/samsung/clk-exynos5250.c               |    1 +
 drivers/clk/samsung/clk-exynos5260.c               |    3 -
 drivers/clk/samsung/clk-exynos5410.c               |    2 -
 drivers/clk/samsung/clk-exynos5420.c               |    1 +
 drivers/clk/samsung/clk-exynos5433.c               |    4 +-
 drivers/clk/samsung/clk-exynos7.c                  |    1 -
 drivers/clk/samsung/clk-exynos7870.c               | 1829 +++++++++
 drivers/clk/samsung/clk-exynos7885.c               |    2 +-
 drivers/clk/samsung/clk-exynos850.c                |    2 +-
 drivers/clk/samsung/clk-exynos8895.c               |    2 +-
 drivers/clk/samsung/clk-exynos990.c                |  182 +-
 drivers/clk/samsung/clk-exynosautov9.c             |    2 +-
 drivers/clk/samsung/clk-exynosautov920.c           |    2 +-
 drivers/clk/samsung/clk-fsd.c                      |    2 +-
 drivers/clk/samsung/clk-gs101.c                    |    2 +-
 drivers/clk/samsung/clk-pll.c                      |    1 +
 drivers/clk/samsung/clk-pll.h                      |    1 +
 drivers/clk/samsung/clk-s3c64xx.c                  |    1 -
 drivers/clk/samsung/clk-s5pv210-audss.c            |    1 +
 drivers/clk/samsung/clk-s5pv210.c                  |    1 -
 drivers/clk/samsung/clk.c                          |    4 +-
 drivers/clk/samsung/clk.h                          |    1 +
 include/dt-bindings/clock/samsung,exynos2200-cmu.h |  431 +++
 include/dt-bindings/clock/samsung,exynos7870-cmu.h |  324 ++
 include/dt-bindings/clock/samsung,exynos990.h      |   21 +
 37 files changed, 7231 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/samsung,exynos2200-cmu.yaml
 create mode 100644 Documentation/devicetree/bindings/clock/samsung,exynos7870-cmu.yaml
 create mode 100644 drivers/clk/samsung/clk-exynos2200.c
 create mode 100644 drivers/clk/samsung/clk-exynos7870.c
 create mode 100644 include/dt-bindings/clock/samsung,exynos2200-cmu.h
 create mode 100644 include/dt-bindings/clock/samsung,exynos7870-cmu.h


From krzysztof.kozlowski at linaro.org  Sun Mar  9 10:51:53 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 18:51:53 +0100
Subject: [GIT PULL] clk: samsung: Fixes for v6.14
Message-ID: <20250309175154.6701-1-krzysztof.kozlowski@linaro.org>

Hi,

Fixes for current RC.

Best regards,
Krzysztof


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-clk-fixes-6.14

for you to fetch changes up to 53517a70873c7a91675f7244768aad5006cc45de:

  clk: samsung: update PLL locktime for PLL142XX used on FSD platform (2025-03-05 20:13:25 +0100)

----------------------------------------------------------------
Samsung clock controller fixes for v6.14

1. Google GS101: Fix synchronous external abort during system suspend.
   The driver access registers not available for OS, although issue
   would not be visible in earlier kernels due to missing suspend
   support.

2. Tesla FSD: Correct PLL142XX lock time.

----------------------------------------------------------------
Peter Griffin (1):
      clk: samsung: gs101: fix synchronous external abort in samsung_clk_save()

Varada Pavani (1):
      clk: samsung: update PLL locktime for PLL142XX used on FSD platform

 drivers/clk/samsung/clk-gs101.c | 8 --------
 drivers/clk/samsung/clk-pll.c   | 7 ++++++-
 2 files changed, 6 insertions(+), 9 deletions(-)


From krzysztof.kozlowski at linaro.org  Sun Mar  9 11:55:57 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 19:55:57 +0100
Subject: [GIT PULL 3/4] ARM: samsung: soc/drivers for v6.15
In-Reply-To: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
References: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250309185601.10616-3-krzysztof.kozlowski@linaro.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-soc-6.15

for you to fetch changes up to c8222ef6cf29dd7cad21643228f96535cc02b327:

  soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe() (2025-02-15 14:37:19 +0100)

----------------------------------------------------------------
Samsung mach/soc changes for v6.15

1. S3C: Drop linux/fb.h header.
2. Exynos ChipID: Check if memory allocation succeeded.

----------------------------------------------------------------
Chenyuan Yang (1):
      soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe()

Thomas Zimmermann (1):
      ARM: s3c: Do not include <linux/fb.h>

 arch/arm/mach-s3c/devs.c                   | 1 -
 arch/arm/mach-s3c/setup-fb-24bpp-s3c64xx.c | 1 -
 drivers/soc/samsung/exynos-chipid.c        | 2 ++
 3 files changed, 2 insertions(+), 2 deletions(-)


From krzysztof.kozlowski at linaro.org  Sun Mar  9 11:55:58 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun,  9 Mar 2025 19:55:58 +0100
Subject: [GIT PULL 4/4 PATCH] arm64: defconfig: enable ACPM protocol and Exynos mailbox
In-Reply-To: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
References: <20250309185601.10616-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250309185601.10616-4-krzysztof.kozlowski@linaro.org>

From: Tudor Ambarus <tudor.ambarus at linaro.org>

Enable the Samsung Exynos ACPM protocol and its transport layer, the
Exynos mailbox driver. Samsung Exynos platforms implement ACPM to
provide support for PMIC, clock frequency scaling, clock configuration
and temperature sensors.

Signed-off-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Link: https://lore.kernel.org/r/20250207-gs101-acpm-dt-v4-4-230ba8663a2d at linaro.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..18f96796298c 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -264,6 +264,7 @@ CONFIG_IMX_SCU=y
 CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y
 CONFIG_QCOM_QSEECOM=y
 CONFIG_QCOM_QSEECOM_UEFISECAPP=y
+CONFIG_EXYNOS_ACPM_PROTOCOL=m
 CONFIG_GNSS=m
 CONFIG_GNSS_MTK_SERIAL=m
 CONFIG_MTD=y
@@ -1403,6 +1404,7 @@ CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_TEGRA186_TIMER=y
 CONFIG_RENESAS_OSTM=y
 CONFIG_ARM_MHU=y
+CONFIG_EXYNOS_MBOX=m
 CONFIG_IMX_MBOX=y
 CONFIG_OMAP2PLUS_MBOX=m
 CONFIG_PLATFORM_MHU=y
-- 
2.43.0



From maz at kernel.org  Sun Mar  9 12:01:05 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 09 Mar 2025 19:01:05 +0000
Subject: [PATCH v2 3/3] KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
In-Reply-To: <20250307-pmc-v2-3-6c3375a5f1e4@daynix.com>
References: <20250307-pmc-v2-0-6c3375a5f1e4@daynix.com>
	<20250307-pmc-v2-3-6c3375a5f1e4@daynix.com>
Message-ID: <864j02owpa.wl-maz@kernel.org>

On Fri, 07 Mar 2025 10:55:30 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> Commit a45f41d754e0 ("KVM: arm64: Add {get,set}_user for
> PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}") changed KVM_SET_ONE_REG to update
> the mentioned registers in a way matching with the behavior of guest
> register writes. This is a breaking change of a UAPI though the new
> semantics looks cleaner and VMMs are not prepared for this.
> 
> Firecracker, QEMU, and crosvm perform migration by listing registers
> with KVM_GET_REG_LIST, getting their values with KVM_GET_ONE_REG and
> setting them with KVM_SET_ONE_REG. This algorithm assumes
> KVM_SET_ONE_REG restores the values retrieved with KVM_GET_ONE_REG
> without any alteration. However, bit operations added by the earlier
> commit do not preserve the values retried with KVM_GET_ONE_REG and
> potentially break migration.
> 
> Remove the bit operations that alter the values retrieved with
> KVM_GET_ONE_REG.
> 
> Fixes: a45f41d754e0 ("KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}")
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
>  arch/arm64/kvm/sys_regs.c | 21 +--------------------
>  1 file changed, 1 insertion(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 51054b7befc0b4bd822cecf717ee4a4740c4a685..2f44d4d4f54112787683dd75ea93fd60e92dd31f 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1142,26 +1142,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>  
>  static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
>  {
> -	bool set;
> -
> -	val &= kvm_pmu_valid_counter_mask(vcpu);
> -
> -	switch (r->reg) {
> -	case PMOVSSET_EL0:
> -		/* CRm[1] being set indicates a SET register, and CLR otherwise */
> -		set = r->CRm & 2;
> -		break;
> -	default:
> -		/* Op2[0] being set indicates a SET register, and CLR otherwise */
> -		set = r->Op2 & 1;
> -		break;
> -	}
> -
> -	if (set)
> -		__vcpu_sys_reg(vcpu, r->reg) |= val;
> -	else
> -		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
> -
> +	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
>  	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
>  
>  	return 0;
> 

Yup, this code was definitely a brain fart. Thanks for spotting it.
One of the big mistake was to expose both CLR and SET registers to
userspace (one of the two should have been hidden).

This requires a Cc to stable at vger.kernel.org so that this can be
backported to anything from 6.12. It would also help if you put this
patch at the head of the series, before adding the PMU request (it is
then likely to be very easy to backport).

With that,

Acked-by: Marc Zyngier <maz at kernel.org>

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From ansuelsmth at gmail.com  Sun Mar  9 10:45:43 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun, 9 Mar 2025 18:45:43 +0100
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
 <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
Message-ID: <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>

On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > +/* If a non empty valid_addr_mask is passed, PHY address and
> > + * read/write register are encoded in the regmap register
> > + * by placing the register in the first 16 bits and the PHY address
> > + * right after.
> > + */
> > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> 
> Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> and then 16 bits of register address - significant in that order. Can
> we adjust the mask for the PHY address later to add the MMD between
> the PHY address and register number?
>

Honestly to future proof this, I think a good idea might be to add
helper to encode these info and use Clause 45 format even for C22.
Maybe we can use an extra bit to signal if the format is C22 or C45.

BIT(26) 0: C22 1:C45
GENMASK(25, 21) PHY ADDR
GENMASK(20, 16) MMD ADDR
GENMASK(15, 0) REG

What do you think?

-- 
	Ansuel


From ansuelsmth at gmail.com  Sun Mar  9 10:48:33 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sun, 9 Mar 2025 18:48:33 +0100
Subject: [net-next PATCH v12 08/13] net: mdio: regmap: add OF support
In-Reply-To: <Z83R9qVfGbSc8bJs@shell.armlinux.org.uk>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-9-ansuelsmth@gmail.com>
 <Z83R9qVfGbSc8bJs@shell.armlinux.org.uk>
Message-ID: <67cdd473.7b0a0220.170541.e2af@mx.google.com>

On Sun, Mar 09, 2025 at 05:37:58PM +0000, Russell King (Oracle) wrote:
> On Sun, Mar 09, 2025 at 06:26:53PM +0100, Christian Marangi wrote:
> > Permit to pass the device node pointer to mdio regmap config and permit
> > mdio registration with an OF node to support DT PHY probe.
> > 
> > With the device node pointer NULL, the normal mdio registration is used.
> 
> Should this be using a device node, or a fwnode?
> 
> It depends _why_ you're adding this, and you omit to state that in the
> commit description (hint - it should say why!)
>

Ugh totally forgot... It should be a device node. The use of the of_
variant of mdiobus register permits to autoprobe PHY defined in device
tree.

The current regmap driver only permit manual probe using the mask value
so it's problematic for MFD usage with an abstract regmap and PHY
autoprobe.

Will add additional info in the commit.

-- 
	Ansuel


From robh at kernel.org  Sun Mar  9 12:20:18 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sun, 09 Mar 2025 14:20:18 -0500
Subject: [PATCH v2 2/3] ASoC: dt-bindings: meson: t9015: add support
 for A1 SoC family
In-Reply-To: <20250309181630.1322745-3-jan.dakinevich@salutedevices.com>
References: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
 <20250309181630.1322745-3-jan.dakinevich@salutedevices.com>
Message-ID: <174154801891.2046627.7087067779247838486.robh@kernel.org>


On Sun, 09 Mar 2025 21:16:29 +0300, Jan Dakinevich wrote:
> Add support for internal audio codec found A1 SoC family. On this SoC
> the component supports capturing from ADC and has specific configuration
> of input/output lines.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../bindings/sound/amlogic,t9015.yaml         | 69 +++++++++++++++++--
>  1 file changed, 65 insertions(+), 4 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml: allOf:1:else: 'anyOf' conditional failed, one must be fixed:
	'lineout-left' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml: allOf:1:else: 'anyOf' conditional failed, one must be fixed:
	'lineout-right' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml: allOf:1:else: 'anyOf' conditional failed, one must be fixed:
	'linein-left' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml: allOf:1:else: 'anyOf' conditional failed, one must be fixed:
	'linein-right' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml: allOf:1:else: 'anyOf' conditional failed, one must be fixed:
	'micbias' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
	'type' was expected
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250309181630.1322745-3-jan.dakinevich at salutedevices.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From lkp at intel.com  Sun Mar  9 12:26:18 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 10 Mar 2025 03:26:18 +0800
Subject: [net-next PATCH v12 05/13] dt-bindings: mfd: Document support
 for Airoha AN8855 Switch SoC
In-Reply-To: <20250309172717.9067-6-ansuelsmth@gmail.com>
References: <20250309172717.9067-6-ansuelsmth@gmail.com>
Message-ID: <202503100331.nksmBPCd-lkp@intel.com>

Hi Christian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Marangi/dt-bindings-nvmem-Document-support-for-Airoha-AN8855-Switch-EFUSE/20250310-013306
base:   net-next/main
patch link:    https://lore.kernel.org/r/20250309172717.9067-6-ansuelsmth%40gmail.com
patch subject: [net-next PATCH v12 05/13] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
reproduce: (https://download.01.org/0day-ci/archive/20250310/202503100331.nksmBPCd-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503100331.nksmBPCd-lkp at intel.com/

All warnings (new ones prefixed by >>):

   Warning: Documentation/translations/ja_JP/SubmittingPatches references a file that doesn't exist: linux-2.6.12-vanilla/Documentation/dontdiff
   Warning: Documentation/translations/zh_CN/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
   Warning: Documentation/translations/zh_TW/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/mfd/airoha,an8855-mfd.yaml
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/leds/backlight/ti,lp8864.yaml
   Warning: lib/Kconfig.debug references a file that doesn't exist: Documentation/dev-tools/fault-injection/fault-injection.rst
   Using alabaster theme

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From sven at svenpeter.dev  Sun Mar  9 12:45:47 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sun,  9 Mar 2025 20:45:47 +0100
Subject: [PATCH] MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support
In-Reply-To: <20250303154012.1417088-1-neal@gompa.dev>
References: <20250303154012.1417088-1-neal@gompa.dev>
Message-ID: <174154951957.51578.1010090388720574063.b4-ty@svenpeter.dev>

On Mon, 03 Mar 2025 10:40:10 -0500, Neal Gompa wrote:
> As a member of the Asahi Linux project, I (Neal) have been involved in
> reviewing the patches downstream as part of enabling the Fedora Asahi Remix
> distribution for years and have recently been reviewing patches for upstream
> submission as well.
> 
> This formalizes my role as a reviewer for ARM Apple system support patches.
> 
> [...]

Applied to git at github.com:AsahiLinux/linux.git (asahi-soc/maintainers), thanks!

[1/1] MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support
      https://github.com/AsahiLinux/linux/commit/3a0d2facfa64

Best regards,
-- 
Sven Peter <sven at svenpeter.dev>



From heiko at sntech.de  Sun Mar  9 12:47:24 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Sun, 09 Mar 2025 20:47:24 +0100
Subject: [PATCH 1/3] dt-bindings: i2c: i2c-rk3x: Add compatible string for RK3528
In-Reply-To: <20250309070603.35254-2-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
 <20250309070603.35254-2-ziyao@disroot.org>
Message-ID: <1914308.tdWV9SEqCh@diego>

Am Sonntag, 9. M?rz 2025, 08:06:01 MEZ schrieb Yao Zi:
> Document I2C controllers integrated in RK3528, which are compatible with
> the RK3399 variant.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>




From sven at svenpeter.dev  Sun Mar  9 12:49:26 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sun,  9 Mar 2025 20:49:26 +0100
Subject: [GIT PULL] Apple SoC MAINTAINERS updates for v6.14 / arm/fixes
Message-ID: <20250309194926.51824-1-sven@svenpeter.dev>

Hi Arnd,

As briefly mentioned on IRC we also have updates for our section in the
MAINTAINERS file. We're adding Neal Gompa as a reviewer and I also picked
up a patch from November last year that got lost (ouch) which adds the files
for our SPI controller to make sure we're CC'ed for any patches.

Please note that this is based on 6.14-rc5 like your arm/fixes branch
since we would otherwise get a conflict with previous updates to MAINTAINERS.
Hope that works!


Best,

Sven


The following changes since commit 7eb172143d5508b4da468ed59ee857c6e5e01da6:

  Linux 6.14-rc5 (2025-03-02 11:48:20 -0800)

are available in the Git repository at:

  https://github.com/AsahiLinux/linux.git tags/asahi-soc-maintainers-6.14-fixes

for you to fetch changes up to 3a0d2facfa645ce2fca794a1105d0634ab722008:

  MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support (2025-03-09 20:34:36 +0100)

----------------------------------------------------------------
Two updates to our ARM/APPLE MACHINE SUPPORT section in MAINTAINERS:

- Added Neal Gompa as reviewer
- Added the files for our SPI controller driver

----------------------------------------------------------------
Hector Martin (1):
      MAINTAINERS: Add apple-spi driver & binding files

Neal Gompa (1):
      MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support

 MAINTAINERS | 3 +++
 1 file changed, 3 insertions(+)


From krzk at kernel.org  Sun Mar  9 12:50:39 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 9 Mar 2025 20:50:39 +0100
Subject: [PATCH v4 01/19] dt-bindings: mfd: mediatek: mt6397: Add accdet
 subnode
In-Reply-To: <cb2820d8-84e8-49ca-b497-1ea815679a3d@notapiano>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-1-e5ffa5ee9991@collabora.com>
 <20250306-certain-jasmine-mastiff-fd67ba@krzk-bin>
 <2fa6037d-b5e9-45b2-a5d5-dbc92fb3434b@notapiano>
 <0663e03e-e331-4a06-be95-ce8d9059ed6b@kernel.org>
 <cb2820d8-84e8-49ca-b497-1ea815679a3d@notapiano>
Message-ID: <668ada6a-3e53-474d-be81-d69d75277c26@kernel.org>

On 07/03/2025 14:22, N?colas F. R. A. Prado wrote:
> On Fri, Mar 07, 2025 at 08:11:26AM +0100, Krzysztof Kozlowski wrote:
>> On 06/03/2025 13:19, N?colas F. R. A. Prado wrote:
>>>>>    It is interfaced to host controller using SPI interface by a proprietary hardware
>>>>>    called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
>>>>> @@ -224,6 +225,30 @@ properties:
>>>>>      description:
>>>>>        Pin controller
>>>>>  
>>>>> +  accdet:
>>>>> +    type: object
>>>>> +    additionalProperties: false
>>>>> +    description:
>>>>> +      The Accessory Detection module found on the PMIC allows detecting audio
>>>>> +      jack insertion and removal, as well as identifying the type of events
>>>>> +      connected to the jack.
>>>>> +
>>>>> +    properties:
>>>>> +      compatible:
>>>>> +        const: mediatek,mt6359-accdet
>>>>
>>>> You just removed the other file, no folding happened here. Drop the
>>>> accdet node and fold this into parent.
>>>
>>> Sorry, I'm still not sure what you mean by folding here then. Right now the
>>> accdet is a subnode of the PMIC. If you want me to remove the accdet node, where
>>
>> Yes
>>
>>> would its compatible and property go?
>>
>> compatible: nowhere, because it is close to redundancy.
>>
>> property: to the parent pmic node.
>>
>>     pmic {
>>         compatible = "mediatek,mt6359";
>>         interrupt-controller;
>>         #interrupt-cells = <2>;
>>
>>         mediatek,hp-eint-high;
>>     };
> 
> I'm not sure that's right. The ACCDET submodule does have some resources, IRQs,
> that it registers in its mfd cell, see patch 2 of this series [1]. It also has

Binding is supposed to be complete, so why suddenly we have here some
resources which you did not add?

Post complete binding, so you will get proper review.

> its own driver (sound/soc/codecs/mt6359-accdet.c) that probes based on this

Drivers do not define bindings.

> compatible and handles those interrupts. Why would it not get its own node like

Sorry, cannot go. You cannot document binding post factum and claim "I
have a driver which uses that compatible".

This would be a nice way to bypass review.

> the other MFD cells?

I explained why. I gave you the exact reason.

Best regards,
Krzysztof


From krzk at kernel.org  Sun Mar  9 13:24:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 9 Mar 2025 21:24:48 +0100
Subject: [PATCH 1/2] dt-bindings: arm: amlogic: Add Ogoos AM3
In-Reply-To: <20250309-ugoos-am3-v1-1-38cab5a4725b@posteo.net>
References: <20250309-ugoos-am3-v1-0-38cab5a4725b@posteo.net>
 <20250309-ugoos-am3-v1-1-38cab5a4725b@posteo.net>
Message-ID: <4d67f643-a8b1-41ff-b3e6-2833c5cfe524@kernel.org>

On 09/03/2025 14:16, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC.
> 
>   https://ugoos.com/ugoos-am3-16g

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From kw at linux.com  Sun Mar  9 13:36:24 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Mon, 10 Mar 2025 05:36:24 +0900
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250226024256.1678103-3-hongxing.zhu@nxp.com>
References: <20250226024256.1678103-1-hongxing.zhu@nxp.com>
 <20250226024256.1678103-3-hongxing.zhu@nxp.com>
Message-ID: <20250309203624.GB3679091@rocinante>

Hello,

> Use the domain number replace the hardcodes to uniquely identify
> different controller on i.MX8MQ platforms. No function changes.

Applied to controller/imx6, thank you!

	Krzysztof


From piotr.oniszczuk at gmail.com  Sun Mar  9 13:53:50 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Sun, 9 Mar 2025 21:53:50 +0100
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <545cc438.7e3.1956e13a3e2.Coremail.andyshrk@163.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
 <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>
 <326B91E9-FB91-43C3-B98B-3EF079F313C6@gmail.com>
 <545cc438.7e3.1956e13a3e2.Coremail.andyshrk@163.com>
Message-ID: <AD2A56F9-B4FB-406B-BE7C-49BB5DFD3BAD@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 7 mar 2025, o godz. 01:48:
> 
> 
> Hi Piotr,
> ? 2025-03-06 22:28:08?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>> 
>> 
> 
> All dump information currently appears to be correct, so I'm temporarily unsure why
> there is no display on the monitor.
> Maybe try some plug and unplug for the DP cable, or try another cable or monitor?
> 
> It seems that this board uses a DP to HDMI converter? Does this transmitter need a driver?
> 
> I won't be at my computer over the next two or three days, so any further replies to your email
> might have to wait until next week.
> 
> 

Andy,
FYI:

I done test on mine rock5a with applied Naoki dp0 enablement in dts (and only in dts).
No any changes in dw dp driver (so i?m on vanilla  https://patchwork.kernel.org/project/linux-rockchip/cover/20250223113036.74252-1-andyshrk at 163.com/   )

on mine rock5a ra620 hdmi port works ok.
(I contacted also Radxa about ra620 and they confirmed: ra620 is just DP->HDMI converter. No any driver nor special programming/enablement is needed)

This tells me that dp0 (rock5a) works ok while dp1 (rock5itx) not.
i suspect issue is probably in https://patchwork.kernel.org/project/linux-rockchip/cover/20250223113036.74252-1-andyshrk at 163.com/ and is related to dp1 handling?

BTW: there seems to be issue with video modes handling on dp0 port: 
-playing video 1920 at 1080@50 - ok
-playing then video1920 at 1080@59,64 hangs board?.

hdmi0 works ok. video modes issue is only on dp0





From sebastian.reichel at collabora.com  Sun Mar  9 14:17:29 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Sun, 9 Mar 2025 22:17:29 +0100
Subject: [PATCH v2 0/3] net: stmmac: dwmac-rk: Validate GRF and
 peripheral GRF during probe
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <n6frqyzi2rn3sbzmmerq5ennoo6dn2husrtw3qzbtummpjutc7@2bu2753xrb7a>

Hi,

On Sat, Mar 08, 2025 at 09:37:12PM +0000, Jonas Karlman wrote:
> All Rockchip GMAC variants typically write to GRF regs to control e.g.
> interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
> RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
> located with help of a rockchip,grf and rockchip,php-grf phandle.
> 
> However, validating the rockchip,grf and rockchip,php-grf syscon regmap
> is deferred until e.g. interface mode or speed is configured.
> 
> This series change to validate the GRF and peripheral GRF syscon regmap
> at probe time to help simplify the SoC specific operations.
> 
> This should not introduce any backward compatibility issues as all
> GMAC nodes have been added together with a rockchip,grf phandle (and
> rockchip,php-grf where required) in their initial commit.
> 
> Changes in v2:
> - Split removal of the IS_ERR() check in each SoC specific operation to
>   a separate patch
> - Disable rockchip,php-grf in schema for GMAC not requiring it
> - Add a php_grf_required flag to indicate when peripheral GRF is
>   required
> - Only lookup rockchip,php-grf phandle when php_grf_required is true
> - Use ERR_CAST() instead of ERR_PTR()
> 
> Jonas Karlman (3):
>   dt-bindings: net: rockchip-dwmac: Require rockchip,grf and
>     rockchip,php-grf
>   net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
>   net: stmmac: dwmac-rk: Remove unneeded GRF and peripheral GRF checks
> 
>  .../bindings/net/rockchip-dwmac.yaml          |  21 +-
>  .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 270 ++----------------
>  2 files changed, 37 insertions(+), 254 deletions(-)

The series is

Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250309/c464839d/attachment.sig>

From cristian.ciocaltea at collabora.com  Sun Mar  9 15:00:52 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Mon, 10 Mar 2025 00:00:52 +0200
Subject: [PATCH v5 07/12] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz
 unit conversion overhead
In-Reply-To: <20250309144747.744e5197@pumpkin>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-7-35087287f9d1@collabora.com>
 <CAA8EJpoQbvFbNXQ2RB1qY2gHnwZaU-PT-DMLnZkrxkqs2wkXqQ@mail.gmail.com>
 <a1a3e86a-1906-4797-932d-8e1aadafedde@collabora.com>
 <20250309144747.744e5197@pumpkin>
Message-ID: <0fe4388f-3374-409b-8383-ee5200961583@collabora.com>

On 3/9/25 4:47 PM, David Laight wrote:
> On Sun, 9 Mar 2025 12:13:32 +0200
> Cristian Ciocaltea <cristian.ciocaltea at collabora.com> wrote:
> 
>> On 3/9/25 11:22 AM, Dmitry Baryshkov wrote:
>>> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
>>> <cristian.ciocaltea at collabora.com> wrote:  
>>>>
>>>> The ropll_tmds_cfg table used to identify the configuration params for
>>>> the supported rates expects the search key, i.e. bit_rate member of
>>>> struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
>>>> Hz).  This requires multiple conversions between these units being
>>>> performed at runtime.
>>>>
>>>> Improve implementation clarity and efficiency by consistently using the
>>>> Hz unit throughout driver's internal data structures and functions.
>>>> Also rename the rather misleading struct member.
>>>>
>>>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>>>> ---
>>>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
>>>>  1 file changed, 39 insertions(+), 40 deletions(-)
>>>>
>>>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> index 2bf525514c1991a1299265d12e1e85f66333c604..e58a01bdb3ce82d66acdcb02c06de2816288b574 100644
>>>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>>>> @@ -330,7 +330,7 @@ enum dp_link_rate {
>>>>  };
>>>>
>>>>  struct ropll_config {
>>>> -       u32 bit_rate;
>>>> +       u32 rate;  
>>>
>>> unsigned long long, please, to match the tmds_char_rate type.
> 
> Isn't 'bit_rate' more descriptive?
> But maybe rate_hz to make the units more obvious.
> 
> If the max frequency might get near 4Gz then the you need something

The max freq. intended to be handled by the related config table is 600
MHz, that is for supporting HDMI 2.0 (TMDS).  Anything above that
requires HDMI 2.1 (FRL), which is currently not provided and would
anyway not rely on this data structure.

Regards,
Cristian


From jonas at kwiboo.se  Sun Mar  9 16:26:10 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:10 +0000
Subject: [PATCH v2 0/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
Message-ID: <20250309232622.1498084-1-jonas@kwiboo.se>

The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
used with the integrated PHY and a second 1000/100/10 MAC to be used
with an external Ethernet PHY.

This series add initial support for the Ethernet controllers found in
RK3528 and initial support to power up/down the integrated PHY.

This series depends on v2 of the "net: stmmac: dwmac-rk: Validate GRF
and peripheral GRF during probe" [1] cleanup series.


Changes in v2:
- Restrict the minItems: 4 change to rockchip,rk3528-gmac
- Add initial support to power up/down the integrated PHY in RK3528
- Split device tree changes into a separate series

[1] https://lore.kernel.org/r/20250308213720.2517944-1-jonas at kwiboo.se/

David Wu (1):
  net: stmmac: dwmac-rk: Add GMAC support for RK3528

Jonas Karlman (4):
  dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
  net: stmmac: dwmac-rk: Move integrated_phy_powerup/down functions
  net: stmmac: dwmac-rk: Add integrated_phy_powerdown operation
  net: stmmac: dwmac-rk: Add initial support for RK3528 integrated PHY

 .../bindings/net/rockchip-dwmac.yaml          |  16 +-
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 277 ++++++++++++++----
 2 files changed, 242 insertions(+), 51 deletions(-)

-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 16:26:13 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:13 +0000
Subject: [PATCH v2 3/5] net: stmmac: dwmac-rk: Move integrated_phy_powerup/down functions
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250309232622.1498084-4-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these SoCs.

Move the rk_gmac_integrated_phy_powerup/down functions to top of the
file to prepare for them to be called directly by a GMAC variant
specific powerup/down operation.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- New patch
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 88 +++++++++----------
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 03ea9368ffbb..31f4b7eb3718 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -92,6 +92,50 @@ struct rk_priv_data {
 	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
 	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
 
+#define RK_GRF_MACPHY_CON0		0xb00
+#define RK_GRF_MACPHY_CON1		0xb04
+#define RK_GRF_MACPHY_CON2		0xb08
+#define RK_GRF_MACPHY_CON3		0xb0c
+
+#define RK_MACPHY_ENABLE		GRF_BIT(0)
+#define RK_MACPHY_DISABLE		GRF_CLR_BIT(0)
+#define RK_MACPHY_CFG_CLK_50M		GRF_BIT(14)
+#define RK_GMAC2PHY_RMII_MODE		(GRF_BIT(6) | GRF_CLR_BIT(7))
+#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
+#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
+
+static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
+{
+	if (priv->ops->integrated_phy_powerup)
+		priv->ops->integrated_phy_powerup(priv);
+
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
+
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
+
+	if (priv->phy_reset) {
+		/* PHY needs to be disabled before trying to reset it */
+		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
+		if (priv->phy_reset)
+			reset_control_assert(priv->phy_reset);
+		usleep_range(10, 20);
+		if (priv->phy_reset)
+			reset_control_deassert(priv->phy_reset);
+		usleep_range(10, 20);
+		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
+		msleep(30);
+	}
+}
+
+static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
+{
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
+	if (priv->phy_reset)
+		reset_control_assert(priv->phy_reset);
+}
+
 #define PX30_GRF_GMAC_CON1		0x0904
 
 /* PX30_GRF_GMAC_CON1 */
@@ -1463,50 +1507,6 @@ static const struct rk_gmac_ops rv1126_ops = {
 	.set_rmii_speed = rv1126_set_rmii_speed,
 };
 
-#define RK_GRF_MACPHY_CON0		0xb00
-#define RK_GRF_MACPHY_CON1		0xb04
-#define RK_GRF_MACPHY_CON2		0xb08
-#define RK_GRF_MACPHY_CON3		0xb0c
-
-#define RK_MACPHY_ENABLE		GRF_BIT(0)
-#define RK_MACPHY_DISABLE		GRF_CLR_BIT(0)
-#define RK_MACPHY_CFG_CLK_50M		GRF_BIT(14)
-#define RK_GMAC2PHY_RMII_MODE		(GRF_BIT(6) | GRF_CLR_BIT(7))
-#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
-#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
-
-static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
-{
-	if (priv->ops->integrated_phy_powerup)
-		priv->ops->integrated_phy_powerup(priv);
-
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
-
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
-
-	if (priv->phy_reset) {
-		/* PHY needs to be disabled before trying to reset it */
-		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
-		if (priv->phy_reset)
-			reset_control_assert(priv->phy_reset);
-		usleep_range(10, 20);
-		if (priv->phy_reset)
-			reset_control_deassert(priv->phy_reset);
-		usleep_range(10, 20);
-		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
-		msleep(30);
-	}
-}
-
-static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
-{
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
-	if (priv->phy_reset)
-		reset_control_assert(priv->phy_reset);
-}
-
 static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
 {
 	struct rk_priv_data *bsp_priv = plat->bsp_priv;
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 16:26:11 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:11 +0000
Subject: [PATCH v2 1/5] dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250309232622.1498084-2-jonas@kwiboo.se>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add compatible string for the RK3528 variant.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Restrict the minItems: 4 change to rockchip,rk3528-gmac

The enum will be extended in a future patch, Pending RK3562 and a future
RK3506 variant also only have 4 clocks.

Because snps,dwmac-4.20a is already listed in snps,dwmac.yaml adding the
rockchip,rk3528-gmac compatible did not seem necessary.
---
 .../devicetree/bindings/net/rockchip-dwmac.yaml  | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
index 8dd870f0214d..fe417c19b597 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
@@ -24,6 +24,7 @@ select:
           - rockchip,rk3366-gmac
           - rockchip,rk3368-gmac
           - rockchip,rk3399-gmac
+          - rockchip,rk3528-gmac
           - rockchip,rk3568-gmac
           - rockchip,rk3576-gmac
           - rockchip,rk3588-gmac
@@ -49,6 +50,7 @@ properties:
               - rockchip,rv1108-gmac
       - items:
           - enum:
+              - rockchip,rk3528-gmac
               - rockchip,rk3568-gmac
               - rockchip,rk3576-gmac
               - rockchip,rk3588-gmac
@@ -56,7 +58,7 @@ properties:
           - const: snps,dwmac-4.20a
 
   clocks:
-    minItems: 5
+    minItems: 4
     maxItems: 8
 
   clock-names:
@@ -130,6 +132,18 @@ allOf:
       properties:
         rockchip,php-grf: false
 
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - rockchip,rk3528-gmac
+    then:
+      properties:
+        clocks:
+          minItems: 5
+
 unevaluatedProperties: false
 
 examples:
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 16:26:14 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:14 +0000
Subject: [PATCH v2 4/5] net: stmmac: dwmac-rk: Add integrated_phy_powerdown operation
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250309232622.1498084-5-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these newer SoCs.

Add a new integrated_phy_powerdown operation and change the call chain
for integrated_phy_powerup to prepare support for the integrated PHY
found in these newer SoCs.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- New patch
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 26 +++++++++++--------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 31f4b7eb3718..3f096b3ccee8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,6 +33,7 @@ struct rk_gmac_ops {
 	void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
 				    bool enable);
 	void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
+	void (*integrated_phy_powerdown)(struct rk_priv_data *bsp_priv);
 	bool php_grf_required;
 	bool regs_valid;
 	u32 regs[];
@@ -104,11 +105,8 @@ struct rk_priv_data {
 #define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
 #define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
 
-static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
+static void rk_gmac_integrated_ephy_powerup(struct rk_priv_data *priv)
 {
-	if (priv->ops->integrated_phy_powerup)
-		priv->ops->integrated_phy_powerup(priv);
-
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
 
@@ -129,7 +127,7 @@ static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
 	}
 }
 
-static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
+static void rk_gmac_integrated_ephy_powerdown(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
 	if (priv->phy_reset)
@@ -368,6 +366,8 @@ static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK3228_GRF_CON_MUX,
 		     RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY);
+
+	rk_gmac_integrated_ephy_powerup(priv);
 }
 
 static const struct rk_gmac_ops rk3228_ops = {
@@ -375,7 +375,8 @@ static const struct rk_gmac_ops rk3228_ops = {
 	.set_to_rmii = rk3228_set_to_rmii,
 	.set_rgmii_speed = rk3228_set_rgmii_speed,
 	.set_rmii_speed = rk3228_set_rmii_speed,
-	.integrated_phy_powerup =  rk3228_integrated_phy_powerup,
+	.integrated_phy_powerup = rk3228_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown,
 };
 
 #define RK3288_GRF_SOC_CON1	0x0248
@@ -601,6 +602,8 @@ static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK3328_GRF_MACPHY_CON1,
 		     RK3328_MACPHY_RMII_MODE);
+
+	rk_gmac_integrated_ephy_powerup(priv);
 }
 
 static const struct rk_gmac_ops rk3328_ops = {
@@ -608,7 +611,8 @@ static const struct rk_gmac_ops rk3328_ops = {
 	.set_to_rmii = rk3328_set_to_rmii,
 	.set_rgmii_speed = rk3328_set_rgmii_speed,
 	.set_rmii_speed = rk3328_set_rmii_speed,
-	.integrated_phy_powerup =  rk3328_integrated_phy_powerup,
+	.integrated_phy_powerup = rk3328_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown,
 };
 
 #define RK3366_GRF_SOC_CON6	0x0418
@@ -1802,16 +1806,16 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
 
 	pm_runtime_get_sync(dev);
 
-	if (bsp_priv->integrated_phy)
-		rk_gmac_integrated_phy_powerup(bsp_priv);
+	if (bsp_priv->integrated_phy && bsp_priv->ops->integrated_phy_powerup)
+		bsp_priv->ops->integrated_phy_powerup(bsp_priv);
 
 	return 0;
 }
 
 static void rk_gmac_powerdown(struct rk_priv_data *gmac)
 {
-	if (gmac->integrated_phy)
-		rk_gmac_integrated_phy_powerdown(gmac);
+	if (gmac->integrated_phy && gmac->ops->integrated_phy_powerdown)
+		gmac->ops->integrated_phy_powerdown(gmac);
 
 	pm_runtime_put_sync(&gmac->pdev->dev);
 
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 16:26:12 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:12 +0000
Subject: [PATCH v2 2/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250309232622.1498084-3-jonas@kwiboo.se>

From: David Wu <david.wu at rock-chips.com>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add initial support for the RK3528 GMAC variant.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- None

Power up/down of the integrated PHY is added in a separate patch.
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 132 ++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 342463587d06..03ea9368ffbb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -828,6 +828,137 @@ static const struct rk_gmac_ops rk3399_ops = {
 	.set_rmii_speed = rk3399_set_rmii_speed,
 };
 
+#define RK3528_VO_GRF_GMAC_CON		0x0018
+#define RK3528_VO_GRF_MACPHY_CON0	0x001c
+#define RK3528_VO_GRF_MACPHY_CON1	0x0020
+#define RK3528_VPU_GRF_GMAC_CON5	0x0018
+#define RK3528_VPU_GRF_GMAC_CON6	0x001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII	GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII	GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII	GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELECT_CRU	GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELECT_IO	GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2	GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20	GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2	GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20	GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1	(GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5	(GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50	(GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE	GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE	GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE	GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE	GRF_CLR_BIT(9)
+
+static void rk3528_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
+{
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     DELAY_ENABLE(RK3528, tx_delay, rx_delay));
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON6,
+		     RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+	if (bsp_priv->id == 1)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_PHY_INTF_SEL_RMII);
+	else
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON,
+			     RK3528_GMAC0_PHY_INTF_SEL_RMII |
+			     RK3528_GMAC0_CLK_RMII_DIV2);
+}
+
+static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (speed == 10)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV50);
+	else if (speed == 100)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV5);
+	else if (speed == 1000)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV1);
+	else
+		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+	unsigned int reg, val;
+
+	if (speed == 10)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 :
+					  RK3528_GMAC0_CLK_RMII_DIV20;
+	else if (speed == 100)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 :
+					  RK3528_GMAC0_CLK_RMII_DIV2;
+	else {
+		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+		return;
+	}
+
+	reg = bsp_priv->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 :
+				  RK3528_VO_GRF_GMAC_CON;
+
+	regmap_write(bsp_priv->grf, reg, val);
+}
+
+static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
+				       bool input, bool enable)
+{
+	unsigned int val;
+
+	if (bsp_priv->id == 1) {
+		val = input ? RK3528_GMAC1_CLK_SELECT_IO :
+			      RK3528_GMAC1_CLK_SELECT_CRU;
+		val |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+				RK3528_GMAC1_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+	} else {
+		val = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+			       RK3528_GMAC0_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON, val);
+	}
+}
+
+static const struct rk_gmac_ops rk3528_ops = {
+	.set_to_rgmii = rk3528_set_to_rgmii,
+	.set_to_rmii = rk3528_set_to_rmii,
+	.set_rgmii_speed = rk3528_set_rgmii_speed,
+	.set_rmii_speed = rk3528_set_rmii_speed,
+	.set_clock_selection = rk3528_set_clock_selection,
+	.regs_valid = true,
+	.regs = {
+		0xffbd0000, /* gmac0 */
+		0xffbe0000, /* gmac1 */
+		0x0, /* sentinel */
+	},
+};
+
 #define RK3568_GRF_GMAC0_CON0		0x0380
 #define RK3568_GRF_GMAC0_CON1		0x0384
 #define RK3568_GRF_GMAC1_CON0		0x0388
@@ -1816,6 +1947,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
 	{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
 	{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
+	{ .compatible = "rockchip,rk3528-gmac", .data = &rk3528_ops },
 	{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
 	{ .compatible = "rockchip,rk3576-gmac", .data = &rk3576_ops },
 	{ .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 16:26:15 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun,  9 Mar 2025 23:26:15 +0000
Subject: [PATCH v2 5/5] net: stmmac: dwmac-rk: Add initial support for RK3528 integrated PHY
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250309232622.1498084-6-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these newer SoCs.

Add operations to powerup/down the integrated PHY found in RK3528.
Use helpers that can be used by other GMAC variants in the future.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- New patch

This is enough to power up the integrated PHY on RK3528 for MDIO/MII.
However, a PHY driver is still missing and I do not have any RK3528
board that make use of this MAC and PHY, so something that can be
improved upon in the future.
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 3f096b3ccee8..ab2c872d33e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -134,6 +134,35 @@ static void rk_gmac_integrated_ephy_powerdown(struct rk_priv_data *priv)
 		reset_control_assert(priv->phy_reset);
 }
 
+#define RK_FEPHY_SHUTDOWN		GRF_BIT(1)
+#define RK_FEPHY_POWERUP		GRF_CLR_BIT(1)
+#define RK_FEPHY_INTERNAL_RMII_SEL	GRF_BIT(6)
+#define RK_FEPHY_24M_CLK_SEL		(GRF_BIT(8) | GRF_BIT(9))
+#define RK_FEPHY_PHY_ID			GRF_BIT(11)
+
+static void rk_gmac_integrated_fephy_powerup(struct rk_priv_data *priv,
+					     unsigned int reg)
+{
+	reset_control_assert(priv->phy_reset);
+	usleep_range(20, 30);
+
+	regmap_write(priv->grf, reg,
+		     RK_FEPHY_POWERUP |
+		     RK_FEPHY_INTERNAL_RMII_SEL |
+		     RK_FEPHY_24M_CLK_SEL |
+		     RK_FEPHY_PHY_ID);
+	usleep_range(10000, 12000);
+
+	reset_control_deassert(priv->phy_reset);
+	usleep_range(50000, 60000);
+}
+
+static void rk_gmac_integrated_fephy_powerdown(struct rk_priv_data *priv,
+					       unsigned int reg)
+{
+	regmap_write(priv->grf, reg, RK_FEPHY_SHUTDOWN);
+}
+
 #define PX30_GRF_GMAC_CON1		0x0904
 
 /* PX30_GRF_GMAC_CON1 */
@@ -993,12 +1022,24 @@ static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
 	}
 }
 
+static void rk3528_integrated_phy_powerup(struct rk_priv_data *bsp_priv)
+{
+	rk_gmac_integrated_fephy_powerup(bsp_priv, RK3528_VO_GRF_MACPHY_CON0);
+}
+
+static void rk3528_integrated_phy_powerdown(struct rk_priv_data *bsp_priv)
+{
+	rk_gmac_integrated_fephy_powerdown(bsp_priv, RK3528_VO_GRF_MACPHY_CON0);
+}
+
 static const struct rk_gmac_ops rk3528_ops = {
 	.set_to_rgmii = rk3528_set_to_rgmii,
 	.set_to_rmii = rk3528_set_to_rmii,
 	.set_rgmii_speed = rk3528_set_rgmii_speed,
 	.set_rmii_speed = rk3528_set_rmii_speed,
 	.set_clock_selection = rk3528_set_clock_selection,
+	.integrated_phy_powerup = rk3528_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk3528_integrated_phy_powerdown,
 	.regs_valid = true,
 	.regs = {
 		0xffbd0000, /* gmac0 */
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 17:12:49 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 10 Mar 2025 00:12:49 +0000
Subject: [PATCH v2 0/2] rockchip: Enable Ethernet controller on Radxa E20C
Message-ID: <20250310001254.1516138-1-jonas@kwiboo.se>

The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
used with the integrated PHY and a second 1000/100/10 MAC to be used
with an external Ethernet PHY.

This series add device tree nodes for the Ethernet controllers found in
RK3528 and enable the LAN interface on Radxa E20C.

This include a gmac0 node for the 100/10 MAC and its related integrated
PHY node that only have recived limited testing. I have no board that
expose an Ethernet port for the gmac0 and the integrated PHY. However,
the PHY can be identified on addr 0x2 as 0044.1400 and in vendor kernel
this relate to the Rockchip RK630 PHY. A proper PHY driver will be
needed to support any real use of gmac0.

Changes in v2:
- Split from the "Add GMAC support for RK3528" driver series [1]
- Add ethernet-phy at 2 for the integrated PHY
- Rebase on top of the "Support I2C controllers in RK3528" series [2]

This series depend on the "net: stmmac: dwmac-rk: Add GMAC support for
RK3528" [1] series and the "Support I2C controllers in RK3528" [2]
series for a clean apply.

[1] https://lore.kernel.org/r/20250309232622.1498084-1-jonas at kwiboo.se
[2] https://lore.kernel.org/r/20250309070603.35254-1-ziyao at disroot.org

Jonas Karlman (2):
  arm64: dts: rockchip: Add GMAC nodes for RK3528
  arm64: dts: rockchip: Enable Ethernet controller on Radxa E20C

 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   |  30 +++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 105 ++++++++++++++++++
 2 files changed, 135 insertions(+)

-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 17:12:50 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 10 Mar 2025 00:12:50 +0000
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add GMAC nodes for RK3528
In-Reply-To: <20250310001254.1516138-1-jonas@kwiboo.se>
References: <20250310001254.1516138-1-jonas@kwiboo.se>
Message-ID: <20250310001254.1516138-2-jonas@kwiboo.se>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add device tree nodes for the two Ethernet controllers in RK3528.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Add ethernet-phy at 2 for the integrated PHY

I have no board that expose an Ethernet port for the gmac0 and the
integrated PHY. However, the PHY can be identified on addr 0x2 as
0044.1400 and in vendor kernel this relate to the Rockchip RK630 PHY.
A proper PHY driver will be needed to support real use of gmac0.
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 105 +++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 4c0a25cc089c..56ced7c640f1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -678,6 +678,111 @@ saradc: adc at ffae0000 {
 			status = "disabled";
 		};
 
+		gmac0: ethernet at ffbd0000 {
+			compatible = "rockchip,rk3528-gmac", "snps,dwmac-4.20a";
+			reg = <0x0 0xffbd0000 0x0 0x10000>;
+			clocks = <&cru CLK_GMAC0_SRC>, <&cru CLK_GMAC0_RMII_50M>,
+				 <&cru CLK_GMAC0_RX>, <&cru CLK_GMAC0_TX>,
+				 <&cru PCLK_MAC_VO>, <&cru ACLK_MAC_VO>;
+			clock-names = "stmmaceth", "clk_mac_ref",
+				      "mac_clk_rx", "mac_clk_tx",
+				      "pclk_mac", "aclk_mac";
+			interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq";
+			phy-handle = <&rmii0_phy>;
+			phy-mode = "rmii";
+			resets = <&cru SRST_A_MAC_VO>;
+			reset-names = "stmmaceth";
+			rockchip,grf = <&vo_grf>;
+			snps,axi-config = <&gmac0_stmmac_axi_setup>;
+			snps,mixed-burst;
+			snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
+			snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
+			snps,tso;
+			status = "disabled";
+
+			mdio0: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+
+				rmii0_phy: ethernet-phy at 2 {
+					compatible = "ethernet-phy-ieee802.3-c22";
+					reg = <0x2>;
+					clocks = <&cru CLK_MACPHY>;
+					phy-is-integrated;
+					pinctrl-names = "default";
+					pinctrl-0 = <&fephym0_led_link>,
+						    <&fephym0_led_spd>;
+					resets = <&cru SRST_MACPHY>;
+				};
+			};
+
+			gmac0_stmmac_axi_setup: stmmac-axi-config {
+				snps,blen = <0 0 0 0 16 8 4>;
+				snps,rd_osr_lmt = <8>;
+				snps,wr_osr_lmt = <4>;
+			};
+
+			gmac0_mtl_rx_setup: rx-queues-config {
+				snps,rx-queues-to-use = <1>;
+				queue0 {};
+			};
+
+			gmac0_mtl_tx_setup: tx-queues-config {
+				snps,tx-queues-to-use = <1>;
+				queue0 {};
+			};
+		};
+
+		gmac1: ethernet at ffbe0000 {
+			compatible = "rockchip,rk3528-gmac", "snps,dwmac-4.20a";
+			reg = <0x0 0xffbe0000 0x0 0x10000>;
+			clocks = <&cru CLK_GMAC1_SRC_VPU>,
+				 <&cru CLK_GMAC1_RMII_VPU>,
+				 <&cru PCLK_MAC_VPU>,
+				 <&cru ACLK_MAC_VPU>;
+			clock-names = "stmmaceth",
+				      "clk_mac_ref",
+				      "pclk_mac",
+				      "aclk_mac";
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq";
+			resets = <&cru SRST_A_MAC>;
+			reset-names = "stmmaceth";
+			rockchip,grf = <&vpu_grf>;
+			snps,axi-config = <&gmac1_stmmac_axi_setup>;
+			snps,mixed-burst;
+			snps,mtl-rx-config = <&gmac1_mtl_rx_setup>;
+			snps,mtl-tx-config = <&gmac1_mtl_tx_setup>;
+			snps,tso;
+			status = "disabled";
+
+			mdio1: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+			};
+
+			gmac1_stmmac_axi_setup: stmmac-axi-config {
+				snps,blen = <0 0 0 0 16 8 4>;
+				snps,rd_osr_lmt = <8>;
+				snps,wr_osr_lmt = <4>;
+			};
+
+			gmac1_mtl_rx_setup: rx-queues-config {
+				snps,rx-queues-to-use = <1>;
+				queue0 {};
+			};
+
+			gmac1_mtl_tx_setup: tx-queues-config {
+				snps,tx-queues-to-use = <1>;
+				queue0 {};
+			};
+		};
+
 		sdhci: mmc at ffbf0000 {
 			compatible = "rockchip,rk3528-dwcmshc",
 				     "rockchip,rk3588-dwcmshc";
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar  9 17:12:51 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 10 Mar 2025 00:12:51 +0000
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Enable Ethernet controller on Radxa E20C
In-Reply-To: <20250310001254.1516138-1-jonas@kwiboo.se>
References: <20250310001254.1516138-1-jonas@kwiboo.se>
Message-ID: <20250310001254.1516138-3-jonas@kwiboo.se>

The Radxa E20C has two GbE ports, LAN and WAN. The LAN port is provided
using a GMAC controller and a YT8531C PHY and the WAN port is provided
by an RTL8111H PCIe Ethernet controller.

Enable support for the LAN port on Radxa E20C.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v2:
- Rebase on top of the "Support I2C controllers in RK3528" series [1]

[1] https://lore.kernel.org/r/20250309070603.35254-1-ziyao at disroot.org
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 790cd18f29cb..f4984e036f38 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -16,6 +16,7 @@ / {
 	compatible = "radxa,e20c", "rockchip,rk3528";
 
 	aliases {
+		ethernet0 = &gmac1;
 		mmc0 = &sdhci;
 		mmc1 = &sdmmc;
 	};
@@ -123,6 +124,17 @@ vccio_sd: regulator-vccio-sd {
 	};
 };
 
+&gmac1 {
+	clock_in_out = "output";
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-id";
+	phy-supply = <&vcc_3v3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_miim>, <&rgmii_tx_bus2>, <&rgmii_rx_bus2>,
+		    <&rgmii_rgmii_clk>, <&rgmii_rgmii_bus>;
+	status = "okay";
+};
+
 &i2c1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c1m0_xfer>;
@@ -136,7 +148,25 @@ eeprom at 50 {
 	};
 };
 
+&mdio1 {
+	rgmii_phy: ethernet-phy at 1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0x1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&gmac1_rstn_l>;
+		reset-assert-us = <20000>;
+		reset-deassert-us = <100000>;
+		reset-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
+	};
+};
+
 &pinctrl {
+	ethernet {
+		gmac1_rstn_l: gmac1-rstn-l {
+			rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	gpio-keys {
 		user_key: user-key {
 			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
-- 
2.48.1



From wei.liu at kernel.org  Sun Mar  9 17:31:04 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Mon, 10 Mar 2025 00:31:04 +0000
Subject: [PATCH hyperv-next v5 06/11] arm64, x86: hyperv: Report the VTL
 the system boots in
In-Reply-To: <20250307220304.247725-7-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-7-romank@linux.microsoft.com>
Message-ID: <Z84yyAqkqJ2ZyAd-@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Fri, Mar 07, 2025 at 02:02:58PM -0800, Roman Kisel wrote:
> The hyperv guest code might run in various Virtual Trust Levels.
> 
> Report the level when the kernel boots in the non-default (0)
> one.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  arch/arm64/hyperv/mshyperv.c | 2 ++
>  arch/x86/hyperv/hv_vtl.c     | 2 +-
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index a7db03f5413d..3bc16dbee758 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -108,6 +108,8 @@ static int __init hyperv_init(void)
>  	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
>  		hv_get_partition_id();
>  	ms_hyperv.vtl = get_vtl();
> +	if (ms_hyperv.vtl > 0) /* non default VTL */

"non-default".

> +		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
>  
>  	ms_hyperv_late_init();
>  
> diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
> index 4e1b1e3b5658..c21bee7e8ff3 100644
> --- a/arch/x86/hyperv/hv_vtl.c
> +++ b/arch/x86/hyperv/hv_vtl.c
> @@ -24,7 +24,7 @@ static bool __init hv_vtl_msi_ext_dest_id(void)
>  
>  void __init hv_vtl_init_platform(void)
>  {
> -	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
> +	pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);

Where isn't there a check for ms_hyperv.vtl > 0 here?

Please be consistent across different architectures.

>  
>  	x86_platform.realmode_reserve = x86_init_noop;
>  	x86_platform.realmode_init = x86_init_noop;
> -- 
> 2.43.0
> 
> 


From broonie at kernel.org  Sun Mar  9 18:26:01 2025
From: broonie at kernel.org (Mark Brown)
Date: Mon, 10 Mar 2025 01:26:01 +0000
Subject: [PATCH] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph
 port
In-Reply-To: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
References: <20250306053138.1914956-1-shengjiu.wang@nxp.com>
Message-ID: <174156996154.2353078.15110736493128457712.b4-ty@kernel.org>

On Thu, 06 Mar 2025 13:31:38 +0800, Shengjiu Wang wrote:
> This device can be used in conjunction with audio-graph-card to provide
> an endpoint for binding with the other side of the audio link.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph port
      commit: db91ad81a2545eb82aa47d0306bc3e1adb05e336

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From kevin_chen at aspeedtech.com  Sun Mar  9 18:50:30 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 01:50:30 +0000
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
 <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
Message-ID: <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>

> On 04/03/2025 11:44, Kevin Chen wrote:
> > Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.
> 
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory your
> patch is touching. For bindings, the preferred subjects are explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patch
> es.html#i-for-patch-submitters
> 
> Missing 's'.
> 
> >
> > Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> > ---
> >  .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 36
> +++++++++++++++++++
> >  1 file changed, 36 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> > b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> > index 5dfe77aca167..367847bd7e75 100644
> > --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> > +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> > @@ -149,6 +149,35 @@ patternProperties:
> >        - interrupts
> >        - snoop-ports
> >
> > +  "^lpc-pcc@[0-9a-f]+$":
> > +    type: object
> > +    additionalProperties: false
> > +
> > +    description:
> > +      The LPC pcc interface allows the BMC to listen on and record the
> data
> > +      bytes written by the Host to the targeted LPC I/O pots.
> > +
> > +    properties:
> > +      compatible:
> > +        items:
> > +          - enum:
> > +              - aspeed,ast2600-lpc-pcc
> > +
> > +      reg:
> > +        maxItems: 1
> > +
> > +      interrupts:
> > +        maxItems: 1
> > +
> > +      pcc-ports:
> 
> Missing vendor prefix
OK, so I need to add the vendor prefix such as "aspeed,pcc-ports". Right?
But I want to check the snoop-ports usage. In the HW controller, the usage should be the same.
Not only aspeed but nuvoton, there exist a HW module for the snoop-ports or pcc-ports usage.

> 
> > +        $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        description: The LPC I/O ports to pcc
> 
> Description is too vague. Why would we encode I/O ports as some numbers
> instead of GPIOs for example? If these are ports, why this is not a graph?
For the port-mmaped I/O in x80 architecture, BMC need to handle specific port I/O in the relative HW module.
So, I need to add the pcc-ports property as the snoop-ports property in Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml

> 
> Missing constraints - min/maxItems, defaults, minimum/maximum etc.
The port-mmaped I/O is defined from host, BMC as the device would capture the port I/O from the pcc-ports property defined in dts.

> 
> > +
> > +    required:
> > +      - compatible
> > +      - interrupts
> > +      - pcc-ports
> > +
> >    "^uart-routing@[0-9a-f]+$":
> >      $ref: /schemas/soc/aspeed/uart-routing.yaml#
> >      description: The UART routing control under LPC register space @@
> > -176,6 +205,13 @@ examples:
> >          #size-cells = <1>;
> >          ranges = <0x0 0x1e789000 0x1000>;
> >
> > +        lpc_pcc: lpc-pcc at 0 {
> > +            compatible = "aspeed,ast2600-lpc-pcc";
> > +            reg = <0x0 0x140>;
> > +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> > +            pcc-ports = <0x80>;
> 
> So what 0x80 stands for?
Host as x86 architecture would access the 0x80 port, which is mapped to the BMC PCC HW module.
As a result, x86 can keep the port-mmaped I/O usage and access the BMC device, which is needed to know which port using in the PCC module in BMC.

> 
> 
> Best regards,
> Krzysztof

From lkp at intel.com  Sun Mar  9 19:02:18 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 10 Mar 2025 10:02:18 +0800
Subject: [PATCH v2 2/4] ASoC: meson: g12a-toacodec: drop the definition
 of bits
In-Reply-To: <20250309181600.1322701-3-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-3-jan.dakinevich@salutedevices.com>
Message-ID: <202503100909.xnqNYW9u-lkp@intel.com>

Hi Jan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on linus/master v6.14-rc5 next-20250307]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jan-Dakinevich/ASoC-meson-codec-glue-add-support-for-capture-stream/20250310-022013
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
patch link:    https://lore.kernel.org/r/20250309181600.1322701-3-jan.dakinevich%40salutedevices.com
patch subject: [PATCH v2 2/4] ASoC: meson: g12a-toacodec: drop the definition of bits
config: i386-buildonly-randconfig-005-20250310 (https://download.01.org/0day-ci/archive/20250310/202503100909.xnqNYW9u-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250310/202503100909.xnqNYW9u-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503100909.xnqNYW9u-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> sound/soc/meson/g12a-toacodec.c:83:11: warning: result of comparison of constant 18446744073709551615 with expression of type 'typeof (_Generic((mclk_sel), char: (unsigned char)0, unsigned char: (unsigned char)0, signed char: (unsigned char)0, unsigned short: (unsigned short)0, short: (unsigned short)0, unsigned int: (unsigned int)0, int: (unsigned int)0, unsigned long: (unsigned long)0, long: (unsigned long)0, unsigned long long: (unsigned long long)0, long long: (unsigned long long)0, default: (mclk_sel)))' (aka 'unsigned int') is always false [-Wtautological-constant-out-of-range-compare]
      83 |                                       FIELD_PREP(mclk_sel, mux));
         |                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/bitfield.h:115:3: note: expanded from macro 'FIELD_PREP'
     115 |                 __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");    \
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/bitfield.h:72:53: note: expanded from macro '__BF_FIELD_CHECK'
      72 |                 BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) >     \
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
      73 |                                  __bf_cast_unsigned(_reg, ~0ull),       \
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      74 |                                  _pfx "type of reg too small for mask"); \
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:39:58: note: expanded from macro 'BUILD_BUG_ON_MSG'
      39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
         |                                     ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
   include/linux/compiler_types.h:542:22: note: expanded from macro 'compiletime_assert'
     542 |         _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |         ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler_types.h:530:23: note: expanded from macro '_compiletime_assert'
     530 |         __compiletime_assert(condition, msg, prefix, suffix)
         |         ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler_types.h:522:9: note: expanded from macro '__compiletime_assert'
     522 |                 if (!(condition))                                       \
         |                       ^~~~~~~~~
   1 warning generated.


vim +83 sound/soc/meson/g12a-toacodec.c

    42	
    43	static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol,
    44					      struct snd_ctl_elem_value *ucontrol)
    45	{
    46		struct snd_soc_component *component =
    47			snd_soc_dapm_kcontrol_component(kcontrol);
    48		struct g12a_toacodec *priv = snd_soc_component_get_drvdata(component);
    49		struct snd_soc_dapm_context *dapm =
    50			snd_soc_dapm_kcontrol_dapm(kcontrol);
    51		struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
    52		unsigned int mclk_sel = GENMASK(2, 0);
    53		unsigned int mux, reg;
    54	
    55		if (ucontrol->value.enumerated.item[0] >= e->items)
    56			return -EINVAL;
    57	
    58		mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
    59		regmap_field_read(priv->field_dat_sel, &reg);
    60	
    61		if (mux == reg)
    62			return 0;
    63	
    64		/* Force disconnect of the mux while updating */
    65		snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
    66	
    67		regmap_field_write(priv->field_dat_sel, mux);
    68		regmap_field_write(priv->field_lrclk_sel, mux);
    69		regmap_field_write(priv->field_bclk_sel, mux);
    70	
    71		/*
    72		 * FIXME:
    73		 * On this soc, the glue gets the MCLK directly from the clock
    74		 * controller instead of going the through the TDM interface.
    75		 *
    76		 * Here we assume interface A uses clock A, etc ... While it is
    77		 * true for now, it could be different. Instead the glue should
    78		 * find out the clock used by the interface and select the same
    79		 * source. For that, we will need regmap backed clock mux which
    80		 * is a work in progress
    81		 */
    82		snd_soc_component_update_bits(component, e->reg, mclk_sel,
  > 83					      FIELD_PREP(mclk_sel, mux));
    84	
    85		snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
    86	
    87		return 1;
    88	}
    89	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From quic_jiegan at quicinc.com  Sun Mar  9 19:07:32 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 10:07:32 +0800
Subject: [PATCH] Coresight: Improve the method for passing through perf
 handle
In-Reply-To: <20250211062021.7013-1-jie.gan@oss.qualcomm.com>
References: <20250211062021.7013-1-jie.gan@oss.qualcomm.com>
Message-ID: <549b3e5e-5ee1-426f-b256-f3efc1dc4908@quicinc.com>



On 2/11/2025 2:20 PM, Jie Gan wrote:
> From: James Clark <james.clark at linaro.org>
> 
> Currently, the perf handle is being passed to the sink device as a void
> parameter with additional type conversion. Improve the method for
> passing perf handle parameter to make the code more readable.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> Signed-off-by: Jie Gan <jie.gan at oss.qualcomm.com>
> ---
> prerequisite-message-id: <20250207064213.2314482-5-quic_jiegan at quicinc.com>

Gentle ping. The dependency has applied.

Thanks,
Jie

> ---
>   drivers/hwtracing/coresight/coresight-core.c    |  8 ++++----
>   drivers/hwtracing/coresight/coresight-dummy.c   |  2 +-
>   drivers/hwtracing/coresight/coresight-etb10.c   |  7 +++----
>   drivers/hwtracing/coresight/coresight-priv.h    |  2 +-
>   drivers/hwtracing/coresight/coresight-tmc-etf.c |  8 ++++----
>   drivers/hwtracing/coresight/coresight-tmc-etr.c | 11 +++++------
>   drivers/hwtracing/coresight/coresight-tmc.h     |  2 +-
>   drivers/hwtracing/coresight/coresight-tpiu.c    |  2 +-
>   drivers/hwtracing/coresight/coresight-trbe.c    |  3 +--
>   drivers/hwtracing/coresight/ultrasoc-smb.c      |  7 +++----
>   include/linux/coresight.h                       |  2 +-
>   11 files changed, 25 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 3bdd6ebd4b6e..9246b46bdc3b 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -272,9 +272,9 @@ void coresight_add_helper(struct coresight_device *csdev,
>   EXPORT_SYMBOL_GPL(coresight_add_helper);
>   
>   static int coresight_enable_sink(struct coresight_device *csdev,
> -				 enum cs_mode mode, void *data)
> +				 enum cs_mode mode, struct perf_output_handle *handle)
>   {
> -	return sink_ops(csdev)->enable(csdev, mode, data);
> +	return sink_ops(csdev)->enable(csdev, mode, handle);
>   }
>   
>   static void coresight_disable_sink(struct coresight_device *csdev)
> @@ -448,7 +448,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
>   }
>   
>   int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
> -			  void *sink_data)
> +			  struct perf_output_handle *handle)
>   {
>   	int ret = 0;
>   	u32 type;
> @@ -478,7 +478,7 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
>   
>   		switch (type) {
>   		case CORESIGHT_DEV_TYPE_SINK:
> -			ret = coresight_enable_sink(csdev, mode, sink_data);
> +			ret = coresight_enable_sink(csdev, mode, handle);
>   			/*
>   			 * Sink is the first component turned on. If we
>   			 * failed to enable the sink, there are no components
> diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
> index d9a811d44885..42de46949d73 100644
> --- a/drivers/hwtracing/coresight/coresight-dummy.c
> +++ b/drivers/hwtracing/coresight/coresight-dummy.c
> @@ -51,7 +51,7 @@ static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused
>   }
>   
>   static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
> -				void *data)
> +				struct perf_output_handle *handle)
>   {
>   	dev_dbg(csdev->dev.parent, "Dummy sink enabled\n");
>   
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index aea9ac9c4bd0..e373b0f590bf 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -167,13 +167,12 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
>   	return ret;
>   }
>   
> -static int etb_enable_perf(struct coresight_device *csdev, void *data)
> +static int etb_enable_perf(struct coresight_device *csdev, struct perf_output_handle *handle)
>   {
>   	int ret = 0;
>   	pid_t pid;
>   	unsigned long flags;
>   	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> -	struct perf_output_handle *handle = data;
>   	struct cs_buffers *buf = etm_perf_sink_config(handle);
>   
>   	spin_lock_irqsave(&drvdata->spinlock, flags);
> @@ -224,7 +223,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
>   }
>   
>   static int etb_enable(struct coresight_device *csdev, enum cs_mode mode,
> -		      void *data)
> +		      struct perf_output_handle *handle)
>   {
>   	int ret;
>   
> @@ -233,7 +232,7 @@ static int etb_enable(struct coresight_device *csdev, enum cs_mode mode,
>   		ret = etb_enable_sysfs(csdev);
>   		break;
>   	case CS_MODE_PERF:
> -		ret = etb_enable_perf(csdev, data);
> +		ret = etb_enable_perf(csdev, handle);
>   		break;
>   	default:
>   		ret = -EINVAL;
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index c10dd3643854..eca06a89843f 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -134,7 +134,7 @@ static inline void CS_UNLOCK(void __iomem *addr)
>   
>   void coresight_disable_path(struct coresight_path *path);
>   int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
> -			  void *sink_data);
> +			  struct perf_output_handle *handle);
>   struct coresight_device *coresight_get_sink(struct coresight_path *path);
>   struct coresight_device *coresight_get_sink_by_id(u32 id);
>   struct coresight_device *
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index d4f641cd9de6..fdf1c2511d67 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -244,13 +244,13 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
>   	return ret;
>   }
>   
> -static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
> +static int tmc_enable_etf_sink_perf(struct coresight_device *csdev,
> +				    struct perf_output_handle *handle)
>   {
>   	int ret = 0;
>   	pid_t pid;
>   	unsigned long flags;
>   	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> -	struct perf_output_handle *handle = data;
>   	struct cs_buffers *buf = etm_perf_sink_config(handle);
>   
>   	spin_lock_irqsave(&drvdata->spinlock, flags);
> @@ -302,7 +302,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
>   }
>   
>   static int tmc_enable_etf_sink(struct coresight_device *csdev,
> -			       enum cs_mode mode, void *data)
> +			       enum cs_mode mode, struct perf_output_handle *handle)
>   {
>   	int ret;
>   
> @@ -311,7 +311,7 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev,
>   		ret = tmc_enable_etf_sink_sysfs(csdev);
>   		break;
>   	case CS_MODE_PERF:
> -		ret = tmc_enable_etf_sink_perf(csdev, data);
> +		ret = tmc_enable_etf_sink_perf(csdev, handle);
>   		break;
>   	/* We shouldn't be here */
>   	default:
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index a48bb85d0e7f..2d0bd06bab2a 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1252,9 +1252,8 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
>   }
>   
>   struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
> -				   enum cs_mode mode, void *data)
> +				   enum cs_mode mode, struct perf_output_handle *handle)
>   {
> -	struct perf_output_handle *handle = data;
>   	struct etr_perf_buffer *etr_perf;
>   
>   	switch (mode) {
> @@ -1642,13 +1641,13 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
>   	return size;
>   }
>   
> -static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
> +static int tmc_enable_etr_sink_perf(struct coresight_device *csdev,
> +				    struct perf_output_handle *handle)
>   {
>   	int rc = 0;
>   	pid_t pid;
>   	unsigned long flags;
>   	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> -	struct perf_output_handle *handle = data;
>   	struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
>   
>   	spin_lock_irqsave(&drvdata->spinlock, flags);
> @@ -1696,13 +1695,13 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
>   }
>   
>   static int tmc_enable_etr_sink(struct coresight_device *csdev,
> -			       enum cs_mode mode, void *data)
> +			       enum cs_mode mode, struct perf_output_handle *handle)
>   {
>   	switch (mode) {
>   	case CS_MODE_SYSFS:
>   		return tmc_enable_etr_sink_sysfs(csdev);
>   	case CS_MODE_PERF:
> -		return tmc_enable_etr_sink_perf(csdev, data);
> +		return tmc_enable_etr_sink_perf(csdev, handle);
>   	default:
>   		return -EINVAL;
>   	}
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index 2671926be62a..e991afd43742 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -336,7 +336,7 @@ struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
>   void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu);
>   void tmc_etr_remove_catu_ops(void);
>   struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
> -				   enum cs_mode mode, void *data);
> +				   enum cs_mode mode, struct perf_output_handle *handle);
>   extern const struct attribute_group coresight_etr_group;
>   
>   #endif
> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
> index 97ef36f03ec2..ccf463ac7bf5 100644
> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
> @@ -75,7 +75,7 @@ static void tpiu_enable_hw(struct csdev_access *csa)
>   }
>   
>   static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,
> -		       void *__unused)
> +		       struct perf_output_handle *__unused)
>   {
>   	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>   
> diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
> index fff67aac8418..a0914d10ed47 100644
> --- a/drivers/hwtracing/coresight/coresight-trbe.c
> +++ b/drivers/hwtracing/coresight/coresight-trbe.c
> @@ -1011,11 +1011,10 @@ static int __arm_trbe_enable(struct trbe_buf *buf,
>   }
>   
>   static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode,
> -			   void *data)
> +			   struct perf_output_handle *handle)
>   {
>   	struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>   	struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev);
> -	struct perf_output_handle *handle = data;
>   	struct trbe_buf *buf = etm_perf_sink_config(handle);
>   
>   	WARN_ON(cpudata->cpu != smp_processor_id());
> diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
> index dc3c9504dd7c..1574b5067206 100644
> --- a/drivers/hwtracing/coresight/ultrasoc-smb.c
> +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
> @@ -213,10 +213,9 @@ static void smb_enable_sysfs(struct coresight_device *csdev)
>   	coresight_set_mode(csdev, CS_MODE_SYSFS);
>   }
>   
> -static int smb_enable_perf(struct coresight_device *csdev, void *data)
> +static int smb_enable_perf(struct coresight_device *csdev, struct perf_output_handle *handle)
>   {
>   	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
> -	struct perf_output_handle *handle = data;
>   	struct cs_buffers *buf = etm_perf_sink_config(handle);
>   	pid_t pid;
>   
> @@ -240,7 +239,7 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data)
>   }
>   
>   static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
> -		      void *data)
> +		      struct perf_output_handle *handle)
>   {
>   	struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
>   	int ret = 0;
> @@ -261,7 +260,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
>   		smb_enable_sysfs(csdev);
>   		break;
>   	case CS_MODE_PERF:
> -		ret = smb_enable_perf(csdev, data);
> +		ret = smb_enable_perf(csdev, handle);
>   		break;
>   	default:
>   		ret = -EINVAL;
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 55bb825d509e..937a8d4f815b 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -363,7 +363,7 @@ enum cs_mode {
>    */
>   struct coresight_ops_sink {
>   	int (*enable)(struct coresight_device *csdev, enum cs_mode mode,
> -		      void *data);
> +		      struct perf_output_handle *handle);
>   	int (*disable)(struct coresight_device *csdev);
>   	void *(*alloc_buffer)(struct coresight_device *csdev,
>   			      struct perf_event *event, void **pages,



From kevin_chen at aspeedtech.com  Sun Mar  9 19:15:31 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 02:15:31 +0000
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <7ef88ec2-24a5-4aa7-a601-d605a12768ba@wanadoo.fr>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
 <7ef88ec2-24a5-4aa7-a601-d605a12768ba@wanadoo.fr>
Message-ID: <PSAPR06MB49497EF12121AA18F21361A289D62@PSAPR06MB4949.apcprd06.prod.outlook.com>

> Le 04/03/2025 ? 11:44, Kevin Chen a ?crit?:
> > Add LPC PCC controller driver to support POST code capture.
> >
> > Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> 
> Hi,
> 
> > +	init_waitqueue_head(&pcc->wq);
> > +
> > +	pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL);
> 
> Missing ida_free() in therror handling path and in the rmove function?
OK. I will add the ida_free function in remove function. Thanks a lot.

> 
> > +	if (pcc->mdev_id < 0) {
> > +		dev_err(dev, "Couldn't allocate ID\n");
> > +		return pcc->mdev_id;
> > +	}
> > +
> > +	pcc->mdev.parent = dev;
> > +	pcc->mdev.minor = MISC_DYNAMIC_MINOR;
> > +	pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
> DEVICE_NAME,
> > +					pcc->mdev_id);
> > +	pcc->mdev.fops = &pcc_fops;
> > +	rc = misc_register(&pcc->mdev);
> > +	if (rc) {
> > +		dev_err(dev, "Couldn't register misc device\n");
> > +		goto err_free_kfifo;
> > +	}
> > +
> > +	rc = aspeed_pcc_enable(pcc, dev);
> > +	if (rc) {
> > +		dev_err(dev, "Couldn't enable PCC\n");
> > +		goto err_dereg_mdev;
> > +	}
> > +
> > +	dev_set_drvdata(&pdev->dev, pcc);
> > +
> > +	return 0;
> > +
> > +err_dereg_mdev:
> > +	misc_deregister(&pcc->mdev);
> > +
> > +err_free_kfifo:
> > +	kfifo_free(&pcc->fifo);
> > +
> > +	return rc;
> > +}
> > +
> > +static void aspeed_pcc_remove(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev);
> > +
> > +	kfifo_free(&pcc->fifo);
> > +	misc_deregister(&pcc->mdev);
> > +}
> > +
> > +static const struct of_device_id aspeed_pcc_table[] = {
> > +	{ .compatible = "aspeed,ast2600-lpc-pcc" },
> > +	{ },
> 
> Unneeded trailing comma after a terminator.
OK, I will remove it.

> 
> > +};
> > +
> > +static struct platform_driver aspeed_pcc_driver = {
> > +	.driver = {
> > +		.name = "aspeed-pcc",
> > +		.of_match_table = aspeed_pcc_table,
> > +	},
> > +	.probe = aspeed_pcc_probe,
> > +	.remove = aspeed_pcc_remove,
> > +};
> 
> ...
> 
> CJ

From yong.liang.choong at linux.intel.com  Sun Mar  9 19:15:44 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Mon, 10 Mar 2025 10:15:44 +0800
Subject: [bug report] net: stmmac: configure SerDes according to the
 interface mode
In-Reply-To: <677ffce5-0d76-4b97-abd3-1ac7608417f3@stanley.mountain>
References: <677ffce5-0d76-4b97-abd3-1ac7608417f3@stanley.mountain>
Message-ID: <2f1f4a5f-712e-45c4-ae9f-57105f92f14a@linux.intel.com>



On 8/3/2025 7:17 pm, Dan Carpenter wrote:
> Hello Choong Yong Liang,
> 
> Commit a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the
> interface mode") from Feb 27, 2025 (linux-next), leads to the
> following Smatch static checker warning:
> 
> 	drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c:497 intel_tsn_lane_is_available()
> 	warn: missing error code? 'ret'
> 
> drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
>      472 static int intel_tsn_lane_is_available(struct net_device *ndev,
>      473                                        struct intel_priv_data *intel_priv)
>      474 {
>      475         struct stmmac_priv *priv = netdev_priv(ndev);
>      476         struct pmc_ipc_cmd tmp = {};
>      477         struct pmc_ipc_rbuf rbuf = {};
>      478         int ret = 0, i, j;
> 
> Better to avoid initializing ret so that bug show up as uninitialized
> variables.
> 
>      479         const int max_fia_regs = 5;
>      480
>      481         tmp.cmd = IPC_SOC_REGISTER_ACCESS;
>      482         tmp.sub_cmd = IPC_SOC_SUB_CMD_READ;
>      483
>      484         for (i = 0; i < max_fia_regs; i++) {
>      485                 tmp.wbuf[0] = R_PCH_FIA_15_PCR_LOS1_REG_BASE + i;
>      486
>      487                 ret = intel_pmc_ipc(&tmp, &rbuf);
>      488                 if (ret < 0) {
>      489                         netdev_info(priv->dev, "Failed to read from PMC.\n");
>      490                         return ret;
>      491                 }
>      492
>      493                 for (j = 0; j <= intel_priv->max_tsn_lane_regs; j++)
>      494                         if ((rbuf.buf[0] >>
>      495                                 (4 * (intel_priv->tsn_lane_regs[j] % 8)) &
>      496                                         B_PCH_FIA_PCR_L0O) == 0xB)
> --> 497                                 return ret;
> 
> This should probably be return -EINVAL, right?
> 
>      498         }
>      499
>      500         return ret;
> 
> It's more clear to just return 0 for the success path.  Otherwise you
> have to read the code a bit.
> 
>      501 }
> 
> regards,
> dan carpenter

Hello Dan,

Thank you for bringing this to my attention.

The code at line 497 should return 0 to indicate success when the condition 
is met. Additionally, I will modify line 500 to return -EINVAL to clearly 
signify an error when no valid lane is found.

I will prepare and submit a patch to implement these changes. If you have 
any further feedback or suggestions, please feel free to let me know.

Thanks again for your valuable input.

Best regards,
Yong Liang


From baolu.lu at linux.intel.com  Sun Mar  9 19:21:03 2025
From: baolu.lu at linux.intel.com (Baolu Lu)
Date: Mon, 10 Mar 2025 10:21:03 +0800
Subject: [PATCH v3 08/23] iommu/vtd: Use virt_to_phys()
In-Reply-To: <8-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <8-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <2db8d0c9-f6df-48f3-8bbb-4592e86d92fa@linux.intel.com>

On 2/26/25 03:39, Jason Gunthorpe wrote:
> If all the inlines are unwound virt_to_dma_pfn() is simply:
>     return page_to_pfn(virt_to_page(p)) << (PAGE_SHIFT - VTD_PAGE_SHIFT);
> 
> Which can be re-arranged to:
>     (page_to_pfn(virt_to_page(p)) << PAGE_SHIFT) >> VTD_PAGE_SHIFT
> 
> The only caller is:
>     ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT)
> 
> re-arranged to:
>     ((page_to_pfn(virt_to_page(tmp_page)) << PAGE_SHIFT) >> VTD_PAGE_SHIFT) << VTD_PAGE_SHIFT
> 
> Which simplifies to:
>     page_to_pfn(virt_to_page(tmp_page)) << PAGE_SHIFT
> 
> That is the same as virt_to_phys(tmp_page), so just remove all of this.
> 
> Reviewed-by: Lu Baolu<baolu.lu at linux.intel.com>
> Signed-off-by: Jason Gunthorpe<jgg at nvidia.com>
> ---
>   drivers/iommu/intel/iommu.c |  3 ++-
>   drivers/iommu/intel/iommu.h | 19 -------------------
>   2 files changed, 2 insertions(+), 20 deletions(-)

Queued this cleanup patch for iommu/vt-d.

Thanks,
baolu


From fj6611ie at fujitsu.com  Sun Mar  9 19:23:35 2025
From: fj6611ie at fujitsu.com (Toshiyuki Sato (Fujitsu))
Date: Mon, 10 Mar 2025 02:23:35 +0000
Subject: [PATCH v3] serial: amba-pl011: Implement nbcon console
In-Reply-To: <20250204044428.2191983-1-fj6611ie@aa.jp.fujitsu.com>
References: <20250204044428.2191983-1-fj6611ie@aa.jp.fujitsu.com>
Message-ID: <TY4PR01MB13777DB55F2231F7399E42609D7D62@TY4PR01MB13777.jpnprd01.prod.outlook.com>

Dear Reviewers,

It has been about a month since this patch was merged into tty-next -> linux-next.
I would appreciate any comments or feedback on this patch.

Regards.
Toshiyuki Sato


> Implement the callbacks required for an NBCON console [0] on the
> amba-pl011 console driver.
> 
> Referred to the NBCON implementation work for 8250 [1] and imx [2].
> 
> The normal-priority write_thread checks for console ownership each time a
> character is printed.
> write_atomic holds the console ownership until the entire string is printed.
> 
> UART register operations are protected from other contexts by uart_port_lock,
> except for a final flush(nbcon_atomic_flush_unsafe) on panic.
> 
> The patch has been verified to correctly handle the output and competition of
> messages with different priorities and flushing panic message to console after
> nmi panic using ARM64 QEMU and a physical machine(A64FX).
> 
> Stress testing was conducted on a physical machine(A64FX).
> The results are as follows:
> 
> - The output speed and volume of messages using the NBCON console were
>   comparable to the legacy console (data suggests a slight improvement).
> 
> - When inducing a panic (sysrq-triggered or NMI) under heavy contention
>   on the serial console output,
>   the legacy console resulted in the loss of some or all crash messages.
>   However, using the NBCON console, no message loss occurred.
> 
> This testing referenced the NBCON console work for 8250 [3].
> 
> [0] https://lore.kernel.org/all/ZuRRTbapH0DCj334 at pathway.suse.cz/
> [1]
> https://lore.kernel.org/all/20240913140538.221708-1-john.ogness at linutronix.d
> e/T/
> [2]
> https://lore.kernel.org/linux-arm-kernel/20240913-serial-imx-nbcon-v3-1-4c62
> 7302335b at geanix.com/T/
> [3]
> https://lore.kernel.org/lkml/ZsdoD6PomBRsB-ow at debarbos-thinkpadt14sgen2
> i.remote.csb/#t
> 
> Signed-off-by: Toshiyuki Sato <fj6611ie at aa.jp.fujitsu.com>
> ---
> This patch removes the legacy console code.
> Please comment if you have any concerns.
> 
> Changes in v3:
> - Add stress test results to patch comments.
> - based on tty-next branch
>   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
> v2:
> https://lore.kernel.org/all/20250115052749.3205675-1-fj6611ie at aa.jp.fujitsu.c
> om/
> 
> Changes in v2:
> - Remove the module parameter used to switch between legacy and NBCON.
> - Remove codes for legacy console.
> - Fix build errors detected by the test robot.
> - based on 6.13-rc7
> v1:
> https://lore.kernel.org/all/20250108004730.2302996-1-fj6611ie at aa.jp.fujitsu.c
> om/
> 
> Thanks Greg for the comment.
> ---
>  drivers/tty/serial/amba-pl011.c | 143
> ++++++++++++++++++++++----------
>  1 file changed, 97 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
> index 04212c823..9a9a1d630 100644
> --- a/drivers/tty/serial/amba-pl011.c
> +++ b/drivers/tty/serial/amba-pl011.c
> @@ -272,6 +272,7 @@ struct uart_amba_port {
>  	enum pl011_rs485_tx_state	rs485_tx_state;
>  	struct hrtimer		trigger_start_tx;
>  	struct hrtimer		trigger_stop_tx;
> +	bool			console_line_ended;
>  #ifdef CONFIG_DMA_ENGINE
>  	/* DMA stuff */
>  	unsigned int		dmacr;		/* dma control reg */
> @@ -2366,50 +2367,7 @@ static void pl011_console_putchar(struct uart_port
> *port, unsigned char ch)
>  	while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
>  		cpu_relax();
>  	pl011_write(ch, uap, REG_DR);
> -}
> -
> -static void
> -pl011_console_write(struct console *co, const char *s, unsigned int count) -{
> -	struct uart_amba_port *uap = amba_ports[co->index];
> -	unsigned int old_cr = 0, new_cr;
> -	unsigned long flags;
> -	int locked = 1;
> -
> -	clk_enable(uap->clk);
> -
> -	if (oops_in_progress)
> -		locked = uart_port_trylock_irqsave(&uap->port, &flags);
> -	else
> -		uart_port_lock_irqsave(&uap->port, &flags);
> -
> -	/*
> -	 *	First save the CR then disable the interrupts
> -	 */
> -	if (!uap->vendor->always_enabled) {
> -		old_cr = pl011_read(uap, REG_CR);
> -		new_cr = old_cr & ~UART011_CR_CTSEN;
> -		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
> -		pl011_write(new_cr, uap, REG_CR);
> -	}
> -
> -	uart_console_write(&uap->port, s, count, pl011_console_putchar);
> -
> -	/*
> -	 *	Finally, wait for transmitter to become empty and restore the
> -	 *	TCR. Allow feature register bits to be inverted to work around
> -	 *	errata.
> -	 */
> -	while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr)
> -						& uap->vendor->fr_busy)
> -		cpu_relax();
> -	if (!uap->vendor->always_enabled)
> -		pl011_write(old_cr, uap, REG_CR);
> -
> -	if (locked)
> -		uart_port_unlock_irqrestore(&uap->port, flags);
> -
> -	clk_disable(uap->clk);
> +	uap->console_line_ended = (ch == '\n');
>  }
> 
>  static void pl011_console_get_options(struct uart_amba_port *uap, int *baud,
> @@ -2472,6 +2430,8 @@ static int pl011_console_setup(struct console *co, char
> *options)
>  	if (ret)
>  		return ret;
> 
> +	uap->console_line_ended = true;
> +
>  	if (dev_get_platdata(uap->port.dev)) {
>  		struct amba_pl011_data *plat;
> 
> @@ -2555,14 +2515,105 @@ static int pl011_console_match(struct console *co,
> char *name, int idx,
>  	return -ENODEV;
>  }
> 
> +static void
> +pl011_console_write_atomic(struct console *co, struct
> +nbcon_write_context *wctxt) {
> +	struct uart_amba_port *uap = amba_ports[co->index];
> +	unsigned int old_cr = 0;
> +
> +	if (!nbcon_enter_unsafe(wctxt))
> +		return;
> +
> +	clk_enable(uap->clk);
> +
> +	if (!uap->vendor->always_enabled) {
> +		old_cr = pl011_read(uap, REG_CR);
> +		pl011_write((old_cr & ~UART011_CR_CTSEN) |
> (UART01x_CR_UARTEN | UART011_CR_TXE),
> +				uap, REG_CR);
> +	}
> +
> +	if (!uap->console_line_ended)
> +		uart_console_write(&uap->port, "\n", 1,
> pl011_console_putchar);
> +	uart_console_write(&uap->port, wctxt->outbuf, wctxt->len,
> +pl011_console_putchar);
> +
> +	while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) &
> uap->vendor->fr_busy)
> +		cpu_relax();
> +
> +	if (!uap->vendor->always_enabled)
> +		pl011_write(old_cr, uap, REG_CR);
> +
> +	clk_disable(uap->clk);
> +
> +	nbcon_exit_unsafe(wctxt);
> +}
> +
> +static void
> +pl011_console_write_thread(struct console *co, struct
> +nbcon_write_context *wctxt) {
> +	struct uart_amba_port *uap = amba_ports[co->index];
> +	unsigned int old_cr = 0;
> +
> +	if (!nbcon_enter_unsafe(wctxt))
> +		return;
> +
> +	clk_enable(uap->clk);
> +
> +	if (!uap->vendor->always_enabled) {
> +		old_cr = pl011_read(uap, REG_CR);
> +		pl011_write((old_cr & ~UART011_CR_CTSEN) |
> (UART01x_CR_UARTEN | UART011_CR_TXE),
> +				uap, REG_CR);
> +	}
> +
> +	if (nbcon_exit_unsafe(wctxt)) {
> +		int i;
> +		unsigned int len = READ_ONCE(wctxt->len);
> +
> +		for (i = 0; i < len; i++) {
> +			if (!nbcon_enter_unsafe(wctxt))
> +				break;
> +			uart_console_write(&uap->port, wctxt->outbuf + i, 1,
> pl011_console_putchar);
> +			if (!nbcon_exit_unsafe(wctxt))
> +				break;
> +		}
> +	}
> +
> +	while (!nbcon_enter_unsafe(wctxt))
> +		nbcon_reacquire_nobuf(wctxt);
> +
> +	while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) &
> uap->vendor->fr_busy)
> +		cpu_relax();
> +
> +	if (!uap->vendor->always_enabled)
> +		pl011_write(old_cr, uap, REG_CR);
> +
> +	clk_disable(uap->clk);
> +
> +	nbcon_exit_unsafe(wctxt);
> +}
> +
> +static void
> +pl011_console_device_lock(struct console *co, unsigned long *flags) {
> +	__uart_port_lock_irqsave(&amba_ports[co->index]->port, flags); }
> +
> +static void
> +pl011_console_device_unlock(struct console *co, unsigned long flags) {
> +	__uart_port_unlock_irqrestore(&amba_ports[co->index]->port, flags); }
> +
>  static struct uart_driver amba_reg;
>  static struct console amba_console = {
>  	.name		= "ttyAMA",
> -	.write		= pl011_console_write,
>  	.device		= uart_console_device,
>  	.setup		= pl011_console_setup,
>  	.match		= pl011_console_match,
> -	.flags		= CON_PRINTBUFFER | CON_ANYTIME,
> +	.write_atomic	= pl011_console_write_atomic,
> +	.write_thread	= pl011_console_write_thread,
> +	.device_lock	= pl011_console_device_lock,
> +	.device_unlock	= pl011_console_device_unlock,
> +	.flags		= CON_PRINTBUFFER | CON_ANYTIME |
> CON_NBCON,
>  	.index		= -1,
>  	.data		= &amba_reg,
>  };
> 
> base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
> --
> 2.34.1



From quic_jiegan at quicinc.com  Sun Mar  9 19:23:48 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 10:23:48 +0800
Subject: [PATCH] coresight: add verification process for coresight_etm_get_trace_id
Message-ID: <20250310022348.1654501-1-quic_jiegan@quicinc.com>

The coresight_etm_get_trace_id function is a global function. The
verification process for 'csdev' is required prior to its usage.

Fixes: c367a89dec26 ("Coresight: Add trace_id function to retrieving the trace ID")
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/coresight-core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..5a7cd2376e2d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1616,9 +1616,12 @@ EXPORT_SYMBOL_GPL(coresight_remove_driver);
 int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
 			       struct coresight_device *sink)
 {
-	int trace_id;
-	int cpu = source_ops(csdev)->cpu_id(csdev);
+	int cpu, trace_id;
+
+	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE && !source_ops(csdev)->cpu_id)
+		return -EINVAL;
 
+	cpu = source_ops(csdev)->cpu_id(csdev);
 	switch (mode) {
 	case CS_MODE_SYSFS:
 		trace_id = coresight_trace_id_get_cpu_id(cpu);
-- 
2.34.1



From 0x1207 at gmail.com  Sun Mar  9 19:24:32 2025
From: 0x1207 at gmail.com (Furong Xu)
Date: Mon, 10 Mar 2025 10:24:32 +0800
Subject: [PATCH iwl-next v9 03/14] net: ethtool: mm: reset verification
 status when link is down
In-Reply-To: <20250309104648.3895551-4-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
	<20250309104648.3895551-4-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250310102432.000032ad@gmail.com>

On Sun,  9 Mar 2025 06:46:37 -0400
Faizal Rahim <faizal.abdul.rahim at linux.intel.com> wrote:

> When the link partner goes down, "ethtool --show-mm" still displays
> "Verification status: SUCCEEDED," reflecting a previous state that is
> no longer valid.
> 
> Reset the verification status to ensure it reflects the current state.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---
>  net/ethtool/mm.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
> index bfd988464d7d..ad9b40034003 100644
> --- a/net/ethtool/mm.c
> +++ b/net/ethtool/mm.c
> @@ -415,6 +415,10 @@ void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
>  		/* New link => maybe new partner => new verification process */
>  		ethtool_mmsv_apply(mmsv);
>  	} else {
> +		/* Reset the reported verification state while the link is down */
> +		if (mmsv->verify_enabled)
> +			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
> +
>  		/* No link or pMAC not enabled */
>  		ethtool_mmsv_configure_pmac(mmsv, false);
>  		ethtool_mmsv_configure_tx(mmsv, false);

Reviewed-by: Furong Xu <0x1207 at gmail.com>



From quic_jiegan at quicinc.com  Sun Mar  9 19:57:36 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 10:57:36 +0800
Subject: [PATCH v15 10/10] arm64: dts: qcom: sa8775p: Add CTCU and ETR
 nodes
In-Reply-To: <0be31ecd-4386-4eb6-ad6f-a4409a3fc6ad@arm.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-11-quic_jiegan@quicinc.com>
 <0be31ecd-4386-4eb6-ad6f-a4409a3fc6ad@arm.com>
Message-ID: <942d0b2f-c3c1-466d-b894-9dd32ec4e6a1@quicinc.com>



On 3/4/2025 8:28 PM, Suzuki K Poulose wrote:
> On 03/03/2025 03:29, Jie Gan wrote:
>> Add CTCU and ETR nodes in DT to enable related functionalities.
>>
>> Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> 
> Assuming this goes via the soc tree,
> 
> Acked-by: Suzuki K Poulose <suzuki.poulose at arm.com>

Hi Bjorn, Konrad

Gentle ping.

The driver part has applied. BTW, I found this patch has a conflict on 
tag next-20250307, do you need me to send a new rebased patch?

Thanks,
Jie

> 
> 
>> ---
>> ? arch/arm64/boot/dts/qcom/sa8775p.dtsi | 153 ++++++++++++++++++++++++++
>> ? 1 file changed, 153 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/ 
>> dts/qcom/sa8775p.dtsi
>> index 3394ae2d1300..31aa94d2a043 100644
>> --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
>> @@ -2429,6 +2429,35 @@ crypto: crypto at 1dfa000 {
>> ????????????? interconnect-names = "memory";
>> ????????? };
>> +??????? ctcu at 4001000 {
>> +??????????? compatible = "qcom,sa8775p-ctcu";
>> +??????????? reg = <0x0 0x04001000 0x0 0x1000>;
>> +
>> +??????????? clocks = <&aoss_qmp>;
>> +??????????? clock-names = "apb";
>> +
>> +??????????? in-ports {
>> +??????????????? #address-cells = <1>;
>> +??????????????? #size-cells = <0>;
>> +
>> +??????????????? port at 0 {
>> +??????????????????? reg = <0>;
>> +
>> +??????????????????? ctcu_in0: endpoint {
>> +??????????????????????? remote-endpoint = <&etr0_out>;
>> +??????????????????? };
>> +??????????????? };
>> +
>> +??????????????? port at 1 {
>> +??????????????????? reg = <1>;
>> +
>> +??????????????????? ctcu_in1: endpoint {
>> +??????????????????????? remote-endpoint = <&etr1_out>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +??????? };
>> +
>> ????????? stm: stm at 4002000 {
>> ????????????? compatible = "arm,coresight-stm", "arm,primecell";
>> ????????????? reg = <0x0 0x4002000 0x0 0x1000>,
>> @@ -2633,6 +2662,122 @@ qdss_funnel_in1: endpoint {
>> ????????????? };
>> ????????? };
>> +??????? replicator at 4046000 {
>> +??????????? compatible = "arm,coresight-dynamic-replicator", 
>> "arm,primecell";
>> +??????????? reg = <0x0 0x04046000 0x0 0x1000>;
>> +
>> +??????????? clocks = <&aoss_qmp>;
>> +??????????? clock-names = "apb_pclk";
>> +
>> +??????????? in-ports {
>> +??????????????? port {
>> +??????????????????? qdss_rep_in: endpoint {
>> +??????????????????????? remote-endpoint = <&swao_rep_out0>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +
>> +??????????? out-ports {
>> +??????????????? port {
>> +??????????????????? qdss_rep_out0: endpoint {
>> +??????????????????????? remote-endpoint = <&etr_rep_in>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +??????? };
>> +
>> +??????? tmc_etr: tmc at 4048000 {
>> +??????????? compatible = "arm,coresight-tmc", "arm,primecell";
>> +??????????? reg = <0x0 0x04048000 0x0 0x1000>;
>> +
>> +??????????? clocks = <&aoss_qmp>;
>> +??????????? clock-names = "apb_pclk";
>> +??????????? iommus = <&apps_smmu 0x04c0 0x00>;
>> +
>> +??????????? arm,scatter-gather;
>> +
>> +??????????? in-ports {
>> +??????????????? port {
>> +??????????????????? etr0_in: endpoint {
>> +??????????????????????? remote-endpoint = <&etr_rep_out0>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +
>> +??????????? out-ports {
>> +??????????????? port {
>> +??????????????????? etr0_out: endpoint {
>> +??????????????????????? remote-endpoint = <&ctcu_in0>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +??????? };
>> +
>> +??????? replicator at 404e000 {
>> +??????????? compatible = "arm,coresight-dynamic-replicator", 
>> "arm,primecell";
>> +??????????? reg = <0x0 0x0404e000 0x0 0x1000>;
>> +
>> +??????????? clocks = <&aoss_qmp>;
>> +??????????? clock-names = "apb_pclk";
>> +
>> +??????????? in-ports {
>> +??????????????? port {
>> +??????????????????? etr_rep_in: endpoint {
>> +??????????????????????? remote-endpoint = <&qdss_rep_out0>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +
>> +??????????? out-ports {
>> +??????????????? #address-cells = <1>;
>> +??????????????? #size-cells = <0>;
>> +
>> +??????????????? port at 0 {
>> +??????????????????? reg = <0>;
>> +
>> +??????????????????? etr_rep_out0: endpoint {
>> +??????????????????????? remote-endpoint = <&etr0_in>;
>> +??????????????????? };
>> +??????????????? };
>> +
>> +??????????????? port at 1 {
>> +??????????????????? reg = <1>;
>> +
>> +??????????????????? etr_rep_out1: endpoint {
>> +??????????????????????? remote-endpoint = <&etr1_in>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +??????? };
>> +
>> +??????? tmc_etr1: tmc at 404f000 {
>> +??????????? compatible = "arm,coresight-tmc", "arm,primecell";
>> +??????????? reg = <0x0 0x0404f000 0x0 0x1000>;
>> +
>> +??????????? clocks = <&aoss_qmp>;
>> +??????????? clock-names = "apb_pclk";
>> +??????????? iommus = <&apps_smmu 0x04a0 0x40>;
>> +
>> +??????????? arm,scatter-gather;
>> +??????????? arm,buffer-size = <0x400000>;
>> +
>> +??????????? in-ports {
>> +??????????????? port {
>> +??????????????????? etr1_in: endpoint {
>> +??????????????????????? remote-endpoint = <&etr_rep_out1>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +
>> +??????????? out-ports {
>> +??????????????? port {
>> +??????????????????? etr1_out: endpoint {
>> +??????????????????????? remote-endpoint = <&ctcu_in1>;
>> +??????????????????? };
>> +??????????????? };
>> +??????????? };
>> +??????? };
>> +
>> ????????? funnel at 4b04000 {
>> ????????????? compatible = "arm,coresight-dynamic-funnel", 
>> "arm,primecell";
>> ????????????? reg = <0x0 0x4b04000 0x0 0x1000>;
>> @@ -2708,6 +2853,14 @@ out-ports {
>> ????????????????? #address-cells = <1>;
>> ????????????????? #size-cells = <0>;
>> +??????????????? port at 0 {
>> +??????????????????? reg = <0>;
>> +
>> +??????????????????? swao_rep_out0: endpoint {
>> +??????????????????????? remote-endpoint = <&qdss_rep_in>;
>> +??????????????????? };
>> +??????????????? };
>> +
>> ????????????????? port at 1 {
>> ????????????????????? reg = <1>;
>> ????????????????????? swao_rep_out1: endpoint {
> 



From Axe.Yang at mediatek.com  Sun Mar  9 20:31:30 2025
From: Axe.Yang at mediatek.com (=?utf-8?B?QXhlIFlhbmcgKOadqOejiik=?=)
Date: Mon, 10 Mar 2025 03:31:30 +0000
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <20250307-bust-diving-a57644a51543@spud>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
	 <20250306085028.5024-2-axe.yang@mediatek.com>
	 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
	 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
	 <20250307-bust-diving-a57644a51543@spud>
Message-ID: <322f45738a1d0b1bbcd1c5921c9bc8d955793ae6.camel@mediatek.com>

On Fri, 2025-03-07 at 15:48 +0000, Conor Dooley wrote:
> On Fri, Mar 07, 2025 at 06:59:03AM +0000, Axe Yang (??) wrote:
> > On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
> > > > Add 'mediatek,disable-single-burst' setting. This property can
> > > > be
> > > > used to switch bus burst type, from single burst to INCR, which
> > > > is
> > > > determined by the bus type within the IP. Some versions of the
> > > > IP
> > > > are using AXI bus, thus this switch is necessary as 'single' is
> > > > not
> > > > the burst type supported by the bus.
> > > > 
> > > > Signed-off-by: Axe Yang <axe.yang at mediatek.com>
> > > 
> > > I am mostly sure that this is not something to put in devicetree,
> > > but
> > > as
> > > platform data for specific SoC(s), as much as I'm mostly sure
> > > that
> > > all of
> > > the instances of the MSDC IP in one SoC will be *all* using
> > > either
> > > single
> > > or INCR.
> > 
> > No, actually MSDC IPs in one SoC are using different versions.
> > Usually MSDC1 (index from 1) is used as eMMC host, the left hosts
> > are
> > used as SD/SDIO hosts. They have similar designs, but there are
> > still
> > difference.
> > 
> > > 
> > > So, I think I know the answer but I'll still ask just to be
> > > extremely
> > > sure:
> > > 
> > > is there any MediaTek SoC that has different IP versions for
> > > different MSDC
> > > instances, and that hence require single burst on one instance
> > > and
> > > INCR on
> > > another instance?
> > 
> > Yes. Actually every SoC has different IP versions for eMMC and
> > SD/SDIO
> > host as I said.
> > e.g. For MT8168, signel burst bit should be set to 1 for eMMC Host,
> > but
> > 0 for SD/SDIO Host.
> > 
> 
> Sounds like two different IPs that really should have different
> compatibles to me...

Yes, so considering all factors, adding a device tree property might be
the most appropriate approach. This method is more flexible and
convenient.
Another reason, which I didn't mention in the previous reply, is that
MediaTek has too many SoCs using MSDC. Currently, there are already 13
mtXXXX compatible structures in the msdc driver, and a significant
portion of the SoC settings can be reused by the new SoC (without
adding a compatible for new SoC). 
If we add a variable in the compatible to represent the single burst
setting for eMMC/SD/SDIO (maybe using a u8 type variable as bitmap for
different hosts, bit0 for msdc0, bit1 for msdc1, bit2 for msdc2, ...),
we might have to add a compatible for each Soc, leading to a
significant increase in the number of compatibles and making it more
complex.

Regards,
Axe

> > > 
> > > And if there is - is there a pattern? Is it always SDIO requiring
> > > INCR or
> > > always eMMC/SD requiring it?
> > > 
> > > 
> > 
> > No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
> > configured base on IP version. There is no binding relationship
> > between
> > eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
> > single, same as SD/SDIO.
> > 
> > 
> > Regards,
> > Axe
> > 
> > 
> > > 
> > > > ---
> > > >   Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8
> > > > ++++++++
> > > >   1 file changed, 8 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > index 0debccbd6519..6076aff0a689 100644
> > > > --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > @@ -100,6 +100,14 @@ properties:
> > > >       minimum: 0
> > > >       maximum: 0xffffffff
> > > > 
> > > > +  mediatek,disable-single-burst:
> > > > +    $ref: /schemas/types.yaml#/definitions/flag
> > > > +    description:
> > > > +      Burst type setting. For some versions of the IP that do
> > > > not
> > > > use
> > > > +      AHB bus, the burst type need to be switched to INCR.
> > > > +      If present, use INCR burst type.
> > > > +      If not present, use single burst type.
> > > > +
> > > >     mediatek,hs200-cmd-int-delay:
> > > >       $ref: /schemas/types.yaml#/definitions/uint32
> > > >       description:
> > > 
> > > 
> > > 

From anshuman.khandual at arm.com  Sun Mar  9 21:01:15 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 09:31:15 +0530
Subject: [PATCH V2] arm64/mm: Define PTDESC_ORDER
Message-ID: <20250310040115.91298-1-anshuman.khandual@arm.com>

Address bytes shifted with a single 64 bit page table entry (any page table
level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
is not very readable or easy to reason about. Besides it is going to change
with D128, where each 128 bit page table entry will shift address bytes by
4 (aka 2^4 = 16) instead.

Let's just formalise this address bytes shift value into a new macro called
PTDESC_ORDER establishing a logical abstraction, thus improving readability
as well. While here re-organize EARLY_LEVEL macro along with its dependents
for better clarity. This does not cause any functional change.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
Cc: Alexander Potapenko <glider at google.com>
Cc: Andrey Konovalov <andreyknvl at gmail.com>
Cc: Dmitry Vyukov <dvyukov at google.com>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: kasan-dev at googlegroups.com
Acked-by: Ard Biesheuvel <ardb at kernel.org>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
This patch applies on v6.14-rc6

Changes in V2:

- Replaced PTE_SHIFT with PTDESC_ORDER per Ard
- Re-organized EARLY_LEVEL macro per Mark

Changes in V1:

https://lore.kernel.org/all/20250307050851.4034393-1-anshuman.khandual at arm.com/

 arch/arm64/Kconfig                      |  2 +-
 arch/arm64/include/asm/kernel-pgtable.h | 11 ++++++----
 arch/arm64/include/asm/pgtable-hwdef.h  | 27 ++++++++++++++-----------
 arch/arm64/kernel/pi/map_range.c        |  2 +-
 arch/arm64/mm/kasan_init.c              |  6 +++---
 5 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..657baf59fdbe 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
 	default 18
 
 # max bits determined by the following formula:
-#  VA_BITS - PAGE_SHIFT - 3
+#  VA_BITS - PAGE_SHIFT - PTDESC_ORDER
 config ARCH_MMAP_RND_BITS_MAX
 	default 19 if ARM64_VA_BITS=36
 	default 24 if ARM64_VA_BITS=39
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index fd5a08450b12..78c7e03a0e35 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -45,11 +45,14 @@
 #define SPAN_NR_ENTRIES(vstart, vend, shift) \
 	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
 
-#define EARLY_ENTRIES(vstart, vend, shift, add) \
-	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
+/* Number of VA bits resolved by a single translation table level */
+#define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)
 
-#define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
-	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
+#define EARLY_ENTRIES(lvl, vstart, vend) \
+	SPAN_NR_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT)
+
+#define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
+	((lvls) > (lvl) ? EARLY_ENTRIES(lvl, vstart, vend) + (add) : 0)
 
 #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
 	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index a9136cc551cc..3c544edc3968 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -7,40 +7,43 @@
 
 #include <asm/memory.h>
 
+#define PTDESC_ORDER 3
+
 /*
  * Number of page-table levels required to address 'va_bits' wide
  * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
- * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
+ * bits with (PAGE_SHIFT - PTDESC_ORDER) bits at each page table level. Hence:
  *
- *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
+ *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTDESC_ORDER))
  *
  * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
  *
  * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
  * due to build issues. So we open code DIV_ROUND_UP here:
  *
- *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
+ *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTDESC_ORDER) - 1) / (PAGE_SHIFT - PTDESC_ORDER))
  *
  * which gets simplified as :
  */
-#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
+#define ARM64_HW_PGTABLE_LEVELS(va_bits) \
+	(((va_bits) - PTDESC_ORDER - 1) / (PAGE_SHIFT - PTDESC_ORDER))
 
 /*
  * Size mapped by an entry at level n ( -1 <= n <= 3)
- * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
+ * We map (PAGE_SHIFT - PTDESC_ORDER) at all translation levels and PAGE_SHIFT bits
  * in the final page. The maximum number of translation levels supported by
  * the architecture is 5. Hence, starting at level n, we have further
  * ((4 - n) - 1) levels of translation excluding the offset within the page.
  * So, the total number of bits mapped by an entry at level n is :
  *
- *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
+ *  ((4 - n) - 1) * (PAGE_SHIFT - PTDESC_ORDER) + PAGE_SHIFT
  *
  * Rearranging it a bit we get :
- *   (4 - n) * (PAGE_SHIFT - 3) + 3
+ *   (4 - n) * (PAGE_SHIFT - PTDESC_ORDER) + PTDESC_ORDER
  */
-#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
+#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTDESC_ORDER) * (4 - (n)) + PTDESC_ORDER)
 
-#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTDESC_ORDER))
 
 /*
  * PMD_SHIFT determines the size a level 2 page table entry can map.
@@ -49,7 +52,7 @@
 #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
 #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE-1))
-#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
 #endif
 
 /*
@@ -59,14 +62,14 @@
 #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
 #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
 #define PUD_MASK		(~(PUD_SIZE-1))
-#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
 #endif
 
 #if CONFIG_PGTABLE_LEVELS > 4
 #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
 #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
 #define P4D_MASK		(~(P4D_SIZE-1))
-#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTDESC_ORDER))
 #endif
 
 /*
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..f74335e13929 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 {
 	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
 	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
-	int lshift = (3 - level) * (PAGE_SHIFT - 3);
+	int lshift = (3 - level) * (PAGE_SHIFT - PTDESC_ORDER);
 	u64 lmask = (PAGE_SIZE << lshift) - 1;
 
 	start	&= PAGE_MASK;
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index b65a29440a0c..211821f80571 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
  */
 static bool __init root_level_aligned(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
 
 	return (addr % (PAGE_SIZE << shift)) == 0;
 }
@@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
 	 */
 	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
 							: vabits_actual;
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
 
 	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
 }
@@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
  */
 static int __init next_level_idx(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTDESC_ORDER);
 
 	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
 }
-- 
2.25.1



From yong.liang.choong at linux.intel.com  Sun Mar  9 22:08:35 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Mon, 10 Mar 2025 13:08:35 +0800
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for return value in intel_tsn_lane_is_available()
Message-ID: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>

Fix the warning "warn: missing error code? 'ret'" in the
intel_tsn_lane_is_available() function.

The function now returns 0 to indicate that a TSN lane was found and
returns -EINVAL when it is not found.

Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the interface mode")
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 9c8de47ee149..5910571a954f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -494,10 +494,10 @@ static int intel_tsn_lane_is_available(struct net_device *ndev,
 			if ((rbuf.buf[0] >>
 				(4 * (intel_priv->tsn_lane_regs[j] % 8)) &
 					B_PCH_FIA_PCR_L0O) == 0xB)
-				return ret;
+				return 0;
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int intel_set_reg_access(const struct pmc_serdes_regs *regs, int max_regs)
-- 
2.34.1



From anshuman.khandual at arm.com  Sun Mar  9 23:28:12 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 11:58:12 +0530
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in map_range()
Message-ID: <20250310062812.216031-1-anshuman.khandual@arm.com>

Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
section mapping at all page table levels except the last level. This works
fine as the section mapping masks are exactly the same (0x1UL) for all page
table levels.

This will change in the future with D128 page tables that have unique skip
level values (SKL) required for creating section mapping at different page
table levels. Hence use page table level specific section mapping macros
instead of the common PMD_TYPE_SECT. While here also ensure that a section
mapping is only created on page table levels which could support that on a
given page size configuration otherwise fall back to create table entries.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
This patch applies on v6.14-rc6

Changes in V2:

- Dropped PGD_TYPE_SECT macro and its instance from map_range()
- Create table entries on levels where section mapping is not possible

Changes in V1:

https://lore.kernel.org/all/20250303041834.2796751-1-anshuman.khandual at arm.com/

 arch/arm64/kernel/pi/map_range.c | 38 +++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..25a70c675c4d 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -11,6 +11,22 @@
 
 #include "pi.h"
 
+static bool sect_supported(int level)
+{
+	switch (level) {
+	case -1:
+		return false;
+	case 0:
+		if (IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
+		    IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+			return false;
+		else
+			return true;
+	default:
+		return true;
+	}
+}
+
 /**
  * map_range - Map a contiguous range of physical pages into virtual memory
  *
@@ -44,13 +60,29 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	 * Set the right block/page bits for this level unless we are
 	 * clearing the mapping
 	 */
-	if (protval)
-		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
+	if (protval && sect_supported(level)) {
+		switch (level) {
+		case 3:
+			protval |= PTE_TYPE_PAGE;
+			break;
+		case 2:
+			protval |= PMD_TYPE_SECT;
+			break;
+		case 1:
+			protval |= PUD_TYPE_SECT;
+			break;
+		case 0:
+			protval |= P4D_TYPE_SECT;
+			break;
+		default:
+			break;
+		}
+	}
 
 	while (start < end) {
 		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
 
-		if (level < 3 && (start | next | pa) & lmask) {
+		if ((level < 3 && (start | next | pa) & lmask) || !sect_supported(level)) {
 			/*
 			 * This chunk needs a finer grained mapping. Create a
 			 * table mapping if necessary and recurse.
-- 
2.25.1



From anshuman.khandual at arm.com  Sun Mar  9 23:38:36 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 12:08:36 +0530
Subject: [PATCH V2 0/8] arm64/mm: Drop PXD_TABLE_BIT
In-Reply-To: <20250221044227.1145393-1-anshuman.khandual@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
Message-ID: <aae26951-3409-476c-b31d-1738cafe730a@arm.com>

On 2/21/25 10:12, Anshuman Khandual wrote:
> Remove the PXX_TABLE_BIT definitions and instead rely on PXX_TYPE_MASK,
> PXX_TYPE_SECT and PXX_TYPE_TABLE. The latter versions are more abstract
> and also include the PTE_VALID bit.
> 
> This abstraction is valuable for the impending D128 page table support,
> which doesn't have a single page table bit to determine table vs block.
> Instead it has the skip level (SKL) field, where it will consider 0 to
> mean table and any other value to mean a block entry. So PXX_TABLE_BIT
> therefore doesn't fit into the D128 model well, but the type fields do.
> 
> This series applies on v6.14-rc3.
> 
> Changes in V2:
> 
> - Changed pmd_mkhuge() and pud_mkhuge() implementation
> - Changed pud_bad() implementation with an additional patch
> 
> Changes in V1:
> 
> https://lore.kernel.org/all/20241005123824.1366397-1-anshuman.khandual at arm.com/
> 
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Cc: James Morse <james.morse at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: kvmarm at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> 
> Anshuman Khandual (6):
>   KVM: arm64: ptdump: Test PMD_TYPE_MASK for block mapping
>   arm64/ptdump: Test PMD_TYPE_MASK for block mapping
>   arm64/mm: Clear PXX_TYPE_MASK in mk_[pmd|pud]_sect_prot()
>   arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT in [pmd|pud]_mkhuge()
>   arm64/mm: Check PXD_TYPE_TABLE in [p4d|pgd]_bad()
>   arm64/mm: Drop PXD_TABLE_BIT
> 
> Ryan Roberts (2):
>   arm64/mm: Check PUD_TYPE_TABLE in pud_bad()
>   arm64/mm: Check pmd_table() in pmd_trans_huge()
> 
>  arch/arm64/include/asm/pgtable-hwdef.h |  5 --
>  arch/arm64/include/asm/pgtable.h       | 65 ++++++++++++++++++--------
>  arch/arm64/kvm/ptdump.c                |  4 +-
>  arch/arm64/mm/ptdump.c                 |  4 +-
>  4 files changed, 50 insertions(+), 28 deletions(-)
>

Gentle ping again. Does this series look okay or is there any objection ?


From gregkh at linuxfoundation.org  Sun Mar  9 23:58:25 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon, 10 Mar 2025 07:58:25 +0100
Subject: [PATCH v3] serial: amba-pl011: Implement nbcon console
In-Reply-To: <TY4PR01MB13777DB55F2231F7399E42609D7D62@TY4PR01MB13777.jpnprd01.prod.outlook.com>
References: <20250204044428.2191983-1-fj6611ie@aa.jp.fujitsu.com>
 <TY4PR01MB13777DB55F2231F7399E42609D7D62@TY4PR01MB13777.jpnprd01.prod.outlook.com>
Message-ID: <2025031001-outwit-outsider-b34e@gregkh>

On Mon, Mar 10, 2025 at 02:23:35AM +0000, Toshiyuki Sato (Fujitsu) wrote:
> Dear Reviewers,
> 
> It has been about a month since this patch was merged into tty-next -> linux-next.
> I would appreciate any comments or feedback on this patch.

What needs to be commented on?  It is accepted and will be merged in the
next -rc merge cycle.

confused,

greg k-h


From amadeus at jmu.edu.cn  Mon Mar 10 00:00:23 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Mon, 10 Mar 2025 15:00:23 +0800
Subject: [PATCH 3/3] arm64: dts: rockchip: Add onboard EEPROM for Radxa E20C
In-Reply-To: <20250309070603.35254-4-ziyao@disroot.org>
References: <20250309070603.35254-4-ziyao@disroot.org>
Message-ID: <20250310070023.52290-1-amadeus@jmu.edu.cn>

Hi,

> +&i2c1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&i2c1m0_xfer>;
> +	status = "okay";
> +
> +	eeprom at 50 {
> +		compatible = "belling,bl24c16a", "atmel,24c16";
> +		reg = <0x50>;
> +		pagesize = <16>;
> +		vcc-supply = <&vcc_3v3>;
> +	};
> +};

This eeprom stores the device information written by the manufacturer,
such as mac address and sn. So it should be marked as read-only.

Thanks,
Chukun

-- 
2.25.1



From peng.fan at oss.nxp.com  Mon Mar 10 01:16:35 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Mon, 10 Mar 2025 16:16:35 +0800
Subject: [PATCH NOT APPLY v2 4/4] clk: scmi: Support spread spectrum
In-Reply-To: <Z8iKErarE0lHWxEy@pluto>
References: <20250205-clk-ssc-v2-0-fa73083caa92@nxp.com>
 <20250205-clk-ssc-v2-4-fa73083caa92@nxp.com>
 <Z6SqeNsAqbZM8nr1@pluto>
 <20250303041125.GC13236@nxa18884-linux>
 <Z8iKErarE0lHWxEy@pluto>
Message-ID: <20250310081635.GA16799@nxa18884-linux>

On Wed, Mar 05, 2025 at 05:29:54PM +0000, Cristian Marussi wrote:
>On Mon, Mar 03, 2025 at 12:11:25PM +0800, Peng Fan wrote:
>> Hi Cristian,
>> 
>> On Thu, Feb 06, 2025 at 12:26:32PM +0000, Cristian Marussi wrote:
>> >On Wed, Feb 05, 2025 at 05:49:54PM +0800, Peng Fan (OSS) wrote:
>> >> From: Peng Fan <peng.fan at nxp.com>
>> >> 
>> >> Support Spread Spectrum with adding scmi_clk_set_spread_spectrum
>> >> 
>> >
>> >Hi,
>> >
>> >I forwarded ATG with our latest exchange on the possibility of using a
>> >standard OEM type instead of Vendor one if it is general enough....
>> 
>> Do you have any update?
>> 
>
>Yes I think you can go on with your original plan of using vendor OEM
>types: as of now we are not gonna standardize a new commmon SCMI type
>for Clock-SS, given there is really just one SCMI user of such clock
>features...maybe in the future if more users shows up...

Thanks for updating me. Back to how to add extensions in clk-scmi.c,
do you have any suggestions? I am thinking to provide vendor/sub-vendor
for clk-scmi.c and use vendor "NXP" sub-vedor "IMX" for spread spectrum.

Thanks,
Peng


>
>Thanks,
>Cristian


From victor.liu at nxp.com  Mon Mar 10 00:13:49 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Mon, 10 Mar 2025 15:13:49 +0800
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <20250307122212.18252ca6@booty>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
 <f8df2b5e-b005-4ada-8108-159b2b94a72e@nxp.com>
 <20250307122212.18252ca6@booty>
Message-ID: <47b0e1a1-1333-402e-b316-efc4dd9eee50@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> Hello Liu,

Hello Luca,

> 
> thanks for your reviews.
> 
> On Fri, 7 Mar 2025 14:33:37 +0800
> Liu Ying <victor.liu at nxp.com> wrote:
> 
>> On 03/07/2025, Luca Ceresoli wrote:
>>> This warning notifies a clock was set to an inaccurate value. Modify the
>>> string to also show the clock name.
>>>
>>> While doing that also rewrap the entire function call.
>>>
>>> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
>>> ---
>>>  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
>>> index 0fc8a14fd80062248a43b8b93272101a7ca6158a..c7c899a9644bb827845fb3fe96a9695d79a91474 100644
>>> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
>>> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
>>> @@ -181,9 +181,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
>>>  
>>>  	configured_link_freq = clk_get_rate(fsl_ldb->clk);
>>>  	if (configured_link_freq != requested_link_freq)
>>> -		dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
>>> -			 configured_link_freq,
>>> -			 requested_link_freq);
>>> +		dev_warn(fsl_ldb->dev,
>>> +			 "Configured %pC clock (%lu Hz) does not match requested LVDS clock: %lu Hz\n",
>>> +			 fsl_ldb->clk, configured_link_freq, requested_link_freq);  
>>
>> Though this slightly changes the warning message userspace sees, I guess it is
>> acceptable.
>>
>> Does it make sense to s/%pC/%pCn/ so that the clock name is printed in lower
>> case instead of upper case, since it seems that all i.MX specific clock names
>> are in lower case?
> 
> %pC and %pCn print the same string, as I just discovered at
> https://elixir.bootlin.com/linux/v6.14-rc5/source/lib/vsprintf.c#L1972

Ack.

> 
> I've pondering for a moment about whether we should document %pC and
> %pCn produce the same output or rather %pCn. I decided to try the
> latter and just sent a patch to do it [0].
> 
> FYI in my case the printed value is (with both %pC and %pCn)
> "32ec0000.blk-ctrl:bridge at 5c".

This is the LDB device name. The i.MX8MP LDB clock name is "media_ldb_root_clk".

Acked-by: Liu Ying <victor.liu at nxp.com>

> 
> [0] https://lore.kernel.org/20250307-vsprintf-pcn-v1-0-df0b2ccf610f at bootlin.com
> 
> Luca
> 

-- 
Regards,
Liu Ying


From krzk at kernel.org  Mon Mar 10 00:15:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:15:20 +0100
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
 <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
 <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>
Message-ID: <e17cdf9d-ba96-41d2-9656-9e50d0e0795a@kernel.org>

On 10/03/2025 02:50, Kevin Chen wrote:
>>> +        $ref: /schemas/types.yaml#/definitions/uint32-array
>>> +        description: The LPC I/O ports to pcc
>>
>> Description is too vague. Why would we encode I/O ports as some numbers
>> instead of GPIOs for example? If these are ports, why this is not a graph?
> For the port-mmaped I/O in x80 architecture, BMC need to handle specific port I/O in the relative HW module.
> So, I need to add the pcc-ports property as the snoop-ports property in Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> 
>>
>> Missing constraints - min/maxItems, defaults, minimum/maximum etc.
> The port-mmaped I/O is defined from host, BMC as the device would capture the port I/O from the pcc-ports property defined in dts.

Put this information in the description, instead of copying property name.

> 
>>
>>> +
>>> +    required:
>>> +      - compatible
>>> +      - interrupts
>>> +      - pcc-ports
>>> +
>>>    "^uart-routing@[0-9a-f]+$":
>>>      $ref: /schemas/soc/aspeed/uart-routing.yaml#
>>>      description: The UART routing control under LPC register space @@
>>> -176,6 +205,13 @@ examples:
>>>          #size-cells = <1>;
>>>          ranges = <0x0 0x1e789000 0x1000>;
>>>
>>> +        lpc_pcc: lpc-pcc at 0 {
>>> +            compatible = "aspeed,ast2600-lpc-pcc";
>>> +            reg = <0x0 0x140>;
>>> +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
>>> +            pcc-ports = <0x80>;
>>
>> So what 0x80 stands for?
> Host as x86 architecture would access the 0x80 port, which is mapped to the BMC PCC HW module.
> As a result, x86 can keep the port-mmaped I/O usage and access the BMC device, which is needed to know which port using in the PCC module in BMC.

And on different boards this is not 0x80?

Best regards,
Krzysztof


From ping.bai at nxp.com  Mon Mar 10 00:16:40 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Mon, 10 Mar 2025 15:16:40 +0800
Subject: [PATCH] cpufreq: Init cpufreq only for present CPUs
Message-ID: <20250310071640.3140435-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpufreq
in below cpufreq drivers:
  drivers/cpufreq/cpufreq-dt.c
  drivers/cpufreq/mediatek-cpufreq-hw.c
  drivers/cpufreq/mediatek-cpufreq.c
  drivers/cpufreq/qcom-cpufreq-nvmem.c
  drivers/cpufreq/sun50i-cpufreq-nvmem.c

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the cpufreq probe failure or defer probe due to no cpu device
available for not present CPUs.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpufreq drivers to ensure it only registers cpufreq for
CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 drivers/cpufreq/cpufreq-dt.c           | 2 +-
 drivers/cpufreq/mediatek-cpufreq-hw.c  | 2 +-
 drivers/cpufreq/mediatek-cpufreq.c     | 2 +-
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 8 ++++----
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++---
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 778916f89a51..e80dd982a3e2 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -283,7 +283,7 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
 	int ret, cpu;
 
 	/* Request resources early so we can return in case of -EPROBE_DEFER */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = dt_cpufreq_early_init(&pdev->dev, cpu);
 		if (ret)
 			goto err;
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
index aa209f5527dc..74f1b4c796e4 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -303,7 +303,7 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev)
 	struct regulator *cpu_reg;
 
 	/* Make sure that all CPU supplies are available before proceeding. */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_dev = get_cpu_device(cpu);
 		if (!cpu_dev)
 			return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 2656b88db378..f3f02c4b6888 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -631,7 +631,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "failed to get mtk cpufreq platform data\n");
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		info = mtk_cpu_dvfs_info_lookup(cpu);
 		if (info)
 			continue;
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 3a8ed723a23e..54f8117103c8 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 		nvmem_cell_put(speedbin_nvmem);
 	}
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct dev_pm_opp_config config = {
 			.supported_hw = NULL,
 		};
@@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 	dev_err(cpu_dev, "Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
 	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
 	unsigned int cpu;
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		qcom_cpufreq_suspend_pd_devs(drv, cpu);
 
 	return 0;
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 17d6a149f580..47d6840b3489 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	snprintf(name, sizeof(name), "speed%d", speed);
 	config.prop_name = name;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev = get_cpu_device(cpu);
 
 		if (!cpu_dev) {
@@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	pr_err("Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 	kfree(opp_tokens);
 
@@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 
 	kfree(opp_tokens);
-- 
2.34.1



From ziyao at disroot.org  Mon Mar 10 00:15:58 2025
From: ziyao at disroot.org (Yao Zi)
Date: Mon, 10 Mar 2025 07:15:58 +0000
Subject: [PATCH 3/3] arm64: dts: rockchip: Add onboard EEPROM for Radxa
 E20C
In-Reply-To: <20250310070023.52290-1-amadeus@jmu.edu.cn>
References: <20250309070603.35254-4-ziyao@disroot.org>
 <20250310070023.52290-1-amadeus@jmu.edu.cn>
Message-ID: <Z86RrlBTvt9d40Dk@pie>

On Mon, Mar 10, 2025 at 03:00:23PM +0800, Chukun Pan wrote:
> Hi,
> 
> > +&i2c1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&i2c1m0_xfer>;
> > +	status = "okay";
> > +
> > +	eeprom at 50 {
> > +		compatible = "belling,bl24c16a", "atmel,24c16";
> > +		reg = <0x50>;
> > +		pagesize = <16>;
> > +		vcc-supply = <&vcc_3v3>;
> > +	};
> > +};
> 
> This eeprom stores the device information written by the manufacturer,
> such as mac address and sn. So it should be marked as read-only.

Thanks, this makes sense.

> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Best regards,
Yao Zi


From krzk at kernel.org  Mon Mar 10 00:22:43 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:22:43 +0100
Subject: [PATCH 02/10] dt-bindings: display/msm: dsi-controller-main:
 describe SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-2-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-2-1d4c30f43822@linaro.org>
Message-ID: <20250310-wise-jumping-moose-b45f1b@krzk-bin>

On Sat, Mar 08, 2025 at 03:42:20AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Describe MIPI DSI controller present on Qualcomm SAR2130P platform.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From ziyao at disroot.org  Mon Mar 10 00:22:45 2025
From: ziyao at disroot.org (Yao Zi)
Date: Mon, 10 Mar 2025 07:22:45 +0000
Subject: [PATCH 2/3] arm64: dts: rockchip: Add I2C controllers for RK3528
In-Reply-To: <20250309080025.15825-1-amadeus@jmu.edu.cn>
References: <20250309070603.35254-3-ziyao@disroot.org>
 <20250309080025.15825-1-amadeus@jmu.edu.cn>
Message-ID: <Z86TRS4iLm66AqW6@pie>

On Sun, Mar 09, 2025 at 04:00:25PM +0800, Chukun Pan wrote:
> Hi,
> 
> > +		i2c0: i2c at ffa50000 {
> > +			compatible = "rockchip,rk3528-i2c",
> > +				     "rockchip,rk3399-i2c";
> > +			reg = <0x0 0xffa50000 0x0 0x1000>;
> > +			clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
> > +			clock-names = "i2c", "pclk";
> > +			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
> 
> It would be better to add default pinctrl for all i2c nodes
> using m0 group. (Only 1 group of pinctrl for i2c4 and i2c7)

Seems i2c2, i2c4 and i2c7 could be assigned to only one set of pins,
for them I'll add default pinctrls. For the other controllers, I prefer
to keep pinctrls in board-level devicetree, which is easier to read.

Other Rockchip SoCs (like rk3588) seem to provide default pinctrls even
for those capable of multiple groups of pins, so I'm not sure whether
it's necessary to keep the style synchronized. Will add if the
maintainer considers it's better.

> Thanks,
> Chukun
> 
> -- 
> 2.25.1
> 

Thanks,
Yao Zi


From krzk at kernel.org  Mon Mar 10 00:23:03 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:23:03 +0100
Subject: [PATCH 03/10] dt-bindings: display/msm: dsi-phy-7nm: describe
 SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-3-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-3-1d4c30f43822@linaro.org>
Message-ID: <20250310-prompt-economic-gaur-ef0bbe@krzk-bin>

On Sat, Mar 08, 2025 at 03:42:21AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Describe MIPI DSI PHY present on Qualcomm SAR2130P platform.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 10 00:23:18 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:23:18 +0100
Subject: [PATCH 04/10] dt-bindings: display/msm: qcom,sc7280-dpu:
 describe SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-4-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-4-1d4c30f43822@linaro.org>
Message-ID: <20250310-eccentric-rare-rook-e4fb60@krzk-bin>

On Sat, Mar 08, 2025 at 03:42:22AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Describe DPU controller present on Qualcomm SAR2130P platform.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From vkoul at kernel.org  Mon Mar 10 00:26:50 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Mon, 10 Mar 2025 12:56:50 +0530
Subject: [PATCH] phy: rockchip: usbdp: Check these parameters only when
 the corresponding set flags are set
In-Reply-To: <20250306065952.485809-1-andyshrk@163.com>
References: <20250306065952.485809-1-andyshrk@163.com>
Message-ID: <Z86UOmPg/UDSBajZ@vaman>

On 06-03-25, 14:59, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> According documentation of phy_configure_opts_dp, at the configure
> stage, we should only verify/configure the link_rate when set_rate
> flag is set, the same applies to lanes and voltage.
> 
> So we do it as the documentation says, also record the link rate
> and lanes in phy internal for set_voltate stage.

Whenever you say also, that is a sign that it should be another patch!

> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
>  drivers/phy/rockchip/phy-rockchip-usbdp.c | 63 +++++++++++------------
>  1 file changed, 31 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index c04cf64f8a35..d1bbdf382aa2 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -187,6 +187,8 @@ struct rk_udphy {
>  	u32 dp_aux_din_sel;
>  	bool dp_sink_hpd_sel;
>  	bool dp_sink_hpd_cfg;
> +	unsigned int link_rate;
> +	unsigned int lanes;
>  	u8 bw;
>  	int id;
>  
> @@ -1102,42 +1104,39 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
>  	return 0;
>  }
>  
> -static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
> -{
> -	switch (link_rate) {
> -	case 1620:
> -	case 2700:
> -	case 5400:
> -	case 8100:
> -		break;
> -
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
>  					 struct phy_configure_opts_dp *dp)
>  {
> -	int i, ret;
> +	int i;
>  
> -	/* If changing link rate was required, verify it's supported. */
> -	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
> -	if (ret)
> -		return ret;
> +	/* Verify link rate. */
> +	if (dp->set_rate) {
> +		switch (dp->link_rate) {
> +		case 1620:
> +		case 2700:
> +		case 5400:
> +		case 8100:
> +			udphy->link_rate = dp->link_rate;
> +			break;
> +
> +		default:
> +			return -EINVAL;
> +		}

why drop helper? Why not set the rate on success?

> +	}
>  
>  	/* Verify lane count. */
> -	switch (dp->lanes) {
> -	case 1:
> -	case 2:
> -	case 4:
> -		/* valid lane count. */
> -		break;
> +	if (dp->set_lanes) {
> +		switch (dp->lanes) {
> +		case 1:
> +		case 2:
> +		case 4:
> +			/* valid lane count. */
> +			udphy->lanes = dp->lanes;
> +			break;
>  
> -	default:
> -		return -EINVAL;
> +		default:
> +			return -EINVAL;
> +		}

another change where helper would have made this look better

>  	}
>  
>  	/*
> @@ -1146,7 +1145,7 @@ static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
>  	 */
>  	if (dp->set_voltages) {
>  		/* Lane count verified previously. */
> -		for (i = 0; i < dp->lanes; i++) {
> +		for (i = 0; i < udphy->lanes; i++) {
>  			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
>  				return -EINVAL;
>  
> @@ -1243,9 +1242,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
>  	}
>  
>  	if (dp->set_voltages) {
> -		for (i = 0; i < dp->lanes; i++) {
> +		for (i = 0; i < udphy->lanes; i++) {
>  			lane = udphy->dp_lane_sel[i];
> -			switch (dp->link_rate) {
> +			switch (udphy->link_rate) {
>  			case 1620:
>  			case 2700:
>  				regmap_update_bits(udphy->pma_regmap,
> -- 
> 2.34.1

-- 
~Vinod


From lkp at intel.com  Mon Mar 10 00:26:49 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 10 Mar 2025 15:26:49 +0800
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
References: <20250304104434.481429-4-kevin_chen@aspeedtech.com>
Message-ID: <202503101519.AIZNCLz1-lkp@intel.com>

Hi Kevin,

kernel test robot noticed the following build errors:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on char-misc/char-misc-next char-misc/char-misc-linus robh/for-next linus/master v6.14-rc6 next-20250307]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kevin-Chen/ARM-dts-aspeed-g6-Add-AST2600-LPC-PCC-support/20250304-194530
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250304104434.481429-4-kevin_chen%40aspeedtech.com
patch subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
config: s390-randconfig-r112-20250310 (https://download.01.org/0day-ci/archive/20250310/202503101519.AIZNCLz1-lkp at intel.com/config)
compiler: s390-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250310/202503101519.AIZNCLz1-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503101519.AIZNCLz1-lkp at intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/io.h:14,
                    from include/linux/of_address.h:7,
                    from drivers/mfd/syscon.c:18:
   drivers/mfd/syscon.c: In function 'of_syscon_register':
>> arch/s390/include/asm/io.h:31:17: error: implicit declaration of function 'iounmap' [-Wimplicit-function-declaration]
      31 | #define iounmap iounmap
         |                 ^~~~~~~
   drivers/mfd/syscon.c:157:9: note: in expansion of macro 'iounmap'
     157 |         iounmap(base);
         |         ^~~~~~~

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for MFD_SYSCON
   Depends on [n]: HAS_IOMEM [=n]
   Selected by [y]:
   - ASPEED_LPC_PCC [=y]


vim +/iounmap +31 arch/s390/include/asm/io.h

cd24834130ac65 Jan Glauber 2012-11-29  26  
b43b3fff042d08 Baoquan He  2023-07-06  27  /*
b43b3fff042d08 Baoquan He  2023-07-06  28   * I/O memory mapping functions.
b43b3fff042d08 Baoquan He  2023-07-06  29   */
b43b3fff042d08 Baoquan He  2023-07-06  30  #define ioremap_prot ioremap_prot
b43b3fff042d08 Baoquan He  2023-07-06 @31  #define iounmap iounmap
b43b3fff042d08 Baoquan He  2023-07-06  32  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From krzk at kernel.org  Mon Mar 10 00:22:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:22:13 +0100
Subject: [PATCH 01/10] dt-bindings: display/msm: dp-controller: describe
 SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-1-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-1-1d4c30f43822@linaro.org>
Message-ID: <20250310-adamant-wildcat-of-order-8efdda@krzk-bin>

On Sat, Mar 08, 2025 at 03:42:19AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Describe DisplayPort controller present on Qualcomm SAR2130P platform.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> ---
>  Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From victor.liu at nxp.com  Mon Mar 10 00:34:46 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Mon, 10 Mar 2025 15:34:46 +0800
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250307122217.158b24d6@booty>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
 <71c44221-b18b-4928-8faf-00893ec4a109@nxp.com>
 <20250307122217.158b24d6@booty>
Message-ID: <b9e44f72-7407-4194-8054-91b7ed87d79b@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> Hello Liu,
> 
> On Fri, 7 Mar 2025 14:42:12 +0800
> Liu Ying <victor.liu at nxp.com> wrote:
> 
>> On 03/07/2025, Luca Ceresoli wrote:
>>> 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
>>> ret;'. So return 0 for clarity.
>>>
>>> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
>>> ---
>>>  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
>>> index 7bce2305d676714cdec7ce085cb53b25ce42f8e7..bee1c6002d5f84dc33b6d5dc123726703baa427e 100644
>>> --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
>>> +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
>>> @@ -665,7 +665,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
>>>  
>>>  	ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs);
>>>  
>>> -	return ret;
>>> +	return 0;  
>>
>> I guess this is not the only place across the kernel tree where this cleanup
>> could be done.  So, maybe use some tools to cleanup them all?
> 
> I had stumbled upon this as I was doing some changes to this function,
> and needed to understand the code flow. Definitely 'ret 0' would have
> made it  immediately clear that all the code between the last 'if (ret)
> return ret;' and the final 'return ret' is not allowed to fail.
> 
> I think this change would (slightly, but still) improve future readers'
> life.

Reviewed-by: Liu Ying <victor.liu at nxp.com>

> 
> Luca
>


From krzk at kernel.org  Mon Mar 10 00:40:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:40:24 +0100
Subject: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org>
Message-ID: <20250310-impressive-cherry-bullfrog-cbd8fd@krzk-bin>

On Sat, Mar 08, 2025 at 03:42:23AM +0200, Dmitry Baryshkov wrote:
> +patternProperties:
> +  "^display-controller@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: true
> +

Drop blank line

> +    properties:
> +      compatible:
> +        const: qcom,sar2130p-dpu
> +
> +  "^displayport-controller@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: true
> +

Drop blank line

> +    properties:
> +      compatible:
> +        items:
> +          - const: qcom,sar2130p-dp
> +          - const: qcom,sm8350-dp
> +
> +  "^dsi@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: true
> +

Drop blank line

> +    properties:
> +      compatible:
> +        items:
> +          - const: qcom,sar2130p-dsi-ctrl
> +          - const: qcom,mdss-dsi-ctrl

Drop last compatible here and use contains (see v3 of my sm8750)

> +
> +  "^phy@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: true
> +

Drop blank line

> +    properties:
> +      compatible:
> +        const: qcom,sar2130p-dsi-phy-5nm
> +
> +required:
> +  - compatible

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From mazziesaccount at gmail.com  Mon Mar 10 00:41:00 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 10 Mar 2025 09:41:00 +0200
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <20250308162928.72bd1d1b@jic23-huawei>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
 <e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
 <CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
 <54a031d0-df47-4baa-a23a-1a79c0922542@gmail.com>
 <20250308162928.72bd1d1b@jic23-huawei>
Message-ID: <4d5212b3-3801-408c-9a5d-c6111189793c@gmail.com>

On 08/03/2025 18:29, Jonathan Cameron wrote:
> On Wed, 5 Mar 2025 12:54:33 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> Thanks for the review David.
>>
>> On 04/03/2025 11:25, David Lechner wrote:
>>> On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
>>> <mazziesaccount at gmail.com> wrote:
>>>>
>>>> There are ADC ICs which may have some of the AIN pins usable for other
>>>> functions. These ICs may have some of the AIN pins wired so that they
>>>> should not be used for ADC.
>>>>
>>>> (Preferred?) way for marking pins which can be used as ADC inputs is to
>>>> add corresponding channels at N nodes in the device tree as described in
>>>> the ADC binding yaml.
>>>>
>>>> Add couple of helper functions which can be used to retrieve the channel
>>>> information from the device node.
>>>>
>>>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
>>>>
>>>> ---
>>
>>>> + *
>>>> + * Return:     Number of found channels on succes. Negative value to indicate
>>>
>>> s/succes/success/
>>
>> Thanks!
>>
>>>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
>>>> +                                         const struct iio_chan_spec *template,
>>>> +                                         int max_chan_id,
>>>> +                                         struct iio_chan_spec **cs)
>>>> +{
>>>> +       struct iio_chan_spec *chan_array, *chan;
>>>> +       int num_chan = 0, ret;
>>>> +
>>>> +       num_chan = iio_adc_device_num_channels(dev);
>>>> +       if (num_chan < 1)
>>>> +               return num_chan;
>>>> +
>>>> +       chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
>>>> +                                 GFP_KERNEL);
>>>> +       if (!chan_array)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       chan = &chan_array[0];
>>>> +
>>>> +       device_for_each_child_node_scoped(dev, child) {
>>>> +               u32 ch;
>>>> +
>>>> +               if (!fwnode_name_eq(child, "channel"))
>>>> +                       continue;
>>>> +
>>>> +               ret = fwnode_property_read_u32(child, "reg", &ch);
>>>> +               if (ret)
>>>> +                       return ret;
>>>> +
>>>> +               if (max_chan_id != -1 && ch > max_chan_id)
>>>> +                       return -ERANGE;
>>>> +
>>>
>>> Should we use return dev_err_probe() on these to help with debugging a bad dtb?
>>>    
>>
>> I am not fan of using dev_err_probe() in a 'library code'. This is
>> because we never know if there'll be some odd use-case where this is not
>> called from the probe.
>>
>> All in all, I'd leave adding most of the debugs to the callers -
>> especially because we do not expect to have bad device-trees after the
>> initial 'development stage' of a board. The board 'development stage'
>> should really reveal bugs which prevent the channels from being
>> registered - and after the DT is correct, these debug prints become
>> unnecessary (albeit minor) binary bloat.
>>
>>>> +               *chan = *template;
>>>> +               chan->channel = ch;
>>>> +               chan++;
>>>> +       }
>>>> +
>>>> +       *cs = chan_array;
>>>> +
>>>> +       return num_chan;
>>>> +}
>>>> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
>>>
>>> We can make this less verbose by setting #define
>>> DEFAULT_SYMBOL_NAMESPACE at the start of the file. Then we can just do
>>> EXPORT_SYMBOL_GPL() throughout the rest of the file.
>>
>> I am not sure what to think of this. I use the good old 'ctrl + ]' in my
>> editor when I need to check how a function was supposed to be used. That
>> jumps to the spot of code where the function is. I'd like to see the
>> namespace mentioned there in order to not accidentally miss the fact the
>> function belongs to one.
>>
>> OTOH, I do like simplifications. Yet, the added simplification might not
>> warrant the namespace not being visible in the function definition.
>>
>>> Also, I would prefer if the namespace matched config name (IIO_ADC_HELPER).
>>
>> I had some lengthy discussion about this with Andy and Jonathan during
>> earlier review versions. In short, I don't like the idea of very
>> fragmented namespaces in IIO, which will just complicate the drivers
>> without providing any obvious benefit.
>>
>> https://lore.kernel.org/all/20250222174842.57c091c5 at jic23-huawei/
>>
>>>> +
>>>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
>>>> +                                         const struct iio_chan_spec *template,
>>>> +                                         int max_chan_id,
>>>> +                                         struct iio_chan_spec **cs);
>>>> +
>>>
>>> There are some different opinions on this, but on the last patch I did
>>> introducing a new namespace, the consensus seems to be that putting
>>> the MODULE_IMPORT_NS() in the header file was convenient so that users
>>> of the API don't have to remember to both include the header and add
>>> the import macro.
>>>    
>>
>> I do like this suggestion, and I believe this would be the balance
>> between getting the benefit of hiding part of the symbols - while not
>> unnecessarily complicating the callers. I know some people are opposing
>> it though. My personal opinion is that having the MODULE_IMPORT_NS() in
>> a header would be neatly simplifying the calling code with very little
>> harm, especially here where including the header hardly has use-cases
>> outside the IIO ADC.
>>
>> Unfortunately, the "safety" seems to often be a synonym for just "making
>> it intentionally hard". As Finnish people say: "K?rsi, k?rsi,
>> kirkkaamman kruunun saat". :)
>> (Roughly translated as "Suffer, suffer, you will get a brighter crown").
>>
>> Let's hear what Jonathan thinks of your suggestion.
> 
> For this particular case my intent was that all the IIO exports that
> are suitable for use in simple IIO drives will be in this namespace,
> we just haven't started that conversion yet.
> 
> As such, having it defined from a header for this helper isn't a good
> thing to do.

Hmm. I agree.

>  Generally I prefer to see in driver code what namespaces
> are involved but do understand the other viewpoint. In this case I
> definitely don't think it is appropriate unless we go for a specific namespace
> for just this helper.

I suppose having the MODULE_IMPORT_NS() in the header would actually 
make the more fine-grained namespaces (like IIO_ADC_HELPERS, IIO_GTS, 
...) much more usable. That'd relieved the drivers from explicitly 
listing multiple namespaces while nicely limiting the visibility.

If IIO was my territory, I might want to ask people to go with that 
approach - but I am quite happy being a freeloade.. errm, I mean, 
bystander ;)

Thanks!

Yours,
	-- Matti


From krzk at kernel.org  Mon Mar 10 00:54:14 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 08:54:14 +0100
Subject: [PATCH 03/13] dt-bindings: soc: airoha: add SCU SSR Serdes port
 binding
In-Reply-To: <20250309132959.19045-4-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-4-ansuelsmth@gmail.com>
Message-ID: <20250310-ultraviolet-earthworm-of-honor-df114b@krzk-bin>

On Sun, Mar 09, 2025 at 02:29:34PM +0100, Christian Marangi wrote:
> Add Airoha AN7581 SCU SSR Serdes port binding to define what mode is
> supported by each Serdes port. These special binding are needed to
> identify and provide the port mode from any user driver.
> 
> These modes are mutually exclusive and driver needs to correctly
> validate the current mode for the Serdes port in use.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  MAINTAINERS                              |  6 ++++++
>  include/dt-bindings/soc/airoha,scu-ssr.h | 24 ++++++++++++++++++++++++

This should be squashed with the binding for the device.

Best regards,
Krzysztof



From richard.weiyang at gmail.com  Mon Mar 10 00:56:27 2025
From: richard.weiyang at gmail.com (Wei Yang)
Date: Mon, 10 Mar 2025 07:56:27 +0000
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250226020915.ytxusrrl7rv4g64l@master>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250224013131.fzz552bn7fs64umq@master>
 <Z711VP45tjBi0kwx@kernel.org>
 <20250226020915.ytxusrrl7rv4g64l@master>
Message-ID: <20250310075627.5hettrn2j2ien5bj@master>

On Wed, Feb 26, 2025 at 02:09:15AM +0000, Wei Yang wrote:
>On Tue, Feb 25, 2025 at 09:46:28AM +0200, Mike Rapoport wrote:
>>On Mon, Feb 24, 2025 at 01:31:31AM +0000, Wei Yang wrote:
>>> On Wed, Feb 19, 2025 at 09:24:31AM +0200, Mike Rapoport wrote:
>>> >Hi,
>>> >
>>> >On Tue, Feb 18, 2025 at 03:50:04PM +0000, Wei Yang wrote:
>>> >> On Thu, Feb 06, 2025 at 03:27:42PM +0200, Mike Rapoport wrote:
>>> >> >From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
>>> >> >
>>> >> >to denote areas that were reserved for kernel use either directly with
>>> >> >memblock_reserve_kern() or via memblock allocations.
>>> >> >
>>> >> >Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
>>> >> >---
>>> >> > include/linux/memblock.h | 16 +++++++++++++++-
>>> >> > mm/memblock.c            | 32 ++++++++++++++++++++++++--------
>>> >> > 2 files changed, 39 insertions(+), 9 deletions(-)
>>> >> >
>>> >> >diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>>> >> >index e79eb6ac516f..65e274550f5d 100644
>>> >> >--- a/include/linux/memblock.h
>>> >> >+++ b/include/linux/memblock.h
>>> >> >@@ -50,6 +50,7 @@ enum memblock_flags {
>>> >> > 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>>> >> > 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
>>> >> > 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
>>> >> >+	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
>>> >> 
>>> >> Above memblock_flags, there are comments on explaining those flags.
>>> >> 
>>> >> Seems we miss it for MEMBLOCK_RSRV_KERN.
>>> >
>>> >Right, thanks!
>>> > 
>>> >> > 
>>> >> > #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
>>> >> >@@ -1459,14 +1460,14 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
>>> >> > again:
>>> >> > 	found = memblock_find_in_range_node(size, align, start, end, nid,
>>> >> > 					    flags);
>>> >> >-	if (found && !memblock_reserve(found, size))
>>> >> >+	if (found && !__memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN))
>>> >> 
>>> >> Maybe we could use memblock_reserve_kern() directly. If my understanding is
>>> >> correct, the reserved region's nid is not used.
>>> >
>>> >We use nid of reserved regions in reserve_bootmem_region() (commit
>>> >61167ad5fecd ("mm: pass nid to reserve_bootmem_region()")) but KHO needs to
>>> >know the distribution of reserved memory among the nodes before
>>> >memmap_init_reserved_pages().
>>> > 
>>> >> BTW, one question here. How we handle concurrent memblock allocation? If two
>>> >> threads find the same available range and do the reservation, it seems to be a
>>> >> problem to me. Or I missed something?
>>> >
>>> >memblock allocations end before smp_init(), there is no possible concurrency.
>>> > 
>>> 
>>> Thanks, I still have one question here.
>>> 
>>> Below is a simplified call flow.
>>> 
>>>     mm_core_init()
>>>         mem_init()
>>>             memblock_free_all()
>>>                 free_low_memory_core_early()
>>>                     memmap_init_reserved_pages()
>>>                         memblock_set_node(..., memblock.reserved, )   --- (1)
>>>                     __free_memory_core()
>>>         kmem_cache_init()
>>>             slab_state = UP;                                          --- (2)
>>> 
>>> And memblock_allloc_range_nid() is not supposed to be called after
>>> slab_is_available(). Even someone do dose it, it will get memory from slab
>>> instead of reserve region in memblock.
>>> 
>>> From the above call flow and background, there are three cases when
>>> memblock_alloc_range_nid() would be called:
>>> 
>>>   * If it is called before (1), memblock.reserved's nid would be adjusted correctly.
>>>   * If it is called after (2), we don't touch memblock.reserved.
>>>   * If it happens between (1) and (2), it looks would break the consistency of
>>>     nid information in memblock.reserved. Because when we use
>>>     memblock_reserve_kern(), NUMA_NO_NODE would be stored in region.
>>> 
>>> So my question is if the third case happens, would it introduce a bug? If it
>>> won't happen, seems we don't need to specify the nid here?
>>
>>We don't really care about proper assignment of nodes between (1) and (2)
>>from one side and the third case does not happen on the other side. Nothing
>>should call membloc_alloc() after memblock_free_all(). 
>>
>
>My point is if no one would call memblock_alloc() after memblock_free_all(),
>which set nid in memblock.reserved properly, it seems not necessary to do
>__memblock_reserve() with exact nid during memblock_alloc()? 
>
>As you did __memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN) in this
>patch.
>

Hi, Mike

Do you think my understanding is reasonable?

-- 
Wei Yang
Help you, Help me


From fj6611ie at fujitsu.com  Mon Mar 10 00:56:58 2025
From: fj6611ie at fujitsu.com (Toshiyuki Sato (Fujitsu))
Date: Mon, 10 Mar 2025 07:56:58 +0000
Subject: [PATCH v3] serial: amba-pl011: Implement nbcon console
In-Reply-To: <2025031001-outwit-outsider-b34e@gregkh>
References: <20250204044428.2191983-1-fj6611ie@aa.jp.fujitsu.com>
 <TY4PR01MB13777DB55F2231F7399E42609D7D62@TY4PR01MB13777.jpnprd01.prod.outlook.com>
 <2025031001-outwit-outsider-b34e@gregkh>
Message-ID: <TY4PR01MB1377756007BB974DB671F01FED7D62@TY4PR01MB13777.jpnprd01.prod.outlook.com>

Hi Greg, thanks for your comment.

> > Dear Reviewers,
> >
> > It has been about a month since this patch was merged into tty-next ->
> linux-next.
> > I would appreciate any comments or feedback on this patch.
> 
> What needs to be commented on?  It is accepted and will be merged in the next
> -rc merge cycle.
> 
> confused,
>
> greg k-h

I had thought that some kind of action such as "Reviewed-by" would be necessary.
I'm sorry for the confusion. Thanks for accepting this patch.

Regards,
Toshiyuki Sato



From krzk at kernel.org  Mon Mar 10 01:00:40 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:00:40 +0100
Subject: [PATCH 04/13] dt-bindings: soc: airoha: add Documentation for
 Airoha AN7581 SCU SSR
In-Reply-To: <20250309132959.19045-5-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-5-ansuelsmth@gmail.com>
Message-ID: <20250310-aromatic-chihuahua-of-priority-4ee73b@krzk-bin>

On Sun, Mar 09, 2025 at 02:29:35PM +0100, Christian Marangi wrote:
> The Airoha AN7581 SoC have in the SCU register space particular
> address that control how some peripheral are configured.
> 
> These are toggeled in the System Status Register and are used to
> toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).
> 
> Modes are mutually exclusive and selecting one mode cause the
> other feature to not work (example a mode in USB 3.0 cause PCIe
> port 2 to not work) This depends also on what is physically
> connected to the Hardware and needs to correctly reflect the
> System Status Register bits.
> 
> Special care is needed for PCIe port 0 in 2 line mode that
> requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> mode.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../soc/airoha/airoha,an7581-scu-ssr.yaml     | 106 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 107 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> 
> diff --git a/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> new file mode 100644
> index 000000000000..4bbf6e3b79a4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/airoha/airoha,an7581-scu-ssr.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7581 SCU System Status Register
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  The Airoha AN7581 SoC have in the SCU register space particular
> +  address that control how some peripheral are configured.
> +
> +  These are toggeled in the System Status Register and are used to
> +  toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> +  or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).

typo, Ethernet

> +
> +  Modes are mutually exclusive and selecting one mode cause the
> +  other feature to not work (example a mode in USB 3.0 cause PCIe
> +  port 2 to not work) This depends also on what is physically
> +  connected to the Hardware and needs to correctly reflect the
> +  System Status Register bits.
> +
> +  Special care is needed for PCIe port 0 in 2 line mode that
> +  requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> +  mode.
> +
> +properties:
> +  compatible:
> +    const: airoha,an7581-scu-ssr

That's not a separate device, but part of the SCU.

But more important - such definition of choice of serial engines is
really not flexible, not reabable and not helping integrating into DTS.
Are you going to grow this for next chip airoha,serdes-wifi20, then
airoha,serdes-wifi21, 22... ? And then how the if:then: would look like?

Assuming you do not have here child-parent relationship, like usually
for serial engines, so then this should be somehow list of devices
(strings) you want to run.

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 10 01:01:38 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:01:38 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <20250309132959.19045-6-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
Message-ID: <20250310-excellent-quokka-of-abracadabra-15ad69@krzk-bin>

On Sun, Mar 09, 2025 at 02:29:36PM +0100, Christian Marangi wrote:
> +
> +examples:
> +  - |
> +    #include <dt-bindings/soc/airoha,scu-ssr.h>
> +
> +    system-controller at 1fb00000 {
> +        compatible = "airoha,en7581-scu-sysctl", "syscon", "simple-mfd";
> +        reg = <0x1fb00000 0x970>;
> +
> +        clock-controller {
> +            compatible = "airoha,en7581-scu";
> +

No resources here, so this is part of the parent.

> +            #clock-cells = <1>;
> +            #reset-cells = <1>;
> +        };
> +
> +        system-controller {
> +            compatible = "airoha,an7581-scu-ssr";

No, this was told many times - you do not have resources here, so no
chhild.

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 10 01:06:04 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:06:04 +0100
Subject: [PATCH 06/13] dt-bindings: clock: airoha: make reg optional for
 Airoha EN7581
In-Reply-To: <20250309132959.19045-7-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-7-ansuelsmth@gmail.com>
Message-ID: <20250310-pompous-elk-of-serendipity-cfebc9@krzk-bin>

On Sun, Mar 09, 2025 at 02:29:37PM +0100, Christian Marangi wrote:
> The Airoha EN7581 clock-controller registers are placed in the SCU

I don't understand. The registers moved?

> (System Controller Unit). Now that additional pheriperals are supported
> for the SCU, a dedicated SCU node is created and the clock-controller is
> moved as a child of such node hence the register property is taken from
> the parent node.
> 
> To support this, make the reg property optional and provide an
> additional example for this case.

No, post complete binding instead of adding some sort of stubs and then
later totally reworking them to match different Linux drivers.

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 10 01:06:50 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:06:50 +0100
Subject: [PATCH 12/13] arm64: dts: airoha: en7581: convert SCU clock node
 to MFD implementation
In-Reply-To: <20250309132959.19045-13-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-13-ansuelsmth@gmail.com>
Message-ID: <20250310-independent-melodic-hedgehog-d3010a@krzk-bin>

On Sun, Mar 09, 2025 at 02:29:43PM +0100, Christian Marangi wrote:
> Convert SCU clock node for Airoha EN7581 to MFD implementation in
> preparation for USB support.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  arch/arm64/boot/dts/airoha/en7581.dtsi | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/airoha/en7581.dtsi b/arch/arm64/boot/dts/airoha/en7581.dtsi
> index 26b136940917..dfc12fa99748 100644
> --- a/arch/arm64/boot/dts/airoha/en7581.dtsi
> +++ b/arch/arm64/boot/dts/airoha/en7581.dtsi
> @@ -173,11 +173,16 @@ spi_nand: nand at 0 {
>  			};
>  		};
>  
> -		scuclk: clock-controller at 1fb00000 {
> -			compatible = "airoha,en7581-scu";
> +		system-controller at 1fb00000 {
> +			compatible = "airoha,en7581-scu-sysctl", "syscon", "simple-mfd";
>  			reg = <0x0 0x1fb00000 0x0 0x970>;

Hardware did not change and you do not explain why any conversion
affecting users is justified.

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 10 01:09:22 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:09:22 +0100
Subject: [PATCH v2 2/3] ASoC: dt-bindings: meson: t9015: add support for
 A1 SoC family
In-Reply-To: <20250309181630.1322745-3-jan.dakinevich@salutedevices.com>
References: <20250309181630.1322745-1-jan.dakinevich@salutedevices.com>
 <20250309181630.1322745-3-jan.dakinevich@salutedevices.com>
Message-ID: <20250310-smiling-gerbil-of-whirlwind-8fa4a5@krzk-bin>

On Sun, Mar 09, 2025 at 09:16:29PM +0300, Jan Dakinevich wrote:
> Add support for internal audio codec found A1 SoC family. On this SoC
> the component supports capturing from ADC and has specific configuration
> of input/output lines.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../bindings/sound/amlogic,t9015.yaml         | 69 +++++++++++++++++--
>  1 file changed, 65 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
> index 5f5cccdbeb34..962795470601 100644
> --- a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
> +++ b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
> @@ -9,9 +9,6 @@ title: Amlogic T9015 Internal Audio DAC
>  maintainers:
>    - Jerome Brunet <jbrunet at baylibre.com>
>  
> -allOf:
> -  - $ref: dai-common.yaml#
> -
>  properties:
>    $nodename:
>      pattern: "^audio-controller at .*"
> @@ -21,7 +18,9 @@ properties:
>  
>    compatible:
>      items:
> -      - const: amlogic,t9015
> +      - enum:
> +          - amlogic,t9015
> +          - amlogic,t9015-a1
>  
>    clocks:
>      items:
> @@ -43,6 +42,17 @@ properties:
>  
>    sound-name-prefix: true
>  
> +  lineout-left:

Missing vendor prefix.

> +    $ref: /schemas/types.yaml#/definitions/string

enum with values

> +  lineout-right:
> +    $ref: /schemas/types.yaml#/definitions/string
> +  linein-left:
> +    $ref: /schemas/types.yaml#/definitions/string
> +  linein-right:
> +    $ref: /schemas/types.yaml#/definitions/string
> +  micbias:

use proper unit suffix name, e.g. microvolt

> +    $ref: /schemas/types.yaml#/definitions/string
> +
>  required:
>    - "#sound-dai-cells"
>    - compatible
> @@ -52,6 +62,57 @@ required:
>    - resets
>    - AVDD-supply
>  
> +

Only one blank line

> +allOf:
> +  - $ref: dai-common.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: amlogic,t9015-a1
> +    then:
> +      properties:
> +        lineout-left:
> +          items:

You do not have multiple items here, drop.

> +            - enum:
> +                - none
> +                - right
> +                - left-inverted
> +        lineout-right:
> +          items:
> +            - enum:
> +                - none
> +                - left
> +                - right-inverted
> +        linein-left:
> +          items:
> +            - enum:
> +                - none
> +                - differential
> +                - positive
> +                - negative
> +        linein-right:
> +          items:
> +            - enum:
> +                - none
> +                - differential
> +                - positive
> +                - negative

All these go to the top level.

> +        micbias:
> +          items:
> +            - enum:
> +                - 2.0V
> +                - 2.1V
> +                - 2.3V
> +                - 2.5V
> +                - 2.8V
> +    else:
> +      lineout-left: false
> +      lineout-right: false
> +      linein-left: false
> +      linein-right: false
> +      micbias: false

This is correct.

Best regards,
Krzysztof



From andriy.shevchenko at linux.intel.com  Mon Mar 10 01:17:14 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 10 Mar 2025 10:17:14 +0200
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250308003425.7b89bfb6@booty>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
 <20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
 <Z8sqJhbqEBla_Ch7@smile.fi.intel.com>
 <20250308003425.7b89bfb6@booty>
Message-ID: <Z86gCjzuC5UFZBIL@smile.fi.intel.com>

On Sat, Mar 08, 2025 at 12:34:25AM +0100, Luca Ceresoli wrote:
> On Fri, 7 Mar 2025 19:17:26 +0200
> Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:
> > On Fri, Mar 07, 2025 at 12:19:08PM +0100, Luca Ceresoli wrote:
> > > %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> > > add %pC{,n,r} format specifiers for clocks") introducing them does not
> > > clarify any intended difference. It can be assumed %pC is a default for
> > > %pCn as some other specifiers do, but not all are consistent with this
> > > policy. Moreover there is now no other suffix other than 'n', which makes a
> > > default not really useful.
> > > 
> > > All users in the kernel were using %pC except for one which has been
> > > converted. So now remove %pCn and all the unnecessary extra code and
> > > documentation.  
> > 
> > You seem forgot to update translation(s) of the documentation.
> 
> I'm afraid I don't speak Chinese. :-)

At bare minimum we can drop the same line in the list.
Also in such a case we may ask a Chinese speaking person to review / correct /
suggest the changes. I would not leave a leftover as it will be forgotten so
easily and documentation becomes not in sync.

> For this specific change I think I could come up with an approximation
> of it, but the both the docs and git log suggest this is not expected.


-- 
With Best Regards,
Andy Shevchenko




From krzk at kernel.org  Mon Mar 10 01:20:55 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:20:55 +0100
Subject: [PATCH v5 03/13] dt-bindings: can: m_can: Add wakeup properties
In-Reply-To: <20250306-topic-am62-partialio-v6-12-b4-v5-3-f9323d3744a2@baylibre.com>
References: <20250306-topic-am62-partialio-v6-12-b4-v5-0-f9323d3744a2@baylibre.com>
 <20250306-topic-am62-partialio-v6-12-b4-v5-3-f9323d3744a2@baylibre.com>
Message-ID: <20250310-gifted-coati-of-sympathy-dabc5d@krzk-bin>

On Thu, Mar 06, 2025 at 12:14:41PM +0100, Markus Schneider-Pargmann wrote:
> +  pinctrl-names:
> +    description:
> +      When present should contain at least "default" describing the default pin
> +      states. The second state called "wakeup" describes the pins in their
> +      wakeup configuration required to exit sleep states.
> +    minItems: 1
> +    items:
> +      - const: default
> +      - const: wakeup
> +
>    power-domains:
>      description:
>        Power domain provider node and an args specifier containing
> @@ -122,6 +138,8 @@ properties:
>      minItems: 1
>      maxItems: 2
>  
> +  wakeup-source: true

If this patchset depends on dtschema pull, then this should be narrowed
to specific type, I think. Otherwise how exactly your drivers are going
to work if this is just "wakeup-source;"?

Best regards,
Krzysztof



From joro at 8bytes.org  Mon Mar 10 01:26:39 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 10 Mar 2025 09:26:39 +0100
Subject: [PATCH] iommu: Unexport iommu_fwspec_free()
In-Reply-To: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
References: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
Message-ID: <Z86iP6_qe5HwndM7@8bytes.org>

On Thu, Feb 27, 2025 at 02:47:47PM +0000, Robin Murphy wrote:
> The drivers doing their own fwspec parsing have no need to call
> iommu_fwspec_free() since fwspecs were moved into dev_iommu, as
> returning an error from .probe_device will tear down the whole lot
> anyway. Move it into the private interface now that it only serves
> for of_iommu to clean up in an error case.
> 
> I have no idea what mtk_v1 was doing in effectively guaranteeing
> a NULL fwspec would be dereferenced if no "iommus" DT property was
> found, so add a check for that to at least make the code look sane.
> 
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu.c |  1 -
>  drivers/iommu/iommu-priv.h            |  2 ++
>  drivers/iommu/iommu.c                 |  1 -
>  drivers/iommu/mtk_iommu_v1.c          | 14 ++++----------
>  drivers/iommu/tegra-smmu.c            |  1 -
>  include/linux/iommu.h                 |  5 -----
>  6 files changed, 6 insertions(+), 18 deletions(-)

Applied, thanks.


From nichen at iscas.ac.cn  Mon Mar 10 01:26:28 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Mon, 10 Mar 2025 16:26:28 +0800
Subject: [PATCH] mailbox: Remove unneeded semicolon
Message-ID: <20250310082628.845544-1-nichen@iscas.ac.cn>

Remove unnecessary semicolons reported by Coccinelle/coccicheck and the
semantic patch at scripts/coccinelle/misc/semicolon.cocci.

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
 drivers/mailbox/exynos-mailbox.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mailbox/exynos-mailbox.c b/drivers/mailbox/exynos-mailbox.c
index 20049f0ec5ff..2320649bf60c 100644
--- a/drivers/mailbox/exynos-mailbox.c
+++ b/drivers/mailbox/exynos-mailbox.c
@@ -57,7 +57,7 @@ static int exynos_mbox_send_data(struct mbox_chan *chan, void *data)
 	if (msg->chan_type != EXYNOS_MBOX_CHAN_TYPE_DOORBELL) {
 		dev_err(dev, "Unsupported channel type [%d]\n", msg->chan_type);
 		return -EINVAL;
-	};
+	}
 
 	writel(BIT(msg->chan_id), exynos_mbox->regs + EXYNOS_MBOX_INTGR1);
 
-- 
2.25.1



From rppt at kernel.org  Mon Mar 10 01:28:02 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Mon, 10 Mar 2025 10:28:02 +0200
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250310075627.5hettrn2j2ien5bj@master>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250224013131.fzz552bn7fs64umq@master>
 <Z711VP45tjBi0kwx@kernel.org>
 <20250226020915.ytxusrrl7rv4g64l@master>
 <20250310075627.5hettrn2j2ien5bj@master>
Message-ID: <Z86ikkLVHQhLmBWj@kernel.org>

Hi Wei,

On Mon, Mar 10, 2025 at 07:56:27AM +0000, Wei Yang wrote:
> On Wed, Feb 26, 2025 at 02:09:15AM +0000, Wei Yang wrote:
> >>> 
> >>> From the above call flow and background, there are three cases when
> >>> memblock_alloc_range_nid() would be called:
> >>> 
> >>>   * If it is called before (1), memblock.reserved's nid would be adjusted correctly.
> >>>   * If it is called after (2), we don't touch memblock.reserved.
> >>>   * If it happens between (1) and (2), it looks would break the consistency of
> >>>     nid information in memblock.reserved. Because when we use
> >>>     memblock_reserve_kern(), NUMA_NO_NODE would be stored in region.
> >>> 
> >>> So my question is if the third case happens, would it introduce a bug? If it
> >>> won't happen, seems we don't need to specify the nid here?
> >>
> >>We don't really care about proper assignment of nodes between (1) and (2)
> >>from one side and the third case does not happen on the other side. Nothing
> >>should call membloc_alloc() after memblock_free_all(). 
> >>
> >
> >My point is if no one would call memblock_alloc() after memblock_free_all(),
> >which set nid in memblock.reserved properly, it seems not necessary to do
> >__memblock_reserve() with exact nid during memblock_alloc()? 
> >
> >As you did __memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN) in this
> >patch.
> >
> 
> Hi, Mike
> 
> Do you think my understanding is reasonable?

Without KHO it is indeed not strictly necessary to set nid during memblock_alloc().
But since we anyway have nid parameter in memblock_alloc_range_nid() and it
anyway propagates to memblock_add_range(), I think it's easier and cleaner
to pass nid to __memblock_reserve() there.

And for KHO estimation of scratch size it is important to have nid assigned to
the reserved areas before memblock_free_all(), at least for the allocations
that request particular nid explicitly.
 
> -- 
> Wei Yang
> Help you, Help me

-- 
Sincerely yours,
Mike.


From joro at 8bytes.org  Mon Mar 10 01:29:12 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 10 Mar 2025 09:29:12 +0100
Subject: [PATCH v2 0/4] iommu: Fix the longstanding probe issues
In-Reply-To: <cover.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
Message-ID: <Z86i2BHhmAINErv_@8bytes.org>

On Fri, Feb 28, 2025 at 03:46:29PM +0000, Robin Murphy wrote:
> This spin irons out a couple of issues which v1 had. Firstly there
> should now be no change in behaviour for the weird of_dma_configure()
> calls, other than possibly getting the warning if they deserve it.
> Secondly I think there was still a possibility for probe to run via
> the replay path while its "real" probe was waiting to reacquire the
> lock; this is now solved by making dev->iommu a reliable indicator of
> the probe lifecycle, with a couple more prep patches.
> 
> Thanks,
> Robin.
> 
> 
> Robin Murphy (4):
>   iommu: Handle race with default domain setup
>   iommu: Resolve ops in iommu_init_device()
>   iommu: Keep dev->iommu state consistent
>   iommu: Get DT/ACPI parsing into the proper probe path
> 
>  drivers/acpi/arm64/dma.c        |  5 +++
>  drivers/acpi/scan.c             |  7 -----
>  drivers/amba/bus.c              |  3 +-
>  drivers/base/platform.c         |  3 +-
>  drivers/bus/fsl-mc/fsl-mc-bus.c |  3 +-
>  drivers/cdx/cdx.c               |  3 +-
>  drivers/iommu/iommu-priv.h      |  2 ++
>  drivers/iommu/iommu.c           | 55 ++++++++++++++++++++++++---------
>  drivers/iommu/of_iommu.c        | 13 ++++++--
>  drivers/of/device.c             |  7 ++++-
>  drivers/pci/pci-driver.c        |  3 +-
>  11 files changed, 74 insertions(+), 30 deletions(-)

Applied, thanks Robin.


From joro at 8bytes.org  Mon Mar 10 01:30:12 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 10 Mar 2025 09:30:12 +0100
Subject: [PATCH v3 0/2] iommu: apple-dart: Support the ISP DART
In-Reply-To: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
References: <20250307-isp-dart-v3-0-684fe4489591@gmail.com>
Message-ID: <Z86jFK0IS5aja6mC@8bytes.org>

On Fri, Mar 07, 2025 at 09:07:44PM +0100, Sasha Finkelstein via B4 Relay wrote:
> Hector Martin (2):
>       iommu: apple-dart: Increase MAX_DARTS_PER_DEVICE to 3
>       iommu: apple-dart: Allow mismatched bypass support
> 
>  drivers/iommu/apple-dart.c | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)

Applied, thanks.


From krzk at kernel.org  Mon Mar 10 01:30:15 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 09:30:15 +0100
Subject: [PATCH] mailbox: Remove unneeded semicolon
In-Reply-To: <20250310082628.845544-1-nichen@iscas.ac.cn>
References: <20250310082628.845544-1-nichen@iscas.ac.cn>
Message-ID: <e287383d-41a0-4127-bb24-857684fd406f@kernel.org>

On 10/03/2025 09:26, Chen Ni wrote:
> Remove unnecessary semicolons reported by Coccinelle/coccicheck and the
> semantic patch at scripts/coccinelle/misc/semicolon.cocci.
> 
> Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
> ---
>  drivers/mailbox/exynos-mailbox.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From csokas.bence at prolan.hu  Mon Mar 10 01:38:13 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Mon, 10 Mar 2025 09:38:13 +0100
Subject: [PATCH 2/2] counter: microchip-tcb-capture: Add support for RC
 Compare
In-Reply-To: <20250306-introduce-compare-component-v1-2-93993b3dca9c@kernel.org>
References: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
 <20250306-introduce-compare-component-v1-2-93993b3dca9c@kernel.org>
Message-ID: <790f00da-d66e-42bc-bae2-339144fbec95@prolan.hu>

Hi,

On 2025. 03. 06. 8:05, William Breathitt Gray wrote:
> In Capture mode, the RC register serves as a compare register for the
> Timer Counter Channel. When a the Counter Value reaches the RC value, a
> RC Compare event occurs (COUNTER_EVENT_THRESHOLD). This patch exposes
> the RC register to userspace as the 'compare' Count extension, thus
> allowing users to configure the threshold condition for these events.
> 
> Signed-off-by: William Breathitt Gray <wbg at kernel.org>

I'm assuming you'll merge it with my capture extensions patch. Will this 
`compare` extension be carried over to 104-quad-8 as well? Otherwise:

Acked-by: Bence Cs?k?s <csokas.bence at prolan.hu>

Bence



From mike.rudenko at gmail.com  Sun Mar  9 13:18:50 2025
From: mike.rudenko at gmail.com (Mikhail Rudenko)
Date: Sun, 09 Mar 2025 23:18:50 +0300
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in
 dma-contig
In-Reply-To: <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
 <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>
 <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca>
Message-ID: <87wmcxs1xw.fsf@gmail.com>


Hi Nicolas, Tomasz,

On 2025-03-03 at 10:24 -05, Nicolas Dufresne <nicolas at ndufresne.ca> wrote:

> Hi Mikhail,
>
> Le lundi 03 mars 2025 ? 14:40 +0300, Mikhail Rudenko a ?crit?:
>> When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
>> commit 129134e5415d ("media: media/v4l2: remove
>> V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
>> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
>> no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
>> introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
>> V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
>> no-ops, making cache maintenance for non-coherent dmabufs allocated
>> by
>> dma-contig impossible.
>>
>> Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
>> {flush,invalidate}_kernel_vmap_range calls to
>> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
>> buffers.
>>
>> Fixes: c0acf9cfeee0 ("media: videobuf2: handle
>> V4L2_MEMORY_FLAG_NON_COHERENT flag")
>> Cc: stable at vger.kernel.org
>> Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
>> ---
>> ?.../media/common/videobuf2/videobuf2-dma-contig.c? | 22
>> ++++++++++++++++++++++
>> ?1 file changed, 22 insertions(+)
>>
>> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> index
>> a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7
>> bc888a84a95d5 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
>> @@ -427,6 +427,17 @@ static int
>> ?vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
>> ?				?? enum dma_data_direction
>> direction)
>> ?{
>> +	struct vb2_dc_buf *buf = dbuf->priv;
>> +	struct sg_table *sgt = buf->dma_sgt;
>> +
>> +	if (!buf->non_coherent_mem)
>> +		return 0;
>> +
>> +	if (buf->vaddr)
>> +		invalidate_kernel_vmap_range(buf->vaddr, buf->size);
>
> What would make me a lot more confortable with this change is if you
> enable kernel mappings for one test. This will ensure you cover the
> call to "invalidate" in your testing. I'd like to know about the
> performance impact. With this implementation it should be identical to
> the VB2 one.
>

I have re-run my tests on RK3399, with 1280x720 XRGB capture buffers (1
plane, 3686400 bytes). Capture process was pinned to "big" cores running
at fixed frequency of 1.8 GHz. Libcamera was modified to request buffers
with V4L2_MEMORY_FLAG_NON_COHERENT flag. DMA_BUF_IOCTL_SYNC ioctls were
used as appropriate. For kernel mapping effect test, vb2_plane_vaddr
call was inserted into rkisp1_vb2_buf_init.

The timings are as following:

- memcpy coherent buffer: 7570 +/- 63 us
- memcpy non-coherent buffer: 1120 +/- 34 us

without kernel mapping:

- ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ}): 428 +/- 15 us
- ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ}): 422 +/- 28 us

with kernel mapping:

- ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ}): 526 +/- 13 us
- ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ}): 519 +/- 38 us

So, even with kernel mapping enabled, speedup is 7570 / (1120 + 526 + 519) = 3.5,
and the use of noncoherent buffers is justified -- at least on this platform.

--
Best regards,
Mikhail Rudenko


From sumit.garg at kernel.org  Mon Mar 10 01:56:26 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Mon, 10 Mar 2025 14:26:26 +0530
Subject: [PATCH v6 01/10] tee: tee_device_alloc(): copy dma_mask from
 parent device
In-Reply-To: <20250305130634.1850178-2-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-2-jens.wiklander@linaro.org>
Message-ID: <Z86pOi874jfJJSOv@sumit-X1>

On Wed, Mar 05, 2025 at 02:04:07PM +0100, Jens Wiklander wrote:
> If a parent device is supplied to tee_device_alloc(), copy the dma_mask
> field into the new device. This avoids future warnings when mapping a
> DMA-buf for the device.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/tee_core.c | 2 ++
>  1 file changed, 2 insertions(+)
>

Reviewed-by: Sumit Garg <sumit.garg at kernel.org>

-Sumit

> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index d113679b1e2d..685afcaa3ea1 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -922,6 +922,8 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
>  	teedev->dev.class = &tee_class;
>  	teedev->dev.release = tee_release_device;
>  	teedev->dev.parent = dev;
> +	if (dev)
> +		teedev->dev.dma_mask = dev->dma_mask;
>  
>  	teedev->dev.devt = MKDEV(MAJOR(tee_devt), teedev->id);
>  
> -- 
> 2.43.0
> 


From sumit.garg at kernel.org  Mon Mar 10 01:57:24 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Mon, 10 Mar 2025 14:27:24 +0530
Subject: [PATCH v6 02/10] optee: pass parent device to tee_device_alloc()
In-Reply-To: <20250305130634.1850178-3-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-3-jens.wiklander@linaro.org>
Message-ID: <Z86pdKQY440edHNx@sumit-X1>

On Wed, Mar 05, 2025 at 02:04:08PM +0100, Jens Wiklander wrote:
> During probing of the OP-TEE driver, pass the parent device to
> tee_device_alloc() so the dma_mask of the new devices can be updated
> accordingly.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/ffa_abi.c | 8 ++++----
>  drivers/tee/optee/smc_abi.c | 4 ++--
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 

Reviewed-by: Sumit Garg <sumit.garg at kernel.org>

-Sumit

> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index f3af5666bb11..4ca1d5161b82 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -914,16 +914,16 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
>  	    (sec_caps & OPTEE_FFA_SEC_CAP_RPMB_PROBE))
>  		optee->in_kernel_rpmb_routing = true;
>  
> -	teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
> -				  optee);
> +	teedev = tee_device_alloc(&optee_ffa_clnt_desc, &ffa_dev->dev,
> +				  optee->pool, optee);
>  	if (IS_ERR(teedev)) {
>  		rc = PTR_ERR(teedev);
>  		goto err_free_pool;
>  	}
>  	optee->teedev = teedev;
>  
> -	teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
> -				  optee);
> +	teedev = tee_device_alloc(&optee_ffa_supp_desc, &ffa_dev->dev,
> +				  optee->pool, optee);
>  	if (IS_ERR(teedev)) {
>  		rc = PTR_ERR(teedev);
>  		goto err_unreg_teedev;
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index f0c3ac1103bb..165fadd9abc9 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -1691,14 +1691,14 @@ static int optee_probe(struct platform_device *pdev)
>  	    (sec_caps & OPTEE_SMC_SEC_CAP_RPMB_PROBE))
>  		optee->in_kernel_rpmb_routing = true;
>  
> -	teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
> +	teedev = tee_device_alloc(&optee_clnt_desc, &pdev->dev, pool, optee);
>  	if (IS_ERR(teedev)) {
>  		rc = PTR_ERR(teedev);
>  		goto err_free_optee;
>  	}
>  	optee->teedev = teedev;
>  
> -	teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
> +	teedev = tee_device_alloc(&optee_supp_desc, &pdev->dev, pool, optee);
>  	if (IS_ERR(teedev)) {
>  		rc = PTR_ERR(teedev);
>  		goto err_unreg_teedev;
> -- 
> 2.43.0
> 


From tfiga at chromium.org  Mon Mar 10 02:00:03 2025
From: tfiga at chromium.org (Tomasz Figa)
Date: Mon, 10 Mar 2025 18:00:03 +0900
Subject: [PATCH v4 1/2] media: videobuf2: Fix dmabuf cache sync/flush in dma-contig
In-Reply-To: <87wmcxs1xw.fsf@gmail.com>
References: <20250303-b4-rkisp-noncoherent-v4-0-e32e843fb6ef@gmail.com>
 <20250303-b4-rkisp-noncoherent-v4-1-e32e843fb6ef@gmail.com>
 <8b3dac7baed1de9542452547454c53188c384391.camel@ndufresne.ca> <87wmcxs1xw.fsf@gmail.com>
Message-ID: <CAAFQd5A70T2iaN17X2Jfk_6fCKRYZdKpreb+9i76n5WMYNEt1A@mail.gmail.com>

On Mon, Mar 10, 2025 at 5:52?PM Mikhail Rudenko <mike.rudenko at gmail.com> wrote:
>
>
> Hi Nicolas, Tomasz,
>
> On 2025-03-03 at 10:24 -05, Nicolas Dufresne <nicolas at ndufresne.ca> wrote:
>
> > Hi Mikhail,
> >
> > Le lundi 03 mars 2025 ? 14:40 +0300, Mikhail Rudenko a ?crit :
> >> When support for V4L2_FLAG_MEMORY_NON_CONSISTENT was removed in
> >> commit 129134e5415d ("media: media/v4l2: remove
> >> V4L2_FLAG_MEMORY_NON_CONSISTENT flag"),
> >> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions were made
> >> no-ops. Later, when support for V4L2_MEMORY_FLAG_NON_COHERENT was
> >> introduced in commit c0acf9cfeee0 ("media: videobuf2: handle
> >> V4L2_MEMORY_FLAG_NON_COHERENT flag"), the above functions remained
> >> no-ops, making cache maintenance for non-coherent dmabufs allocated
> >> by
> >> dma-contig impossible.
> >>
> >> Fix this by reintroducing dma_sync_sgtable_for_{cpu,device} and
> >> {flush,invalidate}_kernel_vmap_range calls to
> >> vb2_dc_dmabuf_ops_{begin,end}_cpu_access() functions for non-coherent
> >> buffers.
> >>
> >> Fixes: c0acf9cfeee0 ("media: videobuf2: handle
> >> V4L2_MEMORY_FLAG_NON_COHERENT flag")
> >> Cc: stable at vger.kernel.org
> >> Signed-off-by: Mikhail Rudenko <mike.rudenko at gmail.com>
> >> ---
> >>  .../media/common/videobuf2/videobuf2-dma-contig.c  | 22
> >> ++++++++++++++++++++++
> >>  1 file changed, 22 insertions(+)
> >>
> >> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> >> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> >> index
> >> a13ec569c82f6da2d977222b94af32e74c6c6c82..d41095fe5bd21faf815d6b035d7
> >> bc888a84a95d5 100644
> >> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> >> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> >> @@ -427,6 +427,17 @@ static int
> >>  vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
> >>                                 enum dma_data_direction
> >> direction)
> >>  {
> >> +    struct vb2_dc_buf *buf = dbuf->priv;
> >> +    struct sg_table *sgt = buf->dma_sgt;
> >> +
> >> +    if (!buf->non_coherent_mem)
> >> +            return 0;
> >> +
> >> +    if (buf->vaddr)
> >> +            invalidate_kernel_vmap_range(buf->vaddr, buf->size);
> >
> > What would make me a lot more confortable with this change is if you
> > enable kernel mappings for one test. This will ensure you cover the
> > call to "invalidate" in your testing. I'd like to know about the
> > performance impact. With this implementation it should be identical to
> > the VB2 one.
> >
>
> I have re-run my tests on RK3399, with 1280x720 XRGB capture buffers (1
> plane, 3686400 bytes). Capture process was pinned to "big" cores running
> at fixed frequency of 1.8 GHz. Libcamera was modified to request buffers
> with V4L2_MEMORY_FLAG_NON_COHERENT flag. DMA_BUF_IOCTL_SYNC ioctls were
> used as appropriate. For kernel mapping effect test, vb2_plane_vaddr
> call was inserted into rkisp1_vb2_buf_init.
>
> The timings are as following:
>
> - memcpy coherent buffer: 7570 +/- 63 us
> - memcpy non-coherent buffer: 1120 +/- 34 us
>
> without kernel mapping:
>
> - ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ}): 428 +/- 15 us
> - ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ}): 422 +/- 28 us
>
> with kernel mapping:
>
> - ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ}): 526 +/- 13 us
> - ioctl(fd, DMA_BUF_IOCTL_SYNC, {DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ}): 519 +/- 38 us
>
> So, even with kernel mapping enabled, speedup is 7570 / (1120 + 526 + 519) = 3.5,
> and the use of noncoherent buffers is justified -- at least on this platform.

Thanks a lot for the additional testing.

Acked-by: Tomasz Figa <tfiga at chromium.org>

Best regards,
Tomasz


From quic_jiegan at quicinc.com  Mon Mar 10 02:04:04 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:04:04 +0800
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP offset of ETR buffer
In-Reply-To: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
Message-ID: <20250310090407.2069489-2-quic_jiegan@quicinc.com>

The new functions calculate and return the offset to the write pointer of
the ETR buffer based on whether the memory mode is SG, flat or reserved.
The functions have the RWP offset can directly read data from ETR buffer,
enabling the transfer of data to any required location.

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 .../hwtracing/coresight/coresight-tmc-etr.c   | 40 +++++++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc.h   |  1 +
 2 files changed, 41 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index eda7cdad0e2b..ec636ab1fd75 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
 }
 EXPORT_SYMBOL_GPL(tmc_free_sg_table);
 
+static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata)
+{
+	dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
+	u64 rwp;
+
+	rwp = tmc_read_rwp(drvdata);
+	return rwp - paddr;
+}
+
+static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
+{
+	struct etr_buf *etr_buf = drvdata->sysfs_buf;
+	struct etr_sg_table *etr_table = etr_buf->private;
+	struct tmc_sg_table *table = etr_table->sg_table;
+	long w_offset;
+	u64 rwp;
+
+	rwp = tmc_read_rwp(drvdata);
+	w_offset = tmc_sg_get_data_page_offset(table, rwp);
+
+	return w_offset;
+}
+
+/*
+ * Retrieve the offset to the write pointer of the ETR buffer based on whether
+ * the memory mode is SG, flat or reserved.
+ */
+long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
+{
+	struct etr_buf *etr_buf = drvdata->sysfs_buf;
+
+	if (etr_buf->mode == ETR_MODE_ETR_SG)
+		return tmc_sg_get_rwp_offset(drvdata);
+	else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
+		return tmc_flat_resrv_get_rwp_offset(drvdata);
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
+
 /*
  * Alloc pages for the table. Since this will be used by the device,
  * allocate the pages closer to the device (i.e, dev_to_node(dev)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index b48bc9a01cc0..baedb4dcfc3f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
 struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
 				   enum cs_mode mode, void *data);
 extern const struct attribute_group coresight_etr_group;
+long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
 
 #endif
-- 
2.34.1



From quic_jiegan at quicinc.com  Mon Mar 10 02:04:06 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:04:06 +0800
Subject: [PATCH v1 3/4] coresight: ctcu: Enable byte-cntr for TMC ETR devices
In-Reply-To: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
Message-ID: <20250310090407.2069489-4-quic_jiegan@quicinc.com>

The byte-cntr function provided by the CTCU device is used to transfer data
from the ETR buffer to the userspace. An interrupt is triggered if the data
size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
handler counts the number of triggered interruptions and the read function
will read the data from the ETR buffer if the IRQ count is greater than 0.
Each successful read process will decrement the IRQ count by 1.

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 drivers/hwtracing/coresight/Makefile          |   2 +-
 .../coresight/coresight-ctcu-byte-cntr.c      | 339 ++++++++++++++++++
 .../hwtracing/coresight/coresight-ctcu-core.c |  96 ++++-
 drivers/hwtracing/coresight/coresight-ctcu.h  |  59 ++-
 .../hwtracing/coresight/coresight-tmc-etr.c   |   5 +-
 drivers/hwtracing/coresight/coresight-tmc.h   |   2 +
 6 files changed, 493 insertions(+), 10 deletions(-)
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c

diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 8e62c3150aeb..c90a06768a18 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -52,4 +52,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
 obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
 obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
-coresight-ctcu-y := coresight-ctcu-core.o
+coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
new file mode 100644
index 000000000000..0d16385663f5
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/coresight.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/property.h>
+#include <linux/uaccess.h>
+
+#include "coresight-ctcu.h"
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+#define BYTE_CNTR_CLASS_STR "byte-cntr-class"
+
+static struct class *byte_cntr_class;
+static dev_t byte_cntr_base;
+
+static irqreturn_t byte_cntr_handler(int irq, void *data)
+{
+	struct ctcu_byte_cntr *byte_cntr_data = (struct ctcu_byte_cntr *)data;
+
+	atomic_inc(&byte_cntr_data->irq_cnt);
+	wake_up(&byte_cntr_data->wq);
+
+	return IRQ_HANDLED;
+}
+
+/* Read the data from ETR's DDR buffer. */
+static void __ctcu_byte_cntr_read_etr_bytes(struct ctcu_byte_cntr *byte_cntr_data,
+					    size_t *len, char **bufp)
+{
+	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
+	size_t actual, bytes = byte_cntr_data->thresh_val;
+	struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
+	long r_offset;
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	r_offset = byte_cntr_data->r_offset;
+	if (*len >= bytes)
+		*len = bytes;
+	else if ((r_offset % bytes) + *len > bytes)
+		*len = bytes - (r_offset % bytes);
+
+	actual = tmc_etr_buf_get_data(etr_buf, r_offset, *len, bufp);
+	*len = actual;
+	if (actual == bytes || (actual + r_offset) % bytes == 0)
+		atomic_dec(&byte_cntr_data->irq_cnt);
+}
+
+/* Flush the remaining data in the ETR buffer after the byte cntr has stopped. */
+static ssize_t ctcu_flush_etr_buffer(struct ctcu_byte_cntr *byte_cntr_data, size_t len,
+				     char **bufpp)
+{
+	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
+	struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
+	ssize_t read_len = 0, remaining_len;
+	long r_offset, w_offset;
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	r_offset = byte_cntr_data->r_offset;
+	w_offset = byte_cntr_data->w_offset;
+	if (w_offset < r_offset)
+		remaining_len = tmcdrvdata->size + w_offset - r_offset;
+	else
+		remaining_len = w_offset - r_offset;
+
+	if (remaining_len > len)
+		remaining_len = len;
+
+	if (remaining_len > 0)
+		read_len = tmc_etr_buf_get_data(etr_buf, r_offset, remaining_len, bufpp);
+
+	return read_len;
+}
+
+static ssize_t ctcu_byte_cntr_copy_data(char __user *data, size_t len, char *bufp,
+					struct ctcu_byte_cntr *byte_cntr_data,
+					struct tmc_drvdata *tmcdrvdata)
+{
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	if (copy_to_user(data, bufp, len))
+		return -EFAULT;
+
+	byte_cntr_data->total_size += len;
+	if (byte_cntr_data->r_offset + len >= tmcdrvdata->size)
+		byte_cntr_data->r_offset = 0;
+	else
+		byte_cntr_data->r_offset += len;
+
+	return len;
+}
+
+/* The read function for /dev/byte-cntr%d */
+static ssize_t ctcu_byte_cntr_read_etr_bytes(struct file *fp, char __user *data,
+					     size_t len, loff_t *ppos)
+{
+	struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
+	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
+	char *bufp = NULL;
+	ssize_t read_len;
+
+	if (!data)
+		return -EINVAL;
+
+	/*
+	 * Flush the remaining data in the ETR buffer based on the write
+	 * offset of the ETR buffer when the byte cntr function has stopped.
+	 */
+	if (!byte_cntr_data->read_active || !byte_cntr_data->enable) {
+		read_len = ctcu_flush_etr_buffer(byte_cntr_data, len, &bufp);
+		if (read_len > 0)
+			return ctcu_byte_cntr_copy_data(data, read_len, bufp,
+							byte_cntr_data, tmcdrvdata);
+
+		return -EINVAL;
+	}
+
+	if (!atomic_read(&byte_cntr_data->irq_cnt)) {
+		if (wait_event_interruptible(byte_cntr_data->wq,
+					     atomic_read(&byte_cntr_data->irq_cnt) > 0 ||
+					     !byte_cntr_data->enable))
+			return -ERESTARTSYS;
+	}
+
+	__ctcu_byte_cntr_read_etr_bytes(byte_cntr_data, &len, &bufp);
+
+	return ctcu_byte_cntr_copy_data(data, len, bufp, byte_cntr_data, tmcdrvdata);
+}
+
+/* Start the byte-cntr function when the path is enabled. */
+void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct coresight_device *sink = coresight_get_sink(path);
+	struct ctcu_byte_cntr *byte_cntr_data;
+	int port_num;
+
+	if (!sink)
+		return;
+
+	port_num = ctcu_get_active_port(sink, csdev);
+	if (port_num < 0)
+		return;
+
+	byte_cntr_data = &drvdata->byte_cntr_data[port_num];
+	/* Don't start byte-cntr function when threshold is not set. */
+	if (!byte_cntr_data->thresh_val)
+		return;
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	atomic_set(&byte_cntr_data->irq_cnt, 0);
+	byte_cntr_data->sink = sink;
+	byte_cntr_data->enable = true;
+}
+
+/* Stop the byte-cntr function when the path is disabled. */
+void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct coresight_device *sink = coresight_get_sink(path);
+	struct ctcu_byte_cntr *byte_cntr_data;
+	struct tmc_drvdata *tmcdrvdata;
+	int port_num;
+
+	if (!sink)
+		return;
+
+	port_num = ctcu_get_active_port(sink, csdev);
+	if (port_num < 0)
+		return;
+
+	byte_cntr_data = &drvdata->byte_cntr_data[port_num];
+	tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	/* Store the w_offset of the ETR buffer when stopping. */
+	byte_cntr_data->w_offset = tmc_get_rwp_offset(tmcdrvdata);
+	atomic_set(&byte_cntr_data->irq_cnt, 0);
+	byte_cntr_data->read_active = false;
+	byte_cntr_data->enable = false;
+	/*
+	 * Wakeup once to force the read function to read the remaining
+	 * data of the ETR buffer.
+	 */
+	wake_up(&byte_cntr_data->wq);
+}
+
+static int ctcu_byte_cntr_release(struct inode *in, struct file *fp)
+{
+	struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
+	struct device *dev = &byte_cntr_data->sink->dev;
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	atomic_set(&byte_cntr_data->irq_cnt, 0);
+	byte_cntr_data->read_active = false;
+	disable_irq_wake(byte_cntr_data->byte_cntr_irq);
+	dev_dbg(dev, "send data total size: %llu bytes, r_offset: %ld w_offset: %ld\n",
+		byte_cntr_data->total_size, byte_cntr_data->r_offset,
+		byte_cntr_data->w_offset);
+
+	return 0;
+}
+
+static int ctcu_byte_cntr_open(struct inode *in, struct file *fp)
+{
+	struct ctcu_byte_cntr *byte_cntr_data = container_of(in->i_cdev,
+							     struct ctcu_byte_cntr, c_dev);
+	struct tmc_drvdata *tmcdrvdata;
+
+	if (byte_cntr_data->read_active)
+		return -EBUSY;
+
+	if (!byte_cntr_data->thresh_val || !byte_cntr_data->sink ||
+	    (coresight_get_mode(byte_cntr_data->sink) !=  CS_MODE_SYSFS))
+		return -EINVAL;
+
+	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
+	enable_irq_wake(byte_cntr_data->byte_cntr_irq);
+	fp->private_data = byte_cntr_data;
+	nonseekable_open(in, fp);
+	tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
+	/*
+	 * The original r_offset is the w_offset of the ETR buffer at the
+	 * start of the byte-cntr.
+	 */
+	byte_cntr_data->r_offset = tmc_get_rwp_offset(tmcdrvdata);
+	byte_cntr_data->total_size = 0;
+	byte_cntr_data->read_active = true;
+	byte_cntr_data->enable = true;
+
+	return 0;
+}
+
+static const struct file_operations byte_cntr_fops = {
+	.owner		= THIS_MODULE,
+	.open		= ctcu_byte_cntr_open,
+	.read		= ctcu_byte_cntr_read_etr_bytes,
+	.release	= ctcu_byte_cntr_release,
+};
+
+static int ctcu_byte_cntr_register_chardev(struct ctcu_byte_cntr *byte_cntr_data,
+					   int port_num)
+{
+	struct device *device;
+	dev_t devt;
+	int ret;
+
+	cdev_init(&byte_cntr_data->c_dev, &byte_cntr_fops);
+	devt = MKDEV(MAJOR(byte_cntr_base), MINOR(byte_cntr_base) + port_num);
+	ret = cdev_add(&byte_cntr_data->c_dev, devt, 1);
+	if (ret < 0)
+		return -ENOMEM;
+
+	device = device_create(byte_cntr_class, NULL, devt, byte_cntr_data,
+			       byte_cntr_data->name);
+
+	if (IS_ERR(device))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void ctcu_byte_cntr_unregister_chardev(struct ctcu_drvdata *drvdata)
+{
+	struct ctcu_byte_cntr *byte_cntr_data;
+	int i;
+
+	for (i = 0; i < ETR_MAX_NUM; i++) {
+		byte_cntr_data = &drvdata->byte_cntr_data[i];
+		device_destroy(byte_cntr_class, byte_cntr_data->c_dev.dev);
+	}
+}
+
+int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num)
+{
+	struct ctcu_byte_cntr *byte_cntr_data;
+	struct device_node *nd = dev->of_node;
+	int byte_cntr_irq, ret, i;
+
+	ret = alloc_chrdev_region(&byte_cntr_base, 0, ETR_MAX_NUM, BYTE_CNTR_CLASS_STR);
+	if (ret < 0)
+		return -ENOMEM;
+
+	byte_cntr_class = class_create(BYTE_CNTR_CLASS_STR);
+	if (IS_ERR(byte_cntr_class)) {
+		unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < etr_num; i++) {
+		byte_cntr_data = &drvdata->byte_cntr_data[i];
+		byte_cntr_irq = of_irq_get_byname(nd, byte_cntr_data->irq_name);
+		if (byte_cntr_irq < 0) {
+			ret = byte_cntr_irq;
+			goto err_exit;
+		}
+
+		ret = devm_request_irq(dev, byte_cntr_irq, byte_cntr_handler,
+				       IRQF_TRIGGER_RISING | IRQF_SHARED,
+				       dev_name(dev), byte_cntr_data);
+		if (ret) {
+			dev_err(dev, "Failed to register IRQ for %s\n",
+				byte_cntr_data->name);
+			goto err_exit;
+		}
+
+		ret = ctcu_byte_cntr_register_chardev(byte_cntr_data, i);
+		if (ret) {
+			dev_err(dev, "Failed to register chardev for %s\n",
+				byte_cntr_data->name);
+			goto err_exit;
+		}
+
+		byte_cntr_data->byte_cntr_irq = byte_cntr_irq;
+		atomic_set(&byte_cntr_data->irq_cnt, 0);
+		init_waitqueue_head(&byte_cntr_data->wq);
+	}
+
+	return 0;
+
+err_exit:
+	ctcu_byte_cntr_unregister_chardev(drvdata);
+	class_destroy(byte_cntr_class);
+	unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
+	return ret;
+}
+
+void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata)
+{
+	ctcu_byte_cntr_unregister_chardev(drvdata);
+	class_destroy(byte_cntr_class);
+	unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
+}
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index da35d8b4d579..5782655a5f39 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -46,16 +46,24 @@ DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
 #define CTCU_ATID_REG_BIT(traceid)	(traceid % 32)
 #define CTCU_ATID_REG_SIZE		0x10
 #define CTCU_ETR0_ATID0			0xf8
+#define CTCU_ETR0_IRQCTRL		0x6c
 #define CTCU_ETR1_ATID0			0x108
+#define CTCU_ETR1_IRQCTRL		0x70
 
 static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
 	{
-		.atid_offset	= CTCU_ETR0_ATID0,
-		.port_num	= 0,
+		.atid_offset		= CTCU_ETR0_ATID0,
+		.irq_ctrl_offset	= CTCU_ETR0_IRQCTRL,
+		.irq_name		= "etr0",
+		.byte_cntr_name		= "byte-cntr0",
+		.port_num		= 0,
 	},
 	{
-		.atid_offset	= CTCU_ETR1_ATID0,
-		.port_num	= 1,
+		.atid_offset		= CTCU_ETR1_ATID0,
+		.irq_ctrl_offset	= CTCU_ETR1_IRQCTRL,
+		.irq_name		= "etr1",
+		.byte_cntr_name		= "byte-cntr1",
+		.port_num		= 1,
 	},
 };
 
@@ -64,6 +72,69 @@ static const struct ctcu_config sa8775p_cfgs = {
 	.num_etr_config	= ARRAY_SIZE(sa8775p_etr_cfgs),
 };
 
+static ssize_t byte_cntr_val_show(struct device *dev, struct device_attribute *attr,
+				  char *buf)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	int i, len = 0;
+
+	for (i = 0; i < ETR_MAX_NUM; i++) {
+		if (drvdata->byte_cntr_data[i].irq_ctrl_offset)
+			len += scnprintf(buf + len, PAGE_SIZE - len, "%u ",
+					 drvdata->byte_cntr_data[i].thresh_val);
+	}
+
+	len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
+
+	return len;
+}
+
+static ssize_t byte_cntr_val_store(struct device *dev, struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	u32 thresh_vals[ETR_MAX_NUM] = { 0 };
+	u32 irq_ctrl_offset;
+	int num, i;
+
+	num = sscanf(buf, "%i %i", &thresh_vals[0], &thresh_vals[1]);
+	if (num <= 0 || num > ETR_MAX_NUM)
+		return -EINVAL;
+
+	/* Threshold 0 disables the interruption. */
+	guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
+	for (i = 0; i < num; i++) {
+		/* A small threshold will result in a large number of interruptions */
+		if (thresh_vals[i] && thresh_vals[i] < 4096)
+			return -EINVAL;
+
+		if (drvdata->byte_cntr_data[i].irq_ctrl_offset) {
+			drvdata->byte_cntr_data[i].thresh_val = thresh_vals[i];
+			irq_ctrl_offset = drvdata->byte_cntr_data[i].irq_ctrl_offset;
+			CS_UNLOCK(drvdata->base);
+			writel_relaxed(thresh_vals[i], drvdata->base + irq_ctrl_offset);
+			CS_LOCK(drvdata->base);
+		}
+	}
+
+	return size;
+}
+static DEVICE_ATTR_RW(byte_cntr_val);
+
+static struct attribute *ctcu_attrs[] = {
+	&dev_attr_byte_cntr_val.attr,
+	NULL,
+};
+
+static struct attribute_group ctcu_attr_grp = {
+	.attrs = ctcu_attrs,
+};
+
+static const struct attribute_group *ctcu_attr_grps[] = {
+	&ctcu_attr_grp,
+	NULL,
+};
+
 static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset,
 				       u8 bit, bool enable)
 {
@@ -122,7 +193,7 @@ static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, in
  * Searching the sink device from helper's view in case there are multiple helper devices
  * connected to the sink device.
  */
-static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
+int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
 {
 	struct coresight_platform_data *pdata = helper->pdata;
 	int i;
@@ -160,6 +231,8 @@ static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *
 {
 	struct coresight_path *path = (struct coresight_path *)data;
 
+	ctcu_byte_cntr_start(csdev, path);
+
 	return ctcu_set_etr_traceid(csdev, path, true);
 }
 
@@ -167,6 +240,8 @@ static int ctcu_disable(struct coresight_device *csdev, void *data)
 {
 	struct coresight_path *path = (struct coresight_path *)data;
 
+	ctcu_byte_cntr_stop(csdev, path);
+
 	return ctcu_set_etr_traceid(csdev, path, false);
 }
 
@@ -188,7 +263,7 @@ static int ctcu_probe(struct platform_device *pdev)
 	const struct ctcu_config *cfgs;
 	struct ctcu_drvdata *drvdata;
 	void __iomem *base;
-	int i;
+	int ret, i;
 
 	desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
 	if (!desc.name)
@@ -217,7 +292,14 @@ static int ctcu_probe(struct platform_device *pdev)
 			for (i = 0; i < cfgs->num_etr_config; i++) {
 				etr_cfg = &cfgs->etr_cfgs[i];
 				drvdata->atid_offset[i] = etr_cfg->atid_offset;
+				drvdata->byte_cntr_data[i].irq_name = etr_cfg->irq_name;
+				drvdata->byte_cntr_data[i].name = etr_cfg->byte_cntr_name;
+				drvdata->byte_cntr_data[i].irq_ctrl_offset =
+					etr_cfg->irq_ctrl_offset;
 			}
+			ret = ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config);
+			if (ret < 0)
+				dev_warn(dev, "Byte cntr init failed\n");
 		}
 	}
 
@@ -229,6 +311,7 @@ static int ctcu_probe(struct platform_device *pdev)
 	desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU;
 	desc.pdata = pdata;
 	desc.dev = dev;
+	desc.groups = ctcu_attr_grps;
 	desc.ops = &ctcu_ops;
 	desc.access = CSDEV_ACCESS_IOMEM(base);
 
@@ -247,6 +330,7 @@ static void ctcu_remove(struct platform_device *pdev)
 {
 	struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	ctcu_byte_cntr_remove(drvdata);
 	coresight_unregister(drvdata->csdev);
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h
index e9594c38dd91..e38535c91090 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu.h
+++ b/drivers/hwtracing/coresight/coresight-ctcu.h
@@ -5,6 +5,8 @@
 
 #ifndef _CORESIGHT_CTCU_H
 #define _CORESIGHT_CTCU_H
+#include <linux/cdev.h>
+
 #include "coresight-trace-id.h"
 
 /* Maximum number of supported ETR devices for a single CTCU. */
@@ -13,10 +15,16 @@
 /**
  * struct ctcu_etr_config
  * @atid_offset:	offset to the ATID0 Register.
- * @port_num:		in-port number of CTCU device that connected to ETR.
+ * @irq_ctrl_offset:	offset to the BYTECNTRVAL register.
+ * @irq_name:		IRQ name in dt node.
+ * @byte_cntr_name:	name of the byte cntr device node.
+ * @port_num:		in-port number of the CTCU device that connected to ETR.
  */
 struct ctcu_etr_config {
 	const u32 atid_offset;
+	const u32 irq_ctrl_offset;
+	const char *irq_name;
+	const char *byte_cntr_name;
 	const u32 port_num;
 };
 
@@ -25,15 +33,64 @@ struct ctcu_config {
 	int num_etr_config;
 };
 
+/**
+ * struct ctcu_byte_cntr
+ * @c_dev:		cdev for byte_cntr.
+ * @sink		csdev of sink device.
+ * @enable:		indicates that byte_cntr function is enabled or not.
+ * @read_active:	indicates that byte-cntr node is opened or not.
+ * @thresh_val:		threshold to trigger a interruption.
+ * @total_size		total size of transferred data.
+ * @byte_cntr_irq:	IRQ number.
+ * @irq_cnt:		IRQ count.
+ * @wq:			workqueue of reading ETR data.
+ * @read_work:		work of reading ETR data.
+ * @spin_lock:		spinlock of byte cntr data.
+ * @r_offset:		offset of the pointer where reading begins.
+ * @w_offset:		offset of the write pointer in the ETR buffer when
+ *			the byte cntr is stopped.
+ * @irq_ctrl_offset:	offset to the BYTECNTRVAL Register.
+ * @name:		the name of byte cntr device node.
+ * @irq_name:		IRQ name in DT.
+ */
+struct ctcu_byte_cntr {
+	struct cdev		c_dev;
+	struct coresight_device	*sink;
+	bool			enable;
+	bool			read_active;
+	u32			thresh_val;
+	u64			total_size;
+	int			byte_cntr_irq;
+	atomic_t		irq_cnt;
+	wait_queue_head_t	wq;
+	struct work_struct	read_work;
+	raw_spinlock_t		spin_lock;
+	long			r_offset;
+	long			w_offset;
+	u32			irq_ctrl_offset;
+	const char		*name;
+	const char		*irq_name;
+};
+
 struct ctcu_drvdata {
 	void __iomem		*base;
 	struct clk		*apb_clk;
 	struct device		*dev;
 	struct coresight_device	*csdev;
+	struct ctcu_byte_cntr   byte_cntr_data[ETR_MAX_NUM];
 	raw_spinlock_t		spin_lock;
 	u32			atid_offset[ETR_MAX_NUM];
 	/* refcnt for each traceid of each sink */
 	u8			traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
 };
 
+/* Generic functions */
+int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper);
+
+/* Byte-cntr functions */
+void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path);
+void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path);
+int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num);
+void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata);
+
 #endif
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index ec636ab1fd75..5dc94e890927 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1040,14 +1040,15 @@ static void tmc_free_etr_buf(struct etr_buf *etr_buf)
  * Returns: The size of the linear data available @pos, with *bufpp
  * updated to point to the buffer.
  */
-static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
-				    u64 offset, size_t len, char **bufpp)
+ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
+			     u64 offset, size_t len, char **bufpp)
 {
 	/* Adjust the length to limit this transaction to end of buffer */
 	len = (len < (etr_buf->size - offset)) ? len : etr_buf->size - offset;
 
 	return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
 }
+EXPORT_SYMBOL_GPL(tmc_etr_buf_get_data);
 
 static inline s64
 tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index baedb4dcfc3f..2fc77fd4ea25 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -443,5 +443,7 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
 				   enum cs_mode mode, void *data);
 extern const struct attribute_group coresight_etr_group;
 long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
+ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, size_t len,
+			     char **bufpp);
 
 #endif
-- 
2.34.1



From quic_jiegan at quicinc.com  Mon Mar 10 02:04:05 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:04:05 +0800
Subject: [PATCH v1 2/4] dt-bindings: arm: Add an interrupt property for Coresight CTCU
In-Reply-To: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
Message-ID: <20250310090407.2069489-3-quic_jiegan@quicinc.com>

Add an interrupt property to CTCU device. The interrupt will be triggered
when the data size in the ETR buffer exceeds the threshlod of the
BYTECNTRVAL register. Programming a threshold in the BYTECNTRVAL register
of CTCU device will enable the interrupt.

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
 .../bindings/arm/qcom,coresight-ctcu.yaml       | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
index 843b52eaf872..ea05ad8f3dd3 100644
--- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml
@@ -39,6 +39,16 @@ properties:
     items:
       - const: apb
 
+  interrupts:
+    items:
+      - description: Byte cntr interrupt for etr0
+      - description: Byte cntr interrupt for etr1
+
+  interrupt-names:
+    items:
+      - const: etr0
+      - const: etr1
+
   in-ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -56,6 +66,8 @@ additionalProperties: false
 
 examples:
   - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
     ctcu at 1001000 {
         compatible = "qcom,sa8775p-ctcu";
         reg = <0x1001000 0x1000>;
@@ -63,6 +75,11 @@ examples:
         clocks = <&aoss_qmp>;
         clock-names = "apb";
 
+        interrupts = <GIC_SPI 270 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 262 IRQ_TYPE_EDGE_RISING>;
+        interrupt-names = "etr0",
+                          "etr1";
+
         in-ports {
             #address-cells = <1>;
             #size-cells = <0>;
-- 
2.34.1



From quic_jiegan at quicinc.com  Mon Mar 10 02:04:07 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:04:07 +0800
Subject: [PATCH v1 4/4] arm64: dts: qcom: sa8775p: Add interrupts to CTCU device
In-Reply-To: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
Message-ID: <20250310090407.2069489-5-quic_jiegan@quicinc.com>

Add interrupts to enable byte-cntr function for TMC ETR devices.

Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
Dependency:
prerequisite-message-id: 20250303032931.2500935-11-quic_jiegan at quicinc.com
---
 arch/arm64/boot/dts/qcom/sa8775p.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 93ca37843990..091ae73774fa 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -2425,6 +2425,11 @@ ctcu at 4001000 {
 			clocks = <&aoss_qmp>;
 			clock-names = "apb";
 
+			interrupts = <GIC_SPI 270 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 262 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "etr0",
+					  "etr1";
+
 			in-ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
-- 
2.34.1



From quic_jiegan at quicinc.com  Mon Mar 10 02:04:03 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:04:03 +0800
Subject: [PATCH v1 0/4] coresight: ctcu: Enable byte-cntr function for TMC ETR
Message-ID: <20250310090407.2069489-1-quic_jiegan@quicinc.com>

From: Jie Gan <jie.gan at oss.qualcomm.com>

The byte-cntr function provided by the CTCU device is used to transfer data
from the ETR buffer to the userspace. An interrupt is tiggered if the data
size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
handler counts the number of triggered interruptions and the read function
will read the data from the ETR buffer if the IRQ count is greater than 0.
Each successful read process will decrement the IRQ count by 1.

The byte cntr function will start when the device node is opened for reading,
and the IRQ count will reset when the byte cntr function has stopped. When
the file node is opened, the w_offset of the ETR buffer will be read and
stored in byte_cntr_data, serving as the original r_offset (indicating
where reading starts) for the byte counter function.

The work queue for the read operation will wake up once when ETR is stopped,
ensuring that the remaining data in the ETR buffer has been flushed based on
the w_offset read at the time of stopping.

The following shell commands write threshold to BYTECNTRVAL registers.

Only enable byte-cntr for ETR0:
echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val

Enable byte-cntr for both ETR0 and ETR1(support both hex and decimal values):
echo 0x10000 4096 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val

Setting the BYTECNTRVAL registers to 0 disables the byte-cntr function.
Disable byte-cntr for ETR0:
echo 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val

Disable byte-cntr for both ETR0 and ETR1:
echo 0 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val

There is a minimum threshold to prevent generating too many interrupts.
The minimum threshold is 4096 bytes. The write process will fail if user try
to set the BYTECNTRVAL registers to a value less than 4096 bytes(except
for 0).

Finally, the user can read data from the ETR buffer through the byte-cntr file
nodes located under /dev, for example reads data from the ETR0 buffer:
cat /dev/byte-cntr0

Way to enable and start byte-cntr for ETR0:
echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
echo 1 > /sys/bus/coresight/devices/etm0/enable_source
cat /dev/byte-cntr0

Jie Gan (4):
  coresight: tmc: Introduce new APIs to get the RWP offset of ETR buffer
  dt-bindings: arm: Add an interrupt property for Coresight CTCU
  coresight: ctcu: Enable byte-cntr for TMC ETR devices
  arm64: dts: qcom: sa8775p: Add interrupts to CTCU device

 .../bindings/arm/qcom,coresight-ctcu.yaml     |  17 +
 arch/arm64/boot/dts/qcom/sa8775p.dtsi         |   5 +
 drivers/hwtracing/coresight/Makefile          |   2 +-
 .../coresight/coresight-ctcu-byte-cntr.c      | 339 ++++++++++++++++++
 .../hwtracing/coresight/coresight-ctcu-core.c |  96 ++++-
 drivers/hwtracing/coresight/coresight-ctcu.h  |  59 ++-
 .../hwtracing/coresight/coresight-tmc-etr.c   |  45 ++-
 drivers/hwtracing/coresight/coresight-tmc.h   |   3 +
 8 files changed, 556 insertions(+), 10 deletions(-)
 create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c

-- 
2.34.1



From krzk at kernel.org  Mon Mar 10 02:07:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 10:07:20 +0100
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <20250310090407.2069489-2-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com>
Message-ID: <b724d9c1-cd73-4e4e-aed1-101049204c90@kernel.org>

On 10/03/2025 10:04, Jie Gan wrote:
> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
> +{
> +	struct etr_buf *etr_buf = drvdata->sysfs_buf;
> +	struct etr_sg_table *etr_table = etr_buf->private;
> +	struct tmc_sg_table *table = etr_table->sg_table;
> +	long w_offset;
> +	u64 rwp;
> +
> +	rwp = tmc_read_rwp(drvdata);
> +	w_offset = tmc_sg_get_data_page_offset(table, rwp);
> +
> +	return w_offset;
> +}
> +
> +/*
> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
> + * the memory mode is SG, flat or reserved.
> + */
> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)

You need kerneldoc for exports.


Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 10 02:08:18 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 10:08:18 +0100
Subject: [PATCH v1 4/4] arm64: dts: qcom: sa8775p: Add interrupts to CTCU
 device
In-Reply-To: <20250310090407.2069489-5-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-5-quic_jiegan@quicinc.com>
Message-ID: <24d5b56f-5078-4128-be66-436b1755d4b7@kernel.org>

On 10/03/2025 10:04, Jie Gan wrote:
> Add interrupts to enable byte-cntr function for TMC ETR devices.
> 
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
> Dependency:
> prerequisite-message-id: 20250303032931.2500935-11-quic_jiegan at quicinc.com
Which too generated such changelog? Why this cannot be lore link?

Best regards,
Krzysztof


From quic_jiegan at quicinc.com  Mon Mar 10 02:12:33 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:12:33 +0800
Subject: [PATCH v1 4/4] arm64: dts: qcom: sa8775p: Add interrupts to CTCU
 device
In-Reply-To: <24d5b56f-5078-4128-be66-436b1755d4b7@kernel.org>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-5-quic_jiegan@quicinc.com>
 <24d5b56f-5078-4128-be66-436b1755d4b7@kernel.org>
Message-ID: <ca5e2cf0-598f-484f-a096-137baeed381d@quicinc.com>



On 3/10/2025 5:08 PM, Krzysztof Kozlowski wrote:
> On 10/03/2025 10:04, Jie Gan wrote:
>> Add interrupts to enable byte-cntr function for TMC ETR devices.
>>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>> Dependency:
>> prerequisite-message-id: 20250303032931.2500935-11-quic_jiegan at quicinc.com
> Which too generated such changelog? Why this cannot be lore link?
> 
> Best regards,
> Krzysztof

Hi Krzysztof,

It was entered manually. It's my fault, will fix in next version.

Thanks,
Jie



From jaroslaw.kownacki at commetro.pl  Mon Mar 10 02:01:01 2025
From: jaroslaw.kownacki at commetro.pl (=?UTF-8?Q? Jaros=C5=82aw_Kownacki ?=)
Date: Mon, 10 Mar 2025 09:01:01 GMT
Subject: =?UTF-8?Q?Pytanie_o_ofert=C4=99?=
Message-ID: <20250310084500-0.1.1a.fayz.0.igw20eoa61@commetro.pl>

Dzie? dobry,

Czy potrzebuj? Pa?stwo aktualnie nowych klient?w ?

Skutecznie pomagamy rozpoczyna? rozmowy handlowe z klientami zainteresowanymi Pa?stwa ofert?.

Zapraszam do kontaktu zwrotnego.


Pozdrawiam serdecznie
Jaros?aw Kownacki


From quic_jiegan at quicinc.com  Mon Mar 10 02:14:57 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 17:14:57 +0800
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <b724d9c1-cd73-4e4e-aed1-101049204c90@kernel.org>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com>
 <b724d9c1-cd73-4e4e-aed1-101049204c90@kernel.org>
Message-ID: <55e62062-f85f-484d-b577-87e10e73ab31@quicinc.com>



On 3/10/2025 5:07 PM, Krzysztof Kozlowski wrote:
> On 10/03/2025 10:04, Jie Gan wrote:
>> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
>> +{
>> +	struct etr_buf *etr_buf = drvdata->sysfs_buf;
>> +	struct etr_sg_table *etr_table = etr_buf->private;
>> +	struct tmc_sg_table *table = etr_table->sg_table;
>> +	long w_offset;
>> +	u64 rwp;
>> +
>> +	rwp = tmc_read_rwp(drvdata);
>> +	w_offset = tmc_sg_get_data_page_offset(table, rwp);
>> +
>> +	return w_offset;
>> +}
>> +
>> +/*
>> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
>> + * the memory mode is SG, flat or reserved.
>> + */
>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
> 
> You need kerneldoc for exports.

Hi Krzysztof,

Sorry for the insufficient description for an export function. Will fix 
it in next version.

Thanks,
Jie

> 
> 
> Best regards,
> Krzysztof



From krzk at kernel.org  Mon Mar 10 02:21:45 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 10:21:45 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <20250309132959.19045-6-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
Message-ID: <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>

On 09/03/2025 14:29, Christian Marangi wrote:
> Add Documentation for Airoha EN7581 SCU.
> 
> Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
> via the SCU (System Controller Unit).
> 
> Example of these pheriperals are reset-controller, clock-controller,
> PCIe line speed controller and bits to configure different Serdes ports
> for USB or Ethernet usage.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> new file mode 100644
> index 000000000000..d7dc66f912c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> @@ -0,0 +1,68 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha EN7581 SCU (System Controller Unit)
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description:
> +  Airoha EN7581 SoC expose registers to control miscellaneous
> +  pheriperals via the SCU (System Controller Unit).
> +
One more comment - there is no such thing as "sysctl" in your hardware.
Look at the SCU binding which clearly says that it is the hardware you
are duplicating here, so the "System Control Unit".

So you have existing "This node defines the System Control Unit of the
EN7523 SoC" and you add one more node which defines the "System Control
Unit", so you have two "System Control Unit" device nodes?

Look also what Stephen asked for:

https://lore.kernel.org/all/20220106013100.842FCC36AEB at smtp.kernel.org/

so how system-controller can now became clock-controller? Now, it was
the system controller since the beginning.

Best regards,
Krzysztof


From cassel at kernel.org  Mon Mar 10 02:48:26 2025
From: cassel at kernel.org (Niklas Cassel)
Date: Mon, 10 Mar 2025 10:48:26 +0100
Subject: [PATCH v3 0/2] PCI: dw-rockchip: hide broken ATS cap in EP-mode
Message-ID: <20250310094826.842681-4-cassel@kernel.org>

Hello there,

Address Translation Services (ATS) is broken on rk3588 when running the
PCIe controller in Endpoint Mode.

This causes IOTLB invalidation timeout errors on the host side when using
and rk3588 in Endpoint Mode, and you are unable to run pci_endpoint_test.

Solve this by hiding the ATS capability.
With this, we do not get any IOTLB invalidation timeouts, and we can run
pci_endpoint_test successfully.


Changes since v2:
-Added missing EXPORT_SYMBOL_GPL().


Niklas Cassel (2):
  PCI: dwc: ep: Add dw_pcie_ep_hide_ext_capability()
  PCI: dw-rockchip: Hide broken ATS capability

 .../pci/controller/dwc/pcie-designware-ep.c   | 39 +++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h  |  7 ++++
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++
 3 files changed, 73 insertions(+)

-- 
2.48.1



From cassel at kernel.org  Mon Mar 10 02:48:28 2025
From: cassel at kernel.org (Niklas Cassel)
Date: Mon, 10 Mar 2025 10:48:28 +0100
Subject: [PATCH v3 2/2] PCI: dw-rockchip: Hide broken ATS capability
In-Reply-To: <20250310094826.842681-4-cassel@kernel.org>
References: <20250310094826.842681-4-cassel@kernel.org>
Message-ID: <20250310094826.842681-6-cassel@kernel.org>

When running the rk3588 in endpoint mode, with an Intel host with IOMMU
enabled, the host side prints:

  DMAR: VT-d detected Invalidation Time-out Error: SID 0

When running the rk3588 in endpoint mode, with an AMD host with IOMMU
enabled, the host side prints:

  iommu ivhd0: AMD-Vi: Event logged [IOTLB_INV_TIMEOUT device=63:00.0 address=0x42b5b01a0]

Rockchip has confirmed that the ATS support for rk3588 only works when
running the PCIe controller in RC mode [0].

Usually, to handle these issues, we add a quirk for the PCI vendor and
device ID in drivers/pci/quirks.c with quirk_no_ats(). That is because
we cannot usually modify the capabilities on the EP side.

In this case, we can modify the capabilities on the EP side. Thus, hide the
broken ATS capability on rk3588 when running in EP mode. That way,
we don't need any quirk on the host side, and we see no errors on the host
side, and we can run pci_endpoint_test successfully, with the IOMMU
enabled on the host side.

[0] https://lore.kernel.org/linux-pci/93cdce39-1ae6-4939-a3fc-db10be7564e5 at rock-chips.com/

Acked-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Niklas Cassel <cassel at kernel.org>
---
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 836ea10eafbb..bc4339252a03 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -242,6 +242,32 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
 	.init = rockchip_pcie_host_init,
 };
 
+/*
+ * ATS does not work on rk3588 when running in EP mode.
+ * After a host has enabled ATS on the EP side, it will send an IOTLB
+ * invalidation request to the EP side. The rk3588 will never send a completion
+ * back and eventually the host will print an IOTLB_INV_TIMEOUT error, and the
+ * EP will not be operational. If we hide the ATS cap, things work as expected.
+ */
+static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	struct device *dev = pci->dev;
+
+	/* Only hide the ATS cap for rk3588 running in EP mode */
+	if (!of_device_is_compatible(dev->of_node, "rockchip,rk3588-pcie-ep"))
+		return;
+
+	if (dw_pcie_ep_hide_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI,
+					   PCI_EXT_CAP_ID_ATS))
+		dev_err(dev, "failed to hide ATS cap\n");
+}
+
+static void rockchip_pcie_ep_pre_init(struct dw_pcie_ep *ep)
+{
+	rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
+}
+
 static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@ -314,6 +340,7 @@ rockchip_pcie_get_features(struct dw_pcie_ep *ep)
 
 static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = {
 	.init = rockchip_pcie_ep_init,
+	.pre_init = rockchip_pcie_ep_pre_init,
 	.raise_irq = rockchip_pcie_raise_irq,
 	.get_features = rockchip_pcie_get_features,
 };
-- 
2.48.1



From kevin_chen at aspeedtech.com  Mon Mar 10 02:49:43 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 09:49:43 +0000
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <e17cdf9d-ba96-41d2-9656-9e50d0e0795a@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
 <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
 <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>
 <e17cdf9d-ba96-41d2-9656-9e50d0e0795a@kernel.org>
Message-ID: <TY0PR06MB496045B19DCB149EC902D0FF89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>

> On 10/03/2025 02:50, Kevin Chen wrote:
> >>> +        $ref: /schemas/types.yaml#/definitions/uint32-array
> >>> +        description: The LPC I/O ports to pcc
> >>
> >> Description is too vague. Why would we encode I/O ports as some
> >> numbers instead of GPIOs for example? If these are ports, why this is not a
> graph?
> > For the port-mmaped I/O in x86 architecture, BMC need to handle specific
> port I/O in the relative HW module.
> > So, I need to add the pcc-ports property as the snoop-ports property
> > in Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> >
> >>
> >> Missing constraints - min/maxItems, defaults, minimum/maximum etc.
> > The port-mmaped I/O is defined from host, BMC as the device would capture
> the port I/O from the pcc-ports property defined in dts.
> 
> Put this information in the description, instead of copying property name.
OK. I will put this information in the description.

> 
> >
> >>
> >>> +
> >>> +    required:
> >>> +      - compatible
> >>> +      - interrupts
> >>> +      - pcc-ports
> >>> +
> >>>    "^uart-routing@[0-9a-f]+$":
> >>>      $ref: /schemas/soc/aspeed/uart-routing.yaml#
> >>>      description: The UART routing control under LPC register space
> >>> @@
> >>> -176,6 +205,13 @@ examples:
> >>>          #size-cells = <1>;
> >>>          ranges = <0x0 0x1e789000 0x1000>;
> >>>
> >>> +        lpc_pcc: lpc-pcc at 0 {
> >>> +            compatible = "aspeed,ast2600-lpc-pcc";
> >>> +            reg = <0x0 0x140>;
> >>> +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> >>> +            pcc-ports = <0x80>;
> >>
> >> So what 0x80 stands for?
> > Host as x86 architecture would access the 0x80 port, which is mapped to the
> BMC PCC HW module.
> > As a result, x86 can keep the port-mmaped I/O usage and access the BMC
> device, which is needed to know which port using in the PCC module in BMC.
> 
> And on different boards this is not 0x80?
The port-mmaped I/O defined in the intel legacy document as the example usage.
For example, the common usage agreement of port-mmaped I/O are the following. But this setting can be modified due to the host usage. We provide the flexibility to modify the I/O port settings.
KCS : 0xCA2(CMD)/CA3(Data)
BT : 0xE4/E5/E6
SNOOP/PCC : 0x80/81/82/83
Mailbox : 0xCC0
SuperIO : 0x2E/2F or 0x4E/0x4F
System UART : 0x3F8/2F8/3E8/2E8

> 
> Best regards,
> Krzysztof

From richard.weiyang at gmail.com  Mon Mar 10 02:51:24 2025
From: richard.weiyang at gmail.com (Wei Yang)
Date: Mon, 10 Mar 2025 09:51:24 +0000
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250223002229.xuk6xlp23zr72hkc@master>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250223002229.xuk6xlp23zr72hkc@master>
Message-ID: <20250310095124.pa7dwgqhxglqrfes@master>

On Sun, Feb 23, 2025 at 12:22:29AM +0000, Wei Yang wrote:
>On Wed, Feb 19, 2025 at 09:24:31AM +0200, Mike Rapoport wrote:
>>Hi,
>>
>>On Tue, Feb 18, 2025 at 03:50:04PM +0000, Wei Yang wrote:
>>> On Thu, Feb 06, 2025 at 03:27:42PM +0200, Mike Rapoport wrote:
>>> >From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
>>> >
>>> >to denote areas that were reserved for kernel use either directly with
>>> >memblock_reserve_kern() or via memblock allocations.
>>> >
>>> >Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
>>> >---
>>> > include/linux/memblock.h | 16 +++++++++++++++-
>>> > mm/memblock.c            | 32 ++++++++++++++++++++++++--------
>>> > 2 files changed, 39 insertions(+), 9 deletions(-)
>>> >
>>> >diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>>> >index e79eb6ac516f..65e274550f5d 100644
>>> >--- a/include/linux/memblock.h
>>> >+++ b/include/linux/memblock.h
>>> >@@ -50,6 +50,7 @@ enum memblock_flags {
>>> > 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>>> > 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
>>> > 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
>>> >+	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
>>> 
>>> Above memblock_flags, there are comments on explaining those flags.
>>> 
>>> Seems we miss it for MEMBLOCK_RSRV_KERN.
>>
>>Right, thanks!
>> 
>>> > 
>>> > #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
>>> >@@ -1459,14 +1460,14 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
>>> > again:
>>> > 	found = memblock_find_in_range_node(size, align, start, end, nid,
>>> > 					    flags);
>>> >-	if (found && !memblock_reserve(found, size))
>>> >+	if (found && !__memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN))
>>> 
>>> Maybe we could use memblock_reserve_kern() directly. If my understanding is
>>> correct, the reserved region's nid is not used.
>>
>>We use nid of reserved regions in reserve_bootmem_region() (commit
>>61167ad5fecd ("mm: pass nid to reserve_bootmem_region()")) but KHO needs to
>>know the distribution of reserved memory among the nodes before
>>memmap_init_reserved_pages().
>> 
>
>I took another look into this commit. There maybe a very corner case in which
>will leave a reserved region with no nid set.
>
>memmap_init_reserved_pages()
>    for_each_mem_region() {
>        ...
>	memblock_set_node(start, end, &memblock.reserved, nid);
>    }
>
>We leverage the iteration here to set nid to all regions in memblock.reserved.
>But memblock_set_node() may call memblock_double_array() to expand the array,
>which may get a range before current start. So we would miss to set the
>correct nid to the new reserved region.
>
>I have tried to create a case in memblock test. This would happen when there
>are 126 memblock.reserved regions. And the last region is across the last two
>node.
>
>One way to fix this is compare type->max in memblock_set_node(). Then check
>this return value in memmap_init_reserved_pages(). If we found the size
>changes, repeat the iteration.
>
>But this is a very trivial one, not sure it worth fix.
>

Hi, Mike

I have done a user space test which shows we may have a chance to leave a
region with non-nid set.

Not sure you are ok with my approach of fixing.

-- 
Wei Yang
Help you, Help me


From anshuman.khandual at arm.com  Mon Mar 10 02:59:01 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 15:29:01 +0530
Subject: [RFC 1/2] mm/ptdump: Split note_page() into level specific callbacks
In-Reply-To: <20250310095902.390664-1-anshuman.khandual@arm.com>
References: <20250310095902.390664-1-anshuman.khandual@arm.com>
Message-ID: <20250310095902.390664-2-anshuman.khandual@arm.com>

Last argument passed down in note_page() is u64 assuming pxd_val() returned
value (all page table levels) is 64 bit - which might not be the case going
ahead when D128 page tables is enabled on arm64 platform. Besides pxd_val()
is very platform specific and its type should not be assumed in generic MM.

Split note_page() into individual page table level specific callbacks which
accepts corresponding pxd_t argument instead and then subscribing platforms
just derive pxd_val() from the entries as required and proceed as earlier.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
Cc: Nicholas Piggin <npiggin at gmail.com>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Gerald Schaefer <gerald.schaefer at linux.ibm.com>
Cc: Heiko Carstens <hca at linux.ibm.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-mm at kvack.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
 arch/arm64/include/asm/ptdump.h | 10 ++++++++
 arch/arm64/mm/ptdump.c          | 37 ++++++++++++++++++++++++++--
 arch/powerpc/mm/ptdump/ptdump.c | 37 ++++++++++++++++++++++++++--
 arch/riscv/mm/ptdump.c          | 37 ++++++++++++++++++++++++++--
 arch/s390/mm/dump_pagetables.c  | 37 ++++++++++++++++++++++++++--
 arch/x86/mm/dump_pagetables.c   | 31 +++++++++++++++++++++++-
 include/linux/ptdump.h          |  7 ++++--
 mm/ptdump.c                     | 43 +++++++++++++++++++++++++--------
 8 files changed, 218 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index 6cf4aae05219..8baba0d1aa8f 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -60,6 +60,11 @@ struct ptdump_pg_state {
 void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
 void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	       u64 val);
+void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte);
+void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
+void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud);
+void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
+void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
 #ifdef CONFIG_PTDUMP_DEBUGFS
 #define EFI_RUNTIME_MAP_END	DEFAULT_MAP_WINDOW_64
 void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
@@ -70,6 +75,11 @@ static inline void ptdump_debugfs_register(struct ptdump_info *info,
 #else
 static inline void note_page(struct ptdump_state *pt_st, unsigned long addr,
 			     int level, u64 val) { }
+static inline void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte) { }
+static inline void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd) { }
+static inline void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud) { }
+static inline void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d) { }
+static inline void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd) { }
 #endif /* CONFIG_PTDUMP_CORE */
 
 #endif /* __ASM_PTDUMP_H */
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 688fbe0271ca..0c66c8474a48 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -251,6 +251,31 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 
 }
 
+void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
 void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 {
 	unsigned long end = ~0UL;
@@ -266,7 +291,11 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 		.pg_level = &kernel_pg_levels[0],
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]){
 				{info->base_addr, end},
 				{0, 0}
@@ -303,7 +332,11 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]) {
 				{_PAGE_OFFSET(vabits_actual), ~0UL},
 				{0, 0}
diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index 9dc239967b77..12c0fe2e9292 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -298,6 +298,31 @@ static void populate_markers(void)
 #endif
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
 static int ptdump_show(struct seq_file *m, void *v)
 {
 	struct pg_state st = {
@@ -305,7 +330,11 @@ static int ptdump_show(struct seq_file *m, void *v)
 		.marker = address_markers,
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = ptdump_range,
 		}
 	};
@@ -338,7 +367,11 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = ptdump_range,
 		}
 	};
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
index 9d5f657a251b..6750a7e65c76 100644
--- a/arch/riscv/mm/ptdump.c
+++ b/arch/riscv/mm/ptdump.c
@@ -318,6 +318,31 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
 static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
 {
 	struct pg_state st = {
@@ -325,7 +350,11 @@ static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
 		.marker = pinfo->markers,
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]) {
 				{pinfo->base_addr, pinfo->end},
 				{0, 0}
@@ -347,7 +376,11 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]) {
 				{KERN_VIRT_START, ULONG_MAX},
 				{0, 0}
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index fa54f3bc0c8d..f81a2cc47772 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -145,11 +145,40 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
 bool ptdump_check_wx(void)
 {
 	struct pg_state st = {
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]) {
 				{.start = 0, .end = max_addr},
 				{.start = 0, .end = 0},
@@ -188,7 +217,11 @@ static int ptdump_show(struct seq_file *m, void *v)
 {
 	struct pg_state st = {
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.range = (struct ptdump_range[]) {
 				{.start = 0, .end = max_addr},
 				{.start = 0, .end = 0},
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 89079ea73e65..8e06667045e8 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -362,6 +362,31 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
 bool ptdump_walk_pgd_level_core(struct seq_file *m,
 				struct mm_struct *mm, pgd_t *pgd,
 				bool checkwx, bool dmesg)
@@ -378,7 +403,11 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m,
 
 	struct pg_state st = {
 		.ptdump = {
-			.note_page	= note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
 			.effective_prot = effective_prot,
 			.range		= ptdump_ranges
 		},
diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h
index 8dbd51ea8626..3bb5ed62fc6d 100644
--- a/include/linux/ptdump.h
+++ b/include/linux/ptdump.h
@@ -12,8 +12,11 @@ struct ptdump_range {
 
 struct ptdump_state {
 	/* level is 0:PGD to 4:PTE, or -1 if unknown */
-	void (*note_page)(struct ptdump_state *st, unsigned long addr,
-			  int level, u64 val);
+	void (*note_page_pte)(struct ptdump_state *st, unsigned long addr, pte_t pte);
+	void (*note_page_pmd)(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
+	void (*note_page_pud)(struct ptdump_state *st, unsigned long addr, pud_t pud);
+	void (*note_page_p4d)(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
+	void (*note_page_pgd)(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
 	void (*effective_prot)(struct ptdump_state *st, int level, u64 val);
 	const struct ptdump_range *range;
 };
diff --git a/mm/ptdump.c b/mm/ptdump.c
index 106e1d66e9f9..cac4dec90c24 100644
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -18,7 +18,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk,
 {
 	struct ptdump_state *st = walk->private;
 
-	st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0]));
+	st->note_page_pte(st, addr, kasan_early_shadow_pte[0]);
 
 	walk->action = ACTION_CONTINUE;
 
@@ -42,7 +42,7 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr,
 		st->effective_prot(st, 0, pgd_val(val));
 
 	if (pgd_leaf(val)) {
-		st->note_page(st, addr, 0, pgd_val(val));
+		st->note_page_pgd(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -65,7 +65,7 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr,
 		st->effective_prot(st, 1, p4d_val(val));
 
 	if (p4d_leaf(val)) {
-		st->note_page(st, addr, 1, p4d_val(val));
+		st->note_page_p4d(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -88,7 +88,7 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr,
 		st->effective_prot(st, 2, pud_val(val));
 
 	if (pud_leaf(val)) {
-		st->note_page(st, addr, 2, pud_val(val));
+		st->note_page_pud(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -109,7 +109,7 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr,
 	if (st->effective_prot)
 		st->effective_prot(st, 3, pmd_val(val));
 	if (pmd_leaf(val)) {
-		st->note_page(st, addr, 3, pmd_val(val));
+		st->note_page_pmd(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -125,7 +125,7 @@ static int ptdump_pte_entry(pte_t *pte, unsigned long addr,
 	if (st->effective_prot)
 		st->effective_prot(st, 4, pte_val(val));
 
-	st->note_page(st, addr, 4, pte_val(val));
+	st->note_page_pte(st, addr, val);
 
 	return 0;
 }
@@ -134,9 +134,31 @@ static int ptdump_hole(unsigned long addr, unsigned long next,
 		       int depth, struct mm_walk *walk)
 {
 	struct ptdump_state *st = walk->private;
-
-	st->note_page(st, addr, depth, 0);
-
+	pte_t pte_zero = {0};
+	pmd_t pmd_zero = {0};
+	pud_t pud_zero = {0};
+	p4d_t p4d_zero = {0};
+	pgd_t pgd_zero = {0};
+
+	switch (depth) {
+	case 4:
+		st->note_page_pte(st, addr, pte_zero);
+		break;
+	case 3:
+		st->note_page_pmd(st, addr, pmd_zero);
+		break;
+	case 2:
+		st->note_page_pud(st, addr, pud_zero);
+		break;
+	case 1:
+		st->note_page_p4d(st, addr, p4d_zero);
+		break;
+	case 0:
+		st->note_page_pgd(st, addr, pgd_zero);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
@@ -152,6 +174,7 @@ static const struct mm_walk_ops ptdump_ops = {
 void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
 {
 	const struct ptdump_range *range = st->range;
+	pte_t pte_zero = {0};
 
 	mmap_write_lock(mm);
 	while (range->start != range->end) {
@@ -162,7 +185,7 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
 	mmap_write_unlock(mm);
 
 	/* Flush out the last page */
-	st->note_page(st, 0, -1, 0);
+	st->note_page_pte(st, 0, pte_zero);
 }
 
 static int check_wx_show(struct seq_file *m, void *v)
-- 
2.25.1



From anshuman.khandual at arm.com  Mon Mar 10 02:59:02 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 15:29:02 +0530
Subject: [RFC 2/2] arm64/ptdump: Replace u64 with pteval_t
In-Reply-To: <20250310095902.390664-1-anshuman.khandual@arm.com>
References: <20250310095902.390664-1-anshuman.khandual@arm.com>
Message-ID: <20250310095902.390664-3-anshuman.khandual@arm.com>

Page table entry's value, mask and protection are represented with pteval_t
data type format not u64 that has been assumed while dumping the page table
entries. Replace all such u64 instances with pteval_t instead as required.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Marc Zyngier <maz at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
 arch/arm64/include/asm/ptdump.h | 12 ++++++------
 arch/arm64/mm/ptdump.c          |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index 8baba0d1aa8f..8ade657547f9 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -24,8 +24,8 @@ struct ptdump_info {
 };
 
 struct ptdump_prot_bits {
-	u64		mask;
-	u64		val;
+	pteval_t	mask;
+	pteval_t	val;
 	const char	*set;
 	const char	*clear;
 };
@@ -34,7 +34,7 @@ struct ptdump_pg_level {
 	const struct ptdump_prot_bits *bits;
 	char name[4];
 	int num;
-	u64 mask;
+	pteval_t mask;
 };
 
 /*
@@ -51,7 +51,7 @@ struct ptdump_pg_state {
 	const struct mm_struct *mm;
 	unsigned long start_address;
 	int level;
-	u64 current_prot;
+	pteval_t current_prot;
 	bool check_wx;
 	unsigned long wx_pages;
 	unsigned long uxn_pages;
@@ -59,7 +59,7 @@ struct ptdump_pg_state {
 
 void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
 void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
-	       u64 val);
+	       pteval_t val);
 void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte);
 void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
 void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud);
@@ -74,7 +74,7 @@ static inline void ptdump_debugfs_register(struct ptdump_info *info,
 #endif /* CONFIG_PTDUMP_DEBUGFS */
 #else
 static inline void note_page(struct ptdump_state *pt_st, unsigned long addr,
-			     int level, u64 val) { }
+			     int level, pteval_t val) { }
 static inline void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte) { }
 static inline void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd) { }
 static inline void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud) { }
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 0c66c8474a48..7950c0e9e89c 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -189,12 +189,12 @@ static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr)
 }
 
 void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
-	       u64 val)
+	       pteval_t val)
 {
 	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
 	struct ptdump_pg_level *pg_level = st->pg_level;
 	static const char units[] = "KMGTPE";
-	u64 prot = 0;
+	pteval_t prot = 0;
 
 	/* check if the current level has been folded dynamically */
 	if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) ||
-- 
2.25.1



From nicolas.frattaroli at collabora.com  Mon Mar 10 02:59:55 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 10 Mar 2025 10:59:55 +0100
Subject: [PATCH 0/2] Fix CPU and GPU clocks on RK3576
Message-ID: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>

As Jonas Karlman pointed out on the #linux-rockchip IRC channel on
Libera yesterday, mainline has once again chosen a different set of
clock IDs compared to downstream, with hugely detrimental effects to
mainline's ability to use SCMI for clock operations. This is because
TF-A will use the downstream IDs, and when we reclock things through
SCMI, TF-A will get the wrong clock ID from us.

So this series adds the three relevant clock IDs to the bindings in
patch 1, and then uses them in the SoC .dtsi in patch 2. That way, we
actually get functional GPU reclocking, and cpufreq will work as well.
As a bonus, we no longer change random unrelated clocks all over the
place, and it seems somewhat miraculous this didn't blow up in our faces
in a much bigger way before this.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
Nicolas Frattaroli (2):
      dt-bindings: clock: rk3576: add SCMI clocks
      arm64: dts: rockchip: fix RK3576 SCMI clock IDs

 arch/arm64/boot/dts/rockchip/rk3576.dtsi        | 18 +++++++++---------
 include/dt-bindings/clock/rockchip,rk3576-cru.h |  5 +++++
 2 files changed, 14 insertions(+), 9 deletions(-)
---
base-commit: f064b0a4aa5f2bc61c9611a23a7fc83855751626
change-id: 20250310-rk3576-scmi-clocks-a30655d70a72

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From nicolas.frattaroli at collabora.com  Mon Mar 10 02:59:56 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 10 Mar 2025 10:59:56 +0100
Subject: [PATCH 1/2] dt-bindings: clock: rk3576: add SCMI clocks
In-Reply-To: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
References: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
Message-ID: <20250310-rk3576-scmi-clocks-v1-1-e165deb034e8@collabora.com>

Mainline Linux uses different clock IDs from both downstream and
mainline TF-A, which both got them from downstream Linux. If we want to
control clocks through SCMI, we'll need to know about these IDs.

Add the relevant ones prefixed with SCMI_ to the header.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 include/dt-bindings/clock/rockchip,rk3576-cru.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/dt-bindings/clock/rockchip,rk3576-cru.h b/include/dt-bindings/clock/rockchip,rk3576-cru.h
index 25aed298ac2c2e2d37e2b441c9d92ac68801be6e..f576e61bec7041455e10ac18c92f3b33ec0760e3 100644
--- a/include/dt-bindings/clock/rockchip,rk3576-cru.h
+++ b/include/dt-bindings/clock/rockchip,rk3576-cru.h
@@ -589,4 +589,9 @@
 #define PCLK_EDP_S			569
 #define ACLK_KLAD			570
 
+/* SCMI clocks, use these when changing clocks through SCMI */
+#define SCMI_ARMCLK_L			10
+#define SCMI_ARMCLK_B			11
+#define SCMI_CLK_GPU			456
+
 #endif

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 10 02:59:57 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 10 Mar 2025 10:59:57 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: fix RK3576 SCMI clock IDs
In-Reply-To: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
References: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
Message-ID: <20250310-rk3576-scmi-clocks-v1-2-e165deb034e8@collabora.com>

Downstream Linux, and consequently both downstream and mainline TF-A,
all use a different set of clock IDs from mainline Linux. If we want to
fiddle with these clocks through SCMI, we'll need to use the right IDs.
If we don't do this we'll end up changing unrelated clocks all over the
place.

Change the clock IDs to the newly added SCMI clock IDs for the CPU and
GPU nodes, which are currently the only ones using SCMI clocks. This
fixes the terrible GPU performance, as we weren't reclocking it
properly.

Fixes: 57b1ce903966 ("arm64: dts: rockchip: Add rk3576 SoC base DT")
Reported-by: Jonas Karlman <jonas at kwiboo.se>
Closes: https://libera.irclog.whitequark.org/linux-rockchip/2025-03-09#1741542223-1741542875;
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3576.dtsi | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
index 8591065b575223a5eb2da70f723f16969aa2ecf7..1fddf298795e5c914a76d9779b6f8563ee15c8e3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -111,7 +111,7 @@ cpu_l0: cpu at 0 {
 			reg = <0x0>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <485>;
-			clocks = <&scmi_clk ARMCLK_L>;
+			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			#cooling-cells = <2>;
 			dynamic-power-coefficient = <120>;
@@ -124,7 +124,7 @@ cpu_l1: cpu at 1 {
 			reg = <0x1>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <485>;
-			clocks = <&scmi_clk ARMCLK_L>;
+			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -135,7 +135,7 @@ cpu_l2: cpu at 2 {
 			reg = <0x2>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <485>;
-			clocks = <&scmi_clk ARMCLK_L>;
+			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -146,7 +146,7 @@ cpu_l3: cpu at 3 {
 			reg = <0x3>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <485>;
-			clocks = <&scmi_clk ARMCLK_L>;
+			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -157,7 +157,7 @@ cpu_b0: cpu at 100 {
 			reg = <0x100>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
-			clocks = <&scmi_clk ARMCLK_B>;
+			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			#cooling-cells = <2>;
 			dynamic-power-coefficient = <320>;
@@ -170,7 +170,7 @@ cpu_b1: cpu at 101 {
 			reg = <0x101>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
-			clocks = <&scmi_clk ARMCLK_B>;
+			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -181,7 +181,7 @@ cpu_b2: cpu at 102 {
 			reg = <0x102>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
-			clocks = <&scmi_clk ARMCLK_B>;
+			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -192,7 +192,7 @@ cpu_b3: cpu at 103 {
 			reg = <0x103>;
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
-			clocks = <&scmi_clk ARMCLK_B>;
+			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
 		};
@@ -932,7 +932,7 @@ power-domain at RK3576_PD_VO1 {
 		gpu: gpu at 27800000 {
 			compatible = "rockchip,rk3576-mali", "arm,mali-bifrost";
 			reg = <0x0 0x27800000 0x0 0x200000>;
-			assigned-clocks = <&scmi_clk CLK_GPU>;
+			assigned-clocks = <&scmi_clk SCMI_CLK_GPU>;
 			assigned-clock-rates = <198000000>;
 			clocks = <&cru CLK_GPU>;
 			clock-names = "core";

-- 
2.48.1



From kevin_chen at aspeedtech.com  Mon Mar 10 03:05:37 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 10:05:37 +0000
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <2fd83d68-7104-4755-a0f0-8ce4a2601e09@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
 <2fd83d68-7104-4755-a0f0-8ce4a2601e09@kernel.org>
Message-ID: <TY0PR06MB496072786197162F19ED7DDD89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>

> On 04/03/2025 11:44, Kevin Chen wrote:
> > +
> > +static int aspeed_pcc_probe(struct platform_device *pdev) {
> > +	int rc;
> > +	struct aspeed_pcc_ctrl *pcc;
> > +	struct device *dev;
> > +	uint32_t fifo_size = PAGE_SIZE;
> > +
> > +	dev = &pdev->dev;
> 
> This goes to declaration.
OK. I will move it to declaration.

> 
> > +
> > +	pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL);
> 
> Maybe my previous comment was not clear, but you agreed with it. Anyway
> nothing improved here.
Could I reserve the pcc variable using for the pcc_ctrl data structure?
Pcc_ctrl data include the regmap/irq/io_port/dma/kfifo.
If I change the name to dev, it does not make sense for these data to be.

> 
> If you have 'dev' variable, use it.
Do you mean just use the pdev->dev not local dev variable?

> 
> > +	if (!pcc)
> > +		return -ENOMEM;
> > +
> > +	pcc->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
> 
> same here and everywhere else.
> 
> > +	if (IS_ERR(pcc->regmap)) {
> > +		dev_err(dev, "Couldn't get regmap\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
> > +	if (rc) {
> > +		dev_err(dev, "no pcc ports configured\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> > +	if (rc) {
> > +		dev_err(dev, "cannot set 64-bits DMA mask\n");
> > +		return rc;
> > +	}
> > +
> > +	pcc->dma.size = PCC_DMA_BUFSZ;
> > +	pcc->dma.virt = dmam_alloc_coherent(dev,
> > +					    pcc->dma.size,
> > +					    &pcc->dma.addr,
> > +					    GFP_KERNEL);
> > +	if (!pcc->dma.virt) {
> > +		dev_err(dev, "cannot allocate DMA buffer\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
> > +	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
> > +	if (rc) {
> > +		dev_err(dev, "cannot allocate kFIFO\n");
> 
> Drop
Agree.

> 
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* Disable PCC to clean up DMA buffer before request IRQ. */
> > +	rc = aspeed_pcc_disable(pcc);
> > +	if (rc) {
> > +		dev_err(dev, "Couldn't disable PCC\n");
> > +		goto err_free_kfifo;
> > +	}
> > +
> > +	pcc->irq = platform_get_irq(pdev, 0);
> > +	if (pcc->irq < 0) {
> > +		dev_err(dev, "Couldn't get IRQ\n");
> 
> Drop, core already prints this. Do not duplicate messages.
Agree.

> 
> > +		rc = -ENODEV;
> 
> Why not using pcc->irq as rc?
Agree.

> 
> > +		goto err_free_kfifo;
> > +	}
> > +
> Best regards,
> Krzysztof

From damon.ding at rock-chips.com  Mon Mar 10 03:09:20 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:09:20 +0800
Subject: [PATCH v7 10/15] drm/rockchip: analogix_dp: Add support to get
 panel from the DP AUX bus
In-Reply-To: <CAD=FV=WS_2JAKMyFFmrNtaN7-O4dh2hOXHc25FytDxXAjAr+5A@mail.gmail.com>
References: <20250224081325.96724-1-damon.ding@rock-chips.com>
 <20250224081325.96724-11-damon.ding@rock-chips.com>
 <CAD=FV=WS_2JAKMyFFmrNtaN7-O4dh2hOXHc25FytDxXAjAr+5A@mail.gmail.com>
Message-ID: <5dc47134-fabb-4f9c-acc3-8bf37d2cc733@rock-chips.com>

Hi Doug,

On 2025/2/25 9:42, Doug Anderson wrote:
> Hi,
> 
> On Mon, Feb 24, 2025 at 12:14?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>>
>> @@ -392,11 +393,27 @@ static const struct component_ops rockchip_dp_component_ops = {
>>          .unbind = rockchip_dp_unbind,
>>   };
>>
>> +static int rockchip_dp_link_panel(struct drm_dp_aux *aux)
>> +{
>> +       struct analogix_dp_plat_data *plat_data = analogix_dp_aux_to_plat_data(aux);
>> +       struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
>> +       int ret;
>> +
>> +       ret = drm_of_find_panel_or_bridge(dp->dev->of_node, 1, 0, &plat_data->panel, NULL);
>> +       if (ret && ret != -ENODEV)
>> +               return ret;
> 
> Can you explain why you treat -ENODEV as a non-error case here? Maybe
> this is for the non-eDP case (AKA the DP case) where there's no
> further panels or bridges? Maybe a comment would be helpful to remind
> us?
> 

I think the commit 86caee745e45 ("drm/rockchip: analogix_dp: allow to 
work without panel") can help the Analogix DP driver work when the 
bridge is driver-free or when the user uses the eDP IP as a DP.

And I will add some comments in the next version.

> 
>> +       ret = component_add(dp->dev, &rockchip_dp_component_ops);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return ret;
> 
> nit: the above could just be:
> 
> return component_add(dp->dev, &rockchip_dp_component_ops);
> 

Yeah, it is a good idea.

> 
>> @@ -448,9 +460,16 @@ static int rockchip_dp_probe(struct platform_device *pdev)
>>          if (IS_ERR(dp->adp))
>>                  return PTR_ERR(dp->adp);
>>
>> -       ret = component_add(dev, &rockchip_dp_component_ops);
>> -       if (ret)
>> -               return ret;
>> +       ret = devm_of_dp_aux_populate_bus(analogix_dp_get_aux(dp->adp), rockchip_dp_link_panel);
>> +       if (ret) {
>> +               if (ret != -ENODEV)
>> +                       return dev_err_probe(dp->dev, ret,
>> +                                            "failed to populate aux bus : %d\n", ret);
> 
> IIRC this -ENODEV case is for old legacy panels that aren't listed
> under the aux bus in the device tree. Maybe a comment would be helpful
> to remind us?

I will add a comment here if devm_of_dp_aux_populate_bus() returns -ENODEV.

> 
> nit: don't need the %d in your error message. dev_err_probe() already
> prints the error code.
> 

I will remove it in the next version.

> 
>> +               ret = rockchip_dp_link_panel(analogix_dp_get_aux(dp->adp));
>> +               if (ret)
>> +                       return ret;
>> +       }
>>
>>          return 0;
> 
> You can get rid of a few of your return cases by just returning "ret" here.
> 

Yeah, it is better.

> 
> -Doug
> 
> 

Best regards
Damon


From ryan at testtoast.com  Mon Mar 10 02:09:46 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:46 +1300
Subject: [PATCH v8 00/11] drm: sun4i: add Display Engine 3.3 (DE33) support
Message-ID: <20250310092345.31708-1-ryan@testtoast.com>

Hi All,

v8 of this patch adding support for the Allwinner DE33 display engine, used in the H616 family of SoCs. As discussed in the previous patchset [1] even though the DE3 and DE33 engines both support YUV, and the DE33 adds RCQ/DMA shadowing for hardware registers. This adds complexity to implementing YUV support because of the lack of support for appropriately timing these writes. Therefore v8 removes YUV support and the colorspace code refactoring to support that, leaving this patchset as the minimum changes required to support the DE33 engine with the current driver. A further patchset/RFC for the more extensive driver changes needed for YUV and ultimately HDMI support.

I have also decided to pull AFBC support out of this patchset to go with the YUV code. While relatively standalone and also applicable to RGB framebuffers, it is not required for RGB output and seems to fit much better with (and is more useful for) YUV support.

The upside is that this code is relatively less complex for RGB support with the existing driver, and the patches [2] for the TCON and LCD support for the H616 and Anbernic devices using this SoC can be applied directly on top of this smaller set (noting feedback on that set prompting a v2 which is WIP currently).

Original blurb below:

There is existing mainline support for the DE2 and DE3 AllWinner display pipeline IP blocks, used in the A64 and H6 among others, however the H700 (as well as the H616/H618 and the T507 automotive SoC) have a newer version of the Display Engine (v3.3/DE33) which adds additional high-resolution support as well as YUV colour formats and AFBC compression support.

This patch set adds DE33 support, following up from the previous RFC [1], with significant rework to break down the previous relatively complex set into more logical steps, detailed below.

1. Refactor the existing DE2/DE3 code in readiness to support YUV colour formats in the DE3 engine (patches 1-4).
2. Add YUV420 colour format support in the DE3 driver (patches 5-13).
3. Replace the is_de3 mixer flag with an enum to support multiple DE versions (patch 14).
4. Refactor the mixer, vi_scaler and some register code to merge common init code and more easily support multiple DE versions (patches 15-18).
5. Add Arm Frame Buffer Compression (AFBC) compressed buffer support to the DE3 driver. This is currently only supported for VI layers (for HW-decoded video output) but is well integrated into these changes and a subsequent patchset to enable the Video Engine is planned. (patch 19).
6. Add DT bindings for the DE33 engine. (patches 20-22).
7. Extend the DE2/3 driver for the DE33, comprising clock, mixer, vi_scaler, fmt and csc module support (patches 23-27).

Further patchsets are planned to support HDMI and the LCD timing controller present in these SoCs.

Regards,

Ryan

[1]: https://lore.kernel.org/linux-sunxi/7770397.EvYhyI6sBW at jernej-laptop/
[2]: https://lore.kernel.org/linux-sunxi/20250216092827.15444-1-ryan at testtoast.com/

Jernej Skrabec (7):
  drm: sun4i: de2/de3: add mixer version enum
  drm: sun4i: de2/de3: refactor mixer initialisation
  drm: sun4i: de2/de3: add generic blender register reference function
  drm: sun4i: de2/de3: use generic register reference function for layer
    configuration
  drm: sun4i: de33: vi_scaler: add Display Engine 3.3 (DE33) support
  drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support
  drm: sun4i: de33: mixer: add mixer configuration for the H616

Ryan Walklin (4):
  dt-bindings: allwinner: add H616 DE33 bus binding
  dt-bindings: allwinner: add H616 DE33 clock binding
  dt-bindings: allwinner: add H616 DE33 mixer binding
  clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support

 .../bus/allwinner,sun50i-a64-de2.yaml         |   7 +-
 .../clock/allwinner,sun8i-a83t-de2-clk.yaml   |   1 +
 .../allwinner,sun8i-a83t-de2-mixer.yaml       |  21 ++-
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c          |  25 +++
 drivers/gpu/drm/sun4i/sun8i_csc.c             |   4 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c           | 168 ++++++++++++++----
 drivers/gpu/drm/sun4i/sun8i_mixer.h           |  30 +++-
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c        |  27 ++-
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c       |   2 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  14 +-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c       |   6 +-
 11 files changed, 242 insertions(+), 63 deletions(-)

-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:47 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:47 +1300
Subject: [PATCH v8 01/11] drm: sun4i: de2/de3: add mixer version enum
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-2-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

The Allwinner DE2 and DE3 display engine mixers are currently identified
by a simple boolean flag. This will not scale to support additional DE
variants.

Convert the boolean flag to an enum.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>

--
Changelog v5..v6:
- Update struct comment regarding change from is_de3 flag to de_type
---
 drivers/gpu/drm/sun4i/sun8i_csc.c       |  4 ++--
 drivers/gpu/drm/sun4i/sun8i_mixer.c     | 14 ++++++++++++--
 drivers/gpu/drm/sun4i/sun8i_mixer.h     |  4 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c |  2 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c  |  8 ++++----
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c |  4 ++--
 6 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 58480d8e4f70..6f4a2e9c6fca 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -212,7 +212,7 @@ void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
 {
 	u32 base;
 
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type == sun8i_mixer_de3) {
 		sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer,
 						mode, encoding, range);
 		return;
@@ -228,7 +228,7 @@ void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
 {
 	u32 base;
 
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type == sun8i_mixer_de3) {
 		sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable);
 		return;
 	}
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 8b41d33baa30..2252bef19597 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -537,7 +537,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	base = sun8i_blender_base(mixer);
 
 	/* Reset registers and disable unused sub-engines */
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type == sun8i_mixer_de3) {
 		for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
 			regmap_write(mixer->engine.regs, i, 0);
 
@@ -628,6 +628,7 @@ static void sun8i_mixer_remove(struct platform_device *pdev)
 
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
 	.ccsc		= CCSC_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.scaler_mask	= 0xf,
 	.scanline_yuv	= 2048,
 	.ui_num		= 3,
@@ -636,6 +637,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
 
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
 	.ccsc		= CCSC_MIXER1_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.scaler_mask	= 0x3,
 	.scanline_yuv	= 2048,
 	.ui_num		= 1,
@@ -644,6 +646,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
 
 static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
 	.ccsc		= CCSC_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 432000000,
 	.scaler_mask	= 0xf,
 	.scanline_yuv	= 2048,
@@ -653,6 +656,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
 
 static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
 	.ccsc		= CCSC_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0xf,
 	.scanline_yuv	= 2048,
@@ -662,6 +666,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
 
 static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
 	.ccsc		= CCSC_MIXER1_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x3,
 	.scanline_yuv	= 2048,
@@ -670,6 +675,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
 };
 
 static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.de_type = sun8i_mixer_de2,
 	.vi_num = 2,
 	.ui_num = 1,
 	.scaler_mask = 0x3,
@@ -680,6 +686,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 
 static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
 	.ccsc		= CCSC_D1_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x3,
 	.scanline_yuv	= 2048,
@@ -689,6 +696,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
 
 static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
 	.ccsc		= CCSC_MIXER1_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x1,
 	.scanline_yuv	= 1024,
@@ -698,6 +706,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
 
 static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
 	.ccsc		= CCSC_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0xf,
 	.scanline_yuv	= 4096,
@@ -707,6 +716,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
 
 static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
 	.ccsc		= CCSC_MIXER1_LAYOUT,
+	.de_type	= sun8i_mixer_de2,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x3,
 	.scanline_yuv	= 2048,
@@ -716,7 +726,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
 
 static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
 	.ccsc		= CCSC_MIXER0_LAYOUT,
-	.is_de3		= true,
+	.de_type	= sun8i_mixer_de3,
 	.mod_rate	= 600000000,
 	.scaler_mask	= 0xf,
 	.scanline_yuv	= 4096,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index d7898c9c9cc0..7fe5ce20082a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -162,7 +162,7 @@ enum {
  * @ccsc: select set of CCSC base addresses from the enumeration above.
  * @mod_rate: module clock rate that needs to be set in order to have
  *	a functional block.
- * @is_de3: true, if this is next gen display engine 3.0, false otherwise.
+ * @de_type: sun8i_mixer_type enum representing the display engine generation.
  * @scaline_yuv: size of a scanline for VI scaler for YUV formats.
  */
 struct sun8i_mixer_cfg {
@@ -214,7 +214,7 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 static inline u32
 sun8i_blender_base(struct sun8i_mixer *mixer)
 {
-	return mixer->cfg->is_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
+	return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
 }
 
 static inline u32
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
index ae0806bccac7..504ffa0971a4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
@@ -93,7 +93,7 @@ static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel)
 {
 	int vi_num = mixer->cfg->vi_num;
 
-	if (mixer->cfg->is_de3)
+	if (mixer->cfg->de_type == sun8i_mixer_de3)
 		return DE3_VI_SCALER_UNIT_BASE +
 		       DE3_VI_SCALER_UNIT_SIZE * vi_num +
 		       DE3_UI_SCALER_UNIT_SIZE * (channel - vi_num);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 9c09d9c08496..a7a3a75ffd63 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -25,7 +25,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
 
 	ch_base = sun8i_channel_base(mixer, channel);
 
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type >= sun8i_mixer_de3) {
 		mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK |
 		       SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK;
 		val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA
@@ -483,7 +483,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 	if (!layer)
 		return ERR_PTR(-ENOMEM);
 
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type >= sun8i_mixer_de3) {
 		formats = sun8i_vi_layer_de3_formats;
 		format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
 	} else {
@@ -507,7 +507,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 
 	plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
 
-	if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) {
+	if (mixer->cfg->vi_num == 1 || mixer->cfg->de_type >= sun8i_mixer_de3) {
 		ret = drm_plane_create_alpha_property(&layer->plane);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't add alpha property\n");
@@ -524,7 +524,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 
 	supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
 			      BIT(DRM_COLOR_YCBCR_BT709);
-	if (mixer->cfg->is_de3)
+	if (mixer->cfg->de_type >= sun8i_mixer_de3)
 		supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
 
 	supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
index 7ba75011adf9..ad87ab395803 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
@@ -835,7 +835,7 @@ static const u32 bicubic4coefftab32[480] = {
 
 static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
 {
-	if (mixer->cfg->is_de3)
+	if (mixer->cfg->de_type == sun8i_mixer_de3)
 		return DE3_VI_SCALER_UNIT_BASE +
 		       DE3_VI_SCALER_UNIT_SIZE * channel;
 	else
@@ -956,7 +956,7 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 		cvphase = vphase;
 	}
 
-	if (mixer->cfg->is_de3) {
+	if (mixer->cfg->de_type >= sun8i_mixer_de3) {
 		u32 val;
 
 		if (format->hsub == 1 && format->vsub == 1)
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:48 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:48 +1300
Subject: [PATCH v8 02/11] drm: sun4i: de2/de3: refactor mixer initialisation
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-3-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

Now that the DE variant can be selected by enum, take the oppportunity
to factor out some common initialisation code to a separate function.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>

---
Changelog v1..v2:
- Combine base register allocation and initialisation in sun8i_mixer_init
- Whitespace fix

Changelog v4..v5:
- Remove trailing whitespace

Changelog v7..v8:
- Remove CSC configuration changes (logically better placed with future YUV support) making this the first patch in the series.
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 64 +++++++++++++++--------------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 2252bef19597..41815b42d6d2 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -425,6 +425,38 @@ static int sun8i_mixer_of_get_id(struct device_node *node)
 	return of_ep.id;
 }
 
+static void sun8i_mixer_init(struct sun8i_mixer *mixer)
+{
+	unsigned int base = sun8i_blender_base(mixer);
+	int plane_cnt, i;
+
+	/* Enable the mixer */
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Set background color to black */
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
+		     SUN8I_MIXER_BLEND_COLOR_BLACK);
+
+	/*
+	 * Set fill color of bottom plane to black. Generally not needed
+	 * except when VI plane is at bottom (zpos = 0) and enabled.
+	 */
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
+		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
+		     SUN8I_MIXER_BLEND_COLOR_BLACK);
+
+	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
+	for (i = 0; i < plane_cnt; i++)
+		regmap_write(mixer->engine.regs,
+			     SUN8I_MIXER_BLEND_MODE(base, i),
+			     SUN8I_MIXER_BLEND_MODE_DEF);
+
+	regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+}
+
 static int sun8i_mixer_bind(struct device *dev, struct device *master,
 			      void *data)
 {
@@ -433,8 +465,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sun8i_mixer *mixer;
 	void __iomem *regs;
-	unsigned int base;
-	int plane_cnt;
 	int i, ret;
 
 	/*
@@ -534,8 +564,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 
 	list_add_tail(&mixer->engine.list, &drv->engine_list);
 
-	base = sun8i_blender_base(mixer);
-
 	/* Reset registers and disable unused sub-engines */
 	if (mixer->cfg->de_type == sun8i_mixer_de3) {
 		for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
@@ -551,7 +579,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0);
 		regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0);
 		regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0);
-	} else {
+	} else if (mixer->cfg->de_type == sun8i_mixer_de2) {
 		for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4)
 			regmap_write(mixer->engine.regs, i, 0);
 
@@ -564,31 +592,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0);
 	}
 
-	/* Enable the mixer */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
-		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
-
-	/* Set background color to black */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
-		     SUN8I_MIXER_BLEND_COLOR_BLACK);
-
-	/*
-	 * Set fill color of bottom plane to black. Generally not needed
-	 * except when VI plane is at bottom (zpos = 0) and enabled.
-	 */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
-		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
-		     SUN8I_MIXER_BLEND_COLOR_BLACK);
-
-	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
-	for (i = 0; i < plane_cnt; i++)
-		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_BLEND_MODE(base, i),
-			     SUN8I_MIXER_BLEND_MODE_DEF);
-
-	regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
-			   SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+	sun8i_mixer_init(mixer);
 
 	return 0;
 
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:49 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:49 +1300
Subject: [PATCH v8 03/11] drm: sun4i: de2/de3: add generic blender register reference function
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-4-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

The DE2 and DE3 engines have a blender register range within the
mixer engine register map, whereas the DE33 separates this out into
a separate display group.

Prepare for this by adding a function to look the blender reference up,
with a subsequent patch to add a conditional based on the DE type.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 7fe5ce20082a..43c413052a22 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -217,6 +217,12 @@ sun8i_blender_base(struct sun8i_mixer *mixer)
 	return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE;
 }
 
+static inline struct regmap *
+sun8i_blender_regmap(struct sun8i_mixer *mixer)
+{
+	return mixer->engine.regs;
+}
+
 static inline u32
 sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
 {
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:50 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:50 +1300
Subject: [PATCH v8 04/11] drm: sun4i: de2/de3: use generic register reference function for layer configuration
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-5-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

Use the new blender register lookup function where required in the layer
commit and update code.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>

---
Changelog v2..v3:
- Refactor for 6.11 layer init/modesetting changes
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c    | 5 +++--
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 +++++--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 ++++--
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 41815b42d6d2..cc4da11e2c10 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -274,6 +274,7 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
 {
 	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
 	u32 bld_base = sun8i_blender_base(mixer);
+	struct regmap *bld_regs = sun8i_blender_regmap(mixer);
 	struct drm_plane_state *plane_state;
 	struct drm_plane *plane;
 	u32 route = 0, pipe_en = 0;
@@ -313,8 +314,8 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
 		pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
 	}
 
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+	regmap_write(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
+	regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
 		     pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
 
 	regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index b90e5edef4e8..7a21d32ff1e4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -23,6 +23,7 @@
 #include "sun8i_mixer.h"
 #include "sun8i_ui_layer.h"
 #include "sun8i_ui_scaler.h"
+#include "sun8i_vi_scaler.h"
 
 static void sun8i_ui_layer_update_alpha(struct sun8i_mixer *mixer, int channel,
 					int overlay, struct drm_plane *plane)
@@ -51,6 +52,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 {
 	struct drm_plane_state *state = plane->state;
 	u32 src_w, src_h, dst_w, dst_h;
+	struct regmap *bld_regs;
 	u32 bld_base, ch_base;
 	u32 outsize, insize;
 	u32 hphase, vphase;
@@ -59,6 +61,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 			 channel, overlay);
 
 	bld_base = sun8i_blender_base(mixer);
+	bld_regs = sun8i_blender_regmap(mixer);
 	ch_base = sun8i_channel_base(mixer, channel);
 
 	src_w = drm_rect_width(&state->src) >> 16;
@@ -103,10 +106,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 			 state->dst.x1, state->dst.y1);
 	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
-	regmap_write(mixer->engine.regs,
+	regmap_write(bld_regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
-	regmap_write(mixer->engine.regs,
+	regmap_write(bld_regs,
 		     SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
 		     outsize);
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index a7a3a75ffd63..3d81d23d0195 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -55,6 +55,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	struct drm_plane_state *state = plane->state;
 	const struct drm_format_info *format = state->fb->format;
 	u32 src_w, src_h, dst_w, dst_h;
+	struct regmap *bld_regs;
 	u32 bld_base, ch_base;
 	u32 outsize, insize;
 	u32 hphase, vphase;
@@ -66,6 +67,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 			 channel, overlay);
 
 	bld_base = sun8i_blender_base(mixer);
+	bld_regs = sun8i_blender_regmap(mixer);
 	ch_base = sun8i_channel_base(mixer, channel);
 
 	src_w = drm_rect_width(&state->src) >> 16;
@@ -183,10 +185,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 			 state->dst.x1, state->dst.y1);
 	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
-	regmap_write(mixer->engine.regs,
+	regmap_write(bld_regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
-	regmap_write(mixer->engine.regs,
+	regmap_write(bld_regs,
 		     SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
 		     outsize);
 
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:51 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:51 +1300
Subject: [PATCH v8 05/11] dt-bindings: allwinner: add H616 DE33 bus binding
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-6-ryan@testtoast.com>

The Allwinner H616 and variants have a new display engine revision
(DE33).

Add a display engine bus binding for the DE33 and increase reg maxItems
to 3 to accommodate additional register blocks.

Signed-off-by: Ryan Walklin <ryan at testtoast.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>

---
Changelog v1..v2:
- Correct DE2 bus enum to reflect fallback devices accurately.

Changelog v2..v3:
- Separate content into three patches for three separate subsystems

Changelog v5..v6:
- Increase reg maxItems to 3.
---
 .../devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml  | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
index 9845a187bdf6..317a27cf590b 100644
--- a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
+++ b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
@@ -24,11 +24,14 @@ properties:
     oneOf:
       - const: allwinner,sun50i-a64-de2
       - items:
-          - const: allwinner,sun50i-h6-de3
+          - enum:
+              - allwinner,sun50i-h6-de3
+              - allwinner,sun50i-h616-de33
           - const: allwinner,sun50i-a64-de2
 
   reg:
-    maxItems: 1
+    minItems: 1
+    maxItems: 3
 
   allwinner,sram:
     description:
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:52 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:52 +1300
Subject: [PATCH v8 06/11] dt-bindings: allwinner: add H616 DE33 clock binding
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-7-ryan@testtoast.com>

The Allwinner H616 and variants have a new display engine revision
(DE33).

Add a clock binding for the DE33.

Signed-off-by: Ryan Walklin <ryan at testtoast.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>

---
Changelog v2..v3:
- Separate content into three patches for three separate subsystems
---
 .../devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml  | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
index 70369bd633e4..7fcd55d468d4 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml
@@ -25,6 +25,7 @@ properties:
       - const: allwinner,sun50i-a64-de2-clk
       - const: allwinner,sun50i-h5-de2-clk
       - const: allwinner,sun50i-h6-de3-clk
+      - const: allwinner,sun50i-h616-de33-clk
       - items:
           - const: allwinner,sun8i-r40-de2-clk
           - const: allwinner,sun8i-h3-de2-clk
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:53 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:53 +1300
Subject: [PATCH v8 07/11] dt-bindings: allwinner: add H616 DE33 mixer binding
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-8-ryan@testtoast.com>

The Allwinner H616 and variants have a new display engine revision
(DE33).

The mixer configuration registers are significantly different to the DE3
and DE2 revisions, being split into separate top and display blocks,
therefore a fallback for the mixer compatible is not provided.

Add a display engine mixer binding for the DE33.

Signed-off-by: Ryan Walklin <ryan at testtoast.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Reviewed-by: Chen-Yu Tsai <wens at csie.org>

---
Changelog v2..v3:
- Separate content into three patches for three separate subsystems

Changelog v5..v6:
- increase reg maxItems to 3 and add conditional for h616-de33
---
 .../allwinner,sun8i-a83t-de2-mixer.yaml       | 21 ++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
index b75c1ec686ad..274f5e632733 100644
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
@@ -24,9 +24,11 @@ properties:
       - allwinner,sun50i-a64-de2-mixer-0
       - allwinner,sun50i-a64-de2-mixer-1
       - allwinner,sun50i-h6-de3-mixer-0
+      - allwinner,sun50i-h616-de33-mixer-0
 
   reg:
-    maxItems: 1
+    minItems: 1
+    maxItems: 3
 
   clocks:
     items:
@@ -61,6 +63,23 @@ properties:
     required:
       - port at 1
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun50i-h616-de33-mixer-0
+
+    then:
+      properties:
+        reg:
+          maxItems: 3
+
+    else:
+      properties:
+        reg:
+          maxItems: 1
+
 required:
   - compatible
   - reg
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:54 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:54 +1300
Subject: [PATCH v8 08/11] clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-9-ryan@testtoast.com>

The DE33 is a newer version of the Allwinner Display Engine IP block,
found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already
supported by the mainline driver.

The DE33 in the H616 has mixer0 and writeback units. The clocks
and resets required are identical to the H3 and H5 respectively, so use
those existing structs for the H616 description.

There are two additional 32-bit registers (at offsets 0x24 and 0x28)
which require clearing and setting respectively to bring up the
hardware. The function of these registers is currently unknown, and the
values are taken from the out-of-tree driver.

Add the required clock description struct and compatible string to the
DE2 driver.

Signed-off-by: Ryan Walklin <ryan at testtoast.com>

---
Changelog v2..v3:
- Lowercase hex value

Changelog v2..v3:
- Correct #include for writel()

Changelog v4..v5:
- Whitespace fix
---
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index f2aa71206bc2..a6cd0f988859 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -5,6 +5,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -239,6 +240,16 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = {
 	.num_resets	= ARRAY_SIZE(sun50i_h5_de2_resets),
 };
 
+static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = {
+	.ccu_clks	= sun8i_de2_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun8i_de2_ccu_clks),
+
+	.hw_clks	= &sun8i_h3_de2_hw_clks,
+
+	.resets		= sun50i_h5_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_h5_de2_resets),
+};
+
 static int sunxi_de2_clk_probe(struct platform_device *pdev)
 {
 	struct clk *bus_clk, *mod_clk;
@@ -291,6 +302,16 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
 		goto err_disable_mod_clk;
 	}
 
+	/*
+	 * The DE33 requires these additional (unknown) registers set
+	 * during initialisation.
+	 */
+	if (of_device_is_compatible(pdev->dev.of_node,
+				    "allwinner,sun50i-h616-de33-clk")) {
+		writel(0, reg + 0x24);
+		writel(0x0000a980, reg + 0x28);
+	}
+
 	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc);
 	if (ret)
 		goto err_assert_reset;
@@ -335,6 +356,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = {
 		.compatible = "allwinner,sun50i-h6-de3-clk",
 		.data = &sun50i_h5_de2_clk_desc,
 	},
+	{
+		.compatible = "allwinner,sun50i-h616-de33-clk",
+		.data = &sun50i_h616_de33_clk_desc,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids);
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:55 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:55 +1300
Subject: [PATCH v8 09/11] drm: sun4i: de33: vi_scaler: add Display Engine 3.3 (DE33) support
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-10-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

The vi_scaler appears to be used in preference to the ui_scaler module
for hardware video scaling in the DE33.

Enable support for this scaler.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>
---
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c  | 20 ++++++++++++++++----
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c |  4 +++-
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 7a21d32ff1e4..3eefdb710dee 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -94,12 +94,24 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 		hscale = state->src_w / state->crtc_w;
 		vscale = state->src_h / state->crtc_h;
 
-		sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w,
-				      dst_h, hscale, vscale, hphase, vphase);
-		sun8i_ui_scaler_enable(mixer, channel, true);
+		if (mixer->cfg->de_type == sun8i_mixer_de33) {
+			sun8i_vi_scaler_setup(mixer, channel, src_w, src_h,
+					      dst_w, dst_h, hscale, vscale,
+					      hphase, vphase,
+					      state->fb->format);
+			sun8i_vi_scaler_enable(mixer, channel, true);
+		} else {
+			sun8i_ui_scaler_setup(mixer, channel, src_w, src_h,
+					      dst_w, dst_h, hscale, vscale,
+					      hphase, vphase);
+			sun8i_ui_scaler_enable(mixer, channel, true);
+		}
 	} else {
 		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
-		sun8i_ui_scaler_enable(mixer, channel, false);
+		if (mixer->cfg->de_type == sun8i_mixer_de33)
+			sun8i_vi_scaler_enable(mixer, channel, false);
+		else
+			sun8i_ui_scaler_enable(mixer, channel, false);
 	}
 
 	/* Set base coordinates */
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
index ad87ab395803..6839fd5ab602 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
@@ -835,7 +835,9 @@ static const u32 bicubic4coefftab32[480] = {
 
 static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
 {
-	if (mixer->cfg->de_type == sun8i_mixer_de3)
+	if (mixer->cfg->de_type == sun8i_mixer_de33)
+		return sun8i_channel_base(mixer, channel) + 0x3000;
+	else if (mixer->cfg->de_type == sun8i_mixer_de3)
 		return DE3_VI_SCALER_UNIT_BASE +
 		       DE3_VI_SCALER_UNIT_SIZE * channel;
 	else
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:56 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:56 +1300
Subject: [PATCH v8 10/11] drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-11-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

The DE33 is a newer version of the Allwinner Display Engine IP block,
found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already
supported by the mainline driver.

Notable features (from the H616 datasheet and implemented):
- 4096 x 2048 (4K) output support

Other features (implemented but not in this patchset):
- AFBC ARM Frame Buffer Compression support
- YUV pipeline support

The DE2 and DE3 engines have a blender register range within the
mixer engine register map, whereas the DE33 separates this out into
a separate display group, and adds a top register map.

The DE33 also appears to remove the global double buffer control
register, present in the DE2 and DE3.

Extend the mixer to support the DE33.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>

---
Changelog v4..v5:
- Whitespace fixes
- Correct strict mode warnings from checkpatch.pl

Changelog v7..v8:
- Add top/disp regmaps to mixer for DE33
- Remove YUV-specific code
- Remove use of global double buffer
- Remove unneeded if/then parentheses and fix an alignment issue as suggested by checkpatch.pl
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 82 +++++++++++++++++++++++++----
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 22 ++++++--
 2 files changed, 90 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cc4da11e2c10..0bfd4b28b283 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -318,8 +318,9 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
 	regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
 		     pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
 
-	regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
-		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+	if (mixer->cfg->de_type != sun8i_mixer_de33)
+		regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+			     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
 static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
@@ -368,25 +369,31 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
 				 const struct drm_display_mode *mode)
 {
 	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+	struct regmap *bld_regs;
 	u32 bld_base, size, val;
 	bool interlaced;
 
 	bld_base = sun8i_blender_base(mixer);
+	bld_regs = sun8i_blender_regmap(mixer);
 	interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
 	size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay);
 
 	DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
 			 mode->hdisplay, mode->vdisplay);
 
-	regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size);
-	regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
+	if (mixer->cfg->de_type == sun8i_mixer_de33)
+		regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_SIZE, size);
+	else
+		regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, size);
+
+	regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
 
 	if (interlaced)
 		val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
 	else
 		val = 0;
 
-	regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
+	regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
 			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
 
 	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
@@ -400,12 +407,29 @@ static const struct sunxi_engine_ops sun8i_engine_ops = {
 };
 
 static const struct regmap_config sun8i_mixer_regmap_config = {
+	.name		= "layers",
 	.reg_bits	= 32,
 	.val_bits	= 32,
 	.reg_stride	= 4,
 	.max_register	= 0xffffc, /* guessed */
 };
 
+static const struct regmap_config sun8i_top_regmap_config = {
+	.name		= "top",
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0x3c,
+};
+
+static const struct regmap_config sun8i_disp_regmap_config = {
+	.name		= "display",
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0x20000,
+};
+
 static int sun8i_mixer_of_get_id(struct device_node *node)
 {
 	struct device_node *ep, *remote;
@@ -428,33 +452,45 @@ static int sun8i_mixer_of_get_id(struct device_node *node)
 
 static void sun8i_mixer_init(struct sun8i_mixer *mixer)
 {
+	struct regmap *top_regs, *disp_regs;
 	unsigned int base = sun8i_blender_base(mixer);
 	int plane_cnt, i;
 
+	if (mixer->cfg->de_type == sun8i_mixer_de33) {
+		top_regs = mixer->top_regs;
+		disp_regs = mixer->disp_regs;
+	} else {
+		top_regs = mixer->engine.regs;
+		disp_regs = mixer->engine.regs;
+	}
+
 	/* Enable the mixer */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
+	regmap_write(top_regs, SUN8I_MIXER_GLOBAL_CTL,
 		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
 
+	if (mixer->cfg->de_type == sun8i_mixer_de33)
+		regmap_write(top_regs, SUN50I_MIXER_GLOBAL_CLK, 1);
+
 	/* Set background color to black */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
+	regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
 	/*
 	 * Set fill color of bottom plane to black. Generally not needed
 	 * except when VI plane is at bottom (zpos = 0) and enabled.
 	 */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
+	regmap_write(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
 		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
+	regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
 	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
 	for (i = 0; i < plane_cnt; i++)
-		regmap_write(mixer->engine.regs,
+		regmap_write(disp_regs,
 			     SUN8I_MIXER_BLEND_MODE(base, i),
 			     SUN8I_MIXER_BLEND_MODE_DEF);
 
-	regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
+	regmap_update_bits(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
 			   SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
 }
 
@@ -526,6 +562,30 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		return PTR_ERR(mixer->engine.regs);
 	}
 
+	if (mixer->cfg->de_type == sun8i_mixer_de33) {
+		regs = devm_platform_ioremap_resource(pdev, 1);
+		if (IS_ERR(regs))
+			return PTR_ERR(regs);
+
+		mixer->top_regs = devm_regmap_init_mmio(dev, regs,
+							&sun8i_top_regmap_config);
+		if (IS_ERR(mixer->top_regs)) {
+			dev_err(dev, "Couldn't create the top regmap\n");
+			return PTR_ERR(mixer->top_regs);
+		}
+
+		regs = devm_platform_ioremap_resource(pdev, 2);
+		if (IS_ERR(regs))
+			return PTR_ERR(regs);
+
+		mixer->disp_regs = devm_regmap_init_mmio(dev, regs,
+							 &sun8i_disp_regmap_config);
+		if (IS_ERR(mixer->disp_regs)) {
+			dev_err(dev, "Couldn't create the disp regmap\n");
+			return PTR_ERR(mixer->disp_regs);
+		}
+	}
+
 	mixer->reset = devm_reset_control_get(dev, NULL);
 	if (IS_ERR(mixer->reset)) {
 		dev_err(dev, "Couldn't get our reset line\n");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 43c413052a22..d87d197610e1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -21,6 +21,9 @@
 #define SUN8I_MIXER_GLOBAL_DBUFF		0x8
 #define SUN8I_MIXER_GLOBAL_SIZE			0xc
 
+#define SUN50I_MIXER_GLOBAL_SIZE		0x8
+#define SUN50I_MIXER_GLOBAL_CLK			0xc
+
 #define SUN8I_MIXER_GLOBAL_CTL_RT_EN		BIT(0)
 
 #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		BIT(0)
@@ -151,6 +154,12 @@ enum {
 	CCSC_D1_MIXER0_LAYOUT,
 };
 
+enum sun8i_mixer_type {
+	sun8i_mixer_de2,
+	sun8i_mixer_de3,
+	sun8i_mixer_de33,
+};
+
 /**
  * struct sun8i_mixer_cfg - mixer HW configuration
  * @vi_num: number of VI channels
@@ -171,8 +180,9 @@ struct sun8i_mixer_cfg {
 	int		scaler_mask;
 	int		ccsc;
 	unsigned long	mod_rate;
-	unsigned int	is_de3 : 1;
+	unsigned int	de_type;
 	unsigned int	scanline_yuv;
+	unsigned int	map[6];
 };
 
 struct sun8i_mixer {
@@ -184,6 +194,9 @@ struct sun8i_mixer {
 
 	struct clk			*bus_clk;
 	struct clk			*mod_clk;
+
+	struct regmap			*top_regs;
+	struct regmap			*disp_regs;
 };
 
 enum {
@@ -220,13 +233,16 @@ sun8i_blender_base(struct sun8i_mixer *mixer)
 static inline struct regmap *
 sun8i_blender_regmap(struct sun8i_mixer *mixer)
 {
-	return mixer->engine.regs;
+	return mixer->cfg->de_type == sun8i_mixer_de33 ?
+		mixer->disp_regs : mixer->engine.regs;
 }
 
 static inline u32
 sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
 {
-	if (mixer->cfg->is_de3)
+	if (mixer->cfg->de_type == sun8i_mixer_de33)
+		return mixer->cfg->map[channel] * 0x20000 + DE2_CH_SIZE;
+	else if (mixer->cfg->de_type == sun8i_mixer_de3)
 		return DE3_CH_BASE + channel * DE3_CH_SIZE;
 	else
 		return DE2_CH_BASE + channel * DE2_CH_SIZE;
-- 
2.48.1



From ryan at testtoast.com  Mon Mar 10 02:09:57 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:09:57 +1300
Subject: [PATCH v8 11/11] drm: sun4i: de33: mixer: add mixer configuration for the H616
In-Reply-To: <20250310092345.31708-1-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
Message-ID: <20250310092345.31708-12-ryan@testtoast.com>

From: Jernej Skrabec <jernej.skrabec at gmail.com>

The H616 (and related SoC packages sharing the same die) carry the new
DE33 display engine.

Add the mixer configuration and a compatible string for the H616 to the
mixer.

Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Ryan Walklin <ryan at testtoast.com>

--
Changelog v7..v8:
- Separate DE33 support and H616 enablement in the mixer.
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 0bfd4b28b283..c9211a173a13 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -799,6 +799,17 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
 	.vi_num		= 1,
 };
 
+static const struct sun8i_mixer_cfg sun50i_h616_mixer0_cfg = {
+	.ccsc		= CCSC_MIXER0_LAYOUT,
+	.de_type	= sun8i_mixer_de33,
+	.mod_rate	= 600000000,
+	.scaler_mask	= 0xf,
+	.scanline_yuv	= 4096,
+	.ui_num		= 3,
+	.vi_num		= 1,
+	.map		= {0, 6, 7, 8},
+};
+
 static const struct of_device_id sun8i_mixer_of_table[] = {
 	{
 		.compatible = "allwinner,sun8i-a83t-de2-mixer-0",
@@ -844,6 +855,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
 		.compatible = "allwinner,sun50i-h6-de3-mixer-0",
 		.data = &sun50i_h6_mixer0_cfg,
 	},
+	{
+		.compatible = "allwinner,sun50i-h616-de33-mixer-0",
+		.data = &sun50i_h616_mixer0_cfg,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
-- 
2.48.1



From tudor.ambarus at linaro.org  Mon Mar 10 02:26:06 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 10 Mar 2025 09:26:06 +0000
Subject: [PATCH] mailbox: Remove unneeded semicolon
In-Reply-To: <20250310082628.845544-1-nichen@iscas.ac.cn>
References: <20250310082628.845544-1-nichen@iscas.ac.cn>
Message-ID: <282d3519-8ea6-4a42-97e2-d4cb9ad80c96@linaro.org>



On 3/10/25 8:26 AM, Chen Ni wrote:
> Remove unnecessary semicolons reported by Coccinelle/coccicheck and the
> semantic patch at scripts/coccinelle/misc/semicolon.cocci.
> 
> Signed-off-by: Chen Ni <nichen at iscas.ac.cn>

thanks, Chen!

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> ---
>  drivers/mailbox/exynos-mailbox.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mailbox/exynos-mailbox.c b/drivers/mailbox/exynos-mailbox.c
> index 20049f0ec5ff..2320649bf60c 100644
> --- a/drivers/mailbox/exynos-mailbox.c
> +++ b/drivers/mailbox/exynos-mailbox.c
> @@ -57,7 +57,7 @@ static int exynos_mbox_send_data(struct mbox_chan *chan, void *data)
>  	if (msg->chan_type != EXYNOS_MBOX_CHAN_TYPE_DOORBELL) {
>  		dev_err(dev, "Unsupported channel type [%d]\n", msg->chan_type);
>  		return -EINVAL;
> -	};
> +	}
>  
>  	writel(BIT(msg->chan_id), exynos_mbox->regs + EXYNOS_MBOX_INTGR1);
>  



From krzk at kernel.org  Mon Mar 10 02:28:44 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 10:28:44 +0100
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <20250307220304.247725-8-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
Message-ID: <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>

On Fri, Mar 07, 2025 at 02:02:59PM -0800, Roman Kisel wrote:
> To boot on ARM64, VMBus requires configuring interrupts. Missing
> DMA coherence property is sub-optimal as the VMBus transations are
> cache-coherent.
> 
> Add interrupts to be able to boot on ARM64. Add DMA coherence to
> avoid doing extra work on maintaining caches on ARM64.

How do you add it?

> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  .../devicetree/bindings/bus/microsoft,vmbus.yaml          | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
> index a8d40c766dcd..3ab7d0116626 100644
> --- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
> +++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
> @@ -28,13 +28,16 @@ properties:
>  required:
>    - compatible
>    - ranges
> +  - interrupts
>    - '#address-cells'
>    - '#size-cells'
>  
> -additionalProperties: false
> +additionalProperties: true

This is neither explained in commit msg nor correct.

Drop the change. You cannot have device bindings ending with 'true'
here - see talks, example-bindings, writing-schema and whatever resource
is there.

Best regards,
Krzysztof



From sudeep.holla at arm.com  Mon Mar 10 02:29:01 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 10 Mar 2025 09:29:01 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
References: <Z6uFMW94QNpFxQLK@bogus>
 <20250212070120.GD15796@localhost.localdomain>
 <Z6x8cNyDt8rJ73_B@bogus>
 <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto>
 <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus>
 <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
Message-ID: <Z86w3ZRS6T2MvV3X@bogus>

On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
>
> Sorry, if I misunderstood.
>
> I will give a look on this and propose a RFC.
>
> DT maintainers may ask for a patchset including binding change and
> driver changes to get a whole view on the compatible stuff.
>
> BTW, Cristian, Saravana if you have any objections/ideas or would take on this
> effort, please let me know.
>

Can you point me to the DTS with which you are seeing this issue ?
I am trying to reproduce the issue but so far not successful. I did
move to power-domains for CPUFreq on Juno. IIUC all we need is both cpufreq
and performance genpd drivers in the kernel and then GPU using perf genpd
fails with probe deferral right ? I need pointers to reproduce the issue
so that I can check if what I have cooked up as a solution really works.

--
Regards,
Sudeep


From ryan at testtoast.com  Mon Mar 10 02:30:36 2025
From: ryan at testtoast.com (Ryan Walklin)
Date: Mon, 10 Mar 2025 22:30:36 +1300
Subject: [PATCH v7 22/27] dt-bindings: allwinner: add H616 DE33 mixer binding
In-Reply-To: <20250224175642.170c124e@donnerap.manchester.arm.com>
References: <20250216183710.8443-3-ryan@testtoast.com>
 <20250216183710.8443-23-ryan@testtoast.com>
 <20250224175642.170c124e@donnerap.manchester.arm.com>
Message-ID: <c8b85753-5c97-4258-a158-06a17929fad6@app.fastmail.com>

On Tue, 25 Feb 2025, at 6:56 AM, Andre Przywara wrote:

Apologies Andre, I came to review your comments on the TCON series and realised I had missed responding to this comment before sending v8. 

>> +      - allwinner,sun50i-h616-de33-mixer-0
>>  
>>    reg:
>> -    maxItems: 1
>> +    minItems: 1
>> +    maxItems: 3
>
> What are those three regions? I wonder if we should have reg-names here,
> to fix the order, and to document them on the way?

This would be the top, display and mixer groups for the DE333, and mixer for DE3 and earlier. Can certainly add in names for these. Is there any example elsewhere in the bindings to look at?

>> @@ -61,6 +63,23 @@ properties:
>>      required:
>>        - port at 1
>>  
>> +allOf:
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          enum:
>> +            - allwinner,sun50i-h616-de33-mixer-0
>> +
>> +    then:
>> +      properties:
>> +        reg:
>> +          maxItems: 3
>
> Should we override minItems here as well? I guess any driver would need
> all three region to work?

This seems sensible, as you say it would always be 3 groups for the DE33.

Regards,

Ryan


From wbg at kernel.org  Mon Mar 10 02:35:11 2025
From: wbg at kernel.org (William Breathitt Gray)
Date: Mon, 10 Mar 2025 18:35:11 +0900
Subject: [PATCH 2/2] counter: microchip-tcb-capture: Add support for RC
 Compare
In-Reply-To: <790f00da-d66e-42bc-bae2-339144fbec95@prolan.hu>
References: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
 <20250306-introduce-compare-component-v1-2-93993b3dca9c@kernel.org>
 <790f00da-d66e-42bc-bae2-339144fbec95@prolan.hu>
Message-ID: <Z86yT0WoGbX7JXND@ishi>

On Mon, Mar 10, 2025 at 09:38:13AM +0100, Cs?k?s Bence wrote:
> Hi,
> 
> On 2025. 03. 06. 8:05, William Breathitt Gray wrote:
> > In Capture mode, the RC register serves as a compare register for the
> > Timer Counter Channel. When a the Counter Value reaches the RC value, a
> > RC Compare event occurs (COUNTER_EVENT_THRESHOLD). This patch exposes
> > the RC register to userspace as the 'compare' Count extension, thus
> > allowing users to configure the threshold condition for these events.
> > 
> > Signed-off-by: William Breathitt Gray <wbg at kernel.org>
> 
> I'm assuming you'll merge it with my capture extensions patch. Will this
> `compare` extension be carried over to 104-quad-8 as well? Otherwise:
> 
> Acked-by: Bence Cs?k?s <csokas.bence at prolan.hu>
> 
> Bence

Thank you for the Ack, I've merged this series now and pushed it to
counter-next.

The compare functionality is already exposed through the `preset`
component in the 104-quad-8 module, so I decided not to add a `compare`
because it felt redundant. However, I'm certain `compare` will be useful
in future drivers so that's why I want to get it merged with the rest of
the microchip-tcb-capture changes. :-)

Best regards,

William Breathitt Gray
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/76dd1ef8/attachment.sig>

From leo.yan at arm.com  Mon Mar 10 02:37:08 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 09:37:08 +0000
Subject: [PATCH] arm64: dts: hi3660: Add property for fixing CPUIdle
Message-ID: <20250310093708.9332-1-leo.yan@arm.com>

During CPU low power modes, ETM components will lose their context.  Add
the "arm,coresight-loses-context-with-cpu" property to ETM nodes to save
and restore ETM context for CPU idle states.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
index 79a55a0fa2f1..4c6a075908d1 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
@@ -17,6 +17,7 @@ etm at ecc40000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu0>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -34,6 +35,7 @@ etm at ecd40000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu1>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -51,6 +53,7 @@ etm at ece40000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu2>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -68,6 +71,7 @@ etm at ecf40000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu3>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -160,6 +164,7 @@ etm at ed440000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu4>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -177,6 +182,7 @@ etm at ed540000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu5>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -194,6 +200,7 @@ etm at ed640000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu6>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
@@ -211,6 +218,7 @@ etm at ed740000 {
 			clocks = <&crg_ctrl HI3660_PCLK>;
 			clock-names = "apb_pclk";
 			cpu = <&cpu7>;
+			arm,coresight-loses-context-with-cpu;
 
 			out-ports {
 				port {
-- 
2.34.1



From richard.weiyang at gmail.com  Mon Mar 10 02:42:38 2025
From: richard.weiyang at gmail.com (Wei Yang)
Date: Mon, 10 Mar 2025 09:42:38 +0000
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <Z86ikkLVHQhLmBWj@kernel.org>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250224013131.fzz552bn7fs64umq@master>
 <Z711VP45tjBi0kwx@kernel.org>
 <20250226020915.ytxusrrl7rv4g64l@master>
 <20250310075627.5hettrn2j2ien5bj@master>
 <Z86ikkLVHQhLmBWj@kernel.org>
Message-ID: <20250310094238.lgsiyqci3aqdzrhj@master>

On Mon, Mar 10, 2025 at 10:28:02AM +0200, Mike Rapoport wrote:
>Hi Wei,
>
>On Mon, Mar 10, 2025 at 07:56:27AM +0000, Wei Yang wrote:
>> On Wed, Feb 26, 2025 at 02:09:15AM +0000, Wei Yang wrote:
>> >>> 
>> >>> From the above call flow and background, there are three cases when
>> >>> memblock_alloc_range_nid() would be called:
>> >>> 
>> >>>   * If it is called before (1), memblock.reserved's nid would be adjusted correctly.
>> >>>   * If it is called after (2), we don't touch memblock.reserved.
>> >>>   * If it happens between (1) and (2), it looks would break the consistency of
>> >>>     nid information in memblock.reserved. Because when we use
>> >>>     memblock_reserve_kern(), NUMA_NO_NODE would be stored in region.
>> >>> 
>> >>> So my question is if the third case happens, would it introduce a bug? If it
>> >>> won't happen, seems we don't need to specify the nid here?
>> >>
>> >>We don't really care about proper assignment of nodes between (1) and (2)
>> >>from one side and the third case does not happen on the other side. Nothing
>> >>should call membloc_alloc() after memblock_free_all(). 
>> >>
>> >
>> >My point is if no one would call memblock_alloc() after memblock_free_all(),
>> >which set nid in memblock.reserved properly, it seems not necessary to do
>> >__memblock_reserve() with exact nid during memblock_alloc()? 
>> >
>> >As you did __memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN) in this
>> >patch.
>> >
>> 
>> Hi, Mike
>> 
>> Do you think my understanding is reasonable?
>
>Without KHO it is indeed not strictly necessary to set nid during memblock_alloc().
>But since we anyway have nid parameter in memblock_alloc_range_nid() and it
>anyway propagates to memblock_add_range(), I think it's easier and cleaner
>to pass nid to __memblock_reserve() there.
>
>And for KHO estimation of scratch size it is important to have nid assigned to
>the reserved areas before memblock_free_all(), at least for the allocations
>that request particular nid explicitly.

Thanks, I see your point.

> 
>> -- 
>> Wei Yang
>> Help you, Help me
>
>-- 
>Sincerely yours,
>Mike.

-- 
Wei Yang
Help you, Help me


From konrad.dybcio at oss.qualcomm.com  Mon Mar 10 02:46:09 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Mon, 10 Mar 2025 10:46:09 +0100
Subject: [PATCH v15 10/10] arm64: dts: qcom: sa8775p: Add CTCU and ETR
 nodes
In-Reply-To: <942d0b2f-c3c1-466d-b894-9dd32ec4e6a1@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
 <20250303032931.2500935-11-quic_jiegan@quicinc.com>
 <0be31ecd-4386-4eb6-ad6f-a4409a3fc6ad@arm.com>
 <942d0b2f-c3c1-466d-b894-9dd32ec4e6a1@quicinc.com>
Message-ID: <dcbdeb90-d274-4914-84d3-24bd1d6e826e@oss.qualcomm.com>

On 10.03.2025 3:57 AM, Jie Gan wrote:
> 
> 
> On 3/4/2025 8:28 PM, Suzuki K Poulose wrote:
>> On 03/03/2025 03:29, Jie Gan wrote:
>>> Add CTCU and ETR nodes in DT to enable related functionalities.
>>>
>>> Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
>>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>>
>> Assuming this goes via the soc tree,
>>
>> Acked-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Hi Bjorn, Konrad
> 
> Gentle ping.
> 
> The driver part has applied. BTW, I found this patch has a conflict on tag next-20250307, do you need me to send a new rebased patch?

Yes, please resend this just this one, rebased on next/master

Konrad


From krzk at kernel.org  Mon Mar 10 02:57:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 10:57:13 +0100
Subject: [PATCH v2 1/3] dt-bindings: net: rockchip-dwmac: Require
 rockchip,grf and rockchip,php-grf
In-Reply-To: <20250308213720.2517944-2-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
 <20250308213720.2517944-2-jonas@kwiboo.se>
Message-ID: <20250310-striped-perfect-sambar-bdcb3e@krzk-bin>

On Sat, Mar 08, 2025 at 09:37:13PM +0000, Jonas Karlman wrote:
> All Rockchip GMAC variants typically write to GRF regs to control e.g.
> interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3562,
> RK3576 and RK3588 use a mix of GRF and peripheral GRF regs.
> 
> Prior to the commit b331b8ef86f0 ("dt-bindings: net: convert
> rockchip-dwmac to json-schema") the property rockchip,grf was listed
> under "Required properties". During the conversion this was lost and
> rockchip,grf has since then incorrectly been treated as optional and
> not as required.
> 
> Similarly, when rockchip,php-grf was added to the schema in the
> commit a2b77831427c ("dt-bindings: net: rockchip-dwmac: add rk3588 gmac
> compatible") it also incorrectly has been treated as optional for all
> GMAC variants, when it should have been required for RK3588, and later
> also for RK3576.
> 
> Update this binding to require rockchip,grf and rockchip,php-grf to
> properly reflect that GRF (and peripheral GRF for RK3576/RK3588) is
> required to control part of GMAC.
> 
> This should not introduce any breakage as all Rockchip GMAC nodes have
> been added together with a rockchip,grf phandle (and rockchip,php-grf
> where required) in their initial commit.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From anshuman.khandual at arm.com  Mon Mar 10 02:59:00 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 15:29:00 +0530
Subject: [RFC 0/2] mm/ptdump: Drop assumption that pxd_val() is u64
Message-ID: <20250310095902.390664-1-anshuman.khandual@arm.com>

Last argument passed down in note_page() is u64 assuming pxd_val() returned
value (all page table levels) is 64 bit - which might not be the case going
ahead when D128 page tables is enabled on arm64 platform. Besides pxd_val()
is very platform specific and its type should not be assumed in generic MM.

This series splits note_page() into individual page table level specific
callbacks which accepts corresponding pxd_t page table entry as an argument
instead and later all subscribing platforms could derive pxd_val() from the
entries as required and proceed as before.

Page table entry's value, mask and protection are represented with pteval_t
not u64 that has been assumed while dumping the page table entries on arm64
platform. Replace such u64 instances with pteval_t instead as expected.

This series has been lightly tested on arm64 platform but it does build on
other relevant platforms (v6.14-rc5).

Some questions:

- Is there a better method to address this problem than splitting current
  note_page() into multiple call backs as proposed here ?

- This replaces note_page(st, 0, -1, 0) with note_page_pte(st, 0, pte_zero)
  Is that problematic ? Does level = -1 has got a special meaning ? Should
  level = -1 case be handled differently possibly via a separate callback ?

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
Cc: Nicholas Piggin <npiggin at gmail.com>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Gerald Schaefer <gerald.schaefer at linux.ibm.com>
Cc: Heiko Carstens <hca at linux.ibm.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-mm at kvack.org

Anshuman Khandual (2):
  mm/ptdump: Split note_page() into level specific callbacks
  arm64/ptdump: Replace u64 with pteval_t

 arch/arm64/include/asm/ptdump.h | 22 ++++++++++++-----
 arch/arm64/mm/ptdump.c          | 41 ++++++++++++++++++++++++++++---
 arch/powerpc/mm/ptdump/ptdump.c | 37 ++++++++++++++++++++++++++--
 arch/riscv/mm/ptdump.c          | 37 ++++++++++++++++++++++++++--
 arch/s390/mm/dump_pagetables.c  | 37 ++++++++++++++++++++++++++--
 arch/x86/mm/dump_pagetables.c   | 31 +++++++++++++++++++++++-
 include/linux/ptdump.h          |  7 ++++--
 mm/ptdump.c                     | 43 +++++++++++++++++++++++++--------
 8 files changed, 226 insertions(+), 29 deletions(-)

-- 
2.25.1



From suzuki.poulose at arm.com  Mon Mar 10 03:17:02 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 10:17:02 +0000
Subject: [PATCH] coresight: add verification process for
 coresight_etm_get_trace_id
In-Reply-To: <20250310022348.1654501-1-quic_jiegan@quicinc.com>
References: <20250310022348.1654501-1-quic_jiegan@quicinc.com>
Message-ID: <23943463-94d0-4e37-b5fa-5efb20015063@arm.com>

On 10/03/2025 02:23, Jie Gan wrote:
> The coresight_etm_get_trace_id function is a global function. The
> verification process for 'csdev' is required prior to its usage.
> 
> Fixes: c367a89dec26 ("Coresight: Add trace_id function to retrieving the trace ID")
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index bd0a7edd38c9..5a7cd2376e2d 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -1616,9 +1616,12 @@ EXPORT_SYMBOL_GPL(coresight_remove_driver);
>   int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
>   			       struct coresight_device *sink)
>   {
> -	int trace_id;
> -	int cpu = source_ops(csdev)->cpu_id(csdev);
> +	int cpu, trace_id;
> +
> +	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE && !source_ops(csdev)->cpu_id)

That must be :

	csdev->type != CORESIGHT_DEV_TYPE_SOURCE || !source_ops(csdev)->cpu_id)


Suzuki


> +		return -EINVAL;
>   
> +	cpu = source_ops(csdev)->cpu_id(csdev);
>   	switch (mode) {
>   	case CS_MODE_SYSFS:
>   		trace_id = coresight_trace_id_get_cpu_id(cpu);



From sudeep.holla at arm.com  Mon Mar 10 03:19:48 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 10 Mar 2025 10:19:48 +0000
Subject: [PATCH] cpufreq: Init cpufreq only for present CPUs
In-Reply-To: <20250310071640.3140435-1-ping.bai@nxp.com>
References: <20250310071640.3140435-1-ping.bai@nxp.com>
Message-ID: <Z868xB3_3NhMsa7R@bogus>

On Mon, Mar 10, 2025 at 03:16:40PM +0800, Jacky Bai wrote:
> for_each_possible_cpu() is currently used to initialize cpufreq
> in below cpufreq drivers:
>   drivers/cpufreq/cpufreq-dt.c
>   drivers/cpufreq/mediatek-cpufreq-hw.c
>   drivers/cpufreq/mediatek-cpufreq.c
>   drivers/cpufreq/qcom-cpufreq-nvmem.c
>   drivers/cpufreq/sun50i-cpufreq-nvmem.c
>

Again how did you just narrow down to the list above ? Is that just a
random pick ? As I suggested with corresponding cpuidle changes, please
look into the details in side the for_each_possible_cpu() loop and then
decide if it applies or not.

For me, it applied to the below files as well at the least.

drivers/cpufreq/mvebu-cpufreq.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/cpufreq/scmi-cpufreq.c
drivers/cpufreq/scpi-cpufreq.c
drivers/cpufreq/virtual-cpufreq.c

Please check everything thoroughly as I just looked at these briefly.

--
Regards,
Sudeep


From quic_jiegan at quicinc.com  Mon Mar 10 03:19:51 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 18:19:51 +0800
Subject: [PATCH] coresight: add verification process for
 coresight_etm_get_trace_id
In-Reply-To: <23943463-94d0-4e37-b5fa-5efb20015063@arm.com>
References: <20250310022348.1654501-1-quic_jiegan@quicinc.com>
 <23943463-94d0-4e37-b5fa-5efb20015063@arm.com>
Message-ID: <3fcbf259-aea5-4170-b988-1c23a3472a00@quicinc.com>



On 3/10/2025 6:17 PM, Suzuki K Poulose wrote:
> On 10/03/2025 02:23, Jie Gan wrote:
>> The coresight_etm_get_trace_id function is a global function. The
>> verification process for 'csdev' is required prior to its usage.
>>
>> Fixes: c367a89dec26 ("Coresight: Add trace_id function to retrieving 
>> the trace ID")
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>> ? drivers/hwtracing/coresight/coresight-core.c | 7 +++++--
>> ? 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index bd0a7edd38c9..5a7cd2376e2d 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -1616,9 +1616,12 @@ EXPORT_SYMBOL_GPL(coresight_remove_driver);
>> ? int coresight_etm_get_trace_id(struct coresight_device *csdev, enum 
>> cs_mode mode,
>> ???????????????????? struct coresight_device *sink)
>> ? {
>> -??? int trace_id;
>> -??? int cpu = source_ops(csdev)->cpu_id(csdev);
>> +??? int cpu, trace_id;
>> +
>> +??? if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE && ! 
>> source_ops(csdev)->cpu_id)
> 
> That must be :
> 
>  ????csdev->type != CORESIGHT_DEV_TYPE_SOURCE || !source_ops(csdev)- 
>  >cpu_id)
> 
> 
> Suzuki

Hi Suzuki,

Yes, you are right. I made a big mistake. It should return an error 
number if one of the conditions failed.

Sorry about that, will send another patch to fix it.

Thanks,
Jie

> 
> 
>> +??????? return -EINVAL;
>> +??? cpu = source_ops(csdev)->cpu_id(csdev);
>> ????? switch (mode) {
>> ????? case CS_MODE_SYSFS:
>> ????????? trace_id = coresight_trace_id_get_cpu_id(cpu);
> 



From sakari.ailus at iki.fi  Mon Mar 10 03:25:04 2025
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Mon, 10 Mar 2025 10:25:04 +0000
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z8r21Z2HthBwGDSq@mt.com>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
 <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
 <Z8r21Z2HthBwGDSq@mt.com>
Message-ID: <Z86-AFnPQ2wXKidi@valkosipuli.retiisi.eu>

Hi Mathis,

On Fri, Mar 07, 2025 at 02:38:29PM +0100, Mathis Foerst wrote:
> Hi Sakari, Hi Dan,
> 
> thanks a lot for your feedback.
> 
> On Thu, Mar 06, 2025 at 09:13:46PM +0000, Sakari Ailus wrote:
> > Hi Dan,
> > 
> > On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> > > On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > > > Hi Mathis,
> > > > 
> > > > Thanks for the patch.
> > > > 
> > > > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > > > The imx-media-csi driver requires upstream camera drivers to implement
> > > > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > > > implement this function are not usable on the i.MX6.
> > > > > 
> > > > > The docs for get_mbus_config [1] say:
> > > > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > > > >             The media bus configuration is usually retrieved from the
> > > > >             firmware interface at sub-device probe time, immediately
> > > > >             applied to the hardware and eventually adjusted by the
> > > > >             driver.
> > > > > 
> > > > > Currently, the imx-media-csi driver is not incorporating the information
> > > > > from the firmware interface and therefore relies on the implementation of
> > > > > get_mbus_config by the camera driver.
> > > > > 
> > > > > To be compatible with camera drivers not implementing get_mbus_config
> > > > > (which is the usual case), use the bus information from the fw interface:
> > > > > 
> > > > > The camera does not necessarily has a direct media bus link to the CSI as
> > > > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > > > between them on the media pipeline.
> > > > > The CSI driver already implements the functionality to find the connected
> > > > > camera sub-device to call get_mbus_config on it.
> > > > > 
> > > > > At this point the driver is modified as follows:
> > > > > In the case that get_mbus_config is not implemented by the upstream
> > > > > camera, try to get its endpoint configuration from the firmware interface
> > > > > usign v4l2_fwnode_endpoint_parse.
> > > > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > > > configuration.
> > > > > For all other mbus_types, return an error.
> > > > > 
> > > > > Note that parsing the mbus_config from the fw interface is not done during
> > > > > probing because the camera that's connected to the CSI can change based on
> > > > > the selected input of the video-mux at runtime.
> > > > > 
> > > > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > > > [1] include/media/v4l2-subdev.h - line 814
> > > > > 
> > > > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > > > ---
> > > > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > > > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > > > index 3edbc57be2ca..394a9321a10b 100644
> > > > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > >  {
> > > > >  	struct v4l2_subdev *sd, *remote_sd;
> > > > >  	struct media_pad *remote_pad;
> > > > > +	struct fwnode_handle *ep_node;
> > > > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > > > 
> > > > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > > > field to zero this way is redundant, just use {}.
> > > > 
> > > 
> > > I was going to respond in much the same way.  This is equivalen to:
> > > 
> > > struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
> > 
> > Thinking about this in a context of parsing the endpoint, in fact the
> > bus_type should be specified. Presumably the hardware is D-PHY, so the
> > correct value would be V4L2_MBUS_CSI2_DPHY. This way
> > v4l2_fwnode_endpoint_parse() doesn't need to guess.
> 
> I think we must use "bus_type = V4L2_MBUS_UNKNOWN" here:
> 
> The i.MX6 has two types of camera interfaces: Parallel and MIPI CSI-2.
> They are connected either directly or via a video-mux to the CSIs
> (See IMX6DQRM.pdf - Figure 9-3 for the connection diagram)
> 
> Pre-defining V4L2_MBUS_CSI2_DPHY here would let
> v4l2_fwnode_endpoint_parse() fail if the camera uses the parallel bus.
> 
> We could distinguish between MIPI CSI-2 and Parallel input by checking
> the grp_id of the upstream device like it's already done in
> csi_get_upstream_mbus_config().
> But for the Parallel case we still can't know if we should set bus_type
> to V4L2_MBUS_PARALLEL or to V4L2_MBUS_BT656 - the i.MX6 supports both
> formats on the parallel interface.
> 
> That's why I would argue that v4l2_fwnode_endpoint_parse() must figure
> out the bus_type from the fw node.

Right, nowadays you can indeed do this -- it wasn't a long ago when you
couldn't. I presume the bindings do specify the bus-type property is
mandatory? Where are the bindings btw.?

> 
> > 
> > > 
> > > > >  	int ret;
> > > > >  
> > > > >  	if (!priv->src_sd)
> > > > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > >  
> > > > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > > > >  			       remote_pad->index, mbus_cfg);
> > > > > -	if (ret == -ENOIOCTLCMD)
> > > > > -		v4l2_err(&priv->sd,
> > > > > -			 "entity %s does not implement get_mbus_config()\n",
> > > > > -			 remote_pad->entity->name);
> > > > > +	if (ret == -ENOIOCTLCMD) {
> > > > 
> > > > 	if (!ret)
> > > > 		return 0;
> > > > 
> > > > And you can unindent the rest.
> > > 
> > > I was going to say this too but then I thought actually this needs to
> > > be:
> > > 
> > > 	if (ret != -ENOIOCTLCMD)
> > > 		return ret;
> > > 
> > > Which is weird.  Better to break all the new code into a separate
> > > helper function.
> > > 
> > > 	if (ret == -ENOIOCTLCMD)
> > > 		ret = parse_fw_link_config_stuff();
> > > 
> > > 	return ret;
> 
> Good point. I factored out a helper function as suggested.
> 
> > 
> > Indeed. get_mbus_config() presumably wouldn't return an error but
> > correctness is usually a good idea.
> > 

-- 
Regards,

Sakari Ailus


From mark.rutland at arm.com  Mon Mar 10 03:28:47 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 10:28:47 +0000
Subject: [PATCH V2] arm64/mm: Define PTDESC_ORDER
In-Reply-To: <20250310040115.91298-1-anshuman.khandual@arm.com>
References: <20250310040115.91298-1-anshuman.khandual@arm.com>
Message-ID: <Z86-34-fgk7iskX_@J2N7QTR9R3.cambridge.arm.com>

On Mon, Mar 10, 2025 at 09:31:15AM +0530, Anshuman Khandual wrote:
> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
> index fd5a08450b12..78c7e03a0e35 100644
> --- a/arch/arm64/include/asm/kernel-pgtable.h
> +++ b/arch/arm64/include/asm/kernel-pgtable.h
> @@ -45,11 +45,14 @@
>  #define SPAN_NR_ENTRIES(vstart, vend, shift) \
>  	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
>  
> -#define EARLY_ENTRIES(vstart, vend, shift, add) \
> -	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
> +/* Number of VA bits resolved by a single translation table level */
> +#define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)

To be clear, when I suggested adding PTDESC_TABLE_SHIFT, I expected that
it would be used consistently in place of (PAGE_SHIFT - PTDESC_ORDER),
and not only replacing that within the EARLY_ENTRIES() macro
specifically.

Mark.

> -#define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
> -	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
> +#define EARLY_ENTRIES(lvl, vstart, vend) \
> +	SPAN_NR_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT)
> +
> +#define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
> +	((lvls) > (lvl) ? EARLY_ENTRIES(lvl, vstart, vend) + (add) : 0)
>  
>  #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
>  	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index a9136cc551cc..3c544edc3968 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -7,40 +7,43 @@
>  
>  #include <asm/memory.h>
>  
> +#define PTDESC_ORDER 3
> +
>  /*
>   * Number of page-table levels required to address 'va_bits' wide
>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
> + * bits with (PAGE_SHIFT - PTDESC_ORDER) bits at each page table level. Hence:
>   *
> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTDESC_ORDER))
>   *
>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>   *
>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>   * due to build issues. So we open code DIV_ROUND_UP here:
>   *
> - *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
> + *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTDESC_ORDER) - 1) / (PAGE_SHIFT - PTDESC_ORDER))
>   *
>   * which gets simplified as :
>   */
> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) \
> +	(((va_bits) - PTDESC_ORDER - 1) / (PAGE_SHIFT - PTDESC_ORDER))
>  
>  /*
>   * Size mapped by an entry at level n ( -1 <= n <= 3)
> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
> + * We map (PAGE_SHIFT - PTDESC_ORDER) at all translation levels and PAGE_SHIFT bits
>   * in the final page. The maximum number of translation levels supported by
>   * the architecture is 5. Hence, starting at level n, we have further
>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>   * So, the total number of bits mapped by an entry at level n is :
>   *
> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTDESC_ORDER) + PAGE_SHIFT
>   *
>   * Rearranging it a bit we get :
> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
> + *   (4 - n) * (PAGE_SHIFT - PTDESC_ORDER) + PTDESC_ORDER
>   */
> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTDESC_ORDER) * (4 - (n)) + PTDESC_ORDER)
>  
> -#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>  
>  /*
>   * PMD_SHIFT determines the size a level 2 page table entry can map.
> @@ -49,7 +52,7 @@
>  #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>  #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
>  #define PMD_MASK		(~(PMD_SIZE-1))
> -#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>  #endif
>  
>  /*
> @@ -59,14 +62,14 @@
>  #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>  #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
>  #define PUD_MASK		(~(PUD_SIZE-1))
> -#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>  #endif
>  
>  #if CONFIG_PGTABLE_LEVELS > 4
>  #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>  #define P4D_MASK		(~(P4D_SIZE-1))
> -#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
> +#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>  #endif
>  
>  /*
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..f74335e13929 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  {
>  	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>  	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
> -	int lshift = (3 - level) * (PAGE_SHIFT - 3);
> +	int lshift = (3 - level) * (PAGE_SHIFT - PTDESC_ORDER);
>  	u64 lmask = (PAGE_SIZE << lshift) - 1;
>  
>  	start	&= PAGE_MASK;
> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> index b65a29440a0c..211821f80571 100644
> --- a/arch/arm64/mm/kasan_init.c
> +++ b/arch/arm64/mm/kasan_init.c
> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>   */
>  static bool __init root_level_aligned(u64 addr)
>  {
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
>  
>  	return (addr % (PAGE_SIZE << shift)) == 0;
>  }
> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>  	 */
>  	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>  							: vabits_actual;
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
>  
>  	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>  }
> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>   */
>  static int __init next_level_idx(u64 addr)
>  {
> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTDESC_ORDER);
>  
>  	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>  }
> -- 
> 2.25.1
> 


From ankita at nvidia.com  Mon Mar 10 03:30:08 2025
From: ankita at nvidia.com (ankita at nvidia.com)
Date: Mon, 10 Mar 2025 10:30:08 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <20250310103008.3471-1-ankita@nvidia.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
Message-ID: <20250310103008.3471-2-ankita@nvidia.com>

From: Ankit Agrawal <ankita at nvidia.com>

Today KVM forces the memory to either NORMAL or DEVICE_nGnRE
based on pfn_is_map_memory (which tracks whether the device memory
is added to the kernel) and ignores the per-VMA flags that indicates the
memory attributes. The KVM code is thus restrictive and allows only for
the memory that is added to the kernel to be marked as cacheable.

The device memory such as on the Grace Hopper/Blackwell systems
is interchangeable with DDR memory and retains properties such as
cacheability, unaligned accesses, atomics and handling of executable
faults. This requires the device memory to be mapped as NORMAL in
stage-2.

Given that the GPU device memory is not added to the kernel (but is rather
VMA mapped through remap_pfn_range() in nvgrace-gpu module which sets
VM_PFNMAP), pfn_is_map_memory() is false and thus KVM prevents such memory
to be mapped Normal cacheable. The patch aims to solve this use case.

A cachebility check is made if the VM_PFNMAP is set in VMA flags by
consulting the VMA pgprot value. If the pgprot mapping type is MT_NORMAL,
it is safe to be mapped cacheable as the KVM S2 will have the same
Normal memory type as the VMA has in the S1 and KVM has no additional
responsibility for safety. Checking pgprot as NORMAL is thus a KVM
sanity check.

Introduce a new variable cacheable_devmem to indicate a safely
cacheable mapping. Do not set the device variable when cacheable_devmem
is true. This essentially have the effect of setting stage-2 mapping
as NORMAL through kvm_pgtable_stage2_map.

Add check for COW VM_PFNMAP and refuse such mapping.

No additional checks for MTE are needed as kvm_arch_prepare_memory_region()
already tests it at an early stage during memslot creation. There would
not even be a fault if the memslot is not created.

Note when FWB is not enabled, the kernel expects to trivially do
cache management by flushing the memory by linearly converting a
kvm_pte to phys_addr to a KVA, see kvm_flush_dcache_to_poc(). The
cache management thus relies on memory being mapped. So do not allow
!FWB.

Signed-off-by: Ankit Agrawal <ankita at nvidia.com>
Suggested-by: Catalin Marinas <catalin.marinas at arm.com>
Suggested-by: Jason Gunthorpe <jgg at nvidia.com>
Suggested-by: David Hildenbrand <david at redhat.com>
---
 arch/arm64/include/asm/kvm_pgtable.h |  8 ++++++
 arch/arm64/kvm/hyp/pgtable.c         |  2 +-
 arch/arm64/kvm/mmu.c                 | 43 +++++++++++++++++++++++++++-
 3 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 6b9d274052c7..f21e2fae2bfe 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -507,6 +507,14 @@ u64 kvm_pgtable_hyp_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size);
  */
 u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift);
 
+/**
+ * stage2_has_fwb() - Determine whether FWB is supported
+ * @pgt:    Page-table structure initialised by kvm_pgtable_stage2_init*()
+ *
+ * Return: True if FWB is supported.
+ */
+bool stage2_has_fwb(struct kvm_pgtable *pgt);
+
 /**
  * kvm_pgtable_stage2_pgd_size() - Helper to compute size of a stage-2 PGD
  * @vtcr:	Content of the VTCR register.
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index df5cc74a7dd0..ee6b98fefd61 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -637,7 +637,7 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
 	return vtcr;
 }
 
-static bool stage2_has_fwb(struct kvm_pgtable *pgt)
+bool stage2_has_fwb(struct kvm_pgtable *pgt)
 {
 	if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
 		return false;
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..4b3a03c9d700 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1454,6 +1454,15 @@ static bool kvm_vma_mte_allowed(struct vm_area_struct *vma)
 	return vma->vm_flags & VM_MTE_ALLOWED;
 }
 
+/*
+ * Determine the memory region cacheability from VMA's pgprot. This
+ * is used to set the stage 2 PTEs.
+ */
+static unsigned long mapping_type(pgprot_t page_prot)
+{
+	return FIELD_GET(PTE_ATTRINDX_MASK, pgprot_val(page_prot));
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			  struct kvm_s2_trans *nested,
 			  struct kvm_memory_slot *memslot, unsigned long hva,
@@ -1463,6 +1472,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	bool write_fault, writable, force_pte = false;
 	bool exec_fault, mte_allowed;
 	bool device = false, vfio_allow_any_uc = false;
+	bool cacheable_devmem = false;
 	unsigned long mmu_seq;
 	phys_addr_t ipa = fault_ipa;
 	struct kvm *kvm = vcpu->kvm;
@@ -1600,6 +1610,19 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
 	vfio_allow_any_uc = vma->vm_flags & VM_ALLOW_ANY_UNCACHED;
 
+	if (vma->vm_flags & VM_PFNMAP) {
+		/* Reject COW VM_PFNMAP */
+		if (is_cow_mapping(vma->vm_flags))
+			return -EINVAL;
+		/*
+		 * If the VM_PFNMAP is set in VMA flags, do a KVM sanity
+		 * check to see if pgprot mapping type is MT_NORMAL and a
+		 * safely cacheable device memory.
+		 */
+		if (mapping_type(vma->vm_page_prot) == MT_NORMAL)
+			cacheable_devmem = true;
+	}
+
 	/* Don't use the VMA after the unlock -- it may have vanished */
 	vma = NULL;
 
@@ -1633,8 +1656,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		 *
 		 * In both cases, we don't let transparent_hugepage_adjust()
 		 * change things at the last minute.
+		 *
+		 * Do not set device as the device memory is cacheable. Note
+		 * that such mapping is safe as the KVM S2 will have the same
+		 * Normal memory type as the VMA has in the S1.
 		 */
-		device = true;
+		if (!cacheable_devmem)
+			device = true;
 	} else if (logging_active && !write_fault) {
 		/*
 		 * Only actually map the page as writable if this was a write
@@ -1716,6 +1744,19 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		prot |= KVM_PGTABLE_PROT_X;
 	}
 
+	/*
+	 *  When FWB is unsupported KVM needs to do cache flushes
+	 *  (via dcache_clean_inval_poc()) of the underlying memory. This is
+	 *  only possible if the memory is already mapped into the kernel map.
+	 *
+	 *  Outright reject as the cacheable device memory is not present in
+	 *  the kernel map and not suitable for cache management.
+	 */
+	if (cacheable_devmem && !stage2_has_fwb(pgt)) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
 	/*
 	 * Under the premise of getting a FSC_PERM fault, we just need to relax
 	 * permissions only if vma_pagesize equals fault_granule. Otherwise,
-- 
2.34.1



From ankita at nvidia.com  Mon Mar 10 03:30:07 2025
From: ankita at nvidia.com (ankita at nvidia.com)
Date: Mon, 10 Mar 2025 10:30:07 +0000
Subject: [PATCH v3 0/1] KVM: arm64: Map GPU device memory as cacheable
Message-ID: <20250310103008.3471-1-ankita@nvidia.com>

From: Ankit Agrawal <ankita at nvidia.com>

Grace based platforms such as Grace Hopper/Blackwell Superchips have
CPU accessible cache coherent GPU memory. The GPU device memory is
essentially a DDR memory and retains properties such as cacheability,
unaligned accesses, atomics and handling of executable faults. This
requires the device memory to be mapped as NORMAL in stage-2.

Today KVM forces the memory to either NORMAL or DEVICE_nGnRE depending
on whethere the memory region is added to the kernel. The KVM code is
thus restrictive and prevents device memory that is not added to the
kernel to be marked as cacheable. The patch aims to solve this.

A cachebility check is made if the VM_PFNMAP is set in VMA flags by
consulting the VMA pgprot value. If the pgprot mapping type is MT_NORMAL,
it is considered safe to be mapped cacheable as the KVM S2 will have
the same Normal memory type as the VMA has in the S1 and KVM has no
additional responsibility for safety.

Note when FWB is not enabled, the kernel expects to trivially do
cache management by flushing the memory by linearly converting a
kvm_pte to phys_addr to a KVA. The cache management thus relies on
memory being mapped. Since the GPU device memory is not kernel
mapped, exit when the FWB is not supported.

The changes are heavily influenced by the discussions between
Catalin Marinas, David Hildenbrand and Jason Gunthorpe [1] on v2.
Many thanks for their valuable suggestions.

Applied over next-20250305 and tested on the Grace Hopper and
Grace Blackwell platforms by booting up VM, loading NVIDIA module [2]
and running nvidia-smi in the VM.

To run CUDA workloads, there is a dependency on the IOMMUFD and the
Nested Page Table patches being worked on separately by Nicolin Chen.
(nicolinc at nvidia.com). NVIDIA has provided git repositories which
includes all the requisite kernel [3] and Qemu [4] patches in case
one wants to try.

v2 -> v3
1. Restricted the new changes to check for cacheability to VM_PFNMAP
   based on David Hildenbrand's (david at redhat.com) suggestion.
2. Removed the MTE checks based on Jason Gunthorpe's (jgg at nvidia.com)
   observation that it already done earlier in
   kvm_arch_prepare_memory_region.
3. Dropped the pfn_valid() checks based on suggestions by
   Catalin Marinas (catalin.marinas at arm.com).
4. Removed the code for exec fault handling as it is not needed
   anymore.

v1 -> v2
1. Removed kvm_is_device_pfn() as a determiner for device type memory
   determination. Instead using pfn_valid()
2. Added handling for MTE.
3. Minor cleanup.

Link: https://lore.kernel.org/all/20241118131958.4609-1-ankita at nvidia.com/ [1]
Link: https://github.com/NVIDIA/open-gpu-kernel-modules [2]
Link: https://github.com/NVIDIA/NV-Kernels/tree/6.8_ghvirt [3]
Link: https://github.com/NVIDIA/QEMU/tree/6.8_ghvirt_iommufd_vcmdq [4]

Ankit Agrawal (1):
  KVM: arm64: Allow cacheable stage 2 mapping using VMA flags

 arch/arm64/include/asm/kvm_pgtable.h |  8 ++++++
 arch/arm64/kvm/hyp/pgtable.c         |  2 +-
 arch/arm64/kvm/mmu.c                 | 43 +++++++++++++++++++++++++++-
 3 files changed, 51 insertions(+), 2 deletions(-)

-- 
2.34.1



From ansuelsmth at gmail.com  Mon Mar 10 03:30:50 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Mon, 10 Mar 2025 11:30:50 +0100
Subject: [PATCH 03/13] dt-bindings: soc: airoha: add SCU SSR Serdes port
 binding
In-Reply-To: <20250310-ultraviolet-earthworm-of-honor-df114b@krzk-bin>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-4-ansuelsmth@gmail.com>
 <20250310-ultraviolet-earthworm-of-honor-df114b@krzk-bin>
Message-ID: <67cebf5d.a70a0220.fe6c9.6ad3@mx.google.com>

On Mon, Mar 10, 2025 at 08:54:14AM +0100, Krzysztof Kozlowski wrote:
> On Sun, Mar 09, 2025 at 02:29:34PM +0100, Christian Marangi wrote:
> > Add Airoha AN7581 SCU SSR Serdes port binding to define what mode is
> > supported by each Serdes port. These special binding are needed to
> > identify and provide the port mode from any user driver.
> > 
> > These modes are mutually exclusive and driver needs to correctly
> > validate the current mode for the Serdes port in use.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
> >  MAINTAINERS                              |  6 ++++++
> >  include/dt-bindings/soc/airoha,scu-ssr.h | 24 ++++++++++++++++++++++++
> 
> This should be squashed with the binding for the device.
>

I split them to mute checkpatch warning

"DT binding docs and includes should be a separate patch. See:
Documentation/devicetree/bindings/submitting-patches.rst"

But I think I always took it wrong and with "docs and includes" it's
intended in a single patch.

Ok will squash!

-- 
	Ansuel


From anshuman.khandual at arm.com  Mon Mar 10 03:33:12 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 10 Mar 2025 16:03:12 +0530
Subject: [PATCH V2] arm64/mm: Define PTDESC_ORDER
In-Reply-To: <Z86-34-fgk7iskX_@J2N7QTR9R3.cambridge.arm.com>
References: <20250310040115.91298-1-anshuman.khandual@arm.com>
 <Z86-34-fgk7iskX_@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <68188aa1-8f80-4f91-beb5-9ddb0129a490@arm.com>



On 3/10/25 15:58, Mark Rutland wrote:
> On Mon, Mar 10, 2025 at 09:31:15AM +0530, Anshuman Khandual wrote:
>> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
>> index fd5a08450b12..78c7e03a0e35 100644
>> --- a/arch/arm64/include/asm/kernel-pgtable.h
>> +++ b/arch/arm64/include/asm/kernel-pgtable.h
>> @@ -45,11 +45,14 @@
>>  #define SPAN_NR_ENTRIES(vstart, vend, shift) \
>>  	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
>>  
>> -#define EARLY_ENTRIES(vstart, vend, shift, add) \
>> -	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
>> +/* Number of VA bits resolved by a single translation table level */
>> +#define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)
> 
> To be clear, when I suggested adding PTDESC_TABLE_SHIFT, I expected that
> it would be used consistently in place of (PAGE_SHIFT - PTDESC_ORDER),
> and not only replacing that within the EARLY_ENTRIES() macro
> specifically.

I had that dilemma as well but alright, will respin this once more.

> 
> Mark.
> 
>> -#define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
>> -	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
>> +#define EARLY_ENTRIES(lvl, vstart, vend) \
>> +	SPAN_NR_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT)
>> +
>> +#define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
>> +	((lvls) > (lvl) ? EARLY_ENTRIES(lvl, vstart, vend) + (add) : 0)
>>  
>>  #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
>>  	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
>> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
>> index a9136cc551cc..3c544edc3968 100644
>> --- a/arch/arm64/include/asm/pgtable-hwdef.h
>> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
>> @@ -7,40 +7,43 @@
>>  
>>  #include <asm/memory.h>
>>  
>> +#define PTDESC_ORDER 3
>> +
>>  /*
>>   * Number of page-table levels required to address 'va_bits' wide
>>   * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
>> - * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
>> + * bits with (PAGE_SHIFT - PTDESC_ORDER) bits at each page table level. Hence:
>>   *
>> - *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
>> + *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - PTDESC_ORDER))
>>   *
>>   * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
>>   *
>>   * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
>>   * due to build issues. So we open code DIV_ROUND_UP here:
>>   *
>> - *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
>> + *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - PTDESC_ORDER) - 1) / (PAGE_SHIFT - PTDESC_ORDER))
>>   *
>>   * which gets simplified as :
>>   */
>> -#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
>> +#define ARM64_HW_PGTABLE_LEVELS(va_bits) \
>> +	(((va_bits) - PTDESC_ORDER - 1) / (PAGE_SHIFT - PTDESC_ORDER))
>>  
>>  /*
>>   * Size mapped by an entry at level n ( -1 <= n <= 3)
>> - * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
>> + * We map (PAGE_SHIFT - PTDESC_ORDER) at all translation levels and PAGE_SHIFT bits
>>   * in the final page. The maximum number of translation levels supported by
>>   * the architecture is 5. Hence, starting at level n, we have further
>>   * ((4 - n) - 1) levels of translation excluding the offset within the page.
>>   * So, the total number of bits mapped by an entry at level n is :
>>   *
>> - *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
>> + *  ((4 - n) - 1) * (PAGE_SHIFT - PTDESC_ORDER) + PAGE_SHIFT
>>   *
>>   * Rearranging it a bit we get :
>> - *   (4 - n) * (PAGE_SHIFT - 3) + 3
>> + *   (4 - n) * (PAGE_SHIFT - PTDESC_ORDER) + PTDESC_ORDER
>>   */
>> -#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
>> +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - PTDESC_ORDER) * (4 - (n)) + PTDESC_ORDER)
>>  
>> -#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>>  
>>  /*
>>   * PMD_SHIFT determines the size a level 2 page table entry can map.
>> @@ -49,7 +52,7 @@
>>  #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
>>  #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
>>  #define PMD_MASK		(~(PMD_SIZE-1))
>> -#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>>  #endif
>>  
>>  /*
>> @@ -59,14 +62,14 @@
>>  #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
>>  #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
>>  #define PUD_MASK		(~(PUD_SIZE-1))
>> -#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>>  #endif
>>  
>>  #if CONFIG_PGTABLE_LEVELS > 4
>>  #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
>>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>>  #define P4D_MASK		(~(P4D_SIZE-1))
>> -#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
>> +#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - PTDESC_ORDER))
>>  #endif
>>  
>>  /*
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 2b69e3beeef8..f74335e13929 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>  {
>>  	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
>>  	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
>> -	int lshift = (3 - level) * (PAGE_SHIFT - 3);
>> +	int lshift = (3 - level) * (PAGE_SHIFT - PTDESC_ORDER);
>>  	u64 lmask = (PAGE_SIZE << lshift) - 1;
>>  
>>  	start	&= PAGE_MASK;
>> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
>> index b65a29440a0c..211821f80571 100644
>> --- a/arch/arm64/mm/kasan_init.c
>> +++ b/arch/arm64/mm/kasan_init.c
>> @@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
>>   */
>>  static bool __init root_level_aligned(u64 addr)
>>  {
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
>>  
>>  	return (addr % (PAGE_SIZE << shift)) == 0;
>>  }
>> @@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
>>  	 */
>>  	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
>>  							: vabits_actual;
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - PTDESC_ORDER);
>>  
>>  	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
>>  }
>> @@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
>>   */
>>  static int __init next_level_idx(u64 addr)
>>  {
>> -	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
>> +	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - PTDESC_ORDER);
>>  
>>  	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
>>  }
>> -- 
>> 2.25.1
>>


From ansuelsmth at gmail.com  Mon Mar 10 03:33:41 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Mon, 10 Mar 2025 11:33:41 +0100
Subject: [PATCH 04/13] dt-bindings: soc: airoha: add Documentation for
 Airoha AN7581 SCU SSR
In-Reply-To: <20250310-aromatic-chihuahua-of-priority-4ee73b@krzk-bin>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-5-ansuelsmth@gmail.com>
 <20250310-aromatic-chihuahua-of-priority-4ee73b@krzk-bin>
Message-ID: <67cec007.170a0220.37245a.99cd@mx.google.com>

On Mon, Mar 10, 2025 at 09:00:40AM +0100, Krzysztof Kozlowski wrote:
> On Sun, Mar 09, 2025 at 02:29:35PM +0100, Christian Marangi wrote:
> > The Airoha AN7581 SoC have in the SCU register space particular
> > address that control how some peripheral are configured.
> > 
> > These are toggeled in the System Status Register and are used to
> > toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> > or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).
> > 
> > Modes are mutually exclusive and selecting one mode cause the
> > other feature to not work (example a mode in USB 3.0 cause PCIe
> > port 2 to not work) This depends also on what is physically
> > connected to the Hardware and needs to correctly reflect the
> > System Status Register bits.
> > 
> > Special care is needed for PCIe port 0 in 2 line mode that
> > requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> > mode.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
> >  .../soc/airoha/airoha,an7581-scu-ssr.yaml     | 106 ++++++++++++++++++
> >  MAINTAINERS                                   |   1 +
> >  2 files changed, 107 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> > new file mode 100644
> > index 000000000000..4bbf6e3b79a4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
> > @@ -0,0 +1,106 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/soc/airoha/airoha,an7581-scu-ssr.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Airoha AN7581 SCU System Status Register
> > +
> > +maintainers:
> > +  - Christian Marangi <ansuelsmth at gmail.com>
> > +
> > +description: >
> > +  The Airoha AN7581 SoC have in the SCU register space particular
> > +  address that control how some peripheral are configured.
> > +
> > +  These are toggeled in the System Status Register and are used to
> > +  toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> > +  or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).
> 
> typo, Ethernet
> 
> > +
> > +  Modes are mutually exclusive and selecting one mode cause the
> > +  other feature to not work (example a mode in USB 3.0 cause PCIe
> > +  port 2 to not work) This depends also on what is physically
> > +  connected to the Hardware and needs to correctly reflect the
> > +  System Status Register bits.
> > +
> > +  Special care is needed for PCIe port 0 in 2 line mode that
> > +  requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> > +  mode.
> > +
> > +properties:
> > +  compatible:
> > +    const: airoha,an7581-scu-ssr
> 
> That's not a separate device, but part of the SCU.
>

More comments on this in the MFD patch.

> But more important - such definition of choice of serial engines is
> really not flexible, not reabable and not helping integrating into DTS.
> Are you going to grow this for next chip airoha,serdes-wifi20, then
> airoha,serdes-wifi21, 22... ? And then how the if:then: would look like?
> 
> Assuming you do not have here child-parent relationship, like usually
> for serial engines, so then this should be somehow list of devices
> (strings) you want to run.
> 

You are right, string is more flexible and I don't need the include
file.

-- 
	Ansuel


From quic_jiegan at quicinc.com  Mon Mar 10 03:27:24 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 10 Mar 2025 18:27:24 +0800
Subject: [PATCH v2] coresight: add verification process for coresight_etm_get_trace_id
Message-ID: <20250310102724.2112905-1-quic_jiegan@quicinc.com>

The coresight_etm_get_trace_id function is a global function. The
verification process for 'csdev' is required prior to its usage.

Fixes: c367a89dec26 ("Coresight: Add trace_id function to retrieving the trace ID")
Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
---
Changes in V2:
1. fix the logic error.
Link to V1 - https://lore.kernel.org/all/20250310022348.1654501-1-quic_jiegan at quicinc.com/
---
 drivers/hwtracing/coresight/coresight-core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..c915a055534e 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1616,9 +1616,12 @@ EXPORT_SYMBOL_GPL(coresight_remove_driver);
 int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode,
 			       struct coresight_device *sink)
 {
-	int trace_id;
-	int cpu = source_ops(csdev)->cpu_id(csdev);
+	int cpu, trace_id;
+
+	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE || !source_ops(csdev)->cpu_id)
+		return -EINVAL;
 
+	cpu = source_ops(csdev)->cpu_id(csdev);
 	switch (mode) {
 	case CS_MODE_SYSFS:
 		trace_id = coresight_trace_id_get_cpu_id(cpu);
-- 
2.34.1



From wiagn233 at outlook.com  Mon Mar 10 03:33:53 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Mon, 10 Mar 2025 18:33:53 +0800
Subject: [PATCH v9 RESEND] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <b6b52bfcdb614137ac63fddfdaf9cb97@realtek.com>
References: <TYCPR01MB84376C7074C566865654F05098D42@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <b6b52bfcdb614137ac63fddfdaf9cb97@realtek.com>
Message-ID: <OSZPR01MB843481965BA47B030566DF2698D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>



? 2025/3/10 8:33, Ping-Ke Shih ??:
> Shengyu Qu <wiagn233 at outlook.com> wrote:
>> @@ -1280,6 +1292,34 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>>          if (!msta->wcid.sta)
>>                  return;
>>
>> +       if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> +           !is_mt7915(&dev->mt76) &&
>> +           (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
>> +               pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
> 
> Need to check if pre_sta != NULL before using.
Thanks, will fix.

> 
>> +               pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
>> +
>> +               flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
>> +                       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
>> +
>> +               tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
>> +               if (tmp_idx == -1)
> 
> At other places, it checks this by 'idx < 0'.
Will fix.

> 
>> +                       goto error;
>> +               pre_msta->wcid.idx = (u16)tmp_idx;
>> +               mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
>> +               rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
>> +
>> +               tmp_idx = msta->wcid.idx;
>> +               msta->wcid.idx = pre_msta->wcid.idx;
>> +               pre_msta->wcid.idx = (u16)tmp_idx;
>> +               rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
>> +
>> +               synchronize_rcu();
>> +               mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
>> +
>> +error:
>> +               kfree(pre_sta);
>> +       }
>> +
>>          mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
>>   }
>>
> 
> [...]
> 
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> index 9d790f234e82..32c5aa1a361e 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> @@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
>>
>>          mt76_connac_mcu_del_wtbl_all(&dev->mt76);
>>
>> -       if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> -            is_mt7915(&dev->mt76)) ||
>> -           !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
>> -               mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
>> +#ifdef CONFIG_NET_MEDIATEK_SOC_WED
> 
> if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) ... ?
I did a search in code about this, seems current MT76 code is using a
mix of IS_ENABLED and ifdef. And this file already have a ifdef
implementation. I prefer keep it as is and use another patch to convert
the whole mt76 driver.

> 
>> +       if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
>> +               if (is_mt7915(&dev->mt76) ||
>> +                   !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
>> +                       ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
>> +                                               0, 0, 0);
>> +               else
>> +                       ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
>> +                                               MCU_WA_PARAM_WED_VERSION,
>> +                                               dev->mt76.mmio.wed.rev_id, 0);
>> +               if (ret)
>> +                       return ret;
>> +       }
>> +#endif
>>
>>          ret = mt7915_mcu_set_mwds(dev, 1);
>>          if (ret)
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
>> b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
>> index 49476a4182fd..c3dd0cb4a5d3 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
>> @@ -278,6 +278,7 @@ enum {
>>          MCU_WA_PARAM_PDMA_RX = 0x04,
>>          MCU_WA_PARAM_CPU_UTIL = 0x0b,
>>          MCU_WA_PARAM_RED = 0x0e,
>> +       MCU_WA_PARAM_WED_VERSION = 0x32,
>>          MCU_WA_PARAM_RED_SETTING = 0x40,
>>   };
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
>> index 95b3dc96e4c4..7fac9c79ebdf 100644
>> --- a/drivers/net/wireless/mediatek/mt76/util.c
>> +++ b/drivers/net/wireless/mediatek/mt76/util.c
>> @@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
>>   }
>>   EXPORT_SYMBOL_GPL(____mt76_poll_msec);
>>
>> -int mt76_wcid_alloc(u32 *mask, int size)
>> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
>>   {
>>          int i, idx = 0, cur;
>> +       int min = MT76_WED_WDS_MIN;
>> +       int max = MT76_WED_WDS_MAX;
> 
> In reverse X'mas tree order?
Will fix.

> 
>>
>>          for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
>>                  idx = ffs(~mask[i]);
>> @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
>>
>>                  idx--;
>>                  cur = i * 32 + idx;
>> -               if (cur >= size)
>> +
>> +               switch (flag) {
>> +               case MT76_WED_ACTIVE:
>> +                       if (cur >= min && cur < max)
>> +                               continue;
>> +
>> +                       if (cur >= size) {
>> +                               u32 end = max - min - 1;
>> +
>> +                               i = min / 32;
>> +                               idx = ffs(~mask[i] & GENMASK(end, 0));
>> +                               if (!idx)
>> +                                       goto error;
>> +                               idx--;
>> +                               cur = min + idx;
>> +                       }
>> +
>>                          break;
>> +               case MT76_WED_WDS_ACTIVE:
>> +                       if (cur < min)
>> +                               continue;
>> +                       if (cur >= max)
>> +                               goto error;
>> +
>> +                       break;
>> +               default:
>> +                       if (cur >= size)
>> +                               goto error;
>> +                       break;
>> +               }
>>
>>                  mask[i] |= BIT(idx);
>>                  return cur;
>>          }
>>
>> +error:
>>          return -1;
>>   }
>> -EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
>> +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
>>
>>   int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
>>   {
>> diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
>> index 260965dde94c..99b7263c0a20 100644
>> --- a/drivers/net/wireless/mediatek/mt76/util.h
>> +++ b/drivers/net/wireless/mediatek/mt76/util.h
>> @@ -27,7 +27,12 @@ enum {
>>   #define MT76_INCR(_var, _size) \
>>          (_var = (((_var) + 1) % (_size)))
>>
>> -int mt76_wcid_alloc(u32 *mask, int size);
>> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
>> +
>> +static inline int mt76_wcid_alloc(u32 *mask, int size)
>> +{
>> +       return __mt76_wcid_alloc(mask, size, 0);
> 
> return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); ?
Will fix.

> 
>> +}
>>
>>   static inline void
>>   mt76_wcid_mask_set(u32 *mask, int idx)
>> --
>> 2.48.1
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/84336462/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/84336462/attachment.sig>

From nbd at nbd.name  Mon Mar 10 03:41:06 2025
From: nbd at nbd.name (Felix Fietkau)
Date: Mon, 10 Mar 2025 11:41:06 +0100
Subject: [PATCH v9 RESEND] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <OSZPR01MB843481965BA47B030566DF2698D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>
References: <TYCPR01MB84376C7074C566865654F05098D42@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <b6b52bfcdb614137ac63fddfdaf9cb97@realtek.com>
 <OSZPR01MB843481965BA47B030566DF2698D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>
Message-ID: <71ed8398-4619-4793-804d-77cad36e7402@nbd.name>

On 10.03.25 11:33, Shengyu Qu wrote:
>> if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) ... ?
> I did a search in code about this, seems current MT76 code is using a
> mix of IS_ENABLED and ifdef. And this file already have a ifdef
> implementation. I prefer keep it as is and use another patch to convert
> the whole mt76 driver.

The driver uses #ifdef where it relies on struct members that are also 
#ifdef'd out, and using IS_ENABLED would lead do build failures.

- Felix


From damon.ding at rock-chips.com  Mon Mar 10 03:41:04 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:04 +0800
Subject: [PATCH v8 03/13] drm/bridge: analogix_dp: Add support for phy configuration.
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-4-damon.ding@rock-chips.com>

Add support to configurate link rate, lane count, voltage swing and
pre-emphasis with phy_configure(). It is helpful in application scenarios
where analogix controller is mixed with the phy of other vendors.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v2:
- remove needless assignments for phy_configure()
- remove unnecessary changes for phy_power_on()/phy_power_off()

Changes in v4:
- remove unnecessary &phy_configure_opts_dp.lanes assignments in
  analogix_dp_set_link_bandwidth()
- remove needless &phy_configure_opts_dp.lanes and
  &phy_configure_opts_dp.link_rate assignments in
  analogix_dp_set_lane_link_training()

Changes in v5:
- include <drm/drm_print.h> for dev_err()
- use drm_err() instead of dev_err()

Changes in v6:
- Pass 'dp' in drm_...() rather than 'dp->drm_dev'

Changes in v7:
- For the new error logs, use dev_err() as with the other error logs
---
 .../drm/bridge/analogix/analogix_dp_core.c    |  1 +
 .../gpu/drm/bridge/analogix/analogix_dp_reg.c | 52 +++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 132f8513f93f..d5bbc8843a56 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1680,6 +1680,7 @@ int analogix_dp_resume(struct analogix_dp_device *dp)
 	if (dp->plat_data->power_on)
 		dp->plat_data->power_on(dp->plat_data);
 
+	phy_set_mode(dp->phy, PHY_MODE_DP);
 	phy_power_on(dp->phy);
 
 	analogix_dp_init_dp(dp);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 3afc73c858c4..38fd8d5014d2 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -11,6 +11,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/phy/phy.h>
 
 #include <drm/bridge/analogix_dp.h>
 
@@ -513,10 +514,24 @@ void analogix_dp_enable_sw_function(struct analogix_dp_device *dp)
 void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
 {
 	u32 reg;
+	int ret;
 
 	reg = bwtype;
 	if ((bwtype == DP_LINK_BW_2_7) || (bwtype == DP_LINK_BW_1_62))
 		writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET);
+
+	if (dp->phy) {
+		union phy_configure_opts phy_cfg = {0};
+
+		phy_cfg.dp.link_rate =
+			drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100;
+		phy_cfg.dp.set_rate = true;
+		ret = phy_configure(dp->phy, &phy_cfg);
+		if (ret && ret != -EOPNOTSUPP) {
+			dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
+			return;
+		}
+	}
 }
 
 void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
@@ -530,9 +545,22 @@ void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
 void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)
 {
 	u32 reg;
+	int ret;
 
 	reg = count;
 	writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);
+
+	if (dp->phy) {
+		union phy_configure_opts phy_cfg = {0};
+
+		phy_cfg.dp.lanes = dp->link_train.lane_count;
+		phy_cfg.dp.set_lanes = true;
+		ret = phy_configure(dp->phy, &phy_cfg);
+		if (ret && ret != -EOPNOTSUPP) {
+			dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
+			return;
+		}
+	}
 }
 
 void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
@@ -546,10 +574,34 @@ void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
 void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)
 {
 	u8 lane;
+	int ret;
 
 	for (lane = 0; lane < dp->link_train.lane_count; lane++)
 		writel(dp->link_train.training_lane[lane],
 		       dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);
+
+	if (dp->phy) {
+		union phy_configure_opts phy_cfg = {0};
+
+		for (lane = 0; lane < dp->link_train.lane_count; lane++) {
+			u8 training_lane = dp->link_train.training_lane[lane];
+			u8 vs, pe;
+
+			vs = (training_lane & DP_TRAIN_VOLTAGE_SWING_MASK) >>
+			     DP_TRAIN_VOLTAGE_SWING_SHIFT;
+			pe = (training_lane & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+			     DP_TRAIN_PRE_EMPHASIS_SHIFT;
+			phy_cfg.dp.voltage[lane] = vs;
+			phy_cfg.dp.pre[lane] = pe;
+		}
+
+		phy_cfg.dp.set_voltages = true;
+		ret = phy_configure(dp->phy, &phy_cfg);
+		if (ret && ret != -EOPNOTSUPP) {
+			dev_err(dp->dev, "%s: phy_configure() failed: %d\n", __func__, ret);
+			return;
+		}
+	}
 }
 
 u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:05 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:05 +0800
Subject: [PATCH v8 04/13] dt-bindings: display: rockchip: analogix-dp: Add support to get panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-5-damon.ding@rock-chips.com>

According to Documentation/devicetree/bindings/display/dp-aux-bus.yaml,
it is a good way to get panel through the DP AUX bus.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v4:
- Move the dt-bindings commit before related driver commits

Changes in v5:
- Remove the unexpected change logs in commit message
---
 .../bindings/display/rockchip/rockchip,analogix-dp.yaml        | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
index 60dedf9b2be7..eaf4e67e232e 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
@@ -41,6 +41,9 @@ properties:
     description:
       This SoC makes use of GRF regs.
 
+  aux-bus:
+    $ref: /schemas/display/dp-aux-bus.yaml#
+
 required:
   - compatible
   - clocks
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:06 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:06 +0800
Subject: [PATCH v8 05/13] drm/bridge: analogix_dp: Support to get &analogix_dp_device.plat_data and &analogix_dp_device.aux
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-6-damon.ding@rock-chips.com>

Add two new functions: one to find &analogix_dp_device.plat_data via
&drm_dp_aux, and the other to get &analogix_dp_device.aux. Both of them
serve for the function of getting panel from DP AUX bus, which is why
they are included in a single commit.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v7:
- Use the forward-declare struct drm_dp_aux instead of including the
  relevant header file.
---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 14 ++++++++++++++
 include/drm/bridge/analogix_dp.h                   |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index d5bbc8843a56..dd91760c4b1c 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1764,6 +1764,20 @@ int analogix_dp_stop_crc(struct drm_connector *connector)
 }
 EXPORT_SYMBOL_GPL(analogix_dp_stop_crc);
 
+struct analogix_dp_plat_data *analogix_dp_aux_to_plat_data(struct drm_dp_aux *aux)
+{
+	struct analogix_dp_device *dp = to_dp(aux);
+
+	return dp->plat_data;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_aux_to_plat_data);
+
+struct drm_dp_aux *analogix_dp_get_aux(struct analogix_dp_device *dp)
+{
+	return &dp->aux;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_get_aux);
+
 MODULE_AUTHOR("Jingoo Han <jg1.han at samsung.com>");
 MODULE_DESCRIPTION("Analogix DP Core Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index 6002c5666031..e19b0bbc57d6 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -10,6 +10,7 @@
 #include <drm/drm_crtc.h>
 
 struct analogix_dp_device;
+struct drm_dp_aux;
 
 enum analogix_dp_devtype {
 	EXYNOS_DP,
@@ -48,4 +49,7 @@ void analogix_dp_unbind(struct analogix_dp_device *dp);
 int analogix_dp_start_crc(struct drm_connector *connector);
 int analogix_dp_stop_crc(struct drm_connector *connector);
 
+struct analogix_dp_plat_data *analogix_dp_aux_to_plat_data(struct drm_dp_aux *aux);
+struct drm_dp_aux *analogix_dp_get_aux(struct analogix_dp_device *dp);
+
 #endif /* _ANALOGIX_DP_H_ */
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:07 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:07 +0800
Subject: [PATCH v8 06/13] drm/bridge: analogix_dp: Add support to get panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-7-damon.ding@rock-chips.com>

The main modification is moving the DP AUX initialization from function
analogix_dp_bind() to analogix_dp_probe(). In order to get the EDID of
eDP panel during probing, it is also needed to advance PM operations to
ensure that eDP controller and phy are prepared for AUX transmission.

Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v4:
- Use done_probing() to call drm_of_find_panel_or_bridge() and
  component_add() when getting panel from the DP AUX bus

Changes in v5:
- Advance PM operations to make eDP AUX work well

Changes in v6:
- Use devm_pm_runtime_enable() instead of devm_add_action_or_reset()
- Add a new function analogix_dp_remove() to ensure symmetry for PM
  operations

Changes in v7:
- Fix the misspelling of word 'operations' in commit message
- Remove the check related to CONFIG_PM
- Remove the unnecessary call to pm_runtime_dont_use_autosuspend() if
  devm_pm_runtime_enable() fails
- Remove unnecessary function analogix_dp_remove()
- Add new function analogix_dpaux_wait_hpd_asserted()

Changes in v8:
- Move the addition of the analogix_dpaux_wait_hpd_asserted() to the
  other patch
---
 .../drm/bridge/analogix/analogix_dp_core.c    | 20 ++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index dd91760c4b1c..2b76a9cf3bcb 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1650,6 +1650,17 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 		return ERR_PTR(ret);
 	}
 
+	dp->aux.name = "DP-AUX";
+	dp->aux.transfer = analogix_dpaux_transfer;
+	dp->aux.dev = dp->dev;
+	drm_dp_aux_init(&dp->aux);
+
+	pm_runtime_use_autosuspend(dp->dev);
+	pm_runtime_set_autosuspend_delay(dp->dev, 100);
+	ret = devm_pm_runtime_enable(dp->dev);
+	if (ret)
+		return ERR_PTR(ret);
+
 	return dp;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_probe);
@@ -1696,15 +1707,6 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
 	dp->drm_dev = drm_dev;
 	dp->encoder = dp->plat_data->encoder;
 
-	pm_runtime_use_autosuspend(dp->dev);
-	pm_runtime_set_autosuspend_delay(dp->dev, 100);
-	ret = devm_pm_runtime_enable(dp->dev);
-	if (ret)
-		return ret;
-
-	dp->aux.name = "DP-AUX";
-	dp->aux.transfer = analogix_dpaux_transfer;
-	dp->aux.dev = dp->dev;
 	dp->aux.drm_dev = drm_dev;
 
 	ret = drm_dp_aux_register(&dp->aux);
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:08 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:08 +0800
Subject: [PATCH v8 07/13] drm/bridge: analogix_dp: Add support for &drm_dp_aux.wait_hpd_asserted()
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-8-damon.ding@rock-chips.com>

Add analogix_dpaux_wait_hpd_asserted() to help confirm the HPD state
before doing AUX transfers.

Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
---
 .../drm/bridge/analogix/analogix_dp_core.c    | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 2b76a9cf3bcb..b7e143b3ff75 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1548,6 +1548,26 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
 	return ret;
 }
 
+static int analogix_dpaux_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
+{
+	struct analogix_dp_device *dp = to_dp(aux);
+	int val;
+	int ret;
+
+	if (dp->force_hpd)
+		return 0;
+
+	pm_runtime_get_sync(dp->dev);
+
+	ret = readx_poll_timeout(analogix_dp_get_plug_in_status, dp, val, !val,
+				 wait_us / 100, wait_us);
+
+	pm_runtime_mark_last_busy(dp->dev);
+	pm_runtime_put_autosuspend(dp->dev);
+
+	return ret;
+}
+
 struct analogix_dp_device *
 analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 {
@@ -1652,6 +1672,7 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 
 	dp->aux.name = "DP-AUX";
 	dp->aux.transfer = analogix_dpaux_transfer;
+	dp->aux.wait_hpd_asserted = analogix_dpaux_wait_hpd_asserted;
 	dp->aux.dev = dp->dev;
 	drm_dp_aux_init(&dp->aux);
 
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:09 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:09 +0800
Subject: [PATCH v8 08/13] drm/rockchip: analogix_dp: Add support to get panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-9-damon.ding@rock-chips.com>

Move drm_of_find_panel_or_bridge() a little later and combine it with
component_add() into a new function rockchip_dp_link_panel(). The function
will serve as done_probing() callback of devm_of_dp_aux_populate_bus(),
aiding to support for obtaining the eDP panel via the DP AUX bus.

If failed to get the panel from the DP AUX bus, it will then try the other
way to get panel information through the platform bus.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v4:
- Use done_probing() to call drm_of_find_panel_or_bridge() and
  component_add() when getting panel from the DP AUX bus

Changes in v5:
- Use the functions exported by the Analogix side to get the pointers of
  struct analogix_dp_plat_data and struct drm_dp_aux.
- Use dev_err() instead of drm_err() in rockchip_dp_poweron().

Changes in v6:
- Keep drm_err() in rockchip_dp_poweron()
- Pass 'dp' in drm_...() rather than 'dp->drm_dev'

Changes in v7:
- Include the drm_dp_aux_bus.h for devm_of_dp_aux_populate_bus()
- Use dev_err_probe() for the return value check of
  devm_of_dp_aux_populate_bus()
- Select DRM_DISPLAY_DP_AUX_BUS if ROCKCHIP_ANALOGIX_DP
- Restore the error check for drm_of_find_panel_or_bridge() which was
  removed by mistake

Changes in v8:
- Add comments when drm_of_find_panel_or_bridge() returns -ENODEV
- Remove some redundant return cases
- Add comments when devm_of_dp_aux_populate_bus() returns -ENODEV
---
 drivers/gpu/drm/rockchip/Kconfig              |  1 +
 .../gpu/drm/rockchip/analogix_dp-rockchip.c   | 42 +++++++++++++++----
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 26c4410b2407..f9d7776a859a 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
 	select DRM_PANEL
 	select VIDEOMODE_HELPERS
 	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
+	select DRM_DISPLAY_DP_AUX_BUS if ROCKCHIP_ANALOGIX_DP
 	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
 	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
 	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index a8265a1bf9ff..5632b7e3e122 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -21,6 +21,7 @@
 #include <video/of_videomode.h>
 #include <video/videomode.h>
 
+#include <drm/display/drm_dp_aux_bus.h>
 #include <drm/display/drm_dp_helper.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -392,11 +393,28 @@ static const struct component_ops rockchip_dp_component_ops = {
 	.unbind = rockchip_dp_unbind,
 };
 
+static int rockchip_dp_link_panel(struct drm_dp_aux *aux)
+{
+	struct analogix_dp_plat_data *plat_data = analogix_dp_aux_to_plat_data(aux);
+	struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
+	int ret;
+
+	/*
+	 * If drm_of_find_panel_or_bridge() returns -ENODEV, there may be no valid panel
+	 * or bridge nodes. The driver should go on for the driver-free bridge or the DP
+	 * mode applications.
+	 */
+	ret = drm_of_find_panel_or_bridge(dp->dev->of_node, 1, 0, &plat_data->panel, NULL);
+	if (ret && ret != -ENODEV)
+		return ret;
+
+	return component_add(dp->dev, &rockchip_dp_component_ops);
+}
+
 static int rockchip_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct rockchip_dp_chip_data *dp_data;
-	struct drm_panel *panel = NULL;
 	struct rockchip_dp_device *dp;
 	struct resource *res;
 	int i;
@@ -406,10 +424,6 @@ static int rockchip_dp_probe(struct platform_device *pdev)
 	if (!dp_data)
 		return -ENODEV;
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
-	if (ret < 0 && ret != -ENODEV)
-		return ret;
-
 	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
 	if (!dp)
 		return -ENOMEM;
@@ -432,7 +446,6 @@ static int rockchip_dp_probe(struct platform_device *pdev)
 
 	dp->dev = dev;
 	dp->adp = ERR_PTR(-ENODEV);
-	dp->plat_data.panel = panel;
 	dp->plat_data.dev_type = dp->data->chip_type;
 	dp->plat_data.power_on = rockchip_dp_poweron;
 	dp->plat_data.power_off = rockchip_dp_powerdown;
@@ -448,9 +461,20 @@ static int rockchip_dp_probe(struct platform_device *pdev)
 	if (IS_ERR(dp->adp))
 		return PTR_ERR(dp->adp);
 
-	ret = component_add(dev, &rockchip_dp_component_ops);
-	if (ret)
-		return ret;
+	ret = devm_of_dp_aux_populate_bus(analogix_dp_get_aux(dp->adp), rockchip_dp_link_panel);
+	if (ret) {
+		/*
+		 * If devm_of_dp_aux_populate_bus() returns -ENODEV, the done_probing() will not
+		 * be called because there are no EP devices. Then the rockchip_dp_link_panel()
+		 * will be called directly in order to support the other valid DT configurations.
+		 *
+		 * NOTE: The devm_of_dp_aux_populate_bus() is allowed to return -EPROBE_DEFER.
+		 */
+		if (ret != -ENODEV)
+			return dev_err_probe(dp->dev, ret, "failed to populate aux bus\n");
+
+		return rockchip_dp_link_panel(analogix_dp_get_aux(dp->adp));
+	}
 
 	return 0;
 }
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:10 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:10 +0800
Subject: [PATCH v8 09/13] dt-bindings: display: rockchip: analogix-dp: Add support for RK3588
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-10-damon.ding@rock-chips.com>

Compared with RK3288/RK3399, the HBR2 link rate support is the main
improvement of RK3588 eDP TX controller, and there are also two
independent eDP display interfaces on RK3588 Soc.

The newly added 'apb' reset is to ensure the APB bus of eDP controller
works well on the RK3588 SoC.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v2:
- Add the main defferences of the RK3588 eDP and the previous versions
  in commit message

Changes in v3:
- Expand the property clock-names, resets and reset-names

Changes in v4:
- Remove 'spdif' clock which added in v3
- Add the comment of newly added 'apb' reset in commit message

Changes in v5:
- Put the differences between RK3288/RK3399 and RK3588 into 'allOf'

Changes in v6:
- Keep the widest constraints and add only RK3588 related constraints
  into 'allOf'

Changes in v7:
- Fix the errors related to 'reset-names'
- Remove unnecessary 'maxItems' under 'reset-names'
---
 .../rockchip/rockchip,analogix-dp.yaml        | 22 +++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
index eaf4e67e232e..d99b23b88cc5 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
@@ -15,6 +15,7 @@ properties:
     enum:
       - rockchip,rk3288-dp
       - rockchip,rk3399-edp
+      - rockchip,rk3588-edp
 
   clocks:
     minItems: 2
@@ -31,10 +32,14 @@ properties:
     maxItems: 1
 
   resets:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
 
   reset-names:
-    const: dp
+    minItems: 1
+    items:
+      - const: dp
+      - const: apb
 
   rockchip,grf:
     $ref: /schemas/types.yaml#/definitions/phandle
@@ -55,6 +60,19 @@ required:
 allOf:
   - $ref: /schemas/display/bridge/analogix,dp.yaml#
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - rockchip,rk3588-edp
+    then:
+      properties:
+        resets:
+          minItems: 2
+        reset-names:
+          minItems: 2
+
 unevaluatedProperties: false
 
 examples:
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:11 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:11 +0800
Subject: [PATCH v8 10/13] drm/bridge: analogix_dp: Add support for RK3588
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-11-damon.ding@rock-chips.com>

Expand enum analogix_dp_devtype with RK3588_EDP, and add max_link_rate
and max_lane_count configs for it.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v5:
- Add the RK3588_EDP related modification in analogix_dp.h
- Move this commit above related commit on the Rockchip side
---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 ++++
 include/drm/bridge/analogix_dp.h                   | 3 ++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index b7e143b3ff75..c06429142a40 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1513,6 +1513,10 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
 		video_info->max_link_rate = 0x0A;
 		video_info->max_lane_count = 0x04;
 		break;
+	case RK3588_EDP:
+		video_info->max_link_rate = 0x14;
+		video_info->max_lane_count = 0x04;
+		break;
 	case EXYNOS_DP:
 		/*
 		 * NOTE: those property parseing code is used for
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index e19b0bbc57d6..cf17646c1310 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -16,11 +16,12 @@ enum analogix_dp_devtype {
 	EXYNOS_DP,
 	RK3288_DP,
 	RK3399_EDP,
+	RK3588_EDP,
 };
 
 static inline bool is_rockchip(enum analogix_dp_devtype type)
 {
-	return type == RK3288_DP || type == RK3399_EDP;
+	return type == RK3288_DP || type == RK3399_EDP || type == RK3588_EDP;
 }
 
 struct analogix_dp_plat_data {
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:12 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:12 +0800
Subject: [PATCH v8 11/13] drm/rockchip: analogix_dp: Add support for RK3588
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-12-damon.ding@rock-chips.com>

RK3588 integrates the Analogix eDP 1.3 TX controller IP and the HDMI/eDP
TX Combo PHY based on a Samsung IP block. There are also two independent
eDP display interface with different address on RK3588 Soc.

The patch currently adds only the basic support, specifically RGB output
up to 4K at 60Hz, without the tests for audio, PSR and other eDP 1.3 specific
features.

In additon, the above Analogix IP has always been utilized as eDP on
Rockchip platform, despite its capability to also support the DP v1.2.
Therefore, the newly added logs will contain the term 'edp' rather than
'dp'. And the newly added 'apb' reset control is to ensure the APB bus
of eDP controller works well on the RK3588 SoC.

Acked-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v2:
- Add support for the other eDP output edp1

Changes in v3:
- Fix the unexpected use of alias
- Add more details in commit message

Changes in v4:
- Add the 'apb' reset control

Changes in v5:
- Use drm_...()/dev_...() instead of DRM_...()
- Clean &rockchip_dp_chip_data.reg related comments in commit message
- Move the modifications in anlogix_dp.h to the Analogix side in order
  to avoid the warning:

  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c:1506:10: warning:
  enumeration value 'RK3588_EDP' not handled in switch [-Wswitch]
          switch (dp->plat_data->dev_type) {

Changes in v6:
- Pass 'dp' in drm_...() rather than 'dp->drm_dev'
- Use drm_...() uniformly rather than mixing drm_...() and dev_..()

Changes in v7:
- Just keep the DRM_...() as they were in the previous for this series
---
 .../gpu/drm/rockchip/analogix_dp-rockchip.c   | 61 ++++++++++++++++++-
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 5632b7e3e122..d30f0983a53a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -52,11 +52,13 @@ struct rockchip_grf_reg_field {
 /**
  * struct rockchip_dp_chip_data - splite the grf setting of kind of chips
  * @lcdc_sel: grf register field of lcdc_sel
+ * @edp_mode: grf register field of edp_mode
  * @chip_type: specific chip type
  * @reg: register base address
  */
 struct rockchip_dp_chip_data {
 	const struct rockchip_grf_reg_field lcdc_sel;
+	const struct rockchip_grf_reg_field edp_mode;
 	u32	chip_type;
 	u32	reg;
 };
@@ -71,6 +73,7 @@ struct rockchip_dp_device {
 	struct clk               *grfclk;
 	struct regmap            *grf;
 	struct reset_control     *rst;
+	struct reset_control     *apbrst;
 
 	const struct rockchip_dp_chip_data *data;
 
@@ -116,6 +119,10 @@ static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
 	usleep_range(10, 20);
 	reset_control_deassert(dp->rst);
 
+	reset_control_assert(dp->apbrst);
+	usleep_range(10, 20);
+	reset_control_deassert(dp->apbrst);
+
 	return 0;
 }
 
@@ -137,12 +144,21 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
 		return ret;
 	}
 
+	ret = rockchip_grf_field_write(dp->grf, &dp->data->edp_mode, 1);
+	if (ret != 0)
+		DRM_DEV_ERROR(dp->dev, "failed to set edp mode %d\n", ret);
+
 	return ret;
 }
 
 static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
 {
 	struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
+	int ret;
+
+	ret = rockchip_grf_field_write(dp->grf, &dp->data->edp_mode, 0);
+	if (ret != 0)
+		DRM_DEV_ERROR(dp->dev, "failed to set edp mode %d\n", ret);
 
 	clk_disable_unprepare(dp->pclk);
 
@@ -206,6 +222,10 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
 	struct rockchip_dp_device *dp = encoder_to_dp(encoder);
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *old_crtc_state;
+	struct of_endpoint endpoint;
+	struct device_node *remote_port, *remote_port_parent;
+	char name[32];
+	u32 port_id;
 	int ret;
 
 	crtc = rockchip_dp_drm_get_new_crtc(encoder, state);
@@ -223,13 +243,27 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
 		return;
 	}
 
-	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
+	ret = drm_of_encoder_active_endpoint(dp->dev->of_node, encoder, &endpoint);
 	if (ret < 0)
 		return;
 
-	DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
+	remote_port_parent = of_graph_get_remote_port_parent(endpoint.local_node);
+	if (remote_port_parent) {
+		if (of_get_child_by_name(remote_port_parent, "ports")) {
+			remote_port = of_graph_get_remote_port(endpoint.local_node);
+			of_property_read_u32(remote_port, "reg", &port_id);
+			of_node_put(remote_port);
+			sprintf(name, "%s vp%d", remote_port_parent->full_name, port_id);
+		} else {
+			sprintf(name, "%s %s",
+				remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb");
+		}
+		of_node_put(remote_port_parent);
+
+		DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
+	}
 
-	ret = rockchip_grf_field_write(dp->grf, &dp->data->lcdc_sel, ret);
+	ret = rockchip_grf_field_write(dp->grf, &dp->data->lcdc_sel, endpoint.id);
 	if (ret != 0)
 		DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret);
 
@@ -323,6 +357,12 @@ static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
 		return PTR_ERR(dp->rst);
 	}
 
+	dp->apbrst = devm_reset_control_get_optional(dev, "apb");
+	if (IS_ERR(dp->apbrst)) {
+		DRM_DEV_ERROR(dev, "failed to get apb reset control\n");
+		return PTR_ERR(dp->apbrst);
+	}
+
 	return 0;
 }
 
@@ -525,9 +565,24 @@ static const struct rockchip_dp_chip_data rk3288_dp[] = {
 	{ /* sentinel */ }
 };
 
+static const struct rockchip_dp_chip_data rk3588_edp[] = {
+	{
+		.edp_mode = GRF_REG_FIELD(0x0000, 0, 0),
+		.chip_type = RK3588_EDP,
+		.reg = 0xfdec0000,
+	},
+	{
+		.edp_mode = GRF_REG_FIELD(0x0004, 0, 0),
+		.chip_type = RK3588_EDP,
+		.reg = 0xfded0000,
+	},
+	{ /* sentinel */ }
+};
+
 static const struct of_device_id rockchip_dp_dt_ids[] = {
 	{.compatible = "rockchip,rk3288-dp", .data = &rk3288_dp },
 	{.compatible = "rockchip,rk3399-edp", .data = &rk3399_edp },
+	{.compatible = "rockchip,rk3588-edp", .data = &rk3588_edp },
 	{}
 };
 MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:13 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:13 +0800
Subject: [PATCH v8 12/13] arm64: dts: rockchip: Add eDP0 node for RK3588
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-13-damon.ding@rock-chips.com>

Add support for the eDP0 output on RK3588 SoC.

Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v3:
- Remove currently unsupported property '#sound-dai-cells'

Changes in v4:
- Remove currently unsupported clock 'spdif'
---
 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index 2403a3950128..7e089422c947 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1410,6 +1410,34 @@ hdmi0_out: port at 1 {
 		};
 	};
 
+	edp0: edp at fdec0000 {
+		compatible = "rockchip,rk3588-edp";
+		reg = <0x0 0xfdec0000 0x0 0x1000>;
+		clocks = <&cru CLK_EDP0_24M>, <&cru PCLK_EDP0>;
+		clock-names = "dp", "pclk";
+		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH 0>;
+		phys = <&hdptxphy0>;
+		phy-names = "dp";
+		power-domains = <&power RK3588_PD_VO1>;
+		resets = <&cru SRST_EDP0_24M>, <&cru SRST_P_EDP0>;
+		reset-names = "dp", "apb";
+		rockchip,grf = <&vo1_grf>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			edp0_in: port at 0 {
+				reg = <0>;
+			};
+
+			edp0_out: port at 1 {
+				reg = <1>;
+			};
+		};
+	};
+
 	qos_gpu_m0: qos at fdf35000 {
 		compatible = "rockchip,rk3588-qos", "syscon";
 		reg = <0x0 0xfdf35000 0x0 0x20>;
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:14 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:14 +0800
Subject: [PATCH v8 13/13] arm64: dts: rockchip: Enable eDP0 display on RK3588S EVB1 board
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-14-damon.ding@rock-chips.com>

Add the necessary DT changes to enable eDP0 on RK3588S EVB1 board:
- Set pinctrl of pwm12 for backlight
- Enable edp0/hdptxphy0/vp2
- Assign the parent of DCLK_VOP2_SRC to PLL_V0PLL
- Add aux-bus/panel nodes

For RK3588, the PLL_V0PLL is specifically designed for the VOP2. This
means the clock rate of PLL_V0PLL can be adjusted according to the dclk
rate of relevant VP. It is typically assigned as the dclk source of a
specific VP when the clock of relevant display mode is unusual, such as
the eDP panel 'lg,lp079qx1-sp0v' paired with RK3588S EVB1, which has a
clock rate of 202.02MHz.

Additionally, the 'force-hpd' is set for edp0 because the HPD pin on the
panel side is not connected to the eDP HPD pin on the SoC side according
to the RK3588S EVB1 hardware design.

Signed-off-by: Damon Ding <damon.ding at rock-chips.com>

---

Changes in v2:
- Remove brightness-levels and default-brightness-level properties in
  backlight node.
- Add the detail DT changes to commit message.

Changes in v3:
- Use aux-bus instead of platform bus for edp-panel.

Changes in v4:
- Add comments related to the use of panel compatible "lg,lp079qx1-sp0v"
  in the commit message.

Changes in v5:
- Use "edp-panel" instead of "lg,lp079qx1-sp0v"
- Remove unnecessary comments in commit message
- Assign the parent of DCLK_VOP2_SRC to PLL_V0PLL

Changes in v6:
- Add PLL_V0PLL related descriptions in commit message

Changes in v7:
- Describe why to set the 'force-hpd' for edp0
- Add no-hpd for the panel node
---
 .../boot/dts/rockchip/rk3588s-evb1-v10.dts    | 55 +++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
index bc4077575beb..de52a6600b7b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
@@ -9,6 +9,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
 #include <dt-bindings/usb/pd.h>
 #include "rk3588s.dtsi"
 
@@ -238,6 +239,42 @@ &combphy2_psu {
 	status = "okay";
 };
 
+&edp0 {
+	force-hpd;
+	status = "okay";
+
+	aux-bus {
+		panel {
+			compatible = "edp-panel";
+			backlight = <&backlight>;
+			power-supply = <&vcc3v3_lcd_edp>;
+			no-hpd;
+
+			port {
+				panel_in_edp: endpoint {
+					remote-endpoint = <&edp_out_panel>;
+				};
+			};
+		};
+	};
+};
+
+&edp0_in {
+	edp0_in_vp2: endpoint {
+		remote-endpoint = <&vp2_out_edp0>;
+	};
+};
+
+&edp0_out {
+	edp_out_panel: endpoint {
+		remote-endpoint = <&panel_in_edp>;
+	};
+};
+
+&hdptxphy0 {
+	status = "okay";
+};
+
 &i2c3 {
 	status = "okay";
 
@@ -399,6 +436,7 @@ usbc0_int: usbc0-int {
 };
 
 &pwm12 {
+	pinctrl-0 = <&pwm12m1_pins>;
 	status = "okay";
 };
 
@@ -1168,3 +1206,20 @@ usbdp_phy0_dp_altmode_mux: endpoint at 1 {
 		};
 	};
 };
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vop {
+	assigned-clocks = <&cru DCLK_VOP2_SRC>;
+	assigned-clock-parents = <&cru PLL_V0PLL>;
+	status = "okay";
+};
+
+&vp2 {
+	vp2_out_edp0: endpoint at ROCKCHIP_VOP2_EP_EDP0 {
+		reg = <ROCKCHIP_VOP2_EP_EDP0>;
+		remote-endpoint = <&edp0_in_vp2>;
+	};
+};
-- 
2.34.1



From Yong.Wu at mediatek.com  Mon Mar 10 03:45:03 2025
From: Yong.Wu at mediatek.com (=?utf-8?B?WW9uZyBXdSAo5ZC05YuHKQ==?=)
Date: Mon, 10 Mar 2025 10:45:03 +0000
Subject: [PATCH] memory: mtk-smi: Add ostd setting for mt8192
In-Reply-To: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
References: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
Message-ID: <ba7863b39d259c469b58f53285d1bb0f2c48a0b0.camel@mediatek.com>

On Fri, 2025-03-07 at 13:45 +0800, Xueqi Zhang wrote:
> Add initial ostd setting for mt8192. All the settings come from DE.
> These settings help adjust Multimedia HW's bandwidth limits to
> achieve
> a balanced bandwidth requirement.
> Without this, the VENC HW work abnormal while stress testing.
> 
> Fixes: 02c02ddce427 ("memory: mtk-smi: Add mt8192 support")
> Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>

Reviewed-by: Yong Wu <yong.wu at mediatek.com>

Thanks.

From peng.fan at nxp.com  Mon Mar 10 03:45:44 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Mon, 10 Mar 2025 10:45:44 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z86w3ZRS6T2MvV3X@bogus>
References: <Z6uFMW94QNpFxQLK@bogus>
 <20250212070120.GD15796@localhost.localdomain> <Z6x8cNyDt8rJ73_B@bogus>
 <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto> <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus> <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus> <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
Message-ID: <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> fwnode for scmi cpufreq
> 
> On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
> >
> > Sorry, if I misunderstood.
> >
> > I will give a look on this and propose a RFC.
> >
> > DT maintainers may ask for a patchset including binding change and
> > driver changes to get a whole view on the compatible stuff.
> >
> > BTW, Cristian, Saravana if you have any objections/ideas or would
> take
> > on this effort, please let me know.
> >
> 
> Can you point me to the DTS with which you are seeing this issue ?
> I am trying to reproduce the issue but so far not successful. I did move
> to power-domains for CPUFreq on Juno. IIUC all we need is both
> cpufreq and performance genpd drivers in the kernel and then GPU
> using perf genpd fails with probe deferral right ? I need pointers to
> reproduce the issue so that I can check if what I have cooked up as a
> solution really works.

This is in downstream tree:
https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L2971
https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L3043
https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L80

we are using "power-domains" property for cpu perf and gpu/vpu perf.

If cpufreq.off=1 is set in bootargs, the vpu/gpu driver will defer probe.

Regards,
Peng.

> 
> --
> Regards,
> Sudeep


From ansuelsmth at gmail.com  Mon Mar 10 03:47:00 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Mon, 10 Mar 2025 11:47:00 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
 <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>
Message-ID: <67cec328.170a0220.27ecbc.9c6e@mx.google.com>

On Mon, Mar 10, 2025 at 10:21:45AM +0100, Krzysztof Kozlowski wrote:
> On 09/03/2025 14:29, Christian Marangi wrote:
> > Add Documentation for Airoha EN7581 SCU.
> > 
> > Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
> > via the SCU (System Controller Unit).
> > 
> > Example of these pheriperals are reset-controller, clock-controller,
> > PCIe line speed controller and bits to configure different Serdes ports
> > for USB or Ethernet usage.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
> >  .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
> >  1 file changed, 68 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> > new file mode 100644
> > index 000000000000..d7dc66f912c1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> > @@ -0,0 +1,68 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Airoha EN7581 SCU (System Controller Unit)
> > +
> > +maintainers:
> > +  - Christian Marangi <ansuelsmth at gmail.com>
> > +
> > +description:
> > +  Airoha EN7581 SoC expose registers to control miscellaneous
> > +  pheriperals via the SCU (System Controller Unit).
> > +
> One more comment - there is no such thing as "sysctl" in your hardware.
> Look at the SCU binding which clearly says that it is the hardware you
> are duplicating here, so the "System Control Unit".
> 
> So you have existing "This node defines the System Control Unit of the
> EN7523 SoC" and you add one more node which defines the "System Control
> Unit", so you have two "System Control Unit" device nodes?
> 
> Look also what Stephen asked for:
> 
> https://lore.kernel.org/all/20220106013100.842FCC36AEB at smtp.kernel.org/
> 
> so how system-controller can now became clock-controller? Now, it was
> the system controller since the beginning.
>

The main problem here (and we had a similar problem with GPIO and PWM)
is that the Vendor (Airoha) wasn't so bright in placing the different
registers for the SoC so we have case where everything is mixed and not
one after another... 

Example we have 
- CLK register part 1
- Some bits that configure PCIe
- CLK register part 2
- GPIO
- CLK register part 3
- ...

The driver solution for this is syscon and the simple-mfd node
structure.

Now the main problem is how to modle this in DT. There are lots of case
where the simple-mfd model is used (like the one proposed) but probably
this is not accepted anymore. But again this should be clearly stated or
we have a chicken-egg problem when other devs implement similar thing and
have to implement simple MFD driver to handle this. (and driver
maintainers say "Use the simple-mfd model like it was already done)

For this specific case (and to give an answer to the clock patch after
this) the problem is that this register space was originally used only
to control the clock and I wasn't aware that it was also used to control
USB. Now that I'm implementing support for it, the disaster happened.

So In short SCU is lots of thing, both a system-controller, a
clock-controller and even a reset-controller.

To make it short, 2 different solution:
1. We can keep the current node structure of the node-controller and add a
child node for the SSR part (with a dedicated compatible).
2. Those property need to be be defined in the clock-controller node?

The ideal solution is 1. Does it work for you?

Sorry for the long post and hope you understand why this mess of
reworking the binding.

-- 
	Ansuel


From andre.przywara at arm.com  Mon Mar 10 03:48:21 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 10 Mar 2025 10:48:21 +0000
Subject: [PATCH v7 22/27] dt-bindings: allwinner: add H616 DE33 mixer
 binding
In-Reply-To: <c8b85753-5c97-4258-a158-06a17929fad6@app.fastmail.com>
References: <20250216183710.8443-3-ryan@testtoast.com>
	<20250216183710.8443-23-ryan@testtoast.com>
	<20250224175642.170c124e@donnerap.manchester.arm.com>
	<c8b85753-5c97-4258-a158-06a17929fad6@app.fastmail.com>
Message-ID: <20250310104821.3c85977a@donnerap.manchester.arm.com>

On Mon, 10 Mar 2025 22:30:36 +1300
"Ryan Walklin" <ryan at testtoast.com> wrote:

Hi Ryan,

> On Tue, 25 Feb 2025, at 6:56 AM, Andre Przywara wrote:
> 
> Apologies Andre, I came to review your comments on the TCON series and realised I had missed responding to this comment before sending v8. 

No worries about that!

> >> +      - allwinner,sun50i-h616-de33-mixer-0
> >>  
> >>    reg:
> >> -    maxItems: 1
> >> +    minItems: 1
> >> +    maxItems: 3  
> >
> > What are those three regions? I wonder if we should have reg-names here,
> > to fix the order, and to document them on the way?  
> 
> This would be the top, display and mixer groups for the DE333, and mixer for DE3 and earlier. Can certainly add in names for these. Is there any example elsewhere in the bindings to look at?

It's basically the same idea as for clock-names, as used in this very file
here (allwinner,sun8i-a83t-de2-mixer.yaml). You can find an explicit
example for reg-names in allwinner,sun4i-a10-mbus.yaml, for instance.
In the code you would use devm_platform_ioremap_resource_byname() then.

Cheers,
Andre

> >> @@ -61,6 +63,23 @@ properties:
> >>      required:
> >>        - port at 1
> >>  
> >> +allOf:
> >> +  - if:
> >> +      properties:
> >> +        compatible:
> >> +          enum:
> >> +            - allwinner,sun50i-h616-de33-mixer-0
> >> +
> >> +    then:
> >> +      properties:
> >> +        reg:
> >> +          maxItems: 3  
> >
> > Should we override minItems here as well? I guess any driver would need
> > all three region to work?  
> 
> This seems sensible, as you say it would always be 3 groups for the DE33.
> 
> Regards,
> 
> Ryan



From dan.carpenter at linaro.org  Mon Mar 10 03:48:27 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 10 Mar 2025 13:48:27 +0300
Subject: [PATCH net] net: ethernet: mediatek: Fix bit field in
 mtk_set_queue_speed()
Message-ID: <eaab1b7b-b33b-458b-a89a-81391bd2e6e8@stanley.mountain>

This was supposed to set "FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1)"
but there was typo and the | operation was missing and which turned
it into a no-op.

Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
>From static analysis, not tested.

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 922330b3f4d7..9efef0e860da 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -757,7 +757,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
 		case SPEED_100:
 			val |= MTK_QTX_SCH_MAX_RATE_EN |
 			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
-			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
 			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
 			break;
 		case SPEED_1000:
-- 
2.47.2



From damon.ding at rock-chips.com  Mon Mar 10 03:41:01 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:01 +0800
Subject: [PATCH v8 00/13] Add eDP support for RK3588
Message-ID: <20250310104114.2608063-1-damon.ding@rock-chips.com>

Picked from:
https://patchwork.kernel.org/project/linux-rockchip/list/?series=936932

These patchs have been tested with a 1536x2048p60 eDP panel on
RK3588S EVB1 board, and HDMI 1080P/4K display also has been verified
on RK3588 EVB1 board. Furthermore, the eDP display has been rechecked
on RK3399 sapphire excavator board.

Patch 1~3   are preparations for the RK3588 eDP support on both Analogix
            side.
Patch 4~8   are to support to get panel from the DP AUX bus.
Patch 9~11  are the RK3588 Analogix DP driver support.
Patch 12    is the addition of RK3588 eDP0 node.
Patch 13    is to enable the eDP0 display on RK3588S EVB1 board.

Damon Ding (13):
  drm/bridge: analogix_dp: Add irq flag IRQF_NO_AUTOEN instead of
    calling disable_irq()
  drm/bridge: analogix_dp: Remove CONFIG_PM related check in
    analogix_dp_bind()/analogix_dp_unbind()
  drm/bridge: analogix_dp: Add support for phy configuration.
  dt-bindings: display: rockchip: analogix-dp: Add support to get panel
    from the DP AUX bus
  drm/bridge: analogix_dp: Support to get &analogix_dp_device.plat_data
    and &analogix_dp_device.aux
  drm/bridge: analogix_dp: Add support to get panel from the DP AUX bus
  drm/bridge: analogix_dp: Add support for
    &drm_dp_aux.wait_hpd_asserted()
  drm/rockchip: analogix_dp: Add support to get panel from the DP AUX
    bus
  dt-bindings: display: rockchip: analogix-dp: Add support for RK3588
  drm/bridge: analogix_dp: Add support for RK3588
  drm/rockchip: analogix_dp: Add support for RK3588
  arm64: dts: rockchip: Add eDP0 node for RK3588
  arm64: dts: rockchip: Enable eDP0 display on RK3588S EVB1 board

 .../rockchip/rockchip,analogix-dp.yaml        |  25 ++++-
 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi |  28 +++++
 .../boot/dts/rockchip/rk3588s-evb1-v10.dts    |  55 ++++++++++
 .../drm/bridge/analogix/analogix_dp_core.c    |  85 +++++++++------
 .../gpu/drm/bridge/analogix/analogix_dp_reg.c |  52 +++++++++
 drivers/gpu/drm/rockchip/Kconfig              |   1 +
 .../gpu/drm/rockchip/analogix_dp-rockchip.c   | 103 ++++++++++++++++--
 include/drm/bridge/analogix_dp.h              |   7 +-
 8 files changed, 310 insertions(+), 46 deletions(-)

-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:02 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:02 +0800
Subject: [PATCH v8 01/13] drm/bridge: analogix_dp: Add irq flag IRQF_NO_AUTOEN instead of calling disable_irq()
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-2-damon.ding@rock-chips.com>

The IRQF_NO_AUTOEN can be used for the drivers that don't want
interrupts to be enabled automatically via devm_request_threaded_irq().
Using this flag can provide be more robust compared to the way of
calling disable_irq() after devm_request_threaded_irq() without the
IRQF_NO_AUTOEN flag.

Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 817070613b03..5ef6bb6010ca 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1630,10 +1630,10 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 		 * that we can get the current state of the GPIO.
 		 */
 		dp->irq = gpiod_to_irq(dp->hpd_gpiod);
-		irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+		irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN;
 	} else {
 		dp->irq = platform_get_irq(pdev, 0);
-		irq_flags = 0;
+		irq_flags = IRQF_NO_AUTOEN;
 	}
 
 	if (dp->irq == -ENXIO) {
@@ -1649,7 +1649,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 		dev_err(&pdev->dev, "failed to request irq\n");
 		return ERR_PTR(ret);
 	}
-	disable_irq(dp->irq);
 
 	return dp;
 }
-- 
2.34.1



From damon.ding at rock-chips.com  Mon Mar 10 03:41:03 2025
From: damon.ding at rock-chips.com (Damon Ding)
Date: Mon, 10 Mar 2025 18:41:03 +0800
Subject: [PATCH v8 02/13] drm/bridge: analogix_dp: Remove CONFIG_PM related check in analogix_dp_bind()/analogix_dp_unbind()
In-Reply-To: <20250310104114.2608063-1-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
Message-ID: <20250310104114.2608063-3-damon.ding@rock-chips.com>

Remove the check related to CONFIG_PM in order to make the code more
concise, as the CONFIG_PM should be a required option for many drivers.

In addition, it is preferable to use devm_pm_runtime_enable() instead of
manually invoking pm_runtime_enable() followed by pm_runtime_disable().

Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
---
 .../drm/bridge/analogix/analogix_dp_core.c    | 30 ++++---------------
 1 file changed, 6 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5ef6bb6010ca..132f8513f93f 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1695,15 +1695,11 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
 	dp->drm_dev = drm_dev;
 	dp->encoder = dp->plat_data->encoder;
 
-	if (IS_ENABLED(CONFIG_PM)) {
-		pm_runtime_use_autosuspend(dp->dev);
-		pm_runtime_set_autosuspend_delay(dp->dev, 100);
-		pm_runtime_enable(dp->dev);
-	} else {
-		ret = analogix_dp_resume(dp);
-		if (ret)
-			return ret;
-	}
+	pm_runtime_use_autosuspend(dp->dev);
+	pm_runtime_set_autosuspend_delay(dp->dev, 100);
+	ret = devm_pm_runtime_enable(dp->dev);
+	if (ret)
+		return ret;
 
 	dp->aux.name = "DP-AUX";
 	dp->aux.transfer = analogix_dpaux_transfer;
@@ -1713,7 +1709,7 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
 	ret = drm_dp_aux_register(&dp->aux);
 	if (ret) {
 		DRM_ERROR("failed to register AUX (%d)\n", ret);
-		goto err_disable_pm_runtime;
+		return ret;
 	}
 
 	ret = analogix_dp_create_bridge(drm_dev, dp);
@@ -1726,13 +1722,6 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
 
 err_unregister_aux:
 	drm_dp_aux_unregister(&dp->aux);
-err_disable_pm_runtime:
-	if (IS_ENABLED(CONFIG_PM)) {
-		pm_runtime_dont_use_autosuspend(dp->dev);
-		pm_runtime_disable(dp->dev);
-	} else {
-		analogix_dp_suspend(dp);
-	}
 
 	return ret;
 }
@@ -1749,13 +1738,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp)
 	}
 
 	drm_dp_aux_unregister(&dp->aux);
-
-	if (IS_ENABLED(CONFIG_PM)) {
-		pm_runtime_dont_use_autosuspend(dp->dev);
-		pm_runtime_disable(dp->dev);
-	} else {
-		analogix_dp_suspend(dp);
-	}
 }
 EXPORT_SYMBOL_GPL(analogix_dp_unbind);
 
-- 
2.34.1



From dan.carpenter at linaro.org  Mon Mar 10 03:48:34 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 10 Mar 2025 13:48:34 +0300
Subject: [PATCH next] pinctrl: bcm281xx: Add missing assignment in
 bcm21664_pinctrl_lock_all()
Message-ID: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>

The next line checks if this regmap_write() failed, but it doesn't
work because the assignment was accidentally left out.  Add the
assignment.

Fixes: 60d69769c851 ("pinctrl: bcm281xx: Add support for BCM21664 pinmux")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
index 7c8f8bd7da12..9ea20fde3a24 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -1498,8 +1498,8 @@ static int bcm21664_pinctrl_lock_all(struct bcm281xx_pinctrl_data *pdata)
 				rc);
 			return rc;
 		}
-		regmap_write(pdata->regmap, BCM21664_ACCESS_LOCK_OFFSET(i),
-			     0xffffffff);
+		rc = regmap_write(pdata->regmap, BCM21664_ACCESS_LOCK_OFFSET(i),
+				  0xffffffff);
 		if (rc) {
 			dev_err(pdata->dev, "Failed to write access lock: %d\n",
 				rc);
-- 
2.47.2



From leo.yan at arm.com  Mon Mar 10 03:55:51 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:55:51 +0000
Subject: [PATCH v2 1/5] perf: Allow periodic events to alternate between
 two sample periods
In-Reply-To: <c62a9f8a-312d-4f9e-9022-265e53564101@arm.com>
References: <20250106120156.227273-1-mark.barnett@arm.com>
 <20250106120156.227273-2-mark.barnett@arm.com>
 <20250121130154.GA416913@e132581.arm.com>
 <c62a9f8a-312d-4f9e-9022-265e53564101@arm.com>
Message-ID: <20250310105551.GB9682@e132581.arm.com>

On Fri, Mar 07, 2025 at 08:28:13PM +0000, Mark Barnett wrote:
> On 1/21/25 13:01, Leo Yan wrote:
> > >   	local64_set(&hwc->period_left, hwc->sample_period);
> > > +	if (attr->alt_sample_period) {
> > > +		hwc->sample_period = attr->alt_sample_period;
> > > +		hwc->using_alt_sample_period = true;
> > > +	}
> > 
> > My understanding it sets a short sample window for the first period.
> > Would it initialize the `hwc->period_left` with the updated sample
> > period?
> > 
> 
> It sets the long period first: hwc->period_left is used to program the PMU
> when setting up the event, and hwc->sample_period is queued up as the next
> period to switch to.

Makes sense to me.  Thanks for explanation.

Leo


From ping.bai at nxp.com  Mon Mar 10 03:56:51 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Mon, 10 Mar 2025 10:56:51 +0000
Subject: [PATCH] cpufreq: Init cpufreq only for present CPUs
In-Reply-To: <Z868xB3_3NhMsa7R@bogus>
References: <20250310071640.3140435-1-ping.bai@nxp.com>
 <Z868xB3_3NhMsa7R@bogus>
Message-ID: <AS8PR04MB864253339F818E0FC0D9982287D62@AS8PR04MB8642.eurprd04.prod.outlook.com>

Hi Sudeep,

> Subject: Re: [PATCH] cpufreq: Init cpufreq only for present CPUs
> 
> On Mon, Mar 10, 2025 at 03:16:40PM +0800, Jacky Bai wrote:
> > for_each_possible_cpu() is currently used to initialize cpufreq in
> > below cpufreq drivers:
> >   drivers/cpufreq/cpufreq-dt.c
> >   drivers/cpufreq/mediatek-cpufreq-hw.c
> >   drivers/cpufreq/mediatek-cpufreq.c
> >   drivers/cpufreq/qcom-cpufreq-nvmem.c
> >   drivers/cpufreq/sun50i-cpufreq-nvmem.c
> >
> 
> Again how did you just narrow down to the list above ? Is that just a random
> pick ? As I suggested with corresponding cpuidle changes, please look into the
> details in side the for_each_possible_cpu() loop and then decide if it applies
> or not.
> 
> For me, it applied to the below files as well at the least.
> 
> drivers/cpufreq/mvebu-cpufreq.c
> drivers/cpufreq/qcom-cpufreq-hw.c
> drivers/cpufreq/scmi-cpufreq.c
> drivers/cpufreq/scpi-cpufreq.c
> drivers/cpufreq/virtual-cpufreq.c
> 

I checked these drivers before, these drivers has logic to check
if the cpu device is available, then skip the not present cpu.
>From my understanding, using 'for_each_possible_cpu' will not
cause the cpufreq driver failed to register for nosmp case, so I skipped.
For those I just changed in the patch, the cpufreq will be failed to register totally.
I can changes all of them together as you suggested if no other guys object.

Thank you for your comments. :)

BR
Jacky Bai
> Please check everything thoroughly as I just looked at these briefly.
> 
> --
> Regards,
> Sudeep


From suzuki.poulose at arm.com  Mon Mar 10 03:57:25 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 10:57:25 +0000
Subject: [PATCH v2 1/8] coresight: etm4x: Extract the trace unit
 controlling
In-Reply-To: <20250310104919.58816-2-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-2-leo.yan@arm.com>
Message-ID: <bb390d95-7f2b-4327-a809-9e4cdbd1a1bc@arm.com>

Hi Leo

On 10/03/2025 10:49, Leo Yan wrote:
> The trace unit is controlled in the ETM hardware enabling and disabling.
> The sequential changes for support AUX pause and resume will reuse the
> same operations.
> 
> Extract the operations in the etm4_{enable|disable}_trace_unit()
> functions.  A minor improvement in etm4_enable_trace_unit() is for
> returning the timeout error to callers.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>

fyi, this area of code has changes significantly and will cause
conflicts, due to the introduction of synchronization after
each access to the TRCSTATR. Please rebase your next version on
the coresight next branch to avoid the conflict.

The changes as such look good to me.

Suzuki



> ---
>   .../coresight/coresight-etm4x-core.c          | 126 ++++++++++--------
>   1 file changed, 74 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 2c1a60577728..71be566bd117 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -428,6 +428,78 @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
>   }
>   #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
>   
> +static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
> +{
> +	struct coresight_device *csdev = drvdata->csdev;
> +	struct device *etm_dev = &csdev->dev;
> +	struct csdev_access *csa = &csdev->access;
> +
> +	/*
> +	 * ETE mandates that the TRCRSR is written to before
> +	 * enabling it.
> +	 */
> +	if (etm4x_is_ete(drvdata))
> +		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
> +
> +	etm4x_allow_trace(drvdata);
> +	/* Enable the trace unit */
> +	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
> +
> +	/* Synchronize the register updates for sysreg access */
> +	if (!csa->io_mem)
> +		isb();
> +
> +	/* wait for TRCSTATR.IDLE to go back down to '0' */
> +	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) {
> +		dev_err(etm_dev,
> +			"timeout while waiting for Idle Trace Status\n");
> +		return -ETIME;
> +	}
> +
> +	/*
> +	 * As recommended by section 4.3.7 ("Synchronization when using the
> +	 * memory-mapped interface") of ARM IHI 0064D
> +	 */
> +	dsb(sy);
> +	isb();
> +
> +	return 0;
> +}
> +
> +static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
> +{
> +	u32 control;
> +	struct coresight_device *csdev = drvdata->csdev;
> +	struct device *etm_dev = &csdev->dev;
> +	struct csdev_access *csa = &csdev->access;
> +
> +	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
> +
> +	/* EN, bit[0] Trace unit enable bit */
> +	control &= ~0x1;
> +
> +	/*
> +	 * If the CPU supports v8.4 Trace filter Control,
> +	 * set the ETM to trace prohibited region.
> +	 */
> +	etm4x_prohibit_trace(drvdata);
> +	/*
> +	 * Make sure everything completes before disabling, as recommended
> +	 * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
> +	 * SSTATUS") of ARM IHI 0064D
> +	 */
> +	dsb(sy);
> +	isb();
> +	/* Trace synchronization barrier, is a nop if not supported */
> +	tsb_csync();
> +	etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
> +
> +	/* wait for TRCSTATR.PMSTABLE to go to '1' */
> +	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
> +		dev_err(etm_dev,
> +			"timeout while waiting for PM stable Trace Status\n");
> +}
> +
>   static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>   {
>   	int i, rc;
> @@ -536,33 +608,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>   		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
>   	}
>   
> -	/*
> -	 * ETE mandates that the TRCRSR is written to before
> -	 * enabling it.
> -	 */
> -	if (etm4x_is_ete(drvdata))
> -		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
> -
> -	etm4x_allow_trace(drvdata);
> -	/* Enable the trace unit */
> -	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
> -
> -	/* Synchronize the register updates for sysreg access */
> -	if (!csa->io_mem)
> -		isb();
> -
> -	/* wait for TRCSTATR.IDLE to go back down to '0' */
> -	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
> -		dev_err(etm_dev,
> -			"timeout while waiting for Idle Trace Status\n");
> -
> -	/*
> -	 * As recommended by section 4.3.7 ("Synchronization when using the
> -	 * memory-mapped interface") of ARM IHI 0064D
> -	 */
> -	dsb(sy);
> -	isb();
> -
> +	rc = etm4_enable_trace_unit(drvdata);
>   done:
>   	etm4_cs_lock(drvdata, csa);
>   
> @@ -906,7 +952,6 @@ static void etm4_disable_hw(void *info)
>   	struct etmv4_drvdata *drvdata = info;
>   	struct etmv4_config *config = &drvdata->config;
>   	struct coresight_device *csdev = drvdata->csdev;
> -	struct device *etm_dev = &csdev->dev;
>   	struct csdev_access *csa = &csdev->access;
>   	int i;
>   
> @@ -920,31 +965,8 @@ static void etm4_disable_hw(void *info)
>   		etm4x_relaxed_write32(csa, control, TRCPDCR);
>   	}
>   
> -	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
> +	etm4_disable_trace_unit(drvdata);
>   
> -	/* EN, bit[0] Trace unit enable bit */
> -	control &= ~0x1;
> -
> -	/*
> -	 * If the CPU supports v8.4 Trace filter Control,
> -	 * set the ETM to trace prohibited region.
> -	 */
> -	etm4x_prohibit_trace(drvdata);
> -	/*
> -	 * Make sure everything completes before disabling, as recommended
> -	 * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
> -	 * SSTATUS") of ARM IHI 0064D
> -	 */
> -	dsb(sy);
> -	isb();
> -	/* Trace synchronization barrier, is a nop if not supported */
> -	tsb_csync();
> -	etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
> -
> -	/* wait for TRCSTATR.PMSTABLE to go to '1' */
> -	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
> -		dev_err(etm_dev,
> -			"timeout while waiting for PM stable Trace Status\n");
>   	/* read the status of the single shot comparators */
>   	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
>   		config->ss_status[i] =



From ansuelsmth at gmail.com  Mon Mar 10 03:57:41 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Mon, 10 Mar 2025 11:57:41 +0100
Subject: [net-next PATCH v12 12/13] net: dsa: Add Airoha AN8855 5-Port
 Gigabit DSA Switch driver
In-Reply-To: <Z83WgMeg_IxgbxhO@shell.armlinux.org.uk>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-13-ansuelsmth@gmail.com>
 <Z83WgMeg_IxgbxhO@shell.armlinux.org.uk>
Message-ID: <67cec5a9.170a0220.93f86.9dcf@mx.google.com>

On Sun, Mar 09, 2025 at 05:57:20PM +0000, Russell King (Oracle) wrote:
> On Sun, Mar 09, 2025 at 06:26:57PM +0100, Christian Marangi wrote:
> > +static int an8855_port_enable(struct dsa_switch *ds, int port,
> > +			      struct phy_device *phy)
> > +{
> > +	struct an8855_priv *priv = ds->priv;
> > +
> > +	return regmap_set_bits(priv->regmap, AN8855_PMCR_P(port),
> > +			       AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
> 
> Shouldn't you wait for phylink to call your mac_link_up() method?
>

Did something change recently for this? I checked the pattern for other
driver and port enable normally just enable TX/RX traffic for the port.

Any hint for this?

> > +}
> > +
> > +static void an8855_port_disable(struct dsa_switch *ds, int port)
> > +{
> > +	struct an8855_priv *priv = ds->priv;
> > +	int ret;
> > +
> > +	ret = regmap_clear_bits(priv->regmap, AN8855_PMCR_P(port),
> > +				AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN);
> > +	if (ret)
> > +		dev_err(priv->ds->dev, "failed to disable port: %d\n", ret);
> 
> Doesn't the link get set down before this is called? IOW, doesn't
> phylink call your mac_link_down() method first?
> 
> ...
> 
> > +static void an8855_phylink_mac_link_up(struct phylink_config *config,
> > +				       struct phy_device *phydev, unsigned int mode,
> > +				       phy_interface_t interface, int speed,
> > +				       int duplex, bool tx_pause, bool rx_pause)
> > +{
> > +	struct dsa_port *dp = dsa_phylink_to_port(config);
> > +	struct an8855_priv *priv = dp->ds->priv;
> > +	int port = dp->index;
> > +	u32 reg;
> > +
> > +	reg = regmap_read(priv->regmap, AN8855_PMCR_P(port), &reg);
> > +	if (phylink_autoneg_inband(mode)) {
> > +		reg &= ~AN8855_PMCR_FORCE_MODE;
> > +	} else {
> > +		reg |= AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK;
> > +
> > +		reg &= ~AN8855_PMCR_FORCE_SPEED;
> > +		switch (speed) {
> > +		case SPEED_10:
> > +			reg |= AN8855_PMCR_FORCE_SPEED_10;
> > +			break;
> > +		case SPEED_100:
> > +			reg |= AN8855_PMCR_FORCE_SPEED_100;
> > +			break;
> > +		case SPEED_1000:
> > +			reg |= AN8855_PMCR_FORCE_SPEED_1000;
> > +			break;
> > +		case SPEED_2500:
> > +			reg |= AN8855_PMCR_FORCE_SPEED_2500;
> > +			break;
> > +		case SPEED_5000:
> > +			dev_err(priv->ds->dev, "Missing support for 5G speed. Aborting...\n");
> > +			return;
> > +		}
> > +
> > +		reg &= ~AN8855_PMCR_FORCE_FDX;
> > +		if (duplex == DUPLEX_FULL)
> > +			reg |= AN8855_PMCR_FORCE_FDX;
> > +
> > +		reg &= ~AN8855_PMCR_RX_FC_EN;
> > +		if (rx_pause || dsa_port_is_cpu(dp))
> > +			reg |= AN8855_PMCR_RX_FC_EN;
> > +
> > +		reg &= ~AN8855_PMCR_TX_FC_EN;
> > +		if (rx_pause || dsa_port_is_cpu(dp))
> > +			reg |= AN8855_PMCR_TX_FC_EN;
> > +
> > +		/* Disable any EEE options */
> > +		reg &= ~(AN8855_PMCR_FORCE_EEE5G | AN8855_PMCR_FORCE_EEE2P5G |
> > +			 AN8855_PMCR_FORCE_EEE1G | AN8855_PMCR_FORCE_EEE100);
> 
> Why? Maybe consider implementing the phylink tx_lpi functions for EEE
> support.
> 

Will do, I disabled this as the EEE rework was being approved.

> > +	}
> > +
> > +	reg |= AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN;
> > +
> > +	regmap_write(priv->regmap, AN8855_PMCR_P(port), reg);
> > +}
> > +
> > +static unsigned int an8855_pcs_inband_caps(struct phylink_pcs *pcs,
> > +					   phy_interface_t interface)
> > +{
> > +	/* SGMII can be configured to use inband with AN result */
> > +	if (interface == PHY_INTERFACE_MODE_SGMII)
> > +		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
> > +
> > +	/* inband is not supported in 2500-baseX and must be disabled */
> > +	return  LINK_INBAND_DISABLE;
> 
> Spurious double space.
> 

Will drop.

> > +}
> > +
> > +static void an8855_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
> > +				 struct phylink_link_state *state)
> > +{
> > +	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = regmap_read(priv->regmap, AN8855_PMSR_P(AN8855_CPU_PORT), &val);
> > +	if (ret < 0) {
> > +		state->link = false;
> > +		return;
> > +	}
> > +
> > +	state->link = !!(val & AN8855_PMSR_LNK);
> > +	state->an_complete = state->link;
> > +	state->duplex = (val & AN8855_PMSR_DPX) ? DUPLEX_FULL :
> > +						  DUPLEX_HALF;
> > +
> > +	switch (val & AN8855_PMSR_SPEED) {
> > +	case AN8855_PMSR_SPEED_10:
> > +		state->speed = SPEED_10;
> > +		break;
> > +	case AN8855_PMSR_SPEED_100:
> > +		state->speed = SPEED_100;
> > +		break;
> > +	case AN8855_PMSR_SPEED_1000:
> > +		state->speed = SPEED_1000;
> > +		break;
> > +	case AN8855_PMSR_SPEED_2500:
> > +		state->speed = SPEED_2500;
> > +		break;
> > +	case AN8855_PMSR_SPEED_5000:
> > +		dev_err(priv->ds->dev, "Missing support for 5G speed. Setting Unknown.\n");
> > +		fallthrough;
> 
> Which is wrong now, we have SPEED_5000.
> 

Maybe the comments weren't so clear. The Switch doesn't support the
speed... Even if it does have bits, the switch doesn't support it. And
the 2500 speed is really only for the CPU port. The user port are only
gigabit.

> > +	default:
> > +		state->speed = SPEED_UNKNOWN;
> > +		break;
> > +	}
> > +
> > +	if (val & AN8855_PMSR_RX_FC)
> > +		state->pause |= MLO_PAUSE_RX;
> > +	if (val & AN8855_PMSR_TX_FC)
> > +		state->pause |= MLO_PAUSE_TX;
> > +}
> > +
> > +static int an8855_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
> > +			     phy_interface_t interface,
> > +			     const unsigned long *advertising,
> > +			     bool permit_pause_to_mac)
> > +{
> > +	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
> > +	u32 val;
> > +	int ret;
> > +
> > +	/*                   !!! WELCOME TO HELL !!!                   */
> > +
> [... hell ...]

Will drop :( It was an easter egg for the 300 lines to configure PCS.

> > +	ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_2,
> > +			   AN8855_RG_RXFC_AN_BYPASS_P3 |
> > +			   AN8855_RG_RXFC_AN_BYPASS_P2 |
> > +			   AN8855_RG_RXFC_AN_BYPASS_P1 |
> > +			   AN8855_RG_TXFC_AN_BYPASS_P3 |
> > +			   AN8855_RG_TXFC_AN_BYPASS_P2 |
> > +			   AN8855_RG_TXFC_AN_BYPASS_P1 |
> > +			   AN8855_RG_DPX_AN_BYPASS_P3 |
> > +			   AN8855_RG_DPX_AN_BYPASS_P2 |
> > +			   AN8855_RG_DPX_AN_BYPASS_P1 |
> > +			   AN8855_RG_DPX_AN_BYPASS_P0);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return 0;
> 
> Is this disruptive to the link if the link is up, and this is called
> (e.g. to change the advertisement rather than switch interface mode).
> If so, please do something about that - e.g. only doing the bulk of
> the configuration if the interface mode has changed.

Airoha confirmed this is not disruptive, applying these config doesn't
terminate or disrupt the link.

> 
> I guess, however, that as you're only using SGMII with in-band, it
> probably doesn't make much difference, but having similar behaviour
> in the various drivers helps with ongoing maintenance.

Do we have some driver that implement the logic of skipping the bulk of
configuration if the mode doesn't change?

Maybe we can introduce some kind of additional OP like .init to apply
the very initial configuration that are not related to the mode.
Or something like .setup?

-- 
	Ansuel


From kory.maincent at bootlin.com  Mon Mar 10 03:58:45 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 10 Mar 2025 11:58:45 +0100
Subject: [PATCH net-next v2 1/7] net: ethtool: netlink: Allow
 per-netdevice DUMP operations
In-Reply-To: <20250308155440.267782-2-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
	<20250308155440.267782-2-maxime.chevallier@bootlin.com>
Message-ID: <20250310115845.17a04100@kmaincent-XPS-13-7390>

On Sat,  8 Mar 2025 16:54:33 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> We have a number of netlink commands in the ethnl family that may have
> multiple objects to dump even for a single net_device, including :
> 
>  - PLCA, PSE-PD, phy: one message per PHY device
>  - tsinfo: one message per timestamp source (netdev + phys)
>  - rss: One per RSS context
> 
> To get this behaviour, these netlink commands need to roll a custom
> ->dumpit().  
> 
> To prepare making per-netdev DUMP more generic in ethnl, introduce a
> member in the ethnl ops to indicate if a given command may allow
> pernetdev DUMPs (also referred to as filtered DUMPs).
> 
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---
> V2: - Rebase
>     - Fix kdoc
>     - Fix bissectabilitu by using the right function names
> 
>  net/ethtool/netlink.c | 45 ++++++++++++++++++++++++++++---------------
>  net/ethtool/netlink.h |  2 ++
>  2 files changed, 31 insertions(+), 16 deletions(-)
> 
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index 70834947f474..11e4122b7707 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -586,21 +586,34 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
>  	int ret = 0;
>  
>  	rcu_read_lock();
> -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> -		dev_hold(dev);
> +	if (ctx->req_info->dev) {
> +		dev = ctx->req_info->dev;
>  		rcu_read_unlock();
> -
> -		ret = ethnl_default_dump_one(skb, dev, ctx,
> genl_info_dump(cb)); -
> +		/* Filtered DUMP request targeted to a single netdev. We
> already
> +		 * hold a ref to the netdev from ->start()
> +		 */
> +		ret = ethnl_default_dump_one(skb, dev, ctx,
> +					     genl_info_dump(cb));
>  		rcu_read_lock();
> -		dev_put(dev);
> -
> -		if (ret < 0 && ret != -EOPNOTSUPP) {
> -			if (likely(skb->len))
> -				ret = skb->len;
> -			break;

You are not checking -EOPNOTSUPP, so you can return this error in the
ctx->req_info->dev condition. I am not sure about the policy but do we want to
report the EOPNOTSUPP error in the dump command instead of simply returning
nothing.

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From leo.yan at arm.com  Mon Mar 10 04:02:51 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 11:02:51 +0000
Subject: [PATCH v2 2/5] coresight: add coresight Trace NOC driver
In-Reply-To: <c0848f24-26c4-4282-9813-1842c2a50c1e@quicinc.com>
References: <20250226-trace-noc-driver-v2-0-8afc6584afc5@quicinc.com>
 <20250226-trace-noc-driver-v2-2-8afc6584afc5@quicinc.com>
 <20250227113910.GA2157064@e132581.arm.com>
 <c0848f24-26c4-4282-9813-1842c2a50c1e@quicinc.com>
Message-ID: <20250310110251.GC9682@e132581.arm.com>

On Thu, Mar 06, 2025 at 04:22:20PM +0800, Yuanfang Zhang wrote:

[...]

> >> +static int trace_noc_init_default_data(struct trace_noc_drvdata *drvdata)
> >> +{
> >> +       int atid;
> >> +
> >> +       atid = coresight_trace_id_get_system_id();
> >> +       if (atid < 0)
> >> +               return atid;
> >> +
> >> +       drvdata->atid = atid;
> >> +
> >> +       drvdata->freq_type = FREQ_TS;
> > 
> > I don't see anywhere uses FREQ.  Please remove the unused definitions
> > and related code.
>
> it is used in trace_noc_enable_hw().

I understood some macros and definitions are used by seqential patches.

A good practice is code should be added only when they are used.  This
can allow every patch in neat way and easier for review.

Thanks,
Leo

> > 
> >> +       drvdata->flag_type = FLAG;
> > 
> > FLAG_TS is not used in the driver as well.  Remove it.
> it is used in trace_noc_enable_hw().


From linux at armlinux.org.uk  Mon Mar 10 04:05:53 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 11:05:53 +0000
Subject: [net-next PATCH v12 12/13] net: dsa: Add Airoha AN8855 5-Port
 Gigabit DSA Switch driver
In-Reply-To: <67cec5a9.170a0220.93f86.9dcf@mx.google.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-13-ansuelsmth@gmail.com>
 <Z83WgMeg_IxgbxhO@shell.armlinux.org.uk>
 <67cec5a9.170a0220.93f86.9dcf@mx.google.com>
Message-ID: <Z87HkcdK2QTjooDK@shell.armlinux.org.uk>

On Mon, Mar 10, 2025 at 11:57:41AM +0100, Christian Marangi wrote:
> > > +static int an8855_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
> > > +			     phy_interface_t interface,
> > > +			     const unsigned long *advertising,
> > > +			     bool permit_pause_to_mac)
> > > +{
> > > +	struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs);
> > > +	u32 val;
> > > +	int ret;
> > > +
> > > +	/*                   !!! WELCOME TO HELL !!!                   */
> > > +
> > [... hell ...]
> 
> Will drop :( It was an easter egg for the 300 lines to configure PCS.

That wasn't a request to drop the comment, just that I didn't want to
include all that in my reply.

> > I guess, however, that as you're only using SGMII with in-band, it
> > probably doesn't make much difference, but having similar behaviour
> > in the various drivers helps with ongoing maintenance.
> 
> Do we have some driver that implement the logic of skipping the bulk of
> configuration if the mode doesn't change?

For many, it doesn't matter, but for e.g. xpcs, there may be a reset
of the XPCS when the mode changes, and there's workarounds for the
TXGBE - both of those only happen when the interface mode actually
changes.

Re-reading my .pcs_config() documentation, I really ought to mention
that .pcs_config() will be called for both interface mode changes and
for advertisement changes, and should not disrupt the link when
nothing has changed.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From quic_pbrahma at quicinc.com  Mon Mar 10 04:18:33 2025
From: quic_pbrahma at quicinc.com (Pratyush Brahma)
Date: Mon, 10 Mar 2025 16:48:33 +0530
Subject: [PATCH v6 0/2] Add support for GPU SMMU on QCS8300
Message-ID: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>

Enable GPU SMMU function on QCS8300 platform. GPU SMMU is required
for address translation in GPU device.

Signed-off-by: Pratyush Brahma <quic_pbrahma at quicinc.com>
---
Changes since v5:
- Corrected the clock order to be compatible with existing bindings
- Link to v5: https://lore.kernel.org/r/20250211-b4-branch-gfx-smmu-v5-0-ff0bcb6a3c51 at quicinc.com

Changes since v4:
- Corrected the clocks list to be inline with clock-names
- Removed stray whitespaces
- Added r-by tag from Krzysztof on the bindings patch
- Link to v4: https://lore.kernel.org/r/20250203-b4-branch-gfx-smmu-v4-0-eaa7aa762f48 at quicinc.com

Changes since v3:
- Modified the order of clock voting and properties as suggested by Konrad
- Removed dependency on clocks in commit text as change is merged in
  linux-next before current base commit

Link to v3:
https://lore.kernel.org/all/20241227105818.28516-1-quic_pbrahma at quicinc.com/

Changes since v2:
Corrected typo in cover letter to include QCS8300
Link to
v2:https://lore.kernel.org/all/20241227104651.4531-1-quic_pbrahma at quicinc.com/

Changes since v1:
Updated bindings for gpu smmu for qcs8300 as per Dmitry's comment
Link to v1:
https://lore.kernel.org/all/20241224100521.7616-1-quic_pbrahma at quicinc.com/

To: Will Deacon <will at kernel.org>
To: Robin Murphy <robin.murphy at arm.com>
To: Joerg Roedel <joro at 8bytes.org>
To: Rob Herring <robh at kernel.org>
To: Krzysztof Kozlowski <krzk+dt at kernel.org>
To: Conor Dooley <conor+dt at kernel.org>
To: Bjorn Andersson <andersson at kernel.org>
To: Konrad Dybcio <konradybcio at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: devicetree at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-msm at vger.kernel.org

---
Pratyush Brahma (2):
      dt-bindings: arm-smmu: Document QCS8300 GPU SMMU
      arm64: dts: qcom: qcs8300: Add device node for  gfx_smmu

 .../devicetree/bindings/iommu/arm,smmu.yaml        |  3 +-
 arch/arm64/boot/dts/qcom/qcs8300.dtsi              | 39 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)
---
base-commit: a13f6e0f405ed0d3bcfd37c692c7d7fa3c052154
change-id: 20250131-b4-branch-gfx-smmu-b03261963064

Best regards,
-- 
Pratyush Brahma <quic_pbrahma at quicinc.com>



From quic_pbrahma at quicinc.com  Mon Mar 10 04:18:34 2025
From: quic_pbrahma at quicinc.com (Pratyush Brahma)
Date: Mon, 10 Mar 2025 16:48:34 +0530
Subject: [PATCH v6 1/2] dt-bindings: arm-smmu: Document QCS8300 GPU SMMU
In-Reply-To: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
References: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
Message-ID: <20250310-b4-branch-gfx-smmu-v6-1-15c60b8abd99@quicinc.com>

Add the compatible for Qualcomm QCS8300 GPU SMMU. Add the compatible
in the list of clocks required by the GPU SMMU and remove it from the
list of disallowed clocks.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Pratyush Brahma <quic_pbrahma at quicinc.com>
---
 Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 032fdc27127bffd689ffc23630c9978c4460b336..7b9d5507d6ccd6b845a57eeae59fe80ba75cc652 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -90,6 +90,7 @@ properties:
           - enum:
               - qcom,qcm2290-smmu-500
               - qcom,qcs615-smmu-500
+              - qcom,qcs8300-smmu-500
               - qcom,sa8255p-smmu-500
               - qcom,sa8775p-smmu-500
               - qcom,sar2130p-smmu-500
@@ -397,6 +398,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - qcom,qcs8300-smmu-500
               - qcom,sa8775p-smmu-500
               - qcom,sc7280-smmu-500
               - qcom,sc8280xp-smmu-500
@@ -581,7 +583,6 @@ allOf:
               - cavium,smmu-v2
               - marvell,ap806-smmu-500
               - nvidia,smmu-500
-              - qcom,qcs8300-smmu-500
               - qcom,qdu1000-smmu-500
               - qcom,sa8255p-smmu-500
               - qcom,sc7180-smmu-500

-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:11 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:11 +0000
Subject: [PATCH v2 0/8] Arm CoreSight: Support AUX pause and resume
Message-ID: <20250310104919.58816-1-leo.yan@arm.com>

This series is to enable AUX pause and resume on Arm CoreSight.

The first patch extracts the trace unit controlling operations to two
functions.  These two functions will be used by AUX pause and resume.

Patches 02 and 03 change the ETMv4 driver to prepare callback functions
for AUX pause and resume.

Patch 04 changes the ETM perf layer to support AUX pause and resume in a
perf session.  The patches 05 and 06 offers an extra feature for
updating buffer on AUX pause occasion, which can mitigate the trace data
lose issue.

Patch 07 documents the AUX pause usages with Arm CoreSight.  The last
patch syncs headers between user space and the kernel.

This patch set has been verified on the Hikey960 board and TC platform.
The previous one uses ETR and the later uses TRBE as sink.

It is suggested to disable CPUIdle (add `nohlt` option in Linux command
line) when verifying this series.  ETM and funnel drivers are found
issues during CPU suspend and resume which will be addressed separately.

Changes from v1:
- Added validation function pointers in pause and resume APIs (Mike).


Leo Yan (8):
  coresight: etm4x: Extract the trace unit controlling
  coresight: Introduce pause and resume APIs for source
  coresight: etm4x: Hook pause and resume callbacks
  coresight: perf: Support AUX trace pause and resume
  coresight: etm: Add an attribute for updating buffer
  coresight: perf: Update buffer on AUX pause
  Documentation: coresight: Document AUX pause and resume
  perf cs-etm: Sync kernel coresight-pmu.h header

 .../trace/coresight/coresight-perf.rst        |  50 ++++++
 drivers/hwtracing/coresight/coresight-core.c  |  20 +++
 .../hwtracing/coresight/coresight-etm-perf.c  |  94 +++++++++-
 .../hwtracing/coresight/coresight-etm-perf.h  |   2 +
 .../coresight/coresight-etm4x-core.c          | 166 ++++++++++++------
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +
 drivers/hwtracing/coresight/coresight-priv.h  |   2 +
 include/linux/coresight-pmu.h                 |   1 +
 include/linux/coresight.h                     |   4 +
 tools/include/linux/coresight-pmu.h           |   1 +
 10 files changed, 289 insertions(+), 53 deletions(-)

-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:12 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:12 +0000
Subject: [PATCH v2 1/8] coresight: etm4x: Extract the trace unit controlling
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-2-leo.yan@arm.com>

The trace unit is controlled in the ETM hardware enabling and disabling.
The sequential changes for support AUX pause and resume will reuse the
same operations.

Extract the operations in the etm4_{enable|disable}_trace_unit()
functions.  A minor improvement in etm4_enable_trace_unit() is for
returning the timeout error to callers.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../coresight/coresight-etm4x-core.c          | 126 ++++++++++--------
 1 file changed, 74 insertions(+), 52 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2c1a60577728..71be566bd117 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -428,6 +428,78 @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
 }
 #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
 
+static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
+{
+	struct coresight_device *csdev = drvdata->csdev;
+	struct device *etm_dev = &csdev->dev;
+	struct csdev_access *csa = &csdev->access;
+
+	/*
+	 * ETE mandates that the TRCRSR is written to before
+	 * enabling it.
+	 */
+	if (etm4x_is_ete(drvdata))
+		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
+
+	etm4x_allow_trace(drvdata);
+	/* Enable the trace unit */
+	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
+
+	/* Synchronize the register updates for sysreg access */
+	if (!csa->io_mem)
+		isb();
+
+	/* wait for TRCSTATR.IDLE to go back down to '0' */
+	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) {
+		dev_err(etm_dev,
+			"timeout while waiting for Idle Trace Status\n");
+		return -ETIME;
+	}
+
+	/*
+	 * As recommended by section 4.3.7 ("Synchronization when using the
+	 * memory-mapped interface") of ARM IHI 0064D
+	 */
+	dsb(sy);
+	isb();
+
+	return 0;
+}
+
+static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
+{
+	u32 control;
+	struct coresight_device *csdev = drvdata->csdev;
+	struct device *etm_dev = &csdev->dev;
+	struct csdev_access *csa = &csdev->access;
+
+	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
+
+	/* EN, bit[0] Trace unit enable bit */
+	control &= ~0x1;
+
+	/*
+	 * If the CPU supports v8.4 Trace filter Control,
+	 * set the ETM to trace prohibited region.
+	 */
+	etm4x_prohibit_trace(drvdata);
+	/*
+	 * Make sure everything completes before disabling, as recommended
+	 * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
+	 * SSTATUS") of ARM IHI 0064D
+	 */
+	dsb(sy);
+	isb();
+	/* Trace synchronization barrier, is a nop if not supported */
+	tsb_csync();
+	etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
+
+	/* wait for TRCSTATR.PMSTABLE to go to '1' */
+	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
+		dev_err(etm_dev,
+			"timeout while waiting for PM stable Trace Status\n");
+}
+
 static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 {
 	int i, rc;
@@ -536,33 +608,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
 	}
 
-	/*
-	 * ETE mandates that the TRCRSR is written to before
-	 * enabling it.
-	 */
-	if (etm4x_is_ete(drvdata))
-		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
-
-	etm4x_allow_trace(drvdata);
-	/* Enable the trace unit */
-	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
-
-	/* Synchronize the register updates for sysreg access */
-	if (!csa->io_mem)
-		isb();
-
-	/* wait for TRCSTATR.IDLE to go back down to '0' */
-	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
-		dev_err(etm_dev,
-			"timeout while waiting for Idle Trace Status\n");
-
-	/*
-	 * As recommended by section 4.3.7 ("Synchronization when using the
-	 * memory-mapped interface") of ARM IHI 0064D
-	 */
-	dsb(sy);
-	isb();
-
+	rc = etm4_enable_trace_unit(drvdata);
 done:
 	etm4_cs_lock(drvdata, csa);
 
@@ -906,7 +952,6 @@ static void etm4_disable_hw(void *info)
 	struct etmv4_drvdata *drvdata = info;
 	struct etmv4_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
-	struct device *etm_dev = &csdev->dev;
 	struct csdev_access *csa = &csdev->access;
 	int i;
 
@@ -920,31 +965,8 @@ static void etm4_disable_hw(void *info)
 		etm4x_relaxed_write32(csa, control, TRCPDCR);
 	}
 
-	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
+	etm4_disable_trace_unit(drvdata);
 
-	/* EN, bit[0] Trace unit enable bit */
-	control &= ~0x1;
-
-	/*
-	 * If the CPU supports v8.4 Trace filter Control,
-	 * set the ETM to trace prohibited region.
-	 */
-	etm4x_prohibit_trace(drvdata);
-	/*
-	 * Make sure everything completes before disabling, as recommended
-	 * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
-	 * SSTATUS") of ARM IHI 0064D
-	 */
-	dsb(sy);
-	isb();
-	/* Trace synchronization barrier, is a nop if not supported */
-	tsb_csync();
-	etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
-
-	/* wait for TRCSTATR.PMSTABLE to go to '1' */
-	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
-		dev_err(etm_dev,
-			"timeout while waiting for PM stable Trace Status\n");
 	/* read the status of the single shot comparators */
 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
 		config->ss_status[i] =
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:13 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:13 +0000
Subject: [PATCH v2 2/8] coresight: Introduce pause and resume APIs for source
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-3-leo.yan@arm.com>

Introduce APIs for pausing and resuming trace source and export as GPL
symbols.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 drivers/hwtracing/coresight/coresight-core.c | 20 ++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-priv.h |  2 ++
 include/linux/coresight.h                    |  4 ++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 0a9380350fb5..eb7b83a7bfa2 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -365,6 +365,26 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
 }
 EXPORT_SYMBOL_GPL(coresight_disable_source);
 
+void coresight_pause_source(struct coresight_device *csdev)
+{
+	if (!csdev || !coresight_is_percpu_source(csdev))
+		return;
+
+	if (source_ops(csdev)->pause)
+		source_ops(csdev)->pause(csdev);
+}
+EXPORT_SYMBOL_GPL(coresight_pause_source);
+
+void coresight_resume_source(struct coresight_device *csdev)
+{
+	if (!csdev || !coresight_is_percpu_source(csdev))
+		return;
+
+	if (source_ops(csdev)->resume)
+		source_ops(csdev)->resume(csdev);
+}
+EXPORT_SYMBOL_GPL(coresight_resume_source);
+
 /*
  * coresight_disable_path_from : Disable components in the given path beyond
  * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 76403530f33e..a9f14c075e91 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -247,5 +247,7 @@ void coresight_add_helper(struct coresight_device *csdev,
 void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
 struct coresight_device *coresight_get_percpu_sink(int cpu);
 void coresight_disable_source(struct coresight_device *csdev, void *data);
+void coresight_pause_source(struct coresight_device *csdev);
+void coresight_resume_source(struct coresight_device *csdev);
 
 #endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 17276965ff1d..703e1b8dbe22 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -385,6 +385,8 @@ struct coresight_ops_link {
  *		is associated to.
  * @enable:	enables tracing for a source.
  * @disable:	disables tracing for a source.
+ * @resume:	resumes tracing for a source.
+ * @pause:	pauses tracing for a source.
  */
 struct coresight_ops_source {
 	int (*cpu_id)(struct coresight_device *csdev);
@@ -392,6 +394,8 @@ struct coresight_ops_source {
 		      enum cs_mode mode, struct coresight_trace_id_map *id_map);
 	void (*disable)(struct coresight_device *csdev,
 			struct perf_event *event);
+	int (*resume)(struct coresight_device *csdev);
+	void (*pause)(struct coresight_device *csdev);
 };
 
 /**
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:14 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:14 +0000
Subject: [PATCH v2 3/8] coresight: etm4x: Hook pause and resume callbacks
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-4-leo.yan@arm.com>

Add callbacks for pausing and resuming the tracer.

A "paused" flag in the driver data indicates whether the tracer is
paused.  If the flag is set, the driver will skip starting the hardware
trace.  The flag is always set to false for the sysfs mode, meaning the
tracer will never be paused in the case.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../coresight/coresight-etm4x-core.c          | 42 ++++++++++++++++++-
 drivers/hwtracing/coresight/coresight-etm4x.h |  2 +
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 71be566bd117..3a97d81b79db 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -608,7 +608,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
 	}
 
-	rc = etm4_enable_trace_unit(drvdata);
+	if (!drvdata->paused)
+		rc = etm4_enable_trace_unit(drvdata);
 done:
 	etm4_cs_lock(drvdata, csa);
 
@@ -866,6 +867,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
 	}
 	drvdata->trcid = (u8)trace_id;
 
+	/* Populate pause state */
+	drvdata->paused = !!READ_ONCE(event->hw.aux_paused);
+
 	/* And enable it */
 	ret = etm4_enable_hw(drvdata);
 
@@ -895,6 +899,9 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
 	if (ret < 0)
 		goto unlock_sysfs_enable;
 
+	/* Tracer will never be paused in sysfs mode */
+	drvdata->paused = false;
+
 	/*
 	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
 	 * ensures that register writes occur when cpu is powered.
@@ -1082,10 +1089,43 @@ static void etm4_disable(struct coresight_device *csdev,
 		coresight_set_mode(csdev, CS_MODE_DISABLED);
 }
 
+static int etm4_resume(struct coresight_device *csdev)
+{
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct csdev_access *csa = &csdev->access;
+
+	if (coresight_get_mode(csdev) != CS_MODE_PERF)
+		return -EINVAL;
+
+	etm4_cs_unlock(drvdata, csa);
+	etm4_enable_trace_unit(drvdata);
+	etm4_cs_lock(drvdata, csa);
+
+	drvdata->paused = false;
+	return 0;
+}
+
+static void etm4_pause(struct coresight_device *csdev)
+{
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct csdev_access *csa = &csdev->access;
+
+	if (coresight_get_mode(csdev) != CS_MODE_PERF)
+		return;
+
+	etm4_cs_unlock(drvdata, csa);
+	etm4_disable_trace_unit(drvdata);
+	etm4_cs_lock(drvdata, csa);
+
+	drvdata->paused = true;
+}
+
 static const struct coresight_ops_source etm4_source_ops = {
 	.cpu_id		= etm4_cpu_id,
 	.enable		= etm4_enable,
 	.disable	= etm4_disable,
+	.resume		= etm4_resume,
+	.pause		= etm4_pause,
 };
 
 static const struct coresight_ops etm4_cs_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 1119762b5cec..c3389fdb5d67 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -983,6 +983,7 @@ struct etmv4_save_state {
  * @state_needs_restore: True when there is context to restore after PM exit
  * @skip_power_up: Indicates if an implementation can skip powering up
  *		   the trace unit.
+ * @paused:	Indicates if the trace unit is paused.
  * @arch_features: Bitmap of arch features of etmv4 devices.
  */
 struct etmv4_drvdata {
@@ -1036,6 +1037,7 @@ struct etmv4_drvdata {
 	struct etmv4_save_state		*save_state;
 	bool				state_needs_restore;
 	bool				skip_power_up;
+	bool				paused;
 	DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
 };
 
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:15 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:15 +0000
Subject: [PATCH v2 4/8] coresight: perf: Support AUX trace pause and resume
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-5-leo.yan@arm.com>

This commit supports AUX trace pause and resume in a perf session for
Arm CoreSight.

First, we need to decide which flag can indicate the CoreSight PMU event
has started.  The 'event->hw.state' cannot be used for this purpose
because its initial value and the value after hardware trace enabling
are both 0.

On the other hand, the context value 'ctxt->event_data' stores the ETM
private info.  This pointer is valid only when the PMU event has been
enabled. It is safe to permit AUX trace pause and resume operations only
when it is not a NULL pointer.

To achieve fine-grained control of the pause and resume, only the tracer
is disabled and enabled.  This avoids the unnecessary complexity and
latency caused by manipulating the entire link path.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../hwtracing/coresight/coresight-etm-perf.c  | 40 ++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index ad6a8f4b70b6..29d52386ffbb 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -366,6 +366,18 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 			continue;
 		}
 
+		/*
+		 * If AUX pause feature is enabled but the ETM driver does not
+		 * support the operations, clear this CPU from the mask and
+		 * continue to next one.
+		 */
+		if (event->attr.aux_start_paused &&
+		    (!source_ops(csdev)->pause || !source_ops(csdev)->resume)) {
+			dev_err_once(&csdev->dev, "AUX pause is not supported.\n");
+			cpumask_clear_cpu(cpu, mask);
+			continue;
+		}
+
 		/*
 		 * No sink provided - look for a default sink for all the ETMs,
 		 * where this event can be scheduled.
@@ -451,6 +463,15 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 	goto out;
 }
 
+static void etm_event_resume(struct coresight_device *csdev,
+			     struct etm_ctxt *ctxt)
+{
+	if (!ctxt->event_data)
+		return;
+
+	coresight_resume_source(csdev);
+}
+
 static void etm_event_start(struct perf_event *event, int flags)
 {
 	int cpu = smp_processor_id();
@@ -465,6 +486,9 @@ static void etm_event_start(struct perf_event *event, int flags)
 	if (!csdev)
 		goto fail;
 
+	if (flags & PERF_EF_RESUME)
+		return etm_event_resume(csdev, ctxt);
+
 	/* Have we messed up our tracking ? */
 	if (WARN_ON(ctxt->event_data))
 		goto fail;
@@ -550,6 +574,16 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 }
 
+static void etm_event_pause(struct coresight_device *csdev,
+			    struct etm_ctxt *ctxt)
+{
+	if (!ctxt->event_data)
+		return;
+
+	/* Stop tracer */
+	coresight_pause_source(csdev);
+}
+
 static void etm_event_stop(struct perf_event *event, int mode)
 {
 	int cpu = smp_processor_id();
@@ -560,6 +594,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	struct etm_event_data *event_data;
 	struct list_head *path;
 
+	if (mode & PERF_EF_PAUSE)
+		return etm_event_pause(csdev, ctxt);
+
 	/*
 	 * If we still have access to the event_data via handle,
 	 * confirm that we haven't messed up the tracking.
@@ -904,7 +941,8 @@ int __init etm_perf_init(void)
 	int ret;
 
 	etm_pmu.capabilities		= (PERF_PMU_CAP_EXCLUSIVE |
-					   PERF_PMU_CAP_ITRACE);
+					   PERF_PMU_CAP_ITRACE |
+					   PERF_PMU_CAP_AUX_PAUSE);
 
 	etm_pmu.attr_groups		= etm_pmu_attr_groups;
 	etm_pmu.task_ctx_nr		= perf_sw_context;
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:16 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:16 +0000
Subject: [PATCH v2 5/8] coresight: etm: Add an attribute for updating buffer
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-6-leo.yan@arm.com>

Add an attribute for updating buffer when the AUX trace is paused.  And
populate the value to the 'update_buf_on_pause' flag during the AUX
setting up.

If the AUX pause operation is attached to a PMU counter, when the
counter is overflow and if the PMU interrupt in an NMI, then AUX pause
operation will be triggered in the NMI context.  On the other hand, the
per CPU sink has its own interrupt handling.  Thus, there will be a race
condition between the updating buffer in NMI and sink's interrupt
handler.

To avoid the race condition, this commit disallows updating buffer on
AUX pause for the per CPU sink.  Currently, this is only applied for
TRBE.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../hwtracing/coresight/coresight-etm-perf.c  | 20 +++++++++++++++++++
 .../hwtracing/coresight/coresight-etm-perf.h  |  2 ++
 include/linux/coresight-pmu.h                 |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 29d52386ffbb..d759663a1f7d 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -62,6 +62,8 @@ PMU_FORMAT_ATTR(contextid1,	"config:" __stringify(ETM_OPT_CTXTID));
 PMU_FORMAT_ATTR(contextid2,	"config:" __stringify(ETM_OPT_CTXTID2));
 PMU_FORMAT_ATTR(timestamp,	"config:" __stringify(ETM_OPT_TS));
 PMU_FORMAT_ATTR(retstack,	"config:" __stringify(ETM_OPT_RETSTK));
+PMU_FORMAT_ATTR(update_buf_on_pause,
+		"config:" __stringify(ETM_OPT_UPDATE_BUF_ON_PAUSE));
 /* preset - if sink ID is used as a configuration selector */
 PMU_FORMAT_ATTR(preset,		"config:0-3");
 /* Sink ID - same for all ETMs */
@@ -103,6 +105,7 @@ static struct attribute *etm_config_formats_attr[] = {
 	&format_attr_configid.attr,
 	&format_attr_branch_broadcast.attr,
 	&format_attr_cc_threshold.attr,
+	&format_attr_update_buf_on_pause.attr,
 	NULL,
 };
 
@@ -434,6 +437,23 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 	if (!sink)
 		goto err;
 
+	/* Populate the flag for updating buffer on AUX pause */
+	event_data->update_buf_on_pause =
+		!!(event->attr.config & BIT(ETM_OPT_UPDATE_BUF_ON_PAUSE));
+
+	if (event_data->update_buf_on_pause) {
+		/*
+		 * The per CPU sink has own interrupt handling, it might have
+		 * race condition with updating buffer on AUX trace pause if
+		 * it is invoked from NMI.  To avoid the race condition,
+		 * disallows updating buffer for the per CPU sink case.
+		 */
+		if (coresight_is_percpu_sink(sink)) {
+			dev_err(&sink->dev, "update_buf_on_pause is not permitted.\n");
+			goto err;
+		}
+	}
+
 	/* If we don't have any CPUs ready for tracing, abort */
 	cpu = cpumask_first(mask);
 	if (cpu >= nr_cpu_ids)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
index 744531158d6b..52b9385f8c11 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.h
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
@@ -51,6 +51,7 @@ struct etm_filters {
  * @aux_hwid_done:	Whether a CPU has emitted the TraceID packet or not.
  * @snk_config:		The sink configuration.
  * @cfg_hash:		The hash id of any coresight config selected.
+ * @update_buf_on_pause: The flag to indicate updating buffer on AUX pause.
  * @path:		An array of path, each slot for one CPU.
  */
 struct etm_event_data {
@@ -59,6 +60,7 @@ struct etm_event_data {
 	cpumask_t aux_hwid_done;
 	void *snk_config;
 	u32 cfg_hash;
+	bool update_buf_on_pause;
 	struct list_head * __percpu *path;
 };
 
diff --git a/include/linux/coresight-pmu.h b/include/linux/coresight-pmu.h
index 89b0ac0014b0..04147e30c2f2 100644
--- a/include/linux/coresight-pmu.h
+++ b/include/linux/coresight-pmu.h
@@ -35,6 +35,7 @@
 #define ETM_OPT_CTXTID2		15
 #define ETM_OPT_TS		28
 #define ETM_OPT_RETSTK		29
+#define ETM_OPT_UPDATE_BUF_ON_PAUSE	30
 
 /* ETMv4 CONFIGR programming bits for the ETM OPTs */
 #define ETM4_CFG_BIT_BB         3
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:17 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:17 +0000
Subject: [PATCH v2 6/8] coresight: perf: Update buffer on AUX pause
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-7-leo.yan@arm.com>

Due to sinks like ETR and ETB don't support interrupt handling, the
hardware trace data might be lost for continuous running tasks.

This commit takes advantage of the AUX pause for updating trace buffer
to mitigate the trace data losing issue.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../hwtracing/coresight/coresight-etm-perf.c  | 38 ++++++++++++++++++-
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index d759663a1f7d..667110429de9 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -594,14 +594,48 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 }
 
-static void etm_event_pause(struct coresight_device *csdev,
+static void etm_event_pause(struct perf_event *event,
+			    struct coresight_device *csdev,
 			    struct etm_ctxt *ctxt)
 {
+	int cpu = smp_processor_id();
+	struct coresight_device *sink;
+	struct perf_output_handle *handle = &ctxt->handle;
+	struct list_head *path;
+	unsigned long size;
+
 	if (!ctxt->event_data)
 		return;
 
 	/* Stop tracer */
 	coresight_pause_source(csdev);
+
+	/* Bail out if no need update buffer */
+	if (!ctxt->event_data->update_buf_on_pause)
+		return;
+
+	if (WARN_ON_ONCE(handle->event != event))
+		return;
+
+	path = etm_event_cpu_path(ctxt->event_data, cpu);
+	sink = coresight_get_sink(path);
+	if (WARN_ON_ONCE(!sink))
+		return;
+
+	if (!sink_ops(sink)->update_buffer)
+		return;
+
+	size = sink_ops(sink)->update_buffer(sink, handle,
+					     ctxt->event_data->snk_config);
+	if (READ_ONCE(handle->event)) {
+		if (!size)
+			return;
+
+		perf_aux_output_end(handle, size);
+		perf_aux_output_begin(handle, event);
+	} else {
+		WARN_ON_ONCE(size);
+	}
 }
 
 static void etm_event_stop(struct perf_event *event, int mode)
@@ -615,7 +649,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	struct list_head *path;
 
 	if (mode & PERF_EF_PAUSE)
-		return etm_event_pause(csdev, ctxt);
+		return etm_event_pause(event, csdev, ctxt);
 
 	/*
 	 * If we still have access to the event_data via handle,
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:18 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:18 +0000
Subject: [PATCH v2 7/8] Documentation: coresight: Document AUX pause and resume
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-8-leo.yan@arm.com>

This adds description for AUX pause and resume.  It gives introduction
for what's AUX pause and resume and how to use the configuration terms.
As last, it records several usage examples.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../trace/coresight/coresight-perf.rst        | 50 +++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst
index d087aae7d492..c49aa05c51eb 100644
--- a/Documentation/trace/coresight/coresight-perf.rst
+++ b/Documentation/trace/coresight/coresight-perf.rst
@@ -78,6 +78,56 @@ enabled like::
 
 Please refer to the kernel configuration help for more information.
 
+Fine-grained tracing with AUX pause and resume
+----------------------------------------------
+
+Arm CoreSight may generate a large amount of hardware trace data, which
+will lead to overhead in recording and distract users when reviewing
+profiling result. To mitigate the issue of excessive trace data, Perf
+provides AUX pause and resume functionality for fine-grained tracing.
+
+The AUX pause and resume can be triggered by associated events. These
+events can be ftrace tracepoints (including static and dynamic
+tracepoints) or PMU events (e.g. CPU PMU cycle event). To create a perf
+session with AUX pause / resume, three configuration terms are
+introduced:
+
+- "aux-action=start-paused": it is specified for the cs_etm PMU event to
+  launch in a paused state.
+- "aux-action=pause": an associated event is specified with this term
+  to pause AUX trace.
+- "aux-action=resume": an associated event is specified with this term
+  to resume AUX trace.
+
+Some Arm CoreSight sinks (e.g., ETR, ETB) do not support interrupt
+mechanism. As a result, trace data might be lost if it cannot be copied
+to the user space tool in a timely manner. To mitigate trace data lose,
+a configuration term "update_buf_on_pause" can be used for the cs_etm
+PMU event. As its name suggests, it directs the driver to update the
+buffer when the AUX trace is paused. By default, this feature is
+disabled until users explicitly specify "update_buf_on_pause=1".
+
+TRBE has interrupt handling.  To avoid the race condition between the
+AUX pause or resume invoked in NMI and TRBE interrupt handler, the
+driver reports a failure if users try to use "update_buf_on_pause=1" on
+TRBE.
+
+Example for triggering AUX pause and resume with ftrace tracepoints::
+
+  perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls
+
+Example for triggering AUX pause and resume with PMU event::
+
+  perf record -a -e cs_etm/aux-action=start-paused/k \
+        -e cycles/aux-action=pause,period=10000000/ \
+        -e cycles/aux-action=resume,period=1050000/ -- sleep 1
+
+Example for updating buffer on AUX pause::
+
+  perf record -a -e cs_etm/aux-action=start-paused,update_buf_on_pause=1/ \
+        -e cycles/aux-action=pause,period=10000000/ \
+        -e cycles/aux-action=resume,period=1050000/ -- sleep 1
+
 Perf test - Verify kernel and userspace perf CoreSight work
 -----------------------------------------------------------
 
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 03:49:19 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 10:49:19 +0000
Subject: [PATCH v2 8/8] perf cs-etm: Sync kernel coresight-pmu.h header
In-Reply-To: <20250310104919.58816-1-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
Message-ID: <20250310104919.58816-9-leo.yan@arm.com>

Update the header in the tools to align with the kernel header.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 tools/include/linux/coresight-pmu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h
index 89b0ac0014b0..04147e30c2f2 100644
--- a/tools/include/linux/coresight-pmu.h
+++ b/tools/include/linux/coresight-pmu.h
@@ -35,6 +35,7 @@
 #define ETM_OPT_CTXTID2		15
 #define ETM_OPT_TS		28
 #define ETM_OPT_RETSTK		29
+#define ETM_OPT_UPDATE_BUF_ON_PAUSE	30
 
 /* ETMv4 CONFIGR programming bits for the ETM OPTs */
 #define ETM4_CFG_BIT_BB         3
-- 
2.34.1



From alexandre.torgue at foss.st.com  Mon Mar 10 03:48:36 2025
From: alexandre.torgue at foss.st.com (Alexandre TORGUE)
Date: Mon, 10 Mar 2025 11:48:36 +0100
Subject: [PATCH] ARM: dts: stm32: use IRQ_TYPE_EDGE_FALLING on
 stm32mp157c-dk2
In-Reply-To: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com>
References: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com>
Message-ID: <e5a5dd9b-475b-4c66-a580-08f11a80e5a3@foss.st.com>

Hi Dario

On 3/1/25 12:51, Dario Binacchi wrote:
> Replace the number 2 with the appropriate numerical constant defined in
> dt-bindings/interrupt-controller/irq.h.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> 
> ---
> 
>   arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> index 5f9c0160a9c4..dcf17c493022 100644
> --- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> @@ -11,6 +11,7 @@
>   #include "stm32mp15-pinctrl.dtsi"
>   #include "stm32mp15xxac-pinctrl.dtsi"
>   #include "stm32mp15xx-dkx.dtsi"
> +#include <dt-bindings/interrupt-controller/irq.h>

really needed ? as it comes also with 
dt-bindings/interrupt-controller/arm-gic.h

>   / {
>   	model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
> @@ -67,7 +68,7 @@ &i2c1 {
>   	touchscreen at 38 {
>   		compatible = "focaltech,ft6236";
>   		reg = <0x38>;
> -		interrupts = <2 2>;
> +		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
>   		interrupt-parent = <&gpiof>;
>   		touchscreen-size-x = <480>;
>   		touchscreen-size-y = <800>;


From mark.rutland at arm.com  Mon Mar 10 03:55:18 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 10:55:18 +0000
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <20250310062812.216031-1-anshuman.khandual@arm.com>
References: <20250310062812.216031-1-anshuman.khandual@arm.com>
Message-ID: <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com>

On Mon, Mar 10, 2025 at 11:58:12AM +0530, Anshuman Khandual wrote:
> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
> section mapping at all page table levels except the last level. This works
> fine as the section mapping masks are exactly the same (0x1UL) for all page
> table levels.
> 
> This will change in the future with D128 page tables that have unique skip
> level values (SKL) required for creating section mapping at different page
> table levels. Hence use page table level specific section mapping macros
> instead of the common PMD_TYPE_SECT. While here also ensure that a section
> mapping is only created on page table levels which could support that on a
> given page size configuration otherwise fall back to create table entries.
> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: linux-kernel at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
> This patch applies on v6.14-rc6
> 
> Changes in V2:
> 
> - Dropped PGD_TYPE_SECT macro and its instance from map_range()
> - Create table entries on levels where section mapping is not possible

On the last version, there was talk of an extant bug:

  https://lore.kernel.org/all/5f1b36e2-6455-44d9-97b0-253aefd5024f at arm.com/

... did that turn out to not be the case?

> 
> Changes in V1:
> 
> https://lore.kernel.org/all/20250303041834.2796751-1-anshuman.khandual at arm.com/
> 
>  arch/arm64/kernel/pi/map_range.c | 38 +++++++++++++++++++++++++++++---
>  1 file changed, 35 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..25a70c675c4d 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -11,6 +11,22 @@
>  
>  #include "pi.h"
>  
> +static bool sect_supported(int level)

What exactly is this function supposed to indicate?

Due to the 'default' case, it'll return true for level-3 tables where
sections/blocks aren't possible, but pages are. So maybe this is just
misnamed, and wants to be something like "leaf_supported()" ?

> +{
> +	switch (level) {
> +	case -1:
> +		return false;
> +	case 0:
> +		if (IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
> +		    IS_ENABLED(CONFIG_ARM64_64K_PAGES))
> +			return false;
> +		else
> +			return true;

Surely:

	case 0:
		return IS_ENABLED(CONFIG_ARM64_4K_PAGES);

... though that's only the case when LPA2 is supported and TCR_ELx.DS is
set.

> +	default:
> +		return true;

As above, what is this supposed to return for level-3 tables where
sections/blocks aren't possible?

Can we BUILD_BUG() for bogus levels?

> +	}
> +}
> +
>  /**
>   * map_range - Map a contiguous range of physical pages into virtual memory
>   *
> @@ -44,13 +60,29 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	 * Set the right block/page bits for this level unless we are
>  	 * clearing the mapping
>  	 */
> -	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> +	if (protval && sect_supported(level)) {

The existing code is trying to find the leaf prot for a given level of
table, so as-is checking sect_supported() is at best misleading.

If we're going to do something different below based on
sect_supported(), I reckon this should be moved into the path where
sect_supported() returned true, maybe factored out into a helper for
clarity.

Mark.

> +		switch (level) {
> +		case 3:
> +			protval |= PTE_TYPE_PAGE;
> +			break;
> +		case 2:
> +			protval |= PMD_TYPE_SECT;
> +			break;
> +		case 1:
> +			protval |= PUD_TYPE_SECT;
> +			break;
> +		case 0:
> +			protval |= P4D_TYPE_SECT;
> +			break;
> +		default:
> +			break;
> +		}
> +	}
>  
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -		if (level < 3 && (start | next | pa) & lmask) {
> +		if ((level < 3 && (start | next | pa) & lmask) || !sect_supported(level)) {
>  			/*
>  			 * This chunk needs a finer grained mapping. Create a
>  			 * table mapping if necessary and recurse.
> -- 
> 2.25.1
> 
> 


From quic_pbrahma at quicinc.com  Mon Mar 10 04:18:35 2025
From: quic_pbrahma at quicinc.com (Pratyush Brahma)
Date: Mon, 10 Mar 2025 16:48:35 +0530
Subject: [PATCH v6 2/2] arm64: dts: qcom: qcs8300: Add device node for
 gfx_smmu
In-Reply-To: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
References: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
Message-ID: <20250310-b4-branch-gfx-smmu-v6-2-15c60b8abd99@quicinc.com>

Add the device node for gfx smmu that is required for gpu
specific address translations.

Signed-off-by: Pratyush Brahma <quic_pbrahma at quicinc.com>
---
 arch/arm64/boot/dts/qcom/qcs8300.dtsi | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/qcs8300.dtsi b/arch/arm64/boot/dts/qcom/qcs8300.dtsi
index 4a057f7c0d9fae0ebd1b3cf3468746b382bc886b..40771b062e8d7010dd93d7cc7b3db73cfa16bfdb 100644
--- a/arch/arm64/boot/dts/qcom/qcs8300.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs8300.dtsi
@@ -2674,6 +2674,45 @@ gpucc: clock-controller at 3d90000 {
 			#power-domain-cells = <1>;
 		};
 
+		adreno_smmu: iommu at 3da0000 {
+			compatible = "qcom,qcs8300-smmu-500", "qcom,adreno-smmu",
+				     "qcom,smmu-500", "arm,mmu-500";
+			reg = <0x0 0x3da0000 0x0 0x20000>;
+			#iommu-cells = <2>;
+			#global-interrupts = <2>;
+
+			interrupts = <GIC_SPI 672 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 673 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 678 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 679 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 680 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 681 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 682 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 683 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 684 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 685 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 686 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 687 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&gcc GCC_GPU_MEMNOC_GFX_CLK>,
+				 <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>,
+				 <&gpucc GPU_CC_AHB_CLK>,
+				 <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>,
+				 <&gpucc GPU_CC_CX_GMU_CLK>,
+				 <&gpucc GPU_CC_HUB_CX_INT_CLK>,
+				 <&gpucc GPU_CC_HUB_AON_CLK>;
+
+			clock-names = "gcc_gpu_memnoc_gfx_clk",
+				      "gcc_gpu_snoc_dvm_gfx_clk",
+				      "gpu_cc_ahb_clk",
+				      "gpu_cc_hlos1_vote_gpu_smmu_clk",
+				      "gpu_cc_cx_gmu_clk",
+				      "gpu_cc_hub_cx_int_clk",
+				      "gpu_cc_hub_aon_clk";
+			power-domains = <&gpucc GPU_CC_CX_GDSC>;
+			dma-coherent;
+		};
+
 		pmu at 9091000 {
 			compatible = "qcom,qcs8300-llcc-bwmon", "qcom,sc7280-llcc-bwmon";
 			reg = <0x0 0x9091000 0x0 0x1000>;

-- 
2.34.1



From luca.ceresoli at bootlin.com  Mon Mar 10 04:23:58 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Mon, 10 Mar 2025 12:23:58 +0100
Subject: [PATCH 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <Z86gCjzuC5UFZBIL@smile.fi.intel.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
	<20250307-vsprintf-pcn-v1-2-df0b2ccf610f@bootlin.com>
	<Z8sqJhbqEBla_Ch7@smile.fi.intel.com>
	<20250308003425.7b89bfb6@booty>
	<Z86gCjzuC5UFZBIL@smile.fi.intel.com>
Message-ID: <20250310122358.3c07ed18@booty>

Hello,

+To: Alex Shi, Yanteng Si (Chinese docs maintainers)
+Cc: Binbin Zhou (contributor to English version of printk-formats.rst)

On Mon, 10 Mar 2025 10:17:14 +0200
Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:

> On Sat, Mar 08, 2025 at 12:34:25AM +0100, Luca Ceresoli wrote:
> > On Fri, 7 Mar 2025 19:17:26 +0200
> > Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:  
> > > On Fri, Mar 07, 2025 at 12:19:08PM +0100, Luca Ceresoli wrote:  
> > > > %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> > > > add %pC{,n,r} format specifiers for clocks") introducing them does not
> > > > clarify any intended difference. It can be assumed %pC is a default for
> > > > %pCn as some other specifiers do, but not all are consistent with this
> > > > policy. Moreover there is now no other suffix other than 'n', which makes a
> > > > default not really useful.
> > > > 
> > > > All users in the kernel were using %pC except for one which has been
> > > > converted. So now remove %pCn and all the unnecessary extra code and
> > > > documentation.    
> > > 
> > > You seem forgot to update translation(s) of the documentation.  
> > 
> > I'm afraid I don't speak Chinese. :-)  
> 
> At bare minimum we can drop the same line in the list.
> Also in such a case we may ask a Chinese speaking person to review / correct /
> suggest the changes. I would not leave a leftover as it will be forgotten so
> easily and documentation becomes not in sync.

Alex Shi, Yanteng Si: what is the process to update the Chinese
documentation after changes to the English one, considering I don't
speak Chinese?

The documentation [0] seems to imply it will be done by you after the
English documentation update, is it the case?

Otherwise, for this simple change, I can add a patch that looks like a
somewhat correct one for Chinese:

@@ -523,9 +523,8 @@ clk???
 ::
 
 	%pC	pll1
-	%pCn	pll1
 
-????clk???%pC ? %pCn ???????????????????32?
+????clk???%pC ???????????????????32?
 ID?????????
 
 ???????

Can you confirm the above is a correct change?

Luca

[0] https://docs.kernel.org/translations/index.html

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From krzk at kernel.org  Mon Mar 10 04:43:29 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 12:43:29 +0100
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <TY0PR06MB496072786197162F19ED7DDD89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
 <2fd83d68-7104-4755-a0f0-8ce4a2601e09@kernel.org>
 <TY0PR06MB496072786197162F19ED7DDD89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
Message-ID: <58466532-3e17-4968-bade-210f478ccc76@kernel.org>

On 10/03/2025 11:05, Kevin Chen wrote:
>> On 04/03/2025 11:44, Kevin Chen wrote:
>>> +
>>> +static int aspeed_pcc_probe(struct platform_device *pdev) {
>>> +	int rc;
>>> +	struct aspeed_pcc_ctrl *pcc;
>>> +	struct device *dev;
>>> +	uint32_t fifo_size = PAGE_SIZE;
>>> +
>>> +	dev = &pdev->dev;
>>
>> This goes to declaration.
> OK. I will move it to declaration.
> 
>>
>>> +
>>> +	pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL);
>>
>> Maybe my previous comment was not clear, but you agreed with it. Anyway
>> nothing improved here.
> Could I reserve the pcc variable using for the pcc_ctrl data structure?
> Pcc_ctrl data include the regmap/irq/io_port/dma/kfifo.
> If I change the name to dev, it does not make sense for these data to be.
> 
>>
>> If you have 'dev' variable, use it.
> Do you mean just use the pdev->dev not local dev variable?
What is the point of this:
dev = &pdev->dev;

if you do not use 'dev'? If you come with a reason, sure. If you do not
have such, then everything should use 'dev', not pdev->dev.

Best regards,
Krzysztof


From leo.yan at arm.com  Mon Mar 10 04:46:51 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 11:46:51 +0000
Subject: [PATCH v2 3/5] coresight-tnoc: add nodes to configure flush
In-Reply-To: <7c702a81-fb6c-4399-8d7d-d8c4ad9a8c65@quicinc.com>
References: <20250226-trace-noc-driver-v2-0-8afc6584afc5@quicinc.com>
 <20250226-trace-noc-driver-v2-3-8afc6584afc5@quicinc.com>
 <20250227162349.GB2157064@e132581.arm.com>
 <7c702a81-fb6c-4399-8d7d-d8c4ad9a8c65@quicinc.com>
Message-ID: <20250310114651.GD9682@e132581.arm.com>

On Thu, Mar 06, 2025 at 04:39:27PM +0800, Yuanfang Zhang wrote:

[...]

> >> +static ssize_t flush_req_store(struct device *dev,
> >> +                              struct device_attribute *attr,
> >> +                              const char *buf,
> >> +                              size_t size)
> >> +{

...

> >> +       reg = readl_relaxed(drvdata->base + TRACE_NOC_CTRL);
> >> +       reg = reg | TRACE_NOC_CTRL_FLUSHREQ;
> >> +       writel_relaxed(reg, drvdata->base + TRACE_NOC_CTRL);
> > 
> > How can userspace determine when to trigger a flush?
> It can be triggered under any circumstances.
> > 
> > Generally, a driver kicks off a flush operation for a hardware before
> > reading data from buffer or when disable a link path.  I don't know the
> > hardware mechanism of TNOC, but seems to me, it does not make sense to
> > let the userspace to trigger a hardware flush, given the userspace has
> > no knowledge for device's state.
>
> TNOC supports the aforementioned flush operation, and it also adds this
> flush functionality, allowing users to set the flush themselves.

I am still not convinced for providing knobs to allow userspace to
directly control hardware.

A low level driver should have sufficient information to know when and
how it triggers a flush.  E.g., CoreSight ETF (coresight-tmc-etf.c) can
act as a link, in this case, it calls the tmc_flush_and_stop() function
to flush its buffer when it is stopped.  A flushing is triggered when a
session is terminated (either is a perf session or a Sysfs session).

Why not TNOC driver do the flushing same as other drivers?  It can flush
the data before a hardware link is to be disabled.  I don't think flush
operations are required at any time.

Seems to me, exposing APIs to userspace for flushing operations also
will introduce potential security risk.  A malicious software might
attack system with triggering tons of flushing in short time.

> > Furthermore, based on my understanding for patch 02 and 03, the working
> > flow is also concerned me.  IIUC, you want to use the driver to create
> > a linkage and then use userspace program to poll state and trigger
> > flushing.  Could you explain why use this way for managing the device?
> > 
> TNOC support flush just like other links. This interface simply provides
> customers with an additional option to trigger the flush.

This is not true for Arm CoreSight components.  My understanding is Arm
CoreSight drivers never provides an API to userspace to manually trigger
flush operations.

Thanks,
Leo


From kevin_chen at aspeedtech.com  Mon Mar 10 04:48:36 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 19:48:36 +0800
Subject: [PATCH v3 0/3] Add AST2600 LPC PCC support
Message-ID: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>

--
v3
aspeed-lpc-pcc.c:
 -- Add ida_free and fix the dev usage with removing some debug messages.
aspeed-lpc.yaml:
 -- Add description about the pcc-ports usage.

v2:
 -- Change driver path to drivers/misc

Kevin Chen (3):
  dt-binding: aspeed: Add LPC PCC controller
  ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
  soc: aspeed: lpc-pcc: Add PCC controller support

 .../devicetree/bindings/mfd/aspeed-lpc.yaml   |  38 ++
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi       |   7 +
 drivers/misc/Kconfig                          |  10 +
 drivers/misc/Makefile                         |   1 +
 drivers/misc/aspeed-lpc-pcc.c                 | 440 ++++++++++++++++++
 5 files changed, 496 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

-- 
2.34.1



From kevin_chen at aspeedtech.com  Mon Mar 10 04:48:37 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 19:48:37 +0800
Subject: [PATCH v3 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
Message-ID: <20250310114839.3098148-2-kevin_chen@aspeedtech.com>

Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
index 5dfe77aca167..178c151a19ba 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
@@ -149,6 +149,37 @@ patternProperties:
       - interrupts
       - snoop-ports
 
+  "^lpc-pcc@[0-9a-f]+$":
+    type: object
+    additionalProperties: false
+
+    description:
+      The LPC pcc interface allows the BMC to listen on and record the data
+      bytes written by the Host to the targeted LPC I/O pots.
+
+    properties:
+      compatible:
+        items:
+          - enum:
+              - aspeed,ast2600-lpc-pcc
+
+      reg:
+        maxItems: 1
+
+      interrupts:
+        maxItems: 1
+
+      pcc-ports:
+        $ref: /schemas/types.yaml#/definitions/uint32-array
+        description:
+          As a device handshake with a host using the port-mmaped I/O in x86
+          architecture, need to handle specific which port I/O address for use.
+
+    required:
+      - compatible
+      - interrupts
+      - pcc-ports
+
   "^uart-routing@[0-9a-f]+$":
     $ref: /schemas/soc/aspeed/uart-routing.yaml#
     description: The UART routing control under LPC register space
@@ -176,6 +207,13 @@ examples:
         #size-cells = <1>;
         ranges = <0x0 0x1e789000 0x1000>;
 
+        lpc_pcc: lpc-pcc at 0 {
+            compatible = "aspeed,ast2600-lpc-pcc";
+            reg = <0x0 0x140>;
+            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+            pcc-ports = <0x80>;
+        };
+
         lpc_ctrl: lpc-ctrl at 80 {
             compatible = "aspeed,ast2600-lpc-ctrl";
             reg = <0x80 0x80>;
-- 
2.34.1



From kevin_chen at aspeedtech.com  Mon Mar 10 04:48:38 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 19:48:38 +0800
Subject: [PATCH v3 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
Message-ID: <20250310114839.3098148-3-kevin_chen@aspeedtech.com>

The AST2600 has PCC controller in LPC, placed in LPC node.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 8ed715bd53aa..87dcacb78692 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -626,6 +626,13 @@ lpc_snoop: lpc-snoop at 80 {
 					status = "disabled";
 				};
 
+				lpc_pcc: lpc-pcc at 0 {
+					compatible = "aspeed,ast2600-lpc-pcc";
+					reg = <0x0 0x140>;
+					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+					status = "disabled";
+				};
+
 				lhc: lhc at a0 {
 					compatible = "aspeed,ast2600-lhc";
 					reg = <0xa0 0x24 0xc8 0x8>;
-- 
2.34.1



From suzuki.poulose at arm.com  Mon Mar 10 04:33:17 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 11:33:17 +0000
Subject: [PATCH v2] coresight: add verification process for coresight_etm_get_trace_id
In-Reply-To: <20250310102724.2112905-1-quic_jiegan@quicinc.com>
References: <20250310102724.2112905-1-quic_jiegan@quicinc.com>
Message-ID: <174160625281.2197960.2271358102397768915.b4-ty@arm.com>


On Mon, 10 Mar 2025 18:27:24 +0800, Jie Gan wrote:
> The coresight_etm_get_trace_id function is a global function. The
> verification process for 'csdev' is required prior to its usage.
> 
> 

Applied, thanks!

[1/1] coresight: add verification process for coresight_etm_get_trace_id
      https://git.kernel.org/coresight/c/ab37128a

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From krzk at kernel.org  Mon Mar 10 04:41:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 12:41:06 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <67cec328.170a0220.27ecbc.9c6e@mx.google.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
 <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>
 <67cec328.170a0220.27ecbc.9c6e@mx.google.com>
Message-ID: <026296c8-a460-43ca-a423-0fa38269fbc2@kernel.org>

On 10/03/2025 11:47, Christian Marangi wrote:
> On Mon, Mar 10, 2025 at 10:21:45AM +0100, Krzysztof Kozlowski wrote:
>> On 09/03/2025 14:29, Christian Marangi wrote:
>>> Add Documentation for Airoha EN7581 SCU.
>>>
>>> Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
>>> via the SCU (System Controller Unit).
>>>
>>> Example of these pheriperals are reset-controller, clock-controller,
>>> PCIe line speed controller and bits to configure different Serdes ports
>>> for USB or Ethernet usage.
>>>
>>> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
>>> ---
>>>  .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
>>>  1 file changed, 68 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
>>> new file mode 100644
>>> index 000000000000..d7dc66f912c1
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
>>> @@ -0,0 +1,68 @@
>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Airoha EN7581 SCU (System Controller Unit)
>>> +
>>> +maintainers:
>>> +  - Christian Marangi <ansuelsmth at gmail.com>
>>> +
>>> +description:
>>> +  Airoha EN7581 SoC expose registers to control miscellaneous
>>> +  pheriperals via the SCU (System Controller Unit).
>>> +
>> One more comment - there is no such thing as "sysctl" in your hardware.
>> Look at the SCU binding which clearly says that it is the hardware you
>> are duplicating here, so the "System Control Unit".
>>
>> So you have existing "This node defines the System Control Unit of the
>> EN7523 SoC" and you add one more node which defines the "System Control
>> Unit", so you have two "System Control Unit" device nodes?
>>
>> Look also what Stephen asked for:
>>
>> https://lore.kernel.org/all/20220106013100.842FCC36AEB at smtp.kernel.org/
>>
>> so how system-controller can now became clock-controller? Now, it was
>> the system controller since the beginning.
>>
> 
> The main problem here (and we had a similar problem with GPIO and PWM)
> is that the Vendor (Airoha) wasn't so bright in placing the different
> registers for the SoC so we have case where everything is mixed and not
> one after another... 
> 
> Example we have 
> - CLK register part 1
> - Some bits that configure PCIe
> - CLK register part 2
> - GPIO
> - CLK register part 3
> - ...

This does not explain that binding said "This node defines the System
Control Unit".

So what are you adding here if not SCU?

> 
> The driver solution for this is syscon and the simple-mfd node
> structure.

Let's keep driver entirely separate, we don't talk about them and mixing
arguments won't make it easier.

> 
> Now the main problem is how to modle this in DT. There are lots of case
> where the simple-mfd model is used (like the one proposed) but probably
> this is not accepted anymore. But again this should be clearly stated or
> we have a chicken-egg problem when other devs implement similar thing and
> have to implement simple MFD driver to handle this. (and driver
> maintainers say "Use the simple-mfd model like it was already done)

simple-mfd has nothing to do here. Describe the hardware - what is the SCU?


> 
> For this specific case (and to give an answer to the clock patch after
> this) the problem is that this register space was originally used only
> to control the clock and I wasn't aware that it was also used to control
> USB. Now that I'm implementing support for it, the disaster happened.
> 
> So In short SCU is lots of thing, both a system-controller, a
> clock-controller and even a reset-controller.

And you have bindings for that already. Done.

> 
> To make it short, 2 different solution:
> 1. We can keep the current node structure of the node-controller and add a
> child node for the SSR part (with a dedicated compatible).

No, you do not add child nodes just because you want some drivers.

What is SSR? How is it a device?

> 2. Those property need to be be defined in the clock-controller node?

In the SCU node. Do you have only one SCU or more?

> 
> The ideal solution is 1. Does it work for you?
> 
> Sorry for the long post and hope you understand why this mess of
> reworking the binding.
> 


Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 10 04:42:23 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 12:42:23 +0100
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <TY0PR06MB496045B19DCB149EC902D0FF89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
 <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
 <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>
 <e17cdf9d-ba96-41d2-9656-9e50d0e0795a@kernel.org>
 <TY0PR06MB496045B19DCB149EC902D0FF89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
Message-ID: <a12afc26-2e8e-42cc-ac68-27ba8906707f@kernel.org>

On 10/03/2025 10:49, Kevin Chen wrote:
>>>>> +            compatible = "aspeed,ast2600-lpc-pcc";
>>>>> +            reg = <0x0 0x140>;
>>>>> +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
>>>>> +            pcc-ports = <0x80>;
>>>>
>>>> So what 0x80 stands for?
>>> Host as x86 architecture would access the 0x80 port, which is mapped to the
>> BMC PCC HW module.
>>> As a result, x86 can keep the port-mmaped I/O usage and access the BMC
>> device, which is needed to know which port using in the PCC module in BMC.
>>
>> And on different boards this is not 0x80?
> The port-mmaped I/O defined in the intel legacy document as the example usage.
> For example, the common usage agreement of port-mmaped I/O are the following. But this setting can be modified due to the host usage. We provide the flexibility to modify the I/O port settings.
> KCS : 0xCA2(CMD)/CA3(Data)
> BT : 0xE4/E5/E6
> SNOOP/PCC : 0x80/81/82/83
> Mailbox : 0xCC0
> SuperIO : 0x2E/2F or 0x4E/0x4F
> System UART : 0x3F8/2F8/3E8/2E8
So which boards have it modified?

Best regards,
Krzysztof


From maz at kernel.org  Mon Mar 10 04:42:48 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 11:42:48 +0000
Subject: [PATCH 07/18] KVM: arm64: Compute FGT masks from KVM's own FGT tables
In-Reply-To: <CA+EHjTwm4CosWDGcaH_tnLU7zMNCq8twDyEcKd7-V0Lu7b-LcA@mail.gmail.com>
References: <20250210184150.2145093-1-maz@kernel.org>
	<20250210184150.2145093-8-maz@kernel.org>
	<CA+EHjTwm4CosWDGcaH_tnLU7zMNCq8twDyEcKd7-V0Lu7b-LcA@mail.gmail.com>
Message-ID: <8634flp0w7.wl-maz@kernel.org>

On Tue, 04 Mar 2025 16:55:50 +0000,
Fuad Tabba <tabba at google.com> wrote:
> 
> Hi Marc,
> 
> On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
> >
> > In the process of decoupling KVM's view of the FGT bits from the
> > wider architectural state, use KVM's own FGT tables to build
> > a synthitic view of what is actually known.
> 
> synthitic -> synthetic
> 
> 
> > This allows for some checking along the way.
> >
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > ---
> >  arch/arm64/include/asm/kvm_arm.h  |   4 ++
> >  arch/arm64/include/asm/kvm_host.h |  14 ++++
> >  arch/arm64/kvm/emulate-nested.c   | 102 ++++++++++++++++++++++++++++++
> >  3 files changed, 120 insertions(+)
> >
> > diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> > index 8d94a6c0ed5c4..e424085f2aaca 100644
> > --- a/arch/arm64/include/asm/kvm_arm.h
> > +++ b/arch/arm64/include/asm/kvm_arm.h
> > @@ -359,6 +359,10 @@
> >  #define __HAFGRTR_EL2_MASK     (GENMASK(49, 17) | GENMASK(4, 0))
> >  #define __HAFGRTR_EL2_nMASK    ~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
> >
> > +/* Because the sysreg file mixes R and W... */
> > +#define HFGRTR_EL2_RES0                HFGxTR_EL2_RES0 (0)
> > +#define HFGWTR_EL2_RES0                (HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
> 
> __HFGRTR_ONLY_MASK is a hand-crafted bitmask. The only bit remaining
> in HFGxTR_EL2 that is RES0 is bit 51. If that were to be used as an
> HFGRTR-only bit without __HFGRTR_ONLY_MASK getting updated, then
> aggregate_fgt() below would set its bit in hfgwtr_masks. Could this be
> a problem if this happens and the polarity of this bit ends up being
> negative, thereby setting the corresponding nmask bit?

This could become a problem indeed. But the only fix for that is to
kill the HFGxTR stupidity and describe all the bits as needed so that
we stop assuming things.

I'm half tempted to do that next.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From kevin_chen at aspeedtech.com  Mon Mar 10 04:48:39 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Mon, 10 Mar 2025 19:48:39 +0800
Subject: [PATCH v3 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
Message-ID: <20250310114839.3098148-4-kevin_chen@aspeedtech.com>

Add LPC PCC controller driver to support POST code capture.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 drivers/misc/Kconfig          |  10 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/aspeed-lpc-pcc.c | 440 ++++++++++++++++++++++++++++++++++
 3 files changed, 451 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 56bc72c7ce4a..35c1d2e0c271 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -50,6 +50,16 @@ config AD525X_DPOT_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
+config ASPEED_LPC_PCC
+	tristate "Aspeed Post Code Capture support"
+	select REGMAP
+	select MFD_SYSCON
+	default ARCH_ASPEED
+	help
+	  Provides a driver to control the LPC PCC interface,
+	  allowing the BMC to capture post code written by the
+	  the host to an arbitrary LPC I/O port.
+
 config DUMMY_IRQ
 	tristate "Dummy IRQ handler"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 545aad06d088..4762da7804bf 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_IBMVMC)		+= ibmvmc.o
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
+obj-$(CONFIG_ASPEED_LPC_PCC)	+= aspeed-lpc-pcc.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
diff --git a/drivers/misc/aspeed-lpc-pcc.c b/drivers/misc/aspeed-lpc-pcc.c
new file mode 100644
index 000000000000..9ed4b453d199
--- /dev/null
+++ b/drivers/misc/aspeed-lpc-pcc.c
@@ -0,0 +1,440 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/kfifo.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regmap.h>
+#include <linux/dma-mapping.h>
+#include <linux/sizes.h>
+
+#define DEVICE_NAME "aspeed-lpc-pcc"
+
+static DEFINE_IDA(aspeed_pcc_ida);
+
+#define HICR5	0x80
+#define HICR5_EN_SNP0W			BIT(0)
+#define HICR5_EN_SNP1W			BIT(2)
+#define HICR6	0x084
+#define   HICR6_EN2BMODE		BIT(19)
+#define SNPWADR	0x090
+#define PCCR6	0x0c4
+#define   PCCR6_DMA_CUR_ADDR		GENMASK(27, 0)
+#define PCCR4	0x0d0
+#define   PCCR4_DMA_ADDRL_MASK		GENMASK(31, 0)
+#define   PCCR4_DMA_ADDRL_SHIFT		0
+#define PCCR5	0x0d4
+#define   PCCR5_DMA_ADDRH_MASK		GENMASK(27, 24)
+#define   PCCR5_DMA_ADDRH_SHIFT		24
+#define   PCCR5_DMA_LEN_MASK		GENMASK(23, 0)
+#define   PCCR5_DMA_LEN_SHIFT		0
+#define HICRB	0x100
+#define   HICRB_ENSNP0D			BIT(14)
+#define   HICRB_ENSNP1D			BIT(15)
+#define PCCR0	0x130
+#define   PCCR0_EN_DMA_INT		BIT(31)
+#define   PCCR0_EN_DMA_MODE		BIT(14)
+#define   PCCR0_ADDR_SEL_MASK		GENMASK(13, 12)
+#define   PCCR0_ADDR_SEL_SHIFT		12
+#define   PCCR0_RX_TRIG_LVL_MASK	GENMASK(10, 8)
+#define   PCCR0_RX_TRIG_LVL_SHIFT	8
+#define   PCCR0_CLR_RX_FIFO		BIT(7)
+#define   PCCR0_MODE_SEL_MASK		GENMASK(5, 4)
+#define   PCCR0_MODE_SEL_SHIFT		4
+#define   PCCR0_EN_RX_TMOUT_INT		BIT(2)
+#define   PCCR0_EN_RX_AVAIL_INT		BIT(1)
+#define   PCCR0_EN			BIT(0)
+#define PCCR1	0x134
+#define   PCCR1_BASE_ADDR_MASK		GENMASK(15, 0)
+#define   PCCR1_BASE_ADDR_SHIFT		0
+#define   PCCR1_DONT_CARE_BITS_MASK	GENMASK(21, 16)
+#define   PCCR1_DONT_CARE_BITS_SHIFT	16
+#define PCCR2	0x138
+#define   PCCR2_INT_STATUS_PATTERN_B	BIT(16)
+#define   PCCR2_INT_STATUS_PATTERN_A	BIT(8)
+#define   PCCR2_INT_STATUS_DMA_DONE	BIT(4)
+#define   PCCR2_INT_STATUS_DATA_RDY	PCCR2_INT_STATUS_DMA_DONE
+#define   PCCR2_INT_STATUS_RX_OVER	BIT(3)
+#define   PCCR2_INT_STATUS_RX_TMOUT	BIT(2)
+#define   PCCR2_INT_STATUS_RX_AVAIL	BIT(1)
+#define PCCR3	0x13c
+#define   PCCR3_FIFO_DATA_MASK		GENMASK(7, 0)
+
+#define PCC_DMA_BUFSZ	(256 * SZ_1K)
+
+enum pcc_fifo_threshold {
+	PCC_FIFO_THR_1_BYTE,
+	PCC_FIFO_THR_1_EIGHTH,
+	PCC_FIFO_THR_2_EIGHTH,
+	PCC_FIFO_THR_3_EIGHTH,
+	PCC_FIFO_THR_4_EIGHTH,
+	PCC_FIFO_THR_5_EIGHTH,
+	PCC_FIFO_THR_6_EIGHTH,
+	PCC_FIFO_THR_7_EIGHTH,
+	PCC_FIFO_THR_8_EIGHTH,
+};
+
+enum pcc_record_mode {
+	PCC_REC_1B,
+	PCC_REC_2B,
+	PCC_REC_4B,
+	PCC_REC_FULL,
+};
+
+enum pcc_port_hbits_select {
+	PCC_PORT_HBITS_SEL_NONE,
+	PCC_PORT_HBITS_SEL_45,
+	PCC_PORT_HBITS_SEL_67,
+	PCC_PORT_HBITS_SEL_89,
+};
+
+struct aspeed_pcc_dma {
+	uint32_t rptr;
+	uint8_t *virt;
+	dma_addr_t addr;
+	uint32_t size;
+};
+
+struct aspeed_pcc_ctrl {
+	struct device *dev;
+	struct regmap *regmap;
+	int irq;
+	uint32_t port;
+	struct aspeed_pcc_dma dma;
+	struct kfifo fifo;
+	wait_queue_head_t wq;
+	struct miscdevice mdev;
+	int mdev_id;
+};
+
+static inline bool is_valid_rec_mode(uint32_t mode)
+{
+	return (mode > PCC_REC_FULL) ? false : true;
+}
+
+static inline bool is_valid_high_bits_select(uint32_t sel)
+{
+	return (sel > PCC_PORT_HBITS_SEL_89) ? false : true;
+}
+
+static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	int rc;
+	unsigned int copied;
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	if (kfifo_is_empty(&pcc->fifo)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		rc = wait_event_interruptible(pcc->wq,
+					      !kfifo_is_empty(&pcc->fifo));
+		if (rc == -ERESTARTSYS)
+			return -EINTR;
+	}
+
+	rc = kfifo_to_user(&pcc->fifo, buffer, count, &copied);
+
+	return rc ? rc : copied;
+}
+
+static __poll_t aspeed_pcc_file_poll(struct file *file,
+				     struct poll_table_struct *pt)
+{
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	poll_wait(file, &pcc->wq, pt);
+
+	return !kfifo_is_empty(&pcc->fifo) ? POLLIN : 0;
+}
+
+static const struct file_operations pcc_fops = {
+	.owner = THIS_MODULE,
+	.read = aspeed_pcc_file_read,
+	.poll = aspeed_pcc_file_poll,
+};
+
+static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg)
+{
+	uint32_t reg, rptr, wptr;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+	struct kfifo *fifo = &pcc->fifo;
+
+	regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_INT_STATUS_DMA_DONE);
+
+	regmap_read(pcc->regmap, PCCR6, &reg);
+	wptr = (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR);
+	rptr = pcc->dma.rptr;
+
+	do {
+		if (kfifo_is_full(fifo))
+			kfifo_skip(fifo);
+
+		kfifo_put(fifo, pcc->dma.virt[rptr]);
+
+		rptr = (rptr + 1) % pcc->dma.size;
+	} while (rptr != wptr);
+
+	pcc->dma.rptr = rptr;
+
+	wake_up_interruptible(&pcc->wq);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t aspeed_pcc_isr(int irq, void *arg)
+{
+	uint32_t sts;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+
+	regmap_read(pcc->regmap, PCCR2, &sts);
+
+	if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT |
+		     PCCR2_INT_STATUS_RX_AVAIL |
+		     PCCR2_INT_STATUS_DMA_DONE)))
+		return IRQ_NONE;
+
+	return aspeed_pcc_dma_isr(irq, arg);
+}
+
+/*
+ * A2600-15 AP note
+ *
+ * SW workaround to prevent generating Non-Fatal-Error (NFE)
+ * eSPI response when PCC is used for port I/O byte snooping
+ * over eSPI.
+ */
+static int aspeed_a2600_15(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	u32 hicr5_en, hicrb_en;
+
+	/* abort if snoop is enabled */
+	regmap_read(pcc->regmap, HICR5, &hicr5_en);
+	if (hicr5_en & (HICR5_EN_SNP0W | HICR5_EN_SNP1W)) {
+		dev_err(dev, "A2600-15 should be applied with snoop disabled\n");
+		return -EPERM;
+	}
+
+	/* set SNPWADR of snoop device */
+	regmap_write(pcc->regmap, SNPWADR, pcc->port | ((pcc->port + 2) << 16));
+
+	/* set HICRB[15:14]=11b to enable ACCEPT response for SNPWADR */
+	hicrb_en = HICRB_ENSNP0D | HICRB_ENSNP1D;
+	regmap_update_bits(pcc->regmap, HICRB, hicrb_en, hicrb_en);
+
+	/* set HICR6[19] to extend SNPWADR to 2x range */
+	regmap_update_bits(pcc->regmap, HICR6, HICR6_EN2BMODE, HICR6_EN2BMODE);
+
+	return 0;
+}
+
+static int aspeed_pcc_enable(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	int rc;
+
+	rc = aspeed_a2600_15(pcc, dev);
+	if (rc)
+		return rc;
+
+	/* record mode: Set 2-Byte mode. */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_MODE_SEL_MASK,
+			   PCC_REC_2B << PCCR0_MODE_SEL_SHIFT);
+
+	/* port address */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_BASE_ADDR_MASK,
+			   pcc->port << PCCR1_BASE_ADDR_SHIFT);
+
+	/* Set address high bits selection to 0b01 for address bit[5:4] */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_ADDR_SEL_MASK,
+			   PCC_PORT_HBITS_SEL_45 << PCCR0_ADDR_SEL_SHIFT);
+
+	/* Set LPC don't care address to 0x3 for port 80~83h */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_DONT_CARE_BITS_MASK,
+			   0x3 << PCCR1_DONT_CARE_BITS_SHIFT);
+
+	/* set DMA ring buffer size and enable interrupts */
+	regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff);
+#ifdef CONFIG_ARM64
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK,
+			   (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT);
+#endif
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK,
+			   (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT);
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE);
+
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN, PCCR0_EN);
+
+	return 0;
+}
+
+static int aspeed_pcc_disable(struct aspeed_pcc_ctrl *pcc)
+{
+	/* Disable PCC and DMA Mode for safety */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN |  PCCR0_EN_DMA_MODE, 0);
+
+	/* Clear Rx FIFO. */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1);
+
+	/* Clear All interrupts status. */
+	regmap_write(pcc->regmap, PCCR2,
+		     PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE |
+		     PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B);
+
+	return 0;
+}
+
+static int aspeed_pcc_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct aspeed_pcc_ctrl *pcc;
+	struct device *dev = &pdev->dev;
+	uint32_t fifo_size = PAGE_SIZE;
+
+	pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL);
+	if (!pcc)
+		return -ENOMEM;
+
+	pcc->regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(pcc->regmap)) {
+		dev_err(dev, "Couldn't get regmap\n");
+		return -ENODEV;
+	}
+
+	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
+	if (rc) {
+		dev_err(dev, "no pcc ports configured\n");
+		return -ENODEV;
+	}
+
+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+	if (rc) {
+		dev_err(dev, "cannot set 64-bits DMA mask\n");
+		return rc;
+	}
+
+	pcc->dma.size = PCC_DMA_BUFSZ;
+	pcc->dma.virt = dmam_alloc_coherent(dev,
+					    pcc->dma.size,
+					    &pcc->dma.addr,
+					    GFP_KERNEL);
+	if (!pcc->dma.virt) {
+		dev_err(dev, "cannot allocate DMA buffer\n");
+		return -ENOMEM;
+	}
+
+	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
+	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
+	if (rc) {
+		return -ENOMEM;
+	}
+
+	/* Disable PCC to clean up DMA buffer before request IRQ. */
+	rc = aspeed_pcc_disable(pcc);
+	if (rc) {
+		dev_err(dev, "Couldn't disable PCC\n");
+		goto err_free_kfifo;
+	}
+
+	pcc->irq = platform_get_irq(pdev, 0);
+	if (pcc->irq < 0) {
+		rc = pcc->irq;
+		goto err_free_kfifo;
+	}
+
+	rc = devm_request_irq(dev, pcc->irq, aspeed_pcc_isr, 0, DEVICE_NAME, pcc);
+	if (rc < 0) {
+		dev_err(dev, "Couldn't request IRQ %d\n", pcc->irq);
+		goto err_free_kfifo;
+	}
+
+	init_waitqueue_head(&pcc->wq);
+
+	pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL);
+	if (pcc->mdev_id < 0) {
+		dev_err(dev, "Couldn't allocate ID\n");
+		goto err_free_kfifo;
+	}
+
+	pcc->mdev.parent = dev;
+	pcc->mdev.minor = MISC_DYNAMIC_MINOR;
+	pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME,
+					pcc->mdev_id);
+	pcc->mdev.fops = &pcc_fops;
+	rc = misc_register(&pcc->mdev);
+	if (rc) {
+		dev_err(dev, "Couldn't register misc device\n");
+		goto err_free_ida;
+	}
+
+	rc = aspeed_pcc_enable(pcc, dev);
+	if (rc) {
+		dev_err(dev, "Couldn't enable PCC\n");
+		goto err_dereg_mdev;
+	}
+
+	dev_set_drvdata(dev, pcc);
+
+	return 0;
+
+err_dereg_mdev:
+	misc_deregister(&pcc->mdev);
+
+err_free_ida:
+	ida_free(&aspeed_pcc_ida, pcc->mdev_id);
+
+err_free_kfifo:
+	kfifo_free(&pcc->fifo);
+
+	return rc;
+}
+
+static void aspeed_pcc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev);
+
+	kfifo_free(&pcc->fifo);
+	ida_free(&aspeed_pcc_ida, pcc->mdev_id);
+	misc_deregister(&pcc->mdev);
+}
+
+static const struct of_device_id aspeed_pcc_table[] = {
+	{ .compatible = "aspeed,ast2600-lpc-pcc" },
+};
+
+static struct platform_driver aspeed_pcc_driver = {
+	.driver = {
+		.name = "aspeed-pcc",
+		.of_match_table = aspeed_pcc_table,
+	},
+	.probe = aspeed_pcc_probe,
+	.remove = aspeed_pcc_remove,
+};
+
+module_platform_driver(aspeed_pcc_driver);
+
+MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang at aspeedtech.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Aspeed Post Code Capture");
-- 
2.34.1



From leo.yan at arm.com  Mon Mar 10 04:59:11 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 11:59:11 +0000
Subject: [PATCH v2 1/8] coresight: etm4x: Extract the trace unit
 controlling
In-Reply-To: <bb390d95-7f2b-4327-a809-9e4cdbd1a1bc@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-2-leo.yan@arm.com>
 <bb390d95-7f2b-4327-a809-9e4cdbd1a1bc@arm.com>
Message-ID: <20250310115911.GE9682@e132581.arm.com>

Hi Suzuki,

On Mon, Mar 10, 2025 at 10:57:25AM +0000, Suzuki Kuruppassery Poulose wrote:
> Hi Leo
> 
> On 10/03/2025 10:49, Leo Yan wrote:
> > The trace unit is controlled in the ETM hardware enabling and disabling.
> > The sequential changes for support AUX pause and resume will reuse the
> > same operations.
> > 
> > Extract the operations in the etm4_{enable|disable}_trace_unit()
> > functions.  A minor improvement in etm4_enable_trace_unit() is for
> > returning the timeout error to callers.
> > 
> > Signed-off-by: Leo Yan <leo.yan at arm.com>
> 
> fyi, this area of code has changes significantly and will cause
> conflicts, due to the introduction of synchronization after
> each access to the TRCSTATR. Please rebase your next version on
> the coresight next branch to avoid the conflict.

Sure.  Will rebase on CoreSight next branch [1].

Thanks for reminding.

Leo

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git/log/?//h=next

> The changes as such look good to me.
> 
> Suzuki


From sudeep.holla at arm.com  Mon Mar 10 04:59:33 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 10 Mar 2025 11:59:33 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
References: <Z6x8cNyDt8rJ73_B@bogus>
 <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto>
 <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus>
 <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
Message-ID: <Z87UJdhiTWhssnbl@bogus>

On Mon, Mar 10, 2025 at 10:45:44AM +0000, Peng Fan wrote:
> > Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> > fwnode for scmi cpufreq
> > 
> > On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
> > >
> > > Sorry, if I misunderstood.
> > >
> > > I will give a look on this and propose a RFC.
> > >
> > > DT maintainers may ask for a patchset including binding change and
> > > driver changes to get a whole view on the compatible stuff.
> > >
> > > BTW, Cristian, Saravana if you have any objections/ideas or would
> > take
> > > on this effort, please let me know.
> > >
> > 
> > Can you point me to the DTS with which you are seeing this issue ?
> > I am trying to reproduce the issue but so far not successful. I did move
> > to power-domains for CPUFreq on Juno. IIUC all we need is both
> > cpufreq and performance genpd drivers in the kernel and then GPU
> > using perf genpd fails with probe deferral right ? I need pointers to
> > reproduce the issue so that I can check if what I have cooked up as a
> > solution really works.
>
> This is in downstream tree:
> https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L2971
> https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L3043
> https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L80
>
> we are using "power-domains" property for cpu perf and gpu/vpu perf.
>
> If cpufreq.off=1 is set in bootargs, the vpu/gpu driver will defer probe.
>

OK, does the probe of these drivers get called or they don't as the driver
core doesn't allow that ? I just have a dummy driver for mali on Juno
which just does dev_pm_domain_attach_list() in the probe and it seem to
succeed even when cpufreq.off=1 is passed. I see scmi-cpufreq failing
with -ENODEV as expected.

I need to follow the code and check if I can somehow reproduce. Also are
you sure this is not with anything in the downstream code ? Also have you
tried this with v6.14-rc* ? Are you sure all the fw_devlink code is backported
in the tree you pointed me which is v6.6-stable ?

--
Regards,
Sudeep


From suzuki.poulose at arm.com  Mon Mar 10 05:01:25 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 12:01:25 +0000
Subject: [PATCH v2 2/8] coresight: Introduce pause and resume APIs for
 source
In-Reply-To: <20250310104919.58816-3-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-3-leo.yan@arm.com>
Message-ID: <65979e92-0047-427c-848d-53f908671905@arm.com>

On 10/03/2025 10:49, Leo Yan wrote:
> Introduce APIs for pausing and resuming trace source and export as GPL
> symbols.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c | 20 ++++++++++++++++++++
>   drivers/hwtracing/coresight/coresight-priv.h |  2 ++
>   include/linux/coresight.h                    |  4 ++++
>   3 files changed, 26 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 0a9380350fb5..eb7b83a7bfa2 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -365,6 +365,26 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
>   }
>   EXPORT_SYMBOL_GPL(coresight_disable_source);
>   
> +void coresight_pause_source(struct coresight_device *csdev)
> +{
> +	if (!csdev || !coresight_is_percpu_source(csdev))

You may remove the !csdev check, coresight_is_percpu_source() already 
checks that.


> +		return;
> +
> +	if (source_ops(csdev)->pause)
> +		source_ops(csdev)->pause(csdev);
> +}
> +EXPORT_SYMBOL_GPL(coresight_pause_source);
> +
> +void coresight_resume_source(struct coresight_device *csdev)
> +{
> +	if (!csdev || !coresight_is_percpu_source(csdev))
> +		return;
> +

Same as above.

> +	if (source_ops(csdev)->resume)
> +		source_ops(csdev)->resume(csdev);
> +}
> +EXPORT_SYMBOL_GPL(coresight_resume_source);
> +
>   /*
>    * coresight_disable_path_from : Disable components in the given path beyond
>    * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 76403530f33e..a9f14c075e91 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -247,5 +247,7 @@ void coresight_add_helper(struct coresight_device *csdev,
>   void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
>   struct coresight_device *coresight_get_percpu_sink(int cpu);
>   void coresight_disable_source(struct coresight_device *csdev, void *data);
> +void coresight_pause_source(struct coresight_device *csdev);
> +void coresight_resume_source(struct coresight_device *csdev);
>   
>   #endif
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 17276965ff1d..703e1b8dbe22 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -385,6 +385,8 @@ struct coresight_ops_link {
>    *		is associated to.
>    * @enable:	enables tracing for a source.
>    * @disable:	disables tracing for a source.
> + * @resume:	resumes tracing for a source.
> + * @pause:	pauses tracing for a source.
>    */
>   struct coresight_ops_source {
>   	int (*cpu_id)(struct coresight_device *csdev);
> @@ -392,6 +394,8 @@ struct coresight_ops_source {
>   		      enum cs_mode mode, struct coresight_trace_id_map *id_map);
>   	void (*disable)(struct coresight_device *csdev,
>   			struct perf_event *event);
> +	int (*resume)(struct coresight_device *csdev);
> +	void (*pause)(struct coresight_device *csdev);

Given these callbacks are for perf mode, does it make sense  to pass the 
parameters similar to enable() ? Also, should we rename these as :

resume_perf
pause_perf

To explicitly mark them perf mode specific ?

Suzuki

>   };
>   
>   /**



From linux at armlinux.org.uk  Mon Mar 10 05:08:54 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:08:54 +0000
Subject: [PATCH net-next 0/9] net: stmmac: remove unnecessary
 of_get_phy_mode() calls
Message-ID: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>

Hi,

This series removes unnecessary of_get_phy_mode() calls from the stmmac
glue drivers. stmmac_probe_config_dt() / devm_stmmac_probe_config_dt()
already gets the interface mode using device_get_phy_mode() and stores
it in plat_dat->phy_interface.

Therefore, glue drivers using of_get_phy_mode() are just duplicating
the work that has already been done.

This series adjusts the glue drivers to remove their usage of
of_get_phy_mode().

 drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c    | 18 ++++++++----------
 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c    | 12 ++++--------
 drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c   |  8 +-------
 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c    |  6 +-----
 .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c    |  4 +---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c         |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c        | 12 ++++--------
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c      |  8 +-------
 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c      |  6 +-----
 9 files changed, 22 insertions(+), 54 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:23 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:23 +0000
Subject: [PATCH net-next 2/9] net: stmmac: mediatek: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbxf-005qY4-QD@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Initialise priv_plat->phy_mode from plat->phy_interface
inmediatek_dwmac_common_data().

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index c9636832a570..d178d5ddc7c7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -456,7 +456,6 @@ static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
 {
 	struct mac_delay_struct *mac_delay = &plat->mac_delay;
 	u32 tx_delay_ps, rx_delay_ps;
-	int err;
 
 	plat->peri_regmap = syscon_regmap_lookup_by_phandle(plat->np, "mediatek,pericfg");
 	if (IS_ERR(plat->peri_regmap)) {
@@ -464,12 +463,6 @@ static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
 		return PTR_ERR(plat->peri_regmap);
 	}
 
-	err = of_get_phy_mode(plat->np, &plat->phy_mode);
-	if (err) {
-		dev_err(plat->dev, "not find phy-mode\n");
-		return err;
-	}
-
 	if (!of_property_read_u32(plat->np, "mediatek,tx-delay-ps", &tx_delay_ps)) {
 		if (tx_delay_ps < plat->variant->tx_delay_max) {
 			mac_delay->tx_delay = tx_delay_ps;
@@ -587,6 +580,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
 {
 	int i;
 
+	priv_plat->phy_mode = plat->phy_interface;
 	plat->mac_interface = priv_plat->phy_mode;
 	if (priv_plat->mac_wol)
 		plat->flags &= ~STMMAC_FLAG_USE_PHY_WOL;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:28 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:28 +0000
Subject: [PATCH net-next 3/9] net: stmmac: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbxk-005qYA-Up@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Rearrange the initialisation order so we can pass plat_dat into
anarion_config_dt(), thereby providing plat_dat->phy_interface as
necessary there.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../ethernet/stmicro/stmmac/dwmac-anarion.c    | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
index ef99ef3f1ab4..fe47a5c337f6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
@@ -59,7 +59,9 @@ static void anarion_gmac_exit(struct platform_device *pdev, void *priv)
 	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);
 }
 
-static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
+static struct anarion_gmac *
+anarion_config_dt(struct platform_device *pdev,
+		  struct plat_stmmacenet_data *plat_dat)
 {
 	struct anarion_gmac *gmac;
 	phy_interface_t phy_mode;
@@ -79,11 +81,7 @@ static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
 
 	gmac->ctl_block = ctl_block;
 
-	err = of_get_phy_mode(pdev->dev.of_node, &phy_mode);
-	if (err)
-		return ERR_PTR(err);
-
-	switch (phy_mode) {
+	switch (plat_dat->phy_interface) {
 	case PHY_INTERFACE_MODE_RGMII:
 		fallthrough;
 	case PHY_INTERFACE_MODE_RGMII_ID:
@@ -111,14 +109,14 @@ static int anarion_dwmac_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	gmac = anarion_config_dt(pdev);
-	if (IS_ERR(gmac))
-		return PTR_ERR(gmac);
-
 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
 	if (IS_ERR(plat_dat))
 		return PTR_ERR(plat_dat);
 
+	gmac = anarion_config_dt(pdev, plat_dat);
+	if (IS_ERR(gmac))
+		return PTR_ERR(gmac);
+
 	plat_dat->init = anarion_gmac_init;
 	plat_dat->exit = anarion_gmac_exit;
 	anarion_gmac_init(pdev, gmac);
-- 
2.30.2



From maz at kernel.org  Mon Mar 10 05:24:49 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:49 +0000
Subject: [PATCH v2 07/23] KVM: arm64: Don't treat HCRX_EL2 as a FGT register
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-8-maz@kernel.org>

Treating HCRX_EL2 as yet another FGT register seems excessive, and
gets in a way of further improvements. It is actually simpler to
just be explicit about the masking, so just to that.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 23bbe28eaaf95..927f27badf758 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -261,12 +261,9 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
 	if (cpus_have_final_cap(ARM64_HAS_HCX)) {
 		u64 hcrx = vcpu->arch.hcrx_el2;
 		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
-			u64 clr = 0, set = 0;
-
-			compute_clr_set(vcpu, HCRX_EL2, clr, set);
-
-			hcrx |= set;
-			hcrx &= ~clr;
+			u64 val = __vcpu_sys_reg(vcpu, HCRX_EL2);
+			hcrx |= val & __HCRX_EL2_MASK;
+			hcrx &= ~(~val & __HCRX_EL2_nMASK);
 		}
 
 		write_sysreg_s(hcrx, SYS_HCRX_EL2);
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:51 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:51 +0000
Subject: [PATCH v2 09/23] KVM: arm64: Compute FGT masks from KVM's own FGT tables
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-10-maz@kernel.org>

In the process of decoupling KVM's view of the FGT bits from the
wider architectural state, use KVM's own FGT tables to build
a synthitic view of what is actually known.

This allows for some checking along the way.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_arm.h  |   4 ++
 arch/arm64/include/asm/kvm_host.h |  14 ++++
 arch/arm64/kvm/emulate-nested.c   | 102 ++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 52bd4abc2a85d..9ff6fda07a68e 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -362,6 +362,10 @@
 #define __HAFGRTR_EL2_MASK	(GENMASK(49, 17) | GENMASK(4, 0))
 #define __HAFGRTR_EL2_nMASK	~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
 
+/* Because the sysreg file mixes R and W... */
+#define HFGRTR_EL2_RES0		HFGxTR_EL2_RES0
+#define HFGWTR_EL2_RES0		(HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
+
 /* Similar definitions for HCRX_EL2 */
 #define __HCRX_EL2_RES0         HCRX_EL2_RES0
 #define __HCRX_EL2_MASK		(BIT(6))
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3a7ec98ef1238..657fb8243ea63 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -569,6 +569,20 @@ struct kvm_sysreg_masks {
 	} mask[NR_SYS_REGS - __SANITISED_REG_START__];
 };
 
+struct fgt_masks {
+	const char	*str;
+	u64		mask;
+	u64		nmask;
+	u64		res0;
+};
+
+extern struct fgt_masks hfgrtr_masks;
+extern struct fgt_masks hfgwtr_masks;
+extern struct fgt_masks hfgitr_masks;
+extern struct fgt_masks hdfgrtr_masks;
+extern struct fgt_masks hdfgwtr_masks;
+extern struct fgt_masks hafgrtr_masks;
+
 struct kvm_cpu_context {
 	struct user_pt_regs regs;	/* sp = sp_el0 */
 
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 607d37bab70b4..bbfe89c37a86e 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2033,6 +2033,101 @@ static u32 encoding_next(u32 encoding)
 	return sys_reg(op0 + 1, 0, 0, 0, 0);
 }
 
+#define FGT_MASKS(__n, __m)						\
+	struct fgt_masks __n = { .str = #__m, .res0 = __m, }
+
+FGT_MASKS(hfgrtr_masks, HFGRTR_EL2_RES0);
+FGT_MASKS(hfgwtr_masks, HFGWTR_EL2_RES0);
+FGT_MASKS(hfgitr_masks, HFGITR_EL2_RES0);
+FGT_MASKS(hdfgrtr_masks, HDFGRTR_EL2_RES0);
+FGT_MASKS(hdfgwtr_masks, HDFGWTR_EL2_RES0);
+FGT_MASKS(hafgrtr_masks, HAFGRTR_EL2_RES0);
+
+static __init bool aggregate_fgt(union trap_config tc)
+{
+	struct fgt_masks *rmasks, *wmasks;
+
+	switch (tc.fgt) {
+	case HFGxTR_GROUP:
+		rmasks = &hfgrtr_masks;
+		wmasks = &hfgwtr_masks;
+		break;
+	case HDFGRTR_GROUP:
+		rmasks = &hdfgrtr_masks;
+		wmasks = &hdfgwtr_masks;
+		break;
+	case HAFGRTR_GROUP:
+		rmasks = &hafgrtr_masks;
+		wmasks = NULL;
+		break;
+	case HFGITR_GROUP:
+		rmasks = &hfgitr_masks;
+		wmasks = NULL;
+		break;
+	}
+
+	/*
+	 * A bit can be reserved in either the R or W register, but
+	 * not both.
+	 */
+	if ((BIT(tc.bit) & rmasks->res0) &&
+	    (!wmasks || (BIT(tc.bit) & wmasks->res0)))
+		return false;
+
+	if (tc.pol)
+		rmasks->mask |= BIT(tc.bit) & ~rmasks->res0;
+	else
+		rmasks->nmask |= BIT(tc.bit) & ~rmasks->res0;
+
+	if (wmasks) {
+		if (tc.pol)
+			wmasks->mask |= BIT(tc.bit) & ~wmasks->res0;
+		else
+			wmasks->nmask |= BIT(tc.bit) & ~wmasks->res0;
+	}
+
+	return true;
+}
+
+static __init int check_fgt_masks(struct fgt_masks *masks)
+{
+	unsigned long duplicate = masks->mask & masks->nmask;
+	u64 res0 = masks->res0;
+	int ret = 0;
+
+	if (duplicate) {
+		int i;
+
+		for_each_set_bit(i, &duplicate, 64) {
+			kvm_err("%s[%d] bit has both polarities\n",
+				masks->str, i);
+		}
+
+		ret = -EINVAL;
+	}
+
+	masks->res0 = ~(masks->mask | masks->nmask);
+	if (masks->res0 != res0)
+		kvm_info("Implicit %s = %016llx, expecting %016llx\n",
+			 masks->str, masks->res0, res0);
+
+	return ret;
+}
+
+static __init int check_all_fgt_masks(int ret)
+{
+	int err = 0;
+
+	err |= check_fgt_masks(&hfgrtr_masks);
+	err |= check_fgt_masks(&hfgwtr_masks);
+	err |= check_fgt_masks(&hfgitr_masks);
+	err |= check_fgt_masks(&hdfgrtr_masks);
+	err |= check_fgt_masks(&hdfgwtr_masks);
+	err |= check_fgt_masks(&hafgrtr_masks);
+
+	return ret ?: err;
+}
+
 int __init populate_nv_trap_config(void)
 {
 	int ret = 0;
@@ -2097,8 +2192,15 @@ int __init populate_nv_trap_config(void)
 			ret = xa_err(prev);
 			print_nv_trap_error(fgt, "Failed FGT insertion", ret);
 		}
+
+		if (!aggregate_fgt(tc)) {
+			ret = -EINVAL;
+			print_nv_trap_error(fgt, "FGT bit is reserved", ret);
+		}
 	}
 
+	ret = check_all_fgt_masks(ret);
+
 	kvm_info("nv: %ld fine grained trap handlers\n",
 		 ARRAY_SIZE(encoding_to_fgt));
 
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:50 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:50 +0000
Subject: [PATCH v2 08/23] KVM: arm64: Plug FEAT_GCS handling
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-9-maz@kernel.org>

We don't seem to be handling the GCS-specific exception class.
Handle it by delivering an UNDEF to the guest, and populate the
relevant trap bits.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/handle_exit.c | 11 +++++++++++
 arch/arm64/kvm/sys_regs.c    |  8 ++++++++
 2 files changed, 19 insertions(+)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index b2d11cd0447c1..bf08c44491b4a 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -294,6 +294,16 @@ static int handle_svc(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+static int kvm_handle_gcs(struct kvm_vcpu *vcpu)
+{
+	/* We don't expect GCS, so treat it with contempt */
+	if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP))
+		WARN_ON_ONCE(1);
+
+	kvm_inject_undefined(vcpu);
+	return 1;
+}
+
 static int handle_other(struct kvm_vcpu *vcpu)
 {
 	bool is_l2 = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
@@ -376,6 +386,7 @@ static exit_handle_fn arm_exit_handlers[] = {
 	[ESR_ELx_EC_BRK64]	= kvm_handle_guest_debug,
 	[ESR_ELx_EC_FP_ASIMD]	= kvm_handle_fpasimd,
 	[ESR_ELx_EC_PAC]	= kvm_handle_ptrauth,
+	[ESR_ELx_EC_GCS]	= kvm_handle_gcs,
 };
 
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 18721c773475d..2ecd0d51a2dae 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -5056,6 +5056,14 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
 						HFGITR_EL2_nBRBIALL);
 	}
 
+	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP)) {
+		kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nGCS_EL0 |
+						HFGxTR_EL2_nGCS_EL1);
+		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_nGCSPUSHM_EL1 |
+						HFGITR_EL2_nGCSSTR_EL1 |
+						HFGITR_EL2_nGCSEPP);
+	}
+
 	set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags);
 out:
 	mutex_unlock(&kvm->arch.config_lock);
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:52 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:52 +0000
Subject: [PATCH v2 10/23] KVM: arm64: Add description of FGT bits leading to EC!=0x18
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-11-maz@kernel.org>

The current FTP tables are only concerned with the bits generating
ESR_ELx.EC==0x18. However, we want an exhaustive view of what KVM
really knows about.

So let's add another small table that provides that extra information.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/emulate-nested.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index bbfe89c37a86e..4f468759268c0 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -1279,16 +1279,21 @@ enum fg_filter_id {
 	__NR_FG_FILTER_IDS__
 };
 
-#define SR_FGF(sr, g, b, p, f)					\
-	{							\
-		.encoding	= sr,				\
-		.end		= sr,				\
-		.tc		= {				\
+#define __FGT(g, b, p, f)					\
+		{						\
 			.fgt = g ## _GROUP,			\
 			.bit = g ## _EL2_ ## b ## _SHIFT,	\
 			.pol = p,				\
 			.fgf = f,				\
-		},						\
+		}
+
+#define FGT(g, b, p)		__FGT(g, b, p, __NO_FGF__)
+
+#define SR_FGF(sr, g, b, p, f)					\
+	{							\
+		.encoding	= sr,				\
+		.end		= sr,				\
+		.tc		= __FGT(g, b, p, f),		\
 		.line = __LINE__,				\
 	}
 
@@ -1989,6 +1994,14 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
 	SR_FGT(SYS_AMEVCNTR0_EL0(0),	HAFGRTR, AMEVCNTR00_EL0, 1),
 };
 
+/* Additional FGTs that do not fire with ESR_EL2.EC==0x18 */
+static const union trap_config non_0x18_fgt[] __initconst = {
+	FGT(HFGITR, nGCSSTR_EL1, 0),
+	FGT(HFGITR, SVC_EL1, 1),
+	FGT(HFGITR, SVC_EL0, 1),
+	FGT(HFGITR, ERET, 1),
+};
+
 static union trap_config get_trap_config(u32 sysreg)
 {
 	return (union trap_config) {
@@ -2199,6 +2212,13 @@ int __init populate_nv_trap_config(void)
 		}
 	}
 
+	for (int i = 0; i < ARRAY_SIZE(non_0x18_fgt); i++) {
+		if (!aggregate_fgt(non_0x18_fgt[i])) {
+			ret = -EINVAL;
+			kvm_err("non_0x18_fgt[%d] is reserved\n", i);
+		}
+	}
+
 	ret = check_all_fgt_masks(ret);
 
 	kvm_info("nv: %ld fine grained trap handlers\n",
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:55 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:55 +0000
Subject: [PATCH v2 13/23] KVM: arm64: Propagate FGT masks to the nVHE hypervisor
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-14-maz@kernel.org>

The nVHE hypervisor needs to have access to its own view of the FGT
masks, which unfortunately results in a bit of data duplication.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h | 7 +++++++
 arch/arm64/kvm/arm.c              | 8 ++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c  | 7 +++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 657fb8243ea63..78ae52e4f48b0 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -583,6 +583,13 @@ extern struct fgt_masks hdfgrtr_masks;
 extern struct fgt_masks hdfgwtr_masks;
 extern struct fgt_masks hafgrtr_masks;
 
+extern struct fgt_masks kvm_nvhe_sym(hfgrtr_masks);
+extern struct fgt_masks kvm_nvhe_sym(hfgwtr_masks);
+extern struct fgt_masks kvm_nvhe_sym(hfgitr_masks);
+extern struct fgt_masks kvm_nvhe_sym(hdfgrtr_masks);
+extern struct fgt_masks kvm_nvhe_sym(hdfgwtr_masks);
+extern struct fgt_masks kvm_nvhe_sym(hafgrtr_masks);
+
 struct kvm_cpu_context {
 	struct user_pt_regs regs;	/* sp = sp_el0 */
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b8e55a441282f..b5ee4669fe7cb 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2414,6 +2414,14 @@ static void kvm_hyp_init_symbols(void)
 	kvm_nvhe_sym(__icache_flags) = __icache_flags;
 	kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits;
 
+	/* Propagate the FGT state to the the nVHE side */
+	kvm_nvhe_sym(hfgrtr_masks)  = hfgrtr_masks;
+	kvm_nvhe_sym(hfgwtr_masks)  = hfgwtr_masks;
+	kvm_nvhe_sym(hfgitr_masks)  = hfgitr_masks;
+	kvm_nvhe_sym(hdfgrtr_masks) = hdfgrtr_masks;
+	kvm_nvhe_sym(hdfgwtr_masks) = hdfgwtr_masks;
+	kvm_nvhe_sym(hafgrtr_masks) = hafgrtr_masks;
+
 	/*
 	 * Flush entire BSS since part of its data containing init symbols is read
 	 * while the MMU is off.
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 7d2ba6ef02618..ae55d6d87e3d2 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -33,6 +33,13 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
 DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
+struct fgt_masks hfgrtr_masks;
+struct fgt_masks hfgwtr_masks;
+struct fgt_masks hfgitr_masks;
+struct fgt_masks hdfgrtr_masks;
+struct fgt_masks hdfgwtr_masks;
+struct fgt_masks hafgrtr_masks;
+
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
 static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:54 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:54 +0000
Subject: [PATCH v2 12/23] KVM: arm64: Unconditionally configure fine-grain traps
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-13-maz@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

... otherwise we can inherit the host configuration if this differs from
the KVM configuration.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
[maz: simplified a couple of things]
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 39 ++++++++++---------------
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 927f27badf758..c4e12516f6466 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -107,7 +107,8 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 
 #define update_fgt_traps_cs(hctxt, vcpu, kvm, reg, clr, set)		\
 	do {								\
-		u64 c = 0, s = 0;					\
+		u64 c = clr, s = set;					\
+		u64 val;						\
 									\
 		ctxt_sys_reg(hctxt, reg) = read_sysreg_s(SYS_ ## reg);	\
 		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))		\
@@ -115,14 +116,10 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 									\
 		compute_undef_clr_set(vcpu, kvm, reg, c, s);		\
 									\
-		s |= set;						\
-		c |= clr;						\
-		if (c || s) {						\
-			u64 val = __ ## reg ## _nMASK;			\
-			val |= s;					\
-			val &= ~c;					\
-			write_sysreg_s(val, SYS_ ## reg);		\
-		}							\
+		val = __ ## reg ## _nMASK;				\
+		val |= s;						\
+		val &= ~c;						\
+		write_sysreg_s(val, SYS_ ## reg);			\
 	} while(0)
 
 #define update_fgt_traps(hctxt, vcpu, kvm, reg)		\
@@ -175,33 +172,27 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 		update_fgt_traps(hctxt, vcpu, kvm, HAFGRTR_EL2);
 }
 
-#define __deactivate_fgt(htcxt, vcpu, kvm, reg)				\
+#define __deactivate_fgt(htcxt, vcpu, reg)				\
 	do {								\
-		if ((vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) ||	\
-		    kvm->arch.fgu[reg_to_fgt_group_id(reg)])		\
-			write_sysreg_s(ctxt_sys_reg(hctxt, reg),	\
-				       SYS_ ## reg);			\
+		write_sysreg_s(ctxt_sys_reg(hctxt, reg),		\
+			       SYS_ ## reg);				\
 	} while(0)
 
 static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);
-	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 
 	if (!cpus_have_final_cap(ARM64_HAS_FGT))
 		return;
 
-	__deactivate_fgt(hctxt, vcpu, kvm, HFGRTR_EL2);
-	if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
-		write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2);
-	else
-		__deactivate_fgt(hctxt, vcpu, kvm, HFGWTR_EL2);
-	__deactivate_fgt(hctxt, vcpu, kvm, HFGITR_EL2);
-	__deactivate_fgt(hctxt, vcpu, kvm, HDFGRTR_EL2);
-	__deactivate_fgt(hctxt, vcpu, kvm, HDFGWTR_EL2);
+	__deactivate_fgt(hctxt, vcpu, HFGRTR_EL2);
+	__deactivate_fgt(hctxt, vcpu, HFGWTR_EL2);
+	__deactivate_fgt(hctxt, vcpu, HFGITR_EL2);
+	__deactivate_fgt(hctxt, vcpu, HDFGRTR_EL2);
+	__deactivate_fgt(hctxt, vcpu, HDFGWTR_EL2);
 
 	if (cpu_has_amu())
-		__deactivate_fgt(hctxt, vcpu, kvm, HAFGRTR_EL2);
+		__deactivate_fgt(hctxt, vcpu, HAFGRTR_EL2);
 }
 
 static inline void  __activate_traps_mpam(struct kvm_vcpu *vcpu)
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:53 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:53 +0000
Subject: [PATCH v2 11/23] KVM: arm64: Use computed masks as sanitisers for FGT registers
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-12-maz@kernel.org>

Now that we have computed RES0 bits, use them to sanitise the
guest view of FGT registers.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/nested.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 0c9387d2f5070..63fe1595f318d 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1118,8 +1118,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 		res0 |= HFGxTR_EL2_nS2POR_EL1;
 	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, AIE, IMP))
 		res0 |= (HFGxTR_EL2_nMAIR2_EL1 | HFGxTR_EL2_nAMAIR2_EL1);
-	set_sysreg_masks(kvm, HFGRTR_EL2, res0 | __HFGRTR_EL2_RES0, res1);
-	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | __HFGWTR_EL2_RES0, res1);
+	set_sysreg_masks(kvm, HFGRTR_EL2, res0 | hfgrtr_masks.res0, res1);
+	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | hfgwtr_masks.res0, res1);
 
 	/* HDFG[RW]TR_EL2 */
 	res0 = res1 = 0;
@@ -1157,7 +1157,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 			 HDFGRTR_EL2_nBRBDATA);
 	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P2))
 		res0 |= HDFGRTR_EL2_nPMSNEVFR_EL1;
-	set_sysreg_masks(kvm, HDFGRTR_EL2, res0 | HDFGRTR_EL2_RES0, res1);
+	set_sysreg_masks(kvm, HDFGRTR_EL2, res0 | hdfgrtr_masks.res0, res1);
 
 	/* Reuse the bits from the read-side and add the write-specific stuff */
 	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
@@ -1166,10 +1166,10 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 		res0 |= HDFGWTR_EL2_TRCOSLAR;
 	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceFilt, IMP))
 		res0 |= HDFGWTR_EL2_TRFCR_EL1;
-	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | HDFGWTR_EL2_RES0, res1);
+	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | hdfgwtr_masks.res0, res1);
 
 	/* HFGITR_EL2 */
-	res0 = HFGITR_EL2_RES0;
+	res0 = hfgitr_masks.res0;
 	res1 = HFGITR_EL2_RES1;
 	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, DPB, DPB2))
 		res0 |= HFGITR_EL2_DCCVADP;
@@ -1203,7 +1203,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	set_sysreg_masks(kvm, HFGITR_EL2, res0, res1);
 
 	/* HAFGRTR_EL2 - not a lot to see here */
-	res0 = HAFGRTR_EL2_RES0;
+	res0 = hafgrtr_masks.res0;
 	res1 = HAFGRTR_EL2_RES1;
 	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
 		res0 |= ~(res0 | res1);
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:58 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:58 +0000
Subject: [PATCH v2 16/23] KVM: arm64: Use KVM-specific HCRX_EL2 RES0 mask
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-17-maz@kernel.org>

We do not have a computed table for HCRX_EL2, so statically define
the bits we know about. A warning will fire if the architecture
grows bits that are not handled yet.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_arm.h | 18 ++++++++++++++----
 arch/arm64/kvm/emulate-nested.c  |  5 +++++
 arch/arm64/kvm/nested.c          |  4 ++--
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 5bdeea023f01f..66012bbb8032a 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -326,10 +326,20 @@
 #define HFGRTR_EL2_RES0		HFGxTR_EL2_RES0
 #define HFGWTR_EL2_RES0		(HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
 
-/* Polarity masks for HCRX_EL2 */
-#define __HCRX_EL2_RES0         HCRX_EL2_RES0
-#define __HCRX_EL2_MASK		(BIT(6))
-#define __HCRX_EL2_nMASK	~(__HCRX_EL2_RES0 | __HCRX_EL2_MASK)
+/*
+ * Polarity masks for HCRX_EL2, limited to the bits that we know about
+ * at this point in time. It doesn't mean that we actually *handle*
+ * them, but that at least those that are not advertised to a guest
+ * will be RES0 for that guest.
+ */
+#define __HCRX_EL2_MASK		(BIT_ULL(6))
+#define __HCRX_EL2_nMASK	(GENMASK_ULL(24, 14) | \
+				 GENMASK_ULL(11, 7)  | \
+				 GENMASK_ULL(5, 0))
+#define __HCRX_EL2_RES0		~(__HCRX_EL2_nMASK | __HCRX_EL2_MASK)
+#define __HCRX_EL2_RES1		~(__HCRX_EL2_nMASK | \
+				  __HCRX_EL2_MASK  | \
+				  __HCRX_EL2_RES0)
 
 /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
 #define HPFAR_MASK	(~UL(0xf))
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 4f468759268c0..f6c7331c21ca4 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2149,6 +2149,7 @@ int __init populate_nv_trap_config(void)
 	BUILD_BUG_ON(__NR_CGT_GROUP_IDS__ > BIT(TC_CGT_BITS));
 	BUILD_BUG_ON(__NR_FGT_GROUP_IDS__ > BIT(TC_FGT_BITS));
 	BUILD_BUG_ON(__NR_FG_FILTER_IDS__ > BIT(TC_FGF_BITS));
+	BUILD_BUG_ON(__HCRX_EL2_MASK & __HCRX_EL2_nMASK);
 
 	for (int i = 0; i < ARRAY_SIZE(encoding_to_cgt); i++) {
 		const struct encoding_to_trap_config *cgt = &encoding_to_cgt[i];
@@ -2174,6 +2175,10 @@ int __init populate_nv_trap_config(void)
 		}
 	}
 
+	if (__HCRX_EL2_RES0 != HCRX_EL2_RES0)
+		kvm_info("Sanitised HCR_EL2_RES0 = %016llx, expecting %016llx\n",
+			 __HCRX_EL2_RES0, HCRX_EL2_RES0);
+
 	kvm_info("nv: %ld coarse grained trap handlers\n",
 		 ARRAY_SIZE(encoding_to_cgt));
 
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 63fe1595f318d..48b8a700de457 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1039,8 +1039,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	set_sysreg_masks(kvm, HCR_EL2, res0, res1);
 
 	/* HCRX_EL2 */
-	res0 = HCRX_EL2_RES0;
-	res1 = HCRX_EL2_RES1;
+	res0 = __HCRX_EL2_RES0;
+	res1 = __HCRX_EL2_RES1;
 	if (!kvm_has_feat(kvm, ID_AA64ISAR3_EL1, PACM, TRIVIAL_IMP))
 		res0 |= HCRX_EL2_PACMEn;
 	if (!kvm_has_feat(kvm, ID_AA64PFR2_EL1, FPMR, IMP))
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:57 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:57 +0000
Subject: [PATCH v2 15/23] KVM: arm64: Remove most hand-crafted masks for FGT registers
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-16-maz@kernel.org>

These masks are now useless, and can be removed. One notable
exception is __HFGRTR_ONLY_MASK, as the sysreg file conflates
the HFGRTR_EL2 and HFGWTR_EL2 bits in a most unhelpful way.

To be fixed one day...

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_arm.h        | 42 +------------------------
 arch/arm64/kvm/hyp/include/hyp/switch.h | 19 -----------
 2 files changed, 1 insertion(+), 60 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 9ff6fda07a68e..5bdeea023f01f 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -317,56 +317,16 @@
 
 /*
  * FGT register definitions
- *
- * RES0 and polarity masks as of DDI0487J.a, to be updated as needed.
- * We're not using the generated masks as they are usually ahead of
- * the published ARM ARM, which we use as a reference.
- *
- * Once we get to a point where the two describe the same thing, we'll
- * merge the definitions. One day.
- */
-#define __HFGRTR_EL2_RES0	HFGxTR_EL2_RES0
-#define __HFGRTR_EL2_MASK	GENMASK(49, 0)
-#define __HFGRTR_EL2_nMASK	~(__HFGRTR_EL2_RES0 | __HFGRTR_EL2_MASK)
-
-/*
- * The HFGWTR bits are a subset of HFGRTR bits. To ensure we don't miss any
- * future additions, define __HFGWTR* macros relative to __HFGRTR* ones.
  */
 #define __HFGRTR_ONLY_MASK	(BIT(46) | BIT(42) | BIT(40) | BIT(28) | \
 				 GENMASK(26, 25) | BIT(21) | BIT(18) | \
 				 GENMASK(15, 14) | GENMASK(10, 9) | BIT(2))
-#define __HFGWTR_EL2_RES0	(__HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
-#define __HFGWTR_EL2_MASK	(__HFGRTR_EL2_MASK & ~__HFGRTR_ONLY_MASK)
-#define __HFGWTR_EL2_nMASK	~(__HFGWTR_EL2_RES0 | __HFGWTR_EL2_MASK)
-
-#define __HFGITR_EL2_RES0	HFGITR_EL2_RES0
-#define __HFGITR_EL2_MASK	(BIT(62) | BIT(60) | GENMASK(54, 0))
-#define __HFGITR_EL2_nMASK	~(__HFGITR_EL2_RES0 | __HFGITR_EL2_MASK)
-
-#define __HDFGRTR_EL2_RES0	HDFGRTR_EL2_RES0
-#define __HDFGRTR_EL2_MASK	(BIT(63) | GENMASK(58, 50) | GENMASK(48, 43) | \
-				 GENMASK(41, 40) | GENMASK(37, 22) | \
-				 GENMASK(19, 9) | GENMASK(7, 0))
-#define __HDFGRTR_EL2_nMASK	~(__HDFGRTR_EL2_RES0 | __HDFGRTR_EL2_MASK)
-
-#define __HDFGWTR_EL2_RES0	HDFGWTR_EL2_RES0
-#define __HDFGWTR_EL2_MASK	(GENMASK(57, 52) | GENMASK(50, 48) | \
-				 GENMASK(46, 44) | GENMASK(42, 41) | \
-				 GENMASK(37, 35) | GENMASK(33, 31) | \
-				 GENMASK(29, 23) | GENMASK(21, 10) | \
-				 GENMASK(8, 7) | GENMASK(5, 0))
-#define __HDFGWTR_EL2_nMASK	~(__HDFGWTR_EL2_RES0 | __HDFGWTR_EL2_MASK)
-
-#define __HAFGRTR_EL2_RES0	HAFGRTR_EL2_RES0
-#define __HAFGRTR_EL2_MASK	(GENMASK(49, 17) | GENMASK(4, 0))
-#define __HAFGRTR_EL2_nMASK	~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
 
 /* Because the sysreg file mixes R and W... */
 #define HFGRTR_EL2_RES0		HFGxTR_EL2_RES0
 #define HFGWTR_EL2_RES0		(HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
 
-/* Similar definitions for HCRX_EL2 */
+/* Polarity masks for HCRX_EL2 */
 #define __HCRX_EL2_RES0         HCRX_EL2_RES0
 #define __HCRX_EL2_MASK		(BIT(6))
 #define __HCRX_EL2_nMASK	~(__HCRX_EL2_RES0 | __HCRX_EL2_MASK)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index b3f02fa5ab79e..392d3d03b77d3 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -156,17 +156,6 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 #define update_fgt_traps(hctxt, vcpu, kvm, reg)		\
 	update_fgt_traps_cs(hctxt, vcpu, kvm, reg, 0, 0)
 
-/*
- * Validate the fine grain trap masks.
- * Check that the masks do not overlap and that all bits are accounted for.
- */
-#define CHECK_FGT_MASKS(reg)							\
-	do {									\
-		BUILD_BUG_ON((__ ## reg ## _MASK) & (__ ## reg ## _nMASK));	\
-		BUILD_BUG_ON(~((__ ## reg ## _RES0) ^ (__ ## reg ## _MASK) ^	\
-			       (__ ## reg ## _nMASK)));				\
-	} while(0)
-
 static inline bool cpu_has_amu(void)
 {
        u64 pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
@@ -180,14 +169,6 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 	struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);
 	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 
-	CHECK_FGT_MASKS(HFGRTR_EL2);
-	CHECK_FGT_MASKS(HFGWTR_EL2);
-	CHECK_FGT_MASKS(HFGITR_EL2);
-	CHECK_FGT_MASKS(HDFGRTR_EL2);
-	CHECK_FGT_MASKS(HDFGWTR_EL2);
-	CHECK_FGT_MASKS(HAFGRTR_EL2);
-	CHECK_FGT_MASKS(HCRX_EL2);
-
 	if (!cpus_have_final_cap(ARM64_HAS_FGT))
 		return;
 
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:59 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:59 +0000
Subject: [PATCH v2 17/23] KVM: arm64: Handle PSB CSYNC traps
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-18-maz@kernel.org>

The architecture introduces a trap for PSB CSYNC that fits in
 the same EC as LS64. Let's deal with it in a similar way as
LS64.

It's not that we expect this to be useful any time soon anyway.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/esr.h    | 3 ++-
 arch/arm64/kvm/emulate-nested.c | 1 +
 arch/arm64/kvm/handle_exit.c    | 5 +++++
 arch/arm64/tools/sysreg         | 2 +-
 4 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 547b4e857a3e2..f340af79679d8 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -175,10 +175,11 @@
 #define ESR_ELx_WFx_ISS_WFE	(UL(1) << 0)
 #define ESR_ELx_xVC_IMM_MASK	((UL(1) << 16) - 1)
 
-/* ISS definitions for LD64B/ST64B instructions */
+/* ISS definitions for LD64B/ST64B/PSBCSYNC instructions */
 #define ESR_ELx_ISS_OTHER_ST64BV	(0)
 #define ESR_ELx_ISS_OTHER_ST64BV0	(1)
 #define ESR_ELx_ISS_OTHER_LDST64B	(2)
+#define ESR_ELx_ISS_OTHER_PSBCSYNC	(3)
 
 #define DISR_EL1_IDS		(UL(1) << 24)
 /*
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index f6c7331c21ca4..ebfb2805f716b 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -1996,6 +1996,7 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
 
 /* Additional FGTs that do not fire with ESR_EL2.EC==0x18 */
 static const union trap_config non_0x18_fgt[] __initconst = {
+	FGT(HFGITR, PSBCSYNC, 1),
 	FGT(HFGITR, nGCSSTR_EL1, 0),
 	FGT(HFGITR, SVC_EL1, 1),
 	FGT(HFGITR, SVC_EL0, 1),
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index bf08c44491b4a..0491eecd521b0 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -343,6 +343,11 @@ static int handle_other(struct kvm_vcpu *vcpu)
 		if (is_l2)
 			fwd = !(hcrx & HCRX_EL2_EnALS);
 		break;
+	case ESR_ELx_ISS_OTHER_PSBCSYNC:
+		allowed = kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P5);
+		if (is_l2)
+			fwd = (__vcpu_sys_reg(vcpu, HFGITR_EL2) & HFGITR_EL2_PSBCSYNC);
+		break;
 	default:
 		/* Clearly, we're missing something. */
 		WARN_ON_ONCE(1);
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 1cf9a07cce522..f680cd6b3bc75 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -2641,7 +2641,7 @@ Fields	HFGxTR_EL2
 EndSysreg
 
 Sysreg HFGITR_EL2	3	4	1	1	6
-Res0	63
+Field   63	PSBCSYNC
 Field	62	ATS1E1A
 Res0	61
 Field	60	COSPRCTX
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:56 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:56 +0000
Subject: [PATCH v2 14/23] KVM: arm64: Use computed FGT masks to setup FGT registers
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-15-maz@kernel.org>

Flip the hyervisor FGT configuration over to the computed FGT
masks.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 45 +++++++++++++++++++++----
 1 file changed, 38 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index c4e12516f6466..b3f02fa5ab79e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -65,12 +65,41 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 	}
 }
 
+#define reg_to_fgt_masks(reg)						\
+	({								\
+		struct fgt_masks *m;					\
+		switch(reg) {						\
+		case HFGRTR_EL2:					\
+			m = &hfgrtr_masks;				\
+			break;						\
+		case HFGWTR_EL2:					\
+			m = &hfgwtr_masks;				\
+			break;						\
+		case HFGITR_EL2:					\
+			m = &hfgitr_masks;				\
+			break;						\
+		case HDFGRTR_EL2:					\
+			m = &hdfgrtr_masks;				\
+			break;						\
+		case HDFGWTR_EL2:					\
+			m = &hdfgwtr_masks;				\
+			break;						\
+		case HAFGRTR_EL2:					\
+			m = &hafgrtr_masks;				\
+			break;						\
+		default:						\
+			BUILD_BUG_ON(1);				\
+		}							\
+									\
+		m;							\
+	})
+
 #define compute_clr_set(vcpu, reg, clr, set)				\
 	do {								\
-		u64 hfg;						\
-		hfg = __vcpu_sys_reg(vcpu, reg) & ~__ ## reg ## _RES0;	\
-		set |= hfg & __ ## reg ## _MASK; 			\
-		clr |= ~hfg & __ ## reg ## _nMASK; 			\
+		u64 hfg = __vcpu_sys_reg(vcpu, reg);			\
+		struct fgt_masks *m = reg_to_fgt_masks(reg);		\
+		set |= hfg & m->mask;					\
+		clr |= ~hfg & m->nmask;					\
 	} while(0)
 
 #define reg_to_fgt_group_id(reg)					\
@@ -101,12 +130,14 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 #define compute_undef_clr_set(vcpu, kvm, reg, clr, set)			\
 	do {								\
 		u64 hfg = kvm->arch.fgu[reg_to_fgt_group_id(reg)];	\
-		set |= hfg & __ ## reg ## _MASK;			\
-		clr |= hfg & __ ## reg ## _nMASK; 			\
+		struct fgt_masks *m = reg_to_fgt_masks(reg);		\
+		set |= hfg & m->mask;					\
+		clr |= hfg & m->nmask;					\
 	} while(0)
 
 #define update_fgt_traps_cs(hctxt, vcpu, kvm, reg, clr, set)		\
 	do {								\
+		struct fgt_masks *m = reg_to_fgt_masks(reg);		\
 		u64 c = clr, s = set;					\
 		u64 val;						\
 									\
@@ -116,7 +147,7 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
 									\
 		compute_undef_clr_set(vcpu, kvm, reg, c, s);		\
 									\
-		val = __ ## reg ## _nMASK;				\
+		val = m->nmask;						\
 		val |= s;						\
 		val &= ~c;						\
 		write_sysreg_s(val, SYS_ ## reg);			\
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:01 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:01 +0000
Subject: [PATCH v2 19/23] KVM: arm64: Validate FGT register descriptions against RES0 masks
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-20-maz@kernel.org>

In order to point out to the unsuspecting KVM hacker that they
are missing something somewhere, validate that the known FGT bits
do not intersect with the corresponding RES0 mask, as computed at
boot time.

THis check is also performed at boot time, ensuring that there is
no runtime overhead.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/kvm/config.c           | 29 +++++++++++++++++++++++++++++
 arch/arm64/kvm/sys_regs.c         |  2 ++
 3 files changed, 32 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fa046a9ad8264..c98f7eed68142 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1565,5 +1565,6 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 	(kvm_has_feat((k), ID_AA64MMFR3_EL1, S1POE, IMP))
 
 void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt);
+void check_feature_map(void);
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index e38da17445926..d39f1f14e3dc4 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -494,6 +494,35 @@ static struct reg_bits_to_feat_map hafgrtr_feat_map[] = {
 		   FEAT_AMUv1),
 };
 
+static void __init check_feat_map(struct reg_bits_to_feat_map *map,
+				  int map_size, u64 res0, const char *str)
+{
+	u64 mask = 0;
+
+	for (int i = 0; i < map_size; i++)
+		mask |= map[i].bits;
+
+	if (mask != ~res0)
+		kvm_err("Undefined %s behaviour, bits %016llx\n",
+			str, mask ^ ~res0);
+}
+
+void __init check_feature_map(void)
+{
+	check_feat_map(hfgrtr_feat_map, ARRAY_SIZE(hfgrtr_feat_map),
+		       hfgrtr_masks.res0, hfgrtr_masks.str);
+	check_feat_map(hfgwtr_feat_map, ARRAY_SIZE(hfgwtr_feat_map),
+		       hfgwtr_masks.res0, hfgwtr_masks.str);
+	check_feat_map(hfgitr_feat_map, ARRAY_SIZE(hfgitr_feat_map),
+		       hfgitr_masks.res0, hfgitr_masks.str);
+	check_feat_map(hdfgrtr_feat_map, ARRAY_SIZE(hdfgrtr_feat_map),
+		       hdfgrtr_masks.res0, hdfgrtr_masks.str);
+	check_feat_map(hdfgwtr_feat_map, ARRAY_SIZE(hdfgwtr_feat_map),
+		       hdfgwtr_masks.res0, hdfgwtr_masks.str);
+	check_feat_map(hafgrtr_feat_map, ARRAY_SIZE(hafgrtr_feat_map),
+		       hafgrtr_masks.res0, hafgrtr_masks.str);
+}
+
 static bool idreg_feat_match(struct kvm *kvm, struct reg_bits_to_feat_map *map)
 {
 	u64 regval = kvm->arch.id_regs[map->regidx];
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index d3990ceaa59c2..89fc07c57e438 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -5058,6 +5058,8 @@ int __init kvm_sys_reg_table_init(void)
 
 	ret = populate_nv_trap_config();
 
+	check_feature_map();
+
 	for (i = 0; !ret && i < ARRAY_SIZE(sys_reg_descs); i++)
 		ret = populate_sysreg_config(sys_reg_descs + i, i);
 
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:00 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:00 +0000
Subject: [PATCH v2 18/23] KVM: arm64: Switch to table-driven FGU configuration
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-19-maz@kernel.org>

Defining the FGU behaviour is extremely tedious. It relies on matching
each set of bits from FGT registers with am architectural feature, and
adding them to the FGU list if the corresponding feature isn't advertised
to the guest.

It is however relatively easy to dump most of that information from
the architecture JSON description, and use that to control the FGU bits.

Let's introduce a new set of tables descripbing the mapping between
FGT bits and features. Most of the time, this is only a lookup in
an idreg field, with a few more complex exceptions.

While this is obviously many more lines in a new file, this is
mostly generated, and is pretty easy to maintain.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |   2 +
 arch/arm64/kvm/Makefile           |   2 +-
 arch/arm64/kvm/config.c           | 589 ++++++++++++++++++++++++++++++
 arch/arm64/kvm/sys_regs.c         |  73 +---
 4 files changed, 596 insertions(+), 70 deletions(-)
 create mode 100644 arch/arm64/kvm/config.c

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 78ae52e4f48b0..fa046a9ad8264 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1564,4 +1564,6 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 #define kvm_has_s1poe(k)				\
 	(kvm_has_feat((k), ID_AA64MMFR3_EL1, S1POE, IMP))
 
+void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt);
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 3cf7adb2b5038..f05713e125077 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -14,7 +14,7 @@ CFLAGS_sys_regs.o += -Wno-override-init
 CFLAGS_handle_exit.o += -Wno-override-init
 
 kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
-	 inject_fault.o va_layout.o handle_exit.o \
+	 inject_fault.o va_layout.o handle_exit.o config.o \
 	 guest.o debug.o reset.o sys_regs.o stacktrace.o \
 	 vgic-sys-reg-v3.o fpsimd.o pkvm.o \
 	 arch_timer.o trng.o vmid.o emulate-nested.o nested.o at.o \
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
new file mode 100644
index 0000000000000..e38da17445926
--- /dev/null
+++ b/arch/arm64/kvm/config.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Google LLC
+ * Author: Marc Zyngier <maz at kernel.org>
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/sysreg.h>
+
+struct reg_bits_to_feat_map {
+	u64		bits;
+
+#define	NEVER_FGU	BIT(0)	/* Can trap, but never UNDEF */
+#define	CALL_FUNC	BIT(1)	/* Needs to evaluate tons of crap */
+#define	FIXED_VALUE	BIT(2)	/* RAZ/WI or RAO/WI in KVM */
+	unsigned long	flags;
+
+	union {
+		struct {
+			u8	regidx;
+			u8	shift;
+			u8	width;
+			bool	sign;
+			s8	lo_lim;
+		};
+		bool	(*match)(struct kvm *);
+		bool	(*fval)(struct kvm *, u64 *);
+	};
+};
+
+#define __NEEDS_FEAT_3(m, f, id, fld, lim)		\
+	{						\
+		.bits	= (m),				\
+		.flags = (f),				\
+		.regidx	= IDREG_IDX(SYS_ ## id),	\
+		.shift	= id ##_## fld ## _SHIFT,	\
+		.width	= id ##_## fld ## _WIDTH,	\
+		.sign	= id ##_## fld ## _SIGNED,	\
+		.lo_lim	= id ##_## fld ##_## lim	\
+	}
+
+#define __NEEDS_FEAT_2(m, f, fun, dummy)		\
+	{						\
+		.bits	= (m),				\
+		.flags = (f) | CALL_FUNC,		\
+		.fval = (fun),				\
+	}
+
+#define __NEEDS_FEAT_1(m, f, fun)			\
+	{						\
+		.bits	= (m),				\
+		.flags = (f) | CALL_FUNC,		\
+		.match = (fun),				\
+	}
+
+#define NEEDS_FEAT_FLAG(m, f, ...)			\
+	CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, __VA_ARGS__)
+
+#define NEEDS_FEAT_FIXED(m, ...)			\
+	NEEDS_FEAT_FLAG(m, FIXED_VALUE, __VA_ARGS__, 0)
+
+#define NEEDS_FEAT(m, ...)	NEEDS_FEAT_FLAG(m, 0, __VA_ARGS__)
+
+#define FEAT_SPE		ID_AA64DFR0_EL1, PMSVer, IMP
+#define FEAT_SPE_FnE		ID_AA64DFR0_EL1, PMSVer, V1P2
+#define FEAT_BRBE		ID_AA64DFR0_EL1, BRBE, IMP
+#define FEAT_TRC_SR		ID_AA64DFR0_EL1, TraceVer, IMP
+#define FEAT_PMUv3		ID_AA64DFR0_EL1, PMUVer, IMP
+#define FEAT_TRBE		ID_AA64DFR0_EL1, TraceBuffer, IMP
+#define FEAT_DoubleLock		ID_AA64DFR0_EL1, DoubleLock, IMP
+#define FEAT_TRF		ID_AA64DFR0_EL1, TraceFilt, IMP
+#define FEAT_AA64EL1		ID_AA64PFR0_EL1, EL1, IMP
+#define FEAT_AIE		ID_AA64MMFR3_EL1, AIE, IMP
+#define FEAT_S2POE		ID_AA64MMFR3_EL1, S2POE, IMP
+#define FEAT_S1POE		ID_AA64MMFR3_EL1, S1POE, IMP
+#define FEAT_S1PIE		ID_AA64MMFR3_EL1, S1PIE, IMP
+#define FEAT_THE		ID_AA64PFR1_EL1, THE, IMP
+#define FEAT_SME		ID_AA64PFR1_EL1, SME, IMP
+#define FEAT_GCS		ID_AA64PFR1_EL1, GCS, IMP
+#define FEAT_LS64_ACCDATA	ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA
+#define FEAT_RAS		ID_AA64PFR0_EL1, RAS, IMP
+#define FEAT_GICv3		ID_AA64PFR0_EL1, GIC, IMP
+#define FEAT_LOR		ID_AA64MMFR1_EL1, LO, IMP
+#define FEAT_SPEv1p5		ID_AA64DFR0_EL1, PMSVer, V1P5
+#define FEAT_ATS1A		ID_AA64ISAR2_EL1, ATS1A, IMP
+#define FEAT_SPECRES2		ID_AA64ISAR1_EL1, SPECRES, COSP_RCTX
+#define FEAT_SPECRES		ID_AA64ISAR1_EL1, SPECRES, IMP
+#define FEAT_TLBIRANGE		ID_AA64ISAR0_EL1, TLB, RANGE
+#define FEAT_TLBIOS		ID_AA64ISAR0_EL1, TLB, OS
+#define FEAT_PAN2		ID_AA64MMFR1_EL1, PAN, PAN2
+#define FEAT_DPB2		ID_AA64ISAR1_EL1, DPB, DPB2
+#define FEAT_AMUv1		ID_AA64PFR0_EL1, AMU, IMP
+
+static bool feat_rasv1p1(struct kvm *kvm)
+{
+	return (kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, V1P1) ||
+		(kvm_has_feat_enum(kvm, ID_AA64PFR0_EL1, RAS, IMP) &&
+		 kvm_has_feat(kvm, ID_AA64PFR1_EL1, RAS_frac, RASv1p1)));
+}
+
+static bool feat_csv2_2_csv2_1p2(struct kvm *kvm)
+{
+	return (kvm_has_feat(kvm,  ID_AA64PFR0_EL1, CSV2, CSV2_2) ||
+		(kvm_has_feat(kvm, ID_AA64PFR1_EL1, CSV2_frac, CSV2_1p2) &&
+		 kvm_has_feat_enum(kvm,  ID_AA64PFR0_EL1, CSV2, IMP)));
+}
+
+static bool feat_pauth(struct kvm *kvm)
+{
+	return kvm_has_pauth(kvm, PAuth);
+}
+
+static struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
+	NEEDS_FEAT(HFGxTR_EL2_nAMAIR2_EL1	|
+		   HFGxTR_EL2_nMAIR2_EL1,
+		   FEAT_AIE),
+	NEEDS_FEAT(HFGxTR_EL2_nS2POR_EL1, FEAT_S2POE),
+	NEEDS_FEAT(HFGxTR_EL2_nPOR_EL1		|
+		   HFGxTR_EL2_nPOR_EL0,
+		   FEAT_S1POE),
+	NEEDS_FEAT(HFGxTR_EL2_nPIR_EL1		|
+		   HFGxTR_EL2_nPIRE0_EL1,
+		   FEAT_S1PIE),
+	NEEDS_FEAT(HFGxTR_EL2_nRCWMASK_EL1, FEAT_THE),
+	NEEDS_FEAT(HFGxTR_EL2_nTPIDR2_EL0	|
+		   HFGxTR_EL2_nSMPRI_EL1,
+		   FEAT_SME),
+	NEEDS_FEAT(HFGxTR_EL2_nGCS_EL1		|
+		   HFGxTR_EL2_nGCS_EL0,
+		   FEAT_GCS),
+	NEEDS_FEAT(HFGxTR_EL2_nACCDATA_EL1, FEAT_LS64_ACCDATA),
+	NEEDS_FEAT(HFGxTR_EL2_ERXADDR_EL1	|
+		   HFGxTR_EL2_ERXMISCn_EL1	|
+		   HFGxTR_EL2_ERXSTATUS_EL1	|
+		   HFGxTR_EL2_ERXCTLR_EL1	|
+		   HFGxTR_EL2_ERXFR_EL1		|
+		   HFGxTR_EL2_ERRSELR_EL1	|
+		   HFGxTR_EL2_ERRIDR_EL1,
+		   FEAT_RAS),
+	NEEDS_FEAT(HFGxTR_EL2_ERXPFGCDN_EL1|
+		   HFGxTR_EL2_ERXPFGCTL_EL1|
+		   HFGxTR_EL2_ERXPFGF_EL1,
+		   feat_rasv1p1),
+	NEEDS_FEAT(HFGxTR_EL2_ICC_IGRPENn_EL1, FEAT_GICv3),
+	NEEDS_FEAT(HFGxTR_EL2_SCXTNUM_EL0	|
+		   HFGxTR_EL2_SCXTNUM_EL1,
+		   feat_csv2_2_csv2_1p2),
+	NEEDS_FEAT(HFGxTR_EL2_LORSA_EL1		|
+		   HFGxTR_EL2_LORN_EL1		|
+		   HFGxTR_EL2_LORID_EL1		|
+		   HFGxTR_EL2_LOREA_EL1		|
+		   HFGxTR_EL2_LORC_EL1,
+		   FEAT_LOR),
+	NEEDS_FEAT(HFGxTR_EL2_APIBKey		|
+		   HFGxTR_EL2_APIAKey		|
+		   HFGxTR_EL2_APGAKey		|
+		   HFGxTR_EL2_APDBKey		|
+		   HFGxTR_EL2_APDAKey,
+		   feat_pauth),
+	NEEDS_FEAT(HFGxTR_EL2_VBAR_EL1		|
+		   HFGxTR_EL2_TTBR1_EL1		|
+		   HFGxTR_EL2_TTBR0_EL1		|
+		   HFGxTR_EL2_TPIDR_EL0		|
+		   HFGxTR_EL2_TPIDRRO_EL0	|
+		   HFGxTR_EL2_TPIDR_EL1		|
+		   HFGxTR_EL2_TCR_EL1		|
+		   HFGxTR_EL2_SCTLR_EL1		|
+		   HFGxTR_EL2_REVIDR_EL1	|
+		   HFGxTR_EL2_PAR_EL1		|
+		   HFGxTR_EL2_MPIDR_EL1		|
+		   HFGxTR_EL2_MIDR_EL1		|
+		   HFGxTR_EL2_MAIR_EL1		|
+		   HFGxTR_EL2_ISR_EL1		|
+		   HFGxTR_EL2_FAR_EL1		|
+		   HFGxTR_EL2_ESR_EL1		|
+		   HFGxTR_EL2_DCZID_EL0		|
+		   HFGxTR_EL2_CTR_EL0		|
+		   HFGxTR_EL2_CSSELR_EL1	|
+		   HFGxTR_EL2_CPACR_EL1		|
+		   HFGxTR_EL2_CONTEXTIDR_EL1	|
+		   HFGxTR_EL2_CLIDR_EL1		|
+		   HFGxTR_EL2_CCSIDR_EL1	|
+		   HFGxTR_EL2_AMAIR_EL1		|
+		   HFGxTR_EL2_AIDR_EL1		|
+		   HFGxTR_EL2_AFSR1_EL1		|
+		   HFGxTR_EL2_AFSR0_EL1,
+		   FEAT_AA64EL1),
+};
+
+static struct reg_bits_to_feat_map hfgwtr_feat_map[] = {
+	NEEDS_FEAT(HFGxTR_EL2_nAMAIR2_EL1	|
+		   HFGxTR_EL2_nMAIR2_EL1,
+		   FEAT_AIE),
+	NEEDS_FEAT(HFGxTR_EL2_nS2POR_EL1, FEAT_S2POE),
+	NEEDS_FEAT(HFGxTR_EL2_nPOR_EL1		|
+		   HFGxTR_EL2_nPOR_EL0,
+		   FEAT_S1POE),
+	NEEDS_FEAT(HFGxTR_EL2_nPIR_EL1		|
+		   HFGxTR_EL2_nPIRE0_EL1,
+		   FEAT_S1PIE),
+	NEEDS_FEAT(HFGxTR_EL2_nRCWMASK_EL1, FEAT_THE),
+	NEEDS_FEAT(HFGxTR_EL2_nTPIDR2_EL0	|
+		   HFGxTR_EL2_nSMPRI_EL1,
+		   FEAT_SME),
+	NEEDS_FEAT(HFGxTR_EL2_nGCS_EL1		|
+		   HFGxTR_EL2_nGCS_EL0,
+		   FEAT_GCS),
+	NEEDS_FEAT(HFGxTR_EL2_nACCDATA_EL1, FEAT_LS64_ACCDATA),
+	NEEDS_FEAT(HFGxTR_EL2_ERXADDR_EL1	|
+		   HFGxTR_EL2_ERXMISCn_EL1	|
+		   HFGxTR_EL2_ERXSTATUS_EL1	|
+		   HFGxTR_EL2_ERXCTLR_EL1	|
+		   HFGxTR_EL2_ERRSELR_EL1,
+		   FEAT_RAS),
+	NEEDS_FEAT(HFGxTR_EL2_ERXPFGCDN_EL1	|
+		   HFGxTR_EL2_ERXPFGCTL_EL1,
+		   feat_rasv1p1),
+	NEEDS_FEAT(HFGxTR_EL2_ICC_IGRPENn_EL1, FEAT_GICv3),
+	NEEDS_FEAT(HFGxTR_EL2_SCXTNUM_EL0	|
+		   HFGxTR_EL2_SCXTNUM_EL1,
+		   feat_csv2_2_csv2_1p2),
+	NEEDS_FEAT(HFGxTR_EL2_LORSA_EL1		|
+		   HFGxTR_EL2_LORN_EL1		|
+		   HFGxTR_EL2_LOREA_EL1		|
+		   HFGxTR_EL2_LORC_EL1,
+		   FEAT_LOR),
+	NEEDS_FEAT(HFGxTR_EL2_APIBKey		|
+		   HFGxTR_EL2_APIAKey		|
+		   HFGxTR_EL2_APGAKey		|
+		   HFGxTR_EL2_APDBKey		|
+		   HFGxTR_EL2_APDAKey,
+		   feat_pauth),
+	NEEDS_FEAT(HFGxTR_EL2_VBAR_EL1		|
+		   HFGxTR_EL2_TTBR1_EL1		|
+		   HFGxTR_EL2_TTBR0_EL1		|
+		   HFGxTR_EL2_TPIDR_EL0		|
+		   HFGxTR_EL2_TPIDRRO_EL0	|
+		   HFGxTR_EL2_TPIDR_EL1		|
+		   HFGxTR_EL2_TCR_EL1		|
+		   HFGxTR_EL2_SCTLR_EL1		|
+		   HFGxTR_EL2_PAR_EL1		|
+		   HFGxTR_EL2_MAIR_EL1		|
+		   HFGxTR_EL2_FAR_EL1		|
+		   HFGxTR_EL2_ESR_EL1		|
+		   HFGxTR_EL2_CSSELR_EL1	|
+		   HFGxTR_EL2_CPACR_EL1		|
+		   HFGxTR_EL2_CONTEXTIDR_EL1	|
+		   HFGxTR_EL2_AMAIR_EL1		|
+		   HFGxTR_EL2_AFSR1_EL1		|
+		   HFGxTR_EL2_AFSR0_EL1,
+		   FEAT_AA64EL1),
+};
+
+static struct reg_bits_to_feat_map hdfgrtr_feat_map[] = {
+	NEEDS_FEAT(HDFGRTR_EL2_PMBIDR_EL1	|
+		   HDFGRTR_EL2_PMSLATFR_EL1	|
+		   HDFGRTR_EL2_PMSIRR_EL1	|
+		   HDFGRTR_EL2_PMSIDR_EL1	|
+		   HDFGRTR_EL2_PMSICR_EL1	|
+		   HDFGRTR_EL2_PMSFCR_EL1	|
+		   HDFGRTR_EL2_PMSEVFR_EL1	|
+		   HDFGRTR_EL2_PMSCR_EL1	|
+		   HDFGRTR_EL2_PMBSR_EL1	|
+		   HDFGRTR_EL2_PMBPTR_EL1	|
+		   HDFGRTR_EL2_PMBLIMITR_EL1,
+		   FEAT_SPE),
+	NEEDS_FEAT(HDFGRTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
+	NEEDS_FEAT(HDFGRTR_EL2_nBRBDATA		|
+		   HDFGRTR_EL2_nBRBCTL		|
+		   HDFGRTR_EL2_nBRBIDR,
+		   FEAT_BRBE),
+	NEEDS_FEAT(HDFGRTR_EL2_TRCVICTLR	|
+		   HDFGRTR_EL2_TRCSTATR		|
+		   HDFGRTR_EL2_TRCSSCSRn	|
+		   HDFGRTR_EL2_TRCSEQSTR	|
+		   HDFGRTR_EL2_TRCPRGCTLR	|
+		   HDFGRTR_EL2_TRCOSLSR		|
+		   HDFGRTR_EL2_TRCIMSPECn	|
+		   HDFGRTR_EL2_TRCID		|
+		   HDFGRTR_EL2_TRCCNTVRn	|
+		   HDFGRTR_EL2_TRCCLAIM		|
+		   HDFGRTR_EL2_TRCAUXCTLR	|
+		   HDFGRTR_EL2_TRCAUTHSTATUS	|
+		   HDFGRTR_EL2_TRC,
+		   FEAT_TRC_SR),
+	NEEDS_FEAT(HDFGRTR_EL2_PMCEIDn_EL0	|
+		   HDFGRTR_EL2_PMUSERENR_EL0	|
+		   HDFGRTR_EL2_PMMIR_EL1	|
+		   HDFGRTR_EL2_PMSELR_EL0	|
+		   HDFGRTR_EL2_PMOVS		|
+		   HDFGRTR_EL2_PMINTEN		|
+		   HDFGRTR_EL2_PMCNTEN		|
+		   HDFGRTR_EL2_PMCCNTR_EL0	|
+		   HDFGRTR_EL2_PMCCFILTR_EL0	|
+		   HDFGRTR_EL2_PMEVTYPERn_EL0	|
+		   HDFGRTR_EL2_PMEVCNTRn_EL0,
+		   FEAT_PMUv3),
+	NEEDS_FEAT(HDFGRTR_EL2_TRBTRG_EL1	|
+		   HDFGRTR_EL2_TRBSR_EL1	|
+		   HDFGRTR_EL2_TRBPTR_EL1	|
+		   HDFGRTR_EL2_TRBMAR_EL1	|
+		   HDFGRTR_EL2_TRBLIMITR_EL1	|
+		   HDFGRTR_EL2_TRBIDR_EL1	|
+		   HDFGRTR_EL2_TRBBASER_EL1,
+		   FEAT_TRBE),
+	NEEDS_FEAT_FLAG(HDFGRTR_EL2_OSDLR_EL1, NEVER_FGU,
+			FEAT_DoubleLock),
+	NEEDS_FEAT(HDFGRTR_EL2_OSECCR_EL1	|
+		   HDFGRTR_EL2_OSLSR_EL1	|
+		   HDFGRTR_EL2_DBGPRCR_EL1	|
+		   HDFGRTR_EL2_DBGAUTHSTATUS_EL1|
+		   HDFGRTR_EL2_DBGCLAIM		|
+		   HDFGRTR_EL2_MDSCR_EL1	|
+		   HDFGRTR_EL2_DBGWVRn_EL1	|
+		   HDFGRTR_EL2_DBGWCRn_EL1	|
+		   HDFGRTR_EL2_DBGBVRn_EL1	|
+		   HDFGRTR_EL2_DBGBCRn_EL1,
+		   FEAT_AA64EL1)
+};
+
+static struct reg_bits_to_feat_map hdfgwtr_feat_map[] = {
+	NEEDS_FEAT(HDFGWTR_EL2_PMSLATFR_EL1	|
+		   HDFGWTR_EL2_PMSIRR_EL1	|
+		   HDFGWTR_EL2_PMSICR_EL1	|
+		   HDFGWTR_EL2_PMSFCR_EL1	|
+		   HDFGWTR_EL2_PMSEVFR_EL1	|
+		   HDFGWTR_EL2_PMSCR_EL1	|
+		   HDFGWTR_EL2_PMBSR_EL1	|
+		   HDFGWTR_EL2_PMBPTR_EL1	|
+		   HDFGWTR_EL2_PMBLIMITR_EL1,
+		   FEAT_SPE),
+	NEEDS_FEAT(HDFGWTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
+	NEEDS_FEAT(HDFGWTR_EL2_nBRBDATA		|
+		   HDFGWTR_EL2_nBRBCTL,
+		   FEAT_BRBE),
+	NEEDS_FEAT(HDFGWTR_EL2_TRCVICTLR	|
+		   HDFGWTR_EL2_TRCSSCSRn	|
+		   HDFGWTR_EL2_TRCSEQSTR	|
+		   HDFGWTR_EL2_TRCPRGCTLR	|
+		   HDFGWTR_EL2_TRCOSLAR		|
+		   HDFGWTR_EL2_TRCIMSPECn	|
+		   HDFGWTR_EL2_TRCCNTVRn	|
+		   HDFGWTR_EL2_TRCCLAIM		|
+		   HDFGWTR_EL2_TRCAUXCTLR	|
+		   HDFGWTR_EL2_TRC,
+		   FEAT_TRC_SR),
+	NEEDS_FEAT(HDFGWTR_EL2_PMUSERENR_EL0	|
+		   HDFGWTR_EL2_PMCR_EL0		|
+		   HDFGWTR_EL2_PMSWINC_EL0	|
+		   HDFGWTR_EL2_PMSELR_EL0	|
+		   HDFGWTR_EL2_PMOVS		|
+		   HDFGWTR_EL2_PMINTEN		|
+		   HDFGWTR_EL2_PMCNTEN		|
+		   HDFGWTR_EL2_PMCCNTR_EL0	|
+		   HDFGWTR_EL2_PMCCFILTR_EL0	|
+		   HDFGWTR_EL2_PMEVTYPERn_EL0	|
+		   HDFGWTR_EL2_PMEVCNTRn_EL0,
+		   FEAT_PMUv3),
+	NEEDS_FEAT(HDFGWTR_EL2_TRBTRG_EL1	|
+		   HDFGWTR_EL2_TRBSR_EL1	|
+		   HDFGWTR_EL2_TRBPTR_EL1	|
+		   HDFGWTR_EL2_TRBMAR_EL1	|
+		   HDFGWTR_EL2_TRBLIMITR_EL1	|
+		   HDFGWTR_EL2_TRBBASER_EL1,
+		   FEAT_TRBE),
+	NEEDS_FEAT_FLAG(HDFGWTR_EL2_OSDLR_EL1,
+			NEVER_FGU, FEAT_DoubleLock),
+	NEEDS_FEAT(HDFGWTR_EL2_OSECCR_EL1	|
+		   HDFGWTR_EL2_OSLAR_EL1	|
+		   HDFGWTR_EL2_DBGPRCR_EL1	|
+		   HDFGWTR_EL2_DBGCLAIM		|
+		   HDFGWTR_EL2_MDSCR_EL1	|
+		   HDFGWTR_EL2_DBGWVRn_EL1	|
+		   HDFGWTR_EL2_DBGWCRn_EL1	|
+		   HDFGWTR_EL2_DBGBVRn_EL1	|
+		   HDFGWTR_EL2_DBGBCRn_EL1,
+		   FEAT_AA64EL1),
+	NEEDS_FEAT(HDFGWTR_EL2_TRFCR_EL1, FEAT_TRF),
+};
+
+
+static struct reg_bits_to_feat_map hfgitr_feat_map[] = {
+	NEEDS_FEAT(HFGITR_EL2_PSBCSYNC, FEAT_SPEv1p5),
+	NEEDS_FEAT(HFGITR_EL2_ATS1E1A, FEAT_ATS1A),
+	NEEDS_FEAT(HFGITR_EL2_COSPRCTX, FEAT_SPECRES2),
+	NEEDS_FEAT(HFGITR_EL2_nGCSEPP		|
+		   HFGITR_EL2_nGCSSTR_EL1	|
+		   HFGITR_EL2_nGCSPUSHM_EL1,
+		   FEAT_GCS),
+	NEEDS_FEAT(HFGITR_EL2_nBRBIALL		|
+		   HFGITR_EL2_nBRBINJ,
+		   FEAT_BRBE),
+	NEEDS_FEAT(HFGITR_EL2_CPPRCTX		|
+		   HFGITR_EL2_DVPRCTX		|
+		   HFGITR_EL2_CFPRCTX,
+		   FEAT_SPECRES),
+	NEEDS_FEAT(HFGITR_EL2_TLBIRVAALE1	|
+		   HFGITR_EL2_TLBIRVALE1	|
+		   HFGITR_EL2_TLBIRVAAE1	|
+		   HFGITR_EL2_TLBIRVAE1		|
+		   HFGITR_EL2_TLBIRVAALE1IS	|
+		   HFGITR_EL2_TLBIRVALE1IS	|
+		   HFGITR_EL2_TLBIRVAAE1IS	|
+		   HFGITR_EL2_TLBIRVAE1IS	|
+		   HFGITR_EL2_TLBIRVAALE1OS	|
+		   HFGITR_EL2_TLBIRVALE1OS	|
+		   HFGITR_EL2_TLBIRVAAE1OS	|
+		   HFGITR_EL2_TLBIRVAE1OS,
+		   FEAT_TLBIRANGE),
+	NEEDS_FEAT(HFGITR_EL2_TLBIVAALE1OS	|
+		   HFGITR_EL2_TLBIVALE1OS	|
+		   HFGITR_EL2_TLBIVAAE1OS	|
+		   HFGITR_EL2_TLBIASIDE1OS	|
+		   HFGITR_EL2_TLBIVAE1OS	|
+		   HFGITR_EL2_TLBIVMALLE1OS,
+		   FEAT_TLBIOS),
+	NEEDS_FEAT(HFGITR_EL2_ATS1E1WP		|
+		   HFGITR_EL2_ATS1E1RP,
+		   FEAT_PAN2),
+	NEEDS_FEAT(HFGITR_EL2_DCCVADP, FEAT_DPB2),
+	NEEDS_FEAT(HFGITR_EL2_DCCVAC		|
+		   HFGITR_EL2_SVC_EL1		|
+		   HFGITR_EL2_SVC_EL0		|
+		   HFGITR_EL2_ERET		|
+		   HFGITR_EL2_TLBIVAALE1	|
+		   HFGITR_EL2_TLBIVALE1		|
+		   HFGITR_EL2_TLBIVAAE1		|
+		   HFGITR_EL2_TLBIASIDE1	|
+		   HFGITR_EL2_TLBIVAE1		|
+		   HFGITR_EL2_TLBIVMALLE1	|
+		   HFGITR_EL2_TLBIVAALE1IS	|
+		   HFGITR_EL2_TLBIVALE1IS	|
+		   HFGITR_EL2_TLBIVAAE1IS	|
+		   HFGITR_EL2_TLBIASIDE1IS	|
+		   HFGITR_EL2_TLBIVAE1IS	|
+		   HFGITR_EL2_TLBIVMALLE1IS	|
+		   HFGITR_EL2_ATS1E0W		|
+		   HFGITR_EL2_ATS1E0R		|
+		   HFGITR_EL2_ATS1E1W		|
+		   HFGITR_EL2_ATS1E1R		|
+		   HFGITR_EL2_DCZVA		|
+		   HFGITR_EL2_DCCIVAC		|
+		   HFGITR_EL2_DCCVAP		|
+		   HFGITR_EL2_DCCVAU		|
+		   HFGITR_EL2_DCCISW		|
+		   HFGITR_EL2_DCCSW		|
+		   HFGITR_EL2_DCISW		|
+		   HFGITR_EL2_DCIVAC		|
+		   HFGITR_EL2_ICIVAU		|
+		   HFGITR_EL2_ICIALLU		|
+		   HFGITR_EL2_ICIALLUIS,
+		   FEAT_AA64EL1),
+};
+
+static struct reg_bits_to_feat_map hafgrtr_feat_map[] = {
+	NEEDS_FEAT(HAFGRTR_EL2_AMEVTYPER115_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER114_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER113_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER112_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER111_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER110_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER19_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER18_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER17_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER16_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER15_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER14_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER13_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER12_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER11_EL0	|
+		   HAFGRTR_EL2_AMEVTYPER10_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR115_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR114_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR113_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR112_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR111_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR110_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR19_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR18_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR17_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR16_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR15_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR14_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR13_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR12_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR11_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR10_EL0	|
+		   HAFGRTR_EL2_AMCNTEN1		|
+		   HAFGRTR_EL2_AMCNTEN0		|
+		   HAFGRTR_EL2_AMEVCNTR03_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR02_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR01_EL0	|
+		   HAFGRTR_EL2_AMEVCNTR00_EL0,
+		   FEAT_AMUv1),
+};
+
+static bool idreg_feat_match(struct kvm *kvm, struct reg_bits_to_feat_map *map)
+{
+	u64 regval = kvm->arch.id_regs[map->regidx];
+	u64 regfld = (regval >> map->shift) & GENMASK(map->width - 1, 0);
+
+	if (map->sign) {
+		s64 sfld = sign_extend64(regfld, map->width - 1);
+		s64 slim = sign_extend64(map->lo_lim, map->width - 1);
+		return sfld >= slim;
+	} else {
+		return regfld >= map->lo_lim;
+	}
+}
+
+static u64 __compute_fixed_bits(struct kvm *kvm,
+				struct reg_bits_to_feat_map *map,
+				int map_size,
+				u64 *fixed_bits,
+				unsigned long require,
+				unsigned long exclude)
+{
+	u64 val = 0;
+
+	for (int i = 0; i < map_size; i++) {
+		bool match;
+
+		if ((map[i].flags & require) != require)
+			continue;
+
+		if (map[i].flags & exclude)
+			continue;
+
+		if (map[i].flags & CALL_FUNC)
+			match = (map[i].flags & FIXED_VALUE) ?
+				map[i].fval(kvm, fixed_bits) :
+				map[i].match(kvm);
+		else
+			match = idreg_feat_match(kvm, &map[i]);
+
+		if (!match || (map[i].flags & FIXED_VALUE))
+			val |= map[i].bits;
+	}
+
+	return val;
+}
+
+static u64 compute_res0_bits(struct kvm *kvm,
+			     struct reg_bits_to_feat_map *map,
+			     int map_size,
+			     unsigned long require,
+			     unsigned long exclude)
+{
+	return __compute_fixed_bits(kvm, map, map_size, NULL,
+				    require, exclude | FIXED_VALUE);
+}
+
+void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
+{
+	u64 val = 0;
+
+	switch (fgt) {
+	case HFGxTR_GROUP:
+		val |= compute_res0_bits(kvm, hfgrtr_feat_map,
+					 ARRAY_SIZE(hfgrtr_feat_map),
+					 0, NEVER_FGU);
+		val |= compute_res0_bits(kvm, hfgwtr_feat_map,
+					 ARRAY_SIZE(hfgwtr_feat_map),
+					 0, NEVER_FGU);
+		break;
+	case HFGITR_GROUP:
+		val |= compute_res0_bits(kvm, hfgitr_feat_map,
+					 ARRAY_SIZE(hfgitr_feat_map),
+					 0, NEVER_FGU);
+		break;
+	case HDFGRTR_GROUP:
+		val |= compute_res0_bits(kvm, hdfgrtr_feat_map,
+					 ARRAY_SIZE(hdfgrtr_feat_map),
+					 0, NEVER_FGU);
+		val |= compute_res0_bits(kvm, hdfgwtr_feat_map,
+					 ARRAY_SIZE(hdfgwtr_feat_map),
+					 0, NEVER_FGU);
+		break;
+	case HAFGRTR_GROUP:
+		val |= compute_res0_bits(kvm, hafgrtr_feat_map,
+					 ARRAY_SIZE(hafgrtr_feat_map),
+					 0, NEVER_FGU);
+		break;
+	default:
+		BUG();
+	}
+
+	kvm->arch.fgu[fgt] = val;
+}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 2ecd0d51a2dae..d3990ceaa59c2 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -4994,75 +4994,10 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
 	if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
 		goto out;
 
-	kvm->arch.fgu[HFGxTR_GROUP] = (HFGxTR_EL2_nAMAIR2_EL1		|
-				       HFGxTR_EL2_nMAIR2_EL1		|
-				       HFGxTR_EL2_nS2POR_EL1		|
-				       HFGxTR_EL2_nSMPRI_EL1_MASK	|
-				       HFGxTR_EL2_nTPIDR2_EL0_MASK);
-
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
-		kvm->arch.fgu[HFGxTR_GROUP] |= HFGxTR_EL2_nACCDATA_EL1;
-
-	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
-		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_TLBIRVAALE1OS|
-						HFGITR_EL2_TLBIRVALE1OS	|
-						HFGITR_EL2_TLBIRVAAE1OS	|
-						HFGITR_EL2_TLBIRVAE1OS	|
-						HFGITR_EL2_TLBIVAALE1OS	|
-						HFGITR_EL2_TLBIVALE1OS	|
-						HFGITR_EL2_TLBIVAAE1OS	|
-						HFGITR_EL2_TLBIASIDE1OS	|
-						HFGITR_EL2_TLBIVAE1OS	|
-						HFGITR_EL2_TLBIVMALLE1OS);
-
-	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
-		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_TLBIRVAALE1	|
-						HFGITR_EL2_TLBIRVALE1	|
-						HFGITR_EL2_TLBIRVAAE1	|
-						HFGITR_EL2_TLBIRVAE1	|
-						HFGITR_EL2_TLBIRVAALE1IS|
-						HFGITR_EL2_TLBIRVALE1IS	|
-						HFGITR_EL2_TLBIRVAAE1IS	|
-						HFGITR_EL2_TLBIRVAE1IS	|
-						HFGITR_EL2_TLBIRVAALE1OS|
-						HFGITR_EL2_TLBIRVALE1OS	|
-						HFGITR_EL2_TLBIRVAAE1OS	|
-						HFGITR_EL2_TLBIRVAE1OS);
-
-	if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, ATS1A, IMP))
-		kvm->arch.fgu[HFGITR_GROUP] |= HFGITR_EL2_ATS1E1A;
-
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN2))
-		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_ATS1E1RP |
-						HFGITR_EL2_ATS1E1WP);
-
-	if (!kvm_has_s1pie(kvm))
-		kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 |
-						HFGxTR_EL2_nPIR_EL1);
-
-	if (!kvm_has_s1poe(kvm))
-		kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPOR_EL1 |
-						HFGxTR_EL2_nPOR_EL0);
-
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP))
-		kvm->arch.fgu[HAFGRTR_GROUP] |= ~(HAFGRTR_EL2_RES0 |
-						  HAFGRTR_EL2_RES1);
-
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP)) {
-		kvm->arch.fgu[HDFGRTR_GROUP] |= (HDFGRTR_EL2_nBRBDATA  |
-						 HDFGRTR_EL2_nBRBCTL   |
-						 HDFGRTR_EL2_nBRBIDR);
-		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_nBRBINJ |
-						HFGITR_EL2_nBRBIALL);
-	}
-
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP)) {
-		kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nGCS_EL0 |
-						HFGxTR_EL2_nGCS_EL1);
-		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_nGCSPUSHM_EL1 |
-						HFGITR_EL2_nGCSSTR_EL1 |
-						HFGITR_EL2_nGCSEPP);
-	}
+	compute_fgu(kvm, HFGxTR_GROUP);
+	compute_fgu(kvm, HFGITR_GROUP);
+	compute_fgu(kvm, HDFGRTR_GROUP);
+	compute_fgu(kvm, HAFGRTR_GROUP);
 
 	set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags);
 out:
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:05 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:05 +0000
Subject: [PATCH v2 23/23] KVM: arm64: Use HCR_EL2 feature map to drive fixed-value bits
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-24-maz@kernel.org>

Similarly to other registers, describe which HCR_EL2 bit depends
on which feature, and use this to compute the RES0 status of these
bits.

An additional complexity stems from the status of some bits such
as E2H and RW, which do not had a RESx status, but still take
a fixed value due to implementation choices in KVM.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/config.c | 149 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/nested.c |  35 +---------
 2 files changed, 150 insertions(+), 34 deletions(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 15ec8bdc57055..120464c6dee1c 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -69,7 +69,10 @@ struct reg_bits_to_feat_map {
 #define FEAT_TRBE		ID_AA64DFR0_EL1, TraceBuffer, IMP
 #define FEAT_DoubleLock		ID_AA64DFR0_EL1, DoubleLock, IMP
 #define FEAT_TRF		ID_AA64DFR0_EL1, TraceFilt, IMP
+#define FEAT_AA32EL0		ID_AA64PFR0_EL1, EL0, AARCH32
+#define FEAT_AA32EL1		ID_AA64PFR0_EL1, EL1, AARCH32
 #define FEAT_AA64EL1		ID_AA64PFR0_EL1, EL1, IMP
+#define FEAT_AA64EL3		ID_AA64PFR0_EL1, EL3, IMP
 #define FEAT_AIE		ID_AA64MMFR3_EL1, AIE, IMP
 #define FEAT_S2POE		ID_AA64MMFR3_EL1, S2POE, IMP
 #define FEAT_S1POE		ID_AA64MMFR3_EL1, S1POE, IMP
@@ -92,6 +95,7 @@ struct reg_bits_to_feat_map {
 #define FEAT_PAN2		ID_AA64MMFR1_EL1, PAN, PAN2
 #define FEAT_DPB2		ID_AA64ISAR1_EL1, DPB, DPB2
 #define FEAT_AMUv1		ID_AA64PFR0_EL1, AMU, IMP
+#define FEAT_AMUv1p1		ID_AA64PFR0_EL1, AMU, V1P1
 #define FEAT_CMOW		ID_AA64MMFR1_EL1, CMOW, IMP
 #define FEAT_D128		ID_AA64MMFR3_EL1, D128, IMP
 #define FEAT_DoubleFault2	ID_AA64PFR1_EL1, DF2, IMP
@@ -102,6 +106,31 @@ struct reg_bits_to_feat_map {
 #define FEAT_SYSREG128		ID_AA64ISAR2_EL1, SYSREG_128, IMP
 #define FEAT_TCR2		ID_AA64MMFR3_EL1, TCRX, IMP
 #define FEAT_XS			ID_AA64ISAR1_EL1, XS, IMP
+#define FEAT_EVT		ID_AA64MMFR2_EL1, EVT, IMP
+#define FEAT_EVT_TTLBxS		ID_AA64MMFR2_EL1, EVT, TTLBxS
+#define FEAT_MTE2		ID_AA64PFR1_EL1, MTE, MTE2
+#define FEAT_RME		ID_AA64PFR0_EL1, RME, IMP
+#define FEAT_S2FWB		ID_AA64MMFR2_EL1, FWB, IMP
+#define FEAT_TME		ID_AA64ISAR0_EL1, TME, IMP
+#define FEAT_TWED		ID_AA64MMFR1_EL1, TWED, IMP
+#define FEAT_E2H0		ID_AA64MMFR4_EL1, E2H0, IMP
+
+static bool not_feat_aa64el3(struct kvm *kvm)
+{
+	return !kvm_has_feat(kvm, FEAT_AA64EL3);
+}
+
+static bool feat_nv2(struct kvm *kvm)
+{
+	return ((kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY) &&
+		 kvm_has_feat_enum(kvm, ID_AA64MMFR2_EL1, NV, NI)) ||
+		kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, NV2));
+}
+
+static bool feat_nv2_e2h0_ni(struct kvm *kvm)
+{
+	return feat_nv2(kvm) && !kvm_has_feat(kvm, FEAT_E2H0);
+}
 
 static bool feat_rasv1p1(struct kvm *kvm)
 {
@@ -151,6 +180,31 @@ static bool feat_sme_smps(struct kvm *kvm)
 		(read_sysreg_s(SYS_SMIDR_EL1) & SMIDR_EL1_SMPS));
 }
 
+static bool compute_hcr_rw(struct kvm *kvm, u64 *bits)
+{
+	/* This is purely academic: AArch32 and NV are mutually exclusive */
+	if (bits) {
+		if (kvm_has_feat(kvm, FEAT_AA32EL1))
+			*bits &= ~HCR_EL2_RW;
+		else
+			*bits |= HCR_EL2_RW;
+	}
+
+	return true;
+}
+
+static bool compute_hcr_e2h(struct kvm *kvm, u64 *bits)
+{
+	if (bits) {
+		if (kvm_has_feat(kvm, FEAT_E2H0))
+			*bits &= ~HCR_EL2_E2H;
+		else
+			*bits |= HCR_EL2_E2H;
+	}
+
+	return true;
+}
+
 static struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
 	NEEDS_FEAT(HFGxTR_EL2_nAMAIR2_EL1	|
 		   HFGxTR_EL2_nMAIR2_EL1,
@@ -564,6 +618,77 @@ static struct reg_bits_to_feat_map hcrx_feat_map[] = {
 	NEEDS_FEAT(HCRX_EL2_EnAS0, FEAT_LS64_ACCDATA),
 };
 
+static struct reg_bits_to_feat_map hcr_feat_map[] = {
+	NEEDS_FEAT(HCR_EL2_TID0, FEAT_AA32EL0),
+	NEEDS_FEAT_FIXED(HCR_EL2_RW, compute_hcr_rw),
+	NEEDS_FEAT(HCR_EL2_HCD, not_feat_aa64el3),
+	NEEDS_FEAT(HCR_EL2_AMO		|
+		   HCR_EL2_BSU		|
+		   HCR_EL2_CD		|
+		   HCR_EL2_DC		|
+		   HCR_EL2_FB		|
+		   HCR_EL2_FMO		|
+		   HCR_EL2_ID		|
+		   HCR_EL2_IMO		|
+		   HCR_EL2_MIOCNCE	|
+		   HCR_EL2_PTW		|
+		   HCR_EL2_SWIO		|
+		   HCR_EL2_TACR		|
+		   HCR_EL2_TDZ		|
+		   HCR_EL2_TGE		|
+		   HCR_EL2_TID1		|
+		   HCR_EL2_TID2		|
+		   HCR_EL2_TID3		|
+		   HCR_EL2_TIDCP	|
+		   HCR_EL2_TPCP		|
+		   HCR_EL2_TPU		|
+		   HCR_EL2_TRVM		|
+		   HCR_EL2_TSC		|
+		   HCR_EL2_TSW		|
+		   HCR_EL2_TTLB		|
+		   HCR_EL2_TVM		|
+		   HCR_EL2_TWE		|
+		   HCR_EL2_TWI		|
+		   HCR_EL2_VF		|
+		   HCR_EL2_VI		|
+		   HCR_EL2_VM		|
+		   HCR_EL2_VSE,
+		   FEAT_AA64EL1),
+	NEEDS_FEAT(HCR_EL2_AMVOFFEN, FEAT_AMUv1p1),
+	NEEDS_FEAT(HCR_EL2_EnSCXT, feat_csv2_2_csv2_1p2),
+	NEEDS_FEAT(HCR_EL2_TICAB	|
+		   HCR_EL2_TID4		|
+		   HCR_EL2_TOCU,
+		   FEAT_EVT),
+	NEEDS_FEAT(HCR_EL2_TTLBIS	|
+		   HCR_EL2_TTLBOS,
+		   FEAT_EVT_TTLBxS),
+	NEEDS_FEAT(HCR_EL2_TLOR, FEAT_LOR),
+	NEEDS_FEAT(HCR_EL2_ATA		|
+		   HCR_EL2_DCT		|
+		   HCR_EL2_TID5,
+		   FEAT_MTE2),
+	NEEDS_FEAT(HCR_EL2_AT		| /* Ignore the original FEAT_NV */
+		   HCR_EL2_NV2		|
+		   HCR_EL2_NV,
+		   feat_nv2),
+	NEEDS_FEAT(HCR_EL2_NV1, feat_nv2_e2h0_ni), /* Missing from JSON */
+	NEEDS_FEAT(HCR_EL2_API		|
+		   HCR_EL2_APK,
+		   feat_pauth),
+	NEEDS_FEAT(HCR_EL2_TEA		|
+		   HCR_EL2_TERR,
+		   FEAT_RAS),
+	NEEDS_FEAT(HCR_EL2_FIEN, feat_rasv1p1),
+	NEEDS_FEAT(HCR_EL2_GPF, FEAT_RME),
+	NEEDS_FEAT(HCR_EL2_FWB, FEAT_S2FWB),
+	NEEDS_FEAT(HCR_EL2_TME, FEAT_TME),
+	NEEDS_FEAT(HCR_EL2_TWEDEL	|
+		   HCR_EL2_TWEDEn,
+		   FEAT_TWED),
+	NEEDS_FEAT_FIXED(HCR_EL2_E2H, compute_hcr_e2h),
+};
+
 static void __init check_feat_map(struct reg_bits_to_feat_map *map,
 				  int map_size, u64 res0, const char *str)
 {
@@ -593,6 +718,8 @@ void __init check_feature_map(void)
 		       hafgrtr_masks.res0, hafgrtr_masks.str);
 	check_feat_map(hcrx_feat_map, ARRAY_SIZE(hcrx_feat_map),
 		       __HCRX_EL2_RES0, "HCRX_EL2");
+	check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
+		       HCR_EL2_RES0, "HCR_EL2");
 }
 
 static bool idreg_feat_match(struct kvm *kvm, struct reg_bits_to_feat_map *map)
@@ -651,6 +778,17 @@ static u64 compute_res0_bits(struct kvm *kvm,
 				    require, exclude | FIXED_VALUE);
 }
 
+static u64 compute_fixed_bits(struct kvm *kvm,
+			      struct reg_bits_to_feat_map *map,
+			      int map_size,
+			      u64 *fixed_bits,
+			      unsigned long require,
+			      unsigned long exclude)
+{
+	return __compute_fixed_bits(kvm, map, map_size, fixed_bits,
+				    require | FIXED_VALUE, exclude);
+}
+
 void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
 {
 	u64 val = 0;
@@ -691,6 +829,8 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
 
 void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *res1)
 {
+	u64 fixed = 0, mask;
+
 	switch (reg) {
 	case HFGRTR_EL2:
 		*res0 = compute_res0_bits(kvm, hfgrtr_feat_map,
@@ -734,6 +874,15 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
 		*res0 |= __HCRX_EL2_RES0;
 		*res1 = __HCRX_EL2_RES1;
 		break;
+	case HCR_EL2:
+		mask = compute_fixed_bits(kvm, hcr_feat_map,
+					  ARRAY_SIZE(hcr_feat_map), &fixed,
+					  0, 0);
+		*res0 = compute_res0_bits(kvm, hcr_feat_map,
+					  ARRAY_SIZE(hcr_feat_map), 0, 0);
+		*res0 |= HCR_EL2_RES0 | (mask & ~fixed);
+		*res1 = HCR_EL2_RES1 | (mask & fixed);
+		break;
 	default:
 		WARN_ON_ONCE(1);
 		*res0 = *res1 = 0;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 984940781a4cf..07fa8c3f89df7 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1002,40 +1002,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	set_sysreg_masks(kvm, VMPIDR_EL2, res0, res1);
 
 	/* HCR_EL2 */
-	res0 = BIT(48);
-	res1 = HCR_RW;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, TWED, IMP))
-		res0 |= GENMASK(63, 59);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, MTE, MTE2))
-		res0 |= (HCR_TID5 | HCR_DCT | HCR_ATA);
-	if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, EVT, TTLBxS))
-		res0 |= (HCR_TTLBIS | HCR_TTLBOS);
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, CSV2, CSV2_2) &&
-	    !kvm_has_feat(kvm, ID_AA64PFR1_EL1, CSV2_frac, CSV2_1p2))
-		res0 |= HCR_ENSCXT;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, EVT, IMP))
-		res0 |= (HCR_TOCU | HCR_TICAB | HCR_TID4);
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
-		res0 |= HCR_AMVOFFEN;
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, V1P1))
-		res0 |= HCR_FIEN;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, FWB, IMP))
-		res0 |= HCR_FWB;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, NV2))
-		res0 |= HCR_NV2;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, NV, IMP))
-		res0 |= (HCR_AT | HCR_NV1 | HCR_NV);
-	if (!(kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_ADDRESS) &&
-	      kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC)))
-		res0 |= (HCR_API | HCR_APK);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TME, IMP))
-		res0 |= BIT(39);
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP))
-		res0 |= (HCR_TEA | HCR_TERR);
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
-		res0 |= HCR_TLOR;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
-		res1 |= HCR_E2H;
+	get_reg_fixed_bits(kvm, HCR_EL2, &res0, &res1);
 	set_sysreg_masks(kvm, HCR_EL2, res0, res1);
 
 	/* HCRX_EL2 */
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:02 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:02 +0000
Subject: [PATCH v2 20/23] KVM: arm64: Use FGT feature maps to drive RES0 bits
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-21-maz@kernel.org>

Another benefit of mapping bits to features is that it becomes trivial
to define which bits should be handled as RES0.

Let's apply this principle to the guest's view of the FGT registers.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |   1 +
 arch/arm64/kvm/config.c           |  46 +++++++++++
 arch/arm64/kvm/nested.c           | 129 +++---------------------------
 3 files changed, 57 insertions(+), 119 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index c98f7eed68142..9bac3c6800294 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1565,6 +1565,7 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 	(kvm_has_feat((k), ID_AA64MMFR3_EL1, S1POE, IMP))
 
 void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt);
+void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64*res1);
 void check_feature_map(void);
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index d39f1f14e3dc4..f88783bd9a2f1 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -616,3 +616,49 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
 
 	kvm->arch.fgu[fgt] = val;
 }
+
+void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *res1)
+{
+	switch (reg) {
+	case HFGRTR_EL2:
+		*res0 = compute_res0_bits(kvm, hfgrtr_feat_map,
+					  ARRAY_SIZE(hfgrtr_feat_map), 0, 0);
+		*res0 |= hfgrtr_masks.res0;
+		*res1 = HFGxTR_EL2_RES1;
+		break;
+	case HFGWTR_EL2:
+		*res0 = compute_res0_bits(kvm, hfgwtr_feat_map,
+					  ARRAY_SIZE(hfgwtr_feat_map), 0, 0);
+		*res0 |= hfgwtr_masks.res0;
+		*res1 = HFGxTR_EL2_RES1;
+		break;
+	case HFGITR_EL2:
+		*res0 = compute_res0_bits(kvm, hfgitr_feat_map,
+					  ARRAY_SIZE(hfgitr_feat_map), 0, 0);
+		*res0 |= hfgitr_masks.res0;
+		*res1 = HFGITR_EL2_RES1;
+		break;
+	case HDFGRTR_EL2:
+		*res0 = compute_res0_bits(kvm, hdfgrtr_feat_map,
+					  ARRAY_SIZE(hdfgrtr_feat_map), 0, 0);
+		*res0 |= hdfgrtr_masks.res0;
+		*res1 = HDFGRTR_EL2_RES1;
+		break;
+	case HDFGWTR_EL2:
+		*res0 = compute_res0_bits(kvm, hdfgwtr_feat_map,
+					  ARRAY_SIZE(hdfgwtr_feat_map), 0, 0);
+		*res0 |= hdfgwtr_masks.res0;
+		*res1 = HDFGWTR_EL2_RES1;
+		break;
+	case HAFGRTR_EL2:
+		*res0 = compute_res0_bits(kvm, hafgrtr_feat_map,
+					  ARRAY_SIZE(hafgrtr_feat_map), 0, 0);
+		*res0 |= hafgrtr_masks.res0;
+		*res1 = HAFGRTR_EL2_RES1;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		*res0 = *res1 = 0;
+		break;
+	}
+}
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 48b8a700de457..74df066f9ab3f 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1081,132 +1081,23 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	set_sysreg_masks(kvm, HCRX_EL2, res0, res1);
 
 	/* HFG[RW]TR_EL2 */
-	res0 = res1 = 0;
-	if (!(kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_ADDRESS) &&
-	      kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC)))
-		res0 |= (HFGxTR_EL2_APDAKey | HFGxTR_EL2_APDBKey |
-			 HFGxTR_EL2_APGAKey | HFGxTR_EL2_APIAKey |
-			 HFGxTR_EL2_APIBKey);
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
-		res0 |= (HFGxTR_EL2_LORC_EL1 | HFGxTR_EL2_LOREA_EL1 |
-			 HFGxTR_EL2_LORID_EL1 | HFGxTR_EL2_LORN_EL1 |
-			 HFGxTR_EL2_LORSA_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, CSV2, CSV2_2) &&
-	    !kvm_has_feat(kvm, ID_AA64PFR1_EL1, CSV2_frac, CSV2_1p2))
-		res0 |= (HFGxTR_EL2_SCXTNUM_EL1 | HFGxTR_EL2_SCXTNUM_EL0);
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP))
-		res0 |= HFGxTR_EL2_ICC_IGRPENn_EL1;
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP))
-		res0 |= (HFGxTR_EL2_ERRIDR_EL1 | HFGxTR_EL2_ERRSELR_EL1 |
-			 HFGxTR_EL2_ERXFR_EL1 | HFGxTR_EL2_ERXCTLR_EL1 |
-			 HFGxTR_EL2_ERXSTATUS_EL1 | HFGxTR_EL2_ERXMISCn_EL1 |
-			 HFGxTR_EL2_ERXPFGF_EL1 | HFGxTR_EL2_ERXPFGCTL_EL1 |
-			 HFGxTR_EL2_ERXPFGCDN_EL1 | HFGxTR_EL2_ERXADDR_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
-		res0 |= HFGxTR_EL2_nACCDATA_EL1;
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
-		res0 |= (HFGxTR_EL2_nGCS_EL0 | HFGxTR_EL2_nGCS_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP))
-		res0 |= (HFGxTR_EL2_nSMPRI_EL1 | HFGxTR_EL2_nTPIDR2_EL0);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
-		res0 |= HFGxTR_EL2_nRCWMASK_EL1;
-	if (!kvm_has_s1pie(kvm))
-		res0 |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1);
-	if (!kvm_has_s1poe(kvm))
-		res0 |= (HFGxTR_EL2_nPOR_EL0 | HFGxTR_EL2_nPOR_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S2POE, IMP))
-		res0 |= HFGxTR_EL2_nS2POR_EL1;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, AIE, IMP))
-		res0 |= (HFGxTR_EL2_nMAIR2_EL1 | HFGxTR_EL2_nAMAIR2_EL1);
-	set_sysreg_masks(kvm, HFGRTR_EL2, res0 | hfgrtr_masks.res0, res1);
-	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | hfgwtr_masks.res0, res1);
+	get_reg_fixed_bits(kvm, HFGRTR_EL2, &res0, &res1);
+	set_sysreg_masks(kvm, HFGRTR_EL2, res0, res1);
+	get_reg_fixed_bits(kvm, HFGWTR_EL2, &res0, &res1);
+	set_sysreg_masks(kvm, HFGWTR_EL2, res0, res1);
 
 	/* HDFG[RW]TR_EL2 */
-	res0 = res1 = 0;
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, DoubleLock, IMP))
-		res0 |= HDFGRTR_EL2_OSDLR_EL1;
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
-		res0 |= (HDFGRTR_EL2_PMEVCNTRn_EL0 | HDFGRTR_EL2_PMEVTYPERn_EL0 |
-			 HDFGRTR_EL2_PMCCFILTR_EL0 | HDFGRTR_EL2_PMCCNTR_EL0 |
-			 HDFGRTR_EL2_PMCNTEN | HDFGRTR_EL2_PMINTEN |
-			 HDFGRTR_EL2_PMOVS | HDFGRTR_EL2_PMSELR_EL0 |
-			 HDFGRTR_EL2_PMMIR_EL1 | HDFGRTR_EL2_PMUSERENR_EL0 |
-			 HDFGRTR_EL2_PMCEIDn_EL0);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, IMP))
-		res0 |= (HDFGRTR_EL2_PMBLIMITR_EL1 | HDFGRTR_EL2_PMBPTR_EL1 |
-			 HDFGRTR_EL2_PMBSR_EL1 | HDFGRTR_EL2_PMSCR_EL1 |
-			 HDFGRTR_EL2_PMSEVFR_EL1 | HDFGRTR_EL2_PMSFCR_EL1 |
-			 HDFGRTR_EL2_PMSICR_EL1 | HDFGRTR_EL2_PMSIDR_EL1 |
-			 HDFGRTR_EL2_PMSIRR_EL1 | HDFGRTR_EL2_PMSLATFR_EL1 |
-			 HDFGRTR_EL2_PMBIDR_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceVer, IMP))
-		res0 |= (HDFGRTR_EL2_TRC | HDFGRTR_EL2_TRCAUTHSTATUS |
-			 HDFGRTR_EL2_TRCAUXCTLR | HDFGRTR_EL2_TRCCLAIM |
-			 HDFGRTR_EL2_TRCCNTVRn | HDFGRTR_EL2_TRCID |
-			 HDFGRTR_EL2_TRCIMSPECn | HDFGRTR_EL2_TRCOSLSR |
-			 HDFGRTR_EL2_TRCPRGCTLR | HDFGRTR_EL2_TRCSEQSTR |
-			 HDFGRTR_EL2_TRCSSCSRn | HDFGRTR_EL2_TRCSTATR |
-			 HDFGRTR_EL2_TRCVICTLR);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceBuffer, IMP))
-		res0 |= (HDFGRTR_EL2_TRBBASER_EL1 | HDFGRTR_EL2_TRBIDR_EL1 |
-			 HDFGRTR_EL2_TRBLIMITR_EL1 | HDFGRTR_EL2_TRBMAR_EL1 |
-			 HDFGRTR_EL2_TRBPTR_EL1 | HDFGRTR_EL2_TRBSR_EL1 |
-			 HDFGRTR_EL2_TRBTRG_EL1);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP))
-		res0 |= (HDFGRTR_EL2_nBRBIDR | HDFGRTR_EL2_nBRBCTL |
-			 HDFGRTR_EL2_nBRBDATA);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P2))
-		res0 |= HDFGRTR_EL2_nPMSNEVFR_EL1;
-	set_sysreg_masks(kvm, HDFGRTR_EL2, res0 | hdfgrtr_masks.res0, res1);
-
-	/* Reuse the bits from the read-side and add the write-specific stuff */
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
-		res0 |= (HDFGWTR_EL2_PMCR_EL0 | HDFGWTR_EL2_PMSWINC_EL0);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceVer, IMP))
-		res0 |= HDFGWTR_EL2_TRCOSLAR;
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceFilt, IMP))
-		res0 |= HDFGWTR_EL2_TRFCR_EL1;
-	set_sysreg_masks(kvm, HFGWTR_EL2, res0 | hdfgwtr_masks.res0, res1);
+	get_reg_fixed_bits(kvm, HDFGRTR_EL2, &res0, &res1);
+	set_sysreg_masks(kvm, HDFGRTR_EL2, res0, res1);
+	get_reg_fixed_bits(kvm, HDFGWTR_EL2, &res0, &res1);
+	set_sysreg_masks(kvm, HDFGWTR_EL2, res0, res1);
 
 	/* HFGITR_EL2 */
-	res0 = hfgitr_masks.res0;
-	res1 = HFGITR_EL2_RES1;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, DPB, DPB2))
-		res0 |= HFGITR_EL2_DCCVADP;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN2))
-		res0 |= (HFGITR_EL2_ATS1E1RP | HFGITR_EL2_ATS1E1WP);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
-		res0 |= (HFGITR_EL2_TLBIRVAALE1OS | HFGITR_EL2_TLBIRVALE1OS |
-			 HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS |
-			 HFGITR_EL2_TLBIVAALE1OS | HFGITR_EL2_TLBIVALE1OS |
-			 HFGITR_EL2_TLBIVAAE1OS | HFGITR_EL2_TLBIASIDE1OS |
-			 HFGITR_EL2_TLBIVAE1OS | HFGITR_EL2_TLBIVMALLE1OS);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
-		res0 |= (HFGITR_EL2_TLBIRVAALE1 | HFGITR_EL2_TLBIRVALE1 |
-			 HFGITR_EL2_TLBIRVAAE1 | HFGITR_EL2_TLBIRVAE1 |
-			 HFGITR_EL2_TLBIRVAALE1IS | HFGITR_EL2_TLBIRVALE1IS |
-			 HFGITR_EL2_TLBIRVAAE1IS | HFGITR_EL2_TLBIRVAE1IS |
-			 HFGITR_EL2_TLBIRVAALE1OS | HFGITR_EL2_TLBIRVALE1OS |
-			 HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, SPECRES, IMP))
-		res0 |= (HFGITR_EL2_CFPRCTX | HFGITR_EL2_DVPRCTX |
-			 HFGITR_EL2_CPPRCTX);
-	if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP))
-		res0 |= (HFGITR_EL2_nBRBINJ | HFGITR_EL2_nBRBIALL);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
-		res0 |= (HFGITR_EL2_nGCSPUSHM_EL1 | HFGITR_EL2_nGCSSTR_EL1 |
-			 HFGITR_EL2_nGCSEPP);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, SPECRES, COSP_RCTX))
-		res0 |= HFGITR_EL2_COSPRCTX;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, ATS1A, IMP))
-		res0 |= HFGITR_EL2_ATS1E1A;
+	get_reg_fixed_bits(kvm, HFGITR_EL2, &res0, &res1);
 	set_sysreg_masks(kvm, HFGITR_EL2, res0, res1);
 
 	/* HAFGRTR_EL2 - not a lot to see here */
-	res0 = hafgrtr_masks.res0;
-	res1 = HAFGRTR_EL2_RES1;
-	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
-		res0 |= ~(res0 | res1);
+	get_reg_fixed_bits(kvm, HAFGRTR_EL2, &res0, &res1);
 	set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
 
 	/* TCR2_EL2 */
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:03 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:03 +0000
Subject: [PATCH v2 21/23] KVM: arm64: Allow kvm_has_feat() to take variable arguments
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-22-maz@kernel.org>

In order to be able to write more compact (and easier to read) code,
let kvm_has_feat() and co take variable arguments. This enables
constructs such as:

	#define FEAT_SME	ID_AA64PFR1_EL1, SME, IMP

	if (kvm_has_feat(kvm, FEAT_SME))
		[...]

which is admitedly more readable.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9bac3c6800294..89f8415fea063 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1526,12 +1526,16 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 	 kvm_cmp_feat_signed(kvm, id, fld, op, limit) :			\
 	 kvm_cmp_feat_unsigned(kvm, id, fld, op, limit))
 
-#define kvm_has_feat(kvm, id, fld, limit)				\
+#define __kvm_has_feat(kvm, id, fld, limit)				\
 	kvm_cmp_feat(kvm, id, fld, >=, limit)
 
-#define kvm_has_feat_enum(kvm, id, fld, val)				\
+#define kvm_has_feat(kvm, ...) __kvm_has_feat(kvm, __VA_ARGS__)
+
+#define __kvm_has_feat_enum(kvm, id, fld, val)				\
 	kvm_cmp_feat_unsigned(kvm, id, fld, ==, val)
 
+#define kvm_has_feat_enum(kvm, ...) __kvm_has_feat_enum(kvm, __VA_ARGS__)
+
 #define kvm_has_feat_range(kvm, id, fld, min, max)			\
 	(kvm_cmp_feat(kvm, id, fld, >=, min) &&				\
 	kvm_cmp_feat(kvm, id, fld, <=, max))
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:25:04 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:25:04 +0000
Subject: [PATCH v2 22/23] KVM: arm64: Use HCRX_EL2 feature map to drive fixed-value bits
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-23-maz@kernel.org>

Similarly to other registers, describe which HCR_EL2 bit depends
on which feature, and use this to compute the RES0 status of these
bits.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/config.c | 78 +++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/nested.c | 40 +--------------------
 2 files changed, 79 insertions(+), 39 deletions(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index f88783bd9a2f1..15ec8bdc57055 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -77,6 +77,8 @@ struct reg_bits_to_feat_map {
 #define FEAT_THE		ID_AA64PFR1_EL1, THE, IMP
 #define FEAT_SME		ID_AA64PFR1_EL1, SME, IMP
 #define FEAT_GCS		ID_AA64PFR1_EL1, GCS, IMP
+#define FEAT_LS64		ID_AA64ISAR1_EL1, LS64, LS64
+#define FEAT_LS64_V		ID_AA64ISAR1_EL1, LS64, LS64_V
 #define FEAT_LS64_ACCDATA	ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA
 #define FEAT_RAS		ID_AA64PFR0_EL1, RAS, IMP
 #define FEAT_GICv3		ID_AA64PFR0_EL1, GIC, IMP
@@ -90,6 +92,16 @@ struct reg_bits_to_feat_map {
 #define FEAT_PAN2		ID_AA64MMFR1_EL1, PAN, PAN2
 #define FEAT_DPB2		ID_AA64ISAR1_EL1, DPB, DPB2
 #define FEAT_AMUv1		ID_AA64PFR0_EL1, AMU, IMP
+#define FEAT_CMOW		ID_AA64MMFR1_EL1, CMOW, IMP
+#define FEAT_D128		ID_AA64MMFR3_EL1, D128, IMP
+#define FEAT_DoubleFault2	ID_AA64PFR1_EL1, DF2, IMP
+#define FEAT_FPMR		ID_AA64PFR2_EL1, FPMR, IMP
+#define FEAT_MOPS		ID_AA64ISAR2_EL1, MOPS, IMP
+#define FEAT_NMI		ID_AA64PFR1_EL1, NMI, IMP
+#define FEAT_SCTLR2		ID_AA64MMFR3_EL1, SCTLRX, IMP
+#define FEAT_SYSREG128		ID_AA64ISAR2_EL1, SYSREG_128, IMP
+#define FEAT_TCR2		ID_AA64MMFR3_EL1, TCRX, IMP
+#define FEAT_XS			ID_AA64ISAR1_EL1, XS, IMP
 
 static bool feat_rasv1p1(struct kvm *kvm)
 {
@@ -110,6 +122,35 @@ static bool feat_pauth(struct kvm *kvm)
 	return kvm_has_pauth(kvm, PAuth);
 }
 
+static bool feat_pauth_lr(struct kvm *kvm)
+{
+	return kvm_has_pauth(kvm, PAuth_LR);
+}
+
+static bool feat_aderr(struct kvm *kvm)
+{
+	return (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, ADERR, FEAT_ADERR) &&
+		kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SDERR, FEAT_ADERR));
+}
+
+static bool feat_anerr(struct kvm *kvm)
+{
+	return (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, ANERR, FEAT_ANERR) &&
+		kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SNERR, FEAT_ANERR));
+}
+
+static bool feat_sme_smps(struct kvm *kvm)
+{
+	/*
+	 * Revists this if KVM ever supports SME -- this really should
+	 * look at the guest's view of SMIDR_EL1. Funnily enough, this
+	 * is not captured in the JSON file, but only as a note in the
+	 * ARM ARM.
+	 */
+	return (kvm_has_feat(kvm, FEAT_SME) &&
+		(read_sysreg_s(SYS_SMIDR_EL1) & SMIDR_EL1_SMPS));
+}
+
 static struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
 	NEEDS_FEAT(HFGxTR_EL2_nAMAIR2_EL1	|
 		   HFGxTR_EL2_nMAIR2_EL1,
@@ -494,6 +535,35 @@ static struct reg_bits_to_feat_map hafgrtr_feat_map[] = {
 		   FEAT_AMUv1),
 };
 
+static struct reg_bits_to_feat_map hcrx_feat_map[] = {
+	NEEDS_FEAT(HCRX_EL2_PACMEn, feat_pauth_lr),
+	NEEDS_FEAT(HCRX_EL2_EnFPM, FEAT_FPMR),
+	NEEDS_FEAT(HCRX_EL2_GCSEn, FEAT_GCS),
+	NEEDS_FEAT(HCRX_EL2_EnIDCP128, FEAT_SYSREG128),
+	NEEDS_FEAT(HCRX_EL2_EnSDERR, feat_aderr),
+	NEEDS_FEAT(HCRX_EL2_TMEA, FEAT_DoubleFault2),
+	NEEDS_FEAT(HCRX_EL2_EnSNERR, feat_anerr),
+	NEEDS_FEAT(HCRX_EL2_D128En, FEAT_D128),
+	NEEDS_FEAT(HCRX_EL2_PTTWI, FEAT_THE),
+	NEEDS_FEAT(HCRX_EL2_SCTLR2En, FEAT_SCTLR2),
+	NEEDS_FEAT(HCRX_EL2_TCR2En, FEAT_TCR2),
+	NEEDS_FEAT(HCRX_EL2_MSCEn		|
+		   HCRX_EL2_MCE2,
+		   FEAT_MOPS),
+	NEEDS_FEAT(HCRX_EL2_CMOW, FEAT_CMOW),
+	NEEDS_FEAT(HCRX_EL2_VFNMI		|
+		   HCRX_EL2_VINMI		|
+		   HCRX_EL2_TALLINT,
+		   FEAT_NMI),
+	NEEDS_FEAT(HCRX_EL2_SMPME, feat_sme_smps),
+	NEEDS_FEAT(HCRX_EL2_FGTnXS		|
+		   HCRX_EL2_FnXS,
+		   FEAT_XS),
+	NEEDS_FEAT(HCRX_EL2_EnASR, FEAT_LS64_V),
+	NEEDS_FEAT(HCRX_EL2_EnALS, FEAT_LS64),
+	NEEDS_FEAT(HCRX_EL2_EnAS0, FEAT_LS64_ACCDATA),
+};
+
 static void __init check_feat_map(struct reg_bits_to_feat_map *map,
 				  int map_size, u64 res0, const char *str)
 {
@@ -521,6 +591,8 @@ void __init check_feature_map(void)
 		       hdfgwtr_masks.res0, hdfgwtr_masks.str);
 	check_feat_map(hafgrtr_feat_map, ARRAY_SIZE(hafgrtr_feat_map),
 		       hafgrtr_masks.res0, hafgrtr_masks.str);
+	check_feat_map(hcrx_feat_map, ARRAY_SIZE(hcrx_feat_map),
+		       __HCRX_EL2_RES0, "HCRX_EL2");
 }
 
 static bool idreg_feat_match(struct kvm *kvm, struct reg_bits_to_feat_map *map)
@@ -656,6 +728,12 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
 		*res0 |= hafgrtr_masks.res0;
 		*res1 = HAFGRTR_EL2_RES1;
 		break;
+	case HCRX_EL2:
+		*res0 = compute_res0_bits(kvm, hcrx_feat_map,
+					  ARRAY_SIZE(hcrx_feat_map), 0, 0);
+		*res0 |= __HCRX_EL2_RES0;
+		*res1 = __HCRX_EL2_RES1;
+		break;
 	default:
 		WARN_ON_ONCE(1);
 		*res0 = *res1 = 0;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 74df066f9ab3f..984940781a4cf 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1039,45 +1039,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	set_sysreg_masks(kvm, HCR_EL2, res0, res1);
 
 	/* HCRX_EL2 */
-	res0 = __HCRX_EL2_RES0;
-	res1 = __HCRX_EL2_RES1;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR3_EL1, PACM, TRIVIAL_IMP))
-		res0 |= HCRX_EL2_PACMEn;
-	if (!kvm_has_feat(kvm, ID_AA64PFR2_EL1, FPMR, IMP))
-		res0 |= HCRX_EL2_EnFPM;
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
-		res0 |= HCRX_EL2_GCSEn;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, SYSREG_128, IMP))
-		res0 |= HCRX_EL2_EnIDCP128;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, ADERR, DEV_ASYNC))
-		res0 |= (HCRX_EL2_EnSDERR | HCRX_EL2_EnSNERR);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, DF2, IMP))
-		res0 |= HCRX_EL2_TMEA;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, D128, IMP))
-		res0 |= HCRX_EL2_D128En;
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
-		res0 |= HCRX_EL2_PTTWI;
-	if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SCTLRX, IMP))
-		res0 |= HCRX_EL2_SCTLR2En;
-	if (!kvm_has_tcr2(kvm))
-		res0 |= HCRX_EL2_TCR2En;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
-		res0 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
-	if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, CMOW, IMP))
-		res0 |= HCRX_EL2_CMOW;
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, NMI, IMP))
-		res0 |= (HCRX_EL2_VFNMI | HCRX_EL2_VINMI | HCRX_EL2_TALLINT);
-	if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP) ||
-	    !(read_sysreg_s(SYS_SMIDR_EL1) & SMIDR_EL1_SMPS))
-		res0 |= HCRX_EL2_SMPME;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, XS, IMP))
-		res0 |= (HCRX_EL2_FGTnXS | HCRX_EL2_FnXS);
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V))
-		res0 |= HCRX_EL2_EnASR;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64))
-		res0 |= HCRX_EL2_EnALS;
-	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
-		res0 |= HCRX_EL2_EnAS0;
+	get_reg_fixed_bits(kvm, HCRX_EL2, &res0, &res1);
 	set_sysreg_masks(kvm, HCRX_EL2, res0, res1);
 
 	/* HFG[RW]TR_EL2 */
-- 
2.39.2



From eichest at gmail.com  Mon Mar 10 05:27:02 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Mon, 10 Mar 2025 13:27:02 +0100
Subject: [PATCH v3 0/2] phy: freescale: imx8m-pcie: fix and cleanup phy
Message-ID: <20250310122745.34947-1-eichest@gmail.com>

The imx8m-pcie PHY PLL fails to lock under certain conditions when
returning from suspend. This is resolved by asserting the PHY reset when
powering off the PHY during suspend. This ensures that the PHY is
properly reset when powering on again in resume.

Changes in v3:
- Update commit message of cleanup patch (Frank)
- Add Reviewd-by and Acked-by (Frank and Richard)

Changes in v2:
- Remove unnecessary check if perst is not null (Philipp)

Stefan Eichenberger (2):
  phy: freescale: imx8m-pcie: cleanup reset logic
  phy: freescale: imx8m-pcie: assert phy reset and perst in power off

 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 23 +++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

-- 
2.45.2



From eichest at gmail.com  Mon Mar 10 05:27:03 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Mon, 10 Mar 2025 13:27:03 +0100
Subject: [PATCH v3 1/2] phy: freescale: imx8m-pcie: cleanup reset logic
In-Reply-To: <20250310122745.34947-1-eichest@gmail.com>
References: <20250310122745.34947-1-eichest@gmail.com>
Message-ID: <20250310122745.34947-2-eichest@gmail.com>

From: Stefan Eichenberger <stefan.eichenberger at toradex.com>

Remove the switch statement for releasing perst and reset since they are
already correctly set at probe and are no-ops for
reset_control_deassert(NULL). Call these unconditionally.

This does not change the behavior of the driver but reduces driver
complexity and allows for easier future modifications.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Acked-by: Richard Zhu <hongxing.zhu at nxp.com>
Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
---
 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index e98361dcdeadf..5b505e34ca364 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -141,15 +141,9 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
 			   IMX8MM_GPR_PCIE_REF_CLK_PLL);
 	usleep_range(100, 200);
 
-	switch (imx8_phy->drvdata->variant) {
-	case IMX8MP:
-		reset_control_deassert(imx8_phy->perst);
-		fallthrough;
-	case IMX8MM:
-		reset_control_deassert(imx8_phy->reset);
-		usleep_range(200, 500);
-		break;
-	}
+	reset_control_deassert(imx8_phy->perst);
+	reset_control_deassert(imx8_phy->reset);
+	usleep_range(200, 500);
 
 	/* Do the PHY common block reset */
 	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
-- 
2.45.2



From eichest at gmail.com  Mon Mar 10 05:27:04 2025
From: eichest at gmail.com (Stefan Eichenberger)
Date: Mon, 10 Mar 2025 13:27:04 +0100
Subject: [PATCH v3 2/2] phy: freescale: imx8m-pcie: assert phy reset and perst in power off
In-Reply-To: <20250310122745.34947-1-eichest@gmail.com>
References: <20250310122745.34947-1-eichest@gmail.com>
Message-ID: <20250310122745.34947-3-eichest@gmail.com>

From: Stefan Eichenberger <stefan.eichenberger at toradex.com>

Ensure the PHY reset and perst is asserted during power-off to
guarantee it is in a reset state upon repeated power-on calls. This
resolves an issue where the PHY may not properly initialize during
subsequent power-on cycles. Power-on will deassert the reset at the
appropriate time after tuning the PHY parameters.

During suspend/resume cycles, we observed that the PHY PLL failed to
lock during resume when the CPU temperature increased from 65C to 75C.
The observed errors were:
  phy phy-32f00000.pcie-phy.3: phy poweron failed --> -110
  imx6q-pcie 33800000.pcie: waiting for PHY ready timeout!
  imx6q-pcie 33800000.pcie: PM: dpm_run_callback(): genpd_resume_noirq+0x0/0x80 returns -110
  imx6q-pcie 33800000.pcie: PM: failed to resume noirq: error -110

This resulted in a complete CPU freeze, which is resolved by ensuring
the PHY is in reset during power-on, thus preventing PHY PLL failures.

Cc: stable at vger.kernel.org
Fixes: 1aa97b002258 ("phy: freescale: pcie: Initialize the imx8 pcie standalone phy driver")
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Acked-by: Richard Zhu <hongxing.zhu at nxp.com>
Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
---
 drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index 5b505e34ca364..7355d9921b646 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -156,6 +156,16 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
 	return ret;
 }
 
+static int imx8_pcie_phy_power_off(struct phy *phy)
+{
+	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+
+	reset_control_assert(imx8_phy->reset);
+	reset_control_assert(imx8_phy->perst);
+
+	return 0;
+}
+
 static int imx8_pcie_phy_init(struct phy *phy)
 {
 	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
@@ -176,6 +186,7 @@ static const struct phy_ops imx8_pcie_phy_ops = {
 	.init		= imx8_pcie_phy_init,
 	.exit		= imx8_pcie_phy_exit,
 	.power_on	= imx8_pcie_phy_power_on,
+	.power_off	= imx8_pcie_phy_power_off,
 	.owner		= THIS_MODULE,
 };
 
-- 
2.45.2



From linux at armlinux.org.uk  Mon Mar 10 05:31:32 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:31:32 +0000
Subject: [PATCH net-next 0/2] net: stmmac: avoid unnecessary work in
 stmmac_release()/stmmac_dvr_remove()
Message-ID: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>

Hi,

This small series is a subset of a RFC I sent earlier. These two
patches remove code that is unnecessary and/or wrong in these paths.
Details in each commit.

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 -----
 1 file changed, 5 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:31:25 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:31:25 +0000
Subject: [PATCH net-next 1/2] net: stmmac: remove redundant racy tear-down in
 stmmac_dvr_remove()
In-Reply-To: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
References: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
Message-ID: <E1trcI1-005rn2-CZ@rmk-PC.armlinux.org.uk>

While the network device is registered, it is published to userspace,
and thus userspace can change its state. This means calling
functions such as stmmac_stop_all_dma() and stmmac_mac_set() are
racy.

Moreover, unregister_netdev() will unpublish the network device, and
then if appropriate call the .ndo_stop() method, which is
stmmac_release(). This will first call phylink_stop() which will
synchronously take the link down, resulting in stmmac_mac_link_down()
and stmmac_mac_set(, false) being called.

stmmac_release() will also call stmmac_stop_all_dma().

Consequently, neither of these two functions need to called prior
to unregister_netdev() as that will safely call paths that will
result in this work being done if necessary.

Remove these redundant racy calls.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Furong Xu <0x1207 at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fa1d7d3a2f43..c2ee6c0af3fd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7768,8 +7768,6 @@ void stmmac_dvr_remove(struct device *dev)
 
 	pm_runtime_get_sync(dev);
 
-	stmmac_stop_all_dma(priv);
-	stmmac_mac_set(priv, priv->ioaddr, false);
 	unregister_netdev(ndev);
 
 #ifdef CONFIG_DEBUG_FS
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:31:30 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:31:30 +0000
Subject: [PATCH net-next 2/2] net: stmmac: remove unnecessary stmmac_mac_set()
 in stmmac_release()
In-Reply-To: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
References: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
Message-ID: <E1trcI6-005rn8-GV@rmk-PC.armlinux.org.uk>

stmmac_release() calls phylink_stop() and then goes on to call
stmmac_mac_set(, false). However, phylink_stop() will call
stmmac_mac_link_down() before returning, which will do this work.
Remove this unnecessary call.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Tested-by: Furong Xu <0x1207 at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c2ee6c0af3fd..839ecebf5f5f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -4129,9 +4129,6 @@ static int stmmac_release(struct net_device *dev)
 	/* Release and free the Rx/Tx resources */
 	free_dma_desc_resources(priv, &priv->dma_conf);
 
-	/* Disable the MAC Rx/Tx */
-	stmmac_mac_set(priv, priv->ioaddr, false);
-
 	/* Powerdown Serdes if there is */
 	if (priv->plat->serdes_powerdown)
 		priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
-- 
2.30.2



From robh at kernel.org  Mon Mar 10 05:32:07 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 07:32:07 -0500
Subject: [RFC PATCH 09/24] dt-bindings: media: i2c: max96714: make
 i2c-gate conditional on compatible
In-Reply-To: <20250308183410.3013996-10-demonsingur@gmail.com>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-10-demonsingur@gmail.com>
Message-ID: <20250310123207.GA3853920-robh@kernel.org>

On Sat, Mar 08, 2025 at 08:33:38PM +0200, Cosmin Tanislav wrote:
> Devices to be added in following patches don't use I2C gate.
> 
> Make this property conditional on the compatible strings.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96714.yaml    | 21 ++++++++++++-------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
> index 2f453189338f..d0a2aaf7df9c 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
> @@ -84,14 +84,6 @@ properties:
>      required:
>        - port at 1
>  
> -  i2c-gate:
> -    $ref: /schemas/i2c/i2c-gate.yaml
> -    unevaluatedProperties: false
> -    description:
> -      The MAX96714 will pass through and forward the I2C requests from the
> -      incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate
> -      subnode to configure a serializer.
> -
>    port0-poc-supply:
>      description: Regulator providing Power over Coax for the GMSL port
>  
> @@ -101,6 +93,19 @@ required:
>    - ports
>  
>  additionalProperties: false
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - maxim,max96714
> +              - maxim,max96714f
> +    then:
> +      properties:
> +        i2c-gate:

Leave the original definition, invert the 'if', and here you just need:

i2c-gate: false

> +          $ref: /schemas/i2c/i2c-gate.yaml
> +          unevaluatedProperties: false
>  
>  examples:
>    - |
> -- 
> 2.48.1
> 


From leo.yan at arm.com  Mon Mar 10 05:32:13 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 12:32:13 +0000
Subject: [PATCH v2 2/8] coresight: Introduce pause and resume APIs for
 source
In-Reply-To: <65979e92-0047-427c-848d-53f908671905@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-3-leo.yan@arm.com>
 <65979e92-0047-427c-848d-53f908671905@arm.com>
Message-ID: <20250310123213.GF9682@e132581.arm.com>

On Mon, Mar 10, 2025 at 12:01:25PM +0000, Suzuki Kuruppassery Poulose wrote:
> On 10/03/2025 10:49, Leo Yan wrote:
> > Introduce APIs for pausing and resuming trace source and export as GPL
> > symbols.
> > 
> > Signed-off-by: Leo Yan <leo.yan at arm.com>
> > ---
> >   drivers/hwtracing/coresight/coresight-core.c | 20 ++++++++++++++++++++
> >   drivers/hwtracing/coresight/coresight-priv.h |  2 ++
> >   include/linux/coresight.h                    |  4 ++++
> >   3 files changed, 26 insertions(+)
> > 
> > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> > index 0a9380350fb5..eb7b83a7bfa2 100644
> > --- a/drivers/hwtracing/coresight/coresight-core.c
> > +++ b/drivers/hwtracing/coresight/coresight-core.c
> > @@ -365,6 +365,26 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
> >   }
> >   EXPORT_SYMBOL_GPL(coresight_disable_source);
> > +void coresight_pause_source(struct coresight_device *csdev)
> > +{
> > +	if (!csdev || !coresight_is_percpu_source(csdev))
> 
> You may remove the !csdev check, coresight_is_percpu_source() already checks
> that.

Will do.

> > +		return;
> > +
> > +	if (source_ops(csdev)->pause)
> > +		source_ops(csdev)->pause(csdev);
> > +}
> > +EXPORT_SYMBOL_GPL(coresight_pause_source);
> > +
> > +void coresight_resume_source(struct coresight_device *csdev)
> > +{
> > +	if (!csdev || !coresight_is_percpu_source(csdev))
> > +		return;
> > +
> 
> Same as above.

Will do.

> > +	if (source_ops(csdev)->resume)
> > +		source_ops(csdev)->resume(csdev);
> > +}
> > +EXPORT_SYMBOL_GPL(coresight_resume_source);
> > +
> >   /*
> >    * coresight_disable_path_from : Disable components in the given path beyond
> >    * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
> > diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> > index 76403530f33e..a9f14c075e91 100644
> > --- a/drivers/hwtracing/coresight/coresight-priv.h
> > +++ b/drivers/hwtracing/coresight/coresight-priv.h
> > @@ -247,5 +247,7 @@ void coresight_add_helper(struct coresight_device *csdev,
> >   void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
> >   struct coresight_device *coresight_get_percpu_sink(int cpu);
> >   void coresight_disable_source(struct coresight_device *csdev, void *data);
> > +void coresight_pause_source(struct coresight_device *csdev);
> > +void coresight_resume_source(struct coresight_device *csdev);
> >   #endif
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index 17276965ff1d..703e1b8dbe22 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -385,6 +385,8 @@ struct coresight_ops_link {
> >    *		is associated to.
> >    * @enable:	enables tracing for a source.
> >    * @disable:	disables tracing for a source.
> > + * @resume:	resumes tracing for a source.
> > + * @pause:	pauses tracing for a source.
> >    */
> >   struct coresight_ops_source {
> >   	int (*cpu_id)(struct coresight_device *csdev);
> > @@ -392,6 +394,8 @@ struct coresight_ops_source {
> >   		      enum cs_mode mode, struct coresight_trace_id_map *id_map);
> >   	void (*disable)(struct coresight_device *csdev,
> >   			struct perf_event *event);
> > +	int (*resume)(struct coresight_device *csdev);
> > +	void (*pause)(struct coresight_device *csdev);
> 
> Given these callbacks are for perf mode, does it make sense to pass the
> parameters similar to enable() ?

It is not necessary to pass perf event handle to resume() and pause()
callbacks.

The main reason is perf related operations have been processed in the
coresight-etm-perf.c layer, the low level's callbacks (pause/resume)
should simply take actions on hardware logic.

> Also, should we rename these as :
> 
> resume_perf
> pause_perf
> 
> To explicitly mark them perf mode specific ?

This makes sense to me.  The naming "resume" might be confused with
CPUIdle's terminology (CPU resume).  pause_perf/resume_perf can
perfectly avoid any confusion.

Thanks,
Leo


From robh at kernel.org  Mon Mar 10 05:40:14 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 07:40:14 -0500
Subject: [PATCH v8 05/11] dt-bindings: allwinner: add H616 DE33 bus
 binding
In-Reply-To: <20250310092345.31708-6-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
 <20250310092345.31708-6-ryan@testtoast.com>
Message-ID: <20250310124014.GA3866055-robh@kernel.org>

On Mon, Mar 10, 2025 at 10:09:51PM +1300, Ryan Walklin wrote:
> The Allwinner H616 and variants have a new display engine revision
> (DE33).
> 
> Add a display engine bus binding for the DE33 and increase reg maxItems
> to 3 to accommodate additional register blocks.
> 
> Signed-off-by: Ryan Walklin <ryan at testtoast.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>
> Reviewed-by: Chen-Yu Tsai <wens at csie.org>
> 
> ---
> Changelog v1..v2:
> - Correct DE2 bus enum to reflect fallback devices accurately.
> 
> Changelog v2..v3:
> - Separate content into three patches for three separate subsystems
> 
> Changelog v5..v6:
> - Increase reg maxItems to 3.
> ---
>  .../devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml  | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
> index 9845a187bdf6..317a27cf590b 100644
> --- a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
> +++ b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
> @@ -24,11 +24,14 @@ properties:
>      oneOf:
>        - const: allwinner,sun50i-a64-de2
>        - items:
> -          - const: allwinner,sun50i-h6-de3
> +          - enum:
> +              - allwinner,sun50i-h6-de3
> +              - allwinner,sun50i-h616-de33
>            - const: allwinner,sun50i-a64-de2
>  
>    reg:
> -    maxItems: 1
> +    minItems: 1
> +    maxItems: 3

You have to define what each region is and the order.

And there should be constraints such that the existing cases don't 
now allow 2-3 entries.

>  
>    allwinner,sram:
>      description:
> -- 
> 2.48.1
> 


From ltykernel at gmail.com  Mon Mar 10 05:40:46 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 20:40:46 +0800
Subject: [PATCH v5 09/10] hyperv: Add definitions for root partition
 driver to hv headers
In-Reply-To: <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <CAMvTesB5dCD5Cx+CE8oPQ35OHC+C=tyXbHQ0BNxSABEFVK53Tg@mail.gmail.com>

On Thu, Feb 27, 2025 at 7:11?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> A few additional definitions are required for the mshv driver code
> (to follow). Introduce those here and clean up a little bit while
> at it.
>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---

It may be better to unify data type u8, u16, u32, u64 or __u8, __u16,
__u32, __u64 in the hvhdk.h.

Others like good.

Reviewed-by: Tianyu Lan <tiala at microsoft.com>

-- 
Thanks
Tianyu Lan


From matt.coster at imgtec.com  Mon Mar 10 06:10:30 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:30 +0000
Subject: [PATCH v3 06/18] drm/imagination: Mask GPU IRQs in threaded
 handler
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-6-143b3dbef02f@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Pass IRQF_ONESHOT flag to request_threaded_irq(), so that interrupts will
be masked by the kernel until the end of the threaded IRQ handler. Since
the calls to pvr_fw_irq_enable() and pvr_fw_irq_disable() are now
redundant, remove them.

Interrupts to the host from the soon-to-be-added RISC-V firmware
processors cannot be masked in hardware. This change allows us to continue
using the threaded handler in GPUs with a RISC-V firmware.

For simplicity, the same approach is taken for all firmware processors.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_device.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index 1704c0268589bdeb65fa6535f9ec63182b0a3e94..b6ce936f07c8bb26d240e50b72a1d991dbe4b045 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -169,8 +169,6 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 		ret = IRQ_HANDLED;
 	}
 
-	/* Unmask FW irqs before returning, so new interrupts can be received. */
-	pvr_fw_irq_enable(pvr_dev);
 	return ret;
 }
 
@@ -181,10 +179,6 @@ static irqreturn_t pvr_device_irq_handler(int irq, void *data)
 	if (!pvr_fw_irq_pending(pvr_dev))
 		return IRQ_NONE; /* Spurious IRQ - ignore. */
 
-	/* Mask the FW interrupts before waking up the thread. Will be unmasked
-	 * when the thread handler is done processing events.
-	 */
-	pvr_fw_irq_disable(pvr_dev);
 	return IRQ_WAKE_THREAD;
 }
 
@@ -213,9 +207,13 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 	pvr_fw_irq_clear(pvr_dev);
 	pvr_fw_irq_enable(pvr_dev);
 
+	/*
+	 * The ONESHOT flag ensures IRQs are masked while the thread handler is
+	 * running.
+	 */
 	return request_threaded_irq(pvr_dev->irq, pvr_device_irq_handler,
 				    pvr_device_irq_thread_handler,
-				    IRQF_SHARED, "gpu", pvr_dev);
+				    IRQF_SHARED | IRQF_ONESHOT, "gpu", pvr_dev);
 }
 
 /**

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:38 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:38 +0000
Subject: [PATCH v3 14/18] drm/imagination: Add RISC-V firmware processor
 support
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-14-143b3dbef02f@imgtec.com>

From: Sarah Walker <sarah.walker at imgtec.com>

Newer PowerVR GPUs (such as the BXS-4-64 MC1) use a RISC-V firmware
processor instead of the previous MIPS or META.

Signed-off-by: Sarah Walker <sarah.walker at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Don't enable debug module
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-17-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-17-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/Makefile           |   1 +
 drivers/gpu/drm/imagination/pvr_fw.c           |  18 +--
 drivers/gpu/drm/imagination/pvr_fw.h           |  10 ++
 drivers/gpu/drm/imagination/pvr_fw_riscv.c     | 163 +++++++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_fw_startstop.c |  17 +++
 drivers/gpu/drm/imagination/pvr_rogue_riscv.h  |  41 +++++++
 6 files changed, 242 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile
index 077e4762c7c383b6e339da1584c3865d830ef8d6..d748ad9d62e092ed7c3d772214ccd327818d507f 100644
--- a/drivers/gpu/drm/imagination/Makefile
+++ b/drivers/gpu/drm/imagination/Makefile
@@ -14,6 +14,7 @@ powervr-y := \
 	pvr_fw.o \
 	pvr_fw_meta.o \
 	pvr_fw_mips.o \
+	pvr_fw_riscv.o \
 	pvr_fw_startstop.o \
 	pvr_fw_trace.o \
 	pvr_fw_util.o \
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index 6e19b20ab67c3dbfe20110cbc7bb0de05b7bb08b..9cee40fb04c8979841544f92edf6b40aacafab04 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -932,7 +932,7 @@ pvr_fw_init(struct pvr_device *pvr_dev)
 	static const struct pvr_fw_defs *fw_defs[PVR_FW_PROCESSOR_TYPE_COUNT] = {
 		[PVR_FW_PROCESSOR_TYPE_META] = &pvr_fw_defs_meta,
 		[PVR_FW_PROCESSOR_TYPE_MIPS] = &pvr_fw_defs_mips,
-		[PVR_FW_PROCESSOR_TYPE_RISCV] = NULL,
+		[PVR_FW_PROCESSOR_TYPE_RISCV] = &pvr_fw_defs_riscv,
 	};
 
 	u32 kccb_size_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT;
@@ -945,13 +945,6 @@ pvr_fw_init(struct pvr_device *pvr_dev)
 
 	fw_dev->defs = fw_defs[fw_dev->processor_type];
 
-	/*
-	 * Not all firmware processor types are currently supported.
-	 * Once they are, this check can be removed.
-	 */
-	if (!fw_dev->defs)
-		return -EINVAL;
-
 	err = fw_dev->defs->init(pvr_dev);
 	if (err)
 		return err;
@@ -1457,6 +1450,15 @@ void pvr_fw_object_get_fw_addr_offset(struct pvr_fw_object *fw_obj, u32 offset,
 	*fw_addr_out = pvr_dev->fw_dev.defs->get_fw_addr_with_offset(fw_obj, offset);
 }
 
+u64
+pvr_fw_obj_get_gpu_addr(struct pvr_fw_object *fw_obj)
+{
+	struct pvr_device *pvr_dev = to_pvr_device(gem_from_pvr_gem(fw_obj->gem)->dev);
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+
+	return fw_dev->fw_heap_info.gpu_addr + fw_obj->fw_addr_offset;
+}
+
 /*
  * pvr_fw_hard_reset() - Re-initialise the FW code and data segments, and reset all global FW
  *                       structures
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index e120eae06bf78633b5bae79a77adac63aa5e06d3..1404dd492d7cd82d62dd407a780efcae34d9bf2d 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -392,6 +392,7 @@ enum pvr_fw_processor_type {
 
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
+extern const struct pvr_fw_defs pvr_fw_defs_riscv;
 
 int pvr_fw_validate_init_device_info(struct pvr_device *pvr_dev);
 int pvr_fw_init(struct pvr_device *pvr_dev);
@@ -478,6 +479,15 @@ pvr_fw_object_get_fw_addr(struct pvr_fw_object *fw_obj, u32 *fw_addr_out)
 	pvr_fw_object_get_fw_addr_offset(fw_obj, 0, fw_addr_out);
 }
 
+u64
+pvr_fw_obj_get_gpu_addr(struct pvr_fw_object *fw_obj);
+
+static __always_inline size_t
+pvr_fw_obj_get_object_size(struct pvr_fw_object *fw_obj)
+{
+	return pvr_gem_object_size(fw_obj->gem);
+}
+
 /* Util functions defined in pvr_fw_util.c. These are intended for use in pvr_fw_<arch>.c files. */
 int
 pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_riscv.c b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
new file mode 100644
index 0000000000000000000000000000000000000000..14021e6ef7533f7185dc3c2378fc1d0c46c2ffed
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#include "pvr_device.h"
+#include "pvr_fw.h"
+#include "pvr_fw_info.h"
+#include "pvr_fw_mips.h"
+#include "pvr_gem.h"
+#include "pvr_rogue_cr_defs.h"
+#include "pvr_rogue_riscv.h"
+#include "pvr_vm.h"
+
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/ktime.h>
+#include <linux/types.h>
+
+#define ROGUE_FW_HEAP_RISCV_SHIFT 25 /* 32 MB */
+#define ROGUE_FW_HEAP_RISCV_SIZE (1u << ROGUE_FW_HEAP_RISCV_SHIFT)
+
+static int
+pvr_riscv_wrapper_init(struct pvr_device *pvr_dev)
+{
+	const u64 common_opts =
+		((u64)(ROGUE_FW_HEAP_RISCV_SIZE >> FWCORE_ADDR_REMAP_CONFIG0_SIZE_ALIGNSHIFT)
+		 << ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_SIZE_SHIFT) |
+		((u64)MMU_CONTEXT_MAPPING_FWPRIV
+		 << FWCORE_ADDR_REMAP_CONFIG0_MMU_CONTEXT_SHIFT);
+
+	u64 code_addr = pvr_fw_obj_get_gpu_addr(pvr_dev->fw_dev.mem.code_obj);
+	u64 data_addr = pvr_fw_obj_get_gpu_addr(pvr_dev->fw_dev.mem.data_obj);
+
+	/* This condition allows us to OR the addresses into the register directly. */
+	static_assert(ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_SHIFT ==
+		      ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_ALIGNSHIFT);
+
+	WARN_ON(code_addr & ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_CLRMSK);
+	WARN_ON(data_addr & ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_CLRMSK);
+
+	pvr_cr_write64(pvr_dev, ROGUE_RISCVFW_REGION_REMAP_CR(BOOTLDR_CODE),
+		       code_addr | common_opts | ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_FETCH_EN_EN);
+
+	pvr_cr_write64(pvr_dev, ROGUE_RISCVFW_REGION_REMAP_CR(BOOTLDR_DATA),
+		       data_addr | common_opts |
+			       ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_LOAD_STORE_EN_EN);
+
+	/* Garten IDLE bit controlled by RISC-V. */
+	pvr_cr_write64(pvr_dev, ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG,
+		       ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
+
+	return 0;
+}
+
+struct rogue_riscv_fw_boot_data {
+	u64 coremem_code_dev_vaddr;
+	u64 coremem_data_dev_vaddr;
+	u32 coremem_code_fw_addr;
+	u32 coremem_data_fw_addr;
+	u32 coremem_code_size;
+	u32 coremem_data_size;
+	u32 flags;
+	u32 reserved;
+};
+
+static int
+pvr_riscv_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
+		    u8 *fw_code_ptr, u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr,
+		    u32 core_code_alloc_size)
+{
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+	struct pvr_fw_mem *fw_mem = &fw_dev->mem;
+	struct rogue_riscv_fw_boot_data *boot_data;
+	int err;
+
+	err = pvr_fw_process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr,
+						fw_core_code_ptr, fw_core_data_ptr);
+	if (err)
+		goto err_out;
+
+	boot_data = (struct rogue_riscv_fw_boot_data *)fw_data_ptr;
+
+	if (fw_mem->core_code_obj) {
+		boot_data->coremem_code_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_code_obj);
+		pvr_fw_object_get_fw_addr(fw_mem->core_code_obj, &boot_data->coremem_code_fw_addr);
+		boot_data->coremem_code_size = pvr_fw_obj_get_object_size(fw_mem->core_code_obj);
+	}
+
+	if (fw_mem->core_data_obj) {
+		boot_data->coremem_data_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_data_obj);
+		pvr_fw_object_get_fw_addr(fw_mem->core_data_obj, &boot_data->coremem_data_fw_addr);
+		boot_data->coremem_data_size = pvr_fw_obj_get_object_size(fw_mem->core_data_obj);
+	}
+
+	return 0;
+
+err_out:
+	return err;
+}
+
+static int
+pvr_riscv_init(struct pvr_device *pvr_dev)
+{
+	pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_RISCV_SHIFT, 0);
+
+	return 0;
+}
+
+static u32
+pvr_riscv_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
+{
+	u32 fw_addr = fw_obj->fw_addr_offset + offset;
+
+	/* RISC-V cacheability is determined by address. */
+	if (fw_obj->gem->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
+		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_UNCACHED_DATA);
+	else
+		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_CACHED_DATA);
+
+	return fw_addr;
+}
+
+static int
+pvr_riscv_vm_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
+{
+	struct pvr_gem_object *pvr_obj = fw_obj->gem;
+
+	return pvr_vm_map(pvr_dev->kernel_vm_ctx, pvr_obj, 0, fw_obj->fw_mm_node.start,
+			  pvr_gem_object_size(pvr_obj));
+}
+
+static void
+pvr_riscv_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
+{
+	pvr_vm_unmap(pvr_dev->kernel_vm_ctx, fw_obj->fw_mm_node.start,
+		     fw_obj->fw_mm_node.size);
+}
+
+static bool
+pvr_riscv_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_IRQ_OS0_EVENT_STATUS) &
+	       ROGUE_CR_IRQ_OS0_EVENT_STATUS_SOURCE_EN;
+}
+
+static void
+pvr_riscv_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_IRQ_OS0_EVENT_CLEAR,
+		       ROGUE_CR_IRQ_OS0_EVENT_CLEAR_SOURCE_EN);
+}
+
+const struct pvr_fw_defs pvr_fw_defs_riscv = {
+	.init = pvr_riscv_init,
+	.fw_process = pvr_riscv_fw_process,
+	.vm_map = pvr_riscv_vm_map,
+	.vm_unmap = pvr_riscv_vm_unmap,
+	.get_fw_addr_with_offset = pvr_riscv_get_fw_addr_with_offset,
+	.wrapper_init = pvr_riscv_wrapper_init,
+	.irq_pending = pvr_riscv_irq_pending,
+	.irq_clear = pvr_riscv_irq_clear,
+	.has_fixed_data_addr = false,
+};
diff --git a/drivers/gpu/drm/imagination/pvr_fw_startstop.c b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
index 36cec227cfe3cf5b1e293f48b164bb1be1b0ea54..dcbb9903e791e600db22d334b2e9580057edc89b 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_startstop.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
@@ -49,6 +49,14 @@ rogue_bif_init(struct pvr_device *pvr_dev)
 
 	pvr_cr_write64(pvr_dev, BIF_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV),
 		       pc_addr);
+
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
+		pc_addr = (((u64)pc_dma_addr >> ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_ALIGNSHIFT)
+			   << ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT) &
+			  ~ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_CLRMSK;
+
+		pvr_cr_write64(pvr_dev, FWCORE_MEM_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV), pc_addr);
+	}
 }
 
 static int
@@ -114,6 +122,9 @@ pvr_fw_start(struct pvr_device *pvr_dev)
 		(void)pvr_cr_read32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE); /* Fence write */
 	}
 
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV)
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 0);
+
 	/* Set Rogue in soft-reset. */
 	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);
 	if (has_reset2)
@@ -167,6 +178,12 @@ pvr_fw_start(struct pvr_device *pvr_dev)
 	/* ... and afterwards. */
 	udelay(3);
 
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
+		/* Boot the FW. */
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 1);
+		udelay(3);
+	}
+
 	return 0;
 
 err_reset:
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_riscv.h b/drivers/gpu/drm/imagination/pvr_rogue_riscv.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a070e24fa6a8bb44ff1e421ae6750cbf724d346
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_rogue_riscv.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#ifndef PVR_ROGUE_RISCV_H
+#define PVR_ROGUE_RISCV_H
+
+#include "pvr_rogue_cr_defs.h"
+
+#include <linux/bitops.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+#define ROGUE_RISCVFW_REGION_SIZE SZ_256M
+#define ROGUE_RISCVFW_REGION_SHIFT __ffs(ROGUE_RISCVFW_REGION_SIZE)
+
+enum rogue_riscvfw_region {
+	ROGUE_RISCV_REGION__RESERVED_0 = 0,
+	ROGUE_RISCV_REGION__RESERVED_1,
+	ROGUE_RISCV_REGION_SOCIF,
+	ROGUE_RISCV_REGION__RESERVED_3,
+	ROGUE_RISCV_REGION__RESERVED_4,
+	ROGUE_RISCV_REGION_BOOTLDR_DATA,
+	ROGUE_RISCV_REGION_SHARED_CACHED_DATA,
+	ROGUE_RISCV_REGION__RESERVED_7,
+	ROGUE_RISCV_REGION_COREMEM,
+	ROGUE_RISCV_REGION__RESERVED_9,
+	ROGUE_RISCV_REGION__RESERVED_A,
+	ROGUE_RISCV_REGION__RESERVED_B,
+	ROGUE_RISCV_REGION_BOOTLDR_CODE,
+	ROGUE_RISCV_REGION_SHARED_UNCACHED_DATA,
+	ROGUE_RISCV_REGION__RESERVED_E,
+	ROGUE_RISCV_REGION__RESERVED_F,
+
+	ROGUE_RISCV_REGION__COUNT,
+};
+
+#define ROGUE_RISCVFW_REGION_BASE(r) ((u32)(ROGUE_RISCV_REGION_##r) << ROGUE_RISCVFW_REGION_SHIFT)
+#define ROGUE_RISCVFW_REGION_REMAP_CR(r) \
+	(ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0 + (u32)(ROGUE_RISCV_REGION_##r) * 8U)
+
+#endif /* PVR_ROGUE_RISCV_H */

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:40 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:40 +0000
Subject: [PATCH v3 16/18] drm/imagination: Add support for TI AM68 GPU
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-16-143b3dbef02f@imgtec.com>

Since we already added a generic compatible string for all IMG Rogue GPUs
("img,img-rogue"), all that's needed here is to link the appropriate
firmware for the BXS-4-64 GPU in the AM68.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Remove device overrides
- Remove specific compatible string
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-20-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-20-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index ac4f5855c5692f0956862cebdbf76b16d8da9a81..b058ec183bb30ab5c3db17ebaadf2754520a2a1f 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -44,6 +44,7 @@
  * This driver supports the following PowerVR/IMG graphics cores from Imagination Technologies:
  *
  * * AXE-1-16M (found in Texas Instruments AM62)
+ * * BXS-4-64 MC1 (found in Texas Instruments J721S2/AM68)
  */
 
 /**
@@ -1512,3 +1513,4 @@ MODULE_DESCRIPTION(PVR_DRIVER_DESC);
 MODULE_LICENSE("Dual MIT/GPL");
 MODULE_IMPORT_NS("DMA_BUF");
 MODULE_FIRMWARE("powervr/rogue_33.15.11.3_v1.fw");
+MODULE_FIRMWARE("powervr/rogue_36.53.104.796_v1.fw");

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:35 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:35 +0000
Subject: [PATCH v3 11/18] drm/imagination: Use a lookup table for fw defs
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-11-143b3dbef02f@imgtec.com>

With more than two firmware processor types, the if/else chain in
pvr_fw_init() gets a bit ridiculous. Use a static array indexed on
pvr_fw_processor_type (which is now a proper enum instead of #defines)
instead.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-13-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-13-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h |  4 ----
 drivers/gpu/drm/imagination/pvr_fw.c     | 21 ++++++++++++++++-----
 drivers/gpu/drm/imagination/pvr_fw.h     |  7 +++++++
 3 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 6c01d96657de6dc3904ef5ca28365f06cfe0f40b..12bf0b9e5bfb48ef9e5ed9faa44e0896b7555f49 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -739,8 +739,4 @@ pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
 					      __union_size, __member_size);  \
 	})
 
-#define PVR_FW_PROCESSOR_TYPE_META  0
-#define PVR_FW_PROCESSOR_TYPE_MIPS  1
-#define PVR_FW_PROCESSOR_TYPE_RISCV 2
-
 #endif /* PVR_DEVICE_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index c331d6001550a0b1d9cfbda2cd6629533ab6ee33..6e19b20ab67c3dbfe20110cbc7bb0de05b7bb08b 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -929,16 +929,27 @@ pvr_fw_validate_init_device_info(struct pvr_device *pvr_dev)
 int
 pvr_fw_init(struct pvr_device *pvr_dev)
 {
+	static const struct pvr_fw_defs *fw_defs[PVR_FW_PROCESSOR_TYPE_COUNT] = {
+		[PVR_FW_PROCESSOR_TYPE_META] = &pvr_fw_defs_meta,
+		[PVR_FW_PROCESSOR_TYPE_MIPS] = &pvr_fw_defs_mips,
+		[PVR_FW_PROCESSOR_TYPE_RISCV] = NULL,
+	};
+
 	u32 kccb_size_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT;
 	u32 kccb_rtn_size = (1 << kccb_size_log2) * sizeof(*pvr_dev->kccb.rtn);
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
 	int err;
 
-	if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_META)
-		fw_dev->defs = &pvr_fw_defs_meta;
-	else if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_MIPS)
-		fw_dev->defs = &pvr_fw_defs_mips;
-	else
+	if (fw_dev->processor_type >= PVR_FW_PROCESSOR_TYPE_COUNT)
+		return -EINVAL;
+
+	fw_dev->defs = fw_defs[fw_dev->processor_type];
+
+	/*
+	 * Not all firmware processor types are currently supported.
+	 * Once they are, this check can be removed.
+	 */
+	if (!fw_dev->defs)
 		return -EINVAL;
 
 	err = fw_dev->defs->init(pvr_dev);
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 180d310074e3585c641e540a9e2576b5ab2a5705..88ad713468ce3a1ee459b04dde5363c24791a4f1 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -402,6 +402,13 @@ struct pvr_fw_device {
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
 
+enum pvr_fw_processor_type {
+	PVR_FW_PROCESSOR_TYPE_META = 0,
+	PVR_FW_PROCESSOR_TYPE_MIPS,
+	PVR_FW_PROCESSOR_TYPE_RISCV,
+	PVR_FW_PROCESSOR_TYPE_COUNT,
+};
+
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
 

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:25 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:25 +0000
Subject: [PATCH v3 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f@imgtec.com>

The first compatible strings added for the AXE-1-16M are not sufficient to
accurately describe all the IMG Rogue GPUs. The current "img,img-axe"
string refers to the entire family of Series AXE GPUs, but this is
primarily a marketing term and does not denote a level of hardware
similarity any greater than just "Rogue".

The more specific "img,img-axe-1-16m" string refers to individual AXE-1-16M
GPU. For example, unlike the rest of the Series AXE GPUs, the AXE-1-16M
only uses a single power domain.

The situation is actually slightly worse than described in the first
paragraph, since many "series" (such as Series BXS found in the TI AM68
among others and added later in this series) contain cores with both Rogue
and Volcanic architectures.

Besides attempting to move away from vague groupings defined only
by marketing terms, we want to draw a line between properties inherent to
the IP core and choices made by the silicon vendor at integration time.
For instance, the number of power domains is a property of the IP core,
whereas the decision to use one or multiple clocks is a vendor one.

In the original compatible strings, we must use "ti,am62-gpu" to constrain
both of these properties since the number of power domains cannot be fixed
for "img,img-axe".

Work is currently underway to add support for volcanic-based Imagination
GPUs, for which bindings will be added in "img,powervr-volcanic.yaml".
As alluded to previously, the split between rogue and volcanic cores is
non-obvious at times, so add a generic top-level "img,img-rogue" compatible
string here to allow for simpler differentiation in devicetrees without
referring back to the bindings.

The currently supported GPU (AXE-1-16M) only requires a single power
domain. Subsequent patches will add support for BXS-4-64 MC1, which has
two power domains. Add infrastructure now to allow for this.

Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
are DMA devices. The decision for coherency is made at integration time and
this property should be applied wherever it accurately describes the
vendor integration.

Note that the new required properties for power domains are conditional on
the new base compatible string to avoid an ABI break.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Remove unnecessary example
- Remove second power domain details, add these where they're used instead
- Avoid ABI breaks by limiting new required properties to new compatible
  strings and making all binding changes in a single patch.
- Links to v2:
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
---
 .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 43 ++++++++++++++++++----
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 256e252f8087fa0d6081f771a01601d34b66fe19..5c16b2881447c9cda78e5bb46569e2f675d740c4 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -12,10 +12,20 @@ maintainers:
 
 properties:
   compatible:
-    items:
-      - enum:
-          - ti,am62-gpu
-      - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
+    oneOf:
+      - items:
+          - enum:
+              - ti,am62-gpu
+          - const: img,img-axe-1-16m
+          - const: img,img-rogue
+
+      # This legacy combination of compatible strings was introduced early on
+      # before the more specific GPU identifiers were used.
+      - items:
+          - enum:
+              - ti,am62-gpu
+          - const: img,img-axe
+        deprecated: true
 
   reg:
     maxItems: 1
@@ -34,8 +44,13 @@ properties:
   interrupts:
     maxItems: 1
 
-  power-domains:
-    maxItems: 1
+  power-domains: true
+
+  power-domain-names:
+    items:
+      - const: a
+
+  dma-coherent: true
 
 required:
   - compatible
@@ -47,6 +62,19 @@ required:
 additionalProperties: false
 
 allOf:
+  # Constraints added alongside the new compatible strings that would otherwise
+  # create an ABI break.
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: img,img-rogue
+    then:
+      required:
+        - power-domains
+        - power-domain-names
+
+  # Vendor integrations using a single clock domain
   - if:
       properties:
         compatible:
@@ -64,10 +92,11 @@ examples:
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
     gpu at fd00000 {
-        compatible = "ti,am62-gpu", "img,img-axe";
+        compatible = "ti,am62-gpu", "img,img-axe-1-16m", "img,img-rogue";
         reg = <0x0fd00000 0x20000>;
         clocks = <&k3_clks 187 0>;
         clock-names = "core";
         interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
         power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+        power-domain-names = "a";
     };

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:42 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:42 +0000
Subject: [PATCH DO NOT MERGE v3 18/18] arm64: dts: ti: k3-j721s2: Add GPU
 node
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-18-143b3dbef02f@imgtec.com>

The J721S2 binding is based on the TI downstream binding in 54b0f2a00d92
("arm64: dts: ti: k3-j721s2-main: add gpu node") from [1] but with updated
compatible strings.

The clock[2] and power[3] indices were verified from docs, but the
source of the interrupt index remains elusive.

[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel
[2]: https://downloads.ti.com/tisci/esd/latest/5_soc_doc/j721s2/clocks.html
[3]: https://downloads.ti.com/tisci/esd/latest/5_soc_doc/j721s2/devices.html

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-21-3fd45d9fb0cf at imgtec.com
Changes in v2:
- Use normal reg syntax for 64-bit values
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-21-4ed30e865892 at imgtec.com
---
 arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 92bf48fdbeba45ecca8c854db5f72fd3666239c5..a79ac41b2c1f51b7193e6133864428bd35a5e835 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -2048,4 +2048,16 @@ watchdog8: watchdog at 23f0000 {
 		/* reserved for MAIN_R5F1_1 */
 		status = "reserved";
 	};
+
+	gpu: gpu at 4e20000000 {
+		compatible = "ti,j721s2-gpu", "img,img-bxs-4-64", "img,img-rogue";
+		reg = <0x4e 0x20000000 0x00 0x80000>;
+		clocks = <&k3_clks 130 1>;
+		clock-names = "core";
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>,
+				<&k3_pds 373 TI_SCI_PD_EXCLUSIVE>;
+		power-domain-names = "a", "b";
+		dma-coherent;
+	};
 };

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:36 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:36 +0000
Subject: [PATCH v3 12/18] drm/imagination: Use callbacks for fw irq
 handling
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-12-143b3dbef02f@imgtec.com>

This allows for more versatility in checking and clearing firmware
registers used for interrupt handling.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-14-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-14-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h  | 18 +++++++++++++
 drivers/gpu/drm/imagination/pvr_fw.h      | 45 +++++++++----------------------
 drivers/gpu/drm/imagination/pvr_fw_meta.c | 22 ++++++++++-----
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 22 ++++++++++-----
 4 files changed, 63 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 12bf0b9e5bfb48ef9e5ed9faa44e0896b7555f49..eb5da8c7040fc9e9751f433279cb0c92fd4d1336 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -739,4 +739,22 @@ pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
 					      __union_size, __member_size);  \
 	})
 
+/*
+ * These utility functions should more properly be placed in pvr_fw.h, but that
+ * would cause a dependency cycle between that header and this one. Since
+ * they're primarily used in pvr_device.c, let's put them in here for now.
+ */
+
+static __always_inline bool
+pvr_fw_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_dev->fw_dev.defs->irq_pending(pvr_dev);
+}
+
+static __always_inline void
+pvr_fw_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_dev->fw_dev.defs->irq_clear(pvr_dev);
+}
+
 #endif /* PVR_DEVICE_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 88ad713468ce3a1ee459b04dde5363c24791a4f1..ab69f40a7fbc6304171f16dd16d825a68b0362a5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -167,29 +167,22 @@ struct pvr_fw_defs {
 	int (*wrapper_init)(struct pvr_device *pvr_dev);
 
 	/**
-	 * @irq: FW Interrupt information.
+	 * @irq_pending: Check interrupt status register for pending interrupts.
 	 *
-	 * Those are processor dependent, and should be initialized by the
-	 * processor backend in pvr_fw_funcs::init().
+	 * @pvr_dev: Target PowerVR device.
+	 *
+	 * This function is mandatory.
 	 */
-	struct {
-		/** @status_reg: FW interrupt status register. */
-		u32 status_reg;
+	bool (*irq_pending)(struct pvr_device *pvr_dev);
 
-		/**
-		 * @clear_reg: FW interrupt clear register.
-		 *
-		 * If @status_reg == @clear_reg, we clear by write a bit to zero,
-		 * otherwise we clear by writing a bit to one.
-		 */
-		u32 clear_reg;
-
-		/** @status_mask: Bitmask of events to listen for in the status_reg. */
-		u32 status_mask;
-
-		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
-		u32 clear_mask;
-	} irq;
+	/**
+	 * @irq_clear: Clear pending interrupts.
+	 *
+	 * @pvr_dev: Target PowerVR device.
+	 *
+	 * This function is mandatory.
+	 */
+	void (*irq_clear)(struct pvr_device *pvr_dev);
 
 	/**
 	 * @has_fixed_data_addr: Specify whether the firmware fixed data must be loaded at the
@@ -390,18 +383,6 @@ struct pvr_fw_device {
 	} fw_objs;
 };
 
-#define pvr_fw_irq_read_reg(pvr_dev, name) \
-	pvr_cr_read32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg)
-
-#define pvr_fw_irq_write_reg(pvr_dev, name, value) \
-	pvr_cr_write32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg, value)
-
-#define pvr_fw_irq_pending(pvr_dev) \
-	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.status_mask)
-
-#define pvr_fw_irq_clear(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
-
 enum pvr_fw_processor_type {
 	PVR_FW_PROCESSOR_TYPE_META = 0,
 	PVR_FW_PROCESSOR_TYPE_MIPS,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index 4433b04e0adb3684b86a4e90f63d670a81ecd826..09de3a30b625013c190196e02074fe72d08629a6 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -531,6 +531,20 @@ pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 		     fw_obj->fw_mm_node.size);
 }
 
+static bool
+pvr_meta_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_META_SP_MSLVIRQSTATUS) &
+	       ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN;
+}
+
+static void
+pvr_meta_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_META_SP_MSLVIRQSTATUS,
+		       ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
+}
+
 const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.init = pvr_meta_init,
 	.fw_process = pvr_meta_fw_process,
@@ -538,11 +552,7 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.vm_unmap = pvr_meta_vm_unmap,
 	.get_fw_addr_with_offset = pvr_meta_get_fw_addr_with_offset,
 	.wrapper_init = pvr_meta_wrapper_init,
-	.irq = {
-		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
-		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
-	},
+	.irq_pending = pvr_meta_irq_pending,
+	.irq_clear = pvr_meta_irq_clear,
 	.has_fixed_data_addr = false,
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 2c3172841886b70eb7a9992ec3851f18adcad8d5..524a9bd0a20b64c509f5708cc61d93b4c864b835 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -227,6 +227,20 @@ pvr_mips_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
 	       ROGUE_FW_HEAP_MIPS_BASE;
 }
 
+static bool
+pvr_mips_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS) &
+	       ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN;
+}
+
+static void
+pvr_mips_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
+		       ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN);
+}
+
 const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.init = pvr_mips_init,
 	.fini = pvr_mips_fini,
@@ -235,11 +249,7 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.vm_unmap = pvr_vm_mips_unmap,
 	.get_fw_addr_with_offset = pvr_mips_get_fw_addr_with_offset,
 	.wrapper_init = pvr_mips_wrapper_init,
-	.irq = {
-		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
-		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
-		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
-		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
-	},
+	.irq_pending = pvr_mips_irq_pending,
+	.irq_clear = pvr_mips_irq_clear,
 	.has_fixed_data_addr = true,
 };

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:33 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:33 +0000
Subject: [PATCH v3 09/18] drm/imagination: Rename event_mask -> status_mask
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-9-143b3dbef02f@imgtec.com>

Now that enable_reg isn't used, rename the previously shared event_mask to
status_mask since it's only used with status_reg.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-11-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-11-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_fw.h      | 6 +++---
 drivers/gpu/drm/imagination/pvr_fw_meta.c | 2 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 29bae4bc244a243a6a95bcf838d924060cc043e2..eead744835726712622d5aba9b3480fe264a089f 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -199,8 +199,8 @@ struct pvr_fw_defs {
 		 */
 		u32 clear_reg;
 
-		/** @event_mask: Bitmask of events to listen for in the status_reg. */
-		u32 event_mask;
+		/** @status_mask: Bitmask of events to listen for in the status_reg. */
+		u32 status_mask;
 
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
 		u32 clear_mask;
@@ -404,7 +404,7 @@ struct pvr_fw_device {
 	pvr_cr_write32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg, value)
 
 #define pvr_fw_irq_pending(pvr_dev) \
-	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.event_mask)
+	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.status_mask)
 
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index 76b24ad9aa221b6a384dc7b55ed2e78d2e761550..cf86701ca8f14920329ccb4c2811424b0c394b14 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -548,7 +548,7 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.irq = {
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.event_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
+		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
 		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
 	},
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index c810a67eeecf1016064e76baf534e31a44c859b5..f195c602bb112066e88210d0106cb5ffc0a9abc6 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -245,7 +245,7 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.irq = {
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
-		.event_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
+		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
 		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
 	},
 };

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:32 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:32 +0000
Subject: [PATCH v3 08/18] drm/imagination: Remove firmware enable_reg
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-8-143b3dbef02f@imgtec.com>

After a previous commit ("drm/imagination: Mask GPU IRQs in threaded
handler"), this register is now only used to enable firmware interrupts at
start-of-day. This is, however, unnecessary since they are enabled by
default.

In addition, the soon-to-be-added RISC-V firmware processors do not have
an equivalent register.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Reference a different commit removing use of enable/disable ops.
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-10-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-10-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.c  |  1 -
 drivers/gpu/drm/imagination/pvr_fw.h      | 11 +----------
 drivers/gpu/drm/imagination/pvr_fw_meta.c |  1 -
 drivers/gpu/drm/imagination/pvr_fw_mips.c |  1 -
 4 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index b1594dd3ed5997bd9510b1444aef2c6f0d7cfd76..ef011e53e61527f5847c22d7ffd1721dded16516 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -311,7 +311,6 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 
 	/* Clear any pending events before requesting the IRQ line. */
 	pvr_fw_irq_clear(pvr_dev);
-	pvr_fw_irq_enable(pvr_dev);
 	pvr_device_safety_irq_clear(pvr_dev);
 
 	/*
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index b7966bd574a924862b7877c175fa2b5d757d89db..29bae4bc244a243a6a95bcf838d924060cc043e2 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -188,9 +188,6 @@ struct pvr_fw_defs {
 	 * processor backend in pvr_fw_funcs::init().
 	 */
 	struct {
-		/** @enable_reg: FW interrupt enable register. */
-		u32 enable_reg;
-
 		/** @status_reg: FW interrupt status register. */
 		u32 status_reg;
 
@@ -202,7 +199,7 @@ struct pvr_fw_defs {
 		 */
 		u32 clear_reg;
 
-		/** @event_mask: Bitmask of events to listen for. */
+		/** @event_mask: Bitmask of events to listen for in the status_reg. */
 		u32 event_mask;
 
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
@@ -412,12 +409,6 @@ struct pvr_fw_device {
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
 
-#define pvr_fw_irq_enable(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, enable, (pvr_dev)->fw_dev.defs->irq.event_mask)
-
-#define pvr_fw_irq_disable(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, enable, 0)
-
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
 
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index c39beb70c3173ebdab13b4e810ce5d9a3419f0ba..76b24ad9aa221b6a384dc7b55ed2e78d2e761550 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -546,7 +546,6 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.wrapper_init = pvr_meta_wrapper_init,
 	.has_fixed_data_addr = pvr_meta_has_fixed_data_addr,
 	.irq = {
-		.enable_reg = ROGUE_CR_META_SP_MSLVIRQENABLE,
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.event_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 0bed0257e2ab75f66d8b8966b2ceac6342396fb5..c810a67eeecf1016064e76baf534e31a44c859b5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -243,7 +243,6 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.wrapper_init = pvr_mips_wrapper_init,
 	.has_fixed_data_addr = pvr_mips_has_fixed_data_addr,
 	.irq = {
-		.enable_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_ENABLE,
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
 		.event_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,

-- 
2.48.1



From geert+renesas at glider.be  Mon Mar 10 06:12:20 2025
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Mon, 10 Mar 2025 14:12:20 +0100
Subject: [PATCH] ARM: shmobile: smp: Enforce shmobile_smp_* alignment
Message-ID: <c499234d559a0d95ad9472883e46077311051cd8.1741612208.git.geert+renesas@glider.be>

When the addresses of the shmobile_smp_mpidr, shmobile_smp_fn, and
shmobile_smp_arg variables are not multiples of 4 bytes, secondary CPU
bring-up fails:

    smp: Bringing up secondary CPUs ...
    CPU1: failed to come online
    CPU2: failed to come online
    CPU3: failed to come online
    smp: Brought up 1 node, 1 CPU

Fix this by adding the missing alignment directive.

Fixes: 4e960f52fce16a3b ("ARM: shmobile: Move shmobile_smp_{mpidr, fn, arg}[] from .text to .bss")
Closes: https://lore.kernel.org/r/CAMuHMdU=QR-JLgEHKWpsr6SbaZRc-Hz9r91JfpP8c3n2G-OjqA at mail.gmail.com
Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
To be queued in renesas-fixes-for-v6.14.
---
 arch/arm/mach-shmobile/headsmp.S | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index a956b489b6ea12ca..2bc7e73a8582d2b3 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -136,6 +136,7 @@ ENDPROC(shmobile_smp_sleep)
 	.long	shmobile_smp_arg - 1b
 
 	.bss
+	.align	2
 	.globl	shmobile_smp_mpidr
 shmobile_smp_mpidr:
 	.space	NR_CPUS * 4
-- 
2.43.0



From maz at kernel.org  Mon Mar 10 06:13:21 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 13:13:21 +0000
Subject: [PATCH v3 00/14] KVM: arm64: FEAT_PMUv3 on Apple hardware
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <86zfhtni4u.wl-maz@kernel.org>

On Wed, 05 Mar 2025 20:26:27 +0000,
Oliver Upton <oliver.upton at linux.dev> wrote:
> 
> Hopefully close to the last spin, this time addressing Marc's comments
> on v2.
> 
> Full details found in the v1 cover letter.
> 
> v1: https://lore.kernel.org/kvmarm/20241217212048.3709204-1-oliver.upton at linux.dev/
> v2: https://lore.kernel.org/kvmarm/20250203183111.191519-1-oliver.upton at linux.dev/
> 
> v2 -> v3:
>  - Reorder and restructure patches to include map_pmuv3_event()
>    definition w/ KVM usage.
>  - Disallow events that lack a valid PMUv3 -> HW mapping
>  - Various minor fixes/typos
> 
> Oliver Upton (14):
>   drivers/perf: apple_m1: Refactor event select/filter configuration
>   drivers/perf: apple_m1: Support host/guest event filtering
>   KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
>   KVM: arm64: Always support SW_INCR PMU event
>   KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
>   KVM: arm64: Drop kvm_arm_pmu_available static key
>   KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
>   KVM: arm64: Move PMUVer filtering into KVM code
>   KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
>   KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
>   KVM: arm64: Remap PMUv3 events onto hardware
>   drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
>   KVM: arm64: Provide 1 event counter on IMPDEF hardware
>   arm64: Enable IMP DEF PMUv3 traps on Apple M*
> 
>  arch/arm64/include/asm/apple_m1_pmu.h   |   1 +
>  arch/arm64/include/asm/cpucaps.h        |   2 +
>  arch/arm64/include/asm/cpufeature.h     |  28 +----
>  arch/arm64/kernel/cpu_errata.c          |  44 ++++++++
>  arch/arm64/kernel/cpufeature.c          |  28 +++++
>  arch/arm64/kernel/image-vars.h          |   5 -
>  arch/arm64/kvm/arm.c                    |   4 +-
>  arch/arm64/kvm/hyp/include/hyp/switch.h |   4 +-
>  arch/arm64/kvm/hyp/vhe/switch.c         |  22 ++++
>  arch/arm64/kvm/pmu-emul.c               | 138 +++++++++++++++++-------
>  arch/arm64/kvm/pmu.c                    |  10 +-
>  arch/arm64/tools/cpucaps                |   2 +
>  drivers/perf/apple_m1_cpu_pmu.c         | 101 +++++++++++++----
>  include/kvm/arm_pmu.h                   |  12 +--
>  include/linux/perf/arm_pmu.h            |   4 +
>  15 files changed, 301 insertions(+), 104 deletions(-)
> 
> 
> base-commit: 0ad2507d5d93f39619fc42372c347d6006b64319

I'm quite happy with the way this looks now (well, apart from patch
#9, but that's not something you can fix...).

Reviewed-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From alexandre.torgue at foss.st.com  Mon Mar 10 06:12:21 2025
From: alexandre.torgue at foss.st.com (Alexandre TORGUE)
Date: Mon, 10 Mar 2025 14:12:21 +0100
Subject: [PATCH v2] ARM: dts: stm32: use IRQ_TYPE_EDGE_FALLING on
 stm32mp157c-dk2
In-Reply-To: <20250310122402.8795-1-dario.binacchi@amarulasolutions.com>
References: <20250310122402.8795-1-dario.binacchi@amarulasolutions.com>
Message-ID: <37d0b2f0-05c9-4e52-9fa9-d73ed0c56ec0@foss.st.com>

Hi Dario

On 3/10/25 13:23, Dario Binacchi wrote:
> Replace the number 2 with the appropriate numerical constant defined in
> dt-bindings/interrupt-controller/irq.h.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> Reviewed-by: Antonio Borneo <antonio.borneo at foss.st.com>
> 
> ---
> 
> Changes in v2:
> - Drop inclusion of dt-bindings/interrupt-controller/irq.h header
> - Add Reviewed-by tag of Antonio Borneo
> 
>   arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> index 5f9c0160a9c4..324f7bb988d1 100644
> --- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> @@ -67,7 +67,7 @@ &i2c1 {
>   	touchscreen at 38 {
>   		compatible = "focaltech,ft6236";
>   		reg = <0x38>;
> -		interrupts = <2 2>;
> +		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
>   		interrupt-parent = <&gpiof>;
>   		touchscreen-size-x = <480>;
>   		touchscreen-size-y = <800>;

Applied on stm32-next.

Thanks
Alex


From geert at linux-m68k.org  Mon Mar 10 06:15:58 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 10 Mar 2025 14:15:58 +0100
Subject: [PATCH 2/2] of: Warn when of_property_read_bool() is used on
 non-boolean properties
In-Reply-To: <CAMuHMdWZsQ9UbwVub=36P_2DCPEN0aORz9FxCbivKkOyeWkuww@mail.gmail.com>
References: <20250109-dt-type-warnings-v1-0-0150e32e716c@kernel.org>
 <20250109-dt-type-warnings-v1-2-0150e32e716c@kernel.org> <CAMuHMdU=QR-JLgEHKWpsr6SbaZRc-Hz9r91JfpP8c3n2G-OjqA@mail.gmail.com>
 <CAL_JsqJNgxLgvB502Bk=5aMeP2rY6KVL_FykeSyN1tsDRXi9cA@mail.gmail.com> <CAMuHMdWZsQ9UbwVub=36P_2DCPEN0aORz9FxCbivKkOyeWkuww@mail.gmail.com>
Message-ID: <CAMuHMdUHsTYjamDkyoe_CwJhXbf7LpAPk+Dazd4wChEmfcuYPQ@mail.gmail.com>

On Wed, 15 Jan 2025 at 12:20, Geert Uytterhoeven <geert at linux-m68k.org> wrote:
> On Tue, Jan 14, 2025 at 8:19?PM Rob Herring <robh at kernel.org> wrote:
> > On Tue, Jan 14, 2025 at 12:35?PM Geert Uytterhoeven
> > <geert at linux-m68k.org> wrote:
> > > On Thu, Jan 9, 2025 at 8:42?PM Rob Herring (Arm) <robh at kernel.org> wrote:
> > > > The use of of_property_read_bool() for non-boolean properties is
> > > > deprecated. The primary use of it was to test property presence, but
> > > > that has been replaced in favor of of_property_present(). With those
> > > > uses now fixed, add a warning to discourage new ones.
> > > >
> > > > Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> > >
> > > Thanks for your patch, which is now commit c141ecc3cecd7647 ("of:
> > > Warn when of_property_read_bool() is used on non-boolean properties")
> > > in dt-rh/for-next.
> > >
> > > I have bisected a failure in secondary CPU bring-up on R-Car H1 (quad
> > > Cortex-A9 MPCore) to this commit:
> > >
> > >      Detected Renesas R-Car Gen1 r8a7779 ES1.0
> > >      smp: Bringing up secondary CPUs ...
> > >     -CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
> > >     -CPU1: Spectre v2: using BPIALL workaround
> > >     -CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
> > >     -CPU2: Spectre v2: using BPIALL workaround
> > >     -CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
> > >     -CPU3: Spectre v2: using BPIALL workaround
> > >     -smp: Brought up 1 node, 4 CPUs
> > >     -SMP: Total of 4 processors activated (2000.00 BogoMIPS).
> > >     +CPU1: failed to come online
> > >     +CPU2: failed to come online
> > >     +CPU3: failed to come online
> > >     +smp: Brought up 1 node, 1 CPU
> > >     +SMP: Total of 1 processors activated (500.00 BogoMIPS).
> > >      CPU: All CPU(s) started in SVC mode.
> > >
> > > Reverting this commit on top of my work tree fixes the issue, too.
> > > However, I do not see how this commit could impact CPU bring-up?
> >
> > Strange. Perhaps the of_property_read_bool was inlined into some
> > special section before?
>
> I re-added the old inline of_property_read_bool(), but with a different
> name.  CPU bringup starts working again if I replace at least one call
> to of_property_read_bool() in arch/arm/mm/cache-l2x0.c:aurora_of_parse()
> by a call to the inline variant, or even if I just add
>
>     pr_info("xf_property_read_bool(np, \"wt-override\") = %d\n",
> xf_property_read_bool(np, "wt-override"));
>
> to that function. Note that that function is not called at all on my platform.
>
> This small change causes quite some reordering in arch/arm/mm/cache-l2x0.s,
> so it looks like a layout issue. More analysis will follow...

The assembler SMP bring-up code for Renesas SoCs lacked an alignment
directive.  I have posted a fix:
https://lore.kernel.org/r/CAMuHMdU=QR-JLgEHKWpsr6SbaZRc-Hz9r91JfpP8c3n2G-OjqA at mail.gmail.com

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From florian.fainelli at broadcom.com  Mon Mar 10 06:17:24 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 10 Mar 2025 06:17:24 -0700
Subject: [PATCH next] pinctrl: bcm281xx: Add missing assignment in
 bcm21664_pinctrl_lock_all()
In-Reply-To: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
References: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
Message-ID: <c55f5485-0a32-4745-98a0-d620e4a2c4f1@broadcom.com>



On 3/10/2025 3:48 AM, Dan Carpenter wrote:
> The next line checks if this regmap_write() failed, but it doesn't
> work because the assignment was accidentally left out.  Add the
> assignment.
> 
> Fixes: 60d69769c851 ("pinctrl: bcm281xx: Add support for BCM21664 pinmux")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>

Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
-- 
Florian



From ltykernel at gmail.com  Mon Mar 10 06:17:12 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 21:17:12 +0800
Subject: [PATCH v5 02/10] x86/mshyperv: Add support for extended Hyper-V features
In-Reply-To: <1740611284-27506-3-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-3-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <CAMvTesBG_=Vzwm5DtMcC29DELWvMEhC+XFZhZ=9p7WdiJBSK8Q@mail.gmail.com>

On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> From: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
>
> Extend the "ms_hyperv_info" structure to include a new field,
> "ext_features", for capturing extended Hyper-V features.
> Update the "ms_hyperv_init_platform" function to retrieve these features
> using the cpuid instruction and include them in the informational output.
>
> Signed-off-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---

Reviewed-by: Tianyu Lan <tiala at microsoft.com>

-- 
Thanks
Tianyu Lan


From matt.coster at imgtec.com  Mon Mar 10 06:10:24 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:24 +0000
Subject: [PATCH v3 00/18] Imagination BXS-4-64 MC1 GPU support
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>

This GPU is found in the TI AM68 family of SoCs, with initial support
added to the k3-j721s2 devicetree and tested on a TI SK-AM68 board.

A suitable firmware binary can currently be found in the IMG
linux-firmware repository[1] as powervr/rogue_36.53.104.796_v1.fw.

No new UAPI will be necessary for this platform as it is sufficiently
similar to the already supported AXE-1-16M.

UMD support is close to being complete. We're now able to pass >90% of
Vulkan conformance on our Mesa development branch. The compiler has been
undergoing a significant rework needed to accomodate the BXS-4-64, as
well as to make it more flexible to support additional Rogue GPUs going
forward. The first part of this rework landed in Mesa in [2], and more
MRs will follow in the coming weeks.

There are several dt-bindings changes at the beginning of this series.
We expect the result to be versatile enough to handle all Imagination
Rogue GPUs while being a strong foundation to build bindings for the
newer Volcanic architecture (for which we're currently developing
support).

The DTS changes at the end of the series are marked [DO NOT MERGE]. Once
the series is reviewed, we will request these be taken through the
relevant tree.

[1]: https://gitlab.freedesktop.org/imagination/linux-firmware/-/tree/powervr
[3]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258

---
Changes in v3:
- Reorder some patches to ensure the proper sequencing
- Update status of UMD support (cover)
- Don't use more specific compatible strings when not required (P1)
- Avoid ABI break by limiting new required properties to new compatible
  strings (P2)
- Move power domain changes to the patch in which they're used (P2/P5)
- Update register definitions (P3) [Thanks, Alessio!]
- Don't use more specific compatible strings when not required (P4)
- Enhanced commit messages (P4)
- Remove unnecessary example (P5)
- Add proper fixes for threaded IRQs (P6) [Thanks, Alessio!]
- Include fix for a separate IRQ issue (P7) [Thanks, Alessio!]
- Don't enable firmware debug module (was P13 in v2, also in P14)
- Change from a workaround to a regular codepath (P15)
- Drop platform overrides framework (was P18 in v2, also in P16)
- Mark DTS changes [DO NOT MERGE] (P17/P18)
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-0-3fd45d9fb0cf at imgtec.com

Changes in v2:
- Clarified justification for compatible strings (P1)
- Simplified clocks constraints (P2)
- Simplified power-domains constraints (P3/P4)
- Use normal reg syntax for 64-bit values (P8/P21)
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-0-4ed30e865892 at imgtec.com

---
Alessio Belle (3):
      drm/imagination: Update register defs for newer GPUs
      drm/imagination: Mask GPU IRQs in threaded handler
      drm/imagination: Handle Rogue safety event IRQs

Matt Coster (14):
      dt-bindings: gpu: img: Future-proofing enhancements
      dt-bindings: gpu: img: Add BXS-4-64 devicetree bindings
      drm/imagination: Use new generic compatible string
      drm/imagination: Add power domain control
      drm/imagination: Remove firmware enable_reg
      drm/imagination: Rename event_mask -> status_mask
      drm/imagination: Make has_fixed_data_addr a value
      drm/imagination: Use a lookup table for fw defs
      drm/imagination: Use callbacks for fw irq handling
      drm/imagination: Move ELF fw utils to common file
      drm/imagination: Use cached memory with dma_coherent
      drm/imagination: Add support for TI AM68 GPU
      [DO NOT MERGE] arm64: dts: ti: k3-am62: New GPU binding details
      [DO NOT MERGE] arm64: dts: ti: k3-j721s2: Add GPU node

Sarah Walker (1):
      drm/imagination: Add RISC-V firmware processor support

 .../devicetree/bindings/gpu/img,powervr-rogue.yaml |  77 +++++++++-
 arch/arm64/boot/dts/ti/k3-am62-main.dtsi           |   3 +-
 arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi         |  12 ++
 drivers/gpu/drm/imagination/Makefile               |   2 +
 drivers/gpu/drm/imagination/pvr_device.c           | 124 ++++++++++++++--
 drivers/gpu/drm/imagination/pvr_device.h           |  31 +++-
 drivers/gpu/drm/imagination/pvr_drv.c              |  16 ++
 drivers/gpu/drm/imagination/pvr_fw.c               |  28 +++-
 drivers/gpu/drm/imagination/pvr_fw.h               |  85 +++++------
 drivers/gpu/drm/imagination/pvr_fw_meta.c          |  23 +--
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  82 ++---------
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         | 163 +++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_fw_startstop.c     |  17 +++
 drivers/gpu/drm/imagination/pvr_fw_util.c          |  67 +++++++++
 drivers/gpu/drm/imagination/pvr_gem.c              |  10 +-
 drivers/gpu/drm/imagination/pvr_gem.h              |   6 +-
 drivers/gpu/drm/imagination/pvr_mmu.c              |   8 +-
 drivers/gpu/drm/imagination/pvr_power.c            | 114 ++++++++++++++
 drivers/gpu/drm/imagination/pvr_power.h            |   3 +
 drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h    | 153 ++++++++++++++++---
 drivers/gpu/drm/imagination/pvr_rogue_riscv.h      |  41 ++++++
 21 files changed, 886 insertions(+), 179 deletions(-)
---
base-commit: 10232dac98d3803ec4fcc0cd8a4d1bd2a09b3e18
change-id: 20241021-sets-bxs-4-64-patch-v1-44cdf9cc555f



From matt.coster at imgtec.com  Mon Mar 10 06:10:41 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:41 +0000
Subject: [PATCH DO NOT MERGE v3 17/18] arm64: dts: ti: k3-am62: New GPU
 binding details
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-17-143b3dbef02f@imgtec.com>

Use the new compatible string introduced earlier (in "dt-bindings: gpu:
img: More explicit compatible strings") and add a name to the single power
domain for this GPU (introduced in "dt-bindings: gpu: img: Power domain
details").

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-7-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-7-4ed30e865892 at imgtec.com
---
 arch/arm64/boot/dts/ti/k3-am62-main.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 7cd727d10a5f277e4b19189347e832b4b034b1a0..429fc5c957ceff16750786e0de1f9207c8b1b119 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -692,12 +692,13 @@ ospi0: spi at fc40000 {
 	};
 
 	gpu: gpu at fd00000 {
-		compatible = "ti,am62-gpu", "img,img-axe";
+		compatible = "ti,am62-gpu", "img,img-axe-1-16m", "img,img-rogue";
 		reg = <0x00 0x0fd00000 0x00 0x20000>;
 		clocks = <&k3_clks 187 0>;
 		clock-names = "core";
 		interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 		power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+		power-domain-names = "a";
 	};
 
 	cpsw3g: ethernet at 8000000 {

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:26 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:26 +0000
Subject: [PATCH v3 02/18] dt-bindings: gpu: img: Add BXS-4-64 devicetree
 bindings
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>

Unlike AXE-1-16M, BXS-4-64 uses two power domains.

Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
integration in the TI k3-j721s2.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Include adding the second power domain so it's in context
- Remove unnecessary example
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
Changes in v2:
- Use normal reg syntax for 64-bit values
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
---
 .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 34 +++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 5c16b2881447c9cda78e5bb46569e2f675d740c4..d9409d33154d429019776ddbf9d123b33f8c9740 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -18,6 +18,11 @@ properties:
               - ti,am62-gpu
           - const: img,img-axe-1-16m
           - const: img,img-rogue
+      - items:
+          - enum:
+              - ti,j721s2-gpu
+          - const: img,img-bxs-4-64
+          - const: img,img-rogue
 
       # This legacy combination of compatible strings was introduced early on
       # before the more specific GPU identifiers were used.
@@ -49,6 +54,7 @@ properties:
   power-domain-names:
     items:
       - const: a
+      - const: b
 
   dma-coherent: true
 
@@ -74,12 +80,38 @@ allOf:
         - power-domains
         - power-domain-names
 
+  # Cores with one power domain
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: img,img-axe-1-16m
+    then:
+      properties:
+        power-domain-names:
+          minItems: 1
+          maxItems: 1
+
+  # Cores with two power domains
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: img,img-bxs-4-64
+    then:
+      properties:
+        power-domain-names:
+          minItems: 2
+          maxItems: 2
+
   # Vendor integrations using a single clock domain
   - if:
       properties:
         compatible:
           contains:
-            const: ti,am62-gpu
+            anyOf:
+              - const: ti,am62-gpu
+              - const: ti,j721s2-gpu
     then:
       properties:
         clocks:

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:37 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:37 +0000
Subject: [PATCH v3 13/18] drm/imagination: Move ELF fw utils to common file
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-13-143b3dbef02f@imgtec.com>

Currently only MIPS firmware processors use ELF-formatted firmware. When
adding support for RISC-V firmware processors, it will be useful to have
ELF handling functions ready to go.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-16-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-16-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/Makefile      |  1 +
 drivers/gpu/drm/imagination/pvr_fw.h      |  5 +++
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 59 +--------------------------
 drivers/gpu/drm/imagination/pvr_fw_util.c | 67 +++++++++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile
index 9bc6a3884c2239e44265f3cdebee149841b270de..077e4762c7c383b6e339da1584c3865d830ef8d6 100644
--- a/drivers/gpu/drm/imagination/Makefile
+++ b/drivers/gpu/drm/imagination/Makefile
@@ -16,6 +16,7 @@ powervr-y := \
 	pvr_fw_mips.o \
 	pvr_fw_startstop.o \
 	pvr_fw_trace.o \
+	pvr_fw_util.o \
 	pvr_gem.o \
 	pvr_hwrt.o \
 	pvr_job.o \
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index ab69f40a7fbc6304171f16dd16d825a68b0362a5..e120eae06bf78633b5bae79a77adac63aa5e06d3 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -478,4 +478,9 @@ pvr_fw_object_get_fw_addr(struct pvr_fw_object *fw_obj, u32 *fw_addr_out)
 	pvr_fw_object_get_fw_addr_offset(fw_obj, 0, fw_addr_out);
 }
 
+/* Util functions defined in pvr_fw_util.c. These are intended for use in pvr_fw_<arch>.c files. */
+int
+pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
+				  u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr);
+
 #endif /* PVR_FW_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 524a9bd0a20b64c509f5708cc61d93b4c864b835..7f341ceb0661c61ac059654faeec91e149036467 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -8,7 +8,6 @@
 #include "pvr_rogue_mips.h"
 #include "pvr_vm_mips.h"
 
-#include <linux/elf.h>
 #include <linux/err.h>
 #include <linux/types.h>
 
@@ -16,60 +15,6 @@
 #define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */
 #define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M
 
-/**
- * process_elf_command_stream() - Process ELF firmware image and populate
- *                                firmware sections
- * @pvr_dev: Device pointer.
- * @fw: Pointer to firmware image.
- * @fw_code_ptr: Pointer to FW code section.
- * @fw_data_ptr: Pointer to FW data section.
- * @fw_core_code_ptr: Pointer to FW coremem code section.
- * @fw_core_data_ptr: Pointer to FW coremem data section.
- *
- * Returns :
- *  * 0 on success, or
- *  * -EINVAL on any error in ELF command stream.
- */
-static int
-process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
-			   u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr)
-{
-	struct elf32_hdr *header = (struct elf32_hdr *)fw;
-	struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff);
-	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
-	u32 entry;
-	int err;
-
-	for (entry = 0; entry < header->e_phnum; entry++, program_header++) {
-		void *write_addr;
-
-		/* Only consider loadable entries in the ELF segment table */
-		if (program_header->p_type != PT_LOAD)
-			continue;
-
-		err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr,
-					      program_header->p_memsz, fw_code_ptr, fw_data_ptr,
-					      fw_core_code_ptr, fw_core_data_ptr, &write_addr);
-		if (err) {
-			drm_err(drm_dev,
-				"Addr 0x%x (size: %d) not found in any firmware segment",
-				program_header->p_vaddr, program_header->p_memsz);
-			return err;
-		}
-
-		/* Write to FW allocation only if available */
-		if (write_addr) {
-			memcpy(write_addr, fw + program_header->p_offset,
-			       program_header->p_filesz);
-
-			memset((u8 *)write_addr + program_header->p_filesz, 0,
-			       program_header->p_memsz - program_header->p_filesz);
-		}
-	}
-
-	return 0;
-}
-
 static int
 pvr_mips_init(struct pvr_device *pvr_dev)
 {
@@ -100,8 +45,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	u32 page_nr;
 	int err;
 
-	err = process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr, fw_core_code_ptr,
-					 fw_core_data_ptr);
+	err = pvr_fw_process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr,
+						fw_core_code_ptr, fw_core_data_ptr);
 	if (err)
 		return err;
 
diff --git a/drivers/gpu/drm/imagination/pvr_fw_util.c b/drivers/gpu/drm/imagination/pvr_fw_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bc8a5c48e9b0eed2045607ab2cfed80a60a32b5
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_fw_util.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#include "pvr_device.h"
+#include "pvr_fw.h"
+
+#include <drm/drm_device.h>
+#include <drm/drm_print.h>
+
+#include <linux/elf.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+/**
+ * pvr_fw_process_elf_command_stream() - Process ELF firmware image and populate
+ *                                       firmware sections
+ * @pvr_dev: Device pointer.
+ * @fw: Pointer to firmware image.
+ * @fw_code_ptr: Pointer to FW code section.
+ * @fw_data_ptr: Pointer to FW data section.
+ * @fw_core_code_ptr: Pointer to FW coremem code section.
+ * @fw_core_data_ptr: Pointer to FW coremem data section.
+ *
+ * Returns :
+ *  * 0 on success, or
+ *  * -EINVAL on any error in ELF command stream.
+ */
+int
+pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw,
+				  u8 *fw_code_ptr, u8 *fw_data_ptr,
+				  u8 *fw_core_code_ptr, u8 *fw_core_data_ptr)
+{
+	struct elf32_hdr *header = (struct elf32_hdr *)fw;
+	struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff);
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
+	u32 entry;
+	int err;
+
+	for (entry = 0; entry < header->e_phnum; entry++, program_header++) {
+		void *write_addr;
+
+		/* Only consider loadable entries in the ELF segment table */
+		if (program_header->p_type != PT_LOAD)
+			continue;
+
+		err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr,
+					      program_header->p_memsz, fw_code_ptr, fw_data_ptr,
+					      fw_core_code_ptr, fw_core_data_ptr, &write_addr);
+		if (err) {
+			drm_err(drm_dev,
+				"Addr 0x%x (size: %d) not found in any firmware segment",
+				program_header->p_vaddr, program_header->p_memsz);
+			return err;
+		}
+
+		/* Write to FW allocation only if available */
+		if (write_addr) {
+			memcpy(write_addr, fw + program_header->p_offset,
+			       program_header->p_filesz);
+
+			memset((u8 *)write_addr + program_header->p_filesz, 0,
+			       program_header->p_memsz - program_header->p_filesz);
+		}
+	}
+
+	return 0;
+}

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:34 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:34 +0000
Subject: [PATCH v3 10/18] drm/imagination: Make has_fixed_data_addr a value
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-10-143b3dbef02f@imgtec.com>

This is currently a callback function which takes no parameters; there's
no reason for this so let's make it a straightforward value in pvr_fw_defs.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-11-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-12-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_fw.c      |  2 +-
 drivers/gpu/drm/imagination/pvr_fw.h      | 23 ++++++++---------------
 drivers/gpu/drm/imagination/pvr_fw_meta.c |  8 +-------
 drivers/gpu/drm/imagination/pvr_fw_mips.c |  8 +-------
 4 files changed, 11 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index 9147c70edc0ef4e86d0b24c3568a43efbafb6bd8..c331d6001550a0b1d9cfbda2cd6629533ab6ee33 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -666,7 +666,7 @@ pvr_fw_process(struct pvr_device *pvr_dev)
 		return PTR_ERR(fw_code_ptr);
 	}
 
-	if (pvr_dev->fw_dev.defs->has_fixed_data_addr()) {
+	if (pvr_dev->fw_dev.defs->has_fixed_data_addr) {
 		u32 base_addr = private_data->base_addr & pvr_dev->fw_dev.fw_heap_info.offset_mask;
 
 		fw_data_ptr =
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index eead744835726712622d5aba9b3480fe264a089f..180d310074e3585c641e540a9e2576b5ab2a5705 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -166,21 +166,6 @@ struct pvr_fw_defs {
 	 */
 	int (*wrapper_init)(struct pvr_device *pvr_dev);
 
-	/**
-	 * @has_fixed_data_addr:
-	 *
-	 * Called to check if firmware fixed data must be loaded at the address given by the
-	 * firmware layout table.
-	 *
-	 * This function is mandatory.
-	 *
-	 * Returns:
-	 *  * %true if firmware fixed data must be loaded at the address given by the firmware
-	 *    layout table.
-	 *  * %false otherwise.
-	 */
-	bool (*has_fixed_data_addr)(void);
-
 	/**
 	 * @irq: FW Interrupt information.
 	 *
@@ -205,6 +190,14 @@ struct pvr_fw_defs {
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
 		u32 clear_mask;
 	} irq;
+
+	/**
+	 * @has_fixed_data_addr: Specify whether the firmware fixed data must be loaded at the
+	 *                       address given by the firmware layout table.
+	 *
+	 * This value is mandatory.
+	 */
+	bool has_fixed_data_addr;
 };
 
 /**
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index cf86701ca8f14920329ccb4c2811424b0c394b14..4433b04e0adb3684b86a4e90f63d670a81ecd826 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -531,12 +531,6 @@ pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 		     fw_obj->fw_mm_node.size);
 }
 
-static bool
-pvr_meta_has_fixed_data_addr(void)
-{
-	return false;
-}
-
 const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.init = pvr_meta_init,
 	.fw_process = pvr_meta_fw_process,
@@ -544,11 +538,11 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.vm_unmap = pvr_meta_vm_unmap,
 	.get_fw_addr_with_offset = pvr_meta_get_fw_addr_with_offset,
 	.wrapper_init = pvr_meta_wrapper_init,
-	.has_fixed_data_addr = pvr_meta_has_fixed_data_addr,
 	.irq = {
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
 		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
 	},
+	.has_fixed_data_addr = false,
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index f195c602bb112066e88210d0106cb5ffc0a9abc6..2c3172841886b70eb7a9992ec3851f18adcad8d5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -227,12 +227,6 @@ pvr_mips_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
 	       ROGUE_FW_HEAP_MIPS_BASE;
 }
 
-static bool
-pvr_mips_has_fixed_data_addr(void)
-{
-	return true;
-}
-
 const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.init = pvr_mips_init,
 	.fini = pvr_mips_fini,
@@ -241,11 +235,11 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.vm_unmap = pvr_vm_mips_unmap,
 	.get_fw_addr_with_offset = pvr_mips_get_fw_addr_with_offset,
 	.wrapper_init = pvr_mips_wrapper_init,
-	.has_fixed_data_addr = pvr_mips_has_fixed_data_addr,
 	.irq = {
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
 		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
 		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
 	},
+	.has_fixed_data_addr = true,
 };

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:31 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:31 +0000
Subject: [PATCH v3 07/18] drm/imagination: Handle Rogue safety event IRQs
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-7-143b3dbef02f@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Extend interrupt handling logic to check for safety event IRQs, then clear
and handle them in the IRQ handler thread.

Safety events need to be checked and cleared with a different set of GPU
registers than those the IRQ handler has been using so far.

Only two safety events need to be handled on the host: FW fault (ECC error
correction or detection) and device watchdog timeout. Handling right now
simply consists of clearing any error and logging the event. If either of
these events results in an unrecoverable GPU or FW, the driver will
eventually attempt to recover from it e.g. via pvr_power_reset().

Note that Rogue GPUs may send interrupts to the host for all types of
safety events, not just the two above. For events not handled by the host,
clearing the associated interrupt is sufficient.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_device.c | 111 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/imagination/pvr_device.h |   3 +
 drivers/gpu/drm/imagination/pvr_fw.c     |   3 +
 3 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index b6ce936f07c8bb26d240e50b72a1d991dbe4b045..b1594dd3ed5997bd9510b1444aef2c6f0d7cfd76 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -146,9 +146,61 @@ static void pvr_device_process_active_queues(struct pvr_device *pvr_dev)
 	mutex_unlock(&pvr_dev->queues.lock);
 }
 
+static bool pvr_device_safety_irq_pending(struct pvr_device *pvr_dev)
+{
+	u32 events;
+
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	events = pvr_cr_read32(pvr_dev, ROGUE_CR_EVENT_STATUS);
+
+	return (events & ROGUE_CR_EVENT_STATUS_SAFETY_EN) != 0;
+}
+
+static void pvr_device_safety_irq_clear(struct pvr_device *pvr_dev)
+{
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	pvr_cr_write32(pvr_dev, ROGUE_CR_EVENT_CLEAR,
+		       ROGUE_CR_EVENT_CLEAR_SAFETY_EN);
+}
+
+static void pvr_device_handle_safety_events(struct pvr_device *pvr_dev)
+{
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
+	u32 events;
+
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	events = pvr_cr_read32(pvr_dev, ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE);
+
+	/* Handle only these events on the host and leave the rest to the FW. */
+	events &= ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__FAULT_FW_EN |
+		ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__WATCHDOG_TIMEOUT_EN;
+
+	pvr_cr_write32(pvr_dev, ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE, events);
+
+	if (events & ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__FAULT_FW_EN) {
+		u32 fault_fw = pvr_cr_read32(pvr_dev, ROGUE_CR_FAULT_FW_STATUS);
+
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FAULT_FW_CLEAR, fault_fw);
+
+		drm_info(drm_dev, "Safety event: FW fault (mask=0x%08x)\n", fault_fw);
+	}
+
+	if (events & ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__WATCHDOG_TIMEOUT_EN) {
+		/*
+		 * The watchdog timer is disabled by the driver so this event
+		 * should never be fired.
+		 */
+		drm_info(drm_dev, "Safety event: Watchdog timeout\n");
+	}
+}
+
 static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 {
 	struct pvr_device *pvr_dev = data;
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
 	irqreturn_t ret = IRQ_NONE;
 
 	/* We are in the threaded handler, we can keep dequeuing events until we
@@ -164,24 +216,76 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 			pvr_device_process_active_queues(pvr_dev);
 		}
 
-		pm_runtime_mark_last_busy(from_pvr_device(pvr_dev)->dev);
+		pm_runtime_mark_last_busy(drm_dev->dev);
 
 		ret = IRQ_HANDLED;
 	}
 
+	if (pvr_dev->has_safety_events) {
+		int err;
+
+		/*
+		 * Ensure the GPU is powered on since some safety events (such
+		 * as ECC faults) can happen outside of job submissions, which
+		 * are otherwise the only time a power reference is held.
+		 */
+		err = pvr_power_get(pvr_dev);
+		if (err) {
+			drm_err_ratelimited(drm_dev,
+					    "%s: could not take power reference (%d)\n",
+					    __func__, err);
+			return ret;
+		}
+
+		while (pvr_device_safety_irq_pending(pvr_dev)) {
+			pvr_device_safety_irq_clear(pvr_dev);
+			pvr_device_handle_safety_events(pvr_dev);
+
+			ret = IRQ_HANDLED;
+		}
+
+		pvr_power_put(pvr_dev);
+	}
+
 	return ret;
 }
 
 static irqreturn_t pvr_device_irq_handler(int irq, void *data)
 {
 	struct pvr_device *pvr_dev = data;
+	bool safety_irq_pending = false;
+
+	if (pvr_dev->has_safety_events)
+		safety_irq_pending = pvr_device_safety_irq_pending(pvr_dev);
 
-	if (!pvr_fw_irq_pending(pvr_dev))
+	if (!pvr_fw_irq_pending(pvr_dev) && !safety_irq_pending)
 		return IRQ_NONE; /* Spurious IRQ - ignore. */
 
 	return IRQ_WAKE_THREAD;
 }
 
+static void pvr_device_safety_irq_init(struct pvr_device *pvr_dev)
+{
+	u32 num_ecc_rams = 0;
+
+	/*
+	 * Safety events are an optional feature of the RogueXE platform. They
+	 * are only enabled if at least one of ECC memory or the watchdog timer
+	 * are present in HW. While safety events can be generated by other
+	 * systems, that will never happen if the above mentioned hardware is
+	 * not present.
+	 */
+	if (!PVR_HAS_FEATURE(pvr_dev, roguexe)) {
+		pvr_dev->has_safety_events = false;
+		return;
+	}
+
+	PVR_FEATURE_VALUE(pvr_dev, ecc_rams, &num_ecc_rams);
+
+	pvr_dev->has_safety_events =
+		num_ecc_rams > 0 || PVR_HAS_FEATURE(pvr_dev, watchdog_timer);
+}
+
 /**
  * pvr_device_irq_init() - Initialise IRQ required by a PowerVR device
  * @pvr_dev: Target PowerVR device.
@@ -199,6 +303,8 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 
 	init_waitqueue_head(&pvr_dev->kccb.rtn_q);
 
+	pvr_device_safety_irq_init(pvr_dev);
+
 	pvr_dev->irq = platform_get_irq(plat_dev, 0);
 	if (pvr_dev->irq < 0)
 		return pvr_dev->irq;
@@ -206,6 +312,7 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 	/* Clear any pending events before requesting the IRQ line. */
 	pvr_fw_irq_clear(pvr_dev);
 	pvr_fw_irq_enable(pvr_dev);
+	pvr_device_safety_irq_clear(pvr_dev);
 
 	/*
 	 * The ONESHOT flag ensures IRQs are masked while the thread handler is
diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 2dd8a8885fe07078896d669d822525fb2b7bab51..6c01d96657de6dc3904ef5ca28365f06cfe0f40b 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -308,6 +308,9 @@ struct pvr_device {
 	 *  struct pvr_file.
 	 */
 	spinlock_t ctx_list_lock;
+
+	/** @has_safety_events: Whether this device can raise safety events. */
+	bool has_safety_events;
 };
 
 /**
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index 3debc9870a82ae7de9b2dc173df84c466c137bb3..9147c70edc0ef4e86d0b24c3568a43efbafb6bd8 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -441,6 +441,9 @@ fw_runtime_cfg_init(void *cpu_ptr, void *priv)
 	runtime_cfg->active_pm_latency_persistant = true;
 	WARN_ON(PVR_FEATURE_VALUE(pvr_dev, num_clusters,
 				  &runtime_cfg->default_dusts_num_init) != 0);
+
+	/* Keep watchdog timer disabled. */
+	runtime_cfg->wdg_period_us = 0;
 }
 
 static void

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:39 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:39 +0000
Subject: [PATCH v3 15/18] drm/imagination: Use cached memory with
 dma_coherent
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-15-143b3dbef02f@imgtec.com>

The TI k3-j721s2 platform does not allow us to use uncached memory
(which is what the driver currently does) without disabling cache snooping
on the AXI ACE-Lite interface, which would be too much of a performance
hit.

Given the platform is dma-coherent, we can simply force all
device-accessible memory allocations through the CPU cache. In fact, this
can be done whenever the dma_coherent attribute is present.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Change from a workaround to a regular codepath
- Add missing <linux/property.h> include
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-19-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-19-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_gem.c | 10 +++++++---
 drivers/gpu/drm/imagination/pvr_gem.h |  6 ++++--
 drivers/gpu/drm/imagination/pvr_mmu.c |  8 +++++++-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_gem.c b/drivers/gpu/drm/imagination/pvr_gem.c
index 6a8c81fe8c1e85c2130a4fe90fce35b6a2be35aa..9467cd563339cd5bf62ff92edba115ed5721ee76 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.c
+++ b/drivers/gpu/drm/imagination/pvr_gem.c
@@ -19,6 +19,7 @@
 #include <linux/log2.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
+#include <linux/property.h>
 #include <linux/refcount.h>
 #include <linux/scatterlist.h>
 
@@ -336,6 +337,7 @@ struct drm_gem_object *pvr_gem_create_object(struct drm_device *drm_dev, size_t
 struct pvr_gem_object *
 pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 {
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
 	struct drm_gem_shmem_object *shmem_obj;
 	struct pvr_gem_object *pvr_obj;
 	struct sg_table *sgt;
@@ -345,7 +347,10 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 	if (size == 0 || !pvr_gem_object_flags_validate(flags))
 		return ERR_PTR(-EINVAL);
 
-	shmem_obj = drm_gem_shmem_create(from_pvr_device(pvr_dev), size);
+	if (device_get_dma_attr(drm_dev->dev) == DEV_DMA_COHERENT)
+		flags |= PVR_BO_CPU_CACHED;
+
+	shmem_obj = drm_gem_shmem_create(drm_dev, size);
 	if (IS_ERR(shmem_obj))
 		return ERR_CAST(shmem_obj);
 
@@ -360,8 +365,7 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 		goto err_shmem_object_free;
 	}
 
-	dma_sync_sgtable_for_device(shmem_obj->base.dev->dev, sgt,
-				    DMA_BIDIRECTIONAL);
+	dma_sync_sgtable_for_device(drm_dev->dev, sgt, DMA_BIDIRECTIONAL);
 
 	/*
 	 * Do this last because pvr_gem_object_zero() requires a fully
diff --git a/drivers/gpu/drm/imagination/pvr_gem.h b/drivers/gpu/drm/imagination/pvr_gem.h
index e0e5ea509a2e88a437b8d241ea13c7bab2220f56..c99f30cc62088c030bd8a806df79b738b62a968f 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.h
+++ b/drivers/gpu/drm/imagination/pvr_gem.h
@@ -44,8 +44,10 @@ struct pvr_file;
  * Bits not defined anywhere are "undefined".
  *
  * CPU mapping options
- *    :PVR_BO_CPU_CACHED: By default, all GEM objects are mapped write-combined on the CPU. Set this
- *       flag to override this behaviour and map the object cached.
+ *    :PVR_BO_CPU_CACHED: By default, all GEM objects are mapped write-combined on the CPU. Set
+ *       this flag to override this behaviour and map the object cached. If the dma_coherent
+ *       property is present in devicetree, all allocations will be mapped as if this flag was set.
+ *       This does not require any additional consideration at allocation time.
  *
  * Firmware options
  *    :PVR_BO_FW_NO_CLEAR_ON_RESET: By default, all FW objects are cleared and reinitialised on hard
diff --git a/drivers/gpu/drm/imagination/pvr_mmu.c b/drivers/gpu/drm/imagination/pvr_mmu.c
index 4fe70610ed94cf707e631f8148af081a94f97327..450d476d183f0173d0ef03f0d8897fbeb04831a2 100644
--- a/drivers/gpu/drm/imagination/pvr_mmu.c
+++ b/drivers/gpu/drm/imagination/pvr_mmu.c
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kmemleak.h>
 #include <linux/minmax.h>
+#include <linux/property.h>
 #include <linux/sizes.h>
 
 #define PVR_SHIFT_FROM_SIZE(size_) (__builtin_ctzll(size_))
@@ -259,6 +260,7 @@ pvr_mmu_backing_page_init(struct pvr_mmu_backing_page *page,
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
 
 	struct page *raw_page;
+	pgprot_t prot;
 	int err;
 
 	dma_addr_t dma_addr;
@@ -268,7 +270,11 @@ pvr_mmu_backing_page_init(struct pvr_mmu_backing_page *page,
 	if (!raw_page)
 		return -ENOMEM;
 
-	host_ptr = vmap(&raw_page, 1, VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+	prot = PAGE_KERNEL;
+	if (device_get_dma_attr(dev) != DEV_DMA_COHERENT)
+		prot = pgprot_writecombine(prot);
+
+	host_ptr = vmap(&raw_page, 1, VM_MAP, prot);
 	if (!host_ptr) {
 		err = -ENOMEM;
 		goto err_free_page;

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:29 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:29 +0000
Subject: [PATCH v3 05/18] drm/imagination: Add power domain control
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-5-143b3dbef02f@imgtec.com>

The first supported GPU only used a single power domain so this was
automatically handled by the device runtime.

In order to support multiple power domains, they must be enumerated from
devicetree and linked to both the GPU device and each other to ensure
correct power sequencing at start time.

For all Imagination Rogue GPUs, power domains are named "a", "b", etc. and
the sequence A->B->... is always valid for startup with the reverse true
for shutdown. Note this is not always the *only* valid sequence, but it's
simple and does not require special-casing for different GPU power
topologies.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-6-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-6-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h |   8 +++
 drivers/gpu/drm/imagination/pvr_drv.c    |   7 ++
 drivers/gpu/drm/imagination/pvr_power.c  | 114 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_power.h  |   3 +
 4 files changed, 132 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 6d0dfacb677b46a880f37f419dfa7b67c68fe63d..2dd8a8885fe07078896d669d822525fb2b7bab51 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -18,6 +18,7 @@
 #include <linux/bits.h>
 #include <linux/compiler_attributes.h>
 #include <linux/compiler_types.h>
+#include <linux/device.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
@@ -131,6 +132,13 @@ struct pvr_device {
 	 */
 	struct clk *mem_clk;
 
+	struct pvr_device_power {
+		struct device **domain_devs;
+		struct device_link **domain_links;
+
+		u32 domain_count;
+	} power;
+
 	/** @irq: IRQ number. */
 	int irq;
 
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 3130193f8fffc185e630a293be53374bdc4b7ce0..ac4f5855c5692f0956862cebdbf76b16d8da9a81 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1411,6 +1411,10 @@ pvr_probe(struct platform_device *plat_dev)
 
 	platform_set_drvdata(plat_dev, drm_dev);
 
+	err = pvr_power_domains_init(pvr_dev);
+	if (err)
+		return err;
+
 	init_rwsem(&pvr_dev->reset_sem);
 
 	pvr_context_device_init(pvr_dev);
@@ -1450,6 +1454,8 @@ pvr_probe(struct platform_device *plat_dev)
 err_context_fini:
 	pvr_context_device_fini(pvr_dev);
 
+	pvr_power_domains_fini(pvr_dev);
+
 	return err;
 }
 
@@ -1470,6 +1476,7 @@ static void pvr_remove(struct platform_device *plat_dev)
 	pvr_watchdog_fini(pvr_dev);
 	pvr_queue_device_fini(pvr_dev);
 	pvr_context_device_fini(pvr_dev);
+	pvr_power_domains_fini(pvr_dev);
 }
 
 static const struct of_device_id dt_match[] = {
diff --git a/drivers/gpu/drm/imagination/pvr_power.c b/drivers/gpu/drm/imagination/pvr_power.c
index ba7816fd28ec77e6ca5ce408302a413ce1afeb6e..19b079b357df78e8bcdecfa377fc9c05b6e8e4b0 100644
--- a/drivers/gpu/drm/imagination/pvr_power.c
+++ b/drivers/gpu/drm/imagination/pvr_power.c
@@ -10,10 +10,13 @@
 
 #include <drm/drm_drv.h>
 #include <drm/drm_managed.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/timer.h>
 #include <linux/types.h>
@@ -431,3 +434,114 @@ pvr_watchdog_fini(struct pvr_device *pvr_dev)
 {
 	cancel_delayed_work_sync(&pvr_dev->watchdog.work);
 }
+
+int pvr_power_domains_init(struct pvr_device *pvr_dev)
+{
+	struct device *dev = from_pvr_device(pvr_dev)->dev;
+
+	struct device_link **domain_links __free(kfree) = NULL;
+	struct device **domain_devs __free(kfree) = NULL;
+	int domain_count;
+	int link_count;
+
+	char dev_name[2] = "a";
+	int err;
+	int i;
+
+	domain_count = of_count_phandle_with_args(dev->of_node, "power-domains",
+						  "#power-domain-cells");
+	if (domain_count < 0)
+		return domain_count;
+
+	if (domain_count <= 1)
+		return 0;
+
+	link_count = domain_count + (domain_count - 1);
+
+	domain_devs = kcalloc(domain_count, sizeof(*domain_devs), GFP_KERNEL);
+	if (!domain_devs)
+		return -ENOMEM;
+
+	domain_links = kcalloc(link_count, sizeof(*domain_links), GFP_KERNEL);
+	if (!domain_links)
+		return -ENOMEM;
+
+	for (i = 0; i < domain_count; i++) {
+		struct device *domain_dev;
+
+		dev_name[0] = 'a' + i;
+		domain_dev = dev_pm_domain_attach_by_name(dev, dev_name);
+		if (IS_ERR_OR_NULL(domain_dev)) {
+			err = domain_dev ? PTR_ERR(domain_dev) : -ENODEV;
+			goto err_detach;
+		}
+
+		domain_devs[i] = domain_dev;
+	}
+
+	for (i = 0; i < domain_count; i++) {
+		struct device_link *link;
+
+		link = device_link_add(dev, domain_devs[i], DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+		if (!link) {
+			err = -ENODEV;
+			goto err_unlink;
+		}
+
+		domain_links[i] = link;
+	}
+
+	for (i = domain_count; i < link_count; i++) {
+		struct device_link *link;
+
+		link = device_link_add(domain_devs[i - domain_count + 1],
+				       domain_devs[i - domain_count],
+				       DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+		if (!link) {
+			err = -ENODEV;
+			goto err_unlink;
+		}
+
+		domain_links[i] = link;
+	}
+
+	pvr_dev->power = (struct pvr_device_power){
+		.domain_devs = no_free_ptr(domain_devs),
+		.domain_links = no_free_ptr(domain_links),
+		.domain_count = domain_count,
+	};
+
+	return 0;
+
+err_unlink:
+	while (--i >= 0)
+		device_link_del(domain_links[i]);
+
+	i = domain_count;
+
+err_detach:
+	while (--i >= 0)
+		dev_pm_domain_detach(domain_devs[i], true);
+
+	return err;
+}
+
+void pvr_power_domains_fini(struct pvr_device *pvr_dev)
+{
+	const int domain_count = pvr_dev->power.domain_count;
+
+	int i = domain_count + (domain_count - 1);
+
+	while (--i >= 0)
+		device_link_del(pvr_dev->power.domain_links[i]);
+
+	i = domain_count;
+
+	while (--i >= 0)
+		dev_pm_domain_detach(pvr_dev->power.domain_devs[i], true);
+
+	kfree(pvr_dev->power.domain_links);
+	kfree(pvr_dev->power.domain_devs);
+
+	pvr_dev->power = (struct pvr_device_power){ 0 };
+}
diff --git a/drivers/gpu/drm/imagination/pvr_power.h b/drivers/gpu/drm/imagination/pvr_power.h
index 9a9312dcb2dab7d36ee8ff7f69e69d126c5469a9..ada85674a7ca762dcf92df40424230e1c3910342 100644
--- a/drivers/gpu/drm/imagination/pvr_power.h
+++ b/drivers/gpu/drm/imagination/pvr_power.h
@@ -38,4 +38,7 @@ pvr_power_put(struct pvr_device *pvr_dev)
 	return pm_runtime_put(drm_dev->dev);
 }
 
+int pvr_power_domains_init(struct pvr_device *pvr_dev);
+void pvr_power_domains_fini(struct pvr_device *pvr_dev);
+
 #endif /* PVR_POWER_H */

-- 
2.48.1



From Qun-wei.Lin at mediatek.com  Mon Mar 10 06:21:35 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Mon, 10 Mar 2025 13:21:35 +0000
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4z4yKRQiqMtGRr2bjvgVY6mmujdqyKyVgid=RUXr_9TbQ@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <CAGsJ_4z4yKRQiqMtGRr2bjvgVY6mmujdqyKyVgid=RUXr_9TbQ@mail.gmail.com>
Message-ID: <b9fc1efa457aa29104737e5f6a4868602a3078e5.camel@mediatek.com>

On Sat, 2025-03-08 at 08:34 +1300, Barry Song wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com>
> wrote:
> > 
> > This patch series introduces a new mechanism called kcompressd to
> > improve the efficiency of memory reclaiming in the operating
> > system. The
> > main goal is to separate the tasks of page scanning and page
> > compression
> > into distinct processes or threads, thereby reducing the load on
> > the
> > kswapd thread and enhancing overall system performance under high
> > memory
> > pressure conditions.
> > 
> > Problem:
> > ?In the current system, the kswapd thread is responsible for both
> > ?scanning the LRU pages and compressing pages into the ZRAM. This
> > ?combined responsibility can lead to significant performance
> > bottlenecks,
> > ?especially under high memory pressure. The kswapd thread becomes a
> > ?single point of contention, causing delays in memory reclaiming
> > and
> > ?overall system performance degradation.
> > 
> > Target:
> > ?The target of this invention is to improve the efficiency of
> > memory
> > ?reclaiming. By separating the tasks of page scanning and page
> > ?compression into distinct processes or threads, the system can
> > handle
> > ?memory pressure more effectively.
> 
> Sounds great. However, we also have a time window where folios under
> writeback are kept, whereas previously, writeback was done
> synchronously
> without your patch. This may temporarily increase memory usage until
> the
> kept folios are re-scanned.
> 
> So, you?ve observed that folio_rotate_reclaimable() runs shortly
> while the
> async thread completes compression? Then the kept folios are shortly
> re-scanned?
> 

Yes, these folios may need to be re-scanned, so
folio_rotate_reclaimable() will be run. This can be observed from the
increase in pgrotated in /proc/vmstat.

> > 
> > Patch 1:
> > - Introduces 2 new feature flags, BLK_FEAT_READ_SYNCHRONOUS and
> > ? SWP_READ_SYNCHRONOUS_IO.
> > 
> > Patch 2:
> > - Implemented the core functionality of Kcompressd and made
> > necessary
> > ? modifications to the zram driver to support it.
> > 
> > In our handheld devices, we found that applying this mechanism
> > under high
> > memory pressure scenarios can increase the rate of pgsteal_anon per
> > second
> > by over 260% compared to the situation with only kswapd.
> 
> Sounds really great.
> 
> What compression algorithm is being used? I assume that after
> switching to a
> different compression algorithms, the benefits will change
> significantly. For
> example, Zstd might not show as much improvement.
> How was the CPU usage ratio between page scan/unmap and compression
> observed before applying this patch?
> 

The original tests were based on LZ4.
We have observed that the CPU time spent on scanning the LRU and
compressing folios is approximately in 3:7.

We also try ZSTD as the zram backend, but the the number of anonymous
folios reclaimed per second did not differ significantly from LZ4 (the
benefits were far less compared to what could be achieved with parallel
processing). Even with ZSTD, we were still able to reach around 800,000
pgsteal_anon per second using kcompressd.


> > 
> > Qun-Wei Lin (2):
> > ? mm: Split BLK_FEAT_SYNCHRONOUS and SWP_SYNCHRONOUS_IO into
> > separate
> > ??? read and write flags
> > ? kcompressd: Add Kcompressd for accelerated zram compression
> > 
> > ?drivers/block/brd.c???????????? |?? 3 +-
> > ?drivers/block/zram/Kconfig????? |? 11 ++
> > ?drivers/block/zram/Makefile???? |?? 3 +-
> > ?drivers/block/zram/kcompressd.c | 340
> > ++++++++++++++++++++++++++++++++
> > ?drivers/block/zram/kcompressd.h |? 25 +++
> > ?drivers/block/zram/zram_drv.c?? |? 21 +-
> > ?drivers/nvdimm/btt.c??????????? |?? 3 +-
> > ?drivers/nvdimm/pmem.c?????????? |?? 5 +-
> > ?include/linux/blkdev.h????????? |? 24 ++-
> > ?include/linux/swap.h??????????? |? 31 +--
> > ?mm/memory.c???????????????????? |?? 4 +-
> > ?mm/page_io.c??????????????????? |?? 6 +-
> > ?mm/swapfile.c?????????????????? |?? 7 +-
> > ?13 files changed, 446 insertions(+), 37 deletions(-)
> > ?create mode 100644 drivers/block/zram/kcompressd.c
> > ?create mode 100644 drivers/block/zram/kcompressd.h
> > 
> > --
> > 2.45.2
> > 
> 
> Thanks
> Barry

Best Regards,
Qun-wei


From Qun-wei.Lin at mediatek.com  Mon Mar 10 06:22:26 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Mon, 10 Mar 2025 13:22:26 +0000
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
	 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
Message-ID: <52896654fa07a685707b11cfcc141b038a13b649.camel@mediatek.com>

On Sat, 2025-03-08 at 18:41 +1300, Barry Song wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Sat, Mar 8, 2025 at 12:03?PM Nhat Pham <nphamcs at gmail.com> wrote:
> > 
> > On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin
> > <qun-wei.lin at mediatek.com> wrote:
> > > 
> > > This patch series introduces a new mechanism called kcompressd to
> > > improve the efficiency of memory reclaiming in the operating
> > > system. The
> > > main goal is to separate the tasks of page scanning and page
> > > compression
> > > into distinct processes or threads, thereby reducing the load on
> > > the
> > > kswapd thread and enhancing overall system performance under high
> > > memory
> > > pressure conditions.
> > 
> > Please excuse my ignorance, but from your cover letter I still
> > don't
> > quite get what is the problem here? And how would decouple
> > compression
> > and scanning help?
> 
> My understanding is as follows:
> 
> When kswapd attempts to reclaim M anonymous folios and N file folios,
> the process involves the following steps:
> 
> * t1: Time to scan and unmap anonymous folios
> * t2: Time to compress anonymous folios
> * t3: Time to reclaim file folios
> 
> Currently, these steps are executed sequentially, meaning the total
> time
> required to reclaim M + N folios is t1 + t2 + t3.
> 
> However, Qun-Wei's patch enables t1 + t3 and t2 to run in parallel,
> reducing the total time to max(t1 + t3, t2). This likely improves the
> reclamation speed, potentially reducing allocation stalls.
> 
> I don?t have concrete data on this. Does Qun-Wei have detailed
> performance data?
> 

Thank you for your explanation. Compared to the original single kswapd,
we expect t1 to have a slight increase in re-scan time. However, since
our kcompressd can focus on compression tasks and we can have multiple
kcompressd instances (kcompressd0, kcompressd1, ...) running in
parallel, we anticipate that the number of times a folio needs be re-
scanned will not be too many.

In our experiments, we fixed the CPU and DRAM at a certain frequency.
We created a high memory pressure enviroment using a memory eater and
recorded the increase in pgsteal_anon per second, which was around 300,
000. Then we applied our patch and measured again, that pgsteal_anon/s
increased to over 800,000.

> > 
> > > 
> > > Problem:
> > > ?In the current system, the kswapd thread is responsible for both
> > > ?scanning the LRU pages and compressing pages into the ZRAM. This
> > > ?combined responsibility can lead to significant performance
> > > bottlenecks,
> > 
> > What bottleneck are we talking about? Is one stage slower than the
> > other?
> > 
> > > ?especially under high memory pressure. The kswapd thread becomes
> > > a
> > > ?single point of contention, causing delays in memory reclaiming
> > > and
> > > ?overall system performance degradation.
> > > 
> > > Target:
> > > ?The target of this invention is to improve the efficiency of
> > > memory
> > > ?reclaiming. By separating the tasks of page scanning and page
> > > ?compression into distinct processes or threads, the system can
> > > handle
> > > ?memory pressure more effectively.
> > 
> > I'm not a zram maintainer, so I'm definitely not trying to stop
> > this
> > patch. But whatever problem zram is facing will likely occur with
> > zswap too, so I'd like to learn more :)
> 
> Right, this is likely something that could be addressed more
> generally
> for zswap and zram.
> 

Yes, we also hope to extend this to other swap devices, but currently,
we have only modified zram. We are not very familiar with zswap and
would like to ask if anyone has any suggestions for modifications?

> Thanks
> Barry

Best Regards,
Qun-wei


From Qun-wei.Lin at mediatek.com  Mon Mar 10 06:26:11 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Mon, 10 Mar 2025 13:26:11 +0000
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram
 compression
In-Reply-To: <CAKEwX=MtzM4Vw221pHTj8CZJ1NhLgo7Ls3xroxLRO399fzG98Q@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
	 <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
	 <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>
	 <CAKEwX=MtzM4Vw221pHTj8CZJ1NhLgo7Ls3xroxLRO399fzG98Q@mail.gmail.com>
Message-ID: <80d463f2155a949244881302722865443e709572.camel@mediatek.com>

On Fri, 2025-03-07 at 15:14 -0800, Nhat Pham wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, Mar 7, 2025 at 3:13?PM Nhat Pham <nphamcs at gmail.com> wrote:
> > 
> > 
> > Agree. A shared solution would be much appreciated. We can keep the
> > kcompressd idea, but have it accept IO work from multiple sources
> > (zram, zswap, whatever) through a shared API.
> 
> by IO I meant compress work (should be double quoted "IO"). But you
> get the idea :)

I also agree that we can evolve into a more general solution.
So this is also why we designed kcompressd to do writeback using
callbacks rather than hard coding it directly into zram.

But currently we only extend Zram. If anyone has good suggestions, we
would greatly appreciate your help.

Thanks!
Qun-wei

From alexandre.torgue at foss.st.com  Mon Mar 10 06:27:43 2025
From: alexandre.torgue at foss.st.com (Alexandre TORGUE)
Date: Mon, 10 Mar 2025 14:27:43 +0100
Subject: [PATCH] ARM: dts: stm32: Add support for STM32MP13xx DHCOR SoM
 and DHSBC rev.200 board
In-Reply-To: <20250302152605.54792-1-marex@denx.de>
References: <20250302152605.54792-1-marex@denx.de>
Message-ID: <6d42bdc8-825a-4fd9-80ab-cfe02fff6c86@foss.st.com>

Hi Marek

On 3/2/25 16:25, Marek Vasut wrote:
> LDO2 is expansion connector supply on STM32MP13xx DHCOR DHSBC rev.200.
> LDO5 is carrier board supply on STM32MP13xx DHCOR DHSBC rev.200. Keep
> both regulators always enabled to make sure both the carrier board and
> the expansion connector is always powered on and supplied with correct
> voltage.
> 
> Describe ST33TPHF2XSPI TPM 2.0 chip interrupt and reset lines.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Alexandre Torgue <alexandre.torgue at foss.st.com>
> Cc: Christoph Niedermaier <cniedermaier at dh-electronics.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
> Cc: Rob Herring <robh at kernel.org>
> Cc: devicetree at vger.kernel.org
> Cc: kernel at dh-electronics.com
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-stm32 at st-md-mailman.stormreply.com
> ---
>   .../boot/dts/st/stm32mp135f-dhcor-dhsbc.dts   | 30 +++++++++++++++++--
>   1 file changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
> index 853dc21449d99..9902849ed0406 100644
> --- a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
> +++ b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts


Applied on stm32-next.

Thanks
Alex

> @@ -176,7 +176,7 @@ &gpioa {
>   	gpio-line-names = "", "", "", "",
>   			  "", "DHSBC_USB_PWR_CC1", "", "",
>   			  "", "", "", "DHSBC_nETH1_RST",
> -			  "", "DHCOR_HW-CODING_0", "", "";
> +			  "", "DHCOR_HW-CODING_0", "", "DHSBC_HW-CODE_2";
>   };
>   
>   &gpiob {
> @@ -197,7 +197,7 @@ &gpiod {
>   	gpio-line-names = "", "", "", "",
>   			  "", "DHCOR_RAM-CODING_0", "", "",
>   			  "", "DHCOR_RAM-CODING_1", "", "",
> -			  "", "", "", "";
> +			  "", "DHSBC_HW-CODE_1", "", "";
>   };
>   
>   &gpioe {
> @@ -221,6 +221,13 @@ &gpiog {
>   			  "DHSBC_ETH1_INTB", "", "", "DHSBC_ETH2_INTB";
>   };
>   
> +&gpioh {
> +	gpio-line-names = "", "", "", "DHSBC_HW-CODE_0",
> +			  "", "", "", "",
> +			  "", "", "", "",
> +			  "", "", "", "";
> +};
> +
>   &gpioi {
>   	gpio-line-names = "DHCOR_RTC_nINT", "DHCOR_HW-CODING_1",
>   			  "DHCOR_BT_REG_ON", "DHCOR_PMIC_nINT",
> @@ -296,6 +303,9 @@ &spi2 {
>   	st33htph: tpm at 0 {
>   		compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi";
>   		reg = <0>;
> +		interrupt-parent = <&gpioe>;
> +		interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
> +		reset-gpios = <&gpioe 12 GPIO_ACTIVE_LOW>;
>   		spi-max-frequency = <24000000>;
>   	};
>   };
> @@ -419,3 +429,19 @@ connector {
>   		type = "micro";
>   	};
>   };
> +
> +/* LDO2 is expansion connector 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
> +&vdd_ldo2 {
> +	regulator-always-on;
> +	regulator-boot-on;
> +	regulator-min-microvolt = <3300000>;
> +	regulator-max-microvolt = <3300000>;
> +};
> +
> +/* LDO5 is carrier board 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
> +&vdd_sd {
> +	regulator-always-on;
> +	regulator-boot-on;
> +	regulator-min-microvolt = <3300000>;
> +	regulator-max-microvolt = <3300000>;
> +};


From robh at kernel.org  Mon Mar 10 06:30:41 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 08:30:41 -0500
Subject: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <nddxntwmiyurqew75gc6yoj2dcinhjqu36cdujhruqyrz62ry5@4e2y76ghmo4h>
References: <20250308-sar2130p-display-v1-0-1d4c30f43822@linaro.org>
 <20250308-sar2130p-display-v1-5-1d4c30f43822@linaro.org> <174140525677.1770282.3232695979994091275.robh@kernel.org>
 <nddxntwmiyurqew75gc6yoj2dcinhjqu36cdujhruqyrz62ry5@4e2y76ghmo4h>
Message-ID: <CAL_JsqJ6iYm-8BF+4QwimAX69jmivpCNqKbD_AtWkKDtAn_Wgw@mail.gmail.com>

On Fri, Mar 7, 2025 at 11:09?PM Dmitry Baryshkov
<dmitry.baryshkov at linaro.org> wrote:
>
> On Fri, Mar 07, 2025 at 09:40:56PM -0600, Rob Herring (Arm) wrote:
> >
> > On Sat, 08 Mar 2025 03:42:23 +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > >
> > > Describe the Mobile Display SubSystem (MDSS) device present on the
> > > Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
> > > system level. SAR2130P features two DSI hosts and single DisplayPort
> > > controller.
> > >
> > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> > > ---
> > >  .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 +++++++++++++++++++++
> > >  1 file changed, 445 insertions(+)
> > >
> >
> > My bot found errors running 'make dt_binding_check' on your patch:
> >
> > yamllint warnings/errors:
> >
> > dtschema/dtc warnings/errors:
> > /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb: dsi at ae94000: compatible: 'oneOf' conditional failed, one must be fixed:
> >       ['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
> >       'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 'qcom,sm8650-dsi-ctrl']
> >       'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 'qcom,mdss-dsi-ctrl']
> >       from schema $id: http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
>
> It looks like the patch 2 could not be applied and was skipped. Is the
> bot parsing the dependencies from the cover letter?

No, it's not that smart. I need to move it to using b4 though that has
its own quirks when no dependencies are given.

Rob


From robh at kernel.org  Mon Mar 10 05:49:56 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 07:49:56 -0500
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop
 unnecessary status from example
In-Reply-To: <5417098.31r3eYUQgx@workhorse>
References: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
 <5417098.31r3eYUQgx@workhorse>
Message-ID: <20250310124956.GA3875809-robh@kernel.org>

On Fri, Mar 07, 2025 at 03:05:50PM +0100, Nicolas Frattaroli wrote:
> On Friday, 7 March 2025 10:33:09 Central European Standard Time Krzysztof 
> Kozlowski wrote:
> > Device nodes are enabled by default, so no need for 'status = "okay"' in
> > the DTS example.
> > 
> > Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> > 
> > ---
> > 
> > Changes in v2:
> > 1. Drop unnecessary full stop in subject prefix after ':'.
> > 2. Add Rb tag.
> > ---
> >  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
> >  1 file changed, 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml index
> > 757967212f55..ca71b400bcae 100644
> > --- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > +++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > @@ -53,7 +53,6 @@ examples:
> >          interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
> >          clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
> >          resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
> > -        status = "okay";
> >        };
> >      };
> 
> Hi,
> 
> is there the possibility we could make dtschema as invoked by `make 
> dt_binding_check W=1` (or W=2) add a warning for examples that have disabled 
> or explicitly listed status properties when not needed? Or is this something 
> better handled in, say, checkpatch.pl?
> 
> The question arises because dumb mistakes by me like this should ideally be 
> caught before they waste precious maintainer time.
> 
> If it's best handled in dtschema, I can look into working on that so you guys 
> don't have to do even more work due to me.

Trust me, I'm always looking for things to check automatically. :)

I have something like that which adds a schema for examples only. I 
think there were some corner cases. I'll take a fresh look at it.

Rob


From robh at kernel.org  Mon Mar 10 05:50:03 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 10 Mar 2025 07:50:03 -0500
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop
 unnecessary status from example
In-Reply-To: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
References: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174161100282.3880379.16414852796970978869.robh@kernel.org>


On Fri, 07 Mar 2025 10:33:09 +0100, Krzysztof Kozlowski wrote:
> Device nodes are enabled by default, so no need for 'status = "okay"' in
> the DTS example.
> 
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> ---
> 
> Changes in v2:
> 1. Drop unnecessary full stop in subject prefix after ':'.
> 2. Add Rb tag.
> ---
>  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
>  1 file changed, 1 deletion(-)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From ltykernel at gmail.com  Mon Mar 10 05:50:20 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 20:50:20 +0800
Subject: [PATCH v5 05/10] acpi: numa: Export node_to_pxm()
In-Reply-To: <1740611284-27506-6-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-6-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <CAMvTesAh9hK3r81TqbSwB58c1zuXpMzhk=7=gt2cR1QvpJC35Q@mail.gmail.com>

On Thu, Feb 27, 2025 at 7:10?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> node_to_pxm() is used by hv_numa_node_to_pxm_info().
> That helper will be used by Hyper-V root partition module code
> when CONFIG_MSHV_ROOT=m.
>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---

Reviewed-by: Tianyu Lan <tiala at microsoft.com>


-- 
Thanks
Tianyu Lan


From ltykernel at gmail.com  Mon Mar 10 05:51:36 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 20:51:36 +0800
Subject: [PATCH v5 04/10] hyperv: Introduce hv_recommend_using_aeoi()
In-Reply-To: <1740611284-27506-5-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-5-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <CAMvTesCs3ieYDEnC1xd_U=XYvg2u_qE7FZRLp5OoWh1Co8p6+w@mail.gmail.com>

On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> Factor out the check for enabling auto eoi, to be reused in root
> partition code.
>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---

Reviewed-by: Tianyu Lan <tiala at microsoft.com>

-- 
Thanks
Tianyu Lan


From demonsingur at gmail.com  Mon Mar 10 05:52:57 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Mon, 10 Mar 2025 14:52:57 +0200
Subject: [RFC PATCH 09/24] dt-bindings: media: i2c: max96714: make
 i2c-gate conditional on compatible
In-Reply-To: <20250310123207.GA3853920-robh@kernel.org>
References: <20250308183410.3013996-1-demonsingur@gmail.com>
 <20250308183410.3013996-10-demonsingur@gmail.com>
 <20250310123207.GA3853920-robh@kernel.org>
Message-ID: <a678823b-de37-461f-991f-fe8b3a7e7c40@gmail.com>



On 3/10/25 2:32 PM, Rob Herring wrote:
> On Sat, Mar 08, 2025 at 08:33:38PM +0200, Cosmin Tanislav wrote:
>> Devices to be added in following patches don't use I2C gate.
>>
>> Make this property conditional on the compatible strings.
>>
>> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
>> ---
>>   .../bindings/media/i2c/maxim,max96714.yaml    | 21 ++++++++++++-------
>>   1 file changed, 13 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
>> index 2f453189338f..d0a2aaf7df9c 100644
>> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
>> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
>> @@ -84,14 +84,6 @@ properties:
>>       required:
>>         - port at 1
>>   
>> -  i2c-gate:
>> -    $ref: /schemas/i2c/i2c-gate.yaml
>> -    unevaluatedProperties: false
>> -    description:
>> -      The MAX96714 will pass through and forward the I2C requests from the
>> -      incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate
>> -      subnode to configure a serializer.
>> -
>>     port0-poc-supply:
>>       description: Regulator providing Power over Coax for the GMSL port
>>   
>> @@ -101,6 +93,19 @@ required:
>>     - ports
>>   
>>   additionalProperties: false
>> +allOf:
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            enum:
>> +              - maxim,max96714
>> +              - maxim,max96714f
>> +    then:
>> +      properties:
>> +        i2c-gate:
> 
> Leave the original definition, invert the 'if', and here you just need:
> 
> i2c-gate: false
> 

Hi Rob.

Thanks for your comments.

After noticing that my dt-schema validation scripts are failing (because
of the jsonschema version incompatibility), I fixed them and then fixed
all the issues and sent a V2 where I introduce a separate file for these
bindings since they all have a different number of ports compared to the
max96714 one.

So the V1 of these patches have been superseded.

>> +          $ref: /schemas/i2c/i2c-gate.yaml
>> +          unevaluatedProperties: false
>>   
>>   examples:
>>     - |
>> -- 
>> 2.48.1
>>



From robh at kernel.org  Mon Mar 10 05:53:55 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 10 Mar 2025 07:53:55 -0500
Subject: [PATCH net-next 6/7] dt-bindings: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <E1trIAQ-005nto-3w@rmk-PC.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
 <E1trIAQ-005nto-3w@rmk-PC.armlinux.org.uk>
Message-ID: <174161123533.3885448.13844393493565707617.robh@kernel.org>


On Sun, 09 Mar 2025 15:02:14 +0000, Russell King (Oracle) wrote:
> Whether the MII transmit clock can be stopped is primarily a property
> of the PHY (there is a capability bit that should be checked first.)
> Whether the MAC is capable of stopping the transmit clock is a separate
> issue, but this is already handled by the core DesignWare MAC code.
> 
> Therefore, snps,en-tx-lpi-clockgating is technically incorrect, so this
> commit deprecates the property in the binding.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  Documentation/devicetree/bindings/net/snps,dwmac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From mazziesaccount at gmail.com  Mon Mar 10 05:56:11 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 10 Mar 2025 14:56:11 +0200
Subject: [PATCH v6 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1741610847.git.mazziesaccount@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
Message-ID: <c9654fcda1c5c8ac98f99ec8e3babdc41cbcb67b.1741610847.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v5 => v6:
 - Adapt to changed fwnode helper names
 - Fix spelling
v4 => v5:
 - Inline iio_adc_device_num_channels()
 - Fix Indenting function parameters
 - Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 79 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 111 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..6cfb001c74b9
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use -1 if no checking
+ *			is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on success. Negative value to indicate
+ *		failure.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan = 0, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 1)
+		return num_chan;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_named_child_node_scoped(dev, child, "channel") {
+		u32 ch;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id != -1 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..56b092a2a4c4
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_named_child_node_count(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/7134dd47/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 10 05:56:35 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 10 Mar 2025 14:56:35 +0200
Subject: [PATCH v6 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1741610847.git.mazziesaccount@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
Message-ID: <06e8f4f84731df9fc5d6f324e74fbd1bf83a81d5.1741610847.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-properties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v5 => v6:
 - Commit message typofix
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 38 ++++++++++++------------------
 2 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..bf1db2a3de9b 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,37 +150,27 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
+
 	if (num_channels == 0)
 		return dev_err_probe(dev, -ENODEV, "no channel children\n");
 
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
-
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
 
@@ -271,3 +262,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/50c95cdd/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 10 05:56:59 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 10 Mar 2025 14:56:59 +0200
Subject: [PATCH v6 07/10] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1741610847.git.mazziesaccount@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
Message-ID: <e180c9de76bc478b5f25ab6f5f22377cd359d485.1741610847.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
v2 =>
 - No changes
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/9a776a13/attachment.sig>

From ltykernel at gmail.com  Mon Mar 10 06:01:45 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 21:01:45 +0800
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com>

On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
> SynIC event ring buffer for each SINT.
>
> This will be used by the mshv driver, but must be tracked independently
> since the driver module could be removed and re-inserted.
>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Wei Liu <wei.liu at kernel.org>

It's better to expose a function to check the tail instead of exposing
hv_synic_eventring_tail directly.

BTW, how does mshv driver use hv_synic_eventring_tail? Which patch
uses it in this series?

Thanks.


> ---
>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 252fd66ad4db..2763cb6d3678 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
>
>  static struct ctl_table_header *hv_ctl_table_hdr;
>
> +/*
> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
> + * for each SINT.
> + *
> + * We cannot maintain this in mshv driver because the tail pointer should
> + * persist even if the mshv driver is unloaded.
> + */
> +u8 __percpu **hv_synic_eventring_tail;
> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
> +
>  /*
>   * Hyper-V specific initialization and shutdown code that is
>   * common across all architectures.  Called from architecture
> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
>
>         free_percpu(hyperv_pcpu_input_arg);
>         hyperv_pcpu_input_arg = NULL;
> +
> +       free_percpu(hv_synic_eventring_tail);
> +       hv_synic_eventring_tail = NULL;
>  }
>
>  /*
> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
>                 BUG_ON(!hyperv_pcpu_output_arg);
>         }
>
> +       if (hv_root_partition()) {
> +               hv_synic_eventring_tail = alloc_percpu(u8 *);
> +               BUG_ON(hv_synic_eventring_tail == NULL);
> +       }
> +
>         hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
>                                     GFP_KERNEL);
>         if (!hv_vp_index) {
> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
>  int hv_common_cpu_init(unsigned int cpu)
>  {
>         void **inputarg, **outputarg;
> +       u8 **synic_eventring_tail;
>         u64 msr_vp_index;
>         gfp_t flags;
>         const int pgcount = hv_output_page_exists() ? 2 : 1;
> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
>         inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
>
>         /*
> -        * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
> -        * allocated if this CPU was previously online and then taken offline
> +        * The per-cpu memory is already allocated if this CPU was previously
> +        * online and then taken offline
>          */
>         if (!*inputarg) {
>                 mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
>                         *outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
>                 }
>
> +               if (hv_root_partition()) {
> +                       synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> +                       *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
> +                                                       sizeof(u8), flags);
> +
> +                       if (unlikely(!*synic_eventring_tail)) {
> +                               kfree(mem);
> +                               return -ENOMEM;
> +                       }
> +               }
> +
>                 if (!ms_hyperv.paravisor_present &&
>                     (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
>                         ret = set_memory_decrypted((unsigned long)mem, pgcount);
> --
> 2.34.1
>
>


-- 
Thanks
Tianyu Lan


From angelogioacchino.delregno at collabora.com  Mon Mar 10 06:06:06 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 14:06:06 +0100
Subject: [PATCH] memory: mtk-smi: Add ostd setting for mt8192
In-Reply-To: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
References: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
Message-ID: <6295bee6-326e-4eee-9636-1d3b41a59e30@collabora.com>

Il 07/03/25 06:45, Xueqi Zhang ha scritto:
> Add initial ostd setting for mt8192. All the settings come from DE.
> These settings help adjust Multimedia HW's bandwidth limits to achieve
> a balanced bandwidth requirement.
> Without this, the VENC HW work abnormal while stress testing.
> 
> Fixes: 02c02ddce427 ("memory: mtk-smi: Add mt8192 support")
> Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar 10 06:08:30 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 14:08:30 +0100
Subject: [PATCH 00/13] pmdomain: mediatek: Add MT8196 power domain
In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com>
References: <20250307034454.12243-1-guangjie.song@mediatek.com>
Message-ID: <0abe6c3a-cffe-4aec-a95d-ea27704729b2@collabora.com>

Il 07/03/25 04:44, Guangjie Song ha scritto:
> This series is based on linux-next, tag: next-20250306.
> 
> Changes:
> - Update mtk-scpsys driver for MT8196
> - Add MT8196 power domain support

The mtk-scpsys driver is deprecated since ... 2 years ago, and I have no idea why
MediaTek folks still use it downstream.

Please refactor this and use the mtk-pm-domains driver for any new MTCMOS
implementation.

Thanks,
Angelo

> 
> Guangjie Song (13):
>    pmdomain: mediatek: Support sram isolation
>    pmdomain: mediatek: Support sram low power
>    pmdomain: mediatek: Support power on bypass
>    pmdomain: mediatek: Support check power on/off ack
>    pmdomain: mediatek: Support voting for power domain
>    pmdomain: mediatek: Support trigger subsys save/restore regesters
>    pmdomain: mediatek: Support power domain irq safe
>    pmdomain: mediatek: Support power domain always on
>    pmdomain: mediatek: Refactor parameters of init_scp
>    pmdomain: mediatek: Support bus protect with table
>    pmdomain: mediatek: Add post init callback
>    dt-bindings: power: mediatek: Add new MT8196 power domain
>    pmdomain: mediatek: Add MT8196 power domain support
> 
>   .../mediatek,mt8196-power-controller.yaml     |   74 +
>   drivers/pmdomain/mediatek/mt8196-scpsys.h     |  114 ++
>   drivers/pmdomain/mediatek/mtk-scpsys.c        | 1276 ++++++++++++++++-
>   include/dt-bindings/power/mt8196-power.h      |   57 +
>   4 files changed, 1483 insertions(+), 38 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/power/mediatek,mt8196-power-controller.yaml
>   create mode 100644 drivers/pmdomain/mediatek/mt8196-scpsys.h
>   create mode 100644 include/dt-bindings/power/mt8196-power.h
> 





From matt.coster at imgtec.com  Mon Mar 10 06:10:27 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:27 +0000
Subject: [PATCH v3 03/18] drm/imagination: Update register defs for newer
 GPUs
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-3-143b3dbef02f@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Update the register define header to a newer version that covers more
recent GPUs, including BXS-4-64.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h | 153 +++++++++++++++++++++---
 1 file changed, 134 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h b/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
index 2a90d02796d3e071b18e18dead105e29798bcddc..790c97f80a2ac03ac76b933d009a2f9cfc6003f7 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
@@ -827,6 +827,120 @@
 #define ROGUE_CR_EVENT_STATUS_TLA_COMPLETE_CLRMSK 0xFFFFFFFEU
 #define ROGUE_CR_EVENT_STATUS_TLA_COMPLETE_EN 0x00000001U
 
+/* Register ROGUE_CR_EVENT_CLEAR */
+#define ROGUE_CR_EVENT_CLEAR 0x0138U
+#define ROGUE_CR_EVENT_CLEAR__ROGUEXE__MASKFULL 0x00000000E01DFFFFULL
+#define ROGUE_CR_EVENT_CLEAR__SIGNALS__MASKFULL 0x00000000E007FFFFULL
+#define ROGUE_CR_EVENT_CLEAR_MASKFULL 0x00000000FFFFFFFFULL
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_SHIFT 31U
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_CLRMSK 0x7FFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_EN 0x80000000U
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_SHIFT 30U
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_CLRMSK 0xBFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_EN 0x40000000U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_SHIFT 29U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_CLRMSK 0xDFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_EN 0x20000000U
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_SHIFT 28U
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_CLRMSK 0xEFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_EN 0x10000000U
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_SHIFT 27U
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_CLRMSK 0xF7FFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_EN 0x08000000U
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_SHIFT 26U
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_CLRMSK 0xFBFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_EN 0x04000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_SHIFT 25U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_CLRMSK 0xFDFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_EN 0x02000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_SHIFT 24U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_CLRMSK 0xFEFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_EN 0x01000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_SHIFT 23U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_CLRMSK 0xFF7FFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_EN 0x00800000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_SHIFT 22U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_CLRMSK 0xFFBFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_EN 0x00400000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_SHIFT 21U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_CLRMSK 0xFFDFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_EN 0x00200000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_SHIFT 20U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_CLRMSK 0xFFEFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_EN 0x00100000U
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_SHIFT 20U
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_CLRMSK 0xFFEFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_EN 0x00100000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_SHIFT 19U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_CLRMSK 0xFFF7FFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_EN 0x00080000U
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_SHIFT 19U
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_CLRMSK 0xFFF7FFFFU
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_EN 0x00080000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_SHIFT 18U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_CLRMSK 0xFFFBFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_EN 0x00040000U
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_SHIFT 18U
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_CLRMSK 0xFFFBFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_EN 0x00040000U
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_SHIFT 17U
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_CLRMSK 0xFFFDFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_EN 0x00020000U
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_SHIFT 17U
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_CLRMSK 0xFFFDFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_EN 0x00020000U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_SHIFT 16U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_EN 0x00010000U
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_SHIFT 15U
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_CLRMSK 0xFFFF7FFFU
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_EN 0x00008000U
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_SHIFT 14U
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_CLRMSK 0xFFFFBFFFU
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_EN 0x00004000U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_SHIFT 13U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_CLRMSK 0xFFFFDFFFU
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_EN 0x00002000U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_SHIFT 12U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_CLRMSK 0xFFFFEFFFU
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_EN 0x00001000U
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_SHIFT 11U
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_CLRMSK 0xFFFFF7FFU
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_EN 0x00000800U
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_SHIFT 10U
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_CLRMSK 0xFFFFFBFFU
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_EN 0x00000400U
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_SHIFT 9U
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_CLRMSK 0xFFFFFDFFU
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_EN 0x00000200U
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_SHIFT 8U
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_CLRMSK 0xFFFFFEFFU
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_EN 0x00000100U
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_SHIFT 7U
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_CLRMSK 0xFFFFFF7FU
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_EN 0x00000080U
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_SHIFT 6U
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_CLRMSK 0xFFFFFFBFU
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_EN 0x00000040U
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_SHIFT 5U
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_CLRMSK 0xFFFFFFDFU
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_EN 0x00000020U
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_SHIFT 4U
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_CLRMSK 0xFFFFFFEFU
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_EN 0x00000010U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_SHIFT 3U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_CLRMSK 0xFFFFFFF7U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_EN 0x00000008U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_SHIFT 2U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_CLRMSK 0xFFFFFFFBU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_EN 0x00000004U
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_SHIFT 1U
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_CLRMSK 0xFFFFFFFDU
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_EN 0x00000002U
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_SHIFT 0U
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_EN 0x00000001U
+
 /* Register ROGUE_CR_TIMER */
 #define ROGUE_CR_TIMER 0x0160U
 #define ROGUE_CR_TIMER_MASKFULL 0x8000FFFFFFFFFFFFULL
@@ -6031,25 +6145,6 @@
 #define ROGUE_CR_MULTICORE_COMPUTE_CTRL_COMMON_GPU_ENABLE_SHIFT 0U
 #define ROGUE_CR_MULTICORE_COMPUTE_CTRL_COMMON_GPU_ENABLE_CLRMSK 0xFFFFFF00U
 
-/* Register ROGUE_CR_ECC_RAM_ERR_INJ */
-#define ROGUE_CR_ECC_RAM_ERR_INJ 0xF340U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MASKFULL 0x000000000000001FULL
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_SHIFT 4U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_CLRMSK 0xFFFFFFEFU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_EN 0x00000010U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_SHIFT 3U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_CLRMSK 0xFFFFFFF7U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_EN 0x00000008U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_SHIFT 2U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_CLRMSK 0xFFFFFFFBU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_EN 0x00000004U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_SHIFT 1U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_CLRMSK 0xFFFFFFFDU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_EN 0x00000002U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_SHIFT 0U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_CLRMSK 0xFFFFFFFEU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_EN 0x00000001U
-
 /* Register ROGUE_CR_ECC_RAM_INIT_KICK */
 #define ROGUE_CR_ECC_RAM_INIT_KICK 0xF348U
 #define ROGUE_CR_ECC_RAM_INIT_KICK_MASKFULL 0x000000000000001FULL
@@ -6163,6 +6258,26 @@
 #define ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE__GPU_PAGE_FAULT_CLRMSK 0xFFFFFFFEU
 #define ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE__GPU_PAGE_FAULT_EN 0x00000001U
 
+/* Register ROGUE_CR_FAULT_FW_STATUS */
+#define ROGUE_CR_FAULT_FW_STATUS 0xF3B0U
+#define ROGUE_CR_FAULT_FW_STATUS_MASKFULL 0x0000000000010001ULL
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_SHIFT 16U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_EN 0x00010000U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_SHIFT 0U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_EN 0x00000001U
+
+/* Register ROGUE_CR_FAULT_FW_CLEAR */
+#define ROGUE_CR_FAULT_FW_CLEAR 0xF3B8U
+#define ROGUE_CR_FAULT_FW_CLEAR_MASKFULL 0x0000000000010001ULL
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_SHIFT 16U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_EN 0x00010000U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_SHIFT 0U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_EN 0x00000001U
+
 /* Register ROGUE_CR_MTS_SAFETY_EVENT_ENABLE */
 #define ROGUE_CR_MTS_SAFETY_EVENT_ENABLE__ROGUEXE 0xF3D8U
 #define ROGUE_CR_MTS_SAFETY_EVENT_ENABLE__ROGUEXE__MASKFULL 0x000000000000007FULL

-- 
2.48.1



From matt.coster at imgtec.com  Mon Mar 10 06:10:28 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Mon, 10 Mar 2025 13:10:28 +0000
Subject: [PATCH v3 04/18] drm/imagination: Use new generic compatible
 string
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <20250310-sets-bxs-4-64-patch-v1-v3-4-143b3dbef02f@imgtec.com>

Follow-on from the companion dt-bindings change ("dt-bindings: gpu: img:
More explicit compatible strings"), deprecating "img,img-axe" in favour of
the more explicit combination of "img,img-rogue" and "img,img-axe-1-16m".

Since all relevant details are interrogated from the device at runtime,
we can match on the generic "img,img-rogue" and avoid adding more entries
with NULL data members (barring hardware quirks).

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v3:
- Don't use more specific compatible strings when not required
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-5-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-5-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_drv.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 0639502137b4431dc23a349476572cc898d1f8d0..3130193f8fffc185e630a293be53374bdc4b7ce0 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1473,6 +1473,13 @@ static void pvr_remove(struct platform_device *plat_dev)
 }
 
 static const struct of_device_id dt_match[] = {
+	{ .compatible = "img,img-rogue", .data = NULL },
+
+	/*
+	 * This legacy compatible string was introduced early on before the more generic
+	 * "img,img-rogue" was added. Keep it around here for compatibility, but never use
+	 * "img,img-axe" in new devicetrees.
+	 */
 	{ .compatible = "img,img-axe", .data = NULL },
 	{}
 };

-- 
2.48.1



From andre.przywara at arm.com  Mon Mar 10 06:38:19 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 10 Mar 2025 13:38:19 +0000
Subject: [PATCH net-next 8/9] net: stmmac: sun8i: remove
 of_get_phy_mode()
In-Reply-To: <E1trbyA-005qYf-Hb@rmk-PC.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
	<E1trbyA-005qYf-Hb@rmk-PC.armlinux.org.uk>
Message-ID: <20250310133819.7c2204a6@donnerap.manchester.arm.com>

On Mon, 10 Mar 2025 12:10:54 +0000
"Russell King (Oracle)" <rmk+kernel at armlinux.org.uk> wrote:

Hi,

> devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
> which is stored in plat_dat->phy_interface. Therefore, we don't need to
> get it in platform code.
> 
> sun8i was using of_get_phy_mode() to set plat_dat->mac_interface, which
> defaults to plat_dat->phy_interface when the mac-mode DT property is
> not present. As nothing in arch/*/boot/dts sets the mac-mode property,
> it is highly likely that these two will be identical, and thus there
> is no need for this glue driver to set plat_dat->mac_interface.

Well, the current sun8i code wouldn't help anyway, because the driver
would set mac_interface to the value of "phy-mode", not "mac-mode", which
is strictly speaking a bug.
But in any case this is indeed redundant, so:

> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Reviewed-by: Andre Przywara <andre.przywara at arm.com>

Cheers,
Andre

> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 +-------
>  1 file changed, 1 insertion(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index 4b7b2582a120..85723a78793a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -1155,11 +1155,10 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
>  	struct stmmac_resources stmmac_res;
>  	struct sunxi_priv_data *gmac;
>  	struct device *dev = &pdev->dev;
> -	phy_interface_t interface;
> -	int ret;
>  	struct stmmac_priv *priv;
>  	struct net_device *ndev;
>  	struct regmap *regmap;
> +	int ret;
>  
>  	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
>  	if (ret)
> @@ -1219,10 +1218,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = of_get_phy_mode(dev->of_node, &interface);
> -	if (ret)
> -		return -EINVAL;
> -
>  	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
>  	if (IS_ERR(plat_dat))
>  		return PTR_ERR(plat_dat);
> @@ -1230,7 +1225,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
>  	/* platform data specifying hardware features and callbacks.
>  	 * hardware features were copied from Allwinner drivers.
>  	 */
> -	plat_dat->mac_interface = interface;
>  	plat_dat->rx_coe = STMMAC_RX_COE_TYPE2;
>  	plat_dat->tx_coe = 1;
>  	plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I;



From sudeep.holla at arm.com  Mon Mar 10 06:41:44 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 10 Mar 2025 13:41:44 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z87UJdhiTWhssnbl@bogus>
References: <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto>
 <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus>
 <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus>
Message-ID: <Z87sGF_jHKau_FMe@bogus>

On Mon, Mar 10, 2025 at 11:59:33AM +0000, Sudeep Holla wrote:
> On Mon, Mar 10, 2025 at 10:45:44AM +0000, Peng Fan wrote:
> > > Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> > > fwnode for scmi cpufreq
> > > 
> > > On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
> > > >
> > > > Sorry, if I misunderstood.
> > > >
> > > > I will give a look on this and propose a RFC.
> > > >
> > > > DT maintainers may ask for a patchset including binding change and
> > > > driver changes to get a whole view on the compatible stuff.
> > > >
> > > > BTW, Cristian, Saravana if you have any objections/ideas or would
> > > take
> > > > on this effort, please let me know.
> > > >
> > > 
> > > Can you point me to the DTS with which you are seeing this issue ?
> > > I am trying to reproduce the issue but so far not successful. I did move
> > > to power-domains for CPUFreq on Juno. IIUC all we need is both
> > > cpufreq and performance genpd drivers in the kernel and then GPU
> > > using perf genpd fails with probe deferral right ? I need pointers to
> > > reproduce the issue so that I can check if what I have cooked up as a
> > > solution really works.
> >
> > This is in downstream tree:
> > https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L2971
> > https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L3043
> > https://github.com/nxp-imx/linux-imx/blob/lf-6.6.y/arch/arm64/boot/dts/freescale/imx95.dtsi#L80
> >
> > we are using "power-domains" property for cpu perf and gpu/vpu perf.
> >
> > If cpufreq.off=1 is set in bootargs, the vpu/gpu driver will defer probe.
> >
> 
> OK, does the probe of these drivers get called or they don't as the driver
> core doesn't allow that ? I just have a dummy driver for mali on Juno
> which just does dev_pm_domain_attach_list() in the probe and it seem to
> succeed even when cpufreq.off=1 is passed. I see scmi-cpufreq failing
> with -ENODEV as expected.
> 
> I need to follow the code and check if I can somehow reproduce. Also are
> you sure this is not with anything in the downstream code ? Also have you
> tried this with v6.14-rc* ? Are you sure all the fw_devlink code is backported
> in the tree you pointed me which is v6.6-stable ?
> 

I even tried the above branch, but no luck. The above is neither latest
stable version nor pure stable. It has few extra patches backported
though IIUC. Anyways any pointers to enable me to reproduce the issue
would be much appreciated.

-- 
Regards,
Sudeep


From ltykernel at gmail.com  Mon Mar 10 06:41:57 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 21:41:57 +0800
Subject: [PATCH hyperv-next v5 09/11] Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
In-Reply-To: <20250307220304.247725-10-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com> <20250307220304.247725-10-romank@linux.microsoft.com>
Message-ID: <CAMvTesCFZ6sxQp7qqSDjD9idRjVHxh96Sp4betomgFH-OFLZ3Q@mail.gmail.com>

On Sat, Mar 8, 2025 at 6:05?AM Roman Kisel <romank at linux.microsoft.com> wrote:
>
> The ARM64 PCI code for hyperv needs to know the VMBus root
> device, and it is private.
>
> Provide a function that returns it. Rename it from "hv_dev"
> as "hv_dev" as a symbol is very overloaded. No functional
> changes.
>
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>

Why change all device's parent to vmbus_root_device?

The ARM64 platform uses the device tree to enumerate vmbus
devices..  Can we find the root device via device tree? vmbus
code on the x86 use ACPI and it seems to work via ACPI.


> ---
>  drivers/hv/vmbus_drv.c | 23 +++++++++++++++--------
>  include/linux/hyperv.h |  2 ++
>  2 files changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index c8474b48dcd2..7bfafe702963 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -45,7 +45,8 @@ struct vmbus_dynid {
>         struct hv_vmbus_device_id id;
>  };
>
> -static struct device  *hv_dev;
> +/* VMBus Root Device */
> +static struct device  *vmbus_root_device;
>
>  static int hyperv_cpuhp_online;
>
> @@ -80,9 +81,15 @@ static struct resource *fb_mmio;
>  static struct resource *hyperv_mmio;
>  static DEFINE_MUTEX(hyperv_mmio_lock);
>
> +struct device *hv_get_vmbus_root_device(void)
> +{
> +       return vmbus_root_device;
> +}
> +EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
> +
>  static int vmbus_exists(void)
>  {
> -       if (hv_dev == NULL)
> +       if (vmbus_root_device == NULL)
>                 return -ENODEV;
>
>         return 0;
> @@ -861,7 +868,7 @@ static int vmbus_dma_configure(struct device *child_device)
>          * On x86/x64 coherence is assumed and these calls have no effect.
>          */
>         hv_setup_dma_ops(child_device,
> -               device_get_dma_attr(hv_dev) == DEV_DMA_COHERENT);
> +               device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
>         return 0;
>  }
>
> @@ -1930,7 +1937,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
>                      &child_device_obj->channel->offermsg.offer.if_instance);
>
>         child_device_obj->device.bus = &hv_bus;
> -       child_device_obj->device.parent = hv_dev;
> +       child_device_obj->device.parent = vmbus_root_device;
>         child_device_obj->device.release = vmbus_device_release;
>
>         child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
> @@ -2292,7 +2299,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
>         struct acpi_device *ancestor;
>         struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
>
> -       hv_dev = &device->dev;
> +       vmbus_root_device = &device->dev;
>
>         /*
>          * Older versions of Hyper-V for ARM64 fail to include the _CCA
> @@ -2383,7 +2390,7 @@ static int vmbus_device_add(struct platform_device *pdev)
>         struct device_node *np = pdev->dev.of_node;
>         int ret;
>
> -       hv_dev = &pdev->dev;
> +       vmbus_root_device = &pdev->dev;
>
>         ret = of_range_parser_init(&parser, np);
>         if (ret)
> @@ -2702,7 +2709,7 @@ static int __init hv_acpi_init(void)
>         if (ret)
>                 return ret;
>
> -       if (!hv_dev) {
> +       if (!vmbus_root_device) {
>                 ret = -ENODEV;
>                 goto cleanup;
>         }
> @@ -2733,7 +2740,7 @@ static int __init hv_acpi_init(void)
>
>  cleanup:
>         platform_driver_unregister(&vmbus_platform_driver);
> -       hv_dev = NULL;
> +       vmbus_root_device = NULL;
>         return ret;
>  }
>
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 7f4f8d8bdf43..1f0851fde041 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1333,6 +1333,8 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
>         return dev_get_drvdata(&dev->device);
>  }
>
> +struct device *hv_get_vmbus_root_device(void);
> +
>  struct hv_ring_buffer_debug_info {
>         u32 current_interrupt_mask;
>         u32 current_read_index;
> --
> 2.43.0
>
>


-- 
Thanks
Tianyu Lan


From michal.kubiak at intel.com  Mon Mar 10 06:42:37 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Mon, 10 Mar 2025 14:42:37 +0100
Subject: [PATCH net-next 0/9] net: stmmac: remove unnecessary
 of_get_phy_mode() calls
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <Z87sTf8ZzMIpjXEw@localhost.localdomain>

On Mon, Mar 10, 2025 at 12:08:54PM +0000, Russell King (Oracle) wrote:
> Hi,
> 
> This series removes unnecessary of_get_phy_mode() calls from the stmmac
> glue drivers. stmmac_probe_config_dt() / devm_stmmac_probe_config_dt()
> already gets the interface mode using device_get_phy_mode() and stores
> it in plat_dat->phy_interface.
> 
> Therefore, glue drivers using of_get_phy_mode() are just duplicating
> the work that has already been done.
> 
> This series adjusts the glue drivers to remove their usage of
> of_get_phy_mode().
> 

The series looks reasonable.

Thanks,
Michal

For the series:
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>


From ltykernel at gmail.com  Mon Mar 10 06:44:55 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Mon, 10 Mar 2025 21:44:55 +0800
Subject: [PATCH hyperv-next v5 04/11] Drivers: hv: Provide arch-neutral
 implementation of get_vtl()
In-Reply-To: <20250307220304.247725-5-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com> <20250307220304.247725-5-romank@linux.microsoft.com>
Message-ID: <CAMvTesC+McATYa-xsi0omJ0LnFUUUooBk_r+oYSHYimyXPz5ZA@mail.gmail.com>

On Sat, Mar 8, 2025 at 6:04?AM Roman Kisel <romank at linux.microsoft.com> wrote:
>
> To run in the VTL mode, Hyper-V drivers have to know what
> VTL the system boots in, and the arm64/hyperv code does not
> have the means to compute that.
>
> Refactor the code to hoist the function that detects VTL,
> make it arch-neutral to be able to employ it to get the VTL
> on arm64.
>
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> ---
Reviewed-by: Tianyu Lan <tiala at microsoft.com>

-- 
Thanks
Tianyu Lan


From ryan.roberts at arm.com  Mon Mar 10 06:48:53 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 10 Mar 2025 13:48:53 +0000
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com>
References: <20250310062812.216031-1-anshuman.khandual@arm.com>
 <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <b1fb982a-4936-4c18-aaad-3e8e8f61bccc@arm.com>

On 10/03/2025 10:55, Mark Rutland wrote:
> On Mon, Mar 10, 2025 at 11:58:12AM +0530, Anshuman Khandual wrote:
>> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
>> section mapping at all page table levels except the last level. This works
>> fine as the section mapping masks are exactly the same (0x1UL) for all page
>> table levels.
>>
>> This will change in the future with D128 page tables that have unique skip
>> level values (SKL) required for creating section mapping at different page
>> table levels. Hence use page table level specific section mapping macros
>> instead of the common PMD_TYPE_SECT. While here also ensure that a section
>> mapping is only created on page table levels which could support that on a
>> given page size configuration otherwise fall back to create table entries.
>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: linux-kernel at vger.kernel.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>> This patch applies on v6.14-rc6
>>
>> Changes in V2:
>>
>> - Dropped PGD_TYPE_SECT macro and its instance from map_range()
>> - Create table entries on levels where section mapping is not possible
> 
> On the last version, there was talk of an extant bug:
> 
>   https://lore.kernel.org/all/5f1b36e2-6455-44d9-97b0-253aefd5024f at arm.com/
> 
> ... did that turn out to not be the case?

In the absence of Ard (or anyone else) telling me it's not a bug, then I'll
continue to assert that it is a bug, and should have a Fixes tag, and Cc stable.

> 
>>
>> Changes in V1:
>>
>> https://lore.kernel.org/all/20250303041834.2796751-1-anshuman.khandual at arm.com/
>>
>>  arch/arm64/kernel/pi/map_range.c | 38 +++++++++++++++++++++++++++++---
>>  1 file changed, 35 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 2b69e3beeef8..25a70c675c4d 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -11,6 +11,22 @@
>>  
>>  #include "pi.h"
>>  
>> +static bool sect_supported(int level)
> 
> What exactly is this function supposed to indicate?
> 
> Due to the 'default' case, it'll return true for level-3 tables where
> sections/blocks aren't possible, but pages are. So maybe this is just
> misnamed, and wants to be something like "leaf_supported()" ?

I always thought a "section" was (outdated?) linux terminology for a leaf
mapping at any level. For my understanding, I think you're saying it
specifically means a leaf mapping at any level other than the last level, so it
is actually equivalent to a "block" mapping in the Arm ARM?

Either way, the intended semantic for this function is "is it valid to create a
leaf mapping at the specified level?" where leaf = block or page.

Thanks,
Ryan

> 
>> +{
>> +	switch (level) {
>> +	case -1:
>> +		return false;
>> +	case 0:
>> +		if (IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
>> +		    IS_ENABLED(CONFIG_ARM64_64K_PAGES))
>> +			return false;
>> +		else
>> +			return true;
> 
> Surely:
> 
> 	case 0:
> 		return IS_ENABLED(CONFIG_ARM64_4K_PAGES);
> 
> ... though that's only the case when LPA2 is supported and TCR_ELx.DS is
> set.
> 
>> +	default:
>> +		return true;
> 
> As above, what is this supposed to return for level-3 tables where
> sections/blocks aren't possible?
> 
> Can we BUILD_BUG() for bogus levels?
> 
>> +	}
>> +}
>> +
>>  /**
>>   * map_range - Map a contiguous range of physical pages into virtual memory
>>   *
>> @@ -44,13 +60,29 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>>  	 * Set the right block/page bits for this level unless we are
>>  	 * clearing the mapping
>>  	 */
>> -	if (protval)
>> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
>> +	if (protval && sect_supported(level)) {
> 
> The existing code is trying to find the leaf prot for a given level of
> table, so as-is checking sect_supported() is at best misleading.
> 
> If we're going to do something different below based on
> sect_supported(), I reckon this should be moved into the path where
> sect_supported() returned true, maybe factored out into a helper for
> clarity.
> 
> Mark.
> 
>> +		switch (level) {
>> +		case 3:
>> +			protval |= PTE_TYPE_PAGE;
>> +			break;
>> +		case 2:
>> +			protval |= PMD_TYPE_SECT;
>> +			break;
>> +		case 1:
>> +			protval |= PUD_TYPE_SECT;
>> +			break;
>> +		case 0:
>> +			protval |= P4D_TYPE_SECT;
>> +			break;
>> +		default:
>> +			break;
>> +		}
>> +	}
>>  
>>  	while (start < end) {
>>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>>  
>> -		if (level < 3 && (start | next | pa) & lmask) {
>> +		if ((level < 3 && (start | next | pa) & lmask) || !sect_supported(level)) {
>>  			/*
>>  			 * This chunk needs a finer grained mapping. Create a
>>  			 * table mapping if necessary and recurse.
>> -- 
>> 2.25.1
>>
>>



From patrice.chotard at foss.st.com  Mon Mar 10 06:52:26 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Mon, 10 Mar 2025 14:52:26 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <20250219080059.367045-5-patrice.chotard@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
Message-ID: <6e1757ea-3f5e-4cc0-b142-aee52f016c8f@foss.st.com>



On 2/19/25 09:00, patrice.chotard at foss.st.com wrote:
> From: Patrice Chotard <patrice.chotard at foss.st.com>
> 
> Octo Memory Manager driver (OMM) manages:
>   - the muxing between 2 OSPI busses and 2 output ports.
>     There are 4 possible muxing configurations:
>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>         output is on port 2
>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>         OSPI2 output is on port 1
>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>   - the split of the memory area shared between the 2 OSPI instances.
>   - chip select selection override.
>   - the time between 2 transactions in multiplexed mode.
>   - check firewall access.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
> Signed-off-by: Christophe Kerello <christophe.kerello at foss.st.com>
> ---
>  drivers/memory/Kconfig     |  17 ++
>  drivers/memory/Makefile    |   1 +
>  drivers/memory/stm32_omm.c | 522 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 540 insertions(+)
>  create mode 100644 drivers/memory/stm32_omm.c
> 
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index c82d8d8a16ea..3a0703fbfee7 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -225,6 +225,23 @@ config STM32_FMC2_EBI
>  	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
>  	  SOCs containing the FMC2 External Bus Interface.
>  
> +config STM32_OMM
> +	tristate "STM32 Octo Memory Manager"
> +	depends on SPI_STM32_OSPI || COMPILE_TEST
> +	help
> +	  This driver manages the muxing between the 2 OSPI busses and
> +	  the 2 output ports. There are 4 possible muxing configurations:
> +	  - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
> +	       output is on port 2
> +	  - OSPI1 and OSPI2 are multiplexed over the same output port 1
> +	  - swapped mode (no multiplexing), OSPI1 output is on port 2,
> +	       OSPI2 output is on port 1
> +	  - OSPI1 and OSPI2 are multiplexed over the same output port 2
> +	  It also manages :
> +	    - the split of the memory area shared between the 2 OSPI instances.
> +	    - chip select selection override.
> +	    - the time between 2 transactions in multiplexed mode.
> +
>  source "drivers/memory/samsung/Kconfig"
>  source "drivers/memory/tegra/Kconfig"
>  
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index d2e6ca9abbe0..c1959661bf63 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_DA8XX_DDRCTL)	+= da8xx-ddrctl.o
>  obj-$(CONFIG_PL353_SMC)		+= pl353-smc.o
>  obj-$(CONFIG_RENESAS_RPCIF)	+= renesas-rpc-if.o
>  obj-$(CONFIG_STM32_FMC2_EBI)	+= stm32-fmc2-ebi.o
> +obj-$(CONFIG_STM32_OMM)		+= stm32_omm.o
>  
>  obj-$(CONFIG_SAMSUNG_MC)	+= samsung/
>  obj-$(CONFIG_TEGRA_MC)		+= tegra/
> diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c
> new file mode 100644
> index 000000000000..8f7f475769e7
> --- /dev/null
> +++ b/drivers/memory/stm32_omm.c
> @@ -0,0 +1,522 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
> + * Author(s): Patrice Chotard <patrice.chotard at foss.st.com> for STMicroelectronics.
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/bus/stm32_firewall_device.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#define OMM_CR			0
> +#define CR_MUXEN		BIT(0)
> +#define CR_MUXENMODE_MASK	GENMASK(1, 0)
> +#define CR_CSSEL_OVR_EN		BIT(4)
> +#define CR_CSSEL_OVR_MASK	GENMASK(6, 5)
> +#define CR_REQ2ACK_MASK		GENMASK(23, 16)
> +
> +#define OMM_CHILD_NB		2
> +
> +struct ospi_child {
> +	struct device *dev;
> +	struct device_node *node;
> +	struct clk *clk;
> +};
> +
> +struct stm32_omm {
> +	struct ospi_child child[OMM_CHILD_NB];
> +	struct resource *mm_res;
> +	struct clk *clk;
> +	void __iomem *io_base;
> +	u32 cr;
> +	u8 nb_child;
> +	bool restore_omm;
> +};
> +
> +static int stm32_omm_set_amcr(struct device *dev, bool set)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	struct regmap *syscfg_regmap;
> +	struct device_node *node;
> +	struct resource res, res1;
> +	resource_size_t mm_ospi2_size = 0;
> +	static const char * const mm_name[] = { "ospi1", "ospi2" };
> +	u32 amcr_base, amcr_mask;
> +	int ret, idx;
> +	unsigned int i, amcr, read_amcr;
> +
> +	for (i = 0; i < omm->nb_child; i++) {
> +		idx = of_property_match_string(dev->of_node,
> +					       "memory-region-names",
> +					       mm_name[i]);
> +		if (idx < 0)
> +			continue;
> +
> +		/* res1 only used on second loop iteration */
> +		res1.start = res.start;
> +		res1.end = res.end;
> +
> +		node = of_parse_phandle(dev->of_node, "memory-region", idx);
> +		if (!node)
> +			continue;
> +
> +		ret = of_address_to_resource(node, 0, &res);
> +		if (ret) {
> +			dev_err(dev, "unable to resolve memory region\n");
> +			return ret;
> +		}
> +
> +		/* check that memory region fits inside OMM memory map area */
> +		if (!resource_contains(omm->mm_res, &res)) {
> +			dev_err(dev, "%s doesn't fit inside OMM memory map area\n",
> +				mm_name[i]);
> +			dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res);
> +
> +			return -EFAULT;
> +		}
> +
> +		if (i == 1) {
> +			mm_ospi2_size = resource_size(&res);
> +
> +			/* check that OMM memory region 1 doesn't overlap memory region 2 */
> +			if (resource_overlaps(&res, &res1)) {
> +				dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
> +					mm_name[0], mm_name[1]);
> +				dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
> +
> +				return -EFAULT;
> +			}
> +		}
> +	}
> +
> +	syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
> +	if (IS_ERR(syscfg_regmap)) {
> +		dev_err(dev, "Failed to get st,syscfg-amcr property\n");
> +		return PTR_ERR(syscfg_regmap);
> +	}
> +
> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
> +					 &amcr_base);
> +	if (ret)
> +		return ret;
> +
> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
> +					 &amcr_mask);
> +	if (ret)
> +		return ret;
> +
> +	amcr = mm_ospi2_size / SZ_64M;
> +
> +	if (set)
> +		regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
> +
> +	/* read AMCR and check coherency with memory-map areas defined in DT */
> +	regmap_read(syscfg_regmap, amcr_base, &read_amcr);
> +	read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
> +
> +	if (amcr != read_amcr) {
> +		dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static int stm32_omm_enable_child_clock(struct device *dev, bool enable)
> +{
> +	/* As there is only 2 children, remember first child in case of error */
> +	struct clk *first_child_clk = NULL;
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	u8 i;
> +	int ret;
> +
> +	for (i = 0; i < omm->nb_child; i++) {
> +		if (enable) {
> +			ret = clk_prepare_enable(omm->child[i].clk);
> +			if (ret) {
> +				if (first_child_clk)
> +					clk_disable_unprepare(first_child_clk);
> +
> +				dev_err(dev, "Can not enable clock\n");
> +				return ret;
> +			}
> +		} else {
> +			clk_disable_unprepare(omm->child[i].clk);
> +		}
> +
> +		first_child_clk = omm->child[i].clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_omm_configure(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	struct reset_control *rstc;
> +	unsigned long clk_rate, clk_rate_max = 0;
> +	int ret;
> +	u8 i;
> +	u32 mux = 0;
> +	u32 cssel_ovr = 0;
> +	u32 req2ack = 0;
> +
> +	omm->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(omm->clk)) {
> +		dev_err(dev, "Failed to get OMM clock (%ld)\n",
> +			PTR_ERR(omm->clk));
> +
> +		return PTR_ERR(omm->clk);
> +	}
> +
> +	ret = pm_runtime_resume_and_get(dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* parse children's clock */
> +	for (i = 0; i < omm->nb_child; i++) {
> +		clk_rate = clk_get_rate(omm->child[i].clk);
> +		if (!clk_rate) {
> +			dev_err(dev, "Invalid clock rate\n");
> +			pm_runtime_disable(dev);
> +			goto err_clk_disable;
> +		}
> +
> +		if (clk_rate > clk_rate_max)
> +			clk_rate_max = clk_rate;
> +	}
> +
> +	rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
> +	if (IS_ERR(rstc)) {
> +		ret = dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
> +		pm_runtime_disable(dev);
> +		goto err_clk_disable;
> +	}
> +
> +	reset_control_assert(rstc);
> +	udelay(2);
> +	reset_control_deassert(rstc);
> +
> +	omm->cr = readl_relaxed(omm->io_base + OMM_CR);
> +	/* optional */
> +	ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
> +	if (!ret) {
> +		if (mux & CR_MUXEN) {
> +			ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
> +						   &req2ack);
> +			if (!ret && !req2ack) {
> +				req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
> +
> +				if (req2ack > 256)
> +					req2ack = 256;
> +			}
> +
> +			req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
> +
> +			omm->cr &= ~CR_REQ2ACK_MASK;
> +			omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
> +
> +			/*
> +			 * If the mux is enabled, the 2 OSPI clocks have to be
> +			 * always enabled
> +			 */
> +			ret = stm32_omm_enable_child_clock(dev, true);
> +			if (ret) {
> +				pm_runtime_disable(dev);
> +				goto err_clk_disable;
> +			}
> +		}
> +
> +		omm->cr &= ~CR_MUXENMODE_MASK;
> +		omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
> +	}
> +
> +	/* optional */
> +	ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
> +	if (!ret) {
> +		omm->cr &= ~CR_CSSEL_OVR_MASK;
> +		omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
> +		omm->cr |= CR_CSSEL_OVR_EN;
> +	}
> +
> +	omm->restore_omm = true;
> +	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
> +
> +	ret = stm32_omm_set_amcr(dev, true);
> +
> +err_clk_disable:
> +	pm_runtime_put_sync_suspend(dev);
> +
> +	return ret;
> +}
> +
> +static int stm32_omm_check_access(struct device *dev, struct device_node *np)
> +{
> +	struct stm32_firewall firewall;
> +	int ret;
> +
> +	ret = stm32_firewall_get_firewall(np, &firewall, 1);
> +	if (ret)
> +		return ret;
> +
> +	return stm32_firewall_grant_access(&firewall);
> +}
> +
> +static int stm32_omm_disable_child(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	struct reset_control *reset;
> +	int ret;
> +	u8 i;
> +
> +	for (i = 0; i < omm->nb_child; i++) {
> +		ret = clk_prepare_enable(omm->child[i].clk);
> +		if (ret) {
> +			dev_err(dev, "Can not enable clock\n");
> +			return ret;
> +		}
> +
> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
> +		if (IS_ERR(reset)) {
> +			dev_err(dev, "Can't get child reset\n");
> +			return PTR_ERR(reset);
> +		};
> +
> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
> +		reset_control_assert(reset);
> +		udelay(2);
> +		reset_control_deassert(reset);
> +
> +		reset_control_put(reset);
> +		clk_disable_unprepare(omm->child[i].clk);
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_omm_probe(struct platform_device *pdev)
> +{
> +	struct platform_device *vdev;
> +	struct device *dev = &pdev->dev;
> +	struct stm32_omm *omm;
> +	struct clk *clk;
> +	int ret;
> +	u8 child_access_granted = 0;
> +	u8 i, j;
> +	bool child_access[OMM_CHILD_NB];
> +
> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
> +	if (!omm)
> +		return -ENOMEM;
> +
> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
> +	if (IS_ERR(omm->io_base))
> +		return PTR_ERR(omm->io_base);
> +
> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
> +	if (IS_ERR(omm->mm_res))
> +		return PTR_ERR(omm->mm_res);
> +
> +	/* check child's access */
> +	for_each_child_of_node_scoped(dev->of_node, child) {
> +		if (omm->nb_child >= OMM_CHILD_NB) {
> +			dev_err(dev, "Bad DT, found too much children\n");
> +			ret = -E2BIG;
> +			goto err_clk_release;
> +		}
> +
> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
> +			ret = -EINVAL;
> +			goto err_clk_release;
> +		}
> +
> +		ret = stm32_omm_check_access(dev, child);
> +		if (ret < 0 && ret != -EACCES)
> +			goto err_clk_release;
> +
> +		child_access[omm->nb_child] = false;
> +		if (!ret) {
> +			child_access_granted++;
> +			child_access[omm->nb_child] = true;
> +		}
> +
> +		omm->child[omm->nb_child].node = child;
> +
> +		clk = of_clk_get(child, 0);
> +		if (IS_ERR(clk)) {
> +			dev_err(dev, "Can't get child clock\n");
> +			ret = PTR_ERR(clk);
> +			goto err_clk_release;
> +		};
> +
> +		omm->child[omm->nb_child].clk = clk;
> +		omm->nb_child++;
> +	}
> +
> +	if (omm->nb_child != OMM_CHILD_NB) {
> +		ret = -EINVAL;
> +		goto err_clk_release;
> +	}
> +
> +	platform_set_drvdata(pdev, omm);
> +
> +	pm_runtime_enable(dev);
> +
> +	/* check if OMM's resource access is granted */
> +	ret = stm32_omm_check_access(dev, dev->of_node);
> +	if (ret < 0 && ret != -EACCES)
> +		goto err_clk_release;
> +
> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
> +		/* Ensure both OSPI instance are disabled before configuring OMM */
> +		ret = stm32_omm_disable_child(dev);
> +		if (ret)
> +			goto err_clk_release;
> +
> +		ret = stm32_omm_configure(dev);
> +		if (ret)
> +			goto err_clk_release;
> +	} else {
> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
> +		/*
> +		 * AMCR can't be set, so check if current value is coherent
> +		 * with memory-map areas defined in DT
> +		 */
> +		ret = stm32_omm_set_amcr(dev, false);
> +		if (ret)
> +			goto err_clk_release;
> +	}
> +
> +	/* for each child, if resource access is granted and status "okay", probe it */
> +	for (i = 0; i < omm->nb_child; i++) {
> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
> +			continue;
> +
> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
> +		if (!vdev) {
> +			dev_err(dev, "Failed to create Octo Memory Manager child\n");
> +			for (j = i; j > 0; --j) {
> +				if (omm->child[j].dev)
> +					of_platform_device_destroy(omm->child[j].dev, NULL);
> +			}
> +
> +			ret = -EINVAL;
> +			goto err_clk_release;
> +		}
> +		omm->child[i].dev = &vdev->dev;
> +	}
> +
> +err_clk_release:
> +	for (i = 0; i < omm->nb_child; i++)
> +		clk_put(omm->child[i].clk);
> +
> +	return ret;
> +}
> +
> +static void stm32_omm_remove(struct platform_device *pdev)
> +{
> +	struct stm32_omm *omm = platform_get_drvdata(pdev);
> +	int i;
> +
> +	for (i = 0; i < omm->nb_child; i++)
> +		if (omm->child[i].dev)
> +			of_platform_device_destroy(omm->child[i].dev, NULL);
> +
> +	if (omm->cr & CR_MUXEN)
> +		stm32_omm_enable_child_clock(&pdev->dev, false);
> +
> +	pm_runtime_disable(&pdev->dev);
> +}
> +
> +static const struct of_device_id stm32_omm_of_match[] = {
> +	{ .compatible = "st,stm32mp25-omm", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
> +
> +static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(omm->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	return clk_prepare_enable(omm->clk);
> +}
> +
> +static int __maybe_unused stm32_omm_suspend(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	if (omm->restore_omm && omm->cr & CR_MUXEN)
> +		stm32_omm_enable_child_clock(dev, false);
> +
> +	return pinctrl_pm_select_sleep_state(dev);
> +}
> +
> +static int __maybe_unused stm32_omm_resume(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	int ret;
> +
> +	pinctrl_pm_select_default_state(dev);
> +
> +	if (!omm->restore_omm)
> +		return 0;
> +
> +	/* Ensure both OSPI instance are disabled before configuring OMM */
> +	ret = stm32_omm_disable_child(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = pm_runtime_resume_and_get(dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
> +	ret = stm32_omm_set_amcr(dev, true);
> +	pm_runtime_put_sync_suspend(dev);
> +	if (ret)
> +		return ret;
> +
> +	if (omm->cr & CR_MUXEN)
> +		ret = stm32_omm_enable_child_clock(dev, true);
> +
> +	return ret;
> +}
> +
> +static const struct dev_pm_ops stm32_omm_pm_ops = {
> +	SET_RUNTIME_PM_OPS(stm32_omm_runtime_suspend,
> +			   stm32_omm_runtime_resume, NULL)
> +	SET_SYSTEM_SLEEP_PM_OPS(stm32_omm_suspend, stm32_omm_resume)
> +};
> +
> +static struct platform_driver stm32_omm_driver = {
> +	.probe	= stm32_omm_probe,
> +	.remove = stm32_omm_remove,
> +	.driver	= {
> +		.name = "stm32-omm",
> +		.of_match_table = stm32_omm_of_match,
> +		.pm = &stm32_omm_pm_ops,
> +	},
> +};
> +module_platform_driver(stm32_omm_driver);
> +
> +MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
> +MODULE_LICENSE("GPL");


Hi all,

Anybody alse has additionnal remarks on this driver ?

Thanks
Patrice


From andrea.porta at suse.com  Mon Mar 10 06:59:41 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Mon, 10 Mar 2025 14:59:41 +0100
Subject: [PATCH v6 00/10] Add support for RaspberryPi RP1 PCI device
 using a DT overlay
In-Reply-To: <CAMEGJJ1++aeE7WWLVVesbujME+r2WicEkK+CQgigRRp2grYf=A@mail.gmail.com>
References: <CAMEGJJ3=W8_R0xBvm8r+Q7iExZx8xPBHEWWGAT9ngpGWDSKCaQ@mail.gmail.com>
 <20250213171435.1c2ce376@bootlin.com>
 <CAMEGJJ1++aeE7WWLVVesbujME+r2WicEkK+CQgigRRp2grYf=A@mail.gmail.com>
Message-ID: <Z87wTfChRC5Ruwc0@apocalypse>

Hi,

On 16:27 Thu 13 Feb     , Phil Elwell wrote:
> Hi Herv?,
> 
> On Thu, 13 Feb 2025 at 16:14, Herve Codina <herve.codina at bootlin.com> wrote:
> >
> > Hi Phil,
> >
> > On Thu, 13 Feb 2025 15:18:45 +0000
> > Phil Elwell <phil at raspberrypi.com> wrote:
> >
> > > Hi Andrea,
> > >
> > > The problem with this approach (loading an overlay from the RP1 PCIe
> > > driver), and it's one that I have raised with you offline, is that
> > > (unless anyone can prove otherwise) it becomes impossible to create a
> > > Pi 5 DTS file which makes use of the RP1's resources. How do you
> > > declare something as simple as a button wired to an RP1 GPIO, or fan
> > > connected to a PWM output?
> >
> > The driver could be improved in a second step.
> > For instance, it could load the dtbo from user-space using request_firmare()
> > instead of loading the embedded dtbo.
> >
> > >
> > > If this is the preferred route to upstream adoption, I would prefer it
> > > if rp1.dtso could be split in two - an rp1.dtsi similar to what we
> > > have downstream, and an rp1.dtso that #includes it. In this way we can
> > > keep the patching and duplication to a minimum.
> >
> > Indeed, having a rp1.dtsi avoid duplication but how the rp1.dtso in
> > the the kernel sources could include user customization (button, fan, ...)
> > without being modified ?
> > At least we have to '#include <my_rp1_customizations.dtsi>'.
> >
> > Requesting the dtbo from user-space allows to let the user to create
> > its own dtso without the need to modify the one in kernel sources.
> >
> > Does it make sense ?
> 
> I think I understand what you are saying, but at this point the RP1
> overlay would no longer be an RP1 overlay - it would be an
> RP1-and-everything-connected-to-it overlay, which is inherently
> board-specific. Which user-space process do you think would be
> responsible for loading this alternative overlay, choosing carefully
> based on the platform it is running on? Doesn't that place quite a
> burden on all the OS maintainers who up to now have just needed a
> kernel and a bunch of dtb files?
> 
> If it is considered essential that the upstream Pi 5 dts file does not
> include RP1 and its children, then Raspberry Pi are going to have to
> walk a different path until we've seen how that can work. By splitting
> rp1.dtso as I suggested, and perhaps providing an alternative helper
> function that only applies the built-in overlay if the device node
> doesn't already exist, we get to stay as close to upstream as
> possible.
> 
> Phil

So, the problem is twofold: the first is due to the fact that downstream
expects the dtb to be fully declared at fw load time (I'll call that
*monolithic* dtb from now on), the second is about how to represent dependencies
between board dtb and rp1 overlay which arises only when using overlays instead
of a monolithic dtb.

The former issue must be solved first in order for the latter to even exists
(if we don't use overlay, the dependencies are fully exposed in the dtb since
the beginning), so I'll concentrate on the former for now.

There are 3 possible scenarios to be reconciled:


1 - MONOLITHIC DTB

This is the downstream case, where it's advisable to have only one dtb blob
containing everything (rp1 included) loaded by the fw. In this case the
resulting devicetree would looks like:

  axi {
    pcie at 120000 {
      rp1_nexus {
        pci-ep-bus at 1 {
             ...
        }
      }
    }
  }


2 - RP1 LOADED FROM OVERLAY BY THE FW

In this case the rp1 dt node is loaded from overlay directly by the fw and the 
resulting devicetree is exactly equal to the monolithic dtb scenario.
In order for that overlay to be loaded by fw, just add 'dtoverlay=rp1' in
'config.txt'.


3 - RP1 LOADED FROM OVERLAY AT RUNTIME

Here it's the rp1 driver that loads the overlay at runtime, which is the case
that this patchset originally proposed. The devicetree ends up like this:

  axi {
    pcie at 120000 {
      pci at 0,0 {
        dev at 0,0 {
          pci-ep-bus at 1 {
               ...
          }
        }
      }
    }
  }

and this is exepcially useful to cope with the case in which there's no DT
natively used, e.g. on ACPI systems.


In order for all those 3 mentioned scenatios to work, I propose the following
inclusion scheme for for the dts files (the arrow points to the includer):
                   
 
 rp1-pci.dtso         rp1.dtso
     ^                    ^
     |                    |
rp1-common.dtsi ----> rp1-nexus.dtsi ----> bcm2712-rpi-5-b-MONOLITHIC.dts
   
   
where those dts are defined as follows (omitting the internal properties for
clarity sake):


- rp1-common.dtsi ------- // definition of core rp1 and its peripherals, common
			  // for all cases

	pci_ep_bus: pci-ep-bus at 1 
	{
		rp1_clocks { };

		rp1_gpio { };

		rp1_eth { };
	};

- rp1-pci.dtso ---------- // ovl linked in the rp1 driver code to be loaded at
			  // runtime from rp1 driver. Only for case 3

	/plugin/;
	fragment at 0 {
                target-path="";
                __overlay__ {
			#include "rp1-common.dtsi"
		};
	}

- rp1-nexus.dtsi ------- // adapter to decouple rp1 ranges for non runtime-loaded
		         // overlay case (i.e. only for case 1 and 2)

	rp1_nexus {
		ranges = ...
		
		 #include "rp1-common.dtsi"
	};

- rp1.dtso ------------ // overlay to be loaded by fw (case 2)

	/plugin/;
	&pcie2 {
		#include "rp1-nexus.dtsi"
	};

- bcm2712-rpi-5-b-MONOLITHIC.dts --- // monolithic dtb to avoid any overlay use
				     // (case 1)

	/ {
		... all rpi5 board dts ...
		&pcie2 {
        		#include "rp1-nexus.dtsi"
		};
	};


with only minimal changes to the rp1 driver code, I can confirm that all those
scenarios can coexits and are working fine. Before processding with a new patchset
I'd like to have some thoughts about that, do you think this is a viable approach?

Many thanks,
Andrea


From ziyao at disroot.org  Mon Mar 10 07:09:17 2025
From: ziyao at disroot.org (Yao Zi)
Date: Mon, 10 Mar 2025 14:09:17 +0000
Subject: [PATCH] arm64: dts: rockchip: Fix PWM pinctrl names
Message-ID: <20250310140916.14384-2-ziyao@disroot.org>

These Rockchip boards assign "active" as the pinctrl name for PWM
controllers, which has never been supported in mainline Rockchip PWM
driver. It seems the name used by downstream kernel is accidentally
brought into maineline. Let's fix them.

Fixes: 4403e1237be3 ("arm64: dts: rockchip: Add devicetree for board roc-rk3308-cc")
Fixes: 964ed0807b5f ("arm64: dts: rockchip: add rk3318 A95X Z2 board")
Fixes: e7a095908227 ("arm64: dts: rockchip: Add devicetree for NanoPC-T4")
Fixes: 3f5d336d64d6 ("arm64: dts: rockchip: Add support for rk3588s based board Cool Pi 4B")
Signed-off-by: Yao Zi <ziyao at disroot.org>
---

It's uncommon to have a commit carrying so many fix tags, but otherwise
four seperate small commits will be created with the same topic. I'm
willing to change this if it's inappropriate.

I don't have these boards for a real test, but the change should be the
right way.

Thanks for your time and review.

 arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts     | 2 +-
 arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts    | 4 ++--
 arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi   | 2 +-
 arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
index 629121de5a13..5e7181948992 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
@@ -147,7 +147,7 @@ rtc: rtc at 51 {
 
 &pwm5 {
 	status = "okay";
-	pinctrl-names = "active";
+	pinctrl-names = "default";
 	pinctrl-0 = <&pwm5_pin_pull_down>;
 };
 
diff --git a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
index a94114fb7cc1..96c27fc5005d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
@@ -274,13 +274,13 @@ otg_vbus_drv: otg-vbus-drv {
 
 &pwm0 {
 	pinctrl-0 = <&pwm0_pin_pull_up>;
-	pinctrl-names = "active";
+	pinctrl-names = "default";
 	status = "okay";
 };
 
 &pwm1 {
 	pinctrl-0 = <&pwm1_pin_pull_up>;
-	pinctrl-names = "active";
+	pinctrl-names = "default";
 	status = "okay";
 };
 
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
index b169be06d4d1..c8eb5481f43d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
@@ -603,7 +603,7 @@ &pwm1 {
 };
 
 &pwm2 {
-	pinctrl-names = "active";
+	pinctrl-names = "default";
 	pinctrl-0 = <&pwm2_pin_pull_down>;
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
index 8f00e0444c00..8b717c4017a4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
@@ -433,7 +433,7 @@ &pwm2 {
 };
 
 &pwm13 {
-	pinctrl-names = "active";
+	pinctrl-names = "default";
 	pinctrl-0 = <&pwm13m2_pins>;
 	status = "okay";
 };
-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Mon Mar 10 07:12:19 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 15:12:19 +0100
Subject: [PATCH 03/26] clk: mediatek: Support voting for mux
In-Reply-To: <20250307032942.10447-4-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
 <20250307032942.10447-4-guangjie.song@mediatek.com>
Message-ID: <cd8bd504-8d91-4420-8053-10ee814417bf@collabora.com>

Il 07/03/25 04:26, Guangjie Song ha scritto:
> Add data fields, defines and ops to support voting for mux.
> 

The main thing that is missing here is an answer to an obvious question....

...what are the advantages of hardware voting, and why do we need to use
HW voting instead of the refcount that is already kept by the common clock
framework?

As far as I can see here, the only difference is that the enable/disable
is more complex, losing more time for polling after writes and nothing else?

Is this to synchronize the clock voting between SCP and AP or what?!
If this is the answer, I don't see why we should use this HW voter for all
clocks, since it's simply more expensive (so the clock drivers are wrong as
they enable the voter for all clocks).


> Signed-off-by: Guangjie Song <guangjie.song at mediatek.com>
> ---
>   drivers/clk/mediatek/clk-mux.c | 198 ++++++++++++++++++++++++++++++++-
>   drivers/clk/mediatek/clk-mux.h |  79 +++++++++++++
>   2 files changed, 275 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
> index 60990296450b..8a2c89cb3cd5 100644
> --- a/drivers/clk/mediatek/clk-mux.c
> +++ b/drivers/clk/mediatek/clk-mux.c
> @@ -15,11 +15,13 @@
>   #include <linux/spinlock.h>
>   #include <linux/slab.h>
>   
> +#include "clk-mtk.h"
>   #include "clk-mux.h"
>   
>   struct mtk_clk_mux {
>   	struct clk_hw hw;
>   	struct regmap *regmap;
> +	struct regmap *vote_regmap;
>   	const struct mtk_mux *data;
>   	spinlock_t *lock;
>   	bool reparent;
> @@ -30,6 +32,46 @@ static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
>   	return container_of(hw, struct mtk_clk_mux, hw);
>   }
>   
> +static int mtk_clk_mux_fenc_enable_setclr(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	unsigned long flags = 0;
> +	u32 val = 0;
> +	int i = 0;
> +	int ret = 0;
> +
> +	if (mux->lock)
> +		spin_lock_irqsave(mux->lock, flags);
> +	else
> +		__acquire(mux->lock);
> +
> +	regmap_write(mux->regmap, mux->data->clr_ofs, BIT(mux->data->gate_shift));
> +
> +	while (1) {
> +		regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val);

Why are you reinventing the wheel instead of just using regmap_read_poll_timeout()?

> +
> +		if ((val & BIT(mux->data->fenc_shift)) != 0)
> +			break;
> +
> +		if (i < MTK_WAIT_FENC_DONE_CNT) {
> +			udelay(MTK_WAIT_FENC_DONE_US);
> +		} else {
> +			pr_err("%s wait fenc done timeout\n", clk_hw_get_name(hw));
> +			ret = -EBUSY;
> +			break;
> +		}
> +
> +		i++;
> +	}
> +
> +	if (mux->lock)
> +		spin_unlock_irqrestore(mux->lock, flags);
> +	else
> +		__release(mux->lock);
> +
> +	return ret;
> +}
> +
>   static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
>   {
>   	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> @@ -70,6 +112,16 @@ static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
>   			BIT(mux->data->gate_shift));
>   }
>   
> +static int mtk_clk_mux_fenc_is_enabled(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	u32 val = 0;
> +
> +	regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val);
> +
> +	return (val & BIT(mux->data->fenc_shift)) != 0;

That's just `return val & BIT(mux->data->fenc_shift);` ...

> +}
> +
>   static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
>   {
>   	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> @@ -80,6 +132,106 @@ static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
>   	return (val & BIT(mux->data->gate_shift)) == 0;
>   }
>   
> +static int mtk_clk_vote_mux_is_enabled(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	u32 val = 0;
> +
> +	regmap_read(mux->vote_regmap, mux->data->vote_set_ofs, &val);
> +
> +	return (val & BIT(mux->data->gate_shift)) != 0;

same

> +}
> +
> +static int mtk_clk_vote_mux_is_done(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	u32 val = 0;
> +
> +	regmap_read(mux->vote_regmap, mux->data->vote_sta_ofs, &val);
> +
> +	return (val & BIT(mux->data->gate_shift)) != 0;

ditto

> +}
> +
> +static int mtk_clk_mux_vote_fenc_enable(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	u32 val = 0, val2 = 0;
> +	bool is_done = false;
> +	int i = 0;
> +
> +	regmap_write(mux->vote_regmap, mux->data->vote_set_ofs, BIT(mux->data->gate_shift));
> +
> +	while (!mtk_clk_vote_mux_is_enabled(hw)) {
> +		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
> +			udelay(MTK_WAIT_VOTE_PREPARE_US);

regmap_readl_poll_timeout().....

> +		} else {
> +			pr_err("%s mux prepare timeout(%x)\n", clk_hw_get_name(hw), val);
> +			return -EBUSY;
> +		}
> +
> +		i++;
> +	}
> +
> +	i = 0;
> +
> +	while (1) {
> +		if (!is_done)
> +			regmap_read(mux->vote_regmap, mux->data->vote_sta_ofs, &val);
> +
> +		if (((val & BIT(mux->data->gate_shift)) != 0))
> +			is_done = true;
> +

and again - twice.

> +		if (is_done) {
> +			regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val2);
> +			if ((val2 & BIT(mux->data->fenc_shift)) != 0)
> +				break;
> +		}
> +
> +		if (i < MTK_WAIT_VOTE_DONE_CNT) {
> +			udelay(MTK_WAIT_VOTE_DONE_US);
> +		} else {
> +			pr_err("%s mux enable timeout(%x %x)\n", clk_hw_get_name(hw), val, val2);
> +			return -EBUSY;
> +		}
> +
> +		i++;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mtk_clk_mux_vote_disable(struct clk_hw *hw)
> +{
> +	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> +	int i = 0;
> +
> +	regmap_write(mux->vote_regmap, mux->data->vote_clr_ofs, BIT(mux->data->gate_shift));
> +
> +	while (mtk_clk_vote_mux_is_enabled(hw)) {
> +		if (i < MTK_WAIT_VOTE_PREPARE_CNT) {
> +			udelay(MTK_WAIT_VOTE_PREPARE_US);
> +		} else {
> +			pr_err("%s mux unprepare timeout\n", clk_hw_get_name(hw));
> +			return;
> +		}
> +

....and again....

> +		i++;
> +	}
> +
> +	i = 0;
> +
> +	while (!mtk_clk_vote_mux_is_done(hw)) {
> +		if (i < MTK_WAIT_VOTE_DONE_CNT) {
> +			udelay(MTK_WAIT_VOTE_DONE_US);
> +		} else {
> +			pr_err("%s mux disable timeout\n", clk_hw_get_name(hw));
> +			return;
> +		}
> +
> +		i++;
> +	}
> +}
> +
>   static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
>   {
>   	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> @@ -151,6 +303,12 @@ static int mtk_clk_mux_determine_rate(struct clk_hw *hw,
>   	return clk_mux_determine_rate_flags(hw, req, mux->data->flags);
>   }
>   
> +static void mtk_clk_mux_vote_fenc_disable_unused(struct clk_hw *hw)
> +{
> +	mtk_clk_mux_vote_fenc_enable(hw);
> +	mtk_clk_mux_vote_disable(hw);

Why would you need to enable and disable?

If this is not a mistake... this definitely needs a comment in the code.

> +}
> +
>   const struct clk_ops mtk_mux_clr_set_upd_ops = {
>   	.get_parent = mtk_clk_mux_get_parent,
>   	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
> @@ -168,9 +326,31 @@ const struct clk_ops mtk_mux_gate_clr_set_upd_ops  = {
>   };
>   EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops);
>   
> +const struct clk_ops mtk_mux_gate_fenc_clr_set_upd_ops = {
> +	.enable = mtk_clk_mux_fenc_enable_setclr,
> +	.disable = mtk_clk_mux_disable_setclr,
> +	.is_enabled = mtk_clk_mux_fenc_is_enabled,
> +	.get_parent = mtk_clk_mux_get_parent,
> +	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
> +	.determine_rate = mtk_clk_mux_determine_rate,
> +};
> +EXPORT_SYMBOL_GPL(mtk_mux_gate_fenc_clr_set_upd_ops);
> +
> +const struct clk_ops mtk_mux_vote_fenc_ops = {
> +	.enable = mtk_clk_mux_vote_fenc_enable,
> +	.disable = mtk_clk_mux_vote_disable,
> +	.is_enabled = mtk_clk_mux_fenc_is_enabled,
> +	.get_parent = mtk_clk_mux_get_parent,
> +	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
> +	.determine_rate = mtk_clk_mux_determine_rate,
> +	.disable_unused = mtk_clk_mux_vote_fenc_disable_unused,
> +};
> +EXPORT_SYMBOL_GPL(mtk_mux_vote_fenc_ops);
> +
>   static struct clk_hw *mtk_clk_register_mux(struct device *dev,
>   					   const struct mtk_mux *mux,
>   					   struct regmap *regmap,
> +					   struct regmap *vote_regmap,
>   					   spinlock_t *lock)
>   {
>   	struct mtk_clk_mux *clk_mux;
> @@ -185,9 +365,17 @@ static struct clk_hw *mtk_clk_register_mux(struct device *dev,
>   	init.flags = mux->flags;
>   	init.parent_names = mux->parent_names;
>   	init.num_parents = mux->num_parents;
> -	init.ops = mux->ops;
> +	if (mux->flags & CLK_USE_VOTE) {
> +		if (vote_regmap)
> +			init.ops = mux->ops;
> +		else
> +			init.ops = mux->dma_ops;

Sorry why is this called dma_ops?!
That's at least confusing, if not simply wrong.... please explain.

> +	} else {
> +		init.ops = mux->ops;
> +	}
>   
>   	clk_mux->regmap = regmap;
> +	clk_mux->vote_regmap = vote_regmap;
>   	clk_mux->data = mux;
>   	clk_mux->lock = lock;
>   	clk_mux->hw.init = &init;
> @@ -220,6 +408,7 @@ int mtk_clk_register_muxes(struct device *dev,
>   			   struct clk_hw_onecell_data *clk_data)
>   {
>   	struct regmap *regmap;
> +	struct regmap *vote_regmap = NULL;
>   	struct clk_hw *hw;
>   	int i;
>   
> @@ -238,8 +427,13 @@ int mtk_clk_register_muxes(struct device *dev,
>   			continue;
>   		}
>   
> -		hw = mtk_clk_register_mux(dev, mux, regmap, lock);
> +		if (mux->vote_comp) {
> +			vote_regmap = syscon_regmap_lookup_by_phandle(node, mux->vote_comp);
> +			if (IS_ERR(vote_regmap))
> +				vote_regmap = NULL;
> +		}
>   
> +		hw = mtk_clk_register_mux(dev, mux, regmap, vote_regmap, lock);

...and this change just breaks each and every MediaTek SoC that is currently
supported upstream.

Please test your changes on older platforms before submitting upstream.

Regards,
Angelo



From alyssa at rosenzweig.io  Mon Mar 10 07:14:07 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Mon, 10 Mar 2025 10:14:07 -0400
Subject: [PATCH] drm: Add UAPI for the Asahi driver
Message-ID: <20250310-agx-uapi-v1-1-86c80905004e@rosenzweig.io>

This adds the UAPI for the Asahi driver targeting the GPU in the Apple
M1 and M2 series systems on chip. The UAPI design is based on other
modern Vulkan-capable drivers, including Xe and Panthor. Memory
management is based on explicit VM management. Synchronization is
exclusively explicit sync.

This UAPI is validated against our open source Mesa stack, which is
fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
VM_BIND mechanism.

This patch adds the standalone UAPI header. It is implemented by an open
source DRM driver written in Rust. We fully intend to upstream this
driver when possible. However, as a production graphics driver, it
depends on a significant number of Rust abstractions that will take a
long time to upstream. In the mean time, our userspace is upstream in
Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
yet reviewed and merged in the upstream kernel. Although we ship a
patched Mesa in Fedora Asahi Remix, any containers shipping upstream
Mesa builds are broken for our users, including upstream Flatpak and
Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
and virglrenderer, which complicates bisects.

The intention in sending out this patch is for this UAPI to be
thoroughly reviewed. Once we as the DRM community are satisfied with the
UAPI, this header lands signifying that the UAPI is stable and must only
be evolved in backwards-compatible ways; it will be the UAPI implemented
in the DRM driver that eventually lands upstream. That promise lets us
enable upstream Mesa, solving all these issues while the upstream Rust
abstractions are developed.

https://github.com/alyssarosenzweig/linux/commits/agx/uapi/ contains the
DRM driver implementing this proposed UAPI.

https://github.com/alyssarosenzweig/mesa/tree/agx-uapi contains the Mesa
patches to implement this proposed UAPI.

That Linux and Mesa branch together give a complete graphics/compute
stack on top of this UAPI.

Co-developed-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
 Documentation/gpu/driver-uapi.rst |    5 +
 MAINTAINERS                       |    1 +
 include/uapi/drm/asahi_drm.h      | 1153 +++++++++++++++++++++++++++++++++++++
 3 files changed, 1159 insertions(+)

diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
--- a/Documentation/gpu/driver-uapi.rst
+++ b/Documentation/gpu/driver-uapi.rst
@@ -27,3 +27,8 @@ drm/xe uAPI
 ===========
 
 .. kernel-doc:: include/uapi/drm/xe_drm.h
+
+drm/asahi uAPI
+================
+
+.. kernel-doc:: include/uapi/drm/asahi_drm.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2256,6 +2256,7 @@ F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
 F:	include/linux/soc/apple/*
+F:	include/uapi/drm/asahi_drm.h
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson at axis.com>
diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
new file mode 100644
index 0000000000000000000000000000000000000000..1491ddbf807d1a26d7d5c5df78a7a988787d15c4
--- /dev/null
+++ b/include/uapi/drm/asahi_drm.h
@@ -0,0 +1,1153 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) The Asahi Linux Contributors
+ * Copyright (C) 2018-2023 Collabora Ltd.
+ * Copyright (C) 2014-2018 Broadcom
+ */
+#ifndef _ASAHI_DRM_H_
+#define _ASAHI_DRM_H_
+
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * DOC: Introduction to the Asahi UAPI
+ *
+ * This documentation describes the Asahi IOCTLs.
+ *
+ * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
+ * from Panthor):
+ *
+ * - Structures must be aligned on 64-bit/8-byte. If the object is not
+ *   naturally aligned, a padding field must be added.
+ * - Fields must be explicitly aligned to their natural type alignment with
+ *   pad[0..N] fields.
+ * - All padding fields will be checked by the driver to make sure they are
+ *   zeroed.
+ * - Flags can be added, but not removed/replaced.
+ * - New fields can be added to the main structures (the structures
+ *   directly passed to the ioctl). Those fields can be added at the end of
+ *   the structure, or replace existing padding fields. Any new field being
+ *   added must preserve the behavior that existed before those fields were
+ *   added when a value of zero is passed.
+ * - New fields can be added to indirect objects (objects pointed by the
+ *   main structure), iff those objects are passed a size to reflect the
+ *   size known by the userspace driver (see
+ *   drm_asahi_command::cmd_buffer_size).
+ * - If the kernel driver is too old to know some fields, those will be
+ *   ignored if zero, and otherwise rejected (and so will be zero on output).
+ * - If userspace is too old to know some fields, those will be zeroed
+ *   (input) before the structure is parsed by the kernel driver.
+ * - Each new flag/field addition must come with a driver version update so
+ *   the userspace driver doesn't have to trial and error to know which
+ *   flags are supported.
+ * - Structures should not contain unions, as this would defeat the
+ *   extensibility of such structures.
+ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
+ *   at the end of the drm_asahi_ioctl_id enum.
+ */
+
+/**
+ * enum drm_asahi_ioctl_id - IOCTL IDs
+ *
+ * Place new ioctls at the end, don't re-order, don't replace or remove entries.
+ *
+ * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
+ * definitions instead.
+ */
+enum drm_asahi_ioctl_id {
+	/** @DRM_ASAHI_GET_PARAMS: Query device properties. */
+	DRM_ASAHI_GET_PARAMS = 0,
+
+	/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
+	DRM_ASAHI_VM_CREATE,
+
+	/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
+	DRM_ASAHI_VM_DESTROY,
+
+	/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
+	DRM_ASAHI_GEM_CREATE,
+
+	/**
+	 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
+	 * given GEM handle.
+	 */
+	DRM_ASAHI_GEM_MMAP_OFFSET,
+
+	/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
+	DRM_ASAHI_GEM_BIND,
+
+	/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
+	DRM_ASAHI_QUEUE_CREATE,
+
+	/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
+	DRM_ASAHI_QUEUE_DESTROY,
+
+	/** @DRM_ASAHI_SUBMIT: Submit an array of commands to a queue. */
+	DRM_ASAHI_SUBMIT,
+
+	/** @DRM_ASAHI_GET_TIME: Query device time. */
+	DRM_ASAHI_GET_TIME,
+
+	/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
+	DRM_ASAHI_GEM_BIND_OBJECT,
+};
+
+#define DRM_ASAHI_MAX_CLUSTERS	64
+
+/**
+ * struct drm_asahi_params_global - Global parameters.
+ *
+ * This struct may be queried by drm_asahi_get_params.
+ */
+struct drm_asahi_params_global {
+	/** @features: Feature bits from drm_asahi_feature */
+	__u64 features;
+
+	/** @gpu_generation: GPU generation, e.g. 13 for G13G */
+	__u32 gpu_generation;
+
+	/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
+	__u32 gpu_variant;
+
+	/**
+	 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
+	 * 0x21 for 'C1'
+	 */
+	__u32 gpu_revision;
+
+	/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
+	__u32 chip_id;
+
+	/** @num_dies: Number of dies in the SoC */
+	__u32 num_dies;
+
+	/** @num_clusters_total: Number of GPU clusters (across all dies) */
+	__u32 num_clusters_total;
+
+	/**
+	 * @num_cores_per_cluster: Number of logical cores per cluster
+	 * (including inactive/nonexistent)
+	 */
+	__u32 num_cores_per_cluster;
+
+	/** @num_frags_per_cluster: Number of frags per cluster */
+	__u32 num_frags_per_cluster;
+
+	/** @num_gps_per_cluster: Number of GPs per cluster */
+	__u32 num_gps_per_cluster;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @core_masks: Bitmask of present/enabled cores per cluster */
+	__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
+
+	/** @timer_frequency_hz: Clock frequency for timestamps */
+	__u64 timer_frequency_hz;
+
+	/** @min_frequency_khz: Minimum GPU core clock frequency */
+	__u32 min_frequency_khz;
+
+	/** @max_frequency_khz: Maximum GPU core clock frequency */
+	__u32 max_frequency_khz;
+
+	/** @max_power_mw: Maximum GPU power consumption */
+	__u32 max_power_mw;
+
+	/** @vm_page_size: GPU VM page size */
+	__u32 vm_page_size;
+
+	/** @vm_user_start: VM user range start VMA */
+	__u64 vm_user_start;
+
+	/** @vm_user_end: VM user range end VMA */
+	__u64 vm_user_end;
+
+	/**
+	 * @vm_kernel_min_size: Minimum kernel VMA window size within user
+	 * range
+	 */
+	__u64 vm_kernel_min_size;
+
+	/**
+	 * @max_commands_per_submission: Maximum number of supported commands
+	 * per submission
+	 */
+	__u32 max_commands_per_submission;
+
+	/**
+	 * @max_attachments: Maximum number of drm_asahi_attachment's per
+	 * command
+	 */
+	__u32 max_attachments;
+
+	/**
+	 * @firmware_version: GPU firmware version, as 4 integers
+	 */
+	__u32 firmware_version[4];
+
+	/**
+	 * @user_timestamp_frequency_hz: Timebase frequency for user timestamps
+	 */
+	__u64 user_timestamp_frequency_hz;
+};
+
+/**
+ * enum drm_asahi_feature - Feature bits
+ *
+ * This covers only features that userspace cannot infer from the architecture
+ * version. Most features don't need to be here.
+ */
+enum drm_asahi_feature {
+	/**
+	 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
+	 * loads of unmapped memory will return zero. Shader stores to unmapped
+	 * memory will be silently discarded. Note that only shader load/store
+	 * is affected. Other hardware units are not affected, notably including
+	 * texture sampling.
+	 */
+	DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
+};
+
+/**
+ * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
+ */
+struct drm_asahi_get_params {
+	/** @param_group: Parameter group to fetch (MBZ) */
+	__u32 param_group;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @pointer: User pointer to write parameter struct */
+	__u64 pointer;
+
+	/** @size: Size of user buffer, max size supported on return */
+	__u64 size;
+};
+
+/**
+ * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
+ */
+struct drm_asahi_vm_create {
+	/** @kernel_start: Start of the kernel-reserved address range */
+	__u64 kernel_start;
+
+	/** @kernel_end: End of the kernel-reserved address range */
+	__u64 kernel_end;
+
+	/** @vm_id: Returned VM ID */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
+ */
+struct drm_asahi_vm_destroy {
+	/** @vm_id: VM ID to be destroyed */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * define ASAHI_GEM_WRITEBACK - BO should be CPU-mapped as writeback.
+ *
+ * Map as writeback instead of write-combine. This optimizes for CPU reads.
+ */
+#define ASAHI_GEM_WRITEBACK (1L << 0)
+
+/**
+ * define ASAHI_GEM_VM_PRIVATE - BO is private to this GPU VM (no exports)
+ */
+#define ASAHI_GEM_VM_PRIVATE (1L << 1)
+
+/**
+ * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
+ */
+struct drm_asahi_gem_create {
+	/** @size: Size of the BO */
+	__u64 size;
+
+	/** @flags: Combination of ASAHI_GEM_* flags. */
+	__u32 flags;
+
+	/**
+	 * @vm_id: VM ID to assign to the BO, if ASAHI_GEM_VM_PRIVATE is set
+	 */
+	__u32 vm_id;
+
+	/** @handle: Returned GEM handle for the BO */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_gem_mmap_offset - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
+ */
+struct drm_asahi_gem_mmap_offset {
+	/** @handle: Handle for the object being mapped. */
+	__u32 handle;
+
+	/** @flags: Must be zero */
+	__u32 flags;
+
+	/** @offset: The fake offset to use for subsequent mmap call */
+	__u64 offset;
+};
+
+/**
+ * enum drm_asahi_bind_op - Bind operation
+ */
+enum drm_asahi_bind_op {
+	/** @ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
+	ASAHI_BIND_OP_BIND = 0,
+
+	/** @ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
+	ASAHI_BIND_OP_UNBIND = 1,
+
+	/** @ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */
+	ASAHI_BIND_OP_UNBIND_ALL = 2,
+};
+
+/**
+ * define ASAHI_BIND_READ - Map BO with GPU read permission
+ */
+#define ASAHI_BIND_READ		(1L << 0)
+
+/**
+ * define ASAHI_BIND_WRITE - Map BO with GPU write permission
+ */
+#define ASAHI_BIND_WRITE	(1L << 1)
+
+/**
+ * define ASAHI_BIND_SINGLE_PAGE - Map a single page of the BO repeatedly across
+ * the VA range.
+ *
+ * This is useful to fill a VA range with scratch pages or zero pages. It is
+ * intended as a mechanism to accelerate sparse.
+ */
+#define ASAHI_BIND_SINGLE_PAGE	(1L << 2)
+
+/**
+ * struct drm_asahi_gem_bind - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND
+ */
+struct drm_asahi_gem_bind {
+	/** @op: Bind operation (enum drm_asahi_bind_op) */
+	__u32 op;
+
+	/** @flags: One or more of ASAHI_BIND_* (BIND only) */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/**
+	 * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
+	 */
+	__u64 range;
+
+	/** @addr: Address to bind to (BIND or UNBIND only) */
+	__u64 addr;
+};
+
+/**
+ * enum drm_asahi_bind_object_op - Special object bind operation
+ */
+enum drm_asahi_bind_object_op {
+	/** @ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
+	ASAHI_BIND_OBJECT_OP_BIND = 0,
+
+	/** @ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
+	ASAHI_BIND_OBJECT_OP_UNBIND = 1,
+};
+
+/**
+ * define ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS - Map a BO as a timestamp buffer
+ */
+#define ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS	(1L << 0)
+
+/**
+ * struct drm_asahi_gem_bind_object - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
+ */
+struct drm_asahi_gem_bind_object {
+	/** @op: Bind operation (enum drm_asahi_bind_object_op) */
+	__u32 op;
+
+	/** @flags: One or more of ASAHI_BIND_OBJECT_* */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on (MBZ currently) */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/** @range: Number of bytes to bind/unbind (BIND only) */
+	__u64 range;
+
+	/** @object_handle: Object handle (out for BIND, in for UNBIND) */
+	__u32 object_handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_cmd_type - Command type
+ */
+enum drm_asahi_cmd_type {
+	/**
+	 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
+	 * subqueue. Combined vertex and fragment operation.
+	 */
+	DRM_ASAHI_CMD_RENDER = 0,
+
+	/** @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue. */
+	DRM_ASAHI_CMD_COMPUTE = 1,
+};
+
+/**
+ * enum drm_asahi_queue_cap - Queue capabilities
+ */
+enum drm_asahi_queue_cap {
+	/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
+	DRM_ASAHI_QUEUE_CAP_RENDER	= (1UL << DRM_ASAHI_CMD_RENDER),
+
+	/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
+	DRM_ASAHI_QUEUE_CAP_COMPUTE	= (1UL << DRM_ASAHI_CMD_COMPUTE),
+};
+
+/**
+ * struct drm_asahi_queue_create - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_CREATE
+ */
+struct drm_asahi_queue_create {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @vm_id: The ID of the VM this queue is bound to */
+	__u32 vm_id;
+
+	/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
+	__u32 queue_caps;
+
+	/** @priority: Queue priority, 0-3 */
+	__u32 priority;
+
+	/** @queue_id: The returned queue ID */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_queue_destroy - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_DESTROY
+ */
+struct drm_asahi_queue_destroy {
+	/** @queue_id: The queue ID to be destroyed */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_sync_type - Sync item type
+ */
+enum drm_asahi_sync_type {
+	/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
+	DRM_ASAHI_SYNC_SYNCOBJ = 0,
+
+	/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
+	DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
+};
+
+/**
+ * struct drm_asahi_sync - Sync item
+ */
+struct drm_asahi_sync {
+	/** @sync_type: One of drm_asahi_sync_type */
+	__u32 sync_type;
+
+	/** @handle: The sync object handle */
+	__u32 handle;
+
+	/** @timeline_value: Timeline value for timeline sync objects */
+	__u64 timeline_value;
+};
+
+/**
+ * enum drm_asahi_subqueue - Subqueue within a queue
+ */
+enum drm_asahi_subqueue {
+	/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */
+	DRM_ASAHI_SUBQUEUE_RENDER = 0,
+
+	/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */
+	DRM_ASAHI_SUBQUEUE_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2
+	 * for struct alignment
+	 */
+	DRM_ASAHI_SUBQUEUE_COUNT = 2,
+};
+
+/**
+ * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
+ *
+ * This special value may be passed in to drm_asahi_command::barriers[] to
+ * indicate that the respective subqueue should not wait on any previous work.
+ */
+#define DRM_ASAHI_BARRIER_NONE ~(0U)
+
+/**
+ * struct drm_asahi_command - Top level command structure
+ */
+struct drm_asahi_command {
+	/** @cmd_type: One of drm_asahi_cmd_type */
+	__u32 cmd_type;
+
+	/** @flags: Flags for command submission */
+	__u32 flags;
+
+	/** @cmd_buffer: Pointer to the appropriate command buffer structure */
+	__u64 cmd_buffer;
+
+	/** @cmd_buffer_size: Size of the command buffer structure */
+	__u64 cmd_buffer_size;
+
+	/** @barriers: Array of command indices per subqueue to wait on */
+	__u32 barriers[DRM_ASAHI_SUBQUEUE_COUNT];
+};
+
+/**
+ * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
+ */
+struct drm_asahi_submit {
+	/**
+	 * @in_syncs: An optional array of drm_asahi_sync to wait on before
+	 * starting this job.
+	 */
+	__u64 in_syncs;
+
+	/**
+	 * @out_syncs: An optional array of drm_asahi_sync objects to signal
+	 * upon completion.
+	 */
+	__u64 out_syncs;
+
+	/**
+	 * @commands: Pointer to the drm_asahi_command array of commands to
+	 * submit.
+	 */
+	__u64 commands;
+
+	/** @flags: Flags for command submission (MBZ) */
+	__u32 flags;
+
+	/** @queue_id: The queue ID to be submitted to */
+	__u32 queue_id;
+
+	/**
+	 * @in_sync_count: Number of sync objects to wait on before starting
+	 * this job.
+	 */
+	__u32 in_sync_count;
+
+	/**
+	 * @out_sync_count: Number of sync objects to signal upon completion of
+	 * this job.
+	 */
+	__u32 out_sync_count;
+
+	/** @command_count: Number of commands to be submitted */
+	__u32 command_count;
+};
+
+/**
+ * struct drm_asahi_attachment - Describe an "attachment".
+ *
+ * Attachments are any memory written by shaders, notably including render
+ * target attachments written by the end-of-tile program. This is purely a hint
+ * about the accessed memory regions. It is optional to specify, which is
+ * fortunate as it cannot be specified precisely with bindless access anyway.
+ * But where possible, it's probably a good idea for userspace to include these
+ * hints, forwarded to the firmware.
+ */
+struct drm_asahi_attachment {
+	/** @pointer: Base address of the attachment */
+	__u64 pointer;
+
+	/** @size: Size of the attachment in bytes */
+	__u64 size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @flags: MBZ */
+	__u32 flags;
+};
+
+/**
+ * define ASAHI_RENDER_VERTEX_SPILLS - Vertex stage shader spills
+ */
+#define ASAHI_RENDER_VERTEX_SPILLS (1UL << 0)
+
+/**
+ * define ASAHI_RENDER_PROCESS_EMPTY_TILES - Process empty tiles through the
+ * fragment load/store
+ */
+#define ASAHI_RENDER_PROCESS_EMPTY_TILES (1UL << 1)
+
+/**
+ * define ASAHI_RENDER_NO_VERTEX_CLUSTERING - Run vertex stage on a single
+ * cluster (on multicluster GPUs)
+ *
+ * This will harm performance but can workaround certain sync/coherency bugs,
+ * and therefore is useful for debugging.
+ */
+#define ASAHI_RENDER_NO_VERTEX_CLUSTERING (1UL << 2)
+
+/**
+ * define ASAHI_RENDER_DBIAS_IS_INT - Use integer depth bias formula.
+ *
+ * Graphics specifications contain two alternate formulas for depth bias, a
+ * float formula used with floating-point depth buffers and an integer formula
+ * using with unorm depth buffers. This flag specifies that the integer formula
+ * should be used. If omitted, the float formula is used instead.
+ *
+ * This corresponds to bit 18 of the relevant hardware control register, so we
+ * match that here for efficiency.
+ */
+#define ASAHI_RENDER_DBIAS_IS_INT (1UL << 18)
+
+/**
+ * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
+ *
+ * These fields correspond directly to hardware registers in the ZLS (Z
+ * Load/Store) unit. Together, they configure a single depth or stencil buffer.
+ * Typically, load/store/partial will all use the same values. However, the
+ * hardware does not require this.
+ */
+struct drm_asahi_zls_buffer {
+	/** @load: Base address of the buffer to load at the start */
+	__u64 load;
+
+	/** @store: Base address of the buffer to store at the end */
+	__u64 store;
+
+	/**
+	 * @partial: Base address of the buffer to load and store during a
+	 * partial render operation.
+	 */
+	__u64 partial;
+
+	/**
+	 * @comp_load: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_load;
+
+	/**
+	 * @comp_store: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_store;
+
+	/**
+	 * @comp_partial: If the partial render buffer is compressed, address of
+	 * the compression metadata section.
+	 */
+	__u64 comp_partial;
+
+	/**
+	 * @load_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the load buffer.
+	 */
+	__u32 load_stride;
+
+	/**
+	 * @store_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the store buffer.
+	 */
+	__u32 store_stride;
+
+	/**
+	 * @partial_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the partial render buffer.
+	 */
+	__u32 partial_stride;
+
+	/**
+	 * @comp_load_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the compression metadata for loads.
+	 */
+	__u32 comp_load_stride;
+
+	/**
+	 * @comp_store_stride: If layered rendering is enabled, the number of
+	 * bytes between each layer of the compression metadata for stores.
+	 */
+	__u32 comp_store_stride;
+
+	/**
+	 * @comp_partial_stride: If layered rendering is enabled, the number of
+	 * bytes between each layer of the compression metadata for partial
+	 * renders.
+	 */
+	__u32 comp_partial_stride;
+};
+
+/**
+ * struct drm_asahi_timestamp - Describe a timestamp write.
+ *
+ * The firmware can optionally write the GPU timestamp at render pass
+ * granularities, but it needs to be mapped specially via
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
+ * write as a handle-offset pair, rather than a GPU address like normal.
+ */
+struct drm_asahi_timestamp {
+	/**
+	 * @handle: Handle of the timestamp buffer, or 0 to skip this
+	 * timestamp. If nonzero, this must equal the value returned in
+	 * drm_asahi_gem_bind_object::object_handle.
+	 */
+	__u32 handle;
+
+	/** @offset: Offset to write into the timestamp buffer */
+	__u32 offset;
+};
+
+/**
+ * struct drm_asahi_timestamps - Describe timestamp writes.
+ *
+ * Each operation that can be timestamped, can be timestamped at the start and
+ * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
+ * together into drm_asahi_timestamps.
+ */
+struct drm_asahi_timestamps {
+	/** @start: Timestamp recorded at the start of the operation */
+	struct drm_asahi_timestamp start;
+
+	/** @end: Timestamp recorded at the end of the operation */
+	struct drm_asahi_timestamp end;
+};
+
+/**
+ * struct drm_asahi_helper_program - Describe helper program configuration.
+ *
+ * The helper program is a compute-like kernel required for various hardware
+ * functionality. Its most important role is dynamically allocating
+ * scratch/stack memory for individual subgroups, by partitioning a static
+ * allocation shared for the whole device. It is supplied by userspace via
+ * drm_asahi_helper_program and internally dispatched by the hardware as needed.
+ */
+struct drm_asahi_helper_program {
+	/**
+	 * @binary: USC address to the helper program binary. This is a tagged
+	 * pointer with configuration in the bottom bits.
+	 */
+	__u32 binary;
+
+	/** @cfg: Configuration bits for the helper program. */
+	__u32 cfg;
+
+	/**
+	 * @data: Data passed to the helper program. This value is not
+	 * interpreted by the kernel, firmware, or hardware in any way. It is
+	 * simply a sideband for userspace, set with the submit ioctl and read
+	 * via special registers inside the helper program.
+	 *
+	 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
+	 * actual arguments, which presumably don't fit in 64-bits.
+	 */
+	__u64 data;
+};
+
+/**
+ * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
+ *
+ * The background and end-of-tile programs are dispatched by the hardware at the
+ * beginning and end of rendering. As the hardware "tilebuffer" is simply local
+ * memory, these programs are necessary to implement API-level render targets.
+ * The fragment-like background program is responsible for loading either the
+ * clear colour or the existing render target contents, while the compute-like
+ * end-of-tile program stores the tilebuffer contents to memory.
+ */
+struct drm_asahi_bg_eot {
+	/**
+	 * @usc: USC address of the hardware USC words binding resources
+	 * (including images and uniforms) and the program itself. Note this is
+	 * an additional layer of indirection compared to the helper program,
+	 * avoiding the need for a sideband for data. This is a tagged pointer
+	 * with additional configuration in the bottom bits.
+	 */
+	__u32 usc;
+
+	/**
+	 * @rsrc_spec: Resource specifier for the program. This is a packed
+	 * hardware data structure describing the required number of registers,
+	 * uniforms, bound textures, and bound samplers.
+	 */
+	__u32 rsrc_spec;
+};
+
+/**
+ * struct drm_asahi_cmd_render - Command to submit 3D
+ *
+ * This command submits a single render pass. The hardware control stream may
+ * include many draws and subpasses, but within the command, the framebuffer
+ * dimensions and attachments are fixed.
+ *
+ * The hardware requires the firmware to set a large number of Control Registers
+ * setting up state at render pass granularity before each command rendering 3D.
+ * The firmware bundles this state into data structures. Unfortunately, we
+ * cannot expose either any of that directly to userspace, because the
+ * kernel-firmware ABI is not stable. Although we can guarantee the firmware
+ * updates in tandem with the kernel, we cannot break old userspace when
+ * upgrading the firmware and kernel. Therefore, we need to abstract well the
+ * data structures to avoid tying our hands with future firmwares.
+ *
+ * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
+ * control registers, marshalled via the firmware interface.
+ *
+ * The framebuffer/tilebuffer dimensions are also specified here. In addition to
+ * being passed to the firmware/hardware, the kernel requires these dimensions
+ * to calculate various essential tiling-related data structures. It is
+ * unfortunate that our submits are heavier than on vendors with saner
+ * hardware-software interfaces. The upshot is all of this information is
+ * readily available to userspace with all current APIs.
+ *
+ * It looks odd - but it's not overly burdensome and it ensures we can remain
+ * compatible with old userspace.
+ */
+struct drm_asahi_cmd_render {
+	/** @flags: Zero or more of ASAHI_RENDER_* */
+	__u64 flags;
+
+	/** @encoder_ptr: GPU base address to the hardware control stream */
+	__u64 encoder_ptr;
+
+	/**
+	 * @usc_base: GPU base address for all USC binaries (shaders) used in
+	 * this command. USC addresses are 32-bit relative to this 64-bit base.
+	 */
+	__u64 usc_base;
+
+	/**
+	 * @vertex_attachments: Pointer to drm_asahi_attachment array used for
+	 * the vertex portion of this command.
+	 */
+	__u64 vertex_attachments;
+
+	/**
+	 * @fragment_attachments: Pointer to drm_asahi_attachment array used for
+	 * the fragment portion of this command. This includes the end-of-tile
+	 * shader, in addition to the fragment shaders themselves.
+	 */
+	__u64 fragment_attachments;
+
+	/**
+	 * @vertex_attachment_count: Number of drm_asahi_attachment's pointed to
+	 * by vertex_attachments
+	 */
+	__u32 vertex_attachment_count;
+
+	/**
+	 * @fragment_attachment_count: Number of drm_asahi_attachment's pointed
+	 * to by fragment_attachmenst
+	 */
+	__u32 fragment_attachment_count;
+
+	/** @vertex_helper: Helper program used for the vertex shader */
+	struct drm_asahi_helper_program vertex_helper;
+
+	/** @fragment_helper: Helper program used for the fragment shader */
+	struct drm_asahi_helper_program fragment_helper;
+
+	/**
+	 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
+	 * array of scissor descriptors indexed in the render pass.
+	 */
+	__u64 isp_scissor_base;
+
+	/**
+	 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
+	 * array of depth bias values indexed in the render pass.
+	 */
+	__u64 isp_dbias_base;
+
+	/**
+	 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
+	 * array of occlusion query results written by the render pass.
+	 */
+	__u64 isp_oclqry_base;
+
+	/** @depth: Physical buffers backing the logical depth buffer */
+	struct drm_asahi_zls_buffer depth;
+
+	/** @stencil: Physical buffers backing the logical stencil buffer */
+	struct drm_asahi_zls_buffer stencil;
+
+	/** @zls_ctrl: ZLS_CTRL register value */
+	__u64 zls_ctrl;
+
+	/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
+	__u64 ppp_multisamplectl;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/** @ppp_ctrl: PPP_CTRL register value */
+	__u32 ppp_ctrl;
+
+	/** @width_px: Framebuffer width in pixels */
+	__u16 width_px;
+
+	/** @height_px: Framebuffer height in pixels */
+	__u16 height_px;
+
+	/** @layers: Number of layers in the framebuffer */
+	__u16 layers;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u16 sampler_count;
+
+	/** @utile_width_px: Width of a logical tilebuffer tile in pixels */
+	__u8 utile_width_px;
+
+	/** @utile_height_px: Height of a logical tilebuffer tile in pixels */
+	__u8 utile_height_px;
+
+	/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
+	__u8 samples;
+
+	/** @sample_size_B: # of bytes in the tilebuffer required per sample. */
+	__u8 sample_size_B;
+
+	/** @encoder_id: Opaque handle identifying what encoded this command. */
+	__u32 encoder_id;
+
+	/**
+	 * @cmd_ta_id: Unique identifier for the Tiling Accelerator (TA)
+	 * portion of this command.
+	 */
+	__u32 cmd_ta_id;
+
+	/**
+	 * @cmd_3d_id: Unique identifier for the 3D
+	 * portion of this command.
+	 */
+	__u32 cmd_3d_id;
+
+	/**
+	 * @isp_merge_upper_x: 32-bit float used in the
+	 * hardware triangle merging. Calculate as:
+	 *
+	 *	tan(60 deg) * width
+	 *
+	 * Making these values UAPI avoids requiring floating-point calculations
+	 * in the kernel in the hot path.
+	 */
+	__u32 isp_merge_upper_x;
+
+	/**
+	 * @isp_merge_upper_y: 32-bit float. Calculate as:
+	 *
+	 *	tan(60 deg) * height
+	 *
+	 * See @isp_merge_upper_x.
+	 */
+
+	__u32 isp_merge_upper_y;
+
+	/**
+	 * @bg: Background program ran at the start of each tile at the start of
+	 * the render pass.
+	 */
+	struct drm_asahi_bg_eot bg;
+
+	/**
+	 * @eot: End-of-tile program ran at the end of each tile at the end of
+	 * the render pass.
+	 */
+	struct drm_asahi_bg_eot eot;
+
+	/**
+	 * @partial_bg: Background program ran at the start of each tile when
+	 * resuming the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_bg;
+
+	/**
+	 * @partial_eot: End-of-tile program ran at the end of each tile when
+	 * pausing the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_eot;
+
+	/**
+	 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
+	 * depth buffer width/height, which is allowed to differ from the
+	 * framebuffer width/height.
+	 */
+	__u32 isp_zls_pixels;
+
+	/**
+	 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
+	 * buffer clear value, encoded in the depth buffer's format: either a
+	 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
+	 */
+	__u32 isp_bgobjdepth;
+
+	/**
+	 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
+	 * contain the stencil buffer clear value.
+	 */
+	__u32 isp_bgobjvals;
+
+	/** @ts_vtx: Timestamps for the vertex portion of the render */
+	struct drm_asahi_timestamps ts_vtx;
+
+	/** @ts_frag: Timestamps for the fragment portion of the render */
+	struct drm_asahi_timestamps ts_frag;
+};
+
+/**
+ * struct drm_asahi_cmd_compute - Command to submit compute
+ *
+ * This command submits a control stream consisting of compute dispatches. There
+ * is essentially no limit on how many compute dispatches may be included in a
+ * single compute command, although timestamping only occurs at command
+ * granularity.
+ */
+struct drm_asahi_cmd_compute {
+	/** @flags: MBZ */
+	__u64 flags;
+
+	/** @encoder_ptr: GPU base address to the hardware control stream */
+	__u64 encoder_ptr;
+
+	/**
+	 * @encoder_end: GPU base address to the end of the hardware control
+	 * stream. Note this only considers the first contiguous segment of the
+	 * control stream, as the stream might jump elsewhere.
+	 */
+	__u64 encoder_end;
+
+	/**
+	 * @usc_base: GPU Base address for all USC binaries (shaders) used in
+	 * this command. USC addresses are 32-bit relative to this 64-bit base.
+	 */
+	__u64 usc_base;
+
+	/**
+	 * @attachments: Pointer to drm_asahi_attachment array used for
+	 * this command
+	 */
+	__u64 attachments;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/**
+	 * @attachment_count: Number of drm_asahi_attachments pointed to by
+	 * @attachments
+	 */
+	__u32 attachment_count;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u32 sampler_count;
+
+	/** @helper: Helper program used for this compute shader */
+	struct drm_asahi_helper_program helper;
+
+	/** @encoder_id: Opaque handle identifying what encoded this command. */
+	__u32 encoder_id;
+
+	/** @cmd_id: Unique identifier for this command. */
+	__u32 cmd_id;
+
+	/** @ts: Timestamps for the compute command */
+	struct drm_asahi_timestamps ts;
+};
+
+/**
+ * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
+ */
+struct drm_asahi_get_time {
+	/** @flags: MBZ. */
+	__u64 flags;
+
+	/** @gpu_timestamp: On return, the current GPU timestamp */
+	__u64 gpu_timestamp;
+};
+
+/**
+ * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
+ * @__access: Access type. Must be R, W or RW.
+ * @__id: One of the DRM_ASAHI_xxx id.
+ * @__type: Suffix of the type being passed to the IOCTL.
+ *
+ * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
+ * values instead.
+ *
+ * Return: An IOCTL number to be passed to ioctl() from userspace.
+ */
+#define DRM_IOCTL_ASAHI(__access, __id, __type) \
+	DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
+			   struct drm_asahi_ ## __type)
+
+/* Note: this is an enum so that it can be resolved by Rust bindgen. */
+enum {
+	DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
+	DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
+	DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
+	DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
+	DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
+	DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
+	DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
+	DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
+	DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
+	DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
+	DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _ASAHI_DRM_H_ */

---
base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
change-id: 20250307-agx-uapi-930579437f19

Best regards,
-- 
Alyssa Rosenzweig <alyssa at rosenzweig.io>



From kristina.martsenko at arm.com  Mon Mar 10 07:15:53 2025
From: kristina.martsenko at arm.com (=?UTF-8?Q?Kristina_Mart=C5=A1enko?=)
Date: Mon, 10 Mar 2025 14:15:53 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <Z8tnARR2jSJEruLw@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
 <Z8s-4OPE2DNSogwB@arm.com> <4c621070-688a-4a75-9134-ea19b6d20f04@arm.com>
 <Z8tnARR2jSJEruLw@arm.com>
Message-ID: <1210b66a-ed75-4bc1-bbaa-d3277c290267@arm.com>

On 07/03/2025 21:37, Catalin Marinas wrote:
> On Fri, Mar 07, 2025 at 06:53:37PM +0000, Robin Murphy wrote:
>> On 2025-03-07 6:45 pm, Catalin Marinas wrote:
>>> On Fri, Feb 28, 2025 at 05:00:05PM +0000, Kristina Martsenko wrote:
>>>> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
>>>> +				  unsigned long esr)
>>>> +{
>>>> +	switch (ex->type) {
>>>> +	case EX_TYPE_UACCESS_CPY:
>>>> +		return cpy_faulted_on_uaccess(ex, esr);
>>>> +	default:
>>>> +		return true;
>>>> +	}
>>>> +}
>>>
>>> Not a problem with this patch but I wonder whether we should return
>>> false for EX_TYPE_LOAD_UNALIGNED_ZEROPAD for completeness
>>
>> Or maybe rather, true for EX_TYPE_UACCESS_ERR_ZERO and then false in the
>> default case?
> 
> Yes.

I thought you said in an earlier (off-list) discussion that 
EX_TYPE_KACCESS_ERR_ZERO shouldn't return false here because 
__get_kernel_nofault() may get called with untrusted addresses? Or did I
misunderstand?

Thanks,
Kristina



From krzysztof.kozlowski at linaro.org  Mon Mar 10 07:18:54 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 15:18:54 +0100
Subject: [PATCH] memory: mtk-smi: Add ostd setting for mt8192
In-Reply-To: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
References: <20250307054515.23455-1-xueqi.zhang@mediatek.com>
Message-ID: <174161633416.57206.15365261153795396869.b4-ty@linaro.org>


On Fri, 07 Mar 2025 13:45:08 +0800, Xueqi Zhang wrote:
> Add initial ostd setting for mt8192. All the settings come from DE.
> These settings help adjust Multimedia HW's bandwidth limits to achieve
> a balanced bandwidth requirement.
> Without this, the VENC HW work abnormal while stress testing.
> 
> 

Applied, thanks!

[1/1] memory: mtk-smi: Add ostd setting for mt8192
      https://git.kernel.org/krzk/linux-mem-ctrl/c/90a0fbaac4a588a1116a191521c3c837c25582ee

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>



From kory.maincent at bootlin.com  Mon Mar 10 07:20:14 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 10 Mar 2025 15:20:14 +0100
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for
 return value in intel_tsn_lane_is_available()
In-Reply-To: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
References: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
Message-ID: <20250310152014.1d593255@kmaincent-XPS-13-7390>

On Mon, 10 Mar 2025 13:08:35 +0800
Choong Yong Liang <yong.liang.choong at linux.intel.com> wrote:

> Fix the warning "warn: missing error code? 'ret'" in the
> intel_tsn_lane_is_available() function.
> 
> The function now returns 0 to indicate that a TSN lane was found and
> returns -EINVAL when it is not found.
> 
> Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the
> interface mode")
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>

This patch is a fix it should go net instead net-next.
Could you resend the patch with net prefix?

Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>

Thank you!
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From jonathanh at nvidia.com  Mon Mar 10 07:20:45 2025
From: jonathanh at nvidia.com (Jon Hunter)
Date: Mon, 10 Mar 2025 14:20:45 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
 <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
 <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>
Message-ID: <673e453b-798f-4fc1-8ed1-3cf597e926b4@nvidia.com>


On 07/03/2025 17:07, Russell King (Oracle) wrote:
> On Fri, Mar 07, 2025 at 04:11:19PM +0000, Jon Hunter wrote:
>> Hi Russell,
>>
>> On 06/03/2025 15:23, Russell King (Oracle) wrote:
>>> Hi,
>>>
>>> This is a second approach to solving the STMMAC reset issues caused by
>>> the lack of receive clock from the PHY where the media is in low power
>>> mode with a PHY that supports receive clock-stop.
>>>
>>> The first approach centred around only addressing the issue in the
>>> resume path, but it seems to also happen when the platform glue module
>>> is removed and re-inserted (Jon - can you check whether that's also
>>> the case for you please?)
>>>
>>> As this is more targetted, I've dropped the patches from this series
>>> which move the call to phylink_resume(), so the link may still come
>>> up too early on resume - but that's something I also intend to fix.
>>>
>>> This is experimental - so I value test reports for this change.
>>
>>
>> The subject indicates 3 patches, but I only see 2 patches? Can you confirm
>> if there are 2 or 3?
> 
> Yes, 2 patches is correct.
> 
>> So far I have only tested to resume case with the 2 patches to make that
>> that is working but on Tegra186, which has been the most problematic, it is
>> not working reliably on top of next-20250305.
> 
> To confirm, you're seeing stmmac_reset() sporadically timing out on
> resume even with these patches appled? That's rather disappointing.

So I am no longer seeing the reset fail, from what I can see, but now
NFS is not responding after resume ...

[   49.825094] Enabling non-boot CPUs ...
[   49.829760] Detected PIPT I-cache on CPU1
[   49.832694] CPU features: SANITY CHECK: Unexpected variation in SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU1: 0x0000009444c004
[   49.844120] CPU features: SANITY CHECK: Unexpected variation in SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU1: 0x00000010305116
[   49.856231] CPU features: SANITY CHECK: Unexpected variation in SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU1: 0x00000003001066
[   49.868081] CPU1: Booted secondary processor 0x0000000000 [0x4e0f0030]
[   49.875389] CPU1 is up
[   49.877187] Detected PIPT I-cache on CPU2
[   49.880824] CPU features: SANITY CHECK: Unexpected variation in SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU2: 0x0000009444c004
[   49.892266] CPU features: SANITY CHECK: Unexpected variation in SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU2: 0x00000010305116
[   49.904467] CPU features: SANITY CHECK: Unexpected variation in SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU2: 0x00000003001066
[   49.916257] CPU2: Booted secondary processor 0x0000000001 [0x4e0f0030]
[   49.923610] CPU2 is up
[   49.925194] Detected PIPT I-cache on CPU3
[   49.929010] CPU3: Booted secondary processor 0x0000000101 [0x411fd073]
[   49.935866] CPU3 is up
[   49.937983] Detected PIPT I-cache on CPU4
[   49.941824] CPU4: Booted secondary processor 0x0000000102 [0x411fd073]
[   49.948593] CPU4 is up
[   49.950810] Detected PIPT I-cache on CPU5
[   49.954651] CPU5: Booted secondary processor 0x0000000103 [0x411fd073]
[   49.961431] CPU5 is up
[   50.069784] dwc-eth-dwmac 2490000.ethernet eth0: configuring for phy/rgmii link mode
[   50.077634] dwmac4: Master AXI performs any burst length
[   50.080718] dwc-eth-dwmac 2490000.ethernet eth0: No Safety Features support found
[   50.088172] dwc-eth-dwmac 2490000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[   50.096851] dwc-eth-dwmac 2490000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
[   50.110897] usb-conn-gpio 3520000.padctl:ports:usb2-0:connector: repeated role: device
[   50.113922] tegra-xusb 3530000.usb: Firmware timestamp: 2020-07-06 13:39:28 UTC
[   50.147552] OOM killer enabled.
[   50.148441] Restarting tasks ... done.
[   50.152552] VDDIO_SDMMC3_AP: voltage operation not allowed
[   50.154761] random: crng reseeded on system resumption
[   50.162912] PM: suspend exit
[   50.212215] VDDIO_SDMMC3_AP: voltage operation not allowed
[   50.271578] VDDIO_SDMMC3_AP: voltage operation not allowed
[   50.338597] VDDIO_SDMMC3_AP: voltage operation not allowed
[  234.474848] nfs: server 10.26.51.252 not responding, still trying
[  234.538769] nfs: server 10.26.51.252 not responding, still trying
[  237.546922] nfs: server 10.26.51.252 not responding, still trying
[  254.762753] nfs: server 10.26.51.252 not responding, timed out
[  254.762771] nfs: server 10.26.51.252 not responding, timed out
[  254.766376] nfs: server 10.26.51.252 not responding, timed out
[  254.766392] nfs: server 10.26.51.252 not responding, timed out
[  254.783778] nfs: server 10.26.51.252 not responding, timed out
[  254.789582] nfs: server 10.26.51.252 not responding, timed out
[  254.795421] nfs: server 10.26.51.252 not responding, timed out
[  254.801193] nfs: server 10.26.51.252 not responding, timed out

> Do either of the two attached diffs make any difference?

I will try these next.

Thanks
Jon

-- 
nvpublic



From phil at raspberrypi.com  Mon Mar 10 07:21:05 2025
From: phil at raspberrypi.com (Phil Elwell)
Date: Mon, 10 Mar 2025 14:21:05 +0000
Subject: [PATCH v6 00/10] Add support for RaspberryPi RP1 PCI device using
 a DT overlay
In-Reply-To: <Z87wTfChRC5Ruwc0@apocalypse>
References: <CAMEGJJ3=W8_R0xBvm8r+Q7iExZx8xPBHEWWGAT9ngpGWDSKCaQ@mail.gmail.com>
 <20250213171435.1c2ce376@bootlin.com> <CAMEGJJ1++aeE7WWLVVesbujME+r2WicEkK+CQgigRRp2grYf=A@mail.gmail.com>
 <Z87wTfChRC5Ruwc0@apocalypse>
Message-ID: <CAMEGJJ0f4YUgdWBhxvQ_dquZHztve9KO7pvQjoDWJ3=zd3cgcg@mail.gmail.com>

Hi Andrea,

On Mon, 10 Mar 2025 at 13:58, Andrea della Porta <andrea.porta at suse.com> wrote:
>
> Hi,
>
> On 16:27 Thu 13 Feb     , Phil Elwell wrote:
> > Hi Herv?,
> >
> > On Thu, 13 Feb 2025 at 16:14, Herve Codina <herve.codina at bootlin.com> wrote:
> > >
> > > Hi Phil,
> > >
> > > On Thu, 13 Feb 2025 15:18:45 +0000
> > > Phil Elwell <phil at raspberrypi.com> wrote:
> > >
> > > > Hi Andrea,
> > > >
> > > > The problem with this approach (loading an overlay from the RP1 PCIe
> > > > driver), and it's one that I have raised with you offline, is that
> > > > (unless anyone can prove otherwise) it becomes impossible to create a
> > > > Pi 5 DTS file which makes use of the RP1's resources. How do you
> > > > declare something as simple as a button wired to an RP1 GPIO, or fan
> > > > connected to a PWM output?
> > >
> > > The driver could be improved in a second step.
> > > For instance, it could load the dtbo from user-space using request_firmare()
> > > instead of loading the embedded dtbo.
> > >
> > > >
> > > > If this is the preferred route to upstream adoption, I would prefer it
> > > > if rp1.dtso could be split in two - an rp1.dtsi similar to what we
> > > > have downstream, and an rp1.dtso that #includes it. In this way we can
> > > > keep the patching and duplication to a minimum.
> > >
> > > Indeed, having a rp1.dtsi avoid duplication but how the rp1.dtso in
> > > the the kernel sources could include user customization (button, fan, ...)
> > > without being modified ?
> > > At least we have to '#include <my_rp1_customizations.dtsi>'.
> > >
> > > Requesting the dtbo from user-space allows to let the user to create
> > > its own dtso without the need to modify the one in kernel sources.
> > >
> > > Does it make sense ?
> >
> > I think I understand what you are saying, but at this point the RP1
> > overlay would no longer be an RP1 overlay - it would be an
> > RP1-and-everything-connected-to-it overlay, which is inherently
> > board-specific. Which user-space process do you think would be
> > responsible for loading this alternative overlay, choosing carefully
> > based on the platform it is running on? Doesn't that place quite a
> > burden on all the OS maintainers who up to now have just needed a
> > kernel and a bunch of dtb files?
> >
> > If it is considered essential that the upstream Pi 5 dts file does not
> > include RP1 and its children, then Raspberry Pi are going to have to
> > walk a different path until we've seen how that can work. By splitting
> > rp1.dtso as I suggested, and perhaps providing an alternative helper
> > function that only applies the built-in overlay if the device node
> > doesn't already exist, we get to stay as close to upstream as
> > possible.
> >
> > Phil
>
> So, the problem is twofold: the first is due to the fact that downstream
> expects the dtb to be fully declared at fw load time (I'll call that
> *monolithic* dtb from now on), the second is about how to represent dependencies
> between board dtb and rp1 overlay which arises only when using overlays instead
> of a monolithic dtb.
>
> The former issue must be solved first in order for the latter to even exists
> (if we don't use overlay, the dependencies are fully exposed in the dtb since
> the beginning), so I'll concentrate on the former for now.
>
> There are 3 possible scenarios to be reconciled:
>
>
> 1 - MONOLITHIC DTB
>
> This is the downstream case, where it's advisable to have only one dtb blob
> containing everything (rp1 included) loaded by the fw. In this case the
> resulting devicetree would looks like:
>
>   axi {
>     pcie at 120000 {
>       rp1_nexus {
>         pci-ep-bus at 1 {
>              ...
>         }
>       }
>     }
>   }

This is indeed our current DT usage for the Pi 5 family - a single DTB
describing each board - although I would like to make it clear that
overlays can then be applied on top of it describing the attached
peripherals.

> 2 - RP1 LOADED FROM OVERLAY BY THE FW
>
> In this case the rp1 dt node is loaded from overlay directly by the fw and the
> resulting devicetree is exactly equal to the monolithic dtb scenario.
> In order for that overlay to be loaded by fw, just add 'dtoverlay=rp1' in
> 'config.txt'.

This halfway house combines the advantages and disadvantages of
scenarios 1 and 3. Compared to scenario 3 it gains support for
applying overlays that make use of interfaces provided by RP1 - I2C,
SPI, UARTs etc. Compared to scenario 1 it loses the ability for the
base DTB to refer to elements of RP1, other than by replacing these
DTB elements with overlays that must be loaded after the RP1 overlay.
As such, we would see that as a backwards step and not use it.

> 3 - RP1 LOADED FROM OVERLAY AT RUNTIME
>
> Here it's the rp1 driver that loads the overlay at runtime, which is the case
> that this patchset originally proposed. The devicetree ends up like this:
>
>   axi {
>     pcie at 120000 {
>       pci at 0,0 {
>         dev at 0,0 {
>           pci-ep-bus at 1 {
>                ...
>           }
>         }
>       }
>     }
>   }
>
> and this is exepcially useful to cope with the case in which there's no DT
> natively used, e.g. on ACPI systems.
>
>
> In order for all those 3 mentioned scenatios to work, I propose the following
> inclusion scheme for for the dts files (the arrow points to the includer):
>
>
>  rp1-pci.dtso         rp1.dtso
>      ^                    ^
>      |                    |
> rp1-common.dtsi ----> rp1-nexus.dtsi ----> bcm2712-rpi-5-b-MONOLITHIC.dts
>
>
> where those dts are defined as follows (omitting the internal properties for
> clarity sake):
>
>
> - rp1-common.dtsi ------- // definition of core rp1 and its peripherals, common
>                           // for all cases
>
>         pci_ep_bus: pci-ep-bus at 1
>         {
>                 rp1_clocks { };
>
>                 rp1_gpio { };
>
>                 rp1_eth { };
>         };
>
> - rp1-pci.dtso ---------- // ovl linked in the rp1 driver code to be loaded at
>                           // runtime from rp1 driver. Only for case 3
>
>         /plugin/;
>         fragment at 0 {
>                 target-path="";
>                 __overlay__ {
>                         #include "rp1-common.dtsi"
>                 };
>         }
>
> - rp1-nexus.dtsi ------- // adapter to decouple rp1 ranges for non runtime-loaded
>                          // overlay case (i.e. only for case 1 and 2)
>
>         rp1_nexus {
>                 ranges = ...
>
>                  #include "rp1-common.dtsi"
>         };
>
> - rp1.dtso ------------ // overlay to be loaded by fw (case 2)
>
>         /plugin/;
>         &pcie2 {
>                 #include "rp1-nexus.dtsi"
>         };
>
> - bcm2712-rpi-5-b-MONOLITHIC.dts --- // monolithic dtb to avoid any overlay use
>                                      // (case 1)
>
>         / {
>                 ... all rpi5 board dts ...
>                 &pcie2 {
>                         #include "rp1-nexus.dtsi"
>                 };
>         };
>
>
> with only minimal changes to the rp1 driver code, I can confirm that all those
> scenarios can coexits and are working fine. Before processding with a new patchset
> I'd like to have some thoughts about that, do you think this is a viable approach?

Thank you for this - the creation of a core RP1 declaration that can
be tailored to multiple applications using different wrappers is
exactly what I had in mind. I agree that your partitioning scheme can
cater for the 3 usage scenarios, but for the reasons outlined above I
think scenario 2 is not useful to us, although it isn't impossible
that U-boot might see things differently; I see no harm in having it
supported, but I wouldn't want anyone to go to unnecessary effort to
make it work.

Phil


From linux.amoon at gmail.com  Mon Mar 10 07:34:41 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Mon, 10 Mar 2025 20:04:41 +0530
Subject: [PATCH v4 0/4] Exynos Thermal code improvement
Message-ID: <20250310143450.8276-1-linux.amoon@gmail.com>

Hi All,

This patch series is a rework of my previous patch series [1],
where the code changes were not adequately justified.

In this new series, I have improved the commit subject
and commit message to better explain the changes.

v4: Tried to address Lukasz review coments.

Tested on Odroid U3 amd XU4 SoC boards.

[2] https://lore.kernel.org/all/20250216195850.5352-2-linux.amoon at gmail.com/
[1] https://lore.kernel.org/all/20220515064126.1424-1-linux.amoon at gmail.com/
[0] https://lore.kernel.org/lkml/CANAwSgS=08fVsqn95WHzSF71WTTyD2-=K2C6-BEz0tY0t6A1-g at mail.gmail.com/T/#m77e57120d230d57f34c29e1422d7fc5f5587ac30

Thanks
-Anand

Anand Moon (4):
  drivers/thermal/exynos: Refactor clk_sec initialization inside
    SOC-specific case
  drivers/thermal/exymos: Remove redundant IS_ERR() checks for clk_sec
    clock
  drivers/thermal/exymos: Fixed the efuse min max value for exynos5422
  drivers/thermal/exymos: Use guard notation when acquiring mutex

 drivers/thermal/samsung/exynos_tmu.c | 87 +++++++++++++++-------------
 1 file changed, 46 insertions(+), 41 deletions(-)


base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
-- 
2.48.1



From linux.amoon at gmail.com  Mon Mar 10 07:34:42 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Mon, 10 Mar 2025 20:04:42 +0530
Subject: [PATCH v4 1/4] drivers/thermal/exynos: Refactor clk_sec initialization inside SOC-specific case
In-Reply-To: <20250310143450.8276-1-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
Message-ID: <20250310143450.8276-2-linux.amoon@gmail.com>

Refactor the initialization of the clk_sec clock to be inside the
SOC_ARCH_EXYNOS5420_TRIMINFO case. It ensures that the clk_sec clock
is only initialized for the specified SOC and not for other SOCs,
thereby simplifying the code. The clk_sec clock is used by the TMU
for GPU on the Exynos 542x platform.

Removed redundant IS_ERR() checks for the clk_sec clock since error
handling is already managed internally by clk_unprepare() functions.

Signed-off-by: Anand Moon <linux.amoon at gmail.com>
---
v4: Fix the aligment of code clk for clk_prepare in proper if/else block.
    update the commit for clk_sec used.
    checked to goto clean up all the clks are proper.
    drop IS_ERR() check for clk_sec.
v3: improve the commit message.
---
 drivers/thermal/samsung/exynos_tmu.c | 37 ++++++++++++++--------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 47a99b3c53958..3657920de0004 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -1037,29 +1037,30 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 		return ret;
 
 	data->clk = devm_clk_get(dev, "tmu_apbif");
-	if (IS_ERR(data->clk))
+	if (IS_ERR(data->clk)) {
 		return dev_err_probe(dev, PTR_ERR(data->clk), "Failed to get clock\n");
-
-	data->clk_sec = devm_clk_get(dev, "tmu_triminfo_apbif");
-	if (IS_ERR(data->clk_sec)) {
-		if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
-			return dev_err_probe(dev, PTR_ERR(data->clk_sec),
-					     "Failed to get triminfo clock\n");
 	} else {
-		ret = clk_prepare(data->clk_sec);
+		ret = clk_prepare(data->clk);
 		if (ret) {
 			dev_err(dev, "Failed to get clock\n");
 			return ret;
 		}
 	}
 
-	ret = clk_prepare(data->clk);
-	if (ret) {
-		dev_err(dev, "Failed to get clock\n");
-		goto err_clk_sec;
-	}
-
 	switch (data->soc) {
+	case SOC_ARCH_EXYNOS5420_TRIMINFO:
+		data->clk_sec = devm_clk_get(dev, "tmu_triminfo_apbif");
+		if (IS_ERR(data->clk_sec)) {
+			ret = dev_err_probe(dev, PTR_ERR(data->clk_sec),
+					    "Failed to get clk_sec clock\n");
+			goto err_clk;
+		}
+		ret = clk_prepare(data->clk_sec);
+		if (ret) {
+			dev_err(dev, "Failed to prepare clk_sec clock\n");
+			goto err_clk_sec;
+		}
+		break;
 	case SOC_ARCH_EXYNOS5433:
 	case SOC_ARCH_EXYNOS7:
 		data->sclk = devm_clk_get(dev, "tmu_sclk");
@@ -1112,11 +1113,10 @@ static int exynos_tmu_probe(struct platform_device *pdev)
 
 err_sclk:
 	clk_disable_unprepare(data->sclk);
+err_clk_sec:
+	clk_unprepare(data->clk_sec);
 err_clk:
 	clk_unprepare(data->clk);
-err_clk_sec:
-	if (!IS_ERR(data->clk_sec))
-		clk_unprepare(data->clk_sec);
 	return ret;
 }
 
@@ -1128,8 +1128,7 @@ static void exynos_tmu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->sclk);
 	clk_unprepare(data->clk);
-	if (!IS_ERR(data->clk_sec))
-		clk_unprepare(data->clk_sec);
+	clk_unprepare(data->clk_sec);
 }
 
 #ifdef CONFIG_PM_SLEEP
-- 
2.48.1



From linux.amoon at gmail.com  Mon Mar 10 07:34:43 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Mon, 10 Mar 2025 20:04:43 +0530
Subject: [PATCH v4 2/4] drivers/thermal/exymos: Remove redundant IS_ERR() checks for clk_sec clock
In-Reply-To: <20250310143450.8276-1-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
Message-ID: <20250310143450.8276-3-linux.amoon@gmail.com>

Remove unnecessary IS_ERR() checks for the clk_sec clock,
the clk_enable() and clk_disable() functions can handle NULL clock
pointers, so the additional checks are redundant and have been removed
to simplify the code.

Signed-off-by: Anand Moon <linux.amoon at gmail.com>
---
v4: drop IE_ERR() for clk_unprepare() as its handle in earlier code.
v3: improve the commit message.
---
 drivers/thermal/samsung/exynos_tmu.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 3657920de0004..ac3b9d2c900ca 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -258,8 +258,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 
 	mutex_lock(&data->lock);
 	clk_enable(data->clk);
-	if (!IS_ERR(data->clk_sec))
-		clk_enable(data->clk_sec);
+	clk_enable(data->clk_sec);
 
 	status = readb(data->base + EXYNOS_TMU_REG_STATUS);
 	if (!status) {
@@ -269,8 +268,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 		data->tmu_clear_irqs(data);
 	}
 
-	if (!IS_ERR(data->clk_sec))
-		clk_disable(data->clk_sec);
+	clk_disable(data->clk_sec);
 	clk_disable(data->clk);
 	mutex_unlock(&data->lock);
 
-- 
2.48.1



From suzuki.poulose at arm.com  Mon Mar 10 04:32:05 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 11:32:05 +0000
Subject: [PATCH v6 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
In-Reply-To: <20250306121110.1647948-1-yeoreum.yun@arm.com>
References: <20250306121110.1647948-1-yeoreum.yun@arm.com>
Message-ID: <174160625284.2197960.9649186230571551042.b4-ty@arm.com>


On Thu, 06 Mar 2025 12:11:01 +0000, Yeoreum Yun wrote:
> In some coresight drivers, drvdata->spinlock can be held during __schedule()
> by perf_event_task_sched_out()/in().
> 
> Since drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
> 
> [...]

Applied, thanks!

[1/9] coresight: change coresight_device lock type to raw_spinlock_t
      https://git.kernel.org/coresight/c/26f060c1
[2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
      https://git.kernel.org/coresight/c/743c5a97
[3/9] coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
      https://git.kernel.org/coresight/c/4cf364ca
[4/9] coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/e3044065
[5/9] coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/6b80c0ab
[6/9] coresight-funnel: change funnel_drvdata spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/56eb02f0
[7/9] coresight-replicator: change replicator_drvdata spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/982d0a0e
[8/9] coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/db11f75b
[9/9] coresight/ultrasoc: change smb_drv_data spinlock's type to raw_spinlock_t
      https://git.kernel.org/coresight/c/d11eb31d

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From maz at kernel.org  Mon Mar 10 04:54:52 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 11:54:52 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <20250310103008.3471-2-ankita@nvidia.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>
Message-ID: <861pv5p0c3.wl-maz@kernel.org>

On Mon, 10 Mar 2025 10:30:08 +0000,
<ankita at nvidia.com> wrote:
> 
> From: Ankit Agrawal <ankita at nvidia.com>
> 
> Today KVM forces the memory to either NORMAL or DEVICE_nGnRE
> based on pfn_is_map_memory (which tracks whether the device memory
> is added to the kernel) and ignores the per-VMA flags that indicates the
> memory attributes. The KVM code is thus restrictive and allows only for
> the memory that is added to the kernel to be marked as cacheable.
> 
> The device memory such as on the Grace Hopper/Blackwell systems
> is interchangeable with DDR memory and retains properties such as
> cacheability, unaligned accesses, atomics and handling of executable
> faults. This requires the device memory to be mapped as NORMAL in
> stage-2.
> 
> Given that the GPU device memory is not added to the kernel (but is rather
> VMA mapped through remap_pfn_range() in nvgrace-gpu module which sets
> VM_PFNMAP), pfn_is_map_memory() is false and thus KVM prevents such memory
> to be mapped Normal cacheable. The patch aims to solve this use case.
> 
> A cachebility check is made if the VM_PFNMAP is set in VMA flags by
> consulting the VMA pgprot value. If the pgprot mapping type is MT_NORMAL,
> it is safe to be mapped cacheable as the KVM S2 will have the same
> Normal memory type as the VMA has in the S1 and KVM has no additional
> responsibility for safety. Checking pgprot as NORMAL is thus a KVM
> sanity check.
> 
> Introduce a new variable cacheable_devmem to indicate a safely
> cacheable mapping. Do not set the device variable when cacheable_devmem
> is true. This essentially have the effect of setting stage-2 mapping
> as NORMAL through kvm_pgtable_stage2_map.
> 
> Add check for COW VM_PFNMAP and refuse such mapping.
> 
> No additional checks for MTE are needed as kvm_arch_prepare_memory_region()
> already tests it at an early stage during memslot creation. There would
> not even be a fault if the memslot is not created.
> 
> Note when FWB is not enabled, the kernel expects to trivially do
> cache management by flushing the memory by linearly converting a
> kvm_pte to phys_addr to a KVA, see kvm_flush_dcache_to_poc(). The
> cache management thus relies on memory being mapped. So do not allow
> !FWB.
> 
> Signed-off-by: Ankit Agrawal <ankita at nvidia.com>
> Suggested-by: Catalin Marinas <catalin.marinas at arm.com>
> Suggested-by: Jason Gunthorpe <jgg at nvidia.com>
> Suggested-by: David Hildenbrand <david at redhat.com>
> ---
>  arch/arm64/include/asm/kvm_pgtable.h |  8 ++++++
>  arch/arm64/kvm/hyp/pgtable.c         |  2 +-
>  arch/arm64/kvm/mmu.c                 | 43 +++++++++++++++++++++++++++-
>  3 files changed, 51 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
> index 6b9d274052c7..f21e2fae2bfe 100644
> --- a/arch/arm64/include/asm/kvm_pgtable.h
> +++ b/arch/arm64/include/asm/kvm_pgtable.h
> @@ -507,6 +507,14 @@ u64 kvm_pgtable_hyp_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size);
>   */
>  u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift);
>  
> +/**
> + * stage2_has_fwb() - Determine whether FWB is supported
> + * @pgt:    Page-table structure initialised by kvm_pgtable_stage2_init*()
> + *
> + * Return: True if FWB is supported.
> + */
> +bool stage2_has_fwb(struct kvm_pgtable *pgt);
> +
>  /**
>   * kvm_pgtable_stage2_pgd_size() - Helper to compute size of a stage-2 PGD
>   * @vtcr:	Content of the VTCR register.
> diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
> index df5cc74a7dd0..ee6b98fefd61 100644
> --- a/arch/arm64/kvm/hyp/pgtable.c
> +++ b/arch/arm64/kvm/hyp/pgtable.c
> @@ -637,7 +637,7 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
>  	return vtcr;
>  }
>  
> -static bool stage2_has_fwb(struct kvm_pgtable *pgt)
> +bool stage2_has_fwb(struct kvm_pgtable *pgt)
>  {
>  	if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
>  		return false;
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 1f55b0c7b11d..4b3a03c9d700 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1454,6 +1454,15 @@ static bool kvm_vma_mte_allowed(struct vm_area_struct *vma)
>  	return vma->vm_flags & VM_MTE_ALLOWED;
>  }
>  
> +/*
> + * Determine the memory region cacheability from VMA's pgprot. This
> + * is used to set the stage 2 PTEs.
> + */
> +static unsigned long mapping_type(pgprot_t page_prot)
> +{
> +	return FIELD_GET(PTE_ATTRINDX_MASK, pgprot_val(page_prot));
> +}
> +
>  static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  			  struct kvm_s2_trans *nested,
>  			  struct kvm_memory_slot *memslot, unsigned long hva,
> @@ -1463,6 +1472,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  	bool write_fault, writable, force_pte = false;
>  	bool exec_fault, mte_allowed;
>  	bool device = false, vfio_allow_any_uc = false;
> +	bool cacheable_devmem = false;
>  	unsigned long mmu_seq;
>  	phys_addr_t ipa = fault_ipa;
>  	struct kvm *kvm = vcpu->kvm;
> @@ -1600,6 +1610,19 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  
>  	vfio_allow_any_uc = vma->vm_flags & VM_ALLOW_ANY_UNCACHED;
>  
> +	if (vma->vm_flags & VM_PFNMAP) {
> +		/* Reject COW VM_PFNMAP */
> +		if (is_cow_mapping(vma->vm_flags))
> +			return -EINVAL;
> +		/*
> +		 * If the VM_PFNMAP is set in VMA flags, do a KVM sanity
> +		 * check to see if pgprot mapping type is MT_NORMAL and a
> +		 * safely cacheable device memory.
> +		 */
> +		if (mapping_type(vma->vm_page_prot) == MT_NORMAL)
> +			cacheable_devmem = true;
> +	}
> +
>  	/* Don't use the VMA after the unlock -- it may have vanished */
>  	vma = NULL;
>  
> @@ -1633,8 +1656,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  		 *
>  		 * In both cases, we don't let transparent_hugepage_adjust()
>  		 * change things at the last minute.
> +		 *
> +		 * Do not set device as the device memory is cacheable. Note
> +		 * that such mapping is safe as the KVM S2 will have the same
> +		 * Normal memory type as the VMA has in the S1.
>  		 */
> -		device = true;
> +		if (!cacheable_devmem)
> +			device = true;
>  	} else if (logging_active && !write_fault) {
>  		/*
>  		 * Only actually map the page as writable if this was a write
> @@ -1716,6 +1744,19 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  		prot |= KVM_PGTABLE_PROT_X;
>  	}
>  
> +	/*
> +	 *  When FWB is unsupported KVM needs to do cache flushes
> +	 *  (via dcache_clean_inval_poc()) of the underlying memory. This is
> +	 *  only possible if the memory is already mapped into the kernel map.
> +	 *
> +	 *  Outright reject as the cacheable device memory is not present in
> +	 *  the kernel map and not suitable for cache management.
> +	 */
> +	if (cacheable_devmem && !stage2_has_fwb(pgt)) {
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +

These new error reasons should at least be complemented by an
equivalent check at the point where the memslot is registered. It
maybe OK to blindly return an error at fault time (because userspace
has messed with the mapping behind our back), but there should at
least be something telling a well behaved userspace that there is a
bunch of combination we're unwilling to support.

Which brings me to the next point: FWB is not discoverable from
userspace. How do you expect a VMM to know what it can or cannot do?

	M.

-- 
Without deviation from the norm, progress is not possible.


From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:34 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:34 +0000
Subject: [PATCH net-next 4/9] net: stmmac: ipq806x: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbxq-005qYG-2E@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Pass plat_dat into ipq806x_gmac_of_parse(), and set gmac->phy_mode from
plat_dat->phy_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index 0a9c137cc4e6..ca4035cbb55b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -211,16 +211,12 @@ static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, int speed)
 	return 0;
 }
 
-static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
+static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac,
+				 struct plat_stmmacenet_data *plat_dat)
 {
 	struct device *dev = &gmac->pdev->dev;
-	int ret;
 
-	ret = of_get_phy_mode(dev->of_node, &gmac->phy_mode);
-	if (ret) {
-		dev_err(dev, "missing phy mode property\n");
-		return -EINVAL;
-	}
+	gmac->phy_mode = plat_dat->phy_interface;
 
 	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
 		dev_err(dev, "missing qcom id property\n");
@@ -398,7 +394,7 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
 
 	gmac->pdev = pdev;
 
-	err = ipq806x_gmac_of_parse(gmac);
+	err = ipq806x_gmac_of_parse(gmac, plat_dat);
 	if (err) {
 		dev_err(dev, "device tree parsing error\n");
 		return err;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:39 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:39 +0000
Subject: [PATCH net-next 5/9] net: stmmac: meson8b: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbxv-005qYM-5m@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set dwmac->phy_mode from plat_dat->phy_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index 9c2d62d133ad..a50782994b97 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -417,11 +417,7 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
 		return PTR_ERR(dwmac->regs);
 
 	dwmac->dev = &pdev->dev;
-	ret = of_get_phy_mode(pdev->dev.of_node, &dwmac->phy_mode);
-	if (ret) {
-		dev_err(&pdev->dev, "missing phy-mode property\n");
-		return ret;
-	}
+	dwmac->phy_mode = plat_dat->phy_interface;
 
 	/* use 2ns as fallback since this value was previously hardcoded */
 	if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns",
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:44 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:44 +0000
Subject: [PATCH net-next 6/9] net: stmmac: rk: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trby0-005qYS-AE@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set bsp_priv->phy_iface from plat->phy_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..40e8197812e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1749,7 +1749,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 	if (!bsp_priv)
 		return ERR_PTR(-ENOMEM);
 
-	of_get_phy_mode(dev->of_node, &bsp_priv->phy_iface);
+	bsp_priv->phy_iface = plat->phy_interface;
 	bsp_priv->ops = ops;
 
 	/* Some SoCs have multiple MAC controllers, which need
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:54 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:54 +0000
Subject: [PATCH net-next 8/9] net: stmmac: sun8i: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbyA-005qYf-Hb@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

sun8i was using of_get_phy_mode() to set plat_dat->mac_interface, which
defaults to plat_dat->phy_interface when the mac-mode DT property is
not present. As nothing in arch/*/boot/dts sets the mac-mode property,
it is highly likely that these two will be identical, and thus there
is no need for this glue driver to set plat_dat->mac_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 4b7b2582a120..85723a78793a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1155,11 +1155,10 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 	struct stmmac_resources stmmac_res;
 	struct sunxi_priv_data *gmac;
 	struct device *dev = &pdev->dev;
-	phy_interface_t interface;
-	int ret;
 	struct stmmac_priv *priv;
 	struct net_device *ndev;
 	struct regmap *regmap;
+	int ret;
 
 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
 	if (ret)
@@ -1219,10 +1218,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = of_get_phy_mode(dev->of_node, &interface);
-	if (ret)
-		return -EINVAL;
-
 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
 	if (IS_ERR(plat_dat))
 		return PTR_ERR(plat_dat);
@@ -1230,7 +1225,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 	/* platform data specifying hardware features and callbacks.
 	 * hardware features were copied from Allwinner drivers.
 	 */
-	plat_dat->mac_interface = interface;
 	plat_dat->rx_coe = STMMAC_RX_COE_TYPE2;
 	plat_dat->tx_coe = 1;
 	plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:59 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:59 +0000
Subject: [PATCH net-next 9/9] net: stmmac: sunxi: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbyF-005qYl-Lu@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set gmac->interface from plat_dat->phy_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index 1b1ce2888b2e..9f098ff0ff05 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -116,11 +116,7 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
 	if (!gmac)
 		return -ENOMEM;
 
-	ret = of_get_phy_mode(dev->of_node, &gmac->interface);
-	if (ret && ret != -ENODEV) {
-		dev_err(dev, "Can't get phy-mode\n");
-		return ret;
-	}
+	gmac->interface = plat_dat->phy_interface;
 
 	gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
 	if (IS_ERR(gmac->tx_clk)) {
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:49 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:49 +0000
Subject: [PATCH net-next 7/9] net: stmmac: sti: remove of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trby5-005qYY-Dp@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Pass plat_dat into sti_dwmac_parse_data(), and set dwmac->interface
from plat_dat->phy_interface.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 13b9c2a51fce..be57c6c12c1c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -185,7 +185,8 @@ static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
 }
 
 static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
-				struct platform_device *pdev)
+				struct platform_device *pdev,
+				struct plat_stmmacenet_data *plat_dat)
 {
 	struct resource *res;
 	struct device *dev = &pdev->dev;
@@ -204,12 +205,7 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
 	if (IS_ERR(regmap))
 		return PTR_ERR(regmap);
 
-	err = of_get_phy_mode(np, &dwmac->interface);
-	if (err && err != -ENODEV) {
-		dev_err(dev, "Can't get phy-mode\n");
-		return err;
-	}
-
+	dwmac->interface = plat_dat->phy_interface;
 	dwmac->regmap = regmap;
 	dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
 	dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
@@ -268,7 +264,7 @@ static int sti_dwmac_probe(struct platform_device *pdev)
 	if (!dwmac)
 		return -ENOMEM;
 
-	ret = sti_dwmac_parse_data(dwmac, pdev);
+	ret = sti_dwmac_parse_data(dwmac, pdev, plat_dat);
 	if (ret) {
 		dev_err(&pdev->dev, "Unable to parse OF data\n");
 		return ret;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Mon Mar 10 05:10:18 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 10 Mar 2025 12:10:18 +0000
Subject: [PATCH net-next 1/9] net: stmmac: qcom-ethqos: remove
 of_get_phy_mode()
In-Reply-To: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
Message-ID: <E1trbxa-005qXy-MQ@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it a second time in qcom_ethqos_probe(). Use
plat_dat->phy_interface to initialise ethqos->phy_mode.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index eafe637540b6..0e4da216f942 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -794,9 +794,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
 	if (!ethqos)
 		return -ENOMEM;
 
-	ret = of_get_phy_mode(np, &ethqos->phy_mode);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to get phy mode\n");
+	ethqos->phy_mode = plat_dat->phy_interface;
 	switch (ethqos->phy_mode) {
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
-- 
2.30.2



From kory.maincent at bootlin.com  Mon Mar 10 05:14:13 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 10 Mar 2025 13:14:13 +0100
Subject: [PATCH net-next v2 5/7] net: ethtool: phy: Convert the PHY_GET
 command to generic phy dump
In-Reply-To: <20250308155440.267782-6-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
	<20250308155440.267782-6-maxime.chevallier@bootlin.com>
Message-ID: <20250310131413.505e676f@kmaincent-XPS-13-7390>

On Sat,  8 Mar 2025 16:54:37 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> Now that we have an infrastructure in ethnl for perphy DUMPs, we can get
> rid of the custom ->doit and ->dumpit to deal with PHY listing commands.
> 
> As most of the code was custom, this basically means re-writing how we
> deal with PHY listing.

Only nitpick ;)

> -static int
> -ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff
> *skb) +static int phy_prepare_data(const struct ethnl_req_info *req_info,
> +			    struct ethnl_reply_data *reply_data,
> +			    const struct genl_info *info)
>  {
> -	struct phy_req_info *req_info = PHY_REQINFO(req_base);
> -	struct phy_device_node *pdn = req_info->pdn;
> -	struct phy_device *phydev = pdn->phy;
> -	enum phy_upstream ptype;
> +	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
> +	struct phy_link_topology *topo = reply_data->dev->link_topo;
> +	struct nlattr **tb = info->attrs;
> +	struct phy_device_node *pdn;
> +	struct phy_device *phydev;
  
Reverse xmas tree.

> -	ptype = pdn->upstream_type;
> +	/* RTNL is held by th caller */

Small typo here *the*.

The rest is good for me.

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From kory.maincent at bootlin.com  Mon Mar 10 05:21:03 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 10 Mar 2025 13:21:03 +0100
Subject: [PATCH net-next v2 4/7] net: ethtool: netlink: Introduce
 per-phy DUMP helpers
In-Reply-To: <20250308155440.267782-5-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
	<20250308155440.267782-5-maxime.chevallier@bootlin.com>
Message-ID: <20250310132103.1312d1b6@kmaincent-XPS-13-7390>

On Sat,  8 Mar 2025 16:54:36 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> As there are multiple ethnl commands that report messages based on
> phy_device information, let's introduce a set of ethnl generic dump
> helpers to allow DUMP support for each PHY on a given netdev.
> 
> This logic iterates over the phy_link_topology of each netdev (or a
> single netdev for filtered DUMP), and call ethnl_default_dump_one() with
> the req_info populated with ifindex + phyindex.
> 
> This allows re-using all the existing infra for phy-targetting commands
> that already use ethnl generic helpers.
> 
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---
> V2: Rebase
> 
>  net/ethtool/netlink.c | 53 +++++++++++++++++++++++++++++++++++++++++++
>  net/ethtool/netlink.h |  6 +++++
>  2 files changed, 59 insertions(+)
> 
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index ae06b72239a8..a09bcd67b38f 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -559,6 +559,59 @@ static int ethnl_default_dump_one(struct sk_buff *skb,
>  	return ret;
>  }
>  
> +/* Specific context for phy-targeting command DUMP operatins. We keep in
> context
> + * the latest phy_index we dumped, in case of an interrupted DUMP.
> + */
> +struct ethnl_dump_ctx_perphy {
> +	unsigned long phy_index;
> +};
> +
> +int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx)

Could you add comments or event better, kdoc for non static function to explain
their purpose.

> +{
> +	struct ethnl_dump_ctx_perphy *dump_ctx;
> +
> +	dump_ctx = kzalloc(sizeof(*dump_ctx), GFP_KERNEL);
> +	if (!dump_ctx)
> +		return -ENOMEM;
> +
> +	ctx->cmd_ctx = dump_ctx;
> +
> +	return 0;
> +}
> +
> +void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx)

same.

> +{
> +	kfree(ctx->cmd_ctx);
> +}
> +
> +int ethnl_dump_one_dev_perphy(struct sk_buff *skb,
> +			      struct ethnl_dump_ctx *ctx,
> +			      const struct genl_info *info)

same.

> +{
> +	struct ethnl_dump_ctx_perphy *dump_ctx = ctx->cmd_ctx;
> +	struct net_device *dev = ctx->reply_data->dev;
> +	struct phy_device_node *pdn;
> +	int ret = 0;
> +
> +	if (!dev->link_topo)
> +		return 0;
> +
> +	xa_for_each_start(&dev->link_topo->phys, dump_ctx->phy_index,
> +			  pdn, dump_ctx->phy_index) {
> +		ctx->req_info->phy_index = dump_ctx->phy_index;
> +
> +		/* We can re-use the original dump_one as ->prepare_data in
> +		 * commands use ethnl_req_get_phydev(), which gets the PHY
> from
> +		 * what's in req_info
> +		 */
> +		ret = ethnl_default_dump_one(skb, ctx, info);
> +		if (ret)
> +			break;
> +	}
> +
> +	return ret;
> +}

Regards,
---
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From kory.maincent at bootlin.com  Mon Mar 10 05:23:16 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Mon, 10 Mar 2025 13:23:16 +0100
Subject: [PATCH net-next v2 7/7] net: ethtool: pse-pd: Use per-PHY DUMP
 operations
In-Reply-To: <20250308155440.267782-8-maxime.chevallier@bootlin.com>
References: <20250308155440.267782-1-maxime.chevallier@bootlin.com>
	<20250308155440.267782-8-maxime.chevallier@bootlin.com>
Message-ID: <20250310132316.413605ad@kmaincent-XPS-13-7390>

On Sat,  8 Mar 2025 16:54:39 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> Leverage the per-phy ethnl DUMP helpers in case we have more that one
> PSE PHY on the link.

I am unavailable now, I will be able to test it in two weeks.

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From dario.binacchi at amarulasolutions.com  Mon Mar 10 05:23:56 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Mon, 10 Mar 2025 13:23:56 +0100
Subject: [PATCH v2] ARM: dts: stm32: use IRQ_TYPE_EDGE_FALLING on stm32mp157c-dk2
Message-ID: <20250310122402.8795-1-dario.binacchi@amarulasolutions.com>

Replace the number 2 with the appropriate numerical constant defined in
dt-bindings/interrupt-controller/irq.h.

Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Reviewed-by: Antonio Borneo <antonio.borneo at foss.st.com>

---

Changes in v2:
- Drop inclusion of dt-bindings/interrupt-controller/irq.h header
- Add Reviewed-by tag of Antonio Borneo

 arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
index 5f9c0160a9c4..324f7bb988d1 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
@@ -67,7 +67,7 @@ &i2c1 {
 	touchscreen at 38 {
 		compatible = "focaltech,ft6236";
 		reg = <0x38>;
-		interrupts = <2 2>;
+		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
 		interrupt-parent = <&gpiof>;
 		touchscreen-size-x = <480>;
 		touchscreen-size-y = <800>;
-- 
2.43.0



From dario.binacchi at amarulasolutions.com  Mon Mar 10 05:24:18 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Mon, 10 Mar 2025 13:24:18 +0100
Subject: [PATCH] ARM: dts: stm32: use IRQ_TYPE_EDGE_FALLING on stm32mp157c-dk2
In-Reply-To: <e5a5dd9b-475b-4c66-a580-08f11a80e5a3@foss.st.com>
References: <20250301115116.2862353-1-dario.binacchi@amarulasolutions.com> <e5a5dd9b-475b-4c66-a580-08f11a80e5a3@foss.st.com>
Message-ID: <CABGWkvpM+MbC=W1Z2yVnQiCXznVKXXv6ijn0dw8AGup8Wuyh0Q@mail.gmail.com>

Hi Alexandre,

On Mon, Mar 10, 2025 at 11:50?AM Alexandre TORGUE
<alexandre.torgue at foss.st.com> wrote:
>
> Hi Dario
>
> On 3/1/25 12:51, Dario Binacchi wrote:
> > Replace the number 2 with the appropriate numerical constant defined in
> > dt-bindings/interrupt-controller/irq.h.
> >
> > Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> >
> > ---
> >
> >   arch/arm/boot/dts/st/stm32mp157c-dk2.dts | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> > index 5f9c0160a9c4..dcf17c493022 100644
> > --- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> > +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
> > @@ -11,6 +11,7 @@
> >   #include "stm32mp15-pinctrl.dtsi"
> >   #include "stm32mp15xxac-pinctrl.dtsi"
> >   #include "stm32mp15xx-dkx.dtsi"
> > +#include <dt-bindings/interrupt-controller/irq.h>
>
> really needed ? as it comes also with
> dt-bindings/interrupt-controller/arm-gic.h

yes, you are right:
         stm32mp157c-dk2.dts
         --> stm32mp157.dtsi
               --> stm32mp153.dtsi
                     --> stm32mp151.dtsi
                           #include <dt-bindings/interrupt-controller/arm-gic.h>

I'll submit v2.

Thanks and regards
Dario
>
> >   / {
> >       model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
> > @@ -67,7 +68,7 @@ &i2c1 {
> >       touchscreen at 38 {
> >               compatible = "focaltech,ft6236";
> >               reg = <0x38>;
> > -             interrupts = <2 2>;
> > +             interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
> >               interrupt-parent = <&gpiof>;
> >               touchscreen-size-x = <480>;
> >               touchscreen-size-y = <800>;



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi at amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info at amarulasolutions.com

www.amarulasolutions.com


From maz at kernel.org  Mon Mar 10 05:24:43 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:43 +0000
Subject: [PATCH v2 01/23] arm64: sysreg: Add ID_AA64ISAR1_EL1.LS64 encoding for FEAT_LS64WB
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-2-maz@kernel.org>

The 2024 extensions are adding yet another variant of LS64
(aptly named FEAT_LS64WB) supporting LS64 accesses to write-back
memory, as well as 32 byte single-copy atomic accesses using pairs
of FP registers.

Add the relevant encoding to ID_AA64ISAR1_EL1.LS64.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/tools/sysreg | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 762ee084b37c5..8c4229b34840f 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -1466,6 +1466,7 @@ UnsignedEnum	63:60	LS64
 	0b0001	LS64
 	0b0010	LS64_V
 	0b0011	LS64_ACCDATA
+	0b0100	LS64WB
 EndEnum
 UnsignedEnum	59:56	XS
 	0b0000	NI
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:42 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:42 +0000
Subject: [PATCH v2 00/23] KVM: arm64: Revamp Fine Grained Trap handling
Message-ID: <20250310122505.2857610-1-maz@kernel.org>

Mark recently mentioned that the way we handled FGTs, and particularly
their RES0 behaviour was not entirely future-proof.

The main issue is that RES0 bits are extracted from the sysreg file,
which is independently updated, and that the KVM-specific enablement
is not necessarily done at the same time. This means that a bit that
KVM considered RES0 at some point all of a sudden acquires a meaning,
and that this can trigger unexpected behaviours.

One way of fixing that would be to mandate that everything gets
updated synchronously. While this is something I'd really want to see,
it is unlikely to happen within my lifetime.

So the next best option is to reintroduce KVM's own view of RES0
masks, so that it can continue to ignore a given feature in a safe
manner. But instead of going back to what we have a while back in the
form of hand-crafted masks that are likely to be wrong, this series
makes use of the rather exhaustive description of traps that we know
about, and then some more:

- compile the encoding_to_fgt[] array into individual positive,
  negative, and res0 masks

- use these masks in place of anything that is hardcoded

- fix a few bugs along the way (thanks Mark!)

- perform some validation and let users know that KVM may be missing
  some FGT bit definitions

But it would be foolish to stop here. We also use FGTs to implement
the so called "Fine Grained UNDEF" (FGU) bits, and make sure that
system registers that are not exposed to a guest do UNDEF. This means
evaluating the guest configuration and setting up these FGU bits when
said configuration isn't supported.

This series therefore goes one step further and, for the HFG*TR_EL2,
HDFG*TR_EL2, and HAFGRTR_EL2 registers, define which bit is controlled
by which feature. This is done mechanically, with very minimal human
intervention, by extracting the relevant data from the ARM-released
JSON files.

Oh, and one more thing: we now do the same for HCRX_EL2 and HCR_EL2.
Isn't that great?

With that data, we greatly simplify the dependency between FGUs and
features, as no code needs to be written. We also use the same data to
set the RES0 bits for any register that requires sanitisation (the
VNCR-backed registers, for example).

Overall, and while this is a lot of new LoCs, it is IMO a reduction in
complexity and maintenance burden.

This series is atop of 6.14-rc4, and contains bits and pieces of
FEAT_LS64 support thanks to the newly added HFGITR_EL2.PSBCSYNC bit
sharing an EC with LS64.

* From v1 [1]:

  - Renamed the LS64 EC to OTHER (Mark)

  - Simplified the handling of the OTHER EC by folding the relevant
    checks (Fuad)

  - Added HCRX_EL2 and HCR_EL2 conversion to the config scheme, the
    latter requiring some extra infrastructure

  - Rebased on v6.14-rc4

[1] https://lore.kernel.org/r/20250210184150.2145093-1-maz at kernel.org

Marc Zyngier (22):
  arm64: sysreg: Add ID_AA64ISAR1_EL1.LS64 encoding for FEAT_LS64WB
  arm64: sysreg: Update ID_AA64MMFR4_EL1 description
  arm64: sysreg: Add layout for HCR_EL2
  arm64: Add syndrome information for trapped LD64B/ST64B{,V,V0}
  KVM: arm64: Handle trapping of FEAT_LS64* instructions
  KVM: arm64: Restrict ACCDATA_EL1 undef to FEAT_ST64_ACCDATA being
    disabled
  KVM: arm64: Don't treat HCRX_EL2 as a FGT register
  KVM: arm64: Plug FEAT_GCS handling
  KVM: arm64: Compute FGT masks from KVM's own FGT tables
  KVM: arm64: Add description of FGT bits leading to EC!=0x18
  KVM: arm64: Use computed masks as sanitisers for FGT registers
  KVM: arm64: Propagate FGT masks to the nVHE hypervisor
  KVM: arm64: Use computed FGT masks to setup FGT registers
  KVM: arm64: Remove most hand-crafted masks for FGT registers
  KVM: arm64: Use KVM-specific HCRX_EL2 RES0 mask
  KVM: arm64: Handle PSB CSYNC traps
  KVM: arm64: Switch to table-driven FGU configuration
  KVM: arm64: Validate FGT register descriptions against RES0 masks
  KVM: arm64: Use FGT feature maps to drive RES0 bits
  KVM: arm64: Allow kvm_has_feat() to take variable arguments
  KVM: arm64: Use HCRX_EL2 feature map to drive fixed-value bits
  KVM: arm64: Use HCR_EL2 feature map to drive fixed-value bits

Mark Rutland (1):
  KVM: arm64: Unconditionally configure fine-grain traps

 arch/arm64/include/asm/esr.h            |   9 +-
 arch/arm64/include/asm/kvm_arm.h        | 189 +++--
 arch/arm64/include/asm/kvm_host.h       |  33 +-
 arch/arm64/kvm/Makefile                 |   2 +-
 arch/arm64/kvm/arm.c                    |   8 +
 arch/arm64/kvm/config.c                 | 891 ++++++++++++++++++++++++
 arch/arm64/kvm/emulate-nested.c         | 140 +++-
 arch/arm64/kvm/handle_exit.c            |  72 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 110 +--
 arch/arm64/kvm/hyp/nvhe/switch.c        |   7 +
 arch/arm64/kvm/nested.c                 | 204 +-----
 arch/arm64/kvm/sys_regs.c               |  65 +-
 arch/arm64/tools/sysreg                 |  90 ++-
 13 files changed, 1394 insertions(+), 426 deletions(-)
 create mode 100644 arch/arm64/kvm/config.c

-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:44 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:44 +0000
Subject: [PATCH v2 02/23] arm64: sysreg: Update ID_AA64MMFR4_EL1 description
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-3-maz@kernel.org>

Resync the ID_AA64MMFR4_EL1 with the architectue description.

This results in:

- the new PoPS field
- the new NV2P1 value for the NV_frac field
- the new RMEGDI field
- the new SRMASK field

These fields have been generated from the reference JSON file.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/tools/sysreg | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 8c4229b34840f..3598ddd84942d 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -1944,12 +1944,21 @@ EndEnum
 EndSysreg
 
 Sysreg	ID_AA64MMFR4_EL1	3	0	0	7	4
-Res0	63:40
+Res0	63:48
+UnsignedEnum	47:44	SRMASK
+	0b0000	NI
+	0b0001	IMP
+EndEnum
+Res0	43:40
 UnsignedEnum	39:36	E3DSE
 	0b0000	NI
 	0b0001	IMP
 EndEnum
-Res0	35:28
+Res0	35:32
+UnsignedEnum	31:28	RMEGDI
+	0b0000	NI
+	0b0001	IMP
+EndEnum
 SignedEnum	27:24	E2H0
 	0b0000	IMP
 	0b1110	NI_NV1
@@ -1958,6 +1967,7 @@ EndEnum
 UnsignedEnum	23:20	NV_frac
 	0b0000	NV_NV2
 	0b0001	NV2_ONLY
+	0b0010	NV2P1
 EndEnum
 UnsignedEnum	19:16	FGWTE3
 	0b0000	NI
@@ -1977,7 +1987,10 @@ SignedEnum	7:4	EIESB
 	0b0010	ToELx
 	0b1111	ANY
 EndEnum
-Res0	3:0
+UnsignedEnum	3:0	PoPS
+	0b0000	NI
+	0b0001	IMP
+EndEnum
 EndSysreg
 
 Sysreg	SCTLR_EL1	3	0	1	0	0
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:45 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:45 +0000
Subject: [PATCH v2 03/23] arm64: sysreg: Add layout for HCR_EL2
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-4-maz@kernel.org>

Add HCR_EL2 to the sysreg file, more or less directly generated
from the JSON file.

Since the generated names significantly differ from the existing
naming, express the old names in terms of the new one. One day, we'll
fix this mess, but I'm not in any hurry.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_arm.h | 125 ++++++++++++++++---------------
 arch/arm64/tools/sysreg          |  68 +++++++++++++++++
 2 files changed, 132 insertions(+), 61 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 8d94a6c0ed5c4..52bd4abc2a85d 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -12,67 +12,70 @@
 #include <asm/sysreg.h>
 #include <asm/types.h>
 
-/* Hyp Configuration Register (HCR) bits */
-
-#define HCR_TID5	(UL(1) << 58)
-#define HCR_DCT		(UL(1) << 57)
-#define HCR_ATA_SHIFT	56
-#define HCR_ATA		(UL(1) << HCR_ATA_SHIFT)
-#define HCR_TTLBOS	(UL(1) << 55)
-#define HCR_TTLBIS	(UL(1) << 54)
-#define HCR_ENSCXT	(UL(1) << 53)
-#define HCR_TOCU	(UL(1) << 52)
-#define HCR_AMVOFFEN	(UL(1) << 51)
-#define HCR_TICAB	(UL(1) << 50)
-#define HCR_TID4	(UL(1) << 49)
-#define HCR_FIEN	(UL(1) << 47)
-#define HCR_FWB		(UL(1) << 46)
-#define HCR_NV2		(UL(1) << 45)
-#define HCR_AT		(UL(1) << 44)
-#define HCR_NV1		(UL(1) << 43)
-#define HCR_NV		(UL(1) << 42)
-#define HCR_API		(UL(1) << 41)
-#define HCR_APK		(UL(1) << 40)
-#define HCR_TEA		(UL(1) << 37)
-#define HCR_TERR	(UL(1) << 36)
-#define HCR_TLOR	(UL(1) << 35)
-#define HCR_E2H		(UL(1) << 34)
-#define HCR_ID		(UL(1) << 33)
-#define HCR_CD		(UL(1) << 32)
-#define HCR_RW_SHIFT	31
-#define HCR_RW		(UL(1) << HCR_RW_SHIFT)
-#define HCR_TRVM	(UL(1) << 30)
-#define HCR_HCD		(UL(1) << 29)
-#define HCR_TDZ		(UL(1) << 28)
-#define HCR_TGE		(UL(1) << 27)
-#define HCR_TVM		(UL(1) << 26)
-#define HCR_TTLB	(UL(1) << 25)
-#define HCR_TPU		(UL(1) << 24)
-#define HCR_TPC		(UL(1) << 23) /* HCR_TPCP if FEAT_DPB */
-#define HCR_TSW		(UL(1) << 22)
-#define HCR_TACR	(UL(1) << 21)
-#define HCR_TIDCP	(UL(1) << 20)
-#define HCR_TSC		(UL(1) << 19)
-#define HCR_TID3	(UL(1) << 18)
-#define HCR_TID2	(UL(1) << 17)
-#define HCR_TID1	(UL(1) << 16)
-#define HCR_TID0	(UL(1) << 15)
-#define HCR_TWE		(UL(1) << 14)
-#define HCR_TWI		(UL(1) << 13)
-#define HCR_DC		(UL(1) << 12)
-#define HCR_BSU		(3 << 10)
-#define HCR_BSU_IS	(UL(1) << 10)
-#define HCR_FB		(UL(1) << 9)
-#define HCR_VSE		(UL(1) << 8)
-#define HCR_VI		(UL(1) << 7)
-#define HCR_VF		(UL(1) << 6)
-#define HCR_AMO		(UL(1) << 5)
-#define HCR_IMO		(UL(1) << 4)
-#define HCR_FMO		(UL(1) << 3)
-#define HCR_PTW		(UL(1) << 2)
-#define HCR_SWIO	(UL(1) << 1)
-#define HCR_VM		(UL(1) << 0)
-#define HCR_RES0	((UL(1) << 48) | (UL(1) << 39))
+/*
+ * Because I'm terribly lazy and that repainting the whole of the KVM
+ * code with the proper names is a pain, use a helper to map the names
+ * inherited from AArch32 with the new fancy nomenclature. One day...
+ */
+#define	__HCR(x)	HCR_EL2_##x
+
+#define HCR_TID5	__HCR(TID5)
+#define HCR_DCT		__HCR(DCT)
+#define HCR_ATA_SHIFT	__HCR(ATA_SHIFT)
+#define HCR_ATA		__HCR(ATA)
+#define HCR_TTLBOS	__HCR(TTLBOS)
+#define HCR_TTLBIS	__HCR(TTLBIS)
+#define HCR_ENSCXT	__HCR(EnSCXT)
+#define HCR_TOCU	__HCR(TOCU)
+#define HCR_AMVOFFEN	__HCR(AMVOFFEN)
+#define HCR_TICAB	__HCR(TICAB)
+#define HCR_TID4	__HCR(TID4)
+#define HCR_FIEN	__HCR(FIEN)
+#define HCR_FWB		__HCR(FWB)
+#define HCR_NV2		__HCR(NV2)
+#define HCR_AT		__HCR(AT)
+#define HCR_NV1		__HCR(NV1)
+#define HCR_NV		__HCR(NV)
+#define HCR_API		__HCR(API)
+#define HCR_APK		__HCR(APK)
+#define HCR_TEA		__HCR(TEA)
+#define HCR_TERR	__HCR(TERR)
+#define HCR_TLOR	__HCR(TLOR)
+#define HCR_E2H		__HCR(E2H)
+#define HCR_ID		__HCR(ID)
+#define HCR_CD		__HCR(CD)
+#define HCR_RW		__HCR(RW)
+#define HCR_TRVM	__HCR(TRVM)
+#define HCR_HCD		__HCR(HCD)
+#define HCR_TDZ		__HCR(TDZ)
+#define HCR_TGE		__HCR(TGE)
+#define HCR_TVM		__HCR(TVM)
+#define HCR_TTLB	__HCR(TTLB)
+#define HCR_TPU		__HCR(TPU)
+#define HCR_TPC		__HCR(TPCP)
+#define HCR_TSW		__HCR(TSW)
+#define HCR_TACR	__HCR(TACR)
+#define HCR_TIDCP	__HCR(TIDCP)
+#define HCR_TSC		__HCR(TSC)
+#define HCR_TID3	__HCR(TID3)
+#define HCR_TID2	__HCR(TID2)
+#define HCR_TID1	__HCR(TID1)
+#define HCR_TID0	__HCR(TID0)
+#define HCR_TWE		__HCR(TWE)
+#define HCR_TWI		__HCR(TWI)
+#define HCR_DC		__HCR(DC)
+#define HCR_BSU		__HCR(BSU)
+#define HCR_BSU_IS	__HCR(BSU_IS)
+#define HCR_FB		__HCR(FB)
+#define HCR_VSE		__HCR(VSE)
+#define HCR_VI		__HCR(VI)
+#define HCR_VF		__HCR(VF)
+#define HCR_AMO		__HCR(AMO)
+#define HCR_IMO		__HCR(IMO)
+#define HCR_FMO		__HCR(FMO)
+#define HCR_PTW		__HCR(PTW)
+#define HCR_SWIO	__HCR(SWIO)
+#define HCR_VM		__HCR(VM)
 
 /*
  * The bits we set in HCR:
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 3598ddd84942d..1cf9a07cce522 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -2529,6 +2529,74 @@ Field	1	AFSR1_EL1
 Field	0	AFSR0_EL1
 EndSysregFields
 
+Sysreg	HCR_EL2		3	4	1	1	0
+Field	63:60	TWEDEL
+Field	59	TWEDEn
+Field	58	TID5
+Field	57	DCT
+Field	56	ATA
+Field	55	TTLBOS
+Field	54	TTLBIS
+Field	53	EnSCXT
+Field	52	TOCU
+Field	51	AMVOFFEN
+Field	50	TICAB
+Field	49	TID4
+Field	48	GPF
+Field	47	FIEN
+Field	46	FWB
+Field	45	NV2
+Field	44	AT
+Field	43	NV1
+Field	42	NV
+Field	41	API
+Field	40	APK
+Field	39	TME
+Field	38	MIOCNCE
+Field	37	TEA
+Field	36	TERR
+Field	35	TLOR
+Field	34	E2H
+Field	33	ID
+Field	32	CD
+Field	31	RW
+Field	30	TRVM
+Field	29	HCD
+Field	28	TDZ
+Field	27	TGE
+Field	26	TVM
+Field	25	TTLB
+Field	24	TPU
+Field	23	TPCP
+Field	22	TSW
+Field	21	TACR
+Field	20	TIDCP
+Field	19	TSC
+Field	18	TID3
+Field	17	TID2
+Field	16	TID1
+Field	15	TID0
+Field	14	TWE
+Field	13	TWI
+Field	12	DC
+UnsignedEnum	11:10	BSU
+	0b00	NONE
+	0b01	IS
+	0b10	OS
+	0b11	FS
+EndEnum
+Field	9	FB
+Field	8	VSE
+Field	7	VI
+Field	6	VF
+Field	5	AMO
+Field	4	IMO
+Field	3	FMO
+Field	2	PTW
+Field	1	SWIO
+Field	0	VM
+EndSysreg
+
 Sysreg MDCR_EL2		3	4	1	1	1
 Res0	63:51
 Field	50	EnSTEPOP
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:47 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:47 +0000
Subject: [PATCH v2 05/23] KVM: arm64: Handle trapping of FEAT_LS64* instructions
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-6-maz@kernel.org>

We generally don't expect FEAT_LS64* instructions to trap, unless
they are trapped by a guest hypervisor.

Otherwise, this is just the guest playing tricks on us by using
an instruction that isn't advertised, which we handle with a well
deserved UNDEF.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/handle_exit.c | 56 ++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 512d152233ff2..b2d11cd0447c1 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -294,6 +294,61 @@ static int handle_svc(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+static int handle_other(struct kvm_vcpu *vcpu)
+{
+	bool is_l2 = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
+	u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
+	u64 esr = kvm_vcpu_get_esr(vcpu);
+	u64 iss = ESR_ELx_ISS(esr);
+	struct kvm *kvm = vcpu->kvm;
+	bool allowed, fwd = false;
+
+	/*
+	 * We only trap for two reasons:
+	 *
+	 * - the feature is disabled, and the only outcome is to
+	 *   generate an UNDEF.
+	 *
+	 * - the feature is enabled, but a NV guest wants to trap the
+	 *   feature used my its L2 guest. We forward the exception in
+	 *   this case.
+	 *
+	 * What we don't expect is to end-up here if the guest is
+	 * expected be be able to directly use the feature, hence the
+	 * WARN_ON below.
+	 */
+	switch (iss) {
+	case ESR_ELx_ISS_OTHER_ST64BV:
+		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
+		if (is_l2)
+			fwd = !(hcrx & HCRX_EL2_EnASR);
+		break;
+	case ESR_ELx_ISS_OTHER_ST64BV0:
+		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
+		if (is_l2)
+			fwd = !(hcrx & HCRX_EL2_EnAS0);
+		break;
+	case ESR_ELx_ISS_OTHER_LDST64B:
+		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
+		if (is_l2)
+			fwd = !(hcrx & HCRX_EL2_EnALS);
+		break;
+	default:
+		/* Clearly, we're missing something. */
+		WARN_ON_ONCE(1);
+		allowed = false;
+	}
+
+	WARN_ON_ONCE(allowed && !fwd);
+
+	if (allowed && fwd)
+		kvm_inject_nested_sync(vcpu, esr);
+	else
+		kvm_inject_undefined(vcpu);
+
+	return 1;
+}
+
 static exit_handle_fn arm_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]	= kvm_handle_unknown_ec,
 	[ESR_ELx_EC_WFx]	= kvm_handle_wfx,
@@ -303,6 +358,7 @@ static exit_handle_fn arm_exit_handlers[] = {
 	[ESR_ELx_EC_CP14_LS]	= kvm_handle_cp14_load_store,
 	[ESR_ELx_EC_CP10_ID]	= kvm_handle_cp10_id,
 	[ESR_ELx_EC_CP14_64]	= kvm_handle_cp14_64,
+	[ESR_ELx_EC_OTHER]	= handle_other,
 	[ESR_ELx_EC_HVC32]	= handle_hvc,
 	[ESR_ELx_EC_SMC32]	= handle_smc,
 	[ESR_ELx_EC_HVC64]	= handle_hvc,
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:48 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:48 +0000
Subject: [PATCH v2 06/23] KVM: arm64: Restrict ACCDATA_EL1 undef to FEAT_ST64_ACCDATA being disabled
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-7-maz@kernel.org>

We currently unconditionally make ACCDATA_EL1 accesses UNDEF.

As we are about to support it, restrict the UNDEF behaviour to cases
where FEAT_ST64_ACCDATA is not exposed to the guest.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/sys_regs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 82430c1e1dd02..18721c773475d 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -4997,10 +4997,12 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
 	kvm->arch.fgu[HFGxTR_GROUP] = (HFGxTR_EL2_nAMAIR2_EL1		|
 				       HFGxTR_EL2_nMAIR2_EL1		|
 				       HFGxTR_EL2_nS2POR_EL1		|
-				       HFGxTR_EL2_nACCDATA_EL1		|
 				       HFGxTR_EL2_nSMPRI_EL1_MASK	|
 				       HFGxTR_EL2_nTPIDR2_EL0_MASK);
 
+	if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
+		kvm->arch.fgu[HFGxTR_GROUP] |= HFGxTR_EL2_nACCDATA_EL1;
+
 	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
 		kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_TLBIRVAALE1OS|
 						HFGITR_EL2_TLBIRVALE1OS	|
-- 
2.39.2



From maz at kernel.org  Mon Mar 10 05:24:46 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 10 Mar 2025 12:24:46 +0000
Subject: [PATCH v2 04/23] arm64: Add syndrome information for trapped LD64B/ST64B{,V,V0}
In-Reply-To: <20250310122505.2857610-1-maz@kernel.org>
References: <20250310122505.2857610-1-maz@kernel.org>
Message-ID: <20250310122505.2857610-5-maz@kernel.org>

Provide the architected EC and ISS values for all the FEAT_LS64*
instructions.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/esr.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index d1b1a33f9a8b0..547b4e857a3e2 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -20,7 +20,8 @@
 #define ESR_ELx_EC_FP_ASIMD	UL(0x07)
 #define ESR_ELx_EC_CP10_ID	UL(0x08)	/* EL2 only */
 #define ESR_ELx_EC_PAC		UL(0x09)	/* EL2 and above */
-/* Unallocated EC: 0x0A - 0x0B */
+#define ESR_ELx_EC_OTHER	UL(0x0A)
+/* Unallocated EC: 0x0B */
 #define ESR_ELx_EC_CP14_64	UL(0x0C)
 #define ESR_ELx_EC_BTI		UL(0x0D)
 #define ESR_ELx_EC_ILL		UL(0x0E)
@@ -174,6 +175,11 @@
 #define ESR_ELx_WFx_ISS_WFE	(UL(1) << 0)
 #define ESR_ELx_xVC_IMM_MASK	((UL(1) << 16) - 1)
 
+/* ISS definitions for LD64B/ST64B instructions */
+#define ESR_ELx_ISS_OTHER_ST64BV	(0)
+#define ESR_ELx_ISS_OTHER_ST64BV0	(1)
+#define ESR_ELx_ISS_OTHER_LDST64B	(2)
+
 #define DISR_EL1_IDS		(UL(1) << 24)
 /*
  * DISR_EL1 and ESR_ELx share the bottom 13 bits, but the RES0 bits may mean
-- 
2.39.2



From wiagn233 at outlook.com  Mon Mar 10 05:41:34 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Mon, 10 Mar 2025 20:41:34 +0800
Subject: [PATCH v9 RESEND] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <71ed8398-4619-4793-804d-77cad36e7402@nbd.name>
References: <TYCPR01MB84376C7074C566865654F05098D42@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <b6b52bfcdb614137ac63fddfdaf9cb97@realtek.com>
 <OSZPR01MB843481965BA47B030566DF2698D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>
 <71ed8398-4619-4793-804d-77cad36e7402@nbd.name>
Message-ID: <OSZPR01MB84345D44294ACA75A863ED6B98D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>

Hello,

I modified the patch as you two adviced. If you think it's ok, please
tell me and I'll send a v10 patch.

Modified patch is attached below.

Best regards,
Shengyu

---
  drivers/net/wireless/mediatek/mt76/mt76.h     | 15 ++++++
  .../net/wireless/mediatek/mt76/mt7915/main.c  | 53 +++++++++++++++++--
  .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
  .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
  drivers/net/wireless/mediatek/mt76/util.c     | 37 +++++++++++--
  drivers/net/wireless/mediatek/mt76/util.h     |  2 +-
  6 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b107..bd943b8b20bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -28,6 +28,9 @@
  
  #define MT76_TOKEN_FREE_THR	64
  
+#define MT76_WED_WDS_MIN    256
+#define MT76_WED_WDS_MAX    272
+
  #define MT_QFLAG_WED_RING	GENMASK(1, 0)
  #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
  #define MT_QFLAG_WED		BIT(5)
@@ -73,6 +76,12 @@ enum mt76_wed_type {
  	MT76_WED_RRO_Q_IND,
  };
  
+enum mt76_wed_state {
+	MT76_WED_DEFAULT,
+	MT76_WED_ACTIVE,
+	MT76_WED_WDS_ACTIVE,
+};
+
  struct mt76_bus_ops {
  	u32 (*rr)(struct mt76_dev *dev, u32 offset);
  	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
@@ -1165,6 +1174,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev);
  int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  			  struct net_device *netdev, enum tc_setup_type type,
  			  void *type_data);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+	return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT);
+}
+			
  #ifdef CONFIG_NET_MEDIATEK_SOC_WED
  u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
  int mt76_wed_offload_enable(struct mtk_wed_device *wed);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 3aa31c5cefa6..07c2ce518d97 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
  	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
  	bool ext_phy = mvif->phy != &dev->phy;
  	int idx;
+	u8 flags = MT76_WED_DEFAULT;
  
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76)) {
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+	}
+
+	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
  	if (idx < 0)
  		return -ENOSPC;
  
@@ -1271,6 +1278,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
  {
  	struct mt7915_dev *dev = mt7915_hw_dev(hw);
  	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
+	struct ieee80211_sta *pre_sta;
+	struct mt7915_sta *pre_msta;
+	u8 flags = MT76_WED_DEFAULT;
+	int tmp_idx;
  
  	if (enabled)
  		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
@@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
  	if (!msta->wcid.sta)
  		return;
  
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76) &&
+	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
+		if (pre_sta == NULL)
+			goto error_alloc;
+		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
+
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+
+		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
+		if (tmp_idx < 0)
+			goto error_wcid;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
+
+		tmp_idx = msta->wcid.idx;
+		msta->wcid.idx = pre_msta->wcid.idx;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
+
+		synchronize_rcu();
+		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
+
+error_wcid:
+		kfree(pre_sta);
+	}
+
+error_alloc:
  	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
  }
  
@@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
  	if (!mtk_wed_device_active(wed))
  		return -ENODEV;
  
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
  		return -EIO;
  
  	path->type = DEV_PATH_MTK_WDMA;
  	path->dev = ctx->dev;
  	path->mtk_wdma.wdma_idx = wed->wdma_idx;
  	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
  	path->mtk_wdma.queue = phy != &dev->phy;
+	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
+	    is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = msta->wcid.idx;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
  
  	ctx->dev = NULL;
  
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9d790f234e82..191f966c3f32 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
  
  	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
  
-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-	     is_mt7915(&dev->mt76)) ||
-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+		if (is_mt7915(&dev->mt76) ||
+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+						0, 0, 0);
+		else
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+						MCU_WA_PARAM_WED_VERSION,
+						dev->mt76.mmio.wed.rev_id, 0);
+		if (ret)
+			return ret;
+	}
+#endif
  
  	ret = mt7915_mcu_set_mwds(dev, 1);
  	if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 49476a4182fd..c3dd0cb4a5d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
  	MCU_WA_PARAM_PDMA_RX = 0x04,
  	MCU_WA_PARAM_CPU_UTIL = 0x0b,
  	MCU_WA_PARAM_RED = 0x0e,
+	MCU_WA_PARAM_WED_VERSION = 0x32,
  	MCU_WA_PARAM_RED_SETTING = 0x40,
  };
  
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 95b3dc96e4c4..e80bef2b33a1 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
  }
  EXPORT_SYMBOL_GPL(____mt76_poll_msec);
  
-int mt76_wcid_alloc(u32 *mask, int size)
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
  {
+	int max = MT76_WED_WDS_MAX;
+	int min = MT76_WED_WDS_MIN;
  	int i, idx = 0, cur;
  
  	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
@@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
  
  		idx--;
  		cur = i * 32 + idx;
-		if (cur >= size)
+
+		switch (flag) {
+		case MT76_WED_ACTIVE:
+			if (cur >= min && cur < max)
+				continue;
+
+			if (cur >= size) {
+				u32 end = max - min - 1;
+
+				i = min / 32;
+				idx = ffs(~mask[i] & GENMASK(end, 0));
+				if (!idx)
+					goto error;
+				idx--;
+				cur = min + idx;
+			}
+
  			break;
+		case MT76_WED_WDS_ACTIVE:
+			if (cur < min)
+				continue;
+			if (cur >= max)
+				goto error;
+
+			break;
+		default:
+			if (cur >= size)
+				goto error;
+			break;
+		}
  
  		mask[i] |= BIT(idx);
  		return cur;
  	}
  
+error:
  	return -1;
  }
-EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
  
  int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
  {
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94c..fe95a847182e 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -27,7 +27,7 @@ enum {
  #define MT76_INCR(_var, _size) \
  	(_var = (((_var) + 1) % (_size)))
  
-int mt76_wcid_alloc(u32 *mask, int size);
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
  
  static inline void
  mt76_wcid_mask_set(u32 *mask, int idx)
-- 
2.48.1


-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/57dac100/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/57dac100/attachment.sig>

From robh at kernel.org  Mon Mar 10 05:42:14 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 07:42:14 -0500
Subject: [PATCH v8 07/11] dt-bindings: allwinner: add H616 DE33 mixer
 binding
In-Reply-To: <20250310092345.31708-8-ryan@testtoast.com>
References: <20250310092345.31708-1-ryan@testtoast.com>
 <20250310092345.31708-8-ryan@testtoast.com>
Message-ID: <20250310124214.GA3869453-robh@kernel.org>

On Mon, Mar 10, 2025 at 10:09:53PM +1300, Ryan Walklin wrote:
> The Allwinner H616 and variants have a new display engine revision
> (DE33).
> 
> The mixer configuration registers are significantly different to the DE3
> and DE2 revisions, being split into separate top and display blocks,
> therefore a fallback for the mixer compatible is not provided.
> 
> Add a display engine mixer binding for the DE33.
> 
> Signed-off-by: Ryan Walklin <ryan at testtoast.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>
> Reviewed-by: Chen-Yu Tsai <wens at csie.org>
> 
> ---
> Changelog v2..v3:
> - Separate content into three patches for three separate subsystems
> 
> Changelog v5..v6:
> - increase reg maxItems to 3 and add conditional for h616-de33
> ---
>  .../allwinner,sun8i-a83t-de2-mixer.yaml       | 21 ++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
> index b75c1ec686ad..274f5e632733 100644
> --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
> +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml
> @@ -24,9 +24,11 @@ properties:
>        - allwinner,sun50i-a64-de2-mixer-0
>        - allwinner,sun50i-a64-de2-mixer-1
>        - allwinner,sun50i-h6-de3-mixer-0
> +      - allwinner,sun50i-h616-de33-mixer-0
>  
>    reg:
> -    maxItems: 1
> +    minItems: 1
> +    maxItems: 3

What's in each region?

>  
>    clocks:
>      items:
> @@ -61,6 +63,23 @@ properties:
>      required:
>        - port at 1
>  
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          enum:
> +            - allwinner,sun50i-h616-de33-mixer-0
> +
> +    then:
> +      properties:
> +        reg:
> +          maxItems: 3
> +
> +    else:
> +      properties:
> +        reg:
> +          maxItems: 1
> +
>  required:
>    - compatible
>    - reg
> -- 
> 2.48.1
> 


From peterz at infradead.org  Mon Mar 10 05:44:03 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 10 Mar 2025 13:44:03 +0100
Subject: [PATCH v3 2/5] perf: Allow periodic events to alternate between
 two sample periods
In-Reply-To: <20250307202247.648633-3-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-3-mark.barnett@arm.com>
Message-ID: <20250310124403.GQ5880@noisy.programming.kicks-ass.net>

On Fri, Mar 07, 2025 at 08:22:44PM +0000, mark.barnett at arm.com wrote:
> From: Ben Gainey <ben.gainey at arm.com>
> 
> This change modifies perf_event_attr to add a second, alternative
> sample period field, and modifies the core perf overflow handling
> such that when specified an event will alternate between two sample
> periods.
> 
> Currently, perf does not provide a  mechanism for decoupling the period
> over which counters are counted from the period between samples. This is
> problematic for building a tool to measure per-function metrics derived
> from a sampled counter group. Ideally such a tool wants a very small
> sample window in order to correctly attribute the metrics to a given
> function, but prefers a larger sample period that provides representative
> coverage without excessive probe effect, triggering throttling, or
> generating excessive amounts of data.
> 
> By alternating between a long and short sample_period and subsequently
> discarding the long samples, tools may decouple the period between
> samples that the tool cares about from the window of time over which
> interesting counts are collected.
> 
> It is expected that typically tools would use this feature with the
> cycles or instructions events as an approximation for time, but no
> restrictions are applied to which events this can be applied to.

So you do add the constraint that 'alt_sample_period < sample_period'
but there is no natural reason for this to be so.

Additionally, this way the total period ends up being 'sample_period +
alt_sample_period'.

Would not a more natural way to express things be:

	p1 = sample_period - alt_sample_period;
	p2 = alt_sample_period;

This way you retain the total period to be 'sample_period' and naturally
get the constraint: 'alt_sample_period < sample_period'.

That is; I'm somewhat confused by the state of things; it doesn't seem
consistent.

(Also note that this alternative form might actually work in combination
with attr.freq set -- although that has a number of 'fun' details I'm
sure).

> Signed-off-by: Ben Gainey <ben.gainey at arm.com>
> Signed-off-by: Mark Barnett <mark.barnett at arm.com>
> ---
>  include/linux/perf_event.h      |  5 +++++
>  include/uapi/linux/perf_event.h |  3 +++
>  kernel/events/core.c            | 39 ++++++++++++++++++++++++++++++++-
>  3 files changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 8333f132f4a9..99ba72c8fb6d 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -276,6 +276,11 @@ struct hw_perf_event {
>  	 */
>  	u64				freq_time_stamp;
>  	u64				freq_count_stamp;
> +
> +	/*
> +	 * Indicates that the alternative sample period is used
> +	 */
> +	bool				using_alt_sample_period;

There's a 4 byte hole in this structure if you look; also please use a
flag, sizeof(_Bool) is ABI dependent.

>  #endif
>  };
>  
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 0524d541d4e3..499a8673df8e 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -379,6 +379,7 @@ enum perf_event_read_format {
>  #define PERF_ATTR_SIZE_VER6	120	/* add: aux_sample_size */
>  #define PERF_ATTR_SIZE_VER7	128	/* add: sig_data */
>  #define PERF_ATTR_SIZE_VER8	136	/* add: config3 */
> +#define PERF_ATTR_SIZE_VER9	144	/* add: alt_sample_period */
>  
>  /*
>   * Hardware event_id to monitor via a performance monitoring event:
> @@ -531,6 +532,8 @@ struct perf_event_attr {
>  	__u64	sig_data;
>  
>  	__u64	config3; /* extension of config2 */
> +
> +	__u64	alt_sample_period;
>  };
>  
>  /*
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index bcb09e011e9e..7ec8ec6ba7ef 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -4178,6 +4178,8 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bo
>  	s64 period, sample_period;
>  	s64 delta;
>  
> +	WARN_ON_ONCE(hwc->using_alt_sample_period);

Groan; so that bit keeps flipping in and off, and statistically we'll
warn, but urgh.

>  	period = perf_calculate_period(event, nsec, count);
>  
>  	delta = (s64)(period - hwc->sample_period);
> @@ -9894,6 +9896,7 @@ static int __perf_event_overflow(struct perf_event *event,
>  				 int throttle, struct perf_sample_data *data,
>  				 struct pt_regs *regs)
>  {
> +	struct hw_perf_event *hwc = &event->hw;
>  	int events = atomic_read(&event->event_limit);
>  	int ret = 0;
>  
> @@ -9913,6 +9916,18 @@ static int __perf_event_overflow(struct perf_event *event,
>  	    !bpf_overflow_handler(event, data, regs))
>  		goto out;
>  
> +	/*
> +	 * Swap the sample period to the alternative period
> +	 */
> +	if (event->attr.alt_sample_period) {
> +		bool using_alt = hwc->using_alt_sample_period;
> +		u64 sample_period = (using_alt ? event->attr.sample_period
> +					       : event->attr.alt_sample_period);
> +
> +		hwc->sample_period = sample_period;
> +		hwc->using_alt_sample_period = !using_alt;
> +	}
> +
>  	/*
>  	 * XXX event_limit might not quite work as expected on inherited
>  	 * events
> @@ -12335,9 +12350,19 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
>  	if (attr->freq && attr->sample_freq)
>  		hwc->sample_period = 1;
>  	hwc->last_period = hwc->sample_period;
> -
>  	local64_set(&hwc->period_left, hwc->sample_period);
>  
> +	/*
> +	 * alt_sample_period cannot be used with freq
> +	 */
> +	if (attr->freq && attr->alt_sample_period)
> +		goto err_ns;

How can this happen? This case has already been filtered in
perf_event_open() below, no?

Also, this doesn't apply to tip/perf/core, someone went and changed
things...

> +
> +	if (attr->alt_sample_period) {
> +		hwc->sample_period = attr->alt_sample_period;
> +		hwc->using_alt_sample_period = true;
> +	}
> +
>  	/*
>  	 * We do not support PERF_SAMPLE_READ on inherited events unless
>  	 * PERF_SAMPLE_TID is also selected, which allows inherited events to
> @@ -12807,9 +12832,21 @@ SYSCALL_DEFINE5(perf_event_open,
>  	if (attr.freq) {
>  		if (attr.sample_freq > sysctl_perf_event_sample_rate)
>  			return -EINVAL;
> +		if (attr.alt_sample_period)
> +			return -EINVAL;
>  	} else {
>  		if (attr.sample_period & (1ULL << 63))
>  			return -EINVAL;
> +		if (attr.alt_sample_period) {
> +			if (!attr.sample_period)
> +				return -EINVAL;
> +			if (attr.alt_sample_period & (1ULL << 63))
> +				return -EINVAL;
> +			if (attr.alt_sample_period > attr.sample_period)
> +				return -EINVAL;
> +			if (attr.alt_sample_period == attr.sample_period)
> +				attr.alt_sample_period = 0;
> +		}
>  	}
>  
>  	/* Only privileged users can get physical addresses */
> -- 
> 2.43.0
> 


From michal.kubiak at intel.com  Mon Mar 10 05:45:35 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Mon, 10 Mar 2025 13:45:35 +0100
Subject: [PATCH net] net: ethernet: mediatek: Fix bit field in
 mtk_set_queue_speed()
In-Reply-To: <eaab1b7b-b33b-458b-a89a-81391bd2e6e8@stanley.mountain>
References: <eaab1b7b-b33b-458b-a89a-81391bd2e6e8@stanley.mountain>
Message-ID: <Z87e75UV0Qc4oY64@localhost.localdomain>

On Mon, Mar 10, 2025 at 01:48:27PM +0300, Dan Carpenter wrote:
> This was supposed to set "FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1)"
> but there was typo and the | operation was missing and which turned
> it into a no-op.
> 
> Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
> From static analysis, not tested.
> 
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 922330b3f4d7..9efef0e860da 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -757,7 +757,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
>  		case SPEED_100:
>  			val |= MTK_QTX_SCH_MAX_RATE_EN |
>  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
> -			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
> +			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
>  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
>  			break;
>  		case SPEED_1000:


There's a similar bug a few lines above (line #737):

	case SPEED_100:
		val |= MTK_QTX_SCH_MAX_RATE_EN |
		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
		break;

I think it would be reasonable to fix that too in the same patch.

Thanks,
Michal

> -- 
> 2.47.2
> 
> 


From peterz at infradead.org  Mon Mar 10 05:47:35 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 10 Mar 2025 13:47:35 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250307202247.648633-4-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
Message-ID: <20250310124735.GR5880@noisy.programming.kicks-ass.net>

On Fri, Mar 07, 2025 at 08:22:45PM +0000, mark.barnett at arm.com wrote:
> @@ -9922,7 +9923,10 @@ static int __perf_event_overflow(struct perf_event *event,
>  	if (event->attr.alt_sample_period) {
>  		bool using_alt = hwc->using_alt_sample_period;
>  		u64 sample_period = (using_alt ? event->attr.sample_period
> -					       : event->attr.alt_sample_period);
> +					       : event->attr.alt_sample_period)
> +				  + (event->attr.jitter_alt_period
> +					? get_random_u32_below(2 << event->attr.jitter_alt_period)
> +					: 0);

So, ... this here is NMI context, right? Have you looked at the guts of
get_random_u32_below() ?

I would strongly suggest you go do so.

>  
>  		hwc->sample_period = sample_period;
>  		hwc->using_alt_sample_period = !using_alt;


From linux.amoon at gmail.com  Mon Mar 10 07:34:44 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Mon, 10 Mar 2025 20:04:44 +0530
Subject: [PATCH v4 3/4] drivers/thermal/exymos: Fixed the efuse min max value for exynos5422
In-Reply-To: <20250310143450.8276-1-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
Message-ID: <20250310143450.8276-4-linux.amoon@gmail.com>

As per Exynos5422 user manual e-Fuse range min~max range is 16~76.
if e-Fuse value is out of this range, then thermal sensor may not
sense thermal data properly. Refactors the efuse value
initialization logic within exynos_map_dt_data function by
replacing the nested if-else statements with a switch statement.
Ensures proper initialization of efuse values based on the SOC type.

Signed-off-by: Anand Moon <linux.amoon at gmail.com>
---
 drivers/thermal/samsung/exynos_tmu.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index ac3b9d2c900ca..a71cde0a4b17e 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -899,12 +899,23 @@ static int exynos_map_dt_data(struct platform_device *pdev)
 		data->gain = 8;
 		data->reference_voltage = 16;
 		data->efuse_value = 55;
-		if (data->soc != SOC_ARCH_EXYNOS5420 &&
-		    data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
+		data->max_efuse_value = 100;
+		switch (data->soc) {
+		case SOC_ARCH_EXYNOS3250:
+		case SOC_ARCH_EXYNOS4412:
+		case SOC_ARCH_EXYNOS5250:
+		case SOC_ARCH_EXYNOS5260:
 			data->min_efuse_value = 40;
-		else
+			break;
+		case SOC_ARCH_EXYNOS5420:
+		case SOC_ARCH_EXYNOS5420_TRIMINFO:
+			data->min_efuse_value = 16;
+			data->max_efuse_value = 76;
+			break;
+		default:
 			data->min_efuse_value = 0;
-		data->max_efuse_value = 100;
+			break;
+		}
 		break;
 	case SOC_ARCH_EXYNOS5433:
 		data->tmu_set_low_temp = exynos5433_tmu_set_low_temp;
-- 
2.48.1



From linux.amoon at gmail.com  Mon Mar 10 07:34:45 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Mon, 10 Mar 2025 20:04:45 +0530
Subject: [PATCH v4 4/4] drivers/thermal/exymos: Use guard notation when acquiring mutex
In-Reply-To: <20250310143450.8276-1-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
Message-ID: <20250310143450.8276-5-linux.amoon@gmail.com>

Using guard notation makes the code more compact and error handling
more robust by ensuring that mutexes are released in all code paths
when control leaves critical section.

Signed-off-by: Anand Moon <linux.amoon at gmail.com>
---
v4: used DEFINE_GUARD macro to guard exynos_tmu_data structure.
    However, incorporating guard(exynos_tmu_data)(data); results
    in a recursive deadlock with the mutex during initialization, as this
    data structure is common to all the code configurations of Exynos TMU
v3: New patch
---
 drivers/thermal/samsung/exynos_tmu.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index a71cde0a4b17e..85f88c5e0f11c 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/cleanup.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -199,6 +200,9 @@ struct exynos_tmu_data {
 	void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
 };
 
+DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *,
+	     mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
+
 /*
  * TMU treats temperature as a mapped temperature code.
  * The temperature is converted differently depending on the calibration type.
@@ -256,7 +260,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 	unsigned int status;
 	int ret = 0;
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 	clk_enable(data->clk_sec);
 
@@ -270,7 +274,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 
 	clk_disable(data->clk_sec);
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 
 	return ret;
 }
@@ -292,13 +295,12 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
 		return ret;
 	}
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 
 	data->tmu_set_crit_temp(data, temp / MCELSIUS);
 
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 
 	return 0;
 }
@@ -325,12 +327,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
 {
 	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 	data->tmu_control(pdev, on);
 	data->enabled = on;
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 }
 
 static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
@@ -645,7 +646,7 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
 		 */
 		return -EAGAIN;
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 
 	value = data->tmu_read(data);
@@ -655,7 +656,6 @@ static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
 		*temp = code_to_temp(data, value) * MCELSIUS;
 
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 
 	return ret;
 }
@@ -720,11 +720,10 @@ static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
 	if (temp && temp < MCELSIUS)
 		goto out;
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 	data->tmu_set_emulation(data, temp);
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 	return 0;
 out:
 	return ret;
@@ -760,14 +759,13 @@ static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id)
 
 	thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 
 	/* TODO: take action based on particular interrupt */
 	data->tmu_clear_irqs(data);
 
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 
 	return IRQ_HANDLED;
 }
@@ -987,7 +985,7 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
 	struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
 
-	mutex_lock(&data->lock);
+	guard(mutex)(&data->lock);
 	clk_enable(data->clk);
 
 	if (low > INT_MIN)
@@ -1000,7 +998,6 @@ static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
 		data->tmu_disable_high(data);
 
 	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
 
 	return 0;
 }
-- 
2.48.1



From robh at kernel.org  Mon Mar 10 07:36:20 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 10 Mar 2025 09:36:20 -0500
Subject: [PATCH 00/13] airoha: en7581: clk cleanup + USB support
In-Reply-To: <20250309132959.19045-1-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
Message-ID: <174161712595.4185316.12073621496624773779.robh@kernel.org>


On Sun, 09 Mar 2025 14:29:31 +0100, Christian Marangi wrote:
> This series implement all the changes required to correctly handle
> USB support for the Airoha EN7581 SoC.
> 
> The first few patch are cleanup for the clock driver and the
> introduction of the SCU SSR SoC driver.
> 
> The SoC always support USB 2.0 but for USB 3.0 it needs additional
> configuration for the Serdes port. Such port can be either configured
> for USB usage or for PCIe lines or HSGMII and these are configured
> in the SCU space.
> 
> To correctly handle this, the SCU is changed to a simple-mfd
> implemenetation and the clock controller updated to follow this new
> node structure. Both implementation are supported to handle old
> binding.
> 
> The xHCI USB is based on the Mediatek implementation but the PHY
> handling although conceptually similar, is indded different compared
> to Mediatek due to SSR checks and different port power up.
> 
> The SSR driver expose an API to poll the current status of the Serdes
> port and the USB PHY driver validates it. Refer to the specific commit
> for additional info.
> 
> Consider that there is currently an inconsistency as AN7581 and
> EN7581 refer to the same thing. This is due to the fact that
> the SoC born under EcoNet but then was acquired by Airoha.
> 
> Christian Marangi (13):
>   clk: en7523: convert driver to regmap API
>   clk: en7523: generalize register clocks function
>   dt-bindings: soc: airoha: add SCU SSR Serdes port binding
>   dt-bindings: soc: airoha: add Documentation for Airoha AN7581 SCU SSR
>   dt-bindings: mfd: add Documentation for Airoha EN7581 SCU
>   dt-bindings: clock: airoha: make reg optional for Airoha EN7581
>   clk: en7523: support getting regmap from parent node for EN7581
>   soc: airoha: add support for configuring SCU SSR Serdes port
>   dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
>   phy: airoha: Add support for Airoha AN7581 USB PHY
>   usb: host: add ARCH_AIROHA in XHCI MTK dependency
>   arm64: dts: airoha: en7581: convert SCU clock node to MFD
>     implementation
>   arm64: dts: airoha: en7581: add USB and SCU SSR nodes
> 
>  .../bindings/clock/airoha,en7523-scu.yaml     |  13 +-
>  .../mfd/airoha,en7581-scu-sysctl.yaml         |  68 +++
>  .../bindings/phy/airoha,an7581-usb-phy.yaml   | 106 ++++
>  .../soc/airoha/airoha,an7581-scu-ssr.yaml     | 106 ++++
>  MAINTAINERS                                   |  15 +
>  arch/arm64/boot/dts/airoha/en7581.dtsi        |  74 ++-
>  drivers/clk/clk-en7523.c                      | 258 ++++----
>  drivers/phy/Kconfig                           |   1 +
>  drivers/phy/Makefile                          |   3 +-
>  drivers/phy/airoha/Kconfig                    |  13 +
>  drivers/phy/airoha/Makefile                   |   3 +
>  drivers/phy/airoha/phy-airoha-usb.c           | 554 ++++++++++++++++++
>  drivers/soc/Kconfig                           |   1 +
>  drivers/soc/Makefile                          |   1 +
>  drivers/soc/airoha/Kconfig                    |  18 +
>  drivers/soc/airoha/Makefile                   |   3 +
>  drivers/soc/airoha/airoha-scu-ssr.c           | 195 ++++++
>  drivers/usb/host/Kconfig                      |   2 +-
>  include/dt-bindings/soc/airoha,scu-ssr.h      |  24 +
>  include/linux/soc/airoha/airoha-scu-ssr.h     |  17 +
>  include/linux/soc/soc/airoha-scu-ssr.h        |  17 +
>  21 files changed, 1355 insertions(+), 137 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
>  create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
>  create mode 100644 Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
>  create mode 100644 drivers/phy/airoha/Kconfig
>  create mode 100644 drivers/phy/airoha/Makefile
>  create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
>  create mode 100644 drivers/soc/airoha/Kconfig
>  create mode 100644 drivers/soc/airoha/Makefile
>  create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
>  create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
>  create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h
>  create mode 100644 include/linux/soc/soc/airoha-scu-ssr.h
> 
> --
> 2.48.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/airoha/' for 20250309132959.19045-1-ansuelsmth at gmail.com:

arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fab0000: compatible:0: 'mediatek,mtk-xhci' is not one of ['mediatek,mt2701-xhci', 'mediatek,mt2712-xhci', 'mediatek,mt7622-xhci', 'mediatek,mt7623-xhci', 'mediatek,mt7629-xhci', 'mediatek,mt7986-xhci', 'mediatek,mt7988-xhci', 'mediatek,mt8173-xhci', 'mediatek,mt8183-xhci', 'mediatek,mt8186-xhci', 'mediatek,mt8188-xhci', 'mediatek,mt8192-xhci', 'mediatek,mt8195-xhci', 'mediatek,mt8365-xhci']
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fab0000: compatible: ['mediatek,mtk-xhci'] is too short
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fad0000: compatible:0: 'mediatek,mtk-xhci' is not one of ['mediatek,mt2701-xhci', 'mediatek,mt2712-xhci', 'mediatek,mt7622-xhci', 'mediatek,mt7623-xhci', 'mediatek,mt7629-xhci', 'mediatek,mt7986-xhci', 'mediatek,mt7988-xhci', 'mediatek,mt8173-xhci', 'mediatek,mt8183-xhci', 'mediatek,mt8186-xhci', 'mediatek,mt8188-xhci', 'mediatek,mt8192-xhci', 'mediatek,mt8195-xhci', 'mediatek,mt8365-xhci']
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fad0000: compatible: ['mediatek,mtk-xhci'] is too short
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#







From antonin.godard at bootlin.com  Mon Mar 10 08:56:08 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 16:56:08 +0100
Subject: [PATCH v3 2/3] ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM
 support
In-Reply-To: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v3-2-551e60713523@bootlin.com>

Add support for the Variscite VAR_SOM-MX6UL SoM with:

- NXP i.MX6 UltraLite SoC
- 128?1024 MB DDR3L
- 8?128 GB eMMC
- 128?512 MB SLC NAND
- Camera Interface
- LVDS / Parallel RGB interfaces (not configured)
- Touch controller (not configured)
- Ethernet RMII interface (not configured)
- On-SoM Wi-Fi/Bluetooth with CYW43353 on SDIO Module (not configured)
- SD/MMC/SDIO interface
- USB Host + USB OTG interface
- I2C interfaces
- SPI interfaces
- PCI-Express 2.0 interface
- on-SoM Audio Codec (not configured)
- S/PDIF interface (not configured)

Product website: https://www.variscite.com/product/system-on-module-som/cortex-a7/var-som-6ul-nxp-imx6ul-6ull-6ulz

Support is handled with a SoM-centric dtsi exporting the default
interfaces along the default pinmuxing to be enabled by the board dts
file.

I tested this on a VAR-SOM-6UL_G2_700C_512R_8N_IT_REV1.3A, which is why
some of the features above are mentioned as "not configured" (I couldn't
test them).

This file is based on the one provided by Variscite on their own kernel,
but adapted for mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi | 233 ++++++++++++++++++++++++++
 1 file changed, 233 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..4e536e0252def06a7660c29b7231169e3aa38dba
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite VAR-SOM-MX6UL Module
+ *
+ * Copyright 2019 Variscite Ltd.
+ * Copyright 2025 Bootlin
+ */
+
+/dts-v1/;
+
+#include "imx6ul.dtsi"
+#include <dt-bindings/clock/imx6ul-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Variscite VAR-SOM-MX6UL module";
+	compatible = "variscite,var-som-imx6ul", "fsl,imx6ul";
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	reg_gpio_dvfs: reg-gpio-dvfs {
+		compatible = "regulator-gpio";
+		regulator-min-microvolt = <1300000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-name = "gpio_dvfs";
+		regulator-type = "voltage";
+		gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+		states = <1300000 0x1
+			  1400000 0x0>;
+	};
+
+	rmii_ref_clk: rmii-ref-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+		clock-output-names = "rmii-ref";
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+	dc-supply = <&reg_gpio_dvfs>;
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>, <&pinctrl_enet1_gpio>, <&pinctrl_enet1_mdio>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <1>;
+			clocks = <&rmii_ref_clk>;
+			clock-names = "rmii-ref";
+			reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <100000>;
+			micrel,led-mode = <1>;
+			micrel,rmii-reference-clock-select-25-mhz = <1>;
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+		>;
+	};
+
+	pinctrl_enet1_gpio: enet1-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x1b0b0 /* fec1 reset */
+		>;
+	};
+
+	pinctrl_enet1_mdio: enet1-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO06__ENET1_MDIO	0x1b0b0
+			MX6UL_PAD_GPIO1_IO07__ENET1_MDC		0x1b0b0
+		>;
+	};
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x1b0b0	/* BT Enable */
+			MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06	0x03029	/* WLAN Enable */
+		>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
+			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
+			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
+			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
+			MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
+		>;
+	};
+
+	pinctrl_tsc: tscgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__GPIO1_IO01	0xb0
+			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0xb0
+			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0xb0
+			MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0xb0
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
+			MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS	0x1b0b1
+			MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x10069
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x17059
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x17059
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x17059
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x17059
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x17059
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x17059
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x17059
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x17059
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x17059
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x100b9
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x170b9
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x170b9
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x170b9
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x170b9
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x170b9
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x170b9
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x170b9
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x170b9
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x100f9
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x170f9
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x170f9
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x170f9
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x170f9
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x170f9
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x170f9
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x170f9
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x170f9
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x170f9
+		>;
+	};
+};
+
+&pxp {
+	status = "okay";
+};
+
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+			  <&clks IMX6UL_CLK_SAI2>;
+	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>, <12288000>;
+	fsl,sai-mclk-direction-output;
+	status = "okay";
+};
+
+&snvs_poweroff {
+	status = "okay";
+};
+
+&tsc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_tsc>;
+	xnur-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+	measure-delay-time = <0xffff>;
+	pre-charge-time = <0xfff>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+	bus-width = <8>;
+	no-1-8-v;
+	non-removable;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};

-- 
2.47.0



From antonin.godard at bootlin.com  Mon Mar 10 08:56:06 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 16:56:06 +0100
Subject: [PATCH v3 0/3] Add Variscite i.MX6UL SoM and Concerto board
 support
Message-ID: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>

Add support for the i.MX6UL Variscite SoM (VAR-SOM-6UL) and the
Variscite Concerto Carrier Board.

I tested this with a VAR-SOM-6UL_G2_700C_512R_8N_IT_REV1.3A (one variant
of this SoM), meaning I couldn't test all of the possible options of the
SoM - so this device tree includes partial support for it.

These are based on the 5.15 Variscite kernel fork but adapted for
mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
Changes in v3:
- Reviews from Shawn:
  - Fix alphabetical order of nodes and pinctrl entries.
  - Fix rmii-ref-clk label (remove "-grp" added by mistake).
  - Fix order of properties for eth nodes.
  - Convert deprecated fec properties to eth properties.
- Link to v2: https://lore.kernel.org/r/20250127-varsom6ul-concerto-dts-v2-0-4dac29256989 at bootlin.com

Changes in v2:
- Reviews from Krzysztof:
  - Use imperative mood in commit descriptions.
  - Remove backlight node as I am unable to test it.
  - Rename gpled2 node to led-0, and set function, color and label for
    it.
  - Remove unnecessary comment "DS1337 RTC module".
- Rename binding "variscite,mx6concerto" to "variscite,mx6ulconcerto"
  since this is for the VAR-SOM-6UL mounted on the Concerto.
- Remove pinctrl_ft5x06_ts_gpio iomuxc node, unused.
- Link to v1: https://lore.kernel.org/r/20250121-varsom6ul-concerto-dts-v1-0-eb349acf0ac6 at bootlin.com

---
Antonin Godard (3):
      dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and Concerto board
      ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM support
      ARM: dts: imx6ul: Add Variscite Concerto board support

 Documentation/devicetree/bindings/arm/fsl.yaml     |   6 +
 arch/arm/boot/dts/nxp/imx/Makefile                 |   1 +
 .../boot/dts/nxp/imx/imx6ul-var-som-concerto.dts   | 320 +++++++++++++++++++++
 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi      | 233 +++++++++++++++
 4 files changed, 560 insertions(+)
---
base-commit: 66683f3b2661643f694607283ee8f01b7a934c83
change-id: 20250120-varsom6ul-concerto-dts-a08be2a6219b

Best regards,
-- 
Antonin Godard <antonin.godard at bootlin.com>



From antonin.godard at bootlin.com  Mon Mar 10 08:56:09 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 16:56:09 +0100
Subject: [PATCH v3 3/3] ARM: dts: imx6ul: Add Variscite Concerto board
 support
In-Reply-To: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v3-3-551e60713523@bootlin.com>

Add support for the Variscite Concerto Carrier Board with:

- LVDS interface for the VLCD-CAP-GLD-LVDS 7" LCD 800 x 480 touch
  display (not configured)
- USB Host + USB OTG Connector
- 10/100 Mbps Ethernet
- miniPCI-Express slot
- SD Card connector
- Audio Headphone/Line In jack connectors
- S-ATA
- On-board DMIC

Product Page: https://www.variscite.com/product/single-board-computers/concerto-board

This file is based on the one provided by Variscite on their own kernel,
but adapted for mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 arch/arm/boot/dts/nxp/imx/Makefile                 |   1 +
 .../boot/dts/nxp/imx/imx6ul-var-som-concerto.dts   | 320 +++++++++++++++++++++
 2 files changed, 321 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 39a153536d2a2b8f75b5fbe4332660f89442064a..94c9bc94cc8e2daa1fb3b5686b0b58db1f6678b6 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -329,6 +329,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
 	imx6ul-tx6ul-0010.dtb \
 	imx6ul-tx6ul-0011.dtb \
 	imx6ul-tx6ul-mainboard.dtb \
+	imx6ul-var-som-concerto.dtb \
 	imx6ull-14x14-evk.dtb \
 	imx6ull-colibri-aster.dtb \
 	imx6ull-colibri-emmc-aster.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts
new file mode 100644
index 0000000000000000000000000000000000000000..9ff3b374a2b31ceb7c4974adf86c2f036c78d4d5
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite MX6 Concerto Carrier board with the VAR-SOM-MX6UL
+ * Variscite SoM mounted on it
+ *
+ * Copyright 2019 Variscite Ltd.
+ * Copyright 2025 Bootlin
+ */
+
+#include "imx6ul-var-som.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "Variscite VAR-SOM-MX6UL Concerto Board";
+	compatible = "variscite,mx6ulconcerto", "variscite,var-som-imx6ul", "fsl,imx6ul";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_key_back>, <&pinctrl_gpio_key_wakeup>;
+
+		key-back {
+			gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		key-wakeup {
+			gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WAKEUP>;
+			wakeup-source;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led-0 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "gpled2";
+			gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&fec1 {
+	status = "disabled";
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2>, <&pinctrl_enet2_gpio>, <&pinctrl_enet2_mdio>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy at 3 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <3>;
+			clocks = <&rmii_ref_clk>;
+			clock-names = "rmii-ref";
+			reset-gpios = <&gpio5 5 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <100000>;
+			micrel,led-mode = <0>;
+			micrel,rmii-reference-clock-select-25-mhz = <1>;
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	rtc at 68 {
+		/*
+		 * To actually use this interrupt
+		 * connect pins J14.8 & J14.10 on the Concerto-Board.
+		 */
+		compatible = "dallas,ds1337";
+		reg = <0x68>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_rtc>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+&iomuxc {
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
+		>;
+	};
+
+	pinctrl_enet2_gpio: enet2-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05	0x1b0b0 /* fec2 reset */
+		>;
+	};
+
+	pinctrl_enet2_mdio: enet2-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
+			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
+			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
+		>;
+	};
+
+	pinctrl_gpio_key_back: gpio-key-backgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_CE1_B__GPIO4_IO14	0x17059
+		>;
+	};
+
+	pinctrl_gpio_leds: gpio-ledsgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25	0x1b0b0	/* GPLED2 */
+		>;
+	};
+
+	pinctrl_gpio_key_wakeup: gpio-keys-wakeupgrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x17059
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_PIXCLK__I2C1_SCL		0x4001b8b0
+			MX6UL_PAD_CSI_MCLK__I2C1_SDA		0x4001b8b0
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO05__PWM4_OUT		0x110b0
+		>;
+	};
+
+	pinctrl_rtc: rtcgrp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_MOD__GPIO1_IO10		0x1b0b0 /* RTC alarm IRQ */
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA00__UART5_DCE_TX	0x1b0b1
+			MX6UL_PAD_CSI_DATA01__UART5_DCE_RX	0x1b0b1
+			MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS	0x1b0b1
+			MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_usb_otg1_id: usbotg1idgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_TX_DATA__ANATOP_OTG1_ID	0x17059
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x17059
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x17059
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x17059
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x17059
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x17059
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x17059
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x170b9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x100b9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x170b9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x170b9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x170b9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x170f9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x100f9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x170f9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x170f9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x170f9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x170f9
+		>;
+	};
+
+	pinctrl_usdhc1_gpio: usdhc1-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO00__GPIO1_IO00	0x1b0b1 /* CD */
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__WDOG1_WDOG_B	0x78b0
+		>;
+	};
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&snvs_pwrkey {
+	status = "disabled";
+};
+
+&snvs_rtc {
+	status = "disabled";
+};
+
+&tsc {
+	/*
+	 * Conflics with wdog1 ext-reset-output & SD CD pins,
+	 * so we keep it disabled by default.
+	 */
+	status = "disabled";
+};
+
+/* Console UART */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+/* ttymxc4 UART */
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb_otg1_id>;
+	dr_mode = "otg";
+	disable-over-current;
+	srp-disable;
+	hnp-disable;
+	adp-disable;
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_gpio>;
+	cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	/*
+	 * To actually use ext-reset-output
+	 * connect pins J17.3 & J17.8 on the Concerto-Board
+	 */
+	fsl,ext-reset-output;
+};

-- 
2.47.0



From jernej.skrabec at gmail.com  Mon Mar 10 09:05:45 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Mon, 10 Mar 2025 17:05:45 +0100
Subject: [PATCH net-next 9/9] net: stmmac: sunxi: remove of_get_phy_mode()
In-Reply-To: <E1trbyF-005qYl-Lu@rmk-PC.armlinux.org.uk>
References: <Z87WVk0NzMUyaxDj@shell.armlinux.org.uk>
 <E1trbyF-005qYl-Lu@rmk-PC.armlinux.org.uk>
Message-ID: <2774218.mvXUDI8C0e@jernej-laptop>

Dne ponedeljek, 10. marec 2025 ob 13:10:59 Srednjeevropski standardni ?as je Russell King (Oracle) napisal(a):
> devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
> which is stored in plat_dat->phy_interface. Therefore, we don't need to
> get it in platform code.
> 
> Set gmac->interface from plat_dat->phy_interface.
> 
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From krzk at kernel.org  Mon Mar 10 09:08:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 17:08:24 +0100
Subject: [PATCH 4/4] ARM: dts: stm32: add initial support for
 stm32mp157-ultra-fly-sbc board
In-Reply-To: <20250310154804.326943-5-goran.radni@gmail.com>
References: <20250310154804.326943-1-goran.radni@gmail.com>
 <20250310154804.326943-5-goran.radni@gmail.com>
Message-ID: <6af3a9fe-0c0b-497d-b143-77edc12f0c1e@kernel.org>

On 10/03/2025 16:48, Goran Ra?enovi? wrote:
> +&gpioj {
> +	gpio-line-names =
> +	"", "", "", "", "", "", "", "",
> +	"", "", "", "", "", "", "", "";
> +};
> +
> +&gpiok {
> +	gpio-line-names =
> +	"", "", "", "", "", "", "", "",
> +	"", "", "", "", "", "", "", "";
> +};
> +
> +&gpioz {
> +	gpio-line-names =
> +	"", "", "", "#SPI_CS2", "", "", "", "",
> +	"", "", "", "", "", "", "", "";
> +};
> +
> +&gpu {
> +	status = "okay";
> +};
> +
> +&i2c1 {
> +	pinctrl-names = "default", "sleep";
> +	pinctrl-0 = <&i2c1_ux_pins_a>;
> +	pinctrl-1 = <&i2c1_ux_pins_sleep_a>;
> +	i2c-scl-rising-time-ns = <100>;
> +	i2c-scl-falling-time-ns = <7>;
> +	status = "okay";
> +	/delete-property/dmas;
> +	/delete-property/dma-names;
> +
> +	rtc at 32 {
> +		compatible = "epson,rx8900";
> +		reg = <0x32>;
> +		epson,vdet-disable;
> +		trickle-diode-disable;
> +	};
> +};
> +
> +&i2c4 {
> +	pinctrl-names = "default", "sleep";
> +	pinctrl-0 = <&i2c4_ux_pins_a>;
> +	pinctrl-1 = <&i2c4_ux_pins_sleep_a>;
> +	i2c-scl-rising-time-ns = <185>;
> +	i2c-scl-falling-time-ns = <20>;
> +	status = "okay";
> +	/delete-property/dmas;
> +	/delete-property/dma-names;
> +
> +	pmic: stpmic at 33 {

Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation

pmic?

> +		compatible = "st,stpmic1";
> +		reg = <0x33>;
> +		interrupts-extended = <&exti 0 IRQ_TYPE_EDGE_FALLING>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		status = "okay";

Does not look disabled


...


> +	dac_ux_ch2_pins_a: dac_ux-ch2-0 {

No underscores in node names.

> +		pins {
> +			pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
> +		};
> +	};
> +




Best regards,
Krzysztof


From ukleinek at kernel.org  Mon Mar 10 09:15:05 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 10 Mar 2025 17:15:05 +0100
Subject: [PATCH] dt-bindings: pwm: imx: Add i.MX93, i.MX94 and i.MX95
 support
In-Reply-To: <20250306170845.240555-1-Frank.Li@nxp.com>
References: <20250306170845.240555-1-Frank.Li@nxp.com>
Message-ID: <jwge3lqlx7t6j4gmag4ghu6vtzatg54i3x3tl75k5upvedakdy@entc6jjcqh47>

Hello Frank,

On Thu, Mar 06, 2025 at 12:08:45PM -0500, Frank Li wrote:
> Add compatible string "fsl,imx93-pwm", "fsl,imx94-pwm" and "fsl,imx95-pwm",
> which is backward compatible with i.MX7ULP. Set it to fall back to
> "fsl,imx7ulp-pwm".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/for-next
with Conor's ack.

Thanks
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/47c7bf68/attachment.sig>

From conor at kernel.org  Mon Mar 10 09:15:12 2025
From: conor at kernel.org (Conor Dooley)
Date: Mon, 10 Mar 2025 16:15:12 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <OSBPR01MB2775D121B55A0C543F251BAEFFD72@OSBPR01MB2775.jpnprd01.prod.outlook.com>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
 <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-barbell-pretzel-368d6a4d1336@spud>
 <OSBPR01MB2775D121B55A0C543F251BAEFFD72@OSBPR01MB2775.jpnprd01.prod.outlook.com>
Message-ID: <20250310-blurry-scam-bee8233878bc@spud>

On Sun, Mar 09, 2025 at 10:39:27AM +0000, John Madieu wrote:
> Hi Conor,
> 
> > -----Original Message-----
> > From: Conor Dooley <conor at kernel.org>
> > Sent: Friday, March 7, 2025 5:04 PM
> > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> > the TSU unit
> > 
> > On Fri, Mar 07, 2025 at 03:55:27PM +0000, John Madieu wrote:
> > > Hi Conor,
> > >
> > > > > > > Signed-off-by: John Madieu <john.madieu.xa at bp.renesas.com>
> > > > > > > ---
> > > > > > > v1 -> v2:
> > > > > > >  * Fix reg property specifier to get rid of yamlint warnings
> > > > > > >  * Fix IRQ name to reflect TSU expectations
> > > > > > >
> > > > > > > +    enum: [0, 1]
> > > > > > > +    description: |
> > > > > > > +      TSU operating mode:
> > > > > > > +      0: Mode 0 - Conversion started by software
> > > > > > > +      1: Mode 1 - Conversion started by ELC trigger
> > > > > >
> > > > > > Can you make this "software" and "elc" or something please,
> > > > > > unless people will genuinely find "0" and 1" to be more
> > informative.
> > > > > > And why doesn't the property have a default?
> > > > >
> > > > > Sorry for miss-specifying.
> > > > > ELC is an external event trigger. May be should I specify it like
> > that ?
> > > >
> > > > If "elc trigger" is meaningful to people using hte device (IOW, it
> > > > matches datasheet wording) then that's fine I think.
> > >
> > > "elc trigger" matches datasheet wording.
> > >
> > > >
> > > > > To make sure I got your point, do you mean specifying a default
> > > > > value in bindings ?
> > > >
> > > > The property doesn't actually need to be required, it could easily
> > > > have a default (say software) and only be set in the case of using
> > > > the elc trigger - which brings you to Rob's comment that it can just
> > > > be a boolean, setting the property if elc and leaving it out of
> > software.
> > >
> > > Got the point now. I can make it default to software trigger, and add
> > > optional Boolean property to ELC trigger. Let's say "renesas,elc-
> > trigger;"
> > 
> > Yah, that works.
> > 
> > >
> > > >
> > > > Rob's other comment was
> > > >
> > > > | Who/what decides the mode? If a user is going to want to change
> > > > | this, then it should be a runtime control, not a DT property.
> > >
> > > Changes are not possible at runtime. Some customers may want software,
> > > while other may want the external trigger, and this is immutable
> > > configuration.
> > 
> > What makes it immutable? Set by some wiring on the board? I couldn't find
> > the user in your driver patches to better understand how you were using
> > it.
> 
> I haven't prototyped ELC trigger yet. Since the hardware manual
> describes about ELC trigger, I have documented it in bindings. If you
> think, it is not needed at this stage, then I can drop it now and
> revisit later.

Ideally a binding is complete, even if the driver isn't. To me
"immutable" would mean something like "the trigger type is determined by
hardware or firmware configuration", but if it is determined by register
writes (e.g. wired up for elc trigger, but you can opt for software
trigger in the driver) then it should be a userspace control.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/2f7bf2bd/attachment.sig>

From ptyadav at amazon.de  Mon Mar 10 09:20:01 2025
From: ptyadav at amazon.de (Pratyush Yadav)
Date: Mon, 10 Mar 2025 16:20:01 +0000
Subject: [PATCH v4 06/14] kexec: Add KHO parsing support
In-Reply-To: <20250206132754.2596694-7-rppt@kernel.org>
References: <20250206132754.2596694-1-rppt@kernel.org>
	<20250206132754.2596694-7-rppt@kernel.org>
Message-ID: <mafs0zfhs97ta.fsf@amazon.de>

Hi Mike,

On Thu, Feb 06 2025, Mike Rapoport wrote:
[...]
> @@ -444,7 +576,141 @@ static void kho_reserve_scratch(void)
>  	kho_enable = false;
>  }
>  
> +/*
> + * Scan the DT for any memory ranges and make sure they are reserved in
> + * memblock, otherwise they will end up in a weird state on free lists.
> + */
> +static void kho_init_reserved_pages(void)
> +{
> +	const void *fdt = kho_get_fdt();
> +	int offset = 0, depth = 0, initial_depth = 0, len;
> +
> +	if (!fdt)
> +		return;
> +
> +	/* Go through the mem list and add 1 for each reference */
> +	for (offset = 0;
> +	     offset >= 0 && depth >= initial_depth;
> +	     offset = fdt_next_node(fdt, offset, &depth)) {
> +		const struct kho_mem *mems;
> +		u32 i;
> +
> +		mems = fdt_getprop(fdt, offset, "mem", &len);
> +		if (!mems || len & (sizeof(*mems) - 1))
> +			continue;
> +
> +		for (i = 0; i < len; i += sizeof(*mems)) {
> +			const struct kho_mem *mem = &mems[i];

i goes from 0 to len in steps of 16, but you use it to dereference an
array of type struct kho_mem. So you end up only looking at only one of
every 16 mems and do an out of bounds access. I found this when testing
the memfd patches and any time the file was more than 1 page, it started
to crash randomly.

Below patch should fix that:

---- 8< ----
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index c26753d613cbc..40d1d8ac68d44 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -685,13 +685,15 @@ static void kho_init_reserved_pages(void)
             offset >= 0 && depth >= initial_depth;
             offset = fdt_next_node(fdt, offset, &depth)) {
                const struct kho_mem *mems;
-               u32 i;
+               u32 i, nr_mems;
 
                mems = fdt_getprop(fdt, offset, "mem", &len);
                if (!mems || len & (sizeof(*mems) - 1))
                        continue;
 
-               for (i = 0; i < len; i += sizeof(*mems)) {
+               nr_mems = len / sizeof(*mems);
+
+               for (i = 0; i < nr_mems; i++) {
                        const struct kho_mem *mem = &mems[i];
 
                        memblock_reserve(mem->addr, mem->size);
---- >8 ----
[...]

-- 
Regards,
Pratyush Yadav


From krzk at kernel.org  Mon Mar 10 09:22:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 17:22:02 +0100
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
 <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
Message-ID: <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>

On 10/03/2025 16:56, Antonin Godard wrote:
> Add support for the Variscite i.MX6UL VAR-SOM-MX6UL and the Variscite
> Concerto carrier board.
> 
> Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
> ---
<form letter>
This is a friendly reminder during the review process.

It looks like you received a tag and forgot to add it.

If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Please read:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577

If a tag was not added on purpose, please state why and what changed.
</form letter>


Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 10 09:22:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 17:22:47 +0100
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
 <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
 <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>
Message-ID: <cd2f3c97-53bb-42f5-a3cd-4385bfda5dc7@kernel.org>

On 10/03/2025 17:22, Krzysztof Kozlowski wrote:
> On 10/03/2025 16:56, Antonin Godard wrote:
>> Add support for the Variscite i.MX6UL VAR-SOM-MX6UL and the Variscite
>> Concerto carrier board.
>>
>> Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
>> ---
> <form letter>
> This is a friendly reminder during the review process.
> 
> It looks like you received a tag and forgot to add it.
> 
> If you do not know the process, here is a short explanation:
> Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
> of patchset, under or above your Signed-off-by tag, unless patch changed
> significantly (e.g. new properties added to the DT bindings). Tag is
> "received", when provided in a message replied to you on the mailing
> list. Tools like b4 can help here. However, there's no need to repost
> patches *only* to add the tags. The upstream maintainer will do that for
> tags received on the version they apply.
> 
> Please read:
> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
> 
> If a tag was not added on purpose, please state why and what changed.

And now I noticed you used b4, so I really do not get how the tags can
be missing here. :/

Best regards,
Krzysztof


From mark.rutland at arm.com  Mon Mar 10 09:24:41 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 16:24:41 +0000
Subject: [PATCH -next] arm64/fpsimd: Remove unused declaration
 fpsimd_kvm_prepare()
In-Reply-To: <20250309070723.1390958-1-yuehaibing@huawei.com>
References: <20250309070723.1390958-1-yuehaibing@huawei.com>
Message-ID: <Z88SSYFJo9R_YgO3@J2N7QTR9R3.cambridge.arm.com>

On Sun, Mar 09, 2025 at 03:07:23PM +0800, Yue Haibing wrote:
> Commit fbc7e61195e2 ("KVM: arm64: Unconditionally save+flush host
> FPSIMD/SVE/SME state") removed the implementation but leave declaration.
> 
> Signed-off-by: Yue Haibing <yuehaibing at huawei.com>

My bad. Looks like a sensible cleanup.

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> ---
>  arch/arm64/include/asm/fpsimd.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index f2a84efc3618..564bc09b3e06 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -80,7 +80,6 @@ extern void fpsimd_signal_preserve_current_state(void);
>  extern void fpsimd_preserve_current_state(void);
>  extern void fpsimd_restore_current_state(void);
>  extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
> -extern void fpsimd_kvm_prepare(void);
>  
>  struct cpu_fp_state {
>  	struct user_fpsimd_state *st;
> -- 
> 2.34.1
> 
> 


From andrea.porta at suse.com  Mon Mar 10 09:26:36 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Mon, 10 Mar 2025 17:26:36 +0100
Subject: [PATCH v6 00/10] Add support for RaspberryPi RP1 PCI device
 using a DT overlay
In-Reply-To: <CAMEGJJ0f4YUgdWBhxvQ_dquZHztve9KO7pvQjoDWJ3=zd3cgcg@mail.gmail.com>
References: <CAMEGJJ3=W8_R0xBvm8r+Q7iExZx8xPBHEWWGAT9ngpGWDSKCaQ@mail.gmail.com>
 <20250213171435.1c2ce376@bootlin.com>
 <CAMEGJJ1++aeE7WWLVVesbujME+r2WicEkK+CQgigRRp2grYf=A@mail.gmail.com>
 <Z87wTfChRC5Ruwc0@apocalypse>
 <CAMEGJJ0f4YUgdWBhxvQ_dquZHztve9KO7pvQjoDWJ3=zd3cgcg@mail.gmail.com>
Message-ID: <Z88SvEmaZYfysQ-k@apocalypse>

Hi Phil,

On 14:21 Mon 10 Mar     , Phil Elwell wrote:
> Hi Andrea,
> 

...

> 
> This is indeed our current DT usage for the Pi 5 family - a single DTB
> describing each board - although I would like to make it clear that
> overlays can then be applied on top of it describing the attached
> peripherals.

Indeed. Thanks for specifying that.

> 
> > 2 - RP1 LOADED FROM OVERLAY BY THE FW
> >
> > In this case the rp1 dt node is loaded from overlay directly by the fw and the
> > resulting devicetree is exactly equal to the monolithic dtb scenario.
> > In order for that overlay to be loaded by fw, just add 'dtoverlay=rp1' in
> > 'config.txt'.
> 
> This halfway house combines the advantages and disadvantages of
> scenarios 1 and 3. Compared to scenario 3 it gains support for
> applying overlays that make use of interfaces provided by RP1 - I2C,
> SPI, UARTs etc. Compared to scenario 1 it loses the ability for the
> base DTB to refer to elements of RP1, other than by replacing these
> DTB elements with overlays that must be loaded after the RP1 overlay.
> As such, we would see that as a backwards step and not use it.

This is in fact the second side of the problem I was mentioning: being
able to reference RP1 nodes from base tree (this of course arise only for
case 2 and 3, i.e. in case overlays are used). Some solutions to this have
been added by Herve (nexus nodes) and it seems promising, but I still
don't have a complete and tested solution.
My intention here is to verify if it is worth spending time on figuring
out a solution for the overlay case, since in case we only accept the
monolithic approach we won't use overlay for rp1 at all.

My idea is that we can still provide the dtbs for all three cases for the
user to choose from (so to potentially benefit from all advantages every
single solution provides), and refine the overlay case as we go, since we
can still fallback to the monolithic dtb in case we can't find a viable
solution to the across-overlay referencing issue.  But I'd like a confirm
from upstream too.
I think that this problem should really be addressed sooner or later (I'm
hinting at fpga hw, but lately we're seeing other appliances of this paradigm
arising more often), so maybe this is a good opportunity to lay the ground
for a proper solution that could be generalized for other situations too, but
again, not at the cost of slowing down rpi5 upstream efforts.

> 
> > 3 - RP1 LOADED FROM OVERLAY AT RUNTIME
> >
> > Here it's the rp1 driver that loads the overlay at runtime, which is the case
> > that this patchset originally proposed. The devicetree ends up like this:
> >
> >   axi {
> >     pcie at 120000 {
> >       pci at 0,0 {
> >         dev at 0,0 {

...

> >         / {
> >                 ... all rpi5 board dts ...
> >                 &pcie2 {
> >                         #include "rp1-nexus.dtsi"
> >                 };
> >         };
> >
> >
> > with only minimal changes to the rp1 driver code, I can confirm that all those
> > scenarios can coexits and are working fine. Before processding with a new patchset
> > I'd like to have some thoughts about that, do you think this is a viable approach?
> 
> Thank you for this - the creation of a core RP1 declaration that can
> be tailored to multiple applications using different wrappers is
> exactly what I had in mind. I agree that your partitioning scheme can
> cater for the 3 usage scenarios, but for the reasons outlined above I
> think scenario 2 is not useful to us, although it isn't impossible
> that U-boot might see things differently; I see no harm in having it
> supported, but I wouldn't want anyone to go to unnecessary effort to
> make it work.

In all truth, this is in fact exactly your proposal (we discussed internally with
Dave also), just slightly re-arranged by me.
I agree with you about not wasting time, as I also mentioned above.

Many thanks,
Andrea

> 
> Phil


From kuba at kernel.org  Mon Mar 10 09:25:41 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Mon, 10 Mar 2025 17:25:41 +0100
Subject: Plan to validate supported flags in PTP core (Was: Re: [PATCH
 net v2 0/2] Fixes for perout configuration in IEP driver)
In-Reply-To: <f7072ca6-47a7-4278-be5d-7cbd240fcd35@intel.com>
References: <20250219062701.995955-1-m-malladi@ti.com>
	<415f755d-18a6-4c81-a1a7-b75d54a5886a@intel.com>
	<20250220172410.025b96d6@kernel.org>
	<a7e434a5-b5f6-4736-98e4-e671f88d1873@intel.com>
	<f7072ca6-47a7-4278-be5d-7cbd240fcd35@intel.com>
Message-ID: <20250310172541.30896e20@kernel.org>

On Fri, 7 Mar 2025 15:48:27 -0800 Jacob Keller wrote:
> Would a series with individual patches for the 3 special cases + one
> patch to handle all the drivers that have no explicit flag check be
> acceptable? Or should I do individual patches for each driver and just
> break the series up? Or are we ok with just fixing this in next with the
> .supported_extts_flags change?

A mass rejection of unsupported settings feels like a net-next material
in general. Handling the more complex cases individually and the rest in
a big patch makes sense.


From mark.barnett at arm.com  Mon Mar 10 09:27:44 2025
From: mark.barnett at arm.com (Mark Barnett)
Date: Mon, 10 Mar 2025 16:27:44 +0000
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250310124735.GR5880@noisy.programming.kicks-ass.net>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250310124735.GR5880@noisy.programming.kicks-ass.net>
Message-ID: <73edda3b-7305-4903-8950-8528c94051b1@arm.com>

On 3/10/25 12:47, Peter Zijlstra wrote:
> On Fri, Mar 07, 2025 at 08:22:45PM +0000, mark.barnett at arm.com wrote:
>> @@ -9922,7 +9923,10 @@ static int __perf_event_overflow(struct perf_event *event,
>>   	if (event->attr.alt_sample_period) {
>>   		bool using_alt = hwc->using_alt_sample_period;
>>   		u64 sample_period = (using_alt ? event->attr.sample_period
>> -					       : event->attr.alt_sample_period);
>> +					       : event->attr.alt_sample_period)
>> +				  + (event->attr.jitter_alt_period
>> +					? get_random_u32_below(2 << event->attr.jitter_alt_period)
>> +					: 0);
> 
> So, ... this here is NMI context, right? Have you looked at the guts of
> get_random_u32_below() ?
> 
> I would strongly suggest you go do so.
> 

Good catch. I think a pseudo-random generator would be fine here and it 
looks like the implementation of prandom is safe to use in an interrupt 
context. I can change to use that.

>>   
>>   		hwc->sample_period = sample_period;
>>   		hwc->using_alt_sample_period = !using_alt;



From antonin.godard at bootlin.com  Mon Mar 10 09:31:32 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 17:31:32 +0100
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <cd2f3c97-53bb-42f5-a3cd-4385bfda5dc7@kernel.org>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
 <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
 <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>
 <cd2f3c97-53bb-42f5-a3cd-4385bfda5dc7@kernel.org>
Message-ID: <D8CQAAKOZ1O5.8JVESQPJSSM8@bootlin.com>

On Mon Mar 10, 2025 at 5:22 PM CET, Krzysztof Kozlowski wrote:
> On 10/03/2025 17:22, Krzysztof Kozlowski wrote:
>> On 10/03/2025 16:56, Antonin Godard wrote:
>>> Add support for the Variscite i.MX6UL VAR-SOM-MX6UL and the Variscite
>>> Concerto carrier board.
>>>
>>> Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
>>> ---
>> <form letter>
>> This is a friendly reminder during the review process.
>> 
>> It looks like you received a tag and forgot to add it.
>> 
>> If you do not know the process, here is a short explanation:
>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
>> of patchset, under or above your Signed-off-by tag, unless patch changed
>> significantly (e.g. new properties added to the DT bindings). Tag is
>> "received", when provided in a message replied to you on the mailing
>> list. Tools like b4 can help here. However, there's no need to repost
>> patches *only* to add the tags. The upstream maintainer will do that for
>> tags received on the version they apply.
>> 
>> Please read:
>> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
>> 
>> If a tag was not added on purpose, please state why and what changed.
>
> And now I noticed you used b4, so I really do not get how the tags can
> be missing here. :/

Sorry, that's totally my fault here, I forgot to run 'b4 trailers -u' before
sending... :/ And I don't think it's part of the prep checks?

I will send a new version with the proper trailers.

Antonin

-- 
Antonin Godard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From krzk at kernel.org  Mon Mar 10 09:34:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 17:34:56 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <20250309132959.19045-10-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-10-ansuelsmth@gmail.com>
Message-ID: <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>

On 09/03/2025 14:29, Christian Marangi wrote:
> Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
> for the USB controller.
> 
> Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> always supported. The USB 3.0 mode is optional and depends on the Serdes
> mode currently configured on the system for the USB port. If USB 3.0 node
> is defined, then airoha,scu-ssr property is required for Serdes mode
> validation.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/phy/airoha,an7581-usb-phy.yaml   | 106 ++++++++++++++++++
>  MAINTAINERS                                   |   6 +
>  2 files changed, 112 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> new file mode 100644
> index 000000000000..39127cfb63a7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7581 SoC USB PHY
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
> +
> +  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> +  always supported. The USB 3.0 mode is optional and depends on the Serdes
> +  mode currently configured on the system for the USB port. If USB 3.0 node
> +  is defined, then airoha,scu-ssr property is required for Serdes mode
> +  validation.
> +
> +properties:
> +  compatible:
> +    const: airoha,an7581-usb-phy
> +
> +  reg:
> +    maxItems: 1
> +
> +  airoha,port-id:
> +    description: Describe the physical port this USB PHY refer to. A dedicated
> +      osciallator is used for each port for the USB 2.0 Slew Rate calibration.

typo

> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1]

I don't understand why do you need index property here (which are
usually not allowed).

> +
> +  airoha,scu-ssr:
> +    description: Phandle to the SCU SSR node for USB 3.0 Serdes mode validation.
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  usb2-phy:
> +    type: object
> +
> +    properties:
> +      '#phy-cells':
> +        const: 1
> +
> +    required:
> +      - '#phy-cells'
> +
> +    additionalProperties: false

Also no resources in usb[23]-phy, so this goes to the parent level and
you have phy-cells=2. Your DTS gives some hint that devices actually
differ but the commit msg contradicts it, so I don't get. Do you have
same IP block here or two different?

> +
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fe34c80b8d52..c2dd385e9165 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -753,6 +753,12 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
>  F:	drivers/spi/spi-airoha-snfi.c
>  
> +AIROHA USB PHY DRIVER
> +M:	Christian Marangi <ansuelsmth at gmail.com>
> +L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam

Typo in extension/missing l.



Best regards,
Krzysztof


From thomas.weissschuh at linutronix.de  Mon Mar 10 08:38:23 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 10 Mar 2025 16:38:23 +0100
Subject: [PATCH v2 1/2] usb: core: Don't use %pK through printk
In-Reply-To: <20250310-restricted-pointers-usb-v2-0-a7598e2d47d1@linutronix.de>
References: <20250310-restricted-pointers-usb-v2-0-a7598e2d47d1@linutronix.de>
Message-ID: <20250310-restricted-pointers-usb-v2-1-a7598e2d47d1@linutronix.de>

This is a revert of
commit 2f964780c03b ("USB: core: replace %p with %pK").

When the formatting was changed from %p to %pK that was a security
improvement, as %p would leak raw pointer values to the kernel log.
Since commit ad67b74d2469 ("printk: hash addresses printed with %p")
the regular %p has been improved to avoid this issue.
On the other hand, restricted pointers ("%pK") were never meant to be used
through printk(). They can unintentionally still leak raw pointers or
acquire sleeping looks in atomic contexts.

Switch back to regular %p again.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 drivers/usb/core/hcd.c | 4 ++--
 drivers/usb/core/urb.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index a75cf1f6d741cf5827b9c4deca3b63013aff6cfe..46026b331267ade29839393b2fb5c0c42e34ab84 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1609,7 +1609,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
 		if (retval == 0)
 			retval = -EINPROGRESS;
 		else if (retval != -EIDRM && retval != -EBUSY)
-			dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n",
+			dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
 					urb, retval);
 		usb_put_dev(udev);
 	}
@@ -1786,7 +1786,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
 		/* kick hcd */
 		unlink1(hcd, urb, -ESHUTDOWN);
 		dev_dbg (hcd->self.controller,
-			"shutdown urb %pK ep%d%s-%s\n",
+			"shutdown urb %p ep%d%s-%s\n",
 			urb, usb_endpoint_num(&ep->desc),
 			is_in ? "in" : "out",
 			usb_ep_type_string(usb_endpoint_type(&ep->desc)));
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 7576920e2d5a3e6c0dfd8bee8fce9d09a55c195c..5e52a35486afbe58bdffd3dfc1eb5964a9471ade 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -376,7 +376,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 	if (!urb || !urb->complete)
 		return -EINVAL;
 	if (urb->hcpriv) {
-		WARN_ONCE(1, "URB %pK submitted while active\n", urb);
+		WARN_ONCE(1, "URB %p submitted while active\n", urb);
 		return -EBUSY;
 	}
 

-- 
2.48.1



From thomas.weissschuh at linutronix.de  Mon Mar 10 08:38:22 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 10 Mar 2025 16:38:22 +0100
Subject: [PATCH v2 0/2] usb: Don't use %pK through printk
Message-ID: <20250310-restricted-pointers-usb-v2-0-a7598e2d47d1@linutronix.de>

Restricted pointers ("%pK") are not meant to be used through printk().
It can unintentionally expose security sensitive, raw pointer values.

Use regular pointer formatting instead.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/

Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
Changes in v2:
- Refer to original %p->%pK changes in commit messages
- Link to v1: https://lore.kernel.org/r/20250217-restricted-pointers-usb-v1-0-78da55158832 at linutronix.de

---
Thomas Wei?schuh (2):
      usb: core: Don't use %pK through printk
      usb: dwc3: Don't use %pK through printk

 drivers/usb/core/hcd.c     | 4 ++--
 drivers/usb/core/urb.c     | 2 +-
 drivers/usb/dwc3/dwc3-st.c | 2 +-
 drivers/usb/dwc3/gadget.c  | 6 +++---
 4 files changed, 7 insertions(+), 7 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250217-restricted-pointers-usb-8c711bae6994

Best regards,
-- 
Thomas Wei?schuh <thomas.weissschuh at linutronix.de>



From thomas.weissschuh at linutronix.de  Mon Mar 10 08:38:24 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 10 Mar 2025 16:38:24 +0100
Subject: [PATCH v2 2/2] usb: dwc3: Don't use %pK through printk
In-Reply-To: <20250310-restricted-pointers-usb-v2-0-a7598e2d47d1@linutronix.de>
References: <20250310-restricted-pointers-usb-v2-0-a7598e2d47d1@linutronix.de>
Message-ID: <20250310-restricted-pointers-usb-v2-2-a7598e2d47d1@linutronix.de>

This is a revert of
commit 04fb365c453e ("usb: dwc3: replace %p with %pK")

When the formatting was changed from %p to %pK that was a security
improvement, as %p would leak raw pointer values to the kernel log.
Since commit ad67b74d2469 ("printk: hash addresses printed with %p")
the regular %p has been improved to avoid this issue.
On the other hand, restricted pointers ("%pK") were never meant to be used
through printk(). They can unintentionally still leak raw pointers or
acquire sleeping looks in atomic contexts.

Switch back to regular %p again.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 drivers/usb/dwc3/dwc3-st.c | 2 +-
 drivers/usb/dwc3/gadget.c  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index ef7c43008946e15b72d88aba4941dc52bf0788d7..5d513decaacd22de15825dc061c2747cf09fef07 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -225,7 +225,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
 
 	dwc3_data->syscfg_reg_off = res->start;
 
-	dev_vdbg(dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
+	dev_vdbg(dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n",
 		 dwc3_data->glue_base, dwc3_data->syscfg_reg_off);
 
 	struct device_node *child __free(device_node) = of_get_compatible_child(node,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 89a4dc8ebf948244a719f21cbbcce565cc1d8610..9a1ec31b6ab46077d3635d1bff3fa5b362bdd9ba 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1971,12 +1971,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		return -ESHUTDOWN;
 	}
 
-	if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
+	if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
 				&req->request, req->dep->name))
 		return -EINVAL;
 
 	if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED,
-				"%s: request %pK already in flight\n",
+				"%s: request %p already in flight\n",
 				dep->name, &req->request))
 		return -EINVAL;
 
@@ -2165,7 +2165,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
 		}
 	}
 
-	dev_err(dwc->dev, "request %pK was not queued to %s\n",
+	dev_err(dwc->dev, "request %p was not queued to %s\n",
 		request, ep->name);
 	ret = -EINVAL;
 out:

-- 
2.48.1



From daniel.lezcano at linaro.org  Mon Mar 10 08:41:03 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 10 Mar 2025 16:41:03 +0100
Subject: [PATCH 1/2] thermal: bcm2835: use %pC instead of %pCn
In-Reply-To: <20250307-vsprintf-pcn-v1-1-df0b2ccf610f@bootlin.com>
References: <20250307-vsprintf-pcn-v1-0-df0b2ccf610f@bootlin.com>
 <20250307-vsprintf-pcn-v1-1-df0b2ccf610f@bootlin.com>
Message-ID: <9dc5dadc-7ff1-484c-88a8-461d505cec03@linaro.org>

On 07/03/2025 12:19, Luca Ceresoli wrote:
> The %pC and %pCn printk format specifiers produce the exact same string. In
> preparation for removing %pCn, use %pC.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---

Applied patch 1/2

Thanks!

-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From mathieu.poirier at linaro.org  Mon Mar 10 08:42:39 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Mon, 10 Mar 2025 09:42:39 -0600
Subject: [PATCH v4 8/8] imx_dsp_rproc: Use reset controller API to
 control the DSP
In-Reply-To: <20250305100037.373782-9-daniel.baluta@nxp.com>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-9-daniel.baluta@nxp.com>
Message-ID: <Z88Ib7HkbRQoiyZp@p14s>

Good day,

On Wed, Mar 05, 2025 at 12:00:36PM +0200, Daniel Baluta wrote:
> DSP on i.MX8MP doesn't have a direct reset line so according to hardware
> design team in order to handle assert/deassert/reset functionality we
> need to use a combination of control bits from two modules. Audio block
> control module for Run/Stall control of the DSP and DAP module in order
> to do software reset.
> 
> Initial design accessed RunStall bits from audio block control using the
> syscon interface but this got NACKed by community because of abusing the
> syscon interface [1].
> 
> So instead we use the reset controller API.

I am good with this patchset.  The only thing I'd like so see modified is the
above changelog.  The second paragraph doesn't belong there, i.e it is not
useful to remark on a design that was not accepted.  Instead please concentrate
on _why_ we are moving from the current design to using the reset controller
API.

This can go in the 6.15 merge window if you send me a V5 fast enough.

Thanks,
Mathieu

> 
> [1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/
> 
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
>  drivers/remoteproc/imx_dsp_rproc.c | 25 +++++++++++++++++--------
>  drivers/remoteproc/imx_rproc.h     |  2 ++
>  2 files changed, 19 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
> index ea5024919c2f..bc60edcdd661 100644
> --- a/drivers/remoteproc/imx_dsp_rproc.c
> +++ b/drivers/remoteproc/imx_dsp_rproc.c
> @@ -19,6 +19,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/regmap.h>
>  #include <linux/remoteproc.h>
> +#include <linux/reset.h>
>  #include <linux/slab.h>
>  
>  #include "imx_rproc.h"
> @@ -111,6 +112,7 @@ enum imx_dsp_rp_mbox_messages {
>   */
>  struct imx_dsp_rproc {
>  	struct regmap				*regmap;
> +	struct reset_control			*run_stall;
>  	struct rproc				*rproc;
>  	const struct imx_dsp_rproc_dcfg		*dsp_dcfg;
>  	struct clk_bulk_data			clks[DSP_RPROC_CLK_MAX];
> @@ -192,9 +194,7 @@ static int imx8mp_dsp_reset(struct imx_dsp_rproc *priv)
>  	/* Keep reset asserted for 10 cycles */
>  	usleep_range(1, 2);
>  
> -	regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2,
> -			   IMX8M_AudioDSP_REG2_RUNSTALL,
> -			   IMX8M_AudioDSP_REG2_RUNSTALL);
> +	reset_control_assert(priv->run_stall);
>  
>  	/* Take the DSP out of reset and keep stalled for FW loading */
>  	pwrctl = readl(dap + IMX8M_DAP_PWRCTL);
> @@ -231,13 +231,9 @@ static int imx8ulp_dsp_reset(struct imx_dsp_rproc *priv)
>  
>  /* Specific configuration for i.MX8MP */
>  static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = {
> -	.src_reg	= IMX8M_AudioDSP_REG2,
> -	.src_mask	= IMX8M_AudioDSP_REG2_RUNSTALL,
> -	.src_start	= 0,
> -	.src_stop	= IMX8M_AudioDSP_REG2_RUNSTALL,
>  	.att		= imx_dsp_rproc_att_imx8mp,
>  	.att_size	= ARRAY_SIZE(imx_dsp_rproc_att_imx8mp),
> -	.method		= IMX_RPROC_MMIO,
> +	.method		= IMX_RPROC_RESET_CONTROLLER,
>  };
>  
>  static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = {
> @@ -329,6 +325,9 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
>  					  true,
>  					  rproc->bootaddr);
>  		break;
> +	case IMX_RPROC_RESET_CONTROLLER:
> +		ret = reset_control_deassert(priv->run_stall);
> +		break;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> @@ -369,6 +368,9 @@ static int imx_dsp_rproc_stop(struct rproc *rproc)
>  					  false,
>  					  rproc->bootaddr);
>  		break;
> +	case IMX_RPROC_RESET_CONTROLLER:
> +		ret = reset_control_assert(priv->run_stall);
> +		break;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> @@ -995,6 +997,13 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv)
>  
>  		priv->regmap = regmap;
>  		break;
> +	case IMX_RPROC_RESET_CONTROLLER:
> +		priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall");
> +		if (IS_ERR(priv->run_stall)) {
> +			dev_err(dev, "Failed to get DSP runstall reset control\n");
> +			return PTR_ERR(priv->run_stall);
> +		}
> +		break;
>  	default:
>  		ret = -EOPNOTSUPP;
>  		break;
> diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
> index 17a7d051c531..cfd38d37e146 100644
> --- a/drivers/remoteproc/imx_rproc.h
> +++ b/drivers/remoteproc/imx_rproc.h
> @@ -24,6 +24,8 @@ enum imx_rproc_method {
>  	IMX_RPROC_SMC,
>  	/* Through System Control Unit API */
>  	IMX_RPROC_SCU_API,
> +	/* Through Reset Controller API */
> +	IMX_RPROC_RESET_CONTROLLER,
>  };
>  
>  /* dcfg flags */
> -- 
> 2.43.0
> 


From catalin.marinas at arm.com  Mon Mar 10 08:43:41 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 15:43:41 +0000
Subject: [PATCH v2 2/3] arm64: mm: Handle PAN faults on uaccess CPY*
 instructions
In-Reply-To: <1210b66a-ed75-4bc1-bbaa-d3277c290267@arm.com>
References: <20250228170006.390100-1-kristina.martsenko@arm.com>
 <20250228170006.390100-3-kristina.martsenko@arm.com>
 <Z8s-4OPE2DNSogwB@arm.com>
 <4c621070-688a-4a75-9134-ea19b6d20f04@arm.com>
 <Z8tnARR2jSJEruLw@arm.com>
 <1210b66a-ed75-4bc1-bbaa-d3277c290267@arm.com>
Message-ID: <Z88IrRhWsQyEtO-S@arm.com>

On Mon, Mar 10, 2025 at 02:15:53PM +0000, Kristina Martsenko wrote:
> On 07/03/2025 21:37, Catalin Marinas wrote:
> > On Fri, Mar 07, 2025 at 06:53:37PM +0000, Robin Murphy wrote:
> >> On 2025-03-07 6:45 pm, Catalin Marinas wrote:
> >>> On Fri, Feb 28, 2025 at 05:00:05PM +0000, Kristina Martsenko wrote:
> >>>> +bool extable_insn_may_access_user(const struct exception_table_entry *ex,
> >>>> +				  unsigned long esr)
> >>>> +{
> >>>> +	switch (ex->type) {
> >>>> +	case EX_TYPE_UACCESS_CPY:
> >>>> +		return cpy_faulted_on_uaccess(ex, esr);
> >>>> +	default:
> >>>> +		return true;
> >>>> +	}
> >>>> +}
> >>>
> >>> Not a problem with this patch but I wonder whether we should return
> >>> false for EX_TYPE_LOAD_UNALIGNED_ZEROPAD for completeness
> >>
> >> Or maybe rather, true for EX_TYPE_UACCESS_ERR_ZERO and then false in the
> >> default case?
> > 
> > Yes.
> 
> I thought you said in an earlier (off-list) discussion that 
> EX_TYPE_KACCESS_ERR_ZERO shouldn't return false here because 
> __get_kernel_nofault() may get called with untrusted addresses? Or did I
> misunderstand?

TBH, I don't remember. Thinking about it, if we have a bug and someone
exploits __get_kernel_nofault() by giving it a user address, the above
function should indeed return false in principle. Not a big problem
since the actual user access won't happen but we may get into an
infinite loop.

I think something like this should do:

diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
index 6e0528831cd3..ab6775747601 100644
--- a/arch/arm64/mm/extable.c
+++ b/arch/arm64/mm/extable.c
@@ -28,10 +28,12 @@ bool insn_may_access_user(unsigned long addr, unsigned long esr)
 		return false;
 
 	switch (ex->type) {
+	case EX_TYPE_UACCESS_ERR_ZERO:
+		return true;
 	case EX_TYPE_UACCESS_CPY:
 		return cpy_faulted_on_uaccess(ex, esr);
 	default:
-		return true;
+		return false;
 	}
 }
 

-- 
Catalin


From james.clark at linaro.org  Mon Mar 10 08:45:02 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 10 Mar 2025 15:45:02 +0000
Subject: [PATCH] arm64: dts: hi3660: Add property for fixing CPUIdle
In-Reply-To: <20250310093708.9332-1-leo.yan@arm.com>
References: <20250310093708.9332-1-leo.yan@arm.com>
Message-ID: <aded13c4-a8cb-464a-b7c5-34cc7d88d918@linaro.org>



On 10/03/2025 9:37 am, Leo Yan wrote:
> During CPU low power modes, ETM components will lose their context.  Add
> the "arm,coresight-loses-context-with-cpu" property to ETM nodes to save
> and restore ETM context for CPU idle states.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi | 8 ++++++++
>   1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> index 79a55a0fa2f1..4c6a075908d1 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> @@ -17,6 +17,7 @@ etm at ecc40000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu0>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -34,6 +35,7 @@ etm at ecd40000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu1>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -51,6 +53,7 @@ etm at ece40000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu2>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -68,6 +71,7 @@ etm at ecf40000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu3>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -160,6 +164,7 @@ etm at ed440000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu4>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -177,6 +182,7 @@ etm at ed540000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu5>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -194,6 +200,7 @@ etm at ed640000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu6>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {
> @@ -211,6 +218,7 @@ etm at ed740000 {
>   			clocks = <&crg_ctrl HI3660_PCLK>;
>   			clock-names = "apb_pclk";
>   			cpu = <&cpu7>;
> +			arm,coresight-loses-context-with-cpu;
>   
>   			out-ports {
>   				port {

Reviewed-by: James Clark <james.clark at linaro.org>



From goran.radni at gmail.com  Mon Mar 10 08:48:00 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Mon, 10 Mar 2025 16:48:00 +0100
Subject: [PATCH 3/4] dt-bindings: arm: stm32: Document Ultratronik's Fly board DT binding
In-Reply-To: <20250310154804.326943-1-goran.radni@gmail.com>
References: <20250310154804.326943-1-goran.radni@gmail.com>
Message-ID: <20250310154804.326943-4-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

This commit documents ultra-fly-sbc devicetree binding based on
STM32MP157 SoC.

Signed-off-by: Goran Ra?enovi? <gradenovic at ultratronik.de>
---
 Documentation/devicetree/bindings/arm/stm32/stm32.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index b6c56d4ce6b9..2cfc08430a87 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -175,6 +175,11 @@ properties:
           - const: phytec,phycore-stm32mp157c-som
           - const: st,stm32mp157
 
+      - description: Ultratronik STM32MP1 SBC based Boards
+        items:
+          - const: ux,stm32mp157c-ultra-fly-sbc
+          - const: st,stm32mp157
+
       - description: ST STM32MP257 based Boards
         items:
           - enum:
-- 
2.43.0



From goran.radni at gmail.com  Mon Mar 10 08:48:01 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Mon, 10 Mar 2025 16:48:01 +0100
Subject: [PATCH 4/4] ARM: dts: stm32: add initial support for stm32mp157-ultra-fly-sbc board
In-Reply-To: <20250310154804.326943-1-goran.radni@gmail.com>
References: <20250310154804.326943-1-goran.radni@gmail.com>
Message-ID: <20250310154804.326943-5-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

Add support for Ultratronik's stm32mp157c fly board. This board embeds
a STM32MP157c SOC and 1GB of DDR3. Several connections are available on
this boards: 2*USB2.0, 1*USB2.0 MiniUSB, Debug UART, 1*UART, 1*USART,
SDcard, RJ45, ...

This patch enables basic support for a kernel boot - SD-card or eMMC.

Signed-off-by: Goran Ra?enovi? <gradenovic at ultratronik.de>
---
 arch/arm/boot/dts/st/Makefile                 |    3 +-
 .../boot/dts/st/stm32mp157c-ultra-fly-sbc.dts | 1156 +++++++++++++++++
 2 files changed, 1158 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts

diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile
index b7d5d305cbbe..270d1c699e1a 100644
--- a/arch/arm/boot/dts/st/Makefile
+++ b/arch/arm/boot/dts/st/Makefile
@@ -66,7 +66,8 @@ dtb-$(CONFIG_ARCH_STM32) += \
 	stm32mp157c-lxa-tac-gen2.dtb \
 	stm32mp157c-odyssey.dtb \
 	stm32mp157c-osd32mp1-red.dtb \
-	stm32mp157c-phycore-stm32mp1-3.dtb
+	stm32mp157c-phycore-stm32mp1-3.dtb \
+	stm32mp157c-ultra-fly-sbc.dtb
 dtb-$(CONFIG_ARCH_U8500) += \
 	ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
diff --git a/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
new file mode 100644
index 000000000000..82896cda0f6c
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
@@ -0,0 +1,1156 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) Ultratronik GmbH 2024-2025 - All Rights Reserved
+ */
+
+/dts-v1/;
+#include "stm32mp157.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "STM STM32MP15x Ultratronik MMI_A7 board";
+	compatible = "ux,stm32mp157c-ultra-fly-sbc", "st,stm32mp157";
+
+	aliases {
+		ethernet0 = &ethernet0;
+		serial0 = &uart4;
+		serial1 = &uart5;
+		serial2 = &uart7;
+		serial3 = &usart1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at c0000000 {
+		device_type = "memory";
+		reg = <0xC0000000 0x40000000>;
+	};
+
+	usb_otg_vbus: regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpioh 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		retram: retram at 38000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x38000000 0x10000>;
+			no-map;
+		};
+
+		mcuram: mcuram at 30000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x30000000 0x40000>;
+			no-map;
+		};
+
+		mcuram2: mcuram2 at 10000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10000000 0x40000>;
+			no-map;
+		};
+
+		vdev0vring0: vdev0vring0 at 10040000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10040000 0x2000>;
+			no-map;
+		};
+
+		vdev0vring1: vdev0vring1 at 10042000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10042000 0x2000>;
+			no-map;
+		};
+
+		vdev0buffer: vdev0buffer at 10044000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10044000 0x4000>;
+			no-map;
+		};
+
+		gpu_reserved: gpu at f8000000 {
+			reg = <0xf8000000 0x8000000>;
+			no-map;
+		};
+	};
+
+	leds: leds {
+		compatible = "gpio-leds";
+
+		led0{
+			label = "buzzer";
+			gpios = <&gpiof 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "none";
+		};
+
+		led1 {
+			label = "led1";
+			gpios = <&gpioa 12 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led2 {
+			label = "led2";
+			gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led3 {
+			label = "led3";
+			gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+
+		key-1 {
+			label = "KEY1";
+			gpios = <&gpiod 1 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <2>;
+		};
+
+		key-2 {
+			label = "KEY2";
+			gpios = <&gpiod 7 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <3>;
+		};
+	};
+};
+
+&adc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc1_ux_ain_pins_a>;
+	vdd-supply = <&vdd>;
+	vdda-supply = <&vdd>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	adc1: adc at 0 {
+		st,min-sample-time-nsecs = <5000>;
+		st,adc-channels = <0 1 6 13>; /* ANA0 ANA1 PF12 PC3 */
+		status = "okay";
+	};
+
+	adc2: adc at 100 {
+		st,adc-channels = <0 1 12>; /* ANA0 ANA1 INT_TEMP*/
+		st,min-sample-time-nsecs = <10000>;
+		status = "okay";
+
+		channel at 12 {
+			reg = <12>;  /* Channel 12 = internal temperature sensor */
+			label = "internal_temp";
+		};
+	};
+};
+
+&dac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dac_ux_ch1_pins_a &dac_ux_ch2_pins_a>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	dac1: dac at 1 {
+		status = "okay";
+	};
+
+	dac2: dac at 2 {
+		status = "okay";
+	};
+};
+
+&dts {
+	compatible = "st,stm32-thermal";
+	status = "okay";
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_ux_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_ux_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii-id";
+	max-speed = <1000>;
+	phy-handle = <&phy1>;
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy1: ethernet-phy at 1 {
+			reg = <1>;
+			interrupt-parent = <&gpiod>;
+			interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+};
+
+&gpioa {
+	gpio-line-names =
+	"#PMIC_IRQ", "", "", "", "DAC1", "DAC2", "", "",
+	"", "", "OTG_ID", "TIM1_4", "#LED1", "#LED2", "#LED3", "";
+};
+
+&gpiob {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioc {
+	gpio-line-names =
+	"#AMP_SD", "", "", "ANA5", "", "", "", "",
+	"", "", "", "", "", "PMIC_WAKEUP", "", "";
+};
+
+&gpiod {
+	gpio-line-names =
+	"#G_INT", "#TASTER1", "", "", "GPIO1", "GPIO2", "", "#TASTER2",
+	"", "", "", "", "", "", "TIM4_3", "TIM4_4";
+};
+
+&gpioe {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "PWM2", "", "", "", "", "";
+};
+
+&gpiof {
+	gpio-line-names =
+	"#SD1_CD", "SD1_WP", "BUZZER", "#DISP_POW", "BKL_POW", "#CAM_RES", "", "",
+	"", "TIM17_1N", "", "CAM_PWDN", "ANA6", "ENA_USB", "", "";
+};
+
+&gpiog {
+	gpio-line-names =
+	"#ESP_RES", "#ESP_BOOT", "GPIO3", "GPIO4", "", "", "", "",
+	"", "#TOUCH_IRQ", "", "", "", "", "", "#PCAP_RES";
+};
+
+&gpioh {
+	gpio-line-names =
+	"", "CAM_LED", "", "USB_OTG_PWR", "", "USB_OTG_OC", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioi {
+	gpio-line-names =
+	"BKL_PWM", "", "", "", "", "", "", "",
+	"#SPI_CS0", "", "", "#SPI_CS1", "", "", "", "";
+};
+
+&gpioj {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpiok {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioz {
+	gpio-line-names =
+	"", "", "", "#SPI_CS2", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c1_ux_pins_a>;
+	pinctrl-1 = <&i2c1_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <100>;
+	i2c-scl-falling-time-ns = <7>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	rtc at 32 {
+		compatible = "epson,rx8900";
+		reg = <0x32>;
+		epson,vdet-disable;
+		trickle-diode-disable;
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c4_ux_pins_a>;
+	pinctrl-1 = <&i2c4_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	pmic: stpmic at 33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupts-extended = <&exti 0 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		status = "okay";
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				st,mask-reset;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <0>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <750000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO4 0>;
+			};
+
+			v1v8: ldo6 {
+				regulator-name = "v1v8";
+				regulator-min-microvolt = <1600000>;/* offset +200 mv ??? */
+				regulator-max-microvolt = <1600000>;/* real 1800000 */
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO6 0>;
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+			};
+
+			bst_out: boost {
+				regulator-name = "bst_out";
+				interrupts = <IT_OCP_BOOST 0>;
+			};
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+				interrupts = <IT_OCP_OTG 0>;
+				regulator-active-discharge = <1>;
+			 };
+
+			 vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				interrupts = <IT_OCP_SWOUT 0>;
+				regulator-active-discharge = <1>;
+			 };
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&m_can2 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&m_can2_ux_pins_a>;
+	pinctrl-1 = <&m_can2_ux_sleep_pins_a>;
+	status = "okay";
+};
+
+&pinctrl {
+
+	adc1_ux_ain_pins_a: adc1_ux-ain-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F',12, ANALOG)>, /* ADC1 in6 */
+				 <STM32_PINMUX('C', 3, ANALOG)>; /* ADC2 in13 */
+		};
+	};
+
+	dac_ux_ch1_pins_a: dac_ux-ch1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 4, ANALOG)>;
+		};
+	};
+
+	dac_ux_ch2_pins_a: dac_ux-ch2-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_a: rgmii-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, AF11)>; /* ETH_RGMII_TX_CTL */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <2>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('H', 7, AF11)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins4 {
+			pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_sleep_a: rgmii-ux-sleep-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+				 <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+				 <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
+				 <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
+		};
+	};
+
+	i2c1_ux_pins_a: i2c1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c1_ux_pins_sleep_a: i2c1-1 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, ANALOG)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
+		};
+	};
+
+	m_can2_ux_pins_a: m-can2_ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN1_TX */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN1_RX */
+			bias-disable;
+		};
+	};
+
+	m_can2_ux_sleep_pins_a: m_can2_ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 6, ANALOG)>, /* CAN1_TX */
+				 <STM32_PINMUX('B', 5, ANALOG)>; /* CAN1_RX */
+		};
+	};
+	pwm1_ux_pins_a: pwm1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, AF1)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, AF1)>; /* TIM1_CH2N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm1_ux_sleep_pins_a: pwm1-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, ANALOG)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, ANALOG)>; /* TIM1_CH2N */
+		};
+	};
+
+	pwm4_ux_pins_a: pwm4-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, AF2)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, AF2)>; /* TIM4_CH4 */
+			bias-disable;
+		};
+	};
+
+	pwm4_ux_sleep_pins_a: pwm4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, ANALOG)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, ANALOG)>; /* TIM4_CH4 */
+		};
+	};
+
+	pwm5_ux_pins_a: pwm5-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, AF2)>; /* TIM5_CH4 */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm5_ux_sleep_pins_a: pwm5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, ANALOG)>; /* TIM5_CH4 */
+		};
+	};
+
+	pwm17_ux_pins_a: pwm17-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, AF1)>; /* TIM17_CH1N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm17_ux_sleep_pins_a: pwm17-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, ANALOG)>; /* TIM17_CH1N */
+		};
+	};
+
+	qspi_bk1_ux_pins_a: qspi-bk1-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, AF9)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B',10, AF9)>; /* QSPI_BK1_NCS */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+	};
+
+	qspi_bk1_ux_sleep_pins_a: qspi-bk1-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, ANALOG)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, ANALOG)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, ANALOG)>, /* QSPI_BK1_IO3 */
+				 <STM32_PINMUX('B',10, ANALOG)>; /* QSPI_BK1_NCS */
+		};
+	};
+
+	qspi_clk_ux_pins_a: qspi-clk_ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, AF9)>; /* QSPI_CLK */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <3>;
+		};
+	};
+
+	qspi_clk_ux_sleep_pins_a: qspi-clk_ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, ANALOG)>; /* QSPI_CLK */
+		};
+	};
+
+	sai2a_ux_pins_a: sai2a-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, AF10)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, AF10)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, AF10)>; /* SAI2_MCLK_A */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sai2a_ux_sleep_pins_a: sai2a-1 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, ANALOG)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, ANALOG)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, ANALOG)>; /* SAI2_MCLK_A */
+		};
+	};
+
+	sdmmc1_ux_b4_pins_a: sdmmc1-ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C',10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C',11, AF12)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_od_pins_a: sdmmc1-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, AF12)>; /* SDMMC1_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+				 <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+		};
+	};
+
+	sdmmc2_ux_b4_pins_a: sdmmc2_ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_od_pins_a: sdmmc2_ux-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_sleep_pins_a: sdmmc2_ux-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
+				<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
+		};
+	};
+
+	sdmmc2_ux_d47_pins_a: sdmmc2_ux-d47-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_d47_sleep_pins_a: sdmmc2_ux-d47-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
+		};
+	};
+
+	uart4_ux_pins_a: uart4_ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+	};
+
+	uart4_ux_idle_pins_a: uart4_ux-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+		};
+
+	uart4_ux_sleep_pins_a: uart4_ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
+				<STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */
+		};
+	};
+
+	uart5_ux_pins_a: uart5-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX */
+			bias-disable;
+		};
+	};
+
+	uart5_ux_idle_pins_a: uart5-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>; /* UART5_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX*/
+			bias-disable;
+		};
+	};
+
+	uart5_ux_sleep_pins_a: uart5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>, /* UART5_TX */
+				 <STM32_PINMUX('B', 12, ANALOG)>; /* UART5_RX */
+		};
+	};
+
+	uart7_ux_pins_a: uart7-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+	};
+
+	uart7_ux_idle_pins_a: uart7-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-disable;
+		};
+	};
+
+	uart7_ux_sleep_pins_a: uart7-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>, /* USART7_RTS/DE */
+				 <STM32_PINMUX('E', 7, ANALOG)>; /* USART7_RX */
+		};
+	};
+};
+
+&pinctrl_z {
+
+	i2c4_ux_pins_a: i2c4_ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c4_ux_pins_sleep_a: i2c4-1 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
+		};
+	};
+
+	spi1_ux_pins_a: spi1_ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
+			bias-disable;
+		};
+	};
+
+	spi1_ux_sleep_pins_a: spi1_ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 0, ANALOG)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 1, ANALOG)>, /* SPI1_MISO */
+				<STM32_PINMUX('Z', 2, ANALOG)>; /* SPI1_MOSI */
+		};
+	};
+};
+
+&pwr_regulators {
+	vdd-supply = <&vdd>;
+	vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&qspi {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&qspi_clk_ux_pins_a &qspi_bk1_ux_pins_a>;
+	pinctrl-1 = <&qspi_clk_ux_sleep_pins_a &qspi_bk1_ux_sleep_pins_a>;
+	reg = <0x58003000 0x1000>, <0x70000000 0x1000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	flash0: flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <133000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&sdmmc1 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc1_ux_b4_pins_a>;
+	pinctrl-1 = <&sdmmc1_ux_b4_od_pins_a>;
+	pinctrl-2 = <&sdmmc1_ux_b4_sleep_pins_a>;
+	broken-cd;
+	st,neg-edge;
+	bus-width = <4>;
+	vmmc-supply = <&v3v3>;
+	no-1-8-v;
+	status = "okay";
+};
+
+&sdmmc2 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc2_ux_b4_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-1 = <&sdmmc2_ux_b4_od_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-2 = <&sdmmc2_ux_b4_sleep_pins_a &sdmmc2_ux_d47_sleep_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,neg-edge;
+	bus-width = <8>;
+	vmmc-supply = <&v3v3>;
+	vqmmc-supply = <&v3v3>;
+	mmc-ddr-3_3v;
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&spi1_ux_pins_a>;
+	pinctrl-1 = <&spi1_ux_sleep_pins_a>;
+	status = "okay";
+	cs-gpios = <&gpioi 8 0>, <&gpioi 11 0>, <&gpioz 3 0>;
+
+	flash: flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&timers1 {
+	/* spare dmas for other usage */
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm {
+		pinctrl-0 = <&pwm1_ux_pins_a>;
+		pinctrl-1 = <&pwm1_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 0 {
+		status = "okay";
+	};
+};
+
+&timers4 {
+	dmas = <&dmamux1 31 0x400 0x5>;
+	dma-names = "ch3";
+	status = "okay";
+
+	pwm4_4: pwm {
+		pinctrl-0 = <&pwm4_ux_pins_a>;
+		pinctrl-1 = <&pwm4_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+};
+
+&timers5 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm5_4: pwm {
+		pinctrl-0 = <&pwm5_ux_pins_a>;
+		pinctrl-1 = <&pwm5_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 4 {
+		status = "okay";
+	};
+};
+
+&timers17 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm17_4: pwm {
+		pinctrl-0 = <&pwm17_ux_pins_a>;
+		pinctrl-1 = <&pwm17_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 16 {
+		status = "okay";
+	};
+};
+
+&uart4 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
+	pinctrl-0 = <&uart4_ux_pins_a>;
+	pinctrl-1 = <&uart4_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart4_ux_idle_pins_a>;
+	pinctrl-3 = <&uart4_ux_pins_a>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart5_ux_pins_a>;
+	pinctrl-1 = <&uart5_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart5_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&uart7 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart7_ux_pins_a>;
+	pinctrl-1 = <&uart7_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart7_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&usart1 {
+	/*Muxing happens in uboot*/
+	status = "okay";
+};
+
+&usbh_ehci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbh_ohci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbotg_hs {
+	phys = <&usbphyc_port1 0>;
+	phy-names = "usb2-phy";
+	vbus-supply = <&usb_otg_vbus>;
+	status = "okay";
+};
+
+&usbphyc {
+	status = "okay";
+};
+
+&usbphyc_port0 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&usbphyc_port1 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&vrefbuf {
+	regulator-min-microvolt = <2500000>;
+	regulator-max-microvolt = <2500000>;
+	vdda-supply = <&vdd>;
+	status = "okay";
+};
-- 
2.43.0



From leo.yan at arm.com  Mon Mar 10 08:50:15 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 15:50:15 +0000
Subject: [PATCH v2 5/8] coresight: etm: Add an attribute for updating
 buffer
In-Reply-To: <d8b1cf1f-1996-4d9c-9f1a-fad556f91577@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-6-leo.yan@arm.com>
 <d8b1cf1f-1996-4d9c-9f1a-fad556f91577@arm.com>
Message-ID: <20250310155015.GG9682@e132581.arm.com>

On Mon, Mar 10, 2025 at 01:29:26PM +0000, Suzuki Kuruppassery Poulose wrote:
> Hi Leo
> 
> On 10/03/2025 10:49, Leo Yan wrote:
> > Add an attribute for updating buffer when the AUX trace is paused.  And
> > populate the value to the 'update_buf_on_pause' flag during the AUX
> > setting up.
> 
> Do we need this attribute in the uAPI ?

This uAPI allows users to perform AUX pause and resume without the long
latency caused by copying hardware trace data.

E.g., a user can specify a large AUX buffer size using option "-m,128M".
If the buffer is considered large enough to accommodate hardware trace
data for a small program, the 'update_buf_on_pause' flag can be set to
false, the copying will be deferred until the end of the perf session.

I am bias to keep this uAPI.  If you prefer to remove it, I am also
fine with that.

> Could we do this by default for
> sinks without interrupt ? This definitely improves the quality of trace
> collected for such sinks and the driver can transparently do this.

How about we dynamically set the default flag in the Perf tool?

- If users set explictly the 'update_buf_on_pause' flag, then the
  setting will be respected.
- If users don't set the flag, perf tool detects it is TRBE sinks,
  then it can set 'update_buf_on_pause' flag as false.
- If users don't set the flag, perf tool detects it is ETF/ETB/ETR
  sinks, it sets the flag as true.

Thanks,
Leo


From thomas.weissschuh at linutronix.de  Mon Mar 10 08:53:33 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Mon, 10 Mar 2025 16:53:33 +0100
Subject: [PATCH] staging: vchiq_arm: Don't use %pK through printk
Message-ID: <20250310-restricted-pointers-vchiq_arm-v1-1-dd04f208ee55@linutronix.de>

In the past %pK was preferable to %p as it would not leak raw pointer
values into the kernel log.
Since commit ad67b74d2469 ("printk: hash addresses printed with %p")
the regular %p has been improved to avoid this issue.
Furthermore, restricted pointers ("%pK") were never meant to be used
through printk(). They can still unintentionally leak raw pointers or
acquire sleeping looks in atomic contexts.

Switch to the regular pointer formatting which is safer and
easier to reason about.
There are still a few users of %pK left, but these use it through seq_file,
for which its usage is safe.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
 .../vc04_services/interface/vchiq_arm/vchiq_arm.c  |  6 +-
 .../vc04_services/interface/vchiq_arm/vchiq_core.c | 64 +++++++++++-----------
 .../vc04_services/interface/vchiq_arm/vchiq_dev.c  | 14 ++---
 3 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index a4e83e5d619bc95f1d4ba311a201bba8c05cd030..2db219e4786f236ce4c37afa86a12615a091c637 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -271,7 +271,7 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state
 		return -ENXIO;
 	}
 
-	dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %pK, phys %pad)\n",
+	dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %p, phys %pad)\n",
 		vchiq_slot_zero, &slot_phys);
 
 	mutex_init(&drv_mgmt->connected_mutex);
@@ -368,7 +368,7 @@ void free_bulk_waiter(struct vchiq_instance *instance)
 				 &instance->bulk_waiter_list, list) {
 		list_del(&waiter->list);
 		dev_dbg(instance->state->dev,
-			"arm: bulk_waiter - cleaned up %pK for pid %d\n",
+			"arm: bulk_waiter - cleaned up %p for pid %d\n",
 			waiter, waiter->pid);
 		kfree(waiter);
 	}
@@ -622,7 +622,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
 		mutex_lock(&instance->bulk_waiter_list_mutex);
 		list_add(&waiter->list, &instance->bulk_waiter_list);
 		mutex_unlock(&instance->bulk_waiter_list_mutex);
-		dev_dbg(instance->state->dev, "arm: saved bulk_waiter %pK for pid %d\n",
+		dev_dbg(instance->state->dev, "arm: saved bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 	}
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 8d5795db4f39f8003310a54ba369367c95e6c079..52126d11e57cced24f10efadd1e79d8378031ec2 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -470,7 +470,7 @@ make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
 		cb_userdata = bulk->cb_userdata;
 	}
 
-	dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n",
+	dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %p, %p %p)\n",
 		service->state->id, service->localport, reason_names[reason],
 		header, cb_data, cb_userdata);
 	status = service->base.callback(service->instance, reason, header, service->handle,
@@ -778,7 +778,7 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
 		complete(&quota->quota_event);
 	} else if (count == 0) {
 		dev_err(state->dev,
-			"core: service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n",
+			"core: service %d message_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n",
 			port, quota->message_use_count, header, msgid,
 			header->msgid, header->size);
 		WARN(1, "invalid message use count\n");
@@ -799,11 +799,11 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
 			 * it has dropped below its quota
 			 */
 			complete(&quota->quota_event);
-			dev_dbg(state->dev, "core: %d: pfq:%d %x@%pK - slot_use->%d\n",
+			dev_dbg(state->dev, "core: %d: pfq:%d %x@%p - slot_use->%d\n",
 				state->id, port, header->size, header, count - 1);
 		} else {
 			dev_err(state->dev,
-				"core: service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n",
+				"core: service %d slot_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n",
 				port, count, header, msgid, header->msgid, header->size);
 			WARN(1, "bad slot use count\n");
 		}
@@ -845,7 +845,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found,
 		 */
 		rmb();
 
-		dev_dbg(state->dev, "core: %d: pfq %d=%pK %x %x\n",
+		dev_dbg(state->dev, "core: %d: pfq %d=%p %x %x\n",
 			state->id, slot_index, data, local->slot_queue_recycle,
 			slot_queue_available);
 
@@ -868,7 +868,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found,
 			pos += calc_stride(header->size);
 			if (pos > VCHIQ_SLOT_SIZE) {
 				dev_err(state->dev,
-					"core: pfq - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n",
+					"core: pfq - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n",
 					pos, header, msgid, header->msgid, header->size);
 				WARN(1, "invalid slot position\n");
 			}
@@ -1060,7 +1060,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
 		int tx_end_index;
 		int slot_use_count;
 
-		dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n",
 			state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 			VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 
@@ -1117,7 +1117,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
 		VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
 		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
 	} else {
-		dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n",
 			state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 			VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 		if (size != 0) {
@@ -1204,7 +1204,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
 				state->id, oldmsgid);
 	}
 
-	dev_dbg(state->dev, "sync: %d: qms %s@%pK,%x (%d->%d)\n",
+	dev_dbg(state->dev, "sync: %d: qms %s@%p,%x (%d->%d)\n",
 		state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 		VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 
@@ -1539,7 +1539,7 @@ create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
 	pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
 				      GFP_KERNEL);
 
-	dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
+	dev_dbg(instance->state->dev, "arm: %p\n", pagelist);
 
 	if (!pagelist)
 		return NULL;
@@ -1692,7 +1692,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel
 	unsigned int num_pages = pagelistinfo->num_pages;
 	unsigned int cache_line_size;
 
-	dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
+	dev_dbg(instance->state->dev, "arm: %p, %d\n", pagelistinfo->pagelist, actual);
 
 	drv_mgmt = dev_get_drvdata(instance->state->dev);
 
@@ -1849,7 +1849,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
 
 	payload = (struct vchiq_open_payload *)header->data;
 	fourcc = payload->fourcc;
-	dev_dbg(state->dev, "core: %d: prs OPEN@%pK (%d->'%p4cc')\n",
+	dev_dbg(state->dev, "core: %d: prs OPEN@%p (%d->'%p4cc')\n",
 		state->id, header, localport, &fourcc);
 
 	service = get_listening_service(state, fourcc);
@@ -1976,14 +1976,14 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			service = get_connected_service(state, remoteport);
 			if (service)
 				dev_warn(state->dev,
-					 "core: %d: prs %s@%pK (%d->%d) - found connected service %d\n",
+					 "core: %d: prs %s@%p (%d->%d) - found connected service %d\n",
 					 state->id, msg_type_str(type), header,
 					 remoteport, localport, service->localport);
 		}
 
 		if (!service) {
 			dev_err(state->dev,
-				"core: %d: prs %s@%pK (%d->%d) - invalid/closed service %d\n",
+				"core: %d: prs %s@%p (%d->%d) - invalid/closed service %d\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, localport);
 			goto skip_message;
@@ -2003,7 +2003,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 
 	if (((unsigned long)header & VCHIQ_SLOT_MASK) +
 	    calc_stride(size) > VCHIQ_SLOT_SIZE) {
-		dev_err(state->dev, "core: header %pK (msgid %x) - size %x too big for slot\n",
+		dev_err(state->dev, "core: header %K (msgid %x) - size %x too big for slot\n",
 			header, (unsigned int)msgid, (unsigned int)size);
 		WARN(1, "oversized for slot\n");
 	}
@@ -2022,7 +2022,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			service->peer_version = payload->version;
 		}
 		dev_dbg(state->dev,
-			"core: %d: prs OPENACK@%pK,%x (%d->%d) v:%d\n",
+			"core: %d: prs OPENACK@%p,%x (%d->%d) v:%d\n",
 			state->id, header, size, remoteport, localport,
 			service->peer_version);
 		if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
@@ -2037,7 +2037,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 	case VCHIQ_MSG_CLOSE:
 		WARN_ON(size); /* There should be no data */
 
-		dev_dbg(state->dev, "core: %d: prs CLOSE@%pK (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: prs CLOSE@%p (%d->%d)\n",
 			state->id, header, remoteport, localport);
 
 		mark_service_closing_internal(service, 1);
@@ -2049,7 +2049,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			&service->base.fourcc, service->localport, service->remoteport);
 		break;
 	case VCHIQ_MSG_DATA:
-		dev_dbg(state->dev, "core: %d: prs DATA@%pK,%x (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: prs DATA@%p,%x (%d->%d)\n",
 			state->id, header, size, remoteport, localport);
 
 		if ((service->remoteport == remoteport) &&
@@ -2069,7 +2069,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		}
 		break;
 	case VCHIQ_MSG_CONNECT:
-		dev_dbg(state->dev, "core: %d: prs CONNECT@%pK\n",
+		dev_dbg(state->dev, "core: %d: prs CONNECT@%p\n",
 			state->id, header);
 		state->version_common =	((struct vchiq_slot_zero *)
 					 state->slot_data)->version;
@@ -2102,7 +2102,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			if ((int)(queue->remote_insert -
 				queue->local_insert) >= 0) {
 				dev_err(state->dev,
-					"core: %d: prs %s@%pK (%d->%d) unexpected (ri=%d,li=%d)\n",
+					"core: %d: prs %s@%p (%d->%d) unexpected (ri=%d,li=%d)\n",
 					state->id, msg_type_str(type), header, remoteport,
 					localport, queue->remote_insert, queue->local_insert);
 				mutex_unlock(&service->bulk_mutex);
@@ -2120,7 +2120,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			bulk->actual = *(int *)header->data;
 			queue->remote_insert++;
 
-			dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n",
+			dev_dbg(state->dev, "core: %d: prs %s@%p (%d->%d) %x@%pad\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, bulk->actual, &bulk->dma_addr);
 
@@ -2140,12 +2140,12 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		}
 		break;
 	case VCHIQ_MSG_PADDING:
-		dev_dbg(state->dev, "core: %d: prs PADDING@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs PADDING@%p,%x\n",
 			state->id, header, size);
 		break;
 	case VCHIQ_MSG_PAUSE:
 		/* If initiated, signal the application thread */
-		dev_dbg(state->dev, "core: %d: prs PAUSE@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs PAUSE@%p,%x\n",
 			state->id, header, size);
 		if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) {
 			dev_err(state->dev, "core: %d: PAUSE received in state PAUSED\n",
@@ -2162,7 +2162,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED);
 		break;
 	case VCHIQ_MSG_RESUME:
-		dev_dbg(state->dev, "core: %d: prs RESUME@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs RESUME@%p,%x\n",
 			state->id, header, size);
 		/* Release the slot mutex */
 		mutex_unlock(&state->slot_mutex);
@@ -2179,7 +2179,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		break;
 
 	default:
-		dev_err(state->dev, "core: %d: prs invalid msgid %x@%pK,%x\n",
+		dev_err(state->dev, "core: %d: prs invalid msgid %x@%p,%x\n",
 			state->id, msgid, header, size);
 		WARN(1, "invalid message\n");
 		break;
@@ -2400,7 +2400,7 @@ sync_func(void *v)
 
 		if (!service) {
 			dev_err(state->dev,
-				"sync: %d: sf %s@%pK (%d->%d) - invalid/closed service %d\n",
+				"sync: %d: sf %s@%p (%d->%d) - invalid/closed service %d\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, localport);
 			release_message_sync(state, header);
@@ -2422,7 +2422,7 @@ sync_func(void *v)
 					header->data;
 				service->peer_version = payload->version;
 			}
-			dev_err(state->dev, "sync: %d: sf OPENACK@%pK,%x (%d->%d) v:%d\n",
+			dev_err(state->dev, "sync: %d: sf OPENACK@%p,%x (%d->%d) v:%d\n",
 				state->id, header, size, remoteport, localport,
 				service->peer_version);
 			if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
@@ -2435,7 +2435,7 @@ sync_func(void *v)
 			break;
 
 		case VCHIQ_MSG_DATA:
-			dev_dbg(state->dev, "sync: %d: sf DATA@%pK,%x (%d->%d)\n",
+			dev_dbg(state->dev, "sync: %d: sf DATA@%p,%x (%d->%d)\n",
 				state->id, header, size, remoteport, localport);
 
 			if ((service->remoteport == remoteport) &&
@@ -2449,7 +2449,7 @@ sync_func(void *v)
 			break;
 
 		default:
-			dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%pK,%x\n",
+			dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%p,%x\n",
 				state->id, msgid, header, size);
 			release_message_sync(state, header);
 			break;
@@ -2926,13 +2926,13 @@ release_service_messages(struct vchiq_service *service)
 			int port = VCHIQ_MSG_DSTPORT(msgid);
 
 			if ((port == service->localport) && (msgid & VCHIQ_MSGID_CLAIMED)) {
-				dev_dbg(state->dev, "core:  fsi - hdr %pK\n", header);
+				dev_dbg(state->dev, "core:  fsi - hdr %p\n", header);
 				release_slot(state, slot_info, header, NULL);
 			}
 			pos += calc_stride(header->size);
 			if (pos > VCHIQ_SLOT_SIZE) {
 				dev_err(state->dev,
-					"core: fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n",
+					"core: fsi - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n",
 					pos, header, msgid, header->msgid, header->size);
 				WARN(1, "invalid slot position\n");
 			}
@@ -3091,7 +3091,7 @@ vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service,
 	 */
 	wmb();
 
-	dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n",
+	dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %p\n",
 		state->id, service->localport, service->remoteport,
 		dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data);
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
index 454f4341650306654d1365653ab3b570795f3331..3b20ba5c736221ce1cacfc9ce86eca623382a30b 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -270,7 +270,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
 		}
 	} else {
 		dev_err(service->state->dev,
-			"arm: header %pK: bufsize %x < size %x\n",
+			"arm: header %p: bufsize %x < size %x\n",
 			header, args->bufsize, header->size);
 		WARN(1, "invalid size\n");
 		ret = -EMSGSIZE;
@@ -328,7 +328,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
 			ret = -ESRCH;
 			goto out;
 		}
-		dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n",
+		dev_dbg(service->state->dev, "arm: found bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 
 		status = vchiq_bulk_xfer_waiting(instance, args->handle,
@@ -366,7 +366,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
 		mutex_lock(&instance->bulk_waiter_list_mutex);
 		list_add(&waiter->list, &instance->bulk_waiter_list);
 		mutex_unlock(&instance->bulk_waiter_list_mutex);
-		dev_dbg(service->state->dev, "arm: saved bulk_waiter %pK for pid %d\n",
+		dev_dbg(service->state->dev, "arm: saved bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 
 		ret = put_user(mode_waiting, mode);
@@ -512,7 +512,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
 			/* This must be a VCHIQ-style service */
 			if (args->msgbufsize < msglen) {
 				dev_err(service->state->dev,
-					"arm: header %pK: msgbufsize %x < msglen %x\n",
+					"arm: header %p: msgbufsize %x < msglen %x\n",
 					header, args->msgbufsize, msglen);
 				WARN(1, "invalid message size\n");
 				if (ret == 0)
@@ -588,7 +588,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	long ret = 0;
 	int i, rc;
 
-	dev_dbg(instance->state->dev, "arm: instance %pK, cmd %s, arg %lx\n", instance,
+	dev_dbg(instance->state->dev, "arm: instance %p, cmd %s, arg %lx\n", instance,
 		((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
 		ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
 
@@ -874,12 +874,12 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	if (!status && (ret < 0) && (ret != -EINTR) && (ret != -EWOULDBLOCK)) {
 		dev_dbg(instance->state->dev,
-			"arm: ioctl instance %pK, cmd %s -> status %d, %ld\n",
+			"arm: ioctl instance %p, cmd %s -> status %d, %ld\n",
 			instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
 			ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret);
 	} else {
 		dev_dbg(instance->state->dev,
-			"arm: ioctl instance %pK, cmd %s -> status %d\n, %ld\n",
+			"arm: ioctl instance %p, cmd %s -> status %d\n, %ld\n",
 			instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
 			ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret);
 	}

---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250310-restricted-pointers-vchiq_arm-1801bf8d634b

Best regards,
-- 
Thomas Wei?schuh <thomas.weissschuh at linutronix.de>



From antonin.godard at bootlin.com  Mon Mar 10 08:56:07 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 16:56:07 +0100
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>

Add support for the Variscite i.MX6UL VAR-SOM-MX6UL and the Variscite
Concerto carrier board.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 0db2cbd7891ffb361e0ac60fe6be66e381b2a8f4..a8f8cb845a2085eb13594adacf33f372185e8b0b 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -688,6 +688,12 @@ properties:
           - const: phytec,imx6ul-pcl063   # PHYTEC phyCORE-i.MX 6UL
           - const: fsl,imx6ul
 
+      - description: i.MX6UL Variscite VAR-SOM-MX6 Boards
+        items:
+          - const: variscite,mx6ulconcerto
+          - const: variscite,var-som-imx6ul
+          - const: fsl,imx6ul
+
       - description: Kontron BL i.MX6UL (N631X S) Board
         items:
           - const: kontron,bl-imx6ul       # Kontron BL i.MX6UL Carrier Board

-- 
2.47.0



From conor at kernel.org  Mon Mar 10 09:37:25 2025
From: conor at kernel.org (Conor Dooley)
Date: Mon, 10 Mar 2025 16:37:25 +0000
Subject: [PATCH net-next 4/7] riscv: dts: starfive: remove
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <E1trIAF-005ntc-S5@rmk-PC.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk>
 <E1trIAF-005ntc-S5@rmk-PC.armlinux.org.uk>
Message-ID: <20250310-climatic-monorail-f06784705219@spud>

On Sun, Mar 09, 2025 at 03:02:03PM +0000, Russell King (Oracle) wrote:
> Whether the MII transmit clock can be stopped is primarily a property
> of the PHY (there is a capability bit that should be checked first.)
> Whether the MAC is capable of stopping the transmit clock is a separate
> issue, but this is already handled by the core DesignWare MAC code.
> 
> As commit "net: stmmac: starfive: use PHY capability for TX clock stop"
> adds the flag to use the PHY capability, remove the DT property that is
> now unecessary.
> 
> Cc: Samin Guo <samin.guo at starfivetech.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/b9632f84/attachment.sig>

From suzuki.poulose at arm.com  Mon Mar 10 09:37:44 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 16:37:44 +0000
Subject: [PATCH v2 5/8] coresight: etm: Add an attribute for updating
 buffer
In-Reply-To: <20250310155015.GG9682@e132581.arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-6-leo.yan@arm.com>
 <d8b1cf1f-1996-4d9c-9f1a-fad556f91577@arm.com>
 <20250310155015.GG9682@e132581.arm.com>
Message-ID: <3f4354e7-e74b-4ce9-b0c7-4be103cbc94d@arm.com>

On 10/03/2025 15:50, Leo Yan wrote:
> On Mon, Mar 10, 2025 at 01:29:26PM +0000, Suzuki Kuruppassery Poulose wrote:
>> Hi Leo
>>
>> On 10/03/2025 10:49, Leo Yan wrote:
>>> Add an attribute for updating buffer when the AUX trace is paused.  And
>>> populate the value to the 'update_buf_on_pause' flag during the AUX
>>> setting up.
>>
>> Do we need this attribute in the uAPI ?
> 
> This uAPI allows users to perform AUX pause and resume without the long
> latency caused by copying hardware trace data.
> 
> E.g., a user can specify a large AUX buffer size using option "-m,128M".
> If the buffer is considered large enough to accommodate hardware trace
> data for a small program, the 'update_buf_on_pause' flag can be set to
> false, the copying will be deferred until the end of the perf session.
> 
> I am bias to keep this uAPI.  If you prefer to remove it, I am also
> fine with that.
> 
>> Could we do this by default for
>> sinks without interrupt ? This definitely improves the quality of trace
>> collected for such sinks and the driver can transparently do this.
> 
> How about we dynamically set the default flag in the Perf tool?
> 
> - If users set explictly the 'update_buf_on_pause' flag, then the
>    setting will be respected.
> - If users don't set the flag, perf tool detects it is TRBE sinks,
>    then it can set 'update_buf_on_pause' flag as false.

Not really possible. There could be systems with mixed sinks. e.g.  TRBE
for some CPU and ETR for others (say due to a non-functioning TRBE).

> - If users don't set the flag, perf tool detects it is ETF/ETB/ETR
>    sinks, it sets the flag as true.

And in the cases above, perf event cannot run on all the CPUs, because
some sinks don't support it.

Why do we need a flag, when the effect is not user (read, perf decoder)
  visible and at the same time improves some scenarios (read non-TRBE 
cases) ?

I would say, let the driver always update on pause, depending on the
sink.

Suzuki


> 
> Thanks,
> Leo



From conor at kernel.org  Mon Mar 10 09:38:52 2025
From: conor at kernel.org (Conor Dooley)
Date: Mon, 10 Mar 2025 16:38:52 +0000
Subject: [PATCH 1/3] dt-bindings: i2c: i2c-rk3x: Add compatible string
 for RK3528
In-Reply-To: <20250309070603.35254-2-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
 <20250309070603.35254-2-ziyao@disroot.org>
Message-ID: <20250310-tidy-passable-434c473861a6@spud>

On Sun, Mar 09, 2025 at 07:06:01AM +0000, Yao Zi wrote:
> Document I2C controllers integrated in RK3528, which are compatible with
> the RK3399 variant.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
> index a9dae5b52f28..259770b1aa08 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml
> @@ -37,6 +37,7 @@ properties:
>                - rockchip,px30-i2c
>                - rockchip,rk3308-i2c
>                - rockchip,rk3328-i2c
> +              - rockchip,rk3528-i2c
>                - rockchip,rk3568-i2c
>                - rockchip,rk3576-i2c
>                - rockchip,rk3588-i2c
> -- 
> 2.48.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/697d3c49/attachment.sig>

From antonin.godard at bootlin.com  Mon Mar 10 09:39:47 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 17:39:47 +0100
Subject: [PATCH v4 0/3] Add Variscite i.MX6UL SoM and Concerto board
 support
Message-ID: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>

Add support for the i.MX6UL Variscite SoM (VAR-SOM-6UL) and the
Variscite Concerto Carrier Board.

I tested this with a VAR-SOM-6UL_G2_700C_512R_8N_IT_REV1.3A (one variant
of this SoM), meaning I couldn't test all of the possible options of the
SoM - so this device tree includes partial support for it.

These are based on the 5.15 Variscite kernel fork but adapted for
mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
Changes in v4:
- Add missing trailer on first patch ("Acked-by: Conor Dooley
  <conor.dooley at microchip.com>").
- Link to v3: https://lore.kernel.org/r/20250310-varsom6ul-concerto-dts-v3-0-551e60713523 at bootlin.com

Changes in v3:
- Reviews from Shawn:
  - Fix alphabetical order of nodes and pinctrl entries.
  - Fix rmii-ref-clk label (remove "-grp" added by mistake).
  - Fix order of properties for eth nodes.
  - Convert deprecated fec properties to eth properties.
- Link to v2: https://lore.kernel.org/r/20250127-varsom6ul-concerto-dts-v2-0-4dac29256989 at bootlin.com

Changes in v2:
- Reviews from Krzysztof:
  - Use imperative mood in commit descriptions.
  - Remove backlight node as I am unable to test it.
  - Rename gpled2 node to led-0, and set function, color and label for
    it.
  - Remove unnecessary comment "DS1337 RTC module".
- Rename binding "variscite,mx6concerto" to "variscite,mx6ulconcerto"
  since this is for the VAR-SOM-6UL mounted on the Concerto.
- Remove pinctrl_ft5x06_ts_gpio iomuxc node, unused.
- Link to v1: https://lore.kernel.org/r/20250121-varsom6ul-concerto-dts-v1-0-eb349acf0ac6 at bootlin.com

---
Antonin Godard (3):
      dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and Concerto board
      ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM support
      ARM: dts: imx6ul: Add Variscite Concerto board support

 Documentation/devicetree/bindings/arm/fsl.yaml     |   6 +
 arch/arm/boot/dts/nxp/imx/Makefile                 |   1 +
 .../boot/dts/nxp/imx/imx6ul-var-som-concerto.dts   | 320 +++++++++++++++++++++
 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi      | 233 +++++++++++++++
 4 files changed, 560 insertions(+)
---
base-commit: 66683f3b2661643f694607283ee8f01b7a934c83
change-id: 20250120-varsom6ul-concerto-dts-a08be2a6219b

Best regards,
-- 
Antonin Godard <antonin.godard at bootlin.com>



From antonin.godard at bootlin.com  Mon Mar 10 09:39:48 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 17:39:48 +0100
Subject: [PATCH v4 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v4-1-6034fda6ec64@bootlin.com>

Add support for the Variscite i.MX6UL VAR-SOM-MX6UL and the Variscite
Concerto carrier board.

Acked-by: Conor Dooley <conor.dooley at microchip.com>
Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 0db2cbd7891ffb361e0ac60fe6be66e381b2a8f4..a8f8cb845a2085eb13594adacf33f372185e8b0b 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -688,6 +688,12 @@ properties:
           - const: phytec,imx6ul-pcl063   # PHYTEC phyCORE-i.MX 6UL
           - const: fsl,imx6ul
 
+      - description: i.MX6UL Variscite VAR-SOM-MX6 Boards
+        items:
+          - const: variscite,mx6ulconcerto
+          - const: variscite,var-som-imx6ul
+          - const: fsl,imx6ul
+
       - description: Kontron BL i.MX6UL (N631X S) Board
         items:
           - const: kontron,bl-imx6ul       # Kontron BL i.MX6UL Carrier Board

-- 
2.47.0



From antonin.godard at bootlin.com  Mon Mar 10 09:39:49 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 17:39:49 +0100
Subject: [PATCH v4 2/3] ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM
 support
In-Reply-To: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v4-2-6034fda6ec64@bootlin.com>

Add support for the Variscite VAR_SOM-MX6UL SoM with:

- NXP i.MX6 UltraLite SoC
- 128?1024 MB DDR3L
- 8?128 GB eMMC
- 128?512 MB SLC NAND
- Camera Interface
- LVDS / Parallel RGB interfaces (not configured)
- Touch controller (not configured)
- Ethernet RMII interface (not configured)
- On-SoM Wi-Fi/Bluetooth with CYW43353 on SDIO Module (not configured)
- SD/MMC/SDIO interface
- USB Host + USB OTG interface
- I2C interfaces
- SPI interfaces
- PCI-Express 2.0 interface
- on-SoM Audio Codec (not configured)
- S/PDIF interface (not configured)

Product website: https://www.variscite.com/product/system-on-module-som/cortex-a7/var-som-6ul-nxp-imx6ul-6ull-6ulz

Support is handled with a SoM-centric dtsi exporting the default
interfaces along the default pinmuxing to be enabled by the board dts
file.

I tested this on a VAR-SOM-6UL_G2_700C_512R_8N_IT_REV1.3A, which is why
some of the features above are mentioned as "not configured" (I couldn't
test them).

This file is based on the one provided by Variscite on their own kernel,
but adapted for mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi | 233 ++++++++++++++++++++++++++
 1 file changed, 233 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..4e536e0252def06a7660c29b7231169e3aa38dba
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite VAR-SOM-MX6UL Module
+ *
+ * Copyright 2019 Variscite Ltd.
+ * Copyright 2025 Bootlin
+ */
+
+/dts-v1/;
+
+#include "imx6ul.dtsi"
+#include <dt-bindings/clock/imx6ul-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Variscite VAR-SOM-MX6UL module";
+	compatible = "variscite,var-som-imx6ul", "fsl,imx6ul";
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	reg_gpio_dvfs: reg-gpio-dvfs {
+		compatible = "regulator-gpio";
+		regulator-min-microvolt = <1300000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-name = "gpio_dvfs";
+		regulator-type = "voltage";
+		gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+		states = <1300000 0x1
+			  1400000 0x0>;
+	};
+
+	rmii_ref_clk: rmii-ref-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+		clock-output-names = "rmii-ref";
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+	dc-supply = <&reg_gpio_dvfs>;
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>, <&pinctrl_enet1_gpio>, <&pinctrl_enet1_mdio>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <1>;
+			clocks = <&rmii_ref_clk>;
+			clock-names = "rmii-ref";
+			reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <100000>;
+			micrel,led-mode = <1>;
+			micrel,rmii-reference-clock-select-25-mhz = <1>;
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+		>;
+	};
+
+	pinctrl_enet1_gpio: enet1-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x1b0b0 /* fec1 reset */
+		>;
+	};
+
+	pinctrl_enet1_mdio: enet1-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO06__ENET1_MDIO	0x1b0b0
+			MX6UL_PAD_GPIO1_IO07__ENET1_MDC		0x1b0b0
+		>;
+	};
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x1b0b0	/* BT Enable */
+			MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06	0x03029	/* WLAN Enable */
+		>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
+			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
+			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
+			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
+			MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
+		>;
+	};
+
+	pinctrl_tsc: tscgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__GPIO1_IO01	0xb0
+			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0xb0
+			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0xb0
+			MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0xb0
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
+			MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS	0x1b0b1
+			MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x10069
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x17059
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x17059
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x17059
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x17059
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x17059
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x17059
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x17059
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x17059
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x17059
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x100b9
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x170b9
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x170b9
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x170b9
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x170b9
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x170b9
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x170b9
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x170b9
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x170b9
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x100f9
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x170f9
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x170f9
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x170f9
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x170f9
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x170f9
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4	0x170f9
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5	0x170f9
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6	0x170f9
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7	0x170f9
+		>;
+	};
+};
+
+&pxp {
+	status = "okay";
+};
+
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+			  <&clks IMX6UL_CLK_SAI2>;
+	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>, <12288000>;
+	fsl,sai-mclk-direction-output;
+	status = "okay";
+};
+
+&snvs_poweroff {
+	status = "okay";
+};
+
+&tsc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_tsc>;
+	xnur-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+	measure-delay-time = <0xffff>;
+	pre-charge-time = <0xfff>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+	bus-width = <8>;
+	no-1-8-v;
+	non-removable;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};

-- 
2.47.0



From antonin.godard at bootlin.com  Mon Mar 10 09:39:50 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Mon, 10 Mar 2025 17:39:50 +0100
Subject: [PATCH v4 3/3] ARM: dts: imx6ul: Add Variscite Concerto board
 support
In-Reply-To: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
Message-ID: <20250310-varsom6ul-concerto-dts-v4-3-6034fda6ec64@bootlin.com>

Add support for the Variscite Concerto Carrier Board with:

- LVDS interface for the VLCD-CAP-GLD-LVDS 7" LCD 800 x 480 touch
  display (not configured)
- USB Host + USB OTG Connector
- 10/100 Mbps Ethernet
- miniPCI-Express slot
- SD Card connector
- Audio Headphone/Line In jack connectors
- S-ATA
- On-board DMIC

Product Page: https://www.variscite.com/product/single-board-computers/concerto-board

This file is based on the one provided by Variscite on their own kernel,
but adapted for mainline.

Signed-off-by: Antonin Godard <antonin.godard at bootlin.com>
---
 arch/arm/boot/dts/nxp/imx/Makefile                 |   1 +
 .../boot/dts/nxp/imx/imx6ul-var-som-concerto.dts   | 320 +++++++++++++++++++++
 2 files changed, 321 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 39a153536d2a2b8f75b5fbe4332660f89442064a..94c9bc94cc8e2daa1fb3b5686b0b58db1f6678b6 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -329,6 +329,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
 	imx6ul-tx6ul-0010.dtb \
 	imx6ul-tx6ul-0011.dtb \
 	imx6ul-tx6ul-mainboard.dtb \
+	imx6ul-var-som-concerto.dtb \
 	imx6ull-14x14-evk.dtb \
 	imx6ull-colibri-aster.dtb \
 	imx6ull-colibri-emmc-aster.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts
new file mode 100644
index 0000000000000000000000000000000000000000..9ff3b374a2b31ceb7c4974adf86c2f036c78d4d5
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite MX6 Concerto Carrier board with the VAR-SOM-MX6UL
+ * Variscite SoM mounted on it
+ *
+ * Copyright 2019 Variscite Ltd.
+ * Copyright 2025 Bootlin
+ */
+
+#include "imx6ul-var-som.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "Variscite VAR-SOM-MX6UL Concerto Board";
+	compatible = "variscite,mx6ulconcerto", "variscite,var-som-imx6ul", "fsl,imx6ul";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_key_back>, <&pinctrl_gpio_key_wakeup>;
+
+		key-back {
+			gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		key-wakeup {
+			gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WAKEUP>;
+			wakeup-source;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led-0 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "gpled2";
+			gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&fec1 {
+	status = "disabled";
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2>, <&pinctrl_enet2_gpio>, <&pinctrl_enet2_mdio>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy at 3 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <3>;
+			clocks = <&rmii_ref_clk>;
+			clock-names = "rmii-ref";
+			reset-gpios = <&gpio5 5 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <100000>;
+			micrel,led-mode = <0>;
+			micrel,rmii-reference-clock-select-25-mhz = <1>;
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	rtc at 68 {
+		/*
+		 * To actually use this interrupt
+		 * connect pins J14.8 & J14.10 on the Concerto-Board.
+		 */
+		compatible = "dallas,ds1337";
+		reg = <0x68>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_rtc>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+&iomuxc {
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
+		>;
+	};
+
+	pinctrl_enet2_gpio: enet2-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05	0x1b0b0 /* fec2 reset */
+		>;
+	};
+
+	pinctrl_enet2_mdio: enet2-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
+			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
+			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
+		>;
+	};
+
+	pinctrl_gpio_key_back: gpio-key-backgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_CE1_B__GPIO4_IO14	0x17059
+		>;
+	};
+
+	pinctrl_gpio_leds: gpio-ledsgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25	0x1b0b0	/* GPLED2 */
+		>;
+	};
+
+	pinctrl_gpio_key_wakeup: gpio-keys-wakeupgrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x17059
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_PIXCLK__I2C1_SCL		0x4001b8b0
+			MX6UL_PAD_CSI_MCLK__I2C1_SDA		0x4001b8b0
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO05__PWM4_OUT		0x110b0
+		>;
+	};
+
+	pinctrl_rtc: rtcgrp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_MOD__GPIO1_IO10		0x1b0b0 /* RTC alarm IRQ */
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA00__UART5_DCE_TX	0x1b0b1
+			MX6UL_PAD_CSI_DATA01__UART5_DCE_RX	0x1b0b1
+			MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS	0x1b0b1
+			MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_usb_otg1_id: usbotg1idgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_TX_DATA__ANATOP_OTG1_ID	0x17059
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x17059
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x17059
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x17059
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x17059
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x17059
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x17059
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x170b9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x100b9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x170b9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x170b9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x170b9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x170f9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x100f9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x170f9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x170f9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x170f9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x170f9
+		>;
+	};
+
+	pinctrl_usdhc1_gpio: usdhc1-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO00__GPIO1_IO00	0x1b0b1 /* CD */
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__WDOG1_WDOG_B	0x78b0
+		>;
+	};
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&snvs_pwrkey {
+	status = "disabled";
+};
+
+&snvs_rtc {
+	status = "disabled";
+};
+
+&tsc {
+	/*
+	 * Conflics with wdog1 ext-reset-output & SD CD pins,
+	 * so we keep it disabled by default.
+	 */
+	status = "disabled";
+};
+
+/* Console UART */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+/* ttymxc4 UART */
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb_otg1_id>;
+	dr_mode = "otg";
+	disable-over-current;
+	srp-disable;
+	hnp-disable;
+	adp-disable;
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_gpio>;
+	cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	/*
+	 * To actually use ext-reset-output
+	 * connect pins J17.3 & J17.8 on the Concerto-Board
+	 */
+	fsl,ext-reset-output;
+};

-- 
2.47.0



From helgaas at kernel.org  Mon Mar 10 09:41:22 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 10 Mar 2025 11:41:22 -0500
Subject: [PATCH hyperv-next v5 11/11] PCI: hv: Get vPCI MSI IRQ domain
 from DeviceTree
In-Reply-To: <20250307220304.247725-12-romank@linux.microsoft.com>
Message-ID: <20250310164122.GA551965@bhelgaas>

On Fri, Mar 07, 2025 at 02:03:03PM -0800, Roman Kisel wrote:
> The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
> arm64. It won't be able to do that in the VTL mode where only DeviceTree
> can be used.
> 
> Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
> case, too.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>

A couple minor comments below, but I don't have any objection to this,
so if it's OK with the pci-hyperv.c folks, it's OK with me.

> +#ifdef CONFIG_OF
> +
> +static struct irq_domain *hv_pci_of_irq_domain_parent(void)
> +{
> +	struct device_node *parent;
> +	struct irq_domain *domain;
> +
> +	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
> +	domain = NULL;
> +	if (parent) {
> +		domain = irq_find_host(parent);
> +		of_node_put(parent);
> +	}
> +
> +	return domain;

I think this would be a little simpler as:

  parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
  if (!parent)
    return NULL;

  domain = irq_find_host(parent);
  of_node_put(parent);
  return domain;

> +}
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +
> +static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
> +{
> +	struct irq_domain *domain;
> +	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
> +
> +	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
> +		return NULL;
> +	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
> +	if (!gsi_domain_disp_fn)
> +		return NULL;
> +	domain = irq_find_matching_fwnode(gsi_domain_disp_fn(0),
> +				     DOMAIN_BUS_ANY);
> +
> +	if (!domain)
> +		return NULL;
> +
> +	return domain;

  if (!domain)
    return NULL;

  return domain;

is the same as:

  return domain;

or even just:

  return irq_find_matching_fwnode(gsi_domain_disp_fn(0), DOMAIN_BUS_ANY);

> +}


From romank at linux.microsoft.com  Mon Mar 10 09:42:15 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 09:42:15 -0700
Subject: [PATCH hyperv-next v5 06/11] arm64, x86: hyperv: Report the VTL
 the system boots in
In-Reply-To: <Z84yyAqkqJ2ZyAd-@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-7-romank@linux.microsoft.com>
 <Z84yyAqkqJ2ZyAd-@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
Message-ID: <2342dda1-2976-4506-ab68-640739a1bd5b@linux.microsoft.com>



On 3/9/2025 5:31 PM, Wei Liu wrote:
> On Fri, Mar 07, 2025 at 02:02:58PM -0800, Roman Kisel wrote:
>> The hyperv guest code might run in various Virtual Trust Levels.
>>
>> Report the level when the kernel boots in the non-default (0)
>> one.
>>
>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
>> ---
>>   arch/arm64/hyperv/mshyperv.c | 2 ++
>>   arch/x86/hyperv/hv_vtl.c     | 2 +-
>>   2 files changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
>> index a7db03f5413d..3bc16dbee758 100644
>> --- a/arch/arm64/hyperv/mshyperv.c
>> +++ b/arch/arm64/hyperv/mshyperv.c
>> @@ -108,6 +108,8 @@ static int __init hyperv_init(void)
>>   	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
>>   		hv_get_partition_id();
>>   	ms_hyperv.vtl = get_vtl();
>> +	if (ms_hyperv.vtl > 0) /* non default VTL */
> 
> "non-default".
> 

Thanks, will fix that!

>> +		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
>>   
>>   	ms_hyperv_late_init();
>>   
>> diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
>> index 4e1b1e3b5658..c21bee7e8ff3 100644
>> --- a/arch/x86/hyperv/hv_vtl.c
>> +++ b/arch/x86/hyperv/hv_vtl.c
>> @@ -24,7 +24,7 @@ static bool __init hv_vtl_msi_ext_dest_id(void)
>>   
>>   void __init hv_vtl_init_platform(void)
>>   {
>> -	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
>> +	pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
> 
> Where isn't there a check for ms_hyperv.vtl > 0 here?
> 

On x86, there is

#ifdef CONFIG_HYPERV_VTL_MODE
void __init hv_vtl_init_platform(void);
int __init hv_vtl_early_init(void);
#else
static inline void __init hv_vtl_init_platform(void) {}
static inline int __init hv_vtl_early_init(void) { return 0; }
#endif

> Please be consistent across different architectures.
> 

In the earlier versions of the patch series, I had that piece
from the above mirrored in the arm64, and there was advice on
removing the function as it contained just one statement.
I'll revisit the approach, thanks for your help!

>>   
>>   	x86_platform.realmode_reserve = x86_init_noop;
>>   	x86_platform.realmode_init = x86_init_noop;
>> -- 
>> 2.43.0
>>
>>

-- 
Thank you,
Roman



From conor at kernel.org  Mon Mar 10 09:49:21 2025
From: conor at kernel.org (Conor Dooley)
Date: Mon, 10 Mar 2025 16:49:21 +0000
Subject: [PATCH] dt-bindings: dma: fsl-mxs-dma: Add compatible string for
 i.MX8 chips
In-Reply-To: <20250307215100.3257649-1-Frank.Li@nxp.com>
References: <20250307215100.3257649-1-Frank.Li@nxp.com>
Message-ID: <20250310-either-ambulance-541738a32b2c@spud>

On Fri, Mar 07, 2025 at 04:50:59PM -0500, Frank Li wrote:
> Add compatible string for all i.MX8 chips, which is backward compatible
> with i.MX28. Set it to fall back to "fsl,imx28-dma-apbh".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Acked-by: Conor Dooley <conor.dooley at microchip.com>

> ---
>  Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml b/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
> index a17cf2360dd4a..75a7d9556699c 100644
> --- a/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
> +++ b/Documentation/devicetree/bindings/dma/fsl,mxs-dma.yaml
> @@ -31,6 +31,12 @@ properties:
>                - fsl,imx6q-dma-apbh
>                - fsl,imx6sx-dma-apbh
>                - fsl,imx7d-dma-apbh
> +              - fsl,imx8dxl-dma-apbh
> +              - fsl,imx8mm-dma-apbh
> +              - fsl,imx8mn-dma-apbh
> +              - fsl,imx8mp-dma-apbh
> +              - fsl,imx8mq-dma-apbh
> +              - fsl,imx8qm-dma-apbh
>                - fsl,imx8qxp-dma-apbh
>            - const: fsl,imx28-dma-apbh
>        - enum:
> -- 
> 2.34.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250310/b2ed2400/attachment.sig>

From wei.liu at kernel.org  Mon Mar 10 09:53:13 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Mon, 10 Mar 2025 16:53:13 +0000
Subject: [PATCH hyperv-next v5 06/11] arm64, x86: hyperv: Report the VTL
 the system boots in
In-Reply-To: <2342dda1-2976-4506-ab68-640739a1bd5b@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-7-romank@linux.microsoft.com>
 <Z84yyAqkqJ2ZyAd-@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
 <2342dda1-2976-4506-ab68-640739a1bd5b@linux.microsoft.com>
Message-ID: <Z88Y-R7BnXa4Xi3I@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Mon, Mar 10, 2025 at 09:42:15AM -0700, Roman Kisel wrote:
> 
> 
> On 3/9/2025 5:31 PM, Wei Liu wrote:
> > On Fri, Mar 07, 2025 at 02:02:58PM -0800, Roman Kisel wrote:
> > > The hyperv guest code might run in various Virtual Trust Levels.
> > > 
> > > Report the level when the kernel boots in the non-default (0)
> > > one.
> > > 
> > > Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> > > ---
> > >   arch/arm64/hyperv/mshyperv.c | 2 ++
> > >   arch/x86/hyperv/hv_vtl.c     | 2 +-
> > >   2 files changed, 3 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> > > index a7db03f5413d..3bc16dbee758 100644
> > > --- a/arch/arm64/hyperv/mshyperv.c
> > > +++ b/arch/arm64/hyperv/mshyperv.c
> > > @@ -108,6 +108,8 @@ static int __init hyperv_init(void)
> > >   	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
> > >   		hv_get_partition_id();
> > >   	ms_hyperv.vtl = get_vtl();
> > > +	if (ms_hyperv.vtl > 0) /* non default VTL */
> > 
> > "non-default".
> > 
> 
> Thanks, will fix that!
> 
> > > +		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
> > >   	ms_hyperv_late_init();
> > > diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
> > > index 4e1b1e3b5658..c21bee7e8ff3 100644
> > > --- a/arch/x86/hyperv/hv_vtl.c
> > > +++ b/arch/x86/hyperv/hv_vtl.c
> > > @@ -24,7 +24,7 @@ static bool __init hv_vtl_msi_ext_dest_id(void)
> > >   void __init hv_vtl_init_platform(void)
> > >   {
> > > -	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
> > > +	pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
> > 
> > Where isn't there a check for ms_hyperv.vtl > 0 here?
> > 
> 
> On x86, there is
> 
> #ifdef CONFIG_HYPERV_VTL_MODE
> void __init hv_vtl_init_platform(void);
> int __init hv_vtl_early_init(void);
> #else
> static inline void __init hv_vtl_init_platform(void) {}
> static inline int __init hv_vtl_early_init(void) { return 0; }
> #endif
> 
> > Please be consistent across different architectures.
> > 
> 
> In the earlier versions of the patch series, I had that piece
> from the above mirrored in the arm64, and there was advice on
> removing the function as it contained just one statement.
> I'll revisit the approach, thanks for your help!

As long as the output is consistent across different architectures, I'm
good.

Wei.

> 
> > >   	x86_platform.realmode_reserve = x86_init_noop;
> > >   	x86_platform.realmode_init = x86_init_noop;
> > > -- 
> > > 2.43.0
> > > 
> > > 
> 
> -- 
> Thank you,
> Roman
> 


From nphamcs at gmail.com  Mon Mar 10 09:58:03 2025
From: nphamcs at gmail.com (Nhat Pham)
Date: Mon, 10 Mar 2025 09:58:03 -0700
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <52896654fa07a685707b11cfcc141b038a13b649.camel@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com> <52896654fa07a685707b11cfcc141b038a13b649.camel@mediatek.com>
Message-ID: <CAKEwX=PNHik8O6swwRPsuDovtCNLxXRQUsiXZSSq8ZbzFvJV0w@mail.gmail.com>

On Mon, Mar 10, 2025 at 6:22?AM Qun-wei Lin (???)
<Qun-wei.Lin at mediatek.com> wrote:
>
>
> Thank you for your explanation. Compared to the original single kswapd,
> we expect t1 to have a slight increase in re-scan time. However, since
> our kcompressd can focus on compression tasks and we can have multiple
> kcompressd instances (kcompressd0, kcompressd1, ...) running in
> parallel, we anticipate that the number of times a folio needs be re-
> scanned will not be too many.
>
> In our experiments, we fixed the CPU and DRAM at a certain frequency.
> We created a high memory pressure enviroment using a memory eater and
> recorded the increase in pgsteal_anon per second, which was around 300,
> 000. Then we applied our patch and measured again, that pgsteal_anon/s
> increased to over 800,000.
>
> > >
> > > >
> > > > Problem:
> > > >  In the current system, the kswapd thread is responsible for both
> > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > >  combined responsibility can lead to significant performance
> > > > bottlenecks,
> > >
> > > What bottleneck are we talking about? Is one stage slower than the
> > > other?
> > >
> > > >  especially under high memory pressure. The kswapd thread becomes
> > > > a
> > > >  single point of contention, causing delays in memory reclaiming
> > > > and
> > > >  overall system performance degradation.
> > > >
> > > > Target:
> > > >  The target of this invention is to improve the efficiency of
> > > > memory
> > > >  reclaiming. By separating the tasks of page scanning and page
> > > >  compression into distinct processes or threads, the system can
> > > > handle
> > > >  memory pressure more effectively.
> > >
> > > I'm not a zram maintainer, so I'm definitely not trying to stop
> > > this
> > > patch. But whatever problem zram is facing will likely occur with
> > > zswap too, so I'd like to learn more :)
> >
> > Right, this is likely something that could be addressed more
> > generally
> > for zswap and zram.
> >
>
> Yes, we also hope to extend this to other swap devices, but currently,
> we have only modified zram. We are not very familiar with zswap and
> would like to ask if anyone has any suggestions for modifications?
>

My understanding is right now schedule_bio_write is the work
submission API right? We can make it generic, having it accept a
callback and a generic untyped pointer which can be casted into a
backend-specific context struct. For zram it would contain struct zram
and the bio. For zswap, depending on at which point do you want to
begin offloading the work - it could simply be just the folio itself
if we offload early, or a more complicated scheme.



> > Thanks
> > Barry
>
> Best Regards,
> Qun-wei
>
>


From oleg at redhat.com  Mon Mar 10 10:03:21 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Mon, 10 Mar 2025 18:03:21 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes:
 uprobe_write_opcode() rewrite
In-Reply-To: <20250304154846.1937958-4-david@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
Message-ID: <20250310170320.GC26382@redhat.com>

On 03/04, David Hildenbrand wrote:
>
> uprobe_write_opcode() does some pretty low-level things that really, it
> shouldn't be doing:

Agreed. Thanks again for doing this.

David, as I said, I can't review. I don't understand this mm/folio magic
with or without your changes.

However. With your changes the code looks "better" and more understandable
to me. So I'd vote for your patches even if I can't ack them.

But I'd like to ask some stupid (no, really) questions.
__uprobe_write_opcode() does:

	/* We're done if we don't find an anonymous folio when unregistering. */
	if (!folio_test_anon(folio))
		return is_register ? -EFAULT : 0;

Yes, but we do not expect !folio_test_anon() if register == true, right?
See also below.

	/* Verify that the page content is still as expected. */
	if (verify_opcode(fw->page, opcode_vaddr, &opcode) <= 0) {
		set_pte_at(vma->vm_mm, vaddr, fw->ptep, fw->pte);
		return -EAGAIN;
	}

The caller, uprobe_write_opcode(), has already called verify_opcode(),
why do we need to re-check?

But whatever reason we have. Can we change uprobe_write_opcode() to
"delay" put_page() and instead of

	/* Walk the page tables again, to perform the actual update. */
	folio = folio_walk_start(&fw, vma, vaddr, 0);
	if (folio) {
		ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr,
					    opcode);
		folio_walk_end(&fw, vma);
	} else {
		ret = -EAGAIN;
	}

do something like

	/* Walk the page tables again, to perform the actual update. */
	ret = -EAGAIN;
	folio = folio_walk_start(&fw, vma, vaddr, 0);
	if (folio) {
		if (fw.page == page) {
			WARN_ON(is_register && !folio_test_anon(folio));
			ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr,
					            opcode);
		}
		folio_walk_end(&fw, vma);
	}

?

Once again, I am not trying to review. I am trying to understand the
basics of your code.

Thanks,

Oleg.



From romank at linux.microsoft.com  Mon Mar 10 10:05:56 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:05:56 -0700
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
 <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
Message-ID: <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>



On 3/10/2025 2:28 AM, Krzysztof Kozlowski wrote:
> On Fri, Mar 07, 2025 at 02:02:59PM -0800, Roman Kisel wrote:
>> To boot on ARM64, VMBus requires configuring interrupts. Missing
>> DMA coherence property is sub-optimal as the VMBus transations are
>> cache-coherent.
>>
>> Add interrupts to be able to boot on ARM64. Add DMA coherence to
>> avoid doing extra work on maintaining caches on ARM64.
> 
> How do you add it?
> 

I added properties to the node. Should I fix the description, or I am
misunderstanding the question?

>>
>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
>> ---
>>   .../devicetree/bindings/bus/microsoft,vmbus.yaml          | 8 +++++++-
>>   1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>> index a8d40c766dcd..3ab7d0116626 100644
>> --- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>> +++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>> @@ -28,13 +28,16 @@ properties:
>>   required:
>>     - compatible
>>     - ranges
>> +  - interrupts
>>     - '#address-cells'
>>     - '#size-cells'
>>   
>> -additionalProperties: false
>> +additionalProperties: true
> 
> This is neither explained in commit msg nor correct.
> 

Not explained, as there is no good explanation as described below.

> Drop the change. You cannot have device bindings ending with 'true'
> here - see talks, example-bindings, writing-schema and whatever resource
> is there.
> 

Thanks, I'll put more effort into bringing this into a better form!
If you have time, could you comment on the below?

The Documentation says

   * additionalProperties: true
     Rare case, used for schemas implementing common set of properties.
Such schemas are supposed to be referenced by other schemas, which then 
use 'unevaluatedProperties: false'.  Typically bus or common-part schemas.

This is a bus so I added that line to the YAML, and I saw it in many
other YAML files. Without that line, there was a warning from the local
DT validation described in the Documentation about not having pin
controls which was weird, and adding

"additionalProperties: true"

fixed the warnings (didn't debug much though). As a side note, there was
a similar warning coming from another YAML during running DT schema
validation as described in the Documentation so maybe warnings are fine.

> Best regards,
> Krzysztof
> 

-- 
Thank you,
Roman



From rppt at kernel.org  Mon Mar 10 10:08:01 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Mon, 10 Mar 2025 19:08:01 +0200
Subject: [PATCH v4 06/14] kexec: Add KHO parsing support
In-Reply-To: <mafs0zfhs97ta.fsf@amazon.de>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-7-rppt@kernel.org>
 <mafs0zfhs97ta.fsf@amazon.de>
Message-ID: <Z88ccZat5wm_iXx1@kernel.org>

Hi Pratyush,

On Mon, Mar 10, 2025 at 04:20:01PM +0000, Pratyush Yadav wrote:
> Hi Mike,
> 
> On Thu, Feb 06 2025, Mike Rapoport wrote:
> [...]
> > @@ -444,7 +576,141 @@ static void kho_reserve_scratch(void)
> >  	kho_enable = false;
> >  }
> >  
> > +/*
> > + * Scan the DT for any memory ranges and make sure they are reserved in
> > + * memblock, otherwise they will end up in a weird state on free lists.
> > + */
> > +static void kho_init_reserved_pages(void)
> > +{
> > +	const void *fdt = kho_get_fdt();
> > +	int offset = 0, depth = 0, initial_depth = 0, len;
> > +
> > +	if (!fdt)
> > +		return;
> > +
> > +	/* Go through the mem list and add 1 for each reference */
> > +	for (offset = 0;
> > +	     offset >= 0 && depth >= initial_depth;
> > +	     offset = fdt_next_node(fdt, offset, &depth)) {
> > +		const struct kho_mem *mems;
> > +		u32 i;
> > +
> > +		mems = fdt_getprop(fdt, offset, "mem", &len);
> > +		if (!mems || len & (sizeof(*mems) - 1))
> > +			continue;
> > +
> > +		for (i = 0; i < len; i += sizeof(*mems)) {
> > +			const struct kho_mem *mem = &mems[i];
> 
> i goes from 0 to len in steps of 16, but you use it to dereference an
> array of type struct kho_mem. So you end up only looking at only one of
> every 16 mems and do an out of bounds access. I found this when testing
> the memfd patches and any time the file was more than 1 page, it started
> to crash randomly.

Thanks! Changyuan already pointed that out privately.
But I'm going to adopt the memory reservation scheme Jason proposed so
this code is going to go away anyway :)

> Below patch should fix that:
> 
> ---- 8< ----
> diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
> index c26753d613cbc..40d1d8ac68d44 100644
> --- a/kernel/kexec_handover.c
> +++ b/kernel/kexec_handover.c
> @@ -685,13 +685,15 @@ static void kho_init_reserved_pages(void)
>              offset >= 0 && depth >= initial_depth;
>              offset = fdt_next_node(fdt, offset, &depth)) {
>                 const struct kho_mem *mems;
> -               u32 i;
> +               u32 i, nr_mems;
>  
>                 mems = fdt_getprop(fdt, offset, "mem", &len);
>                 if (!mems || len & (sizeof(*mems) - 1))
>                         continue;
>  
> -               for (i = 0; i < len; i += sizeof(*mems)) {
> +               nr_mems = len / sizeof(*mems);
> +
> +               for (i = 0; i < nr_mems; i++) {
>                         const struct kho_mem *mem = &mems[i];
>  
>                         memblock_reserve(mem->addr, mem->size);
> ---- >8 ----
> [...]
> 
> -- 
> Regards,
> Pratyush Yadav

-- 
Sincerely yours,
Mike.


From romank at linux.microsoft.com  Mon Mar 10 10:09:45 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:09:45 -0700
Subject: [PATCH hyperv-next v5 09/11] Drivers: hv: vmbus: Introduce
 hv_get_vmbus_root_device()
In-Reply-To: <CAMvTesCFZ6sxQp7qqSDjD9idRjVHxh96Sp4betomgFH-OFLZ3Q@mail.gmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-10-romank@linux.microsoft.com>
 <CAMvTesCFZ6sxQp7qqSDjD9idRjVHxh96Sp4betomgFH-OFLZ3Q@mail.gmail.com>
Message-ID: <e3414583-0437-4fc4-b464-1426e5fe9628@linux.microsoft.com>



On 3/10/2025 6:41 AM, Tianyu Lan wrote:
> On Sat, Mar 8, 2025 at 6:05?AM Roman Kisel <romank at linux.microsoft.com> wrote:
>>
>> The ARM64 PCI code for hyperv needs to know the VMBus root
>> device, and it is private.
>>
>> Provide a function that returns it. Rename it from "hv_dev"
>> as "hv_dev" as a symbol is very overloaded. No functional
>> changes.
>>
>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> 
> Why change all device's parent to vmbus_root_device?
> 

No changes from my account of the code. Please let me know if I am
misunderstanding the question.

> The ARM64 platform uses the device tree to enumerate vmbus
> devices..  Can we find the root device via device tree? vmbus
> code on the x86 use ACPI and it seems to work via ACPI.
> 
> 

Right, we find it from the DT as shown in the next patch:

+static struct irq_domain *hv_pci_of_irq_domain_parent(void)
+{
+	struct device_node *parent;
+	struct irq_domain *domain;
+
+	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
+	domain = NULL;
+	if (parent) {
+		domain = irq_find_host(parent);
+		of_node_put(parent);
+	}
+
+	return domain;
+}
+

and later use it for `irq_create_hierarchy()`. Please let me know
if I missed anything in your question.

>> ---
>>   drivers/hv/vmbus_drv.c | 23 +++++++++++++++--------
>>   include/linux/hyperv.h |  2 ++
>>   2 files changed, 17 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
>> index c8474b48dcd2..7bfafe702963 100644
>> --- a/drivers/hv/vmbus_drv.c
>> +++ b/drivers/hv/vmbus_drv.c
>> @@ -45,7 +45,8 @@ struct vmbus_dynid {
>>          struct hv_vmbus_device_id id;
>>   };
>>
>> -static struct device  *hv_dev;
>> +/* VMBus Root Device */
>> +static struct device  *vmbus_root_device;
>>
>>   static int hyperv_cpuhp_online;
>>
>> @@ -80,9 +81,15 @@ static struct resource *fb_mmio;
>>   static struct resource *hyperv_mmio;
>>   static DEFINE_MUTEX(hyperv_mmio_lock);
>>
>> +struct device *hv_get_vmbus_root_device(void)
>> +{
>> +       return vmbus_root_device;
>> +}
>> +EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
>> +
>>   static int vmbus_exists(void)
>>   {
>> -       if (hv_dev == NULL)
>> +       if (vmbus_root_device == NULL)
>>                  return -ENODEV;
>>
>>          return 0;
>> @@ -861,7 +868,7 @@ static int vmbus_dma_configure(struct device *child_device)
>>           * On x86/x64 coherence is assumed and these calls have no effect.
>>           */
>>          hv_setup_dma_ops(child_device,
>> -               device_get_dma_attr(hv_dev) == DEV_DMA_COHERENT);
>> +               device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
>>          return 0;
>>   }
>>
>> @@ -1930,7 +1937,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
>>                       &child_device_obj->channel->offermsg.offer.if_instance);
>>
>>          child_device_obj->device.bus = &hv_bus;
>> -       child_device_obj->device.parent = hv_dev;
>> +       child_device_obj->device.parent = vmbus_root_device;
>>          child_device_obj->device.release = vmbus_device_release;
>>
>>          child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
>> @@ -2292,7 +2299,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
>>          struct acpi_device *ancestor;
>>          struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
>>
>> -       hv_dev = &device->dev;
>> +       vmbus_root_device = &device->dev;
>>
>>          /*
>>           * Older versions of Hyper-V for ARM64 fail to include the _CCA
>> @@ -2383,7 +2390,7 @@ static int vmbus_device_add(struct platform_device *pdev)
>>          struct device_node *np = pdev->dev.of_node;
>>          int ret;
>>
>> -       hv_dev = &pdev->dev;
>> +       vmbus_root_device = &pdev->dev;
>>
>>          ret = of_range_parser_init(&parser, np);
>>          if (ret)
>> @@ -2702,7 +2709,7 @@ static int __init hv_acpi_init(void)
>>          if (ret)
>>                  return ret;
>>
>> -       if (!hv_dev) {
>> +       if (!vmbus_root_device) {
>>                  ret = -ENODEV;
>>                  goto cleanup;
>>          }
>> @@ -2733,7 +2740,7 @@ static int __init hv_acpi_init(void)
>>
>>   cleanup:
>>          platform_driver_unregister(&vmbus_platform_driver);
>> -       hv_dev = NULL;
>> +       vmbus_root_device = NULL;
>>          return ret;
>>   }
>>
>> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
>> index 7f4f8d8bdf43..1f0851fde041 100644
>> --- a/include/linux/hyperv.h
>> +++ b/include/linux/hyperv.h
>> @@ -1333,6 +1333,8 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
>>          return dev_get_drvdata(&dev->device);
>>   }
>>
>> +struct device *hv_get_vmbus_root_device(void);
>> +
>>   struct hv_ring_buffer_debug_info {
>>          u32 current_interrupt_mask;
>>          u32 current_read_index;
>> --
>> 2.43.0
>>
>>
> 
> 

-- 
Thank you,
Roman



From lkp at intel.com  Mon Mar 10 10:10:10 2025
From: lkp at intel.com (kernel test robot)
Date: Tue, 11 Mar 2025 01:10:10 +0800
Subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller
 driver
In-Reply-To: <20250309180940.1322531-4-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-4-jan.dakinevich@salutedevices.com>
Message-ID: <202503110016.L1KdYGVj-lkp@intel.com>

Hi Jan,

kernel test robot noticed the following build errors:

[auto build test ERROR on clk/clk-next]
[also build test ERROR on robh/for-next krzk/for-next krzk-dt/for-next linus/master v6.14-rc6 next-20250307]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jan-Dakinevich/clk-meson-axg-share-the-set-of-audio-helper-macros/20250310-022012
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
patch link:    https://lore.kernel.org/r/20250309180940.1322531-4-jan.dakinevich%40salutedevices.com
patch subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller driver
config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20250311/202503110016.L1KdYGVj-lkp at intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250311/202503110016.L1KdYGVj-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503110016.L1KdYGVj-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/clk/meson/a1-audio.c:807:11: error: call to undeclared function '__devm_auxiliary_device_create'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     807 |         auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
         |                  ^
   drivers/clk/meson/a1-audio.c:807:11: note: did you mean '__auxiliary_device_add'?
   include/linux/auxiliary_bus.h:221:5: note: '__auxiliary_device_add' declared here
     221 | int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname);
         |     ^
>> drivers/clk/meson/a1-audio.c:807:9: error: incompatible integer to pointer conversion assigning to 'struct auxiliary_device *' from 'int' [-Wint-conversion]
     807 |         auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
         |                ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     808 |                                                 data->rst_drvname, NULL, 0);
         |                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2 errors generated.


vim +/__devm_auxiliary_device_create +807 drivers/clk/meson/a1-audio.c

   748	
   749	static int a1_audio_clkc_probe(struct platform_device *pdev)
   750	{
   751		struct device *dev = &pdev->dev;
   752		const struct a1_audio_data *data;
   753		struct auxiliary_device *auxdev;
   754		struct regmap *map;
   755		void __iomem *base;
   756		struct clk *clk;
   757		unsigned int i;
   758		int ret;
   759	
   760		data = device_get_match_data(dev);
   761		if (!data)
   762			return -EINVAL;
   763	
   764		clk = devm_clk_get_enabled(dev, "pclk");
   765		if (IS_ERR(clk))
   766			return PTR_ERR(clk);
   767	
   768		base = devm_platform_ioremap_resource(pdev, 0);
   769		if (IS_ERR(base))
   770			return PTR_ERR(base);
   771	
   772		map = devm_regmap_init_mmio(dev, base, &a1_audio_regmap_cfg);
   773		if (IS_ERR(map))
   774			return PTR_ERR(map);
   775	
   776		ret = device_reset(dev);
   777		if (ret)
   778			return ret;
   779	
   780		for (i = 0; i < data->hw_clks.num; i++) {
   781			struct clk_hw *hw = data->hw_clks.hws[i];
   782			struct clk_regmap *clk_regmap = to_clk_regmap(hw);
   783	
   784			if (!hw)
   785				continue;
   786	
   787			clk_regmap->map = map;
   788		}
   789	
   790		for (i = 0; i < data->hw_clks.num; i++) {
   791			struct clk_hw *hw;
   792	
   793			hw = data->hw_clks.hws[i];
   794			if (!hw)
   795				continue;
   796	
   797			ret = devm_clk_hw_register(dev, hw);
   798			if (ret)
   799				return ret;
   800		}
   801	
   802		ret = devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
   803						  (void *)&data->hw_clks);
   804		if (ret)
   805			return ret;
   806	
 > 807		auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
   808							data->rst_drvname, NULL, 0);
   809		if (!auxdev)
   810			return -ENODEV;
   811	
   812		return 0;
   813	}
   814	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From Qun-wei.Lin at mediatek.com  Mon Mar 10 06:26:35 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Mon, 10 Mar 2025 13:26:35 +0000
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram
 compression
In-Reply-To: <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
	 <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
Message-ID: <7938f840136165be1c50050feb39fb14ee37721b.camel@mediatek.com>

On Sat, 2025-03-08 at 08:41 +1300, Barry Song wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com>
> wrote:
> > 
> > Introduced Kcompressd to offload zram page compression, improving
> > system efficiency by handling compression separately from memory
> > reclaiming. Added necessary configurations and dependencies.
> > 
> > Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > ---
> > ?drivers/block/zram/Kconfig????? |? 11 ++
> > ?drivers/block/zram/Makefile???? |?? 3 +-
> > ?drivers/block/zram/kcompressd.c | 340
> > ++++++++++++++++++++++++++++++++
> > ?drivers/block/zram/kcompressd.h |? 25 +++
> > ?drivers/block/zram/zram_drv.c?? |? 22 ++-
> > ?5 files changed, 397 insertions(+), 4 deletions(-)
> > ?create mode 100644 drivers/block/zram/kcompressd.c
> > ?create mode 100644 drivers/block/zram/kcompressd.h
> > 
> > diff --git a/drivers/block/zram/Kconfig
> > b/drivers/block/zram/Kconfig
> > index 402b7b175863..f0a1b574f770 100644
> > --- a/drivers/block/zram/Kconfig
> > +++ b/drivers/block/zram/Kconfig
> > @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
> > ????????? re-compress pages using a potentially slower but more
> > effective
> > ????????? compression algorithm. Note, that IDLE page recompression
> > ????????? requires ZRAM_TRACK_ENTRY_ACTIME.
> > +
> > +config KCOMPRESSD
> > +?????? tristate "Kcompressd: Accelerated zram compression"
> > +?????? depends on ZRAM
> > +?????? help
> > +???????? Kcompressd creates multiple daemons to accelerate the
> > compression of pages
> > +???????? in zram, offloading this time-consuming task from the
> > zram driver.
> > +
> > +???????? This approach improves system efficiency by handling page
> > compression separately,
> > +???????? which was originally done by kswapd or direct reclaim.
> 
> For direct reclaim, we were previously able to compress using
> multiple CPUs
> with multi-threading.
> After your patch, it seems that only a single thread/CPU is used for
> compression
> so it won't necessarily improve direct reclaim performance?
> 

Our patch only splits the context of kswapd. When direct reclaim is
occurred, it is bypassed, so direct reclaim remains unchanged, with
each thread that needs memory directly reclaiming it.

> Even for kswapd, we used to have multiple threads like [kswapd0],
> [kswapd1],
> and [kswapd2] for different nodes. Now, are we also limited to just
> one thread?

We only considered a single kswapd here and didn't account for multiple
instances. Since I use kfifo to collect the bios, if there are multiple
kswapds, we need to add a lock to protect the bio queue. I can revise
this in the 2nd version, or do you have any other suggested approaches?

> I also wonder if this could be handled at the vmscan level instead of
> the zram
> level. then it might potentially help other sync devices or even
> zswap later.
> 
> But I agree that for phones, modifying zram seems like an easier
> starting
> point. However, relying on a single thread isn't always the best
> approach.
> 
> 
> > +
> > diff --git a/drivers/block/zram/Makefile
> > b/drivers/block/zram/Makefile
> > index 0fdefd576691..23baa5dfceb9 100644
> > --- a/drivers/block/zram/Makefile
> > +++ b/drivers/block/zram/Makefile
> > @@ -9,4 +9,5 @@ zram-$(CONFIG_ZRAM_BACKEND_ZSTD)??????? +=
> > backend_zstd.o
> > ?zram-$(CONFIG_ZRAM_BACKEND_DEFLATE)??? += backend_deflate.o
> > ?zram-$(CONFIG_ZRAM_BACKEND_842)??????????????? += backend_842.o
> > 
> > -obj-$(CONFIG_ZRAM)???? +=????? zram.o
> > +obj-$(CONFIG_ZRAM)???????????? += zram.o
> > +obj-$(CONFIG_KCOMPRESSD)?????? += kcompressd.o
> > diff --git a/drivers/block/zram/kcompressd.c
> > b/drivers/block/zram/kcompressd.c
> > new file mode 100644
> > index 000000000000..195b7e386869
> > --- /dev/null
> > +++ b/drivers/block/zram/kcompressd.c
> > @@ -0,0 +1,340 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2024 MediaTek Inc.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/bio.h>
> > +#include <linux/bitops.h>
> > +#include <linux/freezer.h>
> > +#include <linux/kernel.h>
> > +#include <linux/psi.h>
> > +#include <linux/kfifo.h>
> > +#include <linux/swap.h>
> > +#include <linux/delay.h>
> > +
> > +#include "kcompressd.h"
> > +
> > +#define INIT_QUEUE_SIZE??????????????? 4096
> > +#define DEFAULT_NR_KCOMPRESSD? 4
> > +
> > +static atomic_t enable_kcompressd;
> > +static unsigned int nr_kcompressd;
> > +static unsigned int queue_size_per_kcompressd;
> > +static struct kcompress *kcompress;
> > +
> > +enum run_state {
> > +?????? KCOMPRESSD_NOT_STARTED = 0,
> > +?????? KCOMPRESSD_RUNNING,
> > +?????? KCOMPRESSD_SLEEPING,
> > +};
> > +
> > +struct kcompressd_para {
> > +?????? wait_queue_head_t *kcompressd_wait;
> > +?????? struct kfifo *write_fifo;
> > +?????? atomic_t *running;
> > +};
> > +
> > +static struct kcompressd_para *kcompressd_para;
> > +static BLOCKING_NOTIFIER_HEAD(kcompressd_notifier_list);
> > +
> > +struct write_work {
> > +?????? void *mem;
> > +?????? struct bio *bio;
> > +?????? compress_callback cb;
> > +};
> > +
> > +int kcompressd_enabled(void)
> > +{
> > +?????? return likely(atomic_read(&enable_kcompressd));
> > +}
> > +EXPORT_SYMBOL(kcompressd_enabled);
> > +
> > +static void kcompressd_try_to_sleep(struct kcompressd_para *p)
> > +{
> > +?????? DEFINE_WAIT(wait);
> > +
> > +?????? if (!kfifo_is_empty(p->write_fifo))
> > +?????????????? return;
> > +
> > +?????? if (freezing(current) || kthread_should_stop())
> > +?????????????? return;
> > +
> > +?????? atomic_set(p->running, KCOMPRESSD_SLEEPING);
> > +?????? prepare_to_wait(p->kcompressd_wait, &wait,
> > TASK_INTERRUPTIBLE);
> > +
> > +?????? /*
> > +??????? * After a short sleep, check if it was a premature sleep.
> > If not, then
> > +??????? * go fully to sleep until explicitly woken up.
> > +??????? */
> > +?????? if (!kthread_should_stop() && kfifo_is_empty(p-
> > >write_fifo))
> > +?????????????? schedule();
> > +
> > +?????? finish_wait(p->kcompressd_wait, &wait);
> > +?????? atomic_set(p->running, KCOMPRESSD_RUNNING);
> > +}
> > +
> > +static int kcompressd(void *para)
> > +{
> > +?????? struct task_struct *tsk = current;
> > +?????? struct kcompressd_para *p = (struct kcompressd_para *)para;
> > +
> > +?????? tsk->flags |= PF_MEMALLOC | PF_KSWAPD;
> > +?????? set_freezable();
> > +
> > +?????? while (!kthread_should_stop()) {
> > +?????????????? bool ret;
> > +
> > +?????????????? kcompressd_try_to_sleep(p);
> > +?????????????? ret = try_to_freeze();
> > +?????????????? if (kthread_should_stop())
> > +?????????????????????? break;
> > +
> > +?????????????? if (ret)
> > +?????????????????????? continue;
> > +
> > +?????????????? while (!kfifo_is_empty(p->write_fifo)) {
> > +?????????????????????? struct write_work entry;
> > +
> > +?????????????????????? if (sizeof(struct write_work) ==
> > kfifo_out(p->write_fifo,
> > +?????????????????????????????????????????????? &entry,
> > sizeof(struct write_work))) {
> > +?????????????????????????????? entry.cb(entry.mem, entry.bio);
> > +?????????????????????????????? bio_put(entry.bio);
> > +?????????????????????? }
> > +?????????????? }
> > +
> > +?????? }
> > +
> > +?????? tsk->flags &= ~(PF_MEMALLOC | PF_KSWAPD);
> > +?????? atomic_set(p->running, KCOMPRESSD_NOT_STARTED);
> > +?????? return 0;
> > +}
> > +
> > +static int init_write_queue(void)
> > +{
> > +?????? int i;
> > +?????? unsigned int queue_len = queue_size_per_kcompressd *
> > sizeof(struct write_work);
> > +
> > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > +?????????????? if (kfifo_alloc(&kcompress[i].write_fifo,
> > +?????????????????????????????????????? queue_len, GFP_KERNEL)) {
> > +?????????????????????? pr_err("Failed to alloc kfifo %d\n", i);
> > +?????????????????????? return -ENOMEM;
> > +?????????????? }
> > +?????? }
> > +?????? return 0;
> > +}
> > +
> > +static void clean_bio_queue(int idx)
> > +{
> > +?????? struct write_work entry;
> > +
> > +?????? while (sizeof(struct write_work) ==
> > kfifo_out(&kcompress[idx].write_fifo,
> > +?????????????????????????????? &entry, sizeof(struct write_work)))
> > {
> > +?????????????? bio_put(entry.bio);
> > +?????????????? entry.cb(entry.mem, entry.bio);
> > +?????? }
> > +?????? kfifo_free(&kcompress[idx].write_fifo);
> > +}
> > +
> > +static int kcompress_update(void)
> > +{
> > +?????? int i;
> > +?????? int ret;
> > +
> > +?????? kcompress = kvmalloc_array(nr_kcompressd, sizeof(struct
> > kcompress), GFP_KERNEL);
> > +?????? if (!kcompress)
> > +?????????????? return -ENOMEM;
> > +
> > +?????? kcompressd_para = kvmalloc_array(nr_kcompressd,
> > sizeof(struct kcompressd_para), GFP_KERNEL);
> > +?????? if (!kcompressd_para)
> > +?????????????? return -ENOMEM;
> > +
> > +?????? ret = init_write_queue();
> > +?????? if (ret) {
> > +?????????????? pr_err("Initialization of writing to FIFOs
> > failed!!\n");
> > +?????????????? return ret;
> > +?????? }
> > +
> > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > +?????????????? init_waitqueue_head(&kcompress[i].kcompressd_wait);
> > +?????????????? kcompressd_para[i].kcompressd_wait =
> > &kcompress[i].kcompressd_wait;
> > +?????????????? kcompressd_para[i].write_fifo =
> > &kcompress[i].write_fifo;
> > +?????????????? kcompressd_para[i].running = &kcompress[i].running;
> > +?????? }
> > +
> > +?????? return 0;
> > +}
> > +
> > +static void stop_all_kcompressd_thread(void)
> > +{
> > +?????? int i;
> > +
> > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > +?????????????? kthread_stop(kcompress[i].kcompressd);
> > +?????????????? kcompress[i].kcompressd = NULL;
> > +?????????????? clean_bio_queue(i);
> > +?????? }
> > +}
> > +
> > +static int do_nr_kcompressd_handler(const char *val,
> > +?????????????? const struct kernel_param *kp)
> > +{
> > +?????? int ret;
> > +
> > +?????? atomic_set(&enable_kcompressd, false);
> > +
> > +?????? stop_all_kcompressd_thread();
> > +
> > +?????? ret = param_set_int(val, kp);
> > +?????? if (!ret) {
> > +?????????????? pr_err("Invalid number of kcompressd.\n");
> > +?????????????? return -EINVAL;
> > +?????? }
> > +
> > +?????? ret = init_write_queue();
> > +?????? if (ret) {
> > +?????????????? pr_err("Initialization of writing to FIFOs
> > failed!!\n");
> > +?????????????? return ret;
> > +?????? }
> > +
> > +?????? atomic_set(&enable_kcompressd, true);
> > +
> > +?????? return 0;
> > +}
> > +
> > +static const struct kernel_param_ops
> > param_ops_change_nr_kcompressd = {
> > +?????? .set = &do_nr_kcompressd_handler,
> > +?????? .get = &param_get_uint,
> > +?????? .free = NULL,
> > +};
> > +
> > +module_param_cb(nr_kcompressd, &param_ops_change_nr_kcompressd,
> > +?????????????? &nr_kcompressd, 0644);
> > +MODULE_PARM_DESC(nr_kcompressd, "Number of pre-created daemon for
> > page compression");
> > +
> > +static int do_queue_size_per_kcompressd_handler(const char *val,
> > +?????????????? const struct kernel_param *kp)
> > +{
> > +?????? int ret;
> > +
> > +?????? atomic_set(&enable_kcompressd, false);
> > +
> > +?????? stop_all_kcompressd_thread();
> > +
> > +?????? ret = param_set_int(val, kp);
> > +?????? if (!ret) {
> > +?????????????? pr_err("Invalid queue size for kcompressd.\n");
> > +?????????????? return -EINVAL;
> > +?????? }
> > +
> > +?????? ret = init_write_queue();
> > +?????? if (ret) {
> > +?????????????? pr_err("Initialization of writing to FIFOs
> > failed!!\n");
> > +?????????????? return ret;
> > +?????? }
> > +
> > +?????? pr_info("Queue size for kcompressd was changed: %d\n",
> > queue_size_per_kcompressd);
> > +
> > +?????? atomic_set(&enable_kcompressd, true);
> > +?????? return 0;
> > +}
> > +
> > +static const struct kernel_param_ops
> > param_ops_change_queue_size_per_kcompressd = {
> > +?????? .set = &do_queue_size_per_kcompressd_handler,
> > +?????? .get = &param_get_uint,
> > +?????? .free = NULL,
> > +};
> > +
> > +module_param_cb(queue_size_per_kcompressd,
> > &param_ops_change_queue_size_per_kcompressd,
> > +?????????????? &queue_size_per_kcompressd, 0644);
> > +MODULE_PARM_DESC(queue_size_per_kcompressd,
> > +?????????????? "Size of queue for kcompressd");
> > +
> > +int schedule_bio_write(void *mem, struct bio *bio,
> > compress_callback cb)
> > +{
> > +?????? int i;
> > +?????? bool submit_success = false;
> > +?????? size_t sz_work = sizeof(struct write_work);
> > +
> > +?????? struct write_work entry = {
> > +?????????????? .mem = mem,
> > +?????????????? .bio = bio,
> > +?????????????? .cb = cb
> > +?????? };
> > +
> > +?????? if (unlikely(!atomic_read(&enable_kcompressd)))
> > +?????????????? return -EBUSY;
> > +
> > +?????? if (!nr_kcompressd || !current_is_kswapd())
> > +?????????????? return -EBUSY;
> > +
> > +?????? bio_get(bio);
> > +
> > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > +?????????????? submit_success =
> > +?????????????????????? (kfifo_avail(&kcompress[i].write_fifo) >=
> > sz_work) &&
> > +?????????????????????? (sz_work ==
> > kfifo_in(&kcompress[i].write_fifo, &entry, sz_work));
> > +
> > +?????????????? if (submit_success) {
> > +?????????????????????? switch (atomic_read(&kcompress[i].running))
> > {
> > +?????????????????????? case KCOMPRESSD_NOT_STARTED:
> > +?????????????????????????????? atomic_set(&kcompress[i].running,
> > KCOMPRESSD_RUNNING);
> > +?????????????????????????????? kcompress[i].kcompressd =
> > kthread_run(kcompressd,
> > +??????????????????????????????????????????????
> > &kcompressd_para[i], "kcompressd:%d", i);
> > +?????????????????????????????? if
> > (IS_ERR(kcompress[i].kcompressd)) {
> > +??????????????????????????????????????
> > atomic_set(&kcompress[i].running, KCOMPRESSD_NOT_STARTED);
> > +?????????????????????????????????????? pr_warn("Failed to start
> > kcompressd:%d\n", i);
> > +?????????????????????????????????????? clean_bio_queue(i);
> > +?????????????????????????????? }
> > +?????????????????????????????? break;
> > +?????????????????????? case KCOMPRESSD_RUNNING:
> > +?????????????????????????????? break;
> > +?????????????????????? case KCOMPRESSD_SLEEPING:
> > +??????????????????????????????
> > wake_up_interruptible(&kcompress[i].kcompressd_wait);
> > +?????????????????????????????? break;
> > +?????????????????????? }
> > +?????????????????????? return 0;
> > +?????????????? }
> > +?????? }
> > +
> > +?????? bio_put(bio);
> > +?????? return -EBUSY;
> > +}
> > +EXPORT_SYMBOL(schedule_bio_write);
> > +
> > +static int __init kcompressd_init(void)
> > +{
> > +?????? int ret;
> > +
> > +?????? nr_kcompressd = DEFAULT_NR_KCOMPRESSD;
> > +?????? queue_size_per_kcompressd = INIT_QUEUE_SIZE;
> > +
> > +?????? ret = kcompress_update();
> > +?????? if (ret) {
> > +?????????????? pr_err("Init kcompressd failed!\n");
> > +?????????????? return ret;
> > +?????? }
> > +
> > +?????? atomic_set(&enable_kcompressd, true);
> > +?????? blocking_notifier_call_chain(&kcompressd_notifier_list, 0,
> > NULL);
> > +?????? return 0;
> > +}
> > +
> > +static void __exit kcompressd_exit(void)
> > +{
> > +?????? atomic_set(&enable_kcompressd, false);
> > +?????? stop_all_kcompressd_thread();
> > +
> > +?????? kvfree(kcompress);
> > +?????? kvfree(kcompressd_para);
> > +}
> > +
> > +module_init(kcompressd_init);
> > +module_exit(kcompressd_exit);
> > +
> > +MODULE_LICENSE("Dual BSD/GPL");
> > +MODULE_AUTHOR("Qun-Wei Lin <qun-wei.lin at mediatek.com>");
> > +MODULE_DESCRIPTION("Separate the page compression from the memory
> > reclaiming");
> > +
> > diff --git a/drivers/block/zram/kcompressd.h
> > b/drivers/block/zram/kcompressd.h
> > new file mode 100644
> > index 000000000000..2fe0b424a7af
> > --- /dev/null
> > +++ b/drivers/block/zram/kcompressd.h
> > @@ -0,0 +1,25 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2024 MediaTek Inc.
> > + */
> > +
> > +#ifndef _KCOMPRESSD_H_
> > +#define _KCOMPRESSD_H_
> > +
> > +#include <linux/rwsem.h>
> > +#include <linux/kfifo.h>
> > +#include <linux/atomic.h>
> > +
> > +typedef void (*compress_callback)(void *mem, struct bio *bio);
> > +
> > +struct kcompress {
> > +?????? struct task_struct *kcompressd;
> > +?????? wait_queue_head_t kcompressd_wait;
> > +?????? struct kfifo write_fifo;
> > +?????? atomic_t running;
> > +};
> > +
> > +int kcompressd_enabled(void);
> > +int schedule_bio_write(void *mem, struct bio *bio,
> > compress_callback cb);
> > +#endif
> > +
> > diff --git a/drivers/block/zram/zram_drv.c
> > b/drivers/block/zram/zram_drv.c
> > index 2e1a70f2f4bd..bcd63ecb6ff2 100644
> > --- a/drivers/block/zram/zram_drv.c
> > +++ b/drivers/block/zram/zram_drv.c
> > @@ -35,6 +35,7 @@
> > ?#include <linux/part_stat.h>
> > ?#include <linux/kernel_read_file.h>
> > 
> > +#include "kcompressd.h"
> > ?#include "zram_drv.h"
> > 
> > ?static DEFINE_IDR(zram_index_idr);
> > @@ -2240,6 +2241,15 @@ static void zram_bio_write(struct zram
> > *zram, struct bio *bio)
> > ??????? bio_endio(bio);
> > ?}
> > 
> > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > +static void zram_bio_write_callback(void *mem, struct bio *bio)
> > +{
> > +?????? struct zram *zram = (struct zram *)mem;
> > +
> > +?????? zram_bio_write(zram, bio);
> > +}
> > +#endif
> > +
> > ?/*
> > ? * Handler function for all zram I/O requests.
> > ? */
> > @@ -2252,6 +2262,10 @@ static void zram_submit_bio(struct bio *bio)
> > ??????????????? zram_bio_read(zram, bio);
> > ??????????????? break;
> > ??????? case REQ_OP_WRITE:
> > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > +?????????????? if (kcompressd_enabled() &&
> > !schedule_bio_write(zram, bio, zram_bio_write_callback))
> > +?????????????????????? break;
> > +#endif
> > ??????????????? zram_bio_write(zram, bio);
> > ??????????????? break;
> > ??????? case REQ_OP_DISCARD:
> > @@ -2535,9 +2549,11 @@ static int zram_add(void)
> > ?#if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
> > ??????????????? .max_write_zeroes_sectors?????? = UINT_MAX,
> > ?#endif
> > -?????????????? .features?????????????????????? =
> > BLK_FEAT_STABLE_WRITES??????? |
> > -????????????????????????????????????????????????
> > BLK_FEAT_READ_SYNCHRONOUS???? |
> > -????????????????????????????????????????????????
> > BLK_FEAT_WRITE_SYNCHRONOUS,
> > +?????????????? .features?????????????????????? =
> > BLK_FEAT_STABLE_WRITES
> > +???????????????????????????????????????????????? |
> > BLK_FEAT_READ_SYNCHRONOUS
> > +#if !IS_ENABLED(CONFIG_KCOMPRESSD)
> > +???????????????????????????????????????????????? |
> > BLK_FEAT_WRITE_SYNCHRONOUS,
> > +#endif
> > ??????? };
> > ??????? struct zram *zram;
> > ??????? int ret, device_id;
> > --
> > 2.45.2
> > 
> 
> Thanks
> Barry


From suzuki.poulose at arm.com  Mon Mar 10 06:29:26 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 10 Mar 2025 13:29:26 +0000
Subject: [PATCH v2 5/8] coresight: etm: Add an attribute for updating
 buffer
In-Reply-To: <20250310104919.58816-6-leo.yan@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-6-leo.yan@arm.com>
Message-ID: <d8b1cf1f-1996-4d9c-9f1a-fad556f91577@arm.com>

Hi Leo

On 10/03/2025 10:49, Leo Yan wrote:
> Add an attribute for updating buffer when the AUX trace is paused.  And
> populate the value to the 'update_buf_on_pause' flag during the AUX
> setting up.

Do we need this attribute in the uAPI ? Could we do this by default for
sinks without interrupt ? This definitely improves the quality of trace
collected for such sinks and the driver can transparently do this.

Cheers
Suzuki

> 
> If the AUX pause operation is attached to a PMU counter, when the
> counter is overflow and if the PMU interrupt in an NMI, then AUX pause
> operation will be triggered in the NMI context.  On the other hand, the
> per CPU sink has its own interrupt handling.  Thus, there will be a race
> condition between the updating buffer in NMI and sink's interrupt
> handler.
> 
> To avoid the race condition, this commit disallows updating buffer on
> AUX pause for the per CPU sink.  Currently, this is only applied for
> TRBE.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   .../hwtracing/coresight/coresight-etm-perf.c  | 20 +++++++++++++++++++
>   .../hwtracing/coresight/coresight-etm-perf.h  |  2 ++
>   include/linux/coresight-pmu.h                 |  1 +
>   3 files changed, 23 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> index 29d52386ffbb..d759663a1f7d 100644
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> @@ -62,6 +62,8 @@ PMU_FORMAT_ATTR(contextid1,	"config:" __stringify(ETM_OPT_CTXTID));
>   PMU_FORMAT_ATTR(contextid2,	"config:" __stringify(ETM_OPT_CTXTID2));
>   PMU_FORMAT_ATTR(timestamp,	"config:" __stringify(ETM_OPT_TS));
>   PMU_FORMAT_ATTR(retstack,	"config:" __stringify(ETM_OPT_RETSTK));
> +PMU_FORMAT_ATTR(update_buf_on_pause,
> +		"config:" __stringify(ETM_OPT_UPDATE_BUF_ON_PAUSE));
>   /* preset - if sink ID is used as a configuration selector */
>   PMU_FORMAT_ATTR(preset,		"config:0-3");
>   /* Sink ID - same for all ETMs */
> @@ -103,6 +105,7 @@ static struct attribute *etm_config_formats_attr[] = {
>   	&format_attr_configid.attr,
>   	&format_attr_branch_broadcast.attr,
>   	&format_attr_cc_threshold.attr,
> +	&format_attr_update_buf_on_pause.attr,
>   	NULL,
>   };
>   
> @@ -434,6 +437,23 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
>   	if (!sink)
>   		goto err;
>   
> +	/* Populate the flag for updating buffer on AUX pause */
> +	event_data->update_buf_on_pause =
> +		!!(event->attr.config & BIT(ETM_OPT_UPDATE_BUF_ON_PAUSE));
> +
> +	if (event_data->update_buf_on_pause) {
> +		/*
> +		 * The per CPU sink has own interrupt handling, it might have
> +		 * race condition with updating buffer on AUX trace pause if
> +		 * it is invoked from NMI.  To avoid the race condition,
> +		 * disallows updating buffer for the per CPU sink case.
> +		 */
> +		if (coresight_is_percpu_sink(sink)) {
> +			dev_err(&sink->dev, "update_buf_on_pause is not permitted.\n");
> +			goto err;
> +		}
> +	}
> +
>   	/* If we don't have any CPUs ready for tracing, abort */
>   	cpu = cpumask_first(mask);
>   	if (cpu >= nr_cpu_ids)
> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
> index 744531158d6b..52b9385f8c11 100644
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.h
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
> @@ -51,6 +51,7 @@ struct etm_filters {
>    * @aux_hwid_done:	Whether a CPU has emitted the TraceID packet or not.
>    * @snk_config:		The sink configuration.
>    * @cfg_hash:		The hash id of any coresight config selected.
> + * @update_buf_on_pause: The flag to indicate updating buffer on AUX pause.
>    * @path:		An array of path, each slot for one CPU.
>    */
>   struct etm_event_data {
> @@ -59,6 +60,7 @@ struct etm_event_data {
>   	cpumask_t aux_hwid_done;
>   	void *snk_config;
>   	u32 cfg_hash;
> +	bool update_buf_on_pause;
>   	struct list_head * __percpu *path;
>   };
>   
> diff --git a/include/linux/coresight-pmu.h b/include/linux/coresight-pmu.h
> index 89b0ac0014b0..04147e30c2f2 100644
> --- a/include/linux/coresight-pmu.h
> +++ b/include/linux/coresight-pmu.h
> @@ -35,6 +35,7 @@
>   #define ETM_OPT_CTXTID2		15
>   #define ETM_OPT_TS		28
>   #define ETM_OPT_RETSTK		29
> +#define ETM_OPT_UPDATE_BUF_ON_PAUSE	30
>   
>   /* ETMv4 CONFIGR programming bits for the ETM OPTs */
>   #define ETM4_CFG_BIT_BB         3



From amelie.delaunay at foss.st.com  Mon Mar 10 07:05:19 2025
From: amelie.delaunay at foss.st.com (Amelie Delaunay)
Date: Mon, 10 Mar 2025 15:05:19 +0100
Subject: [PATCH v2 00/10] Expand STM32MP2 family with new SoC and boards
In-Reply-To: <20250225-b4-stm32mp2_new_dts-v2-0-1a628c1580c7@foss.st.com>
References: <20250225-b4-stm32mp2_new_dts-v2-0-1a628c1580c7@foss.st.com>
Message-ID: <6f776853-65e9-4574-85c2-c2a0446addfe@foss.st.com>

On 2/25/25 09:54, Amelie Delaunay wrote:
> Add STM32MP25 Discovery Kit board [1] STM32MP257F-DK. It is based on a
> different package of STM32MP257 SoC than STM32MP257F-EV1, and has 4GB of
> LPDDR4 instead of DDR4.
> Introduce two new SoC families [2] with Arm Cortex-A35 and Cortex-M33,
> in development:
> - STM32MP23x SoCs family, with STM32MP231 (single Arm Cortex-A35),
> STM32MP233 and STM32MP235 (dual Arm Cortex-A35) [3]. Add STM32MP235F-DK
> board to demonstrate the differences with STM32MP257F-DK board;
> - STM32MP21x SoCs family, based on Cortex-A35 single-core, with
> STM32MP211, STM32MP213 and STM32MP215. Add STM32MP215F-DK board based on
> STM32MP215 SoC, with 2GB of LPDDR4.
> 
> [1] https://www.st.com/en/evaluation-tools/stm32mp257f-dk.html
> [2] https://www.st.com/en/microcontrollers-microprocessors/stm32-arm-cortex-mpus.html
> [3] https://www.st.com/en/microcontrollers-microprocessors/stm32mp235.html
> 
> Signed-off-by: Amelie Delaunay <amelie.delaunay at foss.st.com>
> ---
> Changes in v2:
> - Address Krzysztof's comments:
>    - squash arm64 Kconfig updates for STM32MP21 and STM32MP23
>    - add new compatibles st,stm32mp21-syscfg and st,stm32mp23-syscfg
>    - comply with DTS coding style
>    - move interrupt controller node under soc
>    - remove status property from button nodes
> - Link to v1: https://lore.kernel.org/r/20250210-b4-stm32mp2_new_dts-v1-0-e8ef1e666c5e at foss.st.com

Hi,

Gentle ping, are there any additional comments on this series?

Regards,
Amelie

> 
> ---
> Alexandre Torgue (3):
>        arm64: dts: st: add stm32mp257f-dk board support
>        arm64: dts: st: introduce stm32mp23 SoCs family
>        arm64: dts: st: introduce stm32mp21 SoCs family
> 
> Amelie Delaunay (7):
>        dt-bindings: stm32: document stm32mp257f-dk board
>        arm64: Kconfig: expand STM32 Armv8 SoC with STM32MP21/STM32MP23 SoCs family
>        dt-bindings: stm32: add STM32MP21 and STM32MP23 compatibles for syscon
>        dt-bindings: stm32: document stm32mp235f-dk board
>        arm64: dts: st: add stm32mp235f-dk board support
>        dt-bindings: stm32: document stm32mp215f-dk board
>        arm64: dts: st: add stm32mp215f-dk board support
> 
>   .../bindings/arm/stm32/st,stm32-syscon.yaml        |    2 +
>   .../devicetree/bindings/arm/stm32/stm32.yaml       |   13 +
>   arch/arm64/Kconfig.platforms                       |    4 +
>   arch/arm64/boot/dts/st/Makefile                    |    6 +-
>   arch/arm64/boot/dts/st/stm32mp211.dtsi             |  128 +++
>   arch/arm64/boot/dts/st/stm32mp213.dtsi             |    9 +
>   arch/arm64/boot/dts/st/stm32mp215.dtsi             |    9 +
>   arch/arm64/boot/dts/st/stm32mp215f-dk.dts          |   49 +
>   arch/arm64/boot/dts/st/stm32mp21xc.dtsi            |    8 +
>   arch/arm64/boot/dts/st/stm32mp21xf.dtsi            |    8 +
>   arch/arm64/boot/dts/st/stm32mp231.dtsi             | 1214 ++++++++++++++++++++
>   arch/arm64/boot/dts/st/stm32mp233.dtsi             |   94 ++
>   arch/arm64/boot/dts/st/stm32mp235.dtsi             |   16 +
>   arch/arm64/boot/dts/st/stm32mp235f-dk.dts          |  113 ++
>   arch/arm64/boot/dts/st/stm32mp23xc.dtsi            |    8 +
>   arch/arm64/boot/dts/st/stm32mp23xf.dtsi            |    8 +
>   arch/arm64/boot/dts/st/stm32mp257f-dk.dts          |  113 ++
>   17 files changed, 1801 insertions(+), 1 deletion(-)
> ---
> base-commit: 8c6d469f524960a0f97ec74f1d9ac737a39c3f1e
> change-id: 20250210-b4-stm32mp2_new_dts-8fddd389850a
> 
> Best regards,


From krzk at kernel.org  Mon Mar 10 07:10:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 15:10:53 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <6e1757ea-3f5e-4cc0-b142-aee52f016c8f@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <6e1757ea-3f5e-4cc0-b142-aee52f016c8f@foss.st.com>
Message-ID: <ebc23aa2-c850-43c3-baa0-922da31208df@kernel.org>

On 10/03/2025 14:52, Patrice CHOTARD wrote:
> 
> 
> On 2/19/25 09:00, patrice.chotard at foss.st.com wrote:
>> From: Patrice Chotard <patrice.chotard at foss.st.com>
>>
>> Octo Memory Manager driver (OMM) manages:
>>   - the muxing between 2 OSPI busses and 2 output ports.
>>     There are 4 possible muxing configurations:
>>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>>         output is on port 2
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>>         OSPI2 output is on port 1
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>>   - the split of the memory area shared between the 2 OSPI instances.
>>   - chip select selection override.
>>   - the time between 2 transactions in multiplexed mode.
>>   - check firewall access.
>>



Please kindly trim the replies from unnecessary context. It makes it
much easier to find new content.

...
> 
> 
> Hi all,
> 
> Anybody alse has additionnal remarks on this driver ?

I am waiting too...

Best regards,
Krzysztof


From robh at kernel.org  Mon Mar 10 07:40:06 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 10 Mar 2025 09:40:06 -0500
Subject: [PATCH v3 02/18] dt-bindings: gpu: img: Add BXS-4-64
 devicetree bindings
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
Message-ID: <174161760551.1089.16761714043131512755.robh@kernel.org>


On Mon, 10 Mar 2025 13:10:26 +0000, Matt Coster wrote:
> Unlike AXE-1-16M, BXS-4-64 uses two power domains.
> 
> Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
> integration in the TI k3-j721s2.
> 
> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
> ---
> Changes in v3:
> - Include adding the second power domain so it's in context
> - Remove unnecessary example
> - Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
> Changes in v2:
> - Use normal reg syntax for 64-bit values
> - Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
> ---
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 34 +++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/gpu/img,powervr-rogue.example.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f at imgtec.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From robh at kernel.org  Mon Mar 10 07:40:08 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 10 Mar 2025 09:40:08 -0500
Subject: [PATCH v3 02/18] dt-bindings: gpu: img: Add BXS-4-64
 devicetree bindings
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
Message-ID: <174161760641.1135.692000381478156014.robh@kernel.org>


On Mon, 10 Mar 2025 13:10:26 +0000, Matt Coster wrote:
> Unlike AXE-1-16M, BXS-4-64 uses two power domains.
> 
> Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
> integration in the TI k3-j721s2.
> 
> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
> ---
> Changes in v3:
> - Include adding the second power domain so it's in context
> - Remove unnecessary example
> - Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
> Changes in v2:
> - Use normal reg syntax for 64-bit values
> - Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
> ---
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 34 +++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/gpu/img,powervr-rogue.example.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f at imgtec.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From mark.rutland at arm.com  Mon Mar 10 07:42:24 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 14:42:24 +0000
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <b1fb982a-4936-4c18-aaad-3e8e8f61bccc@arm.com>
References: <20250310062812.216031-1-anshuman.khandual@arm.com>
 <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com>
 <b1fb982a-4936-4c18-aaad-3e8e8f61bccc@arm.com>
Message-ID: <Z876UI5-xGRHl4td@J2N7QTR9R3.cambridge.arm.com>

On Mon, Mar 10, 2025 at 01:48:53PM +0000, Ryan Roberts wrote:
> On 10/03/2025 10:55, Mark Rutland wrote:
> > On Mon, Mar 10, 2025 at 11:58:12AM +0530, Anshuman Khandual wrote:
> >> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
> >> section mapping at all page table levels except the last level. This works
> >> fine as the section mapping masks are exactly the same (0x1UL) for all page
> >> table levels.
> >>
> >> This will change in the future with D128 page tables that have unique skip
> >> level values (SKL) required for creating section mapping at different page
> >> table levels. Hence use page table level specific section mapping macros
> >> instead of the common PMD_TYPE_SECT. While here also ensure that a section
> >> mapping is only created on page table levels which could support that on a
> >> given page size configuration otherwise fall back to create table entries.
> >>
> >> Cc: Catalin Marinas <catalin.marinas at arm.com>
> >> Cc: Will Deacon <will at kernel.org>
> >> Cc: Ryan Roberts <ryan.roberts at arm.com>
> >> Cc: Ard Biesheuvel <ardb at kernel.org>
> >> Cc: linux-kernel at vger.kernel.org
> >> Cc: linux-arm-kernel at lists.infradead.org
> >> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> >> ---
> >> This patch applies on v6.14-rc6
> >>
> >> Changes in V2:
> >>
> >> - Dropped PGD_TYPE_SECT macro and its instance from map_range()
> >> - Create table entries on levels where section mapping is not possible
> > 
> > On the last version, there was talk of an extant bug:
> > 
> >   https://lore.kernel.org/all/5f1b36e2-6455-44d9-97b0-253aefd5024f at arm.com/
> > 
> > ... did that turn out to not be the case?
> 
> In the absence of Ard (or anyone else) telling me it's not a bug, then I'll
> continue to assert that it is a bug, and should have a Fixes tag, and Cc stable.

Ok -- can we please have a description of the bug, and a fix
specifically for that, before we try to reshape this for D128?

IIUC the problem is that for a sufficiently large (and aligned) extent
of physical memory, we might try to create a block mapping larger than
the HW supports?

With that in mind, my earlier comment about LPA2 and blocks at level-0
is particularly relevant...

> >> Changes in V1:
> >>
> >> https://lore.kernel.org/all/20250303041834.2796751-1-anshuman.khandual at arm.com/
> >>
> >>  arch/arm64/kernel/pi/map_range.c | 38 +++++++++++++++++++++++++++++---
> >>  1 file changed, 35 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> >> index 2b69e3beeef8..25a70c675c4d 100644
> >> --- a/arch/arm64/kernel/pi/map_range.c
> >> +++ b/arch/arm64/kernel/pi/map_range.c
> >> @@ -11,6 +11,22 @@
> >>  
> >>  #include "pi.h"
> >>  
> >> +static bool sect_supported(int level)
> > 
> > What exactly is this function supposed to indicate?
> > 
> > Due to the 'default' case, it'll return true for level-3 tables where
> > sections/blocks aren't possible, but pages are. So maybe this is just
> > misnamed, and wants to be something like "leaf_supported()" ?
> 
> I always thought a "section" was (outdated?) linux terminology for a leaf
> mapping at any level. For my understanding, I think you're saying it
> specifically means a leaf mapping at any level other than the last level, so it
> is actually equivalent to a "block" mapping in the Arm ARM?

Yep -- "section" is old style terminology that's (roughly) equivalent to
"block" at level 2. When the arm64 port got written, the
"section"/"sect" terminology was inherited to mean "block" at any level.
Ideally we'd clean that up.

Historically ARM had "small pages", "large pages", "sections", and
"supersections".

See the ARMv7-A ARM (ARM DDI 0406C.d), page B3-1321.

> Either way, the intended semantic for this function is "is it valid to create a
> leaf mapping at the specified level?" where leaf = block or page.

Cool. With that in mind, having "leaf" in the name would be better.

Though TBH, maybe it makes more sense to split this up into separate
levels (as with the code in arch/arm64/mm/mmu.c) and handle each level
explicitly with a separate function. That way each level's check can be
handled within that level's function, and we can use the right types,
etc. It feels like that might be better for D128 in future?

Mark.

> 
> Thanks,
> Ryan
> 
> > 
> >> +{
> >> +	switch (level) {
> >> +	case -1:
> >> +		return false;
> >> +	case 0:
> >> +		if (IS_ENABLED(CONFIG_ARM64_16K_PAGES) ||
> >> +		    IS_ENABLED(CONFIG_ARM64_64K_PAGES))
> >> +			return false;
> >> +		else
> >> +			return true;
> > 
> > Surely:
> > 
> > 	case 0:
> > 		return IS_ENABLED(CONFIG_ARM64_4K_PAGES);
> > 
> > ... though that's only the case when LPA2 is supported and TCR_ELx.DS is
> > set.
> > 
> >> +	default:
> >> +		return true;
> > 
> > As above, what is this supposed to return for level-3 tables where
> > sections/blocks aren't possible?
> > 
> > Can we BUILD_BUG() for bogus levels?
> > 
> >> +	}
> >> +}
> >> +
> >>  /**
> >>   * map_range - Map a contiguous range of physical pages into virtual memory
> >>   *
> >> @@ -44,13 +60,29 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
> >>  	 * Set the right block/page bits for this level unless we are
> >>  	 * clearing the mapping
> >>  	 */
> >> -	if (protval)
> >> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> >> +	if (protval && sect_supported(level)) {
> > 
> > The existing code is trying to find the leaf prot for a given level of
> > table, so as-is checking sect_supported() is at best misleading.
> > 
> > If we're going to do something different below based on
> > sect_supported(), I reckon this should be moved into the path where
> > sect_supported() returned true, maybe factored out into a helper for
> > clarity.
> > 
> > Mark.
> > 
> >> +		switch (level) {
> >> +		case 3:
> >> +			protval |= PTE_TYPE_PAGE;
> >> +			break;
> >> +		case 2:
> >> +			protval |= PMD_TYPE_SECT;
> >> +			break;
> >> +		case 1:
> >> +			protval |= PUD_TYPE_SECT;
> >> +			break;
> >> +		case 0:
> >> +			protval |= P4D_TYPE_SECT;
> >> +			break;
> >> +		default:
> >> +			break;
> >> +		}
> >> +	}
> >>  
> >>  	while (start < end) {
> >>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
> >>  
> >> -		if (level < 3 && (start | next | pa) & lmask) {
> >> +		if ((level < 3 && (start | next | pa) & lmask) || !sect_supported(level)) {
> >>  			/*
> >>  			 * This chunk needs a finer grained mapping. Create a
> >>  			 * table mapping if necessary and recurse.
> >> -- 
> >> 2.25.1
> >>
> >>
> 


From Frank.li at nxp.com  Mon Mar 10 07:50:38 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 10:50:38 -0400
Subject: [PATCH 1/3] usb: chipidea: ci_hdrc_imx: fix usbmisc handling
In-Reply-To: <20250309175805.661684-2-pchelkin@ispras.ru>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
 <20250309175805.661684-2-pchelkin@ispras.ru>
Message-ID: <Z878PqYbtep0mOrx@lizhi-Precision-Tower-5810>

On Sun, Mar 09, 2025 at 08:57:57PM +0300, Fedor Pchelkin wrote:
> usbmisc is an optional device property so it is totally valid for the
> corresponding data->usbmisc_data to have a NULL value.
>
> Check that before dereferencing the pointer.
>
> Found by Linux Verification Center (linuxtesting.org) with Svace static
> analysis tool.

I have not seen any words "linuxtesting.org" in linux source tree. I am
not sure if it reproducable for other people. So this sense have not
provide much useful information.

Fixes itself is good.

Frank

>
> Fixes: 74adad500346 ("usb: chipidea: ci_hdrc_imx: decrement device's refcount in .remove() and in the error path of .probe()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
> ---
>  drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index 1a7fc638213e..619779eef333 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -534,7 +534,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  		cpu_latency_qos_remove_request(&data->pm_qos_req);
>  	data->ci_pdev = NULL;
>  err_put:
> -	put_device(data->usbmisc_data->dev);
> +	if (data->usbmisc_data)
> +		put_device(data->usbmisc_data->dev);
>  	return ret;
>  }
>
> @@ -559,7 +560,8 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
>  		if (data->hsic_pad_regulator)
>  			regulator_disable(data->hsic_pad_regulator);
>  	}
> -	put_device(data->usbmisc_data->dev);
> +	if (data->usbmisc_data)
> +		put_device(data->usbmisc_data->dev);
>  }
>
>  static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
> --
> 2.48.1
>


From Frank.li at nxp.com  Mon Mar 10 07:53:10 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 10:53:10 -0400
Subject: [PATCH 2/3] usb: chipidea: ci_hdrc_imx: disable regulator on
 error path in probe
In-Reply-To: <20250309175805.661684-3-pchelkin@ispras.ru>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
 <20250309175805.661684-3-pchelkin@ispras.ru>
Message-ID: <Z8781hzSKJ5P0gBe@lizhi-Precision-Tower-5810>

On Sun, Mar 09, 2025 at 08:57:58PM +0300, Fedor Pchelkin wrote:
> Upon encountering errors during the HSIC pinctrl handling section the
> regulator should be disabled.
>
> After the above-stated changes it is possible to jump onto
> "disable_hsic_regulator" label without having added the CPU latency QoS
> request previously. This would result in cpu_latency_qos_remove_request()
> yielding a WARNING.
>
> So rearrange the error handling path to follow the reverse order of
> different probing phases.

Suggest use devm_add_action() to simple whole error handle code.

>
> Found by Linux Verification Center (linuxtesting.org).

I think this sentense have not provide valuable informaiton for reader.

Frank

>
> Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional")
> Cc: stable at vger.kernel.org
> Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
> ---
>  drivers/usb/chipidea/ci_hdrc_imx.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index 619779eef333..3f11ae071c7f 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -407,13 +407,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  				"pinctrl_hsic_idle lookup failed, err=%ld\n",
>  					PTR_ERR(pinctrl_hsic_idle));
>  			ret = PTR_ERR(pinctrl_hsic_idle);
> -			goto err_put;
> +			goto disable_hsic_regulator;
>  		}
>
>  		ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle);
>  		if (ret) {
>  			dev_err(dev, "hsic_idle select failed, err=%d\n", ret);
> -			goto err_put;
> +			goto disable_hsic_regulator;
>  		}
>
>  		data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
> @@ -423,7 +423,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  				"pinctrl_hsic_active lookup failed, err=%ld\n",
>  					PTR_ERR(data->pinctrl_hsic_active));
>  			ret = PTR_ERR(data->pinctrl_hsic_active);
> -			goto err_put;
> +			goto disable_hsic_regulator;
>  		}
>  	}
>
> @@ -432,11 +432,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>
>  	ret = imx_get_clks(dev);
>  	if (ret)
> -		goto disable_hsic_regulator;
> +		goto qos_remove_request;
>
>  	ret = imx_prepare_enable_clks(dev);
>  	if (ret)
> -		goto disable_hsic_regulator;
> +		goto qos_remove_request;
>
>  	ret = clk_prepare_enable(data->clk_wakeup);
>  	if (ret)
> @@ -526,12 +526,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  	clk_disable_unprepare(data->clk_wakeup);
>  err_wakeup_clk:
>  	imx_disable_unprepare_clks(dev);
> +qos_remove_request:
> +	if (pdata.flags & CI_HDRC_PMQOS)
> +		cpu_latency_qos_remove_request(&data->pm_qos_req);
>  disable_hsic_regulator:
>  	if (data->hsic_pad_regulator)
>  		/* don't overwrite original ret (cf. EPROBE_DEFER) */
>  		regulator_disable(data->hsic_pad_regulator);
> -	if (pdata.flags & CI_HDRC_PMQOS)
> -		cpu_latency_qos_remove_request(&data->pm_qos_req);
>  	data->ci_pdev = NULL;
>  err_put:
>  	if (data->usbmisc_data)
> --
> 2.48.1
>


From ardb at kernel.org  Mon Mar 10 07:53:33 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Mon, 10 Mar 2025 15:53:33 +0100
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in map_range()
In-Reply-To: <Z876UI5-xGRHl4td@J2N7QTR9R3.cambridge.arm.com>
References: <20250310062812.216031-1-anshuman.khandual@arm.com>
 <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com> <b1fb982a-4936-4c18-aaad-3e8e8f61bccc@arm.com>
 <Z876UI5-xGRHl4td@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <CAMj1kXEZ86C8bouLt+xNkNr+L9AvCSQ2SZeJpLMtyvGo-8h6gw@mail.gmail.com>

On Mon, 10 Mar 2025 at 15:42, Mark Rutland <mark.rutland at arm.com> wrote:
>
> On Mon, Mar 10, 2025 at 01:48:53PM +0000, Ryan Roberts wrote:
> > On 10/03/2025 10:55, Mark Rutland wrote:
> > > On Mon, Mar 10, 2025 at 11:58:12AM +0530, Anshuman Khandual wrote:
> > >> Currently PMD section mapping mask i.e PMD_TYPE_SECT is used while creating
> > >> section mapping at all page table levels except the last level. This works
> > >> fine as the section mapping masks are exactly the same (0x1UL) for all page
> > >> table levels.
> > >>
> > >> This will change in the future with D128 page tables that have unique skip
> > >> level values (SKL) required for creating section mapping at different page
> > >> table levels. Hence use page table level specific section mapping macros
> > >> instead of the common PMD_TYPE_SECT. While here also ensure that a section
> > >> mapping is only created on page table levels which could support that on a
> > >> given page size configuration otherwise fall back to create table entries.
> > >>
> > >> Cc: Catalin Marinas <catalin.marinas at arm.com>
> > >> Cc: Will Deacon <will at kernel.org>
> > >> Cc: Ryan Roberts <ryan.roberts at arm.com>
> > >> Cc: Ard Biesheuvel <ardb at kernel.org>
> > >> Cc: linux-kernel at vger.kernel.org
> > >> Cc: linux-arm-kernel at lists.infradead.org
> > >> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> > >> ---
> > >> This patch applies on v6.14-rc6
> > >>
> > >> Changes in V2:
> > >>
> > >> - Dropped PGD_TYPE_SECT macro and its instance from map_range()
> > >> - Create table entries on levels where section mapping is not possible
> > >
> > > On the last version, there was talk of an extant bug:
> > >
> > >   https://lore.kernel.org/all/5f1b36e2-6455-44d9-97b0-253aefd5024f at arm.com/
> > >
> > > ... did that turn out to not be the case?
> >
> > In the absence of Ard (or anyone else) telling me it's not a bug, then I'll
> > continue to assert that it is a bug, and should have a Fixes tag, and Cc stable.
>
> Ok -- can we please have a description of the bug, and a fix
> specifically for that, before we try to reshape this for D128?
>
> IIUC the problem is that for a sufficiently large (and aligned) extent
> of physical memory, we might try to create a block mapping larger than
> the HW supports?
>

Yes. However, this code is only called to map the kernel, the DTB and
the ID map code and data pages, and so it seems unlikely that we'll
hit this bug in practice.

Nonetheless, it is a shortcoming that we should address to avoid
future surprises.

> With that in mind, my earlier comment about LPA2 and blocks at level-0
> is particularly relevant...
>

Indeed - at the higher levels, there is quite some variation between
page sizes, LPA2 vs !LPA2 etc in which level is the highest at which
block mappings are supported.

But given the context where this code is used, I'd prefer to simply
map everything down to level 2 or higher (for 64-bit descriptors)
rather than add elaborate rules for all these combinations that are
never exercised in practice. The net result should be identical.

...
>
> Though TBH, maybe it makes more sense to split this up into separate
> levels (as with the code in arch/arm64/mm/mmu.c) and handle each level
> explicitly with a separate function. That way each level's check can be
> handled within that level's function, and we can use the right types,
> etc. It feels like that might be better for D128 in future?
>

I have a slight inclination towards having a separate routine for
D128, but I can easily be persuaded otherwise.


From helgaas at kernel.org  Mon Mar 10 08:11:09 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 10 Mar 2025 10:11:09 -0500
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250226024256.1678103-3-hongxing.zhu@nxp.com>
Message-ID: <20250310151109.GA540579@bhelgaas>

On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> Use the domain number replace the hardcodes to uniquely identify
> different controller on i.MX8MQ platforms. No function changes.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 90ace941090f..ab9ebb783593 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -41,7 +41,6 @@
>  #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
>  #define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
>  #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11, 8)
> -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
>  
>  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
>  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  	struct dw_pcie *pci;
>  	struct imx_pcie *imx_pcie;
>  	struct device_node *np;
> -	struct resource *dbi_base;
>  	struct device_node *node = dev->of_node;
>  	int i, ret, req_cnt;
>  	u16 val;
> @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  			return PTR_ERR(imx_pcie->phy_base);
>  	}
>  
> -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev, 0, &dbi_base);
> -	if (IS_ERR(pci->dbi_base))
> -		return PTR_ERR(pci->dbi_base);

This makes me wonder.

IIUC this means that previously we set controller_id to 1 if the first
item in devicetree "reg" was 0x33c00000, and now we will set
controller_id to 1 if the devicetree "linux,pci-domain" property is 1.
This is good, but I think this new dependency on the correct
"linux,pci-domain" in devicetree should be mentioned in the commit
log.

My bigger worry is that we no longer set pci->dbi_base at all.  I see
that the only use of pci->dbi_base in pci-imx6.c was to determine the
controller_id, but this is a DWC-based driver, and the DWC core
certainly uses pci->dbi_base.  Are we sure that none of those DWC core
paths are important to pci-imx6.c?

>  	/* Fetch GPIOs */
>  	imx_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>  	if (IS_ERR(imx_pcie->reset_gpiod))
> @@ -1565,8 +1559,12 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  	switch (imx_pcie->drvdata->variant) {
>  	case IMX8MQ:
>  	case IMX8MQ_EP:
> -		if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR)
> -			imx_pcie->controller_id = 1;
> +		ret = of_get_pci_domain_nr(node);
> +		if (ret < 0 || ret > 1)
> +			return dev_err_probe(dev, -ENODEV,
> +					     "failed to get valid pcie domain\n");
> +		else
> +			imx_pcie->controller_id = ret;
>  		break;
>  	default:
>  		break;
> -- 
> 2.37.1
> 


From angelogioacchino.delregno at collabora.com  Mon Mar 10 08:23:13 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 16:23:13 +0100
Subject: [PATCH 05/14] ASoC: mediatek: mt8196: support audio clock control
In-Reply-To: <20250307124841.23777-6-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-6-darren.ye@mediatek.com>
Message-ID: <d3b7c00a-1d22-47f2-a4da-7062a08c9b12@collabora.com>

Il 07/03/25 13:47, Darren.Ye ha scritto:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Add audio clock wrapper and audio tuner control.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>   sound/soc/mediatek/mt8196/mt8196-afe-clk.c | 698 +++++++++++++++++++++
>   sound/soc/mediatek/mt8196/mt8196-afe-clk.h | 313 +++++++++
>   2 files changed, 1011 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.c
>   create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-clk.h
> 
> diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.c b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
> new file mode 100644
> index 000000000000..d1407d7bf775
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
> @@ -0,0 +1,698 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *  mt8196-afe-clk.c  --  Mediatek 8196 afe clock ctrl
> + *
> + *  Copyright (c) 2024 MediaTek Inc.
> + *  Author: Darren Ye <darren.ye at mediatek.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +#include "mt8196-afe-common.h"
> +#include "mt8196-afe-clk.h"
> +
> +static DEFINE_MUTEX(mutex_request_dram);
> +
> +static const char *aud_clks[CLK_NUM] = {
> +	[CLK_HOPPING] = "aud_hopping_clk",
> +	[CLK_F26M] = "aud_f26m_clk",
> +	[CLK_UL0_ADC_CLK] = "aud_ul0_adc_clk",
> +	[CLK_UL0_ADC_HIRES_CLK] = "aud_ul0_adc_hires_clk",
> +	[CLK_UL1_ADC_CLK] = "aud_ul1_adc_clk",
> +	[CLK_UL1_ADC_HIRES_CLK] = "aud_ul1_adc_hires_clk",
> +	[CLK_APLL1] = "aud_apll1_clk",
> +	[CLK_APLL2] = "aud_apll2_clk",
> +	[CLK_APLL1_TUNER] = "aud_apll_tuner1_clk",
> +	[CLK_APLL2_TUNER] = "aud_apll_tuner2_clk",
> +	[CLK_VLP_MUX_AUDIOINTBUS] = "vlp_mux_audio_int",
> +	[CLK_VLP_MUX_AUD_ENG1] = "vlp_mux_aud_eng1",
> +	[CLK_VLP_MUX_AUD_ENG2] = "vlp_mux_aud_eng2",
> +	[CLK_VLP_MUX_AUDIO_H] = "vlp_mux_audio_h",
> +	[CLK_VLP_CLK26M] = "vlp_clk26m_clk",
> +	[CLK_CK_MAINPLL_D4_D4] = "ck_mainpll_d4_d4",
> +	[CLK_CK_MUX_AUD_1] = "ck_mux_aud_1",
> +	[CLK_CK_APLL1_CK] = "ck_apll1_ck",
> +	[CLK_CK_MUX_AUD_2] = "ck_mux_aud_2",
> +	[CLK_CK_APLL2_CK] = "ck_apll2_ck",
> +	[CLK_CK_APLL1_D4] = "ck_apll1_d4",
> +	[CLK_CK_APLL2_D4] = "ck_apll2_d4",
> +	[CLK_CK_I2SIN0_M_SEL] = "ck_i2sin0_m_sel",
> +	[CLK_CK_I2SIN1_M_SEL] = "ck_i2sin1_m_sel",
> +	[CLK_CK_FMI2S_M_SEL] = "ck_fmi2s_m_sel",
> +	[CLK_CK_TDMOUT_M_SEL] = "ck_tdmout_m_sel",
> +	[CLK_CK_APLL12_DIV_I2SIN0] = "ck_apll12_div_i2sin0",
> +	[CLK_CK_APLL12_DIV_I2SIN1] = "ck_apll12_div_i2sin1",
> +	[CLK_CK_APLL12_DIV_FMI2S] = "ck_apll12_div_fmi2s",
> +	[CLK_CK_APLL12_DIV_TDMOUT_M] = "ck_apll12_div_tdmout_m",
> +	[CLK_CK_APLL12_DIV_TDMOUT_B] = "ck_apll12_div_tdmout_b",
> +	[CLK_CK_ADSP_SEL] = "ck_adsp_sel",
> +	[CLK_CLK26M] = "ck_clk26m_clk",
> +};
> +
> +int mt8196_set_audio_int_bus_parent(struct mtk_base_afe *afe,
> +				    int clk_id, bool int_bus)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	struct clk *clk;
> +	int ret;
> +
> +	if (clk_id >= CLK_NUM || clk_id < 0)
> +		return -EINVAL;
> +
> +	clk = int_bus ? afe_priv->clk[CLK_VLP_MUX_AUDIOINTBUS] :
> +			afe_priv->clk[CLK_VLP_MUX_AUDIO_H];
> +	ret = clk_set_parent(clk, afe_priv->clk[clk_id]);
> +	if (ret)
> +		dev_err(afe->dev, "%s() clk_set_parent %s fail %d, int_bus %d\n",
> +			__func__, aud_clks[clk_id], ret, int_bus);

if (ret) {
	dev_err....
	return ret;
}

return 0;

> +
> +	return ret;
> +}
> +

..snip..

> +
> +int mt8196_afe_disable_apll(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	int ret = 0;
> +
> +	dev_dbg(afe->dev, "%s() successfully start\n", __func__);
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_VLP_MUX_AUDIO_H], ret);
> +		goto EXIT;

You don't need the goto here.
Just return ret.

> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_1]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_CK_MUX_AUD_1], ret);
> +		goto EXIT;

Here you do need the goto, but that's to revert the changes that you've done
with the previous clk_prepare_enable() call.

> +	}
> +
> +	ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_1],
> +			     afe_priv->clk[CLK_CLK26M]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +			__func__, aud_clks[CLK_CK_MUX_AUD_1],
> +			aud_clks[CLK_CLK26M], ret);
> +		goto EXIT;
> +	}
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_CK_MUX_AUD_2]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_CK_MUX_AUD_2], ret);
> +		goto EXIT;
> +	}
> +
> +	ret = clk_set_parent(afe_priv->clk[CLK_CK_MUX_AUD_2],
> +			     afe_priv->clk[CLK_CLK26M]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
> +			__func__, aud_clks[CLK_CK_MUX_AUD_2],
> +			aud_clks[CLK_CLK26M], ret);
> +		goto EXIT;
> +	}
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_1]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_CK_MUX_AUD_2]);
> +	mt8196_set_audio_int_bus_parent(afe, CLK_VLP_CLK26M, false);
> +	clk_disable_unprepare(afe_priv->clk[CLK_VLP_MUX_AUDIO_H]);
> +
> +	return 0;
> +EXIT:

lower case please.

> +	return ret;
> +}
> +
> +static int mt8196_afe_apll_init(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +
> +	/* VLP_APLL1_CON0 = 0x6f28bd4c
> +	 * VLP_APLL2_CON2 = 0x78FD5264
> +	 * VLP_APLL1_TUNER_CON0 = 0x6f28bd4d
> +	 * VLP_APLL2_TUNER_CON0 = 0x78fd5265
> +	 */
> +	if (afe_priv->vlp_ck) {
> +		regmap_write(afe_priv->vlp_ck, VLP_APLL1_TUNER_CON0, 0x6f28bd4d);
> +		regmap_write(afe_priv->vlp_ck, VLP_APLL2_TUNER_CON0, 0x78fd5265);

No magic numbers please.

> +	} else {
> +		dev_warn(afe->dev, "%s vlp_ck regmap is null ptr\n", __func__);
> +	}
> +	return 0;
> +}
> +

..snip..

> +int mt8196_apll1_enable(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* setting for APLL */
> +	apll1_mux_setting(afe, true);
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_APLL1], ret);
> +		goto ERR_CLK_APLL1;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_APLL1_TUNER], ret);
> +		goto ERR_CLK_APLL1_TUNER;
> +	}
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
> +			   0x0000FFF7, 0x00000372);

No magic numbers please.

> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);
> +
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
> +			   AUDIO_APLL1_EN_ON_MASK_SFT,
> +			   0x1 << AUDIO_APLL1_EN_ON_SFT);
> +	return 0;
> +
> +ERR_CLK_APLL1_TUNER:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> +ERR_CLK_APLL1:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1]);
> +
> +	return ret;
> +}
> +
> +void mt8196_apll1_disable(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
> +			   AUDIO_APLL1_EN_ON_MASK_SFT,
> +			   0x0 << AUDIO_APLL1_EN_ON_SFT);

0 << (anything) is ... zero. Just write 0.

> +
> +	regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);

That 0x1 is a mask for a bit

#define SOMETHING BIT(0)

regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, SOMETHING, 0);

> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL1]);
> +
> +	apll1_mux_setting(afe, false);
> +}
> +
> +int mt8196_apll2_enable(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	int ret;
> +
> +	/* setting for APLL */
> +	apll2_mux_setting(afe, true);
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_APLL2], ret);
> +		goto ERR_CLK_APLL2;
> +	}
> +
> +	ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
> +	if (ret) {
> +		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
> +			__func__, aud_clks[CLK_APLL2_TUNER], ret);
> +		goto ERR_CLK_APLL2_TUNER;
> +	}
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
> +			   0x0000FFF7, 0x00000374);
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);
> +
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
> +			   AUDIO_APLL2_EN_ON_MASK_SFT,
> +			   0x1 << AUDIO_APLL2_EN_ON_SFT);
> +
> +	return 0;
> +
> +ERR_CLK_APLL2_TUNER:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> +ERR_CLK_APLL2:
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2]);
> +
> +	return ret;
> +
> +	return 0;
> +}
> +
> +void mt8196_apll2_disable(struct mtk_base_afe *afe)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +
> +	regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0,
> +			   AUDIO_APLL2_EN_ON_MASK_SFT,
> +			   0x0 << AUDIO_APLL2_EN_ON_SFT);
> +
> +	regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);
> +
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
> +	clk_disable_unprepare(afe_priv->clk[CLK_APLL2]);
> +
> +	apll2_mux_setting(afe, false);
> +}
> +
> +int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll)
> +{
> +	return (apll == MT8196_APLL1) ? 180633600 : 196608000;

If those are PLLs for real (and they are), you should read the rate from the actual
PLL, instead of just ignoring everything and pretending that the rate is either
X or Y.

> +}
> +
> +int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
> +{
> +	return ((rate % 8000) == 0) ? MT8196_APLL2 : MT8196_APLL1;
> +}
> +
> +int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
> +{
> +	if (strcmp(name, APLL1_W_NAME) == 0)
> +		return MT8196_APLL1;
> +	else
> +		return MT8196_APLL2;
> +}
> +

..snip..

> diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.h b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
> new file mode 100644
> index 000000000000..0094aebc8bba
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
> @@ -0,0 +1,313 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * mt8196-afe-clk.h  --  Mediatek 8196 afe clock ctrl definition
> + *
> + * Copyright (c) 2024 MediaTek Inc.
> + *  Author: Darren Ye <darren.ye at mediatek.com>
> + */
> +
> +#ifndef _MT8196_AFE_CLOCK_CTRL_H_
> +#define _MT8196_AFE_CLOCK_CTRL_H_
> +
> +// vlp_cksys_clk: 0x1c016000

Consistent comment style please.

> +#define VLP_AP_PLL_CON3 0x0264
> +#define VLP_APLL1_CON0 0x0274
> +#define VLP_APLL1_CON1 0x0278
> +#define VLP_APLL1_CON2 0x027c
> +#define VLP_APLL1_CON4 0x0284
> +#define VLP_APLL1_TUNER_CON0 0x02a4
> +
> +#define VLP_APLL2_CON0 0x028c
> +#define VLP_APLL2_CON1 0x0290
> +#define VLP_APLL2_CON2 0x0294
> +#define VLP_APLL2_CON4 0x029c
> +#define VLP_APLL2_TUNER_CON0 0x02a8
> +#define VLP_CLK_CFG_UPDATE1 0x0008
> +
> +// cksys_clk: 0x10000000
> +#define CLK_CFG_13 0x00e0
> +#define CLK_CFG_UPDATE1 0x0008
> +
> +#define CLK_AUDDIV_0 0x020c
> +#define CLK_AUDDIV_2 0x0214
> +#define CLK_AUDDIV_5 0x0228
> +
> +#define CKSYS_AUD_TOP_CFG 0x0218
> +
> +/* CLK_AUDDIV_0 */
> +#define APLL12_DIV_I2SIN0_PDN_SFT               0
> +#define APLL12_DIV_I2SIN0_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN0_PDN_MASK_SFT          (0x1 << 0)

This is BIT(0)

> +#define APLL12_DIV_I2SIN1_PDN_SFT               1
> +#define APLL12_DIV_I2SIN1_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN1_PDN_MASK_SFT          (0x1 << 1)

BIT(1)

> +#define APLL12_DIV_I2SIN2_PDN_SFT               2
> +#define APLL12_DIV_I2SIN2_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN2_PDN_MASK_SFT          (0x1 << 2)

BIT(2)

> +#define APLL12_DIV_I2SIN3_PDN_SFT               3
> +#define APLL12_DIV_I2SIN3_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN3_PDN_MASK_SFT          (0x1 << 3)

...etc

> +#define APLL12_DIV_I2SIN4_PDN_SFT               4
> +#define APLL12_DIV_I2SIN4_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN4_PDN_MASK_SFT          (0x1 << 4)
> +#define APLL12_DIV_I2SIN6_PDN_SFT               5
> +#define APLL12_DIV_I2SIN6_PDN_MASK              0x1
> +#define APLL12_DIV_I2SIN6_PDN_MASK_SFT          (0x1 << 5)
> +#define APLL12_DIV_I2SOUT0_PDN_SFT              6
> +#define APLL12_DIV_I2SOUT0_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT0_PDN_MASK_SFT         (0x1 << 6)
> +#define APLL12_DIV_I2SOUT1_PDN_SFT              7
> +#define APLL12_DIV_I2SOUT1_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT1_PDN_MASK_SFT         (0x1 << 7)
> +#define APLL12_DIV_I2SOUT2_PDN_SFT              8
> +#define APLL12_DIV_I2SOUT2_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT2_PDN_MASK_SFT         (0x1 << 8)
> +#define APLL12_DIV_I2SOUT3_PDN_SFT              9
> +#define APLL12_DIV_I2SOUT3_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT3_PDN_MASK_SFT         (0x1 << 9)
> +#define APLL12_DIV_I2SOUT4_PDN_SFT              10
> +#define APLL12_DIV_I2SOUT4_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT4_PDN_MASK_SFT         (0x1 << 10)
> +#define APLL12_DIV_I2SOUT6_PDN_SFT              11
> +#define APLL12_DIV_I2SOUT6_PDN_MASK             0x1
> +#define APLL12_DIV_I2SOUT6_PDN_MASK_SFT         (0x1 << 11)
> +#define APLL12_DIV_FMI2S_PDN_SFT                12
> +#define APLL12_DIV_FMI2S_PDN_MASK               0x1
> +#define APLL12_DIV_FMI2S_PDN_MASK_SFT           (0x1 << 12)
> +#define APLL12_DIV_TDMOUT_M_PDN_SFT             13
> +#define APLL12_DIV_TDMOUT_M_PDN_MASK            0x1
> +#define APLL12_DIV_TDMOUT_M_PDN_MASK_SFT        (0x1 << 13)
> +#define APLL12_DIV_TDMOUT_B_PDN_SFT             14
> +#define APLL12_DIV_TDMOUT_B_PDN_MASK            0x1
> +#define APLL12_DIV_TDMOUT_B_PDN_MASK_SFT        (0x1 << 14)
> +#define APLL_I2SIN0_MCK_SEL_SFT                 16
> +#define APLL_I2SIN0_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN0_MCK_SEL_MASK_SFT            (0x1 << 16)
> +#define APLL_I2SIN1_MCK_SEL_SFT                 17
> +#define APLL_I2SIN1_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN1_MCK_SEL_MASK_SFT            (0x1 << 17)
> +#define APLL_I2SIN2_MCK_SEL_SFT                 18
> +#define APLL_I2SIN2_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN2_MCK_SEL_MASK_SFT            (0x1 << 18)
> +#define APLL_I2SIN3_MCK_SEL_SFT                 19
> +#define APLL_I2SIN3_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN3_MCK_SEL_MASK_SFT            (0x1 << 19)
> +#define APLL_I2SIN4_MCK_SEL_SFT                 20
> +#define APLL_I2SIN4_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN4_MCK_SEL_MASK_SFT            (0x1 << 20)
> +#define APLL_I2SIN6_MCK_SEL_SFT                 21
> +#define APLL_I2SIN6_MCK_SEL_MASK                0x1
> +#define APLL_I2SIN6_MCK_SEL_MASK_SFT            (0x1 << 21)
> +#define APLL_I2SOUT0_MCK_SEL_SFT                22
> +#define APLL_I2SOUT0_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT0_MCK_SEL_MASK_SFT           (0x1 << 22)
> +#define APLL_I2SOUT1_MCK_SEL_SFT                23
> +#define APLL_I2SOUT1_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT1_MCK_SEL_MASK_SFT           (0x1 << 23)
> +#define APLL_I2SOUT2_MCK_SEL_SFT                24
> +#define APLL_I2SOUT2_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT2_MCK_SEL_MASK_SFT           (0x1 << 24)
> +#define APLL_I2SOUT3_MCK_SEL_SFT                25
> +#define APLL_I2SOUT3_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT3_MCK_SEL_MASK_SFT           (0x1 << 25)
> +#define APLL_I2SOUT4_MCK_SEL_SFT                26
> +#define APLL_I2SOUT4_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT4_MCK_SEL_MASK_SFT           (0x1 << 26)
> +#define APLL_I2SOUT6_MCK_SEL_SFT                27
> +#define APLL_I2SOUT6_MCK_SEL_MASK               0x1
> +#define APLL_I2SOUT6_MCK_SEL_MASK_SFT           (0x1 << 27)
> +#define APLL_FMI2S_MCK_SEL_SFT                  28
> +#define APLL_FMI2S_MCK_SEL_MASK                 0x1
> +#define APLL_FMI2S_MCK_SEL_MASK_SFT             (0x1 << 28)
> +#define APLL_TDMOUT_MCK_SEL_SFT                 29
> +#define APLL_TDMOUT_MCK_SEL_MASK                0x1
> +#define APLL_TDMOUT_MCK_SEL_MASK_SFT            (0x1 << 29)
> +
> +/* CLK_AUDDIV_1 */
> +#define APLL12_DIV_I2SIN0_INV_SFT               0
> +#define APLL12_DIV_I2SIN0_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN0_INV_MASK_SFT          (0x1 << 0)
> +#define APLL12_DIV_I2SIN1_INV_SFT               1
> +#define APLL12_DIV_I2SIN1_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN1_INV_MASK_SFT          (0x1 << 1)
> +#define APLL12_DIV_I2SIN2_INV_SFT               2
> +#define APLL12_DIV_I2SIN2_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN2_INV_MASK_SFT          (0x1 << 2)
> +#define APLL12_DIV_I2SIN3_INV_SFT               3
> +#define APLL12_DIV_I2SIN3_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN3_INV_MASK_SFT          (0x1 << 3)
> +#define APLL12_DIV_I2SIN4_INV_SFT               4
> +#define APLL12_DIV_I2SIN4_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN4_INV_MASK_SFT          (0x1 << 4)
> +#define APLL12_DIV_I2SIN6_INV_SFT               5
> +#define APLL12_DIV_I2SIN6_INV_MASK              0x1
> +#define APLL12_DIV_I2SIN6_INV_MASK_SFT          (0x1 << 5)
> +#define APLL12_DIV_I2SOUT0_INV_SFT              6
> +#define APLL12_DIV_I2SOUT0_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT0_INV_MASK_SFT         (0x1 << 6)
> +#define APLL12_DIV_I2SOUT1_INV_SFT              7
> +#define APLL12_DIV_I2SOUT1_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT1_INV_MASK_SFT         (0x1 << 7)
> +#define APLL12_DIV_I2SOUT2_INV_SFT              8
> +#define APLL12_DIV_I2SOUT2_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT2_INV_MASK_SFT         (0x1 << 8)
> +#define APLL12_DIV_I2SOUT3_INV_SFT              9
> +#define APLL12_DIV_I2SOUT3_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT3_INV_MASK_SFT         (0x1 << 9)
> +#define APLL12_DIV_I2SOUT4_INV_SFT              10
> +#define APLL12_DIV_I2SOUT4_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT4_INV_MASK_SFT         (0x1 << 10)
> +#define APLL12_DIV_I2SOUT6_INV_SFT              11
> +#define APLL12_DIV_I2SOUT6_INV_MASK             0x1
> +#define APLL12_DIV_I2SOUT6_INV_MASK_SFT         (0x1 << 11)
> +#define APLL12_DIV_FMI2S_INV_SFT                12
> +#define APLL12_DIV_FMI2S_INV_MASK               0x1
> +#define APLL12_DIV_FMI2S_INV_MASK_SFT           (0x1 << 12)
> +#define APLL12_DIV_TDMOUT_M_INV_SFT             13
> +#define APLL12_DIV_TDMOUT_M_INV_MASK            0x1
> +#define APLL12_DIV_TDMOUT_M_INV_MASK_SFT        (0x1 << 13)
> +#define APLL12_DIV_TDMOUT_B_INV_SFT             14
> +#define APLL12_DIV_TDMOUT_B_INV_MASK            0x1
> +#define APLL12_DIV_TDMOUT_B_INV_MASK_SFT        (0x1 << 14)
> +
> +/* CLK_AUDDIV_2 */
> +#define APLL12_CK_DIV_I2SIN0_SFT                0
> +#define APLL12_CK_DIV_I2SIN0_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN0_MASK_SFT           (0xff << 0)
> +#define APLL12_CK_DIV_I2SIN1_SFT                8
> +#define APLL12_CK_DIV_I2SIN1_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN1_MASK_SFT           (0xff << 8)
> +#define APLL12_CK_DIV_I2SIN2_SFT                16
> +#define APLL12_CK_DIV_I2SIN2_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN2_MASK_SFT           (0xff << 16)
> +#define APLL12_CK_DIV_I2SIN3_SFT                24
> +#define APLL12_CK_DIV_I2SIN3_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN3_MASK_SFT           (0xff << 24)
> +
> +/* AUD_TOP_CFG */
> +#define AUD_TOP_CFG_SFT                         0
> +#define AUD_TOP_CFG_MASK                        0xffffffff
> +#define AUD_TOP_CFG_MASK_SFT                    (0xffffffff << 0)

Both of these are GENMASK(31, 0)

> +
> +/* AUD_TOP_MON */
> +#define AUD_TOP_MON_SFT                         0
> +#define AUD_TOP_MON_MASK                        0xffffffff
> +#define AUD_TOP_MON_MASK_SFT                    (0xffffffff << 0)

same

> +
> +/* CLK_AUDDIV_3 */
> +#define APLL12_CK_DIV_I2SIN4_SFT                0
> +#define APLL12_CK_DIV_I2SIN4_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN4_MASK_SFT           (0xff << 0)

GENMASK(7, 0)

> +#define APLL12_CK_DIV_I2SIN6_SFT                8
> +#define APLL12_CK_DIV_I2SIN6_MASK               0xff
> +#define APLL12_CK_DIV_I2SIN6_MASK_SFT           (0xff << 8)

GENMASK(15, 8)

> +#define APLL12_CK_DIV_I2SOUT0_SFT               16
> +#define APLL12_CK_DIV_I2SOUT0_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT0_MASK_SFT          (0xff << 16)

...etc

> +#define APLL12_CK_DIV_I2SOUT1_SFT               24
> +#define APLL12_CK_DIV_I2SOUT1_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT1_MASK_SFT          (0xff << 24)
> +
> +/* CLK_AUDDIV_4 */
> +#define APLL12_CK_DIV_I2SOUT2_SFT               0
> +#define APLL12_CK_DIV_I2SOUT2_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT2_MASK_SFT          (0xff << 0)
> +#define APLL12_CK_DIV_I2SOUT3_SFT               8
> +#define APLL12_CK_DIV_I2SOUT3_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT3_MASK_SFT          (0xff << 8)
> +#define APLL12_CK_DIV_I2SOUT4_SFT               16
> +#define APLL12_CK_DIV_I2SOUT4_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT4_MASK_SFT          (0xff << 16)
> +#define APLL12_CK_DIV_I2SOUT6_SFT               24
> +#define APLL12_CK_DIV_I2SOUT6_MASK              0xff
> +#define APLL12_CK_DIV_I2SOUT6_MASK_SFT          (0xff << 24)
> +
> +/* CLK_AUDDIV_5 */
> +#define APLL12_CK_DIV_FMI2S_SFT                 0
> +#define APLL12_CK_DIV_FMI2S_MASK                0xff
> +#define APLL12_CK_DIV_FMI2S_MASK_SFT            (0xff << 0)
> +#define APLL12_CK_DIV_TDMOUT_M_SFT              8
> +#define APLL12_CK_DIV_TDMOUT_M_MASK             0xff
> +#define APLL12_CK_DIV_TDMOUT_M_MASK_SFT         (0xff << 8)
> +#define APLL12_CK_DIV_TDMOUT_B_SFT              16
> +#define APLL12_CK_DIV_TDMOUT_B_MASK             0xff
> +#define APLL12_CK_DIV_TDMOUT_B_MASK_SFT         (0xff << 16)
> +
> +/* APLL */
> +#define APLL1_W_NAME "APLL1"
> +#define APLL2_W_NAME "APLL2"
> +enum {
> +	MT8196_APLL1 = 0,
> +	MT8196_APLL2,
> +};
> +
> +enum {
> +	/* afe clk */
> +	CLK_HOPPING = 0,
> +	CLK_F26M,
> +	CLK_UL0_ADC_CLK,
> +	CLK_UL0_ADC_HIRES_CLK,
> +	CLK_UL1_ADC_CLK,
> +	CLK_UL1_ADC_HIRES_CLK,
> +	CLK_APLL1,
> +	CLK_APLL2,
> +	CLK_APLL1_TUNER,
> +	CLK_APLL2_TUNER,
> +	/* vlp clk */
> +	CLK_VLP_MUX_AUDIOINTBUS,
> +	CLK_VLP_MUX_AUD_ENG1,
> +	CLK_VLP_MUX_AUD_ENG2,
> +	CLK_VLP_MUX_AUDIO_H,
> +	CLK_VLP_CLK26M,
> +	/* ck clk */
> +	CLK_CK_MAINPLL_D4_D4,
> +	CLK_CK_MUX_AUD_1,
> +	CLK_CK_APLL1_CK,
> +	CLK_CK_MUX_AUD_2,
> +	CLK_CK_APLL2_CK,
> +	CLK_CK_APLL1_D4,
> +	CLK_CK_APLL2_D4,
> +	CLK_CK_I2SIN0_M_SEL,
> +	CLK_CK_I2SIN1_M_SEL,
> +	CLK_CK_FMI2S_M_SEL,
> +	CLK_CK_TDMOUT_M_SEL,
> +	CLK_CK_APLL12_DIV_I2SIN0,
> +	CLK_CK_APLL12_DIV_I2SIN1,
> +	CLK_CK_APLL12_DIV_FMI2S,
> +	CLK_CK_APLL12_DIV_TDMOUT_M,
> +	CLK_CK_APLL12_DIV_TDMOUT_B,
> +	CLK_CK_ADSP_SEL,
> +	CLK_CLK26M,
> +	CLK_NUM
> +};
> +
> +struct mtk_base_afe;
> +
> +int mt8196_init_clock(struct mtk_base_afe *afe);
> +int mt8196_afe_enable_clock(struct mtk_base_afe *afe);
> +void mt8196_afe_disable_clock(struct mtk_base_afe *afe);
> +int mt8196_afe_disable_apll(struct mtk_base_afe *afe);
> +
> +int mt8196_afe_dram_request(struct device *dev);
> +int mt8196_afe_dram_release(struct device *dev);
> +
> +int mt8196_apll1_enable(struct mtk_base_afe *afe);
> +void mt8196_apll1_disable(struct mtk_base_afe *afe);
> +
> +int mt8196_apll2_enable(struct mtk_base_afe *afe);
> +void mt8196_apll2_disable(struct mtk_base_afe *afe);
> +
> +int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll);
> +int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
> +int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
> +
> +void aud_intbus_mux_sel(unsigned int aud_idx);
> +
> +/* these will be replaced by using CCF */

Well, just replace them now instead of fixing them later.

Regards,
Angelo

> +int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
> +int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id);
> +
> +int mt8196_set_audio_int_bus_parent(struct mtk_base_afe *afe,
> +				    int clk_id, bool int_bus);
> +
> +#endif



From angelogioacchino.delregno at collabora.com  Mon Mar 10 08:23:14 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 16:23:14 +0100
Subject: [PATCH 04/14] ASoC: mediatek: mt8196: add common interface for
 mt8196 DAI driver
In-Reply-To: <20250307124841.23777-5-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-5-darren.ye@mediatek.com>
Message-ID: <5983252e-22b6-4150-a770-a6b64031daf5@collabora.com>

Il 07/03/25 13:47, Darren.Ye ha scritto:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Implement sample rate conversion and set private data for mt8196.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>   .../soc/mediatek/mt8196/mt8196-afe-control.c  | 109 ++++++++++++++++++
>   1 file changed, 109 insertions(+)
>   create mode 100644 sound/soc/mediatek/mt8196/mt8196-afe-control.c
> 
> diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-control.c b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
> new file mode 100644
> index 000000000000..bb85f4ad8585
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8196/mt8196-afe-control.c
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *  MediaTek ALSA SoC Audio Control
> + *
> + *  Copyright (c) 2024 MediaTek Inc.
> + *  Author: Darren Ye <darren.ye at mediatek.com>
> + */
> +
> +#include "mt8196-afe-common.h"
> +#include <linux/pm_runtime.h>
> +
> +unsigned int mt8196_general_rate_transform(struct device *dev,
> +					   unsigned int rate)
> +{
> +	switch (rate) {
> +	case 8000:
> +		return MTK_AFE_IPM2P0_RATE_8K;
> +	case 11025:
> +		return MTK_AFE_IPM2P0_RATE_11K;
> +	case 12000:
> +		return MTK_AFE_IPM2P0_RATE_12K;
> +	case 16000:
> +		return MTK_AFE_IPM2P0_RATE_16K;
> +	case 22050:
> +		return MTK_AFE_IPM2P0_RATE_22K;
> +	case 24000:
> +		return MTK_AFE_IPM2P0_RATE_24K;
> +	case 32000:
> +		return MTK_AFE_IPM2P0_RATE_32K;
> +	case 44100:
> +		return MTK_AFE_IPM2P0_RATE_44K;
> +	case 48000:
> +		return MTK_AFE_IPM2P0_RATE_48K;
> +	case 88200:
> +		return MTK_AFE_IPM2P0_RATE_88K;
> +	case 96000:
> +		return MTK_AFE_IPM2P0_RATE_96K;
> +	case 176400:
> +		return MTK_AFE_IPM2P0_RATE_176K;
> +	case 192000:
> +		return MTK_AFE_IPM2P0_RATE_192K;
> +	/* not support 260K */
> +	case 352800:
> +		return MTK_AFE_IPM2P0_RATE_352K;
> +	case 384000:
> +		return MTK_AFE_IPM2P0_RATE_384K;
> +	default:
> +		dev_info(dev, "%s(), rate %u invalid, use %d!!!\n",
> +			 __func__,
> +			 rate, MTK_AFE_IPM2P0_RATE_48K);
> +		return MTK_AFE_IPM2P0_RATE_48K;
> +	}
> +}
> +
> +static unsigned int pcm_rate_transform(struct device *dev,
> +				       unsigned int rate)
> +{

You have this function in mt8186-afe-control.c and mt8192-afe-control.c, with
the only difference being the default case.

Please commonize this function and handle the default case for each SoC (if needed)
in each SoC-specific driver.

While at it, please do the same with mt8196_general_rate_transform, as this IPM2.0
will be in other MediaTek SoCs, and this function will otherwise be commonized next
time anyway.

Possible names could be mtk_afe_pcm_rate_transform() for one, and probably
mtk_ipm20_general_rate_transform() for the other.

> +	switch (rate) {
> +	case 8000:
> +		return MTK_AFE_PCM_RATE_8K;
> +	case 16000:
> +		return MTK_AFE_PCM_RATE_16K;
> +	case 32000:
> +		return MTK_AFE_PCM_RATE_32K;
> +	case 48000:
> +		return MTK_AFE_PCM_RATE_48K;
> +	default:
> +		dev_info(dev, "%s(), rate %u invalid, use %d!!!\n",
> +			 __func__,
> +			 rate, MTK_AFE_PCM_RATE_32K);
> +		return MTK_AFE_PCM_RATE_32K;
> +	}
> +}
> +
> +unsigned int mt8196_rate_transform(struct device *dev,
> +				   unsigned int rate, int aud_blk)
> +{
> +	switch (aud_blk) {
> +	case MT8196_DAI_PCM_0:
> +	case MT8196_DAI_PCM_1:
> +		return pcm_rate_transform(dev, rate);
> +	default:
> +		return mt8196_general_rate_transform(dev, rate);
> +	}
> +}
> +
> +int mt8196_dai_set_priv(struct mtk_base_afe *afe, int id,
> +			int priv_size, const void *priv_data)
> +{
> +	struct mt8196_afe_private *afe_priv = afe->platform_priv;
> +	void *temp_data;
> +
> +	temp_data = devm_kzalloc(afe->dev,
> +				 priv_size,
> +				 GFP_KERNEL);
> +	if (!temp_data)
> +		return -ENOMEM;
> +
> +	if (priv_data)
> +		memcpy(temp_data, priv_data, priv_size);
> +
> +	if (id >= MT8196_DAI_NUM || id < 0)
> +		return -EINVAL;
> +
> +	afe_priv->dai_priv[id] = temp_data;
> +
> +	return 0;
> +}
> +




From angelogioacchino.delregno at collabora.com  Mon Mar 10 08:23:15 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 10 Mar 2025 16:23:15 +0100
Subject: [PATCH 01/14] ASoC: mediatek: common: modify mtk afe common
 driver for mt8196
In-Reply-To: <20250307124841.23777-2-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com>
 <20250307124841.23777-2-darren.ye@mediatek.com>
Message-ID: <b5fd1376-6abb-40c1-b3f0-238e2b0056fa@collabora.com>

Il 07/03/25 13:47, Darren.Ye ha scritto:
> From: Darren Ye <darren.ye at mediatek.com>
> 
> Export register read and write interface, add sample reate interface, and
> update the mtk_memif_set_channel interface for the mt8196 platform.
> 
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>
> ---
>   sound/soc/mediatek/common/mtk-afe-fe-dai.c | 30 ++++++++++++++--------
>   sound/soc/mediatek/common/mtk-afe-fe-dai.h |  6 +++++
>   sound/soc/mediatek/common/mtk-base-afe.h   | 13 ++++++++++
>   3 files changed, 38 insertions(+), 11 deletions(-)
> 
> diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> index 3809068f5620..c36dae520f04 100644
> --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
> @@ -18,7 +18,7 @@
>   
>   #define AFE_BASE_END_OFFSET 8
>   
> -static int mtk_regmap_update_bits(struct regmap *map, int reg,
> +int mtk_regmap_update_bits(struct regmap *map, int reg,
>   			   unsigned int mask,
>   			   unsigned int val, int shift)
>   {
> @@ -26,13 +26,16 @@ static int mtk_regmap_update_bits(struct regmap *map, int reg,
>   		return 0;
>   	return regmap_update_bits(map, reg, mask << shift, val << shift);
>   }
> +EXPORT_SYMBOL(mtk_regmap_update_bits);

Please don't export this function: it's not the greatest, `reg` should be unsigned
and so it should the shift - it's kinda wrong in principle, and you can simply use
regmap_update_bits() directly in your drivers. Please, do so.

> +
> +int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
>   
> -static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
>   {
>   	if (reg < 0)
>   		return 0;
>   	return regmap_write(map, reg, val);
>   }
> +EXPORT_SYMBOL(mtk_regmap_write);
>   

Same here

>   int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
>   		       struct snd_soc_dai *dai)
> @@ -459,8 +462,12 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
>   	struct mtk_base_afe_memif *memif = &afe->memif[id];
>   	unsigned int mono;
>   
> -	if (memif->data->mono_shift < 0)
> -		return 0;
> +	dev_info(afe->dev, "%s(), id: %d, channel: %d\n", __func__, id, channel);

If you really really really need this print, it's for debugging, so this should be
dev_dbg() instead... but otherwise just delete it.

> +	mono = memif->data->mono_invert ^ (channel == 1);
> +
> +	if (memif->data->mono_shift > 0)
> +		mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
> +				       0x1, mono, memif->data->mono_shift);
>   
>   	if (memif->data->quad_ch_mask) {
>   		unsigned int quad_ch = (channel == 4) ? 1 : 0;
> @@ -470,11 +477,6 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
>   				       quad_ch, memif->data->quad_ch_shift);
>   	}
>   
> -	if (memif->data->mono_invert)
> -		mono = (channel == 1) ? 0 : 1;
> -	else
> -		mono = (channel == 1) ? 1 : 0;
> -
>   	/* for specific configuration of memif mono mode */
>   	if (memif->data->int_odd_flag_reg)
>   		mtk_regmap_update_bits(afe->regmap,
> @@ -482,8 +484,14 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
>   				       1, mono,
>   				       memif->data->int_odd_flag_shift);
>   
> -	return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
> -				      1, mono, memif->data->mono_shift);

Don't break older platforms. You're removing functionality here.

> +	if (memif->data->ch_num_maskbit) {
> +		dev_info(afe->dev, "%s(), set ch num id: %d, channel: %d\n", __func__, id, channel);

Same comment applies (plus, this is a double print, even worse).

> +		mtk_regmap_update_bits(afe->regmap, memif->data->ch_num_reg,
> +				       memif->data->ch_num_maskbit,
> +				       channel, memif->data->ch_num_shift);
> +	}
> +
> +	return 0;
>   }
>   EXPORT_SYMBOL_GPL(mtk_memif_set_channel);
>   
> diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.h b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
> index b6d0f2b27e86..64b10ccba291 100644
> --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h
> +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
> @@ -12,7 +12,13 @@
>   struct snd_soc_dai_ops;
>   struct mtk_base_afe;
>   struct mtk_base_afe_memif;
> +struct mtk_base_irq_data;
>   
> +int mtk_regmap_update_bits(struct regmap *map, int reg,
> +			   unsigned int mask, unsigned int val,
> +			   int shift);
> +int mtk_regmap_write(struct regmap *map, int reg,
> +		     unsigned int val);

No, don't export these. Use regmap directly.

Regards,
Angelo



From romank at linux.microsoft.com  Mon Mar 10 10:15:12 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:15:12 -0700
Subject: [PATCH hyperv-next v5 11/11] PCI: hv: Get vPCI MSI IRQ domain
 from DeviceTree
In-Reply-To: <20250310164122.GA551965@bhelgaas>
References: <20250310164122.GA551965@bhelgaas>
Message-ID: <319aac20-229e-4a81-b2c5-e870453634bb@linux.microsoft.com>



On 3/10/2025 9:41 AM, Bjorn Helgaas wrote:
> On Fri, Mar 07, 2025 at 02:03:03PM -0800, Roman Kisel wrote:
>> The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
>> arm64. It won't be able to do that in the VTL mode where only DeviceTree
>> can be used.
>>
>> Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
>> case, too.
>>
>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> 
> A couple minor comments below, but I don't have any objection to this,
> so if it's OK with the pci-hyperv.c folks, it's OK with me.
> 

Bjorn, thanks a lot for your help and guidance! I'll be most happy to
incorporate your suggestions into the next version of the series :)

>> +#ifdef CONFIG_OF
>> +
>> +static struct irq_domain *hv_pci_of_irq_domain_parent(void)
>> +{
>> +	struct device_node *parent;
>> +	struct irq_domain *domain;
>> +
>> +	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
>> +	domain = NULL;
>> +	if (parent) {
>> +		domain = irq_find_host(parent);
>> +		of_node_put(parent);
>> +	}
>> +
>> +	return domain;
> 
> I think this would be a little simpler as:
> 
>    parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
>    if (!parent)
>      return NULL;
> 
>    domain = irq_find_host(parent);
>    of_node_put(parent);
>    return domain;
> 
>> +}
>> +
>> +#endif
>> +
>> +#ifdef CONFIG_ACPI
>> +
>> +static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
>> +{
>> +	struct irq_domain *domain;
>> +	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
>> +
>> +	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
>> +		return NULL;
>> +	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
>> +	if (!gsi_domain_disp_fn)
>> +		return NULL;
>> +	domain = irq_find_matching_fwnode(gsi_domain_disp_fn(0),
>> +				     DOMAIN_BUS_ANY);
>> +
>> +	if (!domain)
>> +		return NULL;
>> +
>> +	return domain;
> 
>    if (!domain)
>      return NULL;
> 
>    return domain;
> 
> is the same as:
> 
>    return domain;
> 
> or even just:
> 
>    return irq_find_matching_fwnode(gsi_domain_disp_fn(0), DOMAIN_BUS_ANY);
> 
>> +}

-- 
Thank you,
Roman



From romank at linux.microsoft.com  Mon Mar 10 10:20:02 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:20:02 -0700
Subject: [PATCH hyperv-next v5 06/11] arm64, x86: hyperv: Report the VTL
 the system boots in
In-Reply-To: <Z88Y-R7BnXa4Xi3I@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-7-romank@linux.microsoft.com>
 <Z84yyAqkqJ2ZyAd-@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
 <2342dda1-2976-4506-ab68-640739a1bd5b@linux.microsoft.com>
 <Z88Y-R7BnXa4Xi3I@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
Message-ID: <ce6f5bb0-545f-4d9f-a792-29a2f1520ba8@linux.microsoft.com>



On 3/10/2025 9:53 AM, Wei Liu wrote:
> On Mon, Mar 10, 2025 at 09:42:15AM -0700, Roman Kisel wrote:

[...]

>>
>>> Please be consistent across different architectures.
>>>
>>
>> In the earlier versions of the patch series, I had that piece
>> from the above mirrored in the arm64, and there was advice on
>> removing the function as it contained just one statement.
>> I'll revisit the approach, thanks for your help!
> 
> As long as the output is consistent across different architectures, I'm
> good.

I should add a comment most likely to save people some time grepping
the code as the line does look like should always print that. IOW
not printing for VTL0 is obscured by the preprocessor/#define cruft.

> 
> Wei.
> 
>>
>>>>    	x86_platform.realmode_reserve = x86_init_noop;
>>>>    	x86_platform.realmode_init = x86_init_noop;
>>>> -- 
>>>> 2.43.0
>>>>
>>>>
>>
>> -- 
>> Thank you,
>> Roman
>>

-- 
Thank you,
Roman



From catalin.marinas at arm.com  Mon Mar 10 10:29:05 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 17:29:05 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <20250308023314.3981455-1-pcc@google.com>
References: <20250308023314.3981455-1-pcc@google.com>
Message-ID: <Z88hYdTAe6ok4_WT@arm.com>

On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> The optimized strscpy() and dentry_string_cmp() routines will read 8
> unaligned bytes at a time via the function read_word_at_a_time(), but
> this is incompatible with MTE which will fault on a partially invalid
> read. The attributes on read_word_at_a_time() that disable KASAN are
> invisible to the CPU so they have no effect on MTE. Let's fix the
> bug for now by disabling the optimizations if the kernel is built
> with HW tag-based KASAN and consider improvements for followup changes.
> 
> Signed-off-by: Peter Collingbourne <pcc at google.com>
> Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> Cc: stable at vger.kernel.org

Some time ago Vincenzo had an attempt at fixing this but neither of us
got around to posting it. It's on top of 6.2 and not sure how cleanly it
would rebase:

git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux devel/mte-strscpy

Feel free to cherry-pick patches from above, rewrite them etc.

> diff --git a/lib/string.c b/lib/string.c
> index eb4486ed40d25..9a43a3824d0d7 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -119,7 +119,8 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
>  		return -E2BIG;
>  
> -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
> +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \
> +	!defined(CONFIG_KASAN_HW_TAGS)

Assuming that no-one wants to ever use KASAN_HW_TAGS=y in production,
this patch would do. Otherwise I'd rather use TCO around the access as
per the last patch from Vincenzo above.

Yet another option - use load_unaligned_zeropad() instead of
read_word_at_a_time(), not sure how it changes the semantics of
strscpy() in any way. This can be done in the arch code

-- 
Catalin


From mark.rutland at arm.com  Mon Mar 10 10:30:21 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 17:30:21 +0000
Subject: [PATCH V2] arm64/mm: Create level specific section mappings in
 map_range()
In-Reply-To: <CAMj1kXEZ86C8bouLt+xNkNr+L9AvCSQ2SZeJpLMtyvGo-8h6gw@mail.gmail.com>
References: <20250310062812.216031-1-anshuman.khandual@arm.com>
 <Z87FFqV03Pd0-NXl@J2N7QTR9R3.cambridge.arm.com>
 <b1fb982a-4936-4c18-aaad-3e8e8f61bccc@arm.com>
 <Z876UI5-xGRHl4td@J2N7QTR9R3.cambridge.arm.com>
 <CAMj1kXEZ86C8bouLt+xNkNr+L9AvCSQ2SZeJpLMtyvGo-8h6gw@mail.gmail.com>
Message-ID: <Z88hrbNFM_7hIx_Z@J2N7QTR9R3.cambridge.arm.com>

On Mon, Mar 10, 2025 at 03:53:33PM +0100, Ard Biesheuvel wrote:
> On Mon, 10 Mar 2025 at 15:42, Mark Rutland <mark.rutland at arm.com> wrote:
> >
> > On Mon, Mar 10, 2025 at 01:48:53PM +0000, Ryan Roberts wrote:
> > > On 10/03/2025 10:55, Mark Rutland wrote:
> > IIUC the problem is that for a sufficiently large (and aligned) extent
> > of physical memory, we might try to create a block mapping larger than
> > the HW supports?
> 
> Yes. However, this code is only called to map the kernel, the DTB and
> the ID map code and data pages, and so it seems unlikely that we'll
> hit this bug in practice.
> 
> Nonetheless, it is a shortcoming that we should address to avoid
> future surprises.
> 
> > With that in mind, my earlier comment about LPA2 and blocks at level-0
> > is particularly relevant...
> 
> Indeed - at the higher levels, there is quite some variation between
> page sizes, LPA2 vs !LPA2 etc in which level is the highest at which
> block mappings are supported.
> 
> But given the context where this code is used, I'd prefer to simply
> map everything down to level 2 or higher (for 64-bit descriptors)
> rather than add elaborate rules for all these combinations that are
> never exercised in practice. The net result should be identical.

That sounds much better to me!

> > Though TBH, maybe it makes more sense to split this up into separate
> > levels (as with the code in arch/arm64/mm/mmu.c) and handle each level
> > explicitly with a separate function. That way each level's check can be
> > handled within that level's function, and we can use the right types,
> > etc. It feels like that might be better for D128 in future?
> 
> I have a slight inclination towards having a separate routine for
> D128, but I can easily be persuaded otherwise.

FWIW, I don't have strong feelings either way w.r.t. sharing the code
with D128. If it's cleaner for that to be separate, sure, but I'd have
to see the code.

My concern here was the the current recursive nature of the PI
map_range() function makes it hard to have level-specific behaviour, and
means that it's structurally different to most other code in the kernel,
e.g. the alloc_init_pXX() functions in arch/arm64/mm/mmu.c, where we
have separate functions for each of the levels that handle the
level-specific details.

I think that structure of separate functions per level is clearer, even
if it's a bit more code.

Mark.


From nphamcs at gmail.com  Mon Mar 10 10:30:48 2025
From: nphamcs at gmail.com (Nhat Pham)
Date: Mon, 10 Mar 2025 10:30:48 -0700
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <CAKEwX=PNHik8O6swwRPsuDovtCNLxXRQUsiXZSSq8ZbzFvJV0w@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
 <52896654fa07a685707b11cfcc141b038a13b649.camel@mediatek.com> <CAKEwX=PNHik8O6swwRPsuDovtCNLxXRQUsiXZSSq8ZbzFvJV0w@mail.gmail.com>
Message-ID: <CAKEwX=Onwhy7FkB97tw4JonN3POj=dDp3ixsfS14=_3x3=KvuA@mail.gmail.com>

On Mon, Mar 10, 2025 at 9:58?AM Nhat Pham <nphamcs at gmail.com> wrote:
>
> On Mon, Mar 10, 2025 at 6:22?AM Qun-wei Lin (???)
> <Qun-wei.Lin at mediatek.com> wrote:
> >
> >
> > Thank you for your explanation. Compared to the original single kswapd,
> > we expect t1 to have a slight increase in re-scan time. However, since
> > our kcompressd can focus on compression tasks and we can have multiple
> > kcompressd instances (kcompressd0, kcompressd1, ...) running in
> > parallel, we anticipate that the number of times a folio needs be re-
> > scanned will not be too many.
> >
> > In our experiments, we fixed the CPU and DRAM at a certain frequency.
> > We created a high memory pressure enviroment using a memory eater and
> > recorded the increase in pgsteal_anon per second, which was around 300,
> > 000. Then we applied our patch and measured again, that pgsteal_anon/s
> > increased to over 800,000.
> >
> > > >
> > > > >
> > > > > Problem:
> > > > >  In the current system, the kswapd thread is responsible for both
> > > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > > >  combined responsibility can lead to significant performance
> > > > > bottlenecks,
> > > >
> > > > What bottleneck are we talking about? Is one stage slower than the
> > > > other?
> > > >
> > > > >  especially under high memory pressure. The kswapd thread becomes
> > > > > a
> > > > >  single point of contention, causing delays in memory reclaiming
> > > > > and
> > > > >  overall system performance degradation.
> > > > >
> > > > > Target:
> > > > >  The target of this invention is to improve the efficiency of
> > > > > memory
> > > > >  reclaiming. By separating the tasks of page scanning and page
> > > > >  compression into distinct processes or threads, the system can
> > > > > handle
> > > > >  memory pressure more effectively.
> > > >
> > > > I'm not a zram maintainer, so I'm definitely not trying to stop
> > > > this
> > > > patch. But whatever problem zram is facing will likely occur with
> > > > zswap too, so I'd like to learn more :)
> > >
> > > Right, this is likely something that could be addressed more
> > > generally
> > > for zswap and zram.
> > >
> >
> > Yes, we also hope to extend this to other swap devices, but currently,
> > we have only modified zram. We are not very familiar with zswap and
> > would like to ask if anyone has any suggestions for modifications?
> >
>
> My understanding is right now schedule_bio_write is the work
> submission API right? We can make it generic, having it accept a
> callback and a generic untyped pointer which can be casted into a
> backend-specific context struct. For zram it would contain struct zram
> and the bio. For zswap, depending on at which point do you want to
> begin offloading the work - it could simply be just the folio itself
> if we offload early, or a more complicated scheme.

To expand a bit - zswap_store() is where all the logic lives. It's
fairly straightforward: checking zswap cgroup limits, acquire the
zswap pool (a combination of compression algorithm and backend memory
allocator, which is just zsmalloc now), perform compression, then ask
for a slot from zsmalloc and store it there.

You can probably just offload the whole thing here, or perform some
steps of the sequence before offloading the rest :) One slight
complication is don't forget to fallback to disk swapping - unlike
zram, zswap is originally designed as a "cache" for underlying swap
files on disk, which we can fallback to if the compression attempt
fails. Everything should be fairly straightforward though :)

>
>
>
> > > Thanks
> > > Barry
> >
> > Best Regards,
> > Qun-wei
> >
> >


From romank at linux.microsoft.com  Mon Mar 10 10:35:05 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:35:05 -0700
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
Message-ID: <e0dce529-0777-491d-aced-1e9ead31ac17@linux.microsoft.com>



On 3/8/2025 1:05 PM, Arnd Bergmann wrote:
> On Fri, Mar 7, 2025, at 23:02, Roman Kisel wrote:
>> @@ -5,18 +5,20 @@ menu "Microsoft Hyper-V guest support"
>>   config HYPERV
>>   	tristate "Microsoft Hyper-V client drivers"
>>   	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
>> -		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
>> +		|| (ARM64 && !CPU_BIG_ENDIAN)
>> +	depends on (ACPI || HYPERV_VTL_MODE)
>>   	select PARAVIRT
>>   	select X86_HV_CALLBACK_VECTOR if X86
>> -	select OF_EARLY_FLATTREE if OF
>>   	help
>>   	  Select this option to run Linux as a Hyper-V client operating
>>   	  system.
>>
>>   config HYPERV_VTL_MODE
>>   	bool "Enable Linux to boot in VTL context"
>> -	depends on X86_64 && HYPERV
>> +	depends on (X86_64 || ARM64)
>>   	depends on SMP
>> +	select OF_EARLY_FLATTREE
>> +	select OF
>>   	default n
>>   	help
> 
> Having the dependency below the top-level Kconfig entry feels a little
> counterintuitive. You could flip that back as it was before by doing
> 
>        select HYPERV_VTL_MODE if !ACPI
>        depends on ACPI || SMP
> 
> in the HYPERV option, leaving the dependency on HYPERV in
> HYPERV_VTL_MODE.
> 

I was implementing Michael's suggestion, and might've gone a bit
overboard, my bad. I'll fix this, thanks a lot for reviewing!

> Is OF_EARLY_FLATTREE actually needed on x86?
> 

No, it is not needed on x86. It is only needed when VTL mode is used.

>        Arnd

-- 
Thank you,
Roman



From romank at linux.microsoft.com  Mon Mar 10 10:36:21 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 10:36:21 -0700
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ
 number from DeviceTree
In-Reply-To: <29bb5b7a-b31f-4b32-92c6-e2588a0f965a@app.fastmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-9-romank@linux.microsoft.com>
 <29bb5b7a-b31f-4b32-92c6-e2588a0f965a@app.fastmail.com>
Message-ID: <b3d1609e-4f64-4a88-b453-cb79936cb469@linux.microsoft.com>



On 3/8/2025 1:11 PM, Arnd Bergmann wrote:
> On Fri, Mar 7, 2025, at 23:03, Roman Kisel wrote:
>>
>> +static int __maybe_unused vmbus_set_irq(struct platform_device *pdev)
> 
> Instead of the __maybe_unused annotation here
> 
>>
>> +#ifndef HYPERVISOR_CALLBACK_VECTOR
>> +	ret = vmbus_set_irq(pdev);
>> +	if (ret)
>> +		return ret;
>> +#endif
>> +
> 
> you can use
> 
>         if (!__is_defined(HYPERVISOR_CALLBACK_VECTOR))
>                    ret = vmbus_set_irq(pdev);
> 
> and make it a little more readable.
> 

Thanks you very much, will update! Very neat :)

>      Arnd

-- 
Thank you,
Roman



From catalin.marinas at arm.com  Mon Mar 10 10:37:50 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 17:37:50 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <202503071927.1A795821A@keescook>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
Message-ID: <Z88jbhobIz2yWBbJ@arm.com>

On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > unaligned bytes at a time via the function read_word_at_a_time(), but
> > this is incompatible with MTE which will fault on a partially invalid
> > read. The attributes on read_word_at_a_time() that disable KASAN are
> > invisible to the CPU so they have no effect on MTE. Let's fix the
> > bug for now by disabling the optimizations if the kernel is built
> > with HW tag-based KASAN and consider improvements for followup changes.
> 
> Why is faulting on a partially invalid read a problem? It's still
> invalid, so ... it should fault, yes? What am I missing?

read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
beyond the end of string. The has_zero() function is then used to check
where the string ends. For this uses, I think we can go with
load_unaligned_zeropad() which handles a potential fault and pads the
rest with zeroes.

> > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> > Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> > Cc: stable at vger.kernel.org
> > ---
> >  fs/dcache.c  | 2 +-
> >  lib/string.c | 3 ++-
> >  2 files changed, 3 insertions(+), 2 deletions(-)
> 
> Why are DCACHE_WORD_ACCESS and HAVE_EFFICIENT_UNALIGNED_ACCESS separate
> things? I can see at least one place where it's directly tied:
> 
> arch/arm/Kconfig:58:    select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS

DCACHE_WORD_ACCESS requires load_unaligned_zeropad() which handles the
faults. For some reason, read_word_at_a_time() doesn't expect to fault
and it is only used with HAVE_EFFICIENT_UNALIGNED_ACCESS. I guess arm32
only enabled load_unaligned_zeropad() on hardware that supports
efficient unaligned accesses (v6 onwards), hence the dependency.

> Would it make sense to sort this out so that KASAN_HW_TAGS can be taken
> into account at the Kconfig level instead?

I don't think we should play with config options but rather sort out the
fault path (load_unaligned_zeropad) or disable MTE temporarily. I'd go
with the former as long as read_word_at_a_time() is only used for
strings in conjunction with has_zero(). I haven't checked.

-- 
Catalin


From krzk at kernel.org  Mon Mar 10 10:40:22 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 18:40:22 +0100
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
 <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
 <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>
Message-ID: <09d4966a-5804-40a4-9c5f-356a954a7704@kernel.org>

On 10/03/2025 18:05, Roman Kisel wrote:
> 
> 
> On 3/10/2025 2:28 AM, Krzysztof Kozlowski wrote:
>> On Fri, Mar 07, 2025 at 02:02:59PM -0800, Roman Kisel wrote:
>>> To boot on ARM64, VMBus requires configuring interrupts. Missing
>>> DMA coherence property is sub-optimal as the VMBus transations are
>>> cache-coherent.
>>>
>>> Add interrupts to be able to boot on ARM64. Add DMA coherence to
>>> avoid doing extra work on maintaining caches on ARM64.
>>
>> How do you add it?
>>
> 
> I added properties to the node. Should I fix the description, or I am
> misunderstanding the question?

I saw interrupts in the schema, but I did not see dma-coherence. I also
did not see any DTS patches here, so I don't understand what node you
are referring to.

> 
>>>
>>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
>>> ---
>>>   .../devicetree/bindings/bus/microsoft,vmbus.yaml          | 8 +++++++-
>>>   1 file changed, 7 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>> index a8d40c766dcd..3ab7d0116626 100644
>>> --- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>> +++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>> @@ -28,13 +28,16 @@ properties:
>>>   required:
>>>     - compatible
>>>     - ranges
>>> +  - interrupts
>>>     - '#address-cells'
>>>     - '#size-cells'
>>>   
>>> -additionalProperties: false
>>> +additionalProperties: true
>>
>> This is neither explained in commit msg nor correct.
>>
> 
> Not explained, as there is no good explanation as described below.
> 
>> Drop the change. You cannot have device bindings ending with 'true'
>> here - see talks, example-bindings, writing-schema and whatever resource
>> is there.
>>
> 
> Thanks, I'll put more effort into bringing this into a better form!
> If you have time, could you comment on the below?
> 
> The Documentation says
> 
>    * additionalProperties: true
>      Rare case, used for schemas implementing common set of properties.
> Such schemas are supposed to be referenced by other schemas, which then 
> use 'unevaluatedProperties: false'.  Typically bus or common-part schemas.
> 
> This is a bus so I added that line to the YAML, and I saw it in many

If this is a bus, then where is schema using it for
bus-attached-devices? You cannot have bus without devices.

You *must* fulfill that part:
"Such schemas are supposed to be referenced by other schemas, which then"

instead of calling it bus...

Please upstream bindings for the bus devices and extend the example here
with these devices.

Or this is not bus (calling something vmpony does not make it a pony).


Best regards,
Krzysztof


From tglx at linutronix.de  Mon Mar 10 10:56:40 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Mon, 10 Mar 2025 18:56:40 +0100
Subject: [PATCH v4 0/4] Add GPIO interrupt support for Amlogic A4 and A5
 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
Message-ID: <87h64022hz.ffs@tglx>

On Fri, Mar 07 2025 at 16:49, Xianwei Zhao via wrote:
> Xianwei Zhao (4):
>       dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
>       irqchip: Add support for Amlogic A4 and A5 SoCs
>       arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
>       arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
>
>  .../amlogic,meson-gpio-intc.yaml                   | 19 ++++++++-
>  arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 19 +++++++++
>  arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 ++++++
>  drivers/irqchip/irq-meson-gpio.c                   | 45 +++++++++++++++++-----

I can't take that through the irqchip tree as the amlogic dtsi files are
new and in Neil's for-next branch.

Neil, feel free to pick the lot up, I don't have conflicting changes for
that driver sitting in my tree. I'll reply to the irqchip patch seperately.

Thanks,

        tglx


From cristian.marussi at arm.com  Mon Mar 10 10:58:00 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Mon, 10 Mar 2025 17:58:00 +0000
Subject: [PATCH] firmware: arm_scmi: Fix timeout checks on polling path
Message-ID: <20250310175800.1444293-1-cristian.marussi@arm.com>

Polling mode transactions wait for a reply busy-looping without holding a
spinlock, but currently the timeout checks are based only on elapsed time:
as a result we could hit a false positive whenever our busy-looping thread
is pre-empted and scheduled out for a time greater than the polling
timeout.

Change the checks at the end of the busy-loop to make sure that the polling
wasn't indeed successful or an out-of-order reply caused the polling to be
forcibly terminated.

Fixes: 31d2f803c19c ("firmware: arm_scmi: Add sync_cmds_completed_on_ret transport flag")
Reported-by: Huangjie <huangjie1663 at phytium.com.cn>
Closes: https://lore.kernel.org/arm-scmi/20250123083323.2363749-1-jackhuang021 at gmail.com/
Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
Cc: <stable at vger.kernel.org> # 5.18.x
---
This fix got to be backported to 5.4/5.10./5.15 due to small changes in the
context
---
 drivers/firmware/arm_scmi/driver.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 60050da54bf2..e6cf83950875 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1248,7 +1248,8 @@ static void xfer_put(const struct scmi_protocol_handle *ph,
 }
 
 static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
-				      struct scmi_xfer *xfer, ktime_t stop)
+				      struct scmi_xfer *xfer, ktime_t stop,
+				      bool *ooo)
 {
 	struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
 
@@ -1257,7 +1258,7 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
 	 * in case of out-of-order receptions of delayed responses
 	 */
 	return info->desc->ops->poll_done(cinfo, xfer) ||
-	       try_wait_for_completion(&xfer->done) ||
+	       (*ooo = try_wait_for_completion(&xfer->done)) ||
 	       ktime_after(ktime_get(), stop);
 }
 
@@ -1274,15 +1275,17 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
 		 * itself to support synchronous commands replies.
 		 */
 		if (!desc->sync_cmds_completed_on_ret) {
+			bool ooo = false;
+
 			/*
 			 * Poll on xfer using transport provided .poll_done();
 			 * assumes no completion interrupt was available.
 			 */
 			ktime_t stop = ktime_add_ms(ktime_get(), timeout_ms);
 
-			spin_until_cond(scmi_xfer_done_no_timeout(cinfo,
-								  xfer, stop));
-			if (ktime_after(ktime_get(), stop)) {
+			spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer,
+								  stop, &ooo));
+			if (!ooo && !info->desc->ops->poll_done(cinfo, xfer)) {
 				dev_err(dev,
 					"timed out in resp(caller: %pS) - polling\n",
 					(void *)_RET_IP_);
-- 
2.47.0



From tglx at linutronix.de  Mon Mar 10 10:58:53 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Mon, 10 Mar 2025 18:58:53 +0100
Subject: [PATCH v4 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <20250307-irqchip-gpio-a4-a5-v4-2-d03a9424151b@amlogic.com>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
 <20250307-irqchip-gpio-a4-a5-v4-2-d03a9424151b@amlogic.com>
Message-ID: <87ecz422ea.ffs@tglx>

On Fri, Mar 07 2025 at 16:49, Xianwei Zhao via wrote:
>  
>  	if (type == IRQ_TYPE_EDGE_BOTH) {
>  		val |= BIT(ctl->params->edge_both_offset + idx);

Not new, but this really should be 'val = ...'

> -		meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4,
> +		meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
>  					   BIT(ctl->params->edge_both_offset + idx), val);

and this BIT() calculation is obviously redundant as it is the same as @val.

Would be nice to have that cleaned up.

With that fixed:

Reviewed-by: Thomas Gleixner <tglx at linutronix.de>


From leo.yan at arm.com  Mon Mar 10 11:03:18 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 10 Mar 2025 18:03:18 +0000
Subject: [PATCH v2 5/8] coresight: etm: Add an attribute for updating
 buffer
In-Reply-To: <3f4354e7-e74b-4ce9-b0c7-4be103cbc94d@arm.com>
References: <20250310104919.58816-1-leo.yan@arm.com>
 <20250310104919.58816-6-leo.yan@arm.com>
 <d8b1cf1f-1996-4d9c-9f1a-fad556f91577@arm.com>
 <20250310155015.GG9682@e132581.arm.com>
 <3f4354e7-e74b-4ce9-b0c7-4be103cbc94d@arm.com>
Message-ID: <20250310180318.GH9682@e132581.arm.com>

On Mon, Mar 10, 2025 at 04:37:44PM +0000, Suzuki Kuruppassery Poulose wrote:

[...]

> > How about we dynamically set the default flag in the Perf tool?
> > 
> > - If users set explictly the 'update_buf_on_pause' flag, then the
> >    setting will be respected.
> > - If users don't set the flag, perf tool detects it is TRBE sinks,
> >    then it can set 'update_buf_on_pause' flag as false.
> 
> Not really possible. There could be systems with mixed sinks. e.g.  TRBE
> for some CPU and ETR for others (say due to a non-functioning TRBE).
> 
> > - If users don't set the flag, perf tool detects it is ETF/ETB/ETR
> >    sinks, it sets the flag as true.
> 
> And in the cases above, perf event cannot run on all the CPUs, because
> some sinks don't support it.
> 
> Why do we need a flag, when the effect is not user (read, perf decoder)
>  visible and at the same time improves some scenarios (read non-TRBE cases)
> ?

Indeed in this case the flag is redundant.

> I would say, let the driver always update on pause, depending on the
> sink.

It is fine for me.  I will move towards this direction.

Thanks,
Leo


From romank at linux.microsoft.com  Mon Mar 10 11:07:08 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 11:07:08 -0700
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <09d4966a-5804-40a4-9c5f-356a954a7704@kernel.org>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
 <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
 <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>
 <09d4966a-5804-40a4-9c5f-356a954a7704@kernel.org>
Message-ID: <ba6b906d-04a2-423d-a527-9ef7ab1dccf2@linux.microsoft.com>



On 3/10/2025 10:40 AM, Krzysztof Kozlowski wrote:
> On 10/03/2025 18:05, Roman Kisel wrote:
>>
>>
>> On 3/10/2025 2:28 AM, Krzysztof Kozlowski wrote:
>>> On Fri, Mar 07, 2025 at 02:02:59PM -0800, Roman Kisel wrote:
>>>> To boot on ARM64, VMBus requires configuring interrupts. Missing
>>>> DMA coherence property is sub-optimal as the VMBus transations are
>>>> cache-coherent.
>>>>
>>>> Add interrupts to be able to boot on ARM64. Add DMA coherence to
>>>> avoid doing extra work on maintaining caches on ARM64.
>>>
>>> How do you add it?
>>>
>>
>> I added properties to the node. Should I fix the description, or I am
>> misunderstanding the question?
> 
> I saw interrupts in the schema, but I did not see dma-coherence. I also
> did not see any DTS patches here, so I don't understand what node you
> are referring to.
> 

I will refer to talks, example-bindings, writing-schema you've suggested
to waste your time less. It appears there is some fundamental flaw in my
understanding of how these YAML files work so much so that I cannot even
write a commit description that can be understood, for the 5th time in
the row, sorry about that.

>>
>>>>
>>>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
>>>> ---
>>>>    .../devicetree/bindings/bus/microsoft,vmbus.yaml          | 8 +++++++-
>>>>    1 file changed, 7 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>>> index a8d40c766dcd..3ab7d0116626 100644
>>>> --- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>>> +++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
>>>> @@ -28,13 +28,16 @@ properties:
>>>>    required:
>>>>      - compatible
>>>>      - ranges
>>>> +  - interrupts
>>>>      - '#address-cells'
>>>>      - '#size-cells'
>>>>    
>>>> -additionalProperties: false
>>>> +additionalProperties: true
>>>
>>> This is neither explained in commit msg nor correct.
>>>
>>
>> Not explained, as there is no good explanation as described below.
>>
>>> Drop the change. You cannot have device bindings ending with 'true'
>>> here - see talks, example-bindings, writing-schema and whatever resource
>>> is there.
>>>
>>
>> Thanks, I'll put more effort into bringing this into a better form!
>> If you have time, could you comment on the below?
>>
>> The Documentation says
>>
>>     * additionalProperties: true
>>       Rare case, used for schemas implementing common set of properties.
>> Such schemas are supposed to be referenced by other schemas, which then
>> use 'unevaluatedProperties: false'.  Typically bus or common-part schemas.
>>
>> This is a bus so I added that line to the YAML, and I saw it in many
> 
> If this is a bus, then where is schema using it for
> bus-attached-devices? You cannot have bus without devices.
> 
> You *must* fulfill that part:
> "Such schemas are supposed to be referenced by other schemas, which then"
> 
> instead of calling it bus...
> 

It is modeled as a bus in the kernel:
https://www.kernel.org/doc/html/latest/virt/hyperv/vmbus.html

> Please upstream bindings for the bus devices and extend the example here
> with these devices.

The set of synthetic devices that reside on the bus isn't fixed, and
they don't require description neither in ACPI nor in DT as
the devices negotiate their MMIO regions through the hyperv driver.

Perhaps, it is not as much bus as expected by the YAML files.

> 
> Or this is not bus (calling something vmpony does not make it a pony).
> 
 > > Best regards,
> Krzysztof

-- 
Thank you,
Roman



From cristian.marussi at arm.com  Mon Mar 10 11:08:11 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Mon, 10 Mar 2025 18:08:11 +0000
Subject: [PATCH] firmware: arm_scmi: Add polling support to raw mode
Message-ID: <20250310180811.1463539-1-cristian.marussi@arm.com>

Provide a couple of additional debugfs entries to enable polling-mode on
the waiting path of injected messages: message_poll will cause the system
to poll while waiting for the reply, while message_poll_async will send an
asynchronous message, as usual, and will use polling mode for the immediate
synchronous part of the async command.

Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
---
Not sure if it is not better to unify all these common read/write entrypoint
into one single function that decide what to do based on the a strcmp of its
own filepath....seems still cleaner using these stupid wrappers to
diffrentiate between message_poll/message_poll_async etc etc
---
 Documentation/ABI/testing/debugfs-scmi-raw | 91 ++++++++++++++++++++++
 drivers/firmware/arm_scmi/driver.c         |  3 +-
 drivers/firmware/arm_scmi/raw_mode.c       | 72 +++++++++++++++--
 3 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/debugfs-scmi-raw b/Documentation/ABI/testing/debugfs-scmi-raw
index 97678cc9535c..5847b96b3896 100644
--- a/Documentation/ABI/testing/debugfs-scmi-raw
+++ b/Documentation/ABI/testing/debugfs-scmi-raw
@@ -31,6 +31,42 @@ Description:	SCMI Raw asynchronous message injection/snooping facility; write
 		(receiving an EOF at each message boundary).
 Users:		Debugging, any userspace test suite
 
+What:		/sys/kernel/debug/scmi/<n>/raw/message_poll
+Date:		June 2025
+KernelVersion:	6.16
+Contact:	cristian.marussi at arm.com
+Description:	SCMI Raw message injection/snooping facility using polling mode;
+		write a complete SCMI command message (header included) in
+		little-endian binary format to have it sent to the configured
+		backend SCMI server for instance <n>, using polling mode on
+		the reception path. (if transport is polling capable)
+		Any subsequently received response can be read from this same
+		entry if it arrived within the configured timeout.
+		Each write to the entry causes one command request to be built
+		and sent while the replies are read back one message at time
+		(receiving an EOF at each message boundary).
+Users:		Debugging, any userspace test suite
+
+What:		/sys/kernel/debug/scmi/<n>/raw/message_poll_async
+Date:		June 2025
+KernelVersion:	6.16
+Contact:	cristian.marussi at arm.com
+Description:	SCMI Raw asynchronous message injection/snooping facility using
+		polling-mode; write a complete SCMI asynchronous command message
+		(header included) in little-endian binary format to have it sent
+		to the configured backend SCMI server for instance <n>, using
+		polling-mode on the reception path of the immediate part of the
+		asynchronous command. (if transport is polling capable)
+		Any subsequently received response can be read from this same
+		entry if it arrived within the configured timeout.
+		Any additional delayed response received afterwards can be read
+		from this same entry too if it arrived within the configured
+		timeout.
+		Each write to the entry causes one command request to be built
+		and sent while the replies are read back one message at time
+		(receiving an EOF at each message boundary).
+Users:		Debugging, any userspace test suite
+
 What:		/sys/kernel/debug/scmi/<n>/raw/errors
 Date:		March 2023
 KernelVersion:	6.3
@@ -115,3 +151,58 @@ Description:	SCMI Raw asynchronous message injection/snooping facility; write
 		exist only if the transport is configured to have more than
 		one default channel.
 Users:		Debugging, any userspace test suite
+
+
+What:		/sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll
+Date:		June 2025
+KernelVersion:	6.16
+Contact:	cristian.marussi at arm.com
+Description:	SCMI Raw message injection/snooping facility using polling mode;
+		write a complete SCMI command message (header included) in
+		little-endian binary format to have it sent to the configured
+		backend SCMI server for instance <n> through the <m> transport
+		channel, using polling mode on the reception path.
+		(if transport is polling capable)
+		Any subsequently received response can be read from this same
+		entry if it arrived on channel <m> within the configured
+		timeout.
+		Each write to the entry causes one command request to be built
+		and sent while the replies are read back one message at time
+		(receiving an EOF at each message boundary).
+		Channel identifier <m> matches the SCMI protocol number which
+		has been associated with this transport channel in the DT
+		description, with base protocol number 0x10 being the default
+		channel for this instance.
+		Note that these per-channel entries rooted at <..>/channels
+		exist only if the transport is configured to have more than
+		one default channel.
+Users:		Debugging, any userspace test suite
+
+What:		/sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll_async
+Date:		June 2025
+KernelVersion:	6.16
+Contact:	cristian.marussi at arm.com
+Description:	SCMI Raw asynchronous message injection/snooping facility using
+		polling-mode; write a complete SCMI asynchronous command message
+		(header included) in little-endian binary format to have it sent
+		to the configured backend SCMI server for instance <n> through
+		the <m> transport channel, using polling mode on the reception
+		path of the immediate part of the asynchronous command.
+		(if transport is polling capable)
+		Any subsequently received response can be read from this same
+		entry if it arrived on channel <m> within the configured
+		timeout.
+		Any additional delayed response received afterwards can be read
+		from this same entry too if it arrived within the configured
+		timeout.
+		Each write to the entry causes one command request to be built
+		and sent while the replies are read back one message at time
+		(receiving an EOF at each message boundary).
+		Channel identifier <m> matches the SCMI protocol number which
+		has been associated with this transport channel in the DT
+		description, with base protocol number 0x10 being the default
+		channel for this instance.
+		Note that these per-channel entries rooted at <..>/channels
+		exist only if the transport is configured to have more than
+		one default channel.
+Users:		Debugging, any userspace test suite
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index e6cf83950875..bf2dc200604e 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1190,7 +1190,8 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
 		 * RX path since it will be already queued at the end of the TX
 		 * poll loop.
 		 */
-		if (!xfer->hdr.poll_completion)
+		if (!xfer->hdr.poll_completion ||
+		    xfer->hdr.type == MSG_TYPE_DELAYED_RESP)
 			scmi_raw_message_report(info->raw, xfer,
 						SCMI_RAW_REPLY_QUEUE,
 						cinfo->id);
diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
index 7cc0d616b8de..3d543b1d8947 100644
--- a/drivers/firmware/arm_scmi/raw_mode.c
+++ b/drivers/firmware/arm_scmi/raw_mode.c
@@ -671,11 +671,13 @@ static int scmi_do_xfer_raw_start(struct scmi_raw_mode_info *raw,
  * @len: Length of the message in @buf.
  * @chan_id: The channel ID to use.
  * @async: A flag stating if an asynchronous command is required.
+ * @poll: A flag stating if a polling transmission is required.
  *
  * Return: 0 on Success
  */
 static int scmi_raw_message_send(struct scmi_raw_mode_info *raw,
-				 void *buf, size_t len, u8 chan_id, bool async)
+				 void *buf, size_t len, u8 chan_id,
+				 bool async, bool poll)
 {
 	int ret;
 	struct scmi_xfer *xfer;
@@ -684,6 +686,16 @@ static int scmi_raw_message_send(struct scmi_raw_mode_info *raw,
 	if (ret)
 		return ret;
 
+	if (poll) {
+		if (is_transport_polling_capable(raw->desc)) {
+			xfer->hdr.poll_completion = true;
+		} else {
+			dev_err(raw->handle->dev,
+				"Failed to send RAW message - Polling NOT supported\n");
+			return -EINVAL;
+		}
+	}
+
 	ret = scmi_do_xfer_raw_start(raw, xfer, chan_id, async);
 	if (ret)
 		scmi_xfer_raw_put(raw->handle, xfer);
@@ -801,7 +813,7 @@ static ssize_t scmi_dbg_raw_mode_common_read(struct file *filp,
 static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
 					      const char __user *buf,
 					      size_t count, loff_t *ppos,
-					      bool async)
+					      bool async, bool poll)
 {
 	int ret;
 	struct scmi_dbg_raw_data *rd = filp->private_data;
@@ -831,7 +843,7 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
 	}
 
 	ret = scmi_raw_message_send(rd->raw, rd->tx.buf, rd->tx_size,
-				    rd->chan_id, async);
+				    rd->chan_id, async, poll);
 
 	/* Reset ppos for next message ... */
 	rd->tx_size = 0;
@@ -875,7 +887,8 @@ static ssize_t scmi_dbg_raw_mode_message_write(struct file *filp,
 					       const char __user *buf,
 					       size_t count, loff_t *ppos)
 {
-	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, false);
+	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+					      false, false);
 }
 
 static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp,
@@ -964,7 +977,8 @@ static ssize_t scmi_dbg_raw_mode_message_async_write(struct file *filp,
 						     const char __user *buf,
 						     size_t count, loff_t *ppos)
 {
-	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, true);
+	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+					      true, false);
 }
 
 static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
@@ -976,6 +990,40 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
 	.owner = THIS_MODULE,
 };
 
+static ssize_t scmi_dbg_raw_mode_message_poll_write(struct file *filp,
+						    const char __user *buf,
+						    size_t count, loff_t *ppos)
+{
+	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+					      false, true);
+}
+
+static const struct file_operations scmi_dbg_raw_mode_message_poll_fops = {
+	.open = scmi_dbg_raw_mode_open,
+	.release = scmi_dbg_raw_mode_release,
+	.read = scmi_dbg_raw_mode_message_read,
+	.write = scmi_dbg_raw_mode_message_poll_write,
+	.poll = scmi_dbg_raw_mode_message_poll,
+	.owner = THIS_MODULE,
+};
+
+static ssize_t scmi_dbg_raw_mode_message_poll_async_write(struct file *filp,
+							  const char __user *buf,
+							  size_t count, loff_t *ppos)
+{
+	return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+					      true, true);
+}
+
+static const struct file_operations scmi_dbg_raw_mode_message_poll_async_fops = {
+	.open = scmi_dbg_raw_mode_open,
+	.release = scmi_dbg_raw_mode_release,
+	.read = scmi_dbg_raw_mode_message_read,
+	.write = scmi_dbg_raw_mode_message_poll_async_write,
+	.poll = scmi_dbg_raw_mode_message_poll,
+	.owner = THIS_MODULE,
+};
+
 static ssize_t scmi_test_dbg_raw_mode_notif_read(struct file *filp,
 						 char __user *buf,
 						 size_t count, loff_t *ppos)
@@ -1199,6 +1247,12 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
 	debugfs_create_file("message_async", 0600, raw->dentry, raw,
 			    &scmi_dbg_raw_mode_message_async_fops);
 
+	debugfs_create_file("message_poll", 0600, raw->dentry, raw,
+			    &scmi_dbg_raw_mode_message_poll_fops);
+
+	debugfs_create_file("message_poll_async", 0600, raw->dentry, raw,
+			    &scmi_dbg_raw_mode_message_poll_async_fops);
+
 	debugfs_create_file("notification", 0400, raw->dentry, raw,
 			    &scmi_dbg_raw_mode_notification_fops);
 
@@ -1230,6 +1284,14 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
 			debugfs_create_file_aux_num("message_async", 0600, chd,
 					    raw, channels[i],
 					    &scmi_dbg_raw_mode_message_async_fops);
+
+			debugfs_create_file_aux_num("message_poll", 0600, chd,
+						    raw, channels[i],
+						    &scmi_dbg_raw_mode_message_poll_fops);
+
+			debugfs_create_file_aux_num("message_poll_async", 0600,
+						    chd, raw, channels[i],
+						    &scmi_dbg_raw_mode_message_poll_async_fops);
 		}
 	}
 
-- 
2.47.0



From kees at kernel.org  Mon Mar 10 11:09:48 2025
From: kees at kernel.org (Kees Cook)
Date: Mon, 10 Mar 2025 11:09:48 -0700
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88jbhobIz2yWBbJ@arm.com>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
Message-ID: <202503101107.995ECFA@keescook>

On Mon, Mar 10, 2025 at 05:37:50PM +0000, Catalin Marinas wrote:
> On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > this is incompatible with MTE which will fault on a partially invalid
> > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > bug for now by disabling the optimizations if the kernel is built
> > > with HW tag-based KASAN and consider improvements for followup changes.
> > 
> > Why is faulting on a partially invalid read a problem? It's still
> > invalid, so ... it should fault, yes? What am I missing?
> 
> read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> beyond the end of string. The has_zero() function is then used to check
> where the string ends. For this uses, I think we can go with
> load_unaligned_zeropad() which handles a potential fault and pads the
> rest with zeroes.

Agh, right, I keep forgetting that this can read past the end of the
actual allocation. I'd agree, load_unaligned_zeropad() makes sense
there.

> 
> > > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > > Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> > > Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> > > Cc: stable at vger.kernel.org
> > > ---
> > >  fs/dcache.c  | 2 +-
> > >  lib/string.c | 3 ++-
> > >  2 files changed, 3 insertions(+), 2 deletions(-)
> > 
> > Why are DCACHE_WORD_ACCESS and HAVE_EFFICIENT_UNALIGNED_ACCESS separate
> > things? I can see at least one place where it's directly tied:
> > 
> > arch/arm/Kconfig:58:    select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
> 
> DCACHE_WORD_ACCESS requires load_unaligned_zeropad() which handles the
> faults. For some reason, read_word_at_a_time() doesn't expect to fault
> and it is only used with HAVE_EFFICIENT_UNALIGNED_ACCESS. I guess arm32
> only enabled load_unaligned_zeropad() on hardware that supports
> efficient unaligned accesses (v6 onwards), hence the dependency.
> 
> > Would it make sense to sort this out so that KASAN_HW_TAGS can be taken
> > into account at the Kconfig level instead?
> 
> I don't think we should play with config options but rather sort out the
> fault path (load_unaligned_zeropad) or disable MTE temporarily. I'd go
> with the former as long as read_word_at_a_time() is only used for
> strings in conjunction with has_zero(). I haven't checked.

Okay, sounds good. (And with a mild thread-merge: yes, folks want to use
KASAN_HW_TAGS=y in production.)

-- 
Kees Cook


From gregkh at linuxfoundation.org  Mon Mar 10 10:04:47 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon, 10 Mar 2025 18:04:47 +0100
Subject: [PATCH 5.15 441/620] drm/rockchip: cdn-dp: Use drm_connector_helper_hpd_irq_event()
In-Reply-To: <20250310170545.553361750@linuxfoundation.org>
References: <20250310170545.553361750@linuxfoundation.org>
Message-ID: <20250310170603.006059216@linuxfoundation.org>

5.15-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Thomas Zimmermann <tzimmermann at suse.de>

[ Upstream commit 666e1960464140cc4bc9203c203097e70b54c95a ]

The code for detecting and updating the connector status in
cdn_dp_pd_event_work() has a number of problems.

- It does not aquire the locks to call the detect helper and update
the connector status. These are struct drm_mode_config.connection_mutex
and struct drm_mode_config.mutex.

- It does not use drm_helper_probe_detect(), which helps with the
details of locking and detection.

- It uses the connector's status field to determine a change to
the connector status. The epoch_counter field is the correct one. The
field signals a change even if the connector status' value did not
change.

Replace the code with a call to drm_connector_helper_hpd_irq_event(),
which fixes all these problems.

Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
Fixes: 81632df69772 ("drm/rockchip: cdn-dp: do not use drm_helper_hpd_irq_event")
Cc: Chris Zhong <zyw at rock-chips.com>
Cc: Guenter Roeck <groeck at chromium.org>
Cc: Sandy Huang <hjc at rock-chips.com>
Cc: "Heiko St?bner" <heiko at sntech.de>
Cc: Andy Yan <andy.yan at rock-chips.com>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-rockchip at lists.infradead.org
Cc: <stable at vger.kernel.org> # v4.11+
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20241105133848.480407-1-tzimmermann at suse.de
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/gpu/drm/rockchip/cdn-dp-core.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index b9ef35a35c857..af1e361da8df9 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -916,9 +916,6 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
 {
 	struct cdn_dp_device *dp = container_of(work, struct cdn_dp_device,
 						event_work);
-	struct drm_connector *connector = &dp->connector;
-	enum drm_connector_status old_status;
-
 	int ret;
 
 	mutex_lock(&dp->lock);
@@ -980,11 +977,7 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
 
 out:
 	mutex_unlock(&dp->lock);
-
-	old_status = connector->status;
-	connector->status = connector->funcs->detect(connector, false);
-	if (old_status != connector->status)
-		drm_kms_helper_hotplug_event(dp->drm_dev);
+	drm_connector_helper_hpd_irq_event(&dp->connector);
 }
 
 static int cdn_dp_pd_event(struct notifier_block *nb,
-- 
2.39.5





From mark.rutland at arm.com  Mon Mar 10 11:13:58 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 18:13:58 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88jbhobIz2yWBbJ@arm.com>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
Message-ID: <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>

On Mon, Mar 10, 2025 at 05:37:50PM +0000, Catalin Marinas wrote:
> On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > this is incompatible with MTE which will fault on a partially invalid
> > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > bug for now by disabling the optimizations if the kernel is built
> > > with HW tag-based KASAN and consider improvements for followup changes.
> > 
> > Why is faulting on a partially invalid read a problem? It's still
> > invalid, so ... it should fault, yes? What am I missing?
> 
> read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> beyond the end of string. The has_zero() function is then used to check
> where the string ends. For this uses, I think we can go with
> load_unaligned_zeropad() which handles a potential fault and pads the
> rest with zeroes.

If we only care about synchronous and asymmetric modes, that should be
possible, but that won't work in asynchronous mode. In asynchronous mode
the fault will accumulate into TFSR and will be detected later
asynchronously where it cannot be related to its source and fixed up.

That means that both read_word_at_a_time() and load_unaligned_zeropad()
are dodgy in async mode.

Can we somehow hang this off ARCH_HAS_SUBPAGE_FAULTS?

... and is there anything else that deliberately makes accesses that
could straddle objects?

Mark.


From dan.carpenter at linaro.org  Mon Mar 10 11:14:55 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 10 Mar 2025 21:14:55 +0300
Subject: [PATCH] staging: vchiq_arm: Don't use %pK through printk
In-Reply-To: <20250310-restricted-pointers-vchiq_arm-v1-1-dd04f208ee55@linutronix.de>
References: <20250310-restricted-pointers-vchiq_arm-v1-1-dd04f208ee55@linutronix.de>
Message-ID: <eb4eeb0c-7cdd-44b6-a9bb-11133ff55925@stanley.mountain>

On Mon, Mar 10, 2025 at 04:53:33PM +0100, Thomas Wei?schuh wrote:
> @@ -2003,7 +2003,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
>  
>  	if (((unsigned long)header & VCHIQ_SLOT_MASK) +
>  	    calc_stride(size) > VCHIQ_SLOT_SIZE) {
> -		dev_err(state->dev, "core: header %pK (msgid %x) - size %x too big for slot\n",
> +		dev_err(state->dev, "core: header %K (msgid %x) - size %x too big for slot\n",
                                                   ^^
You deleted the wrong character here.  :P

regards,
dan carpenter



From dlechner at baylibre.com  Mon Mar 10 11:15:28 2025
From: dlechner at baylibre.com (David Lechner)
Date: Mon, 10 Mar 2025 13:15:28 -0500
Subject: [PATCH 1/2] counter: Introduce the compare component
In-Reply-To: <20250306-introduce-compare-component-v1-1-93993b3dca9c@kernel.org>
References: <20250306-introduce-compare-component-v1-0-93993b3dca9c@kernel.org>
 <20250306-introduce-compare-component-v1-1-93993b3dca9c@kernel.org>
Message-ID: <cf5b14f4-ac10-49a1-9f02-32cdcf62839e@baylibre.com>

On 3/6/25 1:05 AM, William Breathitt Gray wrote:

...

> @@ -301,6 +309,7 @@ Description:
>  
>  What:		/sys/bus/counter/devices/counterX/cascade_counts_enable_component_id
>  What:		/sys/bus/counter/devices/counterX/external_input_phase_clock_select_component_id
> +What:		/sys/bus/counter/devices/counterX/countY/compare_component_id

Prefer alphabetical order?

>  What:		/sys/bus/counter/devices/counterX/countY/capture_component_id
>  What:		/sys/bus/counter/devices/counterX/countY/ceiling_component_id
>  What:		/sys/bus/counter/devices/counterX/countY/floor_component_id


From pchelkin at ispras.ru  Mon Mar 10 11:23:32 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Mon, 10 Mar 2025 21:23:32 +0300
Subject: [PATCH 2/3] usb: chipidea: ci_hdrc_imx: disable regulator on
 error path in probe
In-Reply-To: <Z8781hzSKJ5P0gBe@lizhi-Precision-Tower-5810>
References: <20250309175805.661684-1-pchelkin@ispras.ru>
 <20250309175805.661684-3-pchelkin@ispras.ru>
 <Z8781hzSKJ5P0gBe@lizhi-Precision-Tower-5810>
Message-ID: <lbsj2h2zut3eafu5vy6ysuv4y7xjuqtemovqtg3lzuyhp6fjbl@4xwikb3bxl7k>

On Mon, 10. Mar 10:53, Frank Li wrote:
> On Sun, Mar 09, 2025 at 08:57:58PM +0300, Fedor Pchelkin wrote:
> > Upon encountering errors during the HSIC pinctrl handling section the
> > regulator should be disabled.
> >
> > After the above-stated changes it is possible to jump onto
> > "disable_hsic_regulator" label without having added the CPU latency QoS
> > request previously. This would result in cpu_latency_qos_remove_request()
> > yielding a WARNING.
> >
> > So rearrange the error handling path to follow the reverse order of
> > different probing phases.
> 
> Suggest use devm_add_action() to simple whole error handle code.

I'll try with that in v2 then, thanks for suggestion.

> 
> >
> > Found by Linux Verification Center (linuxtesting.org).
> 
> I think this sentense have not provide valuable informaiton for reader.

Well, that's a line which the organization rules specify to put into
every bugfix patch found on its behalf. I must follow these rules.

Btw, you can find this in the changelogs of many other commits existing
in the main kernel tree:

$ git shortlog --grep="linuxtesting.org" --group=format:""
 (859):
      kernel/range.c: fix clean_sort_range() for the case of full array
      Staging: pohmelfs/dir.c: Remove unneeded mutex_unlock() from pohmelfs_rename()
      USB: usb-gadget: unlock data->lock mutex on error path in ep_read()
      ...

> 
> Frank
> 
> >
> > Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional")
> > Cc: stable at vger.kernel.org
> > Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
> > ---
> >  drivers/usb/chipidea/ci_hdrc_imx.c | 15 ++++++++-------
> >  1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> > index 619779eef333..3f11ae071c7f 100644
> > --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> > +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> > @@ -407,13 +407,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
> >  				"pinctrl_hsic_idle lookup failed, err=%ld\n",
> >  					PTR_ERR(pinctrl_hsic_idle));
> >  			ret = PTR_ERR(pinctrl_hsic_idle);
> > -			goto err_put;
> > +			goto disable_hsic_regulator;
> >  		}
> >
> >  		ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle);
> >  		if (ret) {
> >  			dev_err(dev, "hsic_idle select failed, err=%d\n", ret);
> > -			goto err_put;
> > +			goto disable_hsic_regulator;
> >  		}
> >
> >  		data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
> > @@ -423,7 +423,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
> >  				"pinctrl_hsic_active lookup failed, err=%ld\n",
> >  					PTR_ERR(data->pinctrl_hsic_active));
> >  			ret = PTR_ERR(data->pinctrl_hsic_active);
> > -			goto err_put;
> > +			goto disable_hsic_regulator;
> >  		}
> >  	}
> >
> > @@ -432,11 +432,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
> >
> >  	ret = imx_get_clks(dev);
> >  	if (ret)
> > -		goto disable_hsic_regulator;
> > +		goto qos_remove_request;
> >
> >  	ret = imx_prepare_enable_clks(dev);
> >  	if (ret)
> > -		goto disable_hsic_regulator;
> > +		goto qos_remove_request;
> >
> >  	ret = clk_prepare_enable(data->clk_wakeup);
> >  	if (ret)
> > @@ -526,12 +526,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
> >  	clk_disable_unprepare(data->clk_wakeup);
> >  err_wakeup_clk:
> >  	imx_disable_unprepare_clks(dev);
> > +qos_remove_request:
> > +	if (pdata.flags & CI_HDRC_PMQOS)
> > +		cpu_latency_qos_remove_request(&data->pm_qos_req);
> >  disable_hsic_regulator:
> >  	if (data->hsic_pad_regulator)
> >  		/* don't overwrite original ret (cf. EPROBE_DEFER) */
> >  		regulator_disable(data->hsic_pad_regulator);
> > -	if (pdata.flags & CI_HDRC_PMQOS)
> > -		cpu_latency_qos_remove_request(&data->pm_qos_req);
> >  	data->ci_pdev = NULL;
> >  err_put:
> >  	if (data->usbmisc_data)
> > --
> > 2.48.1
> >


From ardb+git at google.com  Mon Mar 10 11:30:12 2025
From: ardb+git at google.com (Ard Biesheuvel)
Date: Mon, 10 Mar 2025 19:30:12 +0100
Subject: [PATCH] arm64/kernel: Always use level 2 or higher for early mappings
Message-ID: <20250310183011.2591600-2-ardb+git@google.com>

From: Ard Biesheuvel <ardb at kernel.org>

The page table population code in map_range() uses a recursive algorithm
to create the early mappings of the kernel, the DTB and the ID mapped
text and data pages, and this fails to take into account that the way
these page tables may be constructed is not precisely the same at each
level. In particular, block mappings are not permitted at each level,
and the code as it exists today might inadvertently create such a
forbidden block mapping if it were used to map a region of the
appropriate size and alignment.

This never happens in practice, given the limited size of the assets
being mapped by the early boot code. Nonetheless, it would be better if
this code would behave correctly in all circumstances.

So only permit block mappings at level 2, and page mappings at level 3,
for any page size, and use table mappings exclusively at all other
levels. This change should have no impact in practice, but it makes the
code more robust.

Cc: Anshuman Khandual <anshuman.khandual at arm.com>
Reported-by: Ryan Roberts <ryan.roberts at arm.com>
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm64/kernel/pi/map_range.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..025bb9f0aa0b 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -40,17 +40,10 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	/* Advance tbl to the entry that covers start */
 	tbl += (start >> (lshift + PAGE_SHIFT)) % PTRS_PER_PTE;
 
-	/*
-	 * Set the right block/page bits for this level unless we are
-	 * clearing the mapping
-	 */
-	if (protval)
-		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
-
 	while (start < end) {
 		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
 
-		if (level < 3 && (start | next | pa) & lmask) {
+		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
 			/*
 			 * This chunk needs a finer grained mapping. Create a
 			 * table mapping if necessary and recurse.
@@ -64,6 +57,14 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 				  (pte_t *)(__pte_to_phys(*tbl) + va_offset),
 				  may_use_cont, va_offset);
 		} else {
+			/*
+			 * Set the right block/page bits for this level unless
+			 * we are clearing the mapping
+			 */
+			if (protval)
+				protval |= (level == 2) ? PMD_TYPE_SECT
+							: PTE_TYPE_PAGE;
+
 			/*
 			 * Start a contiguous range if start and pa are
 			 * suitably aligned
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From catalin.marinas at arm.com  Mon Mar 10 11:32:42 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 18:32:42 +0000
Subject: [PATCH v3 0/2] arm64: cputype: Add info about some Qualcomm Kryo cores
In-Reply-To: <20241219211131.2389091-1-dianders@chromium.org>
References: <20241219211131.2389091-1-dianders@chromium.org>
Message-ID: <174163155801.3207598.4827401624809854495.b4-ty@arm.com>

On Thu, 19 Dec 2024 13:11:08 -0800, Douglas Anderson wrote:
> This series breaks off of my series that reworked Spectre BHB
> mitigations. Originally I needed Qualcomm Kryo IDs because I was
> adding "guesses" about their Spectre BHB mitigations. Now that the
> Spectre BHB series no longer has guesses I don't need them there, but
> these two patches still seem worth it to land on their own.
> 
> I've still called this series "v3" because the first patch was part of
> the v1 and v2 of the previous series.
> 
> [...]

Applied to arm64 (for-next/cputype-kryo), thanks!

[1/2] arm64: cputype: Add QCOM_CPU_PART_KRYO_3XX_GOLD
      https://git.kernel.org/arm64/c/401c3333bb23
[2/2] arm64: cputype: Add comments about Qualcomm Kryo 5XX and 6XX cores
      https://git.kernel.org/arm64/c/53a52a0ec768

-- 
Catalin



From slavine at d3embedded.com  Mon Mar 10 11:32:47 2025
From: slavine at d3embedded.com (Sebastian LaVine)
Date: Mon, 10 Mar 2025 14:32:47 -0400
Subject: [PATCH 3/4] arm64: dts: ti: k3-am62a7-sk: Add overlay for
 fusion 2 board
In-Reply-To: <bbf4f6db-cac1-4558-b345-8b4d6b36a8fa@ti.com>
References: <20250212195656.69528-1-slavine@d3embedded.com>
 <20250212195656.69528-4-slavine@d3embedded.com>
 <bbf4f6db-cac1-4558-b345-8b4d6b36a8fa@ti.com>
Message-ID: <D8CSV4M7YSV8.3QV5EGNMV1LKF@d3embedded.com>

On Tue Feb 18, 2025 at 2:07 PM EST, Vaishnav Achath wrote:
> Hi Sebastian,
>
> On 13/02/25 01:26, Sebastian LaVine wrote:
>> Adds an overlay for the Fusion 2 (FPD-Link IV) board on SK-AM62A.
>>
>
> Were you able to test and get this working without additional patches on
> linux-next?
>
> The multi-steam support for J721E-CSI2RX and CDNS-CSI2RX drivers are
> still WIP [1] and as per my understanding you will need those to get
> this overlay functional.
>
> 1 -
> https://lore.kernel.org/all/20240627-multistream-v2-0-6ae96c54c1c3 at ti.com/

Thanks for this -- I'll hold off on the overlays for the next series
revision.

--

Sebastian

Please be aware that this email includes email addresses outside of the organization.


From catalin.marinas at arm.com  Mon Mar 10 11:32:59 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 18:32:59 +0000
Subject: [PATCH 0/3] Minor improvements for PIE/POE helpers
In-Reply-To: <20250219164029.2309119-1-kevin.brodsky@arm.com>
References: <20250219164029.2309119-1-kevin.brodsky@arm.com>
Message-ID: <174163157306.3207771.13653726246249700352.b4-ty@arm.com>

On Wed, 19 Feb 2025 16:40:26 +0000, Kevin Brodsky wrote:
> This is a collection of minor cleanups and improvements for the PIE/POE
> macros in asm/sysreg.h and asm/por.h. Besides the readability
> improvement, it will also come in handy for the kpkeys series [1] that
> performs more calculations on POR_EL1.
> 
> - Kevin
> 
> [...]

Applied to arm64 (for-next/pie-poe-cleanup), thanks!

[1/3] arm64/sysreg: Improve PIR/POR helpers
      https://git.kernel.org/arm64/c/f91a3a6088ea
[2/3] arm64/sysreg: Rename POE_RXW to POE_RWX
      https://git.kernel.org/arm64/c/83d78bbfd2a4
[3/3] arm64/sysreg: Move POR_EL0_INIT to asm/por.h
      https://git.kernel.org/arm64/c/650701e4ead6

-- 
Catalin



From catalin.marinas at arm.com  Mon Mar 10 11:40:11 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 10 Mar 2025 18:40:11 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
 <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <Z88yC7Oaj9DGaswc@arm.com>

On Mon, Mar 10, 2025 at 06:13:58PM +0000, Mark Rutland wrote:
> On Mon, Mar 10, 2025 at 05:37:50PM +0000, Catalin Marinas wrote:
> > On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > > this is incompatible with MTE which will fault on a partially invalid
> > > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > > bug for now by disabling the optimizations if the kernel is built
> > > > with HW tag-based KASAN and consider improvements for followup changes.
> > > 
> > > Why is faulting on a partially invalid read a problem? It's still
> > > invalid, so ... it should fault, yes? What am I missing?
> > 
> > read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> > beyond the end of string. The has_zero() function is then used to check
> > where the string ends. For this uses, I think we can go with
> > load_unaligned_zeropad() which handles a potential fault and pads the
> > rest with zeroes.
> 
> If we only care about synchronous and asymmetric modes, that should be
> possible, but that won't work in asynchronous mode. In asynchronous mode
> the fault will accumulate into TFSR and will be detected later
> asynchronously where it cannot be related to its source and fixed up.
> 
> That means that both read_word_at_a_time() and load_unaligned_zeropad()
> are dodgy in async mode.

load_unaligned_zeropad() has a __mte_enable_tco_async() call to set
PSTATE.TCO if in async mode, so that's covered. read_word_at_a_time() is
indeed busted and I've had Vincezo's patches for a couple of years
already, they just never made it to the list.

> Can we somehow hang this off ARCH_HAS_SUBPAGE_FAULTS?

We could, though that was mostly for user-space faults while in-kernel
we'd only need something similar if KASAN_HW_TAGS.

> ... and is there anything else that deliberately makes accesses that
> could straddle objects?

So far we only came across load_unaligned_zeropad() and
read_word_at_a_time(). I'm not aware of anything else.

-- 
Catalin


From andersson at kernel.org  Mon Mar 10 12:11:41 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 10 Mar 2025 14:11:41 -0500
Subject: [GIT PULL] Qualcomm clock fix for v6.14
Message-ID: <20250310191142.1208155-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-clk-fixes-for-6.14

for you to fetch changes up to 787289a1d13d50ff4ce0f496947f8817ef3fdea9:

  clk: qcom: dispcc-sm8750: Drop incorrect CLK_SET_RATE_PARENT on byte intf parent (2025-02-26 08:57:46 -0600)

----------------------------------------------------------------
Qualcomm clock fix for v6.14

Avoid propagating rate changes for the MDSS byte intf clocks on SM8750,
to avoid changing the already configured clocks.

----------------------------------------------------------------
Krzysztof Kozlowski (1):
      clk: qcom: dispcc-sm8750: Drop incorrect CLK_SET_RATE_PARENT on byte intf parent

 drivers/clk/qcom/dispcc-sm8750.c | 2 --
 1 file changed, 2 deletions(-)


From andersson at kernel.org  Mon Mar 10 12:14:08 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 10 Mar 2025 14:14:08 -0500
Subject: [GIT PULL] Qualcomm Arm64 Devicetree fixes for v6.14
Message-ID: <20250310191409.1208520-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm64-fixes-for-6.14

for you to fetch changes up to f00db31d235946853fb430de8c6aa1295efc8353:

  Revert "arm64: dts: qcom: sdm845: Affirm IDR0.CCTW on apps_smmu" (2025-02-25 09:52:52 -0600)

----------------------------------------------------------------
Qualcomm Arm64 Devicetree fixes for v6.14

Revert the change to marking SDM845 SMMU dma-coherent, as this is
reported not to be true.

----------------------------------------------------------------
Konrad Dybcio (1):
      Revert "arm64: dts: qcom: sdm845: Affirm IDR0.CCTW on apps_smmu"

 arch/arm64/boot/dts/qcom/sdm845.dtsi | 1 -
 1 file changed, 1 deletion(-)


From jic23 at kernel.org  Mon Mar 10 12:25:03 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Mon, 10 Mar 2025 19:25:03 +0000
Subject: [PATCH v5 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <4d5212b3-3801-408c-9a5d-c6111189793c@gmail.com>
References: <cover.1740993491.git.mazziesaccount@gmail.com>
	<e71c63c2f61135f9a8c7884525aab2c48f1e84c2.1740993491.git.mazziesaccount@gmail.com>
	<CAMknhBGQaqFZJsPAoauZL4S5MYtN05EOQ-BO2vw5gH+Z2RLOhw@mail.gmail.com>
	<54a031d0-df47-4baa-a23a-1a79c0922542@gmail.com>
	<20250308162928.72bd1d1b@jic23-huawei>
	<4d5212b3-3801-408c-9a5d-c6111189793c@gmail.com>
Message-ID: <20250310192503.71671275@jic23-huawei>

On Mon, 10 Mar 2025 09:41:00 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 08/03/2025 18:29, Jonathan Cameron wrote:
> > On Wed, 5 Mar 2025 12:54:33 +0200
> > Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> >   
> >> Thanks for the review David.
> >>
> >> On 04/03/2025 11:25, David Lechner wrote:  
> >>> On Mon, Mar 3, 2025 at 12:32?PM Matti Vaittinen
> >>> <mazziesaccount at gmail.com> wrote:  
> >>>>
> >>>> There are ADC ICs which may have some of the AIN pins usable for other
> >>>> functions. These ICs may have some of the AIN pins wired so that they
> >>>> should not be used for ADC.
> >>>>
> >>>> (Preferred?) way for marking pins which can be used as ADC inputs is to
> >>>> add corresponding channels at N nodes in the device tree as described in
> >>>> the ADC binding yaml.
> >>>>
> >>>> Add couple of helper functions which can be used to retrieve the channel
> >>>> information from the device node.
> >>>>
> >>>> Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
> >>>>
> >>>> ---  
> >>  
> >>>> + *
> >>>> + * Return:     Number of found channels on succes. Negative value to indicate  
> >>>
> >>> s/succes/success/  
> >>
> >> Thanks!
> >>  
> >>>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> >>>> +                                         const struct iio_chan_spec *template,
> >>>> +                                         int max_chan_id,
> >>>> +                                         struct iio_chan_spec **cs)
> >>>> +{
> >>>> +       struct iio_chan_spec *chan_array, *chan;
> >>>> +       int num_chan = 0, ret;
> >>>> +
> >>>> +       num_chan = iio_adc_device_num_channels(dev);
> >>>> +       if (num_chan < 1)
> >>>> +               return num_chan;
> >>>> +
> >>>> +       chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
> >>>> +                                 GFP_KERNEL);
> >>>> +       if (!chan_array)
> >>>> +               return -ENOMEM;
> >>>> +
> >>>> +       chan = &chan_array[0];
> >>>> +
> >>>> +       device_for_each_child_node_scoped(dev, child) {
> >>>> +               u32 ch;
> >>>> +
> >>>> +               if (!fwnode_name_eq(child, "channel"))
> >>>> +                       continue;
> >>>> +
> >>>> +               ret = fwnode_property_read_u32(child, "reg", &ch);
> >>>> +               if (ret)
> >>>> +                       return ret;
> >>>> +
> >>>> +               if (max_chan_id != -1 && ch > max_chan_id)
> >>>> +                       return -ERANGE;
> >>>> +  
> >>>
> >>> Should we use return dev_err_probe() on these to help with debugging a bad dtb?
> >>>      
> >>
> >> I am not fan of using dev_err_probe() in a 'library code'. This is
> >> because we never know if there'll be some odd use-case where this is not
> >> called from the probe.
> >>
> >> All in all, I'd leave adding most of the debugs to the callers -
> >> especially because we do not expect to have bad device-trees after the
> >> initial 'development stage' of a board. The board 'development stage'
> >> should really reveal bugs which prevent the channels from being
> >> registered - and after the DT is correct, these debug prints become
> >> unnecessary (albeit minor) binary bloat.
> >>  
> >>>> +               *chan = *template;
> >>>> +               chan->channel = ch;
> >>>> +               chan++;
> >>>> +       }
> >>>> +
> >>>> +       *cs = chan_array;
> >>>> +
> >>>> +       return num_chan;
> >>>> +}
> >>>> +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");  
> >>>
> >>> We can make this less verbose by setting #define
> >>> DEFAULT_SYMBOL_NAMESPACE at the start of the file. Then we can just do
> >>> EXPORT_SYMBOL_GPL() throughout the rest of the file.  
> >>
> >> I am not sure what to think of this. I use the good old 'ctrl + ]' in my
> >> editor when I need to check how a function was supposed to be used. That
> >> jumps to the spot of code where the function is. I'd like to see the
> >> namespace mentioned there in order to not accidentally miss the fact the
> >> function belongs to one.
> >>
> >> OTOH, I do like simplifications. Yet, the added simplification might not
> >> warrant the namespace not being visible in the function definition.
> >>  
> >>> Also, I would prefer if the namespace matched config name (IIO_ADC_HELPER).  
> >>
> >> I had some lengthy discussion about this with Andy and Jonathan during
> >> earlier review versions. In short, I don't like the idea of very
> >> fragmented namespaces in IIO, which will just complicate the drivers
> >> without providing any obvious benefit.
> >>
> >> https://lore.kernel.org/all/20250222174842.57c091c5 at jic23-huawei/
> >>  
> >>>> +
> >>>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> >>>> +                                         const struct iio_chan_spec *template,
> >>>> +                                         int max_chan_id,
> >>>> +                                         struct iio_chan_spec **cs);
> >>>> +  
> >>>
> >>> There are some different opinions on this, but on the last patch I did
> >>> introducing a new namespace, the consensus seems to be that putting
> >>> the MODULE_IMPORT_NS() in the header file was convenient so that users
> >>> of the API don't have to remember to both include the header and add
> >>> the import macro.
> >>>      
> >>
> >> I do like this suggestion, and I believe this would be the balance
> >> between getting the benefit of hiding part of the symbols - while not
> >> unnecessarily complicating the callers. I know some people are opposing
> >> it though. My personal opinion is that having the MODULE_IMPORT_NS() in
> >> a header would be neatly simplifying the calling code with very little
> >> harm, especially here where including the header hardly has use-cases
> >> outside the IIO ADC.
> >>
> >> Unfortunately, the "safety" seems to often be a synonym for just "making
> >> it intentionally hard". As Finnish people say: "K?rsi, k?rsi,
> >> kirkkaamman kruunun saat". :)
> >> (Roughly translated as "Suffer, suffer, you will get a brighter crown").
> >>
> >> Let's hear what Jonathan thinks of your suggestion.  
> > 
> > For this particular case my intent was that all the IIO exports that
> > are suitable for use in simple IIO drives will be in this namespace,
> > we just haven't started that conversion yet.
> > 
> > As such, having it defined from a header for this helper isn't a good
> > thing to do.  
> 
> Hmm. I agree.
> 
> >  Generally I prefer to see in driver code what namespaces
> > are involved but do understand the other viewpoint. In this case I
> > definitely don't think it is appropriate unless we go for a specific namespace
> > for just this helper.  
> 
> I suppose having the MODULE_IMPORT_NS() in the header would actually 
> make the more fine-grained namespaces (like IIO_ADC_HELPERS, IIO_GTS, 
> ...) much more usable. That'd relieved the drivers from explicitly 
> listing multiple namespaces while nicely limiting the visibility.
> 
> If IIO was my territory, I might want to ask people to go with that 
> approach - but I am quite happy being a freeloade.. errm, I mean, 
> bystander ;)
> 
It relieves the burden but I'd still prefer explicit opt in to namespaces
unless there is general agreement on the approach of doing it in headers
which there has not been so far.

Jonathan

> Thanks!
> 
> Yours,
> 	-- Matti



From dan.carpenter at linaro.org  Mon Mar 10 12:27:34 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 10 Mar 2025 22:27:34 +0300
Subject: [PATCH net] net: ethernet: mediatek: Fix bit field in
 mtk_set_queue_speed()
In-Reply-To: <Z87e75UV0Qc4oY64@localhost.localdomain>
References: <eaab1b7b-b33b-458b-a89a-81391bd2e6e8@stanley.mountain>
 <Z87e75UV0Qc4oY64@localhost.localdomain>
Message-ID: <aab6d5f3-7ef9-4220-8b67-ee9b09a5f168@stanley.mountain>

On Mon, Mar 10, 2025 at 01:45:35PM +0100, Michal Kubiak wrote:
> On Mon, Mar 10, 2025 at 01:48:27PM +0300, Dan Carpenter wrote:
> > This was supposed to set "FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1)"
> > but there was typo and the | operation was missing and which turned
> > it into a no-op.
> > 
> > Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues")
> > Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> > ---
> > From static analysis, not tested.
> > 
> >  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > index 922330b3f4d7..9efef0e860da 100644
> > --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > @@ -757,7 +757,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
> >  		case SPEED_100:
> >  			val |= MTK_QTX_SCH_MAX_RATE_EN |
> >  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
> > -			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
> > +			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
> >  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
> >  			break;
> >  		case SPEED_1000:
> 
> 
> There's a similar bug a few lines above (line #737):
> 
> 	case SPEED_100:
> 		val |= MTK_QTX_SCH_MAX_RATE_EN |
> 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
> 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
> 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
> 		break;
> 
> I think it would be reasonable to fix that too in the same patch.

Yes.  You're of course correct.  I'm trying to figure out why my
static checker found the one instance and not the other.  I will
send a v2.

regards,
dan carpenter



From robh at kernel.org  Mon Mar 10 12:30:45 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 10 Mar 2025 14:30:45 -0500
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop
 unnecessary status from example
In-Reply-To: <20250310124956.GA3875809-robh@kernel.org>
References: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
 <5417098.31r3eYUQgx@workhorse> <20250310124956.GA3875809-robh@kernel.org>
Message-ID: <CAL_JsqJShHSMzMwiYA79OppJYKKR8qN=1soXPV_hCZiXGyVkSg@mail.gmail.com>

On Mon, Mar 10, 2025 at 7:49?AM Rob Herring <robh at kernel.org> wrote:
>
> On Fri, Mar 07, 2025 at 03:05:50PM +0100, Nicolas Frattaroli wrote:
> > On Friday, 7 March 2025 10:33:09 Central European Standard Time Krzysztof
> > Kozlowski wrote:
> > > Device nodes are enabled by default, so no need for 'status = "okay"' in
> > > the DTS example.
> > >
> > > Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> > > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> > >
> > > ---
> > >
> > > Changes in v2:
> > > 1. Drop unnecessary full stop in subject prefix after ':'.
> > > 2. Add Rb tag.
> > > ---
> > >  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
> > >  1 file changed, 1 deletion(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > > b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml index
> > > 757967212f55..ca71b400bcae 100644
> > > --- a/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > > +++ b/Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml
> > > @@ -53,7 +53,6 @@ examples:
> > >          interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
> > >          clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
> > >          resets = <&scmi_reset SCMI_SRST_H_TRNG_NS>;
> > > -        status = "okay";
> > >        };
> > >      };
> >
> > Hi,
> >
> > is there the possibility we could make dtschema as invoked by `make
> > dt_binding_check W=1` (or W=2) add a warning for examples that have disabled
> > or explicitly listed status properties when not needed? Or is this something
> > better handled in, say, checkpatch.pl?
> >
> > The question arises because dumb mistakes by me like this should ideally be
> > caught before they waste precious maintainer time.
> >
> > If it's best handled in dtschema, I can look into working on that so you guys
> > don't have to do even more work due to me.
>
> Trust me, I'm always looking for things to check automatically. :)
>
> I have something like that which adds a schema for examples only. I
> think there were some corner cases. I'll take a fresh look at it.

I got my check working again. i2c/i2c-demux-pinctrl.yaml is the
problematic one. Not sure what to do there.

Rob


From mark.rutland at arm.com  Mon Mar 10 12:37:32 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 10 Mar 2025 19:37:32 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88yC7Oaj9DGaswc@arm.com>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
 <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>
 <Z88yC7Oaj9DGaswc@arm.com>
Message-ID: <Z88_fFgr23_EtHMf@J2N7QTR9R3>

On Mon, Mar 10, 2025 at 06:40:11PM +0000, Catalin Marinas wrote:
> On Mon, Mar 10, 2025 at 06:13:58PM +0000, Mark Rutland wrote:
> > On Mon, Mar 10, 2025 at 05:37:50PM +0000, Catalin Marinas wrote:
> > > On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > > > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > > > this is incompatible with MTE which will fault on a partially invalid
> > > > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > > > bug for now by disabling the optimizations if the kernel is built
> > > > > with HW tag-based KASAN and consider improvements for followup changes.
> > > > 
> > > > Why is faulting on a partially invalid read a problem? It's still
> > > > invalid, so ... it should fault, yes? What am I missing?
> > > 
> > > read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> > > beyond the end of string. The has_zero() function is then used to check
> > > where the string ends. For this uses, I think we can go with
> > > load_unaligned_zeropad() which handles a potential fault and pads the
> > > rest with zeroes.
> > 
> > If we only care about synchronous and asymmetric modes, that should be
> > possible, but that won't work in asynchronous mode. In asynchronous mode
> > the fault will accumulate into TFSR and will be detected later
> > asynchronously where it cannot be related to its source and fixed up.
> > 
> > That means that both read_word_at_a_time() and load_unaligned_zeropad()
> > are dodgy in async mode.
> 
> load_unaligned_zeropad() has a __mte_enable_tco_async() call to set
> PSTATE.TCO if in async mode, so that's covered. read_word_at_a_time() is
> indeed busted and I've had Vincezo's patches for a couple of years
> already, they just never made it to the list.

Sorry, I missed the __mte_{enable,disable}_tco_async() calls. So long as
we're happy to omit the check in that case, that's fine.

I was worried that ex_handler_load_unaligned_zeropad() might not do the
right thing in response to a tag check fault (e.g. access the wrong 8
bytes), but it looks as though that's ok due to the way it generates the
offset and the aligned pointer.

If load_unaligned_zeropad() is handed a string that starts with an
unexpected tag (and even if that starts off aligned),
ex_handler_load_unaligned_zeropad() will access that and cause another
tag check fault, which will be reported.

Mark.


From slavine at d3embedded.com  Mon Mar 10 12:39:02 2025
From: slavine at d3embedded.com (Sebastian LaVine)
Date: Mon, 10 Mar 2025 15:39:02 -0400
Subject: [PATCH 2/4] media: i2c: Add driver for Sony IMX728
In-Reply-To: <20250213101903.GH5888@pendragon.ideasonboard.com>
References: <20250212195656.69528-1-slavine@d3embedded.com>
 <20250212195656.69528-3-slavine@d3embedded.com>
 <20250213101903.GH5888@pendragon.ideasonboard.com>
Message-ID: <D8CU9UT1XQV9.3NFZ4OAQOKQG0@d3embedded.com>

On Thu Feb 13, 2025 at 5:19 AM EST, Laurent Pinchart wrote:
>
> ...
>
>> +static const struct cci_reg_sequence imx728_wdr_12bit_3856x2176[] = {
>
> This table is way too big, with over 8000 entries. Some are even
> duplicated, with identical or different values for the same register. It
> will take more than a second at 400kHz to program this.
>
> At the very least I would expect a way to compact the table and make use
> of I2C register address auto-increment. Default power-up values should
> also likely be just dropped.
>
> I haven't checked in details, but doesn't this table also contain tuning
> data for your specific camera ?
>

In my testing, it takes around two seconds to write this table to the sensor.

I can investigate how to condense the table further, though the
registers for this sensor are more complex than just writing values to
addresses. The meaning of certain address writes depend on previous
writes -- thus the "duplicated" writes you mentioned.

I do not believe this table contains tuning information for our camera
module in particular.

> [snip]
>
>> +};
>
> [snip]
>
>> +static int imx728_get_frame_interval(struct v4l2_subdev *sd,
>> +                                    struct v4l2_subdev_state *sd_state,
>> +                                    struct v4l2_subdev_frame_interval *fi)
>> +{
>> +       struct imx728 *imx728 = to_imx728(sd);
>> +
>> +       fi->interval.numerator = 1;
>> +       fi->interval.denominator = imx728->fps;
>> +       return 0;
>> +}
>> +
>> +static int imx728_set_frame_interval(struct v4l2_subdev *sd,
>> +                                    struct v4l2_subdev_state *sd_state,
>> +                                    struct v4l2_subdev_frame_interval *fi)
>> +{
>> +       struct imx728 *imx728 = to_imx728(sd);
>> +       u32 req_fps;
>> +
>> +       mutex_lock(&imx728->lock);
>> +
>> +       if (fi->interval.numerator == 0 || fi->interval.denominator == 0) {
>> +               fi->interval.denominator = IMX728_FRAMERATE_DEFAULT;
>> +               fi->interval.numerator = 1;
>> +       }
>> +
>> +       req_fps = clamp_val(DIV_ROUND_CLOSEST(fi->interval.denominator,
>> +                                             fi->interval.numerator),
>> +                           IMX728_FRAMERATE_MIN, IMX728_FRAMERATE_MAX);
>> +
>> +       fi->interval.numerator = 1;
>> +       fi->interval.denominator = req_fps;
>> +
>> +       imx728->fps = req_fps;
>> +
>> +       mutex_unlock(&imx728->lock);
>> +       dev_dbg(imx728->dev, "%s frame rate = %d\n", __func__, imx728->fps);
>> +
>> +       return 0;
>> +}
>
> The frame rate on raw sensors is controlled through h/v blanking. You
> can drop thse functions, especially given that imx728->fps isn't used
> anywhere else.

Okay, I will drop these functions in v4. Thanks.

--
Sebastian

Please be aware that this email includes email addresses outside of the organization.


From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:16 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:16 -0300
Subject: [PATCH v1 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-2-ariel.dalessandro@collabora.com>

Panfrost does not support uncached mappings, so flag them properly. Also
flag the pages that are mapped as response to a page fault as cached.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index b91019cd5acb1..9e6f198ef5c1b 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 	struct drm_gem_object *obj = &shmem->base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
-	int prot = IOMMU_READ | IOMMU_WRITE;
+	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
 
 	if (WARN_ON(mapping->active))
 		return 0;
@@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
 		goto err_map;
 
 	mmu_map_sg(pfdev, bomapping->mmu, addr,
-		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
 
 	bomapping->active = true;
 	bo->heap_rss_size += SZ_2M;
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:17 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:17 -0300
Subject: [PATCH v1 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-3-ariel.dalessandro@collabora.com>

As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
which makes code easier to read and reuse.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 9e6f198ef5c1b..294f86b3c25e7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
 
 struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
+	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
+	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 
 	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
 		.pgsize_bitmap	= SZ_4K | SZ_2M,
-		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
-		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
+		.ias		= va_bits,
+		.oas		= pa_bits,
 		.coherent_walk	= pfdev->coherent,
 		.tlb		= &mmu_tlb_ops,
 		.iommu_dev	= pfdev->dev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index c7bba476ab3f3..b5f279a19a084 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -16,6 +16,8 @@
 #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
 
 #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
+#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
+#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
 #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
 #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
 
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:18 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:18 -0300
Subject: [PATCH v1 3/6] drm/panfrost: Unify panfrost_mmu_enable/disable common code
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-4-ariel.dalessandro@collabora.com>

Both these functions write to MMU_AS_CONTROL register in the same way.
Define a common _panfrost_mmu_as_control_write function with the shared
code.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 33 ++++++++++++-------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 294f86b3c25e7..31df3a96f89bd 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -121,38 +121,37 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 	return ret;
 }
 
-static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
+static void
+_panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
+			       u64 transtab, u64 memattr)
 {
-	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
-
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
 	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab));
 	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab));
 
-	/* Need to revisit mem attrs.
-	 * NC is the default, Mali driver is inner WT.
-	 */
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
-static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
+static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
-	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
-
-	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), 0);
-	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), 0);
+	int as_nr = mmu->as;
+	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
+	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
+	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
 
-	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
-	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
+	/* Need to revisit mem attrs.
+	 * NC is the default, Mali driver is inner WT.
+	 */
+	_panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
+}
 
-	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
+static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
+{
+	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
 }
 
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:19 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:19 -0300
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page table format
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-5-ariel.dalessandro@collabora.com>

Currently, Panfrost only supports MMU configuration in "LEGACY" (as
Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called "mali_lpae".

This commit adds support for conditionally enabling AARCH64_4K page
table format. To achieve that, a "GPU optional configurations" field was
added to `struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
 drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
 3 files changed, 169 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index cffcb0ac7c111..0385702aa43c7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
 	GPU_PM_VREG_OFF,
 };
 
+/**
+ * enum panfrost_gpu_config - GPU optional configurations
+ * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
+ */
+enum panfrost_gpu_config {
+	GPU_CONFIG_AARCH64_4K,
+};
+
 struct panfrost_features {
 	u16 id;
 	u16 revision;
@@ -95,6 +103,9 @@ struct panfrost_compatible {
 
 	/* Allowed PM features */
 	u8 pm_features;
+
+	/* GPU features */
+	u8 gpu_configs;
 };
 
 struct panfrost_device {
@@ -162,6 +173,11 @@ struct panfrost_mmu {
 	int as;
 	atomic_t as_count;
 	struct list_head list;
+	struct {
+		u64 transtab;
+		u64 memattr;
+		u64 transcfg;
+	} cfg;
 };
 
 struct panfrost_engine_usage {
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 31df3a96f89bd..4a9b8de2ff987 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -26,6 +26,48 @@
 #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define mmu_read(dev, reg) readl(dev->iomem + reg)
 
+static u64 mair_to_memattr(u64 mair, bool coherent)
+{
+	u64 memattr = 0;
+	u32 i;
+
+	for (i = 0; i < 8; i++) {
+		u8 in_attr = mair >> (8 * i), out_attr;
+		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
+
+		/* For caching to be enabled, inner and outer caching policy
+		 * have to be both write-back, if one of them is write-through
+		 * or non-cacheable, we just choose non-cacheable. Device
+		 * memory is also translated to non-cacheable.
+		 */
+		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
+				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
+		} else {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
+			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
+			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
+			 * to Mali's internal-shareable mode. As per the Mali
+			 * Spec, inner and outer-shareable modes aren't allowed
+			 * for WB memory when coherency is disabled.
+			 * Use SH_CPU_INNER mode when coherency is enabled, so
+			 * that SH_IS actually maps to the standard definition of
+			 * inner-shareable.
+			 */
+			if (!coherent)
+				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
+			else
+				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
+		}
+
+		memattr |= (u64)out_attr << (8 * i);
+	}
+
+	return memattr;
+}
+
 static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
 {
 	int ret;
@@ -121,9 +163,57 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 	return ret;
 }
 
+static void mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	/* TODO: The following fields are duplicated between the MMU and Page
+	 * Table config structs. Ideally, should be kept in one place.
+	 */
+	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
+	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
+	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
+}
+
+static void mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
+				AS_TRANSTAB_AARCH64_4K_ADDR_MASK;
+
+	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
+					   pgtbl_cfg->coherent_walk);
+
+	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
+			    AS_TRANSCFG_PTW_RA |
+			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
+			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
+	if (pgtbl_cfg->coherent_walk)
+		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
+}
+
+static void panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
+				  enum io_pgtable_fmt fmt)
+{
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		mmu_cfg_init_aarch64_4k(mmu);
+		break;
+	case ARM_MALI_LPAE:
+		mmu_cfg_init_mali_lpae(mmu);
+		break;
+	default:
+		dev_WARN_ONCE(pfdev->dev, 1, "Unhandled page table format\n");
+		break;
+	}
+}
+
 static void
 _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
-			       u64 transtab, u64 memattr)
+			       u64 transtab, u64 memattr, u64 transcfg)
 {
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
@@ -133,25 +223,28 @@ _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
+
+	dev_dbg(pfdev->dev, "mmu_as_control: as=%d, transtab=0x%016llx, memattr=0x%016llx, transcfg=0x%016llx",
+		as_nr, transtab, memattr, transcfg);
 }
 
 static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
-	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
-
 	/* Need to revisit mem attrs.
 	 * NC is the default, Mali driver is inner WT.
 	 */
-	_panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
+	_panfrost_mmu_as_control_write(pfdev, mmu->as, mmu->cfg.transtab,
+				       mmu->cfg.memattr, mmu->cfg.transcfg);
 }
 
 static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 {
-	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
+	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0,
+				       AS_TRANSCFG_ADRMODE_UNMAPPED);
 }
 
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
@@ -616,6 +709,7 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
 	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
 	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
+	enum io_pgtable_fmt fmt = ARM_MALI_LPAE;
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -641,16 +735,28 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 		.iommu_dev	= pfdev->dev,
 	};
 
-	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
-					      mmu);
-	if (!mmu->pgtbl_ops) {
-		kfree(mmu);
-		return ERR_PTR(-EINVAL);
+	if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {
+		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
+			dev_err_once(pfdev->dev,
+				     "AARCH64_4K page table not supported\n");
+			goto err_free_mmu;
+		}
+		fmt = ARM_64_LPAE_S1;
 	}
 
+	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
+	if (!mmu->pgtbl_ops)
+		goto err_free_mmu;
+
+	panfrost_mmu_cfg_init(mmu, fmt);
+
 	kref_init(&mmu->refcount);
 
 	return mmu;
+
+err_free_mmu:
+	kfree(mmu);
+	return ERR_PTR(-EINVAL);
 }
 
 static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index b5f279a19a084..2b8f1617b8369 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -301,6 +301,17 @@
 #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
 #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
+							 ((w) ? BIT(0) : 0) | \
+							 ((r) ? BIT(1) : 0))
+#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
+#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
+#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
 #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
 #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
 #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
@@ -311,6 +322,24 @@
 /* Additional Bifrost AS registers */
 #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
 #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
+#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
+#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
+#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
+#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
+#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
+#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
+#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
+#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
+#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
+#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
+#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
+#define   AS_TRANSCFG_PTW_RA				BIT(30)
+#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
+#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
+#define   AS_TRANSCFG_WXN				BIT(35)
+#define   AS_TRANSCFG_XREADABLE				BIT(36)
 #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
@@ -326,6 +355,11 @@
 #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
 #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
 
+/*
+ * Begin AARCH64_4K MMU TRANSTAB register values
+ */
+#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
+
 #define AS_STATUS_AS_ACTIVE			0x01
 
 #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:20 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:20 -0300
Subject: [PATCH v1 5/6] drm/panfrost: Enable AARCH64_4K page table format on mediatek_mt8188
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-6-ariel.dalessandro@collabora.com>

Now that Panfrost supports AARCH64_4K page table format, let's enable it
on Mediatek MT8188.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 0f3935556ac76..d7b8bded6d784 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
 	.pm_domain_names = mediatek_mt8183_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_configs = BIT(GPU_CONFIG_AARCH64_4K),
 };
 
 static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:21 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:21 -0300
Subject: [PATCH v1 6/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost models
In-Reply-To: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
Message-ID: <20250310195921.157511-7-ariel.dalessandro@collabora.com>

Set this feature flag on all Mali Bifrost platforms as the MMU supports
AARCH64 4K page table format.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_features.h
+++ b/drivers/gpu/drm/panfrost/panfrost_features.h
@@ -54,6 +54,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g72 (\
@@ -64,6 +65,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g51 hw_features_g72
@@ -77,6 +79,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
 	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g76 (\
-- 
2.47.2



From dan.carpenter at linaro.org  Mon Mar 10 13:00:44 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 10 Mar 2025 23:00:44 +0300
Subject: [PATCH net] net: ethernet: mediatek: Fix bit field in
 mtk_set_queue_speed()
In-Reply-To: <aab6d5f3-7ef9-4220-8b67-ee9b09a5f168@stanley.mountain>
References: <eaab1b7b-b33b-458b-a89a-81391bd2e6e8@stanley.mountain>
 <Z87e75UV0Qc4oY64@localhost.localdomain>
 <aab6d5f3-7ef9-4220-8b67-ee9b09a5f168@stanley.mountain>
Message-ID: <20f34718-e60f-4361-9ad7-311d3f67e40b@stanley.mountain>

On Mon, Mar 10, 2025 at 10:27:34PM +0300, Dan Carpenter wrote:
> On Mon, Mar 10, 2025 at 01:45:35PM +0100, Michal Kubiak wrote:
> > On Mon, Mar 10, 2025 at 01:48:27PM +0300, Dan Carpenter wrote:
> > > This was supposed to set "FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1)"
> > > but there was typo and the | operation was missing and which turned
> > > it into a no-op.
> > > 
> > > Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues")
> > > Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> > > ---
> > > From static analysis, not tested.
> > > 
> > >  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > index 922330b3f4d7..9efef0e860da 100644
> > > --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > @@ -757,7 +757,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
> > >  		case SPEED_100:
> > >  			val |= MTK_QTX_SCH_MAX_RATE_EN |
> > >  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
> > > -			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
> > > +			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
> > >  			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
> > >  			break;
> > >  		case SPEED_1000:
> > 
> > 
> > There's a similar bug a few lines above (line #737):
> > 
> > 	case SPEED_100:
> > 		val |= MTK_QTX_SCH_MAX_RATE_EN |
> > 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
> > 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
> > 		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
> > 		break;
> > 
> > I think it would be reasonable to fix that too in the same patch.
> 
> Yes.  You're of course correct.  I'm trying to figure out why my
> static checker found the one instance and not the other.  I will
> send a v2.

Oh...  Duh.  if (IS_ENABLED(CONFIG_SOC_MT7621)) is false for my config so
first line wasn't reachable.

regards,
dan carpenter



From osandov at osandov.com  Mon Mar 10 13:05:04 2025
From: osandov at osandov.com (Omar Sandoval)
Date: Mon, 10 Mar 2025 13:05:04 -0700
Subject: [PATCH] arm64: reserve [_text, _stext) virtual address range
Message-ID: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>

From: Omar Sandoval <osandov at fb.com>

Since the referenced fixes commit, the kernel's .text section is only
mapped starting from _stext; the region [_text, _stext) is omitted. As a
result, other vmalloc/vmap allocations may use the virtual addresses
nominally in the range [_text, _stext). This address reuse confuses
multiple things:

1. crash_prepare_elf64_headers() sets up a segment in /proc/vmcore
   mapping the entire range [_text, _end) to
   [__pa_symbol(_text), __pa_symbol(_end)). Reading an address in
   [_text, _stext) from /proc/vmcore therefore gives the incorrect
   result.
2. Tools doing symbolization (either by reading /proc/kallsyms or based
   on the vmlinux ELF file) will incorrectly identify vmalloc/vmap
   allocations in [_text, _stext) as kernel symbols.

In practice, both of these issues affect the drgn debugger.
Specifically, there were cases where the vmap IRQ stacks for some CPUs
were allocated in [_text, _stext). As a result, drgn could not get the
stack trace for a crash in an IRQ handler because the core dump
contained invalid data for the IRQ stack address. The stack addresses
were also symbolized as being in the _text symbol.

Fix this by creating an unmapped vm_area to cover [_text, _stext). This
prevents other allocations from using it while still achieving the
original goal of not mapping unpredictable data.

Fixes: e2a073dde921 ("arm64: omit [_text, _stext) from permanent kernel mapping")
Cc: stable at vger.kernel.org
Signed-off-by: Omar Sandoval <osandov at fb.com>
---
Based on v6.14-rc6.

Thanks!

 arch/arm64/mm/mmu.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index b4df5bc5b1b8..88595ea12f39 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -703,10 +703,14 @@ static void __init declare_vma(struct vm_struct *vma,
 			       void *va_start, void *va_end,
 			       unsigned long vm_flags)
 {
-	phys_addr_t pa_start = __pa_symbol(va_start);
+	phys_addr_t pa_start = 0;
 	unsigned long size = va_end - va_start;
 
-	BUG_ON(!PAGE_ALIGNED(pa_start));
+	if (vm_flags & VM_MAP) {
+		pa_start = __pa_symbol(va_start);
+		BUG_ON(!PAGE_ALIGNED(pa_start));
+	}
+
 	BUG_ON(!PAGE_ALIGNED(size));
 
 	if (!(vm_flags & VM_NO_GUARD))
@@ -715,7 +719,7 @@ static void __init declare_vma(struct vm_struct *vma,
 	vma->addr	= va_start;
 	vma->phys_addr	= pa_start;
 	vma->size	= size;
-	vma->flags	= VM_MAP | vm_flags;
+	vma->flags	= vm_flags;
 	vma->caller	= __builtin_return_address(0);
 
 	vm_area_add_early(vma);
@@ -765,13 +769,17 @@ core_initcall(map_entry_trampoline);
  */
 static void __init declare_kernel_vmas(void)
 {
-	static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];
+	static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT + 1];
 
-	declare_vma(&vmlinux_seg[0], _stext, _etext, VM_NO_GUARD);
-	declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
-	declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
-	declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
-	declare_vma(&vmlinux_seg[4], _data, _end, 0);
+	declare_vma(&vmlinux_seg[0], _text, _stext, VM_NO_GUARD);
+	declare_vma(&vmlinux_seg[1], _stext, _etext, VM_NO_GUARD);
+	declare_vma(&vmlinux_seg[2], __start_rodata, __inittext_begin,
+		    VM_MAP | VM_NO_GUARD);
+	declare_vma(&vmlinux_seg[3], __inittext_begin, __inittext_end,
+		    VM_MAP | VM_NO_GUARD);
+	declare_vma(&vmlinux_seg[4], __initdata_begin, __initdata_end,
+		    VM_MAP | VM_NO_GUARD);
+	declare_vma(&vmlinux_seg[5], _data, _end, VM_MAP);
 }
 
 void __pi_map_range(u64 *pgd, u64 start, u64 end, u64 pa, pgprot_t prot,
-- 
2.48.1



From laurentiumihalcea111 at gmail.com  Mon Mar 10 13:06:14 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 10 Mar 2025 22:06:14 +0200
Subject: [PATCH v2 0/5] imx8mp: add support for the IMX AIPSTZ bridge
In-Reply-To: <20250307143956.aft3xolakts3nlja@pengutronix.de>
References: <20250226165314.34205-1-laurentiumihalcea111@gmail.com>
 <20250226212219.lthoofw7nrs3gtg6@pengutronix.de>
 <20250227112856.aylsurbt3uqm4ivw@pengutronix.de>
 <541539db-0015-41de-837f-aabbea68486a@gmail.com>
 <20250307143956.aft3xolakts3nlja@pengutronix.de>
Message-ID: <4aef911d-d766-4ae7-951b-76843cf33c56@gmail.com>



On 3/7/2025 4:39 PM, Marco Felsch wrote:
> On 25-03-05, Laurentiu Mihalcea wrote:
>> On 2/27/2025 1:28 PM, Marco Felsch wrote:
>>> Hi Laurentiu,
>>>
>>> On 25-02-26, Marco Felsch wrote:
>>>> Hi,
>>>>
>>>> On 25-02-26, Laurentiu Mihalcea wrote:
>>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>>>
>>>>> The AIPSTZ bridge offers some security-related configurations which can
>>>>> be used to restrict master access to certain peripherals on the bridge.
>>>>>
>>>>> Normally, this could be done from a secure environment such as ATF before
>>>>> Linux boots but the configuration of AIPSTZ5 is lost each time the power
>>>>> domain is powered off and then powered on. Because of this, it has to be
>>>>> configured each time the power domain is turned on and before any master
>>>>> tries to access the peripherals (e.g: AP, CM7, DSP, on i.MX8MP).
>>>> My question still stands:
>>>>
>>>> Setting these bits requires very often that the core is running at EL3
>>>> (e.g. secure-monitor) which is not the case for Linux. Can you please
>>>> provide more information how Linux can set these bits?
>>> Sorry I didn't noticed your response:
>>>
>>> https://lore.kernel.org/all/a62ab860-5e0e-4ebc-af1f-6fb7ac621e2b at gmail.com/
>>>
>>> If EL1 is allowed to set the security access configuration of the IP
>>> cores doesn't this mean that a backdoor can be opened? E.g. your
>>> secure-boot system configures one I2C IP core to be accessible only from
>>> secure-world S-EL1 (OP-TEE) and after the power-domain was power-cycled
>>> it's accessible from EL1 again. This doesn't seem right. Why should a
>>> user be able to limit the access permissions to an IP core to only be
>>> accessible from secure-world if the IP core is accessible from
>>> normal-world after the power-domain was power-cycled.
>>>
>>> Regards,
>>>   Marco
>> I'm no security expert so please feel free to correct me if I get
>> something wrong.
>>
>> This isn't about S/NS world. The bridge AC doesn't offer any
>> configurations for denying access to peripherals based on S/NS world.
> It does, please see the AIPSTZ_OPACR register definition. The imx-atf of
> sets OPACR registers to 0 (of course), which means that the S/NS is not
> checked _but_ it can be configured.

which bits are you referring to more precisely? because, from the OPACR
register definition we have:

1) TP (Trusted protect) - bit 0 => controls whether the peripheral allows
transactions from an untrusted master. A master is considered trusted if
MTR/MTW (from MPR registers) is set to 1 (MTR means trusted for read,
MTW means trusted for write)

2) WP (Write protect) - bit 1 => controls whether the peripherals allows
write transactions (i.e: is write protected or not)

3) SP (Supervisor protect) - bit 2 => controls whether the master needs
supervisor privilege or not to issue transactions to the peripheral. For
Cortex-A53 this refers to the execution level (EL0 - EL3). There's no S/NS
checks here. EL1-EL3 are supervisor accesses, EL0 is not.

4) BW (Buffer Writes) - bit 3 => some flow control configuration bit I'd assume


>
> Also please see chapter 4.7.6.1 Security Block:
>
> The AIPSTZ contains a security block that is connected to each
> off-platform peripheral. This block filters accesses based on
> write/read, non-secure, and supervisor signals.

yep, but this block is not configured by the AIPSTZ. AFAIK it's configured
by the CSU. So, as far as I understand it, the interaction is as follows:

basically you have the CSU which offers some security-related configurations
(see "Table 4-16 Security Levels" from the section you've mentioned). These
configurations are used by the AIPS bridges to filter transactions.

For example: assume you have peripheral X on AIPS5. The user configures
the CSU such that peripheral X should only accept R/W transactions from
privileged S world. Now, assume Cortex-A53 issues a transaction from
NS EL1 (Linux, for example). The bridge will receive the transaction and
check to see if it's privileged and S world. Since it's not then the transaction
will be aborted.

The AIPS bridge offers no S/NS world-related configuration options. All you can
do with it is:

1) Mark certain masters as "trusted" and block read/writes based on that (via MPR's
MTR/MTW and OPACR's TP)
2) Force transactions to user privilege (via MPR's MPL)
3) Make certain peripherals deny unprivileged transactions (via OPACR's SP)

>
>> AFAIK that's the job of the CSU (central security unit), which is a
>> different IP.
> Please see above.
>
>> Perhaps I shouldn't have used the term "trusted" as it might have
>> ended up creating more confusion? If so, please do let me know so I
>> can maybe add a comment about it in one of the commit messages. In
>> this context, "master X is trusted for read/writes" means "master X is
>> allowed to perform read/write transactions".
> No you didn't confused me but you triggered my interest :) and I started
> to check the (S)TRM.

glad to have picked your interest with this series!

>
>> Even if the bridge is configured to allow read/write transactions from
>> a master (i.e: master is marked as trusted for read/writes) that
>> wouldn't be very helpful.
> We're talking about the IP access permissions, right. If the
> "secure-I2C" is accessible from NS world this would make a difference of
> course.

It wouldn't though. No configuration in the AIPS bridge AC will make the I2C
accesible from NS world.

>
>> You'd still have to bypass the CSU configuration which as far as I
>> understand is also used by the bridge to deny access to peripherals
>> (e.g: if transaction is secure+privileged then forward to peripheral,
>> otherwise abort it). See the "4.7.6.1 Security Block" and "4.7.4?
>> Access Protections" chapters from the IMX8MP RM.
> I have read this too, also that the AIPSTZ can force the mode into
> user_mode regardless of the CSU settings, if I get this correct.
>
> What I don't understand as of now is the interaction of the AIPSTZ and
> the CSU. You can configure different bus-masters within the CSU to be
> S/NS as well as the pheripherals. Now the part which I don't understand
> right now: According the OPACx register description:
>
> x0xx SP0 ? This peripheral does not require supervisor privilege level
>            for accesses.
> x1xx SP1 ? This peripheral requires supervisor privilege level for
>            accesses. The master privilege level must indicate supervisor
> 	   via the hprot[1] access attribute, and the MPROTx[MPL] control
> 	   bit for the master must be set. If not, the access is
> 	   terminated with an error response and no peripheral access is
> 	   initiated on the IPS bus.
>
> The peripheral can be configured via the AIPSTZ as well. So which IP
> (CSU or AIPSTZ) override the other if the settings don't match, e.g. if
> CSU says: "this I2C controller for secure-world" and the AIPSTZ says:
> "this I2C is for non-secure-world".

the SP bit you've mentioned is used to deny unprivileged transactions.
The privilege is given by the execution level for CA53. EL0 transactions are
unprivileged, EL1-EL3 are privileged, but this can depend based on the type
of access. See Table 7-10 "Cortex-A53 MPCore mode and ARPROT and AWPROT
values" from ARM's Cortex-A53 MPCore Processor Technical Reference Manual
for details.

the bit has nothing to do with S/NS world so there's no overriding the
S/NS world-related policy given by the CSU.

>
>> Given all of this, I think the purpose of this IP's AC is to add some
>> extra, light, security features on top of the CSU.
> Or to override the CSU settings like the MPROTOx values:
>
> xxx0 MPL0 ? Accesses from this master are forced to user-mode
>            (ips_supervisor_access is forced to zero) regardless of the
> 	   hprot[1] access attribute.
> xxx1 MPL1 ? Accesses from this master are not forced to user-mode. The
>             hprot[1] access attribute is used directly to determine
> 	    ips_supervisor_access.
>
> Can you pleae elaborate a bit more how NXP designed the interaction
> between both the AIPSTZ and the CSU?

I believe this will override the privilege level of the transaction at the
bridge level. This could be useful if you want to, for instance, force
transactions for peripherals under AIPS5 to user but use HPROT[1]
(or the value you've configured via the CSU) for peripherals under AIPS4.
Not sure of an usecase in which you'd want that though.

anyways, hope my comments will shed a bit more light on this.


From vkoul at kernel.org  Mon Mar 10 13:12:56 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 01:42:56 +0530
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add support for
 RK3576
In-Reply-To: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
References: <20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com>
Message-ID: <174163757697.467704.14207163796763946102.b4-ty@kernel.org>


On Thu, 06 Mar 2025 20:29:23 +0100, Nicolas Frattaroli wrote:
> Despite the compatible already being listed in the bindings, the PHY
> driver never gained explicit support for it. This is especially a
> problem because the explicitly listed PHY addresses need to be specified
> for each SoC.
> 
> To solve this, add the compatible, and a PHY config, with the address
> gleaned from rk3576.dtsi.
> 
> [...]

Applied, thanks!

[1/1] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
      commit: 4a8463ae8d871ccd491d48a371a6789eb7378243

Best regards,
-- 
~Vinod




From vkoul at kernel.org  Mon Mar 10 13:13:01 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 01:43:01 +0530
Subject: (subset) [PATCH v3 00/15] arm64: dts: allwinner: Add basic
 Allwinner A523 support
In-Reply-To: <20250307005712.16828-1-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
Message-ID: <174163758109.467704.5227333743858525157.b4-ty@kernel.org>


On Fri, 07 Mar 2025 00:56:57 +0000, Andre Przywara wrote:
> this in an update to the series introducing the basic DT support for the
> Allwinner A523 SoC. It now comes with DTs for three boards, using
> slightly different packages of that SoC.[1]
> Functionality-wise it relies on the pinctrl[2] and clock[3] support
> series, though there are no direct code dependency series between the
> series. Two binding patches from there are required to pass dtbs_check,
> git put their patch IDs in the footer below.
> Compared to v2 only small fixes in the NMI controller driver: renaming
> the struct to better reflect its new usage, add adding the DS pin to
> the eMMC pingroup list. Adding accrued tags on the way, many thanks to
> the diligent reviewers! More detailed changelog below.
> 
> [...]

Applied, thanks!

[07/15] dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
        commit: 1f7af7f3c353ae3b384a66a82c5074ac28901160

Best regards,
-- 
~Vinod




From vkoul at kernel.org  Mon Mar 10 13:13:09 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 01:43:09 +0530
Subject: [PATCH v2 0/2] phy: freescale: imx8m-pcie: fix and cleanup phy
In-Reply-To: <20250305144355.20364-1-eichest@gmail.com>
References: <20250305144355.20364-1-eichest@gmail.com>
Message-ID: <174163758978.467704.1139455752621643908.b4-ty@kernel.org>


On Wed, 05 Mar 2025 15:43:14 +0100, Stefan Eichenberger wrote:
> The imx8m-pcie PHY PLL fails to lock under certain conditions when
> returning from suspend. This is resolved by asserting the PHY reset when
> powering off the PHY during suspend. This ensures that the PHY is
> properly reset when powering on again in resume.
> 
> Changes in v2:
> - Remove unnecessary check if perst is not null (Philipp)
> 
> [...]

Applied, thanks!

[1/2] phy: freescale: imx8m-pcie: cleanup reset logic
      commit: 97e8a2ff28a3dc36ca3cdc94f37359852d7e1c8b
[2/2] phy: freescale: imx8m-pcie: assert phy reset and perst in power off
      commit: aecb63e88c5e5fb9afb782a1577264c76f179af9

Best regards,
-- 
~Vinod




From Frank.Li at nxp.com  Mon Mar 10 13:16:38 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:38 -0400
Subject: [PATCH v10 00/10] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
Message-ID: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>

== RC side:

            ???????????                    ??????????????
 ???????    ?         ? IA: 0x8ff8_0000    ?            ?
 ? CPU ??????   ?????????????????????????  ? PCI        ?
 ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
  CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
            ?      ?  ?             ?   ?  ?            ?   PCI Addr
0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
            ?         ?             ?      ?            ?    0
0x7000_0000??????????????????????   ?      ?            ?
            ???????????         ?   ???????? CfgSpace  ???????????????
             BUS Fabric         ?          ?            ?    0
                                ?          ?            ?
                                ???????????? MemSpace  ???????????????
                        IA: 0x8000_0000    ?            ?  0x8000_0000
                                           ??????????????

Current dwc implimemnt, pci_fixup_addr() call back is needed when bus
fabric convert cpu address before send to PCIe controller.

    bus at 5f000000 {
            compatible = "simple-bus";
            #address-cells = <1>;
            #size-cells = <1>;
            ranges = <0x80000000 0x0 0x70000000 0x10000000>;

            pcie at 5f010000 {
                    compatible = "fsl,imx8q-pcie";
                    reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
                    reg-names = "dbi", "config";
                    #address-cells = <3>;
                    #size-cells = <2>;
                    device_type = "pci";
                    bus-range = <0x00 0xff>;
                    ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
                             <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
            ...
            };
    };

Device tree already can descript all address translate. Some hardware
driver implement fixup function by mask some bits of cpu address. Last
pci-imx6.c are little bit better by fetch memory resource's offset to do
fixup.

static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
{
	...
	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
	return cpu_addr - entry->offset;
}

But it is not good by using IORESOURCE_MEM to fix up io/cfg address map
although address translate is the same as IORESOURCE_MEM.

This patches to fetch untranslate range information for PCIe controller
(pcie at 5f010000: ranges). So current config ATU without cpu_fixup_addr().

== EP side:

                   Endpoint
  ?????????????????????????????????????????????????
  ?                             pcie-ep at 5f010000  ?
  ?                             ???????????????????
  ?                             ?   Endpoint     ??
  ?                             ?   PCIe         ??
  ?                             ?   Controller   ??
  ?           bus at 5f000000      ?                ??
  ?           ????????????      ?                ??
  ?           ?          ? Outbound Transfer     ??
  ????????    ?  Bus     ???????? ATU  ??????????????????
  ??     ?    ?  Fabric  ?Bus   ?                ??PCI Addr
  ?? CPU ??????          ?Addr  ?                ??0xA000_0000
  ??     ?CPU ?          ?0x8000_0000            ??
  ????????Addr????????????      ?                ??
  ?       0x7000_0000           ???????????????????
  ?????????????????????????????????????????????????

bus at 5f000000 {
        compatible = "simple-bus";
        ranges = <0x80000000 0x0 0x70000000 0x10000000>;

        pcie-ep at 5f010000 {
                reg = <0x5f010000 0x00010000>,
                      <0x80000000 0x10000000>;
                reg-names = "dbi", "addr_space";
                ...                ^^^^
        };
        ...
};

Add `bus_addr_base` to configure the outbound window address for CPU write.
The BUS fabric generally passes the same address to the PCIe EP controller,
but some BUS fabrics convert the address before sending it to the PCIe EP
controller.

Above diagram, CPU write data to outbound windows address 0x7000_0000,
Bus fabric convert it to 0x8000_0000. ATU should use BUS address
0x8000_0000 as input address and convert to PCI address 0xA000_0000.

Previously, `cpu_addr_fixup()` was used to handle address conversion. Now,
the device tree provides this information.

The both pave the road to eliminate ugle cpu_fixup_addr() callback function.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Changes in v10:
- Remove patch PCI: Add parent_bus_offset to resource_entry because it
is detect by reg-names["config"] and reg-names["space_addr"];

- using Bjorn suggest method
https://lore.kernel.org/linux-pci/20250307233744.440476-1-helgaas at kernel.org/
- other detail change each patches's change log.
- PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup() is not necessary, but
nice clean up, so keep it.

- Still keep use_parent_dt_ranges in case some platform without cpu_addr_fixup,
which use fake address transation at DTB. If no one report warning for
sometime, we can remove it safely. Bjoin, if you think this case is rare,
you can remove it.

- Link to v9: https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com

Changes in v9:
- There are some change in patches, if need drop review-tags, let me known.
- DTS part: https://lore.kernel.org/imx/20250128211559.1582598-2-Frank.Li at nxp.com/T/#u
- Keep "use_parent_dt_ranges" flags because need below combine logic

cpu_addr_fixup  use_parent_dt_ranges
NULL		X			No difference.
!NULL		true			Use device tree parent_address informaion [1]
!NULL		false			Keep use lagency method	[2]

Generally DTS is in different maintainer tree. It need two steps to cleanup
cpu_address_fixup() to avoid function block.
1. Update dts, which reflect the correct bus fabric behavior.
2. set "use_parent_dt_ranges" to true, then remove "cpu_address_fixup()" callback
in platform driver.

Bjorn's comments in https://lore.kernel.org/imx/20250123190900.GA650360 at bhelgaas/

> After all cpu_address_fixup() removed, we can remove use_parent_dt_ranges
> in one clean up patches.
>
>
  ...
>  dw_pcie_rd_other_conf
>  dw_pcie_wr_other_conf
>    dw_pcie_prog_outbound_atu() only called if pp->cfg0_io_shared,
>    after an ECAM map via dw_pcie_other_conf_map_bus() and subsequent
>    successful access; atu.cpu_addr came from pp->io_base, set by
>    dw_pcie_host_init() from pci_pio_to_address(), which I'm pretty
>    sure returns a CPU address.

io_base is parent_bus_address

>    So this still looks wrong to me.  In addition, I think doing the
>    ATU setup in *_map() and restore in *rd/wr_other_conf() is ugly
>    and looks unreliable.

....

>  dw_pcie_pme_turn_off
>    atu.cpu_addr came from pp.msg_res, set by
>    dw_pcie_host_request_msg_tlp_res() to a CPU address at the end of
>    the first MMIO bridge window.  This one also looks wrong to me.

Fixed at this version.

- Link to v8: https://lore.kernel.org/r/20241119-pci_fixup_addr-v8-0-c4bfa5193288 at nxp.com

Changes in v8:
- Add mani's review tages
- use rename use_dt_ranges to use_parent_dt_ranges
- Add dev_warn_once to reminder to fix their dt file and remove
cpu_fixup_addr() callback.
- rename dw_pcie_get_untranslate_addr() to dw_pcie_get_parent_addr()
- Link to v7: https://lore.kernel.org/r/20241029-pci_fixup_addr-v7-0-8310dc24fb7c at nxp.com

Changes in v7:
- fix
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410291546.kvgEWJv7-lkp at intel.com/
- Link to v6: https://lore.kernel.org/r/20241028-pci_fixup_addr-v6-0-ebebcd8fd4ff at nxp.com

Changes in v6:
- merge RC and EP to one thread!
- Link to v5: https://lore.kernel.org/r/20241015-pci_fixup_addr-v5-0-ced556c85270 at nxp.com

Changes in v5:
- update address order in diagram patches.
- remove confused 0x5f00_0000 range
- update patch1's commit message.
- Link to v4: https://lore.kernel.org/r/20241008-pci_fixup_addr-v4-0-25e5200657bc at nxp.com

Changes in v4:
- Improve commit message by add driver source code path.
- Link to v3: https://lore.kernel.org/r/20240930-pci_fixup_addr-v3-0-80ee70352fc7 at nxp.com

Changes in v3:
- see each patch
- Link to v2: https://lore.kernel.org/r/20240926-pci_fixup_addr-v2-0-e4524541edf4 at nxp.com

Changes in v2:
- see each patch
- Link to v1: https://lore.kernel.org/r/20240924-pci_fixup_addr-v1-0-57d14a91ec4f at nxp.com

---
Bjorn Helgaas (3):
      PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup()
      PCI: dwc: Add helper dw_pcie_init_parent_bus_offset()
      PCI: dwc: Use parent_bus_offset

Frank Li (7):
      PCI: dwc: Use resource start as iomap() input in dw_pcie_pme_turn_off()
      PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
      PCI: dwc: Use devicetree 'ranges' property to get rid of cpu_addr_fixup() callback
      PCI: dwc: ep: Add parent_bus_addr for outbound window
      PCI: dwc: Print warning message when cpu_addr_fixup() exists
      PCI: dwc: ep: Ensure proper iteration over outbound map windows
      PCI: imx6: Remove cpu_addr_fixup()

 drivers/pci/controller/dwc/pci-imx6.c             | 18 +----
 drivers/pci/controller/dwc/pcie-designware-ep.c   | 21 ++++--
 drivers/pci/controller/dwc/pcie-designware-host.c | 63 +++++++++++------
 drivers/pci/controller/dwc/pcie-designware.c      | 84 ++++++++++++++++++-----
 drivers/pci/controller/dwc/pcie-designware.h      | 20 +++++-
 5 files changed, 140 insertions(+), 66 deletions(-)
---
base-commit: 5fcc194143ce5918ea0790a16323a844c5ab9499
change-id: 20240924-pci_fixup_addr-a8568f9bbb34

Best regards,
---
Frank Li <Frank.Li at nxp.com>



From Frank.Li at nxp.com  Mon Mar 10 13:16:39 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:39 -0400
Subject: [PATCH v10 01/10] PCI: dwc: Use resource start as iomap() input in
 dw_pcie_pme_turn_off()
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-1-409dafc950d1@nxp.com>

The msg_res region translates writes into PCIe Message TLPs. Previously we
mapped this region using atu.cpu_addr, the input address programmed into
the ATU.

"cpu_addr" is a misnomer because when a bus fabric translates addresses
between the CPU and the ATU, the ATU input address is different from the
CPU address.  A future patch will rename "cpu_addr" and correct the value
to be the ATU input address instead of the CPU physical address.

Map the msg_res region before writing to it using the msg_res resource
start, a CPU physical address.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- use bjorn's suggested commit messaage.

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ffaded8f2df7b..ae3fd2a5dbf85 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -908,7 +908,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	if (ret)
 		return ret;
 
-	mem = ioremap(atu.cpu_addr, pci->region_align);
+	mem = ioremap(pci->pp.msg_res->start, pci->region_align);
 	if (!mem)
 		return -ENOMEM;
 

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:40 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:40 -0400
Subject: [PATCH v10 02/10] PCI: dwc: Rename cpu_addr to parent_bus_addr for
 ATU configuration
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-2-409dafc950d1@nxp.com>

Rename `cpu_addr` to `parent_bus_addr` in the DesignWare ATU configuration.
The ATU translates parent bus addresses to PCI addresses, which are often
the same as CPU addresses but can differ in systems where the bus fabric
translates addresses before passing them to the PCIe controller. This
renaming clarifies the purpose and avoids confusion.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- rename header file's cpu_addr for dw_pcie_prog_inbound_atu() and
dw_pcie_prog_ep_inbound_atu();

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  8 +++---
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++----
 drivers/pci/controller/dwc/pcie-designware.c      | 34 +++++++++++------------
 drivers/pci/controller/dwc/pcie-designware.h      |  7 +++--
 4 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 8e07d432e74f2..80ac2f9e88eb5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -128,7 +128,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 }
 
 static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
-				  dma_addr_t cpu_addr, enum pci_barno bar,
+				  dma_addr_t parent_bus_addr, enum pci_barno bar,
 				  size_t size)
 {
 	int ret;
@@ -146,7 +146,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
 	}
 
 	ret = dw_pcie_prog_ep_inbound_atu(pci, func_no, free_win, type,
-					  cpu_addr, bar, size);
+					  parent_bus_addr, bar, size);
 	if (ret < 0) {
 		dev_err(pci->dev, "Failed to program IB window\n");
 		return ret;
@@ -181,7 +181,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
 		return ret;
 
 	set_bit(free_win, ep->ob_window_map);
-	ep->outbound_addr[free_win] = atu->cpu_addr;
+	ep->outbound_addr[free_win] = atu->parent_bus_addr;
 
 	return 0;
 }
@@ -333,7 +333,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.cpu_addr = addr;
+	atu.parent_bus_addr = addr;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ae3fd2a5dbf85..1206b26bff3f2 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -616,7 +616,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.cpu_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -641,7 +641,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -667,7 +667,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -736,7 +736,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.cpu_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -758,7 +758,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.cpu_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -902,7 +902,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.cpu_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 145e7f579072c..9d0a5f75effcc 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -470,25 +470,25 @@ static inline u32 dw_pcie_enable_ecrc(u32 val)
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu)
 {
-	u64 cpu_addr = atu->cpu_addr;
+	u64 parent_bus_addr = atu->parent_bus_addr;
 	u32 retries, val;
 	u64 limit_addr;
 
 	if (pci->ops && pci->ops->cpu_addr_fixup)
-		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
+		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
 
-	limit_addr = cpu_addr + atu->size - 1;
+	limit_addr = parent_bus_addr + atu->size - 1;
 
-	if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {
 		return -EINVAL;
 	}
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT,
 			      lower_32_bits(limit_addr));
@@ -502,7 +502,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      upper_32_bits(atu->pci_addr));
 
 	val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no);
-	if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&
+	if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
 	    dw_pcie_ver_is_ge(pci, 460A))
 		val |= PCIE_ATU_INCREASE_REGION_SIZE;
 	if (dw_pcie_ver_is(pci, 490A))
@@ -545,13 +545,13 @@ static inline void dw_pcie_writel_atu_ib(struct dw_pcie *pci, u32 index, u32 reg
 }
 
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size)
+			     u64 parent_bus_addr, u64 pci_addr, u64 size)
 {
 	u64 limit_addr = pci_addr + size - 1;
 	u32 retries, val;
 
 	if ((limit_addr & ~pci->region_limit) != (pci_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(pci_addr, pci->region_align) || !size) {
 		return -EINVAL;
 	}
@@ -568,9 +568,9 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 				      upper_32_bits(limit_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	val = type;
 	if (upper_32_bits(limit_addr) > upper_32_bits(pci_addr) &&
@@ -597,18 +597,18 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 }
 
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size)
+				int type, u64 parent_bus_addr, u8 bar, size_t size)
 {
 	u32 retries, val;
 
-	if (!IS_ALIGNED(cpu_addr, pci->region_align) ||
-	    !IS_ALIGNED(cpu_addr, size))
+	if (!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, size))
 		return -EINVAL;
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, type |
 			      PCIE_ATU_FUNC_NUM(func_no));
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 501d9ddfea163..d0d8c622a6e8b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -343,7 +343,7 @@ struct dw_pcie_ob_atu_cfg {
 	u8 func_no;
 	u8 code;
 	u8 routing;
-	u64 cpu_addr;
+	u64 parent_bus_addr;
 	u64 pci_addr;
 	u64 size;
 };
@@ -491,9 +491,10 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu);
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size);
+			     u64 parent_bus_addr, u64 pci_addr, u64 size);
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size);
+				int type, u64 parent_bus_addr,
+				u8 bar, size_t size);
 void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
 void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:41 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:41 -0400
Subject: [PATCH v10 03/10] PCI: dwc: Move cfg0 setup to
 dw_pcie_cfg0_setup()
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-3-409dafc950d1@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

Move pp->cfg0 setup to dw_pcie_cfg0_setup(). No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Change from v9 to v10
v9 means https://lore.kernel.org/linux-pci/20250307233744.440476-1-helgaas at kernel.org/T/#maa0134c1826bffcccab6028c7732a13f7adcec4d

- move dw_pcie_cfg0_setup() ahead of dw_pcie_host_request_msg_tlp_res() to
nice git diff and easy to review.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 40 +++++++++++++++--------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 1206b26bff3f2..c57831902686e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -392,6 +392,29 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
 	return 0;
 }
 
+static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+	if (!res) {
+		dev_err(dev, "Missing \"config\" reg space\n");
+		return -ENODEV;
+	}
+
+	pp->cfg0_size = resource_size(res);
+	pp->cfg0_base = res->start;
+
+	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
+	if (IS_ERR(pp->va_cfg0_base))
+		return PTR_ERR(pp->va_cfg0_base);
+
+	return 0;
+}
+
 static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -423,10 +446,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct resource_entry *win;
 	struct pci_host_bridge *bridge;
-	struct resource *res;
 	int ret;
 
 	raw_spin_lock_init(&pp->lock);
@@ -435,18 +456,9 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (ret)
 		return ret;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
-	if (!res) {
-		dev_err(dev, "Missing \"config\" reg space\n");
-		return -ENODEV;
-	}
-
-	pp->cfg0_size = resource_size(res);
-	pp->cfg0_base = res->start;
-
-	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
-	if (IS_ERR(pp->va_cfg0_base))
-		return PTR_ERR(pp->va_cfg0_base);
+	ret = dw_pcie_cfg0_setup(pp);
+	if (ret)
+		return ret;
 
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:42 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:42 -0400
Subject: [PATCH v10 04/10] PCI: dwc: Add helper
 dw_pcie_init_parent_bus_offset()
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-4-409dafc950d1@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

Set pci->parent_bus_offset based on the parent bus address from the
"config" (Root complex mode) and "addr_space" (Endpoint mode).

.cpu_addr_fixup(cpu_phy_addr). (if implemented) should return the parent
bus address corresponding according to cpu_phy_addr.

Sets pp->parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Add use_parent_dt_ranges to detect some fake bus translation at platform,
which have not .cpu_addr_fixup(). Set use_parent_dt_ranges true explicitly
at platform that have .cpu_addr_fixup() and fixed DTB's range. If not one
report "fake bus translation" for sometime, this flags can be removed
safely.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
v9: https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-4-3c4bb506f665 at nxp.com/

- use help funtion dw_pcie_init_parent_bus_offset() because both EP and RC
use simular logic.
- still use use_parent_dt_ranges to detect fake bus translation for
no .cpu_addr_fixup()'s platfrom incase block exist platform.
---
 drivers/pci/controller/dwc/pcie-designware.c | 47 ++++++++++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 9d0a5f75effcc..70b4d3369158a 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -16,6 +16,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 #include <linux/types.h>
@@ -1105,3 +1106,49 @@ void dw_pcie_setup(struct dw_pcie *pci)
 
 	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
 }
+
+int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
+				   resource_size_t cpu_phy_addr)
+{
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
+	u64 reg_addr, fixup_addr;
+	int index;
+
+	/* Look up reg_name address on parent bus */
+	index = of_property_match_string(np, "reg-names", reg_name);
+
+	if (index < 0) {
+		dev_err(dev, "Missed reg-name: %s, Broken DTB file\n", reg_name);
+		return -EINVAL;
+	}
+
+	of_property_read_reg(np, index, &reg_addr, NULL);
+
+	fixup = pci->ops->cpu_addr_fixup;
+	if (fixup) {
+		fixup_addr = fixup(pci, cpu_phy_addr);
+		if (reg_addr == fixup_addr) {
+			dev_info(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
+				 cpu_phy_addr, reg_name, index,
+				 fixup_addr, fixup);
+		} else {
+			dev_warn_once(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; DT is broken\n",
+				      cpu_phy_addr, reg_name,
+				      index, fixup_addr);
+			reg_addr = fixup_addr;
+		}
+	} else if (!pci->use_parent_dt_ranges) {
+		if (reg_addr != cpu_phy_addr) {
+			dev_warn_once(dev, "Your DTB try to use fake translation, Please check parent's ranges property,");
+			return 0;
+		}
+	}
+
+	pci->parent_bus_offset = cpu_phy_addr - reg_addr;
+	dev_info(dev, "%s parent bus offset is %#010llx\n",
+		 reg_name, pci->parent_bus_offset);
+
+	return 0;
+}
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index d0d8c622a6e8b..5f941eab57110 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -445,6 +445,7 @@ struct dw_pcie {
 	void __iomem		*atu_base;
 	resource_size_t		atu_phys_addr;
 	size_t			atu_size;
+	resource_size_t		parent_bus_offset;
 	u32			num_ib_windows;
 	u32			num_ob_windows;
 	u32			region_align;
@@ -465,6 +466,16 @@ struct dw_pcie {
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
 	bool			suspended;
+	/*
+	 * This flag indicates that the vendor driver uses devicetree 'ranges'
+	 * property to allow iATU to use the Intermediate Address (IA) for
+	 * outbound mapping. Using this flag also avoids the usage of
+	 * 'cpu_addr_fixup' callback implementation in the driver.
+	 *
+	 * If use_parent_dt_ranges is false, warning will print if IA is not
+	 * equal to cpu physical address. Indicate dtb use a fake translation.
+	 */
+	bool			use_parent_dt_ranges;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
@@ -500,6 +511,8 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
+int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
+				   resource_size_t cpu_phy_addr);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:43 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:43 -0400
Subject: [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-5-409dafc950d1@nxp.com>

parent_bus_offset in resource_entry can indicate address information just
ahead of PCIe controller. Most system's bus fabric use 1:1 map between
input and output address. but some hardware like i.MX8QXP doesn't use 1:1
map. See below diagram:

            ???????????                    ??????????????
 ???????    ?         ? IA: 0x8ff8_0000    ?            ?
 ? CPU ??????   ?????????????????????????  ? PCI        ?
 ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
  CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
            ?      ?  ?             ?   ?  ?            ?   PCI Addr
0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
            ?         ?             ?      ?            ?    0
0x7000_0000??????????????????????   ?      ?            ?
            ???????????         ?   ???????? CfgSpace  ???????????????
             BUS Fabric         ?          ?            ?    0
                                ?          ?            ?
                                ???????????? MemSpace  ???????????????
                        IA: 0x8000_0000    ?            ?  0x8000_0000
                                           ??????????????

bus at 5f000000 {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	ranges = <0x80000000 0x0 0x70000000 0x10000000>;

	pcie at 5f010000 {
		compatible = "fsl,imx8q-pcie";
		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
		reg-names = "dbi", "config";
		#address-cells = <3>;
		#size-cells = <2>;
		device_type = "pci";
		bus-range = <0x00 0xff>;
		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
	...
	};
};

Term Intermediate address (IA) here means the address just before PCIe
controller. After ATU use this IA instead CPU address, cpu_addr_fixup() can
be removed.

Use reg-name "config" to detect parent_bus_addr_offset. Suppose the offset
is the same for all kinds of address translation.

Just set parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- call helper dw_pcie_init_parent_bus_offset()

chagne from v8 to v9
- use resoure_entry parent_bus_offset to simple code logic
- add check for use_parent_dt_ranges and cpu_addr_fixup to make sure only
one set.

Change from v7 to v8
- Add dev_warning_once at dw_pcie_iatu_detect() to reminder
cpu_addr_fixup() user to correct their code
- use 'use_parent_dt_ranges' control enable use dt parent bus node ranges.
- rename dw_pcie_get_untranslate_addr to dw_pcie_get_parent_addr().
- of_property_read_reg() already have comments, so needn't add more.
- return actual err code from function

Change from v6 to v7
Add a resource_size_t parent_bus_addr local varible to fix 32bit build
error.
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410291546.kvgEWJv7-lkp at intel.com/

Chagne from v5 to v6
-add comments for of_property_read_reg().

Change from v4 to v5
- remove confused 0x5f00_0000 range in sample dts.
- reorder address at above diagram.

Change from v3 to v4
- none

Change from v2 to v3
- %s/cpu_untranslate_addr/parent_bus_addr/g
- update diagram.
- improve commit message.

Change from v1 to v2
- update because patch1 change get untranslate address method.
- add using_dtbus_info in case break back compatibility for exited platform.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index c57831902686e..eaa6dd4c7edda 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -478,6 +478,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	bridge->ops = &dw_pcie_ops;
 	bridge->child_ops = &dw_child_pcie_ops;
 
+	/*
+	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
+	 * so have to call dw_pcie_init_parent_bus_offset() after init
+	 * pp->io_base.
+	 */
+	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
+	if (ret)
+		return ret;
+
 	if (pp->ops->init) {
 		ret = pp->ops->init(pp);
 		if (ret)

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:44 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:44 -0400
Subject: [PATCH v10 06/10] PCI: dwc: ep: Add parent_bus_addr for outbound
 window
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-6-409dafc950d1@nxp.com>

                   Endpoint
  ?????????????????????????????????????????????????
  ?                             pcie-ep at 5f010000  ?
  ?                             ???????????????????
  ?                             ?   Endpoint     ??
  ?                             ?   PCIe         ??
  ?                             ?   Controller   ??
  ?           bus at 5f000000      ?                ??
  ?           ????????????      ?                ??
  ?           ?          ? Outbound Transfer     ??
  ????????    ?  Bus     ???????? ATU  ??????????????????
  ??     ?    ?  Fabric  ?Bus   ?                ??PCI Addr
  ?? CPU ??????          ?Addr  ?                ??0xA000_0000
  ??     ?CPU ?          ?0x8000_0000            ??
  ????????Addr????????????      ?                ??
  ?       0x7000_0000           ???????????????????
  ?????????????????????????????????????????????????

Use 'ranges' property in DT to configure the iATU outbound window address.
The bus fabric generally passes the same address to the PCIe EP controller,
but some bus fabrics map the address before sending it to the PCIe EP
controller.

Above diagram, CPU write data to outbound windows address 0x7000_0000, Bus
fabric map it to 0x8000_0000. ATU should use bus address 0x8000_0000 as
input address and map to PCI address 0xA000_0000 (dynamic alloc and assign
from pci device driver in host side).

Previously, 'cpu_addr_fixup()' was used to handle address conversion. Now,
the device tree provides this information, preferring a common method.

bus at 5f000000 {
	compatible = "simple-bus";
	ranges = <0x80000000 0x0 0x70000000 0x10000000>;

	pcie-ep at 5f010000 {
		reg = <0x80000000 0x10000000>;
		reg-names ="addr_space";
		...
	};
	...
};

'ranges' in bus at 5f000000 descript how address map from CPU address to bus
address.

Use `of_property_read_reg()` to obtain the bus address and set it to the
ATU correctly, eliminating the need for vendor-specific cpu_addr_fixup().

Use reg-name "addr_space" to detect parent_bus_addr_offset.

Just set parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Change from v9 to v10
- drop mani's review tag because big change.
- call help funciton dw_pcie_init_parent_bus_offset().

Change from v8 to v9
- change bus_addr_base to parent_bus_addr
- fix dw_pcie_find_index() address compare, which cause atu allocate
failure when run many time test.

Change from v7 to v8
- Add Mani's reviewedby tag
- s/convert/map in commit message
- update comments for of_property_read_reg()
- use 'use_parent_dt_ranges'

Change from v6 to v7
- none

Change from v5 to v6
- update diagram
- Add comments for of_property_read_reg()
- Remove unrelated 0x5f00_0000 in commit message

Change from v3 to v4
- change parent_bus_addr to u64 to fix 32bit build error
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410230328.BTHareG1-lkp at intel.com/

Change from v2 to v3
- Add using_dtbus_info to control if use device tree bus ranges
information.
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 80ac2f9e88eb5..d69d76c150d92 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -915,6 +915,14 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->phys_base = res->start;
 	ep->addr_size = resource_size(res);
 
+	/*
+	 * artpec6_pcie_cpu_addr_fixup() use ep->phys_base. so call
+	 * dw_pcie_init_parent_bus_offset after init ep->phys_base.
+	 */
+	ret = dw_pcie_init_parent_bus_offset(pci, "addr_space", ep->phys_base);
+	if (ret)
+		return ret;
+
 	if (ep->ops->pre_init)
 		ep->ops->pre_init(ep);
 

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:45 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:45 -0400
Subject: [PATCH v10 07/10] PCI: dwc: Use parent_bus_offset
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-7-409dafc950d1@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

We know the parent_bus_offset, either computed from a DT reg property (the
offset is the CPU physical addr - the 'config'/'addr_space' address on the
parent bus) or from a .cpu_addr_fixup() (which may have used a host bridge
window offset).

Apply that parent_bus_offset instead of calling .cpu_addr_fixup() again.

This assumes that all intermediate addresses are at the same offset from
the CPU physical addresses.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
v9: https://lore.kernel.org/linux-pci/20250307233744.440476-5-helgaas at kernel.org/#R
- pp -> pci
- add ep side support
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  5 +++--
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 drivers/pci/controller/dwc/pcie-designware.c      |  3 ---
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d69d76c150d92..62bc71ad20719 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -314,7 +314,8 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	ret = dw_pcie_find_index(ep, addr, &atu_index);
+	ret = dw_pcie_find_index(ep, addr - pci->parent_bus_offset,
+				 &atu_index);
 	if (ret < 0)
 		return;
 
@@ -333,7 +334,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.parent_bus_addr = addr;
+	atu.parent_bus_addr = addr - pci->parent_bus_offset;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index eaa6dd4c7edda..a7b7e15d7b0db 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -637,7 +637,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.parent_bus_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base - pci->parent_bus_offset;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -662,7 +662,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -688,7 +688,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -757,7 +757,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.parent_bus_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -779,7 +779,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.parent_bus_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -923,7 +923,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.parent_bus_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 70b4d3369158a..7061a7ec08cb2 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -475,9 +475,6 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 	u32 retries, val;
 	u64 limit_addr;
 
-	if (pci->ops && pci->ops->cpu_addr_fixup)
-		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
-
 	limit_addr = parent_bus_addr + atu->size - 1;
 
 	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:46 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:46 -0400
Subject: [PATCH v10 08/10] PCI: dwc: Print warning message when
 cpu_addr_fixup() exists
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-8-409dafc950d1@nxp.com>

If the parent 'ranges' property in DT correctly describes the address
translation, the cpu_addr_fixup() callback is not needed. Print a warning
message to inform users to correct their DT files.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- new patch
---
 drivers/pci/controller/dwc/pcie-designware.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 7061a7ec08cb2..3ab85dde22ce4 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1125,6 +1125,8 @@ int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
 
 	fixup = pci->ops->cpu_addr_fixup;
 	if (fixup) {
+		dev_warn_once(pci->dev, "cpu_addr_fixup() usage detected. Please fix DT!\n");
+
 		fixup_addr = fixup(pci, cpu_phy_addr);
 		if (reg_addr == fixup_addr) {
 			dev_info(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:47 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:47 -0400
Subject: [PATCH v10 09/10] PCI: dwc: ep: Ensure proper iteration over
 outbound map windows
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-9-409dafc950d1@nxp.com>

Most systems' PCIe outbound map windows have non-zero physical addresses,
but the possibility of encountering zero increased with commit
("PCI: dwc: ep: Add bus_addr_base for outbound window").

'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
some hardware, which trims high address bits through bus fabric before
sending to the PCIe controller.

Replace the iteration logic with 'for_each_set_bit()' to ensure only
allocated map windows are iterated when determining the ATU index from a
given address.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- remove commit hash value

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 62bc71ad20719..e333855633a77 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
 	u32 index;
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	for (index = 0; index < pci->num_ob_windows; index++) {
+	for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
 		if (ep->outbound_addr[index] != addr)
 			continue;
 		*atu_index = index;

-- 
2.34.1



From Frank.Li at nxp.com  Mon Mar 10 13:16:48 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 16:16:48 -0400
Subject: [PATCH v10 10/10] PCI: imx6: Remove cpu_addr_fixup()
In-Reply-To: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
References: <20250310-pci_fixup_addr-v10-0-409dafc950d1@nxp.com>
Message-ID: <20250310-pci_fixup_addr-v10-10-409dafc950d1@nxp.com>

Remove cpu_addr_fixup() because dwc common driver already handle address
translate.

Acked-by: Richard Zhu <hongxing.zhu at nxp.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v10
- none

Change from v8 to v9
- rebase latest linux-next (close enough to v6.14-rc1)

Change from v7 to v8
- add mani and richard's review/ack tag
- use varible 'use_parent_dt_ranges'

Change from v2 to v7
- none
Change from v1 to v2
- set using_dtbus_info true
---
 drivers/pci/controller/dwc/pci-imx6.c | 18 +-----------------
 1 file changed, 1 insertion(+), 17 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 90ace941090f9..d1eb535df73e1 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1217,22 +1217,6 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
 		regulator_disable(imx_pcie->vpcie);
 }
 
-static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
-{
-	struct imx_pcie *imx_pcie = to_imx_pcie(pcie);
-	struct dw_pcie_rp *pp = &pcie->pp;
-	struct resource_entry *entry;
-
-	if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_CPU_ADDR_FIXUP))
-		return cpu_addr;
-
-	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
-	if (!entry)
-		return cpu_addr;
-
-	return cpu_addr - entry->offset;
-}
-
 /*
  * In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
  * register is reserved, so the generic DWC implementation of sending the
@@ -1263,7 +1247,6 @@ static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
 static const struct dw_pcie_ops dw_pcie_ops = {
 	.start_link = imx_pcie_start_link,
 	.stop_link = imx_pcie_stop_link,
-	.cpu_addr_fixup = imx_pcie_cpu_addr_fixup,
 };
 
 static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
@@ -1645,6 +1628,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	pci->use_parent_dt_ranges = true;
 	if (imx_pcie->drvdata->mode == DW_PCIE_EP_TYPE) {
 		ret = imx_add_pcie_ep(imx_pcie, pdev);
 		if (ret < 0)

-- 
2.34.1



From jic23 at kernel.org  Mon Mar 10 13:23:50 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Mon, 10 Mar 2025 20:23:50 +0000
Subject: [PATCH v6 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <06e8f4f84731df9fc5d6f324e74fbd1bf83a81d5.1741610847.git.mazziesaccount@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
	<06e8f4f84731df9fc5d6f324e74fbd1bf83a81d5.1741610847.git.mazziesaccount@gmail.com>
Message-ID: <20250310202350.043d1c34@jic23-huawei>

On Mon, 10 Mar 2025 14:56:35 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help
here as well.  I'd have just fixed these up if applying but seeing as
you seem to be heading for a v7, good to tidy these up in that!


From laurentiumihalcea111 at gmail.com  Mon Mar 10 13:24:44 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 10 Mar 2025 22:24:44 +0200
Subject: [PATCH 4/5] arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
In-Reply-To: <20250307152236.3ayulbjqnu3vn7mf@pengutronix.de>
References: <20250221191909.31874-1-laurentiumihalcea111@gmail.com>
 <20250221191909.31874-5-laurentiumihalcea111@gmail.com>
 <Z7jahtO3bxjkMfnc@lizhi-Precision-Tower-5810>
 <cd6a84cd-ff17-45df-becc-9bfc74522f73@gmail.com>
 <20250227-monumental-whale-of-security-b1c84e-mkl@pengutronix.de>
 <Z8CWsI/DKZtDBkzE@lizhi-Precision-Tower-5810>
 <20250228101952.g6tae3ni5xrhjk3y@pengutronix.de>
 <bfe3c719-f1c5-4ae5-9a40-45ad75cd5855@gmail.com>
 <20250307152236.3ayulbjqnu3vn7mf@pengutronix.de>
Message-ID: <ec38d41d-f2ce-4a98-bb02-d1ae9beb0b3b@gmail.com>



On 3/7/2025 5:22 PM, Marco Felsch wrote:
> On 25-03-04, Laurentiu Mihalcea wrote:
>> On 2/28/2025 12:19 PM, Marco Felsch wrote:
>>> Hi,
>>>
>>> On 25-02-27, Frank Li wrote:
>>>> On Thu, Feb 27, 2025 at 11:57:54AM +0100, Marc Kleine-Budde wrote:
>>>>> On 25.02.2025 16:14:34, Mihalcea Laurentiu wrote:
>>>>>> On 21.02.2025 21:56, Frank Li wrote:
>>>>>>> On Fri, Feb 21, 2025 at 02:19:08PM -0500, Laurentiu Mihalcea wrote:
>>>>>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
>>>>>>>>
>>>>>>>> AIPS5 is actually AIPSTZ5 as it offers some security-related
>>>>>>>> configurations. Since these configurations need to be applied before
>>>>>>>> accessing any of the peripherals on the bus, it's better to make AIPSTZ5
>>>>>>>> be their parent instead of keeping AIPS5 and adding a child node for
>>>>>>>> AIPSTZ5. Also, because of the security configurations, the address space
>>>>>>>> of the bus has to be changed to that of the configuration registers.
>>>>>>> The orginal 0x30c0_0000..0x31200000 include 0x30df0000, why not map only
>>>>>>> config address part in your drivers.
>>>>>>>
>>>>>>> Frank
>>>>>> Any concerns/anything wrong with current approach?
>>>>>>
>>>>>>
>>>>>> I find it a bit awkward to have the whole bus address space
>>>>>> in the DT given that we're only interested in using the access
>>>>>> controller register space.
>>>>>>
>>>>>>
>>>>>> I'm fine with the approach you suggested but I don't see a
>>>>>> reason for using it?
>>>>> Looking at the "AIPS5 Memory Map" (page 34/35 in i.MX 8M Plus
>>>>> Applications Processor Reference Manual, Rev. 3, 08/2024), the
>>>>> AIPS5_Configuration is part of the AIPS5 bus. IMHO the bus is something
>>>>> different than the bus configuration. Why not model it as part of the
>>>>> bus?
>>>>>
>>>>>>>> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>>>> index e0d3b8cba221..a1d9b834d2da 100644
>>>>>>>> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
>>>>>>>> @@ -1399,11 +1399,13 @@ eqos: ethernet at 30bf0000 {
>>>>>>>>  			};
>>>>>>>>  		};
>>>>>>>>
>>>>>>>> -		aips5: bus at 30c00000 {
>>>>>>>> -			compatible = "fsl,aips-bus", "simple-bus";
>>>>>>>> -			reg = <0x30c00000 0x400000>;
>>>>>>>> +		aips5: bus at 30df0000 {
>>>>>                        ^^^^^^^^^^^^
>>>>>>>> +			compatible = "fsl,imx8mp-aipstz", "simple-bus";
>>>>>>>> +			reg = <0x30df0000 0x10000>;
>>>>>>>> +			power-domains = <&pgc_audio>;
>>>>>>>>  			#address-cells = <1>;
>>>>>>>>  			#size-cells = <1>;
>>>>>>>> +			#access-controller-cells = <0>;
>>>>>>>>  			ranges;
>>>>>>>>
>>>>>>>>  			spba-bus at 30c00000 {
>>>>>                         ^^^^^^^^^^^^^^^^^
>>>>>
>>>>> This looks very strange: The aips5 bus starts at 0x30df0000 and has a
>>>>> child bus starting at 0x30c00000?
>>>> @30df0000 should match controller reg's address.
>>>>
>>>> subnode address 0x30c00000,  should be descript in "ranges", which 1:1 map.
>>>>
>>>> So it should be reasonable. another example:
>>>> i2c at 1000 {
>>>>
>>>> 	device at 1c <- which use difference address space.
>>>> }
>>>>
>>>> The similar case also happen at pcie.
>>> I'm not really convinced that pcie and i2c are good examples here. I2C
>>> does have an other addressing scheme by nature and the hotplug-able pcie
>>> is dependeds on the pcie device memory map of course.
>>>
>>> Here we're talking about an access control IP core on a bus which is
>>> static.
>>>
>>> But.. it looks like from DT abstraction it's fine because STM did
>>> something similiar with their st,stm32mp25-rifsc or st,stm32-etzpc
>>> albeit it does look strange and I don't know why we have to limit the
>>> address space since it was already mapped but used by the fsl,aips-bus
>>> driver.
>>>
>>> Regards,
>>>   Marco
>> The address space of the bridge was changed to that of the bridge's
>> configuration space because I think it's very awkward from the
>> software's point of view to have to hardcode the offset and size of
>> the configuration space inside the driver. 
> You mean the access-controller IP core. I could also arguee that it's
> akward to put the bridge access-controller IP core into the middle of
> the bridge address-space instead of placing it at the very beginning of
> the bridge. But this doesn't help here :)
>
> I see what you mean but from DT abstraction POV it seems more reasonable
> to keep it as it is and just adapt the compatible. The current driver
> maps the whole address space too, so I don't see why we need to change
> it if we change it to the aipstz driver. If you see the
> access-controller IP core as part of the bus I don't see any problem and
> would argue that the offset detail needs to be handled within the
> driver.
>
>> I also looked at what STM did with "st,stm32-etzpc" so I thought this
>> would be acceptable from the DT's POV.
>>
>> Regarding why I chose not to model the access controller part as a subnode of the
>> bus:
>>
>> ??? 1) The access controller is part of the bridge itself (not a separate module accessible
>> ? ? via the bridge like it's the case for its children) so I think the current approach
>> ??? should also make sense if we take the hardware into consideration.
> I don't like this approach if you see the controller as part of the
> bridge because the offset could be handled within the bridge driver.
> I also that the register offset needs to be supplied else we can't reuse
> the driver and we don't want to adapt the driver for each SoC.
>
> What came into my mind is the following:
>
> 	spba-bus at 30c00000 {
> 		compatible = "nxp,imx8mp-aiptz-bus", "nxp,aiptz-bus";
> 		reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;
> 		reg-names = "bus", "aipstz";
>
> 		child-nodes {};
> 		child-nodes {};
> 		child-nodes {};
> 	}
>
> This way we can abstract the access-controller register space and the
> whole bus register space and a generic driver could be written just by
> making use two reg fields.


by changing the compatible, we've also effectively changed the programming model.
I don't really see why we need to stick to the old way of configuring the bus node (i.e:
specify the whole address space of the bus as well) when all we really care about is the AC
configuration region?
?
anyhow, I'm not going to insist on this. I think the proposed approach will work just
fine. If there's no other comments on this then I'll just switch to it in V3.


>
>> ??? 2) The access controller configuration also impacts the AP. As such, we needed a way to
>> ??? enforce a dependency between the children of the aips5 bus and the access controller
>> ??? (we could have used the 'access-controllers' property like we did with the DSP but having
>> ??? to do that for all children of the bus is not ideal I'd say.
>>
>> Of course, argument no. 2 is somewhat brittle in the context of i.MX8MP as the reset
>> values of the AC's registers already allow the AP to access said peripherals. Despite this,
>> I think the current approach would be more scalable given that the IP offers some more
>> configuration bits which we might want to toggle. For that to work, we need to make sure
>> the bits are toggled before the AP accesses the peripherals on the bridge.
> Please have a look on my suggestion above.
>
> Regards,
>   Marco
>
>> Note that we don't do this for aips1-aips4 because it's really not needed. If I'm not mistaken,
>> they're not really attached to a PD so we don't need to re-configure them each time the domain
>> is power cycled (which is why we can just do it once from ATF during the boot process)



From jic23 at kernel.org  Mon Mar 10 13:27:38 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Mon, 10 Mar 2025 20:27:38 +0000
Subject: [PATCH v6 00/10] Support ROHM BD79124 ADC
In-Reply-To: <cover.1741610847.git.mazziesaccount@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
Message-ID: <20250310202738.13301548@jic23-huawei>

On Mon, 10 Mar 2025 14:53:50 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> Support ROHM BD79124 ADC.
> 
> This series adds also couple of IIO ADC helper functions for parsing the
> channel information from the device tree. There are also new helpers
> included for iterating and counting firmware child nodes with a specific
> name.
> 
> Series does also convert couple of drivers to use these helpers. The
> rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.
> 
> The gianfar driver under net and the thp7312 under media/i2c are added as
> first users of the newly added "named child node" -helpers.
> 
> There has been some discussion about how useful these ADC helpers are,
> and whether they should support also differential and single ended channel
> configurations. This version does not include support for those - with the
> benefit of reduced complexity and easier to use API.
> 
> NOTE: Patches 4,5,9 and 10 are untested as I lack of relevant HW.
> They have been compile tested only.
This probably wants an update.  Also, 00/10? There are only 8 that I can see.

Jonathan


From ariel.dalessandro at collabora.com  Mon Mar 10 12:59:15 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 10 Mar 2025 16:59:15 -0300
Subject: [PATCH v1 0/6] drm/panfrost: Add support for AARCH64_4K page table format
Message-ID: <20250310195921.157511-1-ariel.dalessandro@collabora.com>

Hi all,

Following the previous RFC [0], this is the first iteration on Panfrost
support for AARCH64_4K page table format.

Currently, Panfrost only supports MMU configuration in LEGACY mode, as
named by Bifrost. This is a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called ARM_MALI_LPAE.

This commit adds support for conditionally enabling AARCH64_4K page
table format in Panfrost, based on the newly added GPU_CONFIG_AARCH64_4K
flag. This way, we can progressively move away from the legacy format
once enough testing has been done on each target.

The patchset only enables the new format on Mediatek MT8188, which has
been tested on a Mediatek Genio 700 EVK (MT8390) board, with an
integrated Mali-G57 MC3 GPU. No regressions were reported in Mesa CI [1]
for the rest of the currently supported platforms.

[0] https://lore.kernel.org/all/20250226183043.140773-1-ariel.dalessandro at collabora.com/
[1] https://gitlab.freedesktop.org/mesa/mesa/

Thanks!

Changes in v1:
* Added "Set IOMMU_CACHE flag" patch.
* Replaced `panfrost_mmu->enable()` function pointer by `cfg` struct
prepared during init time.
* Made mali_lpae/aarch64_4k name more clear.
* Added GPU_CONFIG_AARCH64_4K flag to enable AARCH64_4K page table
  format.
* Enabled AARCH64_4K mode only on mediatek-mt8188.

Ariel D'Alessandro (6):
  drm/panfrost: Set IOMMU_CACHE flag
  drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
  drm/panfrost: Unify panfrost_mmu_enable/disable common code
  drm/panfrost: Add support for AARCH64_4K page table format
  drm/panfrost: Enable AARCH64_4K page table format on mediatek_mt8188
  drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost
    models

 drivers/gpu/drm/panfrost/panfrost_device.h   |  16 ++
 drivers/gpu/drm/panfrost/panfrost_drv.c      |   1 +
 drivers/gpu/drm/panfrost/panfrost_features.h |   3 +
 drivers/gpu/drm/panfrost/panfrost_mmu.c      | 159 ++++++++++++++++---
 drivers/gpu/drm/panfrost/panfrost_regs.h     |  36 +++++
 5 files changed, 189 insertions(+), 26 deletions(-)

-- 
2.47.2



From nathan at kernel.org  Mon Mar 10 13:37:29 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Mon, 10 Mar 2025 21:37:29 +0100
Subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker
 script
In-Reply-To: <202503050230.820w99b6-lkp@intel.com>
References: <20250224125414.2184-1-ceggers@arri.de>
 <202503050230.820w99b6-lkp@intel.com>
Message-ID: <20250310203729.GA26968@ax162>

On Wed, Mar 05, 2025 at 02:49:38AM +0800, kernel test robot wrote:
> Hi Christian,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on soc/for-next]
> [also build test ERROR on linus/master v6.14-rc5 next-20250304]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Eggers/ARM-avoid-that-vectors-are-removed-during-linker-garbage-collection/20250224-210146
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
> patch link:    https://lore.kernel.org/r/20250224125414.2184-1-ceggers%40arri.de
> patch subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker script
> config: arm-milbeaut_m10v_defconfig (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/config)
> compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202503050230.820w99b6-lkp at intel.com/
> 
> All errors (new ones prefixed by >>):
> 
> >> ld.lld: error: section .vectors.bhb.bpiall virtual address range overlaps with .vectors.bhb.loop8
>    >>> .vectors.bhb.bpiall range is [0xFFFF0000, 0xFFFF001F]
>    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
> --
> >> ld.lld: error: section .vectors.bhb.loop8 virtual address range overlaps with .vectors
>    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
>    >>> .vectors range is [0xFFFF0000, 0xFFFF001F]

Looking at ld.lld's code, this error is intentionally ignored for
OVERLAY:

https://github.com/llvm/llvm-project/blob/9f170e6abed4a7b393bb8abbf07ac8d6930aa3b0/lld/ELF/Writer.cpp#L2751-L2761

I have submitted a patch that allows KEEP within OVERLAY to match GNU
ld:

https://github.com/llvm/llvm-project/pull/130661

Once/if that is accepted, we should go back to your v1 with something
like the following diff on top to keep things working for all linkers. I
hope that it won't take long for the ld.lld change to get reviewed and
landed but if this needs to be fixed urgently, this whole diff minus
'|| LLD_VERSION >= 210000' on the init/Kconfig change should work (with
a comment change). I can always send a follow up change to add it back.

Cheers,
Nathan

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 835b5f100e92..f3f6b7a33b79 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -121,7 +121,7 @@ config ARM
 	select HAVE_KERNEL_XZ
 	select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
 	select HAVE_KRETPROBES if HAVE_KPROBES
-	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD)
+	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_CAN_USE_KEEP_IN_OVERLAY)
 	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_NMI
 	select HAVE_OPTPROBES if !THUMB2_KERNEL
diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h
index f2ff79f740ab..14811b4f48ec 100644
--- a/arch/arm/include/asm/vmlinux.lds.h
+++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -34,6 +34,12 @@
 #define NOCROSSREFS
 #endif
 
+#ifdef CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY
+#define OVERLAY_KEEP(x)		KEEP(x)
+#else
+#define OVERLAY_KEEP(x)		x
+#endif
+
 /* Set start/end symbol names to the LMA for the section */
 #define ARM_LMA(sym, section)						\
 	sym##_start = LOADADDR(section);				\
@@ -125,13 +131,13 @@
 	__vectors_lma = .;						\
 	OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {		\
 		.vectors {						\
-			KEEP(*(.vectors))				\
+			OVERLAY_KEEP(*(.vectors))			\
 		}							\
 		.vectors.bhb.loop8 {					\
-			KEEP(*(.vectors.bhb.loop8))			\
+			OVERLAY_KEEP(*(.vectors.bhb.loop8))		\
 		}							\
 		.vectors.bhb.bpiall {					\
-			KEEP(*(.vectors.bhb.bpiall))			\
+			OVERLAY_KEEP(*(.vectors.bhb.bpiall))		\
 		}							\
 	}								\
 	ARM_LMA(__vectors, .vectors);					\
diff --git a/init/Kconfig b/init/Kconfig
index d0d021b3fa3b..fc994f5cd5db 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -129,6 +129,11 @@ config CC_HAS_COUNTED_BY
 	# https://github.com/llvm/llvm-project/pull/112636
 	depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
 
+config LD_CAN_USE_KEEP_IN_OVERLAY
+	# ld.lld prior to 21.0.0 did not support KEEP within an overlay description
+	# https://github.com/llvm/llvm-project/pull/130661
+	def_bool LD_IS_BFD || LLD_VERSION >= 210000
+
 config RUSTC_HAS_COERCE_POINTEE
 	def_bool RUSTC_VERSION >= 108400
 


From vkoul at kernel.org  Mon Mar 10 13:47:31 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 02:17:31 +0530
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
References: <cover.1740762136.git.robin.murphy@arm.com>
 <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
Message-ID: <Z89P461+Y6kQDOCX@vaman>

On 28-02-25, 17:26, Robin Murphy wrote:

> +static u32 d350_get_residue(struct d350_chan *dch)
> +{
> +	u32 res, xsize, xsizehi, hi_new;
> +
> +	hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
> +	do {
> +		xsizehi = hi_new;
> +		xsize = readl_relaxed(dch->base + CH_XSIZE);
> +		hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
> +	} while (xsizehi != hi_new);

This can go forever, lets have some limits to this loop please

> +static int d350_alloc_chan_resources(struct dma_chan *chan)
> +{
> +	struct d350_chan *dch = to_d350_chan(chan);
> +	int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED,
> +			      dev_name(&dch->vc.chan.dev->device), dch);

This is interesting, any reason why the irq is allocated here? Would it
be not better to do that in probe...

-- 
~Vinod


From dmitry.baryshkov at linaro.org  Mon Mar 10 13:50:35 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Mon, 10 Mar 2025 22:50:35 +0200
Subject: [PATCH v8 07/13] drm/bridge: analogix_dp: Add support for
 &drm_dp_aux.wait_hpd_asserted()
In-Reply-To: <20250310104114.2608063-8-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
 <20250310104114.2608063-8-damon.ding@rock-chips.com>
Message-ID: <gnwqnapqlc7bym2nd55oif5lxxiibeme22upepbrgafilpcxxn@py5j7ju4rac3>

On Mon, Mar 10, 2025 at 06:41:08PM +0800, Damon Ding wrote:
> Add analogix_dpaux_wait_hpd_asserted() to help confirm the HPD state
> before doing AUX transfers.
> 
> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
> ---
>  .../drm/bridge/analogix/analogix_dp_core.c    | 21 +++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at linaro.org  Mon Mar 10 13:51:13 2025
From: dmitry.baryshkov at linaro.org (Dmitry Baryshkov)
Date: Mon, 10 Mar 2025 22:51:13 +0200
Subject: [PATCH v8 06/13] drm/bridge: analogix_dp: Add support to get
 panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-7-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com>
 <20250310104114.2608063-7-damon.ding@rock-chips.com>
Message-ID: <mz7qmjokw4b3zk4y2u45ykzgtgqpsu6f53pflhqodyjd6svvvk@7jzggqezbubl>

On Mon, Mar 10, 2025 at 06:41:07PM +0800, Damon Ding wrote:
> The main modification is moving the DP AUX initialization from function
> analogix_dp_bind() to analogix_dp_probe(). In order to get the EDID of
> eDP panel during probing, it is also needed to advance PM operations to
> ensure that eDP controller and phy are prepared for AUX transmission.
> 
> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
> 
> ---
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

-- 
With best wishes
Dmitry


From mhklinux at outlook.com  Mon Mar 10 14:01:42 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 21:01:42 +0000
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
Message-ID: <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
> 
> On Fri, Mar 7, 2025, at 23:02, Roman Kisel wrote:
> > @@ -5,18 +5,20 @@ menu "Microsoft Hyper-V guest support"
> >  config HYPERV
> >  	tristate "Microsoft Hyper-V client drivers"
> >  	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
> > -		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
> > +		|| (ARM64 && !CPU_BIG_ENDIAN)
> > +	depends on (ACPI || HYPERV_VTL_MODE)
> >  	select PARAVIRT
> >  	select X86_HV_CALLBACK_VECTOR if X86
> > -	select OF_EARLY_FLATTREE if OF
> >  	help
> >  	  Select this option to run Linux as a Hyper-V client operating
> >  	  system.
> >
> >  config HYPERV_VTL_MODE
> >  	bool "Enable Linux to boot in VTL context"
> > -	depends on X86_64 && HYPERV
> > +	depends on (X86_64 || ARM64)
> >  	depends on SMP
> > +	select OF_EARLY_FLATTREE
> > +	select OF
> >  	default n
> >  	help
> 
> Having the dependency below the top-level Kconfig entry feels a little
> counterintuitive. You could flip that back as it was before by doing
> 
>       select HYPERV_VTL_MODE if !ACPI
>       depends on ACPI || SMP
> 
> in the HYPERV option, leaving the dependency on HYPERV in
> HYPERV_VTL_MODE.

I would argue that we don't ever want to implicitly select
HYPERV_VTL_MODE because of some other config setting or
lack thereof.  VTL mode is enough of a special case that it should
only be explicitly selected. If someone omits ACPI, then HYPERV
should not be selectable unless HYPERV_VTL_MODE is explicitly
selected.

The last line of the comment for HYPERV_VTL_MODE says
"A kernel built with this option must run at VTL2, and will not run
as a normal guest."  In other words, don't choose this unless you
100% know that VTL2 is what you want.

Michael

> 
> Is OF_EARLY_FLATTREE actually needed on x86?
> 
>       Arnd


From vkoul at kernel.org  Mon Mar 10 14:06:32 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 02:36:32 +0530
Subject: [PATCH] dt-bindings: dma: fsl-mxs-dma: Add compatible string
 for i.MX8 chips
In-Reply-To: <20250307215100.3257649-1-Frank.Li@nxp.com>
References: <20250307215100.3257649-1-Frank.Li@nxp.com>
Message-ID: <174164079235.489187.5863262843040562459.b4-ty@kernel.org>


On Fri, 07 Mar 2025 16:50:59 -0500, Frank Li wrote:
> Add compatible string for all i.MX8 chips, which is backward compatible
> with i.MX28. Set it to fall back to "fsl,imx28-dma-apbh".
> 
> 

Applied, thanks!

[1/1] dt-bindings: dma: fsl-mxs-dma: Add compatible string for i.MX8 chips
      commit: 964c032d1d5d1d896746b361416b84cef078dba5

Best regards,
-- 
~Vinod




From vkoul at kernel.org  Mon Mar 10 14:06:50 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 02:36:50 +0530
Subject: [PATCH] dmaengine: ti: k3-udma: Enable second resource range
 for BCDMA and PKTDMA
In-Reply-To: <20250205121805.316792-1-s-vadapalli@ti.com>
References: <20250205121805.316792-1-s-vadapalli@ti.com>
Message-ID: <174164081079.489187.11258465770123332216.b4-ty@kernel.org>


On Wed, 05 Feb 2025 17:48:01 +0530, Siddharth Vadapalli wrote:
> The SoC DMA resources for UDMA, BCDMA and PKTDMA can be described via a
> combination of up to two resource ranges. The first resource range handles
> the default partitioning wherein all resources belonging to that range are
> allocated to a single entity and form a continuous range. For use-cases
> where the resources are shared across multiple entities and require to be
> described via discontinuous ranges, a second resource range is required.
> 
> [...]

Applied, thanks!

[1/1] dmaengine: ti: k3-udma: Enable second resource range for BCDMA and PKTDMA
      commit: 566beb347eded7a860511164a7a163bc882dc4d0

Best regards,
-- 
~Vinod




From kw at linux.com  Mon Mar 10 14:07:46 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 11 Mar 2025 06:07:46 +0900
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250305132018.2260771-1-s-vadapalli@ti.com>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
Message-ID: <20250310210746.GA2377483@rocinante>

Hello,

> Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> already reuse this macro since it accurately represents the link-state
> field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.

Can you confirm for me that the following use the correct macro?

  333-static const struct j721e_pcie_data j721e_pcie_rc_data = {
  337:	.linkdown_irq_regfield = LINK_DOWN,
  
  341-static const struct j721e_pcie_data j721e_pcie_ep_data = {
  343:	.linkdown_irq_regfield = LINK_DOWN,
  
  347-static const struct j721e_pcie_data j7200_pcie_rc_data = {
  350:	.linkdown_irq_regfield = J7200_LINK_DOWN,
  
  362-static const struct j721e_pcie_data am64_pcie_rc_data = {
  364:	.linkdown_irq_regfield = J7200_LINK_DOWN,
  
  369-static const struct j721e_pcie_data am64_pcie_ep_data = {
  371:	.linkdown_irq_regfield = J7200_LINK_DOWN,
  
  375-static const struct j721e_pcie_data j784s4_pcie_rc_data = {
  379:	.linkdown_irq_regfield = LINK_DOWN,
  
  383-static const struct j721e_pcie_data j784s4_pcie_ep_data = {
  385:	.linkdown_irq_regfield = LINK_DOWN,
  
  389-static const struct j721e_pcie_data j722s_pcie_rc_data = {
  391:	.linkdown_irq_regfield = J7200_LINK_DOWN,

I am asking as some use LINK_DOWN, so I wanted to make sure.

Tht said, the following has no .linkdown_irq_regfield property set:

  355-static const struct j721e_pcie_data j7200_pcie_ep_data = {
  356-	.mode = PCI_MODE_EP,
  357-	.quirk_detect_quiet_flag = true,
  358-	.quirk_disable_flr = true,
  359-	.max_lanes = 2,
  360-};

Would this be a problem?  Or is this as expected?

Thank you!

	Krzysztof


From Frank.li at nxp.com  Mon Mar 10 14:08:49 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 17:08:49 -0400
Subject: [PATCH v15 00/15] PCI: EP: Add RC-to-EP doorbell with platform
 MSI controller
In-Reply-To: <87senwd3mo.ffs@tglx>
References: <20250211-ep-msi-v15-0-bcacc1f2b1a9@nxp.com>
 <Z7eKBsxrmthtElpz@lizhi-Precision-Tower-5810>
 <86ldtpot6m.wl-maz@kernel.org>
 <87senwd3mo.ffs@tglx>
Message-ID: <Z89U4Sa1SqBPLNrm@lizhi-Precision-Tower-5810>

On Sat, Mar 01, 2025 at 07:09:35PM +0100, Thomas Gleixner wrote:
> On Sat, Mar 01 2025 at 12:02, Marc Zyngier wrote:
> > - This IMMUTABLE thing serves no purpose, because you don't randomly
> >   plug this end-point block on any MSI controller. They come as part
> >   of an SoC.
>
> Yes and no. The problem is that the EP implementation is meant to be a
> generic library and while GIC-ITS guarantees immutability of the
> address/data pair after setup, there are architectures (x86, loongson,
> riscv) where the base MSI controller does not and immutability is only
> achieved when interrupt remapping is enabled. The latter can be disabled
> at boot-time and then the EP implementation becomes a lottery across
> affinity changes.
>
> That was my concern about this library implementation and that's why I
> asked for a mechanism to ensure that the underlying irqdomain provides a
> immutable address/data pair.
>
> So it does not matter for GIC-ITS, but in the larger picture it matters.

Marc:
	Do you satisfy Thomans's anwser? So I can respin this series.

Frank

>
> Thanks,
>
>         tglx


From ryan.roberts at arm.com  Mon Mar 10 14:10:20 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 10 Mar 2025 21:10:20 +0000
Subject: [PATCH] arm64/kernel: Always use level 2 or higher for early
 mappings
In-Reply-To: <20250310183011.2591600-2-ardb+git@google.com>
References: <20250310183011.2591600-2-ardb+git@google.com>
Message-ID: <948cccde-6b00-4542-9882-47d24f3d0d78@arm.com>

On 10/03/2025 18:30, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb at kernel.org>
> 
> The page table population code in map_range() uses a recursive algorithm
> to create the early mappings of the kernel, the DTB and the ID mapped
> text and data pages, and this fails to take into account that the way
> these page tables may be constructed is not precisely the same at each
> level. In particular, block mappings are not permitted at each level,
> and the code as it exists today might inadvertently create such a
> forbidden block mapping if it were used to map a region of the
> appropriate size and alignment.
> 
> This never happens in practice, given the limited size of the assets
> being mapped by the early boot code. Nonetheless, it would be better if
> this code would behave correctly in all circumstances.

ahha, yes I had a hunch we would be able to guarantee not to hit this condition
in practice. Thanks for the explanation.

> 
> So only permit block mappings at level 2, and page mappings at level 3,
> for any page size, and use table mappings exclusively at all other
> levels. This change should have no impact in practice, but it makes the
> code more robust.
> 
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>

This looks good to me, and it's D128 ready!

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

> ---
>  arch/arm64/kernel/pi/map_range.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..025bb9f0aa0b 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -40,17 +40,10 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	/* Advance tbl to the entry that covers start */
>  	tbl += (start >> (lshift + PAGE_SHIFT)) % PTRS_PER_PTE;
>  
> -	/*
> -	 * Set the right block/page bits for this level unless we are
> -	 * clearing the mapping
> -	 */
> -	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> -
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -		if (level < 3 && (start | next | pa) & lmask) {
> +		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
>  			/*
>  			 * This chunk needs a finer grained mapping. Create a
>  			 * table mapping if necessary and recurse.
> @@ -64,6 +57,14 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  				  (pte_t *)(__pte_to_phys(*tbl) + va_offset),
>  				  may_use_cont, va_offset);
>  		} else {
> +			/*
> +			 * Set the right block/page bits for this level unless
> +			 * we are clearing the mapping
> +			 */
> +			if (protval)
> +				protval |= (level == 2) ? PMD_TYPE_SECT
> +							: PTE_TYPE_PAGE;
> +
>  			/*
>  			 * Start a contiguous range if start and pa are
>  			 * suitably aligned



From robdclark at gmail.com  Mon Mar 10 14:12:40 2025
From: robdclark at gmail.com (Rob Clark)
Date: Mon, 10 Mar 2025 14:12:40 -0700
Subject: [PATCH] drm: Add UAPI for the Asahi driver
In-Reply-To: <20250310-agx-uapi-v1-1-86c80905004e@rosenzweig.io>
References: <20250310-agx-uapi-v1-1-86c80905004e@rosenzweig.io>
Message-ID: <CAF6AEGukrBzwwdDWX5jUXDKqj7+kn7LBRy6NocE4=bw1D9WjcQ@mail.gmail.com>

On Mon, Mar 10, 2025 at 7:14?AM Alyssa Rosenzweig <alyssa at rosenzweig.io> wrote:
>
> This adds the UAPI for the Asahi driver targeting the GPU in the Apple
> M1 and M2 series systems on chip. The UAPI design is based on other
> modern Vulkan-capable drivers, including Xe and Panthor. Memory
> management is based on explicit VM management. Synchronization is
> exclusively explicit sync.
>
> This UAPI is validated against our open source Mesa stack, which is
> fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
> Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
> VM_BIND mechanism.
>
> This patch adds the standalone UAPI header. It is implemented by an open
> source DRM driver written in Rust. We fully intend to upstream this
> driver when possible. However, as a production graphics driver, it
> depends on a significant number of Rust abstractions that will take a
> long time to upstream. In the mean time, our userspace is upstream in
> Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
> yet reviewed and merged in the upstream kernel. Although we ship a
> patched Mesa in Fedora Asahi Remix, any containers shipping upstream
> Mesa builds are broken for our users, including upstream Flatpak and
> Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
> and virglrenderer, which complicates bisects.
>
> The intention in sending out this patch is for this UAPI to be
> thoroughly reviewed. Once we as the DRM community are satisfied with the
> UAPI, this header lands signifying that the UAPI is stable and must only
> be evolved in backwards-compatible ways; it will be the UAPI implemented
> in the DRM driver that eventually lands upstream. That promise lets us
> enable upstream Mesa, solving all these issues while the upstream Rust
> abstractions are developed.
>
> https://github.com/alyssarosenzweig/linux/commits/agx/uapi/ contains the
> DRM driver implementing this proposed UAPI.
>
> https://github.com/alyssarosenzweig/mesa/tree/agx-uapi contains the Mesa
> patches to implement this proposed UAPI.
>
> That Linux and Mesa branch together give a complete graphics/compute
> stack on top of this UAPI.
>
> Co-developed-by: Asahi Lina <lina at asahilina.net>
> Signed-off-by: Asahi Lina <lina at asahilina.net>
> Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> ---
>  Documentation/gpu/driver-uapi.rst |    5 +
>  MAINTAINERS                       |    1 +
>  include/uapi/drm/asahi_drm.h      | 1153 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 1159 insertions(+)
>
> diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
> index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
> --- a/Documentation/gpu/driver-uapi.rst
> +++ b/Documentation/gpu/driver-uapi.rst
> @@ -27,3 +27,8 @@ drm/xe uAPI
>  ===========
>
>  .. kernel-doc:: include/uapi/drm/xe_drm.h
> +
> +drm/asahi uAPI
> +================
> +
> +.. kernel-doc:: include/uapi/drm/asahi_drm.h
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2256,6 +2256,7 @@ F:        drivers/watchdog/apple_wdt.c
>  F:     include/dt-bindings/interrupt-controller/apple-aic.h
>  F:     include/dt-bindings/pinctrl/apple.h
>  F:     include/linux/soc/apple/*
> +F:     include/uapi/drm/asahi_drm.h
>
>  ARM/ARTPEC MACHINE SUPPORT
>  M:     Jesper Nilsson <jesper.nilsson at axis.com>
> diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..1491ddbf807d1a26d7d5c5df78a7a988787d15c4
> --- /dev/null
> +++ b/include/uapi/drm/asahi_drm.h
> @@ -0,0 +1,1153 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright (C) The Asahi Linux Contributors
> + * Copyright (C) 2018-2023 Collabora Ltd.
> + * Copyright (C) 2014-2018 Broadcom
> + */
> +#ifndef _ASAHI_DRM_H_
> +#define _ASAHI_DRM_H_
> +
> +#include "drm.h"
> +
> +#if defined(__cplusplus)
> +extern "C" {
> +#endif
> +
> +/**
> + * DOC: Introduction to the Asahi UAPI
> + *
> + * This documentation describes the Asahi IOCTLs.
> + *
> + * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
> + * from Panthor):
> + *
> + * - Structures must be aligned on 64-bit/8-byte. If the object is not
> + *   naturally aligned, a padding field must be added.
> + * - Fields must be explicitly aligned to their natural type alignment with
> + *   pad[0..N] fields.
> + * - All padding fields will be checked by the driver to make sure they are
> + *   zeroed.
> + * - Flags can be added, but not removed/replaced.
> + * - New fields can be added to the main structures (the structures
> + *   directly passed to the ioctl). Those fields can be added at the end of
> + *   the structure, or replace existing padding fields. Any new field being
> + *   added must preserve the behavior that existed before those fields were
> + *   added when a value of zero is passed.
> + * - New fields can be added to indirect objects (objects pointed by the
> + *   main structure), iff those objects are passed a size to reflect the
> + *   size known by the userspace driver (see
> + *   drm_asahi_command::cmd_buffer_size).
> + * - If the kernel driver is too old to know some fields, those will be
> + *   ignored if zero, and otherwise rejected (and so will be zero on output).
> + * - If userspace is too old to know some fields, those will be zeroed
> + *   (input) before the structure is parsed by the kernel driver.
> + * - Each new flag/field addition must come with a driver version update so
> + *   the userspace driver doesn't have to trial and error to know which
> + *   flags are supported.
> + * - Structures should not contain unions, as this would defeat the
> + *   extensibility of such structures.
> + * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
> + *   at the end of the drm_asahi_ioctl_id enum.
> + */
> +
> +/**
> + * enum drm_asahi_ioctl_id - IOCTL IDs
> + *
> + * Place new ioctls at the end, don't re-order, don't replace or remove entries.
> + *
> + * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
> + * definitions instead.
> + */
> +enum drm_asahi_ioctl_id {
> +       /** @DRM_ASAHI_GET_PARAMS: Query device properties. */
> +       DRM_ASAHI_GET_PARAMS = 0,
> +
> +       /** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
> +       DRM_ASAHI_VM_CREATE,
> +
> +       /** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
> +       DRM_ASAHI_VM_DESTROY,
> +
> +       /** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
> +       DRM_ASAHI_GEM_CREATE,
> +
> +       /**
> +        * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
> +        * given GEM handle.
> +        */
> +       DRM_ASAHI_GEM_MMAP_OFFSET,
> +
> +       /** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
> +       DRM_ASAHI_GEM_BIND,
> +
> +       /** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
> +       DRM_ASAHI_QUEUE_CREATE,
> +
> +       /** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
> +       DRM_ASAHI_QUEUE_DESTROY,
> +
> +       /** @DRM_ASAHI_SUBMIT: Submit an array of commands to a queue. */
> +       DRM_ASAHI_SUBMIT,
> +
> +       /** @DRM_ASAHI_GET_TIME: Query device time. */
> +       DRM_ASAHI_GET_TIME,
> +
> +       /** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
> +       DRM_ASAHI_GEM_BIND_OBJECT,
> +};
> +
> +#define DRM_ASAHI_MAX_CLUSTERS 64
> +
> +/**
> + * struct drm_asahi_params_global - Global parameters.
> + *
> + * This struct may be queried by drm_asahi_get_params.
> + */
> +struct drm_asahi_params_global {
> +       /** @features: Feature bits from drm_asahi_feature */
> +       __u64 features;
> +
> +       /** @gpu_generation: GPU generation, e.g. 13 for G13G */
> +       __u32 gpu_generation;
> +
> +       /** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
> +       __u32 gpu_variant;
> +
> +       /**
> +        * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
> +        * 0x21 for 'C1'
> +        */
> +       __u32 gpu_revision;
> +
> +       /** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
> +       __u32 chip_id;
> +
> +       /** @num_dies: Number of dies in the SoC */
> +       __u32 num_dies;
> +
> +       /** @num_clusters_total: Number of GPU clusters (across all dies) */
> +       __u32 num_clusters_total;
> +
> +       /**
> +        * @num_cores_per_cluster: Number of logical cores per cluster
> +        * (including inactive/nonexistent)
> +        */
> +       __u32 num_cores_per_cluster;
> +
> +       /** @num_frags_per_cluster: Number of frags per cluster */
> +       __u32 num_frags_per_cluster;
> +
> +       /** @num_gps_per_cluster: Number of GPs per cluster */
> +       __u32 num_gps_per_cluster;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +
> +       /** @core_masks: Bitmask of present/enabled cores per cluster */
> +       __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
> +
> +       /** @timer_frequency_hz: Clock frequency for timestamps */
> +       __u64 timer_frequency_hz;
> +
> +       /** @min_frequency_khz: Minimum GPU core clock frequency */
> +       __u32 min_frequency_khz;
> +
> +       /** @max_frequency_khz: Maximum GPU core clock frequency */
> +       __u32 max_frequency_khz;
> +
> +       /** @max_power_mw: Maximum GPU power consumption */
> +       __u32 max_power_mw;
> +
> +       /** @vm_page_size: GPU VM page size */
> +       __u32 vm_page_size;
> +
> +       /** @vm_user_start: VM user range start VMA */
> +       __u64 vm_user_start;
> +
> +       /** @vm_user_end: VM user range end VMA */
> +       __u64 vm_user_end;
> +
> +       /**
> +        * @vm_kernel_min_size: Minimum kernel VMA window size within user
> +        * range
> +        */
> +       __u64 vm_kernel_min_size;
> +
> +       /**
> +        * @max_commands_per_submission: Maximum number of supported commands
> +        * per submission
> +        */
> +       __u32 max_commands_per_submission;
> +
> +       /**
> +        * @max_attachments: Maximum number of drm_asahi_attachment's per
> +        * command
> +        */
> +       __u32 max_attachments;
> +
> +       /**
> +        * @firmware_version: GPU firmware version, as 4 integers
> +        */
> +       __u32 firmware_version[4];
> +
> +       /**
> +        * @user_timestamp_frequency_hz: Timebase frequency for user timestamps
> +        */
> +       __u64 user_timestamp_frequency_hz;
> +};
> +
> +/**
> + * enum drm_asahi_feature - Feature bits
> + *
> + * This covers only features that userspace cannot infer from the architecture
> + * version. Most features don't need to be here.
> + */
> +enum drm_asahi_feature {
> +       /**
> +        * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
> +        * loads of unmapped memory will return zero. Shader stores to unmapped
> +        * memory will be silently discarded. Note that only shader load/store
> +        * is affected. Other hardware units are not affected, notably including
> +        * texture sampling.
> +        */
> +       DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
> +};
> +
> +/**
> + * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
> + */
> +struct drm_asahi_get_params {
> +       /** @param_group: Parameter group to fetch (MBZ) */
> +       __u32 param_group;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +
> +       /** @pointer: User pointer to write parameter struct */
> +       __u64 pointer;
> +
> +       /** @size: Size of user buffer, max size supported on return */
> +       __u64 size;
> +};
> +
> +/**
> + * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
> + */
> +struct drm_asahi_vm_create {
> +       /** @kernel_start: Start of the kernel-reserved address range */
> +       __u64 kernel_start;
> +
> +       /** @kernel_end: End of the kernel-reserved address range */
> +       __u64 kernel_end;
> +
> +       /** @vm_id: Returned VM ID */
> +       __u32 vm_id;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
> + */
> +struct drm_asahi_vm_destroy {
> +       /** @vm_id: VM ID to be destroyed */
> +       __u32 vm_id;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * define ASAHI_GEM_WRITEBACK - BO should be CPU-mapped as writeback.
> + *
> + * Map as writeback instead of write-combine. This optimizes for CPU reads.
> + */
> +#define ASAHI_GEM_WRITEBACK (1L << 0)
> +
> +/**
> + * define ASAHI_GEM_VM_PRIVATE - BO is private to this GPU VM (no exports)
> + */
> +#define ASAHI_GEM_VM_PRIVATE (1L << 1)
> +
> +/**
> + * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
> + */
> +struct drm_asahi_gem_create {
> +       /** @size: Size of the BO */
> +       __u64 size;
> +
> +       /** @flags: Combination of ASAHI_GEM_* flags. */
> +       __u32 flags;
> +
> +       /**
> +        * @vm_id: VM ID to assign to the BO, if ASAHI_GEM_VM_PRIVATE is set
> +        */
> +       __u32 vm_id;
> +
> +       /** @handle: Returned GEM handle for the BO */
> +       __u32 handle;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_gem_mmap_offset - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
> + */
> +struct drm_asahi_gem_mmap_offset {
> +       /** @handle: Handle for the object being mapped. */
> +       __u32 handle;
> +
> +       /** @flags: Must be zero */
> +       __u32 flags;
> +
> +       /** @offset: The fake offset to use for subsequent mmap call */
> +       __u64 offset;
> +};
> +
> +/**
> + * enum drm_asahi_bind_op - Bind operation
> + */
> +enum drm_asahi_bind_op {
> +       /** @ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
> +       ASAHI_BIND_OP_BIND = 0,
> +
> +       /** @ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
> +       ASAHI_BIND_OP_UNBIND = 1,
> +
> +       /** @ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */
> +       ASAHI_BIND_OP_UNBIND_ALL = 2,
> +};
> +
> +/**
> + * define ASAHI_BIND_READ - Map BO with GPU read permission
> + */
> +#define ASAHI_BIND_READ                (1L << 0)
> +
> +/**
> + * define ASAHI_BIND_WRITE - Map BO with GPU write permission
> + */
> +#define ASAHI_BIND_WRITE       (1L << 1)
> +
> +/**
> + * define ASAHI_BIND_SINGLE_PAGE - Map a single page of the BO repeatedly across
> + * the VA range.
> + *
> + * This is useful to fill a VA range with scratch pages or zero pages. It is
> + * intended as a mechanism to accelerate sparse.
> + */
> +#define ASAHI_BIND_SINGLE_PAGE (1L << 2)
> +
> +/**
> + * struct drm_asahi_gem_bind - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_BIND
> + */
> +struct drm_asahi_gem_bind {
> +       /** @op: Bind operation (enum drm_asahi_bind_op) */
> +       __u32 op;
> +
> +       /** @flags: One or more of ASAHI_BIND_* (BIND only) */
> +       __u32 flags;
> +
> +       /** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
> +       __u32 handle;
> +
> +       /** @vm_id: The ID of the VM to operate on */
> +       __u32 vm_id;
> +
> +       /** @offset: Offset into the object (BIND only) */
> +       __u64 offset;
> +
> +       /**
> +        * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
> +        */
> +       __u64 range;
> +
> +       /** @addr: Address to bind to (BIND or UNBIND only) */
> +       __u64 addr;
> +};

No in/out syncobj/fences?  This seems to diverge from xe/nouveau/panthor..

> +
> +/**
> + * enum drm_asahi_bind_object_op - Special object bind operation
> + */
> +enum drm_asahi_bind_object_op {
> +       /** @ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
> +       ASAHI_BIND_OBJECT_OP_BIND = 0,
> +
> +       /** @ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
> +       ASAHI_BIND_OBJECT_OP_UNBIND = 1,
> +};
> +
> +/**
> + * define ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS - Map a BO as a timestamp buffer
> + */
> +#define ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS     (1L << 0)
> +
> +/**
> + * struct drm_asahi_gem_bind_object - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
> + */
> +struct drm_asahi_gem_bind_object {
> +       /** @op: Bind operation (enum drm_asahi_bind_object_op) */
> +       __u32 op;
> +
> +       /** @flags: One or more of ASAHI_BIND_OBJECT_* */
> +       __u32 flags;
> +
> +       /** @handle: GEM object to bind/unbind (BIND) */
> +       __u32 handle;
> +
> +       /** @vm_id: The ID of the VM to operate on (MBZ currently) */
> +       __u32 vm_id;
> +
> +       /** @offset: Offset into the object (BIND only) */
> +       __u64 offset;
> +
> +       /** @range: Number of bytes to bind/unbind (BIND only) */
> +       __u64 range;
> +
> +       /** @object_handle: Object handle (out for BIND, in for UNBIND) */
> +       __u32 object_handle;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * enum drm_asahi_cmd_type - Command type
> + */
> +enum drm_asahi_cmd_type {
> +       /**
> +        * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
> +        * subqueue. Combined vertex and fragment operation.
> +        */
> +       DRM_ASAHI_CMD_RENDER = 0,
> +
> +       /** @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue. */
> +       DRM_ASAHI_CMD_COMPUTE = 1,
> +};
> +
> +/**
> + * enum drm_asahi_queue_cap - Queue capabilities
> + */
> +enum drm_asahi_queue_cap {
> +       /** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
> +       DRM_ASAHI_QUEUE_CAP_RENDER      = (1UL << DRM_ASAHI_CMD_RENDER),
> +
> +       /** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
> +       DRM_ASAHI_QUEUE_CAP_COMPUTE     = (1UL << DRM_ASAHI_CMD_COMPUTE),
> +};
> +
> +/**
> + * struct drm_asahi_queue_create - Arguments passed to
> + * DRM_IOCTL_ASAHI_QUEUE_CREATE
> + */
> +struct drm_asahi_queue_create {
> +       /** @flags: MBZ */
> +       __u32 flags;
> +
> +       /** @vm_id: The ID of the VM this queue is bound to */
> +       __u32 vm_id;
> +
> +       /** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
> +       __u32 queue_caps;
> +
> +       /** @priority: Queue priority, 0-3 */
> +       __u32 priority;
> +
> +       /** @queue_id: The returned queue ID */
> +       __u32 queue_id;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_queue_destroy - Arguments passed to
> + * DRM_IOCTL_ASAHI_QUEUE_DESTROY
> + */
> +struct drm_asahi_queue_destroy {
> +       /** @queue_id: The queue ID to be destroyed */
> +       __u32 queue_id;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +};
> +
> +/**
> + * enum drm_asahi_sync_type - Sync item type
> + */
> +enum drm_asahi_sync_type {
> +       /** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
> +       DRM_ASAHI_SYNC_SYNCOBJ = 0,
> +
> +       /** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
> +       DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
> +};

IMHO it would still be worthwhile to also support fence fd's, since it
would avoid a couple extra ioctls to convert btwn fence fds and
syncobj for virtgpu native context..

BR,
-R

> +
> +/**
> + * struct drm_asahi_sync - Sync item
> + */
> +struct drm_asahi_sync {
> +       /** @sync_type: One of drm_asahi_sync_type */
> +       __u32 sync_type;
> +
> +       /** @handle: The sync object handle */
> +       __u32 handle;
> +
> +       /** @timeline_value: Timeline value for timeline sync objects */
> +       __u64 timeline_value;
> +};
> +
> +/**
> + * enum drm_asahi_subqueue - Subqueue within a queue
> + */
> +enum drm_asahi_subqueue {
> +       /** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */
> +       DRM_ASAHI_SUBQUEUE_RENDER = 0,
> +
> +       /** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */
> +       DRM_ASAHI_SUBQUEUE_COMPUTE = 1,
> +
> +       /**
> +        * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2
> +        * for struct alignment
> +        */
> +       DRM_ASAHI_SUBQUEUE_COUNT = 2,
> +};
> +
> +/**
> + * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
> + *
> + * This special value may be passed in to drm_asahi_command::barriers[] to
> + * indicate that the respective subqueue should not wait on any previous work.
> + */
> +#define DRM_ASAHI_BARRIER_NONE ~(0U)
> +
> +/**
> + * struct drm_asahi_command - Top level command structure
> + */
> +struct drm_asahi_command {
> +       /** @cmd_type: One of drm_asahi_cmd_type */
> +       __u32 cmd_type;
> +
> +       /** @flags: Flags for command submission */
> +       __u32 flags;
> +
> +       /** @cmd_buffer: Pointer to the appropriate command buffer structure */
> +       __u64 cmd_buffer;
> +
> +       /** @cmd_buffer_size: Size of the command buffer structure */
> +       __u64 cmd_buffer_size;
> +
> +       /** @barriers: Array of command indices per subqueue to wait on */
> +       __u32 barriers[DRM_ASAHI_SUBQUEUE_COUNT];
> +};
> +
> +/**
> + * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
> + */
> +struct drm_asahi_submit {
> +       /**
> +        * @in_syncs: An optional array of drm_asahi_sync to wait on before
> +        * starting this job.
> +        */
> +       __u64 in_syncs;
> +
> +       /**
> +        * @out_syncs: An optional array of drm_asahi_sync objects to signal
> +        * upon completion.
> +        */
> +       __u64 out_syncs;
> +
> +       /**
> +        * @commands: Pointer to the drm_asahi_command array of commands to
> +        * submit.
> +        */
> +       __u64 commands;
> +
> +       /** @flags: Flags for command submission (MBZ) */
> +       __u32 flags;
> +
> +       /** @queue_id: The queue ID to be submitted to */
> +       __u32 queue_id;
> +
> +       /**
> +        * @in_sync_count: Number of sync objects to wait on before starting
> +        * this job.
> +        */
> +       __u32 in_sync_count;
> +
> +       /**
> +        * @out_sync_count: Number of sync objects to signal upon completion of
> +        * this job.
> +        */
> +       __u32 out_sync_count;
> +
> +       /** @command_count: Number of commands to be submitted */
> +       __u32 command_count;
> +};
> +
> +/**
> + * struct drm_asahi_attachment - Describe an "attachment".
> + *
> + * Attachments are any memory written by shaders, notably including render
> + * target attachments written by the end-of-tile program. This is purely a hint
> + * about the accessed memory regions. It is optional to specify, which is
> + * fortunate as it cannot be specified precisely with bindless access anyway.
> + * But where possible, it's probably a good idea for userspace to include these
> + * hints, forwarded to the firmware.
> + */
> +struct drm_asahi_attachment {
> +       /** @pointer: Base address of the attachment */
> +       __u64 pointer;
> +
> +       /** @size: Size of the attachment in bytes */
> +       __u64 size;
> +
> +       /** @pad: MBZ */
> +       __u32 pad;
> +
> +       /** @flags: MBZ */
> +       __u32 flags;
> +};
> +
> +/**
> + * define ASAHI_RENDER_VERTEX_SPILLS - Vertex stage shader spills
> + */
> +#define ASAHI_RENDER_VERTEX_SPILLS (1UL << 0)
> +
> +/**
> + * define ASAHI_RENDER_PROCESS_EMPTY_TILES - Process empty tiles through the
> + * fragment load/store
> + */
> +#define ASAHI_RENDER_PROCESS_EMPTY_TILES (1UL << 1)
> +
> +/**
> + * define ASAHI_RENDER_NO_VERTEX_CLUSTERING - Run vertex stage on a single
> + * cluster (on multicluster GPUs)
> + *
> + * This will harm performance but can workaround certain sync/coherency bugs,
> + * and therefore is useful for debugging.
> + */
> +#define ASAHI_RENDER_NO_VERTEX_CLUSTERING (1UL << 2)
> +
> +/**
> + * define ASAHI_RENDER_DBIAS_IS_INT - Use integer depth bias formula.
> + *
> + * Graphics specifications contain two alternate formulas for depth bias, a
> + * float formula used with floating-point depth buffers and an integer formula
> + * using with unorm depth buffers. This flag specifies that the integer formula
> + * should be used. If omitted, the float formula is used instead.
> + *
> + * This corresponds to bit 18 of the relevant hardware control register, so we
> + * match that here for efficiency.
> + */
> +#define ASAHI_RENDER_DBIAS_IS_INT (1UL << 18)
> +
> +/**
> + * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
> + *
> + * These fields correspond directly to hardware registers in the ZLS (Z
> + * Load/Store) unit. Together, they configure a single depth or stencil buffer.
> + * Typically, load/store/partial will all use the same values. However, the
> + * hardware does not require this.
> + */
> +struct drm_asahi_zls_buffer {
> +       /** @load: Base address of the buffer to load at the start */
> +       __u64 load;
> +
> +       /** @store: Base address of the buffer to store at the end */
> +       __u64 store;
> +
> +       /**
> +        * @partial: Base address of the buffer to load and store during a
> +        * partial render operation.
> +        */
> +       __u64 partial;
> +
> +       /**
> +        * @comp_load: If the load buffer is compressed, address of the
> +        * compression metadata section.
> +        */
> +       __u64 comp_load;
> +
> +       /**
> +        * @comp_store: If the load buffer is compressed, address of the
> +        * compression metadata section.
> +        */
> +       __u64 comp_store;
> +
> +       /**
> +        * @comp_partial: If the partial render buffer is compressed, address of
> +        * the compression metadata section.
> +        */
> +       __u64 comp_partial;
> +
> +       /**
> +        * @load_stride: If layered rendering is enabled, the number of bytes
> +        * between each layer of the load buffer.
> +        */
> +       __u32 load_stride;
> +
> +       /**
> +        * @store_stride: If layered rendering is enabled, the number of bytes
> +        * between each layer of the store buffer.
> +        */
> +       __u32 store_stride;
> +
> +       /**
> +        * @partial_stride: If layered rendering is enabled, the number of bytes
> +        * between each layer of the partial render buffer.
> +        */
> +       __u32 partial_stride;
> +
> +       /**
> +        * @comp_load_stride: If layered rendering is enabled, the number of bytes
> +        * between each layer of the compression metadata for loads.
> +        */
> +       __u32 comp_load_stride;
> +
> +       /**
> +        * @comp_store_stride: If layered rendering is enabled, the number of
> +        * bytes between each layer of the compression metadata for stores.
> +        */
> +       __u32 comp_store_stride;
> +
> +       /**
> +        * @comp_partial_stride: If layered rendering is enabled, the number of
> +        * bytes between each layer of the compression metadata for partial
> +        * renders.
> +        */
> +       __u32 comp_partial_stride;
> +};
> +
> +/**
> + * struct drm_asahi_timestamp - Describe a timestamp write.
> + *
> + * The firmware can optionally write the GPU timestamp at render pass
> + * granularities, but it needs to be mapped specially via
> + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
> + * write as a handle-offset pair, rather than a GPU address like normal.
> + */
> +struct drm_asahi_timestamp {
> +       /**
> +        * @handle: Handle of the timestamp buffer, or 0 to skip this
> +        * timestamp. If nonzero, this must equal the value returned in
> +        * drm_asahi_gem_bind_object::object_handle.
> +        */
> +       __u32 handle;
> +
> +       /** @offset: Offset to write into the timestamp buffer */
> +       __u32 offset;
> +};
> +
> +/**
> + * struct drm_asahi_timestamps - Describe timestamp writes.
> + *
> + * Each operation that can be timestamped, can be timestamped at the start and
> + * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
> + * together into drm_asahi_timestamps.
> + */
> +struct drm_asahi_timestamps {
> +       /** @start: Timestamp recorded at the start of the operation */
> +       struct drm_asahi_timestamp start;
> +
> +       /** @end: Timestamp recorded at the end of the operation */
> +       struct drm_asahi_timestamp end;
> +};
> +
> +/**
> + * struct drm_asahi_helper_program - Describe helper program configuration.
> + *
> + * The helper program is a compute-like kernel required for various hardware
> + * functionality. Its most important role is dynamically allocating
> + * scratch/stack memory for individual subgroups, by partitioning a static
> + * allocation shared for the whole device. It is supplied by userspace via
> + * drm_asahi_helper_program and internally dispatched by the hardware as needed.
> + */
> +struct drm_asahi_helper_program {
> +       /**
> +        * @binary: USC address to the helper program binary. This is a tagged
> +        * pointer with configuration in the bottom bits.
> +        */
> +       __u32 binary;
> +
> +       /** @cfg: Configuration bits for the helper program. */
> +       __u32 cfg;
> +
> +       /**
> +        * @data: Data passed to the helper program. This value is not
> +        * interpreted by the kernel, firmware, or hardware in any way. It is
> +        * simply a sideband for userspace, set with the submit ioctl and read
> +        * via special registers inside the helper program.
> +        *
> +        * In practice, userspace will pass a 64-bit GPU VA here pointing to the
> +        * actual arguments, which presumably don't fit in 64-bits.
> +        */
> +       __u64 data;
> +};
> +
> +/**
> + * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
> + *
> + * The background and end-of-tile programs are dispatched by the hardware at the
> + * beginning and end of rendering. As the hardware "tilebuffer" is simply local
> + * memory, these programs are necessary to implement API-level render targets.
> + * The fragment-like background program is responsible for loading either the
> + * clear colour or the existing render target contents, while the compute-like
> + * end-of-tile program stores the tilebuffer contents to memory.
> + */
> +struct drm_asahi_bg_eot {
> +       /**
> +        * @usc: USC address of the hardware USC words binding resources
> +        * (including images and uniforms) and the program itself. Note this is
> +        * an additional layer of indirection compared to the helper program,
> +        * avoiding the need for a sideband for data. This is a tagged pointer
> +        * with additional configuration in the bottom bits.
> +        */
> +       __u32 usc;
> +
> +       /**
> +        * @rsrc_spec: Resource specifier for the program. This is a packed
> +        * hardware data structure describing the required number of registers,
> +        * uniforms, bound textures, and bound samplers.
> +        */
> +       __u32 rsrc_spec;
> +};
> +
> +/**
> + * struct drm_asahi_cmd_render - Command to submit 3D
> + *
> + * This command submits a single render pass. The hardware control stream may
> + * include many draws and subpasses, but within the command, the framebuffer
> + * dimensions and attachments are fixed.
> + *
> + * The hardware requires the firmware to set a large number of Control Registers
> + * setting up state at render pass granularity before each command rendering 3D.
> + * The firmware bundles this state into data structures. Unfortunately, we
> + * cannot expose either any of that directly to userspace, because the
> + * kernel-firmware ABI is not stable. Although we can guarantee the firmware
> + * updates in tandem with the kernel, we cannot break old userspace when
> + * upgrading the firmware and kernel. Therefore, we need to abstract well the
> + * data structures to avoid tying our hands with future firmwares.
> + *
> + * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
> + * control registers, marshalled via the firmware interface.
> + *
> + * The framebuffer/tilebuffer dimensions are also specified here. In addition to
> + * being passed to the firmware/hardware, the kernel requires these dimensions
> + * to calculate various essential tiling-related data structures. It is
> + * unfortunate that our submits are heavier than on vendors with saner
> + * hardware-software interfaces. The upshot is all of this information is
> + * readily available to userspace with all current APIs.
> + *
> + * It looks odd - but it's not overly burdensome and it ensures we can remain
> + * compatible with old userspace.
> + */
> +struct drm_asahi_cmd_render {
> +       /** @flags: Zero or more of ASAHI_RENDER_* */
> +       __u64 flags;
> +
> +       /** @encoder_ptr: GPU base address to the hardware control stream */
> +       __u64 encoder_ptr;
> +
> +       /**
> +        * @usc_base: GPU base address for all USC binaries (shaders) used in
> +        * this command. USC addresses are 32-bit relative to this 64-bit base.
> +        */
> +       __u64 usc_base;
> +
> +       /**
> +        * @vertex_attachments: Pointer to drm_asahi_attachment array used for
> +        * the vertex portion of this command.
> +        */
> +       __u64 vertex_attachments;
> +
> +       /**
> +        * @fragment_attachments: Pointer to drm_asahi_attachment array used for
> +        * the fragment portion of this command. This includes the end-of-tile
> +        * shader, in addition to the fragment shaders themselves.
> +        */
> +       __u64 fragment_attachments;
> +
> +       /**
> +        * @vertex_attachment_count: Number of drm_asahi_attachment's pointed to
> +        * by vertex_attachments
> +        */
> +       __u32 vertex_attachment_count;
> +
> +       /**
> +        * @fragment_attachment_count: Number of drm_asahi_attachment's pointed
> +        * to by fragment_attachmenst
> +        */
> +       __u32 fragment_attachment_count;
> +
> +       /** @vertex_helper: Helper program used for the vertex shader */
> +       struct drm_asahi_helper_program vertex_helper;
> +
> +       /** @fragment_helper: Helper program used for the fragment shader */
> +       struct drm_asahi_helper_program fragment_helper;
> +
> +       /**
> +        * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
> +        * array of scissor descriptors indexed in the render pass.
> +        */
> +       __u64 isp_scissor_base;
> +
> +       /**
> +        * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
> +        * array of depth bias values indexed in the render pass.
> +        */
> +       __u64 isp_dbias_base;
> +
> +       /**
> +        * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
> +        * array of occlusion query results written by the render pass.
> +        */
> +       __u64 isp_oclqry_base;
> +
> +       /** @depth: Physical buffers backing the logical depth buffer */
> +       struct drm_asahi_zls_buffer depth;
> +
> +       /** @stencil: Physical buffers backing the logical stencil buffer */
> +       struct drm_asahi_zls_buffer stencil;
> +
> +       /** @zls_ctrl: ZLS_CTRL register value */
> +       __u64 zls_ctrl;
> +
> +       /** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
> +       __u64 ppp_multisamplectl;
> +
> +       /**
> +        * @sampler_heap: Base address of the sampler heap. This heap is used
> +        * for both vertex shaders and fragment shaders. The registers are
> +        * per-stage, but there is no known use case for separate heaps.
> +        */
> +       __u64 sampler_heap;
> +
> +       /** @ppp_ctrl: PPP_CTRL register value */
> +       __u32 ppp_ctrl;
> +
> +       /** @width_px: Framebuffer width in pixels */
> +       __u16 width_px;
> +
> +       /** @height_px: Framebuffer height in pixels */
> +       __u16 height_px;
> +
> +       /** @layers: Number of layers in the framebuffer */
> +       __u16 layers;
> +
> +       /** @sampler_count: Number of samplers in the sampler heap. */
> +       __u16 sampler_count;
> +
> +       /** @utile_width_px: Width of a logical tilebuffer tile in pixels */
> +       __u8 utile_width_px;
> +
> +       /** @utile_height_px: Height of a logical tilebuffer tile in pixels */
> +       __u8 utile_height_px;
> +
> +       /** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
> +       __u8 samples;
> +
> +       /** @sample_size_B: # of bytes in the tilebuffer required per sample. */
> +       __u8 sample_size_B;
> +
> +       /** @encoder_id: Opaque handle identifying what encoded this command. */
> +       __u32 encoder_id;
> +
> +       /**
> +        * @cmd_ta_id: Unique identifier for the Tiling Accelerator (TA)
> +        * portion of this command.
> +        */
> +       __u32 cmd_ta_id;
> +
> +       /**
> +        * @cmd_3d_id: Unique identifier for the 3D
> +        * portion of this command.
> +        */
> +       __u32 cmd_3d_id;
> +
> +       /**
> +        * @isp_merge_upper_x: 32-bit float used in the
> +        * hardware triangle merging. Calculate as:
> +        *
> +        *      tan(60 deg) * width
> +        *
> +        * Making these values UAPI avoids requiring floating-point calculations
> +        * in the kernel in the hot path.
> +        */
> +       __u32 isp_merge_upper_x;
> +
> +       /**
> +        * @isp_merge_upper_y: 32-bit float. Calculate as:
> +        *
> +        *      tan(60 deg) * height
> +        *
> +        * See @isp_merge_upper_x.
> +        */
> +
> +       __u32 isp_merge_upper_y;
> +
> +       /**
> +        * @bg: Background program ran at the start of each tile at the start of
> +        * the render pass.
> +        */
> +       struct drm_asahi_bg_eot bg;
> +
> +       /**
> +        * @eot: End-of-tile program ran at the end of each tile at the end of
> +        * the render pass.
> +        */
> +       struct drm_asahi_bg_eot eot;
> +
> +       /**
> +        * @partial_bg: Background program ran at the start of each tile when
> +        * resuming the render pass during a partial render.
> +        */
> +       struct drm_asahi_bg_eot partial_bg;
> +
> +       /**
> +        * @partial_eot: End-of-tile program ran at the end of each tile when
> +        * pausing the render pass during a partial render.
> +        */
> +       struct drm_asahi_bg_eot partial_eot;
> +
> +       /**
> +        * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
> +        * depth buffer width/height, which is allowed to differ from the
> +        * framebuffer width/height.
> +        */
> +       __u32 isp_zls_pixels;
> +
> +       /**
> +        * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
> +        * buffer clear value, encoded in the depth buffer's format: either a
> +        * 32-bit float or a 16-bit unorm (with upper bits zeroed).
> +        */
> +       __u32 isp_bgobjdepth;
> +
> +       /**
> +        * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
> +        * contain the stencil buffer clear value.
> +        */
> +       __u32 isp_bgobjvals;
> +
> +       /** @ts_vtx: Timestamps for the vertex portion of the render */
> +       struct drm_asahi_timestamps ts_vtx;
> +
> +       /** @ts_frag: Timestamps for the fragment portion of the render */
> +       struct drm_asahi_timestamps ts_frag;
> +};
> +
> +/**
> + * struct drm_asahi_cmd_compute - Command to submit compute
> + *
> + * This command submits a control stream consisting of compute dispatches. There
> + * is essentially no limit on how many compute dispatches may be included in a
> + * single compute command, although timestamping only occurs at command
> + * granularity.
> + */
> +struct drm_asahi_cmd_compute {
> +       /** @flags: MBZ */
> +       __u64 flags;
> +
> +       /** @encoder_ptr: GPU base address to the hardware control stream */
> +       __u64 encoder_ptr;
> +
> +       /**
> +        * @encoder_end: GPU base address to the end of the hardware control
> +        * stream. Note this only considers the first contiguous segment of the
> +        * control stream, as the stream might jump elsewhere.
> +        */
> +       __u64 encoder_end;
> +
> +       /**
> +        * @usc_base: GPU Base address for all USC binaries (shaders) used in
> +        * this command. USC addresses are 32-bit relative to this 64-bit base.
> +        */
> +       __u64 usc_base;
> +
> +       /**
> +        * @attachments: Pointer to drm_asahi_attachment array used for
> +        * this command
> +        */
> +       __u64 attachments;
> +
> +       /**
> +        * @sampler_heap: Base address of the sampler heap. This heap is used
> +        * for both vertex shaders and fragment shaders. The registers are
> +        * per-stage, but there is no known use case for separate heaps.
> +        */
> +       __u64 sampler_heap;
> +
> +       /**
> +        * @attachment_count: Number of drm_asahi_attachments pointed to by
> +        * @attachments
> +        */
> +       __u32 attachment_count;
> +
> +       /** @sampler_count: Number of samplers in the sampler heap. */
> +       __u32 sampler_count;
> +
> +       /** @helper: Helper program used for this compute shader */
> +       struct drm_asahi_helper_program helper;
> +
> +       /** @encoder_id: Opaque handle identifying what encoded this command. */
> +       __u32 encoder_id;
> +
> +       /** @cmd_id: Unique identifier for this command. */
> +       __u32 cmd_id;
> +
> +       /** @ts: Timestamps for the compute command */
> +       struct drm_asahi_timestamps ts;
> +};
> +
> +/**
> + * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
> + */
> +struct drm_asahi_get_time {
> +       /** @flags: MBZ. */
> +       __u64 flags;
> +
> +       /** @gpu_timestamp: On return, the current GPU timestamp */
> +       __u64 gpu_timestamp;
> +};
> +
> +/**
> + * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
> + * @__access: Access type. Must be R, W or RW.
> + * @__id: One of the DRM_ASAHI_xxx id.
> + * @__type: Suffix of the type being passed to the IOCTL.
> + *
> + * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
> + * values instead.
> + *
> + * Return: An IOCTL number to be passed to ioctl() from userspace.
> + */
> +#define DRM_IOCTL_ASAHI(__access, __id, __type) \
> +       DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
> +                          struct drm_asahi_ ## __type)
> +
> +/* Note: this is an enum so that it can be resolved by Rust bindgen. */
> +enum {
> +       DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
> +       DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
> +       DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
> +       DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
> +       DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
> +       DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
> +       DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
> +       DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
> +       DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
> +       DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
> +       DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
> +};
> +
> +#if defined(__cplusplus)
> +}
> +#endif
> +
> +#endif /* _ASAHI_DRM_H_ */
>
> ---
> base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
> change-id: 20250307-agx-uapi-930579437f19
>
> Best regards,
> --
> Alyssa Rosenzweig <alyssa at rosenzweig.io>
>


From mhklinux at outlook.com  Mon Mar 10 14:16:34 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 21:16:34 +0000
Subject: [PATCH hyperv-next v5 01/11] arm64: kvm, smccc: Introduce and use
 API for detectting hypervisor presence
In-Reply-To: <20250307220304.247725-2-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-2-romank@linux.microsoft.com>
Message-ID: <BN7PR02MB4148539DEFFF5ABA42AB44D3D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 

In the Subject line,

s/detectting/detecting/

> The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
> private, and it follows the SMCCC specification. Other existing and
> emerging hypervisor guest implementations can and should use that
> standard approach as well.
> 
> Factor out a common infrastructure that the guests can use, update KVM
> to employ the new API. The cenrtal notion of the SMCCC method is the

s/cenrtal/central/

> UUID of the hypervisor, and the API follows that.
> 
> No functional changes. Validated with a KVM/arm64 guest.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  arch/arm64/kvm/hypercalls.c        |  5 +--
>  drivers/firmware/smccc/kvm_guest.c | 10 ++----
>  drivers/firmware/smccc/smccc.c     | 19 +++++++++++
>  include/linux/arm-smccc.h          | 55 +++++++++++++++++++++++++++---
>  4 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
> index 27ce4cb44904..92b9bc1ea8e8 100644
> --- a/arch/arm64/kvm/hypercalls.c
> +++ b/arch/arm64/kvm/hypercalls.c
> @@ -353,10 +353,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
>  			val[0] = gpa;
>  		break;
>  	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
> -		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
> -		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
> -		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
> -		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
> +		UUID_TO_SMCCC_RES(ARM_SMCCC_VENDOR_HYP_UID_KVM, val);
>  		break;
>  	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
>  		val[0] = smccc_feat->vendor_hyp_bmap;
> diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
> index f3319be20b36..b5084b309ea0 100644
> --- a/drivers/firmware/smccc/kvm_guest.c
> +++ b/drivers/firmware/smccc/kvm_guest.c
> @@ -14,17 +14,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services,
> ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
> 
>  void __init kvm_init_hyp_services(void)
>  {
> +	uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
>  	struct arm_smccc_res res;
>  	u32 val[4];
> 
> -	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> -		return;
> -
> -	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> -	if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
> -	    res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
> -	    res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
> -	    res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
> +	if (!arm_smccc_hyp_present(&kvm_uuid))
>  		return;
> 
>  	memset(&res, 0, sizeof(res));
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index a74600d9f2d7..7399f27d58e5 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
> @@ -67,6 +67,25 @@ s32 arm_smccc_get_soc_id_revision(void)
>  }
>  EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
> 
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> +{
> +	struct arm_smccc_res res = {};
> +
> +	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> +		return false;
> +	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> +	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> +		return false;
> +
> +	return ({
> +		const uuid_t uuid = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
> +		const bool present = uuid_equal(&uuid, hyp_uuid);
> +
> +		present;
> +	});
> +}
> +EXPORT_SYMBOL_GPL(arm_smccc_hyp_present);
> +
>  static int __init smccc_devices_init(void)
>  {
>  	struct platform_device *pdev;
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 67f6fdf2e7cd..726f18221f1c 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -7,6 +7,11 @@
> 
>  #include <linux/args.h>
>  #include <linux/init.h>
> +
> +#ifndef __ASSEMBLER__
> +#include <linux/uuid.h>
> +#endif
> +
>  #include <uapi/linux/const.h>
> 
>  /*
> @@ -107,10 +112,10 @@
>  			   ARM_SMCCC_FUNC_QUERY_CALL_UID)
> 
>  /* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0	0xb66fb428U
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1	0xe911c52eU
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2	0x564bcaa9U
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3	0x743a004dU
> +#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
> +	0xb66fb428, 0xc52e, 0xe911, \
> +	0xa9, 0xca, 0x4b, 0x56, \
> +	0x4d, 0x00, 0x3a, 0x74)
> 
>  /* KVM "vendor specific" services */
>  #define ARM_SMCCC_KVM_FUNC_FEATURES		0
> @@ -333,6 +338,48 @@ s32 arm_smccc_get_soc_id_version(void);
>   */
>  s32 arm_smccc_get_soc_id_revision(void);
> 
> +#ifndef __ASSEMBLER__
> +
> +/**
> + * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> + *
> + * Returns `true` if the hypervisor advertises its presence via SMCCC.
> + *
> + * When the function returns `false`, the caller shall not assume that
> + * there is no hypervisor running. Instead, the caller must fall back to
> + * other approaches if any are available.
> + */
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);
> +
> +#define SMCCC_RES_TO_UUID(r0, r1, r2, r3) \
> +	UUID_INIT( \
> +		cpu_to_le32(lower_32_bits(r0)), \
> +		cpu_to_le32(lower_32_bits(r1)) & 0xffff, \
> +		cpu_to_le32(lower_32_bits(r1)) >> 16, \
> +		cpu_to_le32(lower_32_bits(r2)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 24) & 0xff, \
> +		cpu_to_le32(lower_32_bits(r3)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 24) & 0xff \
> +	)
> +
> +#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
> +		const uuid_t uuid = uuid_init; \
> +		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
> +						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24));
> \
> +		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
> +						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24));
> \
> +		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
> +						((uuid.b[10]) << 16) | ((uuid.b[11]) <<
> 24)); \
> +		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
> +						((uuid.b[14]) << 16) | ((uuid.b[15]) <<
> 24)); \
> +	} while (0)
> +
> +#endif /* !__ASSEMBLER__ */
> +
>  /**
>   * struct arm_smccc_res - Result from SMC/HVC call
>   * @a0-a3 result values from registers 0 to 3
> --
> 2.43.0
> 



From krzk at kernel.org  Mon Mar 10 14:17:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 10 Mar 2025 22:17:20 +0100
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <ba6b906d-04a2-423d-a527-9ef7ab1dccf2@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
 <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
 <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>
 <09d4966a-5804-40a4-9c5f-356a954a7704@kernel.org>
 <ba6b906d-04a2-423d-a527-9ef7ab1dccf2@linux.microsoft.com>
Message-ID: <ff3739bb-a223-401e-9b70-a5201839b72c@kernel.org>

On 10/03/2025 19:07, Roman Kisel wrote:
> 
> It is modeled as a bus in the kernel:
> https://www.kernel.org/doc/html/latest/virt/hyperv/vmbus.html
> 
>> Please upstream bindings for the bus devices and extend the example here
>> with these devices.
> 
> The set of synthetic devices that reside on the bus isn't fixed, and
> they don't require description neither in ACPI nor in DT as
> the devices negotiate their MMIO regions through the hyperv driver.
> 
> Perhaps, it is not as much bus as expected by the YAML files.

OK, then this is not really a bus from the bindings point of view. It is
a device schema which should end with additionalProperties: false.

If you have report about that pinctrl-0, it means you have undocumented
properties in your DTS. Maybe that's the dma-coherence you mentioned in
the commit msg.


Best regards,
Krzysztof


From mhklinux at outlook.com  Mon Mar 10 14:17:41 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 21:17:41 +0000
Subject: [PATCH hyperv-next v5 02/11] arm64: hyperv: Use SMCCC to detect
 hypervisor presence
In-Reply-To: <20250307220304.247725-3-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-3-romank@linux.microsoft.com>
Message-ID: <BN7PR02MB414898162A26B7424D92DDA7D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> The arm64 Hyper-V startup path relies on ACPI to detect
> running under a Hyper-V compatible hypervisor. That
> doesn't work on non-ACPI systems.
> 
> Hoist the ACPI detection logic into a separate function. Then
> use the vendor-specific hypervisor service call (implemented
> recently in Hyper-V) via SMCCC in the non-ACPI case.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++-----
>  1 file changed, 38 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index 29fcfd595f48..c647db56fd6b 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info
> *info)
>  	return 0;
>  }
> 
> +static bool __init hyperv_detect_via_acpi(void)
> +{
> +	if (acpi_disabled)
> +		return false;
> +#if IS_ENABLED(CONFIG_ACPI)
> +	/*
> +	 * Hypervisor ID is only available in ACPI v6+, and the
> +	 * structure layout was extended in v6 to accommodate that
> +	 * new field.
> +	 *
> +	 * At the very minimum, this check makes sure not to read
> +	 * past the FADT structure.
> +	 *
> +	 * It is also needed to catch running in some unknown
> +	 * non-Hyper-V environment that has ACPI 5.x or less.
> +	 * In such a case, it can't be Hyper-V.
> +	 */
> +	if (acpi_gbl_FADT.header.revision < 6)
> +		return false;
> +	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
> +#else
> +	return false;
> +#endif
> +}
> +
> +static bool __init hyperv_detect_via_smccc(void)
> +{
> +	uuid_t hyperv_uuid = UUID_INIT(
> +		0x4d32ba58, 0x4764, 0xcd24,
> +		0x75, 0x6c, 0xef, 0x8e,
> +		0x24, 0x70, 0x59, 0x16);
> +
> +	return arm_smccc_hyp_present(&hyperv_uuid);
> +}
> +
>  static int __init hyperv_init(void)
>  {
>  	struct hv_get_vp_registers_output	result;
> @@ -35,13 +70,11 @@ static int __init hyperv_init(void)
> 
>  	/*
>  	 * Allow for a kernel built with CONFIG_HYPERV to be running in
> -	 * a non-Hyper-V environment, including on DT instead of ACPI.
> +	 * a non-Hyper-V environment.
> +	 *
>  	 * In such cases, do nothing and return success.
>  	 */
> -	if (acpi_disabled)
> -		return 0;
> -
> -	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
> +	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
>  		return 0;
> 
>  	/* Setup the guest ID */
> --
> 2.43.0
> 

Reviewed-by: Michael Kelley <mhklinux at outlook.com>



From arnd at arndb.de  Mon Mar 10 14:20:41 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 10 Mar 2025 22:20:41 +0100
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for arm64
In-Reply-To: <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
Message-ID: <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>

On Mon, Mar 10, 2025, at 22:01, Michael Kelley wrote:
> From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
>> >  config HYPERV_VTL_MODE
>> >  	bool "Enable Linux to boot in VTL context"
>> > -	depends on X86_64 && HYPERV
>> > +	depends on (X86_64 || ARM64)
>> >  	depends on SMP
>> > +	select OF_EARLY_FLATTREE
>> > +	select OF
>> >  	default n
>> >  	help
>> 
>> Having the dependency below the top-level Kconfig entry feels a little
>> counterintuitive. You could flip that back as it was before by doing
>> 
>>       select HYPERV_VTL_MODE if !ACPI
>>       depends on ACPI || SMP
>> 
>> in the HYPERV option, leaving the dependency on HYPERV in
>> HYPERV_VTL_MODE.
>
> I would argue that we don't ever want to implicitly select
> HYPERV_VTL_MODE because of some other config setting or
> lack thereof.  VTL mode is enough of a special case that it should
> only be explicitly selected. If someone omits ACPI, then HYPERV
> should not be selectable unless HYPERV_VTL_MODE is explicitly
> selected.
>
> The last line of the comment for HYPERV_VTL_MODE says
> "A kernel built with this option must run at VTL2, and will not run
> as a normal guest."  In other words, don't choose this unless you
> 100% know that VTL2 is what you want.

It sounds like the latter is the real problem: enabling a feature
should never prevent something else from working. Can you describe
what VTL context is and why it requires an exception to a rather
fundamental rule here? If you build a kernel that runs on every
single piece of arm64 hardware and every hypervisor, why can't
you add HYPERV_VTL_MODE to that as an option?

      Arnd


From kw at linux.com  Mon Mar 10 14:21:25 2025
From: kw at linux.com (Krzysztof Wilczynski)
Date: Tue, 11 Mar 2025 06:21:25 +0900
Subject: [PATCH v7 03/11] dt-bindings: pci: Add common schema for devices
 accessible through PCI BARs
In-Reply-To: <c0acc51a7210fb30cae7b26f4ad1f0449beed95e.1738963156.git.andrea.porta@suse.com>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <c0acc51a7210fb30cae7b26f4ad1f0449beed95e.1738963156.git.andrea.porta@suse.com>
Message-ID: <20250310212125.GB2377483@rocinante>

Hello,

[...]
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d45c88955072..af2e4652bf3b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -19752,6 +19752,7 @@ RASPBERRY PI RP1 PCI DRIVER
>  M:	Andrea della Porta <andrea.porta at suse.com>
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
> +F:	Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
>  F:	Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
>  F:	include/dt-bindings/clock/rp1.h
>  F:	include/dt-bindings/misc/rp1.h

I would be happy to pick this via the PCI tree as per the standard
operating procedure.  However, the MAINTAINERS changes do not exist
for us yet, and are added in the first patch of the series, which is
not ideal.

I can add the missing dependency manually, but that would cause issues
for linux-next tree, which is also not ideal.

I saw some review feedback, as such, when you are going to be sending
another version, can you make MAINTAINERS changes to be the last patch,
perhaps.  Basically, something standalone that perhaps whoever will pick
the misc patch could also pick and apply at the same time.

Alternatively, someone else picking up the PCI dt-bindings would work, too.

Your thoughts?

Thank you!

	Krzysztof


From jacob.e.keller at intel.com  Mon Mar 10 14:27:53 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Mon, 10 Mar 2025 14:27:53 -0700
Subject: Plan to validate supported flags in PTP core (Was: Re: [PATCH net
 v2 0/2] Fixes for perout configuration in IEP driver)
In-Reply-To: <20250310172541.30896e20@kernel.org>
References: <20250219062701.995955-1-m-malladi@ti.com>
 <415f755d-18a6-4c81-a1a7-b75d54a5886a@intel.com>
 <20250220172410.025b96d6@kernel.org>
 <a7e434a5-b5f6-4736-98e4-e671f88d1873@intel.com>
 <f7072ca6-47a7-4278-be5d-7cbd240fcd35@intel.com>
 <20250310172541.30896e20@kernel.org>
Message-ID: <412a7fee-daec-496d-990a-642f2787d5cc@intel.com>



On 3/10/2025 9:25 AM, Jakub Kicinski wrote:
> On Fri, 7 Mar 2025 15:48:27 -0800 Jacob Keller wrote:
>> Would a series with individual patches for the 3 special cases + one
>> patch to handle all the drivers that have no explicit flag check be
>> acceptable? Or should I do individual patches for each driver and just
>> break the series up? Or are we ok with just fixing this in next with the
>> .supported_extts_flags change?
> 
> A mass rejection of unsupported settings feels like a net-next material
> in general. Handling the more complex cases individually and the rest in
> a big patch makes sense.

Alright. I think the three cases with drivers that check flags but do so
incorrectly are worth going to net. I'll send that series shortly, and
will follow up with the next series that introduces the supported flags
knobs afterwards.

Thanks,
Jake


From nunodasneves at linux.microsoft.com  Mon Mar 10 14:46:45 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Mon, 10 Mar 2025 14:46:45 -0700
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <SN6PR02MB41573673D5F786E6C47FC08ED4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
 <Z7-nDUe41XHyZ8RJ@skinsburskii.>
 <7de9b06d-9a32-48b5-beda-2e19b36ae9c9@linux.microsoft.com>
 <SN6PR02MB41573673D5F786E6C47FC08ED4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <71a95f7d-d38b-4f4f-b384-9ad4095bd272@linux.microsoft.com>

On 3/7/2025 9:38 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, February 28, 2025 4:38 PM
>>
>> On 2/26/2025 3:43 PM, Stanislav Kinsburskii wrote:
>>> On Wed, Feb 26, 2025 at 03:08:02PM -0800, Nuno Das Neves wrote:
>>>> This will handle SYNIC interrupts such as intercepts, doorbells, and
>>>> scheduling messages intended for the mshv driver.
>>>>
>>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
>>>> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
>>>> ---
>>>>  arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
>>>>  drivers/hv/hv_common.c         | 5 +++++
>>>>  include/asm-generic/mshyperv.h | 1 +
>>>>  3 files changed, 15 insertions(+)
>>>>
>>>> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
>>>> index 0116d0e96ef9..616e9a5d77b4 100644
>>>> --- a/arch/x86/kernel/cpu/mshyperv.c
>>>> +++ b/arch/x86/kernel/cpu/mshyperv.c
>>>> @@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
>>>>  }
>>>>  EXPORT_SYMBOL_GPL(hv_set_msr);
>>>>
>>>> +static void (*mshv_handler)(void);
>>>>  static void (*vmbus_handler)(void);
>>>>  static void (*hv_stimer0_handler)(void);
>>>>  static void (*hv_kexec_handler)(void);
>>>> @@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>>>>  	struct pt_regs *old_regs = set_irq_regs(regs);
>>>>
>>>>  	inc_irq_stat(irq_hv_callback_count);
>>>> +	if (mshv_handler)
>>>> +		mshv_handler();
>>>
>>> Can mshv_handler be defined as a weak symbol doing nothing instead
>>> of defining it a null pointer?
>>> This should allow to simplify this code and get rid of
>>> hv_setup_mshv_handler, which looks redundant.
>>>
>> Interesting, I tested this and it does seems to work! It seems like
>> a good change, thanks.
> 
> Just be a bit careful. When CONFIG_HYPERV=n, mshyperv.c still gets
> built even through none of the other Hyper-V related files do.  There
> are #ifdef CONFIG_HYPERV in mshyperv.c to eliminate references to
> Hyper-V files that wouldn't be built. I'd suggest doing a test build with
> that configuration to make sure it's all clean.
> 
Thanks Michael - I don't think it would be an issue since the __weak version
would be defined in mshyperv.c itself, replacing the function pointer.

However, I went and tested this __weak version again with CONFIG_MSHV_ROOT=m
and it does not actually work. Everything seems ok at first (it compiles,
can insert the module), but upon starting a guest, the interrupts don't get
delivered to the root (or rather, they don't get handled by mshv_hander()).

This seems to match with what the ld docs say - There's an option
LD_DYNAMIC_LINK to allow __weak symbols to be overridden by the dynamic
linker, but this is not enabled in the kernel.

So I will stick with the current implementation.

Nuno

> Michael
> 
>>
>>> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
>>>
>>>> +
>>>>  	if (vmbus_handler)
>>>>  		vmbus_handler();
>>>>
>>>> @@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
>>>>  	set_irq_regs(old_regs);
>>>>  }
>>>>
>>>> +void hv_setup_mshv_handler(void (*handler)(void))
>>>> +{
>>>> +	mshv_handler = handler;
>>>> +}
>>>> +
>>>>  void hv_setup_vmbus_handler(void (*handler)(void))
>>>>  {
>>>>  	vmbus_handler = handler;
>>>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>>>> index 2763cb6d3678..f5a07fd9a03b 100644
>>>> --- a/drivers/hv/hv_common.c
>>>> +++ b/drivers/hv/hv_common.c
>>>> @@ -677,6 +677,11 @@ void __weak hv_remove_vmbus_handler(void)
>>>>  }
>>>>  EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
>>>>
>>>> +void __weak hv_setup_mshv_handler(void (*handler)(void))
>>>> +{
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
>>>> +
>>>>  void __weak hv_setup_kexec_handler(void (*handler)(void))
>>>>  {
>>>>  }
>>>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>>>> index 1f46d19a16aa..a05f12e63ccd 100644
>>>> --- a/include/asm-generic/mshyperv.h
>>>> +++ b/include/asm-generic/mshyperv.h
>>>> @@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
>>>>  void hv_remove_kexec_handler(void);
>>>>  void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
>>>>  void hv_remove_crash_handler(void);
>>>> +void hv_setup_mshv_handler(void (*handler)(void));
>>>>
>>>>  extern int vmbus_interrupt;
>>>>  extern int vmbus_irq;
>>>> --
>>>> 2.34.1
>>>>
> 



From romank at linux.microsoft.com  Mon Mar 10 14:51:14 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 14:51:14 -0700
Subject: [PATCH hyperv-next v5 07/11] dt-bindings: microsoft,vmbus: Add
 interrupts and DMA coherence
In-Reply-To: <ff3739bb-a223-401e-9b70-a5201839b72c@kernel.org>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-8-romank@linux.microsoft.com>
 <20250310-demonic-ferret-of-judgment-5dbdbf@krzk-bin>
 <c7f9d861-f617-4064-8c98-2ace06e9c25e@linux.microsoft.com>
 <09d4966a-5804-40a4-9c5f-356a954a7704@kernel.org>
 <ba6b906d-04a2-423d-a527-9ef7ab1dccf2@linux.microsoft.com>
 <ff3739bb-a223-401e-9b70-a5201839b72c@kernel.org>
Message-ID: <2eb4e538-d131-4adf-b61a-998d56128183@linux.microsoft.com>



On 3/10/2025 2:17 PM, Krzysztof Kozlowski wrote:
> On 10/03/2025 19:07, Roman Kisel wrote:
>>
>> It is modeled as a bus in the kernel:
>> https://www.kernel.org/doc/html/latest/virt/hyperv/vmbus.html
>>
>>> Please upstream bindings for the bus devices and extend the example here
>>> with these devices.
>>
>> The set of synthetic devices that reside on the bus isn't fixed, and
>> they don't require description neither in ACPI nor in DT as
>> the devices negotiate their MMIO regions through the hyperv driver.
>>
>> Perhaps, it is not as much bus as expected by the YAML files.
> 
> OK, then this is not really a bus from the bindings point of view. It is
> a device schema which should end with additionalProperties: false.
> 
> If you have report about that pinctrl-0, it means you have undocumented
> properties in your DTS. Maybe that's the dma-coherence you mentioned in
> the commit msg.
> 

Much appreciated! I started reviewing the learning materials you
mentioned, and I think I already see where my understanding went
sideways: I perceived the example as the central part of the bindings
whereas it seems to be just what the name suggests: an example. Yet,
the example shall conform to the *schema* iiuc, and that is what the
tooling validates.

Hopefully, I am starting to be getting what this is all about :)
Thanks for your help again!

I've worked out what makes (more) sense (to me at least):

 From 475fb74b49dc4987ca8b9117186941d848f0aacd Mon Sep 17 00:00:00 2001
From: Roman Kisel <romank at linux.microsoft.com>
Date: Mon, 10 Mar 2025 14:39:41 -0700
Subject: [PATCH] dt-bindings: microsoft,vmbus: Add interrupt and DMA
   coherence properties

To boot in the VTL mode, VMBus on arm64 needs interrupt description
which the binding documentation lacks. The transactions on the bus are
DMA coherent which is not mentioned as well.

Add the interrupt property and the DMA coherence property to the VMBus
binding. Update the example to match that. Fix typos.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
  .../bindings/bus/microsoft,vmbus.yaml           | 17 +++++++++++++++--
  1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml 
b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
index a8d40c766dcd..b175ad01f219 100644
--- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
+++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
@@ -10,8 +10,8 @@ maintainers:
    - Saurabh Sengar <ssengar at linux.microsoft.com>

  description:
-  VMBus is a software bus that implement the protocols for communication
-  between the root or host OS and guest OSs (virtual machines).
+  VMBus is a software bus that implements the protocols for communication
+  between the root or host OS and guest OS'es (virtual machines).

  properties:
    compatible:
@@ -25,9 +25,17 @@ properties:
    '#size-cells':
      const: 1

+  dma-coherent: true
+
+  interrupts:
+    maxItems: 1
+    description: |
+      This interrupt signals a message from the host.
+
  required:
    - compatible
    - ranges
+  - interrupts
    - '#address-cells'
    - '#size-cells'

@@ -35,6 +43,8 @@ additionalProperties: false

  examples:
    - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
      soc {
          #address-cells = <2>;
          #size-cells = <1>;
@@ -49,6 +59,9 @@ examples:
                  #address-cells = <2>;
                  #size-cells = <1>;
                  ranges = <0x0f 0xf0000000 0x0f 0xf0000000 0x10000000>;
+                dma-coherent;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_PPI 2 IRQ_TYPE_EDGE_RISING>;
              };
          };
      };
-- 
2.43.0


> 
> Best regards,
> Krzysztof

-- 
Thank you,
Roman



From romank at linux.microsoft.com  Mon Mar 10 14:54:15 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 10 Mar 2025 14:54:15 -0700
Subject: [PATCH hyperv-next v5 01/11] arm64: kvm, smccc: Introduce and use
 API for detectting hypervisor presence
In-Reply-To: <BN7PR02MB4148539DEFFF5ABA42AB44D3D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-2-romank@linux.microsoft.com>
 <BN7PR02MB4148539DEFFF5ABA42AB44D3D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
Message-ID: <28970d64-40b7-408a-a072-c3449d3de08e@linux.microsoft.com>



On 3/10/2025 2:16 PM, Michael Kelley wrote:
> From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
>>
> 
> In the Subject line,
> 
> s/detectting/detecting/

[...]

> s/cenrtal/central/
> 

My bad, will fix! Thanks for spotting that, I'll be sure to have
the spellchecker on.

-- 
Thank you,
Roman



From kw at linux.com  Mon Mar 10 14:57:56 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 11 Mar 2025 06:57:56 +0900
Subject: [PATCH v1] PCI: imx6: Use devm_clk_bulk_get_all to fetch clocks
In-Reply-To: <20250226025628.1681206-1-hongxing.zhu@nxp.com>
References: <20250226025628.1681206-1-hongxing.zhu@nxp.com>
Message-ID: <20250310215756.GC2377483@rocinante>

Hello,

> Use devm_clk_bulk_get_all() to simple clock handle codes. No function
> changes.

Applied to controller/imx6, thank you!

	Krzysztof


From devnull+fnkl.kernel.gmail.com at kernel.org  Mon Mar 10 15:07:57 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Mon, 10 Mar 2025 23:07:57 +0100
Subject: [PATCH v3 0/3] Driver for the Apple SPMI controller
Message-ID: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>

Hi.

This patch series adds support for the SPMI controller persent in most
Apple SoCs. The drivers for the attached PMU and subdevices will be in
further patch series.

Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
Changes in v3:
- Inlined helpers, dropped unneccesary error prefixes
- Link to v2: https://lore.kernel.org/r/20250307-spmi-v2-0-eccdb06afb99 at gmail.com

Changes in v2:
- Removed redundant error prints
- Various style fixes
- Better explanation of why the driver is needed
- Link to v1: https://lore.kernel.org/r/20250305-spmi-v1-0-c98f561fa99f at gmail.com

---
Jean-Francois Bortolotti (1):
      spmi: add a spmi driver for Apple SoC

Sasha Finkelstein (2):
      dt-bindings: spmi: Add Apple SPMI controller
      arm64: dts: apple: Add SPMI controller nodes

 .../devicetree/bindings/spmi/apple,spmi.yaml       |  49 ++++++
 MAINTAINERS                                        |   2 +
 arch/arm64/boot/dts/apple/t600x-die0.dtsi          |   7 +
 arch/arm64/boot/dts/apple/t8103.dtsi               |   8 +
 arch/arm64/boot/dts/apple/t8112.dtsi               |   7 +
 drivers/spmi/Kconfig                               |   8 +
 drivers/spmi/Makefile                              |   1 +
 drivers/spmi/spmi-apple-controller.c               | 168 +++++++++++++++++++++
 8 files changed, 250 insertions(+)
---
base-commit: 48a5eed9ad584315c30ed35204510536235ce402
change-id: 20250304-spmi-6d3c24b9027a




From devnull+fnkl.kernel.gmail.com at kernel.org  Mon Mar 10 15:08:00 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Mon, 10 Mar 2025 23:08:00 +0100
Subject: [PATCH v3 3/3] arm64: dts: apple: Add SPMI controller nodes
In-Reply-To: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
References: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
Message-ID: <20250310-spmi-v3-3-92a82e7d9f0d@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add device tree entries for the SPMI controller

Reviewed-by: Nick Chan <towinchenmi at gmail.com>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 arch/arm64/boot/dts/apple/t600x-die0.dtsi | 7 +++++++
 arch/arm64/boot/dts/apple/t8103.dtsi      | 8 ++++++++
 arch/arm64/boot/dts/apple/t8112.dtsi      | 7 +++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index b1c875e692c8fb9c0af46a23568a7b0cd720141b..64d4f301ca850ddb043bccc087e0b874fb96da9b 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -45,6 +45,13 @@ pinctrl_smc: pinctrl at 290820000 {
 				<AIC_IRQ 0 749 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	nub_spmi0: spmi at 2920a1300 {
+		compatible = "apple,t6000-spmi", "apple,spmi";
+		reg = <0x2 0x920a1300 0x0 0x100>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+	};
+
 	wdt: watchdog at 2922b0000 {
 		compatible = "apple,t6000-wdt", "apple,wdt";
 		reg = <0x2 0x922b0000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 9b0dad6b618444ac6b1c9735c50cccfc3965f947..0f03dc808cf7c6b7d71afc79dd29d368f957f979 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/interrupt-controller/apple-aic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
 
 / {
 	compatible = "apple,t8103", "apple,arm-platform";
@@ -604,6 +605,13 @@ pcie_pins: pcie-pins {
 			};
 		};
 
+		nub_spmi: spmi at 23d0d9300 {
+			compatible = "apple,t8103-spmi", "apple,spmi";
+			reg = <0x2 0x3d0d9300 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_nub: pinctrl at 23d1f0000 {
 			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3d1f0000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 1666e6ab250bc0be9b8318e3c8fc903ccd3f3760..fa4309bb92975c4edbc11c998496f125267f2353 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -679,6 +679,13 @@ wdt: watchdog at 23d2b0000 {
 			interrupts = <AIC_IRQ 379 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		nub_spmi: spmi at 23d714000 {
+			compatible = "apple,t8112-spmi", "apple,spmi";
+			reg = <0x2 0x3d714000 0x0 0x100>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+		};
+
 		pinctrl_smc: pinctrl at 23e820000 {
 			compatible = "apple,t8112-pinctrl", "apple,pinctrl";
 			reg = <0x2 0x3e820000 0x0 0x4000>;

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Mon Mar 10 15:07:59 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Mon, 10 Mar 2025 23:07:59 +0100
Subject: [PATCH v3 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
References: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
Message-ID: <20250310-spmi-v3-2-92a82e7d9f0d@gmail.com>

From: Jean-Francois Bortolotti <jeff at borto.fr>

The connected PMU contains several useful nvmem cells such as RTC offset,
boot failure counters, reboot/shutdown selector, and a few others.
In addition M3+ machines have their USB-PD controller connected via SPMI.

Signed-off-by: Jean-Francois Bortolotti <jeff at borto.fr>
Reviewed-by: Sven Peter <sven at svenpeter.dev>
Co-developed-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 MAINTAINERS                          |   1 +
 drivers/spmi/Kconfig                 |   8 ++
 drivers/spmi/Makefile                |   1 +
 drivers/spmi/spmi-apple-controller.c | 168 +++++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 271ff8110df83c2d4fe7fbbfffc0a72259460bc5..9006695261d29fbc1e15659c2b43d7afeee0b656 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2254,6 +2254,7 @@ F:	drivers/nvmem/apple-efuses.c
 F:	drivers/pinctrl/pinctrl-apple-gpio.c
 F:	drivers/pwm/pwm-apple.c
 F:	drivers/soc/apple/*
+F:	drivers/spmi/spmi-apple-controller.c
 F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 73780204631463631cabcbad5bf83e8dbbee94ce..9005fa91d9f4e541403ccc7bf84e0592402ac41e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,14 @@ menuconfig SPMI
 
 if SPMI
 
+config SPMI_APPLE
+	tristate "Apple SoC SPMI Controller platform driver"
+	depends on ARCH_APPLE || COMPILE_TEST
+	help
+	  If you say yes to this option, support will be included for the
+	  SPMI controller present on many Apple SoCs, including the
+	  t8103 (M1) and t600x (M1 Pro/Max).
+
 config SPMI_HISI3670
 	tristate "Hisilicon 3670 SPMI Controller"
 	select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 7f152167bb05b2c24a0f9669f60278152898eebb..38ac635645ba65aa46cb5e8a50072ed9771e229b 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,6 +4,7 @@
 #
 obj-$(CONFIG_SPMI)	+= spmi.o spmi-devres.o
 
+obj-$(CONFIG_SPMI_APPLE)	+= spmi-apple-controller.o
 obj-$(CONFIG_SPMI_HISI3670)	+= hisi-spmi-controller.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
 obj-$(CONFIG_SPMI_MTK_PMIF)	+= spmi-mtk-pmif.o
diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c
new file mode 100644
index 0000000000000000000000000000000000000000..697b3e8bb023566f17911fc222666d84f5e14c91
--- /dev/null
+++ b/drivers/spmi/spmi-apple-controller.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple SoC SPMI device driver
+ *
+ * Copyright The Asahi Linux Contributors
+ *
+ * Inspired by:
+ *		OpenBSD support Copyright (c) 2021 Mark Kettenis <kettenis at openbsd.org>
+ *		Correllium support Copyright (C) 2021 Corellium LLC
+ *		hisi-spmi-controller.c
+ *		spmi-pmic-arb.c Copyright (c) 2021, The Linux Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+/* SPMI Controller Registers */
+#define SPMI_STATUS_REG 0
+#define SPMI_CMD_REG 0x4
+#define SPMI_RSP_REG 0x8
+
+#define SPMI_RX_FIFO_EMPTY BIT(24)
+
+#define REG_POLL_INTERVAL_US 10000
+#define REG_POLL_TIMEOUT_US (REG_POLL_INTERVAL_US * 5)
+
+struct apple_spmi {
+	void __iomem *regs;
+};
+
+#define poll_reg(spmi, reg, val, cond) \
+	readl_poll_timeout((spmi)->regs + (reg), (val), (cond), \
+			   REG_POLL_INTERVAL_US, REG_POLL_TIMEOUT_US)
+
+static inline u32 apple_spmi_pack_cmd(u8 opc, u8 sid, u16 saddr, size_t len)
+{
+	return opc | sid << 8 | saddr << 16 | (len - 1) | (1 << 15);
+}
+
+/* Wait for Rx FIFO to have something */
+static int apple_spmi_wait_rx_not_empty(struct spmi_controller *ctrl)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	int ret;
+	u32 status;
+
+	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
+	if (ret) {
+		dev_err(&ctrl->dev,
+			"failed to wait for RX FIFO not empty\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			 u16 saddr, u8 *buf, size_t len)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
+	u32 rsp;
+	size_t len_read = 0;
+	u8 i;
+	int ret;
+
+	writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
+
+	ret = apple_spmi_wait_rx_not_empty(ctrl);
+	if (ret)
+		return ret;
+
+	/* Discard SPMI reply status */
+	readl(spmi->regs + SPMI_RSP_REG);
+
+	/* Read SPMI data reply */
+	while (len_read < len) {
+		rsp = readl(spmi->regs + SPMI_RSP_REG);
+		i = 0;
+		while ((len_read < len) && (i < 4)) {
+			buf[len_read++] = ((0xff << (8 * i)) & rsp) >> (8 * i);
+			i += 1;
+		}
+	}
+
+	return 0;
+}
+
+static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			  u16 saddr, const u8 *buf, size_t len)
+{
+	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
+	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
+	size_t i = 0, j;
+	int ret;
+
+	writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
+
+	while (i < len) {
+		j = 0;
+		spmi_cmd = 0;
+		while ((j < 4) & (i < len))
+			spmi_cmd |= buf[i++] << (j++ * 8);
+
+		writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
+	}
+
+	ret = apple_spmi_wait_rx_not_empty(ctrl);
+	if (ret)
+		return ret;
+
+	/* Discard */
+	readl(spmi->regs + SPMI_RSP_REG);
+
+	return 0;
+}
+
+static int apple_spmi_probe(struct platform_device *pdev)
+{
+	struct apple_spmi *spmi;
+	struct spmi_controller *ctrl;
+	int ret;
+
+	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
+	if (IS_ERR(ctrl))
+		return -ENOMEM;
+
+	spmi = spmi_controller_get_drvdata(ctrl);
+
+	spmi->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(spmi->regs))
+		return PTR_ERR(spmi->regs);
+
+	ctrl->dev.of_node = pdev->dev.of_node;
+
+	ctrl->read_cmd = spmi_read_cmd;
+	ctrl->write_cmd = spmi_write_cmd;
+
+	ret = devm_spmi_controller_add(&pdev->dev, ctrl);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "spmi_controller_add failed\n");
+
+	return 0;
+}
+
+static const struct of_device_id apple_spmi_match_table[] = {
+	{ .compatible = "apple,spmi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, apple_spmi_match_table);
+
+static struct platform_driver apple_spmi_driver = {
+	.probe		= apple_spmi_probe,
+	.driver		= {
+		.name	= "apple-spmi",
+		.of_match_table = apple_spmi_match_table,
+	},
+};
+module_platform_driver(apple_spmi_driver);
+
+MODULE_AUTHOR("Jean-Francois Bortolotti <jeff at borto.fr>");
+MODULE_DESCRIPTION("Apple SoC SPMI driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1




From devnull+fnkl.kernel.gmail.com at kernel.org  Mon Mar 10 15:07:58 2025
From: devnull+fnkl.kernel.gmail.com at kernel.org (Sasha Finkelstein via B4 Relay)
Date: Mon, 10 Mar 2025 23:07:58 +0100
Subject: [PATCH v3 1/3] dt-bindings: spmi: Add Apple SPMI controller
In-Reply-To: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
References: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
Message-ID: <20250310-spmi-v3-1-92a82e7d9f0d@gmail.com>

From: Sasha Finkelstein <fnkl.kernel at gmail.com>

Add bindings for the SPMI controller present on most Apple SoCs

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Sven Peter <sven at svenpeter.dev>
Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
---
 .../devicetree/bindings/spmi/apple,spmi.yaml       | 49 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 50 insertions(+)

diff --git a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..16bd7eb2b7af2c0b176f0e5b1970f4670af691da
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SPMI controller
+
+maintainers:
+  - Sasha Finkelstein <fnkl.kernel at gmail.com>
+
+description: A SPMI controller present on most Apple SoCs
+
+allOf:
+  - $ref: spmi.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - apple,t8103-spmi
+          - apple,t6000-spmi
+          - apple,t8112-spmi
+      - const: apple,spmi
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+
+    spmi at 920a1300 {
+        compatible = "apple,t6000-spmi", "apple,spmi";
+        reg = <0x920a1300 0x100>;
+        #address-cells = <2>;
+        #size-cells = <0>;
+
+        pmic at f {
+            reg = <0xf SPMI_USID>;
+            /* PMIC-specific properties */
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0e33544fa373a4978b7dae18c040c..271ff8110df83c2d4fe7fbbfffc0a72259460bc5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2236,6 +2236,7 @@ F:	Documentation/devicetree/bindings/pci/apple,pcie.yaml
 F:	Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
 F:	Documentation/devicetree/bindings/power/apple*
 F:	Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
+F:	Documentation/devicetree/bindings/spmi/apple,spmi.yaml
 F:	Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
 F:	arch/arm64/boot/dts/apple/
 F:	drivers/bluetooth/hci_bcm4377.c

-- 
2.48.1




From mhklinux at outlook.com  Mon Mar 10 15:18:20 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 22:18:20 +0000
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
Message-ID: <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Arnd Bergmann <arnd at arndb.de> Sent: Monday, March 10, 2025 2:21 PM
> 
> On Mon, Mar 10, 2025, at 22:01, Michael Kelley wrote:
> > From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
> >> >  config HYPERV_VTL_MODE
> >> >  	bool "Enable Linux to boot in VTL context"
> >> > -	depends on X86_64 && HYPERV
> >> > +	depends on (X86_64 || ARM64)
> >> >  	depends on SMP
> >> > +	select OF_EARLY_FLATTREE
> >> > +	select OF
> >> >  	default n
> >> >  	help
> >>
> >> Having the dependency below the top-level Kconfig entry feels a little
> >> counterintuitive. You could flip that back as it was before by doing
> >>
> >>       select HYPERV_VTL_MODE if !ACPI
> >>       depends on ACPI || SMP
> >>
> >> in the HYPERV option, leaving the dependency on HYPERV in
> >> HYPERV_VTL_MODE.
> >
> > I would argue that we don't ever want to implicitly select
> > HYPERV_VTL_MODE because of some other config setting or
> > lack thereof.  VTL mode is enough of a special case that it should
> > only be explicitly selected. If someone omits ACPI, then HYPERV
> > should not be selectable unless HYPERV_VTL_MODE is explicitly
> > selected.
> >
> > The last line of the comment for HYPERV_VTL_MODE says
> > "A kernel built with this option must run at VTL2, and will not run
> > as a normal guest."  In other words, don't choose this unless you
> > 100% know that VTL2 is what you want.
> 
> It sounds like the latter is the real problem: enabling a feature
> should never prevent something else from working. Can you describe
> what VTL context is and why it requires an exception to a rather
> fundamental rule here? If you build a kernel that runs on every
> single piece of arm64 hardware and every hypervisor, why can't
> you add HYPERV_VTL_MODE to that as an option?
> 

VTL = Virtual Trust Level, and VSM = Virtual Secure Mode, are Hyper-V's
terminology for offering multiple execution environments with
hierarchical trust in the context of a single VM. A normal guest
operating system runs at VTL 0, and there are no other VTLs in use.
But in some environments, additional software may run as a paravisor
layer between the normal guest OS and the hypervisor. This software
runs at some other VTL > 0, and has a higher privilege level within
the VM than software running at VTL 0 (which is the lowest privilege).
VTL 2 is used today in the Azure cloud with CoCo VMs to run a
paravisor, and there may be other uses in the future. See [1] if you
want more details on VSM and VTLs. Also [2] for the CoCo VM use
case.

Ideally, a Linux kernel image could detect at runtime what VTL it is
running at, and "do the right thing". Unfortunately, on x86 Linux this
has proved difficult (or perhaps impossible) because the amount of
boot-time setup required to ask the question about the current VTL
is significant. The idiosyncrasies and historical baggage of x86 requires
that Linux do some x86-specific initialization steps for VTL > 0
before the question can be asked. Hence the introduction of
CONFIG_HYPERV_VTL_MODE, and the behavior that when it is
selected, the kernel image won't run normally in VTL 0.

I'll go out on a limb and say that I suspect on arm64 a runtime
determination based on querying the VTL *could* be made (though
I'm not the person writing the code). But taking advantage of that
on arm64 produces an undesirable dichotomy with x86.

Roman may have further thoughts on the topic, but that's
what I know about how we got here.

Michael

[1] https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm
[2] https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172


From mhklinux at outlook.com  Mon Mar 10 15:23:24 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 22:23:24 +0000
Subject: [PATCH v5 08/10] x86: hyperv: Add mshv_handler irq handler and
 setup function
In-Reply-To: <71a95f7d-d38b-4f4f-b384-9ad4095bd272@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-9-git-send-email-nunodasneves@linux.microsoft.com>
 <Z7-nDUe41XHyZ8RJ@skinsburskii.>
 <7de9b06d-9a32-48b5-beda-2e19b36ae9c9@linux.microsoft.com>
 <SN6PR02MB41573673D5F786E6C47FC08ED4D52@SN6PR02MB4157.namprd02.prod.outlook.com>
 <71a95f7d-d38b-4f4f-b384-9ad4095bd272@linux.microsoft.com>
Message-ID: <BN7PR02MB41484D4FC07F44033068A5A2D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Monday, March 10, 2025 2:47 PM
> 
> On 3/7/2025 9:38 AM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, February 28,
> 2025 4:38 PM
> >>
> >> On 2/26/2025 3:43 PM, Stanislav Kinsburskii wrote:
> >>> On Wed, Feb 26, 2025 at 03:08:02PM -0800, Nuno Das Neves wrote:
> >>>> This will handle SYNIC interrupts such as intercepts, doorbells, and
> >>>> scheduling messages intended for the mshv driver.
> >>>>
> >>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >>>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> >>>> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
> >>>> ---
> >>>>  arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
> >>>>  drivers/hv/hv_common.c         | 5 +++++
> >>>>  include/asm-generic/mshyperv.h | 1 +
> >>>>  3 files changed, 15 insertions(+)
> >>>>
> >>>> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> >>>> index 0116d0e96ef9..616e9a5d77b4 100644
> >>>> --- a/arch/x86/kernel/cpu/mshyperv.c
> >>>> +++ b/arch/x86/kernel/cpu/mshyperv.c
> >>>> @@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
> >>>>  }
> >>>>  EXPORT_SYMBOL_GPL(hv_set_msr);
> >>>>
> >>>> +static void (*mshv_handler)(void);
> >>>>  static void (*vmbus_handler)(void);
> >>>>  static void (*hv_stimer0_handler)(void);
> >>>>  static void (*hv_kexec_handler)(void);
> >>>> @@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
> >>>>  	struct pt_regs *old_regs = set_irq_regs(regs);
> >>>>
> >>>>  	inc_irq_stat(irq_hv_callback_count);
> >>>> +	if (mshv_handler)
> >>>> +		mshv_handler();
> >>>
> >>> Can mshv_handler be defined as a weak symbol doing nothing instead
> >>> of defining it a null pointer?
> >>> This should allow to simplify this code and get rid of
> >>> hv_setup_mshv_handler, which looks redundant.
> >>>
> >> Interesting, I tested this and it does seems to work! It seems like
> >> a good change, thanks.
> >
> > Just be a bit careful. When CONFIG_HYPERV=n, mshyperv.c still gets
> > built even through none of the other Hyper-V related files do.  There
> > are #ifdef CONFIG_HYPERV in mshyperv.c to eliminate references to
> > Hyper-V files that wouldn't be built. I'd suggest doing a test build with
> > that configuration to make sure it's all clean.
> >
> Thanks Michael - I don't think it would be an issue since the __weak version
> would be defined in mshyperv.c itself, replacing the function pointer.

Yes, sounds right to me.

> 
> However, I went and tested this __weak version again with CONFIG_MSHV_ROOT=m
> and it does not actually work. Everything seems ok at first (it compiles,
> can insert the module), but upon starting a guest, the interrupts don't get
> delivered to the root (or rather, they don't get handled by mshv_hander()).
> 
> This seems to match with what the ld docs say - There's an option
> LD_DYNAMIC_LINK to allow __weak symbols to be overridden by the dynamic
> linker, but this is not enabled in the kernel.
> 

Yeah, I recall learning the hard way that a symbol defined in a module doesn't
override a __weak symbol in the kernel image. At the time, I gave up and took
a different path, and didn't get as far as looking at 'ld' options like you did. :-)

Michael

From namhyung at kernel.org  Mon Mar 10 15:25:47 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 10 Mar 2025 15:25:47 -0700
Subject: [PATCH 1/1 next] perf libunwind: Fixup conversion
 perf_sample->user_regs to a pointer
In-Reply-To: <20250307153448.250871-1-acme@kernel.org>
References: <20250307153448.250871-1-acme@kernel.org>
Message-ID: <Z89m67GyL88ctvO7@google.com>

On Fri, Mar 07, 2025 at 12:34:48PM -0300, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <acme at redhat.com>
> 
> The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
> the changes to a file, resulting in this problem:
> 
>   $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
>   <SNIP>
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
>   <SNIP>
>   util/unwind-libunwind-local.c: In function ?access_mem?:
>   util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
>     582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
>         |                                                        ^
>         |                                                        ->
>   util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
>     587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
>         |                                      ^~~~~~~~~~~~~~~~~~~~~~
>         |                                      |
>         |                                      struct regs_dump **
> <SNIP>
>   ? [acme at toolbox perf-tools-next]$ git bisect bad
>   dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
>   commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
>   Author: Ian Rogers <irogers at google.com>
>   Date:   Mon Jan 13 11:43:45 2025 -0800
> 
>       perf sample: Make user_regs and intr_regs optional
> 
> Detected using:
> 
>   make -C tools/perf build-test
> 
> Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
> Cc: Adrian Hunter <adrian.hunter at intel.com>
> Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
> Cc: Andi Kleen <ak at linux.intel.com>
> Cc: Charlie Jenkins <charlie at rivosinc.com>
> Cc: Ian Rogers <irogers at google.com>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: James Clark <james.clark at linaro.org>
> Cc: John Garry <john.g.garry at oracle.com>
> Cc: Kan Liang <kan.liang at linux.intel.com>
> Cc: Leo Yan <leo.yan at linux.dev>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Michael Petlan <mpetlan at redhat.com>
> Cc: Namhyung Kim <namhyung at kernel.org>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Tavian Barnes <tavianator at tavianator.com>
> Cc: Veronika Molnarova <vmolnaro at redhat.com>
> Cc: coresight at lists.linaro.org
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>
> ---
>  tools/perf/util/unwind-libunwind-local.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
> index 16c2b03831f39afc..cc0e41f2c2f2ef10 100644
> --- a/tools/perf/util/unwind-libunwind-local.c
> +++ b/tools/perf/util/unwind-libunwind-local.c
> @@ -579,12 +579,12 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
>  	int ret;
>  
>  	/* Don't support write, probably not needed. */
> -	if (__write || !stack || !ui->sample->user_regs.regs) {
> +	if (__write || !stack || !ui->sample->user_regs->regs) {

The sample->user_regs can be NULL and I guess it's only allocated when
it has some regs.  Then probably it should be like:

	if (__write || !stack || !ui->sample->user_regs) {


>  		*valp = 0;
>  		return 0;
>  	}
>  
> -	ret = perf_reg_value(&start, &ui->sample->user_regs,
> +	ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample),
>  			     perf_arch_reg_sp(arch));
>  	if (ret)
>  		return ret;
> @@ -628,7 +628,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>  		return 0;
>  	}
>  
> -	if (!ui->sample->user_regs.regs) {
> +	if (!ui->sample->user_regs->regs) {

Ditto.


>  		*valp = 0;
>  		return 0;
>  	}
> @@ -637,7 +637,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>  	if (id < 0)
>  		return -EINVAL;
>  
> -	ret = perf_reg_value(&val, &ui->sample->user_regs, id);
> +	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id);
>  	if (ret) {
>  		if (!ui->best_effort)
>  			pr_err("unwind: can't read reg %d\n", regnum);
> @@ -741,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
>  	unw_cursor_t c;
>  	int ret, i = 0;
>  
> -	ret = perf_reg_value(&val, &ui->sample->user_regs,
> +	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample),
>  			     perf_arch_reg_ip(arch));
>  	if (ret)
>  		return ret;
> @@ -808,7 +808,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
>  		.best_effort  = best_effort
>  	};
>  
> -	if (!data->user_regs.regs)
> +	if (!data->user_regs->regs)

Ditto.

Thanks,
Namhyung


>  		return -EINVAL;
>  
>  	if (max_stack <= 0)
> -- 
> 2.47.0
> 


From samitolvanen at google.com  Mon Mar 10 15:29:43 2025
From: samitolvanen at google.com (Sami Tolvanen)
Date: Mon, 10 Mar 2025 22:29:43 +0000
Subject: [PATCH bpf-next v8 0/2] Support kCFI + BPF on arm64
Message-ID: <20250310222942.1988975-4-samitolvanen@google.com>

Hi folks,

These patches add KCFI types to arm64 BPF JIT output. Puranjay and
Maxwell have been working on this for some time now, but I haven't
seen any progress since June 2024, so I decided to pick up the latest
version[1] posted by Maxwell and fix the few remaining issues I
noticed. I confirmed that with these patches applied, I no longer see
CFI failures when running BPF self-tests on arm64.

[1] https://lore.kernel.org/linux-arm-kernel/ptrugmna4xb5o5lo4xislf4rlz7avdmd4pfho5fjwtjj7v422u at iqrwfrbwuxrq/

Sami

---

v8:
- Changed DEFINE_CFI_TYPE to use .4byte to match __CFI_TYPE.
- Changed cfi_get_func_hash() to again use get_kernel_nofault().
- Fixed a panic in bpf_jit_free() by resetting prog->bpf_func before
  calling bpf_jit_binary_pack_hdr().

---

Mark Rutland (1):
  cfi: add C CFI type macro

Puranjay Mohan (1):
  arm64/cfi,bpf: Support kCFI + BPF on arm64

 arch/arm64/include/asm/cfi.h    | 23 ++++++++++++++++++++++
 arch/arm64/kernel/alternative.c | 25 +++++++++++++++++++++++
 arch/arm64/net/bpf_jit_comp.c   | 22 ++++++++++++++++++---
 arch/riscv/kernel/cfi.c         | 35 +++------------------------------
 arch/x86/kernel/alternative.c   | 35 +++------------------------------
 include/linux/cfi_types.h       | 23 ++++++++++++++++++++++
 6 files changed, 96 insertions(+), 67 deletions(-)
 create mode 100644 arch/arm64/include/asm/cfi.h

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From samitolvanen at google.com  Mon Mar 10 15:29:44 2025
From: samitolvanen at google.com (Sami Tolvanen)
Date: Mon, 10 Mar 2025 22:29:44 +0000
Subject: [PATCH bpf-next v8 1/2] cfi: add C CFI type macro
In-Reply-To: <20250310222942.1988975-4-samitolvanen@google.com>
References: <20250310222942.1988975-4-samitolvanen@google.com>
Message-ID: <20250310222942.1988975-5-samitolvanen@google.com>

From: Mark Rutland <mark.rutland at arm.com>

Currently x86 and riscv open-code 4 instances of the same logic to
define a u32 variable with the KCFI typeid of a given function.

Replace the duplicate logic with a common macro.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Co-Developed-by: Maxwell Bland <mbland at motorola.com>
Signed-off-by: Maxwell Bland <mbland at motorola.com>
Co-Developed-by: Sami Tolvanen <samitolvanen at google.com>
Signed-off-by: Sami Tolvanen <samitolvanen at google.com>
---
 arch/riscv/kernel/cfi.c       | 35 +++--------------------------------
 arch/x86/kernel/alternative.c | 35 +++--------------------------------
 include/linux/cfi_types.h     | 23 +++++++++++++++++++++++
 3 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/arch/riscv/kernel/cfi.c b/arch/riscv/kernel/cfi.c
index 64bdd3e1ab8c..e7aec5f36dd5 100644
--- a/arch/riscv/kernel/cfi.c
+++ b/arch/riscv/kernel/cfi.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2023 Google LLC
  */
+#include <linux/cfi_types.h>
 #include <linux/cfi.h>
 #include <asm/insn.h>
 
@@ -82,41 +83,11 @@ struct bpf_insn;
 /* Must match bpf_func_t / DEFINE_BPF_PROG_RUN() */
 extern unsigned int __bpf_prog_runX(const void *ctx,
 				    const struct bpf_insn *insn);
-
-/*
- * Force a reference to the external symbol so the compiler generates
- * __kcfi_typid.
- */
-__ADDRESSABLE(__bpf_prog_runX);
-
-/* u32 __ro_after_init cfi_bpf_hash = __kcfi_typeid___bpf_prog_runX; */
-asm (
-"	.pushsection	.data..ro_after_init,\"aw\", at progbits	\n"
-"	.type	cfi_bpf_hash, at object				\n"
-"	.globl	cfi_bpf_hash					\n"
-"	.p2align	2, 0x0					\n"
-"cfi_bpf_hash:							\n"
-"	.word	__kcfi_typeid___bpf_prog_runX			\n"
-"	.size	cfi_bpf_hash, 4					\n"
-"	.popsection						\n"
-);
+DEFINE_CFI_TYPE(cfi_bpf_hash, __bpf_prog_runX);
 
 /* Must match bpf_callback_t */
 extern u64 __bpf_callback_fn(u64, u64, u64, u64, u64);
-
-__ADDRESSABLE(__bpf_callback_fn);
-
-/* u32 __ro_after_init cfi_bpf_subprog_hash = __kcfi_typeid___bpf_callback_fn; */
-asm (
-"	.pushsection	.data..ro_after_init,\"aw\", at progbits	\n"
-"	.type	cfi_bpf_subprog_hash, at object			\n"
-"	.globl	cfi_bpf_subprog_hash				\n"
-"	.p2align	2, 0x0					\n"
-"cfi_bpf_subprog_hash:						\n"
-"	.word	__kcfi_typeid___bpf_callback_fn			\n"
-"	.size	cfi_bpf_subprog_hash, 4				\n"
-"	.popsection						\n"
-);
+DEFINE_CFI_TYPE(cfi_bpf_subprog_hash, __bpf_callback_fn);
 
 u32 cfi_get_func_hash(void *func)
 {
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index c71b575bf229..a9f415e873dd 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #define pr_fmt(fmt) "SMP alternatives: " fmt
 
+#include <linux/cfi_types.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/perf_event.h>
@@ -934,41 +935,11 @@ struct bpf_insn;
 /* Must match bpf_func_t / DEFINE_BPF_PROG_RUN() */
 extern unsigned int __bpf_prog_runX(const void *ctx,
 				    const struct bpf_insn *insn);
-
-/*
- * Force a reference to the external symbol so the compiler generates
- * __kcfi_typid.
- */
-__ADDRESSABLE(__bpf_prog_runX);
-
-/* u32 __ro_after_init cfi_bpf_hash = __kcfi_typeid___bpf_prog_runX; */
-asm (
-"	.pushsection	.data..ro_after_init,\"aw\", at progbits	\n"
-"	.type	cfi_bpf_hash, at object				\n"
-"	.globl	cfi_bpf_hash					\n"
-"	.p2align	2, 0x0					\n"
-"cfi_bpf_hash:							\n"
-"	.long	__kcfi_typeid___bpf_prog_runX			\n"
-"	.size	cfi_bpf_hash, 4					\n"
-"	.popsection						\n"
-);
+DEFINE_CFI_TYPE(cfi_bpf_hash, __bpf_prog_runX);
 
 /* Must match bpf_callback_t */
 extern u64 __bpf_callback_fn(u64, u64, u64, u64, u64);
-
-__ADDRESSABLE(__bpf_callback_fn);
-
-/* u32 __ro_after_init cfi_bpf_subprog_hash = __kcfi_typeid___bpf_callback_fn; */
-asm (
-"	.pushsection	.data..ro_after_init,\"aw\", at progbits	\n"
-"	.type	cfi_bpf_subprog_hash, at object			\n"
-"	.globl	cfi_bpf_subprog_hash				\n"
-"	.p2align	2, 0x0					\n"
-"cfi_bpf_subprog_hash:						\n"
-"	.long	__kcfi_typeid___bpf_callback_fn			\n"
-"	.size	cfi_bpf_subprog_hash, 4				\n"
-"	.popsection						\n"
-);
+DEFINE_CFI_TYPE(cfi_bpf_subprog_hash, __bpf_callback_fn);
 
 u32 cfi_get_func_hash(void *func)
 {
diff --git a/include/linux/cfi_types.h b/include/linux/cfi_types.h
index 6b8713675765..209c8a16ac4e 100644
--- a/include/linux/cfi_types.h
+++ b/include/linux/cfi_types.h
@@ -41,5 +41,28 @@
 	SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
 #endif
 
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_CFI_CLANG
+#define DEFINE_CFI_TYPE(name, func)						\
+	/*									\
+	 * Force a reference to the function so the compiler generates		\
+	 * __kcfi_typeid_<func>.						\
+	 */									\
+	__ADDRESSABLE(func);							\
+	/* u32 name = __kcfi_typeid_<func> */					\
+	extern u32 name;							\
+	asm (									\
+	"	.pushsection	.data..ro_after_init,\"aw\", at progbits	\n"	\
+	"	.type	" #name ", at object				\n"	\
+	"	.globl	" #name "					\n"	\
+	"	.p2align	2, 0x0					\n"	\
+	#name ":							\n"	\
+	"	.4byte	__kcfi_typeid_" #func "				\n"	\
+	"	.size	" #name ", 4					\n"	\
+	"	.popsection						\n"	\
+	);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* _LINUX_CFI_TYPES_H */
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From samitolvanen at google.com  Mon Mar 10 15:29:45 2025
From: samitolvanen at google.com (Sami Tolvanen)
Date: Mon, 10 Mar 2025 22:29:45 +0000
Subject: [PATCH bpf-next v8 2/2] arm64/cfi,bpf: Support kCFI + BPF on arm64
In-Reply-To: <20250310222942.1988975-4-samitolvanen@google.com>
References: <20250310222942.1988975-4-samitolvanen@google.com>
Message-ID: <20250310222942.1988975-6-samitolvanen@google.com>

From: Puranjay Mohan <puranjay12 at gmail.com>

Currently, bpf_dispatcher_*_func() is marked with `__nocfi` therefore
calling BPF programs from this interface doesn't cause CFI warnings.

When BPF programs are called directly from C: from BPF helpers or
struct_ops, CFI warnings are generated.

Implement proper CFI prologues for the BPF programs and callbacks and
drop __nocfi for arm64. Fix the trampoline generation code to emit kCFI
prologue when a struct_ops trampoline is being prepared.

Signed-off-by: Puranjay Mohan <puranjay12 at gmail.com>
Co-Developed-by: Maxwell Bland <mbland at motorola.com>
Signed-off-by: Maxwell Bland <mbland at motorola.com>
Co-Developed-by: Sami Tolvanen <samitolvanen at google.com>
Signed-off-by: Sami Tolvanen <samitolvanen at google.com>
---
 arch/arm64/include/asm/cfi.h    | 23 +++++++++++++++++++++++
 arch/arm64/kernel/alternative.c | 25 +++++++++++++++++++++++++
 arch/arm64/net/bpf_jit_comp.c   | 22 +++++++++++++++++++---
 3 files changed, 67 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm64/include/asm/cfi.h

diff --git a/arch/arm64/include/asm/cfi.h b/arch/arm64/include/asm/cfi.h
new file mode 100644
index 000000000000..670e191f8628
--- /dev/null
+++ b/arch/arm64/include/asm/cfi.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_CFI_H
+#define _ASM_ARM64_CFI_H
+
+#ifdef CONFIG_CFI_CLANG
+#define __bpfcall
+static inline int cfi_get_offset(void)
+{
+	return 4;
+}
+#define cfi_get_offset cfi_get_offset
+extern u32 cfi_bpf_hash;
+extern u32 cfi_bpf_subprog_hash;
+extern u32 cfi_get_func_hash(void *func);
+#else
+#define cfi_bpf_hash 0U
+#define cfi_bpf_subprog_hash 0U
+static inline u32 cfi_get_func_hash(void *func)
+{
+	return 0;
+}
+#endif /* CONFIG_CFI_CLANG */
+#endif /* _ASM_ARM64_CFI_H */
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
index 8ff6610af496..71c153488dad 100644
--- a/arch/arm64/kernel/alternative.c
+++ b/arch/arm64/kernel/alternative.c
@@ -8,11 +8,13 @@
 
 #define pr_fmt(fmt) "alternatives: " fmt
 
+#include <linux/cfi_types.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/elf.h>
 #include <asm/cacheflush.h>
 #include <asm/alternative.h>
+#include <asm/cfi.h>
 #include <asm/cpufeature.h>
 #include <asm/insn.h>
 #include <asm/module.h>
@@ -298,3 +300,26 @@ noinstr void alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr,
 		updptr[i] = cpu_to_le32(aarch64_insn_gen_nop());
 }
 EXPORT_SYMBOL(alt_cb_patch_nops);
+
+#ifdef CONFIG_CFI_CLANG
+struct bpf_insn;
+
+/* Must match bpf_func_t / DEFINE_BPF_PROG_RUN() */
+extern unsigned int __bpf_prog_runX(const void *ctx,
+				    const struct bpf_insn *insn);
+DEFINE_CFI_TYPE(cfi_bpf_hash, __bpf_prog_runX);
+
+/* Must match bpf_callback_t */
+extern u64 __bpf_callback_fn(u64, u64, u64, u64, u64);
+DEFINE_CFI_TYPE(cfi_bpf_subprog_hash, __bpf_callback_fn);
+
+u32 cfi_get_func_hash(void *func)
+{
+	u32 hash;
+
+	if (get_kernel_nofault(hash, func - cfi_get_offset()))
+		return 0;
+
+	return hash;
+}
+#endif /* CONFIG_CFI_CLANG */
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 70d7c89d3ac9..8870c205f934 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -17,6 +17,7 @@
 #include <asm/asm-extable.h>
 #include <asm/byteorder.h>
 #include <asm/cacheflush.h>
+#include <asm/cfi.h>
 #include <asm/debug-monitors.h>
 #include <asm/insn.h>
 #include <asm/text-patching.h>
@@ -164,6 +165,12 @@ static inline void emit_bti(u32 insn, struct jit_ctx *ctx)
 		emit(insn, ctx);
 }
 
+static inline void emit_kcfi(u32 hash, struct jit_ctx *ctx)
+{
+	if (IS_ENABLED(CONFIG_CFI_CLANG))
+		emit(hash, ctx);
+}
+
 /*
  * Kernel addresses in the vmalloc space use at most 48 bits, and the
  * remaining bits are guaranteed to be 0x1. So we can compose the address
@@ -474,7 +481,6 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
 	const bool is_main_prog = !bpf_is_subprog(prog);
 	const u8 fp = bpf2a64[BPF_REG_FP];
 	const u8 arena_vm_base = bpf2a64[ARENA_VM_START];
-	const int idx0 = ctx->idx;
 	int cur_offset;
 
 	/*
@@ -500,6 +506,9 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
 	 *
 	 */
 
+	emit_kcfi(is_main_prog ? cfi_bpf_hash : cfi_bpf_subprog_hash, ctx);
+	const int idx0 = ctx->idx;
+
 	/* bpf function may be invoked by 3 instruction types:
 	 * 1. bl, attached via freplace to bpf prog via short jump
 	 * 2. br, attached via freplace to bpf prog via long jump
@@ -2009,9 +2018,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 		jit_data->ro_header = ro_header;
 	}
 
-	prog->bpf_func = (void *)ctx.ro_image;
+	prog->bpf_func = (void *)ctx.ro_image + cfi_get_offset();
 	prog->jited = 1;
-	prog->jited_len = prog_size;
+	prog->jited_len = prog_size - cfi_get_offset();
 
 	if (!prog->is_func || extra_pass) {
 		int i;
@@ -2271,6 +2280,12 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
 	/* return address locates above FP */
 	retaddr_off = stack_size + 8;
 
+	if (flags & BPF_TRAMP_F_INDIRECT) {
+		/*
+		 * Indirect call for bpf_struct_ops
+		 */
+		emit_kcfi(cfi_get_func_hash(func_addr), ctx);
+	}
 	/* bpf trampoline may be invoked by 3 instruction types:
 	 * 1. bl, attached to bpf prog or kernel function via short jump
 	 * 2. br, attached to bpf prog or kernel function via long jump
@@ -2790,6 +2805,7 @@ void bpf_jit_free(struct bpf_prog *prog)
 					   sizeof(jit_data->header->size));
 			kfree(jit_data);
 		}
+		prog->bpf_func -= cfi_get_offset();
 		hdr = bpf_jit_binary_pack_hdr(prog);
 		bpf_jit_binary_pack_free(hdr, NULL);
 		WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(prog));
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From mhklinux at outlook.com  Mon Mar 10 16:07:09 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 23:07:09 +0000
Subject: [PATCH hyperv-next v5 05/11] arm64: hyperv: Initialize the
 Virtual Trust Level field
In-Reply-To: <20250307220304.247725-6-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-6-romank@linux.microsoft.com>
Message-ID: <SN6PR02MB4157DD69C232F25FDBA7594CD4D62@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> Various parts of the hyperv code need to know what VTL
> the kernel runs at, most notably VMBus needs that to
> establish communication with the host.
> 
> Initialize the Virtual Trust Level field to enable
> booting in the Virtual Trust Level.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  arch/arm64/hyperv/mshyperv.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index c647db56fd6b..a7db03f5413d 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -107,6 +107,7 @@ static int __init hyperv_init(void)
> 
>  	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
>  		hv_get_partition_id();
> +	ms_hyperv.vtl = get_vtl();
> 
>  	ms_hyperv_late_init();
> 
> --
> 2.43.0
> 

Reviewed-by: Michael Kelley <mhklinux at outlook.com>



From mhklinux at outlook.com  Mon Mar 10 16:09:34 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 23:09:34 +0000
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ
 number from DeviceTree
In-Reply-To: <20250307220304.247725-9-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-9-romank@linux.microsoft.com>
Message-ID: <SN6PR02MB415732A17E3EE6A4966B853ED4D62@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> The VMBus driver uses ACPI for interrupt assignment on
> arm64 hence it won't function in the VTL mode where only
> DeviceTree can be used.
> 
> Update the VMBus driver to discover interrupt configuration
> from DT.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> ---
>  drivers/hv/vmbus_drv.c | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 75eb1390b45c..c8474b48dcd2 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -2345,6 +2345,36 @@ static int vmbus_acpi_add(struct platform_device *pdev)
>  }
>  #endif
> 
> +static int __maybe_unused vmbus_set_irq(struct platform_device *pdev)
> +{
> +	struct irq_data *data;
> +	int irq;
> +	irq_hw_number_t hwirq;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq == 0) {
> +		pr_err("VMBus interrupt mapping failure\n");
> +		return -EINVAL;
> +	}
> +	if (irq < 0) {
> +		pr_err("VMBus interrupt data can't be read from DeviceTree, error %d\n", irq);
> +		return irq;
> +	}
> +
> +	data = irq_get_irq_data(irq);
> +	if (!data) {
> +		pr_err("No interrupt data for VMBus virq %d\n", irq);
> +		return -ENODEV;
> +	}
> +	hwirq = irqd_to_hwirq(data);
> +
> +	vmbus_irq = irq;
> +	vmbus_interrupt = hwirq;
> +	pr_debug("VMBus virq %d, hwirq %d\n", vmbus_irq, vmbus_interrupt);
> +
> +	return 0;
> +}
> +
>  static int vmbus_device_add(struct platform_device *pdev)
>  {
>  	struct resource **cur_res = &hyperv_mmio;
> @@ -2359,6 +2389,12 @@ static int vmbus_device_add(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
> 
> +#ifndef HYPERVISOR_CALLBACK_VECTOR
> +	ret = vmbus_set_irq(pdev);
> +	if (ret)
> +		return ret;
> +#endif
> +
>  	for_each_of_range(&parser, &range) {
>  		struct resource *res;
> 
> --
> 2.43.0
> 

Modulo Arnd's suggestion for avoiding the #ifndef, 

Reviewed-by: Michael Kelley <mhklinux at outlook.com>



From mhklinux at outlook.com  Mon Mar 10 16:12:19 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 23:12:19 +0000
Subject: [PATCH hyperv-next v5 09/11] Drivers: hv: vmbus: Introduce
 hv_get_vmbus_root_device()
In-Reply-To: <20250307220304.247725-10-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-10-romank@linux.microsoft.com>
Message-ID: <SN6PR02MB415757163CDEC267B0CBB3E4D4D62@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> The ARM64 PCI code for hyperv needs to know the VMBus root
> device, and it is private.
> 
> Provide a function that returns it. Rename it from "hv_dev"
> as "hv_dev" as a symbol is very overloaded. No functional
> changes.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>

Reviewed-by: Michael Kelley <mhklinux at outlook.com>

> ---
>  drivers/hv/vmbus_drv.c | 23 +++++++++++++++--------
>  include/linux/hyperv.h |  2 ++
>  2 files changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index c8474b48dcd2..7bfafe702963 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -45,7 +45,8 @@ struct vmbus_dynid {
>  	struct hv_vmbus_device_id id;
>  };
> 
> -static struct device  *hv_dev;
> +/* VMBus Root Device */
> +static struct device  *vmbus_root_device;
> 
>  static int hyperv_cpuhp_online;
> 
> @@ -80,9 +81,15 @@ static struct resource *fb_mmio;
>  static struct resource *hyperv_mmio;
>  static DEFINE_MUTEX(hyperv_mmio_lock);
> 
> +struct device *hv_get_vmbus_root_device(void)
> +{
> +	return vmbus_root_device;
> +}
> +EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
> +
>  static int vmbus_exists(void)
>  {
> -	if (hv_dev == NULL)
> +	if (vmbus_root_device == NULL)
>  		return -ENODEV;
> 
>  	return 0;
> @@ -861,7 +868,7 @@ static int vmbus_dma_configure(struct device *child_device)
>  	 * On x86/x64 coherence is assumed and these calls have no effect.
>  	 */
>  	hv_setup_dma_ops(child_device,
> -		device_get_dma_attr(hv_dev) == DEV_DMA_COHERENT);
> +		device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
>  	return 0;
>  }
> 
> @@ -1930,7 +1937,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
>  		     &child_device_obj->channel->offermsg.offer.if_instance);
> 
>  	child_device_obj->device.bus = &hv_bus;
> -	child_device_obj->device.parent = hv_dev;
> +	child_device_obj->device.parent = vmbus_root_device;
>  	child_device_obj->device.release = vmbus_device_release;
> 
>  	child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
> @@ -2292,7 +2299,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
>  	struct acpi_device *ancestor;
>  	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
> 
> -	hv_dev = &device->dev;
> +	vmbus_root_device = &device->dev;
> 
>  	/*
>  	 * Older versions of Hyper-V for ARM64 fail to include the _CCA
> @@ -2383,7 +2390,7 @@ static int vmbus_device_add(struct platform_device *pdev)
>  	struct device_node *np = pdev->dev.of_node;
>  	int ret;
> 
> -	hv_dev = &pdev->dev;
> +	vmbus_root_device = &pdev->dev;
> 
>  	ret = of_range_parser_init(&parser, np);
>  	if (ret)
> @@ -2702,7 +2709,7 @@ static int __init hv_acpi_init(void)
>  	if (ret)
>  		return ret;
> 
> -	if (!hv_dev) {
> +	if (!vmbus_root_device) {
>  		ret = -ENODEV;
>  		goto cleanup;
>  	}
> @@ -2733,7 +2740,7 @@ static int __init hv_acpi_init(void)
> 
>  cleanup:
>  	platform_driver_unregister(&vmbus_platform_driver);
> -	hv_dev = NULL;
> +	vmbus_root_device = NULL;
>  	return ret;
>  }
> 
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 7f4f8d8bdf43..1f0851fde041 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1333,6 +1333,8 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
>  	return dev_get_drvdata(&dev->device);
>  }
> 
> +struct device *hv_get_vmbus_root_device(void);
> +
>  struct hv_ring_buffer_debug_info {
>  	u32 current_interrupt_mask;
>  	u32 current_read_index;
> --
> 2.43.0
> 



From mhklinux at outlook.com  Mon Mar 10 16:26:28 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 23:26:28 +0000
Subject: [PATCH hyperv-next v5 10/11] ACPI: irq: Introduce
 acpi_get_gsi_dispatcher()
In-Reply-To: <20250307220304.247725-11-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-11-romank@linux.microsoft.com>
Message-ID: <SN6PR02MB41570D82338A45E13B7A3689D4D62@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> Using acpi_irq_create_hierarchy() in the cases where the code
> also handles OF leads to code duplication as the ACPI subsystem
> doesn't provide means to compute the IRQ domain parent whereas
> the OF does.
> 
> Introduce acpi_get_gsi_dispatcher() so that the drivers relying
> on both ACPI and OF may use irq_domain_create_hierarchy() in the
> common code paths.
> 
> No functional changes.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  drivers/acpi/irq.c   | 14 ++++++++++++--
>  include/linux/acpi.h |  5 ++++-
>  2 files changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index 1687483ff319..6243db610137 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -12,7 +12,7 @@
> 
>  enum acpi_irq_model_id acpi_irq_model;
> 
> -static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi);
> +static acpi_gsi_domain_disp_fn acpi_get_gsi_domain_id;
>  static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi);
> 
>  /**
> @@ -307,12 +307,22 @@ EXPORT_SYMBOL_GPL(acpi_irq_get);
>   *	for a given GSI
>   */
>  void __init acpi_set_irq_model(enum acpi_irq_model_id model,
> -			       struct fwnode_handle *(*fn)(u32))
> +	acpi_gsi_domain_disp_fn fn)
>  {
>  	acpi_irq_model = model;
>  	acpi_get_gsi_domain_id = fn;
>  }
> 
> +/**
> + * acpi_get_gsi_dispatcher - Returns dispatcher function that
> + *                           computes the domain fwnode for a
> + *                           given GSI.
> + */
> +acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void)
> +{
> +	return acpi_get_gsi_domain_id;
> +}

This new function is needed by pci-hyperv.c. It will
need to be marked as EXPORT_SYMBOL_GPL since
pci-hyperv.c can be built as a module.

> +
>  /**
>   * acpi_set_gsi_to_irq_fallback - Register a GSI transfer
>   * callback to fallback to arch specified implementation.
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 4e495b29c640..abc51288e867 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -336,8 +336,11 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int
> polarity
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> 
> +typedef struct fwnode_handle *(*acpi_gsi_domain_disp_fn)(u32);
> +
>  void acpi_set_irq_model(enum acpi_irq_model_id model,
> -			struct fwnode_handle *(*)(u32));
> +	acpi_gsi_domain_disp_fn fn);
> +acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void);
>  void acpi_set_gsi_to_irq_fallback(u32 (*)(u32));
> 
>  struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
> --
> 2.43.0
> 

I'm not at all expert in ACPI code and IRQ domains, but the changes
here look reasonable to me. Modulo adding the EXPORT_SYMBOL_GPL,

Reviewed-by: Michael Kelley <mhklinux at outlook.com>


From mhklinux at outlook.com  Mon Mar 10 16:42:02 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 10 Mar 2025 23:42:02 +0000
Subject: [PATCH hyperv-next v5 11/11] PCI: hv: Get vPCI MSI IRQ domain
 from DeviceTree
In-Reply-To: <20250307220304.247725-12-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-12-romank@linux.microsoft.com>
Message-ID: <SN6PR02MB4157FB49E2120B206294D439D4D62@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Friday, March 7, 2025 2:03 PM
> 
> The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
> arm64. It won't be able to do that in the VTL mode where only DeviceTree
> can be used.
> 
> Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
> case, too.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  drivers/pci/controller/pci-hyperv.c | 79 ++++++++++++++++++++++++++---
>  1 file changed, 73 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
> index 6084b38bdda1..9740006a8c73 100644
> --- a/drivers/pci/controller/pci-hyperv.c
> +++ b/drivers/pci/controller/pci-hyperv.c
> @@ -50,6 +50,7 @@
>  #include <linux/irqdomain.h>
>  #include <linux/acpi.h>
>  #include <linux/sizes.h>
> +#include <linux/of_irq.h>
>  #include <asm/mshyperv.h>
> 
>  /*
> @@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
>  	int ret;
> 
>  	fwspec.fwnode = domain->parent->fwnode;
> -	fwspec.param_count = 2;
> -	fwspec.param[0] = hwirq;
> -	fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +	if (is_of_node(fwspec.fwnode)) {
> +		/* SPI lines for OF translations start at offset 32 */
> +		fwspec.param_count = 3;
> +		fwspec.param[0] = 0;
> +		fwspec.param[1] = hwirq - 32;
> +		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> +	} else {
> +		fwspec.param_count = 2;
> +		fwspec.param[0] = hwirq;
> +		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +	}
> 
>  	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
>  	if (ret)
> @@ -887,10 +896,53 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
>  	.activate = hv_pci_vec_irq_domain_activate,
>  };
> 
> +#ifdef CONFIG_OF
> +
> +static struct irq_domain *hv_pci_of_irq_domain_parent(void)
> +{
> +	struct device_node *parent;
> +	struct irq_domain *domain;
> +
> +	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
> +	domain = NULL;
> +	if (parent) {
> +		domain = irq_find_host(parent);
> +		of_node_put(parent);
> +	}
> +
> +	return domain;
> +}

You could insert the following and avoid the #ifdef's in hv_pci_irqchip_init():

#else
static struct irq_domain *hv_pci_of_irq_domain_parent(void) {return NULL;}

> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +
> +static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
> +{
> +	struct irq_domain *domain;
> +	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
> +
> +	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
> +		return NULL;
> +	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
> +	if (!gsi_domain_disp_fn)
> +		return NULL;
> +	domain = irq_find_matching_fwnode(gsi_domain_disp_fn(0),
> +				     DOMAIN_BUS_ANY);
> +
> +	if (!domain)
> +		return NULL;
> +
> +	return domain;
> +}

Same here:

#else
static struct irq_domain *hv_pci_acpi_irq_domain_parent(void) {return NULL;}

I don't know if it's better or not. Just a suggestion -- keep what you have if
you prefer.

> +
> +#endif
> +
>  static int hv_pci_irqchip_init(void)
>  {
>  	static struct hv_pci_chip_data *chip_data;
>  	struct fwnode_handle *fn = NULL;
> +	struct irq_domain *irq_domain_parent = NULL;
>  	int ret = -ENOMEM;
> 
>  	chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
> @@ -907,9 +959,24 @@ static int hv_pci_irqchip_init(void)
>  	 * way to ensure that all the corresponding devices are also gone and
>  	 * no interrupts will be generated.
>  	 */
> -	hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
> -							  fn, &hv_pci_domain_ops,
> -							  chip_data);
> +#ifdef CONFIG_ACPI
> +	if (!acpi_disabled)
> +		irq_domain_parent = hv_pci_acpi_irq_domain_parent();
> +#endif
> +#if defined(CONFIG_OF)
> +	if (!irq_domain_parent)
> +		irq_domain_parent = hv_pci_of_irq_domain_parent();
> +#endif
> +	if (!irq_domain_parent) {
> +		WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
> +		ret = -EINVAL;
> +		goto free_chip;
> +	}
> +
> +	hv_msi_gic_irq_domain = irq_domain_create_hierarchy(
> +		irq_domain_parent, 0, HV_PCI_MSI_SPI_NR,
> +		fn, &hv_pci_domain_ops,
> +		chip_data);
> 
>  	if (!hv_msi_gic_irq_domain) {
>  		pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
> --
> 2.43.0
> 

Overall, I think the code looks right, though I'm not an expert in this area. I'll
give my Reviewed-by: once Bjorn's coding suggestions are incorporated.

Michael


From kevin_chen at aspeedtech.com  Mon Mar 10 17:17:46 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 11 Mar 2025 00:17:46 +0000
Subject: [PATCH v2 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <58466532-3e17-4968-bade-210f478ccc76@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-4-kevin_chen@aspeedtech.com>
 <2fd83d68-7104-4755-a0f0-8ce4a2601e09@kernel.org>
 <TY0PR06MB496072786197162F19ED7DDD89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
 <58466532-3e17-4968-bade-210f478ccc76@kernel.org>
Message-ID: <PSAPR06MB494913DA3070724B76606F6C89D12@PSAPR06MB4949.apcprd06.prod.outlook.com>

> >> On 04/03/2025 11:44, Kevin Chen wrote:
> >>> +
> >>> +static int aspeed_pcc_probe(struct platform_device *pdev) {
> >>> +	int rc;
> >>> +	struct aspeed_pcc_ctrl *pcc;
> >>> +	struct device *dev;
> >>> +	uint32_t fifo_size = PAGE_SIZE;
> >>> +
> >>> +	dev = &pdev->dev;
> >>
> >> This goes to declaration.
> > OK. I will move it to declaration.
> >
> >>
> >>> +
> >>> +	pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL);
> >>
> >> Maybe my previous comment was not clear, but you agreed with it.
> >> Anyway nothing improved here.
> > Could I reserve the pcc variable using for the pcc_ctrl data structure?
> > Pcc_ctrl data include the regmap/irq/io_port/dma/kfifo.
> > If I change the name to dev, it does not make sense for these data to be.
> >
> >>
> >> If you have 'dev' variable, use it.
> > Do you mean just use the pdev->dev not local dev variable?
> What is the point of this:
> dev = &pdev->dev;
> 
> if you do not use 'dev'? If you come with a reason, sure. If you do not have such,
> then everything should use 'dev', not pdev->dev.
Agree, I fixed it in my v3 patch, and I already submitted.
Thanks for your detailed explanation.
Sorry for my misunderstanding.

> 
> Best regards,
> Krzysztof

From kevin_chen at aspeedtech.com  Mon Mar 10 17:22:18 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Tue, 11 Mar 2025 00:22:18 +0000
Subject: [PATCH v2 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <a12afc26-2e8e-42cc-ac68-27ba8906707f@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-2-kevin_chen@aspeedtech.com>
 <8740eeb8-9467-48bb-a911-e70c3da3c45a@kernel.org>
 <PSAPR06MB494973DC08A8105EA05FBE6D89D62@PSAPR06MB4949.apcprd06.prod.outlook.com>
 <e17cdf9d-ba96-41d2-9656-9e50d0e0795a@kernel.org>
 <TY0PR06MB496045B19DCB149EC902D0FF89D62@TY0PR06MB4960.apcprd06.prod.outlook.com>
 <a12afc26-2e8e-42cc-ac68-27ba8906707f@kernel.org>
Message-ID: <PSAPR06MB49493E890869FE5B3650A7AB89D12@PSAPR06MB4949.apcprd06.prod.outlook.com>

> On 10/03/2025 10:49, Kevin Chen wrote:
> >>>>> +            compatible = "aspeed,ast2600-lpc-pcc";
> >>>>> +            reg = <0x0 0x140>;
> >>>>> +            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> >>>>> +            pcc-ports = <0x80>;
> >>>>
> >>>> So what 0x80 stands for?
> >>> Host as x86 architecture would access the 0x80 port, which is mapped to
> the
> >> BMC PCC HW module.
> >>> As a result, x86 can keep the port-mmaped I/O usage and access the BMC
> >> device, which is needed to know which port using in the PCC module in
> BMC.
> >>
> >> And on different boards this is not 0x80?
> > The port-mmaped I/O defined in the intel legacy document as the example
> usage.
> > For example, the common usage agreement of port-mmaped I/O are the
> following. But this setting can be modified due to the host usage. We provide
> the flexibility to modify the I/O port settings.
> > KCS : 0xCA2(CMD)/CA3(Data)
> > BT : 0xE4/E5/E6
> > SNOOP/PCC : 0x80/81/82/83
> > Mailbox : 0xCC0
> > SuperIO : 0x2E/2F or 0x4E/0x4F
> > System UART : 0x3F8/2F8/3E8/2E8
> So which boards have it modified?
This setting should be as same as the snoop-ports. You can check the dts in arch/arm/boot/dts/aspeed folder.
aspeed-bmc-amd-daytonax.dts
212:    snoop-ports = <0x80>, <0x81>;

aspeed-bmc-facebook-tiogapass.dts
77:     snoop-ports = <0x80>;


> 
> Best regards,
> Krzysztof

From andyshrk at 163.com  Mon Mar 10 17:52:31 2025
From: andyshrk at 163.com (Andy Yan)
Date: Tue, 11 Mar 2025 08:52:31 +0800 (CST)
Subject: [PATCH] phy: rockchip: usbdp: Check these parameters only
 when the corresponding set flags are set
In-Reply-To: <Z86UOmPg/UDSBajZ@vaman>
References: <20250306065952.485809-1-andyshrk@163.com>
 <Z86UOmPg/UDSBajZ@vaman>
Message-ID: <1379400c.90c.19582b05f74.Coremail.andyshrk@163.com>


Hi Vinod,

At 2025-03-10 15:26:50, "Vinod Koul" <vkoul at kernel.org> wrote:
>On 06-03-25, 14:59, Andy Yan wrote:
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> According documentation of phy_configure_opts_dp, at the configure
>> stage, we should only verify/configure the link_rate when set_rate
>> flag is set, the same applies to lanes and voltage.
>> 
>> So we do it as the documentation says, also record the link rate
>> and lanes in phy internal for set_voltate stage.
>
>Whenever you say also, that is a sign that it should be another patch!

This patch is inspired by Dmitry's suggestion for DP/eDP driver which calls phy_configure[0][1]:
the phy driver should skip the values for which the .set_foo isn't set. So we should not set rates and
lanes when we set_voltate, but the rates and lanes are needed for voltage set, this is why I  record 
rates and lanes in this patch.
I can split the record to another patch,  but then this patch will not work correctly itself, 
I'm not sure if this is suitable.


[0]https://patchwork.freedesktop.org/patch/629780/?series=141829&rev=3
[1]https://patchwork.freedesktop.org/patch/638961/?series=145286&rev=1

>
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> ---
>> 
>>  drivers/phy/rockchip/phy-rockchip-usbdp.c | 63 +++++++++++------------
>>  1 file changed, 31 insertions(+), 32 deletions(-)
>> 
>> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
>> index c04cf64f8a35..d1bbdf382aa2 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
>> @@ -187,6 +187,8 @@ struct rk_udphy {
>>  	u32 dp_aux_din_sel;
>>  	bool dp_sink_hpd_sel;
>>  	bool dp_sink_hpd_cfg;
>> +	unsigned int link_rate;
>> +	unsigned int lanes;
>>  	u8 bw;
>>  	int id;
>>  
>> @@ -1102,42 +1104,39 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
>>  	return 0;
>>  }
>>  
>> -static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
>> -{
>> -	switch (link_rate) {
>> -	case 1620:
>> -	case 2700:
>> -	case 5400:
>> -	case 8100:
>> -		break;
>> -
>> -	default:
>> -		return -EINVAL;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>>  static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
>>  					 struct phy_configure_opts_dp *dp)
>>  {
>> -	int i, ret;
>> +	int i;
>>  
>> -	/* If changing link rate was required, verify it's supported. */
>> -	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
>> -	if (ret)
>> -		return ret;
>> +	/* Verify link rate. */
>> +	if (dp->set_rate) {
>> +		switch (dp->link_rate) {
>> +		case 1620:
>> +		case 2700:
>> +		case 5400:
>> +		case 8100:
>> +			udphy->link_rate = dp->link_rate;
>> +			break;
>> +
>> +		default:
>> +			return -EINVAL;
>> +		}
>
>why drop helper? Why not set the rate on success?

I drop helper just because the flowing check for lanes and votages don't 
have helper.
The rate is set in rk_udphy_dp_phy_configure.
>
>> +	}
>>  
>>  	/* Verify lane count. */
>> -	switch (dp->lanes) {
>> -	case 1:
>> -	case 2:
>> -	case 4:
>> -		/* valid lane count. */
>> -		break;
>> +	if (dp->set_lanes) {
>> +		switch (dp->lanes) {
>> +		case 1:
>> +		case 2:
>> +		case 4:
>> +			/* valid lane count. */
>> +			udphy->lanes = dp->lanes;
>> +			break;
>>  
>> -	default:
>> -		return -EINVAL;
>> +		default:
>> +			return -EINVAL;
>> +		}
>
>another change where helper would have made this look better


Do you mean we should do it like this:

static int rk_udphy_dp_phy_configure(struct phy *phy,
                                     union phy_configure_opts *opts)
{
        struct rk_udphy *udphy = phy_get_drvdata(phy);
        struct phy_configure_opts_dp *dp = &opts->dp;
        u32 i, val, lane;
        int ret;

       .............
      if (dp->set_rate)
           	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
     if (dp->set_lanes)
                ret = rk_udphy_dp_phy_verify_link_lanes(dp->lanes);
     if (dp->set_voltates)
               ret = rk_udphy_dp_phy_verify_link_voltate(dp->voltate);


Add helper for each of them ?
      


>
>>  	}
>>  
>>  	/*
>> @@ -1146,7 +1145,7 @@ static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
>>  	 */
>>  	if (dp->set_voltages) {
>>  		/* Lane count verified previously. */
>> -		for (i = 0; i < dp->lanes; i++) {
>> +		for (i = 0; i < udphy->lanes; i++) {
>>  			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
>>  				return -EINVAL;
>>  
>> @@ -1243,9 +1242,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
>>  	}
>>  
>>  	if (dp->set_voltages) {
>> -		for (i = 0; i < dp->lanes; i++) {
>> +		for (i = 0; i < udphy->lanes; i++) {
>>  			lane = udphy->dp_lane_sel[i];
>> -			switch (dp->link_rate) {
>> +			switch (udphy->link_rate) {
>>  			case 1620:
>>  			case 2700:
>>  				regmap_update_bits(udphy->pma_regmap,
>> -- 
>> 2.34.1
>
>-- 
>~Vinod
>
>_______________________________________________
>Linux-rockchip mailing list
>Linux-rockchip at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-rockchip

From peter.chen at cixtech.com  Mon Mar 10 18:02:29 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Tue, 11 Mar 2025 09:02:29 +0800
Subject: [PATCH v4 0/6] arm64: Introduce CIX P1 (SKY1) SoC
In-Reply-To: <20250305053823.2048217-1-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
Message-ID: <Z8-LpRCQfsVfDYtm@nchen-desktop>

On 25-03-05 13:38:17, Peter Chen wrote:
> Cixtech P1 (internal name sky1) is high performance generic Armv9 SoC.
> Orion O6 is the world's first open source Arm V9 Motherboard built by
> Radxa. You could find brief introduction for SoC and related boards at:
> https://radxa.com/products/orion/o6#overview
> 
> In this series, we add initial SoC and board support for Kernel building.
> Patch 1-2: Add dt-binding doc for CIX and its sky1 SoC
> Patch 3: add related maintainers entry
> Patch 4-5: add Arm64 build support
> Patch 6: add initial dts support for SoC and Orion O6 board
> 
> To run upstream kernel at Orion O6 board, you need to use BIOS
> released by Radxa:
> https://docs.radxa.com/en/orion/o6/bios/install-bios
> 
> Changes for v4:
> - Move add MAINTAINERS entry patch to the last, and add two dts files entry in it. 
> - Add three Krzysztof Kozlowski's Reviewed-by Tags
> - For sky1.dtsi, makes below changes:
> 	- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
> 	get its handle
> 	- Remove gic-v3's #redistributor-regions and redistributor-stride properties
> 	- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
> 	- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
> 	- Remove timer's clock frequency due to firmware has already set it

Hi Arnd,

I assume this series (all patches) will go your tree, right?

Peter

> 
> Changes for v3:
> - Patch 1: Add Krzysztof Kozlowski's Acked-by Tag
> - Patch 2: Add Krzysztof Kozlowski's Reviewed-by Tag
> - Patch 6: Fix two dts coding sytle issues
> 
> Changes for v2:
> - Pass dts build check with below commands:
> make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=vendor-prefixes.yaml
> make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=arm/cix.yaml
> make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
> - Re-order the patch set, and move vendor-perfixes to the 1st patch.
> - Patch 4: Ordered Kconfig config entry by alpha-numerically
> - Patch 5: Corrects the Ack tag's name
> - Patch 6: see below.
> 1) Corrects the SoF tag's name
> 2) Fix several coding sytle issues
> 3) move linux,cma node to dts file
> 4) delete memory node, memory size is passed by firmware
> 5) delete uart2 node which will be added in future patches
> 6) Improve for pmu and cpu node to stands for more specific cpu model
> 7) Improve the timer node and add hypervisor virtual timer irq
> 
> Fugang Duan (1):
>   arm64: Kconfig: add ARCH_CIX for cix silicons
> 
> Peter Chen (5):
>   dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
>   dt-bindings: arm: add CIX P1 (SKY1) SoC
>   arm64: defconfig: Enable CIX SoC
>   arm64: dts: cix: add initial CIX P1(SKY1) dts support
>   MAINTAINERS: Add CIX SoC maintainer entry
> 
>  .../devicetree/bindings/arm/cix.yaml          |  26 ++
>  .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
>  MAINTAINERS                                   |  10 +
>  arch/arm64/Kconfig.platforms                  |   6 +
>  arch/arm64/boot/dts/Makefile                  |   1 +
>  arch/arm64/boot/dts/cix/Makefile              |   2 +
>  arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |  26 ++
>  arch/arm64/boot/dts/cix/sky1.dtsi             | 222 ++++++++++++++++++
>  arch/arm64/configs/defconfig                  |   1 +
>  9 files changed, 296 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml
>  create mode 100644 arch/arm64/boot/dts/cix/Makefile
>  create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
>  create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi
> 
> -- 
> 2.25.1
> 

-- 

Best regards,
Peter


From hongxing.zhu at nxp.com  Mon Mar 10 18:11:04 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Tue, 11 Mar 2025 01:11:04 +0000
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250310151109.GA540579@bhelgaas>
References: <20250226024256.1678103-3-hongxing.zhu@nxp.com>
 <20250310151109.GA540579@bhelgaas>
Message-ID: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>

> -----Original Message-----
> From: Bjorn Helgaas <helgaas at kernel.org>
> Sent: 2025?3?10? 23:11
> To: Hongxing Zhu <hongxing.zhu at nxp.com>
> Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> hardcodes
> 
> On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > Use the domain number replace the hardcodes to uniquely identify
> > different controller on i.MX8MQ platforms. No function changes.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > ---
> >  drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> >  1 file changed, 6 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index 90ace941090f..ab9ebb783593 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -41,7 +41,6 @@
> >  #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> >  #define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> >  #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11, 8)
> > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> >
> >  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
> >  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct platform_device
> *pdev)
> >  	struct dw_pcie *pci;
> >  	struct imx_pcie *imx_pcie;
> >  	struct device_node *np;
> > -	struct resource *dbi_base;
> >  	struct device_node *node = dev->of_node;
> >  	int i, ret, req_cnt;
> >  	u16 val;
> > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> platform_device *pdev)
> >  			return PTR_ERR(imx_pcie->phy_base);
> >  	}
> >
> > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev, 0,
> &dbi_base);
> > -	if (IS_ERR(pci->dbi_base))
> > -		return PTR_ERR(pci->dbi_base);
> 
> This makes me wonder.
> 
> IIUC this means that previously we set controller_id to 1 if the first item in
> devicetree "reg" was 0x33c00000, and now we will set controller_id to 1 if
> the devicetree "linux,pci-domain" property is 1.
> This is good, but I think this new dependency on the correct
> "linux,pci-domain" in devicetree should be mentioned in the commit log.
> 
> My bigger worry is that we no longer set pci->dbi_base at all.  I see that the
> only use of pci->dbi_base in pci-imx6.c was to determine the controller_id,
> but this is a DWC-based driver, and the DWC core certainly uses
> pci->dbi_base.  Are we sure that none of those DWC core paths are
> important to pci-imx6.c?
Hi Bjorn:
Thanks for your concerns.
Don't worry about the assignment of pci->dbi_base.
If pci-imx6.c driver doesn't set it. DWC core driver would set it when
 dw_pcie_get_resources() is invoked.

dw_pcie_host_init()/dw_pcie_ep_init()
  ->dw_pcie_get_resources()

...
        if (!pci->dbi_base) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
                pci->dbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
                if (IS_ERR(pci->dbi_base))
                        return PTR_ERR(pci->dbi_base);
                pci->dbi_phys_addr = res->start;
        }
...


Best Regards
Richard Zhu
> 
> >  	/* Fetch GPIOs */
> >  	imx_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset",
> GPIOD_OUT_HIGH);
> >  	if (IS_ERR(imx_pcie->reset_gpiod))
> > @@ -1565,8 +1559,12 @@ static int imx_pcie_probe(struct
> platform_device *pdev)
> >  	switch (imx_pcie->drvdata->variant) {
> >  	case IMX8MQ:
> >  	case IMX8MQ_EP:
> > -		if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR)
> > -			imx_pcie->controller_id = 1;
> > +		ret = of_get_pci_domain_nr(node);
> > +		if (ret < 0 || ret > 1)
> > +			return dev_err_probe(dev, -ENODEV,
> > +					     "failed to get valid pcie domain\n");
> > +		else
> > +			imx_pcie->controller_id = ret;
> >  		break;
> >  	default:
> >  		break;
> > --
> > 2.37.1
> >

From andi.shyti at kernel.org  Mon Mar 10 18:12:03 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 02:12:03 +0100
Subject: [PATCH v2 00/10] i2c: busses: Introduce and use
 i2c_10bit_addr_*_from_msg()
In-Reply-To: <20250213141045.2716943-1-andriy.shevchenko@linux.intel.com>
References: <20250213141045.2716943-1-andriy.shevchenko@linux.intel.com>
Message-ID: <c6xszdhx5ztexlqlmhvdn4dyz5ilzxsm7c62cvkmnwy2y3gaqc@owk2ani2emys>

Hi Andy,

> Andy Shevchenko (10):
>   i2c: Introduce i2c_10bit_addr_*_from_msg() helpers
>   i2c: axxia: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: bcm-kona: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: brcmstb: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: eg20t: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: kempld: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: mt7621: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: rzv2m: Use i2c_10bit_addr_*_from_msg() helpers
>   i2c: ibm_iic: Use i2c_*bit_addr*_from_msg() helpers
>   i2c: mv64xxx: Use i2c_*bit_addr*_from_msg() helpers

merged to i2c/i2c-host.

Thanks,
Andi


From martin.petersen at oracle.com  Mon Mar 10 18:19:01 2025
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Mon, 10 Mar 2025 21:19:01 -0400
Subject: [PATCH][next] scsi: ufs: rockchip: Fix spelling mistake "susped" -> "suspend"
In-Reply-To: <20250225101142.161474-1-colin.i.king@gmail.com>
References: <20250225101142.161474-1-colin.i.king@gmail.com>
Message-ID: <174165504936.528513.7895453741464348013.b4-ty@oracle.com>

On Tue, 25 Feb 2025 10:11:42 +0000, Colin Ian King wrote:

> There is a spelling mistake in a dev_err message. Fix it.
> 
> 

Applied to 6.15/scsi-queue, thanks!

[1/1] scsi: ufs: rockchip: Fix spelling mistake "susped" -> "suspend"
      https://git.kernel.org/mkp/scsi/c/24e81b821724

-- 
Martin K. Petersen	Oracle Linux Engineering


From martin.petersen at oracle.com  Mon Mar 10 18:19:04 2025
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Mon, 10 Mar 2025 21:19:04 -0400
Subject: [PATCH -next] scsi: ufs: rockchip: Simplify bool conversion
In-Reply-To: <20250226021157.77934-1-jiapeng.chong@linux.alibaba.com>
References: <20250226021157.77934-1-jiapeng.chong@linux.alibaba.com>
Message-ID: <174165505002.528513.7169734727155329049.b4-ty@oracle.com>

On Wed, 26 Feb 2025 10:11:57 +0800, Jiapeng Chong wrote:

> ./drivers/ufs/host/ufs-rockchip.c:268:70-75: WARNING: conversion to bool not needed here.
> 
> 

Applied to 6.15/scsi-queue, thanks!

[1/1] scsi: ufs: rockchip: Simplify bool conversion
      https://git.kernel.org/mkp/scsi/c/3d8256903934

-- 
Martin K. Petersen	Oracle Linux Engineering


From shawnguo2 at yeah.net  Mon Mar 10 18:25:30 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:25:30 +0800
Subject: [PATCH v2] arm64: dts: freescale: ten64: add usb hub definition
In-Reply-To: <20250305001901.31594-1-matt@traverse.com.au>
References: <20250129045352.10728-1-matt@traverse.com.au>
 <20250305001901.31594-1-matt@traverse.com.au>
Message-ID: <Z8+RCo8mGOLIck5a@dragon>

On Wed, Mar 05, 2025 at 11:19:01AM +1100, Mathew McBride wrote:
> A device tree binding for the Microchip USB5744 hub controller
> was added in commit 02be19e914b8 ("dt-bindings: usb: Add support
> for Microchip usb5744 hub controller").
> 
> U-Boot will consume this binding in order to perform the
> necessary actions to enable the USB hub ports over I2C.
> (We previously used our own out-of-tree driver for
> this task)
> 
> The Ten64 board does not have any switchable supplies
> for the voltage rails utilized by the USB5744, so a
> pair of dummy supplies have been added to facilitate
> operation with U-Boot's hub driver.
> 
> Signed-off-by: Mathew McBride <matt at traverse.com.au>

Applied, thanks!



From chenyuan0y at gmail.com  Mon Mar 10 18:27:05 2025
From: chenyuan0y at gmail.com (Chenyuan Yang)
Date: Mon, 10 Mar 2025 20:27:05 -0500
Subject: [PATCH] usb: gadget: aspeed: Add NULL pointer check in ast_vhub_init_dev()
Message-ID: <20250311012705.1233829-1-chenyuan0y@gmail.com>

The variable d->name, returned by devm_kasprintf(), could be NULL.
A pointer check is added to prevent potential NULL pointer dereference.
This is similar to the fix in commit 3027e7b15b02
("ice: Fix some null pointer dereference issues in ice_ptp.c").

This issue is found by our static analysis tool

Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
---
 drivers/usb/gadget/udc/aspeed-vhub/dev.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
index 573109ca5b79..a09f72772e6e 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -548,6 +548,9 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
 	d->vhub = vhub;
 	d->index = idx;
 	d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1);
+	if (!d->name)
+		return -ENOMEM;
+
 	d->regs = vhub->regs + 0x100 + 0x10 * idx;
 
 	ast_vhub_init_ep0(vhub, &d->ep0, d);
-- 
2.34.1



From shawnguo2 at yeah.net  Mon Mar 10 18:27:35 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:27:35 +0800
Subject: [PATCH] arm64: dts: imx8mp: configure GPU and NPU clocks to
 overdrive rate
In-Reply-To: <20250204182737.3361431-1-l.stach@pengutronix.de>
References: <20250204182737.3361431-1-l.stach@pengutronix.de>
Message-ID: <Z8+RhzwHNJvUcF+P@dragon>

On Tue, Feb 04, 2025 at 07:27:37PM +0100, Lucas Stach wrote:
> A lot of other clocks on the i.MX8MP, including the DRAM set up by the
> bootloader are already running at overdrive clock rates. While this is a
> deviation from the configuration of other i.MX8M* family SoCs, overdrive
> is the default for most i.MX8MP boards and only some special purpose
> boards will choose to run the SoC at nominal drive rates. Up the GPU and
> NPU clock rates to their overdrive level to be consistent with other
> clocks set up in the dtsi.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 18:37:50 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:37:50 +0800
Subject: [PATCH v4 0/6] arm64: dts: freescale: imx8mp-skov: switch to
 nominal drive mode
In-Reply-To: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
References: <20250218-imx8m-clk-v4-0-b7697dc2dcd0@pengutronix.de>
Message-ID: <Z8+T7sdtIsvkJ1i2@dragon>

On Tue, Feb 18, 2025 at 07:26:40PM +0100, Ahmad Fatoum wrote:
> Ahmad Fatoum (6):
>       dt-bindings: clock: imx8m: document nominal/overdrive properties
>       arm64: dts: imx8mp: Add optional nominal drive mode DTSI
>       arm64: dts: imx8mp: add fsl,nominal-mode property into nominal.dtsi
>       arm64: dts: freescale: imx8mp-skov: configure LDB clock automatically
>       arm64: dts: freescale: imx8mp-skov: operate SoC in nominal mode

Applied 4 DTS changes, thanks!

>       clk: imx8mp: inform CCF of maximum frequency of clocks



From shawnguo2 at yeah.net  Mon Mar 10 18:40:38 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:40:38 +0800
Subject: [PATCH v2 0/6] arm64: dts: imx8mp-skov: add new variants
In-Reply-To: <20250218-skov-imx8mp-new-boards-v2-0-4040379742ea@pengutronix.de>
References: <20250218-skov-imx8mp-new-boards-v2-0-4040379742ea@pengutronix.de>
Message-ID: <Z8+Ultn2BDg+fSng@dragon>

On Tue, Feb 18, 2025 at 07:38:12PM +0100, Ahmad Fatoum wrote:
> Ahmad Fatoum (5):
>       dt-bindings: arm: fsl: add more compatibles for Skov i.MX8MP variants
>       arm64: dts: imx8mp-skov: move I2C2 pin control group into DTSI
>       arm64: dts: imx8mp-skov: describe I2C bus recovery for all controllers
>       arm64: dts: imx8mp-skov: add revC BD500 board
>       arm64: dts: imx8mp-skov: support new 7" panel board
> 
> Oleksij Rempel (1):
>       arm64: dts: imx8mp-skov: add basic board as fallback

Applied all, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 18:52:05 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:52:05 +0800
Subject: [PATCH 0/9] ARM: dts: TQMa6/6UL/7: DT cleanup
In-Reply-To: <20250219081748.1181507-1-alexander.stein@ew.tq-group.com>
References: <20250219081748.1181507-1-alexander.stein@ew.tq-group.com>
Message-ID: <Z8+XRalDiwot8Xsl@dragon>

On Wed, Feb 19, 2025 at 09:17:35AM +0100, Alexander Stein wrote:
> Alexander Stein (4):
>   ARM: dts: imx6qdl-tqma6: Order DT properties
>   ARM: dts: imx6ul-tqma6ul: Order DT properties
>   ARM: dts: imx6ul-tqma6ul: Add vcc-supply for spi-nor
>   ARM: dts: imx7-tqma7: Add vcc-supply for spi-nor
> 
> Markus Niebel (5):
>   ARM: dts: imx6qdl-tqma6: limit PMIC SW4 to 3.3V
>   ARM: dts: imx6qdl-tqma6: use sw4_reg as 3.3V supply
>   ARM: dts: imx6qdl-tqma6: Add partitions subnode to spi-nor
>   ARM: dts: tqma6ul: Add partitions subnode to spi-nor
>   ARM: dts: tqma7: Add partitions subnode to spi-nor

Applied all, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 18:55:22 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:55:22 +0800
Subject: [PATCH v2] ARM: dts: vfxxx: Fix the order of the DMA entries
In-Reply-To: <20250220124809.2361942-1-festevam@gmail.com>
References: <20250220124809.2361942-1-festevam@gmail.com>
Message-ID: <Z8+YCoJwtBeCSco5@dragon>

On Thu, Feb 20, 2025 at 09:48:09AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> According to fsl,dspi.yaml the expected order for describing the dmas
> and dma-names properties is "tx" first, followed by "rx".
> 
> Adjust it acordingly to fix the following dt-schema warnings:
> 
> spi at 4002c000: dma-names:0: 'tx' was expected
> spi at 4002c000: dma-names:1: 'rx' was expected
> 
> Signed-off-by: Fabio Estevam <festevam at denx.de>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 18:56:40 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:56:40 +0800
Subject: [PATCH] ARM: dts: imx31: Use nand-controller as node name
In-Reply-To: <20250220130345.2375204-1-festevam@gmail.com>
References: <20250220130345.2375204-1-festevam@gmail.com>
Message-ID: <Z8+YWBqymWyXISBD@dragon>

On Thu, Feb 20, 2025 at 10:03:45AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> According to mxc-nand.yaml, the correct node name must be
> 'nand-controller'.
> 
> Change it accordingly to fix the following dt-schema warning:
> 
> $nodename:0: 'nand at b8000000' does not match '^nand-controller(@.*)?'
> 
> Signed-off-by: Fabio Estevam <festevam at denx.de>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 18:57:50 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 09:57:50 +0800
Subject: [PATCH] ARM: dts: imx53-mba53: Fix the PCA9554 compatible
In-Reply-To: <20250220133153.2380248-1-festevam@gmail.com>
References: <20250220133153.2380248-1-festevam@gmail.com>
Message-ID: <Z8+YnsJ20SJe7YhC@dragon>

On Thu, Feb 20, 2025 at 10:31:53AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> gpio-pca95xx.yaml documents 'nxp,pca9554', so use this compatible
> to fix the following dt-schema warning:
> 
> failed to match any schema with compatible: ['pca9554']
> 
> Signed-off-by: Fabio Estevam <festevam at denx.de>

Applied, thanks!



From jackbb_wu at compal.com  Mon Mar 10 19:01:21 2025
From: jackbb_wu at compal.com (jackbb_wu at compal.com)
Date: Tue, 11 Mar 2025 10:01:21 +0800
Subject: [net-next,v2] [PATCH net-next v2] net: wwan: t7xx: Change PM_AUTOSUSPEND_MS to 5000
Message-ID: <20250311020121.914989-1-jackbb_wu@compal.com>

From: Jack Wu <wojackbb at gmail.com>

Because optimizing the power consumption of t7XX,
change auto suspend time to 5000.

The Tests uses a script to loop through the power_state
of t7XX.
(for example: /sys/bus/pci/devices/0000\:72\:00.0/power_state)

* If Auto suspend is 20 seconds,
  test script show power_state have 0~5% of the time was in D3 state
  when host don't have data packet transmission.

* Changed auto suspend time to 5 seconds,
  test script show power_state have 50%~80% of the time was in D3 state
  when host don't have data packet transmission.

We tested Fibocom FM350 and our products using the t7xx and they all
benefited from this.

Signed-off-by: Jack Wu <wojackbb at gmail.com>
---
V2:
 * supplementary commit information
---
---
 drivers/net/wwan/t7xx/t7xx_pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c
index e556e5bd49ab..dcadd615a025 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.c
+++ b/drivers/net/wwan/t7xx/t7xx_pci.c
@@ -48,7 +48,7 @@
 #define T7XX_INIT_TIMEOUT              20
 #define PM_SLEEP_DIS_TIMEOUT_MS                20
 #define PM_ACK_TIMEOUT_MS              1500
-#define PM_AUTOSUSPEND_MS              20000
+#define PM_AUTOSUSPEND_MS              5000
 #define PM_RESOURCE_POLL_TIMEOUT_US    10000
 #define PM_RESOURCE_POLL_STEP_US       100

--
2.34.1



================================================================================================================================================================
This message may contain information which is private, privileged or confidential of Compal Electronics, Inc. If you are not the intended recipient of this message, please notify the sender and destroy/delete the message. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information, by persons or entities other than the intended recipient is prohibited.
================================================================================================================================================================


From shawnguo2 at yeah.net  Mon Mar 10 19:22:39 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:22:39 +0800
Subject: [PATCH v4 0/4] arm64: dts: add imx95_15x15_evk boards support
In-Reply-To: <20250221-imx95_15x15-v4-0-385ee8e03dfd@nxp.com>
References: <20250221-imx95_15x15-v4-0-385ee8e03dfd@nxp.com>
Message-ID: <Z8+eb5HNX/FQPg5P@dragon>

On Fri, Feb 21, 2025 at 04:15:56PM -0500, Frank Li wrote:
> Frank Li (4):
>       dt-bindings: arm: fsl: add i.MX95 15x15 EVK board
>       arm64: dts: imx95: Add #io-channel-cells = <1> for adc node
>       arm64: dts: imx95: Add i3c1 and i3c2
>       arm64: dts: imx95: Add imx95-15x15-evk support

Applied all, thanks!



From andersson at kernel.org  Mon Mar 10 19:25:08 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 10 Mar 2025 21:25:08 -0500
Subject: [GIT PULL] Qualcomm driver fixes for v6.14
Message-ID: <20250311022509.1232678-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-drivers-fixes-for-6.14

for you to fetch changes up to 2eeb03ad9f42dfece63051be2400af487ddb96d2:

  soc: qcom: pdr: Fix the potential deadlock (2025-02-14 09:16:27 -0600)

----------------------------------------------------------------
Qualcomm driver fixes for v6.14

Fixes a locking issue in the PDR implementation, which manifest itself
as transaction timeouts during the startup procedure for some
remoteprocs.

A registration race is fixed in the custom efivars implementation,
resolving reported NULL pointer dereferences.

Error handling related to tzmem allocation is corrected, to ensure that
the allocation error is propagated.

Lastly a trivial merge mistake in pmic_glink is addressed.

----------------------------------------------------------------
Dan Carpenter (1):
      firmware: qcom: scm: Fix error code in probe()

Johan Hovold (1):
      firmware: qcom: uefisecapp: fix efivars registration race

Krzysztof Kozlowski (1):
      soc: qcom: pmic_glink: Drop redundant pg assignment before taking lock

Saranya R (1):
      soc: qcom: pdr: Fix the potential deadlock

 drivers/firmware/qcom/qcom_qseecom_uefisecapp.c | 18 +++++++++---------
 drivers/firmware/qcom/qcom_scm.c                |  4 ++--
 drivers/soc/qcom/pdr_interface.c                |  8 +-------
 drivers/soc/qcom/pmic_glink.c                   |  2 +-
 4 files changed, 13 insertions(+), 19 deletions(-)


From shawnguo2 at yeah.net  Mon Mar 10 19:27:13 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:27:13 +0800
Subject: [PATCH] arm64: dts: s32g: add FlexCAN[0..3] support for s32g2
 and s32g3
In-Reply-To: <20250224134016.3921196-1-ciprianmarian.costea@oss.nxp.com>
References: <20250224134016.3921196-1-ciprianmarian.costea@oss.nxp.com>
Message-ID: <Z8+fgXENvCrqXvTP@dragon>

On Mon, Feb 24, 2025 at 03:40:16PM +0200, Ciprian Costea wrote:
> From: Ciprian Marian Costea <ciprianmarian.costea at oss.nxp.com>
> 
> Add FlexCAN[0..3] for S32G2 and S32G3 SoCs.
> 
> Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea at oss.nxp.com>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 19:32:05 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:32:05 +0800
Subject: [PATCH v2 1/2] arm64: dts: imx8mp-tqma8mpql-mba8mpxl: change
 sound card model name
In-Reply-To: <20250224150016.499055-1-alexander.stein@ew.tq-group.com>
References: <20250224150016.499055-1-alexander.stein@ew.tq-group.com>
Message-ID: <Z8+gpX+REkX4SEUz@dragon>

On Mon, Feb 24, 2025 at 04:00:14PM +0100, Alexander Stein wrote:
> From: Markus Niebel <Markus.Niebel at ew.tq-group.com>
> 
> The card name for ALSA is generated from the model name string and
> is limited to 16 characters. Use a shorter name to prevent cutting the
> name.
> 
> Since nearly all starter kit mainboards for i.MX based SoM by TQ-Systems
> use the same codec with the same routing on board it is a good idea to
> use the same model name for the sound card. This allows sharing a default
> asound.conf in BSP over all the kits.
> 
> Signed-off-by: Markus Niebel <Markus.Niebel at ew.tq-group.com>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>

Applied both, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 19:36:52 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:36:52 +0800
Subject: [PATCH 1/1] arm64: dts: im8mq: move dwc3 usb port under ports
In-Reply-To: <20250224193308.407606-1-Frank.Li@nxp.com>
References: <20250224193308.407606-1-Frank.Li@nxp.com>
Message-ID: <Z8+hxCxum9uTLGGC@dragon>

On Mon, Feb 24, 2025 at 02:33:07PM -0500, Frank Li wrote:
> Move port at 0 and port at 1 under ports to fix below DTB_CHECK warnings.
> 
> arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dtb: usb at 38100000: port at 0:reg:0:0: 0 is less than the minimum of 1
> 	from schema $id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
> arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dtb: usb at 38100000: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'dr_mode', 'phy-names', 'phys', 'port at 0', 'port at 1', 'snps,parkmode-disable-ss-quirk' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied with a change on subject prefix, s/im8mq/im8mq-librem5, thanks!



From shinichiro.kawasaki at wdc.com  Mon Mar 10 19:41:42 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 11:41:42 +0900
Subject: [PATCH 0/2] block: nvme: fix blktests nvme/039 failure
Message-ID: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>

Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
conditions") in the kernel tag v6.14-rc3 triggered blktests nvme/039
failure [1].

The test case injects errors to the NVMe driver and confirms the errors
are logged. The first half of the test checks it for non-passthrough
requests, and the second half checks for passthrough requests. The
commit made both halves fail.

This series addresses the test case failure. The first patch covers the
passthrough requests, and the second patch covers the non-passthrough
requests.

[1] https://lkml.kernel.org/linux-block/y7m5kyk5r2eboyfsfprdvhmoo27ur46pz3r2kwb4puhxjhbvt6 at zgh4dg3ewya3/

Shin'ichiro Kawasaki (2):
  nvme: move error logging from nvme_end_req() to __nvme_end_req()
  block: change blk_mq_add_to_batch() third argument type to
    blk_status_t

 drivers/block/null_blk/main.c |  2 +-
 drivers/block/virtio_blk.c    |  5 +++--
 drivers/nvme/host/apple.c     |  3 ++-
 drivers/nvme/host/core.c      | 15 ++++++++-------
 drivers/nvme/host/nvme.h      |  1 +
 drivers/nvme/host/pci.c       |  5 +++--
 include/linux/blk-mq.h        |  5 +++--
 7 files changed, 21 insertions(+), 15 deletions(-)

-- 
2.47.0



From shinichiro.kawasaki at wdc.com  Mon Mar 10 19:41:43 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 11:41:43 +0900
Subject: [PATCH 1/2] nvme: move error logging from nvme_end_req() to __nvme_end_req()
In-Reply-To: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
Message-ID: <20250311024144.1762333-2-shinichiro.kawasaki@wdc.com>

Before the Commit 1f47ed294a2b ("block: cleanup and fix batch completion
adding conditions"), blk_mq_add_to_batch() did not add failed
passthrough requests to batch, and returned false. After the commit,
blk_mq_add_to_batch() always adds passthrough requests to batch
regardless of whether the request failed or not, and returns true. This
affected error logging feature in the NVME driver.

Before the commit, the call chain of failed passthrough request was as
follows:

nvme_handle_cqe()
 blk_mq_add_to_batch() .. false is returned, then call nvme_pci_complete_rq()
 nvme_pci_complete_rq()
  nvme_complete_rq()
   nvme_end_req()
    nvme_log_err_passthru() .. error logging
    __nvme_end_req()        .. end of the rqeuest

After the commit, the call chain is as follows:

nvme_handle_cqe()
 blk_mq_add_to_batch() .. true is returned, then set nvme_pci_complete_batch()
 ..
 nvme_pci_complete_batch()
  nvme_complete_batch()
   nvme_complete_batch_req()
    __nvme_end_req() .. end of the request, without error logging

To make the error logging feature work again for passthrough requests, move the
nvme_log_err_passthru() call from nvme_end_req() to __nvme_end_req().

While at it, move nvme_log_error() call for non-passthrough requests together
with nvme_log_err_passthru(). Even though the trigger commit does not affect
non-passthrough requests, move it together for code simplicity.

Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
 drivers/nvme/host/core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f028913e2e62..8359d0aa0e44 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -431,6 +431,12 @@ static inline void nvme_end_req_zoned(struct request *req)
 
 static inline void __nvme_end_req(struct request *req)
 {
+	if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) {
+		if (blk_rq_is_passthrough(req))
+			nvme_log_err_passthru(req);
+		else
+			nvme_log_error(req);
+	}
 	nvme_end_req_zoned(req);
 	nvme_trace_bio_complete(req);
 	if (req->cmd_flags & REQ_NVME_MPATH)
@@ -441,12 +447,6 @@ void nvme_end_req(struct request *req)
 {
 	blk_status_t status = nvme_error_status(nvme_req(req)->status);
 
-	if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) {
-		if (blk_rq_is_passthrough(req))
-			nvme_log_err_passthru(req);
-		else
-			nvme_log_error(req);
-	}
 	__nvme_end_req(req);
 	blk_mq_end_request(req, status);
 }
-- 
2.47.0



From shinichiro.kawasaki at wdc.com  Mon Mar 10 19:41:44 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 11:41:44 +0900
Subject: [PATCH 2/2] block: change blk_mq_add_to_batch() third argument type to blk_status_t
In-Reply-To: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
Message-ID: <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>

Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
conditions") modified the evaluation criteria for the third argument,
'ioerror', in the blk_mq_add_to_batch() function. Initially, the
function had checked if 'ioerror' equals zero. Following the commit, it
started checking for negative error values, with the presumption that
such values, for instance -EIO, would be passed in.

However, blk_mq_add_to_batch() callers do not pass negative error
values. Instead, they pass status codes defined in various ways:

- NVMe PCI and Apple drivers pass NVMe status code
- virtio_blk driver passes the virtblk request header status byte
- null_blk driver passes blk_status_t

These codes are either zero or positive, therefore the revised check
fails to function as intended. Specifically, with the NVMe PCI driver,
this modification led to the failure of the blktests test case nvme/039.
In this test scenario, errors are artificially injected to the NVMe
driver, resulting in positive NVMe status codes passed to
blk_mq_add_to_batch(), which unexpectedly processes the failed I/O in a
batch. Hence the failure.

To correct the ioerror check within blk_mq_add_to_batch(), make all
callers to uniformly pass the argument as blk_status_t. Modify the
callers to translate their specific status codes into blk_status_t. For
this translation, export the helper function nvme_error_status(). Adjust
blk_mq_add_to_batch() to translate blk_status_t back into the error
number for the appropriate check.

Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
 drivers/block/null_blk/main.c | 2 +-
 drivers/block/virtio_blk.c    | 5 +++--
 drivers/nvme/host/apple.c     | 3 ++-
 drivers/nvme/host/core.c      | 3 ++-
 drivers/nvme/host/nvme.h      | 1 +
 drivers/nvme/host/pci.c       | 5 +++--
 include/linux/blk-mq.h        | 5 +++--
 7 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index d94ef37480bd..31f23f6a8ed0 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1549,7 +1549,7 @@ static int null_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 		cmd = blk_mq_rq_to_pdu(req);
 		cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req),
 						blk_rq_sectors(req));
-		if (!blk_mq_add_to_batch(req, iob, (__force int) cmd->error,
+		if (!blk_mq_add_to_batch(req, iob, cmd->error,
 					blk_mq_end_request_batch))
 			blk_mq_end_request(req, cmd->error);
 		nr++;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 6a61ec35f426..74f73cb8becd 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -1207,11 +1207,12 @@ static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 
 	while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
 		struct request *req = blk_mq_rq_from_pdu(vbr);
+		u8 status = virtblk_vbr_status(vbr);
 
 		found++;
 		if (!blk_mq_complete_request_remote(req) &&
-		    !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
-						virtblk_complete_batch))
+		    !blk_mq_add_to_batch(req, iob, virtblk_result(status),
+					 virtblk_complete_batch))
 			virtblk_request_done(req);
 	}
 
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index a060f69558e7..ae859f772485 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -599,7 +599,8 @@ static inline void apple_nvme_handle_cqe(struct apple_nvme_queue *q,
 	}
 
 	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
-	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
+	    !blk_mq_add_to_batch(req, iob,
+				 nvme_error_status(nvme_req(req)->status),
 				 apple_nvme_complete_batch))
 		apple_nvme_complete_rq(req);
 }
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 8359d0aa0e44..725f2052bcb2 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -274,7 +274,7 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
 	nvme_put_ctrl(ctrl);
 }
 
-static blk_status_t nvme_error_status(u16 status)
+blk_status_t nvme_error_status(u16 status)
 {
 	switch (status & NVME_SCT_SC_MASK) {
 	case NVME_SC_SUCCESS:
@@ -315,6 +315,7 @@ static blk_status_t nvme_error_status(u16 status)
 		return BLK_STS_IOERR;
 	}
 }
+EXPORT_SYMBOL_GPL(nvme_error_status);
 
 static void nvme_retry_req(struct request *req)
 {
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 7be92d07430e..4e166da4aa81 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -904,6 +904,7 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
+blk_status_t nvme_error_status(u16 status);
 void nvme_queue_scan(struct nvme_ctrl *ctrl);
 int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
 		void *log, size_t size, u64 offset);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 640590b21728..873564efc346 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1130,8 +1130,9 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
 
 	trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail);
 	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
-	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
-					nvme_pci_complete_batch))
+	    !blk_mq_add_to_batch(req, iob,
+				 nvme_error_status(nvme_req(req)->status),
+				 nvme_pci_complete_batch))
 		nvme_pci_complete_rq(req);
 }
 
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 71f4f0cc3dac..9ba479a52ce7 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -857,7 +857,8 @@ static inline bool blk_mq_is_reserved_rq(struct request *rq)
  * ->end_io handler.
  */
 static inline bool blk_mq_add_to_batch(struct request *req,
-				       struct io_comp_batch *iob, int ioerror,
+				       struct io_comp_batch *iob,
+				       blk_status_t status,
 				       void (*complete)(struct io_comp_batch *))
 {
 	/*
@@ -874,7 +875,7 @@ static inline bool blk_mq_add_to_batch(struct request *req,
 	if (!blk_rq_is_passthrough(req)) {
 		if (req->end_io)
 			return false;
-		if (ioerror < 0)
+		if (blk_status_to_errno(status) < 0)
 			return false;
 	}
 
-- 
2.47.0



From shawnguo2 at yeah.net  Mon Mar 10 19:44:39 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:44:39 +0800
Subject: [PATCH 0/3] imx8qxp: PCIe fixes
In-Reply-To: <20250225102726.654070-1-alexander.stein@ew.tq-group.com>
References: <20250225102726.654070-1-alexander.stein@ew.tq-group.com>
Message-ID: <Z8+jl+QWCwStEitG@dragon>

On Tue, Feb 25, 2025 at 11:27:20AM +0100, Alexander Stein wrote:
> Alexander Stein (3):
>   dt-bindings: PCI: fsl,imx6q-pcie: Add optional DMA interrupt
>   arm64: dts: imx8qm-ss-hsio: Wire up DMA IRQ for PCIe
>   arm64: dts: mba8xx: Remove invalid propert

s/propert/property as Bjorn suggested, then applied both DTS changes.

Shawn



From shawnguo2 at yeah.net  Mon Mar 10 19:47:26 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:47:26 +0800
Subject: [PATCH 1/1] ARM: dts: imx6ul-tqma6ul1: Change include order to
 disable fec2 node
In-Reply-To: <20250225144436.813645-1-alexander.stein@ew.tq-group.com>
References: <20250225144436.813645-1-alexander.stein@ew.tq-group.com>
Message-ID: <Z8+kPrY3BsyniZS2@dragon>

On Tue, Feb 25, 2025 at 03:44:35PM +0100, Alexander Stein wrote:
> From: Max Merchel <Max.Merchel at ew.tq-group.com>
> 
> TQMa6UL1 has only one FEC which needs to be disabled as one of the last
> steps.
> imx6ul-tqma6ul2.dtsi can't be included in imx6ul-tqma6ul1.dtsi as the
> defaults from imx6ul.dtsi will be applied again.
> 
> Fixes: 7b8861d8e627 ("ARM: dts: imx6ul: add TQ-Systems MBa6ULx device trees")
> Signed-off-by: Max Merchel <Max.Merchel at ew.tq-group.com>
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 19:50:30 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:50:30 +0800
Subject: [PATCH v2 1/1] arm64: dts: imx95: add ref clock for pcie nodes
In-Reply-To: <20250225170802.2671972-1-Frank.Li@nxp.com>
References: <20250225170802.2671972-1-Frank.Li@nxp.com>
Message-ID: <Z8+k9s/vrLE7N4km@dragon>

On Tue, Feb 25, 2025 at 12:08:02PM -0500, Frank Li wrote:
> Add "ref" clock for i.MX95's pcie and fix below CHECK_DTBS warnings:
> arch/arm64/boot/dts/freescale/imx95-19x19-evk.dtb: pcie at 4c300000: clock-names: ['pcie', 'pcie_bus', 'pcie_phy', 'pcie_aux'] is too short
> 	from schema $id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie.yaml
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 19:56:49 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:56:49 +0800
Subject: [PATCH resend v3 1/1] arm64: dts: imx93: add ddr edac support
In-Reply-To: <20250225192159.2907320-1-Frank.Li@nxp.com>
References: <20250225192159.2907320-1-Frank.Li@nxp.com>
Message-ID: <Z8+mcZw9yjOr3m/y@dragon>

On Tue, Feb 25, 2025 at 02:21:58PM -0500, Frank Li wrote:
> Add ddr edac support for imx93.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 19:58:12 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 10:58:12 +0800
Subject: [PATCH] ARM: imx: mark imx53_suspend_sz as unused
In-Reply-To: <20250225201157.4190864-1-arnd@kernel.org>
References: <20250225201157.4190864-1-arnd@kernel.org>
Message-ID: <Z8+mxDdvtak/3SRs@dragon>

On Tue, Feb 25, 2025 at 09:11:52PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> Unused 'static const' variables cause a warning when building with
> W=1, and imx53_suspend_sz has a definition for this as an
> alternative when CONFIG_SUSPEND is disabled:
> 
>     In file included from arch/arm/mach-imx/cpu.c:9:
>     arch/arm/mach-imx/common.h:101:18: error: 'imx53_suspend_sz' defined but not used [-Werror=unused-const-variable=]
> 
> It's still referenced though, so mark it as __maybe_unused, so
> the one user can address the dummy copy and other files that include
> the header don't produce a warning.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 20:04:38 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 11:04:38 +0800
Subject: [PATCH v3 3/4] arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to
 AUDIOMIX block
In-Reply-To: <20250226164513.33822-4-laurentiumihalcea111@gmail.com>
References: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
 <20250226164513.33822-4-laurentiumihalcea111@gmail.com>
Message-ID: <Z8+oRjW7YN+kw73/@dragon>

On Wed, Feb 26, 2025 at 11:45:12AM -0500, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> 
> Needed because the DSP and OCRAM_A components from AUDIOMIX are clocked
> by AUDIO_AXI_CLK_ROOT instead of AUDIO_AHB_CLK_ROOT.
> 
> Fixes: b86c3afabb4f ("arm64: dts: imx8mp: Add SAI, SDMA, AudioMIX")
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>

Applied, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 20:04:52 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 11:04:52 +0800
Subject: [PATCH v3 4/4] arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT
 freq. to 800MHz
In-Reply-To: <20250226164513.33822-5-laurentiumihalcea111@gmail.com>
References: <20250226164513.33822-1-laurentiumihalcea111@gmail.com>
 <20250226164513.33822-5-laurentiumihalcea111@gmail.com>
Message-ID: <Z8+oVEFcKCS8n6em@dragon>

On Wed, Feb 26, 2025 at 11:45:13AM -0500, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> 
> AUDIO_AXI_CLK_ROOT can't run at currently requested 600MHz w/ its parent
> SYS_PLL1 configured at 800MHz. Configure it to run at 800MHz as some
> applications running on the DSP expect the core to run at this frequency
> anyways. This change also affects the AUDIOMIX NoC.
> 
> Fixes: b739681b3f8b ("arm64: dts: imx8mp: Fix SDMA2/3 clocks")
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>

Applied, thanks!



From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 10 20:08:27 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Tue, 11 Mar 2025 11:08:27 +0800
Subject: [PATCH v5 1/4] dt-bindings: interrupt-controller: Add support for
 Amlogic A4 and A5 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <20250311-irqchip-gpio-a4-a5-v5-1-ca4cc276c18c@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Update dt-binding document for GPIO interrupt controller
of Amlogic A4 and A5 SoCs

Acked-by: Conor Dooley <conor.dooley at microchip.com>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 .../interrupt-controller/amlogic,meson-gpio-intc.yaml | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
index a93744763787..3d60d9e9e208 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
@@ -35,6 +35,9 @@ properties:
               - amlogic,meson-sm1-gpio-intc
               - amlogic,meson-a1-gpio-intc
               - amlogic,meson-s4-gpio-intc
+              - amlogic,a4-gpio-intc
+              - amlogic,a4-gpio-ao-intc
+              - amlogic,a5-gpio-intc
               - amlogic,c3-gpio-intc
               - amlogic,t7-gpio-intc
           - const: amlogic,meson-gpio-intc
@@ -49,7 +52,7 @@ properties:
 
   amlogic,channel-interrupts:
     description: Array with the upstream hwirq numbers
-    minItems: 8
+    minItems: 2
     maxItems: 12
     $ref: /schemas/types.yaml#/definitions/uint32-array
 
@@ -60,6 +63,20 @@ required:
   - "#interrupt-cells"
   - amlogic,channel-interrupts
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: amlogic,a4-gpio-ao-intc
+then:
+  properties:
+    amlogic,channel-interrupts:
+      maxItems: 2
+else:
+  properties:
+    amlogic,channel-interrupts:
+      minItems: 8
+
 additionalProperties: false
 
 examples:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 10 20:08:26 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Tue, 11 Mar 2025 11:08:26 +0800
Subject: [PATCH v5 0/4] Add GPIO interrupt support for Amlogic A4 and A5
 SoCs
Message-ID: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>

This patch adds GPIO interrupt support for Amlogic A4 and A5 SoCs

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Changes in v5:
- Make minor changes of source code according to Thomas's suggestion.
- Link to v4: https://lore.kernel.org/r/20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b at amlogic.com

Changes in v4:
- Make minor changes for bindings as Conor and Rob suggest.
- Format adjustment of source code according to Thomas's suggestion.
- Link to v3: https://lore.kernel.org/r/20250305-irqchip-gpio-a4-a5-v3-0-1eec70352fea at amlogic.com

Changes in v3:
- Fix warning when run 'make ARCH=arm64 dtbs_check'.
- Fix warning when run 'make ARCH=arm64 Image W=1'.
- Rebase file amlogic-a4.dtsi.
- Link to v2: https://lore.kernel.org/r/20250226-irqchip-gpio-a4-a5-v2-0-c55b1050cb55 at amlogic.com

Changes in v2:
- Use if/then instead of direct modification minimum value for property 'amlogic,channel-interrupts'.
- Add register offsets to the parameter structure to reduce definition of a function.
- Link to v1: https://lore.kernel.org/r/20250219-irqchip-gpio-a4-a5-v1-0-3c8e44ae42df at amlogic.com

---
Xianwei Zhao (4):
      dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
      irqchip: Add support for Amlogic A4 and A5 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
      arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

 .../amlogic,meson-gpio-intc.yaml                   | 19 ++++++++-
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 19 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 ++++++
 drivers/irqchip/irq-meson-gpio.c                   | 48 +++++++++++++++++-----
 4 files changed, 86 insertions(+), 12 deletions(-)
---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20241213-irqchip-gpio-a4-a5-80c50a1456c4

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 10 20:08:30 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Tue, 11 Mar 2025 11:08:30 +0800
Subject: [PATCH v5 4/4] arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <20250311-irqchip-gpio-a4-a5-v5-4-ca4cc276c18c@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 17a6316de891..32ed1776891b 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -48,3 +48,15 @@ pwrc: power-controller {
 		};
 	};
 };
+
+&apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a5-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+};

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 10 20:08:28 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Tue, 11 Mar 2025 11:08:28 +0800
Subject: [PATCH v5 2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <20250311-irqchip-gpio-a4-a5-v5-2-ca4cc276c18c@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

The Amlogic A4 SoCs support 12 GPIO IRQ lines and 2 AO GPIO IRQ lines,
A5 SoCs support 12 GPIO IRQ lines, details are as below.

A4 IRQ Number:
- 72:55   18 pins on bank T
- 54:32   23 pins on bank X
- 31:16   16 pins on bank D
- 15:14    2 pins on bank E
- 13:0    14 pins on bank B

A4 AO IRQ Number:
- 7       1 pin  on bank TESTN
- 6:0     7 pins on bank AO

A5 IRQ Number:
- 98      1 pin  on bank TESTN
- 97:82   16 pins on bank Z
- 81:62   20 pins on bank X
- 61:48   14 pins on bank T
- 47:32   16 pins on bank D
- 31:27    5 pins on bank H
- 26:25    2 pins on bank E
- 24:14   11 pins on bank C
- 13:0    14 pins on bank B

Reviewed-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/irqchip/irq-meson-gpio.c | 48 +++++++++++++++++++++++++++++++---------
 1 file changed, 37 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index cd789fa51519..0a25536a5d07 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -26,8 +26,6 @@
 
 /* use for A1 like chips */
 #define REG_PIN_A1_SEL	0x04
-/* Used for s4 chips */
-#define REG_EDGE_POL_S4	0x1c
 
 /*
  * Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
@@ -72,6 +70,7 @@ struct meson_gpio_irq_params {
 	bool support_edge_both;
 	unsigned int edge_both_offset;
 	unsigned int edge_single_offset;
+	unsigned int edge_pol_reg;
 	unsigned int pol_low_offset;
 	unsigned int pin_sel_mask;
 	struct irq_ctl_ops ops;
@@ -105,6 +104,18 @@ struct meson_gpio_irq_params {
 	.pin_sel_mask = 0x7f,					\
 	.nr_channels = 8,					\
 
+#define INIT_MESON_A4_AO_COMMON_DATA(irqs)			\
+	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
+			  meson_a1_gpio_irq_sel_pin,		\
+			  meson_s4_gpio_irq_set_type)		\
+	.support_edge_both = true,				\
+	.edge_both_offset = 0,					\
+	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x8,					\
+	.pol_low_offset = 0,					\
+	.pin_sel_mask = 0xff,					\
+	.nr_channels = 2,					\
+
 #define INIT_MESON_S4_COMMON_DATA(irqs)				\
 	INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,		\
 			  meson_a1_gpio_irq_sel_pin,		\
@@ -112,6 +123,7 @@ struct meson_gpio_irq_params {
 	.support_edge_both = true,				\
 	.edge_both_offset = 0,					\
 	.edge_single_offset = 12,				\
+	.edge_pol_reg = 0x1c,					\
 	.pol_low_offset = 0,					\
 	.pin_sel_mask = 0xff,					\
 	.nr_channels = 12,					\
@@ -146,6 +158,18 @@ static const struct meson_gpio_irq_params a1_params = {
 	INIT_MESON_A1_COMMON_DATA(62)
 };
 
+static const struct meson_gpio_irq_params a4_params = {
+	INIT_MESON_S4_COMMON_DATA(81)
+};
+
+static const struct meson_gpio_irq_params a4_ao_params = {
+	INIT_MESON_A4_AO_COMMON_DATA(8)
+};
+
+static const struct meson_gpio_irq_params a5_params = {
+	INIT_MESON_S4_COMMON_DATA(99)
+};
+
 static const struct meson_gpio_irq_params s4_params = {
 	INIT_MESON_S4_COMMON_DATA(82)
 };
@@ -168,6 +192,9 @@ static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
 	{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
 	{ .compatible = "amlogic,meson-a1-gpio-intc", .data = &a1_params },
 	{ .compatible = "amlogic,meson-s4-gpio-intc", .data = &s4_params },
+	{ .compatible = "amlogic,a4-gpio-ao-intc", .data = &a4_ao_params },
+	{ .compatible = "amlogic,a4-gpio-intc", .data = &a4_params },
+	{ .compatible = "amlogic,a5-gpio-intc", .data = &a5_params },
 	{ .compatible = "amlogic,c3-gpio-intc", .data = &c3_params },
 	{ .compatible = "amlogic,t7-gpio-intc", .data = &t7_params },
 	{ }
@@ -299,11 +326,10 @@ meson_gpio_irq_release_channel(struct meson_gpio_irq_controller *ctl,
 static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 				    unsigned int type, u32 *channel_hwirq)
 {
-	u32 val = 0;
+	const struct meson_gpio_irq_params *params = ctl->params;
 	unsigned int idx;
-	const struct meson_gpio_irq_params *params;
+	u32 val = 0;
 
-	params = ctl->params;
 	idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
 
 	/*
@@ -356,19 +382,19 @@ static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 				      unsigned int type, u32 *channel_hwirq)
 {
-	u32 val = 0;
+	const struct meson_gpio_irq_params *params = ctl->params;
 	unsigned int idx;
+	u32 val = 0;
 
 	idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
 
 	type &= IRQ_TYPE_SENSE_MASK;
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4, BIT(idx), 0);
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg, BIT(idx), 0);
 
 	if (type == IRQ_TYPE_EDGE_BOTH) {
-		val |= BIT(ctl->params->edge_both_offset + idx);
-		meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4,
-					   BIT(ctl->params->edge_both_offset + idx), val);
+		val = BIT(ctl->params->edge_both_offset + idx);
+		meson_gpio_irq_update_bits(ctl, params->edge_pol_reg, val, val);
 		return 0;
 	}
 
@@ -378,7 +404,7 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
 		val |= BIT(ctl->params->edge_single_offset + idx);
 
-	meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
+	meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
 				   BIT(idx) | BIT(12 + idx), val);
 	return 0;
 };

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 10 20:08:29 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Tue, 11 Mar 2025 11:08:29 +0800
Subject: [PATCH v5 3/4] arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <20250311-irqchip-gpio-a4-a5-v5-3-ca4cc276c18c@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add GPIO interrupt controller device.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index efba8565af3c..fa80fa365f13 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -51,6 +51,25 @@ pwrc: power-controller {
 };
 
 &apb {
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a4-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+
+	gpio_ao_intc: interrupt-controller at 8e72c {
+		compatible = "amlogic,a4-gpio-ao-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x8e72c 0x0 0x0c>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts = <140 141>;
+	};
+
 	periphs_pinctrl: pinctrl {
 		compatible = "amlogic,pinctrl-a4";
 		#address-cells = <2>;

-- 
2.37.1




From shawnguo2 at yeah.net  Mon Mar 10 20:17:18 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 11:17:18 +0800
Subject: [PATCH v2 0/4] arm: fsl: drop usage of Toradex SOMs compatible
 alone
In-Reply-To: <20250228151352.91768-1-francesco@dolcini.it>
References: <20250228151352.91768-1-francesco@dolcini.it>
Message-ID: <Z8+rPvG177Csh2m1@dragon>

On Fri, Feb 28, 2025 at 04:13:48PM +0100, Francesco Dolcini wrote:
> From: Francesco Dolcini <francesco.dolcini at toradex.com>
> 
> The Toradex SOMs cannot be used alone without a carrier board, so drop
> the usage of its compatible alone.
> 
> Francesco Dolcini (4):
>   dt-bindings: arm: fsl: drop usage of Toradex SOMs compatible alone
>   ARM: dts: imx6qdl-apalis/colibri: Remove compatible from SoM dtsi
>   arm64: dts: imx8qm-apalis: Remove compatible from SoM dtsi
>   ARM: dts: vf610-colibri: Remove compatible from SoM dtsi

Applied all, thanks!



From shawnguo2 at yeah.net  Mon Mar 10 20:36:19 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Tue, 11 Mar 2025 11:36:19 +0800
Subject: [PATCH v4 0/3] Add Variscite i.MX6UL SoM and Concerto board
 support
In-Reply-To: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v4-0-6034fda6ec64@bootlin.com>
Message-ID: <Z8+vs+0dKyBDMU5b@dragon>

On Mon, Mar 10, 2025 at 05:39:47PM +0100, Antonin Godard wrote:
> Antonin Godard (3):
>       dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and Concerto board
>       ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM support
>       ARM: dts: imx6ul: Add Variscite Concerto board support

Applied all, thanks!



From ankita at nvidia.com  Mon Mar 10 20:42:23 2025
From: ankita at nvidia.com (Ankit Agrawal)
Date: Tue, 11 Mar 2025 03:42:23 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <861pv5p0c3.wl-maz@kernel.org>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com> <861pv5p0c3.wl-maz@kernel.org>
Message-ID: <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>

>> +???? /*
>> +????? *? When FWB is unsupported KVM needs to do cache flushes
>> +????? *? (via dcache_clean_inval_poc()) of the underlying memory. This is
>> +????? *? only possible if the memory is already mapped into the kernel map.
>> +????? *
>> +????? *? Outright reject as the cacheable device memory is not present in
>> +????? *? the kernel map and not suitable for cache management.
>> +????? */
>> +???? if (cacheable_devmem && !stage2_has_fwb(pgt)) {
>> +???????????? ret = -EINVAL;
>> +???????????? goto out_unlock;
>> +???? }
>> +
>
> These new error reasons should at least be complemented by an
> equivalent check at the point where the memslot is registered. It

Understood. I can add such check in kvm_arch_prepare_memory_region().


> maybe OK to blindly return an error at fault time (because userspace
> has messed with the mapping behind our back), but there should at
> least be something telling a well behaved userspace that there is a
> bunch of combination we're unwilling to support.

How about WARN_ON() or BUG() for the faulty situation?


> Which brings me to the next point: FWB is not discoverable from
> userspace. How do you expect a VMM to know what it can or cannot do?

Good point. I am not sure if it can. I suppose you are concerned about error
during fault handling when !FWB without VMM having any clear indications
of the cause? Perhaps we can gracefully fall back to the default device mapping
in such case? But that would cause VM to crash as soon as it makes some
access violating DEVICE_nGnRE.

>??????? M.
>
> --
> Without deviation from the norm, progress is not possible.


From yezhenyu2 at huawei.com  Mon Mar 10 21:03:19 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:19 +0800
Subject: [PATCH v1 3/5] arm64/kvm: using ioctl to enable/disable the HDBSS feature
In-Reply-To: <20250311040321.1460-1-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
Message-ID: <20250311040321.1460-4-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

In ARM64, the buffer size corresponding to the HDBSS feature is
configurable. Therefore, we cannot enable the HDBSS feature during
KVM initialization, but we should enable it when triggering a
live migration, where the buffer size can be configured by the user.

The KVM_CAP_ARM_HW_DIRTY_STATE_TRACK ioctl is added to enable/disable
this feature. Users (such as qemu) can invoke the ioctl to enable
HDBSS at the beginning of the migration and disable the feature by
invoking the ioctl again at the end of the migration with size set to 0.

Signed-off-by: eillon <yezhenyu2 at huawei.com>
---
 arch/arm64/include/asm/cpufeature.h | 12 +++++
 arch/arm64/include/asm/kvm_host.h   |  6 +++
 arch/arm64/include/asm/kvm_mmu.h    | 12 +++++
 arch/arm64/include/asm/sysreg.h     | 12 +++++
 arch/arm64/kvm/arm.c                | 70 +++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/vhe/switch.c     |  1 +
 arch/arm64/kvm/mmu.c                |  3 ++
 arch/arm64/kvm/reset.c              |  7 +++
 include/linux/kvm_host.h            |  1 +
 include/uapi/linux/kvm.h            |  1 +
 tools/include/uapi/linux/kvm.h      |  1 +
 11 files changed, 126 insertions(+)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..c76d51506562 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -743,6 +743,18 @@ static __always_inline bool system_supports_fpsimd(void)
 	return alternative_has_cap_likely(ARM64_HAS_FPSIMD);
 }
 
+static inline bool system_supports_hdbss(void)
+{
+	u64 mmfr1;
+	u32 val;
+
+	mmfr1 =	read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+	val = cpuid_feature_extract_unsigned_field(mmfr1,
+						ID_AA64MMFR1_EL1_HAFDBS_SHIFT);
+
+	return val == ID_AA64MMFR1_EL1_HAFDBS_HDBSS;
+}
+
 static inline bool system_uses_hw_pan(void)
 {
 	return alternative_has_cap_unlikely(ARM64_HAS_PAN);
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d919557af5e5..bd73ee92b12c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -787,6 +787,12 @@ struct kvm_vcpu_arch {
 
 	/* Per-vcpu CCSIDR override or NULL */
 	u32 *ccsidr;
+
+	/* HDBSS registers info */
+	struct {
+		u64 br_el2;
+		u64 prod_el2;
+	} hdbss;
 };
 
 /*
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index b98ac6aa631f..ed5b68c2085e 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -330,6 +330,18 @@ static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu,
 	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
 }
 
+static __always_inline void __load_hdbss(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->kvm->enable_hdbss)
+		return;
+
+	write_sysreg_s(vcpu->arch.hdbss.br_el2, SYS_HDBSSBR_EL2);
+	write_sysreg_s(vcpu->arch.hdbss.prod_el2, SYS_HDBSSPROD_EL2);
+
+	dsb(sy);
+	isb();
+}
+
 static inline struct kvm *kvm_s2_mmu_to_kvm(struct kvm_s2_mmu *mmu)
 {
 	return container_of(mmu->arch, struct kvm, arch);
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index b727772c06fb..3040eac74f8c 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -1105,6 +1105,18 @@
 #define GCS_CAP(x)	((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
 					       GCS_CAP_VALID_TOKEN)
 
+/*
+ * Definitions for the HDBSS feature
+ */
+#define HDBSS_MAX_SIZE		HDBSSBR_EL2_SZ_2MB
+
+#define HDBSSBR_EL2(baddr, sz)	(((baddr) & GENMASK(55, 12 + sz)) | \
+				 ((sz) << HDBSSBR_EL2_SZ_SHIFT))
+#define HDBSSBR_BADDR(br)	((br) & GENMASK(55, (12 + HDBSSBR_SZ(br))))
+#define HDBSSBR_SZ(br)		(((br) & HDBSSBR_EL2_SZ_MASK) >> HDBSSBR_EL2_SZ_SHIFT)
+
+#define HDBSSPROD_IDX(prod)	(((prod) & HDBSSPROD_EL2_INDEX_MASK) >> HDBSSPROD_EL2_INDEX_SHIFT)
+
 #define ARM64_FEATURE_FIELD_BITS	4
 
 /* Defined for compatibility only, do not add new users. */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0160b4924351..825cfef3b1c2 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -80,6 +80,70 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
 }
 
+static int kvm_cap_arm_enable_hdbss(struct kvm *kvm,
+				    struct kvm_enable_cap *cap)
+{
+	unsigned long i;
+	struct kvm_vcpu *vcpu;
+	struct page *hdbss_pg;
+	int size = cap->args[0];
+
+	if (!system_supports_hdbss()) {
+		kvm_err("This system does not support HDBSS!\n");
+		return -EINVAL;
+	}
+
+	if (size < 0 || size > HDBSS_MAX_SIZE) {
+		kvm_err("Invalid HDBSS buffer size: %d!\n", size);
+		return -EINVAL;
+	}
+
+	/* Enable the HDBSS feature if size > 0, otherwise disable it. */
+	if (size) {
+		kvm->enable_hdbss = true;
+		kvm->arch.mmu.vtcr |= VTCR_EL2_HD | VTCR_EL2_HDBSS;
+
+		kvm_for_each_vcpu(i, vcpu, kvm) {
+			hdbss_pg = alloc_pages(GFP_KERNEL, size);
+			if (!hdbss_pg) {
+				kvm_err("Alloc HDBSS buffer failed!\n");
+				return -EINVAL;
+			}
+
+			vcpu->arch.hdbss.br_el2 = HDBSSBR_EL2(page_to_phys(hdbss_pg), size);
+			vcpu->arch.hdbss.prod_el2 = 0;
+
+			/*
+			 * We should kick vcpus out of guest mode here to
+			 * load new vtcr value to vtcr_el2 register when
+			 * re-enter guest mode.
+			 */
+			kvm_vcpu_kick(vcpu);
+		}
+
+		kvm_info("Enable HDBSS success, HDBSS buffer size: %d\n", size);
+	} else if (kvm->enable_hdbss) {
+		kvm->arch.mmu.vtcr &= ~(VTCR_EL2_HD | VTCR_EL2_HDBSS);
+
+		kvm_for_each_vcpu(i, vcpu, kvm) {
+			/* Kick vcpus to flush hdbss buffer. */
+			kvm_vcpu_kick(vcpu);
+
+			hdbss_pg = phys_to_page(HDBSSBR_BADDR(vcpu->arch.hdbss.br_el2));
+			if (hdbss_pg)
+				__free_pages(hdbss_pg, HDBSSBR_SZ(vcpu->arch.hdbss.br_el2));
+
+			vcpu->arch.hdbss.br_el2 = 0;
+			vcpu->arch.hdbss.prod_el2 = 0;
+		}
+
+		kvm->enable_hdbss = false;
+		kvm_info("Disable HDBSS success\n");
+	}
+
+	return 0;
+}
+
 int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 			    struct kvm_enable_cap *cap)
 {
@@ -125,6 +189,9 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 		}
 		mutex_unlock(&kvm->slots_lock);
 		break;
+	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
+		r = kvm_cap_arm_enable_hdbss(kvm, cap);
+		break;
 	default:
 		break;
 	}
@@ -393,6 +460,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES:
 		r = BIT(0);
 		break;
+	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
+		r = system_supports_hdbss();
+		break;
 	default:
 		r = 0;
 	}
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 647737d6e8d0..6b633a219e4d 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -256,6 +256,7 @@ void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
 	__vcpu_load_switch_sysregs(vcpu);
 	__vcpu_load_activate_traps(vcpu);
 	__load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
+	__load_hdbss(vcpu);
 }
 
 void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..9c11e2292b1e 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1703,6 +1703,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	if (writable)
 		prot |= KVM_PGTABLE_PROT_W;
 
+	if (kvm->enable_hdbss && logging_active)
+		prot |= KVM_PGTABLE_PROT_DBM;
+
 	if (exec_fault)
 		prot |= KVM_PGTABLE_PROT_X;
 
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 803e11b0dc8f..4e518f9a3df0 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -153,12 +153,19 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
 void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
 	void *sve_state = vcpu->arch.sve_state;
+	struct page *hdbss_pg;
 
 	kvm_unshare_hyp(vcpu, vcpu + 1);
 	if (sve_state)
 		kvm_unshare_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu));
 	kfree(sve_state);
 	kfree(vcpu->arch.ccsidr);
+
+	if (vcpu->arch.hdbss.br_el2) {
+		hdbss_pg = phys_to_page(HDBSSBR_BADDR(vcpu->arch.hdbss.br_el2));
+		if (hdbss_pg)
+			__free_pages(hdbss_pg, HDBSSBR_SZ(vcpu->arch.hdbss.br_el2));
+	}
 }
 
 static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f34f4cfaa513..aae37141c4a6 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -862,6 +862,7 @@ struct kvm {
 	struct xarray mem_attr_array;
 #endif
 	char stats_id[KVM_STATS_NAME_SIZE];
+	bool enable_hdbss;
 };
 
 #define kvm_err(fmt, ...) \
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 45e6d8fca9b9..748891902426 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -929,6 +929,7 @@ struct kvm_enable_cap {
 #define KVM_CAP_PRE_FAULT_MEMORY 236
 #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
 #define KVM_CAP_X86_GUEST_MODE 238
+#define KVM_CAP_ARM_HW_DIRTY_STATE_TRACK 239
 
 struct kvm_irq_routing_irqchip {
 	__u32 irqchip;
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 502ea63b5d2e..27d58b751e77 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -933,6 +933,7 @@ struct kvm_enable_cap {
 #define KVM_CAP_PRE_FAULT_MEMORY 236
 #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
 #define KVM_CAP_X86_GUEST_MODE 238
+#define KVM_CAP_ARM_HW_DIRTY_STATE_TRACK 239
 
 struct kvm_irq_routing_irqchip {
 	__u32 irqchip;
-- 
2.39.3



From yezhenyu2 at huawei.com  Mon Mar 10 21:03:20 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:20 +0800
Subject: [PATCH v1 4/5] arm64/kvm: support to handle the HDBSSF event
In-Reply-To: <20250311040321.1460-1-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
Message-ID: <20250311040321.1460-5-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

Updating the dirty bitmap based on the HDBSS buffer. Similar
to the implementation of the x86 pml feature, KVM flushes the
buffers on all VM-Exits, thus we only need to kick running
vCPUs to force a VM-Exit.

Signed-off-by: eillon <yezhenyu2 at huawei.com>
---
 arch/arm64/kvm/arm.c         | 10 ++++++++
 arch/arm64/kvm/handle_exit.c | 47 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/mmu.c         |  7 ++++++
 3 files changed, 64 insertions(+)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 825cfef3b1c2..fceceeead011 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1845,7 +1845,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 
 void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
+	/*
+	 * Flush all CPUs' dirty log buffers to the dirty_bitmap.  Called
+	 * before reporting dirty_bitmap to userspace.  KVM flushes the buffers
+	 * on all VM-Exits, thus we only need to kick running vCPUs to force a
+	 * VM-Exit.
+	 */
+	struct kvm_vcpu *vcpu;
+	unsigned long i;
 
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vcpu_kick(vcpu);
 }
 
 static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 512d152233ff..db9d7e1f72bf 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -330,6 +330,50 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
 	return arm_exit_handlers[esr_ec];
 }
 
+#define HDBSS_ENTRY_VALID_SHIFT 0
+#define HDBSS_ENTRY_VALID_MASK (1UL << HDBSS_ENTRY_VALID_SHIFT)
+#define HDBSS_ENTRY_IPA_SHIFT 12
+#define HDBSS_ENTRY_IPA_MASK GENMASK_ULL(55, HDBSS_ENTRY_IPA_SHIFT)
+
+static void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu)
+{
+	int idx, curr_idx;
+	u64 *hdbss_buf;
+
+	if (!vcpu->kvm->enable_hdbss)
+		return;
+
+	dsb(sy);
+	isb();
+	curr_idx = HDBSSPROD_IDX(read_sysreg_s(SYS_HDBSSPROD_EL2));
+
+	/* Do nothing if HDBSS buffer is empty or br_el2 is NULL */
+	if (curr_idx == 0 || vcpu->arch.hdbss.br_el2 == 0)
+		return;
+
+	hdbss_buf = page_address(phys_to_page(HDBSSBR_BADDR(vcpu->arch.hdbss.br_el2)));
+	if (!hdbss_buf) {
+		kvm_err("Enter flush hdbss buffer with buffer == NULL!");
+		return;
+	}
+
+	for (idx = 0; idx < curr_idx; idx++) {
+		u64 gpa;
+
+		gpa = hdbss_buf[idx];
+		if (!(gpa & HDBSS_ENTRY_VALID_MASK))
+			continue;
+
+		gpa = gpa & HDBSS_ENTRY_IPA_MASK;
+		kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
+	}
+
+	/* reset HDBSS index */
+	write_sysreg_s(0, SYS_HDBSSPROD_EL2);
+	dsb(sy);
+	isb();
+}
+
 /*
  * We may be single-stepping an emulated instruction. If the emulation
  * has been completed in the kernel, we can return to userspace with a
@@ -365,6 +409,9 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
 {
 	struct kvm_run *run = vcpu->run;
 
+	if (vcpu->kvm->enable_hdbss)
+		kvm_flush_hdbss_buffer(vcpu);
+
 	if (ARM_SERROR_PENDING(exception_index)) {
 		/*
 		 * The SError is handled by handle_exit_early(). If the guest
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 9c11e2292b1e..3e0781ae0ae1 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1790,6 +1790,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
 	ipa = fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
 	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
 
+	/*
+	 * HDBSS buffer already flushed when enter handle_trap_exceptions().
+	 * Nothing to do here.
+	 */
+	if (ESR_ELx_ISS2(esr) & ESR_ELx_HDBSSF)
+		return 1;
+
 	if (esr_fsc_is_translation_fault(esr)) {
 		/* Beyond sanitised PARange (which is the IPA limit) */
 		if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
-- 
2.39.3



From yezhenyu2 at huawei.com  Mon Mar 10 21:03:17 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:17 +0800
Subject: [PATCH v1 1/5] arm64/sysreg: add HDBSS related register information
In-Reply-To: <20250311040321.1460-1-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
Message-ID: <20250311040321.1460-2-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

The ARM architecture added the HDBSS feature and descriptions of
related registers (HDBSSBR/HDBSSPROD) in the DDI0601(ID121123) version,
add them to Linux.

Signed-off-by: eillon <yezhenyu2 at huawei.com>
---
 arch/arm64/include/asm/esr.h          |  2 ++
 arch/arm64/include/asm/kvm_arm.h      |  1 +
 arch/arm64/include/asm/sysreg.h       |  4 ++++
 arch/arm64/tools/sysreg               | 28 +++++++++++++++++++++++++++
 tools/arch/arm64/include/asm/sysreg.h |  4 ++++
 5 files changed, 39 insertions(+)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index d1b1a33f9a8b..a33befe0999a 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -147,6 +147,8 @@
 #define ESR_ELx_CM 		(UL(1) << ESR_ELx_CM_SHIFT)
 
 /* ISS2 field definitions for Data Aborts */
+#define ESR_ELx_HDBSSF_SHIFT	(11)
+#define ESR_ELx_HDBSSF		(UL(1) << ESR_ELx_HDBSSF_SHIFT)
 #define ESR_ELx_TnD_SHIFT	(10)
 #define ESR_ELx_TnD 		(UL(1) << ESR_ELx_TnD_SHIFT)
 #define ESR_ELx_TagAccess_SHIFT	(9)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index c2417a424b98..80793ef57f8b 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -122,6 +122,7 @@
 			 TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK)
 
 /* VTCR_EL2 Registers bits */
+#define VTCR_EL2_HDBSS		(1UL << 45)
 #define VTCR_EL2_DS		TCR_EL2_DS
 #define VTCR_EL2_RES1		(1U << 31)
 #define VTCR_EL2_HD		(1 << 22)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 05ea5223d2d5..b727772c06fb 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -522,6 +522,10 @@
 #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
 
 #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
+
+#define SYS_HDBSSBR_EL2			sys_reg(3, 4, 2, 3, 2)
+#define SYS_HDBSSPROD_EL2		sys_reg(3, 4, 2, 3, 3)
+
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
 #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
 #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 762ee084b37c..c2aea1e7fd22 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -2876,6 +2876,34 @@ Sysreg	GCSPR_EL2	3	4	2	5	1
 Fields	GCSPR_ELx
 EndSysreg
 
+Sysreg	HDBSSBR_EL2	3	4	2	3	2
+Res0	63:56
+Field	55:12	BADDR
+Res0	11:4
+Enum	3:0	SZ
+	0b0001	8KB
+	0b0010	16KB
+	0b0011	32KB
+	0b0100	64KB
+	0b0101	128KB
+	0b0110	256KB
+	0b0111	512KB
+	0b1000	1MB
+	0b1001	2MB
+EndEnum
+EndSysreg
+
+Sysreg	HDBSSPROD_EL2	3	4	2	3	3
+Res0	63:32
+Enum	31:26	FSC
+	0b000000	OK
+	0b010000	ExternalAbort
+	0b101000	GPF
+EndEnum
+Res0	25:19
+Field	18:0	INDEX
+EndSysreg
+
 Sysreg	DACR32_EL2	3	4	3	0	0
 Res0	63:32
 Field	31:30	D15
diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h
index 150416682e2c..95fc6a4ee655 100644
--- a/tools/arch/arm64/include/asm/sysreg.h
+++ b/tools/arch/arm64/include/asm/sysreg.h
@@ -518,6 +518,10 @@
 #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
 
 #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
+
+#define SYS_HDBSSBR_EL2			sys_reg(3, 4, 2, 3, 2)
+#define SYS_HDBSSPROD_EL2		sys_reg(3, 4, 2, 3, 3)
+
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
 #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
 #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)
-- 
2.39.3



From yezhenyu2 at huawei.com  Mon Mar 10 21:03:21 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:21 +0800
Subject: [PATCH v1 5/5] arm64/config: add config to control whether enable HDBSS feature
In-Reply-To: <20250311040321.1460-1-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
Message-ID: <20250311040321.1460-6-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

The HDBSS feature introduces new assembly registers
(HDBSSBR_EL2 and HDBSSPROD_EL2), which depends on the armv9.5-a
compilation support. So add ARM64_HDBSS config to control whether
enable the HDBSS feature.

Signed-off-by: eillon <yezhenyu2 at huawei.com>
---
 arch/arm64/Kconfig                  | 19 +++++++++++++++++++
 arch/arm64/Makefile                 |  4 +++-
 arch/arm64/include/asm/cpufeature.h |  3 +++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..3458261eb14b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2237,6 +2237,25 @@ config ARM64_GCS
 
 endmenu # "v9.4 architectural features"
 
+menu "ARMv9.5 architectural features"
+
+config ARM64_HDBSS
+	bool "Enable support for Hardware Dirty state tracking Structure (HDBSS)"
+	default y
+	depends on AS_HAS_ARMV9_5
+	help
+	  Hardware Dirty state tracking Structure(HDBSS) enhances tracking
+	  translation table descriptors? dirty state to reduce the cost of
+	  surveying for dirtied granules.
+
+	  The feature introduces new assembly registers (HDBSSBR_EL2 and
+	  HDBSSPROD_EL2), which depends on AS_HAS_ARMV9_5.
+
+config AS_HAS_ARMV9_5
+	def_bool $(cc-option,-Wa$(comma)-march=armv9.5-a)
+
+endmenu # "ARMv9.5 architectural features"
+
 config ARM64_SVE
 	bool "ARM Scalable Vector Extension support"
 	default y
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2b25d671365f..f22507fb09b9 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -103,7 +103,9 @@ endif
 # freely generate instructions which are not supported by earlier architecture
 # versions, which would prevent a single kernel image from working on earlier
 # hardware.
-ifeq ($(CONFIG_AS_HAS_ARMV8_5), y)
+ifeq ($(CONFIG_AS_HAS_ARMV9_5), y)
+  asm-arch := armv9.5-a
+else ifeq ($(CONFIG_AS_HAS_ARMV8_5), y)
   asm-arch := armv8.5-a
 else ifeq ($(CONFIG_AS_HAS_ARMV8_4), y)
   asm-arch := armv8.4-a
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index c76d51506562..32e432827934 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -748,6 +748,9 @@ static inline bool system_supports_hdbss(void)
 	u64 mmfr1;
 	u32 val;
 
+	if (!IS_ENABLED(CONFIG_ARM64_HDBSS))
+		return false;
+
 	mmfr1 =	read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
 	val = cpuid_feature_extract_unsigned_field(mmfr1,
 						ID_AA64MMFR1_EL1_HAFDBS_SHIFT);
-- 
2.39.3



From yezhenyu2 at huawei.com  Mon Mar 10 21:03:16 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:16 +0800
Subject: [PATCH v1 0/5] Support the FEAT_HDBSS introduced in Armv9.5
Message-ID: <20250311040321.1460-1-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

This series of patches add support to the Hardware Dirty state tracking
Structure(HDBSS) feature, which is introduced by the ARM architecture
in the DDI0601(ID121123) version.

The HDBSS feature is an extension to the architecture that enhances
tracking translation table descriptors' dirty state, identified as
FEAT_HDBSS.  The goal of this feature is to reduce the cost of surveying
for dirtied granules, with minimal effect on recording when a granule
has been dirtied.

The purpose of this feature is to make the execution overhead of live
migration lower to both the guest and the host, compared to existing
approaches (write-protect or search stage 2 tables).

After these patches, users(such as qemu) can use the 
KVM_CAP_ARM_HW_DIRTY_STATE_TRACK ioctl to enable or disable the HDBSS
feature before and after the live migration.

See patches for details, Thanks.

eillon (5):
  arm64/sysreg: add HDBSS related register information
  arm64/kvm: support set the DBM attr during memory abort
  arm64/kvm: using ioctl to enable/disable the HDBSS feature
  arm64/kvm: support to handle the HDBSSF event
  arm64/config: add config to control whether enable HDBSS feature

 arch/arm64/Kconfig                    | 19 +++++++
 arch/arm64/Makefile                   |  4 +-
 arch/arm64/include/asm/cpufeature.h   | 15 +++++
 arch/arm64/include/asm/esr.h          |  2 +
 arch/arm64/include/asm/kvm_arm.h      |  1 +
 arch/arm64/include/asm/kvm_host.h     |  6 ++
 arch/arm64/include/asm/kvm_mmu.h      | 12 ++++
 arch/arm64/include/asm/kvm_pgtable.h  |  3 +
 arch/arm64/include/asm/sysreg.h       | 16 ++++++
 arch/arm64/kvm/arm.c                  | 80 +++++++++++++++++++++++++++
 arch/arm64/kvm/handle_exit.c          | 47 ++++++++++++++++
 arch/arm64/kvm/hyp/pgtable.c          |  6 ++
 arch/arm64/kvm/hyp/vhe/switch.c       |  1 +
 arch/arm64/kvm/mmu.c                  | 10 ++++
 arch/arm64/kvm/reset.c                |  7 +++
 arch/arm64/tools/sysreg               | 28 ++++++++++
 include/linux/kvm_host.h              |  1 +
 include/uapi/linux/kvm.h              |  1 +
 tools/arch/arm64/include/asm/sysreg.h |  4 ++
 tools/include/uapi/linux/kvm.h        |  1 +
 20 files changed, 263 insertions(+), 1 deletion(-)

-- 
2.39.3



From yezhenyu2 at huawei.com  Mon Mar 10 21:03:18 2025
From: yezhenyu2 at huawei.com (Zhenyu Ye)
Date: Tue, 11 Mar 2025 12:03:18 +0800
Subject: [PATCH v1 2/5] arm64/kvm: support set the DBM attr during memory abort
In-Reply-To: <20250311040321.1460-1-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
Message-ID: <20250311040321.1460-3-yezhenyu2@huawei.com>

From: eillon <yezhenyu2 at huawei.com>

Since the ARMv8, the page entry has supported the DBM attribute.
Support set the attr during user_mem_abort().

Signed-off-by: eillon <yezhenyu2 at huawei.com>
---
 arch/arm64/include/asm/kvm_pgtable.h | 3 +++
 arch/arm64/kvm/hyp/pgtable.c         | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 6b9d274052c7..35648d7f08f5 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -86,6 +86,8 @@ typedef u64 kvm_pte_t;
 
 #define KVM_PTE_LEAF_ATTR_HI_S2_XN	BIT(54)
 
+#define KVM_PTE_LEAF_ATTR_HI_S2_DBM	BIT(51)
+
 #define KVM_PTE_LEAF_ATTR_HI_S1_GP	BIT(50)
 
 #define KVM_PTE_LEAF_ATTR_S2_PERMS	(KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \
@@ -252,6 +254,7 @@ enum kvm_pgtable_prot {
 
 	KVM_PGTABLE_PROT_DEVICE			= BIT(3),
 	KVM_PGTABLE_PROT_NORMAL_NC		= BIT(4),
+	KVM_PGTABLE_PROT_DBM			= BIT(5),
 
 	KVM_PGTABLE_PROT_SW0			= BIT(55),
 	KVM_PGTABLE_PROT_SW1			= BIT(56),
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index df5cc74a7dd0..3ea6bdbc02a0 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -700,6 +700,9 @@ static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot p
 	if (prot & KVM_PGTABLE_PROT_W)
 		attr |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
 
+	if (prot & KVM_PGTABLE_PROT_DBM)
+		attr |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
+
 	if (!kvm_lpa2_is_enabled())
 		attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S2_SH, sh);
 
@@ -1309,6 +1312,9 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
 	if (prot & KVM_PGTABLE_PROT_W)
 		set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
 
+	if (prot & KVM_PGTABLE_PROT_DBM)
+		set |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
+
 	if (prot & KVM_PGTABLE_PROT_X)
 		clr |= KVM_PTE_LEAF_ATTR_HI_S2_XN;
 
-- 
2.39.3



From anshuman.khandual at arm.com  Mon Mar 10 21:12:02 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 11 Mar 2025 09:42:02 +0530
Subject: [PATCH] arm64/kernel: Always use level 2 or higher for early
 mappings
In-Reply-To: <20250310183011.2591600-2-ardb+git@google.com>
References: <20250310183011.2591600-2-ardb+git@google.com>
Message-ID: <2931b574-35ff-4a3e-b073-47ca94c45787@arm.com>



On 3/11/25 00:00, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb at kernel.org>
> 
> The page table population code in map_range() uses a recursive algorithm
> to create the early mappings of the kernel, the DTB and the ID mapped
> text and data pages, and this fails to take into account that the way
> these page tables may be constructed is not precisely the same at each
> level. In particular, block mappings are not permitted at each level,
> and the code as it exists today might inadvertently create such a
> forbidden block mapping if it were used to map a region of the
> appropriate size and alignment.
> 
> This never happens in practice, given the limited size of the assets
> being mapped by the early boot code. Nonetheless, it would be better if
> this code would behave correctly in all circumstances.
> 
> So only permit block mappings at level 2, and page mappings at level 3,
> for any page size, and use table mappings exclusively at all other
> levels. This change should have no impact in practice, but it makes the
> code more robust.
> 
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> ---
>  arch/arm64/kernel/pi/map_range.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..025bb9f0aa0b 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -40,17 +40,10 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	/* Advance tbl to the entry that covers start */
>  	tbl += (start >> (lshift + PAGE_SHIFT)) % PTRS_PER_PTE;
>  
> -	/*
> -	 * Set the right block/page bits for this level unless we are
> -	 * clearing the mapping
> -	 */
> -	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> -
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -		if (level < 3 && (start | next | pa) & lmask) {
> +		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
>  			/*
>  			 * This chunk needs a finer grained mapping. Create a
>  			 * table mapping if necessary and recurse.
> @@ -64,6 +57,14 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  				  (pte_t *)(__pte_to_phys(*tbl) + va_offset),
>  				  may_use_cont, va_offset);
>  		} else {
> +			/*
> +			 * Set the right block/page bits for this level unless
> +			 * we are clearing the mapping
> +			 */
> +			if (protval)
> +				protval |= (level == 2) ? PMD_TYPE_SECT
> +							: PTE_TYPE_PAGE;
> +
>  			/*
>  			 * Start a contiguous range if start and pa are
>  			 * suitably aligned

LGTM and as Ryan mentioned, D128 ready as well !

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>


From gshan at redhat.com  Mon Mar 10 21:37:18 2025
From: gshan at redhat.com (Gavin Shan)
Date: Tue, 11 Mar 2025 14:37:18 +1000
Subject: [PATCH] KVM: arm64: Drop sort_memblock_regions()
Message-ID: <20250311043718.91004-1-gshan@redhat.com>

Drop sort_memblock_regions() and avoid sorting the copied memory
regions to be ascending order on their base addresses, because the
source memory regions should have been sorted correctly when they
are added by memblock_add() or its variants.

This is generally reverting commit a14307f5310c ("KVM: arm64: Sort
the hypervisor memblocks"). No functional changes intended.

Signed-off-by: Gavin Shan <gshan at redhat.com>
---
 arch/arm64/kvm/pkvm.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..d9c9174f89a1 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -10,7 +10,6 @@
 #include <asm/kvm_mmu.h>
 #include <linux/memblock.h>
 #include <linux/mutex.h>
-#include <linux/sort.h>
 
 #include <asm/kvm_pkvm.h>
 
@@ -24,23 +23,6 @@ static unsigned int *hyp_memblock_nr_ptr = &kvm_nvhe_sym(hyp_memblock_nr);
 phys_addr_t hyp_mem_base;
 phys_addr_t hyp_mem_size;
 
-static int cmp_hyp_memblock(const void *p1, const void *p2)
-{
-	const struct memblock_region *r1 = p1;
-	const struct memblock_region *r2 = p2;
-
-	return r1->base < r2->base ? -1 : (r1->base > r2->base);
-}
-
-static void __init sort_memblock_regions(void)
-{
-	sort(hyp_memory,
-	     *hyp_memblock_nr_ptr,
-	     sizeof(struct memblock_region),
-	     cmp_hyp_memblock,
-	     NULL);
-}
-
 static int __init register_memblock_regions(void)
 {
 	struct memblock_region *reg;
@@ -52,7 +34,6 @@ static int __init register_memblock_regions(void)
 		hyp_memory[*hyp_memblock_nr_ptr] = *reg;
 		(*hyp_memblock_nr_ptr)++;
 	}
-	sort_memblock_regions();
 
 	return 0;
 }
-- 
2.48.1



From anshuman.khandual at arm.com  Mon Mar 10 21:57:10 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 11 Mar 2025 10:27:10 +0530
Subject: [PATCH V3] arm64/mm: Define PTDESC_ORDER
Message-ID: <20250311045710.550625-1-anshuman.khandual@arm.com>

Address bytes shifted with a single 64 bit page table entry (any page table
level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
is not very readable or easy to reason about. Besides it is going to change
with D128, where each 128 bit page table entry will shift address bytes by
4 (aka 2^4 = 16) instead.

Let's just formalise this address bytes shift value into a new macro called
PTDESC_ORDER establishing a logical abstraction, thus improving readability
as well. While here re-organize EARLY_LEVEL macro along with its dependents
for better clarity. This does not cause any functional change. Also replace
all (PAGE_SHIFT - PTDESC_ORDER) instances with PTDESC_TABLE_SHIFT.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Andrey Ryabinin <ryabinin.a.a at gmail.com>
Cc: Alexander Potapenko <glider at google.com>
Cc: Andrey Konovalov <andreyknvl at gmail.com>
Cc: Dmitry Vyukov <dvyukov at google.com>
Cc: Ard Biesheuvel <ardb at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: kasan-dev at googlegroups.com
Acked-by: Ard Biesheuvel <ardb at kernel.org>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
This patch applies on v6.14-rc6

Changes in V3:

- Moved PTDESC_TABLE_SHIFT definition inside asm/pgtable-hwdef.h
- Replaced all (PAGE_SHIFT - PTDESC_ORDER) instances with PTDESC_TABLE_SHIFT

Changes in V2:

https://lore.kernel.org/all/20250310040115.91298-1-anshuman.khandual at arm.com/

- Replaced PTE_SHIFT with PTDESC_ORDER per Ard
- Re-organized EARLY_LEVEL macro per Mark

Changes in V1:

https://lore.kernel.org/all/20250307050851.4034393-1-anshuman.khandual at arm.com/

 arch/arm64/Kconfig                      |  2 +-
 arch/arm64/include/asm/kernel-pgtable.h |  8 +++----
 arch/arm64/include/asm/pgtable-hwdef.h  | 30 +++++++++++++++----------
 arch/arm64/kernel/pi/map_range.c        |  2 +-
 arch/arm64/mm/kasan_init.c              |  6 ++---
 5 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..c8f48945cc09 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -323,7 +323,7 @@ config ARCH_MMAP_RND_BITS_MIN
 	default 18
 
 # max bits determined by the following formula:
-#  VA_BITS - PAGE_SHIFT - 3
+#  VA_BITS - PTDESC_TABLE_SHIFT
 config ARCH_MMAP_RND_BITS_MAX
 	default 19 if ARM64_VA_BITS=36
 	default 24 if ARM64_VA_BITS=39
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index fd5a08450b12..9e93733523f6 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -45,11 +45,11 @@
 #define SPAN_NR_ENTRIES(vstart, vend, shift) \
 	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
 
-#define EARLY_ENTRIES(vstart, vend, shift, add) \
-	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
+#define EARLY_ENTRIES(lvl, vstart, vend) \
+	SPAN_NR_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * PTDESC_TABLE_SHIFT)
 
-#define EARLY_LEVEL(lvl, lvls, vstart, vend, add)	\
-	(lvls > lvl ? EARLY_ENTRIES(vstart, vend, SWAPPER_BLOCK_SHIFT + lvl * (PAGE_SHIFT - 3), add) : 0)
+#define EARLY_LEVEL(lvl, lvls, vstart, vend, add) \
+	((lvls) > (lvl) ? EARLY_ENTRIES(lvl, vstart, vend) + (add) : 0)
 
 #define EARLY_PAGES(lvls, vstart, vend, add) (1 	/* PGDIR page */				\
 	+ EARLY_LEVEL(3, (lvls), (vstart), (vend), add) /* each entry needs a next level page table */	\
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index a9136cc551cc..288964341404 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -7,40 +7,46 @@
 
 #include <asm/memory.h>
 
+#define PTDESC_ORDER 3
+
+/* Number of VA bits resolved by a single translation table level */
+#define PTDESC_TABLE_SHIFT	(PAGE_SHIFT - PTDESC_ORDER)
+
 /*
  * Number of page-table levels required to address 'va_bits' wide
  * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
- * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
+ * bits with PTDESC_TABLE_SHIFT bits at each page table level. Hence:
  *
- *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
+ *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), PTDESC_TABLE_SHIFT)
  *
  * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
  *
  * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
  * due to build issues. So we open code DIV_ROUND_UP here:
  *
- *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
+ *	((((va_bits) - PAGE_SHIFT) + PTDESC_TABLE_SHIFT - 1) / PTDESC_TABLE_SHIFT)
  *
  * which gets simplified as :
  */
-#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))
+#define ARM64_HW_PGTABLE_LEVELS(va_bits) \
+	(((va_bits) - PTDESC_ORDER - 1) / PTDESC_TABLE_SHIFT)
 
 /*
  * Size mapped by an entry at level n ( -1 <= n <= 3)
- * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
+ * We map PTDESC_TABLE_SHIFT at all translation levels and PAGE_SHIFT bits
  * in the final page. The maximum number of translation levels supported by
  * the architecture is 5. Hence, starting at level n, we have further
  * ((4 - n) - 1) levels of translation excluding the offset within the page.
  * So, the total number of bits mapped by an entry at level n is :
  *
- *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
+ *  ((4 - n) - 1) * PTDESC_TABLE_SHIFT + PAGE_SHIFT
  *
  * Rearranging it a bit we get :
- *   (4 - n) * (PAGE_SHIFT - 3) + 3
+ *   (4 - n) * PTDESC_TABLE_SHIFT + PTDESC_ORDER
  */
-#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	((PAGE_SHIFT - 3) * (4 - (n)) + 3)
+#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n)	(PTDESC_TABLE_SHIFT * (4 - (n)) + PTDESC_ORDER)
 
-#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PTE		(1 << PTDESC_TABLE_SHIFT)
 
 /*
  * PMD_SHIFT determines the size a level 2 page table entry can map.
@@ -49,7 +55,7 @@
 #define PMD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
 #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE-1))
-#define PTRS_PER_PMD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PMD		(1 << PTDESC_TABLE_SHIFT)
 #endif
 
 /*
@@ -59,14 +65,14 @@
 #define PUD_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
 #define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
 #define PUD_MASK		(~(PUD_SIZE-1))
-#define PTRS_PER_PUD		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_PUD		(1 << PTDESC_TABLE_SHIFT)
 #endif
 
 #if CONFIG_PGTABLE_LEVELS > 4
 #define P4D_SHIFT		ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
 #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
 #define P4D_MASK		(~(P4D_SIZE-1))
-#define PTRS_PER_P4D		(1 << (PAGE_SHIFT - 3))
+#define PTRS_PER_P4D		(1 << PTDESC_TABLE_SHIFT)
 #endif
 
 /*
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..dc68d09555b9 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -31,7 +31,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 {
 	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
 	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
-	int lshift = (3 - level) * (PAGE_SHIFT - 3);
+	int lshift = (3 - level) * PTDESC_TABLE_SHIFT;
 	u64 lmask = (PAGE_SIZE << lshift) - 1;
 
 	start	&= PAGE_MASK;
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index b65a29440a0c..d541ce45daeb 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -190,7 +190,7 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
  */
 static bool __init root_level_aligned(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 1) * PTDESC_TABLE_SHIFT;
 
 	return (addr % (PAGE_SIZE << shift)) == 0;
 }
@@ -245,7 +245,7 @@ static int __init root_level_idx(u64 addr)
 	 */
 	u64 vabits = IS_ENABLED(CONFIG_ARM64_64K_PAGES) ? VA_BITS
 							: vabits_actual;
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits) - 1) * PTDESC_TABLE_SHIFT;
 
 	return (addr & ~_PAGE_OFFSET(vabits)) >> (shift + PAGE_SHIFT);
 }
@@ -269,7 +269,7 @@ static void __init clone_next_level(u64 addr, pgd_t *tmp_pg_dir, pud_t *pud)
  */
 static int __init next_level_idx(u64 addr)
 {
-	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * (PAGE_SHIFT - 3);
+	int shift = (ARM64_HW_PGTABLE_LEVELS(vabits_actual) - 2) * PTDESC_TABLE_SHIFT;
 
 	return (addr >> (shift + PAGE_SHIFT)) % PTRS_PER_PTE;
 }
-- 
2.25.1



From senozhatsky at chromium.org  Mon Mar 10 21:58:24 2025
From: senozhatsky at chromium.org (Sergey Senozhatsky)
Date: Tue, 11 Mar 2025 13:58:24 +0900
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
Message-ID: <dubgo2s3xafoitc2olyjqmkmroiowxbpbswefhdioaeupxoqs2@z3s4uuvojvyu>

On (25/03/08 18:41), Barry Song wrote:
> On Sat, Mar 8, 2025 at 12:03?PM Nhat Pham <nphamcs at gmail.com> wrote:
> >
> > On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
> > >
> > > This patch series introduces a new mechanism called kcompressd to
> > > improve the efficiency of memory reclaiming in the operating system. The
> > > main goal is to separate the tasks of page scanning and page compression
> > > into distinct processes or threads, thereby reducing the load on the
> > > kswapd thread and enhancing overall system performance under high memory
> > > pressure conditions.
> >
> > Please excuse my ignorance, but from your cover letter I still don't
> > quite get what is the problem here? And how would decouple compression
> > and scanning help?
> 
> My understanding is as follows:
> 
> When kswapd attempts to reclaim M anonymous folios and N file folios,
> the process involves the following steps:
> 
> * t1: Time to scan and unmap anonymous folios
> * t2: Time to compress anonymous folios
> * t3: Time to reclaim file folios
> 
> Currently, these steps are executed sequentially, meaning the total time
> required to reclaim M + N folios is t1 + t2 + t3.
> 
> However, Qun-Wei's patch enables t1 + t3 and t2 to run in parallel,
> reducing the total time to max(t1 + t3, t2). This likely improves the
> reclamation speed, potentially reducing allocation stalls.

If compression kthread-s can run (have CPUs to be scheduled on).
This looks a bit like a bottleneck.  Is there anything that
guarantees forward progress?  Also, if compression kthreads
constantly preempt kswapd, then it might not be worth it to
have compression kthreads, I assume?

If we have a pagefault and need to map a page that is still in
the compression queue (not compressed and stored in zram yet, e.g.
dut to scheduling latency + slow compression algorithm) then what
happens?


From senozhatsky at chromium.org  Mon Mar 10 22:02:42 2025
From: senozhatsky at chromium.org (Sergey Senozhatsky)
Date: Tue, 11 Mar 2025 14:02:42 +0900
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram
 compression
In-Reply-To: <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
 <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
 <CAKEwX=OP9PJ9YeUvy3ZMQPByH7ELHLDfeLuuYKvPy3aCQCAJwQ@mail.gmail.com>
Message-ID: <mzythwqmi22gmuunmqcyyn7eiggevvrzkpqmjkoxsj4q4jc46s@64jdco5s6spa>

On (25/03/07 15:13), Nhat Pham wrote:
> > > +config KCOMPRESSD
> > > +       tristate "Kcompressd: Accelerated zram compression"
> > > +       depends on ZRAM
> > > +       help
> > > +         Kcompressd creates multiple daemons to accelerate the compression of pages
> > > +         in zram, offloading this time-consuming task from the zram driver.
> > > +
> > > +         This approach improves system efficiency by handling page compression separately,
> > > +         which was originally done by kswapd or direct reclaim.
> >
> > For direct reclaim, we were previously able to compress using multiple CPUs
> > with multi-threading.
> > After your patch, it seems that only a single thread/CPU is used for compression
> > so it won't necessarily improve direct reclaim performance?
> >
> > Even for kswapd, we used to have multiple threads like [kswapd0], [kswapd1],
> > and [kswapd2] for different nodes. Now, are we also limited to just one thread?
> > I also wonder if this could be handled at the vmscan level instead of the zram
> > level. then it might potentially help other sync devices or even zswap later.
> 
> Agree. A shared solution would be much appreciated. We can keep the
> kcompressd idea, but have it accept IO work from multiple sources
> (zram, zswap, whatever) through a shared API.

I guess it also need to take swapoff into consideration (especially
if it takes I/O from multiple sources)?


From stefanha at gmail.com  Mon Mar 10 22:02:44 2025
From: stefanha at gmail.com (Stefan Hajnoczi)
Date: Tue, 11 Mar 2025 13:02:44 +0800
Subject: [PATCH 2/2] block: change blk_mq_add_to_batch() third argument
 type to blk_status_t
In-Reply-To: <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com> <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
Message-ID: <CAJSP0QXZQWSVV60SWDey7i55VqAw7H+W9mQZ1uQyeOLK4TounA@mail.gmail.com>

On Tue, Mar 11, 2025 at 10:42?AM Shin'ichiro Kawasaki
<shinichiro.kawasaki at wdc.com> wrote:
>
> Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
> conditions") modified the evaluation criteria for the third argument,
> 'ioerror', in the blk_mq_add_to_batch() function. Initially, the
> function had checked if 'ioerror' equals zero. Following the commit, it
> started checking for negative error values, with the presumption that
> such values, for instance -EIO, would be passed in.
>
> However, blk_mq_add_to_batch() callers do not pass negative error
> values. Instead, they pass status codes defined in various ways:
>
> - NVMe PCI and Apple drivers pass NVMe status code
> - virtio_blk driver passes the virtblk request header status byte
> - null_blk driver passes blk_status_t
>
> These codes are either zero or positive, therefore the revised check
> fails to function as intended. Specifically, with the NVMe PCI driver,
> this modification led to the failure of the blktests test case nvme/039.
> In this test scenario, errors are artificially injected to the NVMe
> driver, resulting in positive NVMe status codes passed to
> blk_mq_add_to_batch(), which unexpectedly processes the failed I/O in a
> batch. Hence the failure.
>
> To correct the ioerror check within blk_mq_add_to_batch(), make all
> callers to uniformly pass the argument as blk_status_t. Modify the
> callers to translate their specific status codes into blk_status_t. For
> this translation, export the helper function nvme_error_status(). Adjust
> blk_mq_add_to_batch() to translate blk_status_t back into the error
> number for the appropriate check.
>
> Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
> ---
>  drivers/block/null_blk/main.c | 2 +-
>  drivers/block/virtio_blk.c    | 5 +++--

For virtio_blk:
Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>


From wiagn233 at outlook.com  Mon Mar 10 22:14:41 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Tue, 11 Mar 2025 13:14:41 +0800
Subject: [PATCH v9 RESEND] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <349d0fbe197a40068377e889a2311cb2@realtek.com>
References: <TYCPR01MB84376C7074C566865654F05098D42@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <b6b52bfcdb614137ac63fddfdaf9cb97@realtek.com>
 <OSZPR01MB843481965BA47B030566DF2698D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>
 <71ed8398-4619-4793-804d-77cad36e7402@nbd.name>
 <OSZPR01MB84345D44294ACA75A863ED6B98D62@OSZPR01MB8434.jpnprd01.prod.outlook.com>
 <349d0fbe197a40068377e889a2311cb2@realtek.com>
Message-ID: <TYCPR01MB84379512D874F722A0466D0A98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>



? 2025/3/11 8:47, Ping-Ke Shih ??:
> Shengyu Qu <wiagn233 at outlook.com> wrote:
>> Hello,
>>
>> I modified the patch as you two adviced. If you think it's ok, please
>> tell me and I'll send a v10 patch.
>>
>> Modified patch is attached below.
> 
> Since you want people review whole patch, why not just sending v10?
OK, I'll send v10 after fixing the issue you mentioned.

> 
>>
>> Best regards,
>> Shengyu
>>
>> ---
>>    drivers/net/wireless/mediatek/mt76/mt76.h     | 15 ++++++
>>    .../net/wireless/mediatek/mt76/mt7915/main.c  | 53 +++++++++++++++++--
>>    .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
>>    .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
>>    drivers/net/wireless/mediatek/mt76/util.c     | 37 +++++++++++--
>>    drivers/net/wireless/mediatek/mt76/util.h     |  2 +-
>>    6 files changed, 115 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
>> index 132148f7b107..bd943b8b20bc 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
>> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
>> @@ -28,6 +28,9 @@
>>
>>    #define MT76_TOKEN_FREE_THR	64
>>
>> +#define MT76_WED_WDS_MIN    256
>> +#define MT76_WED_WDS_MAX    272
>> +
>>    #define MT_QFLAG_WED_RING	GENMASK(1, 0)
>>    #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
>>    #define MT_QFLAG_WED		BIT(5)
>> @@ -73,6 +76,12 @@ enum mt76_wed_type {
>>    	MT76_WED_RRO_Q_IND,
>>    };
>>
>> +enum mt76_wed_state {
>> +	MT76_WED_DEFAULT,
>> +	MT76_WED_ACTIVE,
>> +	MT76_WED_WDS_ACTIVE,
>> +};
>> +
>>    struct mt76_bus_ops {
>>    	u32 (*rr)(struct mt76_dev *dev, u32 offset);
>>    	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
>> @@ -1165,6 +1174,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev);
>>    int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>>    			  struct net_device *netdev, enum tc_setup_type type,
>>    			  void *type_data);
>> +
>> +static inline int mt76_wcid_alloc(u32 *mask, int size)
>> +{
>> +	return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT);
>> +}
>> +
>>    #ifdef CONFIG_NET_MEDIATEK_SOC_WED
>>    u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
>>    int mt76_wed_offload_enable(struct mtk_wed_device *wed);
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> index 3aa31c5cefa6..07c2ce518d97 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> @@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>>    	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
>>    	bool ext_phy = mvif->phy != &dev->phy;
>>    	int idx;
>> +	u8 flags = MT76_WED_DEFAULT;
> 
> In reverse X'mas tree order.
Thanks, will fix.

> 
>>
>> -	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
>> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> +	    !is_mt7915(&dev->mt76)) {
>> +		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
>> +		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
>> +	}
>> +
>> +	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
>>    	if (idx < 0)
>>    		return -ENOSPC;
>>
> 
> [...]
> 
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> index 9d790f234e82..191f966c3f32 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
>> @@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
>>
>>    	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
>>
>> -	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> -	     is_mt7915(&dev->mt76)) ||
>> -	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
>> -		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
>> +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
> 
> In MT76, there are two styles:
>    #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
>    #ifdef CONFIG_NET_MEDIATEK_SOC_WED
> 
> I think both are correct. Just wonder why not making them consistent.
Seems you didn't receive Felix's email, check this:
https://lore.kernel.org/linux-wireless/71ed8398-4619-4793-804d-77cad36e7402 at nbd.name/

> 
>> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
>> +		if (is_mt7915(&dev->mt76) ||
>> +		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
>> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
>> +						0, 0, 0);
>> +		else
>> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
>> +						MCU_WA_PARAM_WED_VERSION,
>> +						dev->mt76.mmio.wed.rev_id, 0);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +#endif
>>
>>    	ret = mt7915_mcu_set_mwds(dev, 1);
>>    	if (ret)
> 
> 
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/7e33acd8/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/7e33acd8/attachment.sig>

From s-vadapalli at ti.com  Mon Mar 10 22:18:06 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 10:48:06 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250310210746.GA2377483@rocinante>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
Message-ID: <20250311051806.smcu4o4dxpngimth@uda0492258>

On Tue, Mar 11, 2025 at 06:07:46AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> > Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> > expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> > already reuse this macro since it accurately represents the link-state
> > field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> 
> Can you confirm for me that the following use the correct macro?
> 
>   333-static const struct j721e_pcie_data j721e_pcie_rc_data = {
>   337:	.linkdown_irq_regfield = LINK_DOWN,
>   
>   341-static const struct j721e_pcie_data j721e_pcie_ep_data = {
>   343:	.linkdown_irq_regfield = LINK_DOWN,
>   
>   347-static const struct j721e_pcie_data j7200_pcie_rc_data = {
>   350:	.linkdown_irq_regfield = J7200_LINK_DOWN,
>   
>   362-static const struct j721e_pcie_data am64_pcie_rc_data = {
>   364:	.linkdown_irq_regfield = J7200_LINK_DOWN,
>   
>   369-static const struct j721e_pcie_data am64_pcie_ep_data = {
>   371:	.linkdown_irq_regfield = J7200_LINK_DOWN,
>   
>   375-static const struct j721e_pcie_data j784s4_pcie_rc_data = {
>   379:	.linkdown_irq_regfield = LINK_DOWN,
>   
>   383-static const struct j721e_pcie_data j784s4_pcie_ep_data = {
>   385:	.linkdown_irq_regfield = LINK_DOWN,
>   
>   389-static const struct j721e_pcie_data j722s_pcie_rc_data = {
>   391:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> 
> I am asking as some use LINK_DOWN, so I wanted to make sure.

Yes, the above are accurate except for J784S4 which is fixed by this
patch. LINK_DOWN i.e. BIT(1) is applicable only to J721E which was the
first SoC after which the driver has been named. For all other SoCs, the
integration of the PCIe Controller into the SoC led to BIT(10) of the
register being used to indicate the link status.

> 
> Tht said, the following has no .linkdown_irq_regfield property set:
> 
>   355-static const struct j721e_pcie_data j7200_pcie_ep_data = {
>   356-	.mode = PCI_MODE_EP,
>   357-	.quirk_detect_quiet_flag = true,
>   358-	.quirk_disable_flr = true,
>   359-	.max_lanes = 2,
>   360-};
> 
> Would this be a problem?  Or is this as expected?

Thank you for pointing this out. This has to be fixed and the
"linkdown_irq_regfield" member has to be added to match
j7200_pcie_rc_data. I will post the fix for this.

Regards,
Siddharth.


From rppt at kernel.org  Mon Mar 10 22:27:23 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Tue, 11 Mar 2025 07:27:23 +0200
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250310095124.pa7dwgqhxglqrfes@master>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250223002229.xuk6xlp23zr72hkc@master>
 <20250310095124.pa7dwgqhxglqrfes@master>
Message-ID: <Z8_Ju0p63GBCdSG9@kernel.org>

Hi Wei,

On Mon, Mar 10, 2025 at 09:51:24AM +0000, Wei Yang wrote:
> On Sun, Feb 23, 2025 at 12:22:29AM +0000, Wei Yang wrote:
> >On Wed, Feb 19, 2025 at 09:24:31AM +0200, Mike Rapoport wrote:
> >>Hi,
> >>
> >>On Tue, Feb 18, 2025 at 03:50:04PM +0000, Wei Yang wrote:
> >>> On Thu, Feb 06, 2025 at 03:27:42PM +0200, Mike Rapoport wrote:
> >>> >From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> >>> >
> >>> >to denote areas that were reserved for kernel use either directly with
> >>> >memblock_reserve_kern() or via memblock allocations.
> >>> >
> >>> >Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> >>> >---
> >>> > include/linux/memblock.h | 16 +++++++++++++++-
> >>> > mm/memblock.c            | 32 ++++++++++++++++++++++++--------
> >>> > 2 files changed, 39 insertions(+), 9 deletions(-)
> >>> >
> >>> >diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> >>> >index e79eb6ac516f..65e274550f5d 100644
> >>> >--- a/include/linux/memblock.h
> >>> >+++ b/include/linux/memblock.h
> >>> >@@ -50,6 +50,7 @@ enum memblock_flags {
> >>> > 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
> >>> > 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
> >>> > 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
> >>> >+	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
> >>> 
> >>> Above memblock_flags, there are comments on explaining those flags.
> >>> 
> >>> Seems we miss it for MEMBLOCK_RSRV_KERN.
> >>
> >>Right, thanks!
> >> 
> >>> > 
> >>> > #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
> >>> >@@ -1459,14 +1460,14 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
> >>> > again:
> >>> > 	found = memblock_find_in_range_node(size, align, start, end, nid,
> >>> > 					    flags);
> >>> >-	if (found && !memblock_reserve(found, size))
> >>> >+	if (found && !__memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN))
> >>> 
> >>> Maybe we could use memblock_reserve_kern() directly. If my understanding is
> >>> correct, the reserved region's nid is not used.
> >>
> >>We use nid of reserved regions in reserve_bootmem_region() (commit
> >>61167ad5fecd ("mm: pass nid to reserve_bootmem_region()")) but KHO needs to
> >>know the distribution of reserved memory among the nodes before
> >>memmap_init_reserved_pages().
> >> 
> >
> >I took another look into this commit. There maybe a very corner case in which
> >will leave a reserved region with no nid set.
> >
> >memmap_init_reserved_pages()
> >    for_each_mem_region() {
> >        ...
> >	memblock_set_node(start, end, &memblock.reserved, nid);
> >    }
> >
> >We leverage the iteration here to set nid to all regions in memblock.reserved.
> >But memblock_set_node() may call memblock_double_array() to expand the array,
> >which may get a range before current start. So we would miss to set the
> >correct nid to the new reserved region.
> >
> >I have tried to create a case in memblock test. This would happen when there
> >are 126 memblock.reserved regions. And the last region is across the last two
> >node.
> >
> >One way to fix this is compare type->max in memblock_set_node(). Then check
> >this return value in memmap_init_reserved_pages(). If we found the size
> >changes, repeat the iteration.
> >
> >But this is a very trivial one, not sure it worth fix.
> >
> 
> Hi, Mike
> 
> I have done a user space test which shows we may have a chance to leave a
> region with non-nid set.
> 
> Not sure you are ok with my approach of fixing.

Wouldn't it be better to check for a change in reserved.max in
memmap_init_reserved_pages()?
 
> -- 
> Wei Yang
> Help you, Help me

-- 
Sincerely yours,
Mike.


From wiagn233 at outlook.com  Mon Mar 10 22:29:03 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Tue, 11 Mar 2025 13:29:03 +0800
Subject: [PATCH v10] wifi: mt76: mt7915: add wds support when wed is enabled
Message-ID: <TYCPR01MB84376878FE505F773182062B98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The current WED only supports 256 wcid, whereas mt7986 can support up to
512 entries, so firmware provides a rule to get sta_info by DA when wcid
is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
to 0xff by host driver.

However, firmware is unable to get sta_info from DA as DA != RA for
4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
and (768 ~ 783) for sync up to get correct sta_info.

Currently WDS+WED config is completely broken on MT7986/7981 devices if
without this patch.

Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
Changes since v1:
 - Drop duplicate setting in mmio
 - Reduce the patch size by redefining mt76_wcid_alloc
Changes since v2:
 - Rework wds wcid getting flow
Changes since v3:
 - Rebase to next-20240703
 - Sync with downstream patch
Changes since v4:
 - Rebase to next-20240802
Changes since v5:
 - Fixed build test error reported by robot
 - Rebase to next-20240805
Changes since v6:
 - Fix potential race conditions on tx/rx packets during the transition
 - Rebase to Felix's newest codebase
Changes since v7:
 - Fix build fail
Changes since v8:
 - Changed code as Shih advised
Changes since v9:
 - Changed code as Shih advised
 - Moved mt76_wcid_alloc to mt76.h
---
 drivers/net/wireless/mediatek/mt76/mt76.h     | 15 ++++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 53 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
 drivers/net/wireless/mediatek/mt76/util.c     | 37 +++++++++++--
 drivers/net/wireless/mediatek/mt76/util.h     |  2 +-
 6 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 132148f7b107..f9f11ce1f3fc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -28,6 +28,9 @@
 
 #define MT76_TOKEN_FREE_THR	64
 
+#define MT76_WED_WDS_MIN    256
+#define MT76_WED_WDS_MAX    272
+
 #define MT_QFLAG_WED_RING	GENMASK(1, 0)
 #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
 #define MT_QFLAG_WED		BIT(5)
@@ -73,6 +76,12 @@ enum mt76_wed_type {
 	MT76_WED_RRO_Q_IND,
 };
 
+enum mt76_wed_state {
+	MT76_WED_DEFAULT,
+	MT76_WED_ACTIVE,
+	MT76_WED_WDS_ACTIVE,
+};
+
 struct mt76_bus_ops {
 	u32 (*rr)(struct mt76_dev *dev, u32 offset);
 	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
@@ -1165,6 +1174,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev);
 int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct net_device *netdev, enum tc_setup_type type,
 			  void *type_data);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+	return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT);
+}
+
 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
 u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
 int mt76_wed_offload_enable(struct mtk_wed_device *wed);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 3aa31c5cefa6..fcbf4f971026 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
 	bool ext_phy = mvif->phy != &dev->phy;
+	u8 flags = MT76_WED_DEFAULT;
 	int idx;
 
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76)) {
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+	}
+
+	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
 	if (idx < 0)
 		return -ENOSPC;
 
@@ -1271,6 +1278,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 {
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
+	struct ieee80211_sta *pre_sta;
+	struct mt7915_sta *pre_msta;
+	u8 flags = MT76_WED_DEFAULT;
+	int tmp_idx;
 
 	if (enabled)
 		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
@@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
 	if (!msta->wcid.sta)
 		return;
 
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+	    !is_mt7915(&dev->mt76) &&
+	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
+		if (!pre_sta)
+			goto error_alloc;
+		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
+
+		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+
+		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
+		if (tmp_idx < 0)
+			goto error_wcid;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
+
+		tmp_idx = msta->wcid.idx;
+		msta->wcid.idx = pre_msta->wcid.idx;
+		pre_msta->wcid.idx = (u16)tmp_idx;
+		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
+
+		synchronize_rcu();
+		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
+
+error_wcid:
+		kfree(pre_sta);
+	}
+
+error_alloc:
 	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
 }
 
@@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
 	path->mtk_wdma.queue = phy != &dev->phy;
+	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
+	    is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = msta->wcid.idx;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
 
 	ctx->dev = NULL;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9d790f234e82..191f966c3f32 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
 
 	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
 
-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-	     is_mt7915(&dev->mt76)) ||
-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+		if (is_mt7915(&dev->mt76) ||
+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+						0, 0, 0);
+		else
+			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+						MCU_WA_PARAM_WED_VERSION,
+						dev->mt76.mmio.wed.rev_id, 0);
+		if (ret)
+			return ret;
+	}
+#endif
 
 	ret = mt7915_mcu_set_mwds(dev, 1);
 	if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 49476a4182fd..c3dd0cb4a5d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
 	MCU_WA_PARAM_PDMA_RX = 0x04,
 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
 	MCU_WA_PARAM_RED = 0x0e,
+	MCU_WA_PARAM_WED_VERSION = 0x32,
 	MCU_WA_PARAM_RED_SETTING = 0x40,
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 95b3dc96e4c4..e80bef2b33a1 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 }
 EXPORT_SYMBOL_GPL(____mt76_poll_msec);
 
-int mt76_wcid_alloc(u32 *mask, int size)
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
 {
+	int max = MT76_WED_WDS_MAX;
+	int min = MT76_WED_WDS_MIN;
 	int i, idx = 0, cur;
 
 	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
@@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
 
 		idx--;
 		cur = i * 32 + idx;
-		if (cur >= size)
+
+		switch (flag) {
+		case MT76_WED_ACTIVE:
+			if (cur >= min && cur < max)
+				continue;
+
+			if (cur >= size) {
+				u32 end = max - min - 1;
+
+				i = min / 32;
+				idx = ffs(~mask[i] & GENMASK(end, 0));
+				if (!idx)
+					goto error;
+				idx--;
+				cur = min + idx;
+			}
+
 			break;
+		case MT76_WED_WDS_ACTIVE:
+			if (cur < min)
+				continue;
+			if (cur >= max)
+				goto error;
+
+			break;
+		default:
+			if (cur >= size)
+				goto error;
+			break;
+		}
 
 		mask[i] |= BIT(idx);
 		return cur;
 	}
 
+error:
 	return -1;
 }
-EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
 
 int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94c..fe95a847182e 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -27,7 +27,7 @@ enum {
 #define MT76_INCR(_var, _size) \
 	(_var = (((_var) + 1) % (_size)))
 
-int mt76_wcid_alloc(u32 *mask, int size);
+int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
 
 static inline void
 mt76_wcid_mask_set(u32 *mask, int idx)
-- 
2.48.1



From yong.liang.choong at linux.intel.com  Mon Mar 10 22:33:42 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Tue, 11 Mar 2025 13:33:42 +0800
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for
 return value in intel_tsn_lane_is_available()
In-Reply-To: <20250310152014.1d593255@kmaincent-XPS-13-7390>
References: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
 <20250310152014.1d593255@kmaincent-XPS-13-7390>
Message-ID: <3bc2cc11-3a87-479e-a0e0-c593e3214540@linux.intel.com>



On 10/3/2025 10:20 pm, Kory Maincent wrote:
> On Mon, 10 Mar 2025 13:08:35 +0800
> Choong Yong Liang <yong.liang.choong at linux.intel.com> wrote:
> 
>> Fix the warning "warn: missing error code? 'ret'" in the
>> intel_tsn_lane_is_available() function.
>>
>> The function now returns 0 to indicate that a TSN lane was found and
>> returns -EINVAL when it is not found.
>>
>> Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the
>> interface mode")
>> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> 
> This patch is a fix it should go net instead net-next.
> Could you resend the patch with net prefix?
> 
> Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
> 
> Thank you!

Hi Kory,

Thank you for your feedback. I understand that the patch is a fix. However, 
since the code is not yet in the 'net' tree, we are unable to apply the fix 
there.

I'm not sure if there is another way to handle this fix other than sending 
it to the 'net-next' tree. I would appreciate any guidance you might have 
on this matter.


From mazziesaccount at gmail.com  Mon Mar 10 22:49:35 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Tue, 11 Mar 2025 07:49:35 +0200
Subject: [PATCH v6 00/10] Support ROHM BD79124 ADC
In-Reply-To: <20250310202738.13301548@jic23-huawei>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
 <20250310202738.13301548@jic23-huawei>
Message-ID: <e685d31c-8cdc-4732-b3a8-8e70a6f82578@gmail.com>

On 10/03/2025 22:27, Jonathan Cameron wrote:
> On Mon, 10 Mar 2025 14:53:50 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> Support ROHM BD79124 ADC.
>>
>> This series adds also couple of IIO ADC helper functions for parsing the
>> channel information from the device tree. There are also new helpers
>> included for iterating and counting firmware child nodes with a specific
>> name.
>>
>> Series does also convert couple of drivers to use these helpers. The
>> rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.
>>
>> The gianfar driver under net and the thp7312 under media/i2c are added as
>> first users of the newly added "named child node" -helpers.
>>
>> There has been some discussion about how useful these ADC helpers are,
>> and whether they should support also differential and single ended channel
>> configurations. This version does not include support for those - with the
>> benefit of reduced complexity and easier to use API.
>>
>> NOTE: Patches 4,5,9 and 10 are untested as I lack of relevant HW.
>> They have been compile tested only.
> This probably wants an update.  Also, 00/10? There are only 8 that I can see.

That's odd.
There should be 10 in total. And the 4, 5, 9 and 10 was updated.

9/10:
https://lore.kernel.org/all/1c4b9b4ceb1995bce76a0ddef0e04ad0d1d81190.1741610847.git.mazziesaccount at gmail.com/

10/10:
https://lore.kernel.org/all/ab79cf4415d21ff2854fee4f4189fac555c30b7a.1741610847.git.mazziesaccount at gmail.com/

Perhaps it's because of the "net-next" in subject?

Yours,
	-- Matti


From wei.fang at nxp.com  Mon Mar 10 22:38:17 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:17 +0800
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-2-wei.fang@nxp.com>

Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 458 ++++++++++++++++++
 .../ethernet/freescale/enetc/ntmp_private.h   |  63 +++
 include/linux/fsl/ntmp.h                      | 174 +++++++
 5 files changed, 706 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..c8efbb6f2055 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,13 @@ config NXP_ENETC_PF_COMMON
 
 	  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+	tristate
+	help
+	  This module provides common functionalities for both ENETC and NETC
+	  Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+	  flower and debugfs interfaces and so on.
+
 config FSL_ENETC
 	tristate "ENETC PF driver"
 	depends on PCI_MSI
@@ -40,6 +47,7 @@ config NXP_ENETC4
 	select FSL_ENETC_CORE
 	select FSL_ENETC_MDIO
 	select NXP_ENETC_PF_COMMON
+	select NXP_NETC_LIB
 	select PHYLINK
 	select DIMLIB
 	help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index 000000000000..df10f2f310c1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fsl/netc_global.h>
+#include <linux/iopoll.h>
+
+#include "ntmp_private.h"
+
+#define NETC_CBDR_TIMEOUT		1000 /* us */
+#define NETC_CBDR_MR_EN			BIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN		128
+#define NTMP_DATA_ADDR_ALIGN		32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID			1
+#define NTMP_RSST_ID			3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU		BIT(0)
+#define NTMP_GEN_UA_STSEU		BIT(1)
+
+#define NTMP_ENTRY_ID_SIZE		4
+#define RSST_ENTRY_NUM			64
+#define RSST_STSE_DATA_SIZE(n)		((n) * 8)
+#define RSST_CFGE_DATA_SIZE(n)		(n)
+
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+		    struct netc_cbdr_regs *regs,
+		    struct netc_cbdr *cbdr)
+{
+	size_t size;
+
+	size = cbd_num * sizeof(union netc_cbd) + NTMP_BASE_ADDR_ALIGN;
+	cbdr->addr_base = dma_alloc_coherent(dev, size, &cbdr->dma_base,
+					     GFP_KERNEL);
+	if (!cbdr->addr_base)
+		return -ENOMEM;
+
+	cbdr->dma_size = size;
+	cbdr->bd_num = cbd_num;
+	cbdr->regs = *regs;
+
+	/* The base address of the Control BD Ring must be 128 bytes aligned */
+	cbdr->dma_base_align =  ALIGN(cbdr->dma_base,  NTMP_BASE_ADDR_ALIGN);
+	cbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,
+					  NTMP_BASE_ADDR_ALIGN);
+
+	cbdr->next_to_clean = 0;
+	cbdr->next_to_use = 0;
+	spin_lock_init(&cbdr->ring_lock);
+
+	/* Step 1: Configure the base address of the Control BD Ring */
+	netc_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
+	netc_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
+
+	/* Step 2: Configure the producer index register */
+	netc_write(cbdr->regs.pir, cbdr->next_to_clean);
+
+	/* Step 3: Configure the consumer index register */
+	netc_write(cbdr->regs.cir, cbdr->next_to_use);
+
+	/* Step4: Configure the number of BDs of the Control BD Ring */
+	netc_write(cbdr->regs.lenr, cbdr->bd_num);
+
+	/* Step 5: Enable the Control BD Ring */
+	netc_write(cbdr->regs.mr, NETC_CBDR_MR_EN);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(netc_setup_cbdr);
+
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr)
+{
+	/* Disable the Control BD Ring */
+	netc_write(cbdr->regs.mr, 0);
+	dma_free_coherent(dev, cbdr->dma_size, cbdr->addr_base,
+			  cbdr->dma_base);
+	memset(cbdr, 0, sizeof(*cbdr));
+}
+EXPORT_SYMBOL_GPL(netc_teardown_cbdr);
+
+static int netc_get_free_cbd_num(struct netc_cbdr *cbdr)
+{
+	return (cbdr->next_to_clean - cbdr->next_to_use - 1 +
+		cbdr->bd_num) % cbdr->bd_num;
+}
+
+static union netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
+{
+	return &((union netc_cbd *)(cbdr->addr_base_align))[index];
+}
+
+static void netc_clean_cbdr(struct netc_cbdr *cbdr)
+{
+	union netc_cbd *cbd;
+	int i;
+
+	i = cbdr->next_to_clean;
+	while (netc_read(cbdr->regs.cir) != i) {
+		cbd = netc_get_cbd(cbdr, i);
+		memset(cbd, 0, sizeof(*cbd));
+		i = (i + 1) % cbdr->bd_num;
+	}
+
+	cbdr->next_to_clean = i;
+}
+
+static struct netc_cbdr *netc_select_cbdr(struct netc_cbdrs *cbdrs)
+{
+	int i;
+
+	for (i = 0; i < cbdrs->cbdr_num; i++) {
+		if (spin_is_locked(&cbdrs->ring[i].ring_lock))
+			continue;
+
+		return &cbdrs->ring[i];
+	}
+
+	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];
+}
+
+static int netc_xmit_ntmp_cmd(struct netc_cbdrs *cbdrs, union netc_cbd *cbd)
+{
+	union netc_cbd *cur_cbd;
+	struct netc_cbdr *cbdr;
+	int i, err;
+	u16 status;
+	u32 val;
+
+	if (cbdrs->cbdr_num == 1)
+		cbdr = &cbdrs->ring[0];
+	else
+		cbdr = netc_select_cbdr(cbdrs);
+
+	spin_lock_bh(&cbdr->ring_lock);
+
+	if (unlikely(!netc_get_free_cbd_num(cbdr)))
+		netc_clean_cbdr(cbdr);
+
+	i = cbdr->next_to_use;
+	cur_cbd = netc_get_cbd(cbdr, i);
+	*cur_cbd = *cbd;
+
+	/* Update producer index of both software and hardware */
+	i = (i + 1) % cbdr->bd_num;
+	cbdr->next_to_use = i;
+	dma_wmb();
+	netc_write(cbdr->regs.pir, i);
+
+	err = read_poll_timeout_atomic(netc_read, val, val == i,
+				       10, NETC_CBDR_TIMEOUT, true,
+				       cbdr->regs.cir);
+	if (unlikely(err))
+		goto cbdr_unlock;
+
+	dma_rmb();
+	/* Get the writeback command BD, because the caller may need
+	 * to check some other fields of the response header.
+	 */
+	*cbd = *cur_cbd;
+
+	/* Check the writeback error status */
+	status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
+	if (unlikely(status)) {
+		err = -EIO;
+		dev_err(cbdrs->dma_dev, "Command BD error: 0x%04x\n", status);
+	}
+
+	netc_clean_cbdr(cbdr);
+	dma_wmb();
+
+cbdr_unlock:
+	spin_unlock_bh(&cbdr->ring_lock);
+
+	return err;
+}
+
+static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
+{
+	void *buf;
+
+	buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+				 &data->dma, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	data->buf = buf;
+	*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
+
+	return 0;
+}
+
+static void ntmp_free_data_mem(struct ntmp_dma_buf *data)
+{
+	dma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+			  data->buf, data->dma);
+}
+
+static void ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
+				    int len, int table_id, int cmd,
+				    int access_method)
+{
+	dma_addr_t dma_align;
+
+	memset(cbd, 0, sizeof(*cbd));
+	dma_align = ALIGN(dma, NTMP_DATA_ADDR_ALIGN);
+	cbd->req_hdr.addr = cpu_to_le64(dma_align);
+	cbd->req_hdr.len = cpu_to_le32(len);
+	cbd->req_hdr.cmd = cmd;
+	cbd->req_hdr.access_method = FIELD_PREP(NTMP_ACCESS_METHOD,
+						access_method);
+	cbd->req_hdr.table_id = table_id;
+	cbd->req_hdr.ver_cci_rr = FIELD_PREP(NTMP_HDR_VERSION,
+					     NTMP_HDR_VER2);
+	/* For NTMP version 2.0 or later version */
+	cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
+}
+
+static void ntmp_fill_crd(struct common_req_data *crd,
+			  u8 tblv, u8 qa, u16 ua)
+{
+	crd->update_act = cpu_to_le16(ua);
+	crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
+}
+
+static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
+			      u8 qa, u16 ua, u32 entry_id)
+{
+	ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
+	rbe->entry_id = cpu_to_le32(entry_id);
+}
+
+static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
+				   u8 tbl_ver, u32 entry_id, u32 req_len,
+				   u32 resp_len)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct ntmp_req_by_eid *req;
+	union netc_cbd cbd;
+	u32 len;
+	int err;
+
+	if (entry_id == NTMP_NULL_ENTRY_ID)
+		return 0;
+
+	/* If the req_len is 0, indicates the requested length is the
+	 * standard length.
+	 */
+	if (!req_len)
+		req_len = sizeof(*req);
+
+	data.size = req_len >= resp_len ? req_len : resp_len;
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
+	len = NTMP_LEN(req_len, resp_len);
+	ntmp_fill_request_headr(&cbd, data.dma, len, tbl_id,
+				NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err)
+		dev_err(cbdrs->dma_dev, "Delete table (id: %d) entry failed: %d",
+			tbl_id, err);
+
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+
+static int ntmp_query_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
+				  u32 len, struct ntmp_req_by_eid *req,
+				  dma_addr_t dma, bool compare_eid)
+{
+	struct device *dev = cbdrs->dma_dev;
+	struct common_resp_query *resp;
+	int cmd = NTMP_CMD_QUERY;
+	union netc_cbd cbd;
+	u32 entry_id;
+	int err;
+
+	entry_id = le32_to_cpu(req->entry_id);
+	if (le16_to_cpu(req->crd.update_act))
+		cmd = NTMP_CMD_QU;
+
+	/* Request header */
+	ntmp_fill_request_headr(&cbd, dma, len, tbl_id,
+				cmd, NTMP_AM_ENTRY_ID);
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err) {
+		dev_err(dev, "Query table (id: %d) entry failed: %d\n",
+			tbl_id, err);
+		return err;
+	}
+
+	/* For a few tables, the first field of its response data is not
+	 * entry_id, so directly return success.
+	 */
+	if (!compare_eid)
+		return 0;
+
+	resp = (struct common_resp_query *)req;
+	if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
+		dev_err(dev, "Table (id: %d) query EID:0x%0x, response EID:0x%x\n",
+			tbl_id, entry_id, le32_to_cpu(resp->entry_id));
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			struct maft_entry_data *maft)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct maft_req_add *req;
+	union netc_cbd cbd;
+	int err;
+
+	data.size = sizeof(*req);
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	/* Set mac address filter table request data buffer */
+	ntmp_fill_crd_eid(&req->rbe, cbdrs->tbl.maft_ver, 0, 0, entry_id);
+	req->keye = maft->keye;
+	req->cfge = maft->cfge;
+
+	ntmp_fill_request_headr(&cbd, data.dma, NTMP_LEN(data.size, 0),
+				NTMP_MAFT_ID, NTMP_CMD_ADD,
+				NTMP_AM_ENTRY_ID);
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err)
+		dev_err(cbdrs->dma_dev, "Add MAFT entry failed (%d)", err);
+
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
+
+int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			  struct maft_entry_data *maft)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct maft_resp_query *resp;
+	struct ntmp_req_by_eid *req;
+	u32 req_len = sizeof(*req);
+	int err;
+
+	if (entry_id == NTMP_NULL_ENTRY_ID)
+		return -EINVAL;
+
+	data.size = sizeof(*resp);
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	ntmp_fill_crd_eid(req, cbdrs->tbl.maft_ver, 0, 0, entry_id);
+	err = ntmp_query_entry_by_id(cbdrs, NTMP_MAFT_ID,
+				     NTMP_LEN(req_len, data.size),
+				     req, data.dma, true);
+	if (err)
+		goto end;
+
+	resp = (struct maft_resp_query *)req;
+	maft->keye = resp->keye;
+	maft->cfge = resp->cfge;
+
+end:
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
+
+int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
+{
+	return ntmp_delete_entry_by_id(cbdrs, NTMP_MAFT_ID,
+				       cbdrs->tbl.maft_ver,
+				       entry_id, 0, 0);
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);
+
+int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs, u32 *table,
+				    int count, bool query)
+{
+	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
+	struct rsst_req_update *requ;
+	struct ntmp_req_by_eid *req;
+	union netc_cbd cbd;
+	int err, i;
+	u32 len;
+
+	if (count != RSST_ENTRY_NUM)
+		/* HW only takes in a full 64 entry table */
+		return -EINVAL;
+
+	if (query)
+		data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
+			    RSST_CFGE_DATA_SIZE(count);
+	else
+		data.size = struct_size(requ, groups, count);
+
+	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	if (err)
+		return err;
+
+	/* Set the request data buffer */
+	if (query) {
+		ntmp_fill_crd_eid(req, cbdrs->tbl.rsst_ver, 0, 0, 0);
+		len = NTMP_LEN(sizeof(*req), data.size);
+		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
+					NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
+	} else {
+		requ = (struct rsst_req_update *)req;
+		ntmp_fill_crd_eid(&requ->rbe, cbdrs->tbl.rsst_ver, 0,
+				  NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
+		for (i = 0; i < count; i++)
+			requ->groups[i] = (u8)(table[i]);
+
+		len = NTMP_LEN(data.size, 0);
+		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
+					NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
+	}
+
+	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
+	if (err) {
+		dev_err(cbdrs->dma_dev, "%s RSS table entry failed (%d)",
+			query ? "Query" : "Update", err);
+		goto end;
+	}
+
+	if (query) {
+		u8 *group = (u8 *)req;
+
+		group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
+		for (i = 0; i < count; i++)
+			table[i] = group[i];
+	}
+
+end:
+	ntmp_free_data_mem(&data);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_rsst_query_or_update_entry);
+
+MODULE_DESCRIPTION("NXP NETC Library");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
new file mode 100644
index 000000000000..45e4d083ab0a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * NTMP table request and response data buffer formats
+ * Copyright 2025 NXP
+ */
+
+#ifndef __NTMP_PRIVATE_H
+#define __NTMP_PRIVATE_H
+
+#include <linux/fsl/ntmp.h>
+
+struct ntmp_dma_buf {
+	struct device *dev;
+	size_t size;
+	void *buf;
+	dma_addr_t dma;
+};
+
+struct common_req_data {
+	__le16 update_act;
+	u8 dbg_opt;
+	u8 tblv_qact;
+#define NTMP_QUERY_ACT		GENMASK(3, 0)
+#define NTMP_TBL_VER		GENMASK(7, 0)
+#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
+				 ((a) & NTMP_QUERY_ACT))
+};
+
+struct common_resp_query {
+	__le32 entry_id;
+};
+
+struct common_resp_nq {
+	__le32 status;
+};
+
+/* Generic structure for request data by entry ID  */
+struct ntmp_req_by_eid {
+	struct common_req_data crd;
+	__le32 entry_id;
+};
+
+/* MAC Address Filter Table Request Data Buffer Format of Add action */
+struct maft_req_add {
+	struct ntmp_req_by_eid rbe;
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+/* MAC Address Filter Table Response Data Buffer Format of Query action */
+struct maft_resp_query {
+	__le32 entry_id;
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+/* RSS Table Request Data Buffer Format of Update action */
+struct rsst_req_update {
+	struct ntmp_req_by_eid rbe;
+	u8 groups[];
+};
+
+#endif
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
new file mode 100644
index 000000000000..fe15e394c4a4
--- /dev/null
+++ b/include/linux/fsl/ntmp.h
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+#ifndef __NETC_NTMP_H
+#define __NETC_NTMP_H
+
+#include <linux/bitops.h>
+#include <linux/if_ether.h>
+
+#define NTMP_NULL_ENTRY_ID		0xffffffffU
+#define NETC_CBDR_BD_NUM		256
+
+union netc_cbd {
+	struct {
+		__le64 addr;
+		__le32 len;
+#define NTMP_RESP_LEN		GENMASK(19, 0)
+#define NTMP_REQ_LEN		GENMASK(31, 20)
+#define NTMP_LEN(req, resp)	(FIELD_PREP(NTMP_REQ_LEN, (req)) | \
+				((resp) & NTMP_RESP_LEN))
+		u8 cmd;
+#define NTMP_CMD_DELETE		BIT(0)
+#define NTMP_CMD_UPDATE		BIT(1)
+#define NTMP_CMD_QUERY		BIT(2)
+#define NTMP_CMD_ADD		BIT(3)
+#define NTMP_CMD_QD		(NTMP_CMD_QUERY | NTMP_CMD_DELETE)
+#define NTMP_CMD_QU		(NTMP_CMD_QUERY | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AU		(NTMP_CMD_ADD | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AQ		(NTMP_CMD_ADD | NTMP_CMD_QUERY)
+#define NTMP_CMD_AQU		(NTMP_CMD_AQ | NTMP_CMD_UPDATE)
+		u8 access_method;
+#define NTMP_ACCESS_METHOD	GENMASK(7, 4)
+#define NTMP_AM_ENTRY_ID	0
+#define NTMP_AM_EXACT_KEY	1
+#define NTMP_AM_SEARCH		2
+#define NTMP_AM_TERNARY_KEY	3
+		u8 table_id;
+		u8 ver_cci_rr;
+#define NTMP_HDR_VERSION	GENMASK(5, 0)
+#define NTMP_HDR_VER2		2
+#define NTMP_CCI		BIT(6)
+#define NTMP_RR			BIT(7)
+		__le32 resv[3];
+		__le32 npf;
+#define NTMP_NPF		BIT(15)
+	} req_hdr;	/* NTMP Request Message Header Format */
+
+	struct {
+		__le32 resv0[3];
+		__le16 num_matched;
+		__le16 error_rr;
+#define NTMP_RESP_ERROR		GENMASK(11, 0)
+#define NTMP_RESP_RR		BIT(15)
+		__le32 resv1[4];
+	} resp_hdr; /* NTMP Response Message Header Format */
+};
+
+struct maft_keye_data {
+	u8 mac_addr[ETH_ALEN];
+	__le16 resv;
+};
+
+struct maft_cfge_data {
+	__le16 si_bitmap;
+	__le16 resv;
+};
+
+struct netc_cbdr_regs {
+	void __iomem *pir;
+	void __iomem *cir;
+	void __iomem *mr;
+
+	void __iomem *bar0;
+	void __iomem *bar1;
+	void __iomem *lenr;
+};
+
+struct netc_tbl_vers {
+	u8 maft_ver;
+	u8 rsst_ver;
+};
+
+struct netc_cbdr {
+	struct netc_cbdr_regs regs;
+
+	int bd_num;
+	int next_to_use;
+	int next_to_clean;
+
+	int dma_size;
+	void *addr_base;
+	void *addr_base_align;
+	dma_addr_t dma_base;
+	dma_addr_t dma_base_align;
+
+	spinlock_t ring_lock; /* Avoid race condition */
+};
+
+struct netc_cbdrs {
+	int cbdr_num;	/* number of control BD ring */
+	int cbdr_size;	/* number of BDs per control BD ring */
+	struct device *dma_dev;
+	struct netc_cbdr *ring;
+	struct netc_tbl_vers tbl;
+};
+
+enum netc_dev_type {
+	NETC_DEV_ENETC,
+	NETC_DEV_SWITCH
+};
+
+struct ntmp_priv {
+	enum netc_dev_type dev_type;
+	struct netc_cbdrs cbdrs;
+};
+
+struct maft_entry_data {
+	struct maft_keye_data keye;
+	struct maft_cfge_data cfge;
+};
+
+#if IS_ENABLED(CONFIG_NXP_NETC_LIB)
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+		    struct netc_cbdr_regs *regs,
+		    struct netc_cbdr *cbdr);
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr);
+
+/* NTMP APIs */
+int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			struct maft_entry_data *maft);
+int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+			  struct maft_entry_data *maft);
+int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id);
+int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs,
+				    u32 *table, int count, bool query);
+#else
+static inline int netc_setup_cbdr(struct device *dev, int cbd_num,
+				  struct netc_cbdr_regs *regs,
+				  struct netc_cbdr *cbdr)
+{
+	return 0;
+}
+
+static inline void netc_teardown_cbdr(struct device *dev,
+				      struct netc_cbdr *cbdr)
+{
+}
+
+static inline int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+				      struct maft_entry_data *maft)
+{
+	return 0;
+}
+
+static inline int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
+					struct maft_entry_data *maft)
+{
+	return 0;
+}
+
+static inline int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
+{
+	return 0;
+}
+
+static inline int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs,
+						  u32 *table, int count,
+						  bool query)
+{
+	return 0;
+}
+
+#endif
+
+#endif
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:18 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:18 +0800
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-3-wei.fang@nxp.com>

The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. In order to
ensure driver compatibility, struct enetc_si_ops is introduced. This
structure defines some hooks shared by VSI and PSI. Different hardware
driver will register different hooks, For example, setup_cbdr() is used
to initialize the command BD ring, and teardown_cbdr() is used to free
the command BD ring.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  | 27 +++++++--
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 +++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 55 +++++++++++++++++--
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
 .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
 5 files changed, 136 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..4ff0957e69be 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/fsl/ntmp.h>
 #include <linux/if_vlan.h>
 #include <linux/phylink.h>
 #include <linux/dim.h>
@@ -266,6 +267,19 @@ struct enetc_platform_info {
 	const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+	int (*setup_cbdr)(struct enetc_si *si);
+	void (*teardown_cbdr)(struct enetc_si *si);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
 	struct pci_dev *pdev;
@@ -274,7 +288,10 @@ struct enetc_si {
 
 	struct net_device *ndev; /* back ref. */
 
-	struct enetc_cbdr cbd_ring;
+	union {
+		struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+		struct ntmp_priv ntmp; /* ENETC 4.1 and later */
+	};
 
 	int num_rx_rings; /* how many rings are available in the SI */
 	int num_tx_rings;
@@ -284,6 +301,7 @@ struct enetc_si {
 	u16 revision;
 	int hw_features;
 	const struct enetc_drvdata *drvdata;
+	const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN	32
@@ -490,9 +508,10 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
 void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
 
 /* control buffer descriptor ring (CBDR) */
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-		     struct enetc_cbdr *cbdr);
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc_setup_cbdr(struct enetc_si *si);
+void enetc_teardown_cbdr(struct enetc_si *si);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 			    char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..63001379f0a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,23 @@ static void enetc4_configure_port(struct enetc_pf *pf)
 	enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_priv(struct enetc_si *si)
+{
+	struct ntmp_priv *ntmp = &si->ntmp;
+
+	ntmp->dev_type = NETC_DEV_ENETC;
+
+	/* For ENETC 4.1, all table versions are 0 */
+	memset(&ntmp->cbdrs.tbl, 0, sizeof(ntmp->cbdrs.tbl));
+
+	return si->ops->setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_priv(struct enetc_si *si)
+{
+	si->ops->teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
 	struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +289,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
 		return err;
 	}
 
+	err = enetc4_init_ntmp_priv(pf->si);
+	if (err) {
+		dev_err(dev, "Failed to init CBDR\n");
+		return err;
+	}
+
 	enetc4_configure_port(pf);
 
 	return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+	enetc4_free_ntmp_priv(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
@@ -688,6 +716,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
 	free_netdev(ndev);
 }
 
+static const struct enetc_si_ops enetc4_psi_ops = {
+	.setup_cbdr = enetc4_setup_cbdr,
+	.teardown_cbdr = enetc4_teardown_cbdr,
+};
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
@@ -712,6 +745,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 				     "Couldn't map PF only space\n");
 
 	si->revision = enetc_get_ip_revision(&si->hw);
+	si->ops = &enetc4_psi_ops;
 	err = enetc_get_driver_data(si);
 	if (err)
 		return dev_err_probe(dev, err,
@@ -728,14 +762,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
 	enetc_get_si_caps(si);
 
-	return enetc4_pf_netdev_create(si);
+	err = enetc4_pf_netdev_create(si);
+	if (err)
+		goto err_netdev_create;
+
+	return 0;
+
+err_netdev_create:
+	enetc4_pf_free(pf);
+
+	return err;
 }
 
 static void enetc4_pf_remove(struct pci_dev *pdev)
 {
 	struct enetc_si *si = pci_get_drvdata(pdev);
+	struct enetc_pf *pf = enetc_si_priv(si);
 
 	enetc4_pf_netdev_destroy(si);
+	enetc4_pf_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..4e5125331d7b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -3,10 +3,12 @@
 
 #include "enetc.h"
 
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-		     struct enetc_cbdr *cbdr)
+int enetc_setup_cbdr(struct enetc_si *si)
 {
-	int size = bd_count * sizeof(struct enetc_cbd);
+	int size = ENETC_CBDR_DEFAULT_SIZE * sizeof(struct enetc_cbd);
+	struct enetc_cbdr *cbdr = &si->cbd_ring;
+	struct device *dev = &si->pdev->dev;
+	struct enetc_hw *hw = &si->hw;
 
 	cbdr->bd_base = dma_alloc_coherent(dev, size, &cbdr->bd_dma_base,
 					   GFP_KERNEL);
@@ -23,7 +25,7 @@ int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 	cbdr->next_to_clean = 0;
 	cbdr->next_to_use = 0;
 	cbdr->dma_dev = dev;
-	cbdr->bd_count = bd_count;
+	cbdr->bd_count = ENETC_CBDR_DEFAULT_SIZE;
 
 	cbdr->pir = hw->reg + ENETC_SICBDRPIR;
 	cbdr->cir = hw->reg + ENETC_SICBDRCIR;
@@ -46,13 +48,45 @@ int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 }
 EXPORT_SYMBOL_GPL(enetc_setup_cbdr);
 
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
+int enetc4_setup_cbdr(struct enetc_si *si)
 {
-	int size = cbdr->bd_count * sizeof(struct enetc_cbd);
+	struct netc_cbdrs *cbdrs = &si->ntmp.cbdrs;
+	struct device *dev = &si->pdev->dev;
+	struct enetc_hw *hw = &si->hw;
+	struct netc_cbdr_regs regs;
+
+	cbdrs->cbdr_num = 1;
+	cbdrs->cbdr_size = NETC_CBDR_BD_NUM;
+	cbdrs->dma_dev = dev;
+	cbdrs->ring = devm_kcalloc(dev, cbdrs->cbdr_num,
+				   sizeof(struct netc_cbdr), GFP_KERNEL);
+	if (!cbdrs->ring)
+		return -ENOMEM;
+
+	/* set CBDR cache attributes */
+	enetc_wr(hw, ENETC_SICAR2,
+		 ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+
+	regs.pir = hw->reg + ENETC_SICBDRPIR;
+	regs.cir = hw->reg + ENETC_SICBDRCIR;
+	regs.mr = hw->reg + ENETC_SICBDRMR;
+	regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
+	regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
+	regs.lenr = hw->reg + ENETC_SICBDRLENR;
+
+	return netc_setup_cbdr(dev, cbdrs->cbdr_size, &regs, cbdrs->ring);
+}
+EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
+
+void enetc_teardown_cbdr(struct enetc_si *si)
+{
+	struct enetc_cbdr *cbdr = &si->cbd_ring;
+	int size;
 
 	/* disable ring */
 	enetc_wr_reg(cbdr->mr, 0);
 
+	size = cbdr->bd_count * sizeof(struct enetc_cbd);
 	dma_free_coherent(cbdr->dma_dev, size, cbdr->bd_base,
 			  cbdr->bd_dma_base);
 	cbdr->bd_base = NULL;
@@ -60,6 +94,15 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
 }
 EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
 
+void enetc4_teardown_cbdr(struct enetc_si *si)
+{
+	struct netc_cbdrs *cbdrs = &si->ntmp.cbdrs;
+
+	netc_teardown_cbdr(cbdrs->dma_dev, cbdrs->ring);
+	cbdrs->dma_dev = NULL;
+}
+EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
+
 static void enetc_clean_cbdr(struct enetc_cbdr *ring)
 {
 	struct enetc_cbd *dest_cbd;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..a214749a4af6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -939,6 +939,11 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
 	return enetc_ierb_register_pf(ierb_pdev, pdev);
 }
 
+static const struct enetc_si_ops enetc_psi_ops = {
+	.setup_cbdr = enetc_setup_cbdr,
+	.teardown_cbdr = enetc_teardown_cbdr,
+};
+
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 {
 	struct enetc_si *si;
@@ -957,6 +962,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 		goto out_pci_remove;
 	}
 
+	si->ops = &enetc_psi_ops;
 	si->revision = enetc_get_ip_revision(&si->hw);
 	err = enetc_get_driver_data(si);
 	if (err) {
@@ -964,8 +970,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 		goto out_pci_remove;
 	}
 
-	err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
-			       &si->cbd_ring);
+	err = si->ops->setup_cbdr(si);
 	if (err)
 		goto out_pci_remove;
 
@@ -984,7 +989,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 	return si;
 
 out_teardown_cbdr:
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 out_pci_remove:
 	enetc_pci_remove(pdev);
 out:
@@ -995,7 +1000,7 @@ static void enetc_psi_destroy(struct pci_dev *pdev)
 {
 	struct enetc_si *si = pci_get_drvdata(pdev);
 
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 	enetc_pci_remove(pdev);
 }
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 3768752b6008..d7d9a720069b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -162,6 +162,11 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	enetc_load_primary_mac_addr(&si->hw, ndev);
 }
 
+static const struct enetc_si_ops enetc_vsi_ops = {
+	.setup_cbdr = enetc_setup_cbdr,
+	.teardown_cbdr = enetc_teardown_cbdr,
+};
+
 static int enetc_vf_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *ent)
 {
@@ -176,6 +181,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 	si = pci_get_drvdata(pdev);
 	si->revision = ENETC_REV_1_0;
+	si->ops = &enetc_vsi_ops;
 	err = enetc_get_driver_data(si);
 	if (err) {
 		dev_err_probe(&pdev->dev, err,
@@ -198,8 +204,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 	enetc_init_si_rings_params(priv);
 
-	err = enetc_setup_cbdr(priv->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
-			       &si->cbd_ring);
+	err = si->ops->setup_cbdr(si);
 	if (err)
 		goto err_setup_cbdr;
 
@@ -235,7 +240,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 err_alloc_msix:
 	enetc_free_si_resources(priv);
 err_alloc_si_res:
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 err_setup_cbdr:
 	si->ndev = NULL;
 	free_netdev(ndev);
@@ -256,7 +261,7 @@ static void enetc_vf_remove(struct pci_dev *pdev)
 	enetc_free_msix(priv);
 
 	enetc_free_si_resources(priv);
-	enetc_teardown_cbdr(&si->cbd_ring);
+	si->ops->teardown_cbdr(si);
 
 	free_netdev(si->ndev);
 
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:19 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:19 +0800
Subject: [PATCH v4 net-next 03/14] net: enetc: move generic MAC filterng interfaces to enetc-core
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-4-wei.fang@nxp.com>

Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. At the same time, the struct enetc_mac_filter is
moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
MAC address filtering.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 ++++++++++++++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 17 +++++++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 49 +++----------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 14 ------
 4 files changed, 60 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2106861463e4..3832d2cd91ba 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
 	enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+	u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+	u64 mask = 0;
+	int res = 0;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		mask |= BIT_ULL(i * 6);
+
+	for (i = 0; i < 6; i++)
+		res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+	return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+				  const unsigned char *addr)
+{
+	int idx = enetc_mac_addr_hash_idx(addr);
+
+	/* add hash table entry */
+	__set_bit(idx, filter->mac_hash_table);
+	filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+	filter->mac_addr_cnt = 0;
+
+	bitmap_zero(filter->mac_hash_table,
+		    ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
 	int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ff0957e69be..9380d3e8ca01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ	64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+	union {
+		char mac_addr[ETH_ALEN];
+		DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+	};
+	int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
 	union {
 		struct sk_buff *skb;
@@ -302,6 +314,8 @@ struct enetc_si {
 	int hw_features;
 	const struct enetc_drvdata *drvdata;
 	const struct enetc_si_ops *ops;
+
+	struct enetc_mac_filter mac_filter[MADDR_TYPE];
 };
 
 #define ENETC_SI_ALIGN	32
@@ -484,6 +498,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+				  const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index a214749a4af6..cc3e52bd3096 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
 	enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-	u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-	u64 mask = 0;
-	int res = 0;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		mask |= BIT_ULL(i * 6);
-
-	for (i = 0; i < 6; i++)
-		res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-	return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-	filter->mac_addr_cnt = 0;
-
-	bitmap_zero(filter->mac_hash_table,
-		    ENETC_MADDR_HASH_TBL_SZ);
-}
-
 static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 					 const unsigned char *addr)
 {
@@ -104,16 +80,6 @@ static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 	filter->mac_addr_cnt++;
 }
 
-static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
-					 const unsigned char *addr)
-{
-	int idx = enetc_mac_addr_hash_idx(addr);
-
-	/* add hash table entry */
-	__set_bit(idx, filter->mac_hash_table);
-	filter->mac_addr_cnt++;
-}
-
 static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)
 {
 	bool err = si->errata & ENETC_ERR_UCMCSWP;
@@ -145,10 +111,9 @@ static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,
 	}
 }
 
-static void enetc_sync_mac_filters(struct enetc_pf *pf)
+static void enetc_sync_mac_filters(struct enetc_si *si)
 {
-	struct enetc_mac_filter *f = pf->mac_filter;
-	struct enetc_si *si = pf->si;
+	struct enetc_mac_filter *f = si->mac_filter;
 	int i, pos;
 
 	pos = EMETC_MAC_ADDR_FILT_RES;
@@ -192,10 +157,10 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)
 static void enetc_pf_set_rx_mode(struct net_device *ndev)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
-	struct enetc_hw *hw = &priv->si->hw;
 	bool uprom = false, mprom = false;
 	struct enetc_mac_filter *filter;
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	struct netdev_hw_addr *ha;
 	u32 psipmr = 0;
 	bool em;
@@ -214,7 +179,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 	/* first 2 filter entries belong to PF */
 	if (!uprom) {
 		/* Update unicast filters */
-		filter = &pf->mac_filter[UC];
+		filter = &si->mac_filter[UC];
 		enetc_reset_mac_addr_filter(filter);
 
 		em = (netdev_uc_count(ndev) == 1);
@@ -230,7 +195,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 
 	if (!mprom) {
 		/* Update multicast filters */
-		filter = &pf->mac_filter[MC];
+		filter = &si->mac_filter[MC];
 		enetc_reset_mac_addr_filter(filter);
 
 		netdev_for_each_mc_addr(ha, ndev) {
@@ -243,7 +208,7 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 
 	if (!uprom || !mprom)
 		/* update PF entries */
-		enetc_sync_mac_filters(pf);
+		enetc_sync_mac_filters(si);
 
 	psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) &
 		  ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index a26a12863855..2b9d0f625f01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -6,18 +6,6 @@
 
 #define ENETC_PF_NUM_RINGS	8
 
-enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
-#define ENETC_MAX_NUM_MAC_FLT	((ENETC_MAX_NUM_VFS + 1) * MADDR_TYPE)
-
-#define ENETC_MADDR_HASH_TBL_SZ	64
-struct enetc_mac_filter {
-	union {
-		char mac_addr[ETH_ALEN];
-		DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
-	};
-	int mac_addr_cnt;
-};
-
 #define ENETC_VLAN_HT_SIZE	64
 
 enum enetc_vf_flags {
@@ -52,8 +40,6 @@ struct enetc_pf {
 	int total_vfs; /* max number of VFs, set for PF at probe */
 	struct enetc_vf_state *vf_state;
 
-	struct enetc_mac_filter mac_filter[ENETC_MAX_NUM_MAC_FLT];
-
 	struct enetc_msg_swbd rxmsg[ENETC_MAX_NUM_VFS];
 	struct work_struct msg_task;
 	char msg_int_name[ENETC_INT_NAME_MAX];
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:20 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:20 +0800
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95 ENETC PF
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-5-wei.fang@nxp.com>

The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bits hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 422 +++++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  11 +
 5 files changed, 448 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 9380d3e8ca01..4dba91408e3d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -316,6 +316,8 @@ struct enetc_si {
 	const struct enetc_si_ops *ops;
 
 	struct enetc_mac_filter mac_filter[MADDR_TYPE];
+	struct workqueue_struct *workqueue;
+	struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN	32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a)		((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX		GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)		((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)		((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)		((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)		((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR			0x4004
 #define  PMCAPR_HD			BIT(8)
 #define  PMCAPR_FP			GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 63001379f0a0..7d1c545f3f56 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM	8
 
+#define ENETC_MAC_FILTER_TYPE_UC	BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC	BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL	(ENETC_MAC_FILTER_TYPE_UC | \
+					 ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+	u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
 	struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
 	val = enetc_port_rd(hw, ENETC4_PMCAPR);
 	pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+	val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+	pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,341 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
 	put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
+					 int type, bool en)
+{
+	u32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+
+	if (type == UC) {
+		if (en)
+			val |= PSIPMMR_SI_MAC_UP(si);
+		else
+			val &= ~PSIPMMR_SI_MAC_UP(si);
+	} else { /* Multicast promiscuous mode. */
+		if (en)
+			val |= PSIPMMR_SI_MAC_MP(si);
+		else
+			val &= ~PSIPMMR_SI_MAC_MP(si);
+	}
+
+	enetc_port_wr(hw, ENETC4_PSIPMMR, val);
+}
+
+static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
+					     int type, u64 hash)
+{
+	if (type == UC) {
+		enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
+		enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
+	} else { /* MC */
+		enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
+		enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
+	}
+}
+
+static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
+{
+	struct enetc_mac_list_entry *entry;
+	struct hlist_node *tmp;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+		hlist_del(&entry->node);
+		kfree(entry);
+	}
+
+	pf->num_mfe = 0;
+
+	mutex_unlock(&pf->mac_list_lock);
+}
+
+static bool enetc_mac_filter_type_check(int type, const u8 *addr)
+{
+	if (type == ENETC_MAC_FILTER_TYPE_UC)
+		return !is_multicast_ether_addr(addr);
+	else if (type == ENETC_MAC_FILTER_TYPE_MC)
+		return is_multicast_ether_addr(addr);
+	else
+		return true;
+}
+
+static struct enetc_mac_list_entry *
+enetc_mac_list_lookup_entry(struct enetc_pf *pf, const unsigned char *addr)
+{
+	struct enetc_mac_list_entry *entry;
+
+	hlist_for_each_entry(entry, &pf->mac_list, node)
+		if (ether_addr_equal(entry->mac, addr))
+			return entry;
+
+	return NULL;
+}
+
+static void enetc_mac_list_add_entry(struct enetc_pf *pf,
+				     struct enetc_mac_list_entry *entry)
+{
+	hlist_add_head(&entry->node, &pf->mac_list);
+}
+
+static void enetc_mac_list_del_entry(struct enetc_mac_list_entry *entry)
+{
+	hlist_del(&entry->node);
+	kfree(entry);
+}
+
+static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16 si_bit,
+					       struct enetc_mac_addr *mac,
+					       int mac_cnt)
+{
+	struct enetc_mac_list_entry *entry;
+	int i;
+
+	for (i = 0; i < mac_cnt; i++) {
+		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
+		if (!entry)
+			continue;
+
+		entry->si_bitmap &= ~si_bit;
+		if (entry->si_bitmap)
+			continue;
+
+		enetc_mac_list_del_entry(entry);
+		pf->num_mfe--;
+	}
+}
+
+static bool enetc_mac_list_is_available(struct enetc_pf *pf,
+					struct enetc_mac_addr *mac,
+					int mac_cnt)
+{
+	int max_num_mfe = pf->caps.mac_filter_num;
+	struct enetc_mac_list_entry *entry;
+	int cur_num_mfe = pf->num_mfe;
+	int i, new_mac_cnt = 0;
+
+	if (mac_cnt > max_num_mfe)
+		return false;
+
+	/* Check MAC filter table whether has enough available entries */
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		for (i = 0; i < mac_cnt; i++) {
+			if (ether_addr_equal(entry->mac, mac[i].addr))
+				break;
+		}
+
+		if (i == mac_cnt)
+			new_mac_cnt++;
+
+		if ((cur_num_mfe + new_mac_cnt) > max_num_mfe)
+			return false;
+	}
+
+	return true;
+}
+
+static int enetc4_pf_add_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
+					     struct enetc_mac_addr *mac,
+					     int mac_cnt)
+{
+	struct enetc_mac_list_entry *entry;
+	struct maft_entry_data data = {0};
+	struct enetc_si *si = pf->si;
+	u16 si_bit = BIT(si_id);
+	int i, num_mfe, err = 0;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	if (!enetc_mac_list_is_available(pf, mac, mac_cnt)) {
+		err = -ENOSPC;
+		goto mac_list_unlock;
+	}
+
+	num_mfe = pf->num_mfe;
+	/* Update mac_list */
+	for (i = 0; i < mac_cnt; i++) {
+		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
+		if (entry) {
+			entry->si_bitmap |= si_bit;
+			continue;
+		}
+
+		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+		if (unlikely(!entry)) {
+			/* Restore MAC list to the state before the update
+			 * if an error occurs.
+			 */
+			enetc_mac_list_del_matched_entries(pf, si_bit,
+							   mac, i + 1);
+			err = -ENOMEM;
+			goto mac_list_unlock;
+		}
+
+		ether_addr_copy(entry->mac, mac[i].addr);
+		entry->si_bitmap = si_bit;
+		enetc_mac_list_add_entry(pf, entry);
+		pf->num_mfe++;
+	}
+
+	/* Clear MAC filter table */
+	for (i = 0; i < num_mfe; i++)
+		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
+
+	i = 0;
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
+		ether_addr_copy(data.keye.mac_addr, entry->mac);
+		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
+	}
+
+mac_list_unlock:
+	mutex_unlock(&pf->mac_list_lock);
+
+	return err;
+}
+
+static void enetc4_pf_flush_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
+						int mac_type)
+{
+	struct enetc_mac_list_entry *entry;
+	struct maft_entry_data data = {0};
+	struct enetc_si *si = pf->si;
+	u16 si_bit = BIT(si_id);
+	struct hlist_node *tmp;
+	int i, num_mfe;
+
+	mutex_lock(&pf->mac_list_lock);
+
+	num_mfe = pf->num_mfe;
+	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+		if (enetc_mac_filter_type_check(mac_type, entry->mac) &&
+		    entry->si_bitmap & si_bit) {
+			entry->si_bitmap ^= si_bit;
+			if (entry->si_bitmap)
+				continue;
+
+			enetc_mac_list_del_entry(entry);
+			pf->num_mfe--;
+		}
+	}
+
+	for (i = 0; i < num_mfe; i++)
+		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
+
+	i = 0;
+	hlist_for_each_entry(entry, &pf->mac_list, node) {
+		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
+		ether_addr_copy(data.keye.mac_addr, entry->mac);
+		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
+	}
+
+	mutex_unlock(&pf->mac_list_lock);
+}
+
+static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
+{
+	int max_num_mfe = pf->caps.mac_filter_num;
+	struct net_device *ndev = pf->si->ndev;
+	struct enetc_mac_addr *mac_tbl;
+	struct netdev_hw_addr *ha;
+	u8 si_mac[ETH_ALEN];
+	int mac_cnt = 0;
+	int err;
+
+	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
+	if (!mac_tbl)
+		return -ENOMEM;
+
+	enetc_get_primary_mac_addr(&pf->si->hw, si_mac);
+
+	netif_addr_lock_bh(ndev);
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		netdev_for_each_uc_addr(ha, ndev) {
+			if (!is_valid_ether_addr(ha->addr) ||
+			    ether_addr_equal(ha->addr, si_mac))
+				continue;
+
+			if (mac_cnt >= max_num_mfe)
+				goto err_nospace_out;
+
+			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
+		}
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC) {
+		netdev_for_each_mc_addr(ha, ndev) {
+			if (!is_multicast_ether_addr(ha->addr))
+				continue;
+
+			if (mac_cnt >= max_num_mfe)
+				goto err_nospace_out;
+
+			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
+		}
+	}
+	netif_addr_unlock_bh(ndev);
+
+	err = enetc4_pf_add_si_mac_exact_filter(pf, 0, mac_tbl, mac_cnt);
+	kfree(mac_tbl);
+
+	return err;
+
+err_nospace_out:
+	netif_addr_unlock_bh(ndev);
+	kfree(mac_tbl);
+
+	return -ENOSPC;
+}
+
+static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)
+{
+	struct net_device *ndev = pf->si->ndev;
+	struct enetc_mac_filter *mac_filter;
+	struct enetc_hw *hw = &pf->si->hw;
+	struct enetc_si *si = pf->si;
+	struct netdev_hw_addr *ha;
+
+	netif_addr_lock_bh(ndev);
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		mac_filter = &si->mac_filter[UC];
+		enetc_reset_mac_addr_filter(mac_filter);
+		netdev_for_each_uc_addr(ha, ndev)
+			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
+
+		enetc4_pf_set_si_mac_hash_filter(hw, 0, UC,
+						 *mac_filter->mac_hash_table);
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC) {
+		mac_filter = &si->mac_filter[MC];
+		enetc_reset_mac_addr_filter(mac_filter);
+		netdev_for_each_mc_addr(ha, ndev)
+			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
+
+		enetc4_pf_set_si_mac_hash_filter(hw, 0, MC,
+						 *mac_filter->mac_hash_table);
+	}
+	netif_addr_unlock_bh(ndev);
+}
+
+static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
+{
+	/* Currently, the MAC address filter table only has 4 entries, and the
+	 * table is shared by PF and VFs. In the default network configuration,
+	 * the MAC filter will be configured with multiple multicast addresses,
+	 * so it is only suitable for unicast filtering. If the number of unicast
+	 * addresses exceeds the table capacity, the MAC hash filter will be used.
+	 */
+	if (type & ENETC_MAC_FILTER_TYPE_UC) {
+		if (enetc4_pf_set_mac_exact_filter(pf, ENETC_MAC_FILTER_TYPE_UC))
+			/* Fall back to the MAC hash filter */
+			enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);
+	}
+
+	if (type & ENETC_MAC_FILTER_TYPE_MC)
+		enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
 	.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
 	.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
@@ -71,9 +418,18 @@ static int enetc4_pf_struct_init(struct enetc_si *si)
 
 	enetc4_get_port_caps(pf);
 
+	INIT_HLIST_HEAD(&pf->mac_list);
+	mutex_init(&pf->mac_list_lock);
+
 	return 0;
 }
 
+static void enetc4_pf_struct_free(struct enetc_pf *pf)
+{
+	enetc4_pf_destroy_mac_list(pf);
+	mutex_destroy(&pf->mac_list_lock);
+}
+
 static u32 enetc4_psicfgr0_val_construct(bool is_vf, u32 num_tx_bdr, u32 num_rx_bdr)
 {
 	u32 val;
@@ -305,12 +661,53 @@ static void enetc4_pf_free(struct enetc_pf *pf)
 	enetc4_free_ntmp_priv(pf->si);
 }
 
+static void enetc4_pf_do_set_rx_mode(struct work_struct *work)
+{
+	struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
+	struct enetc_pf *pf = enetc_si_priv(si);
+	struct net_device *ndev = si->ndev;
+	struct enetc_hw *hw = &si->hw;
+	bool uc_promisc = false;
+	bool mc_promisc = false;
+	int type = 0;
+
+	if (ndev->flags & IFF_PROMISC) {
+		uc_promisc = true;
+		mc_promisc = true;
+	} else if (ndev->flags & IFF_ALLMULTI) {
+		mc_promisc = true;
+		type = ENETC_MAC_FILTER_TYPE_UC;
+	} else {
+		type = ENETC_MAC_FILTER_TYPE_ALL;
+	}
+
+	enetc4_pf_set_si_mac_promisc(hw, 0, UC, uc_promisc);
+	enetc4_pf_set_si_mac_promisc(hw, 0, MC, mc_promisc);
+
+	/* Clear Old MAC filter */
+	enetc4_pf_flush_si_mac_exact_filter(pf, 0, ENETC_MAC_FILTER_TYPE_ALL);
+	enetc4_pf_set_si_mac_hash_filter(hw, 0, UC, 0);
+	enetc4_pf_set_si_mac_hash_filter(hw, 0, MC, 0);
+
+	/* Set new MAC filter */
+	enetc4_pf_set_mac_filter(pf, type);
+}
+
+static void enetc4_pf_set_rx_mode(struct net_device *ndev)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_si *si = priv->si;
+
+	queue_work(si->workqueue, &si->rx_mode_task);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
 	.ndo_start_xmit		= enetc_xmit,
 	.ndo_get_stats		= enetc_get_stats,
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
+	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
 };
 
 static struct phylink_pcs *
@@ -721,6 +1118,19 @@ static const struct enetc_si_ops enetc4_psi_ops = {
 	.teardown_cbdr = enetc4_teardown_cbdr,
 };
 
+static int enetc4_pf_wq_task_init(struct enetc_si *si)
+{
+	char wq_name[24];
+
+	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
+	snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
+	si->workqueue = create_singlethread_workqueue(wq_name);
+	if (!si->workqueue)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
@@ -756,9 +1166,13 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 		return err;
 
 	pf = enetc_si_priv(si);
+	err = enetc4_pf_wq_task_init(si);
+	if (err)
+		goto err_wq_task_init;
+
 	err = enetc4_pf_init(pf);
 	if (err)
-		return err;
+		goto err_pf_init;
 
 	enetc_get_si_caps(si);
 
@@ -770,6 +1184,10 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
 err_netdev_create:
 	enetc4_pf_free(pf);
+err_pf_init:
+	destroy_workqueue(si->workqueue);
+err_wq_task_init:
+	enetc4_pf_struct_free(pf);
 
 	return err;
 }
@@ -781,6 +1199,8 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
 
 	enetc4_pf_netdev_destroy(si);
 	enetc4_pf_free(pf);
+	destroy_workqueue(si->workqueue);
+	enetc4_pf_struct_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 4098f01479bc..2e676212d230 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -712,6 +712,12 @@ static inline void enetc_load_primary_mac_addr(struct enetc_hw *hw,
 	eth_hw_addr_set(ndev, addr);
 }
 
+static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr)
+{
+	*(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0);
+	*(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1);
+}
+
 #define ENETC_SI_INT_IDX	0
 /* base index for Rx/Tx interrupts */
 #define ENETC_BDR_INT_BASE_IDX	1
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 2b9d0f625f01..3b0cb0d8bf48 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -22,6 +22,13 @@ struct enetc_port_caps {
 	int num_msix;
 	int num_rx_bdr;
 	int num_tx_bdr;
+	int mac_filter_num;
+};
+
+struct enetc_mac_list_entry {
+	u8 mac[ETH_ALEN];
+	u16 si_bitmap;
+	struct hlist_node node;
 };
 
 struct enetc_pf;
@@ -57,6 +64,10 @@ struct enetc_pf {
 
 	struct enetc_port_caps caps;
 	const struct enetc_pf_ops *ops;
+
+	struct hlist_head mac_list; /* MAC address filter table */
+	struct mutex mac_list_lock; /* mac_list lock */
+	int num_mfe;	/* number of mac address filter table entries */
 };
 
 #define phylink_to_enetc_pf(config) \
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:21 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:21 +0800
Subject: [PATCH v4 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-6-wei.fang@nxp.com>

ENETC's MAC filter consists of hash MAC filter and exact MAC filter. Hash
MAC filter is a 64-entry hash table consisting of two 32-bit registers.
Exact MAC filter is implemented by configuring MAC address filter table
through command BD ring. The table is stored in ENETC's internal memory
and needs to be read through command BD ring. In order to facilitate
debugging, added a debugfs interface to get the relevant information
about MAC filter.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 93 +++++++++++++++++++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 ++++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 119 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4dba91408e3d..ca1bc85c0ac9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -318,6 +318,7 @@ struct enetc_si {
 	struct enetc_mac_filter mac_filter[MADDR_TYPE];
 	struct workqueue_struct *workqueue;
 	struct work_struct rx_mode_task;
+	struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN	32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index 000000000000..3a660c80344a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+#define is_en(x)	(x) ? "Enabled" : "Disabled"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+	struct enetc_si *si = s->private;
+	struct enetc_hw *hw = &si->hw;
+	u32 hash_h, hash_l;
+
+	hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+	hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+	seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+		   i, hash_h, hash_l);
+
+	hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+	hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+	seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+		   i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+	struct maft_entry_data maft_data;
+	struct enetc_si *si = s->private;
+	struct enetc_hw *hw = &si->hw;
+	struct maft_keye_data *keye;
+	struct enetc_pf *pf;
+	int i, err, num_si;
+	u32 val;
+
+	pf = enetc_si_priv(si);
+	num_si = pf->caps.num_vsi + 1;
+
+	val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+	for (i = 0; i < num_si; i++) {
+		seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
+			   i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
+		seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
+			   i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
+	}
+
+	/* MAC hash filter table */
+	for (i = 0; i < num_si; i++)
+		enetc_show_si_mac_hash_filter(s, i);
+
+	if (!pf->num_mfe)
+		return 0;
+
+	/* MAC address filter table */
+	seq_puts(s, "Show MAC address filter table\n");
+	for (i = 0; i < pf->num_mfe; i++) {
+		memset(&maft_data, 0, sizeof(maft_data));
+		err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
+		if (err)
+			return err;
+
+		keye = &maft_data.keye;
+		seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+			   keye->mac_addr, le16_to_cpu(maft_data.cfge.si_bitmap));
+	}
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+	struct net_device *ndev = si->ndev;
+	struct dentry *root;
+
+	root = debugfs_create_dir(netdev_name(ndev), NULL);
+	if (IS_ERR(root))
+		return;
+
+	si->debugfs_root = root;
+
+	debugfs_create_file("mac_filter", 0444, root, si, &enetc_mac_filter_fops);
+}
+
+void enetc_remove_debugfs(struct enetc_si *si)
+{
+	debugfs_remove_recursive(si->debugfs_root);
+	si->debugfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
new file mode 100644
index 000000000000..96caca35f79d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+
+#ifndef __ENETC4_DEBUGFS_H
+#define __ENETC4_DEBUGFS_H
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+void enetc_create_debugfs(struct enetc_si *si);
+void enetc_remove_debugfs(struct enetc_si *si);
+#else
+static inline void enetc_create_debugfs(struct enetc_si *si)
+{
+}
+
+static inline void enetc_remove_debugfs(struct enetc_si *si)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 7d1c545f3f56..a98ed059a83f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -8,6 +8,7 @@
 #include <linux/unaligned.h>
 
 #include "enetc_pf_common.h"
+#include "enetc4_debugfs.h"
 
 #define ENETC_SI_MAX_RING_NUM	8
 
@@ -1180,6 +1181,8 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_netdev_create;
 
+	enetc_create_debugfs(si);
+
 	return 0;
 
 err_netdev_create:
@@ -1197,6 +1200,7 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
 	struct enetc_si *si = pci_get_drvdata(pdev);
 	struct enetc_pf *pf = enetc_si_priv(si);
 
+	enetc_remove_debugfs(si);
 	enetc4_pf_netdev_destroy(si);
 	enetc4_pf_free(pf);
 	destroy_workqueue(si->workqueue);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:22 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:22 +0800
Subject: [PATCH v4 net-next 06/14] net: enetc: add set/get_rss_table() to enetc_si_ops
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-7-wei.fang@nxp.com>

Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which is
different from LS1028A ENETC (v1). In order to reuse some functions
related to the RSS table, so add .get_rss_table() and .set_rss_table()
hooks to enetc_si_ops.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c         |  2 +-
 drivers/net/ethernet/freescale/enetc/enetc.h         |  2 ++
 drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 12 ++++++------
 drivers/net/ethernet/freescale/enetc/enetc_pf.c      |  2 ++
 drivers/net/ethernet/freescale/enetc/enetc_vf.c      |  2 ++
 5 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3832d2cd91ba..2a8fa455e96b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2405,7 +2405,7 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
 	for (i = 0; i < si->num_rss; i++)
 		rss_table[i] = i % num_groups;
 
-	enetc_set_rss_table(si, rss_table, si->num_rss);
+	si->ops->set_rss_table(si, rss_table, si->num_rss);
 
 	kfree(rss_table);
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index ca1bc85c0ac9..deda386b20a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -290,6 +290,8 @@ struct enetc_si;
 struct enetc_si_ops {
 	int (*setup_cbdr)(struct enetc_si *si);
 	void (*teardown_cbdr)(struct enetc_si *si);
+	int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+	int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
 };
 
 /* PCI IEP device data */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index ece3ae28ba82..d14182401d81 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -681,7 +681,8 @@ static int enetc_get_rxfh(struct net_device *ndev,
 			  struct ethtool_rxfh_param *rxfh)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	int err = 0, i;
 
 	/* return hash function */
@@ -695,8 +696,7 @@ static int enetc_get_rxfh(struct net_device *ndev,
 
 	/* return RSS table */
 	if (rxfh->indir)
-		err = enetc_get_rss_table(priv->si, rxfh->indir,
-					  priv->si->num_rss);
+		err = si->ops->get_rss_table(si, rxfh->indir, si->num_rss);
 
 	return err;
 }
@@ -715,7 +715,8 @@ static int enetc_set_rxfh(struct net_device *ndev,
 			  struct netlink_ext_ack *extack)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	int err = 0;
 
 	/* set hash key, if PF */
@@ -724,8 +725,7 @@ static int enetc_set_rxfh(struct net_device *ndev,
 
 	/* set RSS table */
 	if (rxfh->indir)
-		err = enetc_set_rss_table(priv->si, rxfh->indir,
-					  priv->si->num_rss);
+		err = si->ops->set_rss_table(si, rxfh->indir, si->num_rss);
 
 	return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index cc3e52bd3096..097a5b50e448 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -907,6 +907,8 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
 static const struct enetc_si_ops enetc_psi_ops = {
 	.setup_cbdr = enetc_setup_cbdr,
 	.teardown_cbdr = enetc_teardown_cbdr,
+	.get_rss_table = enetc_get_rss_table,
+	.set_rss_table = enetc_set_rss_table,
 };
 
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index d7d9a720069b..072e5b40a199 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -165,6 +165,8 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 static const struct enetc_si_ops enetc_vsi_ops = {
 	.setup_cbdr = enetc_setup_cbdr,
 	.teardown_cbdr = enetc_teardown_cbdr,
+	.get_rss_table = enetc_get_rss_table,
+	.set_rss_table = enetc_set_rss_table,
 };
 
 static int enetc_vf_probe(struct pci_dev *pdev,
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:23 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:23 +0800
Subject: [PATCH v4 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-8-wei.fang@nxp.com>

Since the offset of the RSS key registers of i.MX95 ENETC is different
from that of LS1028A, so add enetc_get_rss_key_base() to get the base
offset for the different chips, so that enetc_set_rss_key() can be
reused for this trivial.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 11 +----------
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 ++++++++++++++-----
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +-
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index deda386b20a0..a3ce324c716c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -539,7 +539,7 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
 		       int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index a98ed059a83f..f991e1aae85c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -583,22 +583,13 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
 	enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-	int i;
-
-	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-		enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
 static void enetc4_set_default_rss_key(struct enetc_pf *pf)
 {
 	u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
-	struct enetc_hw *hw = &pf->si->hw;
 
 	/* set up hash key */
 	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-	enetc4_set_rss_key(hw, hash_key);
+	enetc_set_rss_key(pf->si, hash_key);
 }
 
 static void enetc4_enable_trx(struct enetc_pf *pf)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index d14182401d81..1a8fae3c406b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -677,6 +677,14 @@ static u32 enetc_get_rxfh_indir_size(struct net_device *ndev)
 	return priv->si->num_rss;
 }
 
+static int enetc_get_rss_key_base(struct enetc_si *si)
+{
+	if (is_enetc_rev1(si))
+		return ENETC_PRSSK(0);
+
+	return ENETC4_PRSSKR(0);
+}
+
 static int enetc_get_rxfh(struct net_device *ndev,
 			  struct ethtool_rxfh_param *rxfh)
 {
@@ -701,12 +709,14 @@ static int enetc_get_rxfh(struct net_device *ndev,
 	return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes)
 {
+	int base = enetc_get_rss_key_base(si);
+	struct enetc_hw *hw = &si->hw;
 	int i;
 
 	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-		enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+		enetc_port_wr(hw, base + i * 4, ((u32 *)bytes)[i]);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_key);
 
@@ -716,12 +726,11 @@ static int enetc_set_rxfh(struct net_device *ndev,
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
 	int err = 0;
 
 	/* set hash key, if PF */
-	if (rxfh->key && hw->port)
-		enetc_set_rss_key(hw, rxfh->key);
+	if (rxfh->key && enetc_si_is_pf(si))
+		enetc_set_rss_key(si, rxfh->key);
 
 	/* set RSS table */
 	if (rxfh->indir)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 097a5b50e448..38ec7657b9aa 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -523,7 +523,7 @@ static void enetc_configure_port(struct enetc_pf *pf)
 
 	/* set up hash key */
 	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-	enetc_set_rss_key(hw, hash_key);
+	enetc_set_rss_key(pf->si, hash_key);
 
 	/* split up RFS entries */
 	enetc_port_assign_rfs_entries(pf->si);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:24 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:24 +0800
Subject: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-9-wei.fang@nxp.com>

Compared with LS1028A, there are two main differences: first, i.MX95
ENETC uses NTMP 2.0 to manage the RSS table, and second, the offset
of the RSS Key registers is different. Some modifications have been
made in the previous patches based on these differences to ensure that
the relevant interfaces are compatible with i.MX95. So it's time to
add RSS support to i.MX95 ENETC PF.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  5 +--
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 11 +++++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 14 +++++++
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 42 ++++++++++++++++---
 .../freescale/enetc/enetc_pf_common.c         |  6 +--
 6 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2a8fa455e96b..5b5e65ac8fab 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2436,10 +2436,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
 	if (si->hw_features & ENETC_SI_F_LSO)
 		enetc_set_lso_flags_mask(hw);
 
-	/* TODO: RSS support for i.MX95 will be supported later, and the
-	 * is_enetc_rev1() condition will be removed
-	 */
-	if (si->num_rss && is_enetc_rev1(si)) {
+	if (si->num_rss) {
 		err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
 		if (err)
 			return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index a3ce324c716c..ecf79338cd79 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -543,6 +543,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 					     struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index f991e1aae85c..53dbd5d71859 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -693,6 +693,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 	queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device *ndev,
+				  netdev_features_t features)
+{
+	enetc_set_features(ndev, features);
+
+	return 0;
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_open		= enetc_open,
 	.ndo_stop		= enetc_close,
@@ -700,6 +708,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_get_stats		= enetc_get_stats,
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
 	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
+	.ndo_set_features	= enetc4_pf_set_features,
 };
 
 static struct phylink_pcs *
@@ -1108,6 +1117,8 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
 static const struct enetc_si_ops enetc4_psi_ops = {
 	.setup_cbdr = enetc4_setup_cbdr,
 	.teardown_cbdr = enetc4_teardown_cbdr,
+	.get_rss_table = enetc4_get_rss_table,
+	.set_rss_table = enetc4_set_rss_table,
 };
 
 static int enetc4_pf_wq_task_init(struct enetc_si *si)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 4e5125331d7b..1a74b93f1fd3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -299,3 +299,17 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count)
 	return enetc_cmd_rss_table(si, (u32 *)table, count, false);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
+					       table, count, true);
+}
+EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
+
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
+{
+	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
+					       (u32 *)table, count, false);
+}
+EXPORT_SYMBOL_GPL(enetc4_set_rss_table);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 1a8fae3c406b..bc65135925b8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -625,6 +625,24 @@ static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
 	return 0;
 }
 
+static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
+			    u32 *rule_locs)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_GRXRINGS:
+		rxnfc->data = priv->num_rx_rings;
+		break;
+	case ETHTOOL_GRXFH:
+		return enetc_get_rsshash(rxnfc);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -685,22 +703,29 @@ static int enetc_get_rss_key_base(struct enetc_si *si)
 	return ENETC4_PRSSKR(0);
 }
 
+static void enetc_get_rss_key(struct enetc_si *si, const u8 *key)
+{
+	int base = enetc_get_rss_key_base(si);
+	struct enetc_hw *hw = &si->hw;
+	int i;
+
+	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+		((u32 *)key)[i] = enetc_port_rd(hw, base + i * 4);
+}
+
 static int enetc_get_rxfh(struct net_device *ndev,
 			  struct ethtool_rxfh_param *rxfh)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
-	int err = 0, i;
+	int err = 0;
 
 	/* return hash function */
 	rxfh->hfunc = ETH_RSS_HASH_TOP;
 
 	/* return hash key */
-	if (rxfh->key && hw->port)
-		for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-			((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
-							      ENETC_PRSSK(i));
+	if (rxfh->key && enetc_si_is_pf(si))
+		enetc_get_rss_key(si, rxfh->key);
 
 	/* return RSS table */
 	if (rxfh->indir)
@@ -1249,6 +1274,11 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
 	.set_wol = enetc_set_wol,
 	.get_pauseparam = enetc_get_pauseparam,
 	.set_pauseparam = enetc_set_pauseparam,
+	.get_rxnfc = enetc4_get_rxnfc,
+	.get_rxfh_key_size = enetc_get_rxfh_key_size,
+	.get_rxfh_indir_size = enetc_get_rxfh_indir_size,
+	.get_rxfh = enetc_get_rxfh,
+	.set_rxfh = enetc_set_rxfh,
 };
 
 void enetc_set_ethtool_ops(struct net_device *ndev)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3fd9b0727875..c346e0e3ad37 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,15 +128,15 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	if (si->hw_features & ENETC_SI_F_LSO)
 		priv->active_offloads |= ENETC_F_LSO;
 
+	if (si->num_rss)
+		ndev->hw_features |= NETIF_F_RXHASH;
+
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
 		ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
 		goto end;
 	}
 
-	if (si->num_rss)
-		ndev->hw_features |= NETIF_F_RXHASH;
-
 	ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 			     NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
 			     NETDEV_XDP_ACT_NDO_XMIT_SG;
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:25 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:25 +0800
Subject: [PATCH v4 net-next 09/14] net: enetc: enable RSS feature by default
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-10-wei.fang@nxp.com>

Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++++++++++---------
 .../freescale/enetc/enetc_pf_common.c         |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5b5e65ac8fab..8583ac9f7b9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2420,6 +2420,22 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
 	enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static int enetc_set_rss(struct net_device *ndev, int en)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_hw *hw = &priv->si->hw;
+	u32 reg;
+
+	enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+	reg = enetc_rd(hw, ENETC_SIMR);
+	reg &= ~ENETC_SIMR_RSSE;
+	reg |= (en) ? ENETC_SIMR_RSSE : 0;
+	enetc_wr(hw, ENETC_SIMR, reg);
+
+	return 0;
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
 	struct enetc_si *si = priv->si;
@@ -2440,6 +2456,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
 		err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
 		if (err)
 			return err;
+
+		if (priv->ndev->features & NETIF_F_RXHASH)
+			enetc_set_rss(priv->ndev, true);
 	}
 
 	return 0;
@@ -3232,22 +3251,6 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
-	u32 reg;
-
-	enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-	reg = enetc_rd(hw, ENETC_SIMR);
-	reg &= ~ENETC_SIMR_RSSE;
-	reg |= (en) ? ENETC_SIMR_RSSE : 0;
-	enetc_wr(hw, ENETC_SIMR, reg);
-
-	return 0;
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index c346e0e3ad37..a737a7f8c79e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	if (si->hw_features & ENETC_SI_F_LSO)
 		priv->active_offloads |= ENETC_F_LSO;
 
-	if (si->num_rss)
+	if (si->num_rss) {
 		ndev->hw_features |= NETIF_F_RXHASH;
+		ndev->features |= NETIF_F_RXHASH;
+	}
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 072e5b40a199..3372a9a779a6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
 			      NETIF_F_TSO | NETIF_F_TSO6;
 
-	if (si->num_rss)
+	if (si->num_rss) {
 		ndev->hw_features |= NETIF_F_RXHASH;
+		ndev->features |= NETIF_F_RXHASH;
+	}
 
 	/* pick up primary MAC address from SI */
 	enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:26 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:26 +0800
Subject: [PATCH v4 net-next 10/14] net: enetc: move generic VLAN filter interfaces to enetc-core
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-11-wei.fang@nxp.com>

For ENETC, each SI has a corresponding VLAN hash table. That is to say,
both PF and VFs can support VLAN filter. However, currently only ENETC v1
PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
VF drivers also support VLAN filter, some related macros are moved from
enetc_pf.h to enetc.h, and the related structure variables are moved from
enetc_pf to enetc_si.

Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
so that it can be shared by PF and VF drivers. This will make it easier
to add VLAN filter support for i.MX95 ENETC later.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 25 ++++++++++
 drivers/net/ethernet/freescale/enetc/enetc.h  |  6 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 46 +++++--------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  4 --
 4 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 8583ac9f7b9e..248dbc874eec 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -72,6 +72,31 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
 }
 EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
 
+int enetc_vid_hash_idx(unsigned int vid)
+{
+	int res = 0;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(enetc_vid_hash_idx);
+
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si)
+{
+	int i;
+
+	bitmap_zero(si->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+	for_each_set_bit(i, si->active_vlans, VLAN_N_VID) {
+		int hidx = enetc_vid_hash_idx(i);
+
+		__set_bit(hidx, si->vlan_ht_filter);
+	}
+}
+EXPORT_SYMBOL_GPL(enetc_refresh_vlan_ht_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
 	int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index ecf79338cd79..c60741dfe358 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -24,6 +24,7 @@
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
 #define ENETC_MADDR_HASH_TBL_SZ	64
+#define ENETC_VLAN_HT_SIZE	64
 
 enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
 
@@ -321,6 +322,9 @@ struct enetc_si {
 	struct workqueue_struct *workqueue;
 	struct work_struct rx_mode_task;
 	struct dentry *debugfs_root;
+
+	DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 };
 
 #define ENETC_SI_ALIGN	32
@@ -506,6 +510,8 @@ int enetc_get_driver_data(struct enetc_si *si);
 void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
 				  const unsigned char *addr);
 void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+int enetc_vid_hash_idx(unsigned int vid);
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 38ec7657b9aa..f9b179ed6d8b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -222,45 +222,18 @@ static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
 	enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-	int res = 0;
-	int i;
-
-	for (i = 0; i < 6; i++)
-		res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-	return res;
-}
-
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
-{
-	int i;
-
-	if (rehash) {
-		bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-
-		for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-			int hidx = enetc_vid_hash_idx(i);
-
-			__set_bit(hidx, pf->vlan_ht_filter);
-		}
-	}
-
-	enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-}
-
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 	int idx;
 
-	__set_bit(vid, pf->active_vlans);
+	__set_bit(vid, si->active_vlans);
 
 	idx = enetc_vid_hash_idx(vid);
-	if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-		enetc_sync_vlan_ht_filter(pf, false);
+	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
 
 	return 0;
 }
@@ -268,10 +241,13 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
 
-	__clear_bit(vid, pf->active_vlans);
-	enetc_sync_vlan_ht_filter(pf, true);
+	if (__test_and_clear_bit(vid, si->active_vlans)) {
+		enetc_refresh_vlan_ht_filter(si);
+		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
+	}
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 3b0cb0d8bf48..90137fbb8f48 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -6,8 +6,6 @@
 
 #define ENETC_PF_NUM_RINGS	8
 
-#define ENETC_VLAN_HT_SIZE	64
-
 enum enetc_vf_flags {
 	ENETC_VF_FLAG_PF_SET_MAC	= BIT(0),
 };
@@ -52,8 +50,6 @@ struct enetc_pf {
 	char msg_int_name[ENETC_INT_NAME_MAX];
 
 	char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */
-	DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 
 	struct mii_bus *mdio; /* saved for cleanup */
 	struct mii_bus *imdio;
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:27 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:27 +0800
Subject: [PATCH v4 net-next 11/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-12-wei.fang@nxp.com>

Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
only difference is the offset of the VLAN hash filter registers. So, the
.set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
the registers of the corresponding platform. In addition, the common VLAN
hash filter functions enetc_vlan_rx_add_vid() and enetc_vlan_rx_del_vid()
are moved to enetc_pf_common.c.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 ++-----------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 +
 .../freescale/enetc/enetc_pf_common.c         | 34 +++++++++++++++++++
 .../freescale/enetc/enetc_pf_common.h         |  2 ++
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index f9b179ed6d8b..d3ca9e33893f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -215,43 +215,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 	enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-				     unsigned long hash)
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, u64 hash)
 {
 	enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
 	enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
-	int idx;
-
-	__set_bit(vid, si->active_vlans);
-
-	idx = enetc_vid_hash_idx(vid);
-	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
-		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-
-	return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_si *si = priv->si;
-	struct enetc_hw *hw = &si->hw;
-
-	if (__test_and_clear_bit(vid, si->active_vlans)) {
-		enetc_refresh_vlan_ht_filter(si);
-		enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-	}
-
-	return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -953,6 +922,7 @@ static const struct enetc_pf_ops enetc_pf_ops = {
 	.create_pcs = enetc_pf_create_pcs,
 	.destroy_pcs = enetc_pf_destroy_pcs,
 	.enable_psfp = enetc_psfp_enable,
+	.set_si_vlan_hash_filter = enetc_set_vlan_ht_filter,
 };
 
 static int enetc_pf_probe(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 90137fbb8f48..704c4ee42f61 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -37,6 +37,7 @@ struct enetc_pf_ops {
 	struct phylink_pcs *(*create_pcs)(struct enetc_pf *pf, struct mii_bus *bus);
 	void (*destroy_pcs)(struct phylink_pcs *pcs);
 	int (*enable_psfp)(struct enetc_ndev_priv *priv);
+	void (*set_si_vlan_hash_filter)(struct enetc_hw *hw, int si, u64 hash);
 };
 
 struct enetc_pf {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a737a7f8c79e..9f812c1af7a3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -343,5 +343,39 @@ void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
 }
 EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
 
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
+	int idx;
+
+	__set_bit(vid, si->active_vlans);
+
+	idx = enetc_vid_hash_idx(vid);
+	if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+		pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_pf *pf = enetc_si_priv(priv->si);
+	struct enetc_si *si = priv->si;
+	struct enetc_hw *hw = &si->hw;
+
+	if (__test_and_clear_bit(vid, si->active_vlans)) {
+		enetc_refresh_vlan_ht_filter(si);
+		pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_del_vid);
+
 MODULE_DESCRIPTION("NXP ENETC PF common functionality driver");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index 48f55ee743ad..253310859ca1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -12,6 +12,8 @@ void enetc_mdiobus_destroy(struct enetc_pf *pf);
 int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
 			 const struct phylink_mac_ops *ops);
 void enetc_phylink_destroy(struct enetc_ndev_priv *priv);
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid);
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid);
 
 static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
 {
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:28 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:28 +0800
Subject: [PATCH v4 net-next 12/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-13-wei.fang@nxp.com>

Add VLAN hash filter support for i.MX95 ENETC PF. If VLAN filtering is
disabled, then VLAN promiscuous mode will be enabled, which means that
PF qualifies for reception of all VLAN tags.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 ++++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +++++++++++++++++++
 .../freescale/enetc/enetc_pf_common.c         |  2 +-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)		((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)		((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a)		((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a)		((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR			0x4004
 #define  PMCAPR_HD			BIT(8)
 #define  PMCAPR_FP			GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 53dbd5d71859..4abbbbef00ff 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -101,6 +101,13 @@ static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
 	}
 }
 
+static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
+					      int si, u64 hash)
+{
+	enetc_port_wr(hw, ENETC4_PSIVHFR0(si), lower_32_bits(hash));
+	enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
+}
+
 static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
 {
 	struct enetc_mac_list_entry *entry;
@@ -407,6 +414,7 @@ static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
 static const struct enetc_pf_ops enetc4_pf_ops = {
 	.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
 	.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
+	.set_si_vlan_hash_filter = enetc4_pf_set_si_vlan_hash_filter,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -696,6 +704,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
 				  netdev_features_t features)
 {
+	netdev_features_t changed = ndev->features ^ features;
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_hw *hw = &priv->si->hw;
+
+	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+		bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+		enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+	}
+
 	enetc_set_features(ndev, features);
 
 	return 0;
@@ -709,6 +727,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
 	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
 	.ndo_set_features	= enetc4_pf_set_features,
+	.ndo_vlan_rx_add_vid	= enetc_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 9f812c1af7a3..3f7ccc482301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
 	if (!is_enetc_rev1(si)) {
-		ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
+		ndev->hw_features &= ~NETIF_F_LOOPBACK;
 		goto end;
 	}
 
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:29 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:29 +0800
Subject: [PATCH v4 net-next 13/14] net: enetc: add loopback support for i.MX95 ENETC PF
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-14-wei.fang@nxp.com>

Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++++++++++++++++++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 4abbbbef00ff..c169900ccb4a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -108,6 +108,21 @@ static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
 	enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_si *si = priv->si;
+	u32 val;
+
+	val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+	val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+	/* Default to select MAC level loopback mode if loopback is enabled. */
+	val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+			       PM_CMD_CFG_LPBK_MODE);
+
+	enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
 {
 	struct enetc_mac_list_entry *entry;
@@ -714,6 +729,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
 		enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
 	}
 
+	if (changed & NETIF_F_LOOPBACK)
+		enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
 	enetc_set_features(ndev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3f7ccc482301..0a2b8769a175 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	}
 
 	/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
-	if (!is_enetc_rev1(si)) {
-		ndev->hw_features &= ~NETIF_F_LOOPBACK;
+	if (!is_enetc_rev1(si))
 		goto end;
-	}
 
 	ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 			     NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1



From wei.fang at nxp.com  Mon Mar 10 22:38:30 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:30 +0800
Subject: [PATCH v4 net-next 14/14] MAINTAINERS: add new file ntmp.h to ENETC driver
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250311053830.1516523-15-wei.fang@nxp.com>

Add new file ntmp.h. to ENETC driver.

Signed-off-by: Wei Fang <wei.fang at nxp.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7078199fcebf..e259b659eadb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9174,6 +9174,7 @@ F:	Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F:	drivers/net/ethernet/freescale/enetc/
 F:	include/linux/fsl/enetc_mdio.h
 F:	include/linux/fsl/netc_global.h
+F:	include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M:	Claudiu Manoil <claudiu.manoil at nxp.com>
-- 
2.34.1



From anshuman.khandual at arm.com  Mon Mar 10 23:09:21 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 11 Mar 2025 11:39:21 +0530
Subject: [boot-wrapper] aarch64: Enable access into FEAT_FGT2 registers
 from EL2 and below
In-Reply-To: <Z7xmenE0scM9omcU@J2N7QTR9R3.cambridge.arm.com>
References: <20240730054643.157295-1-anshuman.khandual@arm.com>
 <Z7xmenE0scM9omcU@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <4a87b3b7-6bd3-4c86-9a30-43f15759948a@arm.com>



On 2/24/25 18:00, Mark Rutland wrote:
> On Tue, Jul 30, 2024 at 11:16:43AM +0530, Anshuman Khandual wrote:
>> FEAT_FGT2 adds system registers HDFGRTR2_EL2, HDFGWTR2_EL2, HFGITR2_EL2,
>> HFGRTR2_EL2 and HFGWTR2_EL2. But access into these system registers from
>> EL2 and below exception levels, will trap into EL3 unless SCR_EL3.FGTEN2
>> is set.
>>
>> Enable access to FEAT_FGT2 registers when they are implemented. Given that
>> these new FEAT_FGT2 trap registers have fields that reset to UNKNOWN values
>> when resets are taken to EL3, this initialises all registers as cleared.
>>
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>> This picks up from an earlier discussion regarding [PATCH 2/2].
>>
>> https://lore.kernel.org/all/20240404073726.947215-1-anshuman.khandual at arm.com/
>>
>>  arch/aarch64/include/asm/cpu.h | 7 +++++++
>>  arch/aarch64/init.c            | 9 +++++++++
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h
>> index a5744e1..878d03d 100644
>> --- a/arch/aarch64/include/asm/cpu.h
>> +++ b/arch/aarch64/include/asm/cpu.h
>> @@ -23,6 +23,12 @@
>>  #define SCTLR2_EL1		s3_0_c1_c0_3
>>  #define SCTLR2_EL2		s3_4_c1_c0_3
>>  
>> +#define HDFGRTR2_EL2		s3_4_c3_c1_0
>> +#define HDFGWTR2_EL2		s3_4_c3_c1_1
>> +#define HFGRTR2_EL2		s3_4_c3_c1_2
>> +#define HFGWTR2_EL2		s3_4_c3_c1_3
>> +#define HFGITR2_EL2		s3_4_c3_c1_7
> 
> These all look correct per ARM DDI 0487 L.a, table D23-2.
> 
>> +
>>  /*
>>   * RES1 bit definitions definitions as of ARM DDI 0487G.b
>>   *
>> @@ -63,6 +69,7 @@
>>  #define SCR_EL3_SCTLR2En		BIT(44)
>>  #define SCR_EL3_PIEN			BIT(45)
>>  #define SCR_EL3_D128En			BIT(47)
>> +#define SCR_EL3_FGTEN2			BIT(59)
> 
> This looks correct per ARM DDI 0487 L.a, section D24.2.163.
> 
>>  
>>  #define HCR_EL2_RES1			BIT(1)
>>  
>> diff --git a/arch/aarch64/init.c b/arch/aarch64/init.c
>> index c9fc7f1..b4d64a0 100644
>> --- a/arch/aarch64/init.c
>> +++ b/arch/aarch64/init.c
>> @@ -68,6 +68,15 @@ void cpu_init_el3(void)
>>  	if (mrs_field(ID_AA64MMFR0_EL1, FGT))
>>  		scr |= SCR_EL3_FGTEN;
>>  
>> +	if (mrs_field(ID_AA64MMFR0_EL1, FGT) >= 2) {
>> +		scr |= SCR_EL3_FGTEN2;
>> +		msr(HDFGRTR2_EL2, 0);
>> +		msr(HDFGWTR2_EL2, 0);
>> +		msr(HFGITR2_EL2, 0);
>> +		msr(HFGRTR2_EL2, 0);
>> +		msr(HFGWTR2_EL2, 0);
>> +	}
> 
> Superficially, this looks sane to me. I haven't audited all the bits, but I
> assume that you have gone through all of the bits and checked that zero is a
> sensible reset value for all of these.
> 
> I intend to apply this shortly.
> 
> As an aside, I think some necssary support is missing on the kernel side -- I'll reply
> on that front shortly.

Hello Mark,

Seems like neither this boot wrapper patch nor the more recent one which sets
MDCR_EL3.EnPM2 for FEAT_PMUv3p9 registers [1] (as you had pointed out earlier
on the kernel thread) has been applied.

[1] https://lore.kernel.org/all/20250227041603.2029058-1-anshuman.khandual at arm.com/

IIUC both these boot-wrapper patches are necessary for the kernel patch and
also for existing FEAT_PMUv3p9 feature.

https://lore.kernel.org/all/20250227035119.2025171-1-anshuman.khandual at arm.com/

FEAT_PMUv3p9 is the only current user with dependency on FEAT_FGT2 based traps,
beside upcoming FEAT_Debugv8p9 feature which is still under development.

Just wondering if there is something else that still needs to be addressed ?
Please do let me know, will accommodate the changes as required. Thank you.

- Anshuman

> 
> Mark.
> 
>> +
>>  	if (mrs_field(ID_AA64MMFR0_EL1, ECV) >= 2)
>>  		scr |= SCR_EL3_ECVEN;
>>  
>> -- 
>> 2.25.1
>>
>>


From wei.fang at nxp.com  Mon Mar 10 22:38:16 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 11 Mar 2025 13:38:16 +0800
Subject: [PATCH v4 net-next 00/14] Add more feautues for ENETC v4 - round 2
Message-ID: <20250311053830.1516523-1-wei.fang@nxp.com>

This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.fang at nxp.com/
v2 changes
1. Change NTMP_FILL_CRD() and NTMP_FILL_CRD_EID to functions
2. Fix the compile warning in enetc4_pf.c
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.fang at nxp.com/
v3 changes
1. Rename ntmp_formats.h to ntmp_private.h, becuase in addition to
   defining some table formats, some macros and function declarations
   will be added to this header file in the future
2. Add struct ntmp_dma_buf, so refactor ntmp_alloc_data_mem() and
   ntmp_free_data_mem() accordingly
3. Add the setting for cache attributes of command BD Ring in
   enetc4_setup_cbdr()
4. Remove __free() and scoped_guard() from patch "net: enetc: add MAC
   filter for i.MX95 ENETC PF", as these cleanup APIs are discouraged
   within networking drivers.
5. Remove patch "net: enetc: make enetc_set_rxfh() and enetc_get_rxfh()
   reusable" in v2, and add enetc_set_rss_key() and enetc_get_rss_key()
   instead of adding .set_rss_key() and .get_rss_key() to enetc_pf_ops
6. Separate patch " net: enetc: check if the RSS hfunc is toeplitz" from
   patch "net: enetc: add RSS support for i.MX95 ENETC PF"
v3 Link:https://lore.kernel.org/imx/20250304072201.1332603-1-wei.fang at nxp.com/
v4 changes
1. Optimize the indentation in patch "net: enetc: add MAC filter for
   i.MX95 ENETC PF"
2. Remove pack(1) from ntmp.h and ntmp_private.h
3. Remove the string after "tristate" from CONFG_NXP_NETC_LIB
4. Separate two patches from the patch "net: enetc: add RSS support for
   i.MX95 ENETC PF", one is "net: enetc: add set/get_rss_table() to
   enetc_si_ops", the other one is "net: enetc: make enetc_set_rss_key()
   reusable"
5. Remove patch "net: enetc: check if the RSS hfunc is toeplitz" from
   this patch set.
---

Wei Fang (14):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filterng interfaces to enetc-core
  net: enetc: add MAC filter for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: add set/get_rss_table() to enetc_si_ops
  net: enetc: make enetc_set_rss_key() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: enable RSS feature by default
  net: enetc: move generic VLAN filter interfaces to enetc-core
  net: enetc: move generic VLAN hash filter functions to
    enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF
  MAINTAINERS: add new file ntmp.h to ENETC driver

 MAINTAINERS                                   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  | 103 +++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  59 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 533 +++++++++++++++++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  69 ++-
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  69 ++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 124 +---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  30 +-
 .../freescale/enetc/enetc_pf_common.c         |  46 +-
 .../freescale/enetc/enetc_pf_common.h         |   2 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  19 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 458 +++++++++++++++
 .../ethernet/freescale/enetc/ntmp_private.h   |  63 +++
 include/linux/fsl/ntmp.h                      | 174 ++++++
 20 files changed, 1702 insertions(+), 191 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1



From s-vadapalli at ti.com  Mon Mar 10 23:12:14 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 11:42:14 +0530
Subject: [PATCH net] net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
Message-ID: <20250311061214.4111634-1-s-vadapalli@ti.com>

From: Vignesh Raghavendra <vigneshr at ti.com>

Registering the interrupts for TX or RX DMA Channels prior to registering
their respective NAPI callbacks can result in a NULL pointer dereference.
This is seen in practice as a random occurrence since it depends on the
randomness associated with the generation of traffic by Linux and the
reception of traffic from the wire.

Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---

Hello,

This patch is based on commit
4d872d51bc9d Merge tag 'x86-urgent-2025-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
of Mainline Linux.

Regards,
Siddharth.

 drivers/net/ethernet/ti/am65-cpsw-nuss.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 2806238629f8..d5291281c781 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2314,6 +2314,9 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
 		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
 
+		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
+				  am65_cpsw_nuss_tx_poll);
+
 		ret = devm_request_irq(dev, tx_chn->irq,
 				       am65_cpsw_nuss_tx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2323,9 +2326,6 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 				tx_chn->id, tx_chn->irq, ret);
 			goto err;
 		}
-
-		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
-				  am65_cpsw_nuss_tx_poll);
 	}
 
 	return 0;
@@ -2569,6 +2569,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			     HRTIMER_MODE_REL_PINNED);
 		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
 
+		netif_napi_add(common->dma_ndev, &flow->napi_rx,
+			       am65_cpsw_nuss_rx_poll);
+
 		ret = devm_request_irq(dev, flow->irq,
 				       am65_cpsw_nuss_rx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2579,9 +2582,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			flow->irq = -EINVAL;
 			goto err_flow;
 		}
-
-		netif_napi_add(common->dma_ndev, &flow->napi_rx,
-			       am65_cpsw_nuss_rx_poll);
 	}
 
 	/* setup classifier to route priorities to flows */
-- 
2.34.1



From hare at suse.de  Mon Mar 10 23:51:29 2025
From: hare at suse.de (Hannes Reinecke)
Date: Tue, 11 Mar 2025 07:51:29 +0100
Subject: [PATCH 1/2] nvme: move error logging from nvme_end_req() to
 __nvme_end_req()
In-Reply-To: <20250311024144.1762333-2-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
 <20250311024144.1762333-2-shinichiro.kawasaki@wdc.com>
Message-ID: <78673d08-cd0d-4daf-b471-98fabe824f3a@suse.de>

On 3/11/25 03:41, Shin'ichiro Kawasaki wrote:
> Before the Commit 1f47ed294a2b ("block: cleanup and fix batch completion
> adding conditions"), blk_mq_add_to_batch() did not add failed
> passthrough requests to batch, and returned false. After the commit,
> blk_mq_add_to_batch() always adds passthrough requests to batch
> regardless of whether the request failed or not, and returns true. This
> affected error logging feature in the NVME driver.
> 
> Before the commit, the call chain of failed passthrough request was as
> follows:
> 
> nvme_handle_cqe()
>   blk_mq_add_to_batch() .. false is returned, then call nvme_pci_complete_rq()
>   nvme_pci_complete_rq()
>    nvme_complete_rq()
>     nvme_end_req()
>      nvme_log_err_passthru() .. error logging
>      __nvme_end_req()        .. end of the rqeuest
> 
> After the commit, the call chain is as follows:
> 
> nvme_handle_cqe()
>   blk_mq_add_to_batch() .. true is returned, then set nvme_pci_complete_batch()
>   ..
>   nvme_pci_complete_batch()
>    nvme_complete_batch()
>     nvme_complete_batch_req()
>      __nvme_end_req() .. end of the request, without error logging
> 
> To make the error logging feature work again for passthrough requests, move the
> nvme_log_err_passthru() call from nvme_end_req() to __nvme_end_req().
> 
> While at it, move nvme_log_error() call for non-passthrough requests together
> with nvme_log_err_passthru(). Even though the trigger commit does not affect
> non-passthrough requests, move it together for code simplicity.
> 
> Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
> ---
>   drivers/nvme/host/core.c | 12 ++++++------
>   1 file changed, 6 insertions(+), 6 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare at suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare at suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 N?rnberg
HRB 36809 (AG N?rnberg), GF: I. Totev, A. McDonald, W. Knoblich


From hare at suse.de  Mon Mar 10 23:57:27 2025
From: hare at suse.de (Hannes Reinecke)
Date: Tue, 11 Mar 2025 07:57:27 +0100
Subject: [PATCH 2/2] block: change blk_mq_add_to_batch() third argument
 type to blk_status_t
In-Reply-To: <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
 <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
Message-ID: <16de123b-abe8-4f6d-8b4a-ec9541eca249@suse.de>

On 3/11/25 03:41, Shin'ichiro Kawasaki wrote:
> Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
> conditions") modified the evaluation criteria for the third argument,
> 'ioerror', in the blk_mq_add_to_batch() function. Initially, the
> function had checked if 'ioerror' equals zero. Following the commit, it
> started checking for negative error values, with the presumption that
> such values, for instance -EIO, would be passed in.
> 
> However, blk_mq_add_to_batch() callers do not pass negative error
> values. Instead, they pass status codes defined in various ways:
> 
> - NVMe PCI and Apple drivers pass NVMe status code
> - virtio_blk driver passes the virtblk request header status byte
> - null_blk driver passes blk_status_t
> 
> These codes are either zero or positive, therefore the revised check
> fails to function as intended. Specifically, with the NVMe PCI driver,
> this modification led to the failure of the blktests test case nvme/039.
> In this test scenario, errors are artificially injected to the NVMe
> driver, resulting in positive NVMe status codes passed to
> blk_mq_add_to_batch(), which unexpectedly processes the failed I/O in a
> batch. Hence the failure.
> 
> To correct the ioerror check within blk_mq_add_to_batch(), make all
> callers to uniformly pass the argument as blk_status_t. Modify the
> callers to translate their specific status codes into blk_status_t. For
> this translation, export the helper function nvme_error_status(). Adjust
> blk_mq_add_to_batch() to translate blk_status_t back into the error
> number for the appropriate check.
> 
> Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
> ---
>   drivers/block/null_blk/main.c | 2 +-
>   drivers/block/virtio_blk.c    | 5 +++--
>   drivers/nvme/host/apple.c     | 3 ++-
>   drivers/nvme/host/core.c      | 3 ++-
>   drivers/nvme/host/nvme.h      | 1 +
>   drivers/nvme/host/pci.c       | 5 +++--
>   include/linux/blk-mq.h        | 5 +++--
>   7 files changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
> index d94ef37480bd..31f23f6a8ed0 100644
> --- a/drivers/block/null_blk/main.c
> +++ b/drivers/block/null_blk/main.c
> @@ -1549,7 +1549,7 @@ static int null_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
>   		cmd = blk_mq_rq_to_pdu(req);
>   		cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req),
>   						blk_rq_sectors(req));
> -		if (!blk_mq_add_to_batch(req, iob, (__force int) cmd->error,
> +		if (!blk_mq_add_to_batch(req, iob, cmd->error,
>   					blk_mq_end_request_batch))
>   			blk_mq_end_request(req, cmd->error);
>   		nr++;
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index 6a61ec35f426..74f73cb8becd 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
> @@ -1207,11 +1207,12 @@ static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
>   
>   	while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
>   		struct request *req = blk_mq_rq_from_pdu(vbr);
> +		u8 status = virtblk_vbr_status(vbr);
>   
>   		found++;
>   		if (!blk_mq_complete_request_remote(req) &&
> -		    !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
> -						virtblk_complete_batch))
> +		    !blk_mq_add_to_batch(req, iob, virtblk_result(status),
> +					 virtblk_complete_batch))
>   			virtblk_request_done(req);
>   	}
>   
> diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
> index a060f69558e7..ae859f772485 100644
> --- a/drivers/nvme/host/apple.c
> +++ b/drivers/nvme/host/apple.c
> @@ -599,7 +599,8 @@ static inline void apple_nvme_handle_cqe(struct apple_nvme_queue *q,
>   	}
>   
>   	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
> -	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
> +	    !blk_mq_add_to_batch(req, iob,
> +				 nvme_error_status(nvme_req(req)->status),
>   				 apple_nvme_complete_batch))
>   		apple_nvme_complete_rq(req);
>   }
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 8359d0aa0e44..725f2052bcb2 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -274,7 +274,7 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
>   	nvme_put_ctrl(ctrl);
>   }
>   
> -static blk_status_t nvme_error_status(u16 status)
> +blk_status_t nvme_error_status(u16 status)
>   {
>   	switch (status & NVME_SCT_SC_MASK) {
>   	case NVME_SC_SUCCESS:
> @@ -315,6 +315,7 @@ static blk_status_t nvme_error_status(u16 status)
>   		return BLK_STS_IOERR;
>   	}
>   }
> +EXPORT_SYMBOL_GPL(nvme_error_status);
>   
>   static void nvme_retry_req(struct request *req)
>   {
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index 7be92d07430e..4e166da4aa81 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -904,6 +904,7 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
>   int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
>   int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
>   int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
> +blk_status_t nvme_error_status(u16 status);
>   void nvme_queue_scan(struct nvme_ctrl *ctrl);
>   int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
>   		void *log, size_t size, u64 offset);
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index 640590b21728..873564efc346 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -1130,8 +1130,9 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
>   
>   	trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail);
>   	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
> -	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
> -					nvme_pci_complete_batch))
> +	    !blk_mq_add_to_batch(req, iob,
> +				 nvme_error_status(nvme_req(req)->status),
> +				 nvme_pci_complete_batch))
>   		nvme_pci_complete_rq(req);
>   }
>   
> diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
> index 71f4f0cc3dac..9ba479a52ce7 100644
> --- a/include/linux/blk-mq.h
> +++ b/include/linux/blk-mq.h
> @@ -857,7 +857,8 @@ static inline bool blk_mq_is_reserved_rq(struct request *rq)
>    * ->end_io handler.
>    */
>   static inline bool blk_mq_add_to_batch(struct request *req,
> -				       struct io_comp_batch *iob, int ioerror,
> +				       struct io_comp_batch *iob,
> +				       blk_status_t status,
>   				       void (*complete)(struct io_comp_batch *))
>   {
>   	/*
> @@ -874,7 +875,7 @@ static inline bool blk_mq_add_to_batch(struct request *req,
>   	if (!blk_rq_is_passthrough(req)) {
>   		if (req->end_io)
>   			return false;
> -		if (ioerror < 0)
> +		if (blk_status_to_errno(status) < 0)
>   			return false;
>   	}
>   
That feels a bit odd; errno will always be negative, so we really are 
just checking if it's non-zero. Maybe it's better to use a 'bool' value
here, that would avoid all the rather pointless casting, too.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare at suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 N?rnberg
HRB 36809 (AG N?rnberg), GF: I. Totev, A. McDonald, W. Knoblich


From ardb at kernel.org  Tue Mar 11 00:01:37 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Tue, 11 Mar 2025 08:01:37 +0100
Subject: [PATCH] arm64/kernel: Always use level 2 or higher for early mappings
In-Reply-To: <2931b574-35ff-4a3e-b073-47ca94c45787@arm.com>
References: <20250310183011.2591600-2-ardb+git@google.com> <2931b574-35ff-4a3e-b073-47ca94c45787@arm.com>
Message-ID: <CAMj1kXHmOFN4+4sNSbHKbsYjEAW0Y1tbbYOD3ZA+++Q9nbnSzg@mail.gmail.com>

On Tue, 11 Mar 2025 at 05:12, Anshuman Khandual
<anshuman.khandual at arm.com> wrote:
>
>
>
> On 3/11/25 00:00, Ard Biesheuvel wrote:
> > From: Ard Biesheuvel <ardb at kernel.org>
> >
> > The page table population code in map_range() uses a recursive algorithm
> > to create the early mappings of the kernel, the DTB and the ID mapped
> > text and data pages, and this fails to take into account that the way
> > these page tables may be constructed is not precisely the same at each
> > level. In particular, block mappings are not permitted at each level,
> > and the code as it exists today might inadvertently create such a
> > forbidden block mapping if it were used to map a region of the
> > appropriate size and alignment.
> >
> > This never happens in practice, given the limited size of the assets
> > being mapped by the early boot code. Nonetheless, it would be better if
> > this code would behave correctly in all circumstances.
> >
> > So only permit block mappings at level 2, and page mappings at level 3,
> > for any page size, and use table mappings exclusively at all other
> > levels. This change should have no impact in practice, but it makes the
> > code more robust.
> >
> > Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> > Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> > Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> > ---
> >  arch/arm64/kernel/pi/map_range.c | 17 +++++++++--------
> >  1 file changed, 9 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> > index 2b69e3beeef8..025bb9f0aa0b 100644
> > --- a/arch/arm64/kernel/pi/map_range.c
> > +++ b/arch/arm64/kernel/pi/map_range.c
> > @@ -40,17 +40,10 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
> >       /* Advance tbl to the entry that covers start */
> >       tbl += (start >> (lshift + PAGE_SHIFT)) % PTRS_PER_PTE;
> >
> > -     /*
> > -      * Set the right block/page bits for this level unless we are
> > -      * clearing the mapping
> > -      */
> > -     if (protval)
> > -             protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> > -
> >       while (start < end) {
> >               u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
> >
> > -             if (level < 3 && (start | next | pa) & lmask) {
> > +             if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
> >                       /*
> >                        * This chunk needs a finer grained mapping. Create a
> >                        * table mapping if necessary and recurse.
> > @@ -64,6 +57,14 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
> >                                 (pte_t *)(__pte_to_phys(*tbl) + va_offset),
> >                                 may_use_cont, va_offset);
> >               } else {
> > +                     /*
> > +                      * Set the right block/page bits for this level unless
> > +                      * we are clearing the mapping
> > +                      */
> > +                     if (protval)
> > +                             protval |= (level == 2) ? PMD_TYPE_SECT
> > +                                                     : PTE_TYPE_PAGE;
> > +
> >                       /*
> >                        * Start a contiguous range if start and pa are
> >                        * suitably aligned
>
> LGTM and as Ryan mentioned, D128 ready as well !
>
> Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>

Thanks, both, but the patch is actually buggy so I'll need to respin this.


From 21cnbao at gmail.com  Tue Mar 11 00:05:35 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Tue, 11 Mar 2025 20:05:35 +1300
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <7938f840136165be1c50050feb39fb14ee37721b.camel@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <20250307120141.1566673-3-qun-wei.lin@mediatek.com> <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
 <7938f840136165be1c50050feb39fb14ee37721b.camel@mediatek.com>
Message-ID: <CAGsJ_4zzZdjbr2DbRybHYDmL2EuUBohOP1=ho7fjx1XWoKDDGw@mail.gmail.com>

On Tue, Mar 11, 2025 at 2:26?AM Qun-wei Lin (???)
<Qun-wei.Lin at mediatek.com> wrote:
>
> On Sat, 2025-03-08 at 08:41 +1300, Barry Song wrote:
> >
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> >
> >
> > On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > wrote:
> > >
> > > Introduced Kcompressd to offload zram page compression, improving
> > > system efficiency by handling compression separately from memory
> > > reclaiming. Added necessary configurations and dependencies.
> > >
> > > Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > > ---
> > >  drivers/block/zram/Kconfig      |  11 ++
> > >  drivers/block/zram/Makefile     |   3 +-
> > >  drivers/block/zram/kcompressd.c | 340
> > > ++++++++++++++++++++++++++++++++
> > >  drivers/block/zram/kcompressd.h |  25 +++
> > >  drivers/block/zram/zram_drv.c   |  22 ++-
> > >  5 files changed, 397 insertions(+), 4 deletions(-)
> > >  create mode 100644 drivers/block/zram/kcompressd.c
> > >  create mode 100644 drivers/block/zram/kcompressd.h
> > >
> > > diff --git a/drivers/block/zram/Kconfig
> > > b/drivers/block/zram/Kconfig
> > > index 402b7b175863..f0a1b574f770 100644
> > > --- a/drivers/block/zram/Kconfig
> > > +++ b/drivers/block/zram/Kconfig
> > > @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
> > >           re-compress pages using a potentially slower but more
> > > effective
> > >           compression algorithm. Note, that IDLE page recompression
> > >           requires ZRAM_TRACK_ENTRY_ACTIME.
> > > +
> > > +config KCOMPRESSD
> > > +       tristate "Kcompressd: Accelerated zram compression"
> > > +       depends on ZRAM
> > > +       help
> > > +         Kcompressd creates multiple daemons to accelerate the
> > > compression of pages
> > > +         in zram, offloading this time-consuming task from the
> > > zram driver.
> > > +
> > > +         This approach improves system efficiency by handling page
> > > compression separately,
> > > +         which was originally done by kswapd or direct reclaim.
> >
> > For direct reclaim, we were previously able to compress using
> > multiple CPUs
> > with multi-threading.
> > After your patch, it seems that only a single thread/CPU is used for
> > compression
> > so it won't necessarily improve direct reclaim performance?
> >
>
> Our patch only splits the context of kswapd. When direct reclaim is
> occurred, it is bypassed, so direct reclaim remains unchanged, with
> each thread that needs memory directly reclaiming it.

Qun-wei, I?m getting a bit confused. Looking at the code in page_io.c,
you always call swap_writepage_bdev_async() no matter if it is kswapd
or direct reclaim:

- else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO))
+ else if (data_race(sis->flags & SWP_WRITE_SYNCHRONOUS_IO))
           swap_writepage_bdev_sync(folio, wbc, sis);
  else
            swap_writepage_bdev_async(folio, wbc, sis);

In zram, I notice you are bypassing kcompressd by:

+ if (!nr_kcompressd || !current_is_kswapd())
+        return -EBUSY;

How will this work if no one is calling __end_swap_bio_write(&bio),
which is present in swap_writepage_bdev_sync()?
Am I missing something? Or is it done by zram_bio_write() ?

On the other hand, zram is a generic block device, and coupling its
code with kswapd/direct reclaim somehow violates layering
principles :-)

>
> > Even for kswapd, we used to have multiple threads like [kswapd0],
> > [kswapd1],
> > and [kswapd2] for different nodes. Now, are we also limited to just
> > one thread?
>
> We only considered a single kswapd here and didn't account for multiple
> instances. Since I use kfifo to collect the bios, if there are multiple
> kswapds, we need to add a lock to protect the bio queue. I can revise
> this in the 2nd version, or do you have any other suggested approaches?

I'm wondering if we can move the code to vmscan/page_io instead
of zram. If we're using a sync I/O swap device or have enabled zswap,
we could run reclamation in this separate thread, which should also be
NUMA-aware.

I would definitely be interested in prototyping it when I have the time.

>
> > I also wonder if this could be handled at the vmscan level instead of
> > the zram
> > level. then it might potentially help other sync devices or even
> > zswap later.
> >
> > But I agree that for phones, modifying zram seems like an easier
> > starting
> > point. However, relying on a single thread isn't always the best
> > approach.
> >
> >
> > > +
> > > diff --git a/drivers/block/zram/Makefile
> > > b/drivers/block/zram/Makefile
> > > index 0fdefd576691..23baa5dfceb9 100644
> > > --- a/drivers/block/zram/Makefile
> > > +++ b/drivers/block/zram/Makefile
> > > @@ -9,4 +9,5 @@ zram-$(CONFIG_ZRAM_BACKEND_ZSTD)        +=
> > > backend_zstd.o
> > >  zram-$(CONFIG_ZRAM_BACKEND_DEFLATE)    += backend_deflate.o
> > >  zram-$(CONFIG_ZRAM_BACKEND_842)                += backend_842.o
> > >
> > > -obj-$(CONFIG_ZRAM)     +=      zram.o
> > > +obj-$(CONFIG_ZRAM)             += zram.o
> > > +obj-$(CONFIG_KCOMPRESSD)       += kcompressd.o
> > > diff --git a/drivers/block/zram/kcompressd.c
> > > b/drivers/block/zram/kcompressd.c
> > > new file mode 100644
> > > index 000000000000..195b7e386869
> > > --- /dev/null
> > > +++ b/drivers/block/zram/kcompressd.c
> > > @@ -0,0 +1,340 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (C) 2024 MediaTek Inc.
> > > + */
> > > +
> > > +#include <linux/module.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/bio.h>
> > > +#include <linux/bitops.h>
> > > +#include <linux/freezer.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/psi.h>
> > > +#include <linux/kfifo.h>
> > > +#include <linux/swap.h>
> > > +#include <linux/delay.h>
> > > +
> > > +#include "kcompressd.h"
> > > +
> > > +#define INIT_QUEUE_SIZE                4096
> > > +#define DEFAULT_NR_KCOMPRESSD  4
> > > +
> > > +static atomic_t enable_kcompressd;
> > > +static unsigned int nr_kcompressd;
> > > +static unsigned int queue_size_per_kcompressd;
> > > +static struct kcompress *kcompress;
> > > +
> > > +enum run_state {
> > > +       KCOMPRESSD_NOT_STARTED = 0,
> > > +       KCOMPRESSD_RUNNING,
> > > +       KCOMPRESSD_SLEEPING,
> > > +};
> > > +
> > > +struct kcompressd_para {
> > > +       wait_queue_head_t *kcompressd_wait;
> > > +       struct kfifo *write_fifo;
> > > +       atomic_t *running;
> > > +};
> > > +
> > > +static struct kcompressd_para *kcompressd_para;
> > > +static BLOCKING_NOTIFIER_HEAD(kcompressd_notifier_list);
> > > +
> > > +struct write_work {
> > > +       void *mem;
> > > +       struct bio *bio;
> > > +       compress_callback cb;
> > > +};
> > > +
> > > +int kcompressd_enabled(void)
> > > +{
> > > +       return likely(atomic_read(&enable_kcompressd));
> > > +}
> > > +EXPORT_SYMBOL(kcompressd_enabled);
> > > +
> > > +static void kcompressd_try_to_sleep(struct kcompressd_para *p)
> > > +{
> > > +       DEFINE_WAIT(wait);
> > > +
> > > +       if (!kfifo_is_empty(p->write_fifo))
> > > +               return;
> > > +
> > > +       if (freezing(current) || kthread_should_stop())
> > > +               return;
> > > +
> > > +       atomic_set(p->running, KCOMPRESSD_SLEEPING);
> > > +       prepare_to_wait(p->kcompressd_wait, &wait,
> > > TASK_INTERRUPTIBLE);
> > > +
> > > +       /*
> > > +        * After a short sleep, check if it was a premature sleep.
> > > If not, then
> > > +        * go fully to sleep until explicitly woken up.
> > > +        */
> > > +       if (!kthread_should_stop() && kfifo_is_empty(p-
> > > >write_fifo))
> > > +               schedule();
> > > +
> > > +       finish_wait(p->kcompressd_wait, &wait);
> > > +       atomic_set(p->running, KCOMPRESSD_RUNNING);
> > > +}
> > > +
> > > +static int kcompressd(void *para)
> > > +{
> > > +       struct task_struct *tsk = current;
> > > +       struct kcompressd_para *p = (struct kcompressd_para *)para;
> > > +
> > > +       tsk->flags |= PF_MEMALLOC | PF_KSWAPD;
> > > +       set_freezable();
> > > +
> > > +       while (!kthread_should_stop()) {
> > > +               bool ret;
> > > +
> > > +               kcompressd_try_to_sleep(p);
> > > +               ret = try_to_freeze();
> > > +               if (kthread_should_stop())
> > > +                       break;
> > > +
> > > +               if (ret)
> > > +                       continue;
> > > +
> > > +               while (!kfifo_is_empty(p->write_fifo)) {
> > > +                       struct write_work entry;
> > > +
> > > +                       if (sizeof(struct write_work) ==
> > > kfifo_out(p->write_fifo,
> > > +                                               &entry,
> > > sizeof(struct write_work))) {
> > > +                               entry.cb(entry.mem, entry.bio);
> > > +                               bio_put(entry.bio);
> > > +                       }
> > > +               }
> > > +
> > > +       }
> > > +
> > > +       tsk->flags &= ~(PF_MEMALLOC | PF_KSWAPD);
> > > +       atomic_set(p->running, KCOMPRESSD_NOT_STARTED);
> > > +       return 0;
> > > +}
> > > +
> > > +static int init_write_queue(void)
> > > +{
> > > +       int i;
> > > +       unsigned int queue_len = queue_size_per_kcompressd *
> > > sizeof(struct write_work);
> > > +
> > > +       for (i = 0; i < nr_kcompressd; i++) {
> > > +               if (kfifo_alloc(&kcompress[i].write_fifo,
> > > +                                       queue_len, GFP_KERNEL)) {
> > > +                       pr_err("Failed to alloc kfifo %d\n", i);
> > > +                       return -ENOMEM;
> > > +               }
> > > +       }
> > > +       return 0;
> > > +}
> > > +
> > > +static void clean_bio_queue(int idx)
> > > +{
> > > +       struct write_work entry;
> > > +
> > > +       while (sizeof(struct write_work) ==
> > > kfifo_out(&kcompress[idx].write_fifo,
> > > +                               &entry, sizeof(struct write_work)))
> > > {
> > > +               bio_put(entry.bio);
> > > +               entry.cb(entry.mem, entry.bio);
> > > +       }
> > > +       kfifo_free(&kcompress[idx].write_fifo);
> > > +}
> > > +
> > > +static int kcompress_update(void)
> > > +{
> > > +       int i;
> > > +       int ret;
> > > +
> > > +       kcompress = kvmalloc_array(nr_kcompressd, sizeof(struct
> > > kcompress), GFP_KERNEL);
> > > +       if (!kcompress)
> > > +               return -ENOMEM;
> > > +
> > > +       kcompressd_para = kvmalloc_array(nr_kcompressd,
> > > sizeof(struct kcompressd_para), GFP_KERNEL);
> > > +       if (!kcompressd_para)
> > > +               return -ENOMEM;
> > > +
> > > +       ret = init_write_queue();
> > > +       if (ret) {
> > > +               pr_err("Initialization of writing to FIFOs
> > > failed!!\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       for (i = 0; i < nr_kcompressd; i++) {
> > > +               init_waitqueue_head(&kcompress[i].kcompressd_wait);
> > > +               kcompressd_para[i].kcompressd_wait =
> > > &kcompress[i].kcompressd_wait;
> > > +               kcompressd_para[i].write_fifo =
> > > &kcompress[i].write_fifo;
> > > +               kcompressd_para[i].running = &kcompress[i].running;
> > > +       }
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void stop_all_kcompressd_thread(void)
> > > +{
> > > +       int i;
> > > +
> > > +       for (i = 0; i < nr_kcompressd; i++) {
> > > +               kthread_stop(kcompress[i].kcompressd);
> > > +               kcompress[i].kcompressd = NULL;
> > > +               clean_bio_queue(i);
> > > +       }
> > > +}
> > > +
> > > +static int do_nr_kcompressd_handler(const char *val,
> > > +               const struct kernel_param *kp)
> > > +{
> > > +       int ret;
> > > +
> > > +       atomic_set(&enable_kcompressd, false);
> > > +
> > > +       stop_all_kcompressd_thread();
> > > +
> > > +       ret = param_set_int(val, kp);
> > > +       if (!ret) {
> > > +               pr_err("Invalid number of kcompressd.\n");
> > > +               return -EINVAL;
> > > +       }
> > > +
> > > +       ret = init_write_queue();
> > > +       if (ret) {
> > > +               pr_err("Initialization of writing to FIFOs
> > > failed!!\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       atomic_set(&enable_kcompressd, true);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static const struct kernel_param_ops
> > > param_ops_change_nr_kcompressd = {
> > > +       .set = &do_nr_kcompressd_handler,
> > > +       .get = &param_get_uint,
> > > +       .free = NULL,
> > > +};
> > > +
> > > +module_param_cb(nr_kcompressd, &param_ops_change_nr_kcompressd,
> > > +               &nr_kcompressd, 0644);
> > > +MODULE_PARM_DESC(nr_kcompressd, "Number of pre-created daemon for
> > > page compression");
> > > +
> > > +static int do_queue_size_per_kcompressd_handler(const char *val,
> > > +               const struct kernel_param *kp)
> > > +{
> > > +       int ret;
> > > +
> > > +       atomic_set(&enable_kcompressd, false);
> > > +
> > > +       stop_all_kcompressd_thread();
> > > +
> > > +       ret = param_set_int(val, kp);
> > > +       if (!ret) {
> > > +               pr_err("Invalid queue size for kcompressd.\n");
> > > +               return -EINVAL;
> > > +       }
> > > +
> > > +       ret = init_write_queue();
> > > +       if (ret) {
> > > +               pr_err("Initialization of writing to FIFOs
> > > failed!!\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       pr_info("Queue size for kcompressd was changed: %d\n",
> > > queue_size_per_kcompressd);
> > > +
> > > +       atomic_set(&enable_kcompressd, true);
> > > +       return 0;
> > > +}
> > > +
> > > +static const struct kernel_param_ops
> > > param_ops_change_queue_size_per_kcompressd = {
> > > +       .set = &do_queue_size_per_kcompressd_handler,
> > > +       .get = &param_get_uint,
> > > +       .free = NULL,
> > > +};
> > > +
> > > +module_param_cb(queue_size_per_kcompressd,
> > > &param_ops_change_queue_size_per_kcompressd,
> > > +               &queue_size_per_kcompressd, 0644);
> > > +MODULE_PARM_DESC(queue_size_per_kcompressd,
> > > +               "Size of queue for kcompressd");
> > > +
> > > +int schedule_bio_write(void *mem, struct bio *bio,
> > > compress_callback cb)
> > > +{
> > > +       int i;
> > > +       bool submit_success = false;
> > > +       size_t sz_work = sizeof(struct write_work);
> > > +
> > > +       struct write_work entry = {
> > > +               .mem = mem,
> > > +               .bio = bio,
> > > +               .cb = cb
> > > +       };
> > > +
> > > +       if (unlikely(!atomic_read(&enable_kcompressd)))
> > > +               return -EBUSY;
> > > +
> > > +       if (!nr_kcompressd || !current_is_kswapd())
> > > +               return -EBUSY;
> > > +
> > > +       bio_get(bio);
> > > +
> > > +       for (i = 0; i < nr_kcompressd; i++) {
> > > +               submit_success =
> > > +                       (kfifo_avail(&kcompress[i].write_fifo) >=
> > > sz_work) &&
> > > +                       (sz_work ==
> > > kfifo_in(&kcompress[i].write_fifo, &entry, sz_work));
> > > +
> > > +               if (submit_success) {
> > > +                       switch (atomic_read(&kcompress[i].running))
> > > {
> > > +                       case KCOMPRESSD_NOT_STARTED:
> > > +                               atomic_set(&kcompress[i].running,
> > > KCOMPRESSD_RUNNING);
> > > +                               kcompress[i].kcompressd =
> > > kthread_run(kcompressd,
> > > +
> > > &kcompressd_para[i], "kcompressd:%d", i);
> > > +                               if
> > > (IS_ERR(kcompress[i].kcompressd)) {
> > > +
> > > atomic_set(&kcompress[i].running, KCOMPRESSD_NOT_STARTED);
> > > +                                       pr_warn("Failed to start
> > > kcompressd:%d\n", i);
> > > +                                       clean_bio_queue(i);
> > > +                               }
> > > +                               break;
> > > +                       case KCOMPRESSD_RUNNING:
> > > +                               break;
> > > +                       case KCOMPRESSD_SLEEPING:
> > > +
> > > wake_up_interruptible(&kcompress[i].kcompressd_wait);
> > > +                               break;
> > > +                       }
> > > +                       return 0;
> > > +               }
> > > +       }
> > > +
> > > +       bio_put(bio);
> > > +       return -EBUSY;
> > > +}
> > > +EXPORT_SYMBOL(schedule_bio_write);
> > > +
> > > +static int __init kcompressd_init(void)
> > > +{
> > > +       int ret;
> > > +
> > > +       nr_kcompressd = DEFAULT_NR_KCOMPRESSD;
> > > +       queue_size_per_kcompressd = INIT_QUEUE_SIZE;
> > > +
> > > +       ret = kcompress_update();
> > > +       if (ret) {
> > > +               pr_err("Init kcompressd failed!\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       atomic_set(&enable_kcompressd, true);
> > > +       blocking_notifier_call_chain(&kcompressd_notifier_list, 0,
> > > NULL);
> > > +       return 0;
> > > +}
> > > +
> > > +static void __exit kcompressd_exit(void)
> > > +{
> > > +       atomic_set(&enable_kcompressd, false);
> > > +       stop_all_kcompressd_thread();
> > > +
> > > +       kvfree(kcompress);
> > > +       kvfree(kcompressd_para);
> > > +}
> > > +
> > > +module_init(kcompressd_init);
> > > +module_exit(kcompressd_exit);
> > > +
> > > +MODULE_LICENSE("Dual BSD/GPL");
> > > +MODULE_AUTHOR("Qun-Wei Lin <qun-wei.lin at mediatek.com>");
> > > +MODULE_DESCRIPTION("Separate the page compression from the memory
> > > reclaiming");
> > > +
> > > diff --git a/drivers/block/zram/kcompressd.h
> > > b/drivers/block/zram/kcompressd.h
> > > new file mode 100644
> > > index 000000000000..2fe0b424a7af
> > > --- /dev/null
> > > +++ b/drivers/block/zram/kcompressd.h
> > > @@ -0,0 +1,25 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/*
> > > + * Copyright (C) 2024 MediaTek Inc.
> > > + */
> > > +
> > > +#ifndef _KCOMPRESSD_H_
> > > +#define _KCOMPRESSD_H_
> > > +
> > > +#include <linux/rwsem.h>
> > > +#include <linux/kfifo.h>
> > > +#include <linux/atomic.h>
> > > +
> > > +typedef void (*compress_callback)(void *mem, struct bio *bio);
> > > +
> > > +struct kcompress {
> > > +       struct task_struct *kcompressd;
> > > +       wait_queue_head_t kcompressd_wait;
> > > +       struct kfifo write_fifo;
> > > +       atomic_t running;
> > > +};
> > > +
> > > +int kcompressd_enabled(void);
> > > +int schedule_bio_write(void *mem, struct bio *bio,
> > > compress_callback cb);
> > > +#endif
> > > +
> > > diff --git a/drivers/block/zram/zram_drv.c
> > > b/drivers/block/zram/zram_drv.c
> > > index 2e1a70f2f4bd..bcd63ecb6ff2 100644
> > > --- a/drivers/block/zram/zram_drv.c
> > > +++ b/drivers/block/zram/zram_drv.c
> > > @@ -35,6 +35,7 @@
> > >  #include <linux/part_stat.h>
> > >  #include <linux/kernel_read_file.h>
> > >
> > > +#include "kcompressd.h"
> > >  #include "zram_drv.h"
> > >
> > >  static DEFINE_IDR(zram_index_idr);
> > > @@ -2240,6 +2241,15 @@ static void zram_bio_write(struct zram
> > > *zram, struct bio *bio)
> > >         bio_endio(bio);
> > >  }
> > >
> > > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > > +static void zram_bio_write_callback(void *mem, struct bio *bio)
> > > +{
> > > +       struct zram *zram = (struct zram *)mem;
> > > +
> > > +       zram_bio_write(zram, bio);
> > > +}
> > > +#endif
> > > +
> > >  /*
> > >   * Handler function for all zram I/O requests.
> > >   */
> > > @@ -2252,6 +2262,10 @@ static void zram_submit_bio(struct bio *bio)
> > >                 zram_bio_read(zram, bio);
> > >                 break;
> > >         case REQ_OP_WRITE:
> > > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > > +               if (kcompressd_enabled() &&
> > > !schedule_bio_write(zram, bio, zram_bio_write_callback))
> > > +                       break;
> > > +#endif
> > >                 zram_bio_write(zram, bio);
> > >                 break;
> > >         case REQ_OP_DISCARD:
> > > @@ -2535,9 +2549,11 @@ static int zram_add(void)
> > >  #if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
> > >                 .max_write_zeroes_sectors       = UINT_MAX,
> > >  #endif
> > > -               .features                       =
> > > BLK_FEAT_STABLE_WRITES        |
> > > -
> > > BLK_FEAT_READ_SYNCHRONOUS     |
> > > -
> > > BLK_FEAT_WRITE_SYNCHRONOUS,
> > > +               .features                       =
> > > BLK_FEAT_STABLE_WRITES
> > > +                                                 |
> > > BLK_FEAT_READ_SYNCHRONOUS
> > > +#if !IS_ENABLED(CONFIG_KCOMPRESSD)
> > > +                                                 |
> > > BLK_FEAT_WRITE_SYNCHRONOUS,
> > > +#endif
> > >         };
> > >         struct zram *zram;
> > >         int ret, device_id;
> > > --
> > > 2.45.2
> > >
> >

Thanks
Barry


From alexander.sverdlin at siemens.com  Tue Mar 11 00:09:56 2025
From: alexander.sverdlin at siemens.com (Sverdlin, Alexander)
Date: Tue, 11 Mar 2025 07:09:56 +0000
Subject: [PATCH net] net: ethernet: ti: am65-cpsw: Fix NAPI registration
 sequence
In-Reply-To: <20250311061214.4111634-1-s-vadapalli@ti.com>
References: <20250311061214.4111634-1-s-vadapalli@ti.com>
Message-ID: <421a4c67865215927897e16866814bd6eb68a89d.camel@siemens.com>

Hi Siddharth!

On Tue, 2025-03-11 at 11:42 +0530, Siddharth Vadapalli wrote:
> From: Vignesh Raghavendra <vigneshr at ti.com>
> 
> Registering the interrupts for TX or RX DMA Channels prior to registering
> their respective NAPI callbacks can result in a NULL pointer dereference.
> This is seen in practice as a random occurrence since it depends on the
> randomness associated with the generation of traffic by Linux and the
> reception of traffic from the wire.
> 
> Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")

The patch Vignesh mentions here...

> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> ---
> 
> Hello,
> 
> This patch is based on commit
> 4d872d51bc9d Merge tag 'x86-urgent-2025-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
> of Mainline Linux.
> 
> Regards,
> Siddharth.
> 
> ?drivers/net/ethernet/ti/am65-cpsw-nuss.c | 12 ++++++------
> ?1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> index 2806238629f8..d5291281c781 100644
> --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> @@ -2314,6 +2314,9 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> ?		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
> ?		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
> ?
> +		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> +				? am65_cpsw_nuss_tx_poll);
> +
> ?		ret = devm_request_irq(dev, tx_chn->irq,
> ?				?????? am65_cpsw_nuss_tx_irq,
> ?				?????? IRQF_TRIGGER_HIGH,
> @@ -2323,9 +2326,6 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> ?				tx_chn->id, tx_chn->irq, ret);
> ?			goto err;
> ?		}
> -
> -		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> -				? am65_cpsw_nuss_tx_poll);

... has accounted for the fact ..._napi_add_... happens after [possibly unsuccessful] request_irq,
please grep for "for (--i ;". Is it necessary to adjust both loops, in the below case too?

> ?	}
> ?
> ?	return 0;
> @@ -2569,6 +2569,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?			???? HRTIMER_MODE_REL_PINNED);
> ?		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
> ?
> +		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> +			?????? am65_cpsw_nuss_rx_poll);
> +
> ?		ret = devm_request_irq(dev, flow->irq,
> ?				?????? am65_cpsw_nuss_rx_irq,
> ?				?????? IRQF_TRIGGER_HIGH,
> @@ -2579,9 +2582,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?			flow->irq = -EINVAL;
> ?			goto err_flow;
> ?		}
> -
> -		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> -			?????? am65_cpsw_nuss_rx_poll);
> ?	}
> ?
> ?	/* setup classifier to route priorities to flows */

-- 
Alexander Sverdlin
Siemens AG
www.siemens.com

From 21cnbao at gmail.com  Tue Mar 11 00:25:09 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Tue, 11 Mar 2025 20:25:09 +1300
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram compression
In-Reply-To: <CAGsJ_4zzZdjbr2DbRybHYDmL2EuUBohOP1=ho7fjx1XWoKDDGw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <20250307120141.1566673-3-qun-wei.lin@mediatek.com> <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
 <7938f840136165be1c50050feb39fb14ee37721b.camel@mediatek.com> <CAGsJ_4zzZdjbr2DbRybHYDmL2EuUBohOP1=ho7fjx1XWoKDDGw@mail.gmail.com>
Message-ID: <CAGsJ_4yuyJc_-Ods-um_jtAgFFJ_qJi1=b8Kf-_ngU0UHjMQYA@mail.gmail.com>

On Tue, Mar 11, 2025 at 8:05?PM Barry Song <21cnbao at gmail.com> wrote:
>
> On Tue, Mar 11, 2025 at 2:26?AM Qun-wei Lin (???)
> <Qun-wei.Lin at mediatek.com> wrote:
> >
> > On Sat, 2025-03-08 at 08:41 +1300, Barry Song wrote:
> > >
> > > External email : Please do not click links or open attachments until
> > > you have verified the sender or the content.
> > >
> > >
> > > On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > > wrote:
> > > >
> > > > Introduced Kcompressd to offload zram page compression, improving
> > > > system efficiency by handling compression separately from memory
> > > > reclaiming. Added necessary configurations and dependencies.
> > > >
> > > > Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > > > ---
> > > >  drivers/block/zram/Kconfig      |  11 ++
> > > >  drivers/block/zram/Makefile     |   3 +-
> > > >  drivers/block/zram/kcompressd.c | 340
> > > > ++++++++++++++++++++++++++++++++
> > > >  drivers/block/zram/kcompressd.h |  25 +++
> > > >  drivers/block/zram/zram_drv.c   |  22 ++-
> > > >  5 files changed, 397 insertions(+), 4 deletions(-)
> > > >  create mode 100644 drivers/block/zram/kcompressd.c
> > > >  create mode 100644 drivers/block/zram/kcompressd.h
> > > >
> > > > diff --git a/drivers/block/zram/Kconfig
> > > > b/drivers/block/zram/Kconfig
> > > > index 402b7b175863..f0a1b574f770 100644
> > > > --- a/drivers/block/zram/Kconfig
> > > > +++ b/drivers/block/zram/Kconfig
> > > > @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
> > > >           re-compress pages using a potentially slower but more
> > > > effective
> > > >           compression algorithm. Note, that IDLE page recompression
> > > >           requires ZRAM_TRACK_ENTRY_ACTIME.
> > > > +
> > > > +config KCOMPRESSD
> > > > +       tristate "Kcompressd: Accelerated zram compression"
> > > > +       depends on ZRAM
> > > > +       help
> > > > +         Kcompressd creates multiple daemons to accelerate the
> > > > compression of pages
> > > > +         in zram, offloading this time-consuming task from the
> > > > zram driver.
> > > > +
> > > > +         This approach improves system efficiency by handling page
> > > > compression separately,
> > > > +         which was originally done by kswapd or direct reclaim.
> > >
> > > For direct reclaim, we were previously able to compress using
> > > multiple CPUs
> > > with multi-threading.
> > > After your patch, it seems that only a single thread/CPU is used for
> > > compression
> > > so it won't necessarily improve direct reclaim performance?
> > >
> >
> > Our patch only splits the context of kswapd. When direct reclaim is
> > occurred, it is bypassed, so direct reclaim remains unchanged, with
> > each thread that needs memory directly reclaiming it.
>
> Qun-wei, I?m getting a bit confused. Looking at the code in page_io.c,
> you always call swap_writepage_bdev_async() no matter if it is kswapd
> or direct reclaim:
>
> - else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO))
> + else if (data_race(sis->flags & SWP_WRITE_SYNCHRONOUS_IO))
>            swap_writepage_bdev_sync(folio, wbc, sis);
>   else
>             swap_writepage_bdev_async(folio, wbc, sis);
>
> In zram, I notice you are bypassing kcompressd by:
>
> + if (!nr_kcompressd || !current_is_kswapd())
> +        return -EBUSY;
>
> How will this work if no one is calling __end_swap_bio_write(&bio),
> which is present in swap_writepage_bdev_sync()?
> Am I missing something? Or is it done by zram_bio_write() ?
>
> On the other hand, zram is a generic block device, and coupling its
> code with kswapd/direct reclaim somehow violates layering
> principles :-)
>
> >
> > > Even for kswapd, we used to have multiple threads like [kswapd0],
> > > [kswapd1],
> > > and [kswapd2] for different nodes. Now, are we also limited to just
> > > one thread?
> >
> > We only considered a single kswapd here and didn't account for multiple
> > instances. Since I use kfifo to collect the bios, if there are multiple
> > kswapds, we need to add a lock to protect the bio queue. I can revise
> > this in the 2nd version, or do you have any other suggested approaches?
>
> I'm wondering if we can move the code to vmscan/page_io instead
> of zram. If we're using a sync I/O swap device or have enabled zswap,
> we could run reclamation in this separate thread, which should also be

Sorry for the typo:
s/reclamation/__swap_writepage/g

> NUMA-aware.
>
> I would definitely be interested in prototyping it when I have the time.
>

Thanks
Barry


From kw at linux.com  Tue Mar 11 00:25:46 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Tue, 11 Mar 2025 16:25:46 +0900
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250311051806.smcu4o4dxpngimth@uda0492258>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
 <20250311051806.smcu4o4dxpngimth@uda0492258>
Message-ID: <20250311072546.GA277060@rocinante>

Hello,

> > > Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> > > expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> > > already reuse this macro since it accurately represents the link-state
> > > field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> > 
> > Can you confirm for me that the following use the correct macro?
> > 
> >   333-static const struct j721e_pcie_data j721e_pcie_rc_data = {
> >   337:	.linkdown_irq_regfield = LINK_DOWN,
> >   
> >   341-static const struct j721e_pcie_data j721e_pcie_ep_data = {
> >   343:	.linkdown_irq_regfield = LINK_DOWN,
> >   
> >   347-static const struct j721e_pcie_data j7200_pcie_rc_data = {
> >   350:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> >   
> >   362-static const struct j721e_pcie_data am64_pcie_rc_data = {
> >   364:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> >   
> >   369-static const struct j721e_pcie_data am64_pcie_ep_data = {
> >   371:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> >   
> >   375-static const struct j721e_pcie_data j784s4_pcie_rc_data = {
> >   379:	.linkdown_irq_regfield = LINK_DOWN,
> >   
> >   383-static const struct j721e_pcie_data j784s4_pcie_ep_data = {
> >   385:	.linkdown_irq_regfield = LINK_DOWN,
> >   
> >   389-static const struct j721e_pcie_data j722s_pcie_rc_data = {
> >   391:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> > 
> > I am asking as some use LINK_DOWN, so I wanted to make sure.
> 
> Yes, the above are accurate except for J784S4 which is fixed by this
> patch. LINK_DOWN i.e. BIT(1) is applicable only to J721E which was the
> first SoC after which the driver has been named. For all other SoCs, the
> integration of the PCIe Controller into the SoC led to BIT(10) of the
> register being used to indicate the link status.

Sounds good!  Thank you for letting me know.

> > Tht said, the following has no .linkdown_irq_regfield property set:
> > 
> >   355-static const struct j721e_pcie_data j7200_pcie_ep_data = {
> >   356-	.mode = PCI_MODE_EP,
> >   357-	.quirk_detect_quiet_flag = true,
> >   358-	.quirk_disable_flr = true,
> >   359-	.max_lanes = 2,
> >   360-};
> > 
> > Would this be a problem?  Or is this as expected?
> 
> Thank you for pointing this out. This has to be fixed and the
> "linkdown_irq_regfield" member has to be added to match
> j7200_pcie_rc_data. I will post the fix for this.

No need to send a new version.

I will update the branch directly when I pull the patch.  Not to worry.

Thank you!

	Krzysztof


From vigneshr at ti.com  Tue Mar 11 00:27:55 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Tue, 11 Mar 2025 12:57:55 +0530
Subject: [PATCH 0/5] Add J722S CSI support
In-Reply-To: <174133309362.1072814.5440404016847301624.b4-ty@ti.com>
References: <20250218185452.600797-1-vaishnav.a@ti.com>
 <174133309362.1072814.5440404016847301624.b4-ty@ti.com>
Message-ID: <8f03c097-e2c1-452a-85e2-90accbac7443@ti.com>



On 07/03/25 16:06, Vignesh Raghavendra wrote:
> Hi Vaishnav Achath,
> 
> On Wed, 19 Feb 2025 00:24:47 +0530, Vaishnav Achath wrote:
>> This series adds support for CSI2RX capture on J722S EVM
>> and enables IMX219 and OV5640 overlays to enables
>> 4 sensors on EVM, this provides a reference for a user to
>> enable a different sensor on any of the ports.
>>
>> Test logs:
>> IMX219: https://gist.github.com/vaishnavachath/60cc2ef257601f27f28a315f8cf669c4
>> OV5640: https://gist.github.com/vaishnavachath/648202286d4d34d4d25f7c8c9db8b8bd
>>
>> [...]
> I have applied the following to branch ti-k3-dts-next on [1].
> Thank you!
> 
> [1/5] arm64: dts: ti: k3-j722s-main: Add BCDMA CSI overrides
>       commit: fb1b230bf9c45f5d6579dc329c2aafcd1263b70a
> [2/5] arm64: dts: ti: k3-j722s-main: Add CSI2RX nodes
>       commit: 8fea4519f625e6c1b05078f2ecea252b7b28b06e
> [3/5] arm64: dts: ti: k3-j722s-evm: Add camera peripherals
>       commit: ce553288ad2368f0d27e47b39a23121a825a2b33

> [4/5] arm64: dts: ti: k3-j722s-evm: Add overlay for quad IMX219
>       commit: c24ccb1cd77fb44087b2f7008d99626796b33ca4
> [5/5] arm64: dts: ti: k3-j722s-evm: Add overlay for TEVI OV5640
>       commit: 938806652b0a3c90d67e7137c91708d06940b03d

I have dropped 4 and 5 due to issues Rob pointed out in the other thread.

-- 
Regards
Vignesh
https://ti.com/opensource



From krzk at kernel.org  Tue Mar 11 00:32:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 08:32:47 +0100
Subject: [PATCH v3 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250310114839.3098148-2-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
 <20250310114839.3098148-2-kevin_chen@aspeedtech.com>
Message-ID: <5d14e715-7940-4f1b-ab79-860ada066072@kernel.org>

On 10/03/2025 12:48, Kevin Chen wrote:
> Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.


<form letter>
This is a friendly reminder during the review process.

It seems my or other reviewer's previous comments were not fully
addressed. Maybe the feedback got lost between the quotes, maybe you
just forgot to apply it. Please go back to the previous discussion and
either implement all requested changes or keep discussing them.

Thank you.
</form letter>

> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> ---
>  .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> index 5dfe77aca167..178c151a19ba 100644
> --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
> @@ -149,6 +149,37 @@ patternProperties:
>        - interrupts
>        - snoop-ports
>  
> +  "^lpc-pcc@[0-9a-f]+$":
> +    type: object
> +    additionalProperties: false
> +
> +    description:
> +      The LPC pcc interface allows the BMC to listen on and record the data
> +      bytes written by the Host to the targeted LPC I/O pots.
> +
> +    properties:
> +      compatible:
> +        items:
> +          - enum:
> +              - aspeed,ast2600-lpc-pcc
> +
> +      reg:
> +        maxItems: 1
> +
> +      interrupts:
> +        maxItems: 1
> +
> +      pcc-ports:
> +        $ref: /schemas/types.yaml#/definitions/uint32-array
> +        description:
> +          As a device handshake with a host using the port-mmaped I/O in x86
> +          architecture, need to handle specific which port I/O address for use.

<form letter>
This is a friendly reminder during the review process.

It seems my or other reviewer's previous comments were not fully
addressed. Maybe the feedback got lost between the quotes, maybe you
just forgot to apply it. Please go back to the previous discussion and
either implement all requested changes or keep discussing them.

Thank you.
</form letter>



Best regards,
Krzysztof


From adrian.hunter at intel.com  Tue Mar 11 00:34:28 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 11 Mar 2025 09:34:28 +0200
Subject: [RFC PATCH] mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
In-Reply-To: <20250310140707.23459-1-balejk@matfyz.cz>
References: <20250310140707.23459-1-balejk@matfyz.cz>
Message-ID: <727c857f-0234-417b-af5d-69b3ae064d0f@intel.com>

On 10/03/25 16:07, Karel Balej wrote:
> Set the MMC_CAP_NEED_RSP_BUSY capability for the sdhci-pxav3 host to
> prevent conversion of R1B responses to R1. Without this, the eMMC card
> in the samsung,coreprimevelte smartphone using the Marvell PXA1908 SoC

So that SoC is from 2015?

Is there anything more recent using this driver?

> with this mmc host doesn't probe with the ETIMEDOUT error originating in
> __mmc_poll_for_busy.
> 
> Note that the other issues reported for this phone and host, namely
> floods of "Tuning failed, falling back to fixed sampling clock" dmesg
> messages for the eMMC and unstable SDIO are not mitigated by this
> change.
> 
> Link: https://lore.kernel.org/r/20200310153340.5593-1-ulf.hansson at linaro.org/
> Link: https://lore.kernel.org/r/D7204PWIGQGI.1FRFQPPIEE2P9 at matfyz.cz/
> Link: https://lore.kernel.org/r/20250115-pxa1908-lkml-v14-0-847d24f3665a at skole.hr/
> Cc: Duje Mihanovi? <duje.mihanovic at skole.hr>
> Cc: stable at vger.kernel.org
> Signed-off-by: Karel Balej <balejk at matfyz.cz>
> ---
>  drivers/mmc/host/sdhci-pxav3.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
> index 990723a008ae..3fb56face3d8 100644
> --- a/drivers/mmc/host/sdhci-pxav3.c
> +++ b/drivers/mmc/host/sdhci-pxav3.c
> @@ -399,6 +399,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
>  	if (!IS_ERR(pxa->clk_core))
>  		clk_prepare_enable(pxa->clk_core);
>  
> +	host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
>  	/* enable 1/8V DDR capable */
>  	host->mmc->caps |= MMC_CAP_1_8V_DDR;
>  



From ardb+git at google.com  Tue Mar 11 00:30:44 2025
From: ardb+git at google.com (Ard Biesheuvel)
Date: Tue, 11 Mar 2025 08:30:44 +0100
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early mappings
Message-ID: <20250311073043.96795-2-ardb+git@google.com>

From: Ard Biesheuvel <ardb at kernel.org>

The page table population code in map_range() uses a recursive algorithm
to create the early mappings of the kernel, the DTB and the ID mapped
text and data pages, and this fails to take into account that the way
these page tables may be constructed is not precisely the same at each
level. In particular, block mappings are not permitted at each level,
and the code as it exists today might inadvertently create such a
forbidden block mapping if it were used to map a region of the
appropriate size and alignment.

This never happens in practice, given the limited size of the assets
being mapped by the early boot code. Nonetheless, it would be better if
this code would behave correctly in all circumstances.

So only permit block mappings at level 2, and page mappings at level 3,
for any page size, and use table mappings exclusively at all other
levels. This change should have no impact in practice, but it makes the
code more robust.

Cc: Anshuman Khandual <anshuman.khandual at arm.com>
Reported-by: Ryan Roberts <ryan.roberts at arm.com>
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
v2: take the assignment of protval out of the loop again, so that
    clearing a mapping works as expected wrt the PTE_CONT bit

 arch/arm64/kernel/pi/map_range.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..5778697f3062 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -45,12 +45,12 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	 * clearing the mapping
 	 */
 	if (protval)
-		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
+		protval |= (level == 2) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
 
 	while (start < end) {
 		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
 
-		if (level < 3 && (start | next | pa) & lmask) {
+		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
 			/*
 			 * This chunk needs a finer grained mapping. Create a
 			 * table mapping if necessary and recurse.
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From s-vadapalli at ti.com  Tue Mar 11 00:32:16 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 13:02:16 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250311072546.GA277060@rocinante>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
 <20250311051806.smcu4o4dxpngimth@uda0492258>
 <20250311072546.GA277060@rocinante>
Message-ID: <20250311073216.ynw7rzmu36dwywij@uda0492258>

On Tue, Mar 11, 2025 at 04:25:46PM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> > > > Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> > > > expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> > > > already reuse this macro since it accurately represents the link-state
> > > > field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> > > 
> > > Can you confirm for me that the following use the correct macro?
> > > 
> > >   333-static const struct j721e_pcie_data j721e_pcie_rc_data = {
> > >   337:	.linkdown_irq_regfield = LINK_DOWN,
> > >   
> > >   341-static const struct j721e_pcie_data j721e_pcie_ep_data = {
> > >   343:	.linkdown_irq_regfield = LINK_DOWN,
> > >   
> > >   347-static const struct j721e_pcie_data j7200_pcie_rc_data = {
> > >   350:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> > >   
> > >   362-static const struct j721e_pcie_data am64_pcie_rc_data = {
> > >   364:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> > >   
> > >   369-static const struct j721e_pcie_data am64_pcie_ep_data = {
> > >   371:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> > >   
> > >   375-static const struct j721e_pcie_data j784s4_pcie_rc_data = {
> > >   379:	.linkdown_irq_regfield = LINK_DOWN,
> > >   
> > >   383-static const struct j721e_pcie_data j784s4_pcie_ep_data = {
> > >   385:	.linkdown_irq_regfield = LINK_DOWN,
> > >   
> > >   389-static const struct j721e_pcie_data j722s_pcie_rc_data = {
> > >   391:	.linkdown_irq_regfield = J7200_LINK_DOWN,
> > > 
> > > I am asking as some use LINK_DOWN, so I wanted to make sure.
> > 
> > Yes, the above are accurate except for J784S4 which is fixed by this
> > patch. LINK_DOWN i.e. BIT(1) is applicable only to J721E which was the
> > first SoC after which the driver has been named. For all other SoCs, the
> > integration of the PCIe Controller into the SoC led to BIT(10) of the
> > register being used to indicate the link status.
> 
> Sounds good!  Thank you for letting me know.
> 
> > > Tht said, the following has no .linkdown_irq_regfield property set:
> > > 
> > >   355-static const struct j721e_pcie_data j7200_pcie_ep_data = {
> > >   356-	.mode = PCI_MODE_EP,
> > >   357-	.quirk_detect_quiet_flag = true,
> > >   358-	.quirk_disable_flr = true,
> > >   359-	.max_lanes = 2,
> > >   360-};
> > > 
> > > Would this be a problem?  Or is this as expected?
> > 
> > Thank you for pointing this out. This has to be fixed and the
> > "linkdown_irq_regfield" member has to be added to match
> > j7200_pcie_rc_data. I will post the fix for this.
> 
> No need to send a new version.
> 
> I will update the branch directly when I pull the patch.  Not to worry.

Thank you Krzysztof :)

Regards,
Siddharth.


From krzk at kernel.org  Tue Mar 11 00:34:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 08:34:47 +0100
Subject: [PATCH v3 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250310114839.3098148-4-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
 <20250310114839.3098148-4-kevin_chen@aspeedtech.com>
Message-ID: <0e30c12f-5ac5-4008-8cc8-ec4111520655@kernel.org>

On 10/03/2025 12:48, Kevin Chen wrote:
> +static int aspeed_pcc_probe(struct platform_device *pdev)
> +{
> +	int rc;
> +	struct aspeed_pcc_ctrl *pcc;
> +	struct device *dev = &pdev->dev;
> +	uint32_t fifo_size = PAGE_SIZE;
> +
> +	pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL);
> +	if (!pcc)
> +		return -ENOMEM;
> +
> +	pcc->regmap = syscon_node_to_regmap(dev->parent->of_node);
> +	if (IS_ERR(pcc->regmap)) {
> +		dev_err(dev, "Couldn't get regmap\n");

return dev_err_probe() is not suitable?

> +		return -ENODEV;

Why overriding error code?

> +	}
> +
> +	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
> +	if (rc) {
> +		dev_err(dev, "no pcc ports configured\n");
> +		return -ENODEV;

Why overriding error code?

You got this comment already at v2.

> +	}
> +
> +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> +	if (rc) {
> +		dev_err(dev, "cannot set 64-bits DMA mask\n");
> +		return rc;
> +	}
> +
> +	pcc->dma.size = PCC_DMA_BUFSZ;
> +	pcc->dma.virt = dmam_alloc_coherent(dev,
> +					    pcc->dma.size,
> +					    &pcc->dma.addr,
> +					    GFP_KERNEL);
> +	if (!pcc->dma.virt) {
> +		dev_err(dev, "cannot allocate DMA buffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
> +	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
> +	if (rc) {

Drop {}

> +		return -ENOMEM;
> +	}
> +

Please run scripts/checkpatch.pl and fix reported warnings. After that,
run also `scripts/checkpatch.pl --strict` and (probably) fix more
warnings. Some warnings can be ignored, especially from --strict run,
but the code here looks like it needs a fix. Feel free to get in touch
if the warning is not clear.



Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 11 00:51:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 08:51:48 +0100
Subject: [PATCH v3 02/18] dt-bindings: gpu: img: Add BXS-4-64 devicetree
 bindings
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
Message-ID: <20250311-bizarre-debonair-macaque-451c4f@krzk-bin>

On Mon, Mar 10, 2025 at 01:10:26PM +0000, Matt Coster wrote:
> Unlike AXE-1-16M, BXS-4-64 uses two power domains.
> 
> Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
> integration in the TI k3-j721s2.
> 
> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
> ---
> Changes in v3:
> - Include adding the second power domain so it's in context
> - Remove unnecessary example
> - Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
> Changes in v2:
> - Use normal reg syntax for 64-bit values
> - Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
> ---
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 34 +++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> index 5c16b2881447c9cda78e5bb46569e2f675d740c4..d9409d33154d429019776ddbf9d123b33f8c9740 100644
> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> @@ -18,6 +18,11 @@ properties:
>                - ti,am62-gpu
>            - const: img,img-axe-1-16m
>            - const: img,img-rogue
> +      - items:
> +          - enum:
> +              - ti,j721s2-gpu
> +          - const: img,img-bxs-4-64
> +          - const: img,img-rogue
>  
>        # This legacy combination of compatible strings was introduced early on
>        # before the more specific GPU identifiers were used.
> @@ -49,6 +54,7 @@ properties:
>    power-domain-names:
>      items:
>        - const: a
> +      - const: b

No, you just affected old device claiming it has two items. What's more,
it's not synced with power-domains. Both properties must have the same
constraints, but above power domains have "anything".

>  
>    dma-coherent: true
>  
> @@ -74,12 +80,38 @@ allOf:
>          - power-domains
>          - power-domain-names
>  
> +  # Cores with one power domain

Drop

> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: img,img-axe-1-16m
> +    then:
> +      properties:
> +        power-domain-names:
> +          minItems: 1

Drop

> +          maxItems: 1
> +
> +  # Cores with two power domains

Drop

> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: img,img-bxs-4-64
> +    then:
> +      properties:
> +        power-domain-names:
> +          minItems: 2
> +          maxItems: 2

Missing constraints for power-domains.

Best regards,
Krzysztof



From yangyicong at huawei.com  Tue Mar 11 00:51:42 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 15:51:42 +0800
Subject: [PATCH v12 3/4] arm64: topology: Support SMT control on ACPI based system
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <20250311075143.61078-4-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

For ACPI we'll build the topology from PPTT and we cannot directly
get the SMT number of each core. Instead using a temporary xarray
to record the heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL)
and SMT information of the first core in its heterogeneous CPU cluster
when building the topology. Then we can know the largest SMT number
in the system. If a homogeneous system's using ACPI 6.2 or later,
all the CPUs should be under the root node of PPTT. There'll be
only one entry in the xarray and all the CPUs in the system will
be assumed identical.

The framework's SMT control provides two interface to the users [1]
through /sys/devices/system/cpu/smt/control:
1) enable SMT by writing "on" and disable by "off"
2) enable SMT by writing max_thread_number or disable by writing 1

Both method support to completely disable/enable the SMT cores so both
work correctly for symmetric SMT platform and asymmetric platform with
non-SMT and one type SMT cores like:
core A: 1 thread
core B: X (X!=1) threads

Note that for a theoretically possible multiple SMT-X (X>1) core
platform the SMT control is also supported as expected but only
by writing the "on/off" method.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Reviewed-by: Hanjun Guo <guohanjun at huawei.com>
Reviewed-by: Pierre Gondois <pierre.gondois at arm.com>
Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 arch/arm64/kernel/topology.c | 54 ++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index cb180684d10d..0bcea4f89ea8 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -15,8 +15,10 @@
 #include <linux/arch_topology.h>
 #include <linux/cacheinfo.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu_smt.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
+#include <linux/xarray.h>
 
 #include <asm/cpu.h>
 #include <asm/cputype.h>
@@ -37,17 +39,28 @@ static bool __init acpi_cpu_is_threaded(int cpu)
 	return !!is_threaded;
 }
 
+struct cpu_smt_info {
+	unsigned int thread_num;
+	int core_id;
+};
+
 /*
  * Propagate the topology information of the processor_topology_node tree to the
  * cpu_topology array.
  */
 int __init parse_acpi_topology(void)
 {
+	unsigned int max_smt_thread_num = 1;
+	struct cpu_smt_info *entry;
+	struct xarray hetero_cpu;
+	unsigned long hetero_id;
 	int cpu, topology_id;
 
 	if (acpi_disabled)
 		return 0;
 
+	xa_init(&hetero_cpu);
+
 	for_each_possible_cpu(cpu) {
 		topology_id = find_acpi_cpu_topology(cpu, 0);
 		if (topology_id < 0)
@@ -57,6 +70,34 @@ int __init parse_acpi_topology(void)
 			cpu_topology[cpu].thread_id = topology_id;
 			topology_id = find_acpi_cpu_topology(cpu, 1);
 			cpu_topology[cpu].core_id   = topology_id;
+
+			/*
+			 * In the PPTT, CPUs below a node with the 'identical
+			 * implementation' flag have the same number of threads.
+			 * Count the number of threads for only one CPU (i.e.
+			 * one core_id) among those with the same hetero_id.
+			 * See the comment of find_acpi_cpu_topology_hetero_id()
+			 * for more details.
+			 *
+			 * One entry is created for each node having:
+			 * - the 'identical implementation' flag
+			 * - its parent not having the flag
+			 */
+			hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
+			entry = xa_load(&hetero_cpu, hetero_id);
+			if (!entry) {
+				entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+				WARN_ON_ONCE(!entry);
+
+				if (entry) {
+					entry->core_id = topology_id;
+					entry->thread_num = 1;
+					xa_store(&hetero_cpu, hetero_id,
+						 entry, GFP_KERNEL);
+				}
+			} else if (entry->core_id == topology_id) {
+				entry->thread_num++;
+			}
 		} else {
 			cpu_topology[cpu].thread_id  = -1;
 			cpu_topology[cpu].core_id    = topology_id;
@@ -67,6 +108,19 @@ int __init parse_acpi_topology(void)
 		cpu_topology[cpu].package_id = topology_id;
 	}
 
+	/*
+	 * This is a short loop since the number of XArray elements is the
+	 * number of heterogeneous CPU clusters. On a homogeneous system
+	 * there's only one entry in the XArray.
+	 */
+	xa_for_each(&hetero_cpu, hetero_id, entry) {
+		max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
+		xa_erase(&hetero_cpu, hetero_id);
+		kfree(entry);
+	}
+
+	cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
+	xa_destroy(&hetero_cpu);
 	return 0;
 }
 #endif
-- 
2.24.0



From yangyicong at huawei.com  Tue Mar 11 00:51:43 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 15:51:43 +0800
Subject: [PATCH v12 4/4] arm64: Kconfig: Enable HOTPLUG_SMT
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <20250311075143.61078-5-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Enable HOTPLUG_SMT for SMT control.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Reviewed-by: Pierre Gondois <pierre.gondois at arm.com>
Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..65fe00b1922c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -250,6 +250,7 @@ config ARM64
 	select HAVE_KRETPROBES
 	select HAVE_GENERIC_VDSO
 	select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU
+	select HOTPLUG_SMT if HOTPLUG_CPU
 	select IRQ_DOMAIN
 	select IRQ_FORCED_THREADING
 	select KASAN_VMALLOC if KASAN
-- 
2.24.0



From yangyicong at huawei.com  Tue Mar 11 00:51:41 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 15:51:41 +0800
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based system
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <20250311075143.61078-3-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

On building the topology from the devicetree, we've already gotten the
SMT thread number of each core. Update the largest SMT thread number
and enable the SMT control by the end of topology parsing.

The framework's SMT control provides two interface to the users [1]
through /sys/devices/system/cpu/smt/control:
1) enable SMT by writing "on" and disable by "off"
2) enable SMT by writing max_thread_number or disable by writing 1

Both method support to completely disable/enable the SMT cores so both
work correctly for symmetric SMT platform and asymmetric platform with
non-SMT and one type SMT cores like:
core A: 1 thread
core B: X (X!=1) threads

Note that for a theoretically possible multiple SMT-X (X>1) core
platform the SMT control is also supported as expected but only
by writing the "on/off" method.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
Reviewed-by: Pierre Gondois <pierre.gondois at arm.com>
Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/base/arch_topology.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 3ebe77566788..d409d323ee64 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -11,6 +11,7 @@
 #include <linux/cleanup.h>
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu_smt.h>
 #include <linux/device.h>
 #include <linux/of.h>
 #include <linux/slab.h>
@@ -506,6 +507,10 @@ core_initcall(free_raw_capacity);
 #endif
 
 #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
+
+/* Used to enable the SMT control */
+static unsigned int max_smt_thread_num = 1;
+
 /*
  * This function returns the logic cpu number of the node.
  * There are basically three kinds of return values:
@@ -565,6 +570,8 @@ static int __init parse_core(struct device_node *core, int package_id,
 		i++;
 	} while (1);
 
+	max_smt_thread_num = max_t(unsigned int, max_smt_thread_num, i);
+
 	cpu = get_cpu_for_node(core);
 	if (cpu >= 0) {
 		if (!leaf) {
@@ -677,6 +684,17 @@ static int __init parse_socket(struct device_node *socket)
 	if (!has_socket)
 		ret = parse_cluster(socket, 0, -1, 0);
 
+	/*
+	 * Reset the max_smt_thread_num to 1 on failure. Since on failure
+	 * we need to notify the framework the SMT is not supported, but
+	 * max_smt_thread_num can be initialized to the SMT thread number
+	 * of the cores which are successfully parsed.
+	 */
+	if (ret)
+		max_smt_thread_num = 1;
+
+	cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
+
 	return ret;
 }
 
-- 
2.24.0



From yangyicong at huawei.com  Tue Mar 11 00:51:40 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 15:51:40 +0800
Subject: [PATCH v12 1/4] cpu/SMT: Provide a default topology_is_primary_thread()
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <20250311075143.61078-2-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Currently if architectures want to support HOTPLUG_SMT they need to
provide a topology_is_primary_thread() telling the framework which
thread in the SMT cannot offline. However arm64 doesn't have a
restriction on which thread in the SMT cannot offline, a simplest
choice is that just make 1st thread as the "primary" thread. So
just make this as the default implementation in the framework and
let architectures like x86 that have special primary thread to
override this function (which they've already done).

There's no need to provide a stub function if !CONFIG_SMP or
!CONFIG_HOTPLUG_SMT. In such case the testing CPU is already
the 1st CPU in the SMT so it's always the primary thread.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Reviewed-by: Pierre Gondois <pierre.gondois at arm.com>
Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
Pre questioned in v9 [1] whether this works on architectures not using
CONFIG_GENERIC_ARCH_TOPOLOGY, See [2] for demonstration hacking on LoongArch
VM and this also works. Architectures should use this on their own situation.
[1] https://lore.kernel.org/linux-arm-kernel/427bd639-33c3-47e4-9e83-68c428eb1a7d at arm.com/
[2] https://lore.kernel.org/linux-arm-kernel/a5690fee-3019-f26c-8bad-1d95e388e877 at huawei.com/

 arch/powerpc/include/asm/topology.h |  1 +
 arch/x86/include/asm/topology.h     |  2 +-
 include/linux/topology.h            | 24 ++++++++++++++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 16bacfe8c7a2..da15b5efe807 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -152,6 +152,7 @@ static inline bool topology_is_primary_thread(unsigned int cpu)
 {
 	return cpu == cpu_first_thread_sibling(cpu);
 }
+#define topology_is_primary_thread topology_is_primary_thread
 
 static inline bool topology_smt_thread_allowed(unsigned int cpu)
 {
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index ec134b719144..6c79ee7c0957 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -229,11 +229,11 @@ static inline bool topology_is_primary_thread(unsigned int cpu)
 {
 	return cpumask_test_cpu(cpu, cpu_primary_thread_mask);
 }
+#define topology_is_primary_thread topology_is_primary_thread
 
 #else /* CONFIG_SMP */
 static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
 static inline int topology_max_smt_threads(void) { return 1; }
-static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
 static inline unsigned int topology_amd_nodes_per_pkg(void) { return 1; }
 #endif /* !CONFIG_SMP */
 
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 52f5850730b3..6ae995e18ff5 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -240,6 +240,30 @@ static inline const struct cpumask *cpu_smt_mask(int cpu)
 }
 #endif
 
+#ifndef topology_is_primary_thread
+
+#define topology_is_primary_thread topology_is_primary_thread
+
+static inline bool topology_is_primary_thread(unsigned int cpu)
+{
+	/*
+	 * When disabling SMT the primary thread of the SMT will remain
+	 * enabled/active. Architectures do have a special primary thread
+	 * (e.g. x86) needs to override this function. Otherwise can make
+	 * the first thread in the SMT as the primary thread.
+	 *
+	 * The sibling cpumask of an offline CPU contains always the CPU
+	 * itself for architectures using the implementation of
+	 * CONFIG_GENERIC_ARCH_TOPOLOGY for building their topology.
+	 * Other architectures not using CONFIG_GENERIC_ARCH_TOPOLOGY for
+	 * building their topology have to check whether to use this default
+	 * implementation or to override it.
+	 */
+	return cpu == cpumask_first(topology_sibling_cpumask(cpu));
+}
+
+#endif
+
 static inline const struct cpumask *cpu_cpu_mask(int cpu)
 {
 	return cpumask_of_node(cpu_to_node(cpu));
-- 
2.24.0



From yangyicong at huawei.com  Tue Mar 11 00:51:39 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 15:51:39 +0800
Subject: [PATCH v12 0/4] Support SMT control on arm64
Message-ID: <20250311075143.61078-1-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

The core CPU control framework supports runtime SMT control which
is not yet supported on arm64. Besides the general vulnerabilities
concerns we want this runtime control on our arm64 server for:

- better single CPU performance in some cases
- saving overall power consumption

This patchset implements it in the following aspects:

- Provides a default topology_is_primary_thread()
- support retrieve SMT thread number on OF based system
- support retrieve SMT thread number on ACPI based system
- select HOTPLUG_SMT for arm64

Tests has been done on our ACPI based arm64 server and on ACPI/OF
based QEMU VMs.

Change since v11:
- Remove the check and warning for heterogeneous platform as suggested and discussed
- refine comments/commit according to Dietmar
Link: https://lore.kernel.org/linux-arm-kernel/20250218141018.18082-1-yangyicong at huawei.com/

Change since v10:
- handle topology parsing failure case on DT based system
- address some style comments per Jonathan and add tags, Thanks
Link: https://lore.kernel.org/linux-arm-kernel/20241220075313.51502-1-yangyicong at huawei.com/

Change since v9:
- Refine the comment of topology_is_primary_thread(). Tested with LoongArch
  to prove it also works on architecture's not using CONFIG_GENERIC_ARCH_TOPOLOGY
- always call cpu_smt_set_num_threads() to make the smt/control shows correct
  status on non-SMT system
Link: https://lore.kernel.org/linux-arm-kernel/20241114141127.23232-1-yangyicong at huawei.com/

Change since v8:
- Fix WARN on ACPI based non-SMT platform noticed in v7, per Pierre.
Link: https://lore.kernel.org/all/20241105093237.63565-1-yangyicong at huawei.com/

Change since v7:
Address the comments from Thomas:
- Add a newline between the glue define and function of topology_is_primary_thread
- Explicitly mention the sibling mask won't be empty in the comment
Link: https://lore.kernel.org/lkml/20241030125415.18994-1-yangyicong at huawei.com/

Change since v6:
- Fix unused variable if !CONFIG_ARM64 || !CONFIG_RISV found by lkp-test
- Fix max_smt_thread_num updating in OF path pointed by Pierre
- Drop unused variable and refine the comments/commit per Pierre
Link: https://lore.kernel.org/linux-arm-kernel/20241015021841.35713-1-yangyicong at huawei.com/

Change since v5:
- Drop the dependency on CONFIG_SMP since it's always on arm64, per Pierre
- Avoid potential multiple calls of cpu_smt_set_num_threads() on asymmetric system, per Dietmar
- Detect heterogeneous SMT topology and issue a warning for partly support, per Pierre
- Thanks Dietmar for testing, didn't pickup the tag due to code changes. Thanks testing by Pierre
Link: https://lore.kernel.org/linux-arm-kernel/20240806085320.63514-1-yangyicong at huawei.com/

Change since v4:
- Provide a default topology_is_primary_thread() in the framework, Per Will
Link: https://lore.kernel.org/linux-arm-kernel/20231121092602.47792-1-yangyicong at huawei.com/

Change since v3:
- Fix some build and kconfig error reported by kernel test robot <lkp at intel.com>
Link: https://lore.kernel.org/linux-arm-kernel/20231114040110.54590-1-yangyicong at huawei.com/

Change since v2:
- Detect SMT thread number at topology build from ACPI/DT, avoid looping CPUs
- Split patches into ACPI/OF/arch_topology path and enable the kconfig for arm64
Link: https://lore.kernel.org/linux-arm-kernel/20231010115335.13862-1-yangyicong at huawei.com/

Yicong Yang (4):
  cpu/SMT: Provide a default topology_is_primary_thread()
  arch_topology: Support SMT control for OF based system
  arm64: topology: Support SMT control on ACPI based system
  arm64: Kconfig: Enable HOTPLUG_SMT

 arch/arm64/Kconfig                  |  1 +
 arch/arm64/kernel/topology.c        | 54 +++++++++++++++++++++++++++++
 arch/powerpc/include/asm/topology.h |  1 +
 arch/x86/include/asm/topology.h     |  2 +-
 drivers/base/arch_topology.c        | 18 ++++++++++
 include/linux/topology.h            | 24 +++++++++++++
 6 files changed, 99 insertions(+), 1 deletion(-)

-- 
2.24.0



From krzk at kernel.org  Tue Mar 11 00:50:31 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 08:50:31 +0100
Subject: [PATCH v3 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f@imgtec.com>
Message-ID: <20250311-flashy-rattlesnake-of-rain-dcc4f6@krzk-bin>

On Mon, Mar 10, 2025 at 01:10:25PM +0000, Matt Coster wrote:
> The first compatible strings added for the AXE-1-16M are not sufficient to
> accurately describe all the IMG Rogue GPUs. The current "img,img-axe"
> string refers to the entire family of Series AXE GPUs, but this is
> primarily a marketing term and does not denote a level of hardware
> similarity any greater than just "Rogue".
> 
> The more specific "img,img-axe-1-16m" string refers to individual AXE-1-16M
> GPU. For example, unlike the rest of the Series AXE GPUs, the AXE-1-16M
> only uses a single power domain.
> 
> The situation is actually slightly worse than described in the first
> paragraph, since many "series" (such as Series BXS found in the TI AM68
> among others and added later in this series) contain cores with both Rogue
> and Volcanic architectures.
> 
> Besides attempting to move away from vague groupings defined only
> by marketing terms, we want to draw a line between properties inherent to
> the IP core and choices made by the silicon vendor at integration time.
> For instance, the number of power domains is a property of the IP core,
> whereas the decision to use one or multiple clocks is a vendor one.
> 
> In the original compatible strings, we must use "ti,am62-gpu" to constrain
> both of these properties since the number of power domains cannot be fixed
> for "img,img-axe".
> 
> Work is currently underway to add support for volcanic-based Imagination
> GPUs, for which bindings will be added in "img,powervr-volcanic.yaml".
> As alluded to previously, the split between rogue and volcanic cores is
> non-obvious at times, so add a generic top-level "img,img-rogue" compatible
> string here to allow for simpler differentiation in devicetrees without
> referring back to the bindings.
> 
> The currently supported GPU (AXE-1-16M) only requires a single power
> domain. Subsequent patches will add support for BXS-4-64 MC1, which has
> two power domains. Add infrastructure now to allow for this.
> 
> Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
> are DMA devices. The decision for coherency is made at integration time and
> this property should be applied wherever it accurately describes the
> vendor integration.
> 
> Note that the new required properties for power domains are conditional on
> the new base compatible string to avoid an ABI break.
> 
> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
> ---
> Changes in v3:
> - Remove unnecessary example
> - Remove second power domain details, add these where they're used instead
> - Avoid ABI breaks by limiting new required properties to new compatible
>   strings and making all binding changes in a single patch.
> - Links to v2:
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
> ---
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 43 ++++++++++++++++++----
>  1 file changed, 36 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> index 256e252f8087fa0d6081f771a01601d34b66fe19..5c16b2881447c9cda78e5bb46569e2f675d740c4 100644
> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> @@ -12,10 +12,20 @@ maintainers:
>  
>  properties:
>    compatible:
> -    items:
> -      - enum:
> -          - ti,am62-gpu
> -      - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
> +    oneOf:
> +      - items:
> +          - enum:
> +              - ti,am62-gpu
> +          - const: img,img-axe-1-16m
> +          - const: img,img-rogue

That's still ABI break. You got here NAK. You ust preserve img,img-axe.
Your marketing troubles do not concern Linux.

> +
> +      # This legacy combination of compatible strings was introduced early on
> +      # before the more specific GPU identifiers were used.
> +      - items:
> +          - enum:
> +              - ti,am62-gpu
> +          - const: img,img-axe
> +        deprecated: true
>  
>    reg:
>      maxItems: 1
> @@ -34,8 +44,13 @@ properties:
>    interrupts:
>      maxItems: 1
>  
> -  power-domains:
> -    maxItems: 1
> +  power-domains: true

No, widest constraints always stay here.

> +
> +  power-domain-names:
> +    items:
> +      - const: a

That's not a useful name. Are you sure that datasheet calls it power
domain A?

> +
> +  dma-coherent: true

Best regards,
Krzysztof



From boris.brezillon at collabora.com  Tue Mar 11 00:51:58 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 11 Mar 2025 08:51:58 +0100
Subject: [PATCH v1 3/6] drm/panfrost: Unify panfrost_mmu_enable/disable
 common code
In-Reply-To: <20250310195921.157511-4-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
	<20250310195921.157511-4-ariel.dalessandro@collabora.com>
Message-ID: <20250311085158.37329b0c@collabora.com>

On Mon, 10 Mar 2025 16:59:18 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> Both these functions write to MMU_AS_CONTROL register in the same way.
> Define a common _panfrost_mmu_as_control_write function with the shared
> code.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_mmu.c | 33 ++++++++++++-------------
>  1 file changed, 16 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 294f86b3c25e7..31df3a96f89bd 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -121,38 +121,37 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>  	return ret;
>  }
>  
> -static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
> +static void
> +_panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
> +			       u64 transtab, u64 memattr)

I'm honestly not convinced this is needed. Let's just stick to
panfrost_mmu_enable/disable().

>  {
> -	int as_nr = mmu->as;
> -	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> -	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> -	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
> -
>  	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>  
>  	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab));
>  	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab));
>  
> -	/* Need to revisit mem attrs.
> -	 * NC is the default, Mali driver is inner WT.
> -	 */
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>  
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>  }
>  
> -static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
> +static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
> -	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
> -
> -	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), 0);
> -	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), 0);
> +	int as_nr = mmu->as;
> +	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> +	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> +	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
>  
> -	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
> -	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
> +	/* Need to revisit mem attrs.
> +	 * NC is the default, Mali driver is inner WT.
> +	 */
> +	_panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
> +}
>  
> -	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
> +static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
> +{
> +	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
>  }
>  
>  u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)



From boris.brezillon at collabora.com  Tue Mar 11 01:05:45 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 11 Mar 2025 09:05:45 +0100
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250310195921.157511-5-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
	<20250310195921.157511-5-ariel.dalessandro@collabora.com>
Message-ID: <20250311090545.3b941567@collabora.com>

On Mon, 10 Mar 2025 16:59:19 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> Address Extension", which in Linux we've called "mali_lpae".
> 
> This commit adds support for conditionally enabling AARCH64_4K page
> table format. To achieve that, a "GPU optional configurations" field was
> added to `struct panfrost_features` with the related flag.
> 
> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> the HW_FEATURE_AARCH64_MMU feature flag present.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>  drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
>  drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>  3 files changed, 169 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> index cffcb0ac7c111..0385702aa43c7 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>  	GPU_PM_VREG_OFF,
>  };
>  
> +/**
> + * enum panfrost_gpu_config - GPU optional configurations
> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
> + */
> +enum panfrost_gpu_config {
> +	GPU_CONFIG_AARCH64_4K,
> +};
> +
>  struct panfrost_features {
>  	u16 id;
>  	u16 revision;
> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>  
>  	/* Allowed PM features */
>  	u8 pm_features;
> +
> +	/* GPU features */
> +	u8 gpu_configs;

I would probably name this gpu_quirks, with the GPU_CONFIG_AARCH64_4K
flag renamed GPU_QUIRK_FORCE_AARCH64_PAGE_TABLE.

>  };
>  
>  struct panfrost_device {
> @@ -162,6 +173,11 @@ struct panfrost_mmu {
>  	int as;
>  	atomic_t as_count;
>  	struct list_head list;
> +	struct {
> +		u64 transtab;
> +		u64 memattr;
> +		u64 transcfg;
> +	} cfg;
>  };
>  
>  struct panfrost_engine_usage {
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 31df3a96f89bd..4a9b8de2ff987 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -26,6 +26,48 @@
>  #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
>  #define mmu_read(dev, reg) readl(dev->iomem + reg)
>  
> +static u64 mair_to_memattr(u64 mair, bool coherent)
> +{
> +	u64 memattr = 0;
> +	u32 i;
> +
> +	for (i = 0; i < 8; i++) {
> +		u8 in_attr = mair >> (8 * i), out_attr;
> +		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
> +
> +		/* For caching to be enabled, inner and outer caching policy
> +		 * have to be both write-back, if one of them is write-through
> +		 * or non-cacheable, we just choose non-cacheable. Device
> +		 * memory is also translated to non-cacheable.
> +		 */
> +		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
> +				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
> +		} else {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
> +			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
> +			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
> +			 * to Mali's internal-shareable mode. As per the Mali
> +			 * Spec, inner and outer-shareable modes aren't allowed
> +			 * for WB memory when coherency is disabled.
> +			 * Use SH_CPU_INNER mode when coherency is enabled, so
> +			 * that SH_IS actually maps to the standard definition of
> +			 * inner-shareable.
> +			 */
> +			if (!coherent)
> +				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
> +			else
> +				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
> +		}
> +
> +		memattr |= (u64)out_attr << (8 * i);
> +	}
> +
> +	return memattr;
> +}
> +
>  static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
>  {
>  	int ret;
> @@ -121,9 +163,57 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>  	return ret;
>  }
>  
> +static void mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	/* TODO: The following fields are duplicated between the MMU and Page
> +	 * Table config structs. Ideally, should be kept in one place.
> +	 */
> +	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
> +	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
> +	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
> +}
> +
> +static void mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
> +				AS_TRANSTAB_AARCH64_4K_ADDR_MASK;

Silently masking the low 4bits is not the solution, it's just papering
over a real issue. If pgtbl_cfg->arm_lpae_s1_cfg.ttbr is not aligned on
16 bytes (PAGE_SIZE even) we have a problem, so I would drm_WARN_ON()
here, and return an error so we can fail the probe.

> +
> +	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
> +					   pgtbl_cfg->coherent_walk);
> +
> +	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
> +			    AS_TRANSCFG_PTW_RA |
> +			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
> +			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
> +	if (pgtbl_cfg->coherent_walk)
> +		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
> +}
> +
> +static void panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
> +				  enum io_pgtable_fmt fmt)
> +{
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	switch (fmt) {
> +	case ARM_64_LPAE_S1:
> +		mmu_cfg_init_aarch64_4k(mmu);
> +		break;
> +	case ARM_MALI_LPAE:
> +		mmu_cfg_init_mali_lpae(mmu);
> +		break;
> +	default:
> +		dev_WARN_ONCE(pfdev->dev, 1, "Unhandled page table format\n");
> +		break;
> +	}
> +}
> +
>  static void
>  _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
> -			       u64 transtab, u64 memattr)
> +			       u64 transtab, u64 memattr, u64 transcfg)
>  {
>  	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>  
> @@ -133,25 +223,28 @@ _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>  
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
> +
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
> +
> +	dev_dbg(pfdev->dev, "mmu_as_control: as=%d, transtab=0x%016llx, memattr=0x%016llx, transcfg=0x%016llx",
> +		as_nr, transtab, memattr, transcfg);
>  }
>  
>  static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
> -	int as_nr = mmu->as;
> -	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> -	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> -	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
> -
>  	/* Need to revisit mem attrs.
>  	 * NC is the default, Mali driver is inner WT.
>  	 */
> -	_panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
> +	_panfrost_mmu_as_control_write(pfdev, mmu->as, mmu->cfg.transtab,
> +				       mmu->cfg.memattr, mmu->cfg.transcfg);
>  }
>  
>  static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
>  {
> -	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
> +	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0,
> +				       AS_TRANSCFG_ADRMODE_UNMAPPED);
>  }
>  
>  u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
> @@ -616,6 +709,7 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  {
>  	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>  	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
> +	enum io_pgtable_fmt fmt = ARM_MALI_LPAE;
>  	struct panfrost_mmu *mmu;
>  
>  	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
> @@ -641,16 +735,28 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  		.iommu_dev	= pfdev->dev,
>  	};
>  
> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
> -					      mmu);
> -	if (!mmu->pgtbl_ops) {
> -		kfree(mmu);
> -		return ERR_PTR(-EINVAL);
> +	if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {
> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
> +			dev_err_once(pfdev->dev,
> +				     "AARCH64_4K page table not supported\n");
> +			goto err_free_mmu;
> +		}
> +		fmt = ARM_64_LPAE_S1;
>  	}

How about moving this check before allocating the mmu object, so you
don't have to free it if it fails?

>  
> +	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
> +	if (!mmu->pgtbl_ops)
> +		goto err_free_mmu;
> +
> +	panfrost_mmu_cfg_init(mmu, fmt);
> +
>  	kref_init(&mmu->refcount);
>  
>  	return mmu;
> +
> +err_free_mmu:
> +	kfree(mmu);
> +	return ERR_PTR(-EINVAL);
>  }
>  
>  static const char *access_type_name(struct panfrost_device *pfdev,
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index b5f279a19a084..2b8f1617b8369 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -301,6 +301,17 @@
>  #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
>  #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
>  #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
> +							 ((w) ? BIT(0) : 0) | \
> +							 ((r) ? BIT(1) : 0))
> +#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
> +#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
> +#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
>  #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
>  #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
>  #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
> @@ -311,6 +322,24 @@
>  /* Additional Bifrost AS registers */
>  #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
>  #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
> +#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
> +#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
> +#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
> +#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
> +#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
> +#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
> +#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
> +#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
> +#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
> +#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
> +#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
> +#define   AS_TRANSCFG_PTW_RA				BIT(30)
> +#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
> +#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
> +#define   AS_TRANSCFG_WXN				BIT(35)
> +#define   AS_TRANSCFG_XREADABLE				BIT(36)
>  #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
>  #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>  
> @@ -326,6 +355,11 @@
>  #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
>  #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
>  
> +/*
> + * Begin AARCH64_4K MMU TRANSTAB register values
> + */
> +#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
> +
>  #define AS_STATUS_AS_ACTIVE			0x01
>  
>  #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)



From yangyicong at huawei.com  Tue Mar 11 01:06:24 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 16:06:24 +0800
Subject: [PATCH 1/2] watchdog/perf: Provide function for adjusting the
 event period
In-Reply-To: <CAD=FV=WfB6inJPuwfhbw4mtFBYpr+3ot2J+SJAZ3pT3t4fW7cw@mail.gmail.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
 <20250307021811.46981-2-yangyicong@huawei.com>
 <CAD=FV=WfB6inJPuwfhbw4mtFBYpr+3ot2J+SJAZ3pT3t4fW7cw@mail.gmail.com>
Message-ID: <5eaf8f37-c7f6-b2d0-c87b-6c48dcc80e52@huawei.com>

On 2025/3/8 0:53, Doug Anderson wrote:
> Hi,
> 
> On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
>>
>> @@ -211,6 +211,27 @@ void hardlockup_detector_perf_cleanup(void)
>>         cpumask_clear(&dead_events_mask);
>>  }
>>
>> +/**
>> + * hardlockup_detector_perf_adjust_period - Adjust the events period due
>> + *                                          to cpu frequency change
>> + */
>> +void hardlockup_detector_perf_adjust_period(int cpu, u64 period)
> 
> Running `scripts/kernel-doc -v kernel/watchdog_perf.c > /dev/null`
> after your patch shows:
> 
> kernel/watchdog_perf.c:219: warning: Function parameter or struct
> member 'cpu' not described in 'hardlockup_detector_perf_adjust_period'
> kernel/watchdog_perf.c:219: warning: Function parameter or struct
> member 'period' not described in
> 'hardlockup_detector_perf_adjust_period'
> 

so the script will check whether parameters are documented as well,
need to add description.

I just followed the document convention like hardlockup_detector_perf_cleanup().

> 
> Other than that, this seems reasonable to me.
> 
> ...but I'd also have to ask: is there a reason you're using the "perf"
> hard-lockup detector instead of the buddy one? In my mind, the "buddy"
> watchdog is better in almost all ways (I believe it's lower power,
> doesn't waste a "perf" controller, and doesn't suffer from frequency
> issues).

ok, sounds reasonable to me especially for save one perf counter.

> It's even crossed my mind whether the "perf" lockup detector
> should be deprecated. ;-)
> .

I think it's mainly due to the policy of the distribution. watchdog_perf
is used by default on openEuler which is used on my board.

Thanks.



From hch at infradead.org  Tue Mar 11 01:06:59 2025
From: hch at infradead.org (Christoph Hellwig)
Date: Tue, 11 Mar 2025 01:06:59 -0700
Subject: [PATCH 1/2] nvme: move error logging from nvme_end_req() to
 __nvme_end_req()
In-Reply-To: <20250311024144.1762333-2-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
 <20250311024144.1762333-2-shinichiro.kawasaki@wdc.com>
Message-ID: <Z8_vIwT4AFAfbwwF@infradead.org>

Looks good:

Reviewed-by: Christoph Hellwig <hch at lst.de>



From boris.brezillon at collabora.com  Tue Mar 11 01:06:49 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 11 Mar 2025 09:06:49 +0100
Subject: [PATCH v1 5/6] drm/panfrost: Enable AARCH64_4K page table
 format on mediatek_mt8188
In-Reply-To: <20250310195921.157511-6-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
	<20250310195921.157511-6-ariel.dalessandro@collabora.com>
Message-ID: <20250311090649.0d15d74d@collabora.com>

On Mon, 10 Mar 2025 16:59:20 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> Now that Panfrost supports AARCH64_4K page table format, let's enable it
> on Mediatek MT8188.

Can you maybe give more details on why this is needed
(legacy shareability/cacheability not suitable for this GPU?)?

> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 0f3935556ac76..d7b8bded6d784 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
>  	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
>  	.pm_domain_names = mediatek_mt8183_pm_domains,
>  	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
> +	.gpu_configs = BIT(GPU_CONFIG_AARCH64_4K),
>  };
>  
>  static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };



From boris.brezillon at collabora.com  Tue Mar 11 01:08:55 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 11 Mar 2025 09:08:55 +0100
Subject: [PATCH v1 6/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature
 flag on Bifrost models
In-Reply-To: <20250310195921.157511-7-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
	<20250310195921.157511-7-ariel.dalessandro@collabora.com>
Message-ID: <20250311090855.0211c114@collabora.com>

On Mon, 10 Mar 2025 16:59:21 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> Set this feature flag on all Mali Bifrost platforms as the MMU supports
> AARCH64 4K page table format.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
> index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_features.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_features.h
> @@ -54,6 +54,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g72 (\
> @@ -64,6 +65,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g51 hw_features_g72
> @@ -77,6 +79,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
>  	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g76 (\



From hch at infradead.org  Tue Mar 11 01:13:01 2025
From: hch at infradead.org (Christoph Hellwig)
Date: Tue, 11 Mar 2025 01:13:01 -0700
Subject: [PATCH 2/2] block: change blk_mq_add_to_batch() third argument
 type to blk_status_t
In-Reply-To: <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
 <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
Message-ID: <Z8_wjZUNvM7JAWAQ@infradead.org>

On Tue, Mar 11, 2025 at 11:41:44AM +0900, Shin'ichiro Kawasaki wrote:
> However, blk_mq_add_to_batch() callers do not pass negative error
> values. Instead, they pass status codes defined in various ways:
> 
> - NVMe PCI and Apple drivers pass NVMe status code
> - virtio_blk driver passes the virtblk request header status byte
> - null_blk driver passes blk_status_t

The __force cast in null_blk should have been a big fat warning..

> To correct the ioerror check within blk_mq_add_to_batch(), make all
> callers to uniformly pass the argument as blk_status_t. Modify the
> callers to translate their specific status codes into blk_status_t. For
> this translation, export the helper function nvme_error_status(). Adjust
> blk_mq_add_to_batch() to translate blk_status_t back into the error
> number for the appropriate check.

This still looks a bit ugly because of all the conversions to a
blk_status_t just to convert it back to a errno just to check for
a non-zero value (blk_status_to_errno can't return a positive value).

I suspect simply passing a "bool is_error" might actually be cleaner
than that, combined with a proper kerneldoc comment for
blk_mq_add_to_batch explaining how to set it?



From oliver.upton at linux.dev  Tue Mar 11 01:05:06 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Tue, 11 Mar 2025 01:05:06 -0700
Subject: [PATCH v1 3/5] arm64/kvm: using ioctl to enable/disable the
 HDBSS feature
In-Reply-To: <20250311040321.1460-4-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
 <20250311040321.1460-4-yezhenyu2@huawei.com>
Message-ID: <Z8_usklidqnerurc@linux.dev>

On Tue, Mar 11, 2025 at 12:03:19PM +0800, Zhenyu Ye wrote:
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index d919557af5e5..bd73ee92b12c 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -787,6 +787,12 @@ struct kvm_vcpu_arch {
>  
>  	/* Per-vcpu CCSIDR override or NULL */
>  	u32 *ccsidr;
> +
> +	/* HDBSS registers info */
> +	struct {
> +		u64 br_el2;
> +		u64 prod_el2;
> +	} hdbss;

I'm not a fan of storing the raw system register values in the vCPU
struct. I'd rather we kept track of the buffer base address, size, and
index as three separate fields.

>  };
>  
>  /*
> diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
> index b98ac6aa631f..ed5b68c2085e 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -330,6 +330,18 @@ static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu,
>  	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
>  }
>  
> +static __always_inline void __load_hdbss(struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu->kvm->enable_hdbss)
> +		return;
> +
> +	write_sysreg_s(vcpu->arch.hdbss.br_el2, SYS_HDBSSBR_EL2);
> +	write_sysreg_s(vcpu->arch.hdbss.prod_el2, SYS_HDBSSPROD_EL2);
> +
> +	dsb(sy);
> +	isb();

What are you synchronizing against here? dsb(sy) is a *huge* hammer. A
dsb() in this context would only make sense if there were pending stores
to the dirty tracking structure, which ought not be the case at load.

Also keep in mind the EL1&0 regime is out of context...

> +}
> +
>  static inline struct kvm *kvm_s2_mmu_to_kvm(struct kvm_s2_mmu *mmu)
>  {
>  	return container_of(mmu->arch, struct kvm, arch);
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index b727772c06fb..3040eac74f8c 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -1105,6 +1105,18 @@
>  #define GCS_CAP(x)	((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
>  					       GCS_CAP_VALID_TOKEN)
>  
> +/*
> + * Definitions for the HDBSS feature
> + */
> +#define HDBSS_MAX_SIZE		HDBSSBR_EL2_SZ_2MB
> +
> +#define HDBSSBR_EL2(baddr, sz)	(((baddr) & GENMASK(55, 12 + sz)) | \
> +				 ((sz) << HDBSSBR_EL2_SZ_SHIFT))
> +#define HDBSSBR_BADDR(br)	((br) & GENMASK(55, (12 + HDBSSBR_SZ(br))))
> +#define HDBSSBR_SZ(br)		(((br) & HDBSSBR_EL2_SZ_MASK) >> HDBSSBR_EL2_SZ_SHIFT)
> +
> +#define HDBSSPROD_IDX(prod)	(((prod) & HDBSSPROD_EL2_INDEX_MASK) >> HDBSSPROD_EL2_INDEX_SHIFT)
> +
>  #define ARM64_FEATURE_FIELD_BITS	4
>  
>  /* Defined for compatibility only, do not add new users. */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 0160b4924351..825cfef3b1c2 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -80,6 +80,70 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>  	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
>  }
>  
> +static int kvm_cap_arm_enable_hdbss(struct kvm *kvm,
> +				    struct kvm_enable_cap *cap)
> +{
> +	unsigned long i;
> +	struct kvm_vcpu *vcpu;
> +	struct page *hdbss_pg;
> +	int size = cap->args[0];
> +
> +	if (!system_supports_hdbss()) {
> +		kvm_err("This system does not support HDBSS!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (size < 0 || size > HDBSS_MAX_SIZE) {
> +		kvm_err("Invalid HDBSS buffer size: %d!\n", size);
> +		return -EINVAL;
> +	}
> +
> +	/* Enable the HDBSS feature if size > 0, otherwise disable it. */
> +	if (size) {
> +		kvm->enable_hdbss = true;
> +		kvm->arch.mmu.vtcr |= VTCR_EL2_HD | VTCR_EL2_HDBSS;

Nothing prevents a vCPU from using a VTCR value with HDBSS enabled
before a tracking structure has been allocated.

> +		kvm_for_each_vcpu(i, vcpu, kvm) {
> +			hdbss_pg = alloc_pages(GFP_KERNEL, size);

GFP_KERNEL_ACCOUNT

> +			if (!hdbss_pg) {
> +				kvm_err("Alloc HDBSS buffer failed!\n");
> +				return -EINVAL;
> +			}

enable_hdbss and vtcr aren't cleaned up in this case, and EINVAL is an
inappopriate return for a failed memory allocation.

> +			vcpu->arch.hdbss.br_el2 = HDBSSBR_EL2(page_to_phys(hdbss_pg), size);
> +			vcpu->arch.hdbss.prod_el2 = 0;
> +
> +			/*
> +			 * We should kick vcpus out of guest mode here to
> +			 * load new vtcr value to vtcr_el2 register when
> +			 * re-enter guest mode.
> +			 */
> +			kvm_vcpu_kick(vcpu);

VTCR_EL2 is configured on vcpu_load() for VHE. How is this expected to
work?

> +		}
> +
> +		kvm_info("Enable HDBSS success, HDBSS buffer size: %d\n", size);

Drop the debugging printks.

> +	} else if (kvm->enable_hdbss) {
> +		kvm->arch.mmu.vtcr &= ~(VTCR_EL2_HD | VTCR_EL2_HDBSS);
> +
> +		kvm_for_each_vcpu(i, vcpu, kvm) {
> +			/* Kick vcpus to flush hdbss buffer. */
> +			kvm_vcpu_kick(vcpu);
> +
> +			hdbss_pg = phys_to_page(HDBSSBR_BADDR(vcpu->arch.hdbss.br_el2));
> +			if (hdbss_pg)
> +				__free_pages(hdbss_pg, HDBSSBR_SZ(vcpu->arch.hdbss.br_el2));
> +
> +			vcpu->arch.hdbss.br_el2 = 0;
> +			vcpu->arch.hdbss.prod_el2 = 0;
> +		}
> +
> +		kvm->enable_hdbss = false;
> +		kvm_info("Disable HDBSS success\n");
> +	}
> +
> +	return 0;
> +}
> +
>  int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  			    struct kvm_enable_cap *cap)
>  {
> @@ -125,6 +189,9 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  		}
>  		mutex_unlock(&kvm->slots_lock);
>  		break;
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		r = kvm_cap_arm_enable_hdbss(kvm, cap);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -393,6 +460,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	case KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES:
>  		r = BIT(0);
>  		break;
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		r = system_supports_hdbss();
> +		break;

I'm not sure this is creating the right abstraction for userspace. At
least for the dirty bitmap, this is exposing an implementation detail to
the VMM.

You could, perhaps, associate the dirty tracking structure with a
similar concept (e.g. vCPU dirty rings) available to userspace.

>  	default:
>  		r = 0;
>  	}
> diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
> index 647737d6e8d0..6b633a219e4d 100644
> --- a/arch/arm64/kvm/hyp/vhe/switch.c
> +++ b/arch/arm64/kvm/hyp/vhe/switch.c
> @@ -256,6 +256,7 @@ void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
>  	__vcpu_load_switch_sysregs(vcpu);
>  	__vcpu_load_activate_traps(vcpu);
>  	__load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
> +	__load_hdbss(vcpu);
>  }
>  
>  void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 1f55b0c7b11d..9c11e2292b1e 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1703,6 +1703,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  	if (writable)
>  		prot |= KVM_PGTABLE_PROT_W;
>  
> +	if (kvm->enable_hdbss && logging_active)
> +		prot |= KVM_PGTABLE_PROT_DBM;
> +

We should set DBM if the mapping is PTE sized. That way you can
potentially avoid faults for pages that precede the dirty tracking
enable.

Thanks,
Oliver


From krzk at kernel.org  Tue Mar 11 01:16:57 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 09:16:57 +0100
Subject: [PATCH v6 2/4] dt-bindings: clock: axg-audio: document A1 SoC
 audio clock controller driver
In-Reply-To: <20250309180940.1322531-3-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-1-jan.dakinevich@salutedevices.com>
 <20250309180940.1322531-3-jan.dakinevich@salutedevices.com>
Message-ID: <20250311-famous-adamant-teal-20b1cb@krzk-bin>

On Sun, Mar 09, 2025 at 09:09:38PM +0300, Jan Dakinevich wrote:
> Add device tree bindings for A1 SoC audio clock and reset controllers.

You sent multiple copies of similar series to which you got responses. I
don't know anymore which should be ignored, which got my response, so
just in case I will skip this one. Please implement received feedback
(here or in some other series).

Best regards,
Krzysztof



From ceggers at arri.de  Tue Mar 11 01:18:48 2025
From: ceggers at arri.de (Christian Eggers)
Date: Tue, 11 Mar 2025 09:18:48 +0100
Subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker script
In-Reply-To: <20250310203729.GA26968@ax162>
References: <20250224125414.2184-1-ceggers@arri.de> <202503050230.820w99b6-lkp@intel.com>
 <20250310203729.GA26968@ax162>
Message-ID: <2110116.YKUYFuaPT4@n9w6sw14>

[Resending, as first message got HTML'ed by my mailer...]

Hi Nathan,


thanks for pushing this into the right direction.  Actually I didn't recognize that
lld complains about overlapping virtual address ranges, maybe the .config provided
by the first LKP report (which I used for testing) didn't enable the necessary options.


On Monday, 10 March 2025, 21:37:29 CET, Nathan Chancellor wrote:
> On Wed, Mar 05, 2025 at 02:49:38AM +0800, kernel test robot wrote:
> > Hi Christian,
> > 
> > kernel test robot noticed the following build errors:
> > 
> > [auto build test ERROR on soc/for-next]
> > [also build test ERROR on linus/master v6.14-rc5 next-20250304]
> > [If your patch is applied to the wrong git tree, kindly drop us a note.
> > And when submitting patch, we suggest to use '--base' as documented in
> > https://git-scm.com/docs/git-format-patch#_base_tree_information]
> > 
> > url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Eggers/ARM-avoid-that-vectors-are-removed-during-linker-garbage-collection/20250224-210146
> > base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
> > patch link:    https://lore.kernel.org/r/20250224125414.2184-1-ceggers%40arri.de
> > patch subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker script
> > config: arm-milbeaut_m10v_defconfig (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/config)
> > compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
> > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/reproduce)
> > 
> > If you fix the issue in a separate patch/commit (i.e. not just a new version of
> > the same patch/commit), kindly add following tags
> > | Reported-by: kernel test robot <lkp at intel.com>
> > | Closes: https://lore.kernel.org/oe-kbuild-all/202503050230.820w99b6-lkp at intel.com/
> > 
> > All errors (new ones prefixed by >>):
> > 
> > >> ld.lld: error: section .vectors.bhb.bpiall virtual address range overlaps with .vectors.bhb.loop8
> >    >>> .vectors.bhb.bpiall range is [0xFFFF0000, 0xFFFF001F]
> >    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
> > --
> > >> ld.lld: error: section .vectors.bhb.loop8 virtual address range overlaps with .vectors
> >    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
> >    >>> .vectors range is [0xFFFF0000, 0xFFFF001F]
> 
> Looking at ld.lld's code, this error is intentionally ignored for
> OVERLAY:
> 
> https://github.com/llvm/llvm-project/blob/9f170e6abed4a7b393bb8abbf07ac8d6930aa3b0/lld/ELF/Writer.cpp#L2751-L2761
> 
> I have submitted a patch that allows KEEP within OVERLAY to match GNU
> ld:
> 
> https://github.com/llvm/llvm-project/pull/130661
> 
> Once/if that is accepted, we should go back to your v1 with something
> like the following diff on top to keep things working for all linkers. I
> hope that it won't take long for the ld.lld change to get reviewed and
> landed but if this needs to be fixed urgently, this whole diff minus
> '|| LLD_VERSION >= 210000' on the init/Kconfig change should work (with
> a comment change). I can always send a follow up change to add it back.


I build from an internal tree, so I am not in hurry.  As the Kconfig changes
probably should take your Signed-Off-By, I am also fine if you do the necessary
changes on my v1 and resubmit it together with your patch when it is time.


> 
> Cheers,
> Nathan
> 


regards,
Christian


> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 835b5f100e92..f3f6b7a33b79 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -121,7 +121,7 @@ config ARM
>      select HAVE_KERNEL_XZ
>      select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
>      select HAVE_KRETPROBES if HAVE_KPROBES
> -    select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD)
> +    select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_CAN_USE_KEEP_IN_OVERLAY)
>      select HAVE_MOD_ARCH_SPECIFIC
>      select HAVE_NMI
>      select HAVE_OPTPROBES if !THUMB2_KERNEL
> diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h
> index f2ff79f740ab..14811b4f48ec 100644
> --- a/arch/arm/include/asm/vmlinux.lds.h
> +++ b/arch/arm/include/asm/vmlinux.lds.h
> @@ -34,6 +34,12 @@
>  #define NOCROSSREFS
>  #endif
>  
> +#ifdef CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY
> +#define OVERLAY_KEEP(x)        KEEP(x)
> +#else
> +#define OVERLAY_KEEP(x)        x
> +#endif
> +
>  /* Set start/end symbol names to the LMA for the section */
>  #define ARM_LMA(sym, section)                        \
>      sym##_start = LOADADDR(section);                \
> @@ -125,13 +131,13 @@
>      __vectors_lma = .;                        \
>      OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {        \
>          .vectors {                        \
> -            KEEP(*(.vectors))                \
> +            OVERLAY_KEEP(*(.vectors))            \
>          }                            \
>          .vectors.bhb.loop8 {                    \
> -            KEEP(*(.vectors.bhb.loop8))            \
> +            OVERLAY_KEEP(*(.vectors.bhb.loop8))        \
>          }                            \
>          .vectors.bhb.bpiall {                    \
> -            KEEP(*(.vectors.bhb.bpiall))            \
> +            OVERLAY_KEEP(*(.vectors.bhb.bpiall))        \
>          }                            \
>      }                                \
>      ARM_LMA(__vectors, .vectors);                    \
> diff --git a/init/Kconfig b/init/Kconfig
> index d0d021b3fa3b..fc994f5cd5db 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -129,6 +129,11 @@ config CC_HAS_COUNTED_BY
>      # https://github.com/llvm/llvm-project/pull/112636
>      depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
>  
> +config LD_CAN_USE_KEEP_IN_OVERLAY
> +    # ld.lld prior to 21.0.0 did not support KEEP within an overlay description
> +    # https://github.com/llvm/llvm-project/pull/130661
> +    def_bool LD_IS_BFD || LLD_VERSION >= 210000
> +
>  config RUSTC_HAS_COERCE_POINTEE
>      def_bool RUSTC_VERSION >= 108400
>  
> 







From ericwouds at gmail.com  Tue Mar 11 01:22:35 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Tue, 11 Mar 2025 09:22:35 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <20250305102949.16370-1-ericwouds@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
Message-ID: <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com>



On 3/5/25 11:29 AM, Eric Woudstra wrote:
> This patchset makes it possible to set up a software fastpath between
> bridged interfaces. One patch adds the flow rule for the hardware
> fastpath. This creates the possibility to have a hardware offloaded
> fastpath between bridged interfaces. More patches are added to solve
> issues found with the existing code.


> Changes in v9:
> - No changes, resend to netfilter

Hi Pablo,

I've changed tag [net-next] to [nf], hopefully you can have a look at
this patch-set. But, after some days, I was in doubt if this way I have
brought it to your attention. Perhaps I need to do something different
to ask the netfilter maintainer have a look at it?

Best regards,

Eric



From goran.radni at gmail.com  Tue Mar 11 01:30:20 2025
From: goran.radni at gmail.com (Goran Radenovic)
Date: Tue, 11 Mar 2025 09:30:20 +0100
Subject: [PATCH 4/4] ARM: dts: stm32: add initial support for
 stm32mp157-ultra-fly-sbc board
In-Reply-To: <6af3a9fe-0c0b-497d-b143-77edc12f0c1e@kernel.org>
References: <20250310154804.326943-1-goran.radni@gmail.com>
 <20250310154804.326943-5-goran.radni@gmail.com>
 <6af3a9fe-0c0b-497d-b143-77edc12f0c1e@kernel.org>
Message-ID: <23c708ef-c52d-40c1-a9e8-b05555b21667@gmail.com>

Thank You for the feedback. I will fix this. I have to solve the problem 
with my e-mails in MAINTAINERS first, because I cannot use them to send 
e-mails "inline".

Best regards
Goran


On 10.03.25 17:08, Krzysztof Kozlowski wrote:
> On 10/03/2025 16:48, Goran Ra?enovi? wrote:
>> +&gpioj {
>> +	gpio-line-names =
>> +	"", "", "", "", "", "", "", "",
>> +	"", "", "", "", "", "", "", "";
>> +};
>> +
>> +&gpiok {
>> +	gpio-line-names =
>> +	"", "", "", "", "", "", "", "",
>> +	"", "", "", "", "", "", "", "";
>> +};
>> +
>> +&gpioz {
>> +	gpio-line-names =
>> +	"", "", "", "#SPI_CS2", "", "", "", "",
>> +	"", "", "", "", "", "", "", "";
>> +};
>> +
>> +&gpu {
>> +	status = "okay";
>> +};
>> +
>> +&i2c1 {
>> +	pinctrl-names = "default", "sleep";
>> +	pinctrl-0 = <&i2c1_ux_pins_a>;
>> +	pinctrl-1 = <&i2c1_ux_pins_sleep_a>;
>> +	i2c-scl-rising-time-ns = <100>;
>> +	i2c-scl-falling-time-ns = <7>;
>> +	status = "okay";
>> +	/delete-property/dmas;
>> +	/delete-property/dma-names;
>> +
>> +	rtc at 32 {
>> +		compatible = "epson,rx8900";
>> +		reg = <0x32>;
>> +		epson,vdet-disable;
>> +		trickle-diode-disable;
>> +	};
>> +};
>> +
>> +&i2c4 {
>> +	pinctrl-names = "default", "sleep";
>> +	pinctrl-0 = <&i2c4_ux_pins_a>;
>> +	pinctrl-1 = <&i2c4_ux_pins_sleep_a>;
>> +	i2c-scl-rising-time-ns = <185>;
>> +	i2c-scl-falling-time-ns = <20>;
>> +	status = "okay";
>> +	/delete-property/dmas;
>> +	/delete-property/dma-names;
>> +
>> +	pmic: stpmic at 33 {
> Node names should be generic. See also an explanation and list of
> examples (not exhaustive) in DT specification:
> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
>
> pmic?
>
>> +		compatible = "st,stpmic1";
>> +		reg = <0x33>;
>> +		interrupts-extended = <&exti 0 IRQ_TYPE_EDGE_FALLING>;
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		status = "okay";
> Does not look disabled
>
>
> ...
>
>
>> +	dac_ux_ch2_pins_a: dac_ux-ch2-0 {
> No underscores in node names.
>
>> +		pins {
>> +			pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
>> +		};
>> +	};
>> +
>
>
>
> Best regards,
> Krzysztof


From kory.maincent at bootlin.com  Tue Mar 11 01:30:27 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Tue, 11 Mar 2025 09:30:27 +0100
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for
 return value in intel_tsn_lane_is_available()
In-Reply-To: <3bc2cc11-3a87-479e-a0e0-c593e3214540@linux.intel.com>
References: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
	<20250310152014.1d593255@kmaincent-XPS-13-7390>
	<3bc2cc11-3a87-479e-a0e0-c593e3214540@linux.intel.com>
Message-ID: <20250311093027.4546e766@kmaincent-XPS-13-7390>

On Tue, 11 Mar 2025 13:33:42 +0800
Choong Yong Liang <yong.liang.choong at linux.intel.com> wrote:

> On 10/3/2025 10:20 pm, Kory Maincent wrote:
> > On Mon, 10 Mar 2025 13:08:35 +0800
> > Choong Yong Liang <yong.liang.choong at linux.intel.com> wrote:
> >   
> >> Fix the warning "warn: missing error code? 'ret'" in the
> >> intel_tsn_lane_is_available() function.
> >>
> >> The function now returns 0 to indicate that a TSN lane was found and
> >> returns -EINVAL when it is not found.
> >>
> >> Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the
> >> interface mode")
> >> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>  
> > 
> > This patch is a fix it should go net instead net-next.
> > Could you resend the patch with net prefix?
> > 
> > Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>
> > 
> > Thank you!  
> 
> Hi Kory,
> 
> Thank you for your feedback. I understand that the patch is a fix. However, 
> since the code is not yet in the 'net' tree, we are unable to apply the fix 
> there.
> 
> I'm not sure if there is another way to handle this fix other than sending 
> it to the 'net-next' tree. I would appreciate any guidance you might have 
> on this matter.

Oh, my bad! In that case you are right to send it to net-next. Sorry for the
noise.

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From yangyicong at huawei.com  Tue Mar 11 01:32:53 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Tue, 11 Mar 2025 16:32:53 +0800
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
 <20250307021811.46981-3-yangyicong@huawei.com>
 <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>
Message-ID: <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com>

On 2025/3/8 0:53, Doug Anderson wrote:
> Hi,
> 
> On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
>>
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> arm64 depends on the cpufreq driver to gain the maximum cpu frequency
>> to convert the watchdog_thresh to perf event period. cpufreq drivers
>> like cppc_cpufreq will be initialized lately after the initializing of
>> the hard lockup detector so just use a safe cpufreq which will be
>> inaccurency. Use a cpufreq notifier to adjust the event's period to
>> a more accurate one.
>>
>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>> ---
>>  arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
>>  1 file changed, 34 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
>> index dcd25322127c..719ae39e8bc0 100644
>> --- a/arch/arm64/kernel/watchdog_hld.c
>> +++ b/arch/arm64/kernel/watchdog_hld.c
>> @@ -34,3 +34,37 @@ bool __init arch_perf_nmi_is_available(void)
>>          */
>>         return arm_pmu_irq_is_nmi();
>>  }
>> +
>> +static int watchdog_freq_notifier_callback(struct notifier_block *nb,
>> +                                          unsigned long val, void *data)
>> +{
>> +       struct cpufreq_policy *policy = data;
>> +       unsigned long max_cpu_freq;
> 
> Feels like max_cpu_freq should be a u64. It probably should have been
> u64 in hw_nmi_get_sample_period() as well. Otherwise you could end up
> with a problem if the max CPU frequency is above ~4.3GHz and "unsigned
> long" is 32-bits (I think it technically could be?)
> 

I guess this won't happen for arm64 and we're in kernel space. here I
keep the same type with hw_nmi_get_sample_period() which is also using
"unsigned long".

> 
>> +       u64 new_period;
>> +       int cpu;
>> +
>> +       if (val != CPUFREQ_CREATE_POLICY)
>> +               return 0;
> 
> nit: maybe better documenting to return "NOTIFY_DONE" instead of 0?
> 

will use NOTIFY_NONE.

> 
>> +       for_each_cpu(cpu, policy->cpus) {
>> +               max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
>> +               if (!max_cpu_freq)
>> +                       continue;
>> +
>> +               new_period = watchdog_thresh * max_cpu_freq;
>> +               hardlockup_detector_perf_adjust_period(cpu, new_period);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static struct notifier_block watchdog_freq_notifier = {
>> +       .notifier_call = watchdog_freq_notifier_callback,
>> +};
>> +
>> +static int __init init_watchdog_freq_notifier(void)
>> +{
>> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
>> +                                        CPUFREQ_POLICY_NOTIFIER);
>> +}
>> +core_initcall(init_watchdog_freq_notifier);
> 
> I haven't dug into everything, but don't you have a potential blind
> spot, though? What if the order is this:
> 
> 1. hw_nmi_get_sample_period() is called
> 2. cpufreq driver probes
> 3. init_watchdog_freq_notifier() initcall runs
> 
> Since the cpufreq driver proved before you registered for the
> notifier, won't you miss the creation of the policy? Maybe instead of
> registering for an initcall you should somehow trigger off the first
> call to hw_nmi_get_sample_period() and register at that point in time?
> 

for arm64 the watchdog_perf is registered after armv8 PMU driver's init,
so the sequence is like:

# core_initcall
init_watchdog_freq_notifier()
# device_initcall
armv8_pmu_driver_init()
  lockup_detector_retry_init()
    schedule_work(&detector_work);
# in detector work
hw_nmi_get_sample_period() // notifier's already been registered

so we'll always get the correct frequency, either by the cpufreq
already registered or by the notifier which will update the
frequency. Please correct me if I missed anything :)

Thanks.




From peng.fan at nxp.com  Tue Mar 11 01:36:13 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Tue, 11 Mar 2025 08:36:13 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z87sGF_jHKau_FMe@bogus>
References: <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto> <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus> <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus> <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus> <Z87sGF_jHKau_FMe@bogus>
Message-ID: <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> fwnode for scmi cpufreq
> 
> On Mon, Mar 10, 2025 at 11:59:33AM +0000, Sudeep Holla wrote:
> > On Mon, Mar 10, 2025 at 10:45:44AM +0000, Peng Fan wrote:
> > > > Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> > > > fwnode for scmi cpufreq
> > > >
> > > > On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
> > > > >
> > > > > Sorry, if I misunderstood.
> > > > >
> > > > > I will give a look on this and propose a RFC.
> > > > >
> > > > > DT maintainers may ask for a patchset including binding change
> > > > > and driver changes to get a whole view on the compatible stuff.
> > > > >
> > > > > BTW, Cristian, Saravana if you have any objections/ideas or
> > > > > would
> > > > take
> > > > > on this effort, please let me know.
> > > > >
> > > >
> > > > Can you point me to the DTS with which you are seeing this issue ?
> > > > I am trying to reproduce the issue but so far not successful. I
> > > > did move to power-domains for CPUFreq on Juno. IIUC all we
> need is
> > > > both cpufreq and performance genpd drivers in the kernel and
> then
> > > > GPU using perf genpd fails with probe deferral right ? I need
> > > > pointers to reproduce the issue so that I can check if what I have
> > > > cooked up as a solution really works.
> > >
> > > This is in downstream tree:
> > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> gi
> > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> 6.6.y%2Farch%2Farm64%2Fbo
> > >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L2971&data=05%7C02%7Cpe
> ng.fan%40
> > >
> nxp.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2
> b4c6fa92cd99
> > >
> c5c301635%7C0%7C0%7C638772109152491267%7CUnknown%7CT
> WFpbGZsb3d8eyJFb
> > >
> XB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOI
> joiTWFpb
> > >
> CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=nHFiE5qD7NpmdGmj
> SUL0mIdOq8P4W
> > > ErqVq8xE%2Fb3WM0%3D&reserved=0
> > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> gi
> > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> 6.6.y%2Farch%2Farm64%2Fbo
> > >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L3043&data=05%7C02%7Cpe
> ng.fan%40
> > >
> nxp.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2
> b4c6fa92cd99
> > >
> c5c301635%7C0%7C0%7C638772109152521215%7CUnknown%7CT
> WFpbGZsb3d8eyJFb
> > >
> XB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOI
> joiTWFpb
> > >
> CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=M4LJumL6y9bQ%2FL
> ocPvlNiMnCFtO
> > > vODYNrC0DGbbydxY%3D&reserved=0
> > >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> gi
> > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> 6.6.y%2Farch%2Farm64%2Fbo
> > >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L80&data=05%7C02%7Cpeng
> .fan%40nx
> > >
> p.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2b4
> c6fa92cd99c5
> > >
> c301635%7C0%7C0%7C638772109152541725%7CUnknown%7CTWF
> pbGZsb3d8eyJFbXB
> > >
> 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoi
> TWFpbCI
> > >
> sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=VpxcGrB6Dnr9yCO%2F
> wl8sEw1LYSlX5
> > > nPHqnlJ5mKm%2B7A%3D&reserved=0
> > >
> > > we are using "power-domains" property for cpu perf and gpu/vpu
> perf.
> > >
> > > If cpufreq.off=1 is set in bootargs, the vpu/gpu driver will defer
> probe.
> > >
> >
> > OK, does the probe of these drivers get called or they don't as the
> > driver core doesn't allow that ? I just have a dummy driver for mali
> > on Juno which just does dev_pm_domain_attach_list() in the probe
> and
> > it seem to succeed even when cpufreq.off=1 is passed. I see
> > scmi-cpufreq failing with -ENODEV as expected.
> >
> > I need to follow the code and check if I can somehow reproduce. Also
> > are you sure this is not with anything in the downstream code ? Also
> > have you tried this with v6.14-rc* ? Are you sure all the fw_devlink
> > code is backported in the tree you pointed me which is v6.6-stable ?
> >
> 
> I even tried the above branch, but no luck. The above is neither latest
> stable version nor pure stable. It has few extra patches backported
> though IIUC. Anyways any pointers to enable me to reproduce the
> issue would be much appreciated.

I will setup test based latest linux-next and share results. Please wait.

Thanks,
Peng.
> 
> --
> Regards,
> Sudeep


From maddy at linux.ibm.com  Tue Mar 11 01:41:29 2025
From: maddy at linux.ibm.com (Madhavan Srinivasan)
Date: Tue, 11 Mar 2025 14:11:29 +0530
Subject: [PATCH] selftest/powerpc/mm/pkey: fix build-break introduced by commit 00894c3fc917
Message-ID: <20250311084129.39308-1-maddy@linux.ibm.com>

Build break was reported in the powerpc mailing list for next-20250218 with below errors

make[1]: Nothing to be done for 'all'.
BUILD_TARGET=/root/venkat/linux-next/tools/testing/selftests/powerpc/mm; mkdir -p $BUILD_TARGET; make OUTPUT=$BUILD_TARGET -k -C mm all
  CC       pkey_exec_prot
In file included from pkey_exec_prot.c:18:
/root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h: In function ?pkeys_unsupported?:
/root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h:96:34: error: ?PKEY_UNRESTRICTED? undeclared (first use in this function)
   96 |         pkey = sys_pkey_alloc(0, PKEY_UNRESTRICTED);
      |                                  ^~~~~~~~~~~~~~~~~

https://lore.kernel.org/all/20250113170619.484698-2-yury.khrustalev at arm.com/ patchset
has been queued to arm64/for-next/pkey_unrestricted which is causing a build break
in the selftest/powerpc builds.

Commit 6d61527d931ba ("mm/pkey: Add PKEY_UNRESTRICTED macro") added a macro
PKEY_UNRESTRICTED to handle implicit literal value of 0x0 (which is "unrestricted").
Add the same to selftest/powerpc/pkeys.h to fix the reported build break.

Reported-by: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
Closes: https://lore.kernel.org/lkml/3267ea6e-5a1a-4752-96ef-8351c912d386 at linux.ibm.com/T/
Tested-by: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy at linux.ibm.com>
---
Catalin, can you take this fix via arm64/for-next/pkey_unrestricted?
Patch applies clean on top of arm64/for-next/pkey_unrestricted

 tools/testing/selftests/powerpc/include/pkeys.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/testing/selftests/powerpc/include/pkeys.h b/tools/testing/selftests/powerpc/include/pkeys.h
index c6d4063dd4f6..d6deb6ffa1b9 100644
--- a/tools/testing/selftests/powerpc/include/pkeys.h
+++ b/tools/testing/selftests/powerpc/include/pkeys.h
@@ -24,6 +24,9 @@
 #undef PKEY_DISABLE_EXECUTE
 #define PKEY_DISABLE_EXECUTE	0x4
 
+#undef PKEY_UNRESTRICTED
+#define PKEY_UNRESTRICTED	0x0
+
 /* Older versions of libc do not define this */
 #ifndef SEGV_PKUERR
 #define SEGV_PKUERR	4
-- 
2.48.1



From anshuman.khandual at arm.com  Tue Mar 11 01:42:06 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 11 Mar 2025 14:12:06 +0530
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early
 mappings
In-Reply-To: <20250311073043.96795-2-ardb+git@google.com>
References: <20250311073043.96795-2-ardb+git@google.com>
Message-ID: <901b44cc-7498-4036-ac97-85b30de92c81@arm.com>



On 3/11/25 13:00, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb at kernel.org>
> 
> The page table population code in map_range() uses a recursive algorithm
> to create the early mappings of the kernel, the DTB and the ID mapped
> text and data pages, and this fails to take into account that the way
> these page tables may be constructed is not precisely the same at each
> level. In particular, block mappings are not permitted at each level,
> and the code as it exists today might inadvertently create such a
> forbidden block mapping if it were used to map a region of the
> appropriate size and alignment.
> 
> This never happens in practice, given the limited size of the assets
> being mapped by the early boot code. Nonetheless, it would be better if
> this code would behave correctly in all circumstances.
> 
> So only permit block mappings at level 2, and page mappings at level 3,
> for any page size, and use table mappings exclusively at all other
> levels. This change should have no impact in practice, but it makes the
> code more robust.
> 
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> ---
> v2: take the assignment of protval out of the loop again, so that
>     clearing a mapping works as expected wrt the PTE_CONT bit
> 
>  arch/arm64/kernel/pi/map_range.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..5778697f3062 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -45,12 +45,12 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	 * clearing the mapping
>  	 */
>  	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> +		protval |= (level == 2) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
>  
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -		if (level < 3 && (start | next | pa) & lmask) {
> +		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
>  			/*
>  			 * This chunk needs a finer grained mapping. Create a
>  			 * table mapping if necessary and recurse.

Again did not see any problem running this on various 4K/16K/64K page configs.

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>


From memxor at gmail.com  Tue Mar 11 01:48:51 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Tue, 11 Mar 2025 09:48:51 +0100
Subject: [PATCH 1/4] asm-generic: barrier: Add smp_cond_load_relaxed_timewait()
In-Reply-To: <87pliusihc.fsf@oracle.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-2-ankur.a.arora@oracle.com> <Z8dRalfxYcJIcLGj@arm.com> <87pliusihc.fsf@oracle.com>
Message-ID: <CAP01T76TWAPz4fXh6EoqHLCAxtgbzyvZib72QeFoTSx-0WKPtQ@mail.gmail.com>

On Thu, 6 Mar 2025 at 08:53, Ankur Arora <ankur.a.arora at oracle.com> wrote:
>
>
> Catalin Marinas <catalin.marinas at arm.com> writes:
>
> > On Mon, Feb 03, 2025 at 01:49:08PM -0800, Ankur Arora wrote:
> >> Add smp_cond_load_relaxed_timewait(), a timed variant of
> >> smp_cond_load_relaxed(). This is useful for cases where we want to
> >> wait on a conditional variable but don't want to wait indefinitely.
> >
> > Bikeshedding: why not "timeout" rather than "timewait"?
>
> Well my reasons, such as they are, also involved a fair amount of bikeshedding:
>
>  - timewait and spinwait have same length names which just minimized all
>    the indentation issues.
>  - timeout seems to suggest a timing mechanism of some kind.

I would also be in favor of timewait naming, since this is not a
generic timeout primitive, the alternative naming is useful to
distinguish it.
The wait can be off by 100us or so for arm64 when we need to break out
but that's tolerable for some cases.
I've also taken a copy of the thing in [0] so it can begin using the
in-tree implementation once it's merged.

  [0]: https://lore.kernel.org/bpf/20250303152305.3195648-9-memxor at gmail.com

>
> [...]


From s-vadapalli at ti.com  Tue Mar 11 01:51:09 2025
From: s-vadapalli at ti.com (s-vadapalli at ti.com)
Date: Tue, 11 Mar 2025 14:21:09 +0530
Subject: [PATCH net] net: ethernet: ti: am65-cpsw: Fix NAPI registration
 sequence
In-Reply-To: <421a4c67865215927897e16866814bd6eb68a89d.camel@siemens.com>
References: <20250311061214.4111634-1-s-vadapalli@ti.com>
 <421a4c67865215927897e16866814bd6eb68a89d.camel@siemens.com>
Message-ID: <20250311085109.q3g32v3ycoskhsko@uda0492258>

On Tue, Mar 11, 2025 at 07:09:56AM +0000, Sverdlin, Alexander wrote:
> Hi Siddharth!

Hello Alexander,

> 
> On Tue, 2025-03-11 at 11:42 +0530, Siddharth Vadapalli wrote:
> > From: Vignesh Raghavendra <vigneshr at ti.com>
> > 
> > Registering the interrupts for TX or RX DMA Channels prior to registering
> > their respective NAPI callbacks can result in a NULL pointer dereference.
> > This is seen in practice as a random occurrence since it depends on the
> > randomness associated with the generation of traffic by Linux and the
> > reception of traffic from the wire.
> > 
> > Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> 
> The patch Vignesh mentions here...
> 
> > Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> > Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > ---
> > 
> > Hello,
> > 
> > This patch is based on commit
> > 4d872d51bc9d Merge tag 'x86-urgent-2025-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
> > of Mainline Linux.
> > 
> > Regards,
> > Siddharth.
> > 
> > ?drivers/net/ethernet/ti/am65-cpsw-nuss.c | 12 ++++++------
> > ?1 file changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > index 2806238629f8..d5291281c781 100644
> > --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > @@ -2314,6 +2314,9 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > ?		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
> > ?		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
> > ?
> > +		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > +				? am65_cpsw_nuss_tx_poll);
> > +
> > ?		ret = devm_request_irq(dev, tx_chn->irq,
> > ?				?????? am65_cpsw_nuss_tx_irq,
> > ?				?????? IRQF_TRIGGER_HIGH,
> > @@ -2323,9 +2326,6 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > ?				tx_chn->id, tx_chn->irq, ret);
> > ?			goto err;
> > ?		}
> > -
> > -		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > -				? am65_cpsw_nuss_tx_poll);
> 
> ... has accounted for the fact ..._napi_add_... happens after [possibly unsuccessful] request_irq,
> please grep for "for (--i ;". Is it necessary to adjust both loops, in the below case too?

Yes! The order within the cleanup path has to be reversed too i.e.
release IRQ first followed by deleting the NAPI callback. I assume that
you are referring to the same. Please let me know otherwise. The diff
corresponding to it is:
---------------------------------------------------------------------------------------------------
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index d5291281c781..32c844816501 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2334,8 +2334,8 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
        for (--i ; i >= 0 ; i--) {
                struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];

-               netif_napi_del(&tx_chn->napi_tx);
                devm_free_irq(dev, tx_chn->irq, tx_chn);
+               netif_napi_del(&tx_chn->napi_tx);
        }

        return ret;
@@ -2592,8 +2592,8 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 err_flow:
        for (--i; i >= 0 ; i--) {
                flow = &rx_chn->flows[i];
-               netif_napi_del(&flow->napi_rx);
                devm_free_irq(dev, flow->irq, flow);
+               netif_napi_del(&flow->napi_rx);
        }

 err:
---------------------------------------------------------------------------------------------------
Based on your confirmation, I will implement the above and post the v2
patch. Thank you for reviewing this patch and providing feedback.

Regards,
Siddharth.


From wiagn233 at outlook.com  Tue Mar 11 01:51:28 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Tue, 11 Mar 2025 16:51:28 +0800
Subject: [PATCH v1] mt76: mt7915: wed: find rx token by physical address
In-Reply-To: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
References: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
Message-ID: <TYCPR01MB843726907C170CFE2D3EB7BE98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Hi Shih,

Can you also give this patch a review? Seems I also need to convert to
reverse Xmas tree order for this patch, will do it in next version.

Best regards,
Shengyu

? 2025/2/22 19:38, Shengyu Qu ??:
> The token id in RxDMAD may be incorrect when it is not the last frame
> due to WED HW bug. Lookup correct token id by physical address in sdp0.
> 
> Downstream patch link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/737340322ab22b138fd200e020d61ffdbe3e36a9/autobuild/autobuild_5.4_mac80211_release/mt7988_wifi7_mac80211_mlo/package/kernel/mt76/patches/0062-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
> 
> Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
> Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
> ---
>   drivers/net/wireless/mediatek/mt76/dma.c | 25 +++++++++++++++++++++++-
>   1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> index 844af16ee551..5bf63014263c 100644
> --- a/drivers/net/wireless/mediatek/mt76/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> @@ -444,9 +444,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
>   	mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
>   
>   	if (mt76_queue_is_wed_rx(q)) {
> +		u32 id, find = 0;
>   		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
> -		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
> +		struct mt76_txwi_cache *t;
> +
> +		if (*more) {
> +			spin_lock_bh(&dev->rx_token_lock);
> +
> +			idr_for_each_entry(&dev->rx_token, t, id) {
> +				if (t->dma_addr == le32_to_cpu(desc->buf0)) {
> +					find = 1;
> +					token = id;
> +
> +					/* Write correct id back to DMA*/
> +					u32p_replace_bits(&buf1, id,
> +							  MT_DMA_CTL_TOKEN);
> +					WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
> +					break;
> +				}
> +			}
> +
> +			spin_unlock_bh(&dev->rx_token_lock);
> +			if (!find)
> +				return NULL;
> +		}
>   
> +		t = mt76_rx_token_release(dev, token);
>   		if (!t)
>   			return NULL;
>   

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/3a463285/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/3a463285/attachment.sig>

From daniel.baluta at gmail.com  Tue Mar 11 01:59:46 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:59:46 +0200
Subject: [PATCH v4 8/8] imx_dsp_rproc: Use reset controller API to control
 the DSP
In-Reply-To: <Z88Ib7HkbRQoiyZp@p14s>
References: <20250305100037.373782-1-daniel.baluta@nxp.com>
 <20250305100037.373782-9-daniel.baluta@nxp.com> <Z88Ib7HkbRQoiyZp@p14s>
Message-ID: <CAEnQRZDeBkNYBNQwJL5LZgLK49siqomzyM_RDccdusJa22yiJA@mail.gmail.com>

On Mon, Mar 10, 2025 at 5:43?PM Mathieu Poirier
<mathieu.poirier at linaro.org> wrote:
>
> Good day,
>
> On Wed, Mar 05, 2025 at 12:00:36PM +0200, Daniel Baluta wrote:
> > DSP on i.MX8MP doesn't have a direct reset line so according to hardware
> > design team in order to handle assert/deassert/reset functionality we
> > need to use a combination of control bits from two modules. Audio block
> > control module for Run/Stall control of the DSP and DAP module in order
> > to do software reset.
> >
> > Initial design accessed RunStall bits from audio block control using the
> > syscon interface but this got NACKed by community because of abusing the
> > syscon interface [1].
> >
> > So instead we use the reset controller API.
>
> I am good with this patchset.  The only thing I'd like so see modified is the
> above changelog.  The second paragraph doesn't belong there, i.e it is not
> useful to remark on a design that was not accepted.  Instead please concentrate
> on _why_ we are moving from the current design to using the reset controller
> API.
>
> This can go in the 6.15 merge window if you send me a V5 fast enough.

Thanks for review. Reworded the commit message and send V5.

Thanks,
Daniel.


From s-vadapalli at ti.com  Tue Mar 11 02:00:25 2025
From: s-vadapalli at ti.com (s-vadapalli at ti.com)
Date: Tue, 11 Mar 2025 14:30:25 +0530
Subject: [PATCH net] net: ethernet: ti: am65-cpsw: Fix NAPI registration
 sequence
In-Reply-To: <dbeb0d830c41eefe127d13af55fbaf6243164b0a.camel@siemens.com>
References: <20250311061214.4111634-1-s-vadapalli@ti.com>
 <421a4c67865215927897e16866814bd6eb68a89d.camel@siemens.com>
 <20250311085109.q3g32v3ycoskhsko@uda0492258>
 <dbeb0d830c41eefe127d13af55fbaf6243164b0a.camel@siemens.com>
Message-ID: <20250311090025.kyc657febhgxrhoa@uda0492258>

On Tue, Mar 11, 2025 at 08:56:49AM +0000, Sverdlin, Alexander wrote:
> Hi Siddharth!
> 
> On Tue, 2025-03-11 at 14:21 +0530, s-vadapalli at ti.com wrote:
> > > > Registering the interrupts for TX or RX DMA Channels prior to registering
> > > > their respective NAPI callbacks can result in a NULL pointer dereference.
> > > > This is seen in practice as a random occurrence since it depends on the
> > > > randomness associated with the generation of traffic by Linux and the
> > > > reception of traffic from the wire.
> > > > 
> > > > Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> > > 
> > > The patch Vignesh mentions here...
> > > 
> > > > Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> > > > Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> 
> ...
> 
> > > > --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > > > +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > > > @@ -2314,6 +2314,9 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > > > ?		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
> > > > ?		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
> > > > ?
> > > > +		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > > > +				? am65_cpsw_nuss_tx_poll);
> > > > +
> > > > ?		ret = devm_request_irq(dev, tx_chn->irq,
> > > > ?				?????? am65_cpsw_nuss_tx_irq,
> > > > ?				?????? IRQF_TRIGGER_HIGH,
> > > > @@ -2323,9 +2326,6 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > > > ?				tx_chn->id, tx_chn->irq, ret);
> > > > ?			goto err;
> > > > ?		}
> > > > -
> > > > -		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > > > -				? am65_cpsw_nuss_tx_poll);
> > > 
> > > ... has accounted for the fact ..._napi_add_... happens after [possibly unsuccessful] request_irq,
> > > please grep for "for (--i ;". Is it necessary to adjust both loops, in the below case too?
> > 
> > Yes! The order within the cleanup path has to be reversed too i.e.
> 
> Not only reverting the order...
> What I'm referring is: when requesting i-th IRQ fails there has been 
> i-th NAPI already added, but the cleanup loops start from [i-1]-th instance.
> It looks like a potential leak to me...

Thank you for clarifying. I will address this and the previous feedback in
the v2 patch.

Regards,
Siddharth.


From angelogioacchino.delregno at collabora.com  Tue Mar 11 02:09:40 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 11 Mar 2025 10:09:40 +0100
Subject: [PATCH v1 5/6] drm/panfrost: Enable AARCH64_4K page table format
 on mediatek_mt8188
In-Reply-To: <20250310195921.157511-6-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-6-ariel.dalessandro@collabora.com>
Message-ID: <55b8bc40-0a29-46c2-ba5d-c7cc7742cf5f@collabora.com>

Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
> Now that Panfrost supports AARCH64_4K page table format, let's enable it
> on Mediatek MT8188.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>   drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 0f3935556ac76..d7b8bded6d784 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
>   	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
>   	.pm_domain_names = mediatek_mt8183_pm_domains,
>   	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
> +	.gpu_configs = BIT(GPU_CONFIG_AARCH64_4K),
>   };
>   
>   static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };

Didn't that work on MT8195/8395 as well? I also recall hearing that it was somewhat
giving ever-so-slightly better performance?

If it does, please enable it on 8195 as well :-)

also s/mediatek_mt8188/MediaTek MT8188/g

...and btw
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Cheers,
Angelo


From angelogioacchino.delregno at collabora.com  Tue Mar 11 02:10:06 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 11 Mar 2025 10:10:06 +0100
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250310195921.157511-5-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
Message-ID: <760e3112-0433-41ab-ab39-faaf0463fbe8@collabora.com>

Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> Address Extension", which in Linux we've called "mali_lpae".
> 
> This commit adds support for conditionally enabling AARCH64_4K page
> table format. To achieve that, a "GPU optional configurations" field was
> added to `struct panfrost_features` with the related flag.
> 
> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> the HW_FEATURE_AARCH64_MMU feature flag present.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>   3 files changed, 169 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> index cffcb0ac7c111..0385702aa43c7 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>   	GPU_PM_VREG_OFF,
>   };
>   
> +/**
> + * enum panfrost_gpu_config - GPU optional configurations
> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
> + */
> +enum panfrost_gpu_config {
> +	GPU_CONFIG_AARCH64_4K,
> +};
> +
>   struct panfrost_features {
>   	u16 id;
>   	u16 revision;
> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>   
>   	/* Allowed PM features */
>   	u8 pm_features;
> +
> +	/* GPU features */
> +	u8 gpu_configs;
>   };
>   
>   struct panfrost_device {
> @@ -162,6 +173,11 @@ struct panfrost_mmu {
>   	int as;
>   	atomic_t as_count;
>   	struct list_head list;
> +	struct {
> +		u64 transtab;
> +		u64 memattr;
> +		u64 transcfg;
> +	} cfg;
>   };
>   
>   struct panfrost_engine_usage {
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 31df3a96f89bd..4a9b8de2ff987 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -26,6 +26,48 @@
>   #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
>   #define mmu_read(dev, reg) readl(dev->iomem + reg)
>   
> +static u64 mair_to_memattr(u64 mair, bool coherent)
> +{
> +	u64 memattr = 0;
> +	u32 i;
> +
> +	for (i = 0; i < 8; i++) {
> +		u8 in_attr = mair >> (8 * i), out_attr;
> +		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
> +
> +		/* For caching to be enabled, inner and outer caching policy
> +		 * have to be both write-back, if one of them is write-through
> +		 * or non-cacheable, we just choose non-cacheable. Device
> +		 * memory is also translated to non-cacheable.
> +		 */
> +		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
> +				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
> +		} else {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
> +			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
> +			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
> +			 * to Mali's internal-shareable mode. As per the Mali
> +			 * Spec, inner and outer-shareable modes aren't allowed
> +			 * for WB memory when coherency is disabled.
> +			 * Use SH_CPU_INNER mode when coherency is enabled, so
> +			 * that SH_IS actually maps to the standard definition of
> +			 * inner-shareable.
> +			 */
> +			if (!coherent)
> +				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
> +			else
> +				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
> +		}
> +
> +		memattr |= (u64)out_attr << (8 * i);
> +	}
> +
> +	return memattr;
> +}
> +
>   static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
>   {
>   	int ret;
> @@ -121,9 +163,57 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>   	return ret;
>   }
>   
> +static void mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	/* TODO: The following fields are duplicated between the MMU and Page
> +	 * Table config structs. Ideally, should be kept in one place.
> +	 */
> +	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
> +	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
> +	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
> +}
> +
> +static void mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
> +				AS_TRANSTAB_AARCH64_4K_ADDR_MASK;
> +
> +	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
> +					   pgtbl_cfg->coherent_walk);
> +
> +	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
> +			    AS_TRANSCFG_PTW_RA |
> +			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
> +			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
> +	if (pgtbl_cfg->coherent_walk)
> +		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
> +}
> +
> +static void panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
> +				  enum io_pgtable_fmt fmt)
> +{
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	switch (fmt) {
> +	case ARM_64_LPAE_S1:
> +		mmu_cfg_init_aarch64_4k(mmu);
> +		break;
> +	case ARM_MALI_LPAE:
> +		mmu_cfg_init_mali_lpae(mmu);
> +		break;
> +	default:

If you add a
		/* That should never happen */

...it's clear-er why this function doesn't fail (but still raises some eyebrows,
because if the `default` case is not reachable, why does it even have a print?).

> +		dev_WARN_ONCE(pfdev->dev, 1, "Unhandled page table format\n");
> +		break;
> +	}
> +}
> +
>   static void
>   _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
> -			       u64 transtab, u64 memattr)
> +			       u64 transtab, u64 memattr, u64 transcfg)
>   {
>   	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>   
> @@ -133,25 +223,28 @@ _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
>   	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>   	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>   
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
> +
>   	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
> +
> +	dev_dbg(pfdev->dev, "mmu_as_control: as=%d, transtab=0x%016llx, memattr=0x%016llx, transcfg=0x%016llx",
> +		as_nr, transtab, memattr, transcfg);
>   }
>   
>   static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>   {
> -	int as_nr = mmu->as;
> -	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> -	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> -	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
> -
>   	/* Need to revisit mem attrs.
>   	 * NC is the default, Mali driver is inner WT.
>   	 */
> -	_panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
> +	_panfrost_mmu_as_control_write(pfdev, mmu->as, mmu->cfg.transtab,
> +				       mmu->cfg.memattr, mmu->cfg.transcfg);
>   }
>   
>   static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
>   {
> -	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
> +	_panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0,
> +				       AS_TRANSCFG_ADRMODE_UNMAPPED);
>   }
>   
>   u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
> @@ -616,6 +709,7 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>   {
>   	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>   	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
> +	enum io_pgtable_fmt fmt = ARM_MALI_LPAE;

Double initialization! :-)

>   	struct panfrost_mmu *mmu;
>   
>   	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
> @@ -641,16 +735,28 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>   		.iommu_dev	= pfdev->dev,
>   	};
>   
> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
> -					      mmu);
> -	if (!mmu->pgtbl_ops) {
> -		kfree(mmu);
> -		return ERR_PTR(-EINVAL);
> +	if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {

Why aren't you performing this check before kzalloc?

If you do so, you will be able to avoid having a goto, because this check will
simply return an error (struct not allocated yet, nothing to kfree).
This also means that you won't have to modify anything about the error handling
of the alloc_io_pgtable_ops below....

> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
> +			dev_err_once(pfdev->dev,
> +				     "AARCH64_4K page table not supported\n");
> +			goto err_free_mmu;
> +		}
> +		fmt = ARM_64_LPAE_S1;
>   	}

} else {
	fmt = ARM_MALI_LPAE;
}

>   
> +	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
> +	if (!mmu->pgtbl_ops)
> +		goto err_free_mmu;
> +
> +	panfrost_mmu_cfg_init(mmu, fmt);
> +
>   	kref_init(&mmu->refcount);
>   
>   	return mmu;
> +
> +err_free_mmu:
> +	kfree(mmu);
> +	return ERR_PTR(-EINVAL);
>   }
>   
>   static const char *access_type_name(struct panfrost_device *pfdev,
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index b5f279a19a084..2b8f1617b8369 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -301,6 +301,17 @@
>   #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
>   #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
>   #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
> +							 ((w) ? BIT(0) : 0) | \
> +							 ((r) ? BIT(1) : 0))
> +#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
> +#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
> +#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
>   #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
>   #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
>   #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
> @@ -311,6 +322,24 @@
>   /* Additional Bifrost AS registers */
>   #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
>   #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
> +#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
> +#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
> +#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)

"Anything" shifted in any direction by 0 is equal to the same "anything" :-)

Those are just 0,1,2,6,8

> +#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
> +#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
> +#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
> +#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)

BIT(24)

> +#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)

BIT(25)

> +#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)

0

> +#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)

BIT(29)

> +#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)

GENMASK(29, 28) or BIT(28) | BIT(29)

(btw, rinse and repeat for the memattrs)

> +#define   AS_TRANSCFG_PTW_RA				BIT(30)
> +#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
> +#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
> +#define   AS_TRANSCFG_WXN				BIT(35)
> +#define   AS_TRANSCFG_XREADABLE				BIT(36)
>   #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
>   #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>   
> @@ -326,6 +355,11 @@
>   #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
>   #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
>   
> +/*
> + * Begin AARCH64_4K MMU TRANSTAB register values
> + */
> +#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
> +
>   #define AS_STATUS_AS_ACTIVE			0x01
>   
>   #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)


Cheers,
Angelo



From angelogioacchino.delregno at collabora.com  Tue Mar 11 02:14:44 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 11 Mar 2025 10:14:44 +0100
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250311090545.3b941567@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
 <20250311090545.3b941567@collabora.com>
Message-ID: <16f6a6e2-4dce-4af9-bc0a-61c4d6213f02@collabora.com>

Il 11/03/25 09:05, Boris Brezillon ha scritto:
> On Mon, 10 Mar 2025 16:59:19 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>> Address Extension", which in Linux we've called "mali_lpae".
>>
>> This commit adds support for conditionally enabling AARCH64_4K page
>> table format. To achieve that, a "GPU optional configurations" field was
>> added to `struct panfrost_features` with the related flag.
>>
>> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
>> the HW_FEATURE_AARCH64_MMU feature flag present.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> ---
>>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
>>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>>   3 files changed, 169 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
>> index cffcb0ac7c111..0385702aa43c7 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
>> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
>> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>>   	GPU_PM_VREG_OFF,
>>   };
>>   
>> +/**
>> + * enum panfrost_gpu_config - GPU optional configurations
>> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
>> + */
>> +enum panfrost_gpu_config {
>> +	GPU_CONFIG_AARCH64_4K,
>> +};
>> +
>>   struct panfrost_features {
>>   	u16 id;
>>   	u16 revision;
>> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>>   
>>   	/* Allowed PM features */
>>   	u8 pm_features;
>> +
>> +	/* GPU features */
>> +	u8 gpu_configs;
> 
> I would probably name this gpu_quirks, with the GPU_CONFIG_AARCH64_4K
> flag renamed GPU_QUIRK_FORCE_AARCH64_PAGE_TABLE.
> 

Boris, at this point the quirk should be LPAE, not AARCH64_4K, because the
former is legacy...

I think that Ariel is right in this, as in, that's a capability of the GPU
MMU, so if anything I would rather rename it to gpu_capabilities, but then
that'd be confusing for other stuff - which means that gpu_configs is most
probably the least confusing and/or most appropriate name for this.

Of course, just IMO.

Cheers,
Angelo

>>   };
>>   



From angelogioacchino.delregno at collabora.com  Tue Mar 11 02:16:09 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 11 Mar 2025 10:16:09 +0100
Subject: [PATCH v1 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250310195921.157511-2-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-2-ariel.dalessandro@collabora.com>
Message-ID: <62765c3c-7663-4b27-a839-7fe5ea9a3c12@collabora.com>

Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
> Panfrost does not support uncached mappings, so flag them properly. Also
> flag the pages that are mapped as response to a page fault as cached.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>



From daniel.baluta at nxp.com  Tue Mar 11 01:58:11 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:11 +0200
Subject: [PATCH v5 8/8] imx_dsp_rproc: Use reset controller API to control the DSP
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-9-daniel.baluta@nxp.com>

DSP on i.MX8MP doesn't have a direct reset line so according to hardware
design team in order to handle assert/deassert/reset functionality we
need to use a combination of control bits from two modules. Audio block
control module for Run/Stall control of the DSP and DAP module in order
to do software reset.

In a first step, for i.MX8MP we are switching on using the reset
controller API to handle the DSP Run/Stall bits i.MX8MP. This comes with
the advantage of offering a better probe ordering and a more natural way
of abstracting the Audio block control bits.

[1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/remoteproc/imx_dsp_rproc.c | 25 +++++++++++++++++--------
 drivers/remoteproc/imx_rproc.h     |  2 ++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index ea5024919c2f..bc60edcdd661 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -19,6 +19,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 
 #include "imx_rproc.h"
@@ -111,6 +112,7 @@ enum imx_dsp_rp_mbox_messages {
  */
 struct imx_dsp_rproc {
 	struct regmap				*regmap;
+	struct reset_control			*run_stall;
 	struct rproc				*rproc;
 	const struct imx_dsp_rproc_dcfg		*dsp_dcfg;
 	struct clk_bulk_data			clks[DSP_RPROC_CLK_MAX];
@@ -192,9 +194,7 @@ static int imx8mp_dsp_reset(struct imx_dsp_rproc *priv)
 	/* Keep reset asserted for 10 cycles */
 	usleep_range(1, 2);
 
-	regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2,
-			   IMX8M_AudioDSP_REG2_RUNSTALL,
-			   IMX8M_AudioDSP_REG2_RUNSTALL);
+	reset_control_assert(priv->run_stall);
 
 	/* Take the DSP out of reset and keep stalled for FW loading */
 	pwrctl = readl(dap + IMX8M_DAP_PWRCTL);
@@ -231,13 +231,9 @@ static int imx8ulp_dsp_reset(struct imx_dsp_rproc *priv)
 
 /* Specific configuration for i.MX8MP */
 static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = {
-	.src_reg	= IMX8M_AudioDSP_REG2,
-	.src_mask	= IMX8M_AudioDSP_REG2_RUNSTALL,
-	.src_start	= 0,
-	.src_stop	= IMX8M_AudioDSP_REG2_RUNSTALL,
 	.att		= imx_dsp_rproc_att_imx8mp,
 	.att_size	= ARRAY_SIZE(imx_dsp_rproc_att_imx8mp),
-	.method		= IMX_RPROC_MMIO,
+	.method		= IMX_RPROC_RESET_CONTROLLER,
 };
 
 static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = {
@@ -329,6 +325,9 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
 					  true,
 					  rproc->bootaddr);
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		ret = reset_control_deassert(priv->run_stall);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -369,6 +368,9 @@ static int imx_dsp_rproc_stop(struct rproc *rproc)
 					  false,
 					  rproc->bootaddr);
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		ret = reset_control_assert(priv->run_stall);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -995,6 +997,13 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv)
 
 		priv->regmap = regmap;
 		break;
+	case IMX_RPROC_RESET_CONTROLLER:
+		priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall");
+		if (IS_ERR(priv->run_stall)) {
+			dev_err(dev, "Failed to get DSP runstall reset control\n");
+			return PTR_ERR(priv->run_stall);
+		}
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		break;
diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
index 17a7d051c531..cfd38d37e146 100644
--- a/drivers/remoteproc/imx_rproc.h
+++ b/drivers/remoteproc/imx_rproc.h
@@ -24,6 +24,8 @@ enum imx_rproc_method {
 	IMX_RPROC_SMC,
 	/* Through System Control Unit API */
 	IMX_RPROC_SCU_API,
+	/* Through Reset Controller API */
+	IMX_RPROC_RESET_CONTROLLER,
 };
 
 /* dcfg flags */
-- 
2.43.0



From luca.ceresoli at bootlin.com  Tue Mar 11 02:21:21 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Tue, 11 Mar 2025 10:21:21 +0100
Subject: [PATCH v2 0/2] vsprintf: remove redundant %pCn format specifier
Message-ID: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>

There are two printk format specifiers for clocks: %pC and %pCn, and they
print exactly the same string. Geert confirmed the intended reason for
having two was that %pC would act as a default, like some (but not all)
formats do. However there seem to be no advantage in having two instead of
one, especially now that there is no other %pC specifier since commit
666902e42fd8 ("lib/vsprintf: Remove atomic-unsafe support for %pCr").

Definitely having two without properly documenting they do the same creates
misunderstandings [0].

Since %pCn is used in a single place, replace it with %pC and remove %pCn
to simplify such format specifiers implementation and avoid
misunderstandings.

[0] https://lore.kernel.org/dri-devel/f8df2b5e-b005-4ada-8108-159b2b94a72e at nxp.com/

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
Changes in v2:
- Add Chinese translation
- Link to v1: https://lore.kernel.org/r/20250307-vsprintf-pcn-v1-0-df0b2ccf610f at bootlin.com

---
Luca Ceresoli (2):
      thermal: bcm2835: use %pC instead of %pCn
      vsprintf: remove redundant and unused %pCn format specifier

 Documentation/core-api/printk-formats.rst                    |  3 +--
 Documentation/translations/zh_CN/core-api/printk-formats.rst |  3 +--
 drivers/thermal/broadcom/bcm2835_thermal.c                   |  2 +-
 lib/vsprintf.c                                               | 10 ++--------
 4 files changed, 5 insertions(+), 13 deletions(-)
---
base-commit: 4d872d51bc9d7b899c1f61534e3dbde72613f627
change-id: 20250307-vsprintf-pcn-8a43e3b0d43e

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From luca.ceresoli at bootlin.com  Tue Mar 11 02:21:22 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Tue, 11 Mar 2025 10:21:22 +0100
Subject: [PATCH v2 1/2] thermal: bcm2835: use %pC instead of %pCn
In-Reply-To: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
References: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
Message-ID: <20250311-vsprintf-pcn-v2-1-0af40fc7dee4@bootlin.com>

The %pC and %pCn printk format specifiers produce the exact same string. In
preparation for removing %pCn, use %pC.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v2: none.
---
 drivers/thermal/broadcom/bcm2835_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index 7fbba2233c4c12e14090832a62784e1500c0ab79..685a5aee5e0dfb113638313a9086721beae09db3 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -192,7 +192,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
 	rate = clk_get_rate(data->clk);
 	if ((rate < 1920000) || (rate > 5000000))
 		dev_warn(dev,
-			 "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
+			 "Clock %pC running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
 			 data->clk, rate);
 
 	/* register of thermal sensor and get info from DT */

-- 
2.48.1



From alexander.sverdlin at siemens.com  Tue Mar 11 01:56:49 2025
From: alexander.sverdlin at siemens.com (Sverdlin, Alexander)
Date: Tue, 11 Mar 2025 08:56:49 +0000
Subject: [PATCH net] net: ethernet: ti: am65-cpsw: Fix NAPI registration
 sequence
In-Reply-To: <20250311085109.q3g32v3ycoskhsko@uda0492258>
References: <20250311061214.4111634-1-s-vadapalli@ti.com>
	 <421a4c67865215927897e16866814bd6eb68a89d.camel@siemens.com>
	 <20250311085109.q3g32v3ycoskhsko@uda0492258>
Message-ID: <dbeb0d830c41eefe127d13af55fbaf6243164b0a.camel@siemens.com>

Hi Siddharth!

On Tue, 2025-03-11 at 14:21 +0530, s-vadapalli at ti.com wrote:
> > > Registering the interrupts for TX or RX DMA Channels prior to registering
> > > their respective NAPI callbacks can result in a NULL pointer dereference.
> > > This is seen in practice as a random occurrence since it depends on the
> > > randomness associated with the generation of traffic by Linux and the
> > > reception of traffic from the wire.
> > > 
> > > Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> > 
> > The patch Vignesh mentions here...
> > 
> > > Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> > > Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

...

> > > --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > > +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > > @@ -2314,6 +2314,9 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > > ?		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
> > > ?		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
> > > ?
> > > +		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > > +				? am65_cpsw_nuss_tx_poll);
> > > +
> > > ?		ret = devm_request_irq(dev, tx_chn->irq,
> > > ?				?????? am65_cpsw_nuss_tx_irq,
> > > ?				?????? IRQF_TRIGGER_HIGH,
> > > @@ -2323,9 +2326,6 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> > > ?				tx_chn->id, tx_chn->irq, ret);
> > > ?			goto err;
> > > ?		}
> > > -
> > > -		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
> > > -				? am65_cpsw_nuss_tx_poll);
> > 
> > ... has accounted for the fact ..._napi_add_... happens after [possibly unsuccessful] request_irq,
> > please grep for "for (--i ;". Is it necessary to adjust both loops, in the below case too?
> 
> Yes! The order within the cleanup path has to be reversed too i.e.

Not only reverting the order...
What I'm referring is: when requesting i-th IRQ fails there has been 
i-th NAPI already added, but the cleanup loops start from [i-1]-th instance.
It looks like a potential leak to me...

> release IRQ first followed by deleting the NAPI callback. I assume that
> you are referring to the same. Please let me know otherwise. The diff
> corresponding to it is:
> ---------------------------------------------------------------------------------------------------
> diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> index d5291281c781..32c844816501 100644
> --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> @@ -2334,8 +2334,8 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
> ??????? for (--i ; i >= 0 ; i--) {
> ??????????????? struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
> 
> -?????????????? netif_napi_del(&tx_chn->napi_tx);
> ??????????????? devm_free_irq(dev, tx_chn->irq, tx_chn);
> +?????????????? netif_napi_del(&tx_chn->napi_tx);
> ??????? }
> 
> ??????? return ret;
> @@ -2592,8 +2592,8 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?err_flow:
> ??????? for (--i; i >= 0 ; i--) {
> ??????????????? flow = &rx_chn->flows[i];
> -?????????????? netif_napi_del(&flow->napi_rx);
> ??????????????? devm_free_irq(dev, flow->irq, flow);
> +?????????????? netif_napi_del(&flow->napi_rx);
> ??????? }
> 
> ?err:
> ---------------------------------------------------------------------------------------------------
> Based on your confirmation, I will implement the above and post the v2
> patch. Thank you for reviewing this patch and providing feedback.

-- 
Alexander Sverdlin
Siemens AG
www.siemens.com

From daniel.baluta at nxp.com  Tue Mar 11 01:58:03 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:03 +0200
Subject: [PATCH v5 0/8] imx8mp: Add support to Run/Stall DSP via reset API
Message-ID: <20250311085812.1296243-1-daniel.baluta@nxp.com>

This patch series adds support to control the Run/Stall DSP bits found on
i.MX8MP via the reset controller API instead of using the syscon API.

DSP found on i.MX8MP doesn't have a direct reset line so according to hardware
design team in order to handle assert/deassert/reset functionality we
need to use a combination of control bits from two modules.

Audio block control module:
	- for Run/Stall control bits of the DSP

Debug Access Port (DAP)
	- for Software Reset via IMX8M_DAP_PWRCTL register

The current implementation for IMX DSP Remotproc driver and for Sound Open
Firmware driver (already upstream) uses the following approach:
	- maps the Audio Block Control address via syscon API through
          the fsl,dsp-ctrl property of the dsp node.
	- maps the DAP address space using directly a call to ioremap
          with IMX8M_DAP_DEBUG macro depicting the DAP base address.

The both approaches are problematic when comes to describing the address
spaces via the DT:
	- for Audio Block Control, because it uses the syscon interface
	- for DAP because it hardcodes de base address instead of using a dt node.

This patch series aims to fix the Audio Block control usage of the
syscon interface and replace it with Reset Controller interface.

Main advantages of using the Reset Controller API is that we stop
abusing the syscon interface, offer a better probe ordering, PM runtime
support. Main critique of using the Reset Controller API is that
Run/Stall bits are not reset bits (but according the hardware design
team they are part of the reset proccess since there is no real reset
line).

Initial discussion is here:
https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Note that we can safely remove the fsl,dsp-ctrl property usage from IMX DSP
remoteproc driver because there is no Device Tree users.

Changes since v4:
https://lore.kernel.org/lkml/20250305100037.373782-3-daniel.baluta at nxp.com/T/
	- picked-up R-b tags from Frank Li and Peng Fan
	- reworded commit message of patch 8/8 as per Mathieu Poirier suggestion

Changes since v3:
https://lore.kernel.org/linux-arm-kernel/20250225102005.408773-5-daniel.baluta at nxp.com/T/
	- renamed resets ids as per Philipp comments
	- add boths resets (named them runstall and softreset) as per Philipp comments

Changes since v2:
(https://lore.kernel.org/lkml/Z7ZNngd3wtJ5MZgl at lizhi-Precision-Tower-5810/T/)
        - picked R-b and A-b tags
        - use run_stall instead of reset to refer to reset controller
          instance
        - remove 'resets' description as it is a common property
        - add correct include in the yaml dts snippet example
Changes since v1:
(https://lore.kernel.org/imx/20250219030809.GD6537 at nxa18884-linux/T/)
        - addresed comments received on v1
        - picked up R-b and A-b tags

Daniel Baluta (8):
  dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
  dt-bindings: dsp: fsl,dsp: Add resets property
  arm64: dts: imx8mp: Use resets property
  reset: imx8mp-audiomix: Add prefix for internal macro
  reset: imx8mp-audiomix: Prepare the code for more reset bits
  reset: imx8mp-audiomix: Introduce active_low configuration option
  reset: imx8mp-audiomix: Add support for DSP run/stall
  imx_dsp_rproc: Use reset controller API to control the DSP

 .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 +++++-
 arch/arm64/boot/dts/freescale/imx8mp.dtsi     |  3 +
 drivers/remoteproc/imx_dsp_rproc.c            | 25 ++++--
 drivers/remoteproc/imx_rproc.h                |  2 +
 drivers/reset/reset-imx8mp-audiomix.c         | 78 +++++++++++++------
 .../dt-bindings/reset/imx8mp-reset-audiomix.h | 13 ++++
 6 files changed, 114 insertions(+), 31 deletions(-)
 create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h

-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:04 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:04 +0200
Subject: [PATCH v5 1/8] dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-2-daniel.baluta@nxp.com>

Add reset ids used for EARC and DSP on i.MX8MP platform.

Acked-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 include/dt-bindings/reset/imx8mp-reset-audiomix.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h

diff --git a/include/dt-bindings/reset/imx8mp-reset-audiomix.h b/include/dt-bindings/reset/imx8mp-reset-audiomix.h
new file mode 100644
index 000000000000..746c1337ed99
--- /dev/null
+++ b/include/dt-bindings/reset/imx8mp-reset-audiomix.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef DT_BINDING_RESET_IMX8MP_AUDIOMIX_H
+#define DT_BINDING_RESET_IMX8MP_AUDIOMIX_H
+
+#define IMX8MP_AUDIOMIX_EARC_RESET	0
+#define IMX8MP_AUDIOMIX_EARC_PHY_RESET	1
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL	2
+
+#endif /* DT_BINDING_RESET_IMX8MP_AUDIOMIX_H */
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:05 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:05 +0200
Subject: [PATCH v5 2/8] dt-bindings: dsp: fsl,dsp: Add resets property
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-3-daniel.baluta@nxp.com>

Assert and deassert functionality of the DSP found on i.MX8MP is
realized by combining control bits from two modules: Audio Block
Control and Debug Access Port.

Audio block control bits are used to Run/Stall the DSP core
while the DAP bits are used for software reset the core.

The original plan was to use fsl,dsp-ctrl property and to refer the
audiomix bits via syscon interface. This proposal received NACK from
community we shouldn't abuse the syscon interface [1].

So remove fsl,dsp-ctrl property for i.MX8MP and use reset control
interface instead.

Example dts node only uses runstall control now, but softreset will
be added in the future when we will convert the softreset functionality
to use reset controller API.

[1] https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 ++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
index ab93ffd3d2e5..b8693e4b4b0d 100644
--- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
@@ -82,6 +82,15 @@ properties:
     description:
       Phandle to syscon block which provide access for processor enablement
 
+  resets:
+    minItems: 1
+
+  reset-names:
+    minItems: 1
+    items:
+      - const: runstall
+      - const: softreset
+
 required:
   - compatible
   - reg
@@ -164,6 +173,17 @@ allOf:
             - const: txdb1
             - const: rxdb0
             - const: rxdb1
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - fsl,imx8mp-dsp
+              - fsl,imx8mp-hifi4
+    then:
+      required:
+        - resets
+        - reset-names
 
 additionalProperties: false
 
@@ -186,6 +206,7 @@ examples:
     };
   - |
     #include <dt-bindings/clock/imx8mp-clock.h>
+    #include <dt-bindings/reset/imx8mp-reset-audiomix.h>
     dsp_reserved: dsp at 92400000 {
       reg = <0x92400000 0x1000000>;
       no-map;
@@ -220,5 +241,6 @@ examples:
                <&mu2 3 0>;
       memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
                       <&dsp_vdev0vring1>, <&dsp_reserved>;
-      fsl,dsp-ctrl = <&audio_blk_ctrl>;
+      resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+      reset-names = "runstall";
     };
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:06 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:06 +0200
Subject: [PATCH v5 3/8] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-4-daniel.baluta@nxp.com>

Add resets property to dsp node in order to be able to control the dsp
run/stall bit from audio block control.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index e0d3b8cba221..90ecee81e465 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/imx8mp-clock.h>
 #include <dt-bindings/power/imx8mp-power.h>
 #include <dt-bindings/reset/imx8mp-reset.h>
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interconnect/fsl,imx8mp.h>
@@ -2421,6 +2422,8 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+			reset-names = "runstall";
 			status = "disabled";
 		};
 	};
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:07 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:07 +0200
Subject: [PATCH v5 4/8] reset: imx8mp-audiomix: Add prefix for internal macro
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-5-daniel.baluta@nxp.com>

This adds IMX8MP_AUDIOMIX_ prefix to internal macros in order to show
that specific macros are related to audiomix.

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 6e3f3069f727..c2c3e8113182 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -11,8 +11,8 @@
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
 
-#define EARC			0x200
-#define EARC_RESET_MASK		0x3
+#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET	0x200
+#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		0x3
 
 struct imx8mp_audiomix_reset {
 	struct reset_controller_dev rcdev;
@@ -35,8 +35,8 @@ static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
 
 	mask = BIT(id);
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + EARC);
-	writel(reg & ~mask, reg_addr + EARC);
+	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	writel(reg & ~mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -52,8 +52,8 @@ static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 
 	mask = BIT(id);
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + EARC);
-	writel(reg | mask, reg_addr + EARC);
+	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	writel(reg | mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -78,7 +78,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
 	spin_lock_init(&priv->lock);
 
 	priv->rcdev.owner     = THIS_MODULE;
-	priv->rcdev.nr_resets = fls(EARC_RESET_MASK);
+	priv->rcdev.nr_resets = fls(IMX8MP_AUDIOMIX_EARC_RESET_MASK);
 	priv->rcdev.ops       = &imx8mp_audiomix_reset_ops;
 	priv->rcdev.of_node   = dev->parent->of_node;
 	priv->rcdev.dev	      = dev;
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:08 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:08 +0200
Subject: [PATCH v5 5/8] reset: imx8mp-audiomix: Prepare the code for more reset bits
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-6-daniel.baluta@nxp.com>

Current code supports EARC PHY Software Reset and EARC Software Reset
but it is not easily extensible to more reset bits.

So, refactor the code in order to easily allow more reset bits in the
future.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 43 ++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index c2c3e8113182..abef6d768e62 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -3,6 +3,8 @@
  * Copyright 2024 NXP
  */
 
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
+
 #include <linux/auxiliary_bus.h>
 #include <linux/device.h>
 #include <linux/io.h>
@@ -12,7 +14,24 @@
 #include <linux/reset-controller.h>
 
 #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET	0x200
-#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		0x3
+#define IMX8MP_AUDIOMIX_EARC_RESET_MASK		BIT(1)
+#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK	BIT(2)
+
+struct imx8mp_reset_map {
+	unsigned int offset;
+	unsigned int mask;
+};
+
+static const struct imx8mp_reset_map reset_map[] = {
+	[IMX8MP_AUDIOMIX_EARC_RESET] = {
+		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+	},
+	[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
+		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
+	},
+};
 
 struct imx8mp_audiomix_reset {
 	struct reset_controller_dev rcdev;
@@ -30,13 +49,15 @@ static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, reg;
+	unsigned int mask, offset, reg;
 	unsigned long flags;
 
-	mask = BIT(id);
+	mask = reset_map[id].mask;
+	offset = reset_map[id].offset;
+
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
-	writel(reg & ~mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	reg = readl(reg_addr + offset);
+	writel(reg & ~mask, reg_addr + offset);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -47,13 +68,15 @@ static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, reg;
+	unsigned int mask, offset, reg;
 	unsigned long flags;
 
-	mask = BIT(id);
+	mask = reset_map[id].mask;
+	offset = reset_map[id].offset;
+
 	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
-	writel(reg | mask, reg_addr + IMX8MP_AUDIOMIX_EARC_RESET_OFFSET);
+	reg = readl(reg_addr + offset);
+	writel(reg | mask, reg_addr + offset);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -78,7 +101,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
 	spin_lock_init(&priv->lock);
 
 	priv->rcdev.owner     = THIS_MODULE;
-	priv->rcdev.nr_resets = fls(IMX8MP_AUDIOMIX_EARC_RESET_MASK);
+	priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
 	priv->rcdev.ops       = &imx8mp_audiomix_reset_ops;
 	priv->rcdev.of_node   = dev->parent->of_node;
 	priv->rcdev.dev	      = dev;
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:09 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:09 +0200
Subject: [PATCH v5 6/8] reset: imx8mp-audiomix: Introduce active_low configuration option
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-7-daniel.baluta@nxp.com>

For EARC and EARC PHY the reset happens when clearing the reset bits.
Refactor assert/deassert function in order to take into account the
active_low configuration option.

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 41 ++++++++++++++-------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index abef6d768e62..04ad27aca806 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -20,16 +20,19 @@
 struct imx8mp_reset_map {
 	unsigned int offset;
 	unsigned int mask;
+	bool active_low;
 };
 
 static const struct imx8mp_reset_map reset_map[] = {
 	[IMX8MP_AUDIOMIX_EARC_RESET] = {
 		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
 		.mask	= IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+		.active_low = true,
 	},
 	[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
 		.offset	= IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
 		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
+		.active_low = true,
 	},
 };
 
@@ -44,42 +47,42 @@ static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_contr
 	return container_of(rcdev, struct imx8mp_audiomix_reset, rcdev);
 }
 
-static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
-					unsigned long id)
+static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
+				  unsigned long id, bool assert)
 {
 	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
 	void __iomem *reg_addr = priv->base;
-	unsigned int mask, offset, reg;
-	unsigned long flags;
+	unsigned int mask, offset, active_low;
+	unsigned long reg, flags;
 
 	mask = reset_map[id].mask;
 	offset = reset_map[id].offset;
+	active_low = reset_map[id].active_low;
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	reg = readl(reg_addr + offset);
-	writel(reg & ~mask, reg_addr + offset);
+	if (active_low ^ assert)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	writel(reg, reg_addr + offset);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
 }
 
+static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
+					unsigned long id)
+{
+	return imx8mp_audiomix_update(rcdev, id, true);
+}
+
 static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
 					  unsigned long id)
 {
-	struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
-	void __iomem *reg_addr = priv->base;
-	unsigned int mask, offset, reg;
-	unsigned long flags;
-
-	mask = reset_map[id].mask;
-	offset = reset_map[id].offset;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	reg = readl(reg_addr + offset);
-	writel(reg | mask, reg_addr + offset);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
+	return imx8mp_audiomix_update(rcdev, id, false);
 }
 
 static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
-- 
2.43.0



From daniel.baluta at nxp.com  Tue Mar 11 01:58:10 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Tue, 11 Mar 2025 10:58:10 +0200
Subject: [PATCH v5 7/8] reset: imx8mp-audiomix: Add support for DSP run/stall
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <20250311085812.1296243-8-daniel.baluta@nxp.com>

We can Run/Stall the DSP via audio block control bits found in audiomix.
Implement this functionality using the reset controller and use assert
for Stall and deassert for Run.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/reset/reset-imx8mp-audiomix.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 04ad27aca806..6b357adfe646 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -17,6 +17,9 @@
 #define IMX8MP_AUDIOMIX_EARC_RESET_MASK		BIT(1)
 #define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK	BIT(2)
 
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET	0x108
+#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK	BIT(5)
+
 struct imx8mp_reset_map {
 	unsigned int offset;
 	unsigned int mask;
@@ -34,6 +37,11 @@ static const struct imx8mp_reset_map reset_map[] = {
 		.mask	= IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
 		.active_low = true,
 	},
+	[IMX8MP_AUDIOMIX_DSP_RUNSTALL] = {
+		.offset	= IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET,
+		.mask	= IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK,
+		.active_low = false,
+	},
 };
 
 struct imx8mp_audiomix_reset {
-- 
2.43.0



From luca.ceresoli at bootlin.com  Tue Mar 11 02:21:23 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Tue, 11 Mar 2025 10:21:23 +0100
Subject: [PATCH v2 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
References: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
Message-ID: <20250311-vsprintf-pcn-v2-2-0af40fc7dee4@bootlin.com>

%pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
add %pC{,n,r} format specifiers for clocks") introducing them does not
clarify any intended difference. It can be assumed %pC is a default for
%pCn as some other specifiers do, but not all are consistent with this
policy. Moreover there is now no other suffix other than 'n', which makes a
default not really useful.

All users in the kernel were using %pC except for one which has been
converted. So now remove %pCn and all the unnecessary extra code and
documentation.

Acked-by: Stephen Boyd <sboyd at kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v2:
- update Chinese documentation (change acked by Yanteng Si <si.yanteng at linux.dev>)
---
 Documentation/core-api/printk-formats.rst                    |  3 +--
 Documentation/translations/zh_CN/core-api/printk-formats.rst |  3 +--
 lib/vsprintf.c                                               | 10 ++--------
 3 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index ecccc0473da9c10f45f2464566f690472c61401e..f3009e6ec80a864c330c8812efcd82c12f4066b3 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -571,9 +571,8 @@ struct clk
 ::
 
 	%pC	pll1
-	%pCn	pll1
 
-For printing struct clk structures. %pC and %pCn print the name of the clock
+For printing struct clk structures. %pC prints the name of the clock
 (Common Clock Framework) or a unique 32-bit ID (legacy clock framework).
 
 Passed by reference.
diff --git a/Documentation/translations/zh_CN/core-api/printk-formats.rst b/Documentation/translations/zh_CN/core-api/printk-formats.rst
index bd36d35eba4eb124be43a66227059a30429e4135..96a917ecc93f2a4872784b6d8e3f98bcb9f5f737 100644
--- a/Documentation/translations/zh_CN/core-api/printk-formats.rst
+++ b/Documentation/translations/zh_CN/core-api/printk-formats.rst
@@ -523,9 +523,8 @@ clk???
 ::
 
 	%pC	pll1
-	%pCn	pll1
 
-????clk???%pC ? %pCn ???????????????????32?
+????clk???%pC ???????????????????32?
 ID?????????
 
 ???????
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 56fe96319292674c9f79559cf78dd0d99d1a1f06..143d55cb1c12acac21a6c6bafd255437e878f280 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1969,15 +1969,11 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
 	if (check_pointer(&buf, end, clk, spec))
 		return buf;
 
-	switch (fmt[1]) {
-	case 'n':
-	default:
 #ifdef CONFIG_COMMON_CLK
-		return string(buf, end, __clk_get_name(clk), spec);
+	return string(buf, end, __clk_get_name(clk), spec);
 #else
-		return ptr_to_id(buf, end, clk, spec);
+	return ptr_to_id(buf, end, clk, spec);
 #endif
-	}
 }
 
 static
@@ -2382,8 +2378,6 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
  *      T    time64_t
  * - 'C' For a clock, it prints the name (Common Clock Framework) or address
  *       (legacy clock framework) of the clock
- * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
- *        (legacy clock framework) of the clock
  * - 'G' For flags to be printed as a collection of symbolic strings that would
  *       construct the specific value. Supported flags given by option:
  *       p page flags (see struct page) given as pointer to unsigned long

-- 
2.48.1



From 21cnbao at gmail.com  Tue Mar 11 02:33:04 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Tue, 11 Mar 2025 22:33:04 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <dubgo2s3xafoitc2olyjqmkmroiowxbpbswefhdioaeupxoqs2@z3s4uuvojvyu>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com> <dubgo2s3xafoitc2olyjqmkmroiowxbpbswefhdioaeupxoqs2@z3s4uuvojvyu>
Message-ID: <CAGsJ_4wbgEGKDdUqa8Kpw952qiM_H5V-3X+BH6SboJMh8k2sRg@mail.gmail.com>

On Tue, Mar 11, 2025 at 5:58?PM Sergey Senozhatsky
<senozhatsky at chromium.org> wrote:
>
> On (25/03/08 18:41), Barry Song wrote:
> > On Sat, Mar 8, 2025 at 12:03?PM Nhat Pham <nphamcs at gmail.com> wrote:
> > >
> > > On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin <qun-wei.lin at mediatek.com> wrote:
> > > >
> > > > This patch series introduces a new mechanism called kcompressd to
> > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > main goal is to separate the tasks of page scanning and page compression
> > > > into distinct processes or threads, thereby reducing the load on the
> > > > kswapd thread and enhancing overall system performance under high memory
> > > > pressure conditions.
> > >
> > > Please excuse my ignorance, but from your cover letter I still don't
> > > quite get what is the problem here? And how would decouple compression
> > > and scanning help?
> >
> > My understanding is as follows:
> >
> > When kswapd attempts to reclaim M anonymous folios and N file folios,
> > the process involves the following steps:
> >
> > * t1: Time to scan and unmap anonymous folios
> > * t2: Time to compress anonymous folios
> > * t3: Time to reclaim file folios
> >
> > Currently, these steps are executed sequentially, meaning the total time
> > required to reclaim M + N folios is t1 + t2 + t3.
> >
> > However, Qun-Wei's patch enables t1 + t3 and t2 to run in parallel,
> > reducing the total time to max(t1 + t3, t2). This likely improves the
> > reclamation speed, potentially reducing allocation stalls.
>
> If compression kthread-s can run (have CPUs to be scheduled on).
> This looks a bit like a bottleneck.  Is there anything that
> guarantees forward progress?  Also, if compression kthreads
> constantly preempt kswapd, then it might not be worth it to
> have compression kthreads, I assume?

Thanks for your critical insights, all of which are valuable.

Qun-Wei is likely working on an Android case where the CPU is
relatively idle in many scenarios (though there are certainly cases
where all CPUs are busy), but free memory is quite limited.
We may soon see benefits for these types of use cases. I expect
Android might have the opportunity to adopt it before it's fully
ready upstream.

If the workload keeps all CPUs busy, I suppose this async thread
won?t help, but at least we might find a way to mitigate regression.

We likely need to collect more data on various scenarios?when
CPUs are relatively idle and when all CPUs are busy?and
determine the proper approach based on the data, which we
currently lack :-)

>
> If we have a pagefault and need to map a page that is still in
> the compression queue (not compressed and stored in zram yet, e.g.
> dut to scheduling latency + slow compression algorithm) then what
> happens?

This is happening now even without the patch?  Right now we are
having 4 steps:
1. add_to_swap: The folio is added to the swapcache.
2. try_to_unmap: PTEs are converted to swap entries.
3. pageout: The folio is written back.
4. Swapcache is cleared.

If a swap-in occurs between 2 and 4, doesn't that mean
we've already encountered the case where we hit
the swapcache for a folio undergoing compression?

It seems we might have an opportunity to terminate
compression if the request is still in the queue and
compression hasn?t started for a folio yet? seems
quite difficult to do?

Thanks
Barry


From si.yanteng at linux.dev  Tue Mar 11 02:34:58 2025
From: si.yanteng at linux.dev (Yanteng Si)
Date: Tue, 11 Mar 2025 17:34:58 +0800
Subject: [PATCH v2 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250311-vsprintf-pcn-v2-2-0af40fc7dee4@bootlin.com>
References: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
 <20250311-vsprintf-pcn-v2-2-0af40fc7dee4@bootlin.com>
Message-ID: <aa840586-cd70-417f-82c2-bb887f337720@linux.dev>


? 3/11/25 5:21 PM, Luca Ceresoli ??:
> %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> add %pC{,n,r} format specifiers for clocks") introducing them does not
> clarify any intended difference. It can be assumed %pC is a default for
> %pCn as some other specifiers do, but not all are consistent with this
> policy. Moreover there is now no other suffix other than 'n', which makes a
> default not really useful.
>
> All users in the kernel were using %pC except for one which has been
> converted. So now remove %pCn and all the unnecessary extra code and
> documentation.
>
> Acked-by: Stephen Boyd <sboyd at kernel.org>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

Reviewed-by: Yanteng Si <si.yanteng at linux.dev>


Thanks,

Yanteng

>
> ---
>
> Changes in v2:
> - update Chinese documentation (change acked by Yanteng Si <si.yanteng at linux.dev>)
> ---
>   Documentation/core-api/printk-formats.rst                    |  3 +--
>   Documentation/translations/zh_CN/core-api/printk-formats.rst |  3 +--
>   lib/vsprintf.c                                               | 10 ++--------
>   3 files changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
> index ecccc0473da9c10f45f2464566f690472c61401e..f3009e6ec80a864c330c8812efcd82c12f4066b3 100644
> --- a/Documentation/core-api/printk-formats.rst
> +++ b/Documentation/core-api/printk-formats.rst
> @@ -571,9 +571,8 @@ struct clk
>   ::
>   
>   	%pC	pll1
> -	%pCn	pll1
>   
> -For printing struct clk structures. %pC and %pCn print the name of the clock
> +For printing struct clk structures. %pC prints the name of the clock
>   (Common Clock Framework) or a unique 32-bit ID (legacy clock framework).
>   
>   Passed by reference.
> diff --git a/Documentation/translations/zh_CN/core-api/printk-formats.rst b/Documentation/translations/zh_CN/core-api/printk-formats.rst
> index bd36d35eba4eb124be43a66227059a30429e4135..96a917ecc93f2a4872784b6d8e3f98bcb9f5f737 100644
> --- a/Documentation/translations/zh_CN/core-api/printk-formats.rst
> +++ b/Documentation/translations/zh_CN/core-api/printk-formats.rst
> @@ -523,9 +523,8 @@ clk???
>   ::
>   
>   	%pC	pll1
> -	%pCn	pll1
>   
> -????clk???%pC ? %pCn ???????????????????32?
> +????clk???%pC ???????????????????32?
>   ID?????????
>   
>   ???????
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 56fe96319292674c9f79559cf78dd0d99d1a1f06..143d55cb1c12acac21a6c6bafd255437e878f280 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1969,15 +1969,11 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
>   	if (check_pointer(&buf, end, clk, spec))
>   		return buf;
>   
> -	switch (fmt[1]) {
> -	case 'n':
> -	default:
>   #ifdef CONFIG_COMMON_CLK
> -		return string(buf, end, __clk_get_name(clk), spec);
> +	return string(buf, end, __clk_get_name(clk), spec);
>   #else
> -		return ptr_to_id(buf, end, clk, spec);
> +	return ptr_to_id(buf, end, clk, spec);
>   #endif
> -	}
>   }
>   
>   static
> @@ -2382,8 +2378,6 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
>    *      T    time64_t
>    * - 'C' For a clock, it prints the name (Common Clock Framework) or address
>    *       (legacy clock framework) of the clock
> - * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
> - *        (legacy clock framework) of the clock
>    * - 'G' For flags to be printed as a collection of symbolic strings that would
>    *       construct the specific value. Supported flags given by option:
>    *       p page flags (see struct page) given as pointer to unsigned long
>


From thomas.weissschuh at linutronix.de  Tue Mar 11 02:40:49 2025
From: thomas.weissschuh at linutronix.de (=?utf-8?q?Thomas_Wei=C3=9Fschuh?=)
Date: Tue, 11 Mar 2025 10:40:49 +0100
Subject: [PATCH v2] staging: vchiq_arm: Don't use %pK through printk
Message-ID: <20250311-restricted-pointers-vchiq_arm-v2-1-a14e1c0681fc@linutronix.de>

In the past %pK was preferable to %p as it would not leak raw pointer
values into the kernel log.
Since commit ad67b74d2469 ("printk: hash addresses printed with %p")
the regular %p has been improved to avoid this issue.
Furthermore, restricted pointers ("%pK") were never meant to be used
through printk(). They can still unintentionally leak raw pointers or
acquire sleeping looks in atomic contexts.

Switch to the regular pointer formatting which is safer and
easier to reason about.
There are still a few users of %pK left, but these use it through seq_file,
for which its usage is safe.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
---
Changes in v2:
- Fix wrong replacement with invalid %K (Dan Carpenter)
- Link to v1: https://lore.kernel.org/r/20250310-restricted-pointers-vchiq_arm-v1-1-dd04f208ee55 at linutronix.de
---
 .../vc04_services/interface/vchiq_arm/vchiq_arm.c  |  6 +-
 .../vc04_services/interface/vchiq_arm/vchiq_core.c | 64 +++++++++++-----------
 .../vc04_services/interface/vchiq_arm/vchiq_dev.c  | 14 ++---
 3 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index a4e83e5d619bc95f1d4ba311a201bba8c05cd030..2db219e4786f236ce4c37afa86a12615a091c637 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -271,7 +271,7 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state
 		return -ENXIO;
 	}
 
-	dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %pK, phys %pad)\n",
+	dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %p, phys %pad)\n",
 		vchiq_slot_zero, &slot_phys);
 
 	mutex_init(&drv_mgmt->connected_mutex);
@@ -368,7 +368,7 @@ void free_bulk_waiter(struct vchiq_instance *instance)
 				 &instance->bulk_waiter_list, list) {
 		list_del(&waiter->list);
 		dev_dbg(instance->state->dev,
-			"arm: bulk_waiter - cleaned up %pK for pid %d\n",
+			"arm: bulk_waiter - cleaned up %p for pid %d\n",
 			waiter, waiter->pid);
 		kfree(waiter);
 	}
@@ -622,7 +622,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
 		mutex_lock(&instance->bulk_waiter_list_mutex);
 		list_add(&waiter->list, &instance->bulk_waiter_list);
 		mutex_unlock(&instance->bulk_waiter_list_mutex);
-		dev_dbg(instance->state->dev, "arm: saved bulk_waiter %pK for pid %d\n",
+		dev_dbg(instance->state->dev, "arm: saved bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 	}
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 8d5795db4f39f8003310a54ba369367c95e6c079..e2cac0898b8faa3c255de6b8562c7096a9683c49 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -470,7 +470,7 @@ make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
 		cb_userdata = bulk->cb_userdata;
 	}
 
-	dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n",
+	dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %p, %p %p)\n",
 		service->state->id, service->localport, reason_names[reason],
 		header, cb_data, cb_userdata);
 	status = service->base.callback(service->instance, reason, header, service->handle,
@@ -778,7 +778,7 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
 		complete(&quota->quota_event);
 	} else if (count == 0) {
 		dev_err(state->dev,
-			"core: service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n",
+			"core: service %d message_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n",
 			port, quota->message_use_count, header, msgid,
 			header->msgid, header->size);
 		WARN(1, "invalid message use count\n");
@@ -799,11 +799,11 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found,
 			 * it has dropped below its quota
 			 */
 			complete(&quota->quota_event);
-			dev_dbg(state->dev, "core: %d: pfq:%d %x@%pK - slot_use->%d\n",
+			dev_dbg(state->dev, "core: %d: pfq:%d %x@%p - slot_use->%d\n",
 				state->id, port, header->size, header, count - 1);
 		} else {
 			dev_err(state->dev,
-				"core: service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n",
+				"core: service %d slot_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n",
 				port, count, header, msgid, header->msgid, header->size);
 			WARN(1, "bad slot use count\n");
 		}
@@ -845,7 +845,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found,
 		 */
 		rmb();
 
-		dev_dbg(state->dev, "core: %d: pfq %d=%pK %x %x\n",
+		dev_dbg(state->dev, "core: %d: pfq %d=%p %x %x\n",
 			state->id, slot_index, data, local->slot_queue_recycle,
 			slot_queue_available);
 
@@ -868,7 +868,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found,
 			pos += calc_stride(header->size);
 			if (pos > VCHIQ_SLOT_SIZE) {
 				dev_err(state->dev,
-					"core: pfq - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n",
+					"core: pfq - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n",
 					pos, header, msgid, header->msgid, header->size);
 				WARN(1, "invalid slot position\n");
 			}
@@ -1060,7 +1060,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
 		int tx_end_index;
 		int slot_use_count;
 
-		dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n",
 			state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 			VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 
@@ -1117,7 +1117,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
 		VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
 		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
 	} else {
-		dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n",
 			state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 			VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 		if (size != 0) {
@@ -1204,7 +1204,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
 				state->id, oldmsgid);
 	}
 
-	dev_dbg(state->dev, "sync: %d: qms %s@%pK,%x (%d->%d)\n",
+	dev_dbg(state->dev, "sync: %d: qms %s@%p,%x (%d->%d)\n",
 		state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
 		VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
 
@@ -1539,7 +1539,7 @@ create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
 	pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
 				      GFP_KERNEL);
 
-	dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
+	dev_dbg(instance->state->dev, "arm: %p\n", pagelist);
 
 	if (!pagelist)
 		return NULL;
@@ -1692,7 +1692,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel
 	unsigned int num_pages = pagelistinfo->num_pages;
 	unsigned int cache_line_size;
 
-	dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
+	dev_dbg(instance->state->dev, "arm: %p, %d\n", pagelistinfo->pagelist, actual);
 
 	drv_mgmt = dev_get_drvdata(instance->state->dev);
 
@@ -1849,7 +1849,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
 
 	payload = (struct vchiq_open_payload *)header->data;
 	fourcc = payload->fourcc;
-	dev_dbg(state->dev, "core: %d: prs OPEN@%pK (%d->'%p4cc')\n",
+	dev_dbg(state->dev, "core: %d: prs OPEN@%p (%d->'%p4cc')\n",
 		state->id, header, localport, &fourcc);
 
 	service = get_listening_service(state, fourcc);
@@ -1976,14 +1976,14 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			service = get_connected_service(state, remoteport);
 			if (service)
 				dev_warn(state->dev,
-					 "core: %d: prs %s@%pK (%d->%d) - found connected service %d\n",
+					 "core: %d: prs %s@%p (%d->%d) - found connected service %d\n",
 					 state->id, msg_type_str(type), header,
 					 remoteport, localport, service->localport);
 		}
 
 		if (!service) {
 			dev_err(state->dev,
-				"core: %d: prs %s@%pK (%d->%d) - invalid/closed service %d\n",
+				"core: %d: prs %s@%p (%d->%d) - invalid/closed service %d\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, localport);
 			goto skip_message;
@@ -2003,7 +2003,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 
 	if (((unsigned long)header & VCHIQ_SLOT_MASK) +
 	    calc_stride(size) > VCHIQ_SLOT_SIZE) {
-		dev_err(state->dev, "core: header %pK (msgid %x) - size %x too big for slot\n",
+		dev_err(state->dev, "core: header %p (msgid %x) - size %x too big for slot\n",
 			header, (unsigned int)msgid, (unsigned int)size);
 		WARN(1, "oversized for slot\n");
 	}
@@ -2022,7 +2022,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			service->peer_version = payload->version;
 		}
 		dev_dbg(state->dev,
-			"core: %d: prs OPENACK@%pK,%x (%d->%d) v:%d\n",
+			"core: %d: prs OPENACK@%p,%x (%d->%d) v:%d\n",
 			state->id, header, size, remoteport, localport,
 			service->peer_version);
 		if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
@@ -2037,7 +2037,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 	case VCHIQ_MSG_CLOSE:
 		WARN_ON(size); /* There should be no data */
 
-		dev_dbg(state->dev, "core: %d: prs CLOSE@%pK (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: prs CLOSE@%p (%d->%d)\n",
 			state->id, header, remoteport, localport);
 
 		mark_service_closing_internal(service, 1);
@@ -2049,7 +2049,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			&service->base.fourcc, service->localport, service->remoteport);
 		break;
 	case VCHIQ_MSG_DATA:
-		dev_dbg(state->dev, "core: %d: prs DATA@%pK,%x (%d->%d)\n",
+		dev_dbg(state->dev, "core: %d: prs DATA@%p,%x (%d->%d)\n",
 			state->id, header, size, remoteport, localport);
 
 		if ((service->remoteport == remoteport) &&
@@ -2069,7 +2069,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		}
 		break;
 	case VCHIQ_MSG_CONNECT:
-		dev_dbg(state->dev, "core: %d: prs CONNECT@%pK\n",
+		dev_dbg(state->dev, "core: %d: prs CONNECT@%p\n",
 			state->id, header);
 		state->version_common =	((struct vchiq_slot_zero *)
 					 state->slot_data)->version;
@@ -2102,7 +2102,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			if ((int)(queue->remote_insert -
 				queue->local_insert) >= 0) {
 				dev_err(state->dev,
-					"core: %d: prs %s@%pK (%d->%d) unexpected (ri=%d,li=%d)\n",
+					"core: %d: prs %s@%p (%d->%d) unexpected (ri=%d,li=%d)\n",
 					state->id, msg_type_str(type), header, remoteport,
 					localport, queue->remote_insert, queue->local_insert);
 				mutex_unlock(&service->bulk_mutex);
@@ -2120,7 +2120,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 			bulk->actual = *(int *)header->data;
 			queue->remote_insert++;
 
-			dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n",
+			dev_dbg(state->dev, "core: %d: prs %s@%p (%d->%d) %x@%pad\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, bulk->actual, &bulk->dma_addr);
 
@@ -2140,12 +2140,12 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		}
 		break;
 	case VCHIQ_MSG_PADDING:
-		dev_dbg(state->dev, "core: %d: prs PADDING@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs PADDING@%p,%x\n",
 			state->id, header, size);
 		break;
 	case VCHIQ_MSG_PAUSE:
 		/* If initiated, signal the application thread */
-		dev_dbg(state->dev, "core: %d: prs PAUSE@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs PAUSE@%p,%x\n",
 			state->id, header, size);
 		if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) {
 			dev_err(state->dev, "core: %d: PAUSE received in state PAUSED\n",
@@ -2162,7 +2162,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED);
 		break;
 	case VCHIQ_MSG_RESUME:
-		dev_dbg(state->dev, "core: %d: prs RESUME@%pK,%x\n",
+		dev_dbg(state->dev, "core: %d: prs RESUME@%p,%x\n",
 			state->id, header, size);
 		/* Release the slot mutex */
 		mutex_unlock(&state->slot_mutex);
@@ -2179,7 +2179,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
 		break;
 
 	default:
-		dev_err(state->dev, "core: %d: prs invalid msgid %x@%pK,%x\n",
+		dev_err(state->dev, "core: %d: prs invalid msgid %x@%p,%x\n",
 			state->id, msgid, header, size);
 		WARN(1, "invalid message\n");
 		break;
@@ -2400,7 +2400,7 @@ sync_func(void *v)
 
 		if (!service) {
 			dev_err(state->dev,
-				"sync: %d: sf %s@%pK (%d->%d) - invalid/closed service %d\n",
+				"sync: %d: sf %s@%p (%d->%d) - invalid/closed service %d\n",
 				state->id, msg_type_str(type), header, remoteport,
 				localport, localport);
 			release_message_sync(state, header);
@@ -2422,7 +2422,7 @@ sync_func(void *v)
 					header->data;
 				service->peer_version = payload->version;
 			}
-			dev_err(state->dev, "sync: %d: sf OPENACK@%pK,%x (%d->%d) v:%d\n",
+			dev_err(state->dev, "sync: %d: sf OPENACK@%p,%x (%d->%d) v:%d\n",
 				state->id, header, size, remoteport, localport,
 				service->peer_version);
 			if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
@@ -2435,7 +2435,7 @@ sync_func(void *v)
 			break;
 
 		case VCHIQ_MSG_DATA:
-			dev_dbg(state->dev, "sync: %d: sf DATA@%pK,%x (%d->%d)\n",
+			dev_dbg(state->dev, "sync: %d: sf DATA@%p,%x (%d->%d)\n",
 				state->id, header, size, remoteport, localport);
 
 			if ((service->remoteport == remoteport) &&
@@ -2449,7 +2449,7 @@ sync_func(void *v)
 			break;
 
 		default:
-			dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%pK,%x\n",
+			dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%p,%x\n",
 				state->id, msgid, header, size);
 			release_message_sync(state, header);
 			break;
@@ -2926,13 +2926,13 @@ release_service_messages(struct vchiq_service *service)
 			int port = VCHIQ_MSG_DSTPORT(msgid);
 
 			if ((port == service->localport) && (msgid & VCHIQ_MSGID_CLAIMED)) {
-				dev_dbg(state->dev, "core:  fsi - hdr %pK\n", header);
+				dev_dbg(state->dev, "core:  fsi - hdr %p\n", header);
 				release_slot(state, slot_info, header, NULL);
 			}
 			pos += calc_stride(header->size);
 			if (pos > VCHIQ_SLOT_SIZE) {
 				dev_err(state->dev,
-					"core: fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n",
+					"core: fsi - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n",
 					pos, header, msgid, header->msgid, header->size);
 				WARN(1, "invalid slot position\n");
 			}
@@ -3091,7 +3091,7 @@ vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service,
 	 */
 	wmb();
 
-	dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n",
+	dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %p\n",
 		state->id, service->localport, service->remoteport,
 		dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data);
 
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
index 454f4341650306654d1365653ab3b570795f3331..3b20ba5c736221ce1cacfc9ce86eca623382a30b 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -270,7 +270,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
 		}
 	} else {
 		dev_err(service->state->dev,
-			"arm: header %pK: bufsize %x < size %x\n",
+			"arm: header %p: bufsize %x < size %x\n",
 			header, args->bufsize, header->size);
 		WARN(1, "invalid size\n");
 		ret = -EMSGSIZE;
@@ -328,7 +328,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
 			ret = -ESRCH;
 			goto out;
 		}
-		dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n",
+		dev_dbg(service->state->dev, "arm: found bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 
 		status = vchiq_bulk_xfer_waiting(instance, args->handle,
@@ -366,7 +366,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
 		mutex_lock(&instance->bulk_waiter_list_mutex);
 		list_add(&waiter->list, &instance->bulk_waiter_list);
 		mutex_unlock(&instance->bulk_waiter_list_mutex);
-		dev_dbg(service->state->dev, "arm: saved bulk_waiter %pK for pid %d\n",
+		dev_dbg(service->state->dev, "arm: saved bulk_waiter %p for pid %d\n",
 			waiter, current->pid);
 
 		ret = put_user(mode_waiting, mode);
@@ -512,7 +512,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
 			/* This must be a VCHIQ-style service */
 			if (args->msgbufsize < msglen) {
 				dev_err(service->state->dev,
-					"arm: header %pK: msgbufsize %x < msglen %x\n",
+					"arm: header %p: msgbufsize %x < msglen %x\n",
 					header, args->msgbufsize, msglen);
 				WARN(1, "invalid message size\n");
 				if (ret == 0)
@@ -588,7 +588,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	long ret = 0;
 	int i, rc;
 
-	dev_dbg(instance->state->dev, "arm: instance %pK, cmd %s, arg %lx\n", instance,
+	dev_dbg(instance->state->dev, "arm: instance %p, cmd %s, arg %lx\n", instance,
 		((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
 		ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
 
@@ -874,12 +874,12 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	if (!status && (ret < 0) && (ret != -EINTR) && (ret != -EWOULDBLOCK)) {
 		dev_dbg(instance->state->dev,
-			"arm: ioctl instance %pK, cmd %s -> status %d, %ld\n",
+			"arm: ioctl instance %p, cmd %s -> status %d, %ld\n",
 			instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
 			ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret);
 	} else {
 		dev_dbg(instance->state->dev,
-			"arm: ioctl instance %pK, cmd %s -> status %d\n, %ld\n",
+			"arm: ioctl instance %p, cmd %s -> status %d\n, %ld\n",
 			instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
 			ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret);
 	}

---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250310-restricted-pointers-vchiq_arm-1801bf8d634b

Best regards,
-- 
Thomas Wei?schuh <thomas.weissschuh at linutronix.de>



From maz at kernel.org  Tue Mar 11 02:41:22 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 09:41:22 +0000
Subject: [PATCH v1 1/5] arm64/sysreg: add HDBSS related register information
In-Reply-To: <20250311040321.1460-2-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
	<20250311040321.1460-2-yezhenyu2@huawei.com>
Message-ID: <86y0xboqf1.wl-maz@kernel.org>

On Tue, 11 Mar 2025 04:03:17 +0000,
Zhenyu Ye <yezhenyu2 at huawei.com> wrote:
> 
> From: eillon <yezhenyu2 at huawei.com>
> 
> The ARM architecture added the HDBSS feature and descriptions of
> related registers (HDBSSBR/HDBSSPROD) in the DDI0601(ID121123) version,
> add them to Linux.
> 
> Signed-off-by: eillon <yezhenyu2 at huawei.com>
> ---
>  arch/arm64/include/asm/esr.h          |  2 ++
>  arch/arm64/include/asm/kvm_arm.h      |  1 +
>  arch/arm64/include/asm/sysreg.h       |  4 ++++
>  arch/arm64/tools/sysreg               | 28 +++++++++++++++++++++++++++
>  tools/arch/arm64/include/asm/sysreg.h |  4 ++++
>  5 files changed, 39 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index d1b1a33f9a8b..a33befe0999a 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -147,6 +147,8 @@
>  #define ESR_ELx_CM 		(UL(1) << ESR_ELx_CM_SHIFT)
>  
>  /* ISS2 field definitions for Data Aborts */
> +#define ESR_ELx_HDBSSF_SHIFT	(11)
> +#define ESR_ELx_HDBSSF		(UL(1) << ESR_ELx_HDBSSF_SHIFT)
>  #define ESR_ELx_TnD_SHIFT	(10)
>  #define ESR_ELx_TnD 		(UL(1) << ESR_ELx_TnD_SHIFT)
>  #define ESR_ELx_TagAccess_SHIFT	(9)
> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> index c2417a424b98..80793ef57f8b 100644
> --- a/arch/arm64/include/asm/kvm_arm.h
> +++ b/arch/arm64/include/asm/kvm_arm.h
> @@ -122,6 +122,7 @@
>  			 TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK)
>  
>  /* VTCR_EL2 Registers bits */
> +#define VTCR_EL2_HDBSS		(1UL << 45)
>  #define VTCR_EL2_DS		TCR_EL2_DS
>  #define VTCR_EL2_RES1		(1U << 31)
>  #define VTCR_EL2_HD		(1 << 22)
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 05ea5223d2d5..b727772c06fb 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -522,6 +522,10 @@
>  #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
>  
>  #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
> +
> +#define SYS_HDBSSBR_EL2			sys_reg(3, 4, 2, 3, 2)
> +#define SYS_HDBSSPROD_EL2		sys_reg(3, 4, 2, 3, 3)
> +

Why do you add this here? You have added these two new register to the
sysreg file, which should be enough.

>  #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
>  #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
>  #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)
> diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
> index 762ee084b37c..c2aea1e7fd22 100644
> --- a/arch/arm64/tools/sysreg
> +++ b/arch/arm64/tools/sysreg
> @@ -2876,6 +2876,34 @@ Sysreg	GCSPR_EL2	3	4	2	5	1
>  Fields	GCSPR_ELx
>  EndSysreg
>  
> +Sysreg	HDBSSBR_EL2	3	4	2	3	2
> +Res0	63:56
> +Field	55:12	BADDR
> +Res0	11:4
> +Enum	3:0	SZ
> +	0b0001	8KB
> +	0b0010	16KB
> +	0b0011	32KB
> +	0b0100	64KB
> +	0b0101	128KB
> +	0b0110	256KB
> +	0b0111	512KB
> +	0b1000	1MB
> +	0b1001	2MB
> +EndEnum
> +EndSysreg
> +
> +Sysreg	HDBSSPROD_EL2	3	4	2	3	3
> +Res0	63:32
> +Enum	31:26	FSC
> +	0b000000	OK
> +	0b010000	ExternalAbort
> +	0b101000	GPF
> +EndEnum
> +Res0	25:19
> +Field	18:0	INDEX
> +EndSysreg
> +
>  Sysreg	DACR32_EL2	3	4	3	0	0
>  Res0	63:32
>  Field	31:30	D15
> diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h
> index 150416682e2c..95fc6a4ee655 100644
> --- a/tools/arch/arm64/include/asm/sysreg.h
> +++ b/tools/arch/arm64/include/asm/sysreg.h
> @@ -518,6 +518,10 @@
>  #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
>  
>  #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
> +
> +#define SYS_HDBSSBR_EL2			sys_reg(3, 4, 2, 3, 2)
> +#define SYS_HDBSSPROD_EL2		sys_reg(3, 4, 2, 3, 3)
> +

Same thing here.

>  #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
>  #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
>  #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Tue Mar 11 02:47:12 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 09:47:12 +0000
Subject: [PATCH v1 2/5] arm64/kvm: support set the DBM attr during memory abort
In-Reply-To: <20250311040321.1460-3-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
	<20250311040321.1460-3-yezhenyu2@huawei.com>
Message-ID: <86wmcvoq5b.wl-maz@kernel.org>

Please follow the current convention for the subject of your patch (if
you do a git log --oneline on arch/arm64/kvm, all commit should have
the same style).

On Tue, 11 Mar 2025 04:03:18 +0000,
Zhenyu Ye <yezhenyu2 at huawei.com> wrote:
> 
> From: eillon <yezhenyu2 at huawei.com>
> 
> Since the ARMv8, the page entry has supported the DBM attribute.
> Support set the attr during user_mem_abort().

Not quite. ARMv8.1 added DBM, and that is still, to this day, an
optional functionality, including in ARMv9.5.

> 
> Signed-off-by: eillon <yezhenyu2 at huawei.com>
> ---
>  arch/arm64/include/asm/kvm_pgtable.h | 3 +++
>  arch/arm64/kvm/hyp/pgtable.c         | 6 ++++++
>  2 files changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
> index 6b9d274052c7..35648d7f08f5 100644
> --- a/arch/arm64/include/asm/kvm_pgtable.h
> +++ b/arch/arm64/include/asm/kvm_pgtable.h
> @@ -86,6 +86,8 @@ typedef u64 kvm_pte_t;
>  
>  #define KVM_PTE_LEAF_ATTR_HI_S2_XN	BIT(54)
>  
> +#define KVM_PTE_LEAF_ATTR_HI_S2_DBM	BIT(51)
> +
>  #define KVM_PTE_LEAF_ATTR_HI_S1_GP	BIT(50)
>  
>  #define KVM_PTE_LEAF_ATTR_S2_PERMS	(KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \
> @@ -252,6 +254,7 @@ enum kvm_pgtable_prot {
>  
>  	KVM_PGTABLE_PROT_DEVICE			= BIT(3),
>  	KVM_PGTABLE_PROT_NORMAL_NC		= BIT(4),
> +	KVM_PGTABLE_PROT_DBM			= BIT(5),
>  
>  	KVM_PGTABLE_PROT_SW0			= BIT(55),
>  	KVM_PGTABLE_PROT_SW1			= BIT(56),
> diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
> index df5cc74a7dd0..3ea6bdbc02a0 100644
> --- a/arch/arm64/kvm/hyp/pgtable.c
> +++ b/arch/arm64/kvm/hyp/pgtable.c
> @@ -700,6 +700,9 @@ static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot p
>  	if (prot & KVM_PGTABLE_PROT_W)
>  		attr |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
>  
> +	if (prot & KVM_PGTABLE_PROT_DBM)
> +		attr |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> +
>  	if (!kvm_lpa2_is_enabled())
>  		attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S2_SH, sh);
>  
> @@ -1309,6 +1312,9 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
>  	if (prot & KVM_PGTABLE_PROT_W)
>  		set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
>  
> +	if (prot & KVM_PGTABLE_PROT_DBM)
> +		set |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> +

Why isn't that exclusive of PROT_W?

>  	if (prot & KVM_PGTABLE_PROT_X)
>  		clr |= KVM_PTE_LEAF_ATTR_HI_S2_XN;
>  

What is driving this KVM_PGTABLE_PROT_DBM bit?

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From angelogioacchino.delregno at collabora.com  Tue Mar 11 02:47:23 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 11 Mar 2025 10:47:23 +0100
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
 <20250306085028.5024-2-axe.yang@mediatek.com>
 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
Message-ID: <b09f618a-eaf9-4258-ae2d-67eff1cb249f@collabora.com>

Il 07/03/25 07:59, Axe Yang (??) ha scritto:
> On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
>>> Add 'mediatek,disable-single-burst' setting. This property can be
>>> used to switch bus burst type, from single burst to INCR, which is
>>> determined by the bus type within the IP. Some versions of the IP
>>> are using AXI bus, thus this switch is necessary as 'single' is not
>>> the burst type supported by the bus.
>>>
>>> Signed-off-by: Axe Yang <axe.yang at mediatek.com>
>>
>> I am mostly sure that this is not something to put in devicetree, but
>> as
>> platform data for specific SoC(s), as much as I'm mostly sure that
>> all of
>> the instances of the MSDC IP in one SoC will be *all* using either
>> single
>> or INCR.
> 
> No, actually MSDC IPs in one SoC are using different versions.
> Usually MSDC1 (index from 1) is used as eMMC host, the left hosts are
> used as SD/SDIO hosts. They have similar designs, but there are still
> difference.
> 
>>
>> So, I think I know the answer but I'll still ask just to be extremely
>> sure:
>>
>> is there any MediaTek SoC that has different IP versions for
>> different MSDC
>> instances, and that hence require single burst on one instance and
>> INCR on
>> another instance?
> 
> Yes. Actually every SoC has different IP versions for eMMC and SD/SDIO
> host as I said.
> e.g. For MT8168, signel burst bit should be set to 1 for eMMC Host, but
> 0 for SD/SDIO Host.
> 
>>
>> And if there is - is there a pattern? Is it always SDIO requiring
>> INCR or
>> always eMMC/SD requiring it?
>>
>>
> 
> No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
> configured base on IP version. There is no binding relationship between
> eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
> single, same as SD/SDIO.
> 

Okay but if there are different IP versions, and AXI/AHB is determined
by the IP version, why aren't you parsing the MAIN_VER/ECO_VER registers of
the MSDC IP to check whether to use INCR or SINGLE?

Cheers,
Angelo

> 
> Regards,
> Axe
> 
> 
>>
>>> ---
>>>    Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8 ++++++++
>>>    1 file changed, 8 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>> b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>> index 0debccbd6519..6076aff0a689 100644
>>> --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>> +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>> @@ -100,6 +100,14 @@ properties:
>>>        minimum: 0
>>>        maximum: 0xffffffff
>>>
>>> +  mediatek,disable-single-burst:
>>> +    $ref: /schemas/types.yaml#/definitions/flag
>>> +    description:
>>> +      Burst type setting. For some versions of the IP that do not
>>> use
>>> +      AHB bus, the burst type need to be switched to INCR.
>>> +      If present, use INCR burst type.
>>> +      If not present, use single burst type.
>>> +
>>>      mediatek,hs200-cmd-int-delay:
>>>        $ref: /schemas/types.yaml#/definitions/uint32
>>>        description:
>>
>>
>>



From kelvin.zhang at amlogic.com  Tue Mar 11 02:48:26 2025
From: kelvin.zhang at amlogic.com (Kelvin Zhang)
Date: Tue, 11 Mar 2025 17:48:26 +0800
Subject: [PATCH v3 1/3] dt-bindings: reset: Add compatible for Amlogic
 A4/A5 Reset Controller
In-Reply-To: <20240918-delirious-skiing-224172be96d4@squawk>
References: <20240918074211.8067-1-zelong.dong@amlogic.com>
 <20240918074211.8067-2-zelong.dong@amlogic.com>
 <a5d9b775dd860d8f2bbf174300a2e3161b654035.camel@pengutronix.de>
 <20240918-delirious-skiing-224172be96d4@squawk>
Message-ID: <84612c6b-621d-47cc-8a2e-41d1fa42f0fe@amlogic.com>



On 2024/9/18 16:01, Conor Dooley wrote:
> On Wed, Sep 18, 2024 at 09:51:28AM +0200, Philipp Zabel wrote:
>> On Mi, 2024-09-18 at 15:42 +0800, zelong dong wrote:
>>> From: Zelong Dong<zelong.dong at amlogic.com>
>>>
>>> Add new compatible for Amlogic A4/A5 Reset Controller
>>>
>>> Signed-off-by: Zelong Dong<zelong.dong at amlogic.com>
>>> Acked-by: Conor Dooley<conor.dooley at microchip.com>
>>> ---
>>>   .../bindings/reset/amlogic,meson-reset.yaml   | 23 ++++++++++++-------
>>>   1 file changed, 15 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>> index 695ef38a7bb3..0ad81fe7b629 100644
>>> --- a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>> +++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>> @@ -12,14 +12,21 @@ maintainers:
>>>   
>>>   properties:
>>>     compatible:
>>> -    enum:
>>> -      - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
>>> -      - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
>>> -      - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
>>> -      - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
>>> -      - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
>>> -      - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
>>> -      - amlogic,t7-reset
>>> +    oneOf:
>>> +      - items:
>> I'm not well versed in preferred dt-bindings style, but this items
>> looks superfluous to me. It only contains a single enum.
> Oh, ye. Good spot.

Hello Philipp, Conor,
Sorry for the late reply.

Do you mean to use 'amlogic,meson-s4-reset' for A4 and A5 directly, 
without the fallback?

-- 
Best regards,

Kelvin Zhang



From maz at kernel.org  Tue Mar 11 02:53:02 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 09:53:02 +0000
Subject: [PATCH v1 5/5] arm64/config: add config to control whether enable HDBSS feature
In-Reply-To: <20250311040321.1460-6-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
	<20250311040321.1460-6-yezhenyu2@huawei.com>
Message-ID: <86v7sfopvl.wl-maz@kernel.org>

On Tue, 11 Mar 2025 04:03:21 +0000,
Zhenyu Ye <yezhenyu2 at huawei.com> wrote:
> 
> From: eillon <yezhenyu2 at huawei.com>
> 
> The HDBSS feature introduces new assembly registers
> (HDBSSBR_EL2 and HDBSSPROD_EL2), which depends on the armv9.5-a
> compilation support. So add ARM64_HDBSS config to control whether
> enable the HDBSS feature.
> 
> Signed-off-by: eillon <yezhenyu2 at huawei.com>
> ---
>  arch/arm64/Kconfig                  | 19 +++++++++++++++++++
>  arch/arm64/Makefile                 |  4 +++-
>  arch/arm64/include/asm/cpufeature.h |  3 +++
>  3 files changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..3458261eb14b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2237,6 +2237,25 @@ config ARM64_GCS
>  
>  endmenu # "v9.4 architectural features"
>  
> +menu "ARMv9.5 architectural features"
> +
> +config ARM64_HDBSS
> +	bool "Enable support for Hardware Dirty state tracking Structure (HDBSS)"
> +	default y
> +	depends on AS_HAS_ARMV9_5
> +	help
> +	  Hardware Dirty state tracking Structure(HDBSS) enhances tracking
> +	  translation table descriptors? dirty state to reduce the cost of
> +	  surveying for dirtied granules.
> +
> +	  The feature introduces new assembly registers (HDBSSBR_EL2 and
> +	  HDBSSPROD_EL2), which depends on AS_HAS_ARMV9_5.

Why? You seem to be using the generated accessors everywhere, and I
can't see a need for this compiler dependency.

	M.

-- 
Without deviation from the norm, progress is not possible.


From david at redhat.com  Tue Mar 11 02:54:40 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 11 Mar 2025 10:54:40 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250310170320.GC26382@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
 <20250310170320.GC26382@redhat.com>
Message-ID: <79ec5aa9-1937-436e-8cf4-436746142f7b@redhat.com>

On 10.03.25 18:03, Oleg Nesterov wrote:
> On 03/04, David Hildenbrand wrote:
>>
>> uprobe_write_opcode() does some pretty low-level things that really, it
>> shouldn't be doing:
> 
> Agreed. Thanks again for doing this.
> 
> David, as I said, I can't review. I don't understand this mm/folio magic
> with or without your changes.
> 

No worries! Thanks for taking a look!

> However. With your changes the code looks "better" and more understandable
> to me. So I'd vote for your patches even if I can't ack them.
> 
> But I'd like to ask some stupid (no, really) questions.
> __uprobe_write_opcode() does:
> 
> 	/* We're done if we don't find an anonymous folio when unregistering. */
> 	if (!folio_test_anon(folio))
> 		return is_register ? -EFAULT : 0;
> 
> Yes, but we do not expect !folio_test_anon() if register == true, right?
 > See also below.>
> 	/* Verify that the page content is still as expected. */
> 	if (verify_opcode(fw->page, opcode_vaddr, &opcode) <= 0) {
> 		set_pte_at(vma->vm_mm, vaddr, fw->ptep, fw->pte);
> 		return -EAGAIN;
> 	}
> 
> The caller, uprobe_write_opcode(), has already called verify_opcode(),
> why do we need to re-check?

Regarding both questions, the code is fairly racy. Nothing would stop 
user space from (a) modifying that memory (b) zapping the anon page 
using MADV_DONTNEED (if we don't hold the mmap lock in write mode).

Regarding the latter, uprobe_write_opcode() is documented to: "Called 
with mm->mmap_lock held for read or write.".

Note that both checks are fairly cheap.

> 
> But whatever reason we have. Can we change uprobe_write_opcode() to
> "delay" put_page() and instead of

I was debating with myself whether we should do that and went back and 
forth a couple of times.

> 
> 	/* Walk the page tables again, to perform the actual update. */
> 	folio = folio_walk_start(&fw, vma, vaddr, 0);
> 	if (folio) {
> 		ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr,
> 					    opcode);
> 		folio_walk_end(&fw, vma);
> 	} else {
> 		ret = -EAGAIN;
> 	}
> 
> do something like
> 
> 	/* Walk the page tables again, to perform the actual update. */
> 	ret = -EAGAIN;
> 	folio = folio_walk_start(&fw, vma, vaddr, 0);
> 	if (folio) {
> 		if (fw.page == page) {
> 			WARN_ON(is_register && !folio_test_anon(folio));

Yes, that would work (we could leave the WARN_ON in 
__uprobe_write_opcode), but I am not sure if the end result is better 
better. No strong opinion on the details though.

> 			ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr,
> 					            opcode);
> 		}
> 		folio_walk_end(&fw, vma);
> 	}
> 
> ?
> 
> Once again, I am not trying to review. I am trying to understand the
> basics of your code.

Any feedback is welcome, thanks!

-- 
Cheers,

David / dhildenb



From maz at kernel.org  Tue Mar 11 02:59:50 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 09:59:50 +0000
Subject: [PATCH v1 3/5] arm64/kvm: using ioctl to enable/disable the HDBSS feature
In-Reply-To: <20250311040321.1460-4-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
	<20250311040321.1460-4-yezhenyu2@huawei.com>
Message-ID: <86tt7zopk9.wl-maz@kernel.org>

+1 on everything Oliver said. Additionally:

On Tue, 11 Mar 2025 04:03:19 +0000,
Zhenyu Ye <yezhenyu2 at huawei.com> wrote:
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 1f55b0c7b11d..9c11e2292b1e 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1703,6 +1703,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  	if (writable)
>  		prot |= KVM_PGTABLE_PROT_W;
>  
> +	if (kvm->enable_hdbss && logging_active)
> +		prot |= KVM_PGTABLE_PROT_DBM;
> +

This looks totally wrong. If the page is defined as R/O
(KVM_PGTABLE_PROT_W not being set), setting the DBM flag makes it
writable anyway (the W bit is the Dirty bit). Hello, memory
corruption?

overall, this patch is a total mess, and needs to be split to have the
runtime logic on one side, and the userspace API on the other. Don't
mix the two.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From boris.brezillon at collabora.com  Tue Mar 11 03:05:20 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 11 Mar 2025 11:05:20 +0100
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <16f6a6e2-4dce-4af9-bc0a-61c4d6213f02@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
	<20250310195921.157511-5-ariel.dalessandro@collabora.com>
	<20250311090545.3b941567@collabora.com>
	<16f6a6e2-4dce-4af9-bc0a-61c4d6213f02@collabora.com>
Message-ID: <20250311110520.6b79e090@collabora.com>

On Tue, 11 Mar 2025 10:14:44 +0100
AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
wrote:

> Il 11/03/25 09:05, Boris Brezillon ha scritto:
> > On Mon, 10 Mar 2025 16:59:19 -0300
> > Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> >   
> >> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> >> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> >> Address Extension", which in Linux we've called "mali_lpae".
> >>
> >> This commit adds support for conditionally enabling AARCH64_4K page
> >> table format. To achieve that, a "GPU optional configurations" field was
> >> added to `struct panfrost_features` with the related flag.
> >>
> >> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> >> the HW_FEATURE_AARCH64_MMU feature flag present.
> >>
> >> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> >> ---
> >>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
> >>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
> >>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
> >>   3 files changed, 169 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> >> index cffcb0ac7c111..0385702aa43c7 100644
> >> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> >> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> >> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
> >>   	GPU_PM_VREG_OFF,
> >>   };
> >>   
> >> +/**
> >> + * enum panfrost_gpu_config - GPU optional configurations
> >> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
> >> + */
> >> +enum panfrost_gpu_config {
> >> +	GPU_CONFIG_AARCH64_4K,
> >> +};
> >> +
> >>   struct panfrost_features {
> >>   	u16 id;
> >>   	u16 revision;
> >> @@ -95,6 +103,9 @@ struct panfrost_compatible {
> >>   
> >>   	/* Allowed PM features */
> >>   	u8 pm_features;
> >> +
> >> +	/* GPU features */
> >> +	u8 gpu_configs;  
> > 
> > I would probably name this gpu_quirks, with the GPU_CONFIG_AARCH64_4K
> > flag renamed GPU_QUIRK_FORCE_AARCH64_PAGE_TABLE.
> >   
> 
> Boris, at this point the quirk should be LPAE, not AARCH64_4K, because the
> former is legacy...

It's legacy, but it's also the default in this driver. And just because
it's legacy doesn't mean it's broken :P. As Steve mentioned, there are
perf considerations to take into account, and on some platforms (most?),
it's preferable to use the legacy format because of that.

> 
> I think that Ariel is right in this, as in, that's a capability of the GPU
> MMU, so if anything I would rather rename it to gpu_capabilities,

No, GPU capabilities are extracted from he GPU ID, and all Bifrost GPUs
support the aarch64 page table format. But what matters here is GPUs
that can't use the legacy page table format because it's to limited to
express the cacheability/shareability properties.

> but then
> that'd be confusing for other stuff - which means that gpu_configs is most
> probably the least confusing and/or most appropriate name for this.

Again, it's not a random configuration decision, it's something we do
because the default (legacy page table format) doesn't work, so I keep
thinking quirk is an appropriate name in this context.

Regards,

Boris


From amadeus at jmu.edu.cn  Tue Mar 11 03:00:16 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 11 Mar 2025 18:00:16 +0800
Subject: [PATCH 2/2] phy: rockchip: inno-usb2: add usb2 phy support for rk3562
In-Reply-To: <20241224094240.3817261-2-kever.yang@rock-chips.com>
References: <20241224094240.3817261-2-kever.yang@rock-chips.com>
Message-ID: <20250311100016.841525-1-amadeus@jmu.edu.cn>

Hi,

> This adds vbus detection function control and make the below tuning
> to enhance the usb2-phy SQ for RK3562 SoC.
>  - enable pre-emphasis during non-chirp phase
>  - set HS eye height to 425mv
>  - turn off differential receiver by default to save power

This is implemented by the rk3562_usb2phy_tuning function. Since
this is missing, I think the commit message needs to be changed.

Thanks,
Chukun

--
2.25.1



From pankaj.gupta at nxp.com  Tue Mar 11 08:39:31 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:31 +0530
Subject: [PATCH v13 0/5] v13: firmware: imx: driver for NXP secure-enclave
Message-ID: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>

5/5
- Updated the commit message for imperative mood.
- Remove the usage of macros- NODE_NAME, GET_ASCII_TO_U8, GET_IDX_FROM_DEV_NODE_NAME.
- Clean-up the return path by replacing "ret = -<err>; return ret;" with "return -<err>;"
- Clean-up the return path by replacing "ret = -<err>; goto exit;" with "return -<err>;"
- Removed goto statements from the entire driver, where there is no common code at function's exit.
- Fixes the check-patch erros reported with flag "--strict"
- Replaced devm_add_action, with devm_add_action_or_reset
- Removed the un-necesary and obvious code comments.
- Removed dev_probe_err at the exit of function se_if_probe().

4/5
- Clean-up the return path by replacing "ret = -<err>; return ret;" with "return -<err>;"
- Clean-up the return path by replacing "ret = -<err>; goto exit;" with "return -<err>;"
- Removed goto statements from the entire driver, where there is no common code at function's exit.
- fixes the check-patch erros reported with flag "--strict"
- removed the un-necesary and obvious code comments.
- variable received msg timeout to be different at boot-up & suspend/resume and send/recv ioctlis.

3/5
- compatible string is modified from "fsl,imx8ulp-se" to "fsl,imx8ulp-se-ele-hsm".
- updated the alias name.

2/5
- compatible string is modified from "fsl,imx8ulp-se" to "fsl,imx8ulp-se-ele-hsm".
- compatible string is modified from "fsl,imx93-se" to "fsl,imx93-se-ele-hsm".
- compatible string is modified from "fsl,imx95-se" to "fsl,imx95-se-ele-hsm".
- Mis-understood the +1 from Conor. Hence dropped the Reviewed-by tag.
- Collected Rob's R-b tag on v7 (https://lore.kernel.org/all/172589152997.4184616.5889493628960272898.robh at kernel.org/)

1/5
- No change

Reference:
- Link to v12: https://lore.kernel.org/r/20250120-imx-se-if-v12-0-c5ec9754570c at nxp.com

Changes in v12:

5/5
- increased the wait-timeout.

4/5
- rename flag "handle_susp_resm" to "imem_mgmt"
- moved the buffer allocation ot load_fw->imem.buf, to se_probe_if.
- setting imem state at initialization.

3/5
- No change

2/5
- No change

1/5
- No change

Reference:
- Link to v11: https://lore.kernel.org/r/20241220-imx-se-if-v11-0-0c7e65d7ae7b at nxp.com

Changes in v11:

5/5
- devname is constructed by concatinating get_se_if_name(se_if_id) & se_if_instance_id.
- ele_rcv_msg(), is updated to add the wait_interruptible_timeout for the non-NVM-Daemon message exchanges, such that in case of no response from FW,
  Linux donot hangs.
- added a new helper function get_se_if_name(), to return the secure-enclave interface owner's name string.
- added a new helper function get_se_soc_id(), to return the secure-enclave's SoC id.

4/5
- moved the se_if_node_info member "soc_register", to the struct "se_if_node_info_list"; as soc registration done once, not per interface.
- moved the se_if_node_info member "se_fetch_soc_info", to the struct "se_if_node_info_list"; as soc info fetching is done once, not per interface.
- Added two member variable se_if_id and se_if_instance_id to struct se_if_defines.
- removed the member "se_name" from struct "se_if_node_info". Rather, it will constructed by concatinating get_se_if_name(se_if_id) & se_if_instance_id.
- moved the static global variable "se_version", to the newly created structure "struct se_var_info".
- moved the member "struct se_fw_load_info load_fw" of "se_if_node_info_list", to the newly created structure "struct se_var_info".
- Replaced RUNTIME_PM_OPS with SET_SYSTEM_SLEEP_PM_OPS, in power-managment ops.

3/5
- No change

2/5
- No change

1/5
- No change

Reference:
- Link to v10: https://lore.kernel.org/r/20241104-imx-se-if-v10-0-bf06083cc97f at nxp.com

v10: firmware: imx: driver for NXP secure-enclave

Changes in v10:
5/5
- replaced the u8, u16, u32, u64, with __u8, __u16, __u32, __u64 in
  'include/uapi/linux/se_ioctl.h'.

4/5
- No change

3/5
- No change

2/5
- No change

1/5
- No change

Reference:
- Link to v9: https://lore.kernel.org/r/20241016-imx-se-if-v9-0-fd8fa0c04eab at nxp.com

Changes in v9:

4/5
- change se_if_remove function signature, required after rebase to v6.12-rc1.
- move the info->macros to a structure "struct se_if_defines if_defs".
- Removed "info" from "struct se_if_defines if_defs".
- Moved "mem_pool" from "struct se_if_defines if_defs" to "priv".
- Fetching "info" using container-of.

5/5
- Fetching "info" using container-of.
- Fixed issue reported by sparse.

Reference:
- Link to v8: https://lore.kernel.org/r/20241015-imx-se-if-v8-0-915438e267d3 at nxp.com

Changes in v8:

5/5
- Remove the check for SE_IF_CTX_OPENED.
- replaced dev_ctx->priv-dev, priv->dev, whereever possible.
- func "if_misc_deregister" moved before func "init_device_context".
- func "init_device_context" before func "se_ioctl_cmd_snd_rcv_rsp_handler".
- func "se_if_fops_write" and "se_if_fops_read", are moved after func "se_ioctl_get_mu_info".
- non static functions "se_dev_ctx_cpy_out_data, se_dev_ctx_shared_mem_cleanup & init_device_context" are moved static and local scope.
- Removed back & forth between the two structs "struct se_if_device_ctx *dev_ctx" and "struct se_shared_mem_mgmt_info *se_shared_mem_mgmt"
- removed the NULL check for bdesc.
- fops_open, is corrected for acquiring the fops_lock.
- Fops_close, mutex unlock is removed. Infact check for waiting_rsp_clbk_hdl.dev_ctx, is removed.
- sema_init(&dev_ctx->fops_lock, 1);, replaced with Mutex.
- structure member se_notify, is removed.

4/5
- removed initializing err to zero in func ele_fetch_soc_info(),
- replaced 'return 0', with 'goto exit', if the condition (!priv->mem_pool) is true.
- replaced "struct *dev" with "struct se_if_priv *priv", in base_message API(s) and others.
- Created a separate structure "struct se_if_defines" to maintain interface's fixed values like cmd_tag, rsp_tag, success_tag etc.
- removed the macros "WORD_SZ", "SOC_VER_MASK", "DEFAULT_IMX_SOC_VER", "RESERVED_DMA_POOL".
- Added handling for "ctrl+c", by postponing the interrupt, till the response to the "command in flight" is received.
- Removed the mutext lock "se_if_lock".
- furnction prototype for "se_save_imem_state" and "se_restore_imem_state", is changed to pass "imem" by reference.
- Added a new structure "struct se_fw_load_info", dedicated to contain FW loading relevant info. It is a member of struct info_list.
- split "imem_mgmt_file_in_rfs" into two "prim_fw_nm_in_rfs" and "seco_fw_nm_in_rfs", to be part of "struct se_fw_load_info".
- moved the function "se_load_firmware" prior to func "if_mbox_free_channel".
- function "se_load_firmware" is updated to use "request_firmware", instead of "request_firmware_no_wait".
- function "se_load_firmware" is updated to load "primary" fw image, if the imem_state is not BAD. Then load the "secondary FW" image.
- Added a new mutex_lock in the function "se_load_firmware", for ensuring FW loading done once, when there are multiple application are in play.
- instead of "wait_queue_head_t wq", used "sruct completion".
- add devm_add_action with action as se_if_probe_cleanup.

Reference:
- Link to v7: https://lore.kernel.org/r/20240904-imx-se-if-v7-0-5afd2ab74264 at nxp.com

Changes in v7:

5/5
- struct se_clbk_handle, is added with a member struct se_if_device_ctx *dev_ctx.
- func call to ele_miscdev_msg_rcv() & ele_miscdev_msg_send(), are removed.
- func se_ioctl_cmd_snd_rcv_rsp_handler(), is modified to remove the func call to ele_miscdev_msg_rcv() & ele_miscdev_msg_send()
- func se_ioctl_cmd_snd_rcv_rsp_handler is callig func ele_msg_send_rcv(), instead.
- Mutext "se_cmd_if_lock", handling is removed from this patch.
- func ele_miscdev_msg_send() is replaced with func ele_msg_send(), in fops_write.
- func ele_miscdev_msg_rcv() is replaced with func ele_msg_rcv(), in fops_read.
- fops_open is modified to create the new dev_ctx instance (using func init_device_context()), which is not registered as miscdev.
- Only one dev_ctx is registered as miscdev and its reference is stored in the struct se_if_priv, as priv_dev_ctx.
- Separate func cleanup_se_shared_mem() & func init_se_shared_mem(), for shared memory handling part of struct dev_ctx.
- Input param for func(s) ele_msg_rcv(), ele_msg_send() & ele_msg_send_rcv(), is replaced from struct se_if_priv to struct se_if_device_ctx.

4/5
- A new structure is defined name struct "se_clbk_handle", to contain members processed in mailbox call-back function.
- "struct se_if_priv" is modified to contain the two structures of "se_clbk_handle" - waiting_rsp_clbk_hdl & cmd_receiver_clbk_hdl.
- func ele_msg_rcv() is modified to take a new additional input reference param "struct se_clbk_handle *se_clbk_hdl".
- func ele_msg_send() is modified to take a new additional input tx_msg_sz.
- func ele_msg_send_rcv(), is modified to take 2 more inputs - tx_msg_sz & exp_rx_msg_sz.
- func se_val_rsp_hdr_n_status(), is modified to take input of rx_msg buffer, instead of header value, as input param.
- each caller of the func ele_msg_send_rcv(), is sending these two additional input params.
- func se_if_callback(), is modified to work on two structures of "se_clbk_handle" - waiting_rsp_clbk_hdl & cmd_receiver_clbk_hdl.
- Variable "max_dev_ctx", is removed from info & priv struture, as well its usage.
- New member variable "se_img_file_to_load", is added to structure "priv".
- Other member variables - rx_msg(ptr), rx_msg_sz, completion done & list of dev_ctxs, is removed from priv struture, along with their usage.
- func se_resume(), updated to wakeup the two "wq", part of "struct se_clbk_handle": priv->waiting_rsp_clbk_hdl & priv->cmd_receiver_clbk_hdl.

3/5
- Node name is changed from senclave-firmware at 0 to "secure-enclave"

2/5
- Node name is changed to "secure-enclave".

Reference:
- Link to v6: https://lore.kernel.org/r/20240722-imx-se-if-v6-0-ee26a87b824a at nxp.com

Changes in v6:

5/5
- replaced scope_gaurd with gaurd.

4/5
- replaced scope_gaurd with gaurd.
- remove reading the regs property from dtb.
- Added NULL check for priv data fetched from device, as a sanity check, for ele_base_msg apis)

3/5
- replace firmware with senclave-firmware.

2/5
- replace firmware with senclave-firmware.
- drop description for mbox
- Replaced "items:" with maxItems:1 for "memory-region"
- Replaced "items:" with maxItems:1 for "sram"
- remove regs property.
- remove "$nodename"

Reference:
- Link to v5: https://lore.kernel.org/r/20240712-imx-se-if-v5-0-66a79903a872 at nxp.com

Changes in v5:

2/5
- updated the description of mboxes
- updated the description & items for mbox-names.
- updated the description of memory-region
- move "additional properties: false" after allOf block.
- removed other example except one.

4/5
- Corrected the indentation in Kconfig.
- info members:mbox_tx_name & mbox_rx_name, are replaced with macros.

5/5
- Replaced "for  secure enclaves", with "for secure enclaves"
- Replaced "user space" with "userspace".
- End the line "[include]<linux/firmware/imx/ele_mu_ioctl.h>" with a period.

Reference:
- Link to v4: https://lore.kernel.org/r/20240705-imx-se-if-v4-0-52d000e18a1d at nxp.com

Changes in v4:

1/5
a. Removed - from EdgeLock Enclave.

b. Removed , after "Each of the above feature,"

c. replace "can exists" with "can exist".

d.
-messaging units(MU) per SE. Each co-existing 'se' can have one or multiple exclusive
-MU(s), dedicated to itself. None of the MU is shared between two SEs.
+messaging units(MU) per SE. Each co-existing SE can have one or multiple exclusive
+MUs, dedicated to itself. None of the MU is shared between two SEs.
 Communication of the MU is realized using the Linux mailbox driver.

e.
-All those SE interfaces 'se-if' that is/are dedicated to a particular SE, will be
-enumerated and provisioned under the very single 'SE' node.
+Although MU(s) is/are not shared between SE(s). But for SoC like i.MX95 which has
+multiple SE(s) like HSM, V2X-HSM, V2X-SHE; all the SE(s) and their interfaces 'se-if'
+that is/are dedicated to a particular SE will be enumerated and provisioned using the
+single compatible node("fsl,imx95-se").

f. Removed ",". Replaced for "Each 'se-if'," with "Each se-if'.

g. removed ","
-  This layer is responsible for ensuring the communication protocol, that is defined
+  This layer is responsible for ensuring the communication protocol that is defined

h. removed "-"
-  - FW can handle one command-message at a time.
+  - FW can handle one command message at a time.

i.
-  Using these multiple device contexts, that are getting multiplexed over a single MU,
-  user-space application(s) can call fops like write/read to send the command-message,
-  and read back the command-response-message to/from Firmware.
-  fops like read & write uses the above defined service layer API(s) to communicate with
+  Using these multiple device contexts that are getting multiplexed over a single MU,
+  userspace application(s) can call fops like write/read to send the command message,
+  and read back the command response message to/from Firmware.
+  fops like read & write use the above defined service layer API(s) to communicate with
   Firmware.

j. Uppercase for word "Linux".

2/5
a. Rephrased the description to remove list of phandles.

b. Moved required before allOf:
+required:
+  - compatible
+  - reg
+  - mboxes
+  - mbox-names
+
+additionalProperties: false
+
 allOf:

c. replaced not: required: with properties: <property-name>: false.
   # memory-region
-      not:
-        required:
-          - memory-region
+      properties:
+        memory-region: false

   # sram
-    else:
-      not:
-        required:
-          - sram

d. Reduced examples. keeping example of i.MX95.
e. node-name is changed to "firmware@<hex>"

3/5
- node name changed to "firmware@<hex>".

4/5
- used sizeof(*s_info)
- return early, rather than doing goto exit, in ele_get_info().
- Use upper_32_bits() and lower_32_bits()
- use rx_msg here instead of priv->rx_msg
- Moved the status check to validate_rsp_hdr. Rename the function to "se_val_rsp_hdr_n_status"
- typecasting removed header = (struct se_msg_hdr *) msg;
- Converted the API name with prefix imx_ele_* or imx_se_*, to ele_* and se_*, respectively.
- Removed the functions definition & declaration for: free_phybuf_mem_pool() & get_phybuf_mem_pool()
- removed the mbox_free_channel() calls from clean-up.
- Flag "priv->flags" is removed.
- Converted the int se_if_probe_cleanup() to void se_if_probe_cleanup().
- Replaced NULL initialization of structure members: priv->cmd_receiver_dev & priv->waiting_rsp_dev , with comments.
- Removed the function's declaration get_phy_buf_mem_pool1

5/5
Changes to Documentation/ABI/testing/se-cdev.
a. Removed "-" from "secure-enclave" and "file-descriptor".

b. Removed "-" from "shared-library"

c. Replaced "get" with "getting".

d. Added description for the new IOCTL "send command and receive command response"

e. Replaced "wakeup_intruptible" with "wait_event_interruptible"

f. Removed ";"

g. Removd "," from "mailbox_lock,"

h. Replaced "free" with "frees"

i. In mailbox callback function, checking the buffer size before
copying.

Reference:
- Link to v3: https://lore.kernel.org/r/20240617-imx-se-if-v3-0-a7d28dea5c4a at nxp.com

Changes in v3:
5/5:
- Initialize tx_msg with NULL.
- memdup_user() returns an error pointer, not NULL. correct it by adding check for err_ptr.
- new IOCTL is added to send & recieve the message.
- replaced the while loop till list is empty, with list_for_each_entry.
- replaced __list_del_entry, with list_del.
- Removed the dev_err message from copy to user.
- Removed the casting of void *.
- corrected the typcasting in copy to user.
- removed un-necessary goto statement.
- Removed dead code for clean-up of memory.
- Removed un-mapping of secured memory
- Passing se_if_priv structure to init_device_context.
- Updated the below check to replace io.length with round_up(io.length).
	if (shared_mem->size < shared_mem->pos|| io.length >= shared_mem->size - shared_mem->pos)
- Created a function to cleanup the list of shared memory buffers.
- Used list_for_each_entry_safe(). created a separate functions: se_dev_ctx_cpy_out_data() & se_dev_ctx_shared_mem_cleanup()

4/5
- Changed the compatible string to replace "-ele", to "-se".
- Declaration of imx_se_node_info, is done as const in the whole file
- Remove the unused macros from ele_base_msg.h
- Remove the function declaration get_phy_buf_mem_pool1, from the header file.
- Replace the use of dmam_alloc_coherent to dma_alloc_coherent
- Check for function pointer, before calling the fucntion pointer in imx_fetch_se_soc_info
- Removed the unused flag for SE_MU_IO_FLAGS_USE_SEC_MEM.
-  Removed the unused macros WORD_SZ
- instead of struct device *dev, struct se_if_priv *priv, is used as argument to the funtions:se_save_imem_state, se_restore_imem_state, imx_fetch_se_soc_info
- Removed ret from validate_rsp_hdr.
- changed the prefix of the funtion: plat_add_msg_crc and plat_fill_cmd_msg_hdr.
- indentation correction for info structures.
- remove the check for priv not null from se_if_probe_cleanup
- Removed the casting of void *.
- se_load_firmware function is corrected for not freeing the buffer when allocation fails.
- Checking if get_imx_se_node_info() can return NULL, in se_if_probe()
- imem.size has type u32. return value from se_save_imem_state() will be assigned to imem.size in case of success only.
- removed the flag un-setting in case of failure. priv->flags &= (~RESERVED_DMA_POOL);
- removed the function call for devm_of_platform_populate(dev);
- Checking for not-NULL,  before calling the funtion pointer se_fetch_soc_info.
- Removed the checking for reserved memory flag, before freeing up the reserved memory, in se_probe_if_cleanup.

3/5
- Changed the compatible string to replace "-ele", to "-se".

2/5
- to fix the warning error, replaced the "-ele" & "-v2x" in compatible string, to "-se".
- Added an example for ele at 0 for compatible string "fsl,imx95-se"

Reference
- Link to v2: https://lore.kernel.org/r/20240523-imx-se-if-v2-0-5a6fd189a539 at nxp.com

Changes in v2:

4/4
- Split this patch into two: 1. base driver & 2. Miscdev
- Initialize the return variable "err" as 0, before calling 'return err', in the file ele_common.c
- Fix the usage of un-iniitialized pointer variable, by initializing them with NULL, in ele_base_msg.c.
- Fix initializing the ret variable, to return the correct error code in case of issue.
- replaced dmam_alloc_coherent with dma_alloc_coherent.
- Replace the use of ELE_GET_INFO_READ_SZ, with sizeof(soc_info).
- Replaced -1 with -EPERM
- Removed the safety check on func-input param, in ele_get_info().
- fix the assigning data[1] with lower 32 address, rather than zero, for ele_fw_authenticate API.
- Correctly initializing the function's return error code, for file  ele_base_msg.c.
- replaced 'return' with 'goto'.
- Use length in bytes.
- Corrected the structure se_msg_hdr.
- Moved setting of rx_msg  to priv, into the function imx_ele_msg_send_rcv
- Will add lockdep_assert_held, to receive path, in v2.
- corrected the spacing at "ret  = validate_rsp_hdr"
- FIELD_GET() used for RES_STATUS
- Re-write the structure soc_info, matching the information provided in response to this api.
- The "|" goes to the end of the previous line.
- Moved the locking and unlocking of the command lock to the caller of the function.
- removed the safety check for device private data.
- Structure memory reference, used to read message header.
- In the interrupt call back function, remove assigning waiting_rsp_dev to NULL, in case of response message rcv from FW.
- do while removed.
- replaced BIT(1) for RESERVED_DMA_POOL, to BIT(0)
- The backslash is removed while assigning the file name with absolute path to structure variable.fw_name_in_rfs =.
- Update the 'if' condition by removing "idx < 0".
- mbox_request_channel_byname() uses a "char" for the name not a u8. Corrected.
- devm managed resources, are not cleaned now, in function se_probe_if_cleanup
- Used dev_err_probe().
- Used %pe to print error string.
- remove "__maybe_unused" for "struct platform_device *enum_plat_dev __maybe_unused;"
- used FIELD_GET(), for  RES_STATUS. Removed the use of MSG_TAG, MSG_COMMAND, MSG_SIZE, MSG_VER.
- Depricated the used of member of struct se_if_priv, bool no_dev_ctx_used;
- Moved the text explaing the synchronization logic via mutexes, from patch 1/4 to se_ctrl.h.
- removed the type casting of info_list = (struct imx_se_node_info_list *) device_get_match_data(dev->parent);
- Used static variable priv->soc_rev in the se_ctrl.c, replaced the following condition: if (info_list->soc_rev) to if (priv->soc_rev) for checking if this flow is already executed or not.
- imx_fetch_soc_info will return failure if the get_info function fails.
- Removed devm_free from imx_fetch_soc_info too.

3/3
- Made changes to move all the properties to parent node, without any child node.

2/4
- Use Hex pattern string.
- Move the properties to parent node, with no child node.
- Add i.MX95-ele to compatible nodes to fix the warning "/example-2/v2x: failed to match any schema with compatible: ['fsl,imx95-v2x']"

1/1
- Corrected the spelling from creats to creates.
- drop the braces around the plural 's' for interfaces
- written se in upper case SE.
- Replace "multiple message(s)" with messages.
- Removed too much details about locks.

Testing
- make CHECK_DTBS=y freescale/imx8ulp-evk.dtb;
- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j8  dt_binding_check DT_SCHEMA_FILES=fsl,imx-se.yaml
- make C=1 CHECK=scripts/coccicheck drivers/firmware/imx/*.* W=1 > r.txt
- ./scripts/checkpatch.pl --git <>..HEAD
- Tested the Image and .dtb, on the i.MX8ULP.

Reference
- Link to v1: https://lore.kernel.org/r/20240510-imx-se-if-v1-0-27c5a674916d at nxp.com

---
Pankaj Gupta (5):
      Documentation/firmware: add imx/se to other_interfaces
      dt-bindings: arm: fsl: add imx-se-fw binding doc
      arm64: dts: imx8ulp-evk: add nxp secure enclave firmware
      firmware: imx: add driver for NXP EdgeLock Enclave
      firmware: drivers: imx: adds miscdev

 Documentation/ABI/testing/se-cdev                  |   43 +
 .../devicetree/bindings/firmware/fsl,imx-se.yaml   |   91 ++
 .../driver-api/firmware/other_interfaces.rst       |  121 ++
 arch/arm64/boot/dts/freescale/imx8ulp-evk.dts      |   17 +-
 arch/arm64/boot/dts/freescale/imx8ulp.dtsi         |   13 +-
 drivers/firmware/imx/Kconfig                       |   13 +
 drivers/firmware/imx/Makefile                      |    2 +
 drivers/firmware/imx/ele_base_msg.c                |  373 ++++++
 drivers/firmware/imx/ele_base_msg.h                |   98 ++
 drivers/firmware/imx/ele_common.c                  |  366 ++++++
 drivers/firmware/imx/ele_common.h                  |   54 +
 drivers/firmware/imx/se_ctrl.c                     | 1272 ++++++++++++++++++++
 drivers/firmware/imx/se_ctrl.h                     |  126 ++
 include/linux/firmware/imx/se_api.h                |   14 +
 include/uapi/linux/se_ioctl.h                      |  101 ++
 15 files changed, 2701 insertions(+), 3 deletions(-)
---
base-commit: 8250927cfd6e6538b6c569926865d833ae6b5bc0
change-id: 20240507-imx-se-if-a40055093dc6

Best regards,
-- 
Pankaj Gupta <pankaj.gupta at nxp.com>



From pankaj.gupta at nxp.com  Tue Mar 11 08:39:32 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:32 +0530
Subject: [PATCH v13 1/5] Documentation/firmware: add imx/se to
 other_interfaces
In-Reply-To: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
Message-ID: <20250311-imx-se-if-v13-1-9cc6d8fd6d1c@nxp.com>

Documents i.MX SoC's Service layer and C_DEV driver for selected SoC(s)
that contains the NXP hardware IP(s) for Secure Enclaves(se) like:
- NXP EdgeLock Enclave on i.MX93 & i.MX8ULP

Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
---
 .../driver-api/firmware/other_interfaces.rst       | 121 +++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/Documentation/driver-api/firmware/other_interfaces.rst b/Documentation/driver-api/firmware/other_interfaces.rst
index 06ac89adaafb..a3a95b54a174 100644
--- a/Documentation/driver-api/firmware/other_interfaces.rst
+++ b/Documentation/driver-api/firmware/other_interfaces.rst
@@ -49,3 +49,124 @@ of the requests on to a secure monitor (EL3).
 
 .. kernel-doc:: drivers/firmware/stratix10-svc.c
    :export:
+
+NXP Secure Enclave Firmware Interface
+=====================================
+
+Introduction
+------------
+The NXP's i.MX HW IP like EdgeLock Enclave, V2X etc., creates an embedded secure
+enclave within the SoC boundary to enable features like
+ - Hardware Security Module (HSM)
+ - Security Hardware Extension (SHE)
+ - Vehicular to Anything (V2X)
+
+Each of the above feature is enabled through dedicated NXP H/W IP on the SoC.
+On a single SoC, multiple hardware IP (or can say more than one secure enclave)
+can exist.
+
+NXP SoCs enabled with the such secure enclaves(SEs) IPs are:
+i.MX93, i.MX8ULP
+
+To communicate with one or more co-existing SE(s) on SoC, there is/are dedicated
+messaging units(MU) per SE. Each co-existing SE can have one or multiple exclusive
+MUs, dedicated to itself. None of the MU is shared between two SEs.
+Communication of the MU is realized using the Linux mailbox driver.
+
+NXP Secure Enclave(SE) Interface
+--------------------------------
+Although MU(s) is/are not shared between SE(s). But for SoC like i.MX95 which has
+multiple SE(s) like HSM, V2X-HSM, V2X-SHE; all the SE(s) and their interfaces 'se-if'
+that is/are dedicated to a particular SE will be enumerated and provisioned using the
+single compatible node("fsl,imx95-se").
+
+Each 'se-if' comprise of twp layers:
+- (C_DEV Layer) User-Space software-access interface.
+- (Service Layer) OS-level software-access interface.
+
+   +--------------------------------------------+
+   |            Character Device(C_DEV)         |
+   |                                            |
+   |   +---------+ +---------+     +---------+  |
+   |   | misc #1 | | misc #2 | ... | misc #n |  |
+   |   |  dev    | |  dev    |     | dev     |  |
+   |   +---------+ +---------+     +---------+  |
+   |        +-------------------------+         |
+   |        | Misc. Dev Synchr. Logic |         |
+   |        +-------------------------+         |
+   |                                            |
+   +--------------------------------------------+
+
+   +--------------------------------------------+
+   |               Service Layer                |
+   |                                            |
+   |      +-----------------------------+       |
+   |      | Message Serialization Logic |       |
+   |      +-----------------------------+       |
+   |          +---------------+                 |
+   |          |  imx-mailbox  |                 |
+   |          |   mailbox.c   |                 |
+   |          +---------------+                 |
+   |                                            |
+   +--------------------------------------------+
+
+- service layer:
+  This layer is responsible for ensuring the communication protocol that is defined
+  for communication with firmware.
+
+  FW Communication protocol ensures two things:
+  - Serializing the messages to be sent over an MU.
+
+  - FW can handle one command message at a time.
+
+- c_dev:
+  This layer offers character device contexts, created as '/dev/<se>_mux_chx'.
+  Using these multiple device contexts that are getting multiplexed over a single MU,
+  userspace application(s) can call fops like write/read to send the command message,
+  and read back the command response message to/from Firmware.
+  fops like read & write use the above defined service layer API(s) to communicate with
+  Firmware.
+
+  Misc-device(/dev/<se>_mux_chn) synchronization protocol:
+
+                                Non-Secure               +   Secure
+                                                         |
+                                                         |
+                  +---------+      +-------------+       |
+                  | se_fw.c +<---->+imx-mailbox.c|       |
+                  |         |      |  mailbox.c  +<-->+------+    +------+
+                  +---+-----+      +-------------+    | MU X +<-->+ ELE |
+                      |                               +------+    +------+
+                      +----------------+                 |
+                      |                |                 |
+                      v                v                 |
+                  logical           logical              |
+                  receiver          waiter               |
+                     +                 +                 |
+                     |                 |                 |
+                     |                 |                 |
+                     |            +----+------+          |
+                     |            |           |          |
+                     |            |           |          |
+              device_ctx     device_ctx     device_ctx   |
+                                                         |
+                User 0        User 1       User Y        |
+                +------+      +------+     +------+      |
+                |misc.c|      |misc.c|     |misc.c|      |
+ kernel space   +------+      +------+     +------+      |
+                                                         |
+ +------------------------------------------------------ |
+                    |             |           |          |
+ userspace     /dev/ele_muXch0    |           |          |
+                          /dev/ele_muXch1     |          |
+                                        /dev/ele_muXchY  |
+                                                         |
+
+When a user sends a command to the firmware, it registers its device_ctx
+as waiter of a response from firmware.
+
+Enclave's Firmware owns the storage management, over Linux filesystem.
+For this c_dev provisions a dedicated slave device called "receiver".
+
+.. kernel-doc:: drivers/firmware/imx/se_fw.c
+   :export:

-- 
2.43.0



From pankaj.gupta at nxp.com  Tue Mar 11 08:39:33 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:33 +0530
Subject: [PATCH v13 2/5] dt-bindings: arm: fsl: add imx-se-fw binding doc
In-Reply-To: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
Message-ID: <20250311-imx-se-if-v13-2-9cc6d8fd6d1c@nxp.com>

The NXP security hardware IP(s) like: i.MX EdgeLock Enclave, V2X etc.,
creates an embedded secure enclave within the SoC boundary to enable
features like:
- HSM
- SHE
- V2X

Secure-Enclave(s) communication interface are typically via message
unit, i.e., based on mailbox linux kernel driver. This driver enables
communication ensuring well defined message sequence protocol between
Application Core and enclave's firmware.

Driver configures multiple misc-device on the MU, for multiple
user-space applications, to be able to communicate over single MU.

It exists on some i.MX processors. e.g. i.MX8ULP, i.MX93 etc.

Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../devicetree/bindings/firmware/fsl,imx-se.yaml   | 91 ++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml b/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml
new file mode 100644
index 000000000000..fa81adbf9b80
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/fsl,imx-se.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX HW Secure Enclave(s) EdgeLock Enclave
+
+maintainers:
+  - Pankaj Gupta <pankaj.gupta at nxp.com>
+
+description: |
+  NXP's SoC may contain one or multiple embedded secure-enclave HW
+  IP(s) like i.MX EdgeLock Enclave, V2X etc. These NXP's HW IP(s)
+  enables features like
+    - Hardware Security Module (HSM),
+    - Security Hardware Extension (SHE), and
+    - Vehicular to Anything (V2X)
+
+  Communication interface to the secure-enclaves(se) is based on the
+  messaging unit(s).
+
+properties:
+  compatible:
+    enum:
+      - fsl,imx8ulp-se-ele-hsm
+      - fsl,imx93-se-ele-hsm
+      - fsl,imx95-se-ele-hsm
+
+  mboxes:
+    items:
+      - description: mailbox phandle to send message to se firmware
+      - description: mailbox phandle to receive message from se firmware
+
+  mbox-names:
+    items:
+      - const: tx
+      - const: rx
+
+  memory-region:
+    maxItems: 1
+
+  sram:
+    maxItems: 1
+
+required:
+  - compatible
+  - mboxes
+  - mbox-names
+
+allOf:
+  # memory-region
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - fsl,imx8ulp-se-ele-hsm
+              - fsl,imx93-se-ele-hsm
+    then:
+      required:
+        - memory-region
+    else:
+      properties:
+        memory-region: false
+
+  # sram
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - fsl,imx8ulp-se-ele-hsm
+    then:
+      required:
+        - sram
+
+    else:
+      properties:
+        sram: false
+
+additionalProperties: false
+
+examples:
+  - |
+    secure-enclave {
+      compatible = "fsl,imx95-se-ele-hsm";
+      mboxes = <&ele_mu0 0 0>, <&ele_mu0 1 0>;
+      mbox-names = "tx", "rx";
+    };
+...

-- 
2.43.0



From eb at emlix.com  Tue Mar 11 03:17:32 2025
From: eb at emlix.com (Rolf Eike Beer)
Date: Tue, 11 Mar 2025 11:17:32 +0100
Subject: [PATCH] arm32: simplify ARM_MMU_KEEP usage
In-Reply-To: <CACRpkdaAMu9WtD3a_XXGEwMfyFx6F-a263COna13eUWB0vqbcQ@mail.gmail.com>
References: <2200295.irdbgypaU6@devpool47.emlix.com>
 <1811814.VLH7GnMWUR@devpool47.emlix.com>
 <CACRpkdaAMu9WtD3a_XXGEwMfyFx6F-a263COna13eUWB0vqbcQ@mail.gmail.com>
Message-ID: <2225298.Mh6RI2rZIc@devpool47.emlix.com>

On Dienstag, 24. Dezember 2024 20:25:19 Mitteleurop?ische Normalzeit Linus 
Walleij wrote:
> On Wed, Dec 18, 2024 at 1:13?PM Rolf Eike Beer <eb at emlix.com> wrote:
> > On Montag, 7. Oktober 2024 15:11:40 Mitteleurop?ische Normalzeit Rolf Eike
> > 
> > Beer wrote:
> > > All current users need to add a KEEP() around the argument so the value
> > > is
> > > actually kept, which doesn't feel very natural and is prone to upcoming
> > > bugs as the name suggests that this macro alone already keeps things.
> > > Move that directly into the definition.
> > > 
> > > Signed-off-by: Rolf Eike Beer <eb at emlix.com>
> > > ---
> > 
> > Ping?
> 
> Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
> 
> Please put the patch into Russell's patch tracker so he can apply it.

Ping?

It's available in the tracker here: 
  https://www.armlinux.org.uk/developer/patches/viewpatch.php?id=9439/1
-- 
Rolf Eike Beer

We are nominated for the embedded award Visit us at the embedded 
world 2025 March 11th to 13th, 2025 | Nuremberg Find us in hall 4 at 
booth 336

emlix GmbH
Headquarters: Berliner Str. 12, 37073 G?ttingen, Germany
Phone +49 (0)551 30664-0, e-mail info at emlix.com
District Court of G?ttingen, Registry Number HR B 3160
Managing Directors: Heike Jordan, Dr. Uwe Kracke
VAT ID No. DE 205 198 055
Office Berlin: Panoramastr. 1, 10178 Berlin, Germany
Office Bonn: Bachstr. 6, 53115 Bonn, Germany
http://www.emlix.com

emlix - your embedded Linux partner
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 313 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/1192de77/attachment.sig>

From suzuki.poulose at arm.com  Tue Mar 11 03:17:31 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 11 Mar 2025 10:17:31 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
Message-ID: <5ff34bd0-7823-4f31-9f13-bf60d3345b99@arm.com>

On 03/03/2025 10:17, Ryan Roberts wrote:
> On 01/03/2025 01:32, Yang Shi wrote:
>>
>>
>>
>> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>>> BBM level 2 is claimed.
>>>
>>> Add the feature and testing for it under arm_smmu_sva_supported().
>>>
>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>> ---
>>>  ? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>>>  ? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>>>  ? 4 files changed, 13 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index 63f6d356dc77..1022c63f81b2 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>>> arm64_cpu_capabilities *caps, int sco
>>>  ????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>>>  ????????????????? return false;
>>>  ????????? }
>>> -
>>> -??????? return true;
>>>  ????? } else if (scope & SCOPE_LOCAL_CPU) {
>>>  ????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>>>  ?????????? * If we have the correct MIDR, but the kernel booted on an
>>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>>> arm64_cpu_capabilities *caps, int sco
>>>  ?????????? * we have an incorrect MIDR, but the kernel booted on a
>>>  ?????????? * sufficient CPU, we will not bring up this CPU.
>>>  ?????????? */
>>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>>> +??????????? return false;
>>>  ????? }
>>>  ? -??? return false;
>>> +??? return has_cpuid_feature(caps, scope);
>>
>> Do we really need this? IIRC, it means the MIDR has to be in the allow list
>> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register set.
> 
> Miko, I think this should have been squashed into patch #1? It doesn't belong in
> this patch.
> 
> Yang, we discussed this internally and decided that we thought it was best to
> still require BBML2 being advertised in the feature register. That way if trying
> to use KVM to emulate a CPU that is in the allow list but doesn't really support
> BBML2, we won't try to use it.
> 
> But we still end up with the same problem if running on a physical CPU that
> supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So

I don't understand the problem here ? In the worst case, if we want to 
disable the BBML2 feature on a given CPU, we could provide an id-
override to reset the value of BBML2. Or provide a kernel parameter to
disable this in case we want to absolutely disable the feature on a
"distro" kernel.

Suzuki


> given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
> remove this check.
> 
> Thanks,
> Ryan
> 
> 
>>
>> Thanks,
>> Yang
>>
>>>  ? }
>>>  ? ? #ifdef CONFIG_ARM64_PAN
>>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> index 9ba596430e7c..6ba182572788 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>>>  ????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>>>  ????? }
>>>  ? +??? if (system_supports_bbml2_noabort())
>>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>>> +
>>>  ????? if ((smmu->features & feat_mask) != feat_mask)
>>>  ????????? return false;
>>>  ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3.c
>>> index 358072b4e293..dcee0bdec924 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>>> arm_smmu_device *smmu)
>>>  ????? if (FIELD_GET(IDR3_RIL, reg))
>>>  ????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>>>  ? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>>> +
>>>  ????? /* IDR5 */
>>>  ????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>>>  ? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>>> arm/arm-smmu-v3/arm-smmu-v3.h
>>> index bd9d7c85576a..85eaf3ab88c2 100644
>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>>>  ? #define ARM_SMMU_IDR3??????????? 0xc
>>>  ? #define IDR3_FWB??????????? (1 << 8)
>>>  ? #define IDR3_RIL??????????? (1 << 10)
>>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>>> +#define IDR3_BBML1??????????? (1 << 11)
>>> +#define IDR3_BBML2??????????? (2 << 11)
>>>  ? ? #define ARM_SMMU_IDR5??????????? 0x14
>>>  ? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>>>  ? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>>>  ? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>>>  ? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>>>  ????? u32??????????????? features;
>>>  ? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)
>>
> 



From sakari.ailus at linux.intel.com  Tue Mar 11 03:18:38 2025
From: sakari.ailus at linux.intel.com (Sakari Ailus)
Date: Tue, 11 Mar 2025 10:18:38 +0000
Subject: [PATCH 2/4] media: i2c: Add driver for Sony IMX728
In-Reply-To: <D8CU9UT1XQV9.3NFZ4OAQOKQG0@d3embedded.com>
References: <20250212195656.69528-1-slavine@d3embedded.com>
 <20250212195656.69528-3-slavine@d3embedded.com>
 <20250213101903.GH5888@pendragon.ideasonboard.com>
 <D8CU9UT1XQV9.3NFZ4OAQOKQG0@d3embedded.com>
Message-ID: <Z9AN_lo5T5VfshT9@kekkonen.localdomain>

Hi Sebastian,

On Mon, Mar 10, 2025 at 03:39:02PM -0400, Sebastian LaVine wrote:
> On Thu Feb 13, 2025 at 5:19 AM EST, Laurent Pinchart wrote:
> >
> > ...
> >
> >> +static const struct cci_reg_sequence imx728_wdr_12bit_3856x2176[] = {
> >
> > This table is way too big, with over 8000 entries. Some are even
> > duplicated, with identical or different values for the same register. It
> > will take more than a second at 400kHz to program this.
> >
> > At the very least I would expect a way to compact the table and make use
> > of I2C register address auto-increment. Default power-up values should
> > also likely be just dropped.
> >
> > I haven't checked in details, but doesn't this table also contain tuning
> > data for your specific camera ?
> >
> 
> In my testing, it takes around two seconds to write this table to the sensor.
> 
> I can investigate how to condense the table further, though the
> registers for this sensor are more complex than just writing values to
> addresses. The meaning of certain address writes depend on previous
> writes -- thus the "duplicated" writes you mentioned.
> 
> I do not believe this table contains tuning information for our camera
> module in particular.

The amount of the data is significantly higher than what sensors mostly
have for configuring the analogue processing and does not look like
executable code either (I've seen that, too).

Any idea what that data is?

-- 
Kind regards,

Sakari Ailus


From patchwork-bot+netdevbpf at kernel.org  Tue Mar 11 03:20:32 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 11 Mar 2025 10:20:32 +0000
Subject: [PATCH net-next v4 0/3] net: ti: icssg-prueth: Add native mode XDP
 support
In-Reply-To: <20250305101422.1908370-1-m-malladi@ti.com>
References: <20250305101422.1908370-1-m-malladi@ti.com>
Message-ID: <174168843201.3885087.2899206416205542663.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Wed, 5 Mar 2025 15:44:19 +0530 you wrote:
> This series adds native XDP support using page_pool.
> XDP zero copy support is not included in this patch series.
> 
> Patch 1/3: Replaces skb with page pool for Rx buffer allocation
> Patch 2/3: Adds prueth_swdata struct for SWDATA for all swdata cases
> Patch 3/3: Introduces native mode XDP support
> 
> [...]

Here is the summary with links:
  - [net-next,v4,1/3] net: ti: icssg-prueth: Use page_pool API for RX buffer allocation
    https://git.kernel.org/netdev/net-next/c/46eeb90f03e0
  - [net-next,v4,2/3] net: ti: icssg-prueth: introduce and use prueth_swdata struct for SWDATA
    https://git.kernel.org/netdev/net-next/c/73f7f1311866
  - [net-next,v4,3/3] net: ti: icssg-prueth: Add XDP support
    https://git.kernel.org/netdev/net-next/c/62aa3246f462

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From leo.yan at arm.com  Tue Mar 11 03:22:00 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 10:22:00 +0000
Subject: [PATCH] coresight: docs: Remove target sink from examples
In-Reply-To: <20241210144933.295798-1-james.clark@linaro.org>
References: <20241210144933.295798-1-james.clark@linaro.org>
Message-ID: <20250311102200.GJ9682@e132581.arm.com>

On Tue, Dec 10, 2024 at 02:49:28PM +0000, James Clark wrote:
> 
> Previously the sink had to be specified, but now it auto selects one by
> default. Including a sink in the examples causes issues when copy
> pasting the command because it might not work if that sink isn't
> present. Remove the sink from all the basic examples and create a new
> section specifically about overriding the default one.
> 
> Make the text a but more concise now that it's in the advanced section,
> and similarly for removing the old kernel advice.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  Documentation/trace/coresight/coresight.rst   | 41 ++++++++-----------
>  .../userspace-api/perf_ring_buffer.rst        |  4 +-
>  2 files changed, 18 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
> index d4f93d6a2d63..806699871b80 100644
> --- a/Documentation/trace/coresight/coresight.rst
> +++ b/Documentation/trace/coresight/coresight.rst
> @@ -462,44 +462,35 @@ queried by the perf command line tool:
> 
>                 cs_etm//                                    [Kernel PMU event]
> 
> -       linaro at linaro-nano:~$
> -
>  Regardless of the number of tracers available in a system (usually equal to the
>  amount of processor cores), the "cs_etm" PMU will be listed only once.
> 
>  A Coresight PMU works the same way as any other PMU, i.e the name of the PMU is
> -listed along with configuration options within forward slashes '/'.  Since a
> -Coresight system will typically have more than one sink, the name of the sink to
> -work with needs to be specified as an event option.
> -On newer kernels the available sinks are listed in sysFS under
> +provided along with configuration options within forward slashes '/' (see
> +`Config option formats`_).
> +
> +Advanced Perf framework usage
> +-----------------------------
> +
> +Sink selection
> +~~~~~~~~~~~~~~
> +
> +An appropriate sink will be selected automatically for use with Perf, but since
> +there will typically be more than one sink, the name of the sink to use may be
> +specified as a special config option prefixed with '@'.
> +
> +The available sinks are listed in sysFS under
>  ($SYSFS)/bus/event_source/devices/cs_etm/sinks/::
> 
>         root at localhost:/sys/bus/event_source/devices/cs_etm/sinks# ls
>         tmc_etf0  tmc_etr0  tpiu0

Just a minor comment.  To reflect the latest hardware, it is good to
mention the TRBE case, users should not and cannot specify TRBE as the
sink name.  The driver will give priority for TRBE by default unless
users specify other sink types.

Otherwise, this is a good polish for me.

Thanks,
Leo

> -On older kernels, this may need to be found from the list of coresight devices,
> -available under ($SYSFS)/bus/coresight/devices/::
> -
> -       root:~# ls /sys/bus/coresight/devices/
> -        etm0     etm1     etm2         etm3  etm4      etm5      funnel0
> -        funnel1  funnel2  replicator0  stm0  tmc_etf0  tmc_etr0  tpiu0
>         root at linaro-nano:~# perf record -e cs_etm/@tmc_etr0/u --per-thread program
> 
> -As mentioned above in section "Device Naming scheme", the names of the devices could
> -look different from what is used in the example above. One must use the device names
> -as it appears under the sysFS.
> -
> -The syntax within the forward slashes '/' is important.  The '@' character
> -tells the parser that a sink is about to be specified and that this is the sink
> -to use for the trace session.
> -
>  More information on the above and other example on how to use Coresight with
>  the perf tools can be found in the "HOWTO.md" file of the openCSD gitHub
>  repository [#third]_.
> 
> -Advanced perf framework usage
> ------------------------------
> -
>  AutoFDO analysis using the perf tools
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> @@ -508,7 +499,7 @@ perf can be used to record and analyze trace of programs.
>  Execution can be recorded using 'perf record' with the cs_etm event,
>  specifying the name of the sink to record to, e.g::
> 
> -    perf record -e cs_etm/@tmc_etr0/u --per-thread
> +    perf record -e cs_etm//u --per-thread
> 
>  The 'perf report' and 'perf script' commands can be used to analyze execution,
>  synthesizing instruction and branch events from the instruction trace.
> @@ -572,7 +563,7 @@ sort example is from the AutoFDO tutorial (https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgcc.gnu.org%2Fwiki%2FAutoFDO%2FTuto&data=05%7C02%7Cleo.yan%40arm.com%7C0d4875673b894a332a5508dd192a1f35%7Cf34e597957d94aaaad4db122a662184d%7C0%7C0%7C638694390923618348%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=vX1RVi4hA2gEqrVk9lvMV8UFVDzvClvUN7yILwv0788%3D&reserved=0
>         Bubble sorting array of 30000 elements
>         5910 ms
> 
> -       $ perf record -e cs_etm/@tmc_etr0/u --per-thread taskset -c 2 ./sort
> +       $ perf record -e cs_etm//u --per-thread taskset -c 2 ./sort
>         Bubble sorting array of 30000 elements
>         12543 ms
>         [ perf record: Woken up 35 times to write data ]
> diff --git a/Documentation/userspace-api/perf_ring_buffer.rst b/Documentation/userspace-api/perf_ring_buffer.rst
> index bde9d8cbc106..dc71544532ce 100644
> --- a/Documentation/userspace-api/perf_ring_buffer.rst
> +++ b/Documentation/userspace-api/perf_ring_buffer.rst
> @@ -627,7 +627,7 @@ regular ring buffer.
>  AUX events and AUX trace data are two different things.  Let's see an
>  example::
> 
> -        perf record -a -e cycles -e cs_etm/@tmc_etr0/ -- sleep 2
> +        perf record -a -e cycles -e cs_etm// -- sleep 2
> 
>  The above command enables two events: one is the event *cycles* from PMU
>  and another is the AUX event *cs_etm* from Arm CoreSight, both are saved
> @@ -766,7 +766,7 @@ only record AUX trace data at a specific time point which users are
>  interested in.  E.g. below gives an example of how to take snapshots
>  with 1 second interval with Arm CoreSight::
> 
> -  perf record -e cs_etm/@tmc_etr0/u -S -a program &
> +  perf record -e cs_etm//u -S -a program &
>    PERFPID=$!
>    while true; do
>        kill -USR2 $PERFPID
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From Matt.Coster at imgtec.com  Tue Mar 11 03:28:04 2025
From: Matt.Coster at imgtec.com (Matt Coster)
Date: Tue, 11 Mar 2025 10:28:04 +0000
Subject: [PATCH v3 02/18] dt-bindings: gpu: img: Add BXS-4-64 devicetree
 bindings
In-Reply-To: <20250311-bizarre-debonair-macaque-451c4f@krzk-bin>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f@imgtec.com>
 <20250311-bizarre-debonair-macaque-451c4f@krzk-bin>
Message-ID: <7472842f-73d5-49ad-a93e-cd3b8b66cfa3@imgtec.com>

On 11/03/2025 07:51, Krzysztof Kozlowski wrote:
> On Mon, Mar 10, 2025 at 01:10:26PM +0000, Matt Coster wrote:
>> Unlike AXE-1-16M, BXS-4-64 uses two power domains.
>>
>> Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
>> integration in the TI k3-j721s2.
>>
>> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
>> ---
>> Changes in v3:
>> - Include adding the second power domain so it's in context
>> - Remove unnecessary example
>> - Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
>> Changes in v2:
>> - Use normal reg syntax for 64-bit values
>> - Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
>> ---
>>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 34 +++++++++++++++++++++-
>>  1 file changed, 33 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> index 5c16b2881447c9cda78e5bb46569e2f675d740c4..d9409d33154d429019776ddbf9d123b33f8c9740 100644
>> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> @@ -18,6 +18,11 @@ properties:
>>                - ti,am62-gpu
>>            - const: img,img-axe-1-16m
>>            - const: img,img-rogue
>> +      - items:
>> +          - enum:
>> +              - ti,j721s2-gpu
>> +          - const: img,img-bxs-4-64
>> +          - const: img,img-rogue
>>  
>>        # This legacy combination of compatible strings was introduced early on
>>        # before the more specific GPU identifiers were used.
>> @@ -49,6 +54,7 @@ properties:
>>    power-domain-names:
>>      items:
>>        - const: a
>> +      - const: b
> 
> No, you just affected old device claiming it has two items. What's more,
> it's not synced with power-domains. Both properties must have the same
> constraints, but above power domains have "anything".

My mistake. This is tied to to my misunderstanding below.

> 
>>  
>>    dma-coherent: true
>>  
>> @@ -74,12 +80,38 @@ allOf:
>>          - power-domains
>>          - power-domain-names
>>  
>> +  # Cores with one power domain
> 
> Drop

Ack

> 
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            const: img,img-axe-1-16m
>> +    then:
>> +      properties:
>> +        power-domain-names:
>> +          minItems: 1
> 
> Drop

Ack

> 
>> +          maxItems: 1
>> +
>> +  # Cores with two power domains
> 
> Drop

Ack

> 
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            const: img,img-bxs-4-64
>> +    then:
>> +      properties:
>> +        power-domain-names:
>> +          minItems: 2
>> +          maxItems: 2
> 
> Missing constraints for power-domains.

My mistake, I misunderstood your comment on the V2 series as meaning
replace power-domains, not add to.

Thank you for taking the time to look through these patches again!

Cheers,
Matt

> 
> Best regards,
> Krzysztof
> 


-- 
Matt Coster
E: matt.coster at imgtec.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 236 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/05e39cf1/attachment.sig>

From pankaj.gupta at nxp.com  Tue Mar 11 08:39:35 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:35 +0530
Subject: [PATCH v13 4/5] firmware: imx: add driver for NXP EdgeLock Enclave
In-Reply-To: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
Message-ID: <20250311-imx-se-if-v13-4-9cc6d8fd6d1c@nxp.com>

Add driver for enabling MU based communication interface to secure-enclave.

NXP hardware IP(s) for secure-enclaves like Edgelock Enclave(ELE),
are embedded in the SoC to support the features like HSM, SHE & V2X,
using message based communication interface.

The secure enclave FW communicates with Linux over single or multiple
dedicated messaging unit(MU) based interface(s).
Exists on i.MX SoC(s) like i.MX8ULP, i.MX93, i.MX95 etc.

Other dependent kernel drivers will be:
- NVMEM: that supports non-volatile devices like EFUSES,
         managed by NXP's secure-enclave.

Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
---
 drivers/firmware/imx/Kconfig        |  13 +
 drivers/firmware/imx/Makefile       |   2 +
 drivers/firmware/imx/ele_base_msg.c | 372 ++++++++++++++++++++++++++
 drivers/firmware/imx/ele_base_msg.h |  98 +++++++
 drivers/firmware/imx/ele_common.c   | 329 +++++++++++++++++++++++
 drivers/firmware/imx/ele_common.h   |  50 ++++
 drivers/firmware/imx/se_ctrl.c      | 503 ++++++++++++++++++++++++++++++++++++
 drivers/firmware/imx/se_ctrl.h      |  83 ++++++
 include/linux/firmware/imx/se_api.h |  14 +
 9 files changed, 1464 insertions(+)

diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index c964f4924359..8a487df77976 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -33,3 +33,16 @@ config IMX_SCMI_MISC_DRV
 	  core that could provide misc functions such as board control.
 
 	  This driver can also be built as a module.
+
+config IMX_SEC_ENCLAVE
+	tristate "i.MX Embedded Secure Enclave - EdgeLock Enclave Firmware driver."
+	depends on IMX_MBOX && ARCH_MXC && ARM64
+	select FW_LOADER
+	default m if ARCH_MXC
+
+	help
+	  It is possible to use APIs exposed by the iMX Secure Enclave HW IP called:
+	  - EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93),
+	    like base, HSM, V2X & SHE using the SAB protocol via the shared Messaging
+	    Unit. This driver exposes these interfaces via a set of file descriptors
+	    allowing to configure shared memory, send and receive messages.
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 8d046c341be8..4e1d2706535d 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_IMX_DSP)		+= imx-dsp.o
 obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o
 obj-${CONFIG_IMX_SCMI_MISC_DRV}	+= sm-misc.o
+sec_enclave-objs		= se_ctrl.o ele_common.o ele_base_msg.o
+obj-${CONFIG_IMX_SEC_ENCLAVE}	+= sec_enclave.o
diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
new file mode 100644
index 000000000000..eea86f50d276
--- /dev/null
+++ b/drivers/firmware/imx/ele_base_msg.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/types.h>
+
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/genalloc.h>
+
+#include "ele_base_msg.h"
+#include "ele_common.h"
+
+#define FW_DBG_DUMP_FIXED_STR		"\nELEX: "
+
+int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
+{
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	dma_addr_t get_info_addr = 0;
+	u32 *get_info_data = NULL;
+	int ret = 0;
+
+	if (!priv)
+		return -EINVAL;
+
+	memset(s_info, 0x0, sizeof(*s_info));
+
+	tx_msg = kzalloc(ELE_GET_INFO_REQ_MSG_SZ, GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	rx_msg = kzalloc(ELE_GET_INFO_RSP_MSG_SZ, GFP_KERNEL);
+	if (!rx_msg)
+		return -ENOMEM;
+
+	if (priv->mem_pool)
+		get_info_data = gen_pool_dma_alloc(priv->mem_pool,
+						   ELE_GET_INFO_BUFF_SZ,
+						   &get_info_addr);
+	else
+		get_info_data = dma_alloc_coherent(priv->dev,
+						   ELE_GET_INFO_BUFF_SZ,
+						   &get_info_addr,
+						   GFP_KERNEL);
+	if (!get_info_data) {
+		dev_dbg(priv->dev,
+			"%s: Failed to allocate get_info_addr.\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	ret = se_fill_cmd_msg_hdr(priv,
+				  (struct se_msg_hdr *)&tx_msg->header,
+				  ELE_GET_INFO_REQ,
+				  ELE_GET_INFO_REQ_MSG_SZ,
+				  true);
+	if (ret)
+		goto exit;
+
+	tx_msg->data[0] = upper_32_bits(get_info_addr);
+	tx_msg->data[1] = lower_32_bits(get_info_addr);
+	tx_msg->data[2] = sizeof(*s_info);
+	ret = ele_msg_send_rcv(priv,
+			       tx_msg,
+			       ELE_GET_INFO_REQ_MSG_SZ,
+			       rx_msg,
+			       ELE_GET_INFO_RSP_MSG_SZ);
+	if (ret < 0)
+		goto exit;
+
+	ret = se_val_rsp_hdr_n_status(priv,
+				      rx_msg,
+				      ELE_GET_INFO_REQ,
+				      ELE_GET_INFO_RSP_MSG_SZ,
+				      true);
+
+	memcpy(s_info, get_info_data, sizeof(*s_info));
+
+exit:
+	if (priv->mem_pool)
+		gen_pool_free(priv->mem_pool,
+			      (u64)get_info_data,
+			      ELE_GET_INFO_BUFF_SZ);
+	else
+		dma_free_coherent(priv->dev,
+				  ELE_GET_INFO_BUFF_SZ,
+				  get_info_data,
+				  get_info_addr);
+
+	return ret;
+}
+
+int ele_fetch_soc_info(struct se_if_priv *priv, void *data)
+{
+	int err;
+
+	err = ele_get_info(priv, data);
+	if (err < 0)
+		return err;
+
+	return err;
+}
+
+int ele_ping(struct se_if_priv *priv)
+{
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	int ret = 0;
+
+	if (!priv)
+		return -EINVAL;
+
+	tx_msg = kzalloc(ELE_PING_REQ_SZ, GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	rx_msg = kzalloc(ELE_PING_RSP_SZ, GFP_KERNEL);
+	if (!rx_msg)
+		return -ENOMEM;
+
+	ret = se_fill_cmd_msg_hdr(priv,
+				  (struct se_msg_hdr *)&tx_msg->header,
+				  ELE_PING_REQ, ELE_PING_REQ_SZ, true);
+	if (ret) {
+		dev_err(priv->dev, "Error: se_fill_cmd_msg_hdr failed.\n");
+		return ret;
+	}
+
+	ret = ele_msg_send_rcv(priv,
+			       tx_msg,
+			       ELE_PING_REQ_SZ,
+			       rx_msg,
+			       ELE_PING_RSP_SZ);
+	if (ret < 0)
+		return ret;
+
+	ret = se_val_rsp_hdr_n_status(priv,
+				      rx_msg,
+				      ELE_PING_REQ,
+				      ELE_PING_RSP_SZ,
+				      true);
+
+	return ret;
+}
+
+int ele_service_swap(struct se_if_priv *priv,
+		     phys_addr_t addr,
+		     u32 addr_size, u16 flag)
+{
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	int ret = 0;
+
+	if (!priv)
+		return -EINVAL;
+
+	tx_msg = kzalloc(ELE_SERVICE_SWAP_REQ_MSG_SZ, GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	rx_msg = kzalloc(ELE_SERVICE_SWAP_RSP_MSG_SZ, GFP_KERNEL);
+	if (!rx_msg)
+		return -ENOMEM;
+
+	ret = se_fill_cmd_msg_hdr(priv,
+				  (struct se_msg_hdr *)&tx_msg->header,
+				  ELE_SERVICE_SWAP_REQ,
+				  ELE_SERVICE_SWAP_REQ_MSG_SZ, true);
+	if (ret)
+		return ret;
+
+	tx_msg->data[0] = flag;
+	tx_msg->data[1] = addr_size;
+	tx_msg->data[2] = ELE_NONE_VAL;
+	tx_msg->data[3] = lower_32_bits(addr);
+	tx_msg->data[4] = se_add_msg_crc((uint32_t *)&tx_msg[0],
+					 ELE_SERVICE_SWAP_REQ_MSG_SZ);
+	ret = ele_msg_send_rcv(priv,
+			       tx_msg,
+			       ELE_SERVICE_SWAP_REQ_MSG_SZ,
+			       rx_msg,
+			       ELE_SERVICE_SWAP_RSP_MSG_SZ);
+	if (ret < 0)
+		return ret;
+
+	ret = se_val_rsp_hdr_n_status(priv,
+				      rx_msg,
+				      ELE_SERVICE_SWAP_REQ,
+				      ELE_SERVICE_SWAP_RSP_MSG_SZ,
+				      true);
+	if (ret)
+		return ret;
+
+	if (flag == ELE_IMEM_EXPORT)
+		ret = rx_msg->data[1];
+	else
+		ret = 0;
+
+	return ret;
+}
+
+int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr)
+{
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	int ret = 0;
+
+	if (!priv)
+		return -EINVAL;
+
+	tx_msg = kzalloc(ELE_FW_AUTH_REQ_SZ, GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	rx_msg = kzalloc(ELE_FW_AUTH_RSP_MSG_SZ, GFP_KERNEL);
+	if (!rx_msg)
+		return -ENOMEM;
+
+	ret = se_fill_cmd_msg_hdr(priv,
+				  (struct se_msg_hdr *)&tx_msg->header,
+				  ELE_FW_AUTH_REQ,
+				  ELE_FW_AUTH_REQ_SZ,
+				  true);
+	if (ret)
+		return ret;
+
+	tx_msg->data[1] = upper_32_bits(addr);
+	tx_msg->data[0] = lower_32_bits(addr);
+	tx_msg->data[2] = addr;
+
+	ret = ele_msg_send_rcv(priv,
+			       tx_msg,
+			       ELE_FW_AUTH_REQ_SZ,
+			       rx_msg,
+			       ELE_FW_AUTH_RSP_MSG_SZ);
+	if (ret < 0)
+		return ret;
+
+	ret = se_val_rsp_hdr_n_status(priv,
+				      rx_msg,
+				      ELE_FW_AUTH_REQ,
+				      ELE_FW_AUTH_RSP_MSG_SZ,
+				      true);
+	return ret;
+}
+
+int ele_debug_dump(struct se_if_priv *priv)
+{
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	bool keep_logging;
+	u8 dump_data[408];
+	u8 fmt_str[256];
+	int fmt_str_idx;
+	int rcv_dbg_wd_ct;
+	int msg_ex_cnt;
+	int ret = 0;
+	int w_ct;
+
+	if (!priv)
+		return -EINVAL;
+
+	tx_msg = kzalloc(ELE_DEBUG_DUMP_REQ_SZ, GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	rx_msg = kzalloc(ELE_DEBUG_DUMP_RSP_SZ, GFP_KERNEL);
+	if (!rx_msg)
+		return -ENOMEM;
+
+	ret = se_fill_cmd_msg_hdr(priv,
+				  &tx_msg->header,
+				  ELE_DEBUG_DUMP_REQ,
+				  ELE_DEBUG_DUMP_REQ_SZ,
+				  true);
+	if (ret)
+		return ret;
+
+	msg_ex_cnt = 0;
+	do {
+		w_ct = 0;
+		fmt_str_idx = 0;
+		memset(rx_msg, 0xCC, ELE_DEBUG_DUMP_RSP_SZ);
+
+		ret = ele_msg_send_rcv(priv,
+				       tx_msg,
+				       ELE_DEBUG_DUMP_REQ_SZ,
+				       rx_msg,
+				       ELE_DEBUG_DUMP_RSP_SZ);
+		if (ret < 0)
+			return ret;
+
+		ret = se_val_rsp_hdr_n_status(priv,
+					      rx_msg,
+					      ELE_DEBUG_DUMP_REQ,
+					      ELE_DEBUG_DUMP_RSP_SZ,
+					      true);
+		if (!ret) {
+			rcv_dbg_wd_ct = rx_msg->header.size - ELE_NON_DUMP_BUFFER_SZ;
+			memcpy(fmt_str, FW_DBG_DUMP_FIXED_STR, strlen(FW_DBG_DUMP_FIXED_STR));
+			fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR);
+			for (w_ct = 0; w_ct < rcv_dbg_wd_ct; w_ct++) {
+				fmt_str[fmt_str_idx] = '0';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = 'x';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = '%';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = '0';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = '8';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = 'x';
+				fmt_str_idx++;
+				fmt_str[fmt_str_idx] = ' ';
+				fmt_str_idx++;
+				if (w_ct % 2) {
+					memcpy(fmt_str + fmt_str_idx,
+					       FW_DBG_DUMP_FIXED_STR,
+					       strlen(FW_DBG_DUMP_FIXED_STR));
+					fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR);
+				}
+			}
+			keep_logging = (rx_msg->header.size < (ELE_DEBUG_DUMP_RSP_SZ >> 2)) ?
+					false : true;
+			keep_logging = keep_logging ?
+						(msg_ex_cnt > ELE_MAX_DBG_DMP_PKT ? false : true) :
+						false;
+			/*
+			 * Number of spaces = rcv_dbg_wd_ct
+			 * DBG dump length in bytes = rcv_dbg_wd_ct * 4
+			 *
+			 * Since, one byte is represented as 2 character,
+			 * DBG Dump string-length = rcv_dbg_wd_ct * 8
+			 * Fixed string's string-length =
+			 *                      strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct
+			 *
+			 * Total dump_data length = Number of spaces +
+			 *                          DBG Dump string' string-length +
+			 *                          Fixed string's string-length
+			 *
+			 * Total dump_data length = rcv_dbg_wd_ct + (rcv_dbg_wd_ct * 8) +
+			 *                          strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct
+			 */
+
+			snprintf(dump_data,
+				 ((rcv_dbg_wd_ct * 9) +
+				  (strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct)),
+				  fmt_str,
+				  rx_msg->data[1], rx_msg->data[2],
+				  rx_msg->data[3], rx_msg->data[4],
+				  rx_msg->data[5], rx_msg->data[6],
+				  rx_msg->data[7], rx_msg->data[8],
+				  rx_msg->data[9], rx_msg->data[10],
+				  rx_msg->data[11], rx_msg->data[12],
+				  rx_msg->data[13], rx_msg->data[14],
+				  rx_msg->data[15], rx_msg->data[16],
+				  rx_msg->data[17], rx_msg->data[18],
+				  rx_msg->data[19], rx_msg->data[20]);
+
+			dev_err(priv->dev, "%s", dump_data);
+		} else {
+			dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.", ret);
+			break;
+		}
+		msg_ex_cnt++;
+	} while (keep_logging);
+
+	return ret;
+}
diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h
new file mode 100644
index 000000000000..b8c9d9e29ae8
--- /dev/null
+++ b/drivers/firmware/imx/ele_base_msg.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025 NXP
+ *
+ * Header file for the EdgeLock Enclave Base API(s).
+ */
+
+#ifndef ELE_BASE_MSG_H
+#define ELE_BASE_MSG_H
+
+#include <linux/device.h>
+#include <linux/types.h>
+
+#include "se_ctrl.h"
+
+#define ELE_NONE_VAL			0x0
+
+#define ELE_GET_INFO_REQ		0xDA
+#define ELE_GET_INFO_REQ_MSG_SZ		0x10
+#define ELE_GET_INFO_RSP_MSG_SZ		0x08
+
+#define SOC_ID_MASK			0x0000FFFF
+
+#define MAX_UID_SIZE                     (16)
+#define DEV_GETINFO_ROM_PATCH_SHA_SZ     (32)
+#define DEV_GETINFO_FW_SHA_SZ            (32)
+#define DEV_GETINFO_OEM_SRKH_SZ          (64)
+#define DEV_GETINFO_MIN_VER_MASK	0xFF
+#define DEV_GETINFO_MAJ_VER_MASK	0xFF00
+#define ELE_DEV_INFO_EXTRA_SZ		0x60
+
+struct dev_info {
+	u8  cmd;
+	u8  ver;
+	u16 length;
+	u16 soc_id;
+	u16 soc_rev;
+	u16 lmda_val;
+	u8  ssm_state;
+	u8  dev_atts_api_ver;
+	u8  uid[MAX_UID_SIZE];
+	u8  sha_rom_patch[DEV_GETINFO_ROM_PATCH_SHA_SZ];
+	u8  sha_fw[DEV_GETINFO_FW_SHA_SZ];
+};
+
+struct dev_addn_info {
+	u8  oem_srkh[DEV_GETINFO_OEM_SRKH_SZ];
+	u8  trng_state;
+	u8  csal_state;
+	u8  imem_state;
+	u8  reserved2;
+};
+
+struct ele_dev_info {
+	struct dev_info d_info;
+	struct dev_addn_info d_addn_info;
+};
+
+#define ELE_GET_INFO_BUFF_SZ		(sizeof(struct ele_dev_info) \
+						+ ELE_DEV_INFO_EXTRA_SZ)
+
+#define GET_SERIAL_NUM_FROM_UID(x, uid_word_sz) \
+	(((u64)(((u32 *)(x))[(uid_word_sz) - 1]) << 32) | ((u32 *)(x))[0])
+
+#define ELE_MAX_DBG_DMP_PKT		30
+#define ELE_NON_DUMP_BUFFER_SZ		3
+#define ELE_DEBUG_DUMP_REQ		0x21
+#define ELE_DEBUG_DUMP_REQ_SZ		0x4
+#define ELE_DEBUG_DUMP_RSP_SZ		0x5C
+
+#define ELE_PING_REQ			0x01
+#define ELE_PING_REQ_SZ			0x04
+#define ELE_PING_RSP_SZ			0x08
+
+#define ELE_SERVICE_SWAP_REQ		0xDF
+#define ELE_SERVICE_SWAP_REQ_MSG_SZ	0x18
+#define ELE_SERVICE_SWAP_RSP_MSG_SZ	0x0C
+#define ELE_IMEM_SIZE			0x10000
+#define ELE_IMEM_STATE_OK		0xCA
+#define ELE_IMEM_STATE_BAD		0xFE
+#define ELE_IMEM_STATE_WORD		0x27
+#define ELE_IMEM_STATE_MASK		0x00ff0000
+#define ELE_IMEM_EXPORT			0x1
+#define ELE_IMEM_IMPORT			0x2
+
+#define ELE_FW_AUTH_REQ			0x02
+#define ELE_FW_AUTH_REQ_SZ		0x10
+#define ELE_FW_AUTH_RSP_MSG_SZ		0x08
+
+int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info);
+int ele_fetch_soc_info(struct se_if_priv *priv, void *data);
+int ele_ping(struct se_if_priv *priv);
+int ele_service_swap(struct se_if_priv *priv,
+		     phys_addr_t addr,
+		     u32 addr_size, u16 flag);
+int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr);
+int ele_debug_dump(struct se_if_priv *priv);
+#endif
diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
new file mode 100644
index 000000000000..3fa8182b302f
--- /dev/null
+++ b/drivers/firmware/imx/ele_common.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 NXP
+ */
+
+#include "ele_base_msg.h"
+#include "ele_common.h"
+
+u32 se_add_msg_crc(u32 *msg, u32 msg_len)
+{
+	u32 nb_words = msg_len / (u32)sizeof(u32);
+	u32 crc = 0;
+	u32 i;
+
+	for (i = 0; i < nb_words - 1; i++)
+		crc ^= *(msg + i);
+
+	return crc;
+}
+
+int ele_msg_rcv(struct se_if_priv *priv,
+		struct se_clbk_handle *se_clbk_hdl)
+{
+	int err = 0;
+
+	do {
+		err = wait_for_completion_interruptible(&se_clbk_hdl->done);
+		if (err == -ERESTARTSYS) {
+			if (priv->waiting_rsp_clbk_hdl.rx_msg) {
+				priv->waiting_rsp_clbk_hdl.signal_rcvd = true;
+				continue;
+			}
+			dev_err(priv->dev,
+				"Err[0x%x]:Interrupted by signal.\n",
+				err);
+			err = -EINTR;
+			break;
+		}
+	} while (err != 0);
+
+	return err ? err : se_clbk_hdl->rx_msg_sz;
+}
+
+int ele_msg_send(struct se_if_priv *priv,
+		 void *tx_msg,
+		 int tx_msg_sz)
+{
+	struct se_msg_hdr *header;
+	int err;
+
+	header = tx_msg;
+
+	/*
+	 * Check that the size passed as argument matches the size
+	 * carried in the message.
+	 */
+	if (header->size << 2 != tx_msg_sz) {
+		dev_err(priv->dev,
+			"User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
+			*(u32 *)header,
+			header->size << 2, tx_msg_sz);
+		return -EINVAL;
+	}
+
+	err = mbox_send_message(priv->tx_chan, tx_msg);
+	if (err < 0) {
+		dev_err(priv->dev, "Error: mbox_send_message failure.\n");
+		return err;
+	}
+	err = tx_msg_sz;
+
+	return err;
+}
+
+/* API used for send/receive blocking call. */
+int ele_msg_send_rcv(struct se_if_priv *priv,
+		     void *tx_msg,
+		     int tx_msg_sz,
+		     void *rx_msg,
+		     int exp_rx_msg_sz)
+{
+	int err;
+
+	guard(mutex)(&priv->se_if_cmd_lock);
+
+	priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
+	priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
+
+	err = ele_msg_send(priv, tx_msg, tx_msg_sz);
+	if (err < 0)
+		return err;
+
+	err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl);
+
+	if (priv->waiting_rsp_clbk_hdl.signal_rcvd) {
+		err = -EINTR;
+		priv->waiting_rsp_clbk_hdl.signal_rcvd = false;
+		dev_err(priv->dev,
+			"Err[0x%x]:Interrupted by signal.\n",
+			err);
+	}
+
+	return err;
+}
+
+static bool exception_for_size(struct se_if_priv *priv,
+			       struct se_msg_hdr *header)
+{
+	/* List of API(s) that can be accepte variable length
+	 * response buffer.
+	 */
+	if (header->command == ELE_DEBUG_DUMP_REQ &&
+	    header->ver == priv->if_defs->base_api_ver &&
+	    header->size >= 0 &&
+	    header->size <= ELE_DEBUG_DUMP_RSP_SZ)
+		return true;
+
+	return false;
+}
+
+/*
+ * Callback called by mailbox FW, when data is received.
+ */
+void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
+{
+	struct se_clbk_handle *se_clbk_hdl;
+	struct device *dev = mbox_cl->dev;
+	struct se_msg_hdr *header;
+	struct se_if_priv *priv;
+	u32 rx_msg_sz;
+
+	priv = dev_get_drvdata(dev);
+
+	/* The function can be called with NULL msg */
+	if (!msg) {
+		dev_err(dev, "Message is invalid\n");
+		return;
+	}
+
+	header = msg;
+	rx_msg_sz = header->size << 2;
+
+	/* Incoming command: wake up the receiver if any. */
+	if (header->tag == priv->if_defs->cmd_tag) {
+		se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
+		dev_dbg(dev,
+			"Selecting cmd receiver for mesg header:0x%x.",
+			*(u32 *)header);
+
+		/* Pre-allocated buffer of MAX_NVM_MSG_LEN
+		 * as the NVM command are initiated by FW.
+		 * Size is revealed as part of this call function.
+		 */
+		if (rx_msg_sz > MAX_NVM_MSG_LEN) {
+			dev_err(dev,
+				"CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
+				*(u32 *)header,
+				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
+
+			se_clbk_hdl->rx_msg_sz = MAX_NVM_MSG_LEN;
+		}
+		se_clbk_hdl->rx_msg_sz = rx_msg_sz;
+
+	} else if (header->tag == priv->if_defs->rsp_tag) {
+		se_clbk_hdl = &priv->waiting_rsp_clbk_hdl;
+		dev_dbg(dev,
+			"Selecting resp waiter for mesg header:0x%x.",
+			*(u32 *)header);
+
+		if (rx_msg_sz != se_clbk_hdl->rx_msg_sz &&
+		    !exception_for_size(priv, header)) {
+			dev_err(dev,
+				"Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
+				*(u32 *)header,
+				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
+
+			se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, se_clbk_hdl->rx_msg_sz);
+		}
+	} else {
+		dev_err(dev, "Failed to select a device for message: %.8x\n",
+			*((u32 *)header));
+		return;
+	}
+
+	memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz);
+
+	/* Allow user to read */
+	complete(&se_clbk_hdl->done);
+}
+
+int se_val_rsp_hdr_n_status(struct se_if_priv *priv,
+			    struct se_api_msg *msg,
+			    u8 msg_id,
+			    u8 sz,
+			    bool is_base_api)
+{
+	u32 status;
+	struct se_msg_hdr *header = &msg->header;
+
+	if (header->tag != priv->if_defs->rsp_tag) {
+		dev_err(priv->dev,
+			"MSG[0x%x] Hdr: Resp tag mismatch. (0x%x != 0x%x)",
+			msg_id, header->tag, priv->if_defs->rsp_tag);
+		return -EINVAL;
+	}
+
+	if (header->command != msg_id) {
+		dev_err(priv->dev,
+			"MSG Header: Cmd id mismatch. (0x%x != 0x%x)",
+			header->command, msg_id);
+		return -EINVAL;
+	}
+
+	if (header->size != (sz >> 2) && !exception_for_size(priv, header)) {
+		dev_err(priv->dev,
+			"MSG[0x%x] Hdr: Cmd size mismatch. (0x%x != 0x%x)",
+			msg_id, header->size, (sz >> 2));
+		return -EINVAL;
+	}
+
+	if (is_base_api && header->ver != priv->if_defs->base_api_ver) {
+		dev_err(priv->dev,
+			"MSG[0x%x] Hdr: Base API Vers mismatch. (0x%x != 0x%x)",
+			msg_id, header->ver, priv->if_defs->base_api_ver);
+		return -EINVAL;
+	} else if (!is_base_api && header->ver != priv->if_defs->fw_api_ver) {
+		dev_err(priv->dev,
+			"MSG[0x%x] Hdr: FW API Vers mismatch. (0x%x != 0x%x)",
+			msg_id, header->ver, priv->if_defs->fw_api_ver);
+		return -EINVAL;
+	}
+
+	status = RES_STATUS(msg->data[0]);
+	if (status != priv->if_defs->success_tag) {
+		dev_err(priv->dev, "Command Id[%x], Response Failure = 0x%x",
+			header->command, status);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
+{
+	struct ele_dev_info s_info = {0};
+	int ret;
+
+	ret = ele_get_info(priv, &s_info);
+	if (ret) {
+		dev_err(priv->dev, "Failed to get info from ELE.\n");
+		return ret;
+	}
+
+	/* Do not save the IMEM buffer, if the current IMEM state is BAD. */
+	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD)
+		return ret;
+
+	/* EXPORT command will save encrypted IMEM to given address,
+	 * so later in resume, IMEM can be restored from the given
+	 * address.
+	 *
+	 * Size must be at least 64 kB.
+	 */
+	ret = ele_service_swap(priv,
+			       imem->phyaddr,
+			       ELE_IMEM_SIZE,
+			       ELE_IMEM_EXPORT);
+	if (ret < 0) {
+		dev_err(priv->dev, "Failed to export IMEM\n");
+		imem->size = 0;
+	} else {
+		dev_info(priv->dev,
+			 "Exported %d bytes of encrypted IMEM\n",
+			 ret);
+		imem->size = ret;
+	}
+
+	return ret > 0 ? 0 : -1;
+}
+
+int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
+{
+	struct ele_dev_info s_info;
+	int ret;
+
+	/* get info from ELE */
+	ret = ele_get_info(priv, &s_info);
+	if (ret) {
+		dev_err(priv->dev, "Failed to get info from ELE.\n");
+		return ret;
+	}
+	imem->state = s_info.d_addn_info.imem_state;
+
+	/* Get IMEM state, if 0xFE then import IMEM */
+	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD && imem->size) {
+		/* IMPORT command will restore IMEM from the given
+		 * address, here size is the actual size returned by ELE
+		 * during the export operation
+		 */
+		ret = ele_service_swap(priv,
+				       imem->phyaddr,
+				       imem->size,
+				       ELE_IMEM_IMPORT);
+		if (ret) {
+			dev_err(priv->dev, "Failed to import IMEM\n");
+			return ret;
+		}
+	} else {
+		return ret;
+	}
+
+	/* After importing IMEM, check if IMEM state is equal to 0xCA
+	 * to ensure IMEM is fully loaded and
+	 * ELE functionality can be used.
+	 */
+	ret = ele_get_info(priv, &s_info);
+	if (ret) {
+		dev_err(priv->dev, "Failed to get info from ELE.\n");
+		return ret;
+	}
+	imem->state = s_info.d_addn_info.imem_state;
+
+	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_OK)
+		dev_info(priv->dev, "Successfully restored IMEM\n");
+	else
+		dev_err(priv->dev, "Failed to restore IMEM\n");
+
+	return ret;
+}
diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
new file mode 100644
index 000000000000..aceb8c891ae6
--- /dev/null
+++ b/drivers/firmware/imx/ele_common.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef __ELE_COMMON_H__
+#define __ELE_COMMON_H__
+
+#include "se_ctrl.h"
+
+#define ELE_SUCCESS_IND			0xD6
+
+#define IMX_ELE_FW_DIR                 "imx/ele/"
+
+u32 se_add_msg_crc(u32 *msg, u32 msg_len);
+int ele_msg_rcv(struct se_if_priv *priv,
+		struct se_clbk_handle *se_clbk_hdl);
+int ele_msg_send(struct se_if_priv *priv,
+		 void *tx_msg,
+		 int tx_msg_sz);
+int ele_msg_send_rcv(struct se_if_priv *priv,
+		     void *tx_msg,
+		     int tx_msg_sz,
+		     void *rx_msg,
+		     int exp_rx_msg_sz);
+void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg);
+int se_val_rsp_hdr_n_status(struct se_if_priv *priv,
+			    struct se_api_msg *msg,
+			    u8 msg_id,
+			    u8 sz,
+			    bool is_base_api);
+
+/* Fill a command message header with a given command ID and length in bytes. */
+static inline int se_fill_cmd_msg_hdr(struct se_if_priv *priv,
+				      struct se_msg_hdr *hdr,
+				      u8 cmd, u32 len,
+				      bool is_base_api)
+{
+	hdr->tag = priv->if_defs->cmd_tag;
+	hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver;
+	hdr->command = cmd;
+	hdr->size = len >> 2;
+
+	return 0;
+}
+
+int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
+int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
+
+#endif /*__ELE_COMMON_H__ */
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
new file mode 100644
index 000000000000..12a1ceb87866
--- /dev/null
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/firmware.h>
+#include <linux/firmware/imx/se_api.h>
+#include <linux/genalloc.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/miscdevice.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sys_soc.h>
+
+#include "ele_base_msg.h"
+#include "ele_common.h"
+#include "se_ctrl.h"
+
+#define MAX_SOC_INFO_DATA_SZ		256
+#define MBOX_TX_NAME			"tx"
+#define MBOX_RX_NAME			"rx"
+#define SE_TYPE_STR_HSM			"hsm"
+#define SE_TYPE_ID_HSM			0x2
+
+struct se_fw_img_name {
+	const u8 *prim_fw_nm_in_rfs;
+	const u8 *seco_fw_nm_in_rfs;
+};
+
+struct se_fw_load_info {
+	const struct se_fw_img_name *se_fw_img_nm;
+	bool is_fw_loaded;
+	bool imem_mgmt;
+	struct se_imem_buf imem;
+};
+
+struct se_if_node {
+	u8 se_if_id;
+	u8 se_if_did;
+	struct se_if_defines if_defs;
+	u8 *pool_name;
+	bool reserved_dma_ranges;
+};
+
+/* contains fixed information */
+struct se_soc_info {
+	const u8 num_mu;
+	const u16 soc_id;
+	bool soc_register;
+	int (*se_fetch_soc_info)(struct se_if_priv *priv, void *data);
+	const struct se_fw_img_name se_fw_img_nm;
+	const struct se_if_node if_node[];
+};
+
+struct se_var_info {
+	u16 soc_rev;
+	struct se_fw_load_info load_fw;
+};
+
+static struct se_var_info var_se_info = {
+	.soc_rev = 0,
+	.load_fw = {
+		.is_fw_loaded = true,
+		.imem_mgmt = false,
+	},
+};
+
+static struct se_soc_info se_imx8ulp_info = {
+	.num_mu = 1,
+	.soc_id = SOC_ID_OF_IMX8ULP,
+	.soc_register = true,
+	.se_fetch_soc_info = ele_fetch_soc_info,
+	.se_fw_img_nm = {
+		.prim_fw_nm_in_rfs = IMX_ELE_FW_DIR
+			"mx8ulpa2-ahab-container.img",
+		.seco_fw_nm_in_rfs = IMX_ELE_FW_DIR
+			"mx8ulpa2ext-ahab-container.img",
+	},
+	.if_node = {
+			{
+			.se_if_id = 0,
+			.se_if_did = 7,
+			.if_defs = {
+				.se_if_type = SE_TYPE_ID_HSM,
+				.se_instance_id = 0,
+				.cmd_tag = 0x17,
+				.rsp_tag = 0xe1,
+				.success_tag = ELE_SUCCESS_IND,
+				.base_api_ver = MESSAGING_VERSION_6,
+				.fw_api_ver = MESSAGING_VERSION_7,
+			},
+			.pool_name = "sram",
+			.reserved_dma_ranges = true,
+			},
+	},
+};
+
+static struct se_soc_info se_imx93_info = {
+	.num_mu = 1,
+	.soc_id = SOC_ID_OF_IMX93,
+	.soc_register = false,
+	.se_fetch_soc_info = ele_fetch_soc_info,
+	.se_fw_img_nm = {
+		.prim_fw_nm_in_rfs = NULL,
+		.seco_fw_nm_in_rfs = NULL,
+	},
+	.if_node = {
+			{
+			.se_if_id = 0,
+			.se_if_did = 3,
+			.if_defs = {
+				.se_if_type = SE_TYPE_ID_HSM,
+				.se_instance_id = 0,
+				.cmd_tag = 0x17,
+				.rsp_tag = 0xe1,
+				.success_tag = ELE_SUCCESS_IND,
+				.base_api_ver = MESSAGING_VERSION_6,
+				.fw_api_ver = MESSAGING_VERSION_7,
+			},
+			.reserved_dma_ranges = true,
+			},
+	},
+};
+
+static const struct of_device_id se_match[] = {
+	{ .compatible = "fsl,imx8ulp-se-ele-hsm", .data = (void *)&se_imx8ulp_info.if_node},
+	{ .compatible = "fsl,imx93-se-ele-hsm", .data = (void *)&se_imx93_info.if_node},
+	{},
+};
+
+static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv)
+{
+	return &var_se_info.load_fw;
+}
+
+static int get_se_soc_info(struct se_if_priv *priv, const struct se_soc_info *se_info)
+{
+	struct se_fw_load_info *load_fw = get_load_fw_instance(priv);
+	struct soc_device_attribute *attr;
+	struct ele_dev_info *s_info;
+	struct soc_device *sdev;
+	u8 data[MAX_SOC_INFO_DATA_SZ];
+	int err = 0;
+
+	/* This function should be called once.
+	 * Check if the se_soc_rev is zero to continue.
+	 */
+	if (var_se_info.soc_rev)
+		return err;
+
+	if (se_info->se_fetch_soc_info) {
+		err = se_info->se_fetch_soc_info(priv, &data);
+		if (err < 0) {
+			dev_err(priv->dev, "Failed to fetch SoC Info.");
+			return err;
+		}
+		s_info = (void *)data;
+		var_se_info.soc_rev = s_info->d_info.soc_rev;
+		load_fw->imem.state = s_info->d_addn_info.imem_state;
+	} else {
+		dev_err(priv->dev, "Failed to fetch SoC revision.");
+		if (se_info->soc_register)
+			dev_err(priv->dev, "Failed to do SoC registration.");
+		return -EINVAL;
+	}
+
+	if (!se_info->soc_register)
+		return 0;
+
+	attr = devm_kzalloc(priv->dev, sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	if (FIELD_GET(DEV_GETINFO_MIN_VER_MASK, var_se_info.soc_rev))
+		attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x.%x",
+						FIELD_GET(DEV_GETINFO_MIN_VER_MASK,
+							  var_se_info.soc_rev),
+						FIELD_GET(DEV_GETINFO_MAJ_VER_MASK,
+							  var_se_info.soc_rev));
+	else
+		attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x",
+						FIELD_GET(DEV_GETINFO_MAJ_VER_MASK,
+							  var_se_info.soc_rev));
+
+	switch (se_info->soc_id) {
+	case SOC_ID_OF_IMX8ULP:
+		attr->soc_id = devm_kasprintf(priv->dev, GFP_KERNEL,
+					      "i.MX8ULP");
+		break;
+	case SOC_ID_OF_IMX93:
+		attr->soc_id = devm_kasprintf(priv->dev, GFP_KERNEL,
+					      "i.MX93");
+		break;
+	}
+
+	err = of_property_read_string(of_root, "model",
+				      &attr->machine);
+	if (err)
+		return -EINVAL;
+
+	attr->family = devm_kasprintf(priv->dev, GFP_KERNEL, "Freescale i.MX");
+
+	attr->serial_number = devm_kasprintf(priv->dev,
+					     GFP_KERNEL, "%016llX",
+					     GET_SERIAL_NUM_FROM_UID(s_info->d_info.uid,
+								     MAX_UID_SIZE >> 2));
+
+	sdev = soc_device_register(attr);
+	if (IS_ERR(sdev))
+		return PTR_ERR(sdev);
+
+	return 0;
+}
+
+static int se_load_firmware(struct se_if_priv *priv)
+{
+	struct se_fw_load_info *load_fw = get_load_fw_instance(priv);
+	const struct firmware *fw;
+	phys_addr_t se_fw_phyaddr;
+	const u8 *se_img_file_to_load;
+	u8 *se_fw_buf;
+	int ret;
+
+	if (load_fw->is_fw_loaded)
+		return 0;
+
+	se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs;
+	if (load_fw->se_fw_img_nm->prim_fw_nm_in_rfs &&
+	    load_fw->imem.state == ELE_IMEM_STATE_BAD)
+		se_img_file_to_load = load_fw->se_fw_img_nm->prim_fw_nm_in_rfs;
+
+	do {
+		ret = request_firmware(&fw, se_img_file_to_load, priv->dev);
+		if (ret)
+			return ret;
+
+		dev_info(priv->dev, "loading firmware %s\n", se_img_file_to_load);
+
+		/* allocate buffer to store the SE FW */
+		se_fw_buf = dma_alloc_coherent(priv->dev, fw->size,
+					       &se_fw_phyaddr, GFP_KERNEL);
+		if (!se_fw_buf)
+			return -ENOMEM;
+
+		memcpy(se_fw_buf, fw->data, fw->size);
+		ret = ele_fw_authenticate(priv, se_fw_phyaddr);
+		if (ret < 0) {
+			dev_err(priv->dev,
+				"Error %pe: Authenticate & load SE firmware %s.\n",
+				ERR_PTR(ret),
+				se_img_file_to_load);
+			ret = -EPERM;
+		}
+
+		dma_free_coherent(priv->dev,
+				  fw->size,
+				  se_fw_buf,
+				  se_fw_phyaddr);
+
+		release_firmware(fw);
+		fw = NULL;
+
+		if (!ret && load_fw->imem.state == ELE_IMEM_STATE_BAD &&
+		    se_img_file_to_load == load_fw->se_fw_img_nm->prim_fw_nm_in_rfs)
+			se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs;
+		else
+			se_img_file_to_load = NULL;
+
+	} while (se_img_file_to_load);
+
+	if (!ret)
+		load_fw->is_fw_loaded = true;
+
+	return ret;
+}
+
+/* interface for managed res to free a mailbox channel */
+static void if_mbox_free_channel(void *mbox_chan)
+{
+	mbox_free_channel(mbox_chan);
+}
+
+static int se_if_request_channel(struct device *dev,
+				 struct mbox_chan **chan,
+				 struct mbox_client *cl,
+				 const char *name)
+{
+	struct mbox_chan *t_chan;
+	int ret = 0;
+
+	t_chan = mbox_request_channel_byname(cl, name);
+	if (IS_ERR(t_chan)) {
+		ret = PTR_ERR(t_chan);
+		return dev_err_probe(dev, ret,
+				     "Failed to request %s channel.", name);
+	}
+
+	ret = devm_add_action_or_reset(dev, if_mbox_free_channel, t_chan);
+	if (ret) {
+		ret = -EPERM;
+		return dev_err_probe(dev, ret,
+				     "Failed to add-action for removal of mbox: %s\n",
+				     name);
+	}
+	*chan = t_chan;
+
+	return ret;
+}
+
+static void se_if_probe_cleanup(void *plat_dev)
+{
+	struct platform_device *pdev = plat_dev;
+	struct device *dev = &pdev->dev;
+	struct se_fw_load_info *load_fw;
+	struct se_if_priv *priv;
+
+	priv = dev_get_drvdata(dev);
+	load_fw = get_load_fw_instance(priv);
+
+	/* In se_if_request_channel(), passed the clean-up functional
+	 * pointer reference as action to devm_add_action_or_reset().
+	 * No need to free the mbox channels here.
+	 */
+
+	/* free the buffer in se remove, previously allocated
+	 * in se probe to store encrypted IMEM
+	 */
+	if (load_fw && load_fw->imem.buf) {
+		dmam_free_coherent(dev,
+				   ELE_IMEM_SIZE,
+				   load_fw->imem.buf,
+				   load_fw->imem.phyaddr);
+		load_fw->imem.buf = NULL;
+	}
+
+	/* No need to check, if reserved memory is allocated
+	 * before calling for its release. Or clearing the
+	 * un-set bit.
+	 */
+	of_reserved_mem_device_release(dev);
+}
+
+static int se_if_probe(struct platform_device *pdev)
+{
+	const struct se_soc_info *se_info;
+	const struct se_if_node *if_node;
+	struct device *dev = &pdev->dev;
+	struct se_fw_load_info *load_fw;
+	struct se_if_priv *priv;
+	int ret;
+
+	if_node = device_get_match_data(dev);
+	if (!if_node)
+		return -EINVAL;
+
+	se_info = container_of(if_node,
+			       typeof(*se_info),
+			       if_node[if_node->se_if_id]);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	priv->if_defs = &if_node->if_defs;
+	dev_set_drvdata(dev, priv);
+
+	ret = devm_add_action_or_reset(dev, se_if_probe_cleanup, pdev);
+	if (ret)
+		return ret;
+
+	/* Mailbox client configuration */
+	priv->se_mb_cl.dev		= dev;
+	priv->se_mb_cl.tx_block		= false;
+	priv->se_mb_cl.knows_txdone	= true;
+	priv->se_mb_cl.rx_callback	= se_if_rx_callback;
+
+	ret = se_if_request_channel(dev, &priv->tx_chan,
+				    &priv->se_mb_cl, MBOX_TX_NAME);
+	if (ret)
+		return ret;
+
+	ret = se_if_request_channel(dev, &priv->rx_chan,
+				    &priv->se_mb_cl, MBOX_RX_NAME);
+	if (ret)
+		return ret;
+
+	mutex_init(&priv->se_if_cmd_lock);
+
+	init_completion(&priv->waiting_rsp_clbk_hdl.done);
+	init_completion(&priv->cmd_receiver_clbk_hdl.done);
+
+	if (if_node->pool_name) {
+		priv->mem_pool = of_gen_pool_get(dev->of_node,
+						 if_node->pool_name, 0);
+		if (!priv->mem_pool)
+			return dev_err_probe(dev, -ENOMEM,
+					     "Unable to get sram pool = %s.",
+					     if_node->pool_name);
+	}
+
+	if (if_node->reserved_dma_ranges) {
+		ret = of_reserved_mem_device_init(dev);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					    "Failed to init reserved memory region.");
+	}
+
+	if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) {
+		ret = get_se_soc_info(priv, se_info);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Failed to fetch SoC Info.");
+	}
+
+	/* By default, there is no pending FW to be loaded.*/
+	if (se_info->se_fw_img_nm.prim_fw_nm_in_rfs ||
+	    se_info->se_fw_img_nm.seco_fw_nm_in_rfs) {
+		load_fw = get_load_fw_instance(priv);
+		load_fw->se_fw_img_nm = &se_info->se_fw_img_nm;
+		load_fw->is_fw_loaded = false;
+
+		if (se_info->se_fw_img_nm.prim_fw_nm_in_rfs) {
+			/* allocate buffer where SE store encrypted IMEM */
+			load_fw->imem.buf = dmam_alloc_coherent(priv->dev, ELE_IMEM_SIZE,
+								&load_fw->imem.phyaddr,
+								GFP_KERNEL);
+			if (!load_fw->imem.buf)
+				return dev_err_probe(dev, -ENOMEM,
+						     "dmam-alloc-failed: To store encr-IMEM.");
+			load_fw->imem_mgmt = true;
+		}
+	}
+	dev_info(dev, "i.MX secure-enclave: %s%d interface to firmware, configured.",
+		 SE_TYPE_STR_HSM,
+		 priv->if_defs->se_instance_id);
+
+	return ret;
+}
+
+static void se_if_remove(struct platform_device *pdev)
+{
+	se_if_probe_cleanup(pdev);
+}
+
+static int se_suspend(struct device *dev)
+{
+	struct se_if_priv *priv = dev_get_drvdata(dev);
+	struct se_fw_load_info *load_fw;
+	int ret = 0;
+
+	load_fw = get_load_fw_instance(priv);
+
+	if (load_fw->imem_mgmt)
+		ret = se_save_imem_state(priv, &load_fw->imem);
+
+	return ret;
+}
+
+static int se_resume(struct device *dev)
+{
+	struct se_if_priv *priv = dev_get_drvdata(dev);
+	struct se_fw_load_info *load_fw;
+
+	load_fw = get_load_fw_instance(priv);
+
+	if (load_fw->imem_mgmt)
+		se_restore_imem_state(priv, &load_fw->imem);
+
+	return 0;
+}
+
+static const struct dev_pm_ops se_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(se_suspend, se_resume)
+};
+
+static struct platform_driver se_driver = {
+	.driver = {
+		.name = "fsl-se",
+		.of_match_table = se_match,
+		.pm = &se_pm,
+	},
+	.probe = se_if_probe,
+	.remove = se_if_remove,
+};
+MODULE_DEVICE_TABLE(of, se_match);
+
+module_platform_driver(se_driver);
+MODULE_AUTHOR("Pankaj Gupta <pankaj.gupta at nxp.com>");
+MODULE_DESCRIPTION("iMX Secure Enclave Driver.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h
new file mode 100644
index 000000000000..32547bc97ca3
--- /dev/null
+++ b/drivers/firmware/imx/se_ctrl.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef SE_MU_H
+#define SE_MU_H
+
+#include <linux/miscdevice.h>
+#include <linux/semaphore.h>
+#include <linux/mailbox_client.h>
+
+#define MAX_FW_LOAD_RETRIES		50
+
+#define RES_STATUS(x)			FIELD_GET(0x000000ff, x)
+#define MAX_NVM_MSG_LEN			(256)
+#define MESSAGING_VERSION_6		0x6
+#define MESSAGING_VERSION_7		0x7
+
+struct se_clbk_handle {
+	struct completion done;
+	bool signal_rcvd;
+	u32 rx_msg_sz;
+	/* Assignment of the rx_msg buffer to held till the
+	 * received content as part callback function, is copied.
+	 */
+	struct se_api_msg *rx_msg;
+};
+
+struct se_imem_buf {
+	u8 *buf;
+	phys_addr_t phyaddr;
+	u32 size;
+	u32 state;
+};
+
+/* Header of the messages exchange with the EdgeLock Enclave */
+struct se_msg_hdr {
+	u8 ver;
+	u8 size;
+	u8 command;
+	u8 tag;
+}  __packed;
+
+#define SE_MU_HDR_SZ	4
+
+struct se_api_msg {
+	struct se_msg_hdr header;
+	u32 data[];
+};
+
+struct se_if_defines {
+	const u8 se_if_type;
+	const u8 se_instance_id;
+	u8 cmd_tag;
+	u8 rsp_tag;
+	u8 success_tag;
+	u8 base_api_ver;
+	u8 fw_api_ver;
+};
+
+struct se_if_priv {
+	struct device *dev;
+
+	struct se_clbk_handle cmd_receiver_clbk_hdl;
+	/* Update to the waiting_rsp_dev, to be protected
+	 * under se_if_cmd_lock.
+	 */
+	struct se_clbk_handle waiting_rsp_clbk_hdl;
+	/*
+	 * prevent new command to be sent on the se interface while previous
+	 * command is still processing. (response is awaited)
+	 */
+	struct mutex se_if_cmd_lock;
+
+	struct mbox_client se_mb_cl;
+	struct mbox_chan *tx_chan, *rx_chan;
+
+	struct gen_pool *mem_pool;
+	const struct se_if_defines *if_defs;
+};
+
+#endif
diff --git a/include/linux/firmware/imx/se_api.h b/include/linux/firmware/imx/se_api.h
new file mode 100644
index 000000000000..0d49eb109885
--- /dev/null
+++ b/include/linux/firmware/imx/se_api.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef __SE_API_H__
+#define __SE_API_H__
+
+#include <linux/types.h>
+
+#define SOC_ID_OF_IMX8ULP		0x084D
+#define SOC_ID_OF_IMX93			0x9300
+
+#endif /* __SE_API_H__ */

-- 
2.43.0



From pankaj.gupta at nxp.com  Tue Mar 11 08:39:34 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:34 +0530
Subject: [PATCH v13 3/5] arm64: dts: imx8ulp-evk: add nxp secure enclave
 firmware
In-Reply-To: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
Message-ID: <20250311-imx-se-if-v13-3-9cc6d8fd6d1c@nxp.com>

Add support for NXP secure enclave called EdgeLock Enclave
firmware (se-fw) for imx8ulp-evk.

EdgeLock Enclave has a hardware limitation of restricted access to DDR
address: 0x80000000 to 0xAFFFFFFF, so reserve 1MB of DDR memory region
from 0x80000000.

Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8ulp-evk.dts | 17 ++++++++++++++++-
 arch/arm64/boot/dts/freescale/imx8ulp.dtsi    | 13 +++++++++++--
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
index 290a49bea2f7..a25d71bf2c26 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
- * Copyright 2021 NXP
+ * Copyright 2021, 2025 NXP
  */
 
 /dts-v1/;
@@ -24,6 +24,17 @@ memory at 80000000 {
 		device_type = "memory";
 		reg = <0x0 0x80000000 0 0x80000000>;
 	};
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ele_reserved: ele-reserved at 90000000 {
+			compatible = "shared-dma-pool";
+			reg = <0 0x90000000 0 0x100000>;
+			no-map;
+		};
+	};
 
 	reserved-memory {
 		#address-cells = <2>;
@@ -259,6 +270,10 @@ &usdhc0 {
 	status = "okay";
 };
 
+&hsm0 {
+	memory-region = <&ele_reserved>;
+};
+
 &fec {
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&pinctrl_enet>;
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 2562a35286c2..c79a5de227b3 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
- * Copyright 2021 NXP
+ * Copyright 2021, 2025 NXP
  */
 
 #include <dt-bindings/clock/imx8ulp-clock.h>
@@ -154,7 +154,7 @@ sosc: clock-sosc {
 		#clock-cells = <0>;
 	};
 
-	sram at 2201f000 {
+	sram0: sram at 2201f000 {
 		compatible = "mmio-sram";
 		reg = <0x0 0x2201f000 0x0 0x1000>;
 
@@ -169,6 +169,8 @@ scmi_buf: scmi-sram-section at 0 {
 	};
 
 	firmware {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		scmi {
 			compatible = "arm,scmi-smc";
 			arm,smc-id = <0xc20000fe>;
@@ -186,6 +188,13 @@ scmi_sensor: protocol at 15 {
 				#thermal-sensor-cells = <1>;
 			};
 		};
+
+		hsm0: secure-enclave {
+			 compatible = "fsl,imx8ulp-se-ele-hsm";
+			 mbox-names = "tx", "rx";
+			 mboxes = <&s4muap 0 0>, <&s4muap 1 0>;
+			 sram = <&sram0>;
+		 };
 	};
 
 	cm33: remoteproc-cm33 {

-- 
2.43.0



From pankaj.gupta at nxp.com  Tue Mar 11 08:39:36 2025
From: pankaj.gupta at nxp.com (Pankaj Gupta)
Date: Tue, 11 Mar 2025 21:09:36 +0530
Subject: [PATCH v13 5/5] firmware: drivers: imx: adds miscdev
In-Reply-To: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
Message-ID: <20250311-imx-se-if-v13-5-9cc6d8fd6d1c@nxp.com>

Adds the driver for communication interface to secure-enclave,
for exchanging messages with NXP secure enclave HW IP(s) like
EdgeLock Enclave from:
- User-Space Applications via character driver.

ABI documentation for the NXP secure-enclave driver.

User-space library using this driver:
- i.MX Secure Enclave library:
  -- URL: https://github.com/nxp-imx/imx-secure-enclave.git,
- i.MX Secure Middle-Ware:
  -- URL: https://github.com/nxp-imx/imx-smw.git

Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
---
 Documentation/ABI/testing/se-cdev   |  43 ++
 drivers/firmware/imx/ele_base_msg.c |  11 +-
 drivers/firmware/imx/ele_common.c   |  77 +++-
 drivers/firmware/imx/ele_common.h   |  10 +-
 drivers/firmware/imx/se_ctrl.c      | 775 +++++++++++++++++++++++++++++++++++-
 drivers/firmware/imx/se_ctrl.h      |  43 ++
 include/uapi/linux/se_ioctl.h       | 101 +++++
 7 files changed, 1029 insertions(+), 31 deletions(-)

diff --git a/Documentation/ABI/testing/se-cdev b/Documentation/ABI/testing/se-cdev
new file mode 100644
index 000000000000..dad39ffd245a
--- /dev/null
+++ b/Documentation/ABI/testing/se-cdev
@@ -0,0 +1,43 @@
+What:		/dev/<se>_mu[0-9]+_ch[0-9]+
+Date:		Mar 2025
+KernelVersion:	6.8
+Contact:	linux-imx at nxp.com, pankaj.gupta at nxp.com
+Description:
+		NXP offers multiple hardware IP(s) for secure enclaves like EdgeLock-
+		Enclave(ELE), SECO. The character device file descriptors
+		/dev/<se>_mu*_ch* are the interface between userspace NXP's secure-
+		enclave shared library and the kernel driver.
+
+		The ioctl(2)-based ABI is defined and documented in
+		[include]<linux/firmware/imx/ele_mu_ioctl.h>.
+		ioctl(s) are used primarily for:
+			- shared memory management
+			- allocation of I/O buffers
+			- getting mu info
+			- setting a dev-ctx as receiver to receive all the commands from FW
+			- getting SoC info
+			- send command and receive command response
+
+		The following file operations are supported:
+
+		open(2)
+		  Currently the only useful flags are O_RDWR.
+
+		read(2)
+		  Every read() from the opened character device context is waiting on
+		  wait_event_interruptible, that gets set by the registered mailbox callback
+		  function, indicating a message received from the firmware on message-
+		  unit.
+
+		write(2)
+		  Every write() to the opened character device context needs to acquire
+		  mailbox_lock before sending message on to the message unit.
+
+		close(2)
+		  Stops and frees up the I/O contexts that were associated
+		  with the file descriptor.
+
+Users:		https://github.com/nxp-imx/imx-secure-enclave.git,
+		https://github.com/nxp-imx/imx-smw.git
+		crypto/skcipher,
+		drivers/nvmem/imx-ocotp-ele.c
diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
index eea86f50d276..ed70728f5418 100644
--- a/drivers/firmware/imx/ele_base_msg.c
+++ b/drivers/firmware/imx/ele_base_msg.c
@@ -62,7 +62,7 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
 	tx_msg->data[0] = upper_32_bits(get_info_addr);
 	tx_msg->data[1] = lower_32_bits(get_info_addr);
 	tx_msg->data[2] = sizeof(*s_info);
-	ret = ele_msg_send_rcv(priv,
+	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
 			       tx_msg,
 			       ELE_GET_INFO_REQ_MSG_SZ,
 			       rx_msg,
@@ -128,7 +128,7 @@ int ele_ping(struct se_if_priv *priv)
 		return ret;
 	}
 
-	ret = ele_msg_send_rcv(priv,
+	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
 			       tx_msg,
 			       ELE_PING_REQ_SZ,
 			       rx_msg,
@@ -177,7 +177,8 @@ int ele_service_swap(struct se_if_priv *priv,
 	tx_msg->data[3] = lower_32_bits(addr);
 	tx_msg->data[4] = se_add_msg_crc((uint32_t *)&tx_msg[0],
 					 ELE_SERVICE_SWAP_REQ_MSG_SZ);
-	ret = ele_msg_send_rcv(priv,
+
+	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
 			       tx_msg,
 			       ELE_SERVICE_SWAP_REQ_MSG_SZ,
 			       rx_msg,
@@ -230,7 +231,7 @@ int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr)
 	tx_msg->data[0] = lower_32_bits(addr);
 	tx_msg->data[2] = addr;
 
-	ret = ele_msg_send_rcv(priv,
+	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
 			       tx_msg,
 			       ELE_FW_AUTH_REQ_SZ,
 			       rx_msg,
@@ -284,7 +285,7 @@ int ele_debug_dump(struct se_if_priv *priv)
 		fmt_str_idx = 0;
 		memset(rx_msg, 0xCC, ELE_DEBUG_DUMP_RSP_SZ);
 
-		ret = ele_msg_send_rcv(priv,
+		ret = ele_msg_send_rcv(priv->priv_dev_ctx,
 				       tx_msg,
 				       ELE_DEBUG_DUMP_REQ_SZ,
 				       rx_msg,
diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
index 3fa8182b302f..d63346239936 100644
--- a/drivers/firmware/imx/ele_common.c
+++ b/drivers/firmware/imx/ele_common.c
@@ -6,6 +6,8 @@
 #include "ele_base_msg.h"
 #include "ele_common.h"
 
+u32 se_rcv_msg_timeout = SE_RCV_MSG_DEFAULT_TIMEOUT;
+
 u32 se_add_msg_crc(u32 *msg, u32 msg_len)
 {
 	u32 nb_words = msg_len / (u32)sizeof(u32);
@@ -18,33 +20,57 @@ u32 se_add_msg_crc(u32 *msg, u32 msg_len)
 	return crc;
 }
 
-int ele_msg_rcv(struct se_if_priv *priv,
+void set_se_rcv_msg_timeout(u32 val)
+{
+	se_rcv_msg_timeout = val;
+}
+
+int ele_msg_rcv(struct se_if_device_ctx *dev_ctx,
 		struct se_clbk_handle *se_clbk_hdl)
 {
-	int err = 0;
+	struct se_if_priv *priv = dev_ctx->priv;
+	bool wait_timeout_enabled = true;
+	unsigned int wait;
+	int err;
 
 	do {
-		err = wait_for_completion_interruptible(&se_clbk_hdl->done);
+		if (priv->cmd_receiver_clbk_hdl.dev_ctx == dev_ctx) {
+			/* NVM-D, SE-FW slave waits indefinitly. */
+			wait_timeout_enabled = false;
+			err = wait_for_completion_interruptible(&se_clbk_hdl->done);
+		} else {
+			/* FW must send message-response in a finite time. */
+			wait = msecs_to_jiffies(se_rcv_msg_timeout);
+			err = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done, wait);
+		}
 		if (err == -ERESTARTSYS) {
-			if (priv->waiting_rsp_clbk_hdl.rx_msg) {
+			if (priv->waiting_rsp_clbk_hdl.dev_ctx) {
 				priv->waiting_rsp_clbk_hdl.signal_rcvd = true;
 				continue;
 			}
-			dev_err(priv->dev,
-				"Err[0x%x]:Interrupted by signal.\n",
-				err);
 			err = -EINTR;
 			break;
 		}
-	} while (err != 0);
+		if (err == 0) {
+			if (wait_timeout_enabled) {
+				err = -ETIMEDOUT;
+				dev_err(priv->dev,
+					"Fatal Error: SE interface: %s%d, hangs indefinitely.\n",
+					get_se_if_name(priv->if_defs->se_if_type),
+					priv->if_defs->se_instance_id);
+			}
+			break;
+		}
+	} while (err < 0);
 
-	return err ? err : se_clbk_hdl->rx_msg_sz;
+	return (err >= 0) ? se_clbk_hdl->rx_msg_sz : err;
 }
 
-int ele_msg_send(struct se_if_priv *priv,
+int ele_msg_send(struct se_if_device_ctx *dev_ctx,
 		 void *tx_msg,
 		 int tx_msg_sz)
 {
+	struct se_if_priv *priv = dev_ctx->priv;
 	struct se_msg_hdr *header;
 	int err;
 
@@ -56,7 +82,8 @@ int ele_msg_send(struct se_if_priv *priv,
 	 */
 	if (header->size << 2 != tx_msg_sz) {
 		dev_err(priv->dev,
-			"User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
+			"%s: User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
+			dev_ctx->devname,
 			*(u32 *)header,
 			header->size << 2, tx_msg_sz);
 		return -EINVAL;
@@ -64,7 +91,9 @@ int ele_msg_send(struct se_if_priv *priv,
 
 	err = mbox_send_message(priv->tx_chan, tx_msg);
 	if (err < 0) {
-		dev_err(priv->dev, "Error: mbox_send_message failure.\n");
+		dev_err(priv->dev,
+			"%s: Error: mbox_send_message failure.",
+			dev_ctx->devname);
 		return err;
 	}
 	err = tx_msg_sz;
@@ -73,32 +102,36 @@ int ele_msg_send(struct se_if_priv *priv,
 }
 
 /* API used for send/receive blocking call. */
-int ele_msg_send_rcv(struct se_if_priv *priv,
+int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx,
 		     void *tx_msg,
 		     int tx_msg_sz,
 		     void *rx_msg,
 		     int exp_rx_msg_sz)
 {
 	int err;
+	struct se_if_priv *priv = dev_ctx->priv;
 
 	guard(mutex)(&priv->se_if_cmd_lock);
 
+	priv->waiting_rsp_clbk_hdl.dev_ctx = dev_ctx;
 	priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
 	priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
 
-	err = ele_msg_send(priv, tx_msg, tx_msg_sz);
+	err = ele_msg_send(dev_ctx, tx_msg, tx_msg_sz);
 	if (err < 0)
 		return err;
 
-	err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl);
+	err = ele_msg_rcv(dev_ctx, &priv->waiting_rsp_clbk_hdl);
 
 	if (priv->waiting_rsp_clbk_hdl.signal_rcvd) {
 		err = -EINTR;
 		priv->waiting_rsp_clbk_hdl.signal_rcvd = false;
 		dev_err(priv->dev,
-			"Err[0x%x]:Interrupted by signal.\n",
+			"%s: Err[0x%x]:Interrupted by signal.\n",
+			dev_ctx->devname,
 			err);
 	}
+	priv->waiting_rsp_clbk_hdl.dev_ctx = NULL;
 
 	return err;
 }
@@ -144,7 +177,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
 	if (header->tag == priv->if_defs->cmd_tag) {
 		se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
 		dev_dbg(dev,
-			"Selecting cmd receiver for mesg header:0x%x.",
+			"Selecting cmd receiver:%s for mesg header:0x%x.",
+			se_clbk_hdl->dev_ctx->devname,
 			*(u32 *)header);
 
 		/* Pre-allocated buffer of MAX_NVM_MSG_LEN
@@ -153,7 +187,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
 		 */
 		if (rx_msg_sz > MAX_NVM_MSG_LEN) {
 			dev_err(dev,
-				"CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
+				"%s: CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
+				se_clbk_hdl->dev_ctx->devname,
 				*(u32 *)header,
 				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
 
@@ -164,13 +199,15 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
 	} else if (header->tag == priv->if_defs->rsp_tag) {
 		se_clbk_hdl = &priv->waiting_rsp_clbk_hdl;
 		dev_dbg(dev,
-			"Selecting resp waiter for mesg header:0x%x.",
+			"Selecting resp waiter:%s for mesg header:0x%x.",
+			se_clbk_hdl->dev_ctx->devname,
 			*(u32 *)header);
 
 		if (rx_msg_sz != se_clbk_hdl->rx_msg_sz &&
 		    !exception_for_size(priv, header)) {
 			dev_err(dev,
-				"Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
+				"%s: Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
+				se_clbk_hdl->dev_ctx->devname,
 				*(u32 *)header,
 				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
 
diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
index aceb8c891ae6..3cf124f41487 100644
--- a/drivers/firmware/imx/ele_common.h
+++ b/drivers/firmware/imx/ele_common.h
@@ -12,13 +12,17 @@
 
 #define IMX_ELE_FW_DIR                 "imx/ele/"
 
+#define SE_RCV_MSG_DEFAULT_TIMEOUT	5000
+#define SE_RCV_MSG_LONG_TIMEOUT		5000000
+void set_se_rcv_msg_timeout(u32 val);
+
 u32 se_add_msg_crc(u32 *msg, u32 msg_len);
-int ele_msg_rcv(struct se_if_priv *priv,
+int ele_msg_rcv(struct se_if_device_ctx *dev_ctx,
 		struct se_clbk_handle *se_clbk_hdl);
-int ele_msg_send(struct se_if_priv *priv,
+int ele_msg_send(struct se_if_device_ctx *dev_ctx,
 		 void *tx_msg,
 		 int tx_msg_sz);
-int ele_msg_send_rcv(struct se_if_priv *priv,
+int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx,
 		     void *tx_msg,
 		     int tx_msg_sz,
 		     void *rx_msg,
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
index 12a1ceb87866..f31d97045b89 100644
--- a/drivers/firmware/imx/se_ctrl.c
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/sys_soc.h>
+#include <uapi/linux/se_ioctl.h>
 
 #include "ele_base_msg.h"
 #include "ele_common.h"
@@ -31,8 +32,6 @@
 #define MAX_SOC_INFO_DATA_SZ		256
 #define MBOX_TX_NAME			"tx"
 #define MBOX_RX_NAME			"rx"
-#define SE_TYPE_STR_HSM			"hsm"
-#define SE_TYPE_ID_HSM			0x2
 
 struct se_fw_img_name {
 	const u8 *prim_fw_nm_in_rfs;
@@ -140,6 +139,24 @@ static const struct of_device_id se_match[] = {
 	{},
 };
 
+char *get_se_if_name(u8 se_if_id)
+{
+	switch (se_if_id) {
+	case SE_TYPE_ID_DBG: return SE_TYPE_STR_DBG;
+	case SE_TYPE_ID_HSM: return SE_TYPE_STR_HSM;
+	}
+
+	return NULL;
+}
+
+static uint32_t get_se_soc_id(struct se_if_priv *priv)
+{
+	const struct se_soc_info *se_info =
+				device_get_match_data(priv->dev);
+
+	return se_info->soc_id;
+}
+
 static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv)
 {
 	return &var_se_info.load_fw;
@@ -286,6 +303,742 @@ static int se_load_firmware(struct se_if_priv *priv)
 	return ret;
 }
 
+static int init_se_shared_mem(struct se_if_device_ctx *dev_ctx)
+{
+	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
+	struct se_if_priv *priv = dev_ctx->priv;
+
+	INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_out);
+	INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_in);
+
+	/*
+	 * Allocate some memory for data exchanges with S40x.
+	 * This will be used for data not requiring secure memory.
+	 */
+	se_shared_mem_mgmt->non_secure_mem.ptr =
+			dma_alloc_coherent(priv->dev,
+					   MAX_DATA_SIZE_PER_USER,
+					   &se_shared_mem_mgmt->non_secure_mem.dma_addr,
+					   GFP_KERNEL);
+	if (!se_shared_mem_mgmt->non_secure_mem.ptr)
+		return -ENOMEM;
+
+	se_shared_mem_mgmt->non_secure_mem.size = MAX_DATA_SIZE_PER_USER;
+	se_shared_mem_mgmt->non_secure_mem.pos = 0;
+
+	return 0;
+}
+
+static void cleanup_se_shared_mem(struct se_if_device_ctx *dev_ctx)
+{
+	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
+	struct se_if_priv *priv = dev_ctx->priv;
+
+	/* Unmap secure memory shared buffer. */
+	if (se_shared_mem_mgmt->secure_mem.ptr)
+		devm_iounmap(priv->dev,
+			     (void __iomem *)se_shared_mem_mgmt->secure_mem.ptr);
+
+	se_shared_mem_mgmt->secure_mem.ptr = NULL;
+	se_shared_mem_mgmt->secure_mem.dma_addr = 0;
+	se_shared_mem_mgmt->secure_mem.size = 0;
+	se_shared_mem_mgmt->secure_mem.pos = 0;
+
+	/* Free non-secure shared buffer. */
+	dma_free_coherent(priv->dev, MAX_DATA_SIZE_PER_USER,
+			  se_shared_mem_mgmt->non_secure_mem.ptr,
+			  se_shared_mem_mgmt->non_secure_mem.dma_addr);
+
+	se_shared_mem_mgmt->non_secure_mem.ptr = NULL;
+	se_shared_mem_mgmt->non_secure_mem.dma_addr = 0;
+	se_shared_mem_mgmt->non_secure_mem.size = 0;
+	se_shared_mem_mgmt->non_secure_mem.pos = 0;
+}
+
+/* Need to copy the output data to user-device context.
+ */
+static int se_dev_ctx_cpy_out_data(struct se_if_device_ctx *dev_ctx)
+{
+	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
+	struct se_if_priv *priv = dev_ctx->priv;
+	struct se_buf_desc *b_desc, *temp;
+	bool do_cpy = true;
+
+	list_for_each_entry_safe(b_desc, temp, &se_shared_mem_mgmt->pending_out, link) {
+		if (b_desc->usr_buf_ptr && b_desc->shared_buf_ptr && do_cpy) {
+			dev_dbg(priv->dev,
+				"Copying output data to user.");
+			if (do_cpy && copy_to_user(b_desc->usr_buf_ptr,
+						   b_desc->shared_buf_ptr,
+						   b_desc->size)) {
+				dev_err(priv->dev,
+					"Failure copying output data to user.");
+				do_cpy = false;
+			}
+		}
+
+		if (b_desc->shared_buf_ptr)
+			memset(b_desc->shared_buf_ptr, 0, b_desc->size);
+
+		list_del(&b_desc->link);
+		kfree(b_desc);
+	}
+
+	return do_cpy ? 0 : -EFAULT;
+}
+
+/*
+ * Clean the used Shared Memory space,
+ * whether its Input Data copied from user buffers, or
+ * Data received from FW.
+ */
+static void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx)
+{
+	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
+	struct list_head *pending_lists[] = {&se_shared_mem_mgmt->pending_in,
+						&se_shared_mem_mgmt->pending_out};
+	struct se_buf_desc *b_desc, *temp;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		list_for_each_entry_safe(b_desc, temp,
+					 pending_lists[i], link) {
+			if (b_desc->shared_buf_ptr)
+				memset(b_desc->shared_buf_ptr, 0, b_desc->size);
+
+			list_del(&b_desc->link);
+			kfree(b_desc);
+		}
+	}
+	se_shared_mem_mgmt->secure_mem.pos = 0;
+	se_shared_mem_mgmt->non_secure_mem.pos = 0;
+}
+
+static int add_b_desc_to_pending_list(void *shared_ptr_with_pos,
+				      struct se_ioctl_setup_iobuf *io,
+				      struct se_if_device_ctx *dev_ctx)
+{
+	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
+	struct se_buf_desc *b_desc = NULL;
+
+	b_desc = kzalloc(sizeof(*b_desc), GFP_KERNEL);
+	if (!b_desc)
+		return -ENOMEM;
+
+	b_desc->shared_buf_ptr = shared_ptr_with_pos;
+	b_desc->usr_buf_ptr = io->user_buf;
+	b_desc->size = io->length;
+
+	if (io->flags & SE_IO_BUF_FLAGS_IS_INPUT) {
+		/*
+		 * buffer is input:
+		 * add an entry in the "pending input buffers" list so
+		 * that copied data can be cleaned from shared memory
+		 * later.
+		 */
+		list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_in);
+	} else {
+		/*
+		 * buffer is output:
+		 * add an entry in the "pending out buffers" list so data
+		 * can be copied to user space when receiving Secure-Enclave
+		 * response.
+		 */
+		list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_out);
+	}
+
+	return 0;
+}
+
+/* interface for managed res to unregister a character device */
+static void if_misc_deregister(void *miscdevice)
+{
+	misc_deregister(miscdevice);
+}
+
+static int init_device_context(struct se_if_priv *priv, int ch_id,
+			       struct se_if_device_ctx **new_dev_ctx,
+			       const struct file_operations *se_if_fops)
+{
+	struct se_if_device_ctx *dev_ctx;
+	int ret = 0;
+
+	if (ch_id)
+		dev_ctx = kzalloc(sizeof(*dev_ctx), GFP_KERNEL);
+	else
+		dev_ctx = devm_kzalloc(priv->dev, sizeof(*dev_ctx), GFP_KERNEL);
+
+	if (!dev_ctx)
+		return -ENOMEM;
+
+	dev_ctx->priv = priv;
+
+	if (ch_id)
+		dev_ctx->devname = kasprintf(GFP_KERNEL, "%s%d_ch%d",
+					     get_se_if_name(priv->if_defs->se_if_type),
+					     priv->if_defs->se_instance_id,
+					     ch_id);
+	else
+		dev_ctx->devname = devm_kasprintf(priv->dev, GFP_KERNEL, "%s%d_ch%d",
+						  get_se_if_name(priv->if_defs->se_if_type),
+						  priv->if_defs->se_instance_id,
+						  ch_id);
+	if (!dev_ctx->devname) {
+		if (ch_id)
+			kfree(dev_ctx);
+
+		return -ENOMEM;
+	}
+
+	mutex_init(&dev_ctx->fops_lock);
+
+	*new_dev_ctx = dev_ctx;
+
+	if (ch_id) {
+		list_add_tail(&dev_ctx->link, &priv->dev_ctx_list);
+		priv->active_devctx_count++;
+
+		ret = init_se_shared_mem(dev_ctx);
+		if (ret < 0) {
+			kfree(dev_ctx->devname);
+			kfree(dev_ctx);
+			*new_dev_ctx = NULL;
+			return ret;
+		}
+
+		return ret;
+	}
+
+	/* Only for ch_id = 0:
+	 * - register the misc device.
+	 * - add action
+	 */
+	dev_ctx->miscdev = devm_kzalloc(priv->dev, sizeof(*dev_ctx->miscdev), GFP_KERNEL);
+	if (!dev_ctx->miscdev) {
+		*new_dev_ctx = NULL;
+		return -ENOMEM;
+	}
+
+	dev_ctx->miscdev->name = dev_ctx->devname;
+	dev_ctx->miscdev->minor = MISC_DYNAMIC_MINOR;
+	dev_ctx->miscdev->fops = se_if_fops;
+	dev_ctx->miscdev->parent = priv->dev;
+	ret = misc_register(dev_ctx->miscdev);
+	if (ret) {
+		dev_err(priv->dev, "failed to register misc device %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = devm_add_action(priv->dev, if_misc_deregister,
+			      dev_ctx->miscdev);
+	if (ret) {
+		dev_err(priv->dev,
+			"failed[%d] to add action to the misc-dev\n",
+			ret);
+		misc_deregister(dev_ctx->miscdev);
+	}
+
+	return ret;
+}
+
+static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
+					    u64 arg)
+{
+	struct se_ioctl_cmd_snd_rcv_rsp_info cmd_snd_rcv_rsp_info = {0};
+	struct se_if_priv *priv = dev_ctx->priv;
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_api_msg *rx_msg __free(kfree) = NULL;
+	int err = 0;
+
+	if (copy_from_user(&cmd_snd_rcv_rsp_info, (u8 __user *)arg,
+			   sizeof(cmd_snd_rcv_rsp_info))) {
+		dev_err(priv->dev,
+			"%s: Failed to copy cmd_snd_rcv_rsp_info from user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+		goto exit;
+	}
+
+	if (cmd_snd_rcv_rsp_info.tx_buf_sz < SE_MU_HDR_SZ) {
+		dev_err(priv->dev,
+			"%s: User buffer too small(%d < %d)\n",
+			dev_ctx->devname,
+			cmd_snd_rcv_rsp_info.tx_buf_sz,
+			SE_MU_HDR_SZ);
+		err = -ENOSPC;
+		goto exit;
+	}
+
+	rx_msg = kzalloc(cmd_snd_rcv_rsp_info.rx_buf_sz, GFP_KERNEL);
+	if (!rx_msg) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	tx_msg = memdup_user(cmd_snd_rcv_rsp_info.tx_buf,
+			     cmd_snd_rcv_rsp_info.tx_buf_sz);
+	if (IS_ERR(tx_msg)) {
+		err = PTR_ERR(tx_msg);
+		goto exit;
+	}
+
+	if (tx_msg->header.tag != priv->if_defs->cmd_tag) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	if (tx_msg->header.ver == priv->if_defs->fw_api_ver &&
+	    !get_load_fw_instance(priv)->is_fw_loaded) {
+		err = se_load_firmware(priv);
+		if (err) {
+			dev_err(priv->dev, "Could not send the message as FW is not loaded.");
+			err = -EPERM;
+			goto exit;
+		}
+	}
+	set_se_rcv_msg_timeout(SE_RCV_MSG_LONG_TIMEOUT);
+
+	err = ele_msg_send_rcv(dev_ctx,
+			       tx_msg,
+			       cmd_snd_rcv_rsp_info.tx_buf_sz,
+			       rx_msg,
+			       cmd_snd_rcv_rsp_info.rx_buf_sz);
+	if (err < 0)
+		goto exit;
+
+	dev_dbg(priv->dev,
+		"%s: %s %s\n",
+		dev_ctx->devname,
+		__func__,
+		"message received, start transmit to user");
+
+	/* We may need to copy the output data to user before
+	 * delivering the completion message.
+	 */
+	err = se_dev_ctx_cpy_out_data(dev_ctx);
+	if (err < 0)
+		goto exit;
+
+	/* Copy data from the buffer */
+	print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4,
+			     rx_msg,
+			     cmd_snd_rcv_rsp_info.rx_buf_sz, false);
+
+	if (copy_to_user(cmd_snd_rcv_rsp_info.rx_buf, rx_msg,
+			 cmd_snd_rcv_rsp_info.rx_buf_sz)) {
+		dev_err(priv->dev,
+			"%s: Failed to copy to user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+
+exit:
+
+	/* shared memory is allocated before this IOCTL */
+	se_dev_ctx_shared_mem_cleanup(dev_ctx);
+
+	if (copy_to_user((void __user *)arg, &cmd_snd_rcv_rsp_info,
+			 sizeof(cmd_snd_rcv_rsp_info))) {
+		dev_err(priv->dev,
+			"%s: Failed to copy cmd_snd_rcv_rsp_info from user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+
+	return err;
+}
+
+static int se_ioctl_get_mu_info(struct se_if_device_ctx *dev_ctx,
+				u64 arg)
+{
+	struct se_if_priv *priv = dev_ctx->priv;
+	struct se_if_node *if_node;
+	struct se_ioctl_get_if_info if_info;
+	int err = 0;
+
+	if_node = container_of(priv->if_defs, typeof(*if_node), if_defs);
+
+	if_info.se_if_id = 0;
+	if_info.interrupt_idx = 0;
+	if_info.tz = 0;
+	if_info.did = if_node->se_if_did;
+	if_info.cmd_tag = priv->if_defs->cmd_tag;
+	if_info.rsp_tag = priv->if_defs->rsp_tag;
+	if_info.success_tag = priv->if_defs->success_tag;
+	if_info.base_api_ver = priv->if_defs->base_api_ver;
+	if_info.fw_api_ver = priv->if_defs->fw_api_ver;
+
+	dev_dbg(priv->dev,
+		"%s: info [se_if_id: %d, irq_idx: %d, tz: 0x%x, did: 0x%x]\n",
+		dev_ctx->devname,
+		if_info.se_if_id, if_info.interrupt_idx,
+		if_info.tz, if_info.did);
+
+	if (copy_to_user((u8 __user *)arg, &if_info, sizeof(if_info))) {
+		dev_err(priv->dev,
+			"%s: Failed to copy mu info to user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+
+	return err;
+}
+
+/*
+ * Copy a buffer of data to/from the user and return the address to use in
+ * messages
+ */
+static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
+					u64 arg)
+{
+	struct se_shared_mem *shared_mem = NULL;
+	struct se_ioctl_setup_iobuf io = {0};
+	int err = 0;
+	u32 pos;
+
+	if (copy_from_user(&io, (u8 __user *)arg, sizeof(io))) {
+		dev_err(dev_ctx->priv->dev,
+			"%s: Failed copy iobuf config from user\n",
+			dev_ctx->devname);
+		return -EFAULT;
+	}
+
+	dev_dbg(dev_ctx->priv->dev,
+		"%s: io [buf: %p(%d) flag: %x]\n",
+		dev_ctx->devname,
+		io.user_buf, io.length, io.flags);
+
+	if (io.length == 0 || !io.user_buf) {
+		/*
+		 * Accept NULL pointers since some buffers are optional
+		 * in FW commands. In this case we should return 0 as
+		 * pointer to be embedded into the message.
+		 * Skip all data copy part of code below.
+		 */
+		io.ele_addr = 0;
+		goto copy;
+	}
+
+	/* No specific requirement for this buffer. */
+	shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem;
+
+	/* Check there is enough space in the shared memory. */
+	dev_dbg(dev_ctx->priv->dev,
+		"%s: req_size = %d, max_size= %d, curr_pos = %d",
+		dev_ctx->devname,
+		round_up(io.length, 8u),
+		shared_mem->size, shared_mem->pos);
+
+	if (shared_mem->size < shared_mem->pos ||
+	    round_up(io.length, 8u) > (shared_mem->size - shared_mem->pos)) {
+		dev_err(dev_ctx->priv->dev,
+			"%s: Not enough space in shared memory\n",
+			dev_ctx->devname);
+		return -ENOMEM;
+	}
+
+	/* Allocate space in shared memory. 8 bytes aligned. */
+	pos = shared_mem->pos;
+	shared_mem->pos += round_up(io.length, 8u);
+	io.ele_addr = (u64)shared_mem->dma_addr + pos;
+
+	memset(shared_mem->ptr + pos, 0, io.length);
+	if ((io.flags & SE_IO_BUF_FLAGS_IS_INPUT) ||
+	    (io.flags & SE_IO_BUF_FLAGS_IS_IN_OUT)) {
+		/*
+		 * buffer is input:
+		 * copy data from user space to this allocated buffer.
+		 */
+		if (copy_from_user(shared_mem->ptr + pos, io.user_buf,
+				   io.length)) {
+			dev_err(dev_ctx->priv->dev,
+				"%s: Failed copy data to shared memory\n",
+				dev_ctx->devname);
+			return -EFAULT;
+		}
+	}
+
+	err = add_b_desc_to_pending_list(shared_mem->ptr + pos,
+					 &io,
+					 dev_ctx);
+	if (err < 0)
+		dev_err(dev_ctx->priv->dev,
+			"%s: Failed to allocate/link b_desc.",
+			dev_ctx->devname);
+
+copy:
+	/* Provide the EdgeLock Enclave address to user space only if success.*/
+	if (copy_to_user((u8 __user *)arg, &io, sizeof(io))) {
+		dev_err(dev_ctx->priv->dev,
+			"%s: Failed to copy iobuff setup to user.",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+
+	return err;
+}
+
+/* IOCTL to provide SoC information */
+static int se_ioctl_get_se_soc_info_handler(struct se_if_device_ctx *dev_ctx,
+					    u64 arg)
+{
+	struct se_ioctl_get_soc_info soc_info;
+	int err = -EINVAL;
+
+	soc_info.soc_id = get_se_soc_id(dev_ctx->priv);
+	soc_info.soc_rev = var_se_info.soc_rev;
+
+	err = (int)copy_to_user((u8 __user *)arg, (u8 *)(&soc_info), sizeof(soc_info));
+	if (err) {
+		dev_err(dev_ctx->priv->dev,
+			"%s: Failed to copy soc info to user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+
+	return err;
+}
+
+/*
+ * File operations for user-space
+ */
+
+/* Write a message to the MU. */
+static ssize_t se_if_fops_write(struct file *fp, const char __user *buf,
+				size_t size, loff_t *ppos)
+{
+	struct se_if_device_ctx *dev_ctx = fp->private_data;
+	struct se_api_msg *tx_msg __free(kfree) = NULL;
+	struct se_if_priv *priv = dev_ctx->priv;
+	int err;
+
+	dev_dbg(priv->dev,
+		"%s: write from buf (%p)%zu, ppos=%lld\n",
+		dev_ctx->devname,
+		buf, size, ((ppos) ? *ppos : 0));
+
+	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
+		return -EBUSY;
+
+	if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	if (size < SE_MU_HDR_SZ) {
+		dev_err(priv->dev,
+			"%s: User buffer too small(%zu < %d)\n",
+			dev_ctx->devname,
+			size, SE_MU_HDR_SZ);
+		err = -ENOSPC;
+		goto exit;
+	}
+
+	tx_msg = memdup_user(buf, size);
+	if (IS_ERR(tx_msg)) {
+		err = PTR_ERR(tx_msg);
+		goto exit;
+	}
+
+	print_hex_dump_debug("from user ", DUMP_PREFIX_OFFSET, 4, 4,
+			     tx_msg, size, false);
+
+	err = ele_msg_send(dev_ctx, tx_msg, size);
+
+exit:
+	mutex_unlock(&dev_ctx->fops_lock);
+	return err;
+}
+
+/*
+ * Read a message from the MU.
+ * Blocking until a message is available.
+ */
+static ssize_t se_if_fops_read(struct file *fp, char __user *buf,
+			       size_t size, loff_t *ppos)
+{
+	struct se_if_device_ctx *dev_ctx = fp->private_data;
+	struct se_if_priv *priv = dev_ctx->priv;
+	int err;
+
+	dev_dbg(priv->dev,
+		"%s: read to buf %p(%zu), ppos=%lld\n",
+		dev_ctx->devname,
+		buf, size, ((ppos) ? *ppos : 0));
+
+	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
+		return -EBUSY;
+
+	if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	err = ele_msg_rcv(dev_ctx, &priv->cmd_receiver_clbk_hdl);
+	if (err < 0) {
+		dev_err(priv->dev,
+			"%s: Err[0x%x]:Interrupted by signal.\n",
+			dev_ctx->devname, err);
+		dev_dbg(priv->dev,
+			"Current active dev-ctx count = %d.\n",
+			dev_ctx->priv->active_devctx_count);
+		goto exit;
+	}
+
+	/* We may need to copy the output data to user before
+	 * delivering the completion message.
+	 */
+	err = se_dev_ctx_cpy_out_data(dev_ctx);
+	if (err < 0)
+		goto exit;
+
+	/* Copy data from the buffer */
+	print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4,
+			     priv->cmd_receiver_clbk_hdl.rx_msg,
+			     priv->cmd_receiver_clbk_hdl.rx_msg_sz,
+			     false);
+
+	if (copy_to_user(buf, priv->cmd_receiver_clbk_hdl.rx_msg,
+			 priv->cmd_receiver_clbk_hdl.rx_msg_sz)) {
+		dev_err(priv->dev,
+			"%s: Failed to copy to user\n",
+			dev_ctx->devname);
+		err = -EFAULT;
+	}
+	err = priv->cmd_receiver_clbk_hdl.rx_msg_sz;
+exit:
+	priv->cmd_receiver_clbk_hdl.rx_msg_sz = 0;
+
+	se_dev_ctx_shared_mem_cleanup(dev_ctx);
+
+	mutex_unlock(&dev_ctx->fops_lock);
+	return err;
+}
+
+/* Open a character device. */
+static int se_if_fops_open(struct inode *nd, struct file *fp)
+{
+	struct miscdevice *miscdev = fp->private_data;
+	struct se_if_priv *priv = dev_get_drvdata(miscdev->parent);
+	struct se_if_device_ctx *misc_dev_ctx = priv->priv_dev_ctx;
+	struct se_if_device_ctx *dev_ctx;
+	int err = 0;
+
+	if (mutex_lock_interruptible(&misc_dev_ctx->fops_lock))
+		return -EBUSY;
+
+	priv->dev_ctx_mono_count++;
+	err = init_device_context(priv,
+				  priv->dev_ctx_mono_count ?
+					priv->dev_ctx_mono_count
+					: priv->dev_ctx_mono_count++,
+				  &dev_ctx, NULL);
+	if (err)
+		dev_err(priv->dev,
+			"Failed[0x%x] to create device contexts.\n",
+			err);
+	else
+		fp->private_data = dev_ctx;
+
+	mutex_unlock(&misc_dev_ctx->fops_lock);
+	return err;
+}
+
+/* Close a character device. */
+static int se_if_fops_close(struct inode *nd, struct file *fp)
+{
+	struct se_if_device_ctx *dev_ctx = fp->private_data;
+	struct se_if_priv *priv = dev_ctx->priv;
+
+	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
+		return -EBUSY;
+
+	/* check if this device was registered as command receiver. */
+	if (priv->cmd_receiver_clbk_hdl.dev_ctx == dev_ctx) {
+		priv->cmd_receiver_clbk_hdl.dev_ctx = NULL;
+		kfree(priv->cmd_receiver_clbk_hdl.rx_msg);
+		priv->cmd_receiver_clbk_hdl.rx_msg = NULL;
+	}
+
+	se_dev_ctx_shared_mem_cleanup(dev_ctx);
+	cleanup_se_shared_mem(dev_ctx);
+
+	priv->active_devctx_count--;
+	list_del(&dev_ctx->link);
+
+	mutex_unlock(&dev_ctx->fops_lock);
+	kfree(dev_ctx->devname);
+	kfree(dev_ctx);
+
+	return 0;
+}
+
+/* IOCTL entry point of a character device */
+static long se_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	struct se_if_device_ctx *dev_ctx = fp->private_data;
+	struct se_if_priv *priv = dev_ctx->priv;
+	int err;
+
+	/* Prevent race during change of device context */
+	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
+		return -EBUSY;
+
+	switch (cmd) {
+	case SE_IOCTL_ENABLE_CMD_RCV:
+		if (!priv->cmd_receiver_clbk_hdl.dev_ctx) {
+			if (!priv->cmd_receiver_clbk_hdl.rx_msg) {
+				priv->cmd_receiver_clbk_hdl.rx_msg =
+						kzalloc(MAX_NVM_MSG_LEN,
+							GFP_KERNEL);
+				if (!priv->cmd_receiver_clbk_hdl.rx_msg) {
+					err = -ENOMEM;
+					break;
+				}
+			}
+			priv->cmd_receiver_clbk_hdl.rx_msg_sz = MAX_NVM_MSG_LEN;
+			priv->cmd_receiver_clbk_hdl.dev_ctx = dev_ctx;
+			err = 0;
+		} else {
+			err = -EBUSY;
+		}
+		break;
+	case SE_IOCTL_GET_MU_INFO:
+		err = se_ioctl_get_mu_info(dev_ctx, arg);
+		break;
+	case SE_IOCTL_SETUP_IOBUF:
+		err = se_ioctl_setup_iobuf_handler(dev_ctx, arg);
+		break;
+	case SE_IOCTL_GET_SOC_INFO:
+		err = se_ioctl_get_se_soc_info_handler(dev_ctx, arg);
+		break;
+	case SE_IOCTL_CMD_SEND_RCV_RSP:
+		err = se_ioctl_cmd_snd_rcv_rsp_handler(dev_ctx, arg);
+		break;
+	default:
+		err = -EINVAL;
+		dev_dbg(priv->dev,
+			"%s: IOCTL %.8x not supported\n",
+			dev_ctx->devname,
+			cmd);
+	}
+
+	mutex_unlock(&dev_ctx->fops_lock);
+
+	return (long)err;
+}
+
+/* Char driver setup */
+static const struct file_operations se_if_fops = {
+	.open		= se_if_fops_open,
+	.owner		= THIS_MODULE,
+	.release	= se_if_fops_close,
+	.unlocked_ioctl = se_ioctl,
+	.read		= se_if_fops_read,
+	.write		= se_if_fops_write,
+};
+
 /* interface for managed res to free a mailbox channel */
 static void if_mbox_free_channel(void *mbox_chan)
 {
@@ -321,6 +1074,7 @@ static int se_if_request_channel(struct device *dev,
 
 static void se_if_probe_cleanup(void *plat_dev)
 {
+	struct se_if_device_ctx *dev_ctx, *t_dev_ctx;
 	struct platform_device *pdev = plat_dev;
 	struct device *dev = &pdev->dev;
 	struct se_fw_load_info *load_fw;
@@ -345,6 +1099,13 @@ static void se_if_probe_cleanup(void *plat_dev)
 		load_fw->imem.buf = NULL;
 	}
 
+	if (priv->dev_ctx_mono_count) {
+		list_for_each_entry_safe(dev_ctx, t_dev_ctx, &priv->dev_ctx_list, link) {
+			list_del(&dev_ctx->link);
+			priv->active_devctx_count--;
+		}
+	}
+
 	/* No need to check, if reserved memory is allocated
 	 * before calling for its release. Or clearing the
 	 * un-set bit.
@@ -410,6 +1171,7 @@ static int se_if_probe(struct platform_device *pdev)
 					     "Unable to get sram pool = %s.",
 					     if_node->pool_name);
 	}
+	INIT_LIST_HEAD(&priv->dev_ctx_list);
 
 	if (if_node->reserved_dma_ranges) {
 		ret = of_reserved_mem_device_init(dev);
@@ -418,6 +1180,12 @@ static int se_if_probe(struct platform_device *pdev)
 					    "Failed to init reserved memory region.");
 	}
 
+	ret = init_device_context(priv, 0, &priv->priv_dev_ctx, &se_if_fops);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed[0x%x] to create device contexts.",
+				     ret);
+
 	if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) {
 		ret = get_se_soc_info(priv, se_info);
 		if (ret)
@@ -444,7 +1212,7 @@ static int se_if_probe(struct platform_device *pdev)
 		}
 	}
 	dev_info(dev, "i.MX secure-enclave: %s%d interface to firmware, configured.",
-		 SE_TYPE_STR_HSM,
+		 get_se_if_name(priv->if_defs->se_if_type),
 		 priv->if_defs->se_instance_id);
 
 	return ret;
@@ -461,6 +1229,7 @@ static int se_suspend(struct device *dev)
 	struct se_fw_load_info *load_fw;
 	int ret = 0;
 
+	set_se_rcv_msg_timeout(SE_RCV_MSG_DEFAULT_TIMEOUT);
 	load_fw = get_load_fw_instance(priv);
 
 	if (load_fw->imem_mgmt)
diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h
index 32547bc97ca3..c103563091d5 100644
--- a/drivers/firmware/imx/se_ctrl.h
+++ b/drivers/firmware/imx/se_ctrl.h
@@ -13,6 +13,7 @@
 #define MAX_FW_LOAD_RETRIES		50
 
 #define RES_STATUS(x)			FIELD_GET(0x000000ff, x)
+#define MAX_DATA_SIZE_PER_USER		(65 * 1024)
 #define MAX_NVM_MSG_LEN			(256)
 #define MESSAGING_VERSION_6		0x6
 #define MESSAGING_VERSION_7		0x7
@@ -20,6 +21,7 @@
 struct se_clbk_handle {
 	struct completion done;
 	bool signal_rcvd;
+	struct se_if_device_ctx *dev_ctx;
 	u32 rx_msg_sz;
 	/* Assignment of the rx_msg buffer to held till the
 	 * received content as part callback function, is copied.
@@ -34,6 +36,41 @@ struct se_imem_buf {
 	u32 state;
 };
 
+struct se_buf_desc {
+	u8 *shared_buf_ptr;
+	void __user *usr_buf_ptr;
+	u32 size;
+	struct list_head link;
+};
+
+struct se_shared_mem {
+	dma_addr_t dma_addr;
+	u32 size;
+	u32 pos;
+	u8 *ptr;
+};
+
+struct se_shared_mem_mgmt_info {
+	struct list_head pending_in;
+	struct list_head pending_out;
+
+	struct se_shared_mem secure_mem;
+	struct se_shared_mem non_secure_mem;
+};
+
+/* Private struct for each char device instance. */
+struct se_if_device_ctx {
+	struct se_if_priv *priv;
+	struct miscdevice *miscdev;
+	const char *devname;
+
+	/* process one file operation at a time. */
+	struct mutex fops_lock;
+
+	struct se_shared_mem_mgmt_info se_shared_mem_mgmt;
+	struct list_head link;
+};
+
 /* Header of the messages exchange with the EdgeLock Enclave */
 struct se_msg_hdr {
 	u8 ver;
@@ -78,6 +115,12 @@ struct se_if_priv {
 
 	struct gen_pool *mem_pool;
 	const struct se_if_defines *if_defs;
+
+	struct se_if_device_ctx *priv_dev_ctx;
+	struct list_head dev_ctx_list;
+	u32 active_devctx_count;
+	u32 dev_ctx_mono_count;
 };
 
+char *get_se_if_name(u8 se_if_id);
 #endif
diff --git a/include/uapi/linux/se_ioctl.h b/include/uapi/linux/se_ioctl.h
new file mode 100644
index 000000000000..29a9b1ec5ec3
--- /dev/null
+++ b/include/uapi/linux/se_ioctl.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause*/
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef SE_IOCTL_H
+#define SE_IOCTL_H
+
+#include <linux/types.h>
+
+#define SE_TYPE_STR_DBG			"dbg"
+#define SE_TYPE_STR_HSM			"hsm"
+#define SE_TYPE_ID_UNKWN		0x0
+#define SE_TYPE_ID_DBG			0x1
+#define SE_TYPE_ID_HSM			0x2
+/* IOCTL definitions. */
+
+struct se_ioctl_setup_iobuf {
+	void __user *user_buf;
+	__u32 length;
+	__u32 flags;
+	__u64 ele_addr;
+};
+
+struct se_ioctl_shared_mem_cfg {
+	__u32 base_offset;
+	__u32 size;
+};
+
+struct se_ioctl_get_if_info {
+	__u8 se_if_id;
+	__u8 interrupt_idx;
+	__u8 tz;
+	__u8 did;
+	__u8 cmd_tag;
+	__u8 rsp_tag;
+	__u8 success_tag;
+	__u8 base_api_ver;
+	__u8 fw_api_ver;
+};
+
+struct se_ioctl_cmd_snd_rcv_rsp_info {
+	__u32 __user *tx_buf;
+	int tx_buf_sz;
+	__u32 __user *rx_buf;
+	int rx_buf_sz;
+};
+
+struct se_ioctl_get_soc_info {
+	__u16 soc_id;
+	__u16 soc_rev;
+};
+
+/* IO Buffer Flags */
+#define SE_IO_BUF_FLAGS_IS_OUTPUT	(0x00u)
+#define SE_IO_BUF_FLAGS_IS_INPUT	(0x01u)
+#define SE_IO_BUF_FLAGS_USE_SEC_MEM	(0x02u)
+#define SE_IO_BUF_FLAGS_USE_SHORT_ADDR	(0x04u)
+#define SE_IO_BUF_FLAGS_IS_IN_OUT	(0x10u)
+
+/* IOCTLS */
+#define SE_IOCTL			0x0A /* like MISC_MAJOR. */
+
+/*
+ * ioctl to designated the current fd as logical-reciever.
+ * This is ioctl is send when the nvm-daemon, a slave to the
+ * firmware is started by the user.
+ */
+#define SE_IOCTL_ENABLE_CMD_RCV	_IO(SE_IOCTL, 0x01)
+
+/*
+ * ioctl to get the buffer allocated from the memory, which is shared
+ * between kernel and FW.
+ * Post allocation, the kernel tagged the allocated memory with:
+ *  Output
+ *  Input
+ *  Input-Output
+ *  Short address
+ *  Secure-memory
+ */
+#define SE_IOCTL_SETUP_IOBUF	_IOWR(SE_IOCTL, 0x03, \
+					struct se_ioctl_setup_iobuf)
+
+/*
+ * ioctl to get the mu information, that is used to exchange message
+ * with FW, from user-spaced.
+ */
+#define SE_IOCTL_GET_MU_INFO	_IOR(SE_IOCTL, 0x04, \
+					struct se_ioctl_get_if_info)
+/*
+ * ioctl to get SoC Info from user-space.
+ */
+#define SE_IOCTL_GET_SOC_INFO      _IOR(SE_IOCTL, 0x06, \
+					struct se_ioctl_get_soc_info)
+
+/*
+ * ioctl to send command and receive response from user-space.
+ */
+#define SE_IOCTL_CMD_SEND_RCV_RSP _IOWR(SE_IOCTL, 0x07, \
+					struct se_ioctl_cmd_snd_rcv_rsp_info)
+#endif

-- 
2.43.0



From Matt.Coster at imgtec.com  Tue Mar 11 03:33:23 2025
From: Matt.Coster at imgtec.com (Matt Coster)
Date: Tue, 11 Mar 2025 10:33:23 +0000
Subject: [PATCH v3 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <20250311-flashy-rattlesnake-of-rain-dcc4f6@krzk-bin>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f@imgtec.com>
 <20250311-flashy-rattlesnake-of-rain-dcc4f6@krzk-bin>
Message-ID: <cc6a19b3-ba35-465c-9fa6-a764df7c01c1@imgtec.com>

On 11/03/2025 07:50, Krzysztof Kozlowski wrote:
> On Mon, Mar 10, 2025 at 01:10:25PM +0000, Matt Coster wrote:
>> The first compatible strings added for the AXE-1-16M are not sufficient to
>> accurately describe all the IMG Rogue GPUs. The current "img,img-axe"
>> string refers to the entire family of Series AXE GPUs, but this is
>> primarily a marketing term and does not denote a level of hardware
>> similarity any greater than just "Rogue".
>>
>> The more specific "img,img-axe-1-16m" string refers to individual AXE-1-16M
>> GPU. For example, unlike the rest of the Series AXE GPUs, the AXE-1-16M
>> only uses a single power domain.
>>
>> The situation is actually slightly worse than described in the first
>> paragraph, since many "series" (such as Series BXS found in the TI AM68
>> among others and added later in this series) contain cores with both Rogue
>> and Volcanic architectures.
>>
>> Besides attempting to move away from vague groupings defined only
>> by marketing terms, we want to draw a line between properties inherent to
>> the IP core and choices made by the silicon vendor at integration time.
>> For instance, the number of power domains is a property of the IP core,
>> whereas the decision to use one or multiple clocks is a vendor one.
>>
>> In the original compatible strings, we must use "ti,am62-gpu" to constrain
>> both of these properties since the number of power domains cannot be fixed
>> for "img,img-axe".
>>
>> Work is currently underway to add support for volcanic-based Imagination
>> GPUs, for which bindings will be added in "img,powervr-volcanic.yaml".
>> As alluded to previously, the split between rogue and volcanic cores is
>> non-obvious at times, so add a generic top-level "img,img-rogue" compatible
>> string here to allow for simpler differentiation in devicetrees without
>> referring back to the bindings.
>>
>> The currently supported GPU (AXE-1-16M) only requires a single power
>> domain. Subsequent patches will add support for BXS-4-64 MC1, which has
>> two power domains. Add infrastructure now to allow for this.
>>
>> Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
>> are DMA devices. The decision for coherency is made at integration time and
>> this property should be applied wherever it accurately describes the
>> vendor integration.
>>
>> Note that the new required properties for power domains are conditional on
>> the new base compatible string to avoid an ABI break.
>>
>> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
>> ---
>> Changes in v3:
>> - Remove unnecessary example
>> - Remove second power domain details, add these where they're used instead
>> - Avoid ABI breaks by limiting new required properties to new compatible
>>   strings and making all binding changes in a single patch.
>> - Links to v2:
>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
>> ---
>>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 43 ++++++++++++++++++----
>>  1 file changed, 36 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> index 256e252f8087fa0d6081f771a01601d34b66fe19..5c16b2881447c9cda78e5bb46569e2f675d740c4 100644
>> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>> @@ -12,10 +12,20 @@ maintainers:
>>  
>>  properties:
>>    compatible:
>> -    items:
>> -      - enum:
>> -          - ti,am62-gpu
>> -      - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
>> +    oneOf:
>> +      - items:
>> +          - enum:
>> +              - ti,am62-gpu
>> +          - const: img,img-axe-1-16m
>> +          - const: img,img-rogue
> 
> That's still ABI break. You got here NAK. You ust preserve img,img-axe.
> Your marketing troubles do not concern Linux.

I think I'm misunderstanding something here. Is keeping the existing
compatible string around in the deprecated item below not sufficient to
maintain the existing ABI?

Would adding img,img-axe back into the updated list (bringing it to four
elements) be acceptable?

> 
>> +
>> +      # This legacy combination of compatible strings was introduced early on
>> +      # before the more specific GPU identifiers were used.
>> +      - items:
>> +          - enum:
>> +              - ti,am62-gpu
>> +          - const: img,img-axe
>> +        deprecated: true
>>  
>>    reg:
>>      maxItems: 1
>> @@ -34,8 +44,13 @@ properties:
>>    interrupts:
>>      maxItems: 1
>>  
>> -  power-domains:
>> -    maxItems: 1
>> +  power-domains: true
> 
> No, widest constraints always stay here.

Ack

> 
>> +
>> +  power-domain-names:
>> +    items:
>> +      - const: a
> 
> That's not a useful name. Are you sure that datasheet calls it power
> domain A?

Sadly yes. With the Volcanic architecture the power domains get real
names, but until then we were stuck with abc. I shared a snipet from the
BXS-4-64 TRM with Conor in the replies to the V1 series in [1].

Cheers,
Matt

> 
>> +
>> +  dma-coherent: true
> 
> Best regards,
> Krzysztof
> 

[1]: https://lore.kernel.org/all/ff4e96e4-ebc2-4c50-9715-82ba3d7b8612 at imgtec.com

-- 
Matt Coster
E: matt.coster at imgtec.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 236 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/7f86d496/attachment.sig>

From maz at kernel.org  Tue Mar 11 03:34:38 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 10:34:38 +0000
Subject: [PATCH v1 4/5] arm64/kvm: support to handle the HDBSSF event
In-Reply-To: <20250311040321.1460-5-yezhenyu2@huawei.com>
References: <20250311040321.1460-1-yezhenyu2@huawei.com>
	<20250311040321.1460-5-yezhenyu2@huawei.com>
Message-ID: <86senjony9.wl-maz@kernel.org>

On Tue, 11 Mar 2025 04:03:20 +0000,
Zhenyu Ye <yezhenyu2 at huawei.com> wrote:
> 
> From: eillon <yezhenyu2 at huawei.com>
> 
> Updating the dirty bitmap based on the HDBSS buffer. Similar
> to the implementation of the x86 pml feature, KVM flushes the
> buffers on all VM-Exits, thus we only need to kick running
> vCPUs to force a VM-Exit.
> 
> Signed-off-by: eillon <yezhenyu2 at huawei.com>
> ---
>  arch/arm64/kvm/arm.c         | 10 ++++++++
>  arch/arm64/kvm/handle_exit.c | 47 ++++++++++++++++++++++++++++++++++++
>  arch/arm64/kvm/mmu.c         |  7 ++++++
>  3 files changed, 64 insertions(+)
> 
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 825cfef3b1c2..fceceeead011 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -1845,7 +1845,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>  
>  void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
>  {
> +	/*
> +	 * Flush all CPUs' dirty log buffers to the dirty_bitmap.  Called
> +	 * before reporting dirty_bitmap to userspace.  KVM flushes the buffers
> +	 * on all VM-Exits, thus we only need to kick running vCPUs to force a
> +	 * VM-Exit.
> +	 */
> +	struct kvm_vcpu *vcpu;
> +	unsigned long i;
>  
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		kvm_vcpu_kick(vcpu);

We don't need this outside of HDBSS. Why impose it on everyone else?

I'm also perplexed by the requirement to flush on all exits. Why can't
this be deferred to vcpu_put() only? Specially given that I don't see
any use of this stuff outside of a VHE system.

>  }
>  
>  static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 512d152233ff..db9d7e1f72bf 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -330,6 +330,50 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
>  	return arm_exit_handlers[esr_ec];
>  }
>  
> +#define HDBSS_ENTRY_VALID_SHIFT 0
> +#define HDBSS_ENTRY_VALID_MASK (1UL << HDBSS_ENTRY_VALID_SHIFT)
> +#define HDBSS_ENTRY_IPA_SHIFT 12
> +#define HDBSS_ENTRY_IPA_MASK GENMASK_ULL(55, HDBSS_ENTRY_IPA_SHIFT)

This has no place here. Move this stuff somewhere else. And rewrite in
a more concise way:

#define HDBSS_ENTRY_VALID	BIT(0)
#define HDBSS_ENTRY_IPA		GENMASK(55, 12)

> +
> +static void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu)
> +{
> +	int idx, curr_idx;
> +	u64 *hdbss_buf;
> +
> +	if (!vcpu->kvm->enable_hdbss)

This control is odd. You track the logging per-VM, but dump the
buffers per-vcpu.

> +		return;
> +
> +	dsb(sy);
> +	isb();
> +	curr_idx = HDBSSPROD_IDX(read_sysreg_s(SYS_HDBSSPROD_EL2));
> +
> +	/* Do nothing if HDBSS buffer is empty or br_el2 is NULL */
> +	if (curr_idx == 0 || vcpu->arch.hdbss.br_el2 == 0)
> +		return;
> +
> +	hdbss_buf = page_address(phys_to_page(HDBSSBR_BADDR(vcpu->arch.hdbss.br_el2)));

Do you see why it is silly to keep the raw value of the register? It'd
be far better to just keep the VA (and maybe the PA as well), and
build the register value as required.

> +	if (!hdbss_buf) {
> +		kvm_err("Enter flush hdbss buffer with buffer == NULL!");
> +		return;
> +	}
> +
> +	for (idx = 0; idx < curr_idx; idx++) {
> +		u64 gpa;
> +
> +		gpa = hdbss_buf[idx];
> +		if (!(gpa & HDBSS_ENTRY_VALID_MASK))
> +			continue;
> +
> +		gpa = gpa & HDBSS_ENTRY_IPA_MASK;
> +		kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);

Isn't there a requirement to hold a lock of some sort here?

> +	}
> +
> +	/* reset HDBSS index */
> +	write_sysreg_s(0, SYS_HDBSSPROD_EL2);
> +	dsb(sy);

Where is the DSB(SY) requirement coming from if the logging is
per-vcpu and that each vcpu gets its own buffer?

> +	isb();

And you want to do that on each exit? How will userspace intercept
this? Frankly, this should be moved to put-time, and only be
guaranteed  to be visible to userspace when the vcpus are outside of
the kernel.

> +}
> +
>  /*
>   * We may be single-stepping an emulated instruction. If the emulation
>   * has been completed in the kernel, we can return to userspace with a
> @@ -365,6 +409,9 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
>  {
>  	struct kvm_run *run = vcpu->run;
>  
> +	if (vcpu->kvm->enable_hdbss)
> +		kvm_flush_hdbss_buffer(vcpu);
> +
>  	if (ARM_SERROR_PENDING(exception_index)) {
>  		/*
>  		 * The SError is handled by handle_exit_early(). If the guest
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 9c11e2292b1e..3e0781ae0ae1 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1790,6 +1790,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
>  	ipa = fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
>  	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
>  
> +	/*
> +	 * HDBSS buffer already flushed when enter handle_trap_exceptions().
> +	 * Nothing to do here.
> +	 */
> +	if (ESR_ELx_ISS2(esr) & ESR_ELx_HDBSSF)
> +		return 1;
> +

Can this happen on an instruction abort? Also, you seem to be ignoring
any type of *faults*. Nothing can fail at all?

	M.

-- 
Without deviation from the norm, progress is not possible.


From shinichiro.kawasaki at wdc.com  Tue Mar 11 03:43:58 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 19:43:58 +0900
Subject: [PATCH v2 1/2] nvme: move error logging from nvme_end_req() to __nvme_end_req()
In-Reply-To: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
Message-ID: <20250311104359.1767728-2-shinichiro.kawasaki@wdc.com>

Before the Commit 1f47ed294a2b ("block: cleanup and fix batch completion
adding conditions"), blk_mq_add_to_batch() did not add failed
passthrough requests to batch, and returned false. After the commit,
blk_mq_add_to_batch() always adds passthrough requests to batch
regardless of whether the request failed or not, and returns true. This
affected error logging feature in the NVME driver.

Before the commit, the call chain of failed passthrough request was as
follows:

nvme_handle_cqe()
 blk_mq_add_to_batch() .. false is returned, then call nvme_pci_complete_rq()
 nvme_pci_complete_rq()
  nvme_complete_rq()
   nvme_end_req()
    nvme_log_err_passthru() .. error logging
    __nvme_end_req()        .. end of the rqeuest

After the commit, the call chain is as follows:

nvme_handle_cqe()
 blk_mq_add_to_batch() .. true is returned, then set nvme_pci_complete_batch()
 ..
 nvme_pci_complete_batch()
  nvme_complete_batch()
   nvme_complete_batch_req()
    __nvme_end_req() .. end of the request, without error logging

To make the error logging feature work again for passthrough requests, move the
nvme_log_err_passthru() call from nvme_end_req() to __nvme_end_req().

While at it, move nvme_log_error() call for non-passthrough requests together
with nvme_log_err_passthru(). Even though the trigger commit does not affect
non-passthrough requests, move it together for code simplicity.

Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
Reviewed-by: Hannes Reinecke <hare at suse.de>
Reviewed-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f028913e2e62..8359d0aa0e44 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -431,6 +431,12 @@ static inline void nvme_end_req_zoned(struct request *req)
 
 static inline void __nvme_end_req(struct request *req)
 {
+	if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) {
+		if (blk_rq_is_passthrough(req))
+			nvme_log_err_passthru(req);
+		else
+			nvme_log_error(req);
+	}
 	nvme_end_req_zoned(req);
 	nvme_trace_bio_complete(req);
 	if (req->cmd_flags & REQ_NVME_MPATH)
@@ -441,12 +447,6 @@ void nvme_end_req(struct request *req)
 {
 	blk_status_t status = nvme_error_status(nvme_req(req)->status);
 
-	if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) {
-		if (blk_rq_is_passthrough(req))
-			nvme_log_err_passthru(req);
-		else
-			nvme_log_error(req);
-	}
 	__nvme_end_req(req);
 	blk_mq_end_request(req, status);
 }
-- 
2.47.0



From shinichiro.kawasaki at wdc.com  Tue Mar 11 03:42:32 2025
From: shinichiro.kawasaki at wdc.com (Shinichiro Kawasaki)
Date: Tue, 11 Mar 2025 10:42:32 +0000
Subject: [PATCH 2/2] block: change blk_mq_add_to_batch() third argument
 type to blk_status_t
In-Reply-To: <Z8_wjZUNvM7JAWAQ@infradead.org>
References: <20250311024144.1762333-1-shinichiro.kawasaki@wdc.com>
 <20250311024144.1762333-3-shinichiro.kawasaki@wdc.com>
 <Z8_wjZUNvM7JAWAQ@infradead.org>
Message-ID: <azwm5cno6croi4l3pbp73z53wa77i4gleetrvn5jjf7khi2e2t@ru4yijtbgluz>

On Mar 11, 2025 / 01:13, Christoph Hellwig wrote:
> On Tue, Mar 11, 2025 at 11:41:44AM +0900, Shin'ichiro Kawasaki wrote:
> > However, blk_mq_add_to_batch() callers do not pass negative error
> > values. Instead, they pass status codes defined in various ways:
> > 
> > - NVMe PCI and Apple drivers pass NVMe status code
> > - virtio_blk driver passes the virtblk request header status byte
> > - null_blk driver passes blk_status_t
> 
> The __force cast in null_blk should have been a big fat warning..
> 
> > To correct the ioerror check within blk_mq_add_to_batch(), make all
> > callers to uniformly pass the argument as blk_status_t. Modify the
> > callers to translate their specific status codes into blk_status_t. For
> > this translation, export the helper function nvme_error_status(). Adjust
> > blk_mq_add_to_batch() to translate blk_status_t back into the error
> > number for the appropriate check.
> 
> This still looks a bit ugly because of all the conversions to a
> blk_status_t just to convert it back to a errno just to check for
> a non-zero value (blk_status_to_errno can't return a positive value).
> 
> I suspect simply passing a "bool is_error" might actually be cleaner
> than that,

Thanks. Hannes made same comment. Wiil do so in v2.

> combined with a proper kerneldoc comment for
> blk_mq_add_to_batch explaining how to set it?

Will add it in v2.

I Will send out v2 soon for furhter review.

From shinichiro.kawasaki at wdc.com  Tue Mar 11 03:43:57 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 19:43:57 +0900
Subject: [PATCH v2 0/2] block: nvme: fix blktests nvme/039 failure
Message-ID: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>

Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
conditions") in the kernel tag v6.14-rc3 triggered blktests nvme/039
failure [1].

The test case injects errors to the NVMe driver and confirms the errors
are logged. The first half of the test checks it for non-passthrough
requests, and the second half checks for passthrough requests. The
commit made both halves fail.

This series addresses the test case failure. The first patch covers the
passthrough requests, and the second patch covers the non-passthrough
requests.

[1] https://lkml.kernel.org/linux-block/y7m5kyk5r2eboyfsfprdvhmoo27ur46pz3r2kwb4puhxjhbvt6 at zgh4dg3ewya3/

Changes from v1:
* 1st patch: Added Reviewed-by tags
* 2nd patch: Replaced argument blk_status_t with boolean 'is_error'
             Added kerneldoc of blk_mq_add_to_batch() arguments

Shin'ichiro Kawasaki (2):
  nvme: move error logging from nvme_end_req() to __nvme_end_req()
  block: change blk_mq_add_to_batch() third argument type to bool

 drivers/block/null_blk/main.c |  4 ++--
 drivers/block/virtio_blk.c    |  5 +++--
 drivers/nvme/host/apple.c     |  3 ++-
 drivers/nvme/host/core.c      | 12 ++++++------
 drivers/nvme/host/pci.c       |  5 +++--
 include/linux/blk-mq.h        | 11 ++++++++---
 6 files changed, 24 insertions(+), 16 deletions(-)

-- 
2.47.0



From shinichiro.kawasaki at wdc.com  Tue Mar 11 03:43:59 2025
From: shinichiro.kawasaki at wdc.com (Shin'ichiro Kawasaki)
Date: Tue, 11 Mar 2025 19:43:59 +0900
Subject: [PATCH v2 2/2] block: change blk_mq_add_to_batch() third argument type to bool
In-Reply-To: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
Message-ID: <20250311104359.1767728-3-shinichiro.kawasaki@wdc.com>

Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
conditions") modified the evaluation criteria for the third argument,
'ioerror', in the blk_mq_add_to_batch() function. Initially, the
function had checked if 'ioerror' equals zero. Following the commit, it
started checking for negative error values, with the presumption that
such values, for instance -EIO, would be passed in.

However, blk_mq_add_to_batch() callers do not pass negative error
values. Instead, they pass status codes defined in various ways:

- NVMe PCI and Apple drivers pass NVMe status code
- virtio_blk driver passes the virtblk request header status byte
- null_blk driver passes blk_status_t

These codes are either zero or positive, therefore the revised check
fails to function as intended. Specifically, with the NVMe PCI driver,
this modification led to the failure of the blktests test case nvme/039.
In this test scenario, errors are artificially injected to the NVMe
driver, resulting in positive NVMe status codes passed to
blk_mq_add_to_batch(), which unexpectedly processes the failed I/O in a
batch. Hence the failure.

To correct the ioerror check within blk_mq_add_to_batch(), make all
callers to uniformly pass the argument as boolean. Modify the callers to
check their specific status codes and pass the boolean value 'is_error'.
Also describe the arguments of blK_mq_add_to_batch as kerneldoc.

Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
 drivers/block/null_blk/main.c |  4 ++--
 drivers/block/virtio_blk.c    |  5 +++--
 drivers/nvme/host/apple.c     |  3 ++-
 drivers/nvme/host/pci.c       |  5 +++--
 include/linux/blk-mq.h        | 11 ++++++++---
 5 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index d94ef37480bd..fdc7a0b2af10 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1549,8 +1549,8 @@ static int null_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 		cmd = blk_mq_rq_to_pdu(req);
 		cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req),
 						blk_rq_sectors(req));
-		if (!blk_mq_add_to_batch(req, iob, (__force int) cmd->error,
-					blk_mq_end_request_batch))
+		if (!blk_mq_add_to_batch(req, iob, cmd->error != BLK_STS_OK,
+					 blk_mq_end_request_batch))
 			blk_mq_end_request(req, cmd->error);
 		nr++;
 	}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 6a61ec35f426..91cde76a4b3e 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -1207,11 +1207,12 @@ static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 
 	while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
 		struct request *req = blk_mq_rq_from_pdu(vbr);
+		u8 status = virtblk_vbr_status(vbr);
 
 		found++;
 		if (!blk_mq_complete_request_remote(req) &&
-		    !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
-						virtblk_complete_batch))
+		    !blk_mq_add_to_batch(req, iob, status != VIRTIO_BLK_S_OK,
+					 virtblk_complete_batch))
 			virtblk_request_done(req);
 	}
 
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index a060f69558e7..8971aca41e63 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -599,7 +599,8 @@ static inline void apple_nvme_handle_cqe(struct apple_nvme_queue *q,
 	}
 
 	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
-	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
+	    !blk_mq_add_to_batch(req, iob,
+				 nvme_req(req)->status != NVME_SC_SUCCESS,
 				 apple_nvme_complete_batch))
 		apple_nvme_complete_rq(req);
 }
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 640590b21728..75de86e235ad 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1130,8 +1130,9 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
 
 	trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail);
 	if (!nvme_try_complete_req(req, cqe->status, cqe->result) &&
-	    !blk_mq_add_to_batch(req, iob, nvme_req(req)->status,
-					nvme_pci_complete_batch))
+	    !blk_mq_add_to_batch(req, iob,
+				 nvme_req(req)->status != NVME_SC_SUCCESS,
+				 nvme_pci_complete_batch))
 		nvme_pci_complete_rq(req);
 }
 
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 71f4f0cc3dac..d904e870e72d 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -855,9 +855,14 @@ static inline bool blk_mq_is_reserved_rq(struct request *rq)
 /*
  * Batched completions only work when there is no I/O error and no special
  * ->end_io handler.
+ *
+ * @req: The request to add to batch
+ * @iob: The batch to add the request
+ * @is_error: Specify true if the request failed with an error
+ * @io_comp_batch: The completaion handler for the request
  */
 static inline bool blk_mq_add_to_batch(struct request *req,
-				       struct io_comp_batch *iob, int ioerror,
+				       struct io_comp_batch *iob, bool is_error,
 				       void (*complete)(struct io_comp_batch *))
 {
 	/*
@@ -865,7 +870,7 @@ static inline bool blk_mq_add_to_batch(struct request *req,
 	 * 1) No batch container
 	 * 2) Has scheduler data attached
 	 * 3) Not a passthrough request and end_io set
-	 * 4) Not a passthrough request and an ioerror
+	 * 4) Not a passthrough request and failed with an error
 	 */
 	if (!iob)
 		return false;
@@ -874,7 +879,7 @@ static inline bool blk_mq_add_to_batch(struct request *req,
 	if (!blk_rq_is_passthrough(req)) {
 		if (req->end_io)
 			return false;
-		if (ioerror < 0)
+		if (is_error)
 			return false;
 	}
 
-- 
2.47.0



From james.clark at linaro.org  Tue Mar 11 03:51:39 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 11 Mar 2025 10:51:39 +0000
Subject: [PATCH] coresight: docs: Remove target sink from examples
In-Reply-To: <20250311102200.GJ9682@e132581.arm.com>
References: <20241210144933.295798-1-james.clark@linaro.org>
 <20250311102200.GJ9682@e132581.arm.com>
Message-ID: <898f1265-522f-44aa-a7da-879870b18807@linaro.org>



On 11/03/2025 10:22 am, Leo Yan wrote:
> On Tue, Dec 10, 2024 at 02:49:28PM +0000, James Clark wrote:
>>
>> Previously the sink had to be specified, but now it auto selects one by
>> default. Including a sink in the examples causes issues when copy
>> pasting the command because it might not work if that sink isn't
>> present. Remove the sink from all the basic examples and create a new
>> section specifically about overriding the default one.
>>
>> Make the text a but more concise now that it's in the advanced section,
>> and similarly for removing the old kernel advice.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>   Documentation/trace/coresight/coresight.rst   | 41 ++++++++-----------
>>   .../userspace-api/perf_ring_buffer.rst        |  4 +-
>>   2 files changed, 18 insertions(+), 27 deletions(-)
>>
>> diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
>> index d4f93d6a2d63..806699871b80 100644
>> --- a/Documentation/trace/coresight/coresight.rst
>> +++ b/Documentation/trace/coresight/coresight.rst
>> @@ -462,44 +462,35 @@ queried by the perf command line tool:
>>
>>                  cs_etm//                                    [Kernel PMU event]
>>
>> -       linaro at linaro-nano:~$
>> -
>>   Regardless of the number of tracers available in a system (usually equal to the
>>   amount of processor cores), the "cs_etm" PMU will be listed only once.
>>
>>   A Coresight PMU works the same way as any other PMU, i.e the name of the PMU is
>> -listed along with configuration options within forward slashes '/'.  Since a
>> -Coresight system will typically have more than one sink, the name of the sink to
>> -work with needs to be specified as an event option.
>> -On newer kernels the available sinks are listed in sysFS under
>> +provided along with configuration options within forward slashes '/' (see
>> +`Config option formats`_).
>> +
>> +Advanced Perf framework usage
>> +-----------------------------
>> +
>> +Sink selection
>> +~~~~~~~~~~~~~~
>> +
>> +An appropriate sink will be selected automatically for use with Perf, but since
>> +there will typically be more than one sink, the name of the sink to use may be
>> +specified as a special config option prefixed with '@'.
>> +
>> +The available sinks are listed in sysFS under
>>   ($SYSFS)/bus/event_source/devices/cs_etm/sinks/::
>>
>>          root at localhost:/sys/bus/event_source/devices/cs_etm/sinks# ls
>>          tmc_etf0  tmc_etr0  tpiu0
> 
> Just a minor comment.  To reflect the latest hardware, it is good to
> mention the TRBE case, users should not and cannot specify TRBE as the

Is that strictly true? From looking at the code I think you could pick 
one TRBE sink as long as you are only tracing from a single ETM. 
Although yeah it would be pointless.

> sink name.  The driver will give priority for TRBE by default unless
> users specify other sink types.
> 

IMO mentioning TRBE would be overly wordy and not really add anything. 
Removing the sink from all the base examples is exactly to make TRBE 
work without going into detail about why. And the advanced section 
doesn't mention TRBE because manually picking it is never right.

> Otherwise, this is a good polish for me.
> 
> Thanks,
> Leo
> 
>> -On older kernels, this may need to be found from the list of coresight devices,
>> -available under ($SYSFS)/bus/coresight/devices/::
>> -
>> -       root:~# ls /sys/bus/coresight/devices/
>> -        etm0     etm1     etm2         etm3  etm4      etm5      funnel0
>> -        funnel1  funnel2  replicator0  stm0  tmc_etf0  tmc_etr0  tpiu0
>>          root at linaro-nano:~# perf record -e cs_etm/@tmc_etr0/u --per-thread program
>>
>> -As mentioned above in section "Device Naming scheme", the names of the devices could
>> -look different from what is used in the example above. One must use the device names
>> -as it appears under the sysFS.
>> -
>> -The syntax within the forward slashes '/' is important.  The '@' character
>> -tells the parser that a sink is about to be specified and that this is the sink
>> -to use for the trace session.
>> -
>>   More information on the above and other example on how to use Coresight with
>>   the perf tools can be found in the "HOWTO.md" file of the openCSD gitHub
>>   repository [#third]_.
>>
>> -Advanced perf framework usage
>> ------------------------------
>> -
>>   AutoFDO analysis using the perf tools
>>   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>> @@ -508,7 +499,7 @@ perf can be used to record and analyze trace of programs.
>>   Execution can be recorded using 'perf record' with the cs_etm event,
>>   specifying the name of the sink to record to, e.g::
>>
>> -    perf record -e cs_etm/@tmc_etr0/u --per-thread
>> +    perf record -e cs_etm//u --per-thread
>>
>>   The 'perf report' and 'perf script' commands can be used to analyze execution,
>>   synthesizing instruction and branch events from the instruction trace.
>> @@ -572,7 +563,7 @@ sort example is from the AutoFDO tutorial (https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgcc.gnu.org%2Fwiki%2FAutoFDO%2FTuto&data=05%7C02%7Cleo.yan%40arm.com%7C0d4875673b894a332a5508dd192a1f35%7Cf34e597957d94aaaad4db122a662184d%7C0%7C0%7C638694390923618348%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=vX1RVi4hA2gEqrVk9lvMV8UFVDzvClvUN7yILwv0788%3D&reserved=0
>>          Bubble sorting array of 30000 elements
>>          5910 ms
>>
>> -       $ perf record -e cs_etm/@tmc_etr0/u --per-thread taskset -c 2 ./sort
>> +       $ perf record -e cs_etm//u --per-thread taskset -c 2 ./sort
>>          Bubble sorting array of 30000 elements
>>          12543 ms
>>          [ perf record: Woken up 35 times to write data ]
>> diff --git a/Documentation/userspace-api/perf_ring_buffer.rst b/Documentation/userspace-api/perf_ring_buffer.rst
>> index bde9d8cbc106..dc71544532ce 100644
>> --- a/Documentation/userspace-api/perf_ring_buffer.rst
>> +++ b/Documentation/userspace-api/perf_ring_buffer.rst
>> @@ -627,7 +627,7 @@ regular ring buffer.
>>   AUX events and AUX trace data are two different things.  Let's see an
>>   example::
>>
>> -        perf record -a -e cycles -e cs_etm/@tmc_etr0/ -- sleep 2
>> +        perf record -a -e cycles -e cs_etm// -- sleep 2
>>
>>   The above command enables two events: one is the event *cycles* from PMU
>>   and another is the AUX event *cs_etm* from Arm CoreSight, both are saved
>> @@ -766,7 +766,7 @@ only record AUX trace data at a specific time point which users are
>>   interested in.  E.g. below gives an example of how to take snapshots
>>   with 1 second interval with Arm CoreSight::
>>
>> -  perf record -e cs_etm/@tmc_etr0/u -S -a program &
>> +  perf record -e cs_etm//u -S -a program &
>>     PERFPID=$!
>>     while true; do
>>         kill -USR2 $PERFPID
>> --
>> 2.34.1
>>
>> _______________________________________________
>> CoreSight mailing list -- coresight at lists.linaro.org
>> To unsubscribe send an email to coresight-leave at lists.linaro.org



From ryan.roberts at arm.com  Tue Mar 11 03:58:54 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue, 11 Mar 2025 10:58:54 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <5ff34bd0-7823-4f31-9f13-bf60d3345b99@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
 <5ff34bd0-7823-4f31-9f13-bf60d3345b99@arm.com>
Message-ID: <7cca1edf-fd1b-4622-999e-8e0ca098dfe2@arm.com>

On 11/03/2025 10:17, Suzuki K Poulose wrote:
> On 03/03/2025 10:17, Ryan Roberts wrote:
>> On 01/03/2025 01:32, Yang Shi wrote:
>>>
>>>
>>>
>>> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>>>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>>>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>>>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>>>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>>>> BBM level 2 is claimed.
>>>>
>>>> Add the feature and testing for it under arm_smmu_sva_supported().
>>>>
>>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>>> ---
>>>> ?? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>>>> ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>>>> ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>>>> ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>>>> ?? 4 files changed, 13 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>> index 63f6d356dc77..1022c63f81b2 100644
>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>>>> arm64_cpu_capabilities *caps, int sco
>>>> ?????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>>>> ?????????????????? return false;
>>>> ?????????? }
>>>> -
>>>> -??????? return true;
>>>> ?????? } else if (scope & SCOPE_LOCAL_CPU) {
>>>> ?????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>>>> ??????????? * If we have the correct MIDR, but the kernel booted on an
>>>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>>>> arm64_cpu_capabilities *caps, int sco
>>>> ??????????? * we have an incorrect MIDR, but the kernel booted on a
>>>> ??????????? * sufficient CPU, we will not bring up this CPU.
>>>> ??????????? */
>>>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>>>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>>>> +??????????? return false;
>>>> ?????? }
>>>> ?? -??? return false;
>>>> +??? return has_cpuid_feature(caps, scope);
>>>
>>> Do we really need this? IIRC, it means the MIDR has to be in the allow list
>>> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register
>>> set.
>>
>> Miko, I think this should have been squashed into patch #1? It doesn't belong in
>> this patch.
>>
>> Yang, we discussed this internally and decided that we thought it was best to
>> still require BBML2 being advertised in the feature register. That way if trying
>> to use KVM to emulate a CPU that is in the allow list but doesn't really support
>> BBML2, we won't try to use it.
>>
>> But we still end up with the same problem if running on a physical CPU that
>> supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So
> 
> I don't understand the problem here ? In the worst case, if we want to disable
> the BBML2 feature on a given CPU, we could provide an id-
> override to reset the value of BBML2. Or provide a kernel parameter to
> disable this in case we want to absolutely disable the feature on a
> "distro" kernel.

Hi Suzuki,

Sorry perhaps I'm confusing everyone; As I recall, we had a conversation before
Miko posted this series where you were suggesting we should check BOTH that all
the CPUs' MIDRs are in the allow list AND that BBML2 is advertised in MMFR2 in
order to decide to enable the CPU feature. My understanding was that without the
MMFR2 check, you were concerned that in a virtualization scenario, a CPU's MIDR
could be overridden to emulate a CPU that is in the allow list, but in reality
the CPU does not support BBML2. We would then enable BBML2 and BadThings (TM)
will happen. So additionally checking the MMFR2 would solve this.

But Yang is saying that he plans to add the AmpereOne to the allow list because
it does support BBML2+NOCONFLICT semantics and we want to benefit from that. But
AmpereOne does not advertise BBML2 in it's MMFR2. So with the current approach,
adding AmpereOne to the allow list is not sufficient to enable the feature.

But back to your original justification for checking the MMFR2; I don't think
that really solves the problem in general, because we don't just require BBML2,
we require BBML2+NOCONFLICT. And we can only determine that from the MIDR. So
why bother checking MMFR2?

I guess we could provide an id-override on the kernel command line to *enable*
BBML2 for AmpereOne, but that's not going to be suitable for mass deployment, I
don't think?

Thanks,
Ryan

> 
> Suzuki
> 
> 
>> given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
>> remove this check.
>>
>> Thanks,
>> Ryan
>>
>>
>>>
>>> Thanks,
>>> Yang
>>>
>>>> ?? }
>>>> ?? ? #ifdef CONFIG_ARM64_PAN
>>>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>>>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>> index 9ba596430e7c..6ba182572788 100644
>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>>>> ?????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>>>> ?????? }
>>>> ?? +??? if (system_supports_bbml2_noabort())
>>>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>>>> +
>>>> ?????? if ((smmu->features & feat_mask) != feat_mask)
>>>> ?????????? return false;
>>>> ?? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>>>> arm/arm-smmu-v3/arm-smmu-v3.c
>>>> index 358072b4e293..dcee0bdec924 100644
>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>>>> arm_smmu_device *smmu)
>>>> ?????? if (FIELD_GET(IDR3_RIL, reg))
>>>> ?????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>>>> ?? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>>>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>>>> +
>>>> ?????? /* IDR5 */
>>>> ?????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>>>> ?? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>>>> arm/arm-smmu-v3/arm-smmu-v3.h
>>>> index bd9d7c85576a..85eaf3ab88c2 100644
>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>>>> ?? #define ARM_SMMU_IDR3??????????? 0xc
>>>> ?? #define IDR3_FWB??????????? (1 << 8)
>>>> ?? #define IDR3_RIL??????????? (1 << 10)
>>>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>>>> +#define IDR3_BBML1??????????? (1 << 11)
>>>> +#define IDR3_BBML2??????????? (2 << 11)
>>>> ?? ? #define ARM_SMMU_IDR5??????????? 0x14
>>>> ?? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>>>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>>>> ?? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>>>> ?? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>>>> ?? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>>>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>>>> ?????? u32??????????????? features;
>>>> ?? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)
>>>
>>
> 



From peng.fan at nxp.com  Tue Mar 11 04:12:45 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Tue, 11 Mar 2025 11:12:45 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
References: <CAGETcx87Stfkru9gJrc1sf=PtFGLY7=jrfFaCzK5Z4hq+2TCzg@mail.gmail.com>
 <Z65U2SMwSiOFYC0v@pluto> <20250218010949.GB22580@nxa18884-linux>
 <Z7Rf9GPdO2atP89Z@bogus> <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus> <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus> <Z87sGF_jHKau_FMe@bogus>
 <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
Message-ID: <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: RE: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> fwnode for scmi cpufreq
> 
> > Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting
> > fwnode for scmi cpufreq
> >
> > On Mon, Mar 10, 2025 at 11:59:33AM +0000, Sudeep Holla wrote:
> > > On Mon, Mar 10, 2025 at 10:45:44AM +0000, Peng Fan wrote:
> > > > > Subject: Re: [PATCH 1/4] firmware: arm_scmi: bus: Bypass
> setting
> > > > > fwnode for scmi cpufreq
> > > > >
> > > > > On Thu, Feb 20, 2025 at 08:59:18AM +0800, Peng Fan wrote:
> > > > > >
> > > > > > Sorry, if I misunderstood.
> > > > > >
> > > > > > I will give a look on this and propose a RFC.
> > > > > >
> > > > > > DT maintainers may ask for a patchset including binding
> change
> > > > > > and driver changes to get a whole view on the compatible
> stuff.
> > > > > >
> > > > > > BTW, Cristian, Saravana if you have any objections/ideas or
> > > > > > would
> > > > > take
> > > > > > on this effort, please let me know.
> > > > > >
> > > > >
> > > > > Can you point me to the DTS with which you are seeing this
> issue ?
> > > > > I am trying to reproduce the issue but so far not successful. I
> > > > > did move to power-domains for CPUFreq on Juno. IIUC all we
> > need is
> > > > > both cpufreq and performance genpd drivers in the kernel and
> > then
> > > > > GPU using perf genpd fails with probe deferral right ? I need
> > > > > pointers to reproduce the issue so that I can check if what I
> > > > > have cooked up as a solution really works.
> > > >
> > > > This is in downstream tree:
> > > >
> >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > gi
> > > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> > 6.6.y%2Farch%2Farm64%2Fbo
> > > >
> >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L2971&data=05%7C02%7Cpe
> > ng.fan%40
> > > >
> >
> nxp.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2
> > b4c6fa92cd99
> > > >
> > c5c301635%7C0%7C0%7C638772109152491267%7CUnknown%7CT
> > WFpbGZsb3d8eyJFb
> > > >
> >
> XB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOI
> > joiTWFpb
> > > >
> >
> CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=nHFiE5qD7NpmdGmj
> > SUL0mIdOq8P4W
> > > > ErqVq8xE%2Fb3WM0%3D&reserved=0
> > > >
> >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > gi
> > > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> > 6.6.y%2Farch%2Farm64%2Fbo
> > > >
> >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L3043&data=05%7C02%7Cpe
> > ng.fan%40
> > > >
> >
> nxp.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2
> > b4c6fa92cd99
> > > >
> > c5c301635%7C0%7C0%7C638772109152521215%7CUnknown%7CT
> > WFpbGZsb3d8eyJFb
> > > >
> >
> XB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOI
> > joiTWFpb
> > > >
> >
> CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=M4LJumL6y9bQ%2FL
> > ocPvlNiMnCFtO
> > > > vODYNrC0DGbbydxY%3D&reserved=0
> > > >
> >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > gi
> > > > thub.com%2Fnxp-imx%2Flinux-imx%2Fblob%2Flf-
> > 6.6.y%2Farch%2Farm64%2Fbo
> > > >
> >
> ot%2Fdts%2Ffreescale%2Fimx95.dtsi%23L80&data=05%7C02%7Cpeng
> > .fan%40nx
> > > >
> >
> p.com%7C72778d531e944c7214ca08dd5fd95012%7C686ea1d3bc2b4
> > c6fa92cd99c5
> > > >
> >
> c301635%7C0%7C0%7C638772109152541725%7CUnknown%7CTWF
> > pbGZsb3d8eyJFbXB
> > > >
> >
> 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoi
> > TWFpbCI
> > > >
> >
> sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=VpxcGrB6Dnr9yCO%2F
> > wl8sEw1LYSlX5
> > > > nPHqnlJ5mKm%2B7A%3D&reserved=0
> > > >
> > > > we are using "power-domains" property for cpu perf and gpu/vpu
> > perf.
> > > >
> > > > If cpufreq.off=1 is set in bootargs, the vpu/gpu driver will defer
> > probe.
> > > >
> > >
> > > OK, does the probe of these drivers get called or they don't as the
> > > driver core doesn't allow that ? I just have a dummy driver for mali
> > > on Juno which just does dev_pm_domain_attach_list() in the probe
> > and
> > > it seem to succeed even when cpufreq.off=1 is passed. I see
> > > scmi-cpufreq failing with -ENODEV as expected.
> > >
> > > I need to follow the code and check if I can somehow reproduce.
> Also
> > > are you sure this is not with anything in the downstream code ?
> Also
> > > have you tried this with v6.14-rc* ? Are you sure all the fw_devlink
> > > code is backported in the tree you pointed me which is v6.6-stable ?
> > >
> >
> > I even tried the above branch, but no luck. The above is neither
> > latest stable version nor pure stable. It has few extra patches
> > backported though IIUC. Anyways any pointers to enable me to
> reproduce
> > the issue would be much appreciated.
> 
> I will setup test based latest linux-next and share results. Please wait.


Based on linux-next, I added below node:

+
+               test at 4f000000 {
+                       compatible = "fsl,imx-test";
+                       power-domains = <&scmi_devpd IMX95_PD_VPU>, <&scmi_perf IMX95_PERF_VPU>;
+                       power-domain-names = "vpumix", "vpuperf";
+               };

I not write a driver for it, so just check devlink information from sysfs interface.

>From below sys directory, this test device takes scmi_dev.4 and scmi_dev.3 as supplier.
root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# ls
driver_override  of_node  subsystem                          supplier:scmi_protocol:scmi_dev.4  waiting_for_supplier
modalias         power    supplier:scmi_protocol:scmi_dev.3  uevent

Checking scmi_dev.4 below, it is scmi cpufreq, not the scmi perf device.
scmi_dev.3 is correct, it is genpd.

root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# cat /sys/bus/scmi_protocol/devices/scmi_dev.4/modalias
scmi_dev.4:13:cpufreq
root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# cat /sys/bus/scmi_protocol/devices/scmi_dev.3/modalias
scmi_dev.3:11:genpd
root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000#


So it is clear that wrong fw_devlink is created, it is because scmi cpufreq device is
created earlier and when device_add, the below logic makes the fwnode pointer points
to scmi cpufreq device.
        if (dev->fwnode && !dev->fwnode->dev) {                                                     
                dev->fwnode->dev = dev;                                                             
                fw_devlink_link_device(dev);                                                        
        }

Hope this is clear.

Regards,
Peng.

> 
> Thanks,
> Peng.
> >
> > --
> > Regards,
> > Sudeep



From vkoul at kernel.org  Tue Mar 11 04:13:46 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 12:13:46 +0100
Subject: [PATCH] phy: rockchip: usbdp: Check these parameters only
 when the corresponding set flags are set
In-Reply-To: <1379400c.90c.19582b05f74.Coremail.andyshrk@163.com>
References: <20250306065952.485809-1-andyshrk@163.com>
 <Z86UOmPg/UDSBajZ@vaman>
 <1379400c.90c.19582b05f74.Coremail.andyshrk@163.com>
Message-ID: <Z9Aa6v1/1KRdZDKE@vaman>

On 11-03-25, 08:52, Andy Yan wrote:

> Do you mean we should do it like this:
> 
> static int rk_udphy_dp_phy_configure(struct phy *phy,
>                                      union phy_configure_opts *opts)
> {
>         struct rk_udphy *udphy = phy_get_drvdata(phy);
>         struct phy_configure_opts_dp *dp = &opts->dp;
>         u32 i, val, lane;
>         int ret;
> 
>        .............
>       if (dp->set_rate)
>            	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
>      if (dp->set_lanes)
>                 ret = rk_udphy_dp_phy_verify_link_lanes(dp->lanes);
>      if (dp->set_voltates)
>                ret = rk_udphy_dp_phy_verify_link_voltate(dp->voltate);
> 
> 
> Add helper for each of them ?

That would look better for sure

-- 
~Vinod


From dan.carpenter at linaro.org  Tue Mar 11 04:16:40 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Tue, 11 Mar 2025 14:16:40 +0300
Subject: [PATCH v2] staging: vchiq_arm: Don't use %pK through printk
In-Reply-To: <20250311-restricted-pointers-vchiq_arm-v2-1-a14e1c0681fc@linutronix.de>
References: <20250311-restricted-pointers-vchiq_arm-v2-1-a14e1c0681fc@linutronix.de>
Message-ID: <01a1fcd4-b626-44a2-b850-bf0d8b9efbfa@stanley.mountain>

On Tue, Mar 11, 2025 at 10:40:49AM +0100, Thomas Wei?schuh wrote:
> In the past %pK was preferable to %p as it would not leak raw pointer
> values into the kernel log.
> Since commit ad67b74d2469 ("printk: hash addresses printed with %p")
> the regular %p has been improved to avoid this issue.
> Furthermore, restricted pointers ("%pK") were never meant to be used
> through printk(). They can still unintentionally leak raw pointers or
> acquire sleeping looks in atomic contexts.
> 
> Switch to the regular pointer formatting which is safer and
> easier to reason about.
> There are still a few users of %pK left, but these use it through seq_file,
> for which its usage is safe.
> 
> Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
> Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
> ---
> Changes in v2:
> - Fix wrong replacement with invalid %K (Dan Carpenter)
> - Link to v1: https://lore.kernel.org/r/20250310-restricted-pointers-vchiq_arm-v1-1-dd04f208ee55 at linutronix.de
> ---

Thanks!

Reviewed-by: Dan Carpenter <dan.carpenter at linaro.org>

regards,
dan carpenter



From maz at kernel.org  Tue Mar 11 04:18:40 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 11:18:40 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>
	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
Message-ID: <86r033olwv.wl-maz@kernel.org>

On Tue, 11 Mar 2025 03:42:23 +0000,
Ankit Agrawal <ankita at nvidia.com> wrote:
> 
> >> +???? /*
> >> +????? *? When FWB is unsupported KVM needs to do cache flushes
> >> +????? *? (via dcache_clean_inval_poc()) of the underlying memory. This is
> >> +????? *? only possible if the memory is already mapped into the kernel map.
> >> +????? *
> >> +????? *? Outright reject as the cacheable device memory is not present in
> >> +????? *? the kernel map and not suitable for cache management.
> >> +????? */
> >> +???? if (cacheable_devmem && !stage2_has_fwb(pgt)) {
> >> +???????????? ret = -EINVAL;
> >> +???????????? goto out_unlock;
> >> +???? }
> >> +
> >
> > These new error reasons should at least be complemented by an
> > equivalent check at the point where the memslot is registered. It
> 
> Understood. I can add such check in kvm_arch_prepare_memory_region().
> 
> 
> > maybe OK to blindly return an error at fault time (because userspace
> > has messed with the mapping behind our back), but there should at
> > least be something telling a well behaved userspace that there is a
> > bunch of combination we're unwilling to support.
> 
> How about WARN_ON() or BUG() for the faulty situation?

Absolutely not. Do you really want any user to randomly crash the
kernel because they flip a mapping, which they can do anytime they
want?

The way KVM works is that we return to userspace for the VMM to fix
things. Either by emulating something we can't do in the kernel, or by
fixing things so that the kernel can replay the fault and sort it out.

Either way, this requires some form of fault syndrome so that usespace
has a chance of understanding WTF is going on.

> > Which brings me to the next point: FWB is not discoverable from
> > userspace. How do you expect a VMM to know what it can or cannot do?
> 
> Good point. I am not sure if it can. I suppose you are concerned about error
> during fault handling when !FWB without VMM having any clear indications
> of the cause?

No, I'm concerned that a well established API (populating a memslot)
works in some case and doesn't work in another without a clear
indication of *why* we have this behaviour.

To me, this indicates that userspace needs to buy in this new
behaviour, and that behaviour needs to be advertised by a capability,
which is in turn conditional on FWB.

> Perhaps we can gracefully fall back to the default device mapping
> in such case? But that would cause VM to crash as soon as it makes some
> access violating DEVICE_nGnRE.

Which would now be a regression...

My take is that this cacheable PNFMAP contraption must only be exposed
to a guest if FWB is available. We can't prevent someone to do an
mmap() behind our back, but we can at least:

- tell userspace whether this is supported
- only handle the fault if userspace has bought in this mode
- report the fault to userspace for it to fix things otherwise

	M.

-- 
Without deviation from the norm, progress is not possible.


From konrad.dybcio at oss.qualcomm.com  Tue Mar 11 04:19:01 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 11 Mar 2025 12:19:01 +0100
Subject: [PATCH v2 6/9] phy: qcom: Add M31 based eUSB2 PHY driver
In-Reply-To: <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>
Message-ID: <69fa7f33-e957-4dac-93dc-6fd40167873c@oss.qualcomm.com>

On 3/4/25 10:56 PM, Melody Olvera wrote:
> From: Wesley Cheng <quic_wcheng at quicinc.com>
> 
> SM8750 utilizes an eUSB2 PHY from M31.  Add the initialization
> sequences to bring it out of reset and into an operational state.  This
> differs to the M31 USB driver, in that the M31 eUSB2 driver will
> require a connection to an eUSB2 repeater.  This PHY driver will handle
> the initialization of the associated eUSB2 repeater when required.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
> ---

[...]

> +static int msm_m31_eusb2_write_readback(void __iomem *base, u32 offset,
> +					const u32 mask, u32 val)
> +{
> +	u32 write_val;
> +	u32 tmp;
> +
> +	tmp = readl_relaxed(base + offset);
> +	tmp &= ~mask;
> +	write_val = tmp | val;
> +
> +	writel_relaxed(write_val, base + offset);
> +
> +	tmp = readl_relaxed(base + offset);
> +	tmp &= mask;
> +
> +	if (tmp != val) {
> +		pr_err("write: %x to offset: %x FAILED\n", val, offset);
> +		return -EINVAL;
> +	}
> +
> +	return 0;

Is there a reason we need to read back every write?

Does this have to do with some funny write buffering?

Konrad


From sudeep.holla at arm.com  Tue Mar 11 04:23:12 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 11:23:12 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
References: <Z7Rf9GPdO2atP89Z@bogus>
 <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus>
 <Z87sGF_jHKau_FMe@bogus>
 <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
Message-ID: <Z9AdICiyaCmzKh-N@bogus>

On Tue, Mar 11, 2025 at 11:12:45AM +0000, Peng Fan wrote:
> Based on linux-next, I added below node:
>
> +
> +               test at 4f000000 {
> +                       compatible = "fsl,imx-test";
> +                       power-domains = <&scmi_devpd IMX95_PD_VPU>, <&scmi_perf IMX95_PERF_VPU>;
> +                       power-domain-names = "vpumix", "vpuperf";
> +               };
>
> I not write a driver for it, so just check devlink information from sysfs interface.
>
> From below sys directory, this test device takes scmi_dev.4 and scmi_dev.3 as supplier.
> root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# ls
> driver_override  of_node  subsystem                          supplier:scmi_protocol:scmi_dev.4  waiting_for_supplier
> modalias         power    supplier:scmi_protocol:scmi_dev.3  uevent
>
> Checking scmi_dev.4 below, it is scmi cpufreq, not the scmi perf device.
> scmi_dev.3 is correct, it is genpd.
>
> root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# cat /sys/bus/scmi_protocol/devices/scmi_dev.4/modalias
> scmi_dev.4:13:cpufreq
> root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000# cat /sys/bus/scmi_protocol/devices/scmi_dev.3/modalias
> scmi_dev.3:11:genpd
> root at imx95evk:/sys/bus/platform/devices/soc:test at 4f000000#
>
>
> So it is clear that wrong fw_devlink is created, it is because scmi cpufreq device is
> created earlier and when device_add, the below logic makes the fwnode pointer points
> to scmi cpufreq device.
>         if (dev->fwnode && !dev->fwnode->dev) {
>                 dev->fwnode->dev = dev;
>                 fw_devlink_link_device(dev);
>         }
>

Thanks, looks like simple way to reproduce the issue. I will give it a try.

--
Regards,
Sudeep


From john.madieu.xa at bp.renesas.com  Tue Mar 11 04:24:59 2025
From: john.madieu.xa at bp.renesas.com (John Madieu)
Date: Tue, 11 Mar 2025 11:24:59 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <20250310-blurry-scam-bee8233878bc@spud>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
 <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-barbell-pretzel-368d6a4d1336@spud>
 <OSBPR01MB2775D121B55A0C543F251BAEFFD72@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250310-blurry-scam-bee8233878bc@spud>
Message-ID: <OSBPR01MB2775B3826A9FE602AC08172BFFD12@OSBPR01MB2775.jpnprd01.prod.outlook.com>

Hi Conor,

> -----Original Message-----
> From: Conor Dooley <conor at kernel.org>
> Sent: Monday, March 10, 2025 5:15 PM
> To: John Madieu <john.madieu.xa at bp.renesas.com>
> Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> the TSU unit
> 
> On Sun, Mar 09, 2025 at 10:39:27AM +0000, John Madieu wrote:
> > Hi Conor,
> > > > Changes are not possible at runtime. Some customers may want
> > > > software, while other may want the external trigger, and this is
> > > > immutable configuration.
> > >
> > > What makes it immutable? Set by some wiring on the board? I couldn't
> > > find the user in your driver patches to better understand how you
> > > were using it.
> >
> > I haven't prototyped ELC trigger yet. Since the hardware manual
> > describes about ELC trigger, I have documented it in bindings. If you
> > think, it is not needed at this stage, then I can drop it now and
> > revisit later.
> 
> Ideally a binding is complete, even if the driver isn't. To me "immutable"
> would mean something like "the trigger type is determined by hardware or
> firmware configuration", but if it is determined by register writes (e.g.
> wired up for elc trigger, but you can opt for software trigger in the
> driver) then it should be a userspace control.

It is complete, and I confirm, this can be changed by register writes.
Apart from defining default to 0, should I implement userspace change
support now ?

Or should I keep it as it is, just setting default to 0 (thus making
the property optional), and add support for userspace change when I add
ELC support.

My other question is, in case I must add userspace change support now, would
sysfs be Ok ? If yes, is there any path recommendations ?


Regards,
John


From vkoul at kernel.org  Tue Mar 11 04:22:22 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 12:22:22 +0100
Subject: [PATCH 1/2] dt-bindings: phy: rockchip,inno-usb2phy: add rk3562
In-Reply-To: <20241224094240.3817261-1-kever.yang@rock-chips.com>
References: <20241224094240.3817261-1-kever.yang@rock-chips.com>
Message-ID: <Z9Ac7hhQj9J7sFwJ@vaman>

On 24-12-24, 17:42, Kever Yang wrote:
> Add compatible for the USB2 phy in the Rockchip RK3562 SoC.
> 
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
> 
>  .../devicetree/bindings/phy/rockchip,inno-usb2phy.yaml         | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
> index 6a7ef556414c..367297f6f8b5 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
> @@ -19,6 +19,7 @@ properties:
>        - rockchip,rk3328-usb2phy
>        - rockchip,rk3366-usb2phy
>        - rockchip,rk3399-usb2phy
> +      - rockchip,rk3562-usb2phy
>        - rockchip,rk3568-usb2phy
>        - rockchip,rk3576-usb2phy
>        - rockchip,rk3588-usb2phy
> @@ -150,7 +151,6 @@ allOf:
>              enum:
>                - rockchip,rk3568-usb2phy
>                - rockchip,rk3588-usb2phy
> -

Unrelated change?

>      then:
>        properties:
>          host-port:
> @@ -190,6 +190,7 @@ allOf:
>                - rockchip,rk3328-usb2phy
>                - rockchip,rk3366-usb2phy
>                - rockchip,rk3399-usb2phy
> +              - rockchip,rk3562-usb2phy
>                - rockchip,rk3568-usb2phy
>                - rockchip,rk3588-usb2phy
>                - rockchip,rv1108-usb2phy
> -- 
> 2.25.1
> 
> 
> -- 
> linux-phy mailing list
> linux-phy at lists.infradead.org
> https://lists.infradead.org/mailman/listinfo/linux-phy

-- 
~Vinod


From balejk at matfyz.cz  Tue Mar 11 04:25:56 2025
From: balejk at matfyz.cz (Karel Balej)
Date: Tue, 11 Mar 2025 12:25:56 +0100
Subject: [RFC PATCH] mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
In-Reply-To: <727c857f-0234-417b-af5d-69b3ae064d0f@intel.com>
References: <20250310140707.23459-1-balejk@matfyz.cz>
 <727c857f-0234-417b-af5d-69b3ae064d0f@intel.com>
Message-ID: <D8DEEUPB16WF.154Y3AEPXT4L1@matfyz.cz>

Adrian Hunter, 2025-03-11T09:34:28+02:00:
> On 10/03/25 16:07, Karel Balej wrote:
>> Set the MMC_CAP_NEED_RSP_BUSY capability for the sdhci-pxav3 host to
>> prevent conversion of R1B responses to R1. Without this, the eMMC card
>> in the samsung,coreprimevelte smartphone using the Marvell PXA1908 SoC
>
> So that SoC is from 2015?

Rather at least 2014 as that's the release year of the phone.

> Is there anything more recent using this driver?

Looking at the in-tree DTs using the compatibles offered by it, it seems
that not really.

K. B.


From peterz at infradead.org  Tue Mar 11 04:31:28 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 11 Mar 2025 12:31:28 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250307202247.648633-4-mark.barnett@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
Message-ID: <20250311113128.GD19424@noisy.programming.kicks-ass.net>

On Fri, Mar 07, 2025 at 08:22:45PM +0000, mark.barnett at arm.com wrote:
> From: Ben Gainey <ben.gainey at arm.com>
> 
> This change modifies the core perf overflow handler, adding some small
> random jitter to each sample period whenever an event switches between the
> two alternate sample periods. A new flag is added to perf_event_attr to
> opt into this behaviour.
> 
> This change follows the discussion in [1], where it is recognized that it
> may be possible for certain patterns of execution to end up with biased
> results.
> 
> [1] https://lore.kernel.org/linux-perf-users/Zc24eLqZycmIg3d2 at tassilo/
> 
> Signed-off-by: Ben Gainey <ben.gainey at arm.com>
> Signed-off-by: Mark Barnett <mark.barnett at arm.com>
> ---
>  include/uapi/linux/perf_event.h | 7 ++++++-
>  kernel/events/core.c            | 9 ++++++++-
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 499a8673df8e..c0076ce8f80a 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -461,7 +461,12 @@ struct perf_event_attr {
>  				inherit_thread :  1, /* children only inherit if cloned with CLONE_THREAD */
>  				remove_on_exec :  1, /* event is removed from task on exec */
>  				sigtrap        :  1, /* send synchronous SIGTRAP on event */
> -				__reserved_1   : 26;
> +				/*
> +				 * Add a limited amount of jitter on each alternate period, where
> +				 * the jitter is between [0, (2<<jitter_alt_period) - 1]
> +				 */
> +				jitter_alt_period : 3,
> +				__reserved_1   : 23;

So; I've been thinking about this interface.

I think I prefer you keep the existing sample_period/sample_freq working
as is and simply modulate with random and high-freq components.

A very little like so..

I've made the hf_sample_period 32bit since I figured that ought to be
enough -- you're aiming at very short periods after all. But there's
enough unused bits left.

So this has sample_period or sample_freq compute hwc->sample_period_base
which is first modified with random such that the average is exactly
sample_period_base (assuming a flat distribution).

This means that sample_period_base is still the right number to use for
computing freq based things. Additionally, have the 'extra' interrupt
ignored for adaptive period crud.

Also, someone needs to consider the eBPF hook and what to do with it.
I've kept the ordering as per this series, but I suspect it's wrong and
we want this before the BPF hook. Please think about this and explicitly
mention this in the next series.

Anyway, very much a sketch of things, incomplete and not been near a
compiler.



---
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 76f4265efee9..c5dd6442e96f 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -229,6 +229,10 @@ struct hw_perf_event {
 #define PERF_HES_UPTODATE	0x02 /* event->count up-to-date */
 #define PERF_HES_ARCH		0x04
 
+#define PERF_HES_HF_ON		0x10 /* using high-fred sampling */
+#define PERF_HES_HF_SAMPLE	0x20
+#define PERF_HES_HF_RAND	0x40
+
 	int				state;
 
 	/*
@@ -241,6 +245,7 @@ struct hw_perf_event {
 	 * The period to start the next sample with.
 	 */
 	u64				sample_period;
+	u64				sample_period_base;
 
 	union {
 		struct { /* Sampling */
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 0524d541d4e3..8dbe027f93f1 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -379,6 +379,7 @@ enum perf_event_read_format {
 #define PERF_ATTR_SIZE_VER6	120	/* add: aux_sample_size */
 #define PERF_ATTR_SIZE_VER7	128	/* add: sig_data */
 #define PERF_ATTR_SIZE_VER8	136	/* add: config3 */
+#define PERF_ATTR_SIZE_VER9	144	/* add: hf_sample */
 
 /*
  * Hardware event_id to monitor via a performance monitoring event:
@@ -531,6 +532,14 @@ struct perf_event_attr {
 	__u64	sig_data;
 
 	__u64	config3; /* extension of config2 */
+	union {
+		__u64 hf_sample;
+		struct {
+			__u64 hf_sample_period : 32,
+			      hf_sample_rand   :  4,
+			      __reserved_4     : 28;
+		};
+	};
 };
 
 /*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index b87a5ac42ce2..e5a93edf3b5f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8,6 +8,7 @@
  *  Copyright  ?  2009 Paul Mackerras, IBM Corp. <paulus at au1.ibm.com>
  */
 
+#include "linux/random.h"
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
@@ -55,6 +56,7 @@
 #include <linux/pgtable.h>
 #include <linux/buildid.h>
 #include <linux/task_work.h>
+#include <linux/prandom.h>
 
 #include "internal.h"
 
@@ -443,6 +445,8 @@ static cpumask_var_t perf_online_pkg_mask;
 static cpumask_var_t perf_online_sys_mask;
 static struct kmem_cache *perf_event_cache;
 
+static struct rnd_state perf_rand;
+
 /*
  * perf event paranoia level:
  *  -1 - not paranoid at all
@@ -4233,19 +4237,19 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bo
 
 	period = perf_calculate_period(event, nsec, count);
 
-	delta = (s64)(period - hwc->sample_period);
+	delta = (s64)(period - hwc->sample_period_base);
 	if (delta >= 0)
 		delta += 7;
 	else
 		delta -= 7;
 	delta /= 8; /* low pass filter */
 
-	sample_period = hwc->sample_period + delta;
+	sample_period = hwc->sample_period_base + delta;
 
 	if (!sample_period)
 		sample_period = 1;
 
-	hwc->sample_period = sample_period;
+	hwc->sample_period_base = sample_period;
 
 	if (local64_read(&hwc->period_left) > 8*sample_period) {
 		if (disable)
@@ -4490,6 +4494,8 @@ void perf_event_task_tick(void)
 	if (ctx)
 		perf_adjust_freq_unthr_context(ctx, !!throttled);
 	rcu_read_unlock();
+
+	prandom_seed_state(&perf_rand, get_random_u64());
 }
 
 static int event_enable_on_exec(struct perf_event *event,
@@ -9979,6 +9985,8 @@ static int __perf_event_overflow(struct perf_event *event,
 				 int throttle, struct perf_sample_data *data,
 				 struct pt_regs *regs)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	u64 sample_period;
 	int events = atomic_read(&event->event_limit);
 	int ret = 0;
 
@@ -9989,15 +9997,50 @@ static int __perf_event_overflow(struct perf_event *event,
 	if (unlikely(!is_sampling_event(event)))
 		return 0;
 
-	ret = __perf_event_account_interrupt(event, throttle);
+	/*
+	 * High Freq samples are injected inside the larger period:
+	 *
+	 *   |------------|-|------------|-|
+	 *   P0          HF P1          HF
+	 *
+	 * By ignoring the HF samples, we measure the actual period.
+	 */
+	if (!(hwc->state & PERF_HES_HF_SAMPLE))
+		ret = __perf_event_account_interrupt(event, throttle);
 
 	if (event->attr.aux_pause)
 		perf_event_aux_pause(event->aux_event, true);
 
+	/* XXX interaction between HF samples and BPF */
 	if (event->prog && event->prog->type == BPF_PROG_TYPE_PERF_EVENT &&
 	    !bpf_overflow_handler(event, data, regs))
 		goto out;
 
+	sample_period = hwc->sample_period_base;
+	if (hwc->state & PERF_HES_HF_RAND) {
+		u64 rand = 1 << event->attr.hf_sample_rand;
+		sample_period -= rand / 2;
+		sample_period += prandom_u32_state(&perf_rand) & (rand - 1);
+	}
+	if (hwc->state & PERF_HES_HF_ON) {
+		u64 hf_sample_period = event->attr.hf_sample_period;
+
+		if (sample_period < hf_sample_period) {
+			hwc->state &= ~PERF_HES_HF_ON;
+			goto set_period;
+		}
+
+		if (!(hwc->state & PERF_HES_HF_SAMPLE)) {
+			hwc->sample_period -= hf_sample_period;
+			hwc->state |= PERF_HES_HF_SAMPLE;
+		} else {
+			hwc->sample_period = hf_sample_period;
+			hwc->state &= ~PERF_HES_HF_SAMPLE;
+		}
+	}
+set_period:
+	hwc->sample_period = sample_period;
+
 	/*
 	 * XXX event_limit might not quite work as expected on inherited
 	 * events
@@ -12458,8 +12501,11 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
 	hwc = &event->hw;
 	hwc->sample_period = attr->sample_period;
-	if (attr->freq && attr->sample_freq)
+	hwc->sample_period_base = attr->sample_period;
+	if (attr->freq && attr->sample_freq) {
 		hwc->sample_period = 1;
+		hwc->sample_period_base = 1;
+	}
 	hwc->last_period = hwc->sample_period;
 
 	local64_set(&hwc->period_left, hwc->sample_period);
@@ -13824,6 +13870,7 @@ inherit_event(struct perf_event *parent_event,
 		struct hw_perf_event *hwc = &child_event->hw;
 
 		hwc->sample_period = sample_period;
+		hwc->sample_period_base = sample_period;
 		hwc->last_period   = sample_period;
 
 		local64_set(&hwc->period_left, sample_period);
@@ -14279,6 +14326,8 @@ void __init perf_event_init(void)
 {
 	int ret;
 
+	prandom_seed_state(&perf_rand, get_random_u64());
+
 	idr_init(&pmu_idr);
 
 	perf_event_init_all_cpus();



From ryan.roberts at arm.com  Tue Mar 11 04:31:40 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue, 11 Mar 2025 11:31:40 +0000
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early
 mappings
In-Reply-To: <20250311073043.96795-2-ardb+git@google.com>
References: <20250311073043.96795-2-ardb+git@google.com>
Message-ID: <f6d48d04-fd3c-493e-b7a0-020b912f6f10@arm.com>

On 11/03/2025 07:30, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb at kernel.org>
> 
> The page table population code in map_range() uses a recursive algorithm
> to create the early mappings of the kernel, the DTB and the ID mapped
> text and data pages, and this fails to take into account that the way
> these page tables may be constructed is not precisely the same at each
> level. In particular, block mappings are not permitted at each level,
> and the code as it exists today might inadvertently create such a
> forbidden block mapping if it were used to map a region of the
> appropriate size and alignment.
> 
> This never happens in practice, given the limited size of the assets
> being mapped by the early boot code. Nonetheless, it would be better if
> this code would behave correctly in all circumstances.
> 
> So only permit block mappings at level 2, and page mappings at level 3,
> for any page size, and use table mappings exclusively at all other
> levels. This change should have no impact in practice, but it makes the
> code more robust.
> 
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> ---
> v2: take the assignment of protval out of the loop again, so that
>     clearing a mapping works as expected wrt the PTE_CONT bit

Ouch, totally missed that. Now that I've looked at the code properly, I wonder
if it is worth supporting CONT_PMD mappings at level 2? That would be 32M for 4K
pages, so is likely to actaually get used. I think it would just be something like:

u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 :
	   ((level == 2) ? CONT_PMD_SIZE - 1 : U64_MAX) : U64_MAX;

Anyway, probably not worth the complexity for these boot-time tables, so regardless:

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

> 
>  arch/arm64/kernel/pi/map_range.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
> index 2b69e3beeef8..5778697f3062 100644
> --- a/arch/arm64/kernel/pi/map_range.c
> +++ b/arch/arm64/kernel/pi/map_range.c
> @@ -45,12 +45,12 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
>  	 * clearing the mapping
>  	 */
>  	if (protval)
> -		protval |= (level < 3) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
> +		protval |= (level == 2) ? PMD_TYPE_SECT : PTE_TYPE_PAGE;
>  
>  	while (start < end) {
>  		u64 next = min((start | lmask) + 1, PAGE_ALIGN(end));
>  
> -		if (level < 3 && (start | next | pa) & lmask) {
> +		if (level < 2 || (level == 2 && (start | next | pa) & lmask)) {
>  			/*
>  			 * This chunk needs a finer grained mapping. Create a
>  			 * table mapping if necessary and recurse.



From peterz at infradead.org  Tue Mar 11 04:35:30 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 11 Mar 2025 12:35:30 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250311113128.GD19424@noisy.programming.kicks-ass.net>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250311113128.GD19424@noisy.programming.kicks-ass.net>
Message-ID: <20250311113530.GA9968@noisy.programming.kicks-ass.net>

On Tue, Mar 11, 2025 at 12:31:29PM +0100, Peter Zijlstra wrote:
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index b87a5ac42ce2..e5a93edf3b5f 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -8,6 +8,7 @@
>   *  Copyright  ?  2009 Paul Mackerras, IBM Corp. <paulus at au1.ibm.com>
>   */
>  
> +#include "linux/random.h"
>  #include <linux/fs.h>
>  #include <linux/mm.h>
>  #include <linux/cpu.h>

Argh, this is neovim trying to be 'helpful'. If anybody reading this
knows how to make it stop adding headers, please let me know, its
driving me nuts.


From andrea.porta at suse.com  Tue Mar 11 04:36:59 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Tue, 11 Mar 2025 12:36:59 +0100
Subject: [PATCH v7 03/11] dt-bindings: pci: Add common schema for devices
 accessible through PCI BARs
In-Reply-To: <20250310212125.GB2377483@rocinante>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <c0acc51a7210fb30cae7b26f4ad1f0449beed95e.1738963156.git.andrea.porta@suse.com>
 <20250310212125.GB2377483@rocinante>
Message-ID: <Z9AgW1TEiJ3G9dvh@apocalypse>

Hi Krzysztof,

On 06:21 Tue 11 Mar     , Krzysztof Wilczynski wrote:
> Hello,
> 
> [...]
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d45c88955072..af2e4652bf3b 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -19752,6 +19752,7 @@ RASPBERRY PI RP1 PCI DRIVER
> >  M:	Andrea della Porta <andrea.porta at suse.com>
> >  S:	Maintained
> >  F:	Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
> > +F:	Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
> >  F:	Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
> >  F:	include/dt-bindings/clock/rp1.h
> >  F:	include/dt-bindings/misc/rp1.h
> 
> I would be happy to pick this via the PCI tree as per the standard
> operating procedure.  However, the MAINTAINERS changes do not exist
> for us yet, and are added in the first patch of the series, which is
> not ideal.
> 
> I can add the missing dependency manually, but that would cause issues
> for linux-next tree, which is also not ideal.
> 
> I saw some review feedback, as such, when you are going to be sending
> another version, can you make MAINTAINERS changes to be the last patch,
> perhaps.  Basically, something standalone that perhaps whoever will pick
> the misc patch could also pick and apply at the same time.

Sure, I will split the changes for MAINTAINERS file to its own separate
patch in the next revision.

Many thanks,
Andrea

> 
> Alternatively, someone else picking up the PCI dt-bindings would work, too.
> 
> Your thoughts?
> 
> Thank you!
> 
> 	Krzysztof


From vkoul at kernel.org  Tue Mar 11 04:40:39 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 12:40:39 +0100
Subject: [PATCH 10/13] phy: airoha: Add support for Airoha AN7581 USB PHY
In-Reply-To: <20250309132959.19045-11-ansuelsmth@gmail.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-11-ansuelsmth@gmail.com>
Message-ID: <Z9AhN9T8s1oogCUn@vaman>

On 09-03-25, 14:29, Christian Marangi wrote:
> Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
> USB port with USB 2.0 mode always supported and USB 3.0 mode available
> only if the Serdes port is correctly configured for USB 3.0.
> 
> On xLate probe, the Serdes mode is validated and the driver return error
> if the Serdes mode doesn't reflect the expected mode. This is required
> as Serdes mode are controlled by the SCU SSR bits and can be either USB
> 3.0 mode or HSGMII or PCIe 2. In such case USB 3.0 won't work.
> 
> If the USB 3.0 mode is not supported, the modes needs to be also
> disabled in the xHCI node or the driver will report unsable clock and
> fail probe.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  MAINTAINERS                         |   1 +
>  drivers/phy/Kconfig                 |   1 +
>  drivers/phy/Makefile                |   3 +-
>  drivers/phy/airoha/Kconfig          |  13 +
>  drivers/phy/airoha/Makefile         |   3 +
>  drivers/phy/airoha/phy-airoha-usb.c | 554 ++++++++++++++++++++++++++++
>  6 files changed, 574 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/phy/airoha/Kconfig
>  create mode 100644 drivers/phy/airoha/Makefile
>  create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c2dd385e9165..1835e488ccaa 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -758,6 +758,7 @@ M:	Christian Marangi <ansuelsmth at gmail.com>
>  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam
> +F:	drivers/phy/airoha/phy-airoha-usb.c
>  
>  AIRSPY MEDIA DRIVER
>  L:	linux-media at vger.kernel.org
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 8d58efe998ec..19c9c518fc3d 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -93,6 +93,7 @@ config PHY_NXP_PTN3222
>  	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
>  	  Speed and High Speed.
>  
> +source "drivers/phy/airoha/Kconfig"
>  source "drivers/phy/allwinner/Kconfig"
>  source "drivers/phy/amlogic/Kconfig"
>  source "drivers/phy/broadcom/Kconfig"
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index e281442acc75..71708c6865b8 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -12,7 +12,8 @@ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
>  obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
>  obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
>  obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
> -obj-y					+= allwinner/	\
> +obj-y					+= airoha/	\

Directory for a single driver? Also move the PCIe driver in, if you
really want to do this

> +struct airoha_usb_phy_priv {
> +	struct device *dev;
> +
> +	struct regmap *regmap;
> +
> +	unsigned int id;
> +
> +	struct airoha_usb_phy_instance *phys[AIROHA_USB_PHY_MAX_INSTANCE];

No need for empty lines here?

> +static int airoha_usb_phy_u2_slew_rate_calibration(struct airoha_usb_phy_priv *priv)
> +{
> +	u32 fm_out;
> +	u32 srctrl;
> +
> +	/* Enable HS TX SR calibration */
> +	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
> +			AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
> +
> +	usleep_range(1000, 1500);
> +
> +	/* Enable Free run clock */
> +	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
> +			AIROHA_USB_PHY_FRCK_EN);
> +
> +	/* Select Monitor Clock */
> +	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
> +			   AIROHA_USB_PHY_MONCLK_SEL,
> +			   priv->id == 0 ? AIROHA_USB_PHY_MONCLK_SEL0 :
> +					   AIROHA_USB_PHY_MONCLK_SEL1);
> +
> +	/* Set cyclecnt */
> +	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
> +			   AIROHA_USB_PHY_CYCLECNT,
> +			   FIELD_PREP(AIROHA_USB_PHY_CYCLECNT,
> +				      AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT));
> +
> +	/* Enable Frequency meter */
> +	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
> +			AIROHA_USB_PHY_FREQDET_EN);
> +
> +	/* Timeout can happen and we will apply workaround at the end */
> +	regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out,
> +				 fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
> +				 AIROHA_USB_PHY_FREQDET_TIMEOUT);
> +
> +	/* Disable Frequency meter */
> +	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
> +			  AIROHA_USB_PHY_FREQDET_EN);
> +
> +	/* Disable Free run clock */
> +	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
> +			  AIROHA_USB_PHY_FRCK_EN);
> +
> +	/* Disable HS TX SR calibration */
> +	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
> +			  AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
> +
> +	usleep_range(1000, 1500);
> +
> +	/* Frequency was not detected, use default SR calibration value */
> +	if (!fm_out) {
> +		srctrl = 0x5;

magic?

> +		dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n");
> +	/* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
> +	} else {
> +		srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF;
> +		srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out;
> +		srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR);
> +		dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl);
> +	}
> +
> +	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
> +			   AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
> +			   FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
> +
> +	return 0;

This is the only return... consider making it void return then?
Here and other places

> +static int airoha_usb_phy_exit(struct phy *phy)
> +{
> +	return 0;
> +}

you can drop this

> +static int airoha_usb_phy_power_on(struct phy *phy)
> +{
> +	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
> +	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
> +
> +	if (instance->type == PHY_TYPE_USB2)
> +		return airoha_usb_phy_u2_power_on(priv);
> +
> +	return airoha_usb_phy_u3_power_on(priv);

for non USB2, you power both why?

> +static int airoha_usb_phy_u2_set_mode(struct airoha_usb_phy_priv *priv,
> +				      enum phy_mode mode)
> +{
> +	u32 val = 0;
> +
> +	/*
> +	 * For Device and Host mode, enable force IDDIG.
> +	 * For Device set IDDIG, for Host clear IDDIG.
> +	 * For OTG disable force and clear IDDIG bit while at it.
> +	 */
> +	switch (mode) {
> +	case PHY_MODE_USB_DEVICE:
> +		val |= AIROHA_USB_PHY_IDDIG;
> +		fallthrough;
> +	case PHY_MODE_USB_HOST:
> +		val |= AIROHA_USB_PHY_FORCE_IDDIG;
> +		break;
> +	case PHY_MODE_USB_OTG:
> +		break;

Not expecting to set this?
-- 
~Vinod


From peterz at infradead.org  Tue Mar 11 04:37:27 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 11 Mar 2025 12:37:27 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250311113128.GD19424@noisy.programming.kicks-ass.net>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250311113128.GD19424@noisy.programming.kicks-ass.net>
Message-ID: <20250311113727.GB9968@noisy.programming.kicks-ass.net>

On Tue, Mar 11, 2025 at 12:31:29PM +0100, Peter Zijlstra wrote:
> +	sample_period = hwc->sample_period_base;
> +	if (hwc->state & PERF_HES_HF_RAND) {
> +		u64 rand = 1 << event->attr.hf_sample_rand;
> +		sample_period -= rand / 2;
> +		sample_period += prandom_u32_state(&perf_rand) & (rand - 1);
> +	}
> +	if (hwc->state & PERF_HES_HF_ON) {
> +		u64 hf_sample_period = event->attr.hf_sample_period;
> +
> +		if (sample_period < hf_sample_period) {
> +			hwc->state &= ~PERF_HES_HF_ON;
> +			goto set_period;
> +		}
> +
> +		if (!(hwc->state & PERF_HES_HF_SAMPLE)) {
> +			hwc->sample_period -= hf_sample_period;
> +			hwc->state |= PERF_HES_HF_SAMPLE;
> +		} else {
> +			hwc->sample_period = hf_sample_period;
> +			hwc->state &= ~PERF_HES_HF_SAMPLE;

and obviously this should be the local sample_period modified above, not
the hwc one.

> +		}
> +	}
> +set_period:
> +	hwc->sample_period = sample_period;


From m.felsch at pengutronix.de  Tue Mar 11 04:37:42 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 11 Mar 2025 12:37:42 +0100
Subject: [PATCH v2 0/5] imx8mp: add support for the IMX AIPSTZ bridge
In-Reply-To: <4aef911d-d766-4ae7-951b-76843cf33c56@gmail.com>
References: <20250226165314.34205-1-laurentiumihalcea111@gmail.com>
 <20250226212219.lthoofw7nrs3gtg6@pengutronix.de>
 <20250227112856.aylsurbt3uqm4ivw@pengutronix.de>
 <541539db-0015-41de-837f-aabbea68486a@gmail.com>
 <20250307143956.aft3xolakts3nlja@pengutronix.de>
 <4aef911d-d766-4ae7-951b-76843cf33c56@gmail.com>
Message-ID: <20250311113742.uwedagolaxjy6unb@pengutronix.de>

On 25-03-10, Laurentiu Mihalcea wrote:
> 
> 
> On 3/7/2025 4:39 PM, Marco Felsch wrote:
> > On 25-03-05, Laurentiu Mihalcea wrote:
> >> On 2/27/2025 1:28 PM, Marco Felsch wrote:
> >>> Hi Laurentiu,
> >>>
> >>> On 25-02-26, Marco Felsch wrote:
> >>>> Hi,
> >>>>
> >>>> On 25-02-26, Laurentiu Mihalcea wrote:
> >>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> >>>>>
> >>>>> The AIPSTZ bridge offers some security-related configurations which can
> >>>>> be used to restrict master access to certain peripherals on the bridge.
> >>>>>
> >>>>> Normally, this could be done from a secure environment such as ATF before
> >>>>> Linux boots but the configuration of AIPSTZ5 is lost each time the power
> >>>>> domain is powered off and then powered on. Because of this, it has to be
> >>>>> configured each time the power domain is turned on and before any master
> >>>>> tries to access the peripherals (e.g: AP, CM7, DSP, on i.MX8MP).
> >>>> My question still stands:
> >>>>
> >>>> Setting these bits requires very often that the core is running at EL3
> >>>> (e.g. secure-monitor) which is not the case for Linux. Can you please
> >>>> provide more information how Linux can set these bits?
> >>> Sorry I didn't noticed your response:
> >>>
> >>> https://lore.kernel.org/all/a62ab860-5e0e-4ebc-af1f-6fb7ac621e2b at gmail.com/
> >>>
> >>> If EL1 is allowed to set the security access configuration of the IP
> >>> cores doesn't this mean that a backdoor can be opened? E.g. your
> >>> secure-boot system configures one I2C IP core to be accessible only from
> >>> secure-world S-EL1 (OP-TEE) and after the power-domain was power-cycled
> >>> it's accessible from EL1 again. This doesn't seem right. Why should a
> >>> user be able to limit the access permissions to an IP core to only be
> >>> accessible from secure-world if the IP core is accessible from
> >>> normal-world after the power-domain was power-cycled.
> >>>
> >>> Regards,
> >>>   Marco
> >> I'm no security expert so please feel free to correct me if I get
> >> something wrong.
> >>
> >> This isn't about S/NS world. The bridge AC doesn't offer any
> >> configurations for denying access to peripherals based on S/NS world.
> > It does, please see the AIPSTZ_OPACR register definition. The imx-atf of
> > sets OPACR registers to 0 (of course), which means that the S/NS is not
> > checked _but_ it can be configured.
> 
> which bits are you referring to more precisely? because, from the OPACR
> register definition we have:
> 
> 1) TP (Trusted protect) - bit 0 => controls whether the peripheral allows
> transactions from an untrusted master. A master is considered trusted if
> MTR/MTW (from MPR registers) is set to 1 (MTR means trusted for read,
> MTW means trusted for write)
> 
> 2) WP (Write protect) - bit 1 => controls whether the peripherals allows
> write transactions (i.e: is write protected or not)
> 
> 3) SP (Supervisor protect) - bit 2 => controls whether the master needs
> supervisor privilege or not to issue transactions to the peripheral. For
> Cortex-A53 this refers to the execution level (EL0 - EL3). There's no S/NS
> checks here. EL1-EL3 are supervisor accesses, EL0 is not.

Argh.. my head mixed the supervisor phrase :/

> 4) BW (Buffer Writes) - bit 3 => some flow control configuration bit I'd assume
> 
> 
> >
> > Also please see chapter 4.7.6.1 Security Block:
> >
> > The AIPSTZ contains a security block that is connected to each
> > off-platform peripheral. This block filters accesses based on
> > write/read, non-secure, and supervisor signals.
> 
> yep, but this block is not configured by the AIPSTZ. AFAIK it's configured
> by the CSU. So, as far as I understand it, the interaction is as follows:
> 
> basically you have the CSU which offers some security-related configurations
> (see "Table 4-16 Security Levels" from the section you've mentioned). These
> configurations are used by the AIPS bridges to filter transactions.
> 
> For example: assume you have peripheral X on AIPS5. The user configures
> the CSU such that peripheral X should only accept R/W transactions from
> privileged S world. Now, assume Cortex-A53 issues a transaction from
> NS EL1 (Linux, for example). The bridge will receive the transaction and
> check to see if it's privileged and S world. Since it's not then the transaction
> will be aborted.
> 
> The AIPS bridge offers no S/NS world-related configuration options. All you can
> do with it is:
> 
> 1) Mark certain masters as "trusted" and block read/writes based on that (via MPR's
> MTR/MTW and OPACR's TP)
> 2) Force transactions to user privilege (via MPR's MPL)
> 3) Make certain peripherals deny unprivileged transactions (via OPACR's SP)

Okay, thanks for the explanation with your input and the the TRM 4.7.6.1
saying:

8<--------------------------------------------------------------
A 3-bit input, 8-bit output translation block can be used such that only
three register bits are required to set the security profile and the
translation block will drive the correct 8-bit configuration vector.
Each peripheral connected to the AIPSTZ would require this translation
block. The top level AIPSTZ has this three bit input line
`csu_sec_level[2:0]' corresponding to each peripheral X.
8<--------------------------------------------------------------

I think that I understood the AIPSTZ user/supervisor now. The master
user/supervisor privileges are provided by the CSU HPx settings and can
be forced to user-mode via the AIPSTZ MPRTOx MPL0 bit.

The remaining bits from the config vector between the CSU and the AIPSTZ
are not taken into account.

Thanks for the clarification!

Regards,
  Marco


From vkoul at kernel.org  Tue Mar 11 04:42:08 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Tue, 11 Mar 2025 12:42:08 +0100
Subject: [PATCH 10/13] phy: airoha: Add support for Airoha AN7581 USB PHY
In-Reply-To: <Z9AhN9T8s1oogCUn@vaman>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-11-ansuelsmth@gmail.com>
 <Z9AhN9T8s1oogCUn@vaman>
Message-ID: <Z9AhkByegWQgC9YE@vaman>

On 11-03-25, 12:40, Vinod Koul wrote:
> On 09-03-25, 14:29, Christian Marangi wrote:
> > Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
> > USB port with USB 2.0 mode always supported and USB 3.0 mode available
> > only if the Serdes port is correctly configured for USB 3.0.
> > 
> > On xLate probe, the Serdes mode is validated and the driver return error
> > if the Serdes mode doesn't reflect the expected mode. This is required
> > as Serdes mode are controlled by the SCU SSR bits and can be either USB
> > 3.0 mode or HSGMII or PCIe 2. In such case USB 3.0 won't work.
> > 
> > If the USB 3.0 mode is not supported, the modes needs to be also
> > disabled in the xHCI node or the driver will report unsable clock and
> > fail probe.

Also I dont see phy depends on rest. Please split this and post phy bits
separately at least..

-- 
~Vinod


From will at kernel.org  Tue Mar 11 04:45:20 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 11:45:20 +0000
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <Z8nkNNR6vuoQ9bQD@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
 <CGME20250303113525eucas1p1099e087e2c11b9021603a6f13f8135c4@eucas1p1.samsung.com>
 <2b6d5287-bdea-4ec3-a07f-986bd3c3b285@arm.com>
 <7b5c90cf-00e4-4684-8719-f380badab064@samsung.com>
 <7ad365f0-d335-4da1-845a-8fe3bc5eb055@arm.com>
 <Z8nkNNR6vuoQ9bQD@arm.com>
Message-ID: <20250311114519.GA4202@willie-the-truck>

On Thu, Mar 06, 2025 at 06:06:44PM +0000, Catalin Marinas wrote:
> On Thu, Mar 06, 2025 at 11:39:14AM +0000, Suzuki K Poulose wrote:
> > On 04/03/2025 13:40, Marek Szyprowski wrote:
> > > > On 27/02/2025 14:41, Suzuki K Poulose wrote:
> > > > > Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> > > > > space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> > > > > half and shared top half. In Linux we treat the "top" bit of the IPA space as
> > > > > an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> > > > > Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> > > > > and are managed by RMM. The "top" bit as attribute is only a software construct.
> [...]
> > > The changes look fine. However I won't be able to setup new dma-mapping
> > > git tree this week because I got really sick has to stay in bed. :/ If
> > > You don't want such delay, please merge it via ARM64 tree. Here is my:
> > 
> > Sorry to hear that. Hope you feel better soon.
> > 
> > > Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>
> > 
> > Thanks Marek.
> > 
> > Btw, this series fixes the "Realm Guest" support for Linux, which was merged
> > in v6.13. To be precise, this should have :
> > 
> > Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")
> > 
> > Will/Catalin,
> > 
> > Please let me know if you would like me to send the series with
> > all the Acks, Reviews and mainly the Fixes tag added ?
> 
> We can add the acks and fixes tag, no worries. I can queue them for 6.15
> unless Will takes them as fixes for 6.14 (I'll wait for a bit).

For the series:

Acked-by: Will Deacon <will at kernel.org>

but I'd prefer this to land in 6.15 at this stage given that (a) it's
always been broken and (b) we're not exactly tripping over CCA-capable
hardware.

Cheers,

Will


From catalin.marinas at arm.com  Tue Mar 11 04:45:21 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 11:45:21 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88_fFgr23_EtHMf@J2N7QTR9R3>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
 <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>
 <Z88yC7Oaj9DGaswc@arm.com>
 <Z88_fFgr23_EtHMf@J2N7QTR9R3>
Message-ID: <Z9AiUQdC4o0g8sxu@arm.com>

On Mon, Mar 10, 2025 at 07:37:32PM +0000, Mark Rutland wrote:
> On Mon, Mar 10, 2025 at 06:40:11PM +0000, Catalin Marinas wrote:
> > On Mon, Mar 10, 2025 at 06:13:58PM +0000, Mark Rutland wrote:
> > > On Mon, Mar 10, 2025 at 05:37:50PM +0000, Catalin Marinas wrote:
> > > > On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > > > > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > > > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > > > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > > > > this is incompatible with MTE which will fault on a partially invalid
> > > > > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > > > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > > > > bug for now by disabling the optimizations if the kernel is built
> > > > > > with HW tag-based KASAN and consider improvements for followup changes.
> > > > > 
> > > > > Why is faulting on a partially invalid read a problem? It's still
> > > > > invalid, so ... it should fault, yes? What am I missing?
> > > > 
> > > > read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> > > > beyond the end of string. The has_zero() function is then used to check
> > > > where the string ends. For this uses, I think we can go with
> > > > load_unaligned_zeropad() which handles a potential fault and pads the
> > > > rest with zeroes.
> > > 
> > > If we only care about synchronous and asymmetric modes, that should be
> > > possible, but that won't work in asynchronous mode. In asynchronous mode
> > > the fault will accumulate into TFSR and will be detected later
> > > asynchronously where it cannot be related to its source and fixed up.
> > > 
> > > That means that both read_word_at_a_time() and load_unaligned_zeropad()
> > > are dodgy in async mode.
> > 
> > load_unaligned_zeropad() has a __mte_enable_tco_async() call to set
> > PSTATE.TCO if in async mode, so that's covered. read_word_at_a_time() is
> > indeed busted and I've had Vincezo's patches for a couple of years
> > already, they just never made it to the list.
> 
> Sorry, I missed the __mte_{enable,disable}_tco_async() calls. So long as
> we're happy to omit the check in that case, that's fine.

That was the easiest. Alternatively we can try to sync the TFSR before
and after the load but with the ISBs, that's too expensive. We could
also do a dummy one byte load before setting TCO. read_word_at_a_time()
does have an explicit kasan_check_read() but last time I checked it has
no effect on MTE.

> I was worried that ex_handler_load_unaligned_zeropad() might not do the
> right thing in response to a tag check fault (e.g. access the wrong 8
> bytes), but it looks as though that's ok due to the way it generates the
> offset and the aligned pointer.
> 
> If load_unaligned_zeropad() is handed a string that starts with an
> unexpected tag (and even if that starts off aligned),
> ex_handler_load_unaligned_zeropad() will access that and cause another
> tag check fault, which will be reported.

Yes, it will report an async tag check fault on the
exit_to_kernel_mode() path _if_ load_unaligned_zeropad() triggered the
fault for other reasons (end of page). It's slightly inconsistent, we
could set TCO for the async case in ex_handler_load_unaligned_zeropad()
as well.

For sync checks, we'd get the first fault ending up in
ex_handler_load_unaligned_zeropad() and a second tag check fault while
processing the first. This ends up in do_tag_recovery and we disable tag
checking after the report. Not ideal but not that bad. We could adjust
ex_handler_load_unaligned_zeropad() to return false if the pointer is
already aligned but we need to check the semantics of
load_unaligned_zeropad(), is it allowed to fault on the first byte?

-- 
Catalin


From mark.rutland at arm.com  Tue Mar 11 04:55:43 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 11 Mar 2025 11:55:43 +0000
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z9AiUQdC4o0g8sxu@arm.com>
References: <20250308023314.3981455-1-pcc@google.com>
 <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
 <Z88r5qFLOSo0itaq@J2N7QTR9R3.cambridge.arm.com>
 <Z88yC7Oaj9DGaswc@arm.com>
 <Z88_fFgr23_EtHMf@J2N7QTR9R3>
 <Z9AiUQdC4o0g8sxu@arm.com>
Message-ID: <Z9Akv6qQFfmYFReD@J2N7QTR9R3>

On Tue, Mar 11, 2025 at 11:45:21AM +0000, Catalin Marinas wrote:
> On Mon, Mar 10, 2025 at 07:37:32PM +0000, Mark Rutland wrote:
> > I was worried that ex_handler_load_unaligned_zeropad() might not do the
> > right thing in response to a tag check fault (e.g. access the wrong 8
> > bytes), but it looks as though that's ok due to the way it generates the
> > offset and the aligned pointer.
> > 
> > If load_unaligned_zeropad() is handed a string that starts with an
> > unexpected tag (and even if that starts off aligned),
> > ex_handler_load_unaligned_zeropad() will access that and cause another
> > tag check fault, which will be reported.
> 
> Yes, it will report an async tag check fault on the
> exit_to_kernel_mode() path _if_ load_unaligned_zeropad() triggered the
> fault for other reasons (end of page).

Sorry, yes. The aligned case I mentioned shouldn't apply here.

> It's slightly inconsistent, we could set TCO for the async case in
> ex_handler_load_unaligned_zeropad() as well.

Yep, I think that'd be necessary for async mode.

> For sync checks, we'd get the first fault ending up in
> ex_handler_load_unaligned_zeropad() and a second tag check fault while
> processing the first. This ends up in do_tag_recovery and we disable
> tag checking after the report. Not ideal but not that bad.

Yep; that's what I was describing in the second paragraph above, though
I forgot to say that was assuming sync or asymm mode.

> We could adjust ex_handler_load_unaligned_zeropad() to return false if
> the pointer is already aligned but we need to check the semantics of
> load_unaligned_zeropad(), is it allowed to fault on the first byte?

IIUC today it's only expected to fault due to misalignment, and the
gneral expectation is that for a sequence of load_unaligned_zeropad()
calls, we should get at least one byte without faulting (for the NUL
terminator).

I reckon it'd be better to figure this out based on the ESR if possible.
Kristina's patches for MOPS would give us that.

Mark.


From brgl at bgdev.pl  Tue Mar 11 04:57:20 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 11 Mar 2025 12:57:20 +0100
Subject: [GIT PULL] davinci updates for v6.15-rc1
Message-ID: <20250311115720.40053-1-brgl@bgdev.pl>

From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Hi!

Please pull the following set of DT updates for the TI DaVinci
architecture.

Thanks,
Bartosz

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git tags/davinci-updates-for-v6.15-rc1

for you to fetch changes up to 58abc69e479cf5b36c4fc4287a11c9d92d2ce4b8:

  ARM: dts: ti: davinci: Align GPIO hog name with bindings (2025-02-03 09:11:33 +0100)

----------------------------------------------------------------
TI DaVinci updates for v6.15-rc1

- make GPIO hog names conform to bindings

----------------------------------------------------------------
Krzysztof Kozlowski (1):
      ARM: dts: ti: davinci: Align GPIO hog name with bindings

 arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)


From m.felsch at pengutronix.de  Tue Mar 11 05:05:03 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 11 Mar 2025 13:05:03 +0100
Subject: [PATCH 4/5] arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
In-Reply-To: <ec38d41d-f2ce-4a98-bb02-d1ae9beb0b3b@gmail.com>
References: <20250221191909.31874-1-laurentiumihalcea111@gmail.com>
 <20250221191909.31874-5-laurentiumihalcea111@gmail.com>
 <Z7jahtO3bxjkMfnc@lizhi-Precision-Tower-5810>
 <cd6a84cd-ff17-45df-becc-9bfc74522f73@gmail.com>
 <20250227-monumental-whale-of-security-b1c84e-mkl@pengutronix.de>
 <Z8CWsI/DKZtDBkzE@lizhi-Precision-Tower-5810>
 <20250228101952.g6tae3ni5xrhjk3y@pengutronix.de>
 <bfe3c719-f1c5-4ae5-9a40-45ad75cd5855@gmail.com>
 <20250307152236.3ayulbjqnu3vn7mf@pengutronix.de>
 <ec38d41d-f2ce-4a98-bb02-d1ae9beb0b3b@gmail.com>
Message-ID: <20250311120503.ryqg2thnj4mkgsjz@pengutronix.de>

On 25-03-10, Laurentiu Mihalcea wrote:
> On 3/7/2025 5:22 PM, Marco Felsch wrote:
> > On 25-03-04, Laurentiu Mihalcea wrote:
> >> On 2/28/2025 12:19 PM, Marco Felsch wrote:
> >>> Hi,
> >>>
> >>> On 25-02-27, Frank Li wrote:
> >>>> On Thu, Feb 27, 2025 at 11:57:54AM +0100, Marc Kleine-Budde wrote:
> >>>>> On 25.02.2025 16:14:34, Mihalcea Laurentiu wrote:
> >>>>>> On 21.02.2025 21:56, Frank Li wrote:
> >>>>>>> On Fri, Feb 21, 2025 at 02:19:08PM -0500, Laurentiu Mihalcea wrote:
> >>>>>>>> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> >>>>>>>>
> >>>>>>>> AIPS5 is actually AIPSTZ5 as it offers some security-related
> >>>>>>>> configurations. Since these configurations need to be applied before
> >>>>>>>> accessing any of the peripherals on the bus, it's better to make AIPSTZ5
> >>>>>>>> be their parent instead of keeping AIPS5 and adding a child node for
> >>>>>>>> AIPSTZ5. Also, because of the security configurations, the address space
> >>>>>>>> of the bus has to be changed to that of the configuration registers.
> >>>>>>> The orginal 0x30c0_0000..0x31200000 include 0x30df0000, why not map only
> >>>>>>> config address part in your drivers.
> >>>>>>>
> >>>>>>> Frank
> >>>>>> Any concerns/anything wrong with current approach?
> >>>>>>
> >>>>>>
> >>>>>> I find it a bit awkward to have the whole bus address space
> >>>>>> in the DT given that we're only interested in using the access
> >>>>>> controller register space.
> >>>>>>
> >>>>>>
> >>>>>> I'm fine with the approach you suggested but I don't see a
> >>>>>> reason for using it?
> >>>>> Looking at the "AIPS5 Memory Map" (page 34/35 in i.MX 8M Plus
> >>>>> Applications Processor Reference Manual, Rev. 3, 08/2024), the
> >>>>> AIPS5_Configuration is part of the AIPS5 bus. IMHO the bus is something
> >>>>> different than the bus configuration. Why not model it as part of the
> >>>>> bus?
> >>>>>
> >>>>>>>> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>>>> index e0d3b8cba221..a1d9b834d2da 100644
> >>>>>>>> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> >>>>>>>> @@ -1399,11 +1399,13 @@ eqos: ethernet at 30bf0000 {
> >>>>>>>>  			};
> >>>>>>>>  		};
> >>>>>>>>
> >>>>>>>> -		aips5: bus at 30c00000 {
> >>>>>>>> -			compatible = "fsl,aips-bus", "simple-bus";
> >>>>>>>> -			reg = <0x30c00000 0x400000>;
> >>>>>>>> +		aips5: bus at 30df0000 {
> >>>>>                        ^^^^^^^^^^^^
> >>>>>>>> +			compatible = "fsl,imx8mp-aipstz", "simple-bus";
> >>>>>>>> +			reg = <0x30df0000 0x10000>;
> >>>>>>>> +			power-domains = <&pgc_audio>;
> >>>>>>>>  			#address-cells = <1>;
> >>>>>>>>  			#size-cells = <1>;
> >>>>>>>> +			#access-controller-cells = <0>;
> >>>>>>>>  			ranges;
> >>>>>>>>
> >>>>>>>>  			spba-bus at 30c00000 {
> >>>>>                         ^^^^^^^^^^^^^^^^^
> >>>>>
> >>>>> This looks very strange: The aips5 bus starts at 0x30df0000 and has a
> >>>>> child bus starting at 0x30c00000?
> >>>> @30df0000 should match controller reg's address.
> >>>>
> >>>> subnode address 0x30c00000,  should be descript in "ranges", which 1:1 map.
> >>>>
> >>>> So it should be reasonable. another example:
> >>>> i2c at 1000 {
> >>>>
> >>>> 	device at 1c <- which use difference address space.
> >>>> }
> >>>>
> >>>> The similar case also happen at pcie.
> >>> I'm not really convinced that pcie and i2c are good examples here. I2C
> >>> does have an other addressing scheme by nature and the hotplug-able pcie
> >>> is dependeds on the pcie device memory map of course.
> >>>
> >>> Here we're talking about an access control IP core on a bus which is
> >>> static.
> >>>
> >>> But.. it looks like from DT abstraction it's fine because STM did
> >>> something similiar with their st,stm32mp25-rifsc or st,stm32-etzpc
> >>> albeit it does look strange and I don't know why we have to limit the
> >>> address space since it was already mapped but used by the fsl,aips-bus
> >>> driver.
> >>>
> >>> Regards,
> >>>   Marco
> >> The address space of the bridge was changed to that of the bridge's
> >> configuration space because I think it's very awkward from the
> >> software's point of view to have to hardcode the offset and size of
> >> the configuration space inside the driver. 
> > You mean the access-controller IP core. I could also arguee that it's
> > akward to put the bridge access-controller IP core into the middle of
> > the bridge address-space instead of placing it at the very beginning of
> > the bridge. But this doesn't help here :)
> >
> > I see what you mean but from DT abstraction POV it seems more reasonable
> > to keep it as it is and just adapt the compatible. The current driver
> > maps the whole address space too, so I don't see why we need to change
> > it if we change it to the aipstz driver. If you see the
> > access-controller IP core as part of the bus I don't see any problem and
> > would argue that the offset detail needs to be handled within the
> > driver.
> >
> >> I also looked at what STM did with "st,stm32-etzpc" so I thought this
> >> would be acceptable from the DT's POV.
> >>
> >> Regarding why I chose not to model the access controller part as a subnode of the
> >> bus:
> >>
> >> ??? 1) The access controller is part of the bridge itself (not a separate module accessible
> >> ? ? via the bridge like it's the case for its children) so I think the current approach
> >> ??? should also make sense if we take the hardware into consideration.
> > I don't like this approach if you see the controller as part of the
> > bridge because the offset could be handled within the bridge driver.
> > I also that the register offset needs to be supplied else we can't reuse
> > the driver and we don't want to adapt the driver for each SoC.
> >
> > What came into my mind is the following:
> >
> > 	spba-bus at 30c00000 {
> > 		compatible = "nxp,imx8mp-aiptz-bus", "nxp,aiptz-bus";
> > 		reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;
> > 		reg-names = "bus", "aipstz";
> >
> > 		child-nodes {};
> > 		child-nodes {};
> > 		child-nodes {};
> > 	}
> >
> > This way we can abstract the access-controller register space and the
> > whole bus register space and a generic driver could be written just by
> > making use two reg fields.
> 
> by changing the compatible, we've also effectively changed the
> programming model.

You need to keep the backward compatible which means, a new kernel have
to boot an old dts (firmware), which is stil the case since the
"simple-bus" driver sill matches on the old dts files.

But this doesn't mean that a new dts (firmware) have to be compatible
with an old kernel.

> I don't really see why we need to stick to the old way of configuring
> the bus node (i.e: specify the whole address space of the bus as well)
> when all we really care about is the AC configuration region?

I see and as I said it's just my oppinion that we should abstract it
this way since upstream already accepted the approach you implemented
for the STM32 case.

If NXP would have placed the AC at the beginning of each AIPS bus you
wouldn't need to deal with this problem too since you would have the
base register already.

> anyhow, I'm not going to insist on this. I think the proposed approach
> will work just fine. If there's no other comments on this then I'll
> just switch to it in V3.

That would be nice but please wait for maintainers feedback e.g Shawn.

Regards,
  Marco


From ankita at nvidia.com  Tue Mar 11 05:07:20 2025
From: ankita at nvidia.com (Ankit Agrawal)
Date: Tue, 11 Mar 2025 12:07:20 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <86r033olwv.wl-maz@kernel.org>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
Message-ID: <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>

Thanks Marc for the feedback.

> No, I'm concerned that a well established API (populating a memslot)
> works in some case and doesn't work in another without a clear
> indication of *why* we have this behaviour.
>
> To me, this indicates that userspace needs to buy in this new
> behaviour, and that behaviour needs to be advertised by a capability,
> which is in turn conditional on FWB.

Yes, that makes sense.

>>> Perhaps we can gracefully fall back to the default device mapping
>>> in such case? But that would cause VM to crash as soon as it makes some
>>> access violating DEVICE_nGnRE.
>
> Which would now be a regression...
> 
> My take is that this cacheable PNFMAP contraption must only be exposed
> to a guest if FWB is available. We can't prevent someone to do an
> mmap() behind our back, but we can at least:
>
> - tell userspace whether this is supported

For my education, what is an accepted way to communicate this? Please let
me know if there are any relevant examples that you may be aware of.

I suppose just checking for FWB (for PFNMAP) and returning some sort of
an error on userspace mmap will not be enough of a hint here?

> - only handle the fault if userspace has bought in this mode
> - report the fault to userspace for it to fix things otherwise
>
>??????? M.
>
> --
> Without deviation from the norm, progress is not possible.

From suzuki.poulose at arm.com  Tue Mar 11 05:16:14 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 11 Mar 2025 12:16:14 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <7cca1edf-fd1b-4622-999e-8e0ca098dfe2@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
 <5ff34bd0-7823-4f31-9f13-bf60d3345b99@arm.com>
 <7cca1edf-fd1b-4622-999e-8e0ca098dfe2@arm.com>
Message-ID: <0ac0f1f5-e4a0-46ae-8ea0-2eba7e21a7e1@arm.com>

On 11/03/2025 10:58, Ryan Roberts wrote:
> On 11/03/2025 10:17, Suzuki K Poulose wrote:
>> On 03/03/2025 10:17, Ryan Roberts wrote:
>>> On 01/03/2025 01:32, Yang Shi wrote:
>>>>
>>>>
>>>>
>>>> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>>>>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>>>>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>>>>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>>>>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>>>>> BBM level 2 is claimed.
>>>>>
>>>>> Add the feature and testing for it under arm_smmu_sva_supported().
>>>>>
>>>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>>>> ---
>>>>>  ?? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>>>>>  ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>>>>>  ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>>>>>  ?? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>>>>>  ?? 4 files changed, 13 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>>> index 63f6d356dc77..1022c63f81b2 100644
>>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>>>>> arm64_cpu_capabilities *caps, int sco
>>>>>  ?????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>>>>>  ?????????????????? return false;
>>>>>  ?????????? }
>>>>> -
>>>>> -??????? return true;
>>>>>  ?????? } else if (scope & SCOPE_LOCAL_CPU) {
>>>>>  ?????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>>>>>  ??????????? * If we have the correct MIDR, but the kernel booted on an
>>>>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>>>>> arm64_cpu_capabilities *caps, int sco
>>>>>  ??????????? * we have an incorrect MIDR, but the kernel booted on a
>>>>>  ??????????? * sufficient CPU, we will not bring up this CPU.
>>>>>  ??????????? */
>>>>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>>>>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>>>>> +??????????? return false;
>>>>>  ?????? }
>>>>>  ?? -??? return false;
>>>>> +??? return has_cpuid_feature(caps, scope);
>>>>
>>>> Do we really need this? IIRC, it means the MIDR has to be in the allow list
>>>> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register
>>>> set.
>>>
>>> Miko, I think this should have been squashed into patch #1? It doesn't belong in
>>> this patch.
>>>
>>> Yang, we discussed this internally and decided that we thought it was best to
>>> still require BBML2 being advertised in the feature register. That way if trying
>>> to use KVM to emulate a CPU that is in the allow list but doesn't really support
>>> BBML2, we won't try to use it.
>>>
>>> But we still end up with the same problem if running on a physical CPU that
>>> supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So
>>
>> I don't understand the problem here ? In the worst case, if we want to disable
>> the BBML2 feature on a given CPU, we could provide an id-
>> override to reset the value of BBML2. Or provide a kernel parameter to
>> disable this in case we want to absolutely disable the feature on a
>> "distro" kernel.
> 
> Hi Suzuki,
> 
> Sorry perhaps I'm confusing everyone; As I recall, we had a conversation before
> Miko posted this series where you were suggesting we should check BOTH that all
> the CPUs' MIDRs are in the allow list AND that BBML2 is advertised in MMFR2 in
> order to decide to enable the CPU feature. My understanding was that without the
> MMFR2 check, you were concerned that in a virtualization scenario, a CPU's MIDR
> could be overridden to emulate a CPU that is in the allow list, but in reality
> the CPU does not support BBML2. We would then enable BBML2 and BadThings (TM)
> will happen. So additionally checking the MMFR2 would solve this.
> 
> But Yang is saying that he plans to add the AmpereOne to the allow list because
> it does support BBML2+NOCONFLICT semantics and we want to benefit from that. But
> AmpereOne does not advertise BBML2 in it's MMFR2. So with the current approach,
> adding AmpereOne to the allow list is not sufficient to enable the feature.
> 
> But back to your original justification for checking the MMFR2; I don't think
> that really solves the problem in general, because we don't just require BBML2,
> we require BBML2+NOCONFLICT. And we can only determine that from the MIDR. So
> why bother checking MMFR2?

My concerns are not around enabling a CPU, but having a damage control 
with a "kernel" that a user has no control over (Read, standard 
distribution kernel).

1. If the combination of the above causes problem (in Virtualization)
2. If the combination of the above is detected to have problems in 
baremetal.

In (1), VMM could control the ID register and disable the feature.

For (2) we could provide an id-override on command line to disable it in
the worst case.

So, having the id register case is a good way to get the system running
with a given kernel (in either world). Without that, we don't have a 
tunable to control the behavior at runtime.

May be I am being over paranoid about this.

> 
> I guess we could provide an id-override on the kernel command line to *enable*
> BBML2 for AmpereOne, but that's not going to be suitable for mass deployment, I

Unfortunately, we can't override to provide the "feature" that is 
missing (at least today).

One option is, run with a whitelist, but provide a kernel parameter to 
disable bbml2 feature.

Something like, arm64.bbml2=0

So the decision is based on the parameter && MIDR list.


Cheers
Suzuki

> don't think?
> 
> Thanks,
> Ryan
> 
>>
>> Suzuki
>>
>>
>>> given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
>>> remove this check.
>>>
>>> Thanks,
>>> Ryan
>>>
>>>
>>>>
>>>> Thanks,
>>>> Yang
>>>>
>>>>>  ?? }
>>>>>  ?? ? #ifdef CONFIG_ARM64_PAN
>>>>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>>>>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>> index 9ba596430e7c..6ba182572788 100644
>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>>>>>  ?????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>>>>>  ?????? }
>>>>>  ?? +??? if (system_supports_bbml2_noabort())
>>>>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>>>>> +
>>>>>  ?????? if ((smmu->features & feat_mask) != feat_mask)
>>>>>  ?????????? return false;
>>>>>  ?? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>>>>> arm/arm-smmu-v3/arm-smmu-v3.c
>>>>> index 358072b4e293..dcee0bdec924 100644
>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>>>>> arm_smmu_device *smmu)
>>>>>  ?????? if (FIELD_GET(IDR3_RIL, reg))
>>>>>  ?????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>>>>>  ?? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>>>>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>>>>> +
>>>>>  ?????? /* IDR5 */
>>>>>  ?????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>>>>>  ?? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>>>>> arm/arm-smmu-v3/arm-smmu-v3.h
>>>>> index bd9d7c85576a..85eaf3ab88c2 100644
>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>>>>>  ?? #define ARM_SMMU_IDR3??????????? 0xc
>>>>>  ?? #define IDR3_FWB??????????? (1 << 8)
>>>>>  ?? #define IDR3_RIL??????????? (1 << 10)
>>>>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>>>>> +#define IDR3_BBML1??????????? (1 << 11)
>>>>> +#define IDR3_BBML2??????????? (2 << 11)
>>>>>  ?? ? #define ARM_SMMU_IDR5??????????? 0x14
>>>>>  ?? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>>>>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>>>>>  ?? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>>>>>  ?? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>>>>>  ?? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>>>>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>>>>>  ?????? u32??????????????? features;
>>>>>  ?? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)
>>>>
>>>
>>
> 



From lorenzo at kernel.org  Tue Mar 11 05:18:34 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:34 +0100
Subject: [PATCH net-next 2/7] net: mvpp2: Add metadata support for xdp mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-2-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in mvpp2 driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index f166dc4e650372d66e248601a5c948819e1dcd79..54a235366a01bdba526a1956f27836bcdee210ae 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3915,13 +3915,13 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 
 	while (rx_done < rx_todo) {
 		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+		u32 rx_status, timestamp, metasize = 0;
 		struct mvpp2_bm_pool *bm_pool;
 		struct page_pool *pp = NULL;
 		struct sk_buff *skb;
 		unsigned int frag_size;
 		dma_addr_t dma_addr;
 		phys_addr_t phys_addr;
-		u32 rx_status, timestamp;
 		int pool, rx_bytes, err, ret;
 		struct page *page;
 		void *data;
@@ -3983,7 +3983,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 			xdp_init_buff(&xdp, PAGE_SIZE, xdp_rxq);
 			xdp_prepare_buff(&xdp, data,
 					 MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM,
-					 rx_bytes, false);
+					 rx_bytes, true);
 
 			ret = mvpp2_run_xdp(port, xdp_prog, &xdp, pp, &ps);
 
@@ -3999,6 +3999,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 				ps.rx_bytes += rx_bytes;
 				continue;
 			}
+
+			metasize = xdp.data - xdp.data_meta;
 		}
 
 		if (frag_size)
@@ -4038,6 +4040,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 
 		skb_reserve(skb, MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM);
 		skb_put(skb, rx_bytes);
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		skb->ip_summed = mvpp2_rx_csum(port, rx_status);
 		skb->protocol = eth_type_trans(skb, dev);
 

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 05:18:35 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:35 +0100
Subject: [PATCH net-next 3/7] net: netsec: Add metadata support for xdp
 mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-3-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in netsec driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/socionext/netsec.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index dc99821c6226fbaece65c8ade23899f610b44a9a..ee890de69ffe795dbdcc5331e36be86769f0d9a6 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -970,7 +970,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
 		struct netsec_desc *desc = &dring->desc[idx];
 		struct page *page = virt_to_page(desc->addr);
-		u32 xdp_result = NETSEC_XDP_PASS;
+		u32 metasize, xdp_result = NETSEC_XDP_PASS;
 		struct sk_buff *skb = NULL;
 		u16 pkt_len, desc_len;
 		dma_addr_t dma_handle;
@@ -1019,7 +1019,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		prefetch(desc->addr);
 
 		xdp_prepare_buff(&xdp, desc->addr, NETSEC_RXBUF_HEADROOM,
-				 pkt_len, false);
+				 pkt_len, true);
 
 		if (xdp_prog) {
 			xdp_result = netsec_run_xdp(priv, xdp_prog, &xdp);
@@ -1048,6 +1048,9 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 
 		skb_reserve(skb, xdp.data - xdp.data_hard_start);
 		skb_put(skb, xdp.data_end - xdp.data);
+		metasize = xdp.data - xdp.data_meta;
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		skb->protocol = eth_type_trans(skb, priv->ndev);
 
 		if (priv->rx_cksum_offload_flag &&

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 05:18:36 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:36 +0100
Subject: [PATCH net-next 4/7] net: octeontx2: Add metadata support for xdp
 mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-4-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in octeontx2 driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 6bc5ce5a9f61cc2830975e7cc5219344760b0e51..af8cabe828d05c8832085d24d183312f24d00330 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -41,7 +41,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 				     struct bpf_prog *prog,
 				     struct nix_cqe_rx_s *cqe,
 				     struct otx2_cq_queue *cq,
-				     bool *need_xdp_flush);
+				     u32 *metasize, bool *need_xdp_flush);
 
 static void otx2_sq_set_sqe_base(struct otx2_snd_queue *sq,
 				 struct sk_buff *skb)
@@ -336,6 +336,7 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	struct nix_rx_sg_s *sg = &cqe->sg;
 	struct sk_buff *skb = NULL;
 	void *end, *start;
+	u32 metasize = 0;
 	u64 *seg_addr;
 	u16 *seg_size;
 	int seg;
@@ -346,7 +347,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	}
 
 	if (pfvf->xdp_prog)
-		if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq, need_xdp_flush))
+		if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq,
+					     &metasize, need_xdp_flush))
 			return;
 
 	skb = napi_get_frags(napi);
@@ -378,6 +380,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 		skb->mark = parse->match_id;
 
 	skb_mark_for_recycle(skb);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 
 	napi_gro_frags(napi);
 }
@@ -1482,7 +1486,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 				     struct bpf_prog *prog,
 				     struct nix_cqe_rx_s *cqe,
 				     struct otx2_cq_queue *cq,
-				     bool *need_xdp_flush)
+				     u32 *metasize, bool *need_xdp_flush)
 {
 	struct xdp_buff xdp, *xsk_buff = NULL;
 	unsigned char *hard_start;
@@ -1514,13 +1518,14 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 
 	hard_start = (unsigned char *)phys_to_virt(pa);
 	xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM,
-			 cqe->sg.seg_size, false);
+			 cqe->sg.seg_size, true);
 
 	act = bpf_prog_run_xdp(prog, &xdp);
 
 handle_xdp_verdict:
 	switch (act) {
 	case XDP_PASS:
+		*metasize = xdp.data - xdp.data_meta;
 		break;
 	case XDP_TX:
 		qidx += pfvf->hw.tx_queues;

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 05:18:37 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:37 +0100
Subject: [PATCH net-next 5/7] net: ethernet: mediatek: Add metadata support
 for xdp mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-5-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in mediatek driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 922330b3f4d70421276ecd3f4ab175b3ae263f71..43197b28b3e745319e974c6022a6a51b6953f60a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2122,7 +2122,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 		if (ring->page_pool) {
 			struct page *page = virt_to_head_page(data);
 			struct xdp_buff xdp;
-			u32 ret;
+			u32 ret, metasize;
 
 			new_data = mtk_page_pool_get_buff(ring->page_pool,
 							  &dma_addr,
@@ -2138,7 +2138,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
 			xdp_init_buff(&xdp, PAGE_SIZE, &ring->xdp_q);
 			xdp_prepare_buff(&xdp, data, MTK_PP_HEADROOM, pktlen,
-					 false);
+					 true);
 			xdp_buff_clear_frags_flag(&xdp);
 
 			ret = mtk_xdp_run(eth, ring, &xdp, netdev);
@@ -2158,6 +2158,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
 			skb_reserve(skb, xdp.data - xdp.data_hard_start);
 			skb_put(skb, xdp.data_end - xdp.data);
+			metasize = xdp.data - xdp.data_meta;
+			if (metasize)
+				skb_metadata_set(skb, metasize);
 			skb_mark_for_recycle(skb);
 		} else {
 			if (ring->frag_size <= PAGE_SIZE)

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 05:18:38 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:38 +0100
Subject: [PATCH net-next 6/7] net: mana: Add metadata support for xdp mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-6-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in mana driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/microsoft/mana/mana_bpf.c | 2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c  | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
index 23b1521c0df96e7fd595daad8b49fa9be935090c..d30721d4516fc60cf8883f2b35cc561559082ccc 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
@@ -91,7 +91,7 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
 		goto out;
 
 	xdp_init_buff(xdp, PAGE_SIZE, &rxq->xdp_rxq);
-	xdp_prepare_buff(xdp, buf_va, XDP_PACKET_HEADROOM, pkt_len, false);
+	xdp_prepare_buff(xdp, buf_va, XDP_PACKET_HEADROOM, pkt_len, true);
 
 	act = bpf_prog_run_xdp(prog, xdp);
 
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 2d826077d38cdac7ebe9c355cf883b0d727eeca2..a3986fc47b819dae1f8a1d62ebe1ff051b144236 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1559,8 +1559,12 @@ static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va,
 		return NULL;
 
 	if (xdp->data_hard_start) {
+		u32 metasize = xdp->data - xdp->data_meta;
+
 		skb_reserve(skb, xdp->data - xdp->data_hard_start);
 		skb_put(skb, xdp->data_end - xdp->data);
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		return skb;
 	}
 

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 05:18:39 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:39 +0100
Subject: [PATCH net-next 7/7] net: ti: cpsw: Add metadata support for xdp
 mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-7-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in cpsw/cpsw_new
drivers

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/ti/cpsw.c     | 6 +++++-
 drivers/net/ethernet/ti/cpsw_new.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 0cb6fa6e5b7d4fb9703633f0d67a7e95e6e7d8aa..a984b7d84e5e5917b83547c862924ccd30d83601 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -351,6 +351,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	int			ret = 0, port, ch = xmeta->ch;
 	int			headroom = CPSW_HEADROOM_NA;
 	struct net_device	*ndev = xmeta->ndev;
+	u32			metasize = 0;
 	struct cpsw_priv	*priv;
 	struct page_pool	*pool;
 	struct sk_buff		*skb;
@@ -400,7 +401,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			size -= CPSW_RX_VLAN_ENCAP_HDR_SIZE;
 		}
 
-		xdp_prepare_buff(&xdp, pa, headroom, size, false);
+		xdp_prepare_buff(&xdp, pa, headroom, size, true);
 
 		port = priv->emac_port + cpsw->data.dual_emac;
 		ret = cpsw_run_xdp(priv, ch, &xdp, page, port, &len);
@@ -408,6 +409,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			goto requeue;
 
 		headroom = xdp.data - xdp.data_hard_start;
+		metasize = xdp.data - xdp.data_meta;
 
 		/* XDP prog can modify vlan tag, so can't use encap header */
 		status &= ~CPDMA_RX_VLAN_ENCAP;
@@ -423,6 +425,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
 
 	skb_reserve(skb, headroom);
 	skb_put(skb, len);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->dev = ndev;
 	if (status & CPDMA_RX_VLAN_ENCAP)
 		cpsw_rx_vlan_encap(skb);
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 3da1c131335df1ff79b32ce0e3ea5200a2e53f4b..5b5b52e4e7a757a14965fe6df41935aed547111f 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -293,6 +293,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	struct page_pool *pool;
 	struct sk_buff *skb;
 	struct xdp_buff xdp;
+	u32 metasize = 0;
 	int ret = 0;
 	dma_addr_t dma;
 
@@ -345,13 +346,14 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			size -= CPSW_RX_VLAN_ENCAP_HDR_SIZE;
 		}
 
-		xdp_prepare_buff(&xdp, pa, headroom, size, false);
+		xdp_prepare_buff(&xdp, pa, headroom, size, true);
 
 		ret = cpsw_run_xdp(priv, ch, &xdp, page, priv->emac_port, &len);
 		if (ret != CPSW_XDP_PASS)
 			goto requeue;
 
 		headroom = xdp.data - xdp.data_hard_start;
+		metasize = xdp.data - xdp.data_meta;
 
 		/* XDP prog can modify vlan tag, so can't use encap header */
 		status &= ~CPDMA_RX_VLAN_ENCAP;
@@ -368,6 +370,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	skb->offload_fwd_mark = priv->offload_fwd_mark;
 	skb_reserve(skb, headroom);
 	skb_put(skb, len);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->dev = ndev;
 	if (status & CPDMA_RX_VLAN_ENCAP)
 		cpsw_rx_vlan_encap(skb);

-- 
2.48.1



From andyshrk at 163.com  Tue Mar 11 05:22:10 2025
From: andyshrk at 163.com (Andy Yan)
Date: Tue, 11 Mar 2025 20:22:10 +0800 (CST)
Subject: [PATCH] phy: rockchip: usbdp: Check these parameters
 only when the corresponding set flags are set
In-Reply-To: <Z9Aa6v1/1KRdZDKE@vaman>
References: <20250306065952.485809-1-andyshrk@163.com>
 <Z86UOmPg/UDSBajZ@vaman>
 <1379400c.90c.19582b05f74.Coremail.andyshrk@163.com>
 <Z9Aa6v1/1KRdZDKE@vaman>
Message-ID: <5382b861.a48b.1958527c4dd.Coremail.andyshrk@163.com>



Hi Vinod,
At 2025-03-11 19:13:46, "Vinod Koul" <vkoul at kernel.org> wrote:
>On 11-03-25, 08:52, Andy Yan wrote:
>
>> Do you mean we should do it like this:
>> 
>> static int rk_udphy_dp_phy_configure(struct phy *phy,
>>                                      union phy_configure_opts *opts)
>> {
>>         struct rk_udphy *udphy = phy_get_drvdata(phy);
>>         struct phy_configure_opts_dp *dp = &opts->dp;
>>         u32 i, val, lane;
>>         int ret;
>> 
>>        .............
>>       if (dp->set_rate)
>>            	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
>>      if (dp->set_lanes)
>>                 ret = rk_udphy_dp_phy_verify_link_lanes(dp->lanes);
>>      if (dp->set_voltates)
>>                ret = rk_udphy_dp_phy_verify_link_voltate(dp->voltate);
>> 
>> 
>> Add helper for each of them ?
>
>That would look better for sure

I will do as that in V2.

Thanks

>
>-- 
>~Vinod

From michal.kubiak at intel.com  Tue Mar 11 05:22:21 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Tue, 11 Mar 2025 13:22:21 +0100
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring
 support for i.MX95 ENETC
In-Reply-To: <20250311053830.1516523-3-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
Message-ID: <Z9Aq/XNEBQoh8X2R@localhost.localdomain>

On Tue, Mar 11, 2025 at 01:38:18PM +0800, Wei Fang wrote:
> The command BD ring is used to configure functionality where the
> underlying resources may be shared between different entities or being
> too large to configure using direct registers (such as lookup tables).
> 
> Because the command BD and table formats of i.MX95 and LS1028A are very
> different, the software processing logic is also different. In order to
> ensure driver compatibility, struct enetc_si_ops is introduced. This
> structure defines some hooks shared by VSI and PSI. Different hardware
> driver will register different hooks, For example, setup_cbdr() is used
> to initialize the command BD ring, and teardown_cbdr() is used to free
> the command BD ring.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>

Thanks,
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>


From friday.yang at mediatek.com  Tue Mar 11 05:23:20 2025
From: friday.yang at mediatek.com (Friday Yang)
Date: Tue, 11 Mar 2025 20:23:20 +0800
Subject: [PATCH v5 0/2] Add SMI reset and clamp for MediaTek MT8188 SoC
Message-ID: <20250311122327.20685-1-friday.yang@mediatek.com>

Based on tag: next-20250307, linux-next/master

On the MediaTek MT8188 SoC platform, we encountered power-off failures
and SMI bus hang issues during camera stress tests. The issue arises
because bus glitches are sometimes produced when MTCMOS powers on or
off. While this is fairly normal, the software must handle these
glitches to avoid mistaking them for transaction signals. What's
more, this issue emerged only after the initial upstreaming of SMI
driver.

The software solutions can be summarized as follows:

1. Use CLAMP to disable the SMI sub-common port after turning off the
   LARB CG and before turning off the LARB MTCMOS.
2. Use CLAMP to disable/enable the SMI sub-common port.
3. Implement an AXI reset for SMI LARBs.

Changes v5:
- Use 'devm_pm_runtime_enable' instead of 'pm_runtime_enable'.
- Remove 'pm_runtime_disable' in 'mtk_smi_common_remove' and
  'mtk_smi_larb_remove'.

v4:
https://lore.kernel.org/lkml/20250221074846.14105-2-friday.yang at mediatek.com/
https://lore.kernel.org/lkml/20250221074846.14105-3-friday.yang at mediatek.com/

friday.yang (2):
  dt-bindings: memory: mediatek: Add SMI reset and clamp for MT8188
  memory: mtk-smi: mt8188: Add SMI reset and clamp for MT8188

 .../mediatek,smi-common.yaml                  |   2 +
 .../memory-controllers/mediatek,smi-larb.yaml |  19 +++
 drivers/memory/mtk-smi.c                      | 150 +++++++++++++++++-
 3 files changed, 164 insertions(+), 7 deletions(-)

--
2.46.0



From friday.yang at mediatek.com  Tue Mar 11 05:23:21 2025
From: friday.yang at mediatek.com (Friday Yang)
Date: Tue, 11 Mar 2025 20:23:21 +0800
Subject: [PATCH v5 1/2] dt-bindings: memory: mediatek: Add SMI reset and clamp for MT8188
In-Reply-To: <20250311122327.20685-1-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
Message-ID: <20250311122327.20685-2-friday.yang@mediatek.com>

From: "Friday Yang" <friday.yang at mediatek.com>

On the MediaTek platform, some SMI LARBs are directly connected to
the SMI Common, while others are connected to the SMI Sub-Common,
which in turn is connected to the SMI Common. The hardware block
diagram can be described as follows.

             SMI-Common(Smart Multimedia Interface Common)
                 |
         +----------------+------------------+
         |                |                  |
         |                |                  |
         |                |                  |
         |                |                  |
         |                |                  |
       larb0       SMI-Sub-Common0     SMI-Sub-Common1
                   |      |     |      |             |
                  larb1  larb2 larb3  larb7       larb9

For previous discussion on the direction of the code modifications,
please refer to:
https://lore.kernel.org/all/CAFGrd9qZhObQXvm2_abqaX83xMLqxjQETB2=wXpobDWU1CnvkA at mail.gmail.com/
https://lore.kernel.org/all/CAPDyKFpokXV2gJDgowbixTvOH_5VL3B5H8eyhP+KJ5Fasm2rFg at mail.gmail.com/

On the MediaTek MT8188 SoC platform, we encountered power-off failures
and SMI bus hang issues during camera stress tests. The issue arises
because bus glitches are sometimes produced when MTCMOS powers on or
off. While this is fairly normal, the software must handle these
glitches to avoid mistaking them for transaction signals. What's
more, this issue emerged only after the initial upstreaming of this
binding. Without these patches, the SMI becomes unstable during camera
stress tests.

The software solutions can be summarized as follows:

1. Use CLAMP to disable the SMI sub-common port after turning off the
   LARB CG and before turning off the LARB MTCMOS.
2. Use CLAMP to disable/enable the SMI sub-common port.
3. Implement an AXI reset for SMI LARBs.

This patch primarily add two changes:
1. Add compatible for SMI sub-common on MT8188 SoC.
2. Add 'resets' and 'reset-names' properties for SMI LARBs to
   support SMI reset operations.

Signed-off-by: Friday Yang <friday.yang at mediatek.com>
---
 .../mediatek,smi-common.yaml                  |  2 ++
 .../memory-controllers/mediatek,smi-larb.yaml | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
index 2f36ac23604c..4392d349878c 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
@@ -39,6 +39,7 @@ properties:
           - mediatek,mt8186-smi-common
           - mediatek,mt8188-smi-common-vdo
           - mediatek,mt8188-smi-common-vpp
+          - mediatek,mt8188-smi-sub-common
           - mediatek,mt8192-smi-common
           - mediatek,mt8195-smi-common-vdo
           - mediatek,mt8195-smi-common-vpp
@@ -107,6 +108,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - mediatek,mt8188-smi-sub-common
               - mediatek,mt8195-smi-sub-common
     then:
       required:
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
index 2381660b324c..f4f0ed0f1fd9 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
@@ -69,6 +69,12 @@ properties:
     description: the hardware id of this larb. It's only required when this
       hardware id is not consecutive from its M4U point of view.

+  resets:
+    maxItems: 1
+
+  reset-names:
+    const: larb
+
 required:
   - compatible
   - reg
@@ -125,6 +131,19 @@ allOf:
       required:
         - mediatek,larb-id

+  - if:  # only for image, camera and ipe subsys
+      properties:
+        compatible:
+          const: mediatek,mt8188-smi-larb
+        mediatek,larb-id:
+          enum:
+            [ 9, 10, 11, 12, 13, 16, 17, 18, 19, 20 ]
+
+    then:
+      required:
+        - resets
+        - reset-names
+
 additionalProperties: false

 examples:
--
2.46.0



From friday.yang at mediatek.com  Tue Mar 11 05:23:22 2025
From: friday.yang at mediatek.com (Friday Yang)
Date: Tue, 11 Mar 2025 20:23:22 +0800
Subject: [PATCH v5 2/2] memory: mtk-smi: mt8188: Add SMI reset and clamp for MT8188
In-Reply-To: <20250311122327.20685-1-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
Message-ID: <20250311122327.20685-3-friday.yang@mediatek.com>

From: "Friday Yang" <friday.yang at mediatek.com>

To prevent handling glitch signals during MTCMOS on/off transitions,
SMI requires clamp and reset operations. Parse the reset settings for
SMI LARBs and the clamp settings for the SMI Sub-Common. Register
genpd callback for the SMI LARBs located in image, camera and IPE
subsystems, and apply reset and clamp operations within the callback.

Signed-off-by: Friday Yang <friday.yang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 150 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 143 insertions(+), 7 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 5710348f72f6..300d01d47c89 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -10,11 +10,15 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
 #include <linux/soc/mediatek/mtk_sip_svc.h>
 #include <soc/mediatek/smi.h>
 #include <dt-bindings/memory/mt2701-larb-port.h>
@@ -36,6 +40,12 @@
 #define SMI_DCM				0x300
 #define SMI_DUMMY			0x444

+#define SMI_COMMON_CLAMP_EN		0x3c0
+#define SMI_COMMON_CLAMP_EN_SET		0x3c4
+#define SMI_COMMON_CLAMP_EN_CLR		0x3c8
+
+#define SMI_SUB_COMM_INPORT_NR		(8)
+
 /* SMI LARB */
 #define SMI_LARB_SLP_CON                0xc
 #define SLP_PROT_EN                     BIT(0)
@@ -134,6 +144,7 @@ struct mtk_smi_larb_gen {
 	unsigned int			larb_direct_to_common_mask;
 	unsigned int			flags_general;
 	const u8			(*ostd)[SMI_LARB_PORT_NR_MAX];
+	const u8			*clamp_port;
 };

 struct mtk_smi {
@@ -150,6 +161,7 @@ struct mtk_smi {
 };

 struct mtk_smi_larb { /* larb: local arbiter */
+	struct device			*dev;
 	struct mtk_smi			smi;
 	void __iomem			*base;
 	struct device			*smi_common_dev; /* common or sub-common dev */
@@ -157,6 +169,10 @@ struct mtk_smi_larb { /* larb: local arbiter */
 	int				larbid;
 	u32				*mmu;
 	unsigned char			*bank;
+	struct regmap			*sub_comm_syscon;
+	u8				sub_comm_inport;
+	struct notifier_block		nb;
+	struct reset_control		*rst_con;
 };

 static int
@@ -377,6 +393,19 @@ static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
 	[28] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
 };

+static const u8 mtk_smi_larb_clamp_port_mt8188[MTK_LARB_NR_MAX] = {
+	[9]	= BIT(1), /* larb10 */
+	[10]	= BIT(2), /* larb11a */
+	[11]	= BIT(2), /* larb11b */
+	[12]	= BIT(3), /* larb11c */
+	[13]	= BIT(0), /* larb12 */
+	[16]	= BIT(1), /* larb15 */
+	[17]	= BIT(2), /* larb16a */
+	[18]	= BIT(2), /* larb16b */
+	[19]	= BIT(3), /* larb17a */
+	[20]	= BIT(3), /* larb17b */
+};
+
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
 	.port_in_larb = {
 		LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
@@ -423,6 +452,7 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
 	.flags_general	            = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
 				      MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
 	.ostd		            = mtk_smi_larb_mt8188_ostd,
+	.clamp_port                 = mtk_smi_larb_clamp_port_mt8188,
 };

 static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
@@ -472,6 +502,46 @@ static void mtk_smi_larb_sleep_ctrl_disable(struct mtk_smi_larb *larb)
 	writel_relaxed(0, larb->base + SMI_LARB_SLP_CON);
 }

+static int mtk_smi_larb_clamp_protect_enable(struct device *dev, bool enable)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	u32 reg;
+	int ret;
+
+	/* sub_comm_syscon could be NULL if larb directly linked to SMI common */
+	if (!larb->sub_comm_syscon)
+		return -EINVAL;
+
+	reg = enable ? SMI_COMMON_CLAMP_EN_SET : SMI_COMMON_CLAMP_EN_CLR;
+
+	ret = regmap_write(larb->sub_comm_syscon, reg,
+			   larb->sub_comm_inport);
+	if (ret)
+		dev_err(dev, "Unable to %s clamp for input port %d: %d\n",
+			enable ? "enable" : "disable",
+			larb->sub_comm_inport, ret);
+
+	return ret;
+}
+
+static int mtk_smi_genpd_callback(struct notifier_block *nb,
+				  unsigned long flags, void *data)
+{
+	struct mtk_smi_larb *larb = container_of(nb, struct mtk_smi_larb, nb);
+	struct device *dev = larb->dev;
+
+	if (flags == GENPD_NOTIFY_PRE_ON || flags == GENPD_NOTIFY_PRE_OFF) {
+		/* disable related SMI sub-common port */
+		mtk_smi_larb_clamp_protect_enable(dev, true);
+	} else if (flags == GENPD_NOTIFY_ON) {
+		/* enable related SMI sub-common port */
+		reset_control_reset(larb->rst_con);
+		mtk_smi_larb_clamp_protect_enable(dev, false);
+	}
+
+	return NOTIFY_OK;
+}
+
 static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev)
 {
 	struct platform_device *smi_com_pdev;
@@ -528,6 +598,53 @@ static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi,
 	return ret;
 }

+static int mtk_smi_larb_parse_clamp_optional(struct mtk_smi_larb *larb)
+{
+	struct device *dev = larb->dev;
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+	u32 larb_id;
+	int ret;
+
+	/**
+	 * Only SMI LARBs in camera, image and IPE subsys need to
+	 * apply clamp and reset operations, others can be skipped.
+	 */
+	ret = of_property_read_u32(dev->of_node, "mediatek,larb-id", &larb_id);
+	if (ret)
+		return -EINVAL;
+	if (!larb_gen->clamp_port || !larb_gen->clamp_port[larb_id])
+		return 0;
+
+	larb->sub_comm_inport = larb_gen->clamp_port[larb_id];
+	larb->sub_comm_syscon = syscon_regmap_lookup_by_phandle(dev->of_node,
+								"mediatek,smi");
+	if (IS_ERR(larb->sub_comm_syscon)) {
+		larb->sub_comm_syscon = NULL;
+		return dev_err_probe(dev, -EINVAL,
+				     "Unknown clamp port for larb %d\n", larb_id);
+	}
+
+	return 0;
+}
+
+static int mtk_smi_larb_parse_reset_optional(struct mtk_smi_larb *larb)
+{
+	struct device *dev = larb->dev;
+	int ret;
+
+	larb->rst_con = devm_reset_control_get_optional_exclusive(dev, "larb");
+	if (!larb->rst_con)
+		return 0;
+
+	larb->nb.notifier_call = mtk_smi_genpd_callback;
+	ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
+	if (ret)
+		return dev_err_probe(dev, -EINVAL,
+				     "Failed to add genpd callback %d\n", ret);
+
+	return 0;
+}
+
 static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
@@ -538,6 +655,7 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	if (!larb)
 		return -ENOMEM;

+	larb->dev = dev;
 	larb->larb_gen = of_device_get_match_data(dev);
 	larb->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(larb->base))
@@ -554,15 +672,26 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;

-	pm_runtime_enable(dev);
+	ret = mtk_smi_larb_parse_clamp_optional(larb);
+	if (ret)
+		goto err_link_remove;
+
+	ret = mtk_smi_larb_parse_reset_optional(larb);
+	if (ret)
+		goto err_link_remove;
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		goto err_link_remove;
+
 	platform_set_drvdata(pdev, larb);
 	ret = component_add(dev, &mtk_smi_larb_component_ops);
 	if (ret)
-		goto err_pm_disable;
+		goto err_link_remove;
+
 	return 0;

-err_pm_disable:
-	pm_runtime_disable(dev);
+err_link_remove:
 	device_link_remove(dev, larb->smi_common_dev);
 	return ret;
 }
@@ -572,7 +701,6 @@ static void mtk_smi_larb_remove(struct platform_device *pdev)
 	struct mtk_smi_larb *larb = platform_get_drvdata(pdev);

 	device_link_remove(&pdev->dev, larb->smi_common_dev);
-	pm_runtime_disable(&pdev->dev);
 	component_del(&pdev->dev, &mtk_smi_larb_component_ops);
 }

@@ -686,6 +814,11 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
 	.init     = mtk_smi_common_mt8195_init,
 };

+static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8188 = {
+	.type     = MTK_SMI_GEN2_SUB_COMM,
+	.has_gals = true,
+};
+
 static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
 	.type     = MTK_SMI_GEN2,
 	.has_gals = true,
@@ -729,6 +862,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
 	{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
 	{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
 	{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
+	{.compatible = "mediatek,mt8188-smi-sub-common", .data = &mtk_smi_sub_common_mt8188},
 	{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
 	{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
 	{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
@@ -787,7 +921,10 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 			return ret;
 	}

-	pm_runtime_enable(dev);
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		return ret;
+
 	platform_set_drvdata(pdev, common);
 	return 0;
 }
@@ -798,7 +935,6 @@ static void mtk_smi_common_remove(struct platform_device *pdev)

 	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
 		device_link_remove(&pdev->dev, common->smi_common_dev);
-	pm_runtime_disable(&pdev->dev);
 }

 static int __maybe_unused mtk_smi_common_resume(struct device *dev)
--
2.46.0



From balamanikandan.gunasundar at microchip.com  Tue Mar 11 05:28:44 2025
From: balamanikandan.gunasundar at microchip.com (Balamanikandan Gunasundar)
Date: Tue, 11 Mar 2025 17:58:44 +0530
Subject: [PATCH v2 0/3] dt-bindings: mtd: microchip-nand: convert txt to yaml
Message-ID: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>

Convert microchip nand controllers from text to yaml

This patch is a respin of
https://lore.kernel.org/all/20240320-linux-next-nand-yaml-v1-0-2d2495363e88 at microchip.com/

Summary of changes:

[PATCH v2 1/3] dt-bindings: mtd: microchip-nand: convert txt to yaml
- Change the filename to match the compatible string
- Drop items and oneOf in the compatible property as it is just an enum
- Remove the if in the #address-cells and #size-cells
- Remove the unwanted comments that refers to .txt files
- Fix reg property description
- Define the properties in a list and add constraints
- Fix DT coding style and droped unused labels

[PATCH v2 2/3] dt-bindings: mtd: microchip-nand: add atmel pmecc
- Rename filename to match compatible string
- Add constraints for sam9x7
- Droped unused dt labels 

[PATCH v2 3/3] dt-bindings: mtd: atmel-nand: add legacy nand
- Filename matching the compatibles
- Remove "bindings" from the subject
- Remove "deprecated" as these are the only bindings available for the devices
- Add missing constraints.
- Add default for nand-ecc-mode
- Add 32 in pmecc-cap for sama5d2
- Add default for sector-size, pmecc-lookup-table-offset, nand-bus-width

Balamanikandan Gunasundar (3):
  dt-bindings: mtd: microchip-nand: convert txt to yaml
  dt-bindings: mtd: microchip-nand: add atmel pmecc
  dt-bindings: mtd: atmel-nand: add legacy nand controllers

 .../devicetree/bindings/mtd/atmel-nand.txt    | 227 ------------------
 .../devicetree/bindings/mtd/atmel-nand.yaml   | 163 +++++++++++++
 .../mtd/microchip,nand-controller.yaml        | 175 ++++++++++++++
 .../bindings/mtd/microchip,pmecc.yaml         |  67 ++++++
 4 files changed, 405 insertions(+), 227 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.yaml
 create mode 100644 Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml
 create mode 100644 Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml

-- 
2.34.1



From balamanikandan.gunasundar at microchip.com  Tue Mar 11 05:28:45 2025
From: balamanikandan.gunasundar at microchip.com (Balamanikandan Gunasundar)
Date: Tue, 11 Mar 2025 17:58:45 +0530
Subject: [PATCH v2 1/3] dt-bindings: mtd: microchip-nand: convert txt to yaml
In-Reply-To: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
Message-ID: <20250311122847.90081-2-balamanikandan.gunasundar@microchip.com>

Convert text to yaml for microchip nand controller

Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
---

Changes in v2:

- Change the filename to match the compatible string
- Drop items and oneOf in the compatible property as it is just an enum
- Remove the if in the #address-cells and #size-cells
- Remove the unwanted comments that refers to .txt files
- Fix reg property description
- Define the properties in a list and add constraints
- Fix DT coding style and droped unused labels

 .../devicetree/bindings/mtd/atmel-nand.txt    |  50 -----
 .../mtd/microchip,nand-controller.yaml        | 175 ++++++++++++++++++
 2 files changed, 175 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml

diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index e36c35b17873..dbbc17a866f2 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -1,53 +1,3 @@
-Atmel NAND flash controller bindings
-
-The NAND flash controller node should be defined under the EBI bus (see
-Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt).
-One or several NAND devices can be defined under this NAND controller.
-The NAND controller might be connected to an ECC engine.
-
-* NAND controller bindings:
-
-Required properties:
-- compatible: should be one of the following
-	"atmel,at91rm9200-nand-controller"
-	"atmel,at91sam9260-nand-controller"
-	"atmel,at91sam9261-nand-controller"
-	"atmel,at91sam9g45-nand-controller"
-	"atmel,sama5d3-nand-controller"
-	"microchip,sam9x60-nand-controller"
-- ranges: empty ranges property to forward EBI ranges definitions.
-- #address-cells: should be set to 2.
-- #size-cells: should be set to 1.
-- atmel,nfc-io: phandle to the NFC IO block. Only required for sama5d3
-		controllers.
-- atmel,nfc-sram: phandle to the NFC SRAM block. Only required for sama5d3
-		  controllers.
-
-Optional properties:
-- ecc-engine: phandle to the PMECC block. Only meaningful if the SoC embeds
-	      a PMECC engine.
-
-* NAND device/chip bindings:
-
-Required properties:
-- reg: describes the CS lines assigned to the NAND device. If the NAND device
-       exposes multiple CS lines (multi-dies chips), your reg property will
-       contain X tuples of 3 entries.
-       1st entry: the CS line this NAND chip is connected to
-       2nd entry: the base offset of the memory region assigned to this
-		  device (always 0)
-       3rd entry: the memory region size (always 0x800000)
-
-Optional properties:
-- rb-gpios: the GPIO(s) used to check the Ready/Busy status of the NAND.
-- cs-gpios: the GPIO(s) used to control the CS line.
-- det-gpios: the GPIO used to detect if a Smartmedia Card is present.
-- atmel,rb: an integer identifying the native Ready/Busy pin. Only meaningful
-	    on sama5 SoCs.
-
-All generic properties are described in the generic yaml files under
-Documentation/devicetree/bindings/mtd/.
-
 * ECC engine (PMECC) bindings:
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml
new file mode 100644
index 000000000000..bf644ab0cf27
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/microchip,nand-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip NAND flash controller
+
+maintainers:
+  - Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
+
+description: |
+  The NAND flash controller node should be defined under the EBI bus (see
+  Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt).
+  One or several NAND devices can be defined under this NAND controller.
+  The NAND controller might be connected to an ECC engine.
+
+properties:
+  compatible:
+    enum:
+      - atmel,at91rm9200-nand-controller
+      - atmel,at91sam9260-nand-controller
+      - atmel,at91sam9261-nand-controller
+      - atmel,at91sam9g45-nand-controller
+      - atmel,sama5d3-nand-controller
+      - microchip,sam9x60-nand-controller
+
+  ranges:
+    description: empty ranges property to forward EBI ranges definitions.
+
+  ecc-engine:
+    description:
+      phandle to the PMECC block. Only meaningful if the SoC embeds a PMECC
+      engine.
+
+  "#address-cells":
+    const: 2
+
+  "#size-cells":
+    const: 1
+
+  atmel,nfc-io:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the NFC IO block. Only applicable for atmel,sama5d3-nand-controller
+
+  atmel,nfc-sram:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the NFC SRAM block. Only applicable for atmel,sama5d3-nand-controller
+
+required:
+  - compatible
+  - ranges
+  - "#address-cells"
+  - "#size-cells"
+
+patternProperties:
+  "^nand@[a-f0-9]$":
+    type: object
+    $ref: raw-nand-chip.yaml#
+    description:
+      NAND chip bindings.
+
+    additionalProperties: false
+
+    properties:
+      reg:
+        items:
+          - items:
+              - description: describes the CS lines assigned to the NAND device.
+              - description: the base offset of the memory region assigned to this device (always 0)
+              - description: the memory region size (always 0x800000)
+      rb-gpios:
+        description:
+          the GPIO(s) used to check the Ready/Busy status of the NAND.
+
+      cs-gpios:
+        description:
+          the GPIO(s) used to control the CS line.
+
+      det-gpios:
+        description:
+          the GPIO used to detect if a Smartmedia Card is present.
+
+      atmel,rb:
+        description: |
+          an integer identifying the native Ready/Busy pin.
+        $ref: /schemas/types.yaml#/definitions/uint32
+
+      nand-ecc-step-size:
+        const: 512
+
+      nand-ecc-strength:
+        enum: [2, 4, 8]
+
+      nand-ecc-mode:
+        enum: [soft, hw]
+
+      nand-bus-width:
+        const: 8
+
+      nand-on-flash-bbt: true
+
+      partitions:
+        $ref: /schemas/mtd/partitions/partitions.yaml
+
+      label:
+        description: Name or Label of the device
+
+    allOf:
+      - if:
+          properties:
+            compatible:
+              contains:
+                const: atmel,sama5d3-nand-controller
+        then:
+          properties:
+            "atmel,rb":
+              description: an integer identifying the native Ready/Busy pin.
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    nfc_io: nfc-io at 70000000 {
+        compatible = "atmel,sama5d3-nfc-io", "syscon";
+        reg = <0x70000000 0x8000000>;
+    };
+
+    nfc_sram: sram at 200000 {
+        compatible = "mmio-sram";
+        no-memory-wc;
+        reg = <0x200000 0x2400>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges = <0 0x200000 0x2400>;
+    };
+
+    pmecc: ecc-engine at ffffc070 {
+        compatible = "atmel,at91sam9g45-pmecc";
+        reg = <0xffffc070 0x490>,
+              <0xffffc500 0x100>;
+    };
+
+    ebi at 10000000 {
+        compatible = "atmel,sama5d3-ebi";
+        #address-cells = <2>;
+        #size-cells = <1>;
+        atmel,smc = <&hsmc>;
+        reg = <0x10000000 0x10000000
+               0x40000000 0x30000000>;
+        ranges = <0x0 0x0 0x10000000 0x10000000
+                  0x1 0x0 0x40000000 0x10000000
+                  0x2 0x0 0x50000000 0x10000000
+                  0x3 0x0 0x60000000 0x10000000>;
+        clocks = <&mck>;
+
+        nand_controller: nand-controller {
+            compatible = "atmel,sama5d3-nand-controller";
+            atmel,nfc-sram = <&nfc_sram>;
+            atmel,nfc-io = <&nfc_io>;
+            ecc-engine = <&pmecc>;
+            #address-cells = <2>;
+            #size-cells = <1>;
+            ranges;
+
+            nand at 3 {
+                reg = <0x3 0x0 0x800000>;
+                atmel,rb = <0>;
+                /*
+                 * Put generic NAND/MTD properties and
+                 * subnodes here.
+                 */
+            };
+        };
+    };
-- 
2.34.1



From balamanikandan.gunasundar at microchip.com  Tue Mar 11 05:28:46 2025
From: balamanikandan.gunasundar at microchip.com (Balamanikandan Gunasundar)
Date: Tue, 11 Mar 2025 17:58:46 +0530
Subject: [PATCH v2 2/3] dt-bindings: mtd: microchip-nand: add atmel pmecc
In-Reply-To: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
Message-ID: <20250311122847.90081-3-balamanikandan.gunasundar@microchip.com>

Add bindings for programmable multibit error correction code controller
(PMECC).

Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
---

Changes in v2:
- Rename filename to match compatible string
- Add constraints for sam9x7
- Droped unused dt labels 

.../devicetree/bindings/mtd/atmel-nand.txt    | 61 -----------------
 .../bindings/mtd/microchip,pmecc.yaml         | 67 +++++++++++++++++++
 2 files changed, 67 insertions(+), 61 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml

diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index dbbc17a866f2..1934614a9298 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -1,64 +1,3 @@
-* ECC engine (PMECC) bindings:
-
-Required properties:
-- compatible: should be one of the following
-	"atmel,at91sam9g45-pmecc"
-	"atmel,sama5d4-pmecc"
-	"atmel,sama5d2-pmecc"
-	"microchip,sam9x60-pmecc"
-	"microchip,sam9x7-pmecc", "atmel,at91sam9g45-pmecc"
-- reg: should contain 2 register ranges. The first one is pointing to the PMECC
-       block, and the second one to the PMECC_ERRLOC block.
-
-Example:
-
-	nfc_io: nfc-io at 70000000 {
-		compatible = "atmel,sama5d3-nfc-io", "syscon";
-		reg = <0x70000000 0x8000000>;
-	};
-
-	pmecc: ecc-engine at ffffc070 {
-		compatible = "atmel,at91sam9g45-pmecc";
-                reg = <0xffffc070 0x490>,
-                      <0xffffc500 0x100>;
-	};
-
-	ebi: ebi at 10000000 {
-		compatible = "atmel,sama5d3-ebi";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		atmel,smc = <&hsmc>;
-		reg = <0x10000000 0x10000000
-		       0x40000000 0x30000000>;
-		ranges = <0x0 0x0 0x10000000 0x10000000
-			  0x1 0x0 0x40000000 0x10000000
-			  0x2 0x0 0x50000000 0x10000000
-			  0x3 0x0 0x60000000 0x10000000>;
-		clocks = <&mck>;
-
-                nand_controller: nand-controller {
-			compatible = "atmel,sama5d3-nand-controller";
-			atmel,nfc-sram = <&nfc_sram>;
-			atmel,nfc-io = <&nfc_io>;
-			ecc-engine = <&pmecc>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges;
-
-			nand at 3 {
-				reg = <0x3 0x0 0x800000>;
-				atmel,rb = <0>;
-
-				/*
-				 * Put generic NAND/MTD properties and
-				 * subnodes here.
-				 */
-			};
-		};
-	};
-
------------------------------------------------------------------------
-
 Deprecated bindings (should not be used in new device trees):
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml b/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml
new file mode 100644
index 000000000000..98260a691a2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/microchip,pmecc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip pmecc controller
+
+maintainers:
+  - Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
+
+description: |
+  Bindings for microchip Programmable Multibit Error Correction Code
+  Controller (PMECC). pmecc is a programmable BCH encoder/decoder. This
+  block is passed as the value to the "ecc-engine" property of microchip
+  nand flash controller node.
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - atmel,at91sam9g45-pmecc
+          - atmel,sama5d2-pmecc
+          - atmel,sama5d4-pmecc
+          - microchip,sam9x60-pmecc
+          - microchip,sam9x7-pmecc
+      - items:
+          - const: microchip,sam9x7-pmecc
+          - const: atmel,at91sam9g45-pmecc
+      - items:
+          - const: microchip,sam9x60-pmecc
+          - const: atmel,at91sam9g45-pmecc
+
+  reg:
+    items:
+      - description: Base address and size of PMECC controller registers
+      - description: Base address and size of PMECC_ERRLOC controller
+
+  clocks:
+    description: The clock source for pmecc controller
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: microchip,sam9x7-pmecc
+    then:
+      properties:
+        clocks:
+          description: The clock source for pmecc controller
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    ecc-engine at ffffc070 {
+        compatible = "microchip,sam9x7-pmecc";
+        reg = <0xffffe000 0x300>,
+              <0xffffe600 0x100>;
+        clocks = <&pmc 2 48>;
+    };
-- 
2.34.1



From balamanikandan.gunasundar at microchip.com  Tue Mar 11 05:28:47 2025
From: balamanikandan.gunasundar at microchip.com (Balamanikandan Gunasundar)
Date: Tue, 11 Mar 2025 17:58:47 +0530
Subject: [PATCH v2 3/3] dt-bindings: mtd: atmel-nand: add legacy nand controllers
In-Reply-To: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
Message-ID: <20250311122847.90081-4-balamanikandan.gunasundar@microchip.com>

Add support for atmel legacy nand controllers. These bindings should not be
used with the new device trees.

Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
---

Changes in v2:

- Filename matching the compatibles
- Remove "bindings" from the subject
- Remove "deprecated" as these are the only bindings available for the devices
- Add missing constraints.
- Add default for nand-ecc-mode
- Add 32 in pmecc-cap for sama5d2
- Add default for sector-size, pmecc-lookup-table-offset, nand-bus-width

 .../devicetree/bindings/mtd/atmel-nand.txt    | 116 -------------
 .../devicetree/bindings/mtd/atmel-nand.yaml   | 163 ++++++++++++++++++
 2 files changed, 163 insertions(+), 116 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.yaml

diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
deleted file mode 100644
index 1934614a9298..000000000000
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-Deprecated bindings (should not be used in new device trees):
-
-Required properties:
-- compatible: The possible values are:
-	"atmel,at91rm9200-nand"
-	"atmel,sama5d2-nand"
-	"atmel,sama5d4-nand"
-- reg : should specify localbus address and size used for the chip,
-	and hardware ECC controller if available.
-	If the hardware ECC is PMECC, it should contain address and size for
-	PMECC and PMECC Error Location controller.
-	The PMECC lookup table address and size in ROM is optional. If not
-	specified, driver will build it in runtime.
-- atmel,nand-addr-offset : offset for the address latch.
-- atmel,nand-cmd-offset : offset for the command latch.
-- #address-cells, #size-cells : Must be present if the device has sub-nodes
-  representing partitions.
-
-- gpios : specifies the gpio pins to control the NAND device. detect is an
-  optional gpio and may be set to 0 if not present.
-
-Optional properties:
-- atmel,nand-has-dma : boolean to support dma transfer for nand read/write.
-- nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
-  Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
-  "soft_bch".
-- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware,
-  capable of BCH encoding and decoding, on devices where it is present.
-- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
-  Controller. Supported values are: 2, 4, 8, 12, 24. If the compatible string
-  is "atmel,sama5d2-nand", 32 is also valid.
-- atmel,pmecc-sector-size : sector size for ECC computation. Supported values
-  are: 512, 1024.
-- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
-  for different sector size. First one is for sector size 512, the next is for
-  sector size 1024. If not specified, driver will build the table in runtime.
-- nand-bus-width : 8 or 16 bus width if not present 8
-- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
-
-Nand Flash Controller(NFC) is an optional sub-node
-Required properties:
-- compatible : "atmel,sama5d3-nfc".
-- reg : should specify the address and size used for NFC command registers,
-        NFC registers and NFC SRAM. NFC SRAM address and size can be absent
-        if don't want to use it.
-- clocks: phandle to the peripheral clock
-Optional properties:
-- atmel,write-by-sram: boolean to enable NFC write by SRAM.
-
-Examples:
-nand0: nand at 40000000,0 {
-	compatible = "atmel,at91rm9200-nand";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	reg = <0x40000000 0x10000000
-	       0xffffe800 0x200
-	      >;
-	atmel,nand-addr-offset = <21>;	/* ale */
-	atmel,nand-cmd-offset = <22>;	/* cle */
-	nand-on-flash-bbt;
-	nand-ecc-mode = "soft";
-	gpios = <&pioC 13 0	/* rdy */
-		 &pioC 14 0 	/* nce */
-		 0		/* cd */
-		>;
-	partition at 0 {
-		...
-	};
-};
-
-/* for PMECC supported chips */
-nand0: nand at 40000000 {
-	compatible = "atmel,at91rm9200-nand";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	reg = < 0x40000000 0x10000000	/* bus addr & size */
-		0xffffe000 0x00000600	/* PMECC addr & size */
-		0xffffe600 0x00000200	/* PMECC ERRLOC addr & size */
-		0x00100000 0x00100000	/* ROM addr & size */
-		>;
-	atmel,nand-addr-offset = <21>;	/* ale */
-	atmel,nand-cmd-offset = <22>;	/* cle */
-	nand-on-flash-bbt;
-	nand-ecc-mode = "hw";
-	atmel,has-pmecc;	/* enable PMECC */
-	atmel,pmecc-cap = <2>;
-	atmel,pmecc-sector-size = <512>;
-	atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
-	gpios = <&pioD 5 0	/* rdy */
-		 &pioD 4 0	/* nce */
-		 0		/* cd */
-		>;
-	partition at 0 {
-		...
-	};
-};
-
-/* for NFC supported chips */
-nand0: nand at 40000000 {
-	compatible = "atmel,at91rm9200-nand";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	ranges;
-        ...
-        nfc at 70000000 {
-		compatible = "atmel,sama5d3-nfc";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		clocks = <&hsmc_clk>
-		reg = <
-			0x70000000 0x10000000	/* NFC Command Registers */
-			0xffffc000 0x00000070	/* NFC HSMC regs */
-			0x00200000 0x00100000	/* NFC SRAM banks */
-		>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.yaml b/Documentation/devicetree/bindings/mtd/atmel-nand.yaml
new file mode 100644
index 000000000000..8afc4a144caf
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.yaml
@@ -0,0 +1,163 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/atmel-nand.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Atmel NAND flash controller
+
+maintainers:
+  - Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
+
+description: |
+  Atmel nand flash controller. This should not be used for new device
+  trees. For the latest controllers refer microchip,nand-controller.yaml
+
+properties:
+  compatible:
+    enum:
+      - atmel,at91rm9200-nand
+      - atmel,sama5d2-nand
+      - atmel,sama5d4-nand
+
+  reg:
+    description:
+      The localbus address and size used for the chip, and hardware ECC
+      controller if available. If the hardware ECC is PMECC, it should
+      contain address and size for PMECC and PMECC Error Location
+      controller. The PMECC lookup table address and size in ROM is
+      optional. If not specified, driver will build it in runtime.
+
+  atmel,nand-addr-offset:
+    description:
+      offset for the address latch.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 31
+
+  atmel,nand-cmd-offset:
+    description:
+      offset for the command latch.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 31
+
+  '#address-cells': true
+
+  '#size-cells': true
+
+  gpios:
+    description:
+      specifies the gpio pins to control the NAND device. detect is an
+      optional gpio and may be set to 0 if not present.
+    minItems: 1
+    maxItems: 3
+
+  atmel,nand-has-dma:
+    description:
+      support dma transfer for nand read/write.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  atmel,has-pmecc:
+    description:
+      enable Programmable Multibit ECC hardware, capable of BCH encoding
+      and decoding, on devices where it is present.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  nand-on-flash-bbt:
+    description:
+      enable on flash bbt option if not present false
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  nand-ecc-mode:
+    description:
+      operation mode of the NAND ecc
+    enum:
+      [none, soft, hw, hw_syndrome, hw_oob_first, soft_bch]
+    default: soft
+    $ref: /schemas/types.yaml#/definitions/string
+
+
+  atmel,pmecc-cap:
+    description:
+      error correct capability for Programmable Multibit ECC Controller.
+    enum:
+      [2, 4, 8, 12, 24, 32]
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  atmel,pmecc-sector-size:
+    description:
+      sector size for ECC computation.
+    enum:
+      [512, 1024]
+    default: 512
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+
+  atmel,pmecc-lookup-table-offset:
+    description:
+      Two offsets of lookup table in ROM for different sector size. First
+      one is for sector size 512, the next is for sector size 1024. If not
+      specified, driver will build the table in runtime.
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    default: 512
+
+  nand-bus-width:
+    description:
+      nand bus width
+    enum:
+      [8, 16]
+    default: 8
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+required:
+  - compatible
+  - reg
+  - atmel,nand-addr-offset
+  - atmel,nand-cmd-offset
+  - "#address-cells"
+  - "#size-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    nand at 40000000,0 {
+        compatible = "atmel,at91rm9200-nand";
+        #address-cells = <1>;
+        #size-cells = <1>;
+        reg = <0x40000000 0x10000000
+               0xffffe800 0x200>;
+        atmel,nand-addr-offset = <21>;	/* ale */
+        atmel,nand-cmd-offset = <22>;	/* cle */
+        nand-on-flash-bbt;
+        nand-ecc-mode = "soft";
+        gpios = <&pioC 13 0	/* rdy */
+                 &pioC 14 0 /* nce */
+                 0		/* cd */
+                >;
+    };
+  - |
+    /* for PMECC supported chips */
+    nand1 at 40000000 {
+        compatible = "atmel,at91rm9200-nand";
+        #address-cells = <1>;
+        #size-cells = <1>;
+        reg = <0x40000000 0x10000000	/* bus addr & size */
+               0xffffe000 0x00000600	/* PMECC addr & size */
+               0xffffe600 0x00000200	/* PMECC ERRLOC addr & size */
+               0x00100000 0x00100000>;	/* ROM addr & size */
+
+        atmel,nand-addr-offset = <21>;	/* ale */
+        atmel,nand-cmd-offset = <22>;	/* cle */
+        nand-on-flash-bbt;
+        nand-ecc-mode = "hw";
+        atmel,has-pmecc;	/* enable PMECC */
+        atmel,pmecc-cap = <2>;
+        atmel,pmecc-sector-size = <512>;
+        atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
+        gpios = <&pioD 5 0	/* rdy */
+                 &pioD 4 0	/* nce */
+                 0		/* cd */
+                >;
+    };
-- 
2.34.1



From oleg at redhat.com  Tue Mar 11 05:32:42 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Tue, 11 Mar 2025 13:32:42 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes:
 uprobe_write_opcode() rewrite
In-Reply-To: <79ec5aa9-1937-436e-8cf4-436746142f7b@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
 <20250310170320.GC26382@redhat.com>
 <79ec5aa9-1937-436e-8cf4-436746142f7b@redhat.com>
Message-ID: <20250311123241.GB3493@redhat.com>

On 03/11, David Hildenbrand wrote:
>
> Regarding both questions, the code is fairly racy. Nothing would stop user
> space from (a) modifying that memory

Yes, but we don't really care. uprobes.c assumes that user-space won't play
with the probed memory.

Note that if is_register is false, then vma can be even writable. Hmm, why?
Perhaps valid_vma() should ignore is_register and nack VM_MAYWRITE ? But
this doesn't really matter, say, gdb can change this memory anyway. Again,
we don't really care.

> >do something like
> >
> >	/* Walk the page tables again, to perform the actual update. */
> >	ret = -EAGAIN;
> >	folio = folio_walk_start(&fw, vma, vaddr, 0);
> >	if (folio) {
> >		if (fw.page == page) {
> >			WARN_ON(is_register && !folio_test_anon(folio));
>
> Yes, that would work (we could leave the WARN_ON in __uprobe_write_opcode),
> but I am not sure if the end result is better better. No strong opinion on
> the details though.

Will, this way __uprobe_write_opcode() will look a little bit simpler...

But I won't insist, please do what you think is better.

Oleg.



From alyssa at rosenzweig.io  Tue Mar 11 05:46:30 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Tue, 11 Mar 2025 08:46:30 -0400
Subject: [PATCH] drm: Add UAPI for the Asahi driver
In-Reply-To: <CAF6AEGukrBzwwdDWX5jUXDKqj7+kn7LBRy6NocE4=bw1D9WjcQ@mail.gmail.com>
References: <20250310-agx-uapi-v1-1-86c80905004e@rosenzweig.io>
 <CAF6AEGukrBzwwdDWX5jUXDKqj7+kn7LBRy6NocE4=bw1D9WjcQ@mail.gmail.com>
Message-ID: <Z9Awpj5Avh0rx_fq@blossom>

> > +/**
> > + * struct drm_asahi_gem_bind - Arguments passed to
> > + * DRM_IOCTL_ASAHI_GEM_BIND
> > + */
> > +struct drm_asahi_gem_bind {
> > +       /** @op: Bind operation (enum drm_asahi_bind_op) */
> > +       __u32 op;
> > +
> > +       /** @flags: One or more of ASAHI_BIND_* (BIND only) */
> > +       __u32 flags;
> > +
> > +       /** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
> > +       __u32 handle;
> > +
> > +       /** @vm_id: The ID of the VM to operate on */
> > +       __u32 vm_id;
> > +
> > +       /** @offset: Offset into the object (BIND only) */
> > +       __u64 offset;
> > +
> > +       /**
> > +        * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
> > +        */
> > +       __u64 range;
> > +
> > +       /** @addr: Address to bind to (BIND or UNBIND only) */
> > +       __u64 addr;
> > +};
> 
> No in/out syncobj/fences?  This seems to diverge from xe/nouveau/panthor..

Async vm_bind is useful mainly as an optimization, it's not (as far as I
know) required for correctness - you can always wait/signal from a
userspace submit thread with sync vm_bind. It's my understanding (from
when I chatted with Faith about this when bringing up sparse) that this
is how sparse was implemented historically and maybe still is on
Windows?

> > +/**
> > + * enum drm_asahi_sync_type - Sync item type
> > + */
> > +enum drm_asahi_sync_type {
> > +       /** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
> > +       DRM_ASAHI_SYNC_SYNCOBJ = 0,
> > +
> > +       /** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
> > +       DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
> > +};
> 
> IMHO it would still be worthwhile to also support fence fd's, since it
> would avoid a couple extra ioctls to convert btwn fence fds and
> syncobj for virtgpu native context..

Ditto for this as an optimization. Both of these can be added in a
straightforward backwards-compat way later, so I'm inclined to not add
any extra functionality beyond what we already have (and know works),
rather than commit prematurely to new features and risk getting
something wrong.

(and then it means more rust bindings...)


From alyssa at rosenzweig.io  Tue Mar 11 05:47:52 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Tue, 11 Mar 2025 08:47:52 -0400
Subject: [PATCH v3 2/3] spmi: add a spmi driver for Apple SoC
In-Reply-To: <20250310-spmi-v3-2-92a82e7d9f0d@gmail.com>
References: <20250310-spmi-v3-0-92a82e7d9f0d@gmail.com>
 <20250310-spmi-v3-2-92a82e7d9f0d@gmail.com>
Message-ID: <Z9Aw-MTUdldYRrP5@blossom>

Reviewed-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>

Le Mon , Mar 10, 2025 at 11:07:59PM +0100, Sasha Finkelstein via B4 Relay a ?crit :
> From: Jean-Francois Bortolotti <jeff at borto.fr>
> 
> The connected PMU contains several useful nvmem cells such as RTC offset,
> boot failure counters, reboot/shutdown selector, and a few others.
> In addition M3+ machines have their USB-PD controller connected via SPMI.
> 
> Signed-off-by: Jean-Francois Bortolotti <jeff at borto.fr>
> Reviewed-by: Sven Peter <sven at svenpeter.dev>
> Co-developed-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel at gmail.com>
> ---
>  MAINTAINERS                          |   1 +
>  drivers/spmi/Kconfig                 |   8 ++
>  drivers/spmi/Makefile                |   1 +
>  drivers/spmi/spmi-apple-controller.c | 168 +++++++++++++++++++++++++++++++++++
>  4 files changed, 178 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 271ff8110df83c2d4fe7fbbfffc0a72259460bc5..9006695261d29fbc1e15659c2b43d7afeee0b656 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2254,6 +2254,7 @@ F:	drivers/nvmem/apple-efuses.c
>  F:	drivers/pinctrl/pinctrl-apple-gpio.c
>  F:	drivers/pwm/pwm-apple.c
>  F:	drivers/soc/apple/*
> +F:	drivers/spmi/spmi-apple-controller.c
>  F:	drivers/watchdog/apple_wdt.c
>  F:	include/dt-bindings/interrupt-controller/apple-aic.h
>  F:	include/dt-bindings/pinctrl/apple.h
> diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
> index 73780204631463631cabcbad5bf83e8dbbee94ce..9005fa91d9f4e541403ccc7bf84e0592402ac41e 100644
> --- a/drivers/spmi/Kconfig
> +++ b/drivers/spmi/Kconfig
> @@ -11,6 +11,14 @@ menuconfig SPMI
>  
>  if SPMI
>  
> +config SPMI_APPLE
> +	tristate "Apple SoC SPMI Controller platform driver"
> +	depends on ARCH_APPLE || COMPILE_TEST
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  SPMI controller present on many Apple SoCs, including the
> +	  t8103 (M1) and t600x (M1 Pro/Max).
> +
>  config SPMI_HISI3670
>  	tristate "Hisilicon 3670 SPMI Controller"
>  	select IRQ_DOMAIN_HIERARCHY
> diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
> index 7f152167bb05b2c24a0f9669f60278152898eebb..38ac635645ba65aa46cb5e8a50072ed9771e229b 100644
> --- a/drivers/spmi/Makefile
> +++ b/drivers/spmi/Makefile
> @@ -4,6 +4,7 @@
>  #
>  obj-$(CONFIG_SPMI)	+= spmi.o spmi-devres.o
>  
> +obj-$(CONFIG_SPMI_APPLE)	+= spmi-apple-controller.o
>  obj-$(CONFIG_SPMI_HISI3670)	+= hisi-spmi-controller.o
>  obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
>  obj-$(CONFIG_SPMI_MTK_PMIF)	+= spmi-mtk-pmif.o
> diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..697b3e8bb023566f17911fc222666d84f5e14c91
> --- /dev/null
> +++ b/drivers/spmi/spmi-apple-controller.c
> @@ -0,0 +1,168 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Apple SoC SPMI device driver
> + *
> + * Copyright The Asahi Linux Contributors
> + *
> + * Inspired by:
> + *		OpenBSD support Copyright (c) 2021 Mark Kettenis <kettenis at openbsd.org>
> + *		Correllium support Copyright (C) 2021 Corellium LLC
> + *		hisi-spmi-controller.c
> + *		spmi-pmic-arb.c Copyright (c) 2021, The Linux Foundation.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +#include <linux/spmi.h>
> +
> +/* SPMI Controller Registers */
> +#define SPMI_STATUS_REG 0
> +#define SPMI_CMD_REG 0x4
> +#define SPMI_RSP_REG 0x8
> +
> +#define SPMI_RX_FIFO_EMPTY BIT(24)
> +
> +#define REG_POLL_INTERVAL_US 10000
> +#define REG_POLL_TIMEOUT_US (REG_POLL_INTERVAL_US * 5)
> +
> +struct apple_spmi {
> +	void __iomem *regs;
> +};
> +
> +#define poll_reg(spmi, reg, val, cond) \
> +	readl_poll_timeout((spmi)->regs + (reg), (val), (cond), \
> +			   REG_POLL_INTERVAL_US, REG_POLL_TIMEOUT_US)
> +
> +static inline u32 apple_spmi_pack_cmd(u8 opc, u8 sid, u16 saddr, size_t len)
> +{
> +	return opc | sid << 8 | saddr << 16 | (len - 1) | (1 << 15);
> +}
> +
> +/* Wait for Rx FIFO to have something */
> +static int apple_spmi_wait_rx_not_empty(struct spmi_controller *ctrl)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	int ret;
> +	u32 status;
> +
> +	ret = poll_reg(spmi, SPMI_STATUS_REG, status, !(status & SPMI_RX_FIFO_EMPTY));
> +	if (ret) {
> +		dev_err(&ctrl->dev,
> +			"failed to wait for RX FIFO not empty\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +			 u16 saddr, u8 *buf, size_t len)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
> +	u32 rsp;
> +	size_t len_read = 0;
> +	u8 i;
> +	int ret;
> +
> +	writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
> +
> +	ret = apple_spmi_wait_rx_not_empty(ctrl);
> +	if (ret)
> +		return ret;
> +
> +	/* Discard SPMI reply status */
> +	readl(spmi->regs + SPMI_RSP_REG);
> +
> +	/* Read SPMI data reply */
> +	while (len_read < len) {
> +		rsp = readl(spmi->regs + SPMI_RSP_REG);
> +		i = 0;
> +		while ((len_read < len) && (i < 4)) {
> +			buf[len_read++] = ((0xff << (8 * i)) & rsp) >> (8 * i);
> +			i += 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
> +			  u16 saddr, const u8 *buf, size_t len)
> +{
> +	struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl);
> +	u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len);
> +	size_t i = 0, j;
> +	int ret;
> +
> +	writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
> +
> +	while (i < len) {
> +		j = 0;
> +		spmi_cmd = 0;
> +		while ((j < 4) & (i < len))
> +			spmi_cmd |= buf[i++] << (j++ * 8);
> +
> +		writel(spmi_cmd, spmi->regs + SPMI_CMD_REG);
> +	}
> +
> +	ret = apple_spmi_wait_rx_not_empty(ctrl);
> +	if (ret)
> +		return ret;
> +
> +	/* Discard */
> +	readl(spmi->regs + SPMI_RSP_REG);
> +
> +	return 0;
> +}
> +
> +static int apple_spmi_probe(struct platform_device *pdev)
> +{
> +	struct apple_spmi *spmi;
> +	struct spmi_controller *ctrl;
> +	int ret;
> +
> +	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*spmi));
> +	if (IS_ERR(ctrl))
> +		return -ENOMEM;
> +
> +	spmi = spmi_controller_get_drvdata(ctrl);
> +
> +	spmi->regs = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(spmi->regs))
> +		return PTR_ERR(spmi->regs);
> +
> +	ctrl->dev.of_node = pdev->dev.of_node;
> +
> +	ctrl->read_cmd = spmi_read_cmd;
> +	ctrl->write_cmd = spmi_write_cmd;
> +
> +	ret = devm_spmi_controller_add(&pdev->dev, ctrl);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "spmi_controller_add failed\n");
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id apple_spmi_match_table[] = {
> +	{ .compatible = "apple,spmi", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, apple_spmi_match_table);
> +
> +static struct platform_driver apple_spmi_driver = {
> +	.probe		= apple_spmi_probe,
> +	.driver		= {
> +		.name	= "apple-spmi",
> +		.of_match_table = apple_spmi_match_table,
> +	},
> +};
> +module_platform_driver(apple_spmi_driver);
> +
> +MODULE_AUTHOR("Jean-Francois Bortolotti <jeff at borto.fr>");
> +MODULE_DESCRIPTION("Apple SoC SPMI driver");
> +MODULE_LICENSE("GPL");
> 
> -- 
> 2.48.1
> 
> 


From robin.murphy at arm.com  Tue Mar 11 05:48:32 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 11 Mar 2025 12:48:32 +0000
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <Z89P461+Y6kQDOCX@vaman>
References: <cover.1740762136.git.robin.murphy@arm.com>
 <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
 <Z89P461+Y6kQDOCX@vaman>
Message-ID: <072d1d3a-2aeb-4ab0-9db1-476835a1131e@arm.com>

On 2025-03-10 8:47 pm, Vinod Koul wrote:
> On 28-02-25, 17:26, Robin Murphy wrote:
> 
>> +static u32 d350_get_residue(struct d350_chan *dch)
>> +{
>> +	u32 res, xsize, xsizehi, hi_new;
>> +
>> +	hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
>> +	do {
>> +		xsizehi = hi_new;
>> +		xsize = readl_relaxed(dch->base + CH_XSIZE);
>> +		hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
>> +	} while (xsizehi != hi_new);
> 
> This can go forever, lets have some limits to this loop please

Sure, in practice I doubt we're ever going to be continually preempted 
faster than the controller can move another 64KB of data, but I concur 
there's no harm in making the code easier to reason about at a glance 
either.

>> +static int d350_alloc_chan_resources(struct dma_chan *chan)
>> +{
>> +	struct d350_chan *dch = to_d350_chan(chan);
>> +	int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED,
>> +			      dev_name(&dch->vc.chan.dev->device), dch);
> 
> This is interesting, any reason why the irq is allocated here? Would it
> be not better to do that in probe...

Well, I'd say technically the IRQ is a channel resource, and quite a few 
other drivers do the same... Here it's mostly so I can get the channel 
name - so the IRQs are nice and identifiable in /proc/interrupts - 
easily without making a big mess in probe, since the names don't exist 
until after the device is registered.

Thanks,
Robin.


From michal.kubiak at intel.com  Tue Mar 11 05:17:52 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Tue, 11 Mar 2025 13:17:52 +0100
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <20250311053830.1516523-2-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
Message-ID: <Z9Ap8BT2LZFTlm0p@localhost.localdomain>

On Tue, Mar 11, 2025 at 01:38:17PM +0800, Wei Fang wrote:
> Some NETC functionality is controlled using control messages sent to the
> hardware using BD ring interface with 32B descriptor similar to transmit
> BD ring used on ENETC. This BD ring interface is referred to as command
> BD ring. It is used to configure functionality where the underlying
> resources may be shared between different entities or being too large to
> configure using direct registers. Therefore, a messaging protocol called
> NETC Table Management Protocol (NTMP) is provided for exchanging
> configuration and management information between the software and the
> hardware using the command BD ring interface.
> 
> For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
> with LS1028A, because the message formats have been changed. Therefore,
> add the netc-lib driver to support NTMP 2.0 to operate various tables.
> Note that, only MAC address filter table and RSS table are supported at
> the moment. More tables will be supported in subsequent patches.
> 
> It is worth mentioning that the purpose of the netc-lib driver is to
> provide some NTMP-based generic interfaces for ENETC and NETC Switch
> drivers. Currently, it only supports the configurations of some tables.
> Interfaces such as tc flower and debugfs will be added in the future.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>

The patch looks OK to me.

Thanks,
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>


From lorenzo at kernel.org  Tue Mar 11 05:18:32 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:32 +0100
Subject: [PATCH net-next 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
Message-ID: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>

Introduce missing metadata support for some xdp drivers setting metadata
size building the skb from xdp_buff.
Please note most of the drivers are just compile tested.

---
Lorenzo Bianconi (7):
      net: mvneta: Add metadata support for xdp mode
      net: mvpp2: Add metadata support for xdp mode
      net: netsec: Add metadata support for xdp mode
      net: octeontx2: Add metadata support for xdp mode
      net: ethernet: mediatek: Add metadata support for xdp mode
      net: mana: Add metadata support for xdp mode
      net: ti: cpsw: Add metadata support for xdp mode

 drivers/net/ethernet/marvell/mvneta.c                  |  5 ++++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c        |  8 ++++++--
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 13 +++++++++----
 drivers/net/ethernet/mediatek/mtk_eth_soc.c            |  7 +++++--
 drivers/net/ethernet/microsoft/mana/mana_bpf.c         |  2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c          |  4 ++++
 drivers/net/ethernet/socionext/netsec.c                |  7 +++++--
 drivers/net/ethernet/ti/cpsw.c                         |  6 +++++-
 drivers/net/ethernet/ti/cpsw_new.c                     |  6 +++++-
 9 files changed, 44 insertions(+), 14 deletions(-)
---
base-commit: 8ef890df4031121a94407c84659125cbccd3fdbe
change-id: 20250310-mvneta-xdp-meta-3e0da8ef4498

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From lorenzo at kernel.org  Tue Mar 11 05:18:33 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 13:18:33 +0100
Subject: [PATCH net-next 1/7] net: mvneta: Add metadata support for xdp
 mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <20250311-mvneta-xdp-meta-v1-1-36cf1c99790e@kernel.org>

Set metadata size building the skb from xdp_buff in mvneta driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/mvneta.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 44b18c57390927e37eac267632cace656bb5526e..147571fdada378e430fd96f2fb4a7e7870b784a2 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2342,7 +2342,7 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,
 	prefetch(data);
 	xdp_buff_clear_frags_flag(xdp);
 	xdp_prepare_buff(xdp, data, pp->rx_offset_correction + MVNETA_MH_SIZE,
-			 data_len, false);
+			 data_len, true);
 }
 
 static void
@@ -2396,6 +2396,7 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
 		      struct xdp_buff *xdp, u32 desc_status)
 {
 	struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
+	u32 metasize = xdp->data - xdp->data_meta;
 	struct sk_buff *skb;
 	u8 num_frags;
 
@@ -2410,6 +2411,8 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
 
 	skb_reserve(skb, xdp->data - xdp->data_hard_start);
 	skb_put(skb, xdp->data_end - xdp->data);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->ip_summed = mvneta_rx_csum(pp, desc_status);
 
 	if (unlikely(xdp_buff_has_frags(xdp)))

-- 
2.48.1



From will at kernel.org  Tue Mar 11 05:54:15 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 12:54:15 +0000
Subject: [PATCH] arm64: reserve [_text, _stext) virtual address range
In-Reply-To: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>
References: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>
Message-ID: <20250311125414.GA4601@willie-the-truck>

[+Ard]

On Mon, Mar 10, 2025 at 01:05:04PM -0700, Omar Sandoval wrote:
> From: Omar Sandoval <osandov at fb.com>
> 
> Since the referenced fixes commit, the kernel's .text section is only
> mapped starting from _stext; the region [_text, _stext) is omitted. As a
> result, other vmalloc/vmap allocations may use the virtual addresses
> nominally in the range [_text, _stext). This address reuse confuses
> multiple things:
> 
> 1. crash_prepare_elf64_headers() sets up a segment in /proc/vmcore
>    mapping the entire range [_text, _end) to
>    [__pa_symbol(_text), __pa_symbol(_end)). Reading an address in
>    [_text, _stext) from /proc/vmcore therefore gives the incorrect
>    result.
> 2. Tools doing symbolization (either by reading /proc/kallsyms or based
>    on the vmlinux ELF file) will incorrectly identify vmalloc/vmap
>    allocations in [_text, _stext) as kernel symbols.
> 
> In practice, both of these issues affect the drgn debugger.
> Specifically, there were cases where the vmap IRQ stacks for some CPUs
> were allocated in [_text, _stext). As a result, drgn could not get the
> stack trace for a crash in an IRQ handler because the core dump
> contained invalid data for the IRQ stack address. The stack addresses
> were also symbolized as being in the _text symbol.
> 
> Fix this by creating an unmapped vm_area to cover [_text, _stext). This
> prevents other allocations from using it while still achieving the
> original goal of not mapping unpredictable data.
> 
> Fixes: e2a073dde921 ("arm64: omit [_text, _stext) from permanent kernel mapping")
> Cc: stable at vger.kernel.org
> Signed-off-by: Omar Sandoval <osandov at fb.com>
> ---
> Based on v6.14-rc6.
> 
> Thanks!
> 
>  arch/arm64/mm/mmu.c | 26 +++++++++++++++++---------
>  1 file changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b4df5bc5b1b8..88595ea12f39 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -703,10 +703,14 @@ static void __init declare_vma(struct vm_struct *vma,
>  			       void *va_start, void *va_end,
>  			       unsigned long vm_flags)
>  {
> -	phys_addr_t pa_start = __pa_symbol(va_start);
> +	phys_addr_t pa_start = 0;
>  	unsigned long size = va_end - va_start;
>  
> -	BUG_ON(!PAGE_ALIGNED(pa_start));
> +	if (vm_flags & VM_MAP) {
> +		pa_start = __pa_symbol(va_start);
> +		BUG_ON(!PAGE_ALIGNED(pa_start));
> +	}
> +
>  	BUG_ON(!PAGE_ALIGNED(size));
>  
>  	if (!(vm_flags & VM_NO_GUARD))
> @@ -715,7 +719,7 @@ static void __init declare_vma(struct vm_struct *vma,
>  	vma->addr	= va_start;
>  	vma->phys_addr	= pa_start;
>  	vma->size	= size;
> -	vma->flags	= VM_MAP | vm_flags;
> +	vma->flags	= vm_flags;
>  	vma->caller	= __builtin_return_address(0);
>  
>  	vm_area_add_early(vma);
> @@ -765,13 +769,17 @@ core_initcall(map_entry_trampoline);
>   */
>  static void __init declare_kernel_vmas(void)
>  {
> -	static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];
> +	static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT + 1];
>  
> -	declare_vma(&vmlinux_seg[0], _stext, _etext, VM_NO_GUARD);
> -	declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
> -	declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
> -	declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
> -	declare_vma(&vmlinux_seg[4], _data, _end, 0);
> +	declare_vma(&vmlinux_seg[0], _text, _stext, VM_NO_GUARD);

Should we also put the memblock reservation back as it was, so that this
region can't be allocated there?

In fact, if we're not allocating from here, why don't we just map it
anyway but without execute permissions?

Will


From purvayeshi550 at gmail.com  Tue Mar 11 05:57:56 2025
From: purvayeshi550 at gmail.com (Purva Yeshi)
Date: Tue, 11 Mar 2025 18:27:56 +0530
Subject: [PATCH] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML schema
Message-ID: <20250311125756.24064-1-purvayeshi550@gmail.com>

Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
YAML schema (`lpc32xx-pwm.yaml`).

Changes:

Add SPDX license identifier `(GPL-2.0-only OR BSD-2-Clause)`.
Define `$id` and `$schema` fields for proper schema validation.
Set `title` to describe the LPC32XX PWM controller.
Add maintainers as per `scripts/get_maintainer.pl` output.
Reference `pwm.yaml#` in `allOf` to inherit common PWM properties.

Define properties:
Restrict `compatible` to `"nxp,lpc3220-pwm"` using `const`.
Limit `reg` to `maxItems: 1` to ensure a single register range.
Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.

Mark `compatible` and `reg` as required properties.
Set `unevaluatedProperties: false` to enforce strict validation.

Validate the YAML schema using dt-validate and yamllint.

Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
---
 .../devicetree/bindings/pwm/lpc32xx-pwm.yaml  | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml

diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
new file mode 100644
index 000000000..3e41cd291
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/nxp,lpc32xx-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPC32XX PWM controller
+
+maintainers:
+  - "Uwe Kleine-K??nig <ukleinek at kernel.org>"
+  - "Vladimir Zapolskiy <vz at mleia.com>"
+  - "Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>"
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    const: nxp,lpc3220-pwm
+
+  reg:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    pwm at 4005c000 {
+        compatible = "nxp,lpc3220-pwm";
+        reg = <0x4005c000 0x4>;
+        #pwm-cells = <3>;
+    };
+  - |
+    pwm at 4005c004 {
+        compatible = "nxp,lpc3220-pwm";
+        reg = <0x4005c004 0x4>;
+        #pwm-cells = <3>;
+    };
-- 
2.34.1



From s-vadapalli at ti.com  Tue Mar 11 06:01:03 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 18:31:03 +0530
Subject: [PATCH net v2] net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
Message-ID: <20250311130103.68971-1-s-vadapalli@ti.com>

From: Vignesh Raghavendra <vigneshr at ti.com>

Registering the interrupts for TX or RX DMA Channels prior to registering
their respective NAPI callbacks can result in a NULL pointer dereference.
This is seen in practice as a random occurrence since it depends on the
randomness associated with the generation of traffic by Linux and the
reception of traffic from the wire.

Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---

Hello,

This patch is based on commit
4d872d51bc9d Merge tag 'x86-urgent-2025-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
of Mainline Linux.

v1 of this patch is at:
https://lore.kernel.org/all/20250311061214.4111634-1-s-vadapalli at ti.com/
Changes since v1:
- Based on the feedback provided by Alexander Sverdlin <alexander.sverdlin at siemens.com>
  the patch has been updated to account for the cleanup path in terms of an imbalance
  between the number of successful netif_napi_add_tx/netif_napi_add calls and the
  number of successful devm_request_irq() calls. In the event of an error, we will
  always have one extra successful netif_napi_add_tx/netif_napi_add that needs to be
  cleaned up before we clean an equal number of netif_napi_add_tx/netif_napi_add and
  devm_request_irq.

Regards,
Siddharth.

 drivers/net/ethernet/ti/am65-cpsw-nuss.c | 28 +++++++++++++-----------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 2806238629f8..b88edf2dd8f4 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2306,14 +2306,18 @@ static void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
 static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 {
 	struct device *dev = common->dev;
+	struct am65_cpsw_tx_chn *tx_chn;
 	int i, ret = 0;
 
 	for (i = 0; i < common->tx_ch_num; i++) {
-		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
+		tx_chn = &common->tx_chns[i];
 
 		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
 		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
 
+		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
+				  am65_cpsw_nuss_tx_poll);
+
 		ret = devm_request_irq(dev, tx_chn->irq,
 				       am65_cpsw_nuss_tx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2323,19 +2327,16 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 				tx_chn->id, tx_chn->irq, ret);
 			goto err;
 		}
-
-		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
-				  am65_cpsw_nuss_tx_poll);
 	}
 
 	return 0;
 
 err:
-	for (--i ; i >= 0 ; i--) {
-		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
-
-		netif_napi_del(&tx_chn->napi_tx);
+	netif_napi_del(&tx_chn->napi_tx);
+	for (--i; i >= 0; i--) {
+		tx_chn = &common->tx_chns[i];
 		devm_free_irq(dev, tx_chn->irq, tx_chn);
+		netif_napi_del(&tx_chn->napi_tx);
 	}
 
 	return ret;
@@ -2569,6 +2570,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			     HRTIMER_MODE_REL_PINNED);
 		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
 
+		netif_napi_add(common->dma_ndev, &flow->napi_rx,
+			       am65_cpsw_nuss_rx_poll);
+
 		ret = devm_request_irq(dev, flow->irq,
 				       am65_cpsw_nuss_rx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2579,9 +2583,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			flow->irq = -EINVAL;
 			goto err_flow;
 		}
-
-		netif_napi_add(common->dma_ndev, &flow->napi_rx,
-			       am65_cpsw_nuss_rx_poll);
 	}
 
 	/* setup classifier to route priorities to flows */
@@ -2590,10 +2591,11 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 	return 0;
 
 err_flow:
-	for (--i; i >= 0 ; i--) {
+	netif_napi_del(&flow->napi_rx);
+	for (--i; i >= 0; i--) {
 		flow = &rx_chn->flows[i];
-		netif_napi_del(&flow->napi_rx);
 		devm_free_irq(dev, flow->irq, flow);
+		netif_napi_del(&flow->napi_rx);
 	}
 
 err:
-- 
2.34.1



From pabeni at redhat.com  Tue Mar 11 06:08:45 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Tue, 11 Mar 2025 14:08:45 +0100
Subject: [Intel-wired-lan] [PATCH net-next v11 0/4] fix the DMA API misuse
 problem for page_pool
In-Reply-To: <875xkj1t70.fsf@toke.dk>
References: <20250307092356.638242-1-linyunsheng@huawei.com>
 <87v7slvsed.fsf@toke.dk> <40b33879-509a-4c4a-873b-b5d3573b6e14@gmail.com>
 <875xkj1t70.fsf@toke.dk>
Message-ID: <72cd7f5a-ab92-494c-b7f8-4696d23ed4b1@redhat.com>

On 3/8/25 3:40 PM, Toke H?iland-J?rgensen wrote:
> Yunsheng Lin <yunshenglin0825 at gmail.com> writes:
>> I only took a glance at git code above, it seems reusing the
>> _pp_mapping_pad for pp_dma_index seems like a wrong direction
>> as mentioned in discussion with Ilias above as the field might
>> be used when a page is mmap'ed to user space, and reusing that
>> field in 'struct page' seems to disable the tcp_zerocopy feature,
>> see the below commit from Eric:
>> https://github.com/torvalds/linux/commit/577e4432f3ac810049cb7e6b71f4d96ec7c6e894
>>
>> Also, I am not sure if a page_pool owned page can be spliced into the fs
>> subsystem yet, but if it does, I am not sure how is reusing the
>> page->mapping possible if that page is called in __filemap_add_folio()?
>>
>> https://elixir.bootlin.com/linux/v6.14-rc5/source/mm/filemap.c#L882
> 
> Hmm, so I did look at the mapping field, but concluded using it wouldn't
> interfere with anything relevant as long as it's reset back to zero
> before the page is returned to the page allocator. However, I definitely
> missed the TCP zero-copy thing, and other things as well, it would seem
> (cf the discussion you referred to above).
> 
> However, I did consider alternatives: AFAICT there should be space in
> the pp_magic field (used for the PP_SIGNATURE), so that with a bit of
> care we can stick an ID into the upper bits and still avoid ending up
> with a value that could look like a valid pointer.
> 
> I didn't implement that initially because I wasn't sure it was
> necessary, but seeing as it is, I will take another look at it. I have
> one or two other ideas if this turns out not to pan out.

Another dumb option would be storing directly the page address in the
xarray, and avoid entirely going through an ID. I guess it will use more
memory (the array will be more sparse) and will have more overhead, but
could be possibly simpler?

/P



From will at kernel.org  Tue Mar 11 06:13:36 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 13:13:36 +0000
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
In-Reply-To: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
References: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
Message-ID: <174169306404.278141.17801949874773526998.b4-ty@kernel.org>

On Tue, 04 Mar 2025 00:51:27 -0800, Piotr Jaroszynski wrote:
> Update the __flush_tlb_range_op macro not to modify its parameters as
> these are unexepcted semantics. In practice, this fixes the call to
> mmu_notifier_arch_invalidate_secondary_tlbs() in
> __flush_tlb_range_nosync() to use the correct range instead of an empty
> range with start=end. The empty range was (un)lucky as it results in
> taking the invalidate-all path that doesn't cause correctness issues,
> but can certainly result in suboptimal perf.
> 
> [...]

Applied to arm64 (for-next/fixes), thanks!

[1/1] Fix mmu notifiers for range-based invalidates
      https://git.kernel.org/arm64/c/f7edb07ad7c6

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev


From will at kernel.org  Tue Mar 11 06:13:37 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 13:13:37 +0000
Subject: [PATCH v9] arm64: mm: Populate vmemmap at the page level if not section aligned
In-Reply-To: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
References: <20250304072700.3405036-1-quic_zhenhuah@quicinc.com>
Message-ID: <174169292046.277676.9363571702356367812.b4-ty@kernel.org>

On Tue, 04 Mar 2025 15:27:00 +0800, Zhenhua Huang wrote:
> On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set
> to 27, making one section 128M. The related page struct which vmemmap
> points to is 2M then.
> Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the
> vmemmap to populate at the PMD section level which was suitable
> initially since hot plug granule is always one section(128M). However,
> commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug")
> introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the
> existing arm64 assumptions.
> 
> [...]

Applied to arm64 (for-next/fixes), thanks!

[1/1] arm64: mm: Populate vmemmap at the page level if not section aligned
      https://git.kernel.org/arm64/c/d4234d131b0a

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev


From joro at 8bytes.org  Tue Mar 11 06:15:04 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Tue, 11 Mar 2025 14:15:04 +0100
Subject: [PATCH] iommu: Unexport iommu_fwspec_free()
In-Reply-To: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
References: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
Message-ID: <Z9A3WJSgUPjROev6@8bytes.org>

This patch triggered two compile issues on ARM32, which I fixed up in my
tree:

On Thu, Feb 27, 2025 at 02:47:47PM +0000, Robin Murphy wrote:
>  static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev)
>  {
> -	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> +	struct iommu_fwspec *fwspec = NULL

Missing semicolon here.

>  	struct of_phandle_args iommu_spec;
>  	struct mtk_iommu_v1_data *data;
>  	int err, idx = 0, larbid, larbidx;
>  	struct device_link *link;
>  	struct device *larbdev;
>  
> -	/*
> -	 * In the deferred case, free the existed fwspec.
> -	 * Always initialize the fwspec internally.
> -	 */
> -	if (fwspec) {
> -		iommu_fwspec_free(dev);
> -		fwspec = dev_iommu_fwspec_get(dev);
> -	}
> -
>  	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
>  					   "#iommu-cells",
>  					   idx, &iommu_spec)) {
> @@ -476,6 +467,9 @@ static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev)
>  		idx++;
>  	}
>  
> +	if (!fwspec)
> +		return -ENODEV;
> +

Wrong return type here.

Please be more cautious next time and make sure to compile-test all
changed files of a patch.

Thanks,

	Joerg


From prabhakar.csengg at gmail.com  Tue Mar 11 06:20:02 2025
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Tue, 11 Mar 2025 13:20:02 +0000
Subject: [PATCH net-next 1/7] net: stmmac: allow platforms to use PHY tx
 clock stop capability
In-Reply-To: <E1trIA0-005ntK-FS@rmk-PC.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk> <E1trIA0-005ntK-FS@rmk-PC.armlinux.org.uk>
Message-ID: <CA+V-a8sCxs4MFZgo0q=0HmpyWXk7hYSGq0awm2YuAFZk+x6BEA@mail.gmail.com>

On Sun, Mar 9, 2025 at 3:02?PM Russell King (Oracle)
<rmk+kernel at armlinux.org.uk> wrote:
>
> Allow platform glue to instruct stmmac to make use of the PHY transmit
> clock stop capability when deciding whether to allow the transmit clock
> from the DWMAC core to be stopped.
>
> Cc: "Lad, Prabhakar" <prabhakar.csengg at gmail.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac.h     |  1 +
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 ++++++++++++----
>  include/linux/stmmac.h                           |  3 ++-
>  3 files changed, 15 insertions(+), 5 deletions(-)
>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>

Cheers,
Prabhakar

> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> index d87275c1cf23..bddfa0f4aa21 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> @@ -306,6 +306,7 @@ struct stmmac_priv {
>         struct timer_list eee_ctrl_timer;
>         int lpi_irq;
>         u32 tx_lpi_timer;
> +       bool tx_lpi_clk_stop;
>         bool eee_enabled;
>         bool eee_active;
>         bool eee_sw_timer_en;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index fa1d7d3a2f43..6f29804148b6 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -457,8 +457,7 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
>         /* Check and enter in LPI mode */
>         if (!priv->tx_path_in_lpi_mode)
>                 stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_FORCED,
> -                       priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
> -                       0);
> +                                   priv->tx_lpi_clk_stop, 0);
>  }
>
>  /**
> @@ -1104,13 +1103,18 @@ static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
>
>         priv->eee_enabled = true;
>
> +       /* Update the transmit clock stop according to PHY capability if
> +        * the platform allows
> +        */
> +       if (priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP)
> +               priv->tx_lpi_clk_stop = tx_clk_stop;
> +
>         stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
>                              STMMAC_DEFAULT_TWT_LS);
>
>         /* Try to cnfigure the hardware timer. */
>         ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
> -                                 priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
> -                                 priv->tx_lpi_timer);
> +                                 priv->tx_lpi_clk_stop, priv->tx_lpi_timer);
>
>         if (ret) {
>                 /* Hardware timer mode not supported, or value out of range.
> @@ -1269,6 +1273,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
>         if (!(priv->plat->flags & STMMAC_FLAG_RX_CLK_RUNS_IN_LPI))
>                 priv->phylink_config.eee_rx_clk_stop_enable = true;
>
> +       /* Set the default transmit clock stop bit based on the platform glue */
> +       priv->tx_lpi_clk_stop = priv->plat->flags &
> +                               STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
> +
>         mdio_bus_data = priv->plat->mdio_bus_data;
>         if (mdio_bus_data)
>                 priv->phylink_config.default_an_inband =
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index b6f03ab12595..c4ec8bb8144e 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -183,7 +183,8 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_INT_SNAPSHOT_EN            BIT(9)
>  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI         BIT(10)
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING      BIT(11)
> -#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY   BIT(12)
> +#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP      BIT(12)
> +#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY   BIT(13)
>
>  struct plat_stmmacenet_data {
>         int bus_id;
> --
> 2.30.2
>


From ryan.roberts at arm.com  Tue Mar 11 06:20:56 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Tue, 11 Mar 2025 13:20:56 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <0ac0f1f5-e4a0-46ae-8ea0-2eba7e21a7e1@arm.com>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <b46dc626-edc9-4d20-99d2-6cd08a01346c@os.amperecomputing.com>
 <43732270-8fd0-4a18-abec-096e383a6a4d@arm.com>
 <5ff34bd0-7823-4f31-9f13-bf60d3345b99@arm.com>
 <7cca1edf-fd1b-4622-999e-8e0ca098dfe2@arm.com>
 <0ac0f1f5-e4a0-46ae-8ea0-2eba7e21a7e1@arm.com>
Message-ID: <818529f7-f720-4ae9-ab72-c8cd6dc43c0b@arm.com>

On 11/03/2025 12:16, Suzuki K Poulose wrote:
> On 11/03/2025 10:58, Ryan Roberts wrote:
>> On 11/03/2025 10:17, Suzuki K Poulose wrote:
>>> On 03/03/2025 10:17, Ryan Roberts wrote:
>>>> On 01/03/2025 01:32, Yang Shi wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 2/28/25 10:24 AM, Miko?aj Lenczewski wrote:
>>>>>> For supporting BBM Level 2 for userspace mappings, we want to ensure
>>>>>> that the smmu also supports its own version of BBM Level 2. Luckily, the
>>>>>> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
>>>>>> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
>>>>>> BBM level 2 is claimed.
>>>>>>
>>>>>> Add the feature and testing for it under arm_smmu_sva_supported().
>>>>>>
>>>>>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>>>>>> ---
>>>>>> ??? arch/arm64/kernel/cpufeature.c????????????????? | 7 +++----
>>>>>> ??? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>>>>>> ??? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c???? | 3 +++
>>>>>> ??? drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h???? | 4 ++++
>>>>>> ??? 4 files changed, 13 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>>>> index 63f6d356dc77..1022c63f81b2 100644
>>>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>>>> @@ -2223,8 +2223,6 @@ static bool has_bbml2_noabort(const struct
>>>>>> arm64_cpu_capabilities *caps, int sco
>>>>>> ??????????????? if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
>>>>>> ??????????????????? return false;
>>>>>> ??????????? }
>>>>>> -
>>>>>> -??????? return true;
>>>>>> ??????? } else if (scope & SCOPE_LOCAL_CPU) {
>>>>>> ??????????? /* We are a hot-plugged CPU, so only need to check our MIDR.
>>>>>> ???????????? * If we have the correct MIDR, but the kernel booted on an
>>>>>> @@ -2232,10 +2230,11 @@ static bool has_bbml2_noabort(const struct
>>>>>> arm64_cpu_capabilities *caps, int sco
>>>>>> ???????????? * we have an incorrect MIDR, but the kernel booted on a
>>>>>> ???????????? * sufficient CPU, we will not bring up this CPU.
>>>>>> ???????????? */
>>>>>> -??????? return cpu_has_bbml2_noabort(read_cpuid_id());
>>>>>> +??????? if (!cpu_has_bbml2_noabort(read_cpuid_id()))
>>>>>> +??????????? return false;
>>>>>> ??????? }
>>>>>> ??? -??? return false;
>>>>>> +??? return has_cpuid_feature(caps, scope);
>>>>>
>>>>> Do we really need this? IIRC, it means the MIDR has to be in the allow list
>>>>> *AND* MMFR2 register has to be set too. AmpereOne doesn't have MMFR2 register
>>>>> set.
>>>>
>>>> Miko, I think this should have been squashed into patch #1? It doesn't
>>>> belong in
>>>> this patch.
>>>>
>>>> Yang, we discussed this internally and decided that we thought it was best to
>>>> still require BBML2 being advertised in the feature register. That way if
>>>> trying
>>>> to use KVM to emulate a CPU that is in the allow list but doesn't really
>>>> support
>>>> BBML2, we won't try to use it.
>>>>
>>>> But we still end up with the same problem if running on a physical CPU that
>>>> supports BBML2 with conflict aborts, but emulating a CPU in the allow list. So
>>>
>>> I don't understand the problem here ? In the worst case, if we want to disable
>>> the BBML2 feature on a given CPU, we could provide an id-
>>> override to reset the value of BBML2. Or provide a kernel parameter to
>>> disable this in case we want to absolutely disable the feature on a
>>> "distro" kernel.
>>
>> Hi Suzuki,
>>
>> Sorry perhaps I'm confusing everyone; As I recall, we had a conversation before
>> Miko posted this series where you were suggesting we should check BOTH that all
>> the CPUs' MIDRs are in the allow list AND that BBML2 is advertised in MMFR2 in
>> order to decide to enable the CPU feature. My understanding was that without the
>> MMFR2 check, you were concerned that in a virtualization scenario, a CPU's MIDR
>> could be overridden to emulate a CPU that is in the allow list, but in reality
>> the CPU does not support BBML2. We would then enable BBML2 and BadThings (TM)
>> will happen. So additionally checking the MMFR2 would solve this.
>>
>> But Yang is saying that he plans to add the AmpereOne to the allow list because
>> it does support BBML2+NOCONFLICT semantics and we want to benefit from that. But
>> AmpereOne does not advertise BBML2 in it's MMFR2. So with the current approach,
>> adding AmpereOne to the allow list is not sufficient to enable the feature.
>>
>> But back to your original justification for checking the MMFR2; I don't think
>> that really solves the problem in general, because we don't just require BBML2,
>> we require BBML2+NOCONFLICT. And we can only determine that from the MIDR. So
>> why bother checking MMFR2?
> 
> My concerns are not around enabling a CPU, but having a damage control with a
> "kernel" that a user has no control over (Read, standard distribution kernel).

Ahh I misunderstood then.

> 
> 1. If the combination of the above causes problem (in Virtualization)
> 2. If the combination of the above is detected to have problems in baremetal.
> 
> In (1), VMM could control the ID register and disable the feature.
> 
> For (2) we could provide an id-override on command line to disable it in
> the worst case.
> 
> So, having the id register case is a good way to get the system running
> with a given kernel (in either world). Without that, we don't have a tunable to
> control the behavior at runtime.
> 
> May be I am being over paranoid about this.
> 
>>
>> I guess we could provide an id-override on the kernel command line to *enable*
>> BBML2 for AmpereOne, but that's not going to be suitable for mass deployment, I
> 
> Unfortunately, we can't override to provide the "feature" that is missing (at
> least today).
> 
> One option is, run with a whitelist, but provide a kernel parameter to disable
> bbml2 feature.
> 
> Something like, arm64.bbml2=0
> > So the decision is based on the parameter && MIDR list.

This sounds like a good solution to me. I guess we would wire this up to the SW
features "register".

Thanks,
Ryan

> 
> 
> Cheers
> Suzuki
> 
>> don't think?
>>
>> Thanks,
>> Ryan
>>
>>>
>>> Suzuki
>>>
>>>
>>>> given AmpereOne doesn't advertise BBML2 but does support it, I'd be happy to
>>>> remove this check.
>>>>
>>>> Thanks,
>>>> Ryan
>>>>
>>>>
>>>>>
>>>>> Thanks,
>>>>> Yang
>>>>>
>>>>>> ??? }
>>>>>> ??? ? #ifdef CONFIG_ARM64_PAN
>>>>>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/
>>>>>> arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>>> index 9ba596430e7c..6ba182572788 100644
>>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>>>>>> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>>>>>> ??????????? feat_mask |= ARM_SMMU_FEAT_VAX;
>>>>>> ??????? }
>>>>>> ??? +??? if (system_supports_bbml2_noabort())
>>>>>> +??????? feat_mask |= ARM_SMMU_FEAT_BBML2;
>>>>>> +
>>>>>> ??????? if ((smmu->features & feat_mask) != feat_mask)
>>>>>> ??????????? return false;
>>>>>> ??? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/
>>>>>> arm/arm-smmu-v3/arm-smmu-v3.c
>>>>>> index 358072b4e293..dcee0bdec924 100644
>>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>>>>>> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct
>>>>>> arm_smmu_device *smmu)
>>>>>> ??????? if (FIELD_GET(IDR3_RIL, reg))
>>>>>> ??????????? smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>>>>>> ??? +??? if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
>>>>>> +??????? smmu->features |= ARM_SMMU_FEAT_BBML2;
>>>>>> +
>>>>>> ??????? /* IDR5 */
>>>>>> ??????? reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>>>>>> ??? diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/
>>>>>> arm/arm-smmu-v3/arm-smmu-v3.h
>>>>>> index bd9d7c85576a..85eaf3ab88c2 100644
>>>>>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>>>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>>>>>> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>>>>>> ??? #define ARM_SMMU_IDR3??????????? 0xc
>>>>>> ??? #define IDR3_FWB??????????? (1 << 8)
>>>>>> ??? #define IDR3_RIL??????????? (1 << 10)
>>>>>> +#define IDR3_BBML??????????? GENMASK(12, 11)
>>>>>> +#define IDR3_BBML1??????????? (1 << 11)
>>>>>> +#define IDR3_BBML2??????????? (2 << 11)
>>>>>> ??? ? #define ARM_SMMU_IDR5??????????? 0x14
>>>>>> ??? #define IDR5_STALL_MAX??????????? GENMASK(31, 16)
>>>>>> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>>>>>> ??? #define ARM_SMMU_FEAT_HA??????? (1 << 21)
>>>>>> ??? #define ARM_SMMU_FEAT_HD??????? (1 << 22)
>>>>>> ??? #define ARM_SMMU_FEAT_S2FWB??????? (1 << 23)
>>>>>> +#define ARM_SMMU_FEAT_BBML2??????? (1 << 24)
>>>>>> ??????? u32??????????????? features;
>>>>>> ??? ? #define ARM_SMMU_OPT_SKIP_PREFETCH??? (1 << 0)
>>>>>
>>>>
>>>
>>
> 



From krzk at kernel.org  Tue Mar 11 06:22:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 14:22:54 +0100
Subject: [PATCH] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML schema
In-Reply-To: <20250311125756.24064-1-purvayeshi550@gmail.com>
References: <20250311125756.24064-1-purvayeshi550@gmail.com>
Message-ID: <af6ebce2-7256-48bd-94d4-dc81e2944966@kernel.org>

On 11/03/2025 13:57, Purva Yeshi wrote:
> Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
> YAML schema (`lpc32xx-pwm.yaml`).
> 
> Changes:
> 
> Add SPDX license identifier `(GPL-2.0-only OR BSD-2-Clause)`.

That's not a change in the binding.

> Define `$id` and `$schema` fields for proper schema validation.
> Set `title` to describe the LPC32XX PWM controller.

Neither these.

> Add maintainers as per `scripts/get_maintainer.pl` output.

These should not be subsystem maintainers.

> Reference `pwm.yaml#` in `allOf` to inherit common PWM properties.

Not a change to the binding.

> 
> Define properties:
> Restrict `compatible` to `"nxp,lpc3220-pwm"` using `const`.
> Limit `reg` to `maxItems: 1` to ensure a single register range.
> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.
> 
> Mark `compatible` and `reg` as required properties.

So it wasn't before? What are you implying here?

> Set `unevaluatedProperties: false` to enforce strict validation.
> 
> Validate the YAML schema using dt-validate and yamllint.

None of above is suitable for commit msg.

> 
> Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
> ---
>  .../devicetree/bindings/pwm/lpc32xx-pwm.yaml  | 45 +++++++++++++++++++
>  1 file changed, 45 insertions(+)

Where is the conversion?

>  create mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
> new file mode 100644
> index 000000000..3e41cd291
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pwm/nxp,lpc32xx-pwm.yaml#

Filename matching compatible.

> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: LPC32XX PWM controller
> +
> +maintainers:
> +  - "Uwe Kleine-K?nig <ukleinek at kernel.org>"
> +  - "Vladimir Zapolskiy <vz at mleia.com>"
> +  - "Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>"

Look at other bindings - none of them use quotes.

> +
> +allOf:
> +  - $ref: pwm.yaml#
> +
> +properties:
> +  compatible:
> +    const: nxp,lpc3220-pwm
> +
> +  reg:
> +    maxItems: 1
> +
> +  "#pwm-cells":
> +    const: 3
> +
> +required:
> +  - compatible
> +  - reg
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    pwm at 4005c000 {
> +        compatible = "nxp,lpc3220-pwm";
> +        reg = <0x4005c000 0x4>;
> +        #pwm-cells = <3>;
> +    };
> +  - |
> +    pwm at 4005c004 {
> +        compatible = "nxp,lpc3220-pwm";

One example is enough.



Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 11 06:25:52 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 14:25:52 +0100
Subject: [PATCH v3 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <cc6a19b3-ba35-465c-9fa6-a764df7c01c1@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
 <20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f@imgtec.com>
 <20250311-flashy-rattlesnake-of-rain-dcc4f6@krzk-bin>
 <cc6a19b3-ba35-465c-9fa6-a764df7c01c1@imgtec.com>
Message-ID: <c7de47e5-9a5d-455e-b293-b25b6f801b2b@kernel.org>

On 11/03/2025 11:33, Matt Coster wrote:
>>> The currently supported GPU (AXE-1-16M) only requires a single power
>>> domain. Subsequent patches will add support for BXS-4-64 MC1, which has
>>> two power domains. Add infrastructure now to allow for this.
>>>
>>> Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
>>> are DMA devices. The decision for coherency is made at integration time and
>>> this property should be applied wherever it accurately describes the
>>> vendor integration.
>>>
>>> Note that the new required properties for power domains are conditional on
>>> the new base compatible string to avoid an ABI break.
>>>
>>> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
>>> ---
>>> Changes in v3:
>>> - Remove unnecessary example
>>> - Remove second power domain details, add these where they're used instead
>>> - Avoid ABI breaks by limiting new required properties to new compatible
>>>   strings and making all binding changes in a single patch.
>>> - Links to v2:
>>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
>>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
>>>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
>>> ---
>>>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 43 ++++++++++++++++++----
>>>  1 file changed, 36 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>>> index 256e252f8087fa0d6081f771a01601d34b66fe19..5c16b2881447c9cda78e5bb46569e2f675d740c4 100644
>>> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>>> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
>>> @@ -12,10 +12,20 @@ maintainers:
>>>  
>>>  properties:
>>>    compatible:
>>> -    items:
>>> -      - enum:
>>> -          - ti,am62-gpu
>>> -      - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
>>> +    oneOf:
>>> +      - items:
>>> +          - enum:
>>> +              - ti,am62-gpu
>>> +          - const: img,img-axe-1-16m
>>> +          - const: img,img-rogue
>>
>> That's still ABI break. You got here NAK. You ust preserve img,img-axe.
>> Your marketing troubles do not concern Linux.
> 
> I think I'm misunderstanding something here. Is keeping the existing
> compatible string around in the deprecated item below not sufficient to
> maintain the existing ABI?

I was not precise/correct. This indeed is not an ABI break itself.
However you will break the users of DTS when anyone applies such DTS.

> 
> Would adding img,img-axe back into the updated list (bringing it to four
> elements) be acceptable?

Yes, you must keep all the compatibles. Affecting users because of
marketing choices is a no-go. No one here cares about marketing.

> 
>>
>>> +
>>> +      # This legacy combination of compatible strings was introduced early on
>>> +      # before the more specific GPU identifiers were used.
>>> +      - items:
>>> +          - enum:
>>> +              - ti,am62-gpu
>>> +          - const: img,img-axe
>>> +        deprecated: true
>>>  
>>>    reg:
>>>      maxItems: 1
>>> @@ -34,8 +44,13 @@ properties:
>>>    interrupts:
>>>      maxItems: 1
>>>  
>>> -  power-domains:
>>> -    maxItems: 1
>>> +  power-domains: true
>>
>> No, widest constraints always stay here.
> 
> Ack
> 
>>
>>> +
>>> +  power-domain-names:
>>> +    items:
>>> +      - const: a
>>
>> That's not a useful name. Are you sure that datasheet calls it power
>> domain A?
> 
> Sadly yes. With the Volcanic architecture the power domains get real
> names, but until then we were stuck with abc. I shared a snipet from the
> BXS-4-64 TRM with Conor in the replies to the V1 series in [1].

OK, that's fine.


Best regards,
Krzysztof


From jonathanh at nvidia.com  Tue Mar 11 06:25:58 2025
From: jonathanh at nvidia.com (Jon Hunter)
Date: Tue, 11 Mar 2025 13:25:58 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <673e453b-798f-4fc1-8ed1-3cf597e926b4@nvidia.com>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
 <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
 <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>
 <673e453b-798f-4fc1-8ed1-3cf597e926b4@nvidia.com>
Message-ID: <4fe02d97-2c38-4d40-b17d-5f8174d2f7cc@nvidia.com>


On 10/03/2025 14:20, Jon Hunter wrote:
> 
> On 07/03/2025 17:07, Russell King (Oracle) wrote:
>> On Fri, Mar 07, 2025 at 04:11:19PM +0000, Jon Hunter wrote:
>>> Hi Russell,
>>>
>>> On 06/03/2025 15:23, Russell King (Oracle) wrote:
>>>> Hi,
>>>>
>>>> This is a second approach to solving the STMMAC reset issues caused by
>>>> the lack of receive clock from the PHY where the media is in low power
>>>> mode with a PHY that supports receive clock-stop.
>>>>
>>>> The first approach centred around only addressing the issue in the
>>>> resume path, but it seems to also happen when the platform glue module
>>>> is removed and re-inserted (Jon - can you check whether that's also
>>>> the case for you please?)
>>>>
>>>> As this is more targetted, I've dropped the patches from this series
>>>> which move the call to phylink_resume(), so the link may still come
>>>> up too early on resume - but that's something I also intend to fix.
>>>>
>>>> This is experimental - so I value test reports for this change.
>>>
>>>
>>> The subject indicates 3 patches, but I only see 2 patches? Can you 
>>> confirm
>>> if there are 2 or 3?
>>
>> Yes, 2 patches is correct.
>>
>>> So far I have only tested to resume case with the 2 patches to make that
>>> that is working but on Tegra186, which has been the most problematic, 
>>> it is
>>> not working reliably on top of next-20250305.
>>
>> To confirm, you're seeing stmmac_reset() sporadically timing out on
>> resume even with these patches appled? That's rather disappointing.
> 
> So I am no longer seeing the reset fail, from what I can see, but now
> NFS is not responding after resume ...
> 
> [?? 49.825094] Enabling non-boot CPUs ...
> [?? 49.829760] Detected PIPT I-cache on CPU1
> [?? 49.832694] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU1: 0x0000009444c004
> [?? 49.844120] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU1: 0x00000010305116
> [?? 49.856231] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU1: 0x00000003001066
> [?? 49.868081] CPU1: Booted secondary processor 0x0000000000 [0x4e0f0030]
> [?? 49.875389] CPU1 is up
> [?? 49.877187] Detected PIPT I-cache on CPU2
> [?? 49.880824] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU2: 0x0000009444c004
> [?? 49.892266] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU2: 0x00000010305116
> [?? 49.904467] CPU features: SANITY CHECK: Unexpected variation in 
> SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU2: 0x00000003001066
> [?? 49.916257] CPU2: Booted secondary processor 0x0000000001 [0x4e0f0030]
> [?? 49.923610] CPU2 is up
> [?? 49.925194] Detected PIPT I-cache on CPU3
> [?? 49.929010] CPU3: Booted secondary processor 0x0000000101 [0x411fd073]
> [?? 49.935866] CPU3 is up
> [?? 49.937983] Detected PIPT I-cache on CPU4
> [?? 49.941824] CPU4: Booted secondary processor 0x0000000102 [0x411fd073]
> [?? 49.948593] CPU4 is up
> [?? 49.950810] Detected PIPT I-cache on CPU5
> [?? 49.954651] CPU5: Booted secondary processor 0x0000000103 [0x411fd073]
> [?? 49.961431] CPU5 is up
> [?? 50.069784] dwc-eth-dwmac 2490000.ethernet eth0: configuring for phy/ 
> rgmii link mode
> [?? 50.077634] dwmac4: Master AXI performs any burst length
> [?? 50.080718] dwc-eth-dwmac 2490000.ethernet eth0: No Safety Features 
> support found
> [?? 50.088172] dwc-eth-dwmac 2490000.ethernet eth0: IEEE 1588-2008 
> Advanced Timestamp supported
> [?? 50.096851] dwc-eth-dwmac 2490000.ethernet eth0: Link is Up - 1Gbps/ 
> Full - flow control rx/tx
> [?? 50.110897] usb-conn-gpio 3520000.padctl:ports:usb2-0:connector: 
> repeated role: device
> [?? 50.113922] tegra-xusb 3530000.usb: Firmware timestamp: 2020-07-06 
> 13:39:28 UTC
> [?? 50.147552] OOM killer enabled.
> [?? 50.148441] Restarting tasks ... done.
> [?? 50.152552] VDDIO_SDMMC3_AP: voltage operation not allowed
> [?? 50.154761] random: crng reseeded on system resumption
> [?? 50.162912] PM: suspend exit
> [?? 50.212215] VDDIO_SDMMC3_AP: voltage operation not allowed
> [?? 50.271578] VDDIO_SDMMC3_AP: voltage operation not allowed
> [?? 50.338597] VDDIO_SDMMC3_AP: voltage operation not allowed
> [? 234.474848] nfs: server 10.26.51.252 not responding, still trying
> [? 234.538769] nfs: server 10.26.51.252 not responding, still trying
> [? 237.546922] nfs: server 10.26.51.252 not responding, still trying
> [? 254.762753] nfs: server 10.26.51.252 not responding, timed out
> [? 254.762771] nfs: server 10.26.51.252 not responding, timed out
> [? 254.766376] nfs: server 10.26.51.252 not responding, timed out
> [? 254.766392] nfs: server 10.26.51.252 not responding, timed out
> [? 254.783778] nfs: server 10.26.51.252 not responding, timed out
> [? 254.789582] nfs: server 10.26.51.252 not responding, timed out
> [? 254.795421] nfs: server 10.26.51.252 not responding, timed out
> [? 254.801193] nfs: server 10.26.51.252 not responding, timed out
> 
>> Do either of the two attached diffs make any difference?
> 
> I will try these next.


I tried both of the diffs, but both had the same problem as above and
I see these nfs timeouts after resuming. What works the best is the
original change you proposed (this is based upon the latest two
patches) ...

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e2146d3aee74..48a646b76a29 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3109,10 +3109,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
         if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
                 priv->plat->dma_cfg->atds = 1;
  
-       /* Note that the PHY clock must be running for reset to complete. */
-       phylink_rx_clk_stop_block(priv->phylink);
         ret = stmmac_reset(priv, priv->ioaddr);
-       phylink_rx_clk_stop_unblock(priv->phylink);
         if (ret) {
                 netdev_err(priv->dev, "Failed to reset the dma\n");
                 return ret;
@@ -7951,6 +7948,8 @@ int stmmac_resume(struct device *dev)
         rtnl_lock();
         mutex_lock(&priv->lock);
  
+       /* Note that the PHY clock must be running for reset to complete. */
+       phylink_rx_clk_stop_block(priv->phylink);
         stmmac_reset_queues_param(priv);
  
         stmmac_free_tx_skbufs(priv);
@@ -7961,6 +7960,7 @@ int stmmac_resume(struct device *dev)
         stmmac_set_rx_mode(ndev);
  
         stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
+       phylink_rx_clk_stop_unblock(priv->phylink);
  
         stmmac_enable_all_queues(priv);
         stmmac_enable_all_dma_irq(priv);

-- 
nvpublic



From prabhakar.csengg at gmail.com  Tue Mar 11 06:30:13 2025
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Tue, 11 Mar 2025 13:30:13 +0000
Subject: [PATCH net-next 6/7] dt-bindings: deprecate "snps,en-tx-lpi-clockgating"
 property
In-Reply-To: <E1trIAQ-005nto-3w@rmk-PC.armlinux.org.uk>
References: <Z82tWYZulV12Pjir@shell.armlinux.org.uk> <E1trIAQ-005nto-3w@rmk-PC.armlinux.org.uk>
Message-ID: <CA+V-a8u34cKgccW=qEw=FC34HH+Q6pVmRqeMq7Q_btxqkqNtnQ@mail.gmail.com>

On Sun, Mar 9, 2025 at 3:13?PM Russell King (Oracle)
<rmk+kernel at armlinux.org.uk> wrote:
>
> Whether the MII transmit clock can be stopped is primarily a property
> of the PHY (there is a capability bit that should be checked first.)
> Whether the MAC is capable of stopping the transmit clock is a separate
> issue, but this is already handled by the core DesignWare MAC code.
>
> Therefore, snps,en-tx-lpi-clockgating is technically incorrect, so this
> commit deprecates the property in the binding.
>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  Documentation/devicetree/bindings/net/snps,dwmac.yaml | 1 +
>  1 file changed, 1 insertion(+)
>

Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>

Cheers,
Prabhakar

> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index 3f0aa46d798e..78b3030dc56d 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -494,6 +494,7 @@ title: Synopsys DesignWare MAC
>
>    snps,en-tx-lpi-clockgating:
>      $ref: /schemas/types.yaml#/definitions/flag
> +    deprecated: true
>      description:
>        Enable gating of the MAC TX clock during TX low-power mode
>
> --
> 2.30.2
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


From robh at kernel.org  Tue Mar 11 06:32:28 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 08:32:28 -0500
Subject: [PATCH v7 03/11] dt-bindings: pci: Add common schema for devices
 accessible through PCI BARs
In-Reply-To: <20250310212125.GB2377483@rocinante>
References: <cover.1738963156.git.andrea.porta@suse.com> <c0acc51a7210fb30cae7b26f4ad1f0449beed95e.1738963156.git.andrea.porta@suse.com>
 <20250310212125.GB2377483@rocinante>
Message-ID: <CAL_JsqKPGOdS_8KDggO5tBHAnC-NTLAC5iS9GANm9BuxBfQUsw@mail.gmail.com>

On Mon, Mar 10, 2025 at 4:21?PM Krzysztof Wilczynski <kw at linux.com> wrote:
>
> Hello,
>
> [...]
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d45c88955072..af2e4652bf3b 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -19752,6 +19752,7 @@ RASPBERRY PI RP1 PCI DRIVER
> >  M:   Andrea della Porta <andrea.porta at suse.com>
> >  S:   Maintained
> >  F:   Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
> > +F:   Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
> >  F:   Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
> >  F:   include/dt-bindings/clock/rp1.h
> >  F:   include/dt-bindings/misc/rp1.h
>
> I would be happy to pick this via the PCI tree as per the standard
> operating procedure.  However, the MAINTAINERS changes do not exist
> for us yet, and are added in the first patch of the series, which is
> not ideal.
>
> I can add the missing dependency manually, but that would cause issues
> for linux-next tree, which is also not ideal.
>
> I saw some review feedback, as such, when you are going to be sending
> another version, can you make MAINTAINERS changes to be the last patch,
> perhaps.  Basically, something standalone that perhaps whoever will pick
> the misc patch could also pick and apply at the same time.
>
> Alternatively, someone else picking up the PCI dt-bindings would work, too.
>
> Your thoughts?

I guess I missed this in review, but why is a common schema buried in
a device maintainer entry? Also, an entry in MAINTAINERS is redundant
anyway because get_maintainers.pl can fetch maintainers from the
schema file.

Rob


From ardb at kernel.org  Tue Mar 11 06:32:47 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Tue, 11 Mar 2025 14:32:47 +0100
Subject: [PATCH] arm64: reserve [_text, _stext) virtual address range
In-Reply-To: <20250311125414.GA4601@willie-the-truck>
References: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>
 <20250311125414.GA4601@willie-the-truck>
Message-ID: <CAMj1kXGgKy=1g1dsN1_yd8JwGZC5SpLUwiJk3GCnZhQ8UtTkKQ@mail.gmail.com>

On Tue, 11 Mar 2025 at 13:54, Will Deacon <will at kernel.org> wrote:
>
> [+Ard]
>
> On Mon, Mar 10, 2025 at 01:05:04PM -0700, Omar Sandoval wrote:
> > From: Omar Sandoval <osandov at fb.com>
> >
> > Since the referenced fixes commit, the kernel's .text section is only
> > mapped starting from _stext; the region [_text, _stext) is omitted. As a
> > result, other vmalloc/vmap allocations may use the virtual addresses
> > nominally in the range [_text, _stext). This address reuse confuses
> > multiple things:
> >
> > 1. crash_prepare_elf64_headers() sets up a segment in /proc/vmcore
> >    mapping the entire range [_text, _end) to
> >    [__pa_symbol(_text), __pa_symbol(_end)). Reading an address in
> >    [_text, _stext) from /proc/vmcore therefore gives the incorrect
> >    result.
> > 2. Tools doing symbolization (either by reading /proc/kallsyms or based
> >    on the vmlinux ELF file) will incorrectly identify vmalloc/vmap
> >    allocations in [_text, _stext) as kernel symbols.
> >
> > In practice, both of these issues affect the drgn debugger.
> > Specifically, there were cases where the vmap IRQ stacks for some CPUs
> > were allocated in [_text, _stext). As a result, drgn could not get the
> > stack trace for a crash in an IRQ handler because the core dump
> > contained invalid data for the IRQ stack address. The stack addresses
> > were also symbolized as being in the _text symbol.
> >
> > Fix this by creating an unmapped vm_area to cover [_text, _stext). This
> > prevents other allocations from using it while still achieving the
> > original goal of not mapping unpredictable data.
> >
> > Fixes: e2a073dde921 ("arm64: omit [_text, _stext) from permanent kernel mapping")
> > Cc: stable at vger.kernel.org
> > Signed-off-by: Omar Sandoval <osandov at fb.com>
> > ---
> > Based on v6.14-rc6.
> >
> > Thanks!
> >
> >  arch/arm64/mm/mmu.c | 26 +++++++++++++++++---------
> >  1 file changed, 17 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index b4df5bc5b1b8..88595ea12f39 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -703,10 +703,14 @@ static void __init declare_vma(struct vm_struct *vma,
> >                              void *va_start, void *va_end,
> >                              unsigned long vm_flags)
> >  {
> > -     phys_addr_t pa_start = __pa_symbol(va_start);
> > +     phys_addr_t pa_start = 0;
> >       unsigned long size = va_end - va_start;
> >
> > -     BUG_ON(!PAGE_ALIGNED(pa_start));
> > +     if (vm_flags & VM_MAP) {
> > +             pa_start = __pa_symbol(va_start);
> > +             BUG_ON(!PAGE_ALIGNED(pa_start));
> > +     }
> > +
> >       BUG_ON(!PAGE_ALIGNED(size));
> >
> >       if (!(vm_flags & VM_NO_GUARD))
> > @@ -715,7 +719,7 @@ static void __init declare_vma(struct vm_struct *vma,
> >       vma->addr       = va_start;
> >       vma->phys_addr  = pa_start;
> >       vma->size       = size;
> > -     vma->flags      = VM_MAP | vm_flags;
> > +     vma->flags      = vm_flags;
> >       vma->caller     = __builtin_return_address(0);
> >
> >       vm_area_add_early(vma);
> > @@ -765,13 +769,17 @@ core_initcall(map_entry_trampoline);
> >   */
> >  static void __init declare_kernel_vmas(void)
> >  {
> > -     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];
> > +     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT + 1];
> >
> > -     declare_vma(&vmlinux_seg[0], _stext, _etext, VM_NO_GUARD);
> > -     declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
> > -     declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
> > -     declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
> > -     declare_vma(&vmlinux_seg[4], _data, _end, 0);
> > +     declare_vma(&vmlinux_seg[0], _text, _stext, VM_NO_GUARD);
>
> Should we also put the memblock reservation back as it was, so that this
> region can't be allocated there?
>

The issue is about the virtual address space, not the physical memory
behind it, right? So the VA range should be protected from reuse, but
nothing needs to be mapped there.

> In fact, if we're not allocating from here, why don't we just map it
> anyway but without execute permissions?
>

It's just 64k so if this is the simplest approach, I won't object.

I wonder if this needs to be so intrusive, though - there is already a
precedent of VMAs not actually mapping the entire region they describe
(with guard pages), and so we might just declare the first VMA as
[_text, _etext), even though the first 64k of that region is not not
actually mapped.

However, if that confuses the bookkeeping or creates other problems,
declaring a separate VMA to reserve the VA range seems fine, although
the patch seems a bit intrusive (and I don't even see the whole
thing).


From richard.weiyang at gmail.com  Tue Mar 11 06:41:26 2025
From: richard.weiyang at gmail.com (Wei Yang)
Date: Tue, 11 Mar 2025 13:41:26 +0000
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <Z8_Ju0p63GBCdSG9@kernel.org>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250223002229.xuk6xlp23zr72hkc@master>
 <20250310095124.pa7dwgqhxglqrfes@master>
 <Z8_Ju0p63GBCdSG9@kernel.org>
Message-ID: <20250311134126.xfjdq6sq7jtcotck@master>

On Tue, Mar 11, 2025 at 07:27:23AM +0200, Mike Rapoport wrote:
>Hi Wei,
>
>On Mon, Mar 10, 2025 at 09:51:24AM +0000, Wei Yang wrote:
>> On Sun, Feb 23, 2025 at 12:22:29AM +0000, Wei Yang wrote:
>> >On Wed, Feb 19, 2025 at 09:24:31AM +0200, Mike Rapoport wrote:
>> >>Hi,
>> >>
>> >>On Tue, Feb 18, 2025 at 03:50:04PM +0000, Wei Yang wrote:
>> >>> On Thu, Feb 06, 2025 at 03:27:42PM +0200, Mike Rapoport wrote:
>> >>> >From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
>> >>> >
>> >>> >to denote areas that were reserved for kernel use either directly with
>> >>> >memblock_reserve_kern() or via memblock allocations.
>> >>> >
>> >>> >Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
>> >>> >---
>> >>> > include/linux/memblock.h | 16 +++++++++++++++-
>> >>> > mm/memblock.c            | 32 ++++++++++++++++++++++++--------
>> >>> > 2 files changed, 39 insertions(+), 9 deletions(-)
>> >>> >
>> >>> >diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>> >>> >index e79eb6ac516f..65e274550f5d 100644
>> >>> >--- a/include/linux/memblock.h
>> >>> >+++ b/include/linux/memblock.h
>> >>> >@@ -50,6 +50,7 @@ enum memblock_flags {
>> >>> > 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>> >>> > 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
>> >>> > 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
>> >>> >+	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
>> >>> 
>> >>> Above memblock_flags, there are comments on explaining those flags.
>> >>> 
>> >>> Seems we miss it for MEMBLOCK_RSRV_KERN.
>> >>
>> >>Right, thanks!
>> >> 
>> >>> > 
>> >>> > #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
>> >>> >@@ -1459,14 +1460,14 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
>> >>> > again:
>> >>> > 	found = memblock_find_in_range_node(size, align, start, end, nid,
>> >>> > 					    flags);
>> >>> >-	if (found && !memblock_reserve(found, size))
>> >>> >+	if (found && !__memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN))
>> >>> 
>> >>> Maybe we could use memblock_reserve_kern() directly. If my understanding is
>> >>> correct, the reserved region's nid is not used.
>> >>
>> >>We use nid of reserved regions in reserve_bootmem_region() (commit
>> >>61167ad5fecd ("mm: pass nid to reserve_bootmem_region()")) but KHO needs to
>> >>know the distribution of reserved memory among the nodes before
>> >>memmap_init_reserved_pages().
>> >> 
>> >
>> >I took another look into this commit. There maybe a very corner case in which
>> >will leave a reserved region with no nid set.
>> >
>> >memmap_init_reserved_pages()
>> >    for_each_mem_region() {
>> >        ...
>> >	memblock_set_node(start, end, &memblock.reserved, nid);
>> >    }
>> >
>> >We leverage the iteration here to set nid to all regions in memblock.reserved.
>> >But memblock_set_node() may call memblock_double_array() to expand the array,
>> >which may get a range before current start. So we would miss to set the
>> >correct nid to the new reserved region.
>> >
>> >I have tried to create a case in memblock test. This would happen when there
>> >are 126 memblock.reserved regions. And the last region is across the last two
>> >node.
>> >
>> >One way to fix this is compare type->max in memblock_set_node(). Then check
>> >this return value in memmap_init_reserved_pages(). If we found the size
>> >changes, repeat the iteration.
>> >
>> >But this is a very trivial one, not sure it worth fix.
>> >
>> 
>> Hi, Mike
>> 
>> I have done a user space test which shows we may have a chance to leave a
>> region with non-nid set.
>> 
>> Not sure you are ok with my approach of fixing.
>
>Wouldn't it be better to check for a change in reserved.max in
>memmap_init_reserved_pages()?
> 

Sounds better.

Previously I thought we need to hide detail from user, but actually it is
already in memblock.c :-)

If you agree, I would like to prepare a fix.

>> -- 
>> Wei Yang
>> Help you, Help me
>
>-- 
>Sincerely yours,
>Mike.

-- 
Wei Yang
Help you, Help me


From axboe at kernel.dk  Tue Mar 11 06:49:25 2025
From: axboe at kernel.dk (Jens Axboe)
Date: Tue, 11 Mar 2025 07:49:25 -0600
Subject: [PATCH v2 0/2] block: nvme: fix blktests nvme/039 failure
In-Reply-To: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
Message-ID: <3369329c-13ac-4b18-9923-1a24e1243035@kernel.dk>

On 3/11/25 4:43 AM, Shin'ichiro Kawasaki wrote:
> Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
> conditions") in the kernel tag v6.14-rc3 triggered blktests nvme/039
> failure [1].
> 
> The test case injects errors to the NVMe driver and confirms the errors
> are logged. The first half of the test checks it for non-passthrough
> requests, and the second half checks for passthrough requests. The
> commit made both halves fail.
> 
> This series addresses the test case failure. The first patch covers the
> passthrough requests, and the second patch covers the non-passthrough
> requests.

Looks good to me, and better than the quick fix-up for the problem.
Thanks for taking the time to do it right!

-- 
Jens Axboe



From axboe at kernel.dk  Tue Mar 11 06:50:27 2025
From: axboe at kernel.dk (Jens Axboe)
Date: Tue, 11 Mar 2025 07:50:27 -0600
Subject: [PATCH v2 0/2] block: nvme: fix blktests nvme/039 failure
In-Reply-To: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
Message-ID: <174170102773.320314.5830688529132236537.b4-ty@kernel.dk>


On Tue, 11 Mar 2025 19:43:57 +0900, Shin'ichiro Kawasaki wrote:
> Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding
> conditions") in the kernel tag v6.14-rc3 triggered blktests nvme/039
> failure [1].
> 
> The test case injects errors to the NVMe driver and confirms the errors
> are logged. The first half of the test checks it for non-passthrough
> requests, and the second half checks for passthrough requests. The
> commit made both halves fail.
> 
> [...]

Applied, thanks!

[1/2] nvme: move error logging from nvme_end_req() to __nvme_end_req()
      commit: e5c2bcc0cd47321d78bb4e865d7857304139f95d
[2/2] block: change blk_mq_add_to_batch() third argument type to bool
      commit: f00baf2eac785bba837e5ed79d489f16520e7a6d

Best regards,
-- 
Jens Axboe





From alexander.sverdlin at siemens.com  Tue Mar 11 06:53:10 2025
From: alexander.sverdlin at siemens.com (Sverdlin, Alexander)
Date: Tue, 11 Mar 2025 13:53:10 +0000
Subject: [PATCH net v2] net: ethernet: ti: am65-cpsw: Fix NAPI
 registration sequence
In-Reply-To: <20250311130103.68971-1-s-vadapalli@ti.com>
References: <20250311130103.68971-1-s-vadapalli@ti.com>
Message-ID: <02d685e2aa8721a119f528bde2f4ec9533101663.camel@siemens.com>

Hi Siddharth!

On Tue, 2025-03-11 at 18:31 +0530, Siddharth Vadapalli wrote:
> From: Vignesh Raghavendra <vigneshr at ti.com>
> 
> Registering the interrupts for TX or RX DMA Channels prior to registering
> their respective NAPI callbacks can result in a NULL pointer dereference.
> This is seen in practice as a random occurrence since it depends on the
> randomness associated with the generation of traffic by Linux and the
> reception of traffic from the wire.
> 
> Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

...

> v1 of this patch is at:
> https://lore.kernel.org/all/20250311061214.4111634-1-s-vadapalli at ti.com/
> Changes since v1:
> - Based on the feedback provided by Alexander Sverdlin <alexander.sverdlin at siemens.com>
> ? the patch has been updated to account for the cleanup path in terms of an imbalance
> ? between the number of successful netif_napi_add_tx/netif_napi_add calls and the
> ? number of successful devm_request_irq() calls. In the event of an error, we will
> ? always have one extra successful netif_napi_add_tx/netif_napi_add that needs to be
> ? cleaned up before we clean an equal number of netif_napi_add_tx/netif_napi_add and
> ? devm_request_irq.

...

> --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> @@ -2569,6 +2570,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?			???? HRTIMER_MODE_REL_PINNED);
> ?		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
> ?
> +		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> +			?????? am65_cpsw_nuss_rx_poll);
> +
> ?		ret = devm_request_irq(dev, flow->irq,
> ?				?????? am65_cpsw_nuss_rx_irq,
> ?				?????? IRQF_TRIGGER_HIGH,
> @@ -2579,9 +2583,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?			flow->irq = -EINVAL;
> ?			goto err_flow;
> ?		}
> -
> -		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> -			?????? am65_cpsw_nuss_rx_poll);
> ?	}
> ?
> ?	/* setup classifier to route priorities to flows */
> @@ -2590,10 +2591,11 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> ?	return 0;
> ?
> ?err_flow:
> -	for (--i; i >= 0 ; i--) {
> +	netif_napi_del(&flow->napi_rx);

There are totally 3 "goto err_flow;" instances, so if k3_udma_glue_rx_flow_init() or
k3_udma_glue_rx_get_irq() would fail on the first iteration, we would come here without
a single call to netif_napi_add().

> +	for (--i; i >= 0; i--) {
> ?		flow = &rx_chn->flows[i];
> -		netif_napi_del(&flow->napi_rx);
> ?		devm_free_irq(dev, flow->irq, flow);
> +		netif_napi_del(&flow->napi_rx);
> ?	}
> ?
> ?err:

-- 
Alexander Sverdlin
Siemens AG
www.siemens.com

From leo.yan at arm.com  Tue Mar 11 06:57:04 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 13:57:04 +0000
Subject: [PATCH] coresight: docs: Remove target sink from examples
In-Reply-To: <898f1265-522f-44aa-a7da-879870b18807@linaro.org>
References: <20241210144933.295798-1-james.clark@linaro.org>
 <20250311102200.GJ9682@e132581.arm.com>
 <898f1265-522f-44aa-a7da-879870b18807@linaro.org>
Message-ID: <20250311135704.GK9682@e132581.arm.com>

On Tue, Mar 11, 2025 at 10:51:39AM +0000, James Clark wrote:

[...]

> > > +Sink selection
> > > +~~~~~~~~~~~~~~
> > > +
> > > +An appropriate sink will be selected automatically for use with Perf, but since
> > > +there will typically be more than one sink, the name of the sink to use may be
> > > +specified as a special config option prefixed with '@'.
> > > +
> > > +The available sinks are listed in sysFS under
> > >   ($SYSFS)/bus/event_source/devices/cs_etm/sinks/::
> > > 
> > >          root at localhost:/sys/bus/event_source/devices/cs_etm/sinks# ls
> > >          tmc_etf0  tmc_etr0  tpiu0
> > 
> > Just a minor comment.  To reflect the latest hardware, it is good to
> > mention the TRBE case, users should not and cannot specify TRBE as the
> 
> Is that strictly true? From looking at the code I think you could pick one
> TRBE sink as long as you are only tracing from a single ETM. Although yeah
> it would be pointless.

My testing result shows perf reports error when specifying trbe as sink:

  # perf record -e cs_etm/@trbe0/ -- ls
  failed to mmap with 12 (Cannot allocate memory)

But I can make success for the command:

  # perf record -C 0 -e cs_etm/@trbe0/ -- ls
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.062 MB perf.data ]

This makes sense to me that if a perf session tries to enable trace for
multiple CPUs but only a CPU sink is supported, the driver should
report error to remind users the command does not work.

> > sink name.  The driver will give priority for TRBE by default unless
> > users specify other sink types.
> > 
> 
> IMO mentioning TRBE would be overly wordy and not really add anything.
> Removing the sink from all the base examples is exactly to make TRBE work
> without going into detail about why. And the advanced section doesn't
> mention TRBE because manually picking it is never right.

The section "Sink selection" applies _only_ to traditional sinks, not
to TRBE.  I am not sure if we should clarify a bit for this.  I don't
have strong opinion on it, as it is a trade-off between providing
necessary info and avoiding overstatement.

So this patch is fine for me:

Reviewed-by: Leo Yan <leo.yan at arm.com>


From linux at armlinux.org.uk  Tue Mar 11 06:58:51 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Tue, 11 Mar 2025 13:58:51 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <4fe02d97-2c38-4d40-b17d-5f8174d2f7cc@nvidia.com>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
 <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
 <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>
 <673e453b-798f-4fc1-8ed1-3cf597e926b4@nvidia.com>
 <4fe02d97-2c38-4d40-b17d-5f8174d2f7cc@nvidia.com>
Message-ID: <Z9BBm6tievFukbO8@shell.armlinux.org.uk>

On Tue, Mar 11, 2025 at 01:25:58PM +0000, Jon Hunter wrote:
> 
> On 10/03/2025 14:20, Jon Hunter wrote:
> > 
> > On 07/03/2025 17:07, Russell King (Oracle) wrote:
> > > On Fri, Mar 07, 2025 at 04:11:19PM +0000, Jon Hunter wrote:
> > > > Hi Russell,
> > > > 
> > > > On 06/03/2025 15:23, Russell King (Oracle) wrote:
> > > > > Hi,
> > > > > 
> > > > > This is a second approach to solving the STMMAC reset issues caused by
> > > > > the lack of receive clock from the PHY where the media is in low power
> > > > > mode with a PHY that supports receive clock-stop.
> > > > > 
> > > > > The first approach centred around only addressing the issue in the
> > > > > resume path, but it seems to also happen when the platform glue module
> > > > > is removed and re-inserted (Jon - can you check whether that's also
> > > > > the case for you please?)
> > > > > 
> > > > > As this is more targetted, I've dropped the patches from this series
> > > > > which move the call to phylink_resume(), so the link may still come
> > > > > up too early on resume - but that's something I also intend to fix.
> > > > > 
> > > > > This is experimental - so I value test reports for this change.
> > > > 
> > > > 
> > > > The subject indicates 3 patches, but I only see 2 patches? Can
> > > > you confirm
> > > > if there are 2 or 3?
> > > 
> > > Yes, 2 patches is correct.
> > > 
> > > > So far I have only tested to resume case with the 2 patches to make that
> > > > that is working but on Tegra186, which has been the most
> > > > problematic, it is
> > > > not working reliably on top of next-20250305.
> > > 
> > > To confirm, you're seeing stmmac_reset() sporadically timing out on
> > > resume even with these patches appled? That's rather disappointing.
> > 
> > So I am no longer seeing the reset fail, from what I can see, but now
> > NFS is not responding after resume ...
> > 
> > [?? 49.825094] Enabling non-boot CPUs ...
> > [?? 49.829760] Detected PIPT I-cache on CPU1
> > [?? 49.832694] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU1: 0x0000009444c004
> > [?? 49.844120] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU1: 0x00000010305116
> > [?? 49.856231] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU1: 0x00000003001066
> > [?? 49.868081] CPU1: Booted secondary processor 0x0000000000 [0x4e0f0030]
> > [?? 49.875389] CPU1 is up
> > [?? 49.877187] Detected PIPT I-cache on CPU2
> > [?? 49.880824] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_CTR_EL0. Boot CPU: 0x0000008444c004, CPU2: 0x0000009444c004
> > [?? 49.892266] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_ID_AA64DFR0_EL1. Boot CPU: 0x00000010305106, CPU2: 0x00000010305116
> > [?? 49.904467] CPU features: SANITY CHECK: Unexpected variation in
> > SYS_ID_DFR0_EL1. Boot CPU: 0x00000003010066, CPU2: 0x00000003001066
> > [?? 49.916257] CPU2: Booted secondary processor 0x0000000001 [0x4e0f0030]
> > [?? 49.923610] CPU2 is up
> > [?? 49.925194] Detected PIPT I-cache on CPU3
> > [?? 49.929010] CPU3: Booted secondary processor 0x0000000101 [0x411fd073]
> > [?? 49.935866] CPU3 is up
> > [?? 49.937983] Detected PIPT I-cache on CPU4
> > [?? 49.941824] CPU4: Booted secondary processor 0x0000000102 [0x411fd073]
> > [?? 49.948593] CPU4 is up
> > [?? 49.950810] Detected PIPT I-cache on CPU5
> > [?? 49.954651] CPU5: Booted secondary processor 0x0000000103 [0x411fd073]
> > [?? 49.961431] CPU5 is up
> > [?? 50.069784] dwc-eth-dwmac 2490000.ethernet eth0: configuring for phy/
> > rgmii link mode
> > [?? 50.077634] dwmac4: Master AXI performs any burst length
> > [?? 50.080718] dwc-eth-dwmac 2490000.ethernet eth0: No Safety Features
> > support found
> > [?? 50.088172] dwc-eth-dwmac 2490000.ethernet eth0: IEEE 1588-2008
> > Advanced Timestamp supported
> > [?? 50.096851] dwc-eth-dwmac 2490000.ethernet eth0: Link is Up - 1Gbps/
> > Full - flow control rx/tx
> > [?? 50.110897] usb-conn-gpio 3520000.padctl:ports:usb2-0:connector:
> > repeated role: device
> > [?? 50.113922] tegra-xusb 3530000.usb: Firmware timestamp: 2020-07-06
> > 13:39:28 UTC
> > [?? 50.147552] OOM killer enabled.
> > [?? 50.148441] Restarting tasks ... done.
> > [?? 50.152552] VDDIO_SDMMC3_AP: voltage operation not allowed
> > [?? 50.154761] random: crng reseeded on system resumption
> > [?? 50.162912] PM: suspend exit
> > [?? 50.212215] VDDIO_SDMMC3_AP: voltage operation not allowed
> > [?? 50.271578] VDDIO_SDMMC3_AP: voltage operation not allowed
> > [?? 50.338597] VDDIO_SDMMC3_AP: voltage operation not allowed
> > [? 234.474848] nfs: server 10.26.51.252 not responding, still trying
> > [? 234.538769] nfs: server 10.26.51.252 not responding, still trying
> > [? 237.546922] nfs: server 10.26.51.252 not responding, still trying
> > [? 254.762753] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.762771] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.766376] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.766392] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.783778] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.789582] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.795421] nfs: server 10.26.51.252 not responding, timed out
> > [? 254.801193] nfs: server 10.26.51.252 not responding, timed out
> > 
> > > Do either of the two attached diffs make any difference?
> > 
> > I will try these next.
> 
> 
> I tried both of the diffs, but both had the same problem as above and
> I see these nfs timeouts after resuming. What works the best is the
> original change you proposed (this is based upon the latest two
> patches) ...

I'm wondering whether there's something else which needs the RX clock
running in order to take effect.

> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index e2146d3aee74..48a646b76a29 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3109,10 +3109,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>         if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
>                 priv->plat->dma_cfg->atds = 1;
> -       /* Note that the PHY clock must be running for reset to complete. */
> -       phylink_rx_clk_stop_block(priv->phylink);
>         ret = stmmac_reset(priv, priv->ioaddr);
> -       phylink_rx_clk_stop_unblock(priv->phylink);
>         if (ret) {
>                 netdev_err(priv->dev, "Failed to reset the dma\n");
>                 return ret;
> @@ -7951,6 +7948,8 @@ int stmmac_resume(struct device *dev)
>         rtnl_lock();
>         mutex_lock(&priv->lock);
> +       /* Note that the PHY clock must be running for reset to complete. */
> +       phylink_rx_clk_stop_block(priv->phylink);
>         stmmac_reset_queues_param(priv);
>         stmmac_free_tx_skbufs(priv);
> @@ -7961,6 +7960,7 @@ int stmmac_resume(struct device *dev)
>         stmmac_set_rx_mode(ndev);
>         stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
> +       phylink_rx_clk_stop_unblock(priv->phylink);
>         stmmac_enable_all_queues(priv);
>         stmmac_enable_all_dma_irq(priv);

If you haven't already, can you try shrinking down the number of
functions that are within the block..unblock region please?

Looking at the functions called:

stmmac_reset_queues_param()
stmmac_free_tx_skbufs()
stmmac_clear_descriptors()
	These look like it's only manipulating software state

stmmac_hw_setup()
	We know this calls stmmac_reset() and thus needs the blocking

stmmac_init_coalesce()
	Looks like it's only manipulating software state

stmmac_set_rx_mode()
	This manipulates GMAC_RXQ_CTRL4, GMAC_HASH_TAB(*),
	GMAC_ADDR_HIGH(*), GMAC_ADDR_LOW(*), and GMAC_PACKET_FILTER.

stmmac_restore_hw_vlan_rx_fltr()
	This manipulates GMAC_VLAN_TAG_DATA, GMAC_VLAN_TAG,
	GMAC_VLAN_HASH_TABLE, GMAC_VLAN_TAG

I wonder whether the last two also require the RX clock to be running.

The reason I want to track this down is that we may need to add
block..unblock elsewhere in the driver to ensure that the RX clock
is running when configuration is done elsewhere.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From robin.murphy at arm.com  Tue Mar 11 07:15:56 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 11 Mar 2025 14:15:56 +0000
Subject: [PATCH] iommu/mediatek-v1: Support COMPILE_TEST
Message-ID: <a8d7c0b4393b360ce556f5f15e229d1e2fe73c83.1741702556.git.robin.murphy@arm.com>

Add COMPILE_TEST support to Mediatek v1 so I have less chance of
breaking it again in future. This just needs the ARM dma-iommu API
stubbing out for now.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/Kconfig        |  3 +--
 drivers/iommu/mtk_iommu_v1.c | 11 ++++++++++-
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ec1b5e32b972..d935b59abb35 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -483,8 +483,7 @@ config MTK_IOMMU
 
 config MTK_IOMMU_V1
 	tristate "MediaTek IOMMU Version 1 (M4U gen1) Support"
-	depends on ARM
-	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
 	select ARM_DMA_USE_IOMMU
 	select IOMMU_API
 	select MEMORY
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 3e724e7f10f0..66824982e05f 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -27,11 +27,20 @@
 #include <linux/spinlock.h>
 #include <linux/string_choices.h>
 #include <asm/barrier.h>
-#include <asm/dma-iommu.h>
 #include <dt-bindings/memory/mtk-memory-port.h>
 #include <dt-bindings/memory/mt2701-larb-port.h>
 #include <soc/mediatek/smi.h>
 
+#if defined(CONFIG_ARM)
+#include <asm/dma-iommu.h>
+#else
+#define arm_iommu_create_mapping(...) NULL
+#define arm_iommu_attach_device(...)	-ENODEV
+struct dma_iommu_mapping {
+	struct iommu_domain *domain;
+};
+#endif
+
 #define REG_MMU_PT_BASE_ADDR			0x000
 
 #define F_ALL_INVLD				0x2
-- 
2.39.2.101.g768bb238c484.dirty



From Qun-wei.Lin at mediatek.com  Tue Mar 11 07:12:55 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Tue, 11 Mar 2025 14:12:55 +0000
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4wbgEGKDdUqa8Kpw952qiM_H5V-3X+BH6SboJMh8k2sRg@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
	 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
	 <dubgo2s3xafoitc2olyjqmkmroiowxbpbswefhdioaeupxoqs2@z3s4uuvojvyu>
	 <CAGsJ_4wbgEGKDdUqa8Kpw952qiM_H5V-3X+BH6SboJMh8k2sRg@mail.gmail.com>
Message-ID: <32d951629ab18bcb2cb59b0c0baab65de915dbea.camel@mediatek.com>

On Tue, 2025-03-11 at 22:33 +1300, Barry Song wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Tue, Mar 11, 2025 at 5:58?PM Sergey Senozhatsky
> <senozhatsky at chromium.org> wrote:
> > 
> > On (25/03/08 18:41), Barry Song wrote:
> > > On Sat, Mar 8, 2025 at 12:03?PM Nhat Pham <nphamcs at gmail.com>
> > > wrote:
> > > > 
> > > > On Fri, Mar 7, 2025 at 4:02?AM Qun-Wei Lin
> > > > <qun-wei.lin at mediatek.com> wrote:
> > > > > 
> > > > > This patch series introduces a new mechanism called
> > > > > kcompressd to
> > > > > improve the efficiency of memory reclaiming in the operating
> > > > > system. The
> > > > > main goal is to separate the tasks of page scanning and page
> > > > > compression
> > > > > into distinct processes or threads, thereby reducing the load
> > > > > on the
> > > > > kswapd thread and enhancing overall system performance under
> > > > > high memory
> > > > > pressure conditions.
> > > > 
> > > > Please excuse my ignorance, but from your cover letter I still
> > > > don't
> > > > quite get what is the problem here? And how would decouple
> > > > compression
> > > > and scanning help?
> > > 
> > > My understanding is as follows:
> > > 
> > > When kswapd attempts to reclaim M anonymous folios and N file
> > > folios,
> > > the process involves the following steps:
> > > 
> > > * t1: Time to scan and unmap anonymous folios
> > > * t2: Time to compress anonymous folios
> > > * t3: Time to reclaim file folios
> > > 
> > > Currently, these steps are executed sequentially, meaning the
> > > total time
> > > required to reclaim M + N folios is t1 + t2 + t3.
> > > 
> > > However, Qun-Wei's patch enables t1 + t3 and t2 to run in
> > > parallel,
> > > reducing the total time to max(t1 + t3, t2). This likely improves
> > > the
> > > reclamation speed, potentially reducing allocation stalls.
> > 
> > If compression kthread-s can run (have CPUs to be scheduled on).
> > This looks a bit like a bottleneck.? Is there anything that
> > guarantees forward progress?? Also, if compression kthreads
> > constantly preempt kswapd, then it might not be worth it to
> > have compression kthreads, I assume?
> 
> Thanks for your critical insights, all of which are valuable.
> 
> Qun-Wei is likely working on an Android case where the CPU is
> relatively idle in many scenarios (though there are certainly cases
> where all CPUs are busy), but free memory is quite limited.
> We may soon see benefits for these types of use cases. I expect
> Android might have the opportunity to adopt it before it's fully
> ready upstream.
> 
> If the workload keeps all CPUs busy, I suppose this async thread
> won?t help, but at least we might find a way to mitigate regression.
> 
> We likely need to collect more data on various scenarios?when
> CPUs are relatively idle and when all CPUs are busy?and
> determine the proper approach based on the data, which we
> currently lack :-)
> 

Thanks for the explaining!

> > 
> > If we have a pagefault and need to map a page that is still in
> > the compression queue (not compressed and stored in zram yet, e.g.
> > dut to scheduling latency + slow compression algorithm) then what
> > happens?
> 
> This is happening now even without the patch?? Right now we are
> having 4 steps:
> 1. add_to_swap: The folio is added to the swapcache.
> 2. try_to_unmap: PTEs are converted to swap entries.
> 3. pageout: The folio is written back.
> 4. Swapcache is cleared.
> 
> If a swap-in occurs between 2 and 4, doesn't that mean
> we've already encountered the case where we hit
> the swapcache for a folio undergoing compression?
> 
> It seems we might have an opportunity to terminate
> compression if the request is still in the queue and
> compression hasn?t started for a folio yet? seems
> quite difficult to do?

As Barry explained, these folios that are being compressed are in the
swapcache. If a refault occurs during the compression process, its
correctness is already guaranteed by the swap subsystem (similar to 
other asynchronous swap devices).

Indeed, terminating a folio that is already in the queue waiting for
compression is a challenging task. Will this require some modifications
to the current architecture of swap subsystem?

> 
> Thanks
> Barry

Best Regards,
Qun-wei

From liujianfeng1994 at gmail.com  Tue Mar 11 07:12:39 2025
From: liujianfeng1994 at gmail.com (Jianfeng Liu)
Date: Tue, 11 Mar 2025 22:12:39 +0800
Subject: [PATCH] arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max
Message-ID: <20250311141245.2719796-1-liujianfeng1994@gmail.com>

According to the schematic, pcie reset gpio is GPIO3_D4,
not GPIO4_D4.

Fixes: c600d252dc52 ("arm64: dts: rockchip: Add Orange Pi 5 Max board")
Signed-off-by: Jianfeng Liu <liujianfeng1994 at gmail.com>
---

 arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
index 6e4dcd8fff26..f748c6f760d8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
@@ -64,7 +64,7 @@ &led_blue_pwm {
 
 /* phy2 */
 &pcie2x1l1 {
-	reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
 	vpcie3v3-supply = <&vcc3v3_pcie_eth>;
 	status = "okay";
 };
-- 
2.43.0



From will at kernel.org  Tue Mar 11 07:17:18 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 14:17:18 +0000
Subject: [PATCH] arm64: reserve [_text, _stext) virtual address range
In-Reply-To: <CAMj1kXGgKy=1g1dsN1_yd8JwGZC5SpLUwiJk3GCnZhQ8UtTkKQ@mail.gmail.com>
References: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>
 <20250311125414.GA4601@willie-the-truck>
 <CAMj1kXGgKy=1g1dsN1_yd8JwGZC5SpLUwiJk3GCnZhQ8UtTkKQ@mail.gmail.com>
Message-ID: <20250311141717.GA4931@willie-the-truck>

On Tue, Mar 11, 2025 at 02:32:47PM +0100, Ard Biesheuvel wrote:
> On Tue, 11 Mar 2025 at 13:54, Will Deacon <will at kernel.org> wrote:
> >
> > [+Ard]
> >
> > On Mon, Mar 10, 2025 at 01:05:04PM -0700, Omar Sandoval wrote:
> > > From: Omar Sandoval <osandov at fb.com>
> > >
> > > Since the referenced fixes commit, the kernel's .text section is only
> > > mapped starting from _stext; the region [_text, _stext) is omitted. As a
> > > result, other vmalloc/vmap allocations may use the virtual addresses
> > > nominally in the range [_text, _stext). This address reuse confuses
> > > multiple things:
> > >
> > > 1. crash_prepare_elf64_headers() sets up a segment in /proc/vmcore
> > >    mapping the entire range [_text, _end) to
> > >    [__pa_symbol(_text), __pa_symbol(_end)). Reading an address in
> > >    [_text, _stext) from /proc/vmcore therefore gives the incorrect
> > >    result.

[...]

> > > @@ -765,13 +769,17 @@ core_initcall(map_entry_trampoline);
> > >   */
> > >  static void __init declare_kernel_vmas(void)
> > >  {
> > > -     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];
> > > +     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT + 1];
> > >
> > > -     declare_vma(&vmlinux_seg[0], _stext, _etext, VM_NO_GUARD);
> > > -     declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
> > > -     declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
> > > -     declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
> > > -     declare_vma(&vmlinux_seg[4], _data, _end, 0);
> > > +     declare_vma(&vmlinux_seg[0], _text, _stext, VM_NO_GUARD);
> >
> > Should we also put the memblock reservation back as it was, so that this
> > region can't be allocated there?
> >
> 
> The issue is about the virtual address space, not the physical memory
> behind it, right? So the VA range should be protected from reuse, but
> nothing needs to be mapped there.

You're absolutely right, but now I'm more confused about the reference
to crash_prepare_elf64_headers() in the commit message. That sets both
the virtual (_text) and the physical (__pa_symbol(_text)) addresses in
the header, so it feels like we really need to keep that memory around
because it's accessible via /proc/vmcore.

> 
> > In fact, if we're not allocating from here, why don't we just map it
> > anyway but without execute permissions?
> >
> 
> It's just 64k so if this is the simplest approach, I won't object.
> 
> I wonder if this needs to be so intrusive, though - there is already a
> precedent of VMAs not actually mapping the entire region they describe
> (with guard pages), and so we might just declare the first VMA as
> [_text, _etext), even though the first 64k of that region is not not
> actually mapped.
> 
> However, if that confuses the bookkeeping or creates other problems,
> declaring a separate VMA to reserve the VA range seems fine, although
> the patch seems a bit intrusive (and I don't even see the whole
> thing).

As above, I think we'll have to give /proc/vmcore the physical address
of _something_.

Will


From robin.murphy at arm.com  Tue Mar 11 07:21:05 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 11 Mar 2025 14:21:05 +0000
Subject: [PATCH] iommu: Unexport iommu_fwspec_free()
In-Reply-To: <Z9A3WJSgUPjROev6@8bytes.org>
References: <36e245489361de2d13db22a510fa5c79e7126278.1740667667.git.robin.murphy@arm.com>
 <Z9A3WJSgUPjROev6@8bytes.org>
Message-ID: <d8d7c381-b3e6-4259-b1f4-ff06328df0a0@arm.com>

On 11/03/2025 1:15 pm, Joerg Roedel wrote:
> This patch triggered two compile issues on ARM32, which I fixed up in my
> tree:
> 
> On Thu, Feb 27, 2025 at 02:47:47PM +0000, Robin Murphy wrote:
>>   static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev)
>>   {
>> -	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>> +	struct iommu_fwspec *fwspec = NULL
> 
> Missing semicolon here.
> 
>>   	struct of_phandle_args iommu_spec;
>>   	struct mtk_iommu_v1_data *data;
>>   	int err, idx = 0, larbid, larbidx;
>>   	struct device_link *link;
>>   	struct device *larbdev;
>>   
>> -	/*
>> -	 * In the deferred case, free the existed fwspec.
>> -	 * Always initialize the fwspec internally.
>> -	 */
>> -	if (fwspec) {
>> -		iommu_fwspec_free(dev);
>> -		fwspec = dev_iommu_fwspec_get(dev);
>> -	}
>> -
>>   	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
>>   					   "#iommu-cells",
>>   					   idx, &iommu_spec)) {
>> @@ -476,6 +467,9 @@ static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev)
>>   		idx++;
>>   	}
>>   
>> +	if (!fwspec)
>> +		return -ENODEV;
>> +
> 
> Wrong return type here.
> 
> Please be more cautious next time and make sure to compile-test all
> changed files of a patch.

Oops, sorry, indeed that was a failure of my process - seems I need to 
be more diligent about COMPILE_TEST. Patch sent :)

Thanks a lot for the fixups!

Robin.


From liujianfeng1994 at gmail.com  Tue Mar 11 07:27:50 2025
From: liujianfeng1994 at gmail.com (Jianfeng Liu)
Date: Tue, 11 Mar 2025 22:27:50 +0800
Subject: [PATCH] arm64: dts: rockchip: Add AP6275P wireless support to ArmSoM Sige7
Message-ID: <20250311142825.2727171-1-liujianfeng1994@gmail.com>

ArmSoM Sige7 uses the PCI-e AP6275P Wi-Fi 6 module. The pcie at 0 node can
be used as Bridge1, so the wifi at 0 node is used as a device under the
Bridege 1 similar with Khadas Edge 2.

Signed-off-by: Jianfeng Liu <liujianfeng1994 at gmail.com>
---

 .../boot/dts/rockchip/rk3588-armsom-sige7.dts    | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 6a0fffaa26ee..face42bb0d7d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -300,6 +300,22 @@ &pcie2x1l0 {
 &pcie2x1l1 {
 	reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
 	status = "okay";
+
+	pcie at 0,0 {
+		reg = <0x300000 0 0 0 0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+		device_type = "pci";
+		bus-range = <0x30 0x3f>;
+
+		wifi: wifi at 0,0 {
+			compatible = "pci14e4,449d";
+			reg = <0x310000 0 0 0 0>;
+			clocks = <&hym8563>;
+			clock-names = "lpo";
+		};
+	};
 };
 
 /* phy0 - left ethernet port */
-- 
2.43.0



From Qun-wei.Lin at mediatek.com  Tue Mar 11 07:33:45 2025
From: Qun-wei.Lin at mediatek.com (=?utf-8?B?UXVuLXdlaSBMaW4gKOael+e+pOW0tCk=?=)
Date: Tue, 11 Mar 2025 14:33:45 +0000
Subject: [PATCH 2/2] kcompressd: Add Kcompressd for accelerated zram
 compression
In-Reply-To: <CAGsJ_4zzZdjbr2DbRybHYDmL2EuUBohOP1=ho7fjx1XWoKDDGw@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
	 <20250307120141.1566673-3-qun-wei.lin@mediatek.com>
	 <CAGsJ_4xtp9iGPQinu5DOi3R2B47X9o=wS94GdhdY-0JUATf5hw@mail.gmail.com>
	 <7938f840136165be1c50050feb39fb14ee37721b.camel@mediatek.com>
	 <CAGsJ_4zzZdjbr2DbRybHYDmL2EuUBohOP1=ho7fjx1XWoKDDGw@mail.gmail.com>
Message-ID: <653c5ace4e5154e923b9f50c5e820c8fdb07aaf4.camel@mediatek.com>

On Tue, 2025-03-11 at 20:05 +1300, Barry Song wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Tue, Mar 11, 2025 at 2:26?AM Qun-wei Lin (???)
> <Qun-wei.Lin at mediatek.com> wrote:
> > 
> > On Sat, 2025-03-08 at 08:41 +1300, Barry Song wrote:
> > > 
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Sat, Mar 8, 2025 at 1:02?AM Qun-Wei Lin
> > > <qun-wei.lin at mediatek.com>
> > > wrote:
> > > > 
> > > > Introduced Kcompressd to offload zram page compression,
> > > > improving
> > > > system efficiency by handling compression separately from
> > > > memory
> > > > reclaiming. Added necessary configurations and dependencies.
> > > > 
> > > > Signed-off-by: Qun-Wei Lin <qun-wei.lin at mediatek.com>
> > > > ---
> > > > ?drivers/block/zram/Kconfig????? |? 11 ++
> > > > ?drivers/block/zram/Makefile???? |?? 3 +-
> > > > ?drivers/block/zram/kcompressd.c | 340
> > > > ++++++++++++++++++++++++++++++++
> > > > ?drivers/block/zram/kcompressd.h |? 25 +++
> > > > ?drivers/block/zram/zram_drv.c?? |? 22 ++-
> > > > ?5 files changed, 397 insertions(+), 4 deletions(-)
> > > > ?create mode 100644 drivers/block/zram/kcompressd.c
> > > > ?create mode 100644 drivers/block/zram/kcompressd.h
> > > > 
> > > > diff --git a/drivers/block/zram/Kconfig
> > > > b/drivers/block/zram/Kconfig
> > > > index 402b7b175863..f0a1b574f770 100644
> > > > --- a/drivers/block/zram/Kconfig
> > > > +++ b/drivers/block/zram/Kconfig
> > > > @@ -145,3 +145,14 @@ config ZRAM_MULTI_COMP
> > > > ????????? re-compress pages using a potentially slower but more
> > > > effective
> > > > ????????? compression algorithm. Note, that IDLE page
> > > > recompression
> > > > ????????? requires ZRAM_TRACK_ENTRY_ACTIME.
> > > > +
> > > > +config KCOMPRESSD
> > > > +?????? tristate "Kcompressd: Accelerated zram compression"
> > > > +?????? depends on ZRAM
> > > > +?????? help
> > > > +???????? Kcompressd creates multiple daemons to accelerate the
> > > > compression of pages
> > > > +???????? in zram, offloading this time-consuming task from the
> > > > zram driver.
> > > > +
> > > > +???????? This approach improves system efficiency by handling
> > > > page
> > > > compression separately,
> > > > +???????? which was originally done by kswapd or direct
> > > > reclaim.
> > > 
> > > For direct reclaim, we were previously able to compress using
> > > multiple CPUs
> > > with multi-threading.
> > > After your patch, it seems that only a single thread/CPU is used
> > > for
> > > compression
> > > so it won't necessarily improve direct reclaim performance?
> > > 
> > 
> > Our patch only splits the context of kswapd. When direct reclaim is
> > occurred, it is bypassed, so direct reclaim remains unchanged, with
> > each thread that needs memory directly reclaiming it.
> 
> Qun-wei, I?m getting a bit confused. Looking at the code in
> page_io.c,
> you always call swap_writepage_bdev_async() no matter if it is kswapd
> or direct reclaim:
> 
> - else if (data_race(sis->flags & SWP_SYNCHRONOUS_IO))
> + else if (data_race(sis->flags & SWP_WRITE_SYNCHRONOUS_IO))
> ?????????? swap_writepage_bdev_sync(folio, wbc, sis);
> ? else
> ??????????? swap_writepage_bdev_async(folio, wbc, sis);
> 
> In zram, I notice you are bypassing kcompressd by:
> 
> + if (!nr_kcompressd || !current_is_kswapd())
> +??????? return -EBUSY;
> 
> How will this work if no one is calling __end_swap_bio_write(&bio),
> which is present in swap_writepage_bdev_sync()?
> Am I missing something? Or is it done by zram_bio_write() ?
> 

In swap_writepage_bdev_async(), 'bio->bi_end_io = end_swap_bio_write'
is set. So yes, the bio_endio(bio) in zram_bio_write() will handle
this.

> On the other hand, zram is a generic block device, and coupling its
> code with kswapd/direct reclaim somehow violates layering
> principles :-)

OK, so it seems that moving kcompressd to the vmscan level might
resolve this issue, right?


> > 
> > > Even for kswapd, we used to have multiple threads like [kswapd0],
> > > [kswapd1],
> > > and [kswapd2] for different nodes. Now, are we also limited to
> > > just
> > > one thread?
> > 
> > We only considered a single kswapd here and didn't account for
> > multiple
> > instances. Since I use kfifo to collect the bios, if there are
> > multiple
> > kswapds, we need to add a lock to protect the bio queue. I can
> > revise
> > this in the 2nd version, or do you have any other suggested
> > approaches?
> 
> I'm wondering if we can move the code to vmscan/page_io instead
> of zram. If we're using a sync I/O swap device or have enabled zswap,
> we could run reclamation in this separate thread, which should also
> be
> NUMA-aware.
> 
> I would definitely be interested in prototyping it when I have the
> time.

Thank you so much!

> 
> > 
> > > I also wonder if this could be handled at the vmscan level
> > > instead of
> > > the zram
> > > level. then it might potentially help other sync devices or even
> > > zswap later.
> > > 
> > > But I agree that for phones, modifying zram seems like an easier
> > > starting
> > > point. However, relying on a single thread isn't always the best
> > > approach.
> > > 
> > > 
> > > > +
> > > > diff --git a/drivers/block/zram/Makefile
> > > > b/drivers/block/zram/Makefile
> > > > index 0fdefd576691..23baa5dfceb9 100644
> > > > --- a/drivers/block/zram/Makefile
> > > > +++ b/drivers/block/zram/Makefile
> > > > @@ -9,4 +9,5 @@ zram-$(CONFIG_ZRAM_BACKEND_ZSTD)??????? +=
> > > > backend_zstd.o
> > > > ?zram-$(CONFIG_ZRAM_BACKEND_DEFLATE)??? += backend_deflate.o
> > > > ?zram-$(CONFIG_ZRAM_BACKEND_842)??????????????? +=
> > > > backend_842.o
> > > > 
> > > > -obj-$(CONFIG_ZRAM)???? +=????? zram.o
> > > > +obj-$(CONFIG_ZRAM)???????????? += zram.o
> > > > +obj-$(CONFIG_KCOMPRESSD)?????? += kcompressd.o
> > > > diff --git a/drivers/block/zram/kcompressd.c
> > > > b/drivers/block/zram/kcompressd.c
> > > > new file mode 100644
> > > > index 000000000000..195b7e386869
> > > > --- /dev/null
> > > > +++ b/drivers/block/zram/kcompressd.c
> > > > @@ -0,0 +1,340 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * Copyright (C) 2024 MediaTek Inc.
> > > > + */
> > > > +
> > > > +#include <linux/module.h>
> > > > +#include <linux/kernel.h>
> > > > +#include <linux/bio.h>
> > > > +#include <linux/bitops.h>
> > > > +#include <linux/freezer.h>
> > > > +#include <linux/kernel.h>
> > > > +#include <linux/psi.h>
> > > > +#include <linux/kfifo.h>
> > > > +#include <linux/swap.h>
> > > > +#include <linux/delay.h>
> > > > +
> > > > +#include "kcompressd.h"
> > > > +
> > > > +#define INIT_QUEUE_SIZE??????????????? 4096
> > > > +#define DEFAULT_NR_KCOMPRESSD? 4
> > > > +
> > > > +static atomic_t enable_kcompressd;
> > > > +static unsigned int nr_kcompressd;
> > > > +static unsigned int queue_size_per_kcompressd;
> > > > +static struct kcompress *kcompress;
> > > > +
> > > > +enum run_state {
> > > > +?????? KCOMPRESSD_NOT_STARTED = 0,
> > > > +?????? KCOMPRESSD_RUNNING,
> > > > +?????? KCOMPRESSD_SLEEPING,
> > > > +};
> > > > +
> > > > +struct kcompressd_para {
> > > > +?????? wait_queue_head_t *kcompressd_wait;
> > > > +?????? struct kfifo *write_fifo;
> > > > +?????? atomic_t *running;
> > > > +};
> > > > +
> > > > +static struct kcompressd_para *kcompressd_para;
> > > > +static BLOCKING_NOTIFIER_HEAD(kcompressd_notifier_list);
> > > > +
> > > > +struct write_work {
> > > > +?????? void *mem;
> > > > +?????? struct bio *bio;
> > > > +?????? compress_callback cb;
> > > > +};
> > > > +
> > > > +int kcompressd_enabled(void)
> > > > +{
> > > > +?????? return likely(atomic_read(&enable_kcompressd));
> > > > +}
> > > > +EXPORT_SYMBOL(kcompressd_enabled);
> > > > +
> > > > +static void kcompressd_try_to_sleep(struct kcompressd_para *p)
> > > > +{
> > > > +?????? DEFINE_WAIT(wait);
> > > > +
> > > > +?????? if (!kfifo_is_empty(p->write_fifo))
> > > > +?????????????? return;
> > > > +
> > > > +?????? if (freezing(current) || kthread_should_stop())
> > > > +?????????????? return;
> > > > +
> > > > +?????? atomic_set(p->running, KCOMPRESSD_SLEEPING);
> > > > +?????? prepare_to_wait(p->kcompressd_wait, &wait,
> > > > TASK_INTERRUPTIBLE);
> > > > +
> > > > +?????? /*
> > > > +??????? * After a short sleep, check if it was a premature
> > > > sleep.
> > > > If not, then
> > > > +??????? * go fully to sleep until explicitly woken up.
> > > > +??????? */
> > > > +?????? if (!kthread_should_stop() && kfifo_is_empty(p-
> > > > > write_fifo))
> > > > +?????????????? schedule();
> > > > +
> > > > +?????? finish_wait(p->kcompressd_wait, &wait);
> > > > +?????? atomic_set(p->running, KCOMPRESSD_RUNNING);
> > > > +}
> > > > +
> > > > +static int kcompressd(void *para)
> > > > +{
> > > > +?????? struct task_struct *tsk = current;
> > > > +?????? struct kcompressd_para *p = (struct kcompressd_para
> > > > *)para;
> > > > +
> > > > +?????? tsk->flags |= PF_MEMALLOC | PF_KSWAPD;
> > > > +?????? set_freezable();
> > > > +
> > > > +?????? while (!kthread_should_stop()) {
> > > > +?????????????? bool ret;
> > > > +
> > > > +?????????????? kcompressd_try_to_sleep(p);
> > > > +?????????????? ret = try_to_freeze();
> > > > +?????????????? if (kthread_should_stop())
> > > > +?????????????????????? break;
> > > > +
> > > > +?????????????? if (ret)
> > > > +?????????????????????? continue;
> > > > +
> > > > +?????????????? while (!kfifo_is_empty(p->write_fifo)) {
> > > > +?????????????????????? struct write_work entry;
> > > > +
> > > > +?????????????????????? if (sizeof(struct write_work) ==
> > > > kfifo_out(p->write_fifo,
> > > > +?????????????????????????????????????????????? &entry,
> > > > sizeof(struct write_work))) {
> > > > +?????????????????????????????? entry.cb(entry.mem, entry.bio);
> > > > +?????????????????????????????? bio_put(entry.bio);
> > > > +?????????????????????? }
> > > > +?????????????? }
> > > > +
> > > > +?????? }
> > > > +
> > > > +?????? tsk->flags &= ~(PF_MEMALLOC | PF_KSWAPD);
> > > > +?????? atomic_set(p->running, KCOMPRESSD_NOT_STARTED);
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static int init_write_queue(void)
> > > > +{
> > > > +?????? int i;
> > > > +?????? unsigned int queue_len = queue_size_per_kcompressd *
> > > > sizeof(struct write_work);
> > > > +
> > > > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > > > +?????????????? if (kfifo_alloc(&kcompress[i].write_fifo,
> > > > +?????????????????????????????????????? queue_len, GFP_KERNEL))
> > > > {
> > > > +?????????????????????? pr_err("Failed to alloc kfifo %d\n",
> > > > i);
> > > > +?????????????????????? return -ENOMEM;
> > > > +?????????????? }
> > > > +?????? }
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static void clean_bio_queue(int idx)
> > > > +{
> > > > +?????? struct write_work entry;
> > > > +
> > > > +?????? while (sizeof(struct write_work) ==
> > > > kfifo_out(&kcompress[idx].write_fifo,
> > > > +?????????????????????????????? &entry, sizeof(struct
> > > > write_work)))
> > > > {
> > > > +?????????????? bio_put(entry.bio);
> > > > +?????????????? entry.cb(entry.mem, entry.bio);
> > > > +?????? }
> > > > +?????? kfifo_free(&kcompress[idx].write_fifo);
> > > > +}
> > > > +
> > > > +static int kcompress_update(void)
> > > > +{
> > > > +?????? int i;
> > > > +?????? int ret;
> > > > +
> > > > +?????? kcompress = kvmalloc_array(nr_kcompressd, sizeof(struct
> > > > kcompress), GFP_KERNEL);
> > > > +?????? if (!kcompress)
> > > > +?????????????? return -ENOMEM;
> > > > +
> > > > +?????? kcompressd_para = kvmalloc_array(nr_kcompressd,
> > > > sizeof(struct kcompressd_para), GFP_KERNEL);
> > > > +?????? if (!kcompressd_para)
> > > > +?????????????? return -ENOMEM;
> > > > +
> > > > +?????? ret = init_write_queue();
> > > > +?????? if (ret) {
> > > > +?????????????? pr_err("Initialization of writing to FIFOs
> > > > failed!!\n");
> > > > +?????????????? return ret;
> > > > +?????? }
> > > > +
> > > > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > > > +??????????????
> > > > init_waitqueue_head(&kcompress[i].kcompressd_wait);
> > > > +?????????????? kcompressd_para[i].kcompressd_wait =
> > > > &kcompress[i].kcompressd_wait;
> > > > +?????????????? kcompressd_para[i].write_fifo =
> > > > &kcompress[i].write_fifo;
> > > > +?????????????? kcompressd_para[i].running =
> > > > &kcompress[i].running;
> > > > +?????? }
> > > > +
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static void stop_all_kcompressd_thread(void)
> > > > +{
> > > > +?????? int i;
> > > > +
> > > > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > > > +?????????????? kthread_stop(kcompress[i].kcompressd);
> > > > +?????????????? kcompress[i].kcompressd = NULL;
> > > > +?????????????? clean_bio_queue(i);
> > > > +?????? }
> > > > +}
> > > > +
> > > > +static int do_nr_kcompressd_handler(const char *val,
> > > > +?????????????? const struct kernel_param *kp)
> > > > +{
> > > > +?????? int ret;
> > > > +
> > > > +?????? atomic_set(&enable_kcompressd, false);
> > > > +
> > > > +?????? stop_all_kcompressd_thread();
> > > > +
> > > > +?????? ret = param_set_int(val, kp);
> > > > +?????? if (!ret) {
> > > > +?????????????? pr_err("Invalid number of kcompressd.\n");
> > > > +?????????????? return -EINVAL;
> > > > +?????? }
> > > > +
> > > > +?????? ret = init_write_queue();
> > > > +?????? if (ret) {
> > > > +?????????????? pr_err("Initialization of writing to FIFOs
> > > > failed!!\n");
> > > > +?????????????? return ret;
> > > > +?????? }
> > > > +
> > > > +?????? atomic_set(&enable_kcompressd, true);
> > > > +
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static const struct kernel_param_ops
> > > > param_ops_change_nr_kcompressd = {
> > > > +?????? .set = &do_nr_kcompressd_handler,
> > > > +?????? .get = &param_get_uint,
> > > > +?????? .free = NULL,
> > > > +};
> > > > +
> > > > +module_param_cb(nr_kcompressd,
> > > > &param_ops_change_nr_kcompressd,
> > > > +?????????????? &nr_kcompressd, 0644);
> > > > +MODULE_PARM_DESC(nr_kcompressd, "Number of pre-created daemon
> > > > for
> > > > page compression");
> > > > +
> > > > +static int do_queue_size_per_kcompressd_handler(const char
> > > > *val,
> > > > +?????????????? const struct kernel_param *kp)
> > > > +{
> > > > +?????? int ret;
> > > > +
> > > > +?????? atomic_set(&enable_kcompressd, false);
> > > > +
> > > > +?????? stop_all_kcompressd_thread();
> > > > +
> > > > +?????? ret = param_set_int(val, kp);
> > > > +?????? if (!ret) {
> > > > +?????????????? pr_err("Invalid queue size for kcompressd.\n");
> > > > +?????????????? return -EINVAL;
> > > > +?????? }
> > > > +
> > > > +?????? ret = init_write_queue();
> > > > +?????? if (ret) {
> > > > +?????????????? pr_err("Initialization of writing to FIFOs
> > > > failed!!\n");
> > > > +?????????????? return ret;
> > > > +?????? }
> > > > +
> > > > +?????? pr_info("Queue size for kcompressd was changed: %d\n",
> > > > queue_size_per_kcompressd);
> > > > +
> > > > +?????? atomic_set(&enable_kcompressd, true);
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static const struct kernel_param_ops
> > > > param_ops_change_queue_size_per_kcompressd = {
> > > > +?????? .set = &do_queue_size_per_kcompressd_handler,
> > > > +?????? .get = &param_get_uint,
> > > > +?????? .free = NULL,
> > > > +};
> > > > +
> > > > +module_param_cb(queue_size_per_kcompressd,
> > > > &param_ops_change_queue_size_per_kcompressd,
> > > > +?????????????? &queue_size_per_kcompressd, 0644);
> > > > +MODULE_PARM_DESC(queue_size_per_kcompressd,
> > > > +?????????????? "Size of queue for kcompressd");
> > > > +
> > > > +int schedule_bio_write(void *mem, struct bio *bio,
> > > > compress_callback cb)
> > > > +{
> > > > +?????? int i;
> > > > +?????? bool submit_success = false;
> > > > +?????? size_t sz_work = sizeof(struct write_work);
> > > > +
> > > > +?????? struct write_work entry = {
> > > > +?????????????? .mem = mem,
> > > > +?????????????? .bio = bio,
> > > > +?????????????? .cb = cb
> > > > +?????? };
> > > > +
> > > > +?????? if (unlikely(!atomic_read(&enable_kcompressd)))
> > > > +?????????????? return -EBUSY;
> > > > +
> > > > +?????? if (!nr_kcompressd || !current_is_kswapd())
> > > > +?????????????? return -EBUSY;
> > > > +
> > > > +?????? bio_get(bio);
> > > > +
> > > > +?????? for (i = 0; i < nr_kcompressd; i++) {
> > > > +?????????????? submit_success =
> > > > +?????????????????????? (kfifo_avail(&kcompress[i].write_fifo)
> > > > >=
> > > > sz_work) &&
> > > > +?????????????????????? (sz_work ==
> > > > kfifo_in(&kcompress[i].write_fifo, &entry, sz_work));
> > > > +
> > > > +?????????????? if (submit_success) {
> > > > +?????????????????????? switch
> > > > (atomic_read(&kcompress[i].running))
> > > > {
> > > > +?????????????????????? case KCOMPRESSD_NOT_STARTED:
> > > > +??????????????????????????????
> > > > atomic_set(&kcompress[i].running,
> > > > KCOMPRESSD_RUNNING);
> > > > +?????????????????????????????? kcompress[i].kcompressd =
> > > > kthread_run(kcompressd,
> > > > +
> > > > &kcompressd_para[i], "kcompressd:%d", i);
> > > > +?????????????????????????????? if
> > > > (IS_ERR(kcompress[i].kcompressd)) {
> > > > +
> > > > atomic_set(&kcompress[i].running, KCOMPRESSD_NOT_STARTED);
> > > > +?????????????????????????????????????? pr_warn("Failed to
> > > > start
> > > > kcompressd:%d\n", i);
> > > > +?????????????????????????????????????? clean_bio_queue(i);
> > > > +?????????????????????????????? }
> > > > +?????????????????????????????? break;
> > > > +?????????????????????? case KCOMPRESSD_RUNNING:
> > > > +?????????????????????????????? break;
> > > > +?????????????????????? case KCOMPRESSD_SLEEPING:
> > > > +
> > > > wake_up_interruptible(&kcompress[i].kcompressd_wait);
> > > > +?????????????????????????????? break;
> > > > +?????????????????????? }
> > > > +?????????????????????? return 0;
> > > > +?????????????? }
> > > > +?????? }
> > > > +
> > > > +?????? bio_put(bio);
> > > > +?????? return -EBUSY;
> > > > +}
> > > > +EXPORT_SYMBOL(schedule_bio_write);
> > > > +
> > > > +static int __init kcompressd_init(void)
> > > > +{
> > > > +?????? int ret;
> > > > +
> > > > +?????? nr_kcompressd = DEFAULT_NR_KCOMPRESSD;
> > > > +?????? queue_size_per_kcompressd = INIT_QUEUE_SIZE;
> > > > +
> > > > +?????? ret = kcompress_update();
> > > > +?????? if (ret) {
> > > > +?????????????? pr_err("Init kcompressd failed!\n");
> > > > +?????????????? return ret;
> > > > +?????? }
> > > > +
> > > > +?????? atomic_set(&enable_kcompressd, true);
> > > > +?????? blocking_notifier_call_chain(&kcompressd_notifier_list,
> > > > 0,
> > > > NULL);
> > > > +?????? return 0;
> > > > +}
> > > > +
> > > > +static void __exit kcompressd_exit(void)
> > > > +{
> > > > +?????? atomic_set(&enable_kcompressd, false);
> > > > +?????? stop_all_kcompressd_thread();
> > > > +
> > > > +?????? kvfree(kcompress);
> > > > +?????? kvfree(kcompressd_para);
> > > > +}
> > > > +
> > > > +module_init(kcompressd_init);
> > > > +module_exit(kcompressd_exit);
> > > > +
> > > > +MODULE_LICENSE("Dual BSD/GPL");
> > > > +MODULE_AUTHOR("Qun-Wei Lin <qun-wei.lin at mediatek.com>");
> > > > +MODULE_DESCRIPTION("Separate the page compression from the
> > > > memory
> > > > reclaiming");
> > > > +
> > > > diff --git a/drivers/block/zram/kcompressd.h
> > > > b/drivers/block/zram/kcompressd.h
> > > > new file mode 100644
> > > > index 000000000000..2fe0b424a7af
> > > > --- /dev/null
> > > > +++ b/drivers/block/zram/kcompressd.h
> > > > @@ -0,0 +1,25 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > > +/*
> > > > + * Copyright (C) 2024 MediaTek Inc.
> > > > + */
> > > > +
> > > > +#ifndef _KCOMPRESSD_H_
> > > > +#define _KCOMPRESSD_H_
> > > > +
> > > > +#include <linux/rwsem.h>
> > > > +#include <linux/kfifo.h>
> > > > +#include <linux/atomic.h>
> > > > +
> > > > +typedef void (*compress_callback)(void *mem, struct bio *bio);
> > > > +
> > > > +struct kcompress {
> > > > +?????? struct task_struct *kcompressd;
> > > > +?????? wait_queue_head_t kcompressd_wait;
> > > > +?????? struct kfifo write_fifo;
> > > > +?????? atomic_t running;
> > > > +};
> > > > +
> > > > +int kcompressd_enabled(void);
> > > > +int schedule_bio_write(void *mem, struct bio *bio,
> > > > compress_callback cb);
> > > > +#endif
> > > > +
> > > > diff --git a/drivers/block/zram/zram_drv.c
> > > > b/drivers/block/zram/zram_drv.c
> > > > index 2e1a70f2f4bd..bcd63ecb6ff2 100644
> > > > --- a/drivers/block/zram/zram_drv.c
> > > > +++ b/drivers/block/zram/zram_drv.c
> > > > @@ -35,6 +35,7 @@
> > > > ?#include <linux/part_stat.h>
> > > > ?#include <linux/kernel_read_file.h>
> > > > 
> > > > +#include "kcompressd.h"
> > > > ?#include "zram_drv.h"
> > > > 
> > > > ?static DEFINE_IDR(zram_index_idr);
> > > > @@ -2240,6 +2241,15 @@ static void zram_bio_write(struct zram
> > > > *zram, struct bio *bio)
> > > > ??????? bio_endio(bio);
> > > > ?}
> > > > 
> > > > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > > > +static void zram_bio_write_callback(void *mem, struct bio
> > > > *bio)
> > > > +{
> > > > +?????? struct zram *zram = (struct zram *)mem;
> > > > +
> > > > +?????? zram_bio_write(zram, bio);
> > > > +}
> > > > +#endif
> > > > +
> > > > ?/*
> > > > ? * Handler function for all zram I/O requests.
> > > > ? */
> > > > @@ -2252,6 +2262,10 @@ static void zram_submit_bio(struct bio
> > > > *bio)
> > > > ??????????????? zram_bio_read(zram, bio);
> > > > ??????????????? break;
> > > > ??????? case REQ_OP_WRITE:
> > > > +#if IS_ENABLED(CONFIG_KCOMPRESSD)
> > > > +?????????????? if (kcompressd_enabled() &&
> > > > !schedule_bio_write(zram, bio, zram_bio_write_callback))
> > > > +?????????????????????? break;
> > > > +#endif
> > > > ??????????????? zram_bio_write(zram, bio);
> > > > ??????????????? break;
> > > > ??????? case REQ_OP_DISCARD:
> > > > @@ -2535,9 +2549,11 @@ static int zram_add(void)
> > > > ?#if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
> > > > ??????????????? .max_write_zeroes_sectors?????? = UINT_MAX,
> > > > ?#endif
> > > > -?????????????? .features?????????????????????? =
> > > > BLK_FEAT_STABLE_WRITES??????? |
> > > > -
> > > > BLK_FEAT_READ_SYNCHRONOUS???? |
> > > > -
> > > > BLK_FEAT_WRITE_SYNCHRONOUS,
> > > > +?????????????? .features?????????????????????? =
> > > > BLK_FEAT_STABLE_WRITES
> > > > +???????????????????????????????????????????????? |
> > > > BLK_FEAT_READ_SYNCHRONOUS
> > > > +#if !IS_ENABLED(CONFIG_KCOMPRESSD)
> > > > +???????????????????????????????????????????????? |
> > > > BLK_FEAT_WRITE_SYNCHRONOUS,
> > > > +#endif
> > > > ??????? };
> > > > ??????? struct zram *zram;
> > > > ??????? int ret, device_id;
> > > > --
> > > > 2.45.2
> > > > 
> > > 
> 
> Thanks
> Barry

Best Regards,
Qun-wei


From andrea.porta at suse.com  Tue Mar 11 07:36:53 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Tue, 11 Mar 2025 15:36:53 +0100
Subject: [PATCH v7 03/11] dt-bindings: pci: Add common schema for devices
 accessible through PCI BARs
In-Reply-To: <CAL_JsqKPGOdS_8KDggO5tBHAnC-NTLAC5iS9GANm9BuxBfQUsw@mail.gmail.com>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <c0acc51a7210fb30cae7b26f4ad1f0449beed95e.1738963156.git.andrea.porta@suse.com>
 <20250310212125.GB2377483@rocinante>
 <CAL_JsqKPGOdS_8KDggO5tBHAnC-NTLAC5iS9GANm9BuxBfQUsw@mail.gmail.com>
Message-ID: <Z9BKhR5exw13yN36@apocalypse>

Hi Rob,

On 08:32 Tue 11 Mar     , Rob Herring wrote:
> On Mon, Mar 10, 2025 at 4:21?PM Krzysztof Wilczynski <kw at linux.com> wrote:
> >
> > Hello,
> >
> > [...]
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index d45c88955072..af2e4652bf3b 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -19752,6 +19752,7 @@ RASPBERRY PI RP1 PCI DRIVER
> > >  M:   Andrea della Porta <andrea.porta at suse.com>
> > >  S:   Maintained
> > >  F:   Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
> > > +F:   Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
> > >  F:   Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
> > >  F:   include/dt-bindings/clock/rp1.h
> > >  F:   include/dt-bindings/misc/rp1.h
> >
> > I would be happy to pick this via the PCI tree as per the standard
> > operating procedure.  However, the MAINTAINERS changes do not exist
> > for us yet, and are added in the first patch of the series, which is
> > not ideal.
> >
> > I can add the missing dependency manually, but that would cause issues
> > for linux-next tree, which is also not ideal.
> >
> > I saw some review feedback, as such, when you are going to be sending
> > another version, can you make MAINTAINERS changes to be the last patch,
> > perhaps.  Basically, something standalone that perhaps whoever will pick
> > the misc patch could also pick and apply at the same time.
> >
> > Alternatively, someone else picking up the PCI dt-bindings would work, too.
> >
> > Your thoughts?
> 
> I guess I missed this in review, but why is a common schema buried in
> a device maintainer entry? Also, an entry in MAINTAINERS is redundant
> anyway because get_maintainers.pl can fetch maintainers from the
> schema file.

Oh nice, I've added all that .yaml entries in MAINTAINERS because I saw many
reference already existing there, so I was thinking that was a good behaviour.
Now I guess I can get rid of all .yaml references in MAINTAINERS file from all my
patches, since they will be solved automatically by get_mainatainer.pl... 
There's only one minor caveat though: I have a middle name, and it turns out
that get_maintainer.pl is skipping my first name. Unluckily I'm not a Perl guy
so I guess I have to dive a little bit in Perl regex and send a separate patch
for that.

Many thanks,
Andrea

> 
> Rob


From sudeep.holla at arm.com  Tue Mar 11 07:41:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 14:41:24 +0000
Subject: [PATCH v12 0/4] Support SMT control on arm64
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <Z9BLlOgL3RFLCFnz@bogus>

On Tue, Mar 11, 2025 at 03:51:39PM +0800, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> The core CPU control framework supports runtime SMT control which
> is not yet supported on arm64. Besides the general vulnerabilities
> concerns we want this runtime control on our arm64 server for:
> 
> - better single CPU performance in some cases
> - saving overall power consumption
> 
> This patchset implements it in the following aspects:
> 
> - Provides a default topology_is_primary_thread()
> - support retrieve SMT thread number on OF based system
> - support retrieve SMT thread number on ACPI based system
> - select HOTPLUG_SMT for arm64
> 
> Tests has been done on our ACPI based arm64 server and on ACPI/OF
> based QEMU VMs.
> 
> Change since v11:
> - Remove the check and warning for heterogeneous platform as suggested and discussed

IIUC, the ask was not to remove it completely but to allow single
threaded and same number of threads in all the multi-threaded CPUs.
Anyways that is not a must, we can just stash max_smt_thread_num value
before updating with max and see if it changes from one value to another
with value != 1. It can be done later when we want to warn such systems
if they appear in the future and we can't support them. For now, it looks
fine.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Mar 11 07:41:39 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 14:41:39 +0000
Subject: [PATCH v12 1/4] cpu/SMT: Provide a default
 topology_is_primary_thread()
In-Reply-To: <20250311075143.61078-2-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-2-yangyicong@huawei.com>
Message-ID: <Z9BLo0rDthj2NwFu@bogus>

On Tue, Mar 11, 2025 at 03:51:40PM +0800, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> Currently if architectures want to support HOTPLUG_SMT they need to
> provide a topology_is_primary_thread() telling the framework which
> thread in the SMT cannot offline. However arm64 doesn't have a
> restriction on which thread in the SMT cannot offline, a simplest
> choice is that just make 1st thread as the "primary" thread. So
> just make this as the default implementation in the framework and
> let architectures like x86 that have special primary thread to
> override this function (which they've already done).
> 
> There's no need to provide a stub function if !CONFIG_SMP or
> !CONFIG_HOTPLUG_SMT. In such case the testing CPU is already
> the 1st CPU in the SMT so it's always the primary thread.
>

LGTM:

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

> +	 * enabled/active. Architectures do have a special primary thread

If you respin

^^ s/do/that/ or s/do/that do/

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Mar 11 07:41:56 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 14:41:56 +0000
Subject: [PATCH v12 4/4] arm64: Kconfig: Enable HOTPLUG_SMT
In-Reply-To: <20250311075143.61078-5-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-5-yangyicong@huawei.com>
Message-ID: <Z9BLtGYyQ3CqkX5Z@bogus>

On Tue, Mar 11, 2025 at 03:51:43PM +0800, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> Enable HOTPLUG_SMT for SMT control.
> 

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Mar 11 07:42:13 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 14:42:13 +0000
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <20250311075143.61078-3-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-3-yangyicong@huawei.com>
Message-ID: <Z9BLxeHrLZ1MJVhy@bogus>

On Tue, Mar 11, 2025 at 03:51:41PM +0800, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> On building the topology from the devicetree, we've already gotten the
> SMT thread number of each core. Update the largest SMT thread number
> and enable the SMT control by the end of topology parsing.
> 
> The framework's SMT control provides two interface to the users [1]
> through /sys/devices/system/cpu/smt/control:
> 1) enable SMT by writing "on" and disable by "off"
> 2) enable SMT by writing max_thread_number or disable by writing 1
> 
> Both method support to completely disable/enable the SMT cores so both
> work correctly for symmetric SMT platform and asymmetric platform with
> non-SMT and one type SMT cores like:
> core A: 1 thread
> core B: X (X!=1) threads
> 
> Note that for a theoretically possible multiple SMT-X (X>1) core
> platform the SMT control is also supported as expected but only
> by writing the "on/off" method.
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542

Just the path must suffice here, no need for URL.

LGTM otherwise, much simple now:

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Mar 11 07:42:28 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 11 Mar 2025 14:42:28 +0000
Subject: [PATCH v12 3/4] arm64: topology: Support SMT control on ACPI
 based system
In-Reply-To: <20250311075143.61078-4-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-4-yangyicong@huawei.com>
Message-ID: <Z9BL1DgDlcYKVaDu@bogus>

On Tue, Mar 11, 2025 at 03:51:42PM +0800, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> For ACPI we'll build the topology from PPTT and we cannot directly
> get the SMT number of each core. Instead using a temporary xarray
> to record the heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL)
> and SMT information of the first core in its heterogeneous CPU cluster
> when building the topology. Then we can know the largest SMT number
> in the system. If a homogeneous system's using ACPI 6.2 or later,
> all the CPUs should be under the root node of PPTT. There'll be
> only one entry in the xarray and all the CPUs in the system will
> be assumed identical.
> 
> The framework's SMT control provides two interface to the users [1]
> through /sys/devices/system/cpu/smt/control:
> 1) enable SMT by writing "on" and disable by "off"
> 2) enable SMT by writing max_thread_number or disable by writing 1
> 
> Both method support to completely disable/enable the SMT cores so both
> work correctly for symmetric SMT platform and asymmetric platform with
> non-SMT and one type SMT cores like:
> core A: 1 thread
> core B: X (X!=1) threads
> 
> Note that for a theoretically possible multiple SMT-X (X>1) core
> platform the SMT control is also supported as expected but only
> by writing the "on/off" method.
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542

Ditto, just path please.

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

--
Regards,
Sudeep


From pmladek at suse.com  Tue Mar 11 07:36:11 2025
From: pmladek at suse.com (Petr Mladek)
Date: Tue, 11 Mar 2025 15:36:11 +0100
Subject: [PATCH v2 2/2] vsprintf: remove redundant and unused %pCn format
 specifier
In-Reply-To: <20250311-vsprintf-pcn-v2-2-0af40fc7dee4@bootlin.com>
References: <20250311-vsprintf-pcn-v2-0-0af40fc7dee4@bootlin.com>
 <20250311-vsprintf-pcn-v2-2-0af40fc7dee4@bootlin.com>
Message-ID: <Z9BKW_06nLAOzYfY@pathway.suse.cz>

On Tue 2025-03-11 10:21:23, Luca Ceresoli wrote:
> %pC and %pCn print the same string, and commit 900cca294425 ("lib/vsprintf:
> add %pC{,n,r} format specifiers for clocks") introducing them does not
> clarify any intended difference. It can be assumed %pC is a default for
> %pCn as some other specifiers do, but not all are consistent with this
> policy. Moreover there is now no other suffix other than 'n', which makes a
> default not really useful.
> 
> All users in the kernel were using %pC except for one which has been
> converted. So now remove %pCn and all the unnecessary extra code and
> documentation.
> 
> Acked-by: Stephen Boyd <sboyd at kernel.org>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

Makes sense. Looks and works well, so:

Reviewed-by: Petr Mladek <pmladek at suse.com>
Tested-by: Petr Mladek <pmladek at suse.com>

Daniel, if I get it correctly, you have already taken the 1st patch.
Would you mind to take also this patch using the same tree, please?
Otherwise, we would need to coordinate pull requests in the upcoming
merge window ;-)

Best Regards,
Petr


From Frank.li at nxp.com  Tue Mar 11 07:36:00 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 11 Mar 2025 10:36:00 -0400
Subject: [PATCH v13 3/5] arm64: dts: imx8ulp-evk: add nxp secure enclave
 firmware
In-Reply-To: <20250311-imx-se-if-v13-3-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
 <20250311-imx-se-if-v13-3-9cc6d8fd6d1c@nxp.com>
Message-ID: <Z9BKUBlcF2W2oBEp@lizhi-Precision-Tower-5810>

On Tue, Mar 11, 2025 at 09:09:34PM +0530, Pankaj Gupta wrote:
> Add support for NXP secure enclave called EdgeLock Enclave
> firmware (se-fw) for imx8ulp-evk.
>
> EdgeLock Enclave has a hardware limitation of restricted access to DDR
> address: 0x80000000 to 0xAFFFFFFF, so reserve 1MB of DDR memory region
> from 0x80000000.
>
> Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8ulp-evk.dts | 17 ++++++++++++++++-
>  arch/arm64/boot/dts/freescale/imx8ulp.dtsi    | 13 +++++++++++--
>  2 files changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> index 290a49bea2f7..a25d71bf2c26 100644
> --- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>  /*
> - * Copyright 2021 NXP
> + * Copyright 2021, 2025 NXP
>   */
>
>  /dts-v1/;
> @@ -24,6 +24,17 @@ memory at 80000000 {
>  		device_type = "memory";
>  		reg = <0x0 0x80000000 0 0x80000000>;
>  	};

space line here.

> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		ele_reserved: ele-reserved at 90000000 {
> +			compatible = "shared-dma-pool";
> +			reg = <0 0x90000000 0 0x100000>;
> +			no-map;
> +		};
> +	};
>
>  	reserved-memory {
>  		#address-cells = <2>;
> @@ -259,6 +270,10 @@ &usdhc0 {
>  	status = "okay";
>  };
>
> +&hsm0 {
> +	memory-region = <&ele_reserved>;
> +};
> +
>  &fec {
>  	pinctrl-names = "default", "sleep";
>  	pinctrl-0 = <&pinctrl_enet>;
> diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> index 2562a35286c2..c79a5de227b3 100644
> --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>  /*
> - * Copyright 2021 NXP
> + * Copyright 2021, 2025 NXP
>   */
>
>  #include <dt-bindings/clock/imx8ulp-clock.h>
> @@ -154,7 +154,7 @@ sosc: clock-sosc {
>  		#clock-cells = <0>;
>  	};
>
> -	sram at 2201f000 {
> +	sram0: sram at 2201f000 {
>  		compatible = "mmio-sram";
>  		reg = <0x0 0x2201f000 0x0 0x1000>;
>
> @@ -169,6 +169,8 @@ scmi_buf: scmi-sram-section at 0 {
>  	};
>
>  	firmware {
> +		#address-cells = <1>;
> +		#size-cells = <0>;

Needn't #address-cells and  #size-cells because no regs in children nodes

Frank

>  		scmi {
>  			compatible = "arm,scmi-smc";
>  			arm,smc-id = <0xc20000fe>;
> @@ -186,6 +188,13 @@ scmi_sensor: protocol at 15 {
>  				#thermal-sensor-cells = <1>;
>  			};
>  		};
> +
> +		hsm0: secure-enclave {
> +			 compatible = "fsl,imx8ulp-se-ele-hsm";
> +			 mbox-names = "tx", "rx";
> +			 mboxes = <&s4muap 0 0>, <&s4muap 1 0>;
> +			 sram = <&sram0>;
> +		 };
>  	};
>
>  	cm33: remoteproc-cm33 {
>
> --
> 2.43.0
>


From robin.murphy at arm.com  Tue Mar 11 07:37:48 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 11 Mar 2025 14:37:48 +0000
Subject: [PATCH v2 4/4] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250304161943.GD5011@ziepe.ca>
References: <20250228182403.6269-2-miko.lenczewski@arm.com>
 <20250228182403.6269-6-miko.lenczewski@arm.com>
 <20250228193221.GM5011@ziepe.ca>
 <b23aa37f8e864dea82a6143bece912d6@huawei.com>
 <20250303103102.GC13345@e133081.arm.com> <20250303165255.GS5011@ziepe.ca>
 <20250303190330.GA426248@e133081.arm.com> <20250304142634.GC5011@ziepe.ca>
 <67fbe3f4-4fb6-4753-b34c-320b7897fd16@arm.com>
 <20250304161943.GD5011@ziepe.ca>
Message-ID: <58c5e76a-e320-4296-8292-1ddf3f7ba56d@arm.com>

On 04/03/2025 4:19 pm, Jason Gunthorpe wrote:
> On Tue, Mar 04, 2025 at 04:02:20PM +0000, Ryan Roberts wrote:
>> On 04/03/2025 14:26, Jason Gunthorpe wrote:
>>> On Mon, Mar 03, 2025 at 07:03:42PM +0000, Miko?aj Lenczewski wrote:
>>>
>>>> For example, if we use BBML2 for kernel mappings, does that require us
>>>> to repaint all kernel mappings when disabling BBML2 on smmu attach? I
>>>> am not sure, but definitely something to be worked out.
>>>
>>> No, it would be a per-mm_struct basis only if we did something like
>>> that
>>>
>>> When the SMMU driver puts a SVA on top of the mm_struct it would
>>> disable BBML2 usage only for that mm_struct and it's contained VMAs.
>>
>> I guess we would need to figure out some synchonization mechanism if disabling
>> BBML2 dynaically per-mm. If there was already a BBML2 operation in flight would
>> want to wait for it to end. But that's a problem to solve if/when it's shown to
>> be needed, I think.
> 
> I have a feeling we can piggyback on the mmu notifiers to achieve this
> as all the changes to the PTEs should be bracketed by notifier
> callbacks..
> 
> Let's hope it isn't needed.

Yup, as mentioned previously, this is largely theoretical and at worst 
only a risk of affecting 3rd-party SMMU implementations. Arm's 
implementations from MMU-700 onwards do support BBML2; MMU-600 *might* 
actually be OK as well, but it predates the definition of the feature, 
and there are more practical reasons not to integrate a decade-old SMMU 
design with brand new CPUs anyway.

Thanks,
Robin.


From ulf.hansson at linaro.org  Tue Mar 11 07:42:31 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 11 Mar 2025 15:42:31 +0100
Subject: [PATCH v5] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <20250307145547.2784821-1-ping.bai@nxp.com>
References: <20250307145547.2784821-1-ping.bai@nxp.com>
Message-ID: <CAPDyKFqsE4nArB+Qn5gH5P7vVePpZ6Z7ruas2-EGYsctGV-=4w@mail.gmail.com>

On Fri, 7 Mar 2025 at 15:54, Jacky Bai <ping.bai at nxp.com> wrote:
>
> for_each_possible_cpu() is currently used to initialize cpuidle
> in below cpuidle drivers:
>   drivers/cpuidle/cpuidle-arm.c
>   drivers/cpuidle/cpuidle-big_little.c
>   drivers/cpuidle/cpuidle-psci.c
>   drivers/cpuidle/cpuidle-qcom-spm.c
>   drivers/cpuidle/cpuidle-riscv-sbi.c
>
> However, in cpu_dev_register_generic(), for_each_present_cpu()
> is used to register CPU devices which means the CPU devices are
> only registered for present CPUs and not all possible CPUs.
>
> With nosmp or maxcpus=0, only the boot CPU is present, lead
> to the failure:
>
>   |  Failed to register cpuidle device for cpu1
>
> Then rollback to cancel all CPUs' cpuidle registration.
>
> Change for_each_possible_cpu() to for_each_present_cpu() in the
> above cpuidle drivers to ensure it only registers cpuidle devices
> for CPUs that are actually present.
>
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Reviewed-by: Dhruva Gole <d-gole at ti.com>
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>

Reviewed-by: Ulf Hansson <ulf.hansson at linaro.org>

Rafael, I assume you will pick these up? Or let me know if you want me
to take them via my pmdomain tree.

Kind regards
Uffe

> ---
>  - v5 changes:
>    - add changes for cpuidle-qcom-spm
>
>  - v4 changes:
>   - add changes for other cpuidle driver that has the similar issue
>     as cpuidle-pcsi driver.
>
>  - v3 changes:
>   - improve the changelog as suggested by Sudeep
> ---
>  drivers/cpuidle/cpuidle-arm.c        | 8 ++++----
>  drivers/cpuidle/cpuidle-big_little.c | 2 +-
>  drivers/cpuidle/cpuidle-psci.c       | 4 ++--
>  drivers/cpuidle/cpuidle-qcom-spm.c   | 2 +-
>  drivers/cpuidle/cpuidle-riscv-sbi.c  | 4 ++--
>  5 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
> index caba6f4bb1b7..e044fefdb816 100644
> --- a/drivers/cpuidle/cpuidle-arm.c
> +++ b/drivers/cpuidle/cpuidle-arm.c
> @@ -137,9 +137,9 @@ static int __init arm_idle_init_cpu(int cpu)
>  /*
>   * arm_idle_init - Initializes arm cpuidle driver
>   *
> - * Initializes arm cpuidle driver for all CPUs, if any CPU fails
> - * to register cpuidle driver then rollback to cancel all CPUs
> - * registration.
> + * Initializes arm cpuidle driver for all present CPUs, if any
> + * CPU fails to register cpuidle driver then rollback to cancel
> + * all CPUs registration.
>   */
>  static int __init arm_idle_init(void)
>  {
> @@ -147,7 +147,7 @@ static int __init arm_idle_init(void)
>         struct cpuidle_driver *drv;
>         struct cpuidle_device *dev;
>
> -       for_each_possible_cpu(cpu) {
> +       for_each_present_cpu(cpu) {
>                 ret = arm_idle_init_cpu(cpu);
>                 if (ret)
>                         goto out_fail;
> diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
> index 74972deda0ea..4abba42fcc31 100644
> --- a/drivers/cpuidle/cpuidle-big_little.c
> +++ b/drivers/cpuidle/cpuidle-big_little.c
> @@ -148,7 +148,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
>         if (!cpumask)
>                 return -ENOMEM;
>
> -       for_each_possible_cpu(cpu)
> +       for_each_present_cpu(cpu)
>                 if (smp_cpuid_part(cpu) == part_id)
>                         cpumask_set_cpu(cpu, cpumask);
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index dd8d776d6e39..b46a83f5ffe4 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -403,7 +403,7 @@ static int psci_idle_init_cpu(struct device *dev, int cpu)
>  /*
>   * psci_idle_probe - Initializes PSCI cpuidle driver
>   *
> - * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails
> + * Initializes PSCI cpuidle driver for all present CPUs, if any CPU fails
>   * to register cpuidle driver then rollback to cancel all CPUs
>   * registration.
>   */
> @@ -413,7 +413,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev)
>         struct cpuidle_driver *drv;
>         struct cpuidle_device *dev;
>
> -       for_each_possible_cpu(cpu) {
> +       for_each_present_cpu(cpu) {
>                 ret = psci_idle_init_cpu(&pdev->dev, cpu);
>                 if (ret)
>                         goto out_fail;
> diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c
> index 3ab240e0e122..5f386761b156 100644
> --- a/drivers/cpuidle/cpuidle-qcom-spm.c
> +++ b/drivers/cpuidle/cpuidle-qcom-spm.c
> @@ -135,7 +135,7 @@ static int spm_cpuidle_drv_probe(struct platform_device *pdev)
>         if (ret)
>                 return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed");
>
> -       for_each_possible_cpu(cpu) {
> +       for_each_present_cpu(cpu) {
>                 ret = spm_cpuidle_register(&pdev->dev, cpu);
>                 if (ret && ret != -ENODEV) {
>                         dev_err(&pdev->dev,
> diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
> index 0c92a628bbd4..0fe1ece9fbdc 100644
> --- a/drivers/cpuidle/cpuidle-riscv-sbi.c
> +++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
> @@ -529,8 +529,8 @@ static int sbi_cpuidle_probe(struct platform_device *pdev)
>                         return ret;
>         }
>
> -       /* Initialize CPU idle driver for each CPU */
> -       for_each_possible_cpu(cpu) {
> +       /* Initialize CPU idle driver for each present CPU */
> +       for_each_present_cpu(cpu) {
>                 ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu);
>                 if (ret) {
>                         pr_debug("HART%ld: idle driver init failed\n",
> --
> 2.34.1
>


From robh at kernel.org  Tue Mar 11 07:52:50 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 09:52:50 -0500
Subject: [PATCH v2 1/3] dt-bindings: mtd: microchip-nand: convert txt
 to yaml
In-Reply-To: <20250311122847.90081-2-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
 <20250311122847.90081-2-balamanikandan.gunasundar@microchip.com>
Message-ID: <174170473601.3452705.4276708145941047362.robh@kernel.org>


On Tue, 11 Mar 2025 17:58:45 +0530, Balamanikandan Gunasundar wrote:
> Convert text to yaml for microchip nand controller
> 
> Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
> ---
> 
> Changes in v2:
> 
> - Change the filename to match the compatible string
> - Drop items and oneOf in the compatible property as it is just an enum
> - Remove the if in the #address-cells and #size-cells
> - Remove the unwanted comments that refers to .txt files
> - Fix reg property description
> - Define the properties in a list and add constraints
> - Fix DT coding style and droped unused labels
> 
>  .../devicetree/bindings/mtd/atmel-nand.txt    |  50 -----
>  .../mtd/microchip,nand-controller.yaml        | 175 ++++++++++++++++++
>  2 files changed, 175 insertions(+), 50 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mtd/microchip,nand-controller.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/mtd/microchip,nand-controller.example.dtb: /example-0/ecc-engine at ffffc070: failed to match any schema with compatible: ['atmel,at91sam9g45-pmecc']
Documentation/devicetree/bindings/mtd/microchip,nand-controller.example.dtb: /example-0/ebi at 10000000: failed to match any schema with compatible: ['atmel,sama5d3-ebi']
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mtd/microchip,nand-controller.example.dtb: nand-controller: #address-cells: 1 was expected
	from schema $id: http://devicetree.org/schemas/mtd/nand-controller.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mtd/microchip,nand-controller.example.dtb: nand-controller: #size-cells: 0 was expected
	from schema $id: http://devicetree.org/schemas/mtd/nand-controller.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250311122847.90081-2-balamanikandan.gunasundar at microchip.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From purvayeshi550 at gmail.com  Tue Mar 11 07:55:37 2025
From: purvayeshi550 at gmail.com (Purva Yeshi)
Date: Tue, 11 Mar 2025 20:25:37 +0530
Subject: [PATCH] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML schema
In-Reply-To: <af6ebce2-7256-48bd-94d4-dc81e2944966@kernel.org>
References: <20250311125756.24064-1-purvayeshi550@gmail.com>
 <af6ebce2-7256-48bd-94d4-dc81e2944966@kernel.org>
Message-ID: <47f6713b-b751-4791-9059-a128dd1fc71d@gmail.com>

On 11/03/25 18:52, Krzysztof Kozlowski wrote:
> On 11/03/2025 13:57, Purva Yeshi wrote:
>> Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
>> YAML schema (`lpc32xx-pwm.yaml`).
>>
>> Changes:
>>
>> Add SPDX license identifier `(GPL-2.0-only OR BSD-2-Clause)`.
> 
> That's not a change in the binding.
> 
>> Define `$id` and `$schema` fields for proper schema validation.
>> Set `title` to describe the LPC32XX PWM controller.
> 
> Neither these.
> 
>> Add maintainers as per `scripts/get_maintainer.pl` output.
> 
> These should not be subsystem maintainers.

I have removed the subsystem maintainers and included only relevant ones:
      Vladimir Zapolskiy <vz at mleia.com>
      Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>

> 
>> Reference `pwm.yaml#` in `allOf` to inherit common PWM properties.
> 
> Not a change to the binding.
> 
>>
>> Define properties:
>> Restrict `compatible` to `"nxp,lpc3220-pwm"` using `const`.
>> Limit `reg` to `maxItems: 1` to ensure a single register range.
>> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.
>>
>> Mark `compatible` and `reg` as required properties.
> 
> So it wasn't before? What are you implying here?

The compatible and reg properties were already present in the .txt file, 
but in a different format. I initially kept the commit message for them 
but have now removed it.

> 
>> Set `unevaluatedProperties: false` to enforce strict validation.
>>
>> Validate the YAML schema using dt-validate and yamllint.
> 
> None of above is suitable for commit msg.

I have removed all commit message parts you mentioned.

> 
>>
>> Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
>> ---
>>   .../devicetree/bindings/pwm/lpc32xx-pwm.yaml  | 45 +++++++++++++++++++
>>   1 file changed, 45 insertions(+)
> 
> Where is the conversion?

Apologies for the confusion. I missed removing lpc32xx-pwm.txt. I'll 
delete it in the next version to properly reflect the conversion.

> 
>>   create mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>> new file mode 100644
>> index 000000000..3e41cd291
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>> @@ -0,0 +1,45 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/pwm/nxp,lpc32xx-pwm.yaml#
> 
> Filename matching compatible.

In the lpc32xx-pwm.txt file, the compatible property was defined as 
"nxp,lpc3220-pwm", so I have kept it the same. To ensure consistency 
between the filename and compatible, should I rename the file to 
nxp,lpc3220-pwm.yaml?

> 
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: LPC32XX PWM controller
>> +
>> +maintainers:
>> +  - "Uwe Kleine-K?nig <ukleinek at kernel.org>"
>> +  - "Vladimir Zapolskiy <vz at mleia.com>"
>> +  - "Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>"
> 
> Look at other bindings - none of them use quotes.
> 
>> +
>> +allOf:
>> +  - $ref: pwm.yaml#
>> +
>> +properties:
>> +  compatible:
>> +    const: nxp,lpc3220-pwm
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  "#pwm-cells":
>> +    const: 3
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +
>> +unevaluatedProperties: false
>> +
>> +examples:
>> +  - |
>> +    pwm at 4005c000 {
>> +        compatible = "nxp,lpc3220-pwm";
>> +        reg = <0x4005c000 0x4>;
>> +        #pwm-cells = <3>;
>> +    };
>> +  - |
>> +    pwm at 4005c004 {
>> +        compatible = "nxp,lpc3220-pwm";
> 
> One example is enough.

Okay. I'll remove the second example and keep only one in the next version.

> 
> 
> 
> Best regards,
> Krzysztof

Best regards,
Purva Yeshi


From suzuki.poulose at arm.com  Tue Mar 11 07:57:11 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 11 Mar 2025 14:57:11 +0000
Subject: [PATCH] coresight: docs: Remove target sink from examples
In-Reply-To: <20241210144933.295798-1-james.clark@linaro.org>
References: <20241210144933.295798-1-james.clark@linaro.org>
Message-ID: <174170501277.145861.13343578930961537547.b4-ty@arm.com>


On Tue, 10 Dec 2024 14:49:28 +0000, James Clark wrote:
> Previously the sink had to be specified, but now it auto selects one by
> default. Including a sink in the examples causes issues when copy
> pasting the command because it might not work if that sink isn't
> present. Remove the sink from all the basic examples and create a new
> section specifically about overriding the default one.
> 
> Make the text a but more concise now that it's in the advanced section,
> and similarly for removing the old kernel advice.
> 
> [...]

Applied, thanks!

[1/1] coresight: docs: Remove target sink from examples
      https://git.kernel.org/coresight/c/4a29fa26

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From osandov at osandov.com  Tue Mar 11 07:54:46 2025
From: osandov at osandov.com (Omar Sandoval)
Date: Tue, 11 Mar 2025 07:54:46 -0700
Subject: [PATCH] arm64: reserve [_text, _stext) virtual address range
In-Reply-To: <20250311141717.GA4931@willie-the-truck>
References: <ec2d02358eee53f095ad9a7d9c96af8f4d0d4eeb.1741636880.git.osandov@osandov.com>
 <20250311125414.GA4601@willie-the-truck>
 <CAMj1kXGgKy=1g1dsN1_yd8JwGZC5SpLUwiJk3GCnZhQ8UtTkKQ@mail.gmail.com>
 <20250311141717.GA4931@willie-the-truck>
Message-ID: <Z9BOttC9HTIDx62P@telecaster>

On Tue, Mar 11, 2025 at 02:17:18PM +0000, Will Deacon wrote:
> On Tue, Mar 11, 2025 at 02:32:47PM +0100, Ard Biesheuvel wrote:
> > On Tue, 11 Mar 2025 at 13:54, Will Deacon <will at kernel.org> wrote:
> > >
> > > [+Ard]
> > >
> > > On Mon, Mar 10, 2025 at 01:05:04PM -0700, Omar Sandoval wrote:
> > > > From: Omar Sandoval <osandov at fb.com>
> > > >
> > > > Since the referenced fixes commit, the kernel's .text section is only
> > > > mapped starting from _stext; the region [_text, _stext) is omitted. As a
> > > > result, other vmalloc/vmap allocations may use the virtual addresses
> > > > nominally in the range [_text, _stext). This address reuse confuses
> > > > multiple things:
> > > >
> > > > 1. crash_prepare_elf64_headers() sets up a segment in /proc/vmcore
> > > >    mapping the entire range [_text, _end) to
> > > >    [__pa_symbol(_text), __pa_symbol(_end)). Reading an address in
> > > >    [_text, _stext) from /proc/vmcore therefore gives the incorrect
> > > >    result.
> 
> [...]
> 
> > > > @@ -765,13 +769,17 @@ core_initcall(map_entry_trampoline);
> > > >   */
> > > >  static void __init declare_kernel_vmas(void)
> > > >  {
> > > > -     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];
> > > > +     static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT + 1];
> > > >
> > > > -     declare_vma(&vmlinux_seg[0], _stext, _etext, VM_NO_GUARD);
> > > > -     declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
> > > > -     declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
> > > > -     declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
> > > > -     declare_vma(&vmlinux_seg[4], _data, _end, 0);
> > > > +     declare_vma(&vmlinux_seg[0], _text, _stext, VM_NO_GUARD);
> > >
> > > Should we also put the memblock reservation back as it was, so that this
> > > region can't be allocated there?
> > >
> > 
> > The issue is about the virtual address space, not the physical memory
> > behind it, right? So the VA range should be protected from reuse, but
> > nothing needs to be mapped there.
> 
> You're absolutely right, but now I'm more confused about the reference
> to crash_prepare_elf64_headers() in the commit message. That sets both
> the virtual (_text) and the physical (__pa_symbol(_text)) addresses in
> the header, so it feels like we really need to keep that memory around
> because it's accessible via /proc/vmcore.
> 
> > 
> > > In fact, if we're not allocating from here, why don't we just map it
> > > anyway but without execute permissions?
> > >
> > 
> > It's just 64k so if this is the simplest approach, I won't object.
> > 
> > I wonder if this needs to be so intrusive, though - there is already a
> > precedent of VMAs not actually mapping the entire region they describe
> > (with guard pages), and so we might just declare the first VMA as
> > [_text, _etext), even though the first 64k of that region is not not
> > actually mapped.
> > 
> > However, if that confuses the bookkeeping or creates other problems,
> > declaring a separate VMA to reserve the VA range seems fine, although
> > the patch seems a bit intrusive (and I don't even see the whole
> > thing).
> 
> As above, I think we'll have to give /proc/vmcore the physical address
> of _something_.

I figured since there's nothing actually at that virtual address
anymore, it doesn't matter what physical address /proc/vmcore gives. But
that doesn't sound great now that you point it out. I'll rework this to
map the range non-executable.

Thanks,
Omar


From rafael at kernel.org  Tue Mar 11 07:58:02 2025
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 11 Mar 2025 15:58:02 +0100
Subject: [PATCH v5] cpuidle: Init cpuidle only for present CPUs
In-Reply-To: <CAPDyKFqsE4nArB+Qn5gH5P7vVePpZ6Z7ruas2-EGYsctGV-=4w@mail.gmail.com>
References: <20250307145547.2784821-1-ping.bai@nxp.com> <CAPDyKFqsE4nArB+Qn5gH5P7vVePpZ6Z7ruas2-EGYsctGV-=4w@mail.gmail.com>
Message-ID: <CAJZ5v0jjezx5sUEZwsbsw-iZiwbirmB+690-syOCur26DvOSNQ@mail.gmail.com>

On Tue, Mar 11, 2025 at 3:43?PM Ulf Hansson <ulf.hansson at linaro.org> wrote:
>
> On Fri, 7 Mar 2025 at 15:54, Jacky Bai <ping.bai at nxp.com> wrote:
> >
> > for_each_possible_cpu() is currently used to initialize cpuidle
> > in below cpuidle drivers:
> >   drivers/cpuidle/cpuidle-arm.c
> >   drivers/cpuidle/cpuidle-big_little.c
> >   drivers/cpuidle/cpuidle-psci.c
> >   drivers/cpuidle/cpuidle-qcom-spm.c
> >   drivers/cpuidle/cpuidle-riscv-sbi.c
> >
> > However, in cpu_dev_register_generic(), for_each_present_cpu()
> > is used to register CPU devices which means the CPU devices are
> > only registered for present CPUs and not all possible CPUs.
> >
> > With nosmp or maxcpus=0, only the boot CPU is present, lead
> > to the failure:
> >
> >   |  Failed to register cpuidle device for cpu1
> >
> > Then rollback to cancel all CPUs' cpuidle registration.
> >
> > Change for_each_possible_cpu() to for_each_present_cpu() in the
> > above cpuidle drivers to ensure it only registers cpuidle devices
> > for CPUs that are actually present.
> >
> > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> > Reviewed-by: Dhruva Gole <d-gole at ti.com>
> > Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> > Tested-by: Yuanjie Yang <quic_yuanjiey at quicinc.com>
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
>
> Reviewed-by: Ulf Hansson <ulf.hansson at linaro.org>
>
> Rafael, I assume you will pick these up? Or let me know if you want me
> to take them via my pmdomain tree.

I can pick it up.


From kw at linux.com  Tue Mar 11 08:00:00 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 12 Mar 2025 00:00:00 +0900
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250305132018.2260771-1-s-vadapalli@ti.com>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
Message-ID: <20250311150000.GB1381004@rocinante>

Hello,

> Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
> J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
> to the Technical Reference Manual and Register Documentation for the J784S4
> SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
> the field for the link-state interrupt. Instead, it is BIT(10) of the
> "PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
> field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".
> 
> Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> already reuse this macro since it accurately represents the link-state
> field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> 
> [0]: https://www.ti.com/lit/zip/spruj52

Applied to controller/j721e, thank you!

	Krzysztof


From suzuki.poulose at arm.com  Tue Mar 11 08:00:05 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 11 Mar 2025 15:00:05 +0000
Subject: [PATCH v2] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
References: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
Message-ID: <c31de6cb-f8f5-432c-b99e-68b10a24bc5e@arm.com>

On 05/03/2025 15:07, James Clark wrote:
> Add a test to confirm that default sink selection skips over an ETF
> and returns an ETR even if it's further away.
> 
> This also makes it easier to add new unit tests in the future.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
> Changes in v2:
> - Let devm free everything rather than doing individual kfrees:
>    "Like with managed drivers, KUnit-managed fake devices are
>    automatically cleaned up when the test finishes, but can be manually
>    cleaned up early with kunit_device_unregister()."
> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
> ---
>   drivers/hwtracing/coresight/Kconfig                |  9 +++
>   drivers/hwtracing/coresight/Makefile               |  3 +-
>   drivers/hwtracing/coresight/coresight-core.c       |  1 +
>   .../hwtracing/coresight/coresight-kunit-tests.c    | 77 ++++++++++++++++++++++
>   4 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index ecd7086a5b83..f064e3d172b3 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>   
>   	  To compile this driver as a module, choose M here: the module will be
>   	  called coresight-dummy.
> +
> +config CORESIGHT_KUNIT_TESTS
> +	  tristate "Enable Coresight unit tests"
> +	  depends on KUNIT
> +	  default KUNIT_ALL_TESTS
> +	  help
> +	    Enable Coresight unit tests. Only useful for development and not
> +	    intended for production.
> +
>   endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 8e62c3150aeb..96f0dfedb1bf 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
>   		   coresight-cti-sysfs.o
>   obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
> -coresight-ctcu-y := coresight-ctcu-core.o
> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index bd0a7edd38c9..b101aa133ceb 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>   	}
>   	return csdev->def_sink;
>   }
> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>   
>   static int coresight_remove_sink_ref(struct device *dev, void *data)
>   {
> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> new file mode 100644
> index 000000000000..a136af05eaf4
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +#include <kunit/device.h>
> +#include <linux/coresight.h>
> +
> +#include "coresight-priv.h"
> +
> +static struct coresight_device *coresight_test_device(struct device *dev)
> +{
> +	struct coresight_device *csdev = devm_kcalloc(dev, 1,
> +						     sizeof(struct coresight_device),
> +						     GFP_KERNEL);
> +	csdev->pdata = devm_kcalloc(dev, 1,
> +				   sizeof(struct coresight_platform_data),
> +				   GFP_KERNEL);
> +	return csdev;
> +}
> +
> +static int coresight_test_cpuid(struct coresight_device *csdev)
> +{
> +	return 0;
> +}
> +
> +static void test_default_sink(struct kunit *test)
> +{
> +	/*
> +	 * ETM -> ETF -> ETR -> CATU
> +	 *                ^
> +	 *                | default
> +	 */
> +	struct device *dev = kunit_device_register(test, "coresight_kunit");
> +	struct coresight_device *etm = coresight_test_device(dev),
> +				*etf = coresight_test_device(dev),
> +				*etr = coresight_test_device(dev),
> +				*catu = coresight_test_device(dev);
> +	struct coresight_connection conn = {};
> +	struct coresight_ops_source src_ops = {.cpu_id = coresight_test_cpuid };

Do we need the trace_id() ? Why is this required ?

Suzuki

> +	struct coresight_ops etm_cs_ops = { .source_ops	= &src_ops };
> +
> +	etm->type = CORESIGHT_DEV_TYPE_SOURCE;
> +	etm->ops = &etm_cs_ops;
> +	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
> +	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
> +	etr->type = CORESIGHT_DEV_TYPE_SINK;
> +	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
> +	catu->type = CORESIGHT_DEV_TYPE_HELPER;
> +
> +	conn.src_dev = etm;
> +	conn.dest_dev = etf;
> +	coresight_add_out_conn(dev, etm->pdata, &conn);
> +
> +	conn.src_dev = etf;
> +	conn.dest_dev = etr;
> +	coresight_add_out_conn(dev, etf->pdata, &conn);
> +
> +	conn.src_dev = etr;
> +	conn.dest_dev = catu;
> +	coresight_add_out_conn(dev, etr->pdata, &conn);
> +
> +	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
> +}
> +
> +static struct kunit_case coresight_testcases[] = {
> +	KUNIT_CASE(test_default_sink),
> +	{}
> +};
> +
> +static struct kunit_suite coresight_test_suite = {
> +	.name = "coresight_test_suite",
> +	.test_cases = coresight_testcases,
> +};
> +
> +kunit_test_suites(&coresight_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
> +MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
> 
> ---
> base-commit: eeafe6a8790ea125252ca2e23c1a2469eaff1d9a
> change-id: 20250305-james-cs-kunit-test-3af1df2401e6
> 
> Best regards,



From kamal.dasu at broadcom.com  Tue Mar 11 08:01:28 2025
From: kamal.dasu at broadcom.com (Kamal Dasu)
Date: Tue, 11 Mar 2025 11:01:28 -0400
Subject: [PATCH] mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
Message-ID: <20250311150136.46938-1-kamal.dasu@broadcom.com>

cqhci timeouts observed on brcmstb platforms during suspend:
  ...
  [  164.832853] mmc0: cqhci: timeout for tag 18
  ...

Adding cqhci_suspend()/resume() calls to disable cqe
in sdhci_brcmstb_suspend()/resume() respectively to fix
CQE timeouts seen on PM suspend.

Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)")
Cc: stable at vger.kernel.org
Signed-off-by: Kamal Dasu <kamal.dasu at broadcom.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 0ef4d578ade8..bf55a9185eb6 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -505,6 +505,12 @@ static int sdhci_brcmstb_suspend(struct device *dev)
 	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
 
 	clk_disable_unprepare(priv->base_clk);
+	if (host->mmc->caps2 & MMC_CAP2_CQE) {
+		ret = cqhci_suspend(host->mmc);
+		if (ret)
+			return ret;
+	}
+
 	return sdhci_pltfm_suspend(dev);
 }
 
@@ -529,6 +535,9 @@ static int sdhci_brcmstb_resume(struct device *dev)
 			ret = clk_set_rate(priv->base_clk, priv->base_freq_hz);
 	}
 
+	if (host->mmc->caps2 & MMC_CAP2_CQE)
+		ret = cqhci_resume(host->mmc);
+
 	return ret;
 }
 #endif
-- 
2.17.1



From prabhakar.csengg at gmail.com  Tue Mar 11 08:11:16 2025
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Tue, 11 Mar 2025 15:11:16 +0000
Subject: [PATCH] ARM: shmobile: smp: Enforce shmobile_smp_* alignment
In-Reply-To: <c499234d559a0d95ad9472883e46077311051cd8.1741612208.git.geert+renesas@glider.be>
References: <c499234d559a0d95ad9472883e46077311051cd8.1741612208.git.geert+renesas@glider.be>
Message-ID: <CA+V-a8tGuxgan7Zx0YedSByfFSgrg5gmR6Fy3dMDXwU+TscZzg@mail.gmail.com>

Hi Geert,

Thank you for the patch.

On Mon, Mar 10, 2025 at 1:14?PM Geert Uytterhoeven
<geert+renesas at glider.be> wrote:
>
> When the addresses of the shmobile_smp_mpidr, shmobile_smp_fn, and
> shmobile_smp_arg variables are not multiples of 4 bytes, secondary CPU
> bring-up fails:
>
>     smp: Bringing up secondary CPUs ...
>     CPU1: failed to come online
>     CPU2: failed to come online
>     CPU3: failed to come online
>     smp: Brought up 1 node, 1 CPU
>
> Fix this by adding the missing alignment directive.
>
> Fixes: 4e960f52fce16a3b ("ARM: shmobile: Move shmobile_smp_{mpidr, fn, arg}[] from .text to .bss")
I wonder if this fixes tag should go back a bit far as I was able to
reproduce this on 5.10-cip BSP kernel on RZ/G1E this was only seen
when CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE was enabled,

RZ/G1E failure logs:
--------------------------
[    0.006719] smp: Bringing up secondary CPUs ...
[    1.040749] CPU1: failed to come online
[    1.041014] smp: Brought up 1 node, 1 CPU
[    1.041038] SMP: Total of 1 processors activated (65.00 BogoMIPS).
[    1.041063] CPU: All CPU(s) started in SVC mode.
[    1.041904] devtmpfs: initialized
[    1.050811] VFP support v0.3: implementor 41 architecture 2 part 30
variant 7 rev 5
[    1.051143] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 19112604462750000 ns
[    1.051197] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
[    1.060510] pinctrl core: initialized pinctrl subsystem
[    1.063139] NET: Registered protocol family 16

$ grep shmobile_smp_ System.map-notworking
c021caa0 t shmobile_smp_apmu_cpu_kill
c021cb20 t shmobile_smp_apmu_enter_suspend
c021cb54 t shmobile_smp_apmu_boot_secondary
c021cbc0 t shmobile_smp_apmu_cpu_shutdown
c021cc18 t shmobile_smp_apmu_do_suspend
c021cc60 t shmobile_smp_apmu_cpu_die
c021cc84 T shmobile_smp_hook
c021ccd8 T shmobile_smp_cpu_can_disable
c021d050 t shmobile_smp_continue_gen2
c021d0c4 T shmobile_smp_boot
c021d0e4 t shmobile_smp_boot_find_mpidr
c021d0fc t shmobile_smp_boot_next
c021d10c t shmobile_smp_boot_found
c021d114 T shmobile_smp_sleep
c021d380 T shmobile_smp_scu_cpu_die
c021d3b4 T shmobile_smp_scu_cpu_kill
c120a87c t shmobile_smp_apmu_prepare_cpus_dt
c120aab8 T shmobile_smp_apmu_suspend_init
c120aad0 T shmobile_smp_init_fallback_ops
c120b0f0 T shmobile_smp_scu_prepare_cpus
c1262778 t __cpu_method_of_table_shmobile_smp_apmu
c154d5fd B shmobile_smp_mpidr
c154d61d B shmobile_smp_fn
c154d63d B shmobile_smp_arg


> Closes: https://lore.kernel.org/r/CAMuHMdU=QR-JLgEHKWpsr6SbaZRc-Hz9r91JfpP8c3n2G-OjqA at mail.gmail.com
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> To be queued in renesas-fixes-for-v6.14.
> ---
>  arch/arm/mach-shmobile/headsmp.S | 1 +
>  1 file changed, 1 insertion(+)
>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>

Cheers,
Prabhakar

> diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
> index a956b489b6ea12ca..2bc7e73a8582d2b3 100644
> --- a/arch/arm/mach-shmobile/headsmp.S
> +++ b/arch/arm/mach-shmobile/headsmp.S
> @@ -136,6 +136,7 @@ ENDPROC(shmobile_smp_sleep)
>         .long   shmobile_smp_arg - 1b
>
>         .bss
> +       .align  2
>         .globl  shmobile_smp_mpidr
>  shmobile_smp_mpidr:
>         .space  NR_CPUS * 4
> --
> 2.43.0
>
>


From krzk at kernel.org  Tue Mar 11 08:14:55 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 16:14:55 +0100
Subject: [PATCH] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML schema
In-Reply-To: <47f6713b-b751-4791-9059-a128dd1fc71d@gmail.com>
References: <20250311125756.24064-1-purvayeshi550@gmail.com>
 <af6ebce2-7256-48bd-94d4-dc81e2944966@kernel.org>
 <47f6713b-b751-4791-9059-a128dd1fc71d@gmail.com>
Message-ID: <23a5d017-06e5-4f4d-a522-1f4beb7a1f32@kernel.org>

On 11/03/2025 15:55, Purva Yeshi wrote:
>>>
>>> Define properties:
>>> Restrict `compatible` to `"nxp,lpc3220-pwm"` using `const`.
>>> Limit `reg` to `maxItems: 1` to ensure a single register range.
>>> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.
>>>
>>> Mark `compatible` and `reg` as required properties.
>>
>> So it wasn't before? What are you implying here?
> 
> The compatible and reg properties were already present in the .txt file, 
> but in a different format. I initially kept the commit message for them 
> but have now removed it.

What does it mean "different format"?

...

>>>
>>>   create mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>>> new file mode 100644
>>> index 000000000..3e41cd291
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.yaml
>>> @@ -0,0 +1,45 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/pwm/nxp,lpc32xx-pwm.yaml#
>>
>> Filename matching compatible.
> 
> In the lpc32xx-pwm.txt file, the compatible property was defined as 
> "nxp,lpc3220-pwm", so I have kept it the same. To ensure consistency 
> between the filename and compatible, should I rename the file to 
> nxp,lpc3220-pwm.yaml?

Use whatever is there in the compatible property as the filename.


Best regards,
Krzysztof


From catalin.marinas at arm.com  Tue Mar 11 08:15:20 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 15:15:20 +0000
Subject: [PATCH] selftest/powerpc/mm/pkey: fix build-break introduced by
 commit 00894c3fc917
In-Reply-To: <20250311084129.39308-1-maddy@linux.ibm.com>
References: <20250311084129.39308-1-maddy@linux.ibm.com>
Message-ID: <Z9BTiOh6DkstKZ53@arm.com>

Hi Madhavan,

On Tue, Mar 11, 2025 at 02:11:29PM +0530, Madhavan Srinivasan wrote:
> Build break was reported in the powerpc mailing list for next-20250218 with below errors
> 
> make[1]: Nothing to be done for 'all'.
> BUILD_TARGET=/root/venkat/linux-next/tools/testing/selftests/powerpc/mm; mkdir -p $BUILD_TARGET; make OUTPUT=$BUILD_TARGET -k -C mm all
>   CC       pkey_exec_prot
> In file included from pkey_exec_prot.c:18:
> /root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h: In function ?pkeys_unsupported?:
> /root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h:96:34: error: ?PKEY_UNRESTRICTED? undeclared (first use in this function)
>    96 |         pkey = sys_pkey_alloc(0, PKEY_UNRESTRICTED);
>       |                                  ^~~~~~~~~~~~~~~~~
> 
> https://lore.kernel.org/all/20250113170619.484698-2-yury.khrustalev at arm.com/ patchset
> has been queued to arm64/for-next/pkey_unrestricted which is causing a build break
> in the selftest/powerpc builds.
> 
> Commit 6d61527d931ba ("mm/pkey: Add PKEY_UNRESTRICTED macro") added a macro
> PKEY_UNRESTRICTED to handle implicit literal value of 0x0 (which is "unrestricted").
> Add the same to selftest/powerpc/pkeys.h to fix the reported build break.
> 
> Reported-by: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
> Closes: https://lore.kernel.org/lkml/3267ea6e-5a1a-4752-96ef-8351c912d386 at linux.ibm.com/T/
> Tested-by: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
> Signed-off-by: Madhavan Srinivasan <maddy at linux.ibm.com>
> ---
> Catalin, can you take this fix via arm64/for-next/pkey_unrestricted?
> Patch applies clean on top of arm64/for-next/pkey_unrestricted

I'll take it, sorry for the break. I did not realise powerpc duplicates
those definitions.

-- 
Catalin


From geert at linux-m68k.org  Tue Mar 11 08:20:44 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 11 Mar 2025 16:20:44 +0100
Subject: [PATCH] ARM: shmobile: smp: Enforce shmobile_smp_* alignment
In-Reply-To: <CA+V-a8tGuxgan7Zx0YedSByfFSgrg5gmR6Fy3dMDXwU+TscZzg@mail.gmail.com>
References: <c499234d559a0d95ad9472883e46077311051cd8.1741612208.git.geert+renesas@glider.be>
 <CA+V-a8tGuxgan7Zx0YedSByfFSgrg5gmR6Fy3dMDXwU+TscZzg@mail.gmail.com>
Message-ID: <CAMuHMdWXcRoqKz6S0sAtBpSM+_ghTs82wsN1dHvbHD5vO8W+7A@mail.gmail.com>

Hi Prabhakar,

On Tue, 11 Mar 2025 at 16:11, Lad, Prabhakar <prabhakar.csengg at gmail.com> wrote:
> On Mon, Mar 10, 2025 at 1:14?PM Geert Uytterhoeven
> > When the addresses of the shmobile_smp_mpidr, shmobile_smp_fn, and
> > shmobile_smp_arg variables are not multiples of 4 bytes, secondary CPU
> > bring-up fails:
> >
> >     smp: Bringing up secondary CPUs ...
> >     CPU1: failed to come online
> >     CPU2: failed to come online
> >     CPU3: failed to come online
> >     smp: Brought up 1 node, 1 CPU
> >
> > Fix this by adding the missing alignment directive.
> >
> > Fixes: 4e960f52fce16a3b ("ARM: shmobile: Move shmobile_smp_{mpidr, fn, arg}[] from .text to .bss")
>
> I wonder if this fixes tag should go back a bit far as I was able to
> reproduce this on 5.10-cip BSP kernel on RZ/G1E this was only seen
> when CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE was enabled,

4e960f52fce16a3b is in v4.5, so it covers 5.10-cip.

> RZ/G1E failure logs:
> --------------------------
> [    0.006719] smp: Bringing up secondary CPUs ...
> [    1.040749] CPU1: failed to come online

> c154d5fd B shmobile_smp_mpidr
> c154d61d B shmobile_smp_fn
> c154d63d B shmobile_smp_arg

Bang!

> > Closes: https://lore.kernel.org/r/CAMuHMdU=QR-JLgEHKWpsr6SbaZRc-Hz9r91JfpP8c3n2G-OjqA at mail.gmail.com
> > Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> > ---
> > To be queued in renesas-fixes-for-v6.14.
> > ---
> >  arch/arm/mach-shmobile/headsmp.S | 1 +
> >  1 file changed, 1 insertion(+)
> >
> Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>

Thanks!

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From s-vadapalli at ti.com  Tue Mar 11 08:18:33 2025
From: s-vadapalli at ti.com (s-vadapalli at ti.com)
Date: Tue, 11 Mar 2025 20:48:33 +0530
Subject: [PATCH net v2] net: ethernet: ti: am65-cpsw: Fix NAPI
 registration sequence
In-Reply-To: <02d685e2aa8721a119f528bde2f4ec9533101663.camel@siemens.com>
References: <20250311130103.68971-1-s-vadapalli@ti.com>
 <02d685e2aa8721a119f528bde2f4ec9533101663.camel@siemens.com>
Message-ID: <20250311151833.v3gymfqao4y2zls7@uda0492258>

On Tue, Mar 11, 2025 at 01:53:10PM +0000, Sverdlin, Alexander wrote:
> Hi Siddharth!
> 
> On Tue, 2025-03-11 at 18:31 +0530, Siddharth Vadapalli wrote:
> > From: Vignesh Raghavendra <vigneshr at ti.com>
> > 
> > Registering the interrupts for TX or RX DMA Channels prior to registering
> > their respective NAPI callbacks can result in a NULL pointer dereference.
> > This is seen in practice as a random occurrence since it depends on the
> > randomness associated with the generation of traffic by Linux and the
> > reception of traffic from the wire.
> > 
> > Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> > Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> > Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> 
> ...
> 
> > v1 of this patch is at:
> > https://lore.kernel.org/all/20250311061214.4111634-1-s-vadapalli at ti.com/
> > Changes since v1:
> > - Based on the feedback provided by Alexander Sverdlin <alexander.sverdlin at siemens.com>
> > ? the patch has been updated to account for the cleanup path in terms of an imbalance
> > ? between the number of successful netif_napi_add_tx/netif_napi_add calls and the
> > ? number of successful devm_request_irq() calls. In the event of an error, we will
> > ? always have one extra successful netif_napi_add_tx/netif_napi_add that needs to be
> > ? cleaned up before we clean an equal number of netif_napi_add_tx/netif_napi_add and
> > ? devm_request_irq.
> 
> ...
> 
> > --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
> > @@ -2569,6 +2570,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> > ?			???? HRTIMER_MODE_REL_PINNED);
> > ?		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
> > ?
> > +		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> > +			?????? am65_cpsw_nuss_rx_poll);
> > +
> > ?		ret = devm_request_irq(dev, flow->irq,
> > ?				?????? am65_cpsw_nuss_rx_irq,
> > ?				?????? IRQF_TRIGGER_HIGH,
> > @@ -2579,9 +2583,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> > ?			flow->irq = -EINVAL;
> > ?			goto err_flow;
> > ?		}
> > -
> > -		netif_napi_add(common->dma_ndev, &flow->napi_rx,
> > -			?????? am65_cpsw_nuss_rx_poll);
> > ?	}
> > ?
> > ?	/* setup classifier to route priorities to flows */
> > @@ -2590,10 +2591,11 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
> > ?	return 0;
> > ?
> > ?err_flow:
> > -	for (--i; i >= 0 ; i--) {
> > +	netif_napi_del(&flow->napi_rx);
> 
> There are totally 3 "goto err_flow;" instances, so if k3_udma_glue_rx_flow_init() or
> k3_udma_glue_rx_get_irq() would fail on the first iteration, we would come here without
> a single call to netif_napi_add().

The following should address this right?
------------------------------------------------------------------------------------------------
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index b88edf2dd8f4..bef734c6e5c2 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2581,7 +2581,7 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
                        dev_err(dev, "failure requesting rx %d irq %u, %d\n",
                                i, flow->irq, ret);
                        flow->irq = -EINVAL;
-                       goto err_flow;
+                       goto err_request_irq;
                }
        }

@@ -2590,8 +2590,10 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)

        return 0;

-err_flow:
+err_request_irq:
        netif_napi_del(&flow->napi_rx);
+
+err_flow:
        for (--i; i >= 0; i--) {
                flow = &rx_chn->flows[i];
                devm_free_irq(dev, flow->irq, flow);
------------------------------------------------------------------------------------------------

err_request_irq => We have an extra netif_napi_add() which needs to be
cleaned up.
err_flow => Equal count of netif_napi_add() and devm_request_irq() that
should be cleaned up.

Regards,
Siddharth.


From robh at kernel.org  Tue Mar 11 08:19:26 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 10:19:26 -0500
Subject: [PATCH v3 00/18] Imagination BXS-4-64 MC1 GPU support
In-Reply-To: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
References: <20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f@imgtec.com>
Message-ID: <174170613791.3566312.1327920809474076624.robh@kernel.org>


On Mon, 10 Mar 2025 13:10:24 +0000, Matt Coster wrote:
> This GPU is found in the TI AM68 family of SoCs, with initial support
> added to the k3-j721s2 devicetree and tested on a TI SK-AM68 board.
> 
> A suitable firmware binary can currently be found in the IMG
> linux-firmware repository[1] as powervr/rogue_36.53.104.796_v1.fw.
> 
> No new UAPI will be necessary for this platform as it is sufficiently
> similar to the already supported AXE-1-16M.
> 
> UMD support is close to being complete. We're now able to pass >90% of
> Vulkan conformance on our Mesa development branch. The compiler has been
> undergoing a significant rework needed to accomodate the BXS-4-64, as
> well as to make it more flexible to support additional Rogue GPUs going
> forward. The first part of this rework landed in Mesa in [2], and more
> MRs will follow in the coming weeks.
> 
> There are several dt-bindings changes at the beginning of this series.
> We expect the result to be versatile enough to handle all Imagination
> Rogue GPUs while being a strong foundation to build bindings for the
> newer Volcanic architecture (for which we're currently developing
> support).
> 
> The DTS changes at the end of the series are marked [DO NOT MERGE]. Once
> the series is reviewed, we will request these be taken through the
> relevant tree.
> 
> [1]: https://gitlab.freedesktop.org/imagination/linux-firmware/-/tree/powervr
> [3]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258
> 
> ---
> Changes in v3:
> - Reorder some patches to ensure the proper sequencing
> - Update status of UMD support (cover)
> - Don't use more specific compatible strings when not required (P1)
> - Avoid ABI break by limiting new required properties to new compatible
>   strings (P2)
> - Move power domain changes to the patch in which they're used (P2/P5)
> - Update register definitions (P3) [Thanks, Alessio!]
> - Don't use more specific compatible strings when not required (P4)
> - Enhanced commit messages (P4)
> - Remove unnecessary example (P5)
> - Add proper fixes for threaded IRQs (P6) [Thanks, Alessio!]
> - Include fix for a separate IRQ issue (P7) [Thanks, Alessio!]
> - Don't enable firmware debug module (was P13 in v2, also in P14)
> - Change from a workaround to a regular codepath (P15)
> - Drop platform overrides framework (was P18 in v2, also in P16)
> - Mark DTS changes [DO NOT MERGE] (P17/P18)
> - Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-0-3fd45d9fb0cf at imgtec.com
> 
> Changes in v2:
> - Clarified justification for compatible strings (P1)
> - Simplified clocks constraints (P2)
> - Simplified power-domains constraints (P3/P4)
> - Use normal reg syntax for 64-bit values (P8/P21)
> - Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-0-4ed30e865892 at imgtec.com
> 
> ---
> Alessio Belle (3):
>       drm/imagination: Update register defs for newer GPUs
>       drm/imagination: Mask GPU IRQs in threaded handler
>       drm/imagination: Handle Rogue safety event IRQs
> 
> Matt Coster (14):
>       dt-bindings: gpu: img: Future-proofing enhancements
>       dt-bindings: gpu: img: Add BXS-4-64 devicetree bindings
>       drm/imagination: Use new generic compatible string
>       drm/imagination: Add power domain control
>       drm/imagination: Remove firmware enable_reg
>       drm/imagination: Rename event_mask -> status_mask
>       drm/imagination: Make has_fixed_data_addr a value
>       drm/imagination: Use a lookup table for fw defs
>       drm/imagination: Use callbacks for fw irq handling
>       drm/imagination: Move ELF fw utils to common file
>       drm/imagination: Use cached memory with dma_coherent
>       drm/imagination: Add support for TI AM68 GPU
>       [DO NOT MERGE] arm64: dts: ti: k3-am62: New GPU binding details
>       [DO NOT MERGE] arm64: dts: ti: k3-j721s2: Add GPU node
> 
> Sarah Walker (1):
>       drm/imagination: Add RISC-V firmware processor support
> 
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml |  77 +++++++++-
>  arch/arm64/boot/dts/ti/k3-am62-main.dtsi           |   3 +-
>  arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi         |  12 ++
>  drivers/gpu/drm/imagination/Makefile               |   2 +
>  drivers/gpu/drm/imagination/pvr_device.c           | 124 ++++++++++++++--
>  drivers/gpu/drm/imagination/pvr_device.h           |  31 +++-
>  drivers/gpu/drm/imagination/pvr_drv.c              |  16 ++
>  drivers/gpu/drm/imagination/pvr_fw.c               |  28 +++-
>  drivers/gpu/drm/imagination/pvr_fw.h               |  85 +++++------
>  drivers/gpu/drm/imagination/pvr_fw_meta.c          |  23 +--
>  drivers/gpu/drm/imagination/pvr_fw_mips.c          |  82 ++---------
>  drivers/gpu/drm/imagination/pvr_fw_riscv.c         | 163 +++++++++++++++++++++
>  drivers/gpu/drm/imagination/pvr_fw_startstop.c     |  17 +++
>  drivers/gpu/drm/imagination/pvr_fw_util.c          |  67 +++++++++
>  drivers/gpu/drm/imagination/pvr_gem.c              |  10 +-
>  drivers/gpu/drm/imagination/pvr_gem.h              |   6 +-
>  drivers/gpu/drm/imagination/pvr_mmu.c              |   8 +-
>  drivers/gpu/drm/imagination/pvr_power.c            | 114 ++++++++++++++
>  drivers/gpu/drm/imagination/pvr_power.h            |   3 +
>  drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h    | 153 ++++++++++++++++---
>  drivers/gpu/drm/imagination/pvr_rogue_riscv.h      |  41 ++++++
>  21 files changed, 886 insertions(+), 179 deletions(-)
> ---
> base-commit: 10232dac98d3803ec4fcc0cd8a4d1bd2a09b3e18
> change-id: 20241021-sets-bxs-4-64-patch-v1-44cdf9cc555f
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/ti/' for 20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f at imgtec.com:

arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dahlia.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dev.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-beagleplay.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-mallow.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-ivy.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dahlia.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-yavia.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dev.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am62-lp-sk.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-yavia.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-mallow.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-sk.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#
arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-ivy.dtb: gpu at fd00000: power-domain-names: ['a'] is too short
	from schema $id: http://devicetree.org/schemas/gpu/img,powervr-rogue.yaml#







From kw at linux.com  Tue Mar 11 08:21:33 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 12 Mar 2025 00:21:33 +0900
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250311073216.ynw7rzmu36dwywij@uda0492258>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
 <20250311051806.smcu4o4dxpngimth@uda0492258>
 <20250311072546.GA277060@rocinante>
 <20250311073216.ynw7rzmu36dwywij@uda0492258>
Message-ID: <20250311152133.GC1381004@rocinante>

Hello,

[...]
> > No need to send a new version.
> > 
> > I will update the branch directly when I pull the patch.  Not to worry.
> 
> Thank you Krzysztof :)

Done.  Have a look at:

  https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/j721e&id=01d04dcd6e80f63ca5e97324ec17c20553947e35

Let me know if there is anything else to update.

Thank you!

	Krzysztof


From robh at kernel.org  Tue Mar 11 08:27:00 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 10:27:00 -0500
Subject: [PATCH v2 2/3] dt-bindings: mtd: microchip-nand: add atmel pmecc
In-Reply-To: <20250311122847.90081-3-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
 <20250311122847.90081-3-balamanikandan.gunasundar@microchip.com>
Message-ID: <20250311152700.GA3573545-robh@kernel.org>

On Tue, Mar 11, 2025 at 05:58:46PM +0530, Balamanikandan Gunasundar wrote:
> Add bindings for programmable multibit error correction code controller
> (PMECC).
> 
> Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
> ---
> 
> Changes in v2:
> - Rename filename to match compatible string
> - Add constraints for sam9x7
> - Droped unused dt labels 
> 
> .../devicetree/bindings/mtd/atmel-nand.txt    | 61 -----------------
>  .../bindings/mtd/microchip,pmecc.yaml         | 67 +++++++++++++++++++
>  2 files changed, 67 insertions(+), 61 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> index dbbc17a866f2..1934614a9298 100644
> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> @@ -1,64 +1,3 @@
> -* ECC engine (PMECC) bindings:
> -
> -Required properties:
> -- compatible: should be one of the following
> -	"atmel,at91sam9g45-pmecc"
> -	"atmel,sama5d4-pmecc"
> -	"atmel,sama5d2-pmecc"
> -	"microchip,sam9x60-pmecc"
> -	"microchip,sam9x7-pmecc", "atmel,at91sam9g45-pmecc"
> -- reg: should contain 2 register ranges. The first one is pointing to the PMECC
> -       block, and the second one to the PMECC_ERRLOC block.
> -
> -Example:
> -
> -	nfc_io: nfc-io at 70000000 {
> -		compatible = "atmel,sama5d3-nfc-io", "syscon";
> -		reg = <0x70000000 0x8000000>;
> -	};
> -
> -	pmecc: ecc-engine at ffffc070 {
> -		compatible = "atmel,at91sam9g45-pmecc";
> -                reg = <0xffffc070 0x490>,
> -                      <0xffffc500 0x100>;
> -	};
> -
> -	ebi: ebi at 10000000 {
> -		compatible = "atmel,sama5d3-ebi";
> -		#address-cells = <2>;
> -		#size-cells = <1>;
> -		atmel,smc = <&hsmc>;
> -		reg = <0x10000000 0x10000000
> -		       0x40000000 0x30000000>;
> -		ranges = <0x0 0x0 0x10000000 0x10000000
> -			  0x1 0x0 0x40000000 0x10000000
> -			  0x2 0x0 0x50000000 0x10000000
> -			  0x3 0x0 0x60000000 0x10000000>;
> -		clocks = <&mck>;
> -
> -                nand_controller: nand-controller {
> -			compatible = "atmel,sama5d3-nand-controller";
> -			atmel,nfc-sram = <&nfc_sram>;
> -			atmel,nfc-io = <&nfc_io>;
> -			ecc-engine = <&pmecc>;
> -			#address-cells = <2>;
> -			#size-cells = <1>;
> -			ranges;
> -
> -			nand at 3 {
> -				reg = <0x3 0x0 0x800000>;
> -				atmel,rb = <0>;
> -
> -				/*
> -				 * Put generic NAND/MTD properties and
> -				 * subnodes here.
> -				 */
> -			};
> -		};
> -	};
> -
> ------------------------------------------------------------------------
> -
>  Deprecated bindings (should not be used in new device trees):
>  
>  Required properties:
> diff --git a/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml b/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml
> new file mode 100644
> index 000000000000..98260a691a2e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/microchip,pmecc.yaml
> @@ -0,0 +1,67 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mtd/microchip,pmecc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip pmecc controller
> +
> +maintainers:
> +  - Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
> +
> +description: |

Don't need '|' if no formatting to preserve.

> +  Bindings for microchip Programmable Multibit Error Correction Code
> +  Controller (PMECC). pmecc is a programmable BCH encoder/decoder. This
> +  block is passed as the value to the "ecc-engine" property of microchip
> +  nand flash controller node.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - atmel,at91sam9g45-pmecc
> +          - atmel,sama5d2-pmecc
> +          - atmel,sama5d4-pmecc
> +          - microchip,sam9x60-pmecc
> +          - microchip,sam9x7-pmecc

Both alone and with a fallback should not be allowed. Pick one. A 
fallback is only useful if there's a driver/client that only understands 
the fallback and would work with the new implementation. IOW, if 'they 
are the same'.

> +      - items:
> +          - const: microchip,sam9x7-pmecc
> +          - const: atmel,at91sam9g45-pmecc
> +      - items:
> +          - const: microchip,sam9x60-pmecc
> +          - const: atmel,at91sam9g45-pmecc

Combine the last 2 'items' to 1 as the fallback is the same for both.

> +
> +  reg:
> +    items:
> +      - description: Base address and size of PMECC controller registers
> +      - description: Base address and size of PMECC_ERRLOC controller

Drop 'Base address and size of '.

> +
> +  clocks:
> +    description: The clock source for pmecc controller

For a single clock, what else would it be? Drop.

> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: microchip,sam9x7-pmecc
> +    then:
> +      properties:
> +        clocks:
> +          description: The clock source for pmecc controller

What's the purpose of this if/then? It doesn't do anything.

> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    ecc-engine at ffffc070 {
> +        compatible = "microchip,sam9x7-pmecc";
> +        reg = <0xffffe000 0x300>,
> +              <0xffffe600 0x100>;
> +        clocks = <&pmc 2 48>;
> +    };
> -- 
> 2.34.1
> 


From s-vadapalli at ti.com  Tue Mar 11 08:29:21 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 20:59:21 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250311152133.GC1381004@rocinante>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
 <20250311051806.smcu4o4dxpngimth@uda0492258>
 <20250311072546.GA277060@rocinante>
 <20250311073216.ynw7rzmu36dwywij@uda0492258>
 <20250311152133.GC1381004@rocinante>
Message-ID: <20250311152921.cwb7obw5bmlrhvsi@uda0492258>

On Wed, Mar 12, 2025 at 12:21:33AM +0900, Krzysztof Wilczy?ski wrote:
> Hello,
> 
> [...]
> > > No need to send a new version.
> > > 
> > > I will update the branch directly when I pull the patch.  Not to worry.
> > 
> > Thank you Krzysztof :)
> 
> Done.  Have a look at:
> 
>   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/j721e&id=01d04dcd6e80f63ca5e97324ec17c20553947e35
> 
> Let me know if there is anything else to update.

The changes look good to me. There seems to be a minor typo in the
commit message:
[kwilczynski: add a issing .linkdown_irq_regfield member set to

You probably meant "missing".

Thank you once again for fixing it without the need for a new patch.

Regards,
Siddharth.


From gregkh at linuxfoundation.org  Tue Mar 11 07:59:47 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Tue, 11 Mar 2025 15:59:47 +0100
Subject: [PATCH 5.10 321/462] drm/rockchip: cdn-dp: Use drm_connector_helper_hpd_irq_event()
In-Reply-To: <20250311145758.343076290@linuxfoundation.org>
References: <20250311145758.343076290@linuxfoundation.org>
Message-ID: <20250311145811.039581105@linuxfoundation.org>

5.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Thomas Zimmermann <tzimmermann at suse.de>

[ Upstream commit 666e1960464140cc4bc9203c203097e70b54c95a ]

The code for detecting and updating the connector status in
cdn_dp_pd_event_work() has a number of problems.

- It does not aquire the locks to call the detect helper and update
the connector status. These are struct drm_mode_config.connection_mutex
and struct drm_mode_config.mutex.

- It does not use drm_helper_probe_detect(), which helps with the
details of locking and detection.

- It uses the connector's status field to determine a change to
the connector status. The epoch_counter field is the correct one. The
field signals a change even if the connector status' value did not
change.

Replace the code with a call to drm_connector_helper_hpd_irq_event(),
which fixes all these problems.

Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
Fixes: 81632df69772 ("drm/rockchip: cdn-dp: do not use drm_helper_hpd_irq_event")
Cc: Chris Zhong <zyw at rock-chips.com>
Cc: Guenter Roeck <groeck at chromium.org>
Cc: Sandy Huang <hjc at rock-chips.com>
Cc: "Heiko St?bner" <heiko at sntech.de>
Cc: Andy Yan <andy.yan at rock-chips.com>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-rockchip at lists.infradead.org
Cc: <stable at vger.kernel.org> # v4.11+
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20241105133848.480407-1-tzimmermann at suse.de
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/gpu/drm/rockchip/cdn-dp-core.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 53cad1003ad77..a36646e234aec 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -915,9 +915,6 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
 {
 	struct cdn_dp_device *dp = container_of(work, struct cdn_dp_device,
 						event_work);
-	struct drm_connector *connector = &dp->connector;
-	enum drm_connector_status old_status;
-
 	int ret;
 
 	mutex_lock(&dp->lock);
@@ -979,11 +976,7 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
 
 out:
 	mutex_unlock(&dp->lock);
-
-	old_status = connector->status;
-	connector->status = connector->funcs->detect(connector, false);
-	if (old_status != connector->status)
-		drm_kms_helper_hotplug_event(dp->drm_dev);
+	drm_connector_helper_hpd_irq_event(&dp->connector);
 }
 
 static int cdn_dp_pd_event(struct notifier_block *nb,
-- 
2.39.5





From kw at linux.com  Tue Mar 11 08:34:23 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 12 Mar 2025 00:34:23 +0900
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250311152921.cwb7obw5bmlrhvsi@uda0492258>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250310210746.GA2377483@rocinante>
 <20250311051806.smcu4o4dxpngimth@uda0492258>
 <20250311072546.GA277060@rocinante>
 <20250311073216.ynw7rzmu36dwywij@uda0492258>
 <20250311152133.GC1381004@rocinante>
 <20250311152921.cwb7obw5bmlrhvsi@uda0492258>
Message-ID: <20250311153423.GD1381004@rocinante>

Hello,

[...]
> > > > No need to send a new version.
> > > > 
> > > > I will update the branch directly when I pull the patch.  Not to worry.
> > > 
> > > Thank you Krzysztof :)
> > 
> > Done.  Have a look at:
> > 
> >   https://web.git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=controller/j721e&id=01d04dcd6e80f63ca5e97324ec17c20553947e35
> > 
> > Let me know if there is anything else to update.
> 
> The changes look good to me. There seems to be a minor typo in the
> commit message:
> [kwilczynski: add a issing .linkdown_irq_regfield member set to
> 
> You probably meant "missing".

Oops... Fixed. :)  Thank you!

> Thank you once again for fixing it without the need for a new patch.

No worries.

	Krzysztof


From michal.kubiak at intel.com  Tue Mar 11 08:35:16 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Tue, 11 Mar 2025 16:35:16 +0100
Subject: [PATCH net-next 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <Z9BYNBaAGZbtbfa4@localhost.localdomain>

On Tue, Mar 11, 2025 at 01:18:32PM +0100, Lorenzo Bianconi wrote:
> Introduce missing metadata support for some xdp drivers setting metadata
> size building the skb from xdp_buff.
> Please note most of the drivers are just compile tested.
> 
> ---
> Lorenzo Bianconi (7):
>       net: mvneta: Add metadata support for xdp mode
>       net: mvpp2: Add metadata support for xdp mode
>       net: netsec: Add metadata support for xdp mode
>       net: octeontx2: Add metadata support for xdp mode
>       net: ethernet: mediatek: Add metadata support for xdp mode
>       net: mana: Add metadata support for xdp mode
>       net: ti: cpsw: Add metadata support for xdp mode
> 
>  drivers/net/ethernet/marvell/mvneta.c                  |  5 ++++-
>  drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c        |  8 ++++++--
>  drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 13 +++++++++----
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c            |  7 +++++--
>  drivers/net/ethernet/microsoft/mana/mana_bpf.c         |  2 +-
>  drivers/net/ethernet/microsoft/mana/mana_en.c          |  4 ++++
>  drivers/net/ethernet/socionext/netsec.c                |  7 +++++--
>  drivers/net/ethernet/ti/cpsw.c                         |  6 +++++-
>  drivers/net/ethernet/ti/cpsw_new.c                     |  6 +++++-
>  9 files changed, 44 insertions(+), 14 deletions(-)
> ---
> base-commit: 8ef890df4031121a94407c84659125cbccd3fdbe
> change-id: 20250310-mvneta-xdp-meta-3e0da8ef4498
> 
> Best regards,
> -- 
> Lorenzo Bianconi <lorenzo at kernel.org>
> 
> 

As far as I checked, all modified drivers use the Page Pool and set the XDP
headroom. So, a necessary space for metadata seems to be assured for all
of the drivers.
In summary, the series looks OK.

Thanks,
Michal

For the series:
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>


From Frank.li at nxp.com  Tue Mar 11 08:40:13 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 11 Mar 2025 11:40:13 -0400
Subject: [PATCH v13 4/5] firmware: imx: add driver for NXP EdgeLock
 Enclave
In-Reply-To: <20250311-imx-se-if-v13-4-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
 <20250311-imx-se-if-v13-4-9cc6d8fd6d1c@nxp.com>
Message-ID: <Z9BZXVCpNlxWQgVd@lizhi-Precision-Tower-5810>

On Tue, Mar 11, 2025 at 09:09:35PM +0530, Pankaj Gupta wrote:
> Add driver for enabling MU based communication interface to secure-enclave.
>
> NXP hardware IP(s) for secure-enclaves like Edgelock Enclave(ELE),
> are embedded in the SoC to support the features like HSM, SHE & V2X,
> using message based communication interface.
>
> The secure enclave FW communicates with Linux over single or multiple
> dedicated messaging unit(MU) based interface(s).
> Exists on i.MX SoC(s) like i.MX8ULP, i.MX93, i.MX95 etc.
>
> Other dependent kernel drivers will be:
> - NVMEM: that supports non-volatile devices like EFUSES,
>          managed by NXP's secure-enclave.
>
> Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
> ---
>  drivers/firmware/imx/Kconfig        |  13 +
>  drivers/firmware/imx/Makefile       |   2 +
>  drivers/firmware/imx/ele_base_msg.c | 372 ++++++++++++++++++++++++++
>  drivers/firmware/imx/ele_base_msg.h |  98 +++++++
>  drivers/firmware/imx/ele_common.c   | 329 +++++++++++++++++++++++
>  drivers/firmware/imx/ele_common.h   |  50 ++++
>  drivers/firmware/imx/se_ctrl.c      | 503 ++++++++++++++++++++++++++++++++++++
>  drivers/firmware/imx/se_ctrl.h      |  83 ++++++
>  include/linux/firmware/imx/se_api.h |  14 +
>  9 files changed, 1464 insertions(+)
>
> diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
> index c964f4924359..8a487df77976 100644
> --- a/drivers/firmware/imx/Kconfig
> +++ b/drivers/firmware/imx/Kconfig
> @@ -33,3 +33,16 @@ config IMX_SCMI_MISC_DRV
>  	  core that could provide misc functions such as board control.
>
>  	  This driver can also be built as a module.
> +
> +config IMX_SEC_ENCLAVE
> +	tristate "i.MX Embedded Secure Enclave - EdgeLock Enclave Firmware driver."
> +	depends on IMX_MBOX && ARCH_MXC && ARM64
> +	select FW_LOADER
> +	default m if ARCH_MXC
> +
> +	help
> +	  It is possible to use APIs exposed by the iMX Secure Enclave HW IP called:
> +	  - EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93),
> +	    like base, HSM, V2X & SHE using the SAB protocol via the shared Messaging
> +	    Unit. This driver exposes these interfaces via a set of file descriptors
> +	    allowing to configure shared memory, send and receive messages.
> diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
> index 8d046c341be8..4e1d2706535d 100644
> --- a/drivers/firmware/imx/Makefile
> +++ b/drivers/firmware/imx/Makefile
> @@ -2,3 +2,5 @@
>  obj-$(CONFIG_IMX_DSP)		+= imx-dsp.o
>  obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o
>  obj-${CONFIG_IMX_SCMI_MISC_DRV}	+= sm-misc.o
> +sec_enclave-objs		= se_ctrl.o ele_common.o ele_base_msg.o
> +obj-${CONFIG_IMX_SEC_ENCLAVE}	+= sec_enclave.o
> diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
> new file mode 100644
> index 000000000000..eea86f50d276
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_base_msg.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include <linux/types.h>
> +
> +#include <linux/completion.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/genalloc.h>
> +
> +#include "ele_base_msg.h"
> +#include "ele_common.h"
> +
> +#define FW_DBG_DUMP_FIXED_STR		"\nELEX: "
> +
> +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
> +{
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	dma_addr_t get_info_addr = 0;
> +	u32 *get_info_data = NULL;
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	memset(s_info, 0x0, sizeof(*s_info));
> +
> +	tx_msg = kzalloc(ELE_GET_INFO_REQ_MSG_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	rx_msg = kzalloc(ELE_GET_INFO_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	if (priv->mem_pool)
> +		get_info_data = gen_pool_dma_alloc(priv->mem_pool,
> +						   ELE_GET_INFO_BUFF_SZ,
> +						   &get_info_addr);
> +	else
> +		get_info_data = dma_alloc_coherent(priv->dev,
> +						   ELE_GET_INFO_BUFF_SZ,
> +						   &get_info_addr,
> +						   GFP_KERNEL);
> +	if (!get_info_data) {
> +		dev_dbg(priv->dev,
> +			"%s: Failed to allocate get_info_addr.\n",
> +			__func__);
> +		return -ENOMEM;
> +	}
> +
> +	ret = se_fill_cmd_msg_hdr(priv,
> +				  (struct se_msg_hdr *)&tx_msg->header,
> +				  ELE_GET_INFO_REQ,
> +				  ELE_GET_INFO_REQ_MSG_SZ,
> +				  true);
> +	if (ret)
> +		goto exit;
> +
> +	tx_msg->data[0] = upper_32_bits(get_info_addr);
> +	tx_msg->data[1] = lower_32_bits(get_info_addr);
> +	tx_msg->data[2] = sizeof(*s_info);
> +	ret = ele_msg_send_rcv(priv,
> +			       tx_msg,
> +			       ELE_GET_INFO_REQ_MSG_SZ,
> +			       rx_msg,
> +			       ELE_GET_INFO_RSP_MSG_SZ);
> +	if (ret < 0)
> +		goto exit;
> +
> +	ret = se_val_rsp_hdr_n_status(priv,
> +				      rx_msg,
> +				      ELE_GET_INFO_REQ,
> +				      ELE_GET_INFO_RSP_MSG_SZ,
> +				      true);
> +
> +	memcpy(s_info, get_info_data, sizeof(*s_info));
> +
> +exit:
> +	if (priv->mem_pool)
> +		gen_pool_free(priv->mem_pool,
> +			      (u64)get_info_data,
> +			      ELE_GET_INFO_BUFF_SZ);
> +	else
> +		dma_free_coherent(priv->dev,
> +				  ELE_GET_INFO_BUFF_SZ,
> +				  get_info_data,
> +				  get_info_addr);
> +
> +	return ret;
> +}
> +
> +int ele_fetch_soc_info(struct se_if_priv *priv, void *data)
> +{
> +	int err;
> +
> +	err = ele_get_info(priv, data);
> +	if (err < 0)
> +		return err;
> +
> +	return err;

any way you return err.

you can simple

	return ele_get_info(priv, data);

why need ele_fetch_soc_info() if it is simple wrap ele_get_info() ?

> +}
> +
> +int ele_ping(struct se_if_priv *priv)
> +{
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	tx_msg = kzalloc(ELE_PING_REQ_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	rx_msg = kzalloc(ELE_PING_RSP_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	ret = se_fill_cmd_msg_hdr(priv,
> +				  (struct se_msg_hdr *)&tx_msg->header,
> +				  ELE_PING_REQ, ELE_PING_REQ_SZ, true);
> +	if (ret) {
> +		dev_err(priv->dev, "Error: se_fill_cmd_msg_hdr failed.\n");
> +		return ret;
> +	}
> +
> +	ret = ele_msg_send_rcv(priv,
> +			       tx_msg,
> +			       ELE_PING_REQ_SZ,
> +			       rx_msg,
> +			       ELE_PING_RSP_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv,
> +				      rx_msg,
> +				      ELE_PING_REQ,
> +				      ELE_PING_RSP_SZ,
> +				      true);
> +
> +	return ret;
> +}
> +
> +int ele_service_swap(struct se_if_priv *priv,
> +		     phys_addr_t addr,
> +		     u32 addr_size, u16 flag)
> +{
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	tx_msg = kzalloc(ELE_SERVICE_SWAP_REQ_MSG_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	rx_msg = kzalloc(ELE_SERVICE_SWAP_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	ret = se_fill_cmd_msg_hdr(priv,
> +				  (struct se_msg_hdr *)&tx_msg->header,
> +				  ELE_SERVICE_SWAP_REQ,
> +				  ELE_SERVICE_SWAP_REQ_MSG_SZ, true);
> +	if (ret)
> +		return ret;
> +
> +	tx_msg->data[0] = flag;
> +	tx_msg->data[1] = addr_size;
> +	tx_msg->data[2] = ELE_NONE_VAL;
> +	tx_msg->data[3] = lower_32_bits(addr);
> +	tx_msg->data[4] = se_add_msg_crc((uint32_t *)&tx_msg[0],
> +					 ELE_SERVICE_SWAP_REQ_MSG_SZ);
> +	ret = ele_msg_send_rcv(priv,
> +			       tx_msg,
> +			       ELE_SERVICE_SWAP_REQ_MSG_SZ,
> +			       rx_msg,
> +			       ELE_SERVICE_SWAP_RSP_MSG_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv,
> +				      rx_msg,
> +				      ELE_SERVICE_SWAP_REQ,
> +				      ELE_SERVICE_SWAP_RSP_MSG_SZ,
> +				      true);
> +	if (ret)
> +		return ret;
> +
> +	if (flag == ELE_IMEM_EXPORT)
> +		ret = rx_msg->data[1];
> +	else
> +		ret = 0;
> +
> +	return ret;
> +}
> +
> +int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr)
> +{
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	tx_msg = kzalloc(ELE_FW_AUTH_REQ_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	rx_msg = kzalloc(ELE_FW_AUTH_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	ret = se_fill_cmd_msg_hdr(priv,
> +				  (struct se_msg_hdr *)&tx_msg->header,
> +				  ELE_FW_AUTH_REQ,
> +				  ELE_FW_AUTH_REQ_SZ,
> +				  true);
> +	if (ret)
> +		return ret;
> +
> +	tx_msg->data[1] = upper_32_bits(addr);
> +	tx_msg->data[0] = lower_32_bits(addr);
> +	tx_msg->data[2] = addr;
> +
> +	ret = ele_msg_send_rcv(priv,
> +			       tx_msg,
> +			       ELE_FW_AUTH_REQ_SZ,
> +			       rx_msg,
> +			       ELE_FW_AUTH_RSP_MSG_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv,
> +				      rx_msg,
> +				      ELE_FW_AUTH_REQ,
> +				      ELE_FW_AUTH_RSP_MSG_SZ,
> +				      true);
> +	return ret;
> +}
> +
> +int ele_debug_dump(struct se_if_priv *priv)
> +{
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	bool keep_logging;
> +	u8 dump_data[408];
> +	u8 fmt_str[256];
> +	int fmt_str_idx;
> +	int rcv_dbg_wd_ct;
> +	int msg_ex_cnt;
> +	int ret = 0;
> +	int w_ct;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	tx_msg = kzalloc(ELE_DEBUG_DUMP_REQ_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	rx_msg = kzalloc(ELE_DEBUG_DUMP_RSP_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	ret = se_fill_cmd_msg_hdr(priv,
> +				  &tx_msg->header,
> +				  ELE_DEBUG_DUMP_REQ,
> +				  ELE_DEBUG_DUMP_REQ_SZ,
> +				  true);
> +	if (ret)
> +		return ret;
> +
> +	msg_ex_cnt = 0;
> +	do {
> +		w_ct = 0;
> +		fmt_str_idx = 0;
> +		memset(rx_msg, 0xCC, ELE_DEBUG_DUMP_RSP_SZ);
> +
> +		ret = ele_msg_send_rcv(priv,
> +				       tx_msg,
> +				       ELE_DEBUG_DUMP_REQ_SZ,
> +				       rx_msg,
> +				       ELE_DEBUG_DUMP_RSP_SZ);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = se_val_rsp_hdr_n_status(priv,
> +					      rx_msg,
> +					      ELE_DEBUG_DUMP_REQ,
> +					      ELE_DEBUG_DUMP_RSP_SZ,
> +					      true);
> +		if (!ret) {
> +			rcv_dbg_wd_ct = rx_msg->header.size - ELE_NON_DUMP_BUFFER_SZ;
> +			memcpy(fmt_str, FW_DBG_DUMP_FIXED_STR, strlen(FW_DBG_DUMP_FIXED_STR));
> +			fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR);
> +			for (w_ct = 0; w_ct < rcv_dbg_wd_ct; w_ct++) {
> +				fmt_str[fmt_str_idx] = '0';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = 'x';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = '%';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = '0';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = '8';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = 'x';
> +				fmt_str_idx++;
> +				fmt_str[fmt_str_idx] = ' ';
> +				fmt_str_idx++;
> +				if (w_ct % 2) {
> +					memcpy(fmt_str + fmt_str_idx,
> +					       FW_DBG_DUMP_FIXED_STR,
> +					       strlen(FW_DBG_DUMP_FIXED_STR));
> +					fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR);
> +				}
> +			}
> +			keep_logging = (rx_msg->header.size < (ELE_DEBUG_DUMP_RSP_SZ >> 2)) ?
> +					false : true;
> +			keep_logging = keep_logging ?
> +						(msg_ex_cnt > ELE_MAX_DBG_DMP_PKT ? false : true) :
> +						false;
> +			/*
> +			 * Number of spaces = rcv_dbg_wd_ct
> +			 * DBG dump length in bytes = rcv_dbg_wd_ct * 4
> +			 *
> +			 * Since, one byte is represented as 2 character,
> +			 * DBG Dump string-length = rcv_dbg_wd_ct * 8
> +			 * Fixed string's string-length =
> +			 *                      strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct
> +			 *
> +			 * Total dump_data length = Number of spaces +
> +			 *                          DBG Dump string' string-length +
> +			 *                          Fixed string's string-length
> +			 *
> +			 * Total dump_data length = rcv_dbg_wd_ct + (rcv_dbg_wd_ct * 8) +
> +			 *                          strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct
> +			 */
> +
> +			snprintf(dump_data,
> +				 ((rcv_dbg_wd_ct * 9) +
> +				  (strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct)),
> +				  fmt_str,
> +				  rx_msg->data[1], rx_msg->data[2],
> +				  rx_msg->data[3], rx_msg->data[4],
> +				  rx_msg->data[5], rx_msg->data[6],
> +				  rx_msg->data[7], rx_msg->data[8],
> +				  rx_msg->data[9], rx_msg->data[10],
> +				  rx_msg->data[11], rx_msg->data[12],
> +				  rx_msg->data[13], rx_msg->data[14],
> +				  rx_msg->data[15], rx_msg->data[16],
> +				  rx_msg->data[17], rx_msg->data[18],
> +				  rx_msg->data[19], rx_msg->data[20]);
> +
> +			dev_err(priv->dev, "%s", dump_data);

I don't suggest construct format string, which will lost compiler check
and make code logic complex. can you directly use

	dev_err(priv->dev, "0x%08x ...", rx_msg->data[1], ...);



> +		} else {
> +			dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.", ret);
> +			break;
> +		}
> +		msg_ex_cnt++;
> +	} while (keep_logging);
> +
> +	return ret;
> +}
> diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h
> new file mode 100644
> index 000000000000..b8c9d9e29ae8
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_base_msg.h
> @@ -0,0 +1,98 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + *
> + * Header file for the EdgeLock Enclave Base API(s).
> + */
> +
> +#ifndef ELE_BASE_MSG_H
> +#define ELE_BASE_MSG_H
> +
> +#include <linux/device.h>
> +#include <linux/types.h>
> +
> +#include "se_ctrl.h"
> +
> +#define ELE_NONE_VAL			0x0
> +
> +#define ELE_GET_INFO_REQ		0xDA

Look like most people like low case hex number.

> +#define ELE_GET_INFO_REQ_MSG_SZ		0x10
> +#define ELE_GET_INFO_RSP_MSG_SZ		0x08
> +
> +#define SOC_ID_MASK			0x0000FFFF

use GEN_MASK

> +
> +#define MAX_UID_SIZE                     (16)
> +#define DEV_GETINFO_ROM_PATCH_SHA_SZ     (32)
> +#define DEV_GETINFO_FW_SHA_SZ            (32)
> +#define DEV_GETINFO_OEM_SRKH_SZ          (64)
> +#define DEV_GETINFO_MIN_VER_MASK	0xFF
> +#define DEV_GETINFO_MAJ_VER_MASK	0xFF00
> +#define ELE_DEV_INFO_EXTRA_SZ		0x60
> +
> +struct dev_info {
> +	u8  cmd;
> +	u8  ver;
> +	u16 length;
> +	u16 soc_id;
> +	u16 soc_rev;
> +	u16 lmda_val;
> +	u8  ssm_state;
> +	u8  dev_atts_api_ver;
> +	u8  uid[MAX_UID_SIZE];
> +	u8  sha_rom_patch[DEV_GETINFO_ROM_PATCH_SHA_SZ];
> +	u8  sha_fw[DEV_GETINFO_FW_SHA_SZ];
> +};
> +
> +struct dev_addn_info {
> +	u8  oem_srkh[DEV_GETINFO_OEM_SRKH_SZ];
> +	u8  trng_state;
> +	u8  csal_state;
> +	u8  imem_state;
> +	u8  reserved2;
> +};
> +
> +struct ele_dev_info {
> +	struct dev_info d_info;
> +	struct dev_addn_info d_addn_info;
> +};
> +
> +#define ELE_GET_INFO_BUFF_SZ		(sizeof(struct ele_dev_info) \
> +						+ ELE_DEV_INFO_EXTRA_SZ)
> +
> +#define GET_SERIAL_NUM_FROM_UID(x, uid_word_sz) \
> +	(((u64)(((u32 *)(x))[(uid_word_sz) - 1]) << 32) | ((u32 *)(x))[0])
> +
> +#define ELE_MAX_DBG_DMP_PKT		30
> +#define ELE_NON_DUMP_BUFFER_SZ		3
> +#define ELE_DEBUG_DUMP_REQ		0x21
> +#define ELE_DEBUG_DUMP_REQ_SZ		0x4
> +#define ELE_DEBUG_DUMP_RSP_SZ		0x5C
> +
> +#define ELE_PING_REQ			0x01
> +#define ELE_PING_REQ_SZ			0x04
> +#define ELE_PING_RSP_SZ			0x08
> +
> +#define ELE_SERVICE_SWAP_REQ		0xDF
> +#define ELE_SERVICE_SWAP_REQ_MSG_SZ	0x18
> +#define ELE_SERVICE_SWAP_RSP_MSG_SZ	0x0C
> +#define ELE_IMEM_SIZE			0x10000
> +#define ELE_IMEM_STATE_OK		0xCA
> +#define ELE_IMEM_STATE_BAD		0xFE
> +#define ELE_IMEM_STATE_WORD		0x27
> +#define ELE_IMEM_STATE_MASK		0x00ff0000
> +#define ELE_IMEM_EXPORT			0x1
> +#define ELE_IMEM_IMPORT			0x2
> +
> +#define ELE_FW_AUTH_REQ			0x02
> +#define ELE_FW_AUTH_REQ_SZ		0x10
> +#define ELE_FW_AUTH_RSP_MSG_SZ		0x08
> +
> +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info);
> +int ele_fetch_soc_info(struct se_if_priv *priv, void *data);
> +int ele_ping(struct se_if_priv *priv);
> +int ele_service_swap(struct se_if_priv *priv,
> +		     phys_addr_t addr,
> +		     u32 addr_size, u16 flag);
> +int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr);
> +int ele_debug_dump(struct se_if_priv *priv);
> +#endif
> diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
> new file mode 100644
> index 000000000000..3fa8182b302f
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_common.c
> @@ -0,0 +1,329 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include "ele_base_msg.h"
> +#include "ele_common.h"
> +
> +u32 se_add_msg_crc(u32 *msg, u32 msg_len)

Need comments why common crc library doesn't work for you.

> +{
> +	u32 nb_words = msg_len / (u32)sizeof(u32);

u32 nb_words = msg_len / sizeof(u32);

what's happen if msg_len % 4 != 0 ?

> +	u32 crc = 0;
> +	u32 i;
> +
> +	for (i = 0; i < nb_words - 1; i++)
> +		crc ^= *(msg + i);
> +
> +	return crc;
> +}
> +
> +int ele_msg_rcv(struct se_if_priv *priv,
> +		struct se_clbk_handle *se_clbk_hdl)
> +{
> +	int err = 0;
> +
> +	do {
> +		err = wait_for_completion_interruptible(&se_clbk_hdl->done);

Suggest add timeout to avoid possible deadlock.

> +		if (err == -ERESTARTSYS) {
> +			if (priv->waiting_rsp_clbk_hdl.rx_msg) {
> +				priv->waiting_rsp_clbk_hdl.signal_rcvd = true;
> +				continue;
> +			}
> +			dev_err(priv->dev,
> +				"Err[0x%x]:Interrupted by signal.\n",
> +				err);
> +			err = -EINTR;
> +			break;
> +		}
> +	} while (err != 0);
> +
> +	return err ? err : se_clbk_hdl->rx_msg_sz;
> +}
> +
> +int ele_msg_send(struct se_if_priv *priv,
> +		 void *tx_msg,
> +		 int tx_msg_sz)
> +{
> +	struct se_msg_hdr *header;

small tuning, struct se_msg_hdr *header = tx_msg;

> +	int err;
> +
> +	header = tx_msg;
> +
> +	/*
> +	 * Check that the size passed as argument matches the size
> +	 * carried in the message.
> +	 */
> +	if (header->size << 2 != tx_msg_sz) {
> +		dev_err(priv->dev,
> +			"User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
> +			*(u32 *)header,
> +			header->size << 2, tx_msg_sz);
> +		return -EINVAL;
> +	}
> +
> +	err = mbox_send_message(priv->tx_chan, tx_msg);
> +	if (err < 0) {
> +		dev_err(priv->dev, "Error: mbox_send_message failure.\n");
> +		return err;
> +	}
> +	err = tx_msg_sz;
> +
> +	return err;

return tx_msg_sz;

> +}
> +
> +/* API used for send/receive blocking call. */
> +int ele_msg_send_rcv(struct se_if_priv *priv,
> +		     void *tx_msg,
> +		     int tx_msg_sz,
> +		     void *rx_msg,
> +		     int exp_rx_msg_sz)
> +{
> +	int err;
> +
> +	guard(mutex)(&priv->se_if_cmd_lock);
> +
> +	priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
> +	priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
> +
> +	err = ele_msg_send(priv, tx_msg, tx_msg_sz);
> +	if (err < 0)
> +		return err;
> +
> +	err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl);
> +
> +	if (priv->waiting_rsp_clbk_hdl.signal_rcvd) {
> +		err = -EINTR;
> +		priv->waiting_rsp_clbk_hdl.signal_rcvd = false;
> +		dev_err(priv->dev,
> +			"Err[0x%x]:Interrupted by signal.\n",
> +			err);

small, tuning, 'err' can move to previous line, code allow wrap at 100 chars.

> +	}
> +
> +	return err;
> +}
> +
> +static bool exception_for_size(struct se_if_priv *priv,
> +			       struct se_msg_hdr *header)

look like check_header() make sense because you not only check size.

> +{
> +	/* List of API(s) that can be accepte variable length
> +	 * response buffer.
> +	 */
> +	if (header->command == ELE_DEBUG_DUMP_REQ &&
> +	    header->ver == priv->if_defs->base_api_ver &&
> +	    header->size >= 0 &&
> +	    header->size <= ELE_DEBUG_DUMP_RSP_SZ)
> +		return true;
> +
> +	return false;
> +}
> +
> +/*
> + * Callback called by mailbox FW, when data is received.
> + */
> +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
> +{
> +	struct se_clbk_handle *se_clbk_hdl;
> +	struct device *dev = mbox_cl->dev;
> +	struct se_msg_hdr *header;
> +	struct se_if_priv *priv;
> +	u32 rx_msg_sz;
> +
> +	priv = dev_get_drvdata(dev);
> +
> +	/* The function can be called with NULL msg */
> +	if (!msg) {
> +		dev_err(dev, "Message is invalid\n");
> +		return;
> +	}
> +
> +	header = msg;
> +	rx_msg_sz = header->size << 2;
> +
> +	/* Incoming command: wake up the receiver if any. */
> +	if (header->tag == priv->if_defs->cmd_tag) {
> +		se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
> +		dev_dbg(dev,
> +			"Selecting cmd receiver for mesg header:0x%x.",
> +			*(u32 *)header);
> +
> +		/* Pre-allocated buffer of MAX_NVM_MSG_LEN
> +		 * as the NVM command are initiated by FW.
> +		 * Size is revealed as part of this call function.
> +		 */
> +		if (rx_msg_sz > MAX_NVM_MSG_LEN) {
> +			dev_err(dev,
> +				"CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
> +				*(u32 *)header,
> +				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
> +
> +			se_clbk_hdl->rx_msg_sz = MAX_NVM_MSG_LEN;
> +		}
> +		se_clbk_hdl->rx_msg_sz = rx_msg_sz;
> +
> +	} else if (header->tag == priv->if_defs->rsp_tag) {
> +		se_clbk_hdl = &priv->waiting_rsp_clbk_hdl;
> +		dev_dbg(dev,
> +			"Selecting resp waiter for mesg header:0x%x.",
> +			*(u32 *)header);
> +
> +		if (rx_msg_sz != se_clbk_hdl->rx_msg_sz &&
> +		    !exception_for_size(priv, header)) {
> +			dev_err(dev,
> +				"Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
> +				*(u32 *)header,
> +				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
> +
> +			se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, se_clbk_hdl->rx_msg_sz);
> +		}
> +	} else {
> +		dev_err(dev, "Failed to select a device for message: %.8x\n",
> +			*((u32 *)header));
> +		return;
> +	}
> +
> +	memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz);
> +
> +	/* Allow user to read */
> +	complete(&se_clbk_hdl->done);
> +}
> +
> +int se_val_rsp_hdr_n_status(struct se_if_priv *priv,
> +			    struct se_api_msg *msg,
> +			    u8 msg_id,
> +			    u8 sz,
> +			    bool is_base_api)
> +{
> +	u32 status;
> +	struct se_msg_hdr *header = &msg->header;

struct se_msg_hdr *header = &msg->header;
u32 status;

> +
> +	if (header->tag != priv->if_defs->rsp_tag) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: Resp tag mismatch. (0x%x != 0x%x)",
> +			msg_id, header->tag, priv->if_defs->rsp_tag);
> +		return -EINVAL;
> +	}
> +
> +	if (header->command != msg_id) {
> +		dev_err(priv->dev,
> +			"MSG Header: Cmd id mismatch. (0x%x != 0x%x)",
> +			header->command, msg_id);
> +		return -EINVAL;
> +	}
> +
> +	if (header->size != (sz >> 2) && !exception_for_size(priv, header)) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: Cmd size mismatch. (0x%x != 0x%x)",
> +			msg_id, header->size, (sz >> 2));
> +		return -EINVAL;
> +	}
> +
> +	if (is_base_api && header->ver != priv->if_defs->base_api_ver) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: Base API Vers mismatch. (0x%x != 0x%x)",
> +			msg_id, header->ver, priv->if_defs->base_api_ver);
> +		return -EINVAL;
> +	} else if (!is_base_api && header->ver != priv->if_defs->fw_api_ver) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: FW API Vers mismatch. (0x%x != 0x%x)",
> +			msg_id, header->ver, priv->if_defs->fw_api_ver);
> +		return -EINVAL;
> +	}
> +
> +	status = RES_STATUS(msg->data[0]);
> +	if (status != priv->if_defs->success_tag) {
> +		dev_err(priv->dev, "Command Id[%x], Response Failure = 0x%x",
> +			header->command, status);
> +		return -EPERM;
> +	}
> +
> +	return 0;
> +}
> +
> +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
> +{
> +	struct ele_dev_info s_info = {0};
> +	int ret;
> +
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.\n");
> +		return ret;
> +	}
> +
> +	/* Do not save the IMEM buffer, if the current IMEM state is BAD. */
> +	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD)
> +		return ret;
> +
> +	/* EXPORT command will save encrypted IMEM to given address,
> +	 * so later in resume, IMEM can be restored from the given
> +	 * address.
> +	 *
> +	 * Size must be at least 64 kB.
> +	 */
> +	ret = ele_service_swap(priv,
> +			       imem->phyaddr,
> +			       ELE_IMEM_SIZE,
> +			       ELE_IMEM_EXPORT);
> +	if (ret < 0) {
> +		dev_err(priv->dev, "Failed to export IMEM\n");
> +		imem->size = 0;
> +	} else {
> +		dev_info(priv->dev,
> +			 "Exported %d bytes of encrypted IMEM\n",
> +			 ret);
> +		imem->size = ret;
> +	}
> +
> +	return ret > 0 ? 0 : -1;

-1 suggest use err code.

> +}
> +
> +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
> +{
> +	struct ele_dev_info s_info;
> +	int ret;
> +
> +	/* get info from ELE */
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.\n");
> +		return ret;
> +	}
> +	imem->state = s_info.d_addn_info.imem_state;
> +
> +	/* Get IMEM state, if 0xFE then import IMEM */
> +	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD && imem->size) {
> +		/* IMPORT command will restore IMEM from the given
> +		 * address, here size is the actual size returned by ELE
> +		 * during the export operation
> +		 */
> +		ret = ele_service_swap(priv,
> +				       imem->phyaddr,
> +				       imem->size,
> +				       ELE_IMEM_IMPORT);
> +		if (ret) {
> +			dev_err(priv->dev, "Failed to import IMEM\n");
> +			return ret;
> +		}
> +	} else {
> +		return ret;
> +	}


if (!(s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD && imem->size)
	return ret; /* do nothing if not use IMEM */

ret = ele_service_swap()
if (ret) {
	pr_err(...);
	return ret;
}

> +
> +	/* After importing IMEM, check if IMEM state is equal to 0xCA
> +	 * to ensure IMEM is fully loaded and
> +	 * ELE functionality can be used.
> +	 */
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.\n");
> +		return ret;
> +	}
> +	imem->state = s_info.d_addn_info.imem_state;
> +
> +	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_OK)
> +		dev_info(priv->dev, "Successfully restored IMEM\n");
> +	else
> +		dev_err(priv->dev, "Failed to restore IMEM\n");
> +
> +	return ret;
> +}
> diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
> new file mode 100644
> index 000000000000..aceb8c891ae6
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_common.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef __ELE_COMMON_H__
> +#define __ELE_COMMON_H__
> +
> +#include "se_ctrl.h"
> +
> +#define ELE_SUCCESS_IND			0xD6
> +
> +#define IMX_ELE_FW_DIR                 "imx/ele/"
> +
> +u32 se_add_msg_crc(u32 *msg, u32 msg_len);
> +int ele_msg_rcv(struct se_if_priv *priv,
> +		struct se_clbk_handle *se_clbk_hdl);
> +int ele_msg_send(struct se_if_priv *priv,
> +		 void *tx_msg,
> +		 int tx_msg_sz);
> +int ele_msg_send_rcv(struct se_if_priv *priv,
> +		     void *tx_msg,
> +		     int tx_msg_sz,
> +		     void *rx_msg,
> +		     int exp_rx_msg_sz);
> +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg);
> +int se_val_rsp_hdr_n_status(struct se_if_priv *priv,
> +			    struct se_api_msg *msg,
> +			    u8 msg_id,
> +			    u8 sz,
> +			    bool is_base_api);
> +
> +/* Fill a command message header with a given command ID and length in bytes. */
> +static inline int se_fill_cmd_msg_hdr(struct se_if_priv *priv,
> +				      struct se_msg_hdr *hdr,
> +				      u8 cmd, u32 len,
> +				      bool is_base_api)
> +{
> +	hdr->tag = priv->if_defs->cmd_tag;
> +	hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver;
> +	hdr->command = cmd;
> +	hdr->size = len >> 2;
> +
> +	return 0;
> +}
> +
> +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
> +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
> +
> +#endif /*__ELE_COMMON_H__ */
> diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
> new file mode 100644
> index 000000000000..12a1ceb87866
> --- /dev/null
> +++ b/drivers/firmware/imx/se_ctrl.c
> @@ -0,0 +1,503 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/dev_printk.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/firmware.h>
> +#include <linux/firmware/imx/se_api.h>
> +#include <linux/genalloc.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/miscdevice.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/sys_soc.h>
> +
> +#include "ele_base_msg.h"
> +#include "ele_common.h"
> +#include "se_ctrl.h"
> +
> +#define MAX_SOC_INFO_DATA_SZ		256
> +#define MBOX_TX_NAME			"tx"
> +#define MBOX_RX_NAME			"rx"
> +#define SE_TYPE_STR_HSM			"hsm"
> +#define SE_TYPE_ID_HSM			0x2
> +
> +struct se_fw_img_name {
> +	const u8 *prim_fw_nm_in_rfs;
> +	const u8 *seco_fw_nm_in_rfs;
> +};
> +
> +struct se_fw_load_info {
> +	const struct se_fw_img_name *se_fw_img_nm;
> +	bool is_fw_loaded;
> +	bool imem_mgmt;
> +	struct se_imem_buf imem;
> +};
> +
> +struct se_if_node {
> +	u8 se_if_id;
> +	u8 se_if_did;
> +	struct se_if_defines if_defs;
> +	u8 *pool_name;
> +	bool reserved_dma_ranges;
> +};
> +
> +/* contains fixed information */
> +struct se_soc_info {
> +	const u8 num_mu;
> +	const u16 soc_id;
> +	bool soc_register;
> +	int (*se_fetch_soc_info)(struct se_if_priv *priv, void *data);
> +	const struct se_fw_img_name se_fw_img_nm;
> +	const struct se_if_node if_node[];
> +};
> +
> +struct se_var_info {
> +	u16 soc_rev;
> +	struct se_fw_load_info load_fw;
> +};
> +
> +static struct se_var_info var_se_info = {
> +	.soc_rev = 0,
> +	.load_fw = {
> +		.is_fw_loaded = true,
> +		.imem_mgmt = false,
> +	},
> +};
> +
> +static struct se_soc_info se_imx8ulp_info = {
> +	.num_mu = 1,
> +	.soc_id = SOC_ID_OF_IMX8ULP,
> +	.soc_register = true,
> +	.se_fetch_soc_info = ele_fetch_soc_info,
> +	.se_fw_img_nm = {
> +		.prim_fw_nm_in_rfs = IMX_ELE_FW_DIR
> +			"mx8ulpa2-ahab-container.img",
> +		.seco_fw_nm_in_rfs = IMX_ELE_FW_DIR
> +			"mx8ulpa2ext-ahab-container.img",
> +	},
> +	.if_node = {
> +			{
> +			.se_if_id = 0,
> +			.se_if_did = 7,
> +			.if_defs = {
> +				.se_if_type = SE_TYPE_ID_HSM,
> +				.se_instance_id = 0,
> +				.cmd_tag = 0x17,
> +				.rsp_tag = 0xe1,
> +				.success_tag = ELE_SUCCESS_IND,
> +				.base_api_ver = MESSAGING_VERSION_6,
> +				.fw_api_ver = MESSAGING_VERSION_7,
> +			},
> +			.pool_name = "sram",
> +			.reserved_dma_ranges = true,
> +			},
> +	},
> +};
> +
> +static struct se_soc_info se_imx93_info = {
> +	.num_mu = 1,
> +	.soc_id = SOC_ID_OF_IMX93,
> +	.soc_register = false,
> +	.se_fetch_soc_info = ele_fetch_soc_info,
> +	.se_fw_img_nm = {
> +		.prim_fw_nm_in_rfs = NULL,
> +		.seco_fw_nm_in_rfs = NULL,
> +	},
> +	.if_node = {
> +			{
> +			.se_if_id = 0,
> +			.se_if_did = 3,
> +			.if_defs = {
> +				.se_if_type = SE_TYPE_ID_HSM,
> +				.se_instance_id = 0,
> +				.cmd_tag = 0x17,
> +				.rsp_tag = 0xe1,
> +				.success_tag = ELE_SUCCESS_IND,
> +				.base_api_ver = MESSAGING_VERSION_6,
> +				.fw_api_ver = MESSAGING_VERSION_7,
> +			},
> +			.reserved_dma_ranges = true,
> +			},
> +	},
> +};
> +
> +static const struct of_device_id se_match[] = {
> +	{ .compatible = "fsl,imx8ulp-se-ele-hsm", .data = (void *)&se_imx8ulp_info.if_node},

I remember needn't (void*);

> +	{ .compatible = "fsl,imx93-se-ele-hsm", .data = (void *)&se_imx93_info.if_node},
> +	{},
> +};
> +
> +static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv)
> +{
> +	return &var_se_info.load_fw;
> +}
> +
> +static int get_se_soc_info(struct se_if_priv *priv, const struct se_soc_info *se_info)
> +{
> +	struct se_fw_load_info *load_fw = get_load_fw_instance(priv);
> +	struct soc_device_attribute *attr;
> +	struct ele_dev_info *s_info;
> +	struct soc_device *sdev;
> +	u8 data[MAX_SOC_INFO_DATA_SZ];
> +	int err = 0;

Try Reverse christmas tree order.

> +
> +	/* This function should be called once.
> +	 * Check if the se_soc_rev is zero to continue.
> +	 */
> +	if (var_se_info.soc_rev)
> +		return err;
> +
> +	if (se_info->se_fetch_soc_info) {
> +		err = se_info->se_fetch_soc_info(priv, &data);
> +		if (err < 0) {
> +			dev_err(priv->dev, "Failed to fetch SoC Info.");
> +			return err;
> +		}
> +		s_info = (void *)data;
> +		var_se_info.soc_rev = s_info->d_info.soc_rev;
> +		load_fw->imem.state = s_info->d_addn_info.imem_state;
> +	} else {
> +		dev_err(priv->dev, "Failed to fetch SoC revision.");
> +		if (se_info->soc_register)
> +			dev_err(priv->dev, "Failed to do SoC registration.");
> +		return -EINVAL;

look this function call by probe because below you use devm_kzalloc().

return dev_err_probe(...);

> +	}
> +
> +	if (!se_info->soc_register)
> +		return 0;
> +
> +	attr = devm_kzalloc(priv->dev, sizeof(*attr), GFP_KERNEL);
> +	if (!attr)
> +		return -ENOMEM;
> +
> +	if (FIELD_GET(DEV_GETINFO_MIN_VER_MASK, var_se_info.soc_rev))
> +		attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x.%x",
> +						FIELD_GET(DEV_GETINFO_MIN_VER_MASK,
> +							  var_se_info.soc_rev),
> +						FIELD_GET(DEV_GETINFO_MAJ_VER_MASK,
> +							  var_se_info.soc_rev));
> +	else
> +		attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x",
> +						FIELD_GET(DEV_GETINFO_MAJ_VER_MASK,
> +							  var_se_info.soc_rev));
> +
> +	switch (se_info->soc_id) {
> +	case SOC_ID_OF_IMX8ULP:
> +		attr->soc_id = devm_kasprintf(priv->dev, GFP_KERNEL,
> +					      "i.MX8ULP");

No any format at all.

attr->soc_id = "i.MX8ULP";

> +		break;
> +	case SOC_ID_OF_IMX93:
> +		attr->soc_id = devm_kasprintf(priv->dev, GFP_KERNEL,
> +					      "i.MX93");

the same here.

> +		break;
> +	}
> +
> +	err = of_property_read_string(of_root, "model",
> +				      &attr->machine);
> +	if (err)
> +		return -EINVAL;
> +
> +	attr->family = devm_kasprintf(priv->dev, GFP_KERNEL, "Freescale i.MX");

the same here.

> +
> +	attr->serial_number = devm_kasprintf(priv->dev,
> +					     GFP_KERNEL, "%016llX",
> +					     GET_SERIAL_NUM_FROM_UID(s_info->d_info.uid,
> +								     MAX_UID_SIZE >> 2));
> +
> +	sdev = soc_device_register(attr);
> +	if (IS_ERR(sdev))
> +		return PTR_ERR(sdev);
> +
> +	return 0;
> +}
> +
> +static int se_load_firmware(struct se_if_priv *priv)
> +{
> +	struct se_fw_load_info *load_fw = get_load_fw_instance(priv);
> +	const struct firmware *fw;
> +	phys_addr_t se_fw_phyaddr;
> +	const u8 *se_img_file_to_load;
> +	u8 *se_fw_buf;
> +	int ret;
> +
> +	if (load_fw->is_fw_loaded)
> +		return 0;
> +
> +	se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs;
> +	if (load_fw->se_fw_img_nm->prim_fw_nm_in_rfs &&
> +	    load_fw->imem.state == ELE_IMEM_STATE_BAD)
> +		se_img_file_to_load = load_fw->se_fw_img_nm->prim_fw_nm_in_rfs;
> +
> +	do {
> +		ret = request_firmware(&fw, se_img_file_to_load, priv->dev);
> +		if (ret)
> +			return ret;
> +
> +		dev_info(priv->dev, "loading firmware %s\n", se_img_file_to_load);
> +
> +		/* allocate buffer to store the SE FW */
> +		se_fw_buf = dma_alloc_coherent(priv->dev, fw->size,
> +					       &se_fw_phyaddr, GFP_KERNEL);
> +		if (!se_fw_buf)
> +			return -ENOMEM;
> +
> +		memcpy(se_fw_buf, fw->data, fw->size);
> +		ret = ele_fw_authenticate(priv, se_fw_phyaddr);
> +		if (ret < 0) {
> +			dev_err(priv->dev,
> +				"Error %pe: Authenticate & load SE firmware %s.\n",
> +				ERR_PTR(ret),
> +				se_img_file_to_load);

miss dma_free_coherent()
if it call from probe(), use return dev_err_probe().

> +			ret = -EPERM;
> +		}
> +
> +		dma_free_coherent(priv->dev,
> +				  fw->size,
> +				  se_fw_buf,
> +				  se_fw_phyaddr);
> +
> +		release_firmware(fw);
> +		fw = NULL;
> +
> +		if (!ret && load_fw->imem.state == ELE_IMEM_STATE_BAD &&
> +		    se_img_file_to_load == load_fw->se_fw_img_nm->prim_fw_nm_in_rfs)
> +			se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs;
> +		else
> +			se_img_file_to_load = NULL;
> +
> +	} while (se_img_file_to_load);

why need loop here?
request_firmware is block function;

* request_firmware() - send firmware request and wait for it

If need retry, you need set max retry count;

> +
> +	if (!ret)
> +		load_fw->is_fw_loaded = true;
> +
> +	return ret;
> +}
> +
> +/* interface for managed res to free a mailbox channel */
> +static void if_mbox_free_channel(void *mbox_chan)
> +{
> +	mbox_free_channel(mbox_chan);
> +}
> +
> +static int se_if_request_channel(struct device *dev,
> +				 struct mbox_chan **chan,
> +				 struct mbox_client *cl,
> +				 const char *name)
> +{
> +	struct mbox_chan *t_chan;
> +	int ret = 0;
> +
> +	t_chan = mbox_request_channel_byname(cl, name);
> +	if (IS_ERR(t_chan)) {
> +		ret = PTR_ERR(t_chan);
> +		return dev_err_probe(dev, ret,
> +				     "Failed to request %s channel.", name);
> +	}

	if (IS_ERR(t_can))
		return dev_err_probe(dev, PTR_ERR(t_chan),
				     "Failed to request %s channel.", name);
> +
> +	ret = devm_add_action_or_reset(dev, if_mbox_free_channel, t_chan);
> +	if (ret) {
> +		ret = -EPERM;
> +		return dev_err_probe(dev, ret,
> +				     "Failed to add-action for removal of mbox: %s\n",
> +				     name);

the same here.

> +	}
> +	*chan = t_chan;
> +
> +	return ret;
> +}
> +
> +static void se_if_probe_cleanup(void *plat_dev)
> +{
> +	struct platform_device *pdev = plat_dev;
> +	struct device *dev = &pdev->dev;
> +	struct se_fw_load_info *load_fw;
> +	struct se_if_priv *priv;
> +
> +	priv = dev_get_drvdata(dev);
> +	load_fw = get_load_fw_instance(priv);
> +
> +	/* In se_if_request_channel(), passed the clean-up functional
> +	 * pointer reference as action to devm_add_action_or_reset().
> +	 * No need to free the mbox channels here.
> +	 */
> +
> +	/* free the buffer in se remove, previously allocated
> +	 * in se probe to store encrypted IMEM
> +	 */
> +	if (load_fw && load_fw->imem.buf) {
> +		dmam_free_coherent(dev,
> +				   ELE_IMEM_SIZE,
> +				   load_fw->imem.buf,
> +				   load_fw->imem.phyaddr);
> +		load_fw->imem.buf = NULL;
> +	}
> +
> +	/* No need to check, if reserved memory is allocated
> +	 * before calling for its release. Or clearing the
> +	 * un-set bit.
> +	 */
> +	of_reserved_mem_device_release(dev);
> +}
> +
> +static int se_if_probe(struct platform_device *pdev)
> +{
> +	const struct se_soc_info *se_info;
> +	const struct se_if_node *if_node;
> +	struct device *dev = &pdev->dev;
> +	struct se_fw_load_info *load_fw;
> +	struct se_if_priv *priv;
> +	int ret;
> +
> +	if_node = device_get_match_data(dev);
> +	if (!if_node)
> +		return -EINVAL;
> +
> +	se_info = container_of(if_node,
> +			       typeof(*se_info),
> +			       if_node[if_node->se_if_id]);

Use se_if_id is risk. redesign drv data to make it simple and easy
understand.

> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->dev = dev;
> +	priv->if_defs = &if_node->if_defs;
> +	dev_set_drvdata(dev, priv);
> +
> +	ret = devm_add_action_or_reset(dev, se_if_probe_cleanup, pdev);
> +	if (ret)
> +		return ret;
> +
> +	/* Mailbox client configuration */
> +	priv->se_mb_cl.dev		= dev;
> +	priv->se_mb_cl.tx_block		= false;
> +	priv->se_mb_cl.knows_txdone	= true;
> +	priv->se_mb_cl.rx_callback	= se_if_rx_callback;
> +
> +	ret = se_if_request_channel(dev, &priv->tx_chan,
> +				    &priv->se_mb_cl, MBOX_TX_NAME);
> +	if (ret)
> +		return ret;
> +
> +	ret = se_if_request_channel(dev, &priv->rx_chan,
> +				    &priv->se_mb_cl, MBOX_RX_NAME);
> +	if (ret)
> +		return ret;
> +
> +	mutex_init(&priv->se_if_cmd_lock);
> +
> +	init_completion(&priv->waiting_rsp_clbk_hdl.done);
> +	init_completion(&priv->cmd_receiver_clbk_hdl.done);
> +
> +	if (if_node->pool_name) {
> +		priv->mem_pool = of_gen_pool_get(dev->of_node,
> +						 if_node->pool_name, 0);
> +		if (!priv->mem_pool)
> +			return dev_err_probe(dev, -ENOMEM,
> +					     "Unable to get sram pool = %s.",
> +					     if_node->pool_name);
> +	}
> +
> +	if (if_node->reserved_dma_ranges) {
> +		ret = of_reserved_mem_device_init(dev);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					    "Failed to init reserved memory region.");
> +	}
> +
> +	if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) {
> +		ret = get_se_soc_info(priv, se_info);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "Failed to fetch SoC Info.");
> +	}
> +
> +	/* By default, there is no pending FW to be loaded.*/
> +	if (se_info->se_fw_img_nm.prim_fw_nm_in_rfs ||
> +	    se_info->se_fw_img_nm.seco_fw_nm_in_rfs) {
> +		load_fw = get_load_fw_instance(priv);
> +		load_fw->se_fw_img_nm = &se_info->se_fw_img_nm;
> +		load_fw->is_fw_loaded = false;
> +
> +		if (se_info->se_fw_img_nm.prim_fw_nm_in_rfs) {
> +			/* allocate buffer where SE store encrypted IMEM */
> +			load_fw->imem.buf = dmam_alloc_coherent(priv->dev, ELE_IMEM_SIZE,
> +								&load_fw->imem.phyaddr,
> +								GFP_KERNEL);
> +			if (!load_fw->imem.buf)
> +				return dev_err_probe(dev, -ENOMEM,
> +						     "dmam-alloc-failed: To store encr-IMEM.");
> +			load_fw->imem_mgmt = true;
> +		}
> +	}
> +	dev_info(dev, "i.MX secure-enclave: %s%d interface to firmware, configured.",
> +		 SE_TYPE_STR_HSM,
> +		 priv->if_defs->se_instance_id);
> +
> +	return ret;
> +}
> +
> +static void se_if_remove(struct platform_device *pdev)
> +{
> +	se_if_probe_cleanup(pdev);
> +}
> +
> +static int se_suspend(struct device *dev)
> +{
> +	struct se_if_priv *priv = dev_get_drvdata(dev);
> +	struct se_fw_load_info *load_fw;
> +	int ret = 0;
> +
> +	load_fw = get_load_fw_instance(priv);
> +
> +	if (load_fw->imem_mgmt)
> +		ret = se_save_imem_state(priv, &load_fw->imem);
> +
> +	return ret;
> +}
> +
> +static int se_resume(struct device *dev)
> +{
> +	struct se_if_priv *priv = dev_get_drvdata(dev);
> +	struct se_fw_load_info *load_fw;
> +
> +	load_fw = get_load_fw_instance(priv);
> +
> +	if (load_fw->imem_mgmt)
> +		se_restore_imem_state(priv, &load_fw->imem);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops se_pm = {
> +	SET_SYSTEM_SLEEP_PM_OPS(se_suspend, se_resume)
> +};
> +
> +static struct platform_driver se_driver = {
> +	.driver = {
> +		.name = "fsl-se",
> +		.of_match_table = se_match,
> +		.pm = &se_pm,
> +	},
> +	.probe = se_if_probe,
> +	.remove = se_if_remove,
> +};
> +MODULE_DEVICE_TABLE(of, se_match);
> +
> +module_platform_driver(se_driver);
> +MODULE_AUTHOR("Pankaj Gupta <pankaj.gupta at nxp.com>");
> +MODULE_DESCRIPTION("iMX Secure Enclave Driver.");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h
> new file mode 100644
> index 000000000000..32547bc97ca3
> --- /dev/null
> +++ b/drivers/firmware/imx/se_ctrl.h
> @@ -0,0 +1,83 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef SE_MU_H
> +#define SE_MU_H
> +
> +#include <linux/miscdevice.h>
> +#include <linux/semaphore.h>
> +#include <linux/mailbox_client.h>
> +
> +#define MAX_FW_LOAD_RETRIES		50
> +
> +#define RES_STATUS(x)			FIELD_GET(0x000000ff, x)
> +#define MAX_NVM_MSG_LEN			(256)
> +#define MESSAGING_VERSION_6		0x6
> +#define MESSAGING_VERSION_7		0x7
> +
> +struct se_clbk_handle {
> +	struct completion done;
> +	bool signal_rcvd;
> +	u32 rx_msg_sz;
> +	/* Assignment of the rx_msg buffer to held till the
> +	 * received content as part callback function, is copied.
> +	 */
> +	struct se_api_msg *rx_msg;
> +};
> +
> +struct se_imem_buf {
> +	u8 *buf;
> +	phys_addr_t phyaddr;
> +	u32 size;
> +	u32 state;
> +};
> +
> +/* Header of the messages exchange with the EdgeLock Enclave */
> +struct se_msg_hdr {
> +	u8 ver;
> +	u8 size;
> +	u8 command;
> +	u8 tag;
> +}  __packed;
> +
> +#define SE_MU_HDR_SZ	4
> +
> +struct se_api_msg {
> +	struct se_msg_hdr header;
> +	u32 data[];
> +};
> +
> +struct se_if_defines {
> +	const u8 se_if_type;
> +	const u8 se_instance_id;
> +	u8 cmd_tag;
> +	u8 rsp_tag;
> +	u8 success_tag;
> +	u8 base_api_ver;
> +	u8 fw_api_ver;
> +};
> +
> +struct se_if_priv {
> +	struct device *dev;
> +
> +	struct se_clbk_handle cmd_receiver_clbk_hdl;
> +	/* Update to the waiting_rsp_dev, to be protected
> +	 * under se_if_cmd_lock.
> +	 */
> +	struct se_clbk_handle waiting_rsp_clbk_hdl;
> +	/*
> +	 * prevent new command to be sent on the se interface while previous
> +	 * command is still processing. (response is awaited)
> +	 */
> +	struct mutex se_if_cmd_lock;
> +
> +	struct mbox_client se_mb_cl;
> +	struct mbox_chan *tx_chan, *rx_chan;
> +
> +	struct gen_pool *mem_pool;
> +	const struct se_if_defines *if_defs;
> +};
> +
> +#endif
> diff --git a/include/linux/firmware/imx/se_api.h b/include/linux/firmware/imx/se_api.h
> new file mode 100644
> index 000000000000..0d49eb109885
> --- /dev/null
> +++ b/include/linux/firmware/imx/se_api.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef __SE_API_H__
> +#define __SE_API_H__
> +
> +#include <linux/types.h>
> +
> +#define SOC_ID_OF_IMX8ULP		0x084D
> +#define SOC_ID_OF_IMX93			0x9300
> +
> +#endif /* __SE_API_H__ */
>
> --
> 2.43.0
>


From dianders at chromium.org  Tue Mar 11 08:41:46 2025
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 11 Mar 2025 08:41:46 -0700
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com> <20250307021811.46981-3-yangyicong@huawei.com>
 <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com> <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com>
Message-ID: <CAD=FV=Wy9-nDW-F+R1Aob6GOfP1Cnmr1gKkCO+WebA8ES7uu8A@mail.gmail.com>

Hi,

On Tue, Mar 11, 2025 at 1:33?AM Yicong Yang <yangyicong at huawei.com> wrote:
>
> On 2025/3/8 0:53, Doug Anderson wrote:
> > Hi,
> >
> > On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
> >>
> >> From: Yicong Yang <yangyicong at hisilicon.com>
> >>
> >> arm64 depends on the cpufreq driver to gain the maximum cpu frequency
> >> to convert the watchdog_thresh to perf event period. cpufreq drivers
> >> like cppc_cpufreq will be initialized lately after the initializing of
> >> the hard lockup detector so just use a safe cpufreq which will be
> >> inaccurency. Use a cpufreq notifier to adjust the event's period to
> >> a more accurate one.
> >>
> >> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
> >> ---
> >>  arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
> >>  1 file changed, 34 insertions(+)
> >>
> >> diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
> >> index dcd25322127c..719ae39e8bc0 100644
> >> --- a/arch/arm64/kernel/watchdog_hld.c
> >> +++ b/arch/arm64/kernel/watchdog_hld.c
> >> @@ -34,3 +34,37 @@ bool __init arch_perf_nmi_is_available(void)
> >>          */
> >>         return arm_pmu_irq_is_nmi();
> >>  }
> >> +
> >> +static int watchdog_freq_notifier_callback(struct notifier_block *nb,
> >> +                                          unsigned long val, void *data)
> >> +{
> >> +       struct cpufreq_policy *policy = data;
> >> +       unsigned long max_cpu_freq;
> >
> > Feels like max_cpu_freq should be a u64. It probably should have been
> > u64 in hw_nmi_get_sample_period() as well. Otherwise you could end up
> > with a problem if the max CPU frequency is above ~4.3GHz and "unsigned
> > long" is 32-bits (I think it technically could be?)
> >
>
> I guess this won't happen for arm64 and we're in kernel space. here I
> keep the same type with hw_nmi_get_sample_period() which is also using
> "unsigned long".

I guess I won't insist, but given that you use u64 explicitly
elsewhere it feels like you should be explicit that you need 64-bits
here too.


> >> +       for_each_cpu(cpu, policy->cpus) {
> >> +               max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> >> +               if (!max_cpu_freq)
> >> +                       continue;
> >> +
> >> +               new_period = watchdog_thresh * max_cpu_freq;
> >> +               hardlockup_detector_perf_adjust_period(cpu, new_period);
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static struct notifier_block watchdog_freq_notifier = {
> >> +       .notifier_call = watchdog_freq_notifier_callback,
> >> +};
> >> +
> >> +static int __init init_watchdog_freq_notifier(void)
> >> +{
> >> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
> >> +                                        CPUFREQ_POLICY_NOTIFIER);
> >> +}
> >> +core_initcall(init_watchdog_freq_notifier);
> >
> > I haven't dug into everything, but don't you have a potential blind
> > spot, though? What if the order is this:
> >
> > 1. hw_nmi_get_sample_period() is called
> > 2. cpufreq driver probes
> > 3. init_watchdog_freq_notifier() initcall runs
> >
> > Since the cpufreq driver proved before you registered for the
> > notifier, won't you miss the creation of the policy? Maybe instead of
> > registering for an initcall you should somehow trigger off the first
> > call to hw_nmi_get_sample_period() and register at that point in time?
> >
>
> for arm64 the watchdog_perf is registered after armv8 PMU driver's init,
> so the sequence is like:
>
> # core_initcall
> init_watchdog_freq_notifier()
> # device_initcall
> armv8_pmu_driver_init()
>   lockup_detector_retry_init()
>     schedule_work(&detector_work);
> # in detector work
> hw_nmi_get_sample_period() // notifier's already been registered
>
> so we'll always get the correct frequency, either by the cpufreq
> already registered or by the notifier which will update the
> frequency. Please correct me if I missed anything :)

Hmm, OK. So this relies on the fact that because the
init_watchdog_freq_notifier() is at "core" level that it'll pretty
much init before any of the other things. This type of thing is always
a little fragile but I guess it's OK.

What about if the order is different though? Again, I haven't traced
through it all, but I'm thinking:

# core_initcall
init_watchdog_freq_notifier()
# device_initcall
<cpufreq driver policy is created>

Now hardlockup_detector_perf_adjust_period() will be called before
armv8_pmu_driver_init(). Is that a problem?

I guess even worse would be if async probe was on and the cpufreq
driver and PMU driver were running at the same time?


-Doug


From robh at kernel.org  Tue Mar 11 08:42:39 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 10:42:39 -0500
Subject: [PATCH v2 3/3] dt-bindings: mtd: atmel-nand: add legacy nand
 controllers
In-Reply-To: <20250311122847.90081-4-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-1-balamanikandan.gunasundar@microchip.com>
 <20250311122847.90081-4-balamanikandan.gunasundar@microchip.com>
Message-ID: <20250311154239.GB3573545-robh@kernel.org>

On Tue, Mar 11, 2025 at 05:58:47PM +0530, Balamanikandan Gunasundar wrote:
> Add support for atmel legacy nand controllers. These bindings should not be
> used with the new device trees.
> 
> Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
> ---
> 
> Changes in v2:
> 
> - Filename matching the compatibles
> - Remove "bindings" from the subject
> - Remove "deprecated" as these are the only bindings available for the devices
> - Add missing constraints.
> - Add default for nand-ecc-mode
> - Add 32 in pmecc-cap for sama5d2
> - Add default for sector-size, pmecc-lookup-table-offset, nand-bus-width
> 
>  .../devicetree/bindings/mtd/atmel-nand.txt    | 116 -------------
>  .../devicetree/bindings/mtd/atmel-nand.yaml   | 163 ++++++++++++++++++
>  2 files changed, 163 insertions(+), 116 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.txt
>  create mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> deleted file mode 100644
> index 1934614a9298..000000000000
> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -Deprecated bindings (should not be used in new device trees):
> -
> -Required properties:
> -- compatible: The possible values are:
> -	"atmel,at91rm9200-nand"
> -	"atmel,sama5d2-nand"
> -	"atmel,sama5d4-nand"
> -- reg : should specify localbus address and size used for the chip,
> -	and hardware ECC controller if available.
> -	If the hardware ECC is PMECC, it should contain address and size for
> -	PMECC and PMECC Error Location controller.
> -	The PMECC lookup table address and size in ROM is optional. If not
> -	specified, driver will build it in runtime.
> -- atmel,nand-addr-offset : offset for the address latch.
> -- atmel,nand-cmd-offset : offset for the command latch.
> -- #address-cells, #size-cells : Must be present if the device has sub-nodes
> -  representing partitions.
> -
> -- gpios : specifies the gpio pins to control the NAND device. detect is an
> -  optional gpio and may be set to 0 if not present.
> -
> -Optional properties:
> -- atmel,nand-has-dma : boolean to support dma transfer for nand read/write.
> -- nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
> -  Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
> -  "soft_bch".
> -- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware,
> -  capable of BCH encoding and decoding, on devices where it is present.
> -- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
> -  Controller. Supported values are: 2, 4, 8, 12, 24. If the compatible string
> -  is "atmel,sama5d2-nand", 32 is also valid.
> -- atmel,pmecc-sector-size : sector size for ECC computation. Supported values
> -  are: 512, 1024.
> -- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
> -  for different sector size. First one is for sector size 512, the next is for
> -  sector size 1024. If not specified, driver will build the table in runtime.
> -- nand-bus-width : 8 or 16 bus width if not present 8
> -- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
> -
> -Nand Flash Controller(NFC) is an optional sub-node
> -Required properties:
> -- compatible : "atmel,sama5d3-nfc".
> -- reg : should specify the address and size used for NFC command registers,
> -        NFC registers and NFC SRAM. NFC SRAM address and size can be absent
> -        if don't want to use it.
> -- clocks: phandle to the peripheral clock
> -Optional properties:
> -- atmel,write-by-sram: boolean to enable NFC write by SRAM.
> -
> -Examples:
> -nand0: nand at 40000000,0 {
> -	compatible = "atmel,at91rm9200-nand";
> -	#address-cells = <1>;
> -	#size-cells = <1>;
> -	reg = <0x40000000 0x10000000
> -	       0xffffe800 0x200
> -	      >;
> -	atmel,nand-addr-offset = <21>;	/* ale */
> -	atmel,nand-cmd-offset = <22>;	/* cle */
> -	nand-on-flash-bbt;
> -	nand-ecc-mode = "soft";
> -	gpios = <&pioC 13 0	/* rdy */
> -		 &pioC 14 0 	/* nce */
> -		 0		/* cd */
> -		>;
> -	partition at 0 {
> -		...
> -	};
> -};
> -
> -/* for PMECC supported chips */
> -nand0: nand at 40000000 {
> -	compatible = "atmel,at91rm9200-nand";
> -	#address-cells = <1>;
> -	#size-cells = <1>;
> -	reg = < 0x40000000 0x10000000	/* bus addr & size */
> -		0xffffe000 0x00000600	/* PMECC addr & size */
> -		0xffffe600 0x00000200	/* PMECC ERRLOC addr & size */
> -		0x00100000 0x00100000	/* ROM addr & size */
> -		>;
> -	atmel,nand-addr-offset = <21>;	/* ale */
> -	atmel,nand-cmd-offset = <22>;	/* cle */
> -	nand-on-flash-bbt;
> -	nand-ecc-mode = "hw";
> -	atmel,has-pmecc;	/* enable PMECC */
> -	atmel,pmecc-cap = <2>;
> -	atmel,pmecc-sector-size = <512>;
> -	atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
> -	gpios = <&pioD 5 0	/* rdy */
> -		 &pioD 4 0	/* nce */
> -		 0		/* cd */
> -		>;
> -	partition at 0 {
> -		...
> -	};
> -};
> -
> -/* for NFC supported chips */
> -nand0: nand at 40000000 {
> -	compatible = "atmel,at91rm9200-nand";
> -	#address-cells = <1>;
> -	#size-cells = <1>;
> -	ranges;
> -        ...
> -        nfc at 70000000 {
> -		compatible = "atmel,sama5d3-nfc";
> -		#address-cells = <1>;
> -		#size-cells = <1>;
> -		clocks = <&hsmc_clk>
> -		reg = <
> -			0x70000000 0x10000000	/* NFC Command Registers */
> -			0xffffc000 0x00000070	/* NFC HSMC regs */
> -			0x00200000 0x00100000	/* NFC SRAM banks */
> -		>;
> -	};
> -};
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.yaml b/Documentation/devicetree/bindings/mtd/atmel-nand.yaml
> new file mode 100644
> index 000000000000..8afc4a144caf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.yaml
> @@ -0,0 +1,163 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mtd/atmel-nand.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Atmel NAND flash controller
> +
> +maintainers:
> +  - Balamanikandan Gunasundar <balamanikandan.gunasundar at microchip.com>
> +
> +description: |

Don't need '|'.

> +  Atmel nand flash controller. This should not be used for new device
> +  trees. For the latest controllers refer microchip,nand-controller.yaml

This reads more like the h/w changed in newer controllers. Make it clear 
this is deprecated. You can also put at the top-level:

deprecated: true

But you should only put that if you plan to update all in tree .dts 
files to the non-deprecated binding.

> +
> +properties:
> +  compatible:
> +    enum:
> +      - atmel,at91rm9200-nand
> +      - atmel,sama5d2-nand
> +      - atmel,sama5d4-nand
> +
> +  reg:
> +    description:
> +      The localbus address and size used for the chip, and hardware ECC
> +      controller if available. If the hardware ECC is PMECC, it should
> +      contain address and size for PMECC and PMECC Error Location
> +      controller. The PMECC lookup table address and size in ROM is
> +      optional. If not specified, driver will build it in runtime.
> +
> +  atmel,nand-addr-offset:
> +    description:
> +      offset for the address latch.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 31
> +
> +  atmel,nand-cmd-offset:
> +    description:
> +      offset for the command latch.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 31
> +
> +  '#address-cells': true

0-3 is okay?

> +
> +  '#size-cells': true

0-2 is okay?

> +
> +  gpios:
> +    description:
> +      specifies the gpio pins to control the NAND device. detect is an
> +      optional gpio and may be set to 0 if not present.

Which entry is detect? Need to define what each entry is.

> +    minItems: 1
> +    maxItems: 3
> +
> +  atmel,nand-has-dma:
> +    description:
> +      support dma transfer for nand read/write.
> +    $ref: /schemas/types.yaml#/definitions/flag
> +
> +  atmel,has-pmecc:
> +    description:
> +      enable Programmable Multibit ECC hardware, capable of BCH encoding
> +      and decoding, on devices where it is present.
> +    $ref: /schemas/types.yaml#/definitions/flag

All vendor specific properties go last.

> +
> +  nand-on-flash-bbt:
> +    description:
> +      enable on flash bbt option if not present false
> +    $ref: /schemas/types.yaml#/definitions/flag
> +
> +  nand-ecc-mode:
> +    description:
> +      operation mode of the NAND ecc
> +    enum:
> +      [none, soft, hw, hw_syndrome, hw_oob_first, soft_bch]
> +    default: soft
> +    $ref: /schemas/types.yaml#/definitions/string

You should be referencing mtd/raw-nand-chip.yaml either directly or 
indirectly. And then drop the type. Same on the others.

> +
> +
> +  atmel,pmecc-cap:
> +    description:
> +      error correct capability for Programmable Multibit ECC Controller.
> +    enum:
> +      [2, 4, 8, 12, 24, 32]
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +
> +  atmel,pmecc-sector-size:
> +    description:
> +      sector size for ECC computation.
> +    enum:
> +      [512, 1024]
> +    default: 512
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +
> +
> +  atmel,pmecc-lookup-table-offset:
> +    description:
> +      Two offsets of lookup table in ROM for different sector size. First
> +      one is for sector size 512, the next is for sector size 1024. If not
> +      specified, driver will build the table in runtime.
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    default: 512
> +
> +  nand-bus-width:

Before vendor specific properties.

> +    description:
> +      nand bus width
> +    enum:
> +      [8, 16]
> +    default: 8
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +
> +required:
> +  - compatible
> +  - reg
> +  - atmel,nand-addr-offset
> +  - atmel,nand-cmd-offset
> +  - "#address-cells"
> +  - "#size-cells"
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    nand at 40000000,0 {

Not a correct unit-address.

nand-controller is preferred node name.

> +        compatible = "atmel,at91rm9200-nand";
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        reg = <0x40000000 0x10000000
> +               0xffffe800 0x200>;
> +        atmel,nand-addr-offset = <21>;	/* ale */
> +        atmel,nand-cmd-offset = <22>;	/* cle */
> +        nand-on-flash-bbt;
> +        nand-ecc-mode = "soft";
> +        gpios = <&pioC 13 0	/* rdy */
> +                 &pioC 14 0 /* nce */
> +                 0		/* cd */
> +                >;
> +    };
> +  - |
> +    /* for PMECC supported chips */
> +    nand1 at 40000000 {
> +        compatible = "atmel,at91rm9200-nand";
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        reg = <0x40000000 0x10000000	/* bus addr & size */
> +               0xffffe000 0x00000600	/* PMECC addr & size */
> +               0xffffe600 0x00000200	/* PMECC ERRLOC addr & size */
> +               0x00100000 0x00100000>;	/* ROM addr & size */
> +
> +        atmel,nand-addr-offset = <21>;	/* ale */
> +        atmel,nand-cmd-offset = <22>;	/* cle */
> +        nand-on-flash-bbt;
> +        nand-ecc-mode = "hw";
> +        atmel,has-pmecc;	/* enable PMECC */
> +        atmel,pmecc-cap = <2>;
> +        atmel,pmecc-sector-size = <512>;
> +        atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
> +        gpios = <&pioD 5 0	/* rdy */
> +                 &pioD 4 0	/* nce */
> +                 0		/* cd */
> +                >;
> +    };
> -- 
> 2.34.1
> 


From s-vadapalli at ti.com  Tue Mar 11 08:42:59 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 11 Mar 2025 21:12:59 +0530
Subject: [PATCH net v3] net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
Message-ID: <20250311154259.102865-1-s-vadapalli@ti.com>

From: Vignesh Raghavendra <vigneshr at ti.com>

Registering the interrupts for TX or RX DMA Channels prior to registering
their respective NAPI callbacks can result in a NULL pointer dereference.
This is seen in practice as a random occurrence since it depends on the
randomness associated with the generation of traffic by Linux and the
reception of traffic from the wire.

Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
---

Hello,

This patch is based on commit
4d872d51bc9d Merge tag 'x86-urgent-2025-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
of Mainline Linux.

v2 of this patch is at:
https://lore.kernel.org/r/20250311130103.68971-1-s-vadapalli at ti.com/
Changes since v2:
- Updated error handling in am65_cpsw_nuss_init_rx_chns() by introducing
  a new "goto label" namely "err_request_irq", since there are 3 different
  error paths leading to the existing "goto label" named "err_flow", of
  which, only one of them requires an extra netif_napi_del() invocation.
  This change is based on the feedback from 
  Alexander Sverdlin <alexander.sverdlin at siemens.com>
  at:
  https://lore.kernel.org/r/02d685e2aa8721a119f528bde2f4ec9533101663.camel at siemens.com/

v1 of this patch is at:
https://lore.kernel.org/r/20250311061214.4111634-1-s-vadapalli at ti.com/
Changes since v1:
- Based on the feedback provided by Alexander Sverdlin <alexander.sverdlin at siemens.com>
  the patch has been updated to account for the cleanup path in terms of an imbalance
  between the number of successful netif_napi_add_tx/netif_napi_add calls and the
  number of successful devm_request_irq() calls. In the event of an error, we will
  always have one extra successful netif_napi_add_tx/netif_napi_add that needs to be
  cleaned up before we clean an equal number of netif_napi_add_tx/netif_napi_add and
  devm_request_irq.

Regards,
Siddharth.

 drivers/net/ethernet/ti/am65-cpsw-nuss.c | 32 +++++++++++++-----------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 2806238629f8..bef734c6e5c2 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2306,14 +2306,18 @@ static void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
 static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 {
 	struct device *dev = common->dev;
+	struct am65_cpsw_tx_chn *tx_chn;
 	int i, ret = 0;
 
 	for (i = 0; i < common->tx_ch_num; i++) {
-		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
+		tx_chn = &common->tx_chns[i];
 
 		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
 		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
 
+		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
+				  am65_cpsw_nuss_tx_poll);
+
 		ret = devm_request_irq(dev, tx_chn->irq,
 				       am65_cpsw_nuss_tx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2323,19 +2327,16 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 				tx_chn->id, tx_chn->irq, ret);
 			goto err;
 		}
-
-		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
-				  am65_cpsw_nuss_tx_poll);
 	}
 
 	return 0;
 
 err:
-	for (--i ; i >= 0 ; i--) {
-		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
-
-		netif_napi_del(&tx_chn->napi_tx);
+	netif_napi_del(&tx_chn->napi_tx);
+	for (--i; i >= 0; i--) {
+		tx_chn = &common->tx_chns[i];
 		devm_free_irq(dev, tx_chn->irq, tx_chn);
+		netif_napi_del(&tx_chn->napi_tx);
 	}
 
 	return ret;
@@ -2569,6 +2570,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			     HRTIMER_MODE_REL_PINNED);
 		flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
 
+		netif_napi_add(common->dma_ndev, &flow->napi_rx,
+			       am65_cpsw_nuss_rx_poll);
+
 		ret = devm_request_irq(dev, flow->irq,
 				       am65_cpsw_nuss_rx_irq,
 				       IRQF_TRIGGER_HIGH,
@@ -2577,11 +2581,8 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 			dev_err(dev, "failure requesting rx %d irq %u, %d\n",
 				i, flow->irq, ret);
 			flow->irq = -EINVAL;
-			goto err_flow;
+			goto err_request_irq;
 		}
-
-		netif_napi_add(common->dma_ndev, &flow->napi_rx,
-			       am65_cpsw_nuss_rx_poll);
 	}
 
 	/* setup classifier to route priorities to flows */
@@ -2589,11 +2590,14 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 
 	return 0;
 
+err_request_irq:
+	netif_napi_del(&flow->napi_rx);
+
 err_flow:
-	for (--i; i >= 0 ; i--) {
+	for (--i; i >= 0; i--) {
 		flow = &rx_chn->flows[i];
-		netif_napi_del(&flow->napi_rx);
 		devm_free_irq(dev, flow->irq, flow);
+		netif_napi_del(&flow->napi_rx);
 	}
 
 err:
-- 
2.34.1



From florian.fainelli at broadcom.com  Tue Mar 11 08:46:00 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Tue, 11 Mar 2025 08:46:00 -0700
Subject: [PATCH] mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
In-Reply-To: <20250311150136.46938-1-kamal.dasu@broadcom.com>
References: <20250311150136.46938-1-kamal.dasu@broadcom.com>
Message-ID: <aa4284fa-1f68-4c7e-8d58-1c5129adda27@broadcom.com>

On 3/11/25 08:01, Kamal Dasu wrote:
> cqhci timeouts observed on brcmstb platforms during suspend:
>    ...
>    [  164.832853] mmc0: cqhci: timeout for tag 18
>    ...
> 
> Adding cqhci_suspend()/resume() calls to disable cqe
> in sdhci_brcmstb_suspend()/resume() respectively to fix
> CQE timeouts seen on PM suspend.
> 
> Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)")
> Cc: stable at vger.kernel.org
> Signed-off-by: Kamal Dasu <kamal.dasu at broadcom.com>
> ---
>   drivers/mmc/host/sdhci-brcmstb.c | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 0ef4d578ade8..bf55a9185eb6 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -505,6 +505,12 @@ static int sdhci_brcmstb_suspend(struct device *dev)
>   	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);

Missing an int ret declaration here, otherwise that won't build.

>   
>   	clk_disable_unprepare(priv->base_clk);
> +	if (host->mmc->caps2 & MMC_CAP2_CQE) {
> +		ret = cqhci_suspend(host->mmc);
> +		if (ret)
> +			return ret;
> +	}
> +
>   	return sdhci_pltfm_suspend(dev);
>   }
>   
> @@ -529,6 +535,9 @@ static int sdhci_brcmstb_resume(struct device *dev)
>   			ret = clk_set_rate(priv->base_clk, priv->base_freq_hz);
>   	}
>   
> +	if (host->mmc->caps2 & MMC_CAP2_CQE)
> +		ret = cqhci_resume(host->mmc);
> +
>   	return ret;
>   }
>   #endif


-- 
Florian


From helgaas at kernel.org  Tue Mar 11 08:54:52 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 11 Mar 2025 10:54:52 -0500
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>
Message-ID: <20250311155452.GA629749@bhelgaas>

On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > -----Original Message-----
> > From: Bjorn Helgaas <helgaas at kernel.org>
> > Sent: 2025?3?10? 23:11
> > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > hardcodes
> > 
> > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > Use the domain number replace the hardcodes to uniquely identify
> > > different controller on i.MX8MQ platforms. No function changes.
> > >
> > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > ---
> > >  drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > >  1 file changed, 6 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > index 90ace941090f..ab9ebb783593 100644
> > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > @@ -41,7 +41,6 @@
> > >  #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > >  #define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > >  #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11, 8)
> > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > >
> > >  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > >  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct platform_device
> > *pdev)
> > >  	struct dw_pcie *pci;
> > >  	struct imx_pcie *imx_pcie;
> > >  	struct device_node *np;
> > > -	struct resource *dbi_base;
> > >  	struct device_node *node = dev->of_node;
> > >  	int i, ret, req_cnt;
> > >  	u16 val;
> > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > platform_device *pdev)
> > >  			return PTR_ERR(imx_pcie->phy_base);
> > >  	}
> > >
> > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev, 0,
> > &dbi_base);
> > > -	if (IS_ERR(pci->dbi_base))
> > > -		return PTR_ERR(pci->dbi_base);
> > 
> > This makes me wonder.
> > 
> > IIUC this means that previously we set controller_id to 1 if the first item in
> > devicetree "reg" was 0x33c00000, and now we will set controller_id to 1 if
> > the devicetree "linux,pci-domain" property is 1.
> > This is good, but I think this new dependency on the correct
> > "linux,pci-domain" in devicetree should be mentioned in the commit log.
> > 
> > My bigger worry is that we no longer set pci->dbi_base at all.  I see that the
> > only use of pci->dbi_base in pci-imx6.c was to determine the controller_id,
> > but this is a DWC-based driver, and the DWC core certainly uses
> > pci->dbi_base.  Are we sure that none of those DWC core paths are
> > important to pci-imx6.c?
> Hi Bjorn:
> Thanks for your concerns.
> Don't worry about the assignment of pci->dbi_base.
> If pci-imx6.c driver doesn't set it. DWC core driver would set it when
>  dw_pcie_get_resources() is invoked.

Great, thanks!  Maybe we can amend the commit log to mention that and
the new "linux,pci-domain" dependency.


From will at kernel.org  Tue Mar 11 08:57:16 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 15:57:16 +0000
Subject: [PATCH v8 12/14] iommu/arm-smmu-v3: Introduce struct
 arm_smmu_vmaster
In-Reply-To: <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
Message-ID: <20250311155714.GC5138@willie-the-truck>

On Tue, Feb 25, 2025 at 09:25:40AM -0800, Nicolin Chen wrote:
> Use it to store all vSMMU-related data. The vsid (Virtual Stream ID) will
> be the first use case. Since the vsid reader will be the eventq handler
> that already holds a streams_mutex, reuse that to fenche the vmaster too.

"fenche"?

> Also add a pair of arm_smmu_attach_prepare/commit_vmaster helpers to set
> or unset the master->vmaster point. Put these helpers inside the existing

s/point/pointer/

> arm_smmu_attach_prepare/commit().
> 
> For identity/blocked ops that don't call arm_smmu_attach_prepare/commit(),
> add a simpler arm_smmu_master_clear_vmaster helper to unset the vmaster.
> 
> Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
> Reviewed-by: Pranjal Shrivastavat <praan at google.com>

(per Pranjal: please fix his mis-spelling of his own name here and in
the other patches too!)

> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 28 ++++++++++++
>  .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 45 +++++++++++++++++++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 18 +++++++-
>  3 files changed, 90 insertions(+), 1 deletion(-)

[...]

> @@ -1055,9 +1062,30 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
>  				       struct iommu_domain *parent,
>  				       struct iommufd_ctx *ictx,
>  				       unsigned int viommu_type);
> +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> +				    struct arm_smmu_nested_domain *nested_domain);
> +void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
> +void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
>  #else
>  #define arm_smmu_hw_info NULL
>  #define arm_vsmmu_alloc NULL
> +
> +static inline int
> +arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> +				struct arm_smmu_nested_domain *nested_domain)
> +{
> +	return 0; /* NOP */
> +}

Please drop this comment.

> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> index 5aa2e7af58b4..6b712b1ab429 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
> @@ -85,6 +85,51 @@ static void arm_smmu_make_nested_domain_ste(
>  	}
>  }
>  
> +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> +				    struct arm_smmu_nested_domain *nested_domain)
> +{
> +	struct arm_smmu_vmaster *vmaster;
> +	unsigned long vsid;
> +	int ret;
> +
> +	iommu_group_mutex_assert(state->master->dev);
> +
> +	/* Skip invalid vSTE */
> +	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> +		return 0;

Ok, and we don't need to set 'state->vmaster' in this case because we
only report stage-1 faults back to the vSMMU?

With the nits fixed:

Acked-by: Will Deacon <will at kernel.org>

Thanks,

Will


From will at kernel.org  Tue Mar 11 08:56:02 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 15:56:02 +0000
Subject: [PATCH v8 14/14] iommu/arm-smmu-v3: Set MEV bit in nested STE
 for DoS mitigations
In-Reply-To: <f465dd9defdc0fc748c2fa2cfc829e37778a4ced.1740504232.git.nicolinc@nvidia.com>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f465dd9defdc0fc748c2fa2cfc829e37778a4ced.1740504232.git.nicolinc@nvidia.com>
Message-ID: <20250311155602.GA5138@willie-the-truck>

On Tue, Feb 25, 2025 at 09:25:42AM -0800, Nicolin Chen wrote:
> There is a DoS concern on the shared hardware event queue among devices
> passed through to VMs, that too many translation failures that belong to
> VMs could overflow the shared hardware event queue if those VMs or their
> VMMs don't handle/recover the devices properly.
> 
> The MEV bit in the STE allows to configure the SMMU HW to merge similar
> event records, though there is no guarantee. Set it in a nested STE for
> DoS mitigations.
> 
> In the future, we might want to enable the MEV for non-nested cases too
> such as domain->type == IOMMU_DOMAIN_UNMANAGED or even IOMMU_DOMAIN_DMA.
> 
> Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
> Reviewed-by: Pranjal Shrivastavat <praan at google.com>
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 1 +
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 2 ++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c         | 4 ++--
>  3 files changed, 5 insertions(+), 2 deletions(-)

Acked-by: Will Deacon <will at kernel.org>

Will


From will at kernel.org  Tue Mar 11 08:56:38 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 15:56:38 +0000
Subject: [PATCH v8 13/14] iommu/arm-smmu-v3: Report events that belong to
 devices attached to vIOMMU
In-Reply-To: <7f6813dc2b62f5f396ac3172dc2a7d9bf3b47536.1740504232.git.nicolinc@nvidia.com>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <7f6813dc2b62f5f396ac3172dc2a7d9bf3b47536.1740504232.git.nicolinc@nvidia.com>
Message-ID: <20250311155637.GB5138@willie-the-truck>

On Tue, Feb 25, 2025 at 09:25:41AM -0800, Nicolin Chen wrote:
> Aside from the IOPF framework, iommufd provides an additional pathway to
> report hardware events, via the vEVENTQ of vIOMMU infrastructure.
> 
> Define an iommu_vevent_arm_smmuv3 uAPI structure, and report stage-1 events
> in the threaded IRQ handler. Also, add another four event record types that
> can be forwarded to a VM.
> 
> Reviewed-by: Kevin Tian <kevin.tian at intel.com>
> Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
> Reviewed-by: Pranjal Shrivastavat <praan at google.com>
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  7 +++
>  include/uapi/linux/iommufd.h                  | 23 +++++++
>  .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 17 ++++++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 60 +++++++++++--------
>  4 files changed, 82 insertions(+), 25 deletions(-)

[...]

> @@ -1866,7 +1869,14 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
>  		goto out_unlock;
>  	}
>  
> -	ret = iommu_report_device_fault(master->dev, &fault_evt);
> +	if (event->stall) {
> +		ret = iommu_report_device_fault(master->dev, &fault_evt);
> +	} else {
> +		if (master->vmaster && !event->s2)
> +			ret = arm_vmaster_report_event(master->vmaster, evt);
> +		else
> +			ret = -EOPNOTSUPP; /* Unhandled events should be pinned */
> +	}

nit: You don't need this extra indentation.

Patch looks fine:

Acked-by: Will Deacon <will at kernel.org>

Will


From prabhakar.csengg at gmail.com  Tue Mar 11 09:00:06 2025
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Tue, 11 Mar 2025 16:00:06 +0000
Subject: [PATCH] ARM: shmobile: smp: Enforce shmobile_smp_* alignment
In-Reply-To: <CAMuHMdWXcRoqKz6S0sAtBpSM+_ghTs82wsN1dHvbHD5vO8W+7A@mail.gmail.com>
References: <c499234d559a0d95ad9472883e46077311051cd8.1741612208.git.geert+renesas@glider.be>
 <CA+V-a8tGuxgan7Zx0YedSByfFSgrg5gmR6Fy3dMDXwU+TscZzg@mail.gmail.com> <CAMuHMdWXcRoqKz6S0sAtBpSM+_ghTs82wsN1dHvbHD5vO8W+7A@mail.gmail.com>
Message-ID: <CA+V-a8v_FPt0XG-a8GXNaHbk9z02Phq8KWUO5E+LUKDEvgqHUg@mail.gmail.com>

Hi Geert,

On Tue, Mar 11, 2025 at 3:20?PM Geert Uytterhoeven <geert at linux-m68k.org> wrote:
>
> Hi Prabhakar,
>
> On Tue, 11 Mar 2025 at 16:11, Lad, Prabhakar <prabhakar.csengg at gmail.com> wrote:
> > On Mon, Mar 10, 2025 at 1:14?PM Geert Uytterhoeven
> > > When the addresses of the shmobile_smp_mpidr, shmobile_smp_fn, and
> > > shmobile_smp_arg variables are not multiples of 4 bytes, secondary CPU
> > > bring-up fails:
> > >
> > >     smp: Bringing up secondary CPUs ...
> > >     CPU1: failed to come online
> > >     CPU2: failed to come online
> > >     CPU3: failed to come online
> > >     smp: Brought up 1 node, 1 CPU
> > >
> > > Fix this by adding the missing alignment directive.
> > >
> > > Fixes: 4e960f52fce16a3b ("ARM: shmobile: Move shmobile_smp_{mpidr, fn, arg}[] from .text to .bss")
> >
> > I wonder if this fixes tag should go back a bit far as I was able to
> > reproduce this on 5.10-cip BSP kernel on RZ/G1E this was only seen
> > when CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE was enabled,
>
> 4e960f52fce16a3b is in v4.5, so it covers 5.10-cip.
>
Thanks for pointing.

Cheers,
Prabhakar


From krzk at kernel.org  Tue Mar 11 09:04:39 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 17:04:39 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <20250219080059.367045-5-patrice.chotard@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
Message-ID: <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>

On 19/02/2025 09:00, patrice.chotard at foss.st.com wrote:
> From: Patrice Chotard <patrice.chotard at foss.st.com>
> 
> Octo Memory Manager driver (OMM) manages:
>   - the muxing between 2 OSPI busses and 2 output ports.
>     There are 4 possible muxing configurations:
>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>         output is on port 2
>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>         OSPI2 output is on port 1
>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>   - the split of the memory area shared between the 2 OSPI instances.
>   - chip select selection override.
>   - the time between 2 transactions in multiplexed mode.
>   - check firewall access.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
> Signed-off-by: Christophe Kerello <christophe.kerello at foss.st.com>

Incorrect chain. You sent it, so you must be the last person signing it.

I was waiting for any ST review... did not happen, so if you wonder how
to speed things up, you got a hint. Anyway, many questions futher.


> +
> +		if (i == 1) {
> +			mm_ospi2_size = resource_size(&res);
> +
> +			/* check that OMM memory region 1 doesn't overlap memory region 2 */
> +			if (resource_overlaps(&res, &res1)) {
> +				dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
> +					mm_name[0], mm_name[1]);
> +				dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
> +
> +				return -EFAULT;
> +			}
> +		}
> +	}
> +
> +	syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
> +	if (IS_ERR(syscfg_regmap)) {
> +		dev_err(dev, "Failed to get st,syscfg-amcr property\n");
> +		return PTR_ERR(syscfg_regmap);

Same comments as usual, see further.

> +	}
> +
> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
> +					 &amcr_base);
> +	if (ret)
> +		return ret;
> +
> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
> +					 &amcr_mask);
> +	if (ret)
> +		return ret;
> +
> +	amcr = mm_ospi2_size / SZ_64M;
> +
> +	if (set)
> +		regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
> +
> +	/* read AMCR and check coherency with memory-map areas defined in DT */
> +	regmap_read(syscfg_regmap, amcr_base, &read_amcr);
> +	read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
> +
> +	if (amcr != read_amcr) {
> +		dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static int stm32_omm_enable_child_clock(struct device *dev, bool enable)
> +{
> +	/* As there is only 2 children, remember first child in case of error */
> +	struct clk *first_child_clk = NULL;
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	u8 i;
> +	int ret;
> +
> +	for (i = 0; i < omm->nb_child; i++) {
> +		if (enable) {
> +			ret = clk_prepare_enable(omm->child[i].clk);
> +			if (ret) {
> +				if (first_child_clk)
> +					clk_disable_unprepare(first_child_clk);

Function is called stm32_omm_enable_child_clock() but you disable.
Confusing. Probably should be called toggle.

> +
> +				dev_err(dev, "Can not enable clock\n");
> +				return ret;
> +			}
> +		} else {
> +			clk_disable_unprepare(omm->child[i].clk);
> +		}
> +
> +		first_child_clk = omm->child[i].clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_omm_configure(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	struct reset_control *rstc;
> +	unsigned long clk_rate, clk_rate_max = 0;
> +	int ret;
> +	u8 i;
> +	u32 mux = 0;

That's one big mess. Do not mix initialized declarations with
non-initialized in the same line. Then group initialized ones together
and use some reverse christmas tree.

Then the rest also should be organized.

> +	u32 cssel_ovr = 0;
> +	u32 req2ack = 0;
> +
> +	omm->clk = devm_clk_get(dev, NULL);

So here devm_clk_get, but later of_clk_get...

> +	if (IS_ERR(omm->clk)) {
> +		dev_err(dev, "Failed to get OMM clock (%ld)\n",
> +			PTR_ERR(omm->clk));
> +

No. There is no such code anywhere. Please don't upstream downstream,
but take upstream as template.

It is *always* return dev_err_probe. You are flooding dmesg in deferral
for no reason.

> +		return PTR_ERR(omm->clk);
> +	}
> +
> +	ret = pm_runtime_resume_and_get(dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* parse children's clock */
> +	for (i = 0; i < omm->nb_child; i++) {
> +		clk_rate = clk_get_rate(omm->child[i].clk);
> +		if (!clk_rate) {
> +			dev_err(dev, "Invalid clock rate\n");
> +			pm_runtime_disable(dev);
> +			goto err_clk_disable;
> +		}
> +
> +		if (clk_rate > clk_rate_max)
> +			clk_rate_max = clk_rate;
> +	}
> +
> +	rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
> +	if (IS_ERR(rstc)) {
> +		ret = dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
> +		pm_runtime_disable(dev);

Why? It was not enabled in this function. I cannot follow the logic,
feels like random set of calls. Each of your function is supposed to
reverse ONLY what it done so far.

> +		goto err_clk_disable;
> +	}
> +
> +	reset_control_assert(rstc);
> +	udelay(2);
> +	reset_control_deassert(rstc);
> +
> +	omm->cr = readl_relaxed(omm->io_base + OMM_CR);
> +	/* optional */
> +	ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
> +	if (!ret) {
> +		if (mux & CR_MUXEN) {
> +			ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
> +						   &req2ack);
> +			if (!ret && !req2ack) {
> +				req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
> +
> +				if (req2ack > 256)
> +					req2ack = 256;
> +			}
> +
> +			req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
> +
> +			omm->cr &= ~CR_REQ2ACK_MASK;
> +			omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
> +
> +			/*
> +			 * If the mux is enabled, the 2 OSPI clocks have to be
> +			 * always enabled
> +			 */
> +			ret = stm32_omm_enable_child_clock(dev, true);
> +			if (ret) {
> +				pm_runtime_disable(dev);
> +				goto err_clk_disable;
> +			}
> +		}
> +
> +		omm->cr &= ~CR_MUXENMODE_MASK;
> +		omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
> +	}
> +
> +	/* optional */
> +	ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
> +	if (!ret) {
> +		omm->cr &= ~CR_CSSEL_OVR_MASK;
> +		omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
> +		omm->cr |= CR_CSSEL_OVR_EN;
> +	}
> +
> +	omm->restore_omm = true;
> +	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
> +
> +	ret = stm32_omm_set_amcr(dev, true);
> +
> +err_clk_disable:
> +	pm_runtime_put_sync_suspend(dev);
> +
> +	return ret;
> +}
> +
> +static int stm32_omm_check_access(struct device *dev, struct device_node *np)
> +{
> +	struct stm32_firewall firewall;
> +	int ret;
> +
> +	ret = stm32_firewall_get_firewall(np, &firewall, 1);
> +	if (ret)
> +		return ret;
> +
> +	return stm32_firewall_grant_access(&firewall);
> +}
> +
> +static int stm32_omm_disable_child(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +	struct reset_control *reset;
> +	int ret;
> +	u8 i;
> +
> +	for (i = 0; i < omm->nb_child; i++) {
> +		ret = clk_prepare_enable(omm->child[i].clk);
> +		if (ret) {
> +			dev_err(dev, "Can not enable clock\n");
> +			return ret;
> +		}
> +
> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
> +		if (IS_ERR(reset)) {
> +			dev_err(dev, "Can't get child reset\n");

Why do you get reset of child? Parent is not suppposed to poke there.
You might not have the reset there in the first place and it would not
be an error.


> +			return PTR_ERR(reset);
> +		};
> +
> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
> +		reset_control_assert(reset);
> +		udelay(2);
> +		reset_control_deassert(reset);

No, the child should handle this, not parent.

> +
> +		reset_control_put(reset);
> +		clk_disable_unprepare(omm->child[i].clk);
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_omm_probe(struct platform_device *pdev)
> +{
> +	struct platform_device *vdev;
> +	struct device *dev = &pdev->dev;
> +	struct stm32_omm *omm;
> +	struct clk *clk;
> +	int ret;
> +	u8 child_access_granted = 0;

Keep inits/assignments together

> +	u8 i, j;
> +	bool child_access[OMM_CHILD_NB];
> +
> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
> +	if (!omm)
> +		return -ENOMEM;
> +
> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
> +	if (IS_ERR(omm->io_base))
> +		return PTR_ERR(omm->io_base);
> +
> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
> +	if (IS_ERR(omm->mm_res))
> +		return PTR_ERR(omm->mm_res);
> +
> +	/* check child's access */
> +	for_each_child_of_node_scoped(dev->of_node, child) {
> +		if (omm->nb_child >= OMM_CHILD_NB) {
> +			dev_err(dev, "Bad DT, found too much children\n");
> +			ret = -E2BIG;
> +			goto err_clk_release;
> +		}
> +
> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
> +			ret = -EINVAL;
> +			goto err_clk_release;
> +		}
> +
> +		ret = stm32_omm_check_access(dev, child);
> +		if (ret < 0 && ret != -EACCES)
> +			goto err_clk_release;
> +
> +		child_access[omm->nb_child] = false;
> +		if (!ret) {
> +			child_access_granted++;
> +			child_access[omm->nb_child] = true;
> +		}
> +
> +		omm->child[omm->nb_child].node = child;
> +
> +		clk = of_clk_get(child, 0);

Why are you taking children clock? And why with this API, not clk_get?
This looks like mixing clock provider in the clock consumer.

> +		if (IS_ERR(clk)) {
> +			dev_err(dev, "Can't get child clock\n");

Syntax is always return dev_err_probe (or ret = dev_err_probe).

> +			ret = PTR_ERR(clk);
> +			goto err_clk_release;
> +		};
> +
> +		omm->child[omm->nb_child].clk = clk;
> +		omm->nb_child++;
> +	}
> +
> +	if (omm->nb_child != OMM_CHILD_NB) {
> +		ret = -EINVAL;
> +		goto err_clk_release;
> +	}
> +
> +	platform_set_drvdata(pdev, omm);
> +
> +	pm_runtime_enable(dev);
> +
> +	/* check if OMM's resource access is granted */
> +	ret = stm32_omm_check_access(dev, dev->of_node);
> +	if (ret < 0 && ret != -EACCES)
> +		goto err_clk_release;
> +
> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
> +		/* Ensure both OSPI instance are disabled before configuring OMM */
> +		ret = stm32_omm_disable_child(dev);
> +		if (ret)
> +			goto err_clk_release;
> +
> +		ret = stm32_omm_configure(dev);
> +		if (ret)
> +			goto err_clk_release;
> +	} else {
> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
> +		/*
> +		 * AMCR can't be set, so check if current value is coherent
> +		 * with memory-map areas defined in DT
> +		 */
> +		ret = stm32_omm_set_amcr(dev, false);
> +		if (ret)
> +			goto err_clk_release;
> +	}
> +
> +	/* for each child, if resource access is granted and status "okay", probe it */
> +	for (i = 0; i < omm->nb_child; i++) {
> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))

If you have a device available, why do you create one more platform device?

> +			continue;
> +
> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);

Why you cannot just populate the children?

> +		if (!vdev) {
> +			dev_err(dev, "Failed to create Octo Memory Manager child\n");
> +			for (j = i; j > 0; --j) {
> +				if (omm->child[j].dev)
> +					of_platform_device_destroy(omm->child[j].dev, NULL);
> +			}
> +
> +			ret = -EINVAL;
> +			goto err_clk_release;
> +		}
> +		omm->child[i].dev = &vdev->dev;
> +	}
> +
> +err_clk_release:
> +	for (i = 0; i < omm->nb_child; i++)
> +		clk_put(omm->child[i].clk);
> +
> +	return ret;
> +}
> +
> +static void stm32_omm_remove(struct platform_device *pdev)
> +{
> +	struct stm32_omm *omm = platform_get_drvdata(pdev);
> +	int i;
> +
> +	for (i = 0; i < omm->nb_child; i++)
> +		if (omm->child[i].dev)
> +			of_platform_device_destroy(omm->child[i].dev, NULL);
> +
> +	if (omm->cr & CR_MUXEN)
> +		stm32_omm_enable_child_clock(&pdev->dev, false);
> +
> +	pm_runtime_disable(&pdev->dev);
> +}
> +
> +static const struct of_device_id stm32_omm_of_match[] = {
> +	{ .compatible = "st,stm32mp25-omm", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
> +
> +static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(omm->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	return clk_prepare_enable(omm->clk);
> +}
> +
> +static int __maybe_unused stm32_omm_suspend(struct device *dev)
> +{
> +	struct stm32_omm *omm = dev_get_drvdata(dev);
> +
> +	if (omm->restore_omm && omm->cr & CR_MUXEN)
> +		stm32_omm_enable_child_clock(dev, false);

Why do you enable child clock for suspend?

> +
> +	return pinctrl_pm_select_sleep_state(dev);
> +}
> +


Best regards,
Krzysztof


From james.clark at linaro.org  Tue Mar 11 09:06:31 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 11 Mar 2025 16:06:31 +0000
Subject: [PATCH v2] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <c31de6cb-f8f5-432c-b99e-68b10a24bc5e@arm.com>
References: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
 <c31de6cb-f8f5-432c-b99e-68b10a24bc5e@arm.com>
Message-ID: <16fd2023-1ffa-4e87-ad89-a7ccdd8ba458@linaro.org>



On 11/03/2025 3:00 pm, Suzuki K Poulose wrote:
> On 05/03/2025 15:07, James Clark wrote:
>> Add a test to confirm that default sink selection skips over an ETF
>> and returns an ETR even if it's further away.
>>
>> This also makes it easier to add new unit tests in the future.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>> Changes in v2:
>> - Let devm free everything rather than doing individual kfrees:
>> ?? "Like with managed drivers, KUnit-managed fake devices are
>> ?? automatically cleaned up when the test finishes, but can be manually
>> ?? cleaned up early with kunit_device_unregister()."
>> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1- 
>> james.clark at linaro.org
>> ---
>> ? drivers/hwtracing/coresight/Kconfig??????????????? |? 9 +++
>> ? drivers/hwtracing/coresight/Makefile?????????????? |? 3 +-
>> ? drivers/hwtracing/coresight/coresight-core.c?????? |? 1 +
>> ? .../hwtracing/coresight/coresight-kunit-tests.c??? | 77 ++++++++++++ 
>> ++++++++++
>> ? 4 files changed, 88 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/ 
>> coresight/Kconfig
>> index ecd7086a5b83..f064e3d172b3 100644
>> --- a/drivers/hwtracing/coresight/Kconfig
>> +++ b/drivers/hwtracing/coresight/Kconfig
>> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>> ??????? To compile this driver as a module, choose M here: the module 
>> will be
>> ??????? called coresight-dummy.
>> +
>> +config CORESIGHT_KUNIT_TESTS
>> +????? tristate "Enable Coresight unit tests"
>> +????? depends on KUNIT
>> +????? default KUNIT_ALL_TESTS
>> +????? help
>> +??????? Enable Coresight unit tests. Only useful for development and not
>> +??????? intended for production.
>> +
>> ? endif
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/ 
>> coresight/Makefile
>> index 8e62c3150aeb..96f0dfedb1bf 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o    
>> coresight-cti-platform.o \
>> ???????????? coresight-cti-sysfs.o
>> ? obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>> ? obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>> -coresight-ctcu-y := coresight-ctcu-core.o
>> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index bd0a7edd38c9..b101aa133ceb 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct 
>> coresight_device *csdev)
>> ????? }
>> ????? return csdev->def_sink;
>> ? }
>> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>> ? static int coresight_remove_sink_ref(struct device *dev, void *data)
>> ? {
>> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/ 
>> drivers/hwtracing/coresight/coresight-kunit-tests.c
>> new file mode 100644
>> index 000000000000..a136af05eaf4
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> @@ -0,0 +1,77 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#include <kunit/test.h>
>> +#include <kunit/device.h>
>> +#include <linux/coresight.h>
>> +
>> +#include "coresight-priv.h"
>> +
>> +static struct coresight_device *coresight_test_device(struct device 
>> *dev)
>> +{
>> +??? struct coresight_device *csdev = devm_kcalloc(dev, 1,
>> +???????????????????????????? sizeof(struct coresight_device),
>> +???????????????????????????? GFP_KERNEL);
>> +??? csdev->pdata = devm_kcalloc(dev, 1,
>> +?????????????????? sizeof(struct coresight_platform_data),
>> +?????????????????? GFP_KERNEL);
>> +??? return csdev;
>> +}
>> +
>> +static int coresight_test_cpuid(struct coresight_device *csdev)
>> +{
>> +??? return 0;
>> +}
>> +
>> +static void test_default_sink(struct kunit *test)
>> +{
>> +??? /*
>> +???? * ETM -> ETF -> ETR -> CATU
>> +???? *??????????????? ^
>> +???? *??????????????? | default
>> +???? */
>> +??? struct device *dev = kunit_device_register(test, "coresight_kunit");
>> +??? struct coresight_device *etm = coresight_test_device(dev),
>> +??????????????? *etf = coresight_test_device(dev),
>> +??????????????? *etr = coresight_test_device(dev),
>> +??????????????? *catu = coresight_test_device(dev);
>> +??? struct coresight_connection conn = {};
>> +??? struct coresight_ops_source src_ops = {.cpu_id = 
>> coresight_test_cpuid };
> 
> Do we need the trace_id() ? Why is this required ?
> 
> Suzuki
> 

Because it tests with per-cpu sources so it checks if any of the TRBE 
sinks have been assigned first:

  /* look for a default sink if we have not found for this device */
    if (!csdev->def_sink) {
       if (coresight_is_percpu_source(csdev))
	 csdev->def_sink = per_cpu(csdev_sink,
                                    source_ops(csdev)->cpu_id(csdev));

I think this test would probably fail if run somewhere TRBE was already 
probed. I can make the source subtype to be 
CORESIGHT_DEV_SUBTYPE_SOURCE_BUS for the test to work around it. Any 
value other than CORESIGHT_DEV_SUBTYPE_SOURCE_PROC will work. And then I 
can drop the fake cpu_id() callback.



From nicolinc at nvidia.com  Tue Mar 11 09:26:50 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 09:26:50 -0700
Subject: [PATCH v8 13/14] iommu/arm-smmu-v3: Report events that belong to
 devices attached to vIOMMU
In-Reply-To: <20250311155637.GB5138@willie-the-truck>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <7f6813dc2b62f5f396ac3172dc2a7d9bf3b47536.1740504232.git.nicolinc@nvidia.com>
 <20250311155637.GB5138@willie-the-truck>
Message-ID: <Z9BkSq6nLhzsMguU@Asurada-Nvidia>

On Tue, Mar 11, 2025 at 03:56:38PM +0000, Will Deacon wrote:
> On Tue, Feb 25, 2025 at 09:25:41AM -0800, Nicolin Chen wrote:
> > @@ -1866,7 +1869,14 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
> >  		goto out_unlock;
> >  	}
> >  
> > -	ret = iommu_report_device_fault(master->dev, &fault_evt);
> > +	if (event->stall) {
> > +		ret = iommu_report_device_fault(master->dev, &fault_evt);
> > +	} else {
> > +		if (master->vmaster && !event->s2)
> > +			ret = arm_vmaster_report_event(master->vmaster, evt);
> > +		else
> > +			ret = -EOPNOTSUPP; /* Unhandled events should be pinned */
> > +	}
> 
> nit: You don't need this extra indentation.

Yea, there was an extra lock in the previous version.

Fixed with:
-       if (event->stall) {
+       if (event->stall)
                ret = iommu_report_device_fault(master->dev, &fault_evt);
-       } else {
-               if (master->vmaster && !event->s2)
-                       ret = arm_vmaster_report_event(master->vmaster, evt);
-               else
-                       ret = -EOPNOTSUPP; /* Unhandled events should be pinned */
-       }
+       else    if (master->vmaster && !event->s2)
+               ret = arm_vmaster_report_event(master->vmaster, evt);
+       else
+               ret = -EOPNOTSUPP; /* Unhandled events should be pinned */

> Patch looks fine:
> 
> Acked-by: Will Deacon <will at kernel.org>

Thanks!

Nicolin


From mathieu.poirier at linaro.org  Tue Mar 11 09:27:25 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 11 Mar 2025 10:27:25 -0600
Subject: [PATCH v5 0/8] imx8mp: Add support to Run/Stall DSP via reset API
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <Z9BkbVHlx60VFD7q@p14s>

Thanks for the re-spin.  I will wait for Shawn and Sascha to review their
respective bits before picking up this set.

Mathieu

On Tue, Mar 11, 2025 at 10:58:03AM +0200, Daniel Baluta wrote:
> This patch series adds support to control the Run/Stall DSP bits found on
> i.MX8MP via the reset controller API instead of using the syscon API.
> 
> DSP found on i.MX8MP doesn't have a direct reset line so according to hardware
> design team in order to handle assert/deassert/reset functionality we
> need to use a combination of control bits from two modules.
> 
> Audio block control module:
> 	- for Run/Stall control bits of the DSP
> 
> Debug Access Port (DAP)
> 	- for Software Reset via IMX8M_DAP_PWRCTL register
> 
> The current implementation for IMX DSP Remotproc driver and for Sound Open
> Firmware driver (already upstream) uses the following approach:
> 	- maps the Audio Block Control address via syscon API through
>           the fsl,dsp-ctrl property of the dsp node.
> 	- maps the DAP address space using directly a call to ioremap
>           with IMX8M_DAP_DEBUG macro depicting the DAP base address.
> 
> The both approaches are problematic when comes to describing the address
> spaces via the DT:
> 	- for Audio Block Control, because it uses the syscon interface
> 	- for DAP because it hardcodes de base address instead of using a dt node.
> 
> This patch series aims to fix the Audio Block control usage of the
> syscon interface and replace it with Reset Controller interface.
> 
> Main advantages of using the Reset Controller API is that we stop
> abusing the syscon interface, offer a better probe ordering, PM runtime
> support. Main critique of using the Reset Controller API is that
> Run/Stall bits are not reset bits (but according the hardware design
> team they are part of the reset proccess since there is no real reset
> line).
> 
> Initial discussion is here:
> https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/
> 
> Note that we can safely remove the fsl,dsp-ctrl property usage from IMX DSP
> remoteproc driver because there is no Device Tree users.
> 
> Changes since v4:
> https://lore.kernel.org/lkml/20250305100037.373782-3-daniel.baluta at nxp.com/T/
> 	- picked-up R-b tags from Frank Li and Peng Fan
> 	- reworded commit message of patch 8/8 as per Mathieu Poirier suggestion
> 
> Changes since v3:
> https://lore.kernel.org/linux-arm-kernel/20250225102005.408773-5-daniel.baluta at nxp.com/T/
> 	- renamed resets ids as per Philipp comments
> 	- add boths resets (named them runstall and softreset) as per Philipp comments
> 
> Changes since v2:
> (https://lore.kernel.org/lkml/Z7ZNngd3wtJ5MZgl at lizhi-Precision-Tower-5810/T/)
>         - picked R-b and A-b tags
>         - use run_stall instead of reset to refer to reset controller
>           instance
>         - remove 'resets' description as it is a common property
>         - add correct include in the yaml dts snippet example
> Changes since v1:
> (https://lore.kernel.org/imx/20250219030809.GD6537 at nxa18884-linux/T/)
>         - addresed comments received on v1
>         - picked up R-b and A-b tags
> 
> Daniel Baluta (8):
>   dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
>   dt-bindings: dsp: fsl,dsp: Add resets property
>   arm64: dts: imx8mp: Use resets property
>   reset: imx8mp-audiomix: Add prefix for internal macro
>   reset: imx8mp-audiomix: Prepare the code for more reset bits
>   reset: imx8mp-audiomix: Introduce active_low configuration option
>   reset: imx8mp-audiomix: Add support for DSP run/stall
>   imx_dsp_rproc: Use reset controller API to control the DSP
> 
>  .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 +++++-
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi     |  3 +
>  drivers/remoteproc/imx_dsp_rproc.c            | 25 ++++--
>  drivers/remoteproc/imx_rproc.h                |  2 +
>  drivers/reset/reset-imx8mp-audiomix.c         | 78 +++++++++++++------
>  .../dt-bindings/reset/imx8mp-reset-audiomix.h | 13 ++++
>  6 files changed, 114 insertions(+), 31 deletions(-)
>  create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h
> 
> -- 
> 2.43.0
> 


From laurentiumihalcea111 at gmail.com  Tue Mar 11 09:32:54 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 11 Mar 2025 12:32:54 -0400
Subject: [PATCH v5 2/3] ASoC: dt-bindings: audio-graph-card2: add widgets and hp-det-gpios support
In-Reply-To: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
References: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250311163255.2664-3-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Introduce the 'widgets' property, allowing the creation of widgets from
4 template widgets: Microphone, Line, Headphone, and Speaker. Also
introduce the 'hp-det-gpios' property, which allows using headphone
detection using the specified GPIO.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
---
 .../devicetree/bindings/sound/audio-graph-card2.yaml          | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml b/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
index f943f90d8b15..94588353f852 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
@@ -37,6 +37,10 @@ properties:
   codec2codec:
     type: object
     description: Codec to Codec node
+  hp-det-gpios:
+    $ref: audio-graph.yaml#/properties/hp-det-gpios
+  widgets:
+    $ref: audio-graph.yaml#/properties/widgets
 
 required:
   - compatible
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Tue Mar 11 09:32:52 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 11 Mar 2025 12:32:52 -0400
Subject: [PATCH v5 0/3] add sof support on imx95
Message-ID: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Add sof support on imx95. This series also includes some changes to
the audio-graph-card2 binding required for the support.

---
Changes in v5:
- added comment in the DTS regarding the reserved DMA channels.
- addressed Frank's comment regarding the widgets/routing properties.
- changed codec and CPU EP names to include SAI3/WM8962 in their naming.
Previous naming was too generic.
- picked up some more R-b's
- change soundcard DT node name to the more generic "sof-sound" as the
soundcard might support additional DAI-CODEC links in the future.
- change the soundcard label to "audio". Same rationale as above. The
SOF core will append to it the "sof-" prefix, thus the resulting name will
be "sof-audio".
- Link to v4: https://lore.kernel.org/lkml/20250211225808.3050-1-laurentiumihalcea111 at gmail.com/

Changes in v4:
- addressed Frank's comments regarding the DTS.
- squashed commits for common and imx95 bindings.
- dropped patch introducing driver. This was already handled via
https://lore.kernel.org/all/20250207162246.3104-1-laurentiumihalcea111 at gmail.com/
- introduced two new properties: 'reg-names' and 'memory-region-names',
which are now needed by the driver to work properly. Because of this, 'reg'
and 'memory-region' properties had to be moved from the common binding as
'reg-names' and 'memory-region-names' depend on them (you'd get a failure
when running the binding check otherwise).
- added missing 'bitclock-master' and 'frame-master' properties to codec EP.
- addressed Krzysztof's comments regarding the imx95 binding
- added Krzysztof's Acked-by
- Link to v3: https://lore.kernel.org/lkml/20241216145039.3074-1-laurentiumihalcea111 at gmail.com/

Changes in v3:
- Ordered DT nodes alphabetically
- Removed 'cpu' and 'cpu_ep' labels from binding example
- Some small changes to the binding commit messages/titles.
- Link to v2: https://lore.kernel.org/lkml/20241113195240.3699-1-laurentiumihalcea111 at gmail.com/

Changes in v2:
- Added new binding for 95's CM7 core with SOF. fsl,dsp.yaml is no longer used.
- "hp-det-gpios" and "widgets" properties now reference the definitions from audio-graph.yaml
- Removed extra empty spaces from DTS as suggested by Frank
- Ordered 'edma2', 'sai3', 'wm8962' DT nodes alphabetically. The order of the nodes
placed inside / is kept the same for readability
- Ordered driver header files includes alphabetically as suggested by Frank
- Removed "reg-names" and changed the maximum size of the "reg" property to 1 to align
with the other NXP CPUs sharing the same programming model (i.e: audio processing with SOF).
The region described in the DTS is the SRAM and the mailbox region is now hardcoded in the
driver as an offset to the start of the SRAM region.
- Added new binding with properties required by all NXP CPUs sharing the same programming
model (i.e: audio processing with SOF).
- Various driver adjustments made to accomodate the DT changes + some bug fixing related
to the mboxes not being requested/free'd on resume/suspend.
- Fixed value passed to "dma-channel-mask". A set bit means the channel is masked, not the
other way around.
- Link to v1: https://lore.kernel.org/lkml/20241023162114.3354-1-laurentiumihalcea111 at gmail.com/
---

Laurentiu Mihalcea (3):
  ASoC: dt-bindings: support imx95's CM7 core
  ASoC: dt-bindings: audio-graph-card2: add widgets and hp-det-gpios
    support
  arm64: dts: imx: add imx95 dts for sof

 .../bindings/sound/audio-graph-card2.yaml     |  4 +
 .../bindings/sound/fsl,imx95-cm7-sof.yaml     | 64 ++++++++++++++
 .../bindings/sound/fsl,sof-cpu.yaml           | 27 ++++++
 arch/arm64/boot/dts/freescale/Makefile        |  1 +
 .../dts/freescale/imx95-19x19-evk-sof.dts     | 84 +++++++++++++++++++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
 create mode 100644 arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts

-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Tue Mar 11 09:32:53 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 11 Mar 2025 12:32:53 -0400
Subject: [PATCH v5 1/3] ASoC: dt-bindings: support imx95's CM7 core
In-Reply-To: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
References: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250311163255.2664-2-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Add binding for imx95's CM7 core, used for audio processing.
Additionally, introduce a common binding for NXP audio processors with
Sound Open Firmware (SOF) support.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
---
 .../bindings/sound/fsl,imx95-cm7-sof.yaml     | 64 +++++++++++++++++++
 .../bindings/sound/fsl,sof-cpu.yaml           | 27 ++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml

diff --git a/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml b/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml
new file mode 100644
index 000000000000..f00ae3219e15
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,imx95-cm7-sof.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP imx95 CM7 core
+
+maintainers:
+  - Daniel Baluta <daniel.baluta at nxp.com>
+
+description: NXP imx95 CM7 core used for audio processing
+
+properties:
+  compatible:
+    const: fsl,imx95-cm7-sof
+
+  reg:
+    maxItems: 1
+
+  reg-names:
+    const: sram
+
+  memory-region:
+    maxItems: 1
+
+  memory-region-names:
+    const: dma
+
+  port:
+    description: SAI3 port
+    $ref: audio-graph-port.yaml#
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - memory-region
+  - memory-region-names
+  - port
+
+allOf:
+  - $ref: fsl,sof-cpu.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    cm7-cpu at 80000000 {
+        compatible = "fsl,imx95-cm7-sof";
+        reg = <0x80000000 0x6100000>;
+        reg-names = "sram";
+        mboxes = <&mu7 2 0>, <&mu7 2 1>, <&mu7 3 0>, <&mu7 3 1>;
+        mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
+        memory-region = <&adma_res>;
+        memory-region-names = "dma";
+        port {
+            /* SAI3-WM8962 link */
+            endpoint {
+                remote-endpoint = <&wm8962_ep>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml b/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
new file mode 100644
index 000000000000..31863932dbc3
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/fsl,sof-cpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP audio processor common properties
+
+maintainers:
+  - Daniel Baluta <daniel.baluta at nxp.com>
+
+properties:
+  mboxes:
+    maxItems: 4
+
+  mbox-names:
+    items:
+      - const: txdb0
+      - const: txdb1
+      - const: rxdb0
+      - const: rxdb1
+
+required:
+  - mboxes
+  - mbox-names
+
+additionalProperties: true
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Tue Mar 11 09:32:55 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Tue, 11 Mar 2025 12:32:55 -0400
Subject: [PATCH v5 3/3] arm64: dts: imx: add imx95 dts for sof
In-Reply-To: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
References: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250311163255.2664-4-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Add imx95 DTS for SOF usage.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
---
 arch/arm64/boot/dts/freescale/Makefile        |  1 +
 .../dts/freescale/imx95-19x19-evk-sof.dts     | 84 +++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index be6ef4c56fbf..fa19250b6676 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -299,6 +299,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb
 
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
 
diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts
new file mode 100644
index 000000000000..808a9fe3ebb2
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2025 NXP
+ */
+
+/dts-v1/;
+
+#include "imx95-19x19-evk.dts"
+
+/ {
+	sof_cpu: cm7-cpu at 80000000 {
+		compatible = "fsl,imx95-cm7-sof";
+		reg = <0x0 0x80000000 0x0 0x6100000>;
+		reg-names = "sram";
+		memory-region = <&adma_res>;
+		memory-region-names = "dma";
+		mboxes = <&mu7 2 0>, <&mu7 2 1>, <&mu7 3 0>, <&mu7 3 1>;
+		mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
+
+		sai3_cpu: port {
+			sai3_cpu_ep: endpoint {
+				remote-endpoint = <&wm8962_ep>;
+			};
+		};
+	};
+
+	reserved-memory {
+		adma_res: memory at 86100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x0 0x86100000 0x0 0x100000>;
+			no-map;
+		};
+	};
+
+	sof-sound {
+		compatible = "audio-graph-card2";
+		links = <&sai3_cpu>;
+		label = "audio";
+		hp-det-gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_hp>;
+		widgets = "Headphone", "Headphones",
+			  "Microphone", "Headset Mic";
+		routing = "Headphones", "HPOUTL",
+			  "Headphones", "HPOUTR",
+			  "Headset Mic", "MICBIAS",
+			  "IN3R", "Headset Mic",
+			  "IN1R", "Headset Mic";
+	};
+
+	sound-wm8962 {
+		status = "disabled";
+	};
+
+};
+
+&edma2 {
+	/* channels 30 and 31 reserved for FW usage */
+	dma-channel-mask = <0xc0000000>, <0x0>;
+};
+
+&sai3 {
+	status = "disabled";
+};
+
+&wm8962 {
+	assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL1>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2>,
+			  <&scmi_clk IMX95_CLK_SAI3>;
+	assigned-clock-parents = <0>, <0>, <0>, <0>, <&scmi_clk IMX95_CLK_AUDIOPLL1>;
+	assigned-clock-rates = <3932160000>, <3612672000>,
+			       <393216000>, <361267200>,
+			       <12288000>;
+
+	port {
+		wm8962_ep: endpoint {
+			bitclock-master;
+			frame-master;
+			remote-endpoint = <&sai3_cpu_ep>;
+		};
+	};
+};
-- 
2.34.1



From suzuki.poulose at arm.com  Tue Mar 11 09:48:37 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 11 Mar 2025 16:48:37 +0000
Subject: [PATCH v2] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <16fd2023-1ffa-4e87-ad89-a7ccdd8ba458@linaro.org>
References: <20250305-james-cs-kunit-test-v2-1-83ba682b976c@linaro.org>
 <c31de6cb-f8f5-432c-b99e-68b10a24bc5e@arm.com>
 <16fd2023-1ffa-4e87-ad89-a7ccdd8ba458@linaro.org>
Message-ID: <3f6dcb62-f9ba-4bed-9863-2d4569bafcf1@arm.com>

On 11/03/2025 16:06, James Clark wrote:
> 
> 
> On 11/03/2025 3:00 pm, Suzuki K Poulose wrote:
>> On 05/03/2025 15:07, James Clark wrote:
>>> Add a test to confirm that default sink selection skips over an ETF
>>> and returns an ETR even if it's further away.
>>>
>>> This also makes it easier to add new unit tests in the future.
>>>
>>> Signed-off-by: James Clark <james.clark at linaro.org>
>>> ---
>>> Changes in v2:
>>> - Let devm free everything rather than doing individual kfrees:
>>> ?? "Like with managed drivers, KUnit-managed fake devices are
>>> ?? automatically cleaned up when the test finishes, but can be manually
>>> ?? cleaned up early with kunit_device_unregister()."
>>> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1- 
>>> james.clark at linaro.org
>>> ---
>>> ? drivers/hwtracing/coresight/Kconfig??????????????? |? 9 +++
>>> ? drivers/hwtracing/coresight/Makefile?????????????? |? 3 +-
>>> ? drivers/hwtracing/coresight/coresight-core.c?????? |? 1 +
>>> ? .../hwtracing/coresight/coresight-kunit-tests.c??? | 77 +++++++++++ 
>>> + ++++++++++
>>> ? 4 files changed, 88 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/ 
>>> coresight/Kconfig
>>> index ecd7086a5b83..f064e3d172b3 100644
>>> --- a/drivers/hwtracing/coresight/Kconfig
>>> +++ b/drivers/hwtracing/coresight/Kconfig
>>> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>>> ??????? To compile this driver as a module, choose M here: the module 
>>> will be
>>> ??????? called coresight-dummy.
>>> +
>>> +config CORESIGHT_KUNIT_TESTS
>>> +????? tristate "Enable Coresight unit tests"
>>> +????? depends on KUNIT
>>> +????? default KUNIT_ALL_TESTS
>>> +????? help
>>> +??????? Enable Coresight unit tests. Only useful for development and 
>>> not
>>> +??????? intended for production.
>>> +
>>> ? endif
>>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/ 
>>> hwtracing/ coresight/Makefile
>>> index 8e62c3150aeb..96f0dfedb1bf 100644
>>> --- a/drivers/hwtracing/coresight/Makefile
>>> +++ b/drivers/hwtracing/coresight/Makefile
>>> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o coresight- 
>>> cti-platform.o \
>>> ???????????? coresight-cti-sysfs.o
>>> ? obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>>> ? obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>>> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>>> -coresight-ctcu-y := coresight-ctcu-core.o
>>> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
>>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>>> hwtracing/coresight/coresight-core.c
>>> index bd0a7edd38c9..b101aa133ceb 100644
>>> --- a/drivers/hwtracing/coresight/coresight-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>>> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct 
>>> coresight_device *csdev)
>>> ????? }
>>> ????? return csdev->def_sink;
>>> ? }
>>> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>>> ? static int coresight_remove_sink_ref(struct device *dev, void *data)
>>> ? {
>>> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/ 
>>> drivers/hwtracing/coresight/coresight-kunit-tests.c
>>> new file mode 100644
>>> index 000000000000..a136af05eaf4
>>> --- /dev/null
>>> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>>> @@ -0,0 +1,77 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +
>>> +#include <kunit/test.h>
>>> +#include <kunit/device.h>
>>> +#include <linux/coresight.h>
>>> +
>>> +#include "coresight-priv.h"
>>> +
>>> +static struct coresight_device *coresight_test_device(struct device 
>>> *dev)
>>> +{
>>> +??? struct coresight_device *csdev = devm_kcalloc(dev, 1,
>>> +???????????????????????????? sizeof(struct coresight_device),
>>> +???????????????????????????? GFP_KERNEL);
>>> +??? csdev->pdata = devm_kcalloc(dev, 1,
>>> +?????????????????? sizeof(struct coresight_platform_data),
>>> +?????????????????? GFP_KERNEL);
>>> +??? return csdev;
>>> +}
>>> +
>>> +static int coresight_test_cpuid(struct coresight_device *csdev)
>>> +{
>>> +??? return 0;
>>> +}
>>> +
>>> +static void test_default_sink(struct kunit *test)
>>> +{
>>> +??? /*
>>> +???? * ETM -> ETF -> ETR -> CATU
>>> +???? *??????????????? ^
>>> +???? *??????????????? | default
>>> +???? */
>>> +??? struct device *dev = kunit_device_register(test, 
>>> "coresight_kunit");
>>> +??? struct coresight_device *etm = coresight_test_device(dev),
>>> +??????????????? *etf = coresight_test_device(dev),
>>> +??????????????? *etr = coresight_test_device(dev),
>>> +??????????????? *catu = coresight_test_device(dev);
>>> +??? struct coresight_connection conn = {};
>>> +??? struct coresight_ops_source src_ops = {.cpu_id = 
>>> coresight_test_cpuid };
>>
>> Do we need the trace_id() ? Why is this required ?
>>
>> Suzuki
>>
> 
> Because it tests with per-cpu sources so it checks if any of the TRBE 
> sinks have been assigned first:
> 
>  ?/* look for a default sink if we have not found for this device */
>  ?? if (!csdev->def_sink) {
>  ????? if (coresight_is_percpu_source(csdev))
>  ???? csdev->def_sink = per_cpu(csdev_sink,
>  ?????????????????????????????????? source_ops(csdev)->cpu_id(csdev));
> 
> I think this test would probably fail if run somewhere TRBE was already 
> probed. I can make the source subtype to be 
> CORESIGHT_DEV_SUBTYPE_SOURCE_BUS for the test to work around it. Any 
> value other than CORESIGHT_DEV_SUBTYPE_SOURCE_PROC will work. And then I 
> can drop the fake cpu_id() callback.

If the purpose is to detect the ETR, then I guess we could make this a 
non-ETM source

TBH, I don't see any value in the test as such. But it is a good 
starting point for adding further cases. So, lets keep this in.

Suzuki

> 



From mike.leach at linaro.org  Tue Mar 11 09:49:54 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Tue, 11 Mar 2025 16:49:54 +0000
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <20250310090407.2069489-2-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com> <20250310090407.2069489-2-quic_jiegan@quicinc.com>
Message-ID: <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>

Hi,

On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan at quicinc.com> wrote:
>
> The new functions calculate and return the offset to the write pointer of
> the ETR buffer based on whether the memory mode is SG, flat or reserved.
> The functions have the RWP offset can directly read data from ETR buffer,
> enabling the transfer of data to any required location.
>
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>  .../hwtracing/coresight/coresight-tmc-etr.c   | 40 +++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-tmc.h   |  1 +
>  2 files changed, 41 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index eda7cdad0e2b..ec636ab1fd75 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
>  }
>  EXPORT_SYMBOL_GPL(tmc_free_sg_table);
>
> +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata)
> +{
> +       dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
> +       u64 rwp;
> +

It is not valid to read RWP if the TMC is running. It must be in the
stopped or disabled state - see the specifications for TMC /ETR

It is likely that CSUNLOCK / CSLOCK are needed here too,  along with
the spinlock that protects drvdata

See the code in coresight_tmc_etr.c :-

e.g. in

tmc_update_etr_buffer()

...
<take spinlock>
...
CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and
flushed to memory - essential to ensure full formatted frame is in
memory.
tmc_sync_etr_buf(drvdata); // this function reads rwp.
CS_LOCK(drvdata->base);
<release spinlokc>

This type of program flow is common to both sysfs and perf handling of
TMC buffers.

> +       rwp = tmc_read_rwp(drvdata);
> +       return rwp - paddr;
> +}
> +
> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
> +{
> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
> +       struct etr_sg_table *etr_table = etr_buf->private;
> +       struct tmc_sg_table *table = etr_table->sg_table;
> +       long w_offset;
> +       u64 rwp;
> +

Same comments as above

> +       rwp = tmc_read_rwp(drvdata);
> +       w_offset = tmc_sg_get_data_page_offset(table, rwp);
> +
> +       return w_offset;
> +}
> +
> +/*
> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
> + * the memory mode is SG, flat or reserved.
> + */
> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
> +{
> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
> +

As this is an exported function, please ensure that the inputs are
valid - check the pointers

Code to ensure TMC is flushed and stopped could be inserted here.

Regards

Mike

> +       if (etr_buf->mode == ETR_MODE_ETR_SG)
> +               return tmc_sg_get_rwp_offset(drvdata);
> +       else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
> +               return tmc_flat_resrv_get_rwp_offset(drvdata);
> +       else
> +               return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
> +
>  /*
>   * Alloc pages for the table. Since this will be used by the device,
>   * allocate the pages closer to the device (i.e, dev_to_node(dev)
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index b48bc9a01cc0..baedb4dcfc3f 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
>  struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>                                    enum cs_mode mode, void *data);
>  extern const struct attribute_group coresight_etr_group;
> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>
>  #endif
> --
> 2.34.1
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From kamal.dasu at broadcom.com  Tue Mar 11 09:59:35 2025
From: kamal.dasu at broadcom.com (Kamal Dasu)
Date: Tue, 11 Mar 2025 12:59:35 -0400
Subject: [PATCH v2] mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
Message-ID: <20250311165946.28190-1-kamal.dasu@broadcom.com>

cqhci timeouts observed on brcmstb platforms during suspend:
  ...
  [  164.832853] mmc0: cqhci: timeout for tag 18
  ...

Adding cqhci_suspend()/resume() calls to disable cqe
in sdhci_brcmstb_suspend()/resume() respectively to fix
CQE timeouts seen on PM suspend.

Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)")
Cc: stable at vger.kernel.org
Signed-off-by: Kamal Dasu <kamal.dasu at broadcom.com>
---
 drivers/mmc/host/sdhci-brcmstb.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 0ef4d578ade8..48cdcba0f39c 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -503,8 +503,15 @@ static int sdhci_brcmstb_suspend(struct device *dev)
 	struct sdhci_host *host = dev_get_drvdata(dev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	int ret;
 
 	clk_disable_unprepare(priv->base_clk);
+	if (host->mmc->caps2 & MMC_CAP2_CQE) {
+		ret = cqhci_suspend(host->mmc);
+		if (ret)
+			return ret;
+	}
+
 	return sdhci_pltfm_suspend(dev);
 }
 
@@ -529,6 +536,9 @@ static int sdhci_brcmstb_resume(struct device *dev)
 			ret = clk_set_rate(priv->base_clk, priv->base_freq_hz);
 	}
 
+	if (host->mmc->caps2 & MMC_CAP2_CQE)
+		ret = cqhci_resume(host->mmc);
+
 	return ret;
 }
 #endif
-- 
2.17.1



From catalin.marinas at arm.com  Tue Mar 11 10:17:34 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 17:17:34 +0000
Subject: [PATCH V3] arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
In-Reply-To: <20250227035119.2025171-1-anshuman.khandual@arm.com>
References: <20250227035119.2025171-1-anshuman.khandual@arm.com>
Message-ID: <174171335999.3659520.16613654046629962007.b4-ty@arm.com>

On Thu, 27 Feb 2025 09:21:19 +0530, Anshuman Khandual wrote:
> FEAT_PMUv3p9 registers such as PMICNTR_EL0, PMICFILTR_EL0, and PMUACR_EL1
> access from EL1 requires appropriate EL2 fine grained trap configuration
> via FEAT_FGT2 based trap control registers HDFGRTR2_EL2 and HDFGWTR2_EL2.
> Otherwise such register accesses will result in traps into EL2.
> 
> Add a new helper __init_el2_fgt2() which initializes FEAT_FGT2 based fine
> grained trap control registers HDFGRTR2_EL2 and HDFGWTR2_EL2 (setting the
> bits nPMICNTR_EL0, nPMICFILTR_EL0 and nPMUACR_EL1) to enable access into
> PMICNTR_EL0, PMICFILTR_EL0, and PMUACR_EL1 registers.
> 
> [...]

Applied to arm64 (for-next/el2-enable-feat-pmuv3p9), thanks!

[1/1] arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
      https://git.kernel.org/arm64/c/858c7bfcb35e

I removed Cc: stable since, if it gets backported automatically, it will
miss the sysreg updates and break the build. Please send it to stable
directly once it lands upstream, together with the dependencies.

-- 
Catalin



From catalin.marinas at arm.com  Tue Mar 11 10:17:50 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 17:17:50 +0000
Subject: [PATCH] selftest/powerpc/mm/pkey: fix build-break introduced by commit 00894c3fc917
In-Reply-To: <20250311084129.39308-1-maddy@linux.ibm.com>
References: <20250311084129.39308-1-maddy@linux.ibm.com>
Message-ID: <174171346335.3659993.17442583301270023148.b4-ty@arm.com>

On Tue, 11 Mar 2025 14:11:29 +0530, Madhavan Srinivasan wrote:
> Build break was reported in the powerpc mailing list for next-20250218 with below errors
> 
> make[1]: Nothing to be done for 'all'.
> BUILD_TARGET=/root/venkat/linux-next/tools/testing/selftests/powerpc/mm; mkdir -p $BUILD_TARGET; make OUTPUT=$BUILD_TARGET -k -C mm all
>   CC       pkey_exec_prot
> In file included from pkey_exec_prot.c:18:
> /root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h: In function ?pkeys_unsupported?:
> /root/venkat/linux-next/tools/testing/selftests/powerpc/include/pkeys.h:96:34: error: ?PKEY_UNRESTRICTED? undeclared (first use in this function)
>    96 |         pkey = sys_pkey_alloc(0, PKEY_UNRESTRICTED);
>       |                                  ^~~~~~~~~~~~~~~~~
> 
> [...]

Applied to arm64 (for-next/pkey_unrestricted), thanks!

[1/1] selftest/powerpc/mm/pkey: fix build-break introduced by commit 00894c3fc917
      https://git.kernel.org/arm64/c/73276cee1a25

-- 
Catalin



From robh at kernel.org  Tue Mar 11 10:21:03 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 12:21:03 -0500
Subject: [PATCH v4 04/14] dt-bindings: clk: sunxi-ng: document two
 Allwinner A523 CCUs
In-Reply-To: <20250307002628.10684-5-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
 <20250307002628.10684-5-andre.przywara@arm.com>
Message-ID: <174171366302.3801768.11391725958696311975.robh@kernel.org>


On Fri, 07 Mar 2025 00:26:18 +0000, Andre Przywara wrote:
> The Allwinner A523/T527 SoCs have four CCUs, this adds the binding for
> the main and the PRCM R-CCU.
> 
> The source clock list differs in some annoying details, and folding this
> into the existing Allwinner CCU clock binding document gets quite
> unwieldy, so create a new document for these CCUs.
> Add the new compatible string, along with the required input clock
> lists. This conditionally describes the input clock lists, to make
> adding support for the other two CCUs easier.
> 
> Also add the DT binding headers, listing all the clocks with their ID
> numbers.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  .../clock/allwinner,sun55i-a523-ccu.yaml      | 103 ++++++++++
>  include/dt-bindings/clock/sun55i-a523-ccu.h   | 189 ++++++++++++++++++
>  include/dt-bindings/clock/sun55i-a523-r-ccu.h |  37 ++++
>  include/dt-bindings/reset/sun55i-a523-ccu.h   |  88 ++++++++
>  include/dt-bindings/reset/sun55i-a523-r-ccu.h |  25 +++
>  5 files changed, 442 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
>  create mode 100644 include/dt-bindings/clock/sun55i-a523-ccu.h
>  create mode 100644 include/dt-bindings/clock/sun55i-a523-r-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun55i-a523-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun55i-a523-r-ccu.h
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From mark.barnett at arm.com  Tue Mar 11 10:22:16 2025
From: mark.barnett at arm.com (Mark Barnett)
Date: Tue, 11 Mar 2025 17:22:16 +0000
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250311113128.GD19424@noisy.programming.kicks-ass.net>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250311113128.GD19424@noisy.programming.kicks-ass.net>
Message-ID: <431a5acb-4906-4095-8dec-b2d824adaac6@arm.com>

On 3/11/25 11:31, Peter Zijlstra wrote:
> On Fri, Mar 07, 2025 at 08:22:45PM +0000, mark.barnett at arm.com wrote:
>> From: Ben Gainey <ben.gainey at arm.com>
>>
>> This change modifies the core perf overflow handler, adding some small
>> random jitter to each sample period whenever an event switches between the
>> two alternate sample periods. A new flag is added to perf_event_attr to
>> opt into this behaviour.
>>
>> This change follows the discussion in [1], where it is recognized that it
>> may be possible for certain patterns of execution to end up with biased
>> results.
>>
>> [1] https://lore.kernel.org/linux-perf-users/Zc24eLqZycmIg3d2 at tassilo/
>>
>> Signed-off-by: Ben Gainey <ben.gainey at arm.com>
>> Signed-off-by: Mark Barnett <mark.barnett at arm.com>
>> ---
>>   include/uapi/linux/perf_event.h | 7 ++++++-
>>   kernel/events/core.c            | 9 ++++++++-
>>   2 files changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
>> index 499a8673df8e..c0076ce8f80a 100644
>> --- a/include/uapi/linux/perf_event.h
>> +++ b/include/uapi/linux/perf_event.h
>> @@ -461,7 +461,12 @@ struct perf_event_attr {
>>   				inherit_thread :  1, /* children only inherit if cloned with CLONE_THREAD */
>>   				remove_on_exec :  1, /* event is removed from task on exec */
>>   				sigtrap        :  1, /* send synchronous SIGTRAP on event */
>> -				__reserved_1   : 26;
>> +				/*
>> +				 * Add a limited amount of jitter on each alternate period, where
>> +				 * the jitter is between [0, (2<<jitter_alt_period) - 1]
>> +				 */
>> +				jitter_alt_period : 3,
>> +				__reserved_1   : 23;
> 
> So; I've been thinking about this interface.
> 
> I think I prefer you keep the existing sample_period/sample_freq working
> as is and simply modulate with random and high-freq components.
> 
> A very little like so..
> 
> I've made the hf_sample_period 32bit since I figured that ought to be
> enough -- you're aiming at very short periods after all. But there's
> enough unused bits left.
> 
> So this has sample_period or sample_freq compute hwc->sample_period_base
> which is first modified with random such that the average is exactly
> sample_period_base (assuming a flat distribution).
> 
> This means that sample_period_base is still the right number to use for
> computing freq based things. Additionally, have the 'extra' interrupt
> ignored for adaptive period crud.
> 
> Also, someone needs to consider the eBPF hook and what to do with it.
> I've kept the ordering as per this series, but I suspect it's wrong and
> we want this before the BPF hook. Please think about this and explicitly
> mention this in the next series.
> 
> Anyway, very much a sketch of things, incomplete and not been near a
> compiler.
> 
> 

Thanks, Peter!

OK, I see what you mean. Packing the fields into hf_sample makes sense. 
I'll have a look at the eBPF hook and see if we need to do anything. The 
sample period is always stored in perf_sample_data so it's technically 
possible for eBPF programs to identify the high-frequency ones, but it's 
not a great API. Maybe we should have an explicit flag.

I have one question about interrupt accounting, below...

> 
> ---
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 76f4265efee9..c5dd6442e96f 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -229,6 +229,10 @@ struct hw_perf_event {
>   #define PERF_HES_UPTODATE	0x02 /* event->count up-to-date */
>   #define PERF_HES_ARCH		0x04
>   
> +#define PERF_HES_HF_ON		0x10 /* using high-fred sampling */
> +#define PERF_HES_HF_SAMPLE	0x20
> +#define PERF_HES_HF_RAND	0x40
> +
>   	int				state;
>   
>   	/*
> @@ -241,6 +245,7 @@ struct hw_perf_event {
>   	 * The period to start the next sample with.
>   	 */
>   	u64				sample_period;
> +	u64				sample_period_base;
>   
>   	union {
>   		struct { /* Sampling */
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 0524d541d4e3..8dbe027f93f1 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -379,6 +379,7 @@ enum perf_event_read_format {
>   #define PERF_ATTR_SIZE_VER6	120	/* add: aux_sample_size */
>   #define PERF_ATTR_SIZE_VER7	128	/* add: sig_data */
>   #define PERF_ATTR_SIZE_VER8	136	/* add: config3 */
> +#define PERF_ATTR_SIZE_VER9	144	/* add: hf_sample */
>   
>   /*
>    * Hardware event_id to monitor via a performance monitoring event:
> @@ -531,6 +532,14 @@ struct perf_event_attr {
>   	__u64	sig_data;
>   
>   	__u64	config3; /* extension of config2 */
> +	union {
> +		__u64 hf_sample;
> +		struct {
> +			__u64 hf_sample_period : 32,
> +			      hf_sample_rand   :  4,
> +			      __reserved_4     : 28;
> +		};
> +	};
>   };
>   
>   /*
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index b87a5ac42ce2..e5a93edf3b5f 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -8,6 +8,7 @@
>    *  Copyright  ?  2009 Paul Mackerras, IBM Corp. <paulus at au1.ibm.com>
>    */
>   
> +#include "linux/random.h"
>   #include <linux/fs.h>
>   #include <linux/mm.h>
>   #include <linux/cpu.h>
> @@ -55,6 +56,7 @@
>   #include <linux/pgtable.h>
>   #include <linux/buildid.h>
>   #include <linux/task_work.h>
> +#include <linux/prandom.h>
>   
>   #include "internal.h"
>   
> @@ -443,6 +445,8 @@ static cpumask_var_t perf_online_pkg_mask;
>   static cpumask_var_t perf_online_sys_mask;
>   static struct kmem_cache *perf_event_cache;
>   
> +static struct rnd_state perf_rand;
> +
>   /*
>    * perf event paranoia level:
>    *  -1 - not paranoid at all
> @@ -4233,19 +4237,19 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bo
>   
>   	period = perf_calculate_period(event, nsec, count);
>   
> -	delta = (s64)(period - hwc->sample_period);
> +	delta = (s64)(period - hwc->sample_period_base);
>   	if (delta >= 0)
>   		delta += 7;
>   	else
>   		delta -= 7;
>   	delta /= 8; /* low pass filter */
>   
> -	sample_period = hwc->sample_period + delta;
> +	sample_period = hwc->sample_period_base + delta;
>   
>   	if (!sample_period)
>   		sample_period = 1;
>   
> -	hwc->sample_period = sample_period;
> +	hwc->sample_period_base = sample_period;
>   
>   	if (local64_read(&hwc->period_left) > 8*sample_period) {
>   		if (disable)
> @@ -4490,6 +4494,8 @@ void perf_event_task_tick(void)
>   	if (ctx)
>   		perf_adjust_freq_unthr_context(ctx, !!throttled);
>   	rcu_read_unlock();
> +
> +	prandom_seed_state(&perf_rand, get_random_u64());
>   }
>   
>   static int event_enable_on_exec(struct perf_event *event,
> @@ -9979,6 +9985,8 @@ static int __perf_event_overflow(struct perf_event *event,
>   				 int throttle, struct perf_sample_data *data,
>   				 struct pt_regs *regs)
>   {
> +	struct hw_perf_event *hwc = &event->hw;
> +	u64 sample_period;
>   	int events = atomic_read(&event->event_limit);
>   	int ret = 0;
>   
> @@ -9989,15 +9997,50 @@ static int __perf_event_overflow(struct perf_event *event,
>   	if (unlikely(!is_sampling_event(event)))
>   		return 0;
>   
> -	ret = __perf_event_account_interrupt(event, throttle);
> +	/*
> +	 * High Freq samples are injected inside the larger period:
> +	 *
> +	 *   |------------|-|------------|-|
> +	 *   P0          HF P1          HF
> +	 *
> +	 * By ignoring the HF samples, we measure the actual period.
> +	 */
> +	if (!(hwc->state & PERF_HES_HF_SAMPLE))
> +		ret = __perf_event_account_interrupt(event, throttle);
>   

The high-frequency samples should still contribute to interrupt 
accounting/throttling, right? We'd just need to put guards around the 
adaptive period stuff so that HF samples don't contribute to the 
frequency training.

>   	if (event->attr.aux_pause)
>   		perf_event_aux_pause(event->aux_event, true);
>   
> +	/* XXX interaction between HF samples and BPF */
>   	if (event->prog && event->prog->type == BPF_PROG_TYPE_PERF_EVENT &&
>   	    !bpf_overflow_handler(event, data, regs))
>   		goto out;
>   
> +	sample_period = hwc->sample_period_base;
> +	if (hwc->state & PERF_HES_HF_RAND) {
> +		u64 rand = 1 << event->attr.hf_sample_rand;
> +		sample_period -= rand / 2;
> +		sample_period += prandom_u32_state(&perf_rand) & (rand - 1);
> +	}
> +	if (hwc->state & PERF_HES_HF_ON) {
> +		u64 hf_sample_period = event->attr.hf_sample_period;
> +
> +		if (sample_period < hf_sample_period) {
> +			hwc->state &= ~PERF_HES_HF_ON;
> +			goto set_period;
> +		}
> +
> +		if (!(hwc->state & PERF_HES_HF_SAMPLE)) {
> +			hwc->sample_period -= hf_sample_period;
> +			hwc->state |= PERF_HES_HF_SAMPLE;
> +		} else {
> +			hwc->sample_period = hf_sample_period;
> +			hwc->state &= ~PERF_HES_HF_SAMPLE;
> +		}
> +	}
> +set_period:
> +	hwc->sample_period = sample_period;
> +
>   	/*
>   	 * XXX event_limit might not quite work as expected on inherited
>   	 * events
> @@ -12458,8 +12501,11 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
>   
>   	hwc = &event->hw;
>   	hwc->sample_period = attr->sample_period;
> -	if (attr->freq && attr->sample_freq)
> +	hwc->sample_period_base = attr->sample_period;
> +	if (attr->freq && attr->sample_freq) {
>   		hwc->sample_period = 1;
> +		hwc->sample_period_base = 1;
> +	}
>   	hwc->last_period = hwc->sample_period;
>   
>   	local64_set(&hwc->period_left, hwc->sample_period);
> @@ -13824,6 +13870,7 @@ inherit_event(struct perf_event *parent_event,
>   		struct hw_perf_event *hwc = &child_event->hw;
>   
>   		hwc->sample_period = sample_period;
> +		hwc->sample_period_base = sample_period;
>   		hwc->last_period   = sample_period;
>   
>   		local64_set(&hwc->period_left, sample_period);
> @@ -14279,6 +14326,8 @@ void __init perf_event_init(void)
>   {
>   	int ret;
>   
> +	prandom_seed_state(&perf_rand, get_random_u64());
> +
>   	idr_init(&pmu_idr);
>   
>   	perf_event_init_all_cpus();
> 



From krzk at kernel.org  Tue Mar 11 10:30:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 18:30:07 +0100
Subject: [PATCH v4 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <20250310143450.8276-5-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
 <20250310143450.8276-5-linux.amoon@gmail.com>
Message-ID: <25fa661b-98e4-468b-bb4d-4a2c95f32b71@kernel.org>

On 10/03/2025 15:34, Anand Moon wrote:
> Using guard notation makes the code more compact and error handling
> more robust by ensuring that mutexes are released in all code paths
> when control leaves critical section.
> 

Subject: typo, exynos

> Signed-off-by: Anand Moon <linux.amoon at gmail.com>
> ---
> v4: used DEFINE_GUARD macro to guard exynos_tmu_data structure.
>     However, incorporating guard(exynos_tmu_data)(data); results
>     in a recursive deadlock with the mutex during initialization, as this
>     data structure is common to all the code configurations of Exynos TMU
> v3: New patch

If you ever use cleanup or guards, you must build your code with recent
clang and W=1. Failure to do so means you ask reviewers manually to spot
issues not visible in the context, instead of using tools. It's a NAK
for me.

> ---
>  drivers/thermal/samsung/exynos_tmu.c | 25 +++++++++++--------------
>  1 file changed, 11 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> index a71cde0a4b17e..85f88c5e0f11c 100644
> --- a/drivers/thermal/samsung/exynos_tmu.c
> +++ b/drivers/thermal/samsung/exynos_tmu.c
> @@ -12,6 +12,7 @@
>   */
>  
>  #include <linux/clk.h>
> +#include <linux/cleanup.h>
>  #include <linux/io.h>
>  #include <linux/interrupt.h>
>  #include <linux/module.h>
> @@ -199,6 +200,9 @@ struct exynos_tmu_data {
>  	void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
>  };
>  
> +DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *,

I do not understand why do you need custom guard.

> +	     mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
> +
>  /*
>   * TMU treats temperature as a mapped temperature code.
>   * The temperature is converted differently depending on the calibration type.
> @@ -256,7 +260,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>  	unsigned int status;
>  	int ret = 0;
>  
> -	mutex_lock(&data->lock);
> +	guard(mutex)(&data->lock);

Which you do not use... Please don't use cleanup.h if you do not know
it. It leads to bugs.


Best regards,
Krzysztof


From namcao at linutronix.de  Tue Mar 11 10:05:01 2025
From: namcao at linutronix.de (Nam Cao)
Date: Tue, 11 Mar 2025 18:05:01 +0100
Subject: [PATCH 00/10] RV: Linear temporal logic monitors for RT application
Message-ID: <cover.1741708239.git.namcao@linutronix.de>

Realtime applications often have design flaws causing them to have
unexpected latency.  For example, the applications may raise page faults,
or may be blocked trying to take a mutex without priority inheritance.

This series adds runtime verification monitors to detect these flaws.

This monitors was tried on pipewire and detected some issues. One of them
has been reported to pipewire's maintainers and is being fixed:
https://gitlab.freedesktop.org/pipewire/pipewire/-/merge_requests/2285

Patch 1 and patch 2 fix some minor issues with RV.

Patch 3 adds the infrastructure for linear temporal logic monitor.

Patch 4 adds the first monitor: rtapp_block. This monitor detects if a
realtime task is undesirable blocked.

Patch 5-8 prepare the pagefault tracepoints, so that patch 9 can add the
rtapp_pagefault monitor.  This monitor task detects if an RT task raise
page fault.

Patch 10 raises the max number of per-task monitor to 2, so that the above
monitors can be enabled simultaneously.
---
Cc: Petr Mladek <pmladek at suse.com>
Cc: John Ogness <john.ogness at linutronix.de>
Cc: Sergey Senozhatsky <senozhatsky at chromium.org>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Boqun Feng <boqun.feng at gmail.com>
Cc: Waiman Long <longman at redhat.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Borislav Petkov <bp at alien8.de>
Cc: Dave Hansen <dave.hansen at linux.intel.com>
Cc: x86 at kernel.org
Cc: H. Peter Anvin <hpa at zytor.com>
Cc: Andy Lutomirski <luto at kernel.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Albert Ou <aou at eecs.berkeley.edu>
Cc: Alexandre Ghiti <alex at ghiti.fr>
Cc: linux-riscv at lists.infradead.org
---
Nam Cao (10):
  rv: Add #undef TRACE_INCLUDE_FILE
  rv: Let the reactors take care of buffers
  rv: Add infrastructure for linear temporal logic monitor
  rv: Add rtapp_block monitor
  x86/tracing: Remove redundant trace_pagefault_key
  x86/tracing: Move page fault trace points to generic
  arm64: mm: Add page fault trace points
  riscv: mm: Add page fault trace points
  rv: Add rtapp_pagefault monitor
  rv: raise the number of per-task monitor to 2

 .../trace/rv/linear_temporal_logic.rst        |  73 +++
 .../trace/rv/monitor_rtapp_block.rst          |  34 ++
 .../trace/rv/monitor_rtapp_pagefault.rst      |  36 ++
 arch/arm64/mm/fault.c                         |   8 +
 arch/riscv/mm/fault.c                         |   8 +
 arch/x86/include/asm/trace/common.h           |  12 -
 arch/x86/include/asm/trace/irq_vectors.h      |   1 -
 arch/x86/kernel/tracepoint.c                  |  21 -
 arch/x86/mm/fault.c                           |   5 +-
 include/linux/printk.h                        |   1 +
 include/linux/rv.h                            |  39 +-
 include/rv/da_monitor.h                       |  61 +-
 .../trace/events}/exceptions.h                |  27 +-
 include/trace/events/lock.h                   |  12 +
 kernel/fork.c                                 |   5 +-
 kernel/locking/rtmutex.c                      |   4 +
 kernel/printk/internal.h                      |   1 -
 kernel/trace/rv/Kconfig                       |  20 +-
 kernel/trace/rv/Makefile                      |   4 +
 kernel/trace/rv/monitors/rtapp_block/ba.c     | 146 +++++
 kernel/trace/rv/monitors/rtapp_block/ba.h     | 166 ++++++
 kernel/trace/rv/monitors/rtapp_block/ltl      |   9 +
 .../rv/monitors/rtapp_block/rtapp_block.c     | 232 ++++++++
 kernel/trace/rv/monitors/rtapp_pagefault/ba.c | 139 +++++
 kernel/trace/rv/monitors/rtapp_pagefault/ba.h | 158 +++++
 kernel/trace/rv/monitors/rtapp_pagefault/ltl  |   1 +
 .../rtapp_pagefault/rtapp_pagefault.c         |  84 +++
 kernel/trace/rv/reactor_panic.c               |   7 +-
 kernel/trace/rv/reactor_printk.c              |   8 +-
 kernel/trace/rv/rv_reactors.c                 |   2 +-
 kernel/trace/rv/rv_trace.h                    |  67 ++-
 lib/Kconfig.debug                             |   3 +
 tools/verification/ltl2ba/.gitignore          |   3 +
 tools/verification/ltl2ba/generate.py         | 154 +++++
 tools/verification/ltl2ba/ltl.py              | 556 ++++++++++++++++++
 tools/verification/ltl2ba/template.c          | 131 +++++
 tools/verification/ltl2ba/template.h          | 157 +++++
 37 files changed, 2262 insertions(+), 133 deletions(-)
 create mode 100644 Documentation/trace/rv/linear_temporal_logic.rst
 create mode 100644 Documentation/trace/rv/monitor_rtapp_block.rst
 create mode 100644 Documentation/trace/rv/monitor_rtapp_pagefault.rst
 delete mode 100644 arch/x86/include/asm/trace/common.h
 delete mode 100644 arch/x86/kernel/tracepoint.c
 rename {arch/x86/include/asm/trace => include/trace/events}/exceptions.h (55%)
 create mode 100644 kernel/trace/rv/monitors/rtapp_block/ba.c
 create mode 100644 kernel/trace/rv/monitors/rtapp_block/ba.h
 create mode 100644 kernel/trace/rv/monitors/rtapp_block/ltl
 create mode 100644 kernel/trace/rv/monitors/rtapp_block/rtapp_block.c
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ba.c
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ba.h
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ltl
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/rtapp_pagefault.c
 create mode 100644 tools/verification/ltl2ba/.gitignore
 create mode 100755 tools/verification/ltl2ba/generate.py
 create mode 100644 tools/verification/ltl2ba/ltl.py
 create mode 100644 tools/verification/ltl2ba/template.c
 create mode 100644 tools/verification/ltl2ba/template.h

-- 
2.39.5



From namcao at linutronix.de  Tue Mar 11 10:05:08 2025
From: namcao at linutronix.de (Nam Cao)
Date: Tue, 11 Mar 2025 18:05:08 +0100
Subject: [PATCH 07/10] arm64: mm: Add page fault trace points
In-Reply-To: <cover.1741708239.git.namcao@linutronix.de>
References: <cover.1741708239.git.namcao@linutronix.de>
Message-ID: <b0e391920b441487d52652edef822883923e3b39.1741708239.git.namcao@linutronix.de>

Add page fault trace points, which are useful to implement RV monitor which
watches page faults.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm64/mm/fault.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index ef63651099a9..e3f096b0dffd 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -44,6 +44,9 @@
 #include <asm/tlbflush.h>
 #include <asm/traps.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/exceptions.h>
+
 struct fault_info {
 	int	(*fn)(unsigned long far, unsigned long esr,
 		      struct pt_regs *regs);
@@ -559,6 +562,11 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
 	if (kprobe_page_fault(regs, esr))
 		return 0;
 
+	if (user_mode(regs))
+		trace_page_fault_user(addr, regs, esr);
+	else
+		trace_page_fault_kernel(addr, regs, esr);
+
 	/*
 	 * If we're in an interrupt or have no user context, we must not take
 	 * the fault.
-- 
2.39.5



From jeff.johnson at oss.qualcomm.com  Tue Mar 11 10:05:26 2025
From: jeff.johnson at oss.qualcomm.com (Jeff Johnson)
Date: Tue, 11 Mar 2025 10:05:26 -0700
Subject: [PATCH 07/26] clk: mediatek: Add MT8196 apmixedsys clock support
In-Reply-To: <20250307032942.10447-8-guangjie.song@mediatek.com>
References: <20250307032942.10447-1-guangjie.song@mediatek.com>
 <20250307032942.10447-8-guangjie.song@mediatek.com>
Message-ID: <7dc00288-1e12-4524-97e7-a427ee24d984@oss.qualcomm.com>

On 3/6/25 19:27, Guangjie Song wrote:
> +module_platform_driver(clk_mt8196_apmixed_drv);
> +MODULE_LICENSE("GPL");

Since commit 1fffe7a34c89 ("script: modpost: emit a warning when the
description is missing"), a module without a MODULE_DESCRIPTION() will
result in a warning with make W=1. Please add a MODULE_DESCRIPTION()
to avoid this warning.

This is a canned review based upon finding a MODULE_LICENSE without a
MODULE_DESCRIPTION.

Note this issue appears in multiple patches in this series, so please
fix all instances.


From leo.yan at arm.com  Tue Mar 11 10:04:45 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:45 +0000
Subject: [PATCH v3 0/6] Arm CoreSight: Support AUX pause and resume
Message-ID: <20250311170451.611389-1-leo.yan@arm.com>

This series is to enable AUX pause and resume on Arm CoreSight.

The first patch extracts the trace unit controlling operations to two
functions.  These two functions will be used by AUX pause and resume.

Patches 02 and 03 change the ETMv4 driver to prepare callback functions
for AUX pause and resume.

Patch 04 changes the ETM perf layer to support AUX pause and resume in a
perf session.  The patches 05 updates buffer on AUX pause occasion,
which can mitigate the trace data lose issue.

Patch 07 documents the AUX pause usages with Arm CoreSight.

This patch set has been verified on the Hikey960 board and TC platform.
The previous one uses ETR and the later uses TRBE as sink.

It is suggested to disable CPUIdle (add `nohlt` option in Linux command
line) when verifying this series.  ETM and funnel drivers are found
issues during CPU suspend and resume which will be addressed separately.

Changes from v2:
- Rebased on CoreSight next branch.
- Dropped the uAPI 'update_buf_on_pause' and updated document
  respectively (Suzuki).
- Renamed ETM callbacks to .pause_perf() and .resume_perf() (Suzuki).
- Minor improvement for error handling in the AUX resume flow.

Changes from v1:
- Added validation function pointers in pause and resume APIs (Mike).


Leo Yan (6):
  coresight: etm4x: Extract the trace unit controlling
  coresight: Introduce pause and resume APIs for source
  coresight: etm4x: Hook pause and resume callbacks
  coresight: perf: Support AUX trace pause and resume
  coresight: perf: Update buffer on AUX pause
  Documentation: coresight: Document AUX pause and resume

 .../trace/coresight/coresight-perf.rst        |  31 ++++
 drivers/hwtracing/coresight/coresight-core.c  |  22 +++
 .../hwtracing/coresight/coresight-etm-perf.c  |  84 +++++++++-
 .../coresight/coresight-etm4x-core.c          | 143 +++++++++++++-----
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +
 drivers/hwtracing/coresight/coresight-priv.h  |   2 +
 include/linux/coresight.h                     |   4 +
 7 files changed, 246 insertions(+), 42 deletions(-)

-- 
2.34.1



From namcao at linutronix.de  Tue Mar 11 10:05:10 2025
From: namcao at linutronix.de (Nam Cao)
Date: Tue, 11 Mar 2025 18:05:10 +0100
Subject: [PATCH 09/10] rv: Add rtapp_pagefault monitor
In-Reply-To: <cover.1741708239.git.namcao@linutronix.de>
References: <cover.1741708239.git.namcao@linutronix.de>
Message-ID: <4b289114af4191be9e905ed6e5b6d43206136673.1741708239.git.namcao@linutronix.de>

Real time applications can have unexpected latency due to page faults.

Add an RV LTL monitor to detect such cases. For complete description, see
Documentation/trace/rv/monitor_rtapp_pagefault.rst.

The document is mostly from:
https://www.linutronix.de/blog/A-Checklist-for-Real-Time-Applications-in-Linux

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Albert Ou <aou at eecs.berkeley.edu>
Cc: Alexandre Ghiti <alex at ghiti.fr>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Borislav Petkov <bp at alien8.de>
Cc: Dave Hansen <dave.hansen at linux.intel.com>
Cc: x86 at kernel.org
Cc: H. Peter Anvin <hpa at zytor.com>
Cc: Andy Lutomirski <luto at kernel.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-riscv at lists.infradead.org
---
 .../trace/rv/monitor_rtapp_pagefault.rst      |  36 ++++
 kernel/trace/rv/Kconfig                       |   8 +
 kernel/trace/rv/Makefile                      |   2 +
 kernel/trace/rv/monitors/rtapp_pagefault/ba.c | 139 +++++++++++++++
 kernel/trace/rv/monitors/rtapp_pagefault/ba.h | 158 ++++++++++++++++++
 kernel/trace/rv/monitors/rtapp_pagefault/ltl  |   1 +
 .../rtapp_pagefault/rtapp_pagefault.c         |  84 ++++++++++
 kernel/trace/rv/rv_trace.h                    |  20 +++
 8 files changed, 448 insertions(+)
 create mode 100644 Documentation/trace/rv/monitor_rtapp_pagefault.rst
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ba.c
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ba.h
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/ltl
 create mode 100644 kernel/trace/rv/monitors/rtapp_pagefault/rtapp_pagefault.c

diff --git a/Documentation/trace/rv/monitor_rtapp_pagefault.rst b/Documentation/trace/rv/monitor_rtapp_pagefault.rst
new file mode 100644
index 000000000000..0ee223d83d09
--- /dev/null
+++ b/Documentation/trace/rv/monitor_rtapp_pagefault.rst
@@ -0,0 +1,36 @@
+Monitor rtapp_pagefault
+=======================
+
+- Name: rtapp_pagefault - realtime applications raising page faults
+- Type: per-task linear temporal logic monitor
+- Author: Nam Cao <namcao at linutronix.de>
+
+Introduction
+------------
+
+One of the most devastating situations for a real-time application is the need to assign or "page
+in" memory. This can be due to the over-commitment behavior of Linux when accessing allocated or
+reserved memory for the first time. Or it can be paging in disk data (such as text segments) when
+calling functions for the first time. Whatever the case, it must be avoided in order to meet
+response requirements.
+
+The monitor reports these situation where real-time applications raise page faults.
+
+How to fix the monitor's warnings?
+----------------------------------
+
+The first thing a real-time application needs to do is configure glibc to use a single
+non-shrinkable heap for the application. This guarantees that a pool of readily accessible physical
+RAM can be made available to the real-time application. This is accomplished using the mallopt(3)
+function (M_MMAP_MAX=0, M_ARENA_MAX=1, M_TRIM_THRESHOLD=-1).
+
+Next, all allocated and mapped virtual memory must be assigned to physical RAM and locked so that it
+cannot be reclaimed for other purposes. This is accomplished using the mlockall(2) function
+(MCL_CURRENT | MCL_FUTURE).
+
+Finally, the amounts of stack and heap needed during the lifetime of the real-time application must
+be allocated and written to in order to trigger heap and stack assignments to physical RAM. This is
+known as pre-faulting and is usually accomplished by memsetting a large buffer within a stack frame
+and allocating, memsetting, and freeing a large heap buffer.
+
+Pitfall: Keep in mind that each thread will have its own stack.
diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig
index d65bf9bda2f2..2822af1b2b4d 100644
--- a/kernel/trace/rv/Kconfig
+++ b/kernel/trace/rv/Kconfig
@@ -39,6 +39,14 @@ config RV_MON_RTAPP_BLOCK
 	  Enable rtapp_wakeup which monitors that realtime tasks are not blocked.
 	  For details, see Documentation/trace/rv/monitor_rtapp_block.rst.
 
+config RV_MON_RTAPP_PAGEFAULT
+	depends on RV
+	select DA_MON_EVENTS
+	bool "rtapp_pagefault monitor"
+	help
+	  Enable rtapp_pagefault which monitors that real-time tasks do not raise page faults.
+	  See Documentation/trace/rv/monitor_rtapp_pagefault.rst for full details.
+
 config RV_REACTORS
 	bool "Runtime verification reactors"
 	default y
diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile
index 6570a3116127..7f21a679ad70 100644
--- a/kernel/trace/rv/Makefile
+++ b/kernel/trace/rv/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
 obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
 obj-$(CONFIG_RV_MON_RTAPP_BLOCK) += monitors/rtapp_block/ba.o \
 				    monitors/rtapp_block/rtapp_block.o
+obj-$(CONFIG_RV_MON_RTAPP_PAGEFAULT) += monitors/rtapp_pagefault/ba.o \
+					monitors/rtapp_pagefault/rtapp_pagefault.o
 # Add new monitors here
 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
 obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
diff --git a/kernel/trace/rv/monitors/rtapp_pagefault/ba.c b/kernel/trace/rv/monitors/rtapp_pagefault/ba.c
new file mode 100644
index 000000000000..6f6322717854
--- /dev/null
+++ b/kernel/trace/rv/monitors/rtapp_pagefault/ba.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file is generated, do not edit.
+ */
+#include <linux/rv.h>
+#include <rv/instrumentation.h>
+#include <trace/events/task.h>
+#include <trace/events/sched.h>
+
+#include "ba.h"
+
+static_assert(NUM_ATOM <= RV_MAX_LTL_ATOM);
+
+enum buchi_state {
+	INIT,
+	S1,
+	DEAD,
+};
+
+int rv_rtapp_pagefault_task_slot = RV_PER_TASK_MONITOR_INIT;
+
+static void init_monitor(struct task_struct *task)
+{
+	struct ltl_monitor *mon = rv_rtapp_pagefault_get_monitor(task);
+
+	for (int i = 0; i < NUM_ATOM; ++i)
+		mon->atoms[i] = LTL_UNDETERMINED;
+	mon->state = INIT;
+}
+
+static void handle_task_newtask(void *data, struct task_struct *task, unsigned long flags)
+{
+	struct ltl_monitor *mon = rv_rtapp_pagefault_get_monitor(task);
+
+	init_monitor(task);
+
+	rv_rtapp_pagefault_atoms_init(task, mon);
+	rv_rtapp_pagefault_atoms_fetch(task, mon);
+}
+
+int rv_rtapp_pagefault_init(size_t data_size)
+{
+	struct task_struct *g, *p;
+	int ret, cpu;
+
+	if (WARN_ON(data_size > RV_MAX_DATA_SIZE))
+		return -EINVAL;
+
+	ret = rv_get_task_monitor_slot();
+	if (ret < 0)
+		return ret;
+
+	rv_rtapp_pagefault_task_slot = ret;
+
+	rv_attach_trace_probe("rtapp_pagefault", task_newtask, handle_task_newtask);
+
+	read_lock(&tasklist_lock);
+
+	for_each_process_thread(g, p)
+		init_monitor(p);
+
+	for_each_present_cpu(cpu)
+		init_monitor(idle_task(cpu));
+
+	read_unlock(&tasklist_lock);
+
+	return 0;
+}
+
+void rv_rtapp_pagefault_destroy(void)
+{
+	rv_put_task_monitor_slot(rv_rtapp_pagefault_task_slot);
+	rv_rtapp_pagefault_task_slot = RV_PER_TASK_MONITOR_INIT;
+
+	rv_detach_trace_probe("rtapp_pagefault", task_newtask, handle_task_newtask);
+}
+
+static void illegal_state(struct task_struct *task, struct ltl_monitor *mon)
+{
+	mon->state = INIT;
+	rv_rtapp_pagefault_error(task, mon);
+}
+
+static void rv_rtapp_pagefault_attempt_start(struct task_struct *task, struct ltl_monitor *mon)
+{
+	int i;
+
+	mon = rv_rtapp_pagefault_get_monitor(task);
+
+	rv_rtapp_pagefault_atoms_fetch(task, mon);
+
+	for (i = 0; i < NUM_ATOM; ++i) {
+		if (mon->atoms[i] == LTL_UNDETERMINED)
+			return;
+	}
+
+	if (((!mon->atoms[RT] || !mon->atoms[PAGEFAULT])))
+		mon->state = S1;
+	else
+		illegal_state(task, mon);
+}
+
+static void rv_rtapp_pagefault_step(struct task_struct *task, struct ltl_monitor *mon)
+{
+	switch (mon->state) {
+	case S1:
+		if (((!mon->atoms[RT] || !mon->atoms[PAGEFAULT])))
+			mon->state = S1;
+		else
+			illegal_state(task, mon);
+		break;
+	case DEAD:
+	case INIT:
+		break;
+	default:
+		WARN_ON_ONCE(1);
+	}
+}
+
+void rv_rtapp_pagefault_atom_update(struct task_struct *task, unsigned int atom, bool value)
+{
+	struct ltl_monitor *mon = rv_rtapp_pagefault_get_monitor(task);
+
+	rv_rtapp_pagefault_atom_set(mon, atom, value);
+
+	if (mon->state == DEAD)
+		return;
+
+	if (mon->state == INIT)
+		rv_rtapp_pagefault_attempt_start(task, mon);
+	if (mon->state == INIT)
+		return;
+
+	mon->atoms[atom] = value;
+
+	rv_rtapp_pagefault_atoms_fetch(task, mon);
+
+	rv_rtapp_pagefault_step(task, mon);
+}
diff --git a/kernel/trace/rv/monitors/rtapp_pagefault/ba.h b/kernel/trace/rv/monitors/rtapp_pagefault/ba.h
new file mode 100644
index 000000000000..eec2068c1419
--- /dev/null
+++ b/kernel/trace/rv/monitors/rtapp_pagefault/ba.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file is generated, do not edit.
+ *
+ * This file includes necessary functions to glue the Buchi automaton and the kernel together.
+ * Some of these functions must be manually implemented (look for "Must be implemented", or just
+ * let the compiler tells you).
+ *
+ * Essentially, you need to manually define the meaning of the atomic propositions in the LTL
+ * property. The primary function for that is rv_rtapp_pagefault_atom_update(), which can be called
+ * in tracepoints' handlers for example. In some specific cases where
+ * rv_rtapp_pagefault_atom_update() is not convenient, rv_rtapp_pagefault_atoms_fetch() can be used.
+ *
+ * rv_rtapp_pagefault_init()/rv_rtapp_pagefault_destroy() must be called while enabling/disabling
+ * the monitor.
+ *
+ * If the fields in struct ltl_monitor is not enough, extra custom data can be used. See
+ * rv_rtapp_pagefault_get_data().
+ */
+
+#include <linux/sched.h>
+
+enum rtapp_pagefault_atom {
+	PAGEFAULT,
+	RT,
+	NUM_ATOM
+};
+
+/**
+ * rv_rtapp_pagefault_init
+ * @data_size:	required custom data size, can be zero
+ *
+ * Must be called while enabling the monitor
+ */
+int rv_rtapp_pagefault_init(size_t data_size);
+
+/**
+ * rv_rtapp_pagefault_destroy
+ *
+ * must be called while disabling the monitor
+ */
+void rv_rtapp_pagefault_destroy(void);
+
+/**
+ * rv_rtapp_pagefault_error - report violation of the LTL property
+ * @task:	the task violating the LTL property
+ * @mon:	the LTL monitor
+ *
+ * Must be implemented. This function should invoke the RV reactor and the monitor's tracepoints.
+ */
+void rv_rtapp_pagefault_error(struct task_struct *task, struct ltl_monitor *mon);
+
+extern int rv_rtapp_pagefault_task_slot;
+
+/**
+ * rv_rtapp_pagefault_get_monitor - get the struct ltl_monitor of a task
+ */
+static inline struct ltl_monitor *rv_rtapp_pagefault_get_monitor(struct task_struct *task)
+{
+	return &task->rv[rv_rtapp_pagefault_task_slot].ltl_mon;
+}
+
+/**
+ * rv_rtapp_pagefault_atoms_init - initialize the atomic propositions
+ * @task:	the task
+ * @mon:	the LTL monitor
+ *
+ * Must be implemented. This function is called during task creation, and should initialize all
+ * atomic propositions. rv_rtapp_pagefault_atom_set() should be used to implement this function.
+ *
+ * This function does not have to initialize atomic propositions that are updated by
+ * rv_rtapp_pagefault_atoms_fetch(), because the two functions are called together.
+ */
+void rv_rtapp_pagefault_atoms_init(struct task_struct *task, struct ltl_monitor *mon);
+
+/**
+ * rv_rtapp_pagefault_atoms_fetch - fetch the atomic propositions
+ * @task:	the task
+ * @mon:	the LTL monitor
+ *
+ * Must be implemented. This function is called anytime the Buchi automaton is triggered. Its
+ * intended purpose is to update the atomic propositions which are expensive to trace and can be
+ * easily read from @task. rv_rtapp_pagefault_atom_set() should be used to implement this function.
+ *
+ * Using this function may cause incorrect verification result if it is important for the LTL that
+ * the atomic propositions must be updated at the correct time. Therefore, if it is possible,
+ * updating atomic propositions should be done with rv_rtapp_pagefault_atom_update() instead.
+ *
+ * An example where this function is useful is with the LTL property:
+ *    always (RT imply not PAGEFAULT)
+ * (a realtime task does not raise page faults)
+ *
+ * In this example, adding tracepoints to track RT is complicated, because it is changed in
+ * differrent places (mutex's priority boosting, sched_setscheduler). Furthermore, for this LTL
+ * property, we don't care exactly when RT changes, as long as we have its correct value when
+ * PAGEFAULT==true. Therefore, it is better to update RT in rv_rtapp_pagefault_atoms_fetch(), as it
+ * can easily be retrieved from task_struct.
+ *
+ * This function can be empty.
+ */
+void rv_rtapp_pagefault_atoms_fetch(struct task_struct *task, struct ltl_monitor *mon);
+
+/**
+ * rv_rtapp_pagefault_atom_update - update an atomic proposition
+ * @task:	the task
+ * @atom:	the atomic proposition, one of enum rtapp_pagefault_atom
+ * @value:	the new value for @atom
+ *
+ * Update an atomic proposition and trigger the Buchi atomaton to check for violation of the LTL
+ * property. This function can be called in tracepoints' handler, for example.
+ */
+void rv_rtapp_pagefault_atom_update(struct task_struct *task, unsigned int atom, bool value);
+
+/**
+ * rv_rtapp_pagefault_atom_get - get an atomic proposition
+ * @mon:	the monitor
+ * @atom:	the atomic proposition, one of enum rtapp_pagefault_atom
+ *
+ * Returns the value of an atomic proposition.
+ */
+static inline
+enum ltl_truth_value rv_rtapp_pagefault_atom_get(struct ltl_monitor *mon, unsigned int atom)
+{
+	return mon->atoms[atom];
+}
+
+/**
+ * rv_rtapp_pagefault_atom_set - set an atomic proposition
+ * @mon:	the monitor
+ * @atom:	the atomic proposition, one of enum rtapp_pagefault_atom
+ * @value:	the new value for @atom
+ *
+ * Update an atomic proposition without triggering the Buchi automaton. This can be useful to
+ * implement rv_rtapp_pagefault_atoms_fetch() and rv_rtapp_pagefault_atoms_init().
+ *
+ * Another use case for this function is when multiple atomic propositions change at the same time,
+ * because calling rv_rtapp_pagefault_atom_update() (and thus triggering the Buchi automaton)
+ * multiple times may be incorrect. In that case, rv_rtapp_pagefault_atom_set() can be used to avoid
+ * triggering the Buchi automaton, and rv_rtapp_pagefault_atom_update() is only used for the last
+ * atomic proposition.
+ */
+static inline
+void rv_rtapp_pagefault_atom_set(struct ltl_monitor *mon, unsigned int atom, bool value)
+{
+	mon->atoms[atom] = value;
+}
+
+/**
+ * rv_rtapp_pagefault_get_data - get the custom data of this monitor.
+ * @mon: the monitor
+ *
+ * If this function is used, rv_rtapp_pagefault_init() must have been called with a positive
+ * data_size.
+ */
+static inline void *rv_rtapp_pagefault_get_data(struct ltl_monitor *mon)
+{
+	return &mon->data;
+}
diff --git a/kernel/trace/rv/monitors/rtapp_pagefault/ltl b/kernel/trace/rv/monitors/rtapp_pagefault/ltl
new file mode 100644
index 000000000000..d7ce62102733
--- /dev/null
+++ b/kernel/trace/rv/monitors/rtapp_pagefault/ltl
@@ -0,0 +1 @@
+RULE = always (RT imply not PAGEFAULT)
diff --git a/kernel/trace/rv/monitors/rtapp_pagefault/rtapp_pagefault.c b/kernel/trace/rv/monitors/rtapp_pagefault/rtapp_pagefault.c
new file mode 100644
index 000000000000..32aaae9fea46
--- /dev/null
+++ b/kernel/trace/rv/monitors/rtapp_pagefault/rtapp_pagefault.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/ftrace.h>
+#include <linux/tracepoint.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rv.h>
+#include <rv/instrumentation.h>
+#include <linux/sched/rt.h>
+#include <trace/events/sched.h>
+#include <trace/events/exceptions.h>
+#include <rv_trace.h>
+
+#include "ba.h"
+
+static void handle_page_fault(void *data, unsigned long address, struct pt_regs *regs,
+				unsigned long error_code)
+{
+	rv_rtapp_pagefault_atom_update(current, PAGEFAULT, true);
+	rv_rtapp_pagefault_atom_update(current, PAGEFAULT, false);
+}
+
+void rv_rtapp_pagefault_atoms_fetch(struct task_struct *task, struct ltl_monitor *mon)
+{
+	rv_rtapp_pagefault_atom_set(mon, RT, rt_task(task));
+}
+
+void rv_rtapp_pagefault_atoms_init(struct task_struct *task, struct ltl_monitor *mon)
+{
+	rv_rtapp_pagefault_atom_set(mon, PAGEFAULT, false);
+}
+
+static int enable_rtapp_pagefault(void)
+{
+	int ret;
+
+	ret = rv_rtapp_pagefault_init(0);
+	if (ret)
+		return ret;
+
+	rv_attach_trace_probe("rtapp_pagefault", page_fault_kernel, handle_page_fault);
+	rv_attach_trace_probe("rtapp_pagefault", page_fault_user, handle_page_fault);
+
+	return 0;
+}
+
+static void disable_rtapp_pagefault(void)
+{
+	rv_detach_trace_probe("rtapp_pagefault", page_fault_kernel, handle_page_fault);
+	rv_detach_trace_probe("rtapp_pagefault", page_fault_user, handle_page_fault);
+
+	rv_rtapp_pagefault_destroy();
+}
+
+static struct rv_monitor rv_rtapp_pagefault = {
+	.name = "rtapp_pagefault",
+	.description = "monitor RT tasks do not page fault",
+	.enable = enable_rtapp_pagefault,
+	.disable = disable_rtapp_pagefault,
+};
+
+void rv_rtapp_pagefault_error(struct task_struct *task, struct ltl_monitor *mon)
+{
+	trace_rtapp_pagefault_error(task);
+#ifdef CONFIG_RV_REACTORS
+	if (rv_rtapp_pagefault.react)
+		rv_rtapp_pagefault.react("rv: %s[%d](RT) raises a page fault\n",
+					task->comm, task->pid);
+#endif
+}
+
+static int __init register_rtapp_pagefault(void)
+{
+	rv_register_monitor(&rv_rtapp_pagefault);
+	return 0;
+}
+
+static void __exit unregister_rtapp_pagefault(void)
+{
+	rv_unregister_monitor(&rv_rtapp_pagefault);
+}
+
+module_init(register_rtapp_pagefault);
+module_exit(unregister_rtapp_pagefault);
diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h
index 79a7388b5c55..560581d7edcb 100644
--- a/kernel/trace/rv/rv_trace.h
+++ b/kernel/trace/rv/rv_trace.h
@@ -165,6 +165,26 @@ TRACE_EVENT(rtapp_block_sleep_error,
 	TP_printk("rv: %s[%d](RT) is blocked\n", __get_str(comm), __entry->pid)
 );
 #endif
+#ifdef CONFIG_RV_MON_RTAPP_PAGEFAULT
+TRACE_EVENT(rtapp_pagefault_error,
+
+	TP_PROTO(struct task_struct *task),
+
+	TP_ARGS(task),
+
+	TP_STRUCT__entry(
+		__string(comm, task->comm)
+		__field(pid_t, pid)
+	),
+
+	TP_fast_assign(
+		__assign_str(comm);
+		__entry->pid = task->pid;
+	),
+
+	TP_printk("rv: %s[%d](RT) raises a page fault", __get_str(comm), __entry->pid)
+);
+#endif
 #endif /* _TRACE_RV_H */
 
 /* This part must be outside protection */
-- 
2.39.5



From leo.yan at arm.com  Tue Mar 11 10:04:46 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:46 +0000
Subject: [PATCH v3 1/6] coresight: etm4x: Extract the trace unit controlling
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-2-leo.yan@arm.com>

The trace unit is controlled in the ETM hardware enabling and disabling.
The sequential changes for support AUX pause and resume will reuse the
same operations.

Extract the operations in the etm4_{enable|disable}_trace_unit()
functions.  A minor improvement in etm4_enable_trace_unit() is for
returning the timeout error to callers.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../coresight/coresight-etm4x-core.c          | 103 +++++++++++-------
 1 file changed, 62 insertions(+), 41 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e5972f16abff..53cb0569dbbf 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -431,6 +431,44 @@ static int etm4x_wait_status(struct csdev_access *csa, int pos, int val)
 	return coresight_timeout(csa, TRCSTATR, pos, val);
 }
 
+static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
+{
+	struct coresight_device *csdev = drvdata->csdev;
+	struct device *etm_dev = &csdev->dev;
+	struct csdev_access *csa = &csdev->access;
+
+	/*
+	 * ETE mandates that the TRCRSR is written to before
+	 * enabling it.
+	 */
+	if (etm4x_is_ete(drvdata))
+		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
+
+	etm4x_allow_trace(drvdata);
+	/* Enable the trace unit */
+	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
+
+	/* Synchronize the register updates for sysreg access */
+	if (!csa->io_mem)
+		isb();
+
+	/* wait for TRCSTATR.IDLE to go back down to '0' */
+	if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) {
+		dev_err(etm_dev,
+			"timeout while waiting for Idle Trace Status\n");
+		return -ETIME;
+	}
+
+	/*
+	 * As recommended by section 4.3.7 ("Synchronization when using the
+	 * memory-mapped interface") of ARM IHI 0064D
+	 */
+	dsb(sy);
+	isb();
+
+	return 0;
+}
+
 static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 {
 	int i, rc;
@@ -539,33 +577,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
 	}
 
-	/*
-	 * ETE mandates that the TRCRSR is written to before
-	 * enabling it.
-	 */
-	if (etm4x_is_ete(drvdata))
-		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
-
-	etm4x_allow_trace(drvdata);
-	/* Enable the trace unit */
-	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
-
-	/* Synchronize the register updates for sysreg access */
-	if (!csa->io_mem)
-		isb();
-
-	/* wait for TRCSTATR.IDLE to go back down to '0' */
-	if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0))
-		dev_err(etm_dev,
-			"timeout while waiting for Idle Trace Status\n");
-
-	/*
-	 * As recommended by section 4.3.7 ("Synchronization when using the
-	 * memory-mapped interface") of ARM IHI 0064D
-	 */
-	dsb(sy);
-	isb();
-
+	rc = etm4_enable_trace_unit(drvdata);
 done:
 	etm4_cs_lock(drvdata, csa);
 
@@ -884,25 +896,12 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
 	return ret;
 }
 
-static void etm4_disable_hw(void *info)
+static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
 {
 	u32 control;
-	struct etmv4_drvdata *drvdata = info;
-	struct etmv4_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 	struct device *etm_dev = &csdev->dev;
 	struct csdev_access *csa = &csdev->access;
-	int i;
-
-	etm4_cs_unlock(drvdata, csa);
-	etm4_disable_arch_specific(drvdata);
-
-	if (!drvdata->skip_power_up) {
-		/* power can be removed from the trace unit now */
-		control = etm4x_relaxed_read32(csa, TRCPDCR);
-		control &= ~TRCPDCR_PU;
-		etm4x_relaxed_write32(csa, control, TRCPDCR);
-	}
 
 	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
 
@@ -943,6 +942,28 @@ static void etm4_disable_hw(void *info)
 	 * of ARM IHI 0064H.b.
 	 */
 	isb();
+}
+
+static void etm4_disable_hw(void *info)
+{
+	u32 control;
+	struct etmv4_drvdata *drvdata = info;
+	struct etmv4_config *config = &drvdata->config;
+	struct coresight_device *csdev = drvdata->csdev;
+	struct csdev_access *csa = &csdev->access;
+	int i;
+
+	etm4_cs_unlock(drvdata, csa);
+	etm4_disable_arch_specific(drvdata);
+
+	if (!drvdata->skip_power_up) {
+		/* power can be removed from the trace unit now */
+		control = etm4x_relaxed_read32(csa, TRCPDCR);
+		control &= ~TRCPDCR_PU;
+		etm4x_relaxed_write32(csa, control, TRCPDCR);
+	}
+
+	etm4_disable_trace_unit(drvdata);
 
 	/* read the status of the single shot comparators */
 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
-- 
2.34.1



From leo.yan at arm.com  Tue Mar 11 10:04:47 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:47 +0000
Subject: [PATCH v3 2/6] coresight: Introduce pause and resume APIs for source
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-3-leo.yan@arm.com>

Introduce APIs for pausing and resuming trace source and export as GPL
symbols.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 drivers/hwtracing/coresight/coresight-core.c | 22 ++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-priv.h |  2 ++
 include/linux/coresight.h                    |  4 ++++
 3 files changed, 28 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index fb43ef6a3b1f..d4c3000608f2 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -367,6 +367,28 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
 }
 EXPORT_SYMBOL_GPL(coresight_disable_source);
 
+void coresight_pause_source(struct coresight_device *csdev)
+{
+	if (!coresight_is_percpu_source(csdev))
+		return;
+
+	if (source_ops(csdev)->pause_perf)
+		source_ops(csdev)->pause_perf(csdev);
+}
+EXPORT_SYMBOL_GPL(coresight_pause_source);
+
+int coresight_resume_source(struct coresight_device *csdev)
+{
+	if (!coresight_is_percpu_source(csdev))
+		return -EOPNOTSUPP;
+
+	if (!source_ops(csdev)->resume_perf)
+		return -EOPNOTSUPP;
+
+	return source_ops(csdev)->resume_perf(csdev);
+}
+EXPORT_SYMBOL_GPL(coresight_resume_source);
+
 /*
  * coresight_disable_path_from : Disable components in the given path beyond
  * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 82644aff8d2b..2d9baa9d8228 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -249,5 +249,7 @@ void coresight_add_helper(struct coresight_device *csdev,
 void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
 struct coresight_device *coresight_get_percpu_sink(int cpu);
 void coresight_disable_source(struct coresight_device *csdev, void *data);
+void coresight_pause_source(struct coresight_device *csdev);
+int coresight_resume_source(struct coresight_device *csdev);
 
 #endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d79a242b271d..c95c72e07e02 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -398,6 +398,8 @@ struct coresight_ops_link {
  *		is associated to.
  * @enable:	enables tracing for a source.
  * @disable:	disables tracing for a source.
+ * @resume_perf: resumes tracing for a source in perf session.
+ * @pause_perf:	pauses tracing for a source in perf session.
  */
 struct coresight_ops_source {
 	int (*cpu_id)(struct coresight_device *csdev);
@@ -405,6 +407,8 @@ struct coresight_ops_source {
 		      enum cs_mode mode, struct coresight_path *path);
 	void (*disable)(struct coresight_device *csdev,
 			struct perf_event *event);
+	int (*resume_perf)(struct coresight_device *csdev);
+	void (*pause_perf)(struct coresight_device *csdev);
 };
 
 /**
-- 
2.34.1



From leo.yan at arm.com  Tue Mar 11 10:04:49 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:49 +0000
Subject: [PATCH v3 4/6] coresight: perf: Support AUX trace pause and resume
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-5-leo.yan@arm.com>

This commit supports AUX trace pause and resume in a perf session for
Arm CoreSight.

First, we need to decide which flag can indicate the CoreSight PMU event
has started.  The 'event->hw.state' cannot be used for this purpose
because its initial value and the value after hardware trace enabling
are both 0.

On the other hand, the context value 'ctxt->event_data' stores the ETM
private info.  This pointer is valid only when the PMU event has been
enabled. It is safe to permit AUX trace pause and resume operations only
when it is not a NULL pointer.

To achieve fine-grained control of the pause and resume, only the tracer
is disabled and enabled.  This avoids the unnecessary complexity and
latency caused by manipulating the entire link path.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../hwtracing/coresight/coresight-etm-perf.c  | 45 ++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f4cccd68e625..2dcf1809cb7f 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -365,6 +365,18 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 			continue;
 		}
 
+		/*
+		 * If AUX pause feature is enabled but the ETM driver does not
+		 * support the operations, clear this CPU from the mask and
+		 * continue to next one.
+		 */
+		if (event->attr.aux_start_paused &&
+		    (!source_ops(csdev)->pause_perf || !source_ops(csdev)->resume_perf)) {
+			dev_err_once(&csdev->dev, "AUX pause is not supported.\n");
+			cpumask_clear_cpu(cpu, mask);
+			continue;
+		}
+
 		/*
 		 * No sink provided - look for a default sink for all the ETMs,
 		 * where this event can be scheduled.
@@ -450,6 +462,15 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 	goto out;
 }
 
+static int etm_event_resume(struct coresight_device *csdev,
+			     struct etm_ctxt *ctxt)
+{
+	if (!ctxt->event_data)
+		return 0;
+
+	return coresight_resume_source(csdev);
+}
+
 static void etm_event_start(struct perf_event *event, int flags)
 {
 	int cpu = smp_processor_id();
@@ -463,6 +484,14 @@ static void etm_event_start(struct perf_event *event, int flags)
 	if (!csdev)
 		goto fail;
 
+	if (flags & PERF_EF_RESUME) {
+		if (etm_event_resume(csdev, ctxt) < 0) {
+			dev_err(&csdev->dev, "Failed to resume ETM event.\n");
+			goto fail;
+		}
+		return;
+	}
+
 	/* Have we messed up our tracking ? */
 	if (WARN_ON(ctxt->event_data))
 		goto fail;
@@ -545,6 +574,16 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 }
 
+static void etm_event_pause(struct coresight_device *csdev,
+			    struct etm_ctxt *ctxt)
+{
+	if (!ctxt->event_data)
+		return;
+
+	/* Stop tracer */
+	coresight_pause_source(csdev);
+}
+
 static void etm_event_stop(struct perf_event *event, int mode)
 {
 	int cpu = smp_processor_id();
@@ -555,6 +594,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	struct etm_event_data *event_data;
 	struct coresight_path *path;
 
+	if (mode & PERF_EF_PAUSE)
+		return etm_event_pause(csdev, ctxt);
+
 	/*
 	 * If we still have access to the event_data via handle,
 	 * confirm that we haven't messed up the tracking.
@@ -899,7 +941,8 @@ int __init etm_perf_init(void)
 	int ret;
 
 	etm_pmu.capabilities		= (PERF_PMU_CAP_EXCLUSIVE |
-					   PERF_PMU_CAP_ITRACE);
+					   PERF_PMU_CAP_ITRACE |
+					   PERF_PMU_CAP_AUX_PAUSE);
 
 	etm_pmu.attr_groups		= etm_pmu_attr_groups;
 	etm_pmu.task_ctx_nr		= perf_sw_context;
-- 
2.34.1



From leo.yan at arm.com  Tue Mar 11 10:04:48 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:48 +0000
Subject: [PATCH v3 3/6] coresight: etm4x: Hook pause and resume callbacks
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-4-leo.yan@arm.com>

Add callbacks for pausing and resuming the tracer.

A "paused" flag in the driver data indicates whether the tracer is
paused.  If the flag is set, the driver will skip starting the hardware
trace.  The flag is always set to false for the sysfs mode, meaning the
tracer will never be paused in the case.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../coresight/coresight-etm4x-core.c          | 42 ++++++++++++++++++-
 drivers/hwtracing/coresight/coresight-etm4x.h |  2 +
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 53cb0569dbbf..5b69446db947 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -577,7 +577,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
 		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
 	}
 
-	rc = etm4_enable_trace_unit(drvdata);
+	if (!drvdata->paused)
+		rc = etm4_enable_trace_unit(drvdata);
 done:
 	etm4_cs_lock(drvdata, csa);
 
@@ -820,6 +821,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
 
 	drvdata->trcid = path->trace_id;
 
+	/* Populate pause state */
+	drvdata->paused = !!READ_ONCE(event->hw.aux_paused);
+
 	/* And enable it */
 	ret = etm4_enable_hw(drvdata);
 
@@ -846,6 +850,9 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
 
 	drvdata->trcid = path->trace_id;
 
+	/* Tracer will never be paused in sysfs mode */
+	drvdata->paused = false;
+
 	/*
 	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
 	 * ensures that register writes occur when cpu is powered.
@@ -1080,10 +1087,43 @@ static void etm4_disable(struct coresight_device *csdev,
 		coresight_set_mode(csdev, CS_MODE_DISABLED);
 }
 
+static int etm4_resume_perf(struct coresight_device *csdev)
+{
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct csdev_access *csa = &csdev->access;
+
+	if (coresight_get_mode(csdev) != CS_MODE_PERF)
+		return -EINVAL;
+
+	etm4_cs_unlock(drvdata, csa);
+	etm4_enable_trace_unit(drvdata);
+	etm4_cs_lock(drvdata, csa);
+
+	drvdata->paused = false;
+	return 0;
+}
+
+static void etm4_pause_perf(struct coresight_device *csdev)
+{
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	struct csdev_access *csa = &csdev->access;
+
+	if (coresight_get_mode(csdev) != CS_MODE_PERF)
+		return;
+
+	etm4_cs_unlock(drvdata, csa);
+	etm4_disable_trace_unit(drvdata);
+	etm4_cs_lock(drvdata, csa);
+
+	drvdata->paused = true;
+}
+
 static const struct coresight_ops_source etm4_source_ops = {
 	.cpu_id		= etm4_cpu_id,
 	.enable		= etm4_enable,
 	.disable	= etm4_disable,
+	.resume_perf	= etm4_resume_perf,
+	.pause_perf	= etm4_pause_perf,
 };
 
 static const struct coresight_ops etm4_cs_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index bd7db36ba197..ac649515054d 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -983,6 +983,7 @@ struct etmv4_save_state {
  * @state_needs_restore: True when there is context to restore after PM exit
  * @skip_power_up: Indicates if an implementation can skip powering up
  *		   the trace unit.
+ * @paused:	Indicates if the trace unit is paused.
  * @arch_features: Bitmap of arch features of etmv4 devices.
  */
 struct etmv4_drvdata {
@@ -1036,6 +1037,7 @@ struct etmv4_drvdata {
 	struct etmv4_save_state		*save_state;
 	bool				state_needs_restore;
 	bool				skip_power_up;
+	bool				paused;
 	DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
 };
 
-- 
2.34.1



From leo.yan at arm.com  Tue Mar 11 10:04:50 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:50 +0000
Subject: [PATCH v3 5/6] coresight: perf: Update buffer on AUX pause
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-6-leo.yan@arm.com>

Due to sinks like ETR and ETB don't support interrupt handling, the
hardware trace data might be lost for continuous running tasks.

This commit takes advantage of the AUX pause for updating trace buffer
to mitigate the trace data losing issue.

The per CPU sink has its own interrupt handling.  Thus, there will be a
race condition between the updating buffer in NMI and sink's interrupt
handler.  To avoid the race condition, this commit disallows updating
buffer on AUX pause for the per CPU sink.  Currently, this is only
applied for TRBE.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../hwtracing/coresight/coresight-etm-perf.c  | 43 ++++++++++++++++++-
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 2dcf1809cb7f..f1551c08ecb2 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -574,14 +574,53 @@ static void etm_event_start(struct perf_event *event, int flags)
 	return;
 }
 
-static void etm_event_pause(struct coresight_device *csdev,
+static void etm_event_pause(struct perf_event *event,
+			    struct coresight_device *csdev,
 			    struct etm_ctxt *ctxt)
 {
+	int cpu = smp_processor_id();
+	struct coresight_device *sink;
+	struct perf_output_handle *handle = &ctxt->handle;
+	struct coresight_path *path;
+	unsigned long size;
+
 	if (!ctxt->event_data)
 		return;
 
 	/* Stop tracer */
 	coresight_pause_source(csdev);
+
+	path = etm_event_cpu_path(ctxt->event_data, cpu);
+	sink = coresight_get_sink(path);
+	if (WARN_ON_ONCE(!sink))
+		return;
+
+	/*
+	 * The per CPU sink has own interrupt handling, it might have
+	 * race condition with updating buffer on AUX trace pause if
+	 * it is invoked from NMI.  To avoid the race condition,
+	 * disallows updating buffer for the per CPU sink case.
+	 */
+	if (coresight_is_percpu_sink(sink))
+		return;
+
+	if (WARN_ON_ONCE(handle->event != event))
+		return;
+
+	if (!sink_ops(sink)->update_buffer)
+		return;
+
+	size = sink_ops(sink)->update_buffer(sink, handle,
+					     ctxt->event_data->snk_config);
+	if (READ_ONCE(handle->event)) {
+		if (!size)
+			return;
+
+		perf_aux_output_end(handle, size);
+		perf_aux_output_begin(handle, event);
+	} else {
+		WARN_ON_ONCE(size);
+	}
 }
 
 static void etm_event_stop(struct perf_event *event, int mode)
@@ -595,7 +634,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
 	struct coresight_path *path;
 
 	if (mode & PERF_EF_PAUSE)
-		return etm_event_pause(csdev, ctxt);
+		return etm_event_pause(event, csdev, ctxt);
 
 	/*
 	 * If we still have access to the event_data via handle,
-- 
2.34.1



From leo.yan at arm.com  Tue Mar 11 10:04:51 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 11 Mar 2025 17:04:51 +0000
Subject: [PATCH v3 6/6] Documentation: coresight: Document AUX pause and resume
In-Reply-To: <20250311170451.611389-1-leo.yan@arm.com>
References: <20250311170451.611389-1-leo.yan@arm.com>
Message-ID: <20250311170451.611389-7-leo.yan@arm.com>

This adds description for AUX pause and resume.  It gives introduction
for what's AUX pause and resume and records usage examples.

Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 .../trace/coresight/coresight-perf.rst        | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst
index d087aae7d492..30be89320621 100644
--- a/Documentation/trace/coresight/coresight-perf.rst
+++ b/Documentation/trace/coresight/coresight-perf.rst
@@ -78,6 +78,37 @@ enabled like::
 
 Please refer to the kernel configuration help for more information.
 
+Fine-grained tracing with AUX pause and resume
+----------------------------------------------
+
+Arm CoreSight may generate a large amount of hardware trace data, which
+will lead to overhead in recording and distract users when reviewing
+profiling result. To mitigate the issue of excessive trace data, Perf
+provides AUX pause and resume functionality for fine-grained tracing.
+
+The AUX pause and resume can be triggered by associated events. These
+events can be ftrace tracepoints (including static and dynamic
+tracepoints) or PMU events (e.g. CPU PMU cycle event). To create a perf
+session with AUX pause / resume, three configuration terms are
+introduced:
+
+- "aux-action=start-paused": it is specified for the cs_etm PMU event to
+  launch in a paused state.
+- "aux-action=pause": an associated event is specified with this term
+  to pause AUX trace.
+- "aux-action=resume": an associated event is specified with this term
+  to resume AUX trace.
+
+Example for triggering AUX pause and resume with ftrace tracepoints::
+
+  perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls
+
+Example for triggering AUX pause and resume with PMU event::
+
+  perf record -a -e cs_etm/aux-action=start-paused/k \
+        -e cycles/aux-action=pause,period=10000000/ \
+        -e cycles/aux-action=resume,period=1050000/ -- sleep 1
+
 Perf test - Verify kernel and userspace perf CoreSight work
 -----------------------------------------------------------
 
-- 
2.34.1



From catalin.marinas at arm.com  Tue Mar 11 10:15:48 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 17:15:48 +0000
Subject: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
In-Reply-To: <20250227144150.1667735-1-suzuki.poulose@arm.com>
References: <20250227144150.1667735-1-suzuki.poulose@arm.com>
Message-ID: <174171334191.3659388.13494602275110471880.b4-ty@arm.com>

On Thu, 27 Feb 2025 14:41:47 +0000, Suzuki K Poulose wrote:
> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> half and shared top half. In Linux we treat the "top" bit of the IPA space as
> an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> and are managed by RMM. The "top" bit as attribute is only a software construct.
> 
> [...]

Applied to arm64 (for-next/cca-dma-address), thanks!

[1/3] dma: Fix encryption bit clearing for dma_to_phys
      https://git.kernel.org/arm64/c/c380931712d1
[2/3] dma: Introduce generic dma_addr_*crypted helpers
      https://git.kernel.org/arm64/c/b66e2ee7b6c8
[3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
      https://git.kernel.org/arm64/c/7d953a062416

-- 
Catalin



From broonie at kernel.org  Tue Mar 11 10:17:26 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 11 Mar 2025 17:17:26 +0000
Subject: [PATCH v2] spi: mt65xx: add PM QoS support
In-Reply-To: <20250304024045.7788-1-leilk.liu@mediatek.com>
References: <20250304024045.7788-1-leilk.liu@mediatek.com>
Message-ID: <174171344631.214660.9058567324727633834.b4-ty@kernel.org>

On Tue, 04 Mar 2025 10:37:15 +0800, Leilk Liu wrote:
> Enable Quality of Service(QoS) support to speed up interrupt service
> routine handle. Sometimes, a gic interrupt will be generated after
> SPI transmission, but at this time the CPU is in an idle state and the
> processing handler will be very slow. It takes time to exit the idle state
> and then become active. This will cause the SPI handler to execute slowly
> and cause SPI transfer timeouts.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: mt65xx: add PM QoS support
      commit: 632556d5799a2b3e87dd5594a59245523b39cf31

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From jonathanh at nvidia.com  Tue Mar 11 10:32:10 2025
From: jonathanh at nvidia.com (Jon Hunter)
Date: Tue, 11 Mar 2025 17:32:10 +0000
Subject: [PATCH RFC net-next v2 0/3] net: stmmac: approach 2 to solve EEE
 LPI reset issues
In-Reply-To: <Z9BBm6tievFukbO8@shell.armlinux.org.uk>
References: <Z8m-CRucPxDW5zZK@shell.armlinux.org.uk>
 <29bc7abd-b5cc-4359-8aa6-dbf66e8b70e4@nvidia.com>
 <Z8sn7b_ra_QnWUjw@shell.armlinux.org.uk>
 <673e453b-798f-4fc1-8ed1-3cf597e926b4@nvidia.com>
 <4fe02d97-2c38-4d40-b17d-5f8174d2f7cc@nvidia.com>
 <Z9BBm6tievFukbO8@shell.armlinux.org.uk>
Message-ID: <6bfc94a7-0215-4433-9f51-1bfb1cdd1e43@nvidia.com>


On 11/03/2025 13:58, Russell King (Oracle) wrote:

...

> I'm wondering whether there's something else which needs the RX clock
> running in order to take effect.
> 
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index e2146d3aee74..48a646b76a29 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -3109,10 +3109,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>>          if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
>>                  priv->plat->dma_cfg->atds = 1;
>> -       /* Note that the PHY clock must be running for reset to complete. */
>> -       phylink_rx_clk_stop_block(priv->phylink);
>>          ret = stmmac_reset(priv, priv->ioaddr);
>> -       phylink_rx_clk_stop_unblock(priv->phylink);
>>          if (ret) {
>>                  netdev_err(priv->dev, "Failed to reset the dma\n");
>>                  return ret;
>> @@ -7951,6 +7948,8 @@ int stmmac_resume(struct device *dev)
>>          rtnl_lock();
>>          mutex_lock(&priv->lock);
>> +       /* Note that the PHY clock must be running for reset to complete. */
>> +       phylink_rx_clk_stop_block(priv->phylink);
>>          stmmac_reset_queues_param(priv);
>>          stmmac_free_tx_skbufs(priv);
>> @@ -7961,6 +7960,7 @@ int stmmac_resume(struct device *dev)
>>          stmmac_set_rx_mode(ndev);
>>          stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
>> +       phylink_rx_clk_stop_unblock(priv->phylink);
>>          stmmac_enable_all_queues(priv);
>>          stmmac_enable_all_dma_irq(priv);
> 
> If you haven't already, can you try shrinking down the number of
> functions that are within the block..unblock region please?

It seems that at a minimum I need to block/unblock around the following
functions ...

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e2146d3aee74..46c343088b1f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3109,10 +3109,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
         if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
                 priv->plat->dma_cfg->atds = 1;
  
-       /* Note that the PHY clock must be running for reset to complete. */
-       phylink_rx_clk_stop_block(priv->phylink);
         ret = stmmac_reset(priv, priv->ioaddr);
-       phylink_rx_clk_stop_unblock(priv->phylink);
         if (ret) {
                 netdev_err(priv->dev, "Failed to reset the dma\n");
                 return ret;
@@ -7953,10 +7950,13 @@ int stmmac_resume(struct device *dev)
  
         stmmac_reset_queues_param(priv);
  
+       /* Note that the PHY clock must be running for reset to complete. */
+       phylink_rx_clk_stop_block(priv->phylink);
         stmmac_free_tx_skbufs(priv);
         stmmac_clear_descriptors(priv, &priv->dma_conf);
  
         stmmac_hw_setup(ndev, false);
+       phylink_rx_clk_stop_unblock(priv->phylink);
         stmmac_init_coalesce(priv);
         stmmac_set_rx_mode(ndev);

> Looking at the functions called:
> 
> stmmac_reset_queues_param()
> stmmac_free_tx_skbufs()
> stmmac_clear_descriptors()
> 	These look like it's only manipulating software state

So it appears that the last two need to be in the block/unblock region
and ...
  
> stmmac_hw_setup()
> 	We know this calls stmmac_reset() and thus needs the blocking

... this one, which is no surprise, but the others are OK. Please
note so far I have only tested on the Tegra186 board which seems
to be the most sensitive.

Cheers
Jon

-- 
nvpublic



From aweber.kernel at gmail.com  Tue Mar 11 10:34:25 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Tue, 11 Mar 2025 18:34:25 +0100
Subject: [PATCH next] pinctrl: bcm281xx: Add missing assignment in
 bcm21664_pinctrl_lock_all()
In-Reply-To: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
References: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
Message-ID: <8b8b9074-8828-4477-93e0-32be63688d05@gmail.com>

On 10.03.2025 11:48, Dan Carpenter wrote:
> The next line checks if this regmap_write() failed, but it doesn't
> work because the assignment was accidentally left out.  Add the
> assignment.
> 
> Fixes: 60d69769c851 ("pinctrl: bcm281xx: Add support for BCM21664 pinmux")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>

Acked-by: Artur Weber <aweber.kernel at gmail.com>

Best regards
Artur


From kw at linux.com  Tue Mar 11 10:39:16 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Wed, 12 Mar 2025 02:39:16 +0900
Subject: [PATCH v3 0/2] PCI: dw-rockchip: hide broken ATS cap in EP-mode
In-Reply-To: <20250310094826.842681-4-cassel@kernel.org>
References: <20250310094826.842681-4-cassel@kernel.org>
Message-ID: <20250311173916.GA2673952@rocinante>

Hello,

> Hello there,
> 
> Address Translation Services (ATS) is broken on rk3588 when running the
> PCIe controller in Endpoint Mode.
> 
> This causes IOTLB invalidation timeout errors on the host side when using
> and rk3588 in Endpoint Mode, and you are unable to run pci_endpoint_test.
> 
> Solve this by hiding the ATS capability.
> With this, we do not get any IOTLB invalidation timeouts, and we can run
> pci_endpoint_test successfully.

Applied to controller/dwc, thank you!

	Krzysztof


From nicolinc at nvidia.com  Tue Mar 11 10:43:08 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 10:43:08 -0700
Subject: [PATCH v8 12/14] iommu/arm-smmu-v3: Introduce struct
 arm_smmu_vmaster
In-Reply-To: <20250311155714.GC5138@willie-the-truck>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
 <20250311155714.GC5138@willie-the-truck>
Message-ID: <Z9B2LMIi+88hlfza@Asurada-Nvidia>

On Tue, Mar 11, 2025 at 03:57:16PM +0000, Will Deacon wrote:
> On Tue, Feb 25, 2025 at 09:25:40AM -0800, Nicolin Chen wrote:
> > Use it to store all vSMMU-related data. The vsid (Virtual Stream ID) will
> > be the first use case. Since the vsid reader will be the eventq handler
> > that already holds a streams_mutex, reuse that to fenche the vmaster too.
> 
> "fenche"?

fence :)

And I fixed other nits too.

> > +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> > +				    struct arm_smmu_nested_domain *nested_domain)
> > +{
> > +	struct arm_smmu_vmaster *vmaster;
> > +	unsigned long vsid;
> > +	int ret;
> > +
> > +	iommu_group_mutex_assert(state->master->dev);
> > +
> > +	/* Skip invalid vSTE */
> > +	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> > +		return 0;
> 
> Ok, and we don't need to set 'state->vmaster' in this case because we
> only report stage-1 faults back to the vSMMU?

This is a good question that I didn't ask myself hard enough..

I think we should probably drop it. An invalid STE should trigger
a C_BAD_STE event that is in the supported vEVENT list. I'll run
some test before removing this line from v9.

> With the nits fixed:
> 
> Acked-by: Will Deacon <will at kernel.org>

Thanks!
Nicolin


From catalin.marinas at arm.com  Tue Mar 11 11:10:31 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 18:10:31 +0000
Subject: [PATCH V2 1/8] KVM: arm64: ptdump: Test PMD_TYPE_MASK for block
 mapping
In-Reply-To: <20250221044227.1145393-2-anshuman.khandual@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
 <20250221044227.1145393-2-anshuman.khandual@arm.com>
Message-ID: <Z9B8lyYEtL62ZzVb@arm.com>

On Fri, Feb 21, 2025 at 10:12:20AM +0530, Anshuman Khandual wrote:
> Test given page table entries against PMD_TYPE_SECT on PMD_TYPE_MASK mask
> bits for identifying block mappings in stage 2 page tables.
> 
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Cc: James Morse <james.morse at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: kvmarm at lists.linux.dev
> Cc: linux-kernel at vger.kernel.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
>  arch/arm64/kvm/ptdump.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
> index e4a342e903e2..098416d7e5c2 100644
> --- a/arch/arm64/kvm/ptdump.c
> +++ b/arch/arm64/kvm/ptdump.c
> @@ -52,8 +52,8 @@ static const struct ptdump_prot_bits stage2_pte_bits[] = {
>  		.set	= "AF",
>  		.clear	= "  ",
>  	}, {
> -		.mask	= PTE_TABLE_BIT | PTE_VALID,
> -		.val	= PTE_VALID,
> +		.mask	= PMD_TYPE_MASK,
> +		.val	= PMD_TYPE_SECT,
>  		.set	= "BLK",
>  		.clear	= "   ",
>  	},

Marc, Oliver - are you ok with this patch going in through the arm64
tree?

Thanks.

-- 
Catalin


From will at kernel.org  Tue Mar 11 11:11:52 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 18:11:52 +0000
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
Message-ID: <20250311181151.GD5216@willie-the-truck>

On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> Up until now we have only called the set_stall callback during
> initialization when the device is off. But we will soon start calling it
> to temporarily disable stall-on-fault when the device is on, so handle
> that by checking if the device is on and writing SCTLR.
> 
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
>  {
>  	struct arm_smmu_domain *smmu_domain = (void *)cookie;
>  	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> -	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> +	struct arm_smmu_device *smmu = smmu_domain->smmu;
> +	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> +	u32 mask = BIT(cfg->cbndx);
> +	bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> +	unsigned long flags;
>  
>  	if (enabled)
> -		qsmmu->stall_enabled |= BIT(cfg->cbndx);
> +		qsmmu->stall_enabled |= mask;
>  	else
> -		qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> +		qsmmu->stall_enabled &= ~mask;
> +
> +	/*
> +	 * If the device is on and we changed the setting, update the register.
> +	 */
> +	if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> +		spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> +
> +		u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> +
> +		if (enabled)
> +			reg |= ARM_SMMU_SCTLR_CFCFG;
> +		else
> +			reg &= ~ARM_SMMU_SCTLR_CFCFG;
> +
> +		arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);

Are you sure you don't need TLB invalidation for this to take effect? I
think some fields in the SCTLR can be cached in the TLB but you'll need
to check whether or not that applies to CFCFG.

Will


From sboyd at kernel.org  Tue Mar 11 11:13:30 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 11 Mar 2025 11:13:30 -0700
Subject: [GIT PULL] clk: samsung: drivers for v6.15
In-Reply-To: <20250309175147.6672-1-krzysztof.kozlowski@linaro.org>
References: <20250309175147.6672-1-krzysztof.kozlowski@linaro.org>
Message-ID: <135678b71cd2853fe55c5c5c6a6d3fcb.sboyd@kernel.org>

Quoting Krzysztof Kozlowski (2025-03-09 10:51:47)
> Hi,
> 
> New clk drivers for Samsung SoC.  This pull includes drivers which you
> commented later and pointed out few issues.  Pointed issues are in all Samsung
> clk drivers and the ones here just copy existing patterns:
> 
> 1. Headers: I fixed it for new and existing drivers and this pull request
> includes the fixes.
> 2. device_get_match_data(): I still wait for contributors response. If they do
> not respond, I will fix it for next cycle.
> 3. refdata and platform_driver_probe: I tried fixing it, but incomplete and
> need to investigate more.
> 
> Best regards,
> Krzysztof
> 
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-clk-6.15
> 
> for you to fetch changes up to 017bbc922a09630579ff7b5b314fb186b8c0efcf:
> 
>   clk: samsung: Drop unused clk.h and of.h headers (2025-03-07 16:01:22 +0100)
> 
> ----------------------------------------------------------------

Thanks. Pulled into clk-next


From robh at kernel.org  Tue Mar 11 11:15:27 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 13:15:27 -0500
Subject: [RFC PATCH v2 03/16] dt-bindings: media: i2c: max96717: add
 support for I2C ATR
In-Reply-To: <20250309084814.3114794-4-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-4-demonsingur@gmail.com>
Message-ID: <20250311181527.GA3917837-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:47:55AM +0200, Cosmin Tanislav wrote:
> MAX96717 is capable of address translation for the connected I2C slaves.
> 
> Add support for I2C ATR while keeping I2C gate for compatibility to
> support this usecase.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96717.yaml    | 39 +++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> index 1026678a17a7..dd28cc397674 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> @@ -91,6 +91,30 @@ properties:
>        incoming GMSL2 link. Therefore, it supports an i2c-gate
>        subnode to configure a sensor.
>  
> +  i2c-alias-pool:
> +    maxItems: 2
> +
> +  i2c-atr:
> +    type: object
> +    additionalProperties: false
> +
> +    properties:
> +      '#address-cells':
> +        const: 1
> +
> +      '#size-cells':
> +        const: 0
> +
> +    patternProperties:
> +      '^i2c at 0':

This allows "i2c at 0anything-you-want". Based on reg, you want 
'^i2c@[01]$'.

 
> +        $ref: /schemas/i2c/i2c-controller.yaml#
> +        unevaluatedProperties: false
> +        properties:
> +          reg:
> +            items:
> +              minimum: 0
> +              maximum: 1
> +
>  required:
>    - compatible
>    - reg
> @@ -98,6 +122,21 @@ required:
>  
>  additionalProperties: false
>  
> +allOf:
> +  - $ref: /schemas/i2c/i2c-atr.yaml#
> +
> +  - anyOf:
> +      - oneOf:
> +          - required: [i2c-atr]
> +          - required: [i2c-gate]
> +
> +      - not:
> +          required: [i2c-atr, i2c-gate]
> +
> +dependentRequired:
> +  i2c-atr: [i2c-alias-pool]
> +  i2c-alias-pool: [i2c-atr]
> +
>  examples:
>    - |
>      #include <dt-bindings/gpio/gpio.h>
> -- 
> 2.48.1
> 



From catalin.marinas at arm.com  Tue Mar 11 11:20:58 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 11 Mar 2025 18:20:58 +0000
Subject: [PATCH -next] arm64/fpsimd: Remove unused declaration fpsimd_kvm_prepare()
In-Reply-To: <20250309070723.1390958-1-yuehaibing@huawei.com>
References: <20250309070723.1390958-1-yuehaibing@huawei.com>
Message-ID: <174171719963.3723629.1526900223897615698.b4-ty@arm.com>

On Sun, 09 Mar 2025 15:07:23 +0800, Yue Haibing wrote:
> Commit fbc7e61195e2 ("KVM: arm64: Unconditionally save+flush host
> FPSIMD/SVE/SME state") removed the implementation but leave declaration.

Applied to arm64 (for-next/misc), thanks!

[1/1] arm64/fpsimd: Remove unused declaration fpsimd_kvm_prepare()
      https://git.kernel.org/arm64/c/31208bad3937

-- 
Catalin



From maz at kernel.org  Tue Mar 11 11:22:10 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 18:22:10 +0000
Subject: [PATCH V2 1/8] KVM: arm64: ptdump: Test PMD_TYPE_MASK for block
 mapping
In-Reply-To: <Z9B8lyYEtL62ZzVb@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
 <20250221044227.1145393-2-anshuman.khandual@arm.com>
 <Z9B8lyYEtL62ZzVb@arm.com>
Message-ID: <43e4dd905ebc6424511bd230ceb47ac1@kernel.org>

On 2025-03-11 18:10, Catalin Marinas wrote:
> On Fri, Feb 21, 2025 at 10:12:20AM +0530, Anshuman Khandual wrote:
>> Test given page table entries against PMD_TYPE_SECT on PMD_TYPE_MASK 
>> mask
>> bits for identifying block mappings in stage 2 page tables.
>> 
>> Cc: Marc Zyngier <maz at kernel.org>
>> Cc: Oliver Upton <oliver.upton at linux.dev>
>> Cc: James Morse <james.morse at arm.com>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: kvmarm at lists.linux.dev
>> Cc: linux-kernel at vger.kernel.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>>  arch/arm64/kvm/ptdump.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
>> index e4a342e903e2..098416d7e5c2 100644
>> --- a/arch/arm64/kvm/ptdump.c
>> +++ b/arch/arm64/kvm/ptdump.c
>> @@ -52,8 +52,8 @@ static const struct ptdump_prot_bits 
>> stage2_pte_bits[] = {
>>  		.set	= "AF",
>>  		.clear	= "  ",
>>  	}, {
>> -		.mask	= PTE_TABLE_BIT | PTE_VALID,
>> -		.val	= PTE_VALID,
>> +		.mask	= PMD_TYPE_MASK,
>> +		.val	= PMD_TYPE_SECT,
>>  		.set	= "BLK",
>>  		.clear	= "   ",
>>  	},
> 
> Marc, Oliver - are you ok with this patch going in through the arm64
> tree?

Yup, looks OK to me.

Acked-by: Marc Zyngier <maz at kernel.org>

         M.
-- 
Jazz is not dead. It just smells funny...


From robh at kernel.org  Tue Mar 11 11:23:04 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 13:23:04 -0500
Subject: [RFC PATCH v2 04/16] dt-bindings: media: i2c: max96717: add
 support for pinctrl/pinconf
In-Reply-To: <20250309084814.3114794-5-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-5-demonsingur@gmail.com>
Message-ID: <20250311182304.GA3925099-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:47:56AM +0200, Cosmin Tanislav wrote:
> MAX96717 is capable of configuring various pin properties.
> 
> Add pinctrl/pinconf properties to support this usecase.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../media/i2c/maxim,max96717-pinctrl.yaml     | 71 +++++++++++++++++++
>  .../bindings/media/i2c/maxim,max96717.yaml    | 16 ++++-
>  MAINTAINERS                                   |  1 +
>  3 files changed, 87 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
> new file mode 100644
> index 000000000000..347e66a5320c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml
> @@ -0,0 +1,71 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright (C) 2025 Analog Devices Inc.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/i2c/maxim,max96717-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Maxim GMSL2 Serializer Pinctrl
> +
> +maintainers:
> +  - Cosmin Tanislav <cosmin.tanislav at analog.com>
> +
> +allOf:
> +  - $ref: /schemas/pinctrl/pincfg-node.yaml#
> +  - $ref: /schemas/pinctrl/pinmux-node.yaml#
> +
> +unevaluatedProperties: false
> +
> +properties:
> +  function: true
> +  pins: true
> +  drive-open-drain: true
> +  drive-push-pull: true
> +  bias-disable: true
> +  bias-pull-up: true
> +  bias-pull-down: true
> +  output-disable: true
> +  output-enable: true
> +  output-low: true
> +  output-high: true
> +  slew-rate: true
> +  input-enable: true
> +
> +  maxim,jitter-compensation:
> +    type: boolean
> +    description: Enables jitter compensation.
> +
> +  maxim,gmsl-tx:
> +    type: boolean
> +    description: Enable transmitting pin value to GMSL link.
> +
> +  maxim,gmsl-rx:
> +    type: boolean
> +    description: Enable receiving pin value from GMSL link.
> +
> +  maxim,gmsl-tx-id:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Identifier used while transmitting value to GMSL link.
> +      Default value matches the pin number.

Use normally wrapping or blank line between paragraphs.

> +    minimum: 0
> +    maximum: 31
> +
> +  maxim,gmsl-rx-id:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Identifier used while receiving value from GMSL link.
> +      Default value matches the pin number.
> +    minimum: 0
> +    maximum: 31
> +
> +  maxim,rclkout-clock:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Clock value.
> +      0 - XTAL / 1 = 25MHz
> +      1 - XTAL / 2 = 12.5MHz
> +      2 - XTAL / 4 = 6.25MHz
> +      3 - Reference PLL output
> +    minimum: 0
> +    maximum: 3
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> index dd28cc397674..0a43582168a8 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> @@ -120,7 +120,21 @@ required:
>    - reg
>    - ports
>  
> -additionalProperties: false
> +additionalProperties:
> +  anyOf:
> +    - type: object
> +      allOf:
> +        - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#

You can drop the allOf here.

> +
> +      unevaluatedProperties: false
> +
> +    - type: object
> +      additionalProperties:
> +        type: object
> +        allOf:
> +          - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml#

And here.

> +
> +        unevaluatedProperties: false

Do you really need to support 2 forms?

This also allows the node names to be anything. We do that for existing 
cases, but for new ones you should define some prefix or suffix. 
Typically, '-pins$' is used.

Rob


From wens at csie.org  Tue Mar 11 11:24:43 2025
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 02:24:43 +0800
Subject: [PATCH v4 00/14] clk: sunxi-ng: add A523 clock support
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <174171748337.1740144.15952522850275241981.b4-ty@csie.org>

On Fri, 07 Mar 2025 00:26:14 +0000, Andre Przywara wrote:
> this is the fourth drop of the series introducing basic clock support for
> the Allwinner A523 family of SoCs, comprising A523, A527, T527, H728. [1]
> This times just a small rename of a macro name, and fixing the DT
> binding, where the separate patches for the two CCUs got merged into
> one. For a more detailed changelog, see below.
> 
> *************
> Please note that the clock numbers changed compared to v1 and v2, (but
> not against v3) so DTs from that older era cannot be used anymore with
> this driver: you have to update the DTB. Just copying the binding header
> and recompiling the DTB should do the trick, since the symbols stayed
> mostly the same, at least as far they are used in the basic DTs we use
> today.
> *************
> 
> [...]

Applied to clk-for-6.15 in git at github.com:linux-sunxi/linux-sunxi.git, thanks!

[01/14] clk: sunxi-ng: mp: introduce dual-divider clock
        commit: af7a221c12137271e8c31bc0c205ef4c57e89b4c
[02/14] clk: sunxi-ng: mp: provide wrappers for setting feature flags
        commit: 24ad1a7e8a3eca04dfe225b3e7935ab4ec326bb8
[03/14] clk: sunxi-ng: Add support for update bit
        commit: 38ea575784d3121b9c2e4c0bf425bc669e1c5e1b
[04/14] dt-bindings: clk: sunxi-ng: document two Allwinner A523 CCUs
        commit: 17bed1817f11b7d3c4ea0b38254f1bab78531a3d
[05/14] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
        commit: 04f6ff49525a8ba8ef3297de3e1a0e15ea3f5102
[06/14] clk: sunxi-ng: a523: Add support for bus clocks
        commit: 2d47dae9398135a48b58da9b059c23027b0e345e
[07/14] clk: sunxi-ng: a523: add video mod clocks
        commit: 4b759de121c46c693b61d6a22bf77d62333838e9
[08/14] clk: sunxi-ng: a523: add system mod clocks
        commit: 9bc061e57b4d97e187a767e45bff06b63f2a3126
[09/14] clk: sunxi-ng: a523: add interface mod clocks
        commit: dd19c52e686eb9f66816cd55fddfae8c7be2e6ea
[10/14] clk: sunxi-ng: a523: add USB mod clocks
        commit: 5fd7421770fb31a1ec35dd2400a849598466ac3b
[11/14] clk: sunxi-ng: a523: remaining mod clocks
        commit: 680f52d723e2ee9d97d167040eacc6a3af0b9cda
[12/14] clk: sunxi-ng: a523: add bus clock gates
        commit: 4548c0414839989be821e106b5128d5e7e13f2a4
[13/14] clk: sunxi-ng: a523: add reset lines
        commit: 9c8d960c13ab41c7e678eab5396b9258eaf8a159
[14/14] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
        commit: 575464821eb0f72c86d93794a79900a853b256b5

Best regards,
-- 
Chen-Yu Tsai <wens at csie.org>



From robh at kernel.org  Tue Mar 11 11:28:13 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 13:28:13 -0500
Subject: [RFC PATCH v2 05/16] dt-bindings: media: i2c: max96717: add
 support for MAX9295A
In-Reply-To: <20250309084814.3114794-6-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-6-demonsingur@gmail.com>
Message-ID: <20250311182813.GA3934398-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:47:57AM +0200, Cosmin Tanislav wrote:
> MAX9295A is an older variant of the MAX96717 which does not support
> tunnel mode.
> 
> Document the compatibility.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../devicetree/bindings/media/i2c/maxim,max96717.yaml          | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> index 0a43582168a8..31fb62debdc7 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> @@ -24,11 +24,14 @@ description:
>  
>    The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
>    forward direction and 187.5Mbps in the reverse direction.
> +
>    MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
> +  MAX9295A only supports pixel mode.
>  
>  properties:
>    compatible:
>      oneOf:
> +      - const: maxim,max9295a
>        - const: maxim,max96717f

Make these 2 a single 'enum'.

>        - items:
>            - enum:
> -- 
> 2.48.1
> 


From robh at kernel.org  Tue Mar 11 11:30:53 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 13:30:53 -0500
Subject: [RFC PATCH v2 06/16] dt-bindings: media: i2c: max96717: add
 support for MAX96793
In-Reply-To: <20250309084814.3114794-7-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-7-demonsingur@gmail.com>
Message-ID: <174171785257.3942045.11201403719435330786.robh@kernel.org>


On Sun, 09 Mar 2025 10:47:58 +0200, Cosmin Tanislav wrote:
> MAX96793 is a newer variant of the MAX96717 which also supports GMSL3
> links.
> 
> Document this compatibility.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From konstantin at linuxfoundation.org  Tue Mar 11 11:34:56 2025
From: konstantin at linuxfoundation.org (Konstantin Ryabitsev)
Date: Tue, 11 Mar 2025 14:34:56 -0400
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <D8CQAAKOZ1O5.8JVESQPJSSM8@bootlin.com>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
 <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
 <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>
 <cd2f3c97-53bb-42f5-a3cd-4385bfda5dc7@kernel.org>
 <D8CQAAKOZ1O5.8JVESQPJSSM8@bootlin.com>
Message-ID: <20250311-omniscient-fiery-bison-8e7feb@lemur>

On Mon, Mar 10, 2025 at 05:31:32PM +0100, Antonin Godard wrote:
> > And now I noticed you used b4, so I really do not get how the tags can
> > be missing here. :/
> 
> Sorry, that's totally my fault here, I forgot to run 'b4 trailers -u' before
> sending... :/ And I don't think it's part of the prep checks?

Mostly, because there's no clear picture of how this would work reliably. All
other checks are on a "ran since modifications to the series" basis, but this
one would have to be time-based.

Should it check if the trailer updates have been run in the past XX minutes
(and how long should that XX be?).


-K


From ardb at kernel.org  Tue Mar 11 11:35:42 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Tue, 11 Mar 2025 19:35:42 +0100
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early mappings
In-Reply-To: <f6d48d04-fd3c-493e-b7a0-020b912f6f10@arm.com>
References: <20250311073043.96795-2-ardb+git@google.com> <f6d48d04-fd3c-493e-b7a0-020b912f6f10@arm.com>
Message-ID: <CAMj1kXG1jqi9vfTS4wz_a3QPERCUYbHcV6Fq+jf4ZkPtgM5oAg@mail.gmail.com>

On Tue, 11 Mar 2025 at 12:31, Ryan Roberts <ryan.roberts at arm.com> wrote:
>
> On 11/03/2025 07:30, Ard Biesheuvel wrote:
> > From: Ard Biesheuvel <ardb at kernel.org>
> >
> > The page table population code in map_range() uses a recursive algorithm
> > to create the early mappings of the kernel, the DTB and the ID mapped
> > text and data pages, and this fails to take into account that the way
> > these page tables may be constructed is not precisely the same at each
> > level. In particular, block mappings are not permitted at each level,
> > and the code as it exists today might inadvertently create such a
> > forbidden block mapping if it were used to map a region of the
> > appropriate size and alignment.
> >
> > This never happens in practice, given the limited size of the assets
> > being mapped by the early boot code. Nonetheless, it would be better if
> > this code would behave correctly in all circumstances.
> >
> > So only permit block mappings at level 2, and page mappings at level 3,
> > for any page size, and use table mappings exclusively at all other
> > levels. This change should have no impact in practice, but it makes the
> > code more robust.
> >
> > Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> > Reported-by: Ryan Roberts <ryan.roberts at arm.com>
> > Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> > ---
> > v2: take the assignment of protval out of the loop again, so that
> >     clearing a mapping works as expected wrt the PTE_CONT bit
>
> Ouch, totally missed that. Now that I've looked at the code properly, I wonder
> if it is worth supporting CONT_PMD mappings at level 2? That would be 32M for 4K
> pages, so is likely to actaually get used. I think it would just be something like:
>
> u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 :
>            ((level == 2) ? CONT_PMD_SIZE - 1 : U64_MAX) : U64_MAX;
>

With this patch applied, it is guaranteed that cmask is only
referenced if level >= 2, so we can simplify this as

  u64 cmask = (level < 3) ? CONT_PMD_SIZE - 1 : CONT_PTE_SIZE - 1;

(using the level < 3 for consistency with the protval assignment)

> Anyway, probably not worth the complexity for these boot-time tables, so regardless:
>

They are created at boot time but these are not 'boot-time tables' -
they are the ones that are used by the kernel at runtime. So I think
it makes sense to add this.

> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
>

Thanks.


From joro at 8bytes.org  Tue Mar 11 11:42:42 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Tue, 11 Mar 2025 19:42:42 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
Message-ID: <Z9CEIlXoQJ-A0t-d@8bytes.org>

Hi Robin,

On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
> +	/*
> +	 * And if we do now see any replay calls, they would indicate someone
> +	 * misusing the dma_configure path outside bus code.
> +	 */
> +	if (dev->driver)
> +		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");

This warning triggers on my workstation (with an AMD IOMMU), any ideas?

 ------------[ cut here ]------------
 reg-dummy reg-dummy: late IOMMU probe at driver bind, something fishy here!
 WARNING: CPU: 0 PID: 1 at drivers/iommu/iommu.c:449 __iommu_probe_device+0x10b/0x510
 Modules linked in:

 CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc6-iommu-next+ #1 1d691d7aebf343bde741cf4c8610d78a2ea2d2d9
 Hardware name: System manufacturer System Product Name/PRIME X470-PRO, BIOS 5406 11/13/2019
 RIP: 0010:__iommu_probe_device+0x10b/0x510
 Code: 68 00 74 28 48 8b 6b 50 48 85 ed 75 03 48 8b 2b 48 89 df e8 87 71 06 00 48 89 ea 48 c7 c7 90 dd 2c 8b 48 89 c6 e8 35 83 77 ff <0f> 0b 49 8b bd a8 00 00 00 e8 77 ab 85 ff 84 c0 0f 84 ad 01 00 00
 RSP: 0018:ffffafba00047c58 EFLAGS: 00010282
 RAX: 0000000000000000 RBX: ffffa00481301c10 RCX: 0000000000000003
 RDX: 0000000000000000 RSI: 0000000000000003 RDI: 0000000000000001
 RBP: ffffa00480ffaee0 R08: 0000000000000000 R09: ffffafba00047ae8
 R10: ffffa0135e93ffa8 R11: 0000000000000003 R12: ffffafba00047d18
 R13: ffffffff8adac1a0 R14: 0000000000000000 R15: ffffa004802c5800
 FS:  0000000000000000(0000) GS:ffffa0135ea00000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
 CR2: ffffa00baca01000 CR3: 000000082b838000 CR4: 00000000003506f0
 Call Trace:
  <TASK>
  ? __iommu_probe_device+0x10b/0x510
  ? __warn.cold+0x93/0xf7
  ? __iommu_probe_device+0x10b/0x510
  ? report_bug+0xff/0x140
  ? prb_read_valid+0x1b/0x30
  ? handle_bug+0x58/0x90
  ? exc_invalid_op+0x17/0x70
  ? asm_exc_invalid_op+0x1a/0x20
  ? __iommu_probe_device+0x10b/0x510
  ? __iommu_probe_device+0x10b/0x510
  ? __pfx_probe_iommu_group+0x10/0x10
  probe_iommu_group+0x28/0x50
  bus_for_each_dev+0x7e/0xd0
  iommu_device_register+0xee/0x260
  iommu_go_to_state+0xa2a/0x1970
  ? srso_return_thunk+0x5/0x5f
  ? blake2s_update+0x68/0x160
  ? __pfx_pci_iommu_init+0x10/0x10
  amd_iommu_init+0x14/0x50
  ? __pfx_pci_iommu_init+0x10/0x10
  pci_iommu_init+0x12/0x40
  do_one_initcall+0x46/0x300
  kernel_init_freeable+0x23d/0x2a0
  ? __pfx_kernel_init+0x10/0x10
  kernel_init+0x1a/0x140
  ret_from_fork+0x34/0x50
  ? __pfx_kernel_init+0x10/0x10
  ret_from_fork_asm+0x1a/0x30
  </TASK>
 ---[ end trace 0000000000000000 ]---



From alexander.sverdlin at siemens.com  Tue Mar 11 11:49:38 2025
From: alexander.sverdlin at siemens.com (Sverdlin, Alexander)
Date: Tue, 11 Mar 2025 18:49:38 +0000
Subject: [PATCH net v3] net: ethernet: ti: am65-cpsw: Fix NAPI
 registration sequence
In-Reply-To: <20250311154259.102865-1-s-vadapalli@ti.com>
References: <20250311154259.102865-1-s-vadapalli@ti.com>
Message-ID: <3f6b99966ff7ad119d087e65f0f58e5b1411066f.camel@siemens.com>

Thanks Siddharth for reworking the patch!

On Tue, 2025-03-11 at 21:12 +0530, Siddharth Vadapalli wrote:
> From: Vignesh Raghavendra <vigneshr at ti.com>
> 
> Registering the interrupts for TX or RX DMA Channels prior to registering
> their respective NAPI callbacks can result in a NULL pointer dereference.
> This is seen in practice as a random occurrence since it depends on the
> randomness associated with the generation of traffic by Linux and the
> reception of traffic from the wire.
> 
> Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

LGTM,
Reviewed-by: Alexander Sverdlin <alexander.sverdlin at siemens.com>

> ?drivers/net/ethernet/ti/am65-cpsw-nuss.c | 32 +++++++++++++-----------
> ?1 file changed, 18 insertions(+), 14 deletions(-)

-- 
Alexander Sverdlin
Siemens AG
www.siemens.com

From ansuelsmth at gmail.com  Tue Mar 11 11:51:25 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Tue, 11 Mar 2025 19:51:25 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-10-ansuelsmth@gmail.com>
 <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>
Message-ID: <67d0862f.df0a0220.375bd.6b15@mx.google.com>

On Mon, Mar 10, 2025 at 05:34:56PM +0100, Krzysztof Kozlowski wrote:
> On 09/03/2025 14:29, Christian Marangi wrote:
> > Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
> > for the USB controller.
> > 
> > Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> > always supported. The USB 3.0 mode is optional and depends on the Serdes
> > mode currently configured on the system for the USB port. If USB 3.0 node
> > is defined, then airoha,scu-ssr property is required for Serdes mode
> > validation.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
> >  .../bindings/phy/airoha,an7581-usb-phy.yaml   | 106 ++++++++++++++++++
> >  MAINTAINERS                                   |   6 +
> >  2 files changed, 112 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> > new file mode 100644
> > index 000000000000..39127cfb63a7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> > @@ -0,0 +1,106 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Airoha AN7581 SoC USB PHY
> > +
> > +maintainers:
> > +  - Christian Marangi <ansuelsmth at gmail.com>
> > +
> > +description: >
> > +  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
> > +
> > +  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> > +  always supported. The USB 3.0 mode is optional and depends on the Serdes
> > +  mode currently configured on the system for the USB port. If USB 3.0 node
> > +  is defined, then airoha,scu-ssr property is required for Serdes mode
> > +  validation.
> > +
> > +properties:
> > +  compatible:
> > +    const: airoha,an7581-usb-phy
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  airoha,port-id:
> > +    description: Describe the physical port this USB PHY refer to. A dedicated
> > +      osciallator is used for each port for the USB 2.0 Slew Rate calibration.
> 
> typo
> 
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    enum: [0, 1]
> 
> I don't understand why do you need index property here (which are
> usually not allowed).
>

Eh... As said in the description this is really to differentiate the 2
different physical port...

Each port have a dedicated oscillator for calibration and these
calibration are identified by an offset (all placed one after another in
a separate register space).

Oscillator 0 for physical port 0
Oscillator 1 for physcial port 1

And model this is a bit problematic without an additional property, any
hint for this?

> > +
> > +  airoha,scu-ssr:
> > +    description: Phandle to the SCU SSR node for USB 3.0 Serdes mode validation.
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +
> > +  usb2-phy:
> > +    type: object
> > +
> > +    properties:
> > +      '#phy-cells':
> > +        const: 1
> > +
> > +    required:
> > +      - '#phy-cells'
> > +
> > +    additionalProperties: false
> 
> Also no resources in usb[23]-phy, so this goes to the parent level and
> you have phy-cells=2. Your DTS gives some hint that devices actually
> differ but the commit msg contradicts it, so I don't get. Do you have
> same IP block here or two different?
> 

SoC have 2 physical USB port.

Physical port 0 on address: 0x1fab0000
Physcial port 1 on address: 0x1fad0000

In those space there are registers to configure USB 2.0 mode and USB 3.0
mode for each physical port.

So yes no child node, phy-cells 2 and reference with phys = <&usb_phy 0
PHY_TYPE_USB2>, <&usb_phy 1 PHY_TYPE_USB3>; that totally works and hope
now the HW is more clear.

The real problematic part is the one above with identify the 2 physical
port.

> > +
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index fe34c80b8d52..c2dd385e9165 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -753,6 +753,12 @@ S:	Maintained
> >  F:	Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
> >  F:	drivers/spi/spi-airoha-snfi.c
> >  
> > +AIROHA USB PHY DRIVER
> > +M:	Christian Marangi <ansuelsmth at gmail.com>
> > +L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > +S:	Maintained
> > +F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yam
> 
> Typo in extension/missing l.
> 
> 
> 
> Best regards,
> Krzysztof

-- 
	Ansuel


From lumag at kernel.org  Tue Mar 11 11:52:52 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Tue, 11 Mar 2025 20:52:52 +0200
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
Message-ID: <vjkdwjudqsgcq2leabscnb2r5dbtztgfq3jlkfowcauslaymkp@qsxnpis3ksp6>

On Tue, Mar 11, 2025 at 07:02:56PM +0100, Christopher Obbard wrote:
> Currently some Qualcomm interconnect drivers are enabled
> as modules which isn't overly useful since the interconnects
> are required to be loaded during early boot.
> 
> Loading the interconnects late (e.g. in initrd or as module)
> can cause boot issues, such as slowdown or even not booting
> at all (since the interconnect would be required for storage
> devices).

This is not a good justification. It should be perfectly fine to load
block drivers (including their dependencies) from the initramfs.

Up to now we have been enabling only those interconnect (and pinctrl,
btw) drivers, which are required to be able to open the consoe (thanks,
systemd).

> 
> Be consistent and enable all of the Qualcomm interconnect
> drivers as built-in to the kernel image.
> 
> Signed-off-by: Christopher Obbard <christopher.obbard at linaro.org>
> ---
>  arch/arm64/configs/defconfig | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 219ef05ee5a757c43a37ec9f8571ce9976354830..6582baee2ab02ecb2ff442c6e73aa6a23fee8d7f 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -1656,11 +1656,11 @@ CONFIG_INTERCONNECT_IMX8MN=m
>  CONFIG_INTERCONNECT_IMX8MQ=m
>  CONFIG_INTERCONNECT_IMX8MP=y
>  CONFIG_INTERCONNECT_QCOM=y
> -CONFIG_INTERCONNECT_QCOM_MSM8916=m
> +CONFIG_INTERCONNECT_QCOM_MSM8916=y
>  CONFIG_INTERCONNECT_QCOM_MSM8996=y
> -CONFIG_INTERCONNECT_QCOM_OSM_L3=m
> +CONFIG_INTERCONNECT_QCOM_OSM_L3=y

This is the memory / L3 / cpufreq interconnect, it has nothing to do
with the block devices.

>  CONFIG_INTERCONNECT_QCOM_QCM2290=y
> -CONFIG_INTERCONNECT_QCOM_QCS404=m
> +CONFIG_INTERCONNECT_QCOM_QCS404=y
>  CONFIG_INTERCONNECT_QCOM_QCS615=y
>  CONFIG_INTERCONNECT_QCOM_QCS8300=y
>  CONFIG_INTERCONNECT_QCOM_QDU1000=y
> 
> ---
> base-commit: b098bcd8278b89cb3eb73fdb6e06dc49af75ad37
> change-id: 20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-258fcc961b11
> 
> Best regards,
> -- 
> Christopher Obbard <christopher.obbard at linaro.org>
> 

-- 
With best wishes
Dmitry


From robh at kernel.org  Tue Mar 11 11:54:21 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 13:54:21 -0500
Subject: [RFC PATCH v2 07/16] dt-bindings: media: i2c: max96712: add
 myself as maintainer
In-Reply-To: <20250309084814.3114794-8-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-8-demonsingur@gmail.com>
Message-ID: <174171926101.3971802.12167410956543937006.robh@kernel.org>


On Sun, 09 Mar 2025 10:47:59 +0200, Cosmin Tanislav wrote:
> Analog Devices is taking responsability for the maintenance of the Maxim
> GMSL2/3 devices.
> Add myself to the maintainers list and to the device tree bindings.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml | 1 +
>  MAINTAINERS                                                     | 1 +
>  2 files changed, 2 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From lumag at kernel.org  Tue Mar 11 11:57:58 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Tue, 11 Mar 2025 20:57:58 +0200
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
Message-ID: <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>

On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
> I sent this patch to start the discussion, some things I found:
> 
> 1) Some interconnects are missing from arm defconfig. Should they be =y too ?

No, unless those are required for the UART console.

> $ grep CONFIG_INTERCONNECT_QCOM arch/arm/configs/qcom_defconfig
> CONFIG_INTERCONNECT_QCOM=y
> CONFIG_INTERCONNECT_QCOM_MSM8974=m
> CONFIG_INTERCONNECT_QCOM_SDX55=m
> 
> 2) Some interconnects are missing from arm64 defconfig (which should
> probably be in there) (I have included just two examples):

I think `git log -S CONFIG_INTERCONNECT_QCOM
arch/arm64/configs/defconfig` will answer this question. The drivers are
enabled on the premises of being required for a particular device, not
because they exist in the Linux kernel.

> $ grep CONFIG_INTERCONNECT drivers/interconnect/qcom/Makefile
> obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
> obj-$(CONFIG_INTERCONNECT_QCOM_SM7150) += qnoc-sm7150.o
> 
> I can handle these in follow-up or v2 of the patchset as follow-up
> commits, please let me know what you'd prefer.
> 
> On Tue, 11 Mar 2025 at 19:03, Christopher Obbard
> <christopher.obbard at linaro.org> wrote:
> >
> > Currently some Qualcomm interconnect drivers are enabled
> > as modules which isn't overly useful since the interconnects
> > are required to be loaded during early boot.
> >
> > Loading the interconnects late (e.g. in initrd or as module)
> > can cause boot issues, such as slowdown or even not booting
> > at all (since the interconnect would be required for storage
> > devices).
> >
> > Be consistent and enable all of the Qualcomm interconnect
> > drivers as built-in to the kernel image.
> >
> > Signed-off-by: Christopher Obbard <christopher.obbard at linaro.org>
> > ---
> >  arch/arm64/configs/defconfig | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index 219ef05ee5a757c43a37ec9f8571ce9976354830..6582baee2ab02ecb2ff442c6e73aa6a23fee8d7f 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -1656,11 +1656,11 @@ CONFIG_INTERCONNECT_IMX8MN=m
> >  CONFIG_INTERCONNECT_IMX8MQ=m
> >  CONFIG_INTERCONNECT_IMX8MP=y
> >  CONFIG_INTERCONNECT_QCOM=y
> > -CONFIG_INTERCONNECT_QCOM_MSM8916=m
> > +CONFIG_INTERCONNECT_QCOM_MSM8916=y
> >  CONFIG_INTERCONNECT_QCOM_MSM8996=y
> > -CONFIG_INTERCONNECT_QCOM_OSM_L3=m
> > +CONFIG_INTERCONNECT_QCOM_OSM_L3=y
> >  CONFIG_INTERCONNECT_QCOM_QCM2290=y
> > -CONFIG_INTERCONNECT_QCOM_QCS404=m
> > +CONFIG_INTERCONNECT_QCOM_QCS404=y
> >  CONFIG_INTERCONNECT_QCOM_QCS615=y
> >  CONFIG_INTERCONNECT_QCOM_QCS8300=y
> >  CONFIG_INTERCONNECT_QCOM_QDU1000=y
> >
> > ---
> > base-commit: b098bcd8278b89cb3eb73fdb6e06dc49af75ad37
> > change-id: 20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-258fcc961b11
> >
> > Best regards,
> > --
> > Christopher Obbard <christopher.obbard at linaro.org>
> >

-- 
With best wishes
Dmitry


From will at kernel.org  Tue Mar 11 11:58:15 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 18:58:15 +0000
Subject: [PATCH v6 0/2] Add support for GPU SMMU on QCS8300
In-Reply-To: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
References: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
Message-ID: <174169911942.2776458.2825521492777245411.b4-ty@kernel.org>

On Mon, 10 Mar 2025 16:48:33 +0530, Pratyush Brahma wrote:
> Enable GPU SMMU function on QCS8300 platform. GPU SMMU is required
> for address translation in GPU device.
> 
> 

Applied SMMU bindings change to iommu (arm/smmu/bindings), thanks!

[1/2] dt-bindings: arm-smmu: Document QCS8300 GPU SMMU
      https://git.kernel.org/iommu/c/df90abbc31e6

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev


From Frank.li at nxp.com  Tue Mar 11 11:59:19 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 11 Mar 2025 14:59:19 -0400
Subject: [PATCH v13 5/5] firmware: drivers: imx: adds miscdev
In-Reply-To: <20250311-imx-se-if-v13-5-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
 <20250311-imx-se-if-v13-5-9cc6d8fd6d1c@nxp.com>
Message-ID: <Z9CIB9P//Tf9Lo5v@lizhi-Precision-Tower-5810>

On Tue, Mar 11, 2025 at 09:09:36PM +0530, Pankaj Gupta wrote:
> Adds the driver for communication interface to secure-enclave,
> for exchanging messages with NXP secure enclave HW IP(s) like
> EdgeLock Enclave from:
> - User-Space Applications via character driver.
>
> ABI documentation for the NXP secure-enclave driver.
>
> User-space library using this driver:
> - i.MX Secure Enclave library:
>   -- URL: https://github.com/nxp-imx/imx-secure-enclave.git,
> - i.MX Secure Middle-Ware:
>   -- URL: https://github.com/nxp-imx/imx-smw.git
>
> Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
> ---
>  Documentation/ABI/testing/se-cdev   |  43 ++
>  drivers/firmware/imx/ele_base_msg.c |  11 +-
>  drivers/firmware/imx/ele_common.c   |  77 +++-
>  drivers/firmware/imx/ele_common.h   |  10 +-
>  drivers/firmware/imx/se_ctrl.c      | 775 +++++++++++++++++++++++++++++++++++-
>  drivers/firmware/imx/se_ctrl.h      |  43 ++
>  include/uapi/linux/se_ioctl.h       | 101 +++++
>  7 files changed, 1029 insertions(+), 31 deletions(-)
>
> diff --git a/Documentation/ABI/testing/se-cdev b/Documentation/ABI/testing/se-cdev
> new file mode 100644
> index 000000000000..dad39ffd245a
> --- /dev/null
> +++ b/Documentation/ABI/testing/se-cdev
> @@ -0,0 +1,43 @@
> +What:		/dev/<se>_mu[0-9]+_ch[0-9]+
> +Date:		Mar 2025
> +KernelVersion:	6.8
> +Contact:	linux-imx at nxp.com, pankaj.gupta at nxp.com
> +Description:
> +		NXP offers multiple hardware IP(s) for secure enclaves like EdgeLock-
> +		Enclave(ELE), SECO. The character device file descriptors
> +		/dev/<se>_mu*_ch* are the interface between userspace NXP's secure-
> +		enclave shared library and the kernel driver.
> +
> +		The ioctl(2)-based ABI is defined and documented in
> +		[include]<linux/firmware/imx/ele_mu_ioctl.h>.
> +		ioctl(s) are used primarily for:
> +			- shared memory management
> +			- allocation of I/O buffers
> +			- getting mu info
> +			- setting a dev-ctx as receiver to receive all the commands from FW
> +			- getting SoC info
> +			- send command and receive command response
> +
> +		The following file operations are supported:
> +
> +		open(2)
> +		  Currently the only useful flags are O_RDWR.
> +
> +		read(2)
> +		  Every read() from the opened character device context is waiting on
> +		  wait_event_interruptible, that gets set by the registered mailbox callback
> +		  function, indicating a message received from the firmware on message-
> +		  unit.
> +
> +		write(2)
> +		  Every write() to the opened character device context needs to acquire
> +		  mailbox_lock before sending message on to the message unit.
> +
> +		close(2)
> +		  Stops and frees up the I/O contexts that were associated
> +		  with the file descriptor.
> +
> +Users:		https://github.com/nxp-imx/imx-secure-enclave.git,
> +		https://github.com/nxp-imx/imx-smw.git
> +		crypto/skcipher,
> +		drivers/nvmem/imx-ocotp-ele.c
> diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
> index eea86f50d276..ed70728f5418 100644
> --- a/drivers/firmware/imx/ele_base_msg.c
> +++ b/drivers/firmware/imx/ele_base_msg.c
> @@ -62,7 +62,7 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
>  	tx_msg->data[0] = upper_32_bits(get_info_addr);
>  	tx_msg->data[1] = lower_32_bits(get_info_addr);
>  	tx_msg->data[2] = sizeof(*s_info);
> -	ret = ele_msg_send_rcv(priv,
> +	ret = ele_msg_send_rcv(priv->priv_dev_ctx,

Use seperate patch to change this trivial update to reduce review efforts.

>  			       tx_msg,
>  			       ELE_GET_INFO_REQ_MSG_SZ,
>  			       rx_msg,
> @@ -128,7 +128,7 @@ int ele_ping(struct se_if_priv *priv)
>  		return ret;
>  	}
>
> -	ret = ele_msg_send_rcv(priv,
> +	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
>  			       tx_msg,
>  			       ELE_PING_REQ_SZ,
>  			       rx_msg,
> @@ -177,7 +177,8 @@ int ele_service_swap(struct se_if_priv *priv,
>  	tx_msg->data[3] = lower_32_bits(addr);
>  	tx_msg->data[4] = se_add_msg_crc((uint32_t *)&tx_msg[0],
>  					 ELE_SERVICE_SWAP_REQ_MSG_SZ);
> -	ret = ele_msg_send_rcv(priv,
> +
> +	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
>  			       tx_msg,
>  			       ELE_SERVICE_SWAP_REQ_MSG_SZ,
>  			       rx_msg,
> @@ -230,7 +231,7 @@ int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr)
>  	tx_msg->data[0] = lower_32_bits(addr);
>  	tx_msg->data[2] = addr;
>
> -	ret = ele_msg_send_rcv(priv,
> +	ret = ele_msg_send_rcv(priv->priv_dev_ctx,
>  			       tx_msg,
>  			       ELE_FW_AUTH_REQ_SZ,
>  			       rx_msg,
> @@ -284,7 +285,7 @@ int ele_debug_dump(struct se_if_priv *priv)
>  		fmt_str_idx = 0;
>  		memset(rx_msg, 0xCC, ELE_DEBUG_DUMP_RSP_SZ);
>
> -		ret = ele_msg_send_rcv(priv,
> +		ret = ele_msg_send_rcv(priv->priv_dev_ctx,
>  				       tx_msg,
>  				       ELE_DEBUG_DUMP_REQ_SZ,
>  				       rx_msg,
> diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
> index 3fa8182b302f..d63346239936 100644
> --- a/drivers/firmware/imx/ele_common.c
> +++ b/drivers/firmware/imx/ele_common.c
> @@ -6,6 +6,8 @@
>  #include "ele_base_msg.h"
>  #include "ele_common.h"
>
> +u32 se_rcv_msg_timeout = SE_RCV_MSG_DEFAULT_TIMEOUT;
> +
>  u32 se_add_msg_crc(u32 *msg, u32 msg_len)
>  {
>  	u32 nb_words = msg_len / (u32)sizeof(u32);
> @@ -18,33 +20,57 @@ u32 se_add_msg_crc(u32 *msg, u32 msg_len)
>  	return crc;
>  }
>
> -int ele_msg_rcv(struct se_if_priv *priv,
> +void set_se_rcv_msg_timeout(u32 val)
> +{
> +	se_rcv_msg_timeout = val;

Do you intent to use the same timeout value for all instance?


> +}
> +
> +int ele_msg_rcv(struct se_if_device_ctx *dev_ctx,
>  		struct se_clbk_handle *se_clbk_hdl)
>  {
> -	int err = 0;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	bool wait_timeout_enabled = true;
> +	unsigned int wait;
> +	int err;
>
>  	do {
> -		err = wait_for_completion_interruptible(&se_clbk_hdl->done);
> +		if (priv->cmd_receiver_clbk_hdl.dev_ctx == dev_ctx) {
> +			/* NVM-D, SE-FW slave waits indefinitly. */
> +			wait_timeout_enabled = false;
> +			err = wait_for_completion_interruptible(&se_clbk_hdl->done);
> +		} else {
> +			/* FW must send message-response in a finite time. */
> +			wait = msecs_to_jiffies(se_rcv_msg_timeout);
> +			err = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done, wait);
> +		}


wait = priv->cmd_receiver_clbk_hdl.dev_ctx == dev_ctx ?
	MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(se_rcv_msg_timeout);

left = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done, wait);

>  		if (err == -ERESTARTSYS) {
> -			if (priv->waiting_rsp_clbk_hdl.rx_msg) {
> +			if (priv->waiting_rsp_clbk_hdl.dev_ctx) {
>  				priv->waiting_rsp_clbk_hdl.signal_rcvd = true;
>  				continue;
>  			}
> -			dev_err(priv->dev,
> -				"Err[0x%x]:Interrupted by signal.\n",
> -				err);
>  			err = -EINTR;
>  			break;
>  		}
> -	} while (err != 0);
> +		if (err == 0) {
> +			if (wait_timeout_enabled) {
> +				err = -ETIMEDOUT;
> +				dev_err(priv->dev,
> +					"Fatal Error: SE interface: %s%d, hangs indefinitely.\n",
> +					get_se_if_name(priv->if_defs->se_if_type),
> +					priv->if_defs->se_instance_id);

simple logic use left;

> +			}
> +			break;
> +		}
> +	} while (err < 0);
>
> -	return err ? err : se_clbk_hdl->rx_msg_sz;
> +	return (err >= 0) ? se_clbk_hdl->rx_msg_sz : err;

needn't ()

>  }
>
> -int ele_msg_send(struct se_if_priv *priv,
> +int ele_msg_send(struct se_if_device_ctx *dev_ctx,
>  		 void *tx_msg,
>  		 int tx_msg_sz)
>  {
> +	struct se_if_priv *priv = dev_ctx->priv;
>  	struct se_msg_hdr *header;
>  	int err;
>
> @@ -56,7 +82,8 @@ int ele_msg_send(struct se_if_priv *priv,
>  	 */
>  	if (header->size << 2 != tx_msg_sz) {
>  		dev_err(priv->dev,
> -			"User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
> +			"%s: User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
> +			dev_ctx->devname,

put this change to seperated patch, which include below change.
	-     ret = ele_msg_send_rcv(priv,
	+     ret = ele_msg_send_rcv(priv->priv_dev_ctx,

>  			*(u32 *)header,
>  			header->size << 2, tx_msg_sz);
>  		return -EINVAL;
> @@ -64,7 +91,9 @@ int ele_msg_send(struct se_if_priv *priv,
>
>  	err = mbox_send_message(priv->tx_chan, tx_msg);
>  	if (err < 0) {
> -		dev_err(priv->dev, "Error: mbox_send_message failure.\n");
> +		dev_err(priv->dev,
> +			"%s: Error: mbox_send_message failure.",
> +			dev_ctx->devname);
>  		return err;
>  	}
>  	err = tx_msg_sz;
> @@ -73,32 +102,36 @@ int ele_msg_send(struct se_if_priv *priv,
>  }
>
>  /* API used for send/receive blocking call. */
> -int ele_msg_send_rcv(struct se_if_priv *priv,
> +int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx,
>  		     void *tx_msg,
>  		     int tx_msg_sz,
>  		     void *rx_msg,
>  		     int exp_rx_msg_sz)
>  {
>  	int err;
> +	struct se_if_priv *priv = dev_ctx->priv;
>
>  	guard(mutex)(&priv->se_if_cmd_lock);
>
> +	priv->waiting_rsp_clbk_hdl.dev_ctx = dev_ctx;
>  	priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
>  	priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
>
> -	err = ele_msg_send(priv, tx_msg, tx_msg_sz);
> +	err = ele_msg_send(dev_ctx, tx_msg, tx_msg_sz);
>  	if (err < 0)
>  		return err;
>
> -	err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl);
> +	err = ele_msg_rcv(dev_ctx, &priv->waiting_rsp_clbk_hdl);
>
>  	if (priv->waiting_rsp_clbk_hdl.signal_rcvd) {
>  		err = -EINTR;
>  		priv->waiting_rsp_clbk_hdl.signal_rcvd = false;
>  		dev_err(priv->dev,
> -			"Err[0x%x]:Interrupted by signal.\n",
> +			"%s: Err[0x%x]:Interrupted by signal.\n",
> +			dev_ctx->devname,
>  			err);
>  	}
> +	priv->waiting_rsp_clbk_hdl.dev_ctx = NULL;
>
>  	return err;
>  }
> @@ -144,7 +177,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
>  	if (header->tag == priv->if_defs->cmd_tag) {
>  		se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
>  		dev_dbg(dev,
> -			"Selecting cmd receiver for mesg header:0x%x.",
> +			"Selecting cmd receiver:%s for mesg header:0x%x.",
> +			se_clbk_hdl->dev_ctx->devname,
>  			*(u32 *)header);
>
>  		/* Pre-allocated buffer of MAX_NVM_MSG_LEN
> @@ -153,7 +187,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
>  		 */
>  		if (rx_msg_sz > MAX_NVM_MSG_LEN) {
>  			dev_err(dev,
> -				"CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
> +				"%s: CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
> +				se_clbk_hdl->dev_ctx->devname,
>  				*(u32 *)header,
>  				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
>
> @@ -164,13 +199,15 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
>  	} else if (header->tag == priv->if_defs->rsp_tag) {
>  		se_clbk_hdl = &priv->waiting_rsp_clbk_hdl;
>  		dev_dbg(dev,
> -			"Selecting resp waiter for mesg header:0x%x.",
> +			"Selecting resp waiter:%s for mesg header:0x%x.",
> +			se_clbk_hdl->dev_ctx->devname,
>  			*(u32 *)header);
>
>  		if (rx_msg_sz != se_clbk_hdl->rx_msg_sz &&
>  		    !exception_for_size(priv, header)) {
>  			dev_err(dev,
> -				"Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
> +				"%s: Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
> +				se_clbk_hdl->dev_ctx->devname,
>  				*(u32 *)header,
>  				rx_msg_sz, se_clbk_hdl->rx_msg_sz);
>
> diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
> index aceb8c891ae6..3cf124f41487 100644
> --- a/drivers/firmware/imx/ele_common.h
> +++ b/drivers/firmware/imx/ele_common.h
> @@ -12,13 +12,17 @@
>
>  #define IMX_ELE_FW_DIR                 "imx/ele/"
>
> +#define SE_RCV_MSG_DEFAULT_TIMEOUT	5000
> +#define SE_RCV_MSG_LONG_TIMEOUT		5000000
> +void set_se_rcv_msg_timeout(u32 val);
> +
>  u32 se_add_msg_crc(u32 *msg, u32 msg_len);
> -int ele_msg_rcv(struct se_if_priv *priv,
> +int ele_msg_rcv(struct se_if_device_ctx *dev_ctx,
>  		struct se_clbk_handle *se_clbk_hdl);
> -int ele_msg_send(struct se_if_priv *priv,
> +int ele_msg_send(struct se_if_device_ctx *dev_ctx,
>  		 void *tx_msg,
>  		 int tx_msg_sz);
> -int ele_msg_send_rcv(struct se_if_priv *priv,
> +int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx,
>  		     void *tx_msg,
>  		     int tx_msg_sz,
>  		     void *rx_msg,
> diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
> index 12a1ceb87866..f31d97045b89 100644
> --- a/drivers/firmware/imx/se_ctrl.c
> +++ b/drivers/firmware/imx/se_ctrl.c
> @@ -23,6 +23,7 @@
>  #include <linux/slab.h>
>  #include <linux/string.h>
>  #include <linux/sys_soc.h>
> +#include <uapi/linux/se_ioctl.h>
>
>  #include "ele_base_msg.h"
>  #include "ele_common.h"
> @@ -31,8 +32,6 @@
>  #define MAX_SOC_INFO_DATA_SZ		256
>  #define MBOX_TX_NAME			"tx"
>  #define MBOX_RX_NAME			"rx"
> -#define SE_TYPE_STR_HSM			"hsm"
> -#define SE_TYPE_ID_HSM			0x2
>
>  struct se_fw_img_name {
>  	const u8 *prim_fw_nm_in_rfs;
> @@ -140,6 +139,24 @@ static const struct of_device_id se_match[] = {
>  	{},
>  };
>
> +char *get_se_if_name(u8 se_if_id)
> +{
> +	switch (se_if_id) {
> +	case SE_TYPE_ID_DBG: return SE_TYPE_STR_DBG;
> +	case SE_TYPE_ID_HSM: return SE_TYPE_STR_HSM;
> +	}
> +
> +	return NULL;
> +}
> +
> +static uint32_t get_se_soc_id(struct se_if_priv *priv)
> +{
> +	const struct se_soc_info *se_info =
> +				device_get_match_data(priv->dev);
> +
> +	return se_info->soc_id;
> +}
> +
>  static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv)
>  {
>  	return &var_se_info.load_fw;
> @@ -286,6 +303,742 @@ static int se_load_firmware(struct se_if_priv *priv)
>  	return ret;
>  }
>
> +static int init_se_shared_mem(struct se_if_device_ctx *dev_ctx)
> +{
> +	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +
> +	INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_out);
> +	INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_in);
> +
> +	/*
> +	 * Allocate some memory for data exchanges with S40x.
> +	 * This will be used for data not requiring secure memory.
> +	 */
> +	se_shared_mem_mgmt->non_secure_mem.ptr =
> +			dma_alloc_coherent(priv->dev,
> +					   MAX_DATA_SIZE_PER_USER,
> +					   &se_shared_mem_mgmt->non_secure_mem.dma_addr,
> +					   GFP_KERNEL);
> +	if (!se_shared_mem_mgmt->non_secure_mem.ptr)
> +		return -ENOMEM;
> +
> +	se_shared_mem_mgmt->non_secure_mem.size = MAX_DATA_SIZE_PER_USER;
> +	se_shared_mem_mgmt->non_secure_mem.pos = 0;
> +
> +	return 0;
> +}
> +
> +static void cleanup_se_shared_mem(struct se_if_device_ctx *dev_ctx)
> +{
> +	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +
> +	/* Unmap secure memory shared buffer. */
> +	if (se_shared_mem_mgmt->secure_mem.ptr)
> +		devm_iounmap(priv->dev,
> +			     (void __iomem *)se_shared_mem_mgmt->secure_mem.ptr);
> +
> +	se_shared_mem_mgmt->secure_mem.ptr = NULL;
> +	se_shared_mem_mgmt->secure_mem.dma_addr = 0;
> +	se_shared_mem_mgmt->secure_mem.size = 0;
> +	se_shared_mem_mgmt->secure_mem.pos = 0;

where init secure_mem? not symetric with init_se_shared_mem()

> +
> +	/* Free non-secure shared buffer. */
> +	dma_free_coherent(priv->dev, MAX_DATA_SIZE_PER_USER,
> +			  se_shared_mem_mgmt->non_secure_mem.ptr,
> +			  se_shared_mem_mgmt->non_secure_mem.dma_addr);
> +
> +	se_shared_mem_mgmt->non_secure_mem.ptr = NULL;
> +	se_shared_mem_mgmt->non_secure_mem.dma_addr = 0;
> +	se_shared_mem_mgmt->non_secure_mem.size = 0;
> +	se_shared_mem_mgmt->non_secure_mem.pos = 0;
> +}
> +
> +/* Need to copy the output data to user-device context.
> + */
> +static int se_dev_ctx_cpy_out_data(struct se_if_device_ctx *dev_ctx)
> +{
> +	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	struct se_buf_desc *b_desc, *temp;
> +	bool do_cpy = true;
> +
> +	list_for_each_entry_safe(b_desc, temp, &se_shared_mem_mgmt->pending_out, link) {

Why not need lock here?

> +		if (b_desc->usr_buf_ptr && b_desc->shared_buf_ptr && do_cpy) {
> +			dev_dbg(priv->dev,
> +				"Copying output data to user.");
> +			if (do_cpy && copy_to_user(b_desc->usr_buf_ptr,
> +						   b_desc->shared_buf_ptr,
> +						   b_desc->size)) {
> +				dev_err(priv->dev,
> +					"Failure copying output data to user.");
> +				do_cpy = false;

return -EFAULT ? So needn't do_cpy.
missed  list_del(&b_desc->link) and kfree() for copy_to_user fail case.

> +			}
> +		}
> +
> +		if (b_desc->shared_buf_ptr)
> +			memset(b_desc->shared_buf_ptr, 0, b_desc->size);
> +
> +		list_del(&b_desc->link);
> +		kfree(b_desc);
> +	}
> +
> +	return do_cpy ? 0 : -EFAULT;
> +}
> +
> +/*
> + * Clean the used Shared Memory space,
> + * whether its Input Data copied from user buffers, or
> + * Data received from FW.
> + */
> +static void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx)
> +{
> +	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
> +	struct list_head *pending_lists[] = {&se_shared_mem_mgmt->pending_in,
> +						&se_shared_mem_mgmt->pending_out};
> +	struct se_buf_desc *b_desc, *temp;
> +	int i;
> +
> +	for (i = 0; i < 2; i++) {
> +		list_for_each_entry_safe(b_desc, temp,
> +					 pending_lists[i], link) {
> +			if (b_desc->shared_buf_ptr)
> +				memset(b_desc->shared_buf_ptr, 0, b_desc->size);
> +
> +			list_del(&b_desc->link);
> +			kfree(b_desc);
> +		}
> +	}
> +	se_shared_mem_mgmt->secure_mem.pos = 0;
> +	se_shared_mem_mgmt->non_secure_mem.pos = 0;
> +}
> +
> +static int add_b_desc_to_pending_list(void *shared_ptr_with_pos,
> +				      struct se_ioctl_setup_iobuf *io,
> +				      struct se_if_device_ctx *dev_ctx)
> +{
> +	struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
> +	struct se_buf_desc *b_desc = NULL;
> +
> +	b_desc = kzalloc(sizeof(*b_desc), GFP_KERNEL);
> +	if (!b_desc)
> +		return -ENOMEM;
> +
> +	b_desc->shared_buf_ptr = shared_ptr_with_pos;
> +	b_desc->usr_buf_ptr = io->user_buf;
> +	b_desc->size = io->length;
> +
> +	if (io->flags & SE_IO_BUF_FLAGS_IS_INPUT) {
> +		/*
> +		 * buffer is input:
> +		 * add an entry in the "pending input buffers" list so
> +		 * that copied data can be cleaned from shared memory
> +		 * later.
> +		 */
> +		list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_in);

Are you sure needn't lock for link?

> +	} else {
> +		/*
> +		 * buffer is output:
> +		 * add an entry in the "pending out buffers" list so data
> +		 * can be copied to user space when receiving Secure-Enclave
> +		 * response.
> +		 */
> +		list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_out);
> +	}
> +
> +	return 0;
> +}
> +
> +/* interface for managed res to unregister a character device */
> +static void if_misc_deregister(void *miscdevice)
> +{
> +	misc_deregister(miscdevice);
> +}
> +
> +static int init_device_context(struct se_if_priv *priv, int ch_id,
> +			       struct se_if_device_ctx **new_dev_ctx,
> +			       const struct file_operations *se_if_fops)
> +{
> +	struct se_if_device_ctx *dev_ctx;
> +	int ret = 0;
> +
> +	if (ch_id)
> +		dev_ctx = kzalloc(sizeof(*dev_ctx), GFP_KERNEL);
> +	else
> +		dev_ctx = devm_kzalloc(priv->dev, sizeof(*dev_ctx), GFP_KERNEL);

why need distinguish it?

> +
> +	if (!dev_ctx)
> +		return -ENOMEM;
> +
> +	dev_ctx->priv = priv;
> +
> +	if (ch_id)
> +		dev_ctx->devname = kasprintf(GFP_KERNEL, "%s%d_ch%d",
> +					     get_se_if_name(priv->if_defs->se_if_type),
> +					     priv->if_defs->se_instance_id,
> +					     ch_id);
> +	else
> +		dev_ctx->devname = devm_kasprintf(priv->dev, GFP_KERNEL, "%s%d_ch%d",
> +						  get_se_if_name(priv->if_defs->se_if_type),
> +						  priv->if_defs->se_instance_id,
> +						  ch_id);

the same here.


> +	if (!dev_ctx->devname) {
> +		if (ch_id)
> +			kfree(dev_ctx);
> +
> +		return -ENOMEM;
> +	}
> +
> +	mutex_init(&dev_ctx->fops_lock);
> +
> +	*new_dev_ctx = dev_ctx;
> +
> +	if (ch_id) {
> +		list_add_tail(&dev_ctx->link, &priv->dev_ctx_list);
> +		priv->active_devctx_count++;
> +
> +		ret = init_se_shared_mem(dev_ctx);
> +		if (ret < 0) {
> +			kfree(dev_ctx->devname);
> +			kfree(dev_ctx);
> +			*new_dev_ctx = NULL;
> +			return ret;
> +		}
> +
> +		return ret;
> +	}
> +
> +	/* Only for ch_id = 0:
> +	 * - register the misc device.
> +	 * - add action
> +	 */
> +	dev_ctx->miscdev = devm_kzalloc(priv->dev, sizeof(*dev_ctx->miscdev), GFP_KERNEL);
> +	if (!dev_ctx->miscdev) {
> +		*new_dev_ctx = NULL;
> +		return -ENOMEM;
> +	}
> +
> +	dev_ctx->miscdev->name = dev_ctx->devname;
> +	dev_ctx->miscdev->minor = MISC_DYNAMIC_MINOR;
> +	dev_ctx->miscdev->fops = se_if_fops;
> +	dev_ctx->miscdev->parent = priv->dev;
> +	ret = misc_register(dev_ctx->miscdev);
> +	if (ret) {
> +		dev_err(priv->dev, "failed to register misc device %d\n",
> +			ret);
> +		return ret;

return dev_err_probe();

> +	}
> +
> +	ret = devm_add_action(priv->dev, if_misc_deregister,
> +			      dev_ctx->miscdev);
> +	if (ret) {
> +		dev_err(priv->dev,
> +			"failed[%d] to add action to the misc-dev\n",
> +			ret);
> +		misc_deregister(dev_ctx->miscdev);

devm_add_action_or_reset();

> +	}
> +
> +	return ret;
> +}
> +
> +static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
> +					    u64 arg)
> +{
> +	struct se_ioctl_cmd_snd_rcv_rsp_info cmd_snd_rcv_rsp_info = {0};
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_api_msg *rx_msg __free(kfree) = NULL;
> +	int err = 0;
> +
> +	if (copy_from_user(&cmd_snd_rcv_rsp_info, (u8 __user *)arg,
> +			   sizeof(cmd_snd_rcv_rsp_info))) {
> +		dev_err(priv->dev,
> +			"%s: Failed to copy cmd_snd_rcv_rsp_info from user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +		goto exit;
> +	}
> +
> +	if (cmd_snd_rcv_rsp_info.tx_buf_sz < SE_MU_HDR_SZ) {
> +		dev_err(priv->dev,
> +			"%s: User buffer too small(%d < %d)\n",
> +			dev_ctx->devname,
> +			cmd_snd_rcv_rsp_info.tx_buf_sz,
> +			SE_MU_HDR_SZ);
> +		err = -ENOSPC;
> +		goto exit;
> +	}
> +
> +	rx_msg = kzalloc(cmd_snd_rcv_rsp_info.rx_buf_sz, GFP_KERNEL);
> +	if (!rx_msg) {
> +		err = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	tx_msg = memdup_user(cmd_snd_rcv_rsp_info.tx_buf,
> +			     cmd_snd_rcv_rsp_info.tx_buf_sz);
> +	if (IS_ERR(tx_msg)) {
> +		err = PTR_ERR(tx_msg);
> +		goto exit;
> +	}
> +
> +	if (tx_msg->header.tag != priv->if_defs->cmd_tag) {
> +		err = -EINVAL;
> +		goto exit;
> +	}
> +
> +	if (tx_msg->header.ver == priv->if_defs->fw_api_ver &&
> +	    !get_load_fw_instance(priv)->is_fw_loaded) {
> +		err = se_load_firmware(priv);
> +		if (err) {
> +			dev_err(priv->dev, "Could not send the message as FW is not loaded.");
> +			err = -EPERM;
> +			goto exit;
> +		}
> +	}
> +	set_se_rcv_msg_timeout(SE_RCV_MSG_LONG_TIMEOUT);
> +
> +	err = ele_msg_send_rcv(dev_ctx,
> +			       tx_msg,
> +			       cmd_snd_rcv_rsp_info.tx_buf_sz,
> +			       rx_msg,
> +			       cmd_snd_rcv_rsp_info.rx_buf_sz);
> +	if (err < 0)
> +		goto exit;
> +
> +	dev_dbg(priv->dev,
> +		"%s: %s %s\n",
> +		dev_ctx->devname,
> +		__func__,
> +		"message received, start transmit to user");
> +
> +	/* We may need to copy the output data to user before
> +	 * delivering the completion message.
> +	 */
> +	err = se_dev_ctx_cpy_out_data(dev_ctx);
> +	if (err < 0)
> +		goto exit;
> +
> +	/* Copy data from the buffer */
> +	print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4,
> +			     rx_msg,
> +			     cmd_snd_rcv_rsp_info.rx_buf_sz, false);
> +
> +	if (copy_to_user(cmd_snd_rcv_rsp_info.rx_buf, rx_msg,
> +			 cmd_snd_rcv_rsp_info.rx_buf_sz)) {
> +		dev_err(priv->dev,
> +			"%s: Failed to copy to user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +
> +exit:
> +
> +	/* shared memory is allocated before this IOCTL */
> +	se_dev_ctx_shared_mem_cleanup(dev_ctx);
> +
> +	if (copy_to_user((void __user *)arg, &cmd_snd_rcv_rsp_info,
> +			 sizeof(cmd_snd_rcv_rsp_info))) {
> +		dev_err(priv->dev,
> +			"%s: Failed to copy cmd_snd_rcv_rsp_info from user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +
> +	return err;
> +}
> +
> +static int se_ioctl_get_mu_info(struct se_if_device_ctx *dev_ctx,
> +				u64 arg)
> +{
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	struct se_if_node *if_node;
> +	struct se_ioctl_get_if_info if_info;
> +	int err = 0;
> +
> +	if_node = container_of(priv->if_defs, typeof(*if_node), if_defs);
> +
> +	if_info.se_if_id = 0;
> +	if_info.interrupt_idx = 0;
> +	if_info.tz = 0;
> +	if_info.did = if_node->se_if_did;
> +	if_info.cmd_tag = priv->if_defs->cmd_tag;
> +	if_info.rsp_tag = priv->if_defs->rsp_tag;
> +	if_info.success_tag = priv->if_defs->success_tag;
> +	if_info.base_api_ver = priv->if_defs->base_api_ver;
> +	if_info.fw_api_ver = priv->if_defs->fw_api_ver;
> +
> +	dev_dbg(priv->dev,
> +		"%s: info [se_if_id: %d, irq_idx: %d, tz: 0x%x, did: 0x%x]\n",
> +		dev_ctx->devname,
> +		if_info.se_if_id, if_info.interrupt_idx,
> +		if_info.tz, if_info.did);
> +
> +	if (copy_to_user((u8 __user *)arg, &if_info, sizeof(if_info))) {
> +		dev_err(priv->dev,
> +			"%s: Failed to copy mu info to user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +
> +	return err;
> +}
> +
> +/*
> + * Copy a buffer of data to/from the user and return the address to use in
> + * messages
> + */
> +static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
> +					u64 arg)
> +{
> +	struct se_shared_mem *shared_mem = NULL;
> +	struct se_ioctl_setup_iobuf io = {0};
> +	int err = 0;
> +	u32 pos;
> +
> +	if (copy_from_user(&io, (u8 __user *)arg, sizeof(io))) {
> +		dev_err(dev_ctx->priv->dev,
> +			"%s: Failed copy iobuf config from user\n",
> +			dev_ctx->devname);
> +		return -EFAULT;
> +	}
> +
> +	dev_dbg(dev_ctx->priv->dev,
> +		"%s: io [buf: %p(%d) flag: %x]\n",
> +		dev_ctx->devname,
> +		io.user_buf, io.length, io.flags);
> +
> +	if (io.length == 0 || !io.user_buf) {
> +		/*
> +		 * Accept NULL pointers since some buffers are optional
> +		 * in FW commands. In this case we should return 0 as
> +		 * pointer to be embedded into the message.
> +		 * Skip all data copy part of code below.
> +		 */
> +		io.ele_addr = 0;
> +		goto copy;
> +	}
> +
> +	/* No specific requirement for this buffer. */
> +	shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem;
> +
> +	/* Check there is enough space in the shared memory. */
> +	dev_dbg(dev_ctx->priv->dev,
> +		"%s: req_size = %d, max_size= %d, curr_pos = %d",
> +		dev_ctx->devname,
> +		round_up(io.length, 8u),
> +		shared_mem->size, shared_mem->pos);
> +
> +	if (shared_mem->size < shared_mem->pos ||
> +	    round_up(io.length, 8u) > (shared_mem->size - shared_mem->pos)) {
> +		dev_err(dev_ctx->priv->dev,
> +			"%s: Not enough space in shared memory\n",
> +			dev_ctx->devname);
> +		return -ENOMEM;
> +	}
> +
> +	/* Allocate space in shared memory. 8 bytes aligned. */
> +	pos = shared_mem->pos;
> +	shared_mem->pos += round_up(io.length, 8u);
> +	io.ele_addr = (u64)shared_mem->dma_addr + pos;
> +
> +	memset(shared_mem->ptr + pos, 0, io.length);
> +	if ((io.flags & SE_IO_BUF_FLAGS_IS_INPUT) ||
> +	    (io.flags & SE_IO_BUF_FLAGS_IS_IN_OUT)) {
> +		/*
> +		 * buffer is input:
> +		 * copy data from user space to this allocated buffer.
> +		 */
> +		if (copy_from_user(shared_mem->ptr + pos, io.user_buf,
> +				   io.length)) {
> +			dev_err(dev_ctx->priv->dev,
> +				"%s: Failed copy data to shared memory\n",
> +				dev_ctx->devname);
> +			return -EFAULT;
> +		}
> +	}
> +
> +	err = add_b_desc_to_pending_list(shared_mem->ptr + pos,
> +					 &io,
> +					 dev_ctx);
> +	if (err < 0)
> +		dev_err(dev_ctx->priv->dev,
> +			"%s: Failed to allocate/link b_desc.",
> +			dev_ctx->devname);
> +
> +copy:
> +	/* Provide the EdgeLock Enclave address to user space only if success.*/
> +	if (copy_to_user((u8 __user *)arg, &io, sizeof(io))) {
> +		dev_err(dev_ctx->priv->dev,
> +			"%s: Failed to copy iobuff setup to user.",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +
> +	return err;
> +}
> +
> +/* IOCTL to provide SoC information */
> +static int se_ioctl_get_se_soc_info_handler(struct se_if_device_ctx *dev_ctx,
> +					    u64 arg)
> +{
> +	struct se_ioctl_get_soc_info soc_info;
> +	int err = -EINVAL;
> +
> +	soc_info.soc_id = get_se_soc_id(dev_ctx->priv);
> +	soc_info.soc_rev = var_se_info.soc_rev;
> +
> +	err = (int)copy_to_user((u8 __user *)arg, (u8 *)(&soc_info), sizeof(soc_info));

needn't (int)

> +	if (err) {
> +		dev_err(dev_ctx->priv->dev,
> +			"%s: Failed to copy soc info to user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +
> +	return err;
> +}
> +
> +/*
> + * File operations for user-space
> + */
> +
> +/* Write a message to the MU. */
> +static ssize_t se_if_fops_write(struct file *fp, const char __user *buf,
> +				size_t size, loff_t *ppos)
> +{
> +	struct se_if_device_ctx *dev_ctx = fp->private_data;
> +	struct se_api_msg *tx_msg __free(kfree) = NULL;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	int err;
> +
> +	dev_dbg(priv->dev,
> +		"%s: write from buf (%p)%zu, ppos=%lld\n",
> +		dev_ctx->devname,
> +		buf, size, ((ppos) ? *ppos : 0));
> +
> +	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
> +		return -EBUSY;

you can guard() see mutex.h
DEFINE_GUARD_COND(mutex, _intr, mutex_lock_interruptible(_T) == 0)

> +
> +	if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) {
> +		err = -EINVAL;
> +		goto exit;
> +	}
> +
> +	if (size < SE_MU_HDR_SZ) {
> +		dev_err(priv->dev,
> +			"%s: User buffer too small(%zu < %d)\n",
> +			dev_ctx->devname,
> +			size, SE_MU_HDR_SZ);
> +		err = -ENOSPC;
> +		goto exit;
> +	}
> +
> +	tx_msg = memdup_user(buf, size);
> +	if (IS_ERR(tx_msg)) {
> +		err = PTR_ERR(tx_msg);
> +		goto exit;
> +	}
> +
> +	print_hex_dump_debug("from user ", DUMP_PREFIX_OFFSET, 4, 4,
> +			     tx_msg, size, false);
> +
> +	err = ele_msg_send(dev_ctx, tx_msg, size);
> +
> +exit:
> +	mutex_unlock(&dev_ctx->fops_lock);
> +	return err;
> +}
> +
> +/*
> + * Read a message from the MU.
> + * Blocking until a message is available.
> + */
> +static ssize_t se_if_fops_read(struct file *fp, char __user *buf,
> +			       size_t size, loff_t *ppos)
> +{
> +	struct se_if_device_ctx *dev_ctx = fp->private_data;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	int err;
> +
> +	dev_dbg(priv->dev,
> +		"%s: read to buf %p(%zu), ppos=%lld\n",
> +		dev_ctx->devname,
> +		buf, size, ((ppos) ? *ppos : 0));
> +
> +	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
> +		return -EBUSY;
> +
> +	if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) {
> +		err = -EINVAL;
> +		goto exit;
> +	}
> +
> +	err = ele_msg_rcv(dev_ctx, &priv->cmd_receiver_clbk_hdl);
> +	if (err < 0) {
> +		dev_err(priv->dev,
> +			"%s: Err[0x%x]:Interrupted by signal.\n",
> +			dev_ctx->devname, err);
> +		dev_dbg(priv->dev,
> +			"Current active dev-ctx count = %d.\n",
> +			dev_ctx->priv->active_devctx_count);

You can combine to dev_err();

> +		goto exit;
> +	}
> +
> +	/* We may need to copy the output data to user before
> +	 * delivering the completion message.
> +	 */
> +	err = se_dev_ctx_cpy_out_data(dev_ctx);
> +	if (err < 0)
> +		goto exit;
> +
> +	/* Copy data from the buffer */
> +	print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4,
> +			     priv->cmd_receiver_clbk_hdl.rx_msg,
> +			     priv->cmd_receiver_clbk_hdl.rx_msg_sz,
> +			     false);
> +
> +	if (copy_to_user(buf, priv->cmd_receiver_clbk_hdl.rx_msg,
> +			 priv->cmd_receiver_clbk_hdl.rx_msg_sz)) {
> +		dev_err(priv->dev,
> +			"%s: Failed to copy to user\n",
> +			dev_ctx->devname);
> +		err = -EFAULT;
> +	}
> +	err = priv->cmd_receiver_clbk_hdl.rx_msg_sz;
> +exit:
> +	priv->cmd_receiver_clbk_hdl.rx_msg_sz = 0;
> +
> +	se_dev_ctx_shared_mem_cleanup(dev_ctx);
> +
> +	mutex_unlock(&dev_ctx->fops_lock);
> +	return err;
> +}
> +
> +/* Open a character device. */
> +static int se_if_fops_open(struct inode *nd, struct file *fp)
> +{
> +	struct miscdevice *miscdev = fp->private_data;
> +	struct se_if_priv *priv = dev_get_drvdata(miscdev->parent);
> +	struct se_if_device_ctx *misc_dev_ctx = priv->priv_dev_ctx;
> +	struct se_if_device_ctx *dev_ctx;
> +	int err = 0;
> +
> +	if (mutex_lock_interruptible(&misc_dev_ctx->fops_lock))
> +		return -EBUSY;
> +
> +	priv->dev_ctx_mono_count++;
> +	err = init_device_context(priv,
> +				  priv->dev_ctx_mono_count ?
> +					priv->dev_ctx_mono_count
> +					: priv->dev_ctx_mono_count++,
> +				  &dev_ctx, NULL);
> +	if (err)
> +		dev_err(priv->dev,
> +			"Failed[0x%x] to create device contexts.\n",
> +			err);
> +	else
> +		fp->private_data = dev_ctx;
> +
> +	mutex_unlock(&misc_dev_ctx->fops_lock);
> +	return err;
> +}
> +
> +/* Close a character device. */
> +static int se_if_fops_close(struct inode *nd, struct file *fp)
> +{
> +	struct se_if_device_ctx *dev_ctx = fp->private_data;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +
> +	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
> +		return -EBUSY;
> +
> +	/* check if this device was registered as command receiver. */
> +	if (priv->cmd_receiver_clbk_hdl.dev_ctx == dev_ctx) {
> +		priv->cmd_receiver_clbk_hdl.dev_ctx = NULL;
> +		kfree(priv->cmd_receiver_clbk_hdl.rx_msg);
> +		priv->cmd_receiver_clbk_hdl.rx_msg = NULL;
> +	}
> +
> +	se_dev_ctx_shared_mem_cleanup(dev_ctx);
> +	cleanup_se_shared_mem(dev_ctx);
> +
> +	priv->active_devctx_count--;
> +	list_del(&dev_ctx->link);
> +
> +	mutex_unlock(&dev_ctx->fops_lock);
> +	kfree(dev_ctx->devname);
> +	kfree(dev_ctx);
> +
> +	return 0;
> +}
> +
> +/* IOCTL entry point of a character device */
> +static long se_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
> +{
> +	struct se_if_device_ctx *dev_ctx = fp->private_data;
> +	struct se_if_priv *priv = dev_ctx->priv;
> +	int err;
> +
> +	/* Prevent race during change of device context */
> +	if (mutex_lock_interruptible(&dev_ctx->fops_lock))
> +		return -EBUSY;
> +
> +	switch (cmd) {
> +	case SE_IOCTL_ENABLE_CMD_RCV:
> +		if (!priv->cmd_receiver_clbk_hdl.dev_ctx) {
> +			if (!priv->cmd_receiver_clbk_hdl.rx_msg) {
> +				priv->cmd_receiver_clbk_hdl.rx_msg =
> +						kzalloc(MAX_NVM_MSG_LEN,
> +							GFP_KERNEL);
> +				if (!priv->cmd_receiver_clbk_hdl.rx_msg) {
> +					err = -ENOMEM;
> +					break;
> +				}
> +			}
> +			priv->cmd_receiver_clbk_hdl.rx_msg_sz = MAX_NVM_MSG_LEN;
> +			priv->cmd_receiver_clbk_hdl.dev_ctx = dev_ctx;
> +			err = 0;
> +		} else {
> +			err = -EBUSY;
> +		}
> +		break;
> +	case SE_IOCTL_GET_MU_INFO:
> +		err = se_ioctl_get_mu_info(dev_ctx, arg);
> +		break;
> +	case SE_IOCTL_SETUP_IOBUF:
> +		err = se_ioctl_setup_iobuf_handler(dev_ctx, arg);
> +		break;
> +	case SE_IOCTL_GET_SOC_INFO:
> +		err = se_ioctl_get_se_soc_info_handler(dev_ctx, arg);
> +		break;
> +	case SE_IOCTL_CMD_SEND_RCV_RSP:
> +		err = se_ioctl_cmd_snd_rcv_rsp_handler(dev_ctx, arg);
> +		break;
> +	default:
> +		err = -EINVAL;
> +		dev_dbg(priv->dev,
> +			"%s: IOCTL %.8x not supported\n",
> +			dev_ctx->devname,
> +			cmd);
> +	}
> +
> +	mutex_unlock(&dev_ctx->fops_lock);
> +
> +	return (long)err;
> +}
> +
> +/* Char driver setup */
> +static const struct file_operations se_if_fops = {
> +	.open		= se_if_fops_open,
> +	.owner		= THIS_MODULE,
> +	.release	= se_if_fops_close,
> +	.unlocked_ioctl = se_ioctl,
> +	.read		= se_if_fops_read,
> +	.write		= se_if_fops_write,
> +};
> +
>  /* interface for managed res to free a mailbox channel */
>  static void if_mbox_free_channel(void *mbox_chan)
>  {
> @@ -321,6 +1074,7 @@ static int se_if_request_channel(struct device *dev,
>
>  static void se_if_probe_cleanup(void *plat_dev)
>  {
> +	struct se_if_device_ctx *dev_ctx, *t_dev_ctx;
>  	struct platform_device *pdev = plat_dev;
>  	struct device *dev = &pdev->dev;
>  	struct se_fw_load_info *load_fw;
> @@ -345,6 +1099,13 @@ static void se_if_probe_cleanup(void *plat_dev)
>  		load_fw->imem.buf = NULL;
>  	}
>
> +	if (priv->dev_ctx_mono_count) {
> +		list_for_each_entry_safe(dev_ctx, t_dev_ctx, &priv->dev_ctx_list, link) {
> +			list_del(&dev_ctx->link);
> +			priv->active_devctx_count--;
> +		}
> +	}
> +
>  	/* No need to check, if reserved memory is allocated
>  	 * before calling for its release. Or clearing the
>  	 * un-set bit.
> @@ -410,6 +1171,7 @@ static int se_if_probe(struct platform_device *pdev)
>  					     "Unable to get sram pool = %s.",
>  					     if_node->pool_name);
>  	}
> +	INIT_LIST_HEAD(&priv->dev_ctx_list);
>
>  	if (if_node->reserved_dma_ranges) {
>  		ret = of_reserved_mem_device_init(dev);
> @@ -418,6 +1180,12 @@ static int se_if_probe(struct platform_device *pdev)
>  					    "Failed to init reserved memory region.");
>  	}
>
> +	ret = init_device_context(priv, 0, &priv->priv_dev_ctx, &se_if_fops);
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "Failed[0x%x] to create device contexts.",
> +				     ret);
> +
>  	if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) {
>  		ret = get_se_soc_info(priv, se_info);
>  		if (ret)
> @@ -444,7 +1212,7 @@ static int se_if_probe(struct platform_device *pdev)
>  		}
>  	}
>  	dev_info(dev, "i.MX secure-enclave: %s%d interface to firmware, configured.",
> -		 SE_TYPE_STR_HSM,
> +		 get_se_if_name(priv->if_defs->se_if_type),
>  		 priv->if_defs->se_instance_id);
>
>  	return ret;
> @@ -461,6 +1229,7 @@ static int se_suspend(struct device *dev)
>  	struct se_fw_load_info *load_fw;
>  	int ret = 0;
>
> +	set_se_rcv_msg_timeout(SE_RCV_MSG_DEFAULT_TIMEOUT);
>  	load_fw = get_load_fw_instance(priv);
>
>  	if (load_fw->imem_mgmt)
> diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h
> index 32547bc97ca3..c103563091d5 100644
> --- a/drivers/firmware/imx/se_ctrl.h
> +++ b/drivers/firmware/imx/se_ctrl.h
> @@ -13,6 +13,7 @@
>  #define MAX_FW_LOAD_RETRIES		50
>
>  #define RES_STATUS(x)			FIELD_GET(0x000000ff, x)
> +#define MAX_DATA_SIZE_PER_USER		(65 * 1024)
>  #define MAX_NVM_MSG_LEN			(256)
>  #define MESSAGING_VERSION_6		0x6
>  #define MESSAGING_VERSION_7		0x7
> @@ -20,6 +21,7 @@
>  struct se_clbk_handle {
>  	struct completion done;
>  	bool signal_rcvd;
> +	struct se_if_device_ctx *dev_ctx;
>  	u32 rx_msg_sz;
>  	/* Assignment of the rx_msg buffer to held till the
>  	 * received content as part callback function, is copied.
> @@ -34,6 +36,41 @@ struct se_imem_buf {
>  	u32 state;
>  };
>
> +struct se_buf_desc {
> +	u8 *shared_buf_ptr;
> +	void __user *usr_buf_ptr;
> +	u32 size;
> +	struct list_head link;
> +};
> +
> +struct se_shared_mem {
> +	dma_addr_t dma_addr;
> +	u32 size;
> +	u32 pos;
> +	u8 *ptr;
> +};
> +
> +struct se_shared_mem_mgmt_info {
> +	struct list_head pending_in;
> +	struct list_head pending_out;
> +
> +	struct se_shared_mem secure_mem;
> +	struct se_shared_mem non_secure_mem;
> +};
> +
> +/* Private struct for each char device instance. */
> +struct se_if_device_ctx {
> +	struct se_if_priv *priv;
> +	struct miscdevice *miscdev;
> +	const char *devname;
> +
> +	/* process one file operation at a time. */
> +	struct mutex fops_lock;
> +
> +	struct se_shared_mem_mgmt_info se_shared_mem_mgmt;
> +	struct list_head link;
> +};
> +
>  /* Header of the messages exchange with the EdgeLock Enclave */
>  struct se_msg_hdr {
>  	u8 ver;
> @@ -78,6 +115,12 @@ struct se_if_priv {
>
>  	struct gen_pool *mem_pool;
>  	const struct se_if_defines *if_defs;
> +
> +	struct se_if_device_ctx *priv_dev_ctx;
> +	struct list_head dev_ctx_list;
> +	u32 active_devctx_count;
> +	u32 dev_ctx_mono_count;
>  };
>
> +char *get_se_if_name(u8 se_if_id);
>  #endif
> diff --git a/include/uapi/linux/se_ioctl.h b/include/uapi/linux/se_ioctl.h
> new file mode 100644
> index 000000000000..29a9b1ec5ec3
> --- /dev/null
> +++ b/include/uapi/linux/se_ioctl.h
> @@ -0,0 +1,101 @@
> +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause*/
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef SE_IOCTL_H
> +#define SE_IOCTL_H
> +
> +#include <linux/types.h>
> +
> +#define SE_TYPE_STR_DBG			"dbg"
> +#define SE_TYPE_STR_HSM			"hsm"
> +#define SE_TYPE_ID_UNKWN		0x0
> +#define SE_TYPE_ID_DBG			0x1
> +#define SE_TYPE_ID_HSM			0x2
> +/* IOCTL definitions. */
> +
> +struct se_ioctl_setup_iobuf {
> +	void __user *user_buf;
> +	__u32 length;
> +	__u32 flags;
> +	__u64 ele_addr;
> +};
> +
> +struct se_ioctl_shared_mem_cfg {
> +	__u32 base_offset;
> +	__u32 size;
> +};
> +
> +struct se_ioctl_get_if_info {
> +	__u8 se_if_id;
> +	__u8 interrupt_idx;
> +	__u8 tz;
> +	__u8 did;
> +	__u8 cmd_tag;
> +	__u8 rsp_tag;
> +	__u8 success_tag;
> +	__u8 base_api_ver;
> +	__u8 fw_api_ver;
> +};
> +
> +struct se_ioctl_cmd_snd_rcv_rsp_info {
> +	__u32 __user *tx_buf;
> +	int tx_buf_sz;
> +	__u32 __user *rx_buf;
> +	int rx_buf_sz;
> +};
> +
> +struct se_ioctl_get_soc_info {
> +	__u16 soc_id;
> +	__u16 soc_rev;
> +};

It'd better add pack for these interface.

> +
> +/* IO Buffer Flags */
> +#define SE_IO_BUF_FLAGS_IS_OUTPUT	(0x00u)
> +#define SE_IO_BUF_FLAGS_IS_INPUT	(0x01u)
> +#define SE_IO_BUF_FLAGS_USE_SEC_MEM	(0x02u)
> +#define SE_IO_BUF_FLAGS_USE_SHORT_ADDR	(0x04u)
> +#define SE_IO_BUF_FLAGS_IS_IN_OUT	(0x10u)
> +
> +/* IOCTLS */
> +#define SE_IOCTL			0x0A /* like MISC_MAJOR. */
> +
> +/*
> + * ioctl to designated the current fd as logical-reciever.
> + * This is ioctl is send when the nvm-daemon, a slave to the
> + * firmware is started by the user.
> + */
> +#define SE_IOCTL_ENABLE_CMD_RCV	_IO(SE_IOCTL, 0x01)
> +
> +/*
> + * ioctl to get the buffer allocated from the memory, which is shared
> + * between kernel and FW.
> + * Post allocation, the kernel tagged the allocated memory with:
> + *  Output
> + *  Input
> + *  Input-Output
> + *  Short address
> + *  Secure-memory
> + */
> +#define SE_IOCTL_SETUP_IOBUF	_IOWR(SE_IOCTL, 0x03, \
> +					struct se_ioctl_setup_iobuf)
> +
> +/*
> + * ioctl to get the mu information, that is used to exchange message
> + * with FW, from user-spaced.
> + */
> +#define SE_IOCTL_GET_MU_INFO	_IOR(SE_IOCTL, 0x04, \
> +					struct se_ioctl_get_if_info)
> +/*
> + * ioctl to get SoC Info from user-space.
> + */
> +#define SE_IOCTL_GET_SOC_INFO      _IOR(SE_IOCTL, 0x06, \
> +					struct se_ioctl_get_soc_info)
> +
> +/*
> + * ioctl to send command and receive response from user-space.
> + */
> +#define SE_IOCTL_CMD_SEND_RCV_RSP _IOWR(SE_IOCTL, 0x07, \
> +					struct se_ioctl_cmd_snd_rcv_rsp_info)
> +#endif
>
> --
> 2.43.0
>


From robh at kernel.org  Tue Mar 11 12:00:43 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 14:00:43 -0500
Subject: [RFC PATCH v2 08/16] dt-bindings: media: i2c: max96712: use
 pattern properties for ports
In-Reply-To: <20250309084814.3114794-9-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-9-demonsingur@gmail.com>
Message-ID: <20250311190043.GA3972023-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:48:00AM +0200, Cosmin Tanislav wrote:
> The MAX96712 and MAX96724 support up to 4 separate PHYs, depending on
> the selected PHY configuration. Use patternProperties to document this.
> 
> The input ports are all the same, use patternProperties for them.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96712.yaml    | 29 +++++++------------
>  1 file changed, 10 insertions(+), 19 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
> index efdece2b33b9..bf8c861c836b 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
> @@ -40,27 +40,15 @@ properties:
>    ports:
>      $ref: /schemas/graph.yaml#/properties/ports
>  
> -    properties:
> -      port at 0:
> +    patternProperties:
> +      '^port@[0-3]$':
>          $ref: /schemas/graph.yaml#/properties/port
> -        description: GMSL Input 0
> +        description: GMSL Input port

GMSL Inputs 0-3

Though generally every port needs to be documented. So really, this was 
correct before.

>  
> -      port at 1:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: GMSL Input 1
> -
> -      port at 2:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: GMSL Input 2
> -
> -      port at 3:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: GMSL Input 3
> -
> -      port at 4:
> +      '^port@[4-7]$':
>          $ref: /schemas/graph.yaml#/$defs/port-base
>          unevaluatedProperties: false
> -        description: CSI-2 Output
> +        description: CSI-2 Output port

The input port numbers are 1:1 with Input numbering. I imagine that's 
not the case here, so the relationship of port #s to outputs needs to be 
documented.

>  
>          properties:
>            endpoint:
> @@ -78,8 +66,11 @@ properties:
>                - data-lanes
>                - bus-type
>  
> -    required:
> -      - port at 4
> +    anyOf:
> +      - required: [port at 4]
> +      - required: [port at 5]
> +      - required: [port at 6]
> +      - required: [port at 7]
>  
>  required:
>    - compatible
> -- 
> 2.48.1
> 


From robh at kernel.org  Tue Mar 11 12:01:51 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:01:51 -0500
Subject: [RFC PATCH v2 09/16] dt-bindings: media: i2c: max96712: add
 support for I2C MUX
In-Reply-To: <20250309084814.3114794-10-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-10-demonsingur@gmail.com>
Message-ID: <174171971116.3980957.12739233832407896359.robh@kernel.org>


On Sun, 09 Mar 2025 10:48:01 +0200, Cosmin Tanislav wrote:
> MAX96712 and MAX96724 have more than one GMSL2 link, and each link is
> capable of connecting to a separate serializer. If these serializers
> have the same CFG pins configuration, they will also have the same I2C
> address, causing conflicts unless the deserializer muxes the I2C
> channels. Moreover, the serializers can have the same hardware attached
> to their respective I2C bus.
> 
> The MAX96712 and MAX96724 suppot I2C channel muxing via the GMSL2 link
> to facilitate communication to each of the connected serializers.
> 
> Document this capability.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96712.yaml          | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 11 12:02:47 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:02:47 -0500
Subject: [RFC PATCH v2 10/16] dt-bindings: media: i2c: max96712: add
 support for POC supplies
In-Reply-To: <20250309084814.3114794-11-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-11-demonsingur@gmail.com>
Message-ID: <174171976682.3984722.17562171213323916839.robh@kernel.org>


On Sun, 09 Mar 2025 10:48:02 +0200, Cosmin Tanislav wrote:
> The GMSL links can carry power to the serializer when using coaxial
> cables.
> 
> Document this capability.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../devicetree/bindings/media/i2c/maxim,max96712.yaml         | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From lorenzo at kernel.org  Tue Mar 11 10:44:59 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:44:59 +0100
Subject: [PATCH v2 00/13] wifi: mt76: mt7996: Preliminary work to support
 MLO
Message-ID: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>

This series is the first preliminary work needed to support MLO in
MT7996 driver.

---
Changes in v2:
- Rebase on top of mt76 master branch
- get rid of mt76_sta_common_init utility routine and introduce
  mt7996_sta_state routine
- Link to v1: https://lore.kernel.org/r/20250220-mt7996-mlo-v1-0-34c4abb37158 at kernel.org

---
Lorenzo Bianconi (9):
      wifi: mt76: mt7996: Add chage_vif_links stub
      wifi: mt76: mt7996: Introduce mt7996_sta_link container
      wifi: mt76: mt7996: Add mt7996_sta_link struct in mt7996_vif_link
      wifi: mt76: mt7996: Add vif_cfg_changed callback
      wifi: mt76: mt7996: Add link_info_changed callback
      wifi: mt76: mt7996: Add mt7996_sta_state routine
      wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks
      wifi: mt76: mt7996: Support MLO in mt7996_mac_sta_event()
      wifi: mt76: mt7996: Rely on mt7996_vif_link and mt7996_sta_link in mt7996_mac_twt_teardown_flow signature

Shayne Chen (4):
      wifi: mt76: mt7996: Add mt7996_mac_sta_change_links callback
      wifi: mt76: Check link_conf pointer in mt76_connac_mcu_sta_basic_tlv()
      wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support
      wifi: mt76: mt7996: Rely on mt7996_vif_link in mt7996_mcu_twt_agrt_update signature

 drivers/net/wireless/mediatek/mt76/mac80211.c      |   5 +-
 drivers/net/wireless/mediatek/mt76/mt76.h          |   2 +
 .../net/wireless/mediatek/mt76/mt76_connac_mcu.c   |   2 +-
 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    |  12 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 125 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 527 ++++++++++++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 335 +++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/mmio.c   |   3 -
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  36 +-
 9 files changed, 689 insertions(+), 358 deletions(-)
---
base-commit: 33584256a5f38ffb9e8829d08302a3021f2a8475
change-id: 20250220-mt7996-mlo-95e9fe30a9e0

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From lorenzo at kernel.org  Tue Mar 11 10:45:00 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:00 +0100
Subject: [PATCH v2 01/13] wifi: mt76: mt7996: Add chage_vif_links stub
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-1-31df6972519b@kernel.org>

chage_vif_links callback is required by mac80211.
This is a preliminary patch to introduce MLO support for MT7996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index b01cc7ef47999793f4815e4f3c6650c573f8cb28..c0e7ab9bcae5fcd503c10e1a02508977b6921d17 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1650,6 +1650,14 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 
 #endif
 
+static int
+mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			u16 old_links, u16 new_links,
+			struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+	return 0;
+}
+
 const struct ieee80211_ops mt7996_ops = {
 	.add_chanctx = mt76_add_chanctx,
 	.remove_chanctx = mt76_remove_chanctx,
@@ -1705,4 +1713,5 @@ const struct ieee80211_ops mt7996_ops = {
 	.net_fill_forward_path = mt7996_net_fill_forward_path,
 	.net_setup_tc = mt76_wed_net_setup_tc,
 #endif
+	.change_vif_links = mt7996_change_vif_links,
 };

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:01 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:01 +0100
Subject: [PATCH v2 02/13] wifi: mt76: mt7996: Introduce mt7996_sta_link
 container
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-2-31df6972519b@kernel.org>

Similar to mt7996_vif_link, add mt7996_sta_link structure as driver
representation for sta links. This is a preliminary patch to introduce
MLO support for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    |  12 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 117 +++++++++++-------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 136 +++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |  33 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  10 +-
 5 files changed, 181 insertions(+), 127 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index 7b2bb72b407dac53e520f4220eedc5cc38702acd..d453c2fc97e4fad10a29093b70e2ede8375ee0d8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -617,13 +617,14 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct seq_file *s = data;
 	u8 ac;
 
 	for (ac = 0; ac < 4; ac++) {
 		u32 qlen, ctrl, val;
-		u32 idx = msta->wcid.idx >> 5;
-		u8 offs = msta->wcid.idx & GENMASK(4, 0);
+		u32 idx = msta_link->wcid.idx >> 5;
+		u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
 
 		ctrl = BIT(31) | BIT(11) | (ac << 24);
 		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
@@ -631,11 +632,11 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
 		if (val & BIT(offs))
 			continue;
 
-		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx);
+		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
 		qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
 				      GENMASK(11, 0));
 		seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
-			   sta->addr, msta->wcid.idx,
+			   sta->addr, msta_link->wcid.idx,
 			   msta->vif->deflink.mt76.wmm_idx, ac, qlen);
 	}
 }
@@ -930,6 +931,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
 	struct ieee80211_sta *sta = file->private_data;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct ra_rate phy = {};
 	char buf[100];
 	int ret;
@@ -964,7 +966,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
 		goto out;
 	}
 
-	phy.wlan_idx = cpu_to_le16(msta->wcid.idx);
+	phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
 	phy.gi = cpu_to_le16(gi);
 	phy.ltf = cpu_to_le16(ltf);
 	phy.ldpc = phy.ldpc ? 7 : 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 9dfc8106ebec9b01ffa088bb3f3d1a94266e76b9..754f8e520f52f6abf70daa148bf4289f68b1252b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -55,7 +55,8 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = {
 static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
 					    u16 idx, bool unicast)
 {
-	struct mt7996_sta *sta;
+	struct mt7996_sta_link *msta_link;
+	struct mt7996_sta *msta;
 	struct mt76_wcid *wcid;
 
 	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
@@ -68,11 +69,13 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
 	if (!wcid->sta)
 		return NULL;
 
-	sta = container_of(wcid, struct mt7996_sta, wcid);
-	if (!sta->vif)
+	msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
+	msta = msta_link->sta;
+
+	if (!msta->vif)
 		return NULL;
 
-	return &sta->vif->deflink.sta.wcid;
+	return &msta->vif->deflink.sta.deflink.wcid;
 }
 
 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
@@ -100,6 +103,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		[IEEE80211_AC_VI] = 4,
 		[IEEE80211_AC_VO] = 6
 	};
+	struct mt7996_sta_link *msta_link;
 	struct ieee80211_sta *sta;
 	struct mt7996_sta *msta;
 	u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
@@ -123,25 +127,27 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 			spin_unlock_bh(&dev->mt76.sta_poll_lock);
 			break;
 		}
-		msta = list_first_entry(&sta_poll_list,
-					struct mt7996_sta, wcid.poll_list);
-		list_del_init(&msta->wcid.poll_list);
+		msta_link = list_first_entry(&sta_poll_list,
+					     struct mt7996_sta_link,
+					     wcid.poll_list);
+		msta = msta_link->sta;
+		list_del_init(&msta_link->wcid.poll_list);
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
-		idx = msta->wcid.idx;
+		idx = msta_link->wcid.idx;
 
 		/* refresh peer's airtime reporting */
 		addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
 
 		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-			u32 tx_last = msta->airtime_ac[i];
-			u32 rx_last = msta->airtime_ac[i + 4];
+			u32 tx_last = msta_link->airtime_ac[i];
+			u32 rx_last = msta_link->airtime_ac[i + 4];
 
-			msta->airtime_ac[i] = mt76_rr(dev, addr);
-			msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
+			msta_link->airtime_ac[i] = mt76_rr(dev, addr);
+			msta_link->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
 
-			tx_time[i] = msta->airtime_ac[i] - tx_last;
-			rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
+			tx_time[i] = msta_link->airtime_ac[i] - tx_last;
+			rx_time[i] = msta_link->airtime_ac[i + 4] - rx_last;
 
 			if ((tx_last | rx_last) & BIT(30))
 				clear = true;
@@ -152,10 +158,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		if (clear) {
 			mt7996_mac_wtbl_update(dev, idx,
 					       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-			memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
+			memset(msta_link->airtime_ac, 0,
+			       sizeof(msta_link->airtime_ac));
 		}
 
-		if (!msta->wcid.sta)
+		if (!msta_link->wcid.sta)
 			continue;
 
 		sta = container_of((void *)msta, struct ieee80211_sta,
@@ -181,10 +188,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		rssi[2] = to_rssi(GENMASK(23, 16), val);
 		rssi[3] = to_rssi(GENMASK(31, 14), val);
 
-		msta->ack_signal =
+		msta_link->ack_signal =
 			mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
 
-		ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
+		ewma_avg_signal_add(&msta_link->avg_ack_signal,
+				    -msta_link->ack_signal);
 	}
 
 	rcu_read_unlock();
@@ -194,9 +202,10 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
 			      struct ieee80211_vif *vif, bool enable)
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_sta_link *msta_link = &mvif->deflink.sta.deflink;
 	u32 addr;
 
-	addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->deflink.sta.wcid.idx, 5);
+	addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 5);
 	if (enable)
 		mt76_set(dev, addr, BIT(5));
 	else
@@ -477,8 +486,12 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
 	status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
 
 	if (status->wcid) {
-		msta = container_of(status->wcid, struct mt7996_sta, wcid);
-		mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
+		struct mt7996_sta_link *msta_link;
+
+		msta_link = container_of(status->wcid, struct mt7996_sta_link,
+					 wcid);
+		msta = msta_link->sta;
+		mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
 	}
 
 	status->freq = mphy->chandef.chan->center_freq;
@@ -1040,9 +1053,10 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
 static void
 mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
 {
-	struct mt7996_sta *msta;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
+	struct mt7996_sta_link *msta_link;
+	struct mt7996_sta *msta;
 	u16 fc, tid;
 
 	if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
@@ -1071,7 +1085,9 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
 		return;
 
 	msta = (struct mt7996_sta *)sta->drv_priv;
-	if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
+	msta_link = &msta->deflink;
+
+	if (!test_and_set_bit(tid, &msta_link->wcid.ampdu_state))
 		ieee80211_start_tx_ba_session(sta, tid, 0);
 }
 
@@ -1149,7 +1165,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 		 */
 		info = le32_to_cpu(*cur_info);
 		if (info & MT_TXFREE_INFO_PAIR) {
-			struct mt7996_sta *msta;
+			struct mt7996_sta_link *msta_link;
 			u16 idx;
 
 			idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
@@ -1158,8 +1174,9 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 			if (!sta)
 				continue;
 
-			msta = container_of(wcid, struct mt7996_sta, wcid);
-			mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
+			msta_link = container_of(wcid, struct mt7996_sta_link,
+						 wcid);
+			mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
 			continue;
 		} else if (info & MT_TXFREE_INFO_HEADER) {
 			u32 tx_retries = 0, tx_failed = 0;
@@ -1357,7 +1374,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
 
 static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
 {
-	struct mt7996_sta *msta = NULL;
+	struct mt7996_sta_link *msta_link;
 	struct mt76_wcid *wcid;
 	__le32 *txs_data = data;
 	u16 wcidx;
@@ -1378,14 +1395,13 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
 	if (!wcid)
 		goto out;
 
-	msta = container_of(wcid, struct mt7996_sta, wcid);
-
 	mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
 
 	if (!wcid->sta)
 		goto out;
 
-	mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
+	msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
+	mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
 
 out:
 	rcu_read_unlock();
@@ -2252,6 +2268,7 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
 void mt7996_mac_sta_rc_work(struct work_struct *work)
 {
 	struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
+	struct mt7996_sta_link *msta_link;
 	struct ieee80211_sta *sta;
 	struct ieee80211_vif *vif;
 	struct mt7996_sta *msta;
@@ -2262,12 +2279,15 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 	list_splice_init(&dev->sta_rc_list, &list);
 
 	while (!list_empty(&list)) {
-		msta = list_first_entry(&list, struct mt7996_sta, rc_list);
-		list_del_init(&msta->rc_list);
-		changed = msta->changed;
-		msta->changed = 0;
+		msta_link = list_first_entry(&list, struct mt7996_sta_link,
+					     rc_list);
+		list_del_init(&msta_link->rc_list);
+
+		changed = msta_link->changed;
+		msta_link->changed = 0;
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
+		msta = msta_link->sta;
 		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
 		vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
 
@@ -2551,7 +2571,7 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
 }
 
 static bool
-mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
+mt7996_mac_twt_param_equal(struct mt7996_sta_link *msta_link,
 			   struct ieee80211_twt_params *twt_agrt)
 {
 	u16 type = le16_to_cpu(twt_agrt->req_type);
@@ -2562,10 +2582,10 @@ mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
 	for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
 		struct mt7996_twt_flow *f;
 
-		if (!(msta->twt.flowid_mask & BIT(i)))
+		if (!(msta_link->twt.flowid_mask & BIT(i)))
 			continue;
 
-		f = &msta->twt.flow[i];
+		f = &msta_link->twt.flow[i];
 		if (f->duration == twt_agrt->min_twt_dur &&
 		    f->mantissa == twt_agrt->mantissa &&
 		    f->exp == exp &&
@@ -2585,6 +2605,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 	enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	u16 req_type = le16_to_cpu(twt_agrt->req_type);
 	enum ieee80211_twt_setup_cmd sta_setup_cmd;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
@@ -2599,7 +2620,8 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 	if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT)
 		goto unlock;
 
-	if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
+	if (hweight8(msta_link->twt.flowid_mask) ==
+	    ARRAY_SIZE(msta_link->twt.flow))
 		goto unlock;
 
 	if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
@@ -2608,10 +2630,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 		goto unlock;
 	}
 
-	if (mt7996_mac_twt_param_equal(msta, twt_agrt))
+	if (mt7996_mac_twt_param_equal(msta_link, twt_agrt))
 		goto unlock;
 
-	flowid = ffs(~msta->twt.flowid_mask) - 1;
+	flowid = ffs(~msta_link->twt.flowid_mask) - 1;
 	twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
 	twt_agrt->req_type |= le16_encode_bits(flowid,
 					       IEEE80211_TWT_REQTYPE_FLOWID);
@@ -2620,10 +2642,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 	exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
 	sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
 
-	flow = &msta->twt.flow[flowid];
+	flow = &msta_link->twt.flow[flowid];
 	memset(flow, 0, sizeof(*flow));
 	INIT_LIST_HEAD(&flow->list);
-	flow->wcid = msta->wcid.idx;
+	flow->wcid = msta_link->wcid.idx;
 	flow->table_id = table_id;
 	flow->id = flowid;
 	flow->duration = twt_agrt->min_twt_dur;
@@ -2655,7 +2677,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 
 	setup_cmd = TWT_SETUP_CMD_ACCEPT;
 	dev->twt.table_mask |= BIT(table_id);
-	msta->twt.flowid_mask |= BIT(flowid);
+	msta_link->twt.flowid_mask |= BIT(flowid);
 	dev->twt.n_agrt++;
 
 unlock:
@@ -2671,23 +2693,24 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
 				  struct mt7996_sta *msta,
 				  u8 flowid)
 {
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_twt_flow *flow;
 
 	lockdep_assert_held(&dev->mt76.mutex);
 
-	if (flowid >= ARRAY_SIZE(msta->twt.flow))
+	if (flowid >= ARRAY_SIZE(msta_link->twt.flow))
 		return;
 
-	if (!(msta->twt.flowid_mask & BIT(flowid)))
+	if (!(msta_link->twt.flowid_mask & BIT(flowid)))
 		return;
 
-	flow = &msta->twt.flow[flowid];
+	flow = &msta_link->twt.flow[flowid];
 	if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow,
 				       MCU_TWT_AGRT_DELETE))
 		return;
 
 	list_del_init(&flow->list);
-	msta->twt.flowid_mask &= ~BIT(flowid);
+	msta_link->twt.flowid_mask &= ~BIT(flowid);
 	dev->twt.table_mask &= ~BIT(flow->table_id);
 	dev->twt.n_agrt--;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index c0e7ab9bcae5fcd503c10e1a02508977b6921d17..0cd011619fd3fc6f6994e4a8a896668340969cf5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -163,7 +163,7 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv :
 				  &mlink->sta;
-	struct mt76_wcid *wcid = &msta->wcid;
+	struct mt76_wcid *wcid = &msta->deflink.wcid;
 	u8 *wcid_keyidx = &wcid->hw_key_idx;
 	struct mt7996_phy *phy;
 	int idx = key->keyidx;
@@ -208,8 +208,7 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		return mt7996_mcu_bcn_prot_enable(dev, vif, key);
 
 	return mt7996_mcu_add_key(&dev->mt76, vif, key,
-				  MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
-				  &msta->wcid, cmd);
+				  MCU_WMWA_UNI_CMD(STA_REC_UPDATE), wcid, cmd);
 }
 
 static void
@@ -230,6 +229,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_sta_link *msta_link = &link->sta.deflink;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
 	u8 band_idx = phy->mt76->band_idx;
@@ -248,7 +248,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	mlink->omac_idx = idx;
 	mlink->band_idx = band_idx;
 	mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;
-	mlink->wcid = &link->sta.wcid;
+	mlink->wcid = &msta_link->wcid;
 	mlink->wcid->offchannel = mlink->offchannel;
 
 	ret = mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, true);
@@ -260,10 +260,11 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	idx = MT7996_WTBL_RESERVED - mlink->idx;
 
-	INIT_LIST_HEAD(&link->sta.rc_list);
-	link->sta.wcid.idx = idx;
-	link->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
-	mt76_wcid_init(&link->sta.wcid, band_idx);
+	INIT_LIST_HEAD(&msta_link->rc_list);
+	msta_link->sta = &link->sta;
+	msta_link->wcid.idx = idx;
+	msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+	mt76_wcid_init(&msta_link->wcid, band_idx);
 
 	mt7996_mac_wtbl_update(dev, idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -290,7 +291,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	 */
 	if (vif->type != NL80211_IFTYPE_STATION)
 		mt7996_mcu_add_sta(dev, vif, mlink, NULL, CONN_STATE_PORT_SECURE, true);
-	rcu_assign_pointer(dev->mt76.wcid[idx], &link->sta.wcid);
+	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
 
 	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, link);
 
@@ -304,11 +305,10 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
-	struct mt7996_sta *msta;
-	int idx;
+	struct mt7996_sta *msta = &link->sta;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
+	int idx = msta_link->wcid.idx;
 
-	msta = &link->sta;
-	idx = msta->wcid.idx;
 	mt7996_mcu_add_sta(dev, vif, mlink, NULL, CONN_STATE_DISCONNECT, false);
 	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, false);
 
@@ -320,11 +320,11 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
 
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
-	if (!list_empty(&msta->wcid.poll_list))
-		list_del_init(&msta->wcid.poll_list);
+	if (!list_empty(&msta_link->wcid.poll_list))
+		list_del_init(&msta_link->wcid.poll_list);
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
-	mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
+	mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
 }
 
 static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)
@@ -788,6 +788,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif_link *link = &mvif->deflink;
 	u8 band_idx = link->phy->mt76->band_idx;
 	int idx;
@@ -796,14 +797,15 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	if (idx < 0)
 		return -ENOSPC;
 
-	INIT_LIST_HEAD(&msta->rc_list);
-	INIT_LIST_HEAD(&msta->wcid.poll_list);
 	msta->vif = mvif;
-	msta->wcid.sta = 1;
-	msta->wcid.idx = idx;
-	msta->wcid.phy_idx = band_idx;
+	INIT_LIST_HEAD(&msta_link->rc_list);
+	INIT_LIST_HEAD(&msta_link->wcid.poll_list);
+	msta_link->sta = msta;
+	msta_link->wcid.sta = 1;
+	msta_link->wcid.idx = idx;
+	msta_link->wcid.phy_idx = band_idx;
 
-	ewma_avg_signal_init(&msta->avg_ack_signal);
+	ewma_avg_signal_init(&msta_link->avg_ack_signal);
 
 	mt7996_mac_wtbl_update(dev, idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -818,6 +820,7 @@ int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 {
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_vif_link *link = &mvif->deflink;
 	int i, ret;
@@ -833,8 +836,8 @@ int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 		if (ret)
 			return ret;
 
-		msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
-		msta->wcid.sta = 1;
+		msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+		msta_link->wcid.sta = 1;
 
 		return 0;
 
@@ -843,13 +846,13 @@ int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 					  CONN_STATE_PORT_SECURE, false);
 
 	case MT76_STA_EVENT_DISASSOC:
-		for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
+		for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++)
 			mt7996_mac_twt_teardown_flow(dev, msta, i);
 
 		mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
 				   CONN_STATE_DISCONNECT, false);
-		msta->wcid.sta_disabled = 1;
-		msta->wcid.sta = 0;
+		msta_link->wcid.sta_disabled = 1;
+		msta_link->wcid.sta = 0;
 
 		return 0;
 	}
@@ -862,15 +865,16 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 {
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 
-	mt7996_mac_wtbl_update(dev, msta->wcid.idx,
+	mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
 	spin_lock_bh(&mdev->sta_poll_lock);
-	if (!list_empty(&msta->wcid.poll_list))
-		list_del_init(&msta->wcid.poll_list);
-	if (!list_empty(&msta->rc_list))
-		list_del_init(&msta->rc_list);
+	if (!list_empty(&msta_link->wcid.poll_list))
+		list_del_init(&msta_link->wcid.poll_list);
+	if (!list_empty(&msta_link->rc_list))
+		list_del_init(&msta_link->rc_list);
 	spin_unlock_bh(&mdev->sta_poll_lock);
 }
 
@@ -888,7 +892,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 		struct mt7996_vif *mvif;
 
 		mvif = (struct mt7996_vif *)vif->drv_priv;
-		wcid = &mvif->deflink.sta.wcid;
+		wcid = &mvif->deflink.sta.deflink.wcid;
 
 		if (mvif->mt76.roc_phy &&
 		    (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
@@ -901,10 +905,10 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 	}
 
 	if (control->sta) {
-		struct mt7996_sta *sta;
+		struct mt7996_sta_link *msta_link;
 
-		sta = (struct mt7996_sta *)control->sta->drv_priv;
-		wcid = &sta->wcid;
+		msta_link = (struct mt7996_sta_link *)control->sta->drv_priv;
+		wcid = &msta_link->wcid;
 	}
 
 	if (!mphy) {
@@ -944,6 +948,7 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct ieee80211_sta *sta = params->sta;
 	struct ieee80211_txq *txq = sta->txq[params->tid];
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	u16 tid = params->tid;
 	u16 ssn = params->ssn;
 	struct mt76_txq *mtxq;
@@ -957,12 +962,12 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mutex_lock(&dev->mt76.mutex);
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
+		mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, ssn,
 				   params->buf_size);
 		ret = mt7996_mcu_add_rx_ba(dev, params, true);
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
-		mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
+		mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
 		ret = mt7996_mcu_add_rx_ba(dev, params, false);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -973,16 +978,16 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 		mtxq->aggr = false;
-		clear_bit(tid, &msta->wcid.ampdu_state);
+		clear_bit(tid, &msta_link->wcid.ampdu_state);
 		ret = mt7996_mcu_add_tx_ba(dev, params, false);
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		set_bit(tid, &msta->wcid.ampdu_state);
+		set_bit(tid, &msta_link->wcid.ampdu_state);
 		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 		mtxq->aggr = false;
-		clear_bit(tid, &msta->wcid.ampdu_state);
+		clear_bit(tid, &msta_link->wcid.ampdu_state);
 		ret = mt7996_mcu_add_tx_ba(dev, params, false);
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
@@ -1173,7 +1178,8 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct rate_info *txrate = &msta->wcid.rate;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct rate_info *txrate = &msta_link->wcid.rate;
 
 	if (txrate->legacy || txrate->flags) {
 		if (txrate->legacy) {
@@ -1193,29 +1199,30 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
 	sinfo->txrate.flags = txrate->flags;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
 
-	sinfo->tx_failed = msta->wcid.stats.tx_failed;
+	sinfo->tx_failed = msta_link->wcid.stats.tx_failed;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 
-	sinfo->tx_retries = msta->wcid.stats.tx_retries;
+	sinfo->tx_retries = msta_link->wcid.stats.tx_retries;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
 
-	sinfo->ack_signal = (s8)msta->ack_signal;
+	sinfo->ack_signal = (s8)msta_link->ack_signal;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
 
-	sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
+	sinfo->avg_ack_signal =
+		-(s8)ewma_avg_signal_read(&msta_link->avg_ack_signal);
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
 
 	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-		sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
+		sinfo->tx_bytes = msta_link->wcid.stats.tx_bytes;
 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
 
-		sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
+		sinfo->rx_bytes = msta_link->wcid.stats.rx_bytes;
 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
 
-		sinfo->tx_packets = msta->wcid.stats.tx_packets;
+		sinfo->tx_packets = msta_link->wcid.stats.tx_packets;
 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
 
-		sinfo->rx_packets = msta->wcid.stats.rx_packets;
+		sinfo->rx_packets = msta_link->wcid.stats.rx_packets;
 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
 	}
 }
@@ -1224,12 +1231,13 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	u32 *changed = data;
 
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
-	msta->changed |= *changed;
-	if (list_empty(&msta->rc_list))
-		list_add_tail(&msta->rc_list, &dev->sta_rc_list);
+	msta_link->changed |= *changed;
+	if (list_empty(&msta_link->rc_list))
+		list_add_tail(&msta_link->rc_list, &dev->sta_rc_list);
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
 }
 
@@ -1276,13 +1284,14 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 
 	if (enabled)
-		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+		set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
 	else
-		clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+		clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
 
-	if (!msta->wcid.sta)
+	if (!msta_link->wcid.sta)
 		return;
 
 	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
@@ -1295,13 +1304,14 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 
 	if (enabled)
-		set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
+		set_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
 	else
-		clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
+		clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
 
-	if (!msta->wcid.sta)
+	if (!msta_link->wcid.sta)
 		return;
 
 	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
@@ -1436,11 +1446,12 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
 {
 	struct mt76_ethtool_worker_info *wi = wi_data;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 
 	if (msta->vif->deflink.mt76.idx != wi->idx)
 		return;
 
-	mt76_ethtool_worker(wi, &msta->wcid.stats, true);
+	mt76_ethtool_worker(wi, &msta_link->wcid.stats, true);
 }
 
 static
@@ -1617,6 +1628,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif_link *mlink = &mvif->deflink;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
@@ -1632,7 +1644,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (!msta->wcid.sta || msta->wcid.idx > MT7996_WTBL_STA)
+	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
@@ -1640,7 +1652,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->deflink.mt76.idx;
 	path->mtk_wdma.queue = 0;
-	path->mtk_wdma.wcid = msta->wcid.idx;
+	path->mtk_wdma.wcid = msta_link->wcid.idx;
 
 	path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
 	ctx->dev = NULL;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 76f489e2f602166247d4be79e12c4400d96d49e3..b0ddc2af1516995fc11f030ef8360bae4ea3be3b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1162,10 +1162,11 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 bool enable)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif *mvif = msta->vif;
 
 	if (enable && !params->amsdu)
-		msta->wcid.amsdu = false;
+		msta_link->wcid.amsdu = false;
 
 	return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params, enable, true);
 }
@@ -1322,6 +1323,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 			 struct ieee80211_vif *vif, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sta_rec_amsdu *amsdu;
 	struct tlv *tlv;
 
@@ -1337,7 +1339,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	amsdu = (struct sta_rec_amsdu *)tlv;
 	amsdu->max_amsdu_num = 8;
 	amsdu->amsdu_en = true;
-	msta->wcid.amsdu = true;
+	msta_link->wcid.amsdu = true;
 
 	switch (sta->deflink.agg.max_amsdu_len) {
 	case IEEE80211_MAX_MPDU_LEN_VHT_11454:
@@ -1879,13 +1881,14 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sta_phy_uni *phy = data;
 	struct sta_rec_ra_fixed_uni *ra;
 	struct sk_buff *skb;
 	struct tlv *tlv;
 
 	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
-					      &msta->wcid,
+					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
@@ -1972,14 +1975,14 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 	/* fixed GI */
 	if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
 	    mask->control[band].he_gi != GENMASK(7, 0)) {
-		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+		struct mt7996_sta_link *msta_link = (void *)sta->drv_priv;
 		u32 addr;
 
 		/* firmware updates only TXCMD but doesn't take WTBL into
 		 * account, so driver should update here to reflect the
 		 * actual txrate hardware sends out.
 		 */
-		addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
+		addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7);
 		if (sta->deflink.he_cap.has_he)
 			mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
 		else
@@ -2113,11 +2116,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sk_buff *skb;
 	int ret;
 
 	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
-					      &msta->wcid,
+					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
@@ -2148,6 +2152,7 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 {
 #define MT_STA_BSS_GROUP		1
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_sta_link *msta_link;
 	struct mt7996_sta *msta;
 	struct {
 		u8 __rsv1[4];
@@ -2167,7 +2172,8 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	};
 
 	msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->deflink.sta;
-	req.wlan_idx = cpu_to_le16(msta->wcid.idx);
+	msta_link = &msta->deflink;
+	req.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
 
 	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
 				 sizeof(req), true);
@@ -2184,8 +2190,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 
 	if (sta) {
 		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+		struct mt7996_sta_link *msta_link = &msta->deflink;
 
-		wcid = &msta->wcid;
+		wcid = &msta_link->wcid;
 		link_sta = &sta->deflink;
 	}
 
@@ -2312,12 +2319,14 @@ static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 {
 #define TSC_TYPE_BIGTK_PN 2
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_sta_link *msta_link = &mvif->deflink.sta.deflink;
 	struct sta_rec_pn_info *pn_info;
 	struct sk_buff *skb, *rskb;
 	struct tlv *tlv;
 	int ret;
 
-	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76, &mvif->deflink.sta.wcid);
+	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+					    &msta_link->wcid);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
@@ -4344,19 +4353,21 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_sta *sta)
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_sta_link *msta_link;
 	struct mt7996_sta *msta;
 	struct sk_buff *skb;
 
 	msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->deflink.sta;
+	msta_link = &msta->deflink;
 
 	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
-					      &msta->wcid,
+					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
 	/* starec hdr trans */
-	mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, &msta->wcid);
+	mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, &msta_link->wcid);
 	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 29fabb9b04ae328d84a3479f76f6ee93900aef2a..d0a4240f12a482895659e3a359daadcdca7bf7c9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -185,10 +185,10 @@ struct mt7996_twt_flow {
 
 DECLARE_EWMA(avg_signal, 10, 8)
 
-struct mt7996_sta {
+struct mt7996_sta_link {
 	struct mt76_wcid wcid; /* must be first */
 
-	struct mt7996_vif *vif;
+	struct mt7996_sta *sta;
 
 	struct list_head rc_list;
 	u32 airtime_ac[8];
@@ -206,6 +206,12 @@ struct mt7996_sta {
 	} twt;
 };
 
+struct mt7996_sta {
+	struct mt7996_sta_link deflink; /* must be first */
+
+	struct mt7996_vif *vif;
+};
+
 struct mt7996_vif_link {
 	struct mt76_vif_link mt76; /* must be first */
 

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:02 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:02 +0100
Subject: [PATCH v2 03/13] wifi: mt76: mt7996: Add mt7996_sta_link struct in
 mt7996_vif_link
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-3-31df6972519b@kernel.org>

Introduce mt7996_sta_link field in mt7996_vif_link structure instead of
mt7996_sta. This is a preliminary patch to support MLO in MT7996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |  6 +++---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 24 ++++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 10 ++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  2 +-
 4 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 754f8e520f52f6abf70daa148bf4289f68b1252b..456666eb7080c50493dcde61c5399adc6a987d2d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -72,10 +72,10 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
 	msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
 	msta = msta_link->sta;
 
-	if (!msta->vif)
+	if (!msta || !msta->vif)
 		return NULL;
 
-	return &msta->vif->deflink.sta.deflink.wcid;
+	return &msta->vif->deflink.msta_link.wcid;
 }
 
 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
@@ -202,7 +202,7 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
 			      struct ieee80211_vif *vif, bool enable)
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.sta.deflink;
+	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
 	u32 addr;
 
 	addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 5);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 0cd011619fd3fc6f6994e4a8a896668340969cf5..34f984387c00714fbe72af5220ec067760510bb8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -161,19 +161,23 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		  struct mt7996_vif_link *mlink, struct ieee80211_key_conf *key)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv :
-				  &mlink->sta;
-	struct mt76_wcid *wcid = &msta->deflink.wcid;
-	u8 *wcid_keyidx = &wcid->hw_key_idx;
+	struct mt76_wcid *wcid = &mlink->msta_link.wcid;
 	struct mt7996_phy *phy;
 	int idx = key->keyidx;
+	u8 *wcid_keyidx;
 
 	phy = mt7996_vif_link_phy(mlink);
 	if (!phy)
 		return -EINVAL;
 
-	if (sta && !wcid->sta)
-		return -EOPNOTSUPP;
+	if (sta) {
+		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+
+		wcid = &msta->deflink.wcid;
+		if (!wcid->sta)
+			return -EOPNOTSUPP;
+	}
+	wcid_keyidx = &wcid->hw_key_idx;
 
 	switch (key->cipher) {
 	case WLAN_CIPHER_SUITE_AES_CMAC:
@@ -229,7 +233,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
-	struct mt7996_sta_link *msta_link = &link->sta.deflink;
+	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
 	u8 band_idx = phy->mt76->band_idx;
@@ -261,7 +265,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	idx = MT7996_WTBL_RESERVED - mlink->idx;
 
 	INIT_LIST_HEAD(&msta_link->rc_list);
-	msta_link->sta = &link->sta;
 	msta_link->wcid.idx = idx;
 	msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
 	mt76_wcid_init(&msta_link->wcid, band_idx);
@@ -303,10 +306,9 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			    struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
-	struct mt7996_sta *msta = &link->sta;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	int idx = msta_link->wcid.idx;
 
 	mt7996_mcu_add_sta(dev, vif, mlink, NULL, CONN_STATE_DISCONNECT, false);
@@ -892,7 +894,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 		struct mt7996_vif *mvif;
 
 		mvif = (struct mt7996_vif *)vif->drv_priv;
-		wcid = &mvif->deflink.sta.deflink.wcid;
+		wcid = &mvif->deflink.msta_link.wcid;
 
 		if (mvif->mt76.roc_phy &&
 		    (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index b0ddc2af1516995fc11f030ef8360bae4ea3be3b..9018ede6efed49241205ddc042f3df149cd58530 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2171,8 +2171,8 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		.val = cpu_to_le32(mvif->deflink.mt76.idx % 16),
 	};
 
-	msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->deflink.sta;
-	msta_link = &msta->deflink;
+	msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
+	msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link;
 	req.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
 
 	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
@@ -2319,7 +2319,7 @@ static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 {
 #define TSC_TYPE_BIGTK_PN 2
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.sta.deflink;
+	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
 	struct sta_rec_pn_info *pn_info;
 	struct sk_buff *skb, *rskb;
 	struct tlv *tlv;
@@ -4357,8 +4357,8 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 	struct mt7996_sta *msta;
 	struct sk_buff *skb;
 
-	msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->deflink.sta;
-	msta_link = &msta->deflink;
+	msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
+	msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link;
 
 	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
 					      &msta_link->wcid,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index d0a4240f12a482895659e3a359daadcdca7bf7c9..ac5b94e1315ec610f5182563e3fb9d504a67c16f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -215,7 +215,7 @@ struct mt7996_sta {
 struct mt7996_vif_link {
 	struct mt76_vif_link mt76; /* must be first */
 
-	struct mt7996_sta sta;
+	struct mt7996_sta_link msta_link;
 	struct mt7996_phy *phy;
 
 	struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:03 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:03 +0100
Subject: [PATCH v2 04/13] wifi: mt76: mt7996: Add vif_cfg_changed callback
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-4-31df6972519b@kernel.org>

Introduce vif_cfg_changed mac80211 callback as preliminary patch to
enable MLO support in MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 35 +++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 34f984387c00714fbe72af5220ec067760510bb8..59a1e5e52450accc5b01fbe0c3af7e84bcc87df6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -679,6 +679,39 @@ mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]);
 }
 
+static void
+mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		       u64 changed)
+{
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+
+	mutex_lock(&dev->mt76.mutex);
+
+	if ((changed & BSS_CHANGED_ASSOC) && vif->cfg.assoc) {
+		struct ieee80211_bss_conf *link_conf;
+		unsigned long link_id;
+
+		for_each_vif_active_link(vif, link_conf, link_id) {
+			struct mt7996_vif_link *link;
+
+			link = mt7996_vif_link(dev, vif, link_id);
+			if (!link)
+				continue;
+
+			if (!link->phy)
+				continue;
+
+			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
+						&link->mt76, true);
+			mt7996_mcu_add_sta(dev, vif, &link->mt76, NULL,
+					   CONN_STATE_PORT_SECURE,
+					   !!(changed & BSS_CHANGED_BSSID));
+		}
+	}
+
+	mutex_unlock(&dev->mt76.mutex);
+}
+
 static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *info,
@@ -705,7 +738,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
 	 * and then peer references bss_info_rfch to set bandwidth cap.
 	 */
 	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
-	    (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
 	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
 		mt7996_mcu_add_bss_info(phy, vif, info, mvif, true);
 		mt7996_mcu_add_sta(dev, vif, mvif, NULL, CONN_STATE_PORT_SECURE,
@@ -1688,6 +1720,7 @@ const struct ieee80211_ops mt7996_ops = {
 	.conf_tx = mt7996_conf_tx,
 	.configure_filter = mt7996_configure_filter,
 	.bss_info_changed = mt7996_bss_info_changed,
+	.vif_cfg_changed = mt7996_vif_cfg_changed,
 	.sta_state = mt76_sta_state,
 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
 	.link_sta_rc_update = mt7996_sta_rc_update,

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:04 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:04 +0100
Subject: [PATCH v2 05/13] wifi: mt76: mt7996: Add link_info_changed
 callback
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-5-31df6972519b@kernel.org>

Convert bss_info_changed mac80211 callback in link_info_changed one.
This is a preliminary patch to enable MLO support in MT7996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 59a1e5e52450accc5b01fbe0c3af7e84bcc87df6..81a13662db24ec268fdd7a9b3d6b1d829a91430f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -712,10 +712,9 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mutex_unlock(&dev->mt76.mutex);
 }
 
-static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_bss_conf *info,
-				    u64 changed)
+static void
+mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			 struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt76_vif_link *mvif;
@@ -1719,8 +1718,8 @@ const struct ieee80211_ops mt7996_ops = {
 	.config = mt7996_config,
 	.conf_tx = mt7996_conf_tx,
 	.configure_filter = mt7996_configure_filter,
-	.bss_info_changed = mt7996_bss_info_changed,
 	.vif_cfg_changed = mt7996_vif_cfg_changed,
+	.link_info_changed = mt7996_link_info_changed,
 	.sta_state = mt76_sta_state,
 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
 	.link_sta_rc_update = mt7996_sta_rc_update,

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:05 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:05 +0100
Subject: [PATCH v2 06/13] wifi: mt76: mt7996: Add mt7996_sta_state routine
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-6-31df6972519b@kernel.org>

Introduce mt7996_sta_state routine in order to initialize wcid structure
in mt7996 codebase. This is a preliminary patch to enable MLO support in
MT7996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mac80211.c      |   5 +-
 drivers/net/wireless/mediatek/mt76/mt76.h          |   2 +
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 100 ++++++++++++++++++---
 drivers/net/wireless/mediatek/mt76/mt7996/mmio.c   |   3 -
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |   6 --
 5 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 2c98cc42cd7e6335e2a8c7f5dd8c386df004ae00..b88d7e10742ee621d2cc6f17576592c6793f2f6c 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -816,8 +816,8 @@ void mt76_free_device(struct mt76_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76_free_device);
 
-static struct mt76_phy *
-mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif)
 {
 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
 	struct mt76_chanctx *ctx;
@@ -831,6 +831,7 @@ mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	ctx = (struct mt76_chanctx *)mlink->ctx->drv_priv;
 	return ctx->phy;
 }
+EXPORT_SYMBOL_GPL(mt76_vif_phy);
 
 static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index b461273c33064259fa1bb61ea88c06a60cb07178..d7cd467b812fc799428f076efb9b72e7ff988db6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1228,6 +1228,8 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
 				u8 band_idx);
 int mt76_register_phy(struct mt76_phy *phy, bool vht,
 		      struct ieee80211_rate *rates, int n_rates);
+struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif);
 
 struct dentry *mt76_register_debugfs_fops(struct mt76_phy *phy,
 					  const struct file_operations *ops);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 81a13662db24ec268fdd7a9b3d6b1d829a91430f..d99a98d57142fb4826b68c78864614d2c9132fe7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -815,20 +815,26 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
 	mutex_unlock(&dev->mt76.mutex);
 }
 
-int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-		       struct ieee80211_sta *sta)
+static int
+mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+		   struct ieee80211_sta *sta)
 {
+	struct mt76_dev *mdev = mphy->dev;
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif_link *link = &mvif->deflink;
-	u8 band_idx = link->phy->mt76->band_idx;
-	int idx;
+	u8 band_idx = mphy->band_idx;
+	int i, idx, ret = 0;
 
-	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
-	if (idx < 0)
-		return -ENOSPC;
+	mutex_lock(&mdev->mutex);
+
+	idx = mt76_wcid_alloc(mdev->wcid_mask, MT7996_WTBL_STA);
+	if (idx < 0) {
+		ret = -ENOSPC;
+		goto unlock;
+	}
 
 	msta->vif = mvif;
 	INIT_LIST_HEAD(&msta_link->rc_list);
@@ -838,20 +844,37 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	msta_link->wcid.idx = idx;
 	msta_link->wcid.phy_idx = band_idx;
 
+	for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
+		struct mt76_txq *mtxq;
+
+		if (!sta->txq[i])
+			continue;
+
+		mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
+		mtxq->wcid = idx;
+	}
+
 	ewma_avg_signal_init(&msta_link->avg_ack_signal);
+	ewma_signal_init(&msta_link->wcid.rssi);
 
 	mt7996_mac_wtbl_update(dev, idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 	mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
 			   true);
 
-	return 0;
+	rcu_assign_pointer(mdev->wcid[idx], &msta_link->wcid);
+	mt76_wcid_init(&msta_link->wcid, band_idx);
+	mphy->num_sta++;
+unlock:
+	mutex_unlock(&mdev->mutex);
+
+	return ret;
 }
 
-int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta, enum mt76_sta_event ev)
+static int
+mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+		     struct ieee80211_sta *sta, enum mt76_sta_event ev)
 {
-	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
@@ -893,12 +916,20 @@ int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	return 0;
 }
 
-void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-			   struct ieee80211_sta *sta)
+static void
+mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+		      struct ieee80211_sta *sta)
 {
+	struct mt76_dev *mdev = mphy->dev;
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_sta_link *msta_link = &msta->deflink;
+	int i, idx = msta_link->wcid.idx;
+
+	mutex_lock(&mdev->mutex);
+
+	for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
+		mt76_rx_aggr_stop(mdev, &msta_link->wcid, i);
 
 	mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -909,6 +940,47 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 	if (!list_empty(&msta_link->rc_list))
 		list_del_init(&msta_link->rc_list);
 	spin_unlock_bh(&mdev->sta_poll_lock);
+
+	mt76_wcid_cleanup(mdev, &msta_link->wcid);
+	mt76_wcid_mask_clear(mdev->wcid_mask, idx);
+	mphy->num_sta--;
+
+	mutex_unlock(&mdev->mutex);
+}
+
+static int
+mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		 struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
+		 enum ieee80211_sta_state new_state)
+{
+	struct mt76_phy *mphy = mt76_vif_phy(hw, vif);
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	enum mt76_sta_event ev;
+
+	if (!mphy)
+		return -EINVAL;
+
+	if (old_state == IEEE80211_STA_NOTEXIST &&
+	    new_state == IEEE80211_STA_NONE)
+		return mt7996_mac_sta_add(mphy, vif, sta);
+
+	if (old_state == IEEE80211_STA_NONE &&
+	    new_state == IEEE80211_STA_NOTEXIST)
+		mt7996_mac_sta_remove(mphy, vif, sta);
+
+	if (old_state == IEEE80211_STA_AUTH &&
+	    new_state == IEEE80211_STA_ASSOC)
+		ev = MT76_STA_EVENT_ASSOC;
+	else if (old_state == IEEE80211_STA_ASSOC &&
+		 new_state == IEEE80211_STA_AUTHORIZED)
+		ev = MT76_STA_EVENT_AUTHORIZE;
+	else if (old_state == IEEE80211_STA_ASSOC &&
+		 new_state == IEEE80211_STA_AUTH)
+		ev = MT76_STA_EVENT_DISASSOC;
+	else
+		return 0;
+
+	return mt7996_mac_sta_event(dev, vif, sta, ev);
 }
 
 static void mt7996_tx(struct ieee80211_hw *hw,
@@ -1720,7 +1792,7 @@ const struct ieee80211_ops mt7996_ops = {
 	.configure_filter = mt7996_configure_filter,
 	.vif_cfg_changed = mt7996_vif_cfg_changed,
 	.link_info_changed = mt7996_link_info_changed,
-	.sta_state = mt76_sta_state,
+	.sta_state = mt7996_sta_state,
 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
 	.link_sta_rc_update = mt7996_sta_rc_update,
 	.set_key = mt7996_set_key,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
index 9d37f823874643f7ff9121365b6dccd1d1653a99..13b188e281bdb9a1e0d029c9d739769a380a4723 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
@@ -618,9 +618,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
 		.rx_skb = mt7996_queue_rx_skb,
 		.rx_check = mt7996_rx_check,
 		.rx_poll_complete = mt7996_rx_poll_complete,
-		.sta_add = mt7996_mac_sta_add,
-		.sta_event = mt7996_mac_sta_event,
-		.sta_remove = mt7996_mac_sta_remove,
 		.update_survey = mt7996_update_channel,
 		.set_channel = mt7996_set_channel,
 		.vif_link_add = mt7996_vif_link_add,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index ac5b94e1315ec610f5182563e3fb9d504a67c16f..117a9e6c49645e847c579d15809bb5553a64ccfd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -696,12 +696,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 			   struct ieee80211_key_conf *key, int pid,
 			   enum mt76_txq_id qid, u32 changed);
 void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
-int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-		       struct ieee80211_sta *sta);
-int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta, enum mt76_sta_event ev);
-void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-			   struct ieee80211_sta *sta);
 void mt7996_mac_work(struct work_struct *work);
 void mt7996_mac_reset_work(struct work_struct *work);
 void mt7996_mac_dump_work(struct work_struct *work);

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:06 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:06 +0100
Subject: [PATCH v2 07/13] wifi: mt76: mt7996: Rely on mt7996_sta_link in
 sta_add/sta_remove callbacks
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-7-31df6972519b@kernel.org>

Generalize mt7996_mac_sta_add() and mt7996_mac_sta_remove() routines to
deal with mt7996_sta_link structure.
This is a preliminary patch to introduce MLO support for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 189 +++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |   4 +
 2 files changed, 143 insertions(+), 50 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index d99a98d57142fb4826b68c78864614d2c9132fe7..1bca444d2d02333cabd31ba2c8565769a42ab581 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -816,59 +816,164 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
 }
 
 static int
-mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
-		   struct ieee80211_sta *sta)
+mt7996_mac_sta_init_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+			 struct mt7996_vif_link *link,
+			 struct ieee80211_sta *sta, unsigned int link_id)
 {
-	struct mt76_dev *mdev = mphy->dev;
-	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif_link *link = &mvif->deflink;
-	u8 band_idx = mphy->band_idx;
-	int i, idx, ret = 0;
+	struct mt7996_phy *phy = link->phy;
+	struct mt7996_sta_link *msta_link;
+	int idx;
 
-	mutex_lock(&mdev->mutex);
+	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
+	if (idx < 0)
+		return -ENOSPC;
+
+	if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
+		int i;
+
+		msta_link = &msta->deflink;
+		msta->deflink_id = link_id;
+
+		for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
+			struct mt76_txq *mtxq;
+
+			if (!sta->txq[i])
+				continue;
 
-	idx = mt76_wcid_alloc(mdev->wcid_mask, MT7996_WTBL_STA);
-	if (idx < 0) {
-		ret = -ENOSPC;
-		goto unlock;
+			mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
+			mtxq->wcid = idx;
+		}
+	} else {
+		msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL);
+		if (!msta_link)
+			return -ENOMEM;
 	}
 
-	msta->vif = mvif;
 	INIT_LIST_HEAD(&msta_link->rc_list);
 	INIT_LIST_HEAD(&msta_link->wcid.poll_list);
 	msta_link->sta = msta;
 	msta_link->wcid.sta = 1;
 	msta_link->wcid.idx = idx;
-	msta_link->wcid.phy_idx = band_idx;
+	msta_link->wcid.link_id = link_id;
+
+	ewma_avg_signal_init(&msta_link->avg_ack_signal);
+	ewma_signal_init(&msta_link->wcid.rssi);
 
-	for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
-		struct mt76_txq *mtxq;
+	rcu_assign_pointer(msta->link[link_id], msta_link);
 
-		if (!sta->txq[i])
+	mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+	mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
+			   true);
+
+	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
+	mt76_wcid_init(&msta_link->wcid, phy->mt76->band_idx);
+
+	return 0;
+}
+
+static void
+mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
+			   struct mt7996_sta_link *msta_link)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
+		mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, i);
+
+	mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
+			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+
+	spin_lock_bh(&dev->mt76.sta_poll_lock);
+	if (!list_empty(&msta_link->wcid.poll_list))
+		list_del_init(&msta_link->wcid.poll_list);
+	if (!list_empty(&msta_link->rc_list))
+		list_del_init(&msta_link->rc_list);
+	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+
+	mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
+	mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
+}
+
+static void
+mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
+			    unsigned long links)
+{
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt76_dev *mdev = &dev->mt76;
+	unsigned int link_id;
+
+	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct mt7996_sta_link *msta_link = NULL;
+
+		msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
+						lockdep_is_held(&mdev->mutex));
+		if (!msta_link)
 			continue;
 
-		mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
-		mtxq->wcid = idx;
+		mt7996_mac_sta_deinit_link(dev, msta_link);
+		if (msta->deflink_id == link_id) {
+			msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
+			continue;
+		}
+
+		kfree_rcu(msta_link, rcu_head);
 	}
+}
 
-	ewma_avg_signal_init(&msta_link->avg_ack_signal);
-	ewma_signal_init(&msta_link->wcid.rssi);
+static int
+mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+			 struct ieee80211_sta *sta, unsigned long new_links)
+{
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	unsigned int link_id;
+	int err;
 
-	mt7996_mac_wtbl_update(dev, idx,
-			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-	mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
-			   true);
+	for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct mt7996_vif_link *link;
+
+		if (rcu_access_pointer(msta->link[link_id]))
+			continue;
+
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			goto error_unlink;
+
+		err = mt7996_mac_sta_init_link(dev, vif, link, sta, link_id);
+		if (err)
+			goto error_unlink;
+	}
+
+	return 0;
+
+error_unlink:
+	mt7996_mac_sta_remove_links(dev, sta, new_links);
+
+	return err;
+}
+
+static int
+mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+		   struct ieee80211_sta *sta)
+{
+	struct mt76_dev *mdev = mphy->dev;
+	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
+	int err;
+
+	mutex_lock(&mdev->mutex);
+
+	msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
+	msta->vif = mvif;
+	err = mt7996_mac_sta_add_links(dev, vif, sta, links);
+	if (!err)
+		mphy->num_sta++;
 
-	rcu_assign_pointer(mdev->wcid[idx], &msta_link->wcid);
-	mt76_wcid_init(&msta_link->wcid, band_idx);
-	mphy->num_sta++;
-unlock:
 	mutex_unlock(&mdev->mutex);
 
-	return ret;
+	return err;
 }
 
 static int
@@ -922,27 +1027,11 @@ mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 {
 	struct mt76_dev *mdev = mphy->dev;
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	int i, idx = msta_link->wcid.idx;
+	unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
 
 	mutex_lock(&mdev->mutex);
 
-	for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
-		mt76_rx_aggr_stop(mdev, &msta_link->wcid, i);
-
-	mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
-			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-
-	spin_lock_bh(&mdev->sta_poll_lock);
-	if (!list_empty(&msta_link->wcid.poll_list))
-		list_del_init(&msta_link->wcid.poll_list);
-	if (!list_empty(&msta_link->rc_list))
-		list_del_init(&msta_link->rc_list);
-	spin_unlock_bh(&mdev->sta_poll_lock);
-
-	mt76_wcid_cleanup(mdev, &msta_link->wcid);
-	mt76_wcid_mask_clear(mdev->wcid_mask, idx);
+	mt7996_mac_sta_remove_links(dev, sta, links);
 	mphy->num_sta--;
 
 	mutex_unlock(&mdev->mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 117a9e6c49645e847c579d15809bb5553a64ccfd..cf37baa91a8ba1cfafb07a4166aed0a0e84968fa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -204,10 +204,14 @@ struct mt7996_sta_link {
 		u8 flowid_mask;
 		struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
 	} twt;
+
+	struct rcu_head rcu_head;
 };
 
 struct mt7996_sta {
 	struct mt7996_sta_link deflink; /* must be first */
+	struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+	u8 deflink_id;
 
 	struct mt7996_vif *vif;
 };

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:07 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:07 +0100
Subject: [PATCH v2 08/13] wifi: mt76: mt7996: Add
 mt7996_mac_sta_change_links callback
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-8-31df6972519b@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Intrdouce mt7996_mac_sta_change_links routine to set change_sta_links
required by mac80211. This is a preliminary patch to introduce MLO
support for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 1bca444d2d02333cabd31ba2c8565769a42ab581..307c68c6b0cd7c3acdbfd7be78a007a66d3183bf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -952,6 +952,26 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	return err;
 }
 
+static int
+mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta, u16 old_links,
+			    u16 new_links)
+{
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	unsigned long add = new_links & ~old_links;
+	unsigned long rem = old_links & ~new_links;
+	int ret;
+
+	mutex_lock(&dev->mt76.mutex);
+
+	mt7996_mac_sta_remove_links(dev, sta, rem);
+	ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
+
+	mutex_unlock(&dev->mt76.mutex);
+
+	return ret;
+}
+
 static int
 mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 		   struct ieee80211_sta *sta)
@@ -1921,4 +1941,5 @@ const struct ieee80211_ops mt7996_ops = {
 	.net_setup_tc = mt76_wed_net_setup_tc,
 #endif
 	.change_vif_links = mt7996_change_vif_links,
+	.change_sta_links = mt7996_mac_sta_change_links,
 };

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:08 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:08 +0100
Subject: [PATCH v2 09/13] wifi: mt76: mt7996: Support MLO in
 mt7996_mac_sta_event()
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-9-31df6972519b@kernel.org>

Similar to mt7996_mac_sta_add() adn mt7996_mac_sta_remove(), update
mt7996_mac_sta_event routine to take into account MLO support.
Please note mcu routines does not support MLO yet.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 69 ++++++++++++++----------
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 307c68c6b0cd7c3acdbfd7be78a007a66d3183bf..6d323b5e4e8076ca963e585c12dc656dc5ec3fdb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1001,41 +1001,52 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		     struct ieee80211_sta *sta, enum mt76_sta_event ev)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_vif_link *link = &mvif->deflink;
-	int i, ret;
-
-	switch (ev) {
-	case MT76_STA_EVENT_ASSOC:
-		ret = mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
-					 CONN_STATE_CONNECT, true);
-		if (ret)
-			return ret;
-
-		ret = mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
-		if (ret)
-			return ret;
+	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
-		msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
-		msta_link->wcid.sta = 1;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
+		int i, err;
 
-		return 0;
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
 
-	case MT76_STA_EVENT_AUTHORIZE:
-		return mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
-					  CONN_STATE_PORT_SECURE, false);
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
 
-	case MT76_STA_EVENT_DISASSOC:
-		for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++)
-			mt7996_mac_twt_teardown_flow(dev, msta, i);
+		switch (ev) {
+		case MT76_STA_EVENT_ASSOC:
+			err = mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
+						 CONN_STATE_CONNECT, true);
+			if (err)
+				return err;
 
-		mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
-				   CONN_STATE_DISCONNECT, false);
-		msta_link->wcid.sta_disabled = 1;
-		msta_link->wcid.sta = 0;
+			err = mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
+			if (err)
+				return err;
 
-		return 0;
+			msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+			msta_link->wcid.sta = 1;
+			break;
+		case MT76_STA_EVENT_AUTHORIZE:
+			err = mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
+						 CONN_STATE_PORT_SECURE, false);
+			if (err)
+				return err;
+			break;
+		case MT76_STA_EVENT_DISASSOC:
+			for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++)
+				mt7996_mac_twt_teardown_flow(dev, msta, i);
+
+			mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
+					   CONN_STATE_DISCONNECT, false);
+			msta_link->wcid.sta_disabled = 1;
+			msta_link->wcid.sta = 0;
+			break;
+		}
 	}
 
 	return 0;

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:09 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:09 +0100
Subject: [PATCH v2 10/13] wifi: mt76: Check link_conf pointer in
 mt76_connac_mcu_sta_basic_tlv()
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-10-31df6972519b@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

This is a preliminary patch to introduce MLO support for MT7996 driver.

Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index d0e49d68c5dbf0ed4eab084d9c6f1cad230bed93..bafcf5a279e23ff007d9052301cd2f6b899c491e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -391,7 +391,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
 		basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);
 
 		if (vif->type == NL80211_IFTYPE_STATION &&
-		    !is_zero_ether_addr(link_conf->bssid)) {
+		    link_conf && !is_zero_ether_addr(link_conf->bssid)) {
 			memcpy(basic->peer_addr, link_conf->bssid, ETH_ALEN);
 			basic->aid = cpu_to_le16(vif->cfg.aid);
 		} else {

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:10 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:10 +0100
Subject: [PATCH v2 11/13] wifi: mt76: mt7996: Update mt7996_mcu_add_sta to
 MLO support
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-11-31df6972519b@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Update mt7996_mcu_add_sta routine and all the called subroutines to
support MLO. This is a preliminary patch to enable MLO for MT7996
driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  72 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 296 +++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |   9 +-
 3 files changed, 208 insertions(+), 169 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 6d323b5e4e8076ca963e585c12dc656dc5ec3fdb..5ab4f08dba06fdf95ee4e6bc0261749016f07e6a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -293,7 +293,8 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	 * interface, since firmware only records BSSID when the entry is new
 	 */
 	if (vif->type != NL80211_IFTYPE_STATION)
-		mt7996_mcu_add_sta(dev, vif, mlink, NULL, CONN_STATE_PORT_SECURE, true);
+		mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
+				   CONN_STATE_PORT_SECURE, true);
 	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
 
 	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, link);
@@ -311,7 +312,8 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	struct mt7996_dev *dev = phy->dev;
 	int idx = msta_link->wcid.idx;
 
-	mt7996_mcu_add_sta(dev, vif, mlink, NULL, CONN_STATE_DISCONNECT, false);
+	mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
+			   CONN_STATE_DISCONNECT, false);
 	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, false);
 
 	mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
@@ -703,7 +705,7 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
 						&link->mt76, true);
-			mt7996_mcu_add_sta(dev, vif, &link->mt76, NULL,
+			mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
 					   CONN_STATE_PORT_SECURE,
 					   !!(changed & BSS_CHANGED_BSSID));
 		}
@@ -717,17 +719,17 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			 struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt76_vif_link *mvif;
+	struct mt7996_vif_link *link;
 	struct mt7996_phy *phy;
 	struct mt76_phy *mphy;
 
 	mutex_lock(&dev->mt76.mutex);
 
-	mvif = mt76_vif_conf_link(&dev->mt76, vif, info);
-	if (!mvif)
+	link = mt7996_vif_conf_link(dev, vif, info);
+	if (!link)
 		goto out;
 
-	mphy = mt76_vif_link_phy(mvif);
+	mphy = mt76_vif_link_phy(&link->mt76);
 	if (!mphy)
 		goto out;
 
@@ -738,8 +740,9 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	 */
 	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
 	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
-		mt7996_mcu_add_bss_info(phy, vif, info, mvif, true);
-		mt7996_mcu_add_sta(dev, vif, mvif, NULL, CONN_STATE_PORT_SECURE,
+		mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76, true);
+		mt7996_mcu_add_sta(dev, info, NULL, link, NULL,
+				   CONN_STATE_PORT_SECURE,
 				   !!(changed & BSS_CHANGED_BSSID));
 	}
 
@@ -756,11 +759,11 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	}
 
 	if (changed & BSS_CHANGED_MCAST_RATE)
-		mvif->mcast_rates_idx =
+		link->mt76.mcast_rates_idx =
 			mt7996_get_rates_table(phy, info, false, true);
 
 	if (changed & BSS_CHANGED_BASIC_RATES)
-		mvif->basic_rates_idx =
+		link->mt76.basic_rates_idx =
 			mt7996_get_rates_table(phy, info, false, false);
 
 	/* ensure that enable txcmd_mode after bss_info */
@@ -772,15 +775,15 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
 		if ((vif->type == NL80211_IFTYPE_AP &&
-		    mvif->omac_idx <= HW_BSSID_MAX) ||
+		    link->mt76.omac_idx <= HW_BSSID_MAX) ||
 		   vif->type == NL80211_IFTYPE_STATION)
-			mt7996_mcu_update_bss_color(dev, mvif,
+			mt7996_mcu_update_bss_color(dev, &link->mt76,
 						    &info->he_bss_color);
 	}
 
 	if (changed & (BSS_CHANGED_BEACON |
 		       BSS_CHANGED_BEACON_ENABLED)) {
-		mvif->beacon_rates_idx =
+		link->mt76.beacon_rates_idx =
 			mt7996_get_rates_table(phy, info, true, false);
 
 		mt7996_mcu_add_beacon(hw, vif, info);
@@ -816,10 +819,12 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
 }
 
 static int
-mt7996_mac_sta_init_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			 struct mt7996_vif_link *link,
-			 struct ieee80211_sta *sta, unsigned int link_id)
+mt7996_mac_sta_init_link(struct mt7996_dev *dev,
+			 struct ieee80211_bss_conf *link_conf,
+			 struct ieee80211_link_sta *link_sta,
+			 struct mt7996_vif_link *link, unsigned int link_id)
 {
+	struct ieee80211_sta *sta = link_sta->sta;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_phy *phy = link->phy;
 	struct mt7996_sta_link *msta_link;
@@ -863,8 +868,8 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	rcu_assign_pointer(msta->link[link_id], msta_link);
 
 	mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-	mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
-			   true);
+	mt7996_mcu_add_sta(dev, link_conf, link_sta, link, msta_link,
+			   CONN_STATE_DISCONNECT, true);
 
 	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
 	mt76_wcid_init(&msta_link->wcid, phy->mt76->band_idx);
@@ -930,16 +935,27 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	int err;
 
 	for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct ieee80211_bss_conf *link_conf;
+		struct ieee80211_link_sta *link_sta;
 		struct mt7996_vif_link *link;
 
 		if (rcu_access_pointer(msta->link[link_id]))
 			continue;
 
+		link_conf = link_conf_dereference_protected(vif, link_id);
+		if (!link_conf)
+			goto error_unlink;
+
 		link = mt7996_vif_link(dev, vif, link_id);
 		if (!link)
 			goto error_unlink;
 
-		err = mt7996_mac_sta_init_link(dev, vif, link, sta, link_id);
+		link_sta = link_sta_dereference_protected(sta, link_id);
+		if (!link_sta)
+			goto error_unlink;
+
+		err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
+					       link_id);
 		if (err)
 			goto error_unlink;
 	}
@@ -1005,10 +1021,15 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	unsigned int link_id;
 
 	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct ieee80211_bss_conf *link_conf;
 		struct mt7996_sta_link *msta_link;
 		struct mt7996_vif_link *link;
 		int i, err;
 
+		link_conf = link_conf_dereference_protected(vif, link_id);
+		if (!link_conf)
+			continue;
+
 		link = mt7996_vif_link(dev, vif, link_id);
 		if (!link)
 			continue;
@@ -1019,7 +1040,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 
 		switch (ev) {
 		case MT76_STA_EVENT_ASSOC:
-			err = mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
+			err = mt7996_mcu_add_sta(dev, link_conf, link_sta,
+						 link, msta_link,
 						 CONN_STATE_CONNECT, true);
 			if (err)
 				return err;
@@ -1032,7 +1054,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			msta_link->wcid.sta = 1;
 			break;
 		case MT76_STA_EVENT_AUTHORIZE:
-			err = mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
+			err = mt7996_mcu_add_sta(dev, link_conf, link_sta,
+						 link, msta_link,
 						 CONN_STATE_PORT_SECURE, false);
 			if (err)
 				return err;
@@ -1041,8 +1064,9 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++)
 				mt7996_mac_twt_teardown_flow(dev, msta, i);
 
-			mt7996_mcu_add_sta(dev, vif, &link->mt76, sta,
-					   CONN_STATE_DISCONNECT, false);
+			mt7996_mcu_add_sta(dev, link_conf, link_sta, link,
+					   msta_link, CONN_STATE_DISCONNECT,
+					   false);
 			msta_link->wcid.sta_disabled = 1;
 			msta_link->wcid.sta = 0;
 			break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 9018ede6efed49241205ddc042f3df149cd58530..43e85308132e5ed80d8199858014b31a29b2e3b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -118,13 +118,13 @@ mt7996_mcu_get_sta_nss(u16 mcs_map)
 }
 
 static void
-mt7996_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
-			  u16 mcs_map)
+mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta,
+			  struct mt7996_vif_link *link,
+			  __le16 *he_mcs, u16 mcs_map)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	enum nl80211_band band = msta->vif->deflink.phy->mt76->chandef.chan->band;
-	const u16 *mask = msta->vif->deflink.bitrate_mask.control[band].he_mcs;
-	int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
+	int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
+	enum nl80211_band band = link->phy->mt76->chandef.chan->band;
+	const u16 *mask = link->bitrate_mask.control[band].he_mcs;
 
 	for (nss = 0; nss < max_nss; nss++) {
 		int mcs;
@@ -1182,15 +1182,17 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
 }
 
 static void
-mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+mt7996_mcu_sta_he_tlv(struct sk_buff *skb,
+		      struct ieee80211_link_sta *link_sta,
+		      struct mt7996_vif_link *link)
 {
-	struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
+	struct ieee80211_he_cap_elem *elem = &link_sta->he_cap.he_cap_elem;
 	struct ieee80211_he_mcs_nss_supp mcs_map;
 	struct sta_rec_he_v2 *he;
 	struct tlv *tlv;
 	int i = 0;
 
-	if (!sta->deflink.he_cap.has_he)
+	if (!link_sta->he_cap.has_he)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_V2, sizeof(*he));
@@ -1202,21 +1204,21 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 		he->he_phy_cap[i] = elem->phy_cap_info[i];
 	}
 
-	mcs_map = sta->deflink.he_cap.he_mcs_nss_supp;
-	switch (sta->deflink.bandwidth) {
+	mcs_map = link_sta->he_cap.he_mcs_nss_supp;
+	switch (link_sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_160:
 		if (elem->phy_cap_info[0] &
 		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-			mt7996_mcu_set_sta_he_mcs(sta,
+			mt7996_mcu_set_sta_he_mcs(link_sta, link,
 						  &he->max_nss_mcs[CMD_HE_MCS_BW8080],
 						  le16_to_cpu(mcs_map.rx_mcs_80p80));
 
-		mt7996_mcu_set_sta_he_mcs(sta,
+		mt7996_mcu_set_sta_he_mcs(link_sta, link,
 					  &he->max_nss_mcs[CMD_HE_MCS_BW160],
 					  le16_to_cpu(mcs_map.rx_mcs_160));
 		fallthrough;
 	default:
-		mt7996_mcu_set_sta_he_mcs(sta,
+		mt7996_mcu_set_sta_he_mcs(link_sta, link,
 					  &he->max_nss_mcs[CMD_HE_MCS_BW80],
 					  le16_to_cpu(mcs_map.rx_mcs_80));
 		break;
@@ -1226,24 +1228,26 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 }
 
 static void
-mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb,
+			 struct ieee80211_link_sta *link_sta)
 {
 	struct sta_rec_he_6g_capa *he_6g;
 	struct tlv *tlv;
 
-	if (!sta->deflink.he_6ghz_capa.capa)
+	if (!link_sta->he_6ghz_capa.capa)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G, sizeof(*he_6g));
 
 	he_6g = (struct sta_rec_he_6g_capa *)tlv;
-	he_6g->capa = sta->deflink.he_6ghz_capa.capa;
+	he_6g->capa = link_sta->he_6ghz_capa.capa;
 }
 
 static void
-mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+mt7996_mcu_sta_eht_tlv(struct sk_buff *skb,
+		       struct ieee80211_link_sta *link_sta)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv;
 	struct ieee80211_vif *vif = container_of((void *)msta->vif,
 						 struct ieee80211_vif, drv_priv);
 	struct ieee80211_eht_mcs_nss_supp *mcs_map;
@@ -1251,11 +1255,11 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 	struct sta_rec_eht *eht;
 	struct tlv *tlv;
 
-	if (!sta->deflink.eht_cap.has_eht)
+	if (!link_sta->eht_cap.has_eht)
 		return;
 
-	mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp;
-	elem = &sta->deflink.eht_cap.eht_cap_elem;
+	mcs_map = &link_sta->eht_cap.eht_mcs_nss_supp;
+	elem = &link_sta->eht_cap.eht_cap_elem;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht));
 
@@ -1266,7 +1270,7 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 	eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]);
 
 	if (vif->type != NL80211_IFTYPE_STATION &&
-	    (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+	    (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
 	     (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
 	      IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
 	      IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
@@ -1282,48 +1286,48 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 }
 
 static void
-mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
 {
 	struct sta_rec_ht_uni *ht;
 	struct tlv *tlv;
 
-	if (!sta->deflink.ht_cap.ht_supported)
+	if (!link_sta->ht_cap.ht_supported)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
 
 	ht = (struct sta_rec_ht_uni *)tlv;
-	ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);
-	ht->ampdu_param = u8_encode_bits(sta->deflink.ht_cap.ampdu_factor,
+	ht->ht_cap = cpu_to_le16(link_sta->ht_cap.cap);
+	ht->ampdu_param = u8_encode_bits(link_sta->ht_cap.ampdu_factor,
 					 IEEE80211_HT_AMPDU_PARM_FACTOR) |
-			  u8_encode_bits(sta->deflink.ht_cap.ampdu_density,
+			  u8_encode_bits(link_sta->ht_cap.ampdu_density,
 					 IEEE80211_HT_AMPDU_PARM_DENSITY);
 }
 
 static void
-mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
 {
 	struct sta_rec_vht *vht;
 	struct tlv *tlv;
 
 	/* For 6G band, this tlv is necessary to let hw work normally */
-	if (!sta->deflink.he_6ghz_capa.capa && !sta->deflink.vht_cap.vht_supported)
+	if (!link_sta->he_6ghz_capa.capa && !link_sta->vht_cap.vht_supported)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
 
 	vht = (struct sta_rec_vht *)tlv;
-	vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);
-	vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
-	vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
+	vht->vht_cap = cpu_to_le32(link_sta->vht_cap.cap);
+	vht->vht_rx_mcs_map = link_sta->vht_cap.vht_mcs.rx_mcs_map;
+	vht->vht_tx_mcs_map = link_sta->vht_cap.vht_mcs.tx_mcs_map;
 }
 
 static void
 mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
-			 struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			 struct ieee80211_vif *vif,
+			 struct ieee80211_link_sta *link_sta,
+			 struct mt7996_sta_link *msta_link)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sta_rec_amsdu *amsdu;
 	struct tlv *tlv;
 
@@ -1332,7 +1336,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	    vif->type != NL80211_IFTYPE_AP)
 		return;
 
-	if (!sta->deflink.agg.max_amsdu_len)
+	if (!link_sta->agg.max_amsdu_len)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));
@@ -1341,7 +1345,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	amsdu->amsdu_en = true;
 	msta_link->wcid.amsdu = true;
 
-	switch (sta->deflink.agg.max_amsdu_len) {
+	switch (link_sta->agg.max_amsdu_len) {
 	case IEEE80211_MAX_MPDU_LEN_VHT_11454:
 		amsdu->max_mpdu_size =
 			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
@@ -1358,30 +1362,31 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 
 static void
 mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
-			struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			struct ieee80211_bss_conf *link_conf,
+			struct ieee80211_link_sta *link_sta)
 {
-	struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
+	struct ieee80211_he_cap_elem *elem = &link_sta->he_cap.he_cap_elem;
 	struct sta_rec_muru *muru;
 	struct tlv *tlv;
 
-	if (vif->type != NL80211_IFTYPE_STATION &&
-	    vif->type != NL80211_IFTYPE_AP)
+	if (link_conf->vif->type != NL80211_IFTYPE_STATION &&
+	    link_conf->vif->type != NL80211_IFTYPE_AP)
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
 
 	muru = (struct sta_rec_muru *)tlv;
-	muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
-			       vif->bss_conf.he_mu_beamformer ||
-			       vif->bss_conf.vht_mu_beamformer ||
-			       vif->bss_conf.vht_mu_beamformee;
+	muru->cfg.mimo_dl_en = link_conf->eht_mu_beamformer ||
+			       link_conf->he_mu_beamformer ||
+			       link_conf->vht_mu_beamformer ||
+			       link_conf->vht_mu_beamformee;
 	muru->cfg.ofdma_dl_en = true;
 
-	if (sta->deflink.vht_cap.vht_supported)
+	if (link_sta->vht_cap.vht_supported)
 		muru->mimo_dl.vht_mu_bfee =
-			!!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+			!!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
 
-	if (!sta->deflink.he_cap.has_he)
+	if (!link_sta->he_cap.has_he)
 		return;
 
 	muru->mimo_dl.partial_bw_dl_mimo =
@@ -1412,49 +1417,50 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 }
 
 static inline bool
-mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
-			struct ieee80211_sta *sta, bool bfee)
+mt7996_is_ebf_supported(struct mt7996_phy *phy,
+			struct ieee80211_bss_conf *link_conf,
+			struct ieee80211_link_sta *link_sta, bool bfee)
 {
 	int sts = hweight16(phy->mt76->chainmask);
 
-	if (vif->type != NL80211_IFTYPE_STATION &&
-	    vif->type != NL80211_IFTYPE_AP)
+	if (link_conf->vif->type != NL80211_IFTYPE_STATION &&
+	    link_conf->vif->type != NL80211_IFTYPE_AP)
 		return false;
 
 	if (!bfee && sts < 2)
 		return false;
 
-	if (sta->deflink.eht_cap.has_eht) {
-		struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap;
+	if (link_sta->eht_cap.has_eht) {
+		struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap;
 		struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
 
 		if (bfee)
-			return vif->bss_conf.eht_su_beamformee &&
+			return link_conf->eht_su_beamformee &&
 			       EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
 		else
-			return vif->bss_conf.eht_su_beamformer &&
+			return link_conf->eht_su_beamformer &&
 			       EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
 	}
 
-	if (sta->deflink.he_cap.has_he) {
-		struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
+	if (link_sta->he_cap.has_he) {
+		struct ieee80211_he_cap_elem *pe = &link_sta->he_cap.he_cap_elem;
 
 		if (bfee)
-			return vif->bss_conf.he_su_beamformee &&
+			return link_conf->he_su_beamformee &&
 			       HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
 		else
-			return vif->bss_conf.he_su_beamformer &&
+			return link_conf->he_su_beamformer &&
 			       HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
 	}
 
-	if (sta->deflink.vht_cap.vht_supported) {
-		u32 cap = sta->deflink.vht_cap.cap;
+	if (link_sta->vht_cap.vht_supported) {
+		u32 cap = link_sta->vht_cap.cap;
 
 		if (bfee)
-			return vif->bss_conf.vht_su_beamformee &&
+			return link_conf->vht_su_beamformee &&
 			       (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
 		else
-			return vif->bss_conf.vht_su_beamformer &&
+			return link_conf->vht_su_beamformer &&
 			       (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
 	}
 
@@ -1475,10 +1481,11 @@ mt7996_mcu_sta_sounding_rate(struct sta_rec_bf *bf, struct mt7996_phy *phy)
 }
 
 static void
-mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy,
-		       struct sta_rec_bf *bf, bool explicit)
+mt7996_mcu_sta_bfer_ht(struct ieee80211_link_sta *link_sta,
+		       struct mt7996_phy *phy, struct sta_rec_bf *bf,
+		       bool explicit)
 {
-	struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs;
+	struct ieee80211_mcs_info *mcs = &link_sta->ht_cap.mcs;
 	u8 n = 0;
 
 	bf->tx_mode = MT_PHY_TYPE_HT;
@@ -1501,10 +1508,11 @@ mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy,
 }
 
 static void
-mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy,
-			struct sta_rec_bf *bf, bool explicit)
+mt7996_mcu_sta_bfer_vht(struct ieee80211_link_sta *link_sta,
+			struct mt7996_phy *phy, struct sta_rec_bf *bf,
+			bool explicit)
 {
-	struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;
+	struct ieee80211_sta_vht_cap *pc = &link_sta->vht_cap;
 	struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap;
 	u16 mcs_map = le16_to_cpu(pc->vht_mcs.rx_mcs_map);
 	u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map);
@@ -1525,24 +1533,24 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy,
 		bf->ncol = min_t(u8, nss_mcs, bf->nrow);
 		bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, bf->ncol);
 
-		if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
+		if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
 			bf->nrow = 1;
 	} else {
 		bf->nrow = tx_ant;
 		bf->ncol = min_t(u8, nss_mcs, bf->nrow);
 		bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, nss_mcs);
 
-		if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
+		if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
 			bf->ibf_nrow = 1;
 	}
 }
 
 static void
-mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
-		       struct mt7996_phy *phy, struct sta_rec_bf *bf,
-		       bool explicit)
+mt7996_mcu_sta_bfer_he(struct ieee80211_link_sta *link_sta,
+		       struct ieee80211_vif *vif, struct mt7996_phy *phy,
+		       struct sta_rec_bf *bf, bool explicit)
 {
-	struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;
+	struct ieee80211_sta_he_cap *pc = &link_sta->he_cap;
 	struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
 	const struct ieee80211_sta_he_cap *vc =
 		mt76_connac_get_he_phy_cap(phy->mt76, vif);
@@ -1571,7 +1579,7 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
 	bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) :
 				  min_t(u8, MT7996_IBF_MAX_NC, nss_mcs);
 
-	if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160)
+	if (link_sta->bandwidth != IEEE80211_STA_RX_BW_160)
 		return;
 
 	/* go over for 160MHz and 80p80 */
@@ -1603,11 +1611,11 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
 }
 
 static void
-mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
-			struct mt7996_phy *phy, struct sta_rec_bf *bf,
-			bool explicit)
+mt7996_mcu_sta_bfer_eht(struct ieee80211_link_sta *link_sta,
+			struct ieee80211_vif *vif, struct mt7996_phy *phy,
+			struct sta_rec_bf *bf, bool explicit)
 {
-	struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap;
+	struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap;
 	struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
 	struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp;
 	const struct ieee80211_sta_eht_cap *vc =
@@ -1631,10 +1639,10 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
 	bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) :
 				  min_t(u8, MT7996_IBF_MAX_NC, nss_mcs);
 
-	if (sta->deflink.bandwidth < IEEE80211_STA_RX_BW_160)
+	if (link_sta->bandwidth < IEEE80211_STA_RX_BW_160)
 		return;
 
-	switch (sta->deflink.bandwidth) {
+	switch (link_sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_160:
 		snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_160MHZ_MASK, ve->phy_cap_info[2]);
 		sts = EHT_PHY(CAP1_BEAMFORMEE_SS_160MHZ_MASK, pe->phy_cap_info[1]);
@@ -1662,13 +1670,15 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
 
 static void
 mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
-			struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			struct ieee80211_bss_conf *link_conf,
+			struct ieee80211_link_sta *link_sta,
+			struct mt7996_vif_link *link)
 {
 #define EBF_MODE	BIT(0)
 #define IBF_MODE	BIT(1)
 #define BF_MAT_ORDER	4
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_phy *phy = mvif->deflink.phy;
+	struct ieee80211_vif *vif = link_conf->vif;
+	struct mt7996_phy *phy = link->phy;
 	int tx_ant = hweight16(phy->mt76->chainmask) - 1;
 	struct sta_rec_bf *bf;
 	struct tlv *tlv;
@@ -1680,10 +1690,10 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	};
 	bool ebf;
 
-	if (!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
+	if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
 		return;
 
-	ebf = mt7996_is_ebf_supported(phy, vif, sta, false);
+	ebf = mt7996_is_ebf_supported(phy, link_conf, link_sta, false);
 	if (!ebf && !dev->ibf)
 		return;
 
@@ -1694,28 +1704,29 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	 * vht: support eBF and iBF
 	 * ht: iBF only, since mac80211 lacks of eBF support
 	 */
-	if (sta->deflink.eht_cap.has_eht)
-		mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf, ebf);
-	else if (sta->deflink.he_cap.has_he)
-		mt7996_mcu_sta_bfer_he(sta, vif, phy, bf, ebf);
-	else if (sta->deflink.vht_cap.vht_supported)
-		mt7996_mcu_sta_bfer_vht(sta, phy, bf, ebf);
-	else if (sta->deflink.ht_cap.ht_supported)
-		mt7996_mcu_sta_bfer_ht(sta, phy, bf, ebf);
+	if (link_sta->eht_cap.has_eht)
+		mt7996_mcu_sta_bfer_eht(link_sta, vif, link->phy, bf, ebf);
+	else if (link_sta->he_cap.has_he)
+		mt7996_mcu_sta_bfer_he(link_sta, vif, link->phy, bf, ebf);
+	else if (link_sta->vht_cap.vht_supported)
+		mt7996_mcu_sta_bfer_vht(link_sta, link->phy, bf, ebf);
+	else if (link_sta->ht_cap.ht_supported)
+		mt7996_mcu_sta_bfer_ht(link_sta, link->phy, bf, ebf);
 	else
 		return;
 
 	bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0);
 	if (is_mt7992(&dev->mt76) && tx_ant == 4)
 		bf->bf_cap |= IBF_MODE;
-	bf->bw = sta->deflink.bandwidth;
-	bf->ibf_dbw = sta->deflink.bandwidth;
+
+	bf->bw = link_sta->bandwidth;
+	bf->ibf_dbw = link_sta->bandwidth;
 	bf->ibf_nrow = tx_ant;
 
-	if (sta->deflink.eht_cap.has_eht || sta->deflink.he_cap.has_he)
+	if (link_sta->eht_cap.has_eht || link_sta->he_cap.has_he)
 		bf->ibf_timeout = is_mt7996(&dev->mt76) ? MT7996_IBF_TIMEOUT :
 							  MT7992_IBF_TIMEOUT;
-	else if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol)
+	else if (!ebf && link_sta->bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol)
 		bf->ibf_timeout = MT7996_IBF_TIMEOUT_LEGACY;
 	else
 		bf->ibf_timeout = MT7996_IBF_TIMEOUT;
@@ -1729,7 +1740,7 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 				      matrix[bf->nrow][bf->ncol] : 0;
 	}
 
-	switch (sta->deflink.bandwidth) {
+	switch (link_sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_160:
 	case IEEE80211_STA_RX_BW_80:
 		bf->mem_total = bf->mem_20m * 2;
@@ -1745,31 +1756,32 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 
 static void
 mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
-			struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			struct ieee80211_bss_conf *link_conf,
+			struct ieee80211_link_sta *link_sta,
+			struct mt7996_vif_link *link)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_phy *phy = mvif->deflink.phy;
+	struct mt7996_phy *phy = link->phy;
 	int tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
 	struct sta_rec_bfee *bfee;
 	struct tlv *tlv;
 	u8 nrow = 0;
 
-	if (!(sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he))
+	if (!(link_sta->vht_cap.vht_supported || link_sta->he_cap.has_he))
 		return;
 
-	if (!mt7996_is_ebf_supported(phy, vif, sta, true))
+	if (!mt7996_is_ebf_supported(phy, link_conf, link_sta, true))
 		return;
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee));
 	bfee = (struct sta_rec_bfee *)tlv;
 
-	if (sta->deflink.he_cap.has_he) {
-		struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
+	if (link_sta->he_cap.has_he) {
+		struct ieee80211_he_cap_elem *pe = &link_sta->he_cap.he_cap_elem;
 
 		nrow = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
 			      pe->phy_cap_info[5]);
-	} else if (sta->deflink.vht_cap.vht_supported) {
-		struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;
+	} else if (link_sta->vht_cap.vht_supported) {
+		struct ieee80211_sta_vht_cap *pc = &link_sta->vht_cap;
 
 		nrow = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
 				 pc->cap);
@@ -2131,7 +2143,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	 * update sta_rec_he here.
 	 */
 	if (changed)
-		mt7996_mcu_sta_he_tlv(skb, sta);
+		mt7996_mcu_sta_he_tlv(skb, &sta->deflink, &mvif->deflink);
 
 	/* sta_rec_ra accommodates BW, NSS and only MCS range format
 	 * i.e 0-{7,8,9} for VHT.
@@ -2179,67 +2191,67 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				 sizeof(req), true);
 }
 
-int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-		       struct mt76_vif_link *mlink,
-		       struct ieee80211_sta *sta, int conn_state, bool newly)
+int mt7996_mcu_add_sta(struct mt7996_dev *dev,
+		       struct ieee80211_bss_conf *link_conf,
+		       struct ieee80211_link_sta *link_sta,
+		       struct mt7996_vif_link *link,
+		       struct mt7996_sta_link *msta_link,
+		       int conn_state, bool newly)
 {
-	struct ieee80211_link_sta *link_sta = NULL;
-	struct mt76_wcid *wcid = mlink->wcid;
+	struct mt76_wcid *wcid = msta_link ? &msta_link->wcid : link->mt76.wcid;
+	struct ieee80211_sta *sta = link_sta ? link_sta->sta : NULL;
 	struct sk_buff *skb;
 	int ret;
 
-	if (sta) {
-		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-		struct mt7996_sta_link *msta_link = &msta->deflink;
-
-		wcid = &msta_link->wcid;
-		link_sta = &sta->deflink;
-	}
-
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mlink, wcid,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
 	/* starec basic */
-	mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, &vif->bss_conf, link_sta,
+	mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, link_conf, link_sta,
 				      conn_state, newly);
 
 	if (conn_state == CONN_STATE_DISCONNECT)
 		goto out;
 
 	/* starec hdr trans */
-	mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, wcid);
+	mt7996_mcu_sta_hdr_trans_tlv(dev, skb, link_conf->vif, wcid);
 	/* starec tx proc */
 	mt7996_mcu_sta_tx_proc_tlv(skb);
 
 	/* tag order is in accordance with firmware dependency. */
-	if (sta) {
+	if (link_sta) {
 		/* starec hdrt mode */
 		mt7996_mcu_sta_hdrt_tlv(dev, skb);
-		/* starec bfer */
-		mt7996_mcu_sta_bfer_tlv(dev, skb, vif, sta);
+		if (conn_state == CONN_STATE_CONNECT) {
+			/* starec bfer */
+			mt7996_mcu_sta_bfer_tlv(dev, skb, link_conf, link_sta,
+						link);
+			/* starec bfee */
+			mt7996_mcu_sta_bfee_tlv(dev, skb, link_conf, link_sta,
+						link);
+		}
 		/* starec ht */
-		mt7996_mcu_sta_ht_tlv(skb, sta);
+		mt7996_mcu_sta_ht_tlv(skb, link_sta);
 		/* starec vht */
-		mt7996_mcu_sta_vht_tlv(skb, sta);
+		mt7996_mcu_sta_vht_tlv(skb, link_sta);
 		/* starec uapsd */
-		mt76_connac_mcu_sta_uapsd(skb, vif, sta);
+		mt76_connac_mcu_sta_uapsd(skb, link_conf->vif, sta);
 		/* starec amsdu */
-		mt7996_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
+		mt7996_mcu_sta_amsdu_tlv(dev, skb, link_conf->vif, link_sta,
+					 msta_link);
 		/* starec he */
-		mt7996_mcu_sta_he_tlv(skb, sta);
+		mt7996_mcu_sta_he_tlv(skb, link_sta, link);
 		/* starec he 6g*/
-		mt7996_mcu_sta_he_6g_tlv(skb, sta);
+		mt7996_mcu_sta_he_6g_tlv(skb, link_sta);
 		/* starec eht */
-		mt7996_mcu_sta_eht_tlv(skb, sta);
+		mt7996_mcu_sta_eht_tlv(skb, link_sta);
 		/* starec muru */
-		mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta);
-		/* starec bfee */
-		mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
+		mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta);
 	}
 
-	ret = mt7996_mcu_add_group(dev, vif, sta);
+	ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
 	if (ret) {
 		dev_kfree_skb(skb);
 		return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index cf37baa91a8ba1cfafb07a4166aed0a0e84968fa..0dd9d798541f95f82bf8606512052eca79115f5c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -572,9 +572,12 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_bss_conf *link_conf,
 			    struct mt76_vif_link *mlink, int enable);
-int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-		       struct mt76_vif_link *mlink,
-		       struct ieee80211_sta *sta, int conn_state, bool newly);
+int mt7996_mcu_add_sta(struct mt7996_dev *dev,
+		       struct ieee80211_bss_conf *link_conf,
+		       struct ieee80211_link_sta *link_sta,
+		       struct mt7996_vif_link *link,
+		       struct mt7996_sta_link *msta_link,
+		       int conn_state, bool newly);
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
 			 bool add);

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:11 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:11 +0100
Subject: [PATCH v2 12/13] wifi: mt76: mt7996: Rely on mt7996_vif_link in
 mt7996_mcu_twt_agrt_update signature
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-12-31df6972519b@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 5 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 8 ++++----
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 456666eb7080c50493dcde61c5399adc6a987d2d..4a7f6fd9025297f0ffa8ea7e91efd34164a26196 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2672,7 +2672,8 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 	}
 	flow->tsf = le64_to_cpu(twt_agrt->twt);
 
-	if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
+	if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow,
+				       MCU_TWT_AGRT_ADD))
 		goto unlock;
 
 	setup_cmd = TWT_SETUP_CMD_ACCEPT;
@@ -2705,7 +2706,7 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
 		return;
 
 	flow = &msta_link->twt.flow[flowid];
-	if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow,
+	if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow,
 				       MCU_TWT_AGRT_DELETE))
 		return;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 43e85308132e5ed80d8199858014b31a29b2e3b5..e6ebb309a8257637c122702df2f2924649b7fabe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -4236,7 +4236,7 @@ int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
 #define TWT_AGRT_PROTECT	BIT(2)
 
 int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
-			       struct mt7996_vif *mvif,
+			       struct mt7996_vif_link *link,
 			       struct mt7996_twt_flow *flow,
 			       int cmd)
 {
@@ -4267,12 +4267,12 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
 		.len = cpu_to_le16(sizeof(req) - 4),
 		.tbl_idx = flow->table_id,
 		.cmd = cmd,
-		.own_mac_idx = mvif->deflink.mt76.omac_idx,
+		.own_mac_idx = link->mt76.omac_idx,
 		.flowid = flow->id,
 		.peer_id = cpu_to_le16(flow->wcid),
 		.duration = flow->duration,
-		.bss = mvif->deflink.mt76.idx,
-		.bss_idx = mvif->deflink.mt76.idx,
+		.bss = link->mt76.idx,
+		.bss_idx = link->mt76.idx,
 		.start_tsf = cpu_to_le64(flow->tsf),
 		.mantissa = flow->mantissa,
 		.exponent = flow->exp,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 0dd9d798541f95f82bf8606512052eca79115f5c..962022c7eec9fd82ebba8e0d5aa6b6eae769ee32 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -563,7 +563,7 @@ int mt7996_run(struct mt7996_phy *phy);
 int mt7996_mcu_init(struct mt7996_dev *dev);
 int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
 int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
-			       struct mt7996_vif *mvif,
+			       struct mt7996_vif_link *link,
 			       struct mt7996_twt_flow *flow,
 			       int cmd);
 int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 11 10:45:12 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 18:45:12 +0100
Subject: [PATCH v2 13/13] wifi: mt76: mt7996: Rely on mt7996_vif_link and
 mt7996_sta_link in mt7996_mac_twt_teardown_flow signature
In-Reply-To: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
References: <20250311-mt7996-mlo-v2-0-31df6972519b@kernel.org>
Message-ID: <20250311-mt7996-mlo-v2-13-31df6972519b@kernel.org>

This is a preliminary patch to enable MLO for MT7996 driver

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 7 +++----
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 7 +++++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 4a7f6fd9025297f0ffa8ea7e91efd34164a26196..7ddd4b0cadf5d1983379a93ba56da461748ca60e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2691,10 +2691,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 }
 
 void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
-				  struct mt7996_sta *msta,
+				  struct mt7996_vif_link *link,
+				  struct mt7996_sta_link *msta_link,
 				  u8 flowid)
 {
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct mt7996_twt_flow *flow;
 
 	lockdep_assert_held(&dev->mt76.mutex);
@@ -2706,8 +2706,7 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
 		return;
 
 	flow = &msta_link->twt.flow[flowid];
-	if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow,
-				       MCU_TWT_AGRT_DELETE))
+	if (mt7996_mcu_twt_agrt_update(dev, link, flow, MCU_TWT_AGRT_DELETE))
 		return;
 
 	list_del_init(&flow->list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 5ab4f08dba06fdf95ee4e6bc0261749016f07e6a..11ad95e05b94857c95375cdf877518e7ee89f08e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1062,7 +1062,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			break;
 		case MT76_STA_EVENT_DISASSOC:
 			for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++)
-				mt7996_mac_twt_teardown_flow(dev, msta, i);
+				mt7996_mac_twt_teardown_flow(dev, link,
+							     msta_link, i);
 
 			mt7996_mcu_add_sta(dev, link_conf, link_sta, link,
 					   msta_link, CONN_STATE_DISCONNECT,
@@ -1804,10 +1805,12 @@ mt7996_twt_teardown_request(struct ieee80211_hw *hw,
 			    u8 flowid)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_vif_link *link = &msta->vif->deflink;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 
 	mutex_lock(&dev->mt76.mutex);
-	mt7996_mac_twt_teardown_flow(dev, msta, flowid);
+	mt7996_mac_twt_teardown_flow(dev, link, msta_link, flowid);
 	mutex_unlock(&dev->mt76.mutex);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 962022c7eec9fd82ebba8e0d5aa6b6eae769ee32..84b9ff707d56501d212932a9fa6a3037259a1077 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -709,7 +709,8 @@ void mt7996_mac_dump_work(struct work_struct *work);
 void mt7996_mac_sta_rc_work(struct work_struct *work);
 void mt7996_mac_update_stats(struct mt7996_phy *phy);
 void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
-				  struct mt7996_sta *msta,
+				  struct mt7996_vif_link *link,
+				  struct mt7996_sta_link *msta_link,
 				  u8 flowid);
 void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 			      struct ieee80211_sta *sta,

-- 
2.48.1



From sboyd at kernel.org  Tue Mar 11 10:50:42 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 11 Mar 2025 10:50:42 -0700
Subject: [GIT PULL] Qualcomm clock fix for v6.14
In-Reply-To: <20250310191142.1208155-1-andersson@kernel.org>
References: <20250310191142.1208155-1-andersson@kernel.org>
Message-ID: <899b71724428aaa16d424f54d5b1558b.sboyd@kernel.org>

Quoting Bjorn Andersson (2025-03-10 12:11:41)
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-clk-fixes-for-6.14
> 
> for you to fetch changes up to 787289a1d13d50ff4ce0f496947f8817ef3fdea9:
> 
>   clk: qcom: dispcc-sm8750: Drop incorrect CLK_SET_RATE_PARENT on byte intf parent (2025-02-26 08:57:46 -0600)
> 
> ----------------------------------------------------------------
> Qualcomm clock fix for v6.14
> 
> Avoid propagating rate changes for the MDSS byte intf clocks on SM8750,
> to avoid changing the already configured clocks.

I already picked this up to clk-fixes a couple weeks ago.


From sboyd at kernel.org  Tue Mar 11 10:55:27 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 11 Mar 2025 10:55:27 -0700
Subject: [GIT PULL] clk: samsung: Fixes for v6.14
In-Reply-To: <20250309175154.6701-1-krzysztof.kozlowski@linaro.org>
References: <20250309175154.6701-1-krzysztof.kozlowski@linaro.org>
Message-ID: <3436f5e74321461507801ce5a405396b.sboyd@kernel.org>

Quoting Krzysztof Kozlowski (2025-03-09 10:51:53)
> Hi,
> 
> Fixes for current RC.
> 
> Best regards,
> Krzysztof
> 
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-clk-fixes-6.14
> 
> for you to fetch changes up to 53517a70873c7a91675f7244768aad5006cc45de:
> 
>   clk: samsung: update PLL locktime for PLL142XX used on FSD platform (2025-03-05 20:13:25 +0100)
> 
> ----------------------------------------------------------------

Thanks. Pulled into clk-fixes


From will at kernel.org  Tue Mar 11 10:55:30 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 17:55:30 +0000
Subject: [PATCH v18 0/5] iommu/arm-smmu: introduction of ACTLR
 implementation for Qualcomm SoCs
In-Reply-To: <173625436399.258197.10961901698600591079.b4-ty@kernel.org>
References: <20241212151402.159102-1-quic_bibekkum@quicinc.com>
 <173625436399.258197.10961901698600591079.b4-ty@kernel.org>
Message-ID: <20250311175528.GA5216@willie-the-truck>

On Tue, Jan 07, 2025 at 04:42:39PM +0000, Will Deacon wrote:
> On Thu, 12 Dec 2024 20:43:57 +0530, Bibek Kumar Patro wrote:
> > This patch series consist of six parts and covers the following:
> > 
> > 1. Provide option to re-enable context caching to retain prefetcher
> >    settings during reset and runtime suspend.
> > 
> > 2. Remove cfg inside qcom_smmu structure and replace it with single
> >    pointer to qcom_smmu_match_data avoiding replication of multiple
> >    members from same.
> > 
> > [...]
> 
> Applied to iommu (arm/smmu/updates), thanks!
> 
> [1/5] iommu/arm-smmu: Re-enable context caching in smmu reset operation
>       https://git.kernel.org/iommu/c/ef4144b1b47d
> [2/5] iommu/arm-smmu: Refactor qcom_smmu structure to include single pointer
>       https://git.kernel.org/iommu/c/445d7a8ed90e
> [3/5] iommu/arm-smmu: Add support for PRR bit setup
>       https://git.kernel.org/iommu/c/7f2ef1bfc758
> [4/5] iommu/arm-smmu: Introduce ACTLR custom prefetcher settings
>       https://git.kernel.org/iommu/c/9fe18d825a58
> [5/5] iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500
>       https://git.kernel.org/iommu/c/3e35c3e725de

Hrm. I'm not seeing any user of the new ->set_prr*_() functions in
linux-next yet. Is there something under review, or should I revert this
for now?

Will


From robh at kernel.org  Tue Mar 11 11:00:25 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 13:00:25 -0500
Subject: [PATCH 1/2] dt-bindings: pinctrl: airoha: Add missing
 gpio-ranges property
In-Reply-To: <20250307-en7581-gpio-range-v1-1-de1262105428@kernel.org>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
 <20250307-en7581-gpio-range-v1-1-de1262105428@kernel.org>
Message-ID: <174171602460.3890634.5672219037612779159.robh@kernel.org>


On Fri, 07 Mar 2025 18:08:19 +0100, Lorenzo Bianconi wrote:
> Introduce leftover gpio-ranges property for Airoha EN7581 pinctrl binding
> 
> Fixes: d0c15cb96b74 ("dt-bindings: pinctrl: airoha: Add EN7581 pinctrl")
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> ---
>  Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From jeff.johnson at oss.qualcomm.com  Tue Mar 11 11:01:09 2025
From: jeff.johnson at oss.qualcomm.com (Jeff Johnson)
Date: Tue, 11 Mar 2025 11:01:09 -0700
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <fcd132af-03e4-496d-ba70-0097e90a83cf@oss.qualcomm.com>

On 2/26/25 15:08, Nuno Das Neves wrote:
...
> +
> +MODULE_AUTHOR("Microsoft");
> +MODULE_LICENSE("GPL");
> +

Since commit 1fffe7a34c89 ("script: modpost: emit a warning when the
description is missing"), a module without a MODULE_DESCRIPTION() will
result in a warning with make W=1. Please add a MODULE_DESCRIPTION()
to avoid this warning.

This is a canned review based upon finding a MODULE_LICENSE without a
MODULE_DESCRIPTION.

/jeff


From christopher.obbard at linaro.org  Tue Mar 11 11:02:56 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Tue, 11 Mar 2025 19:02:56 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
Message-ID: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>

Currently some Qualcomm interconnect drivers are enabled
as modules which isn't overly useful since the interconnects
are required to be loaded during early boot.

Loading the interconnects late (e.g. in initrd or as module)
can cause boot issues, such as slowdown or even not booting
at all (since the interconnect would be required for storage
devices).

Be consistent and enable all of the Qualcomm interconnect
drivers as built-in to the kernel image.

Signed-off-by: Christopher Obbard <christopher.obbard at linaro.org>
---
 arch/arm64/configs/defconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 219ef05ee5a757c43a37ec9f8571ce9976354830..6582baee2ab02ecb2ff442c6e73aa6a23fee8d7f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1656,11 +1656,11 @@ CONFIG_INTERCONNECT_IMX8MN=m
 CONFIG_INTERCONNECT_IMX8MQ=m
 CONFIG_INTERCONNECT_IMX8MP=y
 CONFIG_INTERCONNECT_QCOM=y
-CONFIG_INTERCONNECT_QCOM_MSM8916=m
+CONFIG_INTERCONNECT_QCOM_MSM8916=y
 CONFIG_INTERCONNECT_QCOM_MSM8996=y
-CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+CONFIG_INTERCONNECT_QCOM_OSM_L3=y
 CONFIG_INTERCONNECT_QCOM_QCM2290=y
-CONFIG_INTERCONNECT_QCOM_QCS404=m
+CONFIG_INTERCONNECT_QCOM_QCS404=y
 CONFIG_INTERCONNECT_QCOM_QCS615=y
 CONFIG_INTERCONNECT_QCOM_QCS8300=y
 CONFIG_INTERCONNECT_QCOM_QDU1000=y

---
base-commit: b098bcd8278b89cb3eb73fdb6e06dc49af75ad37
change-id: 20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-258fcc961b11

Best regards,
-- 
Christopher Obbard <christopher.obbard at linaro.org>



From csokas.bence at prolan.hu  Tue Mar 11 11:02:53 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Tue, 11 Mar 2025 19:02:53 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
Message-ID: <20250311180254.149484-1-csokas.bence@prolan.hu>

Clean up error handling by using devm functions
and dev_err_probe(). This should make it easier
to add new code, as we can eliminate the "goto
ladder" in probe().

Suggested-by: Chen-Yu Tsai <wens at kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Chen-Yu Tsai <wens at csie.org>
Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    Changes in v2:
    * rebase on current next
    Changes in v3:
    * rebase on current next
    * collect Jernej's tag
    Changes in v4:
    * rebase on current next
    * collect Chen-Yu's tag

 drivers/dma/sun4i-dma.c | 31 ++++++-------------------------
 1 file changed, 6 insertions(+), 25 deletions(-)

diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 24796aaaddfa..b10639720efd 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1249,10 +1249,9 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 	if (priv->irq < 0)
 		return priv->irq;
 
-	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(priv->clk)) {
-		dev_err(&pdev->dev, "No clock specified\n");
-		return PTR_ERR(priv->clk);
+		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "Couldn't start the clock");
 	}
 
 	if (priv->cfg->has_reset) {
@@ -1328,12 +1327,6 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 		vchan_init(&vchan->vc, &priv->slave);
 	}
 
-	ret = clk_prepare_enable(priv->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Couldn't enable the clock\n");
-		return ret;
-	}
-
 	/*
 	 * Make sure the IRQs are all disabled and accounted for. The bootloader
 	 * likes to leave these dirty
@@ -1344,32 +1337,23 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 	ret = devm_request_irq(&pdev->dev, priv->irq, sun4i_dma_interrupt,
 			       0, dev_name(&pdev->dev), priv);
 	if (ret) {
-		dev_err(&pdev->dev, "Cannot request IRQ\n");
-		goto err_clk_disable;
+		return dev_err_probe(&pdev->dev, ret, "Cannot request IRQ");
 	}
 
-	ret = dma_async_device_register(&priv->slave);
+	ret = dmaenginem_async_device_register(&priv->slave);
 	if (ret) {
-		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
-		goto err_clk_disable;
+		return dev_err_probe(&pdev->dev, ret, "Failed to register DMA engine device");
 	}
 
 	ret = of_dma_controller_register(pdev->dev.of_node, sun4i_dma_of_xlate,
 					 priv);
 	if (ret) {
-		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
-		goto err_dma_unregister;
+		return dev_err_probe(&pdev->dev, ret, "Failed to register translation function");
 	}
 
 	dev_dbg(&pdev->dev, "Successfully probed SUN4I_DMA\n");
 
 	return 0;
-
-err_dma_unregister:
-	dma_async_device_unregister(&priv->slave);
-err_clk_disable:
-	clk_disable_unprepare(priv->clk);
-	return ret;
 }
 
 static void sun4i_dma_remove(struct platform_device *pdev)
@@ -1380,9 +1364,6 @@ static void sun4i_dma_remove(struct platform_device *pdev)
 	disable_irq(priv->irq);
 
 	of_dma_controller_free(pdev->dev.of_node);
-	dma_async_device_unregister(&priv->slave);
-
-	clk_disable_unprepare(priv->clk);
 }
 
 static struct sun4i_dma_config sun4i_a10_dma_cfg = {
-- 
2.48.1




From will at kernel.org  Tue Mar 11 11:05:54 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 18:05:54 +0000
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
Message-ID: <20250311180553.GB5216@willie-the-truck>

On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> This will be used by drm/msm for GPU page faults, replacing the manual
> register reading it does.
> 
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
>  drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
>  drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
>  3 files changed, 21 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>  
>  	if (list_empty(&tbu_list)) {
>  		ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -					 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +					 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>  
>  		if (ret == -ENOSYS)
>  			arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>  	phys_soft = ops->iova_to_phys(ops, cfi.iova);
>  
>  	tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -				 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +				 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>  	if (!tmp || tmp == -EBUSY) {
>  		ret = IRQ_HANDLED;
>  		resume = ARM_SMMU_RESUME_TERMINATE;
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
>  				      struct arm_smmu_context_fault_info *cfi)
>  {
>  	cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> +	cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
>  	cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> -	cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> +	cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> +	cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);

We already have an implementation hook (->get_fault_info()) which the
qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
That thing dumps these registers already so if we're moving that into
the core SMMU driver, let's get rid of the hook and move everybody over
rather than having it done in both places.

>  	cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> +	cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);

I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
it for stage-2 domains.

Will


From robh at kernel.org  Tue Mar 11 11:06:52 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 13:06:52 -0500
Subject: [RFC PATCH v2 01/16] dt-bindings: media: i2c: max96717: add
 myself as maintainer
In-Reply-To: <20250309084814.3114794-2-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-2-demonsingur@gmail.com>
Message-ID: <174171641225.3915054.13208024290734160025.robh@kernel.org>


On Sun, 09 Mar 2025 10:47:53 +0200, Cosmin Tanislav wrote:
> Analog Devices is taking responsability for the maintenance of the Maxim
> GMSL2/3 devices.
> Add myself to the maintainers list and to the device tree bindings.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 1 +
>  MAINTAINERS                                                     | 1 +
>  2 files changed, 2 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From will at kernel.org  Tue Mar 11 11:08:08 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 11 Mar 2025 18:08:08 +0000
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers
 directly
In-Reply-To: <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
Message-ID: <20250311180807.GC5216@willie-the-truck>

On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> In some cases drm/msm has to resume a stalled transaction directly in
> its fault handler. Experimentally this doesn't work on SMMU500 if the
> fault hasn't already been acknowledged by clearing FSR. Rather than
> trying to clear FSR in msm's fault handler and implementing a
> tricky handshake to avoid accidentally clearing FSR twice, we want to
> clear FSR before calling the fault handlers, but this means that the
> contents of registers can change underneath us in the fault handler and
> msm currently uses a private function to read the register contents for
> its own purposes in its fault handler, such as using the
> implementation-defined FSYNR1 to determine which block caused the fault.
> Fix this by making msm use the register values already read by arm-smmu
> itself before clearing FSR rather than messing around with reading
> registers directly.
> 
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
>  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
>  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
>  3 files changed, 27 insertions(+), 27 deletions(-)

[...]

> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
>  	ARM_SMMU_DOMAIN_NESTED,
>  };
>  
> +struct arm_smmu_context_fault_info {
> +	unsigned long iova;
> +	u64 ttbr0;
> +	u32 fsr;
> +	u32 fsynr0;
> +	u32 fsynr1;
> +	u32 cbfrsynra;
> +	u32 contextidr;
> +};
> +
>  struct arm_smmu_domain {
>  	struct arm_smmu_device		*smmu;
>  	struct io_pgtable_ops		*pgtbl_ops;
> @@ -380,6 +390,7 @@ struct arm_smmu_domain {
>  	const struct iommu_flush_ops	*flush_ops;
>  	struct arm_smmu_cfg		cfg;
>  	enum arm_smmu_domain_stage	stage;
> +	struct arm_smmu_context_fault_info cfi;

Does this mean we have to serialise all faults for a given domain? That
can't be right...

Will


From robh at kernel.org  Tue Mar 11 11:09:09 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 13:09:09 -0500
Subject: [RFC PATCH v2 02/16] dt-bindings: media: i2c: max96717: reflow
 text
In-Reply-To: <20250309084814.3114794-3-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-3-demonsingur@gmail.com>
Message-ID: <20250311180909.GA3915230-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:47:54AM +0200, Cosmin Tanislav wrote:
> This text is using weird line lengths. Fix it.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max96717.yaml    | 19 +++++++++----------
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> index 15ab37702a92..1026678a17a7 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> @@ -12,16 +12,15 @@ maintainers:
>    - Cosmin Tanislav <cosmin.tanislav at analog.com>
>  
>  description:

Use '>' token for multiple paragraphs.

> -  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
> -  into GMSL2 serial outputs. The device allows the GMSL2 link to
> -  simultaneously transmit bidirectional control-channel data while forward
> -  video transmissions are in progress. The MAX96717 can connect to one
> -  remotely located deserializer using industry-standard coax or STP
> -  interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
> -  the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI
> -  data received by the serializer.
> -  The MAX96717 supports Reference Over Reverse (channel),
> -  to generate a clock output for the sensor from the GMSL reverse channel.
> +  The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input into GMSL2
> +  serial outputs. The device allows the GMSL2 link to simultaneously transmit
> +  bidirectional control-channel data while forward video transmissions are in
> +  progress. The MAX96717 can connect to one remotely located deserializer using
> +  industry-standard coax or STP interconnects. The device cans operate in pixel
> +  or tunnel mode. In pixel mode the MAX96717 can select the MIPI datatype, while
> +  the tunnel mode forward all the MIPI data received by the serializer.

> +  The MAX96717 supports Reference Over Reverse (channel), to generate a clock
> +  output for the sensor from the GMSL reverse channel.

Is this a separate paragraph? If not, the wrapping is not right. If so, 
then needs a blank line in between.

>  
>    The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
>    forward direction and 187.5Mbps in the reverse direction.
> -- 
> 2.48.1
> 


From ansuelsmth at gmail.com  Tue Mar 11 11:09:43 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Tue, 11 Mar 2025 19:09:43 +0100
Subject: [PATCH 10/13] phy: airoha: Add support for Airoha AN7581 USB PHY
In-Reply-To: <Z9AhkByegWQgC9YE@vaman>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-11-ansuelsmth@gmail.com>
 <Z9AhN9T8s1oogCUn@vaman>
 <Z9AhkByegWQgC9YE@vaman>
Message-ID: <67d07c68.170a0220.3fa05.2c8e@mx.google.com>

On Tue, Mar 11, 2025 at 12:42:08PM +0100, Vinod Koul wrote:
> On 11-03-25, 12:40, Vinod Koul wrote:
> > On 09-03-25, 14:29, Christian Marangi wrote:
> > > Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
> > > USB port with USB 2.0 mode always supported and USB 3.0 mode available
> > > only if the Serdes port is correctly configured for USB 3.0.
> > > 
> > > On xLate probe, the Serdes mode is validated and the driver return error
> > > if the Serdes mode doesn't reflect the expected mode. This is required
> > > as Serdes mode are controlled by the SCU SSR bits and can be either USB
> > > 3.0 mode or HSGMII or PCIe 2. In such case USB 3.0 won't work.
> > > 
> > > If the USB 3.0 mode is not supported, the modes needs to be also
> > > disabled in the xHCI node or the driver will report unsable clock and
> > > fail probe.
> 
> Also I dont see phy depends on rest. Please split this and post phy bits
> separately at least..

Well USB doesn't work without this driver so they are indirectly
dependent. Will split and address all the other comments.

> 
> -- 
> ~Vinod

-- 
	Ansuel


From christopher.obbard at linaro.org  Tue Mar 11 11:10:06 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Tue, 11 Mar 2025 19:10:06 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as built-in
In-Reply-To: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
Message-ID: <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>

I sent this patch to start the discussion, some things I found:

1) Some interconnects are missing from arm defconfig. Should they be =y too ?
$ grep CONFIG_INTERCONNECT_QCOM arch/arm/configs/qcom_defconfig
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8974=m
CONFIG_INTERCONNECT_QCOM_SDX55=m

2) Some interconnects are missing from arm64 defconfig (which should
probably be in there) (I have included just two examples):
$ grep CONFIG_INTERCONNECT drivers/interconnect/qcom/Makefile
obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
obj-$(CONFIG_INTERCONNECT_QCOM_SM7150) += qnoc-sm7150.o

I can handle these in follow-up or v2 of the patchset as follow-up
commits, please let me know what you'd prefer.

On Tue, 11 Mar 2025 at 19:03, Christopher Obbard
<christopher.obbard at linaro.org> wrote:
>
> Currently some Qualcomm interconnect drivers are enabled
> as modules which isn't overly useful since the interconnects
> are required to be loaded during early boot.
>
> Loading the interconnects late (e.g. in initrd or as module)
> can cause boot issues, such as slowdown or even not booting
> at all (since the interconnect would be required for storage
> devices).
>
> Be consistent and enable all of the Qualcomm interconnect
> drivers as built-in to the kernel image.
>
> Signed-off-by: Christopher Obbard <christopher.obbard at linaro.org>
> ---
>  arch/arm64/configs/defconfig | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 219ef05ee5a757c43a37ec9f8571ce9976354830..6582baee2ab02ecb2ff442c6e73aa6a23fee8d7f 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -1656,11 +1656,11 @@ CONFIG_INTERCONNECT_IMX8MN=m
>  CONFIG_INTERCONNECT_IMX8MQ=m
>  CONFIG_INTERCONNECT_IMX8MP=y
>  CONFIG_INTERCONNECT_QCOM=y
> -CONFIG_INTERCONNECT_QCOM_MSM8916=m
> +CONFIG_INTERCONNECT_QCOM_MSM8916=y
>  CONFIG_INTERCONNECT_QCOM_MSM8996=y
> -CONFIG_INTERCONNECT_QCOM_OSM_L3=m
> +CONFIG_INTERCONNECT_QCOM_OSM_L3=y
>  CONFIG_INTERCONNECT_QCOM_QCM2290=y
> -CONFIG_INTERCONNECT_QCOM_QCS404=m
> +CONFIG_INTERCONNECT_QCOM_QCS404=y
>  CONFIG_INTERCONNECT_QCOM_QCS615=y
>  CONFIG_INTERCONNECT_QCOM_QCS8300=y
>  CONFIG_INTERCONNECT_QCOM_QDU1000=y
>
> ---
> base-commit: b098bcd8278b89cb3eb73fdb6e06dc49af75ad37
> change-id: 20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-258fcc961b11
>
> Best regards,
> --
> Christopher Obbard <christopher.obbard at linaro.org>
>


From robh at kernel.org  Tue Mar 11 12:07:11 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 14:07:11 -0500
Subject: [RFC PATCH v2 11/16] dt-bindings: media: i2c: add MAX9296A,
 MAX96716A, MAX96792A
In-Reply-To: <20250309084814.3114794-12-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-12-demonsingur@gmail.com>
Message-ID: <20250311190711.GA3985355-robh@kernel.org>

On Sun, Mar 09, 2025 at 10:48:03AM +0200, Cosmin Tanislav wrote:
> The MAX9296A deserializer converts single or dual serial inputs to MIPI
> CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps or 6Gbps
> in the forward direction and 187.5Mbps in the reverse direction.
> In GMSL1 mode, each serial link can be paired with 3.12Gbps or 1.5Gbps
> GMSL1 serializers or operate up to 4.5Gbps with GMSL2 serializers with
> GMSL1 backward compatibility. The MAX9296A supports mixed GMSL2 and
> GMSL1 links. The serial inputs operate independently, allowing videos
> with different timings and resolutions to be received on each input.
> 
> MAX96716A supports both tunnel and pixel mode.
> MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  .../bindings/media/i2c/maxim,max9296a.yaml    | 281 ++++++++++++++++++
>  MAINTAINERS                                   |   6 +
>  2 files changed, 287 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
> new file mode 100644
> index 000000000000..97731549d161
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
> @@ -0,0 +1,281 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright (C) 2024 Collabora Ltd.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/i2c/maxim,max9296a.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Maxim MAX9296A GMSL2 to CSI-2 Deserializer
> +
> +maintainers:
> +  - Cosmin Tanislav <cosmin.tanislav at analog.com>
> +
> +description:

Needs '>' token as you have paragraphs.

> +  The MAX9296A deserializer converts single or dual serial inputs to
> +  MIPI CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps
> +  or 6Gbps in the forward direction and 187.5Mbps in the reverse
> +  direction. In GMSL1 mode, each serial link can be paired with 3.12Gbps
> +  or 1.5Gbps GMSL1 serializers or operate up to 4.5Gbps with GMSL2
> +  serializers with GMSL1 backward compatibility. The MAX9296A supports
> +  mixed GMSL2 and GMSL1 links. The serial inputs operate independently,
> +  allowing videos with different timings and resolutions to be received
> +  on each input.
> +
> +  MAX96716A supports both tunnel and pixel mode.
> +  MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - maxim,max9296a
> +      - maxim,max96716a
> +      - maxim,max96792a
> +
> +  reg:
> +    maxItems: 1
> +
> +  powerdown-gpios:
> +    maxItems: 1
> +    description: Specifier for the GPIO connected to the PWDNB pin.
> +
> +  port0-poc-supply:
> +    description: Regulator providing Power over Coax for GMSL port 0
> +
> +  port1-poc-supply:
> +    description: Regulator providing Power over Coax for GMSL port 1
> +
> +  i2c-mux:
> +    $ref: /schemas/i2c/i2c-mux.yaml#
> +    unevaluatedProperties: false
> +    patternProperties:
> +      '^i2c@[0-1]$':
> +        $ref: /schemas/i2c/i2c-controller.yaml#
> +        unevaluatedProperties: false
> +        properties:
> +          reg:
> +            items:
> +              minimum: 0
> +              maximum: 1
> +
> +  i2c-alias-pool:
> +    maxItems: 2
> +
> +  i2c-atr:
> +    type: object
> +    additionalProperties: false
> +
> +    properties:
> +      '#address-cells':
> +        const: 1
> +
> +      '#size-cells':
> +        const: 0
> +
> +    patternProperties:
> +      '^i2c@[0-1]$':
> +        $ref: /schemas/i2c/i2c-controller.yaml#
> +        unevaluatedProperties: false
> +        properties:
> +          reg:
> +            items:
> +              minimum: 0
> +              maximum: 1
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    patternProperties:
> +      '^port@[0-1]$':
> +        $ref: /schemas/graph.yaml#/properties/port
> +        unevaluatedProperties: false
> +        description: GMSL Input
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#

What properties are you using from here?

None actually because /schemas/graph.yaml#/properties/port won't allow 
any.


> +            unevaluatedProperties: false
> +            description: Endpoint for GMSL2-Link port.
> +
> +      '^port@[2-3]$':
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description: CSI-2 Output port
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            unevaluatedProperties: false
> +
> +            properties:
> +              data-lanes:
> +                minItems: 1
> +                maxItems: 4
> +
> +              lane-polarities:
> +                minItems: 1
> +                maxItems: 5
> +
> +              link-frequencies:
> +                maxItems: 1
> +
> +            required:
> +              - data-lanes
> +
> +    anyOf:
> +      - required:
> +          - port at 2
> +      - required:
> +          - port at 3
> +
> +required:
> +  - compatible
> +  - reg
> +  - ports
> +
> +additionalProperties: false
> +
> +allOf:
> +  - $ref: /schemas/i2c/i2c-atr.yaml#
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - maxim,max9296a
> +              - maxim,max96792a
> +    then:
> +      not:
> +        required: [i2c-mux]
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - maxim,max96716a
> +    then:
> +      not:
> +        required: [i2c-atr]
> +
> +dependentRequired:
> +  i2c-atr: [i2c-alias-pool]
> +  i2c-alias-pool: [i2c-atr]
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/media/video-interfaces.h>
> +
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        deserializer at 28 {
> +            compatible = "maxim,max9296a";
> +            reg = <0x28>;
> +            powerdown-gpios = <&main_gpio0 37 GPIO_ACTIVE_LOW>;
> +
> +            i2c-alias-pool = <0x40 0x41>;
> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                port at 0 {
> +                    reg = <0>;
> +                    des_gmsl_in_0: endpoint {
> +                        remote-endpoint = <&ser_0_gmsl_out>;
> +                    };
> +                };
> +
> +                port at 1 {
> +                    reg = <1>;
> +                    des_gmsl_in_1: endpoint {
> +                        remote-endpoint = <&ser_1_gmsl_out>;
> +                    };
> +                };
> +
> +                port at 2 {
> +                    reg = <2>;
> +                    des_csi_out: endpoint {
> +                        data-lanes = <1 2 3 4>;
> +                        link-frequencies = /bits/ 64 <400000000>;
> +                        remote-endpoint = <&csi_in>;
> +                    };
> +                };
> +            };
> +
> +            i2c-atr {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                i2c at 0 {
> +                    #address-cells = <1>;
> +                    #size-cells = <0>;
> +                    reg = <0>;
> +
> +                    serializer at 40 {
> +                        compatible = "maxim,max96717";
> +                        reg = <0x40>;
> +                        gpio-controller;
> +                        #gpio-cells = <2>;
> +                        #clock-cells = <0>;
> +
> +                        ports {
> +                            #address-cells = <1>;
> +                            #size-cells = <0>;
> +
> +                            port at 0 {
> +                                reg = <0>;
> +                                ser_0_csi_in: endpoint {
> +                                    data-lanes = <1 2>;
> +                                    remote-endpoint = <&sensor_0_out>;
> +                                };
> +                            };
> +
> +                            port at 1 {
> +                                reg = <1>;
> +                                ser_0_gmsl_out: endpoint {
> +                                    remote-endpoint = <&des_gmsl_in_0>;
> +                                };
> +                            };
> +                        };
> +                    };
> +                };
> +
> +                i2c at 1 {
> +                    #address-cells = <1>;
> +                    #size-cells = <0>;
> +                    reg = <1>;
> +
> +                    serializer at 40 {
> +                        compatible = "maxim,max96717";
> +                        reg = <0x40>;
> +                        gpio-controller;
> +                        #gpio-cells = <2>;
> +                        #clock-cells = <0>;
> +
> +                        ports {
> +                            #address-cells = <1>;
> +                            #size-cells = <0>;
> +
> +                            port at 0 {
> +                                reg = <0>;
> +                                ser_1_csi_in: endpoint {
> +                                    data-lanes = <1 2>;
> +                                    remote-endpoint = <&sensor_1_out>;
> +                                };
> +                            };
> +
> +                            port at 1 {
> +                                reg = <1>;
> +                                ser_1_gmsl_out: endpoint {
> +                                    remote-endpoint = <&des_gmsl_in_1>;
> +                                };
> +                            };
> +                        };
> +                    };
> +                };
> +            };
> +        };
> +    };
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index abf3afc95fc9..c1e01668e81a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14220,6 +14220,12 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml
>  F:	drivers/iio/proximity/mb1232.c
>  
> +MAXIM GMSL2 SERIALIZERS AND DESERIALIZERS
> +M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
> +L:	linux-media at vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
> +
>  MAXIM MAX11205 DRIVER
>  M:	Ramona Bolboaca <ramona.bolboaca at analog.com>
>  L:	linux-iio at vger.kernel.org
> -- 
> 2.48.1
> 


From ansuelsmth at gmail.com  Tue Mar 11 12:09:02 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Tue, 11 Mar 2025 20:09:02 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <026296c8-a460-43ca-a423-0fa38269fbc2@kernel.org>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
 <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>
 <67cec328.170a0220.27ecbc.9c6e@mx.google.com>
 <026296c8-a460-43ca-a423-0fa38269fbc2@kernel.org>
Message-ID: <67d08a4f.7b0a0220.8fe9e.44fd@mx.google.com>

On Mon, Mar 10, 2025 at 12:41:06PM +0100, Krzysztof Kozlowski wrote:
> On 10/03/2025 11:47, Christian Marangi wrote:
> > On Mon, Mar 10, 2025 at 10:21:45AM +0100, Krzysztof Kozlowski wrote:
> >> On 09/03/2025 14:29, Christian Marangi wrote:
> >>> Add Documentation for Airoha EN7581 SCU.
> >>>
> >>> Airoha EN7581 SoC expose registers to control miscellaneous pheriperals
> >>> via the SCU (System Controller Unit).
> >>>
> >>> Example of these pheriperals are reset-controller, clock-controller,
> >>> PCIe line speed controller and bits to configure different Serdes ports
> >>> for USB or Ethernet usage.
> >>>
> >>> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> >>> ---
> >>>  .../mfd/airoha,en7581-scu-sysctl.yaml         | 68 +++++++++++++++++++
> >>>  1 file changed, 68 insertions(+)
> >>>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> >>> new file mode 100644
> >>> index 000000000000..d7dc66f912c1
> >>> --- /dev/null
> >>> +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-scu-sysctl.yaml
> >>> @@ -0,0 +1,68 @@
> >>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> >>> +%YAML 1.2
> >>> +---
> >>> +$id: http://devicetree.org/schemas/mfd/airoha,en7581-scu-sysctl.yaml#
> >>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >>> +
> >>> +title: Airoha EN7581 SCU (System Controller Unit)
> >>> +
> >>> +maintainers:
> >>> +  - Christian Marangi <ansuelsmth at gmail.com>
> >>> +
> >>> +description:
> >>> +  Airoha EN7581 SoC expose registers to control miscellaneous
> >>> +  pheriperals via the SCU (System Controller Unit).
> >>> +
> >> One more comment - there is no such thing as "sysctl" in your hardware.
> >> Look at the SCU binding which clearly says that it is the hardware you
> >> are duplicating here, so the "System Control Unit".
> >>
> >> So you have existing "This node defines the System Control Unit of the
> >> EN7523 SoC" and you add one more node which defines the "System Control
> >> Unit", so you have two "System Control Unit" device nodes?
> >>
> >> Look also what Stephen asked for:
> >>
> >> https://lore.kernel.org/all/20220106013100.842FCC36AEB at smtp.kernel.org/
> >>
> >> so how system-controller can now became clock-controller? Now, it was
> >> the system controller since the beginning.
> >>
> > 
> > The main problem here (and we had a similar problem with GPIO and PWM)
> > is that the Vendor (Airoha) wasn't so bright in placing the different
> > registers for the SoC so we have case where everything is mixed and not
> > one after another... 
> > 
> > Example we have 
> > - CLK register part 1
> > - Some bits that configure PCIe
> > - CLK register part 2
> > - GPIO
> > - CLK register part 3
> > - ...
> 
> This does not explain that binding said "This node defines the System
> Control Unit".
> 
> So what are you adding here if not SCU?
>

With "This node defines the System Control Unit" I mean, the entire
register space of the IP block is defined and each child specifically
define each part of the IP block.

> > 
> > The driver solution for this is syscon and the simple-mfd node
> > structure.
> 
> Let's keep driver entirely separate, we don't talk about them and mixing
> arguments won't make it easier.
> 

Ok.

> > 
> > Now the main problem is how to modle this in DT. There are lots of case
> > where the simple-mfd model is used (like the one proposed) but probably
> > this is not accepted anymore. But again this should be clearly stated or
> > we have a chicken-egg problem when other devs implement similar thing and
> > have to implement simple MFD driver to handle this. (and driver
> > maintainers say "Use the simple-mfd model like it was already done)
> 
> simple-mfd has nothing to do here. Describe the hardware - what is the SCU?
> 
> 

As I said below, SCU is just the name used in Airoha Documentation for
this IP block. In this register space there are multiple things so it's
not strictly a clock-controller (as it's currently defined)

It was proposed as clock-controller previously as we weren't aware this
IP block was used also for other usage that a strict clock controller.

> > 
> > For this specific case (and to give an answer to the clock patch after
> > this) the problem is that this register space was originally used only
> > to control the clock and I wasn't aware that it was also used to control
> > USB. Now that I'm implementing support for it, the disaster happened.
> > 
> > So In short SCU is lots of thing, both a system-controller, a
> > clock-controller and even a reset-controller.
> 
> And you have bindings for that already. Done.
> 

It's currently defined in DTS as clock-controller, should we change it
to system-controller to make it more clear?

> > 
> > To make it short, 2 different solution:
> > 1. We can keep the current node structure of the node-controller and add a
> > child node for the SSR part (with a dedicated compatible).
> 
> No, you do not add child nodes just because you want some drivers.
> 
> What is SSR? How is it a device?

SSR is the name used in Documentation for the register used to configure
the Serdes and PCIe port.

> 
> > 2. Those property need to be be defined in the clock-controller node?
> 
> In the SCU node. Do you have only one SCU or more?

Strictly speaking it's one register space. One clock-controller, one
reset-controller and one set of SSR registers, and from what I can
understand it's ALWAYS "One device/compatible for Register space"

The simple-mfd pattern can't really work for case like this where in one
register space there are multiple stuff.

Is everything clear now?

To summarize:
- no child nodes
- add additional property for SSR in the SCU .yaml

> 
> > 
> > The ideal solution is 1. Does it work for you?
> > 
> > Sorry for the long post and hope you understand why this mess of
> > reworking the binding.
> > 
> 
> 
> Best regards,
> Krzysztof

-- 
	Ansuel


From maz at kernel.org  Tue Mar 11 12:10:14 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 11 Mar 2025 19:10:14 +0000
Subject: [PATCH 07/18] KVM: arm64: Compute FGT masks from KVM's own FGT tables
In-Reply-To: <CA+EHjTwm4CosWDGcaH_tnLU7zMNCq8twDyEcKd7-V0Lu7b-LcA@mail.gmail.com>
References: <20250210184150.2145093-1-maz@kernel.org>
	<20250210184150.2145093-8-maz@kernel.org>
	<CA+EHjTwm4CosWDGcaH_tnLU7zMNCq8twDyEcKd7-V0Lu7b-LcA@mail.gmail.com>
Message-ID: <86o6y7o02x.wl-maz@kernel.org>

On Tue, 04 Mar 2025 16:55:50 +0000,
Fuad Tabba <tabba at google.com> wrote:
> 
> Hi Marc,
> 
> On Mon, 10 Feb 2025 at 18:42, Marc Zyngier <maz at kernel.org> wrote:
> >
> > In the process of decoupling KVM's view of the FGT bits from the
> > wider architectural state, use KVM's own FGT tables to build
> > a synthitic view of what is actually known.
> 
> synthitic -> synthetic

Ah, I missed that one earlier. Will fix.

> 
> 
> > This allows for some checking along the way.
> >
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > ---
> >  arch/arm64/include/asm/kvm_arm.h  |   4 ++
> >  arch/arm64/include/asm/kvm_host.h |  14 ++++
> >  arch/arm64/kvm/emulate-nested.c   | 102 ++++++++++++++++++++++++++++++
> >  3 files changed, 120 insertions(+)
> >
> > diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> > index 8d94a6c0ed5c4..e424085f2aaca 100644
> > --- a/arch/arm64/include/asm/kvm_arm.h
> > +++ b/arch/arm64/include/asm/kvm_arm.h
> > @@ -359,6 +359,10 @@
> >  #define __HAFGRTR_EL2_MASK     (GENMASK(49, 17) | GENMASK(4, 0))
> >  #define __HAFGRTR_EL2_nMASK    ~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
> >
> > +/* Because the sysreg file mixes R and W... */
> > +#define HFGRTR_EL2_RES0                HFGxTR_EL2_RES0 (0)
> > +#define HFGWTR_EL2_RES0                (HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
> 
> __HFGRTR_ONLY_MASK is a hand-crafted bitmask. The only bit remaining
> in HFGxTR_EL2 that is RES0 is bit 51. If that were to be used as an
> HFGRTR-only bit without __HFGRTR_ONLY_MASK getting updated, then
> aggregate_fgt() below would set its bit in hfgwtr_masks. Could this be
> a problem if this happens and the polarity of this bit ends up being
> negative, thereby setting the corresponding nmask bit?

So I ended up doing exactly what I threatened to do, which is to
completely get rid of the HFGxTR nonsense, and bring HFG{R,W}TR to
their full glory.

The diffstat is a bit annoying:

 arch/arm64/include/asm/el2_setup.h      |  14 +--
 arch/arm64/include/asm/kvm_arm.h        |   4 +-
 arch/arm64/include/asm/kvm_host.h       |   3 +-
 arch/arm64/kvm/emulate-nested.c         | 154 ++++++++++++-------------
 arch/arm64/kvm/hyp/include/hyp/switch.h |   4 +-
 arch/arm64/kvm/hyp/vgic-v3-sr.c         |   8 +-
 arch/arm64/kvm/nested.c                 |  42 +++----
 arch/arm64/kvm/sys_regs.c               |  20 ++--
 arch/arm64/tools/sysreg                 | 194 ++++++++++++++++++++------------
 9 files changed, 250 insertions(+), 193 deletions(-)

but at least it puts all registers in the same bucket, and we don't
assume anything anymore.

I'll repost the series on Monday, once I'm on holiday.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From christopher.obbard at linaro.org  Tue Mar 11 12:15:31 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Tue, 11 Mar 2025 20:15:31 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as built-in
In-Reply-To: <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com> <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
Message-ID: <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>

Hi Dmitry,

On Tue, 11 Mar 2025 at 19:58, Dmitry Baryshkov <lumag at kernel.org> wrote:
>
> On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
> > I sent this patch to start the discussion, some things I found:
> >
> > 1) Some interconnects are missing from arm defconfig. Should they be =y too ?
>
> No, unless those are required for the UART console.

OK, that makes sense. FWIW the cryptic (to me, at least) commit log on
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eee808134ecf1c1093ff1ddfc056dc5e469d0c3
made me think that the interconnects should be built-in on all devices.

Of course, the real problem here is RB3gen2 not actually finding the
UFS/eMMC device due to no interconnect driver.
Until now, I have been building that into the kernel. I will
investigate instead shoving into the initrd (in both debian and
fedora) which should solve my issue and render this patchset useless.


Thanks,

Chris

>
> > $ grep CONFIG_INTERCONNECT_QCOM arch/arm/configs/qcom_defconfig
> > CONFIG_INTERCONNECT_QCOM=y
> > CONFIG_INTERCONNECT_QCOM_MSM8974=m
> > CONFIG_INTERCONNECT_QCOM_SDX55=m
> >
> > 2) Some interconnects are missing from arm64 defconfig (which should
> > probably be in there) (I have included just two examples):
>
> I think `git log -S CONFIG_INTERCONNECT_QCOM
> arch/arm64/configs/defconfig` will answer this question. The drivers are
> enabled on the premises of being required for a particular device, not
> because they exist in the Linux kernel.
>
> > $ grep CONFIG_INTERCONNECT drivers/interconnect/qcom/Makefile
> > obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
> > obj-$(CONFIG_INTERCONNECT_QCOM_SM7150) += qnoc-sm7150.o
> >
> > I can handle these in follow-up or v2 of the patchset as follow-up
> > commits, please let me know what you'd prefer.
> >
> > On Tue, 11 Mar 2025 at 19:03, Christopher Obbard
> > <christopher.obbard at linaro.org> wrote:
> > >
> > > Currently some Qualcomm interconnect drivers are enabled
> > > as modules which isn't overly useful since the interconnects
> > > are required to be loaded during early boot.
> > >
> > > Loading the interconnects late (e.g. in initrd or as module)
> > > can cause boot issues, such as slowdown or even not booting
> > > at all (since the interconnect would be required for storage
> > > devices).
> > >
> > > Be consistent and enable all of the Qualcomm interconnect
> > > drivers as built-in to the kernel image.
> > >
> > > Signed-off-by: Christopher Obbard <christopher.obbard at linaro.org>
> > > ---
> > >  arch/arm64/configs/defconfig | 6 +++---
> > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > > index 219ef05ee5a757c43a37ec9f8571ce9976354830..6582baee2ab02ecb2ff442c6e73aa6a23fee8d7f 100644
> > > --- a/arch/arm64/configs/defconfig
> > > +++ b/arch/arm64/configs/defconfig
> > > @@ -1656,11 +1656,11 @@ CONFIG_INTERCONNECT_IMX8MN=m
> > >  CONFIG_INTERCONNECT_IMX8MQ=m
> > >  CONFIG_INTERCONNECT_IMX8MP=y
> > >  CONFIG_INTERCONNECT_QCOM=y
> > > -CONFIG_INTERCONNECT_QCOM_MSM8916=m
> > > +CONFIG_INTERCONNECT_QCOM_MSM8916=y
> > >  CONFIG_INTERCONNECT_QCOM_MSM8996=y
> > > -CONFIG_INTERCONNECT_QCOM_OSM_L3=m
> > > +CONFIG_INTERCONNECT_QCOM_OSM_L3=y
> > >  CONFIG_INTERCONNECT_QCOM_QCM2290=y
> > > -CONFIG_INTERCONNECT_QCOM_QCS404=m
> > > +CONFIG_INTERCONNECT_QCOM_QCS404=y
> > >  CONFIG_INTERCONNECT_QCOM_QCS615=y
> > >  CONFIG_INTERCONNECT_QCOM_QCS8300=y
> > >  CONFIG_INTERCONNECT_QCOM_QDU1000=y
> > >
> > > ---
> > > base-commit: b098bcd8278b89cb3eb73fdb6e06dc49af75ad37
> > > change-id: 20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-258fcc961b11
> > >
> > > Best regards,
> > > --
> > > Christopher Obbard <christopher.obbard at linaro.org>
> > >
>
> --
> With best wishes
> Dmitry


From nathan at kernel.org  Tue Mar 11 12:17:57 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Tue, 11 Mar 2025 20:17:57 +0100
Subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker
 script
In-Reply-To: <2110116.YKUYFuaPT4@n9w6sw14>
References: <20250224125414.2184-1-ceggers@arri.de>
 <202503050230.820w99b6-lkp@intel.com>
 <20250310203729.GA26968@ax162>
 <2110116.YKUYFuaPT4@n9w6sw14>
Message-ID: <20250311191757.GA1958594@ax162>

On Tue, Mar 11, 2025 at 09:18:48AM +0100, Christian Eggers wrote:
> thanks for pushing this into the right direction.  Actually I didn't recognize that
> lld complains about overlapping virtual address ranges, maybe the .config provided
> by the first LKP report (which I used for testing) didn't enable the necessary options.

Right, it looks like CONFIG_HARDEN_BRANCH_HISTORY is not enabled in the
first configuration (since it was a randconfig) whereas it was in the
second configuration.

> On Monday, 10 March 2025, 21:37:29 CET, Nathan Chancellor wrote:
> > On Wed, Mar 05, 2025 at 02:49:38AM +0800, kernel test robot wrote:
> > > Hi Christian,
> > > 
> > > kernel test robot noticed the following build errors:
> > > 
> > > [auto build test ERROR on soc/for-next]
> > > [also build test ERROR on linus/master v6.14-rc5 next-20250304]
> > > [If your patch is applied to the wrong git tree, kindly drop us a note.
> > > And when submitting patch, we suggest to use '--base' as documented in
> > > https://git-scm.com/docs/git-format-patch#_base_tree_information]
> > > 
> > > url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Eggers/ARM-avoid-that-vectors-are-removed-during-linker-garbage-collection/20250224-210146
> > > base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
> > > patch link:    https://lore.kernel.org/r/20250224125414.2184-1-ceggers%40arri.de
> > > patch subject: [PATCH v2 1/2] ARM: substitute OVERLAY description in linker script
> > > config: arm-milbeaut_m10v_defconfig (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/config)
> > > compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 14170b16028c087ca154878f5ed93d3089a965c6)
> > > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250305/202503050230.820w99b6-lkp at intel.com/reproduce)
> > > 
> > > If you fix the issue in a separate patch/commit (i.e. not just a new version of
> > > the same patch/commit), kindly add following tags
> > > | Reported-by: kernel test robot <lkp at intel.com>
> > > | Closes: https://lore.kernel.org/oe-kbuild-all/202503050230.820w99b6-lkp at intel.com/
> > > 
> > > All errors (new ones prefixed by >>):
> > > 
> > > >> ld.lld: error: section .vectors.bhb.bpiall virtual address range overlaps with .vectors.bhb.loop8
> > >    >>> .vectors.bhb.bpiall range is [0xFFFF0000, 0xFFFF001F]
> > >    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
> > > --
> > > >> ld.lld: error: section .vectors.bhb.loop8 virtual address range overlaps with .vectors
> > >    >>> .vectors.bhb.loop8 range is [0xFFFF0000, 0xFFFF001F]
> > >    >>> .vectors range is [0xFFFF0000, 0xFFFF001F]
> > 
> > Looking at ld.lld's code, this error is intentionally ignored for
> > OVERLAY:
> > 
> > https://github.com/llvm/llvm-project/blob/9f170e6abed4a7b393bb8abbf07ac8d6930aa3b0/lld/ELF/Writer.cpp#L2751-L2761
> > 
> > I have submitted a patch that allows KEEP within OVERLAY to match GNU
> > ld:
> > 
> > https://github.com/llvm/llvm-project/pull/130661
> > 
> > Once/if that is accepted, we should go back to your v1 with something
> > like the following diff on top to keep things working for all linkers. I
> > hope that it won't take long for the ld.lld change to get reviewed and
> > landed but if this needs to be fixed urgently, this whole diff minus
> > '|| LLD_VERSION >= 210000' on the init/Kconfig change should work (with
> > a comment change). I can always send a follow up change to add it back.
> 
> 
> I build from an internal tree, so I am not in hurry.  As the Kconfig changes
> probably should take your Signed-Off-By, I am also fine if you do the necessary
> changes on my v1 and resubmit it together with your patch when it is time.

I landed the ld.lld change a little bit ago so I will go ahead and send
along my patch plus yours formally shortly.

https://github.com/llvm/llvm-project/commit/381599f1fe973afad3094e55ec99b1620dba7d8c

Thanks again for bringing this up.

Cheers,
Nathan


From robh at kernel.org  Tue Mar 11 12:20:19 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 14:20:19 -0500
Subject: [net-next PATCH v12 03/13] dt-bindings: net: dsa: Document
 support for Airoha AN8855 DSA Switch
In-Reply-To: <20250309172717.9067-4-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-4-ansuelsmth@gmail.com>
Message-ID: <20250311192019.GA4067643-robh@kernel.org>

On Sun, Mar 09, 2025 at 06:26:48PM +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 5-port Gigabit Switch.
> 
> It does expose the 5 Internal PHYs on the MDIO bus and each port
> can access the Switch register space by configurting the PHY page.
> 
> Each internal PHY might require calibration with the fused EFUSE on
> the switch exposed by the Airoha AN8855 SoC NVMEM.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../net/dsa/airoha,an8855-switch.yaml         | 105 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> new file mode 100644
> index 000000000000..63bcbebd6a29
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> @@ -0,0 +1,105 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Gigabit Switch
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  Airoha AN8855 is a 5-port Gigabit Switch.
> +
> +  It does expose the 5 Internal PHYs on the MDIO bus and each port
> +  can access the Switch register space by configurting the PHY page.
> +
> +  Each internal PHY might require calibration with the fused EFUSE on
> +  the switch exposed by the Airoha AN8855 SoC NVMEM.
> +
> +$ref: dsa.yaml#

This needs to be:

dsa.yaml#/$defs/ethernet-ports

As that restricts custom properties.

> +
> +properties:
> +  compatible:
> +    const: airoha,an8855-switch
> +
> +  reset-gpios:
> +    description:
> +      GPIO to be used to reset the whole device
> +    maxItems: 1
> +
> +  airoha,ext-surge:
> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      Calibrate the internal PHY with the calibration values stored in EFUSE
> +      for the r50Ohm values.

Should you be using nvmem binding to the efuse block? Or the efuses are 
within this block?

> +
> +required:
> +  - compatible
> +
> +unevaluatedProperties: false


From robh at kernel.org  Tue Mar 11 12:25:16 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 11 Mar 2025 14:25:16 -0500
Subject: [net-next PATCH v12 04/13] dt-bindings: net: Document support
 for AN8855 Switch Internal PHY
In-Reply-To: <20250309172717.9067-5-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-5-ansuelsmth@gmail.com>
Message-ID: <20250311192516.GA4115176-robh@kernel.org>

On Sun, Mar 09, 2025 at 06:26:49PM +0100, Christian Marangi wrote:
> Document support for AN8855 Switch Internal PHY.
> 
> Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
> PHYs on the MDIO bus.
> 
> Each PHY might need to be calibrated to correctly work with the
> use of the eFUSE provided by the Switch SoC. This can be enabled by
> defining in the PHY node the "airoha,ext-surge" property.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/net/airoha,an8855-phy.yaml       | 93 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 94 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
> new file mode 100644
> index 000000000000..301c46f84904
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
> @@ -0,0 +1,93 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Switch Internal PHY
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
> +  PHYs on the MDIO bus.
> +
> +  Each PHY might need to be calibrated to correctly work with the
> +  use of the eFUSE provided by the Switch SoC.
> +
> +allOf:
> +  - $ref: ethernet-phy.yaml#
> +
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - ethernet-phy-idc0ff.0410
> +  required:
> +    - compatible
> +
> +properties:
> +  reg:
> +    maxItems: 1
> +
> +  airoha,ext-surge:
> +    description: enable PHY calibration with the use of SoC eFUSE.

Wouldn't nvmem-cells presence enable this?

> +
> +  nvmem-cells:
> +    items:
> +      - description: phandle to SoC eFUSE tx_a
> +      - description: phandle to SoC eFUSE tx_b
> +      - description: phandle to SoC eFUSE tx_c
> +      - description: phandle to SoC eFUSE tx_d
> +
> +  nvmem-cell-names:
> +    items:
> +      - const: tx_a
> +      - const: tx_b
> +      - const: tx_c
> +      - const: tx_d
> +
> +required:
> +  - compatible
> +  - reg
> +
> +if:
> +  required:
> +    - airoha,ext-surge
> +then:
> +  required:
> +    - nvmem-cells
> +    - nvmem-cell-names

dependentRequired:
  airoha,ext-surge: [ nvmem-cells, nvmem-cell-names ]

> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    mdio {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        ethernet-phy at 1 {
> +            compatible = "ethernet-phy-idc0ff.0410",
> +                         "ethernet-phy-ieee802.3-c45";
> +
> +            reg = <1>;
> +        };
> +
> +        ethernet-phy at 2 {
> +            compatible = "ethernet-phy-idc0ff.0410",
> +                         "ethernet-phy-ieee802.3-c45";
> +
> +            reg = <2>;
> +
> +            airoha,ext-surge;
> +
> +            nvmem-cells = <&shift_sel_port0_tx_a>,
> +                <&shift_sel_port0_tx_b>,
> +                <&shift_sel_port0_tx_c>,
> +                <&shift_sel_port0_tx_d>;
> +            nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
> +        };
> +    };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 696ad8465ea8..45f4bb8deb0d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -726,6 +726,7 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
>  L:	netdev at vger.kernel.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
> +F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
>  F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
>  F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
>  
> -- 
> 2.48.1
> 


From robh at kernel.org  Tue Mar 11 12:26:28 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:26:28 -0500
Subject: [PATCH v2 3/4] ASoC: dt-bindings: meson: g12a-toacodec: add
 support for A1 SoC family
In-Reply-To: <20250309181600.1322701-4-jan.dakinevich@salutedevices.com>
References: <20250309181600.1322701-1-jan.dakinevich@salutedevices.com>
 <20250309181600.1322701-4-jan.dakinevich@salutedevices.com>
Message-ID: <174172118794.4169317.149338949275613581.robh@kernel.org>


On Sun, 09 Mar 2025 21:15:59 +0300, Jan Dakinevich wrote:
> Add support for "toacodec" audio component found A1 SoC family. On this
> SoC the component supports capture streams, additional DAI ids are added
> to configure this feature.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../devicetree/bindings/sound/amlogic,g12a-toacodec.yaml     | 1 +
>  include/dt-bindings/sound/meson-g12a-toacodec.h              | 5 +++++
>  2 files changed, 6 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From krzk at kernel.org  Tue Mar 11 12:36:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 20:36:26 +0100
Subject: [PATCH v4 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org>
Message-ID: <59a1a6eb-d719-49bd-a4b5-bfb9c2817f08@kernel.org>

On 07/03/2025 11:29, Peter Griffin wrote:
> gs101 differs to other SoCs in that fltcon1 register doesn't
> always exist. Additionally the offset of fltcon0 is not fixed
> and needs to use the newly added eint_fltcon_offset variable.
> 
> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> Cc: stable at vger.kernel.org

It looks this depends on previous commit, right? That's really not
optimal, although I understand that if you re-order patches this code
would be soon changed, just like you changed other suspend/resume
callbacks in patch #2?


> Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> Changes since v2:
> * make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
> * align style where the '+' is placed (Andre)
> * remove unnecessary braces (Andre)
> ---

...

> +void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
> +{
> +	struct exynos_eint_gpio_save *save = bank->soc_priv;
> +	const void __iomem *regs = bank->eint_base;
> +
> +	if (bank->eint_type == EINT_TYPE_GPIO) {
> +		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> +				       + bank->eint_offset);
> +
> +		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> +					   + bank->eint_fltcon_offset);
> +
> +		/* fltcon1 register only exists for pins 4-7 */
> +		if (bank->nr_pins > 4)
> +			save->eint_fltcon1 = readl(regs +
> +						EXYNOS_GPIO_EFLTCON_OFFSET
> +						+ bank->eint_fltcon_offset + 4);
> +
> +		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> +					+ bank->eint_offset);
> +
> +		pr_debug("%s: save     con %#010x\n",
> +			 bank->name, save->eint_con);
> +		pr_debug("%s: save fltcon0 %#010x\n",
> +			 bank->name, save->eint_fltcon0);
> +		if (bank->nr_pins > 4)
> +			pr_debug("%s: save fltcon1 %#010x\n",
> +				 bank->name, save->eint_fltcon1);
> +		pr_debug("%s: save    mask %#010x\n",
> +			 bank->name, save->eint_mask);
> +	} else if (bank->eint_type == EINT_TYPE_WKUP)
> +		exynos_set_wakeup(bank);

Missing {}. Run checkpatch --strict.


Best regards,
Krzysztof


From krzysztof.kozlowski at linaro.org  Tue Mar 11 12:38:38 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 20:38:38 +0100
Subject: (subset) [PATCH v4 1/4] pinctrl: samsung: add support for eint_fltcon_offset
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-1-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org> <20250307-pinctrl-fltcon-suspend-v4-1-2d775e486036@linaro.org>
Message-ID: <174172189759.119514.8325135286672051459.b4-ty@linaro.org>


On Fri, 07 Mar 2025 10:29:05 +0000, Peter Griffin wrote:
> On gs101 SoC the fltcon0 (filter configuration 0) offset
> isn't at a fixed offset like previous SoCs as the fltcon1
> register only exists when there are more than 4 pins in the
> bank.
> 
> Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
> macros that take an additional fltcon_offs variable.
> 
> [...]


Re-wrapped commit msg to match wrapping style.

Applied, thanks!

[1/4] pinctrl: samsung: add support for eint_fltcon_offset
      https://git.kernel.org/pinctrl/samsung/c/701d0e910955627734917c3587258aa7e73068bb

Best regards,
-- 
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


From krzk at kernel.org  Tue Mar 11 12:40:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 20:40:24 +0100
Subject: [PATCH 0/3] gs101 max77759 enablement (DT)
In-Reply-To: <b70f17589b91730ecf6080c626492368283ce7a1.camel@linaro.org>
References: <20250306-b4-max77759-mfd-dts-v1-0-9fe8b0eb8123@linaro.org>
 <b70f17589b91730ecf6080c626492368283ce7a1.camel@linaro.org>
Message-ID: <4f3c4249-5e20-4b5d-a6ab-72c79274cb49@kernel.org>

On 06/03/2025 11:57, Andr? Draszik wrote:
> On Thu, 2025-03-06 at 10:14 +0000, Andr? Draszik wrote:
>> Hi,
>>
>> This series enables the recently submitted Maxim max77759 driver and
>> updates the DT for the Google Pixel 6 / Pro (oriole / raven) boards
>> accordingly.
>>
>> !!! Dependency note !!!
>>
>> This series depends on the corresponding driver and DT bindings
>> proposed in
>> https://lore.kernel.org/r/20250228-max77759-mfd-v3-0-0c3627d42526 at linaro.org
>>
>> Note that in that series bindings and gpio driver are accepted, but mfd
>> and nvmem drivers are still waiting for review comments.
> 
> To avoid ambiguity... with 'accepted' I meant reviewed, but not merged!


Thanks for letting me know. This must wait till bindings get applied to
subsystem tree, so probably will miss this merge window. Anyway, please
ping me when bindings get applied.

Best regards,
Krzysztof


From a.fatoum at pengutronix.de  Tue Mar 11 12:41:12 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 11 Mar 2025 20:41:12 +0100
Subject: [PATCH] arm64: dts: imx8mp: configure GPU and NPU clocks in
 nominal DTSI
Message-ID: <20250311-imx8m-clk-nominal-gpu-v1-1-78de5ea24c5d@pengutronix.de>

Commit 255fbd9eabe7 ("arm64: dts: imx8mp: Add optional nominal drive
mode DTSI") added imx8mp-nominal.dtsi, which overrides all overdrive
clock rates in imx8mp.dtsi to the nominal rates.

At the same time, commit 9f7595b3e5ae ("arm64: dts: imx8mp: configure
GPU and NPU clocks to overdrive rate") went in, which changed some
clock rates away from the nominal values.

Resolve the discrepancy by effectively reverting the changes in the
latter commit inside imx8mp-nominal.dtsi. This is required for proper
operation of the imx8mp-skov boards, which are currently
imx8mp-nominal.dtsi's only users and lets all other boards that don't
include it benefit from the new higher frequencies.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
If the commit hashes are not stable, please feel free to squash this
change directly into what's currently commit 255fbd9eabe7 ("arm64: dts:

imx8mp: Add optional nominal drive mode DTSI").
---
 arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi | 26 +++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi
index a1b75c9068b288a2fba73bbd96b1519a50df85a3..dc0ccd723c6d92e7946ebd52bac535e4175498d0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi
@@ -24,6 +24,20 @@ &clk {
 	fsl,operating-mode = "nominal";
 };
 
+&gpu2d {
+	assigned-clocks = <&clk IMX8MP_CLK_GPU2D_CORE>;
+	assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>;
+	assigned-clock-rates = <800000000>;
+};
+
+&gpu3d {
+	assigned-clocks = <&clk IMX8MP_CLK_GPU3D_CORE>,
+			  <&clk IMX8MP_CLK_GPU3D_SHADER_CORE>;
+	assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
+				 <&clk IMX8MP_SYS_PLL1_800M>;
+	assigned-clock-rates = <800000000>, <800000000>;
+};
+
 &pgc_hdmimix {
 	assigned-clocks = <&clk IMX8MP_CLK_HDMI_AXI>,
 			  <&clk IMX8MP_CLK_HDMI_APB>;
@@ -46,6 +60,18 @@ &pgc_gpumix {
 	assigned-clock-rates = <600000000>, <300000000>;
 };
 
+&pgc_mlmix {
+	assigned-clocks = <&clk IMX8MP_CLK_ML_CORE>,
+			  <&clk IMX8MP_CLK_ML_AXI>,
+			  <&clk IMX8MP_CLK_ML_AHB>;
+	assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
+				 <&clk IMX8MP_SYS_PLL1_800M>,
+				 <&clk IMX8MP_SYS_PLL1_800M>;
+	assigned-clock-rates = <800000000>,
+			       <800000000>,
+			       <300000000>;
+};
+
 &media_blk_ctrl {
 	assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>,
 			  <&clk IMX8MP_CLK_MEDIA_APB>,

---
base-commit: 5a690619426fc4b09c7fd3f40d3a69264ef3db0f
change-id: 20250311-imx8m-clk-nominal-gpu-db3bd7b7c905

Best regards,
-- 
Ahmad Fatoum <a.fatoum at pengutronix.de>



From cwabbott0 at gmail.com  Tue Mar 11 12:42:38 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 11 Mar 2025 15:42:38 -0400
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly
In-Reply-To: <20250311180807.GC5216@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com> <20250311180807.GC5216@willie-the-truck>
Message-ID: <CACu1E7Hw6vGbTQ7t-Hj3ziycZhPxtOGSDkt7o4fNUx91KDcXfg@mail.gmail.com>

On Tue, Mar 11, 2025 at 2:08?PM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> > In some cases drm/msm has to resume a stalled transaction directly in
> > its fault handler. Experimentally this doesn't work on SMMU500 if the
> > fault hasn't already been acknowledged by clearing FSR. Rather than
> > trying to clear FSR in msm's fault handler and implementing a
> > tricky handshake to avoid accidentally clearing FSR twice, we want to
> > clear FSR before calling the fault handlers, but this means that the
> > contents of registers can change underneath us in the fault handler and
> > msm currently uses a private function to read the register contents for
> > its own purposes in its fault handler, such as using the
> > implementation-defined FSYNR1 to determine which block caused the fault.
> > Fix this by making msm use the register values already read by arm-smmu
> > itself before clearing FSR rather than messing around with reading
> > registers directly.
> >
> > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
> >  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
> >  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
> >  3 files changed, 27 insertions(+), 27 deletions(-)
>
> [...]
>
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
> >       ARM_SMMU_DOMAIN_NESTED,
> >  };
> >
> > +struct arm_smmu_context_fault_info {
> > +     unsigned long iova;
> > +     u64 ttbr0;
> > +     u32 fsr;
> > +     u32 fsynr0;
> > +     u32 fsynr1;
> > +     u32 cbfrsynra;
> > +     u32 contextidr;
> > +};
> > +
> >  struct arm_smmu_domain {
> >       struct arm_smmu_device          *smmu;
> >       struct io_pgtable_ops           *pgtbl_ops;
> > @@ -380,6 +390,7 @@ struct arm_smmu_domain {
> >       const struct iommu_flush_ops    *flush_ops;
> >       struct arm_smmu_cfg             cfg;
> >       enum arm_smmu_domain_stage      stage;
> > +     struct arm_smmu_context_fault_info cfi;
>
> Does this mean we have to serialise all faults for a given domain? That
> can't be right...
>
> Will

They are already serialized? There's only one of each register per
context bank, so you can only have one context fault at a time per
context bank, and AFAIK a context bank is 1:1 with a domain. Also this
struct is only written and then read inside the context bank's
interrupt handler, and you can only have one interrupt at a time, no?

Connor


From nathan at kernel.org  Tue Mar 11 12:43:41 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Tue, 11 Mar 2025 20:43:41 +0100
Subject: [PATCH 0/2] ARM: Fix ARM_VECTORS with
 CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
Message-ID: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>

Hi all,

Christian sent a fix [1] for ARM_VECTORS with
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION that exposed a deficiency in ld.lld
with regards to KEEP() within an OVERLAY description. I have fixed that
in ld.lld [2] and added a patch before Christian's to disallow
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION when KEEP() cannot be used within
OVERLAY to keep everything working for all linkers.

[1]: https://lore.kernel.org/20250221125520.14035-1-ceggers at arri.de/
[2]: https://github.com/llvm/llvm-project/commit/381599f1fe973afad3094e55ec99b1620dba7d8c

---
Christian Eggers (1):
      ARM: add KEEP() keyword to ARM_VECTORS

Nathan Chancellor (1):
      ARM: Require linker to support KEEP within OVERLAY for DCE

 arch/arm/Kconfig                   |  2 +-
 arch/arm/include/asm/vmlinux.lds.h | 12 +++++++++---
 init/Kconfig                       |  5 +++++
 3 files changed, 15 insertions(+), 4 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250311-arm-fix-vectors-with-linker-dce-83475b0b8f5b

Best regards,
-- 
Nathan Chancellor <nathan at kernel.org>



From nathan at kernel.org  Tue Mar 11 12:43:42 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Tue, 11 Mar 2025 20:43:42 +0100
Subject: [PATCH 1/2] ARM: Require linker to support KEEP within OVERLAY for
 DCE
In-Reply-To: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
References: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
Message-ID: <20250311-arm-fix-vectors-with-linker-dce-v1-1-ec4c382e3bfd@kernel.org>

ld.lld prior to 21.0.0 does not support using the KEEP keyword within an
overlay description, which may be needed to avoid discarding necessary
sections within an overlay with '--gc-sections', which can be enabled
for the kernel via CONFIG_LD_DEAD_CODE_DATA_ELIMINATION.

Disallow CONFIG_LD_DEAD_CODE_DATA_ELIMINATION without support for KEEP
within OVERLAY and introduce a macro, OVERLAY_KEEP, that can be used to
conditionally add KEEP when it is properly supported to avoid breaking
old versions of ld.lld.

Cc: stable at vger.kernel.org
Link: https://github.com/llvm/llvm-project/commit/381599f1fe973afad3094e55ec99b1620dba7d8c
Signed-off-by: Nathan Chancellor <nathan at kernel.org>
---
 arch/arm/Kconfig                   | 2 +-
 arch/arm/include/asm/vmlinux.lds.h | 6 ++++++
 init/Kconfig                       | 5 +++++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 835b5f100e92..f3f6b7a33b79 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -121,7 +121,7 @@ config ARM
 	select HAVE_KERNEL_XZ
 	select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
 	select HAVE_KRETPROBES if HAVE_KPROBES
-	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD)
+	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_CAN_USE_KEEP_IN_OVERLAY)
 	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_NMI
 	select HAVE_OPTPROBES if !THUMB2_KERNEL
diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h
index d60f6e83a9f7..0f8ef1ed725e 100644
--- a/arch/arm/include/asm/vmlinux.lds.h
+++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -34,6 +34,12 @@
 #define NOCROSSREFS
 #endif
 
+#ifdef CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY
+#define OVERLAY_KEEP(x)		KEEP(x)
+#else
+#define OVERLAY_KEEP(x)		x
+#endif
+
 /* Set start/end symbol names to the LMA for the section */
 #define ARM_LMA(sym, section)						\
 	sym##_start = LOADADDR(section);				\
diff --git a/init/Kconfig b/init/Kconfig
index d0d021b3fa3b..fc994f5cd5db 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -129,6 +129,11 @@ config CC_HAS_COUNTED_BY
 	# https://github.com/llvm/llvm-project/pull/112636
 	depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
 
+config LD_CAN_USE_KEEP_IN_OVERLAY
+	# ld.lld prior to 21.0.0 did not support KEEP within an overlay description
+	# https://github.com/llvm/llvm-project/pull/130661
+	def_bool LD_IS_BFD || LLD_VERSION >= 210000
+
 config RUSTC_HAS_COERCE_POINTEE
 	def_bool RUSTC_VERSION >= 108400
 

-- 
2.48.1



From robh at kernel.org  Tue Mar 11 12:28:41 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:28:41 -0500
Subject: [PATCH v2 1/6] ASoC: dt-bindings: meson: meson-axg-audio-arb:
 claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-2-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
 <20250309182127.1322890-2-jan.dakinevich@salutedevices.com>
Message-ID: <174172132043.4178261.11828911327621158641.robh@kernel.org>


On Sun, 09 Mar 2025 21:21:22 +0300, Jan Dakinevich wrote:
> Add "amlogic,meson-a1-audio-arb" compatible string alias to
> "amlogic,meson-sm1-audio-arb".
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../bindings/reset/amlogic,meson-axg-audio-arb.yaml    | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 11 12:28:59 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:28:59 -0500
Subject: [PATCH v2 2/6] ASoC: dt-bindings: meson: axg-fifo: claim support
 of A1 SoC family
In-Reply-To: <20250309182127.1322890-3-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
 <20250309182127.1322890-3-jan.dakinevich@salutedevices.com>
Message-ID: <174172133877.4178691.16143200124324981216.robh@kernel.org>


On Sun, 09 Mar 2025 21:21:23 +0300, Jan Dakinevich wrote:
> Add "amlogic,a1-toddr" and "amlogic,a1-frddr" compatible string aliases
> to "amlogic,sm1-toddr" and "amlogic,sm1-frddr" respectevely.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../devicetree/bindings/sound/amlogic,axg-fifo.yaml       | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 11 12:29:43 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:29:43 -0500
Subject: [PATCH v2 3/6] ASoC: dt-bindings: meson: axg-pdm: claim support
 of A1 SoC family
In-Reply-To: <20250309182127.1322890-4-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
 <20250309182127.1322890-4-jan.dakinevich@salutedevices.com>
Message-ID: <174172138330.4179604.2763607780913254611.robh@kernel.org>


On Sun, 09 Mar 2025 21:21:24 +0300, Jan Dakinevich wrote:
> Add "amlogic,a1-pdm" compatible string alias to "amlogic,axg-pdm".
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  Documentation/devicetree/bindings/sound/amlogic,axg-pdm.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 11 12:30:17 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:30:17 -0500
Subject: [PATCH v2 4/6] ASoC: dt-bindings: meson: axg-tdm-formatters:
 claim support of A1 SoC family
In-Reply-To: <20250309182127.1322890-5-jan.dakinevich@salutedevices.com>
References: <20250309182127.1322890-1-jan.dakinevich@salutedevices.com>
 <20250309182127.1322890-5-jan.dakinevich@salutedevices.com>
Message-ID: <174172141671.4180325.1225905170416898844.robh@kernel.org>


On Sun, 09 Mar 2025 21:21:25 +0300, Jan Dakinevich wrote:
> Add "amlogic,a1-tdmout" and "amlogic,a1-tdmin" compatible string aliases
> to "amlogic,sm1-tdmout" and "amlogic,sm1-tdmin" respectevely.
> 
> Signed-off-by: Jan Dakinevich <jan.dakinevich at salutedevices.com>
> ---
>  .../sound/amlogic,axg-tdm-formatters.yaml     | 22 ++++++++++++-------
>  1 file changed, 14 insertions(+), 8 deletions(-)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 11 12:31:36 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:31:36 -0500
Subject: [PATCH v2 1/5] dt-bindings: net: rockchip-dwmac: Add compatible
 string for RK3528
In-Reply-To: <20250309232622.1498084-2-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
 <20250309232622.1498084-2-jonas@kwiboo.se>
Message-ID: <174172149414.4181803.16963634632371171945.robh@kernel.org>


On Sun, 09 Mar 2025 23:26:11 +0000, Jonas Karlman wrote:
> Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
> Ethernet QoS IP.
> 
> Add compatible string for the RK3528 variant.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> ---
> Changes in v2:
> - Restrict the minItems: 4 change to rockchip,rk3528-gmac
> 
> The enum will be extended in a future patch, Pending RK3562 and a future
> RK3506 variant also only have 4 clocks.
> 
> Because snps,dwmac-4.20a is already listed in snps,dwmac.yaml adding the
> rockchip,rk3528-gmac compatible did not seem necessary.
> ---
>  .../devicetree/bindings/net/rockchip-dwmac.yaml  | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From krzk at kernel.org  Tue Mar 11 12:32:50 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 11 Mar 2025 20:32:50 +0100
Subject: [PATCH v4 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250307-pinctrl-fltcon-suspend-v4-2-2d775e486036@linaro.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-2-2d775e486036@linaro.org>
Message-ID: <c2e2c78c-e85e-406a-90a7-07d5b4fa82a6@kernel.org>

On 07/03/2025 11:29, Peter Griffin wrote:
> gs101 needs it's own suspend/resume callbacks to use the newly
> added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> registers. It also differs to previous SoCs in that fltcon1
> register doesn't always exist for each bank.
> 
> exynosautov920 also has dedicated logic for using eint_con_offset
> and eint_mask_offset for saving & restoring it's registers.
> 
> Refactor the existing platform specific suspend/resume callback
> so that each SoC variant has their own callback containing the
> SoC specific logic.
> 


> Additionally we now call drvdata->suspend() & drvdata->resume()
> from within the loop that iterates the banks in
> samsung_pinctrl_suspend() and samsung_pinctrl_resume().
>
> This simplifies the logic, and allows us to remove the
> clk_enable() and clk_disable() from the callbacks.

Can you make this a separate commit? This would be nicely self-contained
and without any functional impact.

Getting own suspend/resume would be the next commit.


Best regards,
Krzysztof


From Markus.Elfring at web.de  Tue Mar 11 12:33:29 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Tue, 11 Mar 2025 20:33:29 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250311180254.149484-1-csokas.bence@prolan.hu>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
Message-ID: <0a2e1d9f-4046-49ee-9513-dbb3af9cffe9@web.de>

> Clean up error handling by using devm functions
> and dev_err_probe(). This should make it easier
?

You may occasionally put more than 47 characters into text lines
of such a change description.

Regards,
Markus


From nathan at kernel.org  Tue Mar 11 12:43:43 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Tue, 11 Mar 2025 20:43:43 +0100
Subject: [PATCH 2/2] ARM: add KEEP() keyword to ARM_VECTORS
In-Reply-To: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
References: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
Message-ID: <20250311-arm-fix-vectors-with-linker-dce-v1-2-ec4c382e3bfd@kernel.org>

From: Christian Eggers <ceggers at arri.de>

Without this, the vectors are removed if LD_DEAD_CODE_DATA_ELIMINATION
is enabled.  At startup, the CPU (silently) hangs in the undefined
instruction exception as soon as the first timer interrupt arrives.

On my setup, the system also boots fine without the 2nd and 3rd KEEP()
statements, so I cannot tell whether these are actually required.

Cc: stable at vger.kernel.org
Fixes: ed0f94102251 ("ARM: 9404/1: arm32: enable HAVE_LD_DEAD_CODE_DATA_ELIMINATION")
Signed-off-by: Christian Eggers <ceggers at arri.de>
[nathan: Use OVERLAY_KEEP() to avoid breaking old ld.lld versions]
Signed-off-by: Nathan Chancellor <nathan at kernel.org>
---
 arch/arm/include/asm/vmlinux.lds.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h
index 0f8ef1ed725e..14811b4f48ec 100644
--- a/arch/arm/include/asm/vmlinux.lds.h
+++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -131,13 +131,13 @@
 	__vectors_lma = .;						\
 	OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {		\
 		.vectors {						\
-			*(.vectors)					\
+			OVERLAY_KEEP(*(.vectors))			\
 		}							\
 		.vectors.bhb.loop8 {					\
-			*(.vectors.bhb.loop8)				\
+			OVERLAY_KEEP(*(.vectors.bhb.loop8))		\
 		}							\
 		.vectors.bhb.bpiall {					\
-			*(.vectors.bhb.bpiall)				\
+			OVERLAY_KEEP(*(.vectors.bhb.bpiall))		\
 		}							\
 	}								\
 	ARM_LMA(__vectors, .vectors);					\

-- 
2.48.1



From nicolinc at nvidia.com  Tue Mar 11 12:44:25 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:25 -0700
Subject: [PATCH v9 07/14] iommufd/viommu: Add iommufd_viommu_report_event helper
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <44be825042c8255e75d0151b338ffd8ba0e4920b.1741719725.git.nicolinc@nvidia.com>

Similar to iommu_report_device_fault, this allows IOMMU drivers to report
vIOMMU events from threaded IRQ handlers to user space hypervisors.

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 include/linux/iommufd.h        | 11 ++++++++
 drivers/iommu/iommufd/driver.c | 48 ++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 05cb393aff0a..60eff9272551 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -11,6 +11,7 @@
 #include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/xarray.h>
+#include <uapi/linux/iommufd.h>
 
 struct device;
 struct file;
@@ -192,6 +193,9 @@ struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
 				       unsigned long vdev_id);
 int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
 			       struct device *dev, unsigned long *vdev_id);
+int iommufd_viommu_report_event(struct iommufd_viommu *viommu,
+				enum iommu_veventq_type type, void *event_data,
+				size_t data_len);
 #else /* !CONFIG_IOMMUFD_DRIVER_CORE */
 static inline struct iommufd_object *
 _iommufd_object_alloc(struct iommufd_ctx *ictx, size_t size,
@@ -212,6 +216,13 @@ static inline int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
 {
 	return -ENOENT;
 }
+
+static inline int iommufd_viommu_report_event(struct iommufd_viommu *viommu,
+					      enum iommu_veventq_type type,
+					      void *event_data, size_t data_len)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_IOMMUFD_DRIVER_CORE */
 
 /*
diff --git a/drivers/iommu/iommufd/driver.c b/drivers/iommu/iommufd/driver.c
index f132b98fb899..75b365561c16 100644
--- a/drivers/iommu/iommufd/driver.c
+++ b/drivers/iommu/iommufd/driver.c
@@ -73,5 +73,53 @@ int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_viommu_get_vdev_id, "IOMMUFD");
 
+/*
+ * Typically called in driver's threaded IRQ handler.
+ * The @type and @event_data must be defined in include/uapi/linux/iommufd.h
+ */
+int iommufd_viommu_report_event(struct iommufd_viommu *viommu,
+				enum iommu_veventq_type type, void *event_data,
+				size_t data_len)
+{
+	struct iommufd_veventq *veventq;
+	struct iommufd_vevent *vevent;
+	int rc = 0;
+
+	if (WARN_ON_ONCE(!data_len || !event_data))
+		return -EINVAL;
+
+	down_read(&viommu->veventqs_rwsem);
+
+	veventq = iommufd_viommu_find_veventq(viommu, type);
+	if (!veventq) {
+		rc = -EOPNOTSUPP;
+		goto out_unlock_veventqs;
+	}
+
+	spin_lock(&veventq->common.lock);
+	if (veventq->num_events == veventq->depth) {
+		vevent = &veventq->lost_events_header;
+		goto out_set_header;
+	}
+
+	vevent = kmalloc(struct_size(vevent, event_data, data_len), GFP_ATOMIC);
+	if (!vevent) {
+		rc = -ENOMEM;
+		vevent = &veventq->lost_events_header;
+		goto out_set_header;
+	}
+	memcpy(vevent->event_data, event_data, data_len);
+	vevent->data_len = data_len;
+	veventq->num_events++;
+
+out_set_header:
+	iommufd_vevent_handler(veventq, vevent);
+	spin_unlock(&veventq->common.lock);
+out_unlock_veventqs:
+	up_read(&viommu->veventqs_rwsem);
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_viommu_report_event, "IOMMUFD");
+
 MODULE_DESCRIPTION("iommufd code shared with builtin modules");
 MODULE_LICENSE("GPL");
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:21 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:21 -0700
Subject: [PATCH v9 03/14] iommufd: Abstract an iommufd_eventq from iommufd_fault
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <e7336a857954209aabb466e0694aab323da95d90.1741719725.git.nicolinc@nvidia.com>

The fault object was designed exclusively for hwpt's IO page faults (PRI).
But its queue implementation can be reused for other purposes too, such as
hardware IRQ and event injections to user space.

Meanwhile, a fault object holds a list of faults. So it's more accurate to
call it a "fault queue". Combining the reusing idea above, abstract a new
iommufd_eventq as a common structure embedded into struct iommufd_fault,
similar to hwpt_paging holding a common hwpt.

Add a common iommufd_eventq_ops and iommufd_eventq_init to prepare for an
IOMMUFD_OBJ_VEVENTQ (vIOMMU Event Queue).

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/iommufd_private.h |  28 ++++--
 drivers/iommu/iommufd/fault.c           | 111 +++++++++++++-----------
 drivers/iommu/iommufd/hw_pagetable.c    |   6 +-
 3 files changed, 82 insertions(+), 63 deletions(-)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 1c58f5fe17b4..44fb30af10b0 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -454,20 +454,13 @@ void iopt_remove_access(struct io_pagetable *iopt,
 			u32 iopt_access_list_id);
 void iommufd_access_destroy_object(struct iommufd_object *obj);
 
-/*
- * An iommufd_fault object represents an interface to deliver I/O page faults
- * to the user space. These objects are created/destroyed by the user space and
- * associated with hardware page table objects during page-table allocation.
- */
-struct iommufd_fault {
+struct iommufd_eventq {
 	struct iommufd_object obj;
 	struct iommufd_ctx *ictx;
 	struct file *filep;
 
 	spinlock_t lock; /* protects the deliver list */
 	struct list_head deliver;
-	struct mutex mutex; /* serializes response flows */
-	struct xarray response;
 
 	struct wait_queue_head wait_queue;
 };
@@ -480,12 +473,29 @@ struct iommufd_attach_handle {
 /* Convert an iommu attach handle to iommufd handle. */
 #define to_iommufd_handle(hdl)	container_of(hdl, struct iommufd_attach_handle, handle)
 
+/*
+ * An iommufd_fault object represents an interface to deliver I/O page faults
+ * to the user space. These objects are created/destroyed by the user space and
+ * associated with hardware page table objects during page-table allocation.
+ */
+struct iommufd_fault {
+	struct iommufd_eventq common;
+	struct mutex mutex; /* serializes response flows */
+	struct xarray response;
+};
+
+static inline struct iommufd_fault *
+eventq_to_fault(struct iommufd_eventq *eventq)
+{
+	return container_of(eventq, struct iommufd_fault, common);
+}
+
 static inline struct iommufd_fault *
 iommufd_get_fault(struct iommufd_ucmd *ucmd, u32 id)
 {
 	return container_of(iommufd_get_object(ucmd->ictx, id,
 					       IOMMUFD_OBJ_FAULT),
-			    struct iommufd_fault, obj);
+			    struct iommufd_fault, common.obj);
 }
 
 int iommufd_fault_alloc(struct iommufd_ucmd *ucmd);
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index 5d8de98732b6..f8e60e5879d1 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -17,6 +17,8 @@
 #include "../iommu-priv.h"
 #include "iommufd_private.h"
 
+/* IOMMUFD_OBJ_FAULT Functions */
+
 int iommufd_fault_iopf_enable(struct iommufd_device *idev)
 {
 	struct device *dev = idev->dev;
@@ -73,13 +75,13 @@ void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
 	INIT_LIST_HEAD(&free_list);
 
 	mutex_lock(&fault->mutex);
-	spin_lock(&fault->lock);
-	list_for_each_entry_safe(group, next, &fault->deliver, node) {
+	spin_lock(&fault->common.lock);
+	list_for_each_entry_safe(group, next, &fault->common.deliver, node) {
 		if (group->attach_handle != &handle->handle)
 			continue;
 		list_move(&group->node, &free_list);
 	}
-	spin_unlock(&fault->lock);
+	spin_unlock(&fault->common.lock);
 
 	list_for_each_entry_safe(group, next, &free_list, node) {
 		list_del(&group->node);
@@ -99,7 +101,9 @@ void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
 
 void iommufd_fault_destroy(struct iommufd_object *obj)
 {
-	struct iommufd_fault *fault = container_of(obj, struct iommufd_fault, obj);
+	struct iommufd_eventq *eventq =
+		container_of(obj, struct iommufd_eventq, obj);
+	struct iommufd_fault *fault = eventq_to_fault(eventq);
 	struct iopf_group *group, *next;
 	unsigned long index;
 
@@ -109,7 +113,7 @@ void iommufd_fault_destroy(struct iommufd_object *obj)
 	 * accessing this pointer. Therefore, acquiring the mutex here
 	 * is unnecessary.
 	 */
-	list_for_each_entry_safe(group, next, &fault->deliver, node) {
+	list_for_each_entry_safe(group, next, &fault->common.deliver, node) {
 		list_del(&group->node);
 		iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
 		iopf_free_group(group);
@@ -142,15 +146,15 @@ static void iommufd_compose_fault_message(struct iommu_fault *fault,
 static struct iopf_group *
 iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
 {
-	struct list_head *list = &fault->deliver;
+	struct list_head *list = &fault->common.deliver;
 	struct iopf_group *group = NULL;
 
-	spin_lock(&fault->lock);
+	spin_lock(&fault->common.lock);
 	if (!list_empty(list)) {
 		group = list_first_entry(list, struct iopf_group, node);
 		list_del(&group->node);
 	}
-	spin_unlock(&fault->lock);
+	spin_unlock(&fault->common.lock);
 	return group;
 }
 
@@ -158,16 +162,17 @@ iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
 static void iommufd_fault_deliver_restore(struct iommufd_fault *fault,
 					  struct iopf_group *group)
 {
-	spin_lock(&fault->lock);
-	list_add(&group->node, &fault->deliver);
-	spin_unlock(&fault->lock);
+	spin_lock(&fault->common.lock);
+	list_add(&group->node, &fault->common.deliver);
+	spin_unlock(&fault->common.lock);
 }
 
 static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
 				       size_t count, loff_t *ppos)
 {
 	size_t fault_size = sizeof(struct iommu_hwpt_pgfault);
-	struct iommufd_fault *fault = filep->private_data;
+	struct iommufd_eventq *eventq = filep->private_data;
+	struct iommufd_fault *fault = eventq_to_fault(eventq);
 	struct iommu_hwpt_pgfault data = {};
 	struct iommufd_device *idev;
 	struct iopf_group *group;
@@ -216,7 +221,8 @@ static ssize_t iommufd_fault_fops_write(struct file *filep, const char __user *b
 					size_t count, loff_t *ppos)
 {
 	size_t response_size = sizeof(struct iommu_hwpt_page_response);
-	struct iommufd_fault *fault = filep->private_data;
+	struct iommufd_eventq *eventq = filep->private_data;
+	struct iommufd_fault *fault = eventq_to_fault(eventq);
 	struct iommu_hwpt_page_response response;
 	struct iopf_group *group;
 	size_t done = 0;
@@ -256,59 +262,61 @@ static ssize_t iommufd_fault_fops_write(struct file *filep, const char __user *b
 	return done == 0 ? rc : done;
 }
 
-static __poll_t iommufd_fault_fops_poll(struct file *filep,
-					struct poll_table_struct *wait)
+/* Common Event Queue Functions */
+
+static __poll_t iommufd_eventq_fops_poll(struct file *filep,
+					 struct poll_table_struct *wait)
 {
-	struct iommufd_fault *fault = filep->private_data;
+	struct iommufd_eventq *eventq = filep->private_data;
 	__poll_t pollflags = EPOLLOUT;
 
-	poll_wait(filep, &fault->wait_queue, wait);
-	spin_lock(&fault->lock);
-	if (!list_empty(&fault->deliver))
+	poll_wait(filep, &eventq->wait_queue, wait);
+	spin_lock(&eventq->lock);
+	if (!list_empty(&eventq->deliver))
 		pollflags |= EPOLLIN | EPOLLRDNORM;
-	spin_unlock(&fault->lock);
+	spin_unlock(&eventq->lock);
 
 	return pollflags;
 }
 
-static int iommufd_fault_fops_release(struct inode *inode, struct file *filep)
+static int iommufd_eventq_fops_release(struct inode *inode, struct file *filep)
 {
-	struct iommufd_fault *fault = filep->private_data;
+	struct iommufd_eventq *eventq = filep->private_data;
 
-	refcount_dec(&fault->obj.users);
-	iommufd_ctx_put(fault->ictx);
+	refcount_dec(&eventq->obj.users);
+	iommufd_ctx_put(eventq->ictx);
 	return 0;
 }
 
-#define INIT_FAULT_FOPS(read_op, write_op)                                     \
+#define INIT_EVENTQ_FOPS(read_op, write_op)                                    \
 	((const struct file_operations){                                       \
 		.owner = THIS_MODULE,                                          \
 		.open = nonseekable_open,                                      \
 		.read = read_op,                                               \
 		.write = write_op,                                             \
-		.poll = iommufd_fault_fops_poll,                               \
-		.release = iommufd_fault_fops_release,                         \
+		.poll = iommufd_eventq_fops_poll,                              \
+		.release = iommufd_eventq_fops_release,                        \
 	})
 
-static int iommufd_fault_init(struct iommufd_fault *fault, char *name,
-			      struct iommufd_ctx *ictx,
-			      const struct file_operations *fops)
+static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
+			       struct iommufd_ctx *ictx,
+			       const struct file_operations *fops)
 {
 	struct file *filep;
 	int fdno;
 
-	spin_lock_init(&fault->lock);
-	INIT_LIST_HEAD(&fault->deliver);
-	init_waitqueue_head(&fault->wait_queue);
+	spin_lock_init(&eventq->lock);
+	INIT_LIST_HEAD(&eventq->deliver);
+	init_waitqueue_head(&eventq->wait_queue);
 
-	filep = anon_inode_getfile(name, fops, fault, O_RDWR);
+	filep = anon_inode_getfile(name, fops, eventq, O_RDWR);
 	if (IS_ERR(filep))
 		return PTR_ERR(filep);
 
-	fault->ictx = ictx;
-	iommufd_ctx_get(fault->ictx);
-	fault->filep = filep;
-	refcount_inc(&fault->obj.users);
+	eventq->ictx = ictx;
+	iommufd_ctx_get(eventq->ictx);
+	eventq->filep = filep;
+	refcount_inc(&eventq->obj.users);
 
 	fdno = get_unused_fd_flags(O_CLOEXEC);
 	if (fdno < 0)
@@ -317,7 +325,7 @@ static int iommufd_fault_init(struct iommufd_fault *fault, char *name,
 }
 
 static const struct file_operations iommufd_fault_fops =
-	INIT_FAULT_FOPS(iommufd_fault_fops_read, iommufd_fault_fops_write);
+	INIT_EVENTQ_FOPS(iommufd_fault_fops_read, iommufd_fault_fops_write);
 
 int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 {
@@ -329,36 +337,37 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 	if (cmd->flags)
 		return -EOPNOTSUPP;
 
-	fault = iommufd_object_alloc(ucmd->ictx, fault, IOMMUFD_OBJ_FAULT);
+	fault = __iommufd_object_alloc(ucmd->ictx, fault, IOMMUFD_OBJ_FAULT,
+				       common.obj);
 	if (IS_ERR(fault))
 		return PTR_ERR(fault);
 
 	xa_init_flags(&fault->response, XA_FLAGS_ALLOC1);
 	mutex_init(&fault->mutex);
 
-	fdno = iommufd_fault_init(fault, "[iommufd-pgfault]", ucmd->ictx,
-				  &iommufd_fault_fops);
+	fdno = iommufd_eventq_init(&fault->common, "[iommufd-pgfault]",
+				   ucmd->ictx, &iommufd_fault_fops);
 	if (fdno < 0) {
 		rc = fdno;
 		goto out_abort;
 	}
 
-	cmd->out_fault_id = fault->obj.id;
+	cmd->out_fault_id = fault->common.obj.id;
 	cmd->out_fault_fd = fdno;
 
 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
 	if (rc)
 		goto out_put_fdno;
-	iommufd_object_finalize(ucmd->ictx, &fault->obj);
+	iommufd_object_finalize(ucmd->ictx, &fault->common.obj);
 
-	fd_install(fdno, fault->filep);
+	fd_install(fdno, fault->common.filep);
 
 	return 0;
 out_put_fdno:
 	put_unused_fd(fdno);
-	fput(fault->filep);
+	fput(fault->common.filep);
 out_abort:
-	iommufd_object_abort_and_destroy(ucmd->ictx, &fault->obj);
+	iommufd_object_abort_and_destroy(ucmd->ictx, &fault->common.obj);
 
 	return rc;
 }
@@ -371,11 +380,11 @@ int iommufd_fault_iopf_handler(struct iopf_group *group)
 	hwpt = group->attach_handle->domain->iommufd_hwpt;
 	fault = hwpt->fault;
 
-	spin_lock(&fault->lock);
-	list_add_tail(&group->node, &fault->deliver);
-	spin_unlock(&fault->lock);
+	spin_lock(&fault->common.lock);
+	list_add_tail(&group->node, &fault->common.deliver);
+	spin_unlock(&fault->common.lock);
 
-	wake_up_interruptible(&fault->wait_queue);
+	wake_up_interruptible(&fault->common.wait_queue);
 
 	return 0;
 }
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 268315b1d8bc..ee40235f9285 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -14,7 +14,7 @@ static void __iommufd_hwpt_destroy(struct iommufd_hw_pagetable *hwpt)
 		iommu_domain_free(hwpt->domain);
 
 	if (hwpt->fault)
-		refcount_dec(&hwpt->fault->obj.users);
+		refcount_dec(&hwpt->fault->common.obj.users);
 }
 
 void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)
@@ -412,8 +412,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
 		}
 		hwpt->fault = fault;
 		hwpt->domain->iopf_handler = iommufd_fault_iopf_handler;
-		refcount_inc(&fault->obj.users);
-		iommufd_put_object(ucmd->ictx, &fault->obj);
+		refcount_inc(&fault->common.obj.users);
+		iommufd_put_object(ucmd->ictx, &fault->common.obj);
 	}
 	hwpt->domain->iommufd_hwpt = hwpt;
 
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:27 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:27 -0700
Subject: [PATCH v9 09/14] iommufd/selftest: Add IOMMU_TEST_OP_TRIGGER_VEVENT for vEVENTQ coverage
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <1ea874d20e56d65e7cfd6e0e8e01bd3dbd038761.1741719725.git.nicolinc@nvidia.com>

The handler will get vDEVICE object from the given mdev and convert it to
its per-vIOMMU virtual ID to mimic a real IOMMU driver.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/iommufd_test.h | 10 ++++++++++
 drivers/iommu/iommufd/selftest.c     | 30 ++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h
index a6b7a163f636..87e9165cea27 100644
--- a/drivers/iommu/iommufd/iommufd_test.h
+++ b/drivers/iommu/iommufd/iommufd_test.h
@@ -24,6 +24,7 @@ enum {
 	IOMMU_TEST_OP_MD_CHECK_IOTLB,
 	IOMMU_TEST_OP_TRIGGER_IOPF,
 	IOMMU_TEST_OP_DEV_CHECK_CACHE,
+	IOMMU_TEST_OP_TRIGGER_VEVENT,
 };
 
 enum {
@@ -145,6 +146,9 @@ struct iommu_test_cmd {
 			__u32 id;
 			__u32 cache;
 		} check_dev_cache;
+		struct {
+			__u32 dev_id;
+		} trigger_vevent;
 	};
 	__u32 last;
 };
@@ -212,4 +216,10 @@ struct iommu_viommu_invalidate_selftest {
 	__u32 cache_id;
 };
 
+#define IOMMU_VEVENTQ_TYPE_SELFTEST 0xbeefbeef
+
+struct iommu_viommu_event_selftest {
+	__u32 virt_id;
+};
+
 #endif
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index ba84bacbce2e..d55dde28e9bc 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -1621,6 +1621,34 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd,
 	return 0;
 }
 
+static int iommufd_test_trigger_vevent(struct iommufd_ucmd *ucmd,
+				       struct iommu_test_cmd *cmd)
+{
+	struct iommu_viommu_event_selftest test = {};
+	struct iommufd_device *idev;
+	struct mock_dev *mdev;
+	int rc = -ENOENT;
+
+	idev = iommufd_get_device(ucmd, cmd->trigger_vevent.dev_id);
+	if (IS_ERR(idev))
+		return PTR_ERR(idev);
+	mdev = to_mock_dev(idev->dev);
+
+	down_read(&mdev->viommu_rwsem);
+	if (!mdev->viommu || !mdev->vdev_id)
+		goto out_unlock;
+
+	test.virt_id = mdev->vdev_id;
+	rc = iommufd_viommu_report_event(&mdev->viommu->core,
+					 IOMMU_VEVENTQ_TYPE_SELFTEST, &test,
+					 sizeof(test));
+out_unlock:
+	up_read(&mdev->viommu_rwsem);
+	iommufd_put_object(ucmd->ictx, &idev->obj);
+
+	return rc;
+}
+
 void iommufd_selftest_destroy(struct iommufd_object *obj)
 {
 	struct selftest_obj *sobj = to_selftest_obj(obj);
@@ -1702,6 +1730,8 @@ int iommufd_test(struct iommufd_ucmd *ucmd)
 					  cmd->dirty.flags);
 	case IOMMU_TEST_OP_TRIGGER_IOPF:
 		return iommufd_test_trigger_iopf(ucmd, cmd);
+	case IOMMU_TEST_OP_TRIGGER_VEVENT:
+		return iommufd_test_trigger_vevent(ucmd, cmd);
 	default:
 		return -EOPNOTSUPP;
 	}
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:26 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:26 -0700
Subject: [PATCH v9 08/14] iommufd/selftest: Require vdev_id when attaching to a nested domain
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <4051ca8a819e51cb30de6b4fe9e4d94d956afe3d.1741719725.git.nicolinc@nvidia.com>

When attaching a device to a vIOMMU-based nested domain, vdev_id must be
present. Add a piece of code hard-requesting it, preparing for a vEVENTQ
support in the following patch. Then, update the TEST_F.

A HWPT-based nested domain will return a NULL new_viommu, thus no such a
vDEVICE requirement.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/selftest.c        | 24 ++++++++++++++++++++++++
 tools/testing/selftests/iommu/iommufd.c |  5 +++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index d40deb0a4f06..ba84bacbce2e 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -161,7 +161,10 @@ enum selftest_obj_type {
 
 struct mock_dev {
 	struct device dev;
+	struct mock_viommu *viommu;
+	struct rw_semaphore viommu_rwsem;
 	unsigned long flags;
+	unsigned long vdev_id;
 	int id;
 	u32 cache[MOCK_DEV_CACHE_NUM];
 };
@@ -193,10 +196,30 @@ static int mock_domain_nop_attach(struct iommu_domain *domain,
 				  struct device *dev)
 {
 	struct mock_dev *mdev = to_mock_dev(dev);
+	struct mock_viommu *new_viommu = NULL;
+	unsigned long vdev_id = 0;
+	int rc;
 
 	if (domain->dirty_ops && (mdev->flags & MOCK_FLAGS_DEVICE_NO_DIRTY))
 		return -EINVAL;
 
+	iommu_group_mutex_assert(dev);
+	if (domain->type == IOMMU_DOMAIN_NESTED) {
+		new_viommu = to_mock_nested(domain)->mock_viommu;
+		if (new_viommu) {
+			rc = iommufd_viommu_get_vdev_id(&new_viommu->core, dev,
+							&vdev_id);
+			if (rc)
+				return rc;
+		}
+	}
+	if (new_viommu != mdev->viommu) {
+		down_write(&mdev->viommu_rwsem);
+		mdev->viommu = new_viommu;
+		mdev->vdev_id = vdev_id;
+		up_write(&mdev->viommu_rwsem);
+	}
+
 	return 0;
 }
 
@@ -850,6 +873,7 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
 	if (!mdev)
 		return ERR_PTR(-ENOMEM);
 
+	init_rwsem(&mdev->viommu_rwsem);
 	device_initialize(&mdev->dev);
 	mdev->flags = dev_flags;
 	mdev->dev.release = mock_dev_release;
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 618c03bb6509..6a050a1d64ed 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -2740,6 +2740,7 @@ TEST_F(iommufd_viommu, viommu_alloc_nested_iopf)
 	uint32_t iopf_hwpt_id;
 	uint32_t fault_id;
 	uint32_t fault_fd;
+	uint32_t vdev_id;
 
 	if (self->device_id) {
 		test_ioctl_fault_alloc(&fault_id, &fault_fd);
@@ -2756,6 +2757,10 @@ TEST_F(iommufd_viommu, viommu_alloc_nested_iopf)
 			&iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST, &data,
 			sizeof(data));
 
+		/* Must allocate vdevice before attaching to a nested hwpt */
+		test_err_mock_domain_replace(ENOENT, self->stdev_id,
+					     iopf_hwpt_id);
+		test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
 		test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
 		EXPECT_ERRNO(EBUSY,
 			     _test_ioctl_destroy(self->fd, iopf_hwpt_id));
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:24 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:24 -0700
Subject: [PATCH v9 06/14] iommufd/viommu: Add iommufd_viommu_get_vdev_id helper
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <18b8e8bc1b8104d43b205d21602c036fd0804e56.1741719725.git.nicolinc@nvidia.com>

This is a reverse search v.s. iommufd_viommu_find_dev, as drivers may want
to convert a struct device pointer (physical) to its virtual device ID for
an event injection to the user space VM.

Again, this avoids exposing more core structures to the drivers, than the
iommufd_viommu alone.

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 include/linux/iommufd.h        |  9 +++++++++
 drivers/iommu/iommufd/driver.c | 24 ++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 8948b1836940..05cb393aff0a 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -190,6 +190,8 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
 					     enum iommufd_object_type type);
 struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
 				       unsigned long vdev_id);
+int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
+			       struct device *dev, unsigned long *vdev_id);
 #else /* !CONFIG_IOMMUFD_DRIVER_CORE */
 static inline struct iommufd_object *
 _iommufd_object_alloc(struct iommufd_ctx *ictx, size_t size,
@@ -203,6 +205,13 @@ iommufd_viommu_find_dev(struct iommufd_viommu *viommu, unsigned long vdev_id)
 {
 	return NULL;
 }
+
+static inline int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
+					     struct device *dev,
+					     unsigned long *vdev_id)
+{
+	return -ENOENT;
+}
 #endif /* CONFIG_IOMMUFD_DRIVER_CORE */
 
 /*
diff --git a/drivers/iommu/iommufd/driver.c b/drivers/iommu/iommufd/driver.c
index 2d98b04ff1cb..f132b98fb899 100644
--- a/drivers/iommu/iommufd/driver.c
+++ b/drivers/iommu/iommufd/driver.c
@@ -49,5 +49,29 @@ struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, "IOMMUFD");
 
+/* Return -ENOENT if device is not associated to the vIOMMU */
+int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu,
+			       struct device *dev, unsigned long *vdev_id)
+{
+	struct iommufd_vdevice *vdev;
+	unsigned long index;
+	int rc = -ENOENT;
+
+	if (WARN_ON_ONCE(!vdev_id))
+		return -EINVAL;
+
+	xa_lock(&viommu->vdevs);
+	xa_for_each(&viommu->vdevs, index, vdev) {
+		if (vdev->dev == dev) {
+			*vdev_id = vdev->id;
+			rc = 0;
+			break;
+		}
+	}
+	xa_unlock(&viommu->vdevs);
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_viommu_get_vdev_id, "IOMMUFD");
+
 MODULE_DESCRIPTION("iommufd code shared with builtin modules");
 MODULE_LICENSE("GPL");
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:20 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:20 -0700
Subject: [PATCH v9 02/14] iommufd/fault: Add an iommufd_fault_init() helper
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <a9522c521909baeb1bd843950b2490478f3d06e0.1741719725.git.nicolinc@nvidia.com>

The infrastructure of a fault object will be shared with a new vEVENTQ
object in a following change. Add an iommufd_fault_init helper and an
INIT_EVENTQ_FOPS marco for a vEVENTQ allocator to use too.

Reorder the iommufd_ctx_get and refcount_inc, to keep them symmetrical
with the iommufd_fault_fops_release().

Since the new vEVENTQ doesn't need "response" and its "mutex", so keep
the xa_init_flags and mutex_init in their original locations.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/fault.c | 70 +++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index 29e3a97c73c6..5d8de98732b6 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -280,20 +280,49 @@ static int iommufd_fault_fops_release(struct inode *inode, struct file *filep)
 	return 0;
 }
 
-static const struct file_operations iommufd_fault_fops = {
-	.owner		= THIS_MODULE,
-	.open		= nonseekable_open,
-	.read		= iommufd_fault_fops_read,
-	.write		= iommufd_fault_fops_write,
-	.poll		= iommufd_fault_fops_poll,
-	.release	= iommufd_fault_fops_release,
-};
+#define INIT_FAULT_FOPS(read_op, write_op)                                     \
+	((const struct file_operations){                                       \
+		.owner = THIS_MODULE,                                          \
+		.open = nonseekable_open,                                      \
+		.read = read_op,                                               \
+		.write = write_op,                                             \
+		.poll = iommufd_fault_fops_poll,                               \
+		.release = iommufd_fault_fops_release,                         \
+	})
+
+static int iommufd_fault_init(struct iommufd_fault *fault, char *name,
+			      struct iommufd_ctx *ictx,
+			      const struct file_operations *fops)
+{
+	struct file *filep;
+	int fdno;
+
+	spin_lock_init(&fault->lock);
+	INIT_LIST_HEAD(&fault->deliver);
+	init_waitqueue_head(&fault->wait_queue);
+
+	filep = anon_inode_getfile(name, fops, fault, O_RDWR);
+	if (IS_ERR(filep))
+		return PTR_ERR(filep);
+
+	fault->ictx = ictx;
+	iommufd_ctx_get(fault->ictx);
+	fault->filep = filep;
+	refcount_inc(&fault->obj.users);
+
+	fdno = get_unused_fd_flags(O_CLOEXEC);
+	if (fdno < 0)
+		fput(filep);
+	return fdno;
+}
+
+static const struct file_operations iommufd_fault_fops =
+	INIT_FAULT_FOPS(iommufd_fault_fops_read, iommufd_fault_fops_write);
 
 int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 {
 	struct iommu_fault_alloc *cmd = ucmd->cmd;
 	struct iommufd_fault *fault;
-	struct file *filep;
 	int fdno;
 	int rc;
 
@@ -304,28 +333,14 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 	if (IS_ERR(fault))
 		return PTR_ERR(fault);
 
-	fault->ictx = ucmd->ictx;
-	INIT_LIST_HEAD(&fault->deliver);
 	xa_init_flags(&fault->response, XA_FLAGS_ALLOC1);
 	mutex_init(&fault->mutex);
-	spin_lock_init(&fault->lock);
-	init_waitqueue_head(&fault->wait_queue);
-
-	filep = anon_inode_getfile("[iommufd-pgfault]", &iommufd_fault_fops,
-				   fault, O_RDWR);
-	if (IS_ERR(filep)) {
-		rc = PTR_ERR(filep);
-		goto out_abort;
-	}
 
-	refcount_inc(&fault->obj.users);
-	iommufd_ctx_get(fault->ictx);
-	fault->filep = filep;
-
-	fdno = get_unused_fd_flags(O_CLOEXEC);
+	fdno = iommufd_fault_init(fault, "[iommufd-pgfault]", ucmd->ictx,
+				  &iommufd_fault_fops);
 	if (fdno < 0) {
 		rc = fdno;
-		goto out_fput;
+		goto out_abort;
 	}
 
 	cmd->out_fault_id = fault->obj.id;
@@ -341,8 +356,7 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 	return 0;
 out_put_fdno:
 	put_unused_fd(fdno);
-out_fput:
-	fput(filep);
+	fput(fault->filep);
 out_abort:
 	iommufd_object_abort_and_destroy(ucmd->ictx, &fault->obj);
 
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:28 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:28 -0700
Subject: [PATCH v9 10/14] iommufd/selftest: Add IOMMU_VEVENTQ_ALLOC test coverage
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <e829532ec0a3927d61161b7674b20e731ecd495b.1741719725.git.nicolinc@nvidia.com>

Trigger vEVENTs by feeding an idev ID and validating the returned output
virt_ids whether they equal to the value that was set to the vDEVICE.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 tools/testing/selftests/iommu/iommufd_utils.h | 115 ++++++++++++++++++
 tools/testing/selftests/iommu/iommufd.c       |  31 +++++
 .../selftests/iommu/iommufd_fail_nth.c        |   7 ++
 3 files changed, 153 insertions(+)

diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h
index d979f5b0efe8..6f2ba2fa8f76 100644
--- a/tools/testing/selftests/iommu/iommufd_utils.h
+++ b/tools/testing/selftests/iommu/iommufd_utils.h
@@ -9,6 +9,7 @@
 #include <sys/ioctl.h>
 #include <stdint.h>
 #include <assert.h>
+#include <poll.h>
 
 #include "../kselftest_harness.h"
 #include "../../../../drivers/iommu/iommufd/iommufd_test.h"
@@ -936,3 +937,117 @@ static int _test_cmd_vdevice_alloc(int fd, __u32 viommu_id, __u32 idev_id,
 	EXPECT_ERRNO(_errno,                                                 \
 		     _test_cmd_vdevice_alloc(self->fd, viommu_id, idev_id,   \
 					     virt_id, vdev_id))
+
+static int _test_cmd_veventq_alloc(int fd, __u32 viommu_id, __u32 type,
+				   __u32 *veventq_id, __u32 *veventq_fd)
+{
+	struct iommu_veventq_alloc cmd = {
+		.size = sizeof(cmd),
+		.type = type,
+		.veventq_depth = 2,
+		.viommu_id = viommu_id,
+	};
+	int ret;
+
+	ret = ioctl(fd, IOMMU_VEVENTQ_ALLOC, &cmd);
+	if (ret)
+		return ret;
+	if (veventq_id)
+		*veventq_id = cmd.out_veventq_id;
+	if (veventq_fd)
+		*veventq_fd = cmd.out_veventq_fd;
+	return 0;
+}
+
+#define test_cmd_veventq_alloc(viommu_id, type, veventq_id, veventq_fd) \
+	ASSERT_EQ(0, _test_cmd_veventq_alloc(self->fd, viommu_id, type, \
+					     veventq_id, veventq_fd))
+#define test_err_veventq_alloc(_errno, viommu_id, type, veventq_id,     \
+			       veventq_fd)                              \
+	EXPECT_ERRNO(_errno,                                            \
+		     _test_cmd_veventq_alloc(self->fd, viommu_id, type, \
+					     veventq_id, veventq_fd))
+
+static int _test_cmd_trigger_vevents(int fd, __u32 dev_id, __u32 nvevents)
+{
+	struct iommu_test_cmd trigger_vevent_cmd = {
+		.size = sizeof(trigger_vevent_cmd),
+		.op = IOMMU_TEST_OP_TRIGGER_VEVENT,
+		.trigger_vevent = {
+			.dev_id = dev_id,
+		},
+	};
+	int ret;
+
+	while (nvevents--) {
+		ret = ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_TRIGGER_VEVENT),
+			    &trigger_vevent_cmd);
+		if (ret < 0)
+			return -1;
+	}
+	return ret;
+}
+
+#define test_cmd_trigger_vevents(dev_id, nvevents) \
+	ASSERT_EQ(0, _test_cmd_trigger_vevents(self->fd, dev_id, nvevents))
+
+static int _test_cmd_read_vevents(int fd, __u32 event_fd, __u32 nvevents,
+				  __u32 virt_id, int *prev_seq)
+{
+	struct pollfd pollfd = { .fd = event_fd, .events = POLLIN };
+	struct iommu_viommu_event_selftest *event;
+	struct iommufd_vevent_header *hdr;
+	ssize_t bytes;
+	void *data;
+	int ret, i;
+
+	ret = poll(&pollfd, 1, 1000);
+	if (ret < 0)
+		return -1;
+
+	data = calloc(nvevents, sizeof(*hdr) + sizeof(*event));
+	if (!data) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	bytes = read(event_fd, data,
+		     nvevents * (sizeof(*hdr) + sizeof(*event)));
+	if (bytes <= 0) {
+		errno = EFAULT;
+		ret = -1;
+		goto out_free;
+	}
+
+	for (i = 0; i < nvevents; i++) {
+		hdr = data + i * (sizeof(*hdr) + sizeof(*event));
+
+		if (hdr->flags & IOMMU_VEVENTQ_FLAG_LOST_EVENTS ||
+		    hdr->sequence - *prev_seq > 1) {
+			*prev_seq = hdr->sequence;
+			errno = EOVERFLOW;
+			ret = -1;
+			goto out_free;
+		}
+		*prev_seq = hdr->sequence;
+		event = data + sizeof(*hdr);
+		if (event->virt_id != virt_id) {
+			errno = EINVAL;
+			ret = -1;
+			goto out_free;
+		}
+	}
+
+	ret = 0;
+out_free:
+	free(data);
+	return ret;
+}
+
+#define test_cmd_read_vevents(event_fd, nvevents, virt_id, prev_seq)      \
+	ASSERT_EQ(0, _test_cmd_read_vevents(self->fd, event_fd, nvevents, \
+					    virt_id, prev_seq))
+#define test_err_read_vevents(_errno, event_fd, nvevents, virt_id, prev_seq) \
+	EXPECT_ERRNO(_errno,                                                 \
+		     _test_cmd_read_vevents(self->fd, event_fd, nvevents,    \
+					    virt_id, prev_seq))
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 6a050a1d64ed..156c74da53cd 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -2778,15 +2778,46 @@ TEST_F(iommufd_viommu, vdevice_alloc)
 	uint32_t viommu_id = self->viommu_id;
 	uint32_t dev_id = self->device_id;
 	uint32_t vdev_id = 0;
+	uint32_t veventq_id;
+	uint32_t veventq_fd;
+	int prev_seq = -1;
 
 	if (dev_id) {
+		/* Must allocate vdevice before attaching to a nested hwpt */
+		test_err_mock_domain_replace(ENOENT, self->stdev_id,
+					     self->nested_hwpt_id);
+
+		/* Allocate a vEVENTQ with veventq_depth=2 */
+		test_cmd_veventq_alloc(viommu_id, IOMMU_VEVENTQ_TYPE_SELFTEST,
+				       &veventq_id, &veventq_fd);
+		test_err_veventq_alloc(EEXIST, viommu_id,
+				       IOMMU_VEVENTQ_TYPE_SELFTEST, NULL, NULL);
 		/* Set vdev_id to 0x99, unset it, and set to 0x88 */
 		test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
+		test_cmd_mock_domain_replace(self->stdev_id,
+					     self->nested_hwpt_id);
+		test_cmd_trigger_vevents(dev_id, 1);
+		test_cmd_read_vevents(veventq_fd, 1, 0x99, &prev_seq);
 		test_err_vdevice_alloc(EEXIST, viommu_id, dev_id, 0x99,
 				       &vdev_id);
+		test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
 		test_ioctl_destroy(vdev_id);
+
+		/* Try again with 0x88 */
 		test_cmd_vdevice_alloc(viommu_id, dev_id, 0x88, &vdev_id);
+		test_cmd_mock_domain_replace(self->stdev_id,
+					     self->nested_hwpt_id);
+		/* Trigger an overflow with three events */
+		test_cmd_trigger_vevents(dev_id, 3);
+		test_err_read_vevents(EOVERFLOW, veventq_fd, 3, 0x88,
+				      &prev_seq);
+		/* Overflow must be gone after the previous reads */
+		test_cmd_trigger_vevents(dev_id, 1);
+		test_cmd_read_vevents(veventq_fd, 1, 0x88, &prev_seq);
+		close(veventq_fd);
+		test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
 		test_ioctl_destroy(vdev_id);
+		test_ioctl_destroy(veventq_id);
 	} else {
 		test_err_vdevice_alloc(ENOENT, viommu_id, dev_id, 0x99, NULL);
 	}
diff --git a/tools/testing/selftests/iommu/iommufd_fail_nth.c b/tools/testing/selftests/iommu/iommufd_fail_nth.c
index 64b1f8e1b0cf..99a7f7897bb2 100644
--- a/tools/testing/selftests/iommu/iommufd_fail_nth.c
+++ b/tools/testing/selftests/iommu/iommufd_fail_nth.c
@@ -620,6 +620,7 @@ TEST_FAIL_NTH(basic_fail_nth, device)
 	};
 	struct iommu_test_hw_info info;
 	uint32_t fault_id, fault_fd;
+	uint32_t veventq_id, veventq_fd;
 	uint32_t fault_hwpt_id;
 	uint32_t ioas_id;
 	uint32_t ioas_id2;
@@ -692,6 +693,12 @@ TEST_FAIL_NTH(basic_fail_nth, device)
 				 IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data)))
 		return -1;
 
+	if (_test_cmd_veventq_alloc(self->fd, viommu_id,
+				    IOMMU_VEVENTQ_TYPE_SELFTEST, &veventq_id,
+				    &veventq_fd))
+		return -1;
+	close(veventq_fd);
+
 	return 0;
 }
 
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:23 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:23 -0700
Subject: [PATCH v9 05/14] iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <21acf0751dd5c93846935ee06f93b9c65eff5e04.1741719725.git.nicolinc@nvidia.com>

Introduce a new IOMMUFD_OBJ_VEVENTQ object for vIOMMU Event Queue that
provides user space (VMM) another FD to read the vIOMMU Events.

Allow a vIOMMU object to allocate vEVENTQs, with a condition that each
vIOMMU can only have one single vEVENTQ per type.

Add iommufd_veventq_alloc() with iommufd_veventq_ops for the new ioctl.

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/iommufd_private.h |  82 ++++++++++
 include/linux/iommufd.h                 |   3 +
 include/uapi/linux/iommufd.h            |  82 ++++++++++
 drivers/iommu/iommufd/eventq.c          | 209 +++++++++++++++++++++++-
 drivers/iommu/iommufd/main.c            |   7 +
 drivers/iommu/iommufd/viommu.c          |   2 +
 6 files changed, 384 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 44fb30af10b0..8cda9c4672eb 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -507,6 +507,74 @@ void iommufd_fault_iopf_disable(struct iommufd_device *idev);
 void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
 				  struct iommufd_attach_handle *handle);
 
+/* An iommufd_vevent represents a vIOMMU event in an iommufd_veventq */
+struct iommufd_vevent {
+	struct iommufd_vevent_header header;
+	struct list_head node; /* for iommufd_eventq::deliver */
+	ssize_t data_len;
+	u64 event_data[] __counted_by(data_len);
+};
+
+#define vevent_for_lost_events_header(vevent) \
+	(vevent->header.flags & IOMMU_VEVENTQ_FLAG_LOST_EVENTS)
+
+/*
+ * An iommufd_veventq object represents an interface to deliver vIOMMU events to
+ * the user space. It is created/destroyed by the user space and associated with
+ * a vIOMMU object during the allocations.
+ */
+struct iommufd_veventq {
+	struct iommufd_eventq common;
+	struct iommufd_viommu *viommu;
+	struct list_head node; /* for iommufd_viommu::veventqs */
+	struct iommufd_vevent lost_events_header;
+
+	unsigned int type;
+	unsigned int depth;
+
+	/* Use common.lock for protection */
+	u32 num_events;
+	u32 sequence;
+};
+
+static inline struct iommufd_veventq *
+eventq_to_veventq(struct iommufd_eventq *eventq)
+{
+	return container_of(eventq, struct iommufd_veventq, common);
+}
+
+static inline struct iommufd_veventq *
+iommufd_get_veventq(struct iommufd_ucmd *ucmd, u32 id)
+{
+	return container_of(iommufd_get_object(ucmd->ictx, id,
+					       IOMMUFD_OBJ_VEVENTQ),
+			    struct iommufd_veventq, common.obj);
+}
+
+int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd);
+void iommufd_veventq_destroy(struct iommufd_object *obj);
+void iommufd_veventq_abort(struct iommufd_object *obj);
+
+static inline void iommufd_vevent_handler(struct iommufd_veventq *veventq,
+					  struct iommufd_vevent *vevent)
+{
+	struct iommufd_eventq *eventq = &veventq->common;
+
+	lockdep_assert_held(&eventq->lock);
+
+	/*
+	 * Remove the lost_events_header and add the new node at the same time.
+	 * Note the new node can be lost_events_header, for a sequence update.
+	 */
+	if (list_is_last(&veventq->lost_events_header.node, &eventq->deliver))
+		list_del(&veventq->lost_events_header.node);
+	list_add_tail(&vevent->node, &eventq->deliver);
+	vevent->header.sequence = veventq->sequence;
+	veventq->sequence = (veventq->sequence + 1) & INT_MAX;
+
+	wake_up_interruptible(&eventq->wait_queue);
+}
+
 static inline struct iommufd_viommu *
 iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id)
 {
@@ -515,6 +583,20 @@ iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id)
 			    struct iommufd_viommu, obj);
 }
 
+static inline struct iommufd_veventq *
+iommufd_viommu_find_veventq(struct iommufd_viommu *viommu, u32 type)
+{
+	struct iommufd_veventq *veventq, *next;
+
+	lockdep_assert_held(&viommu->veventqs_rwsem);
+
+	list_for_each_entry_safe(veventq, next, &viommu->veventqs, node) {
+		if (veventq->type == type)
+			return veventq;
+	}
+	return NULL;
+}
+
 int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd);
 void iommufd_viommu_destroy(struct iommufd_object *obj);
 int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd);
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 11110c749200..8948b1836940 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -34,6 +34,7 @@ enum iommufd_object_type {
 	IOMMUFD_OBJ_FAULT,
 	IOMMUFD_OBJ_VIOMMU,
 	IOMMUFD_OBJ_VDEVICE,
+	IOMMUFD_OBJ_VEVENTQ,
 #ifdef CONFIG_IOMMUFD_TEST
 	IOMMUFD_OBJ_SELFTEST,
 #endif
@@ -93,6 +94,8 @@ struct iommufd_viommu {
 	const struct iommufd_viommu_ops *ops;
 
 	struct xarray vdevs;
+	struct list_head veventqs;
+	struct rw_semaphore veventqs_rwsem;
 
 	unsigned int type;
 };
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 78747b24bd0f..2ade4839880d 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -55,6 +55,7 @@ enum {
 	IOMMUFD_CMD_VIOMMU_ALLOC = 0x90,
 	IOMMUFD_CMD_VDEVICE_ALLOC = 0x91,
 	IOMMUFD_CMD_IOAS_CHANGE_PROCESS = 0x92,
+	IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93,
 };
 
 /**
@@ -1014,4 +1015,85 @@ struct iommu_ioas_change_process {
 #define IOMMU_IOAS_CHANGE_PROCESS \
 	_IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_CHANGE_PROCESS)
 
+/**
+ * enum iommu_veventq_flag - flag for struct iommufd_vevent_header
+ * @IOMMU_VEVENTQ_FLAG_OVERFLOW: vEVENTQ has lost vEVENTs
+ */
+enum iommu_veventq_flag {
+	IOMMU_VEVENTQ_FLAG_LOST_EVENTS = (1U << 0),
+};
+
+/**
+ * struct iommufd_vevent_header - Virtual Event Header for a vEVENTQ Status
+ * @flags: Combination of enum iommu_veventq_flag
+ * @sequence: The sequence index of a vEVENT in the vEVENTQ, with a range of
+ *            [0, INT_MAX] where the following index of INT_MAX is 0
+ *
+ * Each iommufd_vevent_header reports a sequence index of the following vEVENT:
+ *  -------------------------------------------------------------------------
+ * | header0 {sequence=0} | data0 | header1 {sequence=1} | data1 |...| dataN |
+ *  -------------------------------------------------------------------------
+ * And this sequence index is expected to be monotonic to the sequence index of
+ * the previous vEVENT. If two adjacent sequence indexes has a delta larger than
+ * 1, it means that delta - 1 number of vEVENTs has lost, e.g. two lost vEVENTs:
+ *  -------------------------------------------------------------------------
+ * | ... | header3 {sequence=3} | data3 | header6 {sequence=6} | data6 | ... |
+ *  -------------------------------------------------------------------------
+ * If a vEVENT lost at the tail of the vEVENTQ and there is no following vEVENT
+ * providing the next sequence index, an IOMMU_VEVENTQ_FLAG_LOST_EVENTS header
+ * would be added to the tail, and no data would follow this header:
+ *  ---------------------------------------------------------------------------
+ * |..| header3 {sequence=3} | data3 | header4 {flags=LOST_EVENTS, sequence=4} |
+ *  ---------------------------------------------------------------------------
+ */
+struct iommufd_vevent_header {
+	__u32 flags;
+	__u32 sequence;
+};
+
+/**
+ * enum iommu_veventq_type - Virtual Event Queue Type
+ * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use
+ */
+enum iommu_veventq_type {
+	IOMMU_VEVENTQ_TYPE_DEFAULT = 0,
+};
+
+/**
+ * struct iommu_veventq_alloc - ioctl(IOMMU_VEVENTQ_ALLOC)
+ * @size: sizeof(struct iommu_veventq_alloc)
+ * @flags: Must be 0
+ * @viommu: virtual IOMMU ID to associate the vEVENTQ with
+ * @type: Type of the vEVENTQ. Must be defined in enum iommu_veventq_type
+ * @veventq_depth: Maximum number of events in the vEVENTQ
+ * @out_veventq_id: The ID of the new vEVENTQ
+ * @out_veventq_fd: The fd of the new vEVENTQ. User space must close the
+ *                  successfully returned fd after using it
+ * @__reserved: Must be 0
+ *
+ * Explicitly allocate a virtual event queue interface for a vIOMMU. A vIOMMU
+ * can have multiple FDs for different types, but is confined to one per @type.
+ * User space should open the @out_veventq_fd to read vEVENTs out of a vEVENTQ,
+ * if there are vEVENTs available. A vEVENTQ will lose events due to overflow,
+ * if the number of the vEVENTs hits @veventq_depth.
+ *
+ * Each vEVENT in a vEVENTQ encloses a struct iommufd_vevent_header followed by
+ * a type-specific data structure, in a normal case:
+ *  -------------------------------------------------------------
+ * || header0 | data0 | header1 | data1 | ... | headerN | dataN ||
+ *  -------------------------------------------------------------
+ * unless a tailing IOMMU_VEVENTQ_FLAG_LOST_EVENTS header is logged (refer to
+ * struct iommufd_vevent_header).
+ */
+struct iommu_veventq_alloc {
+	__u32 size;
+	__u32 flags;
+	__u32 viommu_id;
+	__u32 type;
+	__u32 veventq_depth;
+	__u32 out_veventq_id;
+	__u32 out_veventq_fd;
+	__u32 __reserved;
+};
+#define IOMMU_VEVENTQ_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VEVENTQ_ALLOC)
 #endif
diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c
index f8e60e5879d1..4c43ace8c725 100644
--- a/drivers/iommu/iommufd/eventq.c
+++ b/drivers/iommu/iommufd/eventq.c
@@ -262,13 +262,148 @@ static ssize_t iommufd_fault_fops_write(struct file *filep, const char __user *b
 	return done == 0 ? rc : done;
 }
 
+/* IOMMUFD_OBJ_VEVENTQ Functions */
+
+void iommufd_veventq_abort(struct iommufd_object *obj)
+{
+	struct iommufd_eventq *eventq =
+		container_of(obj, struct iommufd_eventq, obj);
+	struct iommufd_veventq *veventq = eventq_to_veventq(eventq);
+	struct iommufd_viommu *viommu = veventq->viommu;
+	struct iommufd_vevent *cur, *next;
+
+	lockdep_assert_held_write(&viommu->veventqs_rwsem);
+
+	list_for_each_entry_safe(cur, next, &eventq->deliver, node) {
+		list_del(&cur->node);
+		if (cur != &veventq->lost_events_header)
+			kfree(cur);
+	}
+
+	refcount_dec(&viommu->obj.users);
+	list_del(&veventq->node);
+}
+
+void iommufd_veventq_destroy(struct iommufd_object *obj)
+{
+	struct iommufd_veventq *veventq = eventq_to_veventq(
+		container_of(obj, struct iommufd_eventq, obj));
+
+	down_write(&veventq->viommu->veventqs_rwsem);
+	iommufd_veventq_abort(obj);
+	up_write(&veventq->viommu->veventqs_rwsem);
+}
+
+static struct iommufd_vevent *
+iommufd_veventq_deliver_fetch(struct iommufd_veventq *veventq)
+{
+	struct iommufd_eventq *eventq = &veventq->common;
+	struct list_head *list = &eventq->deliver;
+	struct iommufd_vevent *vevent = NULL;
+
+	spin_lock(&eventq->lock);
+	if (!list_empty(list)) {
+		struct iommufd_vevent *next;
+
+		next = list_first_entry(list, struct iommufd_vevent, node);
+		/* Make a copy of the lost_events_header for copy_to_user */
+		if (next == &veventq->lost_events_header) {
+			vevent = kzalloc(sizeof(*vevent), GFP_ATOMIC);
+			if (!vevent)
+				goto out_unlock;
+		}
+		list_del(&next->node);
+		if (vevent)
+			memcpy(vevent, next, sizeof(*vevent));
+		else
+			vevent = next;
+	}
+out_unlock:
+	spin_unlock(&eventq->lock);
+	return vevent;
+}
+
+static void iommufd_veventq_deliver_restore(struct iommufd_veventq *veventq,
+					    struct iommufd_vevent *vevent)
+{
+	struct iommufd_eventq *eventq = &veventq->common;
+	struct list_head *list = &eventq->deliver;
+
+	spin_lock(&eventq->lock);
+	if (vevent_for_lost_events_header(vevent)) {
+		/* Remove the copy of the lost_events_header */
+		kfree(vevent);
+		vevent = NULL;
+		/* An empty list needs the lost_events_header back */
+		if (list_empty(list))
+			vevent = &veventq->lost_events_header;
+	}
+	if (vevent)
+		list_add(&vevent->node, list);
+	spin_unlock(&eventq->lock);
+}
+
+static ssize_t iommufd_veventq_fops_read(struct file *filep, char __user *buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iommufd_eventq *eventq = filep->private_data;
+	struct iommufd_veventq *veventq = eventq_to_veventq(eventq);
+	struct iommufd_vevent_header *hdr;
+	struct iommufd_vevent *cur;
+	size_t done = 0;
+	int rc = 0;
+
+	if (*ppos)
+		return -ESPIPE;
+
+	while ((cur = iommufd_veventq_deliver_fetch(veventq))) {
+		/* Validate the remaining bytes against the header size */
+		if (done >= count || sizeof(*hdr) > count - done) {
+			iommufd_veventq_deliver_restore(veventq, cur);
+			break;
+		}
+		hdr = &cur->header;
+
+		/* If being a normal vEVENT, validate against the full size */
+		if (!vevent_for_lost_events_header(cur) &&
+		    sizeof(hdr) + cur->data_len > count - done) {
+			iommufd_veventq_deliver_restore(veventq, cur);
+			break;
+		}
+
+		if (copy_to_user(buf + done, hdr, sizeof(*hdr))) {
+			iommufd_veventq_deliver_restore(veventq, cur);
+			rc = -EFAULT;
+			break;
+		}
+		done += sizeof(*hdr);
+
+		if (cur->data_len &&
+		    copy_to_user(buf + done, cur->event_data, cur->data_len)) {
+			iommufd_veventq_deliver_restore(veventq, cur);
+			rc = -EFAULT;
+			break;
+		}
+		spin_lock(&eventq->lock);
+		veventq->num_events--;
+		spin_unlock(&eventq->lock);
+		done += cur->data_len;
+		kfree(cur);
+	}
+
+	return done == 0 ? rc : done;
+}
+
 /* Common Event Queue Functions */
 
 static __poll_t iommufd_eventq_fops_poll(struct file *filep,
 					 struct poll_table_struct *wait)
 {
 	struct iommufd_eventq *eventq = filep->private_data;
-	__poll_t pollflags = EPOLLOUT;
+	__poll_t pollflags = 0;
+
+	if (eventq->obj.type == IOMMUFD_OBJ_FAULT)
+		pollflags |= EPOLLOUT;
 
 	poll_wait(filep, &eventq->wait_queue, wait);
 	spin_lock(&eventq->lock);
@@ -388,3 +523,75 @@ int iommufd_fault_iopf_handler(struct iopf_group *group)
 
 	return 0;
 }
+
+static const struct file_operations iommufd_veventq_fops =
+	INIT_EVENTQ_FOPS(iommufd_veventq_fops_read, NULL);
+
+int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd)
+{
+	struct iommu_veventq_alloc *cmd = ucmd->cmd;
+	struct iommufd_veventq *veventq;
+	struct iommufd_viommu *viommu;
+	int fdno;
+	int rc;
+
+	if (cmd->flags || cmd->__reserved ||
+	    cmd->type == IOMMU_VEVENTQ_TYPE_DEFAULT)
+		return -EOPNOTSUPP;
+	if (!cmd->veventq_depth)
+		return -EINVAL;
+
+	viommu = iommufd_get_viommu(ucmd, cmd->viommu_id);
+	if (IS_ERR(viommu))
+		return PTR_ERR(viommu);
+
+	down_write(&viommu->veventqs_rwsem);
+
+	if (iommufd_viommu_find_veventq(viommu, cmd->type)) {
+		rc = -EEXIST;
+		goto out_unlock_veventqs;
+	}
+
+	veventq = __iommufd_object_alloc(ucmd->ictx, veventq,
+					 IOMMUFD_OBJ_VEVENTQ, common.obj);
+	if (IS_ERR(veventq)) {
+		rc = PTR_ERR(veventq);
+		goto out_unlock_veventqs;
+	}
+
+	veventq->type = cmd->type;
+	veventq->viommu = viommu;
+	refcount_inc(&viommu->obj.users);
+	veventq->depth = cmd->veventq_depth;
+	list_add_tail(&veventq->node, &viommu->veventqs);
+	veventq->lost_events_header.header.flags =
+		IOMMU_VEVENTQ_FLAG_LOST_EVENTS;
+
+	fdno = iommufd_eventq_init(&veventq->common, "[iommufd-viommu-event]",
+				   ucmd->ictx, &iommufd_veventq_fops);
+	if (fdno < 0) {
+		rc = fdno;
+		goto out_abort;
+	}
+
+	cmd->out_veventq_id = veventq->common.obj.id;
+	cmd->out_veventq_fd = fdno;
+
+	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+	if (rc)
+		goto out_put_fdno;
+
+	iommufd_object_finalize(ucmd->ictx, &veventq->common.obj);
+	fd_install(fdno, veventq->common.filep);
+	goto out_unlock_veventqs;
+
+out_put_fdno:
+	put_unused_fd(fdno);
+	fput(veventq->common.filep);
+out_abort:
+	iommufd_object_abort_and_destroy(ucmd->ictx, &veventq->common.obj);
+out_unlock_veventqs:
+	up_write(&viommu->veventqs_rwsem);
+	iommufd_put_object(ucmd->ictx, &viommu->obj);
+	return rc;
+}
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index b6fa9fd11bc1..3df468f64e7d 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -317,6 +317,7 @@ union ucmd_buffer {
 	struct iommu_ioas_unmap unmap;
 	struct iommu_option option;
 	struct iommu_vdevice_alloc vdev;
+	struct iommu_veventq_alloc veventq;
 	struct iommu_vfio_ioas vfio_ioas;
 	struct iommu_viommu_alloc viommu;
 #ifdef CONFIG_IOMMUFD_TEST
@@ -372,6 +373,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
 	IOCTL_OP(IOMMU_OPTION, iommufd_option, struct iommu_option, val64),
 	IOCTL_OP(IOMMU_VDEVICE_ALLOC, iommufd_vdevice_alloc_ioctl,
 		 struct iommu_vdevice_alloc, virt_id),
+	IOCTL_OP(IOMMU_VEVENTQ_ALLOC, iommufd_veventq_alloc,
+		 struct iommu_veventq_alloc, out_veventq_fd),
 	IOCTL_OP(IOMMU_VFIO_IOAS, iommufd_vfio_ioas, struct iommu_vfio_ioas,
 		 __reserved),
 	IOCTL_OP(IOMMU_VIOMMU_ALLOC, iommufd_viommu_alloc_ioctl,
@@ -514,6 +517,10 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
 	[IOMMUFD_OBJ_VDEVICE] = {
 		.destroy = iommufd_vdevice_destroy,
 	},
+	[IOMMUFD_OBJ_VEVENTQ] = {
+		.destroy = iommufd_veventq_destroy,
+		.abort = iommufd_veventq_abort,
+	},
 	[IOMMUFD_OBJ_VIOMMU] = {
 		.destroy = iommufd_viommu_destroy,
 	},
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 69b88e8c7c26..01df2b985f02 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -59,6 +59,8 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
 	viommu->ictx = ucmd->ictx;
 	viommu->hwpt = hwpt_paging;
 	refcount_inc(&viommu->hwpt->common.obj.users);
+	INIT_LIST_HEAD(&viommu->veventqs);
+	init_rwsem(&viommu->veventqs_rwsem);
 	/*
 	 * It is the most likely case that a physical IOMMU is unpluggable. A
 	 * pluggable IOMMU instance (if exists) is responsible for refcounting
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:29 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:29 -0700
Subject: [PATCH v9 11/14] Documentation: userspace-api: iommufd: Update FAULT and VEVENTQ
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <09829fbc218872d242323d8834da4bec187ce6f4.1741719725.git.nicolinc@nvidia.com>

With the introduction of the new objects, update the doc to reflect that.

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Bagas Sanjaya <bagasdotme at gmail.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 Documentation/userspace-api/iommufd.rst | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Documentation/userspace-api/iommufd.rst b/Documentation/userspace-api/iommufd.rst
index 70289d6815d2..b0df15865dec 100644
--- a/Documentation/userspace-api/iommufd.rst
+++ b/Documentation/userspace-api/iommufd.rst
@@ -63,6 +63,13 @@ Following IOMMUFD objects are exposed to userspace:
   space usually has mappings from guest-level I/O virtual addresses to guest-
   level physical addresses.
 
+- IOMMUFD_FAULT, representing a software queue for an HWPT reporting IO page
+  faults using the IOMMU HW's PRI (Page Request Interface). This queue object
+  provides user space an FD to poll the page fault events and also to respond
+  to those events. A FAULT object must be created first to get a fault_id that
+  could be then used to allocate a fault-enabled HWPT via the IOMMU_HWPT_ALLOC
+  command by setting the IOMMU_HWPT_FAULT_ID_VALID bit in its flags field.
+
 - IOMMUFD_OBJ_VIOMMU, representing a slice of the physical IOMMU instance,
   passed to or shared with a VM. It may be some HW-accelerated virtualization
   features and some SW resources used by the VM. For examples:
@@ -109,6 +116,14 @@ Following IOMMUFD objects are exposed to userspace:
   vIOMMU, which is a separate ioctl call from attaching the same device to an
   HWPT_PAGING that the vIOMMU holds.
 
+- IOMMUFD_OBJ_VEVENTQ, representing a software queue for a vIOMMU to report its
+  events such as translation faults occurred to a nested stage-1 (excluding I/O
+  page faults that should go through IOMMUFD_OBJ_FAULT) and HW-specific events.
+  This queue object provides user space an FD to poll/read the vIOMMU events. A
+  vIOMMU object must be created first to get its viommu_id, which could be then
+  used to allocate a vEVENTQ. Each vIOMMU can support multiple types of vEVENTS,
+  but is confined to one vEVENTQ per vEVENTQ type.
+
 All user-visible objects are destroyed via the IOMMU_DESTROY uAPI.
 
 The diagrams below show relationships between user-visible objects and kernel
@@ -251,8 +266,10 @@ User visible objects are backed by following datastructures:
 - iommufd_device for IOMMUFD_OBJ_DEVICE.
 - iommufd_hwpt_paging for IOMMUFD_OBJ_HWPT_PAGING.
 - iommufd_hwpt_nested for IOMMUFD_OBJ_HWPT_NESTED.
+- iommufd_fault for IOMMUFD_OBJ_FAULT.
 - iommufd_viommu for IOMMUFD_OBJ_VIOMMU.
 - iommufd_vdevice for IOMMUFD_OBJ_VDEVICE.
+- iommufd_veventq for IOMMUFD_OBJ_VEVENTQ.
 
 Several terminologies when looking at these datastructures:
 
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:32 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:32 -0700
Subject: [PATCH v9 14/14] iommu/arm-smmu-v3: Set MEV bit in nested STE for DoS mitigations
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <8ed12feef67fc65273d0f5925f401a81f56acebe.1741719725.git.nicolinc@nvidia.com>

There is a DoS concern on the shared hardware event queue among devices
passed through to VMs, that too many translation failures that belong to
VMs could overflow the shared hardware event queue if those VMs or their
VMMs don't handle/recover the devices properly.

The MEV bit in the STE allows to configure the SMMU HW to merge similar
event records, though there is no guarantee. Set it in a nested STE for
DoS mitigations.

In the future, we might want to enable the MEV for non-nested cases too
such as domain->type == IOMMU_DOMAIN_UNMANAGED or even IOMMU_DOMAIN_DMA.

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan at google.com>
Acked-by: Will Deacon <will at kernel.org>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 1 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 2 ++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c         | 4 ++--
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index df06076a1698..dd1ad56ce863 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -266,6 +266,7 @@ static inline u32 arm_smmu_strtab_l2_idx(u32 sid)
 #define STRTAB_STE_1_S1COR		GENMASK_ULL(5, 4)
 #define STRTAB_STE_1_S1CSH		GENMASK_ULL(7, 6)
 
+#define STRTAB_STE_1_MEV		(1UL << 19)
 #define STRTAB_STE_1_S2FWB		(1UL << 25)
 #define STRTAB_STE_1_S1STALLD		(1UL << 27)
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 65adfed56969..e4fd8d522af8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -43,6 +43,8 @@ static void arm_smmu_make_nested_cd_table_ste(
 	target->data[0] |= nested_domain->ste[0] &
 			   ~cpu_to_le64(STRTAB_STE_0_CFG);
 	target->data[1] |= nested_domain->ste[1];
+	/* Merge events for DoS mitigations on eventq */
+	target->data[1] |= cpu_to_le64(STRTAB_STE_1_MEV);
 }
 
 /*
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 5fa817a8f5f1..b4c21aaed126 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1052,7 +1052,7 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
 			cpu_to_le64(STRTAB_STE_1_S1DSS | STRTAB_STE_1_S1CIR |
 				    STRTAB_STE_1_S1COR | STRTAB_STE_1_S1CSH |
 				    STRTAB_STE_1_S1STALLD | STRTAB_STE_1_STRW |
-				    STRTAB_STE_1_EATS);
+				    STRTAB_STE_1_EATS | STRTAB_STE_1_MEV);
 		used_bits[2] |= cpu_to_le64(STRTAB_STE_2_S2VMID);
 
 		/*
@@ -1068,7 +1068,7 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
 	if (cfg & BIT(1)) {
 		used_bits[1] |=
 			cpu_to_le64(STRTAB_STE_1_S2FWB | STRTAB_STE_1_EATS |
-				    STRTAB_STE_1_SHCFG);
+				    STRTAB_STE_1_SHCFG | STRTAB_STE_1_MEV);
 		used_bits[2] |=
 			cpu_to_le64(STRTAB_STE_2_S2VMID | STRTAB_STE_2_VTCR |
 				    STRTAB_STE_2_S2AA64 | STRTAB_STE_2_S2ENDI |
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:31 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:31 -0700
Subject: [PATCH v9 13/14] iommu/arm-smmu-v3: Report events that belong to devices attached to vIOMMU
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <5cf6719682fdfdabffdb08374cdf31ad2466d75a.1741719725.git.nicolinc@nvidia.com>

Aside from the IOPF framework, iommufd provides an additional pathway to
report hardware events, via the vEVENTQ of vIOMMU infrastructure.

Define an iommu_vevent_arm_smmuv3 uAPI structure, and report stage-1 events
in the threaded IRQ handler. Also, add another four event record types that
can be forwarded to a VM.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan at google.com>
Acked-by: Will Deacon <will at kernel.org>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  7 +++
 include/uapi/linux/iommufd.h                  | 23 ++++++++
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 17 ++++++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 58 +++++++++++--------
 4 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 557b300a3a0f..df06076a1698 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1066,6 +1066,7 @@ int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
 				    struct arm_smmu_nested_domain *nested_domain);
 void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
 void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
+int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt);
 #else
 #define arm_smmu_hw_info NULL
 #define arm_vsmmu_alloc NULL
@@ -1086,6 +1087,12 @@ static inline void
 arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
 {
 }
+
+static inline int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster,
+					   u64 *evt)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
 
 #endif /* _ARM_SMMU_V3_H */
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 2ade4839880d..5fc7e27804b7 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -1054,9 +1054,32 @@ struct iommufd_vevent_header {
 /**
  * enum iommu_veventq_type - Virtual Event Queue Type
  * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use
+ * @IOMMU_VEVENTQ_TYPE_ARM_SMMUV3: ARM SMMUv3 Virtual Event Queue
  */
 enum iommu_veventq_type {
 	IOMMU_VEVENTQ_TYPE_DEFAULT = 0,
+	IOMMU_VEVENTQ_TYPE_ARM_SMMUV3 = 1,
+};
+
+/**
+ * struct iommu_vevent_arm_smmuv3 - ARM SMMUv3 Virtual Event
+ *                                  (IOMMU_VEVENTQ_TYPE_ARM_SMMUV3)
+ * @evt: 256-bit ARM SMMUv3 Event record, little-endian.
+ *       Reported event records: (Refer to "7.3 Event records" in SMMUv3 HW Spec)
+ *       - 0x04 C_BAD_STE
+ *       - 0x06 F_STREAM_DISABLED
+ *       - 0x08 C_BAD_SUBSTREAMID
+ *       - 0x0a C_BAD_CD
+ *       - 0x10 F_TRANSLATION
+ *       - 0x11 F_ADDR_SIZE
+ *       - 0x12 F_ACCESS
+ *       - 0x13 F_PERMISSION
+ *
+ * StreamID field reports a virtual device ID. To receive a virtual event for a
+ * device, a vDEVICE must be allocated via IOMMU_VDEVICE_ALLOC.
+ */
+struct iommu_vevent_arm_smmuv3 {
+	__aligned_le64 evt[4];
 };
 
 /**
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index dfc80e1a8e2e..65adfed56969 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -433,4 +433,21 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 	return &vsmmu->core;
 }
 
+int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt)
+{
+	struct iommu_vevent_arm_smmuv3 vevt;
+	int i;
+
+	lockdep_assert_held(&vmaster->vsmmu->smmu->streams_mutex);
+
+	vevt.evt[0] = cpu_to_le64((evt[0] & ~EVTQ_0_SID) |
+				  FIELD_PREP(EVTQ_0_SID, vmaster->vsid));
+	for (i = 1; i < EVTQ_ENT_DWORDS; i++)
+		vevt.evt[i] = cpu_to_le64(evt[i]);
+
+	return iommufd_viommu_report_event(&vmaster->vsmmu->core,
+					   IOMMU_VEVENTQ_TYPE_ARM_SMMUV3, &vevt,
+					   sizeof(vevt));
+}
+
 MODULE_IMPORT_NS("IOMMUFD");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 964d2cf27d3d..5fa817a8f5f1 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1813,8 +1813,8 @@ static void arm_smmu_decode_event(struct arm_smmu_device *smmu, u64 *raw,
 	mutex_unlock(&smmu->streams_mutex);
 }
 
-static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
-			       struct arm_smmu_event *event)
+static int arm_smmu_handle_event(struct arm_smmu_device *smmu, u64 *evt,
+				 struct arm_smmu_event *event)
 {
 	int ret = 0;
 	u32 perm = 0;
@@ -1823,6 +1823,10 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
 	struct iommu_fault *flt = &fault_evt.fault;
 
 	switch (event->id) {
+	case EVT_ID_BAD_STE_CONFIG:
+	case EVT_ID_STREAM_DISABLED_FAULT:
+	case EVT_ID_BAD_SUBSTREAMID_CONFIG:
+	case EVT_ID_BAD_CD_CONFIG:
 	case EVT_ID_TRANSLATION_FAULT:
 	case EVT_ID_ADDR_SIZE_FAULT:
 	case EVT_ID_ACCESS_FAULT:
@@ -1832,31 +1836,30 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
 		return -EOPNOTSUPP;
 	}
 
-	if (!event->stall)
-		return -EOPNOTSUPP;
-
-	if (event->read)
-		perm |= IOMMU_FAULT_PERM_READ;
-	else
-		perm |= IOMMU_FAULT_PERM_WRITE;
+	if (event->stall) {
+		if (event->read)
+			perm |= IOMMU_FAULT_PERM_READ;
+		else
+			perm |= IOMMU_FAULT_PERM_WRITE;
 
-	if (event->instruction)
-		perm |= IOMMU_FAULT_PERM_EXEC;
+		if (event->instruction)
+			perm |= IOMMU_FAULT_PERM_EXEC;
 
-	if (event->privileged)
-		perm |= IOMMU_FAULT_PERM_PRIV;
+		if (event->privileged)
+			perm |= IOMMU_FAULT_PERM_PRIV;
 
-	flt->type = IOMMU_FAULT_PAGE_REQ;
-	flt->prm = (struct iommu_fault_page_request) {
-		.flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE,
-		.grpid = event->stag,
-		.perm = perm,
-		.addr = event->iova,
-	};
+		flt->type = IOMMU_FAULT_PAGE_REQ;
+		flt->prm = (struct iommu_fault_page_request){
+			.flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE,
+			.grpid = event->stag,
+			.perm = perm,
+			.addr = event->iova,
+		};
 
-	if (event->ssv) {
-		flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
-		flt->prm.pasid = event->ssid;
+		if (event->ssv) {
+			flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
+			flt->prm.pasid = event->ssid;
+		}
 	}
 
 	mutex_lock(&smmu->streams_mutex);
@@ -1866,7 +1869,12 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu,
 		goto out_unlock;
 	}
 
-	ret = iommu_report_device_fault(master->dev, &fault_evt);
+	if (event->stall)
+		ret = iommu_report_device_fault(master->dev, &fault_evt);
+	else if (master->vmaster && !event->s2)
+		ret = arm_vmaster_report_event(master->vmaster, evt);
+	else
+		ret = -EOPNOTSUPP; /* Unhandled events should be pinned */
 out_unlock:
 	mutex_unlock(&smmu->streams_mutex);
 	return ret;
@@ -1944,7 +1952,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
 	do {
 		while (!queue_remove_raw(q, evt)) {
 			arm_smmu_decode_event(smmu, evt, &event);
-			if (arm_smmu_handle_event(smmu, &event))
+			if (arm_smmu_handle_event(smmu, evt, &event))
 				arm_smmu_dump_event(smmu, evt, &event, &rs);
 
 			put_device(event.dev);
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:30 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:30 -0700
Subject: [PATCH v9 12/14] iommu/arm-smmu-v3: Introduce struct arm_smmu_vmaster
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <a7f282e1a531279e25f06c651e95d56f6b120886.1741719725.git.nicolinc@nvidia.com>

Use it to store all vSMMU-related data. The vsid (Virtual Stream ID) will
be the first use case. Since the vsid reader will be the eventq handler
that already holds a streams_mutex, reuse that to fence the vmaster too.

Also add a pair of arm_smmu_attach_prepare/commit_vmaster helpers to set
or unset the master->vmaster pointer. Put the helpers inside the existing
arm_smmu_attach_prepare/commit().

For identity/blocked ops that don't call arm_smmu_attach_prepare/commit(),
add a simpler arm_smmu_master_clear_vmaster helper to unset the vmaster.

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan at google.com>
Acked-by: Will Deacon <will at kernel.org>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 28 +++++++++++++
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 41 +++++++++++++++++++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 18 +++++++-
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index bd9d7c85576a..557b300a3a0f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -799,6 +799,11 @@ struct arm_smmu_stream {
 	struct rb_node			node;
 };
 
+struct arm_smmu_vmaster {
+	struct arm_vsmmu		*vsmmu;
+	unsigned long			vsid;
+};
+
 struct arm_smmu_event {
 	u8				stall : 1,
 					ssv : 1,
@@ -824,6 +829,7 @@ struct arm_smmu_master {
 	struct arm_smmu_device		*smmu;
 	struct device			*dev;
 	struct arm_smmu_stream		*streams;
+	struct arm_smmu_vmaster		*vmaster; /* use smmu->streams_mutex */
 	/* Locked by the iommu core using the group mutex */
 	struct arm_smmu_ctx_desc_cfg	cd_table;
 	unsigned int			num_streams;
@@ -972,6 +978,7 @@ struct arm_smmu_attach_state {
 	bool disable_ats;
 	ioasid_t ssid;
 	/* Resulting state */
+	struct arm_smmu_vmaster *vmaster;
 	bool ats_enabled;
 };
 
@@ -1055,9 +1062,30 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 				       struct iommu_domain *parent,
 				       struct iommufd_ctx *ictx,
 				       unsigned int viommu_type);
+int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
+				    struct arm_smmu_nested_domain *nested_domain);
+void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
+void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
 #else
 #define arm_smmu_hw_info NULL
 #define arm_vsmmu_alloc NULL
+
+static inline int
+arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
+				struct arm_smmu_nested_domain *nested_domain)
+{
+	return 0;
+}
+
+static inline void
+arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state)
+{
+}
+
+static inline void
+arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
+{
+}
 #endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
 
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 5aa2e7af58b4..dfc80e1a8e2e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -85,6 +85,47 @@ static void arm_smmu_make_nested_domain_ste(
 	}
 }
 
+int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
+				    struct arm_smmu_nested_domain *nested_domain)
+{
+	struct arm_smmu_vmaster *vmaster;
+	unsigned long vsid;
+	int ret;
+
+	iommu_group_mutex_assert(state->master->dev);
+
+	ret = iommufd_viommu_get_vdev_id(&nested_domain->vsmmu->core,
+					 state->master->dev, &vsid);
+	if (ret)
+		return ret;
+
+	vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
+	if (!vmaster)
+		return -ENOMEM;
+	vmaster->vsmmu = nested_domain->vsmmu;
+	vmaster->vsid = vsid;
+	state->vmaster = vmaster;
+
+	return 0;
+}
+
+void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state)
+{
+	struct arm_smmu_master *master = state->master;
+
+	mutex_lock(&master->smmu->streams_mutex);
+	kfree(master->vmaster);
+	master->vmaster = state->vmaster;
+	mutex_unlock(&master->smmu->streams_mutex);
+}
+
+void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
+{
+	struct arm_smmu_attach_state state = { .master = master };
+
+	arm_smmu_attach_commit_vmaster(&state);
+}
+
 static int arm_smmu_attach_dev_nested(struct iommu_domain *domain,
 				      struct device *dev)
 {
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 358072b4e293..964d2cf27d3d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2803,6 +2803,7 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
 	struct arm_smmu_domain *smmu_domain =
 		to_smmu_domain_devices(new_domain);
 	unsigned long flags;
+	int ret;
 
 	/*
 	 * arm_smmu_share_asid() must not see two domains pointing to the same
@@ -2832,9 +2833,18 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
 	}
 
 	if (smmu_domain) {
+		if (new_domain->type == IOMMU_DOMAIN_NESTED) {
+			ret = arm_smmu_attach_prepare_vmaster(
+				state, to_smmu_nested_domain(new_domain));
+			if (ret)
+				return ret;
+		}
+
 		master_domain = kzalloc(sizeof(*master_domain), GFP_KERNEL);
-		if (!master_domain)
+		if (!master_domain) {
+			kfree(state->vmaster);
 			return -ENOMEM;
+		}
 		master_domain->master = master;
 		master_domain->ssid = state->ssid;
 		if (new_domain->type == IOMMU_DOMAIN_NESTED)
@@ -2861,6 +2871,7 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
 			spin_unlock_irqrestore(&smmu_domain->devices_lock,
 					       flags);
 			kfree(master_domain);
+			kfree(state->vmaster);
 			return -EINVAL;
 		}
 
@@ -2893,6 +2904,8 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
 
 	lockdep_assert_held(&arm_smmu_asid_lock);
 
+	arm_smmu_attach_commit_vmaster(state);
+
 	if (state->ats_enabled && !master->ats_enabled) {
 		arm_smmu_enable_ats(master);
 	} else if (state->ats_enabled && master->ats_enabled) {
@@ -3162,6 +3175,7 @@ static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
 	struct arm_smmu_ste ste;
 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
 
+	arm_smmu_master_clear_vmaster(master);
 	arm_smmu_make_bypass_ste(master->smmu, &ste);
 	arm_smmu_attach_dev_ste(domain, dev, &ste, STRTAB_STE_1_S1DSS_BYPASS);
 	return 0;
@@ -3180,7 +3194,9 @@ static int arm_smmu_attach_dev_blocked(struct iommu_domain *domain,
 					struct device *dev)
 {
 	struct arm_smmu_ste ste;
+	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
 
+	arm_smmu_master_clear_vmaster(master);
 	arm_smmu_make_abort_ste(&ste);
 	arm_smmu_attach_dev_ste(domain, dev, &ste,
 				STRTAB_STE_1_S1DSS_TERMINATE);
-- 
2.43.0



From robh at kernel.org  Tue Mar 11 12:49:08 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 14:49:08 -0500
Subject: [PATCH 1/2] dt-bindings: clock: rk3576: add SCMI clocks
In-Reply-To: <20250310-rk3576-scmi-clocks-v1-1-e165deb034e8@collabora.com>
References: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
 <20250310-rk3576-scmi-clocks-v1-1-e165deb034e8@collabora.com>
Message-ID: <174172254786.8700.16296927950928692659.robh@kernel.org>


On Mon, 10 Mar 2025 10:59:56 +0100, Nicolas Frattaroli wrote:
> Mainline Linux uses different clock IDs from both downstream and
> mainline TF-A, which both got them from downstream Linux. If we want to
> control clocks through SCMI, we'll need to know about these IDs.
> 
> Add the relevant ones prefixed with SCMI_ to the header.
> 
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
>  include/dt-bindings/clock/rockchip,rk3576-cru.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From Markus.Elfring at web.de  Tue Mar 11 12:54:13 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Tue, 11 Mar 2025 20:54:13 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250311180254.149484-1-csokas.bence@prolan.hu>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
Message-ID: <885ceb3e-d6c6-4e7b-a3b6-585d2d110ccf@web.de>

> Clean up error handling by using devm functions
> and dev_err_probe(). ?

How good does such a change combination fit to the patch requirement
according to separation of concerns?
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc6#n81

Regards,
Markus


From robdclark at gmail.com  Tue Mar 11 13:00:34 2025
From: robdclark at gmail.com (Rob Clark)
Date: Tue, 11 Mar 2025 13:00:34 -0700
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly
In-Reply-To: <CACu1E7Hw6vGbTQ7t-Hj3ziycZhPxtOGSDkt7o4fNUx91KDcXfg@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
 <20250311180807.GC5216@willie-the-truck> <CACu1E7Hw6vGbTQ7t-Hj3ziycZhPxtOGSDkt7o4fNUx91KDcXfg@mail.gmail.com>
Message-ID: <CAF6AEGs8PoZBpFesQ_DGcngn4X24wzFy=zn2mAUJepdibxoKog@mail.gmail.com>

On Tue, Mar 11, 2025 at 12:42?PM Connor Abbott <cwabbott0 at gmail.com> wrote:
>
> On Tue, Mar 11, 2025 at 2:08?PM Will Deacon <will at kernel.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> > > In some cases drm/msm has to resume a stalled transaction directly in
> > > its fault handler. Experimentally this doesn't work on SMMU500 if the
> > > fault hasn't already been acknowledged by clearing FSR. Rather than
> > > trying to clear FSR in msm's fault handler and implementing a
> > > tricky handshake to avoid accidentally clearing FSR twice, we want to
> > > clear FSR before calling the fault handlers, but this means that the
> > > contents of registers can change underneath us in the fault handler and
> > > msm currently uses a private function to read the register contents for
> > > its own purposes in its fault handler, such as using the
> > > implementation-defined FSYNR1 to determine which block caused the fault.
> > > Fix this by making msm use the register values already read by arm-smmu
> > > itself before clearing FSR rather than messing around with reading
> > > registers directly.
> > >
> > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > ---
> > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
> > >  3 files changed, 27 insertions(+), 27 deletions(-)
> >
> > [...]
> >
> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
> > >       ARM_SMMU_DOMAIN_NESTED,
> > >  };
> > >
> > > +struct arm_smmu_context_fault_info {
> > > +     unsigned long iova;
> > > +     u64 ttbr0;
> > > +     u32 fsr;
> > > +     u32 fsynr0;
> > > +     u32 fsynr1;
> > > +     u32 cbfrsynra;
> > > +     u32 contextidr;
> > > +};
> > > +
> > >  struct arm_smmu_domain {
> > >       struct arm_smmu_device          *smmu;
> > >       struct io_pgtable_ops           *pgtbl_ops;
> > > @@ -380,6 +390,7 @@ struct arm_smmu_domain {
> > >       const struct iommu_flush_ops    *flush_ops;
> > >       struct arm_smmu_cfg             cfg;
> > >       enum arm_smmu_domain_stage      stage;
> > > +     struct arm_smmu_context_fault_info cfi;
> >
> > Does this mean we have to serialise all faults for a given domain? That
> > can't be right...
> >
> > Will
>
> They are already serialized? There's only one of each register per
> context bank, so you can only have one context fault at a time per
> context bank, and AFAIK a context bank is 1:1 with a domain. Also this
> struct is only written and then read inside the context bank's
> interrupt handler, and you can only have one interrupt at a time, no?
>
> Connor

And if it was a race condition with cfi getting overridden, it would
have already been an equivalent race condition currently when reading
the values from registers (ie. the register values could have changed
in the elapsed time)

So no additional serialization needed here.

BR,
-R


From cwabbott0 at gmail.com  Tue Mar 11 13:01:00 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 11 Mar 2025 16:01:00 -0400
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250311181151.GD5216@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com> <20250311181151.GD5216@willie-the-truck>
Message-ID: <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>

On Tue, Mar 11, 2025 at 2:11?PM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> > Up until now we have only called the set_stall callback during
> > initialization when the device is off. But we will soon start calling it
> > to temporarily disable stall-on-fault when the device is on, so handle
> > that by checking if the device is on and writing SCTLR.
> >
> > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
> >  1 file changed, 27 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
> >  {
> >       struct arm_smmu_domain *smmu_domain = (void *)cookie;
> >       struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> > -     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> > +     struct arm_smmu_device *smmu = smmu_domain->smmu;
> > +     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > +     u32 mask = BIT(cfg->cbndx);
> > +     bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> > +     unsigned long flags;
> >
> >       if (enabled)
> > -             qsmmu->stall_enabled |= BIT(cfg->cbndx);
> > +             qsmmu->stall_enabled |= mask;
> >       else
> > -             qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> > +             qsmmu->stall_enabled &= ~mask;
> > +
> > +     /*
> > +      * If the device is on and we changed the setting, update the register.
> > +      */
> > +     if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> > +             spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> > +
> > +             u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> > +
> > +             if (enabled)
> > +                     reg |= ARM_SMMU_SCTLR_CFCFG;
> > +             else
> > +                     reg &= ~ARM_SMMU_SCTLR_CFCFG;
> > +
> > +             arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
>
> Are you sure you don't need TLB invalidation for this to take effect? I
> think some fields in the SCTLR can be cached in the TLB but you'll need
> to check whether or not that applies to CFCFG.
>
> Will

I think it should be fine because CFCFG only controls behavior when
there's a context fault and there can't be TLB entries for entries
that cause a context fault: "The architecture permits the caching of
any translation table entry that has been returned from memory without
a fault and that does not, as a result of that entry, cause a
Translation Fault or an Access Flag fault."

Connor


From david at redhat.com  Tue Mar 11 13:02:49 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 11 Mar 2025 21:02:49 +0100
Subject: [PATCH -next v1 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250311123241.GB3493@redhat.com>
References: <20250304154846.1937958-1-david@redhat.com>
 <20250304154846.1937958-4-david@redhat.com>
 <20250310170320.GC26382@redhat.com>
 <79ec5aa9-1937-436e-8cf4-436746142f7b@redhat.com>
 <20250311123241.GB3493@redhat.com>
Message-ID: <03a7797a-75a0-4b45-b5b0-bf8bfb7f0955@redhat.com>

On 11.03.25 13:32, Oleg Nesterov wrote:
> On 03/11, David Hildenbrand wrote:
>>
>> Regarding both questions, the code is fairly racy. Nothing would stop user
>> space from (a) modifying that memory
> 
> Yes, but we don't really care. uprobes.c assumes that user-space won't play
> with the probed memory.

Right, I primarily care about that if user space would do it, that we 
don't trigger unintended behavior (e.g., overwriting pagecache pages 
etc, WARN etc).

Likely the re-validating the page content is indeed something we can drop.

> 
> Note that if is_register is false, then vma can be even writable. Hmm, why?
> Perhaps valid_vma() should ignore is_register and nack VM_MAYWRITE ? But
> this doesn't really matter, say, gdb can change this memory anyway. Again,
> we don't really care.
> 
>>> do something like
>>>
>>> 	/* Walk the page tables again, to perform the actual update. */
>>> 	ret = -EAGAIN;
>>> 	folio = folio_walk_start(&fw, vma, vaddr, 0);
>>> 	if (folio) {
>>> 		if (fw.page == page) {
>>> 			WARN_ON(is_register && !folio_test_anon(folio));
>>
>> Yes, that would work (we could leave the WARN_ON in __uprobe_write_opcode),
>> but I am not sure if the end result is better better. No strong opinion on
>> the details though.
> 
> Will, this way __uprobe_write_opcode() will look a little bit simpler...
> 
> But I won't insist, please do what you think is better.

I'll take another look at this series probably next week (I'm on PTO 
this week) to then resend once adjusted + retested.

Thanks!

-- 
Cheers,

David / dhildenb



From robdclark at gmail.com  Tue Mar 11 13:03:29 2025
From: robdclark at gmail.com (Rob Clark)
Date: Tue, 11 Mar 2025 13:03:29 -0700
Subject: [PATCH v18 0/5] iommu/arm-smmu: introduction of ACTLR
 implementation for Qualcomm SoCs
In-Reply-To: <20250311175528.GA5216@willie-the-truck>
References: <20241212151402.159102-1-quic_bibekkum@quicinc.com>
 <173625436399.258197.10961901698600591079.b4-ty@kernel.org> <20250311175528.GA5216@willie-the-truck>
Message-ID: <CAF6AEGvDyPtXN7Cn98BKsTM9GjUzy1sTEOsLiz-cdvaZ14qWyA@mail.gmail.com>

On Tue, Mar 11, 2025 at 10:55?AM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Jan 07, 2025 at 04:42:39PM +0000, Will Deacon wrote:
> > On Thu, 12 Dec 2024 20:43:57 +0530, Bibek Kumar Patro wrote:
> > > This patch series consist of six parts and covers the following:
> > >
> > > 1. Provide option to re-enable context caching to retain prefetcher
> > >    settings during reset and runtime suspend.
> > >
> > > 2. Remove cfg inside qcom_smmu structure and replace it with single
> > >    pointer to qcom_smmu_match_data avoiding replication of multiple
> > >    members from same.
> > >
> > > [...]
> >
> > Applied to iommu (arm/smmu/updates), thanks!
> >
> > [1/5] iommu/arm-smmu: Re-enable context caching in smmu reset operation
> >       https://git.kernel.org/iommu/c/ef4144b1b47d
> > [2/5] iommu/arm-smmu: Refactor qcom_smmu structure to include single pointer
> >       https://git.kernel.org/iommu/c/445d7a8ed90e
> > [3/5] iommu/arm-smmu: Add support for PRR bit setup
> >       https://git.kernel.org/iommu/c/7f2ef1bfc758
> > [4/5] iommu/arm-smmu: Introduce ACTLR custom prefetcher settings
> >       https://git.kernel.org/iommu/c/9fe18d825a58
> > [5/5] iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500
> >       https://git.kernel.org/iommu/c/3e35c3e725de
>
> Hrm. I'm not seeing any user of the new ->set_prr*_() functions in
> linux-next yet. Is there something under review, or should I revert this
> for now?

It is WIP, part of a larger patchset adding sparse binding support in
drm/msm.  Please do not revert.

BR,
-R


From robh at kernel.org  Tue Mar 11 13:07:02 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 15:07:02 -0500
Subject: [PATCH v5 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <20250311122327.20685-2-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
 <20250311122327.20685-2-friday.yang@mediatek.com>
Message-ID: <174172361378.44650.15345202042780383326.robh@kernel.org>


On Tue, 11 Mar 2025 20:23:21 +0800, Friday Yang wrote:
> From: "Friday Yang" <friday.yang at mediatek.com>
> 
> On the MediaTek platform, some SMI LARBs are directly connected to
> the SMI Common, while others are connected to the SMI Sub-Common,
> which in turn is connected to the SMI Common. The hardware block
> diagram can be described as follows.
> 
>              SMI-Common(Smart Multimedia Interface Common)
>                  |
>          +----------------+------------------+
>          |                |                  |
>          |                |                  |
>          |                |                  |
>          |                |                  |
>          |                |                  |
>        larb0       SMI-Sub-Common0     SMI-Sub-Common1
>                    |      |     |      |             |
>                   larb1  larb2 larb3  larb7       larb9
> 
> For previous discussion on the direction of the code modifications,
> please refer to:
> https://lore.kernel.org/all/CAFGrd9qZhObQXvm2_abqaX83xMLqxjQETB2=wXpobDWU1CnvkA at mail.gmail.com/
> https://lore.kernel.org/all/CAPDyKFpokXV2gJDgowbixTvOH_5VL3B5H8eyhP+KJ5Fasm2rFg at mail.gmail.com/
> 
> On the MediaTek MT8188 SoC platform, we encountered power-off failures
> and SMI bus hang issues during camera stress tests. The issue arises
> because bus glitches are sometimes produced when MTCMOS powers on or
> off. While this is fairly normal, the software must handle these
> glitches to avoid mistaking them for transaction signals. What's
> more, this issue emerged only after the initial upstreaming of this
> binding. Without these patches, the SMI becomes unstable during camera
> stress tests.
> 
> The software solutions can be summarized as follows:
> 
> 1. Use CLAMP to disable the SMI sub-common port after turning off the
>    LARB CG and before turning off the LARB MTCMOS.
> 2. Use CLAMP to disable/enable the SMI sub-common port.
> 3. Implement an AXI reset for SMI LARBs.
> 
> This patch primarily add two changes:
> 1. Add compatible for SMI sub-common on MT8188 SoC.
> 2. Add 'resets' and 'reset-names' properties for SMI LARBs to
>    support SMI reset operations.
> 
> Signed-off-by: Friday Yang <friday.yang at mediatek.com>
> ---
>  .../mediatek,smi-common.yaml                  |  2 ++
>  .../memory-controllers/mediatek,smi-larb.yaml | 19 +++++++++++++++++++
>  2 files changed, 21 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From nicolinc at nvidia.com  Tue Mar 11 12:44:18 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:18 -0700
Subject: [PATCH v9 00/14] iommufd: Add vIOMMU infrastructure (Part-3: vEVENTQ)
Message-ID: <cover.1741719725.git.nicolinc@nvidia.com>

As the vIOMMU infrastructure series part-3, this introduces a new vEVENTQ
object. The existing FAULT object provides a nice notification pathway to
the user space with a queue already, so let vEVENTQ reuse that.

Mimicing the HWPT structure, add a common EVENTQ structure to support its
derivatives: IOMMUFD_OBJ_FAULT (existing) and IOMMUFD_OBJ_VEVENTQ (new).

An IOMMUFD_CMD_VEVENTQ_ALLOC is introduced to allocate vEVENTQ object for
vIOMMUs. One vIOMMU can have multiple vEVENTQs in different types but can
not support multiple vEVENTQs in the same type.

The forwarding part is fairly simple but might need to replace a physical
device ID with a virtual device ID in a driver-level event data structure.
So, this also adds some helpers for drivers to use.

As usual, this series comes with the selftest coverage for this new ioctl
and with a real world use case in the ARM SMMUv3 driver.

This is on Github:
https://github.com/nicolinc/iommufd/commits/iommufd_veventq-v9
Paring QEMU branch for testing:
https://github.com/nicolinc/qemu/commits/wip/for_iommufd_veventq-v9

Changelog
v9
 * Add Acked-by from Will
 * Fix typo in commit logs and reviewer name
 * Allow invaid nested STE for C_BAD_STE report
 * Drop extra indentation in arm_smmu_handle_event()
 * Drop comments in arm_smmu_attach_prepare_vmaster()
v8
 https://lore.kernel.org/all/cover.1740504232.git.nicolinc at nvidia.com/
 * Add Reviewed-by from Jason and Pranjal
 * Fix errno returned in arm_smmu_handle_event()
 * Validate domain->type outside of arm_smmu_attach_prepare_vmaster()
 * Drop unnecessary vmaster comparison in arm_smmu_attach_commit_vmaster()
v7
 https://lore.kernel.org/all/cover.1740238876.git.nicolinc at nvidia.com/
 * Rebase on Jason's for-next tree for latest fault.c
 * Add Reviewed-by
 * Update commit logs
 * Add __reserved field sanity
 * Skip kfree() on the static header
 * Replace "bool on_list" with list_is_last()
 * Use u32 for flags in iommufd_vevent_header
 * Drop casting in iommufd_viommu_get_vdev_id()
 * Update the bounding logic to veventq->sequence
 * Add missing cpu_to_le64() around STRTAB_STE_1_MEV
 * Reuse veventq->common.lock to fence sequence and num_events
 * Rename overflow to lost_events and log it in upon kmalloc failure
 * Correct the error handling part in iommufd_veventq_deliver_fetch()
 * Add an arm_smmu_clear_vmaster() to simplify identity/blocked domain
   attach ops
 * Add additional four event records to forward to user space VM, and
   update the uAPI doc
 * Reuse the existing smmu->streams_mutex lock to fence master->vmaster
   pointer, instead of adding a new rwsem
v6
 https://lore.kernel.org/all/cover.1737754129.git.nicolinc at nvidia.com/
 * Drop supports_veventq viommu op
 * Split bug/cosmetics fixes out of the series
 * Drop the blocking mutex around copy_to_user()
 * Add veventq_depth in uAPI to limit vEVENTQ size
 * Revise the documentation for a clear description
 * Fix sparse warnings in arm_vmaster_report_event()
 * Rework iommufd_viommu_get_vdev_id() to return -ENOENT v.s. 0
 * Allow Abort/Bypass STEs to allocate vEVENTQ and set STE.MEV for DoS
   mitigations
v5
 https://lore.kernel.org/all/cover.1736237481.git.nicolinc at nvidia.com/
 * Add Reviewed-by from Baolu
 * Reorder the OBJ list as well
 * Fix alphabetical order after renaming in v4
 * Add supports_veventq viommu op for vEVENTQ type validation
v4
 https://lore.kernel.org/all/cover.1735933254.git.nicolinc at nvidia.com/
 * Rename "vIRQ" to "vEVENTQ"
 * Use flexible array in struct iommufd_vevent
 * Add the new ioctl command to union ucmd_buffer
 * Fix the alphabetical order in union ucmd_buffer too
 * Rename _TYPE_NONE to _TYPE_DEFAULT aligning with vIOMMU naming
v3
 https://lore.kernel.org/all/cover.1734477608.git.nicolinc at nvidia.com/
 * Rebase on Will's for-joerg/arm-smmu/updates for arm_smmu_event series
 * Add "Reviewed-by" lines from Kevin
 * Fix typos in comments, kdocs, and jump tags
 * Add a patch to sort struct iommufd_ioctl_op
 * Update iommufd's userpsace-api documentation
 * Update uAPI kdoc to quote SMMUv3 offical spec
 * Drop the unused workqueue in struct iommufd_virq
 * Drop might_sleep() in iommufd_viommu_report_irq() helper
 * Add missing "break" in iommufd_viommu_get_vdev_id() helper
 * Shrink the scope of the vmaster's read lock in SMMUv3 driver
 * Pass in two arguments to iommufd_eventq_virq_handler() helper
 * Move "!ops || !ops->read" validation into iommufd_eventq_init()
 * Move "fault->ictx = ictx" closer to iommufd_ctx_get(fault->ictx)
 * Update commit message for arm_smmu_attach_prepare/commit_vmaster()
 * Keep "iommufd_fault" as-is and rename "iommufd_eventq_virq" to just
   "iommufd_virq"
v2
 https://lore.kernel.org/all/cover.1733263737.git.nicolinc at nvidia.com/
 * Rebase on v6.13-rc1
 * Add IOPF and vIRQ in iommufd.rst (userspace-api)
 * Add a proper locking in iommufd_event_virq_destroy
 * Add iommufd_event_virq_abort with a lockdep_assert_held
 * Rename "EVENT_*" to "EVENTQ_*" to describe the objects better
 * Reorganize flows in iommufd_eventq_virq_alloc for abort() to work
 * Adde struct arm_smmu_vmaster to store vSID upon attaching to a nested
   domain, calling a newly added iommufd_viommu_get_vdev_id helper
 * Adde an arm_vmaster_report_event helper in arm-smmu-v3-iommufd file
   to simplify the routine in arm_smmu_handle_evt() of the main driver
v1
 https://lore.kernel.org/all/cover.1724777091.git.nicolinc at nvidia.com/

Thanks!
Nicolin

Nicolin Chen (14):
  iommufd/fault: Move two fault functions out of the header
  iommufd/fault: Add an iommufd_fault_init() helper
  iommufd: Abstract an iommufd_eventq from iommufd_fault
  iommufd: Rename fault.c to eventq.c
  iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC
  iommufd/viommu: Add iommufd_viommu_get_vdev_id helper
  iommufd/viommu: Add iommufd_viommu_report_event helper
  iommufd/selftest: Require vdev_id when attaching to a nested domain
  iommufd/selftest: Add IOMMU_TEST_OP_TRIGGER_VEVENT for vEVENTQ
    coverage
  iommufd/selftest: Add IOMMU_VEVENTQ_ALLOC test coverage
  Documentation: userspace-api: iommufd: Update FAULT and VEVENTQ
  iommu/arm-smmu-v3: Introduce struct arm_smmu_vmaster
  iommu/arm-smmu-v3: Report events that belong to devices attached to
    vIOMMU
  iommu/arm-smmu-v3: Set MEV bit in nested STE for DoS mitigations

 drivers/iommu/iommufd/Makefile                |   2 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  36 ++
 drivers/iommu/iommufd/iommufd_private.h       | 135 +++-
 drivers/iommu/iommufd/iommufd_test.h          |  10 +
 include/linux/iommufd.h                       |  23 +
 include/uapi/linux/iommufd.h                  | 105 +++
 tools/testing/selftests/iommu/iommufd_utils.h | 115 ++++
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     |  60 ++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  80 ++-
 drivers/iommu/iommufd/driver.c                |  72 +++
 drivers/iommu/iommufd/eventq.c                | 597 ++++++++++++++++++
 drivers/iommu/iommufd/fault.c                 | 342 ----------
 drivers/iommu/iommufd/hw_pagetable.c          |   6 +-
 drivers/iommu/iommufd/main.c                  |   7 +
 drivers/iommu/iommufd/selftest.c              |  54 ++
 drivers/iommu/iommufd/viommu.c                |   2 +
 tools/testing/selftests/iommu/iommufd.c       |  36 ++
 .../selftests/iommu/iommufd_fail_nth.c        |   7 +
 Documentation/userspace-api/iommufd.rst       |  17 +
 19 files changed, 1298 insertions(+), 408 deletions(-)
 create mode 100644 drivers/iommu/iommufd/eventq.c
 delete mode 100644 drivers/iommu/iommufd/fault.c


base-commit: a05df03a88bc1088be8e9d958f208d6484691e43
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:19 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:19 -0700
Subject: [PATCH v9 01/14] iommufd/fault: Move two fault functions out of the header
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <7eebe32f3d354799f5e28128c693c3c284740b21.1741719725.git.nicolinc@nvidia.com>

There is no need to keep them in the header. The vEVENTQ version of these
two functions will turn out to be a different implementation and will not
share with this fault version. Thus, move them out of the header.

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/iommufd_private.h | 25 -------------------------
 drivers/iommu/iommufd/fault.c           | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 246297452a44..1c58f5fe17b4 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -472,31 +472,6 @@ struct iommufd_fault {
 	struct wait_queue_head wait_queue;
 };
 
-/* Fetch the first node out of the fault->deliver list */
-static inline struct iopf_group *
-iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
-{
-	struct list_head *list = &fault->deliver;
-	struct iopf_group *group = NULL;
-
-	spin_lock(&fault->lock);
-	if (!list_empty(list)) {
-		group = list_first_entry(list, struct iopf_group, node);
-		list_del(&group->node);
-	}
-	spin_unlock(&fault->lock);
-	return group;
-}
-
-/* Restore a node back to the head of the fault->deliver list */
-static inline void iommufd_fault_deliver_restore(struct iommufd_fault *fault,
-						 struct iopf_group *group)
-{
-	spin_lock(&fault->lock);
-	list_add(&group->node, &fault->deliver);
-	spin_unlock(&fault->lock);
-}
-
 struct iommufd_attach_handle {
 	struct iommu_attach_handle handle;
 	struct iommufd_device *idev;
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index c48d72c9668c..29e3a97c73c6 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -138,6 +138,31 @@ static void iommufd_compose_fault_message(struct iommu_fault *fault,
 	hwpt_fault->cookie = cookie;
 }
 
+/* Fetch the first node out of the fault->deliver list */
+static struct iopf_group *
+iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
+{
+	struct list_head *list = &fault->deliver;
+	struct iopf_group *group = NULL;
+
+	spin_lock(&fault->lock);
+	if (!list_empty(list)) {
+		group = list_first_entry(list, struct iopf_group, node);
+		list_del(&group->node);
+	}
+	spin_unlock(&fault->lock);
+	return group;
+}
+
+/* Restore a node back to the head of the fault->deliver list */
+static void iommufd_fault_deliver_restore(struct iommufd_fault *fault,
+					  struct iopf_group *group)
+{
+	spin_lock(&fault->lock);
+	list_add(&group->node, &fault->deliver);
+	spin_unlock(&fault->lock);
+}
+
 static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
 				       size_t count, loff_t *ppos)
 {
-- 
2.43.0



From nicolinc at nvidia.com  Tue Mar 11 12:44:22 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Tue, 11 Mar 2025 12:44:22 -0700
Subject: [PATCH v9 04/14] iommufd: Rename fault.c to eventq.c
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <d726397e2d08028e25a1cb6eb9febefac35a32ba.1741719725.git.nicolinc@nvidia.com>

Rename the file, aligning with the new eventq object.

Reviewed-by: Kevin Tian <kevin.tian at intel.com>
Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
 drivers/iommu/iommufd/Makefile              | 2 +-
 drivers/iommu/iommufd/{fault.c => eventq.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/iommu/iommufd/{fault.c => eventq.c} (100%)

diff --git a/drivers/iommu/iommufd/Makefile b/drivers/iommu/iommufd/Makefile
index cb784da6cddc..71d692c9a8f4 100644
--- a/drivers/iommu/iommufd/Makefile
+++ b/drivers/iommu/iommufd/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 iommufd-y := \
 	device.o \
-	fault.o \
+	eventq.o \
 	hw_pagetable.o \
 	io_pagetable.o \
 	ioas.o \
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/eventq.c
similarity index 100%
rename from drivers/iommu/iommufd/fault.c
rename to drivers/iommu/iommufd/eventq.c
-- 
2.43.0



From lorenzo at kernel.org  Tue Mar 11 13:07:45 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 11 Mar 2025 21:07:45 +0100
Subject: [PATCH 0/2] Add gpio-ranges property for EN7581 gpio controller
In-Reply-To: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org>
Message-ID: <Z9CYEZloamPhVdBS@lore-desk>

> Introduce missing gpio-ranges property for Airoha EN7581 evaluation
> board
> 

Hi Linus and Angelo,

is it fine if this series goes via linux-mediatek tree?
en7581_pinctrl node is only defined there for the moment.

Regards,
Lorenzo

> ---
> Lorenzo Bianconi (2):
>       dt-bindings: pinctrl: airoha: Add missing gpio-ranges property
>       arm64: dts: airoha: en7581: Add gpio-ranges property for gpio controller
> 
>  Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml | 3 +++
>  arch/arm64/boot/dts/airoha/en7581-evb.dts                            | 4 ++++
>  2 files changed, 7 insertions(+)
> ---
> base-commit: a8a297e8bb3dd304cac77f7c435a4983d885a657
> change-id: 20250307-en7581-gpio-range-fceb30c7e2c9
> 
> Best regards,
> -- 
> Lorenzo Bianconi <lorenzo at kernel.org>
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/b67d52e5/attachment.sig>

From konrad.dybcio at oss.qualcomm.com  Tue Mar 11 13:41:17 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 11 Mar 2025 21:41:17 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <vjkdwjudqsgcq2leabscnb2r5dbtztgfq3jlkfowcauslaymkp@qsxnpis3ksp6>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <vjkdwjudqsgcq2leabscnb2r5dbtztgfq3jlkfowcauslaymkp@qsxnpis3ksp6>
Message-ID: <827ca00b-a895-4aab-bd1e-7866df730fef@oss.qualcomm.com>

On 3/11/25 7:52 PM, Dmitry Baryshkov wrote:
> On Tue, Mar 11, 2025 at 07:02:56PM +0100, Christopher Obbard wrote:
>> Currently some Qualcomm interconnect drivers are enabled
>> as modules which isn't overly useful since the interconnects
>> are required to be loaded during early boot.
>>
>> Loading the interconnects late (e.g. in initrd or as module)
>> can cause boot issues, such as slowdown or even not booting
>> at all (since the interconnect would be required for storage
>> devices).
> 
> This is not a good justification. It should be perfectly fine to load
> block drivers (including their dependencies) from the initramfs.
> 
> Up to now we have been enabling only those interconnect (and pinctrl,
> btw) drivers, which are required to be able to open the consoe (thanks,
> systemd).

(non-earlycon) console is a better argument here, though

Konrad


From conor at kernel.org  Tue Mar 11 13:51:07 2025
From: conor at kernel.org (Conor Dooley)
Date: Tue, 11 Mar 2025 20:51:07 +0000
Subject: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document the
 TSU unit
In-Reply-To: <OSBPR01MB2775B3826A9FE602AC08172BFFD12@OSBPR01MB2775.jpnprd01.prod.outlook.com>
References: <20250227122453.30480-1-john.madieu.xa@bp.renesas.com>
 <20250227122453.30480-4-john.madieu.xa@bp.renesas.com>
 <20250228-shampoo-uprising-44ae0d3bd68b@spud>
 <OSBPR01MB2775DFC184F78E9FB50F28FFFFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-everyone-ragweed-e05a10a9646b@spud>
 <OSBPR01MB277531D7C872C9EB0B287069FFD52@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250307-barbell-pretzel-368d6a4d1336@spud>
 <OSBPR01MB2775D121B55A0C543F251BAEFFD72@OSBPR01MB2775.jpnprd01.prod.outlook.com>
 <20250310-blurry-scam-bee8233878bc@spud>
 <OSBPR01MB2775B3826A9FE602AC08172BFFD12@OSBPR01MB2775.jpnprd01.prod.outlook.com>
Message-ID: <20250311-immature-quit-81066aec062e@spud>

On Tue, Mar 11, 2025 at 11:24:59AM +0000, John Madieu wrote:
> Hi Conor,
> 
> > -----Original Message-----
> > From: Conor Dooley <conor at kernel.org>
> > Sent: Monday, March 10, 2025 5:15 PM
> > To: John Madieu <john.madieu.xa at bp.renesas.com>
> > Subject: Re: [PATCH v2 3/7] dt-bindings: thermal: r9a09g047-tsu: Document
> > the TSU unit
> > 
> > On Sun, Mar 09, 2025 at 10:39:27AM +0000, John Madieu wrote:
> > > Hi Conor,
> > > > > Changes are not possible at runtime. Some customers may want
> > > > > software, while other may want the external trigger, and this is
> > > > > immutable configuration.
> > > >
> > > > What makes it immutable? Set by some wiring on the board? I couldn't
> > > > find the user in your driver patches to better understand how you
> > > > were using it.
> > >
> > > I haven't prototyped ELC trigger yet. Since the hardware manual
> > > describes about ELC trigger, I have documented it in bindings. If you
> > > think, it is not needed at this stage, then I can drop it now and
> > > revisit later.
> > 
> > Ideally a binding is complete, even if the driver isn't. To me "immutable"
> > would mean something like "the trigger type is determined by hardware or
> > firmware configuration", but if it is determined by register writes (e.g.
> > wired up for elc trigger, but you can opt for software trigger in the
> > driver) then it should be a userspace control.
> 
> It is complete, and I confirm, this can be changed by register writes.
> Apart from defining default to 0, should I implement userspace change
> support now ?
> 
> Or should I keep it as it is, just setting default to 0 (thus making
> the property optional), and add support for userspace change when I add
> ELC support.
> 
> My other question is, in case I must add userspace change support now, would
> sysfs be Ok ? If yes, is there any path recommendations ?

How to change it from userspace ain't my domain, sorry. Just drop the
property since isn't something determined by the hardware, but rather by
what you put into the registers.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250311/b47e4cbd/attachment.sig>

From anarsoul at gmail.com  Tue Mar 11 15:00:44 2025
From: anarsoul at gmail.com (Vasily Khoruzhick)
Date: Tue, 11 Mar 2025 15:00:44 -0700
Subject: [PATCH v2 0/2] Add support for WiFi/BT header on Pine64 A64
In-Reply-To: <20241220120038.3137248-1-pbrobinson@gmail.com>
References: <20241220120038.3137248-1-pbrobinson@gmail.com>
Message-ID: <CA+E=qVdbbRbR+57WRPTJ-WPJ2jZz0V=mD56Ts2oQmo-rjxvO_w@mail.gmail.com>

On Fri, Dec 20, 2024 at 4:00?AM Peter Robinson <pbrobinson at gmail.com> wrote:
>
> Add the BT and WiFi pins on the WiFi/BT header on the Pine64/Sopine
> boards.
>
> Changes in v2:
> - drop patch that enables the WiFi module, it'll move to a overlay later

Any plans to send v3 with comments from Chen-Yu addressed?


> Peter Robinson (2):
>   arm64: dts: allwinner: a64: Add WiFi/BT header on Pine64
>   arm64: dts: allwinner: a64: Add WiFi/BT header on SoPine
>
>  .../boot/dts/allwinner/sun50i-a64-pine64.dts  | 17 +++++++++++++
>  .../allwinner/sun50i-a64-sopine-baseboard.dts | 24 +++++++++++++++++++
>  2 files changed, 41 insertions(+)
>
> --
> 2.47.1
>
>


From andi.shyti at kernel.org  Tue Mar 11 15:08:59 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 23:08:59 +0100
Subject: [PATCH 1/3] dt-bindings: i2c: i2c-rk3x: Add compatible string
 for RK3528
In-Reply-To: <20250309070603.35254-2-ziyao@disroot.org>
References: <20250309070603.35254-1-ziyao@disroot.org>
 <20250309070603.35254-2-ziyao@disroot.org>
Message-ID: <hzbhauetike6nf6ox3qdpud6hr4cg5kty3a7hlrfizdcwlodyh@rklxe3uhhitg>

Hi,

On Sun, Mar 09, 2025 at 07:06:01AM +0000, Yao Zi wrote:
> Document I2C controllers integrated in RK3528, which are compatible with
> the RK3399 variant.
> 
> Signed-off-by: Yao Zi <ziyao at disroot.org>

for self reference:

Reviewed-by: Andi Shyti <andi.shyti at kernel.org>

I will wait for v2 to apply it.

Thanks,
Andi


From andi.shyti at kernel.org  Tue Mar 11 15:15:38 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 23:15:38 +0100
Subject: [PATCH 1/1] dt-bindings: i2c: imx-lpi2c: add i.MX94 LPI2C
In-Reply-To: <20250306155815.110514-1-Frank.Li@nxp.com>
References: <20250306155815.110514-1-Frank.Li@nxp.com>
Message-ID: <oyjjcxuqki47gruavd2ms5lc4z2mawbdwjd2mwwxss2tq2xqm5@m2ztzpibjrkv>

Hi,

On Thu, Mar 06, 2025 at 10:58:15AM -0500, Frank Li wrote:
> Add compatible string "fsl,imx94-lpi2c" for the i.MX94 chip, which is
> backward compatible with i.MX7ULP. Set it to fall back to
> "fsl,imx7ulp-lpi2c".
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

merged to i2c/i2c-host.

Thanks,
Andi


From demonsingur at gmail.com  Tue Mar 11 15:26:16 2025
From: demonsingur at gmail.com (Cosmin Tanislav)
Date: Wed, 12 Mar 2025 00:26:16 +0200
Subject: [RFC PATCH v2 11/16] dt-bindings: media: i2c: add MAX9296A,
 MAX96716A, MAX96792A
In-Reply-To: <20250311190711.GA3985355-robh@kernel.org>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-12-demonsingur@gmail.com>
 <20250311190711.GA3985355-robh@kernel.org>
Message-ID: <80456f67-1742-4b54-98dd-0985f95c376e@gmail.com>



On 3/11/25 9:07 PM, Rob Herring wrote:
> On Sun, Mar 09, 2025 at 10:48:03AM +0200, Cosmin Tanislav wrote:
>> The MAX9296A deserializer converts single or dual serial inputs to MIPI
>> CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps or 6Gbps
>> in the forward direction and 187.5Mbps in the reverse direction.
>> In GMSL1 mode, each serial link can be paired with 3.12Gbps or 1.5Gbps
>> GMSL1 serializers or operate up to 4.5Gbps with GMSL2 serializers with
>> GMSL1 backward compatibility. The MAX9296A supports mixed GMSL2 and
>> GMSL1 links. The serial inputs operate independently, allowing videos
>> with different timings and resolutions to be received on each input.
>>
>> MAX96716A supports both tunnel and pixel mode.
>> MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
>>
>> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
>> ---
>>   .../bindings/media/i2c/maxim,max9296a.yaml    | 281 ++++++++++++++++++
>>   MAINTAINERS                                   |   6 +
>>   2 files changed, 287 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
>> new file mode 100644
>> index 000000000000..97731549d161
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
>> @@ -0,0 +1,281 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +# Copyright (C) 2024 Collabora Ltd.
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/media/i2c/maxim,max9296a.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Maxim MAX9296A GMSL2 to CSI-2 Deserializer
>> +
>> +maintainers:
>> +  - Cosmin Tanislav <cosmin.tanislav at analog.com>
>> +
>> +description:
> 
> Needs '>' token as you have paragraphs.
> 
>> +  The MAX9296A deserializer converts single or dual serial inputs to
>> +  MIPI CSI-2 outputs. The GMSL2 links operate at a fixed rate of 3Gbps
>> +  or 6Gbps in the forward direction and 187.5Mbps in the reverse
>> +  direction. In GMSL1 mode, each serial link can be paired with 3.12Gbps
>> +  or 1.5Gbps GMSL1 serializers or operate up to 4.5Gbps with GMSL2
>> +  serializers with GMSL1 backward compatibility. The MAX9296A supports
>> +  mixed GMSL2 and GMSL1 links. The serial inputs operate independently,
>> +  allowing videos with different timings and resolutions to be received
>> +  on each input.
>> +
>> +  MAX96716A supports both tunnel and pixel mode.
>> +  MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links.
>> +
>> +properties:
>> +  compatible:
>> +    enum:
>> +      - maxim,max9296a
>> +      - maxim,max96716a
>> +      - maxim,max96792a
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  powerdown-gpios:
>> +    maxItems: 1
>> +    description: Specifier for the GPIO connected to the PWDNB pin.
>> +
>> +  port0-poc-supply:
>> +    description: Regulator providing Power over Coax for GMSL port 0
>> +
>> +  port1-poc-supply:
>> +    description: Regulator providing Power over Coax for GMSL port 1
>> +
>> +  i2c-mux:
>> +    $ref: /schemas/i2c/i2c-mux.yaml#
>> +    unevaluatedProperties: false
>> +    patternProperties:
>> +      '^i2c@[0-1]$':
>> +        $ref: /schemas/i2c/i2c-controller.yaml#
>> +        unevaluatedProperties: false
>> +        properties:
>> +          reg:
>> +            items:
>> +              minimum: 0
>> +              maximum: 1
>> +
>> +  i2c-alias-pool:
>> +    maxItems: 2
>> +
>> +  i2c-atr:
>> +    type: object
>> +    additionalProperties: false
>> +
>> +    properties:
>> +      '#address-cells':
>> +        const: 1
>> +
>> +      '#size-cells':
>> +        const: 0
>> +
>> +    patternProperties:
>> +      '^i2c@[0-1]$':
>> +        $ref: /schemas/i2c/i2c-controller.yaml#
>> +        unevaluatedProperties: false
>> +        properties:
>> +          reg:
>> +            items:
>> +              minimum: 0
>> +              maximum: 1
>> +
>> +  ports:
>> +    $ref: /schemas/graph.yaml#/properties/ports
>> +
>> +    patternProperties:
>> +      '^port@[0-1]$':
>> +        $ref: /schemas/graph.yaml#/properties/port
>> +        unevaluatedProperties: false
>> +        description: GMSL Input
>> +        properties:
>> +          endpoint:
>> +            $ref: /schemas/media/video-interfaces.yaml#
> 
> What properties are you using from here?
> 
> None actually because /schemas/graph.yaml#/properties/port won't allow
> any.
> 

So these lines should be removed.

         unevaluatedProperties: false
         properties:
           endpoint:
             $ref: /schemas/media/video-interfaces.yaml#
             unevaluatedProperties: false
             description:
               Endpoint for GMSL2-Link port.

Should I submit patches to do the same for the maxim,max96714.yaml file?

I basically copied these bindings from there and adapted them, and those
bindings seem to have the same issue.

> 
>> +            unevaluatedProperties: false
>> +            description: Endpoint for GMSL2-Link port.
>> +
>> +      '^port@[2-3]$':
>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>> +        unevaluatedProperties: false
>> +        description: CSI-2 Output port
>> +        properties:
>> +          endpoint:
>> +            $ref: /schemas/media/video-interfaces.yaml#
>> +            unevaluatedProperties: false
>> +
>> +            properties:
>> +              data-lanes:
>> +                minItems: 1
>> +                maxItems: 4
>> +
>> +              lane-polarities:
>> +                minItems: 1
>> +                maxItems: 5
>> +
>> +              link-frequencies:
>> +                maxItems: 1
>> +
>> +            required:
>> +              - data-lanes
>> +
>> +    anyOf:
>> +      - required:
>> +          - port at 2
>> +      - required:
>> +          - port at 3
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - ports
>> +
>> +additionalProperties: false
>> +
>> +allOf:
>> +  - $ref: /schemas/i2c/i2c-atr.yaml#
>> +
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            enum:
>> +              - maxim,max9296a
>> +              - maxim,max96792a
>> +    then:
>> +      not:
>> +        required: [i2c-mux]
>> +
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            enum:
>> +              - maxim,max96716a
>> +    then:
>> +      not:
>> +        required: [i2c-atr]
>> +
>> +dependentRequired:
>> +  i2c-atr: [i2c-alias-pool]
>> +  i2c-alias-pool: [i2c-atr]
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/gpio/gpio.h>
>> +    #include <dt-bindings/media/video-interfaces.h>
>> +
>> +    i2c {
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +
>> +        deserializer at 28 {
>> +            compatible = "maxim,max9296a";
>> +            reg = <0x28>;
>> +            powerdown-gpios = <&main_gpio0 37 GPIO_ACTIVE_LOW>;
>> +
>> +            i2c-alias-pool = <0x40 0x41>;
>> +
>> +            ports {
>> +                #address-cells = <1>;
>> +                #size-cells = <0>;
>> +
>> +                port at 0 {
>> +                    reg = <0>;
>> +                    des_gmsl_in_0: endpoint {
>> +                        remote-endpoint = <&ser_0_gmsl_out>;
>> +                    };
>> +                };
>> +
>> +                port at 1 {
>> +                    reg = <1>;
>> +                    des_gmsl_in_1: endpoint {
>> +                        remote-endpoint = <&ser_1_gmsl_out>;
>> +                    };
>> +                };
>> +
>> +                port at 2 {
>> +                    reg = <2>;
>> +                    des_csi_out: endpoint {
>> +                        data-lanes = <1 2 3 4>;
>> +                        link-frequencies = /bits/ 64 <400000000>;
>> +                        remote-endpoint = <&csi_in>;
>> +                    };
>> +                };
>> +            };
>> +
>> +            i2c-atr {
>> +                #address-cells = <1>;
>> +                #size-cells = <0>;
>> +
>> +                i2c at 0 {
>> +                    #address-cells = <1>;
>> +                    #size-cells = <0>;
>> +                    reg = <0>;
>> +
>> +                    serializer at 40 {
>> +                        compatible = "maxim,max96717";
>> +                        reg = <0x40>;
>> +                        gpio-controller;
>> +                        #gpio-cells = <2>;
>> +                        #clock-cells = <0>;
>> +
>> +                        ports {
>> +                            #address-cells = <1>;
>> +                            #size-cells = <0>;
>> +
>> +                            port at 0 {
>> +                                reg = <0>;
>> +                                ser_0_csi_in: endpoint {
>> +                                    data-lanes = <1 2>;
>> +                                    remote-endpoint = <&sensor_0_out>;
>> +                                };
>> +                            };
>> +
>> +                            port at 1 {
>> +                                reg = <1>;
>> +                                ser_0_gmsl_out: endpoint {
>> +                                    remote-endpoint = <&des_gmsl_in_0>;
>> +                                };
>> +                            };
>> +                        };
>> +                    };
>> +                };
>> +
>> +                i2c at 1 {
>> +                    #address-cells = <1>;
>> +                    #size-cells = <0>;
>> +                    reg = <1>;
>> +
>> +                    serializer at 40 {
>> +                        compatible = "maxim,max96717";
>> +                        reg = <0x40>;
>> +                        gpio-controller;
>> +                        #gpio-cells = <2>;
>> +                        #clock-cells = <0>;
>> +
>> +                        ports {
>> +                            #address-cells = <1>;
>> +                            #size-cells = <0>;
>> +
>> +                            port at 0 {
>> +                                reg = <0>;
>> +                                ser_1_csi_in: endpoint {
>> +                                    data-lanes = <1 2>;
>> +                                    remote-endpoint = <&sensor_1_out>;
>> +                                };
>> +                            };
>> +
>> +                            port at 1 {
>> +                                reg = <1>;
>> +                                ser_1_gmsl_out: endpoint {
>> +                                    remote-endpoint = <&des_gmsl_in_1>;
>> +                                };
>> +                            };
>> +                        };
>> +                    };
>> +                };
>> +            };
>> +        };
>> +    };
>> +...
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index abf3afc95fc9..c1e01668e81a 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -14220,6 +14220,12 @@ S:	Maintained
>>   F:	Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml
>>   F:	drivers/iio/proximity/mb1232.c
>>   
>> +MAXIM GMSL2 SERIALIZERS AND DESERIALIZERS
>> +M:	Cosmin Tanislav <cosmin.tanislav at analog.com>
>> +L:	linux-media at vger.kernel.org
>> +S:	Maintained
>> +F:	Documentation/devicetree/bindings/media/i2c/maxim,max9296a.yaml
>> +
>>   MAXIM MAX11205 DRIVER
>>   M:	Ramona Bolboaca <ramona.bolboaca at analog.com>
>>   L:	linux-iio at vger.kernel.org
>> -- 
>> 2.48.1
>>



From andi.shyti at kernel.org  Tue Mar 11 15:33:42 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 23:33:42 +0100
Subject: [PATCH v3 04/15] dt-bindings: i2c: i2c-rk3x: Add rk3562 support
In-Reply-To: <20250227111913.2344207-5-kever.yang@rock-chips.com>
References: <20250227111913.2344207-1-kever.yang@rock-chips.com>
 <20250227111913.2344207-5-kever.yang@rock-chips.com>
Message-ID: <dqgqw2e33gaieos3lk4vkrfqmnunrxooar7gisrdwqjhdnl4m5@s2cxnaur5a2b>

Hi Kever,

On Thu, Feb 27, 2025 at 07:19:02PM +0800, Kever Yang wrote:
> rk3562 i2c compatible to the existing rk3399 binding.
> 
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>

merged to i2c/i2c-host.

Thanks,
Andi


From cwabbott0 at gmail.com  Tue Mar 11 15:36:38 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Tue, 11 Mar 2025 18:36:38 -0400
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250311180553.GB5216@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com> <20250311180553.GB5216@willie-the-truck>
Message-ID: <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>

On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > This will be used by drm/msm for GPU page faults, replacing the manual
> > register reading it does.
> >
> > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
> >  drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
> >  drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
> >  3 files changed, 21 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> >
> >       if (list_empty(&tbu_list)) {
> >               ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > -                                      cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > +                                      cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> >
> >               if (ret == -ENOSYS)
> >                       arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> > @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> >       phys_soft = ops->iova_to_phys(ops, cfi.iova);
> >
> >       tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > -                              cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > +                              cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> >       if (!tmp || tmp == -EBUSY) {
> >               ret = IRQ_HANDLED;
> >               resume = ARM_SMMU_RESUME_TERMINATE;
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> >                                     struct arm_smmu_context_fault_info *cfi)
> >  {
> >       cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> >       cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
>
> We already have an implementation hook (->get_fault_info()) which the
> qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> That thing dumps these registers already so if we're moving that into
> the core SMMU driver, let's get rid of the hook and move everybody over
> rather than having it done in both places.

As you probably saw, the next commit moves over
qcom_adreno_smmu_get_fault_info() to use this. The current back door
used by drm/msm to access these functions is specific to adreno_smmu
and there isn't an equivalent interface to allow it to call a generic
SMMU function so it isn't possible to move it entirely to the core. At
least not without a bigger refactoring that isn't justified for this
series that is just trying to fix things.

>
> >       cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
>
> I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> it for stage-2 domains.
>
> Will

Does it matter if we read the register though, as long as users are
aware of this and don't use its value for anything?

Connor


From andi.shyti at kernel.org  Tue Mar 11 15:51:32 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 23:51:32 +0100
Subject: [PATCH 0/2] Simplify clock handling and fix probe error handling
 sequence
In-Reply-To: <20250206115708.1085523-1-manikanta.guntupalli@amd.com>
References: <20250206115708.1085523-1-manikanta.guntupalli@amd.com>
Message-ID: <6xj34bjcmcdktbztrovkionpazqadiscmpg632k2qevxbuf2bb@tzdnnrkc4py5>

Hi,

On Thu, Feb 06, 2025 at 05:27:06PM +0530, Manikanta Guntupalli wrote:
> This series includes two patches that improve the Cadence I2C driver
> by simplifying clock handling and ensuring correct reset sequencing
> in the probe error path.
> 
> Manikanta Guntupalli (1):
>   i2c: cadence: Move reset_control_assert after pm_runtime_set_suspended
>     in probe error path
> 
> Michal Simek (1):
>   i2c: cadence: Simplify using devm_clk_get_enabled()

I was sure I did take this patch, but unfortunately I forgot it.
Feel free to ping me in such case.

Merged to i2c/i2c-host.

Thanks,
Andi


From andi.shyti at kernel.org  Tue Mar 11 15:52:49 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Tue, 11 Mar 2025 23:52:49 +0100
Subject: [PATCH] i2c: cadence: fix call balance of id->clk handling
 routines
In-Reply-To: <20250303140805.644143-1-mordan@ispras.ru>
References: <20250303140805.644143-1-mordan@ispras.ru>
Message-ID: <rbn5jxvmcl76n3grg3fzc3z5vqgmieixmrq3rkhbpdremlbeze@quqxmsszknfe>

Hi Vitalii,

On Mon, Mar 03, 2025 at 05:08:05PM +0300, Vitalii Mordan wrote:
> If the clock id->clk was not enabled in cdns_i2c_probe(), it should not be
> disabled in any execution path. If the clock was not enabled, the probe
> function should return an error code.
> 
> Use the devm_clk_get_enabled() helper function to ensure proper call
> balance for id->clk.
> 
> Found by Linux Verification Center (linuxtesting.org) with Klever.
> 
> Fixes: df8eb5691c48 ("i2c: Add driver for Cadence I2C controller")
> Signed-off-by: Vitalii Mordan <mordan at ispras.ru>

Thanks for this patch, but it was already sent previously by
Michal and Manikanta.

Thanks,
Andi


From andi.shyti at kernel.org  Tue Mar 11 16:13:09 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Wed, 12 Mar 2025 00:13:09 +0100
Subject: [PATCH v2 0/4] Add PERIC0/1 support for Exynos 990 and hsi2c
 compatible
In-Reply-To: <20250212004824.1011-1-wachiturroxd150@gmail.com>
References: <20250212004824.1011-1-wachiturroxd150@gmail.com>
Message-ID: <jwihm4ahyjluillz5szgvwj3ntjypqekjf43g4c2poa7r3v7ar@5uka5xftxjzf>

Hi Denzel,

On Wed, Feb 12, 2025 at 12:48:20AM +0000, Denzeel Oliva wrote:
> This patch series enables the PERIC0/1 (Peripheral Connectivity)
> and compatible hsi2 for Exynos990:
> 
> - PERIC0/1 feeds HSI2C, SPI and UART
> 
> This part tests one by one to see which clock hangs without
> the CLK_IGNORE_UNUSED flag.
> 
> Changes v2:
>  - Remove other unnecessary patches which is nothing related
>    to linux shipping style.
> 
> Denzeel Oliva (4):
>   dt-bindings: clock: samsung,exynos990-clock: add PERIC0/1 clock
>     management unit
>   dt-bindings: i2c: exynos5: add samsung,exynos990-hsi2c compatible
>   clk: samsung: exynos990: add support for CMU_PERIC0/1
>   arm64: dts: exyno990: enable cmu-peric0/1 clock controller

what is the future of this series? Are you planning a v2?

Andi


From honyuenkwun at gmail.com  Tue Mar 11 16:15:47 2025
From: honyuenkwun at gmail.com (Jimmy Hon)
Date: Tue, 11 Mar 2025 18:15:47 -0500
Subject: [PATCH] arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max
In-Reply-To: <20250311141245.2719796-1-liujianfeng1994@gmail.com>
References: <20250311141245.2719796-1-liujianfeng1994@gmail.com>
Message-ID: <CALWfF7JfJxudKKfvOBXiLOMijUi+xZCAUL_WRsB-UxpV3XKDEg@mail.gmail.com>

On Tue, Mar 11, 2025 at 9:13?AM Jianfeng Liu <liujianfeng1994 at gmail.com> wrote:
>
> According to the schematic, pcie reset gpio is GPIO3_D4,
> not GPIO4_D4.
Thanks for the correction.
Also applies to the Orange Pi 5 Ultra.

I made the typo when starting with the Orange Pi 5 Plus with "gpio3
RK_PB3" and changed both "3" to "4".

I'm guessing u-boot has already initialized the device, otherwise the
problem would be more obvious.

>
> Fixes: c600d252dc52 ("arm64: dts: rockchip: Add Orange Pi 5 Max board")
> Signed-off-by: Jianfeng Liu <liujianfeng1994 at gmail.com>
Reviewed-by: Jimmy Hon <honyuenkwun at gmail.com>

> ---
>
>  arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
> index 6e4dcd8fff26..f748c6f760d8 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi
> @@ -64,7 +64,7 @@ &led_blue_pwm {
>
>  /* phy2 */
>  &pcie2x1l1 {
> -       reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>;
> +       reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
>         vpcie3v3-supply = <&vcc3v3_pcie_eth>;
>         status = "okay";
>  };
> --
> 2.43.0
>


From andi.shyti at kernel.org  Tue Mar 11 16:16:31 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Wed, 12 Mar 2025 00:16:31 +0100
Subject: [PATCH v4 0/1] i2c: mediatek: add runtime PM operations and bus
 regulator control
In-Reply-To: <ec77bb9478cd86a6737b92135170064970925b3c.camel@mediatek.com>
References: <20250211144016.488001-1-zoie.lin@mediatek.com>
 <46621db1-6096-46af-b021-c919c1cae7ef@collabora.com>
 <ec77bb9478cd86a6737b92135170064970925b3c.camel@mediatek.com>
Message-ID: <idbp6ckhu2pdt5p6vapcblqlinezpq5miqzl4hrzmlbgrniw7o@ucd42tvbtfmr>

Hi Zoie,

On Tue, Mar 04, 2025 at 08:37:27AM +0000, Zoie Lin (???) wrote:
> 
> ...
> 
> On Thu, 2025-02-13 at 12:57 +0100, AngeloGioacchino Del Regno wrote:
> > 
> > 
> > Turning on and off regulators at start of transfer and end of
> > transfer respectively
> > is very expensive and, while it makes sense for power efficiency of
> > the controller,
> > it doesn't make sense for:
> > 
> > ? 1. Responsiveness (latency); and
> > ? 2. Platform power efficiency at a whole.
> > 
> > As a start, just set the autosuspend delay to 250ms; this gives you
> > at least time
> > to bring up clocks and regulators and usually finish a transfer at
> > 400KHz, giving
> > you the chance to also get some more requests before autosuspend
> > decides to, well,
> > auto..suspend the device.
> > 
> > The right way of choosing an autosuspend delay a bit more precisely,
> > though, for
> > this device, would be to check the bus speed and calculate the
> > autosuspend time
> > accordingly.
> 
> We understand the importance of balancing power efficiency and
> responsiveness. Given the diversity of I2C devices connected
> under each platform, it is indeed challenging to estimate an
> appropriate delay time for testing.
> 
> Therefore, we would like to proceed with your initial suggestion
> and set the autosuspend delay to 250ms. Based on our preliminary
> tests, this adjustment appears to be a practical solution across 
> our existing platforms.

Am I understanding correctly that you are planning a v2?

Andi


From lkp at intel.com  Tue Mar 11 16:35:01 2025
From: lkp at intel.com (kernel test robot)
Date: Wed, 12 Mar 2025 07:35:01 +0800
Subject: [PATCH net-next 3/9] net: stmmac: remove of_get_phy_mode()
In-Reply-To: <E1trbxk-005qYA-Up@rmk-PC.armlinux.org.uk>
References: <E1trbxk-005qYA-Up@rmk-PC.armlinux.org.uk>
Message-ID: <202503120741.lpX5066n-lkp@intel.com>

Hi Russell,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Russell-King-Oracle/net-stmmac-qcom-ethqos-remove-of_get_phy_mode/20250311-001446
base:   net-next/main
patch link:    https://lore.kernel.org/r/E1trbxk-005qYA-Up%40rmk-PC.armlinux.org.uk
patch subject: [PATCH net-next 3/9] net: stmmac: remove of_get_phy_mode()
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250312/202503120741.lpX5066n-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250312/202503120741.lpX5066n-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503120741.lpX5066n-lkp at intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c:11:
   In file included from include/linux/of_net.h:9:
   In file included from include/linux/phy.h:16:
   In file included from include/linux/ethtool.h:18:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:10:
   In file included from include/linux/mm.h:2224:
   include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     504 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     505 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     511 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     512 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:524:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     524 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     525 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c:94:4: warning: variable 'phy_mode' is uninitialized when used here [-Wuninitialized]
      94 |                         phy_mode);
         |                         ^~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                        ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                                     ^~~~~~~~~~~
   drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c:67:2: note: variable 'phy_mode' is declared here
      67 |         phy_interface_t phy_mode;
         |         ^
   4 warnings generated.


vim +/phy_mode +94 drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c

2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   61  
41b984be408c088 Russell King (Oracle  2025-03-10   62) static struct anarion_gmac *
41b984be408c088 Russell King (Oracle  2025-03-10   63) anarion_config_dt(struct platform_device *pdev,
41b984be408c088 Russell King (Oracle  2025-03-10   64) 		  struct plat_stmmacenet_data *plat_dat)
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   65  {
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   66  	struct anarion_gmac *gmac;
0c65b2b90d13c1d Andrew Lunn           2019-11-04   67  	phy_interface_t phy_mode;
0c65b2b90d13c1d Andrew Lunn           2019-11-04   68  	void __iomem *ctl_block;
0c65b2b90d13c1d Andrew Lunn           2019-11-04   69  	int err;
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   70  
ad124aa34e51439 YueHaibing            2019-08-21   71  	ctl_block = devm_platform_ioremap_resource(pdev, 1);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   72  	if (IS_ERR(ctl_block)) {
51fe084b17e795f Simon Horman          2023-04-06   73  		err = PTR_ERR(ctl_block);
51fe084b17e795f Simon Horman          2023-04-06   74  		dev_err(&pdev->dev, "Cannot get reset region (%d)!\n", err);
51fe084b17e795f Simon Horman          2023-04-06   75  		return ERR_PTR(err);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   76  	}
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   77  
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   78  	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   79  	if (!gmac)
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   80  		return ERR_PTR(-ENOMEM);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   81  
9f12541d684b925 Simon Horman          2023-04-06   82  	gmac->ctl_block = ctl_block;
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   83  
41b984be408c088 Russell King (Oracle  2025-03-10   84) 	switch (plat_dat->phy_interface) {
df561f6688fef77 Gustavo A. R. Silva   2020-08-23   85  	case PHY_INTERFACE_MODE_RGMII:
df561f6688fef77 Gustavo A. R. Silva   2020-08-23   86  		fallthrough;
df561f6688fef77 Gustavo A. R. Silva   2020-08-23   87  	case PHY_INTERFACE_MODE_RGMII_ID:
df561f6688fef77 Gustavo A. R. Silva   2020-08-23   88  	case PHY_INTERFACE_MODE_RGMII_RXID:
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   89  	case PHY_INTERFACE_MODE_RGMII_TXID:
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   90  		gmac->phy_intf_sel = GMAC_CONFIG_INTF_RGMII;
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   91  		break;
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   92  	default:
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   93  		dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n",
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04  @94  			phy_mode);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   95  		return ERR_PTR(-ENOTSUPP);
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   96  	}
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   97  
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   98  	return gmac;
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04   99  }
2d1611aff3f22a5 Alexandru Gagniuc     2017-08-04  100  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From pablo at netfilter.org  Tue Mar 11 16:44:04 2025
From: pablo at netfilter.org (Pablo Neira Ayuso)
Date: Wed, 12 Mar 2025 00:44:04 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
 <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com>
Message-ID: <Z9DKxOnxr1fSv0On@calendula>

Hi,

On Tue, Mar 11, 2025 at 09:22:35AM +0100, Eric Woudstra wrote:
> 
> 
> On 3/5/25 11:29 AM, Eric Woudstra wrote:
> > This patchset makes it possible to set up a software fastpath between
> > bridged interfaces. One patch adds the flow rule for the hardware
> > fastpath. This creates the possibility to have a hardware offloaded
> > fastpath between bridged interfaces. More patches are added to solve
> > issues found with the existing code.
> 
> 
> > Changes in v9:
> > - No changes, resend to netfilter
> 
> Hi Pablo,
> 
> I've changed tag [net-next] to [nf], hopefully you can have a look at
> this patch-set. But, after some days, I was in doubt if this way I have
> brought it to your attention. Perhaps I need to do something different
> to ask the netfilter maintainer have a look at it?

Apologies, this maintainance service is best effort.

I am also going to be very busy until April to complete a few more
deliverables, I cannot afford more cancelled projects. I will try to
collect what is left for net-next and wait for the next merge window.

Therefore, I suggest you start with a much smaller series with a
carefully selected subset including preparatory patches. I suggest you
start with the software enhancements only. Please, add datapath tests.

As for the hardware offload part, I have a board that I received 4.5
ago years as a engineering sample that maybe I can use to test this,
but no idea, really.

You are a passer-by (ahem, "contributor"), this will get merged
upstream at some point and we will have to maintain all this new code
without your help maybe ... (people change bussiness units...), I have
to understand what is going on here. The throughput available is
limited, I am afraid we can only go _slow and careful_.

Thanks.

P.S: You work is important, very important, but maybe there is no need
to Cc so many mailing lists and people, maybe netdev@,
netfilter-devel@ and bridge@ is sufficient.


From oliver.upton at linux.dev  Tue Mar 11 16:44:26 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Tue, 11 Mar 2025 16:44:26 -0700
Subject: [PATCH v3 00/14] KVM: arm64: FEAT_PMUv3 on Apple hardware
In-Reply-To: <20250305202641.428114-1-oliver.upton@linux.dev>
References: <20250305202641.428114-1-oliver.upton@linux.dev>
Message-ID: <174173663466.1065484.5411031116504311230.b4-ty@linux.dev>

On Wed, 05 Mar 2025 12:26:27 -0800, Oliver Upton wrote:
> Hopefully close to the last spin, this time addressing Marc's comments
> on v2.
> 
> Full details found in the v1 cover letter.
> 
> v1: https://lore.kernel.org/kvmarm/20241217212048.3709204-1-oliver.upton at linux.dev/
> v2: https://lore.kernel.org/kvmarm/20250203183111.191519-1-oliver.upton at linux.dev/
> 
> [...]

Applied to next, thanks!

[01/14] drivers/perf: apple_m1: Refactor event select/filter configuration
        https://git.kernel.org/kvmarm/kvmarm/c/75ecffc361bb
[02/14] drivers/perf: apple_m1: Support host/guest event filtering
        https://git.kernel.org/kvmarm/kvmarm/c/46573d944f00
[03/14] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
        https://git.kernel.org/kvmarm/kvmarm/c/93b01528586b
[04/14] KVM: arm64: Always support SW_INCR PMU event
        https://git.kernel.org/kvmarm/kvmarm/c/ed335722b457
[05/14] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
        https://git.kernel.org/kvmarm/kvmarm/c/6f34024d185e
[06/14] KVM: arm64: Drop kvm_arm_pmu_available static key
        https://git.kernel.org/kvmarm/kvmarm/c/a38b67d15183
[07/14] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
        https://git.kernel.org/kvmarm/kvmarm/c/3d6d9172128e
[08/14] KVM: arm64: Move PMUVer filtering into KVM code
        https://git.kernel.org/kvmarm/kvmarm/c/56290316a443
[09/14] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
        https://git.kernel.org/kvmarm/kvmarm/c/2c433f70dccc
[10/14] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
        https://git.kernel.org/kvmarm/kvmarm/c/bed9b8ec8c71
[11/14] KVM: arm64: Remap PMUv3 events onto hardware
        https://git.kernel.org/kvmarm/kvmarm/c/1e7dcbfa4b7c
[12/14] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
        https://git.kernel.org/kvmarm/kvmarm/c/2d00cab849be
[13/14] KVM: arm64: Provide 1 event counter on IMPDEF hardware
        https://git.kernel.org/kvmarm/kvmarm/c/1b92e65f5006
[14/14] arm64: Enable IMP DEF PMUv3 traps on Apple M*
        https://git.kernel.org/kvmarm/kvmarm/c/e1231aacb065

--
Best,
Oliver


From quic_jiegan at quicinc.com  Tue Mar 11 18:20:44 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Wed, 12 Mar 2025 09:20:44 +0800
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com>
 <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>
Message-ID: <cef984d5-f369-4892-b970-a71285c2ebc5@quicinc.com>



On 3/12/2025 12:49 AM, Mike Leach wrote:
> Hi,
> 
> On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>
>> The new functions calculate and return the offset to the write pointer of
>> the ETR buffer based on whether the memory mode is SG, flat or reserved.
>> The functions have the RWP offset can directly read data from ETR buffer,
>> enabling the transfer of data to any required location.
>>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>>   .../hwtracing/coresight/coresight-tmc-etr.c   | 40 +++++++++++++++++++
>>   drivers/hwtracing/coresight/coresight-tmc.h   |  1 +
>>   2 files changed, 41 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index eda7cdad0e2b..ec636ab1fd75 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
>>   }
>>   EXPORT_SYMBOL_GPL(tmc_free_sg_table);
>>
>> +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata)
>> +{
>> +       dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
>> +       u64 rwp;
>> +
> 
> It is not valid to read RWP if the TMC is running. It must be in the
> stopped or disabled state - see the specifications for TMC /ETR
> 
> It is likely that CSUNLOCK / CSLOCK are needed here too,  along with
> the spinlock that protects drvdata
> 
> See the code in coresight_tmc_etr.c :-
> 
> e.g. in
> 
> tmc_update_etr_buffer()
> 
> ...
> <take spinlock>
> ...
> CS_UNLOCK(drvdata->base);
> tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and
> flushed to memory - essential to ensure full formatted frame is in
> memory.
> tmc_sync_etr_buf(drvdata); // this function reads rwp.
> CS_LOCK(drvdata->base);
> <release spinlokc>
> 
> This type of program flow is common to both sysfs and perf handling of
> TMC buffers.

Hi Mike,

I am fully understood your point here.

The function is designed this way to read the w_offset (which may not be 
entirely accurate because the etr buffer is not synced) when the 
byte-cntr devnode is opened, aiming to reduce the length of redundant 
trace data. In this case, we cannot ensure the TMC is stopped or 
disabled. The byte-cntr only requires an offset to know where it can 
start before the expected trace data gets into ETR buffer.

The w_offset is also read when the byte-cntr function stops, which 
occurs after the TMC is disabled.

Maybe this is not a good idea and I should read r_offset upon open?
The primary goal for byte-cntr is trying to transfer useful trace data 
from the ETR buffer to the userspace, if we start from r_offset, a large 
number of redundant trace data which the user does not expect will be 
transferred simultaneously.


> 
>> +       rwp = tmc_read_rwp(drvdata);
>> +       return rwp - paddr;
>> +}
>> +
>> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
>> +{
>> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
>> +       struct etr_sg_table *etr_table = etr_buf->private;
>> +       struct tmc_sg_table *table = etr_table->sg_table;
>> +       long w_offset;
>> +       u64 rwp;
>> +
> 
> Same comments as above
> 
>> +       rwp = tmc_read_rwp(drvdata);
>> +       w_offset = tmc_sg_get_data_page_offset(table, rwp);
>> +
>> +       return w_offset;
>> +}
>> +
>> +/*
>> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
>> + * the memory mode is SG, flat or reserved.
>> + */
>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
>> +{
>> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
>> +
> 
> As this is an exported function, please ensure that the inputs are
> valid - check the pointers

Sure, will do.

Thanks,
Jie

> 
> Code to ensure TMC is flushed and stopped could be inserted here.
> 
> Regards
> 
> Mike
> 
>> +       if (etr_buf->mode == ETR_MODE_ETR_SG)
>> +               return tmc_sg_get_rwp_offset(drvdata);
>> +       else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
>> +               return tmc_flat_resrv_get_rwp_offset(drvdata);
>> +       else
>> +               return -EINVAL;
>> +}
>> +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
>> +
>>   /*
>>    * Alloc pages for the table. Since this will be used by the device,
>>    * allocate the pages closer to the device (i.e, dev_to_node(dev)
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
>> index b48bc9a01cc0..baedb4dcfc3f 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>> @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
>>   struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>>                                     enum cs_mode mode, void *data);
>>   extern const struct attribute_group coresight_etr_group;
>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>>
>>   #endif
>> --
>> 2.34.1
>>
> 
> 



From robh at kernel.org  Tue Mar 11 18:47:07 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 11 Mar 2025 20:47:07 -0500
Subject: [PATCH v5 0/3] add sof support on imx95
In-Reply-To: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
References: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
Message-ID: <174174398131.182748.13049437230815741677.robh@kernel.org>


On Tue, 11 Mar 2025 12:32:52 -0400, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> 
> Add sof support on imx95. This series also includes some changes to
> the audio-graph-card2 binding required for the support.
> 
> ---
> Changes in v5:
> - added comment in the DTS regarding the reserved DMA channels.
> - addressed Frank's comment regarding the widgets/routing properties.
> - changed codec and CPU EP names to include SAI3/WM8962 in their naming.
> Previous naming was too generic.
> - picked up some more R-b's
> - change soundcard DT node name to the more generic "sof-sound" as the
> soundcard might support additional DAI-CODEC links in the future.
> - change the soundcard label to "audio". Same rationale as above. The
> SOF core will append to it the "sof-" prefix, thus the resulting name will
> be "sof-audio".
> - Link to v4: https://lore.kernel.org/lkml/20250211225808.3050-1-laurentiumihalcea111 at gmail.com/
> 
> Changes in v4:
> - addressed Frank's comments regarding the DTS.
> - squashed commits for common and imx95 bindings.
> - dropped patch introducing driver. This was already handled via
> https://lore.kernel.org/all/20250207162246.3104-1-laurentiumihalcea111 at gmail.com/
> - introduced two new properties: 'reg-names' and 'memory-region-names',
> which are now needed by the driver to work properly. Because of this, 'reg'
> and 'memory-region' properties had to be moved from the common binding as
> 'reg-names' and 'memory-region-names' depend on them (you'd get a failure
> when running the binding check otherwise).
> - added missing 'bitclock-master' and 'frame-master' properties to codec EP.
> - addressed Krzysztof's comments regarding the imx95 binding
> - added Krzysztof's Acked-by
> - Link to v3: https://lore.kernel.org/lkml/20241216145039.3074-1-laurentiumihalcea111 at gmail.com/
> 
> Changes in v3:
> - Ordered DT nodes alphabetically
> - Removed 'cpu' and 'cpu_ep' labels from binding example
> - Some small changes to the binding commit messages/titles.
> - Link to v2: https://lore.kernel.org/lkml/20241113195240.3699-1-laurentiumihalcea111 at gmail.com/
> 
> Changes in v2:
> - Added new binding for 95's CM7 core with SOF. fsl,dsp.yaml is no longer used.
> - "hp-det-gpios" and "widgets" properties now reference the definitions from audio-graph.yaml
> - Removed extra empty spaces from DTS as suggested by Frank
> - Ordered 'edma2', 'sai3', 'wm8962' DT nodes alphabetically. The order of the nodes
> placed inside / is kept the same for readability
> - Ordered driver header files includes alphabetically as suggested by Frank
> - Removed "reg-names" and changed the maximum size of the "reg" property to 1 to align
> with the other NXP CPUs sharing the same programming model (i.e: audio processing with SOF).
> The region described in the DTS is the SRAM and the mailbox region is now hardcoded in the
> driver as an offset to the start of the SRAM region.
> - Added new binding with properties required by all NXP CPUs sharing the same programming
> model (i.e: audio processing with SOF).
> - Various driver adjustments made to accomodate the DT changes + some bug fixing related
> to the mboxes not being requested/free'd on resume/suspend.
> - Fixed value passed to "dma-channel-mask". A set bit means the channel is masked, not the
> other way around.
> - Link to v1: https://lore.kernel.org/lkml/20241023162114.3354-1-laurentiumihalcea111 at gmail.com/
> ---
> 
> Laurentiu Mihalcea (3):
>   ASoC: dt-bindings: support imx95's CM7 core
>   ASoC: dt-bindings: audio-graph-card2: add widgets and hp-det-gpios
>     support
>   arm64: dts: imx: add imx95 dts for sof
> 
>  .../bindings/sound/audio-graph-card2.yaml     |  4 +
>  .../bindings/sound/fsl,imx95-cm7-sof.yaml     | 64 ++++++++++++++
>  .../bindings/sound/fsl,sof-cpu.yaml           | 27 ++++++
>  arch/arm64/boot/dts/freescale/Makefile        |  1 +
>  .../dts/freescale/imx95-19x19-evk-sof.dts     | 84 +++++++++++++++++++
>  5 files changed, 180 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml
>  create mode 100644 arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dts
> 
> --
> 2.34.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/freescale/' for 20250311163255.2664-1-laurentiumihalcea111 at gmail.com:

arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dtb: pcie at 4c300000: clock-names: ['pcie', 'pcie_bus', 'pcie_phy', 'pcie_aux'] is too short
	from schema $id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie.yaml#
arch/arm64/boot/dts/freescale/imx95-19x19-evk-sof.dtb: pcie at 4c380000: clock-names: ['pcie', 'pcie_bus', 'pcie_phy', 'pcie_aux'] is too short
	from schema $id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie.yaml#







From nichen at iscas.ac.cn  Tue Mar 11 20:26:00 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Wed, 12 Mar 2025 11:26:00 +0800
Subject: [PATCH] ASoC: mt8365: remove unnecessary NULL check before clk_disable_unprepare()
Message-ID: <20250312032600.1235158-1-nichen@iscas.ac.cn>

clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL.
Remove unneeded NULL check for clk here.

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
 sound/soc/mediatek/mt8365/mt8365-afe-clk.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
index 8a0af2ea8546..7078c01ba19b 100644
--- a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
@@ -49,8 +49,7 @@ int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe)
 
 void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
 {
-	if (clk)
-		clk_disable_unprepare(clk);
+	clk_disable_unprepare(clk);
 }
 
 int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
-- 
2.25.1



From anshuman.khandual at arm.com  Tue Mar 11 20:46:32 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Wed, 12 Mar 2025 09:16:32 +0530
Subject: [PATCH V3] arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
In-Reply-To: <174171335999.3659520.16613654046629962007.b4-ty@arm.com>
References: <20250227035119.2025171-1-anshuman.khandual@arm.com>
 <174171335999.3659520.16613654046629962007.b4-ty@arm.com>
Message-ID: <ddeb3df1-995b-44f4-ad20-50edfb906a28@arm.com>



On 3/11/25 22:47, Catalin Marinas wrote:
> On Thu, 27 Feb 2025 09:21:19 +0530, Anshuman Khandual wrote:
>> FEAT_PMUv3p9 registers such as PMICNTR_EL0, PMICFILTR_EL0, and PMUACR_EL1
>> access from EL1 requires appropriate EL2 fine grained trap configuration
>> via FEAT_FGT2 based trap control registers HDFGRTR2_EL2 and HDFGWTR2_EL2.
>> Otherwise such register accesses will result in traps into EL2.
>>
>> Add a new helper __init_el2_fgt2() which initializes FEAT_FGT2 based fine
>> grained trap control registers HDFGRTR2_EL2 and HDFGWTR2_EL2 (setting the
>> bits nPMICNTR_EL0, nPMICFILTR_EL0 and nPMUACR_EL1) to enable access into
>> PMICNTR_EL0, PMICFILTR_EL0, and PMUACR_EL1 registers.
>>
>> [...]
> 
> Applied to arm64 (for-next/el2-enable-feat-pmuv3p9), thanks!
> 
> [1/1] arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
>       https://git.kernel.org/arm64/c/858c7bfcb35e
> 
> I removed Cc: stable since, if it gets backported automatically, it will
> miss the sysreg updates and break the build. Please send it to stable
> directly once it lands upstream, together with the dependencies.

Sure, will do that.


From andyshrk at 163.com  Tue Mar 11 20:51:58 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 11:51:58 +0800 (CST)
Subject: [PATCH 0/6] Add support for RK3588 DisplayPort Controller
In-Reply-To: <AD2A56F9-B4FB-406B-BE7C-49BB5DFD3BAD@gmail.com>
References: <25401bfa.291d.19564244e54.Coremail.andyshrk@163.com>
 <75189787-28E1-4FC2-8E10-4960B3877A6F@gmail.com>
 <28b0d3fc.bb3.19568f6b5f8.Coremail.andyshrk@163.com>
 <44213B17-FE14-4FB8-8319-1E31BBF6EAA0@gmail.com>
 <74c154b6.8c50.1956aa8c8d2.Coremail.andyshrk@163.com>
 <1573D5D6-AFED-4D92-8112-B0C6BB52D5FF@gmail.com>
 <46c0d239.a4f5.1956b619b97.Coremail.andyshrk@163.com>
 <252BB2E2-4BC5-4402-953D-F7B30EA5DE14@gmail.com>
 <326B91E9-FB91-43C3-B98B-3EF079F313C6@gmail.com>
 <545cc438.7e3.1956e13a3e2.Coremail.andyshrk@163.com>
 <AD2A56F9-B4FB-406B-BE7C-49BB5DFD3BAD@gmail.com>
Message-ID: <4003289a.41da.195887b0462.Coremail.andyshrk@163.com>


Hi Piotr,
? 2025-03-10 04:53:50?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 7 mar 2025, o godz. 01:48:
>> 
>> 
>> Hi Piotr,
>> ? 2025-03-06 22:28:08?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>>> 
>>> 
>> 
>> All dump information currently appears to be correct, so I'm temporarily unsure why
>> there is no display on the monitor.
>> Maybe try some plug and unplug for the DP cable, or try another cable or monitor?
>> 
>> It seems that this board uses a DP to HDMI converter? Does this transmitter need a driver?
>> 
>> I won't be at my computer over the next two or three days, so any further replies to your email
>> might have to wait until next week.
>> 
>> 
>
>Andy,
>FYI:
>
>I done test on mine rock5a with applied Naoki dp0 enablement in dts (and only in dts).
>No any changes in dw dp driver (so i?m on vanilla  https://patchwork.kernel.org/project/linux-rockchip/cover/20250223113036.74252-1-andyshrk at 163.com/   )
>
>on mine rock5a ra620 hdmi port works ok.
>(I contacted also Radxa about ra620 and they confirmed: ra620 is just DP->HDMI converter. No any driver nor special programming/enablement is needed)
>
>This tells me that dp0 (rock5a) works ok while dp1 (rock5itx) not.


>i suspect issue is probably in https://patchwork.kernel.org/project/linux-rockchip/cover/20250223113036.74252-1-andyshrk at 163.com/ and is related to dp1 handling?

With help from Stephen, we do some online debug, the DP1 display is  ok on his rock5itx board now?


Try the patch as bellow:

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index 75a03e6a875c..d9434310a141 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -329,7 +329,7 @@ struct dw_dp {
 
        struct dw_dp_link link;
        struct dw_dp_video video;
-       const struct dw_dp_plat_data *plat_data;
+       struct dw_dp_plat_data plat_data;


@@ -1998,7 +2012,7 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
        dp->dev = dev;
        dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
 
-       dp->plat_data = plat_data;
+       dp->plat_data.max_link_rate = plat_data->max_link_rate;
        bridge = &dp->bridge;
        mutex_init(&dp->irq_lock);
        INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
 


diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 17a98845fd31..2cf79a1409af 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -2089,9 +2089,9 @@ static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32
                dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags);
                break;
        case ROCKCHIP_VOP2_EP_DP1:
-               die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
-               die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
-                          FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
+               die &= ~RK3588_SYS_DSP_INFACE_EN_DP1_MUX;
+               die |= RK3588_SYS_DSP_INFACE_EN_DP1 |
+                          FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP1_MUX, vp->id);
                dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL;
                dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags);
                break;



>
>BTW: there seems to be issue with video modes handling on dp0 port: 
>-playing video 1920 at 1080@50 - ok
>-playing then video1920 at 1080@59,64 hangs board?.
>
>hdmi0 works ok. video modes issue is only on dp0
The dclk for vp2 is default from GPLL, it can't divde pixel clock for such a refresh rates, 
But it should not hang the board, Sebastian, it seems the frequence of  GPLL be changed?


Plesase try it like this: bond the dclk source for VP2 from V0PLL.

+&vop {
+	assigned-clocks = <&cru DCLK_VOP2_SRC>;
+	assigned-clock-parents = <&cru PLL_V0PLL>;
+	status = "okay";
+};
+
>
>

From wens at kernel.org  Tue Mar 11 21:03:54 2025
From: wens at kernel.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 12:03:54 +0800
Subject: [PATCH v4 00/14] clk: sunxi-ng: add A523 clock support
In-Reply-To: <20250307002628.10684-1-andre.przywara@arm.com>
References: <20250307002628.10684-1-andre.przywara@arm.com>
Message-ID: <174175218236.1911740.8731884904697217692.b4-ty@csie.org>

From: Chen-Yu Tsai <wens at csie.org>

On Fri, 07 Mar 2025 00:26:14 +0000, Andre Przywara wrote:
> this is the fourth drop of the series introducing basic clock support for
> the Allwinner A523 family of SoCs, comprising A523, A527, T527, H728. [1]
> This times just a small rename of a macro name, and fixing the DT
> binding, where the separate patches for the two CCUs got merged into
> one. For a more detailed changelog, see below.
> 
> *************
> Please note that the clock numbers changed compared to v1 and v2, (but
> not against v3) so DTs from that older era cannot be used anymore with
> this driver: you have to update the DTB. Just copying the binding header
> and recompiling the DTB should do the trick, since the symbols stayed
> mostly the same, at least as far they are used in the basic DTs we use
> today.
> *************
> 
> [...]

Re-applied to clk-for-6.15 in git at github.com:linux-sunxi/linux-sunxi.git
to add SoB, thanks! Please note the commit hashes have changed.

[01/14] clk: sunxi-ng: mp: introduce dual-divider clock
        commit: 45717804b75eda8a76eacc04509ca4d68dd2caaf
[02/14] clk: sunxi-ng: mp: provide wrappers for setting feature flags
        commit: cdbb9d0d09db4cd09d23fec02d3b458664bc3d38
[03/14] clk: sunxi-ng: Add support for update bit
        commit: e16b9b71f40f603d5cbdcf02007c05ee03cb2be7
[04/14] dt-bindings: clk: sunxi-ng: document two Allwinner A523 CCUs
        commit: 52dbf84857f051df38f6de3f0c7b7f4506e7ad25
[05/14] clk: sunxi-ng: Add support for the A523/T527 CCU PLLs
        commit: 7cae1e2b5544a6f51972458ec4360c7717ca0145
[06/14] clk: sunxi-ng: a523: Add support for bus clocks
        commit: e6f4b4b77981feb3af06e16da073e788fe16de2a
[07/14] clk: sunxi-ng: a523: add video mod clocks
        commit: 6702d17f54a8f6c48cd6ba12282fae8c936e7944
[08/14] clk: sunxi-ng: a523: add system mod clocks
        commit: 74b0443a0d0ad283f20ee2985758143485942c31
[09/14] clk: sunxi-ng: a523: add interface mod clocks
        commit: ed064e65b92a1d78d90b6b87a3d99790f88c1c83
[10/14] clk: sunxi-ng: a523: add USB mod clocks
        commit: fb2c60366d3259aeb5507902e50032fb05b11895
[11/14] clk: sunxi-ng: a523: remaining mod clocks
        commit: 00bc60ea24a7b31da97a3b8a833711491c285ae4
[12/14] clk: sunxi-ng: a523: add bus clock gates
        commit: f3dabb29f0ca44f2053c0c3943ca6f47b248d348
[13/14] clk: sunxi-ng: a523: add reset lines
        commit: a36cc6cd0feb7ea656a1a33db0e6347149f50fed
[14/14] clk: sunxi-ng: add support for the A523/T527 PRCM CCU
        commit: 8cea339cfb81eb3354b0f27ceb27e2bb107efa6d

Best regards,
-- 
Chen-Yu Tsai <wens at csie.org>


From hongxing.zhu at nxp.com  Tue Mar 11 21:05:30 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Wed, 12 Mar 2025 04:05:30 +0000
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250311155452.GA629749@bhelgaas>
References: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>
 <20250311155452.GA629749@bhelgaas>
Message-ID: <DU2PR04MB8677AC699DF11D847AB768708CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>

> -----Original Message-----
> From: Bjorn Helgaas <helgaas at kernel.org>
> Sent: 2025?3?11? 23:55
> To: Hongxing Zhu <hongxing.zhu at nxp.com>
> Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> hardcodes
> 
> On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > -----Original Message-----
> > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > Sent: 2025?3?10? 23:11
> > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> bhelgaas at google.com;
> > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > hardcodes
> > >
> > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > Use the domain number replace the hardcodes to uniquely identify
> > > > different controller on i.MX8MQ platforms. No function changes.
> > > >
> > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > ---
> > > >  drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > >  1 file changed, 6 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > index 90ace941090f..ab9ebb783593 100644
> > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > @@ -41,7 +41,6 @@
> > > >  #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > >  #define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > >  #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> 8)
> > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > >
> > > >  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > >  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > platform_device
> > > *pdev)
> > > >  	struct dw_pcie *pci;
> > > >  	struct imx_pcie *imx_pcie;
> > > >  	struct device_node *np;
> > > > -	struct resource *dbi_base;
> > > >  	struct device_node *node = dev->of_node;
> > > >  	int i, ret, req_cnt;
> > > >  	u16 val;
> > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > platform_device *pdev)
> > > >  			return PTR_ERR(imx_pcie->phy_base);
> > > >  	}
> > > >
> > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> 0,
> > > &dbi_base);
> > > > -	if (IS_ERR(pci->dbi_base))
> > > > -		return PTR_ERR(pci->dbi_base);
> > >
> > > This makes me wonder.
> > >
> > > IIUC this means that previously we set controller_id to 1 if the
> > > first item in devicetree "reg" was 0x33c00000, and now we will set
> > > controller_id to 1 if the devicetree "linux,pci-domain" property is 1.
> > > This is good, but I think this new dependency on the correct
> > > "linux,pci-domain" in devicetree should be mentioned in the commit log.
> > >
> > > My bigger worry is that we no longer set pci->dbi_base at all.  I
> > > see that the only use of pci->dbi_base in pci-imx6.c was to
> > > determine the controller_id, but this is a DWC-based driver, and the
> > > DWC core certainly uses
> > > pci->dbi_base.  Are we sure that none of those DWC core paths are
> > > important to pci-imx6.c?
> > Hi Bjorn:
> > Thanks for your concerns.
> > Don't worry about the assignment of pci->dbi_base.
> > If pci-imx6.c driver doesn't set it. DWC core driver would set it when
> >  dw_pcie_get_resources() is invoked.
> 
> Great, thanks!  Maybe we can amend the commit log to mention that and
> the new "linux,pci-domain" dependency.
How about the following updates of the commit log?

Use the domain number replace the hardcodes to uniquely identify
different controller on i.MX8MQ platforms. No function changes.
Please make sure the " linux,pci-domain" is set for i.MX8MQ correctly, since
 the controller id is relied on it totally.

Best Regards
Richard Zhu


From hongxing.zhu at nxp.com  Tue Mar 11 21:09:05 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Wed, 12 Mar 2025 04:09:05 +0000
Subject: [PATCH v1 1/2] arm64: dts: imx8mq: Add linux,pci-domain into
 pcie-ep node
In-Reply-To: <Z8JBL7/LoCRemdjH@lizhi-Precision-Tower-5810>
References: <20250226024256.1678103-1-hongxing.zhu@nxp.com>
 <20250226024256.1678103-2-hongxing.zhu@nxp.com>
 <Z8JBL7/LoCRemdjH@lizhi-Precision-Tower-5810>
Message-ID: <DU2PR04MB86776EF9E224096AF09C90BD8CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>

> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: 2025?3?1? 7:05
> To: Hongxing Zhu <hongxing.zhu at nxp.com>
> Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v1 1/2] arm64: dts: imx8mq: Add linux,pci-domain into
> pcie-ep node
> 
> On Wed, Feb 26, 2025 at 10:42:55AM +0800, Richard Zhu wrote:
> > Add linux,pci-domain into pcie-ep node of i.MX8MQ.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > ---
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> 
Hi Frank:
Thanks.

Hi Shawn:
Since the PCIe part is picked up by Krzysztof.
Can you help to pick up this dts changes for i.MX8MQ?
Thanks in advanced.

Best Regards
Richard Zhu
> >  arch/arm64/boot/dts/freescale/imx8mq.dtsi | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > index d51de8d899b2..387b3e227cfc 100644
> > --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > @@ -1828,6 +1828,7 @@ pcie1_ep: pcie-ep at 33c00000 {
> >  			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
> >  			interrupt-names = "dma";
> >  			fsl,max-link-speed = <2>;
> > +			linux,pci-domain = <1>;
> >  			clocks = <&clk IMX8MQ_CLK_PCIE2_ROOT>,
> >  				 <&clk IMX8MQ_CLK_PCIE2_PHY>,
> >  				 <&clk IMX8MQ_CLK_PCIE2_PHY>,
> > --
> > 2.37.1
> >

From wthai at nvidia.com  Tue Mar 11 21:58:02 2025
From: wthai at nvidia.com (Willie Thai)
Date: Wed, 12 Mar 2025 04:58:02 +0000
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
Message-ID: <20250312045802.4115029-1-wthai@nvidia.com>

The GB200NVL BMC is an Aspeed Ast2600 based BMC
for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].
Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Paul Menzel <pmenzel at molgen.mpg.de>
Link: Reference to Ast2600 SOC: https://www.aspeedtech.com/server_ast2600/ [1]
Link: Reference to Blackwell GB200NVL Platform: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes in v2:
  - Fix the SOB name [Krzysztof]
  - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
  - Fix DTS coding style [Krzysztof]
  - Move pinctrl override to the bottom [Krzysztof]
  - Drop bootargs [Krzysztof]
  - Follow DTS coding style and change naming for leds node [Krzysztof]
  - Change flash 0 status property [Krzysztof]
  - Change the phy-mode to rgmii [Andrew]
  - Remove the max-speed in mac0 [Andrew]
---
---
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1229 +++++++++++++++++
 2 files changed, 1230 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..20fd357a1ee9 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-bmc-lenovo-hr630.dtb \
 	aspeed-bmc-lenovo-hr855xg2.dtb \
 	aspeed-bmc-microsoft-olympus.dtb \
+	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
 	aspeed-bmc-opp-lanyang.dtb \
 	aspeed-bmc-opp-mowgli.dtb \
 	aspeed-bmc-opp-nicole.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
new file mode 100644
index 000000000000..eeec3704a43b
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
@@ -0,0 +1,1229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "AST2600 GB200NVL BMC";
+	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";
+
+	aliases {
+		serial2 = &uart3;
+		serial4 = &uart5;
+		i2c16   = &imux16;
+		i2c17   = &imux17;
+		i2c18   = &imux18;
+		i2c19   = &imux19;
+		i2c20   = &imux20;
+		i2c21   = &imux21;
+		i2c22   = &imux22;
+		i2c23   = &imux23;
+		i2c24   = &imux24;
+		i2c25   = &imux25;
+		i2c26   = &imux26;
+		i2c27   = &imux27;
+		i2c28   = &imux28;
+		i2c29   = &imux29;
+		i2c30   = &imux30;
+		i2c31   = &imux31;
+		i2c32   = &imux32;
+		i2c33   = &imux33;
+		i2c34   = &imux34;
+		i2c35   = &imux35;
+		i2c36   = &imux36;
+		i2c37   = &imux37;
+		i2c38   = &imux38;
+		i2c39   = &imux39;
+		i2c40	= &e1si2c0;
+		i2c41	= &e1si2c1;
+		i2c42	= &e1si2c2;
+		i2c43	= &e1si2c3;
+		i2c44	= &e1si2c4;
+		i2c45	= &e1si2c5;
+		i2c46	= &e1si2c6;
+		i2c47	= &e1si2c7;
+		i2c48	= &i2c17mux0;
+		i2c49	= &i2c17mux1;
+		i2c50	= &i2c17mux2;
+		i2c51	= &i2c17mux3;
+		i2c52	= &i2c25mux0;
+		i2c53	= &i2c25mux1;
+		i2c54	= &i2c25mux2;
+		i2c55	= &i2c25mux3;
+		i2c56	= &i2c29mux0;
+		i2c57	= &i2c29mux1;
+		i2c58	= &i2c29mux2;
+		i2c59	= &i2c29mux3;
+	};
+
+	chosen {
+		stdout-path = &uart5;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vga_memory: framebuffer at 9f000000 {
+			no-map;
+			reg = <0x9f000000 0x01000000>; /* 16M */
+		};
+
+		ramoops at a0000000 {
+			compatible = "ramoops";
+			reg = <0xa0000000 0x100000>; /* 1MB */
+			record-size = <0x10000>; /* 64KB */
+			max-reason = <2>; /* KMSG_DUMP_OOPS */
+		};
+
+		gfx_memory: framebuffer {
+			size = <0x01000000>;
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+
+		video_engine_memory: jpegbuffer {
+			size = <0x02000000>;	/* 32M */
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led-0{
+			label = "uid_led";
+			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
+		};
+		led-1{
+			label = "fault_led";
+			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
+		};
+		led-2{
+			label = "power_led";
+			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
+		};
+
+	};
+
+	buttons {
+		button-power {
+			label = "power-btn";
+			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
+		};
+		button-uid {
+			label = "uid-btn";
+			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+};
+
+// Enable Primary flash on FMC for bring up activity
+&fmc {
+	status = "okay";
+	flash at 0 {
+		status = "okay";
+		compatible = "jedec,spi-nor";
+		label = "bmc";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot at 0 {
+				// 896KB
+				reg = <0x0 0xe0000>;
+				label = "u-boot";
+			};
+
+			kernel at 100000 {
+				// 9MB
+				reg = <0x100000 0x900000>;
+				label = "kernel";
+			};
+
+			rofs at a00000 {
+				// 55292KB (extends to end of 64MB SPI - 4KB)
+				reg = <0xa00000 0x35FF000>;
+				label = "rofs";
+			};
+		};
+	};
+};
+
+&spi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi2_default>;
+
+	// Data SPI is 64MB in size
+	flash at 0 {
+		status = "okay";
+		label = "config";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot-env at 0 {
+				// 256KB
+				reg = <0x0 0x40000>;
+				label = "u-boot-env";
+			};
+
+			rwfs at 40000 {
+				// 16MB
+				reg = <0x40000 0x1000000>;
+				label = "rwfs";
+			};
+
+			log at 1040000 {
+				// 40MB
+				reg = <0x1040000 0x2800000>;
+				label = "log";
+			};
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart3 {
+	// Enabling SOL
+	status = "okay";
+};
+
+&uart5 {
+	// BMC Debug Console
+	status = "okay";
+};
+
+&uart_routing {
+	status = "okay";
+};
+
+// MAC1 (per schematics, 1-based MAC1-MAC4) of AST2600 connected to external PHY
+// This is "mac0" in zero-based DTS
+&mdio0 {
+	status = "okay";
+	ethphy0: ethernet-phy at 0 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+
+};
+
+&mdio3 {
+	status = "okay";
+	ethphy3: ethernet-phy at 2 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <2>;
+	};
+};
+
+&mac0 {
+	status = "okay";
+	pinctrl-names = "default";
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy3>;
+	pinctrl-0 = <&pinctrl_rgmii1_default>;
+};
+
+&mac2 {
+	status = "okay";
+	phy-mode = "rmii";
+	use-ncsi;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii3_default>;
+};
+
+// Enable emmc
+&emmc_controller {
+	status = "okay";
+};
+
+&emmc {
+	non-removable;
+	pinctrl-0 = <&pinctrl_emmcg5_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	clk-phase-mmc-hs200 = <9>, <225>;
+};
+
+/*
+ * Enable USB port A as device (via the virtual hub) to host
+ */
+&vhub {
+	status = "okay";
+	pinctrl-names = "default";
+	/*
+	 * Uncomment below line to enable internal EHCI controller
+	 * Current config uses xHCI Port1
+	 */
+};
+
+&video {
+	status = "okay";
+	memory-region = <&video_engine_memory>;
+};
+
+// USB 2.0 to HMC, on USB Port B
+&ehci1 {
+	status = "okay";
+};
+
+// USB 1.0
+&uhci {
+	status = "okay";
+};
+
+&sgpiom0 {
+	status="okay";
+	ngpios = <128>;
+
+	gpio-line-names =
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RUN_POWER_FAULT_L-I","SYS_RST_IN_L-O",
+		"RUN_POWER_PG-I","PWR_BRAKE_L-O",
+		"SYS_RST_OUT_L-I","RUN_POWER_EN-O",
+		"L0L1_RST_REQ_OUT_L-I","SHDN_FORCE_L-O",
+		"L2_RST_REQ_OUT_L-I","SHDN_REQ_L-O",
+		"SHDN_OK_L-I","UID_LED_N-O",
+		"BMC_I2C1_FPGA_ALERT_L-I","SYS_FAULT_LED_N-O",
+		"BMC_I2C0_FPGA_ALERT_L-I","PWR_LED_N-O",
+		"FPGA_RSVD_FFU3-I","",
+		"FPGA_RSVD_FFU2-I","",
+		"FPGA_RSVD_FFU1-I","",
+		"FPGA_RSVD_FFU0-I","BMC_I2C_SSIF_ALERT_L-O",
+		"CPU_BOOT_DONE-I","JTAG_MUX_SELECT-O",
+		"SPI_BMC_FPGA_INT_L-I","RTC_CLR_L-O",
+		"THERM_BB_WARN_L-I","UART_MUX_SEL-O",
+		"THERM_BB_OVERT_L-I","",
+		"CPU0_UPHY3_PRSNT1_L-I","IOBRD0_RUN_POWER_EN-O",
+		"CPU0_UPHY3_PRSNT0_L-I","IOBRD1_RUN_POWER_EN-O",
+		"CPU0_UPHY2_PRSNT1_L-I","FPGA_RSVD_FFU4-O",
+		"CPU0_UPHY2_PRSNT0_L-I","FPGA_RSVD_FFU5-O",
+		"CPU0_UPHY1_PRSNT1_L-I","FPGA_RSVD_FFU6-O",
+		"CPU0_UPHY1_PRSNT0_L-I","FPGA_RSVD_FFU7-O",
+		"CPU0_UPHY0_PRSNT1_L-I","RSVD_NV_PLT_DETECT-O",
+		"CPU0_UPHY0_PRSNT0_L-I","SPI1_INT_L-O",
+		"CPU1_UPHY3_PRSNT1_L-I","",
+		"CPU1_UPHY3_PRSNT0_L-I","HMC_EROT_MUX_STATUS",
+		"CPU1_UPHY2_PRSNT1_L-I","",
+		"CPU1_UPHY2_PRSNT0_L-I","",
+		"CPU1_UPHY1_PRSNT1_L-I","",
+		"CPU1_UPHY1_PRSNT0_L-I","",
+		"CPU1_UPHY0_PRSNT1_L-I","",
+		"CPU1_UPHY0_PRSNT0_L-I","",
+		"FAN1_PRESENT_L-I","",
+		"FAN0_PRESENT_L-I","",
+		"","",
+		"IPEX_CABLE_PRSNT_L-I","",
+		"M2_1_PRSNT_L-I","",
+		"M2_0_PRSNT_L-I","",
+		"CPU1_UPHY4_PRSNT1_L-I","",
+		"CPU0_UPHY4_PRSNT0_L-I","",
+		"","",
+		"I2C_RTC_ALERT_L-I","",
+		"FAN7_PRESENT_L-I","",
+		"FAN6_PRESENT_L-I","",
+		"FAN5_PRESENT_L-I","",
+		"FAN4_PRESENT_L-I","",
+		"FAN3_PRESENT_L-I","",
+		"FAN2_PRESENT_L-I","",
+		"IOBRD0_IOX_INT_L-I","",
+		"IOBRD1_PRSNT_L-I","",
+		"IOBRD0_PRSNT_L-I","",
+		"IOBRD1_PWR_GOOD-I","",
+		"IOBRD0_PWR_GOOD-I","",
+		"","",
+		"","",
+		"FAN_FAIL_IN_L-I","",
+		"","",
+		"","",
+		"","",
+		"PDB_CABLE_PRESENT_L-I","",
+		"","",
+		"CHASSIS_PWR_BRK_L-I","",
+		"","",
+		"IOBRD1_IOX_INT_L-I","",
+		"10GBE_SMBALRT_L-I","",
+		"PCIE_WAKE_L-I","",
+		"I2C_M21_ALERT_L-I","",
+		"I2C_M20_ALERT_L-I","",
+		"TRAY_FAST_SHDN_L-I","",
+		"UID_BTN_N-I","",
+		"PWR_BTN_L-I","",
+		"PSU_SMB_ALERT_L-I","",
+		"","",
+		"","",
+		"NODE_LOC_ID[0]-I","",
+		"NODE_LOC_ID[1]-I","",
+		"NODE_LOC_ID[2]-I","",
+		"NODE_LOC_ID[3]-I","",
+		"NODE_LOC_ID[4]-I","",
+		"NODE_LOC_ID[5]-I","",
+		"FAN10_PRESENT_L-I","",
+		"FAN9_PRESENT_L-I","",
+		"FAN8_PRESENT_L-I","",
+		"FPGA1_READY_HMC-I","",
+		"DP_HPD-I","",
+		"HMC_I2C3_FPGA_ALERT_L-I","",
+		"HMC_I2C2_FPGA_ALERT_L-I","",
+		"FPGA0_READY_HMC-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"LEAK_DETECT_ALERT_L-I","",
+		"MOD1_B2B_CABLE_PRESENT_L-I","",
+		"MOD1_CLINK_CABLE_PRESENT_L-I","",
+		"FAN11_PRESENT_L-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RSVD_SGPIO_IN_CRC[0]","RSVD_SGPIO_O_CRC[7]",
+		"RSVD_SGPIO_IN_CRC[1]","RSVD_SGPIO_O_CRC[6]",
+		"RSVD_SGPIO_IN_CRC[2]","RSVD_SGPIO_O_CRC[5]",
+		"RSVD_SGPIO_IN_CRC[3]","RSVD_SGPIO_O_CRC[4]",
+		"RSVD_SGPIO_IN_CRC[4]","RSVD_SGPIO_O_CRC[3]",
+		"RSVD_SGPIO_IN_CRC[5]","RSVD_SGPIO_O_CRC[2]",
+		"RSVD_SGPIO_IN_CRC[6]","RSVD_SGPIO_O_CRC[1]",
+		"RSVD_SGPIO_IN_CRC[7]","RSVD_SGPIO_O_CRC[0]";
+};
+
+// I2C1, SSIF IPMI interface
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	disable-master = <1>;
+	i2c-scl-clk-low-timeout-us = <32000>;
+	ssif-bmc at 10 {
+		compatible = "ssif-bmc";
+		reg = <0x10>;
+	};
+};
+
+// I2C2
+// BMC_I2C1_FPGA - Secondary FPGA
+// HMC EROT
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+};
+
+// I2C3
+// BMC_I2C0_FPGA - Primary FPGA
+// HMC FRU EEPROM
+&i2c2 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+};
+
+// I2C4
+&i2c3 {
+	status = "disabled";
+};
+
+// I2C5
+// RTC Driver
+// IO Expander
+&i2c4 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// Module 0, Expander @0x21
+	exp4: pca9555 at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"RTC_MUX_SEL-O",
+			"PCI_MUX_SEL-O",
+			"TPM_MUX_SEL-O",
+			"FAN_MUX-SEL-O",
+			"SGMII_MUX_SEL-O",
+			"DP_MUX_SEL-O",
+			"UPHY3_USB_SEL-O",
+			"NCSI_MUX_SEL-O",
+			"BMC_PHY_RST-O",
+			"RTC_CLR_L-O",
+			"BMC_12V_CTRL-O",
+			"PS_RUN_IO0_PG-I",
+			"",
+			"",
+			"",
+			"";
+	};
+};
+
+// I2C6
+// Module 0/1 I2C MUX x3
+&i2c5 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+
+	i2c-switch at 71 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+		i2c-mux-idle-disconnect;
+
+		imux16: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux17: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-switch at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c17mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c17mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c17mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c17mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux18: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux19: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-switch at 72 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x72>;
+		i2c-mux-idle-disconnect;
+
+		imux20: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux21: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			pca9555 at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				gpio-line-names =
+					"RST_CX_0_L-O",
+					"RST_CX_1_L-O",
+					"CX0_SSD0_PRSNT_L-I",
+					"CX1_SSD1_PRSNT_L-I",
+					"CX_BOOT_CMPLT_CX0-I",
+					"CX_BOOT_CMPLT_CX1-I",
+					"CX_TWARN_CX0_L-I",
+					"CX_TWARN_CX1_L-I",
+					"CX_OVT_SHDN_CX0-I",
+					"CX_OVT_SHDN_CX1-I",
+					"FNP_L_CX0-O",
+					"FNP_L_CX1-O",
+					"",
+					"MCU_GPIO-I",
+					"MCU_RST_N-O",
+					"MCU_RECOVERY_N-O";
+			};
+		};
+
+		imux22: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux23: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-switch at 73 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x73>;
+		i2c-mux-idle-disconnect;
+
+		imux24: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux25: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-switch at 70 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x70>;
+				i2c-mux-idle-disconnect;
+
+				i2c25mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c25mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c25mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c25mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux26: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux27: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-switch at 75 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		i2c-mux-idle-disconnect;
+
+		imux28: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux29: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-switch at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c29mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c29mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c29mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c29mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux30: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux31: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-switch at 76 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x76>;
+		i2c-mux-idle-disconnect;
+
+		imux32: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux33: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			pca9555 at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				gpio-line-names =
+					"SEC_RST_CX_0_L-O",
+					"SEC_RST_CX_1_L-O",
+					"SEC_CX0_SSD0_PRSNT_L-I",
+					"SEC_CX1_SSD1_PRSNT_L-I",
+					"SEC_CX_BOOT_CMPLT_CX0-I",
+					"SEC_CX_BOOT_CMPLT_CX1-I",
+					"SEC_CX_TWARN_CX0_L-I",
+					"SEC_CX_TWARN_CX1_L-I",
+					"SEC_CX_OVT_SHDN_CX0-I",
+					"SEC_CX_OVT_SHDN_CX1-I",
+					"SEC_FNP_L_CX0-O",
+					"SEC_FNP_L_CX1-O",
+					"",
+					"SEC_MCU_GPIO-I",
+					"SEC_MCU_RST_N-O",
+					"SEC_MCU_RECOVERY_N-O";
+				};
+		};
+
+		imux34: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux35: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-switch at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		imux36: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux37: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		imux38: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux39: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C7
+// Module 0/1 Leak Sensors
+// Module 0/1 Fan Controllers
+&i2c6 {
+	status = "okay";
+	clock-frequency = <400000>;
+	hsc at 12 {
+		compatible = "ti,lm5066i";
+		reg = <0x12>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+	hsc at 14 {
+		compatible = "ti,lm5066i";
+		reg = <0x14>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+	max31790 at 20 {
+		compatible = "maxim,max31790";
+		reg = <0x20>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	max31790 at 23 {
+		compatible = "maxim,max31790";
+		reg = <0x23>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	max31790 at 2c {
+		compatible = "maxim,max31790";
+		reg = <0x2c>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	max31790 at 2f {
+		compatible = "maxim,max31790";
+		reg = <0x2f>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+};
+
+// I2C9
+// M.2
+&i2c8 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+};
+
+// I2C10
+// HMC IO Expander
+// Module 0/1 IO Expanders
+&i2c9 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// Module 0, Expander @0x20
+	exp0: pca9555 at 20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+		"FPGA_THERM_OVERT_L-I",
+		"FPGA_READY_BMC-I",
+		"HMC_BMC_DETECT-O",
+		"HMC_PGOOD-O",
+		"",
+		"BMC_STBY_CYCLE-O",
+		"FPGA_EROT_FATAL_ERROR_L-I",
+		"WP_HW_EXT_CTRL_L-O",
+		"EROT_FPGA_RST_L-O",
+		"FPGA_EROT_RECOVERY_L-O",
+		"BMC_EROT_FPGA_SPI_MUX_SEL-O",
+		"USB_HUB_RESET_L-O",
+		"NCSI_CS1_SEL-O",
+		"SGPIO_EN_L-O",
+		"B2B_IOEXP_INT_L-I",
+		"I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// Module 1, Expander @0x21
+	exp1: pca9555 at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+		"SEC_FPGA_THERM_OVERT_L-I",
+		"SEC_FPGA_READY_BMC-I",
+		"",
+		"",
+		"",
+		"",
+		"SEC_FPGA_EROT_FATAL_ERROR_L-I",
+		"SEC_WP_HW_EXT_CTRL_L-O",
+		"SEC_EROT_FPGA_RST_L-O",
+		"SEC_FPGA_EROT_RECOVERY_L-O",
+		"SEC_BMC_EROT_FPGA_SPI_MUX_SEL-O",
+		"SEC_USB2_HUB_RST_L-O",
+		"",
+		"",
+		"",
+		"SEC_I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// HMC Expander @0x27
+	exp2: pca9555 at 27 {
+		compatible = "nxp,pca9555";
+		reg = <0x27>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+		"HMC_PRSNT_L-I",
+		"HMC_READY-I",
+		"HMC_EROT_FATAL_ERROR_L-I",
+		"I2C_MUX_SEL-O",
+		"HMC_EROT_SPI_MUX_SEL-O",
+		"HMC_EROT_RECOVERY_L-O",
+		"HMC_EROT_RST_L-O",
+		"GLOBAL_WP_HMC-O",
+		"FPGA_RST_L-O",
+		"USB2_HUB_RST-O",
+		"CPU_UART_MUX_SEL-O",
+		"",
+		"",
+		"",
+		"",
+		"";
+	};
+	// HMC Expander @0x74
+	exp3: pca9555 at 74 {
+		compatible = "nxp,pca9555";
+		reg = <0x74>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+		"IOB_PRSNT_L",
+		"IOB_DP_HPD",
+		"IOX_BMC_RESET",
+		"IOB_IOEXP_INT_L",
+		"IOB_UID_LED_L",
+		"IOB_UID_BTN_L",
+		"IOB_SYS_RST_BTN_L",
+		"IOB_PWR_LED_L",
+		"IOB_PWR_BTN_L",
+		"IOB_PHY_RST",
+		"CPLD_JTAG_MUX_SEL",
+		"",
+		"",
+		"",
+		"",
+		"";
+	};
+};
+
+// I2C11
+// BMC FRU EEPROM
+// BMC Temp Sensor
+&i2c10 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// BMC FRU EEPROM - 256 bytes
+	eeprom at 50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <8>;
+	};
+};
+
+// I2C12
+&i2c11 {
+	status = "disabled";
+};
+
+// I2C13
+&i2c12 {
+	status = "disabled";
+};
+
+// I2C14
+// Module 0 UPHY3 SMBus
+&i2c13 {
+	status = "disabled";
+};
+
+// I2C15
+// Module 1 UPHY3 SMBus
+&i2c14 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+
+	//E1.S drive slot 0-3
+	i2c-switch at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C16
+&i2c15 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+	i2c-scl-clk-low-timeout-us = <32000>;
+
+	//E1.S drive slot 4-7
+	i2c-switch at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c4: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c5: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c6: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c7: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+&rng {
+	status = "okay";
+};
+
+&gpio0 {
+	gpio-line-names =
+
+	/* gpio-line-names are the combination of <signal>-<I/O> , "" is
+	 *	the placeholder for the unused pins
+	 */
+
+	/* 208 (26*8) 3.3V GPIOs */
+
+	/*A0-A7*/ "", "", "", "", "", "", "", "",
+	/*B0-B7*/ "", "", "", "", "", "", "", "",
+	/*C0-C7*/ "SGPIO_I2C_MUX_SEL-O", "", "", "", "", "", "", "",
+	/*D0-D7*/ "", "", "", "UART1_MUX_SEL-O", "", "FPGA_PEX_RST_L-O", "", "",
+	/*E0-E7*/
+	"RTL8221_PHY_RST_L-O",
+	"RTL8211_PHY_INT_L-I",
+	"",
+	"UART3_MUX_SEL-O",
+	"", "", "",
+	"SGPIO_BMC_EN-O",
+	/*F0-F7*/ "", "", "", "", "", "", "", "",
+	/*G0-G7*/ "", "", "", "", "", "", "", "",
+	/*H0-H7*/ "", "", "", "", "", "", "", "",
+	/*I0-I7*/ "", "", "", "", "", "QSPI2_RST_L-O", "GLOBAL_WP_BMC-O", "BMC_DDR4_TEN-O",
+	/*J0-J7*/ "", "", "", "", "", "", "", "",
+	/*K0-K7*/ "", "", "", "", "", "", "", "",
+	/*L0-L7*/ "", "", "", "", "", "", "", "",
+	/*M0-M7*/
+	"PCIE_EP_RST_EN-O",
+	"BMC_FRU_WP-O",
+	"HMC_RESET_L-O",
+	"STBY_POWER_EN-O",
+	"STBY_POWER_PG-I",
+	"PCIE_EP_RST_L-O",
+	"", "",
+	/*N0-N7*/ "", "", "", "", "", "", "", "",
+	/*O0-O7*/ "", "", "", "", "", "", "", "",
+	/*P0-P7*/ "", "", "", "", "", "", "", "",
+	/*Q0-Q7*/ "", "", "", "", "", "", "", "",
+	/*R0-R7*/ "", "", "", "", "", "", "", "",
+	/*S0-S7*/ "", "", "", "", "", "", "", "",
+	/*T0-T7*/ "", "", "", "", "", "", "", "",
+	/*U0-U7*/ "", "", "", "", "", "", "", "",
+	/*V0-V7*/ "AP_EROT_REQ-O", "EROT_AP_GNT-I", "", "","PCB_TEMP_ALERT-I", "","", "",
+	/*W0-W7*/ "", "", "", "", "", "", "", "",
+	/*X0-X7*/ "", "", "TPM_MUX_SEL-O", "", "", "", "", "",
+	/*Y0-Y7*/ "", "", "", "EMMC_RST-O", "","", "", "",
+	/*Z0-Z7*/ "BMC_READY-O","", "", "", "", "", "", "";
+};
+
+&gpio1 {
+	/* 36 1.8V GPIOs */
+	gpio-line-names =
+	/*A0-A7*/ "", "", "", "", "", "", "", "",
+	/*B0-B7*/ "", "", "", "", "", "", "IO_EXPANDER_INT_L-I","",
+	/*C0-C7*/ "", "", "", "", "", "", "", "",
+	/*D0-D7*/ "", "", "", "", "", "", "SPI_HOST_TPM_RST_L-O", "SPI_BMC_FPGA_INT_L-I",
+	/*E0-E7*/ "", "", "", "", "", "", "", "";
+};
+
+// EMMC group that excludes WP pin
+&pinctrl {
+	pinctrl_emmcg5_default: emmcg5_default {
+		function = "EMMC";
+		groups = "EMMCG5";
+	};
+};
-- 
2.25.1



From senozhatsky at chromium.org  Tue Mar 11 22:19:02 2025
From: senozhatsky at chromium.org (Sergey Senozhatsky)
Date: Wed, 12 Mar 2025 14:19:02 +0900
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <32d951629ab18bcb2cb59b0c0baab65de915dbea.camel@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <CAKEwX=NfKrisQL-DBcNxBwK2ErK-u=MSzHNpETcuWWNBh9s9Bg@mail.gmail.com>
 <CAGsJ_4ysL1xV=902oNM3vBfianF6F_iqDgyck6DGzFrZCtOprw@mail.gmail.com>
 <dubgo2s3xafoitc2olyjqmkmroiowxbpbswefhdioaeupxoqs2@z3s4uuvojvyu>
 <CAGsJ_4wbgEGKDdUqa8Kpw952qiM_H5V-3X+BH6SboJMh8k2sRg@mail.gmail.com>
 <32d951629ab18bcb2cb59b0c0baab65de915dbea.camel@mediatek.com>
Message-ID: <y2jpx4xcl34xxrh76jms7wojyhvjvigto4phmdek2ewbcyq32f@2owu5ndtama7>

On (25/03/11 14:12), Qun-wei Lin (???) wrote:
> > > If compression kthread-s can run (have CPUs to be scheduled on).
> > > This looks a bit like a bottleneck.  Is there anything that
> > > guarantees forward progress?  Also, if compression kthreads
> > > constantly preempt kswapd, then it might not be worth it to
> > > have compression kthreads, I assume?
> >
> > Thanks for your critical insights, all of which are valuable.
> >
> > Qun-Wei is likely working on an Android case where the CPU is
> > relatively idle in many scenarios (though there are certainly cases
> > where all CPUs are busy), but free memory is quite limited.
> > We may soon see benefits for these types of use cases. I expect
> > Android might have the opportunity to adopt it before it's fully
> > ready upstream.
> >
> > If the workload keeps all CPUs busy, I suppose this async thread
> > won?t help, but at least we might find a way to mitigate regression.
> >
> > We likely need to collect more data on various scenarios?when
> > CPUs are relatively idle and when all CPUs are busy?and
> > determine the proper approach based on the data, which we
> > currently lack :-)

Right.  The scan/unmap can move very fast (a rabbit) while the
compressor can move rather slow (a tortoise.)  There is some
benefit in the fact that kswap does compression directly, I'd
presume.

Another thing to consider, perhaps, is that not every page is
necessarily required to go through the compressor queue and stay
there until the woken-up compressor finally picks it up just to
realize that the page is filled with 0xff (or any other pattern).
At least on the zram side such pages are not compressed and stored
as an 8-byte pattern in the zram meta table (w/o using any zsmalloc
memory.)

> > > If we have a pagefault and need to map a page that is still in
> > > the compression queue (not compressed and stored in zram yet, e.g.
> > > dut to scheduling latency + slow compression algorithm) then what
> > > happens?
> >
> > This is happening now even without the patch?  Right now we are
> > having 4 steps:
> > 1. add_to_swap: The folio is added to the swapcache.
> > 2. try_to_unmap: PTEs are converted to swap entries.
> > 3. pageout: The folio is written back.
> > 4. Swapcache is cleared.
> >
> > If a swap-in occurs between 2 and 4, doesn't that mean
> > we've already encountered the case where we hit
> > the swapcache for a folio undergoing compression?
> >
> > It seems we might have an opportunity to terminate
> > compression if the request is still in the queue and
> > compression hasn?t started for a folio yet? seems
> > quite difficult to do?
> 
> As Barry explained, these folios that are being compressed are in the
> swapcache. If a refault occurs during the compression process, its
> correctness is already guaranteed by the swap subsystem (similar to
> other asynchronous swap devices).

Right.  I just was thinking that now there is a wake_up between
scan/unmap and compress.  Not sure how much trouble this can make.

> Indeed, terminating a folio that is already in the queue waiting for
> compression is a challenging task. Will this require some modifications
> to the current architecture of swap subsystem?

Yeah, I'll leave it mm folks to decide :)


From rppt at kernel.org  Tue Mar 11 22:22:30 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Wed, 12 Mar 2025 07:22:30 +0200
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250311134126.xfjdq6sq7jtcotck@master>
References: <20250206132754.2596694-1-rppt@kernel.org>
 <20250206132754.2596694-3-rppt@kernel.org>
 <20250218155004.n53fcuj2lrl5rxll@master>
 <Z7WHL_Xqgoln9oLg@kernel.org>
 <20250223002229.xuk6xlp23zr72hkc@master>
 <20250310095124.pa7dwgqhxglqrfes@master>
 <Z8_Ju0p63GBCdSG9@kernel.org>
 <20250311134126.xfjdq6sq7jtcotck@master>
Message-ID: <Z9EaFhviaZHOqs8j@kernel.org>

On Tue, Mar 11, 2025 at 01:41:26PM +0000, Wei Yang wrote:
> On Tue, Mar 11, 2025 at 07:27:23AM +0200, Mike Rapoport wrote:
> >> >> 
> >> >
> >> >I took another look into this commit. There maybe a very corner case in which
> >> >will leave a reserved region with no nid set.
> >> >
> >> >memmap_init_reserved_pages()
> >> >    for_each_mem_region() {
> >> >        ...
> >> >	memblock_set_node(start, end, &memblock.reserved, nid);
> >> >    }
> >> >
> >> >We leverage the iteration here to set nid to all regions in memblock.reserved.
> >> >But memblock_set_node() may call memblock_double_array() to expand the array,
> >> >which may get a range before current start. So we would miss to set the
> >> >correct nid to the new reserved region.
> >> >
> >> >I have tried to create a case in memblock test. This would happen when there
> >> >are 126 memblock.reserved regions. And the last region is across the last two
> >> >node.
> >> >
> >> >One way to fix this is compare type->max in memblock_set_node(). Then check
> >> >this return value in memmap_init_reserved_pages(). If we found the size
> >> >changes, repeat the iteration.
> >> >
> >> >But this is a very trivial one, not sure it worth fix.
> >> >
> >> 
> >> Hi, Mike
> >> 
> >> I have done a user space test which shows we may have a chance to leave a
> >> region with non-nid set.
> >> 
> >> Not sure you are ok with my approach of fixing.
> >
> >Wouldn't it be better to check for a change in reserved.max in
> >memmap_init_reserved_pages()?
> > 
> 
> Sounds better.
> 
> Previously I thought we need to hide detail from user, but actually it is
> already in memblock.c :-)
> 
> If you agree, I would like to prepare a fix.

Sure :)
 
> >> -- 
> >> Wei Yang
> >> Help you, Help me

-- 
Sincerely yours,
Mike.


From hch at infradead.org  Tue Mar 11 22:59:54 2025
From: hch at infradead.org (Christoph Hellwig)
Date: Tue, 11 Mar 2025 22:59:54 -0700
Subject: [PATCH v2 2/2] block: change blk_mq_add_to_batch() third
 argument type to bool
In-Reply-To: <20250311104359.1767728-3-shinichiro.kawasaki@wdc.com>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
 <20250311104359.1767728-3-shinichiro.kawasaki@wdc.com>
Message-ID: <Z9Ei2t7z_7QbEWXW@infradead.org>

On Tue, Mar 11, 2025 at 07:43:59PM +0900, Shin'ichiro Kawasaki wrote:
>  /*
>   * Batched completions only work when there is no I/O error and no special
>   * ->end_io handler.
> + *
> + * @req: The request to add to batch
> + * @iob: The batch to add the request
> + * @is_error: Specify true if the request failed with an error
> + * @io_comp_batch: The completaion handler for the request
>   */

This needs more work to be a proper kerneldoc comment, i.e. start with
"/*8", mention the function name, etc.

The logic changes themselves look good.


From xxm at rock-chips.com  Tue Mar 11 23:20:16 2025
From: xxm at rock-chips.com (Simon Xue)
Date: Wed, 12 Mar 2025 14:20:16 +0800
Subject: [PATCH] iio: adc: rockchip: Fix clock initialization sequence
Message-ID: <20250312062016.137821-1-xxm@rock-chips.com>

clock_set_rate should be executed after devm_clk_get_enabled.

Fixes: 97ad10bb2901 ("iio: adc: rockchip_saradc: Make use of devm_clk_get_enabled")
Signed-off-by: Simon Xue <xxm at rock-chips.com>
---
 drivers/iio/adc/rockchip_saradc.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index a29e54754c8f..ab4de67fb135 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -480,15 +480,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
 	if (info->reset)
 		rockchip_saradc_reset_controller(info->reset);
 
-	/*
-	 * Use a default value for the converter clock.
-	 * This may become user-configurable in the future.
-	 */
-	ret = clk_set_rate(info->clk, info->data->clk_rate);
-	if (ret < 0)
-		return dev_err_probe(&pdev->dev, ret,
-				     "failed to set adc clk rate\n");
-
 	ret = regulator_enable(info->vref);
 	if (ret < 0)
 		return dev_err_probe(&pdev->dev, ret,
@@ -515,6 +506,14 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
 	if (IS_ERR(info->clk))
 		return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
 				     "failed to get adc clock\n");
+	/*
+	 * Use a default value for the converter clock.
+	 * This may become user-configurable in the future.
+	 */
+	ret = clk_set_rate(info->clk, info->data->clk_rate);
+	if (ret < 0)
+		return dev_err_probe(&pdev->dev, ret,
+				     "failed to set adc clk rate\n");
 
 	platform_set_drvdata(pdev, indio_dev);
 
-- 
2.34.1



From Axe.Yang at mediatek.com  Tue Mar 11 23:30:17 2025
From: Axe.Yang at mediatek.com (=?utf-8?B?QXhlIFlhbmcgKOadqOejiik=?=)
Date: Wed, 12 Mar 2025 06:30:17 +0000
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <b09f618a-eaf9-4258-ae2d-67eff1cb249f@collabora.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
	 <20250306085028.5024-2-axe.yang@mediatek.com>
	 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
	 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
	 <b09f618a-eaf9-4258-ae2d-67eff1cb249f@collabora.com>
Message-ID: <f8ce830d831aaba0d2748d31f8ba4a9915b7a14e.camel@mediatek.com>

On Tue, 2025-03-11 at 10:47 +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 07/03/25 07:59, Axe Yang (??) ha scritto:
> > On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
> > > > Add 'mediatek,disable-single-burst' setting. This property can
> > > > be
> > > > used to switch bus burst type, from single burst to INCR, which
> > > > is
> > > > determined by the bus type within the IP. Some versions of the
> > > > IP
> > > > are using AXI bus, thus this switch is necessary as 'single' is
> > > > not
> > > > the burst type supported by the bus.
> > > > 
> > > > Signed-off-by: Axe Yang <axe.yang at mediatek.com>
> > > 
> > > I am mostly sure that this is not something to put in devicetree,
> > > but
> > > as
> > > platform data for specific SoC(s), as much as I'm mostly sure
> > > that
> > > all of
> > > the instances of the MSDC IP in one SoC will be *all* using
> > > either
> > > single
> > > or INCR.
> > 
> > No, actually MSDC IPs in one SoC are using different versions.
> > Usually MSDC1 (index from 1) is used as eMMC host, the left hosts
> > are
> > used as SD/SDIO hosts. They have similar designs, but there are
> > still
> > difference.
> > 
> > > 
> > > So, I think I know the answer but I'll still ask just to be
> > > extremely
> > > sure:
> > > 
> > > is there any MediaTek SoC that has different IP versions for
> > > different MSDC
> > > instances, and that hence require single burst on one instance
> > > and
> > > INCR on
> > > another instance?
> > 
> > Yes. Actually every SoC has different IP versions for eMMC and
> > SD/SDIO
> > host as I said.
> > e.g. For MT8168, signel burst bit should be set to 1 for eMMC Host,
> > but
> > 0 for SD/SDIO Host.
> > 
> > > 
> > > And if there is - is there a pattern? Is it always SDIO requiring
> > > INCR or
> > > always eMMC/SD requiring it?
> > > 
> > > 
> > 
> > No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
> > configured base on IP version. There is no binding relationship
> > between
> > eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
> > single, same as SD/SDIO.
> > 
> 
> Okay but if there are different IP versions, and AXI/AHB is
> determined
> by the IP version, why aren't you parsing the MAIN_VER/ECO_VER
> registers of
> the MSDC IP to check whether to use INCR or SINGLE?


To address your concerns, I had further discussions with the designer.
Their response was that the bus type and IP version are not bound
together. This contradicts my previous statements, and I apologize for
that.
According to the designer's feedback, I must say that the single burst
setting is indeed tied to the IC, but the granularity is such that it
needs to be set individually for each host.
Given the large number of ICs Mediatek currently has, adding burst type
information for each host to the driver's compatible structure would
mean adding hundreds(maybe thousands :() of lines to the driver for the
compatible structures for *all previous SoCs* (currently there are only
13 compatible structures, and they can be reuse by new SoC). This
approach seems very cumbersome.

So I still believe that placing this setting in the DTS is a more
appropriate approach.

Regards,
Axe

> 
> Cheers,
> Angelo
> 
> > 
> > Regards,
> > Axe
> > 
> > 
> > > 
> > > > ---
> > > >    Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8
> > > > ++++++++
> > > >    1 file changed, 8 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > index 0debccbd6519..6076aff0a689 100644
> > > > --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > @@ -100,6 +100,14 @@ properties:
> > > >        minimum: 0
> > > >        maximum: 0xffffffff
> > > > 
> > > > +  mediatek,disable-single-burst:
> > > > +    $ref: /schemas/types.yaml#/definitions/flag
> > > > +    description:
> > > > +      Burst type setting. For some versions of the IP that do
> > > > not
> > > > use
> > > > +      AHB bus, the burst type need to be switched to INCR.
> > > > +      If present, use INCR burst type.
> > > > +      If not present, use single burst type.
> > > > +
> > > >      mediatek,hs200-cmd-int-delay:
> > > >        $ref: /schemas/types.yaml#/definitions/uint32
> > > >        description:
> > > 
> > > 
> > > 
> 
> 

From ankur.a.arora at oracle.com  Tue Mar 11 23:34:55 2025
From: ankur.a.arora at oracle.com (Ankur Arora)
Date: Tue, 11 Mar 2025 23:34:55 -0700
Subject: [PATCH 1/4] asm-generic: barrier: Add
 smp_cond_load_relaxed_timewait()
In-Reply-To: <CAP01T76TWAPz4fXh6EoqHLCAxtgbzyvZib72QeFoTSx-0WKPtQ@mail.gmail.com>
References: <20250203214911.898276-1-ankur.a.arora@oracle.com>
 <20250203214911.898276-2-ankur.a.arora@oracle.com>
 <Z8dRalfxYcJIcLGj@arm.com> <87pliusihc.fsf@oracle.com>
 <CAP01T76TWAPz4fXh6EoqHLCAxtgbzyvZib72QeFoTSx-0WKPtQ@mail.gmail.com>
Message-ID: <87o6y6kb8w.fsf@oracle.com>


Kumar Kartikeya Dwivedi <memxor at gmail.com> writes:

> On Thu, 6 Mar 2025 at 08:53, Ankur Arora <ankur.a.arora at oracle.com> wrote:
>>
>>
>> Catalin Marinas <catalin.marinas at arm.com> writes:
>>
>> > On Mon, Feb 03, 2025 at 01:49:08PM -0800, Ankur Arora wrote:
>> >> Add smp_cond_load_relaxed_timewait(), a timed variant of
>> >> smp_cond_load_relaxed(). This is useful for cases where we want to
>> >> wait on a conditional variable but don't want to wait indefinitely.
>> >
>> > Bikeshedding: why not "timeout" rather than "timewait"?
>>
>> Well my reasons, such as they are, also involved a fair amount of bikeshedding:
>>
>>  - timewait and spinwait have same length names which just minimized all
>>    the indentation issues.
>>  - timeout seems to suggest a timing mechanism of some kind.
>
> I would also be in favor of timewait naming, since this is not a
> generic timeout primitive, the alternative naming is useful to
> distinguish it.
> The wait can be off by 100us or so for arm64 when we need to break out
> but that's tolerable for some cases.
> I've also taken a copy of the thing in [0] so it can begin using the
> in-tree implementation once it's merged.

Sounds good. I'll keep the timewait naming for the next version.
I'm on vacation until the 23rd so will send it out the week after.

Current plan is to address Catalin's comments and make sure that
any fuzziness around the timeout is visible to the caller.

Ankur

>   [0]: https://lore.kernel.org/bpf/20250303152305.3195648-9-memxor at gmail.com
>
>>
>> [...]


--
ankur


From YeoReum.Yun at arm.com  Tue Mar 11 23:36:29 2025
From: YeoReum.Yun at arm.com (Yeo Reum Yun)
Date: Wed, 12 Mar 2025 06:36:29 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <20250109171956.3535294-1-yeoreum.yun@arm.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
Message-ID: <PA6PR08MB1052667843120D0736A4B574AFBD02@PA6PR08MB10526.eurprd08.prod.outlook.com>

Gentle ping in case of forgotten,..

________________________________________
From: Yeoreum Yun <yeoreum.yun at arm.com>
Sent: 09 January 2025 17:19
To: Suzuki Poulose; mike.leach at linaro.org; james.clark at linaro.org; alexander.shishkin at linux.intel.com
Cc: coresight at lists.linaro.org; linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org; Yeo Reum Yun
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while enabling the config

While enable active config via cscfg_csdev_enable_active_config(),
active config could be deactivated via configfs' sysfs interface.
This could make UAF issue in below scenario:

CPU0                                          CPU1
(sysfs enable)                                load module
                                              cscfg_load_config_sets()
                                              activate config. // sysfs
                                              (sys_active_cnt == 1)
...
cscfg_csdev_enable_active_config()
  lock(csdev->cscfg_csdev_lock)
  // here load config activate by CPU1
  unlock(csdev->cscfg_csdev_lock)

                                              deactivate config // sysfs
                                              (sys_activec_cnt == 0)
                                              cscfg_unload_config_sets()
                                              unload module

  // access to config_desc which freed
  // while unloading module.
  cfs_csdev_enable_config

To address this, use cscfg_config_desc's active_cnt as a reference count
which will be holded when
    - activate the config.
    - enable the activated config.
and put the module reference when config_active_cnt == 0.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
from v2 to v3:
    - add cscfg_config_desc_get()/put() (from Suzuki).
    - remove sys_enable_cnt.

from v1 to v2:
    - modify commit message.
---
 .../hwtracing/coresight/coresight-config.h    |  2 +-
 .../coresight/coresight-etm4x-core.c          |  3 +
 .../hwtracing/coresight/coresight-syscfg.c    | 55 ++++++++++++++-----
 3 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index b9ebc9fcfb7f..90fd937d3bd8 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
  * @feats_csdev:references to the device features to enable.
  */
 struct cscfg_config_csdev {
-       const struct cscfg_config_desc *config_desc;
+       struct cscfg_config_desc *config_desc;
        struct coresight_device *csdev;
        bool enabled;
        struct list_head node;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 86893115df17..6218ef40acbc 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -986,6 +986,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
        smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);

        raw_spin_unlock(&drvdata->spinlock);
+
+       cscfg_csdev_disable_active_config(csdev);
+
        cpus_read_unlock();

        /*
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index a70c1454b410..8766f72db33e 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -391,14 +391,17 @@ static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info)
 static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner)
 {
        struct cscfg_config_csdev *config_csdev, *tmp;
+       unsigned long flags;

        if (list_empty(&csdev->config_csdev_list))
                return;

+       raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
        list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
                if (config_csdev->config_desc->load_owner == load_owner)
                        list_del(&config_csdev->node);
        }
+       raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 }

 static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
@@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);

+static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
+{
+       if (enable)
+               return atomic_inc_not_zero(&config_desc->active_cnt);
+
+       /* when activate config */
+
+       /* must ensure that config cannot be unloaded in use */
+       if (cscfg_owner_get(config_desc->load_owner))
+               return false;
+
+       atomic_inc(&config_desc->active_cnt);
+
+       return true;
+}
+
+static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
+{
+       if (!atomic_dec_return(&config_desc->active_cnt))
+               cscfg_owner_put(config_desc->load_owner);
+}
+
 /*
  * This activate configuration for either perf or sysfs. Perf can have multiple
  * active configs, selected per event, sysfs is limited to one.
@@ -890,22 +915,17 @@ static int _cscfg_activate_config(unsigned long cfg_hash)
                        if (config_desc->available == false)
                                return -EBUSY;

-                       /* must ensure that config cannot be unloaded in use */
-                       err = cscfg_owner_get(config_desc->load_owner);
-                       if (err)
+                       if (!cscfg_config_desc_get(config_desc, false)) {
+                               err = -EINVAL;
                                break;
+                       }
+
                        /*
                         * increment the global active count - control changes to
                         * active configurations
                         */
                        atomic_inc(&cscfg_mgr->sys_active_cnt);

-                       /*
-                        * mark the descriptor as active so enable config on a
-                        * device instance will use it
-                        */
-                       atomic_inc(&config_desc->active_cnt);
-
                        err = 0;
                        dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
                        break;
@@ -920,9 +940,8 @@ static void _cscfg_deactivate_config(unsigned long cfg_hash)

        list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
                if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
-                       atomic_dec(&config_desc->active_cnt);
                        atomic_dec(&cscfg_mgr->sys_active_cnt);
-                       cscfg_owner_put(config_desc->load_owner);
+                       cscfg_config_desc_put(config_desc);
                        dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
                        break;
                }
@@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
                                     unsigned long cfg_hash, int preset)
 {
        struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
-       const struct cscfg_config_desc *config_desc;
+       struct cscfg_config_desc *config_desc;
        unsigned long flags;
        int err = 0;

@@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
        raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
        list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
                config_desc = config_csdev_item->config_desc;
-               if ((atomic_read(&config_desc->active_cnt)) &&
-                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
+               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
+                               cscfg_config_desc_get(config_desc, true)) {
                        config_csdev_active = config_csdev_item;
                        csdev->active_cscfg_ctxt = (void *)config_csdev_active;
                        break;
@@ -1097,7 +1116,11 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
                                err = -EBUSY;
                        raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
                }
+
+               if (err)
+                       cscfg_config_desc_put(config_desc);
        }
+
        return err;
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
@@ -1136,8 +1159,10 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
        raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);

        /* true if there was an enabled active config */
-       if (config_csdev)
+       if (config_csdev) {
                cscfg_csdev_disable_config(config_csdev);
+               cscfg_config_desc_put(config_csdev->config_desc);
+       }
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);

--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From andyshrk at 163.com  Tue Mar 11 23:42:10 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 14:42:10 +0800
Subject: [PATCH] drm/rockchip: vop2: Fix interface enable/mux setting of DP1 on rk3588
Message-ID: <20250312064218.524143-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

This is a copy-paste error, which affects DP1 usage.

Fixes: 328e6885996c ("drm/rockchip: vop2: Add platform specific callback")
Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index a8b1ebfc5af5..de2da4f4e434 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -1753,9 +1753,9 @@ static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32
 		dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags);
 		break;
 	case ROCKCHIP_VOP2_EP_DP1:
-		die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
-		die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
-			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
+		die &= ~RK3588_SYS_DSP_INFACE_EN_DP1_MUX;
+		die |= RK3588_SYS_DSP_INFACE_EN_DP1 |
+			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP1_MUX, vp->id);
 		dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL;
 		dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags);
 		break;
-- 
2.34.1



From YeoReum.Yun at arm.com  Tue Mar 11 23:45:41 2025
From: YeoReum.Yun at arm.com (Yeo Reum Yun)
Date: Wed, 12 Mar 2025 06:45:41 +0000
Subject: [PATCH 1/4] coresight/etm4x: disallow altering config via sysfs
 while enabled
In-Reply-To: <GV1PR08MB105212E5552EB50968383C6D6FB132@GV1PR08MB10521.eurprd08.prod.outlook.com>
References: <20241221165934.1161856-1-yeoreum.yun@arm.com>
 <20241221165934.1161856-2-yeoreum.yun@arm.com>
 <6bbc9b64-3ecb-46c3-8c4e-55dba6301ef3@arm.com>
 <Z3+6kL7OGDX/pNul@e129823.arm.com>
 <4f9d2bed-7ce0-429e-83cc-ad6cbcc6085e@arm.com>
 <Z4AJ0kc0DxVwhLlu@e129823.arm.com>
 <GV1PR08MB105212E5552EB50968383C6D6FB132@GV1PR08MB10521.eurprd08.prod.outlook.com>
Message-ID: <PA6PR08MB105264F47A8399568DA2D3344FBD02@PA6PR08MB10526.eurprd08.prod.outlook.com>

Gentle ping in case of forgotten.

________________________________________
From: Yeo Reum Yun <YeoReum.Yun at arm.com>
Sent: 09 January 2025 17:48
To: Suzuki Poulose
Cc: mike.leach at linaro.org; james.clark at linaro.org; alexander.shishkin at linux.intel.com; coresight at lists.linaro.org; linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
Subject: Re: [PATCH 1/4] coresight/etm4x: disallow altering config via sysfs while enabled

> > On 09/01/2025 12:01, Yeoreum Yun wrote:
> > > Hi Suzuki,
> > >
> > > > Is it not better to have separate "configs" for perf and sysfs ?
> > > > And etmX driver can populate the "running" config, based on the
> > > > mode specific config. That way, the configs can be updated
> > > > independently without affecting the running config or the perf one.
> > > >
> > >
> > > That was i've tried but I've accepted Mike's opinion that
> > > it's enough to check whether CS_MODE_DISABLED via coresight_get_mode()
> > > in *_store().
> > >
> > > "the .._store functions in sysfs should use coresight_get_mode() to ensure
> > > this is set to CS_MODE_DISABLED before altering the config,
> > > which ensures that the trace system is inactive.
> > > We don't' really care about reading the config if trace is running."
> >
> > There are two issues with that :
> >
> > 1. Sprinkling the get_mode call in each sysfs stor function doesn't look
> > good to me.
> >
> > 2. Someone preparing for a sysfs session must not be prevented from doing so
> > just because there is a perf session running.
> >
> >
> > Suzuki
> >
>
> But, when separate the config, it doesn't show anymore the current
> configuration set by perf.
> I'm not sure this is okay.
> IMHO, If perf is enabled, since the configuration show the "perf",
> I think prohabit to modify config via sysfs while PERF_ENABLE seems valid.
>
> and about lossing session, I think this is up to user.
> That means to use sysfs, user shouldn't use perf to prevent loss
> its configuration.
>
> Am I missing something?
>
> Thanks

And one more question.
When CS_SYSFS_ENABLE,  Is it valid to allow modification of "config"?
I think It seems valid to show the "current working configration".
If It allows to modificaiton the config value showed via sysfs and current applied be different.

So, IMHO, It seems to valid to modify "config" only in CS_DISABLED.

Am I missing something?

Thanks.





From heiko at sntech.de  Tue Mar 11 23:55:25 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 07:55:25 +0100
Subject: [GIT PULL] Rockchip dts64 changes for 6.15 #1
In-Reply-To: <13791512.uLZWGnKmhe@phil>
References: <13791512.uLZWGnKmhe@phil>
Message-ID: <3339830.aeNJFYEL58@phil>

Hi,

Am Samstag, 8. M?rz 2025, 19:21:59 MEZ schrieb Heiko Stuebner:
> Hi soc maintainers,
> 
> please find below and in a subsequent pull-requests
> Rockchip changes for for 6.15 .
> 
> It looks like the new year caused a flurry of activity, because
> I don't remember having this much changes :-) .

as a note, one Rockchip dts patch has slipped into the scsi tree,
and is causing an (easy to resolve) merge conflict.

So this should not cause an issue, but should probably be mentioned
in the 6.15 merge window soc PR.

See
https://lore.kernel.org/lkml/20250312085101.58cdd1e5 at canb.auug.org.au/


Heiko

> 
> Again, there haven't been arm32 changes this time around (so far)
> 
> 
> Please pull.
> Thanks
> Heiko
> 
> 
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.15-rockchip-dts64-1
> 
> for you to fetch changes up to ba82f56bbf20e4166c988621cd0507509872848e:
> 
>   arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D (2025-03-08 18:19:59 +0100)
> 
> ----------------------------------------------------------------
> New boards: MNT-Reform2 laptop (rk3588), OrangePi5-Ultra (rk3588),
> Radxa Rock 4D (rk3576), Firefly ROC-RK3576-PC, Photonicat (rk3568)
> 
> New overlays: Video-adapters for Theobroma boards and one adapter used
> in hw test scenarios.
> 
> Interesting bigger changes contain clock support for rk3528; support for
> the hdmi1 controller as well as hdmi-audio support on both controllers on
> rk3588; the hdmi-receiver of the rk3588 landed, and rk3576 got basic
> graphics support and can now do hdmi output.
> 
> Another big block is that we're now doing overlays way better and are
> including build-testing for applied overlays to the base dtb - similar
> to how other arches already do this.
> 
> Of cours a big list of more controllers for rk3576 (nvmem, sfc), rk3588
> (rng, spdif, regulator for gpu power-domain) and rk3528 (saradc, pinctrl)
> 
> And a huge number of board-level improvements and additions.
> 
> ----------------------------------------------------------------
> Alexey Charkov (5):
>       arm64: dts: rockchip: Add finer-grained PWM states for the fan on Rock 5C
>       arm64: dts: rockchip: Enable automatic fan control on Radxa Rock 5C
>       arm64: dts: rockchip: switch Rock 5C to PMIC-based TSHUT reset
>       arm64: dts: rockchip: Add SPDIF nodes to RK3588(s) device trees
>       arm64: dts: rockchip: Enable SPDIF output on H96 Max V58
> 
> Andy Yan (5):
>       arm64: dts: rockchip: Enable USB3 OTG on rk3588s Cool Pi 4B
>       arm64: dts: rockchip: Add vop for rk3576
>       arm64: dts: rockchip: Add hdmi for rk3576
>       arm64: dts: rockchip: Enable hdmi display on sige5
>       arm64: dts: rockchip: Enable hdmi out display for rk3576-evb-v10
> 
> Chris Morgan (1):
>       arm64: dts: rockchip: remove rk3588 optee node
> 
> Chukun Pan (3):
>       dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
>       arm64: dts: rockchip: Add rk3528 QoS register node
>       arm64: dts: rockchip: enable SCMI clk for RK3528 SoC
> 
> Cristian Ciocaltea (8):
>       arm64: dts: rockchip: Enable HDMI0 PHY clk provider on RK3588
>       arm64: dts: rockchip: Add HDMI0 PHY PLL clock source to VOP2 on RK3588
>       arm64: dts: rockchip: Add PHY node for HDMI1 TX port on RK3588
>       arm64: dts: rockchip: Add HDMI1 node on RK3588
>       arm64: dts: rockchip: Enable HDMI1 on rock-5b
>       arm64: dts: rockchip: Enable HDMI1 PHY clk provider on RK3588
>       arm64: dts: rockchip: Add HDMI1 PHY PLL clock source to VOP2 on RK3588
>       arm64: dts: rockchip: Enable HDMI1 on rk3588-evb1
> 
> Damon Ding (1):
>       arm64: dts: rockchip: Fix label name of hdptxphy for RK3588
> 
> Detlev Casanova (6):
>       dt-bindings: arm: rockchip: Add Radxa ROCK 4D board
>       arm64: dts: rockchip: Add HDMI audio outputs for rk3588
>       arm64: dts: rockchip: Enable HDMI audio outputs for Rock 5B
>       arm64: dts: rockchip: Add HDMI support for rock-4d
>       arm64: dts: rockchip: Add SFC nodes for rk3576
>       arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D
> 
> Diederik de Haas (1):
>       arm64: dts: rockchip: add 'chassis-type' property on PineNote
> 
> Dragan Simic (3):
>       arm64: dts: rockchip: Describe why is HWRNG disabled in RK356x base dtsi
>       arm64: dts: rockchip: Use "dma-noncoherent" in base RK3588 SoC dtsi
>       arm64: dts: rockchip: linewrap gmac assigned-clocks on Quartz64 Model A/B files a bit
> 
> FUKAUMI Naoki (1):
>       arm64: dts: rockchip: Enable USB OTG for Radxa ROCK Pi E
> 
> Heiko Stuebner (5):
>       dt-bindings: arm: rockchip: Add Firefly ROC-RK3576-PC binding
>       arm64: dts: rockchip: Add devicetree for the ROC-RK3576-PC
>       arm64: dts: rockchip: add rk3576 otp node
>       Merge branch 'v6.15-shared/clkids' into v6.15-armsoc/dts64
>       arm64: dts: rockchip: add usb typec host support to rk3588-jaguar
> 
> Jagan Teki (1):
>       arm64: dts: rockchip: Enable HDMI1 out for Edgeble-6TOPS Modules
> 
> Jianfeng Liu (2):
>       arm64: dts: rockchip: Enable HDMI on armsom-sige7
>       arm64: dts: rockchip: add hdmi1 support to ROCK 5 ITX
> 
> Jimmy Hon (6):
>       arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Max
>       arm64: dts: rockchip: Adapt to differences between Orange Pi 5 Max and Ultra
>       dt-bindings: arm: rockchip: Add Xunlong Orange Pi 5 Ultra
>       arm64: dts: rockchip: Add Orange Pi 5 Ultra board
>       arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Ultra
>       arm64: dts: rockchip: Enable HDMI1 audio output for Orange Pi 5 Ultra
> 
> Jonas Karlman (7):
>       dt-bindings: soc: rockchip: Add RK3528 ioc grf syscon
>       arm64: dts: rockchip: Add pinctrl and gpio nodes for RK3528
>       arm64: dts: rockchip: Add uart0 pinctrl to Radxa E20C
>       arm64: dts: rockchip: Add leds node to Radxa E20C
>       arm64: dts: rockchip: Add user button to Radxa E20C
>       arm64: dts: rockchip: Add SARADC node for RK3528
>       arm64: dts: rockchip: Add maskrom button to Radxa E20C
> 
> Junhao Xie (3):
>       dt-bindings: vendor-prefixes: Add prefix for Ariaboard
>       dt-bindings: arm: rockchip: Add Ariaboard Photonicat RK3568
>       arm64: dts: rockchip: add dts for Ariaboard Photonicat RK3568
> 
> Kever Yang (1):
>       dt-bindings: vendor-prefixes: Update rockchip company name
> 
> Krzysztof Kozlowski (2):
>       arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3399 ROC PC PLUS
>       arm64: dts: rockchip: Add ES8388 audio codec fallback on RK3588 boards
> 
> Nicolas Frattaroli (1):
>       arm64: dts: rockchip: Add rng node to RK3588
> 
> Patrick Wildt (2):
>       dt-bindings: arm: rockchip: Add MNT Reform 2 (RCORE)
>       arm64: dts: rockchip: add MNT Reform 2 laptop
> 
> Quentin Schulz (17):
>       arm64: dts: rockchip: add support for sound output over HDMI on RK3399 Puma Haikou
>       arm64: dts: rockchip: add overlay test for WolfVision PF5
>       arm64: dts: rockchip: add overlay test for Edgeble NCM6A/NCM6B
>       arm64: dts: rockchip: add overlay tests for Rock 5B PCIe overlays
>       arm64: dts: rockchip: minimal support for Pre-ICT tester adapter for RK3588 Jaguar
>       arm64: dts: rockchip: add support for HAIKOU-LVDS-9904379 adapter for PX30 Ringneck
>       arm64: dts: rockchip: add overlay for PX30 Ringneck Haikou Video Demo adapter
>       arm64: dts: rockchip: add overlay for RK3399 Puma Haikou Video Demo adapter
>       arm64: dts: rockchip: enable UART5 on RK3588 Tiger Haikou
>       arm64: dts: rockchip: move DDC bus from Haikou carrierboard to RK3399 Puma DTSI
>       arm64: dts: rockchip: move I2C6 from Haikou carrierboard to Puma DTSI
>       arm64: dts: rockchip: disable I2C6 on Puma DTSI
>       arm64: dts: rockchip: enable I2S0 in Haikou carrierboard, not Puma DTSI
>       arm64: dts: rockchip: add EEPROM found on RK3399 Puma Haikou
>       arm64: dts: rockchip: enable Ethernet in Haikou carrierboard, not Puma DTSI
>       arm64: dts: rockchip: enable I2C3 in Haikou carrierboard, not Ringneck DTSI
>       arm64: dts: rockchip: disable I2C2 bus by default on RK3588 Tiger
> 
> Sebastian Reichel (2):
>       arm64: dts: rockchip: Add GPU power domain regulator dependency for RK3588
>       arm64: dts: rockchip: Enable HDMI receiver on rock-5b
> 
> Shreeya Patel (1):
>       arm64: dts: rockchip: Add device tree support for HDMI RX Controller
> 
> Stephen Chen (1):
>       arm64: dts: rockchip: Add Radxa ROCK 4D device tree
> 
> Yao Zi (5):
>       dt-bindings: clock: Document clock and reset unit of RK3528
>       arm64: dts: rockchip: Add clock generators for RK3528 SoC
>       arm64: dts: rockchip: Add UART clocks for RK3528 SoC
>       dt-bindings: soc: rockchip: Add RK3528 VO GRF syscon
>       dt-bindings: soc: rockchip: Add RK3528 VPU GRF syscon
> 
>  .../devicetree/bindings/arm/rockchip.yaml          |   25 +-
>  .../bindings/clock/rockchip,rk3528-cru.yaml        |   64 +
>  Documentation/devicetree/bindings/mfd/syscon.yaml  |    2 +
>  .../devicetree/bindings/soc/rockchip/grf.yaml      |    3 +
>  .../devicetree/bindings/vendor-prefixes.yaml       |    4 +-
>  arch/arm64/boot/dts/rockchip/Makefile              |   63 +
>  .../px30-ringneck-haikou-lvds-9904379.dtso         |  130 ++
>  .../rockchip/px30-ringneck-haikou-video-demo.dtso  |  190 +++
>  .../boot/dts/rockchip/px30-ringneck-haikou.dts     |    2 +
>  arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi    |    4 -
>  arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts  |    8 +
>  .../rockchip/rk3399-puma-haikou-video-demo.dtso    |  166 +++
>  .../arm64/boot/dts/rockchip/rk3399-puma-haikou.dts |   26 +-
>  arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi      |   10 +-
>  .../arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts |    2 +-
>  arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi   | 1397 ++++++++++++++++++++
>  arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts |  118 ++
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi           |  354 ++++-
>  arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi  |    2 +
>  arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts |    8 +-
>  arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts |    8 +-
>  arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts |  588 ++++++++
>  arch/arm64/boot/dts/rockchip/rk356x-base.dtsi      |    5 +
>  .../boot/dts/rockchip/rk3576-armsom-sige5.dts      |   47 +
>  arch/arm64/boot/dts/rockchip/rk3576-evb1-v10.dts   |   47 +
>  arch/arm64/boot/dts/rockchip/rk3576-roc-pc.dts     |  736 +++++++++++
>  arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts    |  751 +++++++++++
>  arch/arm64/boot/dts/rockchip/rk3576.dtsi           |  187 +++
>  .../arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi |    4 +
>  .../boot/dts/rockchip/rk3588-armsom-sige7.dts      |   51 +
>  arch/arm64/boot/dts/rockchip/rk3588-base.dtsi      |  110 +-
>  .../boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts    |    2 +-
>  .../dts/rockchip/rk3588-coolpi-cm5-genbook.dts     |    2 +-
>  .../arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi |    4 +
>  .../dts/rockchip/rk3588-edgeble-neu6a-common.dtsi  |    4 +
>  .../boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi |   47 +
>  arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts   |   50 +-
>  arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi     |  186 +++
>  arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi |    4 +
>  .../dts/rockchip/rk3588-firefly-core-3588j.dtsi    |    4 +
>  .../dts/rockchip/rk3588-firefly-icore-3588q.dtsi   |  443 +++++++
>  .../boot/dts/rockchip/rk3588-firefly-itx-3588j.dts |    2 +-
>  .../rockchip/rk3588-friendlyelec-cm3588-nas.dts    |    2 +-
>  .../dts/rockchip/rk3588-friendlyelec-cm3588.dtsi   |    4 +
>  .../arm64/boot/dts/rockchip/rk3588-h96-max-v58.dts |   30 +-
>  .../dts/rockchip/rk3588-jaguar-pre-ict-tester.dtso |  171 +++
>  arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts     |  224 +++-
>  .../arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts |  336 +++++
>  arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi |    6 +-
>  arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts   |    4 +
>  .../dts/rockchip/rk3588-orangepi-5-compact.dtsi    |    9 -
>  .../boot/dts/rockchip/rk3588-orangepi-5-max.dts    |   51 +-
>  .../boot/dts/rockchip/rk3588-orangepi-5-plus.dts   |    2 +-
>  .../boot/dts/rockchip/rk3588-orangepi-5-ultra.dts  |   83 ++
>  .../arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi |    6 +-
>  .../arm64/boot/dts/rockchip/rk3588-quartzpro64.dts |    6 +-
>  arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts |   53 +
>  arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts    |   83 +-
>  .../boot/dts/rockchip/rk3588-tiger-haikou.dts      |    4 +-
>  arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi     |    5 +-
>  .../arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts |    4 +
>  .../arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi |    4 +
>  arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts |   29 +-
>  arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts  |    6 +-
>  .../boot/dts/rockchip/rk3588s-gameforce-ace.dts    |    6 +-
>  .../boot/dts/rockchip/rk3588s-indiedroid-nova.dts  |    8 +-
>  .../boot/dts/rockchip/rk3588s-khadas-edge2.dts     |    4 +
>  .../arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi |    6 +-
>  arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts |    6 +-
>  .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi      |    8 +-
>  arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts   |    6 +-
>  arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts   |   42 +-
>  include/dt-bindings/clock/rockchip,rk3528-cru.h    |  453 +++++++
>  include/dt-bindings/reset/rockchip,rk3528-cru.h    |  241 ++++
>  74 files changed, 7693 insertions(+), 69 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3528-cru.yaml
>  create mode 100644 arch/arm64/boot/dts/rockchip/px30-ringneck-haikou-lvds-9904379.dtso
>  create mode 100644 arch/arm64/boot/dts/rockchip/px30-ringneck-haikou-video-demo.dtso
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-puma-haikou-video-demo.dtso
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-roc-pc.dts
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-firefly-icore-3588q.dtsi
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-jaguar-pre-ict-tester.dtso
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-mnt-reform2.dts
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-ultra.dts
>  create mode 100644 include/dt-bindings/clock/rockchip,rk3528-cru.h
>  create mode 100644 include/dt-bindings/reset/rockchip,rk3528-cru.h
> 






From heiko at sntech.de  Wed Mar 12 00:00:54 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:00:54 +0100
Subject: [PATCH] iio: adc: rockchip: Fix clock initialization sequence
In-Reply-To: <20250312062016.137821-1-xxm@rock-chips.com>
References: <20250312062016.137821-1-xxm@rock-chips.com>
Message-ID: <10623626.nUPlyArG6x@phil>

Am Mittwoch, 12. M?rz 2025, 07:20:16 MEZ schrieb Simon Xue:
> clock_set_rate should be executed after devm_clk_get_enabled.
> 
> Fixes: 97ad10bb2901 ("iio: adc: rockchip_saradc: Make use of devm_clk_get_enabled")
> Signed-off-by: Simon Xue <xxm at rock-chips.com>

Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> ---
>  drivers/iio/adc/rockchip_saradc.c | 17 ++++++++---------
>  1 file changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
> index a29e54754c8f..ab4de67fb135 100644
> --- a/drivers/iio/adc/rockchip_saradc.c
> +++ b/drivers/iio/adc/rockchip_saradc.c
> @@ -480,15 +480,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
>  	if (info->reset)
>  		rockchip_saradc_reset_controller(info->reset);
>  
> -	/*
> -	 * Use a default value for the converter clock.
> -	 * This may become user-configurable in the future.
> -	 */
> -	ret = clk_set_rate(info->clk, info->data->clk_rate);
> -	if (ret < 0)
> -		return dev_err_probe(&pdev->dev, ret,
> -				     "failed to set adc clk rate\n");
> -
>  	ret = regulator_enable(info->vref);
>  	if (ret < 0)
>  		return dev_err_probe(&pdev->dev, ret,
> @@ -515,6 +506,14 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
>  	if (IS_ERR(info->clk))
>  		return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
>  				     "failed to get adc clock\n");
> +	/*
> +	 * Use a default value for the converter clock.
> +	 * This may become user-configurable in the future.
> +	 */
> +	ret = clk_set_rate(info->clk, info->data->clk_rate);
> +	if (ret < 0)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "failed to set adc clk rate\n");
>  
>  	platform_set_drvdata(pdev, indio_dev);
>  
> 






From baolu.lu at linux.intel.com  Wed Mar 12 00:07:36 2025
From: baolu.lu at linux.intel.com (Baolu Lu)
Date: Wed, 12 Mar 2025 15:07:36 +0800
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <Z9CEIlXoQJ-A0t-d@8bytes.org>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <Z9CEIlXoQJ-A0t-d@8bytes.org>
Message-ID: <57dab191-6383-4d51-ba77-4d2cd62cc1da@linux.intel.com>

On 2025/3/12 2:42, Joerg Roedel wrote:
> On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
>> +	/*
>> +	 * And if we do now see any replay calls, they would indicate someone
>> +	 * misusing the dma_configure path outside bus code.
>> +	 */
>> +	if (dev->driver)
>> +		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
> This warning triggers on my workstation (with an AMD IOMMU), any ideas?
> 
>   ------------[ cut here ]------------
>   reg-dummy reg-dummy: late IOMMU probe at driver bind, something fishy here!
>   WARNING: CPU: 0 PID: 1 at drivers/iommu/iommu.c:449 __iommu_probe_device+0x10b/0x510
>   Modules linked in:
> 
>   CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc6-iommu-next+ #1 1d691d7aebf343bde741cf4c8610d78a2ea2d2d9
>   Hardware name: System manufacturer System Product Name/PRIME X470-PRO, BIOS 5406 11/13/2019
>   RIP: 0010:__iommu_probe_device+0x10b/0x510
>   Code: 68 00 74 28 48 8b 6b 50 48 85 ed 75 03 48 8b 2b 48 89 df e8 87 71 06 00 48 89 ea 48 c7 c7 90 dd 2c 8b 48 89 c6 e8 35 83 77 ff <0f> 0b 49 8b bd a8 00 00 00 e8 77 ab 85 ff 84 c0 0f 84 ad 01 00 00
>   RSP: 0018:ffffafba00047c58 EFLAGS: 00010282
>   RAX: 0000000000000000 RBX: ffffa00481301c10 RCX: 0000000000000003
>   RDX: 0000000000000000 RSI: 0000000000000003 RDI: 0000000000000001
>   RBP: ffffa00480ffaee0 R08: 0000000000000000 R09: ffffafba00047ae8
>   R10: ffffa0135e93ffa8 R11: 0000000000000003 R12: ffffafba00047d18
>   R13: ffffffff8adac1a0 R14: 0000000000000000 R15: ffffa004802c5800
>   FS:  0000000000000000(0000) GS:ffffa0135ea00000(0000) knlGS:0000000000000000
>   CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>   CR2: ffffa00baca01000 CR3: 000000082b838000 CR4: 00000000003506f0
>   Call Trace:
>    <TASK>
>    ? __iommu_probe_device+0x10b/0x510
>    ? __warn.cold+0x93/0xf7
>    ? __iommu_probe_device+0x10b/0x510
>    ? report_bug+0xff/0x140
>    ? prb_read_valid+0x1b/0x30
>    ? handle_bug+0x58/0x90
>    ? exc_invalid_op+0x17/0x70
>    ? asm_exc_invalid_op+0x1a/0x20
>    ? __iommu_probe_device+0x10b/0x510
>    ? __iommu_probe_device+0x10b/0x510
>    ? __pfx_probe_iommu_group+0x10/0x10
>    probe_iommu_group+0x28/0x50
>    bus_for_each_dev+0x7e/0xd0
>    iommu_device_register+0xee/0x260
>    iommu_go_to_state+0xa2a/0x1970
>    ? srso_return_thunk+0x5/0x5f
>    ? blake2s_update+0x68/0x160
>    ? __pfx_pci_iommu_init+0x10/0x10
>    amd_iommu_init+0x14/0x50
>    ? __pfx_pci_iommu_init+0x10/0x10
>    pci_iommu_init+0x12/0x40
>    do_one_initcall+0x46/0x300
>    kernel_init_freeable+0x23d/0x2a0
>    ? __pfx_kernel_init+0x10/0x10
>    kernel_init+0x1a/0x140
>    ret_from_fork+0x34/0x50
>    ? __pfx_kernel_init+0x10/0x10
>    ret_from_fork_asm+0x1a/0x30
>    </TASK>
>   ---[ end trace 0000000000000000 ]---

I saw the same issue on Intel platforms.

Thanks,
baolu


From tudor.ambarus at linaro.org  Wed Mar 12 00:11:08 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Wed, 12 Mar 2025 07:11:08 +0000
Subject: [PATCH 3/3] firmware: samsung: add ACPM debugfs support
In-Reply-To: <005424c2-7fb7-48db-b38c-c62f9f8b3897@kernel.org>
References: <20250224-acpm-debugfs-v1-0-2418a3ea1b17@linaro.org>
 <20250224-acpm-debugfs-v1-3-2418a3ea1b17@linaro.org>
 <005424c2-7fb7-48db-b38c-c62f9f8b3897@kernel.org>
Message-ID: <696494b8-14e9-4b9b-bf26-2a94a915b2ec@linaro.org>

Hi, Krzysztof,

On 3/5/25 7:37 PM, Krzysztof Kozlowski wrote:
> On 24/02/2025 09:01, Tudor Ambarus wrote:

cut
> Please add something like above also as a comment to the driver, so the
> interface will be documented.

okay, will add.

cut

>> +static struct dentry *rootdir;
> 
> exynos-apcm.c is not a singleton, so neither should this be. You should
> create entries per device (so with device name as subdirectory), just
> for correctness.
> 
>> +
>> +static DEFINE_MUTEX(acpm_log_level_mutex);
> 
> And this also looks per-device-instance.

okay, will create per device instances.

>> +
>> +static void acpm_log_print_entry(struct acpm_info *acpm,
>> +				 const union acpm_log_entry *log_entry)
>> +{

cut

>> +		dev_info(acpm->dev, "[ACPM_FW] : %llu id:%u, %s, %x\n", time,
>> +			 log_entry->plugin_id, (char *)&msg, log_entry->data);
> 
> 
> I don't think these should be printed to dmesg - these are not system
> logs. You either return the contents to the caller's read() on debugfs
> entry or, if this is anyhow crashdump related, it goes to
> pstore/minidump once triggered. Or to ramoops.
> 
> Depends what these logs are (so please also explain what do you find
> there in the commit msg).
> 
> Maybe something like CHROMEOS_PSTORE?
> 
> IOW, if enabled, this should go to ramoops/pstore unconditionally. For
> runtime debugging this should be returned somehow to the userspace
> reading the file. I think usually debugfs and sysfs is not expected to
> provide more than PAGE_SIZE data, so this second part has to be
> rethinked still.
> 

This is a logging feature, it's not oops/panic related. These logs are
referred to as "block logs". A "block" is the start of a mailbox command
to its end, so it logs every ACPM mailbox command issued to the
firmware. After each end of a block, we see the state of all regulators,
frequencies and devices up/down extracted from the block.

These are indeed system logs, and using the dmesg ring buffer seems fine
as we typically care about the recent logs, we don't care if the ring
starts all over again.

>> +DEFINE_DEBUGFS_ATTRIBUTE(acpm_log_level_fops, acpm_log_level_get,
>> +			 acpm_log_level_set, "0%llu\n");
> 
> I also do not think debugfs is a knob to control loglevel of messages
> going to dmesg.
> 

This debugfs entry controls which SRAM log ring buffers are queried -
there are 2 SRAM buffers.

I guess you thought about the "logb_gprio_level" entry, which controls
the ACPM print verbosity. 0xf being ERR, and 0x0 all logs. The firmware
defaults on printing all logs. I can't tell right now other way of
controlling the logs verbosity, maybe via sysfs, but it's equivalent and
with more restrictions. Or maybe you think that I shall always print all
logs?

Thanks,
ta


From shinichiro.kawasaki at wdc.com  Wed Mar 12 00:20:09 2025
From: shinichiro.kawasaki at wdc.com (Shinichiro Kawasaki)
Date: Wed, 12 Mar 2025 07:20:09 +0000
Subject: [PATCH v2 2/2] block: change blk_mq_add_to_batch() third argument
 type to bool
In-Reply-To: <Z9Ei2t7z_7QbEWXW@infradead.org>
References: <20250311104359.1767728-1-shinichiro.kawasaki@wdc.com>
 <20250311104359.1767728-3-shinichiro.kawasaki@wdc.com>
 <Z9Ei2t7z_7QbEWXW@infradead.org>
Message-ID: <slsdaxocaojcfxsq3akvwp4kjzhddx4agcqori3jpnljkfwyji@qlmpctcyejfu>

On Mar 11, 2025 / 22:59, Christoph Hellwig wrote:
> On Tue, Mar 11, 2025 at 07:43:59PM +0900, Shin'ichiro Kawasaki wrote:
> >  /*
> >   * Batched completions only work when there is no I/O error and no special
> >   * ->end_io handler.
> > + *
> > + * @req: The request to add to batch
> > + * @iob: The batch to add the request
> > + * @is_error: Specify true if the request failed with an error
> > + * @io_comp_batch: The completaion handler for the request
> >   */
> 
> This needs more work to be a proper kerneldoc comment, i.e. start with
> "/*8", mention the function name, etc.

Ah, thanks. I should have checked the kerneldoc format. Jens already queued up
this patch (thanks!), so I will send out a separate, follow-up patch to fix the
kerneldoc comment. The follow-up patch will be posted to linux-block list, with
reduced To/Cc members.

From shawnguo2 at yeah.net  Wed Mar 12 00:40:03 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Wed, 12 Mar 2025 15:40:03 +0800
Subject: [GIT PULL 3/5] i.MX dt-bindings changes for 6.15
In-Reply-To: <20250312074005.663165-1-shawnguo2@yeah.net>
References: <20250312074005.663165-1-shawnguo2@yeah.net>
Message-ID: <20250312074005.663165-3-shawnguo2@yeah.net>

From: Shawn Guo <shawnguo at kernel.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-bindings-6.15

for you to fetch changes up to 401735c5f28f41561f60dc11b67520479694f422:

  dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and Concerto board (2025-03-11 11:35:54 +0800)

----------------------------------------------------------------
i.MX dt-bindings changes for 6.15:

- Add compatibles for Skov i.MX8MP variants, VAR-SOM-MX6UL SoM and
  Concerto, i.MX95 15x15 EVK, btt3 i.MX28
- Drop Toradex SOMs compatibles

----------------------------------------------------------------
Ahmad Fatoum (1):
      dt-bindings: arm: fsl: add more compatibles for Skov i.MX8MP variants

Antonin Godard (1):
      dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and Concerto board

Francesco Dolcini (1):
      dt-bindings: arm: fsl: drop usage of Toradex SOMs compatible alone

Frank Li (1):
      dt-bindings: arm: fsl: add i.MX95 15x15 EVK board

Lukasz Majewski (1):
      dt-bindings: arm: Document the btt3 i.MX28 based board

 Documentation/devicetree/bindings/arm/fsl.yaml | 27 +++++++++++---------------
 1 file changed, 11 insertions(+), 16 deletions(-)



From shawnguo2 at yeah.net  Wed Mar 12 00:40:04 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Wed, 12 Mar 2025 15:40:04 +0800
Subject: [GIT PULL 4/5] i.MX ARM device tree changes for 6.15
In-Reply-To: <20250312074005.663165-1-shawnguo2@yeah.net>
References: <20250312074005.663165-1-shawnguo2@yeah.net>
Message-ID: <20250312074005.663165-4-shawnguo2@yeah.net>

From: Shawn Guo <shawnguo at kernel.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-dt-6.15

for you to fetch changes up to 082f59a62474fbffe7e952082f6d265f11bc37a0:

  ARM: dts: apalis/colibri-imx6: Add support for v1.2 (2025-03-11 11:40:10 +0800)

----------------------------------------------------------------
i.MX ARM device tree changes for 6.15:

- New boards support: Variscite VAR-SOM-MX6UL SoM/Concerto, i.MX6
  apalis/colibri v1.2, i.MX28 based btt3
- A bunch of TQMa6/7 cleanups from Alexander Stein and Markus Niebel,
  ordering DT properties, correcting 3.3V supply, adding partitions
  child node to spi-nor, etc.
- A bunch of changes from Fabio Estevam to fix dt-schema warnings on
  various boards
- Other small and random changes

----------------------------------------------------------------
Alexander Stein (5):
      ARM: dts: imx7s: Move csi-mux to below root
      ARM: dts: imx6qdl-tqma6: Order DT properties
      ARM: dts: imx6ul-tqma6ul: Order DT properties
      ARM: dts: imx6ul-tqma6ul: Add vcc-supply for spi-nor
      ARM: dts: imx7-tqma7: Add vcc-supply for spi-nor

Antonin Godard (2):
      ARM: dts: imx6ul: Add Variscite VAR-SOM-MX6UL SoM support
      ARM: dts: imx6ul: Add Variscite Concerto board support

Chancel Liu (2):
      ARM: dts: imx6ul-14x14-evk: Complete WM8960 power supplies
      ARM: dts: imx7d-sdb: Complete WM8960 power supplies

Ernest Van Hoecke (2):
      ARM: dts: apalis/colibri-imx6: Enable STMPE811 TS
      ARM: dts: apalis/colibri-imx6: Add support for v1.2

Fabio Estevam (8):
      ARM: dts: imx53-ppd: Fix touchscreen reset-gpios
      ARM: dts: vfxxx: Fix the CAAM job ring node names
      ARM: dts: imx5: Fix the CCM interrupts description
      ARM: dts: vf610-bk4: Use the more specific "lwn,bk4-spi"
      ARM: dts: imx28-sps1: Fix GPIO LEDs description
      ARM: dts: vfxxx: Fix the order of the DMA entries
      ARM: dts: imx31: Use nand-controller as node name
      ARM: dts: imx53-mba53: Fix the PCA9554 compatible

Francesco Dolcini (2):
      ARM: dts: imx6qdl-apalis/colibri: Remove compatible from SoM dtsi
      ARM: dts: vf610-colibri: Remove compatible from SoM dtsi

Krzysztof Kozlowski (1):
      ARM: dts: nxp: vf: Align GPIO hog name with bindings

Lukasz Majewski (1):
      ARM: dts: mxs: Add descriptions for imx287 based btt3-[012] devices

Markus Niebel (8):
      ARM: dts: imx6qdl-mba6: change sound card model name
      ARM: dts: imx7-mba7: change sound card model name
      ARM: dts: mba6ul: change sound card model name
      ARM: dts: imx6qdl-tqma6: limit PMIC SW4 to 3.3V
      ARM: dts: imx6qdl-tqma6: use sw4_reg as 3.3V supply
      ARM: dts: imx6qdl-tqma6: Add partitions subnode to spi-nor
      ARM: dts: tqma6ul: Add partitions subnode to spi-nor
      ARM: dts: tqma7: Add partitions subnode to spi-nor

Max Merchel (1):
      ARM: dts: imx6ul-tqma6ul1: Change include order to disable fec2 node

 arch/arm/boot/dts/nxp/imx/Makefile                 |  10 +
 arch/arm/boot/dts/nxp/imx/imx31.dtsi               |   2 +-
 arch/arm/boot/dts/nxp/imx/imx50.dtsi               |   2 +-
 arch/arm/boot/dts/nxp/imx/imx51.dtsi               |   2 +-
 arch/arm/boot/dts/nxp/imx/imx53-mba53.dts          |   2 +-
 arch/arm/boot/dts/nxp/imx/imx53-ppd.dts            |   2 +-
 arch/arm/boot/dts/nxp/imx/imx53.dtsi               |   2 +-
 .../boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts |  11 +
 .../dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts    |  11 +
 .../dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts    |  11 +
 .../boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts  |  11 +
 .../dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts    |  11 +
 .../boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts    |  11 +
 .../dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts   |  11 +
 .../dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts   |  11 +
 .../boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts   |  11 +
 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi |  57 ++++
 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi      |   2 -
 .../arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi |  57 ++++
 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi     |   2 -
 arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi        |   2 +-
 arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi       |  25 +-
 arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi      |   4 +-
 arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi      |   4 +-
 arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi    |  32 +++
 .../boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi    |  11 +-
 .../boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts   |   3 +-
 arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi     |   2 -
 .../boot/dts/nxp/imx/imx6ul-var-som-concerto.dts   | 320 +++++++++++++++++++++
 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi      | 233 +++++++++++++++
 arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi           |   2 +-
 arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi          |   7 +
 arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts            |  32 +++
 arch/arm/boot/dts/nxp/imx/imx7s.dtsi               |  56 ++--
 arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi             |   2 +-
 arch/arm/boot/dts/nxp/mxs/Makefile                 |   3 +
 arch/arm/boot/dts/nxp/mxs/imx28-btt3-0.dts         |  12 +
 arch/arm/boot/dts/nxp/mxs/imx28-btt3-1.dts         |   8 +
 arch/arm/boot/dts/nxp/mxs/imx28-btt3-2.dts         |  39 +++
 arch/arm/boot/dts/nxp/mxs/imx28-btt3.dtsi          | 313 ++++++++++++++++++++
 arch/arm/boot/dts/nxp/mxs/imx28-sps1.dts           |  13 +-
 arch/arm/boot/dts/nxp/vf/vf610-bk4.dts             |   4 +-
 arch/arm/boot/dts/nxp/vf/vf610-colibri.dtsi        |   1 -
 arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-c.dts   |   4 +-
 arch/arm/boot/dts/nxp/vf/vfxxx.dtsi                |  21 +-
 45 files changed, 1301 insertions(+), 91 deletions(-)
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-aster.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris-v2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-iris.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-eval.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.1.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora-v1.2.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6q-apalis-v1.2-ixora.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis-v1.2.dtsi
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6qdl-colibri-v1.2.dtsi
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6ul-var-som-concerto.dts
 create mode 100644 arch/arm/boot/dts/nxp/imx/imx6ul-var-som.dtsi
 create mode 100644 arch/arm/boot/dts/nxp/mxs/imx28-btt3-0.dts
 create mode 100644 arch/arm/boot/dts/nxp/mxs/imx28-btt3-1.dts
 create mode 100644 arch/arm/boot/dts/nxp/mxs/imx28-btt3-2.dts
 create mode 100644 arch/arm/boot/dts/nxp/mxs/imx28-btt3.dtsi



From shawnguo2 at yeah.net  Wed Mar 12 00:40:02 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Wed, 12 Mar 2025 15:40:02 +0800
Subject: [GIT PULL 2/5] i.MX SoC changes for 6.15
In-Reply-To: <20250312074005.663165-1-shawnguo2@yeah.net>
References: <20250312074005.663165-1-shawnguo2@yeah.net>
Message-ID: <20250312074005.663165-2-shawnguo2@yeah.net>

From: Shawn Guo <shawnguo at kernel.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-soc-6.15

for you to fetch changes up to 4f8ec94af325d501904d7e86363bd162004161bd:

  ARM: imx: mark imx53_suspend_sz as unused (2025-03-11 10:57:51 +0800)

----------------------------------------------------------------
i.MX SoC changes for 6.15:

- Mark imx53_suspend_sz as __maybe_unused to fix a possible build warning

----------------------------------------------------------------
Arnd Bergmann (1):
      ARM: imx: mark imx53_suspend_sz as unused

 arch/arm/mach-imx/common.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)



From shawnguo2 at yeah.net  Wed Mar 12 00:40:01 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Wed, 12 Mar 2025 15:40:01 +0800
Subject: [GIT PULL 1/5] i.MX drivers changes for 6.15
Message-ID: <20250312074005.663165-1-shawnguo2@yeah.net>

From: Shawn Guo <shawnguo at kernel.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-drivers-6.15

for you to fetch changes up to d3ad803a97c7f53d872eb3e9782c2286cae6954b:

  MAINTAINERS: match mxc in file names by IMX / MXC entry (2025-02-19 17:45:43 +0800)

----------------------------------------------------------------
i.MX drivers changes for 6.15:

- A MAINTAINERS update from Ahmad Fatoum to get mxc drivers matched by
  i.MX entry

----------------------------------------------------------------
Ahmad Fatoum (1):
      MAINTAINERS: match mxc in file names by IMX / MXC entry

 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)



From krzk at kernel.org  Wed Mar 12 00:42:29 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 08:42:29 +0100
Subject: [PATCH 2/2] arm64: dts: exynos: Add DT node for all UART ports
In-Reply-To: <20250312061932.1797993-2-faraz.ata@samsung.com>
References: <20250312061932.1797993-1-faraz.ata@samsung.com>
 <CGME20250312061058epcas5p3ccf293213fe883129358833572b17d92@epcas5p3.samsung.com>
 <20250312061932.1797993-2-faraz.ata@samsung.com>
Message-ID: <5b68a9c2-9145-4131-9fa3-10810c51691f@kernel.org>

On 12/03/2025 07:19, Faraz Ata wrote:
> Universal Serial Interface (USI) supports three serial protocol
> like uart, i2c and spi. ExynosAutov920 has 18 instances of USI.
> Add all the USI DT node and subsequent uart nodes for all the instances.
> 
> Signed-off-by: Faraz Ata <faraz.ata at samsung.com>
> ---
>  .../arm64/boot/dts/exynos/exynosautov920.dtsi | 494 ++++++++++++++++++
>  1 file changed, 494 insertions(+)


Please do not combine DTS changes with serial patches, ever. DTS has to
go via separate tree.

...

> +
> +		usi_17: usi at 10d800c0 {
> +			compatible = "samsung,exynosautov920-usi",
> +				     "samsung,exynos850-usi";
> +			reg = <0x10d800c0 0x20>;
> +			samsung,sysreg = <&syscon_peric1 0x1040>;
> +			samsung,mode = <USI_V2_UART>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			ranges;
> +			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
> +				 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
> +			clock-names = "pclk", "ipclk";
> +			status = "disabled";
> +
> +			serial_17: serial at 10d80000 {
> +				compatible = "samsung,exynosautov920-uart",
> +					     "samsung,exynos850-uart";
> +				reg = <0x10d80000 0xc0>;
> +				interrupts = <GIC_SPI 803 IRQ_TYPE_LEVEL_HIGH>;
> +				pinctrl-names = "default";
> +				pinctrl-0 = <&uart17_bus>;
> +				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
> +					 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
> +				clock-names = "uart", "clk_uart_baud0";
> +				samsung,uart-fifosize = <64>;
> +				status = "disabled";
> +			};
> +		};
> +
> +

Just one blank line.

>  		pwm: pwm at 109b0000 {
>  			compatible = "samsung,exynosautov920-pwm",
>  				     "samsung,exynos4210-pwm";


Best regards,
Krzysztof


From heiko at sntech.de  Wed Mar 12 00:45:56 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:45:56 +0100
Subject: (subset) [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250307120004.959980-1-amadeus@jmu.edu.cn>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
Message-ID: <174176555637.249409.2785731072183565436.b4-ty@sntech.de>


On Fri, 07 Mar 2025 20:00:02 +0800, Chukun Pan wrote:
> Add pwm nodes for RK3528. Most rk3528 boards use pwm-regulator to
> supply to CPU, add node to enable them. The PWM core on RK3528 is
> the same as RK3328, but the driver doesn't support interrupts yet.
> 
> Unlike other SoCs, pinctrl-names need to be in "active" state,
> I'm not sure about this, but otherwise the pwm-regulator will
> not work properly.
> 
> [...]

Applied, thanks!

[2/2] arm64: dts: rockchip: Add pwm nodes for RK3528
      commit: 2973d077aedfc114affab96c3b2c7286163cc8c9

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:45:57 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:45:57 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: rk356x: Move SHMEM memory to reserved memory
In-Reply-To: <20250308100001.572657-2-amadeus@jmu.edu.cn>
References: <20250308100001.572657-1-amadeus@jmu.edu.cn> <20250308100001.572657-2-amadeus@jmu.edu.cn>
Message-ID: <174176555638.249409.3786119315566916178.b4-ty@sntech.de>


On Sat, 08 Mar 2025 18:00:01 +0800, Chukun Pan wrote:
> 0x0 to 0xf0000000 are SDRAM memory areas where 0x10f000 is located.
> So move the SHMEM memory of arm_scmi to the reserved memory node.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: rk356x: Move SHMEM memory to reserved memory
      commit: 19f48b687566b0f52c9ca833fa1f0c27ce44e1ba

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:45:59 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:45:59 +0100
Subject: [PATCH] arm64: dts: rockchip: Add AP6275P wireless support to ArmSoM Sige7
In-Reply-To: <20250311142825.2727171-1-liujianfeng1994@gmail.com>
References: <20250311142825.2727171-1-liujianfeng1994@gmail.com>
Message-ID: <174176555630.249409.3989831081874397806.b4-ty@sntech.de>


On Tue, 11 Mar 2025 22:27:50 +0800, Jianfeng Liu wrote:
> ArmSoM Sige7 uses the PCI-e AP6275P Wi-Fi 6 module. The pcie at 0 node can
> be used as Bridge1, so the wifi at 0 node is used as a device under the
> Bridege 1 similar with Khadas Edge 2.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Add AP6275P wireless support to ArmSoM Sige7
      commit: d6166ea4cc4943cbabdeeedb13f3545fdba3ebf6

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:45:58 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:45:58 +0100
Subject: [PATCH 0/4] Orange Pi 5 series HDMI extras
In-Reply-To: <20250227235623.1624-1-honyuenkwun@gmail.com>
References: <20250227235623.1624-1-honyuenkwun@gmail.com>
Message-ID: <174176555629.249409.12164910795169233638.b4-ty@sntech.de>


On Thu, 27 Feb 2025 17:56:19 -0600, Jimmy Hon wrote:
> HDMI Audio and HDMI1
> 
> Need testers for Orange Pi 5 Plus
> 
> Jimmy Hon (4):
>   arm64: dts: rockchip: Enable HDMI0 audio output for Orange Pi 5/5B
>   arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Max
>   arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Plus
>   arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Plus
> 
> [...]

Applied, thanks!

[1/4] arm64: dts: rockchip: Enable HDMI0 audio output for Orange Pi 5/5B
      commit: 21f1208a3af4c30497f60ce220490edd761c5ed9
[2/4] arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Max
      commit: 01284d7e38fca8a4d6a9982cc69e618aadd30de1
[3/4] arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Plus
      commit: ffafe9c2dc31d1a346aff482157dd37eaadbe054
[4/4] arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Plus
      commit: 1bfb987d1a54bc139b62261e3698006418835229

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:46:00 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:46:00 +0100
Subject: [PATCH] arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max
In-Reply-To: <20250311141245.2719796-1-liujianfeng1994@gmail.com>
References: <20250311141245.2719796-1-liujianfeng1994@gmail.com>
Message-ID: <174176555627.249409.15245635322576159789.b4-ty@sntech.de>


On Tue, 11 Mar 2025 22:12:39 +0800, Jianfeng Liu wrote:
> According to the schematic, pcie reset gpio is GPIO3_D4,
> not GPIO4_D4.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max
      commit: e79abd605edbd45eb61a251c6b0d6e50e605a14a

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:46:02 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:46:02 +0100
Subject: [PATCH] arm64: dts: rockchip: rock-3a: Remove bluetooth node
In-Reply-To: <20250220165051.1889055-1-wens@kernel.org>
References: <20250220165051.1889055-1-wens@kernel.org>
Message-ID: <174176555639.249409.16980967669607961093.b4-ty@sntech.de>


On Fri, 21 Feb 2025 00:50:51 +0800, Chen-Yu Tsai wrote:
> The Bluetooth node described in the device tree is actually on an M.2
> slot. What module is present depends on what the end user installed,
> and should be left to an overlay.
> 
> Remove the existing bluetooth node. This gets rid of bogus timeout
> errors.
> 
> [...]

Applied, thanks!

[1/1] arm64: dts: rockchip: rock-3a: Remove bluetooth node
      commit: 9602f47fe6dcca9318f35f7b72b4e98b91c5a5cf

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:46:01 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:46:01 +0100
Subject: [PATCH 0/2] Fix CPU and GPU clocks on RK3576
In-Reply-To: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
References: <20250310-rk3576-scmi-clocks-v1-0-e165deb034e8@collabora.com>
Message-ID: <174176555624.249409.2523115865031259262.b4-ty@sntech.de>


On Mon, 10 Mar 2025 10:59:55 +0100, Nicolas Frattaroli wrote:
> As Jonas Karlman pointed out on the #linux-rockchip IRC channel on
> Libera yesterday, mainline has once again chosen a different set of
> clock IDs compared to downstream, with hugely detrimental effects to
> mainline's ability to use SCMI for clock operations. This is because
> TF-A will use the downstream IDs, and when we reclock things through
> SCMI, TF-A will get the wrong clock ID from us.
> 
> [...]

Applied, thanks!

[1/2] dt-bindings: clock: rk3576: add SCMI clocks
      commit: 33a409dd1fc8be5ef8f33ebed76856c4cbc5bc15
[2/2] arm64: dts: rockchip: fix RK3576 SCMI clock IDs
      commit: 825f48a12e597e7556768088b74f3384840df5e6

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Wed Mar 12 00:46:03 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 08:46:03 +0100
Subject: [PATCH] arm64: dts: rockchip: Fix PWM pinctrl names
In-Reply-To: <20250310140916.14384-2-ziyao@disroot.org>
References: <20250310140916.14384-2-ziyao@disroot.org>
Message-ID: <174176555635.249409.12410081245956028439.b4-ty@sntech.de>


On Mon, 10 Mar 2025 14:09:17 +0000, Yao Zi wrote:
> These Rockchip boards assign "active" as the pinctrl name for PWM
> controllers, which has never been supported in mainline Rockchip PWM
> driver. It seems the name used by downstream kernel is accidentally
> brought into maineline. Let's fix them.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Fix PWM pinctrl names
      commit: 96d8d325324639f03fcca12e4ea92265ebb24837

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From yangyicong at huawei.com  Wed Mar 12 00:47:48 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Wed, 12 Mar 2025 15:47:48 +0800
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <CAD=FV=Wy9-nDW-F+R1Aob6GOfP1Cnmr1gKkCO+WebA8ES7uu8A@mail.gmail.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
 <20250307021811.46981-3-yangyicong@huawei.com>
 <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>
 <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com>
 <CAD=FV=Wy9-nDW-F+R1Aob6GOfP1Cnmr1gKkCO+WebA8ES7uu8A@mail.gmail.com>
Message-ID: <260393cc-614a-b5c1-0e04-8443e00a7991@huawei.com>

On 2025/3/11 23:41, Doug Anderson wrote:
> Hi,
> 
> On Tue, Mar 11, 2025 at 1:33?AM Yicong Yang <yangyicong at huawei.com> wrote:
>>
>> On 2025/3/8 0:53, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Thu, Mar 6, 2025 at 6:18?PM Yicong Yang <yangyicong at huawei.com> wrote:
>>>>
>>>> From: Yicong Yang <yangyicong at hisilicon.com>
>>>>
>>>> arm64 depends on the cpufreq driver to gain the maximum cpu frequency
>>>> to convert the watchdog_thresh to perf event period. cpufreq drivers
>>>> like cppc_cpufreq will be initialized lately after the initializing of
>>>> the hard lockup detector so just use a safe cpufreq which will be
>>>> inaccurency. Use a cpufreq notifier to adjust the event's period to
>>>> a more accurate one.
>>>>
>>>> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
>>>> ---
>>>>  arch/arm64/kernel/watchdog_hld.c | 34 ++++++++++++++++++++++++++++++++
>>>>  1 file changed, 34 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
>>>> index dcd25322127c..719ae39e8bc0 100644
>>>> --- a/arch/arm64/kernel/watchdog_hld.c
>>>> +++ b/arch/arm64/kernel/watchdog_hld.c
>>>> @@ -34,3 +34,37 @@ bool __init arch_perf_nmi_is_available(void)
>>>>          */
>>>>         return arm_pmu_irq_is_nmi();
>>>>  }
>>>> +
>>>> +static int watchdog_freq_notifier_callback(struct notifier_block *nb,
>>>> +                                          unsigned long val, void *data)
>>>> +{
>>>> +       struct cpufreq_policy *policy = data;
>>>> +       unsigned long max_cpu_freq;
>>>
>>> Feels like max_cpu_freq should be a u64. It probably should have been
>>> u64 in hw_nmi_get_sample_period() as well. Otherwise you could end up
>>> with a problem if the max CPU frequency is above ~4.3GHz and "unsigned
>>> long" is 32-bits (I think it technically could be?)
>>>
>>
>> I guess this won't happen for arm64 and we're in kernel space. here I
>> keep the same type with hw_nmi_get_sample_period() which is also using
>> "unsigned long".
> 
> I guess I won't insist, but given that you use u64 explicitly
> elsewhere it feels like you should be explicit that you need 64-bits
> here too.
> 
> 
>>>> +       for_each_cpu(cpu, policy->cpus) {
>>>> +               max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
>>>> +               if (!max_cpu_freq)
>>>> +                       continue;
>>>> +
>>>> +               new_period = watchdog_thresh * max_cpu_freq;
>>>> +               hardlockup_detector_perf_adjust_period(cpu, new_period);
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static struct notifier_block watchdog_freq_notifier = {
>>>> +       .notifier_call = watchdog_freq_notifier_callback,
>>>> +};
>>>> +
>>>> +static int __init init_watchdog_freq_notifier(void)
>>>> +{
>>>> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
>>>> +                                        CPUFREQ_POLICY_NOTIFIER);
>>>> +}
>>>> +core_initcall(init_watchdog_freq_notifier);
>>>
>>> I haven't dug into everything, but don't you have a potential blind
>>> spot, though? What if the order is this:
>>>
>>> 1. hw_nmi_get_sample_period() is called
>>> 2. cpufreq driver probes
>>> 3. init_watchdog_freq_notifier() initcall runs
>>>
>>> Since the cpufreq driver proved before you registered for the
>>> notifier, won't you miss the creation of the policy? Maybe instead of
>>> registering for an initcall you should somehow trigger off the first
>>> call to hw_nmi_get_sample_period() and register at that point in time?
>>>
>>
>> for arm64 the watchdog_perf is registered after armv8 PMU driver's init,
>> so the sequence is like:
>>
>> # core_initcall
>> init_watchdog_freq_notifier()
>> # device_initcall
>> armv8_pmu_driver_init()
>>   lockup_detector_retry_init()
>>     schedule_work(&detector_work);
>> # in detector work
>> hw_nmi_get_sample_period() // notifier's already been registered
>>
>> so we'll always get the correct frequency, either by the cpufreq
>> already registered or by the notifier which will update the
>> frequency. Please correct me if I missed anything :)
> 
> Hmm, OK. So this relies on the fact that because the
> init_watchdog_freq_notifier() is at "core" level that it'll pretty
> much init before any of the other things. This type of thing is always
> a little fragile but I guess it's OK.
> 
> What about if the order is different though? Again, I haven't traced
> through it all, but I'm thinking:
> 
> # core_initcall
> init_watchdog_freq_notifier()
> # device_initcall
> <cpufreq driver policy is created>
> 
> Now hardlockup_detector_perf_adjust_period() will be called before
> armv8_pmu_driver_init(). Is that a problem?

it doesn't matter, since in this situation:

# device_initcall
<cpufreq driver policy is created>
  hardlockup_detector_perf_adjust_period()
    if (!event) // armv8_pmu_driver_init() not called, not event created
      return;
# later after armv8_pmu_driver_init()
hw_nmi_get_sample_period() // since cpufreq already been registered, we can
                           // get the accurate cpufreq

> 
> I guess even worse would be if async probe was on and the cpufreq
> driver and PMU driver were running at the same time?
> 

I think there're 2 cases here:
1) cpufreq initialized before hw_nmi_get_sample_period() called, in which
   case the cpufreq is accurate when create the event
2) hw_nmi_get_sample_period() called before cpufreq driver's initialized,
   in which case we rely on the notifier call to adjust the event's period

May need further check to see if there's any race window here, but the worst
case will be using the inaccurate cpufreq (5GHz) for calculating the period.

Thanks.



From krzk at kernel.org  Wed Mar 12 00:49:16 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 08:49:16 +0100
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250312045802.4115029-1-wthai@nvidia.com>
References: <20250312045802.4115029-1-wthai@nvidia.com>
Message-ID: <93bb3092-7f49-4a7f-ac97-3cf1a62ac39d@kernel.org>

On 12/03/2025 05:58, Willie Thai wrote:
> The GB200NVL BMC is an Aspeed Ast2600 based BMC
> for Nvidia Blackwell GB200NVL platform.
> Reference to Ast2600 SOC [1].
> Reference to Blackwell GB200NVL Platform [2].

Missing blank line

> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Cc: Krzysztof Kozlowski <krzk at kernel.org>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Paul Menzel <pmenzel at molgen.mpg.de>
> Link: Reference to Ast2600 SOC: https://www.aspeedtech.com/server_ast2600/ [1]
> Link: Reference to Blackwell GB200NVL Platform: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]

Links do not have text, I think. Just link.

> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---
> Changes in v2:
>   - Fix the SOB name [Krzysztof]
>   - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
>   - Fix DTS coding style [Krzysztof]
>   - Move pinctrl override to the bottom [Krzysztof]
>   - Drop bootargs [Krzysztof]
>   - Follow DTS coding style and change naming for leds node [Krzysztof]
>   - Change flash 0 status property [Krzysztof]
>   - Change the phy-mode to rgmii [Andrew]
>   - Remove the max-speed in mac0 [Andrew]
> ---
> ---
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1229 +++++++++++++++++
>  2 files changed, 1230 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> 
> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
> index 2e5f4833a073..20fd357a1ee9 100644
> --- a/arch/arm/boot/dts/aspeed/Makefile
> +++ b/arch/arm/boot/dts/aspeed/Makefile
> @@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>  	aspeed-bmc-lenovo-hr630.dtb \
>  	aspeed-bmc-lenovo-hr855xg2.dtb \
>  	aspeed-bmc-microsoft-olympus.dtb \
> +	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
>  	aspeed-bmc-opp-lanyang.dtb \
>  	aspeed-bmc-opp-mowgli.dtb \
>  	aspeed-bmc-opp-nicole.dtb \
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> new file mode 100644
> index 000000000000..eeec3704a43b
> --- /dev/null
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> @@ -0,0 +1,1229 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/dts-v1/;
> +
> +#include "aspeed-g6.dtsi"
> +#include <dt-bindings/gpio/aspeed-gpio.h>
> +#include <dt-bindings/leds/common.h>
> +
> +/ {
> +	model = "AST2600 GB200NVL BMC";
> +	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";

Missing bindings.

Please run scripts/checkpatch.pl and fix reported warnings. After that,
run also `scripts/checkpatch.pl --strict` and (probably) fix more
warnings. Some warnings can be ignored, especially from --strict run,
but the code here looks like it needs a fix. Feel free to get in touch
if the warning is not clear.


...

> +	leds {
> +		compatible = "gpio-leds";
> +		led-0{

Missing space befre {

This applies everywhere.

> +			label = "uid_led";
> +			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
> +		};
> +		led-1{
> +			label = "fault_led";
> +			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
> +		};
> +		led-2{
> +			label = "power_led";
> +			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
> +		};
> +
> +	};
> +
> +	buttons {
> +		button-power {
> +			label = "power-btn";
> +			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
> +		};
> +		button-uid {
> +			label = "uid-btn";
> +			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +};
> +
> +// Enable Primary flash on FMC for bring up activity
> +&fmc {
> +	status = "okay";
> +	flash at 0 {
> +		status = "okay";

Nothing improved.

Respond to comment instead of ignoring it.



...


> +
> +		imux33: i2c at 1 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <1>;
> +			pca9555 at 21 {

Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation

You already got this comment. You must apply such feedback to entire
file instead of fixing only one issue and relying on us to find all
instances. It's your task to find all of the instances.


Best regards,
Krzysztof


From yujie.liu at intel.com  Wed Mar 12 00:56:36 2025
From: yujie.liu at intel.com (Yujie Liu)
Date: Wed, 12 Mar 2025 15:56:36 +0800
Subject: [PATCH] perf script: Fix typo in branch event mask
Message-ID: <20250312075636.429127-1-yujie.liu@intel.com>

BRACH -> BRANCH

Fixes: 88b1473135e4 ("perf script: Separate events from branch types")
Signed-off-by: Yujie Liu <yujie.liu at intel.com>
---
 tools/perf/util/event.h                 | 2 +-
 tools/perf/util/trace-event-scripting.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c7f4b4b841ca..664bf39567ce 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -91,7 +91,7 @@ enum {
 	PERF_IP_FLAG_VMENTRY		|\
 	PERF_IP_FLAG_VMEXIT)
 
-#define PERF_IP_FLAG_BRACH_EVENT_MASK	\
+#define PERF_IP_FLAG_BRANCH_EVENT_MASK	\
 	(PERF_IP_FLAG_BRANCH_MISS |	\
 	 PERF_IP_FLAG_NOT_TAKEN)
 
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 29cc467be14a..72abb28b7b5a 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -347,7 +347,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
 
 	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);
 
-	types = flags & ~PERF_IP_FLAG_BRACH_EVENT_MASK;
+	types = flags & ~PERF_IP_FLAG_BRANCH_EVENT_MASK;
 	for (i = 0; sample_flags[i].name; i++) {
 		if (sample_flags[i].flags != types)
 			continue;
@@ -359,7 +359,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
 		break;
 	}
 
-	events = flags & PERF_IP_FLAG_BRACH_EVENT_MASK;
+	events = flags & PERF_IP_FLAG_BRANCH_EVENT_MASK;
 	for (i = 0; branch_events[i].name; i++) {
 		if (!(branch_events[i].flags & events))
 			continue;

base-commit: b10f74308e1305275e69ddde711ec817cc69e306
-- 
2.34.1



From faraz.ata at samsung.com  Tue Mar 11 23:19:31 2025
From: faraz.ata at samsung.com (Faraz Ata)
Date: Wed, 12 Mar 2025 11:49:31 +0530
Subject: [PATCH 1/2] tty: serial: samsung_tty: update UART_NR for
 ExynosAutov920
References: <CGME20250312061053epcas5p3b33ffac4d9af89de5ef01d42f6157c47@epcas5p3.samsung.com>
Message-ID: <20250312061932.1797993-1-faraz.ata@samsung.com>

ExynosAutov920 SoC supports 18 UART ports, update
the value of UART_NR to accommodate the same.

Signed-off-by: Faraz Ata <faraz.ata at samsung.com>
---
 drivers/tty/serial/samsung_tty.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 210fff7164c1..9a5211b730fb 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -52,7 +52,7 @@
 #define S3C24XX_SERIAL_MINOR	64
 
 #ifdef CONFIG_ARM64
-#define UART_NR			12
+#define UART_NR			18
 #else
 #define UART_NR			CONFIG_SERIAL_SAMSUNG_UARTS
 #endif
-- 
2.34.1



From faraz.ata at samsung.com  Tue Mar 11 23:19:32 2025
From: faraz.ata at samsung.com (Faraz Ata)
Date: Wed, 12 Mar 2025 11:49:32 +0530
Subject: [PATCH 2/2] arm64: dts: exynos: Add DT node for all UART ports
In-Reply-To: <20250312061932.1797993-1-faraz.ata@samsung.com>
References: <20250312061932.1797993-1-faraz.ata@samsung.com>
	<CGME20250312061058epcas5p3ccf293213fe883129358833572b17d92@epcas5p3.samsung.com>
Message-ID: <20250312061932.1797993-2-faraz.ata@samsung.com>

Universal Serial Interface (USI) supports three serial protocol
like uart, i2c and spi. ExynosAutov920 has 18 instances of USI.
Add all the USI DT node and subsequent uart nodes for all the instances.

Signed-off-by: Faraz Ata <faraz.ata at samsung.com>
---
 .../arm64/boot/dts/exynos/exynosautov920.dtsi | 494 ++++++++++++++++++
 1 file changed, 494 insertions(+)

diff --git a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
index eb446cdc4ab6..76b882187a7d 100644
--- a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
@@ -330,6 +330,500 @@ serial_0: serial at 10880000 {
 			};
 		};
 
+		usi_1: usi at 108a00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108a00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1008>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI01_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_1: serial at 108a0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x108a0000 0xc0>;
+				interrupts = <GIC_SPI 766 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart1_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI01_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <256>;
+				status = "disabled";
+			};
+		};
+
+		usi_2: usi at 108c00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108c00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1010>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI02_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_2: serial at 108c0000 {
+			compatible = "samsung,exynosautov920-uart",
+				     "samsung,exynos850-uart";
+				reg = <0x108c0000 0xc0>;
+				interrupts = <GIC_SPI 768 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart2_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI02_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_3: usi at 108e00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108e00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1018>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI03_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_3: serial at 108e0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x108e0000 0xc0>;
+				interrupts = <GIC_SPI 770 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart3_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI03_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_4: usi at 109000c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109000c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1020>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI04_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_4: serial at 10900000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10900000 0xc0>;
+				interrupts = <GIC_SPI 772 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart4_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI04_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_5: usi at 109200c0 {
+				compatible = "samsung,exynosautov920-usi",
+					     "samsung,exynos850-usi";
+				reg = <0x109200c0 0x20>;
+				samsung,sysreg = <&syscon_peric0 0x1028>;
+				samsung,mode = <USI_V2_UART>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI05_USI>;
+				clock-names = "pclk", "ipclk";
+				status = "disabled";
+
+			serial_5: serial at 10920000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10920000 0xc0>;
+				interrupts = <GIC_SPI 774 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart5_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI05_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_6: usi at 109400c0 {
+				compatible = "samsung,exynosautov920-usi",
+					     "samsung,exynos850-usi";
+			reg = <0x109400c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1030>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI06_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_6: serial at 10940000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10940000 0xc0>;
+				interrupts = <GIC_SPI 776 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart6_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI06_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_7: usi at 109600c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109600c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1038>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI07_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_7: serial at 10960000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10960000 0xc0>;
+				interrupts = <GIC_SPI 778 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart7_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI07_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_8: usi at 109800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109800c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1040>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI08_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_8: serial at 10980000 {
+			compatible = "samsung,exynosautov920-uart",
+				     "samsung,exynos850-uart";
+				reg = <0x10980000 0xc0>;
+				interrupts = <GIC_SPI 780 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart8_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI08_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_9: usi at 10c800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10c800c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1000>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI09_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_9: serial at 10c8000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10c80000 0xc0>;
+				interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart9_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI09_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <256>;
+				status = "disabled";
+			};
+		};
+
+		usi_10: usi at 10ca00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10ca00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1008>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI10_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_10: serial at 10ca0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10ca0000 0xc0>;
+				interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart10_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI10_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_11: usi at 10cc00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10cc00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1010>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI11_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_11: serial at 10cc0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10cc0000 0xc0>;
+				interrupts = <GIC_SPI 791 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart11_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI11_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_12: usi at 10ce00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10ce00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1018>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI12_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_12: serial at 10ce0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10ce0000 0xc0>;
+				interrupts = <GIC_SPI 793 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart12_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI12_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_13: usi at 10d000c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d000c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1020>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI13_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_13: serial at 10d00000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d00000 0xc0>;
+				interrupts = <GIC_SPI 795 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart13_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI13_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_14: usi at 10d200c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d200c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1028>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI14_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_14: serial at 10d20000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d20000 0xc0>;
+				interrupts = <GIC_SPI 797 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart14_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI14_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_15: usi at 10d400c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d400c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1030>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI15_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_15: serial at 10d40000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d40000 0xc0>;
+				interrupts = <GIC_SPI 799 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart15_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI15_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_16: usi at 10d600c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d600c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1038>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI16_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_16: serial at 10d60000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d60000 0xc0>;
+				interrupts = <GIC_SPI 801 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart16_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI16_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_17: usi at 10d800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d800c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1040>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_17: serial at 10d80000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d80000 0xc0>;
+				interrupts = <GIC_SPI 803 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart17_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+
 		pwm: pwm at 109b0000 {
 			compatible = "samsung,exynosautov920-pwm",
 				     "samsung,exynos4210-pwm";
-- 
2.34.1



From nichen at iscas.ac.cn  Wed Mar 12 00:37:29 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Wed, 12 Mar 2025 15:37:29 +0800
Subject: [PATCH] power: supply: mt6370: Remove redundant 'flush_workqueue()' calls
Message-ID: <20250312073729.1430053-1-nichen@iscas.ac.cn>

'destroy_workqueue()' already drains the queue before destroying it, so
there is no need to flush it explicitly.

Remove the redundant 'flush_workqueue()' calls.

This was generated with coccinelle:

@@
expression E;
@@
- flush_workqueue(E);
  destroy_workqueue(E);

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
 drivers/power/supply/mt6370-charger.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/power/supply/mt6370-charger.c b/drivers/power/supply/mt6370-charger.c
index a6939c6059c7..98579998b300 100644
--- a/drivers/power/supply/mt6370-charger.c
+++ b/drivers/power/supply/mt6370-charger.c
@@ -772,7 +772,6 @@ static void mt6370_chg_destroy_wq(void *data)
 {
 	struct workqueue_struct *wq = data;
 
-	flush_workqueue(wq);
 	destroy_workqueue(wq);
 }
 
-- 
2.25.1



From shawnguo2 at yeah.net  Wed Mar 12 00:40:05 2025
From: shawnguo2 at yeah.net (Shawn Guo)
Date: Wed, 12 Mar 2025 15:40:05 +0800
Subject: [GIT PULL 5/5] i.MX arm64 device tree changes for 6.15
In-Reply-To: <20250312074005.663165-1-shawnguo2@yeah.net>
References: <20250312074005.663165-1-shawnguo2@yeah.net>
Message-ID: <20250312074005.663165-5-shawnguo2@yeah.net>

From: Shawn Guo <shawnguo at kernel.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-dt64-6.15

for you to fetch changes up to 5a690619426fc4b09c7fd3f40d3a69264ef3db0f:

  arm64: dts: imx8qm-apalis: Remove compatible from SoM dtsi (2025-03-11 11:16:30 +0800)

----------------------------------------------------------------
i.MX arm64 device tree changes for 6.15:

- New board support: S32G-EVB/RDB, i.MX95 15x15 EVK, i.MX8MP Skov
  revC BD500 and new 7" panel board, i.MX8MM phyboard polis PEB-AV-10
- A series from Ahmad Fatoum and Oleksij Rempel to flesh out
  imx8mp-skov device trees, correcting PMIC board limits, adding display
  pipeline, configuring uart1 for RS485, etc.
- A bunch of changes from Alexander Stein, adding PCIe support for
  mba8xx, enabling jpeg encode and decode for tqma8xx, adding vcc-supply
  for spi-nor, etc.
- A series from Chancel Liu to complete WM8960 power supplies for NXP
  i.MX8 based boards
- A dozen of changes from Frank Li, enabling audio codec for imx8qm-mek,
  adding PCIe EP for i.MX8Q, improving i.MX93 and i.MX95 support, etc.
- A number of changes from Frieder Schrempf to support reading SD_VSEL
  signal for imx8m-kontron devices, fix SD card IO voltage control for
  imx93-kontron
- A series from Teresa Remmet to improve imx8mm-phycore support, keeping
  LDO3 on in suspend, adding overlays for devices without Ethernet PHY,
  SPI NOR Flash, etc.
- A couple of changes from Xu Yang to enable usb3 support for
  imx95-19x19-evk board
- Other random improvements and cleanups on various boards

----------------------------------------------------------------
Ahmad Fatoum (12):
      arm64: dts: imx8mp-skov: correct PMIC board limits
      arm64: dts: imx8mp-skov: operate CPU at 850 mV by default
      arm64: dts: imx8mp-skov: use I2C5 for DDC
      arm64: dts: imx8mp-skov: configure uart1 for RS485
      arm64: dts: imx8mp: Add optional nominal drive mode DTSI
      arm64: dts: imx8mp: add fsl,nominal-mode property into nominal.dtsi
      arm64: dts: freescale: imx8mp-skov: configure LDB clock automatically
      arm64: dts: freescale: imx8mp-skov: operate SoC in nominal mode
      arm64: dts: imx8mp-skov: move I2C2 pin control group into DTSI
      arm64: dts: imx8mp-skov: describe I2C bus recovery for all controllers
      arm64: dts: imx8mp-skov: add revC BD500 board
      arm64: dts: imx8mp-skov: support new 7" panel board

Alexander Stein (14):
      arm64: dts: imx8-ss-hsio: Wire up DMA IRQ for PCIe
      arm64: dts: tqma8xx: Add vcc-supply for spi-nor
      arm64: dts: tqma8xx: enable jpeg encode and decode
      arm64: dts: tqma8xx: Remove GPU TODO
      arm64: dts: mba8xx: Add PCIe support
      arm64: dts: freescale: imx93-tqma9352-mba93xxca: sort pinctrl nodes
      arm64: dts: mba93xxca: Do not assert power-down pins
      arm64: dts: tqma9352-mba93xx[cl]a: swap ethernet aliases
      arm64: dts: freescale: tqma8mpql: Add vcc-supply for spi-nor
      arm64: dts: freescale: tqma8mq: Add vcc-supply for spi-nor
      arm64: dts: freescale: tqma8mqml: Add vcc-supply for spi-nor
      arm64: dts: freescale: tqma8mqnl: Add vcc-supply for spi-nor
      arm64: dts: imx8qm-ss-hsio: Wire up DMA IRQ for PCIe
      arm64: dts: mba8xx: Remove invalid property disable-gpio

Andrej Picej (3):
      arm64: dts: imx8mm-phycore-som: Fix bluetooth wakeup source
      arm64: dts: imx8mm-phyboard-polis: Set RTC as wakeup-source
      arm64: dts: imx8mm-phygate-tauri-l: Set RTC as wakeup-source

Chancel Liu (4):
      arm64: dts: imx8mp-evk: Complete WM8960 power supplies
      arm64: dts: imx8dxl-evk: Complete WM8960 power supplies
      arm64: dts: imx8qm-mek: Complete WM8960 power supplies
      arm64: dts: imx8qxp-mek: Complete WM8960 power supplies

Ciprian Marian Costea (4):
      arm64: dts: s32g: add I2C[0..2] support for s32g2 and s32g3
      arm64: dts: s32g: add common 'S32G-EVB' and 'S32G-RDB' board support
      arm64: dts: s32g399a-rdb3: Add INA231 sensor entry over I2C4
      arm64: dts: s32g: add FlexCAN[0..3] support for s32g2 and s32g3

Dominik Haller (1):
      arm64: dts: imx8mm-phycore-som: Add overlay for rproc

Fabio Estevam (1):
      arm64: dts: imx8mn-bsh-smm-s2pro: Remove invalid audio codec clock

Francesco Dolcini (2):
      arm64: dts: freescale: imx8mm-verdin: Remove LVDS panel and backlight
      arm64: dts: imx8qm-apalis: Remove compatible from SoM dtsi

Frank Li (12):
      arm64: dts: imx8mq-librem5: remove undocument property 'extcon' for usb-pd at 3f
      arm64: dts: imx8qm-mek: add audio-codec cs42888 and related nodes
      arm64: dts: imx8-ss-hsio: fix indentation in pcie node
      arm64: dts: imx8q: add PCIe EP for i.MX8QM and i.MX8QXP
      arm64: dts: imx8q: add PCIe EP overlay file for i.MX8QXP mek board
      arm64: dts: imx95: add PCIe's msi-map and iommu-map property
      arm64: dts: imx95: Add #io-channel-cells = <1> for adc node
      arm64: dts: imx95: Add i3c1 and i3c2
      arm64: dts: imx95: Add imx95-15x15-evk support
      arm64: dts: im8mq-librem5: move dwc3 usb port under ports
      arm64: dts: imx95: add ref clock for pcie nodes
      arm64: dts: imx93: add ddr edac support

Frieder Schrempf (3):
      arm64: dts: imx8mm-kontron: Add support for reading SD_VSEL signal
      arm64: dts: imx93-kontron: Fix SD card IO voltage control
      arm64: dts: imx8mp-kontron: Add support for reading SD_VSEL signal

Janine Hagemann (1):
      arm64: dts: imx8mm-phyboard-polis: Add overlay for PEB-EVAL-01

Larisa Grigore (1):
      arm64: dts: s32g: add the eDMA nodes

Laurentiu Mihalcea (2):
      arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to AUDIOMIX block
      arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT freq. to 800MHz

Lucas Stach (1):
      arm64: dts: imx8mp: configure GPU and NPU clocks to overdrive rate

Markus Niebel (2):
      arm64: dts: imx8mp-tqma8mpql-mba8mpxl: change sound card model name
      arm64: dts: mba8mx: change sound card model name

Mathew McBride (1):
      arm64: dts: freescale: ten64: add usb hub definition

Oleksij Rempel (6):
      arm64: dts: imx8mp-skov: describe HDMI display pipeline
      arm64: dts: imx8mp-skov: describe LVDS display pipeline
      arm64: dts: imx8mp-skov: describe mains fail detection
      arm64: dts: imx8mp-skov: fix phy-mode
      arm64: dts: imx8mp-skov: increase I2C clock frequency for RTC
      arm64: dts: imx8mp-skov: add basic board as fallback

Rafael Beims (1):
      arm64: dts: colibri-imx8x: Add missing gpio-line-names

Stefan Eichenberger (1):
      arm64: dts: imx8-apalis: add clock configuration for 44.1 kHz hdmi audio

Teresa Remmet (5):
      arm64: dts: imx8mm-phycore-som: Keep LDO3 on in suspend
      arm64: dts: imx8mm-phycore-som: Remove magic-packet property
      arm64: dts: imx8mm-phyboard-polis: Add support for PEB-AV-10
      arm64: dts: imx8mm-phycore-som: Add no-eth phy overlay
      arm64: dts: imx8mm-phycore-som: Add overlay to disable SPI NOR flash

Xu Yang (2):
      arm64: dts: imx95: add usb3 related nodes
      arm64: dts: imx95-19x19-evk: add typec nodes and enable usb3 node

Yannic Moog (3):
      arm64: dts: imx8mm-phycore-som: add descriptions to nodes
      arm64: dts: imx8mm-phyboard-polis: add RTC description
      arm64: dts: imx8mm: move bulk of rtc properties to carrierboards

Yashwanth Varakala (2):
      arm64: dts: imx8mm-phycore-som: Assign regulator for dsi to lvds bridge
      arm64: dts: imx8mm-phyboard-polis: Assign missing regulator for bluetooth

 arch/arm64/boot/dts/freescale/Makefile             |   21 +
 .../arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts |   44 +
 .../arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi |   16 +
 arch/arm64/boot/dts/freescale/imx8-ss-hsio.dtsi    |   30 +-
 arch/arm64/boot/dts/freescale/imx8dxl-evk.dts      |   42 +
 .../arm64/boot/dts/freescale/imx8mm-kontron-bl.dts |   10 +-
 .../boot/dts/freescale/imx8mm-kontron-osm-s.dtsi   |    7 +-
 .../freescale/imx8mm-phyboard-polis-peb-av-10.dtso |  237 ++++
 .../imx8mm-phyboard-polis-peb-eval-01.dtso         |   72 ++
 .../dts/freescale/imx8mm-phyboard-polis-rdk.dts    |   17 +-
 .../boot/dts/freescale/imx8mm-phycore-no-eth.dtso  |   12 +
 .../dts/freescale/imx8mm-phycore-no-spiflash.dtso  |   16 +
 .../boot/dts/freescale/imx8mm-phycore-rpmsg.dtso   |   58 +
 .../boot/dts/freescale/imx8mm-phycore-som.dtsi     |   22 +-
 .../boot/dts/freescale/imx8mm-phygate-tauri-l.dts  |   11 +
 .../arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi |    1 +
 arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi   |   21 -
 .../boot/dts/freescale/imx8mn-bsh-smm-s2pro.dts    |    1 -
 .../arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi |    1 +
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts       |   22 +
 .../boot/dts/freescale/imx8mp-kontron-osm-s.dtsi   |    7 +-
 arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi  |   64 ++
 .../arm64/boot/dts/freescale/imx8mp-skov-basic.dts |   10 +
 .../arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi |  126 ++-
 .../boot/dts/freescale/imx8mp-skov-revb-hdmi.dts   |   45 +-
 .../boot/dts/freescale/imx8mp-skov-revb-lt6.dts    |   60 ++
 .../freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts  |   30 +-
 .../boot/dts/freescale/imx8mp-skov-revc-bd500.dts  |   91 ++
 .../dts/freescale/imx8mp-skov-revc-tian-g07017.dts |   81 ++
 .../dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts    |    2 +-
 .../arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi |    1 +
 arch/arm64/boot/dts/freescale/imx8mp.dtsi          |   23 +-
 .../boot/dts/freescale/imx8mq-librem5-devkit.dts   |   25 +-
 arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi  |   26 +-
 arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi  |    1 +
 .../boot/dts/freescale/imx8qm-apalis-v1.1.dtsi     |    2 -
 arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi   |    2 -
 arch/arm64/boot/dts/freescale/imx8qm-mek.dts       |  112 ++
 arch/arm64/boot/dts/freescale/imx8qm-ss-hsio.dtsi  |   24 +-
 .../boot/dts/freescale/imx8qxp-mek-pcie-ep.dtso    |   22 +
 arch/arm64/boot/dts/freescale/imx8qxp-mek.dts      |   32 +
 arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi   |    4 +-
 .../boot/dts/freescale/imx93-kontron-osm-s.dtsi    |    5 +-
 .../dts/freescale/imx93-tqma9352-mba93xxca.dts     |   54 +-
 .../dts/freescale/imx93-tqma9352-mba93xxla.dts     |    6 +-
 arch/arm64/boot/dts/freescale/imx93.dtsi           |    8 +
 arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts  | 1130 ++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts  |   83 ++
 arch/arm64/boot/dts/freescale/imx95.dtsi           |  108 +-
 arch/arm64/boot/dts/freescale/mba8mx.dtsi          |    2 +-
 arch/arm64/boot/dts/freescale/mba8xx.dtsi          |   31 +-
 arch/arm64/boot/dts/freescale/s32g2.dtsi           |  141 +++
 arch/arm64/boot/dts/freescale/s32g274a-evb.dts     |    1 +
 arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts    |    1 +
 arch/arm64/boot/dts/freescale/s32g3.dtsi           |  150 +++
 arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts    |    9 +
 arch/arm64/boot/dts/freescale/s32gxxxa-evb.dtsi    |  222 ++++
 arch/arm64/boot/dts/freescale/s32gxxxa-rdb.dtsi    |  170 +++
 arch/arm64/boot/dts/freescale/tqma8xx.dtsi         |   12 +-
 59 files changed, 3397 insertions(+), 187 deletions(-)
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-eval-01.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-phycore-no-eth.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-phycore-no-spiflash.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-phycore-rpmsg.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-nominal.dtsi
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-skov-basic.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-skov-revc-bd500.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-skov-revc-tian-g07017.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx8qxp-mek-pcie-ep.dtso
 create mode 100644 arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts
 create mode 100644 arch/arm64/boot/dts/freescale/s32gxxxa-evb.dtsi
 create mode 100644 arch/arm64/boot/dts/freescale/s32gxxxa-rdb.dtsi



From andyshrk at 163.com  Wed Mar 12 01:00:07 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 16:00:07 +0800
Subject: [PATCH v2] phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the corresponding set flags are set
Message-ID: <20250312080041.524546-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

According documentation of phy_configure_opts_dp, at the configure
stage, link rates should only be verify/configure when set_rate
flag is set, the same applies to lanes and voltage.

So do it as the documentation says.
Because voltage setting depends on the lanes, link rates set
previously, so record the link rates and lanes at it's verify stage.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>

---

Changes in v2:
- Make each check of link_rates/lanes/voltages helper functions
- Refactor commit message

 drivers/phy/rockchip/phy-rockchip-usbdp.c | 87 ++++++++++++++---------
 1 file changed, 53 insertions(+), 34 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index c04cf64f8a35..fff04e0fbd80 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -187,6 +187,8 @@ struct rk_udphy {
 	u32 dp_aux_din_sel;
 	bool dp_sink_hpd_sel;
 	bool dp_sink_hpd_cfg;
+	unsigned int link_rate;
+	unsigned int lanes;
 	u8 bw;
 	int id;
 
@@ -1102,15 +1104,19 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
 	return 0;
 }
 
-static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
+/*
+ * Verify link rate
+ */
+static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy,
+					    struct phy_configure_opts_dp *dp)
 {
-	switch (link_rate) {
+	switch (dp->link_rate) {
 	case 1620:
 	case 2700:
 	case 5400:
 	case 8100:
+		udphy->link_rate = dp->link_rate;
 		break;
-
 	default:
 		return -EINVAL;
 	}
@@ -1118,45 +1124,44 @@ static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
 	return 0;
 }
 
-static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
-					 struct phy_configure_opts_dp *dp)
+static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy,
+					struct phy_configure_opts_dp *dp)
 {
-	int i, ret;
-
-	/* If changing link rate was required, verify it's supported. */
-	ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
-	if (ret)
-		return ret;
-
-	/* Verify lane count. */
 	switch (dp->lanes) {
 	case 1:
 	case 2:
 	case 4:
 		/* valid lane count. */
+		udphy->lanes = dp->lanes;
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
-	/*
-	 * If changing voltages is required, check swing and pre-emphasis
-	 * levels, per-lane.
-	 */
-	if (dp->set_voltages) {
-		/* Lane count verified previously. */
-		for (i = 0; i < dp->lanes; i++) {
-			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
-				return -EINVAL;
+	return 0;
+}
 
-			/*
-			 * Sum of voltage swing and pre-emphasis levels cannot
-			 * exceed 3.
-			 */
-			if (dp->voltage[i] + dp->pre[i] > 3)
-				return -EINVAL;
-		}
+/*
+ * If changing voltages is required, check swing and pre-emphasis
+ * levels, per-lane.
+ */
+static int rk_udphy_dp_phy_verify_voltages(struct rk_udphy *udphy,
+					   struct phy_configure_opts_dp *dp)
+{
+	int i;
+
+	/* Lane count verified previously. */
+	for (i = 0; i < udphy->lanes; i++) {
+		if (dp->voltage[i] > 3 || dp->pre[i] > 3)
+			return -EINVAL;
+
+		/*
+		 * Sum of voltage swing and pre-emphasis levels cannot
+		 * exceed 3.
+		 */
+		if (dp->voltage[i] + dp->pre[i] > 3)
+			return -EINVAL;
 	}
 
 	return 0;
@@ -1196,9 +1201,23 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
 	u32 i, val, lane;
 	int ret;
 
-	ret = rk_udphy_dp_phy_verify_config(udphy, dp);
-	if (ret)
-		return ret;
+	if (dp->set_rate) {
+		ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp);
+		if (ret)
+			return ret;
+	}
+
+	if (dp->set_lanes) {
+		ret = rk_udphy_dp_phy_verify_lanes(udphy, dp);
+		if (ret)
+			return ret;
+	}
+
+	if (dp->set_voltages) {
+		ret = rk_udphy_dp_phy_verify_voltages(udphy, dp);
+		if (ret)
+			return ret;
+	}
 
 	if (dp->set_rate) {
 		regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
@@ -1243,9 +1262,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
 	}
 
 	if (dp->set_voltages) {
-		for (i = 0; i < dp->lanes; i++) {
+		for (i = 0; i < udphy->lanes; i++) {
 			lane = udphy->dp_lane_sel[i];
-			switch (dp->link_rate) {
+			switch (udphy->link_rate) {
 			case 1620:
 			case 2700:
 				regmap_update_bits(udphy->pma_regmap,
-- 
2.34.1



From tzimmermann at suse.de  Wed Mar 12 01:17:46 2025
From: tzimmermann at suse.de (Thomas Zimmermann)
Date: Wed, 12 Mar 2025 09:17:46 +0100
Subject: [RESEND PATCH v3] drm/mxsfb: Remove generic DRM drivers in probe
 function
In-Reply-To: <20250305140929.174398-1-dario.binacchi@amarulasolutions.com>
References: <20250305140929.174398-1-dario.binacchi@amarulasolutions.com>
Message-ID: <41c4b56d-0932-465c-9dc7-c3a20cb49bdb@suse.de>

Merged into drm-misc-next. Thanks for the patch.

Am 05.03.25 um 15:09 schrieb Dario Binacchi:
> Use aperture helpers to remove all generic graphics drivers before
> loading mxsfb. Makes mxsfb compatible with simpledrm.
>
> Co-developed-by: Michael Trimarchi <michael at amarulasolutions.com>
> Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
> Reviewed-by: Thomas Zimmermann <tzimmermann at suse.de>
>
> ---
>
> Changes in v3:
> - Add 'Reviewed-by' of  Thomas Zimmermann
>
> Changes in v2:
> - Use aperture_remove_all_conflicting_devices() instead of
>    drm_aperture_remove_framebuffers().
>
>   drivers/gpu/drm/mxsfb/mxsfb_drv.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 59020862cf65..e5eb644b54ae 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -8,6 +8,7 @@
>    * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
>    */
>   
> +#include <linux/aperture.h>
>   #include <linux/clk.h>
>   #include <linux/dma-mapping.h>
>   #include <linux/io.h>
> @@ -361,6 +362,15 @@ static int mxsfb_probe(struct platform_device *pdev)
>   	if (ret)
>   		goto err_free;
>   
> +	/*
> +	 * Remove early framebuffers (ie. simplefb). The framebuffer can be
> +	 * located anywhere in RAM
> +	 */
> +	ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "can't kick out existing framebuffers\n");
> +
>   	ret = drm_dev_register(drm, 0);
>   	if (ret)
>   		goto err_unload;

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)



From maz at kernel.org  Wed Mar 12 01:21:48 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 12 Mar 2025 08:21:48 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>
	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<86r033olwv.wl-maz@kernel.org>
	<SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
Message-ID: <87tt7y7j6r.wl-maz@kernel.org>

On Tue, 11 Mar 2025 12:07:20 +0000,
Ankit Agrawal <ankita at nvidia.com> wrote:
> 
> Thanks Marc for the feedback.
> 
> > No, I'm concerned that a well established API (populating a memslot)
> > works in some case and doesn't work in another without a clear
> > indication of *why* we have this behaviour.
> >
> > To me, this indicates that userspace needs to buy in this new
> > behaviour, and that behaviour needs to be advertised by a capability,
> > which is in turn conditional on FWB.
> 
> Yes, that makes sense.
> 
> >>> Perhaps we can gracefully fall back to the default device mapping
> >>> in such case? But that would cause VM to crash as soon as it makes some
> >>> access violating DEVICE_nGnRE.
> >
> > Which would now be a regression...
> > 
> > My take is that this cacheable PNFMAP contraption must only be exposed
> > to a guest if FWB is available. We can't prevent someone to do an
> > mmap() behind our back, but we can at least:
> >
> > - tell userspace whether this is supported
> 
> For my education, what is an accepted way to communicate this? Please let
> me know if there are any relevant examples that you may be aware of.

A KVM capability is what is usually needed.

> 
> I suppose just checking for FWB (for PFNMAP) and returning some sort of
> an error on userspace mmap will not be enough of a hint here?

I don't think checking for FWB at mmap() time is correct. mmap()
shouldn't care about FWB at all, because stage-2 is irrelevant to
mmap(). You also want to be able t perform the same mmap() inside an
EL1 guest, which by definition cannot consider FWB.

This must be checked at the point of memslot creation, and return an
error at that point. Memslots are all about stage-2, so it makes sense
to check it there.

	M.

-- 
Without deviation from the norm, progress is not possible.


From l.stach at pengutronix.de  Wed Mar 12 01:28:02 2025
From: l.stach at pengutronix.de (Lucas Stach)
Date: Wed, 12 Mar 2025 09:28:02 +0100
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
 hardcodes
In-Reply-To: <DU2PR04MB8677AC699DF11D847AB768708CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>
References: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>
	 <20250311155452.GA629749@bhelgaas>
	 <DU2PR04MB8677AC699DF11D847AB768708CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>
Message-ID: <fcb5f09f8e4311c7a6ef60aaf3cb4e3f05a8f05e.camel@pengutronix.de>

Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > -----Original Message-----
> > From: Bjorn Helgaas <helgaas at kernel.org>
> > Sent: 2025?3?11? 23:55
> > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > hardcodes
> > 
> > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > -----Original Message-----
> > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > Sent: 2025?3?10? 23:11
> > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > bhelgaas at google.com;
> > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > hardcodes
> > > > 
> > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > 
> > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > ---
> > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > @@ -41,7 +41,6 @@
> > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > 8)
> > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > 
> > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > platform_device
> > > > *pdev)
> > > > > ?	struct dw_pcie *pci;
> > > > > ?	struct imx_pcie *imx_pcie;
> > > > > ?	struct device_node *np;
> > > > > -	struct resource *dbi_base;
> > > > > ?	struct device_node *node = dev->of_node;
> > > > > ?	int i, ret, req_cnt;
> > > > > ?	u16 val;
> > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > platform_device *pdev)
> > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > ?	}
> > > > > 
> > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > 0,
> > > > &dbi_base);
> > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > -		return PTR_ERR(pci->dbi_base);
> > > > 
> > > > This makes me wonder.
> > > > 
> > > > IIUC this means that previously we set controller_id to 1 if the
> > > > first item in devicetree "reg" was 0x33c00000, and now we will set
> > > > controller_id to 1 if the devicetree "linux,pci-domain" property is 1.
> > > > This is good, but I think this new dependency on the correct
> > > > "linux,pci-domain" in devicetree should be mentioned in the commit log.
> > > > 
> > > > My bigger worry is that we no longer set pci->dbi_base at all.  I
> > > > see that the only use of pci->dbi_base in pci-imx6.c was to
> > > > determine the controller_id, but this is a DWC-based driver, and the
> > > > DWC core certainly uses
> > > > pci->dbi_base.  Are we sure that none of those DWC core paths are
> > > > important to pci-imx6.c?
> > > Hi Bjorn:
> > > Thanks for your concerns.
> > > Don't worry about the assignment of pci->dbi_base.
> > > If pci-imx6.c driver doesn't set it. DWC core driver would set it when
> > > ?dw_pcie_get_resources() is invoked.
> > 
> > Great, thanks!  Maybe we can amend the commit log to mention that and
> > the new "linux,pci-domain" dependency.
> How about the following updates of the commit log?
> 
> Use the domain number replace the hardcodes to uniquely identify
> different controller on i.MX8MQ platforms. No function changes.
> Please make sure the " linux,pci-domain" is set for i.MX8MQ correctly, since
> ?the controller id is relied on it totally.
> 
This breaks running a new kernel on an old DT without the
linux,pci-domain property, which I'm absolutely no fan of. We tried
really hard to keep this way around working in the i.MX world.

I'm fine with using the property if present and even mandating it for
new platforms, but getting rid of the existing code for the i.MX8MQ
platform is only a marginal cleanup of the driver code with the obvious
downside of the above breakage.

Regards,
Lucas


From maz at kernel.org  Wed Mar 12 01:38:43 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 12 Mar 2025 08:38:43 +0000
Subject: [PATCH v3 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <20250307113411.469018-2-vdonnefort@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
	<20250307113411.469018-2-vdonnefort@google.com>
Message-ID: <87r0327iek.wl-maz@kernel.org>

On Fri, 07 Mar 2025 11:34:09 +0000,
Vincent Donnefort <vdonnefort at google.com> wrote:
> 
> Add flags to kvm_hyp_memcache and propagate the latter to the allocation
> and free callbacks. This will later allow to account for memory, based
> on the memcache configuration.
> 
> Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 3a7ec98ef123..12691ae23d4c 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -86,6 +86,7 @@ struct kvm_hyp_memcache {
>  	phys_addr_t head;
>  	unsigned long nr_pages;
>  	struct pkvm_mapping *mapping; /* only used from EL1 */
> +	unsigned long flags;
>  };
>  
>  static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 1f55b0c7b11d..c01ad4430729 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1086,12 +1086,12 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
>  	}
>  }
>  
> -static void hyp_mc_free_fn(void *addr, void *unused)
> +static void hyp_mc_free_fn(void *addr, void *mc)
>  {
>  	free_page((unsigned long)addr);
>  }
>  
> -static void *hyp_mc_alloc_fn(void *unused)
> +static void *hyp_mc_alloc_fn(void *mc)
>  {
>  	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
>  }
> @@ -1102,7 +1102,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
>  		return;
>  
>  	kfree(mc->mapping);
> -	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
> +	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, (void *)mc);

Why the cast? It looks superfluous to me.

>  }
>  
>  int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
> @@ -1117,7 +1117,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
>  	}
>  
>  	return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
> -				    kvm_host_pa, NULL);
> +				    kvm_host_pa, (void *)mc);

Same here.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From piotr.oniszczuk at gmail.com  Wed Mar 12 01:46:51 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Wed, 12 Mar 2025 09:46:51 +0100
Subject: [PATCH] drm/rockchip: vop2: Fix interface enable/mux setting of
 DP1 on rk3588
In-Reply-To: <20250312064218.524143-1-andyshrk@163.com>
References: <20250312064218.524143-1-andyshrk@163.com>
Message-ID: <695656A7-BF2A-4031-A9BE-659C27F311DE@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 12 mar 2025, o godz. 07:42:
> 
> copy-paste error, which affects DP1 usage


Andy,

Great finding.
Now i see nice screen on rock5itx on dpi1 out :-)

With this: my users are politely asking: when we wili have audio (and cec) support on dpi1? 




From csokas.bence at prolan.hu  Wed Mar 12 01:53:04 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Wed, 12 Mar 2025 09:53:04 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <885ceb3e-d6c6-4e7b-a3b6-585d2d110ccf@web.de>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
 <885ceb3e-d6c6-4e7b-a3b6-585d2d110ccf@web.de>
Message-ID: <81f87d39-d3f8-4b6a-91cb-b0177d34171b@prolan.hu>

Dear Markus,

On 2025. 03. 11. 20:33, Markus Elfring wrote:
 >> Clean up error handling by using devm functions
 >> and dev_err_probe(). This should make it easier
 > ?
 >
 > You may occasionally put more than 47 characters into text lines
 > of such a change description.

It was an old patch I hadn't yet reformatted to 75 cols. I used 50-60 
cols before, because my mail client's preview panel is very narrow, so 
anything more than ~65 characters will wrap. If there will be a v5, I'll 
reformat it to 75 cols as well, as per the style guidelines.

> How good does such a change combination fit to the patch requirement
> according to separation of concerns?
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc6#n81

It is a general refactor patch, it shouldn't change any functionality. I 
could split it to one part introducing `devm_clk_get_enabled()` and the 
other `dmaenginem_async_device_register()`, but I don't feel that to be 
necessary, nor does it bring any advantages I believe.

> Regards,
> Markus

Bence



From krzk at kernel.org  Wed Mar 12 01:54:14 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 09:54:14 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
Message-ID: <78f6091c-1630-48c2-93e6-71f2cdbe63c5@kernel.org>

On 11/03/2025 19:02, Christopher Obbard wrote:
> Currently some Qualcomm interconnect drivers are enabled
> as modules which isn't overly useful since the interconnects
> are required to be loaded during early boot.
> 
> Loading the interconnects late (e.g. in initrd or as module)
> can cause boot issues, such as slowdown or even not booting
> at all (since the interconnect would be required for storage
> devices).
> 
> Be consistent and enable all of the Qualcomm interconnect
> drivers as built-in to the kernel image.


I don't agree. If you want consistency, fix booting process and make
everything module. We switch them to builtin on exception, so come with
reasoning for given exceptions instead of making exceptions the new normal.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 12 01:56:05 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 09:56:05 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
Message-ID: <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org>

On 11/03/2025 20:15, Christopher Obbard wrote:
> Hi Dmitry,
> 
> On Tue, 11 Mar 2025 at 19:58, Dmitry Baryshkov <lumag at kernel.org> wrote:
>>
>> On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
>>> I sent this patch to start the discussion, some things I found:
>>>
>>> 1) Some interconnects are missing from arm defconfig. Should they be =y too ?
>>
>> No, unless those are required for the UART console.
> 
> OK, that makes sense. FWIW the cryptic (to me, at least) commit log on
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eee808134ecf1c1093ff1ddfc056dc5e469d0c3
> made me think that the interconnects should be built-in on all devices.
> 
> Of course, the real problem here is RB3gen2 not actually finding the
> UFS/eMMC device due to no interconnect driver.
> Until now, I have been building that into the kernel. I will
> investigate instead shoving into the initrd (in both debian and
> fedora) which should solve my issue and render this patchset useless.

For Qualcomm platforms you are expected to always have initramfs, thus
you will have the modules for UFS/eMMC mounts. I don't understand the
problem which you were trying to solve.

The interconnects were built in *only* because of need for serial
console. Only.

Best regards,
Krzysztof


From maz at kernel.org  Wed Mar 12 01:59:15 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 12 Mar 2025 08:59:15 +0000
Subject: [PATCH v3 2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
In-Reply-To: <20250307113411.469018-3-vdonnefort@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
	<20250307113411.469018-3-vdonnefort@google.com>
Message-ID: <87plim7hgc.wl-maz@kernel.org>

On Fri, 07 Mar 2025 11:34:10 +0000,
Vincent Donnefort <vdonnefort at google.com> wrote:
> 
> In order to account for memory dedicated to the stage-2 page-tables, use
> a separated memcache when tearing down the VM.
> 
> Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 12691ae23d4c..ace3969e8106 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
>  struct kvm_protected_vm {
>  	pkvm_handle_t handle;
>  	struct kvm_hyp_memcache teardown_mc;
> +	struct kvm_hyp_memcache stage2_teardown_mc;
>  	bool enabled;
>  };
>  
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index 3927fe52a3dd..15f8d5315959 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
>  
>  int __pkvm_teardown_vm(pkvm_handle_t handle)
>  {
> -	struct kvm_hyp_memcache *mc;
> +	struct kvm_hyp_memcache *mc, *stage2_mc;
>  	struct pkvm_hyp_vm *hyp_vm;
>  	struct kvm *host_kvm;
>  	unsigned int idx;
> @@ -706,7 +706,8 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
>  
>  	/* Reclaim guest pages (including page-table pages) */
>  	mc = &host_kvm->arch.pkvm.teardown_mc;
> -	reclaim_guest_pages(hyp_vm, mc);
> +	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
> +	reclaim_guest_pages(hyp_vm, stage2_mc);

This looks odd. What counts as stage-2 pages here? Or is it that
reclaim_guest_pages() is very badly named?

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From nbd at nbd.name  Wed Mar 12 02:09:48 2025
From: nbd at nbd.name (Felix Fietkau)
Date: Wed, 12 Mar 2025 10:09:48 +0100
Subject: [PATCH v1] mt76: mt7915: wed: find rx token by physical address
In-Reply-To: <e144d2ffe9924d81a7b60f38cdcf516a@realtek.com>
References: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <TYCPR01MB843726907C170CFE2D3EB7BE98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <e144d2ffe9924d81a7b60f38cdcf516a@realtek.com>
Message-ID: <1c46870f-965b-4f70-a01b-adbcd60c2876@nbd.name>

On 12.03.25 02:41, Ping-Ke Shih wrote:
> Shengyu Qu <wiagn233 at outlook.com> wrote:
>> 
>> Hi Shih,
>> 
>> Can you also give this patch a review? Seems I also need to convert to
>> reverse Xmas tree order for this patch, will do it in next version.
> 
> Yes. Please do it.
> 
>> 
>> Best regards,
>> Shengyu
>> 
>> ? 2025/2/22 19:38, Shengyu Qu ??:
>> > The token id in RxDMAD may be incorrect when it is not the last frame
>> > due to WED HW bug. Lookup correct token id by physical address in sdp0.
>> >
>> > Downstream patch link:
>> https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/737340322ab22b138fd200e02
>> 0d61ffdbe3e36a9/autobuild/autobuild_5.4_mac80211_release/mt7988_wifi7_mac80211_mlo/package/kernel/mt76
>> /patches/0062-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
>> >
>> > Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
>> > Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
>> > ---
>> >   drivers/net/wireless/mediatek/mt76/dma.c | 25 +++++++++++++++++++++++-
>> >   1 file changed, 24 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
>> > index 844af16ee551..5bf63014263c 100644
>> > --- a/drivers/net/wireless/mediatek/mt76/dma.c
>> > +++ b/drivers/net/wireless/mediatek/mt76/dma.c
>> > @@ -444,9 +444,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
>> >   	mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
>> >
>> >   	if (mt76_queue_is_wed_rx(q)) {
>> > +		u32 id, find = 0;
>> >   		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
>> > -		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
>> > +		struct mt76_txwi_cache *t;
>> > +
>> > +		if (*more) {
> 
> Because of scope, should define 'find' (or 'found'?) as bool here.
> 
>> > +			spin_lock_bh(&dev->rx_token_lock);
>> > +
>> > +			idr_for_each_entry(&dev->rx_token, t, id) {
> 
> idr_find() can only get a pointer associated with the ID. Not sure if it can
> have a reverse way -- get ID from pointer. With sequential search in data path,
> cost is higher.
> 
> Maybe you can consider to build association between argument 'idx' and
> pointer/token by another patch.
> 
> But logic is okay to me.

Adding to that, it matters how frequently the token ID is incorrect. If 
the token ID is correct most of the time, then it's worth optimizing for 
that as the default case. In that case you should avoid the extra idr 
scan if the pointer for the provided token id already matches.

- Felix


From faraz.ata at samsung.com  Wed Mar 12 01:07:57 2025
From: faraz.ata at samsung.com (Faraz Ata)
Date: Wed, 12 Mar 2025 13:37:57 +0530
Subject: [PATCH 2/2] arm64: dts: exynos: Add DT node for all UART ports
In-Reply-To: <5b68a9c2-9145-4131-9fa3-10810c51691f@kernel.org>
References: <20250312061932.1797993-1-faraz.ata@samsung.com>
	<CGME20250312061058epcas5p3ccf293213fe883129358833572b17d92@epcas5p3.samsung.com>
	<20250312061932.1797993-2-faraz.ata@samsung.com>
	<5b68a9c2-9145-4131-9fa3-10810c51691f@kernel.org>
Message-ID: <2aa201db9325$e8ef6e00$bace4a00$@samsung.com>

Hello Krzysztof

> -----Original Message-----
> On 12/03/2025 07:19, Faraz Ata wrote:
> > Universal Serial Interface (USI) supports three serial protocol like
> > uart, i2c and spi. ExynosAutov920 has 18 instances of USI.
> > Add all the USI DT node and subsequent uart nodes for all the instances.
> >
> > Signed-off-by: Faraz Ata <faraz.ata at samsung.com>
> > ---
> >  .../arm64/boot/dts/exynos/exynosautov920.dtsi | 494
> > ++++++++++++++++++
> >  1 file changed, 494 insertions(+)
> 
> 
> Please do not combine DTS changes with serial patches, ever. DTS has to go
> via separate tree.
> 
Sure, while sending v2, I will send DT separately and serial driver change separately.
Thanks for your review.
> ...
> 
.
.
.
> > +
> > +
> 
> Just one blank line.
Sure will correct in v2. 

> 
> >  		pwm: pwm at 109b0000 {
> >  			compatible = "samsung,exynosautov920-pwm",
> >  				     "samsung,exynos4210-pwm";
> 
> 
> Best regards,
> Krzysztof



From linux at armlinux.org.uk  Wed Mar 12 02:14:53 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:14:53 +0000
Subject: [PATCH net-next v2 0/9] net: stmmac: remove unnecessary
 of_get_phy_mode() calls
Message-ID: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>

Hi,

This series removes unnecessary of_get_phy_mode() calls from the stmmac
glue drivers. stmmac_probe_config_dt() / devm_stmmac_probe_config_dt()
already gets the interface mode using device_get_phy_mode() and stores
it in plat_dat->phy_interface.

Therefore, glue drivers using of_get_phy_mode() are just duplicating
the work that has already been done.

This series adjusts the glue drivers to remove their usage of
of_get_phy_mode().

Changes in v2:
- correct subject for patch 3
- fix build error in patch 3
- add attributations

 drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c | 21 +++++++++------------
 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 12 ++++--------
 .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c    |  8 +-------
 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c |  6 +-----
 .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c |  4 +---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c      |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c     | 12 ++++--------
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c   |  8 +-------
 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c   |  6 +-----
 9 files changed, 23 insertions(+), 56 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From vkoul at kernel.org  Wed Mar 12 02:18:06 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Wed, 12 Mar 2025 10:18:06 +0100
Subject: [PATCH 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <072d1d3a-2aeb-4ab0-9db1-476835a1131e@arm.com>
References: <cover.1740762136.git.robin.murphy@arm.com>
 <55e084dd2b5720bdddf503ffac560d111032aa96.1740762136.git.robin.murphy@arm.com>
 <Z89P461+Y6kQDOCX@vaman>
 <072d1d3a-2aeb-4ab0-9db1-476835a1131e@arm.com>
Message-ID: <Z9FRTtcfQK9m6NE7@vaman>

On 11-03-25, 12:48, Robin Murphy wrote:
> On 2025-03-10 8:47 pm, Vinod Koul wrote:
> > On 28-02-25, 17:26, Robin Murphy wrote:
> > 
> > > +static u32 d350_get_residue(struct d350_chan *dch)
> > > +{
> > > +	u32 res, xsize, xsizehi, hi_new;
> > > +
> > > +	hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
> > > +	do {
> > > +		xsizehi = hi_new;
> > > +		xsize = readl_relaxed(dch->base + CH_XSIZE);
> > > +		hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
> > > +	} while (xsizehi != hi_new);
> > 
> > This can go forever, lets have some limits to this loop please
> 
> Sure, in practice I doubt we're ever going to be continually preempted
> faster than the controller can move another 64KB of data, but I concur
> there's no harm in making the code easier to reason about at a glance
> either.

Yes you are coreect but when things go bad, a bug in h/w or something, I
would like to see a fail safe

> > > +static int d350_alloc_chan_resources(struct dma_chan *chan)
> > > +{
> > > +	struct d350_chan *dch = to_d350_chan(chan);
> > > +	int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED,
> > > +			      dev_name(&dch->vc.chan.dev->device), dch);
> > 
> > This is interesting, any reason why the irq is allocated here? Would it
> > be not better to do that in probe...
> 
> Well, I'd say technically the IRQ is a channel resource, and quite a few
> other drivers do the same... Here it's mostly so I can get the channel name
> - so the IRQs are nice and identifiable in /proc/interrupts - easily without
> making a big mess in probe, since the names don't exist until after the
> device is registered.

Ok

-- 
~Vinod


From lkp at intel.com  Wed Mar 12 02:18:09 2025
From: lkp at intel.com (kernel test robot)
Date: Wed, 12 Mar 2025 17:18:09 +0800
Subject: [PATCH v2 3/3] dt-bindings: mtd: atmel-nand: add legacy nand
 controllers
In-Reply-To: <20250311122847.90081-4-balamanikandan.gunasundar@microchip.com>
References: <20250311122847.90081-4-balamanikandan.gunasundar@microchip.com>
Message-ID: <202503121629.f5Hsa5Zy-lkp@intel.com>

Hi Balamanikandan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mtd/mtd/next]
[also build test WARNING on mtd/mtd/fixes robh/for-next linus/master v6.14-rc6 next-20250311]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Balamanikandan-Gunasundar/dt-bindings-mtd-microchip-nand-convert-txt-to-yaml/20250311-203706
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
patch link:    https://lore.kernel.org/r/20250311122847.90081-4-balamanikandan.gunasundar%40microchip.com
patch subject: [PATCH v2 3/3] dt-bindings: mtd: atmel-nand: add legacy nand controllers
reproduce: (https://download.01.org/0day-ci/archive/20250312/202503121629.f5Hsa5Zy-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503121629.f5Hsa5Zy-lkp at intel.com/

All warnings (new ones prefixed by >>):

   Warning: Documentation/translations/ja_JP/SubmittingPatches references a file that doesn't exist: linux-2.6.12-vanilla/Documentation/dontdiff
   Warning: Documentation/translations/zh_CN/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
   Warning: Documentation/translations/zh_TW/admin-guide/README.rst references a file that doesn't exist: Documentation/dev-tools/kgdb.rst
   Warning: Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst references a file that doesn't exist: Documentation/dev-tools/gdb-kernel-debugging.rst
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/mtd/atmel-nand.txt
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/leds/backlight/ti,lp8864.yaml
   Warning: lib/Kconfig.debug references a file that doesn't exist: Documentation/dev-tools/fault-injection/fault-injection.rst
   Using alabaster theme

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:21:07 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:21:07 +0000
Subject: [PATCH net-next v2 9/9] net: stmmac: sunxi: remove of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGx-005v0F-Ev@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set gmac->interface from plat_dat->phy_interface.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index 1b1ce2888b2e..9f098ff0ff05 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -116,11 +116,7 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
 	if (!gmac)
 		return -ENOMEM;
 
-	ret = of_get_phy_mode(dev->of_node, &gmac->interface);
-	if (ret && ret != -ENODEV) {
-		dev_err(dev, "Can't get phy-mode\n");
-		return ret;
-	}
+	gmac->interface = plat_dat->phy_interface;
 
 	gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
 	if (IS_ERR(gmac->tx_clk)) {
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:26 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:26 +0000
Subject: [PATCH net-next v2 1/9] net: stmmac: qcom-ethqos: remove
 of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGI-005uzT-KB@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it a second time in qcom_ethqos_probe(). Use
plat_dat->phy_interface to initialise ethqos->phy_mode.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index eafe637540b6..0e4da216f942 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -794,9 +794,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
 	if (!ethqos)
 		return -ENOMEM;
 
-	ret = of_get_phy_mode(np, &ethqos->phy_mode);
-	if (ret)
-		return dev_err_probe(dev, ret, "Failed to get phy mode\n");
+	ethqos->phy_mode = plat_dat->phy_interface;
 	switch (ethqos->phy_mode) {
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:31 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:31 +0000
Subject: [PATCH net-next v2 2/9] net: stmmac: mediatek: remove
 of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGN-005uzZ-NG@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Initialise priv_plat->phy_mode from plat->phy_interface
inmediatek_dwmac_common_data().

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index c9636832a570..d178d5ddc7c7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -456,7 +456,6 @@ static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
 {
 	struct mac_delay_struct *mac_delay = &plat->mac_delay;
 	u32 tx_delay_ps, rx_delay_ps;
-	int err;
 
 	plat->peri_regmap = syscon_regmap_lookup_by_phandle(plat->np, "mediatek,pericfg");
 	if (IS_ERR(plat->peri_regmap)) {
@@ -464,12 +463,6 @@ static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
 		return PTR_ERR(plat->peri_regmap);
 	}
 
-	err = of_get_phy_mode(plat->np, &plat->phy_mode);
-	if (err) {
-		dev_err(plat->dev, "not find phy-mode\n");
-		return err;
-	}
-
 	if (!of_property_read_u32(plat->np, "mediatek,tx-delay-ps", &tx_delay_ps)) {
 		if (tx_delay_ps < plat->variant->tx_delay_max) {
 			mac_delay->tx_delay = tx_delay_ps;
@@ -587,6 +580,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
 {
 	int i;
 
+	priv_plat->phy_mode = plat->phy_interface;
 	plat->mac_interface = priv_plat->phy_mode;
 	if (priv_plat->mac_wol)
 		plat->flags &= ~STMMAC_FLAG_USE_PHY_WOL;
-- 
2.30.2



From peterz at infradead.org  Wed Mar 12 02:39:47 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 12 Mar 2025 10:39:47 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <431a5acb-4906-4095-8dec-b2d824adaac6@arm.com>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250311113128.GD19424@noisy.programming.kicks-ass.net>
 <431a5acb-4906-4095-8dec-b2d824adaac6@arm.com>
Message-ID: <20250312093947.GJ19424@noisy.programming.kicks-ass.net>

On Tue, Mar 11, 2025 at 05:22:16PM +0000, Mark Barnett wrote:

> > @@ -9979,6 +9985,8 @@ static int __perf_event_overflow(struct perf_event *event,
> >   				 int throttle, struct perf_sample_data *data,
> >   				 struct pt_regs *regs)
> >   {
> > +	struct hw_perf_event *hwc = &event->hw;
> > +	u64 sample_period;
> >   	int events = atomic_read(&event->event_limit);
> >   	int ret = 0;
> > @@ -9989,15 +9997,50 @@ static int __perf_event_overflow(struct perf_event *event,
> >   	if (unlikely(!is_sampling_event(event)))
> >   		return 0;
> > -	ret = __perf_event_account_interrupt(event, throttle);
> > +	/*
> > +	 * High Freq samples are injected inside the larger period:
> > +	 *
> > +	 *   |------------|-|------------|-|
> > +	 *   P0          HF P1          HF
> > +	 *
> > +	 * By ignoring the HF samples, we measure the actual period.
> > +	 */
> > +	if (!(hwc->state & PERF_HES_HF_SAMPLE))
> > +		ret = __perf_event_account_interrupt(event, throttle);
> 
> The high-frequency samples should still contribute to interrupt
> accounting/throttling, right? We'd just need to put guards around the
> adaptive period stuff so that HF samples don't contribute to the frequency
> training.

Yeah, I suppose it should. This means breaking up that function but that
isn't hard.


From sudeep.holla at arm.com  Wed Mar 12 02:50:49 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 09:50:49 +0000
Subject: [PATCH v2] cpufreq: Init cpufreq only for present CPUs
In-Reply-To: <20250312092127.357316-1-ping.bai@nxp.com>
References: <20250312092127.357316-1-ping.bai@nxp.com>
Message-ID: <Z9FY-Uu-7R9eWEQ7@bogus>

On Wed, Mar 12, 2025 at 05:21:27PM +0800, Jacky Bai wrote:
> for_each_possible_cpu() is currently used to initialize cpufreq
> in below cpufreq drivers:
>   drivers/cpufreq/cpufreq-dt.c
>   drivers/cpufreq/mediatek-cpufreq-hw.c
>   drivers/cpufreq/mediatek-cpufreq.c
>   drivers/cpufreq/qcom-cpufreq-nvmem.c
>   drivers/cpufreq/sun50i-cpufreq-nvmem.c
>

Just drop this list, totally redundant as diffstat must give that anyways.
You have already made it stale as it doesn't match the diffstat.

With that fixed:

Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>

> However, in cpu_dev_register_generic(), for_each_present_cpu()
> is used to register CPU devices which means the CPU devices are
> only registered for present CPUs and not all possible CPUs.
> 
> With nosmp or maxcpus=0, only the boot CPU is present, lead
> to the cpufreq probe failure or defer probe due to no cpu device
> available for not present CPUs.
> 
> Change for_each_possible_cpu() to for_each_present_cpu() in the
> above cpufreq drivers to ensure it only registers cpufreq for
> CPUs that are actually present.
> 
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v2 changes:
>   - Add changes for armada-8k-cpufreq, mvebu-cpfureq, qcome-cpufreq-hw,
>     scmi-cpufreq, scpi-cpufreq, virtual-cpufreq.
> ---
>  drivers/cpufreq/armada-8k-cpufreq.c    | 2 +-
>  drivers/cpufreq/cpufreq-dt.c           | 2 +-
>  drivers/cpufreq/mediatek-cpufreq-hw.c  | 2 +-
>  drivers/cpufreq/mediatek-cpufreq.c     | 2 +-
>  drivers/cpufreq/mvebu-cpufreq.c        | 2 +-
>  drivers/cpufreq/qcom-cpufreq-hw.c      | 2 +-
>  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 8 ++++----
>  drivers/cpufreq/scmi-cpufreq.c         | 2 +-
>  drivers/cpufreq/scpi-cpufreq.c         | 2 +-
>  drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++---
>  drivers/cpufreq/virtual-cpufreq.c      | 2 +-
>  11 files changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c
> index 7a979db81f09..5a3545bd0d8d 100644
> --- a/drivers/cpufreq/armada-8k-cpufreq.c
> +++ b/drivers/cpufreq/armada-8k-cpufreq.c
> @@ -47,7 +47,7 @@ static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk,
>  {
>  	int cpu;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		struct device *cpu_dev;
>  		struct clk *clk;
>  
> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
> index 778916f89a51..e80dd982a3e2 100644
> --- a/drivers/cpufreq/cpufreq-dt.c
> +++ b/drivers/cpufreq/cpufreq-dt.c
> @@ -283,7 +283,7 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
>  	int ret, cpu;
>  
>  	/* Request resources early so we can return in case of -EPROBE_DEFER */
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		ret = dt_cpufreq_early_init(&pdev->dev, cpu);
>  		if (ret)
>  			goto err;
> diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
> index aa209f5527dc..74f1b4c796e4 100644
> --- a/drivers/cpufreq/mediatek-cpufreq-hw.c
> +++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
> @@ -303,7 +303,7 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev)
>  	struct regulator *cpu_reg;
>  
>  	/* Make sure that all CPU supplies are available before proceeding. */
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		cpu_dev = get_cpu_device(cpu);
>  		if (!cpu_dev)
>  			return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
> diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> index 2656b88db378..f3f02c4b6888 100644
> --- a/drivers/cpufreq/mediatek-cpufreq.c
> +++ b/drivers/cpufreq/mediatek-cpufreq.c
> @@ -631,7 +631,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
>  		return dev_err_probe(&pdev->dev, -ENODEV,
>  				     "failed to get mtk cpufreq platform data\n");
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		info = mtk_cpu_dvfs_info_lookup(cpu);
>  		if (info)
>  			continue;
> diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
> index 7f3cfe668f30..2aad4c04673c 100644
> --- a/drivers/cpufreq/mvebu-cpufreq.c
> +++ b/drivers/cpufreq/mvebu-cpufreq.c
> @@ -56,7 +56,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
>  	 * it), and registers the clock notifier that will take care
>  	 * of doing the PMSU part of a frequency transition.
>  	 */
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		struct device *cpu_dev;
>  		struct clk *clk;
>  		int ret;
> diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
> index 4b3b3dbc7d38..8422704a3b10 100644
> --- a/drivers/cpufreq/qcom-cpufreq-hw.c
> +++ b/drivers/cpufreq/qcom-cpufreq-hw.c
> @@ -306,7 +306,7 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
>  	struct of_phandle_args args;
>  	int cpu, ret;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		cpu_np = of_cpu_device_node_get(cpu);
>  		if (!cpu_np)
>  			continue;
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index 3a8ed723a23e..54f8117103c8 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  		nvmem_cell_put(speedbin_nvmem);
>  	}
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		struct dev_pm_opp_config config = {
>  			.supported_hw = NULL,
>  		};
> @@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>  	dev_err(cpu_dev, "Failed to register platform device\n");
>  
>  free_opp:
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
>  		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
>  	}
> @@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
>  
>  	platform_device_unregister(cpufreq_dt_pdev);
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
>  		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
>  	}
> @@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
>  	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
>  	unsigned int cpu;
>  
> -	for_each_possible_cpu(cpu)
> +	for_each_present_cpu(cpu)
>  		qcom_cpufreq_suspend_pd_devs(drv, cpu);
>  
>  	return 0;
> diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
> index ff2897789797..c310aeebc8f3 100644
> --- a/drivers/cpufreq/scmi-cpufreq.c
> +++ b/drivers/cpufreq/scmi-cpufreq.c
> @@ -104,7 +104,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
>  	int cpu, tdomain;
>  	struct device *tcpu_dev;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		if (cpu == cpu_dev->id)
>  			continue;
>  
> diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
> index 048dc43a9997..17cda84f00df 100644
> --- a/drivers/cpufreq/scpi-cpufreq.c
> +++ b/drivers/cpufreq/scpi-cpufreq.c
> @@ -65,7 +65,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
>  	if (domain < 0)
>  		return domain;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		if (cpu == cpu_dev->id)
>  			continue;
>  
> diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> index 17d6a149f580..47d6840b3489 100644
> --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> @@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
>  	snprintf(name, sizeof(name), "speed%d", speed);
>  	config.prop_name = name;
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		struct device *cpu_dev = get_cpu_device(cpu);
>  
>  		if (!cpu_dev) {
> @@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
>  	pr_err("Failed to register platform device\n");
>  
>  free_opp:
> -	for_each_possible_cpu(cpu)
> +	for_each_present_cpu(cpu)
>  		dev_pm_opp_clear_config(opp_tokens[cpu]);
>  	kfree(opp_tokens);
>  
> @@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
>  
>  	platform_device_unregister(cpufreq_dt_pdev);
>  
> -	for_each_possible_cpu(cpu)
> +	for_each_present_cpu(cpu)
>  		dev_pm_opp_clear_config(opp_tokens[cpu]);
>  
>  	kfree(opp_tokens);
> diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c
> index 45becb92aa4a..7dd1b0c263c7 100644
> --- a/drivers/cpufreq/virtual-cpufreq.c
> +++ b/drivers/cpufreq/virtual-cpufreq.c
> @@ -138,7 +138,7 @@ static int virt_cpufreq_get_sharing_cpus(struct cpufreq_policy *policy)
>  	cur_perf_domain = readl_relaxed(base + policy->cpu *
>  					PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
>  
> -	for_each_possible_cpu(cpu) {
> +	for_each_present_cpu(cpu) {
>  		cpu_dev = get_cpu_device(cpu);
>  		if (!cpu_dev)
>  			continue;
> -- 
> 2.34.1
> 

-- 
Regards,
Sudeep


From suraj.gupta2 at amd.com  Wed Mar 12 02:54:09 2025
From: suraj.gupta2 at amd.com (Suraj Gupta)
Date: Wed, 12 Mar 2025 15:24:09 +0530
Subject: [PATCH net-next V2 0/2] Add support for 2500Base-X only configuration
Message-ID: <20250312095411.1392379-1-suraj.gupta2@amd.com>

Add support for 2500Base-X only configuration, which is a
synthesis option of AXI 1G/2.5G IP.

Changes in V2:
- Read 2.5G ability from Temac ability register and remove
max-speed DT property.
- Mentioned all 3 IP configurations in comment and commit description.
- Mention this series is for 2.5G only configuration.

Suraj Gupta (2):
  dt-bindings: net: xlnx,axi-ethernet: Modify descriptions and phy-mode
    value to support 2500base-X only configuration
  net: axienet: Add support for 2500base-X only configuration.

 .../bindings/net/xlnx,axi-ethernet.yaml       |  9 ++++---
 drivers/net/ethernet/xilinx/xilinx_axienet.h  |  2 +-
 .../net/ethernet/xilinx/xilinx_axienet_main.c | 24 +++++++++++++++----
 3 files changed, 26 insertions(+), 9 deletions(-)

-- 
2.25.1



From ping.bai at nxp.com  Wed Mar 12 02:21:27 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Wed, 12 Mar 2025 17:21:27 +0800
Subject: [PATCH v2] cpufreq: Init cpufreq only for present CPUs
Message-ID: <20250312092127.357316-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpufreq
in below cpufreq drivers:
  drivers/cpufreq/cpufreq-dt.c
  drivers/cpufreq/mediatek-cpufreq-hw.c
  drivers/cpufreq/mediatek-cpufreq.c
  drivers/cpufreq/qcom-cpufreq-nvmem.c
  drivers/cpufreq/sun50i-cpufreq-nvmem.c

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the cpufreq probe failure or defer probe due to no cpu device
available for not present CPUs.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpufreq drivers to ensure it only registers cpufreq for
CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v2 changes:
  - Add changes for armada-8k-cpufreq, mvebu-cpfureq, qcome-cpufreq-hw,
    scmi-cpufreq, scpi-cpufreq, virtual-cpufreq.
---
 drivers/cpufreq/armada-8k-cpufreq.c    | 2 +-
 drivers/cpufreq/cpufreq-dt.c           | 2 +-
 drivers/cpufreq/mediatek-cpufreq-hw.c  | 2 +-
 drivers/cpufreq/mediatek-cpufreq.c     | 2 +-
 drivers/cpufreq/mvebu-cpufreq.c        | 2 +-
 drivers/cpufreq/qcom-cpufreq-hw.c      | 2 +-
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 8 ++++----
 drivers/cpufreq/scmi-cpufreq.c         | 2 +-
 drivers/cpufreq/scpi-cpufreq.c         | 2 +-
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++---
 drivers/cpufreq/virtual-cpufreq.c      | 2 +-
 11 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c
index 7a979db81f09..5a3545bd0d8d 100644
--- a/drivers/cpufreq/armada-8k-cpufreq.c
+++ b/drivers/cpufreq/armada-8k-cpufreq.c
@@ -47,7 +47,7 @@ static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk,
 {
 	int cpu;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev;
 		struct clk *clk;
 
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 778916f89a51..e80dd982a3e2 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -283,7 +283,7 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
 	int ret, cpu;
 
 	/* Request resources early so we can return in case of -EPROBE_DEFER */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = dt_cpufreq_early_init(&pdev->dev, cpu);
 		if (ret)
 			goto err;
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
index aa209f5527dc..74f1b4c796e4 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -303,7 +303,7 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev)
 	struct regulator *cpu_reg;
 
 	/* Make sure that all CPU supplies are available before proceeding. */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_dev = get_cpu_device(cpu);
 		if (!cpu_dev)
 			return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 2656b88db378..f3f02c4b6888 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -631,7 +631,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "failed to get mtk cpufreq platform data\n");
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		info = mtk_cpu_dvfs_info_lookup(cpu);
 		if (info)
 			continue;
diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
index 7f3cfe668f30..2aad4c04673c 100644
--- a/drivers/cpufreq/mvebu-cpufreq.c
+++ b/drivers/cpufreq/mvebu-cpufreq.c
@@ -56,7 +56,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
 	 * it), and registers the clock notifier that will take care
 	 * of doing the PMSU part of a frequency transition.
 	 */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev;
 		struct clk *clk;
 		int ret;
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 4b3b3dbc7d38..8422704a3b10 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -306,7 +306,7 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
 	struct of_phandle_args args;
 	int cpu, ret;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_np = of_cpu_device_node_get(cpu);
 		if (!cpu_np)
 			continue;
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 3a8ed723a23e..54f8117103c8 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 		nvmem_cell_put(speedbin_nvmem);
 	}
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct dev_pm_opp_config config = {
 			.supported_hw = NULL,
 		};
@@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 	dev_err(cpu_dev, "Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
 	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
 	unsigned int cpu;
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		qcom_cpufreq_suspend_pd_devs(drv, cpu);
 
 	return 0;
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index ff2897789797..c310aeebc8f3 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -104,7 +104,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
 	int cpu, tdomain;
 	struct device *tcpu_dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		if (cpu == cpu_dev->id)
 			continue;
 
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 048dc43a9997..17cda84f00df 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -65,7 +65,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 	if (domain < 0)
 		return domain;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		if (cpu == cpu_dev->id)
 			continue;
 
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 17d6a149f580..47d6840b3489 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	snprintf(name, sizeof(name), "speed%d", speed);
 	config.prop_name = name;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev = get_cpu_device(cpu);
 
 		if (!cpu_dev) {
@@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	pr_err("Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 	kfree(opp_tokens);
 
@@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 
 	kfree(opp_tokens);
diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c
index 45becb92aa4a..7dd1b0c263c7 100644
--- a/drivers/cpufreq/virtual-cpufreq.c
+++ b/drivers/cpufreq/virtual-cpufreq.c
@@ -138,7 +138,7 @@ static int virt_cpufreq_get_sharing_cpus(struct cpufreq_policy *policy)
 	cur_perf_domain = readl_relaxed(base + policy->cpu *
 					PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_dev = get_cpu_device(cpu);
 		if (!cpu_dev)
 			continue;
-- 
2.34.1



From marcin.wojciechowski at ventrazo.pl  Wed Mar 12 02:15:49 2025
From: marcin.wojciechowski at ventrazo.pl (Marcin Wojciechowski)
Date: Wed, 12 Mar 2025 09:15:49 GMT
Subject: Zapytanie ofertowe 
Message-ID: <20250312084500-0.1.he.3pful.0.s253y3ngb0@OriginatePro.pl>

Dzie? dobry,

Pozwoli?em sobie na kontakt, poniewa? jestem zainteresowany weryfikacj? mo?liwo?ci nawi?zania wsp??pracy.

Wspieramy firmy w pozyskiwaniu nowych klient?w biznesowych.

Czy mo?emy porozmawia? w celu przedstawienia szczeg??owych informacji? 
 

Pozdrawiam serdecznie
Marcin Wojciechowski


From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:41 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:41 +0000
Subject: [PATCH net-next v2 4/9] net: stmmac: ipq806x: remove
 of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGX-005uzl-TQ@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Pass plat_dat into ipq806x_gmac_of_parse(), and set gmac->phy_mode from
plat_dat->phy_interface.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index 0a9c137cc4e6..ca4035cbb55b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -211,16 +211,12 @@ static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, int speed)
 	return 0;
 }
 
-static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
+static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac,
+				 struct plat_stmmacenet_data *plat_dat)
 {
 	struct device *dev = &gmac->pdev->dev;
-	int ret;
 
-	ret = of_get_phy_mode(dev->of_node, &gmac->phy_mode);
-	if (ret) {
-		dev_err(dev, "missing phy mode property\n");
-		return -EINVAL;
-	}
+	gmac->phy_mode = plat_dat->phy_interface;
 
 	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
 		dev_err(dev, "missing qcom id property\n");
@@ -398,7 +394,7 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
 
 	gmac->pdev = pdev;
 
-	err = ipq806x_gmac_of_parse(gmac);
+	err = ipq806x_gmac_of_parse(gmac, plat_dat);
 	if (err) {
 		dev_err(dev, "device tree parsing error\n");
 		return err;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:47 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:47 +0000
Subject: [PATCH net-next v2 5/9] net: stmmac: meson8b: remove
 of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGd-005uzr-0C@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set dwmac->phy_mode from plat_dat->phy_interface.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index 9c2d62d133ad..a50782994b97 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -417,11 +417,7 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
 		return PTR_ERR(dwmac->regs);
 
 	dwmac->dev = &pdev->dev;
-	ret = of_get_phy_mode(pdev->dev.of_node, &dwmac->phy_mode);
-	if (ret) {
-		dev_err(&pdev->dev, "missing phy-mode property\n");
-		return ret;
-	}
+	dwmac->phy_mode = plat_dat->phy_interface;
 
 	/* use 2ns as fallback since this value was previously hardcoded */
 	if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns",
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:52 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:52 +0000
Subject: [PATCH net-next v2 6/9] net: stmmac: rk: remove of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGi-005uzx-3p@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Set bsp_priv->phy_iface from plat->phy_interface.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..40e8197812e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1749,7 +1749,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 	if (!bsp_priv)
 		return ERR_PTR(-ENOMEM);
 
-	of_get_phy_mode(dev->of_node, &bsp_priv->phy_iface);
+	bsp_priv->phy_iface = plat->phy_interface;
 	bsp_priv->ops = ops;
 
 	/* Some SoCs have multiple MAC controllers, which need
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:57 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:57 +0000
Subject: [PATCH net-next v2 7/9] net: stmmac: sti: remove of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGn-005v02-7G@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Pass plat_dat into sti_dwmac_parse_data(), and set dwmac->interface
from plat_dat->phy_interface.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 13b9c2a51fce..be57c6c12c1c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -185,7 +185,8 @@ static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
 }
 
 static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
-				struct platform_device *pdev)
+				struct platform_device *pdev,
+				struct plat_stmmacenet_data *plat_dat)
 {
 	struct resource *res;
 	struct device *dev = &pdev->dev;
@@ -204,12 +205,7 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
 	if (IS_ERR(regmap))
 		return PTR_ERR(regmap);
 
-	err = of_get_phy_mode(np, &dwmac->interface);
-	if (err && err != -ENODEV) {
-		dev_err(dev, "Can't get phy-mode\n");
-		return err;
-	}
-
+	dwmac->interface = plat_dat->phy_interface;
 	dwmac->regmap = regmap;
 	dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
 	dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
@@ -268,7 +264,7 @@ static int sti_dwmac_probe(struct platform_device *pdev)
 	if (!dwmac)
 		return -ENOMEM;
 
-	ret = sti_dwmac_parse_data(dwmac, pdev);
+	ret = sti_dwmac_parse_data(dwmac, pdev, plat_dat);
 	if (ret) {
 		dev_err(&pdev->dev, "Unable to parse OF data\n");
 		return ret;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:21:02 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:21:02 +0000
Subject: [PATCH net-next v2 8/9] net: stmmac: sun8i: remove of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGs-005v09-CD@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

sun8i was using of_get_phy_mode() to set plat_dat->mac_interface, which
defaults to plat_dat->phy_interface when the mac-mode DT property is
not present. As nothing in arch/*/boot/dts sets the mac-mode property,
it is highly likely that these two will be identical, and thus there
is no need for this glue driver to set plat_dat->mac_interface.

Reviewed-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 4b7b2582a120..85723a78793a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1155,11 +1155,10 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 	struct stmmac_resources stmmac_res;
 	struct sunxi_priv_data *gmac;
 	struct device *dev = &pdev->dev;
-	phy_interface_t interface;
-	int ret;
 	struct stmmac_priv *priv;
 	struct net_device *ndev;
 	struct regmap *regmap;
+	int ret;
 
 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
 	if (ret)
@@ -1219,10 +1218,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = of_get_phy_mode(dev->of_node, &interface);
-	if (ret)
-		return -EINVAL;
-
 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
 	if (IS_ERR(plat_dat))
 		return PTR_ERR(plat_dat);
@@ -1230,7 +1225,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
 	/* platform data specifying hardware features and callbacks.
 	 * hardware features were copied from Allwinner drivers.
 	 */
-	plat_dat->mac_interface = interface;
 	plat_dat->rx_coe = STMMAC_RX_COE_TYPE2;
 	plat_dat->tx_coe = 1;
 	plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:20:36 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:20:36 +0000
Subject: [PATCH net-next v2 3/9] net: stmmac: anarion: remove
 of_get_phy_mode()
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <E1tsIGS-005uzf-QE@rmk-PC.armlinux.org.uk>

devm_stmmac_probe_config_dt() already gets the PHY mode from firmware,
which is stored in plat_dat->phy_interface. Therefore, we don't need to
get it in platform code.

Rearrange the initialisation order so we can pass plat_dat into
anarion_config_dt(), thereby providing plat_dat->phy_interface as
necessary there.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../ethernet/stmicro/stmmac/dwmac-anarion.c   | 21 ++++++++-----------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
index ef99ef3f1ab4..37fe7c288878 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
@@ -59,10 +59,11 @@ static void anarion_gmac_exit(struct platform_device *pdev, void *priv)
 	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);
 }
 
-static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
+static struct anarion_gmac *
+anarion_config_dt(struct platform_device *pdev,
+		  struct plat_stmmacenet_data *plat_dat)
 {
 	struct anarion_gmac *gmac;
-	phy_interface_t phy_mode;
 	void __iomem *ctl_block;
 	int err;
 
@@ -79,11 +80,7 @@ static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
 
 	gmac->ctl_block = ctl_block;
 
-	err = of_get_phy_mode(pdev->dev.of_node, &phy_mode);
-	if (err)
-		return ERR_PTR(err);
-
-	switch (phy_mode) {
+	switch (plat_dat->phy_interface) {
 	case PHY_INTERFACE_MODE_RGMII:
 		fallthrough;
 	case PHY_INTERFACE_MODE_RGMII_ID:
@@ -93,7 +90,7 @@ static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
 		break;
 	default:
 		dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n",
-			phy_mode);
+			plat_dat->phy_interface);
 		return ERR_PTR(-ENOTSUPP);
 	}
 
@@ -111,14 +108,14 @@ static int anarion_dwmac_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	gmac = anarion_config_dt(pdev);
-	if (IS_ERR(gmac))
-		return PTR_ERR(gmac);
-
 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
 	if (IS_ERR(plat_dat))
 		return PTR_ERR(plat_dat);
 
+	gmac = anarion_config_dt(pdev, plat_dat);
+	if (IS_ERR(gmac))
+		return PTR_ERR(gmac);
+
 	plat_dat->init = anarion_gmac_init;
 	plat_dat->exit = anarion_gmac_exit;
 	anarion_gmac_init(pdev, gmac);
-- 
2.30.2



From yuzenghui at huawei.com  Wed Mar 12 02:27:50 2025
From: yuzenghui at huawei.com (Zenghui Yu)
Date: Wed, 12 Mar 2025 17:27:50 +0800
Subject: [report] WARN_ON_ONCE() was triggered with pseudo NMI enabled
Message-ID: <ce10f231-4ecd-cb12-4b5c-1c503d9177da@huawei.com>

Hi,

With pseudo NMI enabled, I can trigger the following splat when running
selftests (e.g., arm64/signal/fake_sigreturn_bad_magic, which will issue
a BRK instruction).

 ------------[ cut here ]------------
 WARNING: CPU: 5 PID: 386876 at ./arch/arm64/include/asm/irqflags.h:34
send_user_sigtrap+0xc8/0xd0
 CPU: 5 UID: 0 PID: 386876 Comm: fake_sigreturn_ Kdump: loaded Not
tainted 6.14.0-rc6-00017-g5e35b5d3ce97-dirty
 pstate: 204003c9 (nzCv DAIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
 pc : send_user_sigtrap+0xc8/0xd0
 lr : brk_handler+0x3c/0xbc
 sp : ffff8000ade3be00
 pmr: 000000f0
 x29: ffff8000ade3be00 x28: ffff00209777c600 x27: 0000000000000000
 x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000400e30
 x23: ffff800082cb8458 x22: ffff800082cb83c8 x21: 00000000f200029a
 x20: ffff8000ade3beb0 x19: ffff8000ade3beb0 x18: 0000000000000000
 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
 x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000
 x8 : 0000000000000000 x7 : 0000000000000000 x6 : ffff8000827e6638
 x5 : 0000000000000000 x4 : ffff8000827e6638 x3 : 0000000060000000
 x2 : ffff8000ade3c000 x1 : 0000000000000001 x0 : 00000000000000d0
 Call trace:
  send_user_sigtrap+0xc8/0xd0 (P)
  brk_handler+0x3c/0xbc
  do_debug_exception+0x68/0x110
  el0_dbg+0x28/0xb8
  el0t_64_sync_handler+0x50/0xcc
  el0t_64_sync+0x1ac/0x1b0
 ---[ end trace 0000000000000000 ]---

I use mainline and the kernel is built with defconfig + ARM64_PSEUDO_NMI
+ ARM64_DEBUG_PRIORITY_MASKING.

Thanks,
Zenghui


From andriy.shevchenko at linux.intel.com  Wed Mar 12 02:32:32 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Wed, 12 Mar 2025 11:32:32 +0200
Subject: [PATCH v2 00/10] i2c: busses: Introduce and use
 i2c_10bit_addr_*_from_msg()
In-Reply-To: <c6xszdhx5ztexlqlmhvdn4dyz5ilzxsm7c62cvkmnwy2y3gaqc@owk2ani2emys>
References: <20250213141045.2716943-1-andriy.shevchenko@linux.intel.com>
 <c6xszdhx5ztexlqlmhvdn4dyz5ilzxsm7c62cvkmnwy2y3gaqc@owk2ani2emys>
Message-ID: <Z9FUsLC0TcglJZN_@smile.fi.intel.com>

On Tue, Mar 11, 2025 at 02:12:03AM +0100, Andi Shyti wrote:
> Hi Andy,
> 
> > Andy Shevchenko (10):
> >   i2c: Introduce i2c_10bit_addr_*_from_msg() helpers
> >   i2c: axxia: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: bcm-kona: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: brcmstb: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: eg20t: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: kempld: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: mt7621: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: rzv2m: Use i2c_10bit_addr_*_from_msg() helpers
> >   i2c: ibm_iic: Use i2c_*bit_addr*_from_msg() helpers
> >   i2c: mv64xxx: Use i2c_*bit_addr*_from_msg() helpers
> 
> merged to i2c/i2c-host.

Thank you!

-- 
With Best Regards,
Andy Shevchenko




From linux at armlinux.org.uk  Wed Mar 12 02:34:20 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:20 +0000
Subject: [PATCH net-next v2 0/7] net: stmmac: deprecate
 "snps,en-tx-lpi-clockgating" property
Message-ID: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>

On Sun, Mar 09, 2025 at 03:01:45PM +0000, Russell King (Oracle) wrote:
Hi,

This series deprecates the "snps,en-tx-lpi-clockgating" property for
stmmac.

MII Transmit clock gating, where the MAC hardware supports gating this
clock, is a function of the connected PHY capabilities, which it
reports through its status register.

GMAC versions that support transmit clock gating twiddle the LPITCSE
bit accordingly in the LPI control/status register, which is handled
by the GMAC core specific code.

So, "snps,en-tx-lpi-clockgating" not something that is a GMAC property,
but is a work-around for phylib not providing an interface to determine
whether the PHY allows the transmit clock to be disabled.

This series converts the two SoCs that make use of this property (which,
I hasten to add, is set in the SoC code) to use the PHY capability bit
instead of a DT property, then removes the DT property from the .dtsi,
deprecates it in the snps,dwmac binding, and finally in the stmmac code.

I am expecting some discussion on how to merge this, as I think the
order in which these changes is made is important - we don't want to
deprecate the old way until the new code has landed.

Changes in v2:
- Correct Cc list

 Documentation/devicetree/bindings/net/snps,dwmac.yaml |  1 +
 arch/arm/boot/dts/st/stm32mp151.dtsi                  |  1 -
 arch/riscv/boot/dts/starfive/jh7110.dtsi              |  2 --
 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c  |  1 +
 drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c     |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h          |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     | 16 ++++++++++++----
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c |  5 ++++-
 include/linux/stmmac.h                                |  3 ++-
 9 files changed, 22 insertions(+), 9 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:25 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:25 +0000
Subject: [PATCH net-next v2 1/7] net: stmmac: allow platforms to use PHY tx
 clock stop capability
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsITp-005vG9-Px@rmk-PC.armlinux.org.uk>

Allow platform glue to instruct stmmac to make use of the PHY transmit
clock stop capability when deciding whether to allow the transmit clock
from the DWMAC core to be stopped.

Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h     |  1 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 ++++++++++++----
 include/linux/stmmac.h                           |  3 ++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index d87275c1cf23..bddfa0f4aa21 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -306,6 +306,7 @@ struct stmmac_priv {
 	struct timer_list eee_ctrl_timer;
 	int lpi_irq;
 	u32 tx_lpi_timer;
+	bool tx_lpi_clk_stop;
 	bool eee_enabled;
 	bool eee_active;
 	bool eee_sw_timer_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fa1d7d3a2f43..6f29804148b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -457,8 +457,7 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
 	/* Check and enter in LPI mode */
 	if (!priv->tx_path_in_lpi_mode)
 		stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_FORCED,
-			priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-			0);
+				    priv->tx_lpi_clk_stop, 0);
 }
 
 /**
@@ -1104,13 +1103,18 @@ static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
 
 	priv->eee_enabled = true;
 
+	/* Update the transmit clock stop according to PHY capability if
+	 * the platform allows
+	 */
+	if (priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP)
+		priv->tx_lpi_clk_stop = tx_clk_stop;
+
 	stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
 			     STMMAC_DEFAULT_TWT_LS);
 
 	/* Try to cnfigure the hardware timer. */
 	ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
-				  priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
-				  priv->tx_lpi_timer);
+				  priv->tx_lpi_clk_stop, priv->tx_lpi_timer);
 
 	if (ret) {
 		/* Hardware timer mode not supported, or value out of range.
@@ -1269,6 +1273,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	if (!(priv->plat->flags & STMMAC_FLAG_RX_CLK_RUNS_IN_LPI))
 		priv->phylink_config.eee_rx_clk_stop_enable = true;
 
+	/* Set the default transmit clock stop bit based on the platform glue */
+	priv->tx_lpi_clk_stop = priv->plat->flags &
+				STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+
 	mdio_bus_data = priv->plat->mdio_bus_data;
 	if (mdio_bus_data)
 		priv->phylink_config.default_an_inband =
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index b6f03ab12595..c4ec8bb8144e 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -183,7 +183,8 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_INT_SNAPSHOT_EN		BIT(9)
 #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
-#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
+#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP	BIT(12)
+#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:30 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:30 +0000
Subject: [PATCH net-next v2 2/7] net: stmmac: starfive: use PHY capability for
 TX clock stop
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsITu-005vGF-TM@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Add the flag to allow the stmmac core to use the PHY capability.

Cc: Samin Guo <samin.guo at starfivetech.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 5e31cb3bb4b8..2013d7477eb7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -124,6 +124,7 @@ static int starfive_dwmac_probe(struct platform_device *pdev)
 		plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
 
 	dwmac->dev = &pdev->dev;
+	plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
 	plat_dat->bsp_priv = dwmac;
 	plat_dat->dma_cfg->dche = true;
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:36 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:36 +0000
Subject: [PATCH net-next v2 3/7] net: stmmac: stm32: use PHY capability for TX
 clock stop
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsIU0-005vGL-17@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Add the flag to allow the stmmac core to use the PHY capability.

Cc: Christophe Roullier <christophe.roullier at st.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 1fcb74e9e3ff..c3d321192581 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -538,6 +538,7 @@ static int stm32_dwmac_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
 	plat_dat->bsp_priv = dwmac;
 
 	ret = stm32_dwmac_init(plat_dat, false);
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:41 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:41 +0000
Subject: [PATCH net-next v2 4/7] riscv: dts: starfive: remove
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsIU5-005vGR-4c@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

As commit "net: stmmac: starfive: use PHY capability for TX clock stop"
adds the flag to use the PHY capability, remove the DT property that is
now unecessary.

Cc: Samin Guo <samin.guo at starfivetech.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 arch/riscv/boot/dts/starfive/jh7110.dtsi | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 0d8339357bad..a7aed4a21b65 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -1022,7 +1022,6 @@ gmac0: ethernet at 16030000 {
 			snps,force_thresh_dma_mode;
 			snps,axi-config = <&stmmac_axi_setup>;
 			snps,tso;
-			snps,en-tx-lpi-clockgating;
 			snps,txpbl = <16>;
 			snps,rxpbl = <16>;
 			starfive,syscon = <&aon_syscon 0xc 0x12>;
@@ -1053,7 +1052,6 @@ gmac1: ethernet at 16040000 {
 			snps,force_thresh_dma_mode;
 			snps,axi-config = <&stmmac_axi_setup>;
 			snps,tso;
-			snps,en-tx-lpi-clockgating;
 			snps,txpbl = <16>;
 			snps,rxpbl = <16>;
 			starfive,syscon = <&sys_syscon 0x90 0x2>;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:46 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:46 +0000
Subject: [PATCH net-next v2 5/7] ARM: dts: stm32: remove
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsIUA-005vGX-8A@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

As commit "net: stmmac: stm32: use PHY capability for TX clock stop"
adds the flag to use the PHY capability, remove the DT property that is
now unecessary.

Cc: Samin Guo <samin.guo at starfivetech.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 arch/arm/boot/dts/st/stm32mp151.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi
index b9a87fbe971d..0daa8ffe2ff5 100644
--- a/arch/arm/boot/dts/st/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp151.dtsi
@@ -1781,7 +1781,6 @@ ethernet0: ethernet at 5800a000 {
 				st,syscon = <&syscfg 0x4>;
 				snps,mixed-burst;
 				snps,pbl = <2>;
-				snps,en-tx-lpi-clockgating;
 				snps,axi-config = <&stmmac_axi_config_0>;
 				snps,tso;
 				access-controllers = <&etzpc 94>;
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:51 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:51 +0000
Subject: [PATCH net-next v2 6/7] dt-bindings: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsIUF-005vGd-C5@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Therefore, snps,en-tx-lpi-clockgating is technically incorrect, so this
commit deprecates the property in the binding.

Acked-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 Documentation/devicetree/bindings/net/snps,dwmac.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 3f0aa46d798e..78b3030dc56d 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -494,6 +494,7 @@ title: Synopsys DesignWare MAC
 
   snps,en-tx-lpi-clockgating:
     $ref: /schemas/types.yaml#/definitions/flag
+    deprecated: true
     description:
       Enable gating of the MAC TX clock during TX low-power mode
 
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Wed Mar 12 02:34:56 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 09:34:56 +0000
Subject: [PATCH net-next v2 7/7] net: stmmac: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <E1tsIUK-005vGk-H7@rmk-PC.armlinux.org.uk>

Whether the MII transmit clock can be stopped is primarily a property
of the PHY (there is a capability bit that should be checked first.)
Whether the MAC is capable of stopping the transmit clock is a separate
issue, but this is already handled by the core DesignWare MAC code.

Therefore, snps,en-tx-lpi-clockgating is technically incorrect, and
this commit adds a warning should a DT be encountered with the property
present.

However, we keep backwards compatibility.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 8dc3bd6946c6..c73eff6a56b8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -497,8 +497,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
 	plat->force_sf_dma_mode =
 		of_property_read_bool(np, "snps,force_sf_dma_mode");
 
-	if (of_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+	if (of_property_read_bool(np, "snps,en-tx-lpi-clockgating")) {
+		dev_warn(&pdev->dev,
+			 "OF property snps,en-tx-lpi-clockgating is deprecated, please convert driver to use STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP\n");
 		plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+	}
 
 	/* Set the maxmtu to a default of JUMBO_LEN in case the
 	 * parameter is not present in the device tree.
-- 
2.30.2



From leo.yan at arm.com  Wed Mar 12 02:56:57 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 12 Mar 2025 09:56:57 +0000
Subject: [PATCH] perf script: Fix typo in branch event mask
In-Reply-To: <20250312075636.429127-1-yujie.liu@intel.com>
References: <20250312075636.429127-1-yujie.liu@intel.com>
Message-ID: <20250312095657.GM9682@e132581.arm.com>

On Wed, Mar 12, 2025 at 03:56:36PM +0800, Yujie Liu wrote:
> BRACH -> BRANCH
> 
> Fixes: 88b1473135e4 ("perf script: Separate events from branch types")
> Signed-off-by: Yujie Liu <yujie.liu at intel.com>

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  tools/perf/util/event.h                 | 2 +-
>  tools/perf/util/trace-event-scripting.c | 4 ++--
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
> index c7f4b4b841ca..664bf39567ce 100644
> --- a/tools/perf/util/event.h
> +++ b/tools/perf/util/event.h
> @@ -91,7 +91,7 @@ enum {
>  	PERF_IP_FLAG_VMENTRY		|\
>  	PERF_IP_FLAG_VMEXIT)
>  
> -#define PERF_IP_FLAG_BRACH_EVENT_MASK	\
> +#define PERF_IP_FLAG_BRANCH_EVENT_MASK	\
>  	(PERF_IP_FLAG_BRANCH_MISS |	\
>  	 PERF_IP_FLAG_NOT_TAKEN)
>  
> diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
> index 29cc467be14a..72abb28b7b5a 100644
> --- a/tools/perf/util/trace-event-scripting.c
> +++ b/tools/perf/util/trace-event-scripting.c
> @@ -347,7 +347,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
>  
>  	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);
>  
> -	types = flags & ~PERF_IP_FLAG_BRACH_EVENT_MASK;
> +	types = flags & ~PERF_IP_FLAG_BRANCH_EVENT_MASK;
>  	for (i = 0; sample_flags[i].name; i++) {
>  		if (sample_flags[i].flags != types)
>  			continue;
> @@ -359,7 +359,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
>  		break;
>  	}
>  
> -	events = flags & PERF_IP_FLAG_BRACH_EVENT_MASK;
> +	events = flags & PERF_IP_FLAG_BRANCH_EVENT_MASK;
>  	for (i = 0; branch_events[i].name; i++) {
>  		if (!(branch_events[i].flags & events))
>  			continue;
> 
> base-commit: b10f74308e1305275e69ddde711ec817cc69e306
> -- 
> 2.34.1
> 


From james.clark at linaro.org  Wed Mar 12 03:02:33 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 12 Mar 2025 10:02:33 +0000
Subject: [PATCH] perf script: Fix typo in branch event mask
In-Reply-To: <20250312075636.429127-1-yujie.liu@intel.com>
References: <20250312075636.429127-1-yujie.liu@intel.com>
Message-ID: <6b43a3e5-b76f-45fc-bb2a-6c47a0a7c511@linaro.org>



On 12/03/2025 7:56 am, Yujie Liu wrote:
> BRACH -> BRANCH
> 
> Fixes: 88b1473135e4 ("perf script: Separate events from branch types")
> Signed-off-by: Yujie Liu <yujie.liu at intel.com>
> ---
>   tools/perf/util/event.h                 | 2 +-
>   tools/perf/util/trace-event-scripting.c | 4 ++--
>   2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
> index c7f4b4b841ca..664bf39567ce 100644
> --- a/tools/perf/util/event.h
> +++ b/tools/perf/util/event.h
> @@ -91,7 +91,7 @@ enum {
>   	PERF_IP_FLAG_VMENTRY		|\
>   	PERF_IP_FLAG_VMEXIT)
>   
> -#define PERF_IP_FLAG_BRACH_EVENT_MASK	\
> +#define PERF_IP_FLAG_BRANCH_EVENT_MASK	\
>   	(PERF_IP_FLAG_BRANCH_MISS |	\
>   	 PERF_IP_FLAG_NOT_TAKEN)
>   
> diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
> index 29cc467be14a..72abb28b7b5a 100644
> --- a/tools/perf/util/trace-event-scripting.c
> +++ b/tools/perf/util/trace-event-scripting.c
> @@ -347,7 +347,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
>   
>   	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);
>   
> -	types = flags & ~PERF_IP_FLAG_BRACH_EVENT_MASK;
> +	types = flags & ~PERF_IP_FLAG_BRANCH_EVENT_MASK;
>   	for (i = 0; sample_flags[i].name; i++) {
>   		if (sample_flags[i].flags != types)
>   			continue;
> @@ -359,7 +359,7 @@ static int sample_flags_to_name(u32 flags, char *str, size_t size)
>   		break;
>   	}
>   
> -	events = flags & PERF_IP_FLAG_BRACH_EVENT_MASK;
> +	events = flags & PERF_IP_FLAG_BRANCH_EVENT_MASK;
>   	for (i = 0; branch_events[i].name; i++) {
>   		if (!(branch_events[i].flags & events))
>   			continue;
> 
> base-commit: b10f74308e1305275e69ddde711ec817cc69e306

Reviewed-by: James Clark <james.clark at linaro.org>



From suraj.gupta2 at amd.com  Wed Mar 12 02:54:10 2025
From: suraj.gupta2 at amd.com (Suraj Gupta)
Date: Wed, 12 Mar 2025 15:24:10 +0530
Subject: [PATCH net-next V2 1/2] dt-bindings: net: xlnx,axi-ethernet: Modify descriptions and phy-mode value to support 2500base-X only configuration
In-Reply-To: <20250312095411.1392379-1-suraj.gupta2@amd.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
Message-ID: <20250312095411.1392379-2-suraj.gupta2@amd.com>

AXI 1G/2.5G Ethernet subsystem supports 1G and 2.5G speeds. Modify
existing binding description, pcs-handle description and add
2500base-x in phy-mode for 2500base-X only configuration.

Signed-off-by: Suraj Gupta <suraj.gupta2 at amd.com>
---
 .../devicetree/bindings/net/xlnx,axi-ethernet.yaml       | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
index fb02e579463c..977f55b98f31 100644
--- a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
+++ b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
@@ -9,10 +9,12 @@ title: AXI 1G/2.5G Ethernet Subsystem
 description: |
   Also called  AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core
   provides connectivity to an external ethernet PHY supporting different
-  interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two
+  interfaces: MII, GMII, RGMII, SGMII, 1000BaseX and 2500BaseX. It also includes two
   segments of memory for buffering TX and RX, as well as the capability of
   offloading TX/RX checksum calculation off the processor.
 
+  AXI 2.5G MAC is incremental speed upgrade of AXI 1G and supports 2.5G speed.
+
   Management configuration is done through the AXI interface, while payload is
   sent and received through means of an AXI DMA controller. This driver
   includes the DMA driver code, so this driver is incompatible with AXI DMA
@@ -62,6 +64,7 @@ properties:
       - rgmii
       - sgmii
       - 1000base-x
+      - 2500base-x
 
   xlnx,phy-type:
     description:
@@ -118,8 +121,8 @@ properties:
     type: object
 
   pcs-handle:
-    description: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X
-      modes, where "pcs-handle" should be used to point to the PCS/PMA PHY,
+    description: Phandle to the internal PCS/PMA PHY in SGMII or 1000base-x/
+      2500base-x modes, where "pcs-handle" should be used to point to the PCS/PMA PHY,
       and "phy-handle" should point to an external PHY if exists.
     maxItems: 1
 
-- 
2.25.1



From robin.murphy at arm.com  Wed Mar 12 03:10:04 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 10:10:04 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <Z9CEIlXoQJ-A0t-d@8bytes.org>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <Z9CEIlXoQJ-A0t-d@8bytes.org>
Message-ID: <d55240a4-fe4a-48ea-b3a8-9a997bb7267c@arm.com>

On 2025-03-11 6:42 pm, Joerg Roedel wrote:
> Hi Robin,
> 
> On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
>> +	/*
>> +	 * And if we do now see any replay calls, they would indicate someone
>> +	 * misusing the dma_configure path outside bus code.
>> +	 */
>> +	if (dev->driver)
>> +		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
> 
> This warning triggers on my workstation (with an AMD IOMMU), any ideas?

Argh! When I moved the dma_configure call into iommu_init_device() for
v2 I moved the warning with it, but of course that needs to stay where
it was, *after* the point that ops->probe_device has had a chance to
filter out irrelevant devices. Does this make it behave?

Thanks,
Robin.

----->8-----
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 09798ddbce9d..1da6c55a0d02 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -437,12 +437,6 @@ static int iommu_init_device(struct device *dev)
  		ret = -ENODEV;
  		goto err_free;
  	}
-	/*
-	 * And if we do now see any replay calls, they would indicate someone
-	 * misusing the dma_configure path outside bus code.
-	 */
-	if (dev->driver)
-		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
  
  	if (!try_module_get(ops->owner)) {
  		ret = -EINVAL;
@@ -565,6 +559,12 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
  	ret = iommu_init_device(dev);
  	if (ret)
  		return ret;
+	/*
+	 * And if we do now see any replay calls, they would indicate someone
+	 * misusing the dma_configure path outside bus code.
+	 */
+	if (dev->driver)
+		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
  
  	group = dev->iommu_group;
  	gdev = iommu_group_alloc_device(group, dev);



From suraj.gupta2 at amd.com  Wed Mar 12 02:54:11 2025
From: suraj.gupta2 at amd.com (Suraj Gupta)
Date: Wed, 12 Mar 2025 15:24:11 +0530
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only configuration.
In-Reply-To: <20250312095411.1392379-1-suraj.gupta2@amd.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
Message-ID: <20250312095411.1392379-3-suraj.gupta2@amd.com>

AXI 1G/2.5G ethernet IP has following synthesis options:
1) SGMII/1000base-X only.
2) 2500base-X only.
3) dynamically switching between (1) and (2).
Add support for 2500base-X only configuration.

Co-developed-by: Harini Katakam <harini.katakam at amd.com>
Signed-off-by: Harini Katakam <harini.katakam at amd.com>
Signed-off-by: Suraj Gupta <suraj.gupta2 at amd.com>
---
 drivers/net/ethernet/xilinx/xilinx_axienet.h  |  2 +-
 .../net/ethernet/xilinx/xilinx_axienet_main.c | 24 +++++++++++++++----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 5ff742103beb..ded3e32999d5 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -274,7 +274,7 @@
 #define XAE_EMMC_RX16BIT	0x01000000 /* 16 bit Rx client enable */
 #define XAE_EMMC_LINKSPD_10	0x00000000 /* Link Speed mask for 10 Mbit */
 #define XAE_EMMC_LINKSPD_100	0x40000000 /* Link Speed mask for 100 Mbit */
-#define XAE_EMMC_LINKSPD_1000	0x80000000 /* Link Speed mask for 1000 Mbit */
+#define XAE_EMMC_LINKSPD_1000_2500	0x80000000 /* Link Speed mask for 1000 or 2500 Mbit */
 
 /* Bit masks for Axi Ethernet PHYC register */
 #define XAE_PHYC_SGMIILINKSPEED_MASK	0xC0000000 /* SGMII link speed mask*/
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 054abf283ab3..0885ce201b0a 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -2583,6 +2583,7 @@ static struct phylink_pcs *axienet_mac_select_pcs(struct phylink_config *config,
 	struct axienet_local *lp = netdev_priv(ndev);
 
 	if (interface == PHY_INTERFACE_MODE_1000BASEX ||
+	    interface == PHY_INTERFACE_MODE_2500BASEX ||
 	    interface ==  PHY_INTERFACE_MODE_SGMII)
 		return &lp->pcs;
 
@@ -2616,8 +2617,9 @@ static void axienet_mac_link_up(struct phylink_config *config,
 	emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
 
 	switch (speed) {
+	case SPEED_2500:
 	case SPEED_1000:
-		emmc_reg |= XAE_EMMC_LINKSPD_1000;
+		emmc_reg |= XAE_EMMC_LINKSPD_1000_2500;
 		break;
 	case SPEED_100:
 		emmc_reg |= XAE_EMMC_LINKSPD_100;
@@ -2627,7 +2629,7 @@ static void axienet_mac_link_up(struct phylink_config *config,
 		break;
 	default:
 		dev_err(&ndev->dev,
-			"Speed other than 10, 100 or 1Gbps is not supported\n");
+			"Speed other than 10, 100, 1Gbps or 2.5Gbps is not supported\n");
 		break;
 	}
 
@@ -3055,7 +3057,8 @@ static int axienet_probe(struct platform_device *pdev)
 			 "error registering MDIO bus: %d\n", ret);
 
 	if (lp->phy_mode == PHY_INTERFACE_MODE_SGMII ||
-	    lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) {
+	    lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX ||
+	    lp->phy_mode == PHY_INTERFACE_MODE_2500BASEX) {
 		np = of_parse_phandle(pdev->dev.of_node, "pcs-handle", 0);
 		if (!np) {
 			/* Deprecated: Always use "pcs-handle" for pcs_phy.
@@ -3083,8 +3086,19 @@ static int axienet_probe(struct platform_device *pdev)
 	lp->phylink_config.dev = &ndev->dev;
 	lp->phylink_config.type = PHYLINK_NETDEV;
 	lp->phylink_config.mac_managed_pm = true;
-	lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
-		MAC_10FD | MAC_100FD | MAC_1000FD;
+	lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
+
+	/* AXI 1G/2.5G ethernet IP has following synthesis options:
+	 * 1) SGMII/1000base-X only.
+	 * 2) 2500base-X only.
+	 * 3) Dynamically switching between (1) and (2), and is not
+	 * implemented in driver.
+	 */
+
+	if (axienet_ior(lp, XAE_ABILITY_OFFSET) & XAE_ABILITY_2_5G)
+		lp->phylink_config.mac_capabilities |= MAC_2500FD;
+	else
+		lp->phylink_config.mac_capabilities |= MAC_10FD | MAC_100FD | MAC_1000FD;
 
 	__set_bit(lp->phy_mode, lp->phylink_config.supported_interfaces);
 	if (lp->switch_x_sgmii) {
-- 
2.25.1



From james.clark at linaro.org  Wed Mar 12 03:11:29 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 12 Mar 2025 10:11:29 +0000
Subject: [PATCH v3] coresight: Add a KUnit test for
 coresight_find_default_sink()
Message-ID: <20250312-james-cs-kunit-test-v3-1-dcfb69730161@linaro.org>

Add a test to confirm that default sink selection skips over an ETF
and returns an ETR even if it's further away.

This also makes it easier to add new unit tests in the future.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
Changes in v3:
- Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
  (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
  when TRBE sinks are registered. This also removes the need for the
  fake CPU ID callback.
- Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test-v2-1-83ba682b976c at linaro.org

Changes in v2:
- Let devm free everything rather than doing individual kfrees:
  "Like with managed drivers, KUnit-managed fake devices are
  automatically cleaned up when the test finishes, but can be manually
  cleaned up early with kunit_device_unregister()."
- Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
---
 drivers/hwtracing/coresight/Kconfig                |  9 +++
 drivers/hwtracing/coresight/Makefile               |  3 +-
 drivers/hwtracing/coresight/coresight-core.c       |  1 +
 .../hwtracing/coresight/coresight-kunit-tests.c    | 77 ++++++++++++++++++++++
 4 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index ecd7086a5b83..f064e3d172b3 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called coresight-dummy.
+
+config CORESIGHT_KUNIT_TESTS
+	  tristate "Enable Coresight unit tests"
+	  depends on KUNIT
+	  default KUNIT_ALL_TESTS
+	  help
+	    Enable Coresight unit tests. Only useful for development and not
+	    intended for production.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 8e62c3150aeb..96f0dfedb1bf 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
 		   coresight-cti-sysfs.o
 obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
-obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
-coresight-ctcu-y := coresight-ctcu-core.o
+obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index bd0a7edd38c9..b101aa133ceb 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
 	}
 	return csdev->def_sink;
 }
+EXPORT_SYMBOL_GPL(coresight_find_default_sink);
 
 static int coresight_remove_sink_ref(struct device *dev, void *data)
 {
diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
new file mode 100644
index 000000000000..87439769207c
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <kunit/test.h>
+#include <kunit/device.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+static struct coresight_device *coresight_test_device(struct device *dev)
+{
+	struct coresight_device *csdev = devm_kcalloc(dev, 1,
+						     sizeof(struct coresight_device),
+						     GFP_KERNEL);
+	csdev->pdata = devm_kcalloc(dev, 1,
+				   sizeof(struct coresight_platform_data),
+				   GFP_KERNEL);
+	return csdev;
+}
+
+static void test_default_sink(struct kunit *test)
+{
+	/*
+	 * ETM -> ETF -> ETR -> CATU
+	 *                ^
+	 *                | default
+	 */
+	struct device *dev = kunit_device_register(test, "coresight_kunit");
+	struct coresight_device *etm = coresight_test_device(dev),
+				*etf = coresight_test_device(dev),
+				*etr = coresight_test_device(dev),
+				*catu = coresight_test_device(dev);
+	struct coresight_connection conn = {};
+	struct coresight_ops_source src_ops = {};
+	struct coresight_ops etm_cs_ops = { .source_ops	= &src_ops };
+
+	etm->type = CORESIGHT_DEV_TYPE_SOURCE;
+	/*
+	 * Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
+	 * a TRBE sink if one is registered.
+	 */
+	etm->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
+	etm->ops = &etm_cs_ops;
+	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
+	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	etr->type = CORESIGHT_DEV_TYPE_SINK;
+	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
+	catu->type = CORESIGHT_DEV_TYPE_HELPER;
+
+	conn.src_dev = etm;
+	conn.dest_dev = etf;
+	coresight_add_out_conn(dev, etm->pdata, &conn);
+
+	conn.src_dev = etf;
+	conn.dest_dev = etr;
+	coresight_add_out_conn(dev, etf->pdata, &conn);
+
+	conn.src_dev = etr;
+	conn.dest_dev = catu;
+	coresight_add_out_conn(dev, etr->pdata, &conn);
+
+	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
+}
+
+static struct kunit_case coresight_testcases[] = {
+	KUNIT_CASE(test_default_sink),
+	{}
+};
+
+static struct kunit_suite coresight_test_suite = {
+	.name = "coresight_test_suite",
+	.test_cases = coresight_testcases,
+};
+
+kunit_test_suites(&coresight_test_suite);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
+MODULE_DESCRIPTION("Arm CoreSight KUnit tests");

---
base-commit: eeafe6a8790ea125252ca2e23c1a2469eaff1d9a
change-id: 20250305-james-cs-kunit-test-3af1df2401e6

Best regards,
-- 
James Clark <james.clark at linaro.org>



From suzuki.poulose at arm.com  Wed Mar 12 03:14:26 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Wed, 12 Mar 2025 10:14:26 +0000
Subject: [PATCH v3] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20250312-james-cs-kunit-test-v3-1-dcfb69730161@linaro.org>
References: <20250312-james-cs-kunit-test-v3-1-dcfb69730161@linaro.org>
Message-ID: <d6194071-bc52-4f67-a36e-fc8d9d1be94c@arm.com>

Hi James


On 12/03/2025 10:11, James Clark wrote:
> Add a test to confirm that default sink selection skips over an ETF
> and returns an ETR even if it's further away.
> 
> This also makes it easier to add new unit tests in the future.
> 
> Reviewed-by: Leo Yan <leo.yan at arm.com>
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
> Changes in v3:
> - Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
>    (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
>    when TRBE sinks are registered. This also removes the need for the
>    fake CPU ID callback.
> - Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test-v2-1-83ba682b976c at linaro.org
> 
> Changes in v2:
> - Let devm free everything rather than doing individual kfrees:
>    "Like with managed drivers, KUnit-managed fake devices are
>    automatically cleaned up when the test finishes, but can be manually
>    cleaned up early with kunit_device_unregister()."
> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
> ---
>   drivers/hwtracing/coresight/Kconfig                |  9 +++
>   drivers/hwtracing/coresight/Makefile               |  3 +-
>   drivers/hwtracing/coresight/coresight-core.c       |  1 +
>   .../hwtracing/coresight/coresight-kunit-tests.c    | 77 ++++++++++++++++++++++
>   4 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index ecd7086a5b83..f064e3d172b3 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>   
>   	  To compile this driver as a module, choose M here: the module will be
>   	  called coresight-dummy.
> +
> +config CORESIGHT_KUNIT_TESTS
> +	  tristate "Enable Coresight unit tests"
> +	  depends on KUNIT
> +	  default KUNIT_ALL_TESTS
> +	  help
> +	    Enable Coresight unit tests. Only useful for development and not
> +	    intended for production.
> +
>   endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 8e62c3150aeb..96f0dfedb1bf 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
>   		   coresight-cti-sysfs.o
>   obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
> -coresight-ctcu-y := coresight-ctcu-core.o
> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index bd0a7edd38c9..b101aa133ceb 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>   	}
>   	return csdev->def_sink;
>   }
> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>   
>   static int coresight_remove_sink_ref(struct device *dev, void *data)
>   {
> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> new file mode 100644
> index 000000000000..87439769207c
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +#include <kunit/device.h>
> +#include <linux/coresight.h>
> +
> +#include "coresight-priv.h"
> +
> +static struct coresight_device *coresight_test_device(struct device *dev)
> +{
> +	struct coresight_device *csdev = devm_kcalloc(dev, 1,
> +						     sizeof(struct coresight_device),
> +						     GFP_KERNEL);
> +	csdev->pdata = devm_kcalloc(dev, 1,
> +				   sizeof(struct coresight_platform_data),
> +				   GFP_KERNEL);
> +	return csdev;
> +}
> +
> +static void test_default_sink(struct kunit *test)
> +{
> +	/*
> +	 * ETM -> ETF -> ETR -> CATU
> +	 *                ^
> +	 *                | default

minor nit: Using ETM here is going to be confusing, with the SUBTYPE we
are using. Please could we rename it something else and also rename the 
variable "etm" ? Say, "source" ?

Rest looks good to me.

Suzuki


> +	 */
> +	struct device *dev = kunit_device_register(test, "coresight_kunit");
> +	struct coresight_device *etm = coresight_test_device(dev),
> +				*etf = coresight_test_device(dev),
> +				*etr = coresight_test_device(dev),
> +				*catu = coresight_test_device(dev);
> +	struct coresight_connection conn = {};
> +	struct coresight_ops_source src_ops = {};
> +	struct coresight_ops etm_cs_ops = { .source_ops	= &src_ops };
> +
> +	etm->type = CORESIGHT_DEV_TYPE_SOURCE;
> +	/*
> +	 * Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
> +	 * a TRBE sink if one is registered.
> +	 */
> +	etm->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
> +	etm->ops = &etm_cs_ops;
> +	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
> +	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
> +	etr->type = CORESIGHT_DEV_TYPE_SINK;
> +	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
> +	catu->type = CORESIGHT_DEV_TYPE_HELPER;
> +
> +	conn.src_dev = etm;
> +	conn.dest_dev = etf;
> +	coresight_add_out_conn(dev, etm->pdata, &conn);
> +
> +	conn.src_dev = etf;
> +	conn.dest_dev = etr;
> +	coresight_add_out_conn(dev, etf->pdata, &conn);
> +
> +	conn.src_dev = etr;
> +	conn.dest_dev = catu;
> +	coresight_add_out_conn(dev, etr->pdata, &conn);
> +
> +	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(etm), etr);
> +}
> +
> +static struct kunit_case coresight_testcases[] = {
> +	KUNIT_CASE(test_default_sink),
> +	{}
> +};
> +
> +static struct kunit_suite coresight_test_suite = {
> +	.name = "coresight_test_suite",
> +	.test_cases = coresight_testcases,
> +};
> +
> +kunit_test_suites(&coresight_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
> +MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
> 
> ---
> base-commit: eeafe6a8790ea125252ca2e23c1a2469eaff1d9a
> change-id: 20250305-james-cs-kunit-test-3af1df2401e6
> 
> Best regards,



From quentin.schulz at cherry.de  Wed Mar 12 03:15:42 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Wed, 12 Mar 2025 11:15:42 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores
 on RK3588j
In-Reply-To: <CABjd4YxF4N1tAgGUZk-oKkMUO+Q9rWHZsas9gMQdJ+TF4A1=NA@mail.gmail.com>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <d8ce8db2-1717-40f8-b53e-24cc71a758c9@cherry.de>
 <CABjd4Yw-r-ogfwcrph4K1wbkybS25gk6LFg8wpqLG27uWdybNA@mail.gmail.com>
 <2914631.KiezcSG77Q@diego>
 <CABjd4YxF4N1tAgGUZk-oKkMUO+Q9rWHZsas9gMQdJ+TF4A1=NA@mail.gmail.com>
Message-ID: <e55125ed-64fb-455e-b1e4-cebe2cf006e4@cherry.de>

Hi all,

On 2/16/25 1:32 PM, Alexey Charkov wrote:
> Hi Heiko,
> 
> On Sat, Feb 15, 2025 at 11:30?PM Heiko St?bner <heiko at sntech.de> wrote:
>>
>> Am Samstag, 15. Februar 2025, 19:59:44 MEZ schrieb Alexey Charkov:
>>> On Tue, Feb 11, 2025 at 7:32?PM Quentin Schulz <quentin.schulz at cherry.de> wrote:
>>>> On 6/17/24 8:28 PM, Alexey Charkov wrote:
[...]
>>>>> +     };
>>>>> +
>>>>> +     cluster2_opp_table: opp-table-cluster2 {
>>>>> +             compatible = "operating-points-v2";
>>>>> +             opp-shared;
>>>>> +
>>>>> +             opp-1416000000 {
>>>>> +                     opp-hz = /bits/ 64 <1416000000>;
>>>>> +                     opp-microvolt = <750000 750000 950000>;
>>>>> +                     clock-latency-ns = <40000>;
>>>>> +             };
>>>>> +             opp-1608000000 {
>>>>> +                     opp-hz = /bits/ 64 <1608000000>;
>>>>> +                     opp-microvolt = <787500 787500 950000>;
>>>>> +                     clock-latency-ns = <40000>;
>>>>> +             };
>>>>> +             opp-1800000000 {
>>>>> +                     opp-hz = /bits/ 64 <1800000000>;
>>>>> +                     opp-microvolt = <875000 875000 950000>;
>>>>> +                     clock-latency-ns = <40000>;
>>>>> +             };
>>>>> +             opp-2016000000 {
>>>>> +                     opp-hz = /bits/ 64 <2016000000>;
>>>>> +                     opp-microvolt = <950000 950000 950000>;
>>>>> +                     clock-latency-ns = <40000>;
>>>>> +             };
>>>>
>>>> opp-1800000000 and opp-2016000000 should be removed as well.
>>>>
>>>> Did I misunderstand what Rockchip did here? Adding Kever in Cc at least
>>>> for awareness on Rockchip side :)
>>>>
>>>> I guess another option could be to mark those above as
>>>>
>>>> turbo-mode;
>>>>
>>>> though no clue what this would entail. From a glance at cpufreq, it
>>>> seems that for Rockchip since we use the default cpufreq-dt, it would
>>>> mark those as unusable, so essentially a no-op, so better remove them
>>>> entirely?
>>>
>>> I believe the opp core just marks 'turbo-mode' opps as
>>> CPUFREQ_BOOST_FREQ, and cpufreq-dt only passes that flag along to the
>>> cpufreq core. But then to actually use those boost frequencies I would
>>> guess the governor needs to somehow know the power/thermal constraints
>>> of the chip?.. Don't know where that is defined.
>>
>> personally I don't believe in "boost" frequencies - except when they are
>> declared officially.
>>
>> Rockchip for the longest time maintains that running the chip outside
>> the declared power/rate envelope can reduce its overall lifetime.
>>
>> So for Rockchip in mainline a "it runs stable for me" has never been a
>> suitable reasoning ;-) .
> 
> My key concern here was perhaps that we are looking at a file inside
> the Rockchip source tree which looks relevant by the name of it, but
> doesn't actually get included anywhere for any of the boards. This may
> or may not constitute an endorsement by Rockchip of any OPPs listed
> there :-D
> 

Rockchip support stated:

"""
If you run overdrive mode, you do not need to include rk3588j.dtsi, and 
you can change it to #incldue rk3588.dtsi to ensure that the maximum 
frequency can reach 2GHz

below picture from datasheet.
"""

The picture is the table 3-2 Recommended operating conditions, page 30 
from the RK3588J datasheet, e.g. 
https://www.lcsc.com/datasheet/lcsc_datasheet_2403201054_Rockchip-RK3588J_C22364189.pdf

What is overdrive?

"""
Overdrive mode brings higher frequency, and the voltage will increase 
accordingly. Under
the overdrive mode for a long time, the chipset may shorten the 
lifetime, especially in
high temperature condition
"""

according to the same datasheet, end of the same table, page 31.

so this seems like a turbo-mode frequency to me.

Additionally, the note for the "normal mode" (the one with the lower 
freqs) states:

"""
Normal mode means the chipset works under safety voltage and frequency. 
For the
industrial environment, highly recommend to keep in normal mode, the 
lifetime is
reasonably guaranteed.
"""

I believe "industrial environment" means RK3588J used in the 
temperatures that aren't OK for the standard RK3588 variant?

> I haven't seen a TRM for the J variant, nor do I have a board with
> RK3588J to run tests, so it would be great if Kever could chime in
> with how these OPPs are different from the others (or not).
> 
>> So while the situation might be strange for the rk3588j, I really only want
>> correct frequencies here please - not any pseudo "turbo freqs".
>>
>> I don't care that much what people do on their own device{s/trees}, but
>> the devicetrees we supply centrally (and to u-boot, etc) should only
>> contain frequencies vetted by the manufacturer.
> 
> Fair enough. Let's just try and get another data point on whether
> these frequencies are vetted or not.
> 

So the higher freqs seems to be vetted (and used by default on 
Rockchip's BSP kernel), it just feels like you aren't really supposed to 
run those higher frequencies all the time? And especially not in 
"industrial environment"?

I would assume we want to stay on the safer side and remove those higher 
frequencies? Heiko?

Cheers,
Quentin


From james.clark at linaro.org  Wed Mar 12 03:19:30 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 12 Mar 2025 10:19:30 +0000
Subject: [PATCH v3] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <d6194071-bc52-4f67-a36e-fc8d9d1be94c@arm.com>
References: <20250312-james-cs-kunit-test-v3-1-dcfb69730161@linaro.org>
 <d6194071-bc52-4f67-a36e-fc8d9d1be94c@arm.com>
Message-ID: <4d058a15-376a-4e9a-bfc0-06bd4ffbd71a@linaro.org>



On 12/03/2025 10:14 am, Suzuki K Poulose wrote:
> Hi James
> 
> 
> On 12/03/2025 10:11, James Clark wrote:
>> Add a test to confirm that default sink selection skips over an ETF
>> and returns an ETR even if it's further away.
>>
>> This also makes it easier to add new unit tests in the future.
>>
>> Reviewed-by: Leo Yan <leo.yan at arm.com>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>> Changes in v3:
>> - Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
>> ?? (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
>> ?? when TRBE sinks are registered. This also removes the need for the
>> ?? fake CPU ID callback.
>> - Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test- 
>> v2-1-83ba682b976c at linaro.org
>>
>> Changes in v2:
>> - Let devm free everything rather than doing individual kfrees:
>> ?? "Like with managed drivers, KUnit-managed fake devices are
>> ?? automatically cleaned up when the test finishes, but can be manually
>> ?? cleaned up early with kunit_device_unregister()."
>> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1- 
>> james.clark at linaro.org
>> ---
>> ? drivers/hwtracing/coresight/Kconfig??????????????? |? 9 +++
>> ? drivers/hwtracing/coresight/Makefile?????????????? |? 3 +-
>> ? drivers/hwtracing/coresight/coresight-core.c?????? |? 1 +
>> ? .../hwtracing/coresight/coresight-kunit-tests.c??? | 77 ++++++++++++ 
>> ++++++++++
>> ? 4 files changed, 88 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/ 
>> coresight/Kconfig
>> index ecd7086a5b83..f064e3d172b3 100644
>> --- a/drivers/hwtracing/coresight/Kconfig
>> +++ b/drivers/hwtracing/coresight/Kconfig
>> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>> ??????? To compile this driver as a module, choose M here: the module 
>> will be
>> ??????? called coresight-dummy.
>> +
>> +config CORESIGHT_KUNIT_TESTS
>> +????? tristate "Enable Coresight unit tests"
>> +????? depends on KUNIT
>> +????? default KUNIT_ALL_TESTS
>> +????? help
>> +??????? Enable Coresight unit tests. Only useful for development and not
>> +??????? intended for production.
>> +
>> ? endif
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/ 
>> coresight/Makefile
>> index 8e62c3150aeb..96f0dfedb1bf 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -51,5 +51,4 @@ coresight-cti-y := coresight-cti-core.o    
>> coresight-cti-platform.o \
>> ???????????? coresight-cti-sysfs.o
>> ? obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>> ? obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>> -obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>> -coresight-ctcu-y := coresight-ctcu-core.o
>> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index bd0a7edd38c9..b101aa133ceb 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct 
>> coresight_device *csdev)
>> ????? }
>> ????? return csdev->def_sink;
>> ? }
>> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
>> ? static int coresight_remove_sink_ref(struct device *dev, void *data)
>> ? {
>> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/ 
>> drivers/hwtracing/coresight/coresight-kunit-tests.c
>> new file mode 100644
>> index 000000000000..87439769207c
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> @@ -0,0 +1,77 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#include <kunit/test.h>
>> +#include <kunit/device.h>
>> +#include <linux/coresight.h>
>> +
>> +#include "coresight-priv.h"
>> +
>> +static struct coresight_device *coresight_test_device(struct device 
>> *dev)
>> +{
>> +??? struct coresight_device *csdev = devm_kcalloc(dev, 1,
>> +???????????????????????????? sizeof(struct coresight_device),
>> +???????????????????????????? GFP_KERNEL);
>> +??? csdev->pdata = devm_kcalloc(dev, 1,
>> +?????????????????? sizeof(struct coresight_platform_data),
>> +?????????????????? GFP_KERNEL);
>> +??? return csdev;
>> +}
>> +
>> +static void test_default_sink(struct kunit *test)
>> +{
>> +??? /*
>> +???? * ETM -> ETF -> ETR -> CATU
>> +???? *??????????????? ^
>> +???? *??????????????? | default
> 
> minor nit: Using ETM here is going to be confusing, with the SUBTYPE we
> are using. Please could we rename it something else and also rename the 
> variable "etm" ? Say, "source" ?
> 
> Rest looks good to me.
> 
> Suzuki
> 
> 

Yeah good point, "Source" makes sense.



From james.clark at linaro.org  Wed Mar 12 03:31:57 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 12 Mar 2025 10:31:57 +0000
Subject: [PATCH v4] coresight: Add a KUnit test for
 coresight_find_default_sink()
Message-ID: <20250312-james-cs-kunit-test-v4-1-ae3dd718a26a@linaro.org>

Add a test to confirm that default sink selection skips over an ETF
and returns an ETR even if it's further away.

This also makes it easier to add new unit tests in the future.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
Changes in v4:
- Rename etm to src now that it's not CORESIGHT_DEV_SUBTYPE_SOURCE_PROC
- Remove the now empty src_ops too
- Fix a rebase mistake in the Makefile that removed CTCU
- Link to v3: https://lore.kernel.org/r/20250312-james-cs-kunit-test-v3-1-dcfb69730161 at linaro.org

Changes in v3:
- Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
  (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
  when TRBE sinks are registered. This also removes the need for the
  fake CPU ID callback.
- Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test-v2-1-83ba682b976c at linaro.org

Changes in v2:
- Let devm free everything rather than doing individual kfrees:
  "Like with managed drivers, KUnit-managed fake devices are
  automatically cleaned up when the test finishes, but can be manually
  cleaned up early with kunit_device_unregister()."
- Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
---
 drivers/hwtracing/coresight/Kconfig                |  9 +++
 drivers/hwtracing/coresight/Makefile               |  1 +
 drivers/hwtracing/coresight/coresight-core.c       |  1 +
 .../hwtracing/coresight/coresight-kunit-tests.c    | 74 ++++++++++++++++++++++
 4 files changed, 85 insertions(+)

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index ecd7086a5b83..f064e3d172b3 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called coresight-dummy.
+
+config CORESIGHT_KUNIT_TESTS
+	  tristate "Enable Coresight unit tests"
+	  depends on KUNIT
+	  default KUNIT_ALL_TESTS
+	  help
+	    Enable Coresight unit tests. Only useful for development and not
+	    intended for production.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 8e62c3150aeb..4e6ea5b05b01 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
 obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
 coresight-ctcu-y := coresight-ctcu-core.o
+obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index fb43ef6a3b1f..47af75ba7a00 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
 	}
 	return csdev->def_sink;
 }
+EXPORT_SYMBOL_GPL(coresight_find_default_sink);
 
 static int coresight_remove_sink_ref(struct device *dev, void *data)
 {
diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
new file mode 100644
index 000000000000..c8f361767c45
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <kunit/test.h>
+#include <kunit/device.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+static struct coresight_device *coresight_test_device(struct device *dev)
+{
+	struct coresight_device *csdev = devm_kcalloc(dev, 1,
+						     sizeof(struct coresight_device),
+						     GFP_KERNEL);
+	csdev->pdata = devm_kcalloc(dev, 1,
+				   sizeof(struct coresight_platform_data),
+				   GFP_KERNEL);
+	return csdev;
+}
+
+static void test_default_sink(struct kunit *test)
+{
+	/*
+	 * Source -> ETF -> ETR -> CATU
+	 *                   ^
+	 *                   | default
+	 */
+	struct device *dev = kunit_device_register(test, "coresight_kunit");
+	struct coresight_device *src = coresight_test_device(dev),
+				*etf = coresight_test_device(dev),
+				*etr = coresight_test_device(dev),
+				*catu = coresight_test_device(dev);
+	struct coresight_connection conn = {};
+
+	src->type = CORESIGHT_DEV_TYPE_SOURCE;
+	/*
+	 * Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
+	 * a TRBE sink if one is registered.
+	 */
+	src->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
+	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
+	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	etr->type = CORESIGHT_DEV_TYPE_SINK;
+	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
+	catu->type = CORESIGHT_DEV_TYPE_HELPER;
+
+	conn.src_dev = src;
+	conn.dest_dev = etf;
+	coresight_add_out_conn(dev, src->pdata, &conn);
+
+	conn.src_dev = etf;
+	conn.dest_dev = etr;
+	coresight_add_out_conn(dev, etf->pdata, &conn);
+
+	conn.src_dev = etr;
+	conn.dest_dev = catu;
+	coresight_add_out_conn(dev, etr->pdata, &conn);
+
+	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(src), etr);
+}
+
+static struct kunit_case coresight_testcases[] = {
+	KUNIT_CASE(test_default_sink),
+	{}
+};
+
+static struct kunit_suite coresight_test_suite = {
+	.name = "coresight_test_suite",
+	.test_cases = coresight_testcases,
+};
+
+kunit_test_suites(&coresight_test_suite);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
+MODULE_DESCRIPTION("Arm CoreSight KUnit tests");

---
base-commit: 3eadce8308bc8d808fd9e3a9d211c84215087451
change-id: 20250305-james-cs-kunit-test-3af1df2401e6

Best regards,
-- 
James Clark <james.clark at linaro.org>



From dsimic at manjaro.org  Wed Mar 12 03:34:21 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Wed, 12 Mar 2025 11:34:21 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores
 on RK3588j
In-Reply-To: <e55125ed-64fb-455e-b1e4-cebe2cf006e4@cherry.de>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <d8ce8db2-1717-40f8-b53e-24cc71a758c9@cherry.de>
 <CABjd4Yw-r-ogfwcrph4K1wbkybS25gk6LFg8wpqLG27uWdybNA@mail.gmail.com>
 <2914631.KiezcSG77Q@diego>
 <CABjd4YxF4N1tAgGUZk-oKkMUO+Q9rWHZsas9gMQdJ+TF4A1=NA@mail.gmail.com>
 <e55125ed-64fb-455e-b1e4-cebe2cf006e4@cherry.de>
Message-ID: <a56b59a21dc3c21192fe45197eee4865@manjaro.org>

Hello Quentin,

On 2025-03-12 11:15, Quentin Schulz wrote:
> On 2/16/25 1:32 PM, Alexey Charkov wrote:
>> On Sat, Feb 15, 2025 at 11:30?PM Heiko St?bner <heiko at sntech.de> 
>> wrote:
>>> Am Samstag, 15. Februar 2025, 19:59:44 MEZ schrieb Alexey Charkov:
>>>> On Tue, Feb 11, 2025 at 7:32?PM Quentin Schulz 
>>>> <quentin.schulz at cherry.de> wrote:
>>>>> On 6/17/24 8:28 PM, Alexey Charkov wrote:
> [...]
>>>>>> +     };
>>>>>> +
>>>>>> +     cluster2_opp_table: opp-table-cluster2 {
>>>>>> +             compatible = "operating-points-v2";
>>>>>> +             opp-shared;
>>>>>> +
>>>>>> +             opp-1416000000 {
>>>>>> +                     opp-hz = /bits/ 64 <1416000000>;
>>>>>> +                     opp-microvolt = <750000 750000 950000>;
>>>>>> +                     clock-latency-ns = <40000>;
>>>>>> +             };
>>>>>> +             opp-1608000000 {
>>>>>> +                     opp-hz = /bits/ 64 <1608000000>;
>>>>>> +                     opp-microvolt = <787500 787500 950000>;
>>>>>> +                     clock-latency-ns = <40000>;
>>>>>> +             };
>>>>>> +             opp-1800000000 {
>>>>>> +                     opp-hz = /bits/ 64 <1800000000>;
>>>>>> +                     opp-microvolt = <875000 875000 950000>;
>>>>>> +                     clock-latency-ns = <40000>;
>>>>>> +             };
>>>>>> +             opp-2016000000 {
>>>>>> +                     opp-hz = /bits/ 64 <2016000000>;
>>>>>> +                     opp-microvolt = <950000 950000 950000>;
>>>>>> +                     clock-latency-ns = <40000>;
>>>>>> +             };
>>>>> 
>>>>> opp-1800000000 and opp-2016000000 should be removed as well.
>>>>> 
>>>>> Did I misunderstand what Rockchip did here? Adding Kever in Cc at 
>>>>> least
>>>>> for awareness on Rockchip side :)
>>>>> 
>>>>> I guess another option could be to mark those above as
>>>>> 
>>>>> turbo-mode;
>>>>> 
>>>>> though no clue what this would entail. From a glance at cpufreq, it
>>>>> seems that for Rockchip since we use the default cpufreq-dt, it 
>>>>> would
>>>>> mark those as unusable, so essentially a no-op, so better remove 
>>>>> them
>>>>> entirely?
>>>> 
>>>> I believe the opp core just marks 'turbo-mode' opps as
>>>> CPUFREQ_BOOST_FREQ, and cpufreq-dt only passes that flag along to 
>>>> the
>>>> cpufreq core. But then to actually use those boost frequencies I 
>>>> would
>>>> guess the governor needs to somehow know the power/thermal 
>>>> constraints
>>>> of the chip?.. Don't know where that is defined.
>>> 
>>> personally I don't believe in "boost" frequencies - except when they 
>>> are
>>> declared officially.
>>> 
>>> Rockchip for the longest time maintains that running the chip outside
>>> the declared power/rate envelope can reduce its overall lifetime.
>>> 
>>> So for Rockchip in mainline a "it runs stable for me" has never been 
>>> a
>>> suitable reasoning ;-) .
>> 
>> My key concern here was perhaps that we are looking at a file inside
>> the Rockchip source tree which looks relevant by the name of it, but
>> doesn't actually get included anywhere for any of the boards. This may
>> or may not constitute an endorsement by Rockchip of any OPPs listed
>> there :-D
> 
> Rockchip support stated:
> 
> """
> If you run overdrive mode, you do not need to include rk3588j.dtsi,
> and you can change it to #incldue rk3588.dtsi to ensure that the
> maximum frequency can reach 2GHz
> 
> below picture from datasheet.
> """
> 
> The picture is the table 3-2 Recommended operating conditions, page 30
> from the RK3588J datasheet, e.g.
> https://www.lcsc.com/datasheet/lcsc_datasheet_2403201054_Rockchip-RK3588J_C22364189.pdf
> 
> What is overdrive?
> 
> """
> Overdrive mode brings higher frequency, and the voltage will increase
> accordingly. Under
> the overdrive mode for a long time, the chipset may shorten the
> lifetime, especially in high temperature condition
> """
> 
> according to the same datasheet, end of the same table, page 31.
> 
> so this seems like a turbo-mode frequency to me.
> 
> Additionally, the note for the "normal mode" (the one with the lower
> freqs) states:
> 
> """
> Normal mode means the chipset works under safety voltage and frequency. 
> For the
> industrial environment, highly recommend to keep in normal mode, the 
> lifetime is
> reasonably guaranteed.
> """
> 
> I believe "industrial environment" means RK3588J used in the
> temperatures that aren't OK for the standard RK3588 variant?

Thanks a lot for obtaining these clarifications!

Yes, I'd say that in this case "industrial environment" boils down
to the extended temperature range for the RK3588J variant.

>> I haven't seen a TRM for the J variant, nor do I have a board with
>> RK3588J to run tests, so it would be great if Kever could chime in
>> with how these OPPs are different from the others (or not).
>> 
>>> So while the situation might be strange for the rk3588j, I really 
>>> only want
>>> correct frequencies here please - not any pseudo "turbo freqs".
>>> 
>>> I don't care that much what people do on their own device{s/trees}, 
>>> but
>>> the devicetrees we supply centrally (and to u-boot, etc) should only
>>> contain frequencies vetted by the manufacturer.
>> 
>> Fair enough. Let's just try and get another data point on whether
>> these frequencies are vetted or not.
> 
> So the higher freqs seems to be vetted (and used by default on
> Rockchip's BSP kernel), it just feels like you aren't really supposed
> to run those higher frequencies all the time? And especially not in
> "industrial environment"?
> 
> I would assume we want to stay on the safer side and remove those
> higher frequencies? Heiko?

I agree, we should remove the higher-frequency OPPs.  I'd like
to go through everything once again in detail and prepare a patch
that removes the unsafe OPPs, and you could review it once it's
on the ML, to make sure it's fine.


From angelogioacchino.delregno at collabora.com  Wed Mar 12 03:35:04 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 12 Mar 2025 11:35:04 +0100
Subject: [PATCH v5 2/2] memory: mtk-smi: mt8188: Add SMI reset and clamp
 for MT8188
In-Reply-To: <20250311122327.20685-3-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
 <20250311122327.20685-3-friday.yang@mediatek.com>
Message-ID: <9dca8772-6bc0-4105-98d7-e4f804b0d637@collabora.com>

Il 11/03/25 13:23, Friday Yang ha scritto:
> From: "Friday Yang" <friday.yang at mediatek.com>
> 
> To prevent handling glitch signals during MTCMOS on/off transitions,
> SMI requires clamp and reset operations. Parse the reset settings for
> SMI LARBs and the clamp settings for the SMI Sub-Common. Register
> genpd callback for the SMI LARBs located in image, camera and IPE
> subsystems, and apply reset and clamp operations within the callback.
> 
> Signed-off-by: Friday Yang <friday.yang at mediatek.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Wed Mar 12 03:35:03 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 12 Mar 2025 11:35:03 +0100
Subject: [PATCH v5 1/2] dt-bindings: memory: mediatek: Add SMI reset and
 clamp for MT8188
In-Reply-To: <20250311122327.20685-2-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
 <20250311122327.20685-2-friday.yang@mediatek.com>
Message-ID: <16a54f79-2c0c-49b5-82af-9538ef43abd5@collabora.com>

Il 11/03/25 13:23, Friday Yang ha scritto:
> From: "Friday Yang" <friday.yang at mediatek.com>
> 
> On the MediaTek platform, some SMI LARBs are directly connected to
> the SMI Common, while others are connected to the SMI Sub-Common,
> which in turn is connected to the SMI Common. The hardware block
> diagram can be described as follows.
> 
>               SMI-Common(Smart Multimedia Interface Common)
>                   |
>           +----------------+------------------+
>           |                |                  |
>           |                |                  |
>           |                |                  |
>           |                |                  |
>           |                |                  |
>         larb0       SMI-Sub-Common0     SMI-Sub-Common1
>                     |      |     |      |             |
>                    larb1  larb2 larb3  larb7       larb9
> 
> For previous discussion on the direction of the code modifications,
> please refer to:
> https://lore.kernel.org/all/CAFGrd9qZhObQXvm2_abqaX83xMLqxjQETB2=wXpobDWU1CnvkA at mail.gmail.com/
> https://lore.kernel.org/all/CAPDyKFpokXV2gJDgowbixTvOH_5VL3B5H8eyhP+KJ5Fasm2rFg at mail.gmail.com/
> 
> On the MediaTek MT8188 SoC platform, we encountered power-off failures
> and SMI bus hang issues during camera stress tests. The issue arises
> because bus glitches are sometimes produced when MTCMOS powers on or
> off. While this is fairly normal, the software must handle these
> glitches to avoid mistaking them for transaction signals. What's
> more, this issue emerged only after the initial upstreaming of this
> binding. Without these patches, the SMI becomes unstable during camera
> stress tests.
> 
> The software solutions can be summarized as follows:
> 
> 1. Use CLAMP to disable the SMI sub-common port after turning off the
>     LARB CG and before turning off the LARB MTCMOS.
> 2. Use CLAMP to disable/enable the SMI sub-common port.
> 3. Implement an AXI reset for SMI LARBs.
> 
> This patch primarily add two changes:
> 1. Add compatible for SMI sub-common on MT8188 SoC.
> 2. Add 'resets' and 'reset-names' properties for SMI LARBs to
>     support SMI reset operations.
> 
> Signed-off-by: Friday Yang <friday.yang at mediatek.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>



From wenst at chromium.org  Wed Mar 12 03:43:38 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:38 +0800
Subject: [PATCH 4/8] arm64: dts: mediatek: mt8186-steelix: Mark second source components for probing
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-5-wenst@chromium.org>

Steelix design has two possible trackpad component sources. Currently
they are all marked as available, along with having workarounds for
shared pinctrl muxing and GPIOs.

Instead, mark them all as "fail-needs-probe" and have the implementation
try to probe which one is present.

Also remove the shared resource workaround by moving the pinctrl entry
for the trackpad interrupt line back into the individual trackpad nodes.

Cc: <stable+noautosel at kernel.org> # Needs accompanying new driver to work
Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 .../boot/dts/mediatek/mt8186-corsola-steelix.dtsi      |  7 +++++++
 .../mediatek/mt8186-corsola-tentacool-sku327683.dts    |  2 ++
 .../mediatek/mt8186-corsola-tentacruel-sku262148.dts   |  2 ++
 arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi       | 10 ++++------
 4 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
index e74e886a00cb..822a177e7c19 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
@@ -123,8 +123,11 @@ trackpad at 2c {
 		reg = <0x2c>;
 		hid-descr-addr = <0x20>;
 		interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pin>;
 		vdd-supply = <&pp3300_s3>;
 		wakeup-source;
+		status = "fail-needs-probe";
 	};
 };
 
@@ -197,3 +200,7 @@ pins-vreg-en {
 		};
 	};
 };
+
+&trackpad {
+	status = "fail-needs-probe";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacool-sku327683.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacool-sku327683.dts
index c3ae6f9616c8..4dbf2cb73a81 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacool-sku327683.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacool-sku327683.dts
@@ -17,6 +17,8 @@ trackpad at 15 {
 		compatible = "hid-over-i2c";
 		reg = <0x15>;
 		interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pin>;
 		hid-descr-addr = <0x0001>;
 		vdd-supply = <&pp3300_s3>;
 		wakeup-source;
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacruel-sku262148.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacruel-sku262148.dts
index 447b57b12b41..ee5bc2cd9e9f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacruel-sku262148.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-tentacruel-sku262148.dts
@@ -19,6 +19,8 @@ trackpad at 15 {
 		compatible = "hid-over-i2c";
 		reg = <0x15>;
 		interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pin>;
 		hid-descr-addr = <0x0001>;
 		vdd-supply = <&pp3300_s3>;
 		wakeup-source;
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
index cebb134331fb..918f17385ba5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
@@ -390,19 +390,17 @@ &i2c1 {
 
 &i2c2 {
 	pinctrl-names = "default";
-	/*
-	 * Trackpad pin put here to work around second source components
-	 * sharing the pinmux in steelix designs.
-	 */
-	pinctrl-0 = <&i2c2_pins>, <&trackpad_pin>;
+	pinctrl-0 = <&i2c2_pins>;
 	clock-frequency = <400000>;
 	i2c-scl-internal-delay-ns = <10000>;
 	status = "okay";
 
-	trackpad at 15 {
+	trackpad: trackpad at 15 {
 		compatible = "elan,ekth3000";
 		reg = <0x15>;
 		interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pin>;
 		vcc-supply = <&pp3300_s3>;
 		wakeup-source;
 	};
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:39 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:39 +0800
Subject: [PATCH 5/8] arm64: dts: mediatek: mt8186: Merge Voltorb device trees
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-6-wenst@chromium.org>

There are only two different SKUs of Voltorb, and the only difference
between them is whether a touchscreen is present or not. This can be
detected by a simple I2C transfer to the address, instead of having
separate device trees.

Merge the two device trees together and simplify the compatible string
list. The dtsi is still kept separate since there is an incoming device
that shares the same design, but with slightly difference components.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 arch/arm64/boot/dts/mediatek/Makefile               |  3 +--
 .../mediatek/mt8186-corsola-voltorb-sku589824.dts   | 13 -------------
 ...orb-sku589825.dts => mt8186-corsola-voltorb.dts} |  5 ++---
 3 files changed, 3 insertions(+), 18 deletions(-)
 delete mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
 rename arch/arm64/boot/dts/mediatek/{mt8186-corsola-voltorb-sku589825.dts => mt8186-corsola-voltorb.dts} (76%)

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 58484e830063..ff67931e7821 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -73,8 +73,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb
-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb
-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku0.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
deleted file mode 100644
index d16834eec87a..000000000000
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
+++ /dev/null
@@ -1,13 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright 2022 Google LLC
- */
-
-/dts-v1/;
-#include "mt8186-corsola-voltorb.dtsi"
-
-/ {
-	model = "Google Voltorb sku589824 board";
-	compatible = "google,voltorb-sku589824", "google,voltorb",
-		     "mediatek,mt8186";
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dts
similarity index 76%
rename from arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts
rename to arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dts
index 45e57f7706cc..cc805408a8b7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dts
@@ -7,9 +7,8 @@
 #include "mt8186-corsola-voltorb.dtsi"
 
 / {
-	model = "Google Voltorb sku589825 board";
-	compatible = "google,voltorb-sku589825", "google,voltorb",
-		     "mediatek,mt8186";
+	model = "Google Voltorb board";
+	compatible = "google,voltorb", "mediatek,mt8186";
 };
 
 &i2c1 {
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:40 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:40 +0800
Subject: [PATCH 6/8] arm64: dts: mediatek: mt8186: Add Squirtle Chromebooks
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-7-wenst@chromium.org>

Add a device tree for the MT8186 based Squirtle Chromebooks, also known
as the Acer Chromebook Spin 311 (R724T). The device is a 2-in-1
convertible.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 arch/arm64/boot/dts/mediatek/Makefile         |   1 +
 .../dts/mediatek/mt8186-corsola-squirtle.dts  | 107 ++++++++++++++++++
 .../dts/mediatek/mt8186-corsola-steelix.dtsi  |   2 +-
 3 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index ff67931e7821..77ce29608170 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -65,6 +65,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-squirtle.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts
new file mode 100644
index 000000000000..f721ad4e5c97
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2024 Google LLC
+ */
+
+/dts-v1/;
+#include "mt8186-corsola-voltorb.dtsi"
+
+/ {
+	model = "Google squirtle board";
+	compatible = "google,squirtle", "mediatek,mt8186";
+	chassis-type = "convertible";
+};
+
+&i2c1 {
+	touchscreen at 10 {
+		compatible = "elan,ekth6915";
+		reg = <0x10>;
+		interrupts-extended = <&pio 12 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_pins>;
+		reset-gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+		vcc33-supply = <&pp3300_s3>;
+		status = "fail-needs-probe";
+	};
+
+	touchscreen at 16 {
+		compatible = "elan,ekth8d18", "elan,ekth6a12nay";
+		reg = <0x16>;
+		interrupts-extended = <&pio 12 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_pins>;
+		reset-gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+		vcc33-supply = <&pp3300_s3>;
+		status = "fail-needs-probe";
+	};
+};
+
+&i2c2 {
+	trackpad at 68 {
+		compatible = "hid-over-i2c";
+		reg = <0x68>;
+		hid-descr-addr = <0x20>;
+		interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pin>;
+		vdd-supply = <&pp3300_s3>;
+		wakeup-source;
+		status = "fail-needs-probe";
+	};
+};
+
+&i2c5 {
+	clock-frequency = <400000>;
+
+	/delete-node/ codec at 1a;
+
+	rt5650: codec at 1a {
+		compatible = "realtek,rt5650";
+		reg = <0x1a>;
+		interrupts-extended = <&pio 17 IRQ_TYPE_EDGE_BOTH>;
+		avdd-supply = <&mt6366_vio18_reg>;
+		cpvdd-supply = <&mt6366_vio18_reg>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&speaker_codec_pins_default>;
+		cbj-sleeve-gpios = <&pio 150 GPIO_ACTIVE_HIGH>;
+		#sound-dai-cells = <0>;
+		realtek,dmic1-data-pin = <2>;
+		realtek,jd-mode = <2>;
+	};
+};
+
+&sound {
+	compatible = "mediatek,mt8186-mt6366-rt5650-sound";
+	model = "mt8186_rt5650";
+
+	audio-routing =
+		"Headphone", "HPOL",
+		"Headphone", "HPOR",
+		"HDMI1", "TX";
+
+	hs-playback-dai-link {
+		codec {
+			sound-dai = <&rt5650>;
+		};
+	};
+
+	hs-capture-dai-link {
+		codec {
+			sound-dai = <&rt5650>;
+		};
+	};
+
+	spk-hdmi-playback-dai-link {
+		codec {
+			sound-dai = <&it6505dptx>;
+		};
+	};
+};
+
+&speaker_codec {
+	status = "disabled";
+};
+
+&trackpad_steelix {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
index 822a177e7c19..8a196dc9a96b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-steelix.dtsi
@@ -118,7 +118,7 @@ &i2c2 {
 	i2c-scl-internal-delay-ns = <22000>;
 
 	/* second source component */
-	trackpad at 2c {
+	trackpad_steelix: trackpad at 2c {
 		compatible = "hid-over-i2c";
 		reg = <0x2c>;
 		hid-descr-addr = <0x20>;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:41 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:41 +0800
Subject: [PATCH 7/8] platform/chrome: of_hw_prober: Support trackpad probing on Corsola family
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-8-wenst@chromium.org>

Various MT8186 Corsola Chromebooks (squirtle, steelix and voltorb
families) have second source trackpads that need to be probed.
The power supply for these are always on and their reset/enable
lines are not exposed.

Add them to the probing list.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 drivers/platform/chrome/chromeos_of_hw_prober.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
index c6992f5cdc76..eb01851e1cf5 100644
--- a/drivers/platform/chrome/chromeos_of_hw_prober.c
+++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
@@ -57,6 +57,7 @@ static int chromeos_i2c_component_prober(struct device *dev, const void *_data)
 	}
 
 DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen);
+DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(trackpad);
 
 DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad);
 
@@ -84,6 +85,18 @@ static const struct hw_prober_entry hw_prober_platforms[] = {
 		.compatible = "google,hana",
 		.prober = chromeos_i2c_component_prober,
 		.data = &chromeos_i2c_probe_hana_trackpad,
+	}, {
+		.compatible = "google,squirtle",
+		.prober = chromeos_i2c_component_prober,
+		.data = &chromeos_i2c_probe_dumb_trackpad,
+	}, {
+		.compatible = "google,steelix",
+		.prober = chromeos_i2c_component_prober,
+		.data = &chromeos_i2c_probe_dumb_trackpad,
+	}, {
+		.compatible = "google,voltorb",
+		.prober = chromeos_i2c_component_prober,
+		.data = &chromeos_i2c_probe_dumb_trackpad,
 	},
 };
 
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:42 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:42 +0800
Subject: [PATCH 8/8] platform/chrome: of_hw_prober: Support touchscreen probing on Squirtle
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-9-wenst@chromium.org>

The MT8186 Squirtle Chromebook is built with one of two possible
touchscreens. Let the prober probe for them.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 drivers/platform/chrome/chromeos_of_hw_prober.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
index eb01851e1cf5..a3ec583f316c 100644
--- a/drivers/platform/chrome/chromeos_of_hw_prober.c
+++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
@@ -59,6 +59,7 @@ static int chromeos_i2c_component_prober(struct device *dev, const void *_data)
 DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen);
 DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(trackpad);
 
+DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(touchscreen);
 DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad);
 
 static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = {
@@ -76,6 +77,17 @@ static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = {
 	},
 };
 
+static const struct chromeos_i2c_probe_data chromeos_i2c_probe_squirtle_touchscreen = {
+	.cfg = &chromeos_i2c_probe_simple_touchscreen_cfg,
+	.opts = &(const struct i2c_of_probe_simple_opts) {
+		.res_node_compatible = "elan,ekth6a12nay",
+		.supply_name = "vcc33",
+		.gpio_name = "reset",
+		.post_power_on_delay_ms = 10,
+		.post_gpio_config_delay_ms = 300,
+	},
+};
+
 static const struct hw_prober_entry hw_prober_platforms[] = {
 	{
 		.compatible = "google,hana",
@@ -89,6 +101,10 @@ static const struct hw_prober_entry hw_prober_platforms[] = {
 		.compatible = "google,squirtle",
 		.prober = chromeos_i2c_component_prober,
 		.data = &chromeos_i2c_probe_dumb_trackpad,
+	}, {
+		.compatible = "google,squirtle",
+		.prober = chromeos_i2c_component_prober,
+		.data = &chromeos_i2c_probe_squirtle_touchscreen,
 	}, {
 		.compatible = "google,steelix",
 		.prober = chromeos_i2c_component_prober,
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From james.clark at linaro.org  Wed Mar 12 03:46:50 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 12 Mar 2025 10:46:50 +0000
Subject: [PATCH] coresight: configfs: Constify struct config_item_type
In-Reply-To: <d8164311-83e7-4fb0-ab82-90e1a2762b01@linaro.org>
References: <1011717e5ed35ec12113a0d8c233823e820fb524.1723368522.git.christophe.jaillet@wanadoo.fr>
 <d8164311-83e7-4fb0-ab82-90e1a2762b01@linaro.org>
Message-ID: <bed04866-a477-498a-b33a-a631759733e2@linaro.org>



On 12/08/2024 10:12 am, James Clark wrote:
> 
> 
> On 11/08/2024 10:30 am, Christophe JAILLET wrote:
>> 'struct config_item_type' is not modified in this driver.
>>
>> These structures are only used with config_group_init_type_name() which
>> takes a "const struct config_item_type *" as a 3rd argument or with
>> struct config_group.cg_item.ci_type which is also a "const struct
>> config_item_type??? *".
>>
>> Constifying this structure moves some data to a read-only section, so
>> increase overall security, especially when the structure holds some
>> function pointers.
>>
>> On a x86_64, with allmodconfig:
>> Before:
>> ======
>> ??? text?????? data??????? bss??????? dec??????? hex??? filename
>> ??? 4904?????? 1376??????? 136?????? 6416?????? 1910??? drivers/ 
>> hwtracing/coresight/coresight-syscfg-configfs.o
>>
>> After:
>> =====
>> ??? text?????? data??????? bss??????? dec??????? hex??? filename
>> ??? 5264?????? 1120???????? 16?????? 6400?????? 1900??? drivers/ 
>> hwtracing/coresight/coresight-syscfg-configfs.o
>>
>> Signed-off-by: Christophe JAILLET <christophe.jaillet at wanadoo.fr>
>> ---
>> Compile tested-only.
>> ---
>> ? .../hwtracing/coresight/coresight-syscfg-configfs.c? | 12 ++++++------
>> ? 1 file changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c 
>> b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
>> index 433ede94dd63..213b4159b062 100644
>> --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
>> +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
>> @@ -160,7 +160,7 @@ static struct configfs_attribute 
>> *cscfg_config_view_attrs[] = {
>> ????? NULL,
>> ? };
>> -static struct config_item_type cscfg_config_view_type = {
>> +static const struct config_item_type cscfg_config_view_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ????? .ct_attrs = cscfg_config_view_attrs,
>> ? };
>> @@ -170,7 +170,7 @@ static struct configfs_attribute 
>> *cscfg_config_preset_attrs[] = {
>> ????? NULL,
>> ? };
>> -static struct config_item_type cscfg_config_preset_type = {
>> +static const struct config_item_type cscfg_config_preset_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ????? .ct_attrs = cscfg_config_preset_attrs,
>> ? };
>> @@ -272,7 +272,7 @@ static struct configfs_attribute 
>> *cscfg_feature_view_attrs[] = {
>> ????? NULL,
>> ? };
>> -static struct config_item_type cscfg_feature_view_type = {
>> +static const struct config_item_type cscfg_feature_view_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ????? .ct_attrs = cscfg_feature_view_attrs,
>> ? };
>> @@ -309,7 +309,7 @@ static struct configfs_attribute 
>> *cscfg_param_view_attrs[] = {
>> ????? NULL,
>> ? };
>> -static struct config_item_type cscfg_param_view_type = {
>> +static const struct config_item_type cscfg_param_view_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ????? .ct_attrs = cscfg_param_view_attrs,
>> ? };
>> @@ -380,7 +380,7 @@ static struct config_group 
>> *cscfg_create_feature_group(struct cscfg_feature_desc
>> ????? return &feat_view->group;
>> ? }
>> -static struct config_item_type cscfg_configs_type = {
>> +static const struct config_item_type cscfg_configs_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ? };
>> @@ -414,7 +414,7 @@ void cscfg_configfs_del_config(struct 
>> cscfg_config_desc *config_desc)
>> ????? }
>> ? }
>> -static struct config_item_type cscfg_features_type = {
>> +static const struct config_item_type cscfg_features_type = {
>> ????? .ct_owner = THIS_MODULE,
>> ? };
> 
> Reviewed-by: James Clark <james.clark at linaro.org>

Ping. Just found this one hanging in my coresight branch. Still applies 
cleanly.

Thanks



From sudeep.holla at arm.com  Wed Mar 12 03:52:23 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 10:52:23 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z9AdICiyaCmzKh-N@bogus>
References: <20250218133619.GA22647@nxa18884-linux>
 <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus>
 <Z87sGF_jHKau_FMe@bogus>
 <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <Z9AdICiyaCmzKh-N@bogus>
Message-ID: <Z9FnZzBQuZ1j5k3I@bogus>

On Tue, Mar 11, 2025 at 11:23:12AM +0000, Sudeep Holla wrote:
> On Tue, Mar 11, 2025 at 11:12:45AM +0000, Peng Fan wrote:
> >
> > So it is clear that wrong fw_devlink is created, it is because scmi cpufreq device is
> > created earlier and when device_add, the below logic makes the fwnode pointer points
> > to scmi cpufreq device.
> >         if (dev->fwnode && !dev->fwnode->dev) {
> >                 dev->fwnode->dev = dev;
> >                 fw_devlink_link_device(dev);
> >         }
> >
>
> Thanks, looks like simple way to reproduce the issue. I will give it a try.
>

I could reproduce but none of my solution solved the problem completely
or properly. And I don't like the DT proposal you came up with. I am
not inclined to just drop this fwnode setting in the scmi devices and
just use of_node.

-- 
Regards,
Sudeep


From suzuki.poulose at arm.com  Wed Mar 12 04:04:49 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Wed, 12 Mar 2025 11:04:49 +0000
Subject: [PATCH] coresight: configfs: Constify struct config_item_type
In-Reply-To: <1011717e5ed35ec12113a0d8c233823e820fb524.1723368522.git.christophe.jaillet@wanadoo.fr>
References: <1011717e5ed35ec12113a0d8c233823e820fb524.1723368522.git.christophe.jaillet@wanadoo.fr>
Message-ID: <174177747268.10135.1485424994901107067.b4-ty@arm.com>


On Sun, 11 Aug 2024 11:30:20 +0200, Christophe JAILLET wrote:
> 'struct config_item_type' is not modified in this driver.
> 
> These structures are only used with config_group_init_type_name() which
> takes a "const struct config_item_type *" as a 3rd argument or with
> struct config_group.cg_item.ci_type which is also a "const struct
> config_item_type	*".
> 
> [...]

Applied, thanks!

[1/1] coresight: configfs: Constify struct config_item_type
      https://git.kernel.org/coresight/c/b5060c17

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From dawid.osuchowski at linux.intel.com  Wed Mar 12 04:06:21 2025
From: dawid.osuchowski at linux.intel.com (Dawid Osuchowski)
Date: Wed, 12 Mar 2025 12:06:21 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <20250312095411.1392379-3-suraj.gupta2@amd.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
Message-ID: <93f1c6d0-a1fe-4154-a31d-20cc878476d9@linux.intel.com>

On 2025-03-12 10:54 AM, Suraj Gupta wrote:
> AXI 1G/2.5G ethernet IP has following synthesis options:
> 1) SGMII/1000base-X only.
> 2) 2500base-X only.
> 3) dynamically switching between (1) and (2).
> Add support for 2500base-X only configuration.

Hi, thanks for the patch.

nit: a discrepancy between the commit description for and the comments 
in the code for 3)

Maybe adding that information here in the commit description would make 
sense as well? Or giving a bit of a background that SGMII/1000base-X is 
already implemented in the driver and you are adding 2500base-X only 
support.

> +	/* AXI 1G/2.5G ethernet IP has following synthesis options:
> +	 * 1) SGMII/1000base-X only.
> +	 * 2) 2500base-X only.
> +	 * 3) Dynamically switching between (1) and (2), and is not
> +	 * implemented in driver.
> +	 */

For the rest of the patch, it looks good to me but I'd rather have 
someone more experienced provide the Reviewed-By tag if they find the 
patch appropriate.

Best regards,
Dawid


From christopher.obbard at linaro.org  Wed Mar 12 04:10:56 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Wed, 12 Mar 2025 12:10:56 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as built-in
In-Reply-To: <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com> <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org>
Message-ID: <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>

Hi Krzysztof,

On Wed, 12 Mar 2025 at 09:56, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 11/03/2025 20:15, Christopher Obbard wrote:
> > Hi Dmitry,
> >
> > On Tue, 11 Mar 2025 at 19:58, Dmitry Baryshkov <lumag at kernel.org> wrote:
> >>
> >> On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
> >>> I sent this patch to start the discussion, some things I found:
> >>>
> >>> 1) Some interconnects are missing from arm defconfig. Should they be =y too ?
> >>
> >> No, unless those are required for the UART console.
> >
> > OK, that makes sense. FWIW the cryptic (to me, at least) commit log on
> > https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eee808134ecf1c1093ff1ddfc056dc5e469d0c3
> > made me think that the interconnects should be built-in on all devices.
> >
> > Of course, the real problem here is RB3gen2 not actually finding the
> > UFS/eMMC device due to no interconnect driver.
> > Until now, I have been building that into the kernel. I will
> > investigate instead shoving into the initrd (in both debian and
> > fedora) which should solve my issue and render this patchset useless.
>
> For Qualcomm platforms you are expected to always have initramfs, thus
> you will have the modules for UFS/eMMC mounts. I don't understand the
> problem which you were trying to solve.
>
> The interconnects were built in *only* because of need for serial
> console. Only.

Thanks for confirming. It is all clear now.

Consider this patch dropped from my side.

For reference, I am working on updating initramfs generation tools in
Debian/Fedora to include the required interconnect modules. Currently
the interconnect drivers are built as modules in these distros, but
are not included in the initrd. That is where my confusion initially
stemmed from.

Thanks,

Chris


From tglx at linutronix.de  Wed Mar 12 04:13:32 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Wed, 12 Mar 2025 12:13:32 +0100
Subject: [GIT PULL] Generic entry for ARM
In-Reply-To: <CACRpkdZCiiMTwf7eGJJ9aCKFOC3_xTGv1JKQUijjyp+_++cZ_A@mail.gmail.com>
References: <CACRpkdZCiiMTwf7eGJJ9aCKFOC3_xTGv1JKQUijjyp+_++cZ_A@mail.gmail.com>
Message-ID: <87ecz2zelf.ffs@tglx>

On Fri, Feb 28 2025 at 13:49, Linus Walleij wrote:
> please consider pulling the following git branch for generic entry,
> see below.
>
> This branch was just harvested from my own v5 patch series on
> lore with b4 am -t 20250225-arm-generic-entry-v5-0-2f02313653e5 at linaro.org
> then git am on top of v6.14-rc1, so you can do the same if you
> prefer.
>
> It's possible to squash patches, even all of them into one
> big all-or-nothing patch, given the not very gradual nature generic
> entry conversion seems to have.
>
> Main upsides and downsides are in the signed tag.
>
> I don't know who the most important stakeholders are, but I guess
> the context tracker maintainer (Paul McKenney) and the people working
> on generic entry (tglx) could have a say on how important this is, or isn't.
>
> I think it's pretty neat.

It's valuable to consolidate these common functionalities across
architectures as it reduces maintainence costs.

I read through the patches and did not find anything offending there.

Thanks for doing that!

Acked-by: Thomas Gleixner <tglx at linutronix.de>


From lorenzo at kernel.org  Wed Mar 12 04:13:44 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:44 +0100
Subject: [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to
 support MLO
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>

This series is the second preliminary work needed to support MLO in
MT7996 driver.

---
Lorenzo Bianconi (9):
      wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature
      wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read to support MLO
      wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO
      wifi: mt76: mt7996: rework mt7996_mac_sta_poll to support MLO
      wifi: mt76: mt7996: rework mt7996_update_mu_group to support MLO
      wifi: mt76: mt7996: rework mt7996_net_fill_forward_path to support MLO
      wifi: mt76: mt7996: set vif default link_id adding/removing vif links
      wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
      wifi: mt76: mt7996: Update mt7996_tx to MLO support

Shayne Chen (12):
      wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO
      wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
      wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine
      wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support
      wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb()
      wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO
      wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload to support MLO
      wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO
      wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts()
      wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr to support MLO
      wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov to support MLO
      wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO

 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    |  54 ++-
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 163 +++++--
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 493 ++++++++++++++-------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 321 +++++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h    |  32 ++
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  43 +-
 6 files changed, 754 insertions(+), 352 deletions(-)
---
base-commit: 61cf5540d86945a531dd939e90e72a4b134d7cb8
change-id: 20250312-b4-mt7996-mlo-p2-dd8efe4b6964

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From lorenzo at kernel.org  Wed Mar 12 04:13:45 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:45 +0100
Subject: [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl
 to MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-1-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Update mt7996_mcu_add_rate_ctrl routine and all the called subroutines
to support MLO.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |   9 +-
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |   4 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 144 +++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  15 ++-
 4 files changed, 96 insertions(+), 76 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 7ddd4b0cadf5d1983379a93ba56da461748ca60e..48ba975f069c5062f450326a359ff3442ac96f30 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2294,10 +2294,15 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 		if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
 			       IEEE80211_RC_NSS_CHANGED |
 			       IEEE80211_RC_BW_CHANGED))
-			mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
+			mt7996_mcu_add_rate_ctrl(dev, vif, &vif->bss_conf,
+						 &sta->deflink,
+						 &msta->vif->deflink,
+						 msta_link, true);
 
 		if (changed & IEEE80211_RC_SMPS_CHANGED)
-			mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
+			mt7996_mcu_set_fixed_field(dev, &sta->deflink,
+						   &msta->vif->deflink,
+						   msta_link, NULL,
 						   RATE_PARAM_MMPS_UPDATE);
 
 		spin_lock_bh(&dev->mt76.sta_poll_lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 11ad95e05b94857c95375cdf877518e7ee89f08e..25dbf086c8ef02307ef2510b21853b1eee28f922 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1046,7 +1046,9 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			if (err)
 				return err;
 
-			err = mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
+			err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
+						       link_sta, link,
+						       msta_link, false);
 			if (err)
 				return err;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index e6ebb309a8257637c122702df2f2924649b7fabe..0cc822a8a6799a4552fa537cab2f13d6537bb1a8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -167,11 +167,11 @@ mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta,
 }
 
 static void
-mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
-			   const u16 *mask)
+mt7996_mcu_set_sta_vht_mcs(struct ieee80211_link_sta *link_sta,
+			   __le16 *vht_mcs, const u16 *mask)
 {
-	u16 mcs, mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
-	int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
+	u16 mcs, mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map);
+	int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
 
 	for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {
 		switch (mcs_map & 0x3) {
@@ -193,13 +193,13 @@ mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
 }
 
 static void
-mt7996_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
-			  const u8 *mask)
+mt7996_mcu_set_sta_ht_mcs(struct ieee80211_link_sta *link_sta,
+			  u8 *ht_mcs, const u8 *mask)
 {
-	int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
+	int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
 
 	for (nss = 0; nss < max_nss; nss++)
-		ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss];
+		ht_mcs[nss] = link_sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
 }
 
 static int
@@ -1888,18 +1888,18 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
 				     MCU_WM_UNI_CMD(RA), true);
 }
 
-int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta, void *data, u32 field)
+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
+			       void *data, u32 field)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sta_phy_uni *phy = data;
 	struct sta_rec_ra_fixed_uni *ra;
 	struct sk_buff *skb;
 	struct tlv *tlv;
 
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
@@ -1919,7 +1919,7 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
 			ra->phy = *phy;
 		break;
 	case RATE_PARAM_MMPS_UPDATE:
-		ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
+		ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
 		break;
 	default:
 		break;
@@ -1931,12 +1931,13 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
 }
 
 static int
-mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta)
+mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct cfg80211_chan_def *chandef = &mvif->deflink.phy->mt76->chandef;
-	struct cfg80211_bitrate_mask *mask = &mvif->deflink.bitrate_mask;
+	struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
+	struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
 	enum nl80211_band band = chandef->chan->band;
 	struct sta_phy_uni phy = {};
 	int ret, nrates = 0;
@@ -1957,11 +1958,11 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		}								\
 	} while (0)
 
-	if (sta->deflink.he_cap.has_he) {
+	if (link_sta->he_cap.has_he) {
 		__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
-	} else if (sta->deflink.vht_cap.vht_supported) {
+	} else if (link_sta->vht_cap.vht_supported) {
 		__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
-	} else if (sta->deflink.ht_cap.ht_supported) {
+	} else if (link_sta->ht_cap.ht_supported) {
 		__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
 	} else {
 		nrates = hweight32(mask->control[band].legacy);
@@ -1978,7 +1979,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	/* fixed single rate */
 	if (nrates == 1) {
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_MCS);
 		if (ret)
 			return ret;
@@ -1987,7 +1989,6 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 	/* fixed GI */
 	if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
 	    mask->control[band].he_gi != GENMASK(7, 0)) {
-		struct mt7996_sta_link *msta_link = (void *)sta->drv_priv;
 		u32 addr;
 
 		/* firmware updates only TXCMD but doesn't take WTBL into
@@ -1995,12 +1996,13 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		 * actual txrate hardware sends out.
 		 */
 		addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7);
-		if (sta->deflink.he_cap.has_he)
+		if (link_sta->he_cap.has_he)
 			mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
 		else
 			mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
 
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_GI);
 		if (ret)
 			return ret;
@@ -2008,7 +2010,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	/* fixed HE_LTF */
 	if (mask->control[band].he_ltf != GENMASK(7, 0)) {
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_HE_LTF);
 		if (ret)
 			return ret;
@@ -2019,30 +2022,32 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 static void
 mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
-			     struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *link_conf,
+			     struct ieee80211_link_sta *link_sta,
+			     struct mt7996_vif_link *link)
 {
 #define INIT_RCPI 180
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt76_phy *mphy = mvif->deflink.phy->mt76;
+	struct mt76_phy *mphy = link->phy->mt76;
 	struct cfg80211_chan_def *chandef = &mphy->chandef;
-	struct cfg80211_bitrate_mask *mask = &mvif->deflink.bitrate_mask;
+	struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
+	u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0;
 	enum nl80211_band band = chandef->chan->band;
 	struct sta_rec_ra_uni *ra;
 	struct tlv *tlv;
-	u32 supp_rate = sta->deflink.supp_rates[band];
-	u32 cap = sta->wme ? STA_CAP_WMM : 0;
+	u32 supp_rate = link_sta->supp_rates[band];
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
 	ra = (struct sta_rec_ra_uni *)tlv;
 
 	ra->valid = true;
 	ra->auto_rate = true;
-	ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink);
+	ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, link_sta);
 	ra->channel = chandef->chan->hw_value;
-	ra->bw = (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ?
-		 CMD_CBW_320MHZ : sta->deflink.bandwidth;
+	ra->bw = (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ?
+		 CMD_CBW_320MHZ : link_sta->bandwidth;
 	ra->phy.bw = ra->bw;
-	ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
+	ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
 
 	if (supp_rate) {
 		supp_rate &= mask->control[band].legacy;
@@ -2062,60 +2067,60 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
 		}
 	}
 
-	if (sta->deflink.ht_cap.ht_supported) {
+	if (link_sta->ht_cap.ht_supported) {
 		ra->supp_mode |= MODE_HT;
-		ra->af = sta->deflink.ht_cap.ampdu_factor;
-		ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
+		ra->af = link_sta->ht_cap.ampdu_factor;
+		ra->ht_gf = !!(link_sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
 
 		cap |= STA_CAP_HT;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
 			cap |= STA_CAP_SGI_20;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
 			cap |= STA_CAP_SGI_40;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)
 			cap |= STA_CAP_TX_STBC;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
 			cap |= STA_CAP_RX_STBC;
-		if (vif->bss_conf.ht_ldpc &&
-		    (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
+		if (link_conf->ht_ldpc &&
+		    (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
 			cap |= STA_CAP_LDPC;
 
-		mt7996_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,
+		mt7996_mcu_set_sta_ht_mcs(link_sta, ra->ht_mcs,
 					  mask->control[band].ht_mcs);
 		ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
 	}
 
-	if (sta->deflink.vht_cap.vht_supported) {
+	if (link_sta->vht_cap.vht_supported) {
 		u8 af;
 
 		ra->supp_mode |= MODE_VHT;
 		af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
-			       sta->deflink.vht_cap.cap);
+			       link_sta->vht_cap.cap);
 		ra->af = max_t(u8, ra->af, af);
 
 		cap |= STA_CAP_VHT;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
 			cap |= STA_CAP_VHT_SGI_80;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)
 			cap |= STA_CAP_VHT_SGI_160;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
 			cap |= STA_CAP_VHT_TX_STBC;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
 			cap |= STA_CAP_VHT_RX_STBC;
-		if ((vif->type != NL80211_IFTYPE_AP || vif->bss_conf.vht_ldpc) &&
-		    (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
+		if ((vif->type != NL80211_IFTYPE_AP || link_conf->vht_ldpc) &&
+		    (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
 			cap |= STA_CAP_VHT_LDPC;
 
-		mt7996_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,
+		mt7996_mcu_set_sta_vht_mcs(link_sta, ra->supp_vht_mcs,
 					   mask->control[band].vht_mcs);
 	}
 
-	if (sta->deflink.he_cap.has_he) {
+	if (link_sta->he_cap.has_he) {
 		ra->supp_mode |= MODE_HE;
 		cap |= STA_CAP_HE;
 
-		if (sta->deflink.he_6ghz_capa.capa)
-			ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+		if (link_sta->he_6ghz_capa.capa)
+			ra->af = le16_get_bits(link_sta->he_6ghz_capa.capa,
 					       IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
 	}
 	ra->sta_cap = cpu_to_le32(cap);
@@ -2123,16 +2128,17 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
 	memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
 }
 
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     struct ieee80211_sta *sta, bool changed)
+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *link_conf,
+			     struct ieee80211_link_sta *link_sta,
+			     struct mt7996_vif_link *link,
+			     struct mt7996_sta_link *msta_link, bool changed)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sk_buff *skb;
 	int ret;
 
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
@@ -2143,19 +2149,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	 * update sta_rec_he here.
 	 */
 	if (changed)
-		mt7996_mcu_sta_he_tlv(skb, &sta->deflink, &mvif->deflink);
+		mt7996_mcu_sta_he_tlv(skb, link_sta, link);
 
 	/* sta_rec_ra accommodates BW, NSS and only MCS range format
 	 * i.e 0-{7,8,9} for VHT.
 	 */
-	mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
+	mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link);
 
 	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
 				    MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 	if (ret)
 		return ret;
 
-	return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
+	return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link);
 }
 
 static int
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 84b9ff707d56501d212932a9fa6a3037259a1077..a91a50b72218c6a2d0dd32968681325ea7e6a042 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -593,16 +593,23 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 				    struct ieee80211_vif *vif, u32 changed);
 int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_he_obss_pd *he_obss_pd);
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     struct ieee80211_sta *sta, bool changed);
+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *link_conf,
+			     struct ieee80211_link_sta *link_sta,
+			     struct mt7996_vif_link *link,
+			     struct mt7996_sta_link *msta_link, bool changed);
 int mt7996_set_channel(struct mt76_phy *mphy);
 int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
 int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		      struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
 				   void *data, u16 version);
-int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta, void *data, u32 field);
+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
+			       void *data, u32 field);
 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
 int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
 int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:46 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:46 +0100
Subject: [PATCH 02/21] wifi: mt76: mt7996: Add
 mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-2-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

mt7996_mcu_sta_mld_setup_tlv is needed to push MLO configuration to the
MCU. This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 79 +++++++++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 32 ++++++++++
 2 files changed, 111 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 0cc822a8a6799a4552fa537cab2f13d6537bb1a8..ac01eb880e2a6f6ef3a81591bcacd2b90c48986a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2197,6 +2197,80 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				 sizeof(req), true);
 }
 
+static void
+mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+			     struct ieee80211_sta *sta)
+{
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	unsigned long links = sta->valid_links;
+	unsigned int nlinks = hweight16(links);
+	struct mld_setup_link *mld_setup_link;
+	struct sta_rec_mld_setup *mld_setup;
+	struct mt7996_sta_link *msta_link;
+	struct ieee80211_vif *vif;
+	unsigned int link_id;
+	struct tlv *tlv;
+
+	msta_link = mt76_dereference(msta->link[msta->deflink_id], &dev->mt76);
+	if (!msta_link)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD,
+				      sizeof(struct sta_rec_mld_setup) +
+				      sizeof(struct mld_setup_link) * nlinks);
+
+	mld_setup = (struct sta_rec_mld_setup *)tlv;
+	memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN);
+	mld_setup->setup_wcid = cpu_to_le16(msta_link->wcid.idx);
+	mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
+
+	if (nlinks > 1) {
+		link_id = __ffs(links & ~BIT(msta->deflink_id));
+		msta_link = mt76_dereference(msta->link[msta->deflink_id],
+					     &dev->mt76);
+		if (!msta_link)
+			return;
+	}
+	mld_setup->seconed_id = cpu_to_le16(msta_link->wcid.idx);
+	mld_setup->link_num = nlinks;
+
+	vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
+	mld_setup_link = (struct mld_setup_link *)mld_setup->link_info;
+	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct mt7996_vif_link *link;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		if (!msta_link)
+			continue;
+
+		mld_setup_link->wcid = cpu_to_le16(msta_link->wcid.idx);
+		mld_setup_link->bss_idx = link->mt76.idx;
+		mld_setup_link++;
+	}
+}
+
+static void
+mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+			   struct ieee80211_sta *sta)
+{
+	struct sta_rec_eht_mld *eht_mld;
+	struct tlv *tlv;
+	int i;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
+	eht_mld = (struct sta_rec_eht_mld *)tlv;
+
+	for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++)
+		eht_mld->str_cap[i] = 0x7;
+}
+
 int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct ieee80211_bss_conf *link_conf,
 		       struct ieee80211_link_sta *link_sta,
@@ -2255,6 +2329,11 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		mt7996_mcu_sta_eht_tlv(skb, link_sta);
 		/* starec muru */
 		mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta);
+
+		if (sta->mlo && conn_state != CONN_STATE_DISCONNECT) {
+			mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
+			mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
+		}
 	}
 
 	ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index 5fdc47dad28c66a46c12a1fcede9ef10c7e6d44e..2ab6a53bee869a69d2ee7c0f342e379450c3d6dc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -625,6 +625,35 @@ struct sta_rec_hdr_trans {
 	u8 mesh;
 } __packed;
 
+struct sta_rec_mld_setup {
+	__le16 tag;
+	__le16 len;
+	u8 mld_addr[ETH_ALEN];
+	__le16 primary_id;
+	__le16 seconed_id;
+	__le16 setup_wcid;
+	u8 link_num;
+	u8 info;
+	u8 __rsv[2];
+	u8 link_info[];
+} __packed;
+
+struct sta_rec_eht_mld {
+	__le16 tag;
+	__le16 len;
+	u8 nsep;
+	u8 __rsv1[2];
+	u8 str_cap[__MT_MAX_BAND];
+	__le16 eml_cap;
+	u8 __rsv2[4];
+} __packed;
+
+struct mld_setup_link {
+	__le16 wcid;
+	u8 bss_idx;
+	u8 __rsv;
+} __packed;
+
 struct hdr_trans_en {
 	__le16 tag;
 	__le16 len;
@@ -798,6 +827,9 @@ enum {
 					 sizeof(struct sta_rec_eht) +		\
 					 sizeof(struct sta_rec_hdrt) +		\
 					 sizeof(struct sta_rec_hdr_trans) +	\
+					 sizeof(struct sta_rec_mld_setup) +	\
+					 sizeof(struct mld_setup_link) * 3 +	\
+					 sizeof(struct sta_rec_eht_mld) +	\
 					 sizeof(struct tlv))
 
 #define MT7996_MAX_BEACON_SIZE		1338

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:47 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:47 +0100
Subject: [PATCH 03/21] wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta
 rouine
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-3-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

mt7996_mcu_teardown_mld_sta is used to remove MLO configuration from the
MCU. This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 12 +++++++++---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 18 ++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 +++
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 25dbf086c8ef02307ef2510b21853b1eee28f922..642d633b5126ce81f3d32a9bd912603e2c328c8a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1017,6 +1017,7 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		     struct ieee80211_sta *sta, enum mt76_sta_event ev)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	unsigned long links = sta->valid_links;
 	struct ieee80211_link_sta *link_sta;
 	unsigned int link_id;
 
@@ -1067,11 +1068,16 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				mt7996_mac_twt_teardown_flow(dev, link,
 							     msta_link, i);
 
-			mt7996_mcu_add_sta(dev, link_conf, link_sta, link,
-					   msta_link, CONN_STATE_DISCONNECT,
-					   false);
+			if (sta->mlo && links == BIT(link_id)) /* last link */
+				mt7996_mcu_teardown_mld_sta(dev, link,
+							    msta_link);
+			else
+				mt7996_mcu_add_sta(dev, link_conf, link_sta,
+						   link, msta_link,
+						   CONN_STATE_DISCONNECT, false);
 			msta_link->wcid.sta_disabled = 1;
 			msta_link->wcid.sta = 0;
+			links = links & ~BIT(link_id);
 			break;
 		}
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index ac01eb880e2a6f6ef3a81591bcacd2b90c48986a..46c5e639b9630199ffa601e545fa76690f0101e3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2346,6 +2346,24 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 }
 
+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
+				struct mt7996_vif_link *link,
+				struct mt7996_sta_link *msta_link)
+{
+	struct sk_buff *skb;
+
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
+					      &msta_link->wcid,
+					      MT7996_STA_UPDATE_MAX_SIZE);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, sizeof(struct tlv));
+
+	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+}
+
 static int
 mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
 		       struct sk_buff *skb,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index a91a50b72218c6a2d0dd32968681325ea7e6a042..c2a2916e0647cfdcbee9912e3915241465e32cac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -578,6 +578,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct mt7996_vif_link *link,
 		       struct mt7996_sta_link *msta_link,
 		       int conn_state, bool newly);
+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
+				struct mt7996_vif_link *link,
+				struct mt7996_sta_link *msta_link);
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
 			 bool add);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:48 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:48 +0100
Subject: [PATCH 04/21] wifi: mt76: mt7996: rework mt7996_mac_write_txwi()
 for MLO support
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-4-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Update mt7996_mac_write_txwi routine and all the called subroutines to
support MLO.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 55 ++++++++++++++++++-------
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 48ba975f069c5062f450326a359ff3442ac96f30..eed692cd64a6acedb2f6d9aaf6f459bf4a4f5b08 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -730,9 +730,8 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
 	u32 val;
 
 	if (wcid->sta) {
-		struct ieee80211_sta *sta;
+		struct ieee80211_sta *sta = wcid_to_sta(wcid);
 
-		sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
 		wmm = sta->wme;
 	}
 
@@ -759,7 +758,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
 
 static void
 mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
-			    struct sk_buff *skb, struct ieee80211_key_conf *key)
+			    struct sk_buff *skb,
+			    struct ieee80211_key_conf *key,
+			    struct mt76_wcid *wcid)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -767,6 +768,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 	bool multicast = is_multicast_ether_addr(hdr->addr1);
 	u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
 	__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
+	u16 seqno = le16_to_cpu(sc);
 	u8 fc_type, fc_stype;
 	u32 val;
 
@@ -816,9 +818,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 		txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_INJECTED) {
-		u16 seqno = le16_to_cpu(sc);
+	if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
+		val = MT_TXD3_SN_VALID |
+		      FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
+		txwi[3] |= cpu_to_le32(val);
+	}
 
+	if (info->flags & IEEE80211_TX_CTL_INJECTED) {
 		if (ieee80211_is_back_req(hdr->frame_control)) {
 			struct ieee80211_bar *bar;
 
@@ -831,6 +837,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 		txwi[3] |= cpu_to_le32(val);
 		txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
 	}
+
+	if (ieee80211_vif_is_mld(info->control.vif) &&
+	    (multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
+		txwi[5] |= cpu_to_le32(MT_TXD5_FL);
+
+	if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
+	    ieee80211_vif_is_mld(info->control.vif)) {
+		txwi[5] |= cpu_to_le32(MT_TXD5_FL);
+		txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
+	}
+
+	if (!wcid->sta && ieee80211_is_mgmt(fc))
+		txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
 }
 
 void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
@@ -846,6 +865,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
 	struct mt76_vif_link *mlink = NULL;
 	struct mt7996_vif *mvif;
+	unsigned int link_id;
 	u16 tx_count = 15;
 	u32 val;
 	bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
@@ -853,13 +873,15 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	bool beacon = !!(changed & (BSS_CHANGED_BEACON |
 				    BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
 
-	if (vif) {
-		mvif = (struct mt7996_vif *)vif->drv_priv;
-		if (wcid->offchannel)
-			mlink = rcu_dereference(mvif->mt76.offchannel_link);
-		if (!mlink)
-			mlink = &mvif->deflink.mt76;
-	}
+	if (wcid != &dev->mt76.global_wcid)
+		link_id = wcid->link_id;
+	else
+		link_id = u32_get_bits(info->control.flags,
+				       IEEE80211_TX_CTRL_MLO_LINK);
+
+	mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
+	if (mvif)
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
 
 	if (mlink) {
 		omac_idx = mlink->omac_idx;
@@ -911,7 +933,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 		val |= MT_TXD5_TX_STATUS_HOST;
 	txwi[5] = cpu_to_le32(val);
 
-	val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
+	val = MT_TXD6_DAS;
+	if (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
+		val |= MT_TXD6_DIS_MAT;
+
 	if (is_mt7996(&dev->mt76))
 		val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
 	else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control))
@@ -923,7 +948,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	if (is_8023)
 		mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
 	else
-		mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
+		mt7996_mac_write_txwi_80211(dev, txwi, skb, key, wcid);
 
 	if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
 		bool mcast = ieee80211_is_data(hdr->frame_control) &&
@@ -940,6 +965,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 		}
 
 		val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
+		if (mcast)
+			val |= MT_TXD6_DIS_MAT;
 		txwi[6] |= cpu_to_le32(val);
 		txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
 	}

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:49 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:49 +0100
Subject: [PATCH 05/21] wifi: mt76: mt7996: Rely on wcid_to_sta in
 mt7996_mac_add_txs_skb()
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-5-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index eed692cd64a6acedb2f6d9aaf6f459bf4a4f5b08..9f8436edc81377d852dd4e7221575c7e1255187c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1287,7 +1287,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
 		struct ieee80211_sta *sta;
 		u8 tid;
 
-		sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
+		sta = wcid_to_sta(wcid);
 		tid = FIELD_GET(MT_TXS0_TID, txs);
 		ieee80211_refresh_tx_agg_session_timer(sta, tid);
 	}

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:50 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:50 +0100
Subject: [PATCH 06/21] wifi: mt76: mt7996: rework mt7996_rx_get_wcid to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-6-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

The wcid idx and band idx in the TXS are sometimes mismatched since the
FW will select a transmission link according to a private algorithm.
That is, the wcid idx in the TXS would be the one registered by the
driver rather than the actual wcid idx used during transmission.
However, the band idx in the TXS is the band select for transmission.
Therefore, we should get the driver-registered wcid in order
to notify the driver the packet has been acked; otherwise,
the driver will be unable to match the transmitted packet and its TXS.
This is a preliminary patch to enable MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 33 +++++++++++++++++++------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 9f8436edc81377d852dd4e7221575c7e1255187c..b8d88fdee97a3567b57a20d0322859b7ae8ce88a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -53,29 +53,48 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = {
 };
 
 static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
-					    u16 idx, bool unicast)
+					    u16 idx, u8 band_idx)
 {
 	struct mt7996_sta_link *msta_link;
 	struct mt7996_sta *msta;
+	struct mt7996_vif *mvif;
 	struct mt76_wcid *wcid;
+	int i;
 
 	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
 		return NULL;
 
 	wcid = rcu_dereference(dev->mt76.wcid[idx]);
-	if (unicast || !wcid)
-		return wcid;
+	if (!wcid)
+		return NULL;
 
-	if (!wcid->sta)
+	if (!mt7996_band_valid(dev, band_idx))
 		return NULL;
 
+	if (wcid->phy_idx == band_idx)
+		return wcid;
+
 	msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
 	msta = msta_link->sta;
-
 	if (!msta || !msta->vif)
 		return NULL;
 
-	return &msta->vif->deflink.msta_link.wcid;
+	mvif = msta->vif;
+	for (i = 0; i < ARRAY_SIZE(mvif->mt76.link); i++) {
+		struct mt76_vif_link *mlink;
+
+		mlink = rcu_dereference(mvif->mt76.link[i]);
+		if (!mlink)
+			continue;
+
+		if (mlink->band_idx != band_idx)
+			continue;
+
+		msta_link = rcu_dereference(msta->link[i]);
+		break;
+	}
+
+	return &msta_link->wcid;
 }
 
 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
@@ -483,7 +502,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
 
 	unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
 	idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
-	status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
+	status->wcid = mt7996_rx_get_wcid(dev, idx, band_idx);
 
 	if (status->wcid) {
 		struct mt7996_sta_link *msta_link;

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:51 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:51 +0100
Subject: [PATCH 07/21] wifi: mt76: mt7996: rework mt7996_sta_set_4addr and
 mt7996_sta_set_decap_offload to support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-7-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload routines in
order to properly support multi-link. This is a preliminary patch to enable
MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 74 ++++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 11 +---
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 +-
 3 files changed, 61 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 642d633b5126ce81f3d32a9bd912603e2c328c8a..f7703e00712cd1a59484ceddfad5bd00b8814250 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1540,19 +1540,37 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
 				 struct ieee80211_sta *sta,
 				 bool enabled)
 {
-	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
-	if (enabled)
-		set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
-	else
-		clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+	mutex_lock(&dev->mt76.mutex);
 
-	if (!msta_link->wcid.sta)
-		return;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
 
-	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		if (enabled)
+			set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+		else
+			clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+
+		if (!msta_link->wcid.sta)
+			continue;
+
+		mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);
+	}
+
+	mutex_unlock(&dev->mt76.mutex);
 }
 
 static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
@@ -1560,19 +1578,39 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
 					 struct ieee80211_sta *sta,
 					 bool enabled)
 {
-	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
-	if (enabled)
-		set_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
-	else
-		clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
+	mutex_lock(&dev->mt76.mutex);
 
-	if (!msta_link->wcid.sta)
-		return;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
 
-	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		if (enabled)
+			set_bit(MT_WCID_FLAG_HDR_TRANS,
+				&msta_link->wcid.flags);
+		else
+			clear_bit(MT_WCID_FLAG_HDR_TRANS,
+				  &msta_link->wcid.flags);
+
+		if (!msta_link->wcid.sta)
+			continue;
+
+		mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);
+	}
+
+	mutex_unlock(&dev->mt76.mutex);
 }
 
 static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 46c5e639b9630199ffa601e545fa76690f0101e3..7c097aaead328bd234d87e535497c2f788ffa4c3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -4465,17 +4465,12 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
 
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,
-				     struct ieee80211_sta *sta)
+				     struct mt7996_vif_link *link,
+				     struct mt7996_sta_link *msta_link)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link;
-	struct mt7996_sta *msta;
 	struct sk_buff *skb;
 
-	msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
-	msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link;
-
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index c2a2916e0647cfdcbee9912e3915241465e32cac..f226090bcd02ea478113e4bccea0492cfa34477d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -749,7 +749,8 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 			       struct ieee80211_key_conf *key);
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,
-				     struct ieee80211_sta *sta);
+				     struct mt7996_vif_link *link,
+				     struct mt7996_sta_link *msta_link);
 int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
 #ifdef CONFIG_MAC80211_DEBUGFS
 void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:52 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:52 +0100
Subject: [PATCH 08/21] wifi: mt76: mt7996: Add mt7996_sta_link to
 mt7996_mcu_add_bss_info signature
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-8-015b3d6fd928@kernel.org>

This is a preliminary patch to introduce MLO support for MT996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 13 ++++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |  5 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index f7703e00712cd1a59484ceddfad5bd00b8814250..4abbe761b732f1ea7791ba1f86c2c87db1eea91d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -195,7 +195,8 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 	if (cmd == SET_KEY && !sta && !mlink->mt76.cipher) {
 		mlink->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
-		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76, true);
+		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76,
+					&mlink->msta_link, true);
 	}
 
 	if (cmd == SET_KEY) {
@@ -288,7 +289,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	mt7996_init_bitrate_mask(vif, link);
 
-	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, true);
+	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, true);
 	/* defer the first STA_REC of BMC entry to BSS_CHANGED_BSSID for STA
 	 * interface, since firmware only records BSSID when the entry is new
 	 */
@@ -314,7 +315,7 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
 			   CONN_STATE_DISCONNECT, false);
-	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, false);
+	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
 
 	mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
 
@@ -704,7 +705,8 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				continue;
 
 			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
-						&link->mt76, true);
+						&link->mt76, &link->msta_link,
+						true);
 			mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
 					   CONN_STATE_PORT_SECURE,
 					   !!(changed & BSS_CHANGED_BSSID));
@@ -740,7 +742,8 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	 */
 	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
 	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
-		mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76, true);
+		mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76,
+					&link->msta_link, true);
 		mt7996_mcu_add_sta(dev, info, NULL, link, NULL,
 				   CONN_STATE_PORT_SECURE,
 				   !!(changed & BSS_CHANGED_BSSID));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 7c097aaead328bd234d87e535497c2f788ffa4c3..d1a0dd4698fbe5cf248796ed6f13b99f3c191af1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1064,7 +1064,8 @@ __mt7996_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int
 
 int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_bss_conf *link_conf,
-			    struct mt76_vif_link *mlink, int enable)
+			    struct mt76_vif_link *mlink,
+			    struct mt7996_sta_link *msta_link, int enable)
 {
 	struct mt7996_dev *dev = phy->dev;
 	struct sk_buff *skb;
@@ -1081,7 +1082,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 
 	/* bss_basic must be first */
 	mt7996_mcu_bss_basic_tlv(skb, vif, link_conf, mlink, phy->mt76,
-				 mlink->wcid->idx, enable);
+				 msta_link->wcid.idx, enable);
 	mt7996_mcu_bss_sec_tlv(skb, mlink);
 
 	if (vif->type == NL80211_IFTYPE_MONITOR)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index f226090bcd02ea478113e4bccea0492cfa34477d..4d5ab3f4b78ee6fc584370372fe34b44292e4594 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -571,7 +571,8 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct mt76_vif_link *mlink, bool enable);
 int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_bss_conf *link_conf,
-			    struct mt76_vif_link *mlink, int enable);
+			    struct mt76_vif_link *mlink,
+			    struct mt7996_sta_link *msta_link, int enable);
 int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct ieee80211_bss_conf *link_conf,
 		       struct ieee80211_link_sta *link_sta,

-- 
2.48.1



From andyshrk at 163.com  Wed Mar 12 03:42:01 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:01 +0800
Subject: [PATCH v2 0/7] Add support for RK3588 DisplayPort Controller
Message-ID: <20250312104214.525242-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>


There are two DW DPTX based DisplayPort Controller on rk3588 which
are compliant with the DisplayPort Specification Version 1.4 with
the following features:

* DisplayPort 1.4a
* Main Link: 1/2/4 lanes
* Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
* AUX channel 1Mbps
* Single Stream Transport(SST)
* Multistream Transport (MST)
* Type-C support (alternate mode)
* HDCP 2.2, HDCP 1.3
* Supports up to 8/10 bits per color component
* Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
* Pixel clock up to 594MHz
* I2S, SPDIF audio interface

The current version of this patch series only supports basic display outputs.
I conducted tests with DP0 in 1080p and 4K at 60 YCbCr4:2:0 modes; the ALT/Type-C
mode was tested on Rock 5B, DP1 was tested on Rock 5 ITX by Stephen and Piotr.
HDCP and audio features remain unimplemented.
For RK3588, it's only support SST, while in the upcoming RK3576, it can support
MST output.

This version still has unresolved issues highlighted by Dmitry during
the last code review(I add TODO for them), specifically those depending
on PHY/drm bridge framework changes. My plan is to tackle them sequentially.
Let's make the driver itself to a usable and good shape first.

Currently, there are three dependencies PATCH pending review, take care
if there are someone want to here a try with this series[0][1][2]:

[0]https://lore.kernel.org/linux-rockchip/20250302115257.188774-1-andyshrk at 163.com/
[1]https://lore.kernel.org/linux-rockchip/20250312064218.524143-1-andyshrk at 163.com/T/#u
[2]https://lore.kernel.org/linux-rockchip/20250312080041.524546-1-andyshrk at 163.com/T/#u


Changes in v2:
- Link to V1: https://lore.kernel.org/linux-rockchip/20250223113036.74252-1-andyshrk at 163.com/
- Fix a character encoding issue
- Fix compile error when build as module
- Add phy init
- Only use one dw_dp_link_train_set
- inline dw_dp_phy_update_vs_emph
- Use dp_sdp
- Check return value of drm_modeset_lock
- Merge code in atomic_pre_enable/mode_fixup to atomic_check
- Return NULL if can't find a supported output format
- Fix max_link_rate from plat_data
- no include uapi path
- switch to drmm_encoder_init
- Sort in alphabetical order

Andy Yan (7):
  dt-bindings: display: rockchip: Add schema for RK3588 DPTX Controller
  drm/bridge: synopsys: Add DW DPTX Controller support library
  drm/rockchip: Add RK3588 DPTX output support
  arm64: dts: rockchip: Add DP0 for rk3588
  arm64: dts: rockchip: Add DP1 for rk3588
  arm64: dts: rockchip: Enable DisplayPort for rk3588s Cool Pi 4B
  arm64: dts: rockchip: Enable DP2HDMI for ROCK 5 ITX

 .../display/rockchip/rockchip,dw-dp.yaml      |  150 ++
 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi |   30 +
 .../arm64/boot/dts/rockchip/rk3588-extra.dtsi |   30 +
 .../boot/dts/rockchip/rk3588-rock-5-itx.dts   |   37 +
 .../boot/dts/rockchip/rk3588s-coolpi-4b.dts   |   37 +
 drivers/gpu/drm/bridge/synopsys/Kconfig       |    7 +
 drivers/gpu/drm/bridge/synopsys/Makefile      |    1 +
 drivers/gpu/drm/bridge/synopsys/dw-dp.c       | 2106 +++++++++++++++++
 drivers/gpu/drm/rockchip/Kconfig              |    7 +
 drivers/gpu/drm/rockchip/Makefile             |    1 +
 drivers/gpu/drm/rockchip/dw_dp-rockchip.c     |  154 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |    1 +
 include/drm/bridge/dw_dp.h                    |   19 +
 14 files changed, 2581 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
 create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
 create mode 100644 drivers/gpu/drm/rockchip/dw_dp-rockchip.c
 create mode 100644 include/drm/bridge/dw_dp.h

-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:06 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:06 +0800
Subject: [PATCH v2 5/7] arm64: dts: rockchip: Add DP1 for rk3588
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-6-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The DP1 is compliant with the DisplayPort Specification
Version 1.4, and share the USBDP combo PHY1 with USB 3.1
HOST1 controller.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

(no changes since v1)

 .../arm64/boot/dts/rockchip/rk3588-extra.dtsi | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
index 83113a109810..c498bf2da4fe 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
@@ -140,6 +140,36 @@ i2s10_8ch: i2s at fde00000 {
 		status = "disabled";
 	};
 
+	dp1: dp at fde60000 {
+		compatible = "rockchip,rk3588-dp";
+		reg = <0x0 0xfde60000 0x0 0x4000>;
+		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru PCLK_DP1>, <&cru CLK_AUX16M_1>,
+			 <&cru CLK_DP1>, <&cru MCLK_I2S8_8CH_TX>,
+			 <&cru MCLK_SPDIF5_DP1>;
+		clock-names = "apb", "aux", "hdcp", "i2s", "spdif";
+		assigned-clocks = <&cru CLK_AUX16M_1>;
+		assigned-clock-rates = <16000000>;
+		resets = <&cru SRST_DP1>;
+		phys = <&usbdp_phy1 PHY_TYPE_DP>;
+		power-domains = <&power RK3588_PD_VO0>;
+		#sound-dai-cells = <0>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			dp1_in: port at 0 {
+				reg = <0>;
+			};
+
+			dp1_out: port at 1 {
+				reg = <1>;
+			};
+		};
+	};
+
 	hdmi1: hdmi at fdea0000 {
 		compatible = "rockchip,rk3588-dw-hdmi-qp";
 		reg = <0x0 0xfdea0000 0x0 0x20000>;
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:05 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:05 +0800
Subject: [PATCH v2 4/7] arm64: dts: rockchip: Add DP0 for rk3588
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-5-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The DP0 is compliant with the DisplayPort Specification
Version 1.4, and share the USBDP combo PHY0 with USB 3.1
HOST0 controller.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

(no changes since v1)

 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index 000b119d50f4..675aebe4e8ff 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1371,6 +1371,36 @@ i2s9_8ch: i2s at fddfc000 {
 		status = "disabled";
 	};
 
+	dp0: dp at fde50000 {
+		compatible = "rockchip,rk3588-dp";
+		reg = <0x0 0xfde50000 0x0 0x4000>;
+		interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru PCLK_DP0>, <&cru CLK_AUX16M_0>,
+			 <&cru CLK_DP0>, <&cru MCLK_I2S4_8CH_TX>,
+			 <&cru MCLK_SPDIF2_DP0>;
+		clock-names = "apb", "aux", "hdcp", "i2s", "spdif";
+		assigned-clocks = <&cru CLK_AUX16M_0>;
+		assigned-clock-rates = <16000000>;
+		resets = <&cru SRST_DP0>;
+		phys = <&usbdp_phy0 PHY_TYPE_DP>;
+		power-domains = <&power RK3588_PD_VO0>;
+		#sound-dai-cells = <0>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			dp0_in: port at 0 {
+				reg = <0>;
+			};
+
+			dp0_out: port at 1 {
+				reg = <1>;
+			};
+		};
+	};
+
 	hdmi0: hdmi at fde80000 {
 		compatible = "rockchip,rk3588-dw-hdmi-qp";
 		reg = <0x0 0xfde80000 0x0 0x20000>;
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:02 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:02 +0800
Subject: [PATCH v2 1/7] dt-bindings: display: rockchip: Add schema for RK3588 DPTX Controller
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-2-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The Rockchip RK3588 SoC integrates the Synopsys DesignWare DPTX
controller. And this DPTX controller need share a USBDP PHY with
the USB 3.0 OTG controller during operation.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>

---

Changes in v2:
- Link to V1: https://lore.kernel.org/linux-rockchip/20250223113036.74252-1-andyshrk at 163.com/
- Fix a character encoding issue

 .../display/rockchip/rockchip,dw-dp.yaml      | 150 ++++++++++++++++++
 1 file changed, 150 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
new file mode 100644
index 000000000000..a8a008717997
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
@@ -0,0 +1,150 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/rockchip/rockchip,dw-dp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip DW DisplayPort Transmitter
+
+maintainers:
+  - Andy Yan <andy.yan at rock-chips.com>
+
+description: |
+  The Rockchip RK3588 SoC integrates the Synopsys DesignWare DPTX controller
+  which is compliant with the DisplayPort Specification Version 1.4 with the
+  following features:
+
+  * DisplayPort 1.4a
+  * Main Link: 1/2/4 lanes
+  * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
+  * AUX channel 1Mbps
+  * Single Stream Transport(SST)
+  * Multistream Transport (MST)
+  * Type-C support (alternate mode)
+  * HDCP 2.2, HDCP 1.3
+  * Supports up to 8/10 bits per color component
+  * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
+  * Pixel clock up to 594MHz
+  * I2S, SPDIF audio interface
+
+allOf:
+  - $ref: /schemas/sound/dai-common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3588-dp
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Peripheral/APB bus clock
+      - description: DisplayPort AUX clock
+      - description: HDCP clock
+      - description: I2S interface clock
+      - description: SPDIF interfce clock
+
+  clock-names:
+    items:
+      - const: apb
+      - const: aux
+      - const: hdcp
+      - const: i2s
+      - const: spdif
+
+  phys:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port at 0:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Video port for RGB/YUV input.
+
+      port at 1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Video port for DP output.
+
+    required:
+      - port at 0
+      - port at 1
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  "#sound-dai-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - phys
+  - ports
+  - resets
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+    #include <dt-bindings/phy/phy.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/rk3588-power.h>
+    #include <dt-bindings/reset/rockchip,rk3588-cru.h>
+
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      dp at fde50000 {
+        compatible = "rockchip,rk3588-dp";
+        reg = <0x0 0xfde50000 0x0 0x4000>;
+        interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH 0>;
+        clocks = <&cru PCLK_DP0>, <&cru CLK_AUX16M_0>,
+        <&cru CLK_DP0>, <&cru MCLK_I2S4_8CH_TX>,
+        <&cru MCLK_SPDIF2_DP0>;
+        clock-names = "apb", "aux", "hdcp", "i2s", "spdif";
+        assigned-clocks = <&cru CLK_AUX16M_0>;
+        assigned-clock-rates = <16000000>;
+        resets = <&cru SRST_DP0>;
+        phys = <&usbdp_phy0 PHY_TYPE_DP>;
+        power-domains = <&power RK3588_PD_VO0>;
+        #sound-dai-cells = <0>;
+
+
+        ports {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          port at 0 {
+            reg = <0>;
+
+            dp0_in_vp2: endpoint {
+              remote-endpoint = <&vp2_out_dp0>;
+            };
+          };
+
+          port at 1 {
+            reg = <1>;
+
+            dp0_out_con0: endpoint {
+              remote-endpoint = <&dp_con0_in>;
+            };
+          };
+        };
+      };
+    };
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:08 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:08 +0800
Subject: [PATCH v2 7/7] arm64: dts: rockchip: Enable DP2HDMI for ROCK 5 ITX
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-8-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The HDMI Port next to Headphone Jack is drived by
DP1 on rk3588 via a dp2hdmi converter.

Add related dt nodes to enable it.

Note: ROCKCHIP_VOP2_EP_DP1 is defined as 11 in dt-binding header,
but it will trigger a dtc warning like "graph node unit address
error, expected "b"" if we use it directly after endpoint, so we
use "b" instead here.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

(no changes since v1)

 .../boot/dts/rockchip/rk3588-rock-5-itx.dts   | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
index 67b886329248..29f10ec9f0c1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
@@ -57,6 +57,18 @@ analog-sound {
 			  "Headphone", "Headphones";
 	};
 
+	dp-con {
+		compatible = "dp-connector";
+		label = "DP OUT";
+		type = "full-size";
+
+		port {
+			dp_con_in: endpoint {
+				remote-endpoint = <&dp1_out_con>;
+			};
+		};
+	};
+
 	gpio-leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -268,6 +280,24 @@ &cpu_l3 {
 	cpu-supply = <&vdd_cpu_lit_s0>;
 };
 
+&dp1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp1m0_pins>;
+};
+
+&dp1_in {
+	dp1_in_vp2: endpoint {
+		remote-endpoint = <&vp2_out_dp1>;
+	};
+};
+
+&dp1_out {
+	dp1_out_con: endpoint {
+		remote-endpoint = <&dp_con_in>;
+	};
+};
+
 &gpu {
 	mali-supply = <&vdd_gpu_s0>;
 	status = "okay";
@@ -1262,3 +1292,10 @@ vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
 		remote-endpoint = <&hdmi1_in_vp1>;
 	};
 };
+
+&vp2 {
+	vp2_out_dp1: endpoint at b {
+		reg = <ROCKCHIP_VOP2_EP_DP1>;
+		remote-endpoint = <&dp1_in_vp2>;
+	};
+};
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:07 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:07 +0800
Subject: [PATCH v2 6/7] arm64: dts: rockchip: Enable DisplayPort for rk3588s Cool Pi 4B
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-7-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Enable the Mini DisplayPort on this board.
Note that ROCKCHIP_VOP2_EP_DP0 is defined as 10 in dt-binding header,
but it will trigger a dtc warning like "graph node unit address error,
expected "a"" if we use it directly after endpoint, so we use "a"
instead here.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>

---

Changes in v2:
- Sort in alphabetical order

 .../boot/dts/rockchip/rk3588s-coolpi-4b.dts   | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
index e892dd7c91aa..4f471da1d866 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
@@ -39,6 +39,18 @@ chosen {
 		stdout-path = "serial2:1500000n8";
 	};
 
+	dp-con {
+		compatible = "dp-connector";
+		label = "DP OUT";
+		type = "mini";
+
+		port {
+			dp_con_in: endpoint {
+				remote-endpoint = <&dp0_out_con>;
+			};
+		};
+	};
+
 	hdmi-con {
 		compatible = "hdmi-connector";
 		type = "d";
@@ -215,6 +227,24 @@ &cpu_b2 {
 	cpu-supply = <&vdd_cpu_big1_s0>;
 };
 
+&dp0 {
+	status = "okay";
+	pinctrl-0 = <&dp0m0_pins>;
+	pinctrl-names = "default";
+};
+
+&dp0_in {
+	dp0_in_vp2: endpoint {
+		remote-endpoint = <&vp2_out_dp0>;
+	};
+};
+
+&dp0_out {
+	dp0_out_con: endpoint {
+		remote-endpoint = <&dp_con_in>;
+	};
+};
+
 &gpu {
 	mali-supply = <&vdd_gpu_s0>;
 	status = "okay";
@@ -889,3 +919,10 @@ vp0_out_hdmi0: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
 		remote-endpoint = <&hdmi0_in_vp0>;
 	};
 };
+
+&vp2 {
+	vp2_out_dp0: endpoint at a {
+		reg = <ROCKCHIP_VOP2_EP_DP0>;
+		remote-endpoint = <&dp0_in_vp2>;
+	};
+};
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:03 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:03 +0800
Subject: [PATCH v2 2/7] drm/bridge: synopsys: Add DW DPTX Controller support library
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-3-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The DW DP TX Controller is compliant with the DisplayPort Specification
Version 1.4 with the following features:

* DisplayPort 1.4a
* Main Link: 1/2/4 lanes
* Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
* AUX channel 1Mbps
* Single Stream Transport(SST)
* Multistream Transport (MST)
* Type-C support (alternate mode)
* HDCP 2.2, HDCP 1.3
* Supports up to 8/10 bits per color component
* Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
* Pixel clock up to 594MHz
* I2S, SPDIF audio interface

Add library with common helpers to make it can be shared with
other SoC.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>

---

Changes in v2:
- Fix compile error when build as module
- Add phy init
- Only use one dw_dp_link_train_set
- inline dw_dp_phy_update_vs_emph
- Use dp_sdp
- Check return value of drm_modeset_lock
- Merge code in atomic_pre_enable/mode_fixup to atomic_check
- Return NULL if can't find a supported output format
- Fix max_link_rate from plat_data

 drivers/gpu/drm/bridge/synopsys/Kconfig  |    7 +
 drivers/gpu/drm/bridge/synopsys/Makefile |    1 +
 drivers/gpu/drm/bridge/synopsys/dw-dp.c  | 2106 ++++++++++++++++++++++
 include/drm/bridge/dw_dp.h               |   19 +
 4 files changed, 2133 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-dp.c
 create mode 100644 include/drm/bridge/dw_dp.h

diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index f3ab2f985f8c..2c5e532410de 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -1,4 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0-only
+config DRM_DW_DP
+	tristate
+	select DRM_DISPLAY_HELPER
+	select DRM_DISPLAY_DP_HELPER
+	select DRM_KMS_HELPER
+	select REGMAP_MMIO
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_DISPLAY_HDMI_HELPER
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
index 9dc376d220ad..4dada44029ac 100644
--- a/drivers/gpu/drm/bridge/synopsys/Makefile
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_DRM_DW_DP) += dw-dp.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
new file mode 100644
index 000000000000..70ae8f7adc3a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -0,0 +1,2106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Synopsys DesignWare Cores DisplayPort Transmitter Controller
+ *
+ * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
+ *
+ * Author: Andy Yan <andy.yan at rock-chips.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/media-bus-format.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/unaligned.h>
+
+#include <drm/bridge/dw_dp.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/display/drm_dp_helper.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#define DW_DP_VERSION_NUMBER			0x0000
+#define DW_DP_VERSION_TYPE			0x0004
+#define DW_DP_ID					0x0008
+
+#define DW_DP_CONFIG_REG1			0x0100
+#define DW_DP_CONFIG_REG2			0x0104
+#define DW_DP_CONFIG_REG3			0x0108
+
+#define DW_DP_CCTL				0x0200
+#define FORCE_HPD				BIT(4)
+#define DEFAULT_FAST_LINK_TRAIN_EN		BIT(2)
+#define ENHANCE_FRAMING_EN			BIT(1)
+#define SCRAMBLE_DIS				BIT(0)
+#define DW_DP_SOFT_RESET_CTRL			0x0204
+#define VIDEO_RESET				BIT(5)
+#define AUX_RESET				BIT(4)
+#define AUDIO_SAMPLER_RESET			BIT(3)
+#define HDCP_MODULE_RESET			BIT(2)
+#define PHY_SOFT_RESET				BIT(1)
+#define CONTROLLER_RESET			BIT(0)
+
+#define DW_DP_VSAMPLE_CTRL			0x0300
+#define PIXEL_MODE_SELECT			GENMASK(22, 21)
+#define VIDEO_MAPPING				GENMASK(20, 16)
+#define VIDEO_STREAM_ENABLE			BIT(5)
+
+#define DW_DP_VSAMPLE_STUFF_CTRL1		0x0304
+
+#define DW_DP_VSAMPLE_STUFF_CTRL2		0x0308
+
+#define DW_DP_VINPUT_POLARITY_CTRL		0x030c
+#define DE_IN_POLARITY				BIT(2)
+#define HSYNC_IN_POLARITY			BIT(1)
+#define VSYNC_IN_POLARITY			BIT(0)
+
+#define DW_DP_VIDEO_CONFIG1			0x0310
+#define HACTIVE					GENMASK(31, 16)
+#define HBLANK					GENMASK(15, 2)
+#define I_P					BIT(1)
+#define R_V_BLANK_IN_OSC			BIT(0)
+
+#define DW_DP_VIDEO_CONFIG2			0x0314
+#define VBLANK					GENMASK(31, 16)
+#define VACTIVE					GENMASK(15, 0)
+
+#define DW_DP_VIDEO_CONFIG3			0x0318
+#define H_SYNC_WIDTH				GENMASK(31, 16)
+#define H_FRONT_PORCH				GENMASK(15, 0)
+
+#define DW_DP_VIDEO_CONFIG4			0x031c
+#define V_SYNC_WIDTH				GENMASK(31, 16)
+#define V_FRONT_PORCH				GENMASK(15, 0)
+
+#define DW_DP_VIDEO_CONFIG5			0x0320
+#define INIT_THRESHOLD_HI			GENMASK(22, 21)
+#define AVERAGE_BYTES_PER_TU_FRAC		GENMASK(19, 16)
+#define INIT_THRESHOLD				GENMASK(13, 7)
+#define AVERAGE_BYTES_PER_TU			GENMASK(6, 0)
+
+#define DW_DP_VIDEO_MSA1				0x0324
+#define VSTART					GENMASK(31, 16)
+#define HSTART					GENMASK(15, 0)
+
+#define DW_DP_VIDEO_MSA2			0x0328
+#define MISC0					GENMASK(31, 24)
+
+#define DW_DP_VIDEO_MSA3			0x032c
+#define MISC1					GENMASK(31, 24)
+
+#define DW_DP_VIDEO_HBLANK_INTERVAL		0x0330
+#define HBLANK_INTERVAL_EN			BIT(16)
+#define HBLANK_INTERVAL				GENMASK(15, 0)
+
+#define DW_DP_AUD_CONFIG1			0x0400
+#define AUDIO_TIMESTAMP_VERSION_NUM		GENMASK(29, 24)
+#define AUDIO_PACKET_ID				GENMASK(23, 16)
+#define AUDIO_MUTE				BIT(15)
+#define NUM_CHANNELS				GENMASK(14, 12)
+#define HBR_MODE_ENABLE				BIT(10)
+#define AUDIO_DATA_WIDTH			GENMASK(9, 5)
+#define AUDIO_DATA_IN_EN			GENMASK(4, 1)
+#define AUDIO_INF_SELECT			BIT(0)
+
+#define DW_DP_SDP_VERTICAL_CTRL			0x0500
+#define EN_VERTICAL_SDP				BIT(2)
+#define EN_AUDIO_STREAM_SDP			BIT(1)
+#define EN_AUDIO_TIMESTAMP_SDP			BIT(0)
+#define DW_DP_SDP_HORIZONTAL_CTRL		0x0504
+#define EN_HORIZONTAL_SDP			BIT(2)
+#define DW_DP_SDP_STATUS_REGISTER		0x0508
+#define DW_DP_SDP_MANUAL_CTRL			0x050c
+#define DW_DP_SDP_STATUS_EN			0x0510
+
+#define DW_DP_SDP_REGISTER_BANK			0x0600
+#define SDP_REGS				GENMASK(31, 0)
+
+#define DW_DP_PHYIF_CTRL			0x0a00
+#define PHY_WIDTH				BIT(25)
+#define PHY_POWERDOWN				GENMASK(20, 17)
+#define PHY_BUSY				GENMASK(15, 12)
+#define SSC_DIS					BIT(16)
+#define XMIT_ENABLE				GENMASK(11, 8)
+#define PHY_LANES				GENMASK(7, 6)
+#define PHY_RATE				GENMASK(5, 4)
+#define TPS_SEL					GENMASK(3, 0)
+
+#define DW_DP_PHY_TX_EQ				0x0a04
+#define DW_DP_CUSTOMPAT0			0x0a08
+#define DW_DP_CUSTOMPAT1			0x0a0c
+#define DW_DP_CUSTOMPAT2			0x0a10
+#define DW_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET	0x0a14
+#define DW_DP_PHYIF_PWRDOWN_CTRL		0x0a18
+
+#define DW_DP_AUX_CMD				0x0b00
+#define AUX_CMD_TYPE				GENMASK(31, 28)
+#define AUX_ADDR				GENMASK(27, 8)
+#define I2C_ADDR_ONLY				BIT(4)
+#define AUX_LEN_REQ				GENMASK(3, 0)
+
+#define DW_DP_AUX_STATUS			0x0b04
+#define AUX_TIMEOUT				BIT(17)
+#define AUX_BYTES_READ				GENMASK(23, 19)
+#define AUX_STATUS				GENMASK(7, 4)
+
+#define DW_DP_AUX_DATA0				0x0b08
+#define DW_DP_AUX_DATA1				0x0b0c
+#define DW_DP_AUX_DATA2				0x0b10
+#define DW_DP_AUX_DATA3				0x0b14
+
+#define DW_DP_GENERAL_INTERRUPT			0x0d00
+#define VIDEO_FIFO_OVERFLOW_STREAM0		BIT(6)
+#define AUDIO_FIFO_OVERFLOW_STREAM0		BIT(5)
+#define SDP_EVENT_STREAM0			BIT(4)
+#define AUX_CMD_INVALID				BIT(3)
+#define HDCP_EVENT				BIT(2)
+#define AUX_REPLY_EVENT				BIT(1)
+#define HPD_EVENT				BIT(0)
+
+#define DW_DP_GENERAL_INTERRUPT_ENABLE		0x0d04
+#define HDCP_EVENT_EN				BIT(2)
+#define AUX_REPLY_EVENT_EN			BIT(1)
+#define HPD_EVENT_EN				BIT(0)
+
+#define DW_DP_HPD_STATUS			0x0d08
+#define HPD_STATE				GENMASK(11, 9)
+#define HPD_STATUS				BIT(8)
+#define HPD_HOT_UNPLUG				BIT(2)
+#define HPD_HOT_PLUG				BIT(1)
+#define HPD_IRQ					BIT(0)
+
+#define DW_DP_HPD_INTERRUPT_ENABLE		0x0d0c
+#define HPD_UNPLUG_ERR_EN			BIT(3)
+#define HPD_UNPLUG_EN				BIT(2)
+#define HPD_PLUG_EN				BIT(1)
+#define HPD_IRQ_EN				BIT(0)
+
+#define DW_DP_HDCP_CFG				0x0e00
+#define DPCD12PLUS				BIT(7)
+#define CP_IRQ					BIT(6)
+#define BYPENCRYPTION				BIT(5)
+#define HDCP_LOCK				BIT(4)
+#define ENCRYPTIONDISABLE			BIT(3)
+#define ENABLE_HDCP_13				BIT(2)
+#define ENABLE_HDCP				BIT(1)
+
+#define DW_DP_HDCP_OBS				0x0e04
+#define HDCP22_RE_AUTHENTICATION_REQ		BIT(31)
+#define HDCP22_AUTHENTICATION_FAILED		BIT(30)
+#define HDCP22_AUTHENTICATION_SUCCESS		BIT(29)
+#define HDCP22_CAPABLE_SINK			BIT(28)
+#define HDCP22_SINK_CAP_CHECK_COMPLETE		BIT(27)
+#define HDCP22_STATE				GENMASK(26, 24)
+#define HDCP22_BOOTED				BIT(23)
+#define HDCP13_BSTATUS				GENMASK(22, 19)
+#define REPEATER				BIT(18)
+#define HDCP_CAPABLE				BIT(17)
+#define STATEE					GENMASK(16, 14)
+#define STATEOEG				GENMASK(13, 11)
+#define STATER					GENMASK(10, 8)
+#define STATEA					GENMASK(7, 4)
+#define SUBSTATEA				GENMASK(3, 1)
+#define HDCPENGAGED				BIT(0)
+
+#define DW_DP_HDCP_APIINTCLR			0x0e08
+#define DW_DP_HDCP_APIINTSTAT			0x0e0c
+#define DW_DP_HDCP_APIINTMSK			0x0e10
+#define HDCP22_GPIOINT				BIT(8)
+#define HDCP_ENGAGED				BIT(7)
+#define HDCP_FAILED				BIT(6)
+#define KSVSHA1CALCDONEINT			BIT(5)
+#define AUXRESPNACK7TIMES			BIT(4)
+#define AUXRESPTIMEOUT				BIT(3)
+#define AUXRESPDEFER7TIMES			BIT(2)
+#define KSVACCESSINT				BIT(0)
+
+#define DW_DP_HDCP_KSVMEMCTRL			0x0e18
+#define KSVSHA1STATUS				BIT(4)
+#define KSVMEMACCESS				BIT(1)
+#define KSVMEMREQUEST				BIT(0)
+
+#define DW_DP_HDCP_REG_BKSV0			0x3600
+#define DW_DP_HDCP_REG_BKSV1			0x3604
+#define DW_DP_HDCP_REG_ANCONF			0x3608
+#define AN_BYPASS				BIT(0)
+
+#define DW_DP_HDCP_REG_AN0			0x360c
+#define DW_DP_HDCP_REG_AN1			0x3610
+#define DW_DP_HDCP_REG_RMLCTL			0x3614
+#define ODPK_DECRYPT_ENABLE			BIT(0)
+
+#define DW_DP_HDCP_REG_RMLSTS			0x3618
+#define IDPK_WR_OK_STS				BIT(6)
+#define	IDPK_DATA_INDEX				GENMASK(5, 0)
+#define DW_DP_HDCP_REG_SEED			0x361c
+#define DW_DP_HDCP_REG_DPK0			0x3620
+#define DW_DP_HDCP_REG_DPK1			0x3624
+#define DW_DP_HDCP22_GPIOSTS			0x3628
+#define DW_DP_HDCP22_GPIOCHNGSTS		0x362c
+#define DW_DP_HDCP_REG_DPK_CRC			0x3630
+
+#define DW_DP_MAX_REGISTER			DW_DP_HDCP_REG_DPK_CRC
+
+#define SDP_REG_BANK_SIZE			16
+
+struct dw_dp_link_caps {
+	bool enhanced_framing;
+	bool tps3_supported;
+	bool tps4_supported;
+	bool fast_training;
+	bool channel_coding;
+	bool ssc;
+};
+
+struct dw_dp_link_train_set {
+	unsigned int voltage_swing[4];
+	unsigned int pre_emphasis[4];
+	bool voltage_max_reached[4];
+	bool pre_max_reached[4];
+};
+
+struct dw_dp_link_train {
+	struct dw_dp_link_train_set adjust;
+	bool clock_recovered;
+	bool channel_equalized;
+};
+
+struct dw_dp_link {
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
+	unsigned char revision;
+	unsigned int rate;
+	unsigned int lanes;
+	u8 sink_count;
+	u8 vsc_sdp_supported;
+	struct dw_dp_link_caps caps;
+	struct dw_dp_link_train train;
+	struct drm_dp_desc desc;
+};
+
+struct dw_dp_video {
+	struct drm_display_mode mode;
+	u8 video_mapping;
+	u8 pixel_mode;
+	u8 color_format;
+	u8 bpc;
+	u8 bpp;
+};
+
+struct dw_dp_sdp {
+	struct dp_sdp base;
+	unsigned long flags;
+};
+
+struct dw_dp_hotplug {
+	bool long_hpd;
+};
+
+struct dw_dp {
+	struct drm_bridge bridge;
+	struct device *dev;
+	struct regmap *regmap;
+	struct phy *phy;
+	struct clk *apb_clk;
+	struct clk *aux_clk;
+	struct clk *i2s_clk;
+	struct clk *spdif_clk;
+	struct clk *hdcp_clk;
+	struct reset_control *rstc;
+	struct completion complete;
+	int irq;
+	struct work_struct hpd_work;
+	struct dw_dp_hotplug hotplug;
+	struct mutex irq_lock;
+
+	struct drm_dp_aux aux;
+
+	struct dw_dp_link link;
+	struct dw_dp_video video;
+	struct dw_dp_plat_data plat_data;
+
+	DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
+};
+
+enum {
+	DW_DP_RGB_6BIT,
+	DW_DP_RGB_8BIT,
+	DW_DP_RGB_10BIT,
+	DW_DP_RGB_12BIT,
+	DW_DP_RGB_16BIT,
+	DW_DP_YCBCR444_8BIT,
+	DW_DP_YCBCR444_10BIT,
+	DW_DP_YCBCR444_12BIT,
+	DW_DP_YCBCR444_16BIT,
+	DW_DP_YCBCR422_8BIT,
+	DW_DP_YCBCR422_10BIT,
+	DW_DP_YCBCR422_12BIT,
+	DW_DP_YCBCR422_16BIT,
+	DW_DP_YCBCR420_8BIT,
+	DW_DP_YCBCR420_10BIT,
+	DW_DP_YCBCR420_12BIT,
+	DW_DP_YCBCR420_16BIT,
+};
+
+enum {
+	DW_DP_MP_SINGLE_PIXEL,
+	DW_DP_MP_DUAL_PIXEL,
+	DW_DP_MP_QUAD_PIXEL,
+};
+
+enum {
+	DW_DP_SDP_VERTICAL_INTERVAL = BIT(0),
+	DW_DP_SDP_HORIZONTAL_INTERVAL = BIT(1),
+};
+
+enum {
+	DW_DP_HPD_STATE_IDLE,
+	DW_DP_HPD_STATE_UNPLUG,
+	DP_DP_HPD_STATE_TIMEOUT = 4,
+	DW_DP_HPD_STATE_PLUG = 7
+};
+
+enum {
+	DW_DP_PHY_PATTERN_NONE,
+	DW_DP_PHY_PATTERN_TPS_1,
+	DW_DP_PHY_PATTERN_TPS_2,
+	DW_DP_PHY_PATTERN_TPS_3,
+	DW_DP_PHY_PATTERN_TPS_4,
+	DW_DP_PHY_PATTERN_SERM,
+	DW_DP_PHY_PATTERN_PBRS7,
+	DW_DP_PHY_PATTERN_CUSTOM_80BIT,
+	DW_DP_PHY_PATTERN_CP2520_1,
+	DW_DP_PHY_PATTERN_CP2520_2,
+};
+
+struct dw_dp_output_format {
+	u32 bus_format;
+	u32 color_format;
+	u8 video_mapping;
+	u8 bpc;
+	u8 bpp;
+};
+
+static const struct dw_dp_output_format dw_dp_output_formats[] = {
+	{ MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_10BIT, 10, 30 },
+	{ MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_8BIT, 8, 24 },
+	{ MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_10BIT, 10, 30 },
+	{ MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, DW_DP_YCBCR444_8BIT, 8, 24},
+	{ MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_10BIT, 10, 20 },
+	{ MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, DW_DP_YCBCR422_8BIT, 8, 16 },
+	{ MEDIA_BUS_FMT_UYYVYY10_0_5X30, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_10BIT, 10, 15 },
+	{ MEDIA_BUS_FMT_UYYVYY8_0_5X24, DRM_COLOR_FORMAT_YCBCR420, DW_DP_YCBCR420_8BIT, 8, 12 },
+	{ MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, DW_DP_RGB_6BIT, 6, 18 },
+};
+
+static const struct dw_dp_output_format *dw_dp_get_output_format(u32 bus_format)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++)
+		if (dw_dp_output_formats[i].bus_format == bus_format)
+			return &dw_dp_output_formats[i];
+
+	return NULL;
+}
+
+static inline struct dw_dp *bridge_to_dp(struct drm_bridge *b)
+{
+	return container_of(b, struct dw_dp, bridge);
+}
+
+static inline void dw_dp_phy_set_pattern(struct dw_dp *dp, u32 pattern)
+{
+	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, TPS_SEL,
+			   FIELD_PREP(TPS_SEL, pattern));
+}
+
+static void dw_dp_phy_xmit_enable(struct dw_dp *dp, u32 lanes)
+{
+	u32 xmit_enable;
+
+	switch (lanes) {
+	case 4:
+	case 2:
+	case 1:
+		xmit_enable = GENMASK(lanes - 1, 0);
+		break;
+	case 0:
+	default:
+		xmit_enable = 0;
+		break;
+	}
+
+	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, XMIT_ENABLE,
+			   FIELD_PREP(XMIT_ENABLE, xmit_enable));
+}
+
+static bool dw_dp_bandwidth_ok(struct dw_dp *dp,
+			       const struct drm_display_mode *mode, u32 bpp,
+			       unsigned int lanes, unsigned int rate)
+{
+	u32 max_bw, req_bw;
+
+	req_bw = mode->clock * bpp / 8;
+	max_bw = lanes * rate;
+	if (req_bw > max_bw)
+		return false;
+
+	return true;
+}
+
+static bool dw_dp_hpd_detect(struct dw_dp *dp)
+{
+	u32 value;
+
+	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
+
+	return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
+}
+
+static void dw_dp_link_caps_reset(struct dw_dp_link_caps *caps)
+{
+	caps->enhanced_framing = false;
+	caps->tps3_supported = false;
+	caps->tps4_supported = false;
+	caps->fast_training = false;
+	caps->channel_coding = false;
+}
+
+/* TODO: pull these two functions to DRM DP helpers */
+static void dw_dp_link_reset(struct dw_dp_link *link)
+{
+	link->vsc_sdp_supported = 0;
+	link->sink_count = 0;
+	link->revision = 0;
+	link->rate = 0;
+	link->lanes = 0;
+
+	dw_dp_link_caps_reset(&link->caps);
+	memset(link->dpcd, 0, sizeof(link->dpcd));
+}
+
+static int dw_dp_link_power_up(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	int ret;
+	u8 value;
+
+	if (link->revision < DP_DPCD_REV_11)
+		return 0;
+
+	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
+	if (ret < 0)
+		return ret;
+
+	value &= ~DP_SET_POWER_MASK;
+	value |= DP_SET_POWER_D0;
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+
+	return 0;
+}
+
+static int dw_dp_link_power_down(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	int ret;
+	u8 value;
+
+	if (link->revision < DP_DPCD_REV_11)
+		return 0;
+
+	ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value);
+	if (ret < 0)
+		return ret;
+
+	value &= ~DP_SET_POWER_MASK;
+	value |= DP_SET_POWER_D3;
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* TODO: switch to drm_dp_read_sink_count_cap once we can get connector*/
+static bool dw_dp_has_sink_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				 const struct drm_dp_desc *desc)
+{
+	return dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
+	       dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
+	       !drm_dp_has_quirk(desc, DP_DPCD_QUIRK_NO_SINK_COUNT);
+}
+
+static int dw_dp_link_parse(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	u8 dpcd;
+	int ret;
+
+	dw_dp_link_reset(link);
+
+	ret = drm_dp_read_dpcd_caps(&dp->aux, link->dpcd);
+	if (ret < 0)
+		return ret;
+
+	drm_dp_read_desc(&dp->aux, &link->desc, drm_dp_is_branch(link->dpcd));
+
+	if (dw_dp_has_sink_count(link->dpcd, &link->desc)) {
+		ret = drm_dp_read_sink_count(&dp->aux);
+		if (ret < 0)
+			return ret;
+
+		link->sink_count = ret;
+
+		/* Dongle connected, but no display */
+		if (!link->sink_count)
+			return -ENODEV;
+	}
+
+	ret = drm_dp_dpcd_readb(&dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dpcd);
+	if (ret < 0)
+		return ret;
+
+	link->vsc_sdp_supported = !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
+
+	link->revision = link->dpcd[DP_DPCD_REV];
+	link->rate = min_t(u32, min(dp->plat_data.max_link_rate,
+				    dp->phy->attrs.max_link_rate * 100),
+			   drm_dp_max_link_rate(link->dpcd));
+	link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
+			    drm_dp_max_lane_count(link->dpcd));
+
+	link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
+	link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
+	link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
+	link->caps.fast_training = drm_dp_fast_training_cap(link->dpcd);
+	link->caps.channel_coding = drm_dp_channel_coding_supported(link->dpcd);
+	link->caps.ssc = !!(link->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
+
+	return 0;
+}
+
+static int dw_dp_link_train_update_vs_emph(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	struct dw_dp_link_train_set *train_set = &link->train.adjust;
+	unsigned int rate = dp->link.rate;
+	unsigned int lanes = dp->link.lanes;
+	union phy_configure_opts phy_cfg;
+	unsigned int *vs, *pe;
+	int i, ret;
+	u8 buf[4];
+
+	vs = train_set->voltage_swing;
+	pe = train_set->pre_emphasis;
+
+	for (i = 0; i < lanes; i++) {
+		phy_cfg.dp.voltage[i] = vs[i];
+		phy_cfg.dp.pre[i] = pe[i];
+	}
+
+	/* TODO: drop lanes and link_rate when phy side patch merged*/
+	phy_cfg.dp.lanes = lanes;
+	phy_cfg.dp.link_rate = rate / 100;
+	phy_cfg.dp.set_lanes = false;
+	phy_cfg.dp.set_rate = false;
+	phy_cfg.dp.set_voltages = true;
+
+	ret = phy_configure(dp->phy, &phy_cfg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < lanes; i++) {
+		buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
+			 (pe[i] << DP_TRAIN_PRE_EMPHASIS_SHIFT);
+		if (train_set->voltage_max_reached[i])
+			buf[i] |= DP_TRAIN_MAX_SWING_REACHED;
+		if (train_set->pre_max_reached[i])
+			buf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+	}
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, lanes);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
+			       unsigned int lanes, bool ssc)
+{
+	union phy_configure_opts phy_cfg;
+	int ret;
+
+	/* Move PHY to P3 */
+	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
+			   FIELD_PREP(PHY_POWERDOWN, 0x3));
+
+	phy_cfg.dp.lanes = lanes;
+	phy_cfg.dp.link_rate = rate / 100;
+	phy_cfg.dp.ssc = ssc;
+	phy_cfg.dp.set_lanes = true;
+	phy_cfg.dp.set_rate = true;
+	phy_cfg.dp.set_voltages = false;
+	ret = phy_configure(dp->phy, &phy_cfg);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_LANES,
+			   FIELD_PREP(PHY_LANES, lanes / 2));
+
+	/* Move PHY to P0 */
+	regmap_update_bits(dp->regmap, DW_DP_PHYIF_CTRL, PHY_POWERDOWN,
+			   FIELD_PREP(PHY_POWERDOWN, 0x0));
+
+	dw_dp_phy_xmit_enable(dp, lanes);
+
+	return 0;
+}
+
+static int dw_dp_link_configure(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	u8 buf[2];
+	int ret;
+
+	ret = dw_dp_phy_configure(dp, link->rate, link->lanes, link->caps.ssc);
+	if (ret)
+		return ret;
+
+	buf[0] = drm_dp_link_rate_to_bw_code(link->rate);
+	buf[1] = link->lanes;
+
+	if (link->caps.enhanced_framing) {
+		buf[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
+				   FIELD_PREP(ENHANCE_FRAMING_EN, 1));
+	} else {
+		regmap_update_bits(dp->regmap, DW_DP_CCTL, ENHANCE_FRAMING_EN,
+				   FIELD_PREP(ENHANCE_FRAMING_EN, 0));
+	}
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	buf[0] = link->caps.ssc ? DP_SPREAD_AMP_0_5 : 0;
+	buf[1] = link->caps.channel_coding ? DP_SET_ANSI_8B10B : 0;
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void dw_dp_link_train_init(struct dw_dp_link_train *train)
+{
+	struct dw_dp_link_train_set *adj = &train->adjust;
+	unsigned int i;
+
+	for (i = 0; i < 4; i++) {
+		adj->voltage_swing[i] = 0;
+		adj->pre_emphasis[i] = 0;
+		adj->voltage_max_reached[i] = false;
+		adj->pre_max_reached[i] = false;
+	}
+
+	train->clock_recovered = false;
+	train->channel_equalized = false;
+}
+
+static bool dw_dp_link_train_valid(const struct dw_dp_link_train *train)
+{
+	return train->clock_recovered && train->channel_equalized;
+}
+
+static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
+{
+	u8 buf = 0;
+	int ret;
+
+	if (pattern && pattern != DP_TRAINING_PATTERN_4) {
+		buf |= DP_LINK_SCRAMBLING_DISABLE;
+
+		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
+				   FIELD_PREP(SCRAMBLE_DIS, 1));
+	} else {
+		regmap_update_bits(dp->regmap, DW_DP_CCTL, SCRAMBLE_DIS,
+				   FIELD_PREP(SCRAMBLE_DIS, 0));
+	}
+
+	switch (pattern) {
+	case DP_TRAINING_PATTERN_DISABLE:
+		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_NONE);
+		break;
+	case DP_TRAINING_PATTERN_1:
+		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_1);
+		break;
+	case DP_TRAINING_PATTERN_2:
+		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_2);
+		break;
+	case DP_TRAINING_PATTERN_3:
+		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_3);
+		break;
+	case DP_TRAINING_PATTERN_4:
+		dw_dp_phy_set_pattern(dp, DW_DP_PHY_PATTERN_TPS_4);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+				 buf | pattern);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static u8 dw_dp_voltage_max(u8 preemph)
+{
+	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
+	case DP_TRAIN_PRE_EMPH_LEVEL_0:
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+	case DP_TRAIN_PRE_EMPH_LEVEL_1:
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+	case DP_TRAIN_PRE_EMPH_LEVEL_2:
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
+	case DP_TRAIN_PRE_EMPH_LEVEL_3:
+	default:
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
+	}
+}
+
+static bool dw_dp_link_get_adjustments(struct dw_dp_link *link,
+				       u8 status[DP_LINK_STATUS_SIZE])
+{
+	struct dw_dp_link_train_set *adj = &link->train.adjust;
+	unsigned int i;
+	bool changed = false;
+	u8 v = 0;
+	u8 p = 0;
+
+	for (i = 0; i < link->lanes; i++) {
+		v = drm_dp_get_adjust_request_voltage(status, i);
+		v >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
+		p = drm_dp_get_adjust_request_pre_emphasis(status, i);
+		p >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
+
+		if ((v != adj->voltage_swing[i]) || (p != adj->pre_emphasis[i]))
+			changed = true;
+
+		if (p >=  (DP_TRAIN_PRE_EMPH_LEVEL_3 >> DP_TRAIN_PRE_EMPHASIS_SHIFT)) {
+			adj->pre_emphasis[i] = DP_TRAIN_PRE_EMPH_LEVEL_3 >>
+					       DP_TRAIN_PRE_EMPHASIS_SHIFT;
+			adj->pre_max_reached[i] = true;
+		} else {
+			adj->pre_emphasis[i] = p;
+			adj->pre_max_reached[i] = false;
+		}
+
+		v = min(v, dw_dp_voltage_max(p));
+		if (v >= (DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >> DP_TRAIN_VOLTAGE_SWING_SHIFT)) {
+			adj->voltage_swing[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 >>
+						DP_TRAIN_VOLTAGE_SWING_SHIFT;
+			adj->voltage_max_reached[i] = true;
+		} else {
+			adj->voltage_swing[i] = v;
+			adj->voltage_max_reached[i] = false;
+		}
+	}
+
+	return changed;
+}
+
+static int dw_dp_link_clock_recovery(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	u8 status[DP_LINK_STATUS_SIZE];
+	unsigned int tries = 0;
+	int ret;
+	bool adj_changed;
+
+	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
+	if (ret)
+		return ret;
+
+	for (;;) {
+		ret = dw_dp_link_train_update_vs_emph(dp);
+		if (ret)
+			return ret;
+
+		drm_dp_link_train_clock_recovery_delay(&dp->aux, link->dpcd);
+
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
+		if (ret < 0) {
+			dev_err(dp->dev, "failed to read link status: %d\n", ret);
+			return ret;
+		}
+
+		if (drm_dp_clock_recovery_ok(status, link->lanes)) {
+			link->train.clock_recovered = true;
+			break;
+		}
+
+		/*
+		 * According to DP spec 1.4, if current ADJ is the same
+		 * with previous REQ, we need to retry 5 times.
+		 */
+		adj_changed = dw_dp_link_get_adjustments(link, status);
+		if (!adj_changed)
+			tries++;
+		else
+			tries = 0;
+
+		if (tries == 5)
+			break;
+	}
+
+	return 0;
+}
+
+static int dw_dp_link_channel_equalization(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	u8 status[DP_LINK_STATUS_SIZE], pattern;
+	unsigned int tries;
+	int ret;
+
+	if (link->caps.tps4_supported)
+		pattern = DP_TRAINING_PATTERN_4;
+	else if (link->caps.tps3_supported)
+		pattern = DP_TRAINING_PATTERN_3;
+	else
+		pattern = DP_TRAINING_PATTERN_2;
+	ret = dw_dp_link_train_set_pattern(dp, pattern);
+	if (ret)
+		return ret;
+
+	for (tries = 1; tries < 5; tries++) {
+		ret = dw_dp_link_train_update_vs_emph(dp);
+		if (ret)
+			return ret;
+
+		drm_dp_link_train_channel_eq_delay(&dp->aux, link->dpcd);
+
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
+		if (ret < 0)
+			return ret;
+
+		if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
+			dev_err(dp->dev, "clock recovery lost while equalizing channel\n");
+			link->train.clock_recovered = false;
+			break;
+		}
+
+		if (drm_dp_channel_eq_ok(status, link->lanes)) {
+			link->train.channel_equalized = true;
+			break;
+		}
+
+		dw_dp_link_get_adjustments(link, status);
+	}
+
+	return 0;
+}
+
+static int dw_dp_link_downgrade(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	struct dw_dp_video *video = &dp->video;
+
+	switch (link->rate) {
+	case 162000:
+		return -EINVAL;
+	case 270000:
+		link->rate = 162000;
+		break;
+	case 540000:
+		link->rate = 270000;
+		break;
+	case 810000:
+		link->rate = 540000;
+		break;
+	}
+
+	if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
+				link->rate))
+		return -E2BIG;
+
+	return 0;
+}
+
+static int dw_dp_link_train_full(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	int ret;
+
+retry:
+	dw_dp_link_train_init(&link->train);
+
+	dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
+		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
+
+	ret = dw_dp_link_configure(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
+		return ret;
+	}
+
+	ret = dw_dp_link_clock_recovery(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "clock recovery failed: %d\n", ret);
+		goto out;
+	}
+
+	if (!link->train.clock_recovered) {
+		dev_err(dp->dev, "clock recovery failed, downgrading link\n");
+
+		ret = dw_dp_link_downgrade(dp);
+		if (ret < 0)
+			goto out;
+		else
+			goto retry;
+	}
+
+	dev_dbg(dp->dev, "clock recovery succeeded\n");
+
+	ret = dw_dp_link_channel_equalization(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "channel equalization failed: %d\n", ret);
+		goto out;
+	}
+
+	if (!link->train.channel_equalized) {
+		dev_err(dp->dev, "channel equalization failed, downgrading link\n");
+
+		ret = dw_dp_link_downgrade(dp);
+		if (ret < 0)
+			goto out;
+		else
+			goto retry;
+	}
+
+	dev_dbg(dp->dev, "channel equalization succeeded\n");
+
+out:
+	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
+	return ret;
+}
+
+static int dw_dp_link_train_fast(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	int ret;
+	u8 status[DP_LINK_STATUS_SIZE];
+	u8 pattern;
+
+	dw_dp_link_train_init(&link->train);
+
+	dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
+		link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
+
+	ret = dw_dp_link_configure(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
+		return ret;
+	}
+
+	ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1);
+	if (ret)
+		goto out;
+
+	usleep_range(500, 1000);
+
+	if (link->caps.tps4_supported)
+		pattern = DP_TRAINING_PATTERN_4;
+	else if (link->caps.tps3_supported)
+		pattern = DP_TRAINING_PATTERN_3;
+	else
+		pattern = DP_TRAINING_PATTERN_2;
+	ret = dw_dp_link_train_set_pattern(dp, pattern);
+	if (ret)
+		goto out;
+
+	usleep_range(500, 1000);
+
+	ret = drm_dp_dpcd_read_link_status(&dp->aux, status);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to read link status: %d\n", ret);
+		goto out;
+	}
+
+	if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
+		dev_err(dp->dev, "clock recovery failed\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	if (!drm_dp_channel_eq_ok(status, link->lanes)) {
+		dev_err(dp->dev, "channel equalization failed\n");
+		ret = -EIO;
+		goto out;
+	}
+
+out:
+	dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
+	return ret;
+}
+
+static int dw_dp_link_train(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	int ret;
+
+	if (link->caps.fast_training) {
+		if (dw_dp_link_train_valid(&link->train)) {
+			ret = dw_dp_link_train_fast(dp);
+			if (ret < 0)
+				dev_err(dp->dev, "fast link training failed: %d\n", ret);
+			else
+				return 0;
+		}
+	}
+
+	ret = dw_dp_link_train_full(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "full link training failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_dp_send_sdp(struct dw_dp *dp, struct dw_dp_sdp *sdp)
+{
+	const u8 *payload = sdp->base.db;
+	u32 reg;
+	int i, nr;
+
+	nr = find_first_zero_bit(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
+	if (nr < SDP_REG_BANK_SIZE)
+		set_bit(nr, dp->sdp_reg_bank);
+	else
+		return -EBUSY;
+
+	reg = DW_DP_SDP_REGISTER_BANK + nr * 9 * 4;
+
+	/* SDP header */
+	regmap_write(dp->regmap, reg, get_unaligned_le32(&sdp->base.sdp_header));
+
+	/* SDP data payload */
+	for (i = 1; i < 9; i++, payload += 4)
+		regmap_write(dp->regmap, reg + i * 4,
+			     FIELD_PREP(SDP_REGS, get_unaligned_le32(payload)));
+
+	if (sdp->flags & DW_DP_SDP_VERTICAL_INTERVAL)
+		regmap_update_bits(dp->regmap, DW_DP_SDP_VERTICAL_CTRL,
+				   EN_VERTICAL_SDP << nr,
+				   EN_VERTICAL_SDP << nr);
+
+	if (sdp->flags & DW_DP_SDP_HORIZONTAL_INTERVAL)
+		regmap_update_bits(dp->regmap, DW_DP_SDP_HORIZONTAL_CTRL,
+				   EN_HORIZONTAL_SDP << nr,
+				   EN_HORIZONTAL_SDP << nr);
+
+	return 0;
+}
+
+static int dw_dp_send_vsc_sdp(struct dw_dp *dp)
+{
+	struct dw_dp_video *video = &dp->video;
+	struct dw_dp_sdp sdp = {};
+	struct drm_dp_vsc_sdp vsc = {};
+
+	sdp.flags = DW_DP_SDP_VERTICAL_INTERVAL;
+
+	vsc.sdp_type = DP_SDP_VSC;
+	vsc.revision = 0x5;
+	vsc.length = 0x13;
+	vsc.bpc = video->bpc;
+	vsc.content_type = DP_CONTENT_TYPE_NOT_DEFINED;
+
+	switch (video->color_format) {
+	case DRM_COLOR_FORMAT_YCBCR444:
+		vsc.pixelformat = DP_PIXELFORMAT_YUV444;
+		break;
+	case DRM_COLOR_FORMAT_YCBCR420:
+		vsc.pixelformat = DP_PIXELFORMAT_YUV420;
+		break;
+	case DRM_COLOR_FORMAT_YCBCR422:
+		vsc.pixelformat = DP_PIXELFORMAT_YUV422;
+		break;
+	case DRM_COLOR_FORMAT_RGB444:
+	default:
+		vsc.pixelformat = DP_PIXELFORMAT_RGB;
+		break;
+	}
+
+	if (video->color_format == DRM_COLOR_FORMAT_RGB444) {
+		vsc.colorimetry = DP_COLORIMETRY_DEFAULT;
+		vsc.dynamic_range = DP_DYNAMIC_RANGE_VESA;
+	} else {
+		vsc.colorimetry = DP_COLORIMETRY_BT709_YCC;
+		vsc.dynamic_range = DP_DYNAMIC_RANGE_CTA;
+	}
+
+	drm_dp_vsc_sdp_pack(&vsc, &sdp.base);
+
+	return dw_dp_send_sdp(dp, &sdp);
+}
+
+static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode)
+{
+	switch (pixel_mode) {
+	case DW_DP_MP_SINGLE_PIXEL:
+	case DW_DP_MP_DUAL_PIXEL:
+	case DW_DP_MP_QUAD_PIXEL:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, PIXEL_MODE_SELECT,
+			   FIELD_PREP(PIXEL_MODE_SELECT, pixel_mode));
+
+	return 0;
+}
+
+static bool dw_dp_video_need_vsc_sdp(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	struct dw_dp_video *video = &dp->video;
+
+	if (!link->vsc_sdp_supported)
+		return false;
+
+	if (video->color_format == DRM_COLOR_FORMAT_YCBCR420)
+		return true;
+
+	return false;
+}
+
+static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc,
+			       u16 vstart, u16 hstart)
+{
+	u16 misc = 0;
+
+	if (dw_dp_video_need_vsc_sdp(dp))
+		misc |= DP_MSA_MISC_COLOR_VSC_SDP;
+
+	switch (color_format) {
+	case DRM_COLOR_FORMAT_RGB444:
+		misc |= DP_MSA_MISC_COLOR_RGB;
+		break;
+	case DRM_COLOR_FORMAT_YCBCR444:
+		misc |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
+		break;
+	case DRM_COLOR_FORMAT_YCBCR422:
+		misc |= DP_MSA_MISC_COLOR_YCBCR_422_BT709;
+		break;
+	case DRM_COLOR_FORMAT_YCBCR420:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (bpc) {
+	case 6:
+		misc |= DP_MSA_MISC_6_BPC;
+		break;
+	case 8:
+		misc |= DP_MSA_MISC_8_BPC;
+		break;
+	case 10:
+		misc |= DP_MSA_MISC_10_BPC;
+		break;
+	case 12:
+		misc |= DP_MSA_MISC_12_BPC;
+		break;
+	case 16:
+		misc |= DP_MSA_MISC_16_BPC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_write(dp->regmap, DW_DP_VIDEO_MSA1,
+		     FIELD_PREP(VSTART, vstart) | FIELD_PREP(HSTART, hstart));
+	regmap_write(dp->regmap, DW_DP_VIDEO_MSA2, FIELD_PREP(MISC0, misc));
+	regmap_write(dp->regmap, DW_DP_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8));
+
+	return 0;
+}
+
+static void dw_dp_video_disable(struct dw_dp *dp)
+{
+	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
+			   FIELD_PREP(VIDEO_STREAM_ENABLE, 0));
+}
+
+static int dw_dp_video_enable(struct dw_dp *dp)
+{
+	struct dw_dp_video *video = &dp->video;
+	struct dw_dp_link *link = &dp->link;
+	struct drm_display_mode *mode = &video->mode;
+	u8 color_format = video->color_format;
+	u8 bpc = video->bpc;
+	u8 pixel_mode = video->pixel_mode;
+	u8 bpp = video->bpp, init_threshold, vic;
+	u32 hactive, hblank, h_sync_width, h_front_porch;
+	u32 vactive, vblank, v_sync_width, v_front_porch;
+	u32 vstart = mode->vtotal - mode->vsync_start;
+	u32 hstart = mode->htotal - mode->hsync_start;
+	u32 peak_stream_bandwidth, link_bandwidth;
+	u32 average_bytes_per_tu, average_bytes_per_tu_frac;
+	u32 ts, hblank_interval;
+	u32 value;
+	int ret;
+
+	ret = dw_dp_video_set_pixel_mode(dp, pixel_mode);
+	if (ret)
+		return ret;
+
+	ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_MAPPING,
+			   FIELD_PREP(VIDEO_MAPPING, video->video_mapping));
+
+	/* Configure DW_DP_VINPUT_POLARITY_CTRL register */
+	value = 0;
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		value |= FIELD_PREP(HSYNC_IN_POLARITY, 1);
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		value |= FIELD_PREP(VSYNC_IN_POLARITY, 1);
+	regmap_write(dp->regmap, DW_DP_VINPUT_POLARITY_CTRL, value);
+
+	/* Configure DW_DP_VIDEO_CONFIG1 register */
+	hactive = mode->hdisplay;
+	hblank = mode->htotal - mode->hdisplay;
+	value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		value |= FIELD_PREP(I_P, 1);
+	vic = drm_match_cea_mode(mode);
+	if (vic == 5 || vic == 6 || vic == 7 ||
+	    vic == 10 || vic == 11 || vic == 20 ||
+	    vic == 21 || vic == 22 || vic == 39 ||
+	    vic == 25 || vic == 26 || vic == 40 ||
+	    vic == 44 || vic == 45 || vic == 46 ||
+	    vic == 50 || vic == 51 || vic == 54 ||
+	    vic == 55 || vic == 58 || vic  == 59)
+		value |= R_V_BLANK_IN_OSC;
+	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG1, value);
+
+	/* Configure DW_DP_VIDEO_CONFIG2 register */
+	vblank = mode->vtotal - mode->vdisplay;
+	vactive = mode->vdisplay;
+	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG2,
+		     FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
+
+	/* Configure DW_DP_VIDEO_CONFIG3 register */
+	h_sync_width = mode->hsync_end - mode->hsync_start;
+	h_front_porch = mode->hsync_start - mode->hdisplay;
+	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG3,
+		     FIELD_PREP(H_SYNC_WIDTH, h_sync_width) |
+		     FIELD_PREP(H_FRONT_PORCH, h_front_porch));
+
+	/* Configure DW_DP_VIDEO_CONFIG4 register */
+	v_sync_width = mode->vsync_end - mode->vsync_start;
+	v_front_porch = mode->vsync_start - mode->vdisplay;
+	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG4,
+		     FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
+		     FIELD_PREP(V_FRONT_PORCH, v_front_porch));
+
+	/* Configure DW_DP_VIDEO_CONFIG5 register */
+	peak_stream_bandwidth = mode->clock * bpp / 8;
+	link_bandwidth = (link->rate / 1000) * link->lanes;
+	ts = peak_stream_bandwidth * 64 / link_bandwidth;
+	average_bytes_per_tu = ts / 1000;
+	average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
+	if (pixel_mode == DW_DP_MP_SINGLE_PIXEL) {
+		if (average_bytes_per_tu < 6)
+			init_threshold = 32;
+		else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
+			init_threshold = 12;
+		else if (hblank <= 40 && color_format == DRM_COLOR_FORMAT_YCBCR420)
+			init_threshold = 3;
+		else
+			init_threshold = 16;
+	} else {
+		u32 t1 = 0, t2 = 0, t3 = 0;
+
+		switch (bpc) {
+		case 6:
+			t1 = (4 * 1000 / 9) * link->lanes;
+			break;
+		case 8:
+			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
+				t1 = (1000 / 2) * link->lanes;
+			} else {
+				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
+					t1 = (1000 / 3) * link->lanes;
+				else
+					t1 = (3000 / 16) * link->lanes;
+			}
+			break;
+		case 10:
+			if (color_format == DRM_COLOR_FORMAT_YCBCR422)
+				t1 = (2000 / 5) * link->lanes;
+			else
+				t1 = (4000 / 15) * link->lanes;
+			break;
+		case 12:
+			if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
+				if (pixel_mode == DW_DP_MP_DUAL_PIXEL)
+					t1 = (1000 / 6) * link->lanes;
+				else
+					t1 = (1000 / 3) * link->lanes;
+			} else {
+				t1 = (2000 / 9) * link->lanes;
+			}
+			break;
+		case 16:
+			if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
+			    pixel_mode == DW_DP_MP_DUAL_PIXEL)
+				t1 = (1000 / 6) * link->lanes;
+			else
+				t1 = (1000 / 4) * link->lanes;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (color_format == DRM_COLOR_FORMAT_YCBCR420)
+			t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
+		else
+			t2 = (link->rate / 4) * 1000 / mode->clock;
+
+		if (average_bytes_per_tu_frac)
+			t3 = average_bytes_per_tu + 1;
+		else
+			t3 = average_bytes_per_tu;
+		init_threshold = t1 * t2 * t3 / (1000 * 1000);
+		if (init_threshold <= 16 || average_bytes_per_tu < 10)
+			init_threshold = 40;
+	}
+
+	regmap_write(dp->regmap, DW_DP_VIDEO_CONFIG5,
+		     FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
+		     FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
+		     FIELD_PREP(INIT_THRESHOLD, init_threshold) |
+		     FIELD_PREP(AVERAGE_BYTES_PER_TU, average_bytes_per_tu));
+
+	/* Configure DW_DP_VIDEO_HBLANK_INTERVAL register */
+	hblank_interval = hblank * (link->rate / 4) / mode->clock;
+	regmap_write(dp->regmap, DW_DP_VIDEO_HBLANK_INTERVAL,
+		     FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
+		     FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
+
+	/* Video stream enable */
+	regmap_update_bits(dp->regmap, DW_DP_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE,
+			   FIELD_PREP(VIDEO_STREAM_ENABLE, 1));
+
+	if (dw_dp_video_need_vsc_sdp(dp))
+		dw_dp_send_vsc_sdp(dp);
+
+	return 0;
+}
+
+static void dw_dp_hpd_init(struct dw_dp *dp)
+{
+	/* Enable all HPD interrupts */
+	regmap_update_bits(dp->regmap, DW_DP_HPD_INTERRUPT_ENABLE,
+			   HPD_UNPLUG_EN | HPD_PLUG_EN | HPD_IRQ_EN,
+			   FIELD_PREP(HPD_UNPLUG_EN, 1) |
+			   FIELD_PREP(HPD_PLUG_EN, 1) |
+			   FIELD_PREP(HPD_IRQ_EN, 1));
+
+	/* Enable all top-level interrupts */
+	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
+			   HPD_EVENT_EN, FIELD_PREP(HPD_EVENT_EN, 1));
+}
+
+static void dw_dp_aux_init(struct dw_dp *dp)
+{
+	regmap_update_bits(dp->regmap, DW_DP_GENERAL_INTERRUPT_ENABLE,
+			   AUX_REPLY_EVENT_EN, FIELD_PREP(AUX_REPLY_EVENT_EN, 1));
+}
+
+static void dw_dp_init_hw(struct dw_dp *dp)
+{
+	regmap_update_bits(dp->regmap, DW_DP_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
+			   FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
+
+	dw_dp_hpd_init(dp);
+	dw_dp_aux_init(dp);
+}
+
+static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size)
+{
+	size_t i, j;
+
+	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
+		size_t num = min_t(size_t, size - i * 4, 4);
+		u32 value = 0;
+
+		for (j = 0; j < num; j++)
+			value |= buffer[i * 4 + j] << (j * 8);
+
+		regmap_write(dp->regmap, DW_DP_AUX_DATA0 + i * 4, value);
+	}
+
+	return size;
+}
+
+static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size)
+{
+	size_t i, j;
+
+	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
+		size_t num = min_t(size_t, size - i * 4, 4);
+		u32 value;
+
+		regmap_read(dp->regmap, DW_DP_AUX_DATA0 + i * 4, &value);
+
+		for (j = 0; j < num; j++)
+			buffer[i * 4 + j] = value >> (j * 8);
+	}
+
+	return size;
+}
+
+static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
+				  struct drm_dp_aux_msg *msg)
+{
+	struct dw_dp *dp = container_of(aux, struct dw_dp, aux);
+	unsigned long timeout = msecs_to_jiffies(10);
+	u32 status, value;
+	ssize_t ret = 0;
+
+	if (WARN_ON(msg->size > 16))
+		return -E2BIG;
+
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_NATIVE_WRITE:
+	case DP_AUX_I2C_WRITE:
+	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+		ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size);
+		if (ret < 0)
+			return ret;
+		break;
+	case DP_AUX_NATIVE_READ:
+	case DP_AUX_I2C_READ:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (msg->size > 0)
+		value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1);
+	else
+		value = FIELD_PREP(I2C_ADDR_ONLY, 1);
+	value |= FIELD_PREP(AUX_CMD_TYPE, msg->request);
+	value |= FIELD_PREP(AUX_ADDR, msg->address);
+	regmap_write(dp->regmap, DW_DP_AUX_CMD, value);
+
+	status = wait_for_completion_timeout(&dp->complete, timeout);
+	if (!status) {
+		dev_err(dp->dev, "timeout waiting for AUX reply\n");
+		return -ETIMEDOUT;
+	}
+
+	regmap_read(dp->regmap, DW_DP_AUX_STATUS, &value);
+	if (value & AUX_TIMEOUT)
+		return -ETIMEDOUT;
+
+	msg->reply = FIELD_GET(AUX_STATUS, value);
+
+	if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
+		if (msg->request & DP_AUX_I2C_READ) {
+			size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1;
+
+			if (count != msg->size)
+				return -EBUSY;
+
+			ret = dw_dp_aux_read_data(dp, msg->buffer, count);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Limits for the video timing for DP:
+ * 1. the hfp should be 2 pixels aligned;
+ * 2. the minimum hsync should be 9 pixel;
+ * 3. the minimum hbp should be 16 pixel;
+ */
+static int dw_dp_bridge_atomic_check(struct drm_bridge *bridge,
+				     struct drm_bridge_state *bridge_state,
+				     struct drm_crtc_state *crtc_state,
+				     struct drm_connector_state *conn_state)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+	struct dw_dp_video *video = &dp->video;
+	struct drm_display_mode *m = &video->mode;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	const struct dw_dp_output_format *fmt;
+	int min_hbp = 16;
+	int min_hsync = 9;
+
+	fmt = dw_dp_get_output_format(bridge_state->output_bus_cfg.format);
+	if (!fmt)
+		return -EINVAL;
+
+	video->video_mapping = fmt->video_mapping;
+	video->color_format = fmt->color_format;
+	video->bpc = fmt->bpc;
+	video->bpp = fmt->bpp;
+
+	if ((adjusted_mode->hsync_start - adjusted_mode->hdisplay) & 0x1) {
+		adjusted_mode->hsync_start += 1;
+		dev_warn(dp->dev, "hfp is not 2 pixeel aligned, fixup to aligned hfp\n");
+	}
+	if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) {
+		adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync;
+		dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync);
+	}
+	if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) {
+		adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp;
+		dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp);
+	}
+
+	drm_mode_copy(m, adjusted_mode);
+
+	return 0;
+}
+
+static enum drm_mode_status dw_dp_bridge_mode_valid(struct drm_bridge *bridge,
+						    const struct drm_display_info *info,
+						    const struct drm_display_mode *mode)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+	struct dw_dp_link *link = &dp->link;
+	u32 min_bpp;
+
+	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420 &&
+	    link->vsc_sdp_supported &&
+	    (drm_mode_is_420_only(info, mode) || drm_mode_is_420_also(info, mode)))
+		min_bpp = 12;
+	else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
+		min_bpp = 16;
+	else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
+		min_bpp = 18;
+	else
+		min_bpp = 24;
+
+	if (!link->vsc_sdp_supported &&
+	    drm_mode_is_420_only(info, mode))
+		return MODE_NO_420;
+
+	if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, link->lanes, link->rate))
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static bool dw_dp_needs_link_retrain(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+
+	if (!dw_dp_link_train_valid(&link->train))
+		return false;
+
+	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) < 0)
+		return false;
+
+	/* Retrain if Channel EQ or CR not ok */
+	return !drm_dp_channel_eq_ok(link_status, dp->link.lanes);
+}
+
+static void dw_dp_link_disable(struct dw_dp *dp)
+{
+	struct dw_dp_link *link = &dp->link;
+
+	if (dw_dp_hpd_detect(dp))
+		dw_dp_link_power_down(dp);
+
+	dw_dp_phy_xmit_enable(dp, 0);
+
+	phy_power_off(dp->phy);
+
+	link->train.clock_recovered = false;
+	link->train.channel_equalized = false;
+}
+
+static int dw_dp_link_enable(struct dw_dp *dp)
+{
+	int ret;
+
+	ret = phy_power_on(dp->phy);
+	if (ret)
+		return ret;
+
+	ret = dw_dp_link_power_up(dp);
+	if (ret < 0)
+		return ret;
+
+	ret = dw_dp_link_train(dp);
+
+	return ret;
+}
+
+static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
+				       struct drm_bridge_state *old_state)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+	struct drm_atomic_state *state = old_state->base.state;
+	struct drm_connector *connector;
+	struct drm_connector_state *conn_state;
+	int ret;
+
+	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+	if (!connector) {
+		dev_err(dp->dev, "failed to get connector\n");
+		return;
+	}
+
+	conn_state = drm_atomic_get_new_connector_state(state, connector);
+	if (!conn_state) {
+		dev_err(dp->dev, "failed to get connector state\n");
+		return;
+	}
+
+	set_bit(0, dp->sdp_reg_bank);
+
+	ret = dw_dp_link_enable(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to enable link: %d\n", ret);
+		return;
+	}
+
+	ret = dw_dp_video_enable(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to enable video: %d\n", ret);
+		return;
+	}
+}
+
+static void dw_dp_reset(struct dw_dp *dp)
+{
+	int val;
+
+	disable_irq(dp->irq);
+	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
+			   FIELD_PREP(CONTROLLER_RESET, 1));
+	udelay(10);
+	regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, CONTROLLER_RESET,
+			   FIELD_PREP(CONTROLLER_RESET, 0));
+
+	dw_dp_init_hw(dp);
+	regmap_read_poll_timeout(dp->regmap, DW_DP_HPD_STATUS, val,
+				 FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
+	regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
+	enable_irq(dp->irq);
+}
+
+static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
+					struct drm_bridge_state *old_bridge_state)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+
+	dw_dp_video_disable(dp);
+	dw_dp_link_disable(dp);
+	bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
+	dw_dp_reset(dp);
+}
+
+static bool dw_dp_hpd_detect_link(struct dw_dp *dp)
+{
+	int ret;
+
+	ret = phy_power_on(dp->phy);
+	if (ret < 0)
+		return false;
+	ret = dw_dp_link_parse(dp);
+	phy_power_off(dp->phy);
+
+	return !ret;
+}
+
+static enum drm_connector_status dw_dp_bridge_detect(struct drm_bridge *bridge)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+
+	if (!dw_dp_hpd_detect(dp))
+		return connector_status_disconnected;
+
+	if (!dw_dp_hpd_detect_link(dp))
+		return connector_status_disconnected;
+
+	return connector_status_connected;
+}
+
+static const struct drm_edid *dw_dp_bridge_edid_read(struct drm_bridge *bridge,
+						     struct drm_connector *connector)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+	const struct drm_edid *edid;
+	int ret;
+
+	ret = phy_power_on(dp->phy);
+	if (ret)
+		return NULL;
+
+	edid = drm_edid_read_ddc(connector, &dp->aux.ddc);
+
+	phy_power_off(dp->phy);
+
+	return edid;
+}
+
+static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+						    struct drm_bridge_state *bridge_state,
+						    struct drm_crtc_state *crtc_state,
+						    struct drm_connector_state *conn_state,
+						    unsigned int *num_output_fmts)
+{
+	struct dw_dp *dp = bridge_to_dp(bridge);
+	struct dw_dp_link *link = &dp->link;
+	struct drm_display_info *di = &conn_state->connector->display_info;
+	struct drm_display_mode mode = crtc_state->mode;
+	const struct dw_dp_output_format *fmt;
+	u32 i, j = 0;
+	u32 *output_fmts;
+
+	*num_output_fmts = 0;
+
+	output_fmts = kcalloc(ARRAY_SIZE(dw_dp_output_formats), sizeof(*output_fmts), GFP_KERNEL);
+	if (!output_fmts)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(dw_dp_output_formats); i++) {
+		fmt = &dw_dp_output_formats[i];
+
+		if (fmt->bpc > conn_state->max_bpc)
+			continue;
+
+		if (!(fmt->color_format & di->color_formats))
+			continue;
+
+		if (fmt->color_format == DRM_COLOR_FORMAT_YCBCR420 &&
+		    !link->vsc_sdp_supported)
+			continue;
+
+		if (fmt->color_format != DRM_COLOR_FORMAT_YCBCR420 &&
+		    drm_mode_is_420_only(di, &mode))
+			continue;
+
+		if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate))
+			continue;
+
+		output_fmts[j++] = fmt->bus_format;
+	}
+
+	*num_output_fmts = j;
+
+	return output_fmts;
+}
+
+static const struct drm_bridge_funcs dw_dp_bridge_funcs = {
+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+	.atomic_reset = drm_atomic_helper_bridge_reset,
+	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
+	.atomic_get_output_bus_fmts = dw_dp_bridge_atomic_get_output_bus_fmts,
+	.atomic_check = dw_dp_bridge_atomic_check,
+	.mode_valid = dw_dp_bridge_mode_valid,
+	.atomic_enable = dw_dp_bridge_atomic_enable,
+	.atomic_disable = dw_dp_bridge_atomic_disable,
+	.detect = dw_dp_bridge_detect,
+	.edid_read = dw_dp_bridge_edid_read,
+};
+
+static int dw_dp_link_retrain(struct dw_dp *dp)
+{
+	struct drm_device *dev = dp->bridge.dev;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret;
+
+	if (!dw_dp_needs_link_retrain(dp))
+		return 0;
+
+	dev_dbg(dp->dev, "Retraining link\n");
+
+	drm_modeset_acquire_init(&ctx, 0);
+	for (;;) {
+		ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+		if (ret != -EDEADLK)
+			break;
+
+		drm_modeset_backoff(&ctx);
+	}
+
+	if (!ret)
+		ret = dw_dp_link_train(dp);
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+}
+
+static void dw_dp_hpd_work(struct work_struct *work)
+{
+	struct dw_dp *dp = container_of(work, struct dw_dp, hpd_work);
+	bool long_hpd;
+	int ret;
+
+	mutex_lock(&dp->irq_lock);
+	long_hpd = dp->hotplug.long_hpd;
+	mutex_unlock(&dp->irq_lock);
+
+	dev_dbg(dp->dev, "[drm] Get hpd irq - %s\n", long_hpd ? "long" : "short");
+
+	if (!long_hpd) {
+		if (dw_dp_needs_link_retrain(dp)) {
+			ret = dw_dp_link_retrain(dp);
+			if (ret)
+				dev_warn(dp->dev, "Retrain link failed\n");
+		}
+	} else {
+		drm_helper_hpd_irq_event(dp->bridge.dev);
+	}
+}
+
+static void dw_dp_handle_hpd_event(struct dw_dp *dp)
+{
+	u32 value;
+
+	mutex_lock(&dp->irq_lock);
+	regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
+
+	if (value & HPD_IRQ) {
+		dev_dbg(dp->dev, "IRQ from the HPD\n");
+		dp->hotplug.long_hpd = false;
+		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_IRQ);
+	}
+
+	if (value & HPD_HOT_PLUG) {
+		dev_dbg(dp->dev, "Hot plug detected\n");
+		dp->hotplug.long_hpd = true;
+		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_PLUG);
+	}
+
+	if (value & HPD_HOT_UNPLUG) {
+		dev_dbg(dp->dev, "Unplug detected\n");
+		dp->hotplug.long_hpd = true;
+		regmap_write(dp->regmap, DW_DP_HPD_STATUS, HPD_HOT_UNPLUG);
+	}
+	mutex_unlock(&dp->irq_lock);
+
+	schedule_work(&dp->hpd_work);
+}
+
+static irqreturn_t dw_dp_irq(int irq, void *data)
+{
+	struct dw_dp *dp = data;
+	u32 value;
+
+	regmap_read(dp->regmap, DW_DP_GENERAL_INTERRUPT, &value);
+	if (!value)
+		return IRQ_NONE;
+
+	if (value & HPD_EVENT)
+		dw_dp_handle_hpd_event(dp);
+
+	if (value & AUX_REPLY_EVENT) {
+		regmap_write(dp->regmap, DW_DP_GENERAL_INTERRUPT, AUX_REPLY_EVENT);
+		complete(&dp->complete);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static const struct regmap_range dw_dp_readable_ranges[] = {
+	regmap_reg_range(DW_DP_VERSION_NUMBER, DW_DP_ID),
+	regmap_reg_range(DW_DP_CONFIG_REG1, DW_DP_CONFIG_REG3),
+	regmap_reg_range(DW_DP_CCTL, DW_DP_SOFT_RESET_CTRL),
+	regmap_reg_range(DW_DP_VSAMPLE_CTRL, DW_DP_VIDEO_HBLANK_INTERVAL),
+	regmap_reg_range(DW_DP_AUD_CONFIG1, DW_DP_AUD_CONFIG1),
+	regmap_reg_range(DW_DP_SDP_VERTICAL_CTRL, DW_DP_SDP_STATUS_EN),
+	regmap_reg_range(DW_DP_PHYIF_CTRL, DW_DP_PHYIF_PWRDOWN_CTRL),
+	regmap_reg_range(DW_DP_AUX_CMD, DW_DP_AUX_DATA3),
+	regmap_reg_range(DW_DP_GENERAL_INTERRUPT, DW_DP_HPD_INTERRUPT_ENABLE),
+};
+
+static const struct regmap_access_table dw_dp_readable_table = {
+	.yes_ranges     = dw_dp_readable_ranges,
+	.n_yes_ranges   = ARRAY_SIZE(dw_dp_readable_ranges),
+};
+
+static const struct regmap_config dw_dp_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.fast_io = true,
+	.max_register = DW_DP_MAX_REGISTER,
+	.rd_table = &dw_dp_readable_table,
+};
+
+static void dw_dp_phy_exit(void *data)
+{
+	struct dw_dp *dp = data;
+
+	phy_exit(dp->phy);
+}
+
+struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
+			 const struct dw_dp_plat_data *plat_data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dw_dp *dp;
+	struct drm_bridge *bridge;
+	void __iomem *res;
+	int ret;
+
+	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return ERR_PTR(-ENOMEM);
+
+	dp->dev = dev;
+	dp->video.pixel_mode = DW_DP_MP_QUAD_PIXEL;
+
+	dp->plat_data.max_link_rate = plat_data->max_link_rate;
+	bridge = &dp->bridge;
+	mutex_init(&dp->irq_lock);
+	INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
+	init_completion(&dp->complete);
+
+	res = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(res))
+		return ERR_CAST(res);
+
+	dp->regmap = devm_regmap_init_mmio(dev, res, &dw_dp_regmap_config);
+	if (IS_ERR(dp->regmap)) {
+		dev_err_probe(dev, PTR_ERR(dp->regmap), "failed to create regmap\n");
+		return ERR_CAST(dp->regmap);
+	}
+
+	dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
+	if (IS_ERR(dp->phy)) {
+		dev_err_probe(dev, PTR_ERR(dp->phy), "failed to get phy\n");
+		return ERR_CAST(dp->phy);
+	}
+
+	dp->apb_clk = devm_clk_get_enabled(dev, "apb");
+	if (IS_ERR(dp->apb_clk)) {
+		dev_err_probe(dev, PTR_ERR(dp->apb_clk), "failed to get apb clock\n");
+		return ERR_CAST(dp->apb_clk);
+	}
+
+	dp->aux_clk = devm_clk_get_enabled(dev, "aux");
+	if (IS_ERR(dp->aux_clk)) {
+		dev_err_probe(dev, PTR_ERR(dp->aux_clk), "failed to get aux clock\n");
+		return ERR_CAST(dp->aux_clk);
+	}
+
+	dp->i2s_clk = devm_clk_get(dev, "i2s");
+	if (IS_ERR(dp->i2s_clk)) {
+		dev_err_probe(dev, PTR_ERR(dp->i2s_clk), "failed to get i2s clock\n");
+		return ERR_CAST(dp->i2s_clk);
+	}
+
+	dp->spdif_clk = devm_clk_get(dev, "spdif");
+	if (IS_ERR(dp->spdif_clk)) {
+		dev_err_probe(dev, PTR_ERR(dp->spdif_clk), "failed to get spdif clock\n");
+		return ERR_CAST(dp->spdif_clk);
+	}
+
+	dp->hdcp_clk = devm_clk_get(dev, "hdcp");
+	if (IS_ERR(dp->hdcp_clk)) {
+		dev_err_probe(dev, PTR_ERR(dp->hdcp_clk), "failed to get hdcp clock\n");
+		return ERR_CAST(dp->hdcp_clk);
+	}
+
+	dp->rstc = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(dp->rstc)) {
+		dev_err_probe(dev, PTR_ERR(dp->rstc), "failed to get reset control\n");
+		return ERR_CAST(dp->rstc);
+	}
+
+	bridge->of_node = dev->of_node;
+	bridge->funcs = &dw_dp_bridge_funcs;
+	bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
+	bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
+	bridge->ycbcr_420_allowed = true;
+
+	dp->aux.dev = dev;
+	dp->aux.drm_dev = encoder->dev;
+	dp->aux.name = dev_name(dev);
+	dp->aux.transfer = dw_dp_aux_transfer;
+	ret = drm_dp_aux_register(&dp->aux);
+	if (ret) {
+		dev_err_probe(dev, ret, "Aux register failed\n");
+		return ERR_PTR(ret);
+	}
+
+	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret)
+		dev_err_probe(dev, ret, "Failed to attach bridge\n");
+
+	dw_dp_init_hw(dp);
+
+	ret = phy_init(dp->phy);
+	if (ret) {
+		dev_err_probe(dev, ret, "phy init failed\n");
+		return ERR_PTR(ret);
+	}
+
+	ret = devm_add_action_or_reset(dev, dw_dp_phy_exit, dp);
+	if (ret)
+		return ERR_PTR(ret);
+
+	dp->irq = platform_get_irq(pdev, 0);
+	if (dp->irq < 0)
+		return ERR_PTR(ret);
+
+	ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
+					IRQF_ONESHOT, dev_name(dev), dp);
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to request irq\n");
+		return ERR_PTR(ret);
+	}
+
+	return dp;
+}
+EXPORT_SYMBOL_GPL(dw_dp_bind);
+
+MODULE_AUTHOR("Andy Yan <andyshrk at 163.com>");
+MODULE_DESCRIPTION("DW DP Core Library");
+MODULE_LICENSE("GPL");
diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
new file mode 100644
index 000000000000..07845f609eca
--- /dev/null
+++ b/include/drm/bridge/dw_dp.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __DW_DP__
+#define __DW_DP__
+
+struct device;
+struct drm_encoder;
+struct dw_dp;
+
+struct dw_dp_plat_data {
+	u32 max_link_rate;
+};
+
+struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
+			 const struct dw_dp_plat_data *plat_data);
+#endif /* __DW_DP__ */
-- 
2.34.1



From andyshrk at 163.com  Wed Mar 12 03:42:04 2025
From: andyshrk at 163.com (Andy Yan)
Date: Wed, 12 Mar 2025 18:42:04 +0800
Subject: [PATCH v2 3/7] drm/rockchip: Add RK3588 DPTX output support
In-Reply-To: <20250312104214.525242-1-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
Message-ID: <20250312104214.525242-4-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Add driver extension for Synopsys DesignWare DPTX IP used
on Rockchip RK3588 SoC.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>

---

Changes in v2:
- no include uapi path
- switch to drmm_encoder_init

 drivers/gpu/drm/rockchip/Kconfig            |   7 +
 drivers/gpu/drm/rockchip/Makefile           |   1 +
 drivers/gpu/drm/rockchip/dw_dp-rockchip.c   | 154 ++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 5 files changed, 164 insertions(+)
 create mode 100644 drivers/gpu/drm/rockchip/dw_dp-rockchip.c

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 26c4410b2407..c8638baf9641 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
 	select DRM_PANEL
 	select VIDEOMODE_HELPERS
 	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
+	select DRM_DW_DP if ROCKCHIP_DW_DP
 	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
 	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
 	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
@@ -58,6 +59,12 @@ config ROCKCHIP_CDN_DP
 	  RK3399 based SoC, you should select this
 	  option.
 
+config ROCKCHIP_DW_DP
+	bool "Rockchip specific extensions for Synopsys DW DP"
+	help
+	  Choose this option for Synopsys DesignWare Cores DisplayPort
+	  transmit controller support on Rockchip SoC.
+
 config ROCKCHIP_DW_HDMI
 	bool "Rockchip specific extensions for Synopsys DW HDMI"
 	help
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 2b867cebbc12..097f062399c7 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -14,6 +14,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI2) += dw-mipi-dsi2-rockchip.o
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_DP) += dw_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
 rockchipdrm-$(CONFIG_ROCKCHIP_RGB) += rockchip_rgb.o
diff --git a/drivers/gpu/drm/rockchip/dw_dp-rockchip.c b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
new file mode 100644
index 000000000000..5ff8a6a54997
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ *
+ * Author: Zhang Yubing <yubing.zhang at rock-chips.com>
+ * Author: Andy Yan <andy.yan at rock-chips.com>
+ */
+
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <drm/bridge/dw_dp.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_of.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include <linux/media-bus-format.h>
+#include <linux/videodev2.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_vop.h"
+
+struct rockchip_dw_dp {
+	struct dw_dp *base;
+	struct device *dev;
+	struct rockchip_encoder encoder;
+};
+
+static inline struct rockchip_dw_dp *encoder_to_dp(struct drm_encoder *encoder)
+{
+	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
+
+	return container_of(rkencoder, struct rockchip_dw_dp, encoder);
+}
+
+static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+	struct drm_atomic_state *state = conn_state->state;
+	struct drm_display_info *di = &conn_state->connector->display_info;
+	struct drm_bridge *bridge  = drm_bridge_chain_get_first_bridge(encoder);
+	struct drm_bridge_state *bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+	u32 bus_format = bridge_state->input_bus_cfg.format;
+
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		s->output_mode = ROCKCHIP_OUT_MODE_YUV420;
+		break;
+	case MEDIA_BUS_FMT_YUYV10_1X20:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+		s->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
+		break;
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	default:
+		s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+		break;
+	}
+
+	s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
+	s->bus_format = bus_format;
+	s->bus_flags = di->bus_flags;
+	s->color_space = V4L2_COLORSPACE_DEFAULT;
+
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs dw_dp_encoder_helper_funcs = {
+	.atomic_check		= dw_dp_encoder_atomic_check,
+};
+
+static int dw_dp_rockchip_bind(struct device *dev, struct device *master, void *data)
+{
+	struct dw_dp_plat_data plat_data;
+	struct drm_device *drm_dev = data;
+	struct rockchip_dw_dp *dp;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int ret;
+
+	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	dp->dev = dev;
+	plat_data.max_link_rate = 810000;
+	encoder = &dp->encoder.encoder;
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
+	rockchip_drm_encoder_set_crtc_endpoint_id(&dp->encoder, dev->of_node, 0, 0);
+
+	ret = drmm_encoder_init(drm_dev, encoder, NULL, DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+	drm_encoder_helper_add(encoder, &dw_dp_encoder_helper_funcs);
+
+	dp->base = dw_dp_bind(dev, encoder, &plat_data);
+	if (IS_ERR(dp->base)) {
+		ret = PTR_ERR(dp->base);
+		return ret;
+	}
+
+	connector = drm_bridge_connector_init(drm_dev, encoder);
+	if (IS_ERR(connector)) {
+		ret = PTR_ERR(connector);
+		return dev_err_probe(dev, ret, "Failed to init bridge connector");
+	}
+
+	drm_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
+
+static const struct component_ops dw_dp_rockchip_component_ops = {
+	.bind = dw_dp_rockchip_bind,
+};
+
+static int dw_dp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	return component_add(dev, &dw_dp_rockchip_component_ops);
+}
+
+static void dw_dp_remove(struct platform_device *pdev)
+{
+	struct rockchip_dw_dp *dp = platform_get_drvdata(pdev);
+
+	component_del(dp->dev, &dw_dp_rockchip_component_ops);
+}
+
+static const struct of_device_id dw_dp_of_match[] = {
+	{ .compatible = "rockchip,rk3588-dp", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, dw_dp_of_match);
+
+struct platform_driver dw_dp_driver = {
+	.probe	= dw_dp_probe,
+	.remove = dw_dp_remove,
+	.driver = {
+		.name = "dw-dp",
+		.of_match_table = dw_dp_of_match,
+	},
+};
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 9cf311b5dec1..2b245491c71d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -529,6 +529,7 @@ static int __init rockchip_drm_init(void)
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
 				CONFIG_ROCKCHIP_ANALOGIX_DP);
 	ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
+	ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP);
 	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
 				CONFIG_ROCKCHIP_DW_HDMI);
 	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index c183e82a42a5..2e86ad00979c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -87,6 +87,7 @@ int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder,
 					      struct device_node *np, int port, int reg);
 int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
 extern struct platform_driver cdn_dp_driver;
+extern struct platform_driver dw_dp_driver;
 extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
 extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
 extern struct platform_driver dw_mipi_dsi_rockchip_driver;
-- 
2.34.1



From wenst at chromium.org  Wed Mar 12 03:43:34 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:34 +0800
Subject: [PATCH 0/8] arm64: mediatek: mt8186-corsola: Consolidate and add new devices
Message-ID: <20250312104344.3084425-1-wenst@chromium.org>

Hi everyone,

Here's a follow up series of the I2C component probers for Chromebooks.
This series enables the component prober for the Corsola series of
devices, combines the two existing Voltorb SKUs, and adds a new
device, codename Squirtle.

Patch 1 adds a new HID-over-I2C touchscreen from Elan.

Patch 2 merges the Voltorb entries in the device tree bindings into one.

Patch 3 adds a new entry for the Squirtle device to the bindings.

Patch 4 fixes up the existing device trees for the component prober to
be active.

Patch 5 merges the device trees for the Voltorb device.

Patch 6 adds a device tree file for the Squirtle device, with I2C
components ready to be probed by the prober.

Patch 7 enables the prober to probe trackpads on some devices in the
Corsola family.

Patch 8 enables the prober to probe touchscreens on Squirtle.

Please take a look.


Thanks
ChenYu


Chen-Yu Tsai (8):
  dt-bindings: HID: i2c-hid: elan: Introduce Elan eKTH8D18
  dt-bindings: arm: mediatek: Merge MT8186 Voltorb entries
  dt-bindings: arm: mediatek: Add MT8186 Squirtle Chromebooks
  arm64: dts: mediatek: mt8186-steelix: Mark second source components
    for probing
  arm64: dts: mediatek: mt8186: Merge Voltorb device trees
  arm64: dts: mediatek: mt8186: Add Squirtle Chromebooks
  platform/chrome: of_hw_prober: Support trackpad probing on Corsola
    family
  platform/chrome: of_hw_prober: Support touchscreen probing on Squirtle

 .../devicetree/bindings/arm/mediatek.yaml     |   7 +-
 .../bindings/input/elan,ekth6915.yaml         |  29 ++++-
 arch/arm64/boot/dts/mediatek/Makefile         |   4 +-
 .../dts/mediatek/mt8186-corsola-squirtle.dts  | 107 ++++++++++++++++++
 .../dts/mediatek/mt8186-corsola-steelix.dtsi  |   9 +-
 .../mt8186-corsola-tentacool-sku327683.dts    |   2 +
 .../mt8186-corsola-tentacruel-sku262148.dts   |   2 +
 .../mt8186-corsola-voltorb-sku589824.dts      |  13 ---
 ...u589825.dts => mt8186-corsola-voltorb.dts} |   5 +-
 .../boot/dts/mediatek/mt8186-corsola.dtsi     |  10 +-
 .../platform/chrome/chromeos_of_hw_prober.c   |  29 +++++
 11 files changed, 185 insertions(+), 32 deletions(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts
 delete mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
 rename arch/arm64/boot/dts/mediatek/{mt8186-corsola-voltorb-sku589825.dts => mt8186-corsola-voltorb.dts} (76%)

-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:35 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:35 +0800
Subject: [PATCH 1/8] dt-bindings: HID: i2c-hid: elan: Introduce Elan eKTH8D18
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-2-wenst@chromium.org>

The Elan eKTH8D18 touchscreen controller is an I2C HID device with a
longer boot-up time. Power sequence timing wise it is compatible with
the eKTH6A12NAY, with a power-on delay of at least 5ms, 20ms
out-of-reset for I2C ack response, and 150ms out-of-reset for I2C HID
enumeration. Enumeration and subsequent operation follows the I2C HID
standard. The eKTH6A12NAY requires longer times for both parts.

Add a compatible string for it with the ekth6a12nay one as a fallback.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 .../bindings/input/elan,ekth6915.yaml         | 29 ++++++++++++++++---
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
index cb3e1801b0d3..81c391952ccc 100644
--- a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
+++ b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
@@ -4,14 +4,14 @@
 $id: http://devicetree.org/schemas/input/elan,ekth6915.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Elan eKTH6915 touchscreen controller
+title: Elan I2C-HID touchscreen controllers
 
 maintainers:
   - Douglas Anderson <dianders at chromium.org>
 
 description:
-  Supports the Elan eKTH6915 touchscreen controller.
-  This touchscreen controller uses the i2c-hid protocol with a reset GPIO.
+  Supports the Elan eKTH6915 and other I2C-HID touchscreen controllers.
+  These touchscreen controller use the i2c-hid protocol with a reset GPIO.
 
 allOf:
   - $ref: /schemas/input/touchscreen/touchscreen.yaml#
@@ -23,12 +23,18 @@ properties:
           - enum:
               - elan,ekth5015m
           - const: elan,ekth6915
+      - items:
+          - enum:
+              - elan,ekth8d18
+          - const: elan,ekth6a12nay
       - enum:
           - elan,ekth6915
           - elan,ekth6a12nay
 
   reg:
-    const: 0x10
+    enum:
+      - 0x10
+      - 0x16
 
   interrupts:
     maxItems: 1
@@ -58,6 +64,21 @@ required:
   - interrupts
   - vcc33-supply
 
+if:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - elan,ekth8d18
+then:
+  properties:
+    reg:
+      const: 0x16
+else:
+  properties:
+    reg:
+      const: 0x10
+
 additionalProperties: false
 
 examples:
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:36 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:36 +0800
Subject: [PATCH 2/8] dt-bindings: arm: mediatek: Merge MT8186 Voltorb entries
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-3-wenst@chromium.org>

There are only two different SKUs of Voltorb, and the only difference
between them is whether a touchscreen is present or not. This can be
detected by a simple I2C transfer to the address, instead of having
separate compatible strings and device trees.

Drop the SKU-specific compatible strings and just keep the generic
"google,voltorb" one.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 Documentation/devicetree/bindings/arm/mediatek.yaml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index 108ae5e0185d..49ddc504c160 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -339,9 +339,6 @@ properties:
           - const: mediatek,mt8186
       - description: Google Voltorb (Acer Chromebook 311 C723/C732T)
         items:
-          - enum:
-              - google,voltorb-sku589824
-              - google,voltorb-sku589825
           - const: google,voltorb
           - const: mediatek,mt8186
       - items:
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From wenst at chromium.org  Wed Mar 12 03:43:37 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 18:43:37 +0800
Subject: [PATCH 3/8] dt-bindings: arm: mediatek: Add MT8186 Squirtle Chromebooks
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <20250312104344.3084425-4-wenst@chromium.org>

Add an entry for the MT8186 based Squirtle Chromebooks, also known as the
Acer Chromebook Spin 311 (R724T). The device is a 2-in-1 convertible.

Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
---
 Documentation/devicetree/bindings/arm/mediatek.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index 49ddc504c160..f0b4ccd81c4d 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -291,6 +291,10 @@ properties:
           - const: google,steelix-sku196608
           - const: google,steelix
           - const: mediatek,mt8186
+      - description: Google Squirtle (Acer Chromebook Spin 311 (R724T)
+        items:
+          - const: google,squirtle
+          - const: mediatek,mt8186
       - description: Google Starmie (ASUS Chromebook Enterprise CM30 (CM3001))
         items:
           - const: google,starmie-sku0
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From peterz at infradead.org  Wed Mar 12 03:44:01 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 12 Mar 2025 11:44:01 +0100
Subject: [PATCH v3 3/5] perf: Allow adding fixed random jitter to the
 alternate sampling period
In-Reply-To: <20250311113530.GA9968@noisy.programming.kicks-ass.net>
References: <20250307202247.648633-1-mark.barnett@arm.com>
 <20250307202247.648633-4-mark.barnett@arm.com>
 <20250311113128.GD19424@noisy.programming.kicks-ass.net>
 <20250311113530.GA9968@noisy.programming.kicks-ass.net>
Message-ID: <20250312104401.GC9968@noisy.programming.kicks-ass.net>

On Tue, Mar 11, 2025 at 12:35:30PM +0100, Peter Zijlstra wrote:
> On Tue, Mar 11, 2025 at 12:31:29PM +0100, Peter Zijlstra wrote:
> > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > index b87a5ac42ce2..e5a93edf3b5f 100644
> > --- a/kernel/events/core.c
> > +++ b/kernel/events/core.c
> > @@ -8,6 +8,7 @@
> >   *  Copyright  ?  2009 Paul Mackerras, IBM Corp. <paulus at au1.ibm.com>
> >   */
> >  
> > +#include "linux/random.h"
> >  #include <linux/fs.h>
> >  #include <linux/mm.h>
> >  #include <linux/cpu.h>
> 
> Argh, this is neovim trying to be 'helpful'. If anybody reading this
> knows how to make it stop adding headers, please let me know, its
> driving me nuts.

Adding this cmd thing to the lspconfig like so:

require 'lspconfig'.clangd.setup() {
	cmd = {
		"clangd",
		"--header-insertion=never",
	},
}

seems to do the trick.


From lorenzo at kernel.org  Wed Mar 12 04:13:53 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:53 +0100
Subject: [PATCH 09/21] wifi: mt76: mt7996: rework mt7996_set_hw_key to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-9-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Modify mt7996_set_hw_key routine to work in a multi-link setup.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 138 +++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |  18 +--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |   4 +-
 3 files changed, 99 insertions(+), 61 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4abbe761b732f1ea7791ba1f86c2c87db1eea91d..a845c3e758adcc4802f704a99ac39aa9ca670c88 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -158,62 +158,101 @@ mt7996_init_bitrate_mask(struct ieee80211_vif *vif, struct mt7996_vif_link *mlin
 static int
 mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-		  struct mt7996_vif_link *mlink, struct ieee80211_key_conf *key)
+		  struct ieee80211_key_conf *key)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt76_wcid *wcid = &mlink->msta_link.wcid;
-	struct mt7996_phy *phy;
 	int idx = key->keyidx;
-	u8 *wcid_keyidx;
+	unsigned int link_id;
+	unsigned long links;
+
+	if (key->link_id >= 0)
+		links = BIT(key->link_id);
+	else if (sta && sta->valid_links)
+		links = sta->valid_links;
+	else if (vif->valid_links)
+		links = vif->valid_links;
+	else
+		links = BIT(0);
 
-	phy = mt7996_vif_link_phy(mlink);
-	if (!phy)
-		return -EINVAL;
+	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
+		u8 *wcid_keyidx;
+		int err;
 
-	if (sta) {
-		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
 
-		wcid = &msta->deflink.wcid;
-		if (!wcid->sta)
-			return -EOPNOTSUPP;
-	}
-	wcid_keyidx = &wcid->hw_key_idx;
+		if (sta) {
+			struct mt7996_sta *msta;
 
-	switch (key->cipher) {
-	case WLAN_CIPHER_SUITE_AES_CMAC:
-	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-		if (key->keyidx == 6 || key->keyidx == 7) {
-			wcid_keyidx = &wcid->hw_key_idx2;
-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+			msta = (struct mt7996_sta *)sta->drv_priv;
+			msta_link = mt76_dereference(msta->link[link_id],
+						     &dev->mt76);
+			if (!msta_link)
+				continue;
+
+			if (!msta_link->wcid.sta)
+				return -EOPNOTSUPP;
+		} else {
+			msta_link = &link->msta_link;
+		}
+		wcid_keyidx = &msta_link->wcid.hw_key_idx;
+
+		switch (key->cipher) {
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+			if (key->keyidx == 6 || key->keyidx == 7) {
+				wcid_keyidx = &msta_link->wcid.hw_key_idx2;
+				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+			}
+			break;
+		default:
+			break;
 		}
-		break;
-	default:
-		break;
-	}
 
-	if (cmd == SET_KEY && !sta && !mlink->mt76.cipher) {
-		mlink->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
-		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76,
-					&mlink->msta_link, true);
-	}
+		if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
+			struct ieee80211_bss_conf *link_conf;
 
-	if (cmd == SET_KEY) {
-		*wcid_keyidx = idx;
-	} else {
-		if (idx == *wcid_keyidx)
-			*wcid_keyidx = -1;
-		return 0;
-	}
+			link_conf = link_conf_dereference_protected(vif,
+								    link_id);
+			if (!link_conf)
+				link_conf = &vif->bss_conf;
 
-	mt76_wcid_key_setup(&dev->mt76, wcid, key);
+			link->mt76.cipher =
+				mt76_connac_mcu_get_cipher(key->cipher);
+			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
+						&link->mt76, msta_link, true);
+		}
 
-	if (key->keyidx == 6 || key->keyidx == 7)
-		return mt7996_mcu_bcn_prot_enable(dev, vif, key);
+		if (cmd == SET_KEY) {
+			*wcid_keyidx = idx;
+		} else {
+			if (idx == *wcid_keyidx)
+				*wcid_keyidx = -1;
+			continue;
+		}
 
-	return mt7996_mcu_add_key(&dev->mt76, vif, key,
-				  MCU_WMWA_UNI_CMD(STA_REC_UPDATE), wcid, cmd);
+		mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
+
+		if (key->keyidx == 6 || key->keyidx == 7) {
+			err = mt7996_mcu_bcn_prot_enable(dev, link,
+							 msta_link, key);
+			if (err)
+				return err;
+		}
+
+		err = mt7996_mcu_add_key(&dev->mt76, vif, key,
+					 MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
+					 &msta_link->wcid, cmd);
+		if (err)
+			return err;
+	}
+
+	return 0;
 }
 
 static void
@@ -221,12 +260,10 @@ mt7996_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		struct ieee80211_sta *sta, struct ieee80211_key_conf *key,
 		void *data)
 {
-	struct mt7996_vif_link *mlink = data;
-
 	if (sta)
 		return;
 
-	WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, mlink, key));
+	WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, key));
 }
 
 int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
@@ -298,7 +335,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 				   CONN_STATE_PORT_SECURE, true);
 	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
 
-	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, link);
+	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL);
 
 	return 0;
 }
@@ -486,7 +523,6 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_vif_link *mlink = &mvif->deflink;
 	int err;
 
 	/* The hardware does not support per-STA RX GTK, fallback
@@ -521,11 +557,11 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		return -EOPNOTSUPP;
 	}
 
-	if (!mt7996_vif_link_phy(mlink))
-	    return 0; /* defer until after link add */
+	if (!mt7996_vif_link_phy(&mvif->deflink))
+		return 0; /* defer until after link add */
 
 	mutex_lock(&dev->mt76.mutex);
-	err = mt7996_set_hw_key(hw, cmd, vif, sta, mlink, key);
+	err = mt7996_set_hw_key(hw, cmd, vif, sta, key);
 	mutex_unlock(&dev->mt76.mutex);
 
 	return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index d1a0dd4698fbe5cf248796ed6f13b99f3c191af1..b9f689436bfd3859e01ff7025a1f77cec8348824 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2430,18 +2430,17 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
 	return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
 }
 
-static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     u8 *pn)
+static int mt7996_mcu_get_pn(struct mt7996_dev *dev,
+			     struct mt7996_vif_link *link,
+			     struct mt7996_sta_link *msta_link, u8 *pn)
 {
 #define TSC_TYPE_BIGTK_PN 2
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
 	struct sta_rec_pn_info *pn_info;
 	struct sk_buff *skb, *rskb;
 	struct tlv *tlv;
 	int ret;
 
-	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					    &msta_link->wcid);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
@@ -2466,10 +2465,11 @@ static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	return 0;
 }
 
-int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
 			       struct ieee80211_key_conf *key)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
 	struct sk_buff *skb;
 	struct tlv *tlv;
@@ -2478,7 +2478,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		  sizeof(struct mt7996_mcu_bcn_prot_tlv);
 	int ret;
 
-	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->deflink.mt76, len);
+	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, len);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
@@ -2486,7 +2486,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
 
-	ret = mt7996_mcu_get_pn(dev, vif, pn);
+	ret = mt7996_mcu_get_pn(dev, link, msta_link, pn);
 	if (ret) {
 		dev_kfree_skb(skb);
 		return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 4d5ab3f4b78ee6fc584370372fe34b44292e4594..1e79757b7a5197426438532a2f0c39e54d6ebae5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -746,7 +746,9 @@ bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
 int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
 		       struct ieee80211_key_conf *key, int mcu_cmd,
 		       struct mt76_wcid *wcid, enum set_key_cmd cmd);
-int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
 			       struct ieee80211_key_conf *key);
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:54 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:54 +0100
Subject: [PATCH 10/21] wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read
 to support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-10-015b3d6fd928@kernel.org>

Extend mt7996_sta_hw_queue_read to support multi-link setup.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    | 54 +++++++++++++++-------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index d453c2fc97e4fad10a29093b70e2ede8375ee0d8..4a28db17a2874078489e08ac8a038a51834b33a0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -616,29 +616,51 @@ static void
 mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_vif *mvif = msta->vif;
+	struct mt7996_dev *dev = mvif->deflink.phy->dev;
+	struct ieee80211_link_sta *link_sta;
 	struct seq_file *s = data;
-	u8 ac;
+	struct ieee80211_vif *vif;
+	unsigned int link_id;
 
-	for (ac = 0; ac < 4; ac++) {
-		u32 qlen, ctrl, val;
-		u32 idx = msta_link->wcid.idx >> 5;
-		u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
+	vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
+
+	rcu_read_lock();
 
-		ctrl = BIT(31) | BIT(11) | (ac << 24);
-		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt76_vif_link *mlink;
+		u8 ac;
 
-		if (val & BIT(offs))
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (!mlink)
 			continue;
 
-		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
-		qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
-				      GENMASK(11, 0));
-		seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
-			   sta->addr, msta_link->wcid.idx,
-			   msta->vif->deflink.mt76.wmm_idx, ac, qlen);
+		msta_link = rcu_dereference(msta->link[link_id]);
+		if (!msta_link)
+			continue;
+
+		for (ac = 0; ac < 4; ac++) {
+			u32 idx = msta_link->wcid.idx >> 5, qlen, ctrl, val;
+			u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
+
+			ctrl = BIT(31) | BIT(11) | (ac << 24);
+			val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
+
+			if (val & BIT(offs))
+				continue;
+
+			mt76_wr(dev,
+				MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
+			qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
+					      GENMASK(11, 0));
+			seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
+				   sta->addr, msta_link->wcid.idx,
+				   mlink->wmm_idx, ac, qlen);
+		}
 	}
+
+	rcu_read_unlock();
 }
 
 static int

-- 
2.48.1



From smostafa at google.com  Wed Mar 12 04:43:07 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 11:43:07 +0000
Subject: [PATCH v3 03/23] iommu/pages: Remove
 __iommu_alloc_pages()/__iommu_free_pages()
In-Reply-To: <3-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <3-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9FzS-AzZNzYhrou@google.com>

On Tue, Feb 25, 2025 at 03:39:20PM -0400, Jason Gunthorpe wrote:
> These were only used by tegra-smmu and leaked the struct page out of the
> API. Delete them since tega-smmu has been converted to the other APIs.
> 
> In the process flatten the call tree so we have fewer one line functions
> calling other one line functions.. iommu_alloc_pages_node() is the real
> allocator and everything else can just call it directly.
> 
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>

> ---
>  drivers/iommu/iommu-pages.h | 49 ++++++-------------------------------
>  1 file changed, 7 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/iommu/iommu-pages.h b/drivers/iommu/iommu-pages.h
> index 82ebf00330811c..0ca2437989a0e1 100644
> --- a/drivers/iommu/iommu-pages.h
> +++ b/drivers/iommu/iommu-pages.h
> @@ -46,40 +46,6 @@ static inline void __iommu_free_account(struct page *page, int order)
>  	mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, -pgcnt);
>  }
>  
> -/**
> - * __iommu_alloc_pages - allocate a zeroed page of a given order.
> - * @gfp: buddy allocator flags
> - * @order: page order
> - *
> - * returns the head struct page of the allocated page.
> - */
> -static inline struct page *__iommu_alloc_pages(gfp_t gfp, int order)
> -{
> -	struct page *page;
> -
> -	page = alloc_pages(gfp | __GFP_ZERO, order);
> -	if (unlikely(!page))
> -		return NULL;
> -
> -	__iommu_alloc_account(page, order);
> -
> -	return page;
> -}
> -
> -/**
> - * __iommu_free_pages - free page of a given order
> - * @page: head struct page of the page
> - * @order: page order
> - */
> -static inline void __iommu_free_pages(struct page *page, int order)
> -{
> -	if (!page)
> -		return;
> -
> -	__iommu_free_account(page, order);
> -	__free_pages(page, order);
> -}
> -
>  /**
>   * iommu_alloc_pages_node - allocate a zeroed page of a given order from
>   * specific NUMA node.
> @@ -110,12 +76,7 @@ static inline void *iommu_alloc_pages_node(int nid, gfp_t gfp, int order)
>   */
>  static inline void *iommu_alloc_pages(gfp_t gfp, int order)
>  {
> -	struct page *page = __iommu_alloc_pages(gfp, order);
> -
> -	if (unlikely(!page))
> -		return NULL;
> -
> -	return page_address(page);
> +	return iommu_alloc_pages_node(numa_node_id(), gfp, order);
>  }
>  
>  /**
> @@ -138,7 +99,7 @@ static inline void *iommu_alloc_page_node(int nid, gfp_t gfp)
>   */
>  static inline void *iommu_alloc_page(gfp_t gfp)
>  {
> -	return iommu_alloc_pages(gfp, 0);
> +	return iommu_alloc_pages_node(numa_node_id(), gfp, 0);
>  }
>  
>  /**
> @@ -148,10 +109,14 @@ static inline void *iommu_alloc_page(gfp_t gfp)
>   */
>  static inline void iommu_free_pages(void *virt, int order)
>  {
> +	struct page *page;
> +
>  	if (!virt)
>  		return;
>  
> -	__iommu_free_pages(virt_to_page(virt), order);
> +	page = virt_to_page(virt);
> +	__iommu_free_account(page, order);
> +	__free_pages(page, order);
>  }
>  
>  /**
> -- 
> 2.43.0
> 


From smostafa at google.com  Wed Mar 12 04:43:39 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 11:43:39 +0000
Subject: [PATCH v3 05/23] iommu/pages: Remove the order argument to
 iommu_free_pages()
In-Reply-To: <5-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <5-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9FzazECgXgE8TNX@google.com>

On Tue, Feb 25, 2025 at 03:39:22PM -0400, Jason Gunthorpe wrote:
> Now that we have a folio under the allocation iommu_free_pages() can know
> the order of the original allocation and do the correct thing to free it.
> 
> The next patch will rename iommu_free_page() to iommu_free_pages() so we
> have naming consistency with iommu_alloc_pages_node().
> 
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>

> ---
>  drivers/iommu/amd/init.c            | 28 +++++++++++-----------------
>  drivers/iommu/amd/ppr.c             |  2 +-
>  drivers/iommu/exynos-iommu.c        |  8 ++++----
>  drivers/iommu/intel/irq_remapping.c |  4 ++--
>  drivers/iommu/intel/pasid.c         |  3 +--
>  drivers/iommu/intel/pasid.h         |  1 -
>  drivers/iommu/intel/prq.c           |  4 ++--
>  drivers/iommu/io-pgtable-arm.c      |  4 ++--
>  drivers/iommu/io-pgtable-dart.c     | 10 ++++------
>  drivers/iommu/iommu-pages.h         |  9 +++++----
>  drivers/iommu/riscv/iommu.c         |  6 ++----
>  drivers/iommu/sun50i-iommu.c        |  2 +-
>  12 files changed, 35 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
> index c5cd92edada061..f47ff0e0c75f4e 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -653,8 +653,7 @@ static inline int __init alloc_dev_table(struct amd_iommu_pci_seg *pci_seg)
>  
>  static inline void free_dev_table(struct amd_iommu_pci_seg *pci_seg)
>  {
> -	iommu_free_pages(pci_seg->dev_table,
> -			 get_order(pci_seg->dev_table_size));
> +	iommu_free_pages(pci_seg->dev_table);
>  	pci_seg->dev_table = NULL;
>  }
>  
> @@ -671,8 +670,7 @@ static inline int __init alloc_rlookup_table(struct amd_iommu_pci_seg *pci_seg)
>  
>  static inline void free_rlookup_table(struct amd_iommu_pci_seg *pci_seg)
>  {
> -	iommu_free_pages(pci_seg->rlookup_table,
> -			 get_order(pci_seg->rlookup_table_size));
> +	iommu_free_pages(pci_seg->rlookup_table);
>  	pci_seg->rlookup_table = NULL;
>  }
>  
> @@ -691,8 +689,7 @@ static inline int __init alloc_irq_lookup_table(struct amd_iommu_pci_seg *pci_se
>  static inline void free_irq_lookup_table(struct amd_iommu_pci_seg *pci_seg)
>  {
>  	kmemleak_free(pci_seg->irq_lookup_table);
> -	iommu_free_pages(pci_seg->irq_lookup_table,
> -			 get_order(pci_seg->rlookup_table_size));
> +	iommu_free_pages(pci_seg->irq_lookup_table);
>  	pci_seg->irq_lookup_table = NULL;
>  }
>  
> @@ -716,8 +713,7 @@ static int __init alloc_alias_table(struct amd_iommu_pci_seg *pci_seg)
>  
>  static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg)
>  {
> -	iommu_free_pages(pci_seg->alias_table,
> -			 get_order(pci_seg->alias_table_size));
> +	iommu_free_pages(pci_seg->alias_table);
>  	pci_seg->alias_table = NULL;
>  }
>  
> @@ -826,7 +822,7 @@ static void iommu_disable_command_buffer(struct amd_iommu *iommu)
>  
>  static void __init free_command_buffer(struct amd_iommu *iommu)
>  {
> -	iommu_free_pages(iommu->cmd_buf, get_order(CMD_BUFFER_SIZE));
> +	iommu_free_pages(iommu->cmd_buf);
>  }
>  
>  void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, gfp_t gfp,
> @@ -838,7 +834,7 @@ void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, gfp_t gfp,
>  	if (buf &&
>  	    check_feature(FEATURE_SNP) &&
>  	    set_memory_4k((unsigned long)buf, (1 << order))) {
> -		iommu_free_pages(buf, order);
> +		iommu_free_pages(buf);
>  		buf = NULL;
>  	}
>  
> @@ -882,14 +878,14 @@ static void iommu_disable_event_buffer(struct amd_iommu *iommu)
>  
>  static void __init free_event_buffer(struct amd_iommu *iommu)
>  {
> -	iommu_free_pages(iommu->evt_buf, get_order(EVT_BUFFER_SIZE));
> +	iommu_free_pages(iommu->evt_buf);
>  }
>  
>  static void free_ga_log(struct amd_iommu *iommu)
>  {
>  #ifdef CONFIG_IRQ_REMAP
> -	iommu_free_pages(iommu->ga_log, get_order(GA_LOG_SIZE));
> -	iommu_free_pages(iommu->ga_log_tail, get_order(8));
> +	iommu_free_pages(iommu->ga_log);
> +	iommu_free_pages(iommu->ga_log_tail);
>  #endif
>  }
>  
> @@ -2781,8 +2777,7 @@ static void early_enable_iommus(void)
>  
>  		for_each_pci_segment(pci_seg) {
>  			if (pci_seg->old_dev_tbl_cpy != NULL) {
> -				iommu_free_pages(pci_seg->old_dev_tbl_cpy,
> -						 get_order(pci_seg->dev_table_size));
> +				iommu_free_pages(pci_seg->old_dev_tbl_cpy);
>  				pci_seg->old_dev_tbl_cpy = NULL;
>  			}
>  		}
> @@ -2795,8 +2790,7 @@ static void early_enable_iommus(void)
>  		pr_info("Copied DEV table from previous kernel.\n");
>  
>  		for_each_pci_segment(pci_seg) {
> -			iommu_free_pages(pci_seg->dev_table,
> -					 get_order(pci_seg->dev_table_size));
> +			iommu_free_pages(pci_seg->dev_table);
>  			pci_seg->dev_table = pci_seg->old_dev_tbl_cpy;
>  		}
>  
> diff --git a/drivers/iommu/amd/ppr.c b/drivers/iommu/amd/ppr.c
> index 7c67d69f0b8cad..e6767c057d01fa 100644
> --- a/drivers/iommu/amd/ppr.c
> +++ b/drivers/iommu/amd/ppr.c
> @@ -48,7 +48,7 @@ void amd_iommu_enable_ppr_log(struct amd_iommu *iommu)
>  
>  void __init amd_iommu_free_ppr_log(struct amd_iommu *iommu)
>  {
> -	iommu_free_pages(iommu->ppr_log, get_order(PPR_LOG_SIZE));
> +	iommu_free_pages(iommu->ppr_log);
>  }
>  
>  /*
> diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
> index c666ecab955d21..1019e08b43b71c 100644
> --- a/drivers/iommu/exynos-iommu.c
> +++ b/drivers/iommu/exynos-iommu.c
> @@ -932,9 +932,9 @@ static struct iommu_domain *exynos_iommu_domain_alloc_paging(struct device *dev)
>  	return &domain->domain;
>  
>  err_lv2ent:
> -	iommu_free_pages(domain->lv2entcnt, 1);
> +	iommu_free_pages(domain->lv2entcnt);
>  err_counter:
> -	iommu_free_pages(domain->pgtable, 2);
> +	iommu_free_pages(domain->pgtable);
>  err_pgtable:
>  	kfree(domain);
>  	return NULL;
> @@ -975,8 +975,8 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
>  					phys_to_virt(base));
>  		}
>  
> -	iommu_free_pages(domain->pgtable, 2);
> -	iommu_free_pages(domain->lv2entcnt, 1);
> +	iommu_free_pages(domain->pgtable);
> +	iommu_free_pages(domain->lv2entcnt);
>  	kfree(domain);
>  }
>  
> diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
> index ad795c772f21b5..d6b796f8f100cd 100644
> --- a/drivers/iommu/intel/irq_remapping.c
> +++ b/drivers/iommu/intel/irq_remapping.c
> @@ -620,7 +620,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
>  out_free_bitmap:
>  	bitmap_free(bitmap);
>  out_free_pages:
> -	iommu_free_pages(ir_table_base, INTR_REMAP_PAGE_ORDER);
> +	iommu_free_pages(ir_table_base);
>  out_free_table:
>  	kfree(ir_table);
>  
> @@ -641,7 +641,7 @@ static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
>  			irq_domain_free_fwnode(fn);
>  			iommu->ir_domain = NULL;
>  		}
> -		iommu_free_pages(iommu->ir_table->base, INTR_REMAP_PAGE_ORDER);
> +		iommu_free_pages(iommu->ir_table->base);
>  		bitmap_free(iommu->ir_table->bitmap);
>  		kfree(iommu->ir_table);
>  		iommu->ir_table = NULL;
> diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
> index fb59a7d35958f5..00da94b1c4c907 100644
> --- a/drivers/iommu/intel/pasid.c
> +++ b/drivers/iommu/intel/pasid.c
> @@ -67,7 +67,6 @@ int intel_pasid_alloc_table(struct device *dev)
>  	}
>  
>  	pasid_table->table = dir;
> -	pasid_table->order = order;
>  	pasid_table->max_pasid = 1 << (order + PAGE_SHIFT + 3);
>  	info->pasid_table = pasid_table;
>  
> @@ -100,7 +99,7 @@ void intel_pasid_free_table(struct device *dev)
>  		iommu_free_page(table);
>  	}
>  
> -	iommu_free_pages(pasid_table->table, pasid_table->order);
> +	iommu_free_pages(pasid_table->table);
>  	kfree(pasid_table);
>  }
>  
> diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
> index 668d8ece6b143c..fd0fd1a0df84cc 100644
> --- a/drivers/iommu/intel/pasid.h
> +++ b/drivers/iommu/intel/pasid.h
> @@ -47,7 +47,6 @@ struct pasid_entry {
>  /* The representative of a PASID table */
>  struct pasid_table {
>  	void			*table;		/* pasid table pointer */
> -	int			order;		/* page order of pasid table */
>  	u32			max_pasid;	/* max pasid */
>  };
>  
> diff --git a/drivers/iommu/intel/prq.c b/drivers/iommu/intel/prq.c
> index c2d792db52c3e2..01ecafed31453c 100644
> --- a/drivers/iommu/intel/prq.c
> +++ b/drivers/iommu/intel/prq.c
> @@ -338,7 +338,7 @@ int intel_iommu_enable_prq(struct intel_iommu *iommu)
>  	dmar_free_hwirq(irq);
>  	iommu->pr_irq = 0;
>  free_prq:
> -	iommu_free_pages(iommu->prq, PRQ_ORDER);
> +	iommu_free_pages(iommu->prq);
>  	iommu->prq = NULL;
>  
>  	return ret;
> @@ -361,7 +361,7 @@ int intel_iommu_finish_prq(struct intel_iommu *iommu)
>  		iommu->iopf_queue = NULL;
>  	}
>  
> -	iommu_free_pages(iommu->prq, PRQ_ORDER);
> +	iommu_free_pages(iommu->prq);
>  	iommu->prq = NULL;
>  
>  	return 0;
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 7632c80edea63a..62df2528d020b2 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -300,7 +300,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
>  	if (cfg->free)
>  		cfg->free(cookie, pages, size);
>  	else
> -		iommu_free_pages(pages, order);
> +		iommu_free_pages(pages);
>  
>  	return NULL;
>  }
> @@ -316,7 +316,7 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
>  	if (cfg->free)
>  		cfg->free(cookie, pages, size);
>  	else
> -		iommu_free_pages(pages, get_order(size));
> +		iommu_free_pages(pages);
>  }
>  
>  static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep, int num_entries,
> diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
> index c004640640ee50..7efcaea0bd5c86 100644
> --- a/drivers/iommu/io-pgtable-dart.c
> +++ b/drivers/iommu/io-pgtable-dart.c
> @@ -262,7 +262,7 @@ static int dart_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
>  
>  		pte = dart_install_table(cptep, ptep, 0, data);
>  		if (pte)
> -			iommu_free_pages(cptep, get_order(tblsz));
> +			iommu_free_pages(cptep);
>  
>  		/* L2 table is present (now) */
>  		pte = READ_ONCE(*ptep);
> @@ -423,8 +423,7 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
>  
>  out_free_data:
>  	while (--i >= 0) {
> -		iommu_free_pages(data->pgd[i],
> -				 get_order(DART_GRANULE(data)));
> +		iommu_free_pages(data->pgd[i]);
>  	}
>  	kfree(data);
>  	return NULL;
> @@ -433,7 +432,6 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
>  static void apple_dart_free_pgtable(struct io_pgtable *iop)
>  {
>  	struct dart_io_pgtable *data = io_pgtable_to_data(iop);
> -	int order = get_order(DART_GRANULE(data));
>  	dart_iopte *ptep, *end;
>  	int i;
>  
> @@ -445,9 +443,9 @@ static void apple_dart_free_pgtable(struct io_pgtable *iop)
>  			dart_iopte pte = *ptep++;
>  
>  			if (pte)
> -				iommu_free_pages(iopte_deref(pte, data), order);
> +				iommu_free_pages(iopte_deref(pte, data));
>  		}
> -		iommu_free_pages(data->pgd[i], order);
> +		iommu_free_pages(data->pgd[i]);
>  	}
>  
>  	kfree(data);
> diff --git a/drivers/iommu/iommu-pages.h b/drivers/iommu/iommu-pages.h
> index 26b91940bdc146..88587da1782b94 100644
> --- a/drivers/iommu/iommu-pages.h
> +++ b/drivers/iommu/iommu-pages.h
> @@ -105,11 +105,12 @@ static inline void *iommu_alloc_page(gfp_t gfp)
>  }
>  
>  /**
> - * iommu_free_pages - free page of a given order
> + * iommu_free_pages - free pages
>   * @virt: virtual address of the page to be freed.
> - * @order: page order
> + *
> + * The page must have have been allocated by iommu_alloc_pages_node()
>   */
> -static inline void iommu_free_pages(void *virt, int order)
> +static inline void iommu_free_pages(void *virt)
>  {
>  	struct page *page;
>  
> @@ -127,7 +128,7 @@ static inline void iommu_free_pages(void *virt, int order)
>   */
>  static inline void iommu_free_page(void *virt)
>  {
> -	iommu_free_pages(virt, 0);
> +	iommu_free_pages(virt);
>  }
>  
>  /**
> diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
> index 8f049d4a0e2cb8..1868468d018a28 100644
> --- a/drivers/iommu/riscv/iommu.c
> +++ b/drivers/iommu/riscv/iommu.c
> @@ -48,14 +48,13 @@ static DEFINE_IDA(riscv_iommu_pscids);
>  /* Device resource-managed allocations */
>  struct riscv_iommu_devres {
>  	void *addr;
> -	int order;
>  };
>  
>  static void riscv_iommu_devres_pages_release(struct device *dev, void *res)
>  {
>  	struct riscv_iommu_devres *devres = res;
>  
> -	iommu_free_pages(devres->addr, devres->order);
> +	iommu_free_pages(devres->addr);
>  }
>  
>  static int riscv_iommu_devres_pages_match(struct device *dev, void *res, void *p)
> @@ -80,12 +79,11 @@ static void *riscv_iommu_get_pages(struct riscv_iommu_device *iommu, int order)
>  			      sizeof(struct riscv_iommu_devres), GFP_KERNEL);
>  
>  	if (unlikely(!devres)) {
> -		iommu_free_pages(addr, order);
> +		iommu_free_pages(addr);
>  		return NULL;
>  	}
>  
>  	devres->addr = addr;
> -	devres->order = order;
>  
>  	devres_add(iommu->dev, devres);
>  
> diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
> index 8d8f11854676c0..6385560dbc3fb0 100644
> --- a/drivers/iommu/sun50i-iommu.c
> +++ b/drivers/iommu/sun50i-iommu.c
> @@ -713,7 +713,7 @@ static void sun50i_iommu_domain_free(struct iommu_domain *domain)
>  {
>  	struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
>  
> -	iommu_free_pages(sun50i_domain->dt, get_order(DT_SIZE));
> +	iommu_free_pages(sun50i_domain->dt);
>  	sun50i_domain->dt = NULL;
>  
>  	kfree(sun50i_domain);
> -- 
> 2.43.0
> 


From smostafa at google.com  Wed Mar 12 04:44:20 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 11:44:20 +0000
Subject: [PATCH v3 06/23] iommu/pages: Remove iommu_free_page()
In-Reply-To: <6-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <6-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9FzlCfkRzDnvHuJ@google.com>

On Tue, Feb 25, 2025 at 03:39:23PM -0400, Jason Gunthorpe wrote:
> Use iommu_free_pages() instead.
> 
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>

> ---
>  drivers/iommu/amd/init.c          |  2 +-
>  drivers/iommu/amd/io_pgtable.c    |  4 ++--
>  drivers/iommu/amd/io_pgtable_v2.c |  8 ++++----
>  drivers/iommu/amd/iommu.c         |  4 ++--
>  drivers/iommu/intel/dmar.c        |  4 ++--
>  drivers/iommu/intel/iommu.c       | 12 ++++++------
>  drivers/iommu/intel/pasid.c       |  4 ++--
>  drivers/iommu/iommu-pages.h       |  9 ---------
>  drivers/iommu/riscv/iommu.c       |  6 +++---
>  drivers/iommu/rockchip-iommu.c    |  8 ++++----
>  drivers/iommu/tegra-smmu.c        | 12 ++++++------
>  11 files changed, 32 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
> index f47ff0e0c75f4e..73ebcb958ad864 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -955,7 +955,7 @@ static int __init alloc_cwwb_sem(struct amd_iommu *iommu)
>  static void __init free_cwwb_sem(struct amd_iommu *iommu)
>  {
>  	if (iommu->cmd_sem)
> -		iommu_free_page((void *)iommu->cmd_sem);
> +		iommu_free_pages((void *)iommu->cmd_sem);
>  }
>  
>  static void iommu_enable_xt(struct amd_iommu *iommu)
> diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
> index f3399087859fd1..025d8a3fe9cb78 100644
> --- a/drivers/iommu/amd/io_pgtable.c
> +++ b/drivers/iommu/amd/io_pgtable.c
> @@ -153,7 +153,7 @@ static bool increase_address_space(struct amd_io_pgtable *pgtable,
>  
>  out:
>  	spin_unlock_irqrestore(&domain->lock, flags);
> -	iommu_free_page(pte);
> +	iommu_free_pages(pte);
>  
>  	return ret;
>  }
> @@ -229,7 +229,7 @@ static u64 *alloc_pte(struct amd_io_pgtable *pgtable,
>  
>  			/* pte could have been changed somewhere. */
>  			if (!try_cmpxchg64(pte, &__pte, __npte))
> -				iommu_free_page(page);
> +				iommu_free_pages(page);
>  			else if (IOMMU_PTE_PRESENT(__pte))
>  				*updated = true;
>  
> diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
> index c616de2c5926ec..cce3fc9861ef77 100644
> --- a/drivers/iommu/amd/io_pgtable_v2.c
> +++ b/drivers/iommu/amd/io_pgtable_v2.c
> @@ -121,10 +121,10 @@ static void free_pgtable(u64 *pt, int level)
>  		if (level > 2)
>  			free_pgtable(p, level - 1);
>  		else
> -			iommu_free_page(p);
> +			iommu_free_pages(p);
>  	}
>  
> -	iommu_free_page(pt);
> +	iommu_free_pages(pt);
>  }
>  
>  /* Allocate page table */
> @@ -159,7 +159,7 @@ static u64 *v2_alloc_pte(int nid, u64 *pgd, unsigned long iova,
>  			__npte = set_pgtable_attr(page);
>  			/* pte could have been changed somewhere. */
>  			if (!try_cmpxchg64(pte, &__pte, __npte))
> -				iommu_free_page(page);
> +				iommu_free_pages(page);
>  			else if (IOMMU_PTE_PRESENT(__pte))
>  				*updated = true;
>  
> @@ -181,7 +181,7 @@ static u64 *v2_alloc_pte(int nid, u64 *pgd, unsigned long iova,
>  		if (pg_size == IOMMU_PAGE_SIZE_1G)
>  			free_pgtable(__pte, end_level - 1);
>  		else if (pg_size == IOMMU_PAGE_SIZE_2M)
> -			iommu_free_page(__pte);
> +			iommu_free_pages(__pte);
>  	}
>  
>  	return pte;
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index b48a72bd7b23df..e23d104d177ad9 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -1812,7 +1812,7 @@ static void free_gcr3_tbl_level1(u64 *tbl)
>  
>  		ptr = iommu_phys_to_virt(tbl[i] & PAGE_MASK);
>  
> -		iommu_free_page(ptr);
> +		iommu_free_pages(ptr);
>  	}
>  }
>  
> @@ -1845,7 +1845,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
>  	/* Free per device domain ID */
>  	pdom_id_free(gcr3_info->domid);
>  
> -	iommu_free_page(gcr3_info->gcr3_tbl);
> +	iommu_free_pages(gcr3_info->gcr3_tbl);
>  	gcr3_info->gcr3_tbl = NULL;
>  }
>  
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index 9f424acf474e94..c812c83d77da10 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -1187,7 +1187,7 @@ static void free_iommu(struct intel_iommu *iommu)
>  	}
>  
>  	if (iommu->qi) {
> -		iommu_free_page(iommu->qi->desc);
> +		iommu_free_pages(iommu->qi->desc);
>  		kfree(iommu->qi->desc_status);
>  		kfree(iommu->qi);
>  	}
> @@ -1714,7 +1714,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)
>  
>  	qi->desc_status = kcalloc(QI_LENGTH, sizeof(int), GFP_ATOMIC);
>  	if (!qi->desc_status) {
> -		iommu_free_page(qi->desc);
> +		iommu_free_pages(qi->desc);
>  		kfree(qi);
>  		iommu->qi = NULL;
>  		return -ENOMEM;
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index cc46098f875b16..1e73bfa00329ae 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -571,17 +571,17 @@ static void free_context_table(struct intel_iommu *iommu)
>  	for (i = 0; i < ROOT_ENTRY_NR; i++) {
>  		context = iommu_context_addr(iommu, i, 0, 0);
>  		if (context)
> -			iommu_free_page(context);
> +			iommu_free_pages(context);
>  
>  		if (!sm_supported(iommu))
>  			continue;
>  
>  		context = iommu_context_addr(iommu, i, 0x80, 0);
>  		if (context)
> -			iommu_free_page(context);
> +			iommu_free_pages(context);
>  	}
>  
> -	iommu_free_page(iommu->root_entry);
> +	iommu_free_pages(iommu->root_entry);
>  	iommu->root_entry = NULL;
>  }
>  
> @@ -744,7 +744,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
>  			tmp = 0ULL;
>  			if (!try_cmpxchg64(&pte->val, &tmp, pteval))
>  				/* Someone else set it while we were thinking; use theirs. */
> -				iommu_free_page(tmp_page);
> +				iommu_free_pages(tmp_page);
>  			else
>  				domain_flush_cache(domain, pte, sizeof(*pte));
>  		}
> @@ -857,7 +857,7 @@ static void dma_pte_free_level(struct dmar_domain *domain, int level,
>  		      last_pfn < level_pfn + level_size(level) - 1)) {
>  			dma_clear_pte(pte);
>  			domain_flush_cache(domain, pte, sizeof(*pte));
> -			iommu_free_page(level_pte);
> +			iommu_free_pages(level_pte);
>  		}
>  next:
>  		pfn += level_size(level);
> @@ -881,7 +881,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
>  
>  	/* free pgd */
>  	if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
> -		iommu_free_page(domain->pgd);
> +		iommu_free_pages(domain->pgd);
>  		domain->pgd = NULL;
>  	}
>  }
> diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
> index 00da94b1c4c907..4249f12db7fc43 100644
> --- a/drivers/iommu/intel/pasid.c
> +++ b/drivers/iommu/intel/pasid.c
> @@ -96,7 +96,7 @@ void intel_pasid_free_table(struct device *dev)
>  	max_pde = pasid_table->max_pasid >> PASID_PDE_SHIFT;
>  	for (i = 0; i < max_pde; i++) {
>  		table = get_pasid_table_from_pde(&dir[i]);
> -		iommu_free_page(table);
> +		iommu_free_pages(table);
>  	}
>  
>  	iommu_free_pages(pasid_table->table);
> @@ -160,7 +160,7 @@ static struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid)
>  		tmp = 0ULL;
>  		if (!try_cmpxchg64(&dir[dir_index].val, &tmp,
>  				   (u64)virt_to_phys(entries) | PASID_PTE_PRESENT)) {
> -			iommu_free_page(entries);
> +			iommu_free_pages(entries);
>  			goto retry;
>  		}
>  		if (!ecap_coherent(info->iommu->ecap)) {
> diff --git a/drivers/iommu/iommu-pages.h b/drivers/iommu/iommu-pages.h
> index 88587da1782b94..fcd17b94f7b830 100644
> --- a/drivers/iommu/iommu-pages.h
> +++ b/drivers/iommu/iommu-pages.h
> @@ -122,15 +122,6 @@ static inline void iommu_free_pages(void *virt)
>  	put_page(page);
>  }
>  
> -/**
> - * iommu_free_page - free page
> - * @virt: virtual address of the page to be freed.
> - */
> -static inline void iommu_free_page(void *virt)
> -{
> -	iommu_free_pages(virt);
> -}
> -
>  /**
>   * iommu_put_pages_list - free a list of pages.
>   * @page: the head of the lru list to be freed.
> diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
> index 1868468d018a28..4fe07343d84e61 100644
> --- a/drivers/iommu/riscv/iommu.c
> +++ b/drivers/iommu/riscv/iommu.c
> @@ -1105,7 +1105,7 @@ static void riscv_iommu_pte_free(struct riscv_iommu_domain *domain,
>  	if (freelist)
>  		list_add_tail(&virt_to_page(ptr)->lru, freelist);
>  	else
> -		iommu_free_page(ptr);
> +		iommu_free_pages(ptr);
>  }
>  
>  static unsigned long *riscv_iommu_pte_alloc(struct riscv_iommu_domain *domain,
> @@ -1148,7 +1148,7 @@ static unsigned long *riscv_iommu_pte_alloc(struct riscv_iommu_domain *domain,
>  			old = pte;
>  			pte = _io_pte_entry(virt_to_pfn(addr), _PAGE_TABLE);
>  			if (cmpxchg_relaxed(ptr, old, pte) != old) {
> -				iommu_free_page(addr);
> +				iommu_free_pages(addr);
>  				goto pte_retry;
>  			}
>  		}
> @@ -1393,7 +1393,7 @@ static struct iommu_domain *riscv_iommu_alloc_paging_domain(struct device *dev)
>  	domain->pscid = ida_alloc_range(&riscv_iommu_pscids, 1,
>  					RISCV_IOMMU_MAX_PSCID, GFP_KERNEL);
>  	if (domain->pscid < 0) {
> -		iommu_free_page(domain->pgd_root);
> +		iommu_free_pages(domain->pgd_root);
>  		kfree(domain);
>  		return ERR_PTR(-ENOMEM);
>  	}
> diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
> index 323cc665c35703..798e85bd994d56 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -737,7 +737,7 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
>  	pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
>  	if (dma_mapping_error(dma_dev, pt_dma)) {
>  		dev_err(dma_dev, "DMA mapping error while allocating page table\n");
> -		iommu_free_page(page_table);
> +		iommu_free_pages(page_table);
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
> @@ -1086,7 +1086,7 @@ static struct iommu_domain *rk_iommu_domain_alloc_paging(struct device *dev)
>  	return &rk_domain->domain;
>  
>  err_free_dt:
> -	iommu_free_page(rk_domain->dt);
> +	iommu_free_pages(rk_domain->dt);
>  err_free_domain:
>  	kfree(rk_domain);
>  
> @@ -1107,13 +1107,13 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
>  			u32 *page_table = phys_to_virt(pt_phys);
>  			dma_unmap_single(dma_dev, pt_phys,
>  					 SPAGE_SIZE, DMA_TO_DEVICE);
> -			iommu_free_page(page_table);
> +			iommu_free_pages(page_table);
>  		}
>  	}
>  
>  	dma_unmap_single(dma_dev, rk_domain->dt_dma,
>  			 SPAGE_SIZE, DMA_TO_DEVICE);
> -	iommu_free_page(rk_domain->dt);
> +	iommu_free_pages(rk_domain->dt);
>  
>  	kfree(rk_domain);
>  }
> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
> index c134647292fb22..844682a41afa66 100644
> --- a/drivers/iommu/tegra-smmu.c
> +++ b/drivers/iommu/tegra-smmu.c
> @@ -303,7 +303,7 @@ static struct iommu_domain *tegra_smmu_domain_alloc_paging(struct device *dev)
>  
>  	as->count = kcalloc(SMMU_NUM_PDE, sizeof(u32), GFP_KERNEL);
>  	if (!as->count) {
> -		iommu_free_page(as->pd);
> +		iommu_free_pages(as->pd);
>  		kfree(as);
>  		return NULL;
>  	}
> @@ -311,7 +311,7 @@ static struct iommu_domain *tegra_smmu_domain_alloc_paging(struct device *dev)
>  	as->pts = kcalloc(SMMU_NUM_PDE, sizeof(*as->pts), GFP_KERNEL);
>  	if (!as->pts) {
>  		kfree(as->count);
> -		iommu_free_page(as->pd);
> +		iommu_free_pages(as->pd);
>  		kfree(as);
>  		return NULL;
>  	}
> @@ -608,14 +608,14 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova,
>  		dma = dma_map_single(smmu->dev, pt, SMMU_SIZE_PT,
>  				     DMA_TO_DEVICE);
>  		if (dma_mapping_error(smmu->dev, dma)) {
> -			iommu_free_page(pt);
> +			iommu_free_pages(pt);
>  			return NULL;
>  		}
>  
>  		if (!smmu_dma_addr_valid(smmu, dma)) {
>  			dma_unmap_single(smmu->dev, dma, SMMU_SIZE_PT,
>  					 DMA_TO_DEVICE);
> -			iommu_free_page(pt);
> +			iommu_free_pages(pt);
>  			return NULL;
>  		}
>  
> @@ -656,7 +656,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova)
>  
>  		dma_unmap_single(smmu->dev, pte_dma, SMMU_SIZE_PT,
>  				 DMA_TO_DEVICE);
> -		iommu_free_page(pt);
> +		iommu_free_pages(pt);
>  		as->pts[pde] = NULL;
>  	}
>  }
> @@ -707,7 +707,7 @@ static struct tegra_pt *as_get_pde_page(struct tegra_smmu_as *as,
>  	 */
>  	if (as->pts[pde]) {
>  		if (pt)
> -			iommu_free_page(pt);
> +			iommu_free_pages(pt);
>  
>  		pt = as->pts[pde];
>  	}
> -- 
> 2.43.0
> 


From Markus.Elfring at web.de  Wed Mar 12 04:44:05 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Wed, 12 Mar 2025 12:44:05 +0100
Subject: [v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <81f87d39-d3f8-4b6a-91cb-b0177d34171b@prolan.hu>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
 <885ceb3e-d6c6-4e7b-a3b6-585d2d110ccf@web.de>
 <81f87d39-d3f8-4b6a-91cb-b0177d34171b@prolan.hu>
Message-ID: <9ef781b0-8a63-42b7-91a2-fa8a8ea3c0b4@web.de>

>> How good does such a change combination fit to the patch requirement
>> according to separation of concerns?
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc6#n81
>
> It is a general refactor patch, it shouldn't change any functionality. I could split it to one part introducing `devm_clk_get_enabled()` and the other `dmaenginem_async_device_register()`, but I don't feel that to be necessary, nor does it bring any advantages I believe.
Can it matter a bit more to separate changes for the application of devm functions
and the adjustment of corresponding exception handling with dev_err_probe() calls?

Regards,
Markus


From akihiko.odaki at daynix.com  Wed Mar 12 04:55:54 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:54 +0900
Subject: [PATCH v3 0/6] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Message-ID: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>

Prepare vPMC registers for user-initiated changes after first run. This
is important specifically for debugging Windows on QEMU with GDB; QEMU
tries to write back all visible registers when resuming the VM execution
with GDB, corrupting the PMU state. Windows always uses the PMU so this
can cause adverse effects on that particular OS.

This series also contains patch "KVM: arm64: PMU: Set raw values from
user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
changes made for the mentioned registers in the past. It is necessary
to migrate the PMU state properly on Firecracker, QEMU, and crosvm.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
Changes in v3:
- Added patch "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
- Added an explanation of this path series' motivation to each patch.
- Explained why userspace register writes and register reset should be
  covered in patch "KVM: arm64: PMU: Reload when user modifies
  registers".
- Marked patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" for stable.
- Reoreded so that patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" would come first.
- Added patch "KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking
  PMCNTENSET_EL0".
- Added patch "KVM: arm64: Reload PMCNTENSET_EL0".
- Link to v2: https://lore.kernel.org/r/20250307-pmc-v2-0-6c3375a5f1e4 at daynix.com

Changes in v2:
- Changed to utilize KVM_REQ_RELOAD_PMU as suggested by Oliver Upton.
- Added patch "KVM: arm64: PMU: Reload when user modifies registers"
  to cover more registers.
- Added patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}".
- Link to v1: https://lore.kernel.org/r/20250302-pmc-v1-1-caff989093dc at daynix.com

---
Akihiko Odaki (6):
      KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
      KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
      KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
      KVM: arm64: PMU: Reload when user modifies registers
      KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking PMCNTENSET_EL0
      KVM: arm64: Reload PMCNTENSET_EL0

 arch/arm64/kvm/arm.c      |  8 ++++---
 arch/arm64/kvm/guest.c    | 12 +++++++++++
 arch/arm64/kvm/pmu-emul.c | 54 ++++++++++++++++-------------------------------
 arch/arm64/kvm/sys_regs.c | 53 ++++++++++++++++++++++++++--------------------
 include/kvm/arm_pmu.h     |  1 +
 5 files changed, 66 insertions(+), 62 deletions(-)
---
base-commit: da2f480cb24d39d480b1e235eda0dd2d01f8765b
change-id: 20250302-pmc-b90a86af945c

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From akihiko.odaki at daynix.com  Wed Mar 12 04:55:55 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:55 +0900
Subject: [PATCH v3 1/6] KVM: arm64: PMU: Set raw values from user to
 PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-1-0411cab5dc3d@daynix.com>

Commit a45f41d754e0 ("KVM: arm64: Add {get,set}_user for
PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}") changed KVM_SET_ONE_REG to update
the mentioned registers in a way matching with the behavior of guest
register writes. This is a breaking change of a UAPI though the new
semantics looks cleaner and VMMs are not prepared for this.

Firecracker, QEMU, and crosvm perform migration by listing registers
with KVM_GET_REG_LIST, getting their values with KVM_GET_ONE_REG and
setting them with KVM_SET_ONE_REG. This algorithm assumes
KVM_SET_ONE_REG restores the values retrieved with KVM_GET_ONE_REG
without any alteration. However, bit operations added by the earlier
commit do not preserve the values retried with KVM_GET_ONE_REG and
potentially break migration.

Remove the bit operations that alter the values retrieved with
KVM_GET_ONE_REG.

Cc: stable at vger.kernel.org
Fixes: a45f41d754e0 ("KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
Acked-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/sys_regs.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 42791971f758..0a2ce931a946 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1126,26 +1126,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
-	bool set;
-
-	val &= kvm_pmu_valid_counter_mask(vcpu);
-
-	switch (r->reg) {
-	case PMOVSSET_EL0:
-		/* CRm[1] being set indicates a SET register, and CLR otherwise */
-		set = r->CRm & 2;
-		break;
-	default:
-		/* Op2[0] being set indicates a SET register, and CLR otherwise */
-		set = r->Op2 & 1;
-		break;
-	}
-
-	if (set)
-		__vcpu_sys_reg(vcpu, r->reg) |= val;
-	else
-		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
-
+	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
 	return 0;
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 04:55:56 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:56 +0900
Subject: [PATCH v3 2/6] KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-2-0411cab5dc3d@daynix.com>

Many functions in pmu-emul.c checks kvm_vcpu_has_pmu(vcpu). A favorable
interpretation is defensive programming, but it also has downsides:

- It is confusing as it implies these functions are called without PMU
  although most of them are called only when a PMU is present.

- It makes semantics of functions fuzzy. For example, calling
  kvm_pmu_disable_counter_mask() without PMU may result in no-op as
  there are no enabled counters, but it's unclear what
  kvm_pmu_get_counter_value() returns when there is no PMU.

- It allows callers without checking kvm_vcpu_has_pmu(vcpu), but it is
  often wrong to call these functions without PMU.

- It is error-prone to duplicate kvm_vcpu_has_pmu(vcpu) checks into
  multiple functions. Many functions are called for system registers,
  and the system register infrastructure already employs less
  error-prone, comprehensive checks.

Check kvm_vcpu_has_pmu(vcpu) in callers of these functions instead,
and remove the obsolete checks from pmu-emul.c.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/arm.c      |  8 +++++---
 arch/arm64/kvm/guest.c    | 12 ++++++++++++
 arch/arm64/kvm/pmu-emul.c | 34 ++--------------------------------
 arch/arm64/kvm/sys_regs.c |  6 ++++--
 4 files changed, 23 insertions(+), 37 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index f66ce098f03b..e375468a2217 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -834,9 +834,11 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
-	ret = kvm_arm_pmu_v3_enable(vcpu);
-	if (ret)
-		return ret;
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		ret = kvm_arm_pmu_v3_enable(vcpu);
+		if (ret)
+			return ret;
+	}
 
 	if (is_protected_kvm_enabled()) {
 		ret = pkvm_create_hyp_vm(kvm);
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 962f985977c2..fc09eec3fd94 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -951,6 +951,10 @@ int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
 
 	switch (attr->group) {
 	case KVM_ARM_VCPU_PMU_V3_CTRL:
+		if (!kvm_vcpu_has_pmu(vcpu)) {
+			ret = -ENODEV;
+			break;
+		}
 		mutex_lock(&vcpu->kvm->arch.config_lock);
 		ret = kvm_arm_pmu_v3_set_attr(vcpu, attr);
 		mutex_unlock(&vcpu->kvm->arch.config_lock);
@@ -976,6 +980,10 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
 
 	switch (attr->group) {
 	case KVM_ARM_VCPU_PMU_V3_CTRL:
+		if (!kvm_vcpu_has_pmu(vcpu)) {
+			ret = -ENODEV;
+			break;
+		}
 		ret = kvm_arm_pmu_v3_get_attr(vcpu, attr);
 		break;
 	case KVM_ARM_VCPU_TIMER_CTRL:
@@ -999,6 +1007,10 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
 
 	switch (attr->group) {
 	case KVM_ARM_VCPU_PMU_V3_CTRL:
+		if (!kvm_vcpu_has_pmu(vcpu)) {
+			ret = -ENXIO;
+			break;
+		}
 		ret = kvm_arm_pmu_v3_has_attr(vcpu, attr);
 		break;
 	case KVM_ARM_VCPU_TIMER_CTRL:
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index e3e82b66e226..3e5bf414447f 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -144,9 +144,6 @@ static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
  */
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	return kvm_pmu_get_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
 }
 
@@ -185,9 +182,6 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
  */
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
@@ -289,8 +283,6 @@ u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
 void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
 
 	if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) || !val)
 		return;
@@ -324,7 +316,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu) || !val)
+	if (!val)
 		return;
 
 	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) {
@@ -357,9 +349,6 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
 	bool overflow;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	overflow = !!kvm_pmu_overflow_status(vcpu);
 	if (pmu->irq_level == overflow)
 		return;
@@ -555,9 +544,6 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	/* Fixup PMCR_EL0 to reconcile the PMU version and the LP bit */
 	if (!kvm_has_feat(vcpu->kvm, ID_AA64DFR0_EL1, PMUVer, V3P5))
 		val &= ~ARMV8_PMU_PMCR_LP;
@@ -696,9 +682,6 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
 	struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, select_idx);
 	u64 reg;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	reg = counter_index_to_evtreg(pmc->idx);
 	__vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm);
 
@@ -804,9 +787,6 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
 	u64 val, mask = 0;
 	int base, i, nr_events;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!pmceid1) {
 		val = compute_pmceid0(cpu_pmu);
 		base = 0;
@@ -847,9 +827,6 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 
 int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!vcpu->arch.pmu.created)
 		return -EINVAL;
 
@@ -1022,9 +999,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 
 	lockdep_assert_held(&kvm->arch.config_lock);
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return -ENODEV;
-
 	if (vcpu->arch.pmu.created)
 		return -EBUSY;
 
@@ -1129,9 +1103,6 @@ int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (!irqchip_in_kernel(vcpu->kvm))
 			return -EINVAL;
 
-		if (!kvm_vcpu_has_pmu(vcpu))
-			return -ENODEV;
-
 		if (!kvm_arm_pmu_irq_initialized(vcpu))
 			return -ENXIO;
 
@@ -1150,8 +1121,7 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 	case KVM_ARM_VCPU_PMU_V3_INIT:
 	case KVM_ARM_VCPU_PMU_V3_FILTER:
 	case KVM_ARM_VCPU_PMU_V3_SET_PMU:
-		if (kvm_vcpu_has_pmu(vcpu))
-			return 0;
+		return 0;
 	}
 
 	return -ENXIO;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 0a2ce931a946..6e75557bea1d 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1784,12 +1784,14 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu,
 				      const struct sys_reg_desc *rd)
 {
-	u8 perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
+	u8 perfmon;
 	u64 val = read_sanitised_ftr_reg(SYS_ID_DFR0_EL1);
 
 	val &= ~ID_DFR0_EL1_PerfMon_MASK;
-	if (kvm_vcpu_has_pmu(vcpu))
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
 		val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon);
+	}
 
 	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, Debugv8p8);
 

-- 
2.48.1



From krzk at kernel.org  Wed Mar 12 04:56:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 12:56:13 +0100
Subject: [PATCH v4 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <CADrjBPqSSbt=xM7u12BU2nsF2xvyXe_+bLSCxCPBTfCc07VpuQ@mail.gmail.com>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org>
 <59a1a6eb-d719-49bd-a4b5-bfb9c2817f08@kernel.org>
 <CADrjBPqYoHckqr43y1z8UtthZ9DOG15TJWSv_707Jbyf1yforw@mail.gmail.com>
 <CADrjBPqSSbt=xM7u12BU2nsF2xvyXe_+bLSCxCPBTfCc07VpuQ@mail.gmail.com>
Message-ID: <328d89da-4246-4c75-a277-b06934e4a9d9@kernel.org>

On 12/03/2025 12:39, Peter Griffin wrote:
> Hi Krzysztof,
> 
> On Wed, 12 Mar 2025 at 11:31, Peter Griffin <peter.griffin at linaro.org> wrote:
>>
>> Hi Krzysztof,
>>
>> Thanks for the review feedback.
>>
>> On Tue, 11 Mar 2025 at 19:36, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>>>
>>> On 07/03/2025 11:29, Peter Griffin wrote:
>>>> gs101 differs to other SoCs in that fltcon1 register doesn't
>>>> always exist. Additionally the offset of fltcon0 is not fixed
>>>> and needs to use the newly added eint_fltcon_offset variable.
>>>>
>>>> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
>>>> Cc: stable at vger.kernel.org
>>>
>>> It looks this depends on previous commit, right?
>>
>> Yes that's right, it depends on the refactoring in the previous patch.
>> To fix the bug (which is an Serror on suspend for gs101), we need the
>> dedicated gs101 callback so it can have the knowledge that fltcon1
>> doesn't always exist and it's varying offset.
> 
> and also dependent on the first patch that adds the eint_fltcon_offset :)


That would be fine because it's a fix as well. Ah, well, let's keep the
dependency, but then I think syntax would be:

Cc: <stable at vger.kernel.org> # depends on the previous three patches


Best regards,
Krzysztof


From akihiko.odaki at daynix.com  Wed Mar 12 04:55:57 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:57 +0900
Subject: [PATCH v3 3/6] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-3-0411cab5dc3d@daynix.com>

Reload the perf event when setting the vPMU counter (vPMC) registers
(PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

It is also important to keep the correct state even if userspace writes
them after first run, specifically when debugging Windows on QEMU with
GDB; QEMU tries to write back all visible registers when resuming the VM
execution with GDB, corrupting the PMU state. Windows always uses the
PMU so this can cause adverse effects on that particular OS.

Fix this by releasing the current perf event and trigger recreating one
with KVM_REQ_RELOAD_PMU.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 13 +++++++++++++
 arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
 include/kvm/arm_pmu.h     |  1 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 3e5bf414447f..1cfe53b6353e 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -185,6 +185,19 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
+/**
+ * kvm_pmu_set_counter_value_user - set PMU counter value from user
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ * @val: The counter value
+ */
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+{
+	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+}
+
 /**
  * kvm_pmu_release_perf_event - remove the perf event
  * @pmc: The PMU counter pointer
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 6e75557bea1d..26182cae4ac7 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 	return 0;
 }
 
+static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+			  u64 val)
+{
+	u64 idx;
+
+	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+		/* PMCCNTR_EL0 */
+		idx = ARMV8_PMU_CYCLE_IDX;
+	else
+		/* PMEVCNTRn_EL0 */
+		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+	kvm_pmu_set_counter_value_user(vcpu, idx, val);
+	return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      const struct sys_reg_desc *r)
@@ -1309,6 +1325,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 #define PMU_PMEVCNTR_EL0(n)						\
 	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
 	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
+	  .set_user = set_pmu_evcntr,					\
 	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -2665,7 +2682,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  .access = access_pmceid, .reset = NULL },
 	{ PMU_SYS_REG(PMCCNTR_EL0),
 	  .access = access_pmu_evcntr, .reset = reset_unknown,
-	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
+	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
+	  .set_user = set_pmu_evcntr },
 	{ PMU_SYS_REG(PMXEVTYPER_EL0),
 	  .access = access_pmu_evtyper, .reset = NULL },
 	{ PMU_SYS_REG(PMXEVCNTR_EL0),
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 28b380ad8dfa..9c062756ebfa 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -41,6 +41,7 @@ bool kvm_supports_guest_pmuv3(void);
 #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:55 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:55 +0100
Subject: [PATCH 11/21] wifi: mt76: mt7996: remove
 mt7996_mac_enable_rtscts()
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-11-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

It is controlled by FW, also, driver should not directly write WTBL to
prevent WTBL overwritten issues.

Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 14 --------------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  3 ---
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  2 --
 3 files changed, 19 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index b8d88fdee97a3567b57a20d0322859b7ae8ce88a..c1c7638e29a1205629f4eb126e15163981109557 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -217,20 +217,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 	rcu_read_unlock();
 }
 
-void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
-			      struct ieee80211_vif *vif, bool enable)
-{
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
-	u32 addr;
-
-	addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 5);
-	if (enable)
-		mt76_set(dev, addr, BIT(5));
-	else
-		mt76_clear(dev, addr, BIT(5));
-}
-
 /* The HW does not translate the mac header to 802.3 for mesh point */
 static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index a845c3e758adcc4802f704a99ac39aa9ca670c88..8d7ad2dc2d7bccf6c8f5fe4862828b61145a0c85 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -785,9 +785,6 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				   !!(changed & BSS_CHANGED_BSSID));
 	}
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT)
-		mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
-
 	if (changed & BSS_CHANGED_ERP_SLOT) {
 		int slottime = info->use_short_slot ? 9 : 20;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 1e79757b7a5197426438532a2f0c39e54d6ebae5..8a347dd8e648a43250e7dd717cb65f77cb4a61dd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -707,8 +707,6 @@ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
 void mt7996_mac_reset_counters(struct mt7996_phy *phy);
 void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
 void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
-void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
-			      struct ieee80211_vif *vif, bool enable);
 void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 			   struct sk_buff *skb, struct mt76_wcid *wcid,
 			   struct ieee80211_key_conf *key, int pid,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:56 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:56 +0100
Subject: [PATCH 12/21] wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-12-015b3d6fd928@kernel.org>

Rework mt7996_mac_sta_rc_work routine in order to support multi-link
setup.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c  | 40 ++++++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 30 ++++++++++++------
 2 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c1c7638e29a1205629f4eb126e15163981109557..c56b1126abd59da5895d94fb368004adf6ffbbc8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2300,13 +2300,20 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
 void mt7996_mac_sta_rc_work(struct work_struct *work)
 {
 	struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
+	struct ieee80211_bss_conf *link_conf;
+	struct ieee80211_link_sta *link_sta;
 	struct mt7996_sta_link *msta_link;
+	struct mt7996_vif_link *link;
+	struct mt76_vif_link *mlink;
 	struct ieee80211_sta *sta;
 	struct ieee80211_vif *vif;
 	struct mt7996_sta *msta;
-	u32 changed;
+	struct mt7996_vif *mvif;
 	LIST_HEAD(list);
+	u32 changed;
+	u8 link_id;
 
+	rcu_read_lock();
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
 	list_splice_init(&dev->sta_rc_list, &list);
 
@@ -2319,21 +2326,35 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 		msta_link->changed = 0;
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
+		sta = wcid_to_sta(&msta_link->wcid);
+		link_id = msta_link->wcid.link_id;
 		msta = msta_link->sta;
-		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
-		vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
+		mvif = msta->vif;
+		vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
+
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (!mlink)
+			continue;
+
+		link_sta = rcu_dereference(sta->link[link_id]);
+		if (!link_sta)
+			continue;
+
+		link_conf = rcu_dereference(vif->link_conf[link_id]);
+		if (!link_conf)
+			continue;
+
+		link = (struct mt7996_vif_link *)mlink;
 
 		if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
 			       IEEE80211_RC_NSS_CHANGED |
 			       IEEE80211_RC_BW_CHANGED))
-			mt7996_mcu_add_rate_ctrl(dev, vif, &vif->bss_conf,
-						 &sta->deflink,
-						 &msta->vif->deflink,
-						 msta_link, true);
+			mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
+						 link_sta, link, msta_link,
+						 true);
 
 		if (changed & IEEE80211_RC_SMPS_CHANGED)
-			mt7996_mcu_set_fixed_field(dev, &sta->deflink,
-						   &msta->vif->deflink,
+			mt7996_mcu_set_fixed_field(dev, link_sta, link,
 						   msta_link, NULL,
 						   RATE_PARAM_MMPS_UPDATE);
 
@@ -2341,6 +2362,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 	}
 
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+	rcu_read_unlock();
 }
 
 void mt7996_mac_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 8d7ad2dc2d7bccf6c8f5fe4862828b61145a0c85..4d3098e47dbbc25ced2a4b40c6b92423c451899e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -304,6 +304,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	INIT_LIST_HEAD(&msta_link->rc_list);
 	msta_link->wcid.idx = idx;
+	msta_link->wcid.link_id = link_conf->link_id;
 	msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
 	mt76_wcid_init(&msta_link->wcid, band_idx);
 
@@ -1521,29 +1522,39 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
 	}
 }
 
-static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
+static void mt7996_link_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_sta_link *msta_link;
 	u32 *changed = data;
 
+	rcu_read_lock();
+
+	msta_link = rcu_dereference(msta->link[msta->deflink_id]);
+	if (!msta_link)
+		goto out;
+
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
+
 	msta_link->changed |= *changed;
 	if (list_empty(&msta_link->rc_list))
 		list_add_tail(&msta_link->rc_list, &dev->sta_rc_list);
+
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+out:
+	rcu_read_unlock();
 }
 
-static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_link_sta *link_sta,
-				 u32 changed)
+static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct ieee80211_link_sta *link_sta,
+				      u32 changed)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct ieee80211_sta *sta = link_sta->sta;
 
-	mt7996_sta_rc_work(&changed, sta);
+	mt7996_link_rate_ctrl_update(&changed, sta);
 	ieee80211_queue_work(hw, &dev->rc_work);
 }
 
@@ -1565,7 +1576,8 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	 * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
 	 * then multiple MCS setting (MCS 4,5,6) is not supported.
 	 */
-	ieee80211_iterate_stations_atomic(hw, mt7996_sta_rc_work, &changed);
+	ieee80211_iterate_stations_atomic(hw, mt7996_link_rate_ctrl_update,
+					  &changed);
 	ieee80211_queue_work(hw, &dev->rc_work);
 
 	return 0;
@@ -2023,7 +2035,7 @@ const struct ieee80211_ops mt7996_ops = {
 	.link_info_changed = mt7996_link_info_changed,
 	.sta_state = mt7996_sta_state,
 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
-	.link_sta_rc_update = mt7996_sta_rc_update,
+	.link_sta_rc_update = mt7996_link_sta_rc_update,
 	.set_key = mt7996_set_key,
 	.ampdu_action = mt7996_ampdu_action,
 	.set_rts_threshold = mt7996_set_rts_threshold,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:57 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:57 +0100
Subject: [PATCH 13/21] wifi: mt76: mt7996: rework mt7996_mac_sta_poll to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-13-015b3d6fd928@kernel.org>

Rework mt7996_mac_sta_poll routine in order to support multi-link
setup.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c56b1126abd59da5895d94fb368004adf6ffbbc8..6870ee189dca61a989d4b7cfde741588c8f18482 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -123,10 +123,12 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		[IEEE80211_AC_VO] = 6
 	};
 	struct mt7996_sta_link *msta_link;
+	struct mt76_vif_link *mlink;
 	struct ieee80211_sta *sta;
 	struct mt7996_sta *msta;
 	u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
 	LIST_HEAD(sta_poll_list);
+	struct mt76_wcid *wcid;
 	int i;
 
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
@@ -150,10 +152,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 					     struct mt7996_sta_link,
 					     wcid.poll_list);
 		msta = msta_link->sta;
-		list_del_init(&msta_link->wcid.poll_list);
+		wcid = &msta_link->wcid;
+		list_del_init(&wcid->poll_list);
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
-		idx = msta_link->wcid.idx;
+		idx = wcid->idx;
 
 		/* refresh peer's airtime reporting */
 		addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
@@ -181,7 +184,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 			       sizeof(msta_link->airtime_ac));
 		}
 
-		if (!msta_link->wcid.sta)
+		if (!wcid->sta)
 			continue;
 
 		sta = container_of((void *)msta, struct ieee80211_sta,
@@ -207,8 +210,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		rssi[2] = to_rssi(GENMASK(23, 16), val);
 		rssi[3] = to_rssi(GENMASK(31, 14), val);
 
-		msta_link->ack_signal =
-			mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
+		mlink = rcu_dereference(msta->vif->mt76.link[wcid->link_id]);
+		if (mlink) {
+			struct mt76_phy *mphy = mt76_vif_link_phy(mlink);
+
+			if (mphy)
+				msta_link->ack_signal =
+					mt76_rx_signal(mphy->antenna_mask,
+						       rssi);
+		}
 
 		ewma_avg_signal_add(&msta_link->avg_ack_signal,
 				    -msta_link->ack_signal);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:58 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:58 +0100
Subject: [PATCH 14/21] wifi: mt76: mt7996: rework mt7996_update_mu_group to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-14-015b3d6fd928@kernel.org>

Rework mt7996_update_mu_group routine in order to support multi-link
setup.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4d3098e47dbbc25ced2a4b40c6b92423c451899e..2bf6453975ae584b2ab7cc9a46cc80ad7d73d05d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -700,12 +700,11 @@ mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf,
 }
 
 static void
-mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+mt7996_update_mu_group(struct ieee80211_hw *hw, struct mt7996_vif_link *link,
 		       struct ieee80211_bss_conf *info)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	u8 band = mvif->deflink.mt76.band_idx;
+	u8 band = link->mt76.band_idx;
 	u32 *mu;
 
 	mu = (u32 *)info->mu_group.membership;
@@ -831,7 +830,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		mt7996_mcu_beacon_inband_discov(dev, vif, changed);
 
 	if (changed & BSS_CHANGED_MU_GROUPS)
-		mt7996_update_mu_group(hw, vif, info);
+		mt7996_update_mu_group(hw, link, info);
 
 	if (changed & BSS_CHANGED_TXPOWER &&
 	    info->txpower != phy->txpower) {

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:13:59 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:13:59 +0100
Subject: [PATCH 15/21] wifi: mt76: mt7996: rework
 mt7996_net_fill_forward_path to support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-15-015b3d6fd928@kernel.org>

Rework mt7996_net_fill_forward_path routine in order to support multi-link
setup.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 2bf6453975ae584b2ab7cc9a46cc80ad7d73d05d..4a33979ee8535303fa3d09ec4500546d26f700eb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1973,13 +1973,26 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif_link *mlink = &mvif->deflink;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+	struct mt7996_sta_link *msta_link;
+	struct mt7996_vif_link *link;
+	struct mt76_vif_link *mlink;
 	struct mt7996_phy *phy;
 
-	phy = mt7996_vif_link_phy(mlink);
+	mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]);
+	if (!mlink)
+		return -EIO;
+
+	msta_link = rcu_dereference(msta->link[msta->deflink_id]);
+	if (!msta_link)
+		return -EIO;
+
+	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
+		return -EIO;
+
+	link = (struct mt7996_vif_link *)mlink;
+	phy = mt7996_vif_link_phy(link);
 	if (!phy)
 		return -ENODEV;
 
@@ -1989,13 +2002,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
-		return -EIO;
-
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
-	path->mtk_wdma.bss = mvif->deflink.mt76.idx;
+	path->mtk_wdma.bss = mlink->idx;
 	path->mtk_wdma.queue = 0;
 	path->mtk_wdma.wcid = msta_link->wcid.idx;
 

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:00 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:00 +0100
Subject: [PATCH 16/21] wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr
 to support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-16-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Rework mt7996_mcu_add_obss_spr routine in order to support multi-link
setup.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 11 ++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4a33979ee8535303fa3d09ec4500546d26f700eb..eeb856984298c1e07396c0338e0858afbdb21501 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -807,7 +807,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		mt7996_mcu_set_tx(dev, vif, info);
 
 	if (changed & BSS_CHANGED_HE_OBSS_PD)
-		mt7996_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);
+		mt7996_mcu_add_obss_spr(phy, link, &info->he_obss_pd);
 
 	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
 		if ((vif->type == NL80211_IFTYPE_AP &&
@@ -1254,6 +1254,7 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mtxq = (struct mt76_txq *)txq->drv_priv;
 
 	mutex_lock(&dev->mt76.mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, ssn,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index b9f689436bfd3859e01ff7025a1f77cec8348824..318ab7c2baa22861637137edfb666e779e662557 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -4193,12 +4193,12 @@ mt7996_mcu_set_obss_spr_pd(struct mt7996_phy *phy,
 }
 
 static int
-mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy,
+			     struct mt7996_vif_link *link,
 			     struct ieee80211_he_obss_pd *he_obss_pd)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = phy->dev;
-	u8 omac = mvif->deflink.mt76.omac_idx;
+	u8 omac = link->mt76.omac_idx;
 	struct {
 		u8 band_idx;
 		u8 __rsv[3];
@@ -4270,7 +4270,8 @@ mt7996_mcu_set_obss_spr_bitmap(struct mt7996_phy *phy,
 				 sizeof(req), true);
 }
 
-int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
+			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd)
 {
 	int ret;
@@ -4304,7 +4305,7 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 		return ret;
 
 	/* Set SR prohibit */
-	ret = mt7996_mcu_set_obss_spr_siga(phy, vif, he_obss_pd);
+	ret = mt7996_mcu_set_obss_spr_siga(phy, link, he_obss_pd);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 8a347dd8e648a43250e7dd717cb65f77cb4a61dd..45280f8f34fc4a56dddb3944232c17fdf4b61f69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -595,7 +595,8 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 				    struct ieee80211_vif *vif, u32 changed);
-int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
+			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd);
 int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
 			     struct ieee80211_vif *vif,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:01 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:01 +0100
Subject: [PATCH 17/21] wifi: mt76: mt7996: rework
 mt7996_mcu_beacon_inband_discov to support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-17-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

Rework mt7996_mcu_beacon_inband_discov routine in order to support
multi-link setup.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 19 ++++++++++---------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index eeb856984298c1e07396c0338e0858afbdb21501..bcca1850d471bc43390c2f9e2ffecf6d9a05f377 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -827,7 +827,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
 		       BSS_CHANGED_FILS_DISCOVERY))
-		mt7996_mcu_beacon_inband_discov(dev, vif, changed);
+		mt7996_mcu_beacon_inband_discov(dev, info, link, changed);
 
 	if (changed & BSS_CHANGED_MU_GROUPS)
 		mt7996_update_mu_group(hw, link, info);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 318ab7c2baa22861637137edfb666e779e662557..85602a8594e0c9ab3a0055e04cf1ca836d62b6b9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2717,13 +2717,14 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
-				    struct ieee80211_vif *vif, u32 changed)
+				    struct ieee80211_bss_conf *link_conf,
+				    struct mt7996_vif_link *link, u32 changed)
 {
 #define OFFLOAD_TX_MODE_SU	BIT(0)
 #define OFFLOAD_TX_MODE_MU	BIT(1)
+	struct ieee80211_vif *vif = link_conf->vif;
 	struct ieee80211_hw *hw = mt76_hw(dev);
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_phy *phy = link->phy;
 	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
 	struct bss_inband_discovery_tlv *discov;
 	struct ieee80211_tx_info *info;
@@ -2740,21 +2741,21 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 	chandef = &phy->mt76->chandef;
 	band = chandef->chan->band;
 
-	if (vif->bss_conf.nontransmitted)
+	if (link_conf->nontransmitted)
 		return 0;
 
-	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->deflink.mt76,
+	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
 					  MT7996_MAX_BSS_OFFLOAD_SIZE);
 	if (IS_ERR(rskb))
 		return PTR_ERR(rskb);
 
 	if (changed & BSS_CHANGED_FILS_DISCOVERY &&
-	    vif->bss_conf.fils_discovery.max_interval) {
-		interval = vif->bss_conf.fils_discovery.max_interval;
+	    link_conf->fils_discovery.max_interval) {
+		interval = link_conf->fils_discovery.max_interval;
 		skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
 	} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
-		   vif->bss_conf.unsol_bcast_probe_resp_interval) {
-		interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
+		   link_conf->unsol_bcast_probe_resp_interval) {
+		interval = link_conf->unsol_bcast_probe_resp_interval;
 		skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
 	}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 45280f8f34fc4a56dddb3944232c17fdf4b61f69..124a48e2706e412afc91af5e1c057fca40fe5e3c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -594,7 +594,8 @@ int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
 int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
-				    struct ieee80211_vif *vif, u32 changed);
+				    struct ieee80211_bss_conf *link_conf,
+				    struct mt7996_vif_link *link, u32 changed);
 int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
 			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:02 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:02 +0100
Subject: [PATCH 18/21] wifi: mt76: mt7996: set vif default link_id
 adding/removing vif links
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-18-015b3d6fd928@kernel.org>

This info will be consumed by subsequent patches (e.g. in set/get tsf
routines).

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index bcca1850d471bc43390c2f9e2ffecf6d9a05f377..40efba5bcaac364f8aa1ebf528e283494178616b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -271,6 +271,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
@@ -338,6 +339,9 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL);
 
+	if (mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)
+		mvif->mt76.deflink_id = link_conf->link_id;
+
 	return 0;
 }
 
@@ -346,6 +350,7 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			    struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
@@ -359,6 +364,19 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
 
+	if (mvif->mt76.deflink_id == link_conf->link_id) {
+		struct ieee80211_bss_conf *iter;
+		unsigned int link_id;
+
+		mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
+		for_each_vif_active_link(vif, iter, link_id) {
+			if (link_id != IEEE80211_LINK_UNSPECIFIED) {
+				mvif->mt76.deflink_id = link_id;
+				break;
+			}
+		}
+	}
+
 	dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
 	phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
 
@@ -443,6 +461,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
 	mt76_vif_init(vif, &mvif->mt76);
 
 	vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
+	mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
 
 out:
 	mutex_unlock(&dev->mt76.mutex);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:03 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:03 +0100
Subject: [PATCH 19/21] wifi: mt76: mt7996: rework set/get_tsf callabcks to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-19-015b3d6fd928@kernel.org>

From: Shayne Chen <shayne.chen at mediatek.com>

This is a preliminary patch in order to enable MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao at mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao at mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo at kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 48 ++++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  2 +-
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 6870ee189dca61a989d4b7cfde741588c8f18482..a52b4e71b267e9a72b69cb2ffbc95befb1cca655 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2732,7 +2732,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 
 		flow->sched = true;
 		flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow);
-		curr_tsf = __mt7996_get_tsf(hw, msta->vif);
+		curr_tsf = __mt7996_get_tsf(hw, &msta->vif->deflink);
 		div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
 		flow_tsf = curr_tsf + interval - rem;
 		twt_agrt->twt = cpu_to_le64(flow_tsf);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 40efba5bcaac364f8aa1ebf528e283494178616b..8bcb4b8e3ef58c23294c16c10d38384bfba87e30 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1336,10 +1336,10 @@ mt7996_get_stats(struct ieee80211_hw *hw,
 	return 0;
 }
 
-u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif)
+u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_phy *phy = link->phy;
 	union {
 		u64 t64;
 		u32 t32[2];
@@ -1351,8 +1351,8 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif)
 
 	lockdep_assert_held(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
 	/* TSF software read */
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_READ);
@@ -1370,7 +1370,7 @@ mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	u64 ret;
 
 	mutex_lock(&dev->mt76.mutex);
-	ret = __mt7996_get_tsf(hw, mvif);
+	ret = __mt7996_get_tsf(hw, &mvif->deflink);
 	mutex_unlock(&dev->mt76.mutex);
 
 	return ret;
@@ -1382,26 +1382,33 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_vif_link *link;
+	struct mt7996_phy *phy;
 	union {
 		u64 t64;
 		u32 t32[2];
 	} tsf = { .t64 = timestamp, };
 	u16 n;
 
-	if (!phy)
-		return;
-
 	mutex_lock(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id);
+	if (!link)
+		goto unlock;
+
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
+	phy = link->phy;
+	if (!phy)
+		goto unlock;
+
 	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
 	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);
 	/* TSF software overwrite */
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_WRITE);
 
+unlock:
 	mutex_unlock(&dev->mt76.mutex);
 }
 
@@ -1411,26 +1418,33 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_vif_link *link;
+	struct mt7996_phy *phy;
 	union {
 		u64 t64;
 		u32 t32[2];
 	} tsf = { .t64 = timestamp, };
 	u16 n;
 
-	if (!phy)
-		return;
-
 	mutex_lock(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id);
+	if (!link)
+		goto unlock;
+
+	phy = link->phy;
+	if (!phy)
+		goto unlock;
+
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
 	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
 	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);
 	/* TSF software adjust*/
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_ADJUST);
 
+unlock:
 	mutex_unlock(&dev->mt76.mutex);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 124a48e2706e412afc91af5e1c057fca40fe5e3c..815a3c68b8723469e32e74b85979eaf75c1b176a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -535,7 +535,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
 				     void __iomem *mem_base, u32 device_id);
 void mt7996_wfsys_reset(struct mt7996_dev *dev);
 irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
-u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
 int mt7996_register_device(struct mt7996_dev *dev);
 void mt7996_unregister_device(struct mt7996_dev *dev);
 int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:04 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:04 +0100
Subject: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-20-015b3d6fd928@kernel.org>

Active/de-active TX/RX BA sessssion for each active links running
mt7996_ampdu_action routine.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 89 ++++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 16 ++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  5 +-
 3 files changed, 64 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 8bcb4b8e3ef58c23294c16c10d38384bfba87e30..adeb267b2801894590f90d02e902ebec602de98a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1259,12 +1259,13 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	enum ieee80211_ampdu_mlme_action action = params->action;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct ieee80211_sta *sta = params->sta;
-	struct ieee80211_txq *txq = sta->txq[params->tid];
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct ieee80211_txq *txq = sta->txq[params->tid];
+	struct ieee80211_link_sta *link_sta;
 	u16 tid = params->tid;
 	u16 ssn = params->ssn;
 	struct mt76_txq *mtxq;
+	unsigned int link_id;
 	int ret = 0;
 
 	if (!txq)
@@ -1274,38 +1275,60 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	mutex_lock(&dev->mt76.mutex);
 
-	switch (action) {
-	case IEEE80211_AMPDU_RX_START:
-		mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, ssn,
-				   params->buf_size);
-		ret = mt7996_mcu_add_rx_ba(dev, params, true);
-		break;
-	case IEEE80211_AMPDU_RX_STOP:
-		mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
-		ret = mt7996_mcu_add_rx_ba(dev, params, false);
-		break;
-	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		mtxq->aggr = true;
-		mtxq->send_bar = false;
-		ret = mt7996_mcu_add_tx_ba(dev, params, true);
-		break;
-	case IEEE80211_AMPDU_TX_STOP_FLUSH:
-	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-		mtxq->aggr = false;
-		clear_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = mt7996_mcu_add_tx_ba(dev, params, false);
-		break;
-	case IEEE80211_AMPDU_TX_START:
-		set_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
-		break;
-	case IEEE80211_AMPDU_TX_STOP_CONT:
-		mtxq->aggr = false;
-		clear_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = mt7996_mcu_add_tx_ba(dev, params, false);
-		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		switch (action) {
+		case IEEE80211_AMPDU_RX_START:
+			mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid,
+					   ssn, params->buf_size);
+			ret = mt7996_mcu_add_rx_ba(dev, params, link, true);
+			break;
+		case IEEE80211_AMPDU_RX_STOP:
+			mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
+			ret = mt7996_mcu_add_rx_ba(dev, params, link, false);
+			break;
+		case IEEE80211_AMPDU_TX_OPERATIONAL:
+			mtxq->aggr = true;
+			mtxq->send_bar = false;
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, true);
+			break;
+		case IEEE80211_AMPDU_TX_STOP_FLUSH:
+		case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+			mtxq->aggr = false;
+			clear_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, false);
+			break;
+		case IEEE80211_AMPDU_TX_START:
+			set_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
+			break;
+		case IEEE80211_AMPDU_TX_STOP_CONT:
+			mtxq->aggr = false;
+			clear_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, false);
+			break;
+		}
+
+		if (ret)
+			break;
 	}
+
+	if (action == IEEE80211_AMPDU_TX_STOP_CONT)
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
 	mutex_unlock(&dev->mt76.mutex);
 
 	return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 85602a8594e0c9ab3a0055e04cf1ca836d62b6b9..89e4f0e8858322b636650a27d9ab0872987b7011 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1160,26 +1160,20 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif,
 /** starec & wtbl **/
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool enable)
+			 struct mt7996_vif_link *link,
+			 struct mt7996_sta_link *msta_link, bool enable)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif *mvif = msta->vif;
-
 	if (enable && !params->amsdu)
 		msta_link->wcid.amsdu = false;
 
-	return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params, enable, true);
+	return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, true);
 }
 
 int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool enable)
+			 struct mt7996_vif_link *link, bool enable)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
-	struct mt7996_vif *mvif = msta->vif;
-
-	return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params, enable, false);
+	return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, false);
 }
 
 static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 815a3c68b8723469e32e74b85979eaf75c1b176a..43e646ed6094cb7fb78d201fc3ee8446ad2a16a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -584,10 +584,11 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
 				struct mt7996_sta_link *msta_link);
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool add);
+			 struct mt7996_vif_link *link,
+			 struct mt7996_sta_link *msta_link, bool enable);
 int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool add);
+			 struct mt7996_vif_link *link, bool enable);
 int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
 				struct mt76_vif_link *mlink,
 				struct cfg80211_he_bss_color *he_bss_color);

-- 
2.48.1



From lorenzo at kernel.org  Wed Mar 12 04:14:05 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:14:05 +0100
Subject: [PATCH 21/21] wifi: mt76: mt7996: Update mt7996_tx to MLO support
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
Message-ID: <20250312-b4-mt7996-mlo-p2-v1-21-015b3d6fd928@kernel.org>

Rework mt7996_tx routine in order to support multi-link
setup.

Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 31 +++++++++++++++---------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index adeb267b2801894590f90d02e902ebec602de98a..91c64e3a0860ff0dc5405627b23f79f4ebd1dafd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1200,12 +1200,18 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_vif *vif = info->control.vif;
 	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+	u8 link_id = u32_get_bits(info->control.flags,
+				  IEEE80211_TX_CTRL_MLO_LINK);
+
+	rcu_read_lock();
 
 	if (vif) {
-		struct mt7996_vif *mvif;
+		struct mt7996_vif *mvif = (void *)vif->drv_priv;
+		struct mt76_vif_link *mlink;
 
-		mvif = (struct mt7996_vif *)vif->drv_priv;
-		wcid = &mvif->deflink.msta_link.wcid;
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (mlink && mlink->wcid)
+			wcid = mlink->wcid;
 
 		if (mvif->mt76.roc_phy &&
 		    (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
@@ -1217,19 +1223,22 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (control->sta) {
-		struct mt7996_sta_link *msta_link;
-
-		msta_link = (struct mt7996_sta_link *)control->sta->drv_priv;
-		wcid = &msta_link->wcid;
-	}
-
 	if (!mphy) {
 		ieee80211_free_txskb(hw, skb);
-		return;
+		goto unlock;
 	}
 
+	if (control->sta) {
+		struct mt7996_sta *msta = (void *)control->sta->drv_priv;
+		struct mt7996_sta_link *msta_link;
+
+		msta_link = rcu_dereference(msta->link[link_id]);
+		if (msta_link)
+			wcid = &msta_link->wcid;
+	}
 	mt76_tx(mphy, control->sta, wcid, skb);
+unlock:
+	rcu_read_unlock();
 }
 
 static int mt7996_set_rts_threshold(struct ieee80211_hw *hw, u32 val)

-- 
2.48.1



From sudeep.holla at arm.com  Wed Mar 12 04:14:31 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:14:31 +0000
Subject: [PATCH 0/3] firmware: arm_scmi: Minor cleanups in the scmi bus
 layer
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>

These cleanup centralizes error logging for SCMI device creation into a
single helper function, _scmi_device_create(), consolidates the device
matching logic into a single function, and ensures that devices must
have a name for registration, removing support for unnamed devices while
matching the devices and drivers for probing.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
Sudeep Holla (3):
      firmware: arm_scmi: Ensure scmi_devices are always matched by name as well
      firmware: arm_scmi: Refactor device matching logic to eliminate duplication
      firmware: arm_scmi: Refactor error logging from SCMI device creation to single helper

 drivers/firmware/arm_scmi/bus.c    | 75 ++++++++++++++++++++------------------
 drivers/firmware/arm_scmi/driver.c |  8 +---
 2 files changed, 40 insertions(+), 43 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250312-b4-scmi_minor_cleanup-8f85228d435c

Best regards,
-- 
Regards,
Sudeep



From sudeep.holla at arm.com  Wed Mar 12 04:14:32 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:14:32 +0000
Subject: [PATCH 1/3] firmware: arm_scmi: Ensure scmi_devices are always
 matched by name as well
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-1-51a514282794@arm.com>

Currently, devices without a name in the id_table cannot register drivers,
and no scmi_device is created without a name via scmi_device_create().
However, the function __scmi_device_create() allows devices with no name,
which are then labeled as "unknown."

Removes support for matching scmi_device instances without a name,
ensuring consistency across the driver registration and probing process.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a3386bf36de508d312e2c4fa2e27ba62ba3776a0..050a5ff5dc96a7df58edff5faeb8c1ec6228b97d 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -214,13 +214,10 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_d
 	if (!id)
 		return NULL;
 
-	for (; id->protocol_id; id++)
-		if (id->protocol_id == scmi_dev->protocol_id) {
-			if (!id->name)
-				return id;
-			else if (!strcmp(id->name, scmi_dev->name))
-				return id;
-		}
+	for (; id->protocol_id && id->name; id++)
+		if (id->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id->name, scmi_dev->name))
+			return id;
 
 	return NULL;
 }

-- 
2.34.1



From sudeep.holla at arm.com  Wed Mar 12 04:14:33 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:14:33 +0000
Subject: [PATCH 2/3] firmware: arm_scmi: Refactor device matching logic to
 eliminate duplication
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-2-51a514282794@arm.com>

Currently, the device matching logic is duplicated in two functions:
  - scmi_dev_match() used by the scmi_bus to match scmi_devices with
    scmi_drivers.
  - scmi_child_dev_find() used to check for the presence of a device
    with the same name and protocol_id to avoid adding duplicates to
    the bus.

Refactor the code to eliminate the redundant matching logic and
consolidates the functionality for better maintainability and efficiency.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 43 +++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 050a5ff5dc96a7df58edff5faeb8c1ec6228b97d..a30fd8e05e423e226a63833f309d8d30c400fabd 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -206,52 +206,49 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
 		scmi_protocol_device_unrequest(entry);
 }
 
-static const struct scmi_device_id *
-scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_drv)
+static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
+				      const struct scmi_device_id *id_table)
 {
-	const struct scmi_device_id *id = scmi_drv->id_table;
+	if (!id_table || !id_table->name)
+		return 0;
 
-	if (!id)
-		return NULL;
-
-	for (; id->protocol_id && id->name; id++)
-		if (id->protocol_id == scmi_dev->protocol_id &&
-		    !strcmp(id->name, scmi_dev->name))
-			return id;
+	for (; id_table->protocol_id && id_table->name; id_table++)
+		if (id_table->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id_table->name, scmi_dev->name))
+			return 1;
+	return 0;
+}
 
-	return NULL;
+static int scmi_dev_match_id(struct scmi_device *scmi_dev,
+			     const struct scmi_driver *scmi_drv)
+{
+	return scmi_dev_match_by_id_table(scmi_dev, scmi_drv->id_table);
 }
 
 static int scmi_dev_match(struct device *dev, const struct device_driver *drv)
 {
 	const struct scmi_driver *scmi_drv = to_scmi_driver(drv);
 	struct scmi_device *scmi_dev = to_scmi_dev(dev);
-	const struct scmi_device_id *id;
-
-	id = scmi_dev_match_id(scmi_dev, scmi_drv);
-	if (id)
-		return 1;
 
-	return 0;
+	return scmi_dev_match_id(scmi_dev, scmi_drv);
 }
 
 static int scmi_match_by_id_table(struct device *dev, const void *data)
 {
-	struct scmi_device *sdev = to_scmi_dev(dev);
+	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 	const struct scmi_device_id *id_table = data;
 
-	return sdev->protocol_id == id_table->protocol_id &&
-		(id_table->name && !strcmp(sdev->name, id_table->name));
+	return scmi_dev_match_by_id_table(scmi_dev, id_table);
 }
 
 static struct scmi_device *scmi_child_dev_find(struct device *parent,
 					       int prot_id, const char *name)
 {
-	struct scmi_device_id id_table;
+	struct scmi_device_id id_table[2] = { 0 };
 	struct device *dev;
 
-	id_table.protocol_id = prot_id;
-	id_table.name = name;
+	id_table[0].protocol_id = prot_id;
+	id_table[0].name = name;
 
 	dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
 	if (!dev)

-- 
2.34.1



From sudeep.holla at arm.com  Wed Mar 12 04:14:34 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:14:34 +0000
Subject: [PATCH 3/3] firmware: arm_scmi: Refactor error logging from SCMI
 device creation to single helper
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-3-51a514282794@arm.com>

Refactors the error logging related to SCMI device creation. The goal
is to remove duplicated error-handling code and centralize it into a
single helper function: _scmi_device_create().

By doing so, any code redundancy around error logging is avoided, as
error logging during device creation will now be handled by a unified
helper function.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c    | 29 +++++++++++++++++++----------
 drivers/firmware/arm_scmi/driver.c |  8 +-------
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a30fd8e05e423e226a63833f309d8d30c400fabd..493e2c63b107fd9063f11034b71d65f567bb0778 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -411,6 +411,20 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 	return NULL;
 }
 
+static struct scmi_device *
+_scmi_device_create(struct device_node *np, struct device *parent,
+		    int protocol, const char *name)
+{
+	struct scmi_device *sdev;
+
+	sdev = __scmi_device_create(np, parent, protocol, name);
+	if (!sdev)
+		pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
+		       of_node_full_name(parent->of_node), protocol, name);
+
+	return sdev;
+}
+
 /**
  * scmi_device_create  - A method to create one or more SCMI devices
  *
@@ -443,7 +457,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	struct scmi_device *scmi_dev = NULL;
 
 	if (name)
-		return __scmi_device_create(np, parent, protocol, name);
+		return _scmi_device_create(np, parent, protocol, name);
 
 	mutex_lock(&scmi_requested_devices_mtx);
 	phead = idr_find(&scmi_requested_devices, protocol);
@@ -457,18 +471,13 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	list_for_each_entry(rdev, phead, node) {
 		struct scmi_device *sdev;
 
-		sdev = __scmi_device_create(np, parent,
-					    rdev->id_table->protocol_id,
-					    rdev->id_table->name);
-		/* Report errors and carry on... */
+		sdev = _scmi_device_create(np, parent,
+					   rdev->id_table->protocol_id,
+					   rdev->id_table->name);
 		if (sdev)
 			scmi_dev = sdev;
-		else
-			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
-			       of_node_full_name(parent->of_node),
-			       rdev->id_table->protocol_id,
-			       rdev->id_table->name);
 	}
+
 	mutex_unlock(&scmi_requested_devices_mtx);
 
 	return scmi_dev;
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 60050da54bf24c0245290e846f91aea62392855b..b80c574cb3bb2f12b2980fc844ea3da10abdc9f1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -439,14 +439,8 @@ static void scmi_create_protocol_devices(struct device_node *np,
 					 struct scmi_info *info,
 					 int prot_id, const char *name)
 {
-	struct scmi_device *sdev;
-
 	mutex_lock(&info->devreq_mtx);
-	sdev = scmi_device_create(np, info->dev, prot_id, name);
-	if (name && !sdev)
-		dev_err(info->dev,
-			"failed to create device for protocol 0x%X (%s)\n",
-			prot_id, name);
+	scmi_device_create(np, info->dev, prot_id, name);
 	mutex_unlock(&info->devreq_mtx);
 }
 

-- 
2.34.1



From sudeep.holla at arm.com  Wed Mar 12 04:20:41 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:20:41 +0000
Subject: [PATCH 0/3] firmware: arm_scmi: Minor cleanups in the scmi bus
 layer
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-51a514282794@arm.com>
Message-ID: <Z9FuCUAzjd4y6oEL@bogus>

On Wed, Mar 12, 2025 at 11:14:31AM +0000, Sudeep Holla wrote:
> These cleanup centralizes error logging for SCMI device creation into a
> single helper function, _scmi_device_create(), consolidates the device
> matching logic into a single function, and ensures that devices must
> have a name for registration, removing support for unnamed devices while
> matching the devices and drivers for probing.
> 

Please ignore this as I messed by and somehow managed to not include
arm-scmi list with wrong usage of b4 send, will resend soon.

-- 
Regards,
Sudeep


From ulf.hansson at linaro.org  Wed Mar 12 04:24:16 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:16 +0100
Subject: [PATCH v2 0/3] Introduce DW MMC support for Exynos7870
In-Reply-To: <20250219-exynos7870-mmc-v2-0-b4255a3e39ed@disroot.org>
References: <20250219-exynos7870-mmc-v2-0-b4255a3e39ed@disroot.org>
Message-ID: <CAPDyKFrmn21xksS6Co9AjLQbtq_EWC8WF=r3RSAc6nfWTT9-zA@mail.gmail.com>

On Tue, 18 Feb 2025 at 19:48, Kaustabh Chakraborty
<kauschluss at disroot.org> wrote:
>
> This series adds support for SMU and non-SMU variants of Exynos7870 DW
> MMC controllers.
>
> Some DW MMC controllers require two 32-bit r/w from a 64-bit FIFO,
> the series implements that feature as well.
>
> This patch series is a part of Exynos7870 upstreaming.
>
> Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>

The series applied for next, thanks!

Kind regards
Uffe


> ---
> Changes in v2:
> - Take over ownership of patches by the co-author, upon their request.
> - Link to v1: https://lore.kernel.org/r/20250204-exynos7870-mmc-v1-0-c87cfc72be4a at disroot.org
>
> ---
> Kaustabh Chakraborty (3):
>       dt-bindings: mmc: samsung,exynos-dw-mshc: add exynos7870 support
>       mmc: dw_mmc: add a quirk for accessing 64-bit FIFOs in two halves
>       mmc: dw_mmc: add exynos7870 DW MMC support
>
>  .../bindings/mmc/samsung,exynos-dw-mshc.yaml       |  2 +
>  drivers/mmc/host/dw_mmc-exynos.c                   | 41 +++++++++-
>  drivers/mmc/host/dw_mmc.c                          | 94 +++++++++++++++++++++-
>  drivers/mmc/host/dw_mmc.h                          | 27 +++++++
>  4 files changed, 161 insertions(+), 3 deletions(-)
> ---
> base-commit: e5d3fd687aac5eceb1721fa92b9f49afcf4c3717
> change-id: 20250203-exynos7870-mmc-75bac583c864
>
> Best regards,
> --
> Kaustabh Chakraborty <kauschluss at disroot.org>
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:26 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:26 +0100
Subject: [PATCH] dt-bindings: mmc: fsl-imx-esdhc: Add i.MX94 support
In-Reply-To: <20250306170937.242183-1-Frank.Li@nxp.com>
References: <20250306170937.242183-1-Frank.Li@nxp.com>
Message-ID: <CAPDyKFprhKa-XqJgfPjphuBCcn4ra2Gj0VewZ8iGqjYAYc2CFw@mail.gmail.com>

On Thu, 6 Mar 2025 at 18:09, Frank Li <Frank.Li at nxp.com> wrote:
>
> Add compatible string "fsl,imx94-usdhc" for the i.MX94 chip, which is
> backward compatible with i.MX8mm. Set it to fall back to
> "fsl,imx8mm-usdhc".
>
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> index b9b9995705290..b98a84f932772 100644
> --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> @@ -57,6 +57,7 @@ properties:
>                - fsl,imx8mp-usdhc
>                - fsl,imx8ulp-usdhc
>                - fsl,imx93-usdhc
> +              - fsl,imx94-usdhc
>                - fsl,imx95-usdhc
>            - const: fsl,imx8mm-usdhc
>        - items:
> --
> 2.34.1
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:30 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:30 +0100
Subject: [PATCH v4 0/2] dt-bindings: mmc: Fix the mmc-slot and Convert
 atmel,hsmci to json schema
In-Reply-To: <20250224-mmc-slot-v4-0-231620a31e88@microchip.com>
References: <20250224-mmc-slot-v4-0-231620a31e88@microchip.com>
Message-ID: <CAPDyKFriZ8xaS0EjO8axVpv7e-8D2Yg9Fm0APCK6M-WYe87_9Q@mail.gmail.com>

On Mon, 24 Feb 2025 at 03:53, Dharma Balasubiramani
<dharma.b at microchip.com> wrote:
>
> This patch series modifies the property status of "compatible"
> (required/optional).
>
> Signed-off-by: Dharma Balasubiramani <dharma.b at microchip.com>

The series applied for next, thanks!

Kind regards
Uffe


> ---
> Changes in v4:
> - Rewrapped the commit message with textwidth=75
> - Allow slot pattern property to match only 0 to 2 as per reg.
> - Add Reviewed-by tags from Rob.
> - Link to v3: https://lore.kernel.org/r/20250212-mmc-slot-v3-0-2bf288207040 at microchip.com
>
> Changes in v3:
> - Add compatible as required property in meson binding.
> - Include the dependent patch that converts txt to yaml for clarity in patch series.
> - Refer the mmc-slot binding in the hsmci binding.
> - Explain "why" the property is made optional in commit description.
> - Link to v2: https://lore.kernel.org/r/20250205-mmc-slot-v2-1-da3c5f30e2d9 at microchip.com
>
> Changes in v2:
> - Instead of moving the compatible string to the other binding, just make it
>   optional (remove from required list).
> - Link to v1: https://lore.kernel.org/r/20241219-mmc-slot-v1-1-dfc747a3d3fb at microchip.com
>
> ---
> Dharma Balasubiramani (2):
>       dt-bindings: mmc: mmc-slot: Make compatible property optional
>       dt-bindings: mmc: atmel,hsmci: Convert to json schema
>
>  .../bindings/mmc/amlogic,meson-mx-sdio.yaml        |   3 +
>  .../devicetree/bindings/mmc/atmel,hsmci.yaml       | 106 +++++++++++++++++++++
>  .../devicetree/bindings/mmc/atmel-hsmci.txt        |  73 --------------
>  .../devicetree/bindings/mmc/mmc-slot.yaml          |   1 -
>  4 files changed, 109 insertions(+), 74 deletions(-)
> ---
> base-commit: d4b0fd87ff0d4338b259dc79b2b3c6f7e70e8afa
> change-id: 20241219-mmc-slot-0574889daea3
>
> Best regards,
> --
> Dharma Balasubiramani <dharma.b at microchip.com>
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:34 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:34 +0100
Subject: [PATCH -next] mmc: atmel-mci: Add missing clk_disable_unprepare()
In-Reply-To: <20250225022856.3452240-1-gubowen5@huawei.com>
References: <20250225022856.3452240-1-gubowen5@huawei.com>
Message-ID: <CAPDyKFo4K9H82Wbupug3Str=18ekkrwjxQxSmw2-1eu3FZQwfA@mail.gmail.com>

On Tue, 25 Feb 2025 at 03:18, Gu Bowen <gubowen5 at huawei.com> wrote:
>
> The error path when atmci_configure_dma() set dma fails in atmci driver
> does not correctly disable the clock.
> Add the missing clk_disable_unprepare() to the error path for pair with
> clk_prepare_enable().
>
> Fixes: 467e081d23e6 ("mmc: atmel-mci: use probe deferring if dma controller is not ready yet")
> Signed-off-by: Gu Bowen <gubowen5 at huawei.com>

Applied for fixes and by adding a stable tag, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/atmel-mci.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
> index fc360902729d..24fffc702a94 100644
> --- a/drivers/mmc/host/atmel-mci.c
> +++ b/drivers/mmc/host/atmel-mci.c
> @@ -2499,8 +2499,10 @@ static int atmci_probe(struct platform_device *pdev)
>         /* Get MCI capabilities and set operations according to it */
>         atmci_get_cap(host);
>         ret = atmci_configure_dma(host);
> -       if (ret == -EPROBE_DEFER)
> +       if (ret == -EPROBE_DEFER) {
> +               clk_disable_unprepare(host->mck);
>                 goto err_dma_probe_defer;
> +       }
>         if (ret == 0) {
>                 host->prepare_data = &atmci_prepare_data_dma;
>                 host->submit_data = &atmci_submit_data_dma;
> --
> 2.25.1
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:45 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:45 +0100
Subject: [PATCH v3 03/15] dt-bindings: mmc: rockchip-dw-mshc: Add support
 for rk3562
In-Reply-To: <20250227111913.2344207-4-kever.yang@rock-chips.com>
References: <20250227111913.2344207-1-kever.yang@rock-chips.com> <20250227111913.2344207-4-kever.yang@rock-chips.com>
Message-ID: <CAPDyKFqZeup0hKqeHFV6qOMpFYZLQOdj3xT_6PdSNWJiW48fsw@mail.gmail.com>

On Thu, 27 Feb 2025 at 12:19, Kever Yang <kever.yang at rock-chips.com> wrote:
>
> The dw-mshc core on Rockchip's RK3562 is the same as the one already
> included in RK3288. Extend the binding accordingly to allow
>
>         compatible = "rockchip,rk3562-dw-mshc", "rockchip,rk3288-dw-mshc";
>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>
> Changes in v3:
> - update commit msg
>
> Changes in v2: None
>
>  Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> index 06df1269f247..772f592291bf 100644
> --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> @@ -38,6 +38,7 @@ properties:
>                - rockchip,rk3328-dw-mshc
>                - rockchip,rk3368-dw-mshc
>                - rockchip,rk3399-dw-mshc
> +              - rockchip,rk3562-dw-mshc
>                - rockchip,rk3568-dw-mshc
>                - rockchip,rk3588-dw-mshc
>                - rockchip,rv1108-dw-mshc
> --
> 2.25.1
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:52 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:52 +0100
Subject: [PATCH v3 1/6] dt-bindings: mmc: rockchip-dw-mshc: Add compatible
 string for RK3528
In-Reply-To: <20250309055348.9299-2-ziyao@disroot.org>
References: <20250309055348.9299-1-ziyao@disroot.org> <20250309055348.9299-2-ziyao@disroot.org>
Message-ID: <CAPDyKFp2UzcxfFz=8sREkj3x4DvfkfxU3utc0+e+uPS78Tn-+g@mail.gmail.com>

On Sun, 9 Mar 2025 at 06:54, Yao Zi <ziyao at disroot.org> wrote:
>
> Add RK3528 compatible string for SD/SDIO interface.
>
> Signed-off-by: Yao Zi <ziyao at disroot.org>
> Acked-by: Rob Herring (Arm) <robh at kernel.org>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> index 06df1269f247..ea0feb733e32 100644
> --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
> @@ -38,6 +38,7 @@ properties:
>                - rockchip,rk3328-dw-mshc
>                - rockchip,rk3368-dw-mshc
>                - rockchip,rk3399-dw-mshc
> +              - rockchip,rk3528-dw-mshc
>                - rockchip,rk3568-dw-mshc
>                - rockchip,rk3588-dw-mshc
>                - rockchip,rv1108-dw-mshc
> --
> 2.48.1
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:56 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:56 +0100
Subject: [PATCH 1/3] dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible
 string for RK3528
In-Reply-To: <20250305214108.1327208-2-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se> <20250305214108.1327208-2-jonas@kwiboo.se>
Message-ID: <CAPDyKFqY+0MGsdZDBJ1AoDaDGrnXN=Gu3JNjuK0LoHfjT9JxiA@mail.gmail.com>

On Wed, 5 Mar 2025 at 22:41, Jonas Karlman <jonas at kwiboo.se> wrote:
>
> The SDHCI controller in Rockchip RK3528 is similar to the one included
> in RK3588.
>
> Add compatible string for the SDHCI controller in RK3528.
>
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> index c3d5e0230af1..fb2115e805f5 100644
> --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
> @@ -14,7 +14,9 @@ properties:
>    compatible:
>      oneOf:
>        - items:
> -          - const: rockchip,rk3576-dwcmshc
> +          - enum:
> +              - rockchip,rk3528-dwcmshc
> +              - rockchip,rk3576-dwcmshc
>            - const: rockchip,rk3588-dwcmshc
>        - enum:
>            - rockchip,rk3568-dwcmshc
> --
> 2.48.1
>


From ulf.hansson at linaro.org  Wed Mar 12 04:24:59 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:24:59 +0100
Subject: [PATCH v3 01/15] dt-bindings: mmc: sunxi: Simplify compatible
 string listing
In-Reply-To: <20250307005712.16828-2-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com> <20250307005712.16828-2-andre.przywara@arm.com>
Message-ID: <CAPDyKFpFgNjy+Tu7ZKB05m55HAf5RQ+AFPgk+6Q8_g1xu0akng@mail.gmail.com>

On Fri, 7 Mar 2025 at 01:57, Andre Przywara <andre.przywara at arm.com> wrote:
>
> New Allwinner SoCs only occasionally update their MMC IP, leading to many
> pairs of compatible strings, though there are sometimes a number of them
> being compatible with one particular SoC.
>
> Collate the compatible string listing in the binding, to group those
> being compatible together. This makes the list more readable, and allows
> for easier addition of new SoC's MMC devices.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 36 ++++++++-----------
>  1 file changed, 14 insertions(+), 22 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> index 0ccd632d56200..8e4c77b7e4ab9 100644
> --- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> @@ -30,38 +30,30 @@ properties:
>        - const: allwinner,sun50i-a100-emmc
>        - const: allwinner,sun50i-a100-mmc
>        - items:
> -          - const: allwinner,sun8i-a83t-mmc
> +          - enum:
> +              - allwinner,sun8i-a83t-mmc
> +              - allwinner,suniv-f1c100s-mmc
>            - const: allwinner,sun7i-a20-mmc
>        - items:
> -          - const: allwinner,sun8i-r40-emmc
> +          - enum:
> +              - allwinner,sun8i-r40-emmc
> +              - allwinner,sun50i-h5-emmc
> +              - allwinner,sun50i-h6-emmc
>            - const: allwinner,sun50i-a64-emmc
>        - items:
> -          - const: allwinner,sun8i-r40-mmc
> +          - enum:
> +              - allwinner,sun8i-r40-mmc
> +              - allwinner,sun50i-h5-mmc
> +              - allwinner,sun50i-h6-mmc
>            - const: allwinner,sun50i-a64-mmc
>        - items:
> -          - const: allwinner,sun50i-h5-emmc
> -          - const: allwinner,sun50i-a64-emmc
> -      - items:
> -          - const: allwinner,sun50i-h5-mmc
> -          - const: allwinner,sun50i-a64-mmc
> -      - items:
> -          - const: allwinner,sun50i-h6-emmc
> -          - const: allwinner,sun50i-a64-emmc
> -      - items:
> -          - const: allwinner,sun50i-h6-mmc
> -          - const: allwinner,sun50i-a64-mmc
> -      - items:
> -          - const: allwinner,sun20i-d1-emmc
> -          - const: allwinner,sun50i-a100-emmc
> -      - items:
> -          - const: allwinner,sun50i-h616-emmc
> +          - enum:
> +              - allwinner,sun20i-d1-emmc
> +              - allwinner,sun50i-h616-emmc
>            - const: allwinner,sun50i-a100-emmc
>        - items:
>            - const: allwinner,sun50i-h616-mmc
>            - const: allwinner,sun50i-a100-mmc
> -      - items:
> -          - const: allwinner,suniv-f1c100s-mmc
> -          - const: allwinner,sun7i-a20-mmc
>
>    reg:
>      maxItems: 1
> --
> 2.46.3
>


From ulf.hansson at linaro.org  Wed Mar 12 04:25:02 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 12:25:02 +0100
Subject: [PATCH v3 02/15] dt-bindings: mmc: sunxi: add compatible strings
 for Allwinner A523
In-Reply-To: <20250307005712.16828-3-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com> <20250307005712.16828-3-andre.przywara@arm.com>
Message-ID: <CAPDyKFoFesrcYPDNDsvU_mLdkTGE2=7TCFrYkdFW3bp_0fLSMg@mail.gmail.com>

On Fri, 7 Mar 2025 at 01:57, Andre Przywara <andre.przywara at arm.com> wrote:
>
> The Allwinner A523 uses the same MMC IP as the D1.
>
> Introduce the new specific compatible strings, and use them with
> fallbacks to the D1 strings.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml      | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> index 8e4c77b7e4ab9..9f3b1edacaa02 100644
> --- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
> @@ -50,10 +50,14 @@ properties:
>            - enum:
>                - allwinner,sun20i-d1-emmc
>                - allwinner,sun50i-h616-emmc
> +              - allwinner,sun55i-a523-emmc
>            - const: allwinner,sun50i-a100-emmc
>        - items:
>            - const: allwinner,sun50i-h616-mmc
>            - const: allwinner,sun50i-a100-mmc
> +      - items:
> +          - const: allwinner,sun55i-a523-mmc
> +          - const: allwinner,sun20i-d1-mmc
>
>    reg:
>      maxItems: 1
> --
> 2.46.3
>


From sudeep.holla at arm.com  Wed Mar 12 04:28:52 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:28:52 +0000
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z9FnZzBQuZ1j5k3I@bogus>
References: <Z7Wvyn1QJQMVigf9@bogus>
 <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus>
 <Z87sGF_jHKau_FMe@bogus>
 <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <Z9AdICiyaCmzKh-N@bogus>
 <Z9FnZzBQuZ1j5k3I@bogus>
Message-ID: <Z9Fv9JPdF5OWUHfk@bogus>

On Wed, Mar 12, 2025 at 10:52:23AM +0000, Sudeep Holla wrote:
> On Tue, Mar 11, 2025 at 11:23:12AM +0000, Sudeep Holla wrote:
> > On Tue, Mar 11, 2025 at 11:12:45AM +0000, Peng Fan wrote:
> > >
> > > So it is clear that wrong fw_devlink is created, it is because scmi cpufreq device is
> > > created earlier and when device_add, the below logic makes the fwnode pointer points
> > > to scmi cpufreq device.
> > >         if (dev->fwnode && !dev->fwnode->dev) {
> > >                 dev->fwnode->dev = dev;
> > >                 fw_devlink_link_device(dev);
> > >         }
> > >
> >
> > Thanks, looks like simple way to reproduce the issue. I will give it a try.
> >
> 
> I could reproduce but none of my solution solved the problem completely
> or properly. And I don't like the DT proposal you came up with. I am
> not inclined to just drop this fwnode setting in the scmi devices and
> just use of_node.
>

Sorry for the typo that changes the meaning: s/not/now

I meant "I am now inclined ..", until we figure out a way to make this
work with devlinks properly.

-- 
Regards,
Sudeep


From peter.griffin at linaro.org  Wed Mar 12 04:31:07 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 11:31:07 +0000
Subject: [PATCH v4 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <59a1a6eb-d719-49bd-a4b5-bfb9c2817f08@kernel.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org> <59a1a6eb-d719-49bd-a4b5-bfb9c2817f08@kernel.org>
Message-ID: <CADrjBPqYoHckqr43y1z8UtthZ9DOG15TJWSv_707Jbyf1yforw@mail.gmail.com>

Hi Krzysztof,

Thanks for the review feedback.

On Tue, 11 Mar 2025 at 19:36, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 07/03/2025 11:29, Peter Griffin wrote:
> > gs101 differs to other SoCs in that fltcon1 register doesn't
> > always exist. Additionally the offset of fltcon0 is not fixed
> > and needs to use the newly added eint_fltcon_offset variable.
> >
> > Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> > Cc: stable at vger.kernel.org
>
> It looks this depends on previous commit, right?

Yes that's right, it depends on the refactoring in the previous patch.
To fix the bug (which is an Serror on suspend for gs101), we need the
dedicated gs101 callback so it can have the knowledge that fltcon1
doesn't always exist and it's varying offset.

> That's really not
> optimal, although I understand that if you re-order patches this code
> would be soon changed, just like you changed other suspend/resume
> callbacks in patch #2?

Originally it was just one patch, but the previous review feedback was
to split the refactor into a dedicated patch, and then add gs101
specific parts separately. The refactoring was done primarily so we
can fix this bug without affecting the other platforms, so I don't
re-ordering the patches will help.

Thanks,

Peter
>
>
> > Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
> > Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> > ---
> > Changes since v2:
> > * make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
> > * align style where the '+' is placed (Andre)
> > * remove unnecessary braces (Andre)
> > ---
>
> ...
>
> > +void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
> > +{
> > +     struct exynos_eint_gpio_save *save = bank->soc_priv;
> > +     const void __iomem *regs = bank->eint_base;
> > +
> > +     if (bank->eint_type == EINT_TYPE_GPIO) {
> > +             save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
> > +                                    + bank->eint_offset);
> > +
> > +             save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
> > +                                        + bank->eint_fltcon_offset);
> > +
> > +             /* fltcon1 register only exists for pins 4-7 */
> > +             if (bank->nr_pins > 4)
> > +                     save->eint_fltcon1 = readl(regs +
> > +                                             EXYNOS_GPIO_EFLTCON_OFFSET
> > +                                             + bank->eint_fltcon_offset + 4);
> > +
> > +             save->eint_mask = readl(regs + bank->irq_chip->eint_mask
> > +                                     + bank->eint_offset);
> > +
> > +             pr_debug("%s: save     con %#010x\n",
> > +                      bank->name, save->eint_con);
> > +             pr_debug("%s: save fltcon0 %#010x\n",
> > +                      bank->name, save->eint_fltcon0);
> > +             if (bank->nr_pins > 4)
> > +                     pr_debug("%s: save fltcon1 %#010x\n",
> > +                              bank->name, save->eint_fltcon1);
> > +             pr_debug("%s: save    mask %#010x\n",
> > +                      bank->name, save->eint_mask);
> > +     } else if (bank->eint_type == EINT_TYPE_WKUP)
> > +             exynos_set_wakeup(bank);
>
> Missing {}. Run checkpatch --strict.
>
>
> Best regards,
> Krzysztof


From lorenzo at kernel.org  Wed Mar 12 04:31:46 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 12:31:46 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
Message-ID: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>

The system occasionally crashes dereferencing a NULL pointer when it is
forwarding constant, high load bidirectional traffic.

[ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
[ 2149.925812] Mem abort info:
[ 2149.928713]   ESR = 0x0000000096000005
[ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
[ 2149.938429]   SET = 0, FnV = 0
[ 2149.941814]   EA = 0, S1PTW = 0
[ 2149.945187]   FSC = 0x05: level 1 translation fault
[ 2149.950348] Data abort info:
[ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
[ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
[ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
[ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
[ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
[ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
[ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
[ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
[ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
[ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
[ 2150.218149] sp : ffffffc080e8ba10
[ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
[ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
[ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
[ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
[ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
[ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
[ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
[ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
[ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
[ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
[ 2150.292811] Call trace:
[ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
[ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
[ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
[ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
[ 2150.318200]  process_one_work+0x178/0x2f0
[ 2150.322211]  worker_thread+0x2e4/0x4cc
[ 2150.325953]  kthread+0xd8/0xdc
[ 2150.329008]  ret_from_fork+0x10/0x20
[ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
[ 2150.338681] ---[ end trace 0000000000000000 ]---
[ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
[ 2150.349035] SMP: stopping secondary CPUs
[ 2150.352954] Kernel Offset: disabled
[ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
[ 2150.361743] Memory Limit: none

Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
routine.

Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++
 drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
 drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index c0a642568ac115ea9df6fbaf7133627a4405a36c..776222595b84e4fba6ae5943420e0edf0d0ecf8f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2454,6 +2454,22 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
 	}
 }
 
+int airoha_is_valid_gdm_port(struct airoha_eth *eth,
+			     struct airoha_gdm_port *port)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+		if (!eth->ports[i])
+			continue;
+
+		if (eth->ports[i] == port)
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int airoha_alloc_gdm_port(struct airoha_eth *eth,
 				 struct device_node *np, int index)
 {
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
 #define airoha_qdma_clear(qdma, offset, val)			\
 	airoha_rmw((qdma)->regs, (offset), (val), 0)
 
+int airoha_is_valid_gdm_port(struct airoha_eth *eth,
+			     struct airoha_gdm_port *port);
+
 void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
 int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 				 void *cb_priv);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
 #endif
 }
 
-static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
+static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
+					struct airoha_foe_entry *hwe,
 					struct net_device *dev, int type,
 					struct airoha_flow_data *data,
 					int l4proto)
@@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
 	if (dev) {
 		struct airoha_gdm_port *port = netdev_priv(dev);
 		u8 pse_port;
+		int err;
+
+		err = airoha_is_valid_gdm_port(eth, port);
+		if (err)
+			return err;
 
 		if (dsa_port >= 0)
 			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
@@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
 	    !is_valid_ether_addr(data.eth.h_dest))
 		return -EINVAL;
 
-	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
+	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
 					   &data, l4proto);
 	if (err)
 		return err;

---
base-commit: 0ea09cbf8350b70ad44d67a1dcb379008a356034
change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From krzk at kernel.org  Wed Mar 12 04:34:44 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 12:34:44 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
 <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org>
 <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
Message-ID: <5ecb69c9-c877-4c91-a1ae-0ef59d0ee3d6@kernel.org>

On 12/03/2025 12:10, Christopher Obbard wrote:
> Hi Krzysztof,
> 
> On Wed, 12 Mar 2025 at 09:56, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>>
>> On 11/03/2025 20:15, Christopher Obbard wrote:
>>> Hi Dmitry,
>>>
>>> On Tue, 11 Mar 2025 at 19:58, Dmitry Baryshkov <lumag at kernel.org> wrote:
>>>>
>>>> On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
>>>>> I sent this patch to start the discussion, some things I found:
>>>>>
>>>>> 1) Some interconnects are missing from arm defconfig. Should they be =y too ?
>>>>
>>>> No, unless those are required for the UART console.
>>>
>>> OK, that makes sense. FWIW the cryptic (to me, at least) commit log on
>>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eee808134ecf1c1093ff1ddfc056dc5e469d0c3
>>> made me think that the interconnects should be built-in on all devices.
>>>
>>> Of course, the real problem here is RB3gen2 not actually finding the
>>> UFS/eMMC device due to no interconnect driver.
>>> Until now, I have been building that into the kernel. I will
>>> investigate instead shoving into the initrd (in both debian and
>>> fedora) which should solve my issue and render this patchset useless.
>>
>> For Qualcomm platforms you are expected to always have initramfs, thus
>> you will have the modules for UFS/eMMC mounts. I don't understand the
>> problem which you were trying to solve.
>>
>> The interconnects were built in *only* because of need for serial
>> console. Only.
> 
> Thanks for confirming. It is all clear now.
> 
> Consider this patch dropped from my side.
> 
> For reference, I am working on updating initramfs generation tools in
> Debian/Fedora to include the required interconnect modules. Currently
> the interconnect drivers are built as modules in these distros, but
> are not included in the initrd. That is where my confusion initially
> stemmed from.

Sure. This defconfig is anyway for us - developers, not for the distros
to use directly. Distros have much bigger configs and use almost
everything as module.

Best regards,
Krzysztof


From nm at ti.com  Wed Mar 12 04:38:26 2025
From: nm at ti.com (Nishanth Menon)
Date: Wed, 12 Mar 2025 06:38:26 -0500
Subject: [GIT PULL] soc: ti: Driver updates for v6.15
Message-ID: <20250312113826.ka63nijuftgs6h52@mocker>

Hi,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git tags/ti-driver-soc-for-v6.15

for you to fetch changes up to 9a9b7cd77b2427d0722fe52301fa270690928989:

  firmware: config: ti-sci: Default set to ARCH_K3 for the ti sci driver (2025-02-26 12:45:53 -0600)

----------------------------------------------------------------
TI SoC driver updates for v6.15

- ti-sci: Default set to ARCH_K3 for the ti sci driver in preperation for
  the driver to be default set as module in defconfig.
- k3-socinfo: Explicitly build up regmap instead of depending on syscon
  helper

----------------------------------------------------------------
Andrew Davis (1):
      soc: ti: k3-socinfo: Do not use syscon helper to build regmap

Guillaume La Roque (1):
      firmware: config: ti-sci: Default set to ARCH_K3 for the ti sci driver

 drivers/firmware/Kconfig    |  1 +
 drivers/soc/ti/k3-socinfo.c | 13 ++++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/daf69480/attachment.sig>

From peter.griffin at linaro.org  Wed Mar 12 04:39:50 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 11:39:50 +0000
Subject: [PATCH v4 3/4] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <CADrjBPqYoHckqr43y1z8UtthZ9DOG15TJWSv_707Jbyf1yforw@mail.gmail.com>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-3-2d775e486036@linaro.org>
 <59a1a6eb-d719-49bd-a4b5-bfb9c2817f08@kernel.org> <CADrjBPqYoHckqr43y1z8UtthZ9DOG15TJWSv_707Jbyf1yforw@mail.gmail.com>
Message-ID: <CADrjBPqSSbt=xM7u12BU2nsF2xvyXe_+bLSCxCPBTfCc07VpuQ@mail.gmail.com>

Hi Krzysztof,

On Wed, 12 Mar 2025 at 11:31, Peter Griffin <peter.griffin at linaro.org> wrote:
>
> Hi Krzysztof,
>
> Thanks for the review feedback.
>
> On Tue, 11 Mar 2025 at 19:36, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> >
> > On 07/03/2025 11:29, Peter Griffin wrote:
> > > gs101 differs to other SoCs in that fltcon1 register doesn't
> > > always exist. Additionally the offset of fltcon0 is not fixed
> > > and needs to use the newly added eint_fltcon_offset variable.
> > >
> > > Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> > > Cc: stable at vger.kernel.org
> >
> > It looks this depends on previous commit, right?
>
> Yes that's right, it depends on the refactoring in the previous patch.
> To fix the bug (which is an Serror on suspend for gs101), we need the
> dedicated gs101 callback so it can have the knowledge that fltcon1
> doesn't always exist and it's varying offset.

and also dependent on the first patch that adds the eint_fltcon_offset :)

Peter


From sudeep.holla at arm.com  Wed Mar 12 04:40:23 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:40:23 +0000
Subject: [PATCH 0/3] firmware: arm_scmi: Minor cleanups in the scmi bus
 layer
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>

These cleanup centralizes error logging for SCMI device creation into a
single helper function, _scmi_device_create(), consolidates the device
matching logic into a single function, and ensures that devices must
have a name for registration, removing support for unnamed devices while
matching the devices and drivers for probing.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
Sudeep Holla (3):
      firmware: arm_scmi: Ensure scmi_devices are always matched by name as well
      firmware: arm_scmi: Refactor device matching logic to eliminate duplication
      firmware: arm_scmi: Refactor error logging from SCMI device creation to single helper

 drivers/firmware/arm_scmi/bus.c    | 75 ++++++++++++++++++++------------------
 drivers/firmware/arm_scmi/driver.c |  8 +---
 2 files changed, 40 insertions(+), 43 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250312-b4-scmi_minor_cleanup-8f85228d435c

Best regards,
-- 
Regards,
Sudeep



From sudeep.holla at arm.com  Wed Mar 12 04:40:25 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:40:25 +0000
Subject: [PATCH 2/3] firmware: arm_scmi: Refactor device matching logic to
 eliminate duplication
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-2-c62c6cb4111a@arm.com>

Currently, the device matching logic is duplicated in two functions:
  - scmi_dev_match() used by the scmi_bus to match scmi_devices with
    scmi_drivers.
  - scmi_child_dev_find() used to check for the presence of a device
    with the same name and protocol_id to avoid adding duplicates to
    the bus.

Refactor the code to eliminate the redundant matching logic and
consolidates the functionality for better maintainability and efficiency.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 43 +++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 050a5ff5dc96a7df58edff5faeb8c1ec6228b97d..a30fd8e05e423e226a63833f309d8d30c400fabd 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -206,52 +206,49 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
 		scmi_protocol_device_unrequest(entry);
 }
 
-static const struct scmi_device_id *
-scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_drv)
+static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
+				      const struct scmi_device_id *id_table)
 {
-	const struct scmi_device_id *id = scmi_drv->id_table;
+	if (!id_table || !id_table->name)
+		return 0;
 
-	if (!id)
-		return NULL;
-
-	for (; id->protocol_id && id->name; id++)
-		if (id->protocol_id == scmi_dev->protocol_id &&
-		    !strcmp(id->name, scmi_dev->name))
-			return id;
+	for (; id_table->protocol_id && id_table->name; id_table++)
+		if (id_table->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id_table->name, scmi_dev->name))
+			return 1;
+	return 0;
+}
 
-	return NULL;
+static int scmi_dev_match_id(struct scmi_device *scmi_dev,
+			     const struct scmi_driver *scmi_drv)
+{
+	return scmi_dev_match_by_id_table(scmi_dev, scmi_drv->id_table);
 }
 
 static int scmi_dev_match(struct device *dev, const struct device_driver *drv)
 {
 	const struct scmi_driver *scmi_drv = to_scmi_driver(drv);
 	struct scmi_device *scmi_dev = to_scmi_dev(dev);
-	const struct scmi_device_id *id;
-
-	id = scmi_dev_match_id(scmi_dev, scmi_drv);
-	if (id)
-		return 1;
 
-	return 0;
+	return scmi_dev_match_id(scmi_dev, scmi_drv);
 }
 
 static int scmi_match_by_id_table(struct device *dev, const void *data)
 {
-	struct scmi_device *sdev = to_scmi_dev(dev);
+	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 	const struct scmi_device_id *id_table = data;
 
-	return sdev->protocol_id == id_table->protocol_id &&
-		(id_table->name && !strcmp(sdev->name, id_table->name));
+	return scmi_dev_match_by_id_table(scmi_dev, id_table);
 }
 
 static struct scmi_device *scmi_child_dev_find(struct device *parent,
 					       int prot_id, const char *name)
 {
-	struct scmi_device_id id_table;
+	struct scmi_device_id id_table[2] = { 0 };
 	struct device *dev;
 
-	id_table.protocol_id = prot_id;
-	id_table.name = name;
+	id_table[0].protocol_id = prot_id;
+	id_table[0].name = name;
 
 	dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
 	if (!dev)

-- 
2.34.1



From sudeep.holla at arm.com  Wed Mar 12 04:40:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:40:24 +0000
Subject: [PATCH 1/3] firmware: arm_scmi: Ensure scmi_devices are always
 matched by name as well
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-1-c62c6cb4111a@arm.com>

Currently, devices without a name in the id_table cannot register drivers,
and no scmi_device is created without a name via scmi_device_create().
However, the function __scmi_device_create() allows devices with no name,
which are then labeled as "unknown."

Removes support for matching scmi_device instances without a name,
ensuring consistency across the driver registration and probing process.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a3386bf36de508d312e2c4fa2e27ba62ba3776a0..050a5ff5dc96a7df58edff5faeb8c1ec6228b97d 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -214,13 +214,10 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_d
 	if (!id)
 		return NULL;
 
-	for (; id->protocol_id; id++)
-		if (id->protocol_id == scmi_dev->protocol_id) {
-			if (!id->name)
-				return id;
-			else if (!strcmp(id->name, scmi_dev->name))
-				return id;
-		}
+	for (; id->protocol_id && id->name; id++)
+		if (id->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id->name, scmi_dev->name))
+			return id;
 
 	return NULL;
 }

-- 
2.34.1



From sudeep.holla at arm.com  Wed Mar 12 04:40:26 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 12 Mar 2025 11:40:26 +0000
Subject: [PATCH 3/3] firmware: arm_scmi: Refactor error logging from SCMI
 device creation to single helper
In-Reply-To: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
References: <20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a@arm.com>
Message-ID: <20250312-b4-scmi_minor_cleanup-v1-3-c62c6cb4111a@arm.com>

Refactors the error logging related to SCMI device creation. The goal
is to remove duplicated error-handling code and centralize it into a
single helper function: _scmi_device_create().

By doing so, any code redundancy around error logging is avoided, as
error logging during device creation will now be handled by a unified
helper function.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c    | 29 +++++++++++++++++++----------
 drivers/firmware/arm_scmi/driver.c |  8 +-------
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a30fd8e05e423e226a63833f309d8d30c400fabd..493e2c63b107fd9063f11034b71d65f567bb0778 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -411,6 +411,20 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 	return NULL;
 }
 
+static struct scmi_device *
+_scmi_device_create(struct device_node *np, struct device *parent,
+		    int protocol, const char *name)
+{
+	struct scmi_device *sdev;
+
+	sdev = __scmi_device_create(np, parent, protocol, name);
+	if (!sdev)
+		pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
+		       of_node_full_name(parent->of_node), protocol, name);
+
+	return sdev;
+}
+
 /**
  * scmi_device_create  - A method to create one or more SCMI devices
  *
@@ -443,7 +457,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	struct scmi_device *scmi_dev = NULL;
 
 	if (name)
-		return __scmi_device_create(np, parent, protocol, name);
+		return _scmi_device_create(np, parent, protocol, name);
 
 	mutex_lock(&scmi_requested_devices_mtx);
 	phead = idr_find(&scmi_requested_devices, protocol);
@@ -457,18 +471,13 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	list_for_each_entry(rdev, phead, node) {
 		struct scmi_device *sdev;
 
-		sdev = __scmi_device_create(np, parent,
-					    rdev->id_table->protocol_id,
-					    rdev->id_table->name);
-		/* Report errors and carry on... */
+		sdev = _scmi_device_create(np, parent,
+					   rdev->id_table->protocol_id,
+					   rdev->id_table->name);
 		if (sdev)
 			scmi_dev = sdev;
-		else
-			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
-			       of_node_full_name(parent->of_node),
-			       rdev->id_table->protocol_id,
-			       rdev->id_table->name);
 	}
+
 	mutex_unlock(&scmi_requested_devices_mtx);
 
 	return scmi_dev;
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 60050da54bf24c0245290e846f91aea62392855b..b80c574cb3bb2f12b2980fc844ea3da10abdc9f1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -439,14 +439,8 @@ static void scmi_create_protocol_devices(struct device_node *np,
 					 struct scmi_info *info,
 					 int prot_id, const char *name)
 {
-	struct scmi_device *sdev;
-
 	mutex_lock(&info->devreq_mtx);
-	sdev = scmi_device_create(np, info->dev, prot_id, name);
-	if (name && !sdev)
-		dev_err(info->dev,
-			"failed to create device for protocol 0x%X (%s)\n",
-			prot_id, name);
+	scmi_device_create(np, info->dev, prot_id, name);
 	mutex_unlock(&info->devreq_mtx);
 }
 

-- 
2.34.1



From peter.griffin at linaro.org  Wed Mar 12 04:40:56 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 11:40:56 +0000
Subject: [PATCH v4 2/4] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <c2e2c78c-e85e-406a-90a7-07d5b4fa82a6@kernel.org>
References: <20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036@linaro.org>
 <20250307-pinctrl-fltcon-suspend-v4-2-2d775e486036@linaro.org> <c2e2c78c-e85e-406a-90a7-07d5b4fa82a6@kernel.org>
Message-ID: <CADrjBPp9suYGifVR405k5KWqmGRnO1W5A6J28sWJVT2nGut1ag@mail.gmail.com>

Hi Krzysztof,

Thanks for the review feedback.

On Tue, 11 Mar 2025 at 19:32, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 07/03/2025 11:29, Peter Griffin wrote:
> > gs101 needs it's own suspend/resume callbacks to use the newly
> > added eint_fltcon_offset for saving & restoring fltcon0 & fltcon1
> > registers. It also differs to previous SoCs in that fltcon1
> > register doesn't always exist for each bank.
> >
> > exynosautov920 also has dedicated logic for using eint_con_offset
> > and eint_mask_offset for saving & restoring it's registers.
> >
> > Refactor the existing platform specific suspend/resume callback
> > so that each SoC variant has their own callback containing the
> > SoC specific logic.
> >
>
>
> > Additionally we now call drvdata->suspend() & drvdata->resume()
> > from within the loop that iterates the banks in
> > samsung_pinctrl_suspend() and samsung_pinctrl_resume().
> >
> > This simplifies the logic, and allows us to remove the
> > clk_enable() and clk_disable() from the callbacks.
>
> Can you make this a separate commit? This would be nicely self-contained
> and without any functional impact.

Sure I can split it out into two commits.

Thanks,

Peter

>
> Getting own suspend/resume would be the next commit.
>
>
> Best regards,
> Krzysztof


From akihiko.odaki at daynix.com  Wed Mar 12 04:55:58 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:58 +0900
Subject: [PATCH v3 4/6] KVM: arm64: PMU: Reload when user modifies
 registers
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-4-0411cab5dc3d@daynix.com>

Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
run") added the code to reload the PMU configuration on first run.

It is also important to keep the correct state even if system registers
are modified after first run, specifically when debugging Windows on
QEMU with GDB; QEMU tries to write back all visible registers when
resuming the VM execution with GDB, corrupting the PMU state. Windows
always uses the PMU so this can cause adverse effects on that particular
OS.

The usual register writes are already handled independently, but
register writes from userspace and ones for reset are not covered.
Trigger the code to reload the PMU configuration in these code paths
instead so that PMU configuration changes made by users will be applied
also after the first run.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 3 ---
 arch/arm64/kvm/sys_regs.c | 6 ++++++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 1cfe53b6353e..78cfa8b0964d 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -862,9 +862,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 		   return -EINVAL;
 	}
 
-	/* One-off reload of the PMU on first run */
-	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 26182cae4ac7..307ce37d0434 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1143,6 +1143,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
 	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 	return 0;
 }
 
@@ -1303,6 +1304,8 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 		val |= ARMV8_PMU_PMCR_LC;
 
 	__vcpu_sys_reg(vcpu, r->reg) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 
@@ -4259,6 +4262,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 	}
 
 	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
+
+	if (kvm_vcpu_has_pmu(vcpu))
+		kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 }
 
 /**

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 04:55:59 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:55:59 +0900
Subject: [PATCH v3 5/6] KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after
 masking PMCNTENSET_EL0
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-5-0411cab5dc3d@daynix.com>

kvm_pmu_handle_pmcr() expects PMCNTENSET_EL0 only contains valid
counters.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 78cfa8b0964d..2d19c6048091 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -831,11 +831,11 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 {
 	u64 mask = kvm_pmu_valid_counter_mask(vcpu);
 
-	kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
-
 	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask;
 	__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask;
 	__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask;
+
+	kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
 }
 
 int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 04:56:00 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 12 Mar 2025 20:56:00 +0900
Subject: [PATCH v3 6/6] KVM: arm64: Reload PMCNTENSET_EL0
In-Reply-To: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
Message-ID: <20250312-pmc-v3-6-0411cab5dc3d@daynix.com>

Disable counters that are no longer included in PMCNTENSET_EL0. It is
not necessary to enable counters included in PMCNTENSET_EL0 because
kvm_pmu_handle_pmcr() does so if appropriate.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 2d19c6048091..b14655dda6db 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -831,6 +831,8 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 {
 	u64 mask = kvm_pmu_valid_counter_mask(vcpu);
 
+	kvm_pmu_disable_counter_mask(vcpu, ~__vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
+
 	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask;
 	__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask;
 	__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask;

-- 
2.48.1



From krzk at kernel.org  Wed Mar 12 05:02:05 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 12 Mar 2025 13:02:05 +0100
Subject: [PATCH v5 2/2] memory: mtk-smi: mt8188: Add SMI reset and clamp
 for MT8188
In-Reply-To: <20250311122327.20685-3-friday.yang@mediatek.com>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
 <20250311122327.20685-3-friday.yang@mediatek.com>
Message-ID: <6008832c-e175-4b02-90a6-f790dacd1d09@kernel.org>

On 11/03/2025 13:23, Friday Yang wrote:
>  static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev)
>  {
>  	struct platform_device *smi_com_pdev;
> @@ -528,6 +598,53 @@ static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi,
>  	return ret;
>  }
> 
> +static int mtk_smi_larb_parse_clamp_optional(struct mtk_smi_larb *larb)
> +{
> +	struct device *dev = larb->dev;
> +	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
> +	u32 larb_id;
> +	int ret;
> +
> +	/**

Not a kerneldoc

> +	 * Only SMI LARBs in camera, image and IPE subsys need to
> +	 * apply clamp and reset operations, others can be skipped.
> +	 */
> +	ret = of_property_read_u32(dev->of_node, "mediatek,larb-id", &larb_id);


...


>  static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
>  	.type     = MTK_SMI_GEN2,
>  	.has_gals = true,
> @@ -729,6 +862,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
>  	{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
>  	{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
>  	{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
> +	{.compatible = "mediatek,mt8188-smi-sub-common", .data = &mtk_smi_sub_common_mt8188},
>  	{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
>  	{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
>  	{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
> @@ -787,7 +921,10 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
>  			return ret;
>  	}
> 
> -	pm_runtime_enable(dev);
> +	ret = devm_pm_runtime_enable(dev);
> +	if (ret)
> +		return ret;
> +
>  	platform_set_drvdata(pdev, common);
>  	return 0;
>  }
> @@ -798,7 +935,6 @@ static void mtk_smi_common_remove(struct platform_device *pdev)
> 
>  	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
>  		device_link_remove(&pdev->dev, common->smi_common_dev);
> -	pm_runtime_disable(&pdev->dev);
Does not look related to this patch. Is it some sort of cleanup to devm?

Best regards,
Krzysztof


From andrew at lunn.ch  Wed Mar 12 06:25:27 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 14:25:27 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <20250312095411.1392379-3-suraj.gupta2@amd.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
Message-ID: <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>

> +	/* AXI 1G/2.5G ethernet IP has following synthesis options:
> +	 * 1) SGMII/1000base-X only.
> +	 * 2) 2500base-X only.
> +	 * 3) Dynamically switching between (1) and (2), and is not
> +	 * implemented in driver.
> +	 */
> +
> +	if (axienet_ior(lp, XAE_ABILITY_OFFSET) & XAE_ABILITY_2_5G)

How can we tell if the synthesis allows 3)?

Don't we have a backwards compatibility issue here? Maybe there are
systems which have been synthesised with 3), but are currently limited
to 1) due to the driver. If you don't differentiate between 2 and 3,
such systems are going to swap to 2) and regress.

	Andrew


From cwabbott0 at gmail.com  Wed Mar 12 06:30:07 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 12 Mar 2025 09:30:07 -0400
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250312124907.GB6181@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
 <20250311181151.GD5216@willie-the-truck> <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>
 <20250312124907.GB6181@willie-the-truck>
Message-ID: <CACu1E7Hm=DWDC2aFdBRkT8f=8gKXJPpif_uEOA9iFZcyT-uCfQ@mail.gmail.com>

On Wed, Mar 12, 2025 at 8:49?AM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 11, 2025 at 04:01:00PM -0400, Connor Abbott wrote:
> > On Tue, Mar 11, 2025 at 2:11?PM Will Deacon <will at kernel.org> wrote:
> > >
> > > On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> > > > Up until now we have only called the set_stall callback during
> > > > initialization when the device is off. But we will soon start calling it
> > > > to temporarily disable stall-on-fault when the device is on, so handle
> > > > that by checking if the device is on and writing SCTLR.
> > > >
> > > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > > ---
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
> > > >  1 file changed, 27 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > > index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
> > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > > @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
> > > >  {
> > > >       struct arm_smmu_domain *smmu_domain = (void *)cookie;
> > > >       struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> > > > -     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> > > > +     struct arm_smmu_device *smmu = smmu_domain->smmu;
> > > > +     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > > > +     u32 mask = BIT(cfg->cbndx);
> > > > +     bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> > > > +     unsigned long flags;
> > > >
> > > >       if (enabled)
> > > > -             qsmmu->stall_enabled |= BIT(cfg->cbndx);
> > > > +             qsmmu->stall_enabled |= mask;
> > > >       else
> > > > -             qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> > > > +             qsmmu->stall_enabled &= ~mask;
> > > > +
> > > > +     /*
> > > > +      * If the device is on and we changed the setting, update the register.
> > > > +      */
> > > > +     if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> > > > +             spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> > > > +
> > > > +             u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> > > > +
> > > > +             if (enabled)
> > > > +                     reg |= ARM_SMMU_SCTLR_CFCFG;
> > > > +             else
> > > > +                     reg &= ~ARM_SMMU_SCTLR_CFCFG;
> > > > +
> > > > +             arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
> > >
> > > Are you sure you don't need TLB invalidation for this to take effect? I
> > > think some fields in the SCTLR can be cached in the TLB but you'll need
> > > to check whether or not that applies to CFCFG.
> > >
> >
> > I think it should be fine because CFCFG only controls behavior when
> > there's a context fault and there can't be TLB entries for entries
> > that cause a context fault: "The architecture permits the caching of
> > any translation table entry that has been returned from memory without
> > a fault and that does not, as a result of that entry, cause a
> > Translation Fault or an Access Flag fault."
>
> Ok, but what about other types of fault? For example, a permission fault
> or an address size fault?
>
> Will

I'm not sure, but the pseudocode for context faults mentions
resampling CFCFG after a fault happens ("We have a fault and must
resample FSR, CFCFG and HUPCF") so I don't think it would be legal to
cache it. Also in practice this does seem to work. Does that answer
it?

Connor


From robin.murphy at arm.com  Wed Mar 12 05:05:08 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 12:05:08 +0000
Subject: [PATCH v2 0/2] dmaengine: Add Arm DMA-350 driver
Message-ID: <cover.1741780808.git.robin.murphy@arm.com>

v1: https://lore.kernel.org/dmaengine/cover.1740762136.git.robin.murphy at arm.com/

Just a few minor tweaks for the issues flagged on v1.

Robin Murphy (2):
  dt-bindings: dma: Add Arm DMA-350
  dmaengine: Add Arm DMA-350 driver

 .../devicetree/bindings/dma/arm,dma-350.yaml  |  44 ++
 drivers/dma/Kconfig                           |   7 +
 drivers/dma/Makefile                          |   1 +
 drivers/dma/arm-dma350.c                      | 660 ++++++++++++++++++
 4 files changed, 712 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/arm,dma-350.yaml
 create mode 100644 drivers/dma/arm-dma350.c

-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Wed Mar 12 05:05:09 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 12:05:09 +0000
Subject: [PATCH v2 1/2] dt-bindings: dma: Add Arm DMA-350
In-Reply-To: <cover.1741780808.git.robin.murphy@arm.com>
References: <cover.1741780808.git.robin.murphy@arm.com>
Message-ID: <15830b2a8ff9721e364f30f93ea3993139b0103b.1741780808.git.robin.murphy@arm.com>

Arm CoreLink DMA-350 is a pleasantly straightforward DMA controller
which, although highly configurable, lends itself to a simple binding
thanks to plenty of self-describing ID registers.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
v2: No change

 .../devicetree/bindings/dma/arm,dma-350.yaml  | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/arm,dma-350.yaml

diff --git a/Documentation/devicetree/bindings/dma/arm,dma-350.yaml b/Documentation/devicetree/bindings/dma/arm,dma-350.yaml
new file mode 100644
index 000000000000..429f682f15d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/arm,dma-350.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/arm,dma-350.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Arm CoreLink DMA-350 Controller
+
+maintainers:
+  - Robin Murphy <robin.murphy at arm.com>
+
+allOf:
+  - $ref: dma-controller.yaml#
+
+properties:
+  compatible:
+    const: arm,dma-350
+
+  reg:
+    items:
+      - description: Base and size of the full register map
+
+  interrupts:
+    minItems: 1
+    items:
+      - description: Channel 0 interrupt
+      - description: Channel 1 interrupt
+      - description: Channel 2 interrupt
+      - description: Channel 3 interrupt
+      - description: Channel 4 interrupt
+      - description: Channel 5 interrupt
+      - description: Channel 6 interrupt
+      - description: Channel 7 interrupt
+
+  "#dma-cells":
+    const: 1
+    description: The cell is the trigger input number
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Wed Mar 12 05:05:10 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 12:05:10 +0000
Subject: [PATCH v2 2/2] dmaengine: Add Arm DMA-350 driver
In-Reply-To: <cover.1741780808.git.robin.murphy@arm.com>
References: <cover.1741780808.git.robin.murphy@arm.com>
Message-ID: <6d7d8efefa935d34977b59a74797ab377528db94.1741780808.git.robin.murphy@arm.com>

Add an initial driver for the Arm Corelink DMA-350 controller, to
support basic mem-to-mem async_tx. The design here leaves room for more
fun things like peripheral support and scatter-gather chaining to come
in future.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
v2:
 - Fix build warnings
 - Limit retries for reading live residue
---
 drivers/dma/Kconfig      |   7 +
 drivers/dma/Makefile     |   1 +
 drivers/dma/arm-dma350.c | 660 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 668 insertions(+)
 create mode 100644 drivers/dma/arm-dma350.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8afea2e23360..fa7d7f98e50f 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -93,6 +93,13 @@ config APPLE_ADMAC
 	help
 	  Enable support for Audio DMA Controller found on Apple Silicon SoCs.
 
+config ARM_DMA350
+	tristate "Arm DMA-350 support"
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Enable support for the Arm DMA-350 controller.
+
 config AT_HDMAC
 	tristate "Atmel AHB DMA support"
 	depends on ARCH_AT91
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 19ba465011a6..ba9732644752 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ALTERA_MSGDMA) += altera-msgdma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
 obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
 obj-$(CONFIG_APPLE_ADMAC) += apple-admac.o
+obj-$(CONFIG_ARM_DMA350) += arm-dma350.o
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
 obj-$(CONFIG_AT_XDMAC) += at_xdmac.o
 obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o
diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
new file mode 100644
index 000000000000..9efe2ca7d5ec
--- /dev/null
+++ b/drivers/dma/arm-dma350.c
@@ -0,0 +1,660 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2024-2025 Arm Limited
+// Arm DMA-350 driver
+
+#include <linux/bitfield.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+#define DMAINFO			0x0f00
+
+#define DMA_BUILDCFG0		0xb0
+#define DMA_CFG_DATA_WIDTH	GENMASK(18, 16)
+#define DMA_CFG_ADDR_WIDTH	GENMASK(15, 10)
+#define DMA_CFG_NUM_CHANNELS	GENMASK(9, 4)
+
+#define DMA_BUILDCFG1		0xb4
+#define DMA_CFG_NUM_TRIGGER_IN	GENMASK(8, 0)
+
+#define IIDR			0xc8
+#define IIDR_PRODUCTID		GENMASK(31, 20)
+#define IIDR_VARIANT		GENMASK(19, 16)
+#define IIDR_REVISION		GENMASK(15, 12)
+#define IIDR_IMPLEMENTER	GENMASK(11, 0)
+
+#define PRODUCTID_DMA350	0x3a0
+#define IMPLEMENTER_ARM		0x43b
+
+#define DMACH(n)		(0x1000 + 0x0100 * (n))
+
+#define CH_CMD			0x00
+#define CH_CMD_RESUME		BIT(5)
+#define CH_CMD_PAUSE		BIT(4)
+#define CH_CMD_STOP		BIT(3)
+#define CH_CMD_DISABLE		BIT(2)
+#define CH_CMD_CLEAR		BIT(1)
+#define CH_CMD_ENABLE		BIT(0)
+
+#define CH_STATUS		0x04
+#define CH_STAT_RESUMEWAIT	BIT(21)
+#define CH_STAT_PAUSED		BIT(20)
+#define CH_STAT_STOPPED		BIT(19)
+#define CH_STAT_DISABLED	BIT(18)
+#define CH_STAT_ERR		BIT(17)
+#define CH_STAT_DONE		BIT(16)
+#define CH_STAT_INTR_ERR	BIT(1)
+#define CH_STAT_INTR_DONE	BIT(0)
+
+#define CH_INTREN		0x08
+#define CH_INTREN_ERR		BIT(1)
+#define CH_INTREN_DONE		BIT(0)
+
+#define CH_CTRL			0x0c
+#define CH_CTRL_USEDESTRIGIN	BIT(26)
+#define CH_CTRL_USESRCTRIGIN	BIT(26)
+#define CH_CTRL_DONETYPE	GENMASK(23, 21)
+#define CH_CTRL_REGRELOADTYPE	GENMASK(20, 18)
+#define CH_CTRL_XTYPE		GENMASK(11, 9)
+#define CH_CTRL_TRANSIZE	GENMASK(2, 0)
+
+#define CH_SRCADDR		0x10
+#define CH_SRCADDRHI		0x14
+#define CH_DESADDR		0x18
+#define CH_DESADDRHI		0x1c
+#define CH_XSIZE		0x20
+#define CH_XSIZEHI		0x24
+#define CH_SRCTRANSCFG		0x28
+#define CH_DESTRANSCFG		0x2c
+#define CH_CFG_MAXBURSTLEN	GENMASK(19, 16)
+#define CH_CFG_PRIVATTR		BIT(11)
+#define CH_CFG_SHAREATTR	GENMASK(9, 8)
+#define CH_CFG_MEMATTR		GENMASK(7, 0)
+
+#define TRANSCFG_DEVICE					\
+	FIELD_PREP(CH_CFG_MAXBURSTLEN, 0xf) |		\
+	FIELD_PREP(CH_CFG_SHAREATTR, SHAREATTR_OSH) |	\
+	FIELD_PREP(CH_CFG_MEMATTR, MEMATTR_DEVICE)
+#define TRANSCFG_NC					\
+	FIELD_PREP(CH_CFG_MAXBURSTLEN, 0xf) |		\
+	FIELD_PREP(CH_CFG_SHAREATTR, SHAREATTR_OSH) |	\
+	FIELD_PREP(CH_CFG_MEMATTR, MEMATTR_NC)
+#define TRANSCFG_WB					\
+	FIELD_PREP(CH_CFG_MAXBURSTLEN, 0xf) |		\
+	FIELD_PREP(CH_CFG_SHAREATTR, SHAREATTR_ISH) |	\
+	FIELD_PREP(CH_CFG_MEMATTR, MEMATTR_WB)
+
+#define CH_XADDRINC		0x30
+#define CH_XY_DES		GENMASK(31, 16)
+#define CH_XY_SRC		GENMASK(15, 0)
+
+#define CH_FILLVAL		0x38
+#define CH_SRCTRIGINCFG		0x4c
+#define CH_DESTRIGINCFG		0x50
+#define CH_LINKATTR		0x70
+#define CH_LINK_SHAREATTR	GENMASK(9, 8)
+#define CH_LINK_MEMATTR		GENMASK(7, 0)
+
+#define CH_AUTOCFG		0x74
+#define CH_LINKADDR		0x78
+#define CH_LINKADDR_EN		BIT(0)
+
+#define CH_LINKADDRHI		0x7c
+#define CH_ERRINFO		0x90
+#define CH_ERRINFO_AXIRDPOISERR BIT(18)
+#define CH_ERRINFO_AXIWRRESPERR BIT(17)
+#define CH_ERRINFO_AXIRDRESPERR BIT(16)
+
+#define CH_BUILDCFG0		0xf8
+#define CH_CFG_INC_WIDTH	GENMASK(29, 26)
+#define CH_CFG_DATA_WIDTH	GENMASK(24, 22)
+#define CH_CFG_DATA_BUF_SIZE	GENMASK(7, 0)
+
+#define CH_BUILDCFG1		0xfc
+#define CH_CFG_HAS_CMDLINK	BIT(8)
+#define CH_CFG_HAS_TRIGSEL	BIT(7)
+#define CH_CFG_HAS_TRIGIN	BIT(5)
+#define CH_CFG_HAS_WRAP		BIT(1)
+
+
+#define LINK_REGCLEAR		BIT(0)
+#define LINK_INTREN		BIT(2)
+#define LINK_CTRL		BIT(3)
+#define LINK_SRCADDR		BIT(4)
+#define LINK_SRCADDRHI		BIT(5)
+#define LINK_DESADDR		BIT(6)
+#define LINK_DESADDRHI		BIT(7)
+#define LINK_XSIZE		BIT(8)
+#define LINK_XSIZEHI		BIT(9)
+#define LINK_SRCTRANSCFG	BIT(10)
+#define LINK_DESTRANSCFG	BIT(11)
+#define LINK_XADDRINC		BIT(12)
+#define LINK_FILLVAL		BIT(14)
+#define LINK_SRCTRIGINCFG	BIT(19)
+#define LINK_DESTRIGINCFG	BIT(20)
+#define LINK_AUTOCFG		BIT(29)
+#define LINK_LINKADDR		BIT(30)
+#define LINK_LINKADDRHI		BIT(31)
+
+
+enum ch_ctrl_donetype {
+	CH_CTRL_DONETYPE_NONE = 0,
+	CH_CTRL_DONETYPE_CMD = 1,
+	CH_CTRL_DONETYPE_CYCLE = 3
+};
+
+enum ch_ctrl_xtype {
+	CH_CTRL_XTYPE_DISABLE = 0,
+	CH_CTRL_XTYPE_CONTINUE = 1,
+	CH_CTRL_XTYPE_WRAP = 2,
+	CH_CTRL_XTYPE_FILL = 3
+};
+
+enum ch_cfg_shareattr {
+	SHAREATTR_NSH = 0,
+	SHAREATTR_OSH = 2,
+	SHAREATTR_ISH = 3
+};
+
+enum ch_cfg_memattr {
+	MEMATTR_DEVICE = 0x00,
+	MEMATTR_NC = 0x44,
+	MEMATTR_WB = 0xff
+};
+
+struct d350_desc {
+	struct virt_dma_desc vd;
+	u32 command[16];
+	u16 xsize;
+	u16 xsizehi;
+	u8 tsz;
+};
+
+struct d350_chan {
+	struct virt_dma_chan vc;
+	struct d350_desc *desc;
+	void __iomem *base;
+	int irq;
+	enum dma_status status;
+	dma_cookie_t cookie;
+	u32 residue;
+	u8 tsz;
+	bool has_trig;
+	bool has_wrap;
+	bool coherent;
+};
+
+struct d350 {
+	struct dma_device dma;
+	int nchan;
+	int nreq;
+	struct d350_chan channels[] __counted_by(nchan);
+};
+
+static inline struct d350_chan *to_d350_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct d350_chan, vc.chan);
+}
+
+static inline struct d350_desc *to_d350_desc(struct virt_dma_desc *vd)
+{
+	return container_of(vd, struct d350_desc, vd);
+}
+
+static void d350_desc_free(struct virt_dma_desc *vd)
+{
+	kfree(to_d350_desc(vd));
+}
+
+static struct dma_async_tx_descriptor *d350_prep_memcpy(struct dma_chan *chan,
+		dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	struct d350_desc *desc;
+	u32 *cmd;
+
+	desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+	if (!desc)
+		return NULL;
+
+	desc->tsz = __ffs(len | dest | src | (1 << dch->tsz));
+	desc->xsize = lower_16_bits(len >> desc->tsz);
+	desc->xsizehi = upper_16_bits(len >> desc->tsz);
+
+	cmd = desc->command;
+	cmd[0] = LINK_CTRL | LINK_SRCADDR | LINK_SRCADDRHI | LINK_DESADDR |
+		 LINK_DESADDRHI | LINK_XSIZE | LINK_XSIZEHI | LINK_SRCTRANSCFG |
+		 LINK_DESTRANSCFG | LINK_XADDRINC | LINK_LINKADDR;
+
+	cmd[1] = FIELD_PREP(CH_CTRL_TRANSIZE, desc->tsz) |
+		 FIELD_PREP(CH_CTRL_XTYPE, CH_CTRL_XTYPE_CONTINUE) |
+		 FIELD_PREP(CH_CTRL_DONETYPE, CH_CTRL_DONETYPE_CMD);
+
+	cmd[2] = lower_32_bits(src);
+	cmd[3] = upper_32_bits(src);
+	cmd[4] = lower_32_bits(dest);
+	cmd[5] = upper_32_bits(dest);
+	cmd[6] = FIELD_PREP(CH_XY_SRC, desc->xsize) | FIELD_PREP(CH_XY_DES, desc->xsize);
+	cmd[7] = FIELD_PREP(CH_XY_SRC, desc->xsizehi) | FIELD_PREP(CH_XY_DES, desc->xsizehi);
+	cmd[8] = dch->coherent ? TRANSCFG_WB : TRANSCFG_NC;
+	cmd[9] = dch->coherent ? TRANSCFG_WB : TRANSCFG_NC;
+	cmd[10] = FIELD_PREP(CH_XY_SRC, 1) | FIELD_PREP(CH_XY_DES, 1);
+	cmd[11] = 0;
+
+	return vchan_tx_prep(&dch->vc, &desc->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *d350_prep_memset(struct dma_chan *chan,
+		dma_addr_t dest, int value, size_t len, unsigned long flags)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	struct d350_desc *desc;
+	u32 *cmd;
+
+	desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+	if (!desc)
+		return NULL;
+
+	desc->tsz = __ffs(len | dest | (1 << dch->tsz));
+	desc->xsize = lower_16_bits(len >> desc->tsz);
+	desc->xsizehi = upper_16_bits(len >> desc->tsz);
+
+	cmd = desc->command;
+	cmd[0] = LINK_CTRL | LINK_DESADDR | LINK_DESADDRHI |
+		 LINK_XSIZE | LINK_XSIZEHI | LINK_DESTRANSCFG |
+		 LINK_XADDRINC | LINK_FILLVAL | LINK_LINKADDR;
+
+	cmd[1] = FIELD_PREP(CH_CTRL_TRANSIZE, desc->tsz) |
+		 FIELD_PREP(CH_CTRL_XTYPE, CH_CTRL_XTYPE_FILL) |
+		 FIELD_PREP(CH_CTRL_DONETYPE, CH_CTRL_DONETYPE_CMD);
+
+	cmd[2] = lower_32_bits(dest);
+	cmd[3] = upper_32_bits(dest);
+	cmd[4] = FIELD_PREP(CH_XY_DES, desc->xsize);
+	cmd[5] = FIELD_PREP(CH_XY_DES, desc->xsizehi);
+	cmd[6] = dch->coherent ? TRANSCFG_WB : TRANSCFG_NC;
+	cmd[7] = FIELD_PREP(CH_XY_DES, 1);
+	cmd[8] = (u8)value * 0x01010101;
+	cmd[9] = 0;
+
+	return vchan_tx_prep(&dch->vc, &desc->vd, flags);
+}
+
+static int d350_pause(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dch->vc.lock, flags);
+	if (dch->status == DMA_IN_PROGRESS) {
+		writel_relaxed(CH_CMD_PAUSE, dch->base + CH_CMD);
+		dch->status = DMA_PAUSED;
+	}
+	spin_unlock_irqrestore(&dch->vc.lock, flags);
+
+	return 0;
+}
+
+static int d350_resume(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dch->vc.lock, flags);
+	if (dch->status == DMA_PAUSED) {
+		writel_relaxed(CH_CMD_RESUME, dch->base + CH_CMD);
+		dch->status = DMA_IN_PROGRESS;
+	}
+	spin_unlock_irqrestore(&dch->vc.lock, flags);
+
+	return 0;
+}
+
+static u32 d350_get_residue(struct d350_chan *dch)
+{
+	u32 res, xsize, xsizehi, hi_new;
+	int retries = 3; /* 1st time unlucky, 2nd improbable, 3rd just broken */
+
+	hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
+	do {
+		xsizehi = hi_new;
+		xsize = readl_relaxed(dch->base + CH_XSIZE);
+		hi_new = readl_relaxed(dch->base + CH_XSIZEHI);
+	} while (xsizehi != hi_new && --retries);
+
+	res = FIELD_GET(CH_XY_DES, xsize);
+	res |= FIELD_GET(CH_XY_DES, xsizehi) << 16;
+
+	return res << dch->desc->tsz;
+}
+
+static int d350_terminate_all(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&dch->vc.lock, flags);
+	writel_relaxed(CH_CMD_STOP, dch->base + CH_CMD);
+	if (dch->desc) {
+		if (dch->status != DMA_ERROR)
+			vchan_terminate_vdesc(&dch->desc->vd);
+		dch->desc = NULL;
+		dch->status = DMA_COMPLETE;
+	}
+	vchan_get_all_descriptors(&dch->vc, &list);
+	list_splice_tail(&list, &dch->vc.desc_terminated);
+	spin_unlock_irqrestore(&dch->vc.lock, flags);
+
+	return 0;
+}
+
+static void d350_synchronize(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+
+	vchan_synchronize(&dch->vc);
+}
+
+static u32 d350_desc_bytes(struct d350_desc *desc)
+{
+	return ((u32)desc->xsizehi << 16 | desc->xsize) << desc->tsz;
+}
+
+static enum dma_status d350_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+				      struct dma_tx_state *state)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	struct virt_dma_desc *vd;
+	enum dma_status status;
+	unsigned long flags;
+	u32 residue = 0;
+
+	status = dma_cookie_status(chan, cookie, state);
+
+	spin_lock_irqsave(&dch->vc.lock, flags);
+	if (cookie == dch->cookie) {
+		status = dch->status;
+		if (status == DMA_IN_PROGRESS || status == DMA_PAUSED)
+			dch->residue = d350_get_residue(dch);
+		residue = dch->residue;
+	} else if ((vd = vchan_find_desc(&dch->vc, cookie))) {
+		residue = d350_desc_bytes(to_d350_desc(vd));
+	} else if (status == DMA_IN_PROGRESS) {
+		/* Somebody else terminated it? */
+		status = DMA_ERROR;
+	}
+	spin_unlock_irqrestore(&dch->vc.lock, flags);
+
+	dma_set_residue(state, residue);
+	return status;
+}
+
+static void d350_start_next(struct d350_chan *dch)
+{
+	u32 hdr, *reg;
+
+	dch->desc = to_d350_desc(vchan_next_desc(&dch->vc));
+	if (!dch->desc)
+		return;
+
+	list_del(&dch->desc->vd.node);
+	dch->status = DMA_IN_PROGRESS;
+	dch->cookie = dch->desc->vd.tx.cookie;
+	dch->residue = d350_desc_bytes(dch->desc);
+
+	hdr = dch->desc->command[0];
+	reg = &dch->desc->command[1];
+
+	if (hdr & LINK_INTREN)
+		writel_relaxed(*reg++, dch->base + CH_INTREN);
+	if (hdr & LINK_CTRL)
+		writel_relaxed(*reg++, dch->base + CH_CTRL);
+	if (hdr & LINK_SRCADDR)
+		writel_relaxed(*reg++, dch->base + CH_SRCADDR);
+	if (hdr & LINK_SRCADDRHI)
+		writel_relaxed(*reg++, dch->base + CH_SRCADDRHI);
+	if (hdr & LINK_DESADDR)
+		writel_relaxed(*reg++, dch->base + CH_DESADDR);
+	if (hdr & LINK_DESADDRHI)
+		writel_relaxed(*reg++, dch->base + CH_DESADDRHI);
+	if (hdr & LINK_XSIZE)
+		writel_relaxed(*reg++, dch->base + CH_XSIZE);
+	if (hdr & LINK_XSIZEHI)
+		writel_relaxed(*reg++, dch->base + CH_XSIZEHI);
+	if (hdr & LINK_SRCTRANSCFG)
+		writel_relaxed(*reg++, dch->base + CH_SRCTRANSCFG);
+	if (hdr & LINK_DESTRANSCFG)
+		writel_relaxed(*reg++, dch->base + CH_DESTRANSCFG);
+	if (hdr & LINK_XADDRINC)
+		writel_relaxed(*reg++, dch->base + CH_XADDRINC);
+	if (hdr & LINK_FILLVAL)
+		writel_relaxed(*reg++, dch->base + CH_FILLVAL);
+	if (hdr & LINK_SRCTRIGINCFG)
+		writel_relaxed(*reg++, dch->base + CH_SRCTRIGINCFG);
+	if (hdr & LINK_DESTRIGINCFG)
+		writel_relaxed(*reg++, dch->base + CH_DESTRIGINCFG);
+	if (hdr & LINK_AUTOCFG)
+		writel_relaxed(*reg++, dch->base + CH_AUTOCFG);
+	if (hdr & LINK_LINKADDR)
+		writel_relaxed(*reg++, dch->base + CH_LINKADDR);
+	if (hdr & LINK_LINKADDRHI)
+		writel_relaxed(*reg++, dch->base + CH_LINKADDRHI);
+
+	writel(CH_CMD_ENABLE, dch->base + CH_CMD);
+}
+
+static void d350_issue_pending(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dch->vc.lock, flags);
+	if (vchan_issue_pending(&dch->vc) && !dch->desc)
+		d350_start_next(dch);
+	spin_unlock_irqrestore(&dch->vc.lock, flags);
+}
+
+static irqreturn_t d350_irq(int irq, void *data)
+{
+	struct d350_chan *dch = data;
+	struct device *dev = dch->vc.chan.device->dev;
+	struct virt_dma_desc *vd = &dch->desc->vd;
+	u32 ch_status;
+
+	ch_status = readl(dch->base + CH_STATUS);
+	if (!ch_status)
+		return IRQ_NONE;
+
+	if (ch_status & CH_STAT_INTR_ERR) {
+		u32 errinfo = readl_relaxed(dch->base + CH_ERRINFO);
+
+		if (errinfo & (CH_ERRINFO_AXIRDPOISERR | CH_ERRINFO_AXIRDRESPERR))
+			vd->tx_result.result = DMA_TRANS_READ_FAILED;
+		else if (errinfo & CH_ERRINFO_AXIWRRESPERR)
+			vd->tx_result.result = DMA_TRANS_WRITE_FAILED;
+		else
+			vd->tx_result.result = DMA_TRANS_ABORTED;
+
+		vd->tx_result.residue = d350_get_residue(dch);
+	} else if (!(ch_status & CH_STAT_INTR_DONE)) {
+		dev_warn(dev, "Unexpected IRQ source? 0x%08x\n", ch_status);
+	}
+	writel_relaxed(ch_status, dch->base + CH_STATUS);
+
+	spin_lock(&dch->vc.lock);
+	vchan_cookie_complete(vd);
+	if (ch_status & CH_STAT_INTR_DONE) {
+		dch->status = DMA_COMPLETE;
+		dch->residue = 0;
+		d350_start_next(dch);
+	} else {
+		dch->status = DMA_ERROR;
+		dch->residue = vd->tx_result.residue;
+	}
+	spin_unlock(&dch->vc.lock);
+
+	return IRQ_HANDLED;
+}
+
+static int d350_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+	int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED,
+			      dev_name(&dch->vc.chan.dev->device), dch);
+	if (!ret)
+		writel_relaxed(CH_INTREN_DONE | CH_INTREN_ERR, dch->base + CH_INTREN);
+
+	return ret;
+}
+
+static void d350_free_chan_resources(struct dma_chan *chan)
+{
+	struct d350_chan *dch = to_d350_chan(chan);
+
+	writel_relaxed(0, dch->base + CH_INTREN);
+	free_irq(dch->irq, dch);
+	vchan_free_chan_resources(&dch->vc);
+}
+
+static int d350_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct d350 *dmac;
+	void __iomem *base;
+	u32 reg;
+	int ret, nchan, dw, aw, r, p;
+	bool coherent, memset;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	reg = readl_relaxed(base + DMAINFO + IIDR);
+	r = FIELD_GET(IIDR_VARIANT, reg);
+	p = FIELD_GET(IIDR_REVISION, reg);
+	if (FIELD_GET(IIDR_IMPLEMENTER, reg) != IMPLEMENTER_ARM ||
+	    FIELD_GET(IIDR_PRODUCTID, reg) != PRODUCTID_DMA350)
+		return dev_err_probe(dev, -ENODEV, "Not a DMA-350!");
+
+	reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG0);
+	nchan = FIELD_GET(DMA_CFG_NUM_CHANNELS, reg) + 1;
+	dw = 1 << FIELD_GET(DMA_CFG_DATA_WIDTH, reg);
+	aw = FIELD_GET(DMA_CFG_ADDR_WIDTH, reg) + 1;
+
+	dma_set_mask_and_coherent(dev, DMA_BIT_MASK(aw));
+	coherent = device_get_dma_attr(dev) == DEV_DMA_COHERENT;
+
+	dmac = devm_kzalloc(dev, struct_size(dmac, channels, nchan), GFP_KERNEL);
+	if (!dmac)
+		return -ENOMEM;
+
+	dmac->nchan = nchan;
+
+	reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG1);
+	dmac->nreq = FIELD_GET(DMA_CFG_NUM_TRIGGER_IN, reg);
+
+	dev_dbg(dev, "DMA-350 r%dp%d with %d channels, %d requests\n", r, p, dmac->nchan, dmac->nreq);
+
+	dmac->dma.dev = dev;
+	for (int i = min(dw, 16); i > 0; i /= 2) {
+		dmac->dma.src_addr_widths |= BIT(i);
+		dmac->dma.dst_addr_widths |= BIT(i);
+	}
+	dmac->dma.directions = BIT(DMA_MEM_TO_MEM);
+	dmac->dma.descriptor_reuse = true;
+	dmac->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+	dmac->dma.device_alloc_chan_resources = d350_alloc_chan_resources;
+	dmac->dma.device_free_chan_resources = d350_free_chan_resources;
+	dma_cap_set(DMA_MEMCPY, dmac->dma.cap_mask);
+	dmac->dma.device_prep_dma_memcpy = d350_prep_memcpy;
+	dmac->dma.device_pause = d350_pause;
+	dmac->dma.device_resume = d350_resume;
+	dmac->dma.device_terminate_all = d350_terminate_all;
+	dmac->dma.device_synchronize = d350_synchronize;
+	dmac->dma.device_tx_status = d350_tx_status;
+	dmac->dma.device_issue_pending = d350_issue_pending;
+	INIT_LIST_HEAD(&dmac->dma.channels);
+
+	/* Would be nice to have per-channel caps for this... */
+	memset = true;
+	for (int i = 0; i < nchan; i++) {
+		struct d350_chan *dch = &dmac->channels[i];
+
+		dch->base = base + DMACH(i);
+		writel_relaxed(CH_CMD_CLEAR, dch->base + CH_CMD);
+
+		reg = readl_relaxed(dch->base + CH_BUILDCFG1);
+		if (!(FIELD_GET(CH_CFG_HAS_CMDLINK, reg))) {
+			dev_warn(dev, "No command link support on channel %d\n", i);
+			continue;
+		}
+		dch->irq = platform_get_irq(pdev, i);
+		if (dch->irq < 0)
+			return dev_err_probe(dev, dch->irq,
+					     "Failed to get IRQ for channel %d\n", i);
+
+		dch->has_wrap = FIELD_GET(CH_CFG_HAS_WRAP, reg);
+		dch->has_trig = FIELD_GET(CH_CFG_HAS_TRIGIN, reg) &
+				FIELD_GET(CH_CFG_HAS_TRIGSEL, reg);
+
+		/* Fill is a special case of Wrap */
+		memset &= dch->has_wrap;
+
+		reg = readl_relaxed(dch->base + CH_BUILDCFG0);
+		dch->tsz = FIELD_GET(CH_CFG_DATA_WIDTH, reg);
+
+		reg = FIELD_PREP(CH_LINK_SHAREATTR, coherent ? SHAREATTR_ISH : SHAREATTR_OSH);
+		reg |= FIELD_PREP(CH_LINK_MEMATTR, coherent ? MEMATTR_WB : MEMATTR_NC);
+		writel_relaxed(reg, dch->base + CH_LINKATTR);
+
+		dch->vc.desc_free = d350_desc_free;
+		vchan_init(&dch->vc, &dmac->dma);
+	}
+
+	if (memset) {
+		dma_cap_set(DMA_MEMSET, dmac->dma.cap_mask);
+		dmac->dma.device_prep_dma_memset = d350_prep_memset;
+	}
+
+	platform_set_drvdata(pdev, dmac);
+
+	ret = dma_async_device_register(&dmac->dma);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to register DMA device\n");
+
+	return 0;
+}
+
+static void d350_remove(struct platform_device *pdev)
+{
+	struct d350 *dmac = platform_get_drvdata(pdev);
+
+	dma_async_device_unregister(&dmac->dma);
+}
+
+static const struct of_device_id d350_of_match[] __maybe_unused = {
+	{ .compatible = "arm,dma-350" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, d350_of_match);
+
+static struct platform_driver d350_driver = {
+	.driver = {
+		.name = "arm-dma350",
+		.of_match_table = of_match_ptr(d350_of_match),
+	},
+	.probe = d350_probe,
+	.remove = d350_remove,
+};
+module_platform_driver(d350_driver);
+
+MODULE_AUTHOR("Robin Murphy <robin.murphy at arm.com>");
+MODULE_DESCRIPTION("Arm DMA-350 driver");
+MODULE_LICENSE("GPL v2");
-- 
2.39.2.101.g768bb238c484.dirty



From andrew at lunn.ch  Wed Mar 12 05:11:48 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 13:11:48 +0100
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250312045802.4115029-1-wthai@nvidia.com>
References: <20250312045802.4115029-1-wthai@nvidia.com>
Message-ID: <9ccc845b-9392-4a37-8bca-4f54997126ce@lunn.ch>

> +&mac0 {
> +	status = "okay";
> +	pinctrl-names = "default";
> +	phy-mode = "rgmii";
> +	phy-handle = <&ethphy3>;
> +	pinctrl-0 = <&pinctrl_rgmii1_default>;
> +};

Please read the discussion again. "rgmii" is probably equally wrong as
"rgmii-rxid" you had in v1.

Please talk with Aspeed and ask them the clean up the mess they made
with RGMII delays. Until that happens, adding this node should wait.

     Andrew


From purvayeshi550 at gmail.com  Wed Mar 12 05:27:50 2025
From: purvayeshi550 at gmail.com (Purva Yeshi)
Date: Wed, 12 Mar 2025 17:57:50 +0530
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
Message-ID: <20250312122750.6391-1-purvayeshi550@gmail.com>

Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
YAML schema (`nxp,lpc3220-pwm.yaml`).

Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.

Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
---
V1 - https://lore.kernel.org/all/20250311125756.24064-1-purvayeshi550 at gmail.com/
V2 - Correct filename to match the compatible string, remove unnecessary
quotes in maintainers, and refine commit message.

 .../devicetree/bindings/pwm/lpc32xx-pwm.txt   | 17 ---------
 .../bindings/pwm/nxp,lpc3220-pwm.yaml         | 38 +++++++++++++++++++
 2 files changed, 38 insertions(+), 17 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
 create mode 100644 Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml

diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
deleted file mode 100644
index 74b5bc5dd..000000000
--- a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-LPC32XX PWM controller
-
-Required properties:
-- compatible: should be "nxp,lpc3220-pwm"
-- reg: physical base address and length of the controller's registers
-
-Examples:
-
-pwm at 4005c000 {
-	compatible = "nxp,lpc3220-pwm";
-	reg = <0x4005c000 0x4>;
-};
-
-pwm at 4005c004 {
-	compatible = "nxp,lpc3220-pwm";
-	reg = <0x4005c004 0x4>;
-};
diff --git a/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml b/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml
new file mode 100644
index 000000000..432a5e9d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/nxp,lpc3220-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPC32XX PWM controller
+
+maintainers:
+  - Vladimir Zapolskiy <vz at mleia.com>
+  - Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    const: nxp,lpc3220-pwm
+
+  reg:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    pwm at 4005c000 {
+        compatible = "nxp,lpc3220-pwm";
+        reg = <0x4005c000 0x4>;
+        #pwm-cells = <3>;
+    };
-- 
2.34.1



From csokas.bence at prolan.hu  Wed Mar 12 05:30:45 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Wed, 12 Mar 2025 13:30:45 +0100
Subject: [v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <9ef781b0-8a63-42b7-91a2-fa8a8ea3c0b4@web.de>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
 <885ceb3e-d6c6-4e7b-a3b6-585d2d110ccf@web.de>
 <81f87d39-d3f8-4b6a-91cb-b0177d34171b@prolan.hu>
 <9ef781b0-8a63-42b7-91a2-fa8a8ea3c0b4@web.de>
Message-ID: <505c2e3b-f1bb-4e3a-96f2-eef0d0d682e6@prolan.hu>

Hi,

On 2025. 03. 12. 12:44, Markus Elfring wrote:
>>> How good does such a change combination fit to the patch requirement
>>> according to separation of concerns?
>>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc6#n81
>>
>> It is a general refactor patch, it shouldn't change any functionality. I could split it to one part introducing `devm_clk_get_enabled()` and the other `dmaenginem_async_device_register()`, but I don't feel that to be necessary, nor does it bring any advantages I believe.
> Can it matter a bit more to separate changes for the application of devm functions
> and the adjustment of corresponding exception handling with dev_err_probe() calls?

The change in error handling is just the result of switching to devm 
functions, because it is no longer needed to separately dev_err(), store 
the error code to `ret` and goto a cleanup phase (as the whole point of 
using devm functions is to have auto-cleanup), you can just return with 
the error code (which dev_err_probe() returns for us) right away. The 
devm functions are used precisely _because_ they allow us to simplify 
this error handling.

> Regards,
> Markus

Bence



From lumag at kernel.org  Wed Mar 12 05:37:13 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Wed, 12 Mar 2025 14:37:13 +0200
Subject: [PATCH v2 3/7] drm/rockchip: Add RK3588 DPTX output support
In-Reply-To: <20250312104214.525242-4-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-4-andyshrk@163.com>
Message-ID: <m2376n5bdptphdbyxxqvgeouspn7vslucprgzu25shoajzndy3@gfxh3b2poiic>

On Wed, Mar 12, 2025 at 06:42:04PM +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Add driver extension for Synopsys DesignWare DPTX IP used
> on Rockchip RK3588 SoC.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> 
> ---
> 
> Changes in v2:
> - no include uapi path
> - switch to drmm_encoder_init

Acked-by: Dmitry Baryshkov <lumag at kernel.org>
> 
-- 
With best wishes
Dmitry


From lumag at kernel.org  Wed Mar 12 05:39:17 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Wed, 12 Mar 2025 14:39:17 +0200
Subject: [PATCH v2 7/7] arm64: dts: rockchip: Enable DP2HDMI for ROCK 5
 ITX
In-Reply-To: <20250312104214.525242-8-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-8-andyshrk@163.com>
Message-ID: <q3y36jgswj4xa2g3hnptc6kgzphbqfg675r5paa2lwvdseytio@jysj4f2i6osu>

On Wed, Mar 12, 2025 at 06:42:08PM +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> The HDMI Port next to Headphone Jack is drived by
> DP1 on rk3588 via a dp2hdmi converter.
> 
> Add related dt nodes to enable it.
> 
> Note: ROCKCHIP_VOP2_EP_DP1 is defined as 11 in dt-binding header,
> but it will trigger a dtc warning like "graph node unit address
> error, expected "b"" if we use it directly after endpoint, so we
> use "b" instead here.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
> (no changes since v1)
> 
>  .../boot/dts/rockchip/rk3588-rock-5-itx.dts   | 37 +++++++++++++++++++
>  1 file changed, 37 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> index 67b886329248..29f10ec9f0c1 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> @@ -57,6 +57,18 @@ analog-sound {
>  			  "Headphone", "Headphones";
>  	};
>  
> +	dp-con {
> +		compatible = "dp-connector";

You've written that it is an HDMI connector. Could you possibly clarify,
why is it being registered as a DP connector? Is there any kind of
a bridge between the DP controller and the HDMI connector?

> +		label = "DP OUT";
> +		type = "full-size";
> +
> +		port {
> +			dp_con_in: endpoint {
> +				remote-endpoint = <&dp1_out_con>;
> +			};
> +		};
> +	};
> +
>  	gpio-leds {
>  		compatible = "gpio-leds";
>  		pinctrl-names = "default";
> @@ -268,6 +280,24 @@ &cpu_l3 {
>  	cpu-supply = <&vdd_cpu_lit_s0>;
>  };
>  
> +&dp1 {
> +	status = "okay";
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&dp1m0_pins>;
> +};
> +
> +&dp1_in {
> +	dp1_in_vp2: endpoint {
> +		remote-endpoint = <&vp2_out_dp1>;
> +	};
> +};
> +
> +&dp1_out {
> +	dp1_out_con: endpoint {
> +		remote-endpoint = <&dp_con_in>;
> +	};
> +};
> +
>  &gpu {
>  	mali-supply = <&vdd_gpu_s0>;
>  	status = "okay";
> @@ -1262,3 +1292,10 @@ vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
>  		remote-endpoint = <&hdmi1_in_vp1>;
>  	};
>  };
> +
> +&vp2 {
> +	vp2_out_dp1: endpoint at b {
> +		reg = <ROCKCHIP_VOP2_EP_DP1>;
> +		remote-endpoint = <&dp1_in_vp2>;
> +	};
> +};
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


From wens at kernel.org  Wed Mar 12 05:42:06 2025
From: wens at kernel.org (Chen-Yu Tsai)
Date: Wed, 12 Mar 2025 20:42:06 +0800
Subject: [PATCH netdev v2] net: stmmac: dwmac-rk: Provide FIFO sizes for DWMAC 1000
Message-ID: <20250312124206.2108476-1-wens@kernel.org>

From: Chen-Yu Tsai <wens at csie.org>

The DWMAC 1000 DMA capabilities register does not provide actual
FIFO sizes, nor does the driver really care. If they are not
provided via some other means, the driver will work fine, only
disallowing changing the MTU setting.

Provide the FIFO sizes through the driver's platform data to enable
MTU changes. The FIFO sizes are confirmed to be the same across RK3288,
RK3328, RK3399 and PX30, based on their respective manuals. It is
likely that Rockchip synthesized their DWMAC 1000 with the same
parameters on all their chips that have it.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
Changes since v1:
- Removed references to breakage from commit message as it is already fixed
- Removed Cc stable and Fixes tags
- Rebased onto latest -next
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..e57181ce5f84 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1969,8 +1969,11 @@ static int rk_gmac_probe(struct platform_device *pdev)
 	/* If the stmmac is not already selected as gmac4,
 	 * then make sure we fallback to gmac.
 	 */
-	if (!plat_dat->has_gmac4)
+	if (!plat_dat->has_gmac4) {
 		plat_dat->has_gmac = true;
+		plat_dat->rx_fifo_size = 4096;
+		plat_dat->tx_fifo_size = 2048;
+	}
 
 	plat_dat->set_clk_tx_rate = rk_set_clk_tx_rate;
 
-- 
2.39.5



From smostafa at google.com  Wed Mar 12 05:45:04 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 12:45:04 +0000
Subject: [PATCH v3 07/23] iommu/pages: De-inline the substantial functions
In-Reply-To: <7-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <7-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9GB0IcNc2432dki@google.com>

On Tue, Feb 25, 2025 at 03:39:24PM -0400, Jason Gunthorpe wrote:
> These are called in a lot of places and are not trivial. Move them to the
> core module.
> 
> Tidy some of the comments and function arguments, fold
> __iommu_alloc_account() into its only caller, change
> __iommu_free_account() into __iommu_free_page() to remove some
> duplication.
> 
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>

> ---
>  drivers/iommu/Makefile      |   1 +
>  drivers/iommu/iommu-pages.c |  84 +++++++++++++++++++++++++++++
>  drivers/iommu/iommu-pages.h | 103 ++----------------------------------
>  3 files changed, 90 insertions(+), 98 deletions(-)
>  create mode 100644 drivers/iommu/iommu-pages.c
> 
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index 5e5a83c6c2aae2..fe91d770abe16c 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-y += amd/ intel/ arm/ iommufd/ riscv/
>  obj-$(CONFIG_IOMMU_API) += iommu.o
> +obj-$(CONFIG_IOMMU_SUPPORT) += iommu-pages.o
>  obj-$(CONFIG_IOMMU_API) += iommu-traces.o
>  obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
>  obj-$(CONFIG_IOMMU_DEBUGFS) += iommu-debugfs.o
> diff --git a/drivers/iommu/iommu-pages.c b/drivers/iommu/iommu-pages.c
> new file mode 100644
> index 00000000000000..31ff83ffaf0106
> --- /dev/null
> +++ b/drivers/iommu/iommu-pages.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024, Google LLC.
> + * Pasha Tatashin <pasha.tatashin at soleen.com>
> + */
> +#include "iommu-pages.h"
> +#include <linux/gfp.h>
> +#include <linux/mm.h>
> +
> +/**
> + * iommu_alloc_pages_node - Allocate a zeroed page of a given order from
> + *                          specific NUMA node
> + * @nid: memory NUMA node id
> + * @gfp: buddy allocator flags
> + * @order: page order
> + *
> + * Returns the virtual address of the allocated page. The page must be
> + * freed either by calling iommu_free_pages() or via iommu_put_pages_list().
> + */
> +void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order)
> +{
> +	const unsigned long pgcnt = 1UL << order;
> +	struct page *page;
> +
> +	page = alloc_pages_node(nid, gfp | __GFP_ZERO | __GFP_COMP, order);
> +	if (unlikely(!page))
> +		return NULL;
> +
> +	/*
> +	 * All page allocations that should be reported to as "iommu-pagetables"
> +	 * to userspace must use one of the functions below. This includes
> +	 * allocations of page-tables and other per-iommu_domain configuration
> +	 * structures.
> +	 *
> +	 * This is necessary for the proper accounting as IOMMU state can be
> +	 * rather large, i.e. multiple gigabytes in size.
> +	 */
> +	mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, pgcnt);
> +	mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, pgcnt);
> +
> +	return page_address(page);
> +}
> +EXPORT_SYMBOL_GPL(iommu_alloc_pages_node);
> +
> +static void __iommu_free_page(struct page *page)
> +{
> +	unsigned int order = folio_order(page_folio(page));
> +	const unsigned long pgcnt = 1UL << order;
> +
> +	mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, -pgcnt);
> +	mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, -pgcnt);
> +	put_page(page);
> +}
> +
> +/**
> + * iommu_free_pages - free pages
> + * @virt: virtual address of the page to be freed.
> + *
> + * The page must have have been allocated by iommu_alloc_pages_node()
> + */
> +void iommu_free_pages(void *virt)
> +{
> +	if (!virt)
> +		return;
> +	__iommu_free_page(virt_to_page(virt));
> +}
> +EXPORT_SYMBOL_GPL(iommu_free_pages);
> +
> +/**
> + * iommu_put_pages_list - free a list of pages.
> + * @head: the head of the lru list to be freed.
> + *
> + * Frees a list of pages allocated by iommu_alloc_pages_node().
> + */
> +void iommu_put_pages_list(struct list_head *head)
> +{
> +	while (!list_empty(head)) {
> +		struct page *p = list_entry(head->prev, struct page, lru);
> +
> +		list_del(&p->lru);
> +		__iommu_free_page(p);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(iommu_put_pages_list);
> diff --git a/drivers/iommu/iommu-pages.h b/drivers/iommu/iommu-pages.h
> index fcd17b94f7b830..e3c35aa14ad716 100644
> --- a/drivers/iommu/iommu-pages.h
> +++ b/drivers/iommu/iommu-pages.h
> @@ -7,67 +7,12 @@
>  #ifndef __IOMMU_PAGES_H
>  #define __IOMMU_PAGES_H
>  
> -#include <linux/vmstat.h>
> -#include <linux/gfp.h>
> -#include <linux/mm.h>
> +#include <linux/types.h>
> +#include <linux/topology.h>
>  
> -/*
> - * All page allocations that should be reported to as "iommu-pagetables" to
> - * userspace must use one of the functions below.  This includes allocations of
> - * page-tables and other per-iommu_domain configuration structures.
> - *
> - * This is necessary for the proper accounting as IOMMU state can be rather
> - * large, i.e. multiple gigabytes in size.
> - */
> -
> -/**
> - * __iommu_alloc_account - account for newly allocated page.
> - * @page: head struct page of the page.
> - * @order: order of the page
> - */
> -static inline void __iommu_alloc_account(struct page *page, int order)
> -{
> -	const long pgcnt = 1l << order;
> -
> -	mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, pgcnt);
> -	mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, pgcnt);
> -}
> -
> -/**
> - * __iommu_free_account - account a page that is about to be freed.
> - * @page: head struct page of the page.
> - * @order: order of the page
> - */
> -static inline void __iommu_free_account(struct page *page)
> -{
> -	unsigned int order = folio_order(page_folio(page));
> -	const long pgcnt = 1l << order;
> -
> -	mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, -pgcnt);
> -	mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, -pgcnt);
> -}
> -
> -/**
> - * iommu_alloc_pages_node - allocate a zeroed page of a given order from
> - * specific NUMA node.
> - * @nid: memory NUMA node id
> - * @gfp: buddy allocator flags
> - * @order: page order
> - *
> - * returns the virtual address of the allocated page
> - */
> -static inline void *iommu_alloc_pages_node(int nid, gfp_t gfp, int order)
> -{
> -	struct page *page =
> -		alloc_pages_node(nid, gfp | __GFP_ZERO | __GFP_COMP, order);
> -
> -	if (unlikely(!page))
> -		return NULL;
> -
> -	__iommu_alloc_account(page, order);
> -
> -	return page_address(page);
> -}
> +void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order);
> +void iommu_free_pages(void *virt);
> +void iommu_put_pages_list(struct list_head *head);
>  
>  /**
>   * iommu_alloc_pages - allocate a zeroed page of a given order
> @@ -104,42 +49,4 @@ static inline void *iommu_alloc_page(gfp_t gfp)
>  	return iommu_alloc_pages_node(numa_node_id(), gfp, 0);
>  }
>  
> -/**
> - * iommu_free_pages - free pages
> - * @virt: virtual address of the page to be freed.
> - *
> - * The page must have have been allocated by iommu_alloc_pages_node()
> - */
> -static inline void iommu_free_pages(void *virt)
> -{
> -	struct page *page;
> -
> -	if (!virt)
> -		return;
> -
> -	page = virt_to_page(virt);
> -	__iommu_free_account(page);
> -	put_page(page);
> -}
> -
> -/**
> - * iommu_put_pages_list - free a list of pages.
> - * @page: the head of the lru list to be freed.
> - *
> - * There are no locking requirement for these pages, as they are going to be
> - * put on a free list as soon as refcount reaches 0. Pages are put on this LRU
> - * list once they are removed from the IOMMU page tables. However, they can
> - * still be access through debugfs.
> - */
> -static inline void iommu_put_pages_list(struct list_head *page)
> -{
> -	while (!list_empty(page)) {
> -		struct page *p = list_entry(page->prev, struct page, lru);
> -
> -		list_del(&p->lru);
> -		__iommu_free_account(p);
> -		put_page(p);
> -	}
> -}
> -
>  #endif	/* __IOMMU_PAGES_H */
> -- 
> 2.43.0
> 


From smostafa at google.com  Wed Mar 12 05:45:39 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 12:45:39 +0000
Subject: [PATCH v3 15/23] iommu/pages: Move the __GFP_HIGHMEM checks into
 the common code
In-Reply-To: <15-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <15-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9GB8_j_8a4xCTsT@google.com>

On Tue, Feb 25, 2025 at 03:39:32PM -0400, Jason Gunthorpe wrote:
> The entire allocator API is built around using the kernel virtual address,
> it is illegal to pass GFP_HIGHMEM in as a GFP flag. Block it in the common
> code. Remove the duplicated checks from drivers.
> 
> Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>
> ---
>  drivers/iommu/io-pgtable-arm.c  | 2 --
>  drivers/iommu/io-pgtable-dart.c | 1 -
>  drivers/iommu/iommu-pages.c     | 4 ++++
>  3 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 62df2528d020b2..08d0f62abe8a09 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -267,8 +267,6 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
>  	dma_addr_t dma;
>  	void *pages;
>  
> -	VM_BUG_ON((gfp & __GFP_HIGHMEM));
> -
>  	if (cfg->alloc)
>  		pages = cfg->alloc(cookie, size, gfp);
>  	else
> diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
> index 7efcaea0bd5c86..ebf330e67bfa30 100644
> --- a/drivers/iommu/io-pgtable-dart.c
> +++ b/drivers/iommu/io-pgtable-dart.c
> @@ -111,7 +111,6 @@ static void *__dart_alloc_pages(size_t size, gfp_t gfp)
>  {
>  	int order = get_order(size);
>  
> -	VM_BUG_ON((gfp & __GFP_HIGHMEM));
>  	return iommu_alloc_pages(gfp, order);
>  }
>  
> diff --git a/drivers/iommu/iommu-pages.c b/drivers/iommu/iommu-pages.c
> index 3077df642adb1f..a7eed09420a231 100644
> --- a/drivers/iommu/iommu-pages.c
> +++ b/drivers/iommu/iommu-pages.c
> @@ -37,6 +37,10 @@ void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order)
>  	const unsigned long pgcnt = 1UL << order;
>  	struct folio *folio;
>  
> +	/* This uses page_address() on the memory. */
> +	if (WARN_ON(gfp & __GFP_HIGHMEM))
> +		return NULL;
> +
>  	/*
>  	 * __folio_alloc_node() does not handle NUMA_NO_NODE like
>  	 * alloc_pages_node() did.
> -- 
> 2.43.0
> 


From will at kernel.org  Wed Mar 12 05:49:08 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 12:49:08 +0000
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
 <20250311181151.GD5216@willie-the-truck>
 <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>
Message-ID: <20250312124907.GB6181@willie-the-truck>

On Tue, Mar 11, 2025 at 04:01:00PM -0400, Connor Abbott wrote:
> On Tue, Mar 11, 2025 at 2:11?PM Will Deacon <will at kernel.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> > > Up until now we have only called the set_stall callback during
> > > initialization when the device is off. But we will soon start calling it
> > > to temporarily disable stall-on-fault when the device is on, so handle
> > > that by checking if the device is on and writing SCTLR.
> > >
> > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > ---
> > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
> > >  1 file changed, 27 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > > @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
> > >  {
> > >       struct arm_smmu_domain *smmu_domain = (void *)cookie;
> > >       struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> > > -     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> > > +     struct arm_smmu_device *smmu = smmu_domain->smmu;
> > > +     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > > +     u32 mask = BIT(cfg->cbndx);
> > > +     bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> > > +     unsigned long flags;
> > >
> > >       if (enabled)
> > > -             qsmmu->stall_enabled |= BIT(cfg->cbndx);
> > > +             qsmmu->stall_enabled |= mask;
> > >       else
> > > -             qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> > > +             qsmmu->stall_enabled &= ~mask;
> > > +
> > > +     /*
> > > +      * If the device is on and we changed the setting, update the register.
> > > +      */
> > > +     if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> > > +             spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> > > +
> > > +             u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> > > +
> > > +             if (enabled)
> > > +                     reg |= ARM_SMMU_SCTLR_CFCFG;
> > > +             else
> > > +                     reg &= ~ARM_SMMU_SCTLR_CFCFG;
> > > +
> > > +             arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
> >
> > Are you sure you don't need TLB invalidation for this to take effect? I
> > think some fields in the SCTLR can be cached in the TLB but you'll need
> > to check whether or not that applies to CFCFG.
> >
> 
> I think it should be fine because CFCFG only controls behavior when
> there's a context fault and there can't be TLB entries for entries
> that cause a context fault: "The architecture permits the caching of
> any translation table entry that has been returned from memory without
> a fault and that does not, as a result of that entry, cause a
> Translation Fault or an Access Flag fault."

Ok, but what about other types of fault? For example, a permission fault
or an address size fault?

Will


From mike.leach at linaro.org  Wed Mar 12 05:54:41 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Wed, 12 Mar 2025 12:54:41 +0000
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <cef984d5-f369-4892-b970-a71285c2ebc5@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com> <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>
 <cef984d5-f369-4892-b970-a71285c2ebc5@quicinc.com>
Message-ID: <CAJ9a7VhDD3813LtH_5AYyM-2mhCNP+vRmqXn4RWqg5F8FEe-Mg@mail.gmail.com>

Hi Jie,

On Wed, 12 Mar 2025 at 01:21, Jie Gan <quic_jiegan at quicinc.com> wrote:
>
>
>
> On 3/12/2025 12:49 AM, Mike Leach wrote:
> > Hi,
> >
> > On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan at quicinc.com> wrote:
> >>
> >> The new functions calculate and return the offset to the write pointer of
> >> the ETR buffer based on whether the memory mode is SG, flat or reserved.
> >> The functions have the RWP offset can directly read data from ETR buffer,
> >> enabling the transfer of data to any required location.
> >>
> >> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> >> ---
> >>   .../hwtracing/coresight/coresight-tmc-etr.c   | 40 +++++++++++++++++++
> >>   drivers/hwtracing/coresight/coresight-tmc.h   |  1 +
> >>   2 files changed, 41 insertions(+)
> >>
> >> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >> index eda7cdad0e2b..ec636ab1fd75 100644
> >> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >> @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
> >>   }
> >>   EXPORT_SYMBOL_GPL(tmc_free_sg_table);
> >>
> >> +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata)
> >> +{
> >> +       dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
> >> +       u64 rwp;
> >> +
> >
> > It is not valid to read RWP if the TMC is running. It must be in the
> > stopped or disabled state - see the specifications for TMC /ETR
> >
> > It is likely that CSUNLOCK / CSLOCK are needed here too,  along with
> > the spinlock that protects drvdata
> >
> > See the code in coresight_tmc_etr.c :-
> >
> > e.g. in
> >
> > tmc_update_etr_buffer()
> >
> > ...
> > <take spinlock>
> > ...
> > CS_UNLOCK(drvdata->base);
> > tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and
> > flushed to memory - essential to ensure full formatted frame is in
> > memory.
> > tmc_sync_etr_buf(drvdata); // this function reads rwp.
> > CS_LOCK(drvdata->base);
> > <release spinlokc>
> >
> > This type of program flow is common to both sysfs and perf handling of
> > TMC buffers.
>
> Hi Mike,
>
> I am fully understood your point here.
>
> The function is designed this way to read the w_offset (which may not be
> entirely accurate because the etr buffer is not synced) when the

Why would you ever base memory access on a pointer that is not
entirely accurate?

The manuals for TMC/ETR all state that reads to both RWP and RRP when
the ETR is running return unknown values. These cannot be used to
access the buffer, or determine how much of the buffer has been used
on a running ETR.

The ETR specification specifically states that it is not permitted to
read the buffer data while the ETR is running, when configured in
circular buffer mode - which is the mode used in the TMC-ETR linux
drivers.

Reading the buffer while ETR is running is only permitted if
configured in Software FIFO mode 2 - were the ETR will stop on full
and stall incoming trace until some data is read out, signalled to the
ETR via the RURP.

I also note that you are reading back the etr_buf data without doing
any dma_sync operations that the perf and sysfs methods in the driver
do, after stopping the tmc.

> byte-cntr devnode is opened, aiming to reduce the length of redundant
> trace data. In this case, we cannot ensure the TMC is stopped or
> disabled.

The specification requires that you must ensure the TMC is stopped to
read these registers.


>The byte-cntr only requires an offset to know where it can
> start before the expected trace data gets into ETR buffer.
>
> The w_offset is also read when the byte-cntr function stops, which
> occurs after the TMC is disabled.
>
> Maybe this is not a good idea and I should read r_offset upon open?
> The primary goal for byte-cntr is trying to transfer useful trace data
> from the ETR buffer to the userspace, if we start from r_offset, a large
> number of redundant trace data which the user does not expect will be
> transferred simultaneously.
>
>

It is difficult to justify adding code to a driver that does not
correspond to the specification of the hardware device.

Regards

Mike

> >
> >> +       rwp = tmc_read_rwp(drvdata);
> >> +       return rwp - paddr;
> >> +}
> >> +
> >> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
> >> +{
> >> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
> >> +       struct etr_sg_table *etr_table = etr_buf->private;
> >> +       struct tmc_sg_table *table = etr_table->sg_table;
> >> +       long w_offset;
> >> +       u64 rwp;
> >> +
> >
> > Same comments as above
> >
> >> +       rwp = tmc_read_rwp(drvdata);
> >> +       w_offset = tmc_sg_get_data_page_offset(table, rwp);
> >> +
> >> +       return w_offset;
> >> +}
> >> +
> >> +/*
> >> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
> >> + * the memory mode is SG, flat or reserved.
> >> + */
> >> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
> >> +{
> >> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
> >> +
> >
> > As this is an exported function, please ensure that the inputs are
> > valid - check the pointers
>
> Sure, will do.
>
> Thanks,
> Jie
>
> >
> > Code to ensure TMC is flushed and stopped could be inserted here.
> >
> > Regards
> >
> > Mike
> >
> >> +       if (etr_buf->mode == ETR_MODE_ETR_SG)
> >> +               return tmc_sg_get_rwp_offset(drvdata);
> >> +       else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
> >> +               return tmc_flat_resrv_get_rwp_offset(drvdata);
> >> +       else
> >> +               return -EINVAL;
> >> +}
> >> +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
> >> +
> >>   /*
> >>    * Alloc pages for the table. Since this will be used by the device,
> >>    * allocate the pages closer to the device (i.e, dev_to_node(dev)
> >> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> >> index b48bc9a01cc0..baedb4dcfc3f 100644
> >> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> >> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> >> @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
> >>   struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
> >>                                     enum cs_mode mode, void *data);
> >>   extern const struct attribute_group coresight_etr_group;
> >> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
> >>
> >>   #endif
> >> --
> >> 2.34.1
> >>
> >
> >
>


--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From robin.murphy at arm.com  Wed Mar 12 05:57:11 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 12:57:11 +0000
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers
 directly
In-Reply-To: <CAF6AEGs8PoZBpFesQ_DGcngn4X24wzFy=zn2mAUJepdibxoKog@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
 <20250311180807.GC5216@willie-the-truck>
 <CACu1E7Hw6vGbTQ7t-Hj3ziycZhPxtOGSDkt7o4fNUx91KDcXfg@mail.gmail.com>
 <CAF6AEGs8PoZBpFesQ_DGcngn4X24wzFy=zn2mAUJepdibxoKog@mail.gmail.com>
Message-ID: <44d516b5-5e1f-4b50-b65c-0ed596639fd0@arm.com>

On 11/03/2025 8:00 pm, Rob Clark wrote:
> On Tue, Mar 11, 2025 at 12:42?PM Connor Abbott <cwabbott0 at gmail.com> wrote:
>>
>> On Tue, Mar 11, 2025 at 2:08?PM Will Deacon <will at kernel.org> wrote:
>>>
>>> On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
>>>> In some cases drm/msm has to resume a stalled transaction directly in
>>>> its fault handler. Experimentally this doesn't work on SMMU500 if the
>>>> fault hasn't already been acknowledged by clearing FSR. Rather than
>>>> trying to clear FSR in msm's fault handler and implementing a
>>>> tricky handshake to avoid accidentally clearing FSR twice, we want to
>>>> clear FSR before calling the fault handlers, but this means that the
>>>> contents of registers can change underneath us in the fault handler and
>>>> msm currently uses a private function to read the register contents for
>>>> its own purposes in its fault handler, such as using the
>>>> implementation-defined FSYNR1 to determine which block caused the fault.
>>>> Fix this by making msm use the register values already read by arm-smmu
>>>> itself before clearing FSR rather than messing around with reading
>>>> registers directly.
>>>>
>>>> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
>>>> ---
>>>>   drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
>>>>   drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
>>>>   drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
>>>>   3 files changed, 27 insertions(+), 27 deletions(-)
>>>
>>> [...]
>>>
>>>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
>>>> index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
>>>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
>>>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
>>>> @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
>>>>        ARM_SMMU_DOMAIN_NESTED,
>>>>   };
>>>>
>>>> +struct arm_smmu_context_fault_info {
>>>> +     unsigned long iova;
>>>> +     u64 ttbr0;
>>>> +     u32 fsr;
>>>> +     u32 fsynr0;
>>>> +     u32 fsynr1;
>>>> +     u32 cbfrsynra;
>>>> +     u32 contextidr;
>>>> +};
>>>> +
>>>>   struct arm_smmu_domain {
>>>>        struct arm_smmu_device          *smmu;
>>>>        struct io_pgtable_ops           *pgtbl_ops;
>>>> @@ -380,6 +390,7 @@ struct arm_smmu_domain {
>>>>        const struct iommu_flush_ops    *flush_ops;
>>>>        struct arm_smmu_cfg             cfg;
>>>>        enum arm_smmu_domain_stage      stage;
>>>> +     struct arm_smmu_context_fault_info cfi;
>>>
>>> Does this mean we have to serialise all faults for a given domain? That
>>> can't be right...
>>>
>>> Will
>>
>> They are already serialized? There's only one of each register per
>> context bank, so you can only have one context fault at a time per
>> context bank, and AFAIK a context bank is 1:1 with a domain. Also this
>> struct is only written and then read inside the context bank's
>> interrupt handler, and you can only have one interrupt at a time, no?
>>
>> Connor
> 
> And if it was a race condition with cfi getting overridden, it would
> have already been an equivalent race condition currently when reading
> the values from registers (ie. the register values could have changed
> in the elapsed time)
> 
> So no additional serialization needed here.

Agreed, the only subtlety is the other side of things is true as well - 
i.e. cfi is only valid and stable between the IRQ being fired and 
CBn_RESUME being written, so actually it *mustn't* be touched by 
anything outside the fault handling path.

Thanks,
Robin.


From smostafa at google.com  Wed Mar 12 05:59:00 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Wed, 12 Mar 2025 12:59:00 +0000
Subject: [PATCH v3 20/23] iommu: Update various drivers to pass in lg2sz
 instead of order to iommu pages
In-Reply-To: <20-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <20-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
Message-ID: <Z9GFFBvUFg7a9WEg@google.com>

On Tue, Feb 25, 2025 at 03:39:37PM -0400, Jason Gunthorpe wrote:
> Convert most of the places calling get_order() as an argument to the
> iommu-pages allocator into order_base_2() or the _sz flavour
> instead. These places already have an exact size, there is no particular
> reason to use order here.
> 
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
> ---
>  drivers/iommu/amd/init.c        | 29 +++++++++++++++--------------
>  drivers/iommu/intel/dmar.c      |  6 +++---
>  drivers/iommu/io-pgtable-arm.c  |  3 +--
>  drivers/iommu/io-pgtable-dart.c | 12 +++---------
>  drivers/iommu/sun50i-iommu.c    |  4 ++--
>  5 files changed, 24 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
> index e3f4283ebbc201..a5720df7b22397 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -635,8 +635,8 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table, u16 pci_
>  /* Allocate per PCI segment device table */
>  static inline int __init alloc_dev_table(struct amd_iommu_pci_seg *pci_seg)
>  {
> -	pci_seg->dev_table = iommu_alloc_pages(GFP_KERNEL | GFP_DMA32,
> -					       get_order(pci_seg->dev_table_size));
> +	pci_seg->dev_table = iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32,
> +						  pci_seg->dev_table_size);
>  	if (!pci_seg->dev_table)
>  		return -ENOMEM;
>  
> @@ -716,8 +716,7 @@ static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg)
>   */
>  static int __init alloc_command_buffer(struct amd_iommu *iommu)
>  {
> -	iommu->cmd_buf = iommu_alloc_pages(GFP_KERNEL,
> -					   get_order(CMD_BUFFER_SIZE));
> +	iommu->cmd_buf = iommu_alloc_pages_sz(GFP_KERNEL, CMD_BUFFER_SIZE);
>  
>  	return iommu->cmd_buf ? 0 : -ENOMEM;
>  }
> @@ -820,14 +819,16 @@ static void __init free_command_buffer(struct amd_iommu *iommu)
>  void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, gfp_t gfp,
>  				  size_t size)
>  {
> -	int order = get_order(size);
> -	void *buf = iommu_alloc_pages(gfp, order);
> +	void *buf;
>  
> -	if (buf &&
> -	    check_feature(FEATURE_SNP) &&
> -	    set_memory_4k((unsigned long)buf, (1 << order))) {
> +	size = PAGE_ALIGN(size);
> +	buf = iommu_alloc_pages_sz(gfp, size);
> +	if (!buf)
> +		return NULL;
> +	if (check_feature(FEATURE_SNP) &&
> +	    set_memory_4k((unsigned long)buf, size / PAGE_SIZE)) {
>  		iommu_free_pages(buf);
> -		buf = NULL;
> +		return NULL;
>  	}
>  
>  	return buf;
> @@ -922,11 +923,11 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)
>  	if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
>  		return 0;
>  
> -	iommu->ga_log = iommu_alloc_pages(GFP_KERNEL, get_order(GA_LOG_SIZE));
> +	iommu->ga_log = iommu_alloc_pages_sz(GFP_KERNEL, GA_LOG_SIZE);
>  	if (!iommu->ga_log)
>  		goto err_out;
>  
> -	iommu->ga_log_tail = iommu_alloc_pages(GFP_KERNEL, get_order(8));
> +	iommu->ga_log_tail = iommu_alloc_pages_sz(GFP_KERNEL, 8);
>  	if (!iommu->ga_log_tail)
>  		goto err_out;
>  
> @@ -1021,8 +1022,8 @@ static bool __copy_device_table(struct amd_iommu *iommu)
>  	if (!old_devtb)
>  		return false;
>  
> -	pci_seg->old_dev_tbl_cpy = iommu_alloc_pages(GFP_KERNEL | GFP_DMA32,
> -						     get_order(pci_seg->dev_table_size));
> +	pci_seg->old_dev_tbl_cpy = iommu_alloc_pages_sz(
> +		GFP_KERNEL | GFP_DMA32, pci_seg->dev_table_size);
>  	if (pci_seg->old_dev_tbl_cpy == NULL) {
>  		pr_err("Failed to allocate memory for copying old device table!\n");
>  		memunmap(old_devtb);
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index c812c83d77da10..4c7ce92acf6976 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -1681,7 +1681,6 @@ int dmar_enable_qi(struct intel_iommu *iommu)
>  {
>  	struct q_inval *qi;
>  	void *desc;
> -	int order;
>  
>  	if (!ecap_qis(iommu->ecap))
>  		return -ENOENT;
> @@ -1702,8 +1701,9 @@ int dmar_enable_qi(struct intel_iommu *iommu)
>  	 * Need two pages to accommodate 256 descriptors of 256 bits each
>  	 * if the remapping hardware supports scalable mode translation.
>  	 */
> -	order = ecap_smts(iommu->ecap) ? 1 : 0;
> -	desc = iommu_alloc_pages_node(iommu->node, GFP_ATOMIC, order);
> +	desc = iommu_alloc_pages_node_sz(iommu->node, GFP_ATOMIC,
> +					 ecap_smts(iommu->ecap) ? SZ_8K :
> +								  SZ_4K);
>  	if (!desc) {
>  		kfree(qi);
>  		iommu->qi = NULL;
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 08d0f62abe8a09..d13149ec5be77e 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -263,14 +263,13 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
>  				    void *cookie)
>  {
>  	struct device *dev = cfg->iommu_dev;
> -	int order = get_order(size);
>  	dma_addr_t dma;
>  	void *pages;
>  
>  	if (cfg->alloc)
>  		pages = cfg->alloc(cookie, size, gfp);
>  	else
> -		pages = iommu_alloc_pages_node(dev_to_node(dev), gfp, order);
> +		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp, size);

Although, the current implementation of iommu_alloc_pages_node_sz() would round
the size to order, but this is not correct according to the API definition
"The returned allocation is round_up_pow_two(size) big, and is physically aligned
to its size."

SMMUv3 has special alignment with small number of entries at the start level,
according the manual:
	A 64-byte minimum alignment on starting-level translation table addresses
	is imposed when TG0 selects 64KB granules and the effective IPS value
	indicates 52-bit output. In this case bits [5:0] are treated as zero.

And according to the Arm Arm (ex D24.2.195 in Version L)
	- Bits A[(x-1):0] of the stage 1 translation table base address are zero.
	... The smallest permitted value of x is 5.
Which 32 bytes

For a case as (which is valid in Linux)
- S1 with IAS 40-bits and 4K, start level has 2 entries (16 bytes) but alignment
  must be at least 32 bytes.

- Similarly with 16K and 48 bits.

I'd say we can align the size or use min with 64 bytes before calling the
function would be enough (or change the API to state that allocations
are rounded to order)

Thanks,
Mostafa

>  
>  	if (!pages)
>  		return NULL;
> diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
> index ebf330e67bfa30..a0988669bb951a 100644
> --- a/drivers/iommu/io-pgtable-dart.c
> +++ b/drivers/iommu/io-pgtable-dart.c
> @@ -107,13 +107,6 @@ static phys_addr_t iopte_to_paddr(dart_iopte pte,
>  	return paddr;
>  }
>  
> -static void *__dart_alloc_pages(size_t size, gfp_t gfp)
> -{
> -	int order = get_order(size);
> -
> -	return iommu_alloc_pages(gfp, order);
> -}
> -
>  static int dart_init_pte(struct dart_io_pgtable *data,
>  			     unsigned long iova, phys_addr_t paddr,
>  			     dart_iopte prot, int num_entries,
> @@ -255,7 +248,7 @@ static int dart_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
>  
>  	/* no L2 table present */
>  	if (!pte) {
> -		cptep = __dart_alloc_pages(tblsz, gfp);
> +		cptep = iommu_alloc_pages_sz(gfp, tblsz);
>  		if (!cptep)
>  			return -ENOMEM;
>  
> @@ -412,7 +405,8 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
>  	cfg->apple_dart_cfg.n_ttbrs = 1 << data->tbl_bits;
>  
>  	for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i) {
> -		data->pgd[i] = __dart_alloc_pages(DART_GRANULE(data), GFP_KERNEL);
> +		data->pgd[i] =
> +			iommu_alloc_pages_sz(GFP_KERNEL, DART_GRANULE(data));
>  		if (!data->pgd[i])
>  			goto out_free_data;
>  		cfg->apple_dart_cfg.ttbr[i] = virt_to_phys(data->pgd[i]);
> diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
> index 6385560dbc3fb0..76c9620af4bba8 100644
> --- a/drivers/iommu/sun50i-iommu.c
> +++ b/drivers/iommu/sun50i-iommu.c
> @@ -690,8 +690,8 @@ sun50i_iommu_domain_alloc_paging(struct device *dev)
>  	if (!sun50i_domain)
>  		return NULL;
>  
> -	sun50i_domain->dt = iommu_alloc_pages(GFP_KERNEL | GFP_DMA32,
> -					      get_order(DT_SIZE));
> +	sun50i_domain->dt =
> +		iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32, DT_SIZE);
>  	if (!sun50i_domain->dt)
>  		goto err_free_domain;
>  
> -- 
> 2.43.0
> 


From will at kernel.org  Wed Mar 12 06:05:38 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 13:05:38 +0000
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck>
 <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
Message-ID: <20250312130525.GC6181@willie-the-truck>

On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> >
> > On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > > This will be used by drm/msm for GPU page faults, replacing the manual
> > > register reading it does.
> > >
> > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > ---
> > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
> > >  3 files changed, 21 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> > >
> > >       if (list_empty(&tbu_list)) {
> > >               ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > > -                                      cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > +                                      cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > >
> > >               if (ret == -ENOSYS)
> > >                       arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> > > @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> > >       phys_soft = ops->iova_to_phys(ops, cfi.iova);
> > >
> > >       tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > > -                              cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > +                              cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > >       if (!tmp || tmp == -EBUSY) {
> > >               ret = IRQ_HANDLED;
> > >               resume = ARM_SMMU_RESUME_TERMINATE;
> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> > >                                     struct arm_smmu_context_fault_info *cfi)
> > >  {
> > >       cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > > +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> > >       cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > > -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> >
> > We already have an implementation hook (->get_fault_info()) which the
> > qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> > That thing dumps these registers already so if we're moving that into
> > the core SMMU driver, let's get rid of the hook and move everybody over
> > rather than having it done in both places.
> 
> As you probably saw, the next commit moves over
> qcom_adreno_smmu_get_fault_info() to use this. The current back door
> used by drm/msm to access these functions is specific to adreno_smmu
> and there isn't an equivalent interface to allow it to call a generic
> SMMU function so it isn't possible to move it entirely to the core. At
> least not without a bigger refactoring that isn't justified for this
> series that is just trying to fix things.

Ok :(

> > >       cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > > +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> >
> > I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> > it for stage-2 domains.
> >
> Does it matter if we read the register though, as long as users are
> aware of this and don't use its value for anything?

I think the contents are "UNKNOWN", so it could be hugely confusing even
if they just got logged someplace. Why is it difficult to avoid touching
it for stage-2?

Will


From will at kernel.org  Wed Mar 12 06:06:49 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 13:06:49 +0000
Subject: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers
 directly
In-Reply-To: <CAF6AEGs8PoZBpFesQ_DGcngn4X24wzFy=zn2mAUJepdibxoKog@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-2-be14be37f4c3@gmail.com>
 <20250311180807.GC5216@willie-the-truck>
 <CACu1E7Hw6vGbTQ7t-Hj3ziycZhPxtOGSDkt7o4fNUx91KDcXfg@mail.gmail.com>
 <CAF6AEGs8PoZBpFesQ_DGcngn4X24wzFy=zn2mAUJepdibxoKog@mail.gmail.com>
Message-ID: <20250312130648.GD6181@willie-the-truck>

On Tue, Mar 11, 2025 at 01:00:34PM -0700, Rob Clark wrote:
> On Tue, Mar 11, 2025 at 12:42?PM Connor Abbott <cwabbott0 at gmail.com> wrote:
> >
> > On Tue, Mar 11, 2025 at 2:08?PM Will Deacon <will at kernel.org> wrote:
> > >
> > > On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> > > > In some cases drm/msm has to resume a stalled transaction directly in
> > > > its fault handler. Experimentally this doesn't work on SMMU500 if the
> > > > fault hasn't already been acknowledged by clearing FSR. Rather than
> > > > trying to clear FSR in msm's fault handler and implementing a
> > > > tricky handshake to avoid accidentally clearing FSR twice, we want to
> > > > clear FSR before calling the fault handlers, but this means that the
> > > > contents of registers can change underneath us in the fault handler and
> > > > msm currently uses a private function to read the register contents for
> > > > its own purposes in its fault handler, such as using the
> > > > implementation-defined FSYNR1 to determine which block caused the fault.
> > > > Fix this by making msm use the register values already read by arm-smmu
> > > > itself before clearing FSR rather than messing around with reading
> > > > registers directly.
> > > >
> > > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > > ---
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
> > > >  3 files changed, 27 insertions(+), 27 deletions(-)
> > >
> > > [...]
> > >
> > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > > index d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237 100644
> > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > > @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
> > > >       ARM_SMMU_DOMAIN_NESTED,
> > > >  };
> > > >
> > > > +struct arm_smmu_context_fault_info {
> > > > +     unsigned long iova;
> > > > +     u64 ttbr0;
> > > > +     u32 fsr;
> > > > +     u32 fsynr0;
> > > > +     u32 fsynr1;
> > > > +     u32 cbfrsynra;
> > > > +     u32 contextidr;
> > > > +};
> > > > +
> > > >  struct arm_smmu_domain {
> > > >       struct arm_smmu_device          *smmu;
> > > >       struct io_pgtable_ops           *pgtbl_ops;
> > > > @@ -380,6 +390,7 @@ struct arm_smmu_domain {
> > > >       const struct iommu_flush_ops    *flush_ops;
> > > >       struct arm_smmu_cfg             cfg;
> > > >       enum arm_smmu_domain_stage      stage;
> > > > +     struct arm_smmu_context_fault_info cfi;
> > >
> > > Does this mean we have to serialise all faults for a given domain? That
> > > can't be right...
> > >
> >
> > They are already serialized? There's only one of each register per
> > context bank, so you can only have one context fault at a time per
> > context bank, and AFAIK a context bank is 1:1 with a domain. Also this
> > struct is only written and then read inside the context bank's
> > interrupt handler, and you can only have one interrupt at a time, no?
> >
> > Connor
> 
> And if it was a race condition with cfi getting overridden, it would
> have already been an equivalent race condition currently when reading
> the values from registers (ie. the register values could have changed
> in the elapsed time)
> 
> So no additional serialization needed here.

Oops, yes, sorry. I've been spending too long on SMMUv3 and forgot how
the context banks worked.

Will


From robh at kernel.org  Wed Mar 12 06:07:31 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 12 Mar 2025 08:07:31 -0500
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250312045802.4115029-1-wthai@nvidia.com>
References: <20250312045802.4115029-1-wthai@nvidia.com>
Message-ID: <174178473498.434308.6316925758588470688.robh@kernel.org>


On Wed, 12 Mar 2025 04:58:02 +0000, Willie Thai wrote:
> The GB200NVL BMC is an Aspeed Ast2600 based BMC
> for Nvidia Blackwell GB200NVL platform.
> Reference to Ast2600 SOC [1].
> Reference to Blackwell GB200NVL Platform [2].
> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Cc: Krzysztof Kozlowski <krzk at kernel.org>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Paul Menzel <pmenzel at molgen.mpg.de>
> Link: Reference to Ast2600 SOC: https://www.aspeedtech.com/server_ast2600/ [1]
> Link: Reference to Blackwell GB200NVL Platform: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---
> Changes in v2:
>   - Fix the SOB name [Krzysztof]
>   - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
>   - Fix DTS coding style [Krzysztof]
>   - Move pinctrl override to the bottom [Krzysztof]
>   - Drop bootargs [Krzysztof]
>   - Follow DTS coding style and change naming for leds node [Krzysztof]
>   - Change flash 0 status property [Krzysztof]
>   - Change the phy-mode to rgmii [Andrew]
>   - Remove the max-speed in mac0 [Andrew]
> ---
> ---
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1229 +++++++++++++++++
>  2 files changed, 1230 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250312045802.4115029-1-wthai at nvidia.com:

arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /: compatible: 'oneOf' conditional failed, one must be fixed:
	'nvidia,gb200nvl-bmc' is not one of ['delta,ahe50dc-bmc', 'facebook,galaxy100-bmc', 'facebook,wedge100-bmc', 'facebook,wedge40-bmc', 'microsoft,olympus-bmc', 'quanta,q71l-bmc', 'tyan,palmetto-bmc', 'yadro,vesnin-bmc']
	'nvidia,gb200nvl-bmc' is not one of ['amd,daytonax-bmc', 'amd,ethanolx-bmc', 'ampere,mtjade-bmc', 'aspeed,ast2500-evb', 'asrock,e3c246d4i-bmc', 'asrock,e3c256d4i-bmc', 'asrock,romed8hm3-bmc', 'asrock,spc621d8hm3-bmc', 'asrock,x570d4u-bmc', 'bytedance,g220a-bmc', 'facebook,cmm-bmc', 'facebook,minipack-bmc', 'facebook,tiogapass-bmc', 'facebook,yamp-bmc', 'facebook,yosemitev2-bmc', 'facebook,wedge400-bmc', 'hxt,stardragon4800-rep2-bmc', 'ibm,mihawk-bmc', 'ibm,mowgli-bmc', 'ibm,romulus-bmc', 'ibm,swift-bmc', 'ibm,witherspoon-bmc', 'ingrasys,zaius-bmc', 'inspur,fp5280g2-bmc', 'inspur,nf5280m6-bmc', 'inspur,on5263m5-bmc', 'intel,s2600wf-bmc', 'inventec,lanyang-bmc', 'lenovo,hr630-bmc', 'lenovo,hr855xg2-bmc', 'portwell,neptune-bmc', 'qcom,centriq2400-rep-bmc', 'supermicro,x11spi-bmc', 'tyan,s7106-bmc', 'tyan,s8036-bmc', 'yadro,nicole-bmc', 'yadro,vegman-n110-bmc', 'yadro,vegman-rx20-bmc', 'yadro,vegman-sx20-bmc']
	'nvidia,gb200nvl-bmc' is not one of ['ampere,mtjefferson-bmc', 'ampere,mtmitchell-bmc', 'aspeed,ast2600-evb', 'aspeed,ast2600-evb-a1', 'asus,x4tf-bmc', 'facebook,bletchley-bmc', 'facebook,catalina-bmc', 'facebook,cloudripper-bmc', 'facebook,elbert-bmc', 'facebook,fuji-bmc', 'facebook,greatlakes-bmc', 'facebook,harma-bmc', 'facebook,minerva-cmc', 'facebook,yosemite4-bmc', 'ibm,blueridge-bmc', 'ibm,everest-bmc', 'ibm,fuji-bmc', 'ibm,rainier-bmc', 'ibm,sbp1-bmc', 'ibm,system1-bmc', 'ibm,tacoma-bmc', 'inventec,starscream-bmc', 'inventec,transformer-bmc', 'jabil,rbp-bmc', 'qcom,dc-scm-v1-bmc', 'quanta,s6q-bmc', 'ufispace,ncplite-bmc']
	'aspeed,ast2400' was expected
	'aspeed,ast2500' was expected
	from schema $id: http://devicetree.org/schemas/arm/aspeed/aspeed.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /: failed to match any schema with compatible: ['nvidia,gb200nvl-bmc', 'aspeed,ast2600']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pinctrl: emmcg5_default:groups:0: 'EMMCG5' is not one of ['ADC0', 'ADC1', 'ADC10', 'ADC11', 'ADC12', 'ADC13', 'ADC14', 'ADC15', 'ADC2', 'ADC3', 'ADC4', 'ADC5', 'ADC6', 'ADC7', 'ADC8', 'ADC9', 'BMCINT', 'EMMCG1', 'EMMCG4', 'EMMCG8', 'ESPI', 'ESPIALT', 'FSI1', 'FSI2', 'FWQSPI', 'FWSPIABR', 'FWSPID', 'FWSPIWP', 'GPIT0', 'GPIT1', 'GPIT2', 'GPIT3', 'GPIT4', 'GPIT5', 'GPIT6', 'GPIT7', 'GPIU0', 'GPIU1', 'GPIU2', 'GPIU3', 'GPIU4', 'GPIU5', 'GPIU6', 'GPIU7', 'HVI3C3', 'HVI3C4', 'I2C1', 'I2C10', 'I2C11', 'I2C12', 'I2C13', 'I2C14', 'I2C15', 'I2C16', 'I2C2', 'I2C3', 'I2C4', 'I2C5', 'I2C6', 'I2C7', 'I2C8', 'I2C9', 'I3C1', 'I3C2', 'I3C3', 'I3C4', 'I3C5', 'I3C6', 'JTAGM', 'LHPD', 'LHSIRQ', 'LPC', 'LPCHC', 'LPCPD', 'LPCPME', 'LPCSMI', 'LSIRQ', 'MACLINK1', 'MACLINK2', 'MACLINK3', 'MACLINK4', 'MDIO1', 'MDIO2', 'MDIO3', 'MDIO4', 'NCSI3', 'NCSI4', 'NCTS1', 'NCTS2', 'NCTS3', 'NCTS4', 'NDCD1', 'NDCD2', 'NDCD3', 'NDCD4', 'NDSR1', 'NDSR2', 'NDSR3'
 , 'NDSR4', 'NDTR1', 'NDTR2', 'NDTR3', 'NDTR4', 'NRI1', 'NRI2', 'NRI3', 'NRI4', 'NRTS1', 'NRTS2', 'NRTS3', 'NRTS4', 'OSCCLK', 'PEWAKE', 'PWM0', 'PWM1', 'PWM10G0', 'PWM10G1', 'PWM11G0', 'PWM11G1', 'PWM12G0', 'PWM12G1', 'PWM13G0', 'PWM13G1', 'PWM14G0', 'PWM14G1', 'PWM15G0', 'PWM15G1', 'PWM2', 'PWM3', 'PWM4', 'PWM5', 'PWM6', 'PWM7', 'PWM8G0', 'PWM8G1', 'PWM9G0', 'PWM9G1', 'QSPI1', 'QSPI2', 'RGMII1', 'RGMII2', 'RGMII3', 'RGMII4', 'RMII1', 'RMII2', 'RMII3', 'RMII4', 'RXD1', 'RXD2', 'RXD3', 'RXD4', 'SALT1', 'SALT10G0', 'SALT10G1', 'SALT11G0', 'SALT11G1', 'SALT12G0', 'SALT12G1', 'SALT13G0', 'SALT13G1', 'SALT14G0', 'SALT14G1', 'SALT15G0', 'SALT15G1', 'SALT16G0', 'SALT16G1', 'SALT2', 'SALT3', 'SALT4', 'SALT5', 'SALT6', 'SALT7', 'SALT8', 'SALT9G0', 'SALT9G1', 'SD1', 'SD2', 'SD3', 'SGPM1', 'SGPM2', 'SGPS1', 'SGPS2', 'SIOONCTRL', 'SIOPBI', 'SIOPBO', 'SIOPWREQ', 'SIOPWRGD', 'SIOS3', 'SIOS5', 'SIOSCI', 'SPI1', 'SPI1ABR', 'SPI1CS1', 'SPI1WP', 'SPI2', 'SPI2CS1', 'SPI2CS2', 'TACH0', 'TACH1', 'TACH10'
 , 'TACH11', 'TACH12', 'TACH13', 'TACH14', 'TACH15', 'TACH2', 'TACH3', 'TACH4', 'TACH5', 'TACH6', 'TACH7', 'TACH8', 'TACH9', 'THRU0', 'THRU1', 'THRU2', 'THRU3', 'TXD1', 'TXD2', 'TXD3', 'TXD4', 'UART10', 'UART11', 'UART12G0', 'UART12G1', 'UART13G0', 'UART13G1', 'UART6', 'UART7', 'UART8', 'UART9', 'USBA', 'USBB', 'VB', 'VGAHS', 'VGAVS', 'WDTRST1', 'WDTRST2', 'WDTRST3', 'WDTRST4']
	from schema $id: http://devicetree.org/schemas/pinctrl/aspeed,ast2600-pinctrl.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c at 80: Unevaluated properties are not allowed ('disable-master' was unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/aspeed,i2c.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 71: $nodename:0: 'i2c-switch at 71' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 71: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: $nodename:0: 'i2c-switch at 74' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 72: $nodename:0: 'i2c-switch at 72' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 72: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 73: $nodename:0: 'i2c-switch at 73' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 73: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 70: $nodename:0: 'i2c-switch at 70' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 70: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 75: $nodename:0: 'i2c-switch at 75' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 75: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: $nodename:0: 'i2c-switch at 74' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 76: $nodename:0: 'i2c-switch at 76' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 76: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 23: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 2c: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 2f: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 27: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 74: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']







From robh at kernel.org  Wed Mar 12 06:07:34 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 12 Mar 2025 08:07:34 -0500
Subject: [PATCH 0/8] arm64: mediatek: mt8186-corsola: Consolidate and
 add new devices
In-Reply-To: <20250312104344.3084425-1-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
Message-ID: <174178473613.434362.5052831169970866580.robh@kernel.org>


On Wed, 12 Mar 2025 18:43:34 +0800, Chen-Yu Tsai wrote:
> Hi everyone,
> 
> Here's a follow up series of the I2C component probers for Chromebooks.
> This series enables the component prober for the Corsola series of
> devices, combines the two existing Voltorb SKUs, and adds a new
> device, codename Squirtle.
> 
> Patch 1 adds a new HID-over-I2C touchscreen from Elan.
> 
> Patch 2 merges the Voltorb entries in the device tree bindings into one.
> 
> Patch 3 adds a new entry for the Squirtle device to the bindings.
> 
> Patch 4 fixes up the existing device trees for the component prober to
> be active.
> 
> Patch 5 merges the device trees for the Voltorb device.
> 
> Patch 6 adds a device tree file for the Squirtle device, with I2C
> components ready to be probed by the prober.
> 
> Patch 7 enables the prober to probe trackpads on some devices in the
> Corsola family.
> 
> Patch 8 enables the prober to probe touchscreens on Squirtle.
> 
> Please take a look.
> 
> 
> Thanks
> ChenYu
> 
> 
> Chen-Yu Tsai (8):
>   dt-bindings: HID: i2c-hid: elan: Introduce Elan eKTH8D18
>   dt-bindings: arm: mediatek: Merge MT8186 Voltorb entries
>   dt-bindings: arm: mediatek: Add MT8186 Squirtle Chromebooks
>   arm64: dts: mediatek: mt8186-steelix: Mark second source components
>     for probing
>   arm64: dts: mediatek: mt8186: Merge Voltorb device trees
>   arm64: dts: mediatek: mt8186: Add Squirtle Chromebooks
>   platform/chrome: of_hw_prober: Support trackpad probing on Corsola
>     family
>   platform/chrome: of_hw_prober: Support touchscreen probing on Squirtle
> 
>  .../devicetree/bindings/arm/mediatek.yaml     |   7 +-
>  .../bindings/input/elan,ekth6915.yaml         |  29 ++++-
>  arch/arm64/boot/dts/mediatek/Makefile         |   4 +-
>  .../dts/mediatek/mt8186-corsola-squirtle.dts  | 107 ++++++++++++++++++
>  .../dts/mediatek/mt8186-corsola-steelix.dtsi  |   9 +-
>  .../mt8186-corsola-tentacool-sku327683.dts    |   2 +
>  .../mt8186-corsola-tentacruel-sku262148.dts   |   2 +
>  .../mt8186-corsola-voltorb-sku589824.dts      |  13 ---
>  ...u589825.dts => mt8186-corsola-voltorb.dts} |   5 +-
>  .../boot/dts/mediatek/mt8186-corsola.dtsi     |  10 +-
>  .../platform/chrome/chromeos_of_hw_prober.c   |  29 +++++
>  11 files changed, 185 insertions(+), 32 deletions(-)
>  create mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dts
>  delete mode 100644 arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
>  rename arch/arm64/boot/dts/mediatek/{mt8186-corsola-voltorb-sku589825.dts => mt8186-corsola-voltorb.dts} (76%)
> 
> --
> 2.49.0.rc0.332.g42c0ae87b1-goog
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/mediatek/' for 20250312104344.3084425-1-wenst at chromium.org:

arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtb: spmi at 10015000: Unevaluated properties are not allowed ('interrupts' was unexpected)
	from schema $id: http://devicetree.org/schemas/spmi/mtk,spmi-mtk-pmif.yaml#
arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtb: sound: 'model' is a required property
	from schema $id: http://devicetree.org/schemas/sound/mt8186-mt6366-rt1019-rt5682s.yaml#
arch/arm64/boot/dts/mediatek/mt8186-corsola-squirtle.dtb: spmi at 10015000: Unevaluated properties are not allowed ('interrupts' was unexpected)
	from schema $id: http://devicetree.org/schemas/spmi/mtk,spmi-mtk-pmif.yaml#







From will at kernel.org  Wed Mar 12 06:08:47 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 13:08:47 +0000
Subject: [PATCH v18 0/5] iommu/arm-smmu: introduction of ACTLR
 implementation for Qualcomm SoCs
In-Reply-To: <CAF6AEGvDyPtXN7Cn98BKsTM9GjUzy1sTEOsLiz-cdvaZ14qWyA@mail.gmail.com>
References: <20241212151402.159102-1-quic_bibekkum@quicinc.com>
 <173625436399.258197.10961901698600591079.b4-ty@kernel.org>
 <20250311175528.GA5216@willie-the-truck>
 <CAF6AEGvDyPtXN7Cn98BKsTM9GjUzy1sTEOsLiz-cdvaZ14qWyA@mail.gmail.com>
Message-ID: <20250312130846.GE6181@willie-the-truck>

On Tue, Mar 11, 2025 at 01:03:29PM -0700, Rob Clark wrote:
> On Tue, Mar 11, 2025 at 10:55?AM Will Deacon <will at kernel.org> wrote:
> >
> > On Tue, Jan 07, 2025 at 04:42:39PM +0000, Will Deacon wrote:
> > > On Thu, 12 Dec 2024 20:43:57 +0530, Bibek Kumar Patro wrote:
> > > > This patch series consist of six parts and covers the following:
> > > >
> > > > 1. Provide option to re-enable context caching to retain prefetcher
> > > >    settings during reset and runtime suspend.
> > > >
> > > > 2. Remove cfg inside qcom_smmu structure and replace it with single
> > > >    pointer to qcom_smmu_match_data avoiding replication of multiple
> > > >    members from same.
> > > >
> > > > [...]
> > >
> > > Applied to iommu (arm/smmu/updates), thanks!
> > >
> > > [1/5] iommu/arm-smmu: Re-enable context caching in smmu reset operation
> > >       https://git.kernel.org/iommu/c/ef4144b1b47d
> > > [2/5] iommu/arm-smmu: Refactor qcom_smmu structure to include single pointer
> > >       https://git.kernel.org/iommu/c/445d7a8ed90e
> > > [3/5] iommu/arm-smmu: Add support for PRR bit setup
> > >       https://git.kernel.org/iommu/c/7f2ef1bfc758
> > > [4/5] iommu/arm-smmu: Introduce ACTLR custom prefetcher settings
> > >       https://git.kernel.org/iommu/c/9fe18d825a58
> > > [5/5] iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500
> > >       https://git.kernel.org/iommu/c/3e35c3e725de
> >
> > Hrm. I'm not seeing any user of the new ->set_prr*_() functions in
> > linux-next yet. Is there something under review, or should I revert this
> > for now?
> 
> It is WIP, part of a larger patchset adding sparse binding support in
> drm/msm.  Please do not revert.

Sure, if it's actively being worked on then I'll leave the hooks in
place.

Do you have a link to the patchset so that I can follow along, please?

Will


From robh at kernel.org  Wed Mar 12 06:17:34 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 12 Mar 2025 08:17:34 -0500
Subject: [PATCH net-next V2 1/2] dt-bindings: net: xlnx,axi-ethernet:
 Modify descriptions and phy-mode value to support 2500base-X only
 configuration
In-Reply-To: <20250312095411.1392379-2-suraj.gupta2@amd.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-2-suraj.gupta2@amd.com>
Message-ID: <20250312131734.GA505165-robh@kernel.org>

On Wed, Mar 12, 2025 at 03:24:10PM +0530, Suraj Gupta wrote:
> AXI 1G/2.5G Ethernet subsystem supports 1G and 2.5G speeds. Modify
> existing binding description, pcs-handle description and add
> 2500base-x in phy-mode for 2500base-X only configuration.
> 
> Signed-off-by: Suraj Gupta <suraj.gupta2 at amd.com>
> ---
>  .../devicetree/bindings/net/xlnx,axi-ethernet.yaml       | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
> index fb02e579463c..977f55b98f31 100644
> --- a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
> +++ b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
> @@ -9,10 +9,12 @@ title: AXI 1G/2.5G Ethernet Subsystem
>  description: |
>    Also called  AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core
>    provides connectivity to an external ethernet PHY supporting different
> -  interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two
> +  interfaces: MII, GMII, RGMII, SGMII, 1000BaseX and 2500BaseX. It also includes two

Please re-wrap at 80.

>    segments of memory for buffering TX and RX, as well as the capability of
>    offloading TX/RX checksum calculation off the processor.
>  
> +  AXI 2.5G MAC is incremental speed upgrade of AXI 1G and supports 2.5G speed.
> +
>    Management configuration is done through the AXI interface, while payload is
>    sent and received through means of an AXI DMA controller. This driver
>    includes the DMA driver code, so this driver is incompatible with AXI DMA
> @@ -62,6 +64,7 @@ properties:
>        - rgmii
>        - sgmii
>        - 1000base-x
> +      - 2500base-x
>  
>    xlnx,phy-type:
>      description:
> @@ -118,8 +121,8 @@ properties:
>      type: object
>  
>    pcs-handle:
> -    description: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X
> -      modes, where "pcs-handle" should be used to point to the PCS/PMA PHY,
> +    description: Phandle to the internal PCS/PMA PHY in SGMII or 1000base-x/
> +      2500base-x modes, where "pcs-handle" should be used to point to the PCS/PMA PHY,

And here.

>        and "phy-handle" should point to an external PHY if exists.
>      maxItems: 1
>  
> -- 
> 2.25.1
> 


From ulf.hansson at linaro.org  Wed Mar 12 06:17:52 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 12 Mar 2025 14:17:52 +0100
Subject: [PATCH RFC 0/3] mmc: sdhci-brcmstb: Add rpmb sharing support
In-Reply-To: <d51a9d7a-b942-4c3b-93d2-65b1bb04c8da@broadcom.com>
References: <20250206220940.10553-1-kamal.dasu@broadcom.com>
 <CAPDyKFq1ZbP4c9ECfM1SY+MEopf+dC19w9PkqXaUjevf=bPjcw@mail.gmail.com>
 <115a59e1-75b2-4d09-bbf9-50dfcd2b62dd@broadcom.com> <PH7PR16MB61967C18645C64E582B222B6E5FD2@PH7PR16MB6196.namprd16.prod.outlook.com>
 <d51a9d7a-b942-4c3b-93d2-65b1bb04c8da@broadcom.com>
Message-ID: <CAPDyKFrCjo8gGnxmXWP6V39N+b1o62VQH9zwMUNb2_+D3-qrdw@mail.gmail.com>

On Tue, 11 Feb 2025 at 18:01, Florian Fainelli
<florian.fainelli at broadcom.com> wrote:
>
> On 2/11/25 00:13, Avri Altman wrote:
> >>>> This patch set adds support for Broadcom TZOS to read and write to
> >>>> RPMB partition using synchronized access to the controller hardware.
> > Practically it establishes a communication channel between the trust zone and the host controller regardless of the rpmb protocol.
> > Or did I get it wrong?
>
> Rather than communication channel, I would describe it as an arbitration
> scheme between N participants, with guaranteed forward progress and
> fairness between all participants.

A scheduler in the MMC controller HW?

Nevertheless, it means bypassing the I/O scheduler in Linux and the
mmc block layer, kind of breaking "fairness" from Linux point of view.

>
> The interest here is for one of those participants to own the eMMC
> controller for a certain amount of time and indicate when it is done
> with it. This is not specific to eMMC as this could scale to virtually
> any piece of HW that is driven by transactions from a CPU, but the main
> application is for allowing the Trusted OS to own the eMMC controller
> for a short period of time in order to do its RPMB access, and then give
> it back in the same state it found it to the next participant.

Honestly, I think this is a really terrible idea, sorry.

Data and communication with an eMMC needs to be synchronized and
managed by a single owner. Having multiple clients with their own
channel to the eMMC sounds prone to problems. Is each client going to
have its own mmc protocol stack, dealing with eMMC initialization,
data-synchronization and power-management, etc?

As I said, we now have the RPMB subsystem for in-kernel access. Please
use it instead.

Kind regards
Uffe


From geert+renesas at glider.be  Wed Mar 12 06:19:51 2025
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Wed, 12 Mar 2025 14:19:51 +0100
Subject: [PULL] Renesas fixes for v6.14
Message-ID: <cover.1741785482.git.geert+renesas@glider.be>

	Hi SoC folks,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-fixes-for-v6.14-tag1

for you to fetch changes up to 379c590113ce46f605439d4887996c60ab8820cc:

  ARM: shmobile: smp: Enforce shmobile_smp_* alignment (2025-03-12 09:15:37 +0100)

----------------------------------------------------------------
Renesas fixes for v6.14

  - Fix possible misalignment breaking SMP bring-up.

Thanks for pulling!

----------------------------------------------------------------
Geert Uytterhoeven (1):
      ARM: shmobile: smp: Enforce shmobile_smp_* alignment

 arch/arm/mach-shmobile/headsmp.S | 1 +
 1 file changed, 1 insertion(+)

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


From mike.leach at linaro.org  Wed Mar 12 06:22:09 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Wed, 12 Mar 2025 13:22:09 +0000
Subject: [PATCH v1 0/4] coresight: ctcu: Enable byte-cntr function for TMC ETR
In-Reply-To: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
Message-ID: <CAJ9a7Vj=Ni_o94u1B+oouv0GD5DVmST=N31-hsN=SPSbaoqO_Q@mail.gmail.com>

Hi,

On Mon, 10 Mar 2025 at 09:05, Jie Gan <quic_jiegan at quicinc.com> wrote:
>
> From: Jie Gan <jie.gan at oss.qualcomm.com>
>
> The byte-cntr function provided by the CTCU device is used to transfer data
> from the ETR buffer to the userspace. An interrupt is tiggered if the data
> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
> handler counts the number of triggered interruptions and the read function
> will read the data from the ETR buffer if the IRQ count is greater than 0.
> Each successful read process will decrement the IRQ count by 1.
>
> The byte cntr function will start when the device node is opened for reading,
> and the IRQ count will reset when the byte cntr function has stopped. When
> the file node is opened, the w_offset of the ETR buffer will be read and
> stored in byte_cntr_data, serving as the original r_offset (indicating
> where reading starts) for the byte counter function.
>
> The work queue for the read operation will wake up once when ETR is stopped,
> ensuring that the remaining data in the ETR buffer has been flushed based on
> the w_offset read at the time of stopping.
>
> The following shell commands write threshold to BYTECNTRVAL registers.
>
> Only enable byte-cntr for ETR0:
> echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>
> Enable byte-cntr for both ETR0 and ETR1(support both hex and decimal values):
> echo 0x10000 4096 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>
> Setting the BYTECNTRVAL registers to 0 disables the byte-cntr function.
> Disable byte-cntr for ETR0:
> echo 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>
> Disable byte-cntr for both ETR0 and ETR1:
> echo 0 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>
> There is a minimum threshold to prevent generating too many interrupts.
> The minimum threshold is 4096 bytes. The write process will fail if user try
> to set the BYTECNTRVAL registers to a value less than 4096 bytes(except
> for 0).
>
> Finally, the user can read data from the ETR buffer through the byte-cntr file
> nodes located under /dev, for example reads data from the ETR0 buffer:
> cat /dev/byte-cntr0
>
> Way to enable and start byte-cntr for ETR0:
> echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
> echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
> echo 1 > /sys/bus/coresight/devices/etm0/enable_source
> cat /dev/byte-cntr0
>

There is a significant issue with attempting to drain an ETR buffer
while it is live in the way you appear to be doing.

You have no way of knowing if the TMC hardware write pointer wraps and
overtakes the point where you are currently reading. This could cause
data corruption as TMC writes as you are reading, or contention for
the buffer that affects the TMC write.

Even if those two events do not occur, then the trace capture sequence
is corrupted.

Take a simple example - suppose we split the buffer into 4 blocks of
trace, which are filled by the ETR

buffer = 1, 2, 3, 4

Now you suppose you have read 1 & 2 into your userspace buffer / file.

file = 1, 2

If there is now some system event that prevents your userspace code
from running for a while, then it is possible that the ETR continues,
wraps and the buffer is now

buffer = 5, 6, 7, 4

Your next two reads will be 7, 4

file = 1, 2, 7, 4

This trace is now corrupt and will cause decode errors. There is no
way for the decoder to determine that the interface between blocks 2 &
7 is not correct. If you are fortunate then this issue will cause an
actual explicit decode error, if you are less fortunate then decode
will continue but in fact be inaccurate, with no obvious way to detect
the inaccuracy.

We encountered this problem early in the development of the perf data
collection. Even though perf was stopping the trace to copy the
hardware buffer, it would concatenate unrelated trace blocks into the
perf userspace buffer, which initially caused decoding errors. This is
now mitigated in perf by marking boundaries and recording indexes of
the boundaries, so the tool can reset the decoder at the start of non
contiguous blocks.

If you do not stop the TMC when draining the ETR buffer, you have no
way of determining if this has occurred.

Clearly using large buffers, split into smaller blocks can mitigate
the possibility of a wrap in this way - but never eliminate it,
especially given the extreme rate that trace data can be generated.

Regards

Mike


> Jie Gan (4):
>   coresight: tmc: Introduce new APIs to get the RWP offset of ETR buffer
>   dt-bindings: arm: Add an interrupt property for Coresight CTCU
>   coresight: ctcu: Enable byte-cntr for TMC ETR devices
>   arm64: dts: qcom: sa8775p: Add interrupts to CTCU device
>
>  .../bindings/arm/qcom,coresight-ctcu.yaml     |  17 +
>  arch/arm64/boot/dts/qcom/sa8775p.dtsi         |   5 +
>  drivers/hwtracing/coresight/Makefile          |   2 +-
>  .../coresight/coresight-ctcu-byte-cntr.c      | 339 ++++++++++++++++++
>  .../hwtracing/coresight/coresight-ctcu-core.c |  96 ++++-
>  drivers/hwtracing/coresight/coresight-ctcu.h  |  59 ++-
>  .../hwtracing/coresight/coresight-tmc-etr.c   |  45 ++-
>  drivers/hwtracing/coresight/coresight-tmc.h   |   3 +
>  8 files changed, 556 insertions(+), 10 deletions(-)
>  create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>
> --
> 2.34.1
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From ariel.dalessandro at collabora.com  Wed Mar 12 06:24:24 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Wed, 12 Mar 2025 10:24:24 -0300
Subject: [PATCH v1 3/6] drm/panfrost: Unify panfrost_mmu_enable/disable
 common code
In-Reply-To: <20250311085158.37329b0c@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-4-ariel.dalessandro@collabora.com>
 <20250311085158.37329b0c@collabora.com>
Message-ID: <3aca6477-6014-4c24-8aa6-6c601fc54a32@collabora.com>

Boris,

On 3/11/25 4:51 AM, Boris Brezillon wrote:
> On Mon, 10 Mar 2025 16:59:18 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> Both these functions write to MMU_AS_CONTROL register in the same way.
>> Define a common _panfrost_mmu_as_control_write function with the shared
>> code.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> ---
>>   drivers/gpu/drm/panfrost/panfrost_mmu.c | 33 ++++++++++++-------------
>>   1 file changed, 16 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> index 294f86b3c25e7..31df3a96f89bd 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> @@ -121,38 +121,37 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>>   	return ret;
>>   }
>>   
>> -static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>> +static void
>> +_panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
>> +			       u64 transtab, u64 memattr)
> 
> I'm honestly not convinced this is needed. Let's just stick to
> panfrost_mmu_enable/disable().

Ok, will drop in v2.

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From rogerq at kernel.org  Wed Mar 12 06:39:25 2025
From: rogerq at kernel.org (Roger Quadros)
Date: Wed, 12 Mar 2025 15:39:25 +0200
Subject: [PATCH net v3] net: ethernet: ti: am65-cpsw: Fix NAPI
 registration sequence
In-Reply-To: <20250311154259.102865-1-s-vadapalli@ti.com>
References: <20250311154259.102865-1-s-vadapalli@ti.com>
Message-ID: <80a1f61a-b2aa-414f-b446-087db7fc54a5@kernel.org>



On 11/03/2025 17:42, Siddharth Vadapalli wrote:
> From: Vignesh Raghavendra <vigneshr at ti.com>
> 
> Registering the interrupts for TX or RX DMA Channels prior to registering
> their respective NAPI callbacks can result in a NULL pointer dereference.
> This is seen in practice as a random occurrence since it depends on the
> randomness associated with the generation of traffic by Linux and the
> reception of traffic from the wire.
> 
> Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> Co-developed-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

Reviewed-by: Roger Quadros <rogerq at kernel.org>



From vigneshr at ti.com  Wed Mar 12 06:43:57 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Wed, 12 Mar 2025 19:13:57 +0530
Subject: [GIT PULL 1/2] arm64: dts: ti: K3 devicetree updates for v6.15
Message-ID: <5d612c0e-4cd4-469a-9856-dd4552d74412@ti.com>

Hi ARM SoC Maintainers,


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git tags/ti-k3-dt-for-v6.15

for you to fetch changes up to 377fde74eae4abcbcd5475676d58fb595a07ff85:

  arm64: dts: ti: k3-am62a-phycore-som: Reorder properties per DTS coding style (2025-03-07 18:48:05 +0530)

----------------------------------------------------------------
TI K3 device tree updates for v6.15

Generic Fixups/Cleanups:

SoC Specific features and Fixes:
AM62Ax:
Enable MCU domain pinctrl node

J784S4/J742S4:
GICD reg size fixes
Serdes lane ctrl reg mux mask fix

AM62P/J722s:
Wakeup UART0 sysc updates for system wakeup
pinctrl node fixes drop pinctrl-single,gpio-ranges
BCDMA CSI-RX support
Audio REFCLKx output support

Board Specific:
J784S4:
EVM: Cleanup duplicate gpio-hogs

J722S:
TypeC port mux selection fix

AM62Ax
SK: boot-phase tag to support USB bootmode
RTC support
Aliases for wakeup and MCU serial UARTs

AM62P
SK: boot-phase tag to support USB bootmode
USB wakeup support
Aliases for wakeup and MCU serial UARTs

AM62:
verdin-dahila: microphone support
SK: Aliases for wakeup and MCU serial UARTs
BeaglePlay: reserved CMA region for Multimedia applications

J721e:
SK/EVM: boot-phase tags for Serdes for DFU boot

Phytech board updates:
Boot-phase tag updates for AM64/AM62/AM62A boards
DTS coding style cleanups
RTOS IPC reserved-memory additions
DT overlay for X27 Connectors on AM64 SOMs

J721S2 SOM:
Add flash partitions

----------------------------------------------------------------
Daniel Schultz (1):
      arm64: dts: ti: am64-phyboard-electra: Add DT overlay for X27 connector

Francesco Dolcini (1):
      arm64: dts: ti: k3-am62p: Enable AUDIO_REFCLKx

Hrushikesh Salunke (1):
      arm64: dts: ti: k3-j722s-evm: Fix USB2.0_MUX_SEL to select Type-C

Jayesh Choudhary (1):
      arm64: dts: ti: k3-j784s4-evm-quad-port-eth-exp1: Remove duplicate hogs

Keerthy (1):
      arm64: dts: ti: k3-j784s4-j742s2-main-common: Correct the GICD size

Markus Schneider-Pargmann (2):
      arm64: dts: ti: k3-am62x-sk-common: Add serial aliases
      arm64: dts: ti: k3-am62a7-sk: Add serial alias

Michael Walle (2):
      arm64: dts: ti: k3-am62p: fix pinctrl settings
      arm64: dts: ti: k3-j722s: fix pinctrl settings

Nishanth Menon (1):
      arm64: dts: ti: k3-am625-beagleplay: Reserve 128MiB of global CMA

Sai Sree Kartheek Adivi (1):
      arm64: dts: ti: k3-am62a-mcu: enable mcu domain pinmux

Siddharth Vadapalli (6):
      arm64: dts: ti: k3-am62a7-sk: Add boot phase tag for USB0
      arm64: dts: ti: k3-am62p5-sk: Add boot phase tag for USB0
      arm64: dts: ti: k3-j721e-common-proc-board: Add boot phase tag to SERDES3
      arm64: dts: ti: k3-j721e-sk: Add boot phase tag to SERDES3
      arm64: dts: ti: k3-am62p5-sk: Support SoC wakeup using USB1 wakeup
      arm64: dts: ti: k3-j784s4-j742s2-main-common: Fix serdes_ln_ctrl reg-masks

Stefan Eichenberger (1):
      arm64: dts: ti: k3-am62-verdin-dahlia: add Microphone Jack to sound card

Udit Kumar (1):
      arm64: dts: ti: k3-j721s2-som-p0: Add flash partition details

Vaishnav Achath (3):
      arm64: dts: ti: k3-j722s-main: Add BCDMA CSI overrides
      arm64: dts: ti: k3-j722s-main: Add CSI2RX nodes
      arm64: dts: ti: k3-j722s-evm: Add camera peripherals

Vibhore Vardhan (3):
      arm64: dts: ti: k3-am62a7-sk: Add alias for RTC
      arm64: dts: ti: k3-am62p-j722s-common-wakeup: Configure ti-sysc for wkup_uart0
      arm64: dts: ti: k3-am62p5-sk: Add serial alias

Wadim Egorov (7):
      arm64: dts: ti: k3-am64-phycore-som: Reserve RTOS IPC memory
      arm64: dts: ti: k3-am62-phycore-som: Reserve RTOS IPC memory
      arm64: dts: ti: k3-am62x-phyboard-lyra: Add boot phase tags
      arm64: dts: ti: k3-am62a-phycore-som: Add boot phase tags
      arm64: dts: ti: k3-am642-phyboard-electra: Add boot phase tags
      arm64: dts: ti: k3-am642-phyboard-electra: Reorder properties per DTS coding style
      arm64: dts: ti: k3-am62a-phycore-som: Reorder properties per DTS coding style

 arch/arm64/boot/dts/ti/Makefile                               |   3 +
 arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi               |  25 +-
 arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi             |   6 +-
 arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts                |   8 +
 arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi                      |   1 -
 arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi              |  19 +-
 arch/arm64/boot/dts/ti/k3-am62a7-sk.dts                       |   4 +
 arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi         |   8 -
 arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi      |  36 +-
 arch/arm64/boot/dts/ti/k3-am62p-main.dtsi                     |  26 +-
 arch/arm64/boot/dts/ti/k3-am62p5-sk.dts                       |   4 +-
 arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi            |   9 +
 arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi                |   2 +
 arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi               |  33 +-
 arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts      |  19 +-
 .../ti/k3-am642-phyboard-electra-x27-gpio1-spi1-uart3.dtso    |  63 +++
 arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts         |   1 +
 arch/arm64/boot/dts/ti/k3-j721e-sk.dts                        |   1 +
 arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi                  |  41 ++
 arch/arm64/boot/dts/ti/k3-j722s-evm.dts                       |  30 +-
 arch/arm64/boot/dts/ti/k3-j722s-main.dtsi                     | 208 +++++++++-
 arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso  |   7 -
 arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi      |   6 +-
 23 files changed, 488 insertions(+), 72 deletions(-)
 create mode 100644 arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-x27-gpio1-spi1-uart3.dtso
-- 
Regards
Vignesh
https://ti.com/opensource



From vigneshr at ti.com  Wed Mar 12 06:46:21 2025
From: vigneshr at ti.com (Vignesh Raghavendra)
Date: Wed, 12 Mar 2025 19:16:21 +0530
Subject: [GIT PULL 2/2] arm64: defconfig: Updates for v6.15 for TI K3
 platforms
In-Reply-To: <5d612c0e-4cd4-469a-9856-dd4552d74412@ti.com>
References: <5d612c0e-4cd4-469a-9856-dd4552d74412@ti.com>
Message-ID: <dec6ccc4-76df-47c3-8622-2c08035eff3e@ti.com>

The following changes since commit c7691aec5e991cec9c5c5fdab08c24856a1fc56f:

  arm64: defconfig: Enable TISCI Interrupt Router and Aggregator (2025-02-06 09:10:24 +0530)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git tags/ti-k3-config-for-v6.15

for you to fetch changes up to 75a41c26351a77cd5dd01e14d059eaf11358689c:

  arm64: defconfig: Enable SPI NAND flashes (2025-03-07 16:33:25 +0530)

----------------------------------------------------------------
TI K3 defconfig updates for v6.15

- Enable Support for SPI NAND flashes on AM62Ax/J721s2 and other boards
- HSR protocol support for AM65/AM64 ICSSG based multi-port ethernet
- Greybus modules to support CC1352P7 chips on BeaglePlay

----------------------------------------------------------------
Ayush Singh (1):
      arm64: defconfig: Enable gb_beagleplay

Ravi Gunasekaran (1):
      arm64: defconfig: Enable HSR protocol driver

Santhosh Kumar K (1):
      arm64: defconfig: Enable SPI NAND flashes

 arch/arm64/configs/defconfig | 4 ++++
 1 file changed, 4 insertions(+)


From jonas at kwiboo.se  Wed Mar 12 07:00:57 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 12 Mar 2025 15:00:57 +0100
Subject: (subset) [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for
 RK3528
In-Reply-To: <174176555637.249409.2785731072183565436.b4-ty@sntech.de>
References: <20250307120004.959980-1-amadeus@jmu.edu.cn>
 <174176555637.249409.2785731072183565436.b4-ty@sntech.de>
Message-ID: <a5ec9062-ca57-4748-8c0f-fb5b9c75fa28@kwiboo.se>

Hi Heiko,

On 2025-03-12 08:45, Heiko Stuebner wrote:
> 
> On Fri, 07 Mar 2025 20:00:02 +0800, Chukun Pan wrote:
>> Add pwm nodes for RK3528. Most rk3528 boards use pwm-regulator to
>> supply to CPU, add node to enable them. The PWM core on RK3528 is
>> the same as RK3328, but the driver doesn't support interrupts yet.
>>
>> Unlike other SoCs, pinctrl-names need to be in "active" state,
>> I'm not sure about this, but otherwise the pwm-regulator will
>> not work properly.
>>
>> [...]
> 
> Applied, thanks!

The pinctrl-names should be changed to "default" and not "active",
something you can fixup or do you want a patch?

In commit 96d8d3253246 ("arm64: dts: rockchip: Fix PWM pinctrl names")
similar issue was corrected for current rockchip boards.

Regards,
Jonas

> 
> [2/2] arm64: dts: rockchip: Add pwm nodes for RK3528
>       commit: 2973d077aedfc114affab96c3b2c7286163cc8c9
> 
> Best regards,



From mbenes at suse.cz  Wed Mar 12 07:05:07 2025
From: mbenes at suse.cz (Miroslav Benes)
Date: Wed, 12 Mar 2025 15:05:07 +0100 (CET)
Subject: [PATCH 2/2] arm64: Implement HAVE_LIVEPATCH
In-Reply-To: <20250308012742.3208215-3-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org> <20250308012742.3208215-3-song@kernel.org>
Message-ID: <alpine.LSU.2.21.2503121503340.12980@pobox.suse.cz>

Hi,

On Fri, 7 Mar 2025, Song Liu wrote:

> This is largely based on [1] by Suraj Jitindar Singh.
> 
> Test coverage:
> 
> - Passed manual tests with samples/livepatch.
> - Passed all but test-kprobe.sh in selftests/livepatch.
>   test-kprobe.sh is expected to fail, because arm64 doesn't have
>   KPROBES_ON_FTRACE.

Correct. The test should take into account and bail out.

> - Passed tests with kpatch-build [2]. (This version includes commits that
>   are not merged to upstream kpatch yet).
> 
> [1] https://lore.kernel.org/all/20210604235930.603-1-surajjs at amazon.com/
> [2] https://github.com/liu-song-6/kpatch/tree/fb-6.13
> Cc: Suraj Jitindar Singh <surajjs at amazon.com>
> Cc: Torsten Duwe <duwe at suse.de>
> Signed-off-by: Song Liu <song at kernel.org>

Acked-by: Miroslav Benes <mbenes at suse.cz>

Also as mentioned in the other thread, parts of this patch will go once 
arm64 is converted to generic entry infrastructure.

Thank you,
Miroslav


From linux at armlinux.org.uk  Wed Mar 12 07:13:54 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 14:13:54 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
Message-ID: <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>

On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > +	/* AXI 1G/2.5G ethernet IP has following synthesis options:
> > +	 * 1) SGMII/1000base-X only.
> > +	 * 2) 2500base-X only.
> > +	 * 3) Dynamically switching between (1) and (2), and is not
> > +	 * implemented in driver.
> > +	 */
> > +
> > +	if (axienet_ior(lp, XAE_ABILITY_OFFSET) & XAE_ABILITY_2_5G)
> 
> How can we tell if the synthesis allows 3)?
> 
> Don't we have a backwards compatibility issue here? Maybe there are
> systems which have been synthesised with 3), but are currently limited
> to 1) due to the driver. If you don't differentiate between 2 and 3,
> such systems are going to swap to 2) and regress.

We've discussed this before... but because the author doesn't post
regularly enough, it's not suprising that context keeps getting lost.

Here's the discussion from 20th February 2025 on a patch series that I
commented on on 19th November 2024.

https://lore.kernel.org/r/BL3PR12MB6571FE73FA8D5AAB9FB4BB3CC9C42 at BL3PR12MB6571.namprd12.prod.outlook.com

Suraj Gupta - you _must_ be more responsive so that reviewers can keep
the context of previous discussions in their heads to avoid going over
the same points time and time again. If you can't do that (and it's a
good idea anyway) then you need to supplement the commit descriptions
with the salient points from the previous patch series discussion to
remind reviewers of the appropriate context.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From Frank.li at nxp.com  Wed Mar 12 07:22:19 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 12 Mar 2025 10:22:19 -0400
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <fcb5f09f8e4311c7a6ef60aaf3cb4e3f05a8f05e.camel@pengutronix.de>
References: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>
 <20250311155452.GA629749@bhelgaas>
 <DU2PR04MB8677AC699DF11D847AB768708CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>
 <fcb5f09f8e4311c7a6ef60aaf3cb4e3f05a8f05e.camel@pengutronix.de>
Message-ID: <Z9GYm/jp9VIhCEeY@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > -----Original Message-----
> > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > Sent: 2025?3?11? 23:55
> > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > hardcodes
> > >
> > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > -----Original Message-----
> > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > Sent: 2025?3?10? 23:11
> > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > > bhelgaas at google.com;
> > > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > hardcodes
> > > > >
> > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > >
> > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > ---
> > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > @@ -41,7 +41,6 @@
> > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > 8)
> > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > >
> > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > platform_device
> > > > > *pdev)
> > > > > > ?	struct dw_pcie *pci;
> > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > ?	struct device_node *np;
> > > > > > -	struct resource *dbi_base;
> > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > ?	int i, ret, req_cnt;
> > > > > > ?	u16 val;
> > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > platform_device *pdev)
> > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > ?	}
> > > > > >
> > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > 0,
> > > > > &dbi_base);
> > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > -		return PTR_ERR(pci->dbi_base);
> > > > >
> > > > > This makes me wonder.
> > > > >
> > > > > IIUC this means that previously we set controller_id to 1 if the
> > > > > first item in devicetree "reg" was 0x33c00000, and now we will set
> > > > > controller_id to 1 if the devicetree "linux,pci-domain" property is 1.
> > > > > This is good, but I think this new dependency on the correct
> > > > > "linux,pci-domain" in devicetree should be mentioned in the commit log.
> > > > >
> > > > > My bigger worry is that we no longer set pci->dbi_base at all.  I
> > > > > see that the only use of pci->dbi_base in pci-imx6.c was to
> > > > > determine the controller_id, but this is a DWC-based driver, and the
> > > > > DWC core certainly uses
> > > > > pci->dbi_base.  Are we sure that none of those DWC core paths are
> > > > > important to pci-imx6.c?
> > > > Hi Bjorn:
> > > > Thanks for your concerns.
> > > > Don't worry about the assignment of pci->dbi_base.
> > > > If pci-imx6.c driver doesn't set it. DWC core driver would set it when
> > > > ?dw_pcie_get_resources() is invoked.
> > >
> > > Great, thanks!  Maybe we can amend the commit log to mention that and
> > > the new "linux,pci-domain" dependency.
> > How about the following updates of the commit log?
> >
> > Use the domain number replace the hardcodes to uniquely identify
> > different controller on i.MX8MQ platforms. No function changes.
> > Please make sure the " linux,pci-domain" is set for i.MX8MQ correctly, since
> > ?the controller id is relied on it totally.
> >
> This breaks running a new kernel on an old DT without the
> linux,pci-domain property, which I'm absolutely no fan of. We tried
> really hard to keep this way around working in the i.MX world.

8MQ already add linux,pci-domain since Jan, 2021

commit c0b70f05c87f3b09b391027c6f056d0facf331ef
Author: Peng Fan <peng.fan at nxp.com>
Date:   Fri Jan 15 11:26:57 2021 +0800

Only missed is pcie-ep side, which have not been used at all boards dts
file in upstream.

Frank

>
> I'm fine with using the property if present and even mandating it for
> new platforms, but getting rid of the existing code for the i.MX8MQ
> platform is only a marginal cleanup of the driver code with the obvious
> downside of the above breakage.



>
> Regards,
> Lucas


From ariel.dalessandro at collabora.com  Wed Mar 12 07:20:33 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Wed, 12 Mar 2025 11:20:33 -0300
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <760e3112-0433-41ab-ab39-faaf0463fbe8@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
 <760e3112-0433-41ab-ab39-faaf0463fbe8@collabora.com>
Message-ID: <d2ec6fe3-db78-4e8b-ac81-fd4c631a599b@collabora.com>

Angelo,

On 3/11/25 6:10 AM, AngeloGioacchino Del Regno wrote:
> Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>> Address Extension", which in Linux we've called "mali_lpae".
>>
>> This commit adds support for conditionally enabling AARCH64_4K page
>> table format. To achieve that, a "GPU optional configurations" field was
>> added to `struct panfrost_features` with the related flag.

[snip]

>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/ 
>> drm/panfrost/panfrost_mmu.c
>> index 31df3a96f89bd..4a9b8de2ff987 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c

[snip]

>> +static void panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
>> +????????????????? enum io_pgtable_fmt fmt)
>> +{
>> +??? struct panfrost_device *pfdev = mmu->pfdev;
>> +
>> +??? switch (fmt) {
>> +??? case ARM_64_LPAE_S1:
>> +??????? mmu_cfg_init_aarch64_4k(mmu);
>> +??????? break;
>> +??? case ARM_MALI_LPAE:
>> +??????? mmu_cfg_init_mali_lpae(mmu);
>> +??????? break;
>> +??? default:
> 
> If you add a
>  ??????? /* That should never happen */
> 
> ...it's clear-er why this function doesn't fail (but still raises some 
> eyebrows,
> because if the `default` case is not reachable, why does it even have a 
> print?).

Makes sense. In that case, makes sense to just simplify it as:

         default:
                 /* This should never happen */
                 WARN_ON(1);
                 break;

>> +??????? dev_WARN_ONCE(pfdev->dev, 1, "Unhandled page table format\n");
>> +??????? break;
>> +??? }
>> +}
>> +
>> ? static void
>> ? _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 
>> as_nr,
>> -?????????????????? u64 transtab, u64 memattr)
>> +?????????????????? u64 transtab, u64 memattr, u64 transcfg)
>> ? {
>> ????? mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, 
>> AS_COMMAND_FLUSH_MEM);
>> @@ -133,25 +223,28 @@ _panfrost_mmu_as_control_write(struct 
>> panfrost_device *pfdev, u32 as_nr,
>> ????? mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>> ????? mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>> +??? mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
>> +??? mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
>> +
>> ????? write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>> +
>> +??? dev_dbg(pfdev->dev, "mmu_as_control: as=%d, transtab=0x%016llx, 
>> memattr=0x%016llx, transcfg=0x%016llx",
>> +??????? as_nr, transtab, memattr, transcfg);
>> ? }
>> ? static void panfrost_mmu_enable(struct panfrost_device *pfdev, 
>> struct panfrost_mmu *mmu)
>> ? {
>> -??? int as_nr = mmu->as;
>> -??? struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
>> -??? u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
>> -??? u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
>> -
>> ????? /* Need to revisit mem attrs.
>> ?????? * NC is the default, Mali driver is inner WT.
>> ?????? */
>> -??? _panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
>> +??? _panfrost_mmu_as_control_write(pfdev, mmu->as, mmu->cfg.transtab,
>> +?????????????????????? mmu->cfg.memattr, mmu->cfg.transcfg);
>> ? }
>> ? static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 
>> as_nr)
>> ? {
>> -??? _panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
>> +??? _panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0,
>> +?????????????????????? AS_TRANSCFG_ADRMODE_UNMAPPED);
>> ? }
>> ? u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct 
>> panfrost_mmu *mmu)
>> @@ -616,6 +709,7 @@ struct panfrost_mmu 
>> *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>> ? {
>> ????? u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev- 
>> >features.mmu_features);
>> ????? u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev- 
>> >features.mmu_features);
>> +??? enum io_pgtable_fmt fmt = ARM_MALI_LPAE;
> 
> Double initialization! :-)

Will fix in v2.

>> ????? struct panfrost_mmu *mmu;
>> ????? mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>> @@ -641,16 +735,28 @@ struct panfrost_mmu 
>> *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>> ????????? .iommu_dev??? = pfdev->dev,
>> ????? };
>> -??? mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu- 
>> >pgtbl_cfg,
>> -????????????????????????? mmu);
>> -??? if (!mmu->pgtbl_ops) {
>> -??????? kfree(mmu);
>> -??????? return ERR_PTR(-EINVAL);
>> +??? if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {
> 
> Why aren't you performing this check before kzalloc?
> 
> If you do so, you will be able to avoid having a goto, because this 
> check will
> simply return an error (struct not allocated yet, nothing to kfree).
> This also means that you won't have to modify anything about the error 
> handling
> of the alloc_io_pgtable_ops below....

Yup, definitely agreed. Thanks!

>> +??????? if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
>> +??????????? dev_err_once(pfdev->dev,
>> +???????????????????? "AARCH64_4K page table not supported\n");
>> +??????????? goto err_free_mmu;
>> +??????? }
>> +??????? fmt = ARM_64_LPAE_S1;
>> ????? }
> 
> } else {
>  ????fmt = ARM_MALI_LPAE;
> }

Ack. Will fix in v2.

> 
>> +??? mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
>> +??? if (!mmu->pgtbl_ops)
>> +??????? goto err_free_mmu;
>> +
>> +??? panfrost_mmu_cfg_init(mmu, fmt);
>> +
>> ????? kref_init(&mmu->refcount);
>> ????? return mmu;
>> +
>> +err_free_mmu:
>> +??? kfree(mmu);
>> +??? return ERR_PTR(-EINVAL);
>> ? }
>> ? static const char *access_type_name(struct panfrost_device *pfdev,
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/ 
>> drm/panfrost/panfrost_regs.h
>> index b5f279a19a084..2b8f1617b8369 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
>> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
>> @@ -301,6 +301,17 @@
>> ? #define AS_TRANSTAB_HI(as)??????? (MMU_AS(as) + 0x04) /* (RW) 
>> Translation Table Base Address for address space n, high word */
>> ? #define AS_MEMATTR_LO(as)??????? (MMU_AS(as) + 0x08) /* (RW) Memory 
>> attributes for address space n, low word. */
>> ? #define AS_MEMATTR_HI(as)??????? (MMU_AS(as) + 0x0C) /* (RW) Memory 
>> attributes for address space n, high word. */
>> +#define?? AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL??????? (2 << 2)
>> +#define?? AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)??? ((3 << 2) | \
>> +???????????????????????????? ((w) ? BIT(0) : 0) | \
>> +???????????????????????????? ((r) ? BIT(1) : 0))
>> +#define?? AS_MEMATTR_AARCH64_SH_MIDGARD_INNER??????? (0 << 4)
>> +#define?? AS_MEMATTR_AARCH64_SH_CPU_INNER??????? (1 << 4)
>> +#define?? AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH??? (2 << 4)
>> +#define?? AS_MEMATTR_AARCH64_SHARED??????????? (0 << 6)
>> +#define?? AS_MEMATTR_AARCH64_INNER_OUTER_NC??????? (1 << 6)
>> +#define?? AS_MEMATTR_AARCH64_INNER_OUTER_WB??????? (2 << 6)
>> +#define?? AS_MEMATTR_AARCH64_FAULT??????????? (3 << 6)
>> ? #define AS_LOCKADDR_LO(as)??????? (MMU_AS(as) + 0x10) /* (RW) Lock 
>> region address for address space n, low word */
>> ? #define AS_LOCKADDR_HI(as)??????? (MMU_AS(as) + 0x14) /* (RW) Lock 
>> region address for address space n, high word */
>> ? #define AS_COMMAND(as)??????????? (MMU_AS(as) + 0x18) /* (WO) MMU 
>> command register for address space n */
>> @@ -311,6 +322,24 @@
>> ? /* Additional Bifrost AS registers */
>> ? #define AS_TRANSCFG_LO(as)??????? (MMU_AS(as) + 0x30) /* (RW) 
>> Translation table configuration for address space n, low word */
>> ? #define AS_TRANSCFG_HI(as)??????? (MMU_AS(as) + 0x34) /* (RW) 
>> Translation table configuration for address space n, high word */
>> +#define?? AS_TRANSCFG_ADRMODE_LEGACY??????????? (0 << 0)
>> +#define?? AS_TRANSCFG_ADRMODE_UNMAPPED??????????? (1 << 0)
>> +#define?? AS_TRANSCFG_ADRMODE_IDENTITY??????????? (2 << 0)
>> +#define?? AS_TRANSCFG_ADRMODE_AARCH64_4K??????? (6 << 0)
>> +#define?? AS_TRANSCFG_ADRMODE_AARCH64_64K??????? (8 << 0)
> 
> "Anything" shifted in any direction by 0 is equal to the same 
> "anything" :-)
> 
> Those are just 0,1,2,6,8

Well, I agree... However, I'm copying this from panthor as-is. As these 
are similar drivers, I just kept all the macro definitions.

> 
>> +#define?? AS_TRANSCFG_INA_BITS(x)??????????? ((x) << 6)
>> +#define?? AS_TRANSCFG_OUTA_BITS(x)??????????? ((x) << 14)
>> +#define?? AS_TRANSCFG_SL_CONCAT??????????????? BIT(22)
>> +#define?? AS_TRANSCFG_PTW_MEMATTR_NC??????????? (1 << 24)
> 
> BIT(24)
> 
>> +#define?? AS_TRANSCFG_PTW_MEMATTR_WB??????????? (2 << 24)
> 
> BIT(25)
> 
>> +#define?? AS_TRANSCFG_PTW_SH_NS??????????????? (0 << 28)
> 
> 0
> 
>> +#define?? AS_TRANSCFG_PTW_SH_OS??????????????? (2 << 28)
> 
> BIT(29)
> 
>> +#define?? AS_TRANSCFG_PTW_SH_IS??????????????? (3 << 28)
> 
> GENMASK(29, 28) or BIT(28) | BIT(29)
> 
> (btw, rinse and repeat for the memattrs)

I think the criteria used in panfrost/panthor for these definitions is:
* if the register field is 1 bit, use BIT()
* if the register field is >1 bit, use the value (as defined in the 
datasheet) an shift it.
* and -be super explicit- do this even if the value is 0.

I don't really have a strong opinion, but I'd attach to the 
subsystem/driver criteria used as much as possible :)

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From piotr.oniszczuk at gmail.com  Wed Mar 12 07:23:15 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Wed, 12 Mar 2025 15:23:15 +0100
Subject: [PATCH v2 2/7] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <20250312104214.525242-3-andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-3-andyshrk@163.com>
Message-ID: <61E9B36C-8568-4C0E-A9A7-07FF612912AA@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 12 mar 2025, o godz. 11:42:
> 
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> The DW DP TX Controller is compliant with the DisplayPort Specification
> Version 1.4 with the following features:
> 
> * DisplayPort 1.4a
> * Main Link: 1/2/4 lanes
> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
> * AUX channel 1Mbps
> * Single Stream Transport(SST)
> * Multistream Transport (MST)
> * Type-C support (alternate mode)
> * HDCP 2.2, HDCP 1.3
> * Supports up to 8/10 bits per color component
> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
> * Pixel clock up to 594MHz
> * I2S, SPDIF audio interface
> 
> Add library with common helpers to make it can be shared with
> other SoC.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> 
> ---
> 
> Changes in v2:
> - Fix compile error when build as module
> - Add phy init
> - Only use one dw_dp_link_train_set
> - inline dw_dp_phy_update_vs_emph
> - Use dp_sdp
> - Check return value of drm_modeset_lock
> - Merge code in atomic_pre_enable/mode_fixup to atomic_check
> - Return NULL if can't find a supported output format
> - Fix max_link_rate from plat_data
> 

Andy,

Just small Q: do v2 needs something extra to get it working (particular kernel ver or extra dependency patches)?
I just replaced v1 to v2 and dp stopped to work for me.

e.g. on rock5a i?m getting:

root at myth-frontend-fafc53b591a6:~ # dmesg | grep drm
[    9.245284] panthor fb000000.gpu: [drm] clock rate = 198000000
[    9.249464] panthor fb000000.gpu: [drm] mali-g610 id 0xa867 major 0x0 minor 0x0 status 0x5
[    9.249472] panthor fb000000.gpu: [drm] Features: L2:0x7120306 Tiler:0x809 Mem:0x301 MMU:0x2830 AS:0xff
[    9.249474] panthor fb000000.gpu: [drm] shader_present=0x50005 l2_present=0x1 tiler_present=0x1
[    9.257979] panthor fb000000.gpu: [drm] Firmware protected mode entry not be supported, ignoring
[    9.258030] panthor fb000000.gpu: [drm] Firmware git sha: 814b47b551159067b67a37c4e9adda458ad9d852
[    9.258604] panthor fb000000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 Instrumentation features 0x71
[    9.259671] [drm] Initialized panthor 1.3.0 for fb000000.gpu on minor 0
[    9.324353] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
[    9.324617] rockchip-drm display-subsystem: bound fde50000.dp (ops dw_dp_rockchip_component_ops)
[    9.325202] rockchip-drm display-subsystem: bound fde80000.hdmi (ops dw_hdmi_qp_rockchip_ops)
[    9.325506] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 1
[    9.325531] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
[    9.325594] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes  

dp status is "not connected"

replacing only this patch back to v1 brings dp back to work.




From patrice.chotard at foss.st.com  Wed Mar 12 07:23:24 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Wed, 12 Mar 2025 15:23:24 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
Message-ID: <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>



On 3/11/25 17:04, Krzysztof Kozlowski wrote:
> On 19/02/2025 09:00, patrice.chotard at foss.st.com wrote:
>> From: Patrice Chotard <patrice.chotard at foss.st.com>
>>
>> Octo Memory Manager driver (OMM) manages:
>>   - the muxing between 2 OSPI busses and 2 output ports.
>>     There are 4 possible muxing configurations:
>>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>>         output is on port 2
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>>         OSPI2 output is on port 1
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>>   - the split of the memory area shared between the 2 OSPI instances.
>>   - chip select selection override.
>>   - the time between 2 transactions in multiplexed mode.
>>   - check firewall access.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
>> Signed-off-by: Christophe Kerello <christophe.kerello at foss.st.com>
> 
> Incorrect chain. You sent it, so you must be the last person signing it.

ok

> 
> I was waiting for any ST review... did not happen, so if you wonder how
> to speed things up, you got a hint. Anyway, many questions futher.
> 
> 
>> +
>> +		if (i == 1) {
>> +			mm_ospi2_size = resource_size(&res);
>> +
>> +			/* check that OMM memory region 1 doesn't overlap memory region 2 */
>> +			if (resource_overlaps(&res, &res1)) {
>> +				dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
>> +					mm_name[0], mm_name[1]);
>> +				dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
>> +
>> +				return -EFAULT;
>> +			}
>> +		}
>> +	}
>> +
>> +	syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
>> +	if (IS_ERR(syscfg_regmap)) {
>> +		dev_err(dev, "Failed to get st,syscfg-amcr property\n");
>> +		return PTR_ERR(syscfg_regmap);
> 
> Same comments as usual, see further.

ok, will use dev_err_probe()

> 
>> +	}
>> +
>> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
>> +					 &amcr_base);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
>> +					 &amcr_mask);
>> +	if (ret)
>> +		return ret;
>> +
>> +	amcr = mm_ospi2_size / SZ_64M;
>> +
>> +	if (set)
>> +		regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
>> +
>> +	/* read AMCR and check coherency with memory-map areas defined in DT */
>> +	regmap_read(syscfg_regmap, amcr_base, &read_amcr);
>> +	read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
>> +
>> +	if (amcr != read_amcr) {
>> +		dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
>> +		ret = -EINVAL;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int stm32_omm_enable_child_clock(struct device *dev, bool enable)
>> +{
>> +	/* As there is only 2 children, remember first child in case of error */
>> +	struct clk *first_child_clk = NULL;
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +	u8 i;
>> +	int ret;
>> +
>> +	for (i = 0; i < omm->nb_child; i++) {
>> +		if (enable) {
>> +			ret = clk_prepare_enable(omm->child[i].clk);
>> +			if (ret) {
>> +				if (first_child_clk)
>> +					clk_disable_unprepare(first_child_clk);
> 
> Function is called stm32_omm_enable_child_clock() but you disable.
> Confusing. Probably should be called toggle.

Agree, i will rename it to stm32_omm_toggle_child_clock

> 
>> +
>> +				dev_err(dev, "Can not enable clock\n");
>> +				return ret;
>> +			}
>> +		} else {
>> +			clk_disable_unprepare(omm->child[i].clk);
>> +		}
>> +
>> +		first_child_clk = omm->child[i].clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_omm_configure(struct device *dev)
>> +{
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +	struct reset_control *rstc;
>> +	unsigned long clk_rate, clk_rate_max = 0;
>> +	int ret;
>> +	u8 i;
>> +	u32 mux = 0;
> 
> That's one big mess. Do not mix initialized declarations with
> non-initialized in the same line. Then group initialized ones together
> and use some reverse christmas tree.
> 
> Then the rest also should be organized.

ok

> 
>> +	u32 cssel_ovr = 0;
>> +	u32 req2ack = 0;
>> +
>> +	omm->clk = devm_clk_get(dev, NULL);
> 
> So here devm_clk_get, but later of_clk_get...
> 
>> +	if (IS_ERR(omm->clk)) {
>> +		dev_err(dev, "Failed to get OMM clock (%ld)\n",
>> +			PTR_ERR(omm->clk));
>> +
> 
> No. There is no such code anywhere. Please don't upstream downstream,
> but take upstream as template.
> 
> It is *always* return dev_err_probe. You are flooding dmesg in deferral
> for no reason.

ok, will use dev_err_probe()

> 
>> +		return PTR_ERR(omm->clk);
>> +	}
>> +
>> +	ret = pm_runtime_resume_and_get(dev);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* parse children's clock */
>> +	for (i = 0; i < omm->nb_child; i++) {
>> +		clk_rate = clk_get_rate(omm->child[i].clk);
>> +		if (!clk_rate) {
>> +			dev_err(dev, "Invalid clock rate\n");
>> +			pm_runtime_disable(dev);
>> +			goto err_clk_disable;
>> +		}
>> +
>> +		if (clk_rate > clk_rate_max)
>> +			clk_rate_max = clk_rate;
>> +	}
>> +
>> +	rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
>> +	if (IS_ERR(rstc)) {
>> +		ret = dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
>> +		pm_runtime_disable(dev);
> 
> Why? It was not enabled in this function. I cannot follow the logic,
> feels like random set of calls. Each of your function is supposed to
> reverse ONLY what it done so far.

right, i will move pm_runtime_disable() outside stm32_omm_enable_child_clock()

> 
>> +		goto err_clk_disable;
>> +	}
>> +
>> +	reset_control_assert(rstc);
>> +	udelay(2);
>> +	reset_control_deassert(rstc);
>> +
>> +	omm->cr = readl_relaxed(omm->io_base + OMM_CR);
>> +	/* optional */
>> +	ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
>> +	if (!ret) {
>> +		if (mux & CR_MUXEN) {
>> +			ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
>> +						   &req2ack);
>> +			if (!ret && !req2ack) {
>> +				req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
>> +
>> +				if (req2ack > 256)
>> +					req2ack = 256;
>> +			}
>> +
>> +			req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
>> +
>> +			omm->cr &= ~CR_REQ2ACK_MASK;
>> +			omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
>> +
>> +			/*
>> +			 * If the mux is enabled, the 2 OSPI clocks have to be
>> +			 * always enabled
>> +			 */
>> +			ret = stm32_omm_enable_child_clock(dev, true);
>> +			if (ret) {
>> +				pm_runtime_disable(dev);
>> +				goto err_clk_disable;
>> +			}
>> +		}
>> +
>> +		omm->cr &= ~CR_MUXENMODE_MASK;
>> +		omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
>> +	}
>> +
>> +	/* optional */
>> +	ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
>> +	if (!ret) {
>> +		omm->cr &= ~CR_CSSEL_OVR_MASK;
>> +		omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
>> +		omm->cr |= CR_CSSEL_OVR_EN;
>> +	}
>> +
>> +	omm->restore_omm = true;
>> +	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
>> +
>> +	ret = stm32_omm_set_amcr(dev, true);
>> +
>> +err_clk_disable:
>> +	pm_runtime_put_sync_suspend(dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static int stm32_omm_check_access(struct device *dev, struct device_node *np)
>> +{
>> +	struct stm32_firewall firewall;
>> +	int ret;
>> +
>> +	ret = stm32_firewall_get_firewall(np, &firewall, 1);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return stm32_firewall_grant_access(&firewall);
>> +}
>> +
>> +static int stm32_omm_disable_child(struct device *dev)
>> +{
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +	struct reset_control *reset;
>> +	int ret;
>> +	u8 i;
>> +
>> +	for (i = 0; i < omm->nb_child; i++) {
>> +		ret = clk_prepare_enable(omm->child[i].clk);
>> +		if (ret) {
>> +			dev_err(dev, "Can not enable clock\n");
>> +			return ret;
>> +		}
>> +
>> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
>> +		if (IS_ERR(reset)) {
>> +			dev_err(dev, "Can't get child reset\n");
> 
> Why do you get reset of child? Parent is not suppposed to poke there.
> You might not have the reset there in the first place and it would not
> be an error.

By ressetting child (OSPI), we ensure they are disabled and in a known state.
See the comment below.

> 
> 
>> +			return PTR_ERR(reset);
>> +		};
>> +
>> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
>> +		reset_control_assert(reset);
>> +		udelay(2);
>> +		reset_control_deassert(reset);
> 
> No, the child should handle this, not parent.

Octo Memory Manager can only be configured if both child are disabled.
That's why here, parent handles this.

> 
>> +
>> +		reset_control_put(reset);
>> +		clk_disable_unprepare(omm->child[i].clk);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_omm_probe(struct platform_device *pdev)
>> +{
>> +	struct platform_device *vdev;
>> +	struct device *dev = &pdev->dev;
>> +	struct stm32_omm *omm;
>> +	struct clk *clk;
>> +	int ret;
>> +	u8 child_access_granted = 0;
> 
> Keep inits/assignments together

ok

> 
>> +	u8 i, j;
>> +	bool child_access[OMM_CHILD_NB];
>> +
>> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
>> +	if (!omm)
>> +		return -ENOMEM;
>> +
>> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
>> +	if (IS_ERR(omm->io_base))
>> +		return PTR_ERR(omm->io_base);
>> +
>> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
>> +	if (IS_ERR(omm->mm_res))
>> +		return PTR_ERR(omm->mm_res);
>> +
>> +	/* check child's access */
>> +	for_each_child_of_node_scoped(dev->of_node, child) {
>> +		if (omm->nb_child >= OMM_CHILD_NB) {
>> +			dev_err(dev, "Bad DT, found too much children\n");
>> +			ret = -E2BIG;
>> +			goto err_clk_release;
>> +		}
>> +
>> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
>> +			ret = -EINVAL;
>> +			goto err_clk_release;
>> +		}
>> +
>> +		ret = stm32_omm_check_access(dev, child);
>> +		if (ret < 0 && ret != -EACCES)
>> +			goto err_clk_release;
>> +
>> +		child_access[omm->nb_child] = false;
>> +		if (!ret) {
>> +			child_access_granted++;
>> +			child_access[omm->nb_child] = true;
>> +		}
>> +
>> +		omm->child[omm->nb_child].node = child;
>> +
>> +		clk = of_clk_get(child, 0);
> 
> Why are you taking children clock? And why with this API, not clk_get?

I need children's clock to reset them.
Why of_clk_get() usage is a problem here ? i can't get your point ?

> This looks like mixing clock provider in the clock consumer.
> 
>> +		if (IS_ERR(clk)) {
>> +			dev_err(dev, "Can't get child clock\n");
> 
> Syntax is always return dev_err_probe (or ret = dev_err_probe).

ok

> 
>> +			ret = PTR_ERR(clk);
>> +			goto err_clk_release;
>> +		};
>> +
>> +		omm->child[omm->nb_child].clk = clk;
>> +		omm->nb_child++;
>> +	}
>> +
>> +	if (omm->nb_child != OMM_CHILD_NB) {
>> +		ret = -EINVAL;
>> +		goto err_clk_release;
>> +	}
>> +
>> +	platform_set_drvdata(pdev, omm);
>> +
>> +	pm_runtime_enable(dev);
>> +
>> +	/* check if OMM's resource access is granted */
>> +	ret = stm32_omm_check_access(dev, dev->of_node);
>> +	if (ret < 0 && ret != -EACCES)
>> +		goto err_clk_release;
>> +
>> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
>> +		/* Ensure both OSPI instance are disabled before configuring OMM */
>> +		ret = stm32_omm_disable_child(dev);
>> +		if (ret)
>> +			goto err_clk_release;
>> +
>> +		ret = stm32_omm_configure(dev);
>> +		if (ret)
>> +			goto err_clk_release;
>> +	} else {
>> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
>> +		/*
>> +		 * AMCR can't be set, so check if current value is coherent
>> +		 * with memory-map areas defined in DT
>> +		 */
>> +		ret = stm32_omm_set_amcr(dev, false);
>> +		if (ret)
>> +			goto err_clk_release;
>> +	}
>> +
>> +	/* for each child, if resource access is granted and status "okay", probe it */
>> +	for (i = 0; i < omm->nb_child; i++) {
>> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
> 
> If you have a device available, why do you create one more platform device?
> 
>> +			continue;
>> +
>> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
> 
> Why you cannot just populate the children?

I can't use of_platform_populate(), by default it will populate all OMM's child.
Whereas here, we want to probe only the OMM's child which match our criteria.  

> 
>> +		if (!vdev) {
>> +			dev_err(dev, "Failed to create Octo Memory Manager child\n");
>> +			for (j = i; j > 0; --j) {
>> +				if (omm->child[j].dev)
>> +					of_platform_device_destroy(omm->child[j].dev, NULL);
>> +			}
>> +
>> +			ret = -EINVAL;
>> +			goto err_clk_release;
>> +		}
>> +		omm->child[i].dev = &vdev->dev;
>> +	}
>> +
>> +err_clk_release:
>> +	for (i = 0; i < omm->nb_child; i++)
>> +		clk_put(omm->child[i].clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static void stm32_omm_remove(struct platform_device *pdev)
>> +{
>> +	struct stm32_omm *omm = platform_get_drvdata(pdev);
>> +	int i;
>> +
>> +	for (i = 0; i < omm->nb_child; i++)
>> +		if (omm->child[i].dev)
>> +			of_platform_device_destroy(omm->child[i].dev, NULL);
>> +
>> +	if (omm->cr & CR_MUXEN)
>> +		stm32_omm_enable_child_clock(&pdev->dev, false);
>> +
>> +	pm_runtime_disable(&pdev->dev);
>> +}
>> +
>> +static const struct of_device_id stm32_omm_of_match[] = {
>> +	{ .compatible = "st,stm32mp25-omm", },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
>> +
>> +static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
>> +{
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +
>> +	clk_disable_unprepare(omm->clk);
>> +
>> +	return 0;
>> +}
>> +
>> +static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
>> +{
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +
>> +	return clk_prepare_enable(omm->clk);
>> +}
>> +
>> +static int __maybe_unused stm32_omm_suspend(struct device *dev)
>> +{
>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>> +
>> +	if (omm->restore_omm && omm->cr & CR_MUXEN)
>> +		stm32_omm_enable_child_clock(dev, false);
> 
> Why do you enable child clock for suspend?

The child clock is disbaled here, but as you indicated earlier in this patch,
stm32_omm_enable_child_clock() will be renamed stm32_omm_toggle_child_clock() 
to avoid confussion.

Thanks
Patrice

> 
>> +
>> +	return pinctrl_pm_select_sleep_state(dev);
>> +}
>> +
> 
> 
> Best regards,
> Krzysztof


From michal.kubiak at intel.com  Wed Mar 12 07:32:14 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Wed, 12 Mar 2025 15:32:14 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
Message-ID: <Z9Ga7gx1u3JsOemE@localhost.localdomain>

On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> The system occasionally crashes dereferencing a NULL pointer when it is
> forwarding constant, high load bidirectional traffic.
> 
> [ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
> [ 2149.925812] Mem abort info:
> [ 2149.928713]   ESR = 0x0000000096000005
> [ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
> [ 2149.938429]   SET = 0, FnV = 0
> [ 2149.941814]   EA = 0, S1PTW = 0
> [ 2149.945187]   FSC = 0x05: level 1 translation fault
> [ 2149.950348] Data abort info:
> [ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
> [ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
> [ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
> [ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
> [ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
> [ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
> [ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
> [ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
> [ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> [ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
> [ 2150.218149] sp : ffffffc080e8ba10
> [ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
> [ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
> [ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
> [ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
> [ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
> [ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
> [ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
> [ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
> [ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
> [ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
> [ 2150.292811] Call trace:
> [ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> [ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
> [ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
> [ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
> [ 2150.318200]  process_one_work+0x178/0x2f0
> [ 2150.322211]  worker_thread+0x2e4/0x4cc
> [ 2150.325953]  kthread+0xd8/0xdc
> [ 2150.329008]  ret_from_fork+0x10/0x20
> [ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
> [ 2150.338681] ---[ end trace 0000000000000000 ]---
> [ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
> [ 2150.349035] SMP: stopping secondary CPUs
> [ 2150.352954] Kernel Offset: disabled
> [ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
> [ 2150.361743] Memory Limit: none
> 
> Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> routine.
> 
> Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")

The patch has "Fixes" tag, but it is sent to "net-next" tree.
I think it's rather a candidate for "net".

> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> ---
>  drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++
>  drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
>  drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
>  3 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index c0a642568ac115ea9df6fbaf7133627a4405a36c..776222595b84e4fba6ae5943420e0edf0d0ecf8f 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -2454,6 +2454,22 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
>  	}
>  }
>  
> +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> +			     struct airoha_gdm_port *port)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {

You could reduce the number of lines by moving the declaration inside the
loop:
	for (int i = 0; i < ARRAY_SIZE(eth->ports); i++) {

> +		if (!eth->ports[i])
> +			continue;

Isn't this NULL check redundant?
In the second check you compare the table element to a real pointer.

> +
> +		if (eth->ports[i] == port)
> +			return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
>  				 struct device_node *np, int index)
>  {
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
>  #define airoha_qdma_clear(qdma, offset, val)			\
>  	airoha_rmw((qdma)->regs, (offset), (val), 0)
>  
> +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> +			     struct airoha_gdm_port *port);
> +
>  void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
>  int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
>  				 void *cb_priv);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
>  #endif
>  }
>  
> -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> +					struct airoha_foe_entry *hwe,
>  					struct net_device *dev, int type,
>  					struct airoha_flow_data *data,
>  					int l4proto)
> @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
>  	if (dev) {
>  		struct airoha_gdm_port *port = netdev_priv(dev);
>  		u8 pse_port;
> +		int err;
> +
> +		err = airoha_is_valid_gdm_port(eth, port);
> +		if (err)
> +			return err;
>  
>  		if (dsa_port >= 0)
>  			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
> @@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
>  	    !is_valid_ether_addr(data.eth.h_dest))
>  		return -EINVAL;
>  
> -	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
> +	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
>  					   &data, l4proto);
>  	if (err)
>  		return err;
> 
> ---
> base-commit: 0ea09cbf8350b70ad44d67a1dcb379008a356034
> change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a
> 
> Best regards,
> -- 
> Lorenzo Bianconi <lorenzo at kernel.org>
> 
> 


From baolu.lu at linux.intel.com  Wed Mar 12 07:34:44 2025
From: baolu.lu at linux.intel.com (Baolu Lu)
Date: Wed, 12 Mar 2025 22:34:44 +0800
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <d55240a4-fe4a-48ea-b3a8-9a997bb7267c@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <Z9CEIlXoQJ-A0t-d@8bytes.org> <d55240a4-fe4a-48ea-b3a8-9a997bb7267c@arm.com>
Message-ID: <f30eabf8-86dc-48f3-9f6c-0c1600527cac@linux.intel.com>

On 2025/3/12 18:10, Robin Murphy wrote:
> On 2025-03-11 6:42 pm, Joerg Roedel wrote:
>> Hi Robin,
>>
>> On Fri, Feb 28, 2025 at 03:46:33PM +0000, Robin Murphy wrote:
>>> +??? /*
>>> +???? * And if we do now see any replay calls, they would indicate 
>>> someone
>>> +???? * misusing the dma_configure path outside bus code.
>>> +???? */
>>> +??? if (dev->driver)
>>> +??????? dev_WARN(dev, "late IOMMU probe at driver bind, something 
>>> fishy here!\n");
>>
>> This warning triggers on my workstation (with an AMD IOMMU), any ideas?
> 
> Argh! When I moved the dma_configure call into iommu_init_device() for
> v2 I moved the warning with it, but of course that needs to stay where
> it was, *after* the point that ops->probe_device has had a chance to
> filter out irrelevant devices. Does this make it behave?

Yes. It works on my end.

Thanks,
baolu


From amadeus at jmu.edu.cn  Wed Mar 12 07:35:15 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Wed, 12 Mar 2025 22:35:15 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <a5ec9062-ca57-4748-8c0f-fb5b9c75fa28@kwiboo.se>
References: <a5ec9062-ca57-4748-8c0f-fb5b9c75fa28@kwiboo.se>
Message-ID: <20250312143515.1225171-1-amadeus@jmu.edu.cn>

Hi,

> The pinctrl-names should be changed to "default" and not "active",
> something you can fixup or do you want a patch?

Sorry I've been a bit busy this week and forgot to send the v2 patch.
In rk3528.dtsi, the uart and upcoming i2c nodes do not have pinctrl,
so I prefer to remove them.

>> Unlike other SoCs, pinctrl-names need to be in "active" state,
>> I'm not sure about this, but otherwise the pwm-regulator will
>> not work properly.

BTW, setting the pinctrl of pwm corresponding to pwm-regulator
to "default" will cause kernel boot suspended.
Sorry but do you know why?

e.g.
```
vdd_arm: regulator-vdd-arm {
	compatible = "pwm-regulator";
	pwms = <&pwm1 0 5000 1>;
	...
};

&pwm1 {
	pinctrl-0 = <&pwm1m0_pins>;
	pinctrl-names = "default";
	status = "okay";
};
```

Thanks,
Chukun

--
2.25.1



From Suraj.Gupta2 at amd.com  Wed Mar 12 07:49:05 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Wed, 12 Mar 2025 14:49:05 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
Message-ID: <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Russell King <linux at armlinux.org.uk>
> Sent: Wednesday, March 12, 2025 7:44 PM
> To: Andrew Lunn <andrew at lunn.ch>
> Cc: Gupta, Suraj <Suraj.Gupta2 at amd.com>; Pandey, Radhey Shyam
> <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> <harini.katakam at amd.com>
> Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > +    * 1) SGMII/1000base-X only.
> > > +    * 2) 2500base-X only.
> > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > +    * implemented in driver.
> > > +    */
> > > +
> > > +   if (axienet_ior(lp, XAE_ABILITY_OFFSET) & XAE_ABILITY_2_5G)
> >
> > How can we tell if the synthesis allows 3)?
> >
> > Don't we have a backwards compatibility issue here? Maybe there are
> > systems which have been synthesised with 3), but are currently limited
> > to 1) due to the driver. If you don't differentiate between 2 and 3,
> > such systems are going to swap to 2) and regress.
>
> We've discussed this before... but because the author doesn't post regularly enough,
> it's not suprising that context keeps getting lost.
>
> Here's the discussion from 20th February 2025 on a patch series that I commented
> on on 19th November 2024.
>
> https://lore.kernel.org/r/BL3PR12MB6571FE73FA8D5AAB9FB4BB3CC9C42 at BL3
> PR12MB6571.namprd12.prod.outlook.com
>
> Suraj Gupta - you _must_ be more responsive so that reviewers can keep the
> context of previous discussions in their heads to avoid going over the same points
> time and time again. If you can't do that (and it's a good idea anyway) then you need
> to supplement the commit descriptions with the salient points from the previous
> patch series discussion to remind reviewers of the appropriate context.
>
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

Thanks Russell, sure I'll add salient points from previous discussions if it becomes old (won't try to delay at first).
Andrew - Keeping previous discussion short, identification of (3) depends on how user implements switching logic in FPGA (external GT or RTL logic). AXI 1G/2.5G IP provides only static speed selections and there is no standard register to communicate that to software.


From angelogioacchino.delregno at collabora.com  Wed Mar 12 07:49:44 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 12 Mar 2025 15:49:44 +0100
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <d2ec6fe3-db78-4e8b-ac81-fd4c631a599b@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
 <760e3112-0433-41ab-ab39-faaf0463fbe8@collabora.com>
 <d2ec6fe3-db78-4e8b-ac81-fd4c631a599b@collabora.com>
Message-ID: <99c6850d-0b62-4d1f-a1d1-e5a0065ca27f@collabora.com>

Il 12/03/25 15:20, Ariel D'Alessandro ha scritto:
> Angelo,
> 
> On 3/11/25 6:10 AM, AngeloGioacchino Del Regno wrote:
>> Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
>>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>>> Address Extension", which in Linux we've called "mali_lpae".
>>>
>>> This commit adds support for conditionally enabling AARCH64_4K page
>>> table format. To achieve that, a "GPU optional configurations" field was
>>> added to `struct panfrost_features` with the related flag.
> 
> [snip]
> 
>>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/ drm/ 
>>> panfrost/panfrost_mmu.c
>>> index 31df3a96f89bd..4a9b8de2ff987 100644
>>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> 
> [snip]
> 
>>> +static void panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
>>> +????????????????? enum io_pgtable_fmt fmt)
>>> +{
>>> +??? struct panfrost_device *pfdev = mmu->pfdev;
>>> +
>>> +??? switch (fmt) {
>>> +??? case ARM_64_LPAE_S1:
>>> +??????? mmu_cfg_init_aarch64_4k(mmu);
>>> +??????? break;
>>> +??? case ARM_MALI_LPAE:
>>> +??????? mmu_cfg_init_mali_lpae(mmu);
>>> +??????? break;
>>> +??? default:
>>
>> If you add a
>> ???????? /* That should never happen */
>>
>> ...it's clear-er why this function doesn't fail (but still raises some eyebrows,
>> because if the `default` case is not reachable, why does it even have a print?).
> 
> Makes sense. In that case, makes sense to just simplify it as:
> 
>  ??????? default:
>  ??????????????? /* This should never happen */
>  ??????????????? WARN_ON(1);
>  ??????????????? break;
> 
>>> +??????? dev_WARN_ONCE(pfdev->dev, 1, "Unhandled page table format\n");
>>> +??????? break;
>>> +??? }
>>> +}
>>> +
>>> ? static void
>>> ? _panfrost_mmu_as_control_write(struct panfrost_device *pfdev, u32 as_nr,
>>> -?????????????????? u64 transtab, u64 memattr)
>>> +?????????????????? u64 transtab, u64 memattr, u64 transcfg)
>>> ? {
>>> ????? mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>>> @@ -133,25 +223,28 @@ _panfrost_mmu_as_control_write(struct panfrost_device 
>>> *pfdev, u32 as_nr,
>>> ????? mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>>> ????? mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>>> +??? mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
>>> +??? mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
>>> +
>>> ????? write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>>> +
>>> +??? dev_dbg(pfdev->dev, "mmu_as_control: as=%d, transtab=0x%016llx, 
>>> memattr=0x%016llx, transcfg=0x%016llx",
>>> +??????? as_nr, transtab, memattr, transcfg);
>>> ? }
>>> ? static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct 
>>> panfrost_mmu *mmu)
>>> ? {
>>> -??? int as_nr = mmu->as;
>>> -??? struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
>>> -??? u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
>>> -??? u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
>>> -
>>> ????? /* Need to revisit mem attrs.
>>> ?????? * NC is the default, Mali driver is inner WT.
>>> ?????? */
>>> -??? _panfrost_mmu_as_control_write(pfdev, as_nr, transtab, memattr);
>>> +??? _panfrost_mmu_as_control_write(pfdev, mmu->as, mmu->cfg.transtab,
>>> +?????????????????????? mmu->cfg.memattr, mmu->cfg.transcfg);
>>> ? }
>>> ? static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
>>> ? {
>>> -??? _panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0);
>>> +??? _panfrost_mmu_as_control_write(pfdev, as_nr, 0, 0,
>>> +?????????????????????? AS_TRANSCFG_ADRMODE_UNMAPPED);
>>> ? }
>>> ? u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>>> @@ -616,6 +709,7 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct 
>>> panfrost_device *pfdev)
>>> ? {
>>> ????? u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev- >features.mmu_features);
>>> ????? u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev- >features.mmu_features);
>>> +??? enum io_pgtable_fmt fmt = ARM_MALI_LPAE;
>>
>> Double initialization! :-)
> 
> Will fix in v2.
> 
>>> ????? struct panfrost_mmu *mmu;
>>> ????? mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>>> @@ -641,16 +735,28 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct 
>>> panfrost_device *pfdev)
>>> ????????? .iommu_dev??? = pfdev->dev,
>>> ????? };
>>> -??? mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu- >pgtbl_cfg,
>>> -????????????????????????? mmu);
>>> -??? if (!mmu->pgtbl_ops) {
>>> -??????? kfree(mmu);
>>> -??????? return ERR_PTR(-EINVAL);
>>> +??? if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {
>>
>> Why aren't you performing this check before kzalloc?
>>
>> If you do so, you will be able to avoid having a goto, because this check will
>> simply return an error (struct not allocated yet, nothing to kfree).
>> This also means that you won't have to modify anything about the error handling
>> of the alloc_io_pgtable_ops below....
> 
> Yup, definitely agreed. Thanks!
> 
>>> +??????? if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
>>> +??????????? dev_err_once(pfdev->dev,
>>> +???????????????????? "AARCH64_4K page table not supported\n");
>>> +??????????? goto err_free_mmu;
>>> +??????? }
>>> +??????? fmt = ARM_64_LPAE_S1;
>>> ????? }
>>
>> } else {
>> ?????fmt = ARM_MALI_LPAE;
>> }
> 
> Ack. Will fix in v2.
> 
>>
>>> +??? mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
>>> +??? if (!mmu->pgtbl_ops)
>>> +??????? goto err_free_mmu;
>>> +
>>> +??? panfrost_mmu_cfg_init(mmu, fmt);
>>> +
>>> ????? kref_init(&mmu->refcount);
>>> ????? return mmu;
>>> +
>>> +err_free_mmu:
>>> +??? kfree(mmu);
>>> +??? return ERR_PTR(-EINVAL);
>>> ? }
>>> ? static const char *access_type_name(struct panfrost_device *pfdev,
>>> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/ drm/ 
>>> panfrost/panfrost_regs.h
>>> index b5f279a19a084..2b8f1617b8369 100644
>>> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
>>> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
>>> @@ -301,6 +301,17 @@
>>> ? #define AS_TRANSTAB_HI(as)??????? (MMU_AS(as) + 0x04) /* (RW) Translation 
>>> Table Base Address for address space n, high word */
>>> ? #define AS_MEMATTR_LO(as)??????? (MMU_AS(as) + 0x08) /* (RW) Memory attributes 
>>> for address space n, low word. */
>>> ? #define AS_MEMATTR_HI(as)??????? (MMU_AS(as) + 0x0C) /* (RW) Memory attributes 
>>> for address space n, high word. */
>>> +#define?? AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL??????? (2 << 2)
>>> +#define?? AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)??? ((3 << 2) | \
>>> +???????????????????????????? ((w) ? BIT(0) : 0) | \
>>> +???????????????????????????? ((r) ? BIT(1) : 0))
>>> +#define?? AS_MEMATTR_AARCH64_SH_MIDGARD_INNER??????? (0 << 4)
>>> +#define?? AS_MEMATTR_AARCH64_SH_CPU_INNER??????? (1 << 4)
>>> +#define?? AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH??? (2 << 4)
>>> +#define?? AS_MEMATTR_AARCH64_SHARED??????????? (0 << 6)
>>> +#define?? AS_MEMATTR_AARCH64_INNER_OUTER_NC??????? (1 << 6)
>>> +#define?? AS_MEMATTR_AARCH64_INNER_OUTER_WB??????? (2 << 6)
>>> +#define?? AS_MEMATTR_AARCH64_FAULT??????????? (3 << 6)
>>> ? #define AS_LOCKADDR_LO(as)??????? (MMU_AS(as) + 0x10) /* (RW) Lock region 
>>> address for address space n, low word */
>>> ? #define AS_LOCKADDR_HI(as)??????? (MMU_AS(as) + 0x14) /* (RW) Lock region 
>>> address for address space n, high word */
>>> ? #define AS_COMMAND(as)??????????? (MMU_AS(as) + 0x18) /* (WO) MMU command 
>>> register for address space n */
>>> @@ -311,6 +322,24 @@
>>> ? /* Additional Bifrost AS registers */
>>> ? #define AS_TRANSCFG_LO(as)??????? (MMU_AS(as) + 0x30) /* (RW) Translation 
>>> table configuration for address space n, low word */
>>> ? #define AS_TRANSCFG_HI(as)??????? (MMU_AS(as) + 0x34) /* (RW) Translation 
>>> table configuration for address space n, high word */
>>> +#define?? AS_TRANSCFG_ADRMODE_LEGACY??????????? (0 << 0)
>>> +#define?? AS_TRANSCFG_ADRMODE_UNMAPPED??????????? (1 << 0)
>>> +#define?? AS_TRANSCFG_ADRMODE_IDENTITY??????????? (2 << 0)
>>> +#define?? AS_TRANSCFG_ADRMODE_AARCH64_4K??????? (6 << 0)
>>> +#define?? AS_TRANSCFG_ADRMODE_AARCH64_64K??????? (8 << 0)
>>
>> "Anything" shifted in any direction by 0 is equal to the same "anything" :-)
>>
>> Those are just 0,1,2,6,8
> 
> Well, I agree... However, I'm copying this from panthor as-is. As these are similar 
> drivers, I just kept all the macro definitions.
> 
>>
>>> +#define?? AS_TRANSCFG_INA_BITS(x)??????????? ((x) << 6)
>>> +#define?? AS_TRANSCFG_OUTA_BITS(x)??????????? ((x) << 14)
>>> +#define?? AS_TRANSCFG_SL_CONCAT??????????????? BIT(22)
>>> +#define?? AS_TRANSCFG_PTW_MEMATTR_NC??????????? (1 << 24)
>>
>> BIT(24)
>>
>>> +#define?? AS_TRANSCFG_PTW_MEMATTR_WB??????????? (2 << 24)
>>
>> BIT(25)
>>
>>> +#define?? AS_TRANSCFG_PTW_SH_NS??????????????? (0 << 28)
>>
>> 0
>>
>>> +#define?? AS_TRANSCFG_PTW_SH_OS??????????????? (2 << 28)
>>
>> BIT(29)
>>
>>> +#define?? AS_TRANSCFG_PTW_SH_IS??????????????? (3 << 28)
>>
>> GENMASK(29, 28) or BIT(28) | BIT(29)
>>
>> (btw, rinse and repeat for the memattrs)
> 
> I think the criteria used in panfrost/panthor for these definitions is:
> * if the register field is 1 bit, use BIT()
> * if the register field is >1 bit, use the value (as defined in the datasheet) an 
> shift it.
> * and -be super explicit- do this even if the value is 0.
> 
> I don't really have a strong opinion, but I'd attach to the subsystem/driver 
> criteria used as much as possible :)

Okay, Fair enough!

Cheers,
Angelo

> 
> Thanks!
> 



From michal.kubiak at intel.com  Wed Mar 12 07:49:14 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Wed, 12 Mar 2025 15:49:14 +0100
Subject: [PATCH netdev v2] net: stmmac: dwmac-rk: Provide FIFO sizes for
 DWMAC 1000
In-Reply-To: <20250312124206.2108476-1-wens@kernel.org>
References: <20250312124206.2108476-1-wens@kernel.org>
Message-ID: <Z9Ge6rLHynH1ATjz@localhost.localdomain>

On Wed, Mar 12, 2025 at 08:42:06PM +0800, Chen-Yu Tsai wrote:
> From: Chen-Yu Tsai <wens at csie.org>
> 
> The DWMAC 1000 DMA capabilities register does not provide actual
> FIFO sizes, nor does the driver really care. If they are not
> provided via some other means, the driver will work fine, only
> disallowing changing the MTU setting.
> 
> Provide the FIFO sizes through the driver's platform data to enable
> MTU changes. The FIFO sizes are confirmed to be the same across RK3288,
> RK3328, RK3399 and PX30, based on their respective manuals. It is
> likely that Rockchip synthesized their DWMAC 1000 with the same
> parameters on all their chips that have it.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---
> Changes since v1:
> - Removed references to breakage from commit message as it is already fixed
> - Removed Cc stable and Fixes tags
> - Rebased onto latest -next

The tag of the patch should clearly describe the destination tree. It
can be either "net" or "net-next". "netdev" is not a proper tag.
Assuming you removed the "Fixes" tag, you probably want to send the
patch to "net-next".

Thanks,
Michal



From lorenzo at kernel.org  Wed Mar 12 07:54:21 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 15:54:21 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9Ga7gx1u3JsOemE@localhost.localdomain>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
 <Z9Ga7gx1u3JsOemE@localhost.localdomain>
Message-ID: <Z9GgHZxkSqFCkwMg@lore-desk>

> On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> > The system occasionally crashes dereferencing a NULL pointer when it is
> > forwarding constant, high load bidirectional traffic.
> > 
> > [ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
> > [ 2149.925812] Mem abort info:
> > [ 2149.928713]   ESR = 0x0000000096000005
> > [ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
> > [ 2149.938429]   SET = 0, FnV = 0
> > [ 2149.941814]   EA = 0, S1PTW = 0
> > [ 2149.945187]   FSC = 0x05: level 1 translation fault
> > [ 2149.950348] Data abort info:
> > [ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
> > [ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> > [ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > [ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
> > [ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
> > [ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
> > [ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
> > [ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
> > [ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
> > [ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
> > [ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > [ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > [ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
> > [ 2150.218149] sp : ffffffc080e8ba10
> > [ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
> > [ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
> > [ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
> > [ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
> > [ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
> > [ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
> > [ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
> > [ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
> > [ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
> > [ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
> > [ 2150.292811] Call trace:
> > [ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > [ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
> > [ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
> > [ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
> > [ 2150.318200]  process_one_work+0x178/0x2f0
> > [ 2150.322211]  worker_thread+0x2e4/0x4cc
> > [ 2150.325953]  kthread+0xd8/0xdc
> > [ 2150.329008]  ret_from_fork+0x10/0x20
> > [ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
> > [ 2150.338681] ---[ end trace 0000000000000000 ]---
> > [ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
> > [ 2150.349035] SMP: stopping secondary CPUs
> > [ 2150.352954] Kernel Offset: disabled
> > [ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
> > [ 2150.361743] Memory Limit: none
> > 
> > Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> > routine.
> > 
> > Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
> 
> The patch has "Fixes" tag, but it is sent to "net-next" tree.
> I think it's rather a candidate for "net".

The offending commit is just in net-next at the moment. Do you prefer to drop
the Fixes tag?

> 
> > Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> > ---
> >  drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++
> >  drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
> >  drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
> >  3 files changed, 27 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > index c0a642568ac115ea9df6fbaf7133627a4405a36c..776222595b84e4fba6ae5943420e0edf0d0ecf8f 100644
> > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > @@ -2454,6 +2454,22 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> >  	}
> >  }
> >  
> > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > +			     struct airoha_gdm_port *port)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> 
> You could reduce the number of lines by moving the declaration inside the
> loop:
> 	for (int i = 0; i < ARRAY_SIZE(eth->ports); i++) {

to be consistent with the driver I prefer to keep the current approach.

> 
> > +		if (!eth->ports[i])
> > +			continue;
> 
> Isn't this NULL check redundant?
> In the second check you compare the table element to a real pointer.

Can netdev_priv() be NULL? If not, I guess we can remove this check.

Regards,
Lorenzo

> 
> > +
> > +		if (eth->ports[i] == port)
> > +			return 0;
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> >  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> >  				 struct device_node *np, int index)
> >  {
> > diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> > index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
> > --- a/drivers/net/ethernet/airoha/airoha_eth.h
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> > @@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
> >  #define airoha_qdma_clear(qdma, offset, val)			\
> >  	airoha_rmw((qdma)->regs, (offset), (val), 0)
> >  
> > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > +			     struct airoha_gdm_port *port);
> > +
> >  void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
> >  int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
> >  				 void *cb_priv);
> > diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> > index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
> > --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> > +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> > @@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
> >  #endif
> >  }
> >  
> > -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> > +					struct airoha_foe_entry *hwe,
> >  					struct net_device *dev, int type,
> >  					struct airoha_flow_data *data,
> >  					int l4proto)
> > @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> >  	if (dev) {
> >  		struct airoha_gdm_port *port = netdev_priv(dev);
> >  		u8 pse_port;
> > +		int err;
> > +
> > +		err = airoha_is_valid_gdm_port(eth, port);
> > +		if (err)
> > +			return err;
> >  
> >  		if (dsa_port >= 0)
> >  			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
> > @@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
> >  	    !is_valid_ether_addr(data.eth.h_dest))
> >  		return -EINVAL;
> >  
> > -	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
> > +	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
> >  					   &data, l4proto);
> >  	if (err)
> >  		return err;
> > 
> > ---
> > base-commit: 0ea09cbf8350b70ad44d67a1dcb379008a356034
> > change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a
> > 
> > Best regards,
> > -- 
> > Lorenzo Bianconi <lorenzo at kernel.org>
> > 
> > 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/d00830b5/attachment.sig>

From peng.fan at oss.nxp.com  Wed Mar 12 09:02:07 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Thu, 13 Mar 2025 00:02:07 +0800
Subject: [PATCH v2 0/4] clk: Support spread spectrum and use it in
 clk-pll144x and clk-scmi
In-Reply-To: <PAXPR04MB84596732B538D24F95E9FAC488C02@PAXPR04MB8459.eurprd04.prod.outlook.com>
References: <20250205-clk-ssc-v2-0-fa73083caa92@nxp.com>
 <PAXPR04MB84596732B538D24F95E9FAC488C02@PAXPR04MB8459.eurprd04.prod.outlook.com>
Message-ID: <20250312160207.GA21518@nxa18884-linux>

I am still waiting for a yes or no, or any suggestions.

Thanks,
Peng

On Mon, Feb 24, 2025 at 01:09:20PM +0000, Peng Fan (OSS) wrote:
>Hi Rob, Stephen,
>
>> Subject: [PATCH v2 0/4] clk: Support spread spectrum and use it in clk-
>> pll144x and clk-scmi
>
>Do you have time to give a look on patch 1,2 and the bindings
>part in https://github.com/devicetree-org/dt-schema/pull/154
>
>I would like to see if you agree on this approach or not, then
>I could work on next step to explore new method or else

>
>Thanks,
>Peng.
>
>> 
>> - Introduce clk_set_spread_spectrum to set the parameters for enabling
>>   spread spectrum of a clock.
>> - Parse 'assigned-clock-sscs' and configure it by default before using the
>>   clock. The pull request for this property is at [1]
>>   This property is parsed before parsing clock rate.
>> 
>> - Enable this feature for clk-scmi on i.MX95.
>>   This may not the best, since checking machine compatibles.
>>   I am thinking to provide an API scmi_get_vendor_info, then driver
>>   could use it for OEM stuff, such as
>>   if (scmi_get_vendor_info returns NXP_IMX)
>>       ops->set_spread_spectrum = scmi_clk_set_spread_spectrum;
>> 
>> [1] https://github.com/devicetree-org/dt-schema/pull/154
>> 
>> Signed-off-by: Peng Fan <peng.fan at nxp.com>
>> ---
>> Changes in v2:
>> - Rename to clk_hw_set_spread_spectrum and not export it as
>> consumer API.
>> - Fix error handling
>> - The enable parameter is still kept, because 0% is valid per
>>   https://www.ti.com/lit/an/scaa103/scaa103.pdf?ts=1738667308903
>>   https://www.synopsys.com/blogs/chip-design/understanding-pcie-
>> spread-spectrum-clocking.html
>> - Include the i.MX clk pll14xx which was an effort to enable SSC on
>> i.MX8MN from https://lore.kernel.org/all/20250118124044.157308-1-
>> dario.binacchi at amarulasolutions.com/
>>   With this patchset, things could be simplied a lot.
>> - Update the clk-scmi extconfig, marked as not apply, because spec not
>> settle down.
>> - Link to v1: https://lore.kernel.org/linux-clk/20250124-clk-ssc-v1-0-
>> 2d39f6baf2af at nxp.com/T/#mce926ef10d3d9c1c960c21867c2f1509f1
>> f87cb9
>> 
>> ---
>> Peng Fan (4):
>>       clk: Introduce clk_hw_set_spread_spectrum
>>       clk: conf: Support assigned-clock-sscs
>>       clk: imx: pll14xx: support spread spectrum clock generation
>>       [NOT APPLY] clk: scmi: Support spread spectrum
>> 
>>  drivers/clk/clk-conf.c        | 70
>> +++++++++++++++++++++++++++++++++++++++++++
>>  drivers/clk/clk-scmi.c        | 47 +++++++++++++++++++++++++++--
>>  drivers/clk/clk.c             | 34 +++++++++++++++++++++
>>  drivers/clk/imx/clk-pll14xx.c | 66
>> ++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk-provider.h  | 32 ++++++++++++++++++++
>>  include/linux/clk.h           | 22 ++++++++++++++
>>  include/linux/scmi_protocol.h |  6 ++++
>>  7 files changed, 275 insertions(+), 2 deletions(-)
>> ---
>> base-commit: 40b8e93e17bff4a4e0cc129e04f9fdf5daa5397e
>> change-id: 20250124-clk-ssc-f3d70fb6cd1c
>> 
>> Best regards,
>> --
>> Peng Fan <peng.fan at nxp.com>
>


From linux.amoon at gmail.com  Wed Mar 12 07:58:58 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Wed, 12 Mar 2025 20:28:58 +0530
Subject: [PATCH v4 1/4] drivers/thermal/exynos: Refactor clk_sec
 initialization inside SOC-specific case
In-Reply-To: <20250310143450.8276-2-linux.amoon@gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com> <20250310143450.8276-2-linux.amoon@gmail.com>
Message-ID: <CANAwSgRcuMZTrdn27qdEkZF33cQ4RemjExs5eySO-CMv3Qq6eg@mail.gmail.com>

Hi All,

On Mon, 10 Mar 2025 at 20:05, Anand Moon <linux.amoon at gmail.com> wrote:
>
> Refactor the initialization of the clk_sec clock to be inside the
> SOC_ARCH_EXYNOS5420_TRIMINFO case. It ensures that the clk_sec clock
> is only initialized for the specified SOC and not for other SOCs,
> thereby simplifying the code. The clk_sec clock is used by the TMU
> for GPU on the Exynos 542x platform.
>
> Removed redundant IS_ERR() checks for the clk_sec clock since error
> handling is already managed internally by clk_unprepare() functions.
>
> Signed-off-by: Anand Moon <linux.amoon at gmail.com>

On Exynos4412 Odroid U3 uses the clocks name
      clock-names = "tmu_apbif";

On Exynos5422 Odroid XU4 uses the clocks name
       clock-names = "tmu_apbif", "tmu_triminfo_apbif";

So Exynos 5433 and Exynos7  SoC use the clocks name
      clock-names = "tmu_apbif", "tmu_sclk";

As per my understanding, there could be a common case for GPU clock in
TMU driver
which could simplify the code, any thoughts

-----------------------8<-------------------------------------
switch (data->soc) {
        case SOC_ARCH_EXYNOS5420_TRIMINFO:
        case SOC_ARCH_EXYNOS5433:
        case SOC_ARCH_EXYNOS7:

Thanks
-Anand


From linux.amoon at gmail.com  Wed Mar 12 07:59:19 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Wed, 12 Mar 2025 20:29:19 +0530
Subject: [PATCH v4 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <25fa661b-98e4-468b-bb4d-4a2c95f32b71@kernel.org>
References: <20250310143450.8276-1-linux.amoon@gmail.com> <20250310143450.8276-5-linux.amoon@gmail.com>
 <25fa661b-98e4-468b-bb4d-4a2c95f32b71@kernel.org>
Message-ID: <CANAwSgTeZ83oqatrsWQxT+4RYwEtEqma=R4XX_iGrP2N=phz9Q@mail.gmail.com>

Hi Krzysztof,

Thanks for your review comments.

On Tue, 11 Mar 2025 at 23:00, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 10/03/2025 15:34, Anand Moon wrote:
> > Using guard notation makes the code more compact and error handling
> > more robust by ensuring that mutexes are released in all code paths
> > when control leaves critical section.
> >
>
> Subject: typo, exynos
Ok.
>
> > Signed-off-by: Anand Moon <linux.amoon at gmail.com>
> > ---
> > v4: used DEFINE_GUARD macro to guard exynos_tmu_data structure.
> >     However, incorporating guard(exynos_tmu_data)(data); results
> >     in a recursive deadlock with the mutex during initialization, as this
> >     data structure is common to all the code configurations of Exynos TMU
> > v3: New patch
>
> If you ever use cleanup or guards, you must build your code with recent
> clang and W=1. Failure to do so means you ask reviewers manually to spot
> issues not visible in the context, instead of using tools. It's a NAK
> for me.
 Ok, I will check this next time before submitting the changes.
>
> > ---
> >  drivers/thermal/samsung/exynos_tmu.c | 25 +++++++++++--------------
> >  1 file changed, 11 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
> > index a71cde0a4b17e..85f88c5e0f11c 100644
> > --- a/drivers/thermal/samsung/exynos_tmu.c
> > +++ b/drivers/thermal/samsung/exynos_tmu.c
> > @@ -12,6 +12,7 @@
> >   */
> >
> >  #include <linux/clk.h>
> > +#include <linux/cleanup.h>
> >  #include <linux/io.h>
> >  #include <linux/interrupt.h>
> >  #include <linux/module.h>
> > @@ -199,6 +200,9 @@ struct exynos_tmu_data {
> >       void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
> >  };
> >
> > +DEFINE_GUARD(exynos_tmu_data, struct exynos_tmu_data *,
>
> I do not understand why do you need custom guard.

I thought this should add a global guard to exynos_tmu_data using
mutex_lock and mutex_unlock.
I'll drop this if it turns out to be unnecessary.
>
> > +          mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
> > +
> >  /*
> >   * TMU treats temperature as a mapped temperature code.
> >   * The temperature is converted differently depending on the calibration type.
> > @@ -256,7 +260,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> >       unsigned int status;
> >       int ret = 0;
> >
> > -     mutex_lock(&data->lock);
> > +     guard(mutex)(&data->lock);
>
> Which you do not use... Please don't use cleanup.h if you do not know
> it. It leads to bugs.
>
Ok, I will drop this include of cleanup.h.
>
> Best regards,
> Krzysztof

Thanks
-Anand


From robdclark at gmail.com  Wed Mar 12 07:59:52 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 12 Mar 2025 07:59:52 -0700
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250312130525.GC6181@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck> <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck>
Message-ID: <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>

On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> > On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> > >
> > > On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > > > This will be used by drm/msm for GPU page faults, replacing the manual
> > > > register reading it does.
> > > >
> > > > Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> > > > ---
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu.c            | 27 +++++++++++++-----------
> > > >  drivers/iommu/arm/arm-smmu/arm-smmu.h            |  5 ++++-
> > > >  3 files changed, 21 insertions(+), 15 deletions(-)
> > > >
> > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > > index 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e 100644
> > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > > > @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> > > >
> > > >       if (list_empty(&tbu_list)) {
> > > >               ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > > > -                                      cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > > +                                      cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > >
> > > >               if (ret == -ENOSYS)
> > > >                       arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> > > > @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> > > >       phys_soft = ops->iova_to_phys(ops, cfi.iova);
> > > >
> > > >       tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > > > -                              cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > > +                              cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > > >       if (!tmp || tmp == -EBUSY) {
> > > >               ret = IRQ_HANDLED;
> > > >               resume = ARM_SMMU_RESUME_TERMINATE;
> > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> > > >                                     struct arm_smmu_context_fault_info *cfi)
> > > >  {
> > > >       cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > > > +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> > > >       cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > > > -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> > >
> > > We already have an implementation hook (->get_fault_info()) which the
> > > qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> > > That thing dumps these registers already so if we're moving that into
> > > the core SMMU driver, let's get rid of the hook and move everybody over
> > > rather than having it done in both places.
> >
> > As you probably saw, the next commit moves over
> > qcom_adreno_smmu_get_fault_info() to use this. The current back door
> > used by drm/msm to access these functions is specific to adreno_smmu
> > and there isn't an equivalent interface to allow it to call a generic
> > SMMU function so it isn't possible to move it entirely to the core. At
> > least not without a bigger refactoring that isn't justified for this
> > series that is just trying to fix things.
>
> Ok :(
>
> > > >       cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > > > +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> > >
> > > I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> > > it for stage-2 domains.
> > >
> > Does it matter if we read the register though, as long as users are
> > aware of this and don't use its value for anything?
>
> I think the contents are "UNKNOWN", so it could be hugely confusing even
> if they just got logged someplace. Why is it difficult to avoid touching
> it for stage-2?
>
> Will

Fwiw, we are only ever using stage-1

BR,
-R


From helgaas at kernel.org  Wed Mar 12 08:04:26 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 10:04:26 -0500
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <fcb5f09f8e4311c7a6ef60aaf3cb4e3f05a8f05e.camel@pengutronix.de>
Message-ID: <20250312150426.GA674002@bhelgaas>

On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > -----Original Message-----
> > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > Sent: 2025?3?11? 23:55
> > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > -----Original Message-----
> > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > Sent: 2025?3?10? 23:11
> > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > > 
> > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > ---
> > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > @@ -41,7 +41,6 @@
> > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > 8)
> > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > > 
> > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > platform_device
> > > > > *pdev)
> > > > > > ?	struct dw_pcie *pci;
> > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > ?	struct device_node *np;
> > > > > > -	struct resource *dbi_base;
> > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > ?	int i, ret, req_cnt;
> > > > > > ?	u16 val;
> > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > platform_device *pdev)
> > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > ?	}
> > > > > > 
> > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > 0,
> > > > > &dbi_base);
> > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > -		return PTR_ERR(pci->dbi_base);

> > Use the domain number replace the hardcodes to uniquely identify
> > different controller on i.MX8MQ platforms. No function changes.
> > Please make sure the " linux,pci-domain" is set for i.MX8MQ correctly, since
> > ?the controller id is relied on it totally.
> > 
> This breaks running a new kernel on an old DT without the
> linux,pci-domain property, which I'm absolutely no fan of. We tried
> really hard to keep this way around working in the i.MX world.
> 
> I'm fine with using the property if present and even mandating it for
> new platforms, but getting rid of the existing code for the i.MX8MQ
> platform is only a marginal cleanup of the driver code with the obvious
> downside of the above breakage.

I don't know the history of these DTs, but if there are any old DTs
for platforms that use controller 1 but lack 'linux,pci-domain', I
agree that we should not break them.

If we need to retain the dbi_base check so that old DTs continue to
work, I think it should look something like this:

  domain = of_get_pci_domain_nr(node);
  if (domain >= 0) {
      if (domain > 1)
          return dev_err_probe(..., "invalid domain %d\n", domain);
      imx_pcie->controller_id = domain;
  } else {
      dev_warn(..., "DT lacks linux,pci-domain, falling back to DBI addr\n");
      dbi_res = platform_get_resource(pdev, IORESOURCE_MEM, index);
      if (dbi_res->start == IMX8MQ_PCIE2_BASE_ADDR)
          imx_pcie->controller_id = 1;
  }

The previous code used devm_platform_get_and_ioremap_resource() and
set pci->dbi_base, but (1) there's no need to set pci->dbi_base since
the DWC core does that anyway, and (2) I think using ioremap() means
we depend on CPU virt == CPU phys, and I don't think we need to depend
on that.

Bjorn


From Suraj.Gupta2 at amd.com  Wed Mar 12 08:06:32 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Wed, 12 Mar 2025 15:06:32 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
Message-ID: <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Andrew Lunn <andrew at lunn.ch>
> Sent: Wednesday, March 12, 2025 8:29 PM
> To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> <harini.katakam at amd.com>
> Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> > > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > > +    * 1) SGMII/1000base-X only.
> > > > > +    * 2) 2500base-X only.
> > > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > > +    * implemented in driver.
> > > > > +    */
>
> > - Keeping previous discussion short, identification of (3) depends on
> > how user implements switching logic in FPGA (external GT or RTL
> > logic). AXI 1G/2.5G IP provides only static speed selections and there
> > is no standard register to communicate that to software.
>
> So if anybody has synthesised it as 3) this change will break their system?
>
>         Andrew

It will just restrict their system to (2)


From cristian.marussi at arm.com  Wed Mar 12 08:07:50 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Wed, 12 Mar 2025 15:07:50 +0000
Subject: [PATCH NOT APPLY v2 4/4] clk: scmi: Support spread spectrum
In-Reply-To: <20250310081635.GA16799@nxa18884-linux>
References: <20250205-clk-ssc-v2-0-fa73083caa92@nxp.com>
 <20250205-clk-ssc-v2-4-fa73083caa92@nxp.com>
 <Z6SqeNsAqbZM8nr1@pluto>
 <20250303041125.GC13236@nxa18884-linux>
 <Z8iKErarE0lHWxEy@pluto>
 <20250310081635.GA16799@nxa18884-linux>
Message-ID: <Z9GjRhQmsu0fBoWG@pluto>

On Mon, Mar 10, 2025 at 04:16:35PM +0800, Peng Fan wrote:
> On Wed, Mar 05, 2025 at 05:29:54PM +0000, Cristian Marussi wrote:
> >On Mon, Mar 03, 2025 at 12:11:25PM +0800, Peng Fan wrote:
> >> Hi Cristian,
> >> 
> >> On Thu, Feb 06, 2025 at 12:26:32PM +0000, Cristian Marussi wrote:
> >> >On Wed, Feb 05, 2025 at 05:49:54PM +0800, Peng Fan (OSS) wrote:
> >> >> From: Peng Fan <peng.fan at nxp.com>
> >> >> 
> >> >> Support Spread Spectrum with adding scmi_clk_set_spread_spectrum
> >> >> 
> >> >
> >> >Hi,
> >> >
> >> >I forwarded ATG with our latest exchange on the possibility of using a
> >> >standard OEM type instead of Vendor one if it is general enough....
> >> 
> >> Do you have any update?
> >> 
> >
> >Yes I think you can go on with your original plan of using vendor OEM
> >types: as of now we are not gonna standardize a new commmon SCMI type
> >for Clock-SS, given there is really just one SCMI user of such clock
> >features...maybe in the future if more users shows up...
> 
> Thanks for updating me. Back to how to add extensions in clk-scmi.c,
> do you have any suggestions? I am thinking to provide vendor/sub-vendor
> for clk-scmi.c and use vendor "NXP" sub-vedor "IMX" for spread spectrum.
> 

Definitely based on vendors subvendors, not sure about how, I have not
really though about the details: you also shoudl consider that the new
clk ops for spread spectrum should be registered ONLY when you are on a
supported platform (of course) AND the OEM types nnamespace is per-vendor:
like vendor protocols your NXP OEM config type 0x80 must coexist with any
future possible OTHER_VENDOR OEM ConfigType 0x80.

Thanks,
Cristian



From andrew at lunn.ch  Wed Mar 12 07:58:53 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 15:58:53 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>

> > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > +    * 1) SGMII/1000base-X only.
> > > > +    * 2) 2500base-X only.
> > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > +    * implemented in driver.
> > > > +    */

> - Keeping previous discussion short, identification of (3) depends
> on how user implements switching logic in FPGA (external GT or RTL
> logic). AXI 1G/2.5G IP provides only static speed selections and
> there is no standard register to communicate that to software.

So if anybody has synthesised it as 3) this change will break their
system?

	Andrew


From jonas at kwiboo.se  Wed Mar 12 08:00:00 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 12 Mar 2025 16:00:00 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250312143515.1225171-1-amadeus@jmu.edu.cn>
References: <a5ec9062-ca57-4748-8c0f-fb5b9c75fa28@kwiboo.se>
 <20250312143515.1225171-1-amadeus@jmu.edu.cn>
Message-ID: <b7d8d385-81ee-4947-ab8f-1da43843464b@kwiboo.se>

Hi Chukun,

On 2025-03-12 15:35, Chukun Pan wrote:
> Hi,
> 
>> The pinctrl-names should be changed to "default" and not "active",
>> something you can fixup or do you want a patch?
> 
> Sorry I've been a bit busy this week and forgot to send the v2 patch.
> In rk3528.dtsi, the uart and upcoming i2c nodes do not have pinctrl,
> so I prefer to remove them.
> 
>>> Unlike other SoCs, pinctrl-names need to be in "active" state,
>>> I'm not sure about this, but otherwise the pwm-regulator will
>>> not work properly.
> 
> BTW, setting the pinctrl of pwm corresponding to pwm-regulator
> to "default" will cause kernel boot suspended.
> Sorry but do you know why?

Not an issue I have seen, do you have any more logs or details? E.g.
what board you use, full regulator node, do you have operating points
defined etc.

I have runtime tested a branch at [1], that use pinctrl-names = default,
have vdd_arm and vdd_logic defined, also an opp table for cpu and gpu.

For E20C there is a commit to enable the vdd_logic, however without gpu
enabled and a mali-supply the pwm-regulator is initialized to
max-microvolt by Linux. Have instead updated U-Boot to initialize the
pwm-regulator's:

```
&vdd_arm {
	regulator-init-microvolt = <953000>;
};

&vdd_logic {
	regulator-init-microvolt = <900000>;
};
```

[1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250311-rk3528/

Regards,
Jonas

> 
> e.g.
> ```
> vdd_arm: regulator-vdd-arm {
> 	compatible = "pwm-regulator";
> 	pwms = <&pwm1 0 5000 1>;
> 	...
> };
> 
> &pwm1 {
> 	pinctrl-0 = <&pwm1m0_pins>;
> 	pinctrl-names = "default";
> 	status = "okay";
> };
> ```
> 
> Thanks,
> Chukun
> 
> --
> 2.25.1
> 



From joro at 8bytes.org  Wed Mar 12 08:21:18 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Wed, 12 Mar 2025 16:21:18 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <d55240a4-fe4a-48ea-b3a8-9a997bb7267c@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <Z9CEIlXoQJ-A0t-d@8bytes.org>
 <d55240a4-fe4a-48ea-b3a8-9a997bb7267c@arm.com>
Message-ID: <Z9GmbgYKr0VepQZZ@8bytes.org>

Hi Robin,

On Wed, Mar 12, 2025 at 10:10:04AM +0000, Robin Murphy wrote:
> Argh! When I moved the dma_configure call into iommu_init_device() for
> v2 I moved the warning with it, but of course that needs to stay where
> it was, *after* the point that ops->probe_device has had a chance to
> filter out irrelevant devices. Does this make it behave?

Okay, thanks for the patch. I am currently building a kernel to test it
and will report back.

Regards,

	Joerg


From tabba at google.com  Wed Mar 12 08:31:17 2025
From: tabba at google.com (Fuad Tabba)
Date: Wed, 12 Mar 2025 15:31:17 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <20250312152903.GA6488@willie-the-truck>
References: <20250226215520.1759218-1-tabba@google.com> <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com> <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck> <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
 <20250303214947.GA30619@willie-the-truck> <CA+EHjTzZQ6UnOdaqpZ86JNiY=Gr_UoBAjZxk4CS3Q6nMJYdV2w@mail.gmail.com>
 <20250312152903.GA6488@willie-the-truck>
Message-ID: <CA+EHjTwHb9mDj20WxeqKky6oAfRDV2R7iiQpwmuBmdZ4aWuS4A@mail.gmail.com>

Hi Will,

On Wed, 12 Mar 2025 at 15:29, Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 04, 2025 at 12:33:27PM +0000, Fuad Tabba wrote:
> > On Mon, 3 Mar 2025 at 21:49, Will Deacon <will at kernel.org> wrote:
> > >
> > > On Mon, Mar 03, 2025 at 07:21:33PM +0000, Fuad Tabba wrote:
> > > > On Mon, 3 Mar 2025 at 19:18, Will Deacon <will at kernel.org> wrote:
> > > > > On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> > > > > > On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> > > > > > > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > > > > > > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > > > >  {
> > > > > > > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > > > > > > +     size_t pgd_sz, hyp_vm_sz;
> > > > > > > >       struct kvm_vcpu *host_vcpu;
> > > > > > > > -     pkvm_handle_t handle;
> > > > > > > >       void *pgd, *hyp_vm;
> > > > > > > >       unsigned long idx;
> > > > > > > >       int ret;
> > > > > > > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > > > >       if (ret < 0)
> > > > > > > >               goto free_vm;
> > > > > > > >
> > > > > > > > -     handle = ret;
> > > > > > > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> > > > > > >
> > > > > > > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > > > > > > update the readers to be READ_ONCE()?
> > > > > >
> > > > > > I don't remember the original reason, to be honest. In this case, it
> > > > > > was to make it consistent with downstream code in Android. That said,
> > > > > > I plan on revising all of these soon and fixing this (and related
> > > > > > code) in light of Will's comment regarding potential specter gadgets:
> > > > > >
> > > > > > https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/
> > > > >
> > > > > I'm not sure the spectre stuff changes the concurrency aspects here, so
> > > > > Quentin's question presumably still stands even after that.
> > > > >
> > > > > Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
> > > > > in pkvm_is_hyp_created() which is called without the config_lock held
> > > > > by kvm_arch_prepare_memory_region(). However, given that
> > > > > pkvm_is_hyp_created() is only testing against 0, I don't think the
> > > > > _ONCE() accessors are doing anything useful in that case.
> > > > >
> > > > > The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
> > > > > directly without the 'config_lock' held. The MMU notifiers look like
> > > > > they can do that, so I wonder if there's a theoretical race where they
> > > > > can race with first run and issue TLB invalidation with the wrong handle?
> > > > > That would apply equally to the upstream code, I think.
> > > >
> > > > Would using _ONCE accessors with the MMU notifiers be enough to avoid
> > > > the race, or do we need to reconsider the lock protecting the handle
> > > > and apply it to the notifiers?
> > >
> > > I'm not entirely sure... if we used _ONCE() then we'd get either the
> > > correct handle or zero, but we presumably need to order that against the
> > > page-table somehow. The 'mmu_lock' looks like it gives us that, but I
> > > don't think the notifiers are expecting an uninitialised handle in the
> > > case where the page-table is empty (i.e. if they fire before first run).
> > >
> > > Given that the handle is necessary for TLB invalidation, I'd be inclined
> > > to make sure that the handle is allocated and published _before_ the
> > > kvm_pgtable pointer checked by the notifiers is set, but that means
> > > moving the handle allocation into kvm_arch_init_vm(). Is that do-able?
> >
> > It is doable, but it won't be a simple patch. Up until now, the
> > creation of the hyp view of a vm is associated with the first run of
> > the vm, rather than its allocation at the host. Part of the reason for
> > that is that much of the vm state (mainly the vcpu state) isn't
> > finalized until then.
> >
> > This patch series fixes this in part, by decoupling the initialization
> > of the individual vcpus from the vm. Because of that, it would be
> > doable, but it might be better as another patch series that we could
> > test and analyze separately.
> >
> > If you agree, I could whip up something and send it soon.
>
> Yeah, I think we should fix this as a separate series and drop the
> WRITE_ONCE() from this patch.

I'll send a fix soon.

Oliver, would you like me to respin this series, or can you drop the
WRITE_ONCE()?

Thanks,
/fuad

> Will


From christopher.obbard at linaro.org  Wed Mar 12 08:28:49 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Wed, 12 Mar 2025 16:28:49 +0100
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as built-in
In-Reply-To: <5ecb69c9-c877-4c91-a1ae-0ef59d0ee3d6@kernel.org>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
 <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org> <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
 <5ecb69c9-c877-4c91-a1ae-0ef59d0ee3d6@kernel.org>
Message-ID: <CACr-zFAMa3Awx16avbXNMRhkELFkEZedZfHVCFuFc4fitWFL4w@mail.gmail.com>

Hi Krzysztof,

On Wed, 12 Mar 2025 at 12:34, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 12/03/2025 12:10, Christopher Obbard wrote:
> > Hi Krzysztof,
> >
> > On Wed, 12 Mar 2025 at 09:56, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> >>
> >> On 11/03/2025 20:15, Christopher Obbard wrote:
> >>> Hi Dmitry,
> >>>
> >>> On Tue, 11 Mar 2025 at 19:58, Dmitry Baryshkov <lumag at kernel.org> wrote:
> >>>>
> >>>> On Tue, Mar 11, 2025 at 07:10:06PM +0100, Christopher Obbard wrote:
> >>>>> I sent this patch to start the discussion, some things I found:
> >>>>>
> >>>>> 1) Some interconnects are missing from arm defconfig. Should they be =y too ?
> >>>>
> >>>> No, unless those are required for the UART console.
> >>>
> >>> OK, that makes sense. FWIW the cryptic (to me, at least) commit log on
> >>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eee808134ecf1c1093ff1ddfc056dc5e469d0c3
> >>> made me think that the interconnects should be built-in on all devices.
> >>>
> >>> Of course, the real problem here is RB3gen2 not actually finding the
> >>> UFS/eMMC device due to no interconnect driver.
> >>> Until now, I have been building that into the kernel. I will
> >>> investigate instead shoving into the initrd (in both debian and
> >>> fedora) which should solve my issue and render this patchset useless.
> >>
> >> For Qualcomm platforms you are expected to always have initramfs, thus
> >> you will have the modules for UFS/eMMC mounts. I don't understand the
> >> problem which you were trying to solve.
> >>
> >> The interconnects were built in *only* because of need for serial
> >> console. Only.
> >
> > Thanks for confirming. It is all clear now.
> >
> > Consider this patch dropped from my side.
> >
> > For reference, I am working on updating initramfs generation tools in
> > Debian/Fedora to include the required interconnect modules. Currently
> > the interconnect drivers are built as modules in these distros, but
> > are not included in the initrd. That is where my confusion initially
> > stemmed from.
>
> Sure. This defconfig is anyway for us - developers, not for the distros
> to use directly. Distros have much bigger configs and use almost
> everything as module.

Completely agree - my usual workflow is to build with the kernel's
defconfig (disto config is generally huge) and install the resulting
kernel into my Debian image.

Installing a kernel built with `make bindeb-pkg` then calls
update-initramfs to create the initrd - which then should pack the
RIGHT modules needed for loading storage/network boot/etc into the
initrd. In this case it simply didn't yet copy that module into the
initrd in Debian, so I will sort it out in the distro space ;-).

We can likely stop this discussion now as it's clear to everyone
what's going on I think.

Thanks,

Chris


From will at kernel.org  Wed Mar 12 08:29:04 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 15:29:04 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <CA+EHjTzZQ6UnOdaqpZ86JNiY=Gr_UoBAjZxk4CS3Q6nMJYdV2w@mail.gmail.com>
References: <20250226215520.1759218-1-tabba@google.com>
 <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com>
 <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck>
 <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
 <20250303214947.GA30619@willie-the-truck>
 <CA+EHjTzZQ6UnOdaqpZ86JNiY=Gr_UoBAjZxk4CS3Q6nMJYdV2w@mail.gmail.com>
Message-ID: <20250312152903.GA6488@willie-the-truck>

On Tue, Mar 04, 2025 at 12:33:27PM +0000, Fuad Tabba wrote:
> On Mon, 3 Mar 2025 at 21:49, Will Deacon <will at kernel.org> wrote:
> >
> > On Mon, Mar 03, 2025 at 07:21:33PM +0000, Fuad Tabba wrote:
> > > On Mon, 3 Mar 2025 at 19:18, Will Deacon <will at kernel.org> wrote:
> > > > On Mon, Mar 03, 2025 at 07:57:00AM +0000, Fuad Tabba wrote:
> > > > > On Fri, 28 Feb 2025 at 19:44, Quentin Perret <qperret at google.com> wrote:
> > > > > > On Wednesday 26 Feb 2025 at 21:55:19 (+0000), Fuad Tabba wrote:
> > > > > > >  static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > > >  {
> > > > > > > -     size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
> > > > > > > +     size_t pgd_sz, hyp_vm_sz;
> > > > > > >       struct kvm_vcpu *host_vcpu;
> > > > > > > -     pkvm_handle_t handle;
> > > > > > >       void *pgd, *hyp_vm;
> > > > > > >       unsigned long idx;
> > > > > > >       int ret;
> > > > > > > @@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
> > > > > > >       if (ret < 0)
> > > > > > >               goto free_vm;
> > > > > > >
> > > > > > > -     handle = ret;
> > > > > > > +     WRITE_ONCE(host_kvm->arch.pkvm.handle, ret);
> > > > > >
> > > > > > What's the reason to make this a WRITE_ONCE? Does it mean we should
> > > > > > update the readers to be READ_ONCE()?
> > > > >
> > > > > I don't remember the original reason, to be honest. In this case, it
> > > > > was to make it consistent with downstream code in Android. That said,
> > > > > I plan on revising all of these soon and fixing this (and related
> > > > > code) in light of Will's comment regarding potential specter gadgets:
> > > > >
> > > > > https://lore.kernel.org/all/20250218092705.GA17030 at willie-the-truck/
> > > >
> > > > I'm not sure the spectre stuff changes the concurrency aspects here, so
> > > > Quentin's question presumably still stands even after that.
> > > >
> > > > Looking at the Android code, this WRITE_ONCE() pairs with a READ_ONCE()
> > > > in pkvm_is_hyp_created() which is called without the config_lock held
> > > > by kvm_arch_prepare_memory_region(). However, given that
> > > > pkvm_is_hyp_created() is only testing against 0, I don't think the
> > > > _ONCE() accessors are doing anything useful in that case.
> > > >
> > > > The more confusing stuff is where 'kvm->arch.pkvm.handle' is read
> > > > directly without the 'config_lock' held. The MMU notifiers look like
> > > > they can do that, so I wonder if there's a theoretical race where they
> > > > can race with first run and issue TLB invalidation with the wrong handle?
> > > > That would apply equally to the upstream code, I think.
> > >
> > > Would using _ONCE accessors with the MMU notifiers be enough to avoid
> > > the race, or do we need to reconsider the lock protecting the handle
> > > and apply it to the notifiers?
> >
> > I'm not entirely sure... if we used _ONCE() then we'd get either the
> > correct handle or zero, but we presumably need to order that against the
> > page-table somehow. The 'mmu_lock' looks like it gives us that, but I
> > don't think the notifiers are expecting an uninitialised handle in the
> > case where the page-table is empty (i.e. if they fire before first run).
> >
> > Given that the handle is necessary for TLB invalidation, I'd be inclined
> > to make sure that the handle is allocated and published _before_ the
> > kvm_pgtable pointer checked by the notifiers is set, but that means
> > moving the handle allocation into kvm_arch_init_vm(). Is that do-able?
> 
> It is doable, but it won't be a simple patch. Up until now, the
> creation of the hyp view of a vm is associated with the first run of
> the vm, rather than its allocation at the host. Part of the reason for
> that is that much of the vm state (mainly the vcpu state) isn't
> finalized until then.
> 
> This patch series fixes this in part, by decoupling the initialization
> of the individual vcpus from the vm. Because of that, it would be
> doable, but it might be better as another patch series that we could
> test and analyze separately.
> 
> If you agree, I could whip up something and send it soon.

Yeah, I think we should fix this as a separate series and drop the
WRITE_ONCE() from this patch.

Will


From andrew at lunn.ch  Wed Mar 12 08:33:00 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 16:33:00 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>

On Wed, Mar 12, 2025 at 03:06:32PM +0000, Gupta, Suraj wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
> 
> > -----Original Message-----
> > From: Andrew Lunn <andrew at lunn.ch>
> > Sent: Wednesday, March 12, 2025 8:29 PM
> > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> > devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> > kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > <harini.katakam at amd.com>
> > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> > configuration.
> >
> > Caution: This message originated from an External Source. Use proper caution
> > when opening attachments, clicking links, or responding.
> >
> >
> > > > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > > > +    * 1) SGMII/1000base-X only.
> > > > > > +    * 2) 2500base-X only.
> > > > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > > > +    * implemented in driver.
> > > > > > +    */
> >
> > > - Keeping previous discussion short, identification of (3) depends on
> > > how user implements switching logic in FPGA (external GT or RTL
> > > logic). AXI 1G/2.5G IP provides only static speed selections and there
> > > is no standard register to communicate that to software.
> >
> > So if anybody has synthesised it as 3) this change will break their system?
> >
> >         Andrew
> 
> It will just restrict their system to (2)

Where as before, it was doing SGMII/1000base-X only. So such systems
break?

	Andrew


From vladimir.oltean at nxp.com  Wed Mar 12 08:36:32 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:36:32 +0200
Subject: [PATCH iwl-next v9 02/14] net: ethtool: mm: extract stmmac
 verification logic into common library
In-Reply-To: <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312153632.evkqnjcsuspvzp5g@skbuf>

On Sun, Mar 09, 2025 at 06:46:36AM -0400, Faizal Rahim wrote:
> @@ -7850,7 +7850,7 @@ int stmmac_suspend(struct device *dev)
>  	rtnl_unlock();
>  
>  	if (stmmac_fpe_supported(priv))
> -		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
> +		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
>  
>  	priv->speed = SPEED_UNKNOWN;
>  	return 0;

FWIW, this trivially conflicts with net-next commit 64fdb808660d ("net:
stmmac: remove write-only priv->speed").


From robdclark at gmail.com  Wed Mar 12 08:37:28 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 12 Mar 2025 08:37:28 -0700
Subject: [PATCH v18 0/5] iommu/arm-smmu: introduction of ACTLR
 implementation for Qualcomm SoCs
In-Reply-To: <20250312130846.GE6181@willie-the-truck>
References: <20241212151402.159102-1-quic_bibekkum@quicinc.com>
 <173625436399.258197.10961901698600591079.b4-ty@kernel.org>
 <20250311175528.GA5216@willie-the-truck> <CAF6AEGvDyPtXN7Cn98BKsTM9GjUzy1sTEOsLiz-cdvaZ14qWyA@mail.gmail.com>
 <20250312130846.GE6181@willie-the-truck>
Message-ID: <CAF6AEGtrUKybxPZMxkUgjg8JCxPr7-pRe0noS7=y6UrbHxDzZw@mail.gmail.com>

On Wed, Mar 12, 2025 at 6:08?AM Will Deacon <will at kernel.org> wrote:
>
> On Tue, Mar 11, 2025 at 01:03:29PM -0700, Rob Clark wrote:
> > On Tue, Mar 11, 2025 at 10:55?AM Will Deacon <will at kernel.org> wrote:
> > >
> > > On Tue, Jan 07, 2025 at 04:42:39PM +0000, Will Deacon wrote:
> > > > On Thu, 12 Dec 2024 20:43:57 +0530, Bibek Kumar Patro wrote:
> > > > > This patch series consist of six parts and covers the following:
> > > > >
> > > > > 1. Provide option to re-enable context caching to retain prefetcher
> > > > >    settings during reset and runtime suspend.
> > > > >
> > > > > 2. Remove cfg inside qcom_smmu structure and replace it with single
> > > > >    pointer to qcom_smmu_match_data avoiding replication of multiple
> > > > >    members from same.
> > > > >
> > > > > [...]
> > > >
> > > > Applied to iommu (arm/smmu/updates), thanks!
> > > >
> > > > [1/5] iommu/arm-smmu: Re-enable context caching in smmu reset operation
> > > >       https://git.kernel.org/iommu/c/ef4144b1b47d
> > > > [2/5] iommu/arm-smmu: Refactor qcom_smmu structure to include single pointer
> > > >       https://git.kernel.org/iommu/c/445d7a8ed90e
> > > > [3/5] iommu/arm-smmu: Add support for PRR bit setup
> > > >       https://git.kernel.org/iommu/c/7f2ef1bfc758
> > > > [4/5] iommu/arm-smmu: Introduce ACTLR custom prefetcher settings
> > > >       https://git.kernel.org/iommu/c/9fe18d825a58
> > > > [5/5] iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500
> > > >       https://git.kernel.org/iommu/c/3e35c3e725de
> > >
> > > Hrm. I'm not seeing any user of the new ->set_prr*_() functions in
> > > linux-next yet. Is there something under review, or should I revert this
> > > for now?
> >
> > It is WIP, part of a larger patchset adding sparse binding support in
> > drm/msm.  Please do not revert.
>
> Sure, if it's actively being worked on then I'll leave the hooks in
> place.
>
> Do you have a link to the patchset so that I can follow along, please?
>
> Will

https://patchwork.freedesktop.org/series/142263/

I'm currently working on resolving the shrinker hack, which is the
remaining TODO.  So I'll hopefully be able to drop the RFC tag and
post a new version in a couple of weeks.

BR,
-R


From vkoul at kernel.org  Wed Mar 12 08:58:23 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Wed, 12 Mar 2025 16:58:23 +0100
Subject: [PATCH] phy: rockchip: usbdp: Avoid call hpd_event_trigger in
 dp_phy_init
In-Reply-To: <20250302115257.188774-1-andyshrk@163.com>
References: <20250302115257.188774-1-andyshrk@163.com>
Message-ID: <174179510386.536552.5606148469623251433.b4-ty@kernel.org>


On Sun, 02 Mar 2025 19:52:25 +0800, Andy Yan wrote:
> Function rk_udphy_dp_hpd_event_trigger will set vogrf let it
> trigger HPD interrupt to DP by Type-C. This configuration is only
> required when the DP work in Alternate Mode, and called by
> typec_mux_set. In standard DP mode, such settings will prevent
> the DP from receiving HPD interrupts.
> 
> 
> [...]

Applied, thanks!

[1/1] phy: rockchip: usbdp: Avoid call hpd_event_trigger in dp_phy_init
      commit: 28dc672a1a877c77b000c896abd8f15afcdc1b0c

Best regards,
-- 
~Vinod




From vkoul at kernel.org  Wed Mar 12 08:58:27 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Wed, 12 Mar 2025 16:58:27 +0100
Subject: [PATCH] phy: rockchip: usbdp: Remove unnecessary bool
 conversion
In-Reply-To: <20250224220339.199180-2-thorsten.blum@linux.dev>
References: <20250224220339.199180-2-thorsten.blum@linux.dev>
Message-ID: <174179510715.536552.15016405189922821330.b4-ty@kernel.org>


On Mon, 24 Feb 2025 23:03:39 +0100, Thorsten Blum wrote:
> Remove the unnecessary bool conversion and simplify the code.
> 
> 

Applied, thanks!

[1/1] phy: rockchip: usbdp: Remove unnecessary bool conversion
      commit: b52b330046d16f6e4ce94ae6fa349cc30af027b3

Best regards,
-- 
~Vinod




From vladimir.oltean at nxp.com  Wed Mar 12 09:00:52 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 18:00:52 +0200
Subject: [PATCH iwl-next v9 14/14] igc: add support to get frame
 preemption statistics via ethtool
In-Reply-To: <20250309104648.3895551-15-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-15-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-15-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-15-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312160052.ypq6u4na3klib6l2@skbuf>

On Sun, Mar 09, 2025 at 06:46:48AM -0400, Faizal Rahim wrote:
> +/**
> + * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
> + * @reg_value: Register value for IGC_PRMEXCPRCNT
> + * Return: The count of frame assembly errors.
> + */
> +static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
> +{
> +	/* Out of order statistics */
> +	u32 ooo_frame_cnt, ooo_frag_cnt;
> +	u32 miss_frame_frag_cnt;
> +
> +	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
> +	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
> +	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
> +
> +	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
> +}

Counters should be monotonically increasing 64-bit values, and as per your
response in v8, these are 8-bit saturating, clear-on-read values, which
I have some doubts about. But I don't think there's anything that
software can do to make that situation any better. Even reading them
periodically and integrating them into a software sum risks losing
events due to the saturating behavior, which is confusing in its own
way. So I'll have to tolerate this.

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:47:44 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:47:44 +0200
Subject: [PATCH iwl-next v9 06/14] igc: use FIELD_PREP and GENMASK for
 existing TX packet buffer size
In-Reply-To: <20250309104648.3895551-7-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-7-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-7-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-7-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312154744.rfcq4prjj5tyrflx@skbuf>

On Sun, Mar 09, 2025 at 06:46:40AM -0400, Faizal Rahim wrote:
> In preparation for an upcoming patch that will modify the TX buffer size
> in  TSN mode, replace IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT
> implementation with new macros that utilizes FIELD_PREP and GENMASK for
> clarity.
> 
> The newly introduced macros follow the naming from the i226 SW User Manual
> for easy reference.
> 
> I've tested IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT before and after the
> refactoring, and their values remain unchanged.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:49:20 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:49:20 +0200
Subject: [PATCH iwl-next v9 08/14] igc: use FIELD_PREP and GENMASK for
 existing RX packet buffer size
In-Reply-To: <20250309104648.3895551-9-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-9-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-9-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-9-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312154920.3tv45m5cv6jqplqp@skbuf>

On Sun, Mar 09, 2025 at 06:46:42AM -0400, Faizal Rahim wrote:
> Prepare for an upcoming patch that modifies the RX buffer size in TSN mode.
> Refactor IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN using
> FIELD_PREP and GENMASK to improve clarity and maintainability. Refactor
> both macros for consistency, even though the upcoming patch only use
> IGC_RXPBSIZE_EXP_BMC_DEFAULT.
> 
> The newly introduced macros follow the naming from the i226 SW User Manual
> for easy reference.
> 
> I've tested IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN before
> and after the refactoring, and their values remain unchanged.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From michal.kubiak at intel.com  Wed Mar 12 08:50:03 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Wed, 12 Mar 2025 16:50:03 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9GgHZxkSqFCkwMg@lore-desk>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
 <Z9Ga7gx1u3JsOemE@localhost.localdomain>
 <Z9GgHZxkSqFCkwMg@lore-desk>
Message-ID: <Z9GtKwAuEx+7HKjR@localhost.localdomain>

On Wed, Mar 12, 2025 at 03:54:21PM +0100, Lorenzo Bianconi wrote:
> > On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> > > The system occasionally crashes dereferencing a NULL pointer when it is
> > > forwarding constant, high load bidirectional traffic.
> > > 
> > > [ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
> > > [ 2149.925812] Mem abort info:
> > > [ 2149.928713]   ESR = 0x0000000096000005
> > > [ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
> > > [ 2149.938429]   SET = 0, FnV = 0
> > > [ 2149.941814]   EA = 0, S1PTW = 0
> > > [ 2149.945187]   FSC = 0x05: level 1 translation fault
> > > [ 2149.950348] Data abort info:
> > > [ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
> > > [ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> > > [ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > > [ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
> > > [ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
> > > [ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
> > > [ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
> > > [ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
> > > [ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
> > > [ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
> > > [ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > > [ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > > [ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
> > > [ 2150.218149] sp : ffffffc080e8ba10
> > > [ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
> > > [ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
> > > [ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
> > > [ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
> > > [ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
> > > [ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
> > > [ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
> > > [ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
> > > [ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
> > > [ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
> > > [ 2150.292811] Call trace:
> > > [ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > > [ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
> > > [ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
> > > [ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
> > > [ 2150.318200]  process_one_work+0x178/0x2f0
> > > [ 2150.322211]  worker_thread+0x2e4/0x4cc
> > > [ 2150.325953]  kthread+0xd8/0xdc
> > > [ 2150.329008]  ret_from_fork+0x10/0x20
> > > [ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
> > > [ 2150.338681] ---[ end trace 0000000000000000 ]---
> > > [ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
> > > [ 2150.349035] SMP: stopping secondary CPUs
> > > [ 2150.352954] Kernel Offset: disabled
> > > [ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
> > > [ 2150.361743] Memory Limit: none
> > > 
> > > Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> > > routine.
> > > 
> > > Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
> > 
> > The patch has "Fixes" tag, but it is sent to "net-next" tree.
> > I think it's rather a candidate for "net".
> 
> The offending commit is just in net-next at the moment. Do you prefer to drop
> the Fixes tag?

Oh, I didn't realize this is a new driver in net-next. So, I'm OK with
the "Fixes" tag then.

> 
> > 
> > > Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> > > ---
> > >  drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++
> > >  drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
> > >  drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
> > >  3 files changed, 27 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > > index c0a642568ac115ea9df6fbaf7133627a4405a36c..776222595b84e4fba6ae5943420e0edf0d0ecf8f 100644
> > > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > > @@ -2454,6 +2454,22 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> > >  	}
> > >  }
> > >  
> > > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > > +			     struct airoha_gdm_port *port)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> > 
> > You could reduce the number of lines by moving the declaration inside the
> > loop:
> > 	for (int i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> 
> to be consistent with the driver I prefer to keep the current approach.

OK. That was my suggestion only. Let's keep the code consistent then.

> 
> > 
> > > +		if (!eth->ports[i])
> > > +			continue;
> > 
> > Isn't this NULL check redundant?
> > In the second check you compare the table element to a real pointer.
> 
> Can netdev_priv() be NULL? If not, I guess we can remove this check.

I guess it shouldn't be NULL since "devm_alloc_etherdev_mqs()" was
called, but I'm not 100% sure if there are any special cases for the "airoha"
driver. Maybe in such cases it would be better to check for the netdev_priv?
Anyway, such checks seem a bit too defensive to me.

Thanks,
Michal

> 
> Regards,
> Lorenzo
> 
> > 
> > > +
> > > +		if (eth->ports[i] == port)
> > > +			return 0;
> > > +	}
> > > +
> > > +	return -EINVAL;
> > > +}
> > > +
> > >  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> > >  				 struct device_node *np, int index)
> > >  {
> > > diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> > > index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
> > > --- a/drivers/net/ethernet/airoha/airoha_eth.h
> > > +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> > > @@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
> > >  #define airoha_qdma_clear(qdma, offset, val)			\
> > >  	airoha_rmw((qdma)->regs, (offset), (val), 0)
> > >  
> > > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > > +			     struct airoha_gdm_port *port);
> > > +
> > >  void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
> > >  int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
> > >  				 void *cb_priv);
> > > diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> > > index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
> > > --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> > > +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> > > @@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
> > >  #endif
> > >  }
> > >  
> > > -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > > +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> > > +					struct airoha_foe_entry *hwe,
> > >  					struct net_device *dev, int type,
> > >  					struct airoha_flow_data *data,
> > >  					int l4proto)
> > > @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > >  	if (dev) {
> > >  		struct airoha_gdm_port *port = netdev_priv(dev);
> > >  		u8 pse_port;
> > > +		int err;
> > > +
> > > +		err = airoha_is_valid_gdm_port(eth, port);
> > > +		if (err)
> > > +			return err;
> > >  
> > >  		if (dsa_port >= 0)
> > >  			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
> > > @@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
> > >  	    !is_valid_ether_addr(data.eth.h_dest))
> > >  		return -EINVAL;
> > >  
> > > -	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
> > > +	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
> > >  					   &data, l4proto);
> > >  	if (err)
> > >  		return err;
> > > 
> > > ---
> > > base-commit: 0ea09cbf8350b70ad44d67a1dcb379008a356034
> > > change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a
> > > 
> > > Best regards,
> > > -- 
> > > Lorenzo Bianconi <lorenzo at kernel.org>
> > > 
> > > 




From vkoul at kernel.org  Wed Mar 12 08:51:50 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Wed, 12 Mar 2025 16:51:50 +0100
Subject: [PATCH v6 2/2] phy: rockchip: Add Samsung MIPI D-/C-PHY driver
In-Reply-To: <2030933.8hb0ThOEGa@diego>
References: <20250213210554.1645755-1-heiko@sntech.de>
 <20250213210554.1645755-3-heiko@sntech.de>
 <Z68zdiIl75k2Vv9i@vaman>
 <2030933.8hb0ThOEGa@diego>
Message-ID: <Z9GtlvHwd8/blVKl@vaman>


Sorry this slipped thru...

On 19-02-25, 23:51, Heiko St?bner wrote:
> Hi Vinod,
> 
> thanks for the review.
> I've dropped all the parts that would've just gotten a "ok, changed" ;-)
> 
> Am Freitag, 14. Februar 2025, 13:13:42 MEZ schrieb Vinod Koul:
> > On 13-02-25, 22:05, Heiko Stuebner wrote:
> 
> > > +	{ 200,  7,   1,  0, 33,  9,  0, 26,  5,  0, 11},
> > > +	{ 190,  7,   1,  0, 32,  9,  0, 25,  5,  0, 11},
> > > +	{ 180,  6,   1,  0, 32,  8,  0, 25,  5,  0, 10},
> > > +	{ 170,  6,   0,  0, 32,  8,  0, 25,  5,  0, 10},
> > > +	{ 160,  5,   0,  0, 31,  8,  0, 24,  4,  0,  9},
> > > +	{ 150,  5,   0,  0, 31,  8,  0, 24,  5,  0,  9},
> > > +	{ 140,  5,   0,  0, 31,  8,  0, 24,  5,  0,  8},
> > > +	{ 130,  4,   0,  0, 30,  6,  0, 23,  3,  0,  8},
> > > +	{ 120,  4,   0,  0, 30,  6,  0, 23,  3,  0,  7},
> > > +	{ 110,  3,   0,  0, 30,  6,  0, 23,  3,  0,  7},
> > > +	{ 100,  3,   0,  0, 29,  5,  0, 22,  2,  0,  6},
> > > +	{  90,  3,   0,  0, 29,  5,  0, 22,  2,  0,  6},
> > > +	{  80,  2,   0,  0, 28,  5,  0, 22,  2,  0,  5},
> > > +};
> > 
> > any word on where this table came from, maybe worth documenting that
> > part
> 
> sadly not.
> 
> The table itself came from the vendor-kernel, and I would assume there

Maybe make a note that this is from vendor kernel

> it came from some super-secret additional documentation Rockchip
> got with the IP documentation.
> 
> It is sadly not part of the RK3588 manual.
> 
> 
> > > +
> > > +static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)
> > > +{
> > > +	u32 bias_con2 = 0x3223;
> > 
> > magic value?
> 
> Converted over to some more meaningful constants.
> Did the same to bias_con0+1 below that one too.
> 
> 
> > > +static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung)
> > > +{
> > > +	regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, PHY_ENABLE, 0);
> > > +	regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0, PHY_ENABLE, 0);
> > > +	regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0, PHY_ENABLE, 0);
> > > +	regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0, PHY_ENABLE, 0);
> > > +	regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0, PHY_ENABLE, 0);
> > 
> > Is writing to a register (mmio) faster than a switch case for checking
> > lane count and disabling specific lanes?
> 
> It might make sense to mimic the lane_enable way of doing things, even if
> just for things looking the same in both functions.
> 
> I guess disabling lanes does not really care about minimal speed differences
> a switch/case would cause :-)

ok

> 
> > 
> > > +static void samsung_mipi_dcphy_pll_configure(struct samsung_mipi_dcphy *samsung)
> > > +{
> > > +	regmap_update_bits(samsung->regmap, PLL_CON0, S_MASK | P_MASK,
> > > +			   S(samsung->pll.scaler) | P(samsung->pll.prediv));
> > > +
> > > +	if (samsung->pll.dsm < 0) {
> > > +		u16 dsm_tmp;
> > > +
> > > +		/* Using opposite number subtraction to find complement */
> > > +		dsm_tmp = abs(samsung->pll.dsm);
> > > +		dsm_tmp = dsm_tmp - 1;
> > > +		dsm_tmp ^= 0xffff;
> > > +		regmap_write(samsung->regmap, PLL_CON1, dsm_tmp);
> > > +	} else {
> > > +		regmap_write(samsung->regmap, PLL_CON1, samsung->pll.dsm);
> > > +	}
> > > +
> > > +	regmap_update_bits(samsung->regmap, PLL_CON2,
> > > +			   M_MASK, M(samsung->pll.fbdiv));
> > > +
> > > +	if (samsung->pll.ssc_en) {
> > > +		regmap_write(samsung->regmap, PLL_CON3,
> > > +			     MRR(samsung->pll.mrr) | MFR(samsung->pll.mfr));
> > > +		regmap_update_bits(samsung->regmap, PLL_CON4, SSCG_EN, SSCG_EN);
> > > +	}
> > > +
> > > +	regmap_write(samsung->regmap, PLL_CON5, RESET_N_SEL | PLL_ENABLE_SEL);
> > > +	regmap_write(samsung->regmap, PLL_CON7, PLL_LOCK_CNT(0xf000));
> > > +	regmap_write(samsung->regmap, PLL_CON8, PLL_STB_CNT(0xf000));
> > 
> > I guess you are writing to upper nibble, maybe define that, if we can
> 
> Nope ... the value is defined as bits [15:0] and both being pll lock and
> stabilization timing control registers. Sadly yet again, their usage detail
> is not documented, the manual even does not supply a unit for the 
> register value :-(

:-(


-- 
~Vinod


From vladimir.oltean at nxp.com  Wed Mar 12 08:52:45 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:52:45 +0200
Subject: [PATCH iwl-next v9 10/14] igc: add support for frame preemption
 verification
In-Reply-To: <20250309104648.3895551-11-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-11-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-11-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-11-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312155245.fdntan3nml424ufe@skbuf>

On Sun, Mar 09, 2025 at 06:46:44AM -0400, Faizal Rahim wrote:
> This patch implements the "ethtool --set-mm" callback to trigger the
> frame preemption verification handshake.
> 
> Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool
> to perform the verification handshake for igc.
> The structure fpe.mmsv is set by mmsv in ethtool and should remain
> read-only for the driver.
> 
> Other mmsv callbacks:
> a) configure_tx() -> not used yet at this point
>    - igc lacks registers to configure FPE in the transmit direction, so
>      this API is not utilized for now. When igc supports preemptible queue,
>      driver will use this API to manage its configuration.
> 
> b) configure_pmac() -> not used
>    - this callback dynamically controls pmac_enabled at runtime. For
>      example, mmsv calls configure_pmac() and disables pmac_enabled when
>      the link partner goes down, even if the user previously enabled it.
>      The intention is to save power but it is not feasible in igc
>      because it causes an endless adapter reset loop:
> 
>    1) Board A and Board B complete the verification handshake. Tx mode
>       register for both boards are in TSN mode.
>    2) Board B link goes down.
> 
>    On Board A:
>    3) mmsv calls configure_pmac() with pmac_enabled = false.
>    4) configure_pmac() in igc updates a new field based on pmac_enabled.
>       Driver uses this field in igc_tsn_new_flags() to indicate that the
>       user enabled/disabled FPE.
>    5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
>       whether an adapter reset is needed. Calls existing logic in
>       igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
>    6) Since pmac_enabled is now disabled and no other TSN feature is
>       active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
>       mode will switch from TSN to Legacy.
>    7) Driver resets the adapter.
>    8) Registers are set, and Tx mode switches to Legacy.
>    9) When link partner is up, steps 3?8 repeat, but this time with
>       pmac_enabled = true, reactivating TSN.
>       igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
>       mode will switch from Legacy to TSN.
>   10) Driver resets the adapter.
>   11) Adapter reset completes, registers are set, and Tx mode switches to
>       TSN.
> 
>   On Board B:
>   12) Adapter reset on Board A at step 10 causes it to detect its link
>       partner as down.
>   13) Repeats steps 3?8.
>   14) Once reset adapter on Board A is completed at step 11, it detects
>       its link partner as up.
>   15) Repeats steps 9?11.
> 
>    - this cycle repeats indefinitely. To avoid this issue, igc only uses
>      mmsv.pmac_enabled to track whether FPE is enabled or disabled.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
> Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:54:08 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:54:08 +0200
Subject: [PATCH iwl-next v9 11/14] igc: add support to set
 tx-min-frag-size
In-Reply-To: <20250309104648.3895551-12-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-12-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-12-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-12-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312155408.3shdw7fx4nr3taar@skbuf>

On Sun, Mar 09, 2025 at 06:46:45AM -0400, Faizal Rahim wrote:
> Add support for setting tx-min-frag-size via the set_mm callback in igc.
> If the requested value is unsupported, round it up to the smallest
> supported i226 size (64, 128, 192, 256) and send a netlink message to
> inform the user.
> 
> Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:54:44 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:54:44 +0200
Subject: [PATCH iwl-next v9 12/14] igc: block setting preemptible traffic
 class in taprio
In-Reply-To: <20250309104648.3895551-13-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-13-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-13-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-13-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312155444.366m56g3fsvn5qdy@skbuf>

On Sun, Mar 09, 2025 at 06:46:46AM -0400, Faizal Rahim wrote:
> Since preemptible tc implementation is not ready yet, block it from being
> set in taprio. The existing code already blocks it in mqprio.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:39:14 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:39:14 +0200
Subject: [PATCH iwl-next v9 03/14] net: ethtool: mm: reset verification
 status when link is down
In-Reply-To: <20250309104648.3895551-4-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-4-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312153914.pqmefvkafp7zq5k5@skbuf>

On Sun, Mar 09, 2025 at 06:46:37AM -0400, Faizal Rahim wrote:
> When the link partner goes down, "ethtool --show-mm" still displays
> "Verification status: SUCCEEDED," reflecting a previous state that is
> no longer valid.
> 
> Reset the verification status to ensure it reflects the current state.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vladimir.oltean at nxp.com  Wed Mar 12 08:55:23 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:55:23 +0200
Subject: [PATCH iwl-next v9 13/14] igc: add support to get MAC Merge data
 via ethtool
In-Reply-To: <20250309104648.3895551-14-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-14-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-14-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-14-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312155523.rs6544cbsvyn5ojj@skbuf>

On Sun, Mar 09, 2025 at 06:46:47AM -0400, Faizal Rahim wrote:
> Implement "ethtool --show-mm" callback for IGC.
> 
> Tested with command:
> $ ethtool --show-mm enp1s0.
>   MAC Merge layer state for enp1s0:
>   pMAC enabled: on
>   TX enabled: on
>   TX active: on
>   TX minimum fragment size: 64
>   RX minimum fragment size: 60
>   Verify enabled: on
>   Verify time: 128
>   Max verify time: 128
>   Verification status: SUCCEEDED
> 
> Verified that the fields value are retrieved correctly.
> 
> Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From vkoul at kernel.org  Wed Mar 12 08:58:20 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Wed, 12 Mar 2025 16:58:20 +0100
Subject: [PATCH v2] phy: rockchip: usbdp: Only verify link
 rates/lanes/voltage when the corresponding set flags are set
In-Reply-To: <20250312080041.524546-1-andyshrk@163.com>
References: <20250312080041.524546-1-andyshrk@163.com>
Message-ID: <174179510031.536552.7442060711637646022.b4-ty@kernel.org>


On Wed, 12 Mar 2025 16:00:07 +0800, Andy Yan wrote:
> According documentation of phy_configure_opts_dp, at the configure
> stage, link rates should only be verify/configure when set_rate
> flag is set, the same applies to lanes and voltage.
> 
> So do it as the documentation says.
> Because voltage setting depends on the lanes, link rates set
> previously, so record the link rates and lanes at it's verify stage.
> 
> [...]

Applied, thanks!

[1/1] phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the corresponding set flags are set
      commit: 969a38be437b68dc9e12e3c3f08911c9f9c8be73

Best regards,
-- 
~Vinod




From vladimir.oltean at nxp.com  Wed Mar 12 08:46:20 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Wed, 12 Mar 2025 17:46:20 +0200
Subject: [PATCH iwl-next v9 02/14] net: ethtool: mm: extract stmmac
 verification logic into common library
In-Reply-To: <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
References: <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-1-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
 <20250309104648.3895551-3-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250312154620.abqswbrzqvakeeau@skbuf>

On Sun, Mar 09, 2025 at 06:46:36AM -0400, Faizal Rahim wrote:
> From: Vladimir Oltean <vladimir.oltean at nxp.com>
> 
> It appears that stmmac is not the only hardware which requires a
> software-driven verification state machine for the MAC Merge layer.
> 
> While on the one hand it's good to encourage hardware implementations,
> on the other hand it's quite difficult to tolerate multiple drivers
> implementing independently fairly non-trivial logic.
> 
> Extract the hardware-independent logic from stmmac into library code and
> put it in ethtool. Name the state structure "mmsv" for MAC Merge
> Software Verification. Let this expose an operations structure for
> executing the hardware stuff: sync hardware with the tx_active boolean
> (result of verification process), enable/disable the pMAC, send mPackets,
> notify library of external events (reception of mPackets), as well as
> link state changes.
> 
> Note that it is assumed that the external events are received in hardirq
> context. If they are not, it is probably a good idea to disable hardirqs
> when calling ethtool_mmsv_event_handle(), because the library does not
> do so.
> 
> Also, the MM software verification process has no business with the
> tx_min_frag_size, that is all the driver's to handle.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
> Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Tested-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> Tested-by: Furong Xu <0x1207 at gmail.com>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>


From Suraj.Gupta2 at amd.com  Wed Mar 12 09:08:02 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Wed, 12 Mar 2025 16:08:02 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
Message-ID: <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Andrew Lunn <andrew at lunn.ch>
> Sent: Wednesday, March 12, 2025 9:03 PM
> To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> <harini.katakam at amd.com>
> Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Wed, Mar 12, 2025 at 03:06:32PM +0000, Gupta, Suraj wrote:
> > [AMD Official Use Only - AMD Internal Distribution Only]
> >
> > > -----Original Message-----
> > > From: Andrew Lunn <andrew at lunn.ch>
> > > Sent: Wednesday, March 12, 2025 8:29 PM
> > > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org;
> > > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > > <harini.katakam at amd.com>
> > > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > 2500base-X only configuration.
> > >
> > > Caution: This message originated from an External Source. Use proper
> > > caution when opening attachments, clicking links, or responding.
> > >
> > >
> > > > > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > > > > +    * 1) SGMII/1000base-X only.
> > > > > > > +    * 2) 2500base-X only.
> > > > > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > > > > +    * implemented in driver.
> > > > > > > +    */
> > >
> > > > - Keeping previous discussion short, identification of (3) depends
> > > > on how user implements switching logic in FPGA (external GT or RTL
> > > > logic). AXI 1G/2.5G IP provides only static speed selections and
> > > > there is no standard register to communicate that to software.
> > >
> > > So if anybody has synthesised it as 3) this change will break their system?
> > >
> > >         Andrew
> >
> > It will just restrict their system to (2)
>
> Where as before, it was doing SGMII/1000base-X only. So such systems break?
>
>         Andrew

If the user wants (3), they need to add their custom FPGA logic which anyway will require additional driver changes. (3) was not completely supported by existing driver.


From helgaas at kernel.org  Wed Mar 12 09:16:00 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 11:16:00 -0500
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250305132018.2260771-1-s-vadapalli@ti.com>
Message-ID: <20250312161600.GA680640@bhelgaas>

[+to Matt, author of e49ad667815d]

On Wed, Mar 05, 2025 at 06:50:18PM +0530, Siddharth Vadapalli wrote:
> Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
> J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
> to the Technical Reference Manual and Register Documentation for the J784S4
> SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
> the field for the link-state interrupt. Instead, it is BIT(10) of the
> "PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
> field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".

I guess the reason we want this is that on J784S4, we ignore actual
link-down interrupts (and we don't write STATUS_CLR_REG_SYS_2 to clear
the interrupt indication, so maybe there's an interrupt storm), and we
think some other interrupt (DPA_1, whatever that is) is actually a
link-down interrupt?

> Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> already reuse this macro since it accurately represents the link-state
> field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> 
> [0]: https://www.ti.com/lit/zip/spruj52

Thanks for the spec URL.  Can you include a relevant section number?
I searched for some of this stuff but couldn't find it.

Since I have low confidence that the URL will be valid after a few
years, I wish the spec also had a human-readable name and revision
number.  But maybe the alphabet soup or "SPRUJ52D", "revised July
2024" is all we can hope for.

> Fixes: e49ad667815d ("PCI: j721e: Add TI J784S4 PCIe configuration")
> Cc: stable at vger.kernel.org
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> ---
> 
> Hello,
> 
> This patch is based on commit
> 48a5eed9ad58 Merge tag 'devicetree-fixes-for-6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
> of the master branch of Linux.
> 
> Patch has been tested on J784S4-EVM, validating that disconnecting an
> Endpoint Device connected to J784S4-EVM results in the following message
> on the J784S4-EVM:
> 	j721e-pcie 2900000.pcie: LINK DOWN!
> which wasn't seen earlier.
> 
> Regards,
> Siddharth.
> 
>  drivers/pci/controller/cadence/pci-j721e.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
> index 0341d51d6aed..1da9d9918d0d 100644
> --- a/drivers/pci/controller/cadence/pci-j721e.c
> +++ b/drivers/pci/controller/cadence/pci-j721e.c
> @@ -376,13 +376,13 @@ static const struct j721e_pcie_data j784s4_pcie_rc_data = {
>  	.mode = PCI_MODE_RC,
>  	.quirk_retrain_flag = true,
>  	.byte_access_allowed = false,
> -	.linkdown_irq_regfield = LINK_DOWN,
> +	.linkdown_irq_regfield = J7200_LINK_DOWN,
>  	.max_lanes = 4,
>  };
>  
>  static const struct j721e_pcie_data j784s4_pcie_ep_data = {
>  	.mode = PCI_MODE_EP,
> -	.linkdown_irq_regfield = LINK_DOWN,
> +	.linkdown_irq_regfield = J7200_LINK_DOWN,
>  	.max_lanes = 4,
>  };
>  
> -- 
> 2.34.1
> 


From ericwouds at gmail.com  Wed Mar 12 09:21:29 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Wed, 12 Mar 2025 17:21:29 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <Z9DKxOnxr1fSv0On@calendula>
References: <20250305102949.16370-1-ericwouds@gmail.com>
 <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com> <Z9DKxOnxr1fSv0On@calendula>
Message-ID: <58cbe875-80e7-4a44-950b-b836b97f3259@gmail.com>



On 3/12/25 12:44 AM, Pablo Neira Ayuso wrote:
> Therefore, I suggest you start with a much smaller series with a
> carefully selected subset including preparatory patches. I suggest you
> start with the software enhancements only. Please, add datapath tests.

Then I will split it in:
1. Separate preparatory patches and small patch-sets that apply
     to the forward-fastpath already.
2. One patch-set that brings the bridge-fastpath with datapath tests.

> P.S: You work is important, very important, but maybe there is no need
> to Cc so many mailing lists and people, maybe netdev@,
> netfilter-devel@ and bridge@ is sufficient.

Ok, but my main question then is which tree should I work in, and
therefore which tag should I give my patches, [nf] or [net-next].
I think it will get more complicated if I split my patch-set and half of
the patches go to [nf] and another half to [net-next].

What do you suggest?



From lorenzo at kernel.org  Wed Mar 12 09:22:47 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Wed, 12 Mar 2025 17:22:47 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9GtKwAuEx+7HKjR@localhost.localdomain>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
 <Z9Ga7gx1u3JsOemE@localhost.localdomain>
 <Z9GgHZxkSqFCkwMg@lore-desk>
 <Z9GtKwAuEx+7HKjR@localhost.localdomain>
Message-ID: <Z9G01zGCpbw1YHNs@lore-desk>

> On Wed, Mar 12, 2025 at 03:54:21PM +0100, Lorenzo Bianconi wrote:
> > > On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> > > > The system occasionally crashes dereferencing a NULL pointer when it is
> > > > forwarding constant, high load bidirectional traffic.
> > > > 
> > > > [ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
> > > > [ 2149.925812] Mem abort info:
> > > > [ 2149.928713]   ESR = 0x0000000096000005
> > > > [ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
> > > > [ 2149.938429]   SET = 0, FnV = 0
> > > > [ 2149.941814]   EA = 0, S1PTW = 0
> > > > [ 2149.945187]   FSC = 0x05: level 1 translation fault
> > > > [ 2149.950348] Data abort info:
> > > > [ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
> > > > [ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> > > > [ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > > > [ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
> > > > [ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
> > > > [ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
> > > > [ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
> > > > [ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
> > > > [ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
> > > > [ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
> > > > [ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > > > [ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > > > [ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
> > > > [ 2150.218149] sp : ffffffc080e8ba10
> > > > [ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
> > > > [ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
> > > > [ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
> > > > [ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
> > > > [ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
> > > > [ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
> > > > [ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
> > > > [ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
> > > > [ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
> > > > [ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
> > > > [ 2150.292811] Call trace:
> > > > [ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
> > > > [ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
> > > > [ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
> > > > [ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
> > > > [ 2150.318200]  process_one_work+0x178/0x2f0
> > > > [ 2150.322211]  worker_thread+0x2e4/0x4cc
> > > > [ 2150.325953]  kthread+0xd8/0xdc
> > > > [ 2150.329008]  ret_from_fork+0x10/0x20
> > > > [ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
> > > > [ 2150.338681] ---[ end trace 0000000000000000 ]---
> > > > [ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
> > > > [ 2150.349035] SMP: stopping secondary CPUs
> > > > [ 2150.352954] Kernel Offset: disabled
> > > > [ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
> > > > [ 2150.361743] Memory Limit: none
> > > > 
> > > > Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> > > > routine.
> > > > 
> > > > Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
> > > 
> > > The patch has "Fixes" tag, but it is sent to "net-next" tree.
> > > I think it's rather a candidate for "net".
> > 
> > The offending commit is just in net-next at the moment. Do you prefer to drop
> > the Fixes tag?
> 
> Oh, I didn't realize this is a new driver in net-next. So, I'm OK with
> the "Fixes" tag then.
> 
> > 
> > > 
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> > > > ---
> > > >  drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++
> > > >  drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
> > > >  drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
> > > >  3 files changed, 27 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > > > index c0a642568ac115ea9df6fbaf7133627a4405a36c..776222595b84e4fba6ae5943420e0edf0d0ecf8f 100644
> > > > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > > > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > > > @@ -2454,6 +2454,22 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> > > >  	}
> > > >  }
> > > >  
> > > > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > > > +			     struct airoha_gdm_port *port)
> > > > +{
> > > > +	int i;
> > > > +
> > > > +	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> > > 
> > > You could reduce the number of lines by moving the declaration inside the
> > > loop:
> > > 	for (int i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> > 
> > to be consistent with the driver I prefer to keep the current approach.
> 
> OK. That was my suggestion only. Let's keep the code consistent then.
> 
> > 
> > > 
> > > > +		if (!eth->ports[i])
> > > > +			continue;
> > > 
> > > Isn't this NULL check redundant?
> > > In the second check you compare the table element to a real pointer.
> > 
> > Can netdev_priv() be NULL? If not, I guess we can remove this check.
> 
> I guess it shouldn't be NULL since "devm_alloc_etherdev_mqs()" was
> called, but I'm not 100% sure if there are any special cases for the "airoha"
> driver. Maybe in such cases it would be better to check for the netdev_priv?
> Anyway, such checks seem a bit too defensive to me.

the dev pointer can be allocated even outside of airoha_eth driver.
This pointer is provided by the flowtable.
I guess we can drop the NULL pointer check above, and do something like:

	if (port && eth->ports[i] == port)
		return 0;

what do you think?

Regards,
Lorenzo

> 
> Thanks,
> Michal
> 
> > 
> > Regards,
> > Lorenzo
> > 
> > > 
> > > > +
> > > > +		if (eth->ports[i] == port)
> > > > +			return 0;
> > > > +	}
> > > > +
> > > > +	return -EINVAL;
> > > > +}
> > > > +
> > > >  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> > > >  				 struct device_node *np, int index)
> > > >  {
> > > > diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> > > > index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
> > > > --- a/drivers/net/ethernet/airoha/airoha_eth.h
> > > > +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> > > > @@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
> > > >  #define airoha_qdma_clear(qdma, offset, val)			\
> > > >  	airoha_rmw((qdma)->regs, (offset), (val), 0)
> > > >  
> > > > +int airoha_is_valid_gdm_port(struct airoha_eth *eth,
> > > > +			     struct airoha_gdm_port *port);
> > > > +
> > > >  void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
> > > >  int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
> > > >  				 void *cb_priv);
> > > > diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> > > > index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
> > > > --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> > > > +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> > > > @@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
> > > >  #endif
> > > >  }
> > > >  
> > > > -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > > > +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> > > > +					struct airoha_foe_entry *hwe,
> > > >  					struct net_device *dev, int type,
> > > >  					struct airoha_flow_data *data,
> > > >  					int l4proto)
> > > > @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > > >  	if (dev) {
> > > >  		struct airoha_gdm_port *port = netdev_priv(dev);
> > > >  		u8 pse_port;
> > > > +		int err;
> > > > +
> > > > +		err = airoha_is_valid_gdm_port(eth, port);
> > > > +		if (err)
> > > > +			return err;
> > > >  
> > > >  		if (dsa_port >= 0)
> > > >  			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
> > > > @@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
> > > >  	    !is_valid_ether_addr(data.eth.h_dest))
> > > >  		return -EINVAL;
> > > >  
> > > > -	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
> > > > +	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
> > > >  					   &data, l4proto);
> > > >  	if (err)
> > > >  		return err;
> > > > 
> > > > ---
> > > > base-commit: 0ea09cbf8350b70ad44d67a1dcb379008a356034
> > > > change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a
> > > > 
> > > > Best regards,
> > > > -- 
> > > > Lorenzo Bianconi <lorenzo at kernel.org>
> > > > 
> > > > 
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/65f5a360/attachment.sig>

From wens at kernel.org  Wed Mar 12 09:34:26 2025
From: wens at kernel.org (Chen-Yu Tsai)
Date: Thu, 13 Mar 2025 00:34:26 +0800
Subject: [PATCH RESEND net-next v2] net: stmmac: dwmac-rk: Provide FIFO sizes for DWMAC 1000
Message-ID: <20250312163426.2178314-1-wens@kernel.org>

From: Chen-Yu Tsai <wens at csie.org>

The DWMAC 1000 DMA capabilities register does not provide actual
FIFO sizes, nor does the driver really care. If they are not
provided via some other means, the driver will work fine, only
disallowing changing the MTU setting.

Provide the FIFO sizes through the driver's platform data to enable
MTU changes. The FIFO sizes are confirmed to be the same across RK3288,
RK3328, RK3399 and PX30, based on their respective manuals. It is
likely that Rockchip synthesized their DWMAC 1000 with the same
parameters on all their chips that have it.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
Resent with correct subject tag.

Changes since v1:
- Removed references to breakage from commit message as it is already fixed
- Removed Cc stable and Fixes tags
- Rebased onto latest -next
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 003fa5cf42c3..e57181ce5f84 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1969,8 +1969,11 @@ static int rk_gmac_probe(struct platform_device *pdev)
 	/* If the stmmac is not already selected as gmac4,
 	 * then make sure we fallback to gmac.
 	 */
-	if (!plat_dat->has_gmac4)
+	if (!plat_dat->has_gmac4) {
 		plat_dat->has_gmac = true;
+		plat_dat->rx_fifo_size = 4096;
+		plat_dat->tx_fifo_size = 2048;
+	}
 
 	plat_dat->set_clk_tx_rate = rk_set_clk_tx_rate;
 
-- 
2.39.5



From liujianfeng1994 at gmail.com  Wed Mar 12 09:40:49 2025
From: liujianfeng1994 at gmail.com (Jianfeng Liu)
Date: Thu, 13 Mar 2025 00:40:49 +0800
Subject: [PATCH] arm64: dts: rockchip: Enable HDMI audio output for ArmSoM Sige7
Message-ID: <20250312164056.3998224-1-liujianfeng1994@gmail.com>

HDMI audio is available on the ArmSoM Sige7 HDMI TX port.
Enable it for HDMI0 port.

Signed-off-by: Jianfeng Liu <liujianfeng1994 at gmail.com>
---

 arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 6a0fffaa26ee..0ef8ea76b0a8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -192,6 +192,10 @@ hdmi0_out_con: endpoint {
 	};
 };
 
+&hdmi0_sound {
+	status = "okay";
+};
+
 &hdptxphy0 {
 	status = "okay";
 };
@@ -290,6 +294,10 @@ i2s0_8ch_p0_0: endpoint {
 	};
 };
 
+&i2s5_8ch {
+	status = "okay";
+};
+
 /* phy1 - right ethernet port */
 &pcie2x1l0 {
 	reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
-- 
2.43.0



From will at kernel.org  Wed Mar 12 09:47:36 2025
From: will at kernel.org (Will Deacon)
Date: Wed, 12 Mar 2025 16:47:36 +0000
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck>
 <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck>
 <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
Message-ID: <20250312164735.GA6561@willie-the-truck>

On Wed, Mar 12, 2025 at 07:59:52AM -0700, Rob Clark wrote:
> On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
> > On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> > > On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> > > > On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> > > > >                                     struct arm_smmu_context_fault_info *cfi)
> > > > >  {
> > > > >       cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > > > > +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> > > > >       cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > > > > -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > > +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > > +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> > > >
> > > > We already have an implementation hook (->get_fault_info()) which the
> > > > qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> > > > That thing dumps these registers already so if we're moving that into
> > > > the core SMMU driver, let's get rid of the hook and move everybody over
> > > > rather than having it done in both places.
> > >
> > > As you probably saw, the next commit moves over
> > > qcom_adreno_smmu_get_fault_info() to use this. The current back door
> > > used by drm/msm to access these functions is specific to adreno_smmu
> > > and there isn't an equivalent interface to allow it to call a generic
> > > SMMU function so it isn't possible to move it entirely to the core. At
> > > least not without a bigger refactoring that isn't justified for this
> > > series that is just trying to fix things.
> >
> > Ok :(
> >
> > > > >       cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > > > > +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> > > >
> > > > I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> > > > it for stage-2 domains.
> > > >
> > > Does it matter if we read the register though, as long as users are
> > > aware of this and don't use its value for anything?
> >
> > I think the contents are "UNKNOWN", so it could be hugely confusing even
> > if they just got logged someplace. Why is it difficult to avoid touching
> > it for stage-2?
> >
> Fwiw, we are only ever using stage-1

Sure, but this is in arm-smmu.c which is used by other people and supports
both stages.

Will


From jernej.skrabec at gmail.com  Wed Mar 12 09:56:34 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Wed, 12 Mar 2025 17:56:34 +0100
Subject: [PATCH v4 4/8] pinctrl: sunxi: support moved power configuration
 registers
In-Reply-To: <20250306235827.4895-5-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
 <20250306235827.4895-5-andre.przywara@arm.com>
Message-ID: <5869984.DvuYhMxLoT@jernej-laptop>

Dne petek, 7. marec 2025 ob 00:58:23 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> The Allwinner pincontroller IP features some registers to control the
> withstand voltage of each pin group. So far those registers were always
> located at the same offset, but the A523 SoC has moved them (probably to
> accommodate all eleven pin banks).
> 
> Add a flag to note this feature, and use that to program the registers
> either at offset 0x340 or 0x380. So far no pincontroller driver uses
> this flag, but we need it for the upcoming A523 support.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From horms at kernel.org  Wed Mar 12 10:05:45 2025
From: horms at kernel.org (Simon Horman)
Date: Wed, 12 Mar 2025 18:05:45 +0100
Subject: [PATCH v2 2/3] net: stmmac: dwmac-rk: Validate GRF and
 peripheral GRF during probe
In-Reply-To: <20250308213720.2517944-3-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
 <20250308213720.2517944-3-jonas@kwiboo.se>
Message-ID: <20250312170545.GV4159220@kernel.org>

On Sat, Mar 08, 2025 at 09:37:14PM +0000, Jonas Karlman wrote:
> All Rockchip GMAC variants typically write to GRF regs to control e.g.
> interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
> RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
> located with help of a rockchip,grf and rockchip,php-grf phandle.
> 
> However, validating the rockchip,grf and rockchip,php-grf syscon regmap
> is deferred until e.g. interface mode or speed is configured, inside the
> individual SoC specific operations.
> 
> Change to validate the rockchip,grf and rockchip,php-grf syscon regmap
> at probe time to simplify all SoC specific operations.
> 
> This should not introduce any backward compatibility issues as all
> GMAC nodes have been added together with a rockchip,grf phandle (and
> rockchip,php-grf where required) in their initial commit.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Simon Horman <horms at kernel.org>


From horms at kernel.org  Wed Mar 12 10:06:21 2025
From: horms at kernel.org (Simon Horman)
Date: Wed, 12 Mar 2025 18:06:21 +0100
Subject: [PATCH v2 3/3] net: stmmac: dwmac-rk: Remove unneeded GRF and
 peripheral GRF checks
In-Reply-To: <20250308213720.2517944-4-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
 <20250308213720.2517944-4-jonas@kwiboo.se>
Message-ID: <20250312170621.GW4159220@kernel.org>

On Sat, Mar 08, 2025 at 09:37:15PM +0000, Jonas Karlman wrote:
> Now that GRF, and peripheral GRF where needed, is validated at probe
> time there is no longer any need to check and log an error in each SoC
> specific operation.
> 
> Remove unneeded IS_ERR() checks and early bail out from each SoC
> specific operation.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Simon Horman <horms at kernel.org>


From oliver.upton at linux.dev  Wed Mar 12 10:20:03 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 10:20:03 -0700
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
In-Reply-To: <20250306184013.30008-1-sebott@redhat.com>
References: <20250306184013.30008-1-sebott@redhat.com>
Message-ID: <Z9HCQ40LxShzL4nj@linux.dev>

Hi Sebastian,

On Thu, Mar 06, 2025 at 07:40:13PM +0100, Sebastian Ott wrote:
> Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
> Disallow to change these fields for NV since kvm provides a sanitized view
> for them based on the PAGE_SIZE.
> Also add these bits to the set_id_regs selftest.
> 
> Signed-off-by: Sebastian Ott <sebott at redhat.com>

I can't tell what you've based this patch on, it certainly doesn't apply
on a 6.14 rc. Consider telling git to include the base commit next time
you generate a patch.

> ---
>  arch/arm64/kvm/sys_regs.c                     | 21 +++++++++++++++----
>  .../testing/selftests/kvm/arm64/set_id_regs.c |  3 +++
>  2 files changed, 20 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 14faf213d483..0730ed8314d0 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1948,6 +1948,21 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
>  	return set_id_reg(vcpu, rd, user_val);
>  }
>  
> +static int set_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu,
> +				const struct sys_reg_desc *rd, u64 user_val)
> +{
> +	u64 sanitized_val = kvm_read_sanitised_id_reg(vcpu, rd);
> +	u64 tgran2_mask = ID_AA64MMFR0_EL1_TGRAN4_2_MASK |
> +			  ID_AA64MMFR0_EL1_TGRAN16_2_MASK |
> +			  ID_AA64MMFR0_EL1_TGRAN64_2_MASK;
> +
> +	if (vcpu_has_nv(vcpu) &&
> +	    ((sanitized_val & tgran2_mask) != (user_val & tgran2_mask)))
> +		return -EINVAL;
> +
> +	return set_id_reg(vcpu, rd, user_val);
> +}
> +
>  static int set_id_aa64mmfr2_el1(struct kvm_vcpu *vcpu,
>  				const struct sys_reg_desc *rd, u64 user_val)
>  {
> @@ -2787,10 +2802,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  	ID_UNALLOCATED(6,7),
>  
>  	/* CRm=7 */
> -	ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
> -					ID_AA64MMFR0_EL1_TGRAN4_2 |
> -					ID_AA64MMFR0_EL1_TGRAN64_2 |
> -					ID_AA64MMFR0_EL1_TGRAN16_2 |
> +	ID_FILTERED(ID_AA64MMFR0_EL1, id_aa64mmfr0_el1,
> +				      ~(ID_AA64MMFR0_EL1_RES0 |
>  					ID_AA64MMFR0_EL1_ASIDBITS)),
>  	ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
>  					ID_AA64MMFR1_EL1_HCX |
> diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> index 1d65f4a09e6f..322b9d3b0125 100644
> --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
> +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> @@ -146,6 +146,9 @@ static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] = {
>  static const struct reg_ftr_bits ftr_id_aa64mmfr0_el1[] = {
>  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, ECV, 0),
>  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, EXS, 0),
> +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN4_2, 1),
> +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN64_2, 1),
> +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN16_2, 1),
>  	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN4, 0),
>  	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN64, 0),
>  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN16, 0),

Please do selftests changes in a separate patch.

Don't worry about respinning, I'll fix this up and queue it in a moment.

Thanks,
Oliver


From robdclark at gmail.com  Wed Mar 12 10:23:36 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 12 Mar 2025 10:23:36 -0700
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250312164735.GA6561@willie-the-truck>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck> <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck> <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
 <20250312164735.GA6561@willie-the-truck>
Message-ID: <CAF6AEGskyoemQDrTXh=ewf61e-hVzWMjmqe=nX2J-65W5-M6Zw@mail.gmail.com>

On Wed, Mar 12, 2025 at 9:47?AM Will Deacon <will at kernel.org> wrote:
>
> On Wed, Mar 12, 2025 at 07:59:52AM -0700, Rob Clark wrote:
> > On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
> > > On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> > > > On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> > > > > On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > > > > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > > index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > > > > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > > > > > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> > > > > >                                     struct arm_smmu_context_fault_info *cfi)
> > > > > >  {
> > > > > >       cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > > > > > +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> > > > > >       cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > > > > > -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > > > +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > > > > > +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> > > > >
> > > > > We already have an implementation hook (->get_fault_info()) which the
> > > > > qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> > > > > That thing dumps these registers already so if we're moving that into
> > > > > the core SMMU driver, let's get rid of the hook and move everybody over
> > > > > rather than having it done in both places.
> > > >
> > > > As you probably saw, the next commit moves over
> > > > qcom_adreno_smmu_get_fault_info() to use this. The current back door
> > > > used by drm/msm to access these functions is specific to adreno_smmu
> > > > and there isn't an equivalent interface to allow it to call a generic
> > > > SMMU function so it isn't possible to move it entirely to the core. At
> > > > least not without a bigger refactoring that isn't justified for this
> > > > series that is just trying to fix things.
> > >
> > > Ok :(
> > >
> > > > > >       cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > > > > > +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> > > > >
> > > > > I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> > > > > it for stage-2 domains.
> > > > >
> > > > Does it matter if we read the register though, as long as users are
> > > > aware of this and don't use its value for anything?
> > >
> > > I think the contents are "UNKNOWN", so it could be hugely confusing even
> > > if they just got logged someplace. Why is it difficult to avoid touching
> > > it for stage-2?
> > >
> > Fwiw, we are only ever using stage-1
>
> Sure, but this is in arm-smmu.c which is used by other people and supports
> both stages.

Sure, but no one else is using this field in the fault-info.  So maybe
the addition of a comment in the struct would be enough if it isn't
going to cause an SError/etc to read it for S2 cb?

BR,
-R


From oliver.upton at linux.dev  Wed Mar 12 10:32:03 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 10:32:03 -0700
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
In-Reply-To: <Z9HCQ40LxShzL4nj@linux.dev>
References: <20250306184013.30008-1-sebott@redhat.com>
 <Z9HCQ40LxShzL4nj@linux.dev>
Message-ID: <Z9HE92ZlNlJbHJBB@linux.dev>

On Wed, Mar 12, 2025 at 10:20:03AM -0700, Oliver Upton wrote:
> Hi Sebastian,
> 
> On Thu, Mar 06, 2025 at 07:40:13PM +0100, Sebastian Ott wrote:
> > Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
> > Disallow to change these fields for NV since kvm provides a sanitized view
> > for them based on the PAGE_SIZE.
> > Also add these bits to the set_id_regs selftest.
> > 
> > Signed-off-by: Sebastian Ott <sebott at redhat.com>
> 
> I can't tell what you've based this patch on, it certainly doesn't apply
> on a 6.14 rc. Consider telling git to include the base commit next time
> you generate a patch.

/me finishes a cup of coffee

The conflict is obviously with 9d6745572899 ("KVM: arm64: Hide
ID_AA64MMFR2_EL1.NV from guest and userspace"), which is in
kvmarm/next...

> > ---
> >  arch/arm64/kvm/sys_regs.c                     | 21 +++++++++++++++----
> >  .../testing/selftests/kvm/arm64/set_id_regs.c |  3 +++
> >  2 files changed, 20 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 14faf213d483..0730ed8314d0 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> > @@ -1948,6 +1948,21 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
> >  	return set_id_reg(vcpu, rd, user_val);
> >  }
> >  
> > +static int set_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu,
> > +				const struct sys_reg_desc *rd, u64 user_val)
> > +{
> > +	u64 sanitized_val = kvm_read_sanitised_id_reg(vcpu, rd);
> > +	u64 tgran2_mask = ID_AA64MMFR0_EL1_TGRAN4_2_MASK |
> > +			  ID_AA64MMFR0_EL1_TGRAN16_2_MASK |
> > +			  ID_AA64MMFR0_EL1_TGRAN64_2_MASK;
> > +
> > +	if (vcpu_has_nv(vcpu) &&
> > +	    ((sanitized_val & tgran2_mask) != (user_val & tgran2_mask)))
> > +		return -EINVAL;
> > +
> > +	return set_id_reg(vcpu, rd, user_val);
> > +}
> > +
> >  static int set_id_aa64mmfr2_el1(struct kvm_vcpu *vcpu,
> >  				const struct sys_reg_desc *rd, u64 user_val)
> >  {
> > @@ -2787,10 +2802,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> >  	ID_UNALLOCATED(6,7),
> >  
> >  	/* CRm=7 */
> > -	ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
> > -					ID_AA64MMFR0_EL1_TGRAN4_2 |
> > -					ID_AA64MMFR0_EL1_TGRAN64_2 |
> > -					ID_AA64MMFR0_EL1_TGRAN16_2 |
> > +	ID_FILTERED(ID_AA64MMFR0_EL1, id_aa64mmfr0_el1,
> > +				      ~(ID_AA64MMFR0_EL1_RES0 |
> >  					ID_AA64MMFR0_EL1_ASIDBITS)),
> >  	ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
> >  					ID_AA64MMFR1_EL1_HCX |
> > diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> > index 1d65f4a09e6f..322b9d3b0125 100644
> > --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
> > +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> > @@ -146,6 +146,9 @@ static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] = {
> >  static const struct reg_ftr_bits ftr_id_aa64mmfr0_el1[] = {
> >  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, ECV, 0),
> >  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, EXS, 0),
> > +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN4_2, 1),
> > +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN64_2, 1),
> > +	REG_FTR_BITS(FTR_EXACT, ID_AA64MMFR0_EL1, TGRAN16_2, 1),
> >  	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN4, 0),
> >  	S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN64, 0),
> >  	REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, TGRAN16, 0),
> 
> Please do selftests changes in a separate patch.
> 
> Don't worry about respinning, I'll fix this up and queue it in a moment.
> 
> Thanks,
> Oliver
> 


From sebott at redhat.com  Wed Mar 12 10:33:09 2025
From: sebott at redhat.com (Sebastian Ott)
Date: Wed, 12 Mar 2025 18:33:09 +0100 (CET)
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
In-Reply-To: <Z9HCQ40LxShzL4nj@linux.dev>
References: <20250306184013.30008-1-sebott@redhat.com> <Z9HCQ40LxShzL4nj@linux.dev>
Message-ID: <eb045be7-69ca-fe71-0333-086b71bb624f@redhat.com>

Hi Oliver,

On Wed, 12 Mar 2025, Oliver Upton wrote:
> Hi Sebastian,
>
> On Thu, Mar 06, 2025 at 07:40:13PM +0100, Sebastian Ott wrote:
>> Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
>> Disallow to change these fields for NV since kvm provides a sanitized view
>> for them based on the PAGE_SIZE.
>> Also add these bits to the set_id_regs selftest.
>>
>> Signed-off-by: Sebastian Ott <sebott at redhat.com>
>
> I can't tell what you've based this patch on, it certainly doesn't apply
> on a 6.14 rc. Consider telling git to include the base commit next time
> you generate a patch.

Ok, I'll keep it in mind for next time.
(It was kvm-arm64/next + 2 pkvm series from the list that I applied
manually.)

> Please do selftests changes in a separate patch.
>
> Don't worry about respinning, I'll fix this up and queue it in a moment.

Thanks!
Sebastian



From claudiu.beznea at tuxon.dev  Wed Mar 12 10:37:54 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Wed, 12 Mar 2025 19:37:54 +0200
Subject: [GIT PULL] Microchip AT91 DT updates for v6.15
Message-ID: <20250312173755.975074-1-claudiu.beznea@tuxon.dev>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git tags/at91-dt-6.15

for you to fetch changes up to 6aafec3d215f59e8c4b00d0c2a97988ed5edbb2a:

  ARM: dts: microchip: sama7g5: add ADC hw trigger edge type (2025-03-04 20:39:29 +0200)

----------------------------------------------------------------
Microchip AT91 device tree updates for v6.15

This update includes:
- more controllers enabled for SAMA7D65 SoC (DMA, reset controller,
  shutdown controller, RTC, watchdog)
- power monitor device enabled for SAMA7D65 Curiosity board
- device tree cleanups

----------------------------------------------------------------
Mihai Sain (2):
      ARM: dts: microchip: sama7d65: Add flexcom 10 node
      ARM: dts: microchip: sama7d65_curiosity: Add power monitor support

Nayab Sayed (1):
      ARM: dts: microchip: sama7g5: add ADC hw trigger edge type

Ryan Wanner (9):
      ARM: dts: microchip: sama7d65: Add chipID for sama7d65
      ARM: dts: microchip: sama7d65: Add DMAs to sama7d65 SoC
      ARM: dts: microchip: sama7d65: Enable DMAs
      ARM: dts: microchip: sama7d65: Add Reset Controller to sama7d65 SoC
      ARM: dts: microchip: sama7d65: Add Shutdown controller support
      ARM: dts: microchip: sama7d65: Add RTC support for sama7d65
      ARM: dts: microchip: sama7d65: Add SFRBU support to sama7d65
      ARM: dts: microchip: sama7d65: Enable shutdown controller
      ARM: dts: microchip: sama7d65: Add watchdog for sama7d65

Wolfram Sang (7):
      ARM: dts: at91: calao_usb: fix wrong polarity for LED
      ARM: dts: at91: calao_usb: remove heartbeat for User LEDs
      ARM: dts: at91: use correct vendor name for Calao boards
      ARM: dts: at91: calao_usb: fix button nodes
      ARM: dts: at91: usb_a9g20_lpw: use proper mmc node name
      ARM: dts: microchip: usb_a9263: fix wrong vendor
      ARM: dts: microchip: fix faulty ohci/ehci node names

 arch/arm/boot/dts/microchip/aks-cdu.dts            |  2 +-
 arch/arm/boot/dts/microchip/animeo_ip.dts          |  2 +-
 arch/arm/boot/dts/microchip/at91-foxg20.dts        |  2 +-
 arch/arm/boot/dts/microchip/at91-qil_a9260.dts     |  2 +-
 arch/arm/boot/dts/microchip/at91-sam9_l9260.dts    |  2 +-
 .../boot/dts/microchip/at91-sama5d27_som1_ek.dts   |  4 +-
 .../arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts |  4 +-
 .../boot/dts/microchip/at91-sama5d2_xplained.dts   |  4 +-
 .../boot/dts/microchip/at91-sama5d3_xplained.dts   |  4 +-
 .../boot/dts/microchip/at91-sama5d4_ma5d4evk.dts   |  4 +-
 .../boot/dts/microchip/at91-sama5d4_xplained.dts   |  4 +-
 arch/arm/boot/dts/microchip/at91-sama5d4ek.dts     |  4 +-
 .../boot/dts/microchip/at91-sama7d65_curiosity.dts | 73 +++++++++++++++++
 arch/arm/boot/dts/microchip/at91-sama7g5ek.dts     |  1 +
 arch/arm/boot/dts/microchip/at91-vinco.dts         |  4 +-
 arch/arm/boot/dts/microchip/at91rm9200.dtsi        |  2 +-
 arch/arm/boot/dts/microchip/at91rm9200ek.dts       |  2 +-
 arch/arm/boot/dts/microchip/at91sam9260.dtsi       |  2 +-
 arch/arm/boot/dts/microchip/at91sam9260ek.dts      |  2 +-
 arch/arm/boot/dts/microchip/at91sam9261.dtsi       |  2 +-
 arch/arm/boot/dts/microchip/at91sam9261ek.dts      |  2 +-
 arch/arm/boot/dts/microchip/at91sam9263.dtsi       |  2 +-
 arch/arm/boot/dts/microchip/at91sam9263ek.dts      |  2 +-
 .../boot/dts/microchip/at91sam9g20ek_common.dtsi   |  2 +-
 arch/arm/boot/dts/microchip/at91sam9g45.dtsi       |  4 +-
 arch/arm/boot/dts/microchip/at91sam9m10g45ek.dts   |  4 +-
 arch/arm/boot/dts/microchip/at91sam9n12.dtsi       |  2 +-
 arch/arm/boot/dts/microchip/at91sam9n12ek.dts      |  2 +-
 arch/arm/boot/dts/microchip/at91sam9x5.dtsi        |  4 +-
 arch/arm/boot/dts/microchip/ethernut5.dts          |  2 +-
 arch/arm/boot/dts/microchip/evk-pro3.dts           |  2 +-
 arch/arm/boot/dts/microchip/mpa1600.dts            |  2 +-
 arch/arm/boot/dts/microchip/pm9g45.dts             |  4 +-
 arch/arm/boot/dts/microchip/sam9x60.dtsi           |  4 +-
 arch/arm/boot/dts/microchip/sama5d2.dtsi           |  4 +-
 arch/arm/boot/dts/microchip/sama5d3.dtsi           |  4 +-
 arch/arm/boot/dts/microchip/sama5d3xmb.dtsi        |  4 +-
 arch/arm/boot/dts/microchip/sama5d4.dtsi           |  4 +-
 arch/arm/boot/dts/microchip/sama7d65.dtsi          | 95 ++++++++++++++++++++++
 arch/arm/boot/dts/microchip/tny_a9260.dts          |  2 +-
 arch/arm/boot/dts/microchip/tny_a9260_common.dtsi  |  2 +-
 arch/arm/boot/dts/microchip/tny_a9263.dts          |  2 +-
 arch/arm/boot/dts/microchip/tny_a9g20.dts          |  2 +-
 arch/arm/boot/dts/microchip/usb_a9260.dts          |  2 +-
 arch/arm/boot/dts/microchip/usb_a9260_common.dtsi  | 11 +--
 arch/arm/boot/dts/microchip/usb_a9263.dts          | 11 +--
 arch/arm/boot/dts/microchip/usb_a9g20-dab-mmx.dtsi | 10 +--
 arch/arm/boot/dts/microchip/usb_a9g20.dts          |  2 +-
 arch/arm/boot/dts/microchip/usb_a9g20_common.dtsi  |  2 +-
 arch/arm/boot/dts/microchip/usb_a9g20_lpw.dts      |  4 +-
 50 files changed, 243 insertions(+), 82 deletions(-)


From claudiu.beznea at tuxon.dev  Wed Mar 12 10:37:55 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Wed, 12 Mar 2025 19:37:55 +0200
Subject: [GIT PULL] Microchip AT91 SoC updates for v6.15
In-Reply-To: <20250312173755.975074-1-claudiu.beznea@tuxon.dev>
References: <20250312173755.975074-1-claudiu.beznea@tuxon.dev>
Message-ID: <20250312173755.975074-2-claudiu.beznea@tuxon.dev>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git tags/at91-soc-6.15

for you to fetch changes up to 8bd10f002411c9ea947edc0af18ad81f789e28d5:

  ARM: at91: pm: Enable ULP0/ULP1 for SAMA7D65 (2025-03-02 17:38:54 +0200)

----------------------------------------------------------------
Microchip AT91 SoC updates for v6.15

This update includes:
- SoC driver support for Microchip SAMA7D65
- power management support for Microchip SAMA7D65
- power management fixes
- documentation fixes

----------------------------------------------------------------
Li Bin (1):
      ARM: at91: pm: fix at91_suspend_finish for ZQ calibration

Ryan Wanner (5):
      dt-bindings: atmel-sysreg: Add SAMA7D65 Chip ID
      ARM: at91: Add Support in SoC driver for SAMA7D65
      ARM: at91: pm: add DT compatible support for sama7d65
      ARM: at91: pm: Add Backup mode for SAMA7D65
      ARM: at91: pm: Enable ULP0/ULP1 for SAMA7D65

Wolfram Sang (2):
      dt-bindings: ARM: at91: make separate entry for Olimex board
      dt-bindings: ARM: at91: add Calao USB boards

 .../devicetree/bindings/arm/atmel-at91.yaml        |  33 ++++++-
 .../devicetree/bindings/arm/atmel-sysregs.txt      |   1 +
 arch/arm/mach-at91/pm.c                            |  47 +++++++---
 arch/arm/mach-at91/pm.h                            |   1 +
 arch/arm/mach-at91/pm_data-offsets.c               |   2 +
 arch/arm/mach-at91/pm_suspend.S                    | 101 +++++++++++++++++++--
 drivers/soc/atmel/soc.c                            |   5 +
 drivers/soc/atmel/soc.h                            |   3 +
 8 files changed, 168 insertions(+), 25 deletions(-)


From ariel.dalessandro at collabora.com  Wed Mar 12 10:49:03 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Wed, 12 Mar 2025 14:49:03 -0300
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250311090545.3b941567@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
 <20250311090545.3b941567@collabora.com>
Message-ID: <6bc2abd2-4d1d-4b94-b2f3-6d3638f3e8ba@collabora.com>

Boris,

On 3/11/25 5:05 AM, Boris Brezillon wrote:
> On Mon, 10 Mar 2025 16:59:19 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>> Address Extension", which in Linux we've called "mali_lpae".
>>
>> This commit adds support for conditionally enabling AARCH64_4K page
>> table format. To achieve that, a "GPU optional configurations" field was
>> added to `struct panfrost_features` with the related flag.
>>
>> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
>> the HW_FEATURE_AARCH64_MMU feature flag present.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> ---
>>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
>>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>>   3 files changed, 169 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
>> index cffcb0ac7c111..0385702aa43c7 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
>> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
>> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>>   	GPU_PM_VREG_OFF,
>>   };
>>   
>> +/**
>> + * enum panfrost_gpu_config - GPU optional configurations
>> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
>> + */
>> +enum panfrost_gpu_config {
>> +	GPU_CONFIG_AARCH64_4K,
>> +};
>> +
>>   struct panfrost_features {
>>   	u16 id;
>>   	u16 revision;
>> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>>   
>>   	/* Allowed PM features */
>>   	u8 pm_features;
>> +
>> +	/* GPU features */
>> +	u8 gpu_configs;
> 
> I would probably name this gpu_quirks, with the GPU_CONFIG_AARCH64_4K
> flag renamed GPU_QUIRK_FORCE_AARCH64_PAGE_TABLE.

Will follow on this thread after latest responses.

>>   };
>>   
>>   struct panfrost_device {
>> @@ -162,6 +173,11 @@ struct panfrost_mmu {
>>   	int as;
>>   	atomic_t as_count;
>>   	struct list_head list;
>> +	struct {
>> +		u64 transtab;
>> +		u64 memattr;
>> +		u64 transcfg;
>> +	} cfg;
>>   };
>>   
>>   struct panfrost_engine_usage {
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> index 31df3a96f89bd..4a9b8de2ff987 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> @@ -26,6 +26,48 @@

[snip]

>> +static void mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
>> +{
>> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
>> +
>> +	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
>> +				AS_TRANSTAB_AARCH64_4K_ADDR_MASK;
> 
> Silently masking the low 4bits is not the solution, it's just papering
> over a real issue. If pgtbl_cfg->arm_lpae_s1_cfg.ttbr is not aligned on
> 16 bytes (PAGE_SIZE even) we have a problem, so I would drm_WARN_ON()
> here, and return an error so we can fail the probe.

Good point. I'll add something like this in v2:

         if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
                                      ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
                 return -EINVAL;

>> +
>> +	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
>> +					   pgtbl_cfg->coherent_walk);
>> +
>> +	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
>> +			    AS_TRANSCFG_PTW_RA |
>> +			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
>> +			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
>> +	if (pgtbl_cfg->coherent_walk)
>> +		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
>> +}

[snip]

>> @@ -616,6 +709,7 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>>   {
>>   	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>>   	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
>> +	enum io_pgtable_fmt fmt = ARM_MALI_LPAE;
>>   	struct panfrost_mmu *mmu;
>>   
>>   	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>> @@ -641,16 +735,28 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>>   		.iommu_dev	= pfdev->dev,
>>   	};
>>   
>> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
>> -					      mmu);
>> -	if (!mmu->pgtbl_ops) {
>> -		kfree(mmu);
>> -		return ERR_PTR(-EINVAL);
>> +	if (pfdev->comp->gpu_configs & BIT(GPU_CONFIG_AARCH64_4K)) {
>> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
>> +			dev_err_once(pfdev->dev,
>> +				     "AARCH64_4K page table not supported\n");
>> +			goto err_free_mmu;
>> +		}
>> +		fmt = ARM_64_LPAE_S1;
>>   	}
> 
> How about moving this check before allocating the mmu object, so you
> don't have to free it if it fails?

Yes, will fix in v2.

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From florian.fainelli at broadcom.com  Wed Mar 12 10:51:27 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Wed, 12 Mar 2025 10:51:27 -0700
Subject: [PATCH RFC 0/3] mmc: sdhci-brcmstb: Add rpmb sharing support
In-Reply-To: <CAPDyKFrCjo8gGnxmXWP6V39N+b1o62VQH9zwMUNb2_+D3-qrdw@mail.gmail.com>
References: <20250206220940.10553-1-kamal.dasu@broadcom.com>
 <CAPDyKFq1ZbP4c9ECfM1SY+MEopf+dC19w9PkqXaUjevf=bPjcw@mail.gmail.com>
 <115a59e1-75b2-4d09-bbf9-50dfcd2b62dd@broadcom.com>
 <PH7PR16MB61967C18645C64E582B222B6E5FD2@PH7PR16MB6196.namprd16.prod.outlook.com>
 <d51a9d7a-b942-4c3b-93d2-65b1bb04c8da@broadcom.com>
 <CAPDyKFrCjo8gGnxmXWP6V39N+b1o62VQH9zwMUNb2_+D3-qrdw@mail.gmail.com>
Message-ID: <6328fe8d-c4ea-4945-b6ba-d994403121b5@broadcom.com>

On 3/12/25 06:17, Ulf Hansson wrote:
> On Tue, 11 Feb 2025 at 18:01, Florian Fainelli
> <florian.fainelli at broadcom.com> wrote:
>>
>> On 2/11/25 00:13, Avri Altman wrote:
>>>>>> This patch set adds support for Broadcom TZOS to read and write to
>>>>>> RPMB partition using synchronized access to the controller hardware.
>>> Practically it establishes a communication channel between the trust zone and the host controller regardless of the rpmb protocol.
>>> Or did I get it wrong?
>>
>> Rather than communication channel, I would describe it as an arbitration
>> scheme between N participants, with guaranteed forward progress and
>> fairness between all participants.
> 
> A scheduler in the MMC controller HW?

There is no scheduler in the eMMC controller HW, all of the scheduling 
and coordination is left to the OS and TZOS, and other participants.

> 
> Nevertheless, it means bypassing the I/O scheduler in Linux and the
> mmc block layer, kind of breaking "fairness" from Linux point of view.

Yes that is a given, our approach favors the TZOS that has the ability 
to preempt for short periods of time the eMMC controller issue a RPMB 
access and then return control of the eMMC controller back to Linux. The 
very reason we came up with that scheme is that we are not comfortable 
with having a Linux task responsible for issuing RPMB accesses to the 
eMMC device on behalf of the TEE. That task is subject to the same Linux 
scheduling rules as any other task (yes we can play with priorities and 
classes) and our TEE team was not comfortable with that, they prefer 
hard guarantees that their RPMB accesses can complete within a certain 
time, which this scheme provides.

> 
>>
>> The interest here is for one of those participants to own the eMMC
>> controller for a certain amount of time and indicate when it is done
>> with it. This is not specific to eMMC as this could scale to virtually
>> any piece of HW that is driven by transactions from a CPU, but the main
>> application is for allowing the Trusted OS to own the eMMC controller
>> for a short period of time in order to do its RPMB access, and then give
>> it back in the same state it found it to the next participant.
> 
> Honestly, I think this is a really terrible idea, sorry.
 > > Data and communication with an eMMC needs to be synchronized and
> managed by a single owner. Having multiple clients with their own
> channel to the eMMC sounds prone to problems. Is each client going to
> have its own mmc protocol stack, dealing with eMMC initialization,
> data-synchronization and power-management, etc?

The synchronization is done around the start/end of transactions and yes 
each participant does have a minimal amount of eMMC driver knowledge, 
but is confined to doing RPMB accesses only. The contract is to put the 
eMMC controller back into the state where you found it for the next 
participant to make use of it.

When we operate with a single participant such as Linux, which is a 
degraded mode there is no loss of performance nor any observable difference.

> 
> As I said, we now have the RPMB subsystem for in-kernel access. Please
> use it instead.

That scheme works when all of the participants run on the same CPU, that 
is not our case, as we have another participant that is a separate CPU 
which you cannot factor into Linux's RPMB subsystem.

We considered doing a mediated/proxied eMMC access through a firmware 
interface running on a CPU that would exclusively own the hardware, but 
we really did not like losing access to mmc-utils and other things.
-- 
Florian


From acme at kernel.org  Wed Mar 12 10:57:22 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Wed, 12 Mar 2025 14:57:22 -0300
Subject: [PATCH v5 06/11] perf dso: Add support for reading the e_machine
 type for a dso
In-Reply-To: <20250308003209.234114-7-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
 <20250308003209.234114-7-irogers@google.com>
Message-ID: <Z9HLArg6uGiK8FzM@x1>

On Fri, Mar 07, 2025 at 04:32:04PM -0800, Ian Rogers wrote:
> For ELF file dsos read the e_machine from the ELF header. For kernel
> types assume the e_machine matches the perf tool. In other cases
> return EM_NONE.
> 
> When reading from the ELF header use DSO__SWAP that may need
> dso->needs_swap initializing. Factor out dso__swap_init to allow this.
> 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/util/dso.c        | 88 ++++++++++++++++++++++++++++++++++++
>  tools/perf/util/dso.h        |  3 ++
>  tools/perf/util/symbol-elf.c | 27 -----------
>  3 files changed, 91 insertions(+), 27 deletions(-)

This one, due to this having already been merged:

commit b10f74308e1305275e69ddde711ec817cc69e306 (perf-tools-next/perf-tools-next)
Author: Stephen Brennan <stephen.s.brennan at oracle.com>
Date:   Fri Mar 7 15:22:03 2025 -0800

    perf symbol: Support .gnu_debugdata for symbols

Needs this so that we read the e_machine from the ELF file:

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 8188ba4d432cd5ac..8d2d8bb22e077bea 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1203,6 +1203,7 @@ uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
 	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
 	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
 	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+	case DSO_BINARY_TYPE__GNU_DEBUGDATA:
 		break;
 	case DSO_BINARY_TYPE__NOT_FOUND:
 	default:
 
---

Continuing the review and test.

- Arnaldo

> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 5c6e85fdae0d..00fec1bc32bc 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1170,6 +1170,67 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
>  	return data_read_write_offset(dso, machine, offset, data, size, true);
>  }
>  
> +uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
> +{
> +	uint16_t e_machine = EM_NONE;
> +	int fd;
> +
> +	switch (dso__binary_type(dso)) {
> +	case DSO_BINARY_TYPE__KALLSYMS:
> +	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> +	case DSO_BINARY_TYPE__VMLINUX:
> +	case DSO_BINARY_TYPE__GUEST_VMLINUX:
> +	case DSO_BINARY_TYPE__GUEST_KMODULE:
> +	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
> +	case DSO_BINARY_TYPE__KCORE:
> +	case DSO_BINARY_TYPE__GUEST_KCORE:
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> +	case DSO_BINARY_TYPE__BPF_IMAGE:
> +	case DSO_BINARY_TYPE__OOL:
> +	case DSO_BINARY_TYPE__JAVA_JIT:
> +		return EM_HOST;
> +	case DSO_BINARY_TYPE__DEBUGLINK:
> +	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
> +	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> +	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
> +	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
> +	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
> +	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
> +	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
> +	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
> +		break;
> +	case DSO_BINARY_TYPE__NOT_FOUND:
> +	default:
> +		return EM_NONE;
> +	}
> +
> +	pthread_mutex_lock(&dso__data_open_lock);
> +
> +	/*
> +	 * dso__data(dso)->fd might be closed if other thread opened another
> +	 * file (dso) due to open file limit (RLIMIT_NOFILE).
> +	 */
> +	try_to_open_dso(dso, machine);
> +	fd = dso__data(dso)->fd;
> +	if (fd >= 0) {
> +		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
> +		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
> +		if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
> +			unsigned char eidata;
> +
> +			if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
> +				dso__swap_init(dso, eidata);
> +		}
> +		if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
> +		    pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
> +			e_machine = DSO__SWAP(dso, uint16_t, e_machine);
> +	}
> +	pthread_mutex_unlock(&dso__data_open_lock);
> +	return e_machine;
> +}
> +
>  /**
>   * dso__data_read_addr - Read data from dso address
>   * @dso: dso object
> @@ -1525,6 +1586,33 @@ void dso__put(struct dso *dso)
>  		RC_CHK_PUT(dso);
>  }
>  
> +int dso__swap_init(struct dso *dso, unsigned char eidata)
> +{
> +	static unsigned int const endian = 1;
> +
> +	dso__set_needs_swap(dso, DSO_SWAP__NO);
> +
> +	switch (eidata) {
> +	case ELFDATA2LSB:
> +		/* We are big endian, DSO is little endian. */
> +		if (*(unsigned char const *)&endian != 1)
> +			dso__set_needs_swap(dso, DSO_SWAP__YES);
> +		break;
> +
> +	case ELFDATA2MSB:
> +		/* We are little endian, DSO is big endian. */
> +		if (*(unsigned char const *)&endian != 0)
> +			dso__set_needs_swap(dso, DSO_SWAP__YES);
> +		break;
> +
> +	default:
> +		pr_err("unrecognized DSO data encoding %d\n", eidata);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  void dso__set_build_id(struct dso *dso, struct build_id *bid)
>  {
>  	RC_CHK_ACCESS(dso)->bid = *bid;
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index 4aa8c3d36566..38d9e3eac501 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -730,6 +730,8 @@ bool dso__sorted_by_name(const struct dso *dso);
>  void dso__set_sorted_by_name(struct dso *dso);
>  void dso__sort_by_name(struct dso *dso);
>  
> +int dso__swap_init(struct dso *dso, unsigned char eidata);
> +
>  void dso__set_build_id(struct dso *dso, struct build_id *bid);
>  bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
>  void dso__read_running_kernel_build_id(struct dso *dso,
> @@ -818,6 +820,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
>  off_t dso__data_size(struct dso *dso, struct machine *machine);
>  ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
>  			      u64 offset, u8 *data, ssize_t size);
> +uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
>  ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
>  			    struct machine *machine, u64 addr,
>  			    u8 *data, ssize_t size);
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 66fd1249660a..71df13a5722a 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -1173,33 +1173,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
>  
>  #endif
>  
> -static int dso__swap_init(struct dso *dso, unsigned char eidata)
> -{
> -	static unsigned int const endian = 1;
> -
> -	dso__set_needs_swap(dso, DSO_SWAP__NO);
> -
> -	switch (eidata) {
> -	case ELFDATA2LSB:
> -		/* We are big endian, DSO is little endian. */
> -		if (*(unsigned char const *)&endian != 1)
> -			dso__set_needs_swap(dso, DSO_SWAP__YES);
> -		break;
> -
> -	case ELFDATA2MSB:
> -		/* We are little endian, DSO is big endian. */
> -		if (*(unsigned char const *)&endian != 0)
> -			dso__set_needs_swap(dso, DSO_SWAP__YES);
> -		break;
> -
> -	default:
> -		pr_err("unrecognized DSO data encoding %d\n", eidata);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  bool symsrc__possibly_runtime(struct symsrc *ss)
>  {
>  	return ss->dynsym || ss->opdsec;
> -- 
> 2.49.0.rc0.332.g42c0ae87b1-goog
> 


From vz at mleia.com  Wed Mar 12 10:59:21 2025
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Wed, 12 Mar 2025 19:59:21 +0200
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <20250312122750.6391-1-purvayeshi550@gmail.com>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
Message-ID: <57ae63a2-544b-4241-a54d-8fa9917c1e44@mleia.com>

Hello Purva.

Thank you for your contribution.

On 3/12/25 14:27, Purva Yeshi wrote:
> Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
> YAML schema (`nxp,lpc3220-pwm.yaml`).
> 
> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.

Actually it shall be set to 1.

> 
> Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
> ---
> V1 - https://lore.kernel.org/all/20250311125756.24064-1-purvayeshi550 at gmail.com/
> V2 - Correct filename to match the compatible string, remove unnecessary
> quotes in maintainers, and refine commit message.
> 
>   .../devicetree/bindings/pwm/lpc32xx-pwm.txt   | 17 ---------
>   .../bindings/pwm/nxp,lpc3220-pwm.yaml         | 38 +++++++++++++++++++
>   2 files changed, 38 insertions(+), 17 deletions(-)
>   delete mode 100644 Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
>   create mode 100644 Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
> deleted file mode 100644
> index 74b5bc5dd..000000000
> --- a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -LPC32XX PWM controller
> -
> -Required properties:
> -- compatible: should be "nxp,lpc3220-pwm"
> -- reg: physical base address and length of the controller's registers
> -
> -Examples:
> -
> -pwm at 4005c000 {
> -	compatible = "nxp,lpc3220-pwm";
> -	reg = <0x4005c000 0x4>;
> -};
> -
> -pwm at 4005c004 {
> -	compatible = "nxp,lpc3220-pwm";
> -	reg = <0x4005c004 0x4>;
> -};
> diff --git a/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml b/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml
> new file mode 100644
> index 000000000..432a5e9d4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/nxp,lpc3220-pwm.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pwm/nxp,lpc3220-pwm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: LPC32XX PWM controller
> +
> +maintainers:
> +  - Vladimir Zapolskiy <vz at mleia.com>
> +  - Piotr Wojtaszczyk <piotr.wojtaszczyk at timesys.com>
> +
> +allOf:
> +  - $ref: pwm.yaml#
> +
> +properties:
> +  compatible:
> +    const: nxp,lpc3220-pwm
> +
> +  reg:
> +    maxItems: 1
> +
> +  "#pwm-cells":
> +    const: 3

It shall be 1.

> +
> +required:
> +  - compatible
> +  - reg
> +

There is an error in the original lpc32xx-pwm.txt file, one more property
"clocks" is strictly required, please add it along with the conversion.

Thank you!

> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    pwm at 4005c000 {
> +        compatible = "nxp,lpc3220-pwm";
> +        reg = <0x4005c000 0x4>;
> +        #pwm-cells = <3>;
> +    };

--
Best wishes,
Vladimir


From paulmck at kernel.org  Wed Mar 12 11:00:48 2025
From: paulmck at kernel.org (Paul E. McKenney)
Date: Wed, 12 Mar 2025 11:00:48 -0700
Subject: [GIT PULL] Generic entry for ARM
In-Reply-To: <CACRpkdZCiiMTwf7eGJJ9aCKFOC3_xTGv1JKQUijjyp+_++cZ_A@mail.gmail.com>
References: <CACRpkdZCiiMTwf7eGJJ9aCKFOC3_xTGv1JKQUijjyp+_++cZ_A@mail.gmail.com>
Message-ID: <1277cefd-b080-42a5-bfe5-57296e7ccc3e@paulmck-laptop>

On Fri, Feb 28, 2025 at 01:49:36PM +0100, Linus Walleij wrote:
> Hi Russell,
> 
> please consider pulling the following git branch for generic entry,
> see below.
> 
> This branch was just harvested from my own v5 patch series on
> lore with b4 am -t 20250225-arm-generic-entry-v5-0-2f02313653e5 at linaro.org
> then git am on top of v6.14-rc1, so you can do the same if you
> prefer.
> 
> It's possible to squash patches, even all of them into one
> big all-or-nothing patch, given the not very gradual nature generic
> entry conversion seems to have.
> 
> Main upsides and downsides are in the signed tag.
> 
> I don't know who the most important stakeholders are, but I guess
> the context tracker maintainer (Paul McKenney) and the people working
> on generic entry (tglx) could have a say on how important this is, or isn't.
> 
> I think it's pretty neat.

No argument here!

Once you are confident that you have all the needed "noinstr"
and "__always_inline" instances in place, could you please add
ARCH_WANTS_NO_INSTR to the list of "select" clauses for "config ARM"
in arch/arm/Kconfig?

Once all architectures that support trampoline-based tracing also select
ARCH_WANTS_NO_INSTR we can drop RCU Tasks Rude.  ;-)

In the meantime, for the series:

Acked-by: Paul E. McKenney <paulmck at kernel.org>

							Thanx, Paul

> Yours,
> Linus Walleij
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git
> tags/arm-generic-entry-for-v6.15
> 
> for you to fetch changes up to 98b8e133458a3feefdf882ea16fb7f1f576a49e5:
> 
>   ARM: entry: Reimplement local restart in C (2025-02-28 13:40:44 +0100)
> 
> ----------------------------------------------------------------
> Main upsides:
> 
> - Using the same common entry as used by x86_64, RISCV, S390
>   and Loongarch, probably soon also ARM64.
> 
> - Moves ARM away from the obsoleted context tracker entry points
>   user_enter_callable() and user_exit_callable() are now only used
>   by ARM, CSKY and Xtensa.
> 
> - Solves a few lockdep warnings in the process.
> 
> - Converts a bit of assembly into C.
> 
> Main downside:
> 
> - Slightly increased system call overhead, around 6% in
>   measurements.
> 
> ----------------------------------------------------------------
> Linus Walleij (31):
>       ARM: Prepare includes for generic entry
>       ARM: ptrace: Split report_syscall()
>       ARM: entry: Skip ret_slow_syscall label
>       ARM: process: Rewrite ret_from_fork i C
>       ARM: process: Remove local restart
>       ARM: entry: Invoke syscalls using C
>       ARM: entry: Rewrite two asm calls in C
>       ARM: entry: Move trace entry to C function
>       ARM: entry: save the syscall sp in thread_info
>       ARM: entry: move all tracing invocation to C
>       ARM: entry: Merge the common and trace entry code
>       ARM: entry: Rename syscall invocation
>       ARM: entry: Create user_mode_enter/exit
>       ARM: entry: Drop trace argument from usr_entry macro
>       ARM: entry: Separate call path for syscall SWI entry
>       ARM: entry: Drop argument to asm_irqentry macros
>       ARM: entry: Implement syscall_exit_to_user_mode()
>       ARM: entry: Drop the superfast ret_fast_syscall
>       ARM: entry: Remove fast and offset register restore
>       ARM: entry: Untangle ret_fast_syscall/to_user
>       ARM: entry: Do not double-call exit functions
>       ARM: entry: Move work processing to C
>       ARM: entry: Stop exiting syscalls like IRQs
>       ARM: entry: Complete syscall and IRQ transition to C
>       ARM: entry: Create irqentry calls from kernel mode
>       ARM: entry: Move in-kernel hardirq tracing to C
>       ARM: irq: Add irqstack helper
>       ARM: entry: Convert to generic entry
>       ARM: entry: Handle dabt, pabt, and und as interrupts
>       ARM: entry: Block IRQs in early IRQ context
>       ARM: entry: Reimplement local restart in C
> 
>  arch/arm/Kconfig                    |   1 +
>  arch/arm/include/asm/entry-common.h |  66 ++++++++++++
>  arch/arm/include/asm/entry.h        |  14 +++
>  arch/arm/include/asm/ptrace.h       |   8 +-
>  arch/arm/include/asm/signal.h       |   4 -
>  arch/arm/include/asm/stacktrace.h   |   2 +-
>  arch/arm/include/asm/switch_to.h    |   4 +
>  arch/arm/include/asm/syscall.h      |   7 ++
>  arch/arm/include/asm/thread_info.h  |  22 ++--
>  arch/arm/include/asm/traps.h        |   5 +-
>  arch/arm/include/uapi/asm/ptrace.h  |   2 +
>  arch/arm/kernel/Makefile            |   5 +-
>  arch/arm/kernel/asm-offsets.c       |   1 +
>  arch/arm/kernel/entry-armv.S        |  82 ++++-----------
>  arch/arm/kernel/entry-common.S      | 198 +++++++++++++-----------------------
>  arch/arm/kernel/entry-header.S      | 100 ++----------------
>  arch/arm/kernel/entry.c             | 120 ++++++++++++++++++++++
>  arch/arm/kernel/irq.c               |   6 ++
>  arch/arm/kernel/irq.h               |   2 +
>  arch/arm/kernel/process.c           |  25 ++++-
>  arch/arm/kernel/ptrace.c            |  81 +--------------
>  arch/arm/kernel/signal.c            |  68 +++----------
>  arch/arm/kernel/syscall.c           |  59 +++++++++++
>  arch/arm/kernel/traps.c             |  30 +-----
>  arch/arm/mm/abort-ev4.S             |   2 +-
>  arch/arm/mm/abort-ev4t.S            |   2 +-
>  arch/arm/mm/abort-ev5t.S            |   4 +-
>  arch/arm/mm/abort-ev5tj.S           |   6 +-
>  arch/arm/mm/abort-ev6.S             |   2 +-
>  arch/arm/mm/abort-ev7.S             |   2 +-
>  arch/arm/mm/abort-lv4t.S            |  36 +++----
>  arch/arm/mm/abort-macro.S           |   2 +-
>  arch/arm/mm/abort-nommu.S           |   2 +-
>  arch/arm/mm/fault.c                 |   4 +-
>  arch/arm/mm/fault.h                 |   8 +-
>  arch/arm/mm/pabort-legacy.S         |   2 +-
>  arch/arm/mm/pabort-v6.S             |   2 +-
>  arch/arm/mm/pabort-v7.S             |   2 +-
>  38 files changed, 484 insertions(+), 504 deletions(-)
>  create mode 100644 arch/arm/include/asm/entry-common.h
>  create mode 100644 arch/arm/include/asm/entry.h
>  create mode 100644 arch/arm/kernel/entry.c
>  create mode 100644 arch/arm/kernel/irq.h
>  create mode 100644 arch/arm/kernel/syscall.c


From robin.murphy at arm.com  Wed Mar 12 11:01:25 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 12 Mar 2025 18:01:25 +0000
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <CAF6AEGskyoemQDrTXh=ewf61e-hVzWMjmqe=nX2J-65W5-M6Zw@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck>
 <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck>
 <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
 <20250312164735.GA6561@willie-the-truck>
 <CAF6AEGskyoemQDrTXh=ewf61e-hVzWMjmqe=nX2J-65W5-M6Zw@mail.gmail.com>
Message-ID: <2d47815d-6bee-4d1f-8b60-854763794bf6@arm.com>

On 12/03/2025 5:23 pm, Rob Clark wrote:
> On Wed, Mar 12, 2025 at 9:47?AM Will Deacon <will at kernel.org> wrote:
>>
>> On Wed, Mar 12, 2025 at 07:59:52AM -0700, Rob Clark wrote:
>>> On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
>>>> On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
>>>>> On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
>>>>>> On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
>>>>>>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
>>>>>>> index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
>>>>>>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
>>>>>>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
>>>>>>> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
>>>>>>>                                      struct arm_smmu_context_fault_info *cfi)
>>>>>>>   {
>>>>>>>        cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
>>>>>>> +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
>>>>>>>        cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
>>>>>>> -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
>>>>>>> +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
>>>>>>> +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
>>>>>>
>>>>>> We already have an implementation hook (->get_fault_info()) which the
>>>>>> qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
>>>>>> That thing dumps these registers already so if we're moving that into
>>>>>> the core SMMU driver, let's get rid of the hook and move everybody over
>>>>>> rather than having it done in both places.
>>>>>
>>>>> As you probably saw, the next commit moves over
>>>>> qcom_adreno_smmu_get_fault_info() to use this. The current back door
>>>>> used by drm/msm to access these functions is specific to adreno_smmu
>>>>> and there isn't an equivalent interface to allow it to call a generic
>>>>> SMMU function so it isn't possible to move it entirely to the core. At
>>>>> least not without a bigger refactoring that isn't justified for this
>>>>> series that is just trying to fix things.
>>>>
>>>> Ok :(
>>>>
>>>>>>>        cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
>>>>>>> +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
>>>>>>
>>>>>> I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
>>>>>> it for stage-2 domains.
>>>>>>
>>>>> Does it matter if we read the register though, as long as users are
>>>>> aware of this and don't use its value for anything?
>>>>
>>>> I think the contents are "UNKNOWN", so it could be hugely confusing even
>>>> if they just got logged someplace. Why is it difficult to avoid touching
>>>> it for stage-2?
>>>>
>>> Fwiw, we are only ever using stage-1
>>
>> Sure, but this is in arm-smmu.c which is used by other people and supports
>> both stages.
> 
> Sure, but no one else is using this field in the fault-info.  So maybe
> the addition of a comment in the struct would be enough if it isn't
> going to cause an SError/etc to read it for S2 cb?

Any worthwhile comment isn't going to be significantly shorter or 
clearer than 1 extra line of "if (smmu_domain->stage == 
ARM_SMMU_DOMAIN_S1)"...

TBH it's the Qualcomm register-middle-man firmware I'd be more worried 
about than real hardware, given how touchy it can be even with register 
accesses which *should* be well defined. But then I guess it also has 
the habit of killing the system if anything other than the GPU dares 
cause a fault in the first place, so maybe it OK?

If anyone still uses Arm Fast Models SMMUv1/2 components it'll probably 
squawk an annoying warning there too - ISTR I had at least one patch 
motivated by that in the past.

Thanks,
Robin.


From linux at armlinux.org.uk  Wed Mar 12 10:56:41 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 17:56:41 +0000
Subject: [PATCH v8 2/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <Z8hjKI1ZqU19nrTP@shell.armlinux.org.uk>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
 <CGME20250305091856epcas5p4228c09989c7acfe45a99541eef01fbcd@epcas5p4.samsung.com>
 <20250305091246.106626-3-swathi.ks@samsung.com>
 <Z8hjKI1ZqU19nrTP@shell.armlinux.org.uk>
Message-ID: <Z9HK2de5Ba_Vbeo7@shell.armlinux.org.uk>

On Wed, Mar 05, 2025 at 02:43:52PM +0000, Russell King (Oracle) wrote:
> On Wed, Mar 05, 2025 at 02:42:46PM +0530, Swathi K S wrote:
> > The FSD SoC contains two instance of the Synopsys DWC ethernet QOS IP core.
> > The binding that it uses is slightly different from existing ones because
> > of the integration (clocks, resets).
> > 
> > Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> 
> This looks much better!
> 
> Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> 
> Thanks!

Hi Swathi,

Please can you test with my TX clock gating series applied
( https://lore.kernel.org/r/Z9FVHEf3uUqtKzyt at shell.armlinux.org.uk )
with STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP set as per the attached diff.
Please let me know whether this passes your testing, so I know whether
this platform supports it - please check that this results in a
message in the kernel log indicating "tx_clk_stop = 1". Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: stmmac-dwc-qos-eth-tx-clk-stop.diff
Type: text/x-diff
Size: 1225 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/d5b61c0c/attachment.bin>

From nunodasneves at linux.microsoft.com  Wed Mar 12 11:04:37 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Wed, 12 Mar 2025 11:04:37 -0700
Subject: [PATCH v5 02/10] x86/mshyperv: Add support for extended Hyper-V
 features
In-Reply-To: <SN6PR02MB4157CBBC2D186E1944E6773AD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-3-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157CBBC2D186E1944E6773AD4CA2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <8520ef42-6cb4-4e14-9700-de7ae8a99ae8@linux.microsoft.com>

On 3/6/2025 10:30 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
>> From: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
>>
>> Extend the "ms_hyperv_info" structure to include a new field,
>> "ext_features", for capturing extended Hyper-V features.
>> Update the "ms_hyperv_init_platform" function to retrieve these features
>> using the cpuid instruction and include them in the informational output.
>>
>> Signed-off-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> ---
>>  arch/x86/kernel/cpu/mshyperv.c | 6 ++++--
>>  include/asm-generic/mshyperv.h | 1 +
>>  2 files changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
>> index 4f01f424ea5b..2c29dfd6de19 100644
>> --- a/arch/x86/kernel/cpu/mshyperv.c
>> +++ b/arch/x86/kernel/cpu/mshyperv.c
>> @@ -434,13 +434,15 @@ static void __init ms_hyperv_init_platform(void)
>>  	 */
>>  	ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
>>  	ms_hyperv.priv_high = cpuid_ebx(HYPERV_CPUID_FEATURES);
>> +	ms_hyperv.ext_features = cpuid_ecx(HYPERV_CPUID_FEATURES);
>>  	ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
>>  	ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
>>
>>  	hv_max_functions_eax = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS);
>>
>> -	pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n",
>> -		ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
>> +	pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, ext 0x%x, hints 0x%x, misc 0x%x\n",
>> +		ms_hyperv.features, ms_hyperv.priv_high,
>> +		ms_hyperv.ext_features, ms_hyperv.hints,
>>  		ms_hyperv.misc_features);
>>
>>  	ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
>> diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
>> index dc4729dba9ef..c020d5d0ec2a 100644
>> --- a/include/asm-generic/mshyperv.h
>> +++ b/include/asm-generic/mshyperv.h
>> @@ -36,6 +36,7 @@ enum hv_partition_type {
>>  struct ms_hyperv_info {
>>  	u32 features;
>>  	u32 priv_high;
>> +	u32 ext_features;
>>  	u32 misc_features;
>>  	u32 hints;
>>  	u32 nested_features;
>> --
>> 2.34.1
> 
> Are any of the extended features available on arm64? This code is obviously x86 specific,
> so ms_hyperv.ext_features will be zero on arm64. From what I can see, ext_features is
> referenced only in Patch 10 of this series, and in code that is under #ifdef CONFIG_X86_64,
> so that should be OK.

Just checked - yes ARM64 has features in ECX, but they are different to the x86_64 ones.
We can add the ARM64 ones when needed.

Thanks
Nuno

> 
> The pr_info() line will now be slightly different on x86 and arm64 since arm64 won't have
> the "ext" field, but I think that's OK too.
> 
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>



From catalin.marinas at arm.com  Wed Mar 12 11:09:21 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 12 Mar 2025 18:09:21 +0000
Subject: [PATCH V2 0/8] arm64/mm: Drop PXD_TABLE_BIT
In-Reply-To: <20250221044227.1145393-1-anshuman.khandual@arm.com>
References: <20250221044227.1145393-1-anshuman.khandual@arm.com>
Message-ID: <174180295545.4162360.4956385573664588446.b4-ty@arm.com>

On Fri, 21 Feb 2025 10:12:19 +0530, Anshuman Khandual wrote:
> Remove the PXX_TABLE_BIT definitions and instead rely on PXX_TYPE_MASK,
> PXX_TYPE_SECT and PXX_TYPE_TABLE. The latter versions are more abstract
> and also include the PTE_VALID bit.
> 
> This abstraction is valuable for the impending D128 page table support,
> which doesn't have a single page table bit to determine table vs block.
> Instead it has the skip level (SKL) field, where it will consider 0 to
> mean table and any other value to mean a block entry. So PXX_TABLE_BIT
> therefore doesn't fit into the D128 model well, but the type fields do.
> 
> [...]

Applied to arm64 (for-next/drop-pxd_table_bit), thanks!

[1/8] KVM: arm64: ptdump: Test PMD_TYPE_MASK for block mapping
      https://git.kernel.org/arm64/c/0b626b245c57
[2/8] arm64/ptdump: Test PMD_TYPE_MASK for block mapping
      https://git.kernel.org/arm64/c/f5e93819e2cc
[3/8] arm64/mm: Clear PXX_TYPE_MASK in mk_[pmd|pud]_sect_prot()
      https://git.kernel.org/arm64/c/dba954801004
[4/8] arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT in [pmd|pud]_mkhuge()
      https://git.kernel.org/arm64/c/1601df9e366e
[5/8] arm64/mm: Check PXD_TYPE_TABLE in [p4d|pgd]_bad()
      https://git.kernel.org/arm64/c/4fa8a9c0fc99
[6/8] arm64/mm: Check PUD_TYPE_TABLE in pud_bad()
      https://git.kernel.org/arm64/c/bfb1d2b9021c
[7/8] arm64/mm: Check pmd_table() in pmd_trans_huge()
      https://git.kernel.org/arm64/c/d1770e909898
[8/8] arm64/mm: Drop PXD_TABLE_BIT
      https://git.kernel.org/arm64/c/50c2726654bb

-- 
Catalin



From minchan at kernel.org  Wed Mar 12 11:11:54 2025
From: minchan at kernel.org (Minchan Kim)
Date: Wed, 12 Mar 2025 11:11:54 -0700
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
Message-ID: <Z9HOavSkFf01K9xh@google.com>

Hi Qun-Wei

On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> This patch series introduces a new mechanism called kcompressd to
> improve the efficiency of memory reclaiming in the operating system. The
> main goal is to separate the tasks of page scanning and page compression
> into distinct processes or threads, thereby reducing the load on the
> kswapd thread and enhancing overall system performance under high memory
> pressure conditions.
> 
> Problem:
>  In the current system, the kswapd thread is responsible for both
>  scanning the LRU pages and compressing pages into the ZRAM. This
>  combined responsibility can lead to significant performance bottlenecks,
>  especially under high memory pressure. The kswapd thread becomes a
>  single point of contention, causing delays in memory reclaiming and
>  overall system performance degradation.

Isn't it general problem if backend for swap is slow(but synchronous)?
I think zram need to support asynchrnous IO(can do introduce multiple
threads to compress batched pages) and doesn't declare it's
synchrnous device for the case.


From ariel.dalessandro at collabora.com  Wed Mar 12 11:28:15 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Wed, 12 Mar 2025 15:28:15 -0300
Subject: [PATCH v1 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250311110520.6b79e090@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-5-ariel.dalessandro@collabora.com>
 <20250311090545.3b941567@collabora.com>
 <16f6a6e2-4dce-4af9-bc0a-61c4d6213f02@collabora.com>
 <20250311110520.6b79e090@collabora.com>
Message-ID: <2a6eb940-95b3-4105-8998-5ec190ddaca3@collabora.com>

Boris, Angelo,

On 3/11/25 7:05 AM, Boris Brezillon wrote:
> On Tue, 11 Mar 2025 10:14:44 +0100
> AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> wrote:
> 
>> Il 11/03/25 09:05, Boris Brezillon ha scritto:
>>> On Mon, 10 Mar 2025 16:59:19 -0300
>>> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
>>>    
>>>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>>>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>>>> Address Extension", which in Linux we've called "mali_lpae".
>>>>
>>>> This commit adds support for conditionally enabling AARCH64_4K page
>>>> table format. To achieve that, a "GPU optional configurations" field was
>>>> added to `struct panfrost_features` with the related flag.
>>>>
>>>> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
>>>> the HW_FEATURE_AARCH64_MMU feature flag present.
>>>>
>>>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>>>> ---
>>>>    drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>>>>    drivers/gpu/drm/panfrost/panfrost_mmu.c    | 132 +++++++++++++++++++--
>>>>    drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>>>>    3 files changed, 169 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
>>>> index cffcb0ac7c111..0385702aa43c7 100644
>>>> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
>>>> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
>>>> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>>>>    	GPU_PM_VREG_OFF,
>>>>    };
>>>>    
>>>> +/**
>>>> + * enum panfrost_gpu_config - GPU optional configurations
>>>> + * @GPU_CONFIG_AARCH64_4K: Use AARCH64_4K page table format
>>>> + */
>>>> +enum panfrost_gpu_config {
>>>> +	GPU_CONFIG_AARCH64_4K,
>>>> +};
>>>> +
>>>>    struct panfrost_features {
>>>>    	u16 id;
>>>>    	u16 revision;
>>>> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>>>>    
>>>>    	/* Allowed PM features */
>>>>    	u8 pm_features;
>>>> +
>>>> +	/* GPU features */
>>>> +	u8 gpu_configs;
>>>
>>> I would probably name this gpu_quirks, with the GPU_CONFIG_AARCH64_4K
>>> flag renamed GPU_QUIRK_FORCE_AARCH64_PAGE_TABLE.
>>>    
>>
>> Boris, at this point the quirk should be LPAE, not AARCH64_4K, because the
>> former is legacy...
> 
> It's legacy, but it's also the default in this driver. And just because
> it's legacy doesn't mean it's broken :P. As Steve mentioned, there are
> perf considerations to take into account, and on some platforms (most?),
> it's preferable to use the legacy format because of that.
> 
>>
>> I think that Ariel is right in this, as in, that's a capability of the GPU
>> MMU, so if anything I would rather rename it to gpu_capabilities,
> 
> No, GPU capabilities are extracted from he GPU ID, and all Bifrost GPUs
> support the aarch64 page table format. But what matters here is GPUs
> that can't use the legacy page table format because it's to limited to
> express the cacheability/shareability properties.
> 
>> but then
>> that'd be confusing for other stuff - which means that gpu_configs is most
>> probably the least confusing and/or most appropriate name for this.
> 
> Again, it's not a random configuration decision, it's something we do
> because the default (legacy page table format) doesn't work, so I keep
> thinking quirk is an appropriate name in this context.

Adding my humble bits here :)

I'm not sure if it's preferable to use legacy mode, but can't prove the 
opposite without a proper profiling. As legacy is the default at the 
moment in panfrost, I think it makes sense to explicitly add _FORCE_ to 
the flag name.

Agreed that it's not a capability/feature, rather a config/quirk. Don't 
really have a strong opinion here, so I'll just stick to Boris criteria 
here, and name it as quirks. Will change it in v2.

Just a side note, in the context of panfrost we already have a 
`vendor_quirk` function. Alhough I understand it's vendor-specific, to 
avoid confusions, would it be okay to add another quirk related field as 
we're proposing here?

     struct panfrost_compatible {
         [...]
         /* Vendor implementation quirks callback */
         void (*vendor_quirk)(struct panfrost_device *pfdev);
         [...]
         u8 gpu_quirks;

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From romank at linux.microsoft.com  Wed Mar 12 11:33:11 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Wed, 12 Mar 2025 11:33:11 -0700
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
Message-ID: <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>



On 3/10/2025 3:18 PM, Michael Kelley wrote:
> From: Arnd Bergmann <arnd at arndb.de> Sent: Monday, March 10, 2025 2:21 PM
>>
>> On Mon, Mar 10, 2025, at 22:01, Michael Kelley wrote:
>>> From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
>>>>>   config HYPERV_VTL_MODE
>>>>>   	bool "Enable Linux to boot in VTL context"
>>>>> -	depends on X86_64 && HYPERV
>>>>> +	depends on (X86_64 || ARM64)
>>>>>   	depends on SMP
>>>>> +	select OF_EARLY_FLATTREE
>>>>> +	select OF
>>>>>   	default n
>>>>>   	help
>>>>
>>>> Having the dependency below the top-level Kconfig entry feels a little
>>>> counterintuitive. You could flip that back as it was before by doing
>>>>
>>>>        select HYPERV_VTL_MODE if !ACPI
>>>>        depends on ACPI || SMP
>>>>
>>>> in the HYPERV option, leaving the dependency on HYPERV in
>>>> HYPERV_VTL_MODE.
>>>
>>> I would argue that we don't ever want to implicitly select
>>> HYPERV_VTL_MODE because of some other config setting or
>>> lack thereof.  VTL mode is enough of a special case that it should
>>> only be explicitly selected. If someone omits ACPI, then HYPERV
>>> should not be selectable unless HYPERV_VTL_MODE is explicitly
>>> selected.
>>>
>>> The last line of the comment for HYPERV_VTL_MODE says
>>> "A kernel built with this option must run at VTL2, and will not run
>>> as a normal guest."  In other words, don't choose this unless you
>>> 100% know that VTL2 is what you want.
>>
>> It sounds like the latter is the real problem: enabling a feature
>> should never prevent something else from working. Can you describe
>> what VTL context is and why it requires an exception to a rather
>> fundamental rule here? If you build a kernel that runs on every
>> single piece of arm64 hardware and every hypervisor, why can't
>> you add HYPERV_VTL_MODE to that as an option?
>>

In the VTL mode, we're running the kernel as secure firmware inside the
guest (one might see VTL2 working as Intel SMM or Secure World on ARM).

[...]

> 
> Ideally, a Linux kernel image could detect at runtime what VTL it is
> running at, and "do the right thing". Unfortunately, on x86 Linux this
> has proved difficult (or perhaps impossible) because the amount of
> boot-time setup required to ask the question about the current VTL
> is significant. The idiosyncrasies and historical baggage of x86 requires
> that Linux do some x86-specific initialization steps for VTL > 0
> before the question can be asked. Hence the introduction of
> CONFIG_HYPERV_VTL_MODE, and the behavior that when it is
> selected, the kernel image won't run normally in VTL 0.
> 
> I'll go out on a limb and say that I suspect on arm64 a runtime
> determination based on querying the VTL *could* be made (though
> I'm not the person writing the code). But taking advantage of that
> on arm64 produces an undesirable dichotomy with x86.

On arm64 that is much easier, I agree. On x86 we'd need a kludge of

static void __naked __init __aligned(4096) early_hvcall_pg(void)
{
	/*
	 * Fill the early hvcall page with `0xF1` aka `INT1` to catch
	 * programming errors. The hypervisor will overlay the page with
	 * the vendor-specific code sequences to make hypercalls on x86(_64).
	 */
	asm (".skip 4096, 0xf1");
}

static u8 __init early_hvcall_pg_input[4096] 
__attribute__((aligned(4096)));
static u8 __init early_hvcall_pg_output[4096] 
__attribute__((aligned(4096)));

static void __init early_connect_to_hv(void)
{
	union hv_x64_msr_hypercall_contents hypercall_msr;
	u64 guest_id;

	guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
	wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
	hypercall_msr.enable = 1;
	hypercall_msr.guest_physical_address = 
__phys_to_pfn(virt_to_phys(early_hvcall_pg));
	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
}

or variations thereof.

What's very nice about arm64 in this case at least, it's got SMCCC, hvc,
OF/DT and a history of options of being power-efficient and embedded.
Conversely, on x86(_64) the code sequences for hyeprcalls vary from the
first vendor to the second one so we have to have the hvcall page to
make this regular in the code. Support for OF/DT on x86 was added for
Intel set top boxes (MID, ~2015 iirc), and it took a bit of huffing and
puffing to make that work for us on the large/NUMA systems (and there
might be something about supporting x2apic that had to be figured out).

All told, we can have nicer things in our arm64 code yet diverging the
code much from x86(_64) is not very desirable. I am not sure yet what
the tradeoff should be, and my knowledge of Kconfig is rather basic.
Certainly I cannot propose to arm64 maintainers that we'd like to do
quirky things in Kconfig because of x86(-64), legacy specs, etc.

Perhaps, we could go back to the V2's option of

  config HYPERV
  	tristate "Microsoft Hyper-V client drivers"
  	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
-		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
+		|| (ARM64 && !CPU_BIG_ENDIAN)
  	select PARAVIRT
  	select X86_HV_CALLBACK_VECTOR if X86
  	select OF_EARLY_FLATTREE if OF
@@ -15,7 +15,7 @@ config HYPERV

  config HYPERV_VTL_MODE
  	bool "Enable Linux to boot in VTL context"
-	depends on X86_64 && HYPERV
+	depends on HYPERV
  	depends on SMP
  	default n
  	help
@@ -31,7 +31,7 @@ config HYPERV_VTL_MODE

  	  Select this option to build a Linux kernel to run at a VTL other than
  	  the normal VTL0, which currently is only VTL2.  This option
-	  initializes the x86 platform for VTL2, and adds the ability to boot
+	  initializes the kernel to run in VTL2, and adds the ability to boot
  	  secondary CPUs directly into 64-bit context as required for VTLs other
  	  than 0.  A kernel built with this option must run at VTL2, and will
  	  not run as a normal guest.

That's a minimal extension, its surprise factor is very low. It has not
been seen to cause issues. If no one has strong opinions against that,
I'd send that in V6.

> 
> Roman may have further thoughts on the topic, but that's
> what I know about how we got here.
> 
> Michael
> 
> [1] https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm
> [2] https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172

-- 
Thank you,
Roman



From dev at folker-schwesinger.de  Wed Mar 12 11:23:49 2025
From: dev at folker-schwesinger.de (Folker Schwesinger)
Date: Wed, 12 Mar 2025 19:23:49 +0100
Subject: [PATCH 1/1] dmaengine: xilinx_dma: Set dma_device.directions
In-Reply-To: <D8EI6SI5E4PE.3GOBCNHV38K03@folker-schwesinger.de>
Message-ID: <D8EI6SI5EIUY.2JD240P96ZZSS@folker-schwesinger.de>

When using the dma_get_slave_caps() API, it checks the directions fields of
the dma_device structure. Currently, the Xilinx DMA driver does not set
this, which causes dma_get_slave_caps() to return -ENXIO.

Fix this issue by setting the directions field of the dma_device
structure during DMA channel probe.

Signed-off-by: Folker Schwesinger <dev at folker-schwesinger.de>
---
 drivers/dma/xilinx/xilinx_dma.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 3ad44afd0e74..63c308f2ae81 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -2864,6 +2864,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 	    of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") ||
 	    of_device_is_compatible(node, "xlnx,axi-cdma-channel")) {
 		chan->direction = DMA_MEM_TO_DEV;
+		xdev->common.directions |= BIT(DMA_MEM_TO_DEV);
 		chan->id = xdev->mm2s_chan_id++;
 		chan->tdest = chan->id;
 
@@ -2881,6 +2882,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		   of_device_is_compatible(node,
 					   "xlnx,axi-dma-s2mm-channel")) {
 		chan->direction = DMA_DEV_TO_MEM;
+		xdev->common.directions |= BIT(DMA_DEV_TO_MEM);
 		chan->id = xdev->s2mm_chan_id++;
 		chan->tdest = chan->id - xdev->dma_config->max_channels / 2;
 		chan->has_vflip = of_property_read_bool(node,
-- 
2.48.1


From dev at folker-schwesinger.de  Wed Mar 12 11:36:09 2025
From: dev at folker-schwesinger.de (Folker Schwesinger)
Date: Wed, 12 Mar 2025 19:36:09 +0100
Subject: [PATCH 0/1] dmaengine: xilinx_dma: Set dma_device.directions
Message-ID: <D8EI6SI5E4PE.3GOBCNHV38K03@folker-schwesinger.de>

Currently it is not possible to use the Xilinx DMA driver as a backend
for IIO drivers. Setting up IIO DMA buffers with
devm_iio_dmaengine_buffer_setup() fails because dma_get_slave_caps()
always returns -ENXIO. The reason is that the Xilinx DMA driver does not
set the directions field in struct dma_device, which is checked in
dma_get_slave_caps().

This patch fixes this issue. It basically is a partial resend of this
patch [1], modified to apply on dmaengine->next. It was discussed back
in 2018 in this thread [2].
As I'm quite new to the kernel dev process, I'm not sure if I should
have included any tags to give credit to the original patch author.

[1]: https://patchwork.kernel.org/project/linux-dmaengine/patch/1514961731-1916-2-git-send-email-appanad at xilinx.com/
[2]: https://lore.kernel.org/lkml/20180111062111.GH18649 at localhost/T/

Folker Schwesinger (1):
  dmaengine: xilinx_dma: Set dma_device.directions

 drivers/dma/xilinx/xilinx_dma.c | 2 ++
 1 file changed, 2 insertions(+)


base-commit: 6565439894570a07b00dba0b739729fe6b56fba4
-- 
2.48.1


From andrew at lunn.ch  Wed Mar 12 12:02:15 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 20:02:15 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <ce0796f4-cf2e-4a3d-ae79-1f9b9966773e@lunn.ch>

On Wed, Mar 12, 2025 at 04:08:02PM +0000, Gupta, Suraj wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
> 
> > -----Original Message-----
> > From: Andrew Lunn <andrew at lunn.ch>
> > Sent: Wednesday, March 12, 2025 9:03 PM
> > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> > devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> > kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > <harini.katakam at amd.com>
> > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> > configuration.
> >
> > Caution: This message originated from an External Source. Use proper caution
> > when opening attachments, clicking links, or responding.
> >
> >
> > On Wed, Mar 12, 2025 at 03:06:32PM +0000, Gupta, Suraj wrote:
> > > [AMD Official Use Only - AMD Internal Distribution Only]
> > >
> > > > -----Original Message-----
> > > > From: Andrew Lunn <andrew at lunn.ch>
> > > > Sent: Wednesday, March 12, 2025 8:29 PM
> > > > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > > > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > > > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > > > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > > > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org;
> > > > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > > > <harini.katakam at amd.com>
> > > > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > > 2500base-X only configuration.
> > > >
> > > > Caution: This message originated from an External Source. Use proper
> > > > caution when opening attachments, clicking links, or responding.
> > > >
> > > >
> > > > > > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > > > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > > > > > +    * 1) SGMII/1000base-X only.
> > > > > > > > +    * 2) 2500base-X only.
> > > > > > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > > > > > +    * implemented in driver.
> > > > > > > > +    */
> > > >
> > > > > - Keeping previous discussion short, identification of (3) depends
> > > > > on how user implements switching logic in FPGA (external GT or RTL
> > > > > logic). AXI 1G/2.5G IP provides only static speed selections and
> > > > > there is no standard register to communicate that to software.
> > > >
> > > > So if anybody has synthesised it as 3) this change will break their system?
> > > >
> > > >         Andrew
> > >
> > > It will just restrict their system to (2)
> >
> > Where as before, it was doing SGMII/1000base-X only. So such systems break?
> >
> >         Andrew
> 

> If the user wants (3), they need to add their custom FPGA logic
> which anyway will require additional driver changes. (3) was not
> completely supported by existing driver.

You say 3) is a synthesis option. Say somebody synthesised it that
way, and found it works for what they need with SGMII/1000base-X.
Because the driver took no notice of the capability bit, that is what
it would do. Since it worked for them, they might not of gone back and
optimised the options. "If it is not broken, don't fix it". So we
could have systems out in the wild, synthesised as 3) happily doing 
SGMII/1000base-X ?

With this change, won't you break those systems?

I'm just trying to get to a definitive answer, is this change actually
safe to all todays possible systems?

	Andrew



From rmk+kernel at armlinux.org.uk  Wed Mar 12 12:43:09 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 19:43:09 +0000
Subject: [PATCH net] net: stmmac: dwc-qos-eth: use devm_kzalloc() for AXI data
Message-ID: <E1tsRyv-0064nU-O9@rmk-PC.armlinux.org.uk>

Everywhere else in the driver uses devm_kzalloc() when allocating the
AXI data, so there is no kfree() of this structure. However,
dwc-qos-eth uses kzalloc(), which leads to this memory being leaked.
Switch to use devm_kzalloc().

Fixes: d8256121a91a ("stmmac: adding new glue driver dwmac-dwc-qos-eth")
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index bd4eb187f8c6..b5a7e05ab7a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -46,7 +46,9 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
 	u32 a_index = 0;
 
 	if (!plat_dat->axi) {
-		plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL);
+		plat_dat->axi = devm_kzalloc(&pdev->dev,
+					     sizeof(struct stmmac_axi),
+					     GFP_KERNEL);
 
 		if (!plat_dat->axi)
 			return -ENOMEM;
-- 
2.30.2



From michael at fossekall.de  Wed Mar 12 12:36:28 2025
From: michael at fossekall.de (Michael Klein)
Date: Wed, 12 Mar 2025 20:36:28 +0100
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <20250312193629.85417-1-michael@fossekall.de>
References: <20250312193629.85417-1-michael@fossekall.de>
Message-ID: <20250312193629.85417-2-michael@fossekall.de>

The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
Add the corresponding nodes to the device tree.

Signed-off-by: Michael Klein <michael at fossekall.de>
---
 .../boot/dts/allwinner/sun7i-a20-bananapi.dts | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
index 46ecf9db2324..4976453ed192 100644
--- a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
+++ b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
@@ -48,6 +48,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
 
 / {
 	model = "LeMaker Banana Pi";
@@ -169,6 +170,32 @@ &ir0 {
 &gmac_mdio {
 	phy1: ethernet-phy at 1 {
 		reg = <1>;
+
+		leds {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			led at 0 {
+				reg = <0>;
+				color = <LED_COLOR_ID_GREEN>;
+				default-state = "keep";
+				linux,default-trigger = "netdev";
+			};
+
+			led at 1 {
+				reg = <1>;
+				color = <LED_COLOR_ID_AMBER>;
+				default-state = "keep";
+				linux,default-trigger = "netdev";
+			};
+
+			led at 2 {
+				reg = <2>;
+				color = <LED_COLOR_ID_BLUE>;
+				default-state = "keep";
+				linux,default-trigger = "netdev";
+			};
+		};
 	};
 };
 
-- 
2.39.5



From heiko at sntech.de  Wed Mar 12 12:38:31 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 20:38:31 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <b7d8d385-81ee-4947-ab8f-1da43843464b@kwiboo.se>
References: <a5ec9062-ca57-4748-8c0f-fb5b9c75fa28@kwiboo.se>
 <20250312143515.1225171-1-amadeus@jmu.edu.cn>
 <b7d8d385-81ee-4947-ab8f-1da43843464b@kwiboo.se>
Message-ID: <7779050.EvYhyI6sBW@phil>

Am Mittwoch, 12. M?rz 2025, 16:00:00 MEZ schrieb Jonas Karlman:
> Hi Chukun,
> 
> On 2025-03-12 15:35, Chukun Pan wrote:
> > Hi,
> > 
> >> The pinctrl-names should be changed to "default" and not "active",
> >> something you can fixup or do you want a patch?

so yes of course the pinctrl needs to be default - simply because
that's the only pinctrl state mainline supports.

But judging by the fact that you're discussing working vs. non-working
below, can you please check if we should drop the patch for 6.15 till
that is solved?

Thanks a lot
Heiko

> > Sorry I've been a bit busy this week and forgot to send the v2 patch.
> > In rk3528.dtsi, the uart and upcoming i2c nodes do not have pinctrl,
> > so I prefer to remove them.
> > 
> >>> Unlike other SoCs, pinctrl-names need to be in "active" state,
> >>> I'm not sure about this, but otherwise the pwm-regulator will
> >>> not work properly.
> > 
> > BTW, setting the pinctrl of pwm corresponding to pwm-regulator
> > to "default" will cause kernel boot suspended.
> > Sorry but do you know why?
> 
> Not an issue I have seen, do you have any more logs or details? E.g.
> what board you use, full regulator node, do you have operating points
> defined etc.
> 
> I have runtime tested a branch at [1], that use pinctrl-names = default,
> have vdd_arm and vdd_logic defined, also an opp table for cpu and gpu.
> 
> For E20C there is a commit to enable the vdd_logic, however without gpu
> enabled and a mali-supply the pwm-regulator is initialized to
> max-microvolt by Linux. Have instead updated U-Boot to initialize the
> pwm-regulator's:
> 
> ```
> &vdd_arm {
> 	regulator-init-microvolt = <953000>;
> };
> 
> &vdd_logic {
> 	regulator-init-microvolt = <900000>;
> };
> ```
> 
> [1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250311-rk3528/
> 
> Regards,
> Jonas
> 
> > 
> > e.g.
> > ```
> > vdd_arm: regulator-vdd-arm {
> > 	compatible = "pwm-regulator";
> > 	pwms = <&pwm1 0 5000 1>;
> > 	...
> > };
> > 
> > &pwm1 {
> > 	pinctrl-0 = <&pwm1m0_pins>;
> > 	pinctrl-names = "default";
> > 	status = "okay";
> > };
> > ```
> > 
> > Thanks,
> > Chukun
> > 
> > --
> > 2.25.1
> > 
> 
> 






From heiko at sntech.de  Wed Mar 12 12:38:48 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 20:38:48 +0100
Subject: (subset) [PATCH 0/3] rockchip: Add support for onboard eMMC on Radxa E20C
In-Reply-To: <20250305214108.1327208-1-jonas@kwiboo.se>
References: <20250305214108.1327208-1-jonas@kwiboo.se>
Message-ID: <174180832194.262650.6974587881042851056.b4-ty@sntech.de>


On Wed, 05 Mar 2025 21:41:01 +0000, Jonas Karlman wrote:
> The Radxa E20C may come with an onboard eMMC (8GB / 16GB / 32GB / 64GB).
> 
> This series add dt-binding and SoC DT node for the SDHCI controller
> and enable use of the SDCHI controller on the Radxa E20C.
> 
> This series add support for the onboard eMMC on Radxa E20C.
> 
> [...]

Applied, thanks!

[2/3] arm64: dts: rockchip: Add SDHCI controller for RK3528
      commit: d62917b63e9f2c876bd9abf019a25313bd9cbc07
[3/3] arm64: dts: rockchip: Enable onboard eMMC on Radxa E20C
      commit: f25c3b93f50387849db692891e2b2c6f9cc7d055

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From linux at armlinux.org.uk  Wed Mar 12 12:40:40 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Wed, 12 Mar 2025 19:40:40 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>

On Wed, Mar 12, 2025 at 04:08:02PM +0000, Gupta, Suraj wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
> 
> > -----Original Message-----
> > From: Andrew Lunn <andrew at lunn.ch>
> > Sent: Wednesday, March 12, 2025 9:03 PM
> > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> > devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> > kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > <harini.katakam at amd.com>
> > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> > configuration.
> >
> > Caution: This message originated from an External Source. Use proper caution
> > when opening attachments, clicking links, or responding.
> >
> >
> > On Wed, Mar 12, 2025 at 03:06:32PM +0000, Gupta, Suraj wrote:
> > > [AMD Official Use Only - AMD Internal Distribution Only]
> > >
> > > > -----Original Message-----
> > > > From: Andrew Lunn <andrew at lunn.ch>
> > > > Sent: Wednesday, March 12, 2025 8:29 PM
> > > > To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> > > > Cc: Russell King <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> > > > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > > > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > > > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org;
> > > > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > > > <harini.katakam at amd.com>
> > > > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > > 2500base-X only configuration.
> > > >
> > > > Caution: This message originated from an External Source. Use proper
> > > > caution when opening attachments, clicking links, or responding.
> > > >
> > > >
> > > > > > On Wed, Mar 12, 2025 at 02:25:27PM +0100, Andrew Lunn wrote:
> > > > > > > > +   /* AXI 1G/2.5G ethernet IP has following synthesis options:
> > > > > > > > +    * 1) SGMII/1000base-X only.
> > > > > > > > +    * 2) 2500base-X only.
> > > > > > > > +    * 3) Dynamically switching between (1) and (2), and is not
> > > > > > > > +    * implemented in driver.
> > > > > > > > +    */
> > > >
> > > > > - Keeping previous discussion short, identification of (3) depends
> > > > > on how user implements switching logic in FPGA (external GT or RTL
> > > > > logic). AXI 1G/2.5G IP provides only static speed selections and
> > > > > there is no standard register to communicate that to software.
> > > >
> > > > So if anybody has synthesised it as 3) this change will break their system?
> > > >
> > > >         Andrew
> > >
> > > It will just restrict their system to (2)
> >
> > Where as before, it was doing SGMII/1000base-X only. So such systems break?
> >
> >         Andrew
> 
> If the user wants (3), they need to add their custom FPGA logic which anyway will require additional driver changes. (3) was not completely supported by existing driver.

This is not an approach that works with the Linux kernel, sorry.

What we have today is a driver that works for people's hardware - and
we don't know what the capabilities of that hardware is.

If there's hardware out there today which has XAE_ABILITY_2_5G set, but
defaults to <=1G mode, this will work with the current driver. However,
with your patch applied, it stops working because instead of the driver
indicating MAC_10FD | MAC_100FD | MAC_1000FD, it only indicates
MAC_2500FD. If this happens, it will regress users setups, and that is
something we try not to do.

Saying "someone else needs to add the code for their FPGA logic" misses
the point - there may not be "someone else" to do that, which means
the only option is to revert your change if it were merged. That in
itself can cause its own user regressions because obviously stuff that
works with this patch stops working.

This is why we're being cautious, and given your responses, it's not
making Andrew or myself feel that there's a reasonable approach being
taken here.

>From everything you have said, I am getting the feeling that using
XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is just
wrong. Given that we're talking about an implementation that has been
synthesized at 2.5G and can't operate slower, maybe there's some way
that could be created to specify that in DT?

e.g. (and I'm sure the DT folk aren't going to like it)...

	xlnx,axi-ethernet-X.YY.Z-2.5G

(where X.YY.Z is the version) for implementations that can _only_ do
2.5G, and leave all other implementations only doing 1G and below.

Or maybe some DT property. Or something else.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From bmasney at redhat.com  Wed Mar 12 12:40:35 2025
From: bmasney at redhat.com (Brian Masney)
Date: Wed, 12 Mar 2025 15:40:35 -0400
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as
 built-in
In-Reply-To: <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
 <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org>
 <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
Message-ID: <Z9HjMyjzE9XlqrEj@x1>

Hi Christopher,

On Wed, Mar 12, 2025 at 12:10:56PM +0100, Christopher Obbard wrote:
> For reference, I am working on updating initramfs generation tools in
> Debian/Fedora to include the required interconnect modules. Currently
> the interconnect drivers are built as modules in these distros, but
> are not included in the initrd. That is where my confusion initially
> stemmed from.

>From a Fedora and centos-stream-9/10 perspective, we have dracut
updated so that the interconnect modules are included in the initramfs
by default.

https://github.com/dracutdevs/dracut/blob/master/modules.d/90kernel-modules/module-setup.sh#L74

Let me know if you are seeing a specific issue with the initramfs on
Fedora and I can help you.

We also configured all of the QC pinctrl drivers to be modules in
Fedora, and this causes a large number of probe deferrals on boot up.
One of the boots I measured was about a half second:

https://lore.kernel.org/linux-embedded/Z6J3WpeJKIKENC81 at x13s/

Everything eventually loads and works as expected though. The upstream
defconfig configures most of the pinctrl drivers to be built in for
Qualcomm.

Brian



From nunodasneves at linux.microsoft.com  Wed Mar 12 12:44:38 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Wed, 12 Mar 2025 12:44:38 -0700
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com>
Message-ID: <5e3e8c30-912c-4fe3-bfac-1ae21242473b@linux.microsoft.com>

On 3/10/2025 6:01 AM, Tianyu Lan wrote:
> On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
> <nunodasneves at linux.microsoft.com> wrote:
>>
>> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
>> SynIC event ring buffer for each SINT.
>>
>> This will be used by the mshv driver, but must be tracked independently
>> since the driver module could be removed and re-inserted.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> 
> It's better to expose a function to check the tail instead of exposing
> hv_synic_eventring_tail directly.
> 
What is the advantage of using a function for this? We need to both set
and get the tail.

> BTW, how does mshv driver use hv_synic_eventring_tail? Which patch
> uses it in this series?
>
This variable stores indices into the synic eventring page (one for each
SINT, and per-cpu). Each SINT has a ringbuffer of u32 messages. The tail
index points to the latest one.

This is only used for doorbell messages today. The message in this case is
a port number which is used to lookup and invoke a callback, which signals
ioeventfd(s), to notify the VMM of a guest MMIO write.

It is used in patch 10.

Thanks
Nuno
 
> Thanks.
> 
> 
>> ---
>>  drivers/hv/hv_common.c | 34 ++++++++++++++++++++++++++++++++--
>>  1 file changed, 32 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
>> index 252fd66ad4db..2763cb6d3678 100644
>> --- a/drivers/hv/hv_common.c
>> +++ b/drivers/hv/hv_common.c
>> @@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
>>
>>  static struct ctl_table_header *hv_ctl_table_hdr;
>>
>> +/*
>> + * Per-cpu array holding the tail pointer for the SynIC event ring buffer
>> + * for each SINT.
>> + *
>> + * We cannot maintain this in mshv driver because the tail pointer should
>> + * persist even if the mshv driver is unloaded.
>> + */
>> +u8 __percpu **hv_synic_eventring_tail;
>> +EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
>> +
>>  /*
>>   * Hyper-V specific initialization and shutdown code that is
>>   * common across all architectures.  Called from architecture
>> @@ -90,6 +100,9 @@ void __init hv_common_free(void)
>>
>>         free_percpu(hyperv_pcpu_input_arg);
>>         hyperv_pcpu_input_arg = NULL;
>> +
>> +       free_percpu(hv_synic_eventring_tail);
>> +       hv_synic_eventring_tail = NULL;
>>  }
>>
>>  /*
>> @@ -372,6 +385,11 @@ int __init hv_common_init(void)
>>                 BUG_ON(!hyperv_pcpu_output_arg);
>>         }
>>
>> +       if (hv_root_partition()) {
>> +               hv_synic_eventring_tail = alloc_percpu(u8 *);
>> +               BUG_ON(hv_synic_eventring_tail == NULL);
>> +       }
>> +
>>         hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
>>                                     GFP_KERNEL);
>>         if (!hv_vp_index) {
>> @@ -460,6 +478,7 @@ void __init ms_hyperv_late_init(void)
>>  int hv_common_cpu_init(unsigned int cpu)
>>  {
>>         void **inputarg, **outputarg;
>> +       u8 **synic_eventring_tail;
>>         u64 msr_vp_index;
>>         gfp_t flags;
>>         const int pgcount = hv_output_page_exists() ? 2 : 1;
>> @@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
>>         inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
>>
>>         /*
>> -        * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
>> -        * allocated if this CPU was previously online and then taken offline
>> +        * The per-cpu memory is already allocated if this CPU was previously
>> +        * online and then taken offline
>>          */
>>         if (!*inputarg) {
>>                 mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
>> @@ -485,6 +504,17 @@ int hv_common_cpu_init(unsigned int cpu)
>>                         *outputarg = (char *)mem + HV_HYP_PAGE_SIZE;
>>                 }
>>
>> +               if (hv_root_partition()) {
>> +                       synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
>> +                       *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
>> +                                                       sizeof(u8), flags);
>> +
>> +                       if (unlikely(!*synic_eventring_tail)) {
>> +                               kfree(mem);
>> +                               return -ENOMEM;
>> +                       }
>> +               }
>> +
>>                 if (!ms_hyperv.paravisor_present &&
>>                     (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
>>                         ret = set_memory_decrypted((unsigned long)mem, pgcount);
>> --
>> 2.34.1
>>
>>
> 
> 



From andriy.shevchenko at linux.intel.com  Wed Mar 12 12:49:21 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Wed, 12 Mar 2025 21:49:21 +0200
Subject: [PATCH v1 1/1] clkdev: Mark some functions with __printf() attribute
Message-ID: <20250312194921.103004-1-andriy.shevchenko@linux.intel.com>

Some of the functions are using printf() type of format, and
compiler is not happy about them as is:

drivers/clk/clkdev.c:185:17: error: function ?vclkdev_alloc? might be a candidate for  gnu_printf? format attribute [-Werror=suggest-attribute=format]
drivers/clk/clkdev.c:224:9: error: function ?vclkdev_create? might be a candidate for  gnu_printf? format attribute [-Werror=suggest-attribute=format]
drivers/clk/clkdev.c:314:9: error: function ?__clk_register_clkdev? might be a candidate for ?gnu_printf? format attribute [-Werror=suggest-attribute=format]

Fix the compilation errors by adding __printf() attributes.

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/clk/clkdev.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 2f83fb97c6fb..e0bede6350e1 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -153,7 +153,7 @@ struct clk_lookup_alloc {
 	char	con_id[MAX_CON_ID];
 };
 
-static struct clk_lookup * __ref
+static __printf(3, 0) struct clk_lookup * __ref
 vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
 	va_list ap)
 {
@@ -215,7 +215,7 @@ vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
 	return &cla->cl;
 }
 
-static struct clk_lookup *
+static __printf(3, 0) struct clk_lookup *
 vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
 	va_list ap)
 {
@@ -303,9 +303,8 @@ void clkdev_drop(struct clk_lookup *cl)
 }
 EXPORT_SYMBOL(clkdev_drop);
 
-static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
-						const char *con_id,
-						const char *dev_id, ...)
+static __printf(3, 4) struct clk_lookup *
+__clk_register_clkdev(struct clk_hw *hw, const char *con_id, const char *dev_id, ...)
 {
 	struct clk_lookup *cl;
 	va_list ap;
-- 
2.47.2



From adrian.larumbe at collabora.com  Wed Mar 12 13:05:14 2025
From: adrian.larumbe at collabora.com (Adrian Larumbe)
Date: Wed, 12 Mar 2025 20:05:14 +0000
Subject: [RFC PATCH 4/5] drm/panthor: Add support for protected memory
 allocation in panthor
In-Reply-To: <821252c96ab2ab3e2d8ef211a09f8b171719baaa.1738228114.git.florent.tomasin@arm.com>
References: <cover.1738228114.git.florent.tomasin@arm.com>
 <821252c96ab2ab3e2d8ef211a09f8b171719baaa.1738228114.git.florent.tomasin@arm.com>
Message-ID: <yzshale7kmhdkjjmdcjt7hsekrftor66nshdnxlmc4ji3wuexd@5ptz7dtze7ez>

Hi Florent,

There's a chance whatever I say here's already been discussed in the
review before. If that were the case, ignore it without further ado.

On 30.01.2025 13:09, Florent Tomasin wrote:
> This patch allows Panthor to allocate buffer objects from a
> protected heap. The Panthor driver should be seen as a consumer
> of the heap and not an exporter.
>
> To help with the review of this patch, here are important information
> about the Mali GPU protected mode support:
> - On CSF FW load, the Panthor driver must allocate a protected
>   buffer object to hold data to use by the FW when in protected
>   mode. This protected buffer object is owned by the device
>   and does not belong to a process.
> - On CSG creation, the Panthor driver must allocate a protected
>   suspend buffer object for the FW to store data when suspending
>   the CSG while in protected mode. The kernel owns this allocation
>   and does not allow user space mapping. The format of the data
>   in this buffer is only known by the FW and does not need to be
>   shared with other entities.
>
> To summarize, Mali GPUs require allocations of protected buffer
> objects at the kernel level.
>
> * How is the protected heap accessed by the Panthor driver?
> The driver will retrieve the protected heap using the name of the
> heap provided to the driver via the DTB as attribute.
> If the heap is not yet available, the panthor driver will defer
> the probe until created. It is an integration error to provide
> a heap name that does not exist or is never created in the
> DTB node.
>
> * How is the Panthor driver allocating from the heap?
> Panthor is calling the DMA heap allocation function
> and obtains a DMA buffer from it. This buffer is then
> registered to GEM via PRIME by importing the DMA buffer.
>
> Signed-off-by: Florent Tomasin <florent.tomasin at arm.com>
> ---
>  drivers/gpu/drm/panthor/Kconfig          |  1 +
>  drivers/gpu/drm/panthor/panthor_device.c | 22 ++++++++++-
>  drivers/gpu/drm/panthor/panthor_device.h |  7 ++++
>  drivers/gpu/drm/panthor/panthor_fw.c     | 36 +++++++++++++++--
>  drivers/gpu/drm/panthor/panthor_fw.h     |  2 +
>  drivers/gpu/drm/panthor/panthor_gem.c    | 49 ++++++++++++++++++++++--
>  drivers/gpu/drm/panthor/panthor_gem.h    | 16 +++++++-
>  drivers/gpu/drm/panthor/panthor_heap.c   |  2 +
>  drivers/gpu/drm/panthor/panthor_sched.c  |  5 ++-
>  9 files changed, 130 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/panthor/Kconfig b/drivers/gpu/drm/panthor/Kconfig
> index 55b40ad07f3b..c0208b886d9f 100644
> --- a/drivers/gpu/drm/panthor/Kconfig
> +++ b/drivers/gpu/drm/panthor/Kconfig
> @@ -7,6 +7,7 @@ config DRM_PANTHOR
>  	depends on !GENERIC_ATOMIC64  # for IOMMU_IO_PGTABLE_LPAE
>  	depends on MMU
>  	select DEVFREQ_GOV_SIMPLE_ONDEMAND
> +	select DMABUF_HEAPS
>  	select DRM_EXEC
>  	select DRM_GEM_SHMEM_HELPER
>  	select DRM_GPUVM
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index 00f7b8ce935a..1018e5c90a0e 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -4,7 +4,9 @@
>  /* Copyright 2023 Collabora ltd. */
>
>  #include <linux/clk.h>
> +#include <linux/dma-heap.h>
>  #include <linux/mm.h>
> +#include <linux/of.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> @@ -102,6 +104,9 @@ void panthor_device_unplug(struct panthor_device *ptdev)
>  	panthor_mmu_unplug(ptdev);
>  	panthor_gpu_unplug(ptdev);
>
> +	if (ptdev->protm.heap)
> +		dma_heap_put(ptdev->protm.heap);
> +
Probably beyond the point here, but I think in this case you might be
better off using the CMA API directly rather than going through a
hypothetical extension of dma-heaps.

>  	pm_runtime_dont_use_autosuspend(ptdev->base.dev);
>  	pm_runtime_put_sync_suspend(ptdev->base.dev);
>
> @@ -172,6 +177,7 @@ int panthor_device_init(struct panthor_device *ptdev)
>  	u32 *dummy_page_virt;
>  	struct resource *res;
>  	struct page *p;
> +	const char *protm_heap_name;
>  	int ret;
>
>  	ret = panthor_gpu_coherency_init(ptdev);
> @@ -246,9 +252,19 @@ int panthor_device_init(struct panthor_device *ptdev)
>  			return ret;
>  	}
>
> +	/* If a protected heap is specified but not found, defer the probe until created */
> +	if (!of_property_read_string(ptdev->base.dev->of_node, "protected-heap-name",
> +				     &protm_heap_name)) {
> +		ptdev->protm.heap = dma_heap_find(protm_heap_name);
> +		if (!ptdev->protm.heap) {
> +			ret = -EPROBE_DEFER;
> +			goto err_rpm_put;
> +		}
> +	}

Cince none of the DMA memory is going to be shared with othe devices, I don't
think a dma-heap interface is the right tool for the job here. Whatever
protected contiguous memory you allocate for protected mode, it'll always remain
within the boundaries of the driver, so maybe just do the usual sequence here:

of_reserved_mem_device_init();
dev_get_cma_area();
cma_alloc();

>  	ret = panthor_gpu_init(ptdev);
>  	if (ret)
> -		goto err_rpm_put;
> +		goto err_dma_heap_put;
>
>  	ret = panthor_mmu_init(ptdev);
>  	if (ret)
> @@ -286,6 +302,10 @@ int panthor_device_init(struct panthor_device *ptdev)
>  err_unplug_gpu:
>  	panthor_gpu_unplug(ptdev);
>
> +err_dma_heap_put:
> +	if (ptdev->protm.heap)
> +		dma_heap_put(ptdev->protm.heap);
> +
>  err_rpm_put:
>  	pm_runtime_put_sync_suspend(ptdev->base.dev);
>  	return ret;
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index 0e68f5a70d20..406de9e888e2 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -7,6 +7,7 @@
>  #define __PANTHOR_DEVICE_H__
>
>  #include <linux/atomic.h>
> +#include <linux/dma-heap.h>
>  #include <linux/io-pgtable.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/sched.h>
> @@ -190,6 +191,12 @@ struct panthor_device {
>
>  	/** @fast_rate: Maximum device clock frequency. Set by DVFS */
>  	unsigned long fast_rate;
> +
> +	/** @protm: Protected mode related data. */
> +	struct {
> +		/** @heap: Pointer to the protected heap */
> +		struct dma_heap *heap;
> +	} protm;
>  };
>
>  struct panthor_gpu_usage {
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
> index 4a2e36504fea..7822af1533b4 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.c
> +++ b/drivers/gpu/drm/panthor/panthor_fw.c
> @@ -458,6 +458,7 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev,
>
>  	mem = panthor_kernel_bo_create(ptdev, ptdev->fw->vm, SZ_8K,
>  				       DRM_PANTHOR_BO_NO_MMAP,
> +				       0,
>  				       DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
>  				       DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
>  				       PANTHOR_VM_KERNEL_AUTO_VA);
> @@ -491,6 +492,28 @@ panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size)
>  {
>  	return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
>  					DRM_PANTHOR_BO_NO_MMAP,
> +					0,
> +					DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
> +					PANTHOR_VM_KERNEL_AUTO_VA);
> +}
> +
> +/**
> + * panthor_fw_alloc_protm_suspend_buf_mem() - Allocate a protm suspend buffer
> + * for a command stream group.
> + * @ptdev: Device.
> + * @size: Size of the protm suspend buffer.
> + *
> + * Return: A valid pointer in case of success, NULL if no protected heap, an ERR_PTR() otherwise.
> + */
> +struct panthor_kernel_bo *
> +panthor_fw_alloc_protm_suspend_buf_mem(struct panthor_device *ptdev, size_t size)
> +{
> +	if (!ptdev->protm.heap)
> +		return NULL;
> +
> +	return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
> +					DRM_PANTHOR_BO_NO_MMAP,
> +					DRM_PANTHOR_KBO_PROTECTED_HEAP,
>  					DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
>  					PANTHOR_VM_KERNEL_AUTO_VA);
>  }

Unify the two above into a single interface like:
struct panthor_kernel_bo *
panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size, bool protected)

and then

return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
				DRM_PANTHOR_BO_NO_MMAP,
				(protected ? DRM_PANTHOR_KBO_PROTECTED_HEAP : 0)
				DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
				PANTHOR_VM_KERNEL_AUTO_VA);

> @@ -503,6 +526,7 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
>  	ssize_t vm_pgsz = panthor_vm_page_size(ptdev->fw->vm);
>  	struct panthor_fw_binary_section_entry_hdr hdr;
>  	struct panthor_fw_section *section;
> +	bool is_protm_section = false;
>  	u32 section_size;
>  	u32 name_len;
>  	int ret;
> @@ -541,10 +565,13 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
>  		return -EINVAL;
>  	}
>
> -	if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) {
> +	if ((hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) && !ptdev->protm.heap) {
>  		drm_warn(&ptdev->base,
>  			 "Firmware protected mode entry not be supported, ignoring");
>  		return 0;
> +	} else if ((hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_PROT) && ptdev->protm.heap) {
> +		drm_info(&ptdev->base, "Firmware protected mode entry supported");
> +		is_protm_section = true;
>  	}
>
>  	if (hdr.va.start == CSF_MCU_SHARED_REGION_START &&
> @@ -610,9 +637,10 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
>  			vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED;
>
>  		section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev),
> -							section_size,
> -							DRM_PANTHOR_BO_NO_MMAP,
> -							vm_map_flags, va);
> +					section_size,
> +					DRM_PANTHOR_BO_NO_MMAP,
> +					(is_protm_section ? DRM_PANTHOR_KBO_PROTECTED_HEAP : 0),
> +					vm_map_flags, va);
>  		if (IS_ERR(section->mem))
>  			return PTR_ERR(section->mem);
>
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor/panthor_fw.h
> index 22448abde992..29042d0dc60c 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.h
> +++ b/drivers/gpu/drm/panthor/panthor_fw.h
> @@ -481,6 +481,8 @@ panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev,
>  				 u32 *input_fw_va, u32 *output_fw_va);
>  struct panthor_kernel_bo *
>  panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size);
> +struct panthor_kernel_bo *
> +panthor_fw_alloc_protm_suspend_buf_mem(struct panthor_device *ptdev, size_t size);
>
>  struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev);
>
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> index 8244a4e6c2a2..88caf928acd0 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -9,10 +9,14 @@
>
>  #include <drm/panthor_drm.h>
>
> +#include <uapi/linux/dma-heap.h>
> +
>  #include "panthor_device.h"
>  #include "panthor_gem.h"
>  #include "panthor_mmu.h"
>
> +MODULE_IMPORT_NS(DMA_BUF);
> +
>  static void panthor_gem_free_object(struct drm_gem_object *obj)
>  {
>  	struct panthor_gem_object *bo = to_panthor_bo(obj);
> @@ -31,6 +35,7 @@ static void panthor_gem_free_object(struct drm_gem_object *obj)
>   */
>  void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
>  {
> +	struct dma_buf *dma_bo = NULL;
>  	struct panthor_vm *vm;
>  	int ret;
>
> @@ -38,6 +43,10 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
>  		return;
>
>  	vm = bo->vm;
> +
> +	if (bo->flags & DRM_PANTHOR_KBO_PROTECTED_HEAP)
> +		dma_bo = bo->obj->import_attach->dmabuf;
> +
>  	panthor_kernel_bo_vunmap(bo);
>
>  	if (drm_WARN_ON(bo->obj->dev,
> @@ -51,6 +60,9 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
>  	panthor_vm_free_va(vm, &bo->va_node);
>  	drm_gem_object_put(bo->obj);
>
> +	if (dma_bo)
> +		dma_buf_put(dma_bo);
> +
>  out_free_bo:
>  	panthor_vm_put(vm);
>  	kfree(bo);
> @@ -62,6 +74,7 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
>   * @vm: VM to map the GEM to. If NULL, the kernel object is not GPU mapped.
>   * @size: Size of the buffer object.
>   * @bo_flags: Combination of drm_panthor_bo_flags flags.
> + * @kbo_flags: Combination of drm_panthor_kbo_flags flags.
>   * @vm_map_flags: Combination of drm_panthor_vm_bind_op_flags (only those
>   * that are related to map operations).
>   * @gpu_va: GPU address assigned when mapping to the VM.
> @@ -72,9 +85,11 @@ void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo)
>   */
>  struct panthor_kernel_bo *
>  panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> -			 size_t size, u32 bo_flags, u32 vm_map_flags,
> +			 size_t size, u32 bo_flags, u32 kbo_flags, u32 vm_map_flags,
>  			 u64 gpu_va)
>  {
> +	struct dma_buf *dma_bo = NULL;
> +	struct drm_gem_object *gem_obj = NULL;
>  	struct drm_gem_shmem_object *obj;
>  	struct panthor_kernel_bo *kbo;
>  	struct panthor_gem_object *bo;
> @@ -87,14 +102,38 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
>  	if (!kbo)
>  		return ERR_PTR(-ENOMEM);
>
> -	obj = drm_gem_shmem_create(&ptdev->base, size);
> +	if (kbo_flags & DRM_PANTHOR_KBO_PROTECTED_HEAP) {
> +		if (!ptdev->protm.heap) {
> +			ret = -EINVAL;
> +			goto err_free_bo;
> +		}
> +
> +		dma_bo = dma_heap_buffer_alloc(ptdev->protm.heap, size,
> +					       DMA_HEAP_VALID_FD_FLAGS, DMA_HEAP_VALID_HEAP_FLAGS);

		dma_heap_buffer_alloc() is a static function, so why do you call it from here?
                I suppose you plan on extending the dma-heap interface in the future?

> +		if (!dma_bo) {
> +			ret = -ENOMEM;
> +			goto err_free_bo;
> +		}
> +
> +		gem_obj = drm_gem_prime_import(&ptdev->base, dma_bo);
> +		if (IS_ERR(gem_obj)) {
> +			ret = PTR_ERR(gem_obj);
> +			goto err_free_dma_bo;
> +		}
> +

If you chose the dma-heap interface because dma-heap offers you an easy
way to create a GEM object from an sgtable, perhaps you could create the
dma-buf right here and do a self-import. That way you wouldn't need to
extend dma-heap.


> +		obj = to_drm_gem_shmem_obj(gem_obj);
> +	} else {
> +		obj = drm_gem_shmem_create(&ptdev->base, size);
> +	}
> +
>  	if (IS_ERR(obj)) {
>  		ret = PTR_ERR(obj);
> -		goto err_free_bo;
> +		goto err_free_dma_bo;
>  	}
>
>  	bo = to_panthor_bo(&obj->base);
>  	kbo->obj = &obj->base;
> +	kbo->flags = kbo_flags;
>  	bo->flags = bo_flags;
>
>  	/* The system and GPU MMU page size might differ, which becomes a
> @@ -124,6 +163,10 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
>  err_put_obj:
>  	drm_gem_object_put(&obj->base);
>
> +err_free_dma_bo:
> +	if (dma_bo)
> +		dma_buf_put(dma_bo);
> +
>  err_free_bo:
>  	kfree(kbo);
>  	return ERR_PTR(ret);
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index e43021cf6d45..d4fe8ae9f0a8 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -13,6 +13,17 @@
>
>  struct panthor_vm;
>
> +/**
> + * enum drm_panthor_kbo_flags -  Kernel buffer object flags, passed at creation time
> + */
> +enum drm_panthor_kbo_flags {
> +	/**
> +	 * @DRM_PANTHOR_KBO_PROTECTED_HEAP: The buffer object will be allocated
> +	 * from a DMA-Buf protected heap.
> +	 */
> +	DRM_PANTHOR_KBO_PROTECTED_HEAP = (1 << 0),
> +};
> +
>  /**
>   * struct panthor_gem_object - Driver specific GEM object.
>   */
> @@ -75,6 +86,9 @@ struct panthor_kernel_bo {
>  	 * @kmap: Kernel CPU mapping of @gem.
>  	 */
>  	void *kmap;
> +
> +	/** @flags: Combination of drm_panthor_kbo_flags flags. */
> +	u32 flags;
>  };
>
>  static inline
> @@ -138,7 +152,7 @@ panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo)
>
>  struct panthor_kernel_bo *
>  panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm,
> -			 size_t size, u32 bo_flags, u32 vm_map_flags,
> +			 size_t size, u32 bo_flags, u32 kbo_flags, u32 vm_map_flags,
>  			 u64 gpu_va);
>
>  void panthor_kernel_bo_destroy(struct panthor_kernel_bo *bo);
> diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c
> index 3796a9eb22af..5395f0d90360 100644
> --- a/drivers/gpu/drm/panthor/panthor_heap.c
> +++ b/drivers/gpu/drm/panthor/panthor_heap.c
> @@ -146,6 +146,7 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev,
>
>  	chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size,
>  					     DRM_PANTHOR_BO_NO_MMAP,
> +					     0,
>  					     DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
>  					     PANTHOR_VM_KERNEL_AUTO_VA);
>  	if (IS_ERR(chunk->bo)) {
> @@ -549,6 +550,7 @@ panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm)
>
>  	pool->gpu_contexts = panthor_kernel_bo_create(ptdev, vm, bosize,
>  						      DRM_PANTHOR_BO_NO_MMAP,
> +						      0,
>  						      DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC,
>  						      PANTHOR_VM_KERNEL_AUTO_VA);
>  	if (IS_ERR(pool->gpu_contexts)) {
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
> index ef4bec7ff9c7..e260ed8aef5b 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -3298,6 +3298,7 @@ group_create_queue(struct panthor_group *group,
>  	queue->ringbuf = panthor_kernel_bo_create(group->ptdev, group->vm,
>  						  args->ringbuf_size,
>  						  DRM_PANTHOR_BO_NO_MMAP,
> +						  0,
>  						  DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
>  						  DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
>  						  PANTHOR_VM_KERNEL_AUTO_VA);
> @@ -3328,6 +3329,7 @@ group_create_queue(struct panthor_group *group,
>  					 queue->profiling.slot_count *
>  					 sizeof(struct panthor_job_profiling_data),
>  					 DRM_PANTHOR_BO_NO_MMAP,
> +					 0,
>  					 DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
>  					 DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
>  					 PANTHOR_VM_KERNEL_AUTO_VA);
> @@ -3435,7 +3437,7 @@ int panthor_group_create(struct panthor_file *pfile,
>  	}
>
>  	suspend_size = csg_iface->control->protm_suspend_size;
> -	group->protm_suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, suspend_size);
> +	group->protm_suspend_buf = panthor_fw_alloc_protm_suspend_buf_mem(ptdev, suspend_size);

I think  you could reuse panthor_fw_alloc_suspend_buf_mem() and extend its interface
so that it takes a boolean for the case you want to allocate a protected buffer.

>  	if (IS_ERR(group->protm_suspend_buf)) {
>  		ret = PTR_ERR(group->protm_suspend_buf);
>  		group->protm_suspend_buf = NULL;
> @@ -3446,6 +3448,7 @@ int panthor_group_create(struct panthor_file *pfile,
>  						   group_args->queues.count *
>  						   sizeof(struct panthor_syncobj_64b),
>  						   DRM_PANTHOR_BO_NO_MMAP,
> +						   0,
>  						   DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
>  						   DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
>  						   PANTHOR_VM_KERNEL_AUTO_VA);
> --
> 2.34.1


Adrian Larumbe


From nunodasneves at linux.microsoft.com  Wed Mar 12 13:17:59 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Wed, 12 Mar 2025 13:17:59 -0700
Subject: [PATCH v5 09/10] hyperv: Add definitions for root partition
 driver to hv headers
In-Reply-To: <CAMvTesB5dCD5Cx+CE8oPQ35OHC+C=tyXbHQ0BNxSABEFVK53Tg@mail.gmail.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-10-git-send-email-nunodasneves@linux.microsoft.com>
 <CAMvTesB5dCD5Cx+CE8oPQ35OHC+C=tyXbHQ0BNxSABEFVK53Tg@mail.gmail.com>
Message-ID: <dba492d0-8640-43c1-80b5-aa8bd1cd618f@linux.microsoft.com>

On 3/10/2025 5:40 AM, Tianyu Lan wrote:
> On Thu, Feb 27, 2025 at 7:11?AM Nuno Das Neves
> <nunodasneves at linux.microsoft.com> wrote:
>>
>> A few additional definitions are required for the mshv driver code
>> (to follow). Introduce those here and clean up a little bit while
>> at it.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> ---
> 
> It may be better to unify data type u8, u16, u32, u64 or __u8, __u16,
> __u32, __u64 in the hvhdk.h.
> 
Agreed, this was an oversight. They should all be the kernel types
without the __ prefix.

Thanks
Nuno

> Others like good.
> 
> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
> 



From robdclark at gmail.com  Wed Mar 12 13:20:45 2025
From: robdclark at gmail.com (Rob Clark)
Date: Wed, 12 Mar 2025 13:20:45 -0700
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <2d47815d-6bee-4d1f-8b60-854763794bf6@arm.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck> <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck> <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
 <20250312164735.GA6561@willie-the-truck> <CAF6AEGskyoemQDrTXh=ewf61e-hVzWMjmqe=nX2J-65W5-M6Zw@mail.gmail.com>
 <2d47815d-6bee-4d1f-8b60-854763794bf6@arm.com>
Message-ID: <CAF6AEGvhixYvXghvD+itnSDjr7bO4i3Ls0Y-kXC-ohFN=CS0PQ@mail.gmail.com>

On Wed, Mar 12, 2025 at 11:01?AM Robin Murphy <robin.murphy at arm.com> wrote:
>
> On 12/03/2025 5:23 pm, Rob Clark wrote:
> > On Wed, Mar 12, 2025 at 9:47?AM Will Deacon <will at kernel.org> wrote:
> >>
> >> On Wed, Mar 12, 2025 at 07:59:52AM -0700, Rob Clark wrote:
> >>> On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
> >>>> On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> >>>>> On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> >>>>>> On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> >>>>>>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> >>>>>>> index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> >>>>>>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> >>>>>>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> >>>>>>> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> >>>>>>>                                      struct arm_smmu_context_fault_info *cfi)
> >>>>>>>   {
> >>>>>>>        cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> >>>>>>> +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> >>>>>>>        cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> >>>>>>> -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> >>>>>>> +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> >>>>>>> +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> >>>>>>
> >>>>>> We already have an implementation hook (->get_fault_info()) which the
> >>>>>> qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> >>>>>> That thing dumps these registers already so if we're moving that into
> >>>>>> the core SMMU driver, let's get rid of the hook and move everybody over
> >>>>>> rather than having it done in both places.
> >>>>>
> >>>>> As you probably saw, the next commit moves over
> >>>>> qcom_adreno_smmu_get_fault_info() to use this. The current back door
> >>>>> used by drm/msm to access these functions is specific to adreno_smmu
> >>>>> and there isn't an equivalent interface to allow it to call a generic
> >>>>> SMMU function so it isn't possible to move it entirely to the core. At
> >>>>> least not without a bigger refactoring that isn't justified for this
> >>>>> series that is just trying to fix things.
> >>>>
> >>>> Ok :(
> >>>>
> >>>>>>>        cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> >>>>>>> +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> >>>>>>
> >>>>>> I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> >>>>>> it for stage-2 domains.
> >>>>>>
> >>>>> Does it matter if we read the register though, as long as users are
> >>>>> aware of this and don't use its value for anything?
> >>>>
> >>>> I think the contents are "UNKNOWN", so it could be hugely confusing even
> >>>> if they just got logged someplace. Why is it difficult to avoid touching
> >>>> it for stage-2?
> >>>>
> >>> Fwiw, we are only ever using stage-1
> >>
> >> Sure, but this is in arm-smmu.c which is used by other people and supports
> >> both stages.
> >
> > Sure, but no one else is using this field in the fault-info.  So maybe
> > the addition of a comment in the struct would be enough if it isn't
> > going to cause an SError/etc to read it for S2 cb?
>
> Any worthwhile comment isn't going to be significantly shorter or
> clearer than 1 extra line of "if (smmu_domain->stage ==
> ARM_SMMU_DOMAIN_S1)"...

Just that smmu_domain isn't passed to
arm_smmu_read_context_fault_info(), so it would add some extra churn
on top of that one extra line

> TBH it's the Qualcomm register-middle-man firmware I'd be more worried
> about than real hardware, given how touchy it can be even with register
> accesses which *should* be well defined. But then I guess it also has
> the habit of killing the system if anything other than the GPU dares
> cause a fault in the first place, so maybe it OK?

If we have qc hyp, then we don't get S2 in the first place ;-)

BR,
-R

> If anyone still uses Arm Fast Models SMMUv1/2 components it'll probably
> squawk an annoying warning there too - ISTR I had at least one patch
> motivated by that in the past.
>
> Thanks,
> Robin.


From nathan at kernel.org  Wed Mar 12 13:21:32 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Wed, 12 Mar 2025 21:21:32 +0100
Subject: [PATCH v7 1/1] watchdog: aspeed: Update bootstatus handling
In-Reply-To: <20250113093737.845097-2-chin-ting_kuo@aspeedtech.com>
References: <20250113093737.845097-1-chin-ting_kuo@aspeedtech.com>
 <20250113093737.845097-2-chin-ting_kuo@aspeedtech.com>
Message-ID: <20250312202132.GA1072616@ax162>

On Mon, Jan 13, 2025 at 05:37:37PM +0800, Chin-Ting Kuo wrote:
> The boot status in the watchdog device struct is updated during
> controller probe stage. Application layer can get the boot status
> through the command, cat /sys/class/watchdog/watchdogX/bootstatus.
> The bootstatus can be,
> WDIOF_CARDRESET => System is reset due to WDT timeout occurs.
> Others          => Other reset events, e.g., power on reset.
> 
> On ASPEED platforms, boot status is recorded in the SCU registers.
> - AST2400: Only a bit is used to represent system reset triggered by
>            any WDT controller.
> - AST2500/AST2600: System reset triggered by different WDT controllers
>                    can be distinguished by different SCU bits.
> 
> Besides, on AST2400 and AST2500, since alternating boot event is
> also triggered by using WDT timeout mechanism, it is classified
> as WDIOF_CARDRESET.
> 
> Signed-off-by: Chin-Ting Kuo <chin-ting_kuo at aspeedtech.com>
> ---
>  drivers/watchdog/aspeed_wdt.c | 81 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 79 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
...
> +static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
> +					 struct aspeed_wdt *wdt)
> +{
> +	const struct resource *res;
> +	struct aspeed_wdt_scu scu = wdt->cfg->scu;
> +	struct regmap *scu_base;
> +	u32 reset_mask_width;
> +	u32 reset_mask_shift;
> +	u32 idx = 0;
> +	u32 status;
> +	int ret;
> +
> +	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
> +		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);

This division breaks the build when CONFIG_ARM_LPAE is enabled, which
selects CONFIG_PHYS_ADDR_T_64BIT, turning resource_size_t into a 64-bit
type.

$ make -skj"$(nproc)" ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- mrproper multi_v7_lpae_defconfig all
arm-linux-gnueabi-ld: drivers/watchdog/aspeed_wdt.o: in function `aspeed_wdt_update_bootstatus':
drivers/watchdog/aspeed_wdt.c:257:(.text+0x80c): undefined reference to `__aeabi_uldivmod'

> +	}
> +
> +	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
> +	if (IS_ERR(scu_base)) {
> +		wdt->wdd.bootstatus = WDIOS_UNKNOWN;
> +		return;
> +	}
> +
> +	ret = regmap_read(scu_base, scu.reset_status_reg, &status);
> +	if (ret) {
> +		wdt->wdd.bootstatus = WDIOS_UNKNOWN;
> +		return;
> +	}
> +
> +	reset_mask_width = hweight32(scu.wdt_reset_mask);
> +	reset_mask_shift = scu.wdt_reset_mask_shift +
> +			   reset_mask_width * idx;
> +
> +	if (status & (scu.wdt_reset_mask << reset_mask_shift))
> +		wdt->wdd.bootstatus = WDIOF_CARDRESET;
> +
> +	/* clear wdt reset event flag */
> +	if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") ||
> +	    of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) {
> +		ret = regmap_read(scu_base, scu.reset_status_reg, &status);
> +		if (!ret) {
> +			status &= ~(scu.wdt_reset_mask << reset_mask_shift);
> +			regmap_write(scu_base, scu.reset_status_reg, status);
> +		}
> +	} else {
> +		regmap_write(scu_base, scu.reset_status_reg,
> +			     scu.wdt_reset_mask << reset_mask_shift);
> +	}
> +}
> +

Cheers,
Nathan


From arnd at arndb.de  Wed Mar 12 13:25:59 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 12 Mar 2025 21:25:59 +0100
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for arm64
In-Reply-To: <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
Message-ID: <45171fb1-7533-449f-83d4-066d038c839f@app.fastmail.com>

On Wed, Mar 12, 2025, at 19:33, Roman Kisel wrote:
> On 3/10/2025 3:18 PM, Michael Kelley wrote:
>
> That's a minimal extension, its surprise factor is very low. It has not
> been seen to cause issues. If no one has strong opinions against that,
> I'd send that in V6.
>

Works for me. Thanks for your detailed explanations.

       Arnd


From wei.liu at kernel.org  Wed Mar 12 13:31:26 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Wed, 12 Mar 2025 20:31:26 +0000
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
Message-ID: <Z9HvHsGyXDnN38_B@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Wed, Mar 12, 2025 at 11:33:11AM -0700, Roman Kisel wrote:
> 
> 
> On 3/10/2025 3:18 PM, Michael Kelley wrote:
> > From: Arnd Bergmann <arnd at arndb.de> Sent: Monday, March 10, 2025 2:21 PM
> > > 
> > > On Mon, Mar 10, 2025, at 22:01, Michael Kelley wrote:
> > > > From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
> > > > > >   config HYPERV_VTL_MODE
> > > > > >   	bool "Enable Linux to boot in VTL context"
> > > > > > -	depends on X86_64 && HYPERV
> > > > > > +	depends on (X86_64 || ARM64)
> > > > > >   	depends on SMP
> > > > > > +	select OF_EARLY_FLATTREE
> > > > > > +	select OF
> > > > > >   	default n
> > > > > >   	help
> > > > > 
> > > > > Having the dependency below the top-level Kconfig entry feels a little
> > > > > counterintuitive. You could flip that back as it was before by doing
> > > > > 
> > > > >        select HYPERV_VTL_MODE if !ACPI
> > > > >        depends on ACPI || SMP
> > > > > 
> > > > > in the HYPERV option, leaving the dependency on HYPERV in
> > > > > HYPERV_VTL_MODE.
> > > > 
> > > > I would argue that we don't ever want to implicitly select
> > > > HYPERV_VTL_MODE because of some other config setting or
> > > > lack thereof.  VTL mode is enough of a special case that it should
> > > > only be explicitly selected. If someone omits ACPI, then HYPERV
> > > > should not be selectable unless HYPERV_VTL_MODE is explicitly
> > > > selected.
> > > > 
> > > > The last line of the comment for HYPERV_VTL_MODE says
> > > > "A kernel built with this option must run at VTL2, and will not run
> > > > as a normal guest."  In other words, don't choose this unless you
> > > > 100% know that VTL2 is what you want.
> > > 
> > > It sounds like the latter is the real problem: enabling a feature
> > > should never prevent something else from working. Can you describe
> > > what VTL context is and why it requires an exception to a rather
> > > fundamental rule here? If you build a kernel that runs on every
> > > single piece of arm64 hardware and every hypervisor, why can't
> > > you add HYPERV_VTL_MODE to that as an option?
> > > 
> 
> In the VTL mode, we're running the kernel as secure firmware inside the
> guest (one might see VTL2 working as Intel SMM or Secure World on ARM).
> 
> [...]
> 
> > 
> > Ideally, a Linux kernel image could detect at runtime what VTL it is
> > running at, and "do the right thing". Unfortunately, on x86 Linux this
> > has proved difficult (or perhaps impossible) because the amount of
> > boot-time setup required to ask the question about the current VTL
> > is significant. The idiosyncrasies and historical baggage of x86 requires
> > that Linux do some x86-specific initialization steps for VTL > 0
> > before the question can be asked. Hence the introduction of
> > CONFIG_HYPERV_VTL_MODE, and the behavior that when it is
> > selected, the kernel image won't run normally in VTL 0.
> > 
> > I'll go out on a limb and say that I suspect on arm64 a runtime
> > determination based on querying the VTL *could* be made (though
> > I'm not the person writing the code). But taking advantage of that
> > on arm64 produces an undesirable dichotomy with x86.
> 
> On arm64 that is much easier, I agree. On x86 we'd need a kludge of
> 
> static void __naked __init __aligned(4096) early_hvcall_pg(void)
> {
> 	/*
> 	 * Fill the early hvcall page with `0xF1` aka `INT1` to catch
> 	 * programming errors. The hypervisor will overlay the page with
> 	 * the vendor-specific code sequences to make hypercalls on x86(_64).
> 	 */
> 	asm (".skip 4096, 0xf1");
> }
> 
> static u8 __init early_hvcall_pg_input[4096] __attribute__((aligned(4096)));
> static u8 __init early_hvcall_pg_output[4096]
> __attribute__((aligned(4096)));
> 
> static void __init early_connect_to_hv(void)
> {
> 	union hv_x64_msr_hypercall_contents hypercall_msr;
> 	u64 guest_id;
> 
> 	guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
> 	wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
> 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
> 	hypercall_msr.enable = 1;
> 	hypercall_msr.guest_physical_address =
> __phys_to_pfn(virt_to_phys(early_hvcall_pg));
> 	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
> }
> 
> or variations thereof.

OT here but what's stopping us from doing this on x86?

It seems to me there is some value in setting up the hypercall page as
early as possible. The same page can be used through the lifetime of the
partition. The early input and output pages should be reclaimed.

Also, since the hypervisor will insert an overlay page, it makes sense
to not allocate a page from Linux at all. When I ported Xen to run as
a guest on Hyper-V, I used that approach. The setup worked just fine.

All being said, things work today, so I'm in no hurry to change things.

Wei.


From conor at kernel.org  Wed Mar 12 13:31:36 2025
From: conor at kernel.org (Conor Dooley)
Date: Wed, 12 Mar 2025 20:31:36 +0000
Subject: [PATCH v3 1/3] dt-bindings: reset: Add compatible for Amlogic
 A4/A5 Reset Controller
In-Reply-To: <84612c6b-621d-47cc-8a2e-41d1fa42f0fe@amlogic.com>
References: <20240918074211.8067-1-zelong.dong@amlogic.com>
 <20240918074211.8067-2-zelong.dong@amlogic.com>
 <a5d9b775dd860d8f2bbf174300a2e3161b654035.camel@pengutronix.de>
 <20240918-delirious-skiing-224172be96d4@squawk>
 <84612c6b-621d-47cc-8a2e-41d1fa42f0fe@amlogic.com>
Message-ID: <20250312-atlas-paver-0f0e888a641b@spud>

On Tue, Mar 11, 2025 at 05:48:26PM +0800, Kelvin Zhang wrote:
> 
> 
> On 2024/9/18 16:01, Conor Dooley wrote:
> > On Wed, Sep 18, 2024 at 09:51:28AM +0200, Philipp Zabel wrote:
> > > On Mi, 2024-09-18 at 15:42 +0800, zelong dong wrote:
> > > > From: Zelong Dong<zelong.dong at amlogic.com>
> > > > 
> > > > Add new compatible for Amlogic A4/A5 Reset Controller
> > > > 
> > > > Signed-off-by: Zelong Dong<zelong.dong at amlogic.com>
> > > > Acked-by: Conor Dooley<conor.dooley at microchip.com>
> > > > ---
> > > >   .../bindings/reset/amlogic,meson-reset.yaml   | 23 ++++++++++++-------
> > > >   1 file changed, 15 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
> > > > index 695ef38a7bb3..0ad81fe7b629 100644
> > > > --- a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
> > > > +++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
> > > > @@ -12,14 +12,21 @@ maintainers:
> > > >   properties:
> > > >     compatible:
> > > > -    enum:
> > > > -      - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
> > > > -      - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
> > > > -      - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
> > > > -      - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
> > > > -      - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
> > > > -      - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
> > > > -      - amlogic,t7-reset
> > > > +    oneOf:
> > > > +      - items:
> > > I'm not well versed in preferred dt-bindings style, but this items
> > > looks superfluous to me. It only contains a single enum.
> > Oh, ye. Good spot.
> 
> Hello Philipp, Conor,
> Sorry for the late reply.
> 
> Do you mean to use 'amlogic,meson-s4-reset' for A4 and A5 directly, without
> the fallback?

No. We are saying that

+      - items:
+          - enum:
+              - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs

is pointless duplication, because your "items" list only has only
entry in it (the enum) and you could just remove the "- items" line
entirely and have the same outcome.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/622b73bb/attachment.sig>

From oliver.upton at linux.dev  Wed Mar 12 14:04:37 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 14:04:37 -0700
Subject: [PATCH] KVM: arm64: Writable TGRAN*_2
In-Reply-To: <20250306184013.30008-1-sebott@redhat.com>
References: <20250306184013.30008-1-sebott@redhat.com>
Message-ID: <174181344705.1158293.6270593433232646712.b4-ty@linux.dev>

On Thu, 06 Mar 2025 19:40:13 +0100, Sebastian Ott wrote:
> Allow userspace to write the safe (NI) value for ID_AA64MMFR0_EL1.TGRAN*_2.
> Disallow to change these fields for NV since kvm provides a sanitized view
> for them based on the PAGE_SIZE.
> Also add these bits to the set_id_regs selftest.
> 
> 

Applied to next, thanks!

[1/1] KVM: arm64: Writable TGRAN*_2
      https://git.kernel.org/kvmarm/kvmarm/c/edfd826b8be7

--
Best,
Oliver


From oliver.upton at linux.dev  Wed Mar 12 14:08:26 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 14:08:26 -0700
Subject: [PATCH v3 2/6] KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
In-Reply-To: <20250312-pmc-v3-2-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
 <20250312-pmc-v3-2-0411cab5dc3d@daynix.com>
Message-ID: <Z9H3yuv96gBPty76@linux.dev>

Hi Akihiko,

On Wed, Mar 12, 2025 at 08:55:56PM +0900, Akihiko Odaki wrote:

[...]

> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 962f985977c2..fc09eec3fd94 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -951,6 +951,10 @@ int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
>  
>  	switch (attr->group) {
>  	case KVM_ARM_VCPU_PMU_V3_CTRL:
> +		if (!kvm_vcpu_has_pmu(vcpu)) {
> +			ret = -ENODEV;
> +			break;
> +		}
>  		mutex_lock(&vcpu->kvm->arch.config_lock);
>  		ret = kvm_arm_pmu_v3_set_attr(vcpu, attr);
>  		mutex_unlock(&vcpu->kvm->arch.config_lock);
> @@ -976,6 +980,10 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
>  
>  	switch (attr->group) {
>  	case KVM_ARM_VCPU_PMU_V3_CTRL:
> +		if (!kvm_vcpu_has_pmu(vcpu)) {
> +			ret = -ENODEV;
> +			break;
> +		}
>  		ret = kvm_arm_pmu_v3_get_attr(vcpu, attr);
>  		break;
>  	case KVM_ARM_VCPU_TIMER_CTRL:
> @@ -999,6 +1007,10 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>  
>  	switch (attr->group) {
>  	case KVM_ARM_VCPU_PMU_V3_CTRL:
> +		if (!kvm_vcpu_has_pmu(vcpu)) {
> +			ret = -ENXIO;
> +			break;
> +		}
>  		ret = kvm_arm_pmu_v3_has_attr(vcpu, attr);
>  		break;
>  	case KVM_ARM_VCPU_TIMER_CTRL:

I agree with you for the most part on this patch, but I prefer we keep
the kvm_vcpu_has_pmu() with the ioctl implemementations rather than the
spot at which we demux the ioctl.

Thanks,
Oliver


From oliver.upton at linux.dev  Wed Mar 12 14:18:01 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 14:18:01 -0700
Subject: [PATCH v3 4/6] KVM: arm64: PMU: Reload when user modifies
 registers
In-Reply-To: <20250312-pmc-v3-4-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
 <20250312-pmc-v3-4-0411cab5dc3d@daynix.com>
Message-ID: <Z9H6CWz1Z_v7DxvI@linux.dev>

On Wed, Mar 12, 2025 at 08:55:58PM +0900, Akihiko Odaki wrote:
> Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
> run") added the code to reload the PMU configuration on first run.
> 
> It is also important to keep the correct state even if system registers
> are modified after first run, specifically when debugging Windows on
> QEMU with GDB; QEMU tries to write back all visible registers when
> resuming the VM execution with GDB, corrupting the PMU state. Windows
> always uses the PMU so this can cause adverse effects on that particular
> OS.
> 
> The usual register writes are already handled independently, but
> register writes from userspace and ones for reset are not covered.

Ah -- that explains why you're moving the KVM_REQ_RELOAD_PMU from
kvm_arm_pmuv3_enable().

> @@ -4259,6 +4262,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
>  	}
>  
>  	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
> +
> +	if (kvm_vcpu_has_pmu(vcpu))
> +		kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);

nitpick, but maybe this can be added to kvm_pmu_vcpu_reset() instead.

Thanks,
Oliver


From romank at linux.microsoft.com  Wed Mar 12 14:21:07 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Wed, 12 Mar 2025 14:21:07 -0700
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <45171fb1-7533-449f-83d4-066d038c839f@app.fastmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
 <45171fb1-7533-449f-83d4-066d038c839f@app.fastmail.com>
Message-ID: <996deaab-e1d1-4f04-ba31-c0dcab2d5e1d@linux.microsoft.com>



On 3/12/2025 1:25 PM, Arnd Bergmann wrote:
> On Wed, Mar 12, 2025, at 19:33, Roman Kisel wrote:
>> On 3/10/2025 3:18 PM, Michael Kelley wrote:
>>
>> That's a minimal extension, its surprise factor is very low. It has not
>> been seen to cause issues. If no one has strong opinions against that,
>> I'd send that in V6.
>>
> 
> Works for me. Thanks for your detailed explanations.
> 

Thank you for your review very much!

>         Arnd

-- 
Thank you,
Roman



From oliver.upton at linux.dev  Wed Mar 12 14:23:17 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 12 Mar 2025 14:23:17 -0700
Subject: [PATCH v3 6/6] KVM: arm64: Reload PMCNTENSET_EL0
In-Reply-To: <20250312-pmc-v3-6-0411cab5dc3d@daynix.com>
References: <20250312-pmc-v3-0-0411cab5dc3d@daynix.com>
 <20250312-pmc-v3-6-0411cab5dc3d@daynix.com>
Message-ID: <Z9H7RYEI_cPwNe7h@linux.dev>

On Wed, Mar 12, 2025 at 08:56:00PM +0900, Akihiko Odaki wrote:
> Disable counters that are no longer included in PMCNTENSET_EL0. It is
> not necessary to enable counters included in PMCNTENSET_EL0 because
> kvm_pmu_handle_pmcr() does so if appropriate.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
>  arch/arm64/kvm/pmu-emul.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index 2d19c6048091..b14655dda6db 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -831,6 +831,8 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
>  {
>  	u64 mask = kvm_pmu_valid_counter_mask(vcpu);
>  
> +	kvm_pmu_disable_counter_mask(vcpu, ~__vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
> +

Just so this function appears consistent, can we move this after the
point where the mask is applied?

There's no functional impact of course since PMCR_EL0.N can only be
changed before the VM is started, i.e. not possible to have running
counters >= N.

Thanks,
Oliver


From romank at linux.microsoft.com  Wed Mar 12 14:30:54 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Wed, 12 Mar 2025 14:30:54 -0700
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <Z9HvHsGyXDnN38_B@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
 <Z9HvHsGyXDnN38_B@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
Message-ID: <3d26e47a-cb42-47f6-a18c-e330ee065a2b@linux.microsoft.com>



On 3/12/2025 1:31 PM, Wei Liu wrote:
> On Wed, Mar 12, 2025 at 11:33:11AM -0700, Roman Kisel wrote:
>>
>>
>> On 3/10/2025 3:18 PM, Michael Kelley wrote:
>>> From: Arnd Bergmann <arnd at arndb.de> Sent: Monday, March 10, 2025 2:21 PM
>>>>
>>>> On Mon, Mar 10, 2025, at 22:01, Michael Kelley wrote:
>>>>> From: Arnd Bergmann <arnd at arndb.de> Sent: Saturday, March 8, 2025 1:05 PM
>>>>>>>    config HYPERV_VTL_MODE
>>>>>>>    	bool "Enable Linux to boot in VTL context"
>>>>>>> -	depends on X86_64 && HYPERV
>>>>>>> +	depends on (X86_64 || ARM64)
>>>>>>>    	depends on SMP
>>>>>>> +	select OF_EARLY_FLATTREE
>>>>>>> +	select OF
>>>>>>>    	default n
>>>>>>>    	help
>>>>>>
>>>>>> Having the dependency below the top-level Kconfig entry feels a little
>>>>>> counterintuitive. You could flip that back as it was before by doing
>>>>>>
>>>>>>         select HYPERV_VTL_MODE if !ACPI
>>>>>>         depends on ACPI || SMP
>>>>>>
>>>>>> in the HYPERV option, leaving the dependency on HYPERV in
>>>>>> HYPERV_VTL_MODE.
>>>>>
>>>>> I would argue that we don't ever want to implicitly select
>>>>> HYPERV_VTL_MODE because of some other config setting or
>>>>> lack thereof.  VTL mode is enough of a special case that it should
>>>>> only be explicitly selected. If someone omits ACPI, then HYPERV
>>>>> should not be selectable unless HYPERV_VTL_MODE is explicitly
>>>>> selected.
>>>>>
>>>>> The last line of the comment for HYPERV_VTL_MODE says
>>>>> "A kernel built with this option must run at VTL2, and will not run
>>>>> as a normal guest."  In other words, don't choose this unless you
>>>>> 100% know that VTL2 is what you want.
>>>>
>>>> It sounds like the latter is the real problem: enabling a feature
>>>> should never prevent something else from working. Can you describe
>>>> what VTL context is and why it requires an exception to a rather
>>>> fundamental rule here? If you build a kernel that runs on every
>>>> single piece of arm64 hardware and every hypervisor, why can't
>>>> you add HYPERV_VTL_MODE to that as an option?
>>>>
>>
>> In the VTL mode, we're running the kernel as secure firmware inside the
>> guest (one might see VTL2 working as Intel SMM or Secure World on ARM).
>>
>> [...]
>>
>>>
>>> Ideally, a Linux kernel image could detect at runtime what VTL it is
>>> running at, and "do the right thing". Unfortunately, on x86 Linux this
>>> has proved difficult (or perhaps impossible) because the amount of
>>> boot-time setup required to ask the question about the current VTL
>>> is significant. The idiosyncrasies and historical baggage of x86 requires
>>> that Linux do some x86-specific initialization steps for VTL > 0
>>> before the question can be asked. Hence the introduction of
>>> CONFIG_HYPERV_VTL_MODE, and the behavior that when it is
>>> selected, the kernel image won't run normally in VTL 0.
>>>
>>> I'll go out on a limb and say that I suspect on arm64 a runtime
>>> determination based on querying the VTL *could* be made (though
>>> I'm not the person writing the code). But taking advantage of that
>>> on arm64 produces an undesirable dichotomy with x86.
>>
>> On arm64 that is much easier, I agree. On x86 we'd need a kludge of
>>
>> static void __naked __init __aligned(4096) early_hvcall_pg(void)
>> {
>> 	/*
>> 	 * Fill the early hvcall page with `0xF1` aka `INT1` to catch
>> 	 * programming errors. The hypervisor will overlay the page with
>> 	 * the vendor-specific code sequences to make hypercalls on x86(_64).
>> 	 */
>> 	asm (".skip 4096, 0xf1");
>> }
>>
>> static u8 __init early_hvcall_pg_input[4096] __attribute__((aligned(4096)));
>> static u8 __init early_hvcall_pg_output[4096]
>> __attribute__((aligned(4096)));
>>
>> static void __init early_connect_to_hv(void)
>> {
>> 	union hv_x64_msr_hypercall_contents hypercall_msr;
>> 	u64 guest_id;
>>
>> 	guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
>> 	wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
>> 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
>> 	hypercall_msr.enable = 1;
>> 	hypercall_msr.guest_physical_address =
>> __phys_to_pfn(virt_to_phys(early_hvcall_pg));
>> 	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
>> }
>>
>> or variations thereof.
> 
> OT here but what's stopping us from doing this on x86?
> 

At the first glance, seems like nothing I think. For the conf scenarios
like TDX and SEV-SNP, due to the early hvcall I/O pages above allocated
in BSS, might need to mark the pages as decrypted and zero them out so
they look like proper BSS section (the page contents are scrambled after
flipping the page encryption bit iirc).

> It seems to me there is some value in setting up the hypercall page as
> early as possible. The same page can be used through the lifetime of the
> partition. The early input and output pages should be reclaimed.
> 

Wholeheartedly agree!

> Also, since the hypervisor will insert an overlay page, it makes sense
> to not allocate a page from Linux at all. When I ported Xen to run as
> a guest on Hyper-V, I used that approach. The setup worked just fine.
> 
> All being said, things work today, so I'm in no hurry to change things.
> 

I'll try fleshing this out soon-ish if no one beats me to that :)

> Wei.

-- 
Thank you,
Roman



From helgaas at kernel.org  Wed Mar 12 14:37:57 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 16:37:57 -0500
Subject: [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250310-pci_fixup_addr-v10-5-409dafc950d1@nxp.com>
Message-ID: <20250312213757.GA709739@bhelgaas>

On Mon, Mar 10, 2025 at 04:16:43PM -0400, Frank Li wrote:
> parent_bus_offset in resource_entry can indicate address information just
> ahead of PCIe controller. Most system's bus fabric use 1:1 map between
> input and output address. but some hardware like i.MX8QXP doesn't use 1:1
> map. See below diagram:

> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -478,6 +478,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	bridge->ops = &dw_pcie_ops;
>  	bridge->child_ops = &dw_child_pcie_ops;
>  
> +	/*
> +	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
> +	 * so have to call dw_pcie_init_parent_bus_offset() after init
> +	 * pp->io_base.
> +	 */
> +	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
> +	if (ret)
> +		return ret;

The ordering in dw_pcie_host_init() doesn't look right to me.  We have
this:

  dw_pcie_host_init
    dw_pcie_get_resources
    dw_pcie_cfg0_setup
    devm_pci_alloc_host_bridge
    win = resource_list_first_type(&bridge->windows, IORESOURCE_IO)
    pp->io_base = pci_pio_to_address(win->res->start)
    bridge->ops = ...
    bridge->child_ops = ...
    dw_pcie_init_parent_bus_offset
    pp->ops->init

devm_pci_alloc_host_bridge() is generic, so it obviously can't depend
on any dwc-specific things.  I think the ordering should be more like
this:

  dw_pcie_host_init
    devm_pci_alloc_host_bridge             # generic
    dw_pcie_get_resources                  # dwc RP and EP

    dw_pcie_cfg0_setup
    win = resource_list_first_type(&bridge->windows, IORESOURCE_IO)
    pp->io_base = pci_pio_to_address(win->res->start)
    dw_pcie_init_parent_bus_offset

    bridge->ops = ...
    bridge->child_ops = ...
    pp->ops->init

and everything in the second block (dw_pcie_cfg0_setup() through
dw_pcie_init_parent_bus_offset()) is strictly DT-related resource
setup and could all go in a dw_pcie_host_get_resources() or similar.

>  	if (pp->ops->init) {
>  		ret = pp->ops->init(pp);
>  		if (ret)
> 
> -- 
> 2.34.1
> 


From helgaas at kernel.org  Wed Mar 12 14:47:00 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 16:47:00 -0500
Subject: [PATCH v10 09/10] PCI: dwc: ep: Ensure proper iteration over
 outbound map windows
In-Reply-To: <20250310-pci_fixup_addr-v10-9-409dafc950d1@nxp.com>
Message-ID: <20250312214700.GA710620@bhelgaas>

On Mon, Mar 10, 2025 at 04:16:47PM -0400, Frank Li wrote:
> Most systems' PCIe outbound map windows have non-zero physical addresses,
> but the possibility of encountering zero increased with commit
> ("PCI: dwc: ep: Add bus_addr_base for outbound window").

What is this commit?  I don't see it in the tree, and I don't see it
in this series.

It look like it might be a fixup for something in this series.  In
that case it should go *before* the other commit (or be squashed into
it if it's logically part of it).

I don't think this series touches ep->ob_window_map, so if it's a fix
it looks like it could go anywhere earlier.

> 'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
> some hardware, which trims high address bits through bus fabric before
> sending to the PCIe controller.
> 
> Replace the iteration logic with 'for_each_set_bit()' to ensure only
> allocated map windows are iterated when determining the ATU index from a
> given address.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
> change from v9 to v10
> - remove commit hash value
> 
> change from v8 to v9
> - new patch
> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 62bc71ad20719..e333855633a77 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
>  	u32 index;
>  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>  
> -	for (index = 0; index < pci->num_ob_windows; index++) {
> +	for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
>  		if (ep->outbound_addr[index] != addr)
>  			continue;
>  		*atu_index = index;
> 
> -- 
> 2.34.1
> 


From peter.griffin at linaro.org  Wed Mar 12 14:59:01 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:59:01 +0000
Subject: [PATCH v5 4/5] pinctrl: samsung: add gs101 specific eint
 suspend/resume callbacks
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-4-d98d5b271242@linaro.org>

gs101 differs to other SoCs in that fltcon1 register doesn't
always exist. Additionally the offset of fltcon0 is not fixed
and needs to use the newly added eint_fltcon_offset variable.

Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org  # depends on the previous three patches
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v2:
* make it clear exynos_set_wakeup(bank) is conditional on bank type (Andre)
* align style where the '+' is placed (Andre)
* remove unnecessary braces (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 24 ++++-----
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 71 ++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  2 +
 3 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 57c98d2451b54b00d50e0e948e272ed53d386c34..fca447ebc5f5956b7e8d2f2d08f23622095b1ee6 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1455,15 +1455,15 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (FAR_ALIVE) */
 		.pin_banks	= gs101_pin_far_alive,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_far_alive),
 		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (GSACORE) */
 		.pin_banks	= gs101_pin_gsacore,
@@ -1477,29 +1477,29 @@ static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
 		.pin_banks	= gs101_pin_peric0,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric0),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (PERIC1) */
 		.pin_banks	= gs101_pin_peric1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_peric1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume	= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI1) */
 		.pin_banks	= gs101_pin_hsi1,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi1),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	}, {
 		/* pin banks of gs101 pin-controller (HSI2) */
 		.pin_banks	= gs101_pin_hsi2,
 		.nr_banks	= ARRAY_SIZE(gs101_pin_hsi2),
 		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= gs101_pinctrl_suspend,
+		.resume		= gs101_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index af4fb1cde8de942707d932072bb237521e30c9c6..7887fd41665111d7c4b47e2d74f4e6e335914915 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -799,6 +799,41 @@ void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 	}
 }
 
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + bank->eint_fltcon_offset);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			save->eint_fltcon1 = readl(regs +
+						EXYNOS_GPIO_EFLTCON_OFFSET
+						+ bank->eint_fltcon_offset + 4);
+
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		if (bank->nr_pins > 4)
+			pr_debug("%s: save fltcon1 %#010x\n",
+				 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		exynos_set_wakeup(bank);
+	}
+}
+
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
@@ -818,6 +853,42 @@ void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 	}
 }
 
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+
+	void __iomem *regs = bank->eint_base;
+	void __iomem *eint_fltcfg0 = regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		     + bank->eint_fltcon_offset;
+
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(eint_fltcfg0), save->eint_fltcon0);
+
+		/* fltcon1 register only exists for pins 4-7 */
+		if (bank->nr_pins > 4)
+			pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+				 readl(eint_fltcfg0 + 4), save->eint_fltcon1);
+
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, eint_fltcfg0);
+
+		if (bank->nr_pins > 4)
+			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
+	}
+}
+
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 35c2bc4ea488bda600ebfbda1492f5f49dbd9849..773f161a82a38cbaad05fcbc09a936300f5c7595 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -225,6 +225,8 @@ void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
 void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
+void gs101_pinctrl_suspend(struct samsung_pin_bank *bank);
+void gs101_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 12 14:59:02 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:59:02 +0000
Subject: [PATCH v5 5/5] pinctrl: samsung: Add filter selection support for
 alive bank on gs101
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-5-d98d5b271242@linaro.org>

Newer Exynos based SoCs have a filter selection bitfield in the filter
configuration registers on alive bank pins. This allows the selection of
a digital or analog delay filter for each pin. Add support for selecting
and enabling the filter.

On suspend we set the analog filter to all pins in the bank (as the
digital filter relies on a clock). On resume the digital filter is
reapplied to all pins in the bank. The digital filter is working via
a clock and has an adjustable filter delay flt_width bitfield, whereas
the analog filter uses a fixed delay.

The filter determines to what extent signal fluctuations received through
the pad are considered glitches.

The code path can be exercised using
echo mem > /sys/power/state
And then wake the device using a eint gpio

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---

Changes since v2:
* Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
* Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)

Changes since v1:
* Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
* Move filter config comment to header (Andre)
* Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
* Remove misleading old comment (Andre)
* Refactor exynos_eint_update_flt_reg() into a loop (Andre)

Note: this patch was previously sent as part of the initial gs101/ Pixel 6
series and was dropped in v6. This new version incorporates the review
feedback from Sam Protsenko here in v5.

Link: https://lore.kernel.org/all/20231201160925.3136868-1-peter.griffin at linaro.org/T/#m79ced98939e895c840d812c8b4c2b3f33ce604c8

Changes since previous version
* Drop fltcon_type enum and use bool eint_flt_selectable (Sam)
* Refactor and add exynos_eint_update_flt_reg() (Sam)
* Rename function to exynos_eint_set_filter() for easier readability (Sam)
* Remove comments and `if bank->fltcon_type != FLT_DEFAULT)` checks and indentation (Sam)
---
 drivers/pinctrl/samsung/pinctrl-exynos.c | 34 ++++++++++++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-exynos.h | 20 +++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 7887fd41665111d7c4b47e2d74f4e6e335914915..41de39767a3e09a6b1cb446aeec48552546a98a3 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -369,6 +369,37 @@ struct exynos_eint_gpio_save {
 	u32 eint_mask;
 };
 
+static void exynos_eint_update_flt_reg(void __iomem *reg, int cnt, int con)
+{
+	unsigned int val, shift;
+	int i;
+
+	val = readl(reg);
+	for (i = 0; i < cnt; i++) {
+		shift = i * EXYNOS_FLTCON_LEN;
+		val &= ~(EXYNOS_FLTCON_DIGITAL << shift);
+		val |= con << shift;
+	}
+	writel(val, reg);
+}
+
+/*
+ * Set the desired filter (digital or analog delay) and enable it to
+ * every pin in the bank. Note the filter selection bitfield is only
+ * found on alive banks. The filter determines to what extent signal
+ * fluctuations received through the pad are considered glitches.
+ */
+static void exynos_eint_set_filter(struct samsung_pin_bank *bank, int filter)
+{
+	unsigned int off = EXYNOS_GPIO_EFLTCON_OFFSET + bank->eint_fltcon_offset;
+	void __iomem *reg = bank->drvdata->virt_base + off;
+	unsigned int con = EXYNOS_FLTCON_EN | filter;
+
+	for (int n = 0; n < bank->nr_pins; n += 4)
+		exynos_eint_update_flt_reg(reg + n,
+					   min(bank->nr_pins - n, 4), con);
+}
+
 /*
  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
  * @d: driver data of samsung pinctrl driver.
@@ -831,6 +862,7 @@ void gs101_pinctrl_suspend(struct samsung_pin_bank *bank)
 			 bank->name, save->eint_mask);
 	} else if (bank->eint_type == EINT_TYPE_WKUP) {
 		exynos_set_wakeup(bank);
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_ANALOG);
 	}
 }
 
@@ -886,6 +918,8 @@ void gs101_pinctrl_resume(struct samsung_pin_bank *bank)
 			writel(save->eint_fltcon1, eint_fltcfg0 + 4);
 		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 		       + bank->eint_offset);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		exynos_eint_set_filter(bank, EXYNOS_FLTCON_DIGITAL);
 	}
 }
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 773f161a82a38cbaad05fcbc09a936300f5c7595..66acbd08d3445ca6ee7358d3c4a6cb2be5d82842 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -52,6 +52,26 @@
 #define EXYNOS_EINT_MAX_PER_BANK	8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
+/*
+ * EINT filter configuration register (on alive banks) has
+ * the following layout.
+ *
+ * BitfieldName[PinNum][Bit:Bit]
+ * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24]
+ * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16]
+ * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8]
+ * FLT_EN[0][7]  FLT_SEL[0][6]  FLT_WIDTH[0][5:0]
+ *
+ * FLT_EN	0x0 = Disable, 0x1=Enable
+ * FLT_SEL	0x0 = Analog delay filter, 0x1 Digital filter (clock count)
+ * FLT_WIDTH	Filtering width. Valid when FLT_SEL is 0x1
+ */
+
+#define EXYNOS_FLTCON_EN		BIT(7)
+#define EXYNOS_FLTCON_DIGITAL		BIT(6)
+#define EXYNOS_FLTCON_ANALOG		(0 << 6)
+#define EXYNOS_FLTCON_LEN		8
+
 #define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
 	{						\
 		.type		= &bank_type_off,	\

-- 
2.49.0.rc1.451.g8f38331e32-goog



From heiko at sntech.de  Wed Mar 12 14:59:23 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 12 Mar 2025 22:59:23 +0100
Subject: [PATCH] dt-bindings: reset: fix double id on rk3562-cru reset ids
Message-ID: <20250312215923.275625-1-heiko@sntech.de>

Id 173 was accidentially used two times for SRST_P_DDR_HWLP and
SRST_P_DDR_PHY. This makes both resets ambiguous and also causes build
warnings like:

drivers/clk/rockchip/rst-rk3562.c:21:57: error: initialized field overwritten [-Werror=override-init]
   21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
      |                                                         ^
drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
  266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/clk/rockchip/rst-rk3562.c:21:57: note: (near initialization for 'rk3562_register_offset[173]')
   21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
      |                                                         ^
drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
  266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~

To fix that issue give SRST_P_DDR_PHY a new and now unique id.

Reported-by: Stephen Boyd <sboyd at kernel.org>
Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503121743.0zcDf6nE-lkp at intel.com/
Fixes: dd113c4fefc8 ("dt-bindings: clock: Add RK3562 cru")
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
The original patch did go with the reset of the clock controller code
into the clock tree, so this patch should of course also go that way.

I also don't have anything more open for the 6.15 merge window, so
clock-maintainers could just apply this patch on top of the main changes.

 include/dt-bindings/reset/rockchip,rk3562-cru.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/dt-bindings/reset/rockchip,rk3562-cru.h b/include/dt-bindings/reset/rockchip,rk3562-cru.h
index a74471d7d2a93..8df95113056e3 100644
--- a/include/dt-bindings/reset/rockchip,rk3562-cru.h
+++ b/include/dt-bindings/reset/rockchip,rk3562-cru.h
@@ -217,7 +217,7 @@
 #define SRST_MSCH_BRG_BIU		171
 #define SRST_P_MSCH_BIU			172
 #define SRST_P_DDR_HWLP			173
-#define SRST_P_DDR_PHY			173
+#define SRST_P_DDR_PHY			290
 #define SRST_P_DDR_DFICTL		174
 #define SRST_P_DDR_DMA2DDR		175
 /********Name=DDRSOFTRST_CON01,Offset=0x20204********/
-- 
2.47.2



From helgaas at kernel.org  Wed Mar 12 15:04:24 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 17:04:24 -0500
Subject: [PATCH v10 08/10] PCI: dwc: Print warning message when
 cpu_addr_fixup() exists
In-Reply-To: <20250310-pci_fixup_addr-v10-8-409dafc950d1@nxp.com>
Message-ID: <20250312220424.GA711004@bhelgaas>

On Mon, Mar 10, 2025 at 04:16:46PM -0400, Frank Li wrote:
> If the parent 'ranges' property in DT correctly describes the address
> translation, the cpu_addr_fixup() callback is not needed. Print a warning
> message to inform users to correct their DT files.

> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -1125,6 +1125,8 @@ int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
>  
>  	fixup = pci->ops->cpu_addr_fixup;
>  	if (fixup) {
> +		dev_warn_once(pci->dev, "cpu_addr_fixup() usage detected. Please fix DT!\n");

I don't think we need this.  The mere presence of .cpu_addr_fixup()
doesn't tell us the DT is broken.  When we have .cpu_addr_fixup(), the
DT is only broken if DT tells us something different than
.cpu_addr_fixup() tells us.  And we already warn about that in the
"reg_addr != fixup_addr" case.

> +
>  		fixup_addr = fixup(pci, cpu_phy_addr);
>  		if (reg_addr == fixup_addr) {
>  			dev_info(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",

This message is really just a hint that DT is fine and
.cpu_addr_fixup() is redundant but harmless.  If you want a dev_warn()
here to encourage people to remove .cpu_addr_fixup(), I'm fine with
that.

Seems like "dev_warn()" would be enough, probably no need for
"dev_warn_once()" since we should only run this once per controller
anyway, so I don't think we'll get spammed with messages.


From peter.griffin at linaro.org  Wed Mar 12 14:58:57 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:58:57 +0000
Subject: [PATCH v5 0/5] samsung: pinctrl: Add support for
 eint_fltcon_offset and filter selection on gs101
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>

Hi folks,

This series fixes support for correctly saving and restoring fltcon0
and fltcon1 registers on gs101 for non-alive banks where the fltcon
register offset is not at a fixed offset (unlike previous SoCs).
This is done by adding a eint_fltcon_offset and providing GS101
specific pin macros that take an additional parameter (similar to
how exynosautov920 handles it's eint_con_offset).

Additionally the SoC specific suspend and resume callbacks are
re-factored so that each SoC variant has it's own callback containing
the peculiarities for that SoC.

Finally support for filter selection on alive banks is added, this is
currently only enabled for gs101. The code path can be excercised using
`echo mem > /sys/power/state`

regards,

Peter

To: Krzysztof Kozlowski <krzk at kernel.org>
To: Sylwester Nawrocki <s.nawrocki at samsung.com>
To: Alim Akhtar <alim.akhtar at samsung.com>
To: Linus Walleij <linus.walleij at linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-gpio at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: andre.draszik at linaro.org
Cc: tudor.ambarus at linaro.org
Cc: willmcvicker at google.com
Cc: semen.protsenko at linaro.org
Cc: kernel-team at android.com
Cc: jaewon02.kim at samsung.com

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes in v5:
- Split drvdata suspend & resume callbacks into a dedicated patch (Krzysztof)
- Add comment about stable dependency (Krzysztof)
- Add back in {} braces (Krzysztof)
- Link to v4: https://lore.kernel.org/r/20250307-pinctrl-fltcon-suspend-v4-0-2d775e486036 at linaro.org

Changes in v4:
- save->eint_fltcon1 is an argument to pr_debug(), not readl() change alignment accordingly (Andre)
- Link to v3: https://lore.kernel.org/r/20250306-pinctrl-fltcon-suspend-v3-0-f9ab4ff6a24e at linaro.org

Changes in v3:
- Ensure EXYNOS_FLTCON_DIGITAL bit is cleared (Andre)
- Make it obvious that exynos_eint_set_filter() is conditional on bank type (Andre)
- Make it obvious exynos_set_wakeup() is conditional on bank type (Andre)
- Align style where the '+' is placed first (Andre)
- Remove unnecessary braces (Andre)
- Link to v2: https://lore.kernel.org/r/20250301-pinctrl-fltcon-suspend-v2-0-a7eef9bb443b at linaro.org

Changes in v2:
- Remove eint_flt_selectable bool as it can be deduced from EINT_TYPE_WKUP (Peter)
- Move filter config register comment to header file (Andre)
- Rename EXYNOS_FLTCON_DELAY to EXYNOS_FLTCON_ANALOG (Andre)
- Remove misleading old comment (Andre)
- Refactor exynos_eint_update_flt_reg() into a loop (Andre)
- Split refactor of suspend/resume callbacks & gs101 parts into separate patches (Andre)
- Link to v1: https://lore.kernel.org/r/20250120-pinctrl-fltcon-suspend-v1-0-e77900b2a854 at linaro.org

---
Peter Griffin (5):
      pinctrl: samsung: add support for eint_fltcon_offset
      pinctrl: samsung: refactor drvdata suspend & resume callbacks
      pinctrl: samsung: add dedicated SoC eint suspend/resume callbacks
      pinctrl: samsung: add gs101 specific eint suspend/resume callbacks
      pinctrl: samsung: Add filter selection support for alive bank on gs101

 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 150 ++++++-------
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 294 +++++++++++++++----------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |  50 ++++-
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  12 +-
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  12 +-
 5 files changed, 319 insertions(+), 199 deletions(-)
---
base-commit: 0761652a3b3b607787aebc386d412b1d0ae8008c
change-id: 20250120-pinctrl-fltcon-suspend-2333a137c4d4

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From peter.griffin at linaro.org  Wed Mar 12 14:58:58 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:58:58 +0000
Subject: [PATCH v5 1/5] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-1-d98d5b271242@linaro.org>

On gs101 SoC the fltcon0 (filter configuration 0) offset
isn't at a fixed offset like previous SoCs as the fltcon1
register only exists when there are more than 4 pins in the
bank.

Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
macros that take an additional fltcon_offs variable.

This can then be used in suspend/resume callbacks to
save and restore the fltcon0 and fltcon1 registers.

Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
Cc: stable at vger.kernel.org
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 98 +++++++++++++-------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       | 22 ++++++
 drivers/pinctrl/samsung/pinctrl-samsung.c      |  1 +
 drivers/pinctrl/samsung/pinctrl-samsung.h      |  4 ++
 4 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 3ea7106ce5eae3c21f11790b5a40037042c1d407..e28fe81776466b693417c66bb15752d609b79eb1 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1370,83 +1370,83 @@ const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = {
 
 /* pin banks of gs101 pin-controller (ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10),
-	EXYNOS850_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14),
-	EXYNOS850_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18),
-	EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08, 0x10),
+	GS101_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c, 0x18),
+	GS101_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10, 0x1c),
+	GS101_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14, 0x20),
+	GS101_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18, 0x28),
+	GS101_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c, 0x30),
 };
 
 /* pin banks of gs101 pin-controller (FAR_ALIVE) */
 static const struct samsung_pin_bank_data gs101_pin_far_alive[] = {
-	EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00),
-	EXYNOS850_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04),
-	EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08),
-	EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c),
+	GS101_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00, 0x00),
+	GS101_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04, 0x08),
+	GS101_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c, 0x14),
 };
 
 /* pin banks of gs101 pin-controller (GSACORE) */
 static const struct samsung_pin_bank_data gs101_pin_gsacore[] = {
-	EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04, 0x04),
+	GS101_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08, 0x0c),
 };
 
 /* pin banks of gs101 pin-controller (GSACTRL) */
 static const struct samsung_pin_bank_data gs101_pin_gsactrl[] = {
-	EXYNOS850_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00),
+	GS101_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00, 0x00),
 };
 
 /* pin banks of gs101 pin-controller (PERIC0) */
 static const struct samsung_pin_bank_data gs101_pin_peric0[] = {
-	EXYNOS850_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c),
+	GS101_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10, 0x14),
+	GS101_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18, 0x1c),
+	GS101_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20, 0x24),
+	GS101_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24, 0x28),
+	GS101_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28, 0x2c),
+	GS101_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c, 0x30),
+	GS101_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30, 0x34),
+	GS101_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34, 0x38),
+	GS101_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38, 0x3c),
+	GS101_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c, 0x40),
+	GS101_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40, 0x44),
+	GS101_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44, 0x48),
+	GS101_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48, 0x4c),
+	GS101_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c, 0x50),
 };
 
 /* pin banks of gs101 pin-controller (PERIC1) */
 static const struct samsung_pin_bank_data gs101_pin_peric1[] = {
-	EXYNOS850_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08),
-	EXYNOS850_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c),
-	EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14),
-	EXYNOS850_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18),
-	EXYNOS850_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c),
+	GS101_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08, 0x0c),
+	GS101_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c, 0x10),
+	GS101_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10, 0x18),
+	GS101_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14, 0x1c),
+	GS101_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18, 0x20),
+	GS101_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c, 0x28),
 };
 
 /* pin banks of gs101 pin-controller (HSI1) */
 static const struct samsung_pin_bank_data gs101_pin_hsi1[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04, 0x08),
 };
 
 /* pin banks of gs101 pin-controller (HSI2) */
 static const struct samsung_pin_bank_data gs101_pin_hsi2[] = {
-	EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00),
-	EXYNOS850_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04),
-	EXYNOS850_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00, 0x00),
+	GS101_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04, 0x08),
+	GS101_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08, 0x0c),
 };
 
 static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 7b7ff7ffeb56bdde2504ec90c8df13bdd1ace70e..33df21d5c9d61e852834031570d4a0ac0e51f6a4 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -175,6 +175,28 @@
 		.name			= id				\
 	}
 
+#define GS101_PIN_BANK_EINTG(pins, reg, id, offs, fltcon_offs) \
+	{							\
+		.type			= &exynos850_bank_type_off,	\
+		.pctl_offset		= reg,			\
+		.nr_pins		= pins,			\
+		.eint_type		= EINT_TYPE_GPIO,	\
+		.eint_offset		= offs,			\
+		.eint_fltcon_offset	= fltcon_offs,		\
+		.name			= id			\
+	}
+
+#define GS101_PIN_BANK_EINTW(pins, reg, id, offs, fltcon_offs) \
+	{								\
+		.type			= &exynos850_bank_type_alive,	\
+		.pctl_offset		= reg,				\
+		.nr_pins		= pins,				\
+		.eint_type		= EINT_TYPE_WKUP,		\
+		.eint_offset		= offs,				\
+		.eint_fltcon_offset	= fltcon_offs,			\
+		.name			= id				\
+	}
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index cfced7afd4ca6e99c7e72a588d780f0542990ed9..963060920301ec90affb2ee6d758d3d602ffb4a9 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1230,6 +1230,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
 		bank->eint_con_offset = bdata->eint_con_offset;
 		bank->eint_mask_offset = bdata->eint_mask_offset;
 		bank->eint_pend_offset = bdata->eint_pend_offset;
+		bank->eint_fltcon_offset = bdata->eint_fltcon_offset;
 		bank->name = bdata->name;
 
 		raw_spin_lock_init(&bank->slock);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index bb0689d52ea0b4392714fa9bcdcbae8d253c73a1..371e4f02bbfb375964b7833beb9bbc098a51f4a3 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -144,6 +144,7 @@ struct samsung_pin_bank_type {
  * @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  */
 struct samsung_pin_bank_data {
@@ -158,6 +159,7 @@ struct samsung_pin_bank_data {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 };
 
@@ -175,6 +177,7 @@ struct samsung_pin_bank_data {
  * @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
  * @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
  * @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
+ * @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
  * @name: name to be prefixed for each pin in this pin bank.
  * @id: id of the bank, propagated to the pin range.
  * @pin_base: starting pin number of the bank.
@@ -201,6 +204,7 @@ struct samsung_pin_bank {
 	u32		eint_con_offset;
 	u32		eint_mask_offset;
 	u32		eint_pend_offset;
+	u32		eint_fltcon_offset;
 	const char	*name;
 	u32		id;
 

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 12 14:58:59 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:58:59 +0000
Subject: [PATCH v5 2/5] pinctrl: samsung: refactor drvdata suspend & resume
 callbacks
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-2-d98d5b271242@linaro.org>

Move the call of drvdata->suspend()/resume into the loop which is
iterating drvdata for each bank.

This allows the clk_enable() and clk_disable() logic to be removed
from each callback, and also avoids iterating the same loop again
in the next function.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/pinctrl/samsung/pinctrl-exynos.c  | 89 ++++++++-----------------------
 drivers/pinctrl/samsung/pinctrl-exynos.h  |  4 +-
 drivers/pinctrl/samsung/pinctrl-samsung.c | 11 ++--
 drivers/pinctrl/samsung/pinctrl-samsung.h |  8 +--
 4 files changed, 33 insertions(+), 79 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index ac6dc22b37c98ed5b7fca3335764f19abb2f71cc..62c8d8d907545119c49a89d79b5dae63282467d5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -761,19 +761,11 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	return 0;
 }
 
-static void exynos_pinctrl_suspend_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+static void exynos_pinctrl_suspend_bank(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
-	}
-
 	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
 						+ bank->eint_offset);
 	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
@@ -783,71 +775,46 @@ static void exynos_pinctrl_suspend_bank(
 	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
 						+ bank->eint_offset);
 
-	clk_disable(bank->drvdata->pclk);
-
 	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
 	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
 	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
 	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
-					    struct samsung_pin_bank *bank)
+static void exynosauto_pinctrl_suspend_bank(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for saving state\n");
-		return;
-	}
-
 	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
 	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
 
-	clk_disable(bank->drvdata->pclk);
-
 	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
 	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
 	struct exynos_irq_chip *irq_chip = NULL;
-	int i;
 
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_suspend_bank(drvdata, bank);
-			else
-				exynos_pinctrl_suspend_bank(drvdata, bank);
-		}
-		else if (bank->eint_type == EINT_TYPE_WKUP) {
-			if (!irq_chip) {
-				irq_chip = bank->irq_chip;
-				irq_chip->set_eint_wakeup_mask(drvdata,
-							       irq_chip);
-			}
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		if (bank->eint_con_offset)
+			exynosauto_pinctrl_suspend_bank(bank);
+		else
+			exynos_pinctrl_suspend_bank(bank);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		if (!irq_chip) {
+			irq_chip = bank->irq_chip;
+			irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
 		}
 	}
 }
 
-static void exynos_pinctrl_resume_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
+static void exynos_pinctrl_resume_bank(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
-	}
-
 	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
 			readl(regs + EXYNOS_GPIO_ECON_OFFSET
 			+ bank->eint_offset), save->eint_con);
@@ -869,22 +836,13 @@ static void exynos_pinctrl_resume_bank(
 						+ 2 * bank->eint_offset + 4);
 	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 						+ bank->eint_offset);
-
-	clk_disable(bank->drvdata->pclk);
 }
 
-static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
-					   struct samsung_pin_bank *bank)
+static void exynosauto_pinctrl_resume_bank(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	if (clk_enable(bank->drvdata->pclk)) {
-		dev_err(bank->gpio_chip.parent,
-			"unable to enable clock for restoring state\n");
-		return;
-	}
-
 	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
 		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
 	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
@@ -893,21 +851,16 @@ static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvd
 	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
 	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
 
-	clk_disable(bank->drvdata->pclk);
 }
 
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
-	struct samsung_pin_bank *bank = drvdata->pin_banks;
-	int i;
-
-	for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			if (bank->eint_con_offset)
-				exynosauto_pinctrl_resume_bank(drvdata, bank);
-			else
-				exynos_pinctrl_resume_bank(drvdata, bank);
-		}
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		if (bank->eint_con_offset)
+			exynosauto_pinctrl_resume_bank(bank);
+		else
+			exynos_pinctrl_resume_bank(bank);
+	}
 }
 
 static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 33df21d5c9d61e852834031570d4a0ac0e51f6a4..69be0746e29d9714a33f4aa49df0e8d7257b4220 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -221,8 +221,8 @@ struct exynos_muxed_weint_data {
 
 int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
 int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
-void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata);
-void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata);
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *
 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 		      const struct samsung_retention_data *data);
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 963060920301ec90affb2ee6d758d3d602ffb4a9..375634d8cc79d6533603e3eed562452181e2ee25 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->suspend)
+			drvdata->suspend(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
@@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
 
 	clk_disable(drvdata->pclk);
 
-	if (drvdata->suspend)
-		drvdata->suspend(drvdata);
 	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
 		drvdata->retention_ctrl->enable(drvdata);
 
@@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		return ret;
 	}
 
-	if (drvdata->resume)
-		drvdata->resume(drvdata);
-
 	for (i = 0; i < drvdata->nr_banks; i++) {
 		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
 		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
@@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
 		const u8 *widths = bank->type->fld_width;
 		enum pincfg_type type;
 
+		if (drvdata->resume)
+			drvdata->resume(bank);
+
 		/* Registers without a powerdown config aren't lost */
 		if (!widths[PINCFG_TYPE_CON_PDN])
 			continue;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 371e4f02bbfb375964b7833beb9bbc098a51f4a3..e939e5bb0347458ae4a9014fd9657fc59c5c3994 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -285,8 +285,8 @@ struct samsung_pin_ctrl {
 	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
 	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
 	void		(*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
-	void		(*suspend)(struct samsung_pinctrl_drv_data *);
-	void		(*resume)(struct samsung_pinctrl_drv_data *);
+	void		(*suspend)(struct samsung_pin_bank *bank);
+	void		(*resume)(struct samsung_pin_bank *bank);
 };
 
 /**
@@ -335,8 +335,8 @@ struct samsung_pinctrl_drv_data {
 
 	struct samsung_retention_ctrl	*retention_ctrl;
 
-	void (*suspend)(struct samsung_pinctrl_drv_data *);
-	void (*resume)(struct samsung_pinctrl_drv_data *);
+	void (*suspend)(struct samsung_pin_bank *bank);
+	void (*resume)(struct samsung_pin_bank *bank);
 };
 
 /**

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 12 14:59:00 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 12 Mar 2025 21:59:00 +0000
Subject: [PATCH v5 3/5] pinctrl: samsung: add dedicated SoC eint
 suspend/resume callbacks
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
Message-ID: <20250312-pinctrl-fltcon-suspend-v5-3-d98d5b271242@linaro.org>

Refactor the existing platform specific suspend/resume callback
so that each SoC variant has it's own callback containing the
SoC specific logic.

This allows exynosautov920 to have a dedicated function for using
eint_con_offset and eint_mask_offset. Also it is easily extendable
for gs101 which will need dedicated logic for handling the varying
register offset of fltcon0 via eint_fltcon_offset.

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v4:
* split the clk_enable/clk_disable refactor parts into separate patch (Krzystof)

Changes since v3:
* save->eint_fltcon1 is an argument to pr_debug(), not readl()
  change alignment accordingly (Andre)

Changes since v2:
* Remove useless init (Andre)
* make it clear set_wakeup is conditional on bank->eint_type (Andre)

Changes since v1:
* Split code refactor & gs101 parts into separate patches (Andre)
---
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c |  28 ++---
 drivers/pinctrl/samsung/pinctrl-exynos.c       | 152 +++++++++++++------------
 drivers/pinctrl/samsung/pinctrl-exynos.h       |   2 +
 3 files changed, 97 insertions(+), 85 deletions(-)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index e28fe81776466b693417c66bb15752d609b79eb1..57c98d2451b54b00d50e0e948e272ed53d386c34 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1112,8 +1112,8 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks0,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks0),
 		.eint_wkup_init	= exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 		.retention_data	= &exynosautov920_retention_data,
 	}, {
 		/* pin-controller instance 1 AUD data */
@@ -1124,43 +1124,43 @@ static const struct samsung_pin_ctrl exynosautov920_pin_ctrl[] = {
 		.pin_banks	= exynosautov920_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks2),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 3 HSI1 data */
 		.pin_banks	= exynosautov920_pin_banks3,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks3),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 4 HSI2 data */
 		.pin_banks	= exynosautov920_pin_banks4,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks4),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 5 HSI2UFS data */
 		.pin_banks	= exynosautov920_pin_banks5,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks5),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 6 PERIC0 data */
 		.pin_banks	= exynosautov920_pin_banks6,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks6),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	}, {
 		/* pin-controller instance 7 PERIC1 data */
 		.pin_banks	= exynosautov920_pin_banks7,
 		.nr_banks	= ARRAY_SIZE(exynosautov920_pin_banks7),
 		.eint_gpio_init	= exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
+		.suspend	= exynosautov920_pinctrl_suspend,
+		.resume		= exynosautov920_pinctrl_resume,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 62c8d8d907545119c49a89d79b5dae63282467d5..af4fb1cde8de942707d932072bb237521e30c9c6 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -761,105 +761,115 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	return 0;
 }
 
-static void exynos_pinctrl_suspend_bank(struct samsung_pin_bank *bank)
+static void exynos_set_wakeup(struct samsung_pin_bank *bank)
 {
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	const void __iomem *regs = bank->eint_base;
+	struct exynos_irq_chip *irq_chip;
 
-	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
-	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
+	if (bank->irq_chip) {
+		irq_chip = bank->irq_chip;
+		irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
+	}
 }
 
-static void exynosauto_pinctrl_suspend_bank(struct samsung_pin_bank *bank)
+void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	const void __iomem *regs = bank->eint_base;
 
-	save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
-	save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+				       + bank->eint_offset);
+		save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset);
+		save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+					   + 2 * bank->eint_offset + 4);
+		save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+					+ bank->eint_offset);
+
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save fltcon0 %#010x\n",
+			 bank->name, save->eint_fltcon0);
+		pr_debug("%s: save fltcon1 %#010x\n",
+			 bank->name, save->eint_fltcon1);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
+	} else if (bank->eint_type == EINT_TYPE_WKUP) {
+		exynos_set_wakeup(bank);
+	}
 }
 
-void exynos_pinctrl_suspend(struct samsung_pin_bank *bank)
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank)
 {
-	struct exynos_irq_chip *irq_chip = NULL;
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	const void __iomem *regs = bank->eint_base;
 
 	if (bank->eint_type == EINT_TYPE_GPIO) {
-		if (bank->eint_con_offset)
-			exynosauto_pinctrl_suspend_bank(bank);
-		else
-			exynos_pinctrl_suspend_bank(bank);
+		save->eint_con = readl(regs + bank->pctl_offset +
+				       bank->eint_con_offset);
+		save->eint_mask = readl(regs + bank->pctl_offset +
+					bank->eint_mask_offset);
+		pr_debug("%s: save     con %#010x\n",
+			 bank->name, save->eint_con);
+		pr_debug("%s: save    mask %#010x\n",
+			 bank->name, save->eint_mask);
 	} else if (bank->eint_type == EINT_TYPE_WKUP) {
-		if (!irq_chip) {
-			irq_chip = bank->irq_chip;
-			irq_chip->set_eint_wakeup_mask(bank->drvdata, irq_chip);
-		}
+		exynos_set_wakeup(bank);
 	}
 }
 
-static void exynos_pinctrl_resume_bank(struct samsung_pin_bank *bank)
+void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_ECON_OFFSET
-			+ bank->eint_offset), save->eint_con);
-	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset), save->eint_fltcon0);
-	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-			readl(regs + bank->irq_chip->eint_mask
-			+ bank->eint_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
-						+ bank->eint_offset);
+	if (bank->eint_type == EINT_TYPE_GPIO) {
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			       + bank->eint_offset), save->eint_con);
+		pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset), save->eint_fltcon0);
+		pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+			 readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			       + 2 * bank->eint_offset + 4),
+			 save->eint_fltcon1);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->irq_chip->eint_mask
+			       + bank->eint_offset), save->eint_mask);
+
+		writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+		       + bank->eint_offset);
+		writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset);
+		writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+		       + 2 * bank->eint_offset + 4);
+		writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+		       + bank->eint_offset);
+	}
 }
 
-static void exynosauto_pinctrl_resume_bank(struct samsung_pin_bank *bank)
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank)
 {
 	struct exynos_eint_gpio_save *save = bank->soc_priv;
 	void __iomem *regs = bank->eint_base;
 
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
-	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
-		 readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
-
-	writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
-	writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
-
-}
-
-void exynos_pinctrl_resume(struct samsung_pin_bank *bank)
-{
 	if (bank->eint_type == EINT_TYPE_GPIO) {
-		if (bank->eint_con_offset)
-			exynosauto_pinctrl_resume_bank(bank);
-		else
-			exynos_pinctrl_resume_bank(bank);
+		/* exynosautov920 has eint_con_offset for all but one bank */
+		if (!bank->eint_con_offset)
+			exynos_pinctrl_resume(bank);
+
+		pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset + bank->eint_con_offset),
+			 save->eint_con);
+		pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			 readl(regs + bank->pctl_offset +
+			       bank->eint_mask_offset), save->eint_mask);
+
+		writel(save->eint_con,
+		       regs + bank->pctl_offset + bank->eint_con_offset);
+		writel(save->eint_mask,
+		       regs + bank->pctl_offset + bank->eint_mask_offset);
 	}
 }
 
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 69be0746e29d9714a33f4aa49df0e8d7257b4220..35c2bc4ea488bda600ebfbda1492f5f49dbd9849 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -221,6 +221,8 @@ struct exynos_muxed_weint_data {
 
 int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d);
 int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d);
+void exynosautov920_pinctrl_resume(struct samsung_pin_bank *bank);
+void exynosautov920_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_suspend(struct samsung_pin_bank *bank);
 void exynos_pinctrl_resume(struct samsung_pin_bank *bank);
 struct samsung_retention_ctrl *

-- 
2.49.0.rc1.451.g8f38331e32-goog



From andrew at lunn.ch  Wed Mar 12 15:10:57 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 12 Mar 2025 23:10:57 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
Message-ID: <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>

> This is not an approach that works with the Linux kernel, sorry.
> 
> What we have today is a driver that works for people's hardware - and
> we don't know what the capabilities of that hardware is.
> 
> If there's hardware out there today which has XAE_ABILITY_2_5G set, but
> defaults to <=1G mode, this will work with the current driver. However,
> with your patch applied, it stops working because instead of the driver
> indicating MAC_10FD | MAC_100FD | MAC_1000FD, it only indicates
> MAC_2500FD. If this happens, it will regress users setups, and that is
> something we try not to do.
> 
> Saying "someone else needs to add the code for their FPGA logic" misses
> the point - there may not be "someone else" to do that, which means
> the only option is to revert your change if it were merged. That in
> itself can cause its own user regressions because obviously stuff that
> works with this patch stops working.
> 
> This is why we're being cautious, and given your responses, it's not
> making Andrew or myself feel that there's a reasonable approach being
> taken here.
> 
> >From everything you have said, I am getting the feeling that using
> XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is just
> wrong. Given that we're talking about an implementation that has been
> synthesized at 2.5G and can't operate slower, maybe there's some way
> that could be created to specify that in DT?
> 
> e.g. (and I'm sure the DT folk aren't going to like it)...
> 
> 	xlnx,axi-ethernet-X.YY.Z-2.5G
> 
> (where X.YY.Z is the version) for implementations that can _only_ do
> 2.5G, and leave all other implementations only doing 1G and below.
> 
> Or maybe some DT property. Or something else.

Given that AMD has been talking about an FPGA, not silicon, i actually
think it would be best to change the IP to explicitly enumerate how it
has been synthesised. Make use of some register bits which currently
read as 0. Current IP would then remain as 1000BaseX/SGMII,
independent of how they have been synthesised. Newer versions of the
IP will then set the bits if they have been synthesised as 2) or 3),
and the driver can then enable that capability, without breaking
current generation systems. Plus there needs to be big fat warning for
anybody upgrading to the latest version of the IP for bug fixes to
ensure they correctly set the synthesis options because it now
actually matters.

	 Andrew


From helgaas at kernel.org  Wed Mar 12 15:16:25 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 12 Mar 2025 17:16:25 -0500
Subject: [PATCH v10 04/10] PCI: dwc: Add helper
 dw_pcie_init_parent_bus_offset()
In-Reply-To: <20250310-pci_fixup_addr-v10-4-409dafc950d1@nxp.com>
Message-ID: <20250312221625.GA711258@bhelgaas>

On Mon, Mar 10, 2025 at 04:16:42PM -0400, Frank Li wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
> 
> Set pci->parent_bus_offset based on the parent bus address from the
> "config" (Root complex mode) and "addr_space" (Endpoint mode).
> 
> .cpu_addr_fixup(cpu_phy_addr). (if implemented) should return the parent
> bus address corresponding according to cpu_phy_addr.
> 
> Sets pp->parent_bus_offset, but doesn't use it, so no functional change
> intended yet.
> 
> Add use_parent_dt_ranges to detect some fake bus translation at platform,
> which have not .cpu_addr_fixup(). Set use_parent_dt_ranges true explicitly
> at platform that have .cpu_addr_fixup() and fixed DTB's range. If not one
> report "fake bus translation" for sometime, this flags can be removed
> safely.

> +int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
> +				   resource_size_t cpu_phy_addr)
> +{
> +	struct device *dev = pci->dev;
> +	struct device_node *np = dev->of_node;
> +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
> +	u64 reg_addr, fixup_addr;
> +	int index;
> +
> +	/* Look up reg_name address on parent bus */
> +	index = of_property_match_string(np, "reg-names", reg_name);
> +
> +	if (index < 0) {
> +		dev_err(dev, "Missed reg-name: %s, Broken DTB file\n", reg_name);
> +		return -EINVAL;
> +	}
> +
> +	of_property_read_reg(np, index, &reg_addr, NULL);
> +
> +	fixup = pci->ops->cpu_addr_fixup;
> +	if (fixup) {
> +		fixup_addr = fixup(pci, cpu_phy_addr);
> +		if (reg_addr == fixup_addr) {
> +			dev_info(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
> +				 cpu_phy_addr, reg_name, index,
> +				 fixup_addr, fixup);
> +		} else {
> +			dev_warn_once(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; DT is broken\n",
> +				      cpu_phy_addr, reg_name,
> +				      index, fixup_addr);
> +			reg_addr = fixup_addr;
> +		}
> +	} else if (!pci->use_parent_dt_ranges) {
> +		if (reg_addr != cpu_phy_addr) {
> +			dev_warn_once(dev, "Your DTB try to use fake translation, Please check parent's ranges property,");
> +			return 0;

IIUC the point of this is to catch a DT that describes a non-zero
offset when the driver did not implement .cpu_addr_fixup() and
therefore assumed "reg_addr == cpu_phy_addr".

I guess that makes sense.  But I think we should include both
addresses in the message to help understand the issue.

> +		}
> +	}
> +
> +	pci->parent_bus_offset = cpu_phy_addr - reg_addr;
> +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> +		 reg_name, pci->parent_bus_offset);
> +
> +	return 0;
> +}

> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -465,6 +466,16 @@ struct dw_pcie {
>  	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
>  	struct gpio_desc		*pe_rst;
>  	bool			suspended;
> +	/*
> +	 * This flag indicates that the vendor driver uses devicetree 'ranges'
> +	 * property to allow iATU to use the Intermediate Address (IA) for
> +	 * outbound mapping. Using this flag also avoids the usage of
> +	 * 'cpu_addr_fixup' callback implementation in the driver.

This part of the comment is now wrong.

> +	 * If use_parent_dt_ranges is false, warning will print if IA is not
> +	 * equal to cpu physical address. Indicate dtb use a fake translation.
> +	 */
> +	bool			use_parent_dt_ranges;
>  };


From ukleinek at kernel.org  Wed Mar 12 15:56:14 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Wed, 12 Mar 2025 23:56:14 +0100
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <57ae63a2-544b-4241-a54d-8fa9917c1e44@mleia.com>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
 <57ae63a2-544b-4241-a54d-8fa9917c1e44@mleia.com>
Message-ID: <yvljnqnlka3ecw2n3hw2zgfszlldvbww3k7gq72dczmf6jwzfo@4vqnygxuzvk5>

Hello,

On Wed, Mar 12, 2025 at 07:59:21PM +0200, Vladimir Zapolskiy wrote:
> > +  "#pwm-cells":
> > +    const: 3
> 
> It shall be 1.

No, 3 is the right choice.

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250312/a866370b/attachment.sig>

From pablo at netfilter.org  Wed Mar 12 16:11:40 2025
From: pablo at netfilter.org (Pablo Neira Ayuso)
Date: Thu, 13 Mar 2025 00:11:40 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <58cbe875-80e7-4a44-950b-b836b97f3259@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
 <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com>
 <Z9DKxOnxr1fSv0On@calendula>
 <58cbe875-80e7-4a44-950b-b836b97f3259@gmail.com>
Message-ID: <Z9IUrL0IHTKQMUvC@calendula>

On Wed, Mar 12, 2025 at 05:21:29PM +0100, Eric Woudstra wrote:
> 
> 
> On 3/12/25 12:44 AM, Pablo Neira Ayuso wrote:
> > Therefore, I suggest you start with a much smaller series with a
> > carefully selected subset including preparatory patches. I suggest you
> > start with the software enhancements only. Please, add datapath tests.
> 
> Then I will split it in:
> 1. Separate preparatory patches and small patch-sets that apply
>      to the forward-fastpath already.
> 2. One patch-set that brings the bridge-fastpath with datapath tests.
> 
> > P.S: You work is important, very important, but maybe there is no need
> > to Cc so many mailing lists and people, maybe netdev@,
> > netfilter-devel@ and bridge@ is sufficient.
> 
> Ok, but my main question then is which tree should I work in, and
> therefore which tag should I give my patches, [nf] or [net-next].
> I think it will get more complicated if I split my patch-set and half of
> the patches go to [nf] and another half to [net-next].

Use [nf-next].

> What do you suggest?

Probably I can collect 4/15 and 5/15 from this series to be included
in the next pull request, let me take a look. But it would be good to
have tests for these two patches.

I would suggest you continue by making a series to add bridge support
for the flowtable, software only, including tests.

Once this gets merged, then follow up with the hardware offload code.

Thanks.


From jacob.e.keller at intel.com  Wed Mar 12 16:47:34 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Wed, 12 Mar 2025 16:47:34 -0700
Subject: [PATCH RESEND net-next v2] net: stmmac: dwmac-rk: Provide FIFO
 sizes for DWMAC 1000
In-Reply-To: <20250312163426.2178314-1-wens@kernel.org>
References: <20250312163426.2178314-1-wens@kernel.org>
Message-ID: <468cfeef-3562-4b04-a2c1-e4000472dc85@intel.com>



On 3/12/2025 9:34 AM, Chen-Yu Tsai wrote:
> From: Chen-Yu Tsai <wens at csie.org>
> 
> The DWMAC 1000 DMA capabilities register does not provide actual
> FIFO sizes, nor does the driver really care. If they are not
> provided via some other means, the driver will work fine, only
> disallowing changing the MTU setting.
> 
> Provide the FIFO sizes through the driver's platform data to enable
> MTU changes. The FIFO sizes are confirmed to be the same across RK3288,
> RK3328, RK3399 and PX30, based on their respective manuals. It is
> likely that Rockchip synthesized their DWMAC 1000 with the same
> parameters on all their chips that have it.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---

Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>


From broonie at kernel.org  Wed Mar 12 16:49:12 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:12 +0000
Subject: [PATCH 6.13 4/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.ZEN
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-4-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 16 ----------------
 2 files changed, 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0b39888e86d6d40fea56bb6cb8ccdbaf480d0d55..fe25d411d3d8efbe19d5ffba8ea23bf98eb06c38 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 2ee6bde85235581d6bc9cba7e578c55875b5d5a1..4127abfd319c2c683d2281efa52a6abe5fac67ee 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:13 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:13 +0000
Subject: [PATCH 6.13 5/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.SMEN
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-5-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 21 ---------------------
 2 files changed, 23 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fe25d411d3d8efbe19d5ffba8ea23bf98eb06c38..06e3cfc9a73b8c95712580b13b926b6471a16be7 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 4127abfd319c2c683d2281efa52a6abe5fac67ee..f64724197958e0d8a4ec17deb1f9826ce3625eb7 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:14 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:14 +0000
Subject: [PATCH 6.13 6/8] KVM: arm64: Refactor exit handlers
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-6-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 7601d741bc2ae77ca9f359e4901926a5feac48b9..e330a7825b56f14ccb144810bc0d31f7f400fb22 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -666,23 +666,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -712,20 +705,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -755,7 +737,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7..ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index e7ca0424107adec2371ae4553ebab9857c60b6d9..46c1f5caf007331cdbbc806a184e9b4721042fc0 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:15 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:15 +0000
Subject: [PATCH 6.13 7/8] KVM: arm64: Mark some header functions as inline
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-7-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index e330a7825b56f14ccb144810bc0d31f7f400fb22..300ec597cf1257954019f50cce44d662d6420790 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -326,7 +326,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -404,7 +404,7 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -595,7 +595,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -615,7 +615,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -624,19 +624,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:08 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:08 +0000
Subject: [PATCH 6.13 0/8] KVM: arm64: Backport of SVE fixes to v6.13
Message-ID: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>

This series backports some recent fixes for SVE/KVM interactions from
Mark Rutland to v6.13.

Signed-off-by: Mark Brown <broonie at kernel.org>
---
Fuad Tabba (1):
      KVM: arm64: Calculate cptr_el2 traps on activating traps

Mark Rutland (7):
      KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
      KVM: arm64: Remove host FPSIMD saving for non-protected KVM
      KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
      KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
      KVM: arm64: Refactor exit handlers
      KVM: arm64: Mark some header functions as inline
      KVM: arm64: Eagerly switch ZCR_EL{1,2}

 arch/arm64/include/asm/kvm_host.h       |  25 ++----
 arch/arm64/kernel/fpsimd.c              |  25 ------
 arch/arm64/kvm/arm.c                    |   9 ---
 arch/arm64/kvm/fpsimd.c                 | 100 ++----------------------
 arch/arm64/kvm/hyp/entry.S              |   5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 133 ++++++++++++++++++++++---------
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  15 ++--
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  30 -------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 134 ++++++++++++++++++--------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  21 ++---
 10 files changed, 204 insertions(+), 293 deletions(-)
---
base-commit: 251aeb0f2f570db5290d0dc2f8ebf87247b00b85
change-id: 20250227-stable-sve-6-13-5ceaf408b5f7

Best regards,
-- 
Mark Brown <broonie at kernel.org>



From broonie at kernel.org  Wed Mar 12 16:49:09 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:09 +0000
Subject: [PATCH 6.13 1/8] KVM: arm64: Calculate cptr_el2 traps on
 activating traps
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-1-c7ba07a6f4f7@kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  1 -
 arch/arm64/kvm/arm.c              |  1 -
 arch/arm64/kvm/hyp/nvhe/pkvm.c    | 30 -----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  | 51 ++++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 51 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index c85aa4f1def810a08e7bfa4ab181760839521c25..6762dadce45deb657b6e8df3e14dc9fbef884f1d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -708,7 +708,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3b3ecfed294f2be5bf545f4e89ba6e53415625f5..591f512ab072963424f4b2287a1a572fc72bd639 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1569,7 +1569,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 071993c16de81ca0b0181c56d0598b1b026ae018..6405fa30f961723c0da0761be079e09f91b7e8e1 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -31,8 +31,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -62,21 +60,10 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -106,7 +93,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -133,21 +119,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -198,10 +175,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
@@ -236,7 +209,6 @@ static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
  */
 static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 	vcpu->arch.mdcr_el2 = 0;
 
 	pkvm_vcpu_reset_hcr(vcpu);
@@ -693,8 +665,6 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index cc69106734ca732ba9276ac1eaf84be3e7381648..81d933a71310fd1132b2450cd08108e071a2cf78 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
+
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:10 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:10 +0000
Subject: [PATCH 6.13 2/8] KVM: arm64: Unconditionally save+flush host
 FPSIMD/SVE/SME state
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-2-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 25 -------------------------
 arch/arm64/kvm/fpsimd.c    | 35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 8c4c1a2186cc510a7826d15ec36225857c07ed71..ec68d520b7ca70e7395bab4bc78fc9a7405d6b92 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void)
 		sve_to_fpsimd(current);
 }
 
-/*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
 /*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index ea5484ce1f3ba3121b6938bda15f7a8057d49051..efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:11 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:11 +0000
Subject: [PATCH 6.13 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-3-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[CPACR_EL1_ZEN -> CPACR_ELx_ZEN -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       | 20 +++++---------------
 arch/arm64/kvm/arm.c                    |  8 --------
 arch/arm64/kvm/fpsimd.c                 |  2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h | 25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  8 --------
 7 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 6762dadce45deb657b6e8df3e14dc9fbef884f1d..0b39888e86d6d40fea56bb6cb8ccdbaf480d0d55 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -613,23 +613,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
-
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	struct cpu_sve_state *sve_state;
+
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 591f512ab072963424f4b2287a1a572fc72bd639..78acbd589968771674f6cecaea6d9254eaeb6b8a 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2468,14 +2468,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5..2ee6bde85235581d6bc9cba7e578c55875b5d5a1 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 34f53707892dfe7bba41620e7adb65f1f8376018..7601d741bc2ae77ca9f359e4901926a5feac48b9 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,7 +375,28 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -425,7 +446,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 6aa0b13d86e581a36ed529bcd932498045d2d6df..7262983c75fbc18ab44f52753bff1dd9167a68d3 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 81d933a71310fd1132b2450cd08108e071a2cf78..3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 80581b1c399595fd64d0ccada498edac322480a6..e7ca0424107adec2371ae4553ebab9857c60b6d9 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;

-- 
2.39.5



From broonie at kernel.org  Wed Mar 12 16:49:16 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 12 Mar 2025 23:49:16 +0000
Subject: [PATCH 6.13 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
Message-ID: <20250312-stable-sve-6-13-v1-8-c7ba07a6f4f7@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
(cherry picked from commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59)
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/fpsimd.c                 | 30 -----------------
 arch/arm64/kvm/hyp/entry.S              |  5 +++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 13 ++++----
 arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
 6 files changed, 103 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index f64724197958e0d8a4ec17deb1f9826ce3625eb7..3cbb999419af7bb31ce9cec2baafcad00491610a 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 4433a234aa9ba242f43b943d22011b5ddacd8af7..9f4e8d68ab505cf4a7aa8673643d9b47ca1bc7cb 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 300ec597cf1257954019f50cce44d662d6420790..bcf3a537aac36c705b60a2b99df6061ae110a934 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,6 +375,65 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 7262983c75fbc18ab44f52753bff1dd9167a68d3..84326765c66087d992a517a19fea94b04c39c994 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -178,8 +179,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
 		sync_hyp_vcpu(hyp_vcpu);
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
+		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
+
 		/* The host is fully trusted, run its vCPU directly. */
-		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_guest(vcpu);
+		ret = __kvm_vcpu_run(vcpu);
+		fpsimd_lazy_switch_to_host(vcpu);
 	}
 
 out:
@@ -480,12 +485,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494..a1245fa838319544f3770a05a58eeed5233f0324 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 46c1f5caf007331cdbbc806a184e9b4721042fc0..496abfd3646b9858e95e06a79edec11eee3a5893 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())

-- 
2.39.5



From lkp at intel.com  Wed Mar 12 17:19:09 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 13 Mar 2025 08:19:09 +0800
Subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller
 driver
In-Reply-To: <20250309180940.1322531-4-jan.dakinevich@salutedevices.com>
References: <20250309180940.1322531-4-jan.dakinevich@salutedevices.com>
Message-ID: <202503131003.x6L69hJL-lkp@intel.com>

Hi Jan,

kernel test robot noticed the following build errors:

[auto build test ERROR on clk/clk-next]
[also build test ERROR on robh/for-next krzk/for-next krzk-dt/for-next linus/master v6.14-rc6 next-20250312]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jan-Dakinevich/clk-meson-axg-share-the-set-of-audio-helper-macros/20250310-022012
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
patch link:    https://lore.kernel.org/r/20250309180940.1322531-4-jan.dakinevich%40salutedevices.com
patch subject: [PATCH v6 3/4] clk: meson: a1: add the audio clock controller driver
config: arm64-randconfig-r131-20250312 (https://download.01.org/0day-ci/archive/20250313/202503131003.x6L69hJL-lkp at intel.com/config)
compiler: aarch64-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250313/202503131003.x6L69hJL-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503131003.x6L69hJL-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/clk/meson/a1-audio.c: In function 'a1_audio_clkc_probe':
>> drivers/clk/meson/a1-audio.c:807:18: error: implicit declaration of function '__devm_auxiliary_device_create'; did you mean '__auxiliary_device_add'? [-Wimplicit-function-declaration]
     807 |         auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
         |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                  __auxiliary_device_add
>> drivers/clk/meson/a1-audio.c:807:16: error: assignment to 'struct auxiliary_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     807 |         auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
         |                ^


vim +807 drivers/clk/meson/a1-audio.c

   748	
   749	static int a1_audio_clkc_probe(struct platform_device *pdev)
   750	{
   751		struct device *dev = &pdev->dev;
   752		const struct a1_audio_data *data;
   753		struct auxiliary_device *auxdev;
   754		struct regmap *map;
   755		void __iomem *base;
   756		struct clk *clk;
   757		unsigned int i;
   758		int ret;
   759	
   760		data = device_get_match_data(dev);
   761		if (!data)
   762			return -EINVAL;
   763	
   764		clk = devm_clk_get_enabled(dev, "pclk");
   765		if (IS_ERR(clk))
   766			return PTR_ERR(clk);
   767	
   768		base = devm_platform_ioremap_resource(pdev, 0);
   769		if (IS_ERR(base))
   770			return PTR_ERR(base);
   771	
   772		map = devm_regmap_init_mmio(dev, base, &a1_audio_regmap_cfg);
   773		if (IS_ERR(map))
   774			return PTR_ERR(map);
   775	
   776		ret = device_reset(dev);
   777		if (ret)
   778			return ret;
   779	
   780		for (i = 0; i < data->hw_clks.num; i++) {
   781			struct clk_hw *hw = data->hw_clks.hws[i];
   782			struct clk_regmap *clk_regmap = to_clk_regmap(hw);
   783	
   784			if (!hw)
   785				continue;
   786	
   787			clk_regmap->map = map;
   788		}
   789	
   790		for (i = 0; i < data->hw_clks.num; i++) {
   791			struct clk_hw *hw;
   792	
   793			hw = data->hw_clks.hws[i];
   794			if (!hw)
   795				continue;
   796	
   797			ret = devm_clk_hw_register(dev, hw);
   798			if (ret)
   799				return ret;
   800		}
   801	
   802		ret = devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
   803						  (void *)&data->hw_clks);
   804		if (ret)
   805			return ret;
   806	
 > 807		auxdev = __devm_auxiliary_device_create(dev, dev->driver->name,
   808							data->rst_drvname, NULL, 0);
   809		if (!auxdev)
   810			return -ENODEV;
   811	
   812		return 0;
   813	}
   814	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From andyshrk at 163.com  Wed Mar 12 17:23:43 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 13 Mar 2025 08:23:43 +0800 (CST)
Subject: [PATCH v2 2/7] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <61E9B36C-8568-4C0E-A9A7-07FF612912AA@gmail.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-3-andyshrk@163.com>
 <61E9B36C-8568-4C0E-A9A7-07FF612912AA@gmail.com>
Message-ID: <381bbdeb.342.1958ce2b7f8.Coremail.andyshrk@163.com>


Hi Piotr,
? 2025-03-12 22:23:15?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
>
>
>> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 12 mar 2025, o godz. 11:42:
>> 
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> The DW DP TX Controller is compliant with the DisplayPort Specification
>> Version 1.4 with the following features:
>> 
>> * DisplayPort 1.4a
>> * Main Link: 1/2/4 lanes
>> * Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
>> * AUX channel 1Mbps
>> * Single Stream Transport(SST)
>> * Multistream Transport (MST)
>> * Type-C support (alternate mode)
>> * HDCP 2.2, HDCP 1.3
>> * Supports up to 8/10 bits per color component
>> * Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
>> * Pixel clock up to 594MHz
>> * I2S, SPDIF audio interface
>> 
>> Add library with common helpers to make it can be shared with
>> other SoC.
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> 
>> ---
>> 
>> Changes in v2:
>> - Fix compile error when build as module
>> - Add phy init
>> - Only use one dw_dp_link_train_set
>> - inline dw_dp_phy_update_vs_emph
>> - Use dp_sdp
>> - Check return value of drm_modeset_lock
>> - Merge code in atomic_pre_enable/mode_fixup to atomic_check
>> - Return NULL if can't find a supported output format
>> - Fix max_link_rate from plat_data
>> 
>
>Andy,
>
>Just small Q: do v2 needs something extra to get it working (particular kernel ver or extra dependency patches)?
>I just replaced v1 to v2 and dp stopped to work for me.

This series still  based on Linux 6.14 rc4.

Did you apply the three dependency patch mentioned in my cover letter?


>
>e.g. on rock5a i?m getting:
>
>root at myth-frontend-fafc53b591a6:~ # dmesg | grep drm
>[    9.245284] panthor fb000000.gpu: [drm] clock rate = 198000000
>[    9.249464] panthor fb000000.gpu: [drm] mali-g610 id 0xa867 major 0x0 minor 0x0 status 0x5
>[    9.249472] panthor fb000000.gpu: [drm] Features: L2:0x7120306 Tiler:0x809 Mem:0x301 MMU:0x2830 AS:0xff
>[    9.249474] panthor fb000000.gpu: [drm] shader_present=0x50005 l2_present=0x1 tiler_present=0x1
>[    9.257979] panthor fb000000.gpu: [drm] Firmware protected mode entry not be supported, ignoring
>[    9.258030] panthor fb000000.gpu: [drm] Firmware git sha: 814b47b551159067b67a37c4e9adda458ad9d852
>[    9.258604] panthor fb000000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 Instrumentation features 0x71
>[    9.259671] [drm] Initialized panthor 1.3.0 for fb000000.gpu on minor 0
>[    9.324353] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)
>[    9.324617] rockchip-drm display-subsystem: bound fde50000.dp (ops dw_dp_rockchip_component_ops)
>[    9.325202] rockchip-drm display-subsystem: bound fde80000.hdmi (ops dw_hdmi_qp_rockchip_ops)
>[    9.325506] [drm] Initialized rockchip 1.0.0 for display-subsystem on minor 1
>[    9.325531] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes
>[    9.325594] rockchip-drm display-subsystem: [drm] Cannot find any crtc or sizes  
>
>dp status is "not connected"
>
>replacing only this patch back to v1 brings dp back to work.
>
>

From andyshrk at 163.com  Wed Mar 12 17:32:55 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 13 Mar 2025 08:32:55 +0800 (CST)
Subject: [PATCH v2 7/7] arm64: dts: rockchip: Enable DP2HDMI for ROCK
 5 ITX
In-Reply-To: <q3y36jgswj4xa2g3hnptc6kgzphbqfg675r5paa2lwvdseytio@jysj4f2i6osu>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-8-andyshrk@163.com>
 <q3y36jgswj4xa2g3hnptc6kgzphbqfg675r5paa2lwvdseytio@jysj4f2i6osu>
Message-ID: <5858d492.44b.1958ceb23dd.Coremail.andyshrk@163.com>


Hi Dmitry,

At 2025-03-12 20:39:17, "Dmitry Baryshkov" <lumag at kernel.org> wrote:
>On Wed, Mar 12, 2025 at 06:42:08PM +0800, Andy Yan wrote:
>> From: Andy Yan <andy.yan at rock-chips.com>
>> 
>> The HDMI Port next to Headphone Jack is drived by
>> DP1 on rk3588 via a dp2hdmi converter.
>> 
>> Add related dt nodes to enable it.
>> 
>> Note: ROCKCHIP_VOP2_EP_DP1 is defined as 11 in dt-binding header,
>> but it will trigger a dtc warning like "graph node unit address
>> error, expected "b"" if we use it directly after endpoint, so we
>> use "b" instead here.
>> 
>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>> ---
>> 
>> (no changes since v1)
>> 
>>  .../boot/dts/rockchip/rk3588-rock-5-itx.dts   | 37 +++++++++++++++++++
>>  1 file changed, 37 insertions(+)
>> 
>> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
>> index 67b886329248..29f10ec9f0c1 100644
>> --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
>> +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
>> @@ -57,6 +57,18 @@ analog-sound {
>>  			  "Headphone", "Headphones";
>>  	};
>>  
>> +	dp-con {
>> +		compatible = "dp-connector";
>
>You've written that it is an HDMI connector. Could you possibly clarify,
>why is it being registered as a DP connector? Is there any kind of
>a bridge between the DP controller and the HDMI connector?

When I was preparing this patch at that time, I also had some doubts. 
Whether it should be registered as a DP connector or an HDMI connector. 
There is a DP2HDMI conversion chip between the DP of RK3588 and this hdmi 
interface, but this conversion chip does not require a software driver. 
If the current writing is incorrect, I will change it to hdmi-connector in the next version.

Thanks
>
>> +		label = "DP OUT";
>> +		type = "full-size";
>> +
>> +		port {
>> +			dp_con_in: endpoint {
>> +				remote-endpoint = <&dp1_out_con>;
>> +			};
>> +		};
>> +	};
>> +
>>  	gpio-leds {
>>  		compatible = "gpio-leds";
>>  		pinctrl-names = "default";
>> @@ -268,6 +280,24 @@ &cpu_l3 {
>>  	cpu-supply = <&vdd_cpu_lit_s0>;
>>  };
>>  
>> +&dp1 {
>> +	status = "okay";
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&dp1m0_pins>;
>> +};
>> +
>> +&dp1_in {
>> +	dp1_in_vp2: endpoint {
>> +		remote-endpoint = <&vp2_out_dp1>;
>> +	};
>> +};
>> +
>> +&dp1_out {
>> +	dp1_out_con: endpoint {
>> +		remote-endpoint = <&dp_con_in>;
>> +	};
>> +};
>> +
>>  &gpu {
>>  	mali-supply = <&vdd_gpu_s0>;
>>  	status = "okay";
>> @@ -1262,3 +1292,10 @@ vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
>>  		remote-endpoint = <&hdmi1_in_vp1>;
>>  	};
>>  };
>> +
>> +&vp2 {
>> +	vp2_out_dp1: endpoint at b {
>> +		reg = <ROCKCHIP_VOP2_EP_DP1>;
>> +		remote-endpoint = <&dp1_in_vp2>;
>> +	};
>> +};
>> -- 
>> 2.34.1
>> 
>
>-- 
>With best wishes
>Dmitry

From chenyuan0y at gmail.com  Wed Mar 12 18:15:05 2025
From: chenyuan0y at gmail.com (Chenyuan Yang)
Date: Wed, 12 Mar 2025 20:15:05 -0500
Subject: [PATCH] can: rockchip: bail out if skb cannot be allocated
Message-ID: <20250313011506.3132295-1-chenyuan0y@gmail.com>

Add NULL pointer check in rkcanfd_handle_error_int() to
bail out if skb cannot be allocated.

This is similar to the commit f7f0adfe64de
("can: rockchip: rkcanfd_handle_rx_fifo_overflow_int(): bail out if skb cannot be allocated").

Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
---
 drivers/net/can/rockchip/rockchip_canfd-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index d9a937ba126c..90395cbdaab9 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -551,7 +551,7 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
 
 	rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec);
 
-	if (!cf)
+	if (!cf || !skb)
 		return 0;
 
 	err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
-- 
2.34.1



From quic_jiegan at quicinc.com  Wed Mar 12 18:32:14 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Thu, 13 Mar 2025 09:32:14 +0800
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <CAJ9a7VhDD3813LtH_5AYyM-2mhCNP+vRmqXn4RWqg5F8FEe-Mg@mail.gmail.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com>
 <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>
 <cef984d5-f369-4892-b970-a71285c2ebc5@quicinc.com>
 <CAJ9a7VhDD3813LtH_5AYyM-2mhCNP+vRmqXn4RWqg5F8FEe-Mg@mail.gmail.com>
Message-ID: <51aab2c3-2219-454f-93b1-5820a9c2ced1@quicinc.com>



On 3/12/2025 8:54 PM, Mike Leach wrote:
> Hi Jie,
> 
> On Wed, 12 Mar 2025 at 01:21, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>
>>
>>
>> On 3/12/2025 12:49 AM, Mike Leach wrote:
>>> Hi,
>>>
>>> On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>>>
>>>> The new functions calculate and return the offset to the write pointer of
>>>> the ETR buffer based on whether the memory mode is SG, flat or reserved.
>>>> The functions have the RWP offset can directly read data from ETR buffer,
>>>> enabling the transfer of data to any required location.
>>>>
>>>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>>>> ---
>>>>    .../hwtracing/coresight/coresight-tmc-etr.c   | 40 +++++++++++++++++++
>>>>    drivers/hwtracing/coresight/coresight-tmc.h   |  1 +
>>>>    2 files changed, 41 insertions(+)
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>> index eda7cdad0e2b..ec636ab1fd75 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>> @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
>>>>    }
>>>>    EXPORT_SYMBOL_GPL(tmc_free_sg_table);
>>>>
>>>> +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata)
>>>> +{
>>>> +       dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
>>>> +       u64 rwp;
>>>> +
>>>
>>> It is not valid to read RWP if the TMC is running. It must be in the
>>> stopped or disabled state - see the specifications for TMC /ETR
>>>
>>> It is likely that CSUNLOCK / CSLOCK are needed here too,  along with
>>> the spinlock that protects drvdata
>>>
>>> See the code in coresight_tmc_etr.c :-
>>>
>>> e.g. in
>>>
>>> tmc_update_etr_buffer()
>>>
>>> ...
>>> <take spinlock>
>>> ...
>>> CS_UNLOCK(drvdata->base);
>>> tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and
>>> flushed to memory - essential to ensure full formatted frame is in
>>> memory.
>>> tmc_sync_etr_buf(drvdata); // this function reads rwp.
>>> CS_LOCK(drvdata->base);
>>> <release spinlokc>
>>>
>>> This type of program flow is common to both sysfs and perf handling of
>>> TMC buffers.
>>
>> Hi Mike,
>>
>> I am fully understood your point here.
>>
>> The function is designed this way to read the w_offset (which may not be
>> entirely accurate because the etr buffer is not synced) when the
> 
> Why would you ever base memory access on a pointer that is not
> entirely accurate?
> 
> The manuals for TMC/ETR all state that reads to both RWP and RRP when
> the ETR is running return unknown values. These cannot be used to
> access the buffer, or determine how much of the buffer has been used
> on a running ETR.
> 
> The ETR specification specifically states that it is not permitted to
> read the buffer data while the ETR is running, when configured in
> circular buffer mode - which is the mode used in the TMC-ETR linux
> drivers.
> 
> Reading the buffer while ETR is running is only permitted if
> configured in Software FIFO mode 2 - were the ETR will stop on full
> and stall incoming trace until some data is read out, signalled to the
> ETR via the RURP.
> 

Hi Mike,

I appreciate for your patient explanation.

I was wrong about read data from etr_buffer. I must follow the 
specification to design a method to reading buffer while ETR is running.

How about the following method:

1. The byte-cntr interrupt handler will count the IRQ triggered number 
when byte-cntr file node is opened.
2. Read the buffer after the ETR is stopped(full or stopped manually) 
according to the counted number. we got the etr->offset, etr->size and 
the counted number, so we can calculate the offset where starts to read.
3. Restart the ETR to keep counting the number of IRQ triggers.

Thanks,
Jie

> I also note that you are reading back the etr_buf data without doing
> any dma_sync operations that the perf and sysfs methods in the driver
> do, after stopping the tmc.
> 
>> byte-cntr devnode is opened, aiming to reduce the length of redundant
>> trace data. In this case, we cannot ensure the TMC is stopped or
>> disabled.
> 
> The specification requires that you must ensure the TMC is stopped to
> read these registers.
> 
> 
>> The byte-cntr only requires an offset to know where it can
>> start before the expected trace data gets into ETR buffer.
>>
>> The w_offset is also read when the byte-cntr function stops, which
>> occurs after the TMC is disabled.
>>
>> Maybe this is not a good idea and I should read r_offset upon open?
>> The primary goal for byte-cntr is trying to transfer useful trace data
>> from the ETR buffer to the userspace, if we start from r_offset, a large
>> number of redundant trace data which the user does not expect will be
>> transferred simultaneously.
>>
>>
> 
> It is difficult to justify adding code to a driver that does not
> correspond to the specification of the hardware device.
> 
> Regards
> 
> Mike
> 
>>>
>>>> +       rwp = tmc_read_rwp(drvdata);
>>>> +       return rwp - paddr;
>>>> +}
>>>> +
>>>> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
>>>> +{
>>>> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
>>>> +       struct etr_sg_table *etr_table = etr_buf->private;
>>>> +       struct tmc_sg_table *table = etr_table->sg_table;
>>>> +       long w_offset;
>>>> +       u64 rwp;
>>>> +
>>>
>>> Same comments as above
>>>
>>>> +       rwp = tmc_read_rwp(drvdata);
>>>> +       w_offset = tmc_sg_get_data_page_offset(table, rwp);
>>>> +
>>>> +       return w_offset;
>>>> +}
>>>> +
>>>> +/*
>>>> + * Retrieve the offset to the write pointer of the ETR buffer based on whether
>>>> + * the memory mode is SG, flat or reserved.
>>>> + */
>>>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
>>>> +{
>>>> +       struct etr_buf *etr_buf = drvdata->sysfs_buf;
>>>> +
>>>
>>> As this is an exported function, please ensure that the inputs are
>>> valid - check the pointers
>>
>> Sure, will do.
>>
>> Thanks,
>> Jie
>>
>>>
>>> Code to ensure TMC is flushed and stopped could be inserted here.
>>>
>>> Regards
>>>
>>> Mike
>>>
>>>> +       if (etr_buf->mode == ETR_MODE_ETR_SG)
>>>> +               return tmc_sg_get_rwp_offset(drvdata);
>>>> +       else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
>>>> +               return tmc_flat_resrv_get_rwp_offset(drvdata);
>>>> +       else
>>>> +               return -EINVAL;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
>>>> +
>>>>    /*
>>>>     * Alloc pages for the table. Since this will be used by the device,
>>>>     * allocate the pages closer to the device (i.e, dev_to_node(dev)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
>>>> index b48bc9a01cc0..baedb4dcfc3f 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>>>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>>>> @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
>>>>    struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>>>>                                      enum cs_mode mode, void *data);
>>>>    extern const struct attribute_group coresight_etr_group;
>>>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>>>>
>>>>    #endif
>>>> --
>>>> 2.34.1
>>>>
>>>
>>>
>>
> 
> 
> --
> Mike Leach
> Principal Engineer, ARM Ltd.
> Manchester Design Centre. UK



From ping.bai at nxp.com  Wed Mar 12 18:34:45 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu, 13 Mar 2025 01:34:45 +0000
Subject: [PATCH v2] cpufreq: Init cpufreq only for present CPUs
In-Reply-To: <Z9FY-Uu-7R9eWEQ7@bogus>
References: <20250312092127.357316-1-ping.bai@nxp.com>
 <Z9FY-Uu-7R9eWEQ7@bogus>
Message-ID: <AS8PR04MB86424CF1B1006B70025FCB4C87D32@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCH v2] cpufreq: Init cpufreq only for present CPUs
> 
> On Wed, Mar 12, 2025 at 05:21:27PM +0800, Jacky Bai wrote:
> > for_each_possible_cpu() is currently used to initialize cpufreq in
> > below cpufreq drivers:
> >   drivers/cpufreq/cpufreq-dt.c
> >   drivers/cpufreq/mediatek-cpufreq-hw.c
> >   drivers/cpufreq/mediatek-cpufreq.c
> >   drivers/cpufreq/qcom-cpufreq-nvmem.c
> >   drivers/cpufreq/sun50i-cpufreq-nvmem.c
> >
> 
> Just drop this list, totally redundant as diffstat must give that anyways.
> You have already made it stale as it doesn't match the diffstat.
> 

Ok, will drop this in v3.

BR
> With that fixed:
> 
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> 
> > However, in cpu_dev_register_generic(), for_each_present_cpu() is used
> > to register CPU devices which means the CPU devices are only
> > registered for present CPUs and not all possible CPUs.
> >
> > With nosmp or maxcpus=0, only the boot CPU is present, lead to the
> > cpufreq probe failure or defer probe due to no cpu device available
> > for not present CPUs.
> >
> > Change for_each_possible_cpu() to for_each_present_cpu() in the above
> > cpufreq drivers to ensure it only registers cpufreq for CPUs that are
> > actually present.
> >
> > Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in
> > GENERIC_CPU_DEVICES")
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v2 changes:
> >   - Add changes for armada-8k-cpufreq, mvebu-cpfureq, qcome-cpufreq-hw,
> >     scmi-cpufreq, scpi-cpufreq, virtual-cpufreq.
> > ---
> >  drivers/cpufreq/armada-8k-cpufreq.c    | 2 +-
> >  drivers/cpufreq/cpufreq-dt.c           | 2 +-
> >  drivers/cpufreq/mediatek-cpufreq-hw.c  | 2 +-
> >  drivers/cpufreq/mediatek-cpufreq.c     | 2 +-
> >  drivers/cpufreq/mvebu-cpufreq.c        | 2 +-
> >  drivers/cpufreq/qcom-cpufreq-hw.c      | 2 +-
> >  drivers/cpufreq/qcom-cpufreq-nvmem.c   | 8 ++++----
> >  drivers/cpufreq/scmi-cpufreq.c         | 2 +-
> >  drivers/cpufreq/scpi-cpufreq.c         | 2 +-
> >  drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++---
> >  drivers/cpufreq/virtual-cpufreq.c      | 2 +-
> >  11 files changed, 16 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/cpufreq/armada-8k-cpufreq.c
> > b/drivers/cpufreq/armada-8k-cpufreq.c
> > index 7a979db81f09..5a3545bd0d8d 100644
> > --- a/drivers/cpufreq/armada-8k-cpufreq.c
> > +++ b/drivers/cpufreq/armada-8k-cpufreq.c
> > @@ -47,7 +47,7 @@ static void __init armada_8k_get_sharing_cpus(struct
> > clk *cur_clk,  {
> >  	int cpu;
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		struct device *cpu_dev;
> >  		struct clk *clk;
> >
> > diff --git a/drivers/cpufreq/cpufreq-dt.c
> > b/drivers/cpufreq/cpufreq-dt.c index 778916f89a51..e80dd982a3e2 100644
> > --- a/drivers/cpufreq/cpufreq-dt.c
> > +++ b/drivers/cpufreq/cpufreq-dt.c
> > @@ -283,7 +283,7 @@ static int dt_cpufreq_probe(struct platform_device
> *pdev)
> >  	int ret, cpu;
> >
> >  	/* Request resources early so we can return in case of -EPROBE_DEFER */
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		ret = dt_cpufreq_early_init(&pdev->dev, cpu);
> >  		if (ret)
> >  			goto err;
> > diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c
> > b/drivers/cpufreq/mediatek-cpufreq-hw.c
> > index aa209f5527dc..74f1b4c796e4 100644
> > --- a/drivers/cpufreq/mediatek-cpufreq-hw.c
> > +++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
> > @@ -303,7 +303,7 @@ static int mtk_cpufreq_hw_driver_probe(struct
> platform_device *pdev)
> >  	struct regulator *cpu_reg;
> >
> >  	/* Make sure that all CPU supplies are available before proceeding. */
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		cpu_dev = get_cpu_device(cpu);
> >  		if (!cpu_dev)
> >  			return dev_err_probe(&pdev->dev, -EPROBE_DEFER, diff --git
> > a/drivers/cpufreq/mediatek-cpufreq.c
> > b/drivers/cpufreq/mediatek-cpufreq.c
> > index 2656b88db378..f3f02c4b6888 100644
> > --- a/drivers/cpufreq/mediatek-cpufreq.c
> > +++ b/drivers/cpufreq/mediatek-cpufreq.c
> > @@ -631,7 +631,7 @@ static int mtk_cpufreq_probe(struct platform_device
> *pdev)
> >  		return dev_err_probe(&pdev->dev, -ENODEV,
> >  				     "failed to get mtk cpufreq platform data\n");
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		info = mtk_cpu_dvfs_info_lookup(cpu);
> >  		if (info)
> >  			continue;
> > diff --git a/drivers/cpufreq/mvebu-cpufreq.c
> > b/drivers/cpufreq/mvebu-cpufreq.c index 7f3cfe668f30..2aad4c04673c
> > 100644
> > --- a/drivers/cpufreq/mvebu-cpufreq.c
> > +++ b/drivers/cpufreq/mvebu-cpufreq.c
> > @@ -56,7 +56,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
> >  	 * it), and registers the clock notifier that will take care
> >  	 * of doing the PMSU part of a frequency transition.
> >  	 */
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		struct device *cpu_dev;
> >  		struct clk *clk;
> >  		int ret;
> > diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c
> > b/drivers/cpufreq/qcom-cpufreq-hw.c
> > index 4b3b3dbc7d38..8422704a3b10 100644
> > --- a/drivers/cpufreq/qcom-cpufreq-hw.c
> > +++ b/drivers/cpufreq/qcom-cpufreq-hw.c
> > @@ -306,7 +306,7 @@ static void qcom_get_related_cpus(int index, struct
> cpumask *m)
> >  	struct of_phandle_args args;
> >  	int cpu, ret;
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		cpu_np = of_cpu_device_node_get(cpu);
> >  		if (!cpu_np)
> >  			continue;
> > diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > index 3a8ed723a23e..54f8117103c8 100644
> > --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> > @@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct
> platform_device *pdev)
> >  		nvmem_cell_put(speedbin_nvmem);
> >  	}
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		struct dev_pm_opp_config config = {
> >  			.supported_hw = NULL,
> >  		};
> > @@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct
> platform_device *pdev)
> >  	dev_err(cpu_dev, "Failed to register platform device\n");
> >
> >  free_opp:
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
> >  		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
> >  	}
> > @@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct
> > platform_device *pdev)
> >
> >  	platform_device_unregister(cpufreq_dt_pdev);
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
> >  		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
> >  	}
> > @@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
> >  	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
> >  	unsigned int cpu;
> >
> > -	for_each_possible_cpu(cpu)
> > +	for_each_present_cpu(cpu)
> >  		qcom_cpufreq_suspend_pd_devs(drv, cpu);
> >
> >  	return 0;
> > diff --git a/drivers/cpufreq/scmi-cpufreq.c
> > b/drivers/cpufreq/scmi-cpufreq.c index ff2897789797..c310aeebc8f3
> > 100644
> > --- a/drivers/cpufreq/scmi-cpufreq.c
> > +++ b/drivers/cpufreq/scmi-cpufreq.c
> > @@ -104,7 +104,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, int
> domain,
> >  	int cpu, tdomain;
> >  	struct device *tcpu_dev;
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		if (cpu == cpu_dev->id)
> >  			continue;
> >
> > diff --git a/drivers/cpufreq/scpi-cpufreq.c
> > b/drivers/cpufreq/scpi-cpufreq.c index 048dc43a9997..17cda84f00df
> > 100644
> > --- a/drivers/cpufreq/scpi-cpufreq.c
> > +++ b/drivers/cpufreq/scpi-cpufreq.c
> > @@ -65,7 +65,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct
> cpumask *cpumask)
> >  	if (domain < 0)
> >  		return domain;
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		if (cpu == cpu_dev->id)
> >  			continue;
> >
> > diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> > b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> > index 17d6a149f580..47d6840b3489 100644
> > --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> > +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
> > @@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct
> platform_device *pdev)
> >  	snprintf(name, sizeof(name), "speed%d", speed);
> >  	config.prop_name = name;
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		struct device *cpu_dev = get_cpu_device(cpu);
> >
> >  		if (!cpu_dev) {
> > @@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct
> platform_device *pdev)
> >  	pr_err("Failed to register platform device\n");
> >
> >  free_opp:
> > -	for_each_possible_cpu(cpu)
> > +	for_each_present_cpu(cpu)
> >  		dev_pm_opp_clear_config(opp_tokens[cpu]);
> >  	kfree(opp_tokens);
> >
> > @@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct
> > platform_device *pdev)
> >
> >  	platform_device_unregister(cpufreq_dt_pdev);
> >
> > -	for_each_possible_cpu(cpu)
> > +	for_each_present_cpu(cpu)
> >  		dev_pm_opp_clear_config(opp_tokens[cpu]);
> >
> >  	kfree(opp_tokens);
> > diff --git a/drivers/cpufreq/virtual-cpufreq.c
> > b/drivers/cpufreq/virtual-cpufreq.c
> > index 45becb92aa4a..7dd1b0c263c7 100644
> > --- a/drivers/cpufreq/virtual-cpufreq.c
> > +++ b/drivers/cpufreq/virtual-cpufreq.c
> > @@ -138,7 +138,7 @@ static int virt_cpufreq_get_sharing_cpus(struct
> cpufreq_policy *policy)
> >  	cur_perf_domain = readl_relaxed(base + policy->cpu *
> >  					PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
> >
> > -	for_each_possible_cpu(cpu) {
> > +	for_each_present_cpu(cpu) {
> >  		cpu_dev = get_cpu_device(cpu);
> >  		if (!cpu_dev)
> >  			continue;
> > --
> > 2.34.1
> >
> 
> --
> Regards,
> Sudeep


From ping.bai at nxp.com  Wed Mar 12 18:39:28 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu, 13 Mar 2025 09:39:28 +0800
Subject: [PATCH v3] cpufreq: Init cpufreq only for present CPUs
Message-ID: <20250313013928.529926-1-ping.bai@nxp.com>

for_each_possible_cpu() is currently used to initialize cpufreq.
However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the cpufreq probe failure or defer probe due to no cpu device
available for not present CPUs.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpufreq drivers to ensure it only registers cpufreq for
CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
Signed-off-by: Jacky Bai <ping.bai at nxp.com>
---
 - v3 changes:
  - refine the changlog to drop the changed driver list.

 - v2 changes:
  - Add changes for armada-8k-cpufreq, mvebu-cpfureq, qcome-cpufreq-hw,
    scmi-cpufreq, scpi-cpufreq, virtual-cpufreq.
---
 drivers/cpufreq/armada-8k-cpufreq.c    | 2 +-
 drivers/cpufreq/cpufreq-dt.c           | 2 +-
 drivers/cpufreq/mediatek-cpufreq-hw.c  | 2 +-
 drivers/cpufreq/mediatek-cpufreq.c     | 2 +-
 drivers/cpufreq/mvebu-cpufreq.c        | 2 +-
 drivers/cpufreq/qcom-cpufreq-hw.c      | 2 +-
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 8 ++++----
 drivers/cpufreq/scmi-cpufreq.c         | 2 +-
 drivers/cpufreq/scpi-cpufreq.c         | 2 +-
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++---
 drivers/cpufreq/virtual-cpufreq.c      | 2 +-
 11 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c
index 7a979db81f09..5a3545bd0d8d 100644
--- a/drivers/cpufreq/armada-8k-cpufreq.c
+++ b/drivers/cpufreq/armada-8k-cpufreq.c
@@ -47,7 +47,7 @@ static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk,
 {
 	int cpu;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev;
 		struct clk *clk;
 
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 778916f89a51..e80dd982a3e2 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -283,7 +283,7 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
 	int ret, cpu;
 
 	/* Request resources early so we can return in case of -EPROBE_DEFER */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		ret = dt_cpufreq_early_init(&pdev->dev, cpu);
 		if (ret)
 			goto err;
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
index aa209f5527dc..74f1b4c796e4 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -303,7 +303,7 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev)
 	struct regulator *cpu_reg;
 
 	/* Make sure that all CPU supplies are available before proceeding. */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_dev = get_cpu_device(cpu);
 		if (!cpu_dev)
 			return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 2656b88db378..f3f02c4b6888 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -631,7 +631,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "failed to get mtk cpufreq platform data\n");
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		info = mtk_cpu_dvfs_info_lookup(cpu);
 		if (info)
 			continue;
diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
index 7f3cfe668f30..2aad4c04673c 100644
--- a/drivers/cpufreq/mvebu-cpufreq.c
+++ b/drivers/cpufreq/mvebu-cpufreq.c
@@ -56,7 +56,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
 	 * it), and registers the clock notifier that will take care
 	 * of doing the PMSU part of a frequency transition.
 	 */
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev;
 		struct clk *clk;
 		int ret;
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 4b3b3dbc7d38..8422704a3b10 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -306,7 +306,7 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
 	struct of_phandle_args args;
 	int cpu, ret;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_np = of_cpu_device_node_get(cpu);
 		if (!cpu_np)
 			continue;
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 3a8ed723a23e..54f8117103c8 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 		nvmem_cell_put(speedbin_nvmem);
 	}
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct dev_pm_opp_config config = {
 			.supported_hw = NULL,
 		};
@@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
 	dev_err(cpu_dev, "Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
 		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
 	}
@@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
 	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
 	unsigned int cpu;
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		qcom_cpufreq_suspend_pd_devs(drv, cpu);
 
 	return 0;
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index ff2897789797..c310aeebc8f3 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -104,7 +104,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
 	int cpu, tdomain;
 	struct device *tcpu_dev;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		if (cpu == cpu_dev->id)
 			continue;
 
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 048dc43a9997..17cda84f00df 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -65,7 +65,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 	if (domain < 0)
 		return domain;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		if (cpu == cpu_dev->id)
 			continue;
 
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 17d6a149f580..47d6840b3489 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	snprintf(name, sizeof(name), "speed%d", speed);
 	config.prop_name = name;
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct device *cpu_dev = get_cpu_device(cpu);
 
 		if (!cpu_dev) {
@@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 	pr_err("Failed to register platform device\n");
 
 free_opp:
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 	kfree(opp_tokens);
 
@@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
 
 	platform_device_unregister(cpufreq_dt_pdev);
 
-	for_each_possible_cpu(cpu)
+	for_each_present_cpu(cpu)
 		dev_pm_opp_clear_config(opp_tokens[cpu]);
 
 	kfree(opp_tokens);
diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c
index 45becb92aa4a..7dd1b0c263c7 100644
--- a/drivers/cpufreq/virtual-cpufreq.c
+++ b/drivers/cpufreq/virtual-cpufreq.c
@@ -138,7 +138,7 @@ static int virt_cpufreq_get_sharing_cpus(struct cpufreq_policy *policy)
 	cur_perf_domain = readl_relaxed(base + policy->cpu *
 					PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
 
-	for_each_possible_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		cpu_dev = get_cpu_device(cpu);
 		if (!cpu_dev)
 			continue;
-- 
2.34.1



From vijayb at linux.microsoft.com  Wed Mar 12 18:43:55 2025
From: vijayb at linux.microsoft.com (Vijay Balakrishna)
Date: Wed, 12 Mar 2025 18:43:55 -0700
Subject: [PATCH v5 0/2] Add L1 and L2 error detection for A53 and A57
In-Reply-To: <20210401110615.15326-1-s.hauer@pengutronix.de>
References: <20210401110615.15326-1-s.hauer@pengutronix.de>
Message-ID: <ff79f33d-91fd-49e5-9a6f-fa2c32c7021d@linux.microsoft.com>

On 4/1/2021 4:06 AM, Sascha Hauer wrote:
> Hi,
> 
> Resending this mainly because Marc Zyngier and Mark Rutland raised
> concerns about using implementation defined registers and I forgot to Cc
> them with the last version. This version, like v4 already, should fix
> these concerns. Looking forward to feedback.

We aim to revive and adapt this patch series for A72 and A78.  Is anyone 
actively working on this?  Please share any information on why it wasn't 
pursued and thoughts on adapting it to A72 and A78.

Thanks,
Vijay


From kelvin.zhang at amlogic.com  Wed Mar 12 18:48:54 2025
From: kelvin.zhang at amlogic.com (Kelvin Zhang)
Date: Thu, 13 Mar 2025 09:48:54 +0800
Subject: [PATCH v3 1/3] dt-bindings: reset: Add compatible for Amlogic
 A4/A5 Reset Controller
In-Reply-To: <20250312-atlas-paver-0f0e888a641b@spud>
References: <20240918074211.8067-1-zelong.dong@amlogic.com>
 <20240918074211.8067-2-zelong.dong@amlogic.com>
 <a5d9b775dd860d8f2bbf174300a2e3161b654035.camel@pengutronix.de>
 <20240918-delirious-skiing-224172be96d4@squawk>
 <84612c6b-621d-47cc-8a2e-41d1fa42f0fe@amlogic.com>
 <20250312-atlas-paver-0f0e888a641b@spud>
Message-ID: <b9d6a851-c43f-4db9-9a83-6eba3c9b1dd0@amlogic.com>

On 2025/3/13 04:31, Conor Dooley wrote:
> On Tue, Mar 11, 2025 at 05:48:26PM +0800, Kelvin Zhang wrote:
>>
>> On 2024/9/18 16:01, Conor Dooley wrote:
>>> On Wed, Sep 18, 2024 at 09:51:28AM +0200, Philipp Zabel wrote:
>>>> On Mi, 2024-09-18 at 15:42 +0800, zelong dong wrote:
>>>>> From: Zelong Dong<zelong.dong at amlogic.com>
>>>>>
>>>>> Add new compatible for Amlogic A4/A5 Reset Controller
>>>>>
>>>>> Signed-off-by: Zelong Dong<zelong.dong at amlogic.com>
>>>>> Acked-by: Conor Dooley<conor.dooley at microchip.com>
>>>>> ---
>>>>>    .../bindings/reset/amlogic,meson-reset.yaml   | 23 ++++++++++++-------
>>>>>    1 file changed, 15 insertions(+), 8 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>>>> index 695ef38a7bb3..0ad81fe7b629 100644
>>>>> --- a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>>>> +++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
>>>>> @@ -12,14 +12,21 @@ maintainers:
>>>>>    properties:
>>>>>      compatible:
>>>>> -    enum:
>>>>> -      - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
>>>>> -      - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
>>>>> -      - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
>>>>> -      - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
>>>>> -      - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
>>>>> -      - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
>>>>> -      - amlogic,t7-reset
>>>>> +    oneOf:
>>>>> +      - items:
>>>> I'm not well versed in preferred dt-bindings style, but this items
>>>> looks superfluous to me. It only contains a single enum.
>>> Oh, ye. Good spot.
>> Hello Philipp, Conor,
>> Sorry for the late reply.
>>
>> Do you mean to use 'amlogic,meson-s4-reset' for A4 and A5 directly, without
>> the fallback?
> No. We are saying that
> 
> +      - items:
> +          - enum:
> +              - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
> 
> is pointless duplication, because your "items" list only has only
> entry in it (the enum) and you could just remove the "- items" line
> entirely and have the same outcome.

Got it.
Thanks!

-- 
Best regards,

Kelvin Zhang



From anshuman.khandual at arm.com  Wed Mar 12 19:53:38 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Thu, 13 Mar 2025 08:23:38 +0530
Subject: [PATCH] KVM: arm64: Drop sort_memblock_regions()
In-Reply-To: <20250311043718.91004-1-gshan@redhat.com>
References: <20250311043718.91004-1-gshan@redhat.com>
Message-ID: <34b8242b-529b-4ad5-ac17-e1200965ae1d@arm.com>

On 3/11/25 10:07, Gavin Shan wrote:
> Drop sort_memblock_regions() and avoid sorting the copied memory
> regions to be ascending order on their base addresses, because the
> source memory regions should have been sorted correctly when they
> are added by memblock_add() or its variants.
> 
> This is generally reverting commit a14307f5310c ("KVM: arm64: Sort
> the hypervisor memblocks"). No functional changes intended.

Just wondering what prompted this change ?

> 
> Signed-off-by: Gavin Shan <gshan at redhat.com>
> ---
>  arch/arm64/kvm/pkvm.c | 19 -------------------
>  1 file changed, 19 deletions(-)
> 
> diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
> index 930b677eb9b0..d9c9174f89a1 100644
> --- a/arch/arm64/kvm/pkvm.c
> +++ b/arch/arm64/kvm/pkvm.c
> @@ -10,7 +10,6 @@
>  #include <asm/kvm_mmu.h>
>  #include <linux/memblock.h>
>  #include <linux/mutex.h>
> -#include <linux/sort.h>
>  
>  #include <asm/kvm_pkvm.h>
>  
> @@ -24,23 +23,6 @@ static unsigned int *hyp_memblock_nr_ptr = &kvm_nvhe_sym(hyp_memblock_nr);
>  phys_addr_t hyp_mem_base;
>  phys_addr_t hyp_mem_size;
>  
> -static int cmp_hyp_memblock(const void *p1, const void *p2)
> -{
> -	const struct memblock_region *r1 = p1;
> -	const struct memblock_region *r2 = p2;
> -
> -	return r1->base < r2->base ? -1 : (r1->base > r2->base);
> -}
> -
> -static void __init sort_memblock_regions(void)
> -{
> -	sort(hyp_memory,
> -	     *hyp_memblock_nr_ptr,
> -	     sizeof(struct memblock_region),
> -	     cmp_hyp_memblock,
> -	     NULL);
> -}
> -
>  static int __init register_memblock_regions(void)
>  {
>  	struct memblock_region *reg;
> @@ -52,7 +34,6 @@ static int __init register_memblock_regions(void)
>  		hyp_memory[*hyp_memblock_nr_ptr] = *reg;
>  		(*hyp_memblock_nr_ptr)++;
>  	}
> -	sort_memblock_regions();
>  
>  	return 0;
>  }


From ajd at linux.ibm.com  Wed Mar 12 19:54:39 2025
From: ajd at linux.ibm.com (Andrew Donnellan)
Date: Thu, 13 Mar 2025 13:54:39 +1100
Subject: [PATCH v13 00/11] Support page table check on PowerPC
In-Reply-To: <20250211161404.850215-1-ajd@linux.ibm.com>
References: <20250211161404.850215-1-ajd@linux.ibm.com>
Message-ID: <006ac081cf0e130426bcf0ef777bed346f6df002.camel@linux.ibm.com>

On Wed, 2025-02-12 at 03:13 +1100, Andrew Donnellan wrote:
> Support page table check on all PowerPC platforms. This works by
> serialising assignments, reassignments and clears of page table
> entries at each level in order to ensure that anonymous mappings
> have at most one writable consumer, and likewise that file-backed
> mappings are not simultaneously also anonymous mappings.
> 
> In order to support this infrastructure, a number of stubs must be
> defined for all powerpc platforms. Additionally, seperate
> set_pte_at()
> and set_pte_at_unchecked(), to allow for internal, uninstrumented
> mappings.

Talking to Maddy about this off-list - given that this series touches
on generic code and several architectures, would it be best to take it
through the mm tree rather than powerpc?

-- 
Andrew Donnellan    OzLabs, ADL Canberra
ajd at linux.ibm.com   IBM Australia Limited


From senozhatsky at chromium.org  Wed Mar 12 20:09:18 2025
From: senozhatsky at chromium.org (Sergey Senozhatsky)
Date: Thu, 13 Mar 2025 12:09:18 +0900
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <Z9HOavSkFf01K9xh@google.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com>
Message-ID: <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>

On (25/03/12 11:11), Minchan Kim wrote:
> On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > This patch series introduces a new mechanism called kcompressd to
> > improve the efficiency of memory reclaiming in the operating system. The
> > main goal is to separate the tasks of page scanning and page compression
> > into distinct processes or threads, thereby reducing the load on the
> > kswapd thread and enhancing overall system performance under high memory
> > pressure conditions.
> > 
> > Problem:
> >  In the current system, the kswapd thread is responsible for both
> >  scanning the LRU pages and compressing pages into the ZRAM. This
> >  combined responsibility can lead to significant performance bottlenecks,
> >  especially under high memory pressure. The kswapd thread becomes a
> >  single point of contention, causing delays in memory reclaiming and
> >  overall system performance degradation.
> 
> Isn't it general problem if backend for swap is slow(but synchronous)?
> I think zram need to support asynchrnous IO(can do introduce multiple
> threads to compress batched pages) and doesn't declare it's
> synchrnous device for the case.

The current conclusion is that kcompressd will sit above zram,
because zram is not the only compressing swap backend we have.


From irogers at google.com  Wed Mar 12 20:31:21 2025
From: irogers at google.com (Ian Rogers)
Date: Wed, 12 Mar 2025 20:31:21 -0700
Subject: [PATCH v2] perf libunwind: Fixup conversion perf_sample->user_regs to
 a pointer
Message-ID: <20250313033121.758978-1-irogers@google.com>

From: Arnaldo Carvalho de Melo <acme at redhat.com>

The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
the changes to a file, resulting in this problem:

  $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
  <SNIP>
    CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
    CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
  <SNIP>
  util/unwind-libunwind-local.c: In function ?access_mem?:
  util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
    582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
        |                                                        ^
        |                                                        ->
  util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
    587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
        |                                      ^~~~~~~~~~~~~~~~~~~~~~
        |                                      |
        |                                      struct regs_dump **
<SNIP>
  ? [acme at toolbox perf-tools-next]$ git bisect bad
  dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
  commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
  Author: Ian Rogers <irogers at google.com>
  Date:   Mon Jan 13 11:43:45 2025 -0800

      perf sample: Make user_regs and intr_regs optional

Detected using:

  make -C tools/perf build-test

Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Charlie Jenkins <charlie at rivosinc.com>
Cc: Ian Rogers <irogers at google.com>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: James Clark <james.clark at linaro.org>
Cc: John Garry <john.g.garry at oracle.com>
Cc: Kan Liang <kan.liang at linux.intel.com>
Cc: Leo Yan <leo.yan at linux.dev>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Michael Petlan <mpetlan at redhat.com>
Cc: Namhyung Kim <namhyung at kernel.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Tavian Barnes <tavianator at tavianator.com>
Cc: Veronika Molnarova <vmolnaro at redhat.com>
Cc: coresight at lists.linaro.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Reviewed-by: Ian Rogers <irogers at google.com>
---
v2: Ensure user_regs isn't NULL when read, spotted by Namhyung.
---
 tools/perf/util/unwind-libunwind-local.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 16c2b03831f3..5f4387e2423a 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -579,12 +579,12 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
 	int ret;
 
 	/* Don't support write, probably not needed. */
-	if (__write || !stack || !ui->sample->user_regs.regs) {
+	if (__write || !stack || !ui->sample->user_regs || !ui->sample->user_regs->regs) {
 		*valp = 0;
 		return 0;
 	}
 
-	ret = perf_reg_value(&start, &ui->sample->user_regs,
+	ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample),
 			     perf_arch_reg_sp(arch));
 	if (ret)
 		return ret;
@@ -628,7 +628,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
 		return 0;
 	}
 
-	if (!ui->sample->user_regs.regs) {
+	if (!ui->sample->user_regs || !ui->sample->user_regs->regs) {
 		*valp = 0;
 		return 0;
 	}
@@ -637,7 +637,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
 	if (id < 0)
 		return -EINVAL;
 
-	ret = perf_reg_value(&val, &ui->sample->user_regs, id);
+	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id);
 	if (ret) {
 		if (!ui->best_effort)
 			pr_err("unwind: can't read reg %d\n", regnum);
@@ -741,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
 	unw_cursor_t c;
 	int ret, i = 0;
 
-	ret = perf_reg_value(&val, &ui->sample->user_regs,
+	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample),
 			     perf_arch_reg_ip(arch));
 	if (ret)
 		return ret;
@@ -808,7 +808,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 		.best_effort  = best_effort
 	};
 
-	if (!data->user_regs.regs)
+	if (!data->user_regs || !data->user_regs->regs)
 		return -EINVAL;
 
 	if (max_stack <= 0)
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From Suraj.Gupta2 at amd.com  Wed Mar 12 20:31:29 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Thu, 13 Mar 2025 03:31:29 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
 <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
Message-ID: <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Andrew Lunn <andrew at lunn.ch>
> Sent: Thursday, March 13, 2025 3:41 AM
> To: Russell King (Oracle) <linux at armlinux.org.uk>
> Cc: Gupta, Suraj <Suraj.Gupta2 at amd.com>; Pandey, Radhey Shyam
> <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> <harini.katakam at amd.com>
> Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> > This is not an approach that works with the Linux kernel, sorry.
> >
> > What we have today is a driver that works for people's hardware - and
> > we don't know what the capabilities of that hardware is.
> >
> > If there's hardware out there today which has XAE_ABILITY_2_5G set,
> > but defaults to <=1G mode, this will work with the current driver.
> > However, with your patch applied, it stops working because instead of
> > the driver indicating MAC_10FD | MAC_100FD | MAC_1000FD, it only
> > indicates MAC_2500FD. If this happens, it will regress users setups,
> > and that is something we try not to do.
> >
> > Saying "someone else needs to add the code for their FPGA logic"
> > misses the point - there may not be "someone else" to do that, which
> > means the only option is to revert your change if it were merged. That
> > in itself can cause its own user regressions because obviously stuff
> > that works with this patch stops working.
> >
> > This is why we're being cautious, and given your responses, it's not
> > making Andrew or myself feel that there's a reasonable approach being
> > taken here.
> >
> > >From everything you have said, I am getting the feeling that using
> > XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is just
> > wrong. Given that we're talking about an implementation that has been
> > synthesized at 2.5G and can't operate slower, maybe there's some way
> > that could be created to specify that in DT?
> >
> > e.g. (and I'm sure the DT folk aren't going to like it)...
> >
> >       xlnx,axi-ethernet-X.YY.Z-2.5G
> >
> > (where X.YY.Z is the version) for implementations that can _only_ do
> > 2.5G, and leave all other implementations only doing 1G and below.
> >
> > Or maybe some DT property. Or something else.
>
> Given that AMD has been talking about an FPGA, not silicon, i actually think it would
> be best to change the IP to explicitly enumerate how it has been synthesised. Make
> use of some register bits which currently read as 0. Current IP would then remain as
> 1000BaseX/SGMII, independent of how they have been synthesised. Newer
> versions of the IP will then set the bits if they have been synthesised as 2) or 3), and
> the driver can then enable that capability, without breaking current generation
> systems. Plus there needs to be big fat warning for anybody upgrading to the latest
> version of the IP for bug fixes to ensure they correctly set the synthesis options
> because it now actually matters.
>
>          Andrew

Synthesis options I mentioned in comment might sound confusing, let me clear it up.
Actual synthesis options (as seen from configuration UI) IP provides are (1) and (2). When a user selects (2), IP comes with default 2.5G but also contains 1G capabilities which can be enabled and work with by adding switching FPGA logic (that makes it (3)).

So, in short  if a user selects (1): It's <=1G only.
If it selects (2): It's 2.5G only but can be made (3) by FPGA logic changes. So whatever existing systems for (3) would be working at default (2).

This is the reason we didn't described (3) in V1 series as that is not provided by IP but can be synthesized after FPGA changes.
Hope I'm able to answer your questions.




From vz at mleia.com  Wed Mar 12 20:37:44 2025
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Thu, 13 Mar 2025 05:37:44 +0200
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <yvljnqnlka3ecw2n3hw2zgfszlldvbww3k7gq72dczmf6jwzfo@4vqnygxuzvk5>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
 <57ae63a2-544b-4241-a54d-8fa9917c1e44@mleia.com>
 <yvljnqnlka3ecw2n3hw2zgfszlldvbww3k7gq72dczmf6jwzfo@4vqnygxuzvk5>
Message-ID: <5b62671c-719a-44f2-b28e-878159859a01@mleia.com>

Hi Uwe,

On 3/13/25 00:56, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Wed, Mar 12, 2025 at 07:59:21PM +0200, Vladimir Zapolskiy wrote:
>>> +  "#pwm-cells":
>>> +    const: 3
>>
>> It shall be 1.
> 
> No, 3 is the right choice.
> 

could you please elaborate?

I find that here the only configurable parameter is PWM period, so it
should be sufficient to have one cell only like in marvell,pxa-pwm.yaml
or google,cros-ec-pwm.yaml.

--
Best wishes,
Vladimir


From baohua at kernel.org  Wed Mar 12 20:45:54 2025
From: baohua at kernel.org (Barry Song)
Date: Thu, 13 Mar 2025 16:45:54 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com> <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
Message-ID: <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com>

On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
<senozhatsky at chromium.org> wrote:
>
> On (25/03/12 11:11), Minchan Kim wrote:
> > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > This patch series introduces a new mechanism called kcompressd to
> > > improve the efficiency of memory reclaiming in the operating system. The
> > > main goal is to separate the tasks of page scanning and page compression
> > > into distinct processes or threads, thereby reducing the load on the
> > > kswapd thread and enhancing overall system performance under high memory
> > > pressure conditions.
> > >
> > > Problem:
> > >  In the current system, the kswapd thread is responsible for both
> > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > >  combined responsibility can lead to significant performance bottlenecks,
> > >  especially under high memory pressure. The kswapd thread becomes a
> > >  single point of contention, causing delays in memory reclaiming and
> > >  overall system performance degradation.
> >
> > Isn't it general problem if backend for swap is slow(but synchronous)?
> > I think zram need to support asynchrnous IO(can do introduce multiple
> > threads to compress batched pages) and doesn't declare it's
> > synchrnous device for the case.
>
> The current conclusion is that kcompressd will sit above zram,
> because zram is not the only compressing swap backend we have.

also. it is not good to hack zram to be aware of if it is kswapd
, direct reclaim , proactive reclaim and block device with
mounted filesystem.

so i am thinking sth as below

page_io.c

if (sync_device or zswap_enabled())
   schedule swap_writepage to a separate per-node thread

btw,  ran the current patchset with one thread(not default 4)
on phones and saw 50%+ allocstall reduction. so the idea
looks like a good direction to go.

Thanks
Barry


From 21cnbao at gmail.com  Wed Mar 12 20:52:22 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Thu, 13 Mar 2025 16:52:22 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com> <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
Message-ID: <CAGsJ_4yw17rLJPgS6CNXfXNVQnv2pf0PnLSA4UVAR1sUWDhP5Q@mail.gmail.com>

On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
<senozhatsky at chromium.org> wrote:
>
> On (25/03/12 11:11), Minchan Kim wrote:
> > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > This patch series introduces a new mechanism called kcompressd to
> > > improve the efficiency of memory reclaiming in the operating system. The
> > > main goal is to separate the tasks of page scanning and page compression
> > > into distinct processes or threads, thereby reducing the load on the
> > > kswapd thread and enhancing overall system performance under high memory
> > > pressure conditions.
> > >
> > > Problem:
> > >  In the current system, the kswapd thread is responsible for both
> > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > >  combined responsibility can lead to significant performance bottlenecks,
> > >  especially under high memory pressure. The kswapd thread becomes a
> > >  single point of contention, causing delays in memory reclaiming and
> > >  overall system performance degradation.
> >
> > Isn't it general problem if backend for swap is slow(but synchronous)?
> > I think zram need to support asynchrnous IO(can do introduce multiple
> > threads to compress batched pages) and doesn't declare it's
> > synchrnous device for the case.
>
> The current conclusion is that kcompressd will sit above zram,
> because zram is not the only compressing swap backend we have.

also. it is not good to hack zram to be aware of if it is kswapd
, direct reclaim , proactive reclaim and block device with
mounted filesystem.

so i am thinking sth as below

page_io.c

if (sync_device or zswap_enabled())
   schedule swap_writepage to a separate per-node thread

btw,  ran the current patchset with one thread(not default 4)
on phones and saw 50%+ allocstall reduction. so the idea
looks like a good direction to go.

Thanks
Barry


From vignesh.raman at collabora.com  Wed Mar 12 21:08:24 2025
From: vignesh.raman at collabora.com (Vignesh Raman)
Date: Thu, 13 Mar 2025 09:38:24 +0530
Subject: [PATCH v3] arm64: defconfig: mediatek: enable PHY drivers
Message-ID: <20250313040855.62259-1-vignesh.raman@collabora.com>

The mediatek display driver fails to probe on mt8173-elm-hana and
mt8183-kukui-jacuzzi-juniper-sku16 in v6.14-rc4 due to missing PHY
configurations.

Commit [1] stopped selecting the MediaTek PHY drivers, requiring them
to be explicitly enabled in defconfig.

Enable the following PHY drivers for MediaTek platforms:
- CONFIG_PHY_MTK_HDMI=m for HDMI display
- CONFIG_PHY_MTK_MIPI_DSI=m for DSI display
- CONFIG_PHY_MTK_DP=m for DP display

[1] commit 924d66011f24 ("drm/mediatek: stop selecting foreign drivers")

Fixes: 924d66011f24 ("drm/mediatek: stop selecting foreign drivers")
Signed-off-by: Vignesh Raman <vignesh.raman at collabora.com>
---

v2:
  - Include board details in the commit message.  
  - Sort newly added PHY configs in defconfig.

v3:
  - Use defconfig/savedefconfig to get the correct configs ordering.
  - Removed PHY_MTK_XSPHY since it is not required for probing display driver.
  - Add the commit details which deselected the MediaTek PHY drivers and
    added a Fixes tag.
  - Enabled CONFIG_PHY_MTK_DP, which was previously deselected.

---
 arch/arm64/configs/defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1f25423de383..fa8ee7070b37 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1573,6 +1573,9 @@ CONFIG_PHY_HISTB_COMBPHY=y
 CONFIG_PHY_HISI_INNO_USB2=y
 CONFIG_PHY_MVEBU_CP110_COMPHY=y
 CONFIG_PHY_MTK_TPHY=y
+CONFIG_PHY_MTK_HDMI=m
+CONFIG_PHY_MTK_MIPI_DSI=m
+CONFIG_PHY_MTK_DP=m
 CONFIG_PHY_QCOM_EDP=m
 CONFIG_PHY_QCOM_PCIE2=m
 CONFIG_PHY_QCOM_QMP=m
-- 
2.47.2



From peng.fan at oss.nxp.com  Wed Mar 12 22:23:27 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Thu, 13 Mar 2025 13:23:27 +0800
Subject: [PATCH 1/4] firmware: arm_scmi: bus: Bypass setting fwnode for
 scmi cpufreq
In-Reply-To: <Z9Fv9JPdF5OWUHfk@bogus>
References: <Z7Z-ZnztmvUxWoQJ@NXL53680.wbi.nxp.com>
 <Z86w3ZRS6T2MvV3X@bogus>
 <DB9PR04MB84614FBF96E7BC0D125D97F688D62@DB9PR04MB8461.eurprd04.prod.outlook.com>
 <Z87UJdhiTWhssnbl@bogus>
 <Z87sGF_jHKau_FMe@bogus>
 <PAXPR04MB8459EA5C7898393E51C246AD88D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <PAXPR04MB8459A73179FFF0ED0C9A51E488D12@PAXPR04MB8459.eurprd04.prod.outlook.com>
 <Z9AdICiyaCmzKh-N@bogus>
 <Z9FnZzBQuZ1j5k3I@bogus>
 <Z9Fv9JPdF5OWUHfk@bogus>
Message-ID: <20250313052309.GA11131@nxa18884-linux>

On Wed, Mar 12, 2025 at 11:28:52AM +0000, Sudeep Holla wrote:
>On Wed, Mar 12, 2025 at 10:52:23AM +0000, Sudeep Holla wrote:
>> On Tue, Mar 11, 2025 at 11:23:12AM +0000, Sudeep Holla wrote:
>> > On Tue, Mar 11, 2025 at 11:12:45AM +0000, Peng Fan wrote:
>> > >
>> > > So it is clear that wrong fw_devlink is created, it is because scmi cpufreq device is
>> > > created earlier and when device_add, the below logic makes the fwnode pointer points
>> > > to scmi cpufreq device.
>> > >         if (dev->fwnode && !dev->fwnode->dev) {
>> > >                 dev->fwnode->dev = dev;
>> > >                 fw_devlink_link_device(dev);
>> > >         }
>> > >
>> >
>> > Thanks, looks like simple way to reproduce the issue. I will give it a try.
>> >
>> 
>> I could reproduce but none of my solution solved the problem completely
>> or properly. And I don't like the DT proposal you came up with. I am
>> not inclined to just drop this fwnode setting in the scmi devices and
>> just use of_node.
>>
>
>Sorry for the typo that changes the meaning: s/not/now
>
>I meant "I am now inclined ..", until we figure out a way to make this
>work with devlinks properly.

when you have time, please give a look at
https://github.com/MrVan/linux/commit/b500c29cb7f6f32a38b1ed462e333db5a3e301e4

The upper patch was to follow Cristian's and Dan's suggestion in V2[1] to use
a flag SCMI_DEVICE_NO_FWNODE for scmi device.

I could post out the upper patch as V3 if it basically looks no design flaw.
I will drop the pinctrl patch in v3, considering we are first going
to resolve the fw_devlink issue for cpufreq/devfreq.

[1] https://lore.kernel.org/all/Z6SgFGb4Z88v783c at pluto/

Thanks,
Peng.

>
>-- 
>Regards,
>Sudeep


From quic_tdas at quicinc.com  Wed Mar 12 22:08:33 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 10:38:33 +0530
Subject: [PATCH v5 02/10] dt-bindings: clock: Add Qualcomm QCS615 Camera
 clock controller
In-Reply-To: <ljfgljuhlpkjvqwomhvq5l6giihqv6h5nzswncaqgelvjycgew@bcxjrgbj3lts>
References: <20250221-qcs615-v5-mm-cc-v5-0-b6d9ddf2f28d@quicinc.com>
 <20250221-qcs615-v5-mm-cc-v5-2-b6d9ddf2f28d@quicinc.com>
 <ljfgljuhlpkjvqwomhvq5l6giihqv6h5nzswncaqgelvjycgew@bcxjrgbj3lts>
Message-ID: <b2265099-cf95-47b0-add4-5b0f89e61ba3@quicinc.com>



On 2/21/2025 7:41 PM, Dmitry Baryshkov wrote:
> On Fri, Feb 21, 2025 at 02:50:13PM +0530, Taniya Das wrote:
>> Add DT bindings for the Camera clock on QCS615 platforms. Add the
>> relevant DT include definitions as well.
>>
>> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
>> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> Just noticed. I've never replied with this tag. I've provided a comment
> to the v3 of the series, then in v4 this somehow appeared. Could you
> please comment, what has happened?
> 

I am still confused how the tags were added, as I used only b4 to pull
the patches, only there was one patch from patch series#3 to patch
series#4 was to drop one patch as it was already picked up by Bjorn.

This patch has tag only from Krzysztof.

https://patchwork.kernel.org/project/linux-clk/patch/20241101-qcs615-mm-clockcontroller-v2-3-d1a4870a4aed at quicinc.com/


I will check all the series and correct the tags.


>> Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
>> ---
>>  .../bindings/clock/qcom,qcs615-camcc.yaml          |  54 ++++++++++
>>  include/dt-bindings/clock/qcom,qcs615-camcc.h      | 110 +++++++++++++++++++++
>>  2 files changed, 164 insertions(+)
> 



From quic_tdas at quicinc.com  Wed Mar 12 22:09:26 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 10:39:26 +0530
Subject: [PATCH v5 04/10] dt-bindings: clock: Add Qualcomm QCS615 Display
 clock controller
In-Reply-To: <5f5nt4g3fy7446gxnjg53n4uir57hm62ewgusekls5sbmadwez@pfxmhrkck3zi>
References: <20250221-qcs615-v5-mm-cc-v5-0-b6d9ddf2f28d@quicinc.com>
 <20250221-qcs615-v5-mm-cc-v5-4-b6d9ddf2f28d@quicinc.com>
 <5f5nt4g3fy7446gxnjg53n4uir57hm62ewgusekls5sbmadwez@pfxmhrkck3zi>
Message-ID: <5b81ba9f-810e-45c7-b991-ffa842b8c8eb@quicinc.com>



On 2/21/2025 7:44 PM, Dmitry Baryshkov wrote:
> On Fri, Feb 21, 2025 at 02:50:15PM +0530, Taniya Das wrote:
>> Add DT bindings for the Display clock on QCS615 platforms. Add the
>> relevant DT include definitions as well.
>>
>> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> 
> I don't remember responding with it, nor does lore find such an email.
> I'm totally confused, what is going on?
> 

Dmitry, I will recheck all the series and update the tags and resend.

>> Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
>> ---
>>  .../bindings/clock/qcom,qcs615-dispcc.yaml         | 73 ++++++++++++++++++++++
>>  include/dt-bindings/clock/qcom,qcs615-dispcc.h     | 52 +++++++++++++++
>>  2 files changed, 125 insertions(+)
> 



From mhklinux at outlook.com  Wed Mar 12 22:10:10 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 13 Mar 2025 05:10:10 +0000
Subject: [PATCH hyperv-next v5 03/11] Drivers: hv: Enable VTL mode for
 arm64
In-Reply-To: <996deaab-e1d1-4f04-ba31-c0dcab2d5e1d@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-4-romank@linux.microsoft.com>
 <e0f81049-688e-4f53-a002-5d246281bf8d@app.fastmail.com>
 <BN7PR02MB41488C06B7E42830C700318DD4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <119cfb59-d68b-4718-b7cb-90cba67827e8@app.fastmail.com>
 <BN7PR02MB4148FC15ADF0E49327262B92D4D62@BN7PR02MB4148.namprd02.prod.outlook.com>
 <caa0d793-3f05-4d7c-88d0-224ec0503cfb@linux.microsoft.com>
 <45171fb1-7533-449f-83d4-066d038c839f@app.fastmail.com>
 <996deaab-e1d1-4f04-ba31-c0dcab2d5e1d@linux.microsoft.com>
Message-ID: <SN6PR02MB4157A635B0D1B43A2ED2664DD4D32@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Roman Kisel <romank at linux.microsoft.com> Sent: Wednesday, March 12, 2025 2:21 PM
> 
> On 3/12/2025 1:25 PM, Arnd Bergmann wrote:
> > On Wed, Mar 12, 2025, at 19:33, Roman Kisel wrote:
> >>
> >> That's a minimal extension, its surprise factor is very low. It has not
> >> been seen to cause issues. If no one has strong opinions against that,
> >> I'd send that in V6.
> >>
> >
> > Works for me. Thanks for your detailed explanations.
> >
> 
> Thank you for your review very much!
> 

My original concern [1] with this minimal change is that it allows building
a normal Linux kernel (i.e., not for VTL 2) for Hyper-V with CONFIG_ACPI=n.
Such a kernel will not run in a Hyper-V VM since ACPI is required unless
building for and running in VTL 2. Current upstream code disallows
CONFIG_HYPERV=y with CONFIG_ACPI=n.

However, I don't want to make too big of a deal about now allowing this
misconfiguration. Arguably it's not likely to happen, and the solution is
"don't do that".  So if we want to go back to the minimal set of changes to
drivers/hv/Kconfig as Roman proposes, I won't object further. I just want
to sure everyone is clear on the tradeoffs.

Michael

[1] https://lore.kernel.org/linux-hyperv/SN6PR02MB4157E15EFE263BBA3D8DFC51D4EC2 at SN6PR02MB4157.namprd02.prod.outlook.com/


From anuj20.g at samsung.com  Wed Mar 12 20:53:18 2025
From: anuj20.g at samsung.com (Anuj Gupta)
Date: Thu, 13 Mar 2025 09:23:18 +0530
Subject: [PATCH] block: remove unused parameter
References: <CGME20250313040150epcas5p347f94dac34fd2946dea51049559ee1de@epcas5p3.samsung.com>
Message-ID: <20250313035322.243239-1-anuj20.g@samsung.com>

request_queue param is not used by blk_rq_map_sg and __blk_rq_map_sg.
remove it.

Signed-off-by: Anuj Gupta <anuj20.g at samsung.com>
---
 block/blk-merge.c                   | 4 ++--
 block/bsg-lib.c                     | 2 +-
 drivers/block/mtip32xx/mtip32xx.c   | 2 +-
 drivers/block/rnbd/rnbd-clt.c       | 2 +-
 drivers/block/sunvdc.c              | 2 +-
 drivers/block/virtio_blk.c          | 2 +-
 drivers/block/xen-blkfront.c        | 2 +-
 drivers/memstick/core/ms_block.c    | 2 +-
 drivers/memstick/core/mspro_block.c | 4 +---
 drivers/mmc/core/queue.c            | 2 +-
 drivers/mtd/ubi/block.c             | 2 +-
 drivers/nvme/host/apple.c           | 2 +-
 drivers/nvme/host/fc.c              | 2 +-
 drivers/nvme/host/pci.c             | 2 +-
 drivers/nvme/host/rdma.c            | 3 +--
 drivers/nvme/target/loop.c          | 2 +-
 drivers/scsi/scsi_lib.c             | 2 +-
 include/linux/blk-mq.h              | 9 ++++-----
 18 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index 1d1589c35297..fdd4efb54c6c 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -551,8 +551,8 @@ static inline struct scatterlist *blk_next_sg(struct scatterlist **sg,
  * Map a request to scatterlist, return number of sg entries setup. Caller
  * must make sure sg can hold rq->nr_phys_segments entries.
  */
-int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
-		struct scatterlist *sglist, struct scatterlist **last_sg)
+int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
+		    struct scatterlist **last_sg)
 {
 	struct req_iterator iter = {
 		.bio	= rq->bio,
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 93523d8f8195..9ceb5d0832f5 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -219,7 +219,7 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
 	if (!buf->sg_list)
 		return -ENOMEM;
 	sg_init_table(buf->sg_list, req->nr_phys_segments);
-	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
+	buf->sg_cnt = blk_rq_map_sg(req, buf->sg_list);
 	buf->payload_len = blk_rq_bytes(req);
 	return 0;
 }
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 95361099a2dc..0d619df03fa9 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2056,7 +2056,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, struct request *rq,
 	unsigned int nents;
 
 	/* Map the scatter list for DMA access */
-	nents = blk_rq_map_sg(hctx->queue, rq, command->sg);
+	nents = blk_rq_map_sg(rq, command->sg);
 	nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
 
 	prefetch(&port->flags);
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index 82467ecde7ec..15627417f12e 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -1010,7 +1010,7 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
 	 * See queue limits.
 	 */
 	if ((req_op(rq) != REQ_OP_DISCARD) && (req_op(rq) != REQ_OP_WRITE_ZEROES))
-		sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sgt.sgl);
+		sg_cnt = blk_rq_map_sg(rq, iu->sgt.sgl);
 
 	if (sg_cnt == 0)
 		sg_mark_end(&iu->sgt.sgl[0]);
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 282f81616a78..2b33fb5b949b 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -485,7 +485,7 @@ static int __send_request(struct request *req)
 	}
 
 	sg_init_table(sg, port->ring_cookies);
-	nsg = blk_rq_map_sg(req->q, req, sg);
+	nsg = blk_rq_map_sg(req, sg);
 
 	len = 0;
 	for (i = 0; i < nsg; i++)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 6a61ec35f426..a3df4d49bd46 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -226,7 +226,7 @@ static int virtblk_map_data(struct blk_mq_hw_ctx *hctx, struct request *req,
 	if (unlikely(err))
 		return -ENOMEM;
 
-	return blk_rq_map_sg(hctx->queue, req, vbr->sg_table.sgl);
+	return blk_rq_map_sg(req, vbr->sg_table.sgl);
 }
 
 static void virtblk_cleanup_cmd(struct request *req)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index edcd08a9dcef..5babe575c288 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -751,7 +751,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
 	id = blkif_ring_get_request(rinfo, req, &final_ring_req);
 	ring_req = &rinfo->shadow[id].req;
 
-	num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg);
+	num_sg = blk_rq_map_sg(req, rinfo->shadow[id].sg);
 	num_grant = 0;
 	/* Calculate the number of grant used */
 	for_each_sg(rinfo->shadow[id].sg, sg, num_sg, i)
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index 5b617c1f6789..f4398383ae06 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -1904,7 +1904,7 @@ static void msb_io_work(struct work_struct *work)
 
 		/* process the request */
 		dbg_verbose("IO: processing new request");
-		blk_rq_map_sg(msb->queue, req, sg);
+		blk_rq_map_sg(req, sg);
 
 		lba = blk_rq_pos(req);
 
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 634d343b6bdb..c9853d887d28 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -627,9 +627,7 @@ static int mspro_block_issue_req(struct memstick_dev *card)
 	while (true) {
 		msb->current_page = 0;
 		msb->current_seg = 0;
-		msb->seg_count = blk_rq_map_sg(msb->block_req->q,
-					       msb->block_req,
-					       msb->req_sg);
+		msb->seg_count = blk_rq_map_sg(msb->block_req, msb->req_sg);
 
 		if (!msb->seg_count) {
 			unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index ab662f502fe7..3ba62f825b84 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -523,5 +523,5 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 {
 	struct request *req = mmc_queue_req_to_req(mqrq);
 
-	return blk_rq_map_sg(mq->queue, req, mqrq->sg);
+	return blk_rq_map_sg(req, mqrq->sg);
 }
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 2836905f0152..39cc0a6a4d37 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -199,7 +199,7 @@ static blk_status_t ubiblock_read(struct request *req)
 	 * and ubi_read_sg() will check that limit.
 	 */
 	ubi_sgl_init(&pdu->usgl);
-	blk_rq_map_sg(req->q, req, pdu->usgl.sg);
+	blk_rq_map_sg(req, pdu->usgl.sg);
 
 	while (bytes_left) {
 		/*
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index a060f69558e7..a437eee741e1 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -525,7 +525,7 @@ static blk_status_t apple_nvme_map_data(struct apple_nvme *anv,
 	if (!iod->sg)
 		return BLK_STS_RESOURCE;
 	sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
-	iod->nents = blk_rq_map_sg(req->q, req, iod->sg);
+	iod->nents = blk_rq_map_sg(req, iod->sg);
 	if (!iod->nents)
 		goto out_free_sg;
 
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index b9929a5a7f4e..1b5ad1173bc7 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -2571,7 +2571,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
 	if (ret)
 		return -ENOMEM;
 
-	op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
+	op->nents = blk_rq_map_sg(rq, freq->sg_table.sgl);
 	WARN_ON(op->nents > blk_rq_nr_phys_segments(rq));
 	freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
 				op->nents, rq_dma_dir(rq));
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 950289405ef2..a0b1c57067aa 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -812,7 +812,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
 	if (!iod->sgt.sgl)
 		return BLK_STS_RESOURCE;
 	sg_init_table(iod->sgt.sgl, blk_rq_nr_phys_segments(req));
-	iod->sgt.orig_nents = blk_rq_map_sg(req->q, req, iod->sgt.sgl);
+	iod->sgt.orig_nents = blk_rq_map_sg(req, iod->sgt.sgl);
 	if (!iod->sgt.orig_nents)
 		goto out_free_sg;
 
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 86a2891d9bcc..b5a0295b5bf4 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1476,8 +1476,7 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq,
 	if (ret)
 		return -ENOMEM;
 
-	req->data_sgl.nents = blk_rq_map_sg(rq->q, rq,
-					    req->data_sgl.sg_table.sgl);
+	req->data_sgl.nents = blk_rq_map_sg(rq, req->data_sgl.sg_table.sgl);
 
 	*count = ib_dma_map_sg(ibdev, req->data_sgl.sg_table.sgl,
 			       req->data_sgl.nents, rq_dma_dir(rq));
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index a9d112d34d4f..a5c41144667c 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -162,7 +162,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 		}
 
 		iod->req.sg = iod->sg_table.sgl;
-		iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
+		iod->req.sg_cnt = blk_rq_map_sg(req, iod->sg_table.sgl);
 		iod->req.transfer_len = blk_rq_payload_bytes(req);
 	}
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f1cfe0bb89b2..0d29470e86b0 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1149,7 +1149,7 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
 	 * Next, walk the list, and fill in the addresses and sizes of
 	 * each segment.
 	 */
-	count = __blk_rq_map_sg(rq->q, rq, cmd->sdb.table.sgl, &last_sg);
+	count = __blk_rq_map_sg(rq, cmd->sdb.table.sgl, &last_sg);
 
 	if (blk_rq_bytes(rq) & rq->q->limits.dma_pad_mask) {
 		unsigned int pad_len =
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index fa2a76cc2f73..f2eff998913d 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -1165,14 +1165,13 @@ static inline unsigned short blk_rq_nr_discard_segments(struct request *rq)
 	return max_t(unsigned short, rq->nr_phys_segments, 1);
 }
 
-int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
-		struct scatterlist *sglist, struct scatterlist **last_sg);
-static inline int blk_rq_map_sg(struct request_queue *q, struct request *rq,
-		struct scatterlist *sglist)
+int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
+		struct scatterlist **last_sg);
+static inline int blk_rq_map_sg(struct request *rq, struct scatterlist *sglist)
 {
 	struct scatterlist *last_sg = NULL;
 
-	return __blk_rq_map_sg(q, rq, sglist, &last_sg);
+	return __blk_rq_map_sg(rq, sglist, &last_sg);
 }
 void blk_dump_rq_flags(struct request *, char *);
 
-- 
2.25.1



From s-vadapalli at ti.com  Wed Mar 12 22:55:19 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Thu, 13 Mar 2025 11:25:19 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250312161600.GA680640@bhelgaas>
References: <20250305132018.2260771-1-s-vadapalli@ti.com>
 <20250312161600.GA680640@bhelgaas>
Message-ID: <20250313055519.j3bpvsm6govd5ytk@uda0492258>

On Wed, Mar 12, 2025 at 11:16:00AM -0500, Bjorn Helgaas wrote:

Hello Bjorn,

> [+to Matt, author of e49ad667815d]

I dropped Matt's email on purpose since it will bounce as the email is
no longer valid.

> 
> On Wed, Mar 05, 2025 at 06:50:18PM +0530, Siddharth Vadapalli wrote:
> > Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
> > J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
> > to the Technical Reference Manual and Register Documentation for the J784S4
> > SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
> > the field for the link-state interrupt. Instead, it is BIT(10) of the
> > "PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
> > field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".
> 
> I guess the reason we want this is that on J784S4, we ignore actual
> link-down interrupts (and we don't write STATUS_CLR_REG_SYS_2 to clear
> the interrupt indication, so maybe there's an interrupt storm), and we
> think some other interrupt (DPA_1, whatever that is) is actually a
> link-down interrupt?

While it is true that actual link-down interrupts are ignored, it is not
the case that there's an interrupt storm because the same incorrect macro
is used to enable the interrupt line. Since the enables an interrupt for
DPA_1 which never fires, we don't run into the situation where we are not
clearing the interrupt (the interrupt handler will look for the same
incorrect field to clear the interrupt if it does fire for DPA_1, but that
doesn't happen). The 'linkdown_irq_regfield' corresponds to the
"link-state" field not just in the J784S4 SoC, but in all SoCs supported by
the pci-j721e.c driver. It is only in J721E that it is BIT(1)
[LINK_DOWN macro], while in all other SoCs (J784S4 included), it is BIT(10)
[J7200_LINK_DOWN macro since it was first added for J7200 SoC]. Matt
probably referred to J721E's Technical Reference Manual and ended up
incorrectly assigning "LINK_DOWN", due to which the driver is enabling
the DPA_1 interrupt and the interrupt handler is also going to look for
the field corresponding to receiving an interrupt for DPA_1.

> 
> > Hence, set 'linkdown_irq_regfield' to the macro 'J7200_LINK_DOWN' which
> > expands to BIT(10) and was first defined for the J7200 SoC. Other SoCs
> > already reuse this macro since it accurately represents the link-state
> > field in their respective "PCIE_INTD_ENABLE_REG_SYS_2" register.
> > 
> > [0]: https://www.ti.com/lit/zip/spruj52
> 
> Thanks for the spec URL.  Can you include a relevant section number?
> I searched for some of this stuff but couldn't find it.

The URL above is taken from the "User Guide" section of the following
webpage:
https://www.ti.com/product/TDA4VH-Q1
corresponding to the J784S4 SoC (TDA4VH is another name for it).

The User Guide [0] is a zip file containing the Technical Reference
Manual (without Registers) along with an Excel Sheet containing the
Registers. There unfortunately is no particular section that I can
quote in the Excel Sheet. The PCIe registers described in the Excel
Sheet contain the "PCIE_INTD_ENABLE_REG_SYS_2" register in one of the
rows (I didn't want to mention the row number since things could change
over time, similar to how you pointed out below that the URL could
potentially change). However, the register name should remain the same,
the reason being that the name is consistent across all SoCs supported
by the pci-j721e.c.

> 
> Since I have low confidence that the URL will be valid after a few
> years, I wish the spec also had a human-readable name and revision
> number.  But maybe the alphabet soup or "SPRUJ52D", "revised July
> 2024" is all we can hope for.

I can only hope that the URL will redirect to the latest version of the
User Guide if at all it becomes invalid.

Regards,
Siddharth.


From manivannan.sadhasivam at linaro.org  Wed Mar 12 23:05:21 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Thu, 13 Mar 2025 11:35:21 +0530
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
Message-ID: <20250313060521.kjue4la47xd7g4te@thinkpad>

On Wed, Mar 05, 2025 at 11:20:21AM -0500, Frank Li wrote:
> This patches basic on
> https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/
> 
> I have not hardware to test.
> 
> Look for driver owner, who help test this and start move forward to remove
> cpu_addr_fixup() work.
> 

If you remove cpu_addr_fixup() callback, it will break backwards compatibility
with old DTs.

You should fix the existing DTs and continue carrying the callback for a while.

- Mani

-- 
????????? ????????


From jernej.skrabec at gmail.com  Wed Mar 12 23:07:24 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Thu, 13 Mar 2025 07:07:24 +0100
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <20250312193629.85417-2-michael@fossekall.de>
References: <20250312193629.85417-1-michael@fossekall.de>
 <20250312193629.85417-2-michael@fossekall.de>
Message-ID: <4637912.LvFx2qVVIh@jernej-laptop>

Hi,

Dne sreda, 12. marec 2025 ob 20:36:28 Srednjeevropski standardni ?as je Michael Klein napisal(a):
> The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
> Add the corresponding nodes to the device tree.
> 
> Signed-off-by: Michael Klein <michael at fossekall.de>

This is patch 2/2. Which one is patch 1/2? I got only one.

Best regards,
Jernej

> ---
>  .../boot/dts/allwinner/sun7i-a20-bananapi.dts | 27 +++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> index 46ecf9db2324..4976453ed192 100644
> --- a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> +++ b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> @@ -48,6 +48,7 @@
>  
>  #include <dt-bindings/gpio/gpio.h>
>  #include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/leds/common.h>
>  
>  / {
>  	model = "LeMaker Banana Pi";
> @@ -169,6 +170,32 @@ &ir0 {
>  &gmac_mdio {
>  	phy1: ethernet-phy at 1 {
>  		reg = <1>;
> +
> +		leds {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			led at 0 {
> +				reg = <0>;
> +				color = <LED_COLOR_ID_GREEN>;
> +				default-state = "keep";
> +				linux,default-trigger = "netdev";
> +			};
> +
> +			led at 1 {
> +				reg = <1>;
> +				color = <LED_COLOR_ID_AMBER>;
> +				default-state = "keep";
> +				linux,default-trigger = "netdev";
> +			};
> +
> +			led at 2 {
> +				reg = <2>;
> +				color = <LED_COLOR_ID_BLUE>;
> +				default-state = "keep";
> +				linux,default-trigger = "netdev";
> +			};
> +		};
>  	};
>  };
>  
> 






From gshan at redhat.com  Wed Mar 12 23:09:51 2025
From: gshan at redhat.com (Gavin Shan)
Date: Thu, 13 Mar 2025 16:09:51 +1000
Subject: [PATCH] KVM: arm64: Drop sort_memblock_regions()
In-Reply-To: <34b8242b-529b-4ad5-ac17-e1200965ae1d@arm.com>
References: <20250311043718.91004-1-gshan@redhat.com>
 <34b8242b-529b-4ad5-ac17-e1200965ae1d@arm.com>
Message-ID: <88c66ec3-5b03-4488-9733-ae917cbc0536@redhat.com>

On 3/13/25 12:53 PM, Anshuman Khandual wrote:
> On 3/11/25 10:07, Gavin Shan wrote:
>> Drop sort_memblock_regions() and avoid sorting the copied memory
>> regions to be ascending order on their base addresses, because the
>> source memory regions should have been sorted correctly when they
>> are added by memblock_add() or its variants.
>>
>> This is generally reverting commit a14307f5310c ("KVM: arm64: Sort
>> the hypervisor memblocks"). No functional changes intended.
> 
> Just wondering what prompted this change ?
> 

I found the unnecessary sorting by code inspection. Hope there is nothing I
missed and it's why Quentin Perret has been copied, to confirm it. Commit
a14307f5310c was introduced by the initial series [1/2] to support pKVM.

[1] https://lore.kernel.org/kvmarm/20201117181607.1761516-1-qperret at google.com/
[2] https://lore.kernel.org/all/20210319100146.1149909-1-qperret at google.com/

Thanks,
Gavin

>>
>> Signed-off-by: Gavin Shan <gshan at redhat.com>
>> ---
>>   arch/arm64/kvm/pkvm.c | 19 -------------------
>>   1 file changed, 19 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
>> index 930b677eb9b0..d9c9174f89a1 100644
>> --- a/arch/arm64/kvm/pkvm.c
>> +++ b/arch/arm64/kvm/pkvm.c
>> @@ -10,7 +10,6 @@
>>   #include <asm/kvm_mmu.h>
>>   #include <linux/memblock.h>
>>   #include <linux/mutex.h>
>> -#include <linux/sort.h>
>>   
>>   #include <asm/kvm_pkvm.h>
>>   
>> @@ -24,23 +23,6 @@ static unsigned int *hyp_memblock_nr_ptr = &kvm_nvhe_sym(hyp_memblock_nr);
>>   phys_addr_t hyp_mem_base;
>>   phys_addr_t hyp_mem_size;
>>   
>> -static int cmp_hyp_memblock(const void *p1, const void *p2)
>> -{
>> -	const struct memblock_region *r1 = p1;
>> -	const struct memblock_region *r2 = p2;
>> -
>> -	return r1->base < r2->base ? -1 : (r1->base > r2->base);
>> -}
>> -
>> -static void __init sort_memblock_regions(void)
>> -{
>> -	sort(hyp_memory,
>> -	     *hyp_memblock_nr_ptr,
>> -	     sizeof(struct memblock_region),
>> -	     cmp_hyp_memblock,
>> -	     NULL);
>> -}
>> -
>>   static int __init register_memblock_regions(void)
>>   {
>>   	struct memblock_region *reg;
>> @@ -52,7 +34,6 @@ static int __init register_memblock_regions(void)
>>   		hyp_memory[*hyp_memblock_nr_ptr] = *reg;
>>   		(*hyp_memblock_nr_ptr)++;
>>   	}
>> -	sort_memblock_regions();
>>   
>>   	return 0;
>>   }
> 



From quic_jiegan at quicinc.com  Wed Mar 12 23:15:42 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Thu, 13 Mar 2025 14:15:42 +0800
Subject: [PATCH v1 0/4] coresight: ctcu: Enable byte-cntr function for TMC
 ETR
In-Reply-To: <CAJ9a7Vj=Ni_o94u1B+oouv0GD5DVmST=N31-hsN=SPSbaoqO_Q@mail.gmail.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <CAJ9a7Vj=Ni_o94u1B+oouv0GD5DVmST=N31-hsN=SPSbaoqO_Q@mail.gmail.com>
Message-ID: <8a18c699-3d36-4143-9a1b-6074fea52263@quicinc.com>



On 3/12/2025 9:22 PM, Mike Leach wrote:
> Hi,
> 
> On Mon, 10 Mar 2025 at 09:05, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>
>> From: Jie Gan <jie.gan at oss.qualcomm.com>
>>
>> The byte-cntr function provided by the CTCU device is used to transfer data
>> from the ETR buffer to the userspace. An interrupt is tiggered if the data
>> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
>> handler counts the number of triggered interruptions and the read function
>> will read the data from the ETR buffer if the IRQ count is greater than 0.
>> Each successful read process will decrement the IRQ count by 1.
>>
>> The byte cntr function will start when the device node is opened for reading,
>> and the IRQ count will reset when the byte cntr function has stopped. When
>> the file node is opened, the w_offset of the ETR buffer will be read and
>> stored in byte_cntr_data, serving as the original r_offset (indicating
>> where reading starts) for the byte counter function.
>>
>> The work queue for the read operation will wake up once when ETR is stopped,
>> ensuring that the remaining data in the ETR buffer has been flushed based on
>> the w_offset read at the time of stopping.
>>
>> The following shell commands write threshold to BYTECNTRVAL registers.
>>
>> Only enable byte-cntr for ETR0:
>> echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>>
>> Enable byte-cntr for both ETR0 and ETR1(support both hex and decimal values):
>> echo 0x10000 4096 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>>
>> Setting the BYTECNTRVAL registers to 0 disables the byte-cntr function.
>> Disable byte-cntr for ETR0:
>> echo 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>>
>> Disable byte-cntr for both ETR0 and ETR1:
>> echo 0 0 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>>
>> There is a minimum threshold to prevent generating too many interrupts.
>> The minimum threshold is 4096 bytes. The write process will fail if user try
>> to set the BYTECNTRVAL registers to a value less than 4096 bytes(except
>> for 0).
>>
>> Finally, the user can read data from the ETR buffer through the byte-cntr file
>> nodes located under /dev, for example reads data from the ETR0 buffer:
>> cat /dev/byte-cntr0
>>
>> Way to enable and start byte-cntr for ETR0:
>> echo 0x10000 > /sys/devices/platform/soc at 0/4001000.ctcu/ctcu0/byte_cntr_val
>> echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
>> echo 1 > /sys/bus/coresight/devices/etm0/enable_source
>> cat /dev/byte-cntr0
>>
> 
> There is a significant issue with attempting to drain an ETR buffer
> while it is live in the way you appear to be doing.
> 
> You have no way of knowing if the TMC hardware write pointer wraps and
> overtakes the point where you are currently reading. This could cause
> data corruption as TMC writes as you are reading, or contention for
> the buffer that affects the TMC write.
> 
> Even if those two events do not occur, then the trace capture sequence
> is corrupted.
> 
> Take a simple example - suppose we split the buffer into 4 blocks of
> trace, which are filled by the ETR
> 
> buffer = 1, 2, 3, 4
> 
> Now you suppose you have read 1 & 2 into your userspace buffer / file.
> 
> file = 1, 2
> 
> If there is now some system event that prevents your userspace code
> from running for a while, then it is possible that the ETR continues,
> wraps and the buffer is now
> 
> buffer = 5, 6, 7, 4
> 
> Your next two reads will be 7, 4
> 
> file = 1, 2, 7, 4
> 
> This trace is now corrupt and will cause decode errors. There is no
> way for the decoder to determine that the interface between blocks 2 &
> 7 is not correct. If you are fortunate then this issue will cause an
> actual explicit decode error, if you are less fortunate then decode
> will continue but in fact be inaccurate, with no obvious way to detect
> the inaccuracy.
> 
> We encountered this problem early in the development of the perf data
> collection. Even though perf was stopping the trace to copy the
> hardware buffer, it would concatenate unrelated trace blocks into the
> perf userspace buffer, which initially caused decoding errors. This is
> now mitigated in perf by marking boundaries and recording indexes of
> the boundaries, so the tool can reset the decoder at the start of non
> contiguous blocks.
> 
> If you do not stop the TMC when draining the ETR buffer, you have no
> way of determining if this has occurred.
> 
> Clearly using large buffers, split into smaller blocks can mitigate
> the possibility of a wrap in this way - but never eliminate it,
> especially given the extreme rate that trace data can be generated.
> 

Hi Mike,

Thanks for detailed explanation. It's clear and makes sense to me.

I will look for another reasonable solution.

Thanks,
Jie

> Regards
> 
> Mike
> 
> 
>> Jie Gan (4):
>>    coresight: tmc: Introduce new APIs to get the RWP offset of ETR buffer
>>    dt-bindings: arm: Add an interrupt property for Coresight CTCU
>>    coresight: ctcu: Enable byte-cntr for TMC ETR devices
>>    arm64: dts: qcom: sa8775p: Add interrupts to CTCU device
>>
>>   .../bindings/arm/qcom,coresight-ctcu.yaml     |  17 +
>>   arch/arm64/boot/dts/qcom/sa8775p.dtsi         |   5 +
>>   drivers/hwtracing/coresight/Makefile          |   2 +-
>>   .../coresight/coresight-ctcu-byte-cntr.c      | 339 ++++++++++++++++++
>>   .../hwtracing/coresight/coresight-ctcu-core.c |  96 ++++-
>>   drivers/hwtracing/coresight/coresight-ctcu.h  |  59 ++-
>>   .../hwtracing/coresight/coresight-tmc-etr.c   |  45 ++-
>>   drivers/hwtracing/coresight/coresight-tmc.h   |   3 +
>>   8 files changed, 556 insertions(+), 10 deletions(-)
>>   create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>>
>> --
>> 2.34.1
>>
> 
> 



From hch at lst.de  Wed Mar 12 23:30:19 2025
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 13 Mar 2025 07:30:19 +0100
Subject: [PATCH] block: remove unused parameter
In-Reply-To: <20250313035322.243239-1-anuj20.g@samsung.com>
References: <CGME20250313040150epcas5p347f94dac34fd2946dea51049559ee1de@epcas5p3.samsung.com> <20250313035322.243239-1-anuj20.g@samsung.com>
Message-ID: <20250313063019.GB9789@lst.de>

Looks good:

Reviewed-by: Christoph Hellwig <hch at lst.de>


From rohit.visavalia at amd.com  Wed Mar 12 23:36:35 2025
From: rohit.visavalia at amd.com (Visavalia, Rohit)
Date: Thu, 13 Mar 2025 06:36:35 +0000
Subject: [PATCH v3 0/2] clk: xilinx: vcu: Sequence update and call trace
 fix
In-Reply-To: <20250210113614.4149050-1-rohit.visavalia@amd.com>
References: <20250210113614.4149050-1-rohit.visavalia@amd.com>
Message-ID: <DM6PR12MB48770D3D5731EA5ED4DCCA6DE5D32@DM6PR12MB4877.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

Hi All,

Just a gentle reminder regarding this patch series review.

Thanks & Regards
Rohit

>-----Original Message-----
>From: Rohit Visavalia <rohit.visavalia at amd.com>
>Sent: Monday, February 10, 2025 5:06 PM
>To: mturquette at baylibre.com; sboyd at kernel.org; Simek, Michal
><michal.simek at amd.com>; Sagar, Vishal <vishal.sagar at amd.com>
>Cc: javier.carrasco.cruz at gmail.com; geert+renesas at glider.be; u.kleine-
>koenig at baylibre.com; linux-clk at vger.kernel.org; linux-arm-
>kernel at lists.infradead.org; linux-kernel at vger.kernel.org; Visavalia, Rohit
><rohit.visavalia at amd.com>
>Subject: [PATCH v3 0/2] clk: xilinx: vcu: Sequence update and call trace fix
>
>This patch series updates VCU init/reset sequence and does a driver fix.
>patch1 fixes call trace related to pll_post clk.
>Patch2 adds optional reset-gpio support.
>
>---
>Changes in v3:
>  - Removed patch https://lore.kernel.org/linux-clk/20250102170359.761670-3-
>rohit.visavalia at amd.com
>    as it is not required with latest xilinx clk driver.
>  - Link to v2: https://lore.kernel.org/linux-clk/20250102170359.761670-1-
>rohit.visavalia at amd.com/
>
>Changes in v2:
>  - Changed patches sequence to have patches with "Fixes" as preceding in order
>  - Used dev_err_probe()
>  - Moved warning to dev_dbg() and updated print with more detail
>  - Link to v1: https://lore.kernel.org/linux-clk/20241226122023.3439559-1-
>rohit.visavalia at amd.com
>
>Rohit Visavalia (2):
>  clk: xilinx: vcu: unregister pll_post only if registered correctly
>  clk: xilinx: vcu: Update vcu init/reset sequence
>
> drivers/clk/xilinx/xlnx_vcu.c | 33 +++++++++++++++++++++++++++++++--
> 1 file changed, 31 insertions(+), 2 deletions(-)
>
>--
>2.25.1



From ukleinek at kernel.org  Thu Mar 13 00:22:53 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Thu, 13 Mar 2025 08:22:53 +0100
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <5b62671c-719a-44f2-b28e-878159859a01@mleia.com>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
 <57ae63a2-544b-4241-a54d-8fa9917c1e44@mleia.com>
 <yvljnqnlka3ecw2n3hw2zgfszlldvbww3k7gq72dczmf6jwzfo@4vqnygxuzvk5>
 <5b62671c-719a-44f2-b28e-878159859a01@mleia.com>
Message-ID: <b2nlqt3gp4sk7cax722n7t7xonnrjzi6amsfrhylxmurctytiy@yqp7qpttyc5h>

Hello Vladimir,

On Thu, Mar 13, 2025 at 05:37:44AM +0200, Vladimir Zapolskiy wrote:
> On 3/13/25 00:56, Uwe Kleine-K?nig wrote:
> > Hello,
> > 
> > On Wed, Mar 12, 2025 at 07:59:21PM +0200, Vladimir Zapolskiy wrote:
> > > > +  "#pwm-cells":
> > > > +    const: 3
> > > 
> > > It shall be 1.
> > 
> > No, 3 is the right choice.
> > 
> 
> could you please elaborate?
> 
> I find that here the only configurable parameter is PWM period, so it
> should be sufficient to have one cell only like in marvell,pxa-pwm.yaml
> or google,cros-ec-pwm.yaml.

These two bindings are special snow-flakes and the only drivers that
have #pwm-cells = <1>. Most other bindings use 3 and since commit
895fe4537cc8 ("pwm: Add upgrade path to #pwm-cells = <3> for users of
of_pwm_single_xlate()") (which was created for the pxa driver) the pxa
driver also supports 3 cells. The cros-ec driver even has comment about
that being ugly. 

I intend to convert all bindings to use 3 soon.

While that isn't necessary for each individual piece of hardware to
provide 3 values, having a uniform binding for PWMs provides a nice user
experience and also simplifies matters with nexus nodes (see
e71e46a6f19c ("pwm: Add support for pwm nexus dt bindings")).

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/581c5ba4/attachment.sig>

From krzk at kernel.org  Thu Mar 13 00:30:10 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 08:30:10 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <6e1757ea-3f5e-4cc0-b142-aee52f016c8f@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <6e1757ea-3f5e-4cc0-b142-aee52f016c8f@foss.st.com>
Message-ID: <49e87f3a-2f02-40d2-9307-22cfaaa8be7a@kernel.org>

On 10/03/2025 14:52, Patrice CHOTARD wrote:
>> +module_platform_driver(stm32_omm_driver);
>> +
>> +MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
>> +MODULE_LICENSE("GPL");
> 
> 
> Hi all,
> 
> Anybody alse has additionnal remarks on this driver ?
BTW, you explained nothing about merging in the cover letter, mark
already took the patch, but I see there is dependency. This cannot be
merged and pinging will not change anything here.

In the future, ALWAYS document dependencies between patches and make it
explicit for the maintainers.

Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar 13 00:33:59 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 08:33:59 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
 <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>
Message-ID: <ac119dba-6e73-496c-97e1-d59ac0fe4a27@kernel.org>

On 12/03/2025 15:23, Patrice CHOTARD wrote:
>>> +static int stm32_omm_disable_child(struct device *dev)
>>> +{
>>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>>> +	struct reset_control *reset;
>>> +	int ret;
>>> +	u8 i;
>>> +
>>> +	for (i = 0; i < omm->nb_child; i++) {
>>> +		ret = clk_prepare_enable(omm->child[i].clk);
>>> +		if (ret) {
>>> +			dev_err(dev, "Can not enable clock\n");
>>> +			return ret;
>>> +		}
>>> +
>>> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
>>> +		if (IS_ERR(reset)) {
>>> +			dev_err(dev, "Can't get child reset\n");
>>
>> Why do you get reset of child? Parent is not suppposed to poke there.
>> You might not have the reset there in the first place and it would not
>> be an error.
> 
> By ressetting child (OSPI), we ensure they are disabled and in a known state.
> See the comment below.
> 
>>
>>
>>> +			return PTR_ERR(reset);
>>> +		};
>>> +
>>> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
>>> +		reset_control_assert(reset);
>>> +		udelay(2);
>>> +		reset_control_deassert(reset);
>>
>> No, the child should handle this, not parent.
> 
> Octo Memory Manager can only be configured if both child are disabled.
> That's why here, parent handles this.

So if device by any chance started and is doing some useful work, then
you cancel that work and reset it?

And what if child does not have reset line? Your binding allows that, so
how is it supposed to work then?

This also leads me to questions about bindings - if you need to assert
some reset, doesn't it mean that these resets are also coming through
this device so they are part of this device node?


> 
>>
>>> +
>>> +		reset_control_put(reset);
>>> +		clk_disable_unprepare(omm->child[i].clk);
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int stm32_omm_probe(struct platform_device *pdev)
>>> +{
>>> +	struct platform_device *vdev;
>>> +	struct device *dev = &pdev->dev;
>>> +	struct stm32_omm *omm;
>>> +	struct clk *clk;
>>> +	int ret;
>>> +	u8 child_access_granted = 0;
>>
>> Keep inits/assignments together
> 
> ok
> 
>>
>>> +	u8 i, j;
>>> +	bool child_access[OMM_CHILD_NB];
>>> +
>>> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
>>> +	if (!omm)
>>> +		return -ENOMEM;
>>> +
>>> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
>>> +	if (IS_ERR(omm->io_base))
>>> +		return PTR_ERR(omm->io_base);
>>> +
>>> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
>>> +	if (IS_ERR(omm->mm_res))
>>> +		return PTR_ERR(omm->mm_res);
>>> +
>>> +	/* check child's access */
>>> +	for_each_child_of_node_scoped(dev->of_node, child) {
>>> +		if (omm->nb_child >= OMM_CHILD_NB) {
>>> +			dev_err(dev, "Bad DT, found too much children\n");
>>> +			ret = -E2BIG;
>>> +			goto err_clk_release;
>>> +		}
>>> +
>>> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
>>> +			ret = -EINVAL;
>>> +			goto err_clk_release;
>>> +		}
>>> +
>>> +		ret = stm32_omm_check_access(dev, child);
>>> +		if (ret < 0 && ret != -EACCES)
>>> +			goto err_clk_release;
>>> +
>>> +		child_access[omm->nb_child] = false;
>>> +		if (!ret) {
>>> +			child_access_granted++;
>>> +			child_access[omm->nb_child] = true;
>>> +		}
>>> +
>>> +		omm->child[omm->nb_child].node = child;
>>> +
>>> +		clk = of_clk_get(child, 0);
>>
>> Why are you taking children clock? And why with this API, not clk_get?
> 
> I need children's clock to reset them.


The device driver should reset its device. It is not a discoverable bus,
that would explain power sequencing from the parent.

> Why of_clk_get() usage is a problem here ? i can't get your point ?

Because it is not the API which device drivers should use. You should
use clk_get or devm_clk_get.


> 
>> This looks like mixing clock provider in the clock consumer.
>>
>>> +		if (IS_ERR(clk)) {
>>> +			dev_err(dev, "Can't get child clock\n");
>>
>> Syntax is always return dev_err_probe (or ret = dev_err_probe).
> 
> ok
> 
>>
>>> +			ret = PTR_ERR(clk);
>>> +			goto err_clk_release;
>>> +		};
>>> +
>>> +		omm->child[omm->nb_child].clk = clk;
>>> +		omm->nb_child++;
>>> +	}
>>> +
>>> +	if (omm->nb_child != OMM_CHILD_NB) {
>>> +		ret = -EINVAL;
>>> +		goto err_clk_release;
>>> +	}
>>> +
>>> +	platform_set_drvdata(pdev, omm);
>>> +
>>> +	pm_runtime_enable(dev);
>>> +
>>> +	/* check if OMM's resource access is granted */
>>> +	ret = stm32_omm_check_access(dev, dev->of_node);
>>> +	if (ret < 0 && ret != -EACCES)
>>> +		goto err_clk_release;
>>> +
>>> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
>>> +		/* Ensure both OSPI instance are disabled before configuring OMM */
>>> +		ret = stm32_omm_disable_child(dev);
>>> +		if (ret)
>>> +			goto err_clk_release;
>>> +
>>> +		ret = stm32_omm_configure(dev);
>>> +		if (ret)
>>> +			goto err_clk_release;
>>> +	} else {
>>> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
>>> +		/*
>>> +		 * AMCR can't be set, so check if current value is coherent
>>> +		 * with memory-map areas defined in DT
>>> +		 */
>>> +		ret = stm32_omm_set_amcr(dev, false);
>>> +		if (ret)
>>> +			goto err_clk_release;
>>> +	}
>>> +
>>> +	/* for each child, if resource access is granted and status "okay", probe it */
>>> +	for (i = 0; i < omm->nb_child; i++) {
>>> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
>>
>> If you have a device available, why do you create one more platform device?
>>
>>> +			continue;
>>> +
>>> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
>>
>> Why you cannot just populate the children?
> 
> I can't use of_platform_populate(), by default it will populate all OMM's child.
> Whereas here, we want to probe only the OMM's child which match our criteria.  


Why wouldn't you populate everyone? The task of bus driver is not to
filter out DT. If you got such DT - with all device nodes - you are
expected to populate all of them. Otherwise, if you do not want all of
them, it is expected that firmware or bootloader will give you DT
without these nodes.

Best regards,
Krzysztof


From akihiko.odaki at daynix.com  Wed Mar 12 23:57:41 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:41 +0900
Subject: [PATCH v4 0/7] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Message-ID: <20250313-pmc-v4-0-2c976827118c@daynix.com>

Prepare vPMC registers for user-initiated changes after first run. This
is important specifically for debugging Windows on QEMU with GDB; QEMU
tries to write back all visible registers when resuming the VM execution
with GDB, corrupting the PMU state. Windows always uses the PMU so this
can cause adverse effects on that particular OS.

This series also contains patch "KVM: arm64: PMU: Set raw values from
user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
changes made for the mentioned registers in the past. It is necessary
to migrate the PMU state properly on Firecracker, QEMU, and crosvm.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
Changes in v4:
- Reverted changes for functions implementing ioctls in patch
  "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
- Removed kvm_pmu_vcpu_reset().
- Reordered function calls in kvm_vcpu_reload_pmu() for better style.
- Link to v3: https://lore.kernel.org/r/20250312-pmc-v3-0-0411cab5dc3d at daynix.com

Changes in v3:
- Added patch "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
- Added an explanation of this path series' motivation to each patch.
- Explained why userspace register writes and register reset should be
  covered in patch "KVM: arm64: PMU: Reload when user modifies
  registers".
- Marked patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" for stable.
- Reoreded so that patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" would come first.
- Added patch "KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking
  PMCNTENSET_EL0".
- Added patch "KVM: arm64: Reload PMCNTENSET_EL0".
- Link to v2: https://lore.kernel.org/r/20250307-pmc-v2-0-6c3375a5f1e4 at daynix.com

Changes in v2:
- Changed to utilize KVM_REQ_RELOAD_PMU as suggested by Oliver Upton.
- Added patch "KVM: arm64: PMU: Reload when user modifies registers"
  to cover more registers.
- Added patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}".
- Link to v1: https://lore.kernel.org/r/20250302-pmc-v1-1-caff989093dc at daynix.com

---
Akihiko Odaki (7):
      KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
      KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
      KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
      KVM: arm64: PMU: Reload when user modifies registers
      KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking PMCNTENSET_EL0
      KVM: arm64: PMU: Reload PMCNTENSET_EL0
      KVM: arm64: PMU: Reload when resetting

 arch/arm64/kvm/arm.c      |  8 ++++---
 arch/arm64/kvm/pmu-emul.c | 60 ++++++++++++++---------------------------------
 arch/arm64/kvm/reset.c    |  3 ---
 arch/arm64/kvm/sys_regs.c | 53 +++++++++++++++++++++++------------------
 include/kvm/arm_pmu.h     |  3 +--
 5 files changed, 53 insertions(+), 74 deletions(-)
---
base-commit: da2f480cb24d39d480b1e235eda0dd2d01f8765b
change-id: 20250302-pmc-b90a86af945c

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:42 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:42 +0900
Subject: [PATCH v4 1/7] KVM: arm64: PMU: Set raw values from user to
 PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-1-2c976827118c@daynix.com>

Commit a45f41d754e0 ("KVM: arm64: Add {get,set}_user for
PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}") changed KVM_SET_ONE_REG to update
the mentioned registers in a way matching with the behavior of guest
register writes. This is a breaking change of a UAPI though the new
semantics looks cleaner and VMMs are not prepared for this.

Firecracker, QEMU, and crosvm perform migration by listing registers
with KVM_GET_REG_LIST, getting their values with KVM_GET_ONE_REG and
setting them with KVM_SET_ONE_REG. This algorithm assumes
KVM_SET_ONE_REG restores the values retrieved with KVM_GET_ONE_REG
without any alteration. However, bit operations added by the earlier
commit do not preserve the values retried with KVM_GET_ONE_REG and
potentially break migration.

Remove the bit operations that alter the values retrieved with
KVM_GET_ONE_REG.

Cc: stable at vger.kernel.org
Fixes: a45f41d754e0 ("KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
Acked-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/sys_regs.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 42791971f758..0a2ce931a946 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1126,26 +1126,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
-	bool set;
-
-	val &= kvm_pmu_valid_counter_mask(vcpu);
-
-	switch (r->reg) {
-	case PMOVSSET_EL0:
-		/* CRm[1] being set indicates a SET register, and CLR otherwise */
-		set = r->CRm & 2;
-		break;
-	default:
-		/* Op2[0] being set indicates a SET register, and CLR otherwise */
-		set = r->Op2 & 1;
-		break;
-	}
-
-	if (set)
-		__vcpu_sys_reg(vcpu, r->reg) |= val;
-	else
-		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
-
+	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
 	return 0;
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:43 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:43 +0900
Subject: [PATCH v4 2/7] KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-2-2c976827118c@daynix.com>

Many functions in pmu-emul.c checks kvm_vcpu_has_pmu(vcpu). A favorable
interpretation is defensive programming, but it also has downsides:

- It is confusing as it implies these functions are called without PMU
  although most of them are called only when a PMU is present.

- It makes semantics of functions fuzzy. For example, calling
  kvm_pmu_disable_counter_mask() without PMU may result in no-op as
  there are no enabled counters, but it's unclear what
  kvm_pmu_get_counter_value() returns when there is no PMU.

- It allows callers without checking kvm_vcpu_has_pmu(vcpu), but it is
  often wrong to call these functions without PMU.

- It is error-prone to duplicate kvm_vcpu_has_pmu(vcpu) checks into
  multiple functions. Many functions are called for system registers,
  and the system register infrastructure already employs less
  error-prone, comprehensive checks.

Check kvm_vcpu_has_pmu(vcpu) in callers of these functions instead,
and remove the obsolete checks from pmu-emul.c. The only exceptions are
the functions that implement ioctls as they have definitive semantics
even when the PMU is not present.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/arm.c      |  8 +++++---
 arch/arm64/kvm/pmu-emul.c | 25 +------------------------
 arch/arm64/kvm/sys_regs.c |  6 ++++--
 3 files changed, 10 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index f66ce098f03b..e375468a2217 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -834,9 +834,11 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
-	ret = kvm_arm_pmu_v3_enable(vcpu);
-	if (ret)
-		return ret;
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		ret = kvm_arm_pmu_v3_enable(vcpu);
+		if (ret)
+			return ret;
+	}
 
 	if (is_protected_kvm_enabled()) {
 		ret = pkvm_create_hyp_vm(kvm);
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index e3e82b66e226..3dd0b479c6fd 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -144,9 +144,6 @@ static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
  */
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	return kvm_pmu_get_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
 }
 
@@ -185,9 +182,6 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
  */
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
@@ -289,8 +283,6 @@ u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
 void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
 
 	if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) || !val)
 		return;
@@ -324,7 +316,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu) || !val)
+	if (!val)
 		return;
 
 	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) {
@@ -357,9 +349,6 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
 	bool overflow;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	overflow = !!kvm_pmu_overflow_status(vcpu);
 	if (pmu->irq_level == overflow)
 		return;
@@ -555,9 +544,6 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	/* Fixup PMCR_EL0 to reconcile the PMU version and the LP bit */
 	if (!kvm_has_feat(vcpu->kvm, ID_AA64DFR0_EL1, PMUVer, V3P5))
 		val &= ~ARMV8_PMU_PMCR_LP;
@@ -696,9 +682,6 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
 	struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, select_idx);
 	u64 reg;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	reg = counter_index_to_evtreg(pmc->idx);
 	__vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm);
 
@@ -804,9 +787,6 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
 	u64 val, mask = 0;
 	int base, i, nr_events;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!pmceid1) {
 		val = compute_pmceid0(cpu_pmu);
 		base = 0;
@@ -847,9 +827,6 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 
 int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!vcpu->arch.pmu.created)
 		return -EINVAL;
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 0a2ce931a946..6e75557bea1d 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1784,12 +1784,14 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu,
 				      const struct sys_reg_desc *rd)
 {
-	u8 perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
+	u8 perfmon;
 	u64 val = read_sanitised_ftr_reg(SYS_ID_DFR0_EL1);
 
 	val &= ~ID_DFR0_EL1_PerfMon_MASK;
-	if (kvm_vcpu_has_pmu(vcpu))
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
 		val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon);
+	}
 
 	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, Debugv8p8);
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:44 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:44 +0900
Subject: [PATCH v4 3/7] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-3-2c976827118c@daynix.com>

Reload the perf event when setting the vPMU counter (vPMC) registers
(PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

It is also important to keep the correct state even if userspace writes
them after first run, specifically when debugging Windows on QEMU with
GDB; QEMU tries to write back all visible registers when resuming the VM
execution with GDB, corrupting the PMU state. Windows always uses the
PMU so this can cause adverse effects on that particular OS.

Fix this by releasing the current perf event and trigger recreating one
with KVM_REQ_RELOAD_PMU.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 13 +++++++++++++
 arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
 include/kvm/arm_pmu.h     |  1 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 3dd0b479c6fd..1b91e5188d52 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -185,6 +185,19 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
+/**
+ * kvm_pmu_set_counter_value_user - set PMU counter value from user
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ * @val: The counter value
+ */
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+{
+	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+}
+
 /**
  * kvm_pmu_release_perf_event - remove the perf event
  * @pmc: The PMU counter pointer
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 6e75557bea1d..26182cae4ac7 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 	return 0;
 }
 
+static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+			  u64 val)
+{
+	u64 idx;
+
+	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+		/* PMCCNTR_EL0 */
+		idx = ARMV8_PMU_CYCLE_IDX;
+	else
+		/* PMEVCNTRn_EL0 */
+		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+	kvm_pmu_set_counter_value_user(vcpu, idx, val);
+	return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      const struct sys_reg_desc *r)
@@ -1309,6 +1325,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 #define PMU_PMEVCNTR_EL0(n)						\
 	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
 	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
+	  .set_user = set_pmu_evcntr,					\
 	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -2665,7 +2682,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  .access = access_pmceid, .reset = NULL },
 	{ PMU_SYS_REG(PMCCNTR_EL0),
 	  .access = access_pmu_evcntr, .reset = reset_unknown,
-	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
+	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
+	  .set_user = set_pmu_evcntr },
 	{ PMU_SYS_REG(PMXEVTYPER_EL0),
 	  .access = access_pmu_evtyper, .reset = NULL },
 	{ PMU_SYS_REG(PMXEVCNTR_EL0),
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 28b380ad8dfa..9c062756ebfa 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -41,6 +41,7 @@ bool kvm_supports_guest_pmuv3(void);
 #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:45 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:45 +0900
Subject: [PATCH v4 4/7] KVM: arm64: PMU: Reload when user modifies
 registers
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-4-2c976827118c@daynix.com>

Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
run") added the code to reload the PMU configuration on first run.

It is also important to keep the correct state even if system registers
are modified after first run, specifically when debugging Windows on
QEMU with GDB; QEMU tries to write back all visible registers when
resuming the VM execution with GDB, corrupting the PMU state. Windows
always uses the PMU so this can cause adverse effects on that particular
OS.

The usual register writes and reset are already handled independently,
but register writes from userspace are not covered.
Trigger the code to reload the PMU configuration for them instead so
that PMU configuration changes made by users will be applied also after
the first run.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 3 ---
 arch/arm64/kvm/sys_regs.c | 3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 1b91e5188d52..3ed8b74d9925 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -862,9 +862,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 		   return -EINVAL;
 	}
 
-	/* One-off reload of the PMU on first run */
-	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 26182cae4ac7..11718c635e2f 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1143,6 +1143,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
 	__vcpu_sys_reg(vcpu, r->reg) = val & kvm_pmu_valid_counter_mask(vcpu);
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 	return 0;
 }
 
@@ -1303,6 +1304,8 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 		val |= ARMV8_PMU_PMCR_LC;
 
 	__vcpu_sys_reg(vcpu, r->reg) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:46 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:46 +0900
Subject: [PATCH v4 5/7] KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after
 masking PMCNTENSET_EL0
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-5-2c976827118c@daynix.com>

kvm_pmu_handle_pmcr() expects PMCNTENSET_EL0 only contains valid
counters.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 3ed8b74d9925..461c76a9cb6b 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -831,11 +831,11 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 {
 	u64 mask = kvm_pmu_valid_counter_mask(vcpu);
 
-	kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
-
 	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask;
 	__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask;
 	__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask;
+
+	kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
 }
 
 int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:47 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:47 +0900
Subject: [PATCH v4 6/7] KVM: arm64: PMU: Reload PMCNTENSET_EL0
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-6-2c976827118c@daynix.com>

Disable counters that are no longer included in PMCNTENSET_EL0. It is
not necessary to enable counters included in PMCNTENSET_EL0 because
kvm_pmu_handle_pmcr() does so if appropriate.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 461c76a9cb6b..dfa7048a3e2a 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -835,6 +835,7 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 	__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask;
 	__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask;
 
+	kvm_pmu_disable_counter_mask(vcpu, ~__vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
 	kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Wed Mar 12 23:57:48 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 13 Mar 2025 15:57:48 +0900
Subject: [PATCH v4 7/7] KVM: arm64: PMU: Reload when resetting
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <20250313-pmc-v4-7-2c976827118c@daynix.com>

Replace kvm_pmu_vcpu_reset() with the generic PMU reloading mechanism to
ensure the consistency with system registers and to reduce code size.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 14 --------------
 arch/arm64/kvm/reset.c    |  3 ---
 arch/arm64/kvm/sys_regs.c |  3 +++
 include/kvm/arm_pmu.h     |  2 --
 4 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index dfa7048a3e2a..62b1deba9856 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -248,20 +248,6 @@ void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
 		pmu->pmc[i].idx = i;
 }
 
-/**
- * kvm_pmu_vcpu_reset - reset pmu state for cpu
- * @vcpu: The vcpu pointer
- *
- */
-void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
-{
-	unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
-	int i;
-
-	for_each_set_bit(i, &mask, 32)
-		kvm_pmu_stop_counter(kvm_vcpu_idx_to_pmc(vcpu, i));
-}
-
 /**
  * kvm_pmu_vcpu_destroy - free perf event of PMU for cpu
  * @vcpu: The vcpu pointer
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 0b0ae5ae7bc2..7f44539bc822 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -201,9 +201,6 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 	vcpu->arch.reset_state.reset = false;
 	spin_unlock(&vcpu->arch.mp_state_lock);
 
-	/* Reset PMU outside of the non-preemptible section */
-	kvm_pmu_vcpu_reset(vcpu);
-
 	preempt_disable();
 	loaded = (vcpu->cpu != -1);
 	if (loaded)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 11718c635e2f..307ce37d0434 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -4262,6 +4262,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 	}
 
 	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
+
+	if (kvm_vcpu_has_pmu(vcpu))
+		kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 }
 
 /**
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 9c062756ebfa..8ec6296c5917 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -45,7 +45,6 @@ void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 v
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
-void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val);
 void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val);
@@ -108,7 +107,6 @@ static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
 	return 0;
 }
 static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
-static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
 static inline void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:37 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:37 +0530
Subject: [PATCH v6 00/10] Add support for videocc, camcc, dispcc and gpucc
 on Qualcomm QCS615 platform
Message-ID: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>

Add support for multimedia clock controllers on Qualcomm QCS615 platform.
Update the defconfig to enable these clock controllers.

Global clock controller support
https://lore.kernel.org/all/20241022-qcs615-clock-driver-v4-0-3d716ad0d987 at quicinc.com/

Changes in v6:
- Remove wrongly RB-By tags which got introduced in v4 and was carried
  to v5 as well.
- Adding the reference where the tags were added and dropped.
  -[01/10] clk: qcom: clk-alpha-pll: Add support for dynamic update for slewing PLLs
    - RB-By from Imran (v2)
  -[02/10] dt-bindings: clock: Add Qualcomm QCS615 Camera clock controller
    - RB-By from Krzysztof (v2), drop wrong RB-By from Dmitry (v5)
  -[03/10] clk: qcom: camcc-qcs615: Add QCS615 camera clock controller driver
    - R-By from Bryan (v2)
  -[04/10] dt-bindings: clock: Add Qualcomm QCS615 Display clock controller
    - Drop wrong RB-By from Dmitry (v5)
  -[05/10] clk: qcom: dispcc-qcs615: Add QCS615 display clock controller driver
    - R-By from Dmitry (v1)
  -[06/10] dt-bindings: clock: Add Qualcomm QCS615 Graphics clock controller
    - Drop wrong RB-By from Dmitry(v5)
  -[07/10] clk: qcom: gpucc-qcs615: Add QCS615 graphics clock controller driver
    - R-By from Dmitry (v1)
  -[08/10] dt-bindings: clock: Add Qualcomm QCS615 Video clock controller
    - Drop wrong RB-By from Dmitry(v5)
  -[09/10] clk: qcom: videocc-qcs615: Add QCS615 video clock controller driver
    - R-By from Dmitry and Bryan (v3)
  -[10/10] arm64: defconfig: Enable QCS615 clock controllers
    - Drop wrong RB-By from Dmitry (v5)
- Link to v5: https://lore.kernel.org/r/20250221-qcs615-v5-mm-cc-v5-0-b6d9ddf2f28d at quicinc.com

Changes in v5:
- Update ARM64 || COMPILE_TEST in all Kconfig to resolve kismet warnings.
- Fix sparse errors in GPUCC.
- Link to v4: https://lore.kernel.org/r/20250119-qcs615-mm-v4-clockcontroller-v4-0-5d1bdb5a140c at quicinc.com

Changes in v4:
- Drop patch Update the support for alpha mode configuration as this
  patch was picked - https://lore.kernel.org/all/20241021-fix-alpha-mode-config-v1-1-f32c254e02bc at gmail.com/
- Update the bindings to include "qcom,gcc.yaml" [Dmitry]

Changes in v3:
- update PLL configs to use BIT and GENMASK for vco_val and vco_mask for all CCs [Bryan O'Donoghue]
- Link to v2: https://lore.kernel.org/r/20241101-qcs615-mm-clockcontroller-v2-0-d1a4870a4aed at quicinc.com

Changes in v2:
- cleanups in clk_alpha_pll_slew_update and clk_alpha_pll_slew_enable functions [Christophe]
- update PLL configs for "vco_val = 0x0" shift(20)  [Bryan O'Donoghue]
- update PLL configs to use lower case for L value  [Dmitry]
- Link parents for IFE/IPE/BPS GDSCs as Titan Top GDSC [Bryan O'Donoghue, Dmitry]
- Remove DT_BI_TCXO_AO from camcc-qcs615           [Dmitry]
- Remove HW_CTRL_TRIGGER from camcc-qcs615         [Bryan O'Donoghue]
- Update platform name for default configuration   [Dmitry]
- Link to v1: https://lore.kernel.org/r/20241019-qcs615-mm-clockcontroller-v1-0-4cfb96d779ae at quicinc.com

Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
Taniya Das (10):
      clk: qcom: clk-alpha-pll: Add support for dynamic update for slewing PLLs
      dt-bindings: clock: Add Qualcomm QCS615 Camera clock controller
      clk: qcom: camcc-qcs615: Add QCS615 camera clock controller driver
      dt-bindings: clock: Add Qualcomm QCS615 Display clock controller
      clk: qcom: dispcc-qcs615: Add QCS615 display clock controller driver
      dt-bindings: clock: Add Qualcomm QCS615 Graphics clock controller
      clk: qcom: gpucc-qcs615: Add QCS615 graphics clock controller driver
      dt-bindings: clock: Add Qualcomm QCS615 Video clock controller
      clk: qcom: videocc-qcs615: Add QCS615 video clock controller driver
      arm64: defconfig: Enable QCS615 clock controllers

 .../bindings/clock/qcom,qcs615-camcc.yaml          |   54 +
 .../bindings/clock/qcom,qcs615-dispcc.yaml         |   73 +
 .../bindings/clock/qcom,qcs615-gpucc.yaml          |   66 +
 .../bindings/clock/qcom,qcs615-videocc.yaml        |   64 +
 arch/arm64/configs/defconfig                       |    4 +
 drivers/clk/qcom/Kconfig                           |   38 +
 drivers/clk/qcom/Makefile                          |    4 +
 drivers/clk/qcom/camcc-qcs615.c                    | 1591 ++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.c                   |  170 +++
 drivers/clk/qcom/clk-alpha-pll.h                   |    1 +
 drivers/clk/qcom/dispcc-qcs615.c                   |  786 ++++++++++
 drivers/clk/qcom/gpucc-qcs615.c                    |  525 +++++++
 drivers/clk/qcom/videocc-qcs615.c                  |  332 ++++
 include/dt-bindings/clock/qcom,qcs615-camcc.h      |  110 ++
 include/dt-bindings/clock/qcom,qcs615-dispcc.h     |   52 +
 include/dt-bindings/clock/qcom,qcs615-gpucc.h      |   39 +
 include/dt-bindings/clock/qcom,qcs615-videocc.h    |   30 +
 17 files changed, 3939 insertions(+)
---
base-commit: 50a0c754714aa3ea0b0e62f3765eb666a1579f24
change-id: 20250221-qcs615-v5-mm-cc-8b94afca89c5

Best regards,
-- 
Taniya Das <quic_tdas at quicinc.com>



From quic_tdas at quicinc.com  Wed Mar 12 23:59:38 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:38 +0530
Subject: [PATCH v6 01/10] clk: qcom: clk-alpha-pll: Add support for dynamic
 update for slewing PLLs
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-1-ebf4b9a5e916@quicinc.com>

The alpha PLLs which slew to a new frequency at runtime would require
the PLL to calibrate at the mid point of the VCO. Add the new PLL ops
which can support the slewing of the PLL to a new frequency.

Reviewed-by: Imran Shaik <quic_imrashai at quicinc.com>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 drivers/clk/qcom/clk-alpha-pll.c | 170 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h |   1 +
 2 files changed, 171 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index cec0afea8e446010f0d4140d4ef63121706dde47..7d784db8b7441e886d94ded1d3e3258dda46674c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -2960,3 +2960,173 @@ const struct clk_ops clk_alpha_pll_regera_ops = {
 	.set_rate = clk_zonda_pll_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops);
+
+static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll)
+{
+	int ret;
+	u32 val;
+
+	regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, PLL_UPDATE);
+	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+
+	ret = wait_for_pll_update(pll);
+	if (ret)
+		return ret;
+	/*
+	 * Hardware programming mandates a wait of at least 570ns before polling the LOCK
+	 * detect bit. Have a delay of 1us just to be safe.
+	 */
+	mb();
+	udelay(1);
+
+	return wait_for_pll_enable_lock(pll);
+}
+
+static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	unsigned long freq_hz;
+	const struct pll_vco *curr_vco, *vco;
+	u32 l, alpha_width = pll_alpha_width(pll);
+	u64 a;
+
+	freq_hz =  alpha_pll_round_rate(rate, parent_rate, &l, &a, alpha_width);
+	if (freq_hz != rate) {
+		pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
+		return -EINVAL;
+	}
+
+	curr_vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+	if (!curr_vco) {
+		pr_err("alpha pll: not in a valid vco range\n");
+		return -EINVAL;
+	}
+
+	vco = alpha_pll_find_vco(pll, freq_hz);
+	if (!vco) {
+		pr_err("alpha pll: not in a valid vco range\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Dynamic pll update will not support switching frequencies across
+	 * vco ranges. In those cases fall back to normal alpha set rate.
+	 */
+	if (curr_vco->val != vco->val)
+		return clk_alpha_pll_set_rate(hw, rate, parent_rate);
+
+	a = a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+	/* Ensure that the write above goes through before proceeding. */
+	mb();
+
+	if (clk_hw_is_enabled(hw))
+		return clk_alpha_pll_slew_update(pll);
+
+	return 0;
+}
+
+/*
+ * Slewing plls should be bought up at frequency which is in the middle of the
+ * desired VCO range. So after bringing up the pll at calibration freq, set it
+ * back to desired frequency(that was set by previous clk_set_rate).
+ */
+static int clk_alpha_pll_calibrate(struct clk_hw *hw)
+{
+	unsigned long calibration_freq, freq_hz;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	struct clk_hw *parent;
+	const struct pll_vco *vco;
+	u32 l, alpha_width = pll_alpha_width(pll);
+	int rc;
+	u64 a;
+
+	parent = clk_hw_get_parent(hw);
+	if (!parent) {
+		pr_err("alpha pll: no valid parent found\n");
+		return -EINVAL;
+	}
+
+	vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+	if (!vco) {
+		pr_err("alpha pll: not in a valid vco range\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * As during slewing plls vco_sel won't be allowed to change, vco table
+	 * should have only one entry table, i.e. index = 0, find the
+	 * calibration frequency.
+	 */
+	calibration_freq = (pll->vco_table[0].min_freq + pll->vco_table[0].max_freq) / 2;
+
+	freq_hz = alpha_pll_round_rate(calibration_freq, clk_hw_get_rate(parent),
+					&l, &a, alpha_width);
+	if (freq_hz != calibration_freq) {
+		pr_err("alpha_pll: call clk_set_rate with rounded rates!\n");
+		return -EINVAL;
+	}
+
+	/* Setup PLL for calibration frequency */
+	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_VCO_MASK << PLL_VCO_SHIFT,
+				vco->val << PLL_VCO_SHIFT);
+
+	/* Bringup the pll at calibration frequency */
+	rc = clk_alpha_pll_enable(hw);
+	if (rc) {
+		pr_err("alpha pll calibration failed\n");
+		return rc;
+	}
+
+	/*
+	 * PLL is already running at calibration frequency.
+	 * So slew pll to the previously set frequency.
+	 */
+	freq_hz = alpha_pll_round_rate(clk_hw_get_rate(hw),
+			clk_hw_get_rate(parent), &l, &a, alpha_width);
+
+	pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n",
+		clk_hw_get_name(hw), clk_hw_get_rate(hw), freq_hz);
+
+	/* Setup the PLL for the new frequency */
+	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_ALPHA_EN, PLL_ALPHA_EN);
+
+	return clk_alpha_pll_slew_update(pll);
+}
+
+static int clk_alpha_pll_slew_enable(struct clk_hw *hw)
+{
+	int rc;
+
+	rc = clk_alpha_pll_calibrate(hw);
+	if (rc)
+		return rc;
+
+	return clk_alpha_pll_enable(hw);
+}
+
+const struct clk_ops clk_alpha_pll_slew_ops = {
+	.enable = clk_alpha_pll_slew_enable,
+	.disable = clk_alpha_pll_disable,
+	.recalc_rate = clk_alpha_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+	.set_rate = clk_alpha_pll_slew_set_rate,
+};
+EXPORT_SYMBOL(clk_alpha_pll_slew_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 79aca8525262211ae5295245427d4540abf1e09a..1d19001605eb10fd8ae8041c56d951e928cbbe9f 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -204,6 +204,7 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
 #define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
 
 extern const struct clk_ops clk_alpha_pll_regera_ops;
+extern const struct clk_ops clk_alpha_pll_slew_ops;
 
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 			     const struct alpha_pll_config *config);

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:39 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:39 +0530
Subject: [PATCH v6 02/10] dt-bindings: clock: Add Qualcomm QCS615 Camera
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-2-ebf4b9a5e916@quicinc.com>

Add DT bindings for the Camera clock on QCS615 platforms. Add the
relevant DT include definitions as well.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 .../bindings/clock/qcom,qcs615-camcc.yaml          |  54 ++++++++++
 include/dt-bindings/clock/qcom,qcs615-camcc.h      | 110 +++++++++++++++++++++
 2 files changed, 164 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/qcom,qcs615-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcs615-camcc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ee13c4e97dd4b8c238549b6bc939c4476f8d33b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcs615-camcc.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcs615-camcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Camera Clock & Reset Controller on QCS615
+
+maintainers:
+  - Taniya Das <quic_tdas at quicinc.com>
+
+description: |
+  Qualcomm camera clock control module provides the clocks, resets and power
+  domains on QCS615
+
+  See also: include/dt-bindings/clock/qcom,qcs615-camcc.h
+
+properties:
+  compatible:
+    const: qcom,qcs615-camcc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Board XO source
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+allOf:
+  - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    clock-controller at ad00000 {
+      compatible = "qcom,qcs615-camcc";
+      reg = <0xad00000 0x10000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>;
+
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+...
diff --git a/include/dt-bindings/clock/qcom,qcs615-camcc.h b/include/dt-bindings/clock/qcom,qcs615-camcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..aec57dddc06735a5c6c48a1e93a8c498bdb8726a
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,qcs615-camcc.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_QCS615_H
+#define _DT_BINDINGS_CLK_QCOM_CAM_CC_QCS615_H
+
+/* CAM_CC clocks */
+#define CAM_CC_BPS_AHB_CLK					0
+#define CAM_CC_BPS_AREG_CLK					1
+#define CAM_CC_BPS_AXI_CLK					2
+#define CAM_CC_BPS_CLK						3
+#define CAM_CC_BPS_CLK_SRC					4
+#define CAM_CC_CAMNOC_ATB_CLK					5
+#define CAM_CC_CAMNOC_AXI_CLK					6
+#define CAM_CC_CCI_CLK						7
+#define CAM_CC_CCI_CLK_SRC					8
+#define CAM_CC_CORE_AHB_CLK					9
+#define CAM_CC_CPAS_AHB_CLK					10
+#define CAM_CC_CPHY_RX_CLK_SRC					11
+#define CAM_CC_CSI0PHYTIMER_CLK					12
+#define CAM_CC_CSI0PHYTIMER_CLK_SRC				13
+#define CAM_CC_CSI1PHYTIMER_CLK					14
+#define CAM_CC_CSI1PHYTIMER_CLK_SRC				15
+#define CAM_CC_CSI2PHYTIMER_CLK					16
+#define CAM_CC_CSI2PHYTIMER_CLK_SRC				17
+#define CAM_CC_CSIPHY0_CLK					18
+#define CAM_CC_CSIPHY1_CLK					19
+#define CAM_CC_CSIPHY2_CLK					20
+#define CAM_CC_FAST_AHB_CLK_SRC					21
+#define CAM_CC_ICP_ATB_CLK					22
+#define CAM_CC_ICP_CLK						23
+#define CAM_CC_ICP_CLK_SRC					24
+#define CAM_CC_ICP_CTI_CLK					25
+#define CAM_CC_ICP_TS_CLK					26
+#define CAM_CC_IFE_0_AXI_CLK					27
+#define CAM_CC_IFE_0_CLK					28
+#define CAM_CC_IFE_0_CLK_SRC					29
+#define CAM_CC_IFE_0_CPHY_RX_CLK				30
+#define CAM_CC_IFE_0_CSID_CLK					31
+#define CAM_CC_IFE_0_CSID_CLK_SRC				32
+#define CAM_CC_IFE_0_DSP_CLK					33
+#define CAM_CC_IFE_1_AXI_CLK					34
+#define CAM_CC_IFE_1_CLK					35
+#define CAM_CC_IFE_1_CLK_SRC					36
+#define CAM_CC_IFE_1_CPHY_RX_CLK				37
+#define CAM_CC_IFE_1_CSID_CLK					38
+#define CAM_CC_IFE_1_CSID_CLK_SRC				39
+#define CAM_CC_IFE_1_DSP_CLK					40
+#define CAM_CC_IFE_LITE_CLK					41
+#define CAM_CC_IFE_LITE_CLK_SRC					42
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK				43
+#define CAM_CC_IFE_LITE_CSID_CLK				44
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC				45
+#define CAM_CC_IPE_0_AHB_CLK					46
+#define CAM_CC_IPE_0_AREG_CLK					47
+#define CAM_CC_IPE_0_AXI_CLK					48
+#define CAM_CC_IPE_0_CLK					49
+#define CAM_CC_IPE_0_CLK_SRC					50
+#define CAM_CC_JPEG_CLK						51
+#define CAM_CC_JPEG_CLK_SRC					52
+#define CAM_CC_LRME_CLK						53
+#define CAM_CC_LRME_CLK_SRC					54
+#define CAM_CC_MCLK0_CLK					55
+#define CAM_CC_MCLK0_CLK_SRC					56
+#define CAM_CC_MCLK1_CLK					57
+#define CAM_CC_MCLK1_CLK_SRC					58
+#define CAM_CC_MCLK2_CLK					59
+#define CAM_CC_MCLK2_CLK_SRC					60
+#define CAM_CC_MCLK3_CLK					61
+#define CAM_CC_MCLK3_CLK_SRC					62
+#define CAM_CC_PLL0						63
+#define CAM_CC_PLL1						64
+#define CAM_CC_PLL2						65
+#define CAM_CC_PLL2_OUT_AUX2					66
+#define CAM_CC_PLL3						67
+#define CAM_CC_SLOW_AHB_CLK_SRC					68
+#define CAM_CC_SOC_AHB_CLK					69
+#define CAM_CC_SYS_TMR_CLK					70
+
+/* CAM_CC power domains */
+#define BPS_GDSC						0
+#define IFE_0_GDSC						1
+#define IFE_1_GDSC						2
+#define IPE_0_GDSC						3
+#define TITAN_TOP_GDSC						4
+
+/* CAM_CC resets */
+#define CAM_CC_BPS_BCR						0
+#define CAM_CC_CAMNOC_BCR					1
+#define CAM_CC_CCI_BCR						2
+#define CAM_CC_CPAS_BCR						3
+#define CAM_CC_CSI0PHY_BCR					4
+#define CAM_CC_CSI1PHY_BCR					5
+#define CAM_CC_CSI2PHY_BCR					6
+#define CAM_CC_ICP_BCR						7
+#define CAM_CC_IFE_0_BCR					8
+#define CAM_CC_IFE_1_BCR					9
+#define CAM_CC_IFE_LITE_BCR					10
+#define CAM_CC_IPE_0_BCR					11
+#define CAM_CC_JPEG_BCR						12
+#define CAM_CC_LRME_BCR						13
+#define CAM_CC_MCLK0_BCR					14
+#define CAM_CC_MCLK1_BCR					15
+#define CAM_CC_MCLK2_BCR					16
+#define CAM_CC_MCLK3_BCR					17
+#define CAM_CC_TITAN_TOP_BCR					18
+
+#endif

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:41 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:41 +0530
Subject: [PATCH v6 04/10] dt-bindings: clock: Add Qualcomm QCS615 Display
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>

Add DT bindings for the Display clock on QCS615 platforms. Add the
relevant DT include definitions as well.

Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 .../bindings/clock/qcom,qcs615-dispcc.yaml         | 73 ++++++++++++++++++++++
 include/dt-bindings/clock/qcom,qcs615-dispcc.h     | 52 +++++++++++++++
 2 files changed, 125 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/qcom,qcs615-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcs615-dispcc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..43346ae7e56ef88bc57e450f6f6fe428c649215e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcs615-dispcc.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcs615-dispcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display Clock & Reset Controller on QCS615
+
+maintainers:
+  - Ajit Pandey <quic_ajipan at quicinc.com>
+  - Taniya Das <quic_tdas at quicinc.com>
+
+description: |
+  Qualcomm display clock control module provides the clocks, resets and power
+  domains on QCS615
+
+  See also: include/dt-bindings/clock/qcom,qcs615-dispcc.h
+
+properties:
+  compatible:
+    const: qcom,qcs615-dispcc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: GPLL0 clock source from GCC
+      - description: Byte clock from DSI PHY0
+      - description: Pixel clock from DSI PHY0
+      - description: Pixel clock from DSI PHY1
+      - description: Display port PLL link clock
+      - description: Display port PLL VCO DIV clock
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/clock/qcom,qcs615-gcc.h>
+    clock-controller at af00000 {
+      compatible = "qcom,qcs615-dispcc";
+      reg = <0x0af00000 0x20000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>,
+               <&mdss_dsi0_phy 0>,
+               <&mdss_dsi0_phy 1>,
+               <&mdss_dsi1_phy 0>,
+               <&mdss_dp_phy   0>,
+               <&mdss_dp_vco   0>;
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+...
diff --git a/include/dt-bindings/clock/qcom,qcs615-dispcc.h b/include/dt-bindings/clock/qcom,qcs615-dispcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a29945c5762ce06285a2f4e6a55c13bfaadc5c2
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,qcs615-dispcc.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_QCS615_H
+#define _DT_BINDINGS_CLK_QCOM_DISP_CC_QCS615_H
+
+/* DISP_CC clocks */
+#define DISP_CC_MDSS_AHB_CLK					0
+#define DISP_CC_MDSS_AHB_CLK_SRC				1
+#define DISP_CC_MDSS_BYTE0_CLK					2
+#define DISP_CC_MDSS_BYTE0_CLK_SRC				3
+#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC				4
+#define DISP_CC_MDSS_BYTE0_INTF_CLK				5
+#define DISP_CC_MDSS_DP_AUX_CLK					6
+#define DISP_CC_MDSS_DP_AUX_CLK_SRC				7
+#define DISP_CC_MDSS_DP_CRYPTO_CLK				8
+#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC				9
+#define DISP_CC_MDSS_DP_LINK_CLK				10
+#define DISP_CC_MDSS_DP_LINK_CLK_SRC				11
+#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC			12
+#define DISP_CC_MDSS_DP_LINK_INTF_CLK				13
+#define DISP_CC_MDSS_DP_PIXEL1_CLK				14
+#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC				15
+#define DISP_CC_MDSS_DP_PIXEL_CLK				16
+#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC				17
+#define DISP_CC_MDSS_ESC0_CLK					18
+#define DISP_CC_MDSS_ESC0_CLK_SRC				19
+#define DISP_CC_MDSS_MDP_CLK					20
+#define DISP_CC_MDSS_MDP_CLK_SRC				21
+#define DISP_CC_MDSS_MDP_LUT_CLK				22
+#define DISP_CC_MDSS_NON_GDSC_AHB_CLK				23
+#define DISP_CC_MDSS_PCLK0_CLK					24
+#define DISP_CC_MDSS_PCLK0_CLK_SRC				25
+#define DISP_CC_MDSS_ROT_CLK					26
+#define DISP_CC_MDSS_ROT_CLK_SRC				27
+#define DISP_CC_MDSS_RSCC_AHB_CLK				28
+#define DISP_CC_MDSS_RSCC_VSYNC_CLK				29
+#define DISP_CC_MDSS_VSYNC_CLK					30
+#define DISP_CC_MDSS_VSYNC_CLK_SRC				31
+#define DISP_CC_PLL0						32
+#define DISP_CC_XO_CLK						33
+
+/* DISP_CC power domains */
+#define MDSS_CORE_GDSC						0
+
+/* DISP_CC resets */
+#define DISP_CC_MDSS_CORE_BCR					0
+#define DISP_CC_MDSS_RSCC_BCR					1
+
+#endif

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:40 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:40 +0530
Subject: [PATCH v6 03/10] clk: qcom: camcc-qcs615: Add QCS615 camera clock
 controller driver
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-3-ebf4b9a5e916@quicinc.com>

Add support for the camera clock controller for camera clients to
be able to request for camcc clocks on QCS615 platform.

Reviewed-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 drivers/clk/qcom/Kconfig        |   10 +
 drivers/clk/qcom/Makefile       |    1 +
 drivers/clk/qcom/camcc-qcs615.c | 1591 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1602 insertions(+)

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index d470ed007854c560c476197f9fa52e6406b04ada..4d1a7eb6f2545f6db0c3939f3446d3a49702032c 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -486,6 +486,16 @@ config QCM_DISPCC_2290
 	  Say Y if you want to support display devices and functionality such as
 	  splash screen.
 
+config QCS_CAMCC_615
+	tristate "QCS615 Camera Clock Controller"
+	depends on ARM64 || COMPILE_TEST
+	select QCS_GCC_615
+	help
+	  Support for the camera clock controller on Qualcomm Technologies, Inc
+	  QCS615 devices.
+	  Say Y if you want to support camera devices and functionality such as
+	  capturing pictures.
+
 config QCS_GCC_404
 	tristate "QCS404 Global Clock Controller"
 	help
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 0db2f98bcb3e0b3d2be73a43cbad853c82ec4519..1309137351a911a1b3dcb41e2f1e269a4f53d893 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_QCM_GCC_2290) += gcc-qcm2290.o
 obj-$(CONFIG_QCM_DISPCC_2290) += dispcc-qcm2290.o
+obj-$(CONFIG_QCS_CAMCC_615) += camcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
 obj-$(CONFIG_QCS_GCC_615) += gcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_8300) += gcc-qcs8300.o
diff --git a/drivers/clk/qcom/camcc-qcs615.c b/drivers/clk/qcom/camcc-qcs615.c
new file mode 100644
index 0000000000000000000000000000000000000000..293c538bb754bc2295ec0645c3f6a60ea92204f8
--- /dev/null
+++ b/drivers/clk/qcom/camcc-qcs615.c
@@ -0,0 +1,1591 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,qcs615-camcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+	DT_BI_TCXO,
+};
+
+enum {
+	P_BI_TCXO,
+	P_CAM_CC_PLL0_OUT_AUX,
+	P_CAM_CC_PLL1_OUT_AUX,
+	P_CAM_CC_PLL2_OUT_AUX2,
+	P_CAM_CC_PLL2_OUT_EARLY,
+	P_CAM_CC_PLL3_OUT_MAIN,
+};
+
+static const struct pll_vco brammo_vco[] = {
+	{ 500000000, 1250000000, 0 },
+};
+
+static const struct pll_vco spark_vco[] = {
+	{ 1000000000, 2100000000, 0 },
+	{ 750000000, 1500000000, 1 },
+	{ 500000000, 1000000000, 2 },
+	{ 300000000, 500000000, 3 },
+	{ 550000000, 1100000000, 4 },
+};
+
+/* 600MHz configuration VCO - 2 */
+static const struct alpha_pll_config cam_cc_pll0_config = {
+	.l = 0x1f,
+	.alpha_hi = 0x40,
+	.alpha_en_mask = BIT(24),
+	.vco_val = BIT(21),
+	.vco_mask = GENMASK(21, 20),
+	.aux_output_mask = BIT(1),
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+};
+
+static struct clk_alpha_pll cam_cc_pll0 = {
+	.offset = 0x0,
+	.vco_table = spark_vco,
+	.num_vco = ARRAY_SIZE(spark_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_pll0",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+/* 808MHz configuration VCO - 2 */
+static struct alpha_pll_config cam_cc_pll1_config = {
+	.l = 0x2a,
+	.alpha_hi = 0x15,
+	.alpha = 0x55555555,
+	.alpha_en_mask = BIT(24),
+	.vco_val = BIT(21),
+	.vco_mask = GENMASK(21, 20),
+	.aux_output_mask = BIT(1),
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+};
+
+static struct clk_alpha_pll cam_cc_pll1 = {
+	.offset = 0x1000,
+	.vco_table = spark_vco,
+	.num_vco = ARRAY_SIZE(spark_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_pll1",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+/* 960MHz configuration VCO - 0 */
+static struct alpha_pll_config cam_cc_pll2_config = {
+	.l = 0x32,
+	.vco_val = 0x0,
+	.vco_mask = GENMASK(21, 20),
+	.early_output_mask = BIT(3),
+	.aux2_output_mask = BIT(2),
+	.post_div_val = 0x1 << 8,
+	.post_div_mask = 0x3 << 8,
+	.config_ctl_val = 0x04289,
+	.test_ctl_val = 0x08000000,
+	.test_ctl_mask = 0x08000000,
+};
+
+static struct clk_alpha_pll cam_cc_pll2 = {
+	.offset = 0x2000,
+	.vco_table = brammo_vco,
+	.num_vco = ARRAY_SIZE(brammo_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_pll2",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll2_out_aux2[] = {
+	{ 0x1, 2 },
+	{ }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll2_out_aux2 = {
+	.offset = 0x2000,
+	.post_div_shift = 8,
+	.post_div_table = post_div_table_cam_cc_pll2_out_aux2,
+	.num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_aux2),
+	.width = 2,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO],
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_pll2_out_aux2",
+		.parent_hws = (const struct clk_hw*[]) {
+			&cam_cc_pll2.clkr.hw,
+		},
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+/* 1080MHz configuration - VCO - 0 */
+static struct alpha_pll_config cam_cc_pll3_config = {
+	.l = 0x38,
+	.alpha_hi = 0x40,
+	.alpha_en_mask = BIT(24),
+	.vco_val = 0x0,
+	.vco_mask = GENMASK(21, 20),
+	.main_output_mask = BIT(0),
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+};
+
+static struct clk_alpha_pll cam_cc_pll3 = {
+	.offset = 0x3000,
+	.vco_table = spark_vco,
+	.num_vco = ARRAY_SIZE(spark_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_pll3",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static const struct parent_map cam_cc_parent_map_0[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL1_OUT_AUX, 2 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_0[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll1.clkr.hw },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_1[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL2_OUT_EARLY, 4 },
+	{ P_CAM_CC_PLL3_OUT_MAIN, 5 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_1[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll2.clkr.hw },
+	{ .hw = &cam_cc_pll3.clkr.hw },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_2[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL1_OUT_AUX, 2 },
+	{ P_CAM_CC_PLL2_OUT_EARLY, 4 },
+	{ P_CAM_CC_PLL3_OUT_MAIN, 5 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll1.clkr.hw },
+	{ .hw = &cam_cc_pll2.clkr.hw },
+	{ .hw = &cam_cc_pll3.clkr.hw },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL2_OUT_AUX2, 1 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll2_out_aux2.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL3_OUT_MAIN, 5 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll3.clkr.hw },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_6[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_CAM_CC_PLL1_OUT_AUX, 2 },
+	{ P_CAM_CC_PLL3_OUT_MAIN, 5 },
+	{ P_CAM_CC_PLL0_OUT_AUX, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &cam_cc_pll1.clkr.hw },
+	{ .hw = &cam_cc_pll3.clkr.hw },
+	{ .hw = &cam_cc_pll0.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = {
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+	F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+	F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+	F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0),
+	F(600000000, P_CAM_CC_PLL0_OUT_AUX, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_bps_clk_src = {
+	.cmd_rcgr = 0x6010,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_1,
+	.freq_tbl = ftbl_cam_cc_bps_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_bps_clk_src",
+		.parent_data = cam_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_cci_clk_src[] = {
+	F(37500000, P_CAM_CC_PLL0_OUT_AUX, 16, 0, 0),
+	F(50000000, P_CAM_CC_PLL0_OUT_AUX, 12, 0, 0),
+	F(100000000, P_CAM_CC_PLL0_OUT_AUX, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_cci_clk_src = {
+	.cmd_rcgr = 0xb0d8,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_5,
+	.freq_tbl = ftbl_cam_cc_cci_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_cci_clk_src",
+		.parent_data = cam_cc_parent_data_5,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_5),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+	F(100000000, P_CAM_CC_PLL0_OUT_AUX, 6, 0, 0),
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(269333333, P_CAM_CC_PLL1_OUT_AUX, 3, 0, 0),
+	F(320000000, P_CAM_CC_PLL2_OUT_EARLY, 3, 0, 0),
+	F(384000000, P_CAM_CC_PLL2_OUT_EARLY, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+	.cmd_rcgr = 0x9064,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_2,
+	.freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_cphy_rx_clk_src",
+		.parent_data = cam_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = {
+	F(100000000, P_CAM_CC_PLL0_OUT_AUX, 6, 0, 0),
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(269333333, P_CAM_CC_PLL1_OUT_AUX, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+	.cmd_rcgr = 0x5004,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_0,
+	.freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_csi0phytimer_clk_src",
+		.parent_data = cam_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+	.cmd_rcgr = 0x5028,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_0,
+	.freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_csi1phytimer_clk_src",
+		.parent_data = cam_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = {
+	.cmd_rcgr = 0x504c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_0,
+	.freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_csi2phytimer_clk_src",
+		.parent_data = cam_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = {
+	F(100000000, P_CAM_CC_PLL0_OUT_AUX, 6, 0, 0),
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(300000000, P_CAM_CC_PLL0_OUT_AUX, 2, 0, 0),
+	F(404000000, P_CAM_CC_PLL1_OUT_AUX, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+	.cmd_rcgr = 0x603c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_0,
+	.freq_tbl = ftbl_cam_cc_fast_ahb_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_fast_ahb_clk_src",
+		.parent_data = cam_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = {
+	F(240000000, P_CAM_CC_PLL0_OUT_AUX, 2.5, 0, 0),
+	F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+	F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+	F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+	F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0),
+	F(600000000, P_CAM_CC_PLL0_OUT_AUX, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_icp_clk_src = {
+	.cmd_rcgr = 0xb088,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_1,
+	.freq_tbl = ftbl_cam_cc_icp_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_icp_clk_src",
+		.parent_data = cam_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = {
+	F(240000000, P_CAM_CC_PLL0_OUT_AUX, 2.5, 0, 0),
+	F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+	F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+	F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0),
+	F(600000000, P_CAM_CC_PLL0_OUT_AUX, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+	.cmd_rcgr = 0x9010,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_4,
+	.freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_0_clk_src",
+		.parent_data = cam_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_csid_clk_src[] = {
+	F(100000000, P_CAM_CC_PLL0_OUT_AUX, 6, 0, 0),
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(320000000, P_CAM_CC_PLL2_OUT_EARLY, 3, 0, 0),
+	F(404000000, P_CAM_CC_PLL1_OUT_AUX, 2, 0, 0),
+	F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+	F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = {
+	.cmd_rcgr = 0x903c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_2,
+	.freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_0_csid_clk_src",
+		.parent_data = cam_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+	.cmd_rcgr = 0xa010,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_4,
+	.freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_1_clk_src",
+		.parent_data = cam_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = {
+	.cmd_rcgr = 0xa034,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_2,
+	.freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_1_csid_clk_src",
+		.parent_data = cam_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+	.cmd_rcgr = 0xb004,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_4,
+	.freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_lite_clk_src",
+		.parent_data = cam_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+	.cmd_rcgr = 0xb024,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_2,
+	.freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ife_lite_csid_clk_src",
+		.parent_data = cam_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_ipe_0_clk_src = {
+	.cmd_rcgr = 0x7010,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_1,
+	.freq_tbl = ftbl_cam_cc_icp_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_ipe_0_clk_src",
+		.parent_data = cam_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = {
+	F(66666667, P_CAM_CC_PLL0_OUT_AUX, 9, 0, 0),
+	F(133333333, P_CAM_CC_PLL0_OUT_AUX, 4.5, 0, 0),
+	F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0),
+	F(320000000, P_CAM_CC_PLL2_OUT_EARLY, 3, 0, 0),
+	F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+	F(600000000, P_CAM_CC_PLL0_OUT_AUX, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+	.cmd_rcgr = 0xb04c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_1,
+	.freq_tbl = ftbl_cam_cc_jpeg_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_jpeg_clk_src",
+		.parent_data = cam_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_lrme_clk_src[] = {
+	F(200000000, P_CAM_CC_PLL0_OUT_AUX, 3, 0, 0),
+	F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0),
+	F(300000000, P_CAM_CC_PLL0_OUT_AUX, 2, 0, 0),
+	F(404000000, P_CAM_CC_PLL1_OUT_AUX, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_lrme_clk_src = {
+	.cmd_rcgr = 0xb0f8,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_6,
+	.freq_tbl = ftbl_cam_cc_lrme_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_lrme_clk_src",
+		.parent_data = cam_cc_parent_data_6,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_6),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(24000000, P_CAM_CC_PLL2_OUT_AUX2, 10, 1, 2),
+	F(34285714, P_CAM_CC_PLL2_OUT_AUX2, 14, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+	.cmd_rcgr = 0x4004,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_3,
+	.freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_mclk0_clk_src",
+		.parent_data = cam_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_mclk1_clk_src = {
+	.cmd_rcgr = 0x4024,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_3,
+	.freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_mclk1_clk_src",
+		.parent_data = cam_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_mclk2_clk_src = {
+	.cmd_rcgr = 0x4044,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_3,
+	.freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_mclk2_clk_src",
+		.parent_data = cam_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 cam_cc_mclk3_clk_src = {
+	.cmd_rcgr = 0x4064,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_3,
+	.freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_mclk3_clk_src",
+		.parent_data = cam_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+	F(80000000, P_CAM_CC_PLL0_OUT_AUX, 7.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+	.cmd_rcgr = 0x6058,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = cam_cc_parent_map_0,
+	.freq_tbl = ftbl_cam_cc_slow_ahb_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "cam_cc_slow_ahb_clk_src",
+		.parent_data = cam_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_branch cam_cc_bps_ahb_clk = {
+	.halt_reg = 0x6070,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x6070,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_bps_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_slow_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_bps_areg_clk = {
+	.halt_reg = 0x6054,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x6054,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_bps_areg_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_fast_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_bps_axi_clk = {
+	.halt_reg = 0x6038,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x6038,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_bps_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_bps_clk = {
+	.halt_reg = 0x6028,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x6028,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_bps_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_bps_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_camnoc_axi_clk = {
+	.halt_reg = 0xb124,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb124,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_camnoc_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_cci_clk = {
+	.halt_reg = 0xb0f0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb0f0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_cci_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cci_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_core_ahb_clk = {
+	.halt_reg = 0xb144,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0xb144,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_core_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_slow_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_cpas_ahb_clk = {
+	.halt_reg = 0xb11c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb11c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_cpas_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_slow_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csi0phytimer_clk = {
+	.halt_reg = 0x501c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x501c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csi0phytimer_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_csi0phytimer_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csi1phytimer_clk = {
+	.halt_reg = 0x5040,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x5040,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csi1phytimer_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_csi1phytimer_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csi2phytimer_clk = {
+	.halt_reg = 0x5064,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x5064,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csi2phytimer_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_csi2phytimer_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csiphy0_clk = {
+	.halt_reg = 0x5020,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x5020,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csiphy0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csiphy1_clk = {
+	.halt_reg = 0x5044,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x5044,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csiphy1_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_csiphy2_clk = {
+	.halt_reg = 0x5068,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x5068,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_csiphy2_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_icp_clk = {
+	.halt_reg = 0xb0a0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb0a0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_icp_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_icp_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_0_axi_clk = {
+	.halt_reg = 0x9080,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x9080,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_0_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_0_clk = {
+	.halt_reg = 0x9028,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x9028,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_0_cphy_rx_clk = {
+	.halt_reg = 0x907c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x907c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_0_cphy_rx_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_0_csid_clk = {
+	.halt_reg = 0x9054,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x9054,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_0_csid_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_0_csid_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_0_dsp_clk = {
+	.halt_reg = 0x9038,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x9038,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_0_dsp_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_1_axi_clk = {
+	.halt_reg = 0xa058,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xa058,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_1_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_1_clk = {
+	.halt_reg = 0xa028,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xa028,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_1_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_1_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_1_cphy_rx_clk = {
+	.halt_reg = 0xa054,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xa054,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_1_cphy_rx_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_1_csid_clk = {
+	.halt_reg = 0xa04c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xa04c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_1_csid_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_1_csid_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_1_dsp_clk = {
+	.halt_reg = 0xa030,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xa030,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_1_dsp_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_1_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_lite_clk = {
+	.halt_reg = 0xb01c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb01c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_lite_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_lite_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = {
+	.halt_reg = 0xb044,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb044,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_lite_cphy_rx_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_cphy_rx_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ife_lite_csid_clk = {
+	.halt_reg = 0xb03c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb03c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ife_lite_csid_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ife_lite_csid_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ipe_0_ahb_clk = {
+	.halt_reg = 0x7040,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x7040,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ipe_0_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_slow_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ipe_0_areg_clk = {
+	.halt_reg = 0x703c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x703c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ipe_0_areg_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_fast_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ipe_0_axi_clk = {
+	.halt_reg = 0x7038,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x7038,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ipe_0_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_ipe_0_clk = {
+	.halt_reg = 0x7028,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x7028,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_ipe_0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_ipe_0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_jpeg_clk = {
+	.halt_reg = 0xb064,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb064,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_jpeg_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_jpeg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_lrme_clk = {
+	.halt_reg = 0xb110,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb110,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_lrme_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_lrme_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_mclk0_clk = {
+	.halt_reg = 0x401c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x401c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_mclk0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_mclk0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_mclk1_clk = {
+	.halt_reg = 0x403c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x403c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_mclk1_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_mclk1_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_mclk2_clk = {
+	.halt_reg = 0x405c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x405c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_mclk2_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_mclk2_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_mclk3_clk = {
+	.halt_reg = 0x407c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x407c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_mclk3_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&cam_cc_mclk3_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_soc_ahb_clk = {
+	.halt_reg = 0xb140,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb140,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_soc_ahb_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch cam_cc_sys_tmr_clk = {
+	.halt_reg = 0xb0a8,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb0a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "cam_cc_sys_tmr_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct gdsc titan_top_gdsc = {
+	.gdscr = 0xb134,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "titan_top_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc bps_gdsc = {
+	.gdscr = 0x6004,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "bps_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.parent = &titan_top_gdsc.pd,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc ife_0_gdsc = {
+	.gdscr = 0x9004,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "ife_0_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.parent = &titan_top_gdsc.pd,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc ife_1_gdsc = {
+	.gdscr = 0xa004,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "ife_1_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.parent = &titan_top_gdsc.pd,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc ipe_0_gdsc = {
+	.gdscr = 0x7004,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "ipe_0_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.parent = &titan_top_gdsc.pd,
+	.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *cam_cc_qcs615_clocks[] = {
+	[CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr,
+	[CAM_CC_BPS_AREG_CLK] = &cam_cc_bps_areg_clk.clkr,
+	[CAM_CC_BPS_AXI_CLK] = &cam_cc_bps_axi_clk.clkr,
+	[CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr,
+	[CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr,
+	[CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr,
+	[CAM_CC_CCI_CLK] = &cam_cc_cci_clk.clkr,
+	[CAM_CC_CCI_CLK_SRC] = &cam_cc_cci_clk_src.clkr,
+	[CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+	[CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr,
+	[CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+	[CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr,
+	[CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr,
+	[CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr,
+	[CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr,
+	[CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr,
+	[CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr,
+	[CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
+	[CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
+	[CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
+	[CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
+	[CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr,
+	[CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr,
+	[CAM_CC_IFE_0_AXI_CLK] = &cam_cc_ife_0_axi_clk.clkr,
+	[CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr,
+	[CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr,
+	[CAM_CC_IFE_0_CPHY_RX_CLK] = &cam_cc_ife_0_cphy_rx_clk.clkr,
+	[CAM_CC_IFE_0_CSID_CLK] = &cam_cc_ife_0_csid_clk.clkr,
+	[CAM_CC_IFE_0_CSID_CLK_SRC] = &cam_cc_ife_0_csid_clk_src.clkr,
+	[CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr,
+	[CAM_CC_IFE_1_AXI_CLK] = &cam_cc_ife_1_axi_clk.clkr,
+	[CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr,
+	[CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr,
+	[CAM_CC_IFE_1_CPHY_RX_CLK] = &cam_cc_ife_1_cphy_rx_clk.clkr,
+	[CAM_CC_IFE_1_CSID_CLK] = &cam_cc_ife_1_csid_clk.clkr,
+	[CAM_CC_IFE_1_CSID_CLK_SRC] = &cam_cc_ife_1_csid_clk_src.clkr,
+	[CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr,
+	[CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr,
+	[CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr,
+	[CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr,
+	[CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr,
+	[CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr,
+	[CAM_CC_IPE_0_AHB_CLK] = &cam_cc_ipe_0_ahb_clk.clkr,
+	[CAM_CC_IPE_0_AREG_CLK] = &cam_cc_ipe_0_areg_clk.clkr,
+	[CAM_CC_IPE_0_AXI_CLK] = &cam_cc_ipe_0_axi_clk.clkr,
+	[CAM_CC_IPE_0_CLK] = &cam_cc_ipe_0_clk.clkr,
+	[CAM_CC_IPE_0_CLK_SRC] = &cam_cc_ipe_0_clk_src.clkr,
+	[CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr,
+	[CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr,
+	[CAM_CC_LRME_CLK] = &cam_cc_lrme_clk.clkr,
+	[CAM_CC_LRME_CLK_SRC] = &cam_cc_lrme_clk_src.clkr,
+	[CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr,
+	[CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr,
+	[CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr,
+	[CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr,
+	[CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr,
+	[CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr,
+	[CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr,
+	[CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr,
+	[CAM_CC_PLL0] = &cam_cc_pll0.clkr,
+	[CAM_CC_PLL1] = &cam_cc_pll1.clkr,
+	[CAM_CC_PLL2] = &cam_cc_pll2.clkr,
+	[CAM_CC_PLL2_OUT_AUX2] = &cam_cc_pll2_out_aux2.clkr,
+	[CAM_CC_PLL3] = &cam_cc_pll3.clkr,
+	[CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
+	[CAM_CC_SOC_AHB_CLK] = &cam_cc_soc_ahb_clk.clkr,
+	[CAM_CC_SYS_TMR_CLK] = &cam_cc_sys_tmr_clk.clkr,
+};
+
+static struct gdsc *cam_cc_qcs615_gdscs[] = {
+	[BPS_GDSC] = &bps_gdsc,
+	[IFE_0_GDSC] = &ife_0_gdsc,
+	[IFE_1_GDSC] = &ife_1_gdsc,
+	[IPE_0_GDSC] = &ipe_0_gdsc,
+	[TITAN_TOP_GDSC] = &titan_top_gdsc,
+};
+
+static const struct qcom_reset_map cam_cc_qcs615_resets[] = {
+	[CAM_CC_BPS_BCR] = { 0x6000 },
+	[CAM_CC_CAMNOC_BCR] = { 0xb120 },
+	[CAM_CC_CCI_BCR] = { 0xb0d4 },
+	[CAM_CC_CPAS_BCR] = { 0xb118 },
+	[CAM_CC_CSI0PHY_BCR] = { 0x5000 },
+	[CAM_CC_CSI1PHY_BCR] = { 0x5024 },
+	[CAM_CC_CSI2PHY_BCR] = { 0x5048 },
+	[CAM_CC_ICP_BCR] = { 0xb074 },
+	[CAM_CC_IFE_0_BCR] = { 0x9000 },
+	[CAM_CC_IFE_1_BCR] = { 0xa000 },
+	[CAM_CC_IFE_LITE_BCR] = { 0xb000 },
+	[CAM_CC_IPE_0_BCR] = { 0x7000 },
+	[CAM_CC_JPEG_BCR] = { 0xb048 },
+	[CAM_CC_LRME_BCR] = { 0xb0f4 },
+	[CAM_CC_MCLK0_BCR] = { 0x4000 },
+	[CAM_CC_MCLK1_BCR] = { 0x4020 },
+	[CAM_CC_MCLK2_BCR] = { 0x4040 },
+	[CAM_CC_MCLK3_BCR] = { 0x4060 },
+	[CAM_CC_TITAN_TOP_BCR] = { 0xb130 },
+};
+
+static const struct regmap_config cam_cc_qcs615_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = 0xd004,
+	.fast_io = true,
+};
+
+static const struct qcom_cc_desc cam_cc_qcs615_desc = {
+	.config = &cam_cc_qcs615_regmap_config,
+	.clks = cam_cc_qcs615_clocks,
+	.num_clks = ARRAY_SIZE(cam_cc_qcs615_clocks),
+	.resets = cam_cc_qcs615_resets,
+	.num_resets = ARRAY_SIZE(cam_cc_qcs615_resets),
+	.gdscs = cam_cc_qcs615_gdscs,
+	.num_gdscs = ARRAY_SIZE(cam_cc_qcs615_gdscs),
+};
+
+static const struct of_device_id cam_cc_qcs615_match_table[] = {
+	{ .compatible = "qcom,qcs615-camcc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_qcs615_match_table);
+
+static int cam_cc_qcs615_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &cam_cc_qcs615_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	clk_alpha_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+	clk_alpha_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
+	clk_alpha_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
+	clk_alpha_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+
+	return qcom_cc_really_probe(&pdev->dev, &cam_cc_qcs615_desc, regmap);
+}
+
+static struct platform_driver cam_cc_qcs615_driver = {
+	.probe = cam_cc_qcs615_probe,
+	.driver = {
+		.name = "camcc-qcs615",
+		.of_match_table = cam_cc_qcs615_match_table,
+	},
+};
+
+module_platform_driver(cam_cc_qcs615_driver);
+
+MODULE_DESCRIPTION("QTI CAMCC QCS615 Driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:42 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:42 +0530
Subject: [PATCH v6 05/10] clk: qcom: dispcc-qcs615: Add QCS615 display
 clock controller driver
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-5-ebf4b9a5e916@quicinc.com>

Add support for the display clock controller for display clients to
be able to request for the clocks on QCS615 platform.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 drivers/clk/qcom/Kconfig         |  10 +
 drivers/clk/qcom/Makefile        |   1 +
 drivers/clk/qcom/dispcc-qcs615.c | 786 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 797 insertions(+)

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 4d1a7eb6f2545f6db0c3939f3446d3a49702032c..f6cd8c1cfe5179f5bcd4df6506581336ea22717b 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -486,6 +486,16 @@ config QCM_DISPCC_2290
 	  Say Y if you want to support display devices and functionality such as
 	  splash screen.
 
+config QCS_DISPCC_615
+	tristate "QCS615 Display Clock Controller"
+	depends on ARM64 || COMPILE_TEST
+	select QCS_GCC_615
+	help
+	  Support for the display clock controller on Qualcomm Technologies, Inc
+	  QCS615 devices.
+	  Say Y if you want to support display devices and functionality such as
+	  splash screen.
+
 config QCS_CAMCC_615
 	tristate "QCS615 Camera Clock Controller"
 	depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 1309137351a911a1b3dcb41e2f1e269a4f53d893..5ddf1655cb83a6f27c57a234c175db2e659b9683 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_QCM_GCC_2290) += gcc-qcm2290.o
 obj-$(CONFIG_QCM_DISPCC_2290) += dispcc-qcm2290.o
+obj-$(CONFIG_QCS_DISPCC_615) += dispcc-qcs615.o
 obj-$(CONFIG_QCS_CAMCC_615) += camcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
 obj-$(CONFIG_QCS_GCC_615) += gcc-qcs615.o
diff --git a/drivers/clk/qcom/dispcc-qcs615.c b/drivers/clk/qcom/dispcc-qcs615.c
new file mode 100644
index 0000000000000000000000000000000000000000..d4b4ecb769883423f416c131ba1c53945e5a1320
--- /dev/null
+++ b/drivers/clk/qcom/dispcc-qcs615.c
@@ -0,0 +1,786 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,qcs615-dispcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+	DT_BI_TCXO,
+	DT_GPLL0,
+	DT_DSI0_PHY_PLL_OUT_BYTECLK,
+	DT_DSI0_PHY_PLL_OUT_DSICLK,
+	DT_DSI1_PHY_PLL_OUT_DSICLK,
+	DT_DP_PHY_PLL_LINK_CLK,
+	DT_DP_PHY_PLL_VCO_DIV_CLK,
+};
+
+enum {
+	P_BI_TCXO,
+	P_DISP_CC_PLL0_OUT_MAIN,
+	P_DP_PHY_PLL_LINK_CLK,
+	P_DP_PHY_PLL_VCO_DIV_CLK,
+	P_DSI0_PHY_PLL_OUT_BYTECLK,
+	P_DSI0_PHY_PLL_OUT_DSICLK,
+	P_DSI1_PHY_PLL_OUT_DSICLK,
+	P_GPLL0_OUT_MAIN,
+};
+
+static const struct pll_vco disp_cc_pll_vco[] = {
+	{ 500000000, 1000000000, 2 },
+};
+
+/* 576MHz configuration VCO - 2 */
+static struct alpha_pll_config disp_cc_pll0_config = {
+	.l = 0x1e,
+	.vco_val = BIT(21),
+	.vco_mask = GENMASK(21, 20),
+	.main_output_mask = BIT(0),
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+};
+
+static struct clk_alpha_pll disp_cc_pll0 = {
+	.offset = 0x0,
+	.vco_table = disp_cc_pll_vco,
+	.num_vco = ARRAY_SIZE(disp_cc_pll_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_pll0",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_slew_ops,
+		},
+	},
+};
+
+static const struct parent_map disp_cc_parent_map_0[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_DP_PHY_PLL_LINK_CLK, 1 },
+	{ P_DP_PHY_PLL_VCO_DIV_CLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_0[] = {
+	{ .index = DT_BI_TCXO },
+	{ .index = DT_DP_PHY_PLL_LINK_CLK },
+	{ .index = DT_DP_PHY_PLL_VCO_DIV_CLK },
+};
+
+static const struct parent_map disp_cc_parent_map_1[] = {
+	{ P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_1[] = {
+	{ .index = DT_BI_TCXO },
+};
+
+static const struct parent_map disp_cc_parent_map_2[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_2[] = {
+	{ .index = DT_BI_TCXO },
+	{ .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
+};
+
+static const struct parent_map disp_cc_parent_map_3[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_DISP_CC_PLL0_OUT_MAIN, 1 },
+	{ P_GPLL0_OUT_MAIN, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_3[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &disp_cc_pll0.clkr.hw },
+	{ .index = DT_GPLL0 },
+};
+
+static const struct parent_map disp_cc_parent_map_4[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_GPLL0_OUT_MAIN, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_4[] = {
+	{ .index = DT_BI_TCXO },
+	{ .index = DT_GPLL0 },
+};
+
+static const struct parent_map disp_cc_parent_map_5[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
+	{ P_DSI1_PHY_PLL_OUT_DSICLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_5[] = {
+	{ .index = DT_BI_TCXO },
+	{ .index = DT_DSI0_PHY_PLL_OUT_DSICLK },
+	{ .index = DT_DSI1_PHY_PLL_OUT_DSICLK },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0),
+	F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {
+	.cmd_rcgr = 0x2170,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_4,
+	.freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_ahb_clk_src",
+		.parent_data = disp_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
+	.cmd_rcgr = 0x20c0,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_2,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_byte0_clk_src",
+		.parent_data = disp_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_byte2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_dp_aux1_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_aux_clk_src = {
+	.cmd_rcgr = 0x2158,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_1,
+	.freq_tbl = ftbl_disp_cc_mdss_dp_aux1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "disp_cc_mdss_dp_aux_clk_src",
+		.parent_data = disp_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
+	.cmd_rcgr = 0x2110,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_0,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_dp_crypto_clk_src",
+		.parent_data = disp_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+		.ops = &clk_byte2_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
+	.cmd_rcgr = 0x20f4,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_0,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_dp_link_clk_src",
+		.parent_data = disp_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_byte2_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_pixel1_clk_src = {
+	.cmd_rcgr = 0x2140,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_0,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_dp_pixel1_clk_src",
+		.parent_data = disp_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_dp_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = {
+	.cmd_rcgr = 0x2128,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_0,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_dp_pixel_clk_src",
+		.parent_data = disp_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_dp_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
+	.cmd_rcgr = 0x20dc,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_2,
+	.freq_tbl = ftbl_disp_cc_mdss_dp_aux1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "disp_cc_mdss_esc0_clk_src",
+		.parent_data = disp_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+	F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+	F(307000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
+	.cmd_rcgr = 0x2078,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_3,
+	.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_mdp_clk_src",
+		.parent_data = disp_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
+	.cmd_rcgr = 0x2060,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_5,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_pclk0_clk_src",
+		.parent_data = disp_cc_parent_data_5,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_pixel_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
+	.cmd_rcgr = 0x2090,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_3,
+	.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_rot_clk_src",
+		.parent_data = disp_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
+	.cmd_rcgr = 0x20a8,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = disp_cc_parent_map_1,
+	.freq_tbl = ftbl_disp_cc_mdss_dp_aux1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "disp_cc_mdss_vsync_clk_src",
+		.parent_data = disp_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
+	.reg = 0x20d8,
+	.shift = 0,
+	.width = 2,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_byte0_div_clk_src",
+		.parent_hws = (const struct clk_hw*[]) {
+			&disp_cc_mdss_byte0_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div disp_cc_mdss_dp_link_div_clk_src = {
+	.reg = 0x210c,
+	.shift = 0,
+	.width = 2,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "disp_cc_mdss_dp_link_div_clk_src",
+		.parent_hws = (const struct clk_hw*[]) {
+			&disp_cc_mdss_dp_link_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_branch disp_cc_mdss_ahb_clk = {
+	.halt_reg = 0x2048,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2048,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_byte0_clk = {
+	.halt_reg = 0x2024,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2024,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_byte0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_byte0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
+	.halt_reg = 0x2028,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2028,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_byte0_intf_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_byte0_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_aux_clk = {
+	.halt_reg = 0x2044,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2044,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_aux_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_aux_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_crypto_clk = {
+	.halt_reg = 0x2038,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2038,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_crypto_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_crypto_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_link_clk = {
+	.halt_reg = 0x2030,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2030,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_link_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_link_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_link_intf_clk = {
+	.halt_reg = 0x2034,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2034,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_link_intf_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_link_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_pixel1_clk = {
+	.halt_reg = 0x2040,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2040,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_pixel1_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_pixel1_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_dp_pixel_clk = {
+	.halt_reg = 0x203c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x203c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_dp_pixel_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_dp_pixel_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_esc0_clk = {
+	.halt_reg = 0x202c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x202c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_esc0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_esc0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_mdp_clk = {
+	.halt_reg = 0x2008,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2008,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_mdp_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_mdp_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
+	.halt_reg = 0x2018,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2018,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_mdp_lut_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_mdp_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {
+	.halt_reg = 0x4004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x4004,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_non_gdsc_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_pclk0_clk = {
+	.halt_reg = 0x2004,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2004,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_pclk0_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_pclk0_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_rot_clk = {
+	.halt_reg = 0x2010,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2010,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_rot_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_rot_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {
+	.halt_reg = 0x400c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x400c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_rscc_ahb_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_ahb_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {
+	.halt_reg = 0x4008,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x4008,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_rscc_vsync_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_vsync_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch disp_cc_mdss_vsync_clk = {
+	.halt_reg = 0x2020,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2020,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "disp_cc_mdss_vsync_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&disp_cc_mdss_vsync_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct gdsc mdss_core_gdsc = {
+	.gdscr = 0x3000,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0xf,
+	.pd = {
+		.name = "mdss_core_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = HW_CTRL | POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *disp_cc_qcs615_clocks[] = {
+	[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
+	[DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,
+	[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
+	[DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
+	[DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,
+	[DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
+	[DISP_CC_MDSS_DP_AUX_CLK] = &disp_cc_mdss_dp_aux_clk.clkr,
+	[DISP_CC_MDSS_DP_AUX_CLK_SRC] = &disp_cc_mdss_dp_aux_clk_src.clkr,
+	[DISP_CC_MDSS_DP_CRYPTO_CLK] = &disp_cc_mdss_dp_crypto_clk.clkr,
+	[DISP_CC_MDSS_DP_CRYPTO_CLK_SRC] = &disp_cc_mdss_dp_crypto_clk_src.clkr,
+	[DISP_CC_MDSS_DP_LINK_CLK] = &disp_cc_mdss_dp_link_clk.clkr,
+	[DISP_CC_MDSS_DP_LINK_CLK_SRC] = &disp_cc_mdss_dp_link_clk_src.clkr,
+	[DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC] = &disp_cc_mdss_dp_link_div_clk_src.clkr,
+	[DISP_CC_MDSS_DP_LINK_INTF_CLK] = &disp_cc_mdss_dp_link_intf_clk.clkr,
+	[DISP_CC_MDSS_DP_PIXEL1_CLK] = &disp_cc_mdss_dp_pixel1_clk.clkr,
+	[DISP_CC_MDSS_DP_PIXEL1_CLK_SRC] = &disp_cc_mdss_dp_pixel1_clk_src.clkr,
+	[DISP_CC_MDSS_DP_PIXEL_CLK] = &disp_cc_mdss_dp_pixel_clk.clkr,
+	[DISP_CC_MDSS_DP_PIXEL_CLK_SRC] = &disp_cc_mdss_dp_pixel_clk_src.clkr,
+	[DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
+	[DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
+	[DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
+	[DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
+	[DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
+	[DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
+	[DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
+	[DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
+	[DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
+	[DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
+	[DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,
+	[DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,
+	[DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
+	[DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
+	[DISP_CC_PLL0] = &disp_cc_pll0.clkr,
+};
+
+static struct gdsc *disp_cc_qcs615_gdscs[] = {
+	[MDSS_CORE_GDSC] = &mdss_core_gdsc,
+};
+
+static const struct regmap_config disp_cc_qcs615_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = 0x10000,
+	.fast_io = true,
+};
+
+static const struct qcom_cc_desc disp_cc_qcs615_desc = {
+	.config = &disp_cc_qcs615_regmap_config,
+	.clks = disp_cc_qcs615_clocks,
+	.num_clks = ARRAY_SIZE(disp_cc_qcs615_clocks),
+	.gdscs = disp_cc_qcs615_gdscs,
+	.num_gdscs = ARRAY_SIZE(disp_cc_qcs615_gdscs),
+};
+
+static const struct of_device_id disp_cc_qcs615_match_table[] = {
+	{ .compatible = "qcom,qcs615-dispcc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_qcs615_match_table);
+
+static int disp_cc_qcs615_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &disp_cc_qcs615_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	clk_alpha_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
+
+	/* Keep some clocks always enabled */
+	qcom_branch_set_clk_en(regmap, 0x6054); /* DISP_CC_XO_CLK */
+
+	return qcom_cc_really_probe(&pdev->dev, &disp_cc_qcs615_desc, regmap);
+}
+
+static struct platform_driver disp_cc_qcs615_driver = {
+	.probe = disp_cc_qcs615_probe,
+	.driver = {
+		.name = "dispcc-qcs615",
+		.of_match_table = disp_cc_qcs615_match_table,
+	},
+};
+
+module_platform_driver(disp_cc_qcs615_driver);
+
+MODULE_DESCRIPTION("QTI DISPCC QCS615 Driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:43 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:43 +0530
Subject: [PATCH v6 06/10] dt-bindings: clock: Add Qualcomm QCS615 Graphics
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>

Add DT bindings for the Graphics clock on QCS615 platforms. Add the
relevant DT include definitions as well.

Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 .../bindings/clock/qcom,qcs615-gpucc.yaml          | 66 ++++++++++++++++++++++
 include/dt-bindings/clock/qcom,qcs615-gpucc.h      | 39 +++++++++++++
 2 files changed, 105 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/qcom,qcs615-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcs615-gpucc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b798d2dd0f9cc0f0e742066c5da9a48cdc519243
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcs615-gpucc.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcs615-gpucc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Graphics Clock & Reset Controller on QCS615
+
+maintainers:
+  - Taniya Das <quic_tdas at quicinc.com>
+
+description: |
+  Qualcomm graphics clock control module provides clocks, resets and power
+  domains on QCS615 Qualcomm SoCs.
+
+  See also: include/dt-bindings/clock/qcom,qcs615-gpucc.h
+
+properties:
+  compatible:
+    const: qcom,qcs615-gpucc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: GPLL0 main branch source
+      - description: GPLL0 GPUCC div branch source
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/clock/qcom,qcs615-gcc.h>
+
+    clock-controller at 5090000 {
+      compatible = "qcom,qcs615-gpucc";
+      reg = <0x5090000 0x9000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&gcc    GPLL0>,
+               <&gcc    GCC_GPU_GPLL0_DIV_CLK_SRC>;
+
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+...
diff --git a/include/dt-bindings/clock/qcom,qcs615-gpucc.h b/include/dt-bindings/clock/qcom,qcs615-gpucc.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d8394b90d59074b93a26a9c027407a14b050b27
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,qcs615-gpucc.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_QCS615_H
+#define _DT_BINDINGS_CLK_QCOM_GPU_CC_QCS615_H
+
+/* GPU_CC clocks */
+#define CRC_DIV_PLL0						0
+#define CRC_DIV_PLL1						1
+#define GPU_CC_PLL0						2
+#define GPU_CC_PLL1						3
+#define GPU_CC_CRC_AHB_CLK					4
+#define GPU_CC_CX_GFX3D_CLK					5
+#define GPU_CC_CX_GFX3D_SLV_CLK					6
+#define GPU_CC_CX_GMU_CLK					7
+#define GPU_CC_CX_SNOC_DVM_CLK					8
+#define GPU_CC_CXO_AON_CLK					9
+#define GPU_CC_CXO_CLK						10
+#define GPU_CC_GMU_CLK_SRC					11
+#define GPU_CC_GX_GFX3D_CLK					12
+#define GPU_CC_GX_GFX3D_CLK_SRC					13
+#define GPU_CC_GX_GMU_CLK					14
+#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK				15
+#define GPU_CC_SLEEP_CLK					16
+
+/* GPU_CC power domains */
+#define CX_GDSC							0
+#define GX_GDSC							1
+
+/* GPU_CC resets */
+#define GPU_CC_CX_BCR						0
+#define GPU_CC_GFX3D_AON_BCR					1
+#define GPU_CC_GMU_BCR						2
+#define GPU_CC_GX_BCR						3
+#define GPU_CC_XO_BCR						4
+
+#endif

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:44 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:44 +0530
Subject: [PATCH v6 07/10] clk: qcom: gpucc-qcs615: Add QCS615 graphics
 clock controller driver
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-7-ebf4b9a5e916@quicinc.com>

Add support for the graphics clock controller for graphics clients to
be able to request for the clocks on QCS615 platform.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 drivers/clk/qcom/Kconfig        |   9 +
 drivers/clk/qcom/Makefile       |   1 +
 drivers/clk/qcom/gpucc-qcs615.c | 525 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 535 insertions(+)

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index f6cd8c1cfe5179f5bcd4df6506581336ea22717b..4b74f44ebdbf2f1cec83d311e004ce18091350c8 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -542,6 +542,15 @@ config QCS_GCC_615
 	  Say Y if you want to use multimedia devices or peripheral
 	  devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc.
 
+config QCS_GPUCC_615
+	tristate "QCS615 Graphics clock controller"
+	depends on ARM64 || COMPILE_TEST
+	select QCS_GCC_615
+	help
+	  Support for the graphics clock controller on QCS615 devices.
+	  Say Y if you want to support graphics controller devices and
+	  functionality such as 3D graphics.
+
 config SC_CAMCC_7180
 	tristate "SC7180 Camera Clock Controller"
 	depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 5ddf1655cb83a6f27c57a234c175db2e659b9683..f9497e00d4fef8af05865a235fbb833fe6735528 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_QCS_CAMCC_615) += camcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
 obj-$(CONFIG_QCS_GCC_615) += gcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_8300) += gcc-qcs8300.o
+obj-$(CONFIG_QCS_GPUCC_615) += gpucc-qcs615.o
 obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
 obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
 obj-$(CONFIG_QDU_ECPRICC_1000) += ecpricc-qdu1000.o
diff --git a/drivers/clk/qcom/gpucc-qcs615.c b/drivers/clk/qcom/gpucc-qcs615.c
new file mode 100644
index 0000000000000000000000000000000000000000..a984180fcad3694bc9983582a5246b16ea702dc9
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-qcs615.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,qcs615-gpucc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+	DT_BI_TCXO,
+	DT_GPLL0_OUT_MAIN,
+	DT_GPLL0_OUT_MAIN_DIV,
+};
+
+enum {
+	P_BI_TCXO,
+	P_GPLL0_OUT_MAIN,
+	P_GPLL0_OUT_MAIN_DIV,
+	P_GPU_CC_PLL0_2X_CLK,
+	P_CRC_DIV_PLL0_OUT_AUX2,
+	P_GPU_CC_PLL0_OUT_MAIN,
+	P_GPU_CC_PLL1_OUT_AUX,
+	P_CRC_DIV_PLL1_OUT_AUX2,
+	P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco gpu_cc_pll0_vco[] = {
+	{ 1000000000, 2100000000, 0 },
+};
+
+static struct pll_vco gpu_cc_pll1_vco[] = {
+	{ 500000000,  1000000000, 2 },
+};
+
+/* 1020MHz configuration VCO - 0 */
+static struct alpha_pll_config gpu_cc_pll0_config = {
+	.l = 0x35,
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+	.alpha_hi = 0x20,
+	.alpha = 0x00,
+	.alpha_en_mask = BIT(24),
+	.vco_val = 0x0,
+	.vco_mask = GENMASK(21, 20),
+	.aux2_output_mask = BIT(2),
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+	.offset = 0x0,
+	.vco_table = gpu_cc_pll0_vco,
+	.num_vco = ARRAY_SIZE(gpu_cc_pll0_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_pll0",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_slew_ops,
+		},
+	},
+};
+
+/* 930MHz configuration VCO - 2 */
+static struct alpha_pll_config gpu_cc_pll1_config = {
+	.l = 0x30,
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+	.alpha_hi = 0x70,
+	.alpha = 0x00,
+	.alpha_en_mask = BIT(24),
+	.vco_val = BIT(21),
+	.vco_mask = GENMASK(21, 20),
+	.aux2_output_mask = BIT(2),
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+	.offset = 0x100,
+	.vco_table = gpu_cc_pll1_vco,
+	.num_vco = ARRAY_SIZE(gpu_cc_pll1_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_pll1",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_slew_ops,
+		},
+	}
+};
+
+/* Clock Ramp Controller */
+static struct clk_fixed_factor crc_div_pll0 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "crc_div_pll0",
+			.parent_data = &(const struct clk_parent_data){
+				.hw = &gpu_cc_pll0.clkr.hw,
+			},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+/* Clock Ramp Controller */
+static struct clk_fixed_factor crc_div_pll1 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "crc_div_pll1",
+			.parent_data = &(const struct clk_parent_data){
+				.hw = &gpu_cc_pll1.clkr.hw,
+			},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
+	{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
+	{ P_GPLL0_OUT_MAIN, 5 },
+	{ P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &gpu_cc_pll0.clkr.hw },
+	{ .hw = &gpu_cc_pll1.clkr.hw },
+	{ .index = DT_GPLL0_OUT_MAIN },
+	{ .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_GPU_CC_PLL0_2X_CLK, 1 },
+	{ P_CRC_DIV_PLL0_OUT_AUX2, 2 },
+	{ P_GPU_CC_PLL1_OUT_AUX, 3 },
+	{ P_CRC_DIV_PLL1_OUT_AUX2, 4 },
+	{ P_GPLL0_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &gpu_cc_pll0.clkr.hw },
+	{ .hw = &crc_div_pll0.hw },
+	{ .hw = &gpu_cc_pll1.clkr.hw },
+	{ .hw = &crc_div_pll1.hw },
+	{ .index = DT_GPLL0_OUT_MAIN },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+	.cmd_rcgr = 0x1120,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = gpu_cc_parent_map_0,
+	.freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "gpu_cc_gmu_clk_src",
+		.parent_data = gpu_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = {
+	F(290000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0),
+	F(350000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0),
+	F(435000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0),
+	F(500000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(550000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(650000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(700000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(745000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(845000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	F(895000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
+	.cmd_rcgr = 0x101c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = gpu_cc_parent_map_1,
+	.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "gpu_cc_gx_gfx3d_clk_src",
+		.parent_data = gpu_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+	.halt_reg = 0x107c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x107c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_crc_ahb_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cx_gfx3d_clk = {
+	.halt_reg = 0x10a4,
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x10a4,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_cx_gfx3d_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = {
+	.halt_reg = 0x10a8,
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x10a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_cx_gfx3d_slv_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+	.halt_reg = 0x1098,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x1098,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_cx_gmu_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&gpu_cc_gmu_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
+	.halt_reg = 0x108c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x108c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_cx_snoc_dvm_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cxo_aon_clk = {
+	.halt_reg = 0x1004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_cc_cxo_aon_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+	.halt_reg = 0x109c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x109c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_cxo_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_gx_gfx3d_clk = {
+	.halt_reg = 0x1054,
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x1054,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_gx_gfx3d_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_gx_gmu_clk = {
+	.halt_reg = 0x1064,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x1064,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_gx_gmu_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&gpu_cc_gmu_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+	.halt_reg = 0x5000,
+	.halt_check = BRANCH_VOTED,
+	.clkr = {
+		.enable_reg = 0x5000,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+	.halt_reg = 0x1090,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1090,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "gpu_cc_sleep_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_hw *gpu_cc_qcs615_hws[] = {
+	[CRC_DIV_PLL0] = &crc_div_pll0.hw,
+	[CRC_DIV_PLL1] = &crc_div_pll1.hw,
+};
+
+static struct gdsc cx_gdsc = {
+	.gdscr = 0x106c,
+	.gds_hw_ctrl = 0x1540,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0x8,
+	.pd = {
+		.name = "cx_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc gx_gdsc = {
+	.gdscr = 0x100c,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0x2,
+	.pd = {
+		.name = "gx_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *gpu_cc_qcs615_clocks[] = {
+	[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+	[GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr,
+	[GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr,
+	[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+	[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
+	[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
+	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+	[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
+	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
+	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
+	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+	[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+	[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+	[GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+};
+
+static struct gdsc *gpu_cc_qcs615_gdscs[] = {
+	[CX_GDSC] = &cx_gdsc,
+	[GX_GDSC] = &gx_gdsc,
+};
+
+static const struct qcom_reset_map gpu_cc_qcs615_resets[] = {
+	[GPU_CC_CX_BCR] = { 0x1068 },
+	[GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
+	[GPU_CC_GMU_BCR] = { 0x111c },
+	[GPU_CC_GX_BCR] = { 0x1008 },
+	[GPU_CC_XO_BCR] = { 0x1000 },
+};
+
+static const struct regmap_config gpu_cc_qcs615_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = 0x7008,
+	.fast_io = true,
+};
+
+static const struct qcom_cc_desc gpu_cc_qcs615_desc = {
+	.config = &gpu_cc_qcs615_regmap_config,
+	.clks = gpu_cc_qcs615_clocks,
+	.num_clks = ARRAY_SIZE(gpu_cc_qcs615_clocks),
+	.clk_hws = gpu_cc_qcs615_hws,
+	.num_clk_hws = ARRAY_SIZE(gpu_cc_qcs615_hws),
+	.resets = gpu_cc_qcs615_resets,
+	.num_resets = ARRAY_SIZE(gpu_cc_qcs615_resets),
+	.gdscs = gpu_cc_qcs615_gdscs,
+	.num_gdscs = ARRAY_SIZE(gpu_cc_qcs615_gdscs),
+};
+
+static const struct of_device_id gpu_cc_qcs615_match_table[] = {
+	{ .compatible = "qcom,qcs615-gpucc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_qcs615_match_table);
+
+static void configure_crc(struct regmap *regmap)
+{
+	/* Recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */
+	regmap_update_bits(regmap, gpu_cc_cx_gmu_clk.clkr.enable_reg, 0xff0, 0xff0);
+
+	/*
+	 * After POR, Clock Ramp Controller(CRC) will be in bypass mode.
+	 * Software needs to do the following operation to enable the CRC
+	 * for GFX3D clock and divide the input clock by div by 2.
+	 */
+	regmap_update_bits(regmap, 0x1028, 0x00015011, 0x00015011);
+	regmap_update_bits(regmap, 0x1024, 0x00800000, 0x00800000);
+}
+
+static int gpu_cc_qcs615_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &gpu_cc_qcs615_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	clk_alpha_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+	clk_alpha_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+	/* Keep some clocks always enabled */
+	qcom_branch_set_clk_en(regmap, 0x1078); /* GPU_CC_AHB_CLK */
+
+	configure_crc(regmap);
+
+	return qcom_cc_really_probe(&pdev->dev, &gpu_cc_qcs615_desc, regmap);
+}
+
+static struct platform_driver gpu_cc_qcs615_driver = {
+	.probe = gpu_cc_qcs615_probe,
+	.driver = {
+		.name = "gpucc-qcs615",
+		.of_match_table = gpu_cc_qcs615_match_table,
+	},
+};
+
+module_platform_driver(gpu_cc_qcs615_driver);
+
+MODULE_DESCRIPTION("QTI GPUCC QCS615 Driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:45 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:45 +0530
Subject: [PATCH v6 08/10] dt-bindings: clock: Add Qualcomm QCS615 Video
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-8-ebf4b9a5e916@quicinc.com>

Add DT bindings for the Video clock on QCS615 platforms. Add the
relevant DT include definitions as well.

Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 .../bindings/clock/qcom,qcs615-videocc.yaml        | 64 ++++++++++++++++++++++
 include/dt-bindings/clock/qcom,qcs615-videocc.h    | 30 ++++++++++
 2 files changed, 94 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/qcom,qcs615-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcs615-videocc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3359fb68124341d9673eb860a51d09a60459745d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcs615-videocc.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcs615-videocc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Video Clock & Reset Controller on QCS615
+
+maintainers:
+  - Taniya Das <quic_tdas at quicinc.com>
+
+description: |
+  Qualcomm video clock control module provides clocks, resets and power
+  domains on QCS615 Qualcomm SoCs.
+
+  See also: include/dt-bindings/clock/qcom,qcs615-videocc.h
+
+properties:
+  compatible:
+    const: qcom,qcs615-videocc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: Sleep clock source
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/clock/qcom,qcs615-gcc.h>
+
+    clock-controller at ab00000 {
+      compatible = "qcom,qcs615-videocc";
+      reg = <0xab00000 0x10000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&sleep_clk>;
+
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+...
diff --git a/include/dt-bindings/clock/qcom,qcs615-videocc.h b/include/dt-bindings/clock/qcom,qcs615-videocc.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ca3efb21103d7e0b09ab9c042be761bcbc5960d
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,qcs615-videocc.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_QCS615_H
+#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_QCS615_H
+
+/* VIDEO_CC clocks */
+#define VIDEO_CC_SLEEP_CLK					0
+#define VIDEO_CC_SLEEP_CLK_SRC					1
+#define VIDEO_CC_VCODEC0_AXI_CLK				2
+#define VIDEO_CC_VCODEC0_CORE_CLK				3
+#define VIDEO_CC_VENUS_AHB_CLK					4
+#define VIDEO_CC_VENUS_CLK_SRC					5
+#define VIDEO_CC_VENUS_CTL_AXI_CLK				6
+#define VIDEO_CC_VENUS_CTL_CORE_CLK				7
+#define VIDEO_CC_XO_CLK						8
+#define VIDEO_PLL0						9
+
+/* VIDEO_CC power domains */
+#define VCODEC0_GDSC						0
+#define VENUS_GDSC						1
+
+/* VIDEO_CC resets */
+#define VIDEO_CC_INTERFACE_BCR					0
+#define VIDEO_CC_VCODEC0_BCR					1
+#define VIDEO_CC_VENUS_BCR					2
+
+#endif

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:46 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:46 +0530
Subject: [PATCH v6 09/10] clk: qcom: videocc-qcs615: Add QCS615 video clock
 controller driver
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-9-ebf4b9a5e916@quicinc.com>

Add support for the video clock controller for video clients to
be able to request for the clocks on QCS615 platform.

Reviewed-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 drivers/clk/qcom/Kconfig          |   9 ++
 drivers/clk/qcom/Makefile         |   1 +
 drivers/clk/qcom/videocc-qcs615.c | 332 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 342 insertions(+)

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 4b74f44ebdbf2f1cec83d311e004ce18091350c8..99c8e824abd372a7a661e3fc6233160829308120 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -551,6 +551,15 @@ config QCS_GPUCC_615
 	  Say Y if you want to support graphics controller devices and
 	  functionality such as 3D graphics.
 
+config QCS_VIDEOCC_615
+	tristate "QCS615 Video Clock Controller"
+	depends on ARM64 || COMPILE_TEST
+	select QCS_GCC_615
+	help
+	  Support for the video clock controller on QCS615 devices.
+	  Say Y if you want to support video devices and functionality such as
+	  video encode and decode.
+
 config SC_CAMCC_7180
 	tristate "SC7180 Camera Clock Controller"
 	depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index f9497e00d4fef8af05865a235fbb833fe6735528..14cdf485ad3d3166c9e639900a4745e5a7f12a96 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
 obj-$(CONFIG_QCS_GCC_615) += gcc-qcs615.o
 obj-$(CONFIG_QCS_GCC_8300) += gcc-qcs8300.o
 obj-$(CONFIG_QCS_GPUCC_615) += gpucc-qcs615.o
+obj-$(CONFIG_QCS_VIDEOCC_615) += videocc-qcs615.o
 obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
 obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
 obj-$(CONFIG_QDU_ECPRICC_1000) += ecpricc-qdu1000.o
diff --git a/drivers/clk/qcom/videocc-qcs615.c b/drivers/clk/qcom/videocc-qcs615.c
new file mode 100644
index 0000000000000000000000000000000000000000..14704185d9fa2548ade7dd60f4f9f5d378bb0938
--- /dev/null
+++ b/drivers/clk/qcom/videocc-qcs615.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,qcs615-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+	DT_BI_TCXO,
+	DT_SLEEP_CLK,
+};
+
+enum {
+	P_BI_TCXO,
+	P_SLEEP_CLK,
+	P_VIDEO_PLL0_OUT_AUX,
+	P_VIDEO_PLL0_OUT_AUX2,
+	P_VIDEO_PLL0_OUT_MAIN,
+};
+
+static const struct pll_vco video_cc_pll0_vco[] = {
+	{ 500000000, 1000000000, 2 },
+};
+
+/* 600MHz configuration VCO - 2 */
+static struct alpha_pll_config video_pll0_config = {
+	.l = 0x1f,
+	.alpha_hi = 0x40,
+	.alpha = 0x00,
+	.alpha_en_mask = BIT(24),
+	.vco_val = BIT(21),
+	.vco_mask = GENMASK(21, 20),
+	.main_output_mask = BIT(0),
+	.config_ctl_val = 0x4001055b,
+	.test_ctl_hi_val = 0x1,
+	.test_ctl_hi_mask = 0x1,
+};
+
+static struct clk_alpha_pll video_pll0 = {
+	.offset = 0x42c,
+	.vco_table = video_cc_pll0_vco,
+	.num_vco = ARRAY_SIZE(video_cc_pll0_vco),
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_pll0",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_BI_TCXO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_slew_ops,
+		},
+	},
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+	{ P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0_ao[] = {
+	{ .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+	{ P_BI_TCXO, 0 },
+	{ P_VIDEO_PLL0_OUT_MAIN, 1 },
+	{ P_VIDEO_PLL0_OUT_AUX, 2 },
+	{ P_VIDEO_PLL0_OUT_AUX2, 3 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+	{ .index = DT_BI_TCXO },
+	{ .hw = &video_pll0.clkr.hw },
+	{ .hw = &video_pll0.clkr.hw },
+	{ .hw = &video_pll0.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
+	F(32000, P_SLEEP_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 video_cc_sleep_clk_src = {
+	.cmd_rcgr = 0xaf8,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = video_cc_parent_map_0,
+	.freq_tbl = ftbl_video_cc_sleep_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "video_cc_sleep_clk_src",
+		.parent_data = video_cc_parent_data_0_ao,
+		.num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(133333333, P_VIDEO_PLL0_OUT_MAIN, 4.5, 0, 0),
+	F(240000000, P_VIDEO_PLL0_OUT_MAIN, 2.5, 0, 0),
+	F(300000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
+	F(380000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
+	F(410000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
+	F(460000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 video_cc_venus_clk_src = {
+	.cmd_rcgr = 0x7f0,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = video_cc_parent_map_1,
+	.freq_tbl = ftbl_video_cc_venus_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "video_cc_venus_clk_src",
+		.parent_data = video_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
+static struct clk_branch video_cc_sleep_clk = {
+	.halt_reg = 0xb18,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xb18,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_cc_sleep_clk",
+			.parent_data = &(const struct clk_parent_data){
+				.hw = &video_cc_sleep_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_cc_vcodec0_axi_clk = {
+	.halt_reg = 0x8f0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x8f0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_cc_vcodec0_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_cc_vcodec0_core_clk = {
+	.halt_reg = 0x890,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x890,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_cc_vcodec0_core_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&video_cc_venus_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_cc_venus_ahb_clk = {
+	.halt_reg = 0x9b0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x9b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_cc_venus_ahb_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_cc_venus_ctl_axi_clk = {
+	.halt_reg = 0x8d0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x8d0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_cc_venus_ctl_axi_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_cc_venus_ctl_core_clk = {
+	.halt_reg = 0x850,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x850,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "video_cc_venus_ctl_core_clk",
+			.parent_hws = (const struct clk_hw*[]) {
+				&video_cc_venus_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct gdsc vcodec0_gdsc = {
+	.gdscr = 0x874,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0x6,
+	.pd = {
+		.name = "vcodec0_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR,
+};
+
+static struct gdsc venus_gdsc = {
+	.gdscr = 0x814,
+	.en_rest_wait_val = 0x2,
+	.en_few_wait_val = 0x2,
+	.clk_dis_wait_val = 0x6,
+	.pd = {
+		.name = "venus_gdsc",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *video_cc_qcs615_clocks[] = {
+	[VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,
+	[VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
+	[VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr,
+	[VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr,
+	[VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,
+	[VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr,
+	[VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr,
+	[VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr,
+	[VIDEO_PLL0] = &video_pll0.clkr,
+};
+
+static struct gdsc *video_cc_qcs615_gdscs[] = {
+	[VCODEC0_GDSC] = &vcodec0_gdsc,
+	[VENUS_GDSC] = &venus_gdsc,
+};
+
+static const struct qcom_reset_map video_cc_qcs615_resets[] = {
+	[VIDEO_CC_INTERFACE_BCR] = { 0x8b0 },
+	[VIDEO_CC_VCODEC0_BCR] = { 0x870 },
+	[VIDEO_CC_VENUS_BCR] = { 0x810 },
+};
+
+static const struct regmap_config video_cc_qcs615_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = 0xb94,
+	.fast_io = true,
+};
+
+static const struct qcom_cc_desc video_cc_qcs615_desc = {
+	.config = &video_cc_qcs615_regmap_config,
+	.clks = video_cc_qcs615_clocks,
+	.num_clks = ARRAY_SIZE(video_cc_qcs615_clocks),
+	.resets = video_cc_qcs615_resets,
+	.num_resets = ARRAY_SIZE(video_cc_qcs615_resets),
+	.gdscs = video_cc_qcs615_gdscs,
+	.num_gdscs = ARRAY_SIZE(video_cc_qcs615_gdscs),
+};
+
+static const struct of_device_id video_cc_qcs615_match_table[] = {
+	{ .compatible = "qcom,qcs615-videocc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, video_cc_qcs615_match_table);
+
+static int video_cc_qcs615_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &video_cc_qcs615_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	clk_alpha_pll_configure(&video_pll0, regmap, &video_pll0_config);
+
+	/* Keep some clocks always enabled */
+	qcom_branch_set_clk_en(regmap, 0xab8); /* VIDEO_CC_XO_CLK */
+
+	return qcom_cc_really_probe(&pdev->dev, &video_cc_qcs615_desc, regmap);
+}
+
+static struct platform_driver video_cc_qcs615_driver = {
+	.probe = video_cc_qcs615_probe,
+	.driver = {
+		.name = "videocc-qcs615",
+		.of_match_table = video_cc_qcs615_match_table,
+	},
+};
+
+module_platform_driver(video_cc_qcs615_driver);
+
+MODULE_DESCRIPTION("QTI VIDEOCC QCS615 Driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1



From quic_tdas at quicinc.com  Wed Mar 12 23:59:47 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 12:29:47 +0530
Subject: [PATCH v6 10/10] arm64: defconfig: Enable QCS615 clock controllers
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-qcs615-v5-mm-cc-v6-10-ebf4b9a5e916@quicinc.com>

Enable the QCS615 display, video, camera and graphics clock controller
for their respective functionalities on the Qualcomm QCS615 ride
platform.

Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
---
 arch/arm64/configs/defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index a1cc3814b09b31ee659536a64b7db704153d6fe9..14e5ae9f9562b1b2bec2fe2702dbf6647ca1daa1 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1343,11 +1343,15 @@ CONFIG_MSM_GCC_8998=y
 CONFIG_MSM_MMCC_8998=m
 CONFIG_QCM_GCC_2290=y
 CONFIG_QCM_DISPCC_2290=m
+CONFIG_QCS_DISPCC_615=m
+CONFIG_QCS_CAMCC_615=m
 CONFIG_QCS_GCC_404=y
 CONFIG_QCS_GCC_615=y
 CONFIG_QCS_GCC_8300=y
 CONFIG_SC_CAMCC_7280=m
 CONFIG_SA_CAMCC_8775P=m
+CONFIG_QCS_GPUCC_615=m
+CONFIG_QCS_VIDEOCC_615=m
 CONFIG_QDU_GCC_1000=y
 CONFIG_SC_CAMCC_8280XP=m
 CONFIG_SC_DISPCC_7280=m

-- 
2.48.1



From amadeus at jmu.edu.cn  Thu Mar 13 00:10:31 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 13 Mar 2025 15:10:31 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <7779050.EvYhyI6sBW@phil>
References: <7779050.EvYhyI6sBW@phil>
Message-ID: <20250313071031.1840032-1-amadeus@jmu.edu.cn>

Hi,

> so yes of course the pinctrl needs to be default - simply because
> that's the only pinctrl state mainline supports.

> But judging by the fact that you're discussing working vs. non-working
> below, can you please check if we should drop the patch for 6.15 till
> that is solved?

I suggest dropping this patch first, I will send v2
when this issue is solved.

Thanks,
Chukun

--
2.25.1



From namhyung at kernel.org  Thu Mar 13 00:11:40 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 13 Mar 2025 00:11:40 -0700
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <20250308003209.234114-1-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
Message-ID: <Z9KFLGpenwOP32q3@google.com>

On Fri, Mar 07, 2025 at 04:31:58PM -0800, Ian Rogers wrote:
> This work builds on the clean up of system call tables and removal of
> libaudit by Charlie Jenkins <charlie at rivosinc.com>.
> 
> The system call table in perf trace is used to map system call numbers
> to names and vice versa. Prior to these changes, a single table
> matching the perf binary's build was present. The table would be
> incorrect if tracing say a 32-bit binary from a 64-bit version of
> perf, the names and numbers wouldn't match.
> 
> Change the build so that a single system call file is built and the
> potentially multiple tables are identifiable from the ELF machine type
> of the process being examined. To determine the ELF machine type, the
> executable's maps are searched and the associated DSOs ELF headers are
> read. When this fails and when live, /proc/pid/exe's ELF header is
> read. Fallback to using the perf's binary type when unknown.

Now it works well for me!

  $ sudo ./perf trace a32.out
           ? (         ): a32.out/1267727  ... [continued]: execve())                                           = 0
           ? (         ): a32.out/1267727  ... [continued]: brk())                                              = 0x57f33000
       0.062 ( 0.003 ms): a32.out/1267727 access(filename: 0xf7f170cc, mode: R)                                 = -1 ENOENT (No such file or directory)
       0.070 ( 0.011 ms): a32.out/1267727 openat(dfd: CWD, filename: 0xf7f1347f, flags: RDONLY|CLOEXEC|LARGEFILE) = 3
       0.070 ( 0.023 ms): a32.out/1267727  ... [continued]: close())                                            = 0
       0.103 ( 0.009 ms): a32.out/1267727 openat(dfd: CWD, filename: 0xf7ee43e0, flags: RDONLY|CLOEXEC|LARGEFILE) = 3
       0.113 ( 0.002 ms): a32.out/1267727 read(fd: 3, buf: 0xff854990, count: 512)                              = 512
       0.113 ( 0.049 ms): a32.out/1267727  ... [continued]: close())                                            = 0
       0.113 ( 0.060 ms): a32.out/1267727  ... [continued]: set_tid_address())                                  = 1267727 (a32.out)
       0.175 ( 0.001 ms): a32.out/1267727 set_robust_list(head: 0xf7ee556c, len: 12)                            = 
       0.222 ( 0.005 ms): a32.out/1267727 mprotect(start: 0xf7ebc000, len: 8192, prot: READ)                    = 0
       0.230 ( 0.004 ms): a32.out/1267727 mprotect(start: 0x565b1000, len: 4096, prot: READ)                    = 0
       0.237 ( 0.003 ms): a32.out/1267727 mprotect(start: 0xf7f1f000, len: 8192, prot: READ)                    = 0
       0.258 ( 0.006 ms): a32.out/1267727 munmap(addr: 0xf7ec9000, len: 108298)                                 = 0
       0.258 ( 0.027 ms): a32.out/1267727  ... [continued]: brk())                                              = 0x57f33000
       0.258 ( 0.031 ms): a32.out/1267727  ... [continued]: brk())                                              = 0x57f54000
       0.258 ( 0.033 ms): a32.out/1267727  ... [continued]: brk())                                              = 0x57f55000
       0.296 ( 0.008 ms): a32.out/1267727 openat(dfd: CWD, filename: 0x565b000a)                                = 3
       0.316 ( 0.002 ms): a32.out/1267727 read(fd: 3, buf: 0xff8544a8, count: 4096)                             = 211
       0.319 ( 0.001 ms): a32.out/1267727 read(fd: 3, buf: 0x57f332e0, count: 4096)                             = 0
       0.319 ( 0.005 ms): a32.out/1267727  ... [continued]: close())                                            = 0
       0.319 ( 0.010 ms): a32.out/1267727  ... [continued]: brk())                                              = 0x57f54000
       0.337 (         ): a32.out/1267727 exit_group()                                                          = ?

Thanks,
Namhyung

> 
> Remove some runtime types used by the system call tables and make
> equivalents generated at build time.
> 
> v5: Add byte swap to dso__e_machine and fix comment as suggested by
>     Namhyung.
> 
> v4: Add reading the e_machine from the thread's maps dsos, only read
>     from /proc/pid/exe on failure and when live as requested by
>     Namhyung. Add patches to add dso comments and remove unused
>     dso_data variables that are unused without libunwind.
> 
> v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
>     Bergmann <arnd at arndb.de> on additional optional column and MIPS
>     system call numbering. Rebase past Namhyung's global system call
>     statistics and add comments that they don't yet support an
>     e_machine other than EM_HOST.
> 
> v2: Change the 1 element cache for the last table as suggested by
>     Howard Chu, add Howard's reviewed-by tags.
>     Add a comment and apology to Charlie for not doing better in
>     guiding:
>     https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
>     After discussion on v1 and he agreed this patch series would be
>     the better direction.
> 
> Ian Rogers (11):
>   perf dso: Move libunwind dso_data variables into ifdef
>   perf dso: kernel-doc for enum dso_binary_type
>   perf syscalltbl: Remove syscall_table.h
>   perf trace: Reorganize syscalls
>   perf syscalltbl: Remove struct syscalltbl
>   perf dso: Add support for reading the e_machine type for a dso
>   perf thread: Add support for reading the e_machine type for a thread
>   perf trace beauty: Add syscalltbl.sh generating all system call tables
>   perf syscalltbl: Use lookup table containing multiple architectures
>   perf build: Remove Makefile.syscalls
>   perf syscalltbl: Mask off ABI type for MIPS system calls
> 
>  tools/perf/Makefile.perf                      |  10 +-
>  tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
>  .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/alpha/include/syscall_table.h |   2 -
>  tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
>  .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
>  tools/perf/arch/arc/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
>  .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
>  tools/perf/arch/arm/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
>  .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
>  tools/perf/arch/arm64/include/syscall_table.h |   8 -
>  tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
>  .../csky/entry/syscalls/Makefile.syscalls     |   3 -
>  tools/perf/arch/csky/include/syscall_table.h  |   2 -
>  .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
>  .../entry/syscalls/Makefile.syscalls          |   3 -
>  .../arch/loongarch/include/syscall_table.h    |   2 -
>  tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
>  .../mips/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/mips/include/syscall_table.h  |   2 -
>  tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
>  .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
>  .../perf/arch/parisc/include/syscall_table.h  |   8 -
>  tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
>  .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
>  .../perf/arch/powerpc/include/syscall_table.h |   8 -
>  tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
>  .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
>  tools/perf/arch/riscv/include/syscall_table.h |   8 -
>  tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
>  .../s390/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/s390/include/syscall_table.h  |   2 -
>  tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
>  .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
>  tools/perf/arch/sh/include/syscall_table.h    |   2 -
>  tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
>  .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/sparc/include/syscall_table.h |   8 -
>  tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
>  .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
>  tools/perf/arch/x86/include/syscall_table.h   |   8 -
>  tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
>  .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
>  .../perf/arch/xtensa/include/syscall_table.h  |   2 -
>  tools/perf/builtin-trace.c                    | 290 +++++++++++-------
>  tools/perf/scripts/Makefile.syscalls          |  61 ----
>  tools/perf/scripts/syscalltbl.sh              |  86 ------
>  tools/perf/trace/beauty/syscalltbl.sh         | 274 +++++++++++++++++
>  tools/perf/util/dso.c                         |  88 ++++++
>  tools/perf/util/dso.h                         |  58 ++++
>  tools/perf/util/symbol-elf.c                  |  27 --
>  tools/perf/util/syscalltbl.c                  | 148 ++++-----
>  tools/perf/util/syscalltbl.h                  |  22 +-
>  tools/perf/util/thread.c                      |  80 +++++
>  tools/perf/util/thread.h                      |  14 +-
>  57 files changed, 792 insertions(+), 536 deletions(-)
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
>  delete mode 100644 tools/perf/scripts/Makefile.syscalls
>  delete mode 100755 tools/perf/scripts/syscalltbl.sh
>  create mode 100755 tools/perf/trace/beauty/syscalltbl.sh
> 
> -- 
> 2.49.0.rc0.332.g42c0ae87b1-goog
> 


From ping.bai at nxp.com  Thu Mar 13 00:16:25 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu, 13 Mar 2025 15:16:25 +0800
Subject: [PATCh v3 0/3] Add i.MX943 basic dts support
Message-ID: <20250313071628.729168-1-ping.bai@nxp.com>

i.MX943 is the first SoC of the i.MX94 family, all the SoCs
of this family are pin to pin compatible with only several
peripherals differance.

For i.MX943 device tree support, we split the dtsi into two
part, one for the common dtsi that shared for the i.MX94 family,
and an i.MX943 specific part.

This patchset has dependency on Frank Li's below dt binding changes for i.MX94.
those patch has been reviewed & acked.

https://lore.kernel.org/imx/20250307190816.2971810-1-Frank.Li at nxp.com/T/
https://lore.kernel.org/imx/64d7d06b-337e-498a-87dd-03ae41e6a2de at roeck-us.net/T/
https://lore.kernel.org/lkml/20250306171052.244548-1-Frank.Li at nxp.com/T/
https://lore.kernel.org/imx/20250306171013.243332-1-Frank.Li at nxp.com/T/
https://lore.kernel.org/lkml/20250306170902.241057-1-Frank.Li at nxp.com/T/
https://lore.kernel.org/imx/20250308143214.6dcc41ac at jic23-huawei/T/
https://lore.kernel.org/lkml/20250306170810.239489-1-Frank.Li at nxp.com/T/
https://lore.kernel.org/imx/20250306-immature-ether-d92fb5b8f18a at spud/T/
https://lore.kernel.org/imx/20250307-scion-comprised-03e8ea95abed at spud/T/

Jacky Bai (3):
  dt-bindings: arm: fsl: add i.MX943 EVK board
  arm64: dts: freescale: Add basic dtsi for imx943
  arm64: dts: freescale: Add minimal dts support for imx943 evk

 .../devicetree/bindings/arm/fsl.yaml          |    6 +
 arch/arm64/boot/dts/freescale/Makefile        |    1 +
 arch/arm64/boot/dts/freescale/imx94-clock.h   |  195 ++
 arch/arm64/boot/dts/freescale/imx94-pinfunc.h | 1570 +++++++++++++++++
 arch/arm64/boot/dts/freescale/imx94-power.h   |   41 +
 arch/arm64/boot/dts/freescale/imx94.dtsi      | 1140 ++++++++++++
 arch/arm64/boot/dts/freescale/imx943-evk.dts  |  196 ++
 arch/arm64/boot/dts/freescale/imx943.dtsi     |  148 ++
 8 files changed, 3297 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-clock.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-pinfunc.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94-power.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx94.dtsi
 create mode 100644 arch/arm64/boot/dts/freescale/imx943-evk.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx943.dtsi

-- 
2.34.1



From ping.bai at nxp.com  Thu Mar 13 00:16:26 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu, 13 Mar 2025 15:16:26 +0800
Subject: [PATCh v3 1/3] dt-bindings: arm: fsl: add i.MX943 EVK board
In-Reply-To: <20250313071628.729168-1-ping.bai@nxp.com>
References: <20250313071628.729168-1-ping.bai@nxp.com>
Message-ID: <20250313071628.729168-2-ping.bai@nxp.com>

Add DT compatible string for NXP i.MX943 EVK board.

Signed-off-by: Jacky Bai <ping.bai at nxp.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 - v3 changes:
  - no

 - v2 changes:
  - newly added
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index db781d315698..5b58c23d3c97 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1353,6 +1353,12 @@ properties:
               - fsl,imx93-14x14-evk       # i.MX93 14x14 EVK Board
           - const: fsl,imx93
 
+      - description: i.MX94 based Boards
+        items:
+          - enum:
+              - fsl,imx943-evk            # i.MX943 EVK Board
+          - const: fsl,imx94
+
       - description: i.MX95 based Boards
         items:
           - enum:
-- 
2.34.1



From ping.bai at nxp.com  Thu Mar 13 00:16:28 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Thu, 13 Mar 2025 15:16:28 +0800
Subject: [PATCh v3 3/3] arm64: dts: freescale: Add minimal dts support for imx943 evk
In-Reply-To: <20250313071628.729168-1-ping.bai@nxp.com>
References: <20250313071628.729168-1-ping.bai@nxp.com>
Message-ID: <20250313071628.729168-4-ping.bai@nxp.com>

Add the minimal board dts support for i.MX943 EVK. Only the
console uart, SD & eMMC are enabled for linux basic boot.

Signed-off-by: Jacky Bai <ping.bai at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 - v3 changes:
  - no

 - v2 changes:
  - newly added for board dts
---
 arch/arm64/boot/dts/freescale/Makefile       |   1 +
 arch/arm64/boot/dts/freescale/imx943-evk.dts | 196 +++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx943-evk.dts

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index be6ef4c56fbf..b68067c97994 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -299,6 +299,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx943-evk.dtb
 
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
 
diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts
new file mode 100644
index 000000000000..d4a204eaf5e5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024-2025 NXP
+ */
+
+/dts-v1/;
+
+#include "imx943.dtsi"
+
+/ {
+	compatible = "fsl,imx943-evk", "fsl,imx94";
+	model = "NXP i.MX943 EVK board";
+
+	aliases {
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		serial0 = &lpuart1;
+	};
+
+	chosen {
+		stdout-path = &lpuart1;
+	};
+
+	reg_usdhc2_vmmc: regulator-usdhc2 {
+		compatible = "regulator-fixed";
+		off-on-delay-us = <12000>;
+		pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-name = "VDD_SD2_3V3";
+		gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reserved-memory {
+		ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x80000000 0 0x7f000000>;
+			reusable;
+			size = <0 0x10000000>;
+			linux,cma-default;
+		};
+	};
+
+	memory at 80000000 {
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+		device_type = "memory";
+	};
+};
+
+&lpuart1 {
+	pinctrl-0 = <&pinctrl_uart1>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&scmi_iomuxc {
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			IMX94_PAD_UART1_TXD__LPUART1_TX		0x31e
+			IMX94_PAD_UART1_RXD__LPUART1_RX		0x31e
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x15fe
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x13fe
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x13fe
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x13fe
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x13fe
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x13fe
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x13fe
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x13fe
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x13fe
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x13fe
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x15fe
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			IMX94_PAD_SD1_CLK__USDHC1_CLK		0x158e
+			IMX94_PAD_SD1_CMD__USDHC1_CMD		0x138e
+			IMX94_PAD_SD1_DATA0__USDHC1_DATA0	0x138e
+			IMX94_PAD_SD1_DATA1__USDHC1_DATA1	0x138e
+			IMX94_PAD_SD1_DATA2__USDHC1_DATA2	0x138e
+			IMX94_PAD_SD1_DATA3__USDHC1_DATA3	0x138e
+			IMX94_PAD_SD1_DATA4__USDHC1_DATA4	0x138e
+			IMX94_PAD_SD1_DATA5__USDHC1_DATA5	0x138e
+			IMX94_PAD_SD1_DATA6__USDHC1_DATA6	0x138e
+			IMX94_PAD_SD1_DATA7__USDHC1_DATA7	0x138e
+			IMX94_PAD_SD1_STROBE__USDHC1_STROBE	0x158e
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x15fe
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x13fe
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x13fe
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x13fe
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x13fe
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x13fe
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CD_B__GPIO4_IO20		0x31e
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			IMX94_PAD_SD2_CLK__USDHC2_CLK		0x158e
+			IMX94_PAD_SD2_CMD__USDHC2_CMD		0x138e
+			IMX94_PAD_SD2_DATA0__USDHC2_DATA0	0x138e
+			IMX94_PAD_SD2_DATA1__USDHC2_DATA1	0x138e
+			IMX94_PAD_SD2_DATA2__USDHC2_DATA2	0x138e
+			IMX94_PAD_SD2_DATA3__USDHC2_DATA3	0x138e
+			IMX94_PAD_SD2_VSELECT__USDHC2_VSELECT	0x51e
+		>;
+	};
+
+	pinctrl_reg_usdhc2_vmmc: usdhc2regvmmcgrp {
+		fsl,pins = <
+			IMX94_PAD_SD2_RESET_B__GPIO4_IO27	0x31e
+		>;
+	};
+};
+
+&usdhc1 {
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	pinctrl-3 = <&pinctrl_usdhc1>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	bus-width = <8>;
+	non-removable;
+	no-sdio;
+	no-sd;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	bus-width = <4>;
+	cd-gpios = <&gpio4 20 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_usdhc2_vmmc>;
+	fsl,cd-gpio-wakeup-disable;
+	status = "okay";
+};
+
+&wdog3 {
+	fsl,ext-reset-output;
+	status = "okay";
+};
-- 
2.34.1



From mazziesaccount at gmail.com  Thu Mar 13 00:18:18 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 13 Mar 2025 09:18:18 +0200
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v6 =>
 - No changes
v5 => v6:
 - Adapt to changed fwnode helper names
 - Fix spelling
v4 => v5:
 - Inline iio_adc_device_num_channels()
 - Fix Indenting function parameters
 - Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 79 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 111 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..6cfb001c74b9
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use -1 if no checking
+ *			is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on success. Negative value to indicate
+ *		failure.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan = 0, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 1)
+		return num_chan;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_named_child_node_scoped(dev, child, "channel") {
+		u32 ch;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id != -1 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..56b092a2a4c4
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_named_child_node_count(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/7c50b059/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 13 00:18:49 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 13 Mar 2025 09:18:49 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
help drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-properties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v6 => v7:
 - Fix function name in the commit message
v5 => v6:
 - Commit message typofix
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 38 ++++++++++++------------------
 2 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..bf1db2a3de9b 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,37 +150,27 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
+
 	if (num_channels == 0)
 		return dev_err_probe(dev, -ENODEV, "no channel children\n");
 
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
-
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
 
@@ -271,3 +262,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/3206bc35/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 13 00:19:17 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 13 Mar 2025 09:19:17 +0200
Subject: [PATCH v7 07/10] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <b1d1358a6e8f436fe6a6d5704e63abab660950c8.1741849323.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
v2 =>
 - No changes
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/ac146b9f/attachment.sig>

From Suraj.Gupta2 at amd.com  Thu Mar 13 00:34:55 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Thu, 13 Mar 2025 07:34:55 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <20250312095411.1392379-1-suraj.gupta2@amd.com>
 <20250312095411.1392379-3-suraj.gupta2@amd.com>
 <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
 <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
 <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <BL3PR12MB6571DF7CBA49AF626ABDA382C9D32@BL3PR12MB6571.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Gupta, Suraj
> Sent: Thursday, March 13, 2025 9:01 AM
> To: Andrew Lunn <andrew at lunn.ch>; Russell King (Oracle)
> <linux at armlinux.org.uk>
> Cc: Pandey, Radhey Shyam <radhey.shyam.pandey at amd.com>;
> andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> kuba at kernel.org; pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> netdev at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam,
> Harini <harini.katakam at amd.com>
> Subject: RE: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
>
>
> > -----Original Message-----
> > From: Andrew Lunn <andrew at lunn.ch>
> > Sent: Thursday, March 13, 2025 3:41 AM
> > To: Russell King (Oracle) <linux at armlinux.org.uk>
> > Cc: Gupta, Suraj <Suraj.Gupta2 at amd.com>; Pandey, Radhey Shyam
> > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org;
> > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > <harini.katakam at amd.com>
> > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > 2500base-X only configuration.
> >
> > Caution: This message originated from an External Source. Use proper
> > caution when opening attachments, clicking links, or responding.
> >
> >
> > > This is not an approach that works with the Linux kernel, sorry.
> > >
> > > What we have today is a driver that works for people's hardware -
> > > and we don't know what the capabilities of that hardware is.
> > >
> > > If there's hardware out there today which has XAE_ABILITY_2_5G set,
> > > but defaults to <=1G mode, this will work with the current driver.
> > > However, with your patch applied, it stops working because instead
> > > of the driver indicating MAC_10FD | MAC_100FD | MAC_1000FD, it only
> > > indicates MAC_2500FD. If this happens, it will regress users setups,
> > > and that is something we try not to do.
> > >
> > > Saying "someone else needs to add the code for their FPGA logic"
> > > misses the point - there may not be "someone else" to do that, which
> > > means the only option is to revert your change if it were merged.
> > > That in itself can cause its own user regressions because obviously
> > > stuff that works with this patch stops working.
> > >
> > > This is why we're being cautious, and given your responses, it's not
> > > making Andrew or myself feel that there's a reasonable approach
> > > being taken here.
> > >
> > > >From everything you have said, I am getting the feeling that using
> > > XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is just
> > > wrong. Given that we're talking about an implementation that has
> > > been synthesized at 2.5G and can't operate slower, maybe there's
> > > some way that could be created to specify that in DT?
> > >
> > > e.g. (and I'm sure the DT folk aren't going to like it)...
> > >
> > >       xlnx,axi-ethernet-X.YY.Z-2.5G
> > >
> > > (where X.YY.Z is the version) for implementations that can _only_ do
> > > 2.5G, and leave all other implementations only doing 1G and below.
> > >
> > > Or maybe some DT property. Or something else.
> >
> > Given that AMD has been talking about an FPGA, not silicon, i actually
> > think it would be best to change the IP to explicitly enumerate how it
> > has been synthesised. Make use of some register bits which currently
> > read as 0. Current IP would then remain as 1000BaseX/SGMII,
> > independent of how they have been synthesised. Newer versions of the
> > IP will then set the bits if they have been synthesised as 2) or 3),
> > and the driver can then enable that capability, without breaking
> > current generation systems. Plus there needs to be big fat warning for
> > anybody upgrading to the latest version of the IP for bug fixes to ensure they
> correctly set the synthesis options because it now actually matters.
> >
> >          Andrew
>
> Synthesis options I mentioned in comment might sound confusing, let me clear it up.
> Actual synthesis options (as seen from configuration UI) IP provides are (1) and (2).
> When a user selects (2), IP comes with default 2.5G but also contains 1G
> capabilities which can be enabled and work with by adding switching FPGA logic
> (that makes it (3)).
>
> So, in short  if a user selects (1): It's <=1G only.
> If it selects (2): It's 2.5G only but can be made (3) by FPGA logic changes. So
> whatever existing systems for (3) would be working at default (2).
>
> This is the reason we didn't described (3) in V1 series as that is not provided by IP
> but can be synthesized after FPGA changes.
> Hope I'm able to answer your questions.
>

I understand your concerns that current solution might break if any existing system uses (3).

Russel's suggestion to use DT compatible we can try to send as RFC and check if that is accepted by DT maintainers.
Andrew's suggestion is complete IP solution and will involve IP changes to correct ability register behaviour based on synthesis time selection in a new IP version. But this will need internal discussions and IP rework and might take few months.

Please let me know your thoughts on it.


From ltykernel at gmail.com  Thu Mar 13 00:34:28 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Thu, 13 Mar 2025 15:34:28 +0800
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <5e3e8c30-912c-4fe3-bfac-1ae21242473b@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com> <5e3e8c30-912c-4fe3-bfac-1ae21242473b@linux.microsoft.com>
Message-ID: <CAMvTesAPeLBfYVa5TGx-o6p+0g_Q1bn6s+nZK5i7NK8QGyfbTA@mail.gmail.com>

On Thu, Mar 13, 2025 at 3:45?AM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> On 3/10/2025 6:01 AM, Tianyu Lan wrote:
> > On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
> > <nunodasneves at linux.microsoft.com> wrote:
> >>
> >> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
> >> SynIC event ring buffer for each SINT.
> >>
> >> This will be used by the mshv driver, but must be tracked independently
> >> since the driver module could be removed and re-inserted.
> >>
> >> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> >
> > It's better to expose a function to check the tail instead of exposing
> > hv_synic_eventring_tail directly.
> >
> What is the advantage of using a function for this? We need to both set
> and get the tail.

We may add lock or check to avoid race conditions and this depends on the
user case. This is why I want to see how mshv driver uses it.

>
> > BTW, how does mshv driver use hv_synic_eventring_tail? Which patch
> > uses it in this series?
> >
> This variable stores indices into the synic eventring page (one for each
> SINT, and per-cpu). Each SINT has a ringbuffer of u32 messages. The tail
> index points to the latest one.
>
> This is only used for doorbell messages today. The message in this case is
> a port number which is used to lookup and invoke a callback, which signals
> ioeventfd(s), to notify the VMM of a guest MMIO write.
>
> It is used in patch 10.

I found "extern u8 __percpu **hv_synic_eventring_tail;" in the
drivers/hv/mshv_root.h of patch 10.
I seem to miss the code to use it.

+int hv_call_unmap_stat_page(enum hv_stats_object_type type,
+                           const union hv_stats_object_identity *identity);
+int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
+                                  u64 page_struct_count, u32 host_access,
+                                  u32 flags, u8 acquire);
+
+extern struct mshv_root mshv_root;
+extern enum hv_scheduler_type hv_scheduler_type;
+extern u8 __percpu **hv_synic_eventring_tail;
+
+#endif /* _MSHV_ROOT_H_ */

-- 
Thanks
Tianyu Lan


From krzk at kernel.org  Thu Mar 13 00:49:36 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 08:49:36 +0100
Subject: [PATCH v4 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <CANAwSgTeZ83oqatrsWQxT+4RYwEtEqma=R4XX_iGrP2N=phz9Q@mail.gmail.com>
References: <20250310143450.8276-1-linux.amoon@gmail.com>
 <20250310143450.8276-5-linux.amoon@gmail.com>
 <25fa661b-98e4-468b-bb4d-4a2c95f32b71@kernel.org>
 <CANAwSgTeZ83oqatrsWQxT+4RYwEtEqma=R4XX_iGrP2N=phz9Q@mail.gmail.com>
Message-ID: <43506f83-13d7-46c5-b022-473ac78f0cab@kernel.org>

On 12/03/2025 15:59, Anand Moon wrote:
>>
>>> +          mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
>>> +
>>>  /*
>>>   * TMU treats temperature as a mapped temperature code.
>>>   * The temperature is converted differently depending on the calibration type.
>>> @@ -256,7 +260,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
>>>       unsigned int status;
>>>       int ret = 0;
>>>
>>> -     mutex_lock(&data->lock);
>>> +     guard(mutex)(&data->lock);
>>
>> Which you do not use... Please don't use cleanup.h if you do not know
>> it. It leads to bugs.
>>
> Ok, I will drop this include of cleanup.h.

So the guards as well...

Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar 13 00:53:58 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 08:53:58 +0100
Subject: [PATCH v6 04/10] dt-bindings: clock: Add Qualcomm QCS615 Display
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-noisy-hopping-poodle-c51ccb@krzk-bin>

On Thu, Mar 13, 2025 at 12:29:41PM +0530, Taniya Das wrote:
> Add DT bindings for the Display clock on QCS615 platforms. Add the
> relevant DT include definitions as well.
> 
> Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
> ---
>  .../bindings/clock/qcom,qcs615-dispcc.yaml         | 73 ++++++++++++++++++++++
>  include/dt-bindings/clock/qcom,qcs615-dispcc.h     | 52 +++++++++++++++
>  2 files changed, 125 insertions(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From lumag at kernel.org  Thu Mar 13 01:10:40 2025
From: lumag at kernel.org (Dmitry Baryshkov)
Date: Thu, 13 Mar 2025 10:10:40 +0200
Subject: [PATCH v2 7/7] arm64: dts: rockchip: Enable DP2HDMI for ROCK 5
 ITX
In-Reply-To: <5858d492.44b.1958ceb23dd.Coremail.andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-8-andyshrk@163.com>
 <q3y36jgswj4xa2g3hnptc6kgzphbqfg675r5paa2lwvdseytio@jysj4f2i6osu>
 <5858d492.44b.1958ceb23dd.Coremail.andyshrk@163.com>
Message-ID: <y7ouhmfbls3vcumrgudcvhlahxx7iqliimeq4cljko4xfwgzcb@45iozv6spswb>

On Thu, Mar 13, 2025 at 08:32:55AM +0800, Andy Yan wrote:
> 
> Hi Dmitry,
> 
> At 2025-03-12 20:39:17, "Dmitry Baryshkov" <lumag at kernel.org> wrote:
> >On Wed, Mar 12, 2025 at 06:42:08PM +0800, Andy Yan wrote:
> >> From: Andy Yan <andy.yan at rock-chips.com>
> >> 
> >> The HDMI Port next to Headphone Jack is drived by
> >> DP1 on rk3588 via a dp2hdmi converter.
> >> 
> >> Add related dt nodes to enable it.
> >> 
> >> Note: ROCKCHIP_VOP2_EP_DP1 is defined as 11 in dt-binding header,
> >> but it will trigger a dtc warning like "graph node unit address
> >> error, expected "b"" if we use it directly after endpoint, so we
> >> use "b" instead here.
> >> 
> >> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> >> ---
> >> 
> >> (no changes since v1)
> >> 
> >>  .../boot/dts/rockchip/rk3588-rock-5-itx.dts   | 37 +++++++++++++++++++
> >>  1 file changed, 37 insertions(+)
> >> 
> >> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> >> index 67b886329248..29f10ec9f0c1 100644
> >> --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> >> +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
> >> @@ -57,6 +57,18 @@ analog-sound {
> >>  			  "Headphone", "Headphones";
> >>  	};
> >>  
> >> +	dp-con {
> >> +		compatible = "dp-connector";
> >
> >You've written that it is an HDMI connector. Could you possibly clarify,
> >why is it being registered as a DP connector? Is there any kind of
> >a bridge between the DP controller and the HDMI connector?
> 
> When I was preparing this patch at that time, I also had some doubts. 
> Whether it should be registered as a DP connector or an HDMI connector. 
> There is a DP2HDMI conversion chip between the DP of RK3588 and this hdmi 
> interface, but this conversion chip does not require a software driver. 
> If the current writing is incorrect, I will change it to hdmi-connector in the next version.

Yes. Please add the RA620 chip to simple-bridge.c and simple-bridge.yaml
and use HDMI connector here.

> 
> Thanks
> >
> >> +		label = "DP OUT";
> >> +		type = "full-size";
> >> +
> >> +		port {
> >> +			dp_con_in: endpoint {
> >> +				remote-endpoint = <&dp1_out_con>;
> >> +			};
> >> +		};
> >> +	};
> >> +
> >>  	gpio-leds {
> >>  		compatible = "gpio-leds";
> >>  		pinctrl-names = "default";
> >> @@ -268,6 +280,24 @@ &cpu_l3 {
> >>  	cpu-supply = <&vdd_cpu_lit_s0>;
> >>  };
> >>  
> >> +&dp1 {
> >> +	status = "okay";
> >> +	pinctrl-names = "default";
> >> +	pinctrl-0 = <&dp1m0_pins>;
> >> +};
> >> +
> >> +&dp1_in {
> >> +	dp1_in_vp2: endpoint {
> >> +		remote-endpoint = <&vp2_out_dp1>;
> >> +	};
> >> +};
> >> +
> >> +&dp1_out {
> >> +	dp1_out_con: endpoint {
> >> +		remote-endpoint = <&dp_con_in>;
> >> +	};
> >> +};
> >> +
> >>  &gpu {
> >>  	mali-supply = <&vdd_gpu_s0>;
> >>  	status = "okay";
> >> @@ -1262,3 +1292,10 @@ vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
> >>  		remote-endpoint = <&hdmi1_in_vp1>;
> >>  	};
> >>  };
> >> +
> >> +&vp2 {
> >> +	vp2_out_dp1: endpoint at b {
> >> +		reg = <ROCKCHIP_VOP2_EP_DP1>;
> >> +		remote-endpoint = <&dp1_in_vp2>;
> >> +	};
> >> +};
> >> -- 
> >> 2.34.1
> >> 
> >
> >-- 
> >With best wishes
> >Dmitry

-- 
With best wishes
Dmitry


From linux at armlinux.org.uk  Thu Mar 13 01:12:59 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 13 Mar 2025 08:12:59 +0000
Subject: [PATCH net-next 0/2] net: stmmac: avoid unnecessary work in
 stmmac_release()/stmmac_dvr_remove()
In-Reply-To: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
References: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
Message-ID: <Z9KTixM7_vc_GFe-@shell.armlinux.org.uk>

On Mon, Mar 10, 2025 at 12:31:32PM +0000, Russell King (Oracle) wrote:
> Hi,
> 
> This small series is a subset of a RFC I sent earlier. These two
> patches remove code that is unnecessary and/or wrong in these paths.
> Details in each commit.
> 
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 -----
>  1 file changed, 5 deletions(-)

Hi Jakub,

Why is this series showing in patchwork, but not being subjected to
any nipabot tests?

There's also "net: phylink: expand on .pcs_config() method
documentation" which isn't being subjected to nipabot tests.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From mkl at pengutronix.de  Thu Mar 13 00:12:06 2025
From: mkl at pengutronix.de (Marc Kleine-Budde)
Date: Thu, 13 Mar 2025 08:12:06 +0100
Subject: [PATCH] can: rockchip: bail out if skb cannot be allocated
In-Reply-To: <20250313011506.3132295-1-chenyuan0y@gmail.com>
References: <20250313011506.3132295-1-chenyuan0y@gmail.com>
Message-ID: <20250313-urban-bat-of-cubism-bf5a4a-mkl@pengutronix.de>

Hello Chenyuan Yang,

thanks for your contribution.

On 12.03.2025 20:15:05, Chenyuan Yang wrote:
> Add NULL pointer check in rkcanfd_handle_error_int() to
> bail out if skb cannot be allocated.

If the skb cannot be allocated, the cf is also NULL.

regards,
Marc

> This is similar to the commit f7f0adfe64de
> ("can: rockchip: rkcanfd_handle_rx_fifo_overflow_int(): bail out if skb cannot be allocated").
> 
> Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
> ---
>  drivers/net/can/rockchip/rockchip_canfd-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
> index d9a937ba126c..90395cbdaab9 100644
> --- a/drivers/net/can/rockchip/rockchip_canfd-core.c
> +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
> @@ -551,7 +551,7 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
>  
>  	rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec);
>  
> -	if (!cf)
> +	if (!cf || !skb)
>  		return 0;
>  
>  	err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
> -- 
> 2.34.1
> 
> 

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung N?rnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/d4905a5d/attachment.sig>

From jonas at kwiboo.se  Thu Mar 13 01:22:08 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 13 Mar 2025 09:22:08 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250313071031.1840032-1-amadeus@jmu.edu.cn>
References: <7779050.EvYhyI6sBW@phil>
 <20250313071031.1840032-1-amadeus@jmu.edu.cn>
Message-ID: <60065c0b-4597-4976-b74b-172556c4e156@kwiboo.se>

Hi,

On 2025-03-13 08:10, Chukun Pan wrote:
> Hi,
> 
>> so yes of course the pinctrl needs to be default - simply because
>> that's the only pinctrl state mainline supports.
> 
>> But judging by the fact that you're discussing working vs. non-working
>> below, can you please check if we should drop the patch for 6.15 till
>> that is solved?
> 
> I suggest dropping this patch first, I will send v2
> when this issue is solved.

I noticed that the pwm nodes and saradc node ended up in wrong mmio
address order, so yes please drop the patch (or reorder nodes) ;-)

Chukun, please get back with more details about the issue you are having.
E.g. a stack trace, what board, DT and U-Boot you are using etc.

I have not seen any issue with PWM using the merged patch having
pinctrl-names=default.

Please see my Linux tree [1] and U-Boot tree [2], those are little ahead
of what has been posted on ML, e.g. it has working USB2.0 host, CPU opp,
Hantro VPU, GPU + opp, arm and logic pwm regulators for E20C, ROCK 2A/2F
and Sige1.

Will try to post USB2.0 host and Hantro VPU patches later today.
CPU opp and GPU + opp depend on PWM and I was planning to post that
together with initial thermal support.

[1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250311-rk3528/
[2] https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/commits/rk3528

Regards,
Jonas

> 
> Thanks,
> Chukun
> 
> --
> 2.25.1
> 



From krzk at kernel.org  Thu Mar 13 01:24:12 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 09:24:12 +0100
Subject: [PATCH v6 06/10] dt-bindings: clock: Add Qualcomm QCS615
 Graphics clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-graceful-jackdaw-of-opportunity-62996d@krzk-bin>

On Thu, Mar 13, 2025 at 12:29:43PM +0530, Taniya Das wrote:
 +
> +  '#reset-cells':
> +    const: 1
> +
> +  '#power-domain-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - '#clock-cells'
> +  - '#reset-cells'
> +  - '#power-domain-cells'
> +

I don't get why this binding is different than others and you do not
reference qcom,gcc.yaml? Is it not applicable here? Other gpucc do
reference.


Best regards,
Krzysztof



From krzk at kernel.org  Thu Mar 13 01:25:04 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 09:25:04 +0100
Subject: [PATCH v6 04/10] dt-bindings: clock: Add Qualcomm QCS615 Display
 clock controller
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>
Message-ID: <20250313-mottled-quoll-of-vastness-3f3c6b@krzk-bin>

On Thu, Mar 13, 2025 at 12:29:41PM +0530, Taniya Das wrote:
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - '#clock-cells'
> +  - '#reset-cells'
> +  - '#power-domain-cells'

Also no qcom,gcc.yaml. Why?

Best regards,
Krzysztof



From p.zabel at pengutronix.de  Thu Mar 13 01:39:30 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:39:30 +0100
Subject: [PATCH v8 5/9] dt-bindings: reset: atmel,at91sam9260-reset: add
 sam9x7
In-Reply-To: <cab4ad68-cf3e-4385-8721-837372df2e12@microchip.com>
References: <20241010120142.92057-1-varshini.rajendran@microchip.com>
	 <20241010120419.93043-1-varshini.rajendran@microchip.com>
	 <cab4ad68-cf3e-4385-8721-837372df2e12@microchip.com>
Message-ID: <d6ba31482a0a220bf0c413e5b3c1661498c1485b.camel@pengutronix.de>

On Di, 2025-01-21 at 10:41 +0000, Varshini.Rajendran at microchip.com
wrote:
> Hi,
> 
> A gentle reminder to merge this patch. It has been left out while the 
> other patches in the series have been merged. Please do the needful.

Applied to reset/next, thanks!

[5/9] dt-bindings: reset: atmel,at91sam9260-reset: add sam9x7
      https://git.pengutronix.de/cgit/pza/linux/commit/?id=d41f0d0bbd79

regards
Philipp


From p.zabel at pengutronix.de  Thu Mar 13 01:39:33 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:39:33 +0100
Subject: [PATCH v3 02/12] reset: imx: Add SCU reset driver for i.MX8QXP
 and i.MX8QM
In-Reply-To: <20250210-8qxp_camera-v3-2-324f5105accc@nxp.com>
References: <20250210-8qxp_camera-v3-0-324f5105accc@nxp.com>
	 <20250210-8qxp_camera-v3-2-324f5105accc@nxp.com>
Message-ID: <5849017e43db7ece72463f5c84854386aa7d8e9d.camel@pengutronix.de>

On Mo, 2025-02-10 at 15:59 -0500, Frank Li wrote:
> Add System Controller Firmware(SCU) reset driver for i.MX8QM and i.MX8QXP.
> SCU Manage resets for peripherals such as MIPI CSI. Currently, support two
> reset sources: IMX_SC_R_CSI_0 and IMX_SC_R_CSI_1.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>

Applied to reset/next, thanks!

[01/12] dt-bindings: firmware: imx: add property reset-controller
        https://git.pengutronix.de/cgit/pza/linux/commit/?id=778752759bd0
[02/12] reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM
        https://git.pengutronix.de/cgit/pza/linux/commit/?id=6b64fde5c183

regards
Philipp


From p.zabel at pengutronix.de  Thu Mar 13 01:42:15 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:42:15 +0100
Subject: [PATCH v4] reset: mchp: sparx5: Fix for lan966x
In-Reply-To: <20250227105502.25125-1-horatiu.vultur@microchip.com>
References: <20250227105502.25125-1-horatiu.vultur@microchip.com>
Message-ID: <dbdbc1f6c30cba1e0e1445de09564864dfdb8b58.camel@pengutronix.de>

On Do, 2025-02-27 at 11:55 +0100, Horatiu Vultur wrote:
> With the blamed commit it seems that lan966x doesn't seem to boot
> anymore when the internal CPU is used.
> The reason seems to be the usage of the devm_of_iomap, if we replace
> this with devm_ioremap, this seems to fix the issue as we use the same
> region also for other devices.
> 
> Fixes: 0426a920d6269c ("reset: mchp: sparx5: Map cpu-syscon locally in case of LAN966x")
> Reviewed-by: Herve Codina <herve.codina at bootlin.com>
> Tested-by: Herve Codina <herve.codina at bootlin.com>
> Signed-off-by: Horatiu Vultur <horatiu.vultur at microchip.com>

Applied to reset/fixes, thanks!

[1/1] reset: mchp: sparx5: Fix for lan966x
      https://git.pengutronix.de/cgit/pza/linux/commit/?id=0e2268f88bb2

regards
Philipp


From p.zabel at pengutronix.de  Thu Mar 13 01:43:49 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:43:49 +0100
Subject: [PATCH] dt-bindings: reset: fix double id on rk3562-cru reset
 ids
In-Reply-To: <20250312215923.275625-1-heiko@sntech.de>
References: <20250312215923.275625-1-heiko@sntech.de>
Message-ID: <5824eaa53054cfd9886c6ba745bd5cd8914c26c0.camel@pengutronix.de>

On Mi, 2025-03-12 at 22:59 +0100, Heiko Stuebner wrote:
> Id 173 was accidentially used two times for SRST_P_DDR_HWLP and
> SRST_P_DDR_PHY. This makes both resets ambiguous and also causes build
> warnings like:
> 
> drivers/clk/rockchip/rst-rk3562.c:21:57: error: initialized field overwritten [-Werror=override-init]
>    21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
>       |                                                         ^
> drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
>   266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/clk/rockchip/rst-rk3562.c:21:57: note: (near initialization for 'rk3562_register_offset[173]')
>    21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
>       |                                                         ^
> drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
>   266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> To fix that issue give SRST_P_DDR_PHY a new and now unique id.
> 
> Reported-by: Stephen Boyd <sboyd at kernel.org>
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503121743.0zcDf6nE-lkp at intel.com/
> Fixes: dd113c4fefc8 ("dt-bindings: clock: Add RK3562 cru")
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
> The original patch did go with the reset of the clock controller code
> into the clock tree, so this patch should of course also go that way.

Acked-by: Philipp Zabel <p.zabel at pengutronix.de>

regards
Philipp


From a.fatoum at pengutronix.de  Thu Mar 13 01:33:12 2025
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 13 Mar 2025 09:33:12 +0100
Subject: [BUG] drm/rockchip: vop2: uninitialized variables passed to ilog2 and
 writel
Message-ID: <7ba2e429-113d-4e1c-968b-ffbe65bcf9f4@pengutronix.de>

Hi,

Running clang-analyzer[1] on the VOP2 driver in barebox[2], which was ported
from Linux reports that following variables:

  dclk_out_div, if_pixclk_div, if_dclk_div

defined in rk3588_set_intf_mux() and passed to rk3588_calc_cru_cfg()
are given as uninitialized arguments to ilog2() and in some cases even
used afterwards unconditionally (outside of error cases):

  - dclk_out_div: is not initialized in the HDMI, eDP and DPI cases,
    but is passed to ilog2 unconditionally and the result is written
    into the RK3588_VP_CLK_CTRL register

  - if_pixclk_div: is not initialized in the DP and DPI cases,
    but is passed to ilog2 unconditionally.
    However, the result seems unused.

  - if_clk_div: is not initialized in the DP, MIPI and DPI cases,
    but is passed to ilog2 unconditionally.
    However, the result seems unused.

I checked against Linux v6.14-rc6.

I am not fully sure what a suitable default value would be for the first
case, which is why I report this without a patch.

[1]: https://lore.kernel.org/barebox/20250313080950.3222757-1-a.fatoum at pengutronix.de/T/#m78ca98c01b73ef7fe3316e73ce62cfe4b2c111d0
[2]: https://github.com/barebox/barebox/blob/v2025.02.0/drivers/video/rockchip/rockchip_drm_vop2.c

Thanks,
Ahmad
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



From stanislawa.laskowska at optiora.pl  Thu Mar 13 01:31:07 2025
From: stanislawa.laskowska at optiora.pl (=?UTF-8?Q? Stanis=C5=82awa_Laskowska ?=)
Date: Thu, 13 Mar 2025 08:31:07 GMT
Subject: Kandydat do pracy
Message-ID: <20250313084500-0.1.88.w73z.0.frcbbnjy6p@optiora.pl>

Dzie? dobry,

delegujemy sprawdzone osoby ze Wschodu do pracy w firmach produkcyjnych do prostych prac przy produkcji, na magazynie, przy pakowaniu towaru czy kontroli jako?ci. 

Nasza firma organizuje wszelkie formalno?ci oraz zakwaterowanie, co pozwala zmniejszy? koszty po Pa?stwa stronie.

Czy mog? przedstawi? szczeg??y?


Pozdrawiam
Stanis?awa Laskowska


From nichen at iscas.ac.cn  Thu Mar 13 01:32:59 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Thu, 13 Mar 2025 16:32:59 +0800
Subject: [PATCH] drm/mxsfb: Remove unnecessary NULL check before clk_prepare_enable/clk_disable_unprepare
Message-ID: <20250313083259.2481602-1-nichen@iscas.ac.cn>

clk_prepare_enable() and clk_disable_unprepare() already checked
NULL clock parameter.Remove unneeded NULL check for clk here.

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 7ed2516b6de0..6072de530706 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -152,8 +152,7 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
 {
 	u32 reg;
 
-	if (mxsfb->clk_disp_axi)
-		clk_prepare_enable(mxsfb->clk_disp_axi);
+	clk_prepare_enable(mxsfb->clk_disp_axi);
 	clk_prepare_enable(mxsfb->clk);
 
 	/* Increase number of outstanding requests on all supported IPs */
@@ -222,8 +221,7 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 	writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
 	clk_disable_unprepare(mxsfb->clk);
-	if (mxsfb->clk_disp_axi)
-		clk_disable_unprepare(mxsfb->clk_disp_axi);
+	clk_disable_unprepare(mxsfb->clk_disp_axi);
 }
 
 /*
-- 
2.25.1



From michael at fossekall.de  Thu Mar 13 01:34:50 2025
From: michael at fossekall.de (Michael Klein)
Date: Thu, 13 Mar 2025 09:34:50 +0100
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <4637912.LvFx2qVVIh@jernej-laptop>
References: <20250312193629.85417-1-michael@fossekall.de>
 <20250312193629.85417-2-michael@fossekall.de>
 <4637912.LvFx2qVVIh@jernej-laptop>
Message-ID: <Z9KYqlfUYxRaWnGQ@a98shuttle.de>

Hi,

On Thu, Mar 13, 2025 at 07:07:24AM +0100, Jernej ?krabec wrote:
>Dne sreda, 12. marec 2025 ob 20:36:28 Srednjeevropski standardni ?as je Michael Klein napisal(a):
>> The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
>> Add the corresponding nodes to the device tree.
>>
>> Signed-off-by: Michael Klein <michael at fossekall.de>
>
>This is patch 2/2. Which one is patch 1/2? I got only one.

https://patchwork.kernel.org/project/netdevbpf/patch/20250312193629.85417-1-michael at fossekall.de/

Sorry for any inconvenience in case I messed up the patch submission.

I made two commits for this change and submitted them via `git send-email 
HEAD^^`. The first patch went to netdev at vger.kernel.org, the second 
to linux-arm-kernel at lists.infradead.org, which seems logical. Have I 
done something wrong?

>Best regards,
>Jernej

Michael

>
>> ---
>>  .../boot/dts/allwinner/sun7i-a20-bananapi.dts | 27 +++++++++++++++++++
>>  1 file changed, 27 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
>> index 46ecf9db2324..4976453ed192 100644
>> --- a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
>> +++ b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
>> @@ -48,6 +48,7 @@
>>
>>  #include <dt-bindings/gpio/gpio.h>
>>  #include <dt-bindings/interrupt-controller/irq.h>
>> +#include <dt-bindings/leds/common.h>
>>
>>  / {
>>  	model = "LeMaker Banana Pi";
>> @@ -169,6 +170,32 @@ &ir0 {
>>  &gmac_mdio {
>>  	phy1: ethernet-phy at 1 {
>>  		reg = <1>;
>> +
>> +		leds {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +
>> +			led at 0 {
>> +				reg = <0>;
>> +				color = <LED_COLOR_ID_GREEN>;
>> +				default-state = "keep";
>> +				linux,default-trigger = "netdev";
>> +			};
>> +
>> +			led at 1 {
>> +				reg = <1>;
>> +				color = <LED_COLOR_ID_AMBER>;
>> +				default-state = "keep";
>> +				linux,default-trigger = "netdev";
>> +			};
>> +
>> +			led at 2 {
>> +				reg = <2>;
>> +				color = <LED_COLOR_ID_BLUE>;
>> +				default-state = "keep";
>> +				linux,default-trigger = "netdev";
>> +			};
>> +		};
>>  	};
>>  };
>>
>>
>
>
>
>
>

-- 


From quic_tdas at quicinc.com  Thu Mar 13 01:45:10 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 14:15:10 +0530
Subject: [PATCH v6 04/10] dt-bindings: clock: Add Qualcomm QCS615 Display
 clock controller
In-Reply-To: <20250313-mottled-quoll-of-vastness-3f3c6b@krzk-bin>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-4-ebf4b9a5e916@quicinc.com>
 <20250313-mottled-quoll-of-vastness-3f3c6b@krzk-bin>
Message-ID: <4f3161da-a11b-464f-bf78-45c830b2ea82@quicinc.com>



On 3/13/2025 1:55 PM, Krzysztof Kozlowski wrote:
> On Thu, Mar 13, 2025 at 12:29:41PM +0530, Taniya Das wrote:
>> +required:
>> +  - compatible
>> +  - reg
>> +  - clocks
>> +  - '#clock-cells'
>> +  - '#reset-cells'
>> +  - '#power-domain-cells'
> 
> Also no qcom,gcc.yaml. Why?
> 

Sure, will fix the bindings across and resend the patches.

> Best regards,
> Krzysztof
> 



From p.zabel at pengutronix.de  Thu Mar 13 01:54:37 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:54:37 +0100
Subject: [PATCH v5 0/8] imx8mp: Add support to Run/Stall DSP via reset
 API
In-Reply-To: <Z9BkbVHlx60VFD7q@p14s>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
	 <Z9BkbVHlx60VFD7q@p14s>
Message-ID: <a37615a87d242df0ad858e3926f33e4246bc00ef.camel@pengutronix.de>

Hi Mathieu,

On Di, 2025-03-11 at 10:27 -0600, Mathieu Poirier wrote:
> Thanks for the re-spin.  I will wait for Shawn and Sascha to review their
> respective bits before picking up this set.

Acked-by: Philipp Zabel <p.zabel at pengutronix.de>

for merging the whole series via rproc.

regards
Philipp


From linus.walleij at linaro.org  Thu Mar 13 01:48:42 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 13 Mar 2025 09:48:42 +0100
Subject: [PATCH 1/2] ARM: Require linker to support KEEP within OVERLAY
 for DCE
In-Reply-To: <20250311-arm-fix-vectors-with-linker-dce-v1-1-ec4c382e3bfd@kernel.org>
References: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
 <20250311-arm-fix-vectors-with-linker-dce-v1-1-ec4c382e3bfd@kernel.org>
Message-ID: <CACRpkdY-yxaiG89Co+C2=vyd0i6sh9pP0UGWZh1yUg4jd9jmuQ@mail.gmail.com>

On Tue, Mar 11, 2025 at 8:43?PM Nathan Chancellor <nathan at kernel.org> wrote:

> ld.lld prior to 21.0.0 does not support using the KEEP keyword within an
> overlay description, which may be needed to avoid discarding necessary
> sections within an overlay with '--gc-sections', which can be enabled
> for the kernel via CONFIG_LD_DEAD_CODE_DATA_ELIMINATION.
>
> Disallow CONFIG_LD_DEAD_CODE_DATA_ELIMINATION without support for KEEP
> within OVERLAY and introduce a macro, OVERLAY_KEEP, that can be used to
> conditionally add KEEP when it is properly supported to avoid breaking
> old versions of ld.lld.
>
> Cc: stable at vger.kernel.org
> Link: https://github.com/llvm/llvm-project/commit/381599f1fe973afad3094e55ec99b1620dba7d8c
> Signed-off-by: Nathan Chancellor <nathan at kernel.org>

Very clear and easy to follow.
Reviewed-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From quic_tdas at quicinc.com  Thu Mar 13 01:48:57 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Thu, 13 Mar 2025 14:18:57 +0530
Subject: [PATCH v6 06/10] dt-bindings: clock: Add Qualcomm QCS615 Graphics
 clock controller
In-Reply-To: <20250313-graceful-jackdaw-of-opportunity-62996d@krzk-bin>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>
 <20250313-graceful-jackdaw-of-opportunity-62996d@krzk-bin>
Message-ID: <d1814cd9-5c73-4ac5-a4ed-4cc2aae410d0@quicinc.com>



On 3/13/2025 1:54 PM, Krzysztof Kozlowski wrote:
> On Thu, Mar 13, 2025 at 12:29:43PM +0530, Taniya Das wrote:
>  +
>> +  '#reset-cells':
>> +    const: 1
>> +
>> +  '#power-domain-cells':
>> +    const: 1
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - clocks
>> +  - '#clock-cells'
>> +  - '#reset-cells'
>> +  - '#power-domain-cells'
>> +
> 
> I don't get why this binding is different than others and you do not
> reference qcom,gcc.yaml? Is it not applicable here? Other gpucc do
> reference.
> 

Yes, I will fix them and resend.

> 
> Best regards,
> Krzysztof
> 



From linus.walleij at linaro.org  Thu Mar 13 01:49:06 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 13 Mar 2025 09:49:06 +0100
Subject: [PATCH 2/2] ARM: add KEEP() keyword to ARM_VECTORS
In-Reply-To: <20250311-arm-fix-vectors-with-linker-dce-v1-2-ec4c382e3bfd@kernel.org>
References: <20250311-arm-fix-vectors-with-linker-dce-v1-0-ec4c382e3bfd@kernel.org>
 <20250311-arm-fix-vectors-with-linker-dce-v1-2-ec4c382e3bfd@kernel.org>
Message-ID: <CACRpkdatTYZ9oxSBdjTbs-LjF3ONqcA-9vYojPc-KSGZmoEO=A@mail.gmail.com>

On Tue, Mar 11, 2025 at 8:44?PM Nathan Chancellor <nathan at kernel.org> wrote:

> From: Christian Eggers <ceggers at arri.de>
>
> Without this, the vectors are removed if LD_DEAD_CODE_DATA_ELIMINATION
> is enabled.  At startup, the CPU (silently) hangs in the undefined
> instruction exception as soon as the first timer interrupt arrives.
>
> On my setup, the system also boots fine without the 2nd and 3rd KEEP()
> statements, so I cannot tell whether these are actually required.
>
> Cc: stable at vger.kernel.org
> Fixes: ed0f94102251 ("ARM: 9404/1: arm32: enable HAVE_LD_DEAD_CODE_DATA_ELIMINATION")
> Signed-off-by: Christian Eggers <ceggers at arri.de>
> [nathan: Use OVERLAY_KEEP() to avoid breaking old ld.lld versions]
> Signed-off-by: Nathan Chancellor <nathan at kernel.org>

Reviewed-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From p.zabel at pengutronix.de  Thu Mar 13 01:49:58 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:49:58 +0100
Subject: [PATCH v5 7/8] reset: imx8mp-audiomix: Add support for DSP
 run/stall
In-Reply-To: <20250311085812.1296243-8-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
	 <20250311085812.1296243-8-daniel.baluta@nxp.com>
Message-ID: <d138f147c5df4091418ba8131cdc02c349c7d0ef.camel@pengutronix.de>

On Di, 2025-03-11 at 10:58 +0200, Daniel Baluta wrote:
> We can Run/Stall the DSP via audio block control bits found in audiomix.
> Implement this functionality using the reset controller and use assert
> for Stall and deassert for Run.
> 
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>

regards
Philipp


From p.zabel at pengutronix.de  Thu Mar 13 01:50:01 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 13 Mar 2025 09:50:01 +0100
Subject: [PATCH v5 5/8] reset: imx8mp-audiomix: Prepare the code for
 more reset bits
In-Reply-To: <20250311085812.1296243-6-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
	 <20250311085812.1296243-6-daniel.baluta@nxp.com>
Message-ID: <fa934fa74bf78cccf6a51cef20c294576e425810.camel@pengutronix.de>

On Di, 2025-03-11 at 10:58 +0200, Daniel Baluta wrote:
> Current code supports EARC PHY Software Reset and EARC Software Reset
> but it is not easily extensible to more reset bits.
> 
> So, refactor the code in order to easily allow more reset bits in the
> future.
> 
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>

regards
Philipp


From l.stach at pengutronix.de  Thu Mar 13 01:54:25 2025
From: l.stach at pengutronix.de (Lucas Stach)
Date: Thu, 13 Mar 2025 09:54:25 +0100
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
 hardcodes
In-Reply-To: <Z9GYm/jp9VIhCEeY@lizhi-Precision-Tower-5810>
References: <AS8PR04MB8676E66BD40C37B2A7E390178CD12@AS8PR04MB8676.eurprd04.prod.outlook.com>
	 <20250311155452.GA629749@bhelgaas>
	 <DU2PR04MB8677AC699DF11D847AB768708CD02@DU2PR04MB8677.eurprd04.prod.outlook.com>
	 <fcb5f09f8e4311c7a6ef60aaf3cb4e3f05a8f05e.camel@pengutronix.de>
	 <Z9GYm/jp9VIhCEeY@lizhi-Precision-Tower-5810>
Message-ID: <b425a7c7a7d6508daf23fe7046864a498029a7ac.camel@pengutronix.de>

Am Mittwoch, dem 12.03.2025 um 10:22 -0400 schrieb Frank Li:
> On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> > Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > > -----Original Message-----
> > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > Sent: 2025?3?11? 23:55
> > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > > > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > > > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > hardcodes
> > > > 
> > > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > > -----Original Message-----
> > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > Sent: 2025?3?10? 23:11
> > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > > > bhelgaas at google.com;
> > > > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > hardcodes
> > > > > > 
> > > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > > > 
> > > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > > ---
> > > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > @@ -41,7 +41,6 @@
> > > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > > 8)
> > > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > > > 
> > > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > > platform_device
> > > > > > *pdev)
> > > > > > > ?	struct dw_pcie *pci;
> > > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > > ?	struct device_node *np;
> > > > > > > -	struct resource *dbi_base;
> > > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > > ?	int i, ret, req_cnt;
> > > > > > > ?	u16 val;
> > > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > > platform_device *pdev)
> > > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > > ?	}
> > > > > > > 
> > > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > > 0,
> > > > > > &dbi_base);
> > > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > > -		return PTR_ERR(pci->dbi_base);
> > > > > > 
> > > > > > This makes me wonder.
> > > > > > 
> > > > > > IIUC this means that previously we set controller_id to 1 if the
> > > > > > first item in devicetree "reg" was 0x33c00000, and now we will set
> > > > > > controller_id to 1 if the devicetree "linux,pci-domain" property is 1.
> > > > > > This is good, but I think this new dependency on the correct
> > > > > > "linux,pci-domain" in devicetree should be mentioned in the commit log.
> > > > > > 
> > > > > > My bigger worry is that we no longer set pci->dbi_base at all.  I
> > > > > > see that the only use of pci->dbi_base in pci-imx6.c was to
> > > > > > determine the controller_id, but this is a DWC-based driver, and the
> > > > > > DWC core certainly uses
> > > > > > pci->dbi_base.  Are we sure that none of those DWC core paths are
> > > > > > important to pci-imx6.c?
> > > > > Hi Bjorn:
> > > > > Thanks for your concerns.
> > > > > Don't worry about the assignment of pci->dbi_base.
> > > > > If pci-imx6.c driver doesn't set it. DWC core driver would set it when
> > > > > ?dw_pcie_get_resources() is invoked.
> > > > 
> > > > Great, thanks!  Maybe we can amend the commit log to mention that and
> > > > the new "linux,pci-domain" dependency.
> > > How about the following updates of the commit log?
> > > 
> > > Use the domain number replace the hardcodes to uniquely identify
> > > different controller on i.MX8MQ platforms. No function changes.
> > > Please make sure the " linux,pci-domain" is set for i.MX8MQ correctly, since
> > > ?the controller id is relied on it totally.
> > > 
> > This breaks running a new kernel on an old DT without the
> > linux,pci-domain property, which I'm absolutely no fan of. We tried
> > really hard to keep this way around working in the i.MX world.
> 
> 8MQ already add linux,pci-domain since Jan, 2021
> 
> commit c0b70f05c87f3b09b391027c6f056d0facf331ef
> Author: Peng Fan <peng.fan at nxp.com>
> Date:   Fri Jan 15 11:26:57 2021 +0800
> 
> Only missed is pcie-ep side, which have not been used at all boards dts
> file in upstream.

I wasn't aware of this. 2021 is quite a while ago, so I suspect that
nobody is going to run a new kernel with a DT this old. I retract my
objection.

Regards,
Lucas


From amadeus at jmu.edu.cn  Thu Mar 13 02:01:09 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 13 Mar 2025 17:01:09 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <60065c0b-4597-4976-b74b-172556c4e156@kwiboo.se>
References: <60065c0b-4597-4976-b74b-172556c4e156@kwiboo.se>
Message-ID: <20250313090109.1910997-1-amadeus@jmu.edu.cn>

Hi,

> I have not seen any issue with PWM using the merged patch having
> pinctrl-names=default.
>
> Please see my Linux tree [1] and U-Boot tree [2], those are little ahead
> of what has been posted on ML, e.g. it has working USB2.0 host, CPU opp,
> Hantro VPU, GPU + opp, arm and logic pwm regulators for E20C, ROCK 2A/2F
> and Sige1.
>
> Please see my Linux tree [1] and U-Boot tree [2], those are little ahead
> of what has been posted on ML, e.g. it has working USB2.0 host, CPU opp,
> Hantro VPU, GPU + opp, arm and logic pwm regulators for E20C, ROCK 2A/2F
> and Sige1.
> ...
> [1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250311-rk3528/
> [2] https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/commits/rk3528

I tested your kernel device tree on E20C earlier today and still have
the same issue. But if I replace u-boot with the link [2] you provided,
it will work fine. For reference, I was using v2025.01 plus this series
of patches [3]. So it looks like u-boot does something and kernel doesn't?

[3] https://lore.kernel.org/u-boot/20250123224844.3104592-1-jonas at kwiboo.se/

Thanks,
Chukun

--
2.25.1



From quic_jiegan at quicinc.com  Thu Mar 13 02:00:50 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Thu, 13 Mar 2025 17:00:50 +0800
Subject: [PATCH v1 1/4] coresight: tmc: Introduce new APIs to get the RWP
 offset of ETR buffer
In-Reply-To: <51aab2c3-2219-454f-93b1-5820a9c2ced1@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-2-quic_jiegan@quicinc.com>
 <CAJ9a7Vh7PmBBbvwnUETfCYrTSiXNzeiWpsz+XAGaUWt1Rq1aZw@mail.gmail.com>
 <cef984d5-f369-4892-b970-a71285c2ebc5@quicinc.com>
 <CAJ9a7VhDD3813LtH_5AYyM-2mhCNP+vRmqXn4RWqg5F8FEe-Mg@mail.gmail.com>
 <51aab2c3-2219-454f-93b1-5820a9c2ced1@quicinc.com>
Message-ID: <57b391cc-2ce9-43f5-90b7-51b90cb8abe3@quicinc.com>



On 3/13/2025 9:32 AM, Jie Gan wrote:
> 
> 
> On 3/12/2025 8:54 PM, Mike Leach wrote:
>> Hi Jie,
>>
>> On Wed, 12 Mar 2025 at 01:21, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>>
>>>
>>>
>>> On 3/12/2025 12:49 AM, Mike Leach wrote:
>>>> Hi,
>>>>
>>>> On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan at quicinc.com> wrote:
>>>>>
>>>>> The new functions calculate and return the offset to the write 
>>>>> pointer of
>>>>> the ETR buffer based on whether the memory mode is SG, flat or 
>>>>> reserved.
>>>>> The functions have the RWP offset can directly read data from ETR 
>>>>> buffer,
>>>>> enabling the transfer of data to any required location.
>>>>>
>>>>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>>>>> ---
>>>>> ?? .../hwtracing/coresight/coresight-tmc-etr.c?? | 40 +++++++++++++ 
>>>>> ++++++
>>>>> ?? drivers/hwtracing/coresight/coresight-tmc.h?? |? 1 +
>>>>> ?? 2 files changed, 41 insertions(+)
>>>>>
>>>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/ 
>>>>> drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>>> index eda7cdad0e2b..ec636ab1fd75 100644
>>>>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>>>> @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table 
>>>>> *sg_table)
>>>>> ?? }
>>>>> ?? EXPORT_SYMBOL_GPL(tmc_free_sg_table);
>>>>>
>>>>> +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata 
>>>>> *drvdata)
>>>>> +{
>>>>> +?????? dma_addr_t paddr = drvdata->sysfs_buf->hwaddr;
>>>>> +?????? u64 rwp;
>>>>> +
>>>>
>>>> It is not valid to read RWP if the TMC is running. It must be in the
>>>> stopped or disabled state - see the specifications for TMC /ETR
>>>>
>>>> It is likely that CSUNLOCK / CSLOCK are needed here too,? along with
>>>> the spinlock that protects drvdata
>>>>
>>>> See the code in coresight_tmc_etr.c :-
>>>>
>>>> e.g. in
>>>>
>>>> tmc_update_etr_buffer()
>>>>
>>>> ...
>>>> <take spinlock>
>>>> ...
>>>> CS_UNLOCK(drvdata->base);
>>>> tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and
>>>> flushed to memory - essential to ensure full formatted frame is in
>>>> memory.
>>>> tmc_sync_etr_buf(drvdata); // this function reads rwp.
>>>> CS_LOCK(drvdata->base);
>>>> <release spinlokc>
>>>>
>>>> This type of program flow is common to both sysfs and perf handling of
>>>> TMC buffers.
>>>
>>> Hi Mike,
>>>
>>> I am fully understood your point here.
>>>
>>> The function is designed this way to read the w_offset (which may not be
>>> entirely accurate because the etr buffer is not synced) when the
>>
>> Why would you ever base memory access on a pointer that is not
>> entirely accurate?
>>
>> The manuals for TMC/ETR all state that reads to both RWP and RRP when
>> the ETR is running return unknown values. These cannot be used to
>> access the buffer, or determine how much of the buffer has been used
>> on a running ETR.
>>
>> The ETR specification specifically states that it is not permitted to
>> read the buffer data while the ETR is running, when configured in
>> circular buffer mode - which is the mode used in the TMC-ETR linux
>> drivers.
>>
>> Reading the buffer while ETR is running is only permitted if
>> configured in Software FIFO mode 2 - were the ETR will stop on full
>> and stall incoming trace until some data is read out, signalled to the
>> ETR via the RURP.
>>
> 
> Hi Mike,
> 
> I appreciate for your patient explanation.
> 
> I was wrong about read data from etr_buffer. I must follow the 
> specification to design a method to reading buffer while ETR is running.
> 
> How about the following method:
> 
> 1. The byte-cntr interrupt handler will count the IRQ triggered number 
> when byte-cntr file node is opened.
> 2. Read the buffer after the ETR is stopped(full or stopped manually) 
> according to the counted number. we got the etr->offset, etr->size and 
> the counted number, so we can calculate the offset where starts to read.
> 3. Restart the ETR to keep counting the number of IRQ triggers.
> 
> Thanks,
> Jie

Hi Mike,

Please ignore my previous proposal.

Let me clarify the purpose of the byte-cntr function to ensure there are 
no misunderstandings from my previous comments.

First, we definitely need to change the method for reading the rwp 
pointer from the RWP register.The new method ensures that we obtain a 
valid rwp value.

code snippet:
long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
{
	struct etr_buf *etr_buf;
	unsigned long flags;
	long w_offset;

	if (WARN_ON(!drvdata->sysfs_buf))
		return -EINVAL;

	spin_lock_irqsave(&drvdata->spinlock, flags);
	etr_buf = drvdata->sysfs_buf;
	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
		__tmc_etr_disable_hw(drvdata);

	if (etr_buf->mode == ETR_MODE_ETR_SG)
		w_offset = tmc_sg_get_rwp_offset(drvdata);
	else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV)
		w_offset = tmc_flat_resrv_get_rwp_offset(drvdata);
	else
		w_offset = -EINVAL;

	if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
		__tmc_etr_enable_hw(drvdata);

	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	return w_offset;
}

The rwp offset is necessary because the length of the trace data 
transferred by the byte-cntr depends on the IRQ count number and the rwp 
value is read (as a benchmark to indicate where we start from) when the 
interrupt is enabled.

With a valid rwp value, we can copy trace data from the ETR buffer (The 
trace data in the ETR buffer can still be read using tmc_read) based on 
the IRQ count number.

We need the byte-cntr function to continue transferring data from the 
ETR buffer to userspace (because the etr buffer has some limitations to 
store trace data) while the ETR is running but we just utilize the rwp 
value as a benchmark to copy trace data from etr buffer, is this acceptable?

Please correct me if I am wrong.

Thanks,
Jie

> 
>> I also note that you are reading back the etr_buf data without doing
>> any dma_sync operations that the perf and sysfs methods in the driver
>> do, after stopping the tmc.
>>
>>> byte-cntr devnode is opened, aiming to reduce the length of redundant
>>> trace data. In this case, we cannot ensure the TMC is stopped or
>>> disabled.
>>
>> The specification requires that you must ensure the TMC is stopped to
>> read these registers.
>>
>>
>>> The byte-cntr only requires an offset to know where it can
>>> start before the expected trace data gets into ETR buffer.
>>>
>>> The w_offset is also read when the byte-cntr function stops, which
>>> occurs after the TMC is disabled.
>>>
>>> Maybe this is not a good idea and I should read r_offset upon open?
>>> The primary goal for byte-cntr is trying to transfer useful trace data
>>> from the ETR buffer to the userspace, if we start from r_offset, a large
>>> number of redundant trace data which the user does not expect will be
>>> transferred simultaneously.
>>>
>>>
>>
>> It is difficult to justify adding code to a driver that does not
>> correspond to the specification of the hardware device.
>>
>> Regards
>>
>> Mike
>>
>>>>
>>>>> +?????? rwp = tmc_read_rwp(drvdata);
>>>>> +?????? return rwp - paddr;
>>>>> +}
>>>>> +
>>>>> +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
>>>>> +{
>>>>> +?????? struct etr_buf *etr_buf = drvdata->sysfs_buf;
>>>>> +?????? struct etr_sg_table *etr_table = etr_buf->private;
>>>>> +?????? struct tmc_sg_table *table = etr_table->sg_table;
>>>>> +?????? long w_offset;
>>>>> +?????? u64 rwp;
>>>>> +
>>>>
>>>> Same comments as above
>>>>
>>>>> +?????? rwp = tmc_read_rwp(drvdata);
>>>>> +?????? w_offset = tmc_sg_get_data_page_offset(table, rwp);
>>>>> +
>>>>> +?????? return w_offset;
>>>>> +}
>>>>> +
>>>>> +/*
>>>>> + * Retrieve the offset to the write pointer of the ETR buffer 
>>>>> based on whether
>>>>> + * the memory mode is SG, flat or reserved.
>>>>> + */
>>>>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata)
>>>>> +{
>>>>> +?????? struct etr_buf *etr_buf = drvdata->sysfs_buf;
>>>>> +
>>>>
>>>> As this is an exported function, please ensure that the inputs are
>>>> valid - check the pointers
>>>
>>> Sure, will do.
>>>
>>> Thanks,
>>> Jie
>>>
>>>>
>>>> Code to ensure TMC is flushed and stopped could be inserted here.
>>>>
>>>> Regards
>>>>
>>>> Mike
>>>>
>>>>> +?????? if (etr_buf->mode == ETR_MODE_ETR_SG)
>>>>> +?????????????? return tmc_sg_get_rwp_offset(drvdata);
>>>>> +?????? else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == 
>>>>> ETR_MODE_RESRV)
>>>>> +?????????????? return tmc_flat_resrv_get_rwp_offset(drvdata);
>>>>> +?????? else
>>>>> +?????????????? return -EINVAL;
>>>>> +}
>>>>> +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset);
>>>>> +
>>>>> ?? /*
>>>>> ??? * Alloc pages for the table. Since this will be used by the 
>>>>> device,
>>>>> ??? * allocate the pages closer to the device (i.e, dev_to_node(dev)
>>>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/ 
>>>>> hwtracing/coresight/coresight-tmc.h
>>>>> index b48bc9a01cc0..baedb4dcfc3f 100644
>>>>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>>>>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>>>>> @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void);
>>>>> ?? struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>>>>> ???????????????????????????????????? enum cs_mode mode, void *data);
>>>>> ?? extern const struct attribute_group coresight_etr_group;
>>>>> +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>>>>>
>>>>> ?? #endif
>>>>> -- 
>>>>> 2.34.1
>>>>>
>>>>
>>>>
>>>
>>
>>
>> -- 
>> Mike Leach
>> Principal Engineer, ARM Ltd.
>> Manchester Design Centre. UK
> 
> 



From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 13 02:05:35 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 13 Mar 2025 17:05:35 +0800
Subject: [PATCH v4 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
Message-ID: <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add the device node and related header file for Amlogic
A4 reset controller.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Link: https://lore.kernel.org/r/20240918074211.8067-3-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h | 93 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi    |  8 +++
 2 files changed, 101 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6a4c90bab3cf7cfaa3c98c522bed5e455b73bd3
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __DTS_AMLOGIC_A4_RESET_H
+#define __DTS_AMLOGIC_A4_RESET_H
+
+/* RESET0 */
+/*						0-3 */
+#define RESET_USB				4
+/*						5-6*/
+#define RESET_U2PHY22				7
+#define RESET_USBPHY20				8
+#define RESET_U2PHY21				9
+#define RESET_USB2DRD				10
+#define RESET_U2H				11
+#define RESET_LED_CTRL				12
+/*						13-31 */
+
+/* RESET1 */
+#define RESET_AUDIO				32
+#define RESET_AUDIO_VAD				33
+/*						34*/
+#define RESET_DDR_APB				35
+#define RESET_DDR				36
+#define RESET_VOUT_VENC				37
+#define RESET_VOUT				38
+/*						39-47 */
+#define RESET_ETHERNET				48
+/*						49-63 */
+
+/* RESET2 */
+#define RESET_DEVICE_MMC_ARB			64
+#define RESET_IRCTRL				65
+/*						66*/
+#define RESET_TS_PLL				67
+/*						68-72*/
+#define RESET_SPICC_0				73
+#define RESET_SPICC_1				74
+/*						75-79*/
+#define RESET_MSR_CLK				80
+/*						81*/
+#define RESET_SAR_ADC				82
+/*						83-87*/
+#define RESET_ACODEC				88
+/*						89-90*/
+#define RESET_WATCHDOG				91
+/*						92-95*/
+
+/* RESET3 */
+/*						96-127 */
+
+/* RESET4 */
+/*						128-131 */
+#define RESET_PWM_AB				132
+#define RESET_PWM_CD				133
+#define RESET_PWM_EF				134
+#define RESET_PWM_GH				135
+/*						136-137*/
+#define RESET_UART_A				138
+#define RESET_UART_B				139
+/*						140*/
+#define RESET_UART_D				141
+#define RESET_UART_E				142
+/*						143-144*/
+#define RESET_I2C_M_A				145
+#define RESET_I2C_M_B				146
+#define RESET_I2C_M_C				147
+#define RESET_I2C_M_D				148
+/*						149-151*/
+#define RESET_SDEMMC_A				152
+/*						153*/
+#define RESET_SDEMMC_C				154
+/*						155-159*/
+
+/* RESET5 */
+/*						160-175*/
+#define RESET_BRG_AO_NIC_SYS			176
+/*						177*/
+#define RESET_BRG_AO_NIC_MAIN			178
+#define RESET_BRG_AO_NIC_AUDIO			179
+/*						180-183*/
+#define RESET_BRG_AO_NIC_ALL			184
+/*						185*/
+#define RESET_BRG_NIC_SDIO			186
+#define RESET_BRG_NIC_EMMC			187
+#define RESET_BRG_NIC_DSU			188
+#define RESET_BRG_NIC_CLK81			189
+#define RESET_BRG_NIC_MAIN			190
+#define RESET_BRG_NIC_ALL			191
+
+#endif
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index efba8565af3cf5298f894819572d78e0c0041f71..02365494d8655f8cf97f0ffdc9a9566e42ab61ae 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include "amlogic-a4-common.dtsi"
+#include "amlogic-a4-reset.h"
 #include <dt-bindings/power/amlogic,a4-pwrc.h>
 #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 / {
@@ -51,6 +52,13 @@ pwrc: power-controller {
 };
 
 &apb {
+	reset: reset-controller at 2000 {
+		compatible = "amlogic,a4-reset",
+			     "amlogic,meson-s4-reset";
+		reg = <0x0 0x2000 0x0 0x98>;
+		#reset-cells = <1>;
+	};
+
 	periphs_pinctrl: pinctrl {
 		compatible = "amlogic,pinctrl-a4";
 		#address-cells = <2>;

-- 
2.37.1




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 13 02:05:34 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 13 Mar 2025 17:05:34 +0800
Subject: [PATCH v4 1/3] dt-bindings: reset: Add compatible for Amlogic
 A4/A5 Reset Controller
In-Reply-To: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
Message-ID: <20250313-a4-a5-reset-v4-1-8076f684d6cf@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add compatibles for Amlogic A4 and A5 reset controllers,
which fall back to 'amlogic,meson-s4-reset'.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
Link: https://lore.kernel.org/r/20240918074211.8067-2-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 .../bindings/reset/amlogic,meson-reset.yaml        | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
index 695ef38a7bb346c92b4cf428e7615d45682c940a..150e95c0d9bed74c7045942610a311114a257889 100644
--- a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
@@ -12,14 +12,20 @@ maintainers:
 
 properties:
   compatible:
-    enum:
-      - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
-      - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
-      - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
-      - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
-      - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
-      - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
-      - amlogic,t7-reset
+    oneOf:
+      - enum:
+          - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
+          - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
+          - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
+          - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
+          - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
+          - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
+          - amlogic,t7-reset
+      - items:
+          - enum:
+              - amlogic,a4-reset
+              - amlogic,a5-reset
+          - const: amlogic,meson-s4-reset
 
   reg:
     maxItems: 1

-- 
2.37.1




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 13 02:05:33 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 13 Mar 2025 17:05:33 +0800
Subject: [PATCH v4 0/3] Add support for Amlogic A4/A5 Reset
Message-ID: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>

Add dt-binding compatibles and device nodes for Amlogic A4/A5 reset.

Imported from f20240918074211.8067-1-zelong.dong at amlogic.com

Changes in v4:
- Remove the superfluous 'items' in the dt-binding.
- Rebasing due to recent upstream changes.

Changes in v3:
- rebase on 'amlogic,t7-reset' patchset
- Link to v2: https://lore.kernel.org/all/20240715051217.5286-1-zelong.dong at amlogic.com/

Changes in v2:
- remove 'amlogic,t7-reset'
- move 'amlogic,c3-reset' to the other enum list
- move reset node from amlogic-a4-common.dtsi to
  amlogic-a4.dtsi/amlogic-a5.dtsi
- Link to v1: https://lore.kernel.org/all/20240703061610.37217-1-zelong.dong at amlogic.com/

---
Zelong Dong (3):
  dt-bindings: reset: Add compatible for Amlogic A4/A5 Reset Controller
  arm64: dts: amlogic: Add Amlogic A4 reset controller
  arm64: dts: amlogic: Add Amlogic A5 reset controller

 .../bindings/reset/amlogic,meson-reset.yaml   | 23 +++--
 .../arm64/boot/dts/amlogic/amlogic-a4-reset.h | 93 ++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi   | 10 ++
 .../arm64/boot/dts/amlogic/amlogic-a5-reset.h | 95 +++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi   | 10 ++
 5 files changed, 223 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
 create mode 100644 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h

--
2.35.1

---
Zelong Dong (3):
      dt-bindings: reset: Add compatible for Amlogic A4/A5 Reset Controller
      arm64: dts: amlogic: Add A4 Reset Controller
      arm64: dts: amlogic: Add A5 Reset Controller

 .../bindings/reset/amlogic,meson-reset.yaml        | 22 +++--
 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h     | 93 +++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  8 ++
 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h     | 95 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 10 +++
 5 files changed, 220 insertions(+), 8 deletions(-)
---
base-commit: 9fbcd7b32bf7c0a5bda0f22c25df29d00a872017
change-id: 20250313-a4-a5-reset-6696e5b18e10

Best regards,
-- 
Kelvin Zhang <kelvin.zhang at amlogic.com>




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 13 02:05:36 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 13 Mar 2025 17:05:36 +0800
Subject: [PATCH v4 3/3] arm64: dts: amlogic: Add A5 Reset Controller
In-Reply-To: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
Message-ID: <20250313-a4-a5-reset-v4-3-8076f684d6cf@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add the device node and related header file for Amlogic
A5 reset controller.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Link: https://lore.kernel.org/r/20240918074211.8067-4-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h | 95 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi    | 10 +++
 2 files changed, 105 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdf0f515962097c606e4c53badb19df7d21606ec
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __DTS_AMLOGIC_A5_RESET_H
+#define __DTS_AMLOGIC_A5_RESET_H
+
+/* RESET0 */
+/*						0-3 */
+#define RESET_USB				4
+/*						5-7 */
+#define RESET_USBPHY20				8
+/*						9 */
+#define RESET_USB2DRD				10
+/*						11-31 */
+
+/* RESET1 */
+#define RESET_AUDIO				32
+#define RESET_AUDIO_VAD				33
+/*                                              34 */
+#define RESET_DDR_APB				35
+#define RESET_DDR				36
+/*						37-40 */
+#define RESET_DSPA_DEBUG			41
+/*                                              42 */
+#define RESET_DSPA				43
+/*						44-46 */
+#define RESET_NNA				47
+#define RESET_ETHERNET				48
+/*						49-63 */
+
+/* RESET2 */
+#define RESET_ABUS_ARB				64
+#define RESET_IRCTRL				65
+/*						66 */
+#define RESET_TS_PLL				67
+/*						68-72 */
+#define RESET_SPICC_0				73
+#define RESET_SPICC_1				74
+#define RESET_RSA				75
+
+/*						76-79 */
+#define RESET_MSR_CLK				80
+#define RESET_SPIFC				81
+#define RESET_SAR_ADC				82
+/*						83-90 */
+#define RESET_WATCHDOG				91
+/*						92-95 */
+
+/* RESET3 */
+/*						96-127 */
+
+/* RESET4 */
+#define RESET_RTC				128
+/*						129-131 */
+#define RESET_PWM_AB				132
+#define RESET_PWM_CD				133
+#define RESET_PWM_EF				134
+#define RESET_PWM_GH				135
+/*						104-105 */
+#define RESET_UART_A				138
+#define RESET_UART_B				139
+#define RESET_UART_C				140
+#define RESET_UART_D				141
+#define RESET_UART_E				142
+/*						143*/
+#define RESET_I2C_S_A				144
+#define RESET_I2C_M_A				145
+#define RESET_I2C_M_B				146
+#define RESET_I2C_M_C				147
+#define RESET_I2C_M_D				148
+/*						149-151 */
+#define RESET_SDEMMC_A				152
+/*						153 */
+#define RESET_SDEMMC_C				154
+/*						155-159*/
+
+/* RESET5 */
+/*						160-175 */
+#define RESET_BRG_AO_NIC_SYS			176
+#define RESET_BRG_AO_NIC_DSPA			177
+#define RESET_BRG_AO_NIC_MAIN			178
+#define RESET_BRG_AO_NIC_AUDIO			179
+/*						180-183 */
+#define RESET_BRG_AO_NIC_ALL			184
+#define RESET_BRG_NIC_NNA			185
+#define RESET_BRG_NIC_SDIO			186
+#define RESET_BRG_NIC_EMMC			187
+#define RESET_BRG_NIC_DSU			188
+#define RESET_BRG_NIC_SYSCLK			189
+#define RESET_BRG_NIC_MAIN			190
+#define RESET_BRG_NIC_ALL			191
+
+#endif
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 17a6316de8918f31f3f7625f2eda06a60664139a..b97e2f3091bf62f4bdaaebeaf5d1dfe695cfc6d5 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include "amlogic-a4-common.dtsi"
+#include "amlogic-a5-reset.h"
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
 / {
 	cpus {
@@ -48,3 +49,12 @@ pwrc: power-controller {
 		};
 	};
 };
+
+&apb {
+	reset: reset-controller at 2000 {
+		compatible = "amlogic,a5-reset",
+			     "amlogic,meson-s4-reset";
+		reg = <0x0 0x2000 0x0 0x98>;
+		#reset-cells = <1>;
+	};
+};

-- 
2.37.1




From pabeni at redhat.com  Thu Mar 13 02:13:50 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Thu, 13 Mar 2025 10:13:50 +0100
Subject: [PATCH net-next v5 00/13] net: phy: Rework linkmodes handling in
 a dedicated file
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <92a9cb8d-fe6b-4389-9d65-64b668f1e221@redhat.com>

On 3/7/25 6:35 PM, Maxime Chevallier wrote:
> Hello everyone,
> 
> This is V5 of the phy_caps series. In a nutshell, this series reworks the way
> we maintain the list of speed/duplex capablities for each linkmode so that we
> no longer have multiple definition of these associations.
> 
> That will help making sure that when people add new linkmodes in
> include/uapi/linux/ethtool.h, they don't have to update phylib and phylink as
> well, making the process more straightforward and less error-prone.
> 
> It also generalises the phy_caps interface to be able to lookup linkmodes
> from phy_interface_t, which is needed for the multi-port work I've been working
> on for a while.
> 
> This V5 addresse Russell's and Paolo's reviews, namely :
> 
>  - Error out when encountering an unknown SPEED_XXX setting
> 
>    It prints an error and fails to initialize phylib. I've tested by
>    introducing a dummy 1.6T speed, I guess it's only a matter of time
>    before that actually happens :)
> 
>  - Deal more gracefully with the fixed-link settings, keeping some level of
>    compatibility with what we had before by making sure we report a
>    single BaseT mode like before.
> 
> V1 : https://lore.kernel.org/netdev/20250222142727.894124-1-maxime.chevallier at bootlin.com/
> V2 : https://lore.kernel.org/netdev/20250226100929.1646454-1-maxime.chevallier at bootlin.com/
> V3 : https://lore.kernel.org/netdev/20250228145540.2209551-1-maxime.chevallier at bootlin.com/
> V4 : https://lore.kernel.org/netdev/20250303090321.805785-1-maxime.chevallier at bootlin.com/

LGTM, waiting an extra bit to allow explicit acks from the phy crew.

Thanks,

Paolo



From Jonathan.Cameron at huawei.com  Thu Mar 13 02:16:11 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 13 Mar 2025 09:16:11 +0000
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <20250311075143.61078-3-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
	<20250311075143.61078-3-yangyicong@huawei.com>
Message-ID: <20250313091611.00003ccf@huawei.com>

On Tue, 11 Mar 2025 15:51:41 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> On building the topology from the devicetree, we've already gotten the
> SMT thread number of each core. Update the largest SMT thread number
> and enable the SMT control by the end of topology parsing.
> 
> The framework's SMT control provides two interface to the users [1]
> through /sys/devices/system/cpu/smt/control:
> 1) enable SMT by writing "on" and disable by "off"
> 2) enable SMT by writing max_thread_number or disable by writing 1
> 
> Both method support to completely disable/enable the SMT cores so both
> work correctly for symmetric SMT platform and asymmetric platform with
> non-SMT and one type SMT cores like:
> core A: 1 thread
> core B: X (X!=1) threads
> 
> Note that for a theoretically possible multiple SMT-X (X>1) core
> platform the SMT control is also supported as expected but only
> by writing the "on/off" method.
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542
> Reviewed-by: Pierre Gondois <pierre.gondois at arm.com>
> Reviewed-by: Dietmar Eggemann <dietmar.eggemann at arm.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>


From vdonnefort at google.com  Thu Mar 13 02:13:45 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 09:13:45 +0000
Subject: [PATCH v3 2/3] KVM: arm64: Distinct pKVM teardown memcache for
 stage-2
In-Reply-To: <87plim7hgc.wl-maz@kernel.org>
References: <20250307113411.469018-1-vdonnefort@google.com>
 <20250307113411.469018-3-vdonnefort@google.com>
 <87plim7hgc.wl-maz@kernel.org>
Message-ID: <Z9KhybW0J2WIX1eU@google.com>

On Wed, Mar 12, 2025 at 08:59:15AM +0000, Marc Zyngier wrote:
> On Fri, 07 Mar 2025 11:34:10 +0000,
> Vincent Donnefort <vdonnefort at google.com> wrote:
> > 
> > In order to account for memory dedicated to the stage-2 page-tables, use
> > a separated memcache when tearing down the VM.
> > 
> > Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> > 
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 12691ae23d4c..ace3969e8106 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
> >  struct kvm_protected_vm {
> >  	pkvm_handle_t handle;
> >  	struct kvm_hyp_memcache teardown_mc;
> > +	struct kvm_hyp_memcache stage2_teardown_mc;
> >  	bool enabled;
> >  };
> >  
> > diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > index 3927fe52a3dd..15f8d5315959 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > @@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
> >  
> >  int __pkvm_teardown_vm(pkvm_handle_t handle)
> >  {
> > -	struct kvm_hyp_memcache *mc;
> > +	struct kvm_hyp_memcache *mc, *stage2_mc;
> >  	struct pkvm_hyp_vm *hyp_vm;
> >  	struct kvm *host_kvm;
> >  	unsigned int idx;
> > @@ -706,7 +706,8 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
> >  
> >  	/* Reclaim guest pages (including page-table pages) */
> >  	mc = &host_kvm->arch.pkvm.teardown_mc;
> > -	reclaim_guest_pages(hyp_vm, mc);
> > +	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
> > +	reclaim_guest_pages(hyp_vm, stage2_mc);
> 
> This looks odd. What counts as stage-2 pages here? Or is it that
> reclaim_guest_pages() is very badly named?

Yes, this is a naming issue here. How about 

  reclaim_pgtable_pages(hyp_vm, stage2_mc);

Then I can probably drop that /* Push the metadata pages to the teardown
memcache */  comment as it is clear what is pgtable and what is meta-data?

> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.


From vdonnefort at google.com  Thu Mar 13 02:16:30 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 09:16:30 +0000
Subject: [PATCH v3 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <87r0327iek.wl-maz@kernel.org>
References: <20250307113411.469018-1-vdonnefort@google.com>
 <20250307113411.469018-2-vdonnefort@google.com>
 <87r0327iek.wl-maz@kernel.org>
Message-ID: <Z9KiboTJy9A6qvbK@google.com>

[...]

> > @@ -1102,7 +1102,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
> >  		return;
> >  
> >  	kfree(mc->mapping);
> > -	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
> > +	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, (void *)mc);
> 
> Why the cast? It looks superfluous to me.

Ha yes it is now I pass mc and not mc->flags.

> 
> >  }
> >  
> >  int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
> > @@ -1117,7 +1117,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
> >  	}
> >  
> >  	return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
> > -				    kvm_host_pa, NULL);
> > +				    kvm_host_pa, (void *)mc);
> 
> Same here.
> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.


From maz at kernel.org  Thu Mar 13 02:22:07 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 09:22:07 +0000
Subject: [PATCH v5 0/2] Add L1 and L2 error detection for A53 and A57
In-Reply-To: <ff79f33d-91fd-49e5-9a6f-fa2c32c7021d@linux.microsoft.com>
References: <20210401110615.15326-1-s.hauer@pengutronix.de>
	<ff79f33d-91fd-49e5-9a6f-fa2c32c7021d@linux.microsoft.com>
Message-ID: <86msdpnv40.wl-maz@kernel.org>

On Thu, 13 Mar 2025 01:43:55 +0000,
Vijay Balakrishna <vijayb at linux.microsoft.com> wrote:
> 
> On 4/1/2021 4:06 AM, Sascha Hauer wrote:
> > Hi,
> > 
> > Resending this mainly because Marc Zyngier and Mark Rutland raised
> > concerns about using implementation defined registers and I forgot to Cc
> > them with the last version. This version, like v4 already, should fix
> > these concerns. Looking forward to feedback.
> 
> We aim to revive and adapt this patch series for A72 and A78.  Is
> anyone actively working on this?  Please share any information on why
> it wasn't pursued and thoughts on adapting it to A72 and A78.

Because, and especially for less ancient CPUs such as A78 that
implement some form of FEAT_RAS support, this makes little sense.  We
fully expect RAS errors to be handled by firmware, which knows exactly
the cache topology and can abstract the reporting into error records.
Firmware is also the correct place for all this IMPDEF stuff.

	M.

-- 
Without deviation from the norm, progress is not possible.


From 21cnbao at gmail.com  Thu Mar 13 02:30:05 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Thu, 13 Mar 2025 22:30:05 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <CAGsJ_4yw17rLJPgS6CNXfXNVQnv2pf0PnLSA4UVAR1sUWDhP5Q@mail.gmail.com>
References: <CAGsJ_4yw17rLJPgS6CNXfXNVQnv2pf0PnLSA4UVAR1sUWDhP5Q@mail.gmail.com>
Message-ID: <20250313093005.13998-1-21cnbao@gmail.com>

On Thu, Mar 13, 2025 at 4:52?PM Barry Song <21cnbao at gmail.com> wrote:
>
> On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
> <senozhatsky at chromium.org> wrote:
> >
> > On (25/03/12 11:11), Minchan Kim wrote:
> > > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > > This patch series introduces a new mechanism called kcompressd to
> > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > main goal is to separate the tasks of page scanning and page compression
> > > > into distinct processes or threads, thereby reducing the load on the
> > > > kswapd thread and enhancing overall system performance under high memory
> > > > pressure conditions.
> > > >
> > > > Problem:
> > > >  In the current system, the kswapd thread is responsible for both
> > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > >  combined responsibility can lead to significant performance bottlenecks,
> > > >  especially under high memory pressure. The kswapd thread becomes a
> > > >  single point of contention, causing delays in memory reclaiming and
> > > >  overall system performance degradation.
> > >
> > > Isn't it general problem if backend for swap is slow(but synchronous)?
> > > I think zram need to support asynchrnous IO(can do introduce multiple
> > > threads to compress batched pages) and doesn't declare it's
> > > synchrnous device for the case.
> >
> > The current conclusion is that kcompressd will sit above zram,
> > because zram is not the only compressing swap backend we have.
>
> also. it is not good to hack zram to be aware of if it is kswapd
> , direct reclaim , proactive reclaim and block device with
> mounted filesystem.
>
> so i am thinking sth as below
>
> page_io.c
>
> if (sync_device or zswap_enabled())
>    schedule swap_writepage to a separate per-node thread
>

Hi Qun-wei, Nhat, Sergey and Minchan,

I managed to find some time to prototype a kcompressd that supports
both zswap and zram, though it has only been build-tested.

Hi Qun-wei,

Apologies, but I?m quite busy with other tasks and don?t have time to
debug or test it. Please feel free to test it. When you submit v2, you?re
welcome to keep yourself as the author of the patch as v1.

If you?re okay with it, you can also add me as a co-developer in the
changelog. The below prototype, I'd rather start with a per-node thread
approach. While this might not provide the greatest benefit, it carries
the least risk and helps avoid complex questions, such as how to
determine the number of threads. - And we have actually observed a
significant reduction in allocstall by using a single thread to
asynchronously handle kswapd's compression as I reported.

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index dbb0ad69e17f..4f9ee2fb338d 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -23,6 +23,7 @@
 #include <linux/page-flags.h>
 #include <linux/local_lock.h>
 #include <linux/zswap.h>
+#include <linux/kfifo.h>
 #include <asm/page.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -1389,6 +1390,11 @@ typedef struct pglist_data {
 
 	int kswapd_failures;		/* Number of 'reclaimed == 0' runs */
 
+#define KCOMPRESS_FIFO_SIZE 256
+	wait_queue_head_t kcompressd_wait;
+	struct task_struct *kcompressd;
+	struct kfifo kcompress_fifo;
+
 #ifdef CONFIG_COMPACTION
 	int kcompactd_max_order;
 	enum zone_type kcompactd_highest_zoneidx;
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 281802a7a10d..8cd143f59e76 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -1410,6 +1410,7 @@ static void __meminit pgdat_init_internals(struct pglist_data *pgdat)
 	pgdat_init_kcompactd(pgdat);
 
 	init_waitqueue_head(&pgdat->kswapd_wait);
+	init_waitqueue_head(&pgdat->kcompressd_wait);
 	init_waitqueue_head(&pgdat->pfmemalloc_wait);
 
 	for (i = 0; i < NR_VMSCAN_THROTTLE; i++)
diff --git a/mm/page_io.c b/mm/page_io.c
index 4bce19df557b..7bbd14991ffb 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -233,6 +233,33 @@ static void swap_zeromap_folio_clear(struct folio *folio)
 	}
 }
 
+static bool swap_sched_async_compress(struct folio *folio)
+{
+	struct swap_info_struct *sis = swp_swap_info(folio->swap);
+	int nid = numa_node_id();
+	pg_data_t *pgdat = NODE_DATA(nid);
+
+	if (unlikely(!pgdat->kcompressd))
+		return false;
+
+	if (!current_is_kswapd())
+		return false;
+
+	if (!folio_test_anon(folio))
+		return false;
+	/*
+	 * This case needs to synchronously return AOP_WRITEPAGE_ACTIVATE
+	 */
+	if (!mem_cgroup_zswap_writeback_enabled(folio_memcg(folio)))
+		return false;
+
+	sis = swp_swap_info(folio->swap);
+	if (zswap_is_enabled() || data_race(sis->flags & SWP_SYNCHRONOUS_IO))
+		return kfifo_in(&pgdat->kcompress_fifo, folio, sizeof(folio));
+
+	return false;
+}
+
 /*
  * We may have stale swap cache pages in memory: notice
  * them here and get rid of the unnecessary final write.
@@ -275,6 +302,15 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
 		 */
 		swap_zeromap_folio_clear(folio);
 	}
+
+	/*
+	 * Compression within zswap and zram might block rmap, unmap
+	 * of both file and anon pages, try to do compression async
+	 * if possible
+	 */
+	if (swap_sched_async_compress(folio))
+		return 0;
+
 	if (zswap_store(folio)) {
 		count_mthp_stat(folio_order(folio), MTHP_STAT_ZSWPOUT);
 		folio_unlock(folio);
@@ -289,6 +325,38 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
 	return 0;
 }
 
+int kcompressd(void *p)
+{
+	pg_data_t *pgdat = (pg_data_t *)p;
+	struct folio *folio;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_NONE,
+		.nr_to_write = SWAP_CLUSTER_MAX,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+		.for_reclaim = 1,
+	};
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(pgdat->kcompressd_wait,
+				!kfifo_is_empty(&pgdat->kcompress_fifo));
+
+		if (kthread_should_stop())
+			break;
+		while(!kfifo_is_empty(&pgdat->kcompress_fifo)) {
+			if (kfifo_out(&pgdat->kcompress_fifo, &folio, sizeof(folio))) {
+				if (zswap_store(folio)) {
+					count_mthp_stat(folio_order(folio), MTHP_STAT_ZSWPOUT);
+					folio_unlock(folio);
+					return 0;
+				}
+				__swap_writepage(folio, &wbc);
+			}
+		}
+	}
+	return 0;
+}
+
 static inline void count_swpout_vm_event(struct folio *folio)
 {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
diff --git a/mm/swap.h b/mm/swap.h
index 0abb68091b4f..38d61c6a06f1 100644
--- a/mm/swap.h
+++ b/mm/swap.h
@@ -21,6 +21,7 @@ static inline void swap_read_unplug(struct swap_iocb *plug)
 void swap_write_unplug(struct swap_iocb *sio);
 int swap_writepage(struct page *page, struct writeback_control *wbc);
 void __swap_writepage(struct folio *folio, struct writeback_control *wbc);
+int kcompressd(void *p);
 
 /* linux/mm/swap_state.c */
 /* One swap address space for each 64M swap space */
@@ -198,6 +199,11 @@ static inline int swap_zeromap_batch(swp_entry_t entry, int max_nr,
 	return 0;
 }
 
+static inline int kcompressd(void *p)
+{
+	return 0;
+}
+
 #endif /* CONFIG_SWAP */
 
 #endif /* _MM_SWAP_H */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2bc740637a6c..ba0245b74e45 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -7370,6 +7370,7 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
 void __meminit kswapd_run(int nid)
 {
 	pg_data_t *pgdat = NODE_DATA(nid);
+	int ret;
 
 	pgdat_kswapd_lock(pgdat);
 	if (!pgdat->kswapd) {
@@ -7383,7 +7384,23 @@ void __meminit kswapd_run(int nid)
 		} else {
 			wake_up_process(pgdat->kswapd);
 		}
+		ret = kfifo_alloc(&pgdat->kcompress_fifo,
+				KCOMPRESS_FIFO_SIZE * sizeof(struct folio *),
+				GFP_KERNEL);
+		if (ret)
+			goto out;
+		pgdat->kcompressd = kthread_create_on_node(kcompressd, pgdat, nid,
+				"kcompressd%d", nid);
+		if (IS_ERR(pgdat->kcompressd)) {
+			pr_err("Failed to start kcompressd on node %d?ret=%ld\n",
+					nid, PTR_ERR(pgdat->kcompressd));
+			pgdat->kcompressd = NULL;
+			kfifo_free(&pgdat->kcompress_fifo);
+		} else {
+			wake_up_process(pgdat->kcompressd);
+		}
 	}
+out:
 	pgdat_kswapd_unlock(pgdat);
 }
 
@@ -7402,6 +7419,11 @@ void __meminit kswapd_stop(int nid)
 		kthread_stop(kswapd);
 		pgdat->kswapd = NULL;
 	}
+	if (pgdat->kcompressd) {
+		kthread_stop(pgdat->kcompressd);
+		pgdat->kcompressd = NULL;
+		kfifo_free(&pgdat->kcompress_fifo);
+	}
 	pgdat_kswapd_unlock(pgdat);
 }
 

> btw,  ran the current patchset with one thread(not default 4)
> on phones and saw 50%+ allocstall reduction. so the idea
> looks like a good direction to go.
>

Thanks
Barry


From maz at kernel.org  Thu Mar 13 02:31:42 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 09:31:42 +0000
Subject: [PATCH v3 2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
In-Reply-To: <Z9KhybW0J2WIX1eU@google.com>
References: <20250307113411.469018-1-vdonnefort@google.com>
	<20250307113411.469018-3-vdonnefort@google.com>
	<87plim7hgc.wl-maz@kernel.org>
	<Z9KhybW0J2WIX1eU@google.com>
Message-ID: <86ldt9nuo1.wl-maz@kernel.org>

On Thu, 13 Mar 2025 09:13:45 +0000,
Vincent Donnefort <vdonnefort at google.com> wrote:
> 
> On Wed, Mar 12, 2025 at 08:59:15AM +0000, Marc Zyngier wrote:
> > On Fri, 07 Mar 2025 11:34:10 +0000,
> > Vincent Donnefort <vdonnefort at google.com> wrote:
> > > 
> > > In order to account for memory dedicated to the stage-2 page-tables, use
> > > a separated memcache when tearing down the VM.
> > > 
> > > Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
> > > 
> > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > index 12691ae23d4c..ace3969e8106 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
> > >  struct kvm_protected_vm {
> > >  	pkvm_handle_t handle;
> > >  	struct kvm_hyp_memcache teardown_mc;
> > > +	struct kvm_hyp_memcache stage2_teardown_mc;
> > >  	bool enabled;
> > >  };
> > >  
> > > diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > > index 3927fe52a3dd..15f8d5315959 100644
> > > --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > > +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> > > @@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
> > >  
> > >  int __pkvm_teardown_vm(pkvm_handle_t handle)
> > >  {
> > > -	struct kvm_hyp_memcache *mc;
> > > +	struct kvm_hyp_memcache *mc, *stage2_mc;
> > >  	struct pkvm_hyp_vm *hyp_vm;
> > >  	struct kvm *host_kvm;
> > >  	unsigned int idx;
> > > @@ -706,7 +706,8 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
> > >  
> > >  	/* Reclaim guest pages (including page-table pages) */
> > >  	mc = &host_kvm->arch.pkvm.teardown_mc;
> > > -	reclaim_guest_pages(hyp_vm, mc);
> > > +	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
> > > +	reclaim_guest_pages(hyp_vm, stage2_mc);
> > 
> > This looks odd. What counts as stage-2 pages here? Or is it that
> > reclaim_guest_pages() is very badly named?
> 
> Yes, this is a naming issue here. How about 
> 
>   reclaim_pgtable_pages(hyp_vm, stage2_mc);

LGTM.

> 
> Then I can probably drop that /* Push the metadata pages to the teardown
> memcache */  comment as it is clear what is pgtable and what is meta-data?

Yeah, the comments are actively getting in the way.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From ryan.roberts at arm.com  Thu Mar 13 02:54:22 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 09:54:22 +0000
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early
 mappings
In-Reply-To: <CAMj1kXG1jqi9vfTS4wz_a3QPERCUYbHcV6Fq+jf4ZkPtgM5oAg@mail.gmail.com>
References: <20250311073043.96795-2-ardb+git@google.com>
 <f6d48d04-fd3c-493e-b7a0-020b912f6f10@arm.com>
 <CAMj1kXG1jqi9vfTS4wz_a3QPERCUYbHcV6Fq+jf4ZkPtgM5oAg@mail.gmail.com>
Message-ID: <e844e66a-1ddd-44d7-9fcd-f7ec2fb3440a@arm.com>

On 11/03/2025 18:35, Ard Biesheuvel wrote:
> On Tue, 11 Mar 2025 at 12:31, Ryan Roberts <ryan.roberts at arm.com> wrote:
>>
>> On 11/03/2025 07:30, Ard Biesheuvel wrote:
>>> From: Ard Biesheuvel <ardb at kernel.org>
>>>
>>> The page table population code in map_range() uses a recursive algorithm
>>> to create the early mappings of the kernel, the DTB and the ID mapped
>>> text and data pages, and this fails to take into account that the way
>>> these page tables may be constructed is not precisely the same at each
>>> level. In particular, block mappings are not permitted at each level,
>>> and the code as it exists today might inadvertently create such a
>>> forbidden block mapping if it were used to map a region of the
>>> appropriate size and alignment.
>>>
>>> This never happens in practice, given the limited size of the assets
>>> being mapped by the early boot code. Nonetheless, it would be better if
>>> this code would behave correctly in all circumstances.
>>>
>>> So only permit block mappings at level 2, and page mappings at level 3,
>>> for any page size, and use table mappings exclusively at all other
>>> levels. This change should have no impact in practice, but it makes the
>>> code more robust.
>>>
>>> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
>>> Reported-by: Ryan Roberts <ryan.roberts at arm.com>
>>> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
>>> ---
>>> v2: take the assignment of protval out of the loop again, so that
>>>     clearing a mapping works as expected wrt the PTE_CONT bit
>>
>> Ouch, totally missed that. Now that I've looked at the code properly, I wonder
>> if it is worth supporting CONT_PMD mappings at level 2? That would be 32M for 4K
>> pages, so is likely to actaually get used. I think it would just be something like:
>>
>> u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 :
>>            ((level == 2) ? CONT_PMD_SIZE - 1 : U64_MAX) : U64_MAX;
>>
> 
> With this patch applied, it is guaranteed that cmask is only
> referenced if level >= 2, so we can simplify this as
> 
>   u64 cmask = (level < 3) ? CONT_PMD_SIZE - 1 : CONT_PTE_SIZE - 1;

Ahh good point.

> 
> (using the level < 3 for consistency with the protval assignment)
> 
>> Anyway, probably not worth the complexity for these boot-time tables, so regardless:
>>
> 
> They are created at boot time but these are not 'boot-time tables' -
> they are the ones that are used by the kernel at runtime. So I think
> it makes sense to add this.

Hmm, for some reason I thought everything was being remapped in map_mem(), but
looking again, I guess the kernel image mappings put down by map_range() remain.

I'll add a todo to send this out when I get around to it. Although I guess the
chances of having a portion of the text or data being 32M aligned and sized are
quite slim given the image only needs to be loaded on a 2M boundary?

> 
>> Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
>>
> 
> Thanks.



From m.szyprowski at samsung.com  Thu Mar 13 02:56:30 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Thu, 13 Mar 2025 10:56:30 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
	<e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
	<CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
Message-ID: <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>

Hi Robin,

On 28.02.2025 16:46, Robin Murphy wrote:
> In hindsight, there were some crucial subtleties overlooked when moving
> {of,acpi}_dma_configure() to driver probe time to allow waiting for
> IOMMU drivers with -EPROBE_DEFER, and these have become an
> ever-increasing source of problems. The IOMMU API has some fundamental
> assumptions that iommu_probe_device() is called for every device added
> to the system, in the order in which they are added. Calling it in a
> random order or not at all dependent on driver binding leads to
> malformed groups, a potential lack of isolation for devices with no
> driver, and all manner of unexpected concurrency and race conditions.
> We've attempted to mitigate the latter with point-fix bodges like
> iommu_probe_device_lock, but it's a losing battle and the time has come
> to bite the bullet and address the true source of the problem instead.
>
> The crux of the matter is that the firmware parsing actually serves two
> distinct purposes; one is identifying the IOMMU instance associated with
> a device so we can check its availability, the second is actually
> telling that instance about the relevant firmware-provided data for the
> device. However the latter also depends on the former, and at the time
> there was no good place to defer and retry that separately from the
> availability check we also wanted for client driver probe.
>
> Nowadays, though, we have a proper notion of multiple IOMMU instances in
> the core API itself, and each one gets a chance to probe its own devices
> upon registration, so we can finally make that work as intended for
> DT/IORT/VIOT platforms too. All we need is for iommu_probe_device() to
> be able to run the iommu_fwspec machinery currently buried deep in the
> wrong end of {of,acpi}_dma_configure(). Luckily it turns out to be
> surprisingly straightforward to bootstrap this transformation by pretty
> much just calling the same path twice. At client driver probe time,
> dev->driver is obviously set; conversely at device_add(), or a
> subsequent bus_iommu_probe(), any device waiting for an IOMMU really
> should *not* have a driver already, so we can use that as a condition to
> disambiguate the two cases, and avoid recursing back into the IOMMU core
> at the wrong times.
>
> Obviously this isn't the nicest thing, but for now it gives us a
> functional baseline to then unpick the layers in between without many
> more awkward cross-subsystem patches. There are some minor side-effects
> like dma_range_map potentially being created earlier, and some debug
> prints being repeated, but these aren't significantly detrimental. Let's
> make things work first, then deal with making them nice.
>
> With the basic flow finally in the right order again, the next step is
> probably turning the bus->dma_configure paths inside-out, since all we
> really need from bus code is its notion of which device and input ID(s)
> to parse the common firmware properties with...
>
> Acked-by: Bjorn Helgaas <bhelgaas at google.com> # pci-driver.c
> Acked-by: Rob Herring (Arm) <robh at kernel.org> # of/device.c
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

This patch landed in yesterday's linux-next as commit bcb81ac6ae3c 
("iommu: Get DT/ACPI parsing into the proper probe path"). In my tests I 
found it breaks booting of ARM64 RK3568-based Odroid-M1 board 
(arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the 
relevant kernel log:

Unable to handle kernel NULL pointer dereference at virtual address 
00000000000003e8
Mem abort info:
 ? ESR = 0x0000000096000004
 ? EC = 0x25: DABT (current EL), IL = 32 bits
 ? SET = 0, FnV = 0
 ? EA = 0, S1PTW = 0
 ? FSC = 0x04: level 0 translation fault
Data abort info:
 ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
 ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
 ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[00000000000003e8] user address but active_mm is swapper
Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
Modules linked in:
CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
Hardware name: Hardkernel ODROID-M1 (DT)
pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : devm_kmalloc+0x2c/0x114
lr : rk_iommu_of_xlate+0x30/0x90
...
Call trace:
 ?devm_kmalloc+0x2c/0x114 (P)
 ?rk_iommu_of_xlate+0x30/0x90
 ?of_iommu_xlate+0x9c/0xc8
 ?of_iommu_configure+0x1c4/0x23c
 ?of_dma_configure_id+0x244/0x3b8
 ?platform_dma_configure+0x74/0xac
 ?__iommu_probe_device+0x258/0x49c
 ?probe_iommu_group+0x3c/0x64
 ?bus_for_each_dev+0x74/0xd4
 ?iommu_device_register+0xd4/0x230
 ?rk_iommu_probe+0x1f8/0x350
 ?platform_probe+0x68/0xdc
 ?really_probe+0xbc/0x298
 ?__driver_probe_device+0x78/0x12c
 ?driver_probe_device+0x40/0x164
 ?__driver_attach+0x9c/0x1ac
 ?bus_for_each_dev+0x74/0xd4
 ?driver_attach+0x24/0x30
 ?bus_add_driver+0xe4/0x208
 ?driver_register+0x60/0x128
 ?__platform_driver_register+0x24/0x30
 ?rk_iommu_driver_init+0x1c/0x28
 ?do_one_initcall+0x64/0x308
 ?kernel_init_freeable+0x288/0x4f0
 ?kernel_init+0x20/0x1d8
 ?ret_from_fork+0x10/0x20
Code: d2801017 a90153f3 ab0102e0 aa0103f4 (b943eab8)
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
SMP: stopping secondary CPUs
Kernel Offset: disabled
CPU features: 0x100,00000040,00901250,8200720b
Memory Limit: none
---[ end Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x0000000b ]---

Let me know if You want me to test any experimental patch or provide 
more information.

> ---
>
> v2:
>   - Comment bus driver changes for clarity
>   - Use dev->iommu as the now-robust replay condition
>   - Drop the device_iommu_mapped() checks in the firmware paths as they
>     weren't doing much - we can't replace probe_device_lock just yet...
>   
>   drivers/acpi/arm64/dma.c        |  5 +++++
>   drivers/acpi/scan.c             |  7 -------
>   drivers/amba/bus.c              |  3 ++-
>   drivers/base/platform.c         |  3 ++-
>   drivers/bus/fsl-mc/fsl-mc-bus.c |  3 ++-
>   drivers/cdx/cdx.c               |  3 ++-
>   drivers/iommu/iommu.c           | 24 +++++++++++++++++++++---
>   drivers/iommu/of_iommu.c        |  7 ++++++-
>   drivers/of/device.c             |  7 ++++++-
>   drivers/pci/pci-driver.c        |  3 ++-
>   10 files changed, 48 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/acpi/arm64/dma.c b/drivers/acpi/arm64/dma.c
> index 52b2abf88689..f30f138352b7 100644
> --- a/drivers/acpi/arm64/dma.c
> +++ b/drivers/acpi/arm64/dma.c
> @@ -26,6 +26,11 @@ void acpi_arch_dma_setup(struct device *dev)
>   	else
>   		end = (1ULL << 32) - 1;
>   
> +	if (dev->dma_range_map) {
> +		dev_dbg(dev, "dma_range_map already set\n");
> +		return;
> +	}
> +
>   	ret = acpi_dma_get_range(dev, &map);
>   	if (!ret && map) {
>   		end = dma_range_map_max(map);
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 9f4efa8f75a6..fb1fe9f3b1a3 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1632,13 +1632,6 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
>   		err = viot_iommu_configure(dev);
>   	mutex_unlock(&iommu_probe_device_lock);
>   
> -	/*
> -	 * If we have reason to believe the IOMMU driver missed the initial
> -	 * iommu_probe_device() call for dev, replay it to get things in order.
> -	 */
> -	if (!err && dev->bus)
> -		err = iommu_probe_device(dev);
> -
>   	return err;
>   }
>   
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 8ef259b4d037..71482d639a6d 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -364,7 +364,8 @@ static int amba_dma_configure(struct device *dev)
>   		ret = acpi_dma_configure(dev, attr);
>   	}
>   
> -	if (!ret && !drv->driver_managed_dma) {
> +	/* @drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !drv->driver_managed_dma) {
>   		ret = iommu_device_use_default_domain(dev);
>   		if (ret)
>   			arch_teardown_dma_ops(dev);
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index 6f2a33722c52..1813cfd0c4bd 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -1451,7 +1451,8 @@ static int platform_dma_configure(struct device *dev)
>   		attr = acpi_get_dma_attr(to_acpi_device_node(fwnode));
>   		ret = acpi_dma_configure(dev, attr);
>   	}
> -	if (ret || drv->driver_managed_dma)
> +	/* @drv may not be valid when we're called from the IOMMU layer */
> +	if (ret || !dev->driver || drv->driver_managed_dma)
>   		return ret;
>   
>   	ret = iommu_device_use_default_domain(dev);
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index d1f3d327ddd1..a8be8cf246fb 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -153,7 +153,8 @@ static int fsl_mc_dma_configure(struct device *dev)
>   	else
>   		ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id);
>   
> -	if (!ret && !mc_drv->driver_managed_dma) {
> +	/* @mc_drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !mc_drv->driver_managed_dma) {
>   		ret = iommu_device_use_default_domain(dev);
>   		if (ret)
>   			arch_teardown_dma_ops(dev);
> diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
> index c573ed2ee71a..780fb0c4adba 100644
> --- a/drivers/cdx/cdx.c
> +++ b/drivers/cdx/cdx.c
> @@ -360,7 +360,8 @@ static int cdx_dma_configure(struct device *dev)
>   		return ret;
>   	}
>   
> -	if (!ret && !cdx_drv->driver_managed_dma) {
> +	/* @cdx_drv may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !cdx_drv->driver_managed_dma) {
>   		ret = iommu_device_use_default_domain(dev);
>   		if (ret)
>   			arch_teardown_dma_ops(dev);
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index a3b45b84f42b..1cec7074367a 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -414,9 +414,21 @@ static int iommu_init_device(struct device *dev)
>   	if (!dev_iommu_get(dev))
>   		return -ENOMEM;
>   	/*
> -	 * For FDT-based systems and ACPI IORT/VIOT, drivers register IOMMU
> -	 * instances with non-NULL fwnodes, and client devices should have been
> -	 * identified with a fwspec by this point. Otherwise, we can currently
> +	 * For FDT-based systems and ACPI IORT/VIOT, the common firmware parsing
> +	 * is buried in the bus dma_configure path. Properly unpicking that is
> +	 * still a big job, so for now just invoke the whole thing. The device
> +	 * already having a driver bound means dma_configure has already run and
> +	 * either found no IOMMU to wait for, or we're in its replay call right
> +	 * now, so either way there's no point calling it again.
> +	 */
> +	if (!dev->driver && dev->bus->dma_configure) {
> +		mutex_unlock(&iommu_probe_device_lock);
> +		dev->bus->dma_configure(dev);
> +		mutex_lock(&iommu_probe_device_lock);
> +	}
> +	/*
> +	 * At this point, relevant devices either now have a fwspec which will
> +	 * match ops registered with a non-NULL fwnode, or we can reasonably
>   	 * assume that only one of Intel, AMD, s390, PAMU or legacy SMMUv2 can
>   	 * be present, and that any of their registered instances has suitable
>   	 * ops for probing, and thus cheekily co-opt the same mechanism.
> @@ -426,6 +438,12 @@ static int iommu_init_device(struct device *dev)
>   		ret = -ENODEV;
>   		goto err_free;
>   	}
> +	/*
> +	 * And if we do now see any replay calls, they would indicate someone
> +	 * misusing the dma_configure path outside bus code.
> +	 */
> +	if (dev->driver)
> +		dev_WARN(dev, "late IOMMU probe at driver bind, something fishy here!\n");
>   
>   	if (!try_module_get(ops->owner)) {
>   		ret = -EINVAL;
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e10a68b5ffde..6b989a62def2 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -155,7 +155,12 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
>   		dev_iommu_free(dev);
>   	mutex_unlock(&iommu_probe_device_lock);
>   
> -	if (!err && dev->bus)
> +	/*
> +	 * If we're not on the iommu_probe_device() path (as indicated by the
> +	 * initial dev->iommu) then try to simulate it. This should no longer
> +	 * happen unless of_dma_configure() is being misused outside bus code.
> +	 */
> +	if (!err && dev->bus && !dev_iommu_present)
>   		err = iommu_probe_device(dev);
>   
>   	if (err && err != -EPROBE_DEFER)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index edf3be197265..5053e5d532cc 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -99,6 +99,11 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	bool coherent, set_map = false;
>   	int ret;
>   
> +	if (dev->dma_range_map) {
> +		dev_dbg(dev, "dma_range_map already set\n");
> +		goto skip_map;
> +	}
> +
>   	if (np == dev->of_node)
>   		bus_np = __of_get_dma_parent(np);
>   	else
> @@ -119,7 +124,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   		end = dma_range_map_max(map);
>   		set_map = true;
>   	}
> -
> +skip_map:
>   	/*
>   	 * If @dev is expected to be DMA-capable then the bus code that created
>   	 * it should have initialised its dma_mask pointer by this point. For
> diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> index f57ea36d125d..4468b7327cab 100644
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
> @@ -1653,7 +1653,8 @@ static int pci_dma_configure(struct device *dev)
>   
>   	pci_put_host_bridge_device(bridge);
>   
> -	if (!ret && !driver->driver_managed_dma) {
> +	/* @driver may not be valid when we're called from the IOMMU layer */
> +	if (!ret && dev->driver && !driver->driver_managed_dma) {
>   		ret = iommu_device_use_default_domain(dev);
>   		if (ret)
>   			arch_teardown_dma_ops(dev);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From patchwork-bot+netdevbpf at kernel.org  Thu Mar 13 03:10:32 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 13 Mar 2025 10:10:32 +0000
Subject: [PATCH v2 0/3] net: stmmac: dwmac-rk: Validate GRF and peripheral GRF
 during probe
In-Reply-To: <20250308213720.2517944-1-jonas@kwiboo.se>
References: <20250308213720.2517944-1-jonas@kwiboo.se>
Message-ID: <174186063226.1446759.12026198009173732573.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Sat,  8 Mar 2025 21:37:12 +0000 you wrote:
> All Rockchip GMAC variants typically write to GRF regs to control e.g.
> interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
> RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
> located with help of a rockchip,grf and rockchip,php-grf phandle.
> 
> However, validating the rockchip,grf and rockchip,php-grf syscon regmap
> is deferred until e.g. interface mode or speed is configured.
> 
> [...]

Here is the summary with links:
  - [v2,1/3] dt-bindings: net: rockchip-dwmac: Require rockchip,grf and rockchip,php-grf
    https://git.kernel.org/netdev/net-next/c/313cf06ef4de
  - [v2,2/3] net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
    https://git.kernel.org/netdev/net-next/c/247e84f66a3d
  - [v2,3/3] net: stmmac: dwmac-rk: Remove unneeded GRF and peripheral GRF checks
    https://git.kernel.org/netdev/net-next/c/41f35564cb71

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From vignesh.raman at collabora.com  Thu Mar 13 03:24:37 2025
From: vignesh.raman at collabora.com (Vignesh Raman)
Date: Thu, 13 Mar 2025 15:54:37 +0530
Subject: drm-ci: rockchip:
 kms_bw@connected-linear-tiling-1-displays-2160x1440p flake
Message-ID: <eece9a80-42f3-41f4-86cc-69d8a51b976a@collabora.com>

Hi Maintainers,

There are some flake test reported for rockchip driver testing in drm-ci.

# Board Name: rk3399-gru-kevin
# Failure Rate: 20
# IGT Version: 1.30-g04bedb923
# Linux Version: 6.14.0-rc4
kms_bw at connected-linear-tiling-1-displays-2160x1440p

11:33:40.013: DEBUG - Begin test 
kms_bw at connected-linear-tiling-1-displays-2160x1440p
11:33:40.013: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Test assertion failure function igt_pipe_crc_start, file 
../lib/igt_pipe_crc.c:387:
11:33:45.115: [   69.768463] lr : drm_wait_one_vblank+0x1a0/0x204
11:33:45.115: [   69.768480] sp : ffff80008476bc80
11:33:45.116: [   69.768489] x29: ffff80008476bc80 x28: 0000000000000000 
x27: 0000000000000000
11:33:45.116: [   69.768524] x26: ffff800082cf0e80 x25: ffff00000012a005 
x24: ffff0000054e5080
11:33:45.116: [   69.768559] x23: 0000000000000000 x22: ffff0000f74ebf40 
x21: 00000000ffffffea
11:33:45.116: [   69.768594] x20: 0000000000000001 x19: ffff000005ce4000 
x18: 00000000fffffffe
11:33:45.116: [   69.768628] x17: 000000040044ffff x16: 00500072b5503510 
x15: ffff80008476b870
11:33:45.116: [   69.768664] x14: 00000000000c0000 x13: ffff800082d19460 
x12: 0000000000000000
11:33:45.116: [   69.768698] x11: 0000000000000050 x10: 0000000000000000 
x9 : ffff800083a57530
11:33:45.116: [   69.768733] x8 : ffff80008476ba28 x7 : ffff80008476baf0 
x6 : ffff80008476ba80
11:33:45.116: [   69.768767] x5 : ffff80008476ba68 x4 : 0000000000000002 
x3 : 0000000000000000
11:33:45.116: [   69.768800] x2 : 0000000000000000 x1 : 0000000000000000 
x0 : ffff000006f59bc0
11:33:45.116: [   69.768834] Call trace:
11:33:45.116: [   69.768843]  drm_wait_one_vblank+0x1a0/0x204 (P)
11:33:45.116: [   69.768863]  drm_crtc_wait_one_vblank+0x1c/0x28
11:33:45.116: [   69.768883]  drm_dp_aux_crc_work+0x58/0x15c
11:33:45.116: [   69.768903]  process_one_work+0x208/0x5e8
11:33:45.116: [   69.768925]  worker_thread+0x1ac/0x34c
11:33:45.116: [   69.768947]  kthread+0x12c/0x208
11:33:45.116: [   69.768966]  ret_from_fork+0x10/0x20
11:33:45.116: [   69.768987] irq event stamp: 666314
11:33:45.116: [   69.768996] hardirqs last  enabled at (666313): 
[<ffff80008014fca8>] vprintk_emit+0x3b0/0x3d0
11:33:45.116: [   69.769020] hardirqs last disabled at (666314): 
[<ffff800081479a38>] el1_dbg+0x24/0x8c
11:33:45.116: [   69.769039] softirqs last  enabled at (666010): 
[<ffff8000800bc290>] handle_softirqs+0x4a0/0x4b8
11:33:45.116: [   69.769064] softirqs last disabled at (666005): 
[<ffff8000800105b0>] __do_softirq+0x14/0x20
11:33:45.116: [   69.769083] ---[ end trace 0000000000000000 ]---
11:33:45.116: [   69.769794] ------------[ cut here ]------------
11:33:45.116: [   69.769806] WARNING: CPU: 0 PID: 102 at 
drivers/gpu/drm/display/drm_dp_helper.c:2179 drm_dp_aux_get_crc+0xbc/0xd0
11:33:45.116: [   69.769832] Modules linked in:
11:33:45.116: [   69.769850] CPU: 0 UID: 0 PID: 102 Comm: kworker/0:2 
Tainted: G        W          6.14.0-rc4-g5dbf0298b72f #1
11:33:45.116: [   69.769872] Tainted: [W]=WARN
11:33:45.116: [   69.769881] Hardware name: Google Kevin (DT)
11:33:45.116: [   69.769892] Workqueue: events drm_dp_aux_crc_work
11:33:45.116: [   69.769914] pstate: 60000005 (nZCv daif -PAN -UAO -TCO 
-DIT -SSBS BTYPE=--)
11:33:45.116: [   69.769931] pc : drm_dp_aux_get_crc+0xbc/0xd0
11:33:45.116: [   69.769947] lr : drm_dp_aux_get_crc+0x3c/0xd0
11:33:45.116: [   69.769963] sp : ffff80008476bcd0
11:33:45.116: [   69.769972] x29: ffff80008476bcd0 x28: 0000000000000000 
x27: 0000000000000000
11:33:45.116: [   69.770007] x26: ffff800082cf0e80 x25: ffff00000012a005 
x24: ffff800082cf3000
11:33:45.116: [   69.770042] x23: 0000000000000000 x22: ffff0000f74ebf40 
x21: ffff800082036df8
11:33:45.116: [   69.770077] x20: ffff80008476bd42 x19: ffff0000054dcb88 
x18: 000000000000024d
11:33:45.116: [   69.770112] x17: 000000040044ffff x16: 00500072b5503510 
x15: 0000000000000001
11:33:45.116: [   69.770147] x14: 00000000000e0000 x13: 0000000000000000 
x12: 0000000000000000
11:33:45.116: [   69.770180] x11: 0000000000000078 x10: 0000000000000000 
x9 : ffff800083a57530
11:33:45.116: [   69.770215] x8 : ffff800083e6f000 x7 : 0000000000000001 
x6 : ffff800082036ca8
11:33:45.116: [   69.770249] x5 : 0000000000000000 x4 : ffff000006f5a098 
x3 : ffff800082036c20
11:33:45.116: [   69.770282] x2 : 0000000000000000 x1 : 0000000000000000 
x0 : 0000000000000000
11:33:45.116: [   69.770315] Call trace:
11:33:45.116: [   69.770324]  drm_dp_aux_get_crc+0xbc/0xd0 (P)
11:33:45.116: [   69.770344]  drm_dp_aux_crc_work+0x6c/0x15c
11:33:45.116: [   69.770363]  process_one_work+0x208/0x5e8
11:33:45.116: [   69.770385]  worker_thread+0x1ac/0x34c
11:33:45.116: [   69.770407]  kthread+0x12c/0x208
11:33:45.116: [   69.770427]  ret_from_fork+0x10/0x20
11:33:45.116: [   69.770448] irq event stamp: 666368
11:33:45.116: [   69.770457] hardirqs last  enabled at (666367): 
[<ffff8000801a496c>] ktime_get+0x130/0x174
11:33:45.116: [   69.770477] hardirqs last disabled at (666368): 
[<ffff800081479a38>] el1_dbg+0x24/0x8c
11:33:45.116: [   69.770496] softirqs last  enabled at (666010): 
[<ffff8000800bc290>] handle_softirqs+0x4a0/0x4b8
11:33:45.116: [   69.770521] softirqs last disabled at (666005): 
[<ffff8000800105b0>] __do_softirq+0x14/0x20
11:33:45.116: [   69.770540] ---[ end trace 0000000000000000 ]---
11:33:45.116: [   69.773999] ------------[ cut here ]------------
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Failed assertion: pipe_crc->crc_fd != -1
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Last errno: 5, Input/output error
11:33:45.119: ERROR - Igt error: Subtest 
connected-linear-tiling-1-displays-2160x1440p failed.
11:33:45.119: ERROR - Igt error: **** DEBUG ****
11:33:45.119: ERROR - Igt error: (kms_bw:273) DEBUG: Test requirement 
passed: !(pipe >= num_pipes)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Test 
requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Test 
requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes
11:33:45.119: ERROR - Igt error: (kms_bw:273) DEBUG: Test requirement 
passed: data->output[0]
11:33:45.119: ERROR - Igt error: (kms_bw:273) DEBUG: Test requirement 
passed: !(physical && pipe >= data->connected_outputs)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_fb-DEBUG: 
igt_create_fb_with_bo_size(width=2160, height=1440, 
format=XR24(0x34325258), modifier=0x0, size=0)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_fb-DEBUG: 
igt_create_fb_with_bo_size(handle=1, pitch=8640)
11:33:45.119: ERROR - Igt error: (kms_bw:273) ioctl_wrappers-DEBUG: Test 
requirement passed: igt_has_fb_modifiers(fd)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_fb-DEBUG: Test 
requirement passed: cairo_surface_status(fb->cairo_surface) == 
CAIRO_STATUS_SUCCESS
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
eDP-1: set_pipe(A)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
eDP-1: Selecting pipe A
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
A.0: plane_set_fb(55)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
A.0: plane_set_size (2160x1440)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
A.0: fb_set_position(0,0)
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
A.0: fb_set_size(2160x1440)
11:33:45.119: ERROR - Igt error: (kms_bw:273) INFO: Assigning pipe A to 
output eDP-1 with mode 2160x1440p
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
commit {
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "GAMMA_LUT" to 0x0/0
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "MODE_ID" to 0x39/57
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "ACTIVE" to 0x1/1
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "VRR_ENABLED" to 0x0/0
11:33:45.119: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.0, fb 55
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_W" to 0x8700000/141557760
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_H" to 0x5a00000/94371840
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_W" to 0x870/2160
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_H" to 0x5a0/1440
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "FB_ID" to 0x37/55
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_ID" to 0x26/38
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.1, fb 0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "FB_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.2, fb 0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "FB_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.3, fb 0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "FB_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "GAMMA_LUT" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "MODE_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "ACTIVE" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "VRR_ENABLED" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: B.0, fb 0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "FB_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: B.1, fb 0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_X" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_W" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_H" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "FB_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "rotation" to 0x1/1
11:33:45.120: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  eDP-1: preparing atomic, pipe: A
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: eDP-1: 
Setting property "CRTC_ID" to 0x26/38
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: }
11:33:45.121: ERROR - Igt error: (kms_bw:273) DEBUG: Test requirement 
passed: !(ret != 0)
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
commit {
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "GAMMA_LUT" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "MODE_ID" to 0x39/57
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "ACTIVE" to 0x1/1
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe A: 
Setting property "VRR_ENABLED" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.0, fb 55
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_W" to 0x8700000/141557760
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_H" to 0x5a00000/94371840
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_W" to 0x870/2160
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_H" to 0x5a0/1440
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "FB_ID" to 0x37/55
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_ID" to 0x26/38
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.0: 
Setting property "rotation" to 0x1/1
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.1, fb 0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "FB_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.1: 
Setting property "rotation" to 0x1/1
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.2, fb 0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "FB_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.2: 
Setting property "rotation" to 0x1/1
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: A.3, fb 0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "FB_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane A.3: 
Setting property "rotation" to 0x1/1
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "GAMMA_LUT" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "MODE_ID" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "ACTIVE" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: Pipe B: 
Setting property "VRR_ENABLED" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: B.0, fb 0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_Y" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_W" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_H" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_X" to 0x0/0
11:33:45.121: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_W" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_H" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "FB_ID" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.0: 
Setting property "rotation" to 0x1/1
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  populating plane data: B.1, fb 0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_X" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_Y" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_W" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_H" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_X" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_Y" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_W" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_H" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "FB_ID" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_ID" to 0x0/0
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: plane B.1: 
Setting property "rotation" to 0x1/1
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: 
  eDP-1: preparing atomic, pipe: A
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: eDP-1: 
Setting property "CRTC_ID" to 0x26/38
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_kms-DEBUG: display: }
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Test assertion failure function igt_pipe_crc_start, file 
../lib/igt_pipe_crc.c:387:
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Failed assertion: pipe_crc->crc_fd != -1
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_pipe_crc-CRITICAL: 
Last errno: 5, Input/output error
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO: Stack trace:
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #0 
../lib/igt_core.c:2055 __igt_fail_assert()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #1 
../lib/igt_pipe_crc.c:433 igt_pipe_crc_get_crcs()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #2 
../lib/igt_pipe_crc.c:592 igt_pipe_crc_collect_crc()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #3 
../tests/kms_bw.c:249 run_test_linear_tiling()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #4 
../tests/kms_bw.c:295 __igt_unique____real_main264()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #5 
../tests/kms_bw.c:264 main()
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #6 
[__libc_init_first+0x80]
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #7 
[__libc_start_main+0x98]
11:33:45.122: ERROR - Igt error: (kms_bw:273) igt_core-INFO:   #8 
[_start+0x30]
11:33:45.122: ERROR - Igt error: ****  END  ****
11:33:45.122: ERROR - Test 
kms_bw at connected-linear-tiling-1-displays-2160x1440p: Fail: See 
"/results/igt.kms_bw at connected-linear-tiling-1-displays-2160x1440p.log"
11:33:45.122: DEBUG - End test 
kms_bw at connected-linear-tiling-1-displays-2160x1440p

Pipeline: https://gitlab.freedesktop.org/vigneshraman/linux/-/jobs/72651218

Please could you have a look at these test results and let us know if 
you need more information. Thank you.

Regards,
Vignesh


From vignesh.raman at collabora.com  Thu Mar 13 03:31:36 2025
From: vignesh.raman at collabora.com (Vignesh Raman)
Date: Thu, 13 Mar 2025 16:01:36 +0530
Subject: drm-ci: rockchip: kms_bw@linear-tiling-1-displays-3840x2160p flake
Message-ID: <63dfd5b7-8a54-44a3-9530-f8dcd77a21d1@collabora.com>

Hi Maintainers,

There are some flake test reported for rockchip driver testing in drm-ci.

# Board Name: rk3399-gru-kevin
# Failure Rate: 20
# IGT Version: 1.30-g04bedb923
# Linux Version: 6.14.0-rc4
kms_bw at linear-tiling-1-displays-3840x2160p

11:38:08.782: DEBUG - Begin test kms_bw at linear-tiling-1-displays-3840x2160p
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Test assertion failure function igt_pipe_crc_start, file 
../lib/igt_pipe_crc.c:387:
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Failed assertion: pipe_crc->crc_fd != -1
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Last errno: 5, Input/output error
11:38:08.782: ERROR - Igt error: Subtest 
linear-tiling-1-displays-3840x2160p failed.
11:38:08.782: ERROR - Igt error: **** DEBUG ****
11:38:08.782: ERROR - Igt error: (kms_bw:1520) DEBUG: Test requirement 
passed: !(pipe >= num_pipes)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Test 
requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Test 
requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes
11:38:08.782: ERROR - Igt error: (kms_bw:1520) DEBUG: Test requirement 
passed: data->output[0]
11:38:08.782: ERROR - Igt error: (kms_bw:1520) DEBUG: Test requirement 
passed: !(physical && pipe >= data->connected_outputs)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_fb-DEBUG: 
igt_create_fb_with_bo_size(width=3840, height=2160, 
format=XR24(0x34325258), modifier=0x0, size=0)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_fb-DEBUG: 
igt_create_fb_with_bo_size(handle=1, pitch=15360)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) ioctl_wrappers-DEBUG: 
Test requirement passed: igt_has_fb_modifiers(fd)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_fb-DEBUG: Test 
requirement passed: cairo_surface_status(fb->cairo_surface) == 
CAIRO_STATUS_SUCCESS
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
eDP-1: set_pipe(A)
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
eDP-1: Selecting pipe A
11:38:08.782: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
A.0: plane_set_fb(55)
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
A.0: plane_set_size (3840x2160)
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
A.0: fb_set_position(0,0)
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
A.0: fb_set_size(3840x2160)
11:38:08.783: ERROR - Igt error: (kms_bw:1520) INFO: Assigning pipe A to 
output eDP-1 with mode 3840x2160p
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
commit {
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "GAMMA_LUT" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "MODE_ID" to 0x39/57
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "ACTIVE" to 0x1/1
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "VRR_ENABLED" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.0, fb 55
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_W" to 0xf000000/251658240
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_H" to 0x8700000/141557760
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_W" to 0xf00/3840
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_H" to 0x870/2160
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "FB_ID" to 0x37/55
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_ID" to 0x26/38
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "rotation" to 0x1/1
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.1, fb 0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_W" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_H" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_W" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_H" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "FB_ID" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "rotation" to 0x1/1
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.2, fb 0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_W" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_H" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_W" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_H" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "FB_ID" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "rotation" to 0x1/1
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.3, fb 0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_W" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_H" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_X" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.783: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "FB_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "rotation" to 0x1/1
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "GAMMA_LUT" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "MODE_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "ACTIVE" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "VRR_ENABLED" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: B.0, fb 0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "FB_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "rotation" to 0x1/1
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: B.1, fb 0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "FB_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "rotation" to 0x1/1
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   eDP-1: preparing atomic, pipe: A
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: eDP-1: 
Setting property "CRTC_ID" to 0x26/38
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: }
11:38:08.784: ERROR - Igt error: (kms_bw:1520) DEBUG: Test requirement 
passed: !(ret != 0)
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
commit {
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "GAMMA_LUT" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "MODE_ID" to 0x39/57
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "ACTIVE" to 0x1/1
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe A: 
Setting property "VRR_ENABLED" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.0, fb 55
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_W" to 0xf000000/251658240
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "SRC_H" to 0x8700000/141557760
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_W" to 0xf00/3840
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_H" to 0x870/2160
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "FB_ID" to 0x37/55
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "CRTC_ID" to 0x26/38
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.0: 
Setting property "rotation" to 0x1/1
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.1, fb 0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_X" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_Y" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_W" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "SRC_H" to 0x0/0
11:38:08.784: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "FB_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.1: 
Setting property "rotation" to 0x1/1
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.2, fb 0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "SRC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "FB_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.2: 
Setting property "rotation" to 0x1/1
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: A.3, fb 0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "SRC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "FB_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane A.3: 
Setting property "rotation" to 0x1/1
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "GAMMA_LUT" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "MODE_ID" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "ACTIVE" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: Pipe B: 
Setting property "VRR_ENABLED" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: B.0, fb 0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_Y" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_W" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "SRC_H" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_X" to 0x0/0
11:38:08.785: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_W" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_H" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "FB_ID" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.0: 
Setting property "rotation" to 0x1/1
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   populating plane data: B.1, fb 0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_X" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_Y" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_W" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "SRC_H" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_X" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_Y" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_W" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_H" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "FB_ID" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "CRTC_ID" to 0x0/0
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: plane B.1: 
Setting property "rotation" to 0x1/1
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: 
   eDP-1: preparing atomic, pipe: A
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: eDP-1: 
Setting property "CRTC_ID" to 0x26/38
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_kms-DEBUG: display: }
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Test assertion failure function igt_pipe_crc_start, file 
../lib/igt_pipe_crc.c:387:
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Failed assertion: pipe_crc->crc_fd != -1
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_pipe_crc-CRITICAL: 
Last errno: 5, Input/output error
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO: Stack trace:
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #0 
../lib/igt_core.c:2055 __igt_fail_assert()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #1 
../lib/igt_pipe_crc.c:433 igt_pipe_crc_get_crcs()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #2 
../lib/igt_pipe_crc.c:592 igt_pipe_crc_collect_crc()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #3 
../tests/kms_bw.c:249 run_test_linear_tiling()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #4 
../tests/kms_bw.c:287 __igt_unique____real_main264()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #5 
../tests/kms_bw.c:264 main()
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #6 
[__libc_init_first+0x80]
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #7 
[__libc_start_main+0x98]
11:38:08.786: ERROR - Igt error: (kms_bw:1520) igt_core-INFO:   #8 
[_start+0x30]
11:38:08.786: ERROR - Igt error: ****  END  ****
11:38:08.786: ERROR - Test kms_bw at linear-tiling-1-displays-3840x2160p: 
Fail: See "/results/igt.kms_bw at linear-tiling-1-displays-3840x2160p.log"
11:38:08.786: DEBUG - End test kms_bw at linear-tiling-1-displays-3840x2160p

Pipeline: https://gitlab.freedesktop.org/vigneshraman/linux/-/jobs/72651219

Please could you have a look at these test results and let us know if 
you need more information. Thank you.

Regards,
Vignesh


From linux.amoon at gmail.com  Thu Mar 13 03:35:18 2025
From: linux.amoon at gmail.com (Anand Moon)
Date: Thu, 13 Mar 2025 16:05:18 +0530
Subject: [PATCH v4 4/4] drivers/thermal/exymos: Use guard notation when
 acquiring mutex
In-Reply-To: <43506f83-13d7-46c5-b022-473ac78f0cab@kernel.org>
References: <20250310143450.8276-1-linux.amoon@gmail.com> <20250310143450.8276-5-linux.amoon@gmail.com>
 <25fa661b-98e4-468b-bb4d-4a2c95f32b71@kernel.org> <CANAwSgTeZ83oqatrsWQxT+4RYwEtEqma=R4XX_iGrP2N=phz9Q@mail.gmail.com>
 <43506f83-13d7-46c5-b022-473ac78f0cab@kernel.org>
Message-ID: <CANAwSgQeE0NQp_xwWcYBgZVQnm1N4PaQbaoMXGyFK4KKWAzxNw@mail.gmail.com>

Hi Krzysztof,

On Thu, 13 Mar 2025 at 13:19, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 12/03/2025 15:59, Anand Moon wrote:
> >>
> >>> +          mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
> >>> +
> >>>  /*
> >>>   * TMU treats temperature as a mapped temperature code.
> >>>   * The temperature is converted differently depending on the calibration type.
> >>> @@ -256,7 +260,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
> >>>       unsigned int status;
> >>>       int ret = 0;
> >>>
> >>> -     mutex_lock(&data->lock);
> >>> +     guard(mutex)(&data->lock);
> >>
> >> Which you do not use... Please don't use cleanup.h if you do not know
> >> it. It leads to bugs.
> >>
> > Ok, I will drop this include of cleanup.h.
>
> So the guards as well...
>
Ok I will drop this patch thanks.

> Best regards,
> Krzysztof

Thanks
-Anand


From miko.lenczewski at arm.com  Thu Mar 13 03:41:12 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Thu, 13 Mar 2025 10:41:12 +0000
Subject: [PATCH v3 3/3] arm64/mm: Elide tlbi in contpte_convert() under BBML2
In-Reply-To: <20250313104111.24196-2-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
Message-ID: <20250313104111.24196-5-miko.lenczewski@arm.com>

When converting a region via contpte_convert() to use mTHP, we have two
different goals. We have to mark each entry as contiguous, and we would
like to smear the dirty and young (access) bits across all entries in
the contiguous block. Currently, we do this by first accumulating the
dirty and young bits in the block, using an atomic
__ptep_get_and_clear() and the relevant pte_{dirty,young}() calls,
performing a tlbi, and finally smearing the correct bits across the
block using __set_ptes().

This approach works fine for BBM level 0, but with support for BBM level
2 we are allowed to reorder the tlbi to after setting the pagetable
entries. This reordering reduces the likelyhood of a concurrent page
walk finding an invalid (not present) PTE. This reduces the likelyhood
of a fault in other threads, and improves performance marginally
(more so when there are more threads).

If we support bbml2 without conflict aborts however, we can avoid the
final flush altogether and have hardware manage the tlb entries for us.
Avoiding flushes is a win.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 arch/arm64/mm/contpte.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
index 55107d27d3f8..77ed03b30b72 100644
--- a/arch/arm64/mm/contpte.c
+++ b/arch/arm64/mm/contpte.c
@@ -68,7 +68,8 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
 			pte = pte_mkyoung(pte);
 	}
 
-	__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
+	if (!system_supports_bbml2_noabort())
+		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
 
 	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
 }
-- 
2.48.1



From michal.kubiak at intel.com  Thu Mar 13 03:43:10 2025
From: michal.kubiak at intel.com (Michal Kubiak)
Date: Thu, 13 Mar 2025 11:43:10 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9G01zGCpbw1YHNs@lore-desk>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
 <Z9Ga7gx1u3JsOemE@localhost.localdomain>
 <Z9GgHZxkSqFCkwMg@lore-desk>
 <Z9GtKwAuEx+7HKjR@localhost.localdomain>
 <Z9G01zGCpbw1YHNs@lore-desk>
Message-ID: <Z9K2vujs6+yhiXXh@localhost.localdomain>

On Wed, Mar 12, 2025 at 05:22:47PM +0100, Lorenzo Bianconi wrote:
> > On Wed, Mar 12, 2025 at 03:54:21PM +0100, Lorenzo Bianconi wrote:
> > > > On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> > > > > The system occasionally crashes dereferencing a NULL pointer when it is
> > > > > forwarding constant, high load bidirectional traffic.

[...]

> > 
> > > 
> > > > 
> > > > > +		if (!eth->ports[i])
> > > > > +			continue;
> > > > 
> > > > Isn't this NULL check redundant?
> > > > In the second check you compare the table element to a real pointer.
> > > 
> > > Can netdev_priv() be NULL? If not, I guess we can remove this check.
> > 
> > I guess it shouldn't be NULL since "devm_alloc_etherdev_mqs()" was
> > called, but I'm not 100% sure if there are any special cases for the "airoha"
> > driver. Maybe in such cases it would be better to check for the netdev_priv?
> > Anyway, such checks seem a bit too defensive to me.
> 
> the dev pointer can be allocated even outside of airoha_eth driver.
> This pointer is provided by the flowtable.
> I guess we can drop the NULL pointer check above, and do something like:
> 
> 	if (port && eth->ports[i] == port)
> 		return 0;
> 
> what do you think?
> 
> Regards,
> Lorenzo
> 

I think if there's a risk that 'port' can be NULL, it looks like a
reasonable solution and I'm OK with that.

Thanks,
Michal



From andre.przywara at arm.com  Thu Mar 13 03:40:42 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 13 Mar 2025 10:40:42 +0000
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <Z9KYqlfUYxRaWnGQ@a98shuttle.de>
References: <20250312193629.85417-1-michael@fossekall.de>
	<20250312193629.85417-2-michael@fossekall.de>
	<4637912.LvFx2qVVIh@jernej-laptop>
	<Z9KYqlfUYxRaWnGQ@a98shuttle.de>
Message-ID: <20250313104042.694c1856@donnerap.manchester.arm.com>

On Thu, 13 Mar 2025 09:34:50 +0100
Michael Klein <michael at fossekall.de> wrote:

Hi,

> On Thu, Mar 13, 2025 at 07:07:24AM +0100, Jernej ?krabec wrote:
> >Dne sreda, 12. marec 2025 ob 20:36:28 Srednjeevropski standardni ?as je Michael Klein napisal(a):  
> >> The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
> >> Add the corresponding nodes to the device tree.
> >>
> >> Signed-off-by: Michael Klein <michael at fossekall.de>  
> >
> >This is patch 2/2. Which one is patch 1/2? I got only one.  
> 
> https://patchwork.kernel.org/project/netdevbpf/patch/20250312193629.85417-1-michael at fossekall.de/
> 
> Sorry for any inconvenience in case I messed up the patch submission.
> 
> I made two commits for this change and submitted them via `git send-email 
> HEAD^^`. The first patch went to netdev at vger.kernel.org, the second 
> to linux-arm-kernel at lists.infradead.org, which seems logical. Have I 
> done something wrong?

Well, for those really small "series" it's probably better to send all
patches to everyone, especially if the first patch gives some context,
without which the second leaves people (like me) scratching their head.
Also in this case a cover letter would help
(git format-patch --cover-letter), to give some idea of what you are after.

Cheers,
Andre


> 
> >Best regards,
> >Jernej  
> 
> Michael
> 
> >  
> >> ---
> >>  .../boot/dts/allwinner/sun7i-a20-bananapi.dts | 27 +++++++++++++++++++
> >>  1 file changed, 27 insertions(+)
> >>
> >> diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> >> index 46ecf9db2324..4976453ed192 100644
> >> --- a/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> >> +++ b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts
> >> @@ -48,6 +48,7 @@
> >>
> >>  #include <dt-bindings/gpio/gpio.h>
> >>  #include <dt-bindings/interrupt-controller/irq.h>
> >> +#include <dt-bindings/leds/common.h>
> >>
> >>  / {
> >>  	model = "LeMaker Banana Pi";
> >> @@ -169,6 +170,32 @@ &ir0 {
> >>  &gmac_mdio {
> >>  	phy1: ethernet-phy at 1 {
> >>  		reg = <1>;
> >> +
> >> +		leds {
> >> +			#address-cells = <1>;
> >> +			#size-cells = <0>;
> >> +
> >> +			led at 0 {
> >> +				reg = <0>;
> >> +				color = <LED_COLOR_ID_GREEN>;
> >> +				default-state = "keep";
> >> +				linux,default-trigger = "netdev";
> >> +			};
> >> +
> >> +			led at 1 {
> >> +				reg = <1>;
> >> +				color = <LED_COLOR_ID_AMBER>;
> >> +				default-state = "keep";
> >> +				linux,default-trigger = "netdev";
> >> +			};
> >> +
> >> +			led at 2 {
> >> +				reg = <2>;
> >> +				color = <LED_COLOR_ID_BLUE>;
> >> +				default-state = "keep";
> >> +				linux,default-trigger = "netdev";
> >> +			};
> >> +		};
> >>  	};
> >>  };
> >>
> >>  
> >
> >
> >
> >
> >  
> 



From sumit.garg at kernel.org  Thu Mar 13 03:41:09 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Thu, 13 Mar 2025 16:11:09 +0530
Subject: [PATCH v6 03/10] optee: account for direction while converting
 parameters
In-Reply-To: <20250305130634.1850178-4-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org>
Message-ID: <Z9K2RQYuXSJc8Y1E@sumit-X1>

Hi Jens,

On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> The OP-TEE backend driver has two internal function pointers to convert
> between the subsystem type struct tee_param and the OP-TEE type struct
> optee_msg_param.
> 
> The conversion is done from one of the types to the other, which is then
> involved in some operation and finally converted back to the original
> type. When converting to prepare the parameters for the operation, all
> fields must be taken into account, but then converting back, it's enough
> to update only out-values and out-sizes. So, an update_out parameter is
> added to the conversion functions to tell if all or only some fields
> must be copied.
> 
> This is needed in a later patch where it might get confusing when
> converting back in from_msg_param() callback since an allocated
> restricted SHM can be using the sec_world_id of the used restricted
> memory pool and that doesn't translate back well.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/call.c          | 10 ++--
>  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
>  drivers/tee/optee/optee_private.h | 42 +++++++++++------
>  drivers/tee/optee/rpc.c           | 31 +++++++++----
>  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
>  5 files changed, 144 insertions(+), 58 deletions(-)
> 
> diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> index 16eb953e14bb..f1533b894726 100644
> --- a/drivers/tee/optee/call.c
> +++ b/drivers/tee/optee/call.c
> @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
>  	export_uuid(msg_arg->params[1].u.octets, &client_uuid);
>  
>  	rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> -				      arg->num_params, param);
> +				      arg->num_params, param,
> +				      false /*!update_out*/);
>  	if (rc)
>  		goto out;
>  
> @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
>  	}
>  
>  	if (optee->ops->from_msg_param(optee, param, arg->num_params,
> -				       msg_arg->params + 2)) {
> +				       msg_arg->params + 2,
> +				       true /*update_out*/)) {
>  		arg->ret = TEEC_ERROR_COMMUNICATION;
>  		arg->ret_origin = TEEC_ORIGIN_COMMS;
>  		/* Close session again to avoid leakage */
> @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
>  	msg_arg->cancel_id = arg->cancel_id;
>  
>  	rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> -				      param);
> +				      param, false /*!update_out*/);
>  	if (rc)
>  		goto out;
>  
> @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
>  	}
>  
>  	if (optee->ops->from_msg_param(optee, param, arg->num_params,
> -				       msg_arg->params)) {
> +				       msg_arg->params, true /*update_out*/)) {
>  		msg_arg->ret = TEEC_ERROR_COMMUNICATION;
>  		msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
>  	}
> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index 4ca1d5161b82..e4b08cd195f3 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
>   */
>  
>  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> -				   u32 attr, const struct optee_msg_param *mp)
> +				   u32 attr, const struct optee_msg_param *mp,
> +				   bool update_out)
>  {
>  	struct tee_shm *shm = NULL;
>  	u64 offs_high = 0;
>  	u64 offs_low = 0;
>  
> +	if (update_out) {
> +		if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> +			return;
> +		goto out;
> +	}
> +
>  	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
>  		  attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> -	p->u.memref.size = mp->u.fmem.size;
>  
>  	if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
>  		shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
>  		offs_high = mp->u.fmem.offs_high;
>  	}
>  	p->u.memref.shm_offs = offs_low | offs_high << 32;
> +out:
> +	p->u.memref.size = mp->u.fmem.size;
>  }
>  
>  /**
> @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
>   * @params:	subsystem internal parameter representation
>   * @num_params:	number of elements in the parameter arrays
>   * @msg_params:	OPTEE_MSG parameters
> + * @update_out: update parameter for output only
>   *
>   * Returns 0 on success or <0 on failure
>   */
>  static int optee_ffa_from_msg_param(struct optee *optee,
>  				    struct tee_param *params, size_t num_params,
> -				    const struct optee_msg_param *msg_params)
> +				    const struct optee_msg_param *msg_params,
> +				    bool update_out)
>  {
>  	size_t n;
>  
> @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
>  
>  		switch (attr) {
>  		case OPTEE_MSG_ATTR_TYPE_NONE:
> +			if (update_out)
> +				break;
>  			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
>  			memset(&p->u, 0, sizeof(p->u));
>  			break;
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> -			optee_from_msg_param_value(p, attr, mp);
> +			optee_from_msg_param_value(p, attr, mp, update_out);
>  			break;
>  		case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
>  		case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
>  		case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> -			from_msg_param_ffa_mem(optee, p, attr, mp);
> +			from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
>  			break;
>  		default:
>  			return -EINVAL;
> @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
>  }
>  
>  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> -				const struct tee_param *p)
> +				const struct tee_param *p, bool update_out)
>  {
>  	struct tee_shm *shm = p->u.memref.shm;
>  
> +	if (update_out) {
> +		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> +			return 0;
> +		goto out;
> +	}
> +
>  	mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
>  		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
>  
> @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
>  		memset(&mp->u, 0, sizeof(mp->u));
>  		mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
>  	}
> +out:
>  	mp->u.fmem.size = p->u.memref.size;
>  
>  	return 0;
> @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
>   * @optee:	main service struct
>   * @msg_params:	OPTEE_MSG parameters
>   * @num_params:	number of elements in the parameter arrays
> - * @params:	subsystem itnernal parameter representation
> + * @params:	subsystem internal parameter representation
> + * @update_out: update parameter for output only
>   * Returns 0 on success or <0 on failure
>   */
>  static int optee_ffa_to_msg_param(struct optee *optee,
>  				  struct optee_msg_param *msg_params,
>  				  size_t num_params,
> -				  const struct tee_param *params)
> +				  const struct tee_param *params,
> +				  bool update_out)
>  {
>  	size_t n;
>  
> @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
>  
>  		switch (p->attr) {
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> +			if (update_out)
> +				break;
>  			mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
>  			memset(&mp->u, 0, sizeof(mp->u));
>  			break;
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> -			optee_to_msg_param_value(mp, p);
> +			optee_to_msg_param_value(mp, p, update_out);
>  			break;
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> -			if (to_msg_param_ffa_mem(mp, p))
> +			if (to_msg_param_ffa_mem(mp, p, update_out))
>  				return -EINVAL;
>  			break;
>  		default:

Can we rather handle it as follows to improve code readability and
maintainence long term? Ditto for all other places.

static int optee_ffa_to_msg_param(struct optee *optee,
                                  struct optee_msg_param *msg_params,
                                  size_t num_params,
                                  const struct tee_param *params,
                                  bool update_out)
{
        size_t n;

        for (n = 0; n < num_params; n++) {
                const struct tee_param *p = params + n;
                struct optee_msg_param *mp = msg_params + n;

                if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
                     p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
                     p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
                    continue;

                switch (p->attr) {
                case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
                        mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
                        memset(&mp->u, 0, sizeof(mp->u));
                        break;
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
                        optee_to_msg_param_value(mp, p);
                        break;
                case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
                        if (to_msg_param_ffa_mem(mp, p))
                                return -EINVAL;
                        break;
                default:
                        return -EINVAL;
                }
        }

        return 0;
}

-Sumit

> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index dc0f355ef72a..20eda508dbac 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -185,10 +185,12 @@ struct optee_ops {
>  				bool system_thread);
>  	int (*to_msg_param)(struct optee *optee,
>  			    struct optee_msg_param *msg_params,
> -			    size_t num_params, const struct tee_param *params);
> +			    size_t num_params, const struct tee_param *params,
> +			    bool update_out);
>  	int (*from_msg_param)(struct optee *optee, struct tee_param *params,
>  			      size_t num_params,
> -			      const struct optee_msg_param *msg_params);
> +			      const struct optee_msg_param *msg_params,
> +			      bool update_out);
>  };
>  
>  /**
> @@ -316,23 +318,35 @@ void optee_release(struct tee_context *ctx);
>  void optee_release_supp(struct tee_context *ctx);
>  
>  static inline void optee_from_msg_param_value(struct tee_param *p, u32 attr,
> -					      const struct optee_msg_param *mp)
> +					      const struct optee_msg_param *mp,
> +					      bool update_out)
>  {
> -	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
> -		  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> -	p->u.value.a = mp->u.value.a;
> -	p->u.value.b = mp->u.value.b;
> -	p->u.value.c = mp->u.value.c;
> +	if (!update_out)
> +		p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
> +			  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> +
> +	if (attr == OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT ||
> +	    attr == OPTEE_MSG_ATTR_TYPE_VALUE_INOUT || !update_out) {
> +		p->u.value.a = mp->u.value.a;
> +		p->u.value.b = mp->u.value.b;
> +		p->u.value.c = mp->u.value.c;
> +	}
>  }
>  
>  static inline void optee_to_msg_param_value(struct optee_msg_param *mp,
> -					    const struct tee_param *p)
> +					    const struct tee_param *p,
> +					    bool update_out)
>  {
> -	mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
> -		   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
> -	mp->u.value.a = p->u.value.a;
> -	mp->u.value.b = p->u.value.b;
> -	mp->u.value.c = p->u.value.c;
> +	if (!update_out)
> +		mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
> +			   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
> +
> +	if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
> +	    p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || !update_out) {
> +		mp->u.value.a = p->u.value.a;
> +		mp->u.value.b = p->u.value.b;
> +		mp->u.value.c = p->u.value.c;
> +	}
>  }
>  
>  void optee_cq_init(struct optee_call_queue *cq, int thread_count);
> diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
> index ebbbd42b0e3e..580e6b9b0606 100644
> --- a/drivers/tee/optee/rpc.c
> +++ b/drivers/tee/optee/rpc.c
> @@ -63,7 +63,7 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
>  	}
>  
>  	if (optee->ops->from_msg_param(optee, params, arg->num_params,
> -				       arg->params))
> +				       arg->params, false /*!update_out*/))
>  		goto bad;
>  
>  	for (i = 0; i < arg->num_params; i++) {
> @@ -107,7 +107,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
>  	} else {
>  		params[3].u.value.a = msg.len;
>  		if (optee->ops->to_msg_param(optee, arg->params,
> -					     arg->num_params, params))
> +					     arg->num_params, params,
> +					     true /*update_out*/))
>  			arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		else
>  			arg->ret = TEEC_SUCCESS;
> @@ -188,6 +189,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
>  static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
>  				struct optee_msg_arg *arg)
>  {
> +	bool update_out = false;
>  	struct tee_param *params;
>  
>  	arg->ret_origin = TEEC_ORIGIN_COMMS;
> @@ -200,15 +202,21 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
>  	}
>  
>  	if (optee->ops->from_msg_param(optee, params, arg->num_params,
> -				       arg->params)) {
> +				       arg->params, update_out)) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		goto out;
>  	}
>  
>  	arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
>  
> +	/*
> +	 * Special treatment for OPTEE_RPC_CMD_SHM_ALLOC since input is a
> +	 * value type, but the output is a memref type.
> +	 */
> +	if (arg->cmd != OPTEE_RPC_CMD_SHM_ALLOC)
> +		update_out = true;
>  	if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
> -				     params))
> +				     params, update_out))
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  out:
>  	kfree(params);
> @@ -270,7 +278,7 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
>  
>  	if (arg->num_params != ARRAY_SIZE(params) ||
>  	    optee->ops->from_msg_param(optee, params, arg->num_params,
> -				       arg->params) ||
> +				       arg->params, false /*!update_out*/) ||
>  	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		return;
> @@ -280,7 +288,8 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
>  	params[0].u.value.b = 0;
>  	params[0].u.value.c = 0;
>  	if (optee->ops->to_msg_param(optee, arg->params,
> -				     arg->num_params, params)) {
> +				     arg->num_params, params,
> +				     true /*update_out*/)) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		return;
>  	}
> @@ -324,7 +333,7 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
>  
>  	if (arg->num_params != ARRAY_SIZE(params) ||
>  	    optee->ops->from_msg_param(optee, params, arg->num_params,
> -				       arg->params) ||
> +				       arg->params, false /*!update_out*/) ||
>  	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
>  	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> @@ -358,7 +367,8 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
>  	params[0].u.value.b = rdev->descr.capacity;
>  	params[0].u.value.c = rdev->descr.reliable_wr_count;
>  	if (optee->ops->to_msg_param(optee, arg->params,
> -				     arg->num_params, params)) {
> +				     arg->num_params, params,
> +				     true /*update_out*/)) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		return;
>  	}
> @@ -384,7 +394,7 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
>  
>  	if (arg->num_params != ARRAY_SIZE(params) ||
>  	    optee->ops->from_msg_param(optee, params, arg->num_params,
> -				       arg->params) ||
> +				       arg->params, false /*!update_out*/) ||
>  	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
>  	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> @@ -401,7 +411,8 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
>  		goto out;
>  	}
>  	if (optee->ops->to_msg_param(optee, arg->params,
> -				     arg->num_params, params)) {
> +				     arg->num_params, params,
> +				     true /*update_out*/)) {
>  		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>  		goto out;
>  	}
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index 165fadd9abc9..cfdae266548b 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -81,20 +81,26 @@ static int optee_cpuhp_disable_pcpu_irq(unsigned int cpu)
>   */
>  
>  static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
> -				  const struct optee_msg_param *mp)
> +				  const struct optee_msg_param *mp,
> +				  bool update_out)
>  {
>  	struct tee_shm *shm;
>  	phys_addr_t pa;
>  	int rc;
>  
> +	if (update_out) {
> +		if (attr == OPTEE_MSG_ATTR_TYPE_TMEM_INPUT)
> +			return 0;
> +		goto out;
> +	}
> +
>  	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
>  		  attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
> -	p->u.memref.size = mp->u.tmem.size;
>  	shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
>  	if (!shm) {
>  		p->u.memref.shm_offs = 0;
>  		p->u.memref.shm = NULL;
> -		return 0;
> +		goto out;
>  	}
>  
>  	rc = tee_shm_get_pa(shm, 0, &pa);
> @@ -103,18 +109,25 @@ static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
>  
>  	p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
>  	p->u.memref.shm = shm;
> -
> +out:
> +	p->u.memref.size = mp->u.tmem.size;
>  	return 0;
>  }
>  
>  static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
> -				   const struct optee_msg_param *mp)
> +				   const struct optee_msg_param *mp,
> +				   bool update_out)
>  {
>  	struct tee_shm *shm;
>  
> +	if (update_out) {
> +		if (attr == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT)
> +			return;
> +		goto out;
> +	}
> +
>  	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
>  		  attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
> -	p->u.memref.size = mp->u.rmem.size;
>  	shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
>  
>  	if (shm) {
> @@ -124,6 +137,8 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
>  		p->u.memref.shm_offs = 0;
>  		p->u.memref.shm = NULL;
>  	}
> +out:
> +	p->u.memref.size = mp->u.rmem.size;
>  }
>  
>  /**
> @@ -133,11 +148,13 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
>   * @params:	subsystem internal parameter representation
>   * @num_params:	number of elements in the parameter arrays
>   * @msg_params:	OPTEE_MSG parameters
> + * @update_out:	update parameter for output only
>   * Returns 0 on success or <0 on failure
>   */
>  static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
>  				size_t num_params,
> -				const struct optee_msg_param *msg_params)
> +				const struct optee_msg_param *msg_params,
> +				bool update_out)
>  {
>  	int rc;
>  	size_t n;
> @@ -149,25 +166,27 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
>  
>  		switch (attr) {
>  		case OPTEE_MSG_ATTR_TYPE_NONE:
> +			if (update_out)
> +				break;
>  			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
>  			memset(&p->u, 0, sizeof(p->u));
>  			break;
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
>  		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> -			optee_from_msg_param_value(p, attr, mp);
> +			optee_from_msg_param_value(p, attr, mp, update_out);
>  			break;
>  		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
>  		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
>  		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
> -			rc = from_msg_param_tmp_mem(p, attr, mp);
> +			rc = from_msg_param_tmp_mem(p, attr, mp, update_out);
>  			if (rc)
>  				return rc;
>  			break;
>  		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
>  		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
>  		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
> -			from_msg_param_reg_mem(p, attr, mp);
> +			from_msg_param_reg_mem(p, attr, mp, update_out);
>  			break;
>  
>  		default:
> @@ -178,20 +197,25 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
>  }
>  
>  static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
> -				const struct tee_param *p)
> +				const struct tee_param *p, bool update_out)
>  {
>  	int rc;
>  	phys_addr_t pa;
>  
> +	if (update_out) {
> +		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> +			return 0;
> +		goto out;
> +	}
> +
>  	mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
>  		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
>  
>  	mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
> -	mp->u.tmem.size = p->u.memref.size;
>  
>  	if (!p->u.memref.shm) {
>  		mp->u.tmem.buf_ptr = 0;
> -		return 0;
> +		goto out;
>  	}
>  
>  	rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
> @@ -201,19 +225,27 @@ static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
>  	mp->u.tmem.buf_ptr = pa;
>  	mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
>  		    OPTEE_MSG_ATTR_CACHE_SHIFT;
> -
> +out:
> +	mp->u.tmem.size = p->u.memref.size;
>  	return 0;
>  }
>  
>  static int to_msg_param_reg_mem(struct optee_msg_param *mp,
> -				const struct tee_param *p)
> +				const struct tee_param *p, bool update_out)
>  {
> +	if (update_out) {
> +		if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> +			return 0;
> +		goto out;
> +	}
> +
>  	mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
>  		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
>  
>  	mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
> -	mp->u.rmem.size = p->u.memref.size;
>  	mp->u.rmem.offs = p->u.memref.shm_offs;
> +out:
> +	mp->u.rmem.size = p->u.memref.size;
>  	return 0;
>  }
>  
> @@ -223,11 +255,13 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
>   * @msg_params:	OPTEE_MSG parameters
>   * @num_params:	number of elements in the parameter arrays
>   * @params:	subsystem itnernal parameter representation
> + * @update_out:	update parameter for output only
>   * Returns 0 on success or <0 on failure
>   */
>  static int optee_to_msg_param(struct optee *optee,
>  			      struct optee_msg_param *msg_params,
> -			      size_t num_params, const struct tee_param *params)
> +			      size_t num_params, const struct tee_param *params,
> +			      bool update_out)
>  {
>  	int rc;
>  	size_t n;
> @@ -238,21 +272,23 @@ static int optee_to_msg_param(struct optee *optee,
>  
>  		switch (p->attr) {
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> +			if (update_out)
> +				break;
>  			mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
>  			memset(&mp->u, 0, sizeof(mp->u));
>  			break;
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> -			optee_to_msg_param_value(mp, p);
> +			optee_to_msg_param_value(mp, p, update_out);
>  			break;
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
>  			if (tee_shm_is_dynamic(p->u.memref.shm))
> -				rc = to_msg_param_reg_mem(mp, p);
> +				rc = to_msg_param_reg_mem(mp, p, update_out);
>  			else
> -				rc = to_msg_param_tmp_mem(mp, p);
> +				rc = to_msg_param_tmp_mem(mp, p, update_out);
>  			if (rc)
>  				return rc;
>  			break;
> -- 
> 2.43.0
> 


From dsimic at manjaro.org  Thu Mar 13 03:42:17 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 13 Mar 2025 11:42:17 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores
 on RK3588j
In-Reply-To: <a56b59a21dc3c21192fe45197eee4865@manjaro.org>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <d8ce8db2-1717-40f8-b53e-24cc71a758c9@cherry.de>
 <CABjd4Yw-r-ogfwcrph4K1wbkybS25gk6LFg8wpqLG27uWdybNA@mail.gmail.com>
 <2914631.KiezcSG77Q@diego>
 <CABjd4YxF4N1tAgGUZk-oKkMUO+Q9rWHZsas9gMQdJ+TF4A1=NA@mail.gmail.com>
 <e55125ed-64fb-455e-b1e4-cebe2cf006e4@cherry.de>
 <a56b59a21dc3c21192fe45197eee4865@manjaro.org>
Message-ID: <2cf3889741f84584d8f23a4407fed08e@manjaro.org>

Hello all,

On 2025-03-12 11:34, Dragan Simic wrote:
> On 2025-03-12 11:15, Quentin Schulz wrote:
>> On 2/16/25 1:32 PM, Alexey Charkov wrote:
>>> On Sat, Feb 15, 2025 at 11:30?PM Heiko St?bner <heiko at sntech.de> 
>>> wrote:
>>>> Am Samstag, 15. Februar 2025, 19:59:44 MEZ schrieb Alexey Charkov:
>>>>> On Tue, Feb 11, 2025 at 7:32?PM Quentin Schulz 
>>>>> <quentin.schulz at cherry.de> wrote:
>>>>>> On 6/17/24 8:28 PM, Alexey Charkov wrote:
>> [...]
>>>>>>> +     };
>>>>>>> +
>>>>>>> +     cluster2_opp_table: opp-table-cluster2 {
>>>>>>> +             compatible = "operating-points-v2";
>>>>>>> +             opp-shared;
>>>>>>> +
>>>>>>> +             opp-1416000000 {
>>>>>>> +                     opp-hz = /bits/ 64 <1416000000>;
>>>>>>> +                     opp-microvolt = <750000 750000 950000>;
>>>>>>> +                     clock-latency-ns = <40000>;
>>>>>>> +             };
>>>>>>> +             opp-1608000000 {
>>>>>>> +                     opp-hz = /bits/ 64 <1608000000>;
>>>>>>> +                     opp-microvolt = <787500 787500 950000>;
>>>>>>> +                     clock-latency-ns = <40000>;
>>>>>>> +             };
>>>>>>> +             opp-1800000000 {
>>>>>>> +                     opp-hz = /bits/ 64 <1800000000>;
>>>>>>> +                     opp-microvolt = <875000 875000 950000>;
>>>>>>> +                     clock-latency-ns = <40000>;
>>>>>>> +             };
>>>>>>> +             opp-2016000000 {
>>>>>>> +                     opp-hz = /bits/ 64 <2016000000>;
>>>>>>> +                     opp-microvolt = <950000 950000 950000>;
>>>>>>> +                     clock-latency-ns = <40000>;
>>>>>>> +             };
>>>>>> 
>>>>>> opp-1800000000 and opp-2016000000 should be removed as well.
>>>>>> 
>>>>>> Did I misunderstand what Rockchip did here? Adding Kever in Cc at 
>>>>>> least
>>>>>> for awareness on Rockchip side :)
>>>>>> 
>>>>>> I guess another option could be to mark those above as
>>>>>> 
>>>>>> turbo-mode;
>>>>>> 
>>>>>> though no clue what this would entail. From a glance at cpufreq, 
>>>>>> it
>>>>>> seems that for Rockchip since we use the default cpufreq-dt, it 
>>>>>> would
>>>>>> mark those as unusable, so essentially a no-op, so better remove 
>>>>>> them
>>>>>> entirely?
>>>>> 
>>>>> I believe the opp core just marks 'turbo-mode' opps as
>>>>> CPUFREQ_BOOST_FREQ, and cpufreq-dt only passes that flag along to 
>>>>> the
>>>>> cpufreq core. But then to actually use those boost frequencies I 
>>>>> would
>>>>> guess the governor needs to somehow know the power/thermal 
>>>>> constraints
>>>>> of the chip?.. Don't know where that is defined.
>>>> 
>>>> personally I don't believe in "boost" frequencies - except when they 
>>>> are
>>>> declared officially.
>>>> 
>>>> Rockchip for the longest time maintains that running the chip 
>>>> outside
>>>> the declared power/rate envelope can reduce its overall lifetime.
>>>> 
>>>> So for Rockchip in mainline a "it runs stable for me" has never been 
>>>> a
>>>> suitable reasoning ;-) .
>>> 
>>> My key concern here was perhaps that we are looking at a file inside
>>> the Rockchip source tree which looks relevant by the name of it, but
>>> doesn't actually get included anywhere for any of the boards. This 
>>> may
>>> or may not constitute an endorsement by Rockchip of any OPPs listed
>>> there :-D
>> 
>> Rockchip support stated:
>> 
>> """
>> If you run overdrive mode, you do not need to include rk3588j.dtsi,
>> and you can change it to #incldue rk3588.dtsi to ensure that the
>> maximum frequency can reach 2GHz
>> 
>> below picture from datasheet.
>> """
>> 
>> The picture is the table 3-2 Recommended operating conditions, page 30
>> from the RK3588J datasheet, e.g.
>> https://www.lcsc.com/datasheet/lcsc_datasheet_2403201054_Rockchip-RK3588J_C22364189.pdf
>> 
>> What is overdrive?
>> 
>> """
>> Overdrive mode brings higher frequency, and the voltage will increase
>> accordingly. Under
>> the overdrive mode for a long time, the chipset may shorten the
>> lifetime, especially in high temperature condition
>> """
>> 
>> according to the same datasheet, end of the same table, page 31.
>> 
>> so this seems like a turbo-mode frequency to me.
>> 
>> Additionally, the note for the "normal mode" (the one with the lower
>> freqs) states:
>> 
>> """
>> Normal mode means the chipset works under safety voltage and 
>> frequency. For the
>> industrial environment, highly recommend to keep in normal mode, the 
>> lifetime is
>> reasonably guaranteed.
>> """
>> 
>> I believe "industrial environment" means RK3588J used in the
>> temperatures that aren't OK for the standard RK3588 variant?
> 
> Thanks a lot for obtaining these clarifications!
> 
> Yes, I'd say that in this case "industrial environment" boils down
> to the extended temperature range for the RK3588J variant.
> 
>>> I haven't seen a TRM for the J variant, nor do I have a board with
>>> RK3588J to run tests, so it would be great if Kever could chime in
>>> with how these OPPs are different from the others (or not).
>>> 
>>>> So while the situation might be strange for the rk3588j, I really 
>>>> only want
>>>> correct frequencies here please - not any pseudo "turbo freqs".
>>>> 
>>>> I don't care that much what people do on their own device{s/trees}, 
>>>> but
>>>> the devicetrees we supply centrally (and to u-boot, etc) should only
>>>> contain frequencies vetted by the manufacturer.
>>> 
>>> Fair enough. Let's just try and get another data point on whether
>>> these frequencies are vetted or not.
>> 
>> So the higher freqs seems to be vetted (and used by default on
>> Rockchip's BSP kernel), it just feels like you aren't really supposed
>> to run those higher frequencies all the time? And especially not in
>> "industrial environment"?
>> 
>> I would assume we want to stay on the safer side and remove those
>> higher frequencies? Heiko?
> 
> I agree, we should remove the higher-frequency OPPs.  I'd like
> to go through everything once again in detail and prepare a patch
> that removes the unsafe OPPs, and you could review it once it's
> on the ML, to make sure it's fine.

Just as a note, everything above (and even a bit more) is confirmed
and clearly described in the publicly available RK3588J datasheet,
which I'll provide as a reference in my upcoming patch.


From piotr.oniszczuk at gmail.com  Thu Mar 13 03:42:54 2025
From: piotr.oniszczuk at gmail.com (Piotr Oniszczuk)
Date: Thu, 13 Mar 2025 11:42:54 +0100
Subject: [PATCH v2 2/7] drm/bridge: synopsys: Add DW DPTX Controller
 support library
In-Reply-To: <381bbdeb.342.1958ce2b7f8.Coremail.andyshrk@163.com>
References: <20250312104214.525242-1-andyshrk@163.com>
 <20250312104214.525242-3-andyshrk@163.com>
 <61E9B36C-8568-4C0E-A9A7-07FF612912AA@gmail.com>
 <381bbdeb.342.1958ce2b7f8.Coremail.andyshrk@163.com>
Message-ID: <FE66F347-431A-45E1-8764-06767B7FC74E@gmail.com>



> Wiadomo?? napisana przez Andy Yan <andyshrk at 163.com> w dniu 13 mar 2025, o godz. 01:23:
> 
> 
> Hi Piotr,
> ? 2025-03-12 22:23:15?"Piotr Oniszczuk" <piotr.oniszczuk at gmail.com> ???
> 
> This series still  based on Linux 6.14 rc4.
> 
> Did you apply the three dependency patch mentioned in my cover letter?

Thx!
I noticed https://lore.kernel.org/linux-rockchip/20250302115257.188774-1-andyshrk at 163.com/ was missing
Sorry for false alarm.
Now v2 works ok for me on rock5a and rock5itx
 

From miko.lenczewski at arm.com  Thu Mar 13 03:41:09 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Thu, 13 Mar 2025 10:41:09 +0000
Subject: [PATCH v3 0/3] Initial BBML2 support for contpte_convert()
Message-ID: <20250313104111.24196-2-miko.lenczewski@arm.com>

Hi All,

This patch series adds adding initial support for eliding
break-before-make requirements on systems that support BBML2 and
additionally guarantee to never raise a conflict abort.

This support elides a TLB invalidation in contpte_convert(). This
leads to a 12% improvement when executing a microbenchmark designed
to force the pathological path where contpte_convert() gets called.
This represents an 80% reduction in the cost of calling
contpte_convert().

This series is based on v6.14-rc4 (d082ecbc71e9).

Patch 1 implements an allow-list of cpus that support BBML2, but with
the additional constraint of never causing TLB conflict aborts. We
settled on this constraint because we will use the feature for kernel
mappings in the future, for which we cannot handle conflict aborts
safely.

Yang Shi has a series at [1] that aims to use BBML2 to enable splitting
the linear map at runtime. This series partially overlaps with it to add
the cpu feature. We believe this series is fully compatible with Yang's
requirements and could go first.

[1]:
  https://lore.kernel.org/linux-arm-kernel/20250304222018.615808-1-yang at os.amperecomputing.com/

Miko?aj Lenczewski (3):
  arm64: Add BBM Level 2 cpu feature
  iommu/arm: Add BBM Level 2 smmu feature
  arm64/mm: Elide tlbi in contpte_convert() under BBML2

 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 11 +++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  6 ++
 arch/arm64/kernel/cpufeature.c                | 76 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/mm/contpte.c                       |  3 +-
 arch/arm64/tools/cpucaps                      |  1 +
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  4 +
 11 files changed, 113 insertions(+), 1 deletion(-)

-- 
2.48.1



From miko.lenczewski at arm.com  Thu Mar 13 03:41:10 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Thu, 13 Mar 2025 10:41:10 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313104111.24196-2-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
Message-ID: <20250313104111.24196-3-miko.lenczewski@arm.com>

The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
and this commit adds a dedicated BBML2 cpufeature to test against
support for, as well as a kernel commandline parameter to optionally
disable BBML2 altogether.

This is a system feature as we might have a big.LITTLE architecture
where some cores support BBML2 and some don't, but we want all cores to
be available and BBM to default to level 0 (as opposed to having cores
without BBML2 not coming online).

To support BBML2 in as wide a range of contexts as we can, we want not
only the architectural guarantees that BBML2 makes, but additionally
want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
us having to prove that no recursive faults can be induced in any path
that uses BBML2, allowing its use for arbitrary kernel mappings.
Support detection of such CPUs.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 11 +++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  6 ++
 arch/arm64/kernel/cpufeature.c                | 76 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/tools/cpucaps                      |  1 +
 7 files changed, 101 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec8..3e4cc917a07e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -453,6 +453,9 @@
 	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
 			32 bit applications.
 
+	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
+			2 support
+
 	arm64.nobti	[ARM64] Unconditionally disable Branch Target
 			Identification support
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..49deda2b22ae 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
 	  The feature introduces new assembly instructions, and they were
 	  support when binutils >= 2.30.
 
+config ARM64_BBML2_NOABORT
+	bool "Enable support for Break-Before-Make Level 2 detection and usage"
+	default y
+	help
+	  FEAT_BBM provides detection of support levels for break-before-make
+	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
+	  can be relaxed to improve performance. We additonally require the
+	  property that the implementation cannot ever raise TLB Conflict Aborts.
+	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
+	  even if the system supports BBM level 2.
+
 endmenu # "ARMv8.4 architectural features"
 
 menu "ARMv8.5 architectural features"
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 0b5ca6e0eb09..2d6db33d4e45 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
 		return IS_ENABLED(CONFIG_ARM64_PAN);
 	case ARM64_HAS_EPAN:
 		return IS_ENABLED(CONFIG_ARM64_EPAN);
+	case ARM64_HAS_BBML2_NOABORT:
+		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
 	case ARM64_SVE:
 		return IS_ENABLED(CONFIG_ARM64_SVE);
 	case ARM64_SME:
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..7f5b220dacde 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -18,6 +18,7 @@
 #define ARM64_SW_FEATURE_OVERRIDE_NOKASLR	0
 #define ARM64_SW_FEATURE_OVERRIDE_HVHE		4
 #define ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF	8
+#define ARM64_SW_FEATURE_OVERRIDE_NOBBML2	12
 
 #ifndef __ASSEMBLY__
 
@@ -866,6 +867,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
 	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
 }
 
+static inline bool system_supports_bbml2_noabort(void)
+{
+	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d561cf3b8ac7..b936e0805161 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2176,6 +2176,76 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
 	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
 }
 
+static inline bool bbml2_possible(void)
+{
+	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
+}
+
+static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
+{
+	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
+	 * as possible. This list is therefore an allow-list of known-good
+	 * implementations that both support bbml2 and additionally, fulfill the
+	 * extra constraint of never generating TLB conflict aborts when using
+	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
+	 * kernel contexts difficult to prove safe against recursive aborts).
+	 *
+	 * Note that implementations can only be considered "known-good" if their
+	 * implementors attest to the fact that the implementation never raises
+	 * TLBI conflict aborts for bbml2 mapping granularity changes.
+	 */
+	static const struct midr_range supports_bbml2_noabort_list[] = {
+		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
+		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
+		{}
+	};
+
+	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
+}
+
+static inline unsigned int __cpu_read_midr(int cpu)
+{
+	WARN_ON_ONCE(!cpu_online(cpu));
+
+	return per_cpu(cpu_data, cpu).reg_midr;
+}
+
+static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
+		return false;
+
+	if (!bbml2_possible())
+		return false;
+
+	if (scope & SCOPE_SYSTEM) {
+		int cpu;
+
+		/* We are a boot CPU, and must verify that all enumerated boot
+		 * CPUs have MIDR values within our allowlist. Otherwise, we do
+		 * not allow the BBML2 feature to avoid potential faults when
+		 * the insufficient CPUs access memory regions using BBML2
+		 * semantics.
+		 */
+		for_each_online_cpu(cpu) {
+			if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
+				return false;
+		}
+
+		return true;
+	} else if (scope & SCOPE_LOCAL_CPU) {
+		/* We are a hot-plugged CPU, so only need to check our MIDR.
+		 * If we have the correct MIDR, but the kernel booted on an
+		 * insufficient CPU, we will not use BBML2 (this is safe). If
+		 * we have an incorrect MIDR, but the kernel booted on a
+		 * sufficient CPU, we will not bring up this CPU.
+		 */
+		return cpu_has_bbml2_noabort(read_cpuid_id());
+	}
+
+	return false;
+}
+
 #ifdef CONFIG_ARM64_PAN
 static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
@@ -2926,6 +2996,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.matches = has_cpuid_feature,
 		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
 	},
+	{
+		.desc = "BBM Level 2 without conflict abort",
+		.capability = ARM64_HAS_BBML2_NOABORT,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_bbml2_noabort,
+	},
 	{
 		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
 		.capability = ARM64_HAS_LPA2,
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index c6b185b885f7..9728faa10390 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
 		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
 		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
 		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
+		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
 		{}
 	},
 };
@@ -246,6 +247,7 @@ static const struct {
 	{ "rodata=off",			"arm64_sw.rodataoff=1" },
 	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
 	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
+	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
 };
 
 static int __init parse_hexdigit(const char *p, u64 *v)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1e65f2fb45bd..b03a375e5507 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
 HAS_ADDRESS_AUTH_IMP_DEF
 HAS_AMU_EXTN
 HAS_ARMv8_4_TTL
+HAS_BBML2_NOABORT
 HAS_CACHE_DIC
 HAS_CACHE_IDC
 HAS_CNP
-- 
2.48.1



From miko.lenczewski at arm.com  Thu Mar 13 03:41:11 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Thu, 13 Mar 2025 10:41:11 +0000
Subject: [PATCH v3 2/3] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250313104111.24196-2-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
Message-ID: <20250313104111.24196-4-miko.lenczewski@arm.com>

For supporting BBM Level 2 for userspace mappings, we want to ensure
that the smmu also supports its own version of BBM Level 2. Luckily, the
smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
0487K.a D8.16.2), so already guarantees that no aborts are raised when
BBM level 2 is claimed.

Add the feature and testing for it under arm_smmu_sva_supported().

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 9ba596430e7c..6ba182572788 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 		feat_mask |= ARM_SMMU_FEAT_VAX;
 	}
 
+	if (system_supports_bbml2_noabort())
+		feat_mask |= ARM_SMMU_FEAT_BBML2;
+
 	if ((smmu->features & feat_mask) != feat_mask)
 		return false;
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 358072b4e293..dcee0bdec924 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 	if (FIELD_GET(IDR3_RIL, reg))
 		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
 
+	if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
+		smmu->features |= ARM_SMMU_FEAT_BBML2;
+
 	/* IDR5 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index bd9d7c85576a..85eaf3ab88c2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -60,6 +60,9 @@ struct arm_smmu_device;
 #define ARM_SMMU_IDR3			0xc
 #define IDR3_FWB			(1 << 8)
 #define IDR3_RIL			(1 << 10)
+#define IDR3_BBML			GENMASK(12, 11)
+#define IDR3_BBML1			(1 << 11)
+#define IDR3_BBML2			(2 << 11)
 
 #define ARM_SMMU_IDR5			0x14
 #define IDR5_STALL_MAX			GENMASK(31, 16)
@@ -754,6 +757,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_HA		(1 << 21)
 #define ARM_SMMU_FEAT_HD		(1 << 22)
 #define ARM_SMMU_FEAT_S2FWB		(1 << 23)
+#define ARM_SMMU_FEAT_BBML2		(1 << 24)
 	u32				features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)
-- 
2.48.1



From lorenzo at kernel.org  Thu Mar 13 03:48:13 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Thu, 13 Mar 2025 11:48:13 +0100
Subject: [PATCH net-next] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9K2vujs6+yhiXXh@localhost.localdomain>
References: <20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0@kernel.org>
 <Z9Ga7gx1u3JsOemE@localhost.localdomain>
 <Z9GgHZxkSqFCkwMg@lore-desk>
 <Z9GtKwAuEx+7HKjR@localhost.localdomain>
 <Z9G01zGCpbw1YHNs@lore-desk>
 <Z9K2vujs6+yhiXXh@localhost.localdomain>
Message-ID: <Z9K37URcF_hkCTBM@lore-desk>

> On Wed, Mar 12, 2025 at 05:22:47PM +0100, Lorenzo Bianconi wrote:
> > > On Wed, Mar 12, 2025 at 03:54:21PM +0100, Lorenzo Bianconi wrote:
> > > > > On Wed, Mar 12, 2025 at 12:31:46PM +0100, Lorenzo Bianconi wrote:
> > > > > > The system occasionally crashes dereferencing a NULL pointer when it is
> > > > > > forwarding constant, high load bidirectional traffic.
> 
> [...]
> 
> > > 
> > > > 
> > > > > 
> > > > > > +		if (!eth->ports[i])
> > > > > > +			continue;
> > > > > 
> > > > > Isn't this NULL check redundant?
> > > > > In the second check you compare the table element to a real pointer.
> > > > 
> > > > Can netdev_priv() be NULL? If not, I guess we can remove this check.
> > > 
> > > I guess it shouldn't be NULL since "devm_alloc_etherdev_mqs()" was
> > > called, but I'm not 100% sure if there are any special cases for the "airoha"
> > > driver. Maybe in such cases it would be better to check for the netdev_priv?
> > > Anyway, such checks seem a bit too defensive to me.
> > 
> > the dev pointer can be allocated even outside of airoha_eth driver.
> > This pointer is provided by the flowtable.
> > I guess we can drop the NULL pointer check above, and do something like:
> > 
> > 	if (port && eth->ports[i] == port)
> > 		return 0;
> > 
> > what do you think?
> > 
> > Regards,
> > Lorenzo
> > 
> 
> I think if there's a risk that 'port' can be NULL, it looks like a
> reasonable solution and I'm OK with that.

I guess you are right. I do not think netdev_priv pointer can be NULL since,
even if size_priv is 0, it will just point to the end of the netdevice struct.
I will repost just doing:

	if (eth->ports[i] == port)
		return 0;

Regards,
Lorenzo

> 
> Thanks,
> Michal
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/3c7bf57b/attachment.sig>

From robin.murphy at arm.com  Thu Mar 13 04:01:33 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 11:01:33 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
 <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
Message-ID: <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>

On 2025-03-13 9:56 am, Marek Szyprowski wrote:
[...]
> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my tests I
> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
> relevant kernel log:

...and the bug-flushing-out begins!

> Unable to handle kernel NULL pointer dereference at virtual address
> 00000000000003e8
> Mem abort info:
>   ? ESR = 0x0000000096000004
>   ? EC = 0x25: DABT (current EL), IL = 32 bits
>   ? SET = 0, FnV = 0
>   ? EA = 0, S1PTW = 0
>   ? FSC = 0x04: level 0 translation fault
> Data abort info:
>   ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>   ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>   ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [00000000000003e8] user address but active_mm is swapper
> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
> Hardware name: Hardkernel ODROID-M1 (DT)
> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : devm_kmalloc+0x2c/0x114
> lr : rk_iommu_of_xlate+0x30/0x90
> ...
> Call trace:
>   ?devm_kmalloc+0x2c/0x114 (P)
>   ?rk_iommu_of_xlate+0x30/0x90

Yeah, looks like this is doing something a bit questionable which can't
work properly. TBH the whole dma_dev thing could probably be cleaned up
now that we have proper instances, but for now does this work?

(annoyingly none of my Rockchip boards are set up for testing right now, 
but I might have time to dig one out later)

Thanks,
Robin.

----->8-----

Subject: [PATCH] iommu/rockchip: Allocate per-device data sensibly

Now that DT-based probing is finally happening in the right order again,
it reveals an issue in Rockchip's of_xlate, which can now be called
during registration, but is using the global dma_dev which is only
assigned later. However, this makes little sense when we're already
looking up the correct IOMMU device, who should logically be the owner
of the devm allocation anyway.

Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe 
path")
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
  drivers/iommu/rockchip-iommu.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 323cc665c357..48826d1ccfd8 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1148,12 +1148,12 @@ static int rk_iommu_of_xlate(struct device *dev,
  	struct platform_device *iommu_dev;
  	struct rk_iommudata *data;

-	data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
+	iommu_dev = of_find_device_by_node(args->np);
+
+	data = devm_kzalloc(&iommu_dev->dev, sizeof(*data), GFP_KERNEL);
  	if (!data)
  		return -ENOMEM;

-	iommu_dev = of_find_device_by_node(args->np);
-
  	data->iommu = platform_get_drvdata(iommu_dev);
  	data->iommu->domain = &rk_identity_domain;
  	dev_iommu_priv_set(dev, data);
-- 
2.39.2.101.g768bb238c484.dirty




From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:58 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:58 +0530
Subject: [PATCH v12 5/6] arm64: dts: qcom: ipq9574: Add nsscc node
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-6-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

Add a node for the nss clock controller found on ipq9574 based devices.

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- Pick up R-b tag.

 arch/arm64/boot/dts/qcom/ipq9574.dtsi | 29 +++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
index cac58352182e..346de8ccfd0f 100644
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
@@ -1193,6 +1193,35 @@ pcie0: pci at 28000000 {
 			status = "disabled";
 		};
 
+		nsscc: clock-controller at 39b00000 {
+			compatible = "qcom,ipq9574-nsscc";
+			reg = <0x39b00000 0x80000>;
+			clocks = <&xo_board_clk>,
+				 <&cmn_pll NSS_1200MHZ_CLK>,
+				 <&cmn_pll PPE_353MHZ_CLK>,
+				 <&gcc GPLL0_OUT_AUX>,
+				 <0>,
+				 <0>,
+				 <0>,
+				 <0>,
+				 <0>,
+				 <0>,
+				 <&gcc GCC_NSSCC_CLK>;
+			clock-names = "xo",
+				      "nss_1200",
+				      "ppe_353",
+				      "gpll0_out",
+				      "uniphy0_rx",
+				      "uniphy0_tx",
+				      "uniphy1_rx",
+				      "uniphy1_tx",
+				      "uniphy2_rx",
+				      "uniphy2_tx",
+				      "bus";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#interconnect-cells = <1>;
+		};
 	};
 
 	thermal-zones {
-- 
2.34.1



From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:57 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:57 +0530
Subject: [PATCH v12 4/6] clk: qcom: Add NSS clock Controller driver for IPQ9574
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-5-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

Add Networking Sub System Clock Controller (NSSCC) driver for ipq9574 based
devices.

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- Pick up R-b tag.

 drivers/clk/qcom/Kconfig         |    7 +
 drivers/clk/qcom/Makefile        |    1 +
 drivers/clk/qcom/nsscc-ipq9574.c | 3110 ++++++++++++++++++++++++++++++
 3 files changed, 3118 insertions(+)
 create mode 100644 drivers/clk/qcom/nsscc-ipq9574.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index d470ed007854..7d5dac26b244 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -281,6 +281,13 @@ config IPQ_GCC_9574
 	  i2c, USB, SD/eMMC, etc. Select this for the root clock
 	  of ipq9574.
 
+config IPQ_NSSCC_9574
+        tristate "IPQ9574 NSS Clock Controller"
+        depends on ARM64 || COMPILE_TEST
+        depends on IPQ_GCC_9574
+        help
+          Support for NSS clock controller on ipq9574 devices.
+
 config IPQ_NSSCC_QCA8K
 	tristate "QCA8K(QCA8386 or QCA8084) NSS Clock Controller"
 	depends on MDIO_BUS
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 0db2f98bcb3e..96862e99e5d4 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
 obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o
 obj-$(CONFIG_IPQ_GCC_9574) += gcc-ipq9574.o
+obj-$(CONFIG_IPQ_NSSCC_9574)	+= nsscc-ipq9574.o
 obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
 obj-$(CONFIG_IPQ_NSSCC_QCA8K) += nsscc-qca8k.o
 obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o
diff --git a/drivers/clk/qcom/nsscc-ipq9574.c b/drivers/clk/qcom/nsscc-ipq9574.c
new file mode 100644
index 000000000000..64c6b05ff066
--- /dev/null
+++ b/drivers/clk/qcom/nsscc-ipq9574.c
@@ -0,0 +1,3110 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/interconnect-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,ipq9574-nsscc.h>
+#include <dt-bindings/interconnect/qcom,ipq9574.h>
+#include <dt-bindings/reset/qcom,ipq9574-nsscc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "reset.h"
+
+/* Need to match the order of clocks in DT binding */
+enum {
+	DT_XO,
+	DT_BIAS_PLL_CC_CLK,
+	DT_BIAS_PLL_UBI_NC_CLK,
+	DT_GCC_GPLL0_OUT_AUX,
+	DT_UNIPHY0_NSS_RX_CLK,
+	DT_UNIPHY0_NSS_TX_CLK,
+	DT_UNIPHY1_NSS_RX_CLK,
+	DT_UNIPHY1_NSS_TX_CLK,
+	DT_UNIPHY2_NSS_RX_CLK,
+	DT_UNIPHY2_NSS_TX_CLK,
+};
+
+enum {
+	P_XO,
+	P_BIAS_PLL_CC_CLK,
+	P_BIAS_PLL_UBI_NC_CLK,
+	P_GCC_GPLL0_OUT_AUX,
+	P_UBI32_PLL_OUT_MAIN,
+	P_UNIPHY0_NSS_RX_CLK,
+	P_UNIPHY0_NSS_TX_CLK,
+	P_UNIPHY1_NSS_RX_CLK,
+	P_UNIPHY1_NSS_TX_CLK,
+	P_UNIPHY2_NSS_RX_CLK,
+	P_UNIPHY2_NSS_TX_CLK,
+};
+
+static const struct alpha_pll_config ubi32_pll_config = {
+	.l = 0x3e,
+	.alpha = 0x6666,
+	.config_ctl_val = 0x200d4aa8,
+	.config_ctl_hi_val = 0x3c,
+	.main_output_mask = BIT(0),
+	.aux_output_mask = BIT(1),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(12),
+	.post_div_val = 0x0,
+	.post_div_mask = GENMASK(9, 8),
+	.alpha_en_mask = BIT(24),
+	.test_ctl_val = 0x1c0000c0,
+	.test_ctl_hi_val = 0x4000,
+};
+
+static struct clk_alpha_pll ubi32_pll_main = {
+	.offset = 0x28000,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA],
+	.flags = SUPPORTS_DYNAMIC_UPDATE,
+	.clkr = {
+		.hw.init = &(const struct clk_init_data) {
+			.name = "ubi32_pll_main",
+			.parent_data = &(const struct clk_parent_data) {
+				.index = DT_XO,
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_huayra_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv ubi32_pll = {
+	.offset = 0x28000,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA],
+	.width = 2,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "ubi32_pll",
+		.parent_hws = (const struct clk_hw *[]) {
+			&ubi32_pll_main.clkr.hw
+		},
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ro_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct parent_map nss_cc_parent_map_0[] = {
+	{ P_XO, 0 },
+	{ P_BIAS_PLL_CC_CLK, 1 },
+	{ P_UNIPHY0_NSS_RX_CLK, 2 },
+	{ P_UNIPHY0_NSS_TX_CLK, 3 },
+	{ P_UNIPHY1_NSS_RX_CLK, 4 },
+	{ P_UNIPHY1_NSS_TX_CLK, 5 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_0[] = {
+	{ .index = DT_XO },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+	{ .index = DT_UNIPHY0_NSS_RX_CLK },
+	{ .index = DT_UNIPHY0_NSS_TX_CLK },
+	{ .index = DT_UNIPHY1_NSS_RX_CLK },
+	{ .index = DT_UNIPHY1_NSS_TX_CLK },
+};
+
+static const struct parent_map nss_cc_parent_map_1[] = {
+	{ P_XO, 0 },
+	{ P_BIAS_PLL_UBI_NC_CLK, 1 },
+	{ P_GCC_GPLL0_OUT_AUX, 2 },
+	{ P_BIAS_PLL_CC_CLK, 6 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_1[] = {
+	{ .index = DT_XO },
+	{ .index = DT_BIAS_PLL_UBI_NC_CLK },
+	{ .index = DT_GCC_GPLL0_OUT_AUX },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+};
+
+static const struct parent_map nss_cc_parent_map_2[] = {
+	{ P_XO, 0 },
+	{ P_UBI32_PLL_OUT_MAIN, 1 },
+	{ P_GCC_GPLL0_OUT_AUX, 2 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_2[] = {
+	{ .index = DT_XO },
+	{ .hw = &ubi32_pll.clkr.hw },
+	{ .index = DT_GCC_GPLL0_OUT_AUX },
+};
+
+static const struct parent_map nss_cc_parent_map_3[] = {
+	{ P_XO, 0 },
+	{ P_BIAS_PLL_CC_CLK, 1 },
+	{ P_GCC_GPLL0_OUT_AUX, 2 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_3[] = {
+	{ .index = DT_XO },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+	{ .index = DT_GCC_GPLL0_OUT_AUX },
+};
+
+static const struct parent_map nss_cc_parent_map_4[] = {
+	{ P_XO, 0 },
+	{ P_BIAS_PLL_CC_CLK, 1 },
+	{ P_UNIPHY0_NSS_RX_CLK, 2 },
+	{ P_UNIPHY0_NSS_TX_CLK, 3 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_4[] = {
+	{ .index = DT_XO },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+	{ .index = DT_UNIPHY0_NSS_RX_CLK },
+	{ .index = DT_UNIPHY0_NSS_TX_CLK },
+};
+
+static const struct parent_map nss_cc_parent_map_5[] = {
+	{ P_XO, 0 },
+	{ P_BIAS_PLL_CC_CLK, 1 },
+	{ P_UNIPHY2_NSS_RX_CLK, 2 },
+	{ P_UNIPHY2_NSS_TX_CLK, 3 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_5[] = {
+	{ .index = DT_XO },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+	{ .index = DT_UNIPHY2_NSS_RX_CLK },
+	{ .index = DT_UNIPHY2_NSS_TX_CLK },
+};
+
+static const struct parent_map nss_cc_parent_map_6[] = {
+	{ P_XO, 0 },
+	{ P_GCC_GPLL0_OUT_AUX, 2 },
+	{ P_BIAS_PLL_CC_CLK, 6 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_6[] = {
+	{ .index = DT_XO },
+	{ .index = DT_GCC_GPLL0_OUT_AUX },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+};
+
+static const struct parent_map nss_cc_parent_map_7[] = {
+	{ P_XO, 0 },
+	{ P_UBI32_PLL_OUT_MAIN, 1 },
+	{ P_GCC_GPLL0_OUT_AUX, 2 },
+	{ P_BIAS_PLL_CC_CLK, 6 },
+};
+
+static const struct clk_parent_data nss_cc_parent_data_7[] = {
+	{ .index = DT_XO },
+	{ .hw = &ubi32_pll.clkr.hw },
+	{ .index = DT_GCC_GPLL0_OUT_AUX },
+	{ .index = DT_BIAS_PLL_CC_CLK },
+};
+
+static const struct freq_tbl ftbl_nss_cc_ce_clk_src[] = {
+	F(24000000, P_XO, 1, 0, 0),
+	F(353000000, P_BIAS_PLL_UBI_NC_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_ce_clk_src = {
+	.cmd_rcgr = 0x28404,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_1,
+	.freq_tbl = ftbl_nss_cc_ce_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ce_clk_src",
+		.parent_data = nss_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_1),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_nss_cc_cfg_clk_src[] = {
+	F(100000000, P_GCC_GPLL0_OUT_AUX, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_cfg_clk_src = {
+	.cmd_rcgr = 0x28104,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_3,
+	.freq_tbl = ftbl_nss_cc_cfg_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_cfg_clk_src",
+		.parent_data = nss_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_3),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_nss_cc_clc_clk_src[] = {
+	F(533333333, P_GCC_GPLL0_OUT_AUX, 1.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_clc_clk_src = {
+	.cmd_rcgr = 0x28604,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_6,
+	.freq_tbl = ftbl_nss_cc_clc_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_clc_clk_src",
+		.parent_data = nss_cc_parent_data_6,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_6),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_nss_cc_crypto_clk_src[] = {
+	F(24000000, P_XO, 1, 0, 0),
+	F(300000000, P_BIAS_PLL_CC_CLK, 4, 0, 0),
+	F(600000000, P_BIAS_PLL_CC_CLK, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_crypto_clk_src = {
+	.cmd_rcgr = 0x16008,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_3,
+	.freq_tbl = ftbl_nss_cc_crypto_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_crypto_clk_src",
+		.parent_data = nss_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_3),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_haq_clk_src = {
+	.cmd_rcgr = 0x28304,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_1,
+	.freq_tbl = ftbl_nss_cc_ce_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_haq_clk_src",
+		.parent_data = nss_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_1),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_imem_clk_src = {
+	.cmd_rcgr = 0xe008,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_1,
+	.freq_tbl = ftbl_nss_cc_ce_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_imem_clk_src",
+		.parent_data = nss_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_1),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_nss_cc_int_cfg_clk_src[] = {
+	F(200000000, P_GCC_GPLL0_OUT_AUX, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_int_cfg_clk_src = {
+	.cmd_rcgr = 0x287b4,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_3,
+	.freq_tbl = ftbl_nss_cc_int_cfg_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_int_cfg_clk_src",
+		.parent_data = nss_cc_parent_data_3,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_3),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_25[] = {
+	C(P_UNIPHY0_NSS_RX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_125[] = {
+	C(P_UNIPHY0_NSS_RX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port1_rx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port1_rx_clk_src_25),
+	FMS(78125000, P_UNIPHY0_NSS_RX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port1_rx_clk_src_125),
+	FMS(312500000, P_UNIPHY0_NSS_RX_CLK, 1, 0, 0),
+	{ }
+};
+
+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_25[] = {
+	C(P_UNIPHY0_NSS_TX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_125[] = {
+	C(P_UNIPHY0_NSS_TX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port1_tx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port1_tx_clk_src_25),
+	FMS(78125000, P_UNIPHY0_NSS_TX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port1_tx_clk_src_125),
+	FMS(312500000, P_UNIPHY0_NSS_TX_CLK, 1, 0, 0),
+	{ }
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_25[] = {
+	C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_125[] = {
+	C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_312p5[] = {
+	C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0),
+	C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port5_rx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port5_rx_clk_src_25),
+	FMS(78125000, P_UNIPHY1_NSS_RX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port5_rx_clk_src_125),
+	FMS(156250000, P_UNIPHY1_NSS_RX_CLK, 2, 0, 0),
+	FM(312500000, ftbl_nss_cc_port5_rx_clk_src_312p5),
+	{ }
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_25[] = {
+	C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_125[] = {
+	C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_312p5[] = {
+	C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0),
+	C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port5_tx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port5_tx_clk_src_25),
+	FMS(78125000, P_UNIPHY1_NSS_TX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port5_tx_clk_src_125),
+	FMS(156250000, P_UNIPHY1_NSS_TX_CLK, 2, 0, 0),
+	FM(312500000, ftbl_nss_cc_port5_tx_clk_src_312p5),
+	{ }
+};
+
+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_25[] = {
+	C(P_UNIPHY2_NSS_RX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY2_NSS_RX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_125[] = {
+	C(P_UNIPHY2_NSS_RX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY2_NSS_RX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port6_rx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port6_rx_clk_src_25),
+	FMS(78125000, P_UNIPHY2_NSS_RX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port6_rx_clk_src_125),
+	FMS(156250000, P_UNIPHY2_NSS_RX_CLK, 2, 0, 0),
+	FMS(312500000, P_UNIPHY2_NSS_RX_CLK, 1, 0, 0),
+	{ }
+};
+
+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_25[] = {
+	C(P_UNIPHY2_NSS_TX_CLK, 12.5, 0, 0),
+	C(P_UNIPHY2_NSS_TX_CLK, 5, 0, 0),
+};
+
+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_125[] = {
+	C(P_UNIPHY2_NSS_TX_CLK, 2.5, 0, 0),
+	C(P_UNIPHY2_NSS_TX_CLK, 1, 0, 0),
+};
+
+static const struct freq_multi_tbl ftbl_nss_cc_port6_tx_clk_src[] = {
+	FMS(24000000, P_XO, 1, 0, 0),
+	FM(25000000, ftbl_nss_cc_port6_tx_clk_src_25),
+	FMS(78125000, P_UNIPHY2_NSS_TX_CLK, 4, 0, 0),
+	FM(125000000, ftbl_nss_cc_port6_tx_clk_src_125),
+	FMS(156250000, P_UNIPHY2_NSS_TX_CLK, 2, 0, 0),
+	FMS(312500000, P_UNIPHY2_NSS_TX_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_port1_rx_clk_src = {
+	.cmd_rcgr = 0x28110,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port1_rx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port1_tx_clk_src = {
+	.cmd_rcgr = 0x2811c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port1_tx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port2_rx_clk_src = {
+	.cmd_rcgr = 0x28128,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port2_rx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port2_tx_clk_src = {
+	.cmd_rcgr = 0x28134,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port2_tx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port3_rx_clk_src = {
+	.cmd_rcgr = 0x28140,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port3_rx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port3_tx_clk_src = {
+	.cmd_rcgr = 0x2814c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port3_tx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port4_rx_clk_src = {
+	.cmd_rcgr = 0x28158,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port4_rx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port4_tx_clk_src = {
+	.cmd_rcgr = 0x28164,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_4,
+	.freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port4_tx_clk_src",
+		.parent_data = nss_cc_parent_data_4,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_4),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port5_rx_clk_src = {
+	.cmd_rcgr = 0x28170,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_0,
+	.freq_multi_tbl = ftbl_nss_cc_port5_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port5_rx_clk_src",
+		.parent_data = nss_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_0),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port5_tx_clk_src = {
+	.cmd_rcgr = 0x2817c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_0,
+	.freq_multi_tbl = ftbl_nss_cc_port5_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port5_tx_clk_src",
+		.parent_data = nss_cc_parent_data_0,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_0),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port6_rx_clk_src = {
+	.cmd_rcgr = 0x28188,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_5,
+	.freq_multi_tbl = ftbl_nss_cc_port6_rx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port6_rx_clk_src",
+		.parent_data = nss_cc_parent_data_5,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_5),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_port6_tx_clk_src = {
+	.cmd_rcgr = 0x28194,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_5,
+	.freq_multi_tbl = ftbl_nss_cc_port6_tx_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port6_tx_clk_src",
+		.parent_data = nss_cc_parent_data_5,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_5),
+		.ops = &clk_rcg2_fm_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ppe_clk_src = {
+	.cmd_rcgr = 0x28204,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_1,
+	.freq_tbl = ftbl_nss_cc_ce_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ppe_clk_src",
+		.parent_data = nss_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_1),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_nss_cc_ubi0_clk_src[] = {
+	F(24000000, P_XO, 1, 0, 0),
+	F(187200000, P_UBI32_PLL_OUT_MAIN, 8, 0, 0),
+	F(748800000, P_UBI32_PLL_OUT_MAIN, 2, 0, 0),
+	F(1497600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0),
+	F(1689600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 nss_cc_ubi0_clk_src = {
+	.cmd_rcgr = 0x28704,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_2,
+	.freq_tbl = ftbl_nss_cc_ubi0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi0_clk_src",
+		.parent_data = nss_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_2),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ubi1_clk_src = {
+	.cmd_rcgr = 0x2870c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_2,
+	.freq_tbl = ftbl_nss_cc_ubi0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi1_clk_src",
+		.parent_data = nss_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_2),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ubi2_clk_src = {
+	.cmd_rcgr = 0x28714,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_2,
+	.freq_tbl = ftbl_nss_cc_ubi0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi2_clk_src",
+		.parent_data = nss_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_2),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ubi3_clk_src = {
+	.cmd_rcgr = 0x2871c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_2,
+	.freq_tbl = ftbl_nss_cc_ubi0_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi3_clk_src",
+		.parent_data = nss_cc_parent_data_2,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_2),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ubi_axi_clk_src = {
+	.cmd_rcgr = 0x28724,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_7,
+	.freq_tbl = ftbl_nss_cc_clc_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi_axi_clk_src",
+		.parent_data = nss_cc_parent_data_7,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_7),
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 nss_cc_ubi_nc_axi_bfdcd_clk_src = {
+	.cmd_rcgr = 0x2872c,
+	.mnd_width = 0,
+	.hid_width = 5,
+	.parent_map = nss_cc_parent_map_1,
+	.freq_tbl = ftbl_nss_cc_ce_clk_src,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi_nc_axi_bfdcd_clk_src",
+		.parent_data = nss_cc_parent_data_1,
+		.num_parents = ARRAY_SIZE(nss_cc_parent_data_1),
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port1_rx_div_clk_src = {
+	.reg = 0x28118,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port1_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port1_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port1_tx_div_clk_src = {
+	.reg = 0x28124,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port1_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port1_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port2_rx_div_clk_src = {
+	.reg = 0x28130,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port2_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port2_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port2_tx_div_clk_src = {
+	.reg = 0x2813c,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port2_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port2_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port3_rx_div_clk_src = {
+	.reg = 0x28148,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port3_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port3_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port3_tx_div_clk_src = {
+	.reg = 0x28154,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port3_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port3_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port4_rx_div_clk_src = {
+	.reg = 0x28160,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port4_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port4_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port4_tx_div_clk_src = {
+	.reg = 0x2816c,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port4_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port4_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port5_rx_div_clk_src = {
+	.reg = 0x28178,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port5_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port5_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port5_tx_div_clk_src = {
+	.reg = 0x28184,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port5_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port5_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port6_rx_div_clk_src = {
+	.reg = 0x28190,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port6_rx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port6_rx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_port6_tx_div_clk_src = {
+	.reg = 0x2819c,
+	.shift = 0,
+	.width = 9,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_port6_tx_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_port6_tx_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_ubi0_div_clk_src = {
+	.reg = 0x287a4,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi0_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ubi0_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_ubi1_div_clk_src = {
+	.reg = 0x287a8,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi1_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ubi1_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_ubi2_div_clk_src = {
+	.reg = 0x287ac,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi2_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ubi2_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_ubi3_div_clk_src = {
+	.reg = 0x287b0,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_ubi3_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ubi3_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac0_ptp_ref_div_clk_src = {
+	.reg = 0x28214,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac0_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac1_ptp_ref_div_clk_src = {
+	.reg = 0x28218,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac1_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac2_ptp_ref_div_clk_src = {
+	.reg = 0x2821c,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac2_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac3_ptp_ref_div_clk_src = {
+	.reg = 0x28220,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac3_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac4_ptp_ref_div_clk_src = {
+	.reg = 0x28224,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac4_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_regmap_div nss_cc_xgmac5_ptp_ref_div_clk_src = {
+	.reg = 0x28228,
+	.shift = 0,
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "nss_cc_xgmac5_ptp_ref_div_clk_src",
+		.parent_data = &(const struct clk_parent_data) {
+			.hw = &nss_cc_ppe_clk_src.clkr.hw,
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_regmap_div_ro_ops,
+	},
+};
+
+static struct clk_branch nss_cc_ce_apb_clk = {
+	.halt_reg = 0x2840c,
+	.clkr = {
+		.enable_reg = 0x2840c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ce_apb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ce_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ce_axi_clk = {
+	.halt_reg = 0x28410,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28410,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ce_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ce_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_clc_axi_clk = {
+	.halt_reg = 0x2860c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2860c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_clc_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_clc_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_crypto_clk = {
+	.halt_reg = 0x1601c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x1601c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_crypto_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_crypto_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_crypto_ppe_clk = {
+	.halt_reg = 0x28240,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28240,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_crypto_ppe_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_haq_ahb_clk = {
+	.halt_reg = 0x2830c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2830c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_haq_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_haq_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_haq_axi_clk = {
+	.halt_reg = 0x28310,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28310,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_haq_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_haq_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_imem_ahb_clk = {
+	.halt_reg = 0xe018,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xe018,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_imem_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_imem_qsb_clk = {
+	.halt_reg = 0xe010,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xe010,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_imem_qsb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_imem_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nss_csr_clk = {
+	.halt_reg = 0x281d0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281d0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nss_csr_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ce_apb_clk = {
+	.halt_reg = 0x28414,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28414,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ce_apb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ce_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ce_axi_clk = {
+	.halt_reg = 0x28418,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28418,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ce_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ce_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_clc_axi_clk = {
+	.halt_reg = 0x28610,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28610,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_clc_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_clc_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_crypto_clk = {
+	.halt_reg = 0x16020,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x16020,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_crypto_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_crypto_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_haq_ahb_clk = {
+	.halt_reg = 0x28314,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28314,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_haq_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_haq_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_haq_axi_clk = {
+	.halt_reg = 0x28318,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28318,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_haq_axi_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_haq_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_imem_ahb_clk = {
+	.halt_reg = 0xe01c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xe01c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_imem_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_imem_qsb_clk = {
+	.halt_reg = 0xe014,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0xe014,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_imem_qsb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_imem_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_nss_csr_clk = {
+	.halt_reg = 0x281d4,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281d4,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_nss_csr_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ppe_cfg_clk = {
+	.halt_reg = 0x28248,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28248,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ppe_cfg_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ppe_clk = {
+	.halt_reg = 0x28244,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28244,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ppe_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ubi32_ahb0_clk = {
+	.halt_reg = 0x28788,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28788,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ubi32_ahb0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ubi32_axi0_clk = {
+	.halt_reg = 0x287a0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x287a0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ubi32_axi0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_axi_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ubi32_int0_ahb_clk = {
+	.halt_reg = 0x2878c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2878c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ubi32_int0_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_int_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_1_clk = {
+	.halt_reg = 0x287bc,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x287bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ubi32_nc_axi0_1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_clk = {
+	.halt_reg = 0x28764,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28764,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_nssnoc_ubi32_nc_axi0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port1_mac_clk = {
+	.halt_reg = 0x2824c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2824c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port1_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port1_rx_clk = {
+	.halt_reg = 0x281a0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281a0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port1_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port1_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port1_tx_clk = {
+	.halt_reg = 0x281a4,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281a4,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port1_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port1_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port2_mac_clk = {
+	.halt_reg = 0x28250,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28250,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port2_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port2_rx_clk = {
+	.halt_reg = 0x281a8,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port2_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port2_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port2_tx_clk = {
+	.halt_reg = 0x281ac,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port2_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port2_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port3_mac_clk = {
+	.halt_reg = 0x28254,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28254,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port3_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port3_rx_clk = {
+	.halt_reg = 0x281b0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port3_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port3_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port3_tx_clk = {
+	.halt_reg = 0x281b4,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port3_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port3_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port4_mac_clk = {
+	.halt_reg = 0x28258,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28258,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port4_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port4_rx_clk = {
+	.halt_reg = 0x281b8,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281b8,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port4_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port4_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port4_tx_clk = {
+	.halt_reg = 0x281bc,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port4_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port4_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port5_mac_clk = {
+	.halt_reg = 0x2825c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2825c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port5_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port5_rx_clk = {
+	.halt_reg = 0x281c0,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281c0,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port5_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port5_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port5_tx_clk = {
+	.halt_reg = 0x281c4,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port5_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port5_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port6_mac_clk = {
+	.halt_reg = 0x28260,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28260,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port6_mac_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port6_rx_clk = {
+	.halt_reg = 0x281c8,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port6_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port6_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_port6_tx_clk = {
+	.halt_reg = 0x281cc,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x281cc,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_port6_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port6_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_edma_cfg_clk = {
+	.halt_reg = 0x2823c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2823c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_edma_cfg_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_edma_clk = {
+	.halt_reg = 0x28238,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28238,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_edma_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_switch_btq_clk = {
+	.halt_reg = 0x2827c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2827c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_switch_btq_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_switch_cfg_clk = {
+	.halt_reg = 0x28234,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28234,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_switch_cfg_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_switch_clk = {
+	.halt_reg = 0x28230,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28230,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_switch_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ppe_switch_ipe_clk = {
+	.halt_reg = 0x2822c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2822c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ppe_switch_ipe_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ppe_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_ahb0_clk = {
+	.halt_reg = 0x28768,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28768,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_ahb0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_ahb1_clk = {
+	.halt_reg = 0x28770,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28770,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_ahb1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_ahb2_clk = {
+	.halt_reg = 0x28778,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28778,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_ahb2_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_ahb3_clk = {
+	.halt_reg = 0x28780,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28780,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_ahb3_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_axi0_clk = {
+	.halt_reg = 0x28790,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28790,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_axi0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_axi_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_axi1_clk = {
+	.halt_reg = 0x28794,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28794,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_axi1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_axi_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_axi2_clk = {
+	.halt_reg = 0x28798,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28798,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_axi2_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_axi_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_axi3_clk = {
+	.halt_reg = 0x2879c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2879c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_axi3_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_axi_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_core0_clk = {
+	.halt_reg = 0x28734,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28734,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_core0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi0_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_core1_clk = {
+	.halt_reg = 0x28738,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28738,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_core1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi1_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_core2_clk = {
+	.halt_reg = 0x2873c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2873c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_core2_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi2_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_core3_clk = {
+	.halt_reg = 0x28740,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28740,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_core3_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi3_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_intr0_ahb_clk = {
+	.halt_reg = 0x2876c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2876c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_intr0_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_int_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_intr1_ahb_clk = {
+	.halt_reg = 0x28774,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28774,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_intr1_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_int_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_intr2_ahb_clk = {
+	.halt_reg = 0x2877c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2877c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_intr2_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_int_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_intr3_ahb_clk = {
+	.halt_reg = 0x28784,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28784,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_intr3_ahb_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_int_cfg_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_nc_axi0_clk = {
+	.halt_reg = 0x28744,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28744,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_nc_axi0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_nc_axi1_clk = {
+	.halt_reg = 0x2874c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2874c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_nc_axi1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_nc_axi2_clk = {
+	.halt_reg = 0x28754,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28754,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_nc_axi2_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_nc_axi3_clk = {
+	.halt_reg = 0x2875c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2875c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_nc_axi3_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_utcm0_clk = {
+	.halt_reg = 0x28748,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28748,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_utcm0_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_utcm1_clk = {
+	.halt_reg = 0x28750,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28750,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_utcm1_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_utcm2_clk = {
+	.halt_reg = 0x28758,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28758,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_utcm2_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_ubi32_utcm3_clk = {
+	.halt_reg = 0x28760,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28760,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_ubi32_utcm3_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port1_rx_clk = {
+	.halt_reg = 0x28904,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28904,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port1_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port1_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port1_tx_clk = {
+	.halt_reg = 0x28908,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28908,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port1_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port1_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port2_rx_clk = {
+	.halt_reg = 0x2890c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2890c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port2_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port2_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port2_tx_clk = {
+	.halt_reg = 0x28910,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28910,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port2_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port2_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port3_rx_clk = {
+	.halt_reg = 0x28914,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28914,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port3_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port3_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port3_tx_clk = {
+	.halt_reg = 0x28918,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28918,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port3_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port3_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port4_rx_clk = {
+	.halt_reg = 0x2891c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2891c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port4_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port4_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port4_tx_clk = {
+	.halt_reg = 0x28920,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28920,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port4_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port4_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port5_rx_clk = {
+	.halt_reg = 0x28924,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28924,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port5_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port5_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port5_tx_clk = {
+	.halt_reg = 0x28928,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28928,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port5_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port5_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port6_rx_clk = {
+	.halt_reg = 0x2892c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2892c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port6_rx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port6_rx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_uniphy_port6_tx_clk = {
+	.halt_reg = 0x28930,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28930,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_uniphy_port6_tx_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_port6_tx_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac0_ptp_ref_clk = {
+	.halt_reg = 0x28264,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28264,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac0_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac1_ptp_ref_clk = {
+	.halt_reg = 0x28268,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28268,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac1_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac2_ptp_ref_clk = {
+	.halt_reg = 0x2826c,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x2826c,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac2_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac3_ptp_ref_clk = {
+	.halt_reg = 0x28270,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28270,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac3_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac3_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac4_ptp_ref_clk = {
+	.halt_reg = 0x28274,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28274,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac4_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac4_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch nss_cc_xgmac5_ptp_ref_clk = {
+	.halt_reg = 0x28278,
+	.halt_check = BRANCH_HALT,
+	.clkr = {
+		.enable_reg = 0x28278,
+		.enable_mask = BIT(0),
+		.hw.init = &(const struct clk_init_data) {
+			.name = "nss_cc_xgmac5_ptp_ref_clk",
+			.parent_data = &(const struct clk_parent_data) {
+				.hw = &nss_cc_xgmac5_ptp_ref_div_clk_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_regmap *nss_cc_ipq9574_clocks[] = {
+	[NSS_CC_CE_APB_CLK] = &nss_cc_ce_apb_clk.clkr,
+	[NSS_CC_CE_AXI_CLK] = &nss_cc_ce_axi_clk.clkr,
+	[NSS_CC_CE_CLK_SRC] = &nss_cc_ce_clk_src.clkr,
+	[NSS_CC_CFG_CLK_SRC] = &nss_cc_cfg_clk_src.clkr,
+	[NSS_CC_CLC_AXI_CLK] = &nss_cc_clc_axi_clk.clkr,
+	[NSS_CC_CLC_CLK_SRC] = &nss_cc_clc_clk_src.clkr,
+	[NSS_CC_CRYPTO_CLK] = &nss_cc_crypto_clk.clkr,
+	[NSS_CC_CRYPTO_CLK_SRC] = &nss_cc_crypto_clk_src.clkr,
+	[NSS_CC_CRYPTO_PPE_CLK] = &nss_cc_crypto_ppe_clk.clkr,
+	[NSS_CC_HAQ_AHB_CLK] = &nss_cc_haq_ahb_clk.clkr,
+	[NSS_CC_HAQ_AXI_CLK] = &nss_cc_haq_axi_clk.clkr,
+	[NSS_CC_HAQ_CLK_SRC] = &nss_cc_haq_clk_src.clkr,
+	[NSS_CC_IMEM_AHB_CLK] = &nss_cc_imem_ahb_clk.clkr,
+	[NSS_CC_IMEM_CLK_SRC] = &nss_cc_imem_clk_src.clkr,
+	[NSS_CC_IMEM_QSB_CLK] = &nss_cc_imem_qsb_clk.clkr,
+	[NSS_CC_INT_CFG_CLK_SRC] = &nss_cc_int_cfg_clk_src.clkr,
+	[NSS_CC_NSS_CSR_CLK] = &nss_cc_nss_csr_clk.clkr,
+	[NSS_CC_NSSNOC_CE_APB_CLK] = &nss_cc_nssnoc_ce_apb_clk.clkr,
+	[NSS_CC_NSSNOC_CE_AXI_CLK] = &nss_cc_nssnoc_ce_axi_clk.clkr,
+	[NSS_CC_NSSNOC_CLC_AXI_CLK] = &nss_cc_nssnoc_clc_axi_clk.clkr,
+	[NSS_CC_NSSNOC_CRYPTO_CLK] = &nss_cc_nssnoc_crypto_clk.clkr,
+	[NSS_CC_NSSNOC_HAQ_AHB_CLK] = &nss_cc_nssnoc_haq_ahb_clk.clkr,
+	[NSS_CC_NSSNOC_HAQ_AXI_CLK] = &nss_cc_nssnoc_haq_axi_clk.clkr,
+	[NSS_CC_NSSNOC_IMEM_AHB_CLK] = &nss_cc_nssnoc_imem_ahb_clk.clkr,
+	[NSS_CC_NSSNOC_IMEM_QSB_CLK] = &nss_cc_nssnoc_imem_qsb_clk.clkr,
+	[NSS_CC_NSSNOC_NSS_CSR_CLK] = &nss_cc_nssnoc_nss_csr_clk.clkr,
+	[NSS_CC_NSSNOC_PPE_CFG_CLK] = &nss_cc_nssnoc_ppe_cfg_clk.clkr,
+	[NSS_CC_NSSNOC_PPE_CLK] = &nss_cc_nssnoc_ppe_clk.clkr,
+	[NSS_CC_NSSNOC_UBI32_AHB0_CLK] = &nss_cc_nssnoc_ubi32_ahb0_clk.clkr,
+	[NSS_CC_NSSNOC_UBI32_AXI0_CLK] = &nss_cc_nssnoc_ubi32_axi0_clk.clkr,
+	[NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK] =
+		&nss_cc_nssnoc_ubi32_int0_ahb_clk.clkr,
+	[NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK] =
+		&nss_cc_nssnoc_ubi32_nc_axi0_1_clk.clkr,
+	[NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK] =
+		&nss_cc_nssnoc_ubi32_nc_axi0_clk.clkr,
+	[NSS_CC_PORT1_MAC_CLK] = &nss_cc_port1_mac_clk.clkr,
+	[NSS_CC_PORT1_RX_CLK] = &nss_cc_port1_rx_clk.clkr,
+	[NSS_CC_PORT1_RX_CLK_SRC] = &nss_cc_port1_rx_clk_src.clkr,
+	[NSS_CC_PORT1_RX_DIV_CLK_SRC] = &nss_cc_port1_rx_div_clk_src.clkr,
+	[NSS_CC_PORT1_TX_CLK] = &nss_cc_port1_tx_clk.clkr,
+	[NSS_CC_PORT1_TX_CLK_SRC] = &nss_cc_port1_tx_clk_src.clkr,
+	[NSS_CC_PORT1_TX_DIV_CLK_SRC] = &nss_cc_port1_tx_div_clk_src.clkr,
+	[NSS_CC_PORT2_MAC_CLK] = &nss_cc_port2_mac_clk.clkr,
+	[NSS_CC_PORT2_RX_CLK] = &nss_cc_port2_rx_clk.clkr,
+	[NSS_CC_PORT2_RX_CLK_SRC] = &nss_cc_port2_rx_clk_src.clkr,
+	[NSS_CC_PORT2_RX_DIV_CLK_SRC] = &nss_cc_port2_rx_div_clk_src.clkr,
+	[NSS_CC_PORT2_TX_CLK] = &nss_cc_port2_tx_clk.clkr,
+	[NSS_CC_PORT2_TX_CLK_SRC] = &nss_cc_port2_tx_clk_src.clkr,
+	[NSS_CC_PORT2_TX_DIV_CLK_SRC] = &nss_cc_port2_tx_div_clk_src.clkr,
+	[NSS_CC_PORT3_MAC_CLK] = &nss_cc_port3_mac_clk.clkr,
+	[NSS_CC_PORT3_RX_CLK] = &nss_cc_port3_rx_clk.clkr,
+	[NSS_CC_PORT3_RX_CLK_SRC] = &nss_cc_port3_rx_clk_src.clkr,
+	[NSS_CC_PORT3_RX_DIV_CLK_SRC] = &nss_cc_port3_rx_div_clk_src.clkr,
+	[NSS_CC_PORT3_TX_CLK] = &nss_cc_port3_tx_clk.clkr,
+	[NSS_CC_PORT3_TX_CLK_SRC] = &nss_cc_port3_tx_clk_src.clkr,
+	[NSS_CC_PORT3_TX_DIV_CLK_SRC] = &nss_cc_port3_tx_div_clk_src.clkr,
+	[NSS_CC_PORT4_MAC_CLK] = &nss_cc_port4_mac_clk.clkr,
+	[NSS_CC_PORT4_RX_CLK] = &nss_cc_port4_rx_clk.clkr,
+	[NSS_CC_PORT4_RX_CLK_SRC] = &nss_cc_port4_rx_clk_src.clkr,
+	[NSS_CC_PORT4_RX_DIV_CLK_SRC] = &nss_cc_port4_rx_div_clk_src.clkr,
+	[NSS_CC_PORT4_TX_CLK] = &nss_cc_port4_tx_clk.clkr,
+	[NSS_CC_PORT4_TX_CLK_SRC] = &nss_cc_port4_tx_clk_src.clkr,
+	[NSS_CC_PORT4_TX_DIV_CLK_SRC] = &nss_cc_port4_tx_div_clk_src.clkr,
+	[NSS_CC_PORT5_MAC_CLK] = &nss_cc_port5_mac_clk.clkr,
+	[NSS_CC_PORT5_RX_CLK] = &nss_cc_port5_rx_clk.clkr,
+	[NSS_CC_PORT5_RX_CLK_SRC] = &nss_cc_port5_rx_clk_src.clkr,
+	[NSS_CC_PORT5_RX_DIV_CLK_SRC] = &nss_cc_port5_rx_div_clk_src.clkr,
+	[NSS_CC_PORT5_TX_CLK] = &nss_cc_port5_tx_clk.clkr,
+	[NSS_CC_PORT5_TX_CLK_SRC] = &nss_cc_port5_tx_clk_src.clkr,
+	[NSS_CC_PORT5_TX_DIV_CLK_SRC] = &nss_cc_port5_tx_div_clk_src.clkr,
+	[NSS_CC_PORT6_MAC_CLK] = &nss_cc_port6_mac_clk.clkr,
+	[NSS_CC_PORT6_RX_CLK] = &nss_cc_port6_rx_clk.clkr,
+	[NSS_CC_PORT6_RX_CLK_SRC] = &nss_cc_port6_rx_clk_src.clkr,
+	[NSS_CC_PORT6_RX_DIV_CLK_SRC] = &nss_cc_port6_rx_div_clk_src.clkr,
+	[NSS_CC_PORT6_TX_CLK] = &nss_cc_port6_tx_clk.clkr,
+	[NSS_CC_PORT6_TX_CLK_SRC] = &nss_cc_port6_tx_clk_src.clkr,
+	[NSS_CC_PORT6_TX_DIV_CLK_SRC] = &nss_cc_port6_tx_div_clk_src.clkr,
+	[NSS_CC_PPE_CLK_SRC] = &nss_cc_ppe_clk_src.clkr,
+	[NSS_CC_PPE_EDMA_CFG_CLK] = &nss_cc_ppe_edma_cfg_clk.clkr,
+	[NSS_CC_PPE_EDMA_CLK] = &nss_cc_ppe_edma_clk.clkr,
+	[NSS_CC_PPE_SWITCH_BTQ_CLK] = &nss_cc_ppe_switch_btq_clk.clkr,
+	[NSS_CC_PPE_SWITCH_CFG_CLK] = &nss_cc_ppe_switch_cfg_clk.clkr,
+	[NSS_CC_PPE_SWITCH_CLK] = &nss_cc_ppe_switch_clk.clkr,
+	[NSS_CC_PPE_SWITCH_IPE_CLK] = &nss_cc_ppe_switch_ipe_clk.clkr,
+	[NSS_CC_UBI0_CLK_SRC] = &nss_cc_ubi0_clk_src.clkr,
+	[NSS_CC_UBI0_DIV_CLK_SRC] = &nss_cc_ubi0_div_clk_src.clkr,
+	[NSS_CC_UBI1_CLK_SRC] = &nss_cc_ubi1_clk_src.clkr,
+	[NSS_CC_UBI1_DIV_CLK_SRC] = &nss_cc_ubi1_div_clk_src.clkr,
+	[NSS_CC_UBI2_CLK_SRC] = &nss_cc_ubi2_clk_src.clkr,
+	[NSS_CC_UBI2_DIV_CLK_SRC] = &nss_cc_ubi2_div_clk_src.clkr,
+	[NSS_CC_UBI32_AHB0_CLK] = &nss_cc_ubi32_ahb0_clk.clkr,
+	[NSS_CC_UBI32_AHB1_CLK] = &nss_cc_ubi32_ahb1_clk.clkr,
+	[NSS_CC_UBI32_AHB2_CLK] = &nss_cc_ubi32_ahb2_clk.clkr,
+	[NSS_CC_UBI32_AHB3_CLK] = &nss_cc_ubi32_ahb3_clk.clkr,
+	[NSS_CC_UBI32_AXI0_CLK] = &nss_cc_ubi32_axi0_clk.clkr,
+	[NSS_CC_UBI32_AXI1_CLK] = &nss_cc_ubi32_axi1_clk.clkr,
+	[NSS_CC_UBI32_AXI2_CLK] = &nss_cc_ubi32_axi2_clk.clkr,
+	[NSS_CC_UBI32_AXI3_CLK] = &nss_cc_ubi32_axi3_clk.clkr,
+	[NSS_CC_UBI32_CORE0_CLK] = &nss_cc_ubi32_core0_clk.clkr,
+	[NSS_CC_UBI32_CORE1_CLK] = &nss_cc_ubi32_core1_clk.clkr,
+	[NSS_CC_UBI32_CORE2_CLK] = &nss_cc_ubi32_core2_clk.clkr,
+	[NSS_CC_UBI32_CORE3_CLK] = &nss_cc_ubi32_core3_clk.clkr,
+	[NSS_CC_UBI32_INTR0_AHB_CLK] = &nss_cc_ubi32_intr0_ahb_clk.clkr,
+	[NSS_CC_UBI32_INTR1_AHB_CLK] = &nss_cc_ubi32_intr1_ahb_clk.clkr,
+	[NSS_CC_UBI32_INTR2_AHB_CLK] = &nss_cc_ubi32_intr2_ahb_clk.clkr,
+	[NSS_CC_UBI32_INTR3_AHB_CLK] = &nss_cc_ubi32_intr3_ahb_clk.clkr,
+	[NSS_CC_UBI32_NC_AXI0_CLK] = &nss_cc_ubi32_nc_axi0_clk.clkr,
+	[NSS_CC_UBI32_NC_AXI1_CLK] = &nss_cc_ubi32_nc_axi1_clk.clkr,
+	[NSS_CC_UBI32_NC_AXI2_CLK] = &nss_cc_ubi32_nc_axi2_clk.clkr,
+	[NSS_CC_UBI32_NC_AXI3_CLK] = &nss_cc_ubi32_nc_axi3_clk.clkr,
+	[NSS_CC_UBI32_UTCM0_CLK] = &nss_cc_ubi32_utcm0_clk.clkr,
+	[NSS_CC_UBI32_UTCM1_CLK] = &nss_cc_ubi32_utcm1_clk.clkr,
+	[NSS_CC_UBI32_UTCM2_CLK] = &nss_cc_ubi32_utcm2_clk.clkr,
+	[NSS_CC_UBI32_UTCM3_CLK] = &nss_cc_ubi32_utcm3_clk.clkr,
+	[NSS_CC_UBI3_CLK_SRC] = &nss_cc_ubi3_clk_src.clkr,
+	[NSS_CC_UBI3_DIV_CLK_SRC] = &nss_cc_ubi3_div_clk_src.clkr,
+	[NSS_CC_UBI_AXI_CLK_SRC] = &nss_cc_ubi_axi_clk_src.clkr,
+	[NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC] =
+		&nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr,
+	[NSS_CC_UNIPHY_PORT1_RX_CLK] = &nss_cc_uniphy_port1_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT1_TX_CLK] = &nss_cc_uniphy_port1_tx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT2_RX_CLK] = &nss_cc_uniphy_port2_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT2_TX_CLK] = &nss_cc_uniphy_port2_tx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT3_RX_CLK] = &nss_cc_uniphy_port3_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT3_TX_CLK] = &nss_cc_uniphy_port3_tx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT4_RX_CLK] = &nss_cc_uniphy_port4_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT4_TX_CLK] = &nss_cc_uniphy_port4_tx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT5_RX_CLK] = &nss_cc_uniphy_port5_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT5_TX_CLK] = &nss_cc_uniphy_port5_tx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT6_RX_CLK] = &nss_cc_uniphy_port6_rx_clk.clkr,
+	[NSS_CC_UNIPHY_PORT6_TX_CLK] = &nss_cc_uniphy_port6_tx_clk.clkr,
+	[NSS_CC_XGMAC0_PTP_REF_CLK] = &nss_cc_xgmac0_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac0_ptp_ref_div_clk_src.clkr,
+	[NSS_CC_XGMAC1_PTP_REF_CLK] = &nss_cc_xgmac1_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac1_ptp_ref_div_clk_src.clkr,
+	[NSS_CC_XGMAC2_PTP_REF_CLK] = &nss_cc_xgmac2_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac2_ptp_ref_div_clk_src.clkr,
+	[NSS_CC_XGMAC3_PTP_REF_CLK] = &nss_cc_xgmac3_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac3_ptp_ref_div_clk_src.clkr,
+	[NSS_CC_XGMAC4_PTP_REF_CLK] = &nss_cc_xgmac4_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac4_ptp_ref_div_clk_src.clkr,
+	[NSS_CC_XGMAC5_PTP_REF_CLK] = &nss_cc_xgmac5_ptp_ref_clk.clkr,
+	[NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC] =
+		&nss_cc_xgmac5_ptp_ref_div_clk_src.clkr,
+	[UBI32_PLL] = &ubi32_pll.clkr,
+	[UBI32_PLL_MAIN] = &ubi32_pll_main.clkr,
+};
+
+static const struct qcom_reset_map nss_cc_ipq9574_resets[] = {
+	[NSS_CC_CE_BCR] = { 0x28400, 0 },
+	[NSS_CC_CLC_BCR] = { 0x28600, 0 },
+	[NSS_CC_EIP197_BCR] = { 0x16004, 0 },
+	[NSS_CC_HAQ_BCR] = { 0x28300, 0 },
+	[NSS_CC_IMEM_BCR] = { 0xe004, 0 },
+	[NSS_CC_MAC_BCR] = { 0x28100, 0 },
+	[NSS_CC_PPE_BCR] = { 0x28200, 0 },
+	[NSS_CC_UBI_BCR] = { 0x28700, 0 },
+	[NSS_CC_UNIPHY_BCR] = { 0x28900, 0 },
+	[UBI3_CLKRST_CLAMP_ENABLE] = { 0x28a04, 9 },
+	[UBI3_CORE_CLAMP_ENABLE] = { 0x28a04, 8 },
+	[UBI2_CLKRST_CLAMP_ENABLE] = { 0x28a04, 7 },
+	[UBI2_CORE_CLAMP_ENABLE] = { 0x28a04, 6 },
+	[UBI1_CLKRST_CLAMP_ENABLE] = { 0x28a04, 5 },
+	[UBI1_CORE_CLAMP_ENABLE] = { 0x28a04, 4 },
+	[UBI0_CLKRST_CLAMP_ENABLE] = { 0x28a04, 3 },
+	[UBI0_CORE_CLAMP_ENABLE] = { 0x28a04, 2 },
+	[NSSNOC_NSS_CSR_ARES] = { 0x28a04, 1 },
+	[NSS_CSR_ARES] = { 0x28a04, 0 },
+	[PPE_BTQ_ARES] = { 0x28a08, 20 },
+	[PPE_IPE_ARES] = { 0x28a08, 19 },
+	[PPE_ARES] = { 0x28a08, 18 },
+	[PPE_CFG_ARES] = { 0x28a08, 17 },
+	[PPE_EDMA_ARES] = { 0x28a08, 16 },
+	[PPE_EDMA_CFG_ARES] = { 0x28a08, 15 },
+	[CRY_PPE_ARES] = { 0x28a08, 14 },
+	[NSSNOC_PPE_ARES] = { 0x28a08, 13 },
+	[NSSNOC_PPE_CFG_ARES] = { 0x28a08, 12 },
+	[PORT1_MAC_ARES] = { 0x28a08, 11 },
+	[PORT2_MAC_ARES] = { 0x28a08, 10 },
+	[PORT3_MAC_ARES] = { 0x28a08, 9 },
+	[PORT4_MAC_ARES] = { 0x28a08, 8 },
+	[PORT5_MAC_ARES] = { 0x28a08, 7 },
+	[PORT6_MAC_ARES] = { 0x28a08, 6 },
+	[XGMAC0_PTP_REF_ARES] = { 0x28a08, 5 },
+	[XGMAC1_PTP_REF_ARES] = { 0x28a08, 4 },
+	[XGMAC2_PTP_REF_ARES] = { 0x28a08, 3 },
+	[XGMAC3_PTP_REF_ARES] = { 0x28a08, 2 },
+	[XGMAC4_PTP_REF_ARES] = { 0x28a08, 1 },
+	[XGMAC5_PTP_REF_ARES] = { 0x28a08, 0 },
+	[HAQ_AHB_ARES] = { 0x28a0c, 3 },
+	[HAQ_AXI_ARES] = { 0x28a0c, 2 },
+	[NSSNOC_HAQ_AHB_ARES] = { 0x28a0c, 1 },
+	[NSSNOC_HAQ_AXI_ARES] = { 0x28a0c, 0 },
+	[CE_APB_ARES] = { 0x28a10, 3 },
+	[CE_AXI_ARES] = { 0x28a10, 2 },
+	[NSSNOC_CE_APB_ARES] = { 0x28a10, 1 },
+	[NSSNOC_CE_AXI_ARES] = { 0x28a10, 0 },
+	[CRYPTO_ARES] = { 0x28a14, 1 },
+	[NSSNOC_CRYPTO_ARES] = { 0x28a14, 0 },
+	[NSSNOC_NC_AXI0_1_ARES] = { 0x28a1c, 28 },
+	[UBI0_CORE_ARES] = { 0x28a1c, 27 },
+	[UBI1_CORE_ARES] = { 0x28a1c, 26 },
+	[UBI2_CORE_ARES] = { 0x28a1c, 25 },
+	[UBI3_CORE_ARES] = { 0x28a1c, 24 },
+	[NC_AXI0_ARES] = { 0x28a1c, 23 },
+	[UTCM0_ARES] = { 0x28a1c, 22 },
+	[NC_AXI1_ARES] = { 0x28a1c, 21 },
+	[UTCM1_ARES] = { 0x28a1c, 20 },
+	[NC_AXI2_ARES] = { 0x28a1c, 19 },
+	[UTCM2_ARES] = { 0x28a1c, 18 },
+	[NC_AXI3_ARES] = { 0x28a1c, 17 },
+	[UTCM3_ARES] = { 0x28a1c, 16 },
+	[NSSNOC_NC_AXI0_ARES] = { 0x28a1c, 15 },
+	[AHB0_ARES] = { 0x28a1c, 14 },
+	[INTR0_AHB_ARES] = { 0x28a1c, 13 },
+	[AHB1_ARES] = { 0x28a1c, 12 },
+	[INTR1_AHB_ARES] = { 0x28a1c, 11 },
+	[AHB2_ARES] = { 0x28a1c, 10 },
+	[INTR2_AHB_ARES] = { 0x28a1c, 9 },
+	[AHB3_ARES] = { 0x28a1c, 8 },
+	[INTR3_AHB_ARES] = { 0x28a1c, 7 },
+	[NSSNOC_AHB0_ARES] = { 0x28a1c, 6 },
+	[NSSNOC_INT0_AHB_ARES] = { 0x28a1c, 5 },
+	[AXI0_ARES] = { 0x28a1c, 4 },
+	[AXI1_ARES] = { 0x28a1c, 3 },
+	[AXI2_ARES] = { 0x28a1c, 2 },
+	[AXI3_ARES] = { 0x28a1c, 1 },
+	[NSSNOC_AXI0_ARES] = { 0x28a1c, 0 },
+	[IMEM_QSB_ARES] = { 0x28a20, 3 },
+	[NSSNOC_IMEM_QSB_ARES] = { 0x28a20, 2 },
+	[IMEM_AHB_ARES] = { 0x28a20, 1 },
+	[NSSNOC_IMEM_AHB_ARES] = { 0x28a20, 0 },
+	[UNIPHY_PORT1_RX_ARES] = { 0x28a24, 23 },
+	[UNIPHY_PORT1_TX_ARES] = { 0x28a24, 22 },
+	[UNIPHY_PORT2_RX_ARES] = { 0x28a24, 21 },
+	[UNIPHY_PORT2_TX_ARES] = { 0x28a24, 20 },
+	[UNIPHY_PORT3_RX_ARES] = { 0x28a24, 19 },
+	[UNIPHY_PORT3_TX_ARES] = { 0x28a24, 18 },
+	[UNIPHY_PORT4_RX_ARES] = { 0x28a24, 17 },
+	[UNIPHY_PORT4_TX_ARES] = { 0x28a24, 16 },
+	[UNIPHY_PORT5_RX_ARES] = { 0x28a24, 15 },
+	[UNIPHY_PORT5_TX_ARES] = { 0x28a24, 14 },
+	[UNIPHY_PORT6_RX_ARES] = { 0x28a24, 13 },
+	[UNIPHY_PORT6_TX_ARES] = { 0x28a24, 12 },
+	[PORT1_RX_ARES] = { 0x28a24, 11 },
+	[PORT1_TX_ARES] = { 0x28a24, 10 },
+	[PORT2_RX_ARES] = { 0x28a24, 9 },
+	[PORT2_TX_ARES] = { 0x28a24, 8 },
+	[PORT3_RX_ARES] = { 0x28a24, 7 },
+	[PORT3_TX_ARES] = { 0x28a24, 6 },
+	[PORT4_RX_ARES] = { 0x28a24, 5 },
+	[PORT4_TX_ARES] = { 0x28a24, 4 },
+	[PORT5_RX_ARES] = { 0x28a24, 3 },
+	[PORT5_TX_ARES] = { 0x28a24, 2 },
+	[PORT6_RX_ARES] = { 0x28a24, 1 },
+	[PORT6_TX_ARES] = { 0x28a24, 0 },
+	[PPE_FULL_RESET] = { .reg = 0x28a08, .bitmask = GENMASK(20, 17) },
+	[UNIPHY0_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(23, 14) },
+	[UNIPHY1_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) },
+	[UNIPHY2_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) },
+	[UNIPHY_PORT1_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(23, 22) },
+	[UNIPHY_PORT2_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(21, 20) },
+	[UNIPHY_PORT3_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(19, 18) },
+	[UNIPHY_PORT4_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(17, 16) },
+	[UNIPHY_PORT5_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) },
+	[UNIPHY_PORT6_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) },
+	[NSSPORT1_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(11, 10) },
+	[NSSPORT2_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(9, 8) },
+	[NSSPORT3_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(7, 6) },
+	[NSSPORT4_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(5, 4) },
+	[NSSPORT5_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(3, 2) },
+	[NSSPORT6_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(1, 0) },
+	[EDMA_HW_RESET] =  { .reg = 0x28a08, .bitmask = GENMASK(16, 15) },
+};
+
+static const struct regmap_config nss_cc_ipq9574_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = 0x28a34,
+	.fast_io = true,
+};
+
+static struct qcom_icc_hws_data icc_ipq9574_nss_hws[] = {
+	{ MASTER_NSSNOC_PPE, SLAVE_NSSNOC_PPE, NSS_CC_NSSNOC_PPE_CLK },
+	{ MASTER_NSSNOC_PPE_CFG, SLAVE_NSSNOC_PPE_CFG, NSS_CC_NSSNOC_PPE_CFG_CLK },
+	{ MASTER_NSSNOC_NSS_CSR, SLAVE_NSSNOC_NSS_CSR, NSS_CC_NSSNOC_NSS_CSR_CLK },
+	{ MASTER_NSSNOC_IMEM_QSB, SLAVE_NSSNOC_IMEM_QSB, NSS_CC_NSSNOC_IMEM_QSB_CLK },
+	{ MASTER_NSSNOC_IMEM_AHB, SLAVE_NSSNOC_IMEM_AHB, NSS_CC_NSSNOC_IMEM_AHB_CLK },
+};
+
+#define IPQ_NSSCC_ID	(9574 * 2) /* some unique value */
+
+static const struct qcom_cc_desc nss_cc_ipq9574_desc = {
+	.config = &nss_cc_ipq9574_regmap_config,
+	.clks = nss_cc_ipq9574_clocks,
+	.num_clks = ARRAY_SIZE(nss_cc_ipq9574_clocks),
+	.resets = nss_cc_ipq9574_resets,
+	.num_resets = ARRAY_SIZE(nss_cc_ipq9574_resets),
+	.icc_hws = icc_ipq9574_nss_hws,
+	.num_icc_hws = ARRAY_SIZE(icc_ipq9574_nss_hws),
+	.icc_first_node_id = IPQ_NSSCC_ID,
+};
+
+static const struct dev_pm_ops nss_cc_ipq9574_pm_ops = {
+	SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static const struct of_device_id nss_cc_ipq9574_match_table[] = {
+	{ .compatible = "qcom,ipq9574-nsscc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, nss_cc_ipq9574_match_table);
+
+static int nss_cc_ipq9574_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+	int ret;
+
+	ret = devm_pm_runtime_enable(&pdev->dev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Fail to enable runtime PM\n");
+
+	ret = devm_pm_clk_create(&pdev->dev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Fail to create PM clock\n");
+
+	ret = pm_clk_add(&pdev->dev, "bus");
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n");
+
+	ret = pm_runtime_resume_and_get(&pdev->dev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Fail to resume\n");
+
+	regmap = qcom_cc_map(pdev, &nss_cc_ipq9574_desc);
+	if (IS_ERR(regmap)) {
+		pm_runtime_put(&pdev->dev);
+		return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+				     "Fail to map clock controller registers\n");
+	}
+
+	clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config);
+
+	ret = qcom_cc_really_probe(&pdev->dev, &nss_cc_ipq9574_desc, regmap);
+	pm_runtime_put(&pdev->dev);
+
+	return ret;
+}
+
+static struct platform_driver nss_cc_ipq9574_driver = {
+	.probe = nss_cc_ipq9574_probe,
+	.driver = {
+		.name = "qcom,nsscc-ipq9574",
+		.of_match_table = nss_cc_ipq9574_match_table,
+		.pm = &nss_cc_ipq9574_pm_ops,
+		.sync_state = icc_sync_state,
+	},
+};
+
+module_platform_driver(nss_cc_ipq9574_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. NSSCC IPQ9574 Driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1



From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:59 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:59 +0530
Subject: [PATCH v12 6/6] arm64: defconfig: Build NSS Clock Controller driver for IPQ9574
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-7-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

NSSCC driver is needed to enable the ethernet interfaces present
in RDP433 based on IPQ9574. Since this is not necessary for bootup
enabling it as a module.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- Pick up R-b tag.

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 831afa2c7ea2..ae6ef4454867 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1342,6 +1342,7 @@ CONFIG_IPQ_GCC_5332=y
 CONFIG_IPQ_GCC_6018=y
 CONFIG_IPQ_GCC_8074=y
 CONFIG_IPQ_GCC_9574=y
+CONFIG_IPQ_NSSCC_9574=m
 CONFIG_MSM_GCC_8916=y
 CONFIG_MSM_MMCC_8994=m
 CONFIG_MSM_GCC_8994=y
-- 
2.34.1



From geert at linux-m68k.org  Thu Mar 13 04:13:32 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 13 Mar 2025 12:13:32 +0100
Subject: [PATCH v12 0/6] Add NSS clock controller support for IPQ9574
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <CAMuHMdV_YE2pf+SxXR5sWG1+aG8wv5MtRWk+0+ZF_n8ao7seRg@mail.gmail.com>

Hi Manikanta,

On Thu, 13 Mar 2025 at 12:04, Manikanta Mylavarapu
<quic_mmanikan at quicinc.com> wrote:
> Add bindings, driver and devicetree node for networking sub system clock
> controller on IPQ9574. Also add support for gpll0_out_aux clock
> which serves as the parent for some nss clocks.
>
> Changes in V12:

Thanks for your series!

>  .../bindings/clock/qcom,ipq9574-nsscc.yaml    |   98 +
>  arch/arm64/boot/dts/qcom/ipq9574.dtsi         |   29 +
>  arch/arm64/configs/defconfig                  |    1 +
>  drivers/clk/qcom/Kconfig                      |    7 +
>  drivers/clk/qcom/Makefile                     |    1 +
>  drivers/clk/qcom/gcc-ipq9574.c                |   15 +
>  drivers/clk/qcom/nsscc-ipq9574.c              | 3110 +++++++++++++++++
>  include/dt-bindings/clock/qcom,ipq9574-gcc.h  |    1 +
>  .../dt-bindings/clock/qcom,ipq9574-nsscc.h    |  152 +
>  .../dt-bindings/reset/qcom,ipq9574-nsscc.h    |  134 +

I don't think you need to CC people who just modified the arm64
defconfig before, but never touched qcom clock drivers.  The list of
maintainers and reviewers reported by scripts/get_maintainer.pl is
already quite large.

So please drop me from future submissions.
Thanks!

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From n-francis at ti.com  Thu Mar 13 04:14:06 2025
From: n-francis at ti.com (Neha Malcom Francis)
Date: Thu, 13 Mar 2025 16:44:06 +0530
Subject: [PATCH 1/2] dt-bindings: misc: bist: Add BIST dt-binding for TI
 K3 devices
In-Reply-To: <e57dfc3e-b702-4803-b776-20c6dbd98fef@kernel.org>
References: <20241128140825.263216-1-n-francis@ti.com>
 <20241128140825.263216-2-n-francis@ti.com>
 <ho7ktcnbtl7mvamfthqho23co2fc4z7bgjha7pu4wivxm6ndhu@tfbpveonhckz>
 <837d329b-bcdd-4c3b-b508-e916b110ce25@ti.com>
 <e57dfc3e-b702-4803-b776-20c6dbd98fef@kernel.org>
Message-ID: <8e58b093-1c64-45b9-a9d3-9835a3bbc4fd@ti.com>

Hi Krzysztof

On 29/11/24 14:45, Krzysztof Kozlowski wrote:
> On 29/11/2024 08:43, Neha Malcom Francis wrote:
>>>> +
>>>> +  power-domains:
>>>> +    maxItems: 1
>>>> +
>>>> +  ti,bist-instance:
>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>> +    description:
>>>> +      the BIST instance in the SoC represented as an integer
>>>
>>> No instance indices are allowed. Drop.
>>>
>>
>> Question on this, this is not a property that is driven by software but rather 
>> indicates which register sequences have to be picked up for triggering this test 
>> from this instance. So I don't see how I can workaround this without getting 
>> this number. Or maybe call it ID rather than instance?
> 
> I don't understand how the device operates, so what is exactly behind
> some sequences of registers for triggering this test. You described
> property as index or ID of one instance of the block. That's not what we
> want in the binding. That's said maybe other, different hardware
> characteristic is behind, who knows. Or maybe it's about callers... or
> maybe that's not hardware property at all, but runtime OS, who knows.
> 

Sorry for such a late reply, but I was hoping to get more details on
this "ID" and never got back to the thread...

The best way I can describe is this device (BIST) runs a safety
diagnostic test on a bunch of processors/blocks (let's call them
targets). There's a mapping between the instance of this device and the
targets it will run the test. This ID was essentially letting the BIST
driver know which are these targets.

Should I perhaps trigger it the other way around; a target driver asks
for it's safety test to be run by pointing to the BIST instance? However
the issue with this approach is, the architecture of this safety test
device is that once triggered, it will run the test on all the targets
it controls and that should be reflected in the software arch as well right?

Yet another way would be the BIST points out the targets it controls via
their phandles in its node... but this approach would trigger the probe
of these targets before the test runs on them. And in hardware, the test
must run only one before the device is used, else we see indefinite
behavior.


> Best regards,
> Krzysztof

-- 
Thanking You
Neha Malcom Francis


From antonin.godard at bootlin.com  Thu Mar 13 04:14:26 2025
From: antonin.godard at bootlin.com (Antonin Godard)
Date: Thu, 13 Mar 2025 12:14:26 +0100
Subject: [PATCH v3 1/3] dt-bindings: arm: fsl: Add VAR-SOM-MX6UL SoM and
 Concerto board
In-Reply-To: <20250311-omniscient-fiery-bison-8e7feb@lemur>
References: <20250310-varsom6ul-concerto-dts-v3-0-551e60713523@bootlin.com>
 <20250310-varsom6ul-concerto-dts-v3-1-551e60713523@bootlin.com>
 <63f8aa7d-fcd4-450f-b3a1-44886a29fc7e@kernel.org>
 <cd2f3c97-53bb-42f5-a3cd-4385bfda5dc7@kernel.org>
 <D8CQAAKOZ1O5.8JVESQPJSSM8@bootlin.com>
 <20250311-omniscient-fiery-bison-8e7feb@lemur>
Message-ID: <D8F3F4YLD0ZM.19X0451BIIDVO@bootlin.com>

Hi Konstantin,

On Tue Mar 11, 2025 at 7:34 PM CET, Konstantin Ryabitsev wrote:
> On Mon, Mar 10, 2025 at 05:31:32PM +0100, Antonin Godard wrote:
>> > And now I noticed you used b4, so I really do not get how the tags can
>> > be missing here. :/
>> 
>> Sorry, that's totally my fault here, I forgot to run 'b4 trailers -u' before
>> sending... :/ And I don't think it's part of the prep checks?
>
> Mostly, because there's no clear picture of how this would work reliably. All
> other checks are on a "ran since modifications to the series" basis, but this
> one would have to be time-based.
>
> Should it check if the trailer updates have been run in the past XX minutes
> (and how long should that XX be?).

Had some thoughts about this the past few days.

What about checking if it was run at least once between vX and vX+1? Maybe
during the `b4 send` command? In case it wasn't run, give a hint/warning to the
user before proceeding?

This could also be enforced with an b4 config option like
b4.force-trailers-update - either set by the user or the project configuration.
Not so sure about this one though...

Now if I were to speak for myself, I would love to have an option that just
fetches the new trailers during `b4 send` and errors out / warns me about
it if there's anything new that isn't part of my series. Which could be also
ignored with --ignore-trailer-errors or something like that, in any case.

Antonin

-- 
Antonin Godard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From krzk at kernel.org  Thu Mar 13 04:04:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 13 Mar 2025 12:04:20 +0100
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <20250312122750.6391-1-purvayeshi550@gmail.com>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
Message-ID: <b2f6a357-a468-4526-a1b6-69ab2c643b2c@kernel.org>

On 12/03/2025 13:27, Purva Yeshi wrote:
> Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
> YAML schema (`nxp,lpc3220-pwm.yaml`).
> 
> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.
> 
> Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>


---

<form letter>
This is an automated instruction, just in case, because many review tags
are being ignored. If you know the process, you can skip it (please do
not feel offended by me posting it here - no bad intentions intended).
If you do not know the process, here is a short explanation:

Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Full context and explanation:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
</form letter>

Best regards,
Krzysztof


From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:53 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:53 +0530
Subject: [PATCH v12 0/6] Add NSS clock controller support for IPQ9574
Message-ID: <20250313110359.242491-1-quic_mmanikan@quicinc.com>

Add bindings, driver and devicetree node for networking sub system clock
controller on IPQ9574. Also add support for gpll0_out_aux clock
which serves as the parent for some nss clocks.

Changes in V12:
	- nsscc driver
		- Pick up R-b tag.
	- dtsi
		- Pick up R-b tag.
	- defconfig
		- Pick up R-b tag.
	- Rebased on linux-next tip.

V11 can be found at:
https://lore.kernel.org/linux-arm-msm/20250226075449.136544-1-quic_mmanikan at quicinc.com/

V10 can be found at:
https://lore.kernel.org/linux-arm-msm/20250221101426.776377-1-quic_mmanikan at quicinc.com/

V9 can be found at:
https://lore.kernel.org/linux-arm-msm/20250207073926.2735129-1-quic_mmanikan at quicinc.com/

V8 can be found at:
https://lore.kernel.org/linux-arm-msm/20241025035520.1841792-1-quic_mmanikan at quicinc.com/

V7 can be found at:
https://lore.kernel.org/linux-arm-msm/20241009074125.794997-1-quic_mmanikan at quicinc.com/

V6 can be found at:
https://lore.kernel.org/linux-arm-msm/20241004080332.853503-1-quic_mmanikan at quicinc.com/

V5 can be found at:
https://lore.kernel.org/linux-arm-msm/20240626143302.810632-1-quic_devipriy at quicinc.com/

V4 can be found at:
https://lore.kernel.org/linux-arm-msm/20240625070536.3043630-1-quic_devipriy at quicinc.com/

V3 can be found at:
https://lore.kernel.org/linux-arm-msm/20240129051104.1855487-1-quic_devipriy at quicinc.com/

V2 can be found at:
https://lore.kernel.org/linux-arm-msm/20230825091234.32713-1-quic_devipriy at quicinc.com/

Devi Priya (6):
  dt-bindings: clock: gcc-ipq9574: Add definition for GPLL0_OUT_AUX
  clk: qcom: gcc-ipq9574: Add support for gpll0_out_aux clock
  dt-bindings: clock: Add ipq9574 NSSCC clock and reset definitions
  clk: qcom: Add NSS clock Controller driver for IPQ9574
  arm64: dts: qcom: ipq9574: Add nsscc node
  arm64: defconfig: Build NSS Clock Controller driver for IPQ9574

 .../bindings/clock/qcom,ipq9574-nsscc.yaml    |   98 +
 arch/arm64/boot/dts/qcom/ipq9574.dtsi         |   29 +
 arch/arm64/configs/defconfig                  |    1 +
 drivers/clk/qcom/Kconfig                      |    7 +
 drivers/clk/qcom/Makefile                     |    1 +
 drivers/clk/qcom/gcc-ipq9574.c                |   15 +
 drivers/clk/qcom/nsscc-ipq9574.c              | 3110 +++++++++++++++++
 include/dt-bindings/clock/qcom,ipq9574-gcc.h  |    1 +
 .../dt-bindings/clock/qcom,ipq9574-nsscc.h    |  152 +
 .../dt-bindings/reset/qcom,ipq9574-nsscc.h    |  134 +
 10 files changed, 3548 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
 create mode 100644 drivers/clk/qcom/nsscc-ipq9574.c
 create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h
 create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h


base-commit: 9fbcd7b32bf7c0a5bda0f22c25df29d00a872017
-- 
2.34.1



From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:54 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:54 +0530
Subject: [PATCH v12 1/6] dt-bindings: clock: gcc-ipq9574: Add definition for GPLL0_OUT_AUX
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-2-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

Add the definition for GPLL0_OUT_AUX clock.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- No change.

 include/dt-bindings/clock/qcom,ipq9574-gcc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/qcom,ipq9574-gcc.h b/include/dt-bindings/clock/qcom,ipq9574-gcc.h
index f238aa4794a8..0e7c319897f3 100644
--- a/include/dt-bindings/clock/qcom,ipq9574-gcc.h
+++ b/include/dt-bindings/clock/qcom,ipq9574-gcc.h
@@ -202,4 +202,5 @@
 #define GCC_PCIE1_PIPE_CLK				211
 #define GCC_PCIE2_PIPE_CLK				212
 #define GCC_PCIE3_PIPE_CLK				213
+#define GPLL0_OUT_AUX					214
 #endif
-- 
2.34.1



From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:55 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:55 +0530
Subject: [PATCH v12 2/6] clk: qcom: gcc-ipq9574: Add support for gpll0_out_aux clock
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-3-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

Add support for gpll0_out_aux clock which acts as the parent for
certain networking subsystem (nss) clocks.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- No change.

 drivers/clk/qcom/gcc-ipq9574.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
index 6bb66a7e1fb6..6dc86e686de4 100644
--- a/drivers/clk/qcom/gcc-ipq9574.c
+++ b/drivers/clk/qcom/gcc-ipq9574.c
@@ -108,6 +108,20 @@ static struct clk_alpha_pll_postdiv gpll0 = {
 	},
 };
 
+static struct clk_alpha_pll_postdiv gpll0_out_aux = {
+	.offset = 0x20000,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.width = 4,
+	.clkr.hw.init = &(const struct clk_init_data) {
+		.name = "gpll0_out_aux",
+		.parent_hws = (const struct clk_hw *[]) {
+			&gpll0_main.clkr.hw
+		},
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ro_ops,
+	},
+};
+
 static struct clk_alpha_pll gpll4_main = {
 	.offset = 0x22000,
 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO],
@@ -3896,6 +3910,7 @@ static struct clk_regmap *gcc_ipq9574_clks[] = {
 	[GCC_PCIE1_PIPE_CLK] = &gcc_pcie1_pipe_clk.clkr,
 	[GCC_PCIE2_PIPE_CLK] = &gcc_pcie2_pipe_clk.clkr,
 	[GCC_PCIE3_PIPE_CLK] = &gcc_pcie3_pipe_clk.clkr,
+	[GPLL0_OUT_AUX] = &gpll0_out_aux.clkr,
 };
 
 static const struct qcom_reset_map gcc_ipq9574_resets[] = {
-- 
2.34.1



From quic_mmanikan at quicinc.com  Thu Mar 13 04:03:56 2025
From: quic_mmanikan at quicinc.com (Manikanta Mylavarapu)
Date: Thu, 13 Mar 2025 16:33:56 +0530
Subject: [PATCH v12 3/6] dt-bindings: clock: Add ipq9574 NSSCC clock and reset definitions
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <20250313110359.242491-4-quic_mmanikan@quicinc.com>

From: Devi Priya <quic_devipriy at quicinc.com>

Add NSSCC clock and reset definitions for ipq9574.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Devi Priya <quic_devipriy at quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan at quicinc.com>
---
Changes in V12:
	- No change.

 .../bindings/clock/qcom,ipq9574-nsscc.yaml    |  98 +++++++++++
 .../dt-bindings/clock/qcom,ipq9574-nsscc.h    | 152 ++++++++++++++++++
 .../dt-bindings/reset/qcom,ipq9574-nsscc.h    | 134 +++++++++++++++
 3 files changed, 384 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
 create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h
 create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h

diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
new file mode 100644
index 000000000000..17252b6ea3be
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-nsscc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Networking Sub System Clock & Reset Controller on IPQ9574
+
+maintainers:
+  - Bjorn Andersson <andersson at kernel.org>
+  - Anusha Rao <quic_anusha at quicinc.com>
+
+description: |
+  Qualcomm networking sub system clock control module provides the clocks,
+  resets on IPQ9574
+
+  See also::
+    include/dt-bindings/clock/qcom,ipq9574-nsscc.h
+    include/dt-bindings/reset/qcom,ipq9574-nsscc.h
+
+properties:
+  compatible:
+    const: qcom,ipq9574-nsscc
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: CMN_PLL NSS 1200MHz (Bias PLL cc) clock source
+      - description: CMN_PLL PPE 353MHz (Bias PLL ubi nc) clock source
+      - description: GCC GPLL0 OUT AUX clock source
+      - description: Uniphy0 NSS Rx clock source
+      - description: Uniphy0 NSS Tx clock source
+      - description: Uniphy1 NSS Rx clock source
+      - description: Uniphy1 NSS Tx clock source
+      - description: Uniphy2 NSS Rx clock source
+      - description: Uniphy2 NSS Tx clock source
+      - description: GCC NSSCC clock source
+
+  '#interconnect-cells':
+    const: 1
+
+  clock-names:
+    items:
+      - const: xo
+      - const: nss_1200
+      - const: ppe_353
+      - const: gpll0_out
+      - const: uniphy0_rx
+      - const: uniphy0_tx
+      - const: uniphy1_rx
+      - const: uniphy1_tx
+      - const: uniphy2_rx
+      - const: uniphy2_tx
+      - const: bus
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+
+allOf:
+  - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,ipq9574-gcc.h>
+    #include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
+    clock-controller at 39b00000 {
+      compatible = "qcom,ipq9574-nsscc";
+      reg = <0x39b00000 0x80000>;
+      clocks = <&xo_board_clk>,
+               <&cmn_pll NSS_1200MHZ_CLK>,
+               <&cmn_pll PPE_353MHZ_CLK>,
+               <&gcc GPLL0_OUT_AUX>,
+               <&uniphy 0>,
+               <&uniphy 1>,
+               <&uniphy 2>,
+               <&uniphy 3>,
+               <&uniphy 4>,
+               <&uniphy 5>,
+               <&gcc GCC_NSSCC_CLK>;
+      clock-names = "xo",
+                    "nss_1200",
+                    "ppe_353",
+                    "gpll0_out",
+                    "uniphy0_rx",
+                    "uniphy0_tx",
+                    "uniphy1_rx",
+                    "uniphy1_tx",
+                    "uniphy2_rx",
+                    "uniphy2_tx",
+                    "bus";
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+    };
+...
diff --git a/include/dt-bindings/clock/qcom,ipq9574-nsscc.h b/include/dt-bindings/clock/qcom,ipq9574-nsscc.h
new file mode 100644
index 000000000000..21a16dc0e64c
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq9574-nsscc.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H
+#define _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H
+
+#define NSS_CC_CE_APB_CLK					0
+#define NSS_CC_CE_AXI_CLK					1
+#define NSS_CC_CE_CLK_SRC					2
+#define NSS_CC_CFG_CLK_SRC					3
+#define NSS_CC_CLC_AXI_CLK					4
+#define NSS_CC_CLC_CLK_SRC					5
+#define NSS_CC_CRYPTO_CLK					6
+#define NSS_CC_CRYPTO_CLK_SRC					7
+#define NSS_CC_CRYPTO_PPE_CLK					8
+#define NSS_CC_HAQ_AHB_CLK					9
+#define NSS_CC_HAQ_AXI_CLK					10
+#define NSS_CC_HAQ_CLK_SRC					11
+#define NSS_CC_IMEM_AHB_CLK					12
+#define NSS_CC_IMEM_CLK_SRC					13
+#define NSS_CC_IMEM_QSB_CLK					14
+#define NSS_CC_INT_CFG_CLK_SRC					15
+#define NSS_CC_NSS_CSR_CLK					16
+#define NSS_CC_NSSNOC_CE_APB_CLK				17
+#define NSS_CC_NSSNOC_CE_AXI_CLK				18
+#define NSS_CC_NSSNOC_CLC_AXI_CLK				19
+#define NSS_CC_NSSNOC_CRYPTO_CLK				20
+#define NSS_CC_NSSNOC_HAQ_AHB_CLK				21
+#define NSS_CC_NSSNOC_HAQ_AXI_CLK				22
+#define NSS_CC_NSSNOC_IMEM_AHB_CLK				23
+#define NSS_CC_NSSNOC_IMEM_QSB_CLK				24
+#define NSS_CC_NSSNOC_NSS_CSR_CLK				25
+#define NSS_CC_NSSNOC_PPE_CFG_CLK				26
+#define NSS_CC_NSSNOC_PPE_CLK					27
+#define NSS_CC_NSSNOC_UBI32_AHB0_CLK				28
+#define NSS_CC_NSSNOC_UBI32_AXI0_CLK				29
+#define NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK			30
+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK			31
+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK				32
+#define NSS_CC_PORT1_MAC_CLK					33
+#define NSS_CC_PORT1_RX_CLK					34
+#define NSS_CC_PORT1_RX_CLK_SRC					35
+#define NSS_CC_PORT1_RX_DIV_CLK_SRC				36
+#define NSS_CC_PORT1_TX_CLK					37
+#define NSS_CC_PORT1_TX_CLK_SRC					38
+#define NSS_CC_PORT1_TX_DIV_CLK_SRC				39
+#define NSS_CC_PORT2_MAC_CLK					40
+#define NSS_CC_PORT2_RX_CLK					41
+#define NSS_CC_PORT2_RX_CLK_SRC					42
+#define NSS_CC_PORT2_RX_DIV_CLK_SRC				43
+#define NSS_CC_PORT2_TX_CLK					44
+#define NSS_CC_PORT2_TX_CLK_SRC					45
+#define NSS_CC_PORT2_TX_DIV_CLK_SRC				46
+#define NSS_CC_PORT3_MAC_CLK					47
+#define NSS_CC_PORT3_RX_CLK					48
+#define NSS_CC_PORT3_RX_CLK_SRC					49
+#define NSS_CC_PORT3_RX_DIV_CLK_SRC				50
+#define NSS_CC_PORT3_TX_CLK					51
+#define NSS_CC_PORT3_TX_CLK_SRC					52
+#define NSS_CC_PORT3_TX_DIV_CLK_SRC				53
+#define NSS_CC_PORT4_MAC_CLK					54
+#define NSS_CC_PORT4_RX_CLK					55
+#define NSS_CC_PORT4_RX_CLK_SRC					56
+#define NSS_CC_PORT4_RX_DIV_CLK_SRC				57
+#define NSS_CC_PORT4_TX_CLK					58
+#define NSS_CC_PORT4_TX_CLK_SRC					59
+#define NSS_CC_PORT4_TX_DIV_CLK_SRC				60
+#define NSS_CC_PORT5_MAC_CLK					61
+#define NSS_CC_PORT5_RX_CLK					62
+#define NSS_CC_PORT5_RX_CLK_SRC					63
+#define NSS_CC_PORT5_RX_DIV_CLK_SRC				64
+#define NSS_CC_PORT5_TX_CLK					65
+#define NSS_CC_PORT5_TX_CLK_SRC					66
+#define NSS_CC_PORT5_TX_DIV_CLK_SRC				67
+#define NSS_CC_PORT6_MAC_CLK					68
+#define NSS_CC_PORT6_RX_CLK					69
+#define NSS_CC_PORT6_RX_CLK_SRC					70
+#define NSS_CC_PORT6_RX_DIV_CLK_SRC				71
+#define NSS_CC_PORT6_TX_CLK					72
+#define NSS_CC_PORT6_TX_CLK_SRC					73
+#define NSS_CC_PORT6_TX_DIV_CLK_SRC				74
+#define NSS_CC_PPE_CLK_SRC					75
+#define NSS_CC_PPE_EDMA_CFG_CLK					76
+#define NSS_CC_PPE_EDMA_CLK					77
+#define NSS_CC_PPE_SWITCH_BTQ_CLK				78
+#define NSS_CC_PPE_SWITCH_CFG_CLK				79
+#define NSS_CC_PPE_SWITCH_CLK					80
+#define NSS_CC_PPE_SWITCH_IPE_CLK				81
+#define NSS_CC_UBI0_CLK_SRC					82
+#define NSS_CC_UBI0_DIV_CLK_SRC					83
+#define NSS_CC_UBI1_CLK_SRC					84
+#define NSS_CC_UBI1_DIV_CLK_SRC					85
+#define NSS_CC_UBI2_CLK_SRC					86
+#define NSS_CC_UBI2_DIV_CLK_SRC					87
+#define NSS_CC_UBI32_AHB0_CLK					88
+#define NSS_CC_UBI32_AHB1_CLK					89
+#define NSS_CC_UBI32_AHB2_CLK					90
+#define NSS_CC_UBI32_AHB3_CLK					91
+#define NSS_CC_UBI32_AXI0_CLK					92
+#define NSS_CC_UBI32_AXI1_CLK					93
+#define NSS_CC_UBI32_AXI2_CLK					94
+#define NSS_CC_UBI32_AXI3_CLK					95
+#define NSS_CC_UBI32_CORE0_CLK					96
+#define NSS_CC_UBI32_CORE1_CLK					97
+#define NSS_CC_UBI32_CORE2_CLK					98
+#define NSS_CC_UBI32_CORE3_CLK					99
+#define NSS_CC_UBI32_INTR0_AHB_CLK				100
+#define NSS_CC_UBI32_INTR1_AHB_CLK				101
+#define NSS_CC_UBI32_INTR2_AHB_CLK				102
+#define NSS_CC_UBI32_INTR3_AHB_CLK				103
+#define NSS_CC_UBI32_NC_AXI0_CLK				104
+#define NSS_CC_UBI32_NC_AXI1_CLK				105
+#define NSS_CC_UBI32_NC_AXI2_CLK				106
+#define NSS_CC_UBI32_NC_AXI3_CLK				107
+#define NSS_CC_UBI32_UTCM0_CLK					108
+#define NSS_CC_UBI32_UTCM1_CLK					109
+#define NSS_CC_UBI32_UTCM2_CLK					110
+#define NSS_CC_UBI32_UTCM3_CLK					111
+#define NSS_CC_UBI3_CLK_SRC					112
+#define NSS_CC_UBI3_DIV_CLK_SRC					113
+#define NSS_CC_UBI_AXI_CLK_SRC					114
+#define NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC				115
+#define NSS_CC_UNIPHY_PORT1_RX_CLK				116
+#define NSS_CC_UNIPHY_PORT1_TX_CLK				117
+#define NSS_CC_UNIPHY_PORT2_RX_CLK				118
+#define NSS_CC_UNIPHY_PORT2_TX_CLK				119
+#define NSS_CC_UNIPHY_PORT3_RX_CLK				120
+#define NSS_CC_UNIPHY_PORT3_TX_CLK				121
+#define NSS_CC_UNIPHY_PORT4_RX_CLK				122
+#define NSS_CC_UNIPHY_PORT4_TX_CLK				123
+#define NSS_CC_UNIPHY_PORT5_RX_CLK				124
+#define NSS_CC_UNIPHY_PORT5_TX_CLK				125
+#define NSS_CC_UNIPHY_PORT6_RX_CLK				126
+#define NSS_CC_UNIPHY_PORT6_TX_CLK				127
+#define NSS_CC_XGMAC0_PTP_REF_CLK				128
+#define NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC			129
+#define NSS_CC_XGMAC1_PTP_REF_CLK				130
+#define NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC			131
+#define NSS_CC_XGMAC2_PTP_REF_CLK				132
+#define NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC			133
+#define NSS_CC_XGMAC3_PTP_REF_CLK				134
+#define NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC			135
+#define NSS_CC_XGMAC4_PTP_REF_CLK				136
+#define NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC			137
+#define NSS_CC_XGMAC5_PTP_REF_CLK				138
+#define NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC			139
+#define UBI32_PLL						140
+#define UBI32_PLL_MAIN						141
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,ipq9574-nsscc.h b/include/dt-bindings/reset/qcom,ipq9574-nsscc.h
new file mode 100644
index 000000000000..7f152e98b99c
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,ipq9574-nsscc.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H
+#define _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H
+
+#define EDMA_HW_RESET                   0
+#define NSS_CC_CE_BCR			1
+#define NSS_CC_CLC_BCR			2
+#define NSS_CC_EIP197_BCR		3
+#define NSS_CC_HAQ_BCR			4
+#define NSS_CC_IMEM_BCR			5
+#define NSS_CC_MAC_BCR			6
+#define NSS_CC_PPE_BCR			7
+#define NSS_CC_UBI_BCR			8
+#define NSS_CC_UNIPHY_BCR		9
+#define UBI3_CLKRST_CLAMP_ENABLE	10
+#define UBI3_CORE_CLAMP_ENABLE		11
+#define UBI2_CLKRST_CLAMP_ENABLE	12
+#define UBI2_CORE_CLAMP_ENABLE		13
+#define UBI1_CLKRST_CLAMP_ENABLE	14
+#define UBI1_CORE_CLAMP_ENABLE		15
+#define UBI0_CLKRST_CLAMP_ENABLE	16
+#define UBI0_CORE_CLAMP_ENABLE		17
+#define NSSNOC_NSS_CSR_ARES		18
+#define NSS_CSR_ARES			19
+#define PPE_BTQ_ARES			20
+#define PPE_IPE_ARES			21
+#define PPE_ARES			22
+#define PPE_CFG_ARES			23
+#define PPE_EDMA_ARES			24
+#define PPE_EDMA_CFG_ARES		25
+#define CRY_PPE_ARES			26
+#define NSSNOC_PPE_ARES			27
+#define NSSNOC_PPE_CFG_ARES		28
+#define PORT1_MAC_ARES			29
+#define PORT2_MAC_ARES			30
+#define PORT3_MAC_ARES			31
+#define PORT4_MAC_ARES			32
+#define PORT5_MAC_ARES			33
+#define PORT6_MAC_ARES			34
+#define XGMAC0_PTP_REF_ARES		35
+#define XGMAC1_PTP_REF_ARES		36
+#define XGMAC2_PTP_REF_ARES		37
+#define XGMAC3_PTP_REF_ARES		38
+#define XGMAC4_PTP_REF_ARES		39
+#define XGMAC5_PTP_REF_ARES		40
+#define HAQ_AHB_ARES			41
+#define HAQ_AXI_ARES			42
+#define NSSNOC_HAQ_AHB_ARES		43
+#define NSSNOC_HAQ_AXI_ARES		44
+#define CE_APB_ARES			45
+#define CE_AXI_ARES			46
+#define NSSNOC_CE_APB_ARES		47
+#define NSSNOC_CE_AXI_ARES		48
+#define CRYPTO_ARES			49
+#define NSSNOC_CRYPTO_ARES		50
+#define NSSNOC_NC_AXI0_1_ARES		51
+#define UBI0_CORE_ARES			52
+#define UBI1_CORE_ARES			53
+#define UBI2_CORE_ARES			54
+#define UBI3_CORE_ARES			55
+#define NC_AXI0_ARES			56
+#define UTCM0_ARES			57
+#define NC_AXI1_ARES			58
+#define UTCM1_ARES			59
+#define NC_AXI2_ARES			60
+#define UTCM2_ARES			61
+#define NC_AXI3_ARES			62
+#define UTCM3_ARES			63
+#define NSSNOC_NC_AXI0_ARES		64
+#define AHB0_ARES			65
+#define INTR0_AHB_ARES			66
+#define AHB1_ARES			67
+#define INTR1_AHB_ARES			68
+#define AHB2_ARES			69
+#define INTR2_AHB_ARES			70
+#define AHB3_ARES			71
+#define INTR3_AHB_ARES			72
+#define NSSNOC_AHB0_ARES		73
+#define NSSNOC_INT0_AHB_ARES		74
+#define AXI0_ARES			75
+#define AXI1_ARES			76
+#define AXI2_ARES			77
+#define AXI3_ARES			78
+#define NSSNOC_AXI0_ARES		79
+#define IMEM_QSB_ARES			80
+#define NSSNOC_IMEM_QSB_ARES		81
+#define IMEM_AHB_ARES			82
+#define NSSNOC_IMEM_AHB_ARES		83
+#define UNIPHY_PORT1_RX_ARES		84
+#define UNIPHY_PORT1_TX_ARES		85
+#define UNIPHY_PORT2_RX_ARES		86
+#define UNIPHY_PORT2_TX_ARES		87
+#define UNIPHY_PORT3_RX_ARES		88
+#define UNIPHY_PORT3_TX_ARES		89
+#define UNIPHY_PORT4_RX_ARES		90
+#define UNIPHY_PORT4_TX_ARES		91
+#define UNIPHY_PORT5_RX_ARES		92
+#define UNIPHY_PORT5_TX_ARES		93
+#define UNIPHY_PORT6_RX_ARES		94
+#define UNIPHY_PORT6_TX_ARES		95
+#define PORT1_RX_ARES			96
+#define PORT1_TX_ARES			97
+#define PORT2_RX_ARES			98
+#define PORT2_TX_ARES			99
+#define PORT3_RX_ARES			100
+#define PORT3_TX_ARES			101
+#define PORT4_RX_ARES			102
+#define PORT4_TX_ARES			103
+#define PORT5_RX_ARES			104
+#define PORT5_TX_ARES			105
+#define PORT6_RX_ARES			106
+#define PORT6_TX_ARES			107
+#define PPE_FULL_RESET			108
+#define UNIPHY0_SOFT_RESET		109
+#define UNIPHY1_SOFT_RESET		110
+#define UNIPHY2_SOFT_RESET		111
+#define UNIPHY_PORT1_ARES		112
+#define UNIPHY_PORT2_ARES		113
+#define UNIPHY_PORT3_ARES		114
+#define UNIPHY_PORT4_ARES		115
+#define UNIPHY_PORT5_ARES		116
+#define UNIPHY_PORT6_ARES		117
+#define NSSPORT1_RESET			118
+#define NSSPORT2_RESET			119
+#define NSSPORT3_RESET			120
+#define NSSPORT4_RESET			121
+#define NSSPORT5_RESET			122
+#define NSSPORT6_RESET			123
+
+#endif
-- 
2.34.1



From suzuki.poulose at arm.com  Thu Mar 13 04:22:07 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 13 Mar 2025 11:22:07 +0000
Subject: [PATCH v3 0/3] Initial BBML2 support for contpte_convert()
In-Reply-To: <20250313104111.24196-2-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
Message-ID: <e8749c86-fe93-4123-aa2e-5677e7a2c695@arm.com>

Hi Miko,

On 13/03/2025 10:41, Miko?aj Lenczewski wrote:
> Hi All,
> 
> This patch series adds adding initial support for eliding
> break-before-make requirements on systems that support BBML2 and
> additionally guarantee to never raise a conflict abort.
> 
> This support elides a TLB invalidation in contpte_convert(). This
> leads to a 12% improvement when executing a microbenchmark designed
> to force the pathological path where contpte_convert() gets called.
> This represents an 80% reduction in the cost of calling
> contpte_convert().
> 
> This series is based on v6.14-rc4 (d082ecbc71e9).
> 
> Patch 1 implements an allow-list of cpus that support BBML2, but with
> the additional constraint of never causing TLB conflict aborts. We
> settled on this constraint because we will use the feature for kernel
> mappings in the future, for which we cannot handle conflict aborts
> safely.
> 
> Yang Shi has a series at [1] that aims to use BBML2 to enable splitting
> the linear map at runtime. This series partially overlaps with it to add
> the cpu feature. We believe this series is fully compatible with Yang's
> requirements and could go first.
> 

Nothing about the patch functionality, but :

Minor nit: Generally it is a good idea to add "What changed" from the
previous posting.  That gives the reviewers an idea of what to look for
in the new version. Something like:

Changes since V2:
  {Adding a link to the posting is an added bonus, as we can look up the 
discussions easily}
  - blah blah
  - ..


Cheers
Suzuki


> [1]:
>    https://lore.kernel.org/linux-arm-kernel/20250304222018.615808-1-yang at os.amperecomputing.com/
> 
> Miko?aj Lenczewski (3):
>    arm64: Add BBM Level 2 cpu feature
>    iommu/arm: Add BBM Level 2 smmu feature
>    arm64/mm: Elide tlbi in contpte_convert() under BBML2
> 
>   .../admin-guide/kernel-parameters.txt         |  3 +
>   arch/arm64/Kconfig                            | 11 +++
>   arch/arm64/include/asm/cpucaps.h              |  2 +
>   arch/arm64/include/asm/cpufeature.h           |  6 ++
>   arch/arm64/kernel/cpufeature.c                | 76 +++++++++++++++++++
>   arch/arm64/kernel/pi/idreg-override.c         |  2 +
>   arch/arm64/mm/contpte.c                       |  3 +-
>   arch/arm64/tools/cpucaps                      |  1 +
>   .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  3 +
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  3 +
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  4 +
>   11 files changed, 113 insertions(+), 1 deletion(-)
> 



From leo.yan at arm.com  Thu Mar 13 04:24:57 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 11:24:57 +0000
Subject: [PATCH 1/7] coresight: Rename coresight_{set,clear}_claim_tags()
In-Reply-To: <20250211103945.967495-2-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-2-james.clark@linaro.org>
Message-ID: <20250313112457.GO9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:37AM +0000, James Clark wrote:
> 
> These look like they set the whole tags register as one value, but they
> only set and clear the self hosted bit using a SET/CLR bits mechanism.
> Rename the functions to reflect this better.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-core.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 0a9380350fb5..523dbb381f90 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -142,14 +142,14 @@ static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>         return coresight_read_claim_tags(csdev) != 0;
>  }
> 
> -static inline void coresight_set_claim_tags(struct coresight_device *csdev)
> +static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
>  {
>         csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>                                      CORESIGHT_CLAIMSET);
>         isb();
>  }
> 
> -static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
> +static inline void coresight_clear_self_claim_tag(struct coresight_device *csdev)
>  {
>         csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>                                      CORESIGHT_CLAIMCLR);
> @@ -174,11 +174,11 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
>         if (coresight_is_claimed_any(csdev))
>                 return -EBUSY;
> 
> -       coresight_set_claim_tags(csdev);
> +       coresight_set_self_claim_tag(csdev);
>         if (coresight_is_claimed_self_hosted(csdev))
>                 return 0;
> -       /* There was a race setting the tags, clean up and fail */
> -       coresight_clear_claim_tags(csdev);
> +       /* There was a race setting the tag, clean up and fail */
> +       coresight_clear_self_claim_tag(csdev);
>         return -EBUSY;
>  }
>  EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
> @@ -199,7 +199,7 @@ int coresight_claim_device(struct coresight_device *csdev)
>  EXPORT_SYMBOL_GPL(coresight_claim_device);
> 
>  /*
> - * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
> + * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
>   * Called with CS_UNLOCKed for the component.
>   */
>  void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
> @@ -209,7 +209,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>                 return;
> 
>         if (coresight_is_claimed_self_hosted(csdev))
> -               coresight_clear_claim_tags(csdev);
> +               coresight_clear_self_claim_tag(csdev);
>         else
>                 /*
>                  * The external agent may have not honoured our claim
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From robin.murphy at arm.com  Thu Mar 13 04:29:23 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 11:29:23 +0000
Subject: arm64: Kernel crash at devm_kmalloc include/linux/device.h:
 drivers/base/devres.c
In-Reply-To: <CA+G9fYugh0pBb_XwqnDM344JqCookWZe6EWQf1sLS7Oy-SdL5g@mail.gmail.com>
References: <CA+G9fYugh0pBb_XwqnDM344JqCookWZe6EWQf1sLS7Oy-SdL5g@mail.gmail.com>
Message-ID: <9751cdf9-be27-40b4-a9f4-1e840eaf24ab@arm.com>

On 2025-03-13 11:26 am, Naresh Kamboju wrote:
> Regression on arm64 FVP and rock-pi-4-b while booting the Linux next-20250312
> and next-20250313. the following crash noticed with KVM Kconfigs.
> 
> First seen on next-20250312.
> Good: next-20250311
> Bad: 6.14.0-rc6-next-20250312 and 6.14.0-rc6-next-20250313

Yup, I just posted a potential fix here:

https://lore.kernel.org/linux-iommu/417d6f59-0d78-4e81-ad0b-e06846f786b0 at arm.com/

Thanks,
Robin.

> Boot regression: arm64 devm_kmalloc rk_iommu_of_xlate kernel panic
> Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>
> 
> ## Boot log
> [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> [    0.000000] Linux version 6.14.0-rc6-next-20250313
> (tuxmake at tuxmake) (aarch64-linux-gnu-gcc (Debian 13.3.0-12) 13.3.0,
> GNU ld (GNU Binutils for Debian) 2.44) #1 SMP PREEMPT @1741850074
> [    0.000000] KASLR disabled due to lack of seed
> [    0.000000] Machine model: Radxa ROCK Pi 4B
> <trim>
> [    1.028830] SuperH (H)SCI(F) driver initialized
> [    1.030168] STM32 USART driver initialized
> [    1.052086] Unable to handle kernel NULL pointer dereference at
> virtual address 00000000000002a0
> [    1.052877] Mem abort info:
> [    1.053137]   ESR = 0x0000000096000004
> [    1.053481]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    1.053960]   SET = 0, FnV = 0
> [    1.054241]   EA = 0, S1PTW = 0
> [    1.054530]   FSC = 0x04: level 0 translation fault
> [    1.054971] Data abort info:
> [    1.055236]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> [    1.055760]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [    1.056216]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [    1.056693] [00000000000002a0] user address but active_mm is swapper
> [    1.057264] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> [    1.057821] Modules linked in:
> [    1.058105] CPU: 4 UID: 0 PID: 1 Comm: swapper/0 Not tainted
> 6.14.0-rc6-next-20250313 #1
> [    1.058823] Hardware name: Radxa ROCK Pi 4B (DT)
> [    1.059236] pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [    1.059854] pc : devm_kmalloc (include/linux/device.h:805
> drivers/base/devres.c:853)
> [    1.060225] lr : rk_iommu_of_xlate (drivers/iommu/rockchip-iommu.c:1152)
> [    1.060614] sp : ffff80008306b7c0
> [    1.060913] x29: ffff80008306b7c0 x28: ffff8000825a9068 x27: ffff80008225ce00
> [    1.061560] x26: 0000000000000001 x25: ffff80008225e188 x24: ffff000000eafa80
> [    1.062206] x23: 0000000000000000 x22: ffff800081af6a98 x21: 0000000000000000
> [    1.062850] x20: 0000000000000010 x19: 0000000000000000 x18: 00000000ffffffff
> [    1.063493] x17: ffff0000019abc00 x16: ffff000001985400 x15: ffff80008306b820
> [    1.064136] x14: ffff000002736a1c x13: ffff00000273627c x12: 0101010101010101
> [    1.064780] x11: 7f7f7f7f7f7f7f7f x10: 000000000016f8a0 x9 : ffff800080b65870
> [    1.065424] x8 : ffff80008306b718 x7 : 0000000000000000 x6 : 0000000000000001
> [    1.066066] x5 : ffff800082890000 x4 : ffff8000828905f0 x3 : 0000000000000000
> [    1.066708] x2 : 0000000000000dc0 x1 : 0000000000000010 x0 : 0000000000000090
> [    1.067351] Call trace:
> [    1.067576] devm_kmalloc (include/linux/device.h:805
> drivers/base/devres.c:853) (P)
> [    1.067937] rk_iommu_of_xlate (drivers/iommu/rockchip-iommu.c:1152)
> [    1.068295] of_iommu_xlate (drivers/iommu/of_iommu.c:39)
> [    1.068629] of_iommu_configure (drivers/iommu/of_iommu.c:71
> drivers/iommu/of_iommu.c:98 drivers/iommu/of_iommu.c:149)
> [    1.069008] of_dma_configure_id (drivers/of/device.c:161)
> [    1.069392] platform_dma_configure (drivers/base/platform.c:1455)
> [    1.069796] __iommu_probe_device (drivers/iommu/iommu.c:430
> drivers/iommu/iommu.c:569)
> [    1.070194] probe_iommu_group (drivers/iommu/iommu.c:1722)
> [    1.070553] bus_for_each_dev (drivers/base/bus.c:370)
> [    1.070906] iommu_device_register (drivers/iommu/iommu.c:1875
> drivers/iommu/iommu.c:276)
> [    1.071304] rk_iommu_probe (drivers/iommu/rockchip-iommu.c:1263)
> [    1.071652] platform_probe (drivers/base/platform.c:1404)
> [    1.071986] really_probe (drivers/base/dd.c:579 drivers/base/dd.c:658)
> [    1.072316] __driver_probe_device (drivers/base/dd.c:800)
> [    1.072716] driver_probe_device (drivers/base/dd.c:830)
> [    1.073100] __driver_attach (drivers/base/dd.c:1217)
> [    1.073453] bus_for_each_dev (drivers/base/bus.c:370)
> [    1.073805] driver_attach (drivers/base/dd.c:1235)
> [    1.074135] bus_add_driver (drivers/base/bus.c:678)
> [    1.074488] driver_register (drivers/base/driver.c:249)
> [    1.074836] __platform_driver_register (drivers/base/platform.c:868)
> [    1.075261] rk_iommu_driver_init (drivers/iommu/rockchip-iommu.c:1380)
> [    1.075644] do_one_initcall (init/main.c:1257)
> [    1.075996] kernel_init_freeable (init/main.c:1318 (discriminator
> 1) init/main.c:1335 (discriminator 1) init/main.c:1354 (discriminator
> 1) init/main.c:1567 (discriminator 1))
> [    1.076393] kernel_init (init/main.c:1461)
> [    1.076720] ret_from_fork (arch/arm64/kernel/entry.S:863)
> [ 1.077053] Code: aa0003f5 b1020020 a90153f3 aa0103f4 (b942a2b7)
> All code
> ========
>     0: aa0003f5 mov x21, x0
>     4: b1020020 adds x0, x1, #0x80
>     8: a90153f3 stp x19, x20, [sp, #16]
>     c: aa0103f4 mov x20, x1
>    10:* b942a2b7 ldr w23, [x21, #672] <-- trapping instruction
> 
> Code starting with the faulting instruction
> ===========================================
>     0: b942a2b7 ldr w23, [x21, #672]
> [    1.077594] ---[ end trace 0000000000000000 ]---
> [    1.078059] Kernel panic - not syncing: Attempted to kill init!
> exitcode=0x0000000b
> [    1.078736] SMP: stopping secondary CPUs
> [    1.079099] Kernel Offset: disabled
> [    1.079412] CPU features: 0x0400,00041058,01000400,8200421b
> [    1.079909] Memory Limit: none
> [    1.080188] ---[ end Kernel panic - not syncing: Attempted to kill
> init! exitcode=0x0000000b ]---
> 
> ## Source
> * Kernel version:  6.14.0-rc6-next-20250313
> * Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
> * Git sha: 613af589b566093ce7388bf3202fca70d742c166
> * Git describe:  6.14.0-rc6-next-20250313
> * Project details:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250305/
> * Architectures: arm64
> * Compilers: gcc-13
> 
> ## Test data
> * Test log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611306/suite/boot/test/gcc-13-lkftconfig/log
> * Test history:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611826/suite/boot/test/gcc-13-lkftconfig/history/
> * Test details:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611306/suite/boot/test/gcc-13-lkftconfig/
> * Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uFgT27J8KGNrdNXzKgUzhFI3YX/
> * Kernel config:
> https://storage.tuxsuite.com/public/linaro/lkft/builds/2uFgT27J8KGNrdNXzKgUzhFI3YX/config
> 
> 
> --
> Linaro LKFT
> https://lkft.linaro.org



From naresh.kamboju at linaro.org  Thu Mar 13 04:26:51 2025
From: naresh.kamboju at linaro.org (Naresh Kamboju)
Date: Thu, 13 Mar 2025 16:56:51 +0530
Subject: arm64: Kernel crash at devm_kmalloc include/linux/device.h: drivers/base/devres.c
Message-ID: <CA+G9fYugh0pBb_XwqnDM344JqCookWZe6EWQf1sLS7Oy-SdL5g@mail.gmail.com>

Regression on arm64 FVP and rock-pi-4-b while booting the Linux next-20250312
and next-20250313. the following crash noticed with KVM Kconfigs.

First seen on next-20250312.
Good: next-20250311
Bad: 6.14.0-rc6-next-20250312 and 6.14.0-rc6-next-20250313

Boot regression: arm64 devm_kmalloc rk_iommu_of_xlate kernel panic
Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>

## Boot log
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 6.14.0-rc6-next-20250313
(tuxmake at tuxmake) (aarch64-linux-gnu-gcc (Debian 13.3.0-12) 13.3.0,
GNU ld (GNU Binutils for Debian) 2.44) #1 SMP PREEMPT @1741850074
[    0.000000] KASLR disabled due to lack of seed
[    0.000000] Machine model: Radxa ROCK Pi 4B
<trim>
[    1.028830] SuperH (H)SCI(F) driver initialized
[    1.030168] STM32 USART driver initialized
[    1.052086] Unable to handle kernel NULL pointer dereference at
virtual address 00000000000002a0
[    1.052877] Mem abort info:
[    1.053137]   ESR = 0x0000000096000004
[    1.053481]   EC = 0x25: DABT (current EL), IL = 32 bits
[    1.053960]   SET = 0, FnV = 0
[    1.054241]   EA = 0, S1PTW = 0
[    1.054530]   FSC = 0x04: level 0 translation fault
[    1.054971] Data abort info:
[    1.055236]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[    1.055760]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[    1.056216]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[    1.056693] [00000000000002a0] user address but active_mm is swapper
[    1.057264] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[    1.057821] Modules linked in:
[    1.058105] CPU: 4 UID: 0 PID: 1 Comm: swapper/0 Not tainted
6.14.0-rc6-next-20250313 #1
[    1.058823] Hardware name: Radxa ROCK Pi 4B (DT)
[    1.059236] pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    1.059854] pc : devm_kmalloc (include/linux/device.h:805
drivers/base/devres.c:853)
[    1.060225] lr : rk_iommu_of_xlate (drivers/iommu/rockchip-iommu.c:1152)
[    1.060614] sp : ffff80008306b7c0
[    1.060913] x29: ffff80008306b7c0 x28: ffff8000825a9068 x27: ffff80008225ce00
[    1.061560] x26: 0000000000000001 x25: ffff80008225e188 x24: ffff000000eafa80
[    1.062206] x23: 0000000000000000 x22: ffff800081af6a98 x21: 0000000000000000
[    1.062850] x20: 0000000000000010 x19: 0000000000000000 x18: 00000000ffffffff
[    1.063493] x17: ffff0000019abc00 x16: ffff000001985400 x15: ffff80008306b820
[    1.064136] x14: ffff000002736a1c x13: ffff00000273627c x12: 0101010101010101
[    1.064780] x11: 7f7f7f7f7f7f7f7f x10: 000000000016f8a0 x9 : ffff800080b65870
[    1.065424] x8 : ffff80008306b718 x7 : 0000000000000000 x6 : 0000000000000001
[    1.066066] x5 : ffff800082890000 x4 : ffff8000828905f0 x3 : 0000000000000000
[    1.066708] x2 : 0000000000000dc0 x1 : 0000000000000010 x0 : 0000000000000090
[    1.067351] Call trace:
[    1.067576] devm_kmalloc (include/linux/device.h:805
drivers/base/devres.c:853) (P)
[    1.067937] rk_iommu_of_xlate (drivers/iommu/rockchip-iommu.c:1152)
[    1.068295] of_iommu_xlate (drivers/iommu/of_iommu.c:39)
[    1.068629] of_iommu_configure (drivers/iommu/of_iommu.c:71
drivers/iommu/of_iommu.c:98 drivers/iommu/of_iommu.c:149)
[    1.069008] of_dma_configure_id (drivers/of/device.c:161)
[    1.069392] platform_dma_configure (drivers/base/platform.c:1455)
[    1.069796] __iommu_probe_device (drivers/iommu/iommu.c:430
drivers/iommu/iommu.c:569)
[    1.070194] probe_iommu_group (drivers/iommu/iommu.c:1722)
[    1.070553] bus_for_each_dev (drivers/base/bus.c:370)
[    1.070906] iommu_device_register (drivers/iommu/iommu.c:1875
drivers/iommu/iommu.c:276)
[    1.071304] rk_iommu_probe (drivers/iommu/rockchip-iommu.c:1263)
[    1.071652] platform_probe (drivers/base/platform.c:1404)
[    1.071986] really_probe (drivers/base/dd.c:579 drivers/base/dd.c:658)
[    1.072316] __driver_probe_device (drivers/base/dd.c:800)
[    1.072716] driver_probe_device (drivers/base/dd.c:830)
[    1.073100] __driver_attach (drivers/base/dd.c:1217)
[    1.073453] bus_for_each_dev (drivers/base/bus.c:370)
[    1.073805] driver_attach (drivers/base/dd.c:1235)
[    1.074135] bus_add_driver (drivers/base/bus.c:678)
[    1.074488] driver_register (drivers/base/driver.c:249)
[    1.074836] __platform_driver_register (drivers/base/platform.c:868)
[    1.075261] rk_iommu_driver_init (drivers/iommu/rockchip-iommu.c:1380)
[    1.075644] do_one_initcall (init/main.c:1257)
[    1.075996] kernel_init_freeable (init/main.c:1318 (discriminator
1) init/main.c:1335 (discriminator 1) init/main.c:1354 (discriminator
1) init/main.c:1567 (discriminator 1))
[    1.076393] kernel_init (init/main.c:1461)
[    1.076720] ret_from_fork (arch/arm64/kernel/entry.S:863)
[ 1.077053] Code: aa0003f5 b1020020 a90153f3 aa0103f4 (b942a2b7)
All code
========
   0: aa0003f5 mov x21, x0
   4: b1020020 adds x0, x1, #0x80
   8: a90153f3 stp x19, x20, [sp, #16]
   c: aa0103f4 mov x20, x1
  10:* b942a2b7 ldr w23, [x21, #672] <-- trapping instruction

Code starting with the faulting instruction
===========================================
   0: b942a2b7 ldr w23, [x21, #672]
[    1.077594] ---[ end trace 0000000000000000 ]---
[    1.078059] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b
[    1.078736] SMP: stopping secondary CPUs
[    1.079099] Kernel Offset: disabled
[    1.079412] CPU features: 0x0400,00041058,01000400,8200421b
[    1.079909] Memory Limit: none
[    1.080188] ---[ end Kernel panic - not syncing: Attempted to kill
init! exitcode=0x0000000b ]---

## Source
* Kernel version:  6.14.0-rc6-next-20250313
* Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
* Git sha: 613af589b566093ce7388bf3202fca70d742c166
* Git describe:  6.14.0-rc6-next-20250313
* Project details:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250305/
* Architectures: arm64
* Compilers: gcc-13

## Test data
* Test log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611306/suite/boot/test/gcc-13-lkftconfig/log
* Test history:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611826/suite/boot/test/gcc-13-lkftconfig/history/
* Test details:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250313/testrun/27611306/suite/boot/test/gcc-13-lkftconfig/
* Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uFgT27J8KGNrdNXzKgUzhFI3YX/
* Kernel config:
https://storage.tuxsuite.com/public/linaro/lkft/builds/2uFgT27J8KGNrdNXzKgUzhFI3YX/config


--
Linaro LKFT
https://lkft.linaro.org


From will at kernel.org  Thu Mar 13 04:26:59 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 11:26:59 +0000
Subject: [PATCH] KVM: arm64: Drop sort_memblock_regions()
In-Reply-To: <20250311043718.91004-1-gshan@redhat.com>
References: <20250311043718.91004-1-gshan@redhat.com>
Message-ID: <20250313112659.GA7223@willie-the-truck>

On Tue, Mar 11, 2025 at 02:37:18PM +1000, Gavin Shan wrote:
> Drop sort_memblock_regions() and avoid sorting the copied memory
> regions to be ascending order on their base addresses, because the
> source memory regions should have been sorted correctly when they
> are added by memblock_add() or its variants.
> 
> This is generally reverting commit a14307f5310c ("KVM: arm64: Sort
> the hypervisor memblocks"). No functional changes intended.
> 
> Signed-off-by: Gavin Shan <gshan at redhat.com>
> ---
>  arch/arm64/kvm/pkvm.c | 19 -------------------
>  1 file changed, 19 deletions(-)

It's not especially obvious from the memblock API that the memblocks
are sorted and so for_each_mem_region() will traverse the regions in
order. But it does appear to be true, so I suppose this is fine:

Acked-by: Will Deacon <will at kernel.org>

Will


From miko.lenczewski at arm.com  Thu Mar 13 04:30:30 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 13 Mar 2025 11:30:30 +0000
Subject: [PATCH v3 0/3] Initial BBML2 support for contpte_convert()
In-Reply-To: <e8749c86-fe93-4123-aa2e-5677e7a2c695@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <e8749c86-fe93-4123-aa2e-5677e7a2c695@arm.com>
Message-ID: <20250313113030.GA24356@mazurka.cambridge.arm.com>

On Thu, Mar 13, 2025 at 11:22:07AM +0000, Suzuki K Poulose wrote:
> Hi Miko,
> 
> On 13/03/2025 10:41, Miko?aj Lenczewski wrote:
> > Hi All,
> >  
> Nothing about the patch functionality, but :
> 
> Minor nit: Generally it is a good idea to add "What changed" from the
> previous posting.  That gives the reviewers an idea of what to look for
> in the new version. Something like:
> 
> Changes since V2:
>   {Adding a link to the posting is an added bonus, as we can look up the 
> discussions easily}
>   - blah blah
>   - ..
> 
> 
> Cheers
> Suzuki

Ah, yes. My apologies. Will make sure to include such a changelog with
links to previous versions in future. I do not know why I did not
include it here, other than it not crossing my mind...

-- 
Kind regards,
Miko?aj Lenczewski


From robin.murphy at arm.com  Thu Mar 13 04:39:00 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 11:39:00 +0000
Subject: [PATCH v3 2/3] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250313104111.24196-4-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-4-miko.lenczewski@arm.com>
Message-ID: <880d8d7d-cd83-4e39-a0de-e278187b7a36@arm.com>

On 2025-03-13 10:41 am, Miko?aj Lenczewski wrote:
> For supporting BBM Level 2 for userspace mappings, we want to ensure
> that the smmu also supports its own version of BBM Level 2. Luckily, the
> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
> BBM level 2 is claimed.
> 
> Add the feature and testing for it under arm_smmu_sva_supported().

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> ---
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
>   3 files changed, 10 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> index 9ba596430e7c..6ba182572788 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>   		feat_mask |= ARM_SMMU_FEAT_VAX;
>   	}
>   
> +	if (system_supports_bbml2_noabort())
> +		feat_mask |= ARM_SMMU_FEAT_BBML2;
> +
>   	if ((smmu->features & feat_mask) != feat_mask)
>   		return false;
>   
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 358072b4e293..dcee0bdec924 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
>   	if (FIELD_GET(IDR3_RIL, reg))
>   		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>   
> +	if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
> +		smmu->features |= ARM_SMMU_FEAT_BBML2;
> +
>   	/* IDR5 */
>   	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>   
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> index bd9d7c85576a..85eaf3ab88c2 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>   #define ARM_SMMU_IDR3			0xc
>   #define IDR3_FWB			(1 << 8)
>   #define IDR3_RIL			(1 << 10)
> +#define IDR3_BBML			GENMASK(12, 11)
> +#define IDR3_BBML1			(1 << 11)
> +#define IDR3_BBML2			(2 << 11)
>   
>   #define ARM_SMMU_IDR5			0x14
>   #define IDR5_STALL_MAX			GENMASK(31, 16)
> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>   #define ARM_SMMU_FEAT_HA		(1 << 21)
>   #define ARM_SMMU_FEAT_HD		(1 << 22)
>   #define ARM_SMMU_FEAT_S2FWB		(1 << 23)
> +#define ARM_SMMU_FEAT_BBML2		(1 << 24)
>   	u32				features;
>   
>   #define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)



From vdonnefort at google.com  Thu Mar 13 04:40:38 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 11:40:38 +0000
Subject: [PATCH v4 3/3] KVM: arm64: Count pKVM stage-2 usage in secondary
 pagetable stats
In-Reply-To: <20250313114038.1502357-1-vdonnefort@google.com>
References: <20250313114038.1502357-1-vdonnefort@google.com>
Message-ID: <20250313114038.1502357-4-vdonnefort@google.com>

Count the pages used by pKVM for the guest stage-2 in memory stats under
secondary pagetable, similarly to what the VHE mode does.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ace3969e8106..51754a354b7a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,8 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+
+#define	HYP_MEMCACHE_ACCOUNT_STAGE2	BIT(1)
 	unsigned long flags;
 };
 
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 6107a3c8ccf6..2feb6c6b63af 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1088,12 +1088,24 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 
 static void hyp_mc_free_fn(void *addr, void *mc)
 {
+	struct kvm_hyp_memcache *memcache = mc;
+
+	if (memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, -1);
+
 	free_page((unsigned long)addr);
 }
 
 static void *hyp_mc_alloc_fn(void *mc)
 {
-	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+	struct kvm_hyp_memcache *memcache = mc;
+	void *addr;
+
+	addr = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
+	if (addr && memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
+		kvm_account_pgtable_pages(addr, 1);
+
+	return addr;
 }
 
 void free_hyp_memcache(struct kvm_hyp_memcache *mc)
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 19921ca407c6..4409a10d02b6 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -165,12 +165,16 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 	handle = ret;
 
 	host_kvm->arch.pkvm.handle = handle;
+	host_kvm->arch.pkvm.stage2_teardown_mc.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+	kvm_account_pgtable_pages(pgd, pgd_sz / PAGE_SIZE);
 
 	/* Donate memory for the vcpus at hyp and initialize it. */
 	hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
 	kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
 		void *hyp_vcpu;
 
+		host_vcpu->arch.pkvm_memcache.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
+
 		/* Indexing of the vcpus to be sequential starting at 0. */
 		if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
 			ret = -EINVAL;
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From andrej.picej at norik.com  Thu Mar 13 04:44:33 2025
From: andrej.picej at norik.com (Andrej Picej)
Date: Thu, 13 Mar 2025 12:44:33 +0100
Subject: [Upstream] [PATCH v7 3/3] arm64: dts:
 imx8mm-phyboard-polis-peb-av-10: Set lvds-vod-swing
In-Reply-To: <20241216085410.1968634-4-andrej.picej@norik.com>
References: <20241216085410.1968634-1-andrej.picej@norik.com>
 <20241216085410.1968634-4-andrej.picej@norik.com>
Message-ID: <a0d83b69-c84d-4804-abcd-e546be8a2e3d@norik.com>

Hi,

is there anything else I need to do, or can this patch now be applied?

The initial two patches that introduce property support have already 
been merged, and the patch series that this patch depends on [1] has 
also been applied.

[1] https://lore.kernel.org/all/Z7rZjdXwN2W+Y2Bd at dragon/

Best regards,
Andrej

On 16. 12. 24 09:54, Andrej Picej wrote:
> Set custom differential output voltage for LVDS, to fulfill requirements
> of the connected display. LVDS differential voltage for data-lanes and
> clock output has to be between 200 mV and 600 mV.
> Driver sets 200 Ohm near-end termination by default.
> 
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
> Changes in v7:
> - no change
> Changes in v6:
> - no change
> Changes in v5:
> - no change
> Changes in v4:
> - no change
> Changes in v3:
> - no change
> Changes in v2:
> - use new properties from previous patches
> ---
>   .../boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso     | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso
> index a9de42cf14be..8bf9cc553bea 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso
> +++ b/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-peb-av-10.dtso
> @@ -186,6 +186,8 @@ port at 2 {
>   			reg = <2>;
>   			bridge_out: endpoint {
>   				remote-endpoint = <&panel_in>;
> +				ti,lvds-vod-swing-clock-microvolt = <200000 600000>;
> +				ti,lvds-vod-swing-data-microvolt = <200000 600000>;
>   			};
>   		};
>   	};


From acarmina at redhat.com  Thu Mar 13 04:43:16 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:16 +0000
Subject: [PATCH v4 01/14] bug/kunit: Core support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-2-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Some unit tests intentionally trigger warning backtraces by passing
bad parameters to API functions. Such unit tests typically check the
return value from those calls, not the existence of the warning backtrace.

Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons.
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
  investigated and has to be marked to be ignored, for example by
  adjusting filter scripts. Such filters are ad-hoc because there is
  no real standard format for warnings. On top of that, such filter
  scripts would require constant maintenance.

One option to address problem would be to add messages such as "expected
warning backtraces start / end here" to the kernel log.  However, that
would again require filter scripts, it might result in missing real
problematic warning backtraces triggered while the test is running, and
the irrelevant backtrace(s) would still clog the kernel log.

Solve the problem by providing a means to identify and suppress specific
warning backtraces while executing test code. Since the new functionality
results in an image size increase of about 1% if CONFIG_KUNIT is enabled,
provide configuration option KUNIT_SUPPRESS_BACKTRACE to be able to disable
the new functionality. This option is by default enabled since almost all
systems with CONFIG_KUNIT enabled will want to benefit from it.

Cc: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Daniel Diaz <daniel.diaz at linaro.org>
Cc: Naresh Kamboju <naresh.kamboju at linaro.org>
Cc: Kees Cook <keescook at chromium.org>
Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Reviewed-by: Kees Cook <keescook at chromium.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 include/asm-generic/bug.h | 16 +++++++++---
 include/kunit/bug.h       | 51 +++++++++++++++++++++++++++++++++++++++
 include/kunit/test.h      |  1 +
 include/linux/bug.h       | 13 ++++++++++
 lib/bug.c                 | 51 ++++++++++++++++++++++++++++++++++++---
 lib/kunit/Kconfig         |  9 +++++++
 lib/kunit/Makefile        |  6 +++--
 lib/kunit/bug.c           | 40 ++++++++++++++++++++++++++++++
 8 files changed, 178 insertions(+), 9 deletions(-)
 create mode 100644 include/kunit/bug.h
 create mode 100644 lib/kunit/bug.c

diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 387720933973..9194cf743ec3 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -18,6 +18,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <kunit/bug.h>
 #include <linux/panic.h>
 #include <linux/printk.h>
 
@@ -39,8 +40,14 @@ struct bug_entry {
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
 	const char	*file;
+#ifdef HAVE_BUG_FUNCTION
+	const char      *function;
+#endif
 #else
 	signed int	file_disp;
+#ifdef HAVE_BUG_FUNCTION
+	signed int	function_disp;
+#endif
 #endif
 	unsigned short	line;
 #endif
@@ -96,15 +103,18 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...);
 #define __WARN()		__WARN_printf(TAINT_WARN, NULL)
 #define __WARN_printf(taint, arg...) do {				\
 		instrumentation_begin();				\
-		warn_slowpath_fmt(__FILE__, __LINE__, taint, arg);	\
+		if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))			\
+			warn_slowpath_fmt(__FILE__, __LINE__, taint, arg);\
 		instrumentation_end();					\
 	} while (0)
 #else
 #define __WARN()		__WARN_FLAGS(BUGFLAG_TAINT(TAINT_WARN))
 #define __WARN_printf(taint, arg...) do {				\
 		instrumentation_begin();				\
-		__warn_printk(arg);					\
-		__WARN_FLAGS(BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\
+		if (!KUNIT_IS_SUPPRESSED_WARNING(__func__)) {			\
+			__warn_printk(arg);				\
+			__WARN_FLAGS(BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\
+		}							\
 		instrumentation_end();					\
 	} while (0)
 #define WARN_ON_ONCE(condition) ({				\
diff --git a/include/kunit/bug.h b/include/kunit/bug.h
new file mode 100644
index 000000000000..0a8e62c1fcaf
--- /dev/null
+++ b/include/kunit/bug.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit helpers for backtrace suppression
+ *
+ * Copyright (c) 2024 Guenter Roeck <linux at roeck-us.net>
+ */
+
+#ifndef _KUNIT_BUG_H
+#define _KUNIT_BUG_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/kconfig.h>
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+
+struct __suppressed_warning {
+	struct list_head node;
+	const char *function;
+};
+
+void __kunit_start_suppress_warning(struct __suppressed_warning *warning);
+void __kunit_end_suppress_warning(struct __suppressed_warning *warning);
+bool __kunit_is_suppressed_warning(const char *function);
+
+#define DEFINE_SUPPRESSED_WARNING(func)	\
+	struct __suppressed_warning __kunit_suppress_##func = \
+		{ .function = __stringify(func) }
+
+#define KUNIT_START_SUPPRESSED_WARNING(func) \
+	__kunit_start_suppress_warning(&__kunit_suppress_##func)
+
+#define KUNIT_END_SUPPRESSED_WARNING(func) \
+	__kunit_end_suppress_warning(&__kunit_suppress_##func)
+
+#define KUNIT_IS_SUPPRESSED_WARNING(func) \
+	__kunit_is_suppressed_warning(func)
+
+#else /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
+#define DEFINE_SUPPRESSED_WARNING(func)
+#define KUNIT_START_SUPPRESSED_WARNING(func)
+#define KUNIT_END_SUPPRESSED_WARNING(func)
+#define KUNIT_IS_SUPPRESSED_WARNING(func) (false)
+
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+#endif /* __ASSEMBLY__ */
+#endif /* _KUNIT_BUG_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 58dbab60f853..cad32d174872 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -10,6 +10,7 @@
 #define _KUNIT_TEST_H
 
 #include <kunit/assert.h>
+#include <kunit/bug.h>
 #include <kunit/try-catch.h>
 
 #include <linux/args.h>
diff --git a/include/linux/bug.h b/include/linux/bug.h
index a9948a9f1093..e42f20cf8830 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -36,6 +36,9 @@ static inline int is_warning_bug(const struct bug_entry *bug)
 	return bug->flags & BUGFLAG_WARNING;
 }
 
+void bug_get_file_function_line(struct bug_entry *bug, const char **file,
+				const char **function, unsigned int *line);
+
 void bug_get_file_line(struct bug_entry *bug, const char **file,
 		       unsigned int *line);
 
@@ -62,6 +65,16 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
 }
 
 struct bug_entry;
+static inline void bug_get_file_function_line(struct bug_entry *bug,
+					      const char **file,
+					      const char **function,
+					      unsigned int *line)
+{
+	*file = NULL;
+	*function = NULL;
+	*line = 0;
+}
+
 static inline void bug_get_file_line(struct bug_entry *bug, const char **file,
 				     unsigned int *line)
 {
diff --git a/lib/bug.c b/lib/bug.c
index e0ff21989990..5eb2ee66916f 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -26,6 +26,14 @@
        when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
        the values accordingly.
 
+  2a.Optionally implement support for the "function" entry in struct
+     bug_entry. This entry must point to the name of the function triggering
+     the warning or bug trap (normally __func__). This is only needed if
+     both CONFIG_DEBUG_BUGVERBOSE and CONFIG_KUNIT_SUPPRESS_BACKTRACE are
+     enabled and if the architecture wants to implement support for suppressing
+     warning backtraces. The architecture must define HAVE_BUG_FUNCTION if it
+     adds pointers to function names to struct bug_entry.
+
   3. Implement the trap
      - In the illegal instruction trap handler (typically), verify
        that the fault was in kernel mode, and call report_bug()
@@ -127,14 +135,21 @@ static inline struct bug_entry *module_find_bug(unsigned long bugaddr)
 }
 #endif
 
-void bug_get_file_line(struct bug_entry *bug, const char **file,
-		       unsigned int *line)
+void bug_get_file_function_line(struct bug_entry *bug, const char **file,
+				const char **function, unsigned int *line)
 {
+	*function = NULL;
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
 	*file = (const char *)&bug->file_disp + bug->file_disp;
+#ifdef HAVE_BUG_FUNCTION
+	*function = (const char *)&bug->function_disp + bug->function_disp;
+#endif
 #else
 	*file = bug->file;
+#ifdef HAVE_BUG_FUNCTION
+	*function = bug->function;
+#endif
 #endif
 	*line = bug->line;
 #else
@@ -143,6 +158,13 @@ void bug_get_file_line(struct bug_entry *bug, const char **file,
 #endif
 }
 
+void bug_get_file_line(struct bug_entry *bug, const char **file, unsigned int *line)
+{
+	const char *function;
+
+	bug_get_file_function_line(bug, file, &function, line);
+}
+
 struct bug_entry *find_bug(unsigned long bugaddr)
 {
 	struct bug_entry *bug;
@@ -157,8 +179,9 @@ struct bug_entry *find_bug(unsigned long bugaddr)
 static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *regs)
 {
 	struct bug_entry *bug;
-	const char *file;
+	const char *file, *function;
 	unsigned line, warning, once, done;
+	char __maybe_unused sym[KSYM_SYMBOL_LEN];
 
 	if (!is_valid_bugaddr(bugaddr))
 		return BUG_TRAP_TYPE_NONE;
@@ -169,12 +192,32 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re
 
 	disable_trace_on_warning();
 
-	bug_get_file_line(bug, &file, &line);
+	bug_get_file_function_line(bug, &file, &function, &line);
+#if defined(CONFIG_KUNIT_SUPPRESS_BACKTRACE) && defined(CONFIG_KALLSYMS)
+	if (!function) {
+		/*
+		 * This will be seen if report_bug is called on an architecture
+		 * with no architecture-specific support for suppressing warning
+		 * backtraces, if CONFIG_DEBUG_BUGVERBOSE is not enabled, or if
+		 * the calling code is from assembler which does not record a
+		 * function name. Extracting the function name from the bug
+		 * address is less than perfect since compiler optimization may
+		 * result in 'bugaddr' pointing to a function which does not
+		 * actually trigger the warning, but it is better than no
+		 * suppression at all.
+		 */
+		sprint_symbol_no_offset(sym, bugaddr);
+		function = sym;
+	}
+#endif /* defined(CONFIG_KUNIT_SUPPRESS_BACKTRACE) && defined(CONFIG_KALLSYMS) */
 
 	warning = (bug->flags & BUGFLAG_WARNING) != 0;
 	once = (bug->flags & BUGFLAG_ONCE) != 0;
 	done = (bug->flags & BUGFLAG_DONE) != 0;
 
+	if (warning && KUNIT_IS_SUPPRESSED_WARNING(function))
+		return BUG_TRAP_TYPE_WARN;
+
 	if (warning && once) {
 		if (done)
 			return BUG_TRAP_TYPE_WARN;
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index a97897edd964..201402f0ab49 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -15,6 +15,15 @@ menuconfig KUNIT
 
 if KUNIT
 
+config KUNIT_SUPPRESS_BACKTRACE
+	bool "KUnit - Enable backtrace suppression"
+	default y
+	help
+	  Enable backtrace suppression for KUnit. If enabled, backtraces
+	  generated intentionally by KUnit tests are suppressed. Disable
+	  to reduce kernel image size if image size is more important than
+	  suppression of backtraces generated by KUnit tests.
+
 config KUNIT_DEBUGFS
 	bool "KUnit - Enable /sys/kernel/debug/kunit debugfs representation" if !KUNIT_ALL_TESTS
 	default KUNIT_ALL_TESTS
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 5aa51978e456..3195e861d63c 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -16,8 +16,10 @@ ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
 kunit-objs +=				debugfs.o
 endif
 
-# KUnit 'hooks' are built-in even when KUnit is built as a module.
-obj-y +=				hooks.o
+# KUnit 'hooks' and bug handling are built-in even when KUnit is built
+# as a module.
+obj-y +=				hooks.o \
+					bug.o
 
 obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
 obj-$(CONFIG_KUNIT_TEST) +=		platform-test.o
diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
new file mode 100644
index 000000000000..351f9a595a71
--- /dev/null
+++ b/lib/kunit/bug.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit helpers for backtrace suppression
+ *
+ * Copyright (c) 2024 Guenter Roeck <linux at roeck-us.net>
+ */
+
+#include <kunit/bug.h>
+#include <linux/export.h>
+#include <linux/list.h>
+#include <linux/string.h>
+
+static LIST_HEAD(suppressed_warnings);
+
+void __kunit_start_suppress_warning(struct __suppressed_warning *warning)
+{
+	list_add(&warning->node, &suppressed_warnings);
+}
+EXPORT_SYMBOL_GPL(__kunit_start_suppress_warning);
+
+void __kunit_end_suppress_warning(struct __suppressed_warning *warning)
+{
+	list_del(&warning->node);
+}
+EXPORT_SYMBOL_GPL(__kunit_end_suppress_warning);
+
+bool __kunit_is_suppressed_warning(const char *function)
+{
+	struct __suppressed_warning *warning;
+
+	if (!function)
+		return false;
+
+	list_for_each_entry(warning, &suppressed_warnings, node) {
+		if (!strcmp(function, warning->function))
+			return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL_GPL(__kunit_is_suppressed_warning);
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:15 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:15 +0000
Subject: [PATCH v4 00/14] Add support for suppressing warning backtraces
Message-ID: <20250313114329.284104-1-acarmina@redhat.com>

Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.

Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons.
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
  investigated and has to be marked to be ignored, for example by
  adjusting filter scripts. Such filters are ad-hoc because there is
  no real standard format for warnings. On top of that, such filter
  scripts would require constant maintenance.

One option to address problem would be to add messages such as "expected
warning backtraces start / end here" to the kernel log.  However, that
would again require filter scripts, it might result in missing real
problematic warning backtraces triggered while the test is running, and
the irrelevant backtrace(s) would still clog the kernel log.

Solve the problem by providing a means to identify and suppress specific
warning backtraces while executing test code. Support suppressing multiple
backtraces while at the same time limiting changes to generic code to the
absolute minimum. Architecture specific changes are kept at minimum by
retaining function names only if both CONFIG_DEBUG_BUGVERBOSE and
CONFIG_KUNIT are enabled.

The first patch of the series introduces the necessary infrastructure.
The second patch introduces support for counting suppressed backtraces.
This capability is used in patch three to implement unit tests.
Patch four documents the new API.
The next two patches add support for suppressing backtraces in drm_rect
and dev_addr_lists unit tests. These patches are intended to serve as
examples for the use of the functionality introduced with this series.
The remaining patches implement the necessary changes for all
architectures with GENERIC_BUG support.

With CONFIG_KUNIT enabled, image size increase with this series applied is
approximately 1%. The image size increase (and with it the functionality
introduced by this series) can be avoided by disabling
CONFIG_KUNIT_SUPPRESS_BACKTRACE.

This series is based on the RFC patch and subsequent discussion at
https://patchwork.kernel.org/project/linux-kselftest/patch/02546e59-1afe-4b08-ba81-d94f3b691c9a at moroto.mountain/
and offers a more comprehensive solution of the problem discussed there.

Design note:
  Function pointers are only added to the __bug_table section if both
  CONFIG_KUNIT_SUPPRESS_BACKTRACE and CONFIG_DEBUG_BUGVERBOSE are enabled
  to avoid image size increases if CONFIG_KUNIT is disabled. There would be
  some benefits to adding those pointers all the time (reduced complexity,
  ability to display function names in BUG/WARNING messages). That change,
  if desired, can be made later.

Checkpatch note:
  Remaining checkpatch errors and warnings were deliberately ignored.
  Some are triggered by matching coding style or by comments interpreted
  as code, others by assembler macros which are disliked by checkpatch.
  Suggestions for improvements are welcome.

Changes since RFC:
- Introduced CONFIG_KUNIT_SUPPRESS_BACKTRACE
- Minor cleanups and bug fixes
- Added support for all affected architectures
- Added support for counting suppressed warnings
- Added unit tests using those counters
- Added patch to suppress warning backtraces in dev_addr_lists tests

Changes since v1:
- Rebased to v6.9-rc1
- Added Tested-by:, Acked-by:, and Reviewed-by: tags
  [I retained those tags since there have been no functional changes]
- Introduced KUNIT_SUPPRESS_BACKTRACE configuration option, enabled by
  default.

Changes since v2:
- Rebased to v6.9-rc2
- Added comments to drm warning suppression explaining why it is needed.
- Added patch to move conditional code in arch/sh/include/asm/bug.h
  to avoid kerneldoc warning
- Added architecture maintainers to Cc: for architecture specific patches
- No functional changes

Changes since v3:
- Rebased to v6.14-rc6
- Dropped net: "kunit: Suppress lock warning noise at end of dev_addr_lists tests"
  since 3db3b62955cd6d73afde05a17d7e8e106695c3b9
- Added __kunit_ and KUNIT_ prefixes.
- Tested on interessed architectures.

----
Guenter Roeck (14):
  bug/kunit: Core support for suppressing warning backtraces
  kunit: bug: Count suppressed warning backtraces
  kunit: Add test cases for backtrace warning suppression
  kunit: Add documentation for warning backtrace suppression API
  drm: Suppress intentional warning backtraces in scaling unit tests
  x86: Add support for suppressing warning backtraces
  arm64: Add support for suppressing warning backtraces
  loongarch: Add support for suppressing warning backtraces
  parisc: Add support for suppressing warning backtraces
  s390: Add support for suppressing warning backtraces
  sh: Add support for suppressing warning backtraces
  sh: Move defines needed for suppressing warning backtraces
  riscv: Add support for suppressing warning backtraces
  powerpc: Add support for suppressing warning backtraces

 Documentation/dev-tools/kunit/usage.rst |  30 ++++++-
 arch/arm64/include/asm/asm-bug.h        |  27 ++++--
 arch/arm64/include/asm/bug.h            |   8 +-
 arch/loongarch/include/asm/bug.h        |  42 +++++++---
 arch/parisc/include/asm/bug.h           |  29 +++++--
 arch/powerpc/include/asm/bug.h          |  37 +++++++--
 arch/riscv/include/asm/bug.h            |  38 ++++++---
 arch/s390/include/asm/bug.h             |  17 +++-
 arch/sh/include/asm/bug.h               |  28 ++++++-
 arch/x86/include/asm/bug.h              |  21 +++--
 drivers/gpu/drm/tests/drm_rect_test.c   |  16 ++++
 include/asm-generic/bug.h               |  16 +++-
 include/kunit/bug.h                     |  56 +++++++++++++
 include/kunit/test.h                    |   1 +
 include/linux/bug.h                     |  13 +++
 lib/bug.c                               |  51 +++++++++++-
 lib/kunit/Kconfig                       |   9 ++
 lib/kunit/Makefile                      |   7 +-
 lib/kunit/backtrace-suppression-test.c  | 104 ++++++++++++++++++++++++
 lib/kunit/bug.c                         |  42 ++++++++++
 20 files changed, 519 insertions(+), 73 deletions(-)
 create mode 100644 include/kunit/bug.h
 create mode 100644 lib/kunit/backtrace-suppression-test.c
 create mode 100644 lib/kunit/bug.c

-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:17 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:17 +0000
Subject: [PATCH v4 02/14] kunit: bug: Count suppressed warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-3-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Count suppressed warning backtraces to enable code which suppresses
warning backtraces to check if the expected backtrace(s) have been
observed.

Using atomics for the backtrace count resulted in build errors on some
architectures due to include file recursion, so use a plain integer
for now.

Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Reviewed-by: Kees Cook <keescook at chromium.org>
Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: David Gow <davidgow at google.com>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 include/kunit/bug.h | 7 ++++++-
 lib/kunit/bug.c     | 4 +++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/kunit/bug.h b/include/kunit/bug.h
index 0a8e62c1fcaf..44efa7d5c902 100644
--- a/include/kunit/bug.h
+++ b/include/kunit/bug.h
@@ -20,6 +20,7 @@
 struct __suppressed_warning {
 	struct list_head node;
 	const char *function;
+	int counter;
 };
 
 void __kunit_start_suppress_warning(struct __suppressed_warning *warning);
@@ -28,7 +29,7 @@ bool __kunit_is_suppressed_warning(const char *function);
 
 #define DEFINE_SUPPRESSED_WARNING(func)	\
 	struct __suppressed_warning __kunit_suppress_##func = \
-		{ .function = __stringify(func) }
+		{ .function = __stringify(func), .counter = 0 }
 
 #define KUNIT_START_SUPPRESSED_WARNING(func) \
 	__kunit_start_suppress_warning(&__kunit_suppress_##func)
@@ -39,12 +40,16 @@ bool __kunit_is_suppressed_warning(const char *function);
 #define KUNIT_IS_SUPPRESSED_WARNING(func) \
 	__kunit_is_suppressed_warning(func)
 
+#define SUPPRESSED_WARNING_COUNT(func) \
+	(__kunit_suppress_##func.counter)
+
 #else /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
 
 #define DEFINE_SUPPRESSED_WARNING(func)
 #define KUNIT_START_SUPPRESSED_WARNING(func)
 #define KUNIT_END_SUPPRESSED_WARNING(func)
 #define KUNIT_IS_SUPPRESSED_WARNING(func) (false)
+#define SUPPRESSED_WARNING_COUNT(func) (0)
 
 #endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
 #endif /* __ASSEMBLY__ */
diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
index 351f9a595a71..84c05b1a9e8b 100644
--- a/lib/kunit/bug.c
+++ b/lib/kunit/bug.c
@@ -32,8 +32,10 @@ bool __kunit_is_suppressed_warning(const char *function)
 		return false;
 
 	list_for_each_entry(warning, &suppressed_warnings, node) {
-		if (!strcmp(function, warning->function))
+		if (!strcmp(function, warning->function)) {
+			warning->counter++;
 			return true;
+		}
 	}
 	return false;
 }
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:18 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:18 +0000
Subject: [PATCH v4 03/14] kunit: Add test cases for backtrace warning suppression
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-4-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add unit tests to verify that warning backtrace suppression works.

If backtrace suppression does _not_ work, the unit tests will likely
trigger unsuppressed backtraces, which should actually help to get
the affected architectures / platforms fixed.

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Reviewed-by: Kees Cook <keescook at chromium.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 lib/kunit/Makefile                     |   7 +-
 lib/kunit/backtrace-suppression-test.c | 104 +++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 2 deletions(-)
 create mode 100644 lib/kunit/backtrace-suppression-test.c

diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 3195e861d63c..539a044a9f12 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -18,11 +18,14 @@ endif
 
 # KUnit 'hooks' and bug handling are built-in even when KUnit is built
 # as a module.
-obj-y +=				hooks.o \
-					bug.o
+obj-y +=				hooks.o
+obj-$(CONFIG_KUNIT_SUPPRESS_BACKTRACE) += bug.o
 
 obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
 obj-$(CONFIG_KUNIT_TEST) +=		platform-test.o
+ifeq ($(CONFIG_KUNIT_SUPPRESS_BACKTRACE),y)
+obj-$(CONFIG_KUNIT_TEST) +=		backtrace-suppression-test.o
+endif
 
 # string-stream-test compiles built-in only.
 ifeq ($(CONFIG_KUNIT_TEST),y)
diff --git a/lib/kunit/backtrace-suppression-test.c b/lib/kunit/backtrace-suppression-test.c
new file mode 100644
index 000000000000..8b4125af2481
--- /dev/null
+++ b/lib/kunit/backtrace-suppression-test.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for suppressing warning tracebacks
+ *
+ * Copyright (C) 2024, Guenter Roeck
+ * Author: Guenter Roeck <linux at roeck-us.net>
+ */
+
+#include <kunit/test.h>
+#include <linux/bug.h>
+
+static void backtrace_suppression_test_warn_direct(struct kunit *test)
+{
+	DEFINE_SUPPRESSED_WARNING(backtrace_suppression_test_warn_direct);
+
+	KUNIT_START_SUPPRESSED_WARNING(backtrace_suppression_test_warn_direct);
+	WARN(1, "This backtrace should be suppressed");
+	KUNIT_END_SUPPRESSED_WARNING(backtrace_suppression_test_warn_direct);
+
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(backtrace_suppression_test_warn_direct), 1);
+}
+
+static void trigger_backtrace_warn(void)
+{
+	WARN(1, "This backtrace should be suppressed");
+}
+
+static void backtrace_suppression_test_warn_indirect(struct kunit *test)
+{
+	DEFINE_SUPPRESSED_WARNING(trigger_backtrace_warn);
+
+	KUNIT_START_SUPPRESSED_WARNING(trigger_backtrace_warn);
+	trigger_backtrace_warn();
+	KUNIT_END_SUPPRESSED_WARNING(trigger_backtrace_warn);
+
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(trigger_backtrace_warn), 1);
+}
+
+static void backtrace_suppression_test_warn_multi(struct kunit *test)
+{
+	DEFINE_SUPPRESSED_WARNING(trigger_backtrace_warn);
+	DEFINE_SUPPRESSED_WARNING(backtrace_suppression_test_warn_multi);
+
+	KUNIT_START_SUPPRESSED_WARNING(backtrace_suppression_test_warn_multi);
+	KUNIT_START_SUPPRESSED_WARNING(trigger_backtrace_warn);
+	WARN(1, "This backtrace should be suppressed");
+	trigger_backtrace_warn();
+	KUNIT_END_SUPPRESSED_WARNING(trigger_backtrace_warn);
+	KUNIT_END_SUPPRESSED_WARNING(backtrace_suppression_test_warn_multi);
+
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(backtrace_suppression_test_warn_multi), 1);
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(trigger_backtrace_warn), 1);
+}
+
+static void backtrace_suppression_test_warn_on_direct(struct kunit *test)
+{
+	DEFINE_SUPPRESSED_WARNING(backtrace_suppression_test_warn_on_direct);
+
+	if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE) && !IS_ENABLED(CONFIG_KALLSYMS))
+		kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE or CONFIG_KALLSYMS");
+
+	KUNIT_START_SUPPRESSED_WARNING(backtrace_suppression_test_warn_on_direct);
+	WARN_ON(1);
+	KUNIT_END_SUPPRESSED_WARNING(backtrace_suppression_test_warn_on_direct);
+
+	KUNIT_EXPECT_EQ(test,
+			SUPPRESSED_WARNING_COUNT(backtrace_suppression_test_warn_on_direct), 1);
+}
+
+static void trigger_backtrace_warn_on(void)
+{
+	WARN_ON(1);
+}
+
+static void backtrace_suppression_test_warn_on_indirect(struct kunit *test)
+{
+	DEFINE_SUPPRESSED_WARNING(trigger_backtrace_warn_on);
+
+	if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE))
+		kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
+
+	KUNIT_START_SUPPRESSED_WARNING(trigger_backtrace_warn_on);
+	trigger_backtrace_warn_on();
+	KUNIT_END_SUPPRESSED_WARNING(trigger_backtrace_warn_on);
+
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(trigger_backtrace_warn_on), 1);
+}
+
+static struct kunit_case backtrace_suppression_test_cases[] = {
+	KUNIT_CASE(backtrace_suppression_test_warn_direct),
+	KUNIT_CASE(backtrace_suppression_test_warn_indirect),
+	KUNIT_CASE(backtrace_suppression_test_warn_multi),
+	KUNIT_CASE(backtrace_suppression_test_warn_on_direct),
+	KUNIT_CASE(backtrace_suppression_test_warn_on_indirect),
+	{}
+};
+
+static struct kunit_suite backtrace_suppression_test_suite = {
+	.name = "backtrace-suppression-test",
+	.test_cases = backtrace_suppression_test_cases,
+};
+kunit_test_suites(&backtrace_suppression_test_suite);
+
+MODULE_LICENSE("GPL");
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:19 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:19 +0000
Subject: [PATCH v4 04/14] kunit: Add documentation for warning backtrace suppression API
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-5-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Document API functions for suppressing warning backtraces.

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Reviewed-by: Kees Cook <keescook at chromium.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: David Gow <davidgow at google.com>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 Documentation/dev-tools/kunit/usage.rst | 30 ++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
index 22955d56b379..b2f1e56d53b4 100644
--- a/Documentation/dev-tools/kunit/usage.rst
+++ b/Documentation/dev-tools/kunit/usage.rst
@@ -157,6 +157,34 @@ Alternatively, one can take full control over the error message by using
 	if (some_setup_function())
 		KUNIT_FAIL(test, "Failed to setup thing for testing");
 
+Suppressing warning backtraces
+------------------------------
+
+Some unit tests trigger warning backtraces either intentionally or as side
+effect. Such backtraces are normally undesirable since they distract from
+the actual test and may result in the impression that there is a problem.
+
+Such backtraces can be suppressed. To suppress a backtrace in some_function(),
+use the following code.
+
+.. code-block:: c
+
+	static void some_test(struct kunit *test)
+	{
+		DEFINE_SUPPRESSED_WARNING(some_function);
+
+		KUNIT_START_SUPPRESSED_WARNING(some_function);
+		trigger_backtrace();
+		KUNIT_END_SUPPRESSED_WARNING(some_function);
+	}
+
+SUPPRESSED_WARNING_COUNT() returns the number of suppressed backtraces. If the
+suppressed backtrace was triggered on purpose, this can be used to check if
+the backtrace was actually triggered.
+
+.. code-block:: c
+
+	KUNIT_EXPECT_EQ(test, SUPPRESSED_WARNING_COUNT(some_function), 1);
 
 Test Suites
 ~~~~~~~~~~~
@@ -857,4 +885,4 @@ For example:
 		dev_managed_string = devm_kstrdup(fake_device, "Hello, World!");
 
 		// Everything is cleaned up automatically when the test ends.
-	}
\ No newline at end of file
+	}
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:21 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:21 +0000
Subject: [PATCH v4 06/14] x86: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-7-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Borislav Petkov <bp at alien8.de>
Cc: Dave Hansen <dave.hansen at linux.intel.com>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/x86/include/asm/bug.h | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index e85ac0c7c039..f6e13fc675ab 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -35,18 +35,28 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	__BUG_REL(%c1)
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC_PTR
+# define __BUG_FUNC	NULL
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define _BUG_FLAGS(ins, flags, extra)					\
 do {									\
 	asm_inline volatile("1:\t" ins "\n"				\
 		     ".pushsection __bug_table,\"aw\"\n"		\
 		     "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n"	\
 		     "\t"  __BUG_REL(%c0) "\t# bug_entry::file\n"	\
-		     "\t.word %c1"        "\t# bug_entry::line\n"	\
-		     "\t.word %c2"        "\t# bug_entry::flags\n"	\
-		     "\t.org 2b+%c3\n"					\
+		     "\t"  __BUG_FUNC_PTR "\t# bug_entry::function\n"	\
+		     "\t.word %c2"        "\t# bug_entry::line\n"	\
+		     "\t.word %c3"        "\t# bug_entry::flags\n"	\
+		     "\t.org 2b+%c4\n"					\
 		     ".popsection\n"					\
 		     extra						\
-		     : : "i" (__FILE__), "i" (__LINE__),		\
+		     : : "i" (__FILE__), "i" (__BUG_FUNC), "i" (__LINE__),\
 			 "i" (flags),					\
 			 "i" (sizeof(struct bug_entry)));		\
 } while (0)
@@ -92,7 +102,8 @@ do {								\
 do {								\
 	__auto_type __flags = BUGFLAG_WARNING|(flags);		\
 	instrumentation_begin();				\
-	_BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b));	\
+	if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))			\
+		_BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b));	\
 	instrumentation_end();					\
 } while (0)
 
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:20 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:20 +0000
Subject: [PATCH v4 05/14] drm: Suppress intentional warning backtraces in scaling unit tests
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-6-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

The drm_test_rect_calc_hscale and drm_test_rect_calc_vscale unit tests
intentionally trigger warning backtraces by providing bad parameters to
the tested functions. What is tested is the return value, not the existence
of a warning backtrace. Suppress the backtraces to avoid clogging the
kernel log and distraction from real problems.

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Acked-by: Ma??ra Canal <mcanal at igalia.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: David Airlie <airlied at gmail.com>
Cc: Daniel Vetter <daniel at ffwll.ch>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 drivers/gpu/drm/tests/drm_rect_test.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c
index 17e1f34b7610..e8d707b4a101 100644
--- a/drivers/gpu/drm/tests/drm_rect_test.c
+++ b/drivers/gpu/drm/tests/drm_rect_test.c
@@ -406,22 +406,38 @@ KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc
 
 static void drm_test_rect_calc_hscale(struct kunit *test)
 {
+	DEFINE_SUPPRESSED_WARNING(drm_calc_scale);
 	const struct drm_rect_scale_case *params = test->param_value;
 	int scaling_factor;
 
+	/*
+	 * drm_rect_calc_hscale() generates a warning backtrace whenever bad
+	 * parameters are passed to it. This affects all unit tests with an
+	 * error code in expected_scaling_factor.
+	 */
+	KUNIT_START_SUPPRESSED_WARNING(drm_calc_scale);
 	scaling_factor = drm_rect_calc_hscale(&params->src, &params->dst,
 					      params->min_range, params->max_range);
+	KUNIT_END_SUPPRESSED_WARNING(drm_calc_scale);
 
 	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
 }
 
 static void drm_test_rect_calc_vscale(struct kunit *test)
 {
+	DEFINE_SUPPRESSED_WARNING(drm_calc_scale);
 	const struct drm_rect_scale_case *params = test->param_value;
 	int scaling_factor;
 
+	/*
+	 * drm_rect_calc_vscale() generates a warning backtrace whenever bad
+	 * parameters are passed to it. This affects all unit tests with an
+	 * error code in expected_scaling_factor.
+	 */
+	KUNIT_START_SUPPRESSED_WARNING(drm_calc_scale);
 	scaling_factor = drm_rect_calc_vscale(&params->src, &params->dst,
 					      params->min_range, params->max_range);
+	KUNIT_END_SUPPRESSED_WARNING(drm_calc_scale);
 
 	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
 }
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:23 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:23 +0000
Subject: [PATCH v4 08/14] loongarch: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-9-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Huacai Chen <chenhuacai at kernel.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/loongarch/include/asm/bug.h | 42 ++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/arch/loongarch/include/asm/bug.h b/arch/loongarch/include/asm/bug.h
index f6f254f2c5db..b79ff6696ce6 100644
--- a/arch/loongarch/include/asm/bug.h
+++ b/arch/loongarch/include/asm/bug.h
@@ -3,49 +3,65 @@
 #define __ASM_BUG_H
 
 #include <asm/break.h>
+#include <kunit/bug.h>
 #include <linux/stringify.h>
 #include <linux/objtool.h>
 
 #ifndef CONFIG_DEBUG_BUGVERBOSE
-#define _BUGVERBOSE_LOCATION(file, line)
+#define _BUGVERBOSE_LOCATION(file, func, line)
 #else
-#define __BUGVERBOSE_LOCATION(file, line)			\
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR(func)  .long func - .;
+#else
+# define __BUG_FUNC_PTR(func)
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
+#define __BUGVERBOSE_LOCATION(file, func, line)			\
 		.pushsection .rodata.str, "aMS", @progbits, 1;	\
 	10002:	.string file;					\
 		.popsection;					\
 								\
 		.long 10002b - .;				\
+		__BUG_FUNC_PTR(func)				\
 		.short line;
-#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
+#define _BUGVERBOSE_LOCATION(file, func, line) __BUGVERBOSE_LOCATION(file, func, line)
 #endif
 
 #ifndef CONFIG_GENERIC_BUG
-#define __BUG_ENTRY(flags)
+#define __BUG_ENTRY(flags, func)
 #else
-#define __BUG_ENTRY(flags) 					\
+#define __BUG_ENTRY(flags, func)				\
 		.pushsection __bug_table, "aw";			\
 		.align 2;					\
 	10000:	.long 10001f - .;				\
-		_BUGVERBOSE_LOCATION(__FILE__, __LINE__)	\
+		_BUGVERBOSE_LOCATION(__FILE__, func, __LINE__)	\
 		.short flags; 					\
 		.popsection;					\
 	10001:
 #endif
 
-#define ASM_BUG_FLAGS(flags)					\
-	__BUG_ENTRY(flags)					\
+#define ASM_BUG_FLAGS(flags, func)				\
+	__BUG_ENTRY(flags, func)				\
 	break		BRK_BUG;
 
-#define ASM_BUG()	ASM_BUG_FLAGS(0)
+#define ASM_BUG()	ASM_BUG_FLAGS(0, .)
+
+#ifdef HAVE_BUG_FUNCTION
+# define __BUG_FUNC    __func__
+#else
+# define __BUG_FUNC    NULL
+#endif
 
-#define __BUG_FLAGS(flags, extra)					\
-	asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags))		\
-			     extra);
+#define __BUG_FLAGS(flags, extra)				\
+	asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags, %0)) \
+			     extra : : "i" (__BUG_FUNC) );
 
 #define __WARN_FLAGS(flags)					\
 do {								\
 	instrumentation_begin();				\
-	__BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\
+	if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))			\
+		__BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\
 	instrumentation_end();					\
 } while (0)
 
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:24 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:24 +0000
Subject: [PATCH v4 09/14] parisc: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-10-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

While at it, declare assembler parameters as constants where possible.
Refine .blockz instructions to calculate the necessary padding instead
of using fixed values.

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Acked-by: Helge Deller <deller at gmx.de>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/parisc/include/asm/bug.h | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h
index 833555f74ffa..b59c3f7380bf 100644
--- a/arch/parisc/include/asm/bug.h
+++ b/arch/parisc/include/asm/bug.h
@@ -23,8 +23,17 @@
 # define __BUG_REL(val) ".word " __stringify(val)
 #endif
 
-
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	__BUG_REL(%c1)
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC_PTR
+# define __BUG_FUNC	NULL
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define BUG()								\
 	do {								\
 		asm volatile("\n"					\
@@ -33,10 +42,12 @@
 			     "\t.align 4\n"				\
 			     "2:\t" __BUG_REL(1b) "\n"			\
 			     "\t" __BUG_REL(%c0)  "\n"			\
-			     "\t.short %1, %2\n"			\
-			     "\t.blockz %3-2*4-2*2\n"			\
+			     "\t" __BUG_FUNC_PTR  "\n"			\
+			     "\t.short %c2, %c3\n"			\
+			     "\t.blockz %c4-(.-2b)\n"			\
 			     "\t.popsection"				\
-			     : : "i" (__FILE__), "i" (__LINE__),	\
+			     : : "i" (__FILE__), "i" (__BUG_FUNC),	\
+			     "i" (__LINE__),				\
 			     "i" (0), "i" (sizeof(struct bug_entry)) );	\
 		unreachable();						\
 	} while(0)
@@ -58,10 +69,12 @@
 			     "\t.align 4\n"				\
 			     "2:\t" __BUG_REL(1b) "\n"			\
 			     "\t" __BUG_REL(%c0)  "\n"			\
-			     "\t.short %1, %2\n"			\
-			     "\t.blockz %3-2*4-2*2\n"			\
+			     "\t" __BUG_FUNC_PTR  "\n"			\
+			     "\t.short %c2, %3\n"			\
+			     "\t.blockz %c4-(.-2b)\n"			\
 			     "\t.popsection"				\
-			     : : "i" (__FILE__), "i" (__LINE__),	\
+			     : : "i" (__FILE__), "i" (__BUG_FUNC),	\
+			     "i" (__LINE__),				\
 			     "i" (BUGFLAG_WARNING|(flags)),		\
 			     "i" (sizeof(struct bug_entry)) );		\
 	} while(0)
@@ -74,7 +87,7 @@
 			     "\t.align 4\n"				\
 			     "2:\t" __BUG_REL(1b) "\n"			\
 			     "\t.short %0\n"				\
-			     "\t.blockz %1-4-2\n"			\
+			     "\t.blockz %c1-(.-2b)\n"			\
 			     "\t.popsection"				\
 			     : : "i" (BUGFLAG_WARNING|(flags)),		\
 			     "i" (sizeof(struct bug_entry)) );		\
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:25 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:25 +0000
Subject: [PATCH v4 10/14] s390: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-11-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because
__func__ is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Heiko Carstens <hca at linux.ibm.com>
Cc: Vasily Gorbik <gor at linux.ibm.com>
Cc: Alexander Gordeev <agordeev at linux.ibm.com>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/s390/include/asm/bug.h | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
index c500d45fb465..44d4e9f24ae0 100644
--- a/arch/s390/include/asm/bug.h
+++ b/arch/s390/include/asm/bug.h
@@ -8,6 +8,15 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	"	.long	%0-.\n"
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC_PTR
+# define __BUG_FUNC	NULL
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define __EMIT_BUG(x) do {					\
 	asm_inline volatile(					\
 		"0:	mc	0,0\n"				\
@@ -17,10 +26,12 @@
 		".section __bug_table,\"aw\"\n"			\
 		"2:	.long	0b-.\n"				\
 		"	.long	1b-.\n"				\
-		"	.short	%0,%1\n"			\
-		"	.org	2b+%2\n"			\
+		__BUG_FUNC_PTR					\
+		"	.short	%1,%2\n"			\
+		"	.org	2b+%3\n"			\
 		".previous\n"					\
-		: : "i" (__LINE__),				\
+		: : "i" (__BUG_FUNC),				\
+		    "i" (__LINE__),				\
 		    "i" (x),					\
 		    "i" (sizeof(struct bug_entry)));		\
 } while (0)
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:26 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:26 +0000
Subject: [PATCH v4 11/14] sh: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-12-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Rich Felker <dalias at libc.org>
Cc: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/sh/include/asm/bug.h | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h
index 05a485c4fabc..470ce6567d20 100644
--- a/arch/sh/include/asm/bug.h
+++ b/arch/sh/include/asm/bug.h
@@ -24,21 +24,36 @@
  * The offending file and line are encoded in the __bug_table section.
  */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	"\t.long %O2\n"
+#else
+# define __BUG_FUNC_PTR
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define _EMIT_BUG_ENTRY				\
 	"\t.pushsection __bug_table,\"aw\"\n"	\
 	"2:\t.long 1b, %O1\n"			\
-	"\t.short %O2, %O3\n"			\
-	"\t.org 2b+%O4\n"			\
+	__BUG_FUNC_PTR				\
+	"\t.short %O3, %O4\n"			\
+	"\t.org 2b+%O5\n"			\
 	"\t.popsection\n"
 #else
 #define _EMIT_BUG_ENTRY				\
 	"\t.pushsection __bug_table,\"aw\"\n"	\
 	"2:\t.long 1b\n"			\
-	"\t.short %O3\n"			\
-	"\t.org 2b+%O4\n"			\
+	"\t.short %O4\n"			\
+	"\t.org 2b+%O5\n"			\
 	"\t.popsection\n"
 #endif
 
+#ifdef HAVE_BUG_FUNCTION
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC	NULL
+#endif
+
 #define BUG()						\
 do {							\
 	__asm__ __volatile__ (				\
@@ -47,6 +62,7 @@ do {							\
 		 :					\
 		 : "n" (TRAPA_BUG_OPCODE),		\
 		   "i" (__FILE__),			\
+		   "i" (__BUG_FUNC),			\
 		   "i" (__LINE__), "i" (0),		\
 		   "i" (sizeof(struct bug_entry)));	\
 	unreachable();					\
@@ -60,6 +76,7 @@ do {							\
 		 :					\
 		 : "n" (TRAPA_BUG_OPCODE),		\
 		   "i" (__FILE__),			\
+		   "i" (__BUG_FUNC),			\
 		   "i" (__LINE__),			\
 		   "i" (BUGFLAG_WARNING|(flags)),	\
 		   "i" (sizeof(struct bug_entry)));	\
@@ -85,6 +102,7 @@ do {							\
 		 :					\
 		 : "n" (TRAPA_BUG_OPCODE),		\
 		   "i" (__FILE__),			\
+		   "i" (__BUG_FUNC),			\
 		   "i" (__LINE__),			\
 		   "i" (BUGFLAG_UNWINDER),		\
 		   "i" (sizeof(struct bug_entry)));	\
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:27 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:27 +0000
Subject: [PATCH v4 12/14] sh: Move defines needed for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-13-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Declaring the defines needed for suppressing warning inside
'#ifdef CONFIG_DEBUG_BUGVERBOSE' results in a kerneldoc warning.

.../bug.h:29: warning: expecting prototype for _EMIT_BUG_ENTRY().
	Prototype was for HAVE_BUG_FUNCTION() instead

Move the defines above the kerneldoc entry for _EMIT_BUG_ENTRY
to make kerneldoc happy.

Reported-by: Simon Horman <horms at kernel.org>
Cc: Simon Horman <horms at kernel.org>
Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Rich Felker <dalias at libc.org>
Cc: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/sh/include/asm/bug.h | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h
index 470ce6567d20..bf4947d51d69 100644
--- a/arch/sh/include/asm/bug.h
+++ b/arch/sh/include/asm/bug.h
@@ -11,6 +11,15 @@
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_WARN_ON
 
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	"\t.long %O2\n"
+#else
+# define __BUG_FUNC_PTR
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
 /**
  * _EMIT_BUG_ENTRY
  * %1 - __FILE__
@@ -25,13 +34,6 @@
  */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 
-#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
-# define HAVE_BUG_FUNCTION
-# define __BUG_FUNC_PTR	"\t.long %O2\n"
-#else
-# define __BUG_FUNC_PTR
-#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
-
 #define _EMIT_BUG_ENTRY				\
 	"\t.pushsection __bug_table,\"aw\"\n"	\
 	"2:\t.long 1b, %O1\n"			\
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:28 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:28 +0000
Subject: [PATCH v4 13/14] riscv: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-14-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

To simplify the implementation, unify the __BUG_ENTRY_ADDR and
__BUG_ENTRY_FILE macros into a single macro named __BUG_REL() which takes
the address, file, or function reference as parameter.

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Albert Ou <aou at eecs.berkeley.edu>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/riscv/include/asm/bug.h | 38 ++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h
index 1aaea81fb141..79f360af4ad8 100644
--- a/arch/riscv/include/asm/bug.h
+++ b/arch/riscv/include/asm/bug.h
@@ -30,26 +30,39 @@
 typedef u32 bug_insn_t;
 
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
-#define __BUG_ENTRY_ADDR	RISCV_INT " 1b - ."
-#define __BUG_ENTRY_FILE	RISCV_INT " %0 - ."
+#define __BUG_REL(val)	RISCV_INT " " __stringify(val) " - ."
 #else
-#define __BUG_ENTRY_ADDR	RISCV_PTR " 1b"
-#define __BUG_ENTRY_FILE	RISCV_PTR " %0"
+#define __BUG_REL(val)	RISCV_PTR " " __stringify(val)
 #endif
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	__BUG_REL(%1)
+#else
+# define __BUG_FUNC_PTR
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define __BUG_ENTRY			\
-	__BUG_ENTRY_ADDR "\n\t"		\
-	__BUG_ENTRY_FILE "\n\t"		\
-	RISCV_SHORT " %1\n\t"		\
-	RISCV_SHORT " %2"
+	__BUG_REL(1b) "\n\t"		\
+	__BUG_REL(%0) "\n\t"		\
+	__BUG_FUNC_PTR "\n\t"		\
+	RISCV_SHORT " %2\n\t"		\
+	RISCV_SHORT " %3"
 #else
 #define __BUG_ENTRY			\
-	__BUG_ENTRY_ADDR "\n\t"		\
-	RISCV_SHORT " %2"
+	__BUG_REL(1b) "\n\t"		\
+	RISCV_SHORT " %3"
 #endif
 
 #ifdef CONFIG_GENERIC_BUG
+#ifdef HAVE_BUG_FUNCTION
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC	NULL
+#endif
+
 #define __BUG_FLAGS(flags)					\
 do {								\
 	__asm__ __volatile__ (					\
@@ -58,10 +71,11 @@ do {								\
 			".pushsection __bug_table,\"aw\"\n\t"	\
 		"2:\n\t"					\
 			__BUG_ENTRY "\n\t"			\
-			".org 2b + %3\n\t"                      \
+			".org 2b + %4\n\t"                      \
 			".popsection"				\
 		:						\
-		: "i" (__FILE__), "i" (__LINE__),		\
+		: "i" (__FILE__), "i" (__BUG_FUNC),		\
+		  "i" (__LINE__),				\
 		  "i" (flags),					\
 		  "i" (sizeof(struct bug_entry)));              \
 } while (0)
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:29 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:29 +0000
Subject: [PATCH v4 14/14] powerpc: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-15-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Acked-by: Michael Ellerman <mpe at ellerman.id.au>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/powerpc/include/asm/bug.h | 37 +++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
index 1db485aacbd9..5b06745d20aa 100644
--- a/arch/powerpc/include/asm/bug.h
+++ b/arch/powerpc/include/asm/bug.h
@@ -14,6 +14,9 @@
 	 .section __bug_table,"aw"
 5001:	 .4byte \addr - .
 	 .4byte 5002f - .
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+	 .4byte 0
+#endif
 	 .short \line, \flags
 	 .org 5001b+BUG_ENTRY_SIZE
 	 .previous
@@ -32,30 +35,46 @@
 #endif /* verbose */
 
 #else /* !__ASSEMBLY__ */
-/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
-   sizeof(struct bug_entry), respectively */
+/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3,%4 to be FILE, __func__, LINE, flags
+   and sizeof(struct bug_entry), respectively */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR	"	.4byte %1 - .\n"
+#else
+# define __BUG_FUNC_PTR
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
 #define _EMIT_BUG_ENTRY				\
 	".section __bug_table,\"aw\"\n"		\
 	"2:	.4byte 1b - .\n"		\
 	"	.4byte %0 - .\n"		\
-	"	.short %1, %2\n"		\
-	".org 2b+%3\n"				\
+	__BUG_FUNC_PTR				\
+	"	.short %2, %3\n"		\
+	".org 2b+%4\n"				\
 	".previous\n"
 #else
 #define _EMIT_BUG_ENTRY				\
 	".section __bug_table,\"aw\"\n"		\
 	"2:	.4byte 1b - .\n"		\
-	"	.short %2\n"			\
-	".org 2b+%3\n"				\
+	"	.short %3\n"			\
+	".org 2b+%4\n"				\
 	".previous\n"
 #endif
 
+#ifdef HAVE_BUG_FUNCTION
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC	NULL
+#endif
+
 #define BUG_ENTRY(insn, flags, ...)			\
 	__asm__ __volatile__(				\
 		"1:	" insn "\n"			\
 		_EMIT_BUG_ENTRY				\
-		: : "i" (__FILE__), "i" (__LINE__),	\
+		: : "i" (__FILE__), "i" (__BUG_FUNC),	\
+		  "i" (__LINE__),			\
 		  "i" (flags),				\
 		  "i" (sizeof(struct bug_entry)),	\
 		  ##__VA_ARGS__)
@@ -80,7 +99,7 @@
 		if (x)						\
 			BUG();					\
 	} else {						\
-		BUG_ENTRY(PPC_TLNEI " %4, 0", 0, "r" ((__force long)(x)));	\
+		BUG_ENTRY(PPC_TLNEI " %5, 0", 0, "r" ((__force long)(x)));	\
 	}							\
 } while (0)
 
@@ -90,7 +109,7 @@
 		if (__ret_warn_on)				\
 			__WARN();				\
 	} else {						\
-		BUG_ENTRY(PPC_TLNEI " %4, 0",			\
+		BUG_ENTRY(PPC_TLNEI " %5, 0",			\
 			  BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN),	\
 			  "r" (__ret_warn_on));	\
 	}							\
-- 
2.34.1



From acarmina at redhat.com  Thu Mar 13 04:43:22 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 11:43:22 +0000
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <20250313114329.284104-8-acarmina@redhat.com>

From: Guenter Roeck <linux at roeck-us.net>

Add name of functions triggering warning backtraces to the __bug_table
object section to enable support for suppressing WARNING backtraces.

To limit image size impact, the pointer to the function name is only added
to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
parameter is replaced with a (dummy) NULL parameter to avoid an image size
increase due to unused __func__ entries (this is necessary because __func__
is not a define but a virtual variable).

Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Signed-off-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
---
 arch/arm64/include/asm/asm-bug.h | 27 ++++++++++++++++++---------
 arch/arm64/include/asm/bug.h     |  8 +++++++-
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h
index 6e73809f6492..bf0a5ba81611 100644
--- a/arch/arm64/include/asm/asm-bug.h
+++ b/arch/arm64/include/asm/asm-bug.h
@@ -8,37 +8,46 @@
 #include <asm/brk-imm.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
-#define __BUGVERBOSE_LOCATION(file, line)			\
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+# define HAVE_BUG_FUNCTION
+# define __BUG_FUNC_PTR(func)	.long func - .;
+#else
+# define __BUG_FUNC_PTR(func)
+#endif
+
+#define _BUGVERBOSE_LOCATION(file, func, line) __BUGVERBOSE_LOCATION(file, func, line)
+#define __BUGVERBOSE_LOCATION(file, func, line)		\
 		.pushsection .rodata.str,"aMS", at progbits,1;	\
 	14472:	.string file;					\
 		.popsection;					\
 								\
 		.long 14472b - .;				\
+		__BUG_FUNC_PTR(func)				\
 		.short line;
 #else
-#define _BUGVERBOSE_LOCATION(file, line)
+#define _BUGVERBOSE_LOCATION(file, func, line)
 #endif
 
 #ifdef CONFIG_GENERIC_BUG
 
-#define __BUG_ENTRY(flags) 				\
+#define __BUG_ENTRY(flags, func)			\
 		.pushsection __bug_table,"aw";		\
 		.align 2;				\
 	14470:	.long 14471f - .;			\
-_BUGVERBOSE_LOCATION(__FILE__, __LINE__)		\
+_BUGVERBOSE_LOCATION(__FILE__, func, __LINE__)		\
 		.short flags; 				\
 		.align 2;				\
 		.popsection;				\
 	14471:
 #else
-#define __BUG_ENTRY(flags)
+#define __BUG_ENTRY(flags, func)
 #endif
 
-#define ASM_BUG_FLAGS(flags)				\
-	__BUG_ENTRY(flags)				\
+#define ASM_BUG_FLAGS(flags, func)			\
+	__BUG_ENTRY(flags, func)			\
 	brk	BUG_BRK_IMM
 
-#define ASM_BUG()	ASM_BUG_FLAGS(0)
+#define ASM_BUG()	ASM_BUG_FLAGS(0, .)
 
 #endif /* __ASM_ASM_BUG_H */
diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
index 28be048db3f6..044c5e24a17d 100644
--- a/arch/arm64/include/asm/bug.h
+++ b/arch/arm64/include/asm/bug.h
@@ -11,8 +11,14 @@
 
 #include <asm/asm-bug.h>
 
+#ifdef HAVE_BUG_FUNCTION
+# define __BUG_FUNC	__func__
+#else
+# define __BUG_FUNC	NULL
+#endif
+
 #define __BUG_FLAGS(flags)				\
-	asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
+	asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
 
 #define BUG() do {					\
 	__BUG_FLAGS(0);					\
-- 
2.34.1



From leo.yan at arm.com  Thu Mar 13 04:46:49 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 11:46:49 +0000
Subject: [PATCH 3/7] coresight: Only check bottom two claim bits
In-Reply-To: <20250211103945.967495-4-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-4-james.clark@linaro.org>
Message-ID: <20250313114649.GP9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:39AM +0000, James Clark wrote:
> 
> The use of the whole register and == could break the claim mechanism if
> any of the other bits are used in the future. The referenced doc "PSCI -
> ARM DEN 0022D" also says to only read and clear the bottom two bits.
> 
> Use FIELD_GET() to extract only the relevant part.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

I checked the latest PSCI spec DEN0022F.b, which has no change for
for only using lowest two bits in claim register.

Reviewed-by: Leo Yan <leo.yan at arm.com>


> ---
>  drivers/hwtracing/coresight/coresight-core.c | 3 ++-
>  drivers/hwtracing/coresight/coresight-priv.h | 1 +
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index a669872b4118..7b53165c93af 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -129,7 +129,8 @@ coresight_find_out_connection(struct coresight_device *csdev,
> 
>  static inline u32 coresight_read_claim_tags(struct csdev_access *csa)
>  {
> -       return csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMCLR);
> +       return FIELD_GET(CORESIGHT_CLAIM_MASK,
> +                        csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMCLR));
>  }
> 
>  static inline bool coresight_is_claimed_self_hosted(struct csdev_access *csa)
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 05f891ca6b5c..cc7ff1e36ef4 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -35,6 +35,7 @@ extern const struct device_type coresight_dev_type[];
>   * Coresight device CLAIM protocol.
>   * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
>   */
> +#define CORESIGHT_CLAIM_MASK           GENMASK(1, 0)
>  #define CORESIGHT_CLAIM_SELF_HOSTED    BIT(1)
> 
>  #define TIMEOUT_US             100
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From luca.ceresoli at bootlin.com  Thu Mar 13 04:56:56 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 13 Mar 2025 12:56:56 +0100
Subject: [PATCH v6 14/26] drm/bridge: add support for refcounted DRM
 bridges
In-Reply-To: <20250207-ingenious-daffodil-dugong-51be57@houat>
References: <20250206-hotplug-drm-bridge-v6-0-9d6f2c9c3058@bootlin.com>
	<20250206-hotplug-drm-bridge-v6-14-9d6f2c9c3058@bootlin.com>
	<20250207-ingenious-daffodil-dugong-51be57@houat>
Message-ID: <20250313125656.70448d09@booty>

Hello Maxime,

On Fri, 7 Feb 2025 12:47:51 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> Hi,
> 
> On Thu, Feb 06, 2025 at 07:14:29PM +0100, Luca Ceresoli wrote:
> > DRM bridges are currently considered as a fixed element of a DRM card, and
> > thus their lifetime is assumed to extend for as long as the card
> > exists. New use cases, such as hot-pluggable hardware with video bridges,
> > require DRM bridges to be added and removed to a DRM card without tearing
> > the card down. This is possible for connectors already (used by DP MST), so
> > add this possibility to DRM bridges as well.
> > 
> > Implementation is based on drm_connector_init() as far as it makes sense,
> > and differs when it doesn't. A difference is that bridges are not exposed
> > to userspace, hence struct drm_bridge does not embed a struct
> > drm_mode_object which would provide the refcount. Instead we add to struct
> > drm_bridge a refcount field (we don't need other struct drm_mode_object
> > fields here) and instead of using the drm_mode_object_*() functions we
> > reimplement from those functions the few lines that drm_bridge needs for
> > refcounting.
> > 
> > Also add a new devm_drm_bridge_alloc() macro to allocate a new refcounted
> > bridge.
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>  
> 
> So, a couple of general comments:
> 
> - I've said it a couple of times already, but I really think you're
>   making it harder than necessary for you here. This (and only this!)
>   should be the very first series you should be pushing. The rest can
>   only ever work if that work goes through, and it's already hard enough
>   as it is. So, split that patch into a series of its own, get that
>   merged, and then we will be able to deal with panels conversion and
>   whatever. That's even more true with panels since there's ongoing work
>   that will make it easier for you too. So the best thing here is
>   probably to wait.
> 
> - This patch really needs to be split into several patches, something
>   along the lines of:
> 
>   + Creating devm_drm_bridge_alloc()
>   + Adding refcounting
>   + Taking the references in all the needed places
>   + Converting a bunch of drivers

After reading Anusha's "[PATCH RFC 0/2] drm/panel: Refcounted panel
allocation" [0] I think I need a clarification about the 4 steps you had
outlined in the above quoted text. Are you suggesting those are four
_series_, and you'd want to see a series only creating
devm_drm_bridge_alloc() as a first step, similarly to Anusha's work?

That was not my understanding so far, and so I've been working on a
series containing all 4 items, and it's growing very long due to item 3
needing to touch many dozen drivers which need to put a bridge (many
are identical oneliner patches though).

Luca

[0] https://lore.kernel.org/all/20250312-drm-panel-v1-0-e99cd69f6136 at redhat.com/

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From jonas at kwiboo.se  Thu Mar 13 05:03:04 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 13 Mar 2025 13:03:04 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250313090109.1910997-1-amadeus@jmu.edu.cn>
References: <60065c0b-4597-4976-b74b-172556c4e156@kwiboo.se>
 <20250313090109.1910997-1-amadeus@jmu.edu.cn>
Message-ID: <22d849c3-8a0d-4704-b69c-8019c7f70ca7@kwiboo.se>

Hi,

On 2025-03-13 10:01, Chukun Pan wrote:
> Hi,
> 
>> I have not seen any issue with PWM using the merged patch having
>> pinctrl-names=default.
>>
>> Please see my Linux tree [1] and U-Boot tree [2], those are little ahead
>> of what has been posted on ML, e.g. it has working USB2.0 host, CPU opp,
>> Hantro VPU, GPU + opp, arm and logic pwm regulators for E20C, ROCK 2A/2F
>> and Sige1.
>>
>> Please see my Linux tree [1] and U-Boot tree [2], those are little ahead
>> of what has been posted on ML, e.g. it has working USB2.0 host, CPU opp,
>> Hantro VPU, GPU + opp, arm and logic pwm regulators for E20C, ROCK 2A/2F
>> and Sige1.
>> ...
>> [1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250311-rk3528/
>> [2] https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/commits/rk3528
> 
> I tested your kernel device tree on E20C earlier today and still have
> the same issue. But if I replace u-boot with the link [2] you provided,
> it will work fine. For reference, I was using v2025.01 plus this series
> of patches [3]. So it looks like u-boot does something and kernel doesn't?

Interesting, good that it works with the updated U-Boot. Main change
compared to v1 is that it now use clock/reset id and DT closer to what
has been merged in mainline Linux. It also has DT params to help
initialize the two pwm regulators used by these boards.

I will try with the old v1 U-Boot series and see if I can replicated
your issue.

Regards,
Jonas

> 
> [3] https://lore.kernel.org/u-boot/20250123224844.3104592-1-jonas at kwiboo.se/
> 
> Thanks,
> Chukun
> 
> --
> 2.25.1
> 



From will at kernel.org  Thu Mar 13 05:04:25 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 12:04:25 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Map the hypervisor FF-A buffers on
 ffa init
In-Reply-To: <Z8iZkQHknZfY7mpn@google.com>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-4-sebastianene@google.com>
 <20250303234259.GA30749@willie-the-truck>
 <Z8ZPBZF7J-qKdb_i@google.com>
 <20250304015633.GA30882@willie-the-truck>
 <Z8c6enoolJe7Zeqk@google.com>
 <20250305003808.GA31667@willie-the-truck>
 <Z8iZkQHknZfY7mpn@google.com>
Message-ID: <20250313120424.GA7356@willie-the-truck>

On Wed, Mar 05, 2025 at 06:36:01PM +0000, Sebastian Ene wrote:
> On Wed, Mar 05, 2025 at 12:38:08AM +0000, Will Deacon wrote:
> > On Tue, Mar 04, 2025 at 05:38:02PM +0000, Sebastian Ene wrote:
> > > On Tue, Mar 04, 2025 at 01:56:35AM +0000, Will Deacon wrote:
> > > >   | [...] negotiation of the version must happen before an invocation of
> > > >   | any other FF-A ABI
> > > > 
> > > 
> > > We do that, as the hypervisor negotiates its own version in
> > > hyp_ffa_init.
> > 
> > hyp_ffa_init() only issues FFA_VERSION afaict, which is the one call
> > that you're allowed to make during negotiation. So the existing code is
> > fine.
> > 
> > > I think the host shouldn't be allowed to overwrite the
> > > hyp_ffa_version obtained from _init, this feels wrong as you
> > > can have a driver that forcefully downgrades the hypervisor to an old
> > > version.
> > 
> > I think that's also fine. The FFA code in the hypervisor exists solely
> > to proxy requests from the host; it's not used for anything else and so,
> > from the host's persective, FFA should behave identically to the case in
> > which the proxy is not present (e.g. if we were just using VHE). That
> > means that we're doing the right thing by deferring to the host for
> > version negotation.
> > 
> > Are you saying there's a bug in the current code if the host negotiates
> > the downgrade?
> 
> It is an issue *only* for doing guest-ffa (which isn't posted here yet).
> If we allow the host to dictate the version & there is an issue with TZ
> FF-A dispatcher in that version => the guests will be affected by this
> as well.

When we get to guests doing FF-A, I still think the host should be
responsible for the version negotiation and guests should just be given
whatever has been negotiated. We could extend the hypervisor to marshall
between different versions, but I'd rather do that only if we actually
need it.

> > > We need to do three things, Sudeep & Will please correct me if I am
> > > wrong, but this is how I see it:
> > > 
> > > - the hypervisor should act as a separate entity (it has a different ID and
> > > in the current implementation we don't do a distinction between host/hyp) and
> > > it should be able to lock its own version from init.
> > 
> > I strongly disagree with that. The hypervisor isn't using FFA for
> > anything other than proxying the host and so we don't need to negotiate
> > a separate version.
> > 
> > What would we gain by doing this? Is there a bug with what we're doing
> > at the moment?
> 
> I think we need to make a distinction between the host and the
> hypervisor when we are adding support for guest-ffa. We currently have
> the same id (== 0) for both of them.

Right, and we currently don't support guest-ffa, so no problem :)

> > > - keep a separate version negotiated for the host
> > > - trap FFA_ID_GET from the host and return ID=1 because
> > >   currently we forward the call to the TZ and it returns the same ID
> > >   as the (hypervisor == 0).
> > 
> > Why is this beneficial? It just looks like complexity at EL2 for no gain
> > to me, but maybe I'm missing something.
> >
> 
> Because the host can impersonate the hypervisor using ff-a direct calls atm.
> and we are in a position to restrict the host from playing nasty games
> with TZ.

Can you give a specific example of why impersonating a direct call is a
problem? I agree that it sounds bad, but the hypervisor is still in the
middle and so it can check what the call is requesting.

Will


From ulf.hansson at linaro.org  Thu Mar 13 05:15:15 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Thu, 13 Mar 2025 13:15:15 +0100
Subject: [PATCH] block: remove unused parameter
In-Reply-To: <20250313035322.243239-1-anuj20.g@samsung.com>
References: <CGME20250313040150epcas5p347f94dac34fd2946dea51049559ee1de@epcas5p3.samsung.com>
 <20250313035322.243239-1-anuj20.g@samsung.com>
Message-ID: <CAPDyKFqdK0OPKkTK5C5b1_9kXNSkXJKBvBSa80eXj+GpNfEKBg@mail.gmail.com>

On Thu, 13 Mar 2025 at 06:13, Anuj Gupta <anuj20.g at samsung.com> wrote:
>
> request_queue param is not used by blk_rq_map_sg and __blk_rq_map_sg.
> remove it.
>
> Signed-off-by: Anuj Gupta <anuj20.g at samsung.com>

Acked-by: Ulf Hansson <ulf.hansson at linaro.org> # For MMC/MEMSTICK

> ---
>  block/blk-merge.c                   | 4 ++--
>  block/bsg-lib.c                     | 2 +-
>  drivers/block/mtip32xx/mtip32xx.c   | 2 +-
>  drivers/block/rnbd/rnbd-clt.c       | 2 +-
>  drivers/block/sunvdc.c              | 2 +-
>  drivers/block/virtio_blk.c          | 2 +-
>  drivers/block/xen-blkfront.c        | 2 +-
>  drivers/memstick/core/ms_block.c    | 2 +-
>  drivers/memstick/core/mspro_block.c | 4 +---
>  drivers/mmc/core/queue.c            | 2 +-
>  drivers/mtd/ubi/block.c             | 2 +-
>  drivers/nvme/host/apple.c           | 2 +-
>  drivers/nvme/host/fc.c              | 2 +-
>  drivers/nvme/host/pci.c             | 2 +-
>  drivers/nvme/host/rdma.c            | 3 +--
>  drivers/nvme/target/loop.c          | 2 +-
>  drivers/scsi/scsi_lib.c             | 2 +-
>  include/linux/blk-mq.h              | 9 ++++-----
>  18 files changed, 22 insertions(+), 26 deletions(-)
>
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 1d1589c35297..fdd4efb54c6c 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -551,8 +551,8 @@ static inline struct scatterlist *blk_next_sg(struct scatterlist **sg,
>   * Map a request to scatterlist, return number of sg entries setup. Caller
>   * must make sure sg can hold rq->nr_phys_segments entries.
>   */
> -int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist, struct scatterlist **last_sg)
> +int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
> +                   struct scatterlist **last_sg)
>  {
>         struct req_iterator iter = {
>                 .bio    = rq->bio,
> diff --git a/block/bsg-lib.c b/block/bsg-lib.c
> index 93523d8f8195..9ceb5d0832f5 100644
> --- a/block/bsg-lib.c
> +++ b/block/bsg-lib.c
> @@ -219,7 +219,7 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
>         if (!buf->sg_list)
>                 return -ENOMEM;
>         sg_init_table(buf->sg_list, req->nr_phys_segments);
> -       buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
> +       buf->sg_cnt = blk_rq_map_sg(req, buf->sg_list);
>         buf->payload_len = blk_rq_bytes(req);
>         return 0;
>  }
> diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
> index 95361099a2dc..0d619df03fa9 100644
> --- a/drivers/block/mtip32xx/mtip32xx.c
> +++ b/drivers/block/mtip32xx/mtip32xx.c
> @@ -2056,7 +2056,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, struct request *rq,
>         unsigned int nents;
>
>         /* Map the scatter list for DMA access */
> -       nents = blk_rq_map_sg(hctx->queue, rq, command->sg);
> +       nents = blk_rq_map_sg(rq, command->sg);
>         nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
>
>         prefetch(&port->flags);
> diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
> index 82467ecde7ec..15627417f12e 100644
> --- a/drivers/block/rnbd/rnbd-clt.c
> +++ b/drivers/block/rnbd/rnbd-clt.c
> @@ -1010,7 +1010,7 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
>          * See queue limits.
>          */
>         if ((req_op(rq) != REQ_OP_DISCARD) && (req_op(rq) != REQ_OP_WRITE_ZEROES))
> -               sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sgt.sgl);
> +               sg_cnt = blk_rq_map_sg(rq, iu->sgt.sgl);
>
>         if (sg_cnt == 0)
>                 sg_mark_end(&iu->sgt.sgl[0]);
> diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
> index 282f81616a78..2b33fb5b949b 100644
> --- a/drivers/block/sunvdc.c
> +++ b/drivers/block/sunvdc.c
> @@ -485,7 +485,7 @@ static int __send_request(struct request *req)
>         }
>
>         sg_init_table(sg, port->ring_cookies);
> -       nsg = blk_rq_map_sg(req->q, req, sg);
> +       nsg = blk_rq_map_sg(req, sg);
>
>         len = 0;
>         for (i = 0; i < nsg; i++)
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index 6a61ec35f426..a3df4d49bd46 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
> @@ -226,7 +226,7 @@ static int virtblk_map_data(struct blk_mq_hw_ctx *hctx, struct request *req,
>         if (unlikely(err))
>                 return -ENOMEM;
>
> -       return blk_rq_map_sg(hctx->queue, req, vbr->sg_table.sgl);
> +       return blk_rq_map_sg(req, vbr->sg_table.sgl);
>  }
>
>  static void virtblk_cleanup_cmd(struct request *req)
> diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
> index edcd08a9dcef..5babe575c288 100644
> --- a/drivers/block/xen-blkfront.c
> +++ b/drivers/block/xen-blkfront.c
> @@ -751,7 +751,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
>         id = blkif_ring_get_request(rinfo, req, &final_ring_req);
>         ring_req = &rinfo->shadow[id].req;
>
> -       num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg);
> +       num_sg = blk_rq_map_sg(req, rinfo->shadow[id].sg);
>         num_grant = 0;
>         /* Calculate the number of grant used */
>         for_each_sg(rinfo->shadow[id].sg, sg, num_sg, i)
> diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
> index 5b617c1f6789..f4398383ae06 100644
> --- a/drivers/memstick/core/ms_block.c
> +++ b/drivers/memstick/core/ms_block.c
> @@ -1904,7 +1904,7 @@ static void msb_io_work(struct work_struct *work)
>
>                 /* process the request */
>                 dbg_verbose("IO: processing new request");
> -               blk_rq_map_sg(msb->queue, req, sg);
> +               blk_rq_map_sg(req, sg);
>
>                 lba = blk_rq_pos(req);
>
> diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
> index 634d343b6bdb..c9853d887d28 100644
> --- a/drivers/memstick/core/mspro_block.c
> +++ b/drivers/memstick/core/mspro_block.c
> @@ -627,9 +627,7 @@ static int mspro_block_issue_req(struct memstick_dev *card)
>         while (true) {
>                 msb->current_page = 0;
>                 msb->current_seg = 0;
> -               msb->seg_count = blk_rq_map_sg(msb->block_req->q,
> -                                              msb->block_req,
> -                                              msb->req_sg);
> +               msb->seg_count = blk_rq_map_sg(msb->block_req, msb->req_sg);
>
>                 if (!msb->seg_count) {
>                         unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
> index ab662f502fe7..3ba62f825b84 100644
> --- a/drivers/mmc/core/queue.c
> +++ b/drivers/mmc/core/queue.c
> @@ -523,5 +523,5 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
>  {
>         struct request *req = mmc_queue_req_to_req(mqrq);
>
> -       return blk_rq_map_sg(mq->queue, req, mqrq->sg);
> +       return blk_rq_map_sg(req, mqrq->sg);
>  }
> diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
> index 2836905f0152..39cc0a6a4d37 100644
> --- a/drivers/mtd/ubi/block.c
> +++ b/drivers/mtd/ubi/block.c
> @@ -199,7 +199,7 @@ static blk_status_t ubiblock_read(struct request *req)
>          * and ubi_read_sg() will check that limit.
>          */
>         ubi_sgl_init(&pdu->usgl);
> -       blk_rq_map_sg(req->q, req, pdu->usgl.sg);
> +       blk_rq_map_sg(req, pdu->usgl.sg);
>
>         while (bytes_left) {
>                 /*
> diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
> index a060f69558e7..a437eee741e1 100644
> --- a/drivers/nvme/host/apple.c
> +++ b/drivers/nvme/host/apple.c
> @@ -525,7 +525,7 @@ static blk_status_t apple_nvme_map_data(struct apple_nvme *anv,
>         if (!iod->sg)
>                 return BLK_STS_RESOURCE;
>         sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
> -       iod->nents = blk_rq_map_sg(req->q, req, iod->sg);
> +       iod->nents = blk_rq_map_sg(req, iod->sg);
>         if (!iod->nents)
>                 goto out_free_sg;
>
> diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
> index b9929a5a7f4e..1b5ad1173bc7 100644
> --- a/drivers/nvme/host/fc.c
> +++ b/drivers/nvme/host/fc.c
> @@ -2571,7 +2571,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
>         if (ret)
>                 return -ENOMEM;
>
> -       op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
> +       op->nents = blk_rq_map_sg(rq, freq->sg_table.sgl);
>         WARN_ON(op->nents > blk_rq_nr_phys_segments(rq));
>         freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
>                                 op->nents, rq_dma_dir(rq));
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index 950289405ef2..a0b1c57067aa 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -812,7 +812,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
>         if (!iod->sgt.sgl)
>                 return BLK_STS_RESOURCE;
>         sg_init_table(iod->sgt.sgl, blk_rq_nr_phys_segments(req));
> -       iod->sgt.orig_nents = blk_rq_map_sg(req->q, req, iod->sgt.sgl);
> +       iod->sgt.orig_nents = blk_rq_map_sg(req, iod->sgt.sgl);
>         if (!iod->sgt.orig_nents)
>                 goto out_free_sg;
>
> diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
> index 86a2891d9bcc..b5a0295b5bf4 100644
> --- a/drivers/nvme/host/rdma.c
> +++ b/drivers/nvme/host/rdma.c
> @@ -1476,8 +1476,7 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq,
>         if (ret)
>                 return -ENOMEM;
>
> -       req->data_sgl.nents = blk_rq_map_sg(rq->q, rq,
> -                                           req->data_sgl.sg_table.sgl);
> +       req->data_sgl.nents = blk_rq_map_sg(rq, req->data_sgl.sg_table.sgl);
>
>         *count = ib_dma_map_sg(ibdev, req->data_sgl.sg_table.sgl,
>                                req->data_sgl.nents, rq_dma_dir(rq));
> diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
> index a9d112d34d4f..a5c41144667c 100644
> --- a/drivers/nvme/target/loop.c
> +++ b/drivers/nvme/target/loop.c
> @@ -162,7 +162,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
>                 }
>
>                 iod->req.sg = iod->sg_table.sgl;
> -               iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
> +               iod->req.sg_cnt = blk_rq_map_sg(req, iod->sg_table.sgl);
>                 iod->req.transfer_len = blk_rq_payload_bytes(req);
>         }
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index f1cfe0bb89b2..0d29470e86b0 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -1149,7 +1149,7 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
>          * Next, walk the list, and fill in the addresses and sizes of
>          * each segment.
>          */
> -       count = __blk_rq_map_sg(rq->q, rq, cmd->sdb.table.sgl, &last_sg);
> +       count = __blk_rq_map_sg(rq, cmd->sdb.table.sgl, &last_sg);
>
>         if (blk_rq_bytes(rq) & rq->q->limits.dma_pad_mask) {
>                 unsigned int pad_len =
> diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
> index fa2a76cc2f73..f2eff998913d 100644
> --- a/include/linux/blk-mq.h
> +++ b/include/linux/blk-mq.h
> @@ -1165,14 +1165,13 @@ static inline unsigned short blk_rq_nr_discard_segments(struct request *rq)
>         return max_t(unsigned short, rq->nr_phys_segments, 1);
>  }
>
> -int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist, struct scatterlist **last_sg);
> -static inline int blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist)
> +int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
> +               struct scatterlist **last_sg);
> +static inline int blk_rq_map_sg(struct request *rq, struct scatterlist *sglist)
>  {
>         struct scatterlist *last_sg = NULL;
>
> -       return __blk_rq_map_sg(q, rq, sglist, &last_sg);
> +       return __blk_rq_map_sg(rq, sglist, &last_sg);
>  }
>  void blk_dump_rq_flags(struct request *, char *);
>
> --
> 2.25.1
>


From will at kernel.org  Thu Mar 13 05:15:59 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 12:15:59 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <Z8ltm55D1jrv8QtX@bogus>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
 <20250305004522.GC31667@willie-the-truck>
 <20250305094104.vctshdtgdukno2aj@bogus>
 <20250305193425.GA32246@willie-the-truck>
 <Z8ltm55D1jrv8QtX@bogus>
Message-ID: <20250313121559.GB7356@willie-the-truck>

On Thu, Mar 06, 2025 at 09:40:43AM +0000, Sudeep Holla wrote:
> On Wed, Mar 05, 2025 at 07:34:26PM +0000, Will Deacon wrote:
> > On Wed, Mar 05, 2025 at 09:41:04AM +0000, Sudeep Holla wrote:
> > > On Wed, Mar 05, 2025 at 12:45:23AM +0000, Will Deacon wrote:
> > > > Hmm, the FFA spec is characteristically unclear as to whether or not we
> > > > need to release the rx buffer in the case that the flags indicate use of
> > > > the rx buffer but the returned partition count is 0.
> > > > 
> > > > Sudeep -- do you know what we should be doing in that case?
> > > > 
> > > 
> > > We need to call RX_RELEASE here. I went back to the spec to confirm the
> > > same again.
> > > 
> > > v1.2 EAC0 spec Section 7.2.2.4.2 Transfer of buffer ownership
> > > (Or just look for the section title in any version of the spec)
> > > "
> > > 2. Ownership transfer for the RX buffer takes place as follows.
> > >     2. For a framework message,
> > >        1. Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership
> > >        of the caller?s RX buffer from the Producer to the Consumer.
> > > 3. For both types of messages, an invocation of the following FF-A ABIs
> > >     transfers the ownership from the Consumer to the Producer.
> > >        1. FFA_MSG_WAIT ...
> > >        2. FFA_RX_RELEASE.
> > > "
> > > 
> > > Hope that helps, can dig deeper if there are any ambiguities around this.
> > 
> > Thanks Sudeep, but that also makes it sound like we need the RX_RELEASE
> > even if we're not using the RX buffer per the input flags. :/
> > 
> 
> Good spot, I had forgotten about the input flags that can avoid using the
> buffer. I will see if we can improve the spec in that regards.

Thanks. In the meantime, what do you think is the correct behaviour in that
case? I guess _not_ doing the release when the flags don't request the RX
buffer? In other words:


	if (flags & PARTITION_INFO_GET_RETURN_COUNT_ONLY)
		goto out_unlock;

	if (!count)
		goto release_rx;

	[...]

	if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
		ffa_to_smccc_res(res, FFA_RET_ABORTED);
		goto release_rx;
	}

	memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
release_rx:
	ffa_rx_release(&_res);
out_unlock:
	hyp_spin_unlock(&host_buffers.lock);
}


What do you reckon?

Will


From jinpu.wang at ionos.com  Thu Mar 13 05:17:05 2025
From: jinpu.wang at ionos.com (Jinpu Wang)
Date: Thu, 13 Mar 2025 13:17:05 +0100
Subject: [PATCH] block: remove unused parameter
In-Reply-To: <20250313035322.243239-1-anuj20.g@samsung.com>
References: <CGME20250313040150epcas5p347f94dac34fd2946dea51049559ee1de@epcas5p3.samsung.com>
 <20250313035322.243239-1-anuj20.g@samsung.com>
Message-ID: <CAMGffEkm5zkBM7QPbfd7+qiMA92VBfyoRUdb+3CMzqe3ZCs7rg@mail.gmail.com>

On Thu, Mar 13, 2025 at 6:14?AM Anuj Gupta <anuj20.g at samsung.com> wrote:
>
> request_queue param is not used by blk_rq_map_sg and __blk_rq_map_sg.
> remove it.
>
> Signed-off-by: Anuj Gupta <anuj20.g at samsung.com>
> ---
>  block/blk-merge.c                   | 4 ++--
>  block/bsg-lib.c                     | 2 +-
>  drivers/block/mtip32xx/mtip32xx.c   | 2 +-
>  drivers/block/rnbd/rnbd-clt.c       | 2 +-
lgtm.
Acked-by: Jack Wang <jinpu.wang at ionos.com> #rnbd
>  drivers/block/sunvdc.c              | 2 +-
>  drivers/block/virtio_blk.c          | 2 +-
>  drivers/block/xen-blkfront.c        | 2 +-
>  drivers/memstick/core/ms_block.c    | 2 +-
>  drivers/memstick/core/mspro_block.c | 4 +---
>  drivers/mmc/core/queue.c            | 2 +-
>  drivers/mtd/ubi/block.c             | 2 +-
>  drivers/nvme/host/apple.c           | 2 +-
>  drivers/nvme/host/fc.c              | 2 +-
>  drivers/nvme/host/pci.c             | 2 +-
>  drivers/nvme/host/rdma.c            | 3 +--
>  drivers/nvme/target/loop.c          | 2 +-
>  drivers/scsi/scsi_lib.c             | 2 +-
>  include/linux/blk-mq.h              | 9 ++++-----
>  18 files changed, 22 insertions(+), 26 deletions(-)
>
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 1d1589c35297..fdd4efb54c6c 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -551,8 +551,8 @@ static inline struct scatterlist *blk_next_sg(struct scatterlist **sg,
>   * Map a request to scatterlist, return number of sg entries setup. Caller
>   * must make sure sg can hold rq->nr_phys_segments entries.
>   */
> -int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist, struct scatterlist **last_sg)
> +int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
> +                   struct scatterlist **last_sg)
>  {
>         struct req_iterator iter = {
>                 .bio    = rq->bio,
> diff --git a/block/bsg-lib.c b/block/bsg-lib.c
> index 93523d8f8195..9ceb5d0832f5 100644
> --- a/block/bsg-lib.c
> +++ b/block/bsg-lib.c
> @@ -219,7 +219,7 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
>         if (!buf->sg_list)
>                 return -ENOMEM;
>         sg_init_table(buf->sg_list, req->nr_phys_segments);
> -       buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
> +       buf->sg_cnt = blk_rq_map_sg(req, buf->sg_list);
>         buf->payload_len = blk_rq_bytes(req);
>         return 0;
>  }
> diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
> index 95361099a2dc..0d619df03fa9 100644
> --- a/drivers/block/mtip32xx/mtip32xx.c
> +++ b/drivers/block/mtip32xx/mtip32xx.c
> @@ -2056,7 +2056,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, struct request *rq,
>         unsigned int nents;
>
>         /* Map the scatter list for DMA access */
> -       nents = blk_rq_map_sg(hctx->queue, rq, command->sg);
> +       nents = blk_rq_map_sg(rq, command->sg);
>         nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
>
>         prefetch(&port->flags);
> diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
> index 82467ecde7ec..15627417f12e 100644
> --- a/drivers/block/rnbd/rnbd-clt.c
> +++ b/drivers/block/rnbd/rnbd-clt.c
> @@ -1010,7 +1010,7 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
>          * See queue limits.
>          */
>         if ((req_op(rq) != REQ_OP_DISCARD) && (req_op(rq) != REQ_OP_WRITE_ZEROES))
> -               sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sgt.sgl);
> +               sg_cnt = blk_rq_map_sg(rq, iu->sgt.sgl);
>
>         if (sg_cnt == 0)
>                 sg_mark_end(&iu->sgt.sgl[0]);
> diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
> index 282f81616a78..2b33fb5b949b 100644
> --- a/drivers/block/sunvdc.c
> +++ b/drivers/block/sunvdc.c
> @@ -485,7 +485,7 @@ static int __send_request(struct request *req)
>         }
>
>         sg_init_table(sg, port->ring_cookies);
> -       nsg = blk_rq_map_sg(req->q, req, sg);
> +       nsg = blk_rq_map_sg(req, sg);
>
>         len = 0;
>         for (i = 0; i < nsg; i++)
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index 6a61ec35f426..a3df4d49bd46 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
> @@ -226,7 +226,7 @@ static int virtblk_map_data(struct blk_mq_hw_ctx *hctx, struct request *req,
>         if (unlikely(err))
>                 return -ENOMEM;
>
> -       return blk_rq_map_sg(hctx->queue, req, vbr->sg_table.sgl);
> +       return blk_rq_map_sg(req, vbr->sg_table.sgl);
>  }
>
>  static void virtblk_cleanup_cmd(struct request *req)
> diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
> index edcd08a9dcef..5babe575c288 100644
> --- a/drivers/block/xen-blkfront.c
> +++ b/drivers/block/xen-blkfront.c
> @@ -751,7 +751,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
>         id = blkif_ring_get_request(rinfo, req, &final_ring_req);
>         ring_req = &rinfo->shadow[id].req;
>
> -       num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg);
> +       num_sg = blk_rq_map_sg(req, rinfo->shadow[id].sg);
>         num_grant = 0;
>         /* Calculate the number of grant used */
>         for_each_sg(rinfo->shadow[id].sg, sg, num_sg, i)
> diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
> index 5b617c1f6789..f4398383ae06 100644
> --- a/drivers/memstick/core/ms_block.c
> +++ b/drivers/memstick/core/ms_block.c
> @@ -1904,7 +1904,7 @@ static void msb_io_work(struct work_struct *work)
>
>                 /* process the request */
>                 dbg_verbose("IO: processing new request");
> -               blk_rq_map_sg(msb->queue, req, sg);
> +               blk_rq_map_sg(req, sg);
>
>                 lba = blk_rq_pos(req);
>
> diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
> index 634d343b6bdb..c9853d887d28 100644
> --- a/drivers/memstick/core/mspro_block.c
> +++ b/drivers/memstick/core/mspro_block.c
> @@ -627,9 +627,7 @@ static int mspro_block_issue_req(struct memstick_dev *card)
>         while (true) {
>                 msb->current_page = 0;
>                 msb->current_seg = 0;
> -               msb->seg_count = blk_rq_map_sg(msb->block_req->q,
> -                                              msb->block_req,
> -                                              msb->req_sg);
> +               msb->seg_count = blk_rq_map_sg(msb->block_req, msb->req_sg);
>
>                 if (!msb->seg_count) {
>                         unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
> index ab662f502fe7..3ba62f825b84 100644
> --- a/drivers/mmc/core/queue.c
> +++ b/drivers/mmc/core/queue.c
> @@ -523,5 +523,5 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
>  {
>         struct request *req = mmc_queue_req_to_req(mqrq);
>
> -       return blk_rq_map_sg(mq->queue, req, mqrq->sg);
> +       return blk_rq_map_sg(req, mqrq->sg);
>  }
> diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
> index 2836905f0152..39cc0a6a4d37 100644
> --- a/drivers/mtd/ubi/block.c
> +++ b/drivers/mtd/ubi/block.c
> @@ -199,7 +199,7 @@ static blk_status_t ubiblock_read(struct request *req)
>          * and ubi_read_sg() will check that limit.
>          */
>         ubi_sgl_init(&pdu->usgl);
> -       blk_rq_map_sg(req->q, req, pdu->usgl.sg);
> +       blk_rq_map_sg(req, pdu->usgl.sg);
>
>         while (bytes_left) {
>                 /*
> diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
> index a060f69558e7..a437eee741e1 100644
> --- a/drivers/nvme/host/apple.c
> +++ b/drivers/nvme/host/apple.c
> @@ -525,7 +525,7 @@ static blk_status_t apple_nvme_map_data(struct apple_nvme *anv,
>         if (!iod->sg)
>                 return BLK_STS_RESOURCE;
>         sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
> -       iod->nents = blk_rq_map_sg(req->q, req, iod->sg);
> +       iod->nents = blk_rq_map_sg(req, iod->sg);
>         if (!iod->nents)
>                 goto out_free_sg;
>
> diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
> index b9929a5a7f4e..1b5ad1173bc7 100644
> --- a/drivers/nvme/host/fc.c
> +++ b/drivers/nvme/host/fc.c
> @@ -2571,7 +2571,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
>         if (ret)
>                 return -ENOMEM;
>
> -       op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
> +       op->nents = blk_rq_map_sg(rq, freq->sg_table.sgl);
>         WARN_ON(op->nents > blk_rq_nr_phys_segments(rq));
>         freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
>                                 op->nents, rq_dma_dir(rq));
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index 950289405ef2..a0b1c57067aa 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -812,7 +812,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
>         if (!iod->sgt.sgl)
>                 return BLK_STS_RESOURCE;
>         sg_init_table(iod->sgt.sgl, blk_rq_nr_phys_segments(req));
> -       iod->sgt.orig_nents = blk_rq_map_sg(req->q, req, iod->sgt.sgl);
> +       iod->sgt.orig_nents = blk_rq_map_sg(req, iod->sgt.sgl);
>         if (!iod->sgt.orig_nents)
>                 goto out_free_sg;
>
> diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
> index 86a2891d9bcc..b5a0295b5bf4 100644
> --- a/drivers/nvme/host/rdma.c
> +++ b/drivers/nvme/host/rdma.c
> @@ -1476,8 +1476,7 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq,
>         if (ret)
>                 return -ENOMEM;
>
> -       req->data_sgl.nents = blk_rq_map_sg(rq->q, rq,
> -                                           req->data_sgl.sg_table.sgl);
> +       req->data_sgl.nents = blk_rq_map_sg(rq, req->data_sgl.sg_table.sgl);
>
>         *count = ib_dma_map_sg(ibdev, req->data_sgl.sg_table.sgl,
>                                req->data_sgl.nents, rq_dma_dir(rq));
> diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
> index a9d112d34d4f..a5c41144667c 100644
> --- a/drivers/nvme/target/loop.c
> +++ b/drivers/nvme/target/loop.c
> @@ -162,7 +162,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
>                 }
>
>                 iod->req.sg = iod->sg_table.sgl;
> -               iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
> +               iod->req.sg_cnt = blk_rq_map_sg(req, iod->sg_table.sgl);
>                 iod->req.transfer_len = blk_rq_payload_bytes(req);
>         }
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index f1cfe0bb89b2..0d29470e86b0 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -1149,7 +1149,7 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
>          * Next, walk the list, and fill in the addresses and sizes of
>          * each segment.
>          */
> -       count = __blk_rq_map_sg(rq->q, rq, cmd->sdb.table.sgl, &last_sg);
> +       count = __blk_rq_map_sg(rq, cmd->sdb.table.sgl, &last_sg);
>
>         if (blk_rq_bytes(rq) & rq->q->limits.dma_pad_mask) {
>                 unsigned int pad_len =
> diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
> index fa2a76cc2f73..f2eff998913d 100644
> --- a/include/linux/blk-mq.h
> +++ b/include/linux/blk-mq.h
> @@ -1165,14 +1165,13 @@ static inline unsigned short blk_rq_nr_discard_segments(struct request *rq)
>         return max_t(unsigned short, rq->nr_phys_segments, 1);
>  }
>
> -int __blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist, struct scatterlist **last_sg);
> -static inline int blk_rq_map_sg(struct request_queue *q, struct request *rq,
> -               struct scatterlist *sglist)
> +int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist,
> +               struct scatterlist **last_sg);
> +static inline int blk_rq_map_sg(struct request *rq, struct scatterlist *sglist)
>  {
>         struct scatterlist *last_sg = NULL;
>
> -       return __blk_rq_map_sg(q, rq, sglist, &last_sg);
> +       return __blk_rq_map_sg(rq, sglist, &last_sg);
>  }
>  void blk_dump_rq_flags(struct request *, char *);
>
> --
> 2.25.1
>


From m.szyprowski at samsung.com  Thu Mar 13 05:23:02 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Thu, 13 Mar 2025 13:23:02 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
	<e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
	<CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
	<9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
	<417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
Message-ID: <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>

On 13.03.2025 12:01, Robin Murphy wrote:
> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
> [...]
>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my tests I
>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>> relevant kernel log:
>
> ...and the bug-flushing-out begins!
>
>> Unable to handle kernel NULL pointer dereference at virtual address
>> 00000000000003e8
>> Mem abort info:
>> ? ? ESR = 0x0000000096000004
>> ? ? EC = 0x25: DABT (current EL), IL = 32 bits
>> ? ? SET = 0, FnV = 0
>> ? ? EA = 0, S1PTW = 0
>> ? ? FSC = 0x04: level 0 translation fault
>> Data abort info:
>> ? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>> ? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>> ? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>> [00000000000003e8] user address but active_mm is swapper
>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>> Modules linked in:
>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>> Hardware name: Hardkernel ODROID-M1 (DT)
>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>> pc : devm_kmalloc+0x2c/0x114
>> lr : rk_iommu_of_xlate+0x30/0x90
>> ...
>> Call trace:
>> ? ?devm_kmalloc+0x2c/0x114 (P)
>> ? ?rk_iommu_of_xlate+0x30/0x90
>
> Yeah, looks like this is doing something a bit questionable which can't
> work properly. TBH the whole dma_dev thing could probably be cleaned up
> now that we have proper instances, but for now does this work?

Yes, this patch fixes the problem I've observed.

Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>

BTW, this dma_dev idea has been borrowed from my exynos_iommu driver and 
I doubt it can be cleaned up.


>
> (annoyingly none of my Rockchip boards are set up for testing right 
> now, but I might have time to dig one out later)
>
> Thanks,
> Robin.
>
> ----->8-----
>
> Subject: [PATCH] iommu/rockchip: Allocate per-device data sensibly
>
> Now that DT-based probing is finally happening in the right order again,
> it reveals an issue in Rockchip's of_xlate, which can now be called
> during registration, but is using the global dma_dev which is only
> assigned later. However, this makes little sense when we're already
> looking up the correct IOMMU device, who should logically be the owner
> of the devm allocation anyway.
>
> Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe 
> path")
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> ?drivers/iommu/rockchip-iommu.c | 6 +++---
> ?1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/rockchip-iommu.c 
> b/drivers/iommu/rockchip-iommu.c
> index 323cc665c357..48826d1ccfd8 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -1148,12 +1148,12 @@ static int rk_iommu_of_xlate(struct device *dev,
> ???? struct platform_device *iommu_dev;
> ???? struct rk_iommudata *data;
>
> -??? data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
> +??? iommu_dev = of_find_device_by_node(args->np);
> +
> +??? data = devm_kzalloc(&iommu_dev->dev, sizeof(*data), GFP_KERNEL);
> ???? if (!data)
> ???????? return -ENOMEM;
>
> -??? iommu_dev = of_find_device_by_node(args->np);
> -
> ???? data->iommu = platform_get_drvdata(iommu_dev);
> ???? data->iommu->domain = &rk_identity_domain;
> ???? dev_iommu_priv_set(dev, data);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From will at kernel.org  Thu Mar 13 05:25:04 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 12:25:04 +0000
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <20250313114329.284104-8-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
Message-ID: <20250313122503.GA7438@willie-the-truck>

On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
> diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
> index 28be048db3f6..044c5e24a17d 100644
> --- a/arch/arm64/include/asm/bug.h
> +++ b/arch/arm64/include/asm/bug.h
> @@ -11,8 +11,14 @@
>  
>  #include <asm/asm-bug.h>
>  
> +#ifdef HAVE_BUG_FUNCTION
> +# define __BUG_FUNC	__func__
> +#else
> +# define __BUG_FUNC	NULL
> +#endif
> +
>  #define __BUG_FLAGS(flags)				\
> -	asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
> +	asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));

Why is 'i' the right asm constraint to use here? It seems a bit odd to
use that for a pointer.

Will


From sakari.ailus at linux.intel.com  Thu Mar 13 05:25:09 2025
From: sakari.ailus at linux.intel.com (Sakari Ailus)
Date: Thu, 13 Mar 2025 12:25:09 +0000
Subject: [RFC PATCH v2 06/16] dt-bindings: media: i2c: max96717: add
 support for MAX96793
In-Reply-To: <20250309084814.3114794-7-demonsingur@gmail.com>
References: <20250309084814.3114794-1-demonsingur@gmail.com>
 <20250309084814.3114794-7-demonsingur@gmail.com>
Message-ID: <Z9LOpR5yiILj6KsT@kekkonen.localdomain>

Hi Cosmin,

On Sun, Mar 09, 2025 at 10:47:58AM +0200, Cosmin Tanislav wrote:
> MAX96793 is a newer variant of the MAX96717 which also supports GMSL3
> links.
> 
> Document this compatibility.
> 
> Signed-off-by: Cosmin Tanislav <demonsingur at gmail.com>
> ---
>  Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> index 31fb62debdc7..02857f0364c4 100644
> --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
> @@ -27,6 +27,7 @@ description:
>  
>    MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
>    MAX9295A only supports pixel mode.
> +  MAX96793 also supports GMSL3 mode.

Fits on the previous line. Same goes for some of the commit messages in the
set: the limit is 75 characters per line.

>  
>  properties:
>    compatible:
> @@ -36,6 +37,7 @@ properties:
>        - items:
>            - enum:
>                - maxim,max96717
> +              - maxim,max96793
>            - const: maxim,max96717f
>  
>    '#gpio-cells':

-- 
Regards,

Sakari Ailus


From andriy.shevchenko at linux.intel.com  Thu Mar 13 05:31:18 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Thu, 13 Mar 2025 14:31:18 +0200
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <Z9LQFqSweiV-zT3b@smile.fi.intel.com>

On Thu, Mar 13, 2025 at 09:18:18AM +0200, Matti Vaittinen wrote:
> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
> 
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
> 
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.

...

> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
> +					  const struct iio_chan_spec *template,
> +					  int max_chan_id,
> +					  struct iio_chan_spec **cs)
> +{
> +	struct iio_chan_spec *chan_array, *chan;
> +	int num_chan = 0, ret;

Unneeded assignment.

> +	num_chan = iio_adc_device_num_channels(dev);
> +	if (num_chan < 1)
> +		return num_chan;

This is really interesting code. So, if the above returns negative error code,
we return it, if it returns 0, we return success (but 0 channels)?

Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success?
(Under success I assume that returned values are okay to go with, and cs in
your case will be left uninitialised or contain something we don't control.

> +	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
> +				  GFP_KERNEL);
> +	if (!chan_array)
> +		return -ENOMEM;
> +
> +	chan = &chan_array[0];
> +
> +	device_for_each_named_child_node_scoped(dev, child, "channel") {
> +		u32 ch;
> +
> +		ret = fwnode_property_read_u32(child, "reg", &ch);
> +		if (ret)
> +			return ret;

> +		if (max_chan_id != -1 && ch > max_chan_id)
> +			return -ERANGE;

Hmm... What if max_chan_id is equal to an error code?
Or in other words, why -1 is special and not all negative numbers?

Also note, you used unsigned type and compare it to int which,
in case of being negative will give promotion. The ch will not be
big enough in most cases (unless it's great than (INT_MAX + 1).

TL;DR: you have a potential integer overflow here.

> +		*chan = *template;
> +		chan->channel = ch;
> +		chan++;
> +	}
> +
> +	*cs = chan_array;
> +
> +	return num_chan;
> +}

-- 
With Best Regards,
Andy Shevchenko




From kevin.brodsky at arm.com  Thu Mar 13 05:32:31 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Thu, 13 Mar 2025 13:32:31 +0100
Subject: [RFC PATCH v3 00/15] pkeys-based page table hardening
In-Reply-To: <a32cjyekuecoowzbitc2xykilvpu6l3jjtityp7x5hw7xbiysp@5l2lptwmqiug>
References: <20250203101839.1223008-1-kevin.brodsky@arm.com>
 <a32cjyekuecoowzbitc2xykilvpu6l3jjtityp7x5hw7xbiysp@5l2lptwmqiug>
Message-ID: <802963a0-32bd-49e8-82b1-34443acdd5ae@arm.com>

On 06/03/2025 17:23, Maxwell Bland wrote:
> On Mon, Feb 03, 2025 at 10:18:24AM +0000, Kevin Brodsky wrote:
>> This is a proposal to leverage protection keys (pkeys) to harden
>> critical kernel data, by making it mostly read-only. The series includes
>> a simple framework called "kpkeys" to manipulate pkeys for in-kernel use,
>> as well as a page table hardening feature based on that framework
>> (kpkeys_hardened_pgtables). Both are implemented on arm64 as a proof of
>> concept, but they are designed to be compatible with any architecture
>> implementing pkeys.
> Hi Kevin,
>
> This is awesome. When working on some of these problems, I also thought
> of leveraging the POE feature, but was not sure of a good way to make
> it work.

Hi Maxwell,

I'm glad to hear about your interest!

>> Page tables were chosen as they are a popular (and critical) target for
>> attacks, but there are of course many others - this is only a starting
>> point (see section "Further use-cases"). It has become more and more
>> common for accesses to such target data to be mediated by a hypervisor
>> in vendor kernels; the hope is that kpkeys can provide much of that
>> protection in a simpler manner. No benchmarking has been performed at
>> this stage, but the runtime overhead should also be lower (though likely
>> not negligible).
> Some notes here, having implemented similar page table protections,
> albeit using stage-2 page table permissions and a fault handler.
>
> https://lore.kernel.org/all/2wf4kmoqqmod6njviaq33lbxbx6gvdqbksljxykgltwnxo6ruy at 7ueumwmxxh72/
>
> I wanted to know your thoughts on associating specific policies to
> page table updates in cases where an adversary is able to corrupt
> other state associated with parameters to the page table infrastructure
> code, e.g.
>
> arch/arm64/net/bpf_jit_comp.c
> 2417:		if (set_memory_rw(PAGE_MASK & ((uintptr_t)&plt->target),
>
> Is this something we would assume is handled via the security_* hook
> infrastructure, a shadow stack CFI method, or changing the kernel code
> to reverify the data non-modularly, some combination of the above?

This is a good question and the short answer is that I don't know what
the best approach would be. As far as kpkeys are concerned, I'm not sure
they can really help here - it seems to be about the integrity of a
generated BPF program, and surely that program is already made read-only
once generated?

>> - Pages in the linear mapping are assigned a pkey using set_memory_pkey().
>>   This is sufficient for this series, but of course higher-level
>>   interfaces can be introduced later to ask allocators to return pages
>>   marked with a given pkey. It should also be possible to extend this to
>>   vmalloc() if needed.
> One of the interesting points here, acknowledged below, was that this
> relies on having guarantees around the PC value/CFI of the function.
> Since this is the baseline assumption, it feels natural that the
> locking/unlocking would be associated into the existing CFI
> instrumentation, since (from experience) point-patching each mutable
> data structure allocation/deallocation is difficult.

Could you elaborate on this point? Are you referring to protecting
arbitrary data structures with kpkeys, rather than what this series
covers (i.e. pgtables)?

>> # Further use-cases
>>
>> It should be possible to harden various targets using kpkeys, including:
>>
>> - struct cred (enforcing a "mostly read-only" state once committed)
>>
>> - fixmap (occasionally used even after early boot, e.g.
>>   set_swapper_pgd() in arch/arm64/mm/mmu.c)
>>
>> - SELinux state (e.g. struct selinux_state::initialized)
>>
>> ... and many others.
> Be wary that it is not just struct cred but pointers to struct cred.  We
> quickly run into a problem of, for example, in updates to f_op,
> bookkeeping which f_op is OK to have in the file, e.g., in Android's
> 6.1.x:
>
> drivers/gpu/drm/i810/i810_dma.c
> 138:    file_priv->filp->f_op = &i810_buffer_fops;
> 144:    file_priv->filp->f_op = old_fops;
>
> drivers/staging/android/ashmem.c
> 436:            vmfile->f_op = &vmfile_fops;
>
> Where overwriting f_op is a "classic" bypass of protection systems like
> this one.

Indeed, this has been pointed out to me on a few occasions. On that note
I should reference the follow-up series that aims at protecting struct
cred [1].

Using kpkeys to ensure that the task->cred pointer itself is mostly
read-only is not straightforward, because there is just too much
existing code that directly writes to other fields in task_struct -
meaning we can't simply make the whole task_struct mostly read-only.
What could be done is to split out the cred fields in a separate
kpkeys-protected page, and link that page from task_struct. There is a
clear overhead associated with this approach though, and maybe more
importantly we have just displaced the issue as the pointer to that
protected page remains writeable... I'm not sure how much a page-based
technique like pkeys can help here.

[1]
https://lore.kernel.org/linux-hardening/20250203102809.1223255-1-kevin.brodsky at arm.com/

> I think this problem may be totally solvable if POE was integrated into
> something like CFI, since we can guarantee only the code that sets f_op
> to "vmfile_fops" can unlock/relock the file's page.

I'm interested to hear more about this - I don't think I'm aware of the
CFI instrumentation you're referring to.

> Maybe another approach would work better, though?
>
>> # Open questions
>>
>> A few aspects in this RFC that are debatable and/or worth discussing:
>>
>> - There is currently no restriction on how kpkeys levels map to pkeys
>>   permissions. A typical approach is to allocate one pkey per level and
>>   make it writable at that level only. As the number of levels
>>   increases, we may however run out of pkeys, especially on arm64 (just
>>   8 pkeys with POE). Depending on the use-cases, it may be acceptable to
>>   use the same pkey for the data associated to multiple levels.
> Honestly, I associate each protected virtual page in stage-2 with a
> unique tag (manually, right now, but Kees Cook has some magic that
> does the same via alloc_tag.h), and this works really well to track
> specific resources and resource modification semantics "over" a generic
> protection ring.
>
> I think, though, that the code you provided could be used to bootstrap
> such a system by using the overlay to protect a similar page tag lookup
> table, which then can provide the fine-grained protection semantics.

This sounds sensible. Considering that the size of pkeys is between 3
and 5 bits depending on the architecture, to keep the approach generic
we really don't have many keys to play with (7 excluding the default key
on arm64/POE). kpkeys approaches keys in a static way (no dynamic
allocation), so it's best to think of each key as corresponding to one
subsystem defined at compile time.

> I.e. use this baseline to isolate a secure monitor system.
>
> Hopefully that makes sense! (-:
>
>> - kpkeys_set_level() and kpkeys_restore_pkey_reg() are not symmetric:
>>   the former takes a kpkeys level and returns a pkey register value, to
>>   be consumed by the latter. It would be more intuitive to manipulate
>>   kpkeys levels only. However this assumes that there is a 1:1 mapping
>>   between kpkeys levels and pkey register values, while in principle
>>   the mapping is 1:n (certain pkeys may be used outside the kpkeys
>>   framework).
> Another issue I'm not confident in is the assumption of adversary's
> inability to manipulate system control registers. This is true in the
> context of a Heki-like system (or any well-made HVCI), but not totally
> true of a pure EL1 implementation?

This is entirely reliant on the threat model, i.e. only data-only
attacks are in scope. If the adversary successfully hijacks the control
flow to jump in the middle of a function, or achieves arbitrary code
execution, pkeys won't be of much help. Robust CFI is therefore a clear
prerequisite.

>> - An architecture that supports kpkeys is expected to select
>>   CONFIG_ARCH_HAS_KPKEYS and always enable them if available - there is
>>   no CONFIG_KPKEYS to control this behaviour. Since this creates no
>>   significant overhead (at least on arm64), it seemed better to keep it
>>   simple. Each hardening feature does have its own option and arch
>>   opt-in if needed (CONFIG_KPKEYS_HARDENED_PGTABLES,
>>   CONFIG_ARCH_HAS_KPKEYS_HARDENED_PGTABLES).
> There's so many pieces of data though/data structures! In this model,
> you'd have a separate switch for thousands of types of data! But I do
> think protecting PTs is the first step to a more complicated security
> monitor, since it allows you to have integrity for specific physical
> pages (or IPAs).

Agreed. I think this is good enough for kpkeys where we use roughly one
key per feature (meaning that the total number of features is pretty
limited), but this wouldn't scale if we had a framework to protect many
data types. In that case we'd need a different approach, probably
runtime-based. The advantage of having a CONFIG option per feature
though is that it incurs no overhead at all unless selected.

>>
>> Any comment or feedback will be highly appreciated, be it on the
>> high-level approach or implementation choices!
> Last note, I'd not totallllyyy trust the compiler to inline the
> functions.... I've met cases where functions on memory protections
> I expected to be inlined were not. I think __forceinline *may* work
> here, vs standard "static inline", but am not confident/sure.

That's a fair point, __always_inline could be used to make sure
set_pkey/restore_pkey_reg (and the helpers they call) are actually
inlined. I'll change that in v4. The guard object constructor/destructor
are defined as regular inline functions in <linux/cleanup.h> though, so
the inlining might not be complete.

> Hopefully the above is valuable at all. Thanks!

It is! Thank you for your thoughts and suggestions.

- Kevin


From vdonnefort at google.com  Thu Mar 13 04:40:35 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 11:40:35 +0000
Subject: [PATCH v4 0/3] Count pKVM stage-2 usage in secondary pagetable stat
Message-ID: <20250313114038.1502357-1-vdonnefort@google.com>

This series allows to count stage-2 related memory when using pKVM. The
value can be found in the /proc/meminfo field SecPageTables.

Changes since v3: https://lore.kernel.org/all/20250307113411.469018-1-vdonnefort at google.com/
  - Remove unnecessary void * cast (Marc)
  - Rename reclaim_guest_pages() -> reclaim_pgtable_pages() (Marc)
  - Remove unnecessary PAGE_ALIGN(pgd_sz)

Changes since v2: https://lore.kernel.org/all/20250304134347.369854-1-vdonnefort at google.com/
  - Pass a pointer to kvm_hyp_memcache instead of just the flags
    (Oliver)

Changes since v1: https://lore.kernel.org/all/20250228121355.1377891-1-vdonnefort at google.com/
  - Flags to kvm_hyp_memcache
  - Separate stage-2 memcache
  - Account for PGD

Vincent Donnefort (3):
  KVM: arm64: Add flags to kvm_hyp_memcache
  KVM: arm64: Distinct pKVM teardown memcache for stage-2
  KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats

 arch/arm64/include/asm/kvm_host.h             |  4 ++++
 arch/arm64/kvm/hyp/include/nvhe/mem_protect.h |  2 +-
 arch/arm64/kvm/hyp/nvhe/mem_protect.c         |  2 +-
 arch/arm64/kvm/hyp/nvhe/pkvm.c                |  8 +++----
 arch/arm64/kvm/mmu.c                          | 22 ++++++++++++++-----
 arch/arm64/kvm/pkvm.c                         |  5 +++++
 6 files changed, 32 insertions(+), 11 deletions(-)


base-commit: d082ecbc71e9e0bf49883ee4afd435a77a5101b6
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Thu Mar 13 04:40:36 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 11:40:36 +0000
Subject: [PATCH v4 1/3] KVM: arm64: Add flags to kvm_hyp_memcache
In-Reply-To: <20250313114038.1502357-1-vdonnefort@google.com>
References: <20250313114038.1502357-1-vdonnefort@google.com>
Message-ID: <20250313114038.1502357-2-vdonnefort@google.com>

Add flags to kvm_hyp_memcache and propagate the latter to the allocation
and free callbacks. This will later allow to account for memory, based
on the memcache configuration.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3a7ec98ef123..12691ae23d4c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,6 +86,7 @@ struct kvm_hyp_memcache {
 	phys_addr_t head;
 	unsigned long nr_pages;
 	struct pkvm_mapping *mapping; /* only used from EL1 */
+	unsigned long flags;
 };
 
 static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1f55b0c7b11d..6107a3c8ccf6 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1086,12 +1086,12 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
 	}
 }
 
-static void hyp_mc_free_fn(void *addr, void *unused)
+static void hyp_mc_free_fn(void *addr, void *mc)
 {
 	free_page((unsigned long)addr);
 }
 
-static void *hyp_mc_alloc_fn(void *unused)
+static void *hyp_mc_alloc_fn(void *mc)
 {
 	return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
 }
@@ -1102,7 +1102,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
 		return;
 
 	kfree(mc->mapping);
-	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
+	__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, mc);
 }
 
 int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
@@ -1117,7 +1117,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
 	}
 
 	return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
-				    kvm_host_pa, NULL);
+				    kvm_host_pa, mc);
 }
 
 /**
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From vdonnefort at google.com  Thu Mar 13 04:40:37 2025
From: vdonnefort at google.com (Vincent Donnefort)
Date: Thu, 13 Mar 2025 11:40:37 +0000
Subject: [PATCH v4 2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
In-Reply-To: <20250313114038.1502357-1-vdonnefort@google.com>
References: <20250313114038.1502357-1-vdonnefort@google.com>
Message-ID: <20250313114038.1502357-3-vdonnefort@google.com>

In order to account for memory dedicated to the stage-2 page-tables, use
a separated memcache when tearing down the VM. Meanwhile rename
reclaim_guest_pages to reflect the fact it only reclaim page-table
pages.

Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 12691ae23d4c..ace3969e8106 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -246,6 +246,7 @@ typedef unsigned int pkvm_handle_t;
 struct kvm_protected_vm {
 	pkvm_handle_t handle;
 	struct kvm_hyp_memcache teardown_mc;
+	struct kvm_hyp_memcache stage2_teardown_mc;
 	bool enabled;
 };
 
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 978f38c386ee..ea0a704da9b8 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -56,7 +56,7 @@ void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
 
 int hyp_pin_shared_mem(void *from, void *to);
 void hyp_unpin_shared_mem(void *from, void *to);
-void reclaim_guest_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc);
+void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc);
 int refill_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages,
 		    struct kvm_hyp_memcache *host_mc);
 
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 19c3c631708c..f34f11c720d7 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -266,7 +266,7 @@ int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
 	return 0;
 }
 
-void reclaim_guest_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
+void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
 {
 	struct hyp_page *page;
 	void *addr;
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 3927fe52a3dd..ac85bc51b8d3 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -678,7 +678,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
 
 int __pkvm_teardown_vm(pkvm_handle_t handle)
 {
-	struct kvm_hyp_memcache *mc;
+	struct kvm_hyp_memcache *mc, *stage2_mc;
 	struct pkvm_hyp_vm *hyp_vm;
 	struct kvm *host_kvm;
 	unsigned int idx;
@@ -706,10 +706,10 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 
 	/* Reclaim guest pages (including page-table pages) */
 	mc = &host_kvm->arch.pkvm.teardown_mc;
-	reclaim_guest_pages(hyp_vm, mc);
+	stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
+	reclaim_pgtable_pages(hyp_vm, stage2_mc);
 	unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->nr_vcpus);
 
-	/* Push the metadata pages to the teardown memcache */
 	for (idx = 0; idx < hyp_vm->nr_vcpus; ++idx) {
 		struct pkvm_hyp_vcpu *hyp_vcpu = hyp_vm->vcpus[idx];
 		struct kvm_hyp_memcache *vcpu_mc = &hyp_vcpu->vcpu.arch.pkvm_memcache;
@@ -717,7 +717,7 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 		while (vcpu_mc->nr_pages) {
 			void *addr = pop_hyp_memcache(vcpu_mc, hyp_phys_to_virt);
 
-			push_hyp_memcache(mc, addr, hyp_virt_to_phys);
+			push_hyp_memcache(stage2_mc, addr, hyp_virt_to_phys);
 			unmap_donated_memory_noclear(addr, PAGE_SIZE);
 		}
 
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..19921ca407c6 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -111,6 +111,7 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 
 	host_kvm->arch.pkvm.handle = 0;
 	free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
+	free_hyp_memcache(&host_kvm->arch.pkvm.stage2_teardown_mc);
 }
 
 /*
-- 
2.49.0.rc0.332.g42c0ae87b1-goog



From andriy.shevchenko at linux.intel.com  Thu Mar 13 05:34:24 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Thu, 13 Mar 2025 14:34:24 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <Z9LQ0O34EUM8WZku@smile.fi.intel.com>

On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
> The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
> help drivers avoid open-coding the for_each_node -loop for getting the
> channel IDs. The helper provides standard way to detect the ADC channel
> nodes (by the node name), and a standard way to convert the "reg"
> -properties to channel identification numbers, used in the struct
> iio_chan_spec. Furthermore, the helper can optionally check the found
> channel IDs are smaller than given maximum. This is useful for callers
> which later use the IDs for example for indexing a channel data array.
> 
> The original driver treated all found child nodes as channel nodes. The
> new helper requires channel nodes to be named channel[@N]. This should
> help avoid problems with devices which may contain also other but ADC
> child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
> string didn't reveal any in-tree .dts with channel nodes named
> otherwise. Also, same grep shows all the in-tree .dts seem to have
> channel IDs between 0..num of channels.
> 
> Use the new helper.

...

> +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
> +				&sun20i_gpadc_chan_template, -1, &channels);
> +	if (num_channels < 0)
> +		return num_channels;
> +
>  	if (num_channels == 0)
>  		return dev_err_probe(dev, -ENODEV, "no channel children\n");

Note, this what I would expected in your helper to see, i.e. separated cases
for < 0 (error code) and == 0, no channels.

Also, are all users going to have this check? Usually in other similar APIs
we return -ENOENT. And user won't need to have an additional check in case of
0 being considered as an error case too.




-- 
With Best Regards,
Andy Shevchenko




From andrew at lunn.ch  Thu Mar 13 05:47:19 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 13 Mar 2025 13:47:19 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571DF7CBA49AF626ABDA382C9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
 <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
 <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
 <BL3PR12MB6571DF7CBA49AF626ABDA382C9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <b2a65ad1-d4ca-4c0d-b59e-911b07f96554@lunn.ch>

On Thu, Mar 13, 2025 at 07:34:55AM +0000, Gupta, Suraj wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
> 
> > -----Original Message-----
> > From: Gupta, Suraj
> > Sent: Thursday, March 13, 2025 9:01 AM
> > To: Andrew Lunn <andrew at lunn.ch>; Russell King (Oracle)
> > <linux at armlinux.org.uk>
> > Cc: Pandey, Radhey Shyam <radhey.shyam.pandey at amd.com>;
> > andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> > kuba at kernel.org; pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > netdev at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org;
> > linux-arm-kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam,
> > Harini <harini.katakam at amd.com>
> > Subject: RE: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> > configuration.
> >
> >
> >
> > > -----Original Message-----
> > > From: Andrew Lunn <andrew at lunn.ch>
> > > Sent: Thursday, March 13, 2025 3:41 AM
> > > To: Russell King (Oracle) <linux at armlinux.org.uk>
> > > Cc: Gupta, Suraj <Suraj.Gupta2 at amd.com>; Pandey, Radhey Shyam
> > > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > linux-kernel at vger.kernel.org; linux-arm- kernel at lists.infradead.org;
> > > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > > <harini.katakam at amd.com>
> > > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > 2500base-X only configuration.
> > >
> > > Caution: This message originated from an External Source. Use proper
> > > caution when opening attachments, clicking links, or responding.
> > >
> > >
> > > > This is not an approach that works with the Linux kernel, sorry.
> > > >
> > > > What we have today is a driver that works for people's hardware -
> > > > and we don't know what the capabilities of that hardware is.
> > > >
> > > > If there's hardware out there today which has XAE_ABILITY_2_5G set,
> > > > but defaults to <=1G mode, this will work with the current driver.
> > > > However, with your patch applied, it stops working because instead
> > > > of the driver indicating MAC_10FD | MAC_100FD | MAC_1000FD, it only
> > > > indicates MAC_2500FD. If this happens, it will regress users setups,
> > > > and that is something we try not to do.
> > > >
> > > > Saying "someone else needs to add the code for their FPGA logic"
> > > > misses the point - there may not be "someone else" to do that, which
> > > > means the only option is to revert your change if it were merged.
> > > > That in itself can cause its own user regressions because obviously
> > > > stuff that works with this patch stops working.
> > > >
> > > > This is why we're being cautious, and given your responses, it's not
> > > > making Andrew or myself feel that there's a reasonable approach
> > > > being taken here.
> > > >
> > > > >From everything you have said, I am getting the feeling that using
> > > > XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is just
> > > > wrong. Given that we're talking about an implementation that has
> > > > been synthesized at 2.5G and can't operate slower, maybe there's
> > > > some way that could be created to specify that in DT?
> > > >
> > > > e.g. (and I'm sure the DT folk aren't going to like it)...
> > > >
> > > >       xlnx,axi-ethernet-X.YY.Z-2.5G
> > > >
> > > > (where X.YY.Z is the version) for implementations that can _only_ do
> > > > 2.5G, and leave all other implementations only doing 1G and below.
> > > >
> > > > Or maybe some DT property. Or something else.
> > >
> > > Given that AMD has been talking about an FPGA, not silicon, i actually
> > > think it would be best to change the IP to explicitly enumerate how it
> > > has been synthesised. Make use of some register bits which currently
> > > read as 0. Current IP would then remain as 1000BaseX/SGMII,
> > > independent of how they have been synthesised. Newer versions of the
> > > IP will then set the bits if they have been synthesised as 2) or 3),
> > > and the driver can then enable that capability, without breaking
> > > current generation systems. Plus there needs to be big fat warning for
> > > anybody upgrading to the latest version of the IP for bug fixes to ensure they
> > correctly set the synthesis options because it now actually matters.
> > >
> > >          Andrew
> >
> > Synthesis options I mentioned in comment might sound confusing, let me clear it up.
> > Actual synthesis options (as seen from configuration UI) IP provides are (1) and (2).
> > When a user selects (2), IP comes with default 2.5G but also contains 1G
> > capabilities which can be enabled and work with by adding switching FPGA logic
> > (that makes it (3)).
> >
> > So, in short  if a user selects (1): It's <=1G only.
> > If it selects (2): It's 2.5G only but can be made (3) by FPGA logic changes. So
> > whatever existing systems for (3) would be working at default (2).
> >
> > This is the reason we didn't described (3) in V1 series as that is not provided by IP
> > but can be synthesized after FPGA changes.
> > Hope I'm able to answer your questions.
> >
> 
> I understand your concerns that current solution might break if any existing system uses (3).
> 
> Russel's suggestion to use DT compatible we can try to send as RFC and check if that is accepted by DT maintainers.
> Andrew's suggestion is complete IP solution and will involve IP changes to correct ability register behaviour based on synthesis time selection in a new IP version. But this will need internal discussions and IP rework and might take few months.
> 
> Please let me know your thoughts on it.

Given your comment:

> It's 2.5G only but can be made (3) by FPGA logic changes

It sounds like the design is not ideal at the moment, and you will be
making changes anyway to clean this up. Being fixed in 2.5G mode is
not nice, you need a PHY doing rate adaptation in order to support the
slower speeds.

You should also be thinking forwards. If you add support for fixed
2.5G now, can you cleanly integrate switching between 1000BaseX/SGMII
and 2500BaseX in the future without breaking existing systems? You
probably at least need a paper design of how this will work, so you
can say you have thought through all the user cases: New IP old
driver, Old IP new driver, etc...

	Andrew


From nbd at nbd.name  Thu Mar 13 05:47:16 2025
From: nbd at nbd.name (Felix Fietkau)
Date: Thu, 13 Mar 2025 13:47:16 +0100
Subject: [PATCH v1] mt76: mt7915: wed: find rx token by physical address
In-Reply-To: <TYCPR01MB843770121E6576BB3807CD0A98D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>
References: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <TYCPR01MB843726907C170CFE2D3EB7BE98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <e144d2ffe9924d81a7b60f38cdcf516a@realtek.com>
 <1c46870f-965b-4f70-a01b-adbcd60c2876@nbd.name>
 <TYCPR01MB843770121E6576BB3807CD0A98D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>
Message-ID: <0ab3fb92-b529-46a3-bc78-230eaf4ae805@nbd.name>

On 13.03.25 13:43, Shengyu Qu wrote:
> Hi Felix,
> 
> I'm not sure about the token ID incorrect frequency, this is just a port
> of downstream patch, sorry.

Can you reproduce the issue that the downstream patch supposedly fixes?
If so, you could add some printk to check how frequently it occurs.

- Felix


From nfraprado at collabora.com  Thu Mar 13 05:49:26 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Thu, 13 Mar 2025 09:49:26 -0300
Subject: [PATCH v3] arm64: defconfig: mediatek: enable PHY drivers
In-Reply-To: <20250313040855.62259-1-vignesh.raman@collabora.com>
References: <20250313040855.62259-1-vignesh.raman@collabora.com>
Message-ID: <986ad850-3e7c-43f4-84f0-cbce888676fe@notapiano>

On Thu, Mar 13, 2025 at 09:38:24AM +0530, Vignesh Raman wrote:
> The mediatek display driver fails to probe on mt8173-elm-hana and
> mt8183-kukui-jacuzzi-juniper-sku16 in v6.14-rc4 due to missing PHY
> configurations.
> 
> Commit [1] stopped selecting the MediaTek PHY drivers, requiring them
> to be explicitly enabled in defconfig.
> 
> Enable the following PHY drivers for MediaTek platforms:
> - CONFIG_PHY_MTK_HDMI=m for HDMI display
> - CONFIG_PHY_MTK_MIPI_DSI=m for DSI display
> - CONFIG_PHY_MTK_DP=m for DP display
> 
> [1] commit 924d66011f24 ("drm/mediatek: stop selecting foreign drivers")

Usually this would go directly in the paragraph, like so:

  Commit 924d66011f24 ("drm/mediatek: stop selecting foreign drivers") stopped
  selecting the MediaTek PHY drivers, requiring them to be explicitly enabled in
  defconfig.

But that's just so you know in the future, you don't need to send a new version
just for that.

> 
> Fixes: 924d66011f24 ("drm/mediatek: stop selecting foreign drivers")
> Signed-off-by: Vignesh Raman <vignesh.raman at collabora.com>

Reviewed-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Thanks,
N?colas


From florin.leotescu at oss.nxp.com  Thu Mar 13 05:57:45 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Thu, 13 Mar 2025 14:57:45 +0200
Subject: [PATCH v4 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250313125746.2901904-3-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce OF support for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
---
 drivers/hwmon/emc2305.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 4d39fbd83769..f8a4c76fcadd 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -607,9 +607,16 @@ static void emc2305_remove(struct i2c_client *client)
 		emc2305_unset_tz(dev);
 }
 
+static const struct of_device_id of_emc2305_match_table[] = {
+	{ .compatible = "microchip,emc2305", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
+
 static struct i2c_driver emc2305_driver = {
 	.driver = {
 		.name = "emc2305",
+		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
 	.remove	  = emc2305_remove,
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Thu Mar 13 05:57:46 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Thu, 13 Mar 2025 14:57:46 +0200
Subject: [PATCH v4 3/3] hwmon: emc2305: Use devm_thermal_of_cooling_device_register
In-Reply-To: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250313125746.2901904-4-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Prepare the emc2305 driver to use configuration from Device Tree nodes.
Switch to devm_thermal_of_cooling_device_register to simplify the
cleanup procedure, allowing the removal of emc2305_unset_tz and
emc2305_remove, which are no longer needed.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/hwmon/emc2305.c | 33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index f8a4c76fcadd..234c54956a4b 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
 	"emc2305_fan5",
 };
 
-static void emc2305_unset_tz(struct device *dev);
-
 static int emc2305_get_max_channel(const struct emc2305_data *data)
 {
 	return data->pwm_num;
@@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
 	pwm = data->pwm_min[cdev_idx];
 
 	data->cdev_data[cdev_idx].cdev =
-		thermal_cooling_device_register(emc2305_fan_name[idx], data,
-						&emc2305_cooling_ops);
+		devm_thermal_of_cooling_device_register(dev, dev->of_node,
+							emc2305_fan_name[idx], data,
+							&emc2305_cooling_ops);
 
 	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
 		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
@@ -332,24 +331,9 @@ static int emc2305_set_tz(struct device *dev)
 	for (i = 0; i < data->pwm_num; i++) {
 		ret = emc2305_set_single_tz(dev, i + 1);
 		if (ret)
-			goto thermal_cooling_device_register_fail;
+			return ret;
 	}
 	return 0;
-
-thermal_cooling_device_register_fail:
-	emc2305_unset_tz(dev);
-	return ret;
-}
-
-static void emc2305_unset_tz(struct device *dev)
-{
-	struct emc2305_data *data = dev_get_drvdata(dev);
-	int i;
-
-	/* Unregister cooling device. */
-	for (i = 0; i < EMC2305_PWM_MAX; i++)
-		if (data->cdev_data[i].cdev)
-			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
 }
 
 static umode_t
@@ -599,14 +583,6 @@ static int emc2305_probe(struct i2c_client *client)
 	return 0;
 }
 
-static void emc2305_remove(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-
-	if (IS_REACHABLE(CONFIG_THERMAL))
-		emc2305_unset_tz(dev);
-}
-
 static const struct of_device_id of_emc2305_match_table[] = {
 	{ .compatible = "microchip,emc2305", },
 	{},
@@ -619,7 +595,6 @@ static struct i2c_driver emc2305_driver = {
 		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
-	.remove	  = emc2305_remove,
 	.id_table = emc2305_ids,
 };
 
-- 
2.34.1



From andrew at lunn.ch  Thu Mar 13 05:54:57 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 13 Mar 2025 13:54:57 +0100
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
References: <ad1e81b5-1596-4d94-a0fa-1828d667b7a2@lunn.ch>
 <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
 <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
 <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
Message-ID: <468deb47-1837-4709-84e5-b14bf0e8c2a5@lunn.ch>

> Synthesis options I mentioned in comment might sound confusing, let me clear it up.
> Actual synthesis options (as seen from configuration UI) IP provides are (1) and (2). When a user selects (2), IP comes with default 2.5G but also contains 1G capabilities which can be enabled and work with by adding switching FPGA logic (that makes it (3)).
> 
> So, in short  if a user selects (1): It's <=1G only.
> If it selects (2): It's 2.5G only but can be made (3) by FPGA logic changes. So whatever existing systems for (3) would be working at default (2).
> 
> This is the reason we didn't described (3) in V1 series as that is not provided by IP but can be synthesized after FPGA changes.

This whole discussion would of been much easier and wasted a lot less
time if you had given us accurate information right from the start....

So 3) does not exist at the moment, because if it did, the customer
doing it would need to make proprietary changes, both to the licensed
IP and the driver. We have not seen such driver patch submissions...

    Andrew

---
pw-bot: cr


From wiagn233 at outlook.com  Thu Mar 13 05:43:18 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Thu, 13 Mar 2025 20:43:18 +0800
Subject: [PATCH v1] mt76: mt7915: wed: find rx token by physical address
In-Reply-To: <1c46870f-965b-4f70-a01b-adbcd60c2876@nbd.name>
References: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <TYCPR01MB843726907C170CFE2D3EB7BE98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <e144d2ffe9924d81a7b60f38cdcf516a@realtek.com>
 <1c46870f-965b-4f70-a01b-adbcd60c2876@nbd.name>
Message-ID: <TYCPR01MB843770121E6576BB3807CD0A98D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Hi Felix,

I'm not sure about the token ID incorrect frequency, this is just a port
of downstream patch, sorry.

Best regards,
Shengyu

? 2025/3/12 17:09, Felix Fietkau ??:
> On 12.03.25 02:41, Ping-Ke Shih wrote:
>> Shengyu Qu <wiagn233 at outlook.com> wrote:
>>>
>>> Hi Shih,
>>>
>>> Can you also give this patch a review? Seems I also need to convert to
>>> reverse Xmas tree order for this patch, will do it in next version.
>>
>> Yes. Please do it.
>>
>>>
>>> Best regards,
>>> Shengyu
>>>
>>> ? 2025/2/22 19:38, Shengyu Qu ??:
>>> > The token id in RxDMAD may be incorrect when it is not the last frame
>>> > due to WED HW bug. Lookup correct token id by physical address in 
>>> sdp0.
>>> >
>>> > Downstream patch link:
>>> https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt- 
>>> feeds/+/737340322ab22b138fd200e02
>>> 0d61ffdbe3e36a9/autobuild/autobuild_5.4_mac80211_release/ 
>>> mt7988_wifi7_mac80211_mlo/package/kernel/mt76
>>> /patches/0062-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
>>> >
>>> > Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
>>> > Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
>>> > ---
>>> >?? drivers/net/wireless/mediatek/mt76/dma.c | 25 +++++++++++++++++++ 
>>> ++++-
>>> >?? 1 file changed, 24 insertions(+), 1 deletion(-)
>>> >
>>> > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/ 
>>> net/wireless/mediatek/mt76/dma.c
>>> > index 844af16ee551..5bf63014263c 100644
>>> > --- a/drivers/net/wireless/mediatek/mt76/dma.c
>>> > +++ b/drivers/net/wireless/mediatek/mt76/dma.c
>>> > @@ -444,9 +444,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct 
>>> mt76_queue *q, int idx,
>>> >?????? mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
>>> >
>>> >?????? if (mt76_queue_is_wed_rx(q)) {
>>> > +??????? u32 id, find = 0;
>>> >?????????? u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
>>> > -??????? struct mt76_txwi_cache *t = mt76_rx_token_release(dev, 
>>> token);
>>> > +??????? struct mt76_txwi_cache *t;
>>> > +
>>> > +??????? if (*more) {
>>
>> Because of scope, should define 'find' (or 'found'?) as bool here.
>>
>>> > +??????????? spin_lock_bh(&dev->rx_token_lock);
>>> > +
>>> > +??????????? idr_for_each_entry(&dev->rx_token, t, id) {
>>
>> idr_find() can only get a pointer associated with the ID. Not sure if 
>> it can
>> have a reverse way -- get ID from pointer. With sequential search in 
>> data path,
>> cost is higher.
>>
>> Maybe you can consider to build association between argument 'idx' and
>> pointer/token by another patch.
>>
>> But logic is okay to me.
> 
> Adding to that, it matters how frequently the token ID is incorrect. If 
> the token ID is correct most of the time, then it's worth optimizing for 
> that as the default case. In that case you should avoid the extra idr 
> scan if the pointer for the provided token id already matches.
> 
> - Felix

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/69c28795/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/69c28795/attachment.sig>

From amadeus at jmu.edu.cn  Thu Mar 13 06:01:18 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 13 Mar 2025 21:01:18 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <22d849c3-8a0d-4704-b69c-8019c7f70ca7@kwiboo.se>
References: <22d849c3-8a0d-4704-b69c-8019c7f70ca7@kwiboo.se>
Message-ID: <20250313130118.2772992-1-amadeus@jmu.edu.cn>

Hi,

> Interesting, good that it works with the updated U-Boot. Main change
> compared to v1 is that it now use clock/reset id and DT closer to what
> has been merged in mainline Linux. It also has DT params to help
> initialize the two pwm regulators used by these boards.
>
> I will try with the old v1 U-Boot series and see if I can replicated
> your issue.

It is easy to reproduce this issue.
Make the following changes in the new series of u-boot:

```
--- a/configs/radxa-e20c-rk3528_defconfig
+++ b/configs/radxa-e20c-rk3528_defconfig
@@ -47,9 +47,7 @@ CONFIG_DM_MDIO=y
 CONFIG_DWC_ETH_QOS=y
 CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
-CONFIG_REGULATOR_PWM=y
 CONFIG_DM_REGULATOR_GPIO=y
-CONFIG_PWM_ROCKCHIP=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550_MEM32=y
```

Or change dts:
```
--- a/arch/arm/dts/rk3528-radxa-e20c-u-boot.dtsi
+++ b/arch/arm/dts/rk3528-radxa-e20c-u-boot.dtsi
@@ -8,9 +8,9 @@
 };
 
 &vdd_arm {
-	regulator-init-microvolt = <953000>;
+	status = "disabled";
 };
 
 &vdd_logic {
-	regulator-init-microvolt = <900000>;
+	status = "disabled";
 };
```

Then the kernel will hang when loading the gpio driver:

[    0.162618] gpio gpiochip2: Static allocation of GPIO bae is deprecated, use dynamic allocation.
[    0.163558] rockchip-gpio ffb00000.gpio: probed /soc/pinctrl/gpio at ffb00000
[    0.164322] gpio gpiochip3: Static allocation of GPIO base is deprecated, use dynamic allocation.
[    0.165231] rockchip-gpio ffb10000.gpio: probed /soc/pinctrl/gpio at ffb10000
[    0.165977] gpio gpiochip4: Static allocation of GPIO base is deprecated, use dynamic allocation.
[    0.166886] rockhip-gpio ffb20000.gpio: probed /soc/pinctrl/gpio at ffb20000
[    0.170342] Internal error: Oos - Undefined instruction: 0000000002000000 [#1] SMP

Changing the debug level:
[    0.175260] rockchip-pinctrl soc:pinctrl: setting mux of GPIO4-14 to 0
[    0.175356] rockchip-pinctrl soc:pinctrl: setting mux of GPIO4-20 to 1
[    0.175968] rockchip-pinctrl soc:pinctrl: setting mux of GPIO4-14 to 0
[    0.176849] rockchip-pinctrl soc:pinctrl: setting mux of GPIO4-21 to 1
[    0.178453] rockchip-pinctrl soc:pinctrl: setting mux of GPIO4-13 to 0
(hang)

Thanks,
Chukun

--
2.25.1



From florin.leotescu at oss.nxp.com  Thu Mar 13 05:57:44 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Thu, 13 Mar 2025 14:57:44 +0200
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce yaml schema for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
---
 .../bindings/hwmon/microchip,emc2305.yaml     | 104 ++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
new file mode 100644
index 000000000000..3107fcafcf6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip EMC2305 SMBus compliant PWM fan controller
+
+maintainers:
+  - Michael Shych <michaelsh at nvidia.com>
+
+description:
+  Microchip EMC2301/2/3/5 pwm controller which supports
+  up to five programmable fan control circuits.
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - microchip,emc2305
+      - items:
+          - enum:
+              - microchip,emc2303
+              - microchip,emc2302
+              - microchip,emc2301
+          - const: microchip,emc2305
+
+  reg:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  '#pwm-cells':
+    const: 2
+
+patternProperties:
+  "^fan@[0-4]$":
+    $ref: fan-common.yaml#
+    unevaluatedProperties: false
+    properties:
+      reg:
+        description:
+          The fan number.
+
+    required:
+      - reg
+      - pwms
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        fan_controller: fan-controller at 2f {
+            compatible = "microchip,emc2305";
+            reg = <0x2f>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            #pwm-cells = <2>;
+
+            fan at 0 {
+                #cooling-cells = <2>;
+                reg = <0x0>;
+                pwms = <&fan_controller 1 1>;
+            };
+
+            fan at 1 {
+                #cooling-cells = <2>;
+                reg = <0x1>;
+                pwms = <&fan_controller 1 1>;
+            };
+
+            fan at 2 {
+                #cooling-cells = <2>;
+                reg = <0x2>;
+                pwms = <&fan_controller 1 1>;
+            };
+
+            fan at 3 {
+                #cooling-cells = <2>;
+                reg = <0x3>;
+                pwms = <&fan_controller 1 1>;
+            };
+
+            fan at 4 {
+                #cooling-cells = <2>;
+                reg = <0x4>;
+                pwms = <&fan_controller 1 1>;
+            };
+        };
+    };
+...
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Thu Mar 13 05:57:43 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Thu, 13 Mar 2025 14:57:43 +0200
Subject: [PATCH v4 0/3] Add OF support for Microchip emc2305 fan controller
Message-ID: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

This patch series add initial OF support for Microchip emc2305 fan controller.

Changes since v3:
- Removed thermal_cooling_device_register_fail label since is no longer needed
  and replaced goto with imediate return, as recommended by Guenter Roeck. 
- Redefined compatible property in dt-binding, as recommended by Frank Li.
- Updated driver of compatible list.
- Renamed node name in the dt-binding example, as recommended by Connor Dooley.
- Corrected dt-binding commit subject.
- Added dt-binding fan descriptions and $ref to fan schema, 
  as Connor Dooley & Krzysztof Kozlowski recommended.
  Used similar as on maxim,max6639 and nuvoton,nct7363. 
- Updated dt-binding example.

Changes since v2:
- Removed the introduction of new properties for now and we only 
  enable basic OF support.
- Link to previous version: 
  https://lore.kernel.org/linux-arm-kernel/20250219133221.2641041-3-florin.leotescu at oss.nxp.com/T/

Florin Leotescu (3):
  dt-bindings: hwmon: Add Microchip emc2305 support
  hwmon: emc2305: Add OF support
  hwmon: emc2305: Use devm_thermal_of_cooling_device_register

 .../bindings/hwmon/microchip,emc2305.yaml     | 104 ++++++++++++++++++
 drivers/hwmon/emc2305.c                       |  38 ++-----
 2 files changed, 114 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

-- 
2.34.1



From robin.murphy at arm.com  Thu Mar 13 06:06:59 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 13:06:59 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
 <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
 <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
 <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
Message-ID: <016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>

On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
> On 13.03.2025 12:01, Robin Murphy wrote:
>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>> [...]
>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my tests I
>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>> relevant kernel log:
>>
>> ...and the bug-flushing-out begins!
>>
>>> Unable to handle kernel NULL pointer dereference at virtual address
>>> 00000000000003e8
>>> Mem abort info:
>>>  ? ? ESR = 0x0000000096000004
>>>  ? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>  ? ? SET = 0, FnV = 0
>>>  ? ? EA = 0, S1PTW = 0
>>>  ? ? FSC = 0x04: level 0 translation fault
>>> Data abort info:
>>>  ? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>  ? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>  ? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>> [00000000000003e8] user address but active_mm is swapper
>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>> Modules linked in:
>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>> pc : devm_kmalloc+0x2c/0x114
>>> lr : rk_iommu_of_xlate+0x30/0x90
>>> ...
>>> Call trace:
>>>  ? ?devm_kmalloc+0x2c/0x114 (P)
>>>  ? ?rk_iommu_of_xlate+0x30/0x90
>>
>> Yeah, looks like this is doing something a bit questionable which can't
>> work properly. TBH the whole dma_dev thing could probably be cleaned up
>> now that we have proper instances, but for now does this work?
> 
> Yes, this patch fixes the problem I've observed.
> 
> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
> 
> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver and
> I doubt it can be cleaned up.

On the contrary I suspect they both can - it all dates back to when we 
had the single global platform bus iommu_ops and the SoC drivers were 
forced to bodge their own notion of multiple instances, but with the 
modern core code, ops are always called via a valid IOMMU instance or 
domain, so in principle it should always be possible to get at an 
appropriate IOMMU device now. IIRC it was mostly about allocating and 
DMA-mapping the pagetables in domain_alloc, where the private notion of 
instances didn't have enough information, but domain_alloc_paging solves 
that.

Cheers,
Robin.


From wiagn233 at outlook.com  Thu Mar 13 06:11:54 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Thu, 13 Mar 2025 21:11:54 +0800
Subject: [PATCH v2] mt76: mt7915: wed: find rx token by physical address
Message-ID: <TYCPR01MB843753CE1DBAF4FAEF76B17698D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The token id in RxDMAD may be incorrect when it is not the last frame
due to WED HW bug. Lookup correct token id by physical address in sdp0.

Downstream patch link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/737340322ab22b138fd200e020d61ffdbe3e36a9/autobuild/autobuild_5.4_mac80211_release/mt7988_wifi7_mac80211_mlo/package/kernel/mt76/patches/0062-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch

Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
Changes since v1:
 - Reordered code sequence to reversed Xmas tree order
 - Renamed some variables
---
 drivers/net/wireless/mediatek/mt76/dma.c | 26 +++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 844af16ee5513..25893686cbe85 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -445,8 +445,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
 
 	if (mt76_queue_is_wed_rx(q)) {
 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
-		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
+		struct mt76_txwi_cache *t;
+		bool found = false;
+		u32 id;
+
+		if (*more) {
+			spin_lock_bh(&dev->rx_token_lock);
+
+			idr_for_each_entry(&dev->rx_token, t, id) {
+				if (t->dma_addr == le32_to_cpu(desc->buf0)) {
+					token = id;
+					found = 1;
+
+					/* Write correct id back to DMA*/
+					u32p_replace_bits(&buf1, id,
+							  MT_DMA_CTL_TOKEN);
+					WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+					break;
+				}
+			}
+
+			spin_unlock_bh(&dev->rx_token_lock);
+			if (!found)
+				return NULL;
+		}
 
+		t = mt76_rx_token_release(dev, token);
 		if (!t)
 			return NULL;
 
-- 
2.48.1



From maz at kernel.org  Thu Mar 13 06:13:24 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 13:13:24 +0000
Subject: [PATCH v4 0/3] Count pKVM stage-2 usage in secondary pagetable stat
In-Reply-To: <20250313114038.1502357-1-vdonnefort@google.com>
References: <20250313114038.1502357-1-vdonnefort@google.com>
Message-ID: <86jz8tnkej.wl-maz@kernel.org>

On Thu, 13 Mar 2025 11:40:35 +0000,
Vincent Donnefort <vdonnefort at google.com> wrote:
> 
> This series allows to count stage-2 related memory when using pKVM. The
> value can be found in the /proc/meminfo field SecPageTables.
> 
> Changes since v3: https://lore.kernel.org/all/20250307113411.469018-1-vdonnefort at google.com/
>   - Remove unnecessary void * cast (Marc)
>   - Rename reclaim_guest_pages() -> reclaim_pgtable_pages() (Marc)
>   - Remove unnecessary PAGE_ALIGN(pgd_sz)
> 
> Changes since v2: https://lore.kernel.org/all/20250304134347.369854-1-vdonnefort at google.com/
>   - Pass a pointer to kvm_hyp_memcache instead of just the flags
>     (Oliver)
> 
> Changes since v1: https://lore.kernel.org/all/20250228121355.1377891-1-vdonnefort at google.com/
>   - Flags to kvm_hyp_memcache
>   - Separate stage-2 memcache
>   - Account for PGD
> 
> Vincent Donnefort (3):
>   KVM: arm64: Add flags to kvm_hyp_memcache
>   KVM: arm64: Distinct pKVM teardown memcache for stage-2
>   KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats
> 
>  arch/arm64/include/asm/kvm_host.h             |  4 ++++
>  arch/arm64/kvm/hyp/include/nvhe/mem_protect.h |  2 +-
>  arch/arm64/kvm/hyp/nvhe/mem_protect.c         |  2 +-
>  arch/arm64/kvm/hyp/nvhe/pkvm.c                |  8 +++----
>  arch/arm64/kvm/mmu.c                          | 22 ++++++++++++++-----
>  arch/arm64/kvm/pkvm.c                         |  5 +++++
>  6 files changed, 32 insertions(+), 11 deletions(-)

Acked-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From linux at treblig.org  Thu Mar 13 06:21:05 2025
From: linux at treblig.org (Dr. David Alan Gilbert)
Date: Thu, 13 Mar 2025 13:21:05 +0000
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <3f9dbb7b-6527-48e1-9028-b46e5a0c58ce@csgroup.eu>
References: <20241115152055.279732-1-linux@treblig.org>
 <3f9dbb7b-6527-48e1-9028-b46e5a0c58ce@csgroup.eu>
Message-ID: <Z9LbwRUsHwFLpBZA@gallifrey>

* Christophe Leroy (christophe.leroy at csgroup.eu) wrote:
> 
> 
> Le 15/11/2024 ? 16:20, linux at treblig.org a ?crit?:
> > [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> > 
> > From: "Dr. David Alan Gilbert" <linux at treblig.org>
> > 
> > fsl_mc_allocator_driver_exit() was added explicitly by
> > commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> > but was never used.
> > 
> > Remove it.
> > 
> > fsl_mc_portal_reset() was added in 2015 by
> > commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> > but was never used.
> > 
> > Remove it.
> > 
> > fsl_mc_portal_reset() was the only caller of dpmcp_reset().
> > 
> > Remove it.
> > 
> > Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>
> 
> Acked-by: Christophe Leroy <christophe.leroy at csgroup.eu>

Hi,
  Can someone pick this old change up please?  I see the PPC patchwork says
  'handled elsewhere' but doesn't say where.

Thanks,

Dave
> 
> > ---
> >   drivers/bus/fsl-mc/dpmcp.c            | 22 ----------------------
> >   drivers/bus/fsl-mc/fsl-mc-allocator.c |  5 -----
> >   drivers/bus/fsl-mc/fsl-mc-private.h   |  6 ------
> >   drivers/bus/fsl-mc/mc-io.c            | 20 --------------------
> >   include/linux/fsl/mc.h                |  2 --
> >   5 files changed, 55 deletions(-)
> > 
> > diff --git a/drivers/bus/fsl-mc/dpmcp.c b/drivers/bus/fsl-mc/dpmcp.c
> > index 5fbd0dbde24a..7816c0a728ef 100644
> > --- a/drivers/bus/fsl-mc/dpmcp.c
> > +++ b/drivers/bus/fsl-mc/dpmcp.c
> > @@ -75,25 +75,3 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
> >          /* send command to mc*/
> >          return mc_send_command(mc_io, &cmd);
> >   }
> > -
> > -/**
> > - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
> > - * @mc_io:     Pointer to MC portal's I/O object
> > - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
> > - * @token:     Token of DPMCP object
> > - *
> > - * Return:     '0' on Success; Error code otherwise.
> > - */
> > -int dpmcp_reset(struct fsl_mc_io *mc_io,
> > -               u32 cmd_flags,
> > -               u16 token)
> > -{
> > -       struct fsl_mc_command cmd = { 0 };
> > -
> > -       /* prepare command */
> > -       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
> > -                                         cmd_flags, token);
> > -
> > -       /* send command to mc*/
> > -       return mc_send_command(mc_io, &cmd);
> > -}
> > diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
> > index b5e8c021fa1f..6c3beb82dd1b 100644
> > --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
> > +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
> > @@ -656,8 +656,3 @@ int __init fsl_mc_allocator_driver_init(void)
> >   {
> >          return fsl_mc_driver_register(&fsl_mc_allocator_driver);
> >   }
> > -
> > -void fsl_mc_allocator_driver_exit(void)
> > -{
> > -       fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
> > -}
> > diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
> > index b3520ea1b9f4..e1b7ec3ed1a7 100644
> > --- a/drivers/bus/fsl-mc/fsl-mc-private.h
> > +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
> > @@ -66,10 +66,6 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
> >                  u32 cmd_flags,
> >                  u16 token);
> > 
> > -int dpmcp_reset(struct fsl_mc_io *mc_io,
> > -               u32 cmd_flags,
> > -               u16 token);
> > -
> >   /*
> >    * Data Path Resource Container (DPRC) API
> >    */
> > @@ -631,8 +627,6 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
> > 
> >   int __init fsl_mc_allocator_driver_init(void);
> > 
> > -void fsl_mc_allocator_driver_exit(void);
> > -
> >   void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
> > 
> >   void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
> > diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
> > index 95b10a6cf307..a0ad7866cbfc 100644
> > --- a/drivers/bus/fsl-mc/mc-io.c
> > +++ b/drivers/bus/fsl-mc/mc-io.c
> > @@ -263,23 +263,3 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
> >          dpmcp_dev->consumer_link = NULL;
> >   }
> >   EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
> > -
> > -/**
> > - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
> > - *
> > - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
> > - */
> > -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
> > -{
> > -       int error;
> > -       struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
> > -
> > -       error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
> > -       if (error < 0) {
> > -               dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
> > -               return error;
> > -       }
> > -
> > -       return 0;
> > -}
> > -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
> > diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
> > index c90ec889bfc2..37316a58d2ed 100644
> > --- a/include/linux/fsl/mc.h
> > +++ b/include/linux/fsl/mc.h
> > @@ -417,8 +417,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
> > 
> >   void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
> > 
> > -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
> > -
> >   int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
> >                                          enum fsl_mc_pool_type pool_type,
> >                                          struct fsl_mc_device **new_mc_adev);
> > --
> > 2.47.0
> > 
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


From lee at kernel.org  Thu Mar 13 06:21:36 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 13:21:36 +0000
Subject: [PATCH v6 00/10] mfd: bcm590xx: Add support for BCM59054
In-Reply-To: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
Message-ID: <20250313132136.GC3616286@google.com>

On Tue, 04 Mar 2025, Artur Weber wrote:

> Add support for the BCM59054 MFD to the bcm590xx driver and fix a
> couple of small bugs in it that also affected the already supported
> BCM59056.
> 
> While we're at it - convert the devicetree bindings to YAML format
> and drop the bcm59056 DTS in favor of describing the PMU in users'
> DTS files, as is done for most other MFDs.
> 
> The BCM59054 is fairly similar to the BCM59056, with the primary
> difference being the different number and layout of regulators.
> It is primarily used in devices using the BCM21664 and BCM23550
> chipsets.
> 
> This patchset has been tested on a Samsung Galaxy Grand Neo
> (baffinlite rev02; DTS not in mainline yet) with a BCM59054 PMIC.
> Testing on a BCM59056 would be appreciated.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---
> Changes in v6:
> - Rename mfd/brcm,bcm590xx.yaml to mfd/brcm,bcm59056.yaml again
> - Use PMU ID value as device type
> - Rename rev_dig and rev_ana to rev_digital and rev_analog
> - Link to v5: https://lore.kernel.org/r/20250221-bcm59054-v5-0-065f516a9042 at gmail.com
> 
> Changes in v5:
> - Make regulator binding descriptions reference mfd/brcm,bcm590xx.yaml
>   instead of mfd/brcm,bcm59056.yaml
> - Move regmap type enum to common MFD header
> - Link to v4: https://lore.kernel.org/r/20250215-bcm59054-v4-0-dbfb2d76a855 at gmail.com
> 
> Changes in v4:
> - Fix yamllint warnings in DT bindings
> - Address miscelaneous review comments related to DT bindings
>   - Note that I did not end up moving the regulator refs from
>     allOf compatible matches; I explained my reasoning in [1].
>     [1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/
> - Add PMU ID/revision parsing to MFD driver
> - Fix instances of regulator data not matching vendor kernel for
>   BCM59054
> - Use different voltage table for BCM59054 VSR reg based on PMU
>   revision
> - Link to v3: https://lore.kernel.org/r/20250131-bcm59054-v3-0-bbac52a84787 at gmail.com
> 
> Changes in v3:
> - Split out regulator DT bindings into separate YAML
> - Use tables of regulator info instead of get_XXX_register, reg_is_XXX
>   functions
> - Drop "regulator: bcm590xx: Add proper handling for PMMODE registers";
>   it adds unnecessary noise to the series and will be submitted separately
> - Link to v2: https://lore.kernel.org/r/20231030-bcm59054-v2-0-5fa4011aa5ba at gmail.com
> 
> Changes in v2:
> - Fixed BCM59054 ID being passed to BCM59056 function in the
>   regulator driver
> - Dropped linux-rpi-kernel from the CC list
> - Link to v1: https://lore.kernel.org/r/20231030-bcm59054-v1-0-3517f980c1e3 at gmail.com
> 
> ---
> Artur Weber (10):
>       dt-bindings: mfd: brcm,bcm59056: Convert to YAML
>       dt-bindings: mfd: brcm,bcm59056: Add compatible for BCM59054
>       ARM: dts: Drop DTS for BCM59056 PMU
>       mfd: bcm590xx: Drop unused "id" member of bcm590xx MFD struct
>       mfd: bcm590xx: Add support for multiple device types + BCM59054 compatible
>       mfd: bcm590xx: Add PMU ID/revision parsing function
>       regulator: bcm590xx: Use dev_err_probe for regulator register error
>       regulator: bcm590xx: Store regulator descriptions in table
>       regulator: bcm590xx: Rename BCM59056-specific data as such
>       regulator: bcm590xx: Add support for BCM59054 regulators
> 
>  .../devicetree/bindings/mfd/brcm,bcm59056.txt      |   39 -
>  .../devicetree/bindings/mfd/brcm,bcm59056.yaml     |   76 ++
>  .../bindings/regulator/brcm,bcm59054.yaml          |   56 +
>  .../bindings/regulator/brcm,bcm59056.yaml          |   51 +
>  arch/arm/boot/dts/broadcom/bcm28155-ap.dts         |   68 +-
>  arch/arm/boot/dts/broadcom/bcm59056.dtsi           |   91 --
>  drivers/mfd/bcm590xx.c                             |   75 +-
>  drivers/regulator/bcm590xx-regulator.c             | 1289 ++++++++++++++++----
>  include/linux/mfd/bcm590xx.h                       |   28 +-
>  9 files changed, 1366 insertions(+), 407 deletions(-)

Besides my one comment, the MFD side looks okay.

So you still need ACKs from Mark and to rework Rob's suggestion.

-- 
Lee Jones [???]


From axboe at kernel.dk  Thu Mar 13 06:24:37 2025
From: axboe at kernel.dk (Jens Axboe)
Date: Thu, 13 Mar 2025 07:24:37 -0600
Subject: [PATCH] block: remove unused parameter
In-Reply-To: <20250313035322.243239-1-anuj20.g@samsung.com>
References: <CGME20250313040150epcas5p347f94dac34fd2946dea51049559ee1de@epcas5p3.samsung.com>
 <20250313035322.243239-1-anuj20.g@samsung.com>
Message-ID: <174187227786.18244.14269218969550436496.b4-ty@kernel.dk>


On Thu, 13 Mar 2025 09:23:18 +0530, Anuj Gupta wrote:
> request_queue param is not used by blk_rq_map_sg and __blk_rq_map_sg.
> remove it.
> 
> 

Applied, thanks!

[1/1] block: remove unused parameter
      commit: 61667cb6644f6fb01eb8baa928e381c016b5ed7b

Best regards,
-- 
Jens Axboe





From wiagn233 at outlook.com  Thu Mar 13 06:09:50 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Thu, 13 Mar 2025 21:09:50 +0800
Subject: [PATCH v1] mt76: mt7915: wed: find rx token by physical address
In-Reply-To: <0ab3fb92-b529-46a3-bc78-230eaf4ae805@nbd.name>
References: <TYCPR01MB8437EE1595CD4AB581C006E898C62@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <TYCPR01MB843726907C170CFE2D3EB7BE98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <e144d2ffe9924d81a7b60f38cdcf516a@realtek.com>
 <1c46870f-965b-4f70-a01b-adbcd60c2876@nbd.name>
 <TYCPR01MB843770121E6576BB3807CD0A98D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>
 <0ab3fb92-b529-46a3-bc78-230eaf4ae805@nbd.name>
Message-ID: <TYCPR01MB8437B3AE3BABB36A78FE17D598D32@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Can you do the test? I'll be busy for months since tomorrow, so really 
don't have time to do this test...

I'll send the patch v2 first.

Best regards,
Shengyu

? 2025/3/13 20:47, Felix Fietkau ??:
> On 13.03.25 13:43, Shengyu Qu wrote:
>> Hi Felix,
>>
>> I'm not sure about the token ID incorrect frequency, this is just a port
>> of downstream patch, sorry.
> 
> Can you reproduce the issue that the downstream patch supposedly fixes?
> If so, you could add some printk to check how frequently it occurs.
> 
> - Felix

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/095a241b/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/095a241b/attachment.sig>

From broonie at kernel.org  Thu Mar 13 06:25:18 2025
From: broonie at kernel.org (Mark Brown)
Date: Thu, 13 Mar 2025 13:25:18 +0000
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <20250313132036.GB3616286@google.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
 <20250313132036.GB3616286@google.com>
Message-ID: <ef190ba8-a5c7-4a1a-90e6-2610de00e4ed@sirena.org.uk>

On Thu, Mar 13, 2025 at 01:20:36PM +0000, Lee Jones wrote:
> On Tue, 04 Mar 2025, Artur Weber wrote:

> > +	if (id != bcm590xx->pmu_id) {
> > +		dev_err(bcm590xx->dev,
> > +			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",
> 
> Isn't it more likely that the H/W this is being executed on is
> unsupported?  If so, say that instead.

Given that the compatibles are device specific the driver shouldn't be
binding if the device is unsupported.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/e9403856/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 13 06:17:27 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 13 Mar 2025 15:17:27 +0200
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <Z9LQFqSweiV-zT3b@smile.fi.intel.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQFqSweiV-zT3b@smile.fi.intel.com>
Message-ID: <bca95d63-fb6e-4d6c-8ab6-df67f0e697e6@gmail.com>

On 13/03/2025 14:31, Andy Shevchenko wrote:
> On Thu, Mar 13, 2025 at 09:18:18AM +0200, Matti Vaittinen wrote:
>> There are ADC ICs which may have some of the AIN pins usable for other
>> functions. These ICs may have some of the AIN pins wired so that they
>> should not be used for ADC.
>>
>> (Preferred?) way for marking pins which can be used as ADC inputs is to
>> add corresponding channels at N nodes in the device tree as described in
>> the ADC binding yaml.
>>
>> Add couple of helper functions which can be used to retrieve the channel
>> information from the device node.
> 
> ...
> 
>> +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
>> +					  const struct iio_chan_spec *template,
>> +					  int max_chan_id,
>> +					  struct iio_chan_spec **cs)
>> +{
>> +	struct iio_chan_spec *chan_array, *chan;
>> +	int num_chan = 0, ret;
> 
> Unneeded assignment.

Hmm. I have a deja-vu. Thanks for the reminder.

> 
>> +	num_chan = iio_adc_device_num_channels(dev);
>> +	if (num_chan < 1)
>> +		return num_chan;
> 
> This is really interesting code. So, if the above returns negative error code,
> we return it, if it returns 0, we return success (but 0 channels)?

Yes. I don't think it's that interesting though. Checking the devicetree 
succeeded while no channels were found. I think returning 0 is very much 
aligned with this.

> Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success?

I suppose you're right.

But, as you pointed out in review of the 05/10:
 > Usually in other similar APIs we return -ENOENT. And user won't need
 > to have an additional check in case of 0 being considered as an error
 > case too.

I don't know whether to agree with you here. For majority of the ADC 
drivers, having no channels in devicetree is indeed just another error, 
which I think is not in any ways special.

However, for 33,3333% of the users added in this patch, the "no channels 
found" is not really an error condition ;) The BD79124 could have all 
channels used for GPO - although this would probably be very very 
unusual. (Why buying an ADC chip if you need just a GPO?). Still, this 
wouldn't be an error. (And I need to handle this better in BD79124 probe 
- so thanks).

> (Under success I assume that returned values are okay to go with, and cs in
> your case will be left uninitialised or contain something we don't control.

I see your point although I wouldn't be concerned with cs not being NULL 
for as long as number of channels is zero.

Anyway, I think it makes sense to simplify ~67% of callers by returning 
-ENODEV if there is no channels. The remaining ~33% can then check for 
the -ENODEV and handle it separately from other returned errors. So, thanks.

>> +	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
>> +				  GFP_KERNEL);
>> +	if (!chan_array)
>> +		return -ENOMEM;
>> +
>> +	chan = &chan_array[0];
>> +
>> +	device_for_each_named_child_node_scoped(dev, child, "channel") {
>> +		u32 ch;
>> +
>> +		ret = fwnode_property_read_u32(child, "reg", &ch);
>> +		if (ret)
>> +			return ret;
> 
>> +		if (max_chan_id != -1 && ch > max_chan_id)
>> +			return -ERANGE;
> 
> Hmm... What if max_chan_id is equal to an error code?
> Or in other words, why -1 is special and not all negative numbers?

-1 was just picked to represent a 'don't care' value. Old habit. In the 
old days I handled lots of code where -1 was defined as 'invalid' for 
APIs with unsigned ints as well. It works nicely on systems where it 
turns out to be maximum positive value - leaving most of the number 
space for valid values.

I suppose saying any negative means "don't care" works well here. And, 
dropping all negatives here will also make the check below just work 
with unsigned comparison.

> Also note, you used unsigned type and compare it to int which,
> in case of being negative will give promotion.

Right. I didn't thin negative IDs would make sense and trusted users to 
pass only positive ones. Treating all negatives as "don't care" is 
indeed better than trusting this.

Thanks.

> The ch will not be
> big enough in most cases (unless it's great than (INT_MAX + 1).
> 
> TL;DR: you have a potential integer overflow here.
> 
>> +		*chan = *template;
>> +		chan->channel = ch;
>> +		chan++;
>> +	}
>> +
>> +	*cs = chan_array;
>> +
>> +	return num_chan;
>> +}
> 



From andrew at lunn.ch  Thu Mar 13 06:17:27 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 13 Mar 2025 14:17:27 +0100
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <20250313104042.694c1856@donnerap.manchester.arm.com>
References: <20250312193629.85417-1-michael@fossekall.de>
 <20250312193629.85417-2-michael@fossekall.de>
 <4637912.LvFx2qVVIh@jernej-laptop>
 <Z9KYqlfUYxRaWnGQ@a98shuttle.de>
 <20250313104042.694c1856@donnerap.manchester.arm.com>
Message-ID: <7cf91323-d550-496a-a8ec-ae104c77224d@lunn.ch>

On Thu, Mar 13, 2025 at 10:40:42AM +0000, Andre Przywara wrote:
> On Thu, 13 Mar 2025 09:34:50 +0100
> Michael Klein <michael at fossekall.de> wrote:
> 
> Hi,
> 
> > On Thu, Mar 13, 2025 at 07:07:24AM +0100, Jernej ?krabec wrote:
> > >Dne sreda, 12. marec 2025 ob 20:36:28 Srednjeevropski standardni ?as je Michael Klein napisal(a):  
> > >> The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
> > >> Add the corresponding nodes to the device tree.
> > >>
> > >> Signed-off-by: Michael Klein <michael at fossekall.de>  
> > >
> > >This is patch 2/2. Which one is patch 1/2? I got only one.  
> > 
> > https://patchwork.kernel.org/project/netdevbpf/patch/20250312193629.85417-1-michael at fossekall.de/
> > 
> > Sorry for any inconvenience in case I messed up the patch submission.
> > 
> > I made two commits for this change and submitted them via `git send-email 
> > HEAD^^`. The first patch went to netdev at vger.kernel.org, the second 
> > to linux-arm-kernel at lists.infradead.org, which seems logical. Have I 
> > done something wrong?
> 
> Well, for those really small "series" it's probably better to send all
> patches to everyone, especially if the first patch gives some context,
> without which the second leaves people (like me) scratching their head.

However, netdev does not like pathchsets which contain patches which
should not be applied to the netdev tree. DT patches generally go
through a different Maintainer to driver changes implementing the
binding.

So for your DT patch, you could add to the commit message something
like:

The RTL8211E ethernet PHY driver has recently gained support for
controlling PHY LEDs via /sys/class/leds. The Bananapi M1 has three
LEDs connected to the RTL8211E PHY.  Add the corresponding nodes to
the device tree.

	Andrew


From lee at kernel.org  Thu Mar 13 06:20:36 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 13:20:36 +0000
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
Message-ID: <20250313132036.GB3616286@google.com>

On Tue, 04 Mar 2025, Artur Weber wrote:

> The BCM590xx PMUs have two I2C registers for reading the PMU ID
> and revision. The revision is useful for subdevice drivers, since
> different revisions may have slight differences in behavior (for
> example - BCM59054 has different regulator configurations for
> revision A0 and A1).
> 
> Check the PMU ID register and make sure it matches the DT compatible.
> Fetch the digital and analog revision from the PMUREV register
> so that it can be used in subdevice drivers.
> 
> Also add some known revision values to bcm590xx.h, for convenience
> when writing subdevice drivers.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---
> Changes in v6:
> - Adapt to PMUID being passed as device type value
> - Rename rev_dig and rev_ana to rev_digital and rev_analog
> - Rewrite commit message
> 
> Changes in v5:
> - Add REG_ prefix to register offset constant names
> 
> Changes in v4:
> - Added this commit
> ---
>  drivers/mfd/bcm590xx.c       | 63 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/bcm590xx.h | 14 ++++++++++
>  2 files changed, 77 insertions(+)
> 
> diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
> index 4620eed0066fbf1dd691a2e392e967747b4d125b..74dc4ae5ecd5db7fadc56918f63110c1265d4a76 100644
> --- a/drivers/mfd/bcm590xx.c
> +++ b/drivers/mfd/bcm590xx.c
> @@ -17,6 +17,15 @@
>  #include <linux/regmap.h>
>  #include <linux/slab.h>
>  
> +/* Under primary I2C address: */
> +#define BCM590XX_REG_PMUID		0x1e
> +
> +#define BCM590XX_REG_PMUREV		0x1f
> +#define BCM590XX_PMUREV_DIG_MASK	0xF
> +#define BCM590XX_PMUREV_DIG_SHIFT	0
> +#define BCM590XX_PMUREV_ANA_MASK	0xF0
> +#define BCM590XX_PMUREV_ANA_SHIFT	4
> +
>  static const struct mfd_cell bcm590xx_devs[] = {
>  	{
>  		.name = "bcm590xx-vregs",
> @@ -37,6 +46,56 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
>  	.cache_type	= REGCACHE_MAPLE,
>  };
>  
> +/* Map PMU ID value to model name string */
> +static const char * const bcm590xx_names[] = {
> +	[BCM590XX_PMUID_BCM59054] = "BCM59054",
> +	[BCM590XX_PMUID_BCM59056] = "BCM59056",
> +};
> +
> +/*
> + * Parse the version from version registers and make sure it matches
> + * the device type passed to the compatible.
> + */
> +static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)
> +{
> +	unsigned int id, rev;
> +	int ret;
> +
> +	/* Get PMU ID and verify that it matches compatible */
> +	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);
> +	if (ret) {
> +		dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (id != bcm590xx->pmu_id) {
> +		dev_err(bcm590xx->dev,
> +			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",

Isn't it more likely that the H/W this is being executed on is
unsupported?  If so, say that instead.

> +			bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);
> +		return -EINVAL;

-ENODEV

> +	}
> +
> +	/* Get PMU revision and store it in the info struct */
> +	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);
> +	if (ret) {
> +		dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK)
> +				     >> BCM590XX_PMUREV_DIG_SHIFT;
> +
> +	bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK)
> +				    >> BCM590XX_PMUREV_ANA_SHIFT;
> +
> +	dev_info(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",
> +		 id, bcm590xx_names[id],
> +		 bcm590xx->rev_digital, bcm590xx->rev_analog);
> +
> +	return 0;
> +}
> +
>  static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
>  {
>  	struct bcm590xx *bcm590xx;
> @@ -78,6 +137,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
>  		goto err;
>  	}
>  
> +	ret = bcm590xx_parse_version(bcm590xx);
> +	if (ret)
> +		goto err;
> +
>  	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
>  				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
>  	if (ret < 0) {
> diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
> index 8d146e3b102a7dbce6f4dbab9f8ae5a9c4e68c0e..fbc458e94bef923ca1b69afe2cac944adf6fedf8 100644
> --- a/include/linux/mfd/bcm590xx.h
> +++ b/include/linux/mfd/bcm590xx.h
> @@ -17,6 +17,16 @@
>  #define BCM590XX_PMUID_BCM59054		0x54
>  #define BCM590XX_PMUID_BCM59056		0x56
>  
> +/* Known chip revision IDs */
> +#define BCM59054_REV_DIGITAL_A1		1
> +#define BCM59054_REV_ANALOG_A1		2
> +
> +#define BCM59056_REV_DIGITAL_A0		1
> +#define BCM59056_REV_ANALOG_A0		1
> +
> +#define BCM59056_REV_DIGITAL_B0		2
> +#define BCM59056_REV_ANALOG_B0		2
> +
>  /* max register address */
>  #define BCM590XX_MAX_REGISTER_PRI	0xe7
>  #define BCM590XX_MAX_REGISTER_SEC	0xf0
> @@ -30,6 +40,10 @@ struct bcm590xx {
>  
>  	/* PMU ID value; also used as device type */
>  	u8 pmu_id;
> +
> +	/* Chip revision, read from PMUREV reg */
> +	u8 rev_digital;
> +	u8 rev_analog;
>  };
>  
>  #endif /*  __LINUX_MFD_BCM590XX_H */
> 
> -- 
> 2.48.1
> 

-- 
Lee Jones [???]


From andriy.shevchenko at linux.intel.com  Thu Mar 13 06:29:37 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Thu, 13 Mar 2025 15:29:37 +0200
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <bca95d63-fb6e-4d6c-8ab6-df67f0e697e6@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQFqSweiV-zT3b@smile.fi.intel.com>
 <bca95d63-fb6e-4d6c-8ab6-df67f0e697e6@gmail.com>
Message-ID: <Z9LdwUVBOEx-Tbvr@smile.fi.intel.com>

On Thu, Mar 13, 2025 at 03:17:27PM +0200, Matti Vaittinen wrote:
> On 13/03/2025 14:31, Andy Shevchenko wrote:
> > On Thu, Mar 13, 2025 at 09:18:18AM +0200, Matti Vaittinen wrote:

...

> > > +	num_chan = iio_adc_device_num_channels(dev);
> > > +	if (num_chan < 1)
> > > +		return num_chan;
> > 
> > This is really interesting code. So, if the above returns negative error code,
> > we return it, if it returns 0, we return success (but 0 channels)?
> 
> Yes. I don't think it's that interesting though. Checking the devicetree
> succeeded while no channels were found. I think returning 0 is very much
> aligned with this.

Right, but as I suggested, let's follow already established APIs that return
-ENOENT and never 0 in similar cases.

> > Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success?
> 
> I suppose you're right.
> 
> But, as you pointed out in review of the 05/10:
> > Usually in other similar APIs we return -ENOENT. And user won't need
> > to have an additional check in case of 0 being considered as an error
> > case too.
> 
> I don't know whether to agree with you here. For majority of the ADC
> drivers, having no channels in devicetree is indeed just another error,
> which I think is not in any ways special.

So...? (I see below your answer :-)

> However, for 33,3333% of the users added in this patch, the "no channels
> found" is not really an error condition ;) The BD79124 could have all
> channels used for GPO - although this would probably be very very unusual.
> (Why buying an ADC chip if you need just a GPO?). Still, this wouldn't be an
> error. (And I need to handle this better in BD79124 probe - so thanks).

ENOENT check is again established for optional/not_found cases.

> > (Under success I assume that returned values are okay to go with, and cs in
> > your case will be left uninitialised or contain something we don't control.
> 
> I see your point although I wouldn't be concerned with cs not being NULL for
> as long as number of channels is zero.
> 
> Anyway, I think it makes sense to simplify ~67% of callers by returning
> -ENODEV if there is no channels. The remaining ~33% can then check for the
> -ENODEV and handle it separately from other returned errors. So, thanks.

Not at all!

-- 
With Best Regards,
Andy Shevchenko




From andrew at lunn.ch  Thu Mar 13 06:32:33 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 13 Mar 2025 14:32:33 +0100
Subject: [PATCH net] net: stmmac: dwc-qos-eth: use devm_kzalloc() for AXI
 data
In-Reply-To: <E1tsRyv-0064nU-O9@rmk-PC.armlinux.org.uk>
References: <E1tsRyv-0064nU-O9@rmk-PC.armlinux.org.uk>
Message-ID: <a889db9a-1aa9-4a17-9762-01c74911e39b@lunn.ch>

On Wed, Mar 12, 2025 at 07:43:09PM +0000, Russell King (Oracle) wrote:
> Everywhere else in the driver uses devm_kzalloc() when allocating the
> AXI data, so there is no kfree() of this structure. However,
> dwc-qos-eth uses kzalloc(), which leads to this memory being leaked.
> Switch to use devm_kzalloc().
> 
> Fixes: d8256121a91a ("stmmac: adding new glue driver dwmac-dwc-qos-eth")
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From prabhakar.csengg at gmail.com  Thu Mar 13 06:38:12 2025
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Thu, 13 Mar 2025 13:38:12 +0000
Subject: [PATCH net-next v2 7/7] net: stmmac: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <E1tsIUK-005vGk-H7@rmk-PC.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk> <E1tsIUK-005vGk-H7@rmk-PC.armlinux.org.uk>
Message-ID: <CA+V-a8sasAGkwCWGnbBEjeMRVM79xVVzTq15uJQ_7Q+YwB1QpA@mail.gmail.com>

On Wed, Mar 12, 2025 at 9:58?AM Russell King (Oracle)
<rmk+kernel at armlinux.org.uk> wrote:
>
> Whether the MII transmit clock can be stopped is primarily a property
> of the PHY (there is a capability bit that should be checked first.)
> Whether the MAC is capable of stopping the transmit clock is a separate
> issue, but this is already handled by the core DesignWare MAC code.
>
> Therefore, snps,en-tx-lpi-clockgating is technically incorrect, and
> this commit adds a warning should a DT be encountered with the property
> present.
>
> However, we keep backwards compatibility.
>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>

Cheers,
Prabhakar


From heiko at sntech.de  Thu Mar 13 06:40:32 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 14:40:32 +0100
Subject: [PATCH v8 2/2] phy: rockchip: Add Samsung MIPI D-/C-PHY driver
In-Reply-To: <20250313134035.278133-1-heiko@sntech.de>
References: <20250313134035.278133-1-heiko@sntech.de>
Message-ID: <20250313134035.278133-3-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

Add driver for the MIPI D-/C-PHY block based around a Samsung IP-block
that is for example needed to drive a MIPI DSI output on rk3588.

Right now only the D-PHY portion is implemented, with the C-PHY part
needing separate work.

Tested-by: Daniel Semkowicz <dse at thaumatec.com>
Tested-by: Sebastian Reichel <sebastian.reichel at collabora.com>
Tested-by: Quentin Schulz <quentin.schulz at cherry.de>
Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>
Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 drivers/phy/rockchip/Kconfig                  |   12 +
 drivers/phy/rockchip/Makefile                 |    1 +
 .../phy/rockchip/phy-rockchip-samsung-dcphy.c | 1719 +++++++++++++++++
 3 files changed, 1732 insertions(+)
 create mode 100644 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c

diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index dcb8e1628632e..14698571b6075 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -83,6 +83,18 @@ config PHY_ROCKCHIP_PCIE
 	help
 	  Enable this to support the Rockchip PCIe PHY.
 
+config PHY_ROCKCHIP_SAMSUNG_DCPHY
+	tristate "Rockchip Samsung MIPI DCPHY driver"
+	depends on (ARCH_ROCKCHIP || COMPILE_TEST)
+	select GENERIC_PHY
+	select GENERIC_PHY_MIPI_DPHY
+	help
+	  Enable this to support the Rockchip MIPI DCPHY with
+	  Samsung IP block.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called phy-rockchip-samsung-dcphy
+
 config PHY_ROCKCHIP_SAMSUNG_HDPTX
 	tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
 	depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index 010a824e32ce0..117aaffd037d8 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)	+= phy-rockchip-inno-hdmi.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
 obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY)	+= phy-rockchip-naneng-combphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY)	+= phy-rockchip-samsung-dcphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX)	+= phy-rockchip-samsung-hdptx.o
 obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3)	+= phy-rockchip-snps-pcie3.o
 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
new file mode 100644
index 0000000000000..08c78c1bafc9a
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -0,0 +1,1719 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Rockchip Electronics Co.Ltd
+ * Author:
+ *      Guochun Huang <hero.huang at rock-chips.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define FIELD_PREP_HIWORD(_mask, _val)		\
+	(					\
+		FIELD_PREP((_mask), (_val)) |	\
+		((_mask) << 16)			\
+	)
+
+#define BIAS_CON0		0x0000
+#define I_RES_CNTL_MASK		GENMASK(6, 4)
+#define I_RES_CNTL(x)		FIELD_PREP(I_RES_CNTL_MASK, x)
+#define I_RES_059_2UA		I_RES_CNTL(0)
+#define I_RES_100_2UA		I_RES_CNTL(1)
+#define I_RES_094_2UA		I_RES_CNTL(2)
+#define I_RES_113_8UA		I_RES_CNTL(3)
+#define I_RES_089_7UA		I_RES_CNTL(4)
+#define I_RES_111_8UA		I_RES_CNTL(5)
+#define I_RES_108_2UA		I_RES_CNTL(6)
+#define I_RES_120_8UA		I_RES_CNTL(7)
+#define I_DEV_SEL_MASK		GENMASK(1, 0)
+#define I_DEV_SEL(x)		FIELD_PREP(I_DEV_SEL_MASK, x)
+#define I_DEV_DIV_6		I_DEV_SEL(0)
+#define I_DEV_DIV_12		I_DEV_SEL(1)
+#define I_DEV_DIV_20		I_DEV_SEL(2)
+#define I_DEV_DIV_40		I_DEV_SEL(3)
+
+#define BIAS_CON1		0x0004
+#define I_VBG_SEL_MASK		GENMASK(9, 8)
+#define I_VBG_SEL(x)		FIELD_PREP(I_VBG_SEL_MASK, x)
+#define I_VBG_SEL_780MV		I_VBG_SEL(0)
+#define I_VBG_SEL_820MV		I_VBG_SEL(1)
+#define I_VBG_SEL_860MV		I_VBG_SEL(2)
+#define I_VBG_SEL_900MV		I_VBG_SEL(3)
+#define I_BGR_VREF_SEL_MASK	GENMASK(5, 4)
+#define I_BGR_VREF_SEL(x)	FIELD_PREP(I_BGR_VREF_SEL_MASK, x)
+#define I_BGR_VREF_810MV	I_BGR_VREF_SEL(0)
+#define I_BGR_VREF_820MV	I_BGR_VREF_SEL(1)
+#define I_BGR_VREF_830MV	I_BGR_VREF_SEL(2)
+#define I_BGR_VREF_840MV	I_BGR_VREF_SEL(3)
+#define I_LADDER_SEL_MASK	GENMASK(2, 0)
+#define I_LADDER_SEL(x)		FIELD_PREP(I_LADDER_SEL_MASK, x)
+#define I_LADDER_1_00V		I_LADDER_SEL(0)
+#define I_LADDER_0_96V		I_LADDER_SEL(1)
+#define I_LADDER_0_92V		I_LADDER_SEL(2)
+#define I_LADDER_0_88V		I_LADDER_SEL(3)
+#define I_LADDER_0_84V		I_LADDER_SEL(4)
+#define I_LADDER_0_80V		I_LADDER_SEL(5)
+#define I_LADDER_0_76V		I_LADDER_SEL(6)
+#define I_LADDER_0_72V		I_LADDER_SEL(7)
+
+/*
+ * Voltage corrections around reference voltages
+ * The selection between the 400-based or 200-based values for REG_400M
+ * is done by the hw depending on I_MUX below being 400MV or 200MV.
+ */
+#define BIAS_CON2		0x0008
+#define REG_325M_MASK		GENMASK(14, 12)
+#define REG_325M(x)		FIELD_PREP(REG_325M_MASK, x)
+#define REG_325M_295MV		REG_325M(0)
+#define REG_325M_305MV		REG_325M(1)
+#define REG_325M_315MV		REG_325M(2)
+#define REG_325M_325MV		REG_325M(3)
+#define REG_325M_335MV		REG_325M(4)
+#define REG_325M_345MV		REG_325M(5)
+#define REG_325M_355MV		REG_325M(6)
+#define REG_325M_365MV		REG_325M(7)
+#define REG_LP_400M_MASK	GENMASK(10, 8)
+#define REG_LP_400M(x)		FIELD_PREP(REG_LP_400M_MASK, x)
+#define REG_LP_400M_380MV	REG_LP_400M(0)
+#define REG_LP_400M_390MV	REG_LP_400M(1)
+#define REG_LP_400M_400MV	REG_LP_400M(2)
+#define REG_LP_400M_410MV	REG_LP_400M(3)
+#define REG_LP_400M_420MV	REG_LP_400M(4)
+#define REG_LP_400M_430MV	REG_LP_400M(5)
+#define REG_LP_400M_440MV	REG_LP_400M(6)
+#define REG_LP_400M_450MV	REG_LP_400M(7)
+#define REG_400M_MASK		GENMASK(6, 4)
+#define REG_400M(x)		FIELD_PREP(REG_400M_MASK, x)
+#define REG_400M_380MV		REG_400M(0)
+#define REG_400M_390MV		REG_400M(1)
+#define REG_400M_400MV		REG_400M(2)
+#define REG_400M_410MV		REG_400M(3)
+#define REG_400M_420MV		REG_400M(4)
+#define REG_400M_430MV		REG_400M(5)
+#define REG_400M_440MV		REG_400M(6)
+#define REG_400M_450MV		REG_400M(7)
+#define REG_400M_230MV		REG_400M(0)
+#define REG_400M_220MV		REG_400M(1)
+#define REG_400M_210MV		REG_400M(2)
+#define REG_400M_200MV		REG_400M(3)
+#define REG_400M_190MV		REG_400M(4)
+#define REG_400M_180MV		REG_400M(5)
+#define REG_400M_170MV		REG_400M(6)
+#define REG_400M_160MV		REG_400M(7)
+#define REG_645M_MASK		GENMASK(2, 0)
+#define REG_645M(x)		FIELD_PREP(REG_645M_MASK, x)
+#define REG_645M_605MV		REG_645M(0)
+#define REG_645M_625MV		REG_645M(1)
+#define REG_645M_635MV		REG_645M(2)
+#define REG_645M_645MV		REG_645M(3)
+#define REG_645M_655MV		REG_645M(4)
+#define REG_645M_665MV		REG_645M(5)
+#define REG_645M_685MV		REG_645M(6)
+#define REG_645M_725MV		REG_645M(7)
+
+#define BIAS_CON4		0x0010
+#define I_MUX_SEL_MASK		GENMASK(6, 5)
+#define I_MUX_SEL(x)		FIELD_PREP(I_MUX_SEL_MASK, x)
+#define I_MUX_400MV		I_MUX_SEL(0)
+#define I_MUX_200MV		I_MUX_SEL(1)
+#define I_MUX_530MV		I_MUX_SEL(2)
+
+#define PLL_CON0		0x0100
+#define PLL_EN			BIT(12)
+#define S_MASK			GENMASK(10, 8)
+#define S(x)			FIELD_PREP(S_MASK, x)
+#define P_MASK			GENMASK(5, 0)
+#define P(x)			FIELD_PREP(P_MASK, x)
+#define PLL_CON1		0x0104
+#define PLL_CON2		0x0108
+#define M_MASK			GENMASK(9, 0)
+#define M(x)			FIELD_PREP(M_MASK, x)
+#define PLL_CON3		0x010c
+#define MRR_MASK		GENMASK(13, 8)
+#define MRR(x)			FIELD_PREP(MRR_MASK, x)
+#define MFR_MASK		GENMASK(7, 0)
+#define MFR(x)			FIELD_PREP(MFR_MASK, x)
+#define PLL_CON4		0x0110
+#define SSCG_EN			BIT(11)
+#define PLL_CON5		0x0114
+#define RESET_N_SEL		BIT(10)
+#define PLL_ENABLE_SEL		BIT(8)
+#define PLL_CON6		0x0118
+#define PLL_CON7		0x011c
+#define PLL_LOCK_CNT(x)		FIELD_PREP(GENMASK(15, 0), x)
+#define PLL_CON8		0x0120
+#define PLL_STB_CNT(x)		FIELD_PREP(GENMASK(15, 0), x)
+#define PLL_STAT0		0x0140
+#define PLL_LOCK		BIT(0)
+
+#define DPHY_MC_GNR_CON0	0x0300
+#define PHY_READY		BIT(1)
+#define PHY_ENABLE		BIT(0)
+#define DPHY_MC_GNR_CON1	0x0304
+#define T_PHY_READY(x)		FIELD_PREP(GENMASK(15, 0), x)
+#define DPHY_MC_ANA_CON0	0x0308
+#define EDGE_CON(x)		FIELD_PREP(GENMASK(14, 12), x)
+#define EDGE_CON_DIR(x)		FIELD_PREP(BIT(9), x)
+#define EDGE_CON_EN		BIT(8)
+#define RES_UP(x)		FIELD_PREP(GENMASK(7, 4), x)
+#define RES_DN(x)		FIELD_PREP(GENMASK(3, 0), x)
+#define DPHY_MC_ANA_CON1	0x030c
+#define DPHY_MC_ANA_CON2	0x0310
+#define HS_VREG_AMP_ICON(x)	FIELD_PREP(GENMASK(1, 0), x)
+#define DPHY_MC_TIME_CON0	0x0330
+#define HSTX_CLK_SEL		BIT(12)
+#define T_LPX(x)		FIELD_PREP(GENMASK(11, 4), x)
+#define DPHY_MC_TIME_CON1	0x0334
+#define T_CLK_ZERO(x)		FIELD_PREP(GENMASK(15, 8), x)
+#define T_CLK_PREPARE(x)	FIELD_PREP(GENMASK(7, 0), x)
+#define DPHY_MC_TIME_CON2	0x0338
+#define T_HS_EXIT(x)		FIELD_PREP(GENMASK(15, 8), x)
+#define T_CLK_TRAIL(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define DPHY_MC_TIME_CON3	0x033c
+#define T_CLK_POST(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define DPHY_MC_TIME_CON4	0x0340
+#define T_ULPS_EXIT(x)		FIELD_PREP(GENMASK(9, 0), x)
+#define DPHY_MC_DESKEW_CON0	0x0350
+#define SKEW_CAL_RUN_TIME(x)	FIELD_PREP(GENMASK(15, 12), x)
+
+#define SKEW_CAL_INIT_RUN_TIME(x)	FIELD_PREP(GENMASK(11, 8), x)
+#define SKEW_CAL_INIT_WAIT_TIME(x)	FIELD_PREP(GENMASK(7, 4), x)
+#define SKEW_CAL_EN			BIT(0)
+
+#define COMBO_MD0_GNR_CON0	0x0400
+#define COMBO_MD0_GNR_CON1	0x0404
+#define COMBO_MD0_ANA_CON0	0x0408
+#define COMBO_MD0_ANA_CON1	0x040c
+#define COMBO_MD0_ANA_CON2	0x0410
+
+#define COMBO_MD0_TIME_CON0	0x0430
+#define COMBO_MD0_TIME_CON1	0x0434
+#define COMBO_MD0_TIME_CON2	0x0438
+#define COMBO_MD0_TIME_CON3	0x043c
+#define COMBO_MD0_TIME_CON4	0x0440
+#define COMBO_MD0_DATA_CON0	0x0444
+
+#define COMBO_MD1_GNR_CON0	0x0500
+#define COMBO_MD1_GNR_CON1	0x0504
+#define COMBO_MD1_ANA_CON0	0x0508
+#define COMBO_MD1_ANA_CON1	0x050c
+#define COMBO_MD1_ANA_CON2	0x0510
+#define COMBO_MD1_TIME_CON0	0x0530
+#define COMBO_MD1_TIME_CON1	0x0534
+#define COMBO_MD1_TIME_CON2	0x0538
+#define COMBO_MD1_TIME_CON3	0x053c
+#define COMBO_MD1_TIME_CON4	0x0540
+#define COMBO_MD1_DATA_CON0	0x0544
+
+#define COMBO_MD2_GNR_CON0	0x0600
+#define COMBO_MD2_GNR_CON1	0x0604
+#define COMBO_MD2_ANA_CON0	0X0608
+#define COMBO_MD2_ANA_CON1	0X060c
+#define COMBO_MD2_ANA_CON2	0X0610
+#define COMBO_MD2_TIME_CON0	0x0630
+#define COMBO_MD2_TIME_CON1	0x0634
+#define COMBO_MD2_TIME_CON2	0x0638
+#define COMBO_MD2_TIME_CON3	0x063c
+#define COMBO_MD2_TIME_CON4	0x0640
+#define COMBO_MD2_DATA_CON0	0x0644
+
+#define DPHY_MD3_GNR_CON0	0x0700
+#define DPHY_MD3_GNR_CON1	0x0704
+#define DPHY_MD3_ANA_CON0	0X0708
+#define DPHY_MD3_ANA_CON1	0X070c
+#define DPHY_MD3_ANA_CON2	0X0710
+#define DPHY_MD3_TIME_CON0	0x0730
+#define DPHY_MD3_TIME_CON1	0x0734
+#define DPHY_MD3_TIME_CON2	0x0738
+#define DPHY_MD3_TIME_CON3	0x073c
+#define DPHY_MD3_TIME_CON4	0x0740
+#define DPHY_MD3_DATA_CON0	0x0744
+
+#define T_LP_EXIT_SKEW(x)	FIELD_PREP(GENMASK(3, 2), x)
+#define T_LP_ENTRY_SKEW(x)	FIELD_PREP(GENMASK(1, 0), x)
+#define T_HS_ZERO(x)		FIELD_PREP(GENMASK(15, 8), x)
+#define T_HS_PREPARE(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define T_HS_EXIT(x)		FIELD_PREP(GENMASK(15, 8), x)
+#define T_HS_TRAIL(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define T_TA_GET(x)		FIELD_PREP(GENMASK(7, 4), x)
+#define T_TA_GO(x)		FIELD_PREP(GENMASK(3, 0), x)
+
+/* MIPI_CDPHY_GRF registers */
+#define MIPI_DCPHY_GRF_CON0		0x0000
+#define S_CPHY_MODE			FIELD_PREP_HIWORD(BIT(3), 1)
+#define M_CPHY_MODE			FIELD_PREP_HIWORD(BIT(0), 1)
+
+enum hs_drv_res_ohm {
+	STRENGTH_30_OHM = 0x8,
+	STRENGTH_31_2_OHM,
+	STRENGTH_32_5_OHM,
+	STRENGTH_34_OHM,
+	STRENGTH_35_5_OHM,
+	STRENGTH_37_OHM,
+	STRENGTH_39_OHM,
+	STRENGTH_41_OHM,
+	STRENGTH_43_OHM = 0x0,
+	STRENGTH_46_OHM,
+	STRENGTH_49_OHM,
+	STRENGTH_52_OHM,
+	STRENGTH_56_OHM,
+	STRENGTH_60_OHM,
+	STRENGTH_66_OHM,
+	STRENGTH_73_OHM,
+};
+
+struct hs_drv_res_cfg {
+	enum hs_drv_res_ohm clk_hs_drv_up_ohm;
+	enum hs_drv_res_ohm clk_hs_drv_down_ohm;
+	enum hs_drv_res_ohm data_hs_drv_up_ohm;
+	enum hs_drv_res_ohm data_hs_drv_down_ohm;
+};
+
+struct samsung_mipi_dcphy_plat_data {
+	const struct hs_drv_res_cfg *dphy_hs_drv_res_cfg;
+	u32 dphy_tx_max_lane_kbps;
+};
+
+struct samsung_mipi_dcphy {
+	struct device *dev;
+	struct clk *ref_clk;
+	struct clk *pclk;
+	struct regmap *regmap;
+	struct regmap *grf_regmap;
+	struct reset_control *m_phy_rst;
+	struct reset_control *s_phy_rst;
+	struct reset_control *apb_rst;
+	struct reset_control *grf_apb_rst;
+	unsigned int lanes;
+	struct phy *phy;
+	u8 type;
+
+	const struct samsung_mipi_dcphy_plat_data *pdata;
+	struct {
+		unsigned long long rate;
+		u8 prediv;
+		u16 fbdiv;
+		long dsm;
+		u8 scaler;
+
+		bool ssc_en;
+		u8 mfr;
+		u8 mrr;
+	} pll;
+};
+
+struct samsung_mipi_dphy_timing {
+	unsigned int max_lane_mbps;
+	u8 clk_prepare;
+	u8 clk_zero;
+	u8 clk_post;
+	u8 clk_trail_eot;
+	u8 hs_prepare;
+	u8 hs_zero;
+	u8 hs_trail_eot;
+	u8 lpx;
+	u8 hs_exit;
+	u8 hs_settle;
+};
+
+/*
+ * Timing values taken from rk3588 vendor kernel.
+ * Not documented in hw documentation.
+ */
+static const
+struct samsung_mipi_dphy_timing samsung_mipi_dphy_timing_table[] = {
+	{6500, 32, 117, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6490, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6480, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6470, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6460, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6450, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6440, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37},
+	{6430, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37},
+	{6420, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37},
+	{6410, 31, 116, 31, 27, 30, 55, 27, 24, 44, 37},
+	{6400, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36},
+	{6390, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36},
+	{6380, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36},
+	{6370, 31, 115, 30, 27, 30, 55, 26, 23, 43, 36},
+	{6360, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6350, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6340, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6330, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6320, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6310, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6300, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36},
+	{6290, 31, 113, 30, 27, 29, 54, 26, 23, 43, 36},
+	{6280, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36},
+	{6270, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36},
+	{6260, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36},
+	{6250, 31, 112, 30, 27, 29, 54, 26, 23, 42, 36},
+	{6240, 30, 113, 30, 27, 29, 54, 26, 23, 42, 36},
+	{6230, 30, 112, 30, 27, 29, 54, 26, 23, 42, 35},
+	{6220, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35},
+	{6210, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35},
+	{6200, 30, 112, 29, 27, 29, 53, 26, 23, 42, 35},
+	{6190, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35},
+	{6180, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35},
+	{6170, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35},
+	{6160, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35},
+	{6150, 30, 110, 29, 26, 29, 53, 26, 23, 42, 35},
+	{6140, 30, 110, 29, 26, 29, 52, 26, 23, 42, 35},
+	{6130, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35},
+	{6120, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35},
+	{6110, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35},
+	{6100, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35},
+	{6090, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35},
+	{6080, 30, 109, 29, 26, 28, 53, 25, 22, 41, 35},
+	{6070, 30, 109, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6060, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6050, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6040, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6030, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6020, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6010, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34},
+	{6000, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34},
+	{5990, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34},
+	{5980, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34},
+	{5970, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34},
+	{5960, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34},
+	{5950, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34},
+	{5940, 29, 107, 28, 25, 28, 51, 25, 22, 40, 34},
+	{5930, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34},
+	{5920, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34},
+	{5910, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34},
+	{5900, 29, 106, 28, 25, 28, 50, 24, 22, 40, 33},
+	{5890, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33},
+	{5880, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33},
+	{5870, 29, 105, 28, 25, 27, 51, 24, 22, 40, 33},
+	{5860, 29, 105, 28, 25, 27, 51, 24, 21, 40, 33},
+	{5850, 29, 104, 28, 25, 27, 50, 24, 21, 40, 33},
+	{5840, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33},
+	{5830, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33},
+	{5820, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33},
+	{5810, 28, 104, 28, 25, 27, 50, 24, 21, 39, 33},
+	{5800, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33},
+	{5790, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33},
+	{5780, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33},
+	{5770, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33},
+	{5760, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33},
+	{5750, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33},
+	{5740, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33},
+	{5730, 28, 103, 27, 25, 27, 49, 24, 21, 39, 32},
+	{5720, 28, 102, 27, 25, 27, 49, 24, 21, 39, 32},
+	{5710, 28, 102, 27, 25, 27, 48, 24, 21, 39, 32},
+	{5700, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32},
+	{5690, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32},
+	{5680, 28, 101, 27, 24, 27, 48, 24, 21, 39, 32},
+	{5670, 28, 101, 27, 24, 27, 48, 23, 21, 38, 32},
+	{5660, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32},
+	{5650, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32},
+	{5640, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32},
+	{5630, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32},
+	{5620, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32},
+	{5610, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32},
+	{5600, 27, 101, 26, 24, 26, 48, 23, 20, 38, 32},
+	{5590, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32},
+	{5580, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32},
+	{5570, 27, 100, 26, 24, 26, 48, 23, 20, 38, 31},
+	{5560, 27, 100, 26, 24, 26, 47, 23, 20, 38, 31},
+	{5550, 27,  99, 26, 24, 26, 47, 23, 20, 38, 31},
+	{5540, 27,  99, 26, 24, 26, 47, 23, 20, 38, 31},
+	{5530, 27,  99, 26, 24, 26, 47, 23, 20, 38, 31},
+	{5520, 27,  99, 26, 24, 26, 47, 23, 20, 37, 31},
+	{5510, 27,  98, 26, 24, 26, 47, 23, 20, 37, 31},
+	{5500, 27,  98, 26, 24, 26, 47, 23, 20, 37, 31},
+	{5490, 27,  98, 26, 24, 26, 46, 23, 20, 37, 31},
+	{5480, 27,  98, 26, 24, 26, 46, 23, 20, 37, 31},
+	{5470, 27,  97, 26, 23, 26, 46, 23, 20, 37, 31},
+	{5460, 27,  97, 26, 23, 26, 46, 23, 20, 37, 31},
+	{5450, 27,  97, 26, 23, 25, 47, 23, 20, 37, 31},
+	{5440, 26,  98, 26, 23, 25, 47, 23, 20, 37, 31},
+	{5430, 26,  98, 26, 23, 25, 47, 22, 20, 37, 31},
+	{5420, 26,  97, 26, 23, 25, 46, 22, 20, 37, 31},
+	{5410, 26,  97, 26, 23, 25, 46, 22, 20, 37, 31},
+	{5400, 26,  97, 25, 23, 25, 46, 22, 20, 37, 30},
+	{5390, 26,  97, 25, 23, 25, 46, 22, 20, 37, 30},
+	{5380, 26,  96, 25, 23, 25, 46, 22, 20, 36, 30},
+	{5370, 26,  96, 25, 23, 25, 46, 22, 20, 36, 30},
+	{5360, 26,  96, 25, 23, 25, 46, 22, 20, 36, 30},
+	{5350, 26,  96, 25, 23, 25, 46, 22, 20, 36, 30},
+	{5340, 26,  95, 25, 23, 25, 45, 22, 20, 36, 30},
+	{5330, 26,  95, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5320, 26,  95, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5310, 26,  95, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5300, 26,  95, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5290, 26,  94, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5280, 26,  94, 25, 23, 25, 45, 22, 19, 36, 30},
+	{5270, 26,  94, 25, 23, 25, 44, 22, 19, 36, 30},
+	{5260, 26,  94, 25, 23, 25, 44, 22, 19, 36, 30},
+	{5250, 25,  94, 25, 23, 24, 45, 22, 19, 36, 30},
+	{5240, 25,  94, 25, 23, 24, 45, 22, 19, 36, 29},
+	{5230, 25,  94, 25, 22, 24, 45, 22, 19, 35, 29},
+	{5220, 25,  94, 25, 22, 24, 45, 22, 19, 35, 29},
+	{5210, 25,  93, 25, 22, 24, 45, 22, 19, 35, 29},
+	{5200, 25,  93, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5190, 25,  93, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5180, 25,  93, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5170, 25,  92, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5160, 25,  92, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5150, 25,  92, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5140, 25,  92, 24, 22, 24, 44, 21, 19, 35, 29},
+	{5130, 25,  92, 24, 22, 24, 43, 21, 19, 35, 29},
+	{5120, 25,  91, 24, 22, 24, 43, 21, 19, 35, 29},
+	{5110, 25,  91, 24, 22, 24, 43, 21, 19, 35, 29},
+	{5100, 25,  91, 24, 22, 24, 43, 21, 19, 35, 29},
+	{5090, 25,  91, 24, 22, 24, 43, 21, 19, 34, 29},
+	{5080, 25,  90, 24, 22, 24, 43, 21, 19, 34, 29},
+	{5070, 25,  90, 24, 22, 24, 43, 21, 19, 34, 28},
+	{5060, 25,  90, 24, 22, 24, 43, 21, 18, 34, 28},
+	{5050, 24,  91, 24, 22, 24, 42, 21, 18, 34, 28},
+	{5040, 24,  90, 24, 22, 23, 43, 21, 18, 34, 28},
+	{5030, 24,  90, 24, 22, 23, 43, 21, 18, 34, 28},
+	{5020, 24,  90, 24, 22, 23, 43, 21, 18, 34, 28},
+	{5010, 24,  90, 24, 22, 23, 43, 21, 18, 34, 28},
+	{5000, 24,  89, 23, 21, 23, 43, 21, 18, 34, 28},
+	{4990, 24,  89, 23, 21, 23, 43, 21, 18, 34, 28},
+	{4980, 24,  89, 23, 21, 23, 42, 21, 18, 34, 28},
+	{4970, 24,  89, 23, 21, 23, 42, 21, 18, 34, 28},
+	{4960, 24,  89, 23, 21, 23, 42, 20, 18, 34, 28},
+	{4950, 24,  88, 23, 21, 23, 42, 20, 18, 34, 28},
+	{4940, 24,  88, 23, 21, 23, 42, 20, 18, 33, 28},
+	{4930, 24,  88, 23, 21, 23, 42, 20, 18, 33, 28},
+	{4920, 24,  88, 23, 21, 23, 42, 20, 18, 33, 28},
+	{4910, 24,  87, 23, 21, 23, 41, 20, 18, 33, 28},
+	{4900, 24,  87, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4890, 24,  87, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4880, 24,  87, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4870, 24,  86, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4860, 24,  86, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4850, 23,  87, 23, 21, 23, 41, 20, 18, 33, 27},
+	{4840, 23,  87, 23, 21, 23, 40, 20, 18, 33, 27},
+	{4830, 23,  86, 23, 21, 22, 41, 20, 18, 33, 27},
+	{4820, 23,  86, 23, 21, 22, 41, 20, 18, 33, 27},
+	{4810, 23,  86, 23, 21, 22, 41, 20, 18, 33, 27},
+	{4800, 23,  86, 22, 21, 22, 41, 20, 17, 32, 27},
+	{4790, 23,  86, 22, 21, 22, 41, 20, 17, 32, 27},
+	{4780, 23,  85, 22, 21, 22, 41, 20, 17, 32, 27},
+	{4770, 23,  85, 22, 21, 22, 41, 20, 17, 32, 27},
+	{4760, 23,  85, 22, 20, 22, 40, 20, 17, 32, 27},
+	{4750, 23,  85, 22, 20, 22, 40, 20, 17, 32, 27},
+	{4740, 23,  84, 22, 20, 22, 40, 20, 17, 32, 26},
+	{4730, 23,  84, 22, 20, 22, 40, 19, 17, 32, 26},
+	{4720, 23,  84, 22, 20, 22, 40, 19, 17, 32, 26},
+	{4710, 23,  84, 22, 20, 22, 40, 19, 17, 32, 26},
+	{4700, 23,  83, 22, 20, 22, 40, 19, 17, 32, 26},
+	{4690, 23,  83, 22, 20, 22, 39, 19, 17, 32, 26},
+	{4680, 23,  83, 22, 20, 22, 39, 19, 17, 32, 26},
+	{4670, 23,  83, 22, 20, 22, 39, 19, 17, 32, 26},
+	{4660, 23,  82, 22, 20, 22, 39, 19, 17, 32, 26},
+	{4650, 22,  83, 22, 20, 22, 39, 19, 17, 31, 26},
+	{4640, 22,  83, 22, 20, 22, 39, 19, 17, 31, 26},
+	{4630, 22,  83, 22, 20, 22, 39, 19, 17, 31, 26},
+	{4620, 22,  83, 22, 20, 21, 39, 19, 17, 31, 26},
+	{4610, 22,  82, 22, 20, 21, 39, 19, 17, 31, 26},
+	{4600, 22,  82, 21, 20, 21, 39, 19, 17, 31, 26},
+	{4590, 22,  82, 21, 20, 21, 39, 19, 17, 31, 26},
+	{4580, 22,  82, 21, 20, 21, 39, 19, 17, 31, 26},
+	{4570, 22,  81, 21, 20, 21, 39, 19, 17, 31, 25},
+	{4560, 22,  81, 21, 20, 21, 39, 19, 17, 31, 25},
+	{4550, 22,  81, 21, 20, 21, 38, 19, 17, 31, 25},
+	{4540, 22,  81, 21, 20, 21, 38, 19, 17, 31, 25},
+	{4530, 22,  80, 21, 19, 21, 38, 19, 16, 31, 25},
+	{4520, 22,  80, 21, 19, 21, 38, 19, 16, 31, 25},
+	{4510, 22,  80, 21, 19, 21, 38, 19, 16, 31, 25},
+	{4500, 22,  80, 21, 19, 21, 38, 19, 16, 30, 25},
+	{4490, 22,  80, 21, 19, 21, 38, 18, 16, 30, 25},
+	{4480, 22,  79, 21, 19, 21, 38, 18, 16, 30, 25},
+	{4470, 22,  79, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4460, 22,  79, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4450, 21,  80, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4440, 21,  79, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4430, 21,  79, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4420, 21,  79, 21, 19, 21, 37, 18, 16, 30, 25},
+	{4410, 21,  79, 21, 19, 20, 38, 18, 16, 30, 25},
+	{4400, 21,  78, 20, 19, 20, 37, 18, 16, 30, 24},
+	{4390, 21,  78, 20, 19, 20, 37, 18, 16, 30, 24},
+	{4380, 21,  78, 20, 19, 20, 37, 18, 16, 30, 24},
+	{4370, 21,  78, 20, 19, 20, 37, 18, 16, 30, 24},
+	{4360, 21,  77, 20, 19, 20, 37, 18, 16, 29, 24},
+	{4350, 21,  77, 20, 19, 20, 37, 18, 16, 29, 24},
+	{4340, 21,  77, 20, 19, 20, 37, 18, 16, 29, 24},
+	{4330, 21,  77, 20, 19, 20, 36, 18, 16, 29, 24},
+	{4320, 21,  77, 20, 19, 20, 36, 18, 16, 29, 24},
+	{4310, 21,  76, 20, 19, 20, 36, 18, 16, 29, 24},
+	{4300, 21,  76, 20, 18, 20, 36, 18, 16, 29, 24},
+	{4290, 21,  76, 20, 18, 20, 36, 18, 16, 29, 24},
+	{4280, 21,  76, 20, 18, 20, 36, 18, 16, 29, 24},
+	{4270, 21,  75, 20, 18, 20, 36, 18, 16, 29, 24},
+	{4260, 21,  75, 20, 18, 20, 35, 17, 15, 29, 24},
+	{4250, 20,  76, 20, 18, 20, 35, 17, 15, 29, 24},
+	{4240, 20,  76, 20, 18, 20, 35, 17, 15, 29, 23},
+	{4230, 20,  75, 20, 18, 20, 35, 17, 15, 29, 23},
+	{4220, 20,  75, 20, 18, 20, 35, 17, 15, 29, 23},
+	{4210, 20,  75, 20, 18, 20, 35, 17, 15, 28, 23},
+	{4200, 20,  75, 19, 18, 19, 36, 17, 15, 28, 23},
+	{4190, 20,  74, 19, 18, 19, 36, 17, 15, 28, 23},
+	{4180, 20,  74, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4170, 20,  74, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4160, 20,  74, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4150, 20,  74, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4140, 20,  73, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4130, 20,  73, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4120, 20,  73, 19, 18, 19, 35, 17, 15, 28, 23},
+	{4110, 20,  73, 19, 18, 19, 34, 17, 15, 28, 23},
+	{4100, 20,  72, 19, 18, 19, 34, 17, 15, 28, 23},
+	{4090, 20,  72, 19, 18, 19, 34, 17, 15, 28, 23},
+	{4080, 20,  72, 19, 18, 19, 34, 17, 15, 28, 23},
+	{4070, 20,  72, 19, 18, 19, 34, 17, 15, 27, 22},
+	{4060, 19,  72, 19, 17, 19, 34, 17, 15, 27, 22},
+	{4050, 19,  72, 19, 17, 19, 34, 17, 15, 27, 22},
+	{4040, 19,  72, 19, 17, 19, 33, 17, 15, 27, 22},
+	{4030, 19,  72, 19, 17, 19, 33, 17, 15, 27, 22},
+	{4020, 19,  71, 19, 17, 19, 33, 16, 15, 27, 22},
+	{4010, 19,  71, 19, 17, 19, 33, 16, 15, 27, 22},
+	{4000, 19,  71, 18, 17, 19, 33, 16, 14, 27, 22},
+	{3990, 19,  71, 18, 17, 18, 34, 16, 14, 27, 22},
+	{3980, 19,  71, 18, 17, 18, 34, 16, 14, 27, 22},
+	{3970, 19,  70, 18, 17, 18, 33, 16, 14, 27, 22},
+	{3960, 19,  70, 18, 17, 18, 33, 16, 14, 27, 22},
+	{3950, 19,  70, 18, 17, 18, 33, 16, 14, 27, 22},
+	{3940, 19,  70, 18, 17, 18, 33, 16, 14, 27, 22},
+	{3930, 19,  69, 18, 17, 18, 33, 16, 14, 27, 22},
+	{3920, 19,  69, 18, 17, 18, 33, 16, 14, 26, 22},
+	{3910, 19,  69, 18, 17, 18, 33, 16, 14, 26, 22},
+	{3900, 19,  69, 18, 17, 18, 33, 16, 14, 26, 21},
+	{3890, 19,  68, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3880, 19,  68, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3870, 19,  68, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3860, 18,  69, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3850, 18,  68, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3840, 18,  68, 18, 17, 18, 32, 16, 14, 26, 21},
+	{3830, 18,  68, 18, 16, 18, 32, 16, 14, 26, 21},
+	{3820, 18,  68, 18, 16, 18, 31, 16, 14, 26, 21},
+	{3810, 18,  68, 18, 16, 18, 31, 16, 14, 26, 21},
+	{3800, 18,  67, 17, 16, 18, 31, 16, 14, 26, 21},
+	{3790, 18,  67, 17, 16, 17, 32, 15, 14, 26, 21},
+	{3780, 18,  67, 17, 16, 17, 32, 15, 14, 25, 21},
+	{3770, 18,  67, 17, 16, 17, 32, 15, 14, 25, 21},
+	{3760, 18,  66, 17, 16, 17, 32, 15, 14, 25, 21},
+	{3750, 18,  66, 17, 16, 17, 31, 15, 14, 25, 21},
+	{3740, 18,  66, 17, 16, 17, 31, 15, 14, 25, 20},
+	{3730, 18,  66, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3720, 18,  65, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3710, 18,  65, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3700, 18,  65, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3690, 18,  65, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3680, 18,  64, 17, 16, 17, 31, 15, 13, 25, 20},
+	{3670, 18,  64, 17, 16, 17, 30, 15, 13, 25, 20},
+	{3660, 17,  65, 17, 16, 17, 30, 15, 13, 25, 20},
+	{3650, 17,  65, 17, 16, 17, 30, 15, 13, 25, 20},
+	{3640, 17,  65, 17, 16, 17, 30, 15, 13, 25, 20},
+	{3630, 17,  64, 17, 16, 17, 30, 15, 13, 24, 20},
+	{3620, 17,  64, 17, 16, 17, 30, 15, 13, 24, 20},
+	{3610, 17,  64, 17, 16, 17, 30, 15, 13, 24, 20},
+	{3600, 17,  64, 16, 16, 17, 29, 15, 13, 24, 20},
+	{3590, 17,  63, 16, 15, 17, 29, 15, 13, 24, 20},
+	{3580, 17,  63, 16, 15, 16, 30, 15, 13, 24, 20},
+	{3570, 17,  63, 16, 15, 16, 30, 15, 13, 24, 19},
+	{3560, 17,  63, 16, 15, 16, 30, 14, 13, 24, 19},
+	{3550, 17,  62, 16, 15, 16, 30, 14, 13, 24, 19},
+	{3540, 17,  62, 16, 15, 16, 30, 14, 13, 24, 19},
+	{3530, 17,  62, 16, 15, 16, 29, 14, 13, 24, 19},
+	{3520, 17,  62, 16, 15, 16, 29, 14, 13, 24, 19},
+	{3510, 17,  62, 16, 15, 16, 29, 14, 13, 24, 19},
+	{3500, 17,  61, 16, 15, 16, 29, 14, 13, 24, 19},
+	{3490, 17,  61, 16, 15, 16, 29, 14, 13, 23, 19},
+	{3480, 17,  61, 16, 15, 16, 29, 14, 13, 23, 19},
+	{3470, 17,  61, 16, 15, 16, 29, 14, 13, 23, 19},
+	{3460, 16,  61, 16, 15, 16, 28, 14, 12, 23, 19},
+	{3450, 16,  61, 16, 15, 16, 28, 14, 12, 23, 19},
+	{3440, 16,  61, 16, 15, 16, 28, 14, 12, 23, 19},
+	{3430, 16,  61, 16, 15, 16, 28, 14, 12, 23, 19},
+	{3420, 16,  60, 16, 15, 16, 28, 14, 12, 23, 19},
+	{3410, 16,  60, 16, 15, 16, 28, 14, 12, 23, 18},
+	{3400, 16,  60, 15, 15, 16, 28, 14, 12, 23, 18},
+	{3390, 16,  60, 15, 15, 16, 28, 14, 12, 23, 18},
+	{3380, 16,  59, 15, 15, 16, 27, 14, 12, 23, 18},
+	{3370, 16,  59, 15, 15, 15, 28, 14, 12, 23, 18},
+	{3360, 16,  59, 15, 14, 15, 28, 14, 12, 23, 18},
+	{3350, 16,  59, 15, 14, 15, 28, 14, 12, 23, 18},
+	{3340, 16,  59, 15, 14, 15, 28, 14, 12, 22, 18},
+	{3330, 16,  58, 15, 14, 15, 28, 14, 12, 22, 18},
+	{3320, 16,  58, 15, 14, 15, 28, 13, 12, 22, 18},
+	{3310, 16,  58, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3300, 16,  58, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3290, 16,  57, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3280, 16,  57, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3270, 16,  57, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3260, 15,  58, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3250, 15,  57, 15, 14, 15, 27, 13, 12, 22, 18},
+	{3240, 15,  57, 15, 14, 15, 26, 13, 12, 22, 17},
+	{3230, 15,  57, 15, 14, 15, 26, 13, 12, 22, 17},
+	{3220, 15,  57, 15, 14, 15, 26, 13, 12, 22, 17},
+	{3210, 15,  56, 15, 14, 15, 26, 13, 12, 22, 17},
+	{3200, 15,  56, 14, 14, 15, 26, 13, 11, 21, 17},
+	{3190, 15,  56, 14, 14, 15, 26, 13, 11, 21, 17},
+	{3180, 15,  56, 14, 14, 15, 26, 13, 11, 21, 17},
+	{3170, 15,  56, 14, 14, 15, 25, 13, 11, 21, 17},
+	{3160, 15,  55, 14, 14, 14, 26, 13, 11, 21, 17},
+	{3150, 15,  55, 14, 14, 14, 26, 13, 11, 21, 17},
+	{3140, 15,  55, 14, 14, 14, 26, 13, 11, 21, 17},
+	{3130, 15,  55, 14, 14, 14, 26, 13, 11, 21, 17},
+	{3120, 15,  54, 14, 13, 14, 26, 13, 11, 21, 17},
+	{3110, 15,  54, 14, 13, 14, 26, 13, 11, 21, 17},
+	{3100, 15,  54, 14, 13, 14, 26, 13, 11, 21, 17},
+	{3090, 15,  54, 14, 13, 14, 25, 12, 11, 21, 17},
+	{3080, 15,  53, 14, 13, 14, 25, 12, 11, 21, 17},
+	{3070, 14,  54, 14, 13, 14, 25, 12, 11, 21, 16},
+	{3060, 14,  54, 14, 13, 14, 25, 12, 11, 21, 16},
+	{3050, 14,  54, 14, 13, 14, 25, 12, 11, 20, 16},
+	{3040, 14,  53, 14, 13, 14, 25, 12, 11, 20, 16},
+	{3030, 14,  53, 14, 13, 14, 25, 12, 11, 20, 16},
+	{3020, 14,  53, 14, 13, 14, 24, 12, 11, 20, 16},
+	{3010, 14,  53, 14, 13, 14, 24, 12, 11, 20, 16},
+	{3000, 14,  53, 13, 13, 14, 24, 12, 11, 20, 16},
+	{2990, 14,  52, 13, 13, 14, 24, 12, 11, 20, 16},
+	{2980, 14,  52, 13, 13, 14, 24, 12, 11, 20, 16},
+	{2970, 14,  52, 13, 13, 14, 24, 12, 11, 20, 16},
+	{2960, 14,  52, 13, 13, 14, 24, 12, 11, 20, 16},
+	{2950, 14,  51, 13, 13, 13, 24, 12, 11, 20, 16},
+	{2940, 14,  51, 13, 13, 13, 24, 12, 11, 20, 16},
+	{2930, 14,  51, 13, 13, 13, 24, 12, 10, 20, 16},
+	{2920, 14,  51, 13, 13, 13, 24, 12, 10, 20, 16},
+	{2910, 14,  50, 13, 13, 13, 24, 12, 10, 20, 15},
+	{2900, 14,  50, 13, 13, 13, 24, 12, 10, 19, 15},
+	{2890, 14,  50, 13, 12, 13, 24, 12, 10, 19, 15},
+	{2880, 14,  50, 13, 12, 13, 23, 12, 10, 19, 15},
+	{2870, 13,  50, 13, 12, 13, 23, 12, 10, 19, 15},
+	{2860, 13,  50, 13, 12, 13, 23, 12, 10, 19, 15},
+	{2850, 13,  50, 13, 12, 13, 23, 11, 10, 19, 15},
+	{2840, 13,  50, 13, 12, 13, 23, 11, 10, 19, 15},
+	{2830, 13,  50, 13, 12, 13, 23, 11, 10, 19, 15},
+	{2820, 13,  49, 13, 12, 13, 23, 11, 10, 19, 15},
+	{2810, 13,  49, 13, 12, 13, 23, 11, 10, 19, 15},
+	{2800, 13,  49, 12, 12, 13, 22, 11, 10, 19, 15},
+	{2790, 13,  49, 12, 12, 13, 22, 11, 10, 19, 15},
+	{2780, 13,  48, 12, 12, 13, 22, 11, 10, 19, 15},
+	{2770, 13,  48, 12, 12, 13, 22, 11, 10, 19, 15},
+	{2760, 13,  48, 12, 12, 13, 22, 11, 10, 18, 15},
+	{2750, 13,  48, 12, 12, 13, 22, 11, 10, 18, 15},
+	{2740, 13,  47, 12, 12, 12, 23, 11, 10, 18, 14},
+	{2730, 13,  47, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2720, 13,  47, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2710, 13,  47, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2700, 13,  47, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2690, 13,  46, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2680, 13,  46, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2670, 12,  47, 12, 12, 12, 22, 11, 10, 18, 14},
+	{2660, 12,  47, 12, 12, 12, 21, 11,  9, 18, 14},
+	{2650, 12,  46, 12, 11, 12, 21, 11,  9, 18, 14},
+	{2640, 12,  46, 12, 11, 12, 21, 11,  9, 18, 14},
+	{2630, 12,  46, 12, 11, 12, 21, 11,  9, 18, 14},
+	{2620, 12,  46, 12, 11, 12, 21, 10,  9, 18, 14},
+	{2610, 12,  45, 12, 11, 12, 21, 10,  9, 17, 14},
+	{2600, 12,  45, 11, 11, 12, 21, 10,  9, 17, 14},
+	{2590, 12,  45, 11, 11, 12, 20, 10,  9, 17, 14},
+	{2580, 12,  45, 11, 11, 12, 20, 10,  9, 17, 14},
+	{2570, 12,  44, 11, 11, 12, 20, 10,  9, 17, 13},
+	{2560, 12,  44, 11, 11, 12, 20, 10,  9, 17, 13},
+	{2550, 12,  44, 11, 11, 12, 20, 10,  9, 17, 13},
+	{2540, 12,  44, 11, 11, 11, 21, 10,  9, 17, 13},
+	{2530, 12,  44, 11, 11, 11, 21, 10,  9, 17, 13},
+	{2520, 12,  43, 11, 11, 11, 21, 10,  9, 17, 13},
+	{2510, 12,  43, 11, 11, 11, 20, 10,  9, 17, 13},
+	{2500, 12,  43, 11, 11, 11, 20, 10,  9, 17, 13},
+	{2490, 12,  43, 11, 11, 11, 20, 10,  9, 17, 13},
+	{2480, 12,  42, 11, 11, 11, 20, 10,  9, 17, 13},
+	{2470, 11,  43, 11, 11, 11, 20, 10,  9, 16, 13},
+	{2460, 11,  43, 11, 11, 11, 20, 10,  9, 16, 13},
+	{2450, 11,  43, 11, 11, 11, 20, 10,  9, 16, 13},
+	{2440, 11,  42, 11, 11, 11, 19, 10,  9, 16, 13},
+	{2430, 11,  42, 11, 11, 11, 19, 10,  9, 16, 13},
+	{2420, 11,  42, 11, 10, 11, 19, 10,  9, 16, 13},
+	{2410, 11,  42, 11, 10, 11, 19, 10,  9, 16, 12},
+	{2400, 11,  41, 10, 10, 11, 19, 10,  8, 16, 12},
+	{2390, 11,  41, 10, 10, 11, 19, 10,  8, 16, 12},
+	{2380, 11,  41, 10, 10, 11, 19,  9,  8, 16, 12},
+	{2370, 11,  41, 10, 10, 11, 18,  9,  8, 16, 12},
+	{2360, 11,  41, 10, 10, 11, 18,  9,  8, 16, 12},
+	{2350, 11,  40, 10, 10, 11, 18,  9,  8, 16, 12},
+	{2340, 11,  40, 10, 10, 11, 18,  9,  8, 16, 12},
+	{2330, 11,  40, 10, 10, 10, 19,  9,  8, 16, 12},
+	{2320, 11,  40, 10, 10, 10, 19,  9,  8, 15, 12},
+	{2310, 11,  39, 10, 10, 10, 19,  9,  8, 15, 12},
+	{2300, 11,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2290, 11,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2280, 11,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2270, 10,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2260, 10,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2250, 10,  39, 10, 10, 10, 18,  9,  8, 15, 12},
+	{2240, 10,  39, 10, 10, 10, 18,  9,  8, 15, 11},
+	{2230, 10,  38, 10, 10, 10, 18,  9,  8, 15, 11},
+	{2220, 10,  38, 10, 10, 10, 17,  9,  8, 15, 11},
+	{2210, 10,  38, 10, 10, 10, 17,  9,  8, 15, 11},
+	{2200, 10,  38,  9, 10, 10, 17,  9,  8, 15, 11},
+	{2190, 10,  38,  9,  9, 10, 17,  9,  8, 15, 11},
+	{2180, 10,  37,  9,  9, 10, 17,  9,  8, 14, 11},
+	{2170, 10,  37,  9,  9, 10, 17,  9,  8, 14, 11},
+	{2160, 10,  37,  9,  9, 10, 17,  9,  8, 14, 11},
+	{2150, 10,  37,  9,  9, 10, 16,  8,  8, 14, 11},
+	{2140, 10,  36,  9,  9, 10, 16,  8,  8, 14, 11},
+	{2130, 10,  36,  9,  9, 10, 16,  8,  7, 14, 11},
+	{2120, 10,  36,  9,  9,  9, 17,  8,  7, 14, 11},
+	{2110, 10,  36,  9,  9,  9, 17,  8,  7, 14, 11},
+	{2100, 10,  35,  9,  9,  9, 17,  8,  7, 14, 11},
+	{2090, 10,  35,  9,  9,  9, 17,  8,  7, 14, 11},
+	{2080,  9,  36,  9,  9,  9, 16,  8,  7, 14, 11},
+	{2070,  9,  36,  9,  9,  9, 16,  8,  7, 14, 10},
+	{2060,  9,  35,  9,  9,  9, 16,  8,  7, 14, 10},
+	{2050,  9,  35,  9,  9,  9, 16,  8,  7, 14, 10},
+	{2040,  9,  35,  9,  9,  9, 16,  8,  7, 14, 10},
+	{2030,  9,  35,  9,  9,  9, 16,  8,  7, 13, 10},
+	{2020,  9,  35,  9,  9,  9, 16,  8,  7, 13, 10},
+	{2010,  9,  34,  9,  9,  9, 15,  8,  7, 13, 10},
+	{2000,  9,  34,  8,  9,  9, 15,  8,  7, 13, 10},
+	{1990,  9,  34,  8,  9,  9, 15,  8,  7, 13, 10},
+	{1980,  9,  34,  8,  9,  9, 15,  8,  7, 13, 10},
+	{1970,  9,  33,  8,  9,  9, 15,  8,  7, 13, 10},
+	{1960,  9,  33,  8,  9,  9, 15,  8,  7, 13, 10},
+	{1950,  9,  33,  8,  8,  9, 15,  8,  7, 13, 10},
+	{1940,  9,  33,  8,  8,  9, 15,  8,  7, 13, 10},
+	{1930,  9,  32,  8,  8,  9, 14,  8,  7, 13, 10},
+	{1920,  9,  32,  8,  8,  9, 14,  8,  7, 13, 10},
+	{1910,  9,  32,  8,  8,  8, 15,  7,  7, 13,  9},
+	{1900,  9,  32,  8,  8,  8, 15,  7,  7, 13,  9},
+	{1890,  9,  31,  8,  8,  8, 15,  7,  7, 12,  9},
+	{1880,  8,  32,  8,  8,  8, 15,  7,  7, 12,  9},
+	{1870,  8,  32,  8,  8,  8, 15,  7,  7, 12,  9},
+	{1860,  8,  32,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1850,  8,  32,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1840,  8,  31,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1830,  8,  31,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1820,  8,  31,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1810,  8,  31,  8,  8,  8, 14,  7,  6, 12,  9},
+	{1800,  8,  30,  7,  8,  8, 14,  7,  6, 12,  9},
+	{1790,  8,  30,  7,  8,  8, 13,  7,  6, 12,  9},
+	{1780,  8,  30,  7,  8,  8, 13,  7,  6, 12,  9},
+	{1770,  8,  30,  7,  8,  8, 13,  7,  6, 12,  9},
+	{1760,  8,  29,  7,  8,  8, 13,  7,  6, 12,  9},
+	{1750,  8,  29,  7,  8,  8, 13,  7,  6, 12,  9},
+	{1740,  8,  29,  7,  8,  8, 13,  7,  6, 11,  8},
+	{1730,  8,  29,  7,  8,  8, 13,  7,  6, 11,  8},
+	{1720,  8,  29,  7,  7,  8, 13,  7,  6, 11,  8},
+	{1710,  8,  28,  7,  7,  8, 12,  7,  6, 11,  8},
+	{1700,  8,  28,  7,  7,  7, 13,  7,  6, 11,  8},
+	{1690,  8,  28,  7,  7,  7, 13,  7,  6, 11,  8},
+	{1680,  7,  29,  7,  7,  7, 13,  6,  6, 11,  8},
+	{1670,  7,  28,  7,  7,  7, 13,  6,  6, 11,  8},
+	{1660,  7,  28,  7,  7,  7, 13,  6,  6, 11,  8},
+	{1650,  7,  28,  7,  7,  7, 13,  6,  6, 11,  8},
+	{1640,  7,  28,  7,  7,  7, 12,  6,  6, 11,  8},
+	{1630,  7,  27,  7,  7,  7, 12,  6,  6, 11,  8},
+	{1620,  7,  27,  7,  7,  7, 12,  6,  6, 11,  8},
+	{1610,  7,  27,  7,  7,  7, 12,  6,  6, 11,  8},
+	{1600,  7,  27,  6,  7,  7, 12,  6,  5, 10,  8},
+	{1590,  7,  26,  6,  7,  7, 12,  6,  5, 10,  8},
+	{1580,  7,  26,  6,  7,  7, 12,  6,  5, 10,  7},
+	{1570,  7,  26,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1560,  7,  26,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1550,  7,  26,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1540,  7,  25,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1530,  7,  25,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1520,  7,  25,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1510,  7,  25,  6,  7,  7, 11,  6,  5, 10,  7},
+	{1500,  7,  24,  6,  7,  7, 10,  6,  5, 10,  7},
+	{1490, 59,  25,  6, 77, 59, 10, 70, 44,  9, 73},
+	{1480, 59,  24,  6, 76, 58, 10, 70, 44,  9, 73},
+	{1470, 58,  24,  6, 76, 58, 10, 69, 44,  9, 72},
+	{1460, 58,  24,  6, 76, 58, 10, 69, 43,  9, 72},
+	{1450, 58,  24,  6, 75, 57, 10, 68, 43,  9, 71},
+	{1440, 57,  24,  6, 75, 57, 10, 68, 43,  9, 71},
+	{1430, 57,  23,  6, 75, 57, 10, 68, 43,  8, 70},
+	{1420, 56,  23,  6, 74, 57,  9, 67, 43,  8, 70},
+	{1410, 56,  23,  6, 74, 57,  9, 67, 43,  8, 69},
+	{1400, 56,  23,  5, 74, 55,  9, 67, 41,  8, 69},
+	{1390, 55,  23,  5, 73, 55,  9, 66, 41,  8, 68},
+	{1380, 55,  23,  5, 73, 54,  9, 66, 41,  8, 68},
+	{1370, 54,  22,  5, 72, 54,  9, 66, 41,  8, 67},
+	{1360, 54,  22,  5, 72, 54,  9, 65, 40,  8, 67},
+	{1350, 54,  22,  5, 72, 53,  9, 65, 40,  8, 66},
+	{1340, 53,  22,  5, 71, 53,  9, 65, 40,  8, 66},
+	{1330, 53,  22,  5, 71, 53,  9, 64, 39,  8, 65},
+	{1320, 52,  22,  5, 71, 53,  8, 64, 40,  8, 65},
+	{1310, 52,  21,  5, 70, 53,  8, 64, 40,  8, 64},
+	{1300, 51,  21,  5, 70, 51,  8, 63, 38,  8, 64},
+	{1290, 51,  21,  5, 70, 51,  8, 63, 38,  7, 64},
+	{1280, 51,  21,  5, 69, 51,  8, 63, 38,  7, 63},
+	{1270, 50,  21,  5, 69, 50,  8, 62, 38,  7, 63},
+	{1260, 50,  20,  5, 69, 50,  8, 62, 37,  7, 62},
+	{1250, 49,  20,  5, 68, 49,  8, 62, 37,  7, 62},
+	{1240, 49,  20,  5, 68, 49,  8, 61, 37,  7, 61},
+	{1230, 49,  20,  5, 68, 49,  8, 61, 36,  7, 61},
+	{1220, 48,  20,  5, 67, 48,  8, 61, 36,  7, 60},
+	{1210, 48,  19,  5, 67, 48,  7, 60, 36,  7, 60},
+	{1200, 49,  19,  4, 67, 49,  7, 60, 36,  7, 59},
+	{1190, 48,  19,  4, 66, 48,  7, 60, 36,  7, 59},
+	{1180, 48,  19,  4, 66, 48,  7, 59, 36,  7, 58},
+	{1170, 46,  19,  4, 66, 46,  7, 59, 35,  7, 58},
+	{1160, 46,  18,  4, 65, 46,  7, 59, 34,  7, 57},
+	{1150, 45,  18,  4, 65, 46,  7, 58, 34,  7, 57},
+	{1140, 45,  18,  4, 65, 45,  7, 58, 34,  6, 56},
+	{1130, 45,  18,  4, 64, 45,  7, 58, 33,  6, 56},
+	{1120, 44,  18,  4, 64, 44,  7, 57, 33,  6, 55},
+	{1110, 44,  18,  4, 64, 44,  7, 57, 33,  6, 55},
+	{1100, 43,  17,  4, 63, 44,  6, 57, 32,  6, 54},
+	{1090, 43,  17,  4, 63, 44,  6, 56, 33,  6, 54},
+	{1080, 43,  17,  4, 63, 44,  6, 56, 33,  6, 53},
+	{1070, 42,  17,  4, 62, 44,  6, 56, 33,  6, 53},
+	{1060, 42,  17,  4, 62, 42,  6, 55, 31,  6, 52},
+	{1050, 41,  17,  4, 62, 42,  6, 55, 31,  6, 52},
+	{1040, 41,  16,  4, 61, 41,  6, 54, 31,  6, 52},
+	{1030, 41,  16,  4, 61, 41,  6, 54, 30,  6, 51},
+	{1020, 40,  16,  4, 61, 41,  6, 54, 30,  6, 51},
+	{1010, 40,  16,  4, 60, 40,  6, 53, 30,  6, 50},
+	{1000, 39,  16,  3, 60, 40,  6, 53, 29,  5, 50},
+	{ 990, 39,  15,  3, 60, 39,  6, 53, 29,  5, 49},
+	{ 980, 39,  15,  3, 59, 39,  5, 52, 29,  5, 49},
+	{ 970, 38,  15,  3, 59, 39,  5, 52, 29,  5, 48},
+	{ 960, 38,  15,  3, 59, 39,  5, 52, 29,  5, 48},
+	{ 950, 37,  15,  3, 58, 39,  5, 51, 29,  5, 47},
+	{ 940, 37,  14,  3, 58, 39,  5, 51, 29,  5, 47},
+	{ 930, 37,  14,  3, 57, 37,  5, 51, 27,  5, 46},
+	{ 920, 36,  14,  3, 57, 37,  5, 50, 27,  5, 46},
+	{ 910, 36,  14,  3, 57, 36,  5, 50, 27,  5, 45},
+	{ 900, 35,  14,  3, 56, 36,  5, 50, 26,  5, 45},
+	{ 890, 35,  14,  3, 56, 36,  5, 49, 26,  5, 44},
+	{ 880, 35,  13,  3, 56, 35,  5, 49, 26,  5, 44},
+	{ 870, 34,  13,  3, 55, 35,  4, 49, 26,  5, 43},
+	{ 860, 34,  13,  3, 55, 35,  4, 48, 25,  5, 43},
+	{ 850, 33,  13,  3, 55, 35,  4, 48, 26,  4, 42},
+	{ 840, 33,  13,  3, 54, 35,  4, 48, 26,  4, 42},
+	{ 830, 33,  12,  3, 54, 33,  4, 47, 24,  4, 41},
+	{ 820, 32,  12,  3, 54, 33,  4, 47, 24,  4, 41},
+	{ 810, 32,  12,  3, 53, 33,  4, 47, 24,  4, 40},
+	{ 800, 31,  12,  2, 53, 32,  4, 46, 23,  4, 40},
+	{ 790, 31,  12,  2, 53, 32,  4, 46, 23,  4, 39},
+	{ 780, 30,  12,  2, 52, 31,  4, 46, 23,  4, 39},
+	{ 770, 30,  11,  2, 52, 31,  4, 45, 23,  4, 39},
+	{ 760, 30,  11,  2, 52, 31,  3, 45, 22,  4, 38},
+	{ 750, 29,  11,  2, 51, 30,  3, 45, 22,  4, 38},
+	{ 740, 29,  11,  2, 51, 30,  3, 44, 22,  4, 37},
+	{ 730, 28,  11,  2, 51, 31,  3, 44, 22,  4, 37},
+	{ 720, 28,  10,  2, 50, 30,  3, 44, 22,  4, 36},
+	{ 710, 28,  10,  2, 50, 30,  3, 43, 22,  4, 36},
+	{ 700, 27,  10,  2, 50, 28,  3, 43, 20,  3, 35},
+	{ 690, 27,  10,  2, 49, 28,  3, 43, 20,  3, 35},
+	{ 680, 26,  10,  2, 49, 28,  3, 42, 20,  3, 34},
+	{ 670, 26,  10,  2, 49, 27,  3, 42, 20,  3, 34},
+	{ 660, 26,   9,  2, 48, 27,  3, 42, 19,  3, 33},
+	{ 650, 25,   9,  2, 48, 26,  3, 41, 19,  3, 33},
+	{ 640, 25,   9,  2, 48, 26,  2, 41, 19,  3, 32},
+	{ 630, 24,   9,  2, 47, 26,  2, 40, 18,  3, 32},
+	{ 620, 24,   9,  2, 47, 26,  2, 40, 19,  3, 31},
+	{ 610, 24,   8,  2, 47, 26,  2, 40, 19,  3, 31},
+	{ 600, 23,   8,  1, 46, 26,  2, 39, 18,  3, 30},
+	{ 590, 23,   8,  1, 46, 24,  2, 39, 17,  3, 30},
+	{ 580, 22,   8,  1, 46, 24,  2, 39, 17,  3, 29},
+	{ 570, 22,   8,  1, 45, 23,  2, 38, 17,  3, 29},
+	{ 560, 22,   7,  1, 45, 23,  2, 38, 16,  2, 28},
+	{ 550, 21,   7,  1, 45, 23,  2, 38, 16,  2, 28},
+	{ 540, 21,   7,  1, 44, 22,  2, 37, 16,  2, 27},
+	{ 530, 20,   7,  1, 44, 22,  1, 37, 15,  2, 27},
+	{ 520, 20,   7,  1, 43, 21,  1, 37, 15,  2, 27},
+	{ 510, 20,   6,  1, 43, 21,  1, 36, 15,  2, 26},
+	{ 500, 19,   6,  1, 43, 22,  1, 36, 15,  2, 26},
+	{ 490, 19,   6,  1, 42, 21,  1, 36, 15,  2, 25},
+	{ 480, 18,   6,  1, 42, 21,  1, 35, 15,  2, 25},
+	{ 470, 18,   6,  1, 42, 21,  1, 35, 15,  2, 24},
+	{ 460, 18,   6,  1, 41, 19,  1, 35, 13,  2, 24},
+	{ 450, 17,   5,  1, 41, 19,  1, 34, 13,  2, 23},
+	{ 440, 17,   5,  1, 41, 18,  1, 34, 13,  2, 23},
+	{ 430, 16,   5,  1, 40, 18,  0, 34, 12,  2, 22},
+	{ 420, 16,   5,  1, 40, 18,  0, 33, 12,  2, 22},
+	{ 410, 16,   5,  1, 40, 17,  0, 33, 12,  1, 21},
+	{ 400, 15,   5,  0, 39, 17,  0, 33, 11,  1, 21},
+	{ 390, 15,   4,  0, 39, 17,  0, 32, 12,  1, 20},
+	{ 380, 14,   4,  0, 39, 17,  0, 32, 12,  1, 20},
+	{ 370, 14,   4,  0, 38, 17,  0, 32, 12,  1, 19},
+	{ 360, 14,   4,  0, 38, 15,  0, 31, 10,  1, 19},
+	{ 350, 13,   4,  0, 38, 15,  0, 31, 10,  1, 18},
+	{ 340, 13,   3,  0, 37, 15,  0, 31, 10,  1, 18},
+	{ 330, 12,   3,  0, 37, 14,  0, 30,  9,  1, 17},
+	{ 320, 12,   3,  0, 37, 14,  0, 30,  9,  1, 17},
+	{ 310, 12,   3,  0, 36, 13,  0, 30,  9,  1, 16},
+	{ 300, 11,   3,  0, 36, 13,  0, 29,  8,  1, 16},
+	{ 290, 11,   2,  0, 36, 13,  0, 29,  8,  1, 15},
+	{ 280, 10,   2,  0, 35, 12,  0, 29,  8,  1, 15},
+	{ 270, 10,   2,  0, 35, 12,  0, 28,  8,  0, 14},
+	{ 260,  9,   2,  0, 35, 12,  0, 28,  8,  0, 14},
+	{ 250,  9,   2,  0, 34, 12,  0, 28,  8,  0, 14},
+	{ 240,  9,   2,  0, 34, 12,  0, 27,  8,  0, 13},
+	{ 230,  8,   1,  0, 34, 10,  0, 27,  6,  0, 13},
+	{ 220,  8,   1,  0, 33, 10,  0, 27,  6,  0, 12},
+	{ 210,  7,   1,  0, 33, 10,  0, 26,  6,  0, 12},
+	{ 200,  7,   1,  0, 33,  9,  0, 26,  5,  0, 11},
+	{ 190,  7,   1,  0, 32,  9,  0, 25,  5,  0, 11},
+	{ 180,  6,   1,  0, 32,  8,  0, 25,  5,  0, 10},
+	{ 170,  6,   0,  0, 32,  8,  0, 25,  5,  0, 10},
+	{ 160,  5,   0,  0, 31,  8,  0, 24,  4,  0,  9},
+	{ 150,  5,   0,  0, 31,  8,  0, 24,  5,  0,  9},
+	{ 140,  5,   0,  0, 31,  8,  0, 24,  5,  0,  8},
+	{ 130,  4,   0,  0, 30,  6,  0, 23,  3,  0,  8},
+	{ 120,  4,   0,  0, 30,  6,  0, 23,  3,  0,  7},
+	{ 110,  3,   0,  0, 30,  6,  0, 23,  3,  0,  7},
+	{ 100,  3,   0,  0, 29,  5,  0, 22,  2,  0,  6},
+	{  90,  3,   0,  0, 29,  5,  0, 22,  2,  0,  6},
+	{  80,  2,   0,  0, 28,  5,  0, 22,  2,  0,  5},
+};
+
+static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)
+{
+	regmap_write(samsung->regmap, BIAS_CON0, I_DEV_DIV_6 | I_RES_100_2UA);
+	regmap_write(samsung->regmap, BIAS_CON1, I_VBG_SEL_820MV | I_BGR_VREF_820MV |
+						 I_LADDER_1_00V);
+	regmap_write(samsung->regmap, BIAS_CON2, REG_325M_325MV | REG_LP_400M_400MV |
+						 REG_400M_400MV | REG_645M_645MV);
+
+	/* default output voltage select:
+	 * dphy: 400mv
+	 * cphy: 530mv
+	 */
+	regmap_update_bits(samsung->regmap, BIAS_CON4,
+			   I_MUX_SEL_MASK, I_MUX_400MV);
+}
+
+static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung)
+{
+	regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0x2000));
+	regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0,
+			   PHY_ENABLE, PHY_ENABLE);
+
+	switch (samsung->lanes) {
+	case 4:
+		regmap_write(samsung->regmap, DPHY_MD3_GNR_CON1,
+			     T_PHY_READY(0x2000));
+		regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0,
+				   PHY_ENABLE, PHY_ENABLE);
+		fallthrough;
+	case 3:
+		regmap_write(samsung->regmap, COMBO_MD2_GNR_CON1,
+			     T_PHY_READY(0x2000));
+		regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0,
+				   PHY_ENABLE, PHY_ENABLE);
+		fallthrough;
+	case 2:
+		regmap_write(samsung->regmap, COMBO_MD1_GNR_CON1,
+			     T_PHY_READY(0x2000));
+		regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0,
+				   PHY_ENABLE, PHY_ENABLE);
+		fallthrough;
+	case 1:
+	default:
+		regmap_write(samsung->regmap, COMBO_MD0_GNR_CON1,
+			     T_PHY_READY(0x2000));
+		regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0,
+				   PHY_ENABLE, PHY_ENABLE);
+		break;
+	}
+}
+
+static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung)
+{
+	switch (samsung->lanes) {
+	case 4:
+		regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0,
+				   PHY_ENABLE, 0);
+		fallthrough;
+	case 3:
+		regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0,
+				   PHY_ENABLE, 0);
+		fallthrough;
+	case 2:
+		regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0,
+				   PHY_ENABLE, 0);
+		fallthrough;
+	case 1:
+	default:
+		regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0,
+				   PHY_ENABLE, 0);
+		break;
+	}
+
+	regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, PHY_ENABLE, 0);
+}
+
+static void samsung_mipi_dcphy_pll_configure(struct samsung_mipi_dcphy *samsung)
+{
+	regmap_update_bits(samsung->regmap, PLL_CON0, S_MASK | P_MASK,
+			   S(samsung->pll.scaler) | P(samsung->pll.prediv));
+
+	if (samsung->pll.dsm < 0) {
+		u16 dsm_tmp;
+
+		/* Using opposite number subtraction to find complement */
+		dsm_tmp = abs(samsung->pll.dsm);
+		dsm_tmp = dsm_tmp - 1;
+		dsm_tmp ^= 0xffff;
+		regmap_write(samsung->regmap, PLL_CON1, dsm_tmp);
+	} else {
+		regmap_write(samsung->regmap, PLL_CON1, samsung->pll.dsm);
+	}
+
+	regmap_update_bits(samsung->regmap, PLL_CON2,
+			   M_MASK, M(samsung->pll.fbdiv));
+
+	if (samsung->pll.ssc_en) {
+		regmap_write(samsung->regmap, PLL_CON3,
+			     MRR(samsung->pll.mrr) | MFR(samsung->pll.mfr));
+		regmap_update_bits(samsung->regmap, PLL_CON4, SSCG_EN, SSCG_EN);
+	}
+
+	regmap_write(samsung->regmap, PLL_CON5, RESET_N_SEL | PLL_ENABLE_SEL);
+	regmap_write(samsung->regmap, PLL_CON7, PLL_LOCK_CNT(0xf000));
+	regmap_write(samsung->regmap, PLL_CON8, PLL_STB_CNT(0xf000));
+}
+
+static int samsung_mipi_dcphy_pll_enable(struct samsung_mipi_dcphy *samsung)
+{
+	u32 sts;
+	int ret;
+
+	regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, PLL_EN);
+
+	ret = regmap_read_poll_timeout(samsung->regmap, PLL_STAT0,
+				       sts, (sts & PLL_LOCK), 1000, 20000);
+	if (ret < 0)
+		dev_err(samsung->dev, "DC-PHY pll failed to lock\n");
+
+	return ret;
+}
+
+static void samsung_mipi_dcphy_pll_disable(struct samsung_mipi_dcphy *samsung)
+{
+	regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, 0);
+}
+
+static const struct samsung_mipi_dphy_timing *
+samsung_mipi_dphy_get_timing(struct samsung_mipi_dcphy *samsung)
+{
+	const struct samsung_mipi_dphy_timing *timings;
+	unsigned int num_timings;
+	unsigned int lane_mbps = div64_ul(samsung->pll.rate, USEC_PER_SEC);
+	unsigned int i;
+
+	timings = samsung_mipi_dphy_timing_table;
+	num_timings = ARRAY_SIZE(samsung_mipi_dphy_timing_table);
+
+	for (i = num_timings; i > 1; i--)
+		if (lane_mbps <= timings[i - 1].max_lane_mbps)
+			break;
+
+	return &timings[i - 1];
+}
+
+static unsigned long
+samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
+				  unsigned long prate, unsigned long rate,
+				  u8 *prediv, u16 *fbdiv, int *dsm, u8 *scaler)
+{
+	u32 max_fout = samsung->pdata->dphy_tx_max_lane_kbps;
+	u64 best_freq = 0;
+	u64 fin, fvco, fout;
+	u8 min_prediv, max_prediv;
+	u8 _prediv, best_prediv = 1;
+	u16 _fbdiv, best_fbdiv = 1;
+	u8 _scaler, best_scaler = 0;
+	u32 min_delta = UINT_MAX;
+	long _dsm, best_dsm = 0;
+
+	if (!prate) {
+		dev_err(samsung->dev, "parent rate of PLL can not be zero\n");
+		return 0;
+	}
+
+	/*
+	 * The PLL output frequency can be calculated using a simple formula:
+	 * Fvco = ((m+k/65536) x 2 x Fin) / p
+	 * Fout = ((m+k/65536) x 2 x Fin) / (p x 2^s)
+	 */
+	fin = div64_ul(prate, MSEC_PER_SEC);
+
+	while (!best_freq) {
+		fout = div64_ul(rate, MSEC_PER_SEC);
+		if (fout > max_fout)
+			fout = max_fout;
+
+		/* 0 ? S[2:0] ? 6 */
+		for (_scaler = 0; _scaler < 7; _scaler++) {
+			fvco = fout << _scaler;
+
+			/*
+			 * 2600MHz ? FVCO ? 6600MHz
+			 */
+			if (fvco < 2600 * MSEC_PER_SEC || fvco > 6600 * MSEC_PER_SEC)
+				continue;
+
+			/* 6MHz ? Fref(Fin / p) ? 30MHz */
+			min_prediv = DIV_ROUND_UP_ULL(fin, 30 * MSEC_PER_SEC);
+			max_prediv = DIV_ROUND_CLOSEST_ULL(fin, 6 * MSEC_PER_SEC);
+
+			for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
+				u64 delta, tmp;
+
+				_fbdiv = DIV_ROUND_CLOSEST_ULL(fvco * _prediv, 2 * fin);
+
+				 /* 64 ? M[9:0] ? 1023 */
+				if (_fbdiv < 64 || _fbdiv > 1023)
+					continue;
+
+				/* -32767 ? K[15:0] ? 32767 */
+				_dsm = ((_prediv * fvco) - (2 * _fbdiv * fin));
+				_dsm = DIV_ROUND_UP_ULL(_dsm << 15, fin);
+				if (abs(_dsm) > 32767)
+					continue;
+
+				tmp = DIV_ROUND_CLOSEST_ULL((_fbdiv * fin * 2 * 1000), _prediv);
+				tmp += DIV_ROUND_CLOSEST_ULL((_dsm * fin * 1000), _prediv << 15);
+
+				delta = abs(fvco * MSEC_PER_SEC - tmp);
+				if (delta < min_delta) {
+					best_prediv = _prediv;
+					best_fbdiv = _fbdiv;
+					best_dsm = _dsm;
+					best_scaler = _scaler;
+					min_delta = delta;
+					best_freq = DIV_ROUND_CLOSEST_ULL(tmp, 1000) * MSEC_PER_SEC;
+				}
+			}
+		}
+
+		rate += 100 * MSEC_PER_SEC;
+	}
+
+	*prediv = best_prediv;
+	*fbdiv = best_fbdiv;
+	*dsm = (int)best_dsm & 0xffff;
+	*scaler = best_scaler;
+	dev_dbg(samsung->dev, "p: %d, m: %d, dsm:%ld, scaler: %d\n",
+		best_prediv, best_fbdiv, best_dsm, best_scaler);
+
+	return best_freq >> best_scaler;
+}
+
+static void
+samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
+{
+	const struct samsung_mipi_dphy_timing *timing;
+	unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
+	u32 val, res_up, res_down;
+
+	timing = samsung_mipi_dphy_get_timing(samsung);
+	regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0xf000);
+
+	/*
+	 * The Drive-Strength / Voltage-Amplitude is adjusted by setting
+	 * the Driver-Up Resistor and Driver-Down Resistor.
+	 */
+	res_up = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_up_ohm;
+	res_down = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_down_ohm;
+	val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN |
+	      RES_UP(res_up) | RES_DN(res_down);
+	regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, val);
+
+	if (lane_hs_rate >= 4500)
+		regmap_write(samsung->regmap, DPHY_MC_ANA_CON1, 0x0001);
+
+	val = 0;
+	/*
+	 * Divide-by-2 Clock from Serial Clock. Use this when data rate is under
+	 * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
+	 */
+	if (lane_hs_rate < 1500)
+		val = HSTX_CLK_SEL;
+
+	val |= T_LPX(timing->lpx);
+	/*  T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */
+	regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, val);
+
+	val = T_CLK_ZERO(timing->clk_zero) | T_CLK_PREPARE(timing->clk_prepare);
+	regmap_write(samsung->regmap, DPHY_MC_TIME_CON1, val);
+
+	val = T_HS_EXIT(timing->hs_exit) | T_CLK_TRAIL(timing->clk_trail_eot);
+	regmap_write(samsung->regmap, DPHY_MC_TIME_CON2, val);
+
+	val = T_CLK_POST(timing->clk_post);
+	regmap_write(samsung->regmap, DPHY_MC_TIME_CON3, val);
+
+	/* Escape Clock is 20.00MHz */
+	regmap_write(samsung->regmap, DPHY_MC_TIME_CON4, 0x1f4);
+
+	/*
+	 * skew calibration should be off, if the operation data rate is
+	 * under 1.5Gbps or equal to 1.5Gbps.
+	 */
+	if (lane_hs_rate > 1500)
+		regmap_write(samsung->regmap, DPHY_MC_DESKEW_CON0, 0x9cb1);
+}
+
+static void
+samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
+{
+	const struct samsung_mipi_dphy_timing *timing;
+	unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
+	u32 val, res_up, res_down;
+
+	timing = samsung_mipi_dphy_get_timing(samsung);
+
+	/*
+	 * The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the
+	 *  Driver-Up Resistor and Driver-Down Resistor.
+	 */
+	res_up = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_up_ohm;
+	res_down = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_down_ohm;
+	val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN |
+	      RES_UP(res_up) | RES_DN(res_down);
+	regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, val);
+	regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, val);
+	regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, val);
+	regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, val);
+
+	if (lane_hs_rate >= 4500) {
+		regmap_write(samsung->regmap, COMBO_MD0_ANA_CON1, 0x0001);
+		regmap_write(samsung->regmap, COMBO_MD1_ANA_CON1, 0x0001);
+		regmap_write(samsung->regmap, COMBO_MD2_ANA_CON1, 0x0001);
+		regmap_write(samsung->regmap, DPHY_MD3_ANA_CON1, 0x0001);
+	}
+
+	val = 0;
+	/*
+	 * Divide-by-2 Clock from Serial Clock. Use this when data rate is under
+	 * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
+	 */
+	if (lane_hs_rate < 1500)
+		val = HSTX_CLK_SEL;
+
+	val |= T_LPX(timing->lpx);
+	/*  T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, val);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, val);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, val);
+	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, val);
+
+	val = T_HS_ZERO(timing->hs_zero) | T_HS_PREPARE(timing->hs_prepare);
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON1, val);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON1, val);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON1, val);
+	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON1, val);
+
+	val = T_HS_EXIT(timing->hs_exit) | T_HS_TRAIL(timing->hs_trail_eot);
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON2, val);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON2, val);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON2, val);
+	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON2, val);
+
+	/* TTA-GET/TTA-GO Timing Counter register use default value */
+	val = T_TA_GET(0x3) | T_TA_GO(0x0);
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON3, val);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON3, val);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON3, val);
+	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON3, val);
+
+	/* Escape Clock is 20.00MHz */
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON4, 0x1f4);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON4, 0x1f4);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON4, 0x1f4);
+	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON4, 0x1f4);
+}
+
+static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
+{
+	int ret;
+
+	reset_control_assert(samsung->m_phy_rst);
+
+	samsung_mipi_dcphy_bias_block_enable(samsung);
+	samsung_mipi_dcphy_pll_configure(samsung);
+	samsung_mipi_dphy_clk_lane_timing_init(samsung);
+	samsung_mipi_dphy_data_lane_timing_init(samsung);
+	ret = samsung_mipi_dcphy_pll_enable(samsung);
+	if (ret < 0)
+		return ret;
+
+	samsung_mipi_dphy_lane_enable(samsung);
+
+	reset_control_deassert(samsung->m_phy_rst);
+
+	/* The TSKEWCAL maximum is 100 ?sec
+	 * at initial calibration.
+	 */
+	usleep_range(100, 110);
+
+	return 0;
+}
+
+static int samsung_mipi_dcphy_power_on(struct phy *phy)
+{
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	reset_control_assert(samsung->apb_rst);
+	udelay(1);
+	reset_control_deassert(samsung->apb_rst);
+
+	switch (samsung->type) {
+	case PHY_TYPE_DPHY:
+		return samsung_mipi_dphy_power_on(samsung);
+	default:
+		/* CPHY part to be implemented later */
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int samsung_mipi_dcphy_power_off(struct phy *phy)
+{
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	switch (samsung->type) {
+	case PHY_TYPE_DPHY:
+		samsung_mipi_dphy_lane_disable(samsung);
+		break;
+	default:
+		/* CPHY part to be implemented later */
+		return -EOPNOTSUPP;
+	}
+
+	samsung_mipi_dcphy_pll_disable(samsung);
+
+	return 0;
+}
+
+static int
+samsung_mipi_dcphy_pll_ssc_modulation_calc(struct samsung_mipi_dcphy *samsung,
+					   u8 *mfr, u8 *mrr)
+{
+	unsigned long fin = div64_ul(clk_get_rate(samsung->ref_clk), MSEC_PER_SEC);
+	u16 prediv = samsung->pll.prediv;
+	u16 fbdiv = samsung->pll.fbdiv;
+	u16 min_mfr, max_mfr;
+	u16 _mfr, best_mfr = 0;
+	u16 mr, _mrr, best_mrr = 0;
+
+	/* 20KHz ? MF ? 150KHz */
+	max_mfr = DIV_ROUND_UP(fin, (20 * prediv) << 5);
+	min_mfr = div64_ul(fin, ((150 * prediv) << 5));
+	/*0 ? mfr ? 255 */
+	if (max_mfr > 256)
+		max_mfr = 256;
+
+	for (_mfr = min_mfr; _mfr < max_mfr; _mfr++) {
+		/* 1 ? mrr ? 31 */
+		for (_mrr = 1; _mrr < 32; _mrr++) {
+			mr = DIV_ROUND_UP(_mfr * _mrr * 100, fbdiv << 6);
+			/* 0 ? MR ? 5% */
+			if (mr > 5)
+				continue;
+
+			if (_mfr * _mrr < 513) {
+				best_mfr = _mfr;
+				best_mrr = _mrr;
+				break;
+			}
+		}
+	}
+
+	if (best_mrr) {
+		*mfr = best_mfr & 0xff;
+		*mrr = best_mrr & 0x3f;
+	} else {
+		dev_err(samsung->dev, "failed to calc ssc parameter mfr and mrr\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+samsung_mipi_dcphy_pll_calc_rate(struct samsung_mipi_dcphy *samsung,
+				 unsigned long long rate)
+{
+	unsigned long prate = clk_get_rate(samsung->ref_clk);
+	unsigned long fout;
+	u8 scaler = 0, mfr = 0, mrr = 0;
+	u16 fbdiv = 0;
+	u8 prediv = 1;
+	int dsm = 0;
+	int ret;
+
+	fout = samsung_mipi_dcphy_pll_round_rate(samsung, prate, rate,
+						 &prediv, &fbdiv, &dsm,
+						 &scaler);
+
+	dev_dbg(samsung->dev, "%s: fin=%lu, req_rate=%llu\n",
+		__func__, prate, rate);
+	dev_dbg(samsung->dev, "%s: fout=%lu, prediv=%u, fbdiv=%u\n",
+		__func__, fout, prediv, fbdiv);
+
+	samsung->pll.prediv = prediv;
+	samsung->pll.fbdiv = fbdiv;
+	samsung->pll.dsm = dsm;
+	samsung->pll.scaler = scaler;
+	samsung->pll.rate = fout;
+
+	/*
+	 * All DPHY 2.0 compliant Transmitters shall support SSC operating above
+	 * 2.5 Gbps
+	 */
+	if (fout > 2500000000LL) {
+		ret = samsung_mipi_dcphy_pll_ssc_modulation_calc(samsung,
+								 &mfr, &mrr);
+		if (!ret) {
+			samsung->pll.ssc_en = true;
+			samsung->pll.mfr = mfr;
+			samsung->pll.mrr = mrr;
+		}
+	}
+}
+
+static int samsung_mipi_dcphy_configure(struct phy *phy,
+					union phy_configure_opts *opts)
+{
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+	unsigned long long target_rate = opts->mipi_dphy.hs_clk_rate;
+
+	samsung->lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes;
+
+	samsung_mipi_dcphy_pll_calc_rate(samsung, target_rate);
+	opts->mipi_dphy.hs_clk_rate = samsung->pll.rate;
+
+	return 0;
+}
+
+static int samsung_mipi_dcphy_init(struct phy *phy)
+{
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	return pm_runtime_resume_and_get(samsung->dev);
+}
+
+static int samsung_mipi_dcphy_exit(struct phy *phy)
+{
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	return pm_runtime_put(samsung->dev);
+}
+
+static const struct phy_ops samsung_mipi_dcphy_ops = {
+	.configure = samsung_mipi_dcphy_configure,
+	.power_on  = samsung_mipi_dcphy_power_on,
+	.power_off = samsung_mipi_dcphy_power_off,
+	.init = samsung_mipi_dcphy_init,
+	.exit = samsung_mipi_dcphy_exit,
+	.owner	   = THIS_MODULE,
+};
+
+static const struct regmap_config samsung_mipi_dcphy_regmap_config = {
+	.name = "dcphy",
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x10000,
+};
+
+static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,
+					    const struct of_phandle_args *args)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of arguments\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (samsung->type != PHY_NONE && samsung->type != args->args[0])
+		dev_warn(dev, "phy type select %d overwriting type %d\n",
+			 args->args[0], samsung->type);
+
+	samsung->type = args->args[0];
+
+	return samsung->phy;
+}
+
+static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct samsung_mipi_dcphy *samsung;
+	struct phy_provider *phy_provider;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	samsung = devm_kzalloc(dev, sizeof(*samsung), GFP_KERNEL);
+	if (!samsung)
+		return -ENOMEM;
+
+	samsung->dev = dev;
+	samsung->pdata = device_get_match_data(dev);
+	platform_set_drvdata(pdev, samsung);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	samsung->regmap = devm_regmap_init_mmio(dev, regs,
+						&samsung_mipi_dcphy_regmap_config);
+	if (IS_ERR(samsung->regmap))
+		return dev_err_probe(dev, PTR_ERR(samsung->regmap), "Failed to init regmap\n");
+
+	samsung->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(samsung->grf_regmap))
+		return dev_err_probe(dev, PTR_ERR(samsung->grf_regmap),
+				     "Unable to get rockchip,grf\n");
+
+	samsung->ref_clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(samsung->ref_clk))
+		return dev_err_probe(dev, PTR_ERR(samsung->ref_clk),
+				     "Failed to get reference clock\n");
+
+	samsung->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(samsung->pclk))
+		return dev_err_probe(dev, PTR_ERR(samsung->pclk), "Failed to get pclk\n");
+
+	samsung->m_phy_rst = devm_reset_control_get(dev, "m_phy");
+	if (IS_ERR(samsung->m_phy_rst))
+		return dev_err_probe(dev, PTR_ERR(samsung->m_phy_rst),
+				     "Failed to get system m_phy_rst control\n");
+
+	samsung->s_phy_rst = devm_reset_control_get(dev, "s_phy");
+	if (IS_ERR(samsung->s_phy_rst))
+		return dev_err_probe(dev, PTR_ERR(samsung->s_phy_rst),
+				     "Failed to get system s_phy_rst control\n");
+
+	samsung->apb_rst = devm_reset_control_get(dev, "apb");
+	if (IS_ERR(samsung->apb_rst))
+		return dev_err_probe(dev, PTR_ERR(samsung->apb_rst),
+				     "Failed to get system apb_rst control\n");
+
+	samsung->grf_apb_rst = devm_reset_control_get(dev, "grf");
+	if (IS_ERR(samsung->grf_apb_rst))
+		return dev_err_probe(dev, PTR_ERR(samsung->grf_apb_rst),
+				     "Failed to get system grf_apb_rst control\n");
+
+	samsung->phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_ops);
+	if (IS_ERR(samsung->phy))
+		return dev_err_probe(dev, PTR_ERR(samsung->phy), "Failed to create MIPI DC-PHY\n");
+
+	phy_set_drvdata(samsung->phy, samsung);
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
+
+	phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate);
+	if (IS_ERR(phy_provider))
+		return dev_err_probe(dev, PTR_ERR(phy_provider),
+				     "Failed to register phy provider\n");
+
+	return 0;
+}
+
+static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(samsung->ref_clk);
+	clk_disable_unprepare(samsung->pclk);
+
+	return 0;
+}
+
+static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(samsung->pclk);
+	if (ret) {
+		dev_err(samsung->dev, "Failed to enable pclk, %d\n", ret);
+		return ret;
+	}
+
+	clk_prepare_enable(samsung->ref_clk);
+	if (ret) {
+		dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret);
+		clk_disable_unprepare(samsung->pclk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = {
+	SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend,
+			   samsung_mipi_dcphy_runtime_resume, NULL)
+};
+
+static const struct hs_drv_res_cfg rk3576_dphy_hs_drv_res_cfg = {
+	.clk_hs_drv_up_ohm = STRENGTH_52_OHM,
+	.clk_hs_drv_down_ohm = STRENGTH_52_OHM,
+	.data_hs_drv_up_ohm = STRENGTH_39_OHM,
+	.data_hs_drv_down_ohm = STRENGTH_39_OHM,
+};
+
+static const struct hs_drv_res_cfg rk3588_dphy_hs_drv_res_cfg = {
+	.clk_hs_drv_up_ohm = STRENGTH_34_OHM,
+	.clk_hs_drv_down_ohm = STRENGTH_34_OHM,
+	.data_hs_drv_up_ohm = STRENGTH_43_OHM,
+	.data_hs_drv_down_ohm = STRENGTH_43_OHM,
+};
+
+static const struct samsung_mipi_dcphy_plat_data rk3576_samsung_mipi_dcphy_plat_data = {
+	.dphy_hs_drv_res_cfg = &rk3576_dphy_hs_drv_res_cfg,
+	.dphy_tx_max_lane_kbps = 2500000L,
+};
+
+static const struct samsung_mipi_dcphy_plat_data rk3588_samsung_mipi_dcphy_plat_data = {
+	.dphy_hs_drv_res_cfg = &rk3588_dphy_hs_drv_res_cfg,
+	.dphy_tx_max_lane_kbps = 4500000L,
+};
+
+static const struct of_device_id samsung_mipi_dcphy_of_match[] = {
+	{
+		.compatible = "rockchip,rk3576-mipi-dcphy",
+		.data = &rk3576_samsung_mipi_dcphy_plat_data,
+	}, {
+		.compatible = "rockchip,rk3588-mipi-dcphy",
+		.data = &rk3588_samsung_mipi_dcphy_plat_data,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, samsung_mipi_dcphy_of_match);
+
+static struct platform_driver samsung_mipi_dcphy_driver = {
+	.driver = {
+		.name = "samsung-mipi-dcphy",
+		.of_match_table	= samsung_mipi_dcphy_of_match,
+		.pm = &samsung_mipi_dcphy_pm_ops,
+	},
+	.probe	= samsung_mipi_dcphy_probe,
+};
+module_platform_driver(samsung_mipi_dcphy_driver);
+
+MODULE_AUTHOR("Guochun Huang <hero.huang at rock-chips.com>");
+MODULE_DESCRIPTION("Samsung MIPI DCPHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.47.2



From heiko at sntech.de  Thu Mar 13 06:40:30 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 14:40:30 +0100
Subject: [PATCH v8 0/2] MIPI DSI phy for rk3588
Message-ID: <20250313134035.278133-1-heiko@sntech.de>

This adds the phy driver need for DSI output on rk3588.

The phy itself is used for both DSI output and CSI input, though the
CSI part for the whole chain needs a lot more work, so is left out for
now and only the DSI part implemented.

This allows the rk3588 with its current VOP support to drive a DSI display
using the DSI2 controller driver I'll submit in a next step.

Only generic phy interfaces are used, so the DSI part is pretty straight
forward.

changes in v8:
- add comment that the timing values comes from the vendor kernel (Vinod)

changes in v7:
- missing pclk-disable in resume error path
- replace remaining magic values with actual constants
- lower-case hex values
- made lane_disable behave similar to lane_enable wrt. lane count

changes in v6:
- rebase onto 6.14-rc1
- add Krzysztof binding review
- v5 was sent at the beginning of december '24, so probably has been lost

changes in v5:
- add bitfield.h for the FIELD_PROP definition
  (reported by kernel-test-robot)
- add Sebastian's Reviewed-by
- add Conor's Ack to the dt-binding

changes in v4:
- moved to #phy-cells = 1 as suggested by Sebastian, with the argument
  denoting the requested phy-type (C-PHY, D-PHY). This works similarly
  how the Mediatek C/D-PHY already implements this, see mails around:
  https://lore.kernel.org/all/20230608200552.GA3303349-robh at kernel.org/
- dropped Krzysztof's review tag from the binding because of this
- dropped custom UPDATE macro and use FIELD_PREP instead
- build a FIELD_PREP_HIWORD macro for the GRF settings
- add received Tested-by tags

changes in v3:
- add Krzysztof review tag to the binding
- address Sebastian's review comments
  - better error handling
  - dropping empty function
  - headers
  - not using of_match_ptr - this should also make the
    test-robot happier

changes in v2:
- fix error in dt-binding example
- drop unused frequency table
- pull in some more recent improvements from the vendor-kernel
  which includes a lot less magic values
- already include the support for rk3576
- use dev_err_probe

Heiko Stuebner (2):
  dt-bindings: phy: Add Rockchip MIPI C-/D-PHY schema
  phy: rockchip: Add Samsung MIPI D-/C-PHY driver

 .../phy/rockchip,rk3588-mipi-dcphy.yaml       |   87 +
 drivers/phy/rockchip/Kconfig                  |   12 +
 drivers/phy/rockchip/Makefile                 |    1 +
 .../phy/rockchip/phy-rockchip-samsung-dcphy.c | 1719 +++++++++++++++++
 4 files changed, 1819 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
 create mode 100644 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c

-- 
2.47.2



From heiko at sntech.de  Thu Mar 13 06:40:31 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 14:40:31 +0100
Subject: [PATCH v8 1/2] dt-bindings: phy: Add Rockchip MIPI C-/D-PHY schema
In-Reply-To: <20250313134035.278133-1-heiko@sntech.de>
References: <20250313134035.278133-1-heiko@sntech.de>
Message-ID: <20250313134035.278133-2-heiko@sntech.de>

From: Heiko Stuebner <heiko.stuebner at cherry.de>

Add dt-binding schema for the MIPI C-/D-PHY found on
Rockchip RK3588 SoCs.

Tested-by: Daniel Semkowicz <dse at thaumatec.com>
Tested-by: Sebastian Reichel <sebastian.reichel at collabora.com>
Tested-by: Quentin Schulz <quentin.schulz at cherry.de>
Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Heiko Stuebner <heiko.stuebner at cherry.de>
---
 .../phy/rockchip,rk3588-mipi-dcphy.yaml       | 87 +++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml

diff --git a/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml b/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
new file mode 100644
index 0000000000000..c8ff5ba22a86b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/rockchip,rk3588-mipi-dcphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip MIPI D-/C-PHY with Samsung IP block
+
+maintainers:
+  - Guochun Huang <hero.huang at rock-chips.com>
+  - Heiko Stuebner <heiko at sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3576-mipi-dcphy
+      - rockchip,rk3588-mipi-dcphy
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 1
+    description: |
+      Argument is mode to operate in. Supported modes are:
+        - PHY_TYPE_DPHY
+        - PHY_TYPE_CPHY
+      See include/dt-bindings/phy/phy.h for constants.
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: pclk
+      - const: ref
+
+  resets:
+    maxItems: 4
+
+  reset-names:
+    items:
+      - const: m_phy
+      - const: apb
+      - const: grf
+      - const: s_phy
+
+  rockchip,grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the syscon managing the 'mipi dcphy general register files'.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+    #include <dt-bindings/reset/rockchip,rk3588-cru.h>
+
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      phy at feda0000 {
+        compatible = "rockchip,rk3588-mipi-dcphy";
+        reg = <0x0 0xfeda0000 0x0 0x10000>;
+        clocks = <&cru PCLK_MIPI_DCPHY0>,
+                 <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>;
+        clock-names = "pclk", "ref";
+        resets = <&cru SRST_M_MIPI_DCPHY0>,
+                 <&cru SRST_P_MIPI_DCPHY0>,
+                 <&cru SRST_P_MIPI_DCPHY0_GRF>,
+                 <&cru SRST_S_MIPI_DCPHY0>;
+        reset-names = "m_phy", "apb", "grf", "s_phy";
+        rockchip,grf = <&mipidcphy0_grf>;
+        #phy-cells = <1>;
+      };
+    };
-- 
2.47.2



From christophe.leroy at csgroup.eu  Thu Mar 13 06:37:56 2025
From: christophe.leroy at csgroup.eu (Christophe Leroy)
Date: Thu, 13 Mar 2025 14:37:56 +0100
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <Z9LbwRUsHwFLpBZA@gallifrey>
References: <20241115152055.279732-1-linux@treblig.org>
 <3f9dbb7b-6527-48e1-9028-b46e5a0c58ce@csgroup.eu>
 <Z9LbwRUsHwFLpBZA@gallifrey>
Message-ID: <362f9392-f891-4a15-9ffd-5f5a6cac41b8@csgroup.eu>



Le 13/03/2025 ? 14:21, Dr. David Alan Gilbert a ?crit?:
> [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> 
> * Christophe Leroy (christophe.leroy at csgroup.eu) wrote:
>>
>>
>> Le 15/11/2024 ? 16:20, linux at treblig.org a ?crit :
>>> [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
>>>
>>> From: "Dr. David Alan Gilbert" <linux at treblig.org>
>>>
>>> fsl_mc_allocator_driver_exit() was added explicitly by
>>> commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
>>> but was never used.
>>>
>>> Remove it.
>>>
>>> fsl_mc_portal_reset() was added in 2015 by
>>> commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
>>> but was never used.
>>>
>>> Remove it.
>>>
>>> fsl_mc_portal_reset() was the only caller of dpmcp_reset().
>>>
>>> Remove it.
>>>
>>> Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>
>>
>> Acked-by: Christophe Leroy <christophe.leroy at csgroup.eu>
> 
> Hi,
>    Can someone pick this old change up please?  I see the PPC patchwork says
>    'handled elsewhere' but doesn't say where.

MAINTAINERS file says where:

QORIQ DPAA2 FSL-MC BUS DRIVER
M:	Stuart Yoder <stuyoder at gmail.com>
M:	Laurentiu Tudor <laurentiu.tudor at nxp.com>
L:	linux-kernel at vger.kernel.org
S:	Maintained
F:	Documentation/ABI/stable/sysfs-bus-fsl-mc
F:	Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
F: 
Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
F:	drivers/bus/fsl-mc/
F:	include/uapi/linux/fsl_mc.h

FREESCALE SOC DRIVERS
M:	Christophe Leroy <christophe.leroy at csgroup.eu>
L:	linuxppc-dev at lists.ozlabs.org
L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
S:	Maintained
F:	Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
F:	Documentation/devicetree/bindings/soc/fsl/
F:	drivers/soc/fsl/
F:	include/linux/fsl/
F:	include/soc/fsl/

I acked the 2 line changes in include/linux/fsl/mc.h, the main changes 
being in the C files which are not under my scope.

Stuart, Laurentiu, can you pick up the patch ?

Christophe

> 
> Thanks,
> 
> Dave
>>
>>> ---
>>>    drivers/bus/fsl-mc/dpmcp.c            | 22 ----------------------
>>>    drivers/bus/fsl-mc/fsl-mc-allocator.c |  5 -----
>>>    drivers/bus/fsl-mc/fsl-mc-private.h   |  6 ------
>>>    drivers/bus/fsl-mc/mc-io.c            | 20 --------------------
>>>    include/linux/fsl/mc.h                |  2 --
>>>    5 files changed, 55 deletions(-)
>>>
>>> diff --git a/drivers/bus/fsl-mc/dpmcp.c b/drivers/bus/fsl-mc/dpmcp.c
>>> index 5fbd0dbde24a..7816c0a728ef 100644
>>> --- a/drivers/bus/fsl-mc/dpmcp.c
>>> +++ b/drivers/bus/fsl-mc/dpmcp.c
>>> @@ -75,25 +75,3 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
>>>           /* send command to mc*/
>>>           return mc_send_command(mc_io, &cmd);
>>>    }
>>> -
>>> -/**
>>> - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
>>> - * @mc_io:     Pointer to MC portal's I/O object
>>> - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
>>> - * @token:     Token of DPMCP object
>>> - *
>>> - * Return:     '0' on Success; Error code otherwise.
>>> - */
>>> -int dpmcp_reset(struct fsl_mc_io *mc_io,
>>> -               u32 cmd_flags,
>>> -               u16 token)
>>> -{
>>> -       struct fsl_mc_command cmd = { 0 };
>>> -
>>> -       /* prepare command */
>>> -       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
>>> -                                         cmd_flags, token);
>>> -
>>> -       /* send command to mc*/
>>> -       return mc_send_command(mc_io, &cmd);
>>> -}
>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
>>> index b5e8c021fa1f..6c3beb82dd1b 100644
>>> --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
>>> +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
>>> @@ -656,8 +656,3 @@ int __init fsl_mc_allocator_driver_init(void)
>>>    {
>>>           return fsl_mc_driver_register(&fsl_mc_allocator_driver);
>>>    }
>>> -
>>> -void fsl_mc_allocator_driver_exit(void)
>>> -{
>>> -       fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
>>> -}
>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
>>> index b3520ea1b9f4..e1b7ec3ed1a7 100644
>>> --- a/drivers/bus/fsl-mc/fsl-mc-private.h
>>> +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
>>> @@ -66,10 +66,6 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
>>>                   u32 cmd_flags,
>>>                   u16 token);
>>>
>>> -int dpmcp_reset(struct fsl_mc_io *mc_io,
>>> -               u32 cmd_flags,
>>> -               u16 token);
>>> -
>>>    /*
>>>     * Data Path Resource Container (DPRC) API
>>>     */
>>> @@ -631,8 +627,6 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
>>>
>>>    int __init fsl_mc_allocator_driver_init(void);
>>>
>>> -void fsl_mc_allocator_driver_exit(void);
>>> -
>>>    void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
>>>
>>>    void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
>>> diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
>>> index 95b10a6cf307..a0ad7866cbfc 100644
>>> --- a/drivers/bus/fsl-mc/mc-io.c
>>> +++ b/drivers/bus/fsl-mc/mc-io.c
>>> @@ -263,23 +263,3 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
>>>           dpmcp_dev->consumer_link = NULL;
>>>    }
>>>    EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
>>> -
>>> -/**
>>> - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
>>> - *
>>> - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
>>> - */
>>> -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
>>> -{
>>> -       int error;
>>> -       struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
>>> -
>>> -       error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
>>> -       if (error < 0) {
>>> -               dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
>>> -               return error;
>>> -       }
>>> -
>>> -       return 0;
>>> -}
>>> -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
>>> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
>>> index c90ec889bfc2..37316a58d2ed 100644
>>> --- a/include/linux/fsl/mc.h
>>> +++ b/include/linux/fsl/mc.h
>>> @@ -417,8 +417,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
>>>
>>>    void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
>>>
>>> -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
>>> -
>>>    int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
>>>                                           enum fsl_mc_pool_type pool_type,
>>>                                           struct fsl_mc_device **new_mc_adev);
>>> --
>>> 2.47.0
>>>
>>
> --
>   -----Open up your eyes, open up your mind, open up your code -------
> / Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \
> \        dave @ treblig.org |                               | In Hex /
>   \ _________________________|_____ https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.treblig.org%2F&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C707d35bccc9a4949428b08dd6231e98a%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C638774688697894005%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=ncMBG9AvSfn4mKmQkFv%2F6UfFYp%2FBMDOna7uejbavhUc%3D&reserved=0   |_______/



From linus.walleij at linaro.org  Thu Mar 13 06:49:27 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 13 Mar 2025 14:49:27 +0100
Subject: [PATCH v4 0/8] pinctrl: sunxi: Add Allwinner A523 support
In-Reply-To: <20250306235827.4895-1-andre.przywara@arm.com>
References: <20250306235827.4895-1-andre.przywara@arm.com>
Message-ID: <CACRpkdaVH8GAx_K0a01FbRKe8CQ=jh7jwfVrs_PgS9og4vnWmQ@mail.gmail.com>

On Fri, Mar 7, 2025 at 12:58?AM Andre Przywara <andre.przywara at arm.com> wrote:

> this is the fourth drop of the series introducing pinctrl support for the
> Allwinner A523 family of SoCs (comprising A523, A527, T527, H728). [1]
> This time only a small fix, spotted by Jernej, thanks for that. Also
> adding the new tags. Changelog below.

Patches applied!

Yours,
Linus Walleij


From ioana.ciornei at nxp.com  Thu Mar 13 06:51:42 2025
From: ioana.ciornei at nxp.com (Ioana Ciornei)
Date: Thu, 13 Mar 2025 15:51:42 +0200
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <362f9392-f891-4a15-9ffd-5f5a6cac41b8@csgroup.eu>
References: <20241115152055.279732-1-linux@treblig.org>
 <3f9dbb7b-6527-48e1-9028-b46e5a0c58ce@csgroup.eu>
 <Z9LbwRUsHwFLpBZA@gallifrey>
 <362f9392-f891-4a15-9ffd-5f5a6cac41b8@csgroup.eu>
Message-ID: <oz65tdekf2ywyzadbntuxntwxulcdzyo33se54qqdsddkogquh@bqnmsmqijfvb>

On Thu, Mar 13, 2025 at 02:37:56PM +0100, Christophe Leroy wrote:
> 
> 
> Le 13/03/2025 ? 14:21, Dr. David Alan Gilbert a ?crit?:
> > [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> > 
> > * Christophe Leroy (christophe.leroy at csgroup.eu) wrote:
> > > 
> > > 
> > > Le 15/11/2024 ? 16:20, linux at treblig.org a ?crit :
> > > > [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> > > > 
> > > > From: "Dr. David Alan Gilbert" <linux at treblig.org>
> > > > 
> > > > fsl_mc_allocator_driver_exit() was added explicitly by
> > > > commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> > > > but was never used.
> > > > 
> > > > Remove it.
> > > > 
> > > > fsl_mc_portal_reset() was added in 2015 by
> > > > commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> > > > but was never used.
> > > > 
> > > > Remove it.
> > > > 
> > > > fsl_mc_portal_reset() was the only caller of dpmcp_reset().
> > > > 
> > > > Remove it.
> > > > 
> > > > Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>
> > > 
> > > Acked-by: Christophe Leroy <christophe.leroy at csgroup.eu>
> > 
> > Hi,
> >    Can someone pick this old change up please?  I see the PPC patchwork says
> >    'handled elsewhere' but doesn't say where.
> 
> MAINTAINERS file says where:
> 
> QORIQ DPAA2 FSL-MC BUS DRIVER
> M:	Stuart Yoder <stuyoder at gmail.com>
> M:	Laurentiu Tudor <laurentiu.tudor at nxp.com>
> L:	linux-kernel at vger.kernel.org
> S:	Maintained
> F:	Documentation/ABI/stable/sysfs-bus-fsl-mc
> F:	Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
> F:
> Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
> F:	drivers/bus/fsl-mc/
> F:	include/uapi/linux/fsl_mc.h
> 
> FREESCALE SOC DRIVERS
> M:	Christophe Leroy <christophe.leroy at csgroup.eu>
> L:	linuxppc-dev at lists.ozlabs.org
> L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> S:	Maintained
> F:	Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
> F:	Documentation/devicetree/bindings/soc/fsl/
> F:	drivers/soc/fsl/
> F:	include/linux/fsl/
> F:	include/soc/fsl/
> 
> I acked the 2 line changes in include/linux/fsl/mc.h, the main changes being
> in the C files which are not under my scope.
> 
> Stuart, Laurentiu, can you pick up the patch ?

Stuart and Laurentiu are no longer at NXP. Even when they handled the
fsl-mc bus driver, they didn't have a tree themselves to pick patches up
but rather, historically, patches on the fsl-mc bus were picked by Greg
KH.

Ioana


From linux at treblig.org  Thu Mar 13 06:56:07 2025
From: linux at treblig.org (Dr. David Alan Gilbert)
Date: Thu, 13 Mar 2025 13:56:07 +0000
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <oz65tdekf2ywyzadbntuxntwxulcdzyo33se54qqdsddkogquh@bqnmsmqijfvb>
References: <20241115152055.279732-1-linux@treblig.org>
 <3f9dbb7b-6527-48e1-9028-b46e5a0c58ce@csgroup.eu>
 <Z9LbwRUsHwFLpBZA@gallifrey>
 <362f9392-f891-4a15-9ffd-5f5a6cac41b8@csgroup.eu>
 <oz65tdekf2ywyzadbntuxntwxulcdzyo33se54qqdsddkogquh@bqnmsmqijfvb>
Message-ID: <Z9Lj9_yM1EK5pKee@gallifrey>

Hi Greg,

* Ioana Ciornei (ioana.ciornei at nxp.com) wrote:
> On Thu, Mar 13, 2025 at 02:37:56PM +0100, Christophe Leroy wrote:
> > 
> > 
> > Le 13/03/2025 ? 14:21, Dr. David Alan Gilbert a ?crit?:
> > > [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> > > 
> > > * Christophe Leroy (christophe.leroy at csgroup.eu) wrote:
> > > > 
> > > > 
> > > > Le 15/11/2024 ? 16:20, linux at treblig.org a ?crit :
> > > > > [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> > > > > 
> > > > > From: "Dr. David Alan Gilbert" <linux at treblig.org>
> > > > > 
> > > > > fsl_mc_allocator_driver_exit() was added explicitly by
> > > > > commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> > > > > but was never used.
> > > > > 
> > > > > Remove it.
> > > > > 
> > > > > fsl_mc_portal_reset() was added in 2015 by
> > > > > commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> > > > > but was never used.
> > > > > 
> > > > > Remove it.
> > > > > 
> > > > > fsl_mc_portal_reset() was the only caller of dpmcp_reset().
> > > > > 
> > > > > Remove it.
> > > > > 
> > > > > Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>
> > > > 
> > > > Acked-by: Christophe Leroy <christophe.leroy at csgroup.eu>
> > > 
> > > Hi,
> > >    Can someone pick this old change up please?  I see the PPC patchwork says
> > >    'handled elsewhere' but doesn't say where.
> > 
> > MAINTAINERS file says where:
> > 
> > QORIQ DPAA2 FSL-MC BUS DRIVER
> > M:	Stuart Yoder <stuyoder at gmail.com>
> > M:	Laurentiu Tudor <laurentiu.tudor at nxp.com>
> > L:	linux-kernel at vger.kernel.org
> > S:	Maintained
> > F:	Documentation/ABI/stable/sysfs-bus-fsl-mc
> > F:	Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
> > F:
> > Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
> > F:	drivers/bus/fsl-mc/
> > F:	include/uapi/linux/fsl_mc.h
> > 
> > FREESCALE SOC DRIVERS
> > M:	Christophe Leroy <christophe.leroy at csgroup.eu>
> > L:	linuxppc-dev at lists.ozlabs.org
> > L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > S:	Maintained
> > F:	Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
> > F:	Documentation/devicetree/bindings/soc/fsl/
> > F:	drivers/soc/fsl/
> > F:	include/linux/fsl/
> > F:	include/soc/fsl/
> > 
> > I acked the 2 line changes in include/linux/fsl/mc.h, the main changes being
> > in the C files which are not under my scope.
> > 
> > Stuart, Laurentiu, can you pick up the patch ?
> 
> Stuart and Laurentiu are no longer at NXP. Even when they handled the
> fsl-mc bus driver, they didn't have a tree themselves to pick patches up
> but rather, historically, patches on the fsl-mc bus were picked by Greg
> KH.

OK, copied Greg in.

Dave

> Ioana
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


From sudeep.holla at arm.com  Thu Mar 13 07:00:21 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 13 Mar 2025 14:00:21 +0000
Subject: [PATCH v2 4/4] KVM: arm64: Release the ownership of the hyp rx
 buffer to Trustzone
In-Reply-To: <20250313121559.GB7356@willie-the-truck>
References: <20250227181750.3606372-1-sebastianene@google.com>
 <20250227181750.3606372-5-sebastianene@google.com>
 <20250305004522.GC31667@willie-the-truck>
 <20250305094104.vctshdtgdukno2aj@bogus>
 <20250305193425.GA32246@willie-the-truck>
 <Z8ltm55D1jrv8QtX@bogus>
 <20250313121559.GB7356@willie-the-truck>
Message-ID: <Z9Lk9QwAGhYxk8lC@bogus>

On Thu, Mar 13, 2025 at 12:15:59PM +0000, Will Deacon wrote:
> On Thu, Mar 06, 2025 at 09:40:43AM +0000, Sudeep Holla wrote:
> > On Wed, Mar 05, 2025 at 07:34:26PM +0000, Will Deacon wrote:
> > > On Wed, Mar 05, 2025 at 09:41:04AM +0000, Sudeep Holla wrote:
> > > > On Wed, Mar 05, 2025 at 12:45:23AM +0000, Will Deacon wrote:
> > > > > Hmm, the FFA spec is characteristically unclear as to whether or not we
> > > > > need to release the rx buffer in the case that the flags indicate use of
> > > > > the rx buffer but the returned partition count is 0.
> > > > >
> > > > > Sudeep -- do you know what we should be doing in that case?
> > > > >
> > > >
> > > > We need to call RX_RELEASE here. I went back to the spec to confirm the
> > > > same again.
> > > >
> > > > v1.2 EAC0 spec Section 7.2.2.4.2 Transfer of buffer ownership
> > > > (Or just look for the section title in any version of the spec)
> > > > "
> > > > 2. Ownership transfer for the RX buffer takes place as follows.
> > > >     2. For a framework message,
> > > >        1. Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership
> > > >        of the caller?s RX buffer from the Producer to the Consumer.
> > > > 3. For both types of messages, an invocation of the following FF-A ABIs
> > > >     transfers the ownership from the Consumer to the Producer.
> > > >        1. FFA_MSG_WAIT ...
> > > >        2. FFA_RX_RELEASE.
> > > > "
> > > >
> > > > Hope that helps, can dig deeper if there are any ambiguities around this.
> > >
> > > Thanks Sudeep, but that also makes it sound like we need the RX_RELEASE
> > > even if we're not using the RX buffer per the input flags. :/
> > >
> >
> > Good spot, I had forgotten about the input flags that can avoid using the
> > buffer. I will see if we can improve the spec in that regards.
>
> Thanks. In the meantime, what do you think is the correct behaviour in that
> case? I guess _not_ doing the release when the flags don't request the RX
> buffer? In other words:
>
>
> 	if (flags & PARTITION_INFO_GET_RETURN_COUNT_ONLY)
> 		goto out_unlock;
>
> 	if (!count)
> 		goto release_rx;
>
> 	[...]
>
> 	if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
> 		ffa_to_smccc_res(res, FFA_RET_ABORTED);
> 		goto release_rx;
> 	}
>
> 	memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
> release_rx:
> 	ffa_rx_release(&_res);
> out_unlock:
> 	hyp_spin_unlock(&host_buffers.lock);
> }
>
>
> What do you reckon?

Yes matches my understanding. I also cross checked with FF-A spec authors
to be sure. Now I got to fix that in the driver, currently it releases
buffer unconditionally which is wrong ?.

-- 
Regards,
Sudeep


From vladimir.oltean at nxp.com  Thu Mar 13 06:50:41 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 13 Mar 2025 15:50:41 +0200
Subject: [PATCH v4 net-next 00/14] Add more feautues for ENETC v4 - round
 2
In-Reply-To: <20250311053830.1516523-1-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
Message-ID: <20250313135041.uex3gvhpbmnh4hmp@skbuf>

On Tue, Mar 11, 2025 at 01:38:16PM +0800, Wei Fang wrote:
> This patch set adds the following features.
> 1. Compared with ENETC v1, the formats of tables and command BD of ENETC
> v4 have changed significantly, and the two are not compatible. Therefore,
> in order to support the NETC Table Management Protocol (NTMP) v2.0, we
> introduced the netc-lib driver and added support for MAC address filter
> table and RSS table.
> 2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
> 3. Add RSS support for i.MX95 ENETC PF.
> 4. Add loopback support for i.MX95 ENETC PF.

Can you please fix the "feautues" typo in the cover letter title? It
will get used for the merge commit.


From robin.murphy at arm.com  Thu Mar 13 07:12:06 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 14:12:06 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
 <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
 <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
 <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
 <016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
Message-ID: <b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>

On 2025-03-13 1:06 pm, Robin Murphy wrote:
> On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
>> On 13.03.2025 12:01, Robin Murphy wrote:
>>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>>> [...]
>>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my 
>>>> tests I
>>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>>> relevant kernel log:
>>>
>>> ...and the bug-flushing-out begins!
>>>
>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>> 00000000000003e8
>>>> Mem abort info:
>>>> ?? ? ESR = 0x0000000096000004
>>>> ?? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>> ?? ? SET = 0, FnV = 0
>>>> ?? ? EA = 0, S1PTW = 0
>>>> ?? ? FSC = 0x04: level 0 translation fault
>>>> Data abort info:
>>>> ?? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>> ?? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>> ?? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>> [00000000000003e8] user address but active_mm is swapper
>>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>>> Modules linked in:
>>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>> pc : devm_kmalloc+0x2c/0x114
>>>> lr : rk_iommu_of_xlate+0x30/0x90
>>>> ...
>>>> Call trace:
>>>> ?? ?devm_kmalloc+0x2c/0x114 (P)
>>>> ?? ?rk_iommu_of_xlate+0x30/0x90
>>>
>>> Yeah, looks like this is doing something a bit questionable which can't
>>> work properly. TBH the whole dma_dev thing could probably be cleaned up
>>> now that we have proper instances, but for now does this work?
>>
>> Yes, this patch fixes the problem I've observed.
>>
>> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>
>> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver and
>> I doubt it can be cleaned up.
> 
> On the contrary I suspect they both can - it all dates back to when we 
> had the single global platform bus iommu_ops and the SoC drivers were 
> forced to bodge their own notion of multiple instances, but with the 
> modern core code, ops are always called via a valid IOMMU instance or 
> domain, so in principle it should always be possible to get at an 
> appropriate IOMMU device now. IIRC it was mostly about allocating and 
> DMA-mapping the pagetables in domain_alloc, where the private notion of 
> instances didn't have enough information, but domain_alloc_paging solves 
> that.

Bah, in fact I think I am going to have to do that now, since although 
it doesn't crash, rk_domain_alloc_paging() will also be failing for the 
same reason. Time to find a PSU for the RK3399 board, I guess...

(Or maybe just move the dma_dev assignment earlier to match Exynos?)

Thanks,
Robin.


From Frank.li at nxp.com  Thu Mar 13 07:17:32 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 10:17:32 -0400
Subject: [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250312213757.GA709739@bhelgaas>
References: <20250310-pci_fixup_addr-v10-5-409dafc950d1@nxp.com>
 <20250312213757.GA709739@bhelgaas>
Message-ID: <Z9Lo/PWsjE5Yq0Du@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 04:37:57PM -0500, Bjorn Helgaas wrote:
> On Mon, Mar 10, 2025 at 04:16:43PM -0400, Frank Li wrote:
> > parent_bus_offset in resource_entry can indicate address information just
> > ahead of PCIe controller. Most system's bus fabric use 1:1 map between
> > input and output address. but some hardware like i.MX8QXP doesn't use 1:1
> > map. See below diagram:
>
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -478,6 +478,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> >  	bridge->ops = &dw_pcie_ops;
> >  	bridge->child_ops = &dw_child_pcie_ops;
> >
> > +	/*
> > +	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
> > +	 * so have to call dw_pcie_init_parent_bus_offset() after init
> > +	 * pp->io_base.
> > +	 */
> > +	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
> > +	if (ret)
> > +		return ret;
>
> The ordering in dw_pcie_host_init() doesn't look right to me.  We have
> this:
>
>   dw_pcie_host_init
>     dw_pcie_get_resources
>     dw_pcie_cfg0_setup
>     devm_pci_alloc_host_bridge
>     win = resource_list_first_type(&bridge->windows, IORESOURCE_IO)
>     pp->io_base = pci_pio_to_address(win->res->start)
>     bridge->ops = ...
>     bridge->child_ops = ...
>     dw_pcie_init_parent_bus_offset
>     pp->ops->init
>
> devm_pci_alloc_host_bridge() is generic, so it obviously can't depend
> on any dwc-specific things.  I think the ordering should be more like
> this:
>
>   dw_pcie_host_init
>     devm_pci_alloc_host_bridge             # generic
>     dw_pcie_get_resources                  # dwc RP and EP
>
>     dw_pcie_cfg0_setup
>     win = resource_list_first_type(&bridge->windows, IORESOURCE_IO)
>     pp->io_base = pci_pio_to_address(win->res->start)
>     dw_pcie_init_parent_bus_offset
>
>     bridge->ops = ...
>     bridge->child_ops = ...
>     pp->ops->init
>
> and everything in the second block (dw_pcie_cfg0_setup() through
> dw_pcie_init_parent_bus_offset()) is strictly DT-related resource
> setup and could all go in a dw_pcie_host_get_resources() or similar.

It is not related with these patch series. I can change it if you like.

Frank

>
> >  	if (pp->ops->init) {
> >  		ret = pp->ops->init(pp);
> >  		if (ret)
> >
> > --
> > 2.34.1
> >


From cki-project at redhat.com  Thu Mar 13 07:22:02 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 13 Mar 2025 14:22:02 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc6,
 upstream-arm-next, 78e3fd2b)
Message-ID: <04580.125031310220411118@us-mta-557.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1714960581

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1714960581-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From luca.ceresoli at bootlin.com  Thu Mar 13 07:25:17 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 13 Mar 2025 15:25:17 +0100
Subject: [PATCH] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
Message-ID: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>

When aperture_remove_all_conflicting_devices() fails, the current code
returns without going through the rollback actions at the end of the
function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
undone.

Fix by using a goto statament, as done for the previous and following error
conditions.

Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
The offending commit is not yet merged into master, and even less in a
released kernel, so this does not need to go through stable.
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..b4273e678d26dbc3dee2014266d61470da4e8010 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -365,9 +365,10 @@ static int mxsfb_probe(struct platform_device *pdev)
 	 * located anywhere in RAM
 	 */
 	ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
-	if (ret)
-		return dev_err_probe(&pdev->dev, ret,
-				     "can't kick out existing framebuffers\n");
+	if (ret) {
+		dev_err_probe(&pdev->dev, ret, "can't kick out existing framebuffers\n");
+		goto err_unload;
+	}
 
 	ret = drm_dev_register(drm, 0);
 	if (ret)

---
base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From purvayeshi550 at gmail.com  Thu Mar 13 07:25:41 2025
From: purvayeshi550 at gmail.com (Purva Yeshi)
Date: Thu, 13 Mar 2025 19:55:41 +0530
Subject: [PATCH v2] dt-bindings: pwm: Convert lpc32xx-pwm.txt to YAML
In-Reply-To: <b2f6a357-a468-4526-a1b6-69ab2c643b2c@kernel.org>
References: <20250312122750.6391-1-purvayeshi550@gmail.com>
 <b2f6a357-a468-4526-a1b6-69ab2c643b2c@kernel.org>
Message-ID: <70cab705-c656-48bd-9b65-841f68c41d40@gmail.com>

On 13/03/25 16:34, Krzysztof Kozlowski wrote:
> On 12/03/2025 13:27, Purva Yeshi wrote:
>> Convert the existing `lpc32xx-pwm.txt` bindings documentation into a
>> YAML schema (`nxp,lpc3220-pwm.yaml`).
>>
>> Set `"#pwm-cells"` to `const: 3` for expected PWM cell properties.
>>
>> Signed-off-by: Purva Yeshi <purvayeshi550 at gmail.com>
>> ---
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> 
> ---
> 
> <form letter>
> This is an automated instruction, just in case, because many review tags
> are being ignored. If you know the process, you can skip it (please do
> not feel offended by me posting it here - no bad intentions intended).
> If you do not know the process, here is a short explanation:
> 
> Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
> of patchset, under or above your Signed-off-by tag, unless patch changed
> significantly (e.g. new properties added to the DT bindings). Tag is
> "received", when provided in a message replied to you on the mailing
> list. Tools like b4 can help here. However, there's no need to repost
> patches *only* to add the tags. The upstream maintainer will do that for
> tags received on the version they apply.
> 
> Full context and explanation:
> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
> </form letter>
> 
> Best regards,
> Krzysztof

Hi Krzysztof,

Thank you for your review! I will include your Reviewed-by tag in the 
next version if no significant changes are made.

Best regards,
Purva Yeshi


From Frank.li at nxp.com  Thu Mar 13 07:32:20 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 10:32:20 -0400
Subject: [PATCH v10 08/10] PCI: dwc: Print warning message when
 cpu_addr_fixup() exists
In-Reply-To: <20250312220424.GA711004@bhelgaas>
References: <20250310-pci_fixup_addr-v10-8-409dafc950d1@nxp.com>
 <20250312220424.GA711004@bhelgaas>
Message-ID: <Z9LsdEmMiRvRopKS@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 05:04:24PM -0500, Bjorn Helgaas wrote:
> On Mon, Mar 10, 2025 at 04:16:46PM -0400, Frank Li wrote:
> > If the parent 'ranges' property in DT correctly describes the address
> > translation, the cpu_addr_fixup() callback is not needed. Print a warning
> > message to inform users to correct their DT files.
>
> > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > @@ -1125,6 +1125,8 @@ int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
> >
> >  	fixup = pci->ops->cpu_addr_fixup;
> >  	if (fixup) {
> > +		dev_warn_once(pci->dev, "cpu_addr_fixup() usage detected. Please fix DT!\n");
>
> I don't think we need this.  The mere presence of .cpu_addr_fixup()
> doesn't tell us the DT is broken.  When we have .cpu_addr_fixup(), the
> DT is only broken if DT tells us something different than
> .cpu_addr_fixup() tells us.  And we already warn about that in the
> "reg_addr != fixup_addr" case.

It is encourage people to fix dts first and remove .cpu_addr_fixup().
Most case below "...redundant" is not printed at all at most case, even
there are .cpu_addr_fixup().

>
> > +
> >  		fixup_addr = fixup(pci, cpu_phy_addr);
> >  		if (reg_addr == fixup_addr) {
> >  			dev_info(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
>
> This message is really just a hint that DT is fine and
> .cpu_addr_fixup() is redundant but harmless.  If you want a dev_warn()
> here to encourage people to remove .cpu_addr_fixup(), I'm fine with
> that.

It is encourage people remove .cpu_addr_fixup() because dts already fixed.

>
> Seems like "dev_warn()" would be enough, probably no need for
> "dev_warn_once()" since we should only run this once per controller
> anyway, so I don't think we'll get spammed with messages.


From Frank.li at nxp.com  Thu Mar 13 07:27:05 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 10:27:05 -0400
Subject: [PATCH v10 09/10] PCI: dwc: ep: Ensure proper iteration over
 outbound map windows
In-Reply-To: <20250312214700.GA710620@bhelgaas>
References: <20250310-pci_fixup_addr-v10-9-409dafc950d1@nxp.com>
 <20250312214700.GA710620@bhelgaas>
Message-ID: <Z9LrOY27J47WfdPv@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 04:47:00PM -0500, Bjorn Helgaas wrote:
> On Mon, Mar 10, 2025 at 04:16:47PM -0400, Frank Li wrote:
> > Most systems' PCIe outbound map windows have non-zero physical addresses,
> > but the possibility of encountering zero increased with commit
> > ("PCI: dwc: ep: Add bus_addr_base for outbound window").
>
> What is this commit?  I don't see it in the tree, and I don't see it
> in this series.

Sorry, it refer to old version of this series. It should be

PCI: dwc: Use parent_bus_offset

>
> It look like it might be a fixup for something in this series.  In
> that case it should go *before* the other commit (or be squashed into
> it if it's logically part of it).

Yes it should before PCI: dwc: Use parent_bus_offset to support bisect.

>
> I don't think this series touches ep->ob_window_map, so if it's a fix
> it looks like it could go anywhere earlier.

dw_pcie_ep_outbound_atu() touch ob_window_map.

Frank

>
> > 'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
> > some hardware, which trims high address bits through bus fabric before
> > sending to the PCIe controller.
> >
> > Replace the iteration logic with 'for_each_set_bit()' to ensure only
> > allocated map windows are iterated when determining the ATU index from a
> > given address.
> >
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> > change from v9 to v10
> > - remove commit hash value
> >
> > change from v8 to v9
> > - new patch
> > ---
> >  drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > index 62bc71ad20719..e333855633a77 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > @@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
> >  	u32 index;
> >  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> >
> > -	for (index = 0; index < pci->num_ob_windows; index++) {
> > +	for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
> >  		if (ep->outbound_addr[index] != addr)
> >  			continue;
> >  		*atu_index = index;
> >
> > --
> > 2.34.1
> >


From leo.yan at arm.com  Thu Mar 13 07:40:05 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 14:40:05 +0000
Subject: [PATCH 4/7] coresight: Add claim tag warnings and debug messages
In-Reply-To: <20250211103945.967495-5-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-5-james.clark@linaro.org>
Message-ID: <20250313144005.GQ9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:40AM +0000, James Clark wrote:
> 
> Add a dev_dbg() message so that external debugger conflicts are more
> visible. There are multiple reasons for -EBUSY so a message for this
> particular one could be helpful. Add errors for and enumerate all the
> other cases that are impossible.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-core.c | 48 ++++++++++++--------
>  drivers/hwtracing/coresight/coresight-priv.h |  5 +-
>  2 files changed, 34 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 7b53165c93af..7fe5d5d432c4 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -133,16 +133,6 @@ static inline u32 coresight_read_claim_tags(struct csdev_access *csa)
>                          csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMCLR));
>  }
> 
> -static inline bool coresight_is_claimed_self_hosted(struct csdev_access *csa)
> -{
> -       return coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED;
> -}
> -
> -static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
> -{
> -       return coresight_read_claim_tags(&csdev->access) != 0;
> -}
> -
>  static inline void coresight_set_self_claim_tag(struct csdev_access *csa)
>  {
>         csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
> @@ -169,18 +159,40 @@ static inline void coresight_clear_self_claim_tag(struct csdev_access *csa)
>   */
>  int coresight_claim_device_unlocked(struct coresight_device *csdev)
>  {
> +       int tag;
> +       struct csdev_access *csa;
> +
>         if (WARN_ON(!csdev))
>                 return -EINVAL;
> 
> -       if (coresight_is_claimed_any(csdev))
> +       csa = &csdev->access;
> +       tag = coresight_read_claim_tags(csa);
> +
> +       switch (tag) {
> +       case CORESIGHT_CLAIM_FREE:
> +               coresight_set_self_claim_tag(csa);
> +               if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED)
> +                       return 0;
> +

It would be a rare case if a failure happens here.  Seems to me, it
would be valuable to print a log for this edge case.

Otherwise, looks good to me.

> +               /* There was a race setting the tag, clean up and fail */
> +               coresight_clear_self_claim_tag(csa);
>                 return -EBUSY;
> 
> -       coresight_set_self_claim_tag(&csdev->access);
> -       if (coresight_is_claimed_self_hosted(&csdev->access))
> -               return 0;
> -       /* There was a race setting the tag, clean up and fail */
> -       coresight_clear_self_claim_tag(&csdev->access);
> -       return -EBUSY;
> +       case CORESIGHT_CLAIM_EXTERNAL:
> +               /* External debug is an expected state, so log and report BUSY */
> +               dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
> +               return -EBUSY;
> +
> +       default:
> +       case CORESIGHT_CLAIM_SELF_HOSTED:
> +       case CORESIGHT_CLAIM_INVALID:
> +               /*
> +                * Warn here because we clear a lingering self hosted tag
> +                * on probe, so other tag combinations are impossible.
> +                */
> +               dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
> +               return -EBUSY;
> +       }
>  }
>  EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
> 
> @@ -205,7 +217,7 @@ EXPORT_SYMBOL_GPL(coresight_claim_device);
>   */
>  void coresight_disclaim_device_unlocked(struct csdev_access *csa)
>  {
> -       if (coresight_is_claimed_self_hosted(csa))
> +       if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED)
>                 coresight_clear_self_claim_tag(csa);
>         else
>                 /*
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index cc7ff1e36ef4..a83113225797 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -36,7 +36,10 @@ extern const struct device_type coresight_dev_type[];
>   * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
>   */
>  #define CORESIGHT_CLAIM_MASK           GENMASK(1, 0)
> -#define CORESIGHT_CLAIM_SELF_HOSTED    BIT(1)
> +#define CORESIGHT_CLAIM_FREE           0
> +#define CORESIGHT_CLAIM_EXTERNAL       1
> +#define CORESIGHT_CLAIM_SELF_HOSTED    2
> +#define CORESIGHT_CLAIM_INVALID                3
> 
>  #define TIMEOUT_US             100
>  #define BMVAL(val, lsb, msb)   ((val & GENMASK(msb, lsb)) >> lsb)
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From tzimmermann at suse.de  Thu Mar 13 07:40:43 2025
From: tzimmermann at suse.de (Thomas Zimmermann)
Date: Thu, 13 Mar 2025 15:40:43 +0100
Subject: [PATCH] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
In-Reply-To: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>
References: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>
Message-ID: <468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>

Hi

Am 13.03.25 um 15:25 schrieb Luca Ceresoli:
> When aperture_remove_all_conflicting_devices() fails, the current code
> returns without going through the rollback actions at the end of the
> function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
> undone.
>
> Fix by using a goto statament, as done for the previous and following error
> conditions.
>
> Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
> The offending commit is not yet merged into master, and even less in a
> released kernel, so this does not need to go through stable.
> ---
>   drivers/gpu/drm/mxsfb/mxsfb_drv.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..b4273e678d26dbc3dee2014266d61470da4e8010 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -365,9 +365,10 @@ static int mxsfb_probe(struct platform_device *pdev)
>   	 * located anywhere in RAM
>   	 */
>   	ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
> -	if (ret)
> -		return dev_err_probe(&pdev->dev, ret,
> -				     "can't kick out existing framebuffers\n");
> +	if (ret) {
> +		dev_err_probe(&pdev->dev, ret, "can't kick out existing framebuffers\n");
> +		goto err_unload;
> +	}

I must have missed that when I reviewed the patch. But this call should 
happen much earlier. right at the top of the probe function before 
drm_dev_alloc(). Conflicting drivers need to be kicked out before 
setting up DRM. Could you please send a patch to move the call to the 
top? No extra cleanup would be required then.

Best regards
Thomas

>   
>   	ret = drm_dev_register(drm, 0);
>   	if (ret)
>
> ---
> base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
> change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34
>
> Best regards,

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)



From mwalle at kernel.org  Thu Mar 13 07:41:55 2025
From: mwalle at kernel.org (Michael Walle)
Date: Thu, 13 Mar 2025 15:41:55 +0100
Subject: [PATCH] arm64: dts: ti: k3-am62p-j722s: add rng node
Message-ID: <20250313144155.2382316-1-mwalle@kernel.org>

Add the node for the random number generator inside the crypto module.

Signed-off-by: Michael Walle <mwalle at kernel.org>
---
This was tested on a J722S/AM67A. Also, according to the TRM this is the
MCU instance of the SA3UL. But it's defined in -main.dtsi. Is this
correct?
---
 arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
index 6e3beb5c2e01..e868e006318e 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
@@ -227,9 +227,17 @@ crypto: crypto at 40900000 {
 		reg = <0x00 0x40900000 0x00 0x1200>;
 		#address-cells = <2>;
 		#size-cells = <2>;
+		ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
+
 		dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
 		       <&main_pktdma 0x7507 0>;
 		dma-names = "tx", "rx1", "rx2";
+
+		rng: rng at 40910000 {
+			compatible = "inside-secure,safexcel-eip76";
+			reg = <0x00 0x40910000 0x0 0x7d>;
+			interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
+		};
 	};
 
 	secure_proxy_sa3: mailbox at 43600000 {
-- 
2.39.5



From lee at kernel.org  Thu Mar 13 07:53:06 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 14:53:06 +0000
Subject: (subset) [PATCH v6 3/3] dt-bindings: mfd:
 atmel,sama5d2-flexcom: add microchip,sama7d65-flexcom
In-Reply-To: <9656d46ee0255b9aba404d77d2d204376a9cb248.1736522006.git.Ryan.Wanner@microchip.com>
References: <cover.1736522006.git.Ryan.Wanner@microchip.com>
 <9656d46ee0255b9aba404d77d2d204376a9cb248.1736522006.git.Ryan.Wanner@microchip.com>
Message-ID: <174187758697.3701280.18234838828113464973.b4-ty@kernel.org>

On Fri, 10 Jan 2025 08:25:42 -0700, Ryan.Wanner at microchip.com wrote:
> Add flexcom binding documentation for sama7d65.
> 
> Consolidated entries into one enum to match proper coding style.
> 
> 

Applied, thanks!

[3/3] dt-bindings: mfd: atmel,sama5d2-flexcom: add microchip,sama7d65-flexcom
      commit: c37ee2ed38391eef476fea6af8eccd0d31f5ed98

--
Lee Jones [???]



From leo.yan at arm.com  Thu Mar 13 07:54:56 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 14:54:56 +0000
Subject: [PATCH 2/7] coresight: Convert disclaim functions to take a
 struct cs_access
In-Reply-To: <20250211103945.967495-3-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-3-james.clark@linaro.org>
Message-ID: <20250313145456.GR9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:38AM +0000, James Clark wrote:

[...]

>  static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>  {
> -       return coresight_read_claim_tags(csdev) != 0;
> +       return coresight_read_claim_tags(&csdev->access) != 0;
>  }

Likewise other claim functions, can coresight_is_claimed_any() change its
argument type from struct coresight_device to struct csdev_access?

Thanks,
Leo


From florian.fainelli at broadcom.com  Thu Mar 13 08:13:39 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Thu, 13 Mar 2025 08:13:39 -0700
Subject: [PATCH v2] mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
In-Reply-To: <20250311165946.28190-1-kamal.dasu@broadcom.com>
References: <20250311165946.28190-1-kamal.dasu@broadcom.com>
Message-ID: <06ee4b30-e4c8-4670-9054-b30827ca8931@broadcom.com>



On 3/11/2025 9:59 AM, Kamal Dasu wrote:
> cqhci timeouts observed on brcmstb platforms during suspend:
>    ...
>    [  164.832853] mmc0: cqhci: timeout for tag 18
>    ...
> 
> Adding cqhci_suspend()/resume() calls to disable cqe
> in sdhci_brcmstb_suspend()/resume() respectively to fix
> CQE timeouts seen on PM suspend.
> 
> Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)")
> Cc: stable at vger.kernel.org
> Signed-off-by: Kamal Dasu <kamal.dasu at broadcom.com>
> ---
>   drivers/mmc/host/sdhci-brcmstb.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 0ef4d578ade8..48cdcba0f39c 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -503,8 +503,15 @@ static int sdhci_brcmstb_suspend(struct device *dev)
>   	struct sdhci_host *host = dev_get_drvdata(dev);
>   	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>   	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +	int ret;

Hopefully this won't be causing a possibly uninitialized warning.

Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
-- 
Florian



From luca.ceresoli at bootlin.com  Thu Mar 13 08:14:11 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 13 Mar 2025 16:14:11 +0100
Subject: [PATCH] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
In-Reply-To: <468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>
References: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>
	<468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>
Message-ID: <20250313161411.4604a1a1@booty>

Hello Thomas,

On Thu, 13 Mar 2025 15:40:43 +0100
Thomas Zimmermann <tzimmermann at suse.de> wrote:

> > @@ -365,9 +365,10 @@ static int mxsfb_probe(struct platform_device *pdev)
> >   	 * located anywhere in RAM
> >   	 */
> >   	ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
> > -	if (ret)
> > -		return dev_err_probe(&pdev->dev, ret,
> > -				     "can't kick out existing framebuffers\n");
> > +	if (ret) {
> > +		dev_err_probe(&pdev->dev, ret, "can't kick out existing framebuffers\n");
> > +		goto err_unload;
> > +	}  
> 
> I must have missed that when I reviewed the patch. But this call should 
> happen much earlier. right at the top of the probe function before 
> drm_dev_alloc(). Conflicting drivers need to be kicked out before 
> setting up DRM. Could you please send a patch to move the call to the 
> top? No extra cleanup would be required then.

Sure, sending v2 in a moment.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From luca.ceresoli at bootlin.com  Thu Mar 13 08:21:25 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 13 Mar 2025 16:21:25 +0100
Subject: [PATCH v2] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
Message-ID: <20250313-mxsfb_probe-fix-rollback-on-error-v2-1-38374088e8c7@bootlin.com>

When aperture_remove_all_conflicting_devices() fails, the current code
returns without going through the rollback actions at the end of the
function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
undone.

Fix by moving this call at the very beginning of the probe function, so
that no rollback is needed if it fails. Conflicting drivers need to be
kicked out before setting up DRM anyway.

Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
Suggested-by: Thomas Zimmermann <tzimmermann at suse.de>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
The offending commit is not yet merged into master, and even less in a
released kernel, so this does not need to go through stable.

Changes in v2:
- move this call at the beginning instead of adding a goto
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..ee64053d381448360140c419fed1dc4fe9f7c68e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -352,14 +352,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 	struct drm_device *drm;
 	int ret;
 
-	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
-	if (IS_ERR(drm))
-		return PTR_ERR(drm);
-
-	ret = mxsfb_load(drm, device_get_match_data(&pdev->dev));
-	if (ret)
-		goto err_free;
-
 	/*
 	 * Remove early framebuffers (ie. simplefb). The framebuffer can be
 	 * located anywhere in RAM
@@ -369,6 +361,14 @@ static int mxsfb_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, ret,
 				     "can't kick out existing framebuffers\n");
 
+	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	ret = mxsfb_load(drm, device_get_match_data(&pdev->dev));
+	if (ret)
+		goto err_free;
+
 	ret = drm_dev_register(drm, 0);
 	if (ret)
 		goto err_unload;

---
base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From wens at kernel.org  Thu Mar 13 05:44:40 2025
From: wens at kernel.org (Chen-Yu Tsai)
Date: Thu, 13 Mar 2025 20:44:40 +0800
Subject: [GIT PULL] Allwinner device tree changes for 6.15
Message-ID: <Z9LTOHJDY2p0lNG0@wens.tw>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git sunxi-dt-for-6.15

for you to fetch changes up to a8181e6861fec3068f393d77ff81b2aaf4ea4203:

  arm64: dts: allwinner: a100: Add CPU Operating Performance Points table (2025-02-22 21:17:50 +0800)

----------------------------------------------------------------
Allwinner device tree changes for 6.15

- New board support: NetCube Systems Kumquat
- Enable USB and LED on Anbernic RG35XX
- Fix reboot GPIO detection logic on Anbernic RG35XX
- Disable (non-existent) battery thermistor on Anbernic RG35XX
- Add CPU OPP table for A100

----------------------------------------------------------------
Chris Morgan (4):
      arm64: dts: allwinner: h700: Set cpusldo to always-on for RG35XX
      arm64: dts: allwinner: h700: Add LED1 for Anbernic RG35XX
      arm64: dts: allwinner: h700: Add USB Host for RG35XX-H
      arm64: dts: allwinner: rg35xx: Add no-thermistor property for battery

Lukas Schmid (4):
      dt-bindings: vendor-prefixes: Add NetCube Systems Austria name
      dt-bindings: arm: sunxi: Add NetCube Systems Kumquat board
      ARM: dts: sunxi: add uart1_pe pinctrl for sun8i-v3s
      ARM: dts: sunxi: add support for NetCube Systems Kumquat

Shuosheng Huang (1):
      arm64: dts: allwinner: a100: Add CPU Operating Performance Points table

 Documentation/devicetree/bindings/arm/sunxi.yaml   |   5 +
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 arch/arm/boot/dts/allwinner/Makefile               |   2 +
 .../dts/allwinner/sun8i-v3s-netcube-kumquat.dts    | 276 +++++++++++++++++++++
 arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi         |   6 +
 .../dts/allwinner/sun50i-a100-allwinner-perf1.dts  |   5 +
 .../boot/dts/allwinner/sun50i-a100-cpu-opp.dtsi    |  90 +++++++
 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi     |   8 +
 .../allwinner/sun50i-h700-anbernic-rg35xx-2024.dts |  18 +-
 .../allwinner/sun50i-h700-anbernic-rg35xx-h.dts    |  23 ++
 10 files changed, 434 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/allwinner/sun8i-v3s-netcube-kumquat.dts
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a100-cpu-opp.dtsi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/eee91d91/attachment.sig>

From nunodasneves at linux.microsoft.com  Thu Mar 13 08:56:18 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Thu, 13 Mar 2025 08:56:18 -0700
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <CAMvTesAPeLBfYVa5TGx-o6p+0g_Q1bn6s+nZK5i7NK8QGyfbTA@mail.gmail.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com>
 <5e3e8c30-912c-4fe3-bfac-1ae21242473b@linux.microsoft.com>
 <CAMvTesAPeLBfYVa5TGx-o6p+0g_Q1bn6s+nZK5i7NK8QGyfbTA@mail.gmail.com>
Message-ID: <6ba21efb-7065-44d7-9cee-265a0c137f0c@linux.microsoft.com>

On 3/13/2025 12:34 AM, Tianyu Lan wrote:
> On Thu, Mar 13, 2025 at 3:45?AM Nuno Das Neves
> <nunodasneves at linux.microsoft.com> wrote:
>>
>> On 3/10/2025 6:01 AM, Tianyu Lan wrote:
>>> On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
>>> <nunodasneves at linux.microsoft.com> wrote:
>>>>
>>>> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
>>>> SynIC event ring buffer for each SINT.
>>>>
>>>> This will be used by the mshv driver, but must be tracked independently
>>>> since the driver module could be removed and re-inserted.
>>>>
>>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>>>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
>>>
>>> It's better to expose a function to check the tail instead of exposing
>>> hv_synic_eventring_tail directly.
>>>
>> What is the advantage of using a function for this? We need to both set
>> and get the tail.
> 
> We may add lock or check to avoid race conditions and this depends on the
> user case. This is why I want to see how mshv driver uses it.
> 
>>
>>> BTW, how does mshv driver use hv_synic_eventring_tail? Which patch
>>> uses it in this series?
>>>
>> This variable stores indices into the synic eventring page (one for each
>> SINT, and per-cpu). Each SINT has a ringbuffer of u32 messages. The tail
>> index points to the latest one.
>>
>> This is only used for doorbell messages today. The message in this case is
>> a port number which is used to lookup and invoke a callback, which signals
>> ioeventfd(s), to notify the VMM of a guest MMIO write.
>>
>> It is used in patch 10.
> 
> I found "extern u8 __percpu **hv_synic_eventring_tail;" in the
> drivers/hv/mshv_root.h of patch 10.
> I seem to miss the code to use it.
> 
> +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> +                           const union hv_stats_object_identity *identity);
> +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> +                                  u64 page_struct_count, u32 host_access,
> +                                  u32 flags, u8 acquire);
> +
> +extern struct mshv_root mshv_root;
> +extern enum hv_scheduler_type hv_scheduler_type;
> +extern u8 __percpu **hv_synic_eventring_tail;
> +
> +#endif /* _MSHV_ROOT_H_ */
> 

It is used in mshv_synic.c in synic_event_ring_get_queued_port():

diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
new file mode 100644
index 000000000000..e7782f92e339
--- /dev/null
+++ b/drivers/hv/mshv_synic.c
@@ -0,0 +1,665 @@
<snip>
+static u32 synic_event_ring_get_queued_port(u32 sint_index)
+{
+	struct hv_synic_event_ring_page **event_ring_page;
+	volatile struct hv_synic_event_ring *ring;
+	struct hv_synic_pages *spages;
+	u8 **synic_eventring_tail;
+	u32 message;
+	u8 tail;
+
+	spages = this_cpu_ptr(mshv_root.synic_pages);
+	event_ring_page = &spages->synic_event_ring_page;
+	synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
+	tail = (*synic_eventring_tail)[sint_index];


From ltykernel at gmail.com  Thu Mar 13 09:00:18 2025
From: ltykernel at gmail.com (Tianyu Lan)
Date: Fri, 14 Mar 2025 00:00:18 +0800
Subject: [PATCH v5 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <6ba21efb-7065-44d7-9cee-265a0c137f0c@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-8-git-send-email-nunodasneves@linux.microsoft.com>
 <CAMvTesAW-9Mo0oY6UUh2anp6DQCSsVCUhBiV2-bKp2VD_N0DYw@mail.gmail.com>
 <5e3e8c30-912c-4fe3-bfac-1ae21242473b@linux.microsoft.com>
 <CAMvTesAPeLBfYVa5TGx-o6p+0g_Q1bn6s+nZK5i7NK8QGyfbTA@mail.gmail.com> <6ba21efb-7065-44d7-9cee-265a0c137f0c@linux.microsoft.com>
Message-ID: <CAMvTesCUOTAkiGHq2eh9N7MA86-ZFbLTGaypjKHU8fE0cmc1Dg@mail.gmail.com>

On Thu, Mar 13, 2025 at 11:56?PM Nuno Das Neves
<nunodasneves at linux.microsoft.com> wrote:
>
> On 3/13/2025 12:34 AM, Tianyu Lan wrote:
> > On Thu, Mar 13, 2025 at 3:45?AM Nuno Das Neves
> > <nunodasneves at linux.microsoft.com> wrote:
> >>
> >> On 3/10/2025 6:01 AM, Tianyu Lan wrote:
> >>> On Thu, Feb 27, 2025 at 7:09?AM Nuno Das Neves
> >>> <nunodasneves at linux.microsoft.com> wrote:
> >>>>
> >>>> Add a pointer hv_synic_eventring_tail to track the tail pointer for the
> >>>> SynIC event ring buffer for each SINT.
> >>>>
> >>>> This will be used by the mshv driver, but must be tracked independently
> >>>> since the driver module could be removed and re-inserted.
> >>>>
> >>>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> >>>> Reviewed-by: Wei Liu <wei.liu at kernel.org>
> >>>
> >>> It's better to expose a function to check the tail instead of exposing
> >>> hv_synic_eventring_tail directly.
> >>>
> >> What is the advantage of using a function for this? We need to both set
> >> and get the tail.
> >
> > We may add lock or check to avoid race conditions and this depends on the
> > user case. This is why I want to see how mshv driver uses it.
> >
> >>
> >>> BTW, how does mshv driver use hv_synic_eventring_tail? Which patch
> >>> uses it in this series?
> >>>
> >> This variable stores indices into the synic eventring page (one for each
> >> SINT, and per-cpu). Each SINT has a ringbuffer of u32 messages. The tail
> >> index points to the latest one.
> >>
> >> This is only used for doorbell messages today. The message in this case is
> >> a port number which is used to lookup and invoke a callback, which signals
> >> ioeventfd(s), to notify the VMM of a guest MMIO write.
> >>
> >> It is used in patch 10.
> >
> > I found "extern u8 __percpu **hv_synic_eventring_tail;" in the
> > drivers/hv/mshv_root.h of patch 10.
> > I seem to miss the code to use it.
> >
> > +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> > +                           const union hv_stats_object_identity *identity);
> > +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> > +                                  u64 page_struct_count, u32 host_access,
> > +                                  u32 flags, u8 acquire);
> > +
> > +extern struct mshv_root mshv_root;
> > +extern enum hv_scheduler_type hv_scheduler_type;
> > +extern u8 __percpu **hv_synic_eventring_tail;
> > +
> > +#endif /* _MSHV_ROOT_H_ */
> >
>
> It is used in mshv_synic.c in synic_event_ring_get_queued_port():
>
> diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
> new file mode 100644
> index 000000000000..e7782f92e339
> --- /dev/null
> +++ b/drivers/hv/mshv_synic.c
> @@ -0,0 +1,665 @@
> <snip>
> +static u32 synic_event_ring_get_queued_port(u32 sint_index)
> +{
> +       struct hv_synic_event_ring_page **event_ring_page;
> +       volatile struct hv_synic_event_ring *ring;
> +       struct hv_synic_pages *spages;
> +       u8 **synic_eventring_tail;
> +       u32 message;
> +       u8 tail;
> +
> +       spages = this_cpu_ptr(mshv_root.synic_pages);
> +       event_ring_page = &spages->synic_event_ring_page;
> +       synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> +       tail = (*synic_eventring_tail)[sint_index];

OK. I got it. Thanks.

-- 
Thanks
Tianyu Lan


From helgaas at kernel.org  Thu Mar 13 09:02:15 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 13 Mar 2025 11:02:15 -0500
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250313055519.j3bpvsm6govd5ytk@uda0492258>
Message-ID: <20250313160215.GA736346@bhelgaas>

On Thu, Mar 13, 2025 at 11:25:19AM +0530, Siddharth Vadapalli wrote:
> On Wed, Mar 12, 2025 at 11:16:00AM -0500, Bjorn Helgaas wrote:
> > On Wed, Mar 05, 2025 at 06:50:18PM +0530, Siddharth Vadapalli wrote:
> > > Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
> > > J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
> > > to the Technical Reference Manual and Register Documentation for the J784S4
> > > SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
> > > the field for the link-state interrupt. Instead, it is BIT(10) of the
> > > "PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
> > > field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".
> > 
> > I guess the reason we want this is that on J784S4, we ignore actual
> > link-down interrupts (and we don't write STATUS_CLR_REG_SYS_2 to clear
> > the interrupt indication, so maybe there's an interrupt storm), and we
> > think some other interrupt (DPA_1, whatever that is) is actually a
> > link-down interrupt?
> 
> While it is true that actual link-down interrupts are ignored, it is not
> the case that there's an interrupt storm because the same incorrect macro
> is used to enable the interrupt line. Since the enables an interrupt for
> DPA_1 which never fires, we don't run into the situation where we are not
> clearing the interrupt (the interrupt handler will look for the same
> incorrect field to clear the interrupt if it does fire for DPA_1, but that
> doesn't happen). The 'linkdown_irq_regfield' corresponds to the
> "link-state" field not just in the J784S4 SoC, but in all SoCs supported by
> the pci-j721e.c driver. It is only in J721E that it is BIT(1)
> [LINK_DOWN macro], while in all other SoCs (J784S4 included), it is BIT(10)
> [J7200_LINK_DOWN macro since it was first added for J7200 SoC]. Matt
> probably referred to J721E's Technical Reference Manual and ended up
> incorrectly assigning "LINK_DOWN", due to which the driver is enabling
> the DPA_1 interrupt and the interrupt handler is also going to look for
> the field corresponding to receiving an interrupt for DPA_1.

So I guess without this patch, we incorrectly ignore link-down
interrupts on J784S4.  It's good to have a one-sentence motivation
like that somewhere in the commit log that we can pull out and include
in the merge commit log and the pull request.

> I can only hope that the URL will redirect to the latest version of
> the User Guide if at all it becomes invalid.

OK, thanks, I guess there's nothing more to do ;)  I guess that manual
is not really designed for collaborative development.

Thanks for the patient hand holding!

Bjorn


From tzimmermann at suse.de  Thu Mar 13 09:02:47 2025
From: tzimmermann at suse.de (Thomas Zimmermann)
Date: Thu, 13 Mar 2025 17:02:47 +0100
Subject: [PATCH v2] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
In-Reply-To: <20250313-mxsfb_probe-fix-rollback-on-error-v2-1-38374088e8c7@bootlin.com>
References: <20250313-mxsfb_probe-fix-rollback-on-error-v2-1-38374088e8c7@bootlin.com>
Message-ID: <a2f39979-459d-4581-baed-ff75e0af1bce@suse.de>

Hi

Am 13.03.25 um 16:21 schrieb Luca Ceresoli:
> When aperture_remove_all_conflicting_devices() fails, the current code
> returns without going through the rollback actions at the end of the
> function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
> undone.
>
> Fix by moving this call at the very beginning of the probe function, so
> that no rollback is needed if it fails. Conflicting drivers need to be
> kicked out before setting up DRM anyway.
>
> Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
> Suggested-by: Thomas Zimmermann <tzimmermann at suse.de>
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

The patchdiff is somewhat non-intuitive, but looks correct.

Reviewed-by: Thomas Zimmermann <tzimmermann at suse.de>

Thanks for the fix.

Best regards
Thomas

> ---
> The offending commit is not yet merged into master, and even less in a
> released kernel, so this does not need to go through stable.
>
> Changes in v2:
> - move this call at the beginning instead of adding a goto
> ---
>   drivers/gpu/drm/mxsfb/mxsfb_drv.c | 16 ++++++++--------
>   1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..ee64053d381448360140c419fed1dc4fe9f7c68e 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -352,14 +352,6 @@ static int mxsfb_probe(struct platform_device *pdev)
>   	struct drm_device *drm;
>   	int ret;
>   
> -	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
> -	if (IS_ERR(drm))
> -		return PTR_ERR(drm);
> -
> -	ret = mxsfb_load(drm, device_get_match_data(&pdev->dev));
> -	if (ret)
> -		goto err_free;
> -
>   	/*
>   	 * Remove early framebuffers (ie. simplefb). The framebuffer can be
>   	 * located anywhere in RAM
> @@ -369,6 +361,14 @@ static int mxsfb_probe(struct platform_device *pdev)
>   		return dev_err_probe(&pdev->dev, ret,
>   				     "can't kick out existing framebuffers\n");
>   
> +	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
> +	if (IS_ERR(drm))
> +		return PTR_ERR(drm);
> +
> +	ret = mxsfb_load(drm, device_get_match_data(&pdev->dev));
> +	if (ret)
> +		goto err_free;
> +
>   	ret = drm_dev_register(drm, 0);
>   	if (ret)
>   		goto err_unload;
>
> ---
> base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
> change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34
>
> Best regards,

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)



From Frank.Li at nxp.com  Thu Mar 13 08:38:36 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:36 -0400
Subject: [PATCH v11 00/11] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
Message-ID: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>

== RC side:

            ???????????                    ??????????????
 ???????    ?         ? IA: 0x8ff8_0000    ?            ?
 ? CPU ??????   ?????????????????????????  ? PCI        ?
 ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
  CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
            ?      ?  ?             ?   ?  ?            ?   PCI Addr
0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
            ?         ?             ?      ?            ?    0
0x7000_0000??????????????????????   ?      ?            ?
            ???????????         ?   ???????? CfgSpace  ???????????????
             BUS Fabric         ?          ?            ?    0
                                ?          ?            ?
                                ???????????? MemSpace  ???????????????
                        IA: 0x8000_0000    ?            ?  0x8000_0000
                                           ??????????????

Current dwc implimemnt, pci_fixup_addr() call back is needed when bus
fabric convert cpu address before send to PCIe controller.

    bus at 5f000000 {
            compatible = "simple-bus";
            #address-cells = <1>;
            #size-cells = <1>;
            ranges = <0x80000000 0x0 0x70000000 0x10000000>;

            pcie at 5f010000 {
                    compatible = "fsl,imx8q-pcie";
                    reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
                    reg-names = "dbi", "config";
                    #address-cells = <3>;
                    #size-cells = <2>;
                    device_type = "pci";
                    bus-range = <0x00 0xff>;
                    ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
                             <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
            ...
            };
    };

Device tree already can descript all address translate. Some hardware
driver implement fixup function by mask some bits of cpu address. Last
pci-imx6.c are little bit better by fetch memory resource's offset to do
fixup.

static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
{
	...
	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
	return cpu_addr - entry->offset;
}

But it is not good by using IORESOURCE_MEM to fix up io/cfg address map
although address translate is the same as IORESOURCE_MEM.

This patches to fetch untranslate range information for PCIe controller
(pcie at 5f010000: ranges). So current config ATU without cpu_fixup_addr().

== EP side:

                   Endpoint
  ?????????????????????????????????????????????????
  ?                             pcie-ep at 5f010000  ?
  ?                             ???????????????????
  ?                             ?   Endpoint     ??
  ?                             ?   PCIe         ??
  ?                             ?   Controller   ??
  ?           bus at 5f000000      ?                ??
  ?           ????????????      ?                ??
  ?           ?          ? Outbound Transfer     ??
  ????????    ?  Bus     ???????? ATU  ??????????????????
  ??     ?    ?  Fabric  ?Bus   ?                ??PCI Addr
  ?? CPU ??????          ?Addr  ?                ??0xA000_0000
  ??     ?CPU ?          ?0x8000_0000            ??
  ????????Addr????????????      ?                ??
  ?       0x7000_0000           ???????????????????
  ?????????????????????????????????????????????????

bus at 5f000000 {
        compatible = "simple-bus";
        ranges = <0x80000000 0x0 0x70000000 0x10000000>;

        pcie-ep at 5f010000 {
                reg = <0x5f010000 0x00010000>,
                      <0x80000000 0x10000000>;
                reg-names = "dbi", "addr_space";
                ...                ^^^^
        };
        ...
};

Add `bus_addr_base` to configure the outbound window address for CPU write.
The BUS fabric generally passes the same address to the PCIe EP controller,
but some BUS fabrics convert the address before sending it to the PCIe EP
controller.

Above diagram, CPU write data to outbound windows address 0x7000_0000,
Bus fabric convert it to 0x8000_0000. ATU should use BUS address
0x8000_0000 as input address and convert to PCI address 0xA000_0000.

Previously, `cpu_addr_fixup()` was used to handle address conversion. Now,
the device tree provides this information.

The both pave the road to eliminate ugle cpu_fixup_addr() callback function.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Changes in v11:
- Add patch for Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init()
- move PCI: dwc: ep: Ensure proper iteration over outbound map windows
ahead PCI: dwc: Use parent_bus_offset  to avoid broken bisect for some platfrom
- other  detail change each patches's change log.
- Link to v10: https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-0-409dafc950d1 at nxp.com

Changes in v10:
- Remove patch PCI: Add parent_bus_offset to resource_entry because it
is detect by reg-names["config"] and reg-names["space_addr"];

- using Bjorn suggest method
https://lore.kernel.org/linux-pci/20250307233744.440476-1-helgaas at kernel.org/
- other detail change each patches's change log.
- PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup() is not necessary, but
nice clean up, so keep it.

- Still keep use_parent_dt_ranges in case some platform without cpu_addr_fixup,
which use fake address transation at DTB. If no one report warning for
sometime, we can remove it safely. Bjoin, if you think this case is rare,
you can remove it.

- Link to v9: https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com

Changes in v9:
- There are some change in patches, if need drop review-tags, let me known.
- DTS part: https://lore.kernel.org/imx/20250128211559.1582598-2-Frank.Li at nxp.com/T/#u
- Keep "use_parent_dt_ranges" flags because need below combine logic

cpu_addr_fixup  use_parent_dt_ranges
NULL		X			No difference.
!NULL		true			Use device tree parent_address informaion [1]
!NULL		false			Keep use lagency method	[2]

Generally DTS is in different maintainer tree. It need two steps to cleanup
cpu_address_fixup() to avoid function block.
1. Update dts, which reflect the correct bus fabric behavior.
2. set "use_parent_dt_ranges" to true, then remove "cpu_address_fixup()" callback
in platform driver.

Bjorn's comments in https://lore.kernel.org/imx/20250123190900.GA650360 at bhelgaas/

> After all cpu_address_fixup() removed, we can remove use_parent_dt_ranges
> in one clean up patches.
>
>
  ...
>  dw_pcie_rd_other_conf
>  dw_pcie_wr_other_conf
>    dw_pcie_prog_outbound_atu() only called if pp->cfg0_io_shared,
>    after an ECAM map via dw_pcie_other_conf_map_bus() and subsequent
>    successful access; atu.cpu_addr came from pp->io_base, set by
>    dw_pcie_host_init() from pci_pio_to_address(), which I'm pretty
>    sure returns a CPU address.

io_base is parent_bus_address

>    So this still looks wrong to me.  In addition, I think doing the
>    ATU setup in *_map() and restore in *rd/wr_other_conf() is ugly
>    and looks unreliable.

....

>  dw_pcie_pme_turn_off
>    atu.cpu_addr came from pp.msg_res, set by
>    dw_pcie_host_request_msg_tlp_res() to a CPU address at the end of
>    the first MMIO bridge window.  This one also looks wrong to me.

Fixed at this version.

- Link to v8: https://lore.kernel.org/r/20241119-pci_fixup_addr-v8-0-c4bfa5193288 at nxp.com

Changes in v8:
- Add mani's review tages
- use rename use_dt_ranges to use_parent_dt_ranges
- Add dev_warn_once to reminder to fix their dt file and remove
cpu_fixup_addr() callback.
- rename dw_pcie_get_untranslate_addr() to dw_pcie_get_parent_addr()
- Link to v7: https://lore.kernel.org/r/20241029-pci_fixup_addr-v7-0-8310dc24fb7c at nxp.com

Changes in v7:
- fix
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410291546.kvgEWJv7-lkp at intel.com/
- Link to v6: https://lore.kernel.org/r/20241028-pci_fixup_addr-v6-0-ebebcd8fd4ff at nxp.com

Changes in v6:
- merge RC and EP to one thread!
- Link to v5: https://lore.kernel.org/r/20241015-pci_fixup_addr-v5-0-ced556c85270 at nxp.com

Changes in v5:
- update address order in diagram patches.
- remove confused 0x5f00_0000 range
- update patch1's commit message.
- Link to v4: https://lore.kernel.org/r/20241008-pci_fixup_addr-v4-0-25e5200657bc at nxp.com

Changes in v4:
- Improve commit message by add driver source code path.
- Link to v3: https://lore.kernel.org/r/20240930-pci_fixup_addr-v3-0-80ee70352fc7 at nxp.com

Changes in v3:
- see each patch
- Link to v2: https://lore.kernel.org/r/20240926-pci_fixup_addr-v2-0-e4524541edf4 at nxp.com

Changes in v2:
- see each patch
- Link to v1: https://lore.kernel.org/r/20240924-pci_fixup_addr-v1-0-57d14a91ec4f at nxp.com

---
Bjorn Helgaas (3):
      PCI: dwc: Move cfg0 setup to dw_pcie_cfg0_setup()
      PCI: dwc: Add helper dw_pcie_init_parent_bus_offset()
      PCI: dwc: Use parent_bus_offset

Frank Li (8):
      PCI: dwc: Use resource start as iomap() input in dw_pcie_pme_turn_off()
      PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
      PCI: dwc: Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init()
      PCI: dwc: Use devicetree 'ranges' property to get rid of cpu_addr_fixup() callback
      PCI: dwc: ep: Add parent_bus_addr for outbound window
      PCI: dwc: ep: Ensure proper iteration over outbound map windows
      PCI: dwc: Print warning message when cpu_addr_fixup() exists
      PCI: imx6: Remove cpu_addr_fixup()

 drivers/pci/controller/dwc/pci-imx6.c             | 18 +----
 drivers/pci/controller/dwc/pcie-designware-ep.c   | 21 ++++--
 drivers/pci/controller/dwc/pcie-designware-host.c | 75 +++++++++++++-------
 drivers/pci/controller/dwc/pcie-designware.c      | 85 ++++++++++++++++++-----
 drivers/pci/controller/dwc/pcie-designware.h      | 19 ++++-
 5 files changed, 146 insertions(+), 72 deletions(-)
---
base-commit: 5fcc194143ce5918ea0790a16323a844c5ab9499
change-id: 20240924-pci_fixup_addr-a8568f9bbb34

Best regards,
---
Frank Li <Frank.Li at nxp.com>



From Frank.Li at nxp.com  Thu Mar 13 08:38:37 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:37 -0400
Subject: [PATCH v11 01/11] PCI: dwc: Use resource start as iomap() input in
 dw_pcie_pme_turn_off()
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-1-01d2313502ab@nxp.com>

The msg_res region translates writes into PCIe Message TLPs. Previously we
mapped this region using atu.cpu_addr, the input address programmed into
the ATU.

"cpu_addr" is a misnomer because when a bus fabric translates addresses
between the CPU and the ATU, the ATU input address is different from the
CPU address.  A future patch will rename "cpu_addr" and correct the value
to be the ATU input address instead of the CPU physical address.

Map the msg_res region before writing to it using the msg_res resource
start, a CPU physical address.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- none

change from v9 to v10
- use bjorn's suggested commit messaage.

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ffaded8f2df7b..ae3fd2a5dbf85 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -908,7 +908,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	if (ret)
 		return ret;
 
-	mem = ioremap(atu.cpu_addr, pci->region_align);
+	mem = ioremap(pci->pp.msg_res->start, pci->region_align);
 	if (!mem)
 		return -ENOMEM;
 

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:38 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:38 -0400
Subject: [PATCH v11 02/11] PCI: dwc: Rename cpu_addr to parent_bus_addr for
 ATU configuration
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-2-01d2313502ab@nxp.com>

Rename `cpu_addr` to `parent_bus_addr` in the DesignWare ATU configuration.
The ATU translates parent bus addresses to PCI addresses, which are often
the same as CPU addresses but can differ in systems where the bus fabric
translates addresses before passing them to the PCIe controller. This
renaming clarifies the purpose and avoids confusion.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- none

change from v9 to v10
- rename header file's cpu_addr for dw_pcie_prog_inbound_atu() and
dw_pcie_prog_ep_inbound_atu();

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  8 +++---
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++----
 drivers/pci/controller/dwc/pcie-designware.c      | 34 +++++++++++------------
 drivers/pci/controller/dwc/pcie-designware.h      |  7 +++--
 4 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 8e07d432e74f2..80ac2f9e88eb5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -128,7 +128,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 }
 
 static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
-				  dma_addr_t cpu_addr, enum pci_barno bar,
+				  dma_addr_t parent_bus_addr, enum pci_barno bar,
 				  size_t size)
 {
 	int ret;
@@ -146,7 +146,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
 	}
 
 	ret = dw_pcie_prog_ep_inbound_atu(pci, func_no, free_win, type,
-					  cpu_addr, bar, size);
+					  parent_bus_addr, bar, size);
 	if (ret < 0) {
 		dev_err(pci->dev, "Failed to program IB window\n");
 		return ret;
@@ -181,7 +181,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
 		return ret;
 
 	set_bit(free_win, ep->ob_window_map);
-	ep->outbound_addr[free_win] = atu->cpu_addr;
+	ep->outbound_addr[free_win] = atu->parent_bus_addr;
 
 	return 0;
 }
@@ -333,7 +333,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.cpu_addr = addr;
+	atu.parent_bus_addr = addr;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ae3fd2a5dbf85..1206b26bff3f2 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -616,7 +616,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.cpu_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -641,7 +641,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -667,7 +667,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -736,7 +736,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.cpu_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -758,7 +758,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.cpu_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -902,7 +902,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.cpu_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 145e7f579072c..9d0a5f75effcc 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -470,25 +470,25 @@ static inline u32 dw_pcie_enable_ecrc(u32 val)
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu)
 {
-	u64 cpu_addr = atu->cpu_addr;
+	u64 parent_bus_addr = atu->parent_bus_addr;
 	u32 retries, val;
 	u64 limit_addr;
 
 	if (pci->ops && pci->ops->cpu_addr_fixup)
-		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
+		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
 
-	limit_addr = cpu_addr + atu->size - 1;
+	limit_addr = parent_bus_addr + atu->size - 1;
 
-	if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {
 		return -EINVAL;
 	}
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT,
 			      lower_32_bits(limit_addr));
@@ -502,7 +502,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      upper_32_bits(atu->pci_addr));
 
 	val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no);
-	if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&
+	if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
 	    dw_pcie_ver_is_ge(pci, 460A))
 		val |= PCIE_ATU_INCREASE_REGION_SIZE;
 	if (dw_pcie_ver_is(pci, 490A))
@@ -545,13 +545,13 @@ static inline void dw_pcie_writel_atu_ib(struct dw_pcie *pci, u32 index, u32 reg
 }
 
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size)
+			     u64 parent_bus_addr, u64 pci_addr, u64 size)
 {
 	u64 limit_addr = pci_addr + size - 1;
 	u32 retries, val;
 
 	if ((limit_addr & ~pci->region_limit) != (pci_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(pci_addr, pci->region_align) || !size) {
 		return -EINVAL;
 	}
@@ -568,9 +568,9 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 				      upper_32_bits(limit_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	val = type;
 	if (upper_32_bits(limit_addr) > upper_32_bits(pci_addr) &&
@@ -597,18 +597,18 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 }
 
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size)
+				int type, u64 parent_bus_addr, u8 bar, size_t size)
 {
 	u32 retries, val;
 
-	if (!IS_ALIGNED(cpu_addr, pci->region_align) ||
-	    !IS_ALIGNED(cpu_addr, size))
+	if (!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, size))
 		return -EINVAL;
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, type |
 			      PCIE_ATU_FUNC_NUM(func_no));
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 501d9ddfea163..d0d8c622a6e8b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -343,7 +343,7 @@ struct dw_pcie_ob_atu_cfg {
 	u8 func_no;
 	u8 code;
 	u8 routing;
-	u64 cpu_addr;
+	u64 parent_bus_addr;
 	u64 pci_addr;
 	u64 size;
 };
@@ -491,9 +491,10 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu);
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size);
+			     u64 parent_bus_addr, u64 pci_addr, u64 size);
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size);
+				int type, u64 parent_bus_addr,
+				u8 bar, size_t size);
 void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
 void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:39 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:39 -0400
Subject: [PATCH v11 03/11] PCI: dwc: Move cfg0 setup to
 dw_pcie_cfg0_setup()
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-3-01d2313502ab@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

Move pp->cfg0 setup to dw_pcie_cfg0_setup(). No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Change from v10 v0 v11
- none

Change from v9 to v10
v9 means https://lore.kernel.org/linux-pci/20250307233744.440476-1-helgaas at kernel.org/T/#maa0134c1826bffcccab6028c7732a13f7adcec4d

- move dw_pcie_cfg0_setup() ahead of dw_pcie_host_request_msg_tlp_res() to
nice git diff and easy to review.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 40 +++++++++++++++--------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 1206b26bff3f2..c57831902686e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -392,6 +392,29 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
 	return 0;
 }
 
+static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+	if (!res) {
+		dev_err(dev, "Missing \"config\" reg space\n");
+		return -ENODEV;
+	}
+
+	pp->cfg0_size = resource_size(res);
+	pp->cfg0_base = res->start;
+
+	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
+	if (IS_ERR(pp->va_cfg0_base))
+		return PTR_ERR(pp->va_cfg0_base);
+
+	return 0;
+}
+
 static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -423,10 +446,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct resource_entry *win;
 	struct pci_host_bridge *bridge;
-	struct resource *res;
 	int ret;
 
 	raw_spin_lock_init(&pp->lock);
@@ -435,18 +456,9 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (ret)
 		return ret;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
-	if (!res) {
-		dev_err(dev, "Missing \"config\" reg space\n");
-		return -ENODEV;
-	}
-
-	pp->cfg0_size = resource_size(res);
-	pp->cfg0_base = res->start;
-
-	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
-	if (IS_ERR(pp->va_cfg0_base))
-		return PTR_ERR(pp->va_cfg0_base);
+	ret = dw_pcie_cfg0_setup(pp);
+	if (ret)
+		return ret;
 
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:40 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:40 -0400
Subject: [PATCH v11 04/11] PCI: dwc: Move devm_pci_alloc_host_bridge() to
 the beginning of dw_pcie_host_init()
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-4-01d2313502ab@nxp.com>

Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init().
Since devm_pci_alloc_host_bridge() is common code that doesn't depend on
any DWC resource, moving it earlier improves code logic and readability.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index c57831902686e..52a441662cabe 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -452,6 +452,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 
 	raw_spin_lock_init(&pp->lock);
 
+	bridge = devm_pci_alloc_host_bridge(dev, 0);
+	if (!bridge)
+		return bridge;
+
+	pp->bridge = bridge;
+
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
 		return ret;
@@ -460,12 +466,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (ret)
 		return ret;
 
-	bridge = devm_pci_alloc_host_bridge(dev, 0);
-	if (!bridge)
-		return -ENOMEM;
-
-	pp->bridge = bridge;
-
 	/* Get the I/O range from DT */
 	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
 	if (win) {

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:41 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:41 -0400
Subject: [PATCH v11 05/11] PCI: dwc: Add helper
 dw_pcie_init_parent_bus_offset()
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-5-01d2313502ab@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

Set pci->parent_bus_offset based on the parent bus address from the
"config" (Root complex mode) and "addr_space" (Endpoint mode).

.cpu_addr_fixup(cpu_phy_addr). (if implemented) should return the parent
bus address corresponding according to cpu_phy_addr.

Sets pp->parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Add use_parent_dt_ranges to detect some fake bus translation at platform,
which have not .cpu_addr_fixup(). Set use_parent_dt_ranges true explicitly
at platform that have .cpu_addr_fixup() and fixed DTB's range. If not one
report "fake bus translation" for sometime, this flags can be removed
safely.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- add cpu physical and parent bus address information when no equal
- remove "Using this flag also avoids the usage of 'cpu_addr_fixup'
callback implementation in the driver." for use_parent_dt_ranges.
- change dev_warn_once to dev_warn because only call once.

change from v9 to v10
v9: https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-4-3c4bb506f665 at nxp.com/

- use help funtion dw_pcie_init_parent_bus_offset() because both EP and RC
use simular logic.
- still use use_parent_dt_ranges to detect fake bus translation for
no .cpu_addr_fixup()'s platfrom incase block exist platform.
---
 drivers/pci/controller/dwc/pcie-designware.c | 48 ++++++++++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h | 12 +++++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 9d0a5f75effcc..f17a25fe55a5b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -16,6 +16,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 #include <linux/types.h>
@@ -1105,3 +1106,50 @@ void dw_pcie_setup(struct dw_pcie *pci)
 
 	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
 }
+
+int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
+				   resource_size_t cpu_phy_addr)
+{
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
+	u64 reg_addr, fixup_addr;
+	int index;
+
+	/* Look up reg_name address on parent bus */
+	index = of_property_match_string(np, "reg-names", reg_name);
+
+	if (index < 0) {
+		dev_err(dev, "Missed reg-name: %s, Broken DTB file\n", reg_name);
+		return -EINVAL;
+	}
+
+	of_property_read_reg(np, index, &reg_addr, NULL);
+
+	fixup = pci->ops->cpu_addr_fixup;
+	if (fixup) {
+		fixup_addr = fixup(pci, cpu_phy_addr);
+		if (reg_addr == fixup_addr) {
+			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
+				 cpu_phy_addr, reg_name, index,
+				 fixup_addr, fixup);
+		} else {
+			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; DT is broken\n",
+				 cpu_phy_addr, reg_name,
+				 index, fixup_addr);
+			reg_addr = fixup_addr;
+		}
+	} else if (!pci->use_parent_dt_ranges) {
+		if (reg_addr != cpu_phy_addr) {
+			dev_warn(dev, "Your DTB try to use fake translation, Please check parent's ranges property. cpu physical addr: %#010llx, parent bus addr: %#010llx",
+				 cpu_phy_addr, reg_addr);
+			return 0;
+		}
+	}
+
+	pci->parent_bus_offset = cpu_phy_addr - reg_addr;
+	dev_info(dev, "%s parent bus offset is %#010llx\n",
+		 reg_name, pci->parent_bus_offset);
+
+	return 0;
+}
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index d0d8c622a6e8b..bfed9d45aba9f 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -445,6 +445,7 @@ struct dw_pcie {
 	void __iomem		*atu_base;
 	resource_size_t		atu_phys_addr;
 	size_t			atu_size;
+	resource_size_t		parent_bus_offset;
 	u32			num_ib_windows;
 	u32			num_ob_windows;
 	u32			region_align;
@@ -465,6 +466,15 @@ struct dw_pcie {
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
 	bool			suspended;
+	/*
+	 * This flag indicates that the vendor driver uses devicetree 'ranges'
+	 * property to allow iATU to use the Intermediate Address (IA) for
+	 * outbound mapping.
+	 *
+	 * If use_parent_dt_ranges is false, warning will print if IA is not
+	 * equal to cpu physical address. Indicate dtb use a fake translation.
+	 */
+	bool			use_parent_dt_ranges;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
@@ -500,6 +510,8 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
+int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
+				   resource_size_t cpu_phy_addr);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:42 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:42 -0400
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-6-01d2313502ab@nxp.com>

The 'ranges' property at PCI controller parent bus can indicate address
translation information. Most system's bus fabric use 1:1 map between input
and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.
See below diagram:

            ???????????                    ??????????????
 ???????    ?         ? IA: 0x8ff8_0000    ?            ?
 ? CPU ??????   ?????????????????????????  ? PCI        ?
 ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
  CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
            ?      ?  ?             ?   ?  ?            ?   PCI Addr
0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
            ?         ?             ?      ?            ?    0
0x7000_0000??????????????????????   ?      ?            ?
            ???????????         ?   ???????? CfgSpace  ???????????????
             BUS Fabric         ?          ?            ?    0
                                ?          ?            ?
                                ???????????? MemSpace  ???????????????
                        IA: 0x8000_0000    ?            ?  0x8000_0000
                                           ??????????????

bus at 5f000000 {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	ranges = <0x80000000 0x0 0x70000000 0x10000000>;

	pcie at 5f010000 {
		compatible = "fsl,imx8q-pcie";
		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
		reg-names = "dbi", "config";
		#address-cells = <3>;
		#size-cells = <2>;
		device_type = "pci";
		bus-range = <0x00 0xff>;
		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
	...
	};
};

Term Intermediate address (IA) here means the address just before PCIe
controller. After ATU use this IA instead CPU address, cpu_addr_fixup() can
be removed.

Use reg-name "config" to detect parent_bus_addr_offset. Suppose the offset
is the same for all kinds of address translation.

Just set parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- update commit message's first paragraph because switch to use 'config'
to get address translation.
- move dw_pcie_init_parent_bus_offset() ahead of bridge->ops = ...

change from v9 to v10
- call helper dw_pcie_init_parent_bus_offset()

chagne from v8 to v9
- use resoure_entry parent_bus_offset to simple code logic
- add check for use_parent_dt_ranges and cpu_addr_fixup to make sure only
one set.

Change from v7 to v8
- Add dev_warning_once at dw_pcie_iatu_detect() to reminder
cpu_addr_fixup() user to correct their code
- use 'use_parent_dt_ranges' control enable use dt parent bus node ranges.
- rename dw_pcie_get_untranslate_addr to dw_pcie_get_parent_addr().
- of_property_read_reg() already have comments, so needn't add more.
- return actual err code from function

Change from v6 to v7
Add a resource_size_t parent_bus_addr local varible to fix 32bit build
error.
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410291546.kvgEWJv7-lkp at intel.com/

Chagne from v5 to v6
-add comments for of_property_read_reg().

Change from v4 to v5
- remove confused 0x5f00_0000 range in sample dts.
- reorder address at above diagram.

Change from v3 to v4
- none

Change from v2 to v3
- %s/cpu_untranslate_addr/parent_bus_addr/g
- update diagram.
- improve commit message.

Change from v1 to v2
- update because patch1 change get untranslate address method.
- add using_dtbus_info in case break back compatibility for exited platform.
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 52a441662cabe..482d8ff751526 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -474,6 +474,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 		pp->io_base = pci_pio_to_address(win->res->start);
 	}
 
+	/*
+	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
+	 * so have to call dw_pcie_init_parent_bus_offset() after init
+	 * pp->io_base.
+	 */
+	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
+	if (ret)
+		return ret;
+
 	/* Set default bus ops */
 	bridge->ops = &dw_pcie_ops;
 	bridge->child_ops = &dw_child_pcie_ops;

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:43 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:43 -0400
Subject: [PATCH v11 07/11] PCI: dwc: ep: Add parent_bus_addr for outbound
 window
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-7-01d2313502ab@nxp.com>

                   Endpoint
  ?????????????????????????????????????????????????
  ?                             pcie-ep at 5f010000  ?
  ?                             ???????????????????
  ?                             ?   Endpoint     ??
  ?                             ?   PCIe         ??
  ?                             ?   Controller   ??
  ?           bus at 5f000000      ?                ??
  ?           ????????????      ?                ??
  ?           ?          ? Outbound Transfer     ??
  ????????    ?  Bus     ???????? ATU  ??????????????????
  ??     ?    ?  Fabric  ?Bus   ?                ??PCI Addr
  ?? CPU ??????          ?Addr  ?                ??0xA000_0000
  ??     ?CPU ?          ?0x8000_0000            ??
  ????????Addr????????????      ?                ??
  ?       0x7000_0000           ???????????????????
  ?????????????????????????????????????????????????

Use 'ranges' property in DT to configure the iATU outbound window address.
The bus fabric generally passes the same address to the PCIe EP controller,
but some bus fabrics map the address before sending it to the PCIe EP
controller.

Above diagram, CPU write data to outbound windows address 0x7000_0000, Bus
fabric map it to 0x8000_0000. ATU should use bus address 0x8000_0000 as
input address and map to PCI address 0xA000_0000 (dynamic alloc and assign
from pci device driver in host side).

Previously, 'cpu_addr_fixup()' was used to handle address conversion. Now,
the device tree provides this information, preferring a common method.

bus at 5f000000 {
	compatible = "simple-bus";
	ranges = <0x80000000 0x0 0x70000000 0x10000000>;

	pcie-ep at 5f010000 {
		reg = <0x80000000 0x10000000>;
		reg-names ="addr_space";
		...
	};
	...
};

'ranges' in bus at 5f000000 descript how address map from CPU address to bus
address.

Use `of_property_read_reg()` to obtain the bus address and set it to the
ATU correctly, eliminating the need for vendor-specific cpu_addr_fixup().

Use reg-name "addr_space" to detect parent_bus_addr_offset.

Just set parent_bus_offset, but doesn't use it, so no functional change
intended yet.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
Change from v10 to v11
- none

Change from v9 to v10
- drop mani's review tag because big change.
- call help funciton dw_pcie_init_parent_bus_offset().

Change from v8 to v9
- change bus_addr_base to parent_bus_addr
- fix dw_pcie_find_index() address compare, which cause atu allocate
failure when run many time test.

Change from v7 to v8
- Add Mani's reviewedby tag
- s/convert/map in commit message
- update comments for of_property_read_reg()
- use 'use_parent_dt_ranges'

Change from v6 to v7
- none

Change from v5 to v6
- update diagram
- Add comments for of_property_read_reg()
- Remove unrelated 0x5f00_0000 in commit message

Change from v3 to v4
- change parent_bus_addr to u64 to fix 32bit build error
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410230328.BTHareG1-lkp at intel.com/

Change from v2 to v3
- Add using_dtbus_info to control if use device tree bus ranges
information.
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 80ac2f9e88eb5..d69d76c150d92 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -915,6 +915,14 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->phys_base = res->start;
 	ep->addr_size = resource_size(res);
 
+	/*
+	 * artpec6_pcie_cpu_addr_fixup() use ep->phys_base. so call
+	 * dw_pcie_init_parent_bus_offset after init ep->phys_base.
+	 */
+	ret = dw_pcie_init_parent_bus_offset(pci, "addr_space", ep->phys_base);
+	if (ret)
+		return ret;
+
 	if (ep->ops->pre_init)
 		ep->ops->pre_init(ep);
 

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:44 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:44 -0400
Subject: [PATCH v11 08/11] PCI: dwc: ep: Ensure proper iteration over
 outbound map windows
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-8-01d2313502ab@nxp.com>

Most systems' PCIe outbound map windows have non-zero physical addresses,
but the possibility of encountering zero increased after following commit
("PCI: dwc: Use parent_bus_offset").

'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
some hardware, which trims high address bits through bus fabric before
sending to the PCIe controller.

Replace the iteration logic with 'for_each_set_bit()' to ensure only
allocated map windows are iterated when determining the ATU index from a
given address.

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- change refer commit

change from v9 to v10
- remove commit hash value

change from v8 to v9
- new patch
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d69d76c150d92..4ecddab131b33 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
 	u32 index;
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	for (index = 0; index < pci->num_ob_windows; index++) {
+	for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
 		if (ep->outbound_addr[index] != addr)
 			continue;
 		*atu_index = index;

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:45 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:45 -0400
Subject: [PATCH v11 09/11] PCI: dwc: Use parent_bus_offset
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-9-01d2313502ab@nxp.com>

From: Bjorn Helgaas <bhelgaas at google.com>

We know the parent_bus_offset, either computed from a DT reg property (the
offset is the CPU physical addr - the 'config'/'addr_space' address on the
parent bus) or from a .cpu_addr_fixup() (which may have used a host bridge
window offset).

Apply that parent_bus_offset instead of calling .cpu_addr_fixup() again.

This assumes that all intermediate addresses are at the same offset from
the CPU physical addresses.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- none

change from v9 to v10
v9: https://lore.kernel.org/linux-pci/20250307233744.440476-5-helgaas at kernel.org/#R
- pp -> pci
- add ep side support
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  5 +++--
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 drivers/pci/controller/dwc/pcie-designware.c      |  3 ---
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 4ecddab131b33..e333855633a77 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -314,7 +314,8 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	ret = dw_pcie_find_index(ep, addr, &atu_index);
+	ret = dw_pcie_find_index(ep, addr - pci->parent_bus_offset,
+				 &atu_index);
 	if (ret < 0)
 		return;
 
@@ -333,7 +334,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.parent_bus_addr = addr;
+	atu.parent_bus_addr = addr - pci->parent_bus_offset;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 482d8ff751526..3e7df3d2ac269 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -637,7 +637,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.parent_bus_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base - pci->parent_bus_offset;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -662,7 +662,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -688,7 +688,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -757,7 +757,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.parent_bus_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -779,7 +779,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.parent_bus_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -923,7 +923,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.parent_bus_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index f17a25fe55a5b..8b546131b97f6 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -475,9 +475,6 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 	u32 retries, val;
 	u64 limit_addr;
 
-	if (pci->ops && pci->ops->cpu_addr_fixup)
-		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
-
 	limit_addr = parent_bus_addr + atu->size - 1;
 
 	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:46 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:46 -0400
Subject: [PATCH v11 10/11] PCI: dwc: Print warning message when
 cpu_addr_fixup() exists
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-10-01d2313502ab@nxp.com>

If the parent 'ranges' property in DT correctly describes the address
translation, the cpu_addr_fixup() callback is not needed. Print a warning
message to inform users to correct their DTB files and prepare to remove
cpu_addr_fixup().

Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v10 to v11
- change to dev_warn()
- Bjorn: this is opitional patches to encourage user fix their dtb file.

change from v9 to v10
- new patch
---
 drivers/pci/controller/dwc/pcie-designware.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 8b546131b97f6..d4dc8bf06d4c1 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1125,6 +1125,8 @@ int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
 
 	fixup = pci->ops->cpu_addr_fixup;
 	if (fixup) {
+		dev_warn(pci->dev, "cpu_addr_fixup() usage detected. Please fix your DTB!\n");
+
 		fixup_addr = fixup(pci, cpu_phy_addr);
 		if (reg_addr == fixup_addr) {
 			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",

-- 
2.34.1



From Frank.Li at nxp.com  Thu Mar 13 08:38:47 2025
From: Frank.Li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 11:38:47 -0400
Subject: [PATCH v11 11/11] PCI: imx6: Remove cpu_addr_fixup()
In-Reply-To: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
References: <20250313-pci_fixup_addr-v11-0-01d2313502ab@nxp.com>
Message-ID: <20250313-pci_fixup_addr-v11-11-01d2313502ab@nxp.com>

Remove cpu_addr_fixup() because dwc common driver already handle address
translate.

Acked-by: Richard Zhu <hongxing.zhu at nxp.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
Signed-off-by: Frank Li <Frank.Li at nxp.com>
---
change from v9 to v11
- none

Change from v8 to v9
- rebase latest linux-next (close enough to v6.14-rc1)

Change from v7 to v8
- add mani and richard's review/ack tag
- use varible 'use_parent_dt_ranges'

Change from v2 to v7
- none
Change from v1 to v2
- set using_dtbus_info true
---
 drivers/pci/controller/dwc/pci-imx6.c | 18 +-----------------
 1 file changed, 1 insertion(+), 17 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 90ace941090f9..d1eb535df73e1 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1217,22 +1217,6 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
 		regulator_disable(imx_pcie->vpcie);
 }
 
-static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
-{
-	struct imx_pcie *imx_pcie = to_imx_pcie(pcie);
-	struct dw_pcie_rp *pp = &pcie->pp;
-	struct resource_entry *entry;
-
-	if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_CPU_ADDR_FIXUP))
-		return cpu_addr;
-
-	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
-	if (!entry)
-		return cpu_addr;
-
-	return cpu_addr - entry->offset;
-}
-
 /*
  * In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
  * register is reserved, so the generic DWC implementation of sending the
@@ -1263,7 +1247,6 @@ static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
 static const struct dw_pcie_ops dw_pcie_ops = {
 	.start_link = imx_pcie_start_link,
 	.stop_link = imx_pcie_stop_link,
-	.cpu_addr_fixup = imx_pcie_cpu_addr_fixup,
 };
 
 static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
@@ -1645,6 +1628,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	pci->use_parent_dt_ranges = true;
 	if (imx_pcie->drvdata->mode == DW_PCIE_EP_TYPE) {
 		ret = imx_add_pcie_ep(imx_pcie, pdev);
 		if (ret < 0)

-- 
2.34.1



From rppt at kernel.org  Thu Mar 13 08:41:47 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Thu, 13 Mar 2025 17:41:47 +0200
Subject: [PATCH v4 02/14] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250226015342.2136669-1-changyuanl@google.com>
References: <20250206132754.2596694-3-rppt@kernel.org>
 <20250226015342.2136669-1-changyuanl@google.com>
Message-ID: <Z9L8u4XP5U6iq5Gu@kernel.org>

Hi Changyuan,

On Tue, Feb 25, 2025 at 05:53:39PM -0800, Changyuan Lyu wrote:
> Hi Mike,
> 
> On Thu,  6 Feb 2025 15:27:42 +0200, Mike Rapoport <rppt at kernel.org> wrote:
> > From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> >
> > to denote areas that were reserved for kernel use either directly with
> > memblock_reserve_kern() or via memblock allocations.
> >
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > ---
> >  include/linux/memblock.h | 16 +++++++++++++++-
> >  mm/memblock.c            | 32 ++++++++++++++++++++++++--------
> >  2 files changed, 39 insertions(+), 9 deletions(-)
> >
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index e79eb6ac516f..65e274550f5d 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > ......
> > @@ -116,7 +117,19 @@ int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid,
> >  int memblock_add(phys_addr_t base, phys_addr_t size);
> >  int memblock_remove(phys_addr_t base, phys_addr_t size);
> >  int memblock_phys_free(phys_addr_t base, phys_addr_t size);
> > -int memblock_reserve(phys_addr_t base, phys_addr_t size);
> > +int __memblock_reserve(phys_addr_t base, phys_addr_t size, int nid,
> > +		       enum memblock_flags flags);
> > +
> > +static __always_inline int memblock_reserve(phys_addr_t base, phys_addr_t size)
> > +{
> > +	return __memblock_reserve(base, size, NUMA_NO_NODE, 0);
> 
> Without this patch `memblock_reserve` eventually calls `memblock_add_range`
> with `MAX_NUMNODES`, but with this patch, `memblock_reserve` calls
> `memblock_add_range` with `NUMA_NO_NODE`. Is it intended or an
> accidental typo? Thanks!

We were mixing NUMA_NO_NODE and MAX_NUMNODES for memory with undefined node
id for a while, with MAX_NUMNODES being older and NUMA_NO_NODE newer define
for the same thing.

To make sure both are treated correctly in memblock we use
numa_valid_node() to check if a range has node id set.
 
> Best,
> Changyuan

-- 
Sincerely yours,
Mike.


From mathieu.poirier at linaro.org  Thu Mar 13 08:46:50 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Thu, 13 Mar 2025 09:46:50 -0600
Subject: [PATCH v5 0/8] imx8mp: Add support to Run/Stall DSP via reset API
In-Reply-To: <20250311085812.1296243-1-daniel.baluta@nxp.com>
References: <20250311085812.1296243-1-daniel.baluta@nxp.com>
Message-ID: <Z9L96ssnL1S5z7rb@p14s>

On Tue, Mar 11, 2025 at 10:58:03AM +0200, Daniel Baluta wrote:
> This patch series adds support to control the Run/Stall DSP bits found on
> i.MX8MP via the reset controller API instead of using the syscon API.
> 
> DSP found on i.MX8MP doesn't have a direct reset line so according to hardware
> design team in order to handle assert/deassert/reset functionality we
> need to use a combination of control bits from two modules.
> 
> Audio block control module:
> 	- for Run/Stall control bits of the DSP
> 
> Debug Access Port (DAP)
> 	- for Software Reset via IMX8M_DAP_PWRCTL register
> 
> The current implementation for IMX DSP Remotproc driver and for Sound Open
> Firmware driver (already upstream) uses the following approach:
> 	- maps the Audio Block Control address via syscon API through
>           the fsl,dsp-ctrl property of the dsp node.
> 	- maps the DAP address space using directly a call to ioremap
>           with IMX8M_DAP_DEBUG macro depicting the DAP base address.
> 
> The both approaches are problematic when comes to describing the address
> spaces via the DT:
> 	- for Audio Block Control, because it uses the syscon interface
> 	- for DAP because it hardcodes de base address instead of using a dt node.
> 
> This patch series aims to fix the Audio Block control usage of the
> syscon interface and replace it with Reset Controller interface.
> 
> Main advantages of using the Reset Controller API is that we stop
> abusing the syscon interface, offer a better probe ordering, PM runtime
> support. Main critique of using the Reset Controller API is that
> Run/Stall bits are not reset bits (but according the hardware design
> team they are part of the reset proccess since there is no real reset
> line).
> 
> Initial discussion is here:
> https://patchwork.kernel.org/project/imx/patch/20250212085222.107102-6-daniel.baluta at nxp.com/
> 
> Note that we can safely remove the fsl,dsp-ctrl property usage from IMX DSP
> remoteproc driver because there is no Device Tree users.
> 
> Changes since v4:
> https://lore.kernel.org/lkml/20250305100037.373782-3-daniel.baluta at nxp.com/T/
> 	- picked-up R-b tags from Frank Li and Peng Fan
> 	- reworded commit message of patch 8/8 as per Mathieu Poirier suggestion
> 
> Changes since v3:
> https://lore.kernel.org/linux-arm-kernel/20250225102005.408773-5-daniel.baluta at nxp.com/T/
> 	- renamed resets ids as per Philipp comments
> 	- add boths resets (named them runstall and softreset) as per Philipp comments
> 
> Changes since v2:
> (https://lore.kernel.org/lkml/Z7ZNngd3wtJ5MZgl at lizhi-Precision-Tower-5810/T/)
>         - picked R-b and A-b tags
>         - use run_stall instead of reset to refer to reset controller
>           instance
>         - remove 'resets' description as it is a common property
>         - add correct include in the yaml dts snippet example
> Changes since v1:
> (https://lore.kernel.org/imx/20250219030809.GD6537 at nxa18884-linux/T/)
>         - addresed comments received on v1
>         - picked up R-b and A-b tags
> 
> Daniel Baluta (8):
>   dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
>   dt-bindings: dsp: fsl,dsp: Add resets property
>   arm64: dts: imx8mp: Use resets property
>   reset: imx8mp-audiomix: Add prefix for internal macro
>   reset: imx8mp-audiomix: Prepare the code for more reset bits
>   reset: imx8mp-audiomix: Introduce active_low configuration option
>   reset: imx8mp-audiomix: Add support for DSP run/stall
>   imx_dsp_rproc: Use reset controller API to control the DSP
> 
>  .../devicetree/bindings/dsp/fsl,dsp.yaml      | 24 +++++-
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi     |  3 +
>  drivers/remoteproc/imx_dsp_rproc.c            | 25 ++++--
>  drivers/remoteproc/imx_rproc.h                |  2 +
>  drivers/reset/reset-imx8mp-audiomix.c         | 78 +++++++++++++------
>  .../dt-bindings/reset/imx8mp-reset-audiomix.h | 13 ++++
>  6 files changed, 114 insertions(+), 31 deletions(-)
>  create mode 100644 include/dt-bindings/reset/imx8mp-reset-audiomix.h

Other than patch 3 for which I haven't received a Reviewed-by, I have applied
this set.

Thanks,
Mathieu

> 
> -- 
> 2.43.0
> 


From leo.yan at arm.com  Thu Mar 13 09:04:09 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 16:04:09 +0000
Subject: [PATCH 5/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250211103945.967495-6-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-6-james.clark@linaro.org>
Message-ID: <20250313160409.GS9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:41AM +0000, James Clark wrote:
> 
> This can be left behind from a crashed kernel after a kexec so clear it
> when probing each device. Similarly to
> coresight_disclaim_device_unlocked(), only clear it if it's already set
> to avoid races with an external debugger.
> 
> We need a csdev_access struct in etm_init_arch_data() so just replace
> the iomem pointer with a full csdev_access struct. This means all usages
> need to be updated to go through csa->base.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-catu.c  |  1 +
>  drivers/hwtracing/coresight/coresight-core.c  | 48 +++++++++++++++----
>  .../hwtracing/coresight/coresight-cti-core.c  |  2 +
>  drivers/hwtracing/coresight/coresight-etb10.c |  2 +
>  drivers/hwtracing/coresight/coresight-etm.h   |  6 +--
>  .../coresight/coresight-etm3x-core.c          | 28 +++++------
>  .../coresight/coresight-etm3x-sysfs.c         |  8 ++--
>  .../coresight/coresight-etm4x-core.c          |  2 +
>  .../hwtracing/coresight/coresight-funnel.c    |  2 +
>  .../coresight/coresight-replicator.c          |  1 +
>  .../hwtracing/coresight/coresight-tmc-core.c  |  1 +
>  include/linux/coresight.h                     |  3 ++
>  12 files changed, 73 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index d9259c0b6e64..575c2d247a90 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
>         catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
>         catu_desc.ops = &catu_ops;
> 
> +       coresight_reset_claim(&catu_desc.access);
>         drvdata->csdev = coresight_register(&catu_desc);
>         if (IS_ERR(drvdata->csdev))
>                 ret = PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 7fe5d5d432c4..97f33ffad05e 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -212,20 +212,48 @@ int coresight_claim_device(struct coresight_device *csdev)
>  EXPORT_SYMBOL_GPL(coresight_claim_device);
> 
>  /*
> - * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
> + * Clear the claim tag for the device.
> + * Returns an error if the device wasn't already claimed.
> + */
> +int coresight_reset_claim(struct csdev_access *csa)
> +{
> +       int ret;
> +
> +       CS_UNLOCK(csa->base);
> +       ret = coresight_reset_claim_unlocked(csa);
> +       CS_LOCK(csa->base);
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(coresight_reset_claim);

Maybe my question is overlapping with Mike's comment.

Callers never check the return values from coresight_reset_claim(). I am
wandering if coresight_reset_claim() can directly call
coresight_clear_self_claim_tag() for _trying_ to clear self-host tag in
probe phase. Any self claim tag issues will be deferred to detect until
enable the component.

For consistent, we might rename coresight_reset_claim() to
coresight_reset_self_claim_tag(), which acquires CS lock and clear
self claim tag.

> +/*
> + * Clear the claim tag for the device. Called with CS_UNLOCKed for the component.
> + * Returns an error if the device wasn't already claimed.
> + */
> +int coresight_reset_claim_unlocked(struct csdev_access *csa)
> +{
> +       if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED) {
> +               coresight_clear_self_claim_tag(csa);
> +               return 0;
> +       }
> +
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(coresight_reset_claim_unlocked);
> +
> +/*
> + * coresight_disclaim_device_unlocked : Clear the claim tag for the device
> + * and warn if the device wasn't already claimed.
>   * Called with CS_UNLOCKed for the component.
>   */
>  void coresight_disclaim_device_unlocked(struct csdev_access *csa)
>  {
> -       if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED)
> -               coresight_clear_self_claim_tag(csa);
> -       else
> -               /*
> -                * The external agent may have not honoured our claim
> -                * and has manipulated it. Or something else has seriously
> -                * gone wrong in our driver.
> -                */
> -               WARN_ON_ONCE(1);
> +       /*
> +        * Warn if the external agent hasn't honoured our claim
> +        * and has manipulated it. Or something else has seriously
> +        * gone wrong in our driver.
> +        */
> +       WARN_ON_ONCE(coresight_reset_claim_unlocked(csa));
>  }
>  EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
> index 073f67a41af9..389a72362f0c 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-core.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-core.c
> @@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>         cti_desc.ops = &cti_ops;
>         cti_desc.groups = drvdata->ctidev.con_groups;
>         cti_desc.dev = dev;
> +
> +       coresight_reset_claim(&cti_desc.access);
>         drvdata->csdev = coresight_register(&cti_desc);
>         if (IS_ERR(drvdata->csdev)) {
>                 ret = PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index d8bc3e776c88..b598b2c0c9bb 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
>         desc.pdata = pdata;
>         desc.dev = dev;
>         desc.groups = coresight_etb_groups;
> +
> +       coresight_reset_claim(&desc.access);
>         drvdata->csdev = coresight_register(&desc);
>         if (IS_ERR(drvdata->csdev))
>                 return PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
> index e02c3ea972c9..a89736309c27 100644
> --- a/drivers/hwtracing/coresight/coresight-etm.h
> +++ b/drivers/hwtracing/coresight/coresight-etm.h
> @@ -229,7 +229,7 @@ struct etm_config {
>   * @config:    structure holding configuration parameters.
>   */
>  struct etm_drvdata {
> -       void __iomem                    *base;
> +       struct csdev_access             csa;

I would like to extract the change for using `csdev_access` in the
ETMv3 driver into a new patch, which is irrelevant to reset self claim
tags and would significantly reduce the complexity in this patch.

Thanks,
Leo


From helgaas at kernel.org  Thu Mar 13 09:06:48 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 13 Mar 2025 11:06:48 -0500
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <b425a7c7a7d6508daf23fe7046864a498029a7ac.camel@pengutronix.de>
Message-ID: <20250313160648.GA736867@bhelgaas>

On Thu, Mar 13, 2025 at 09:54:25AM +0100, Lucas Stach wrote:
> Am Mittwoch, dem 12.03.2025 um 10:22 -0400 schrieb Frank Li:
> > On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> > > Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > > > -----Original Message-----
> > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > Sent: 2025?3?11? 23:55
> > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > > > > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > > > > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > hardcodes
> > > > > 
> > > > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > > > -----Original Message-----
> > > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > > Sent: 2025?3?10? 23:11
> > > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > > > > bhelgaas at google.com;
> > > > > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > > hardcodes
> > > > > > > 
> > > > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > > > > 
> > > > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > > > ---
> > > > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > @@ -41,7 +41,6 @@
> > > > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > > > 8)
> > > > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > > > > 
> > > > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > > > platform_device
> > > > > > > *pdev)
> > > > > > > > ?	struct dw_pcie *pci;
> > > > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > > > ?	struct device_node *np;
> > > > > > > > -	struct resource *dbi_base;
> > > > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > > > ?	int i, ret, req_cnt;
> > > > > > > > ?	u16 val;
> > > > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > > > platform_device *pdev)
> > > > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > > > ?	}
> > > > > > > > 
> > > > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > > > 0,
> > > > > > > &dbi_base);
> > > > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > > > -		return PTR_ERR(pci->dbi_base);
> > > > > > > 
> > > > > > > This makes me wonder.
> > > > > > > 
> > > > > > > IIUC this means that previously we set controller_id to
> > > > > > > 1 if the first item in devicetree "reg" was 0x33c00000,
> > > > > > > and now we will set controller_id to 1 if the devicetree
> > > > > > > "linux,pci-domain" property is 1.  This is good, but I
> > > > > > > think this new dependency on the correct
> > > > > > > "linux,pci-domain" in devicetree should be mentioned in
> > > > > > > the commit log.
> > > > > > > 
> > > > > > > My bigger worry is that we no longer set pci->dbi_base
> > > > > > > at all.  I see that the only use of pci->dbi_base in
> > > > > > > pci-imx6.c was to determine the controller_id, but this
> > > > > > > is a DWC-based driver, and the DWC core certainly uses
> > > > > > > pci->dbi_base.  Are we sure that none of those DWC core
> > > > > > > paths are important to pci-imx6.c?
> > > > > >
> > > > > > Thanks for your concerns.  Don't worry about the
> > > > > > assignment of pci->dbi_base.  If pci-imx6.c driver doesn't
> > > > > > set it. DWC core driver would set it when
> > > > > > ?dw_pcie_get_resources() is invoked.
> > > > > 
> > > > > Great, thanks!  Maybe we can amend the commit log to mention
> > > > > that and the new "linux,pci-domain" dependency.
> > > >
> > > > How about the following updates of the commit log?
> > > > 
> > > > Use the domain number replace the hardcodes to uniquely
> > > > identify different controller on i.MX8MQ platforms. No
> > > > function changes.  Please make sure the " linux,pci-domain" is
> > > > set for i.MX8MQ correctly, since ?the controller id is relied
> > > > on it totally.
> > > > 
> > > This breaks running a new kernel on an old DT without the
> > > linux,pci-domain property, which I'm absolutely no fan of. We
> > > tried really hard to keep this way around working in the i.MX
> > > world.
> > 
> > 8MQ already add linux,pci-domain since Jan, 2021
> > 
> > commit c0b70f05c87f3b09b391027c6f056d0facf331ef
> > Author: Peng Fan <peng.fan at nxp.com>
> > Date:   Fri Jan 15 11:26:57 2021 +0800
> > 
> > Only missed is pcie-ep side, which have not been used at all boards dts
> > file in upstream.
> 
> I wasn't aware of this. 2021 is quite a while ago, so I suspect that
> nobody is going to run a new kernel with a DT this old. I retract my
> objection.

Sounds good, thanks, Lucas.  We really do want to avoid breaking old
DTs, so I appreciate your highlighting of it.  Even if we believe none
of them will break, I think it's worth mentioning the
'linux,pci-domain' dependency and the commit that added it to the
.dtsi in the commit log.

Bjorn


From michael at fossekall.de  Thu Mar 13 09:20:25 2025
From: michael at fossekall.de (Michael Klein)
Date: Thu, 13 Mar 2025 17:20:25 +0100
Subject: [PATCH 2/2] ARM: dts: bananapi: add support for PHY LEDs
In-Reply-To: <7cf91323-d550-496a-a8ec-ae104c77224d@lunn.ch>
References: <20250312193629.85417-1-michael@fossekall.de>
 <20250312193629.85417-2-michael@fossekall.de>
 <4637912.LvFx2qVVIh@jernej-laptop>
 <Z9KYqlfUYxRaWnGQ@a98shuttle.de>
 <20250313104042.694c1856@donnerap.manchester.arm.com>
 <7cf91323-d550-496a-a8ec-ae104c77224d@lunn.ch>
Message-ID: <Z9MFyWGG5iNUmRNq@a98shuttle.de>

On Thu, Mar 13, 2025 at 02:17:27PM +0100, Andrew Lunn wrote:
>On Thu, Mar 13, 2025 at 10:40:42AM +0000, Andre Przywara wrote:
>> On Thu, 13 Mar 2025 09:34:50 +0100
>> Michael Klein <michael at fossekall.de> wrote:
>> > On Thu, Mar 13, 2025 at 07:07:24AM +0100, Jernej ?krabec wrote:
>> > >Dne sreda, 12. marec 2025 ob 20:36:28 Srednjeevropski standardni ?as je Michael Klein napisal(a):
>> > >> The Bananapi M1 has three LEDs connected to the RTL8211E ethernet PHY.
>> > >> Add the corresponding nodes to the device tree.
>> > >>
>> > >> Signed-off-by: Michael Klein <michael at fossekall.de>
>> > >
>> > >This is patch 2/2. Which one is patch 1/2? I got only one.
>> >
>> > https://patchwork.kernel.org/project/netdevbpf/patch/20250312193629.85417-1-michael at fossekall.de/
>> >
>> > Sorry for any inconvenience in case I messed up the patch submission.
>> >
>> > I made two commits for this change and submitted them via `git send-email
>> > HEAD^^`. The first patch went to netdev at vger.kernel.org, the second
>> > to linux-arm-kernel at lists.infradead.org, which seems logical. Have I
>> > done something wrong?
>>
>> Well, for those really small "series" it's probably better to send all
>> patches to everyone, especially if the first patch gives some context,
>> without which the second leaves people (like me) scratching their head.
>
>However, netdev does not like pathchsets which contain patches which
>should not be applied to the netdev tree. DT patches generally go
>through a different Maintainer to driver changes implementing the
>binding.
>
>So for your DT patch, you could add to the commit message something
>like:
>
>The RTL8211E ethernet PHY driver has recently gained support for
>controlling PHY LEDs via /sys/class/leds. The Bananapi M1 has three
>LEDs connected to the RTL8211E PHY.  Add the corresponding nodes to
>the device tree.

Thanks, this totally makes sense. I'll split the patch series then and 
follow-up here with the updated commit message when the netdev change is 
accepted.

-- 
Michael


From suzuki.poulose at arm.com  Thu Mar 13 09:24:03 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 13 Mar 2025 16:24:03 +0000
Subject: [PATCH v1 3/4] coresight: ctcu: Enable byte-cntr for TMC ETR
 devices
In-Reply-To: <20250310090407.2069489-4-quic_jiegan@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-4-quic_jiegan@quicinc.com>
Message-ID: <7a65353d-aa18-4c63-abb9-46344de35fc4@arm.com>

On 10/03/2025 09:04, Jie Gan wrote:
> The byte-cntr function provided by the CTCU device is used to transfer data
> from the ETR buffer to the userspace. An interrupt is triggered if the data

Why do we need a new device to transfer the data to userspace ?

> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
> handler counts the number of triggered interruptions and the read function
> will read the data from the ETR buffer if the IRQ count is greater than 0.
> Each successful read process will decrement the IRQ count by 1.

Having an interrupt is good, but see below.

> 
> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
> ---
>   drivers/hwtracing/coresight/Makefile          |   2 +-
>   .../coresight/coresight-ctcu-byte-cntr.c      | 339 ++++++++++++++++++
>   .../hwtracing/coresight/coresight-ctcu-core.c |  96 ++++-
>   drivers/hwtracing/coresight/coresight-ctcu.h  |  59 ++-
>   .../hwtracing/coresight/coresight-tmc-etr.c   |   5 +-
>   drivers/hwtracing/coresight/coresight-tmc.h   |   2 +
>   6 files changed, 493 insertions(+), 10 deletions(-)
>   create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
> 
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 8e62c3150aeb..c90a06768a18 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -52,4 +52,4 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
>   obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>   obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
> -coresight-ctcu-y := coresight-ctcu-core.o
> +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
> new file mode 100644
> index 000000000000..0d16385663f5
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/coresight.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/fs.h>
> +#include <linux/interrupt.h>
> +#include <linux/of_irq.h>
> +#include <linux/property.h>
> +#include <linux/uaccess.h>
> +
> +#include "coresight-ctcu.h"
> +#include "coresight-priv.h"
> +#include "coresight-tmc.h"
> +
> +#define BYTE_CNTR_CLASS_STR "byte-cntr-class"
> +
> +static struct class *byte_cntr_class;
> +static dev_t byte_cntr_base;
> +
> +static irqreturn_t byte_cntr_handler(int irq, void *data)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data = (struct ctcu_byte_cntr *)data;
> +
> +	atomic_inc(&byte_cntr_data->irq_cnt);
> +	wake_up(&byte_cntr_data->wq);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/* Read the data from ETR's DDR buffer. */
> +static void __ctcu_byte_cntr_read_etr_bytes(struct ctcu_byte_cntr *byte_cntr_data,
> +					    size_t *len, char **bufp)
> +{
> +	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
> +	size_t actual, bytes = byte_cntr_data->thresh_val;
> +	struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
> +	long r_offset;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	r_offset = byte_cntr_data->r_offset;
> +	if (*len >= bytes)
> +		*len = bytes;
> +	else if ((r_offset % bytes) + *len > bytes)
> +		*len = bytes - (r_offset % bytes);
> +
> +	actual = tmc_etr_buf_get_data(etr_buf, r_offset, *len, bufp);
> +	*len = actual;
> +	if (actual == bytes || (actual + r_offset) % bytes == 0)
> +		atomic_dec(&byte_cntr_data->irq_cnt);
> +}
> +

How can you safely read the ETR data while it is running ? You should
stop the ETR and then provide the data. You could potentially do things
like split the ETR buffer into two halves and switch the half used by
the ETR on interrupt and expose this to user.


> +/* Flush the remaining data in the ETR buffer after the byte cntr has stopped. */
> +static ssize_t ctcu_flush_etr_buffer(struct ctcu_byte_cntr *byte_cntr_data, size_t len,
> +				     char **bufpp)
> +{
> +	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
> +	struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
> +	ssize_t read_len = 0, remaining_len;
> +	long r_offset, w_offset;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	r_offset = byte_cntr_data->r_offset;
> +	w_offset = byte_cntr_data->w_offset;
> +	if (w_offset < r_offset)
> +		remaining_len = tmcdrvdata->size + w_offset - r_offset;
> +	else
> +		remaining_len = w_offset - r_offset;
> +
> +	if (remaining_len > len)
> +		remaining_len = len;
> +
> +	if (remaining_len > 0)
> +		read_len = tmc_etr_buf_get_data(etr_buf, r_offset, remaining_len, bufpp);
> +
> +	return read_len;
> +}
> +
> +static ssize_t ctcu_byte_cntr_copy_data(char __user *data, size_t len, char *bufp,
> +					struct ctcu_byte_cntr *byte_cntr_data,
> +					struct tmc_drvdata *tmcdrvdata)
> +{
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	if (copy_to_user(data, bufp, len))
> +		return -EFAULT;
> +
> +	byte_cntr_data->total_size += len;
> +	if (byte_cntr_data->r_offset + len >= tmcdrvdata->size)
> +		byte_cntr_data->r_offset = 0;
> +	else
> +		byte_cntr_data->r_offset += len;
> +
> +	return len;
> +}
> +
> +/* The read function for /dev/byte-cntr%d */

WHY ? WHY can't the data be exported by the existing /dev/tmc_etr* ?

> +static ssize_t ctcu_byte_cntr_read_etr_bytes(struct file *fp, char __user *data,
> +					     size_t len, loff_t *ppos)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
> +	struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
> +	char *bufp = NULL;
> +	ssize_t read_len;
> +
> +	if (!data)
> +		return -EINVAL;
> +
> +	/*
> +	 * Flush the remaining data in the ETR buffer based on the write
> +	 * offset of the ETR buffer when the byte cntr function has stopped.
> +	 */
> +	if (!byte_cntr_data->read_active || !byte_cntr_data->enable) {
> +		read_len = ctcu_flush_etr_buffer(byte_cntr_data, len, &bufp);
> +		if (read_len > 0)
> +			return ctcu_byte_cntr_copy_data(data, read_len, bufp,
> +							byte_cntr_data, tmcdrvdata);
> +
> +		return -EINVAL;
> +	}
> +
> +	if (!atomic_read(&byte_cntr_data->irq_cnt)) {
> +		if (wait_event_interruptible(byte_cntr_data->wq,
> +					     atomic_read(&byte_cntr_data->irq_cnt) > 0 ||
> +					     !byte_cntr_data->enable))
> +			return -ERESTARTSYS;
> +	}
> +
> +	__ctcu_byte_cntr_read_etr_bytes(byte_cntr_data, &len, &bufp);
> +
> +	return ctcu_byte_cntr_copy_data(data, len, bufp, byte_cntr_data, tmcdrvdata);
> +}

Could we not plug this into TMC-ETR read ?

NAK for a special file approach. As Mike mentioned you need to make sure 
we are doing this safely.

Suzuki



> +
> +/* Start the byte-cntr function when the path is enabled. */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path)
> +{
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +	struct coresight_device *sink = coresight_get_sink(path);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	int port_num;
> +
> +	if (!sink)
> +		return;
> +
> +	port_num = ctcu_get_active_port(sink, csdev);
> +	if (port_num < 0)
> +		return;
> +
> +	byte_cntr_data = &drvdata->byte_cntr_data[port_num];
> +	/* Don't start byte-cntr function when threshold is not set. */
> +	if (!byte_cntr_data->thresh_val)
> +		return;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	atomic_set(&byte_cntr_data->irq_cnt, 0);
> +	byte_cntr_data->sink = sink;
> +	byte_cntr_data->enable = true;
> +}
> +
> +/* Stop the byte-cntr function when the path is disabled. */
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path)
> +{
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +	struct coresight_device *sink = coresight_get_sink(path);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	struct tmc_drvdata *tmcdrvdata;
> +	int port_num;
> +
> +	if (!sink)
> +		return;
> +
> +	port_num = ctcu_get_active_port(sink, csdev);
> +	if (port_num < 0)
> +		return;
> +
> +	byte_cntr_data = &drvdata->byte_cntr_data[port_num];
> +	tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	/* Store the w_offset of the ETR buffer when stopping. */
> +	byte_cntr_data->w_offset = tmc_get_rwp_offset(tmcdrvdata);
> +	atomic_set(&byte_cntr_data->irq_cnt, 0);
> +	byte_cntr_data->read_active = false;
> +	byte_cntr_data->enable = false;
> +	/*
> +	 * Wakeup once to force the read function to read the remaining
> +	 * data of the ETR buffer.
> +	 */
> +	wake_up(&byte_cntr_data->wq);
> +}
> +
> +static int ctcu_byte_cntr_release(struct inode *in, struct file *fp)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
> +	struct device *dev = &byte_cntr_data->sink->dev;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	atomic_set(&byte_cntr_data->irq_cnt, 0);
> +	byte_cntr_data->read_active = false;
> +	disable_irq_wake(byte_cntr_data->byte_cntr_irq);
> +	dev_dbg(dev, "send data total size: %llu bytes, r_offset: %ld w_offset: %ld\n",
> +		byte_cntr_data->total_size, byte_cntr_data->r_offset,
> +		byte_cntr_data->w_offset);
> +
> +	return 0;
> +}
> +
> +static int ctcu_byte_cntr_open(struct inode *in, struct file *fp)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data = container_of(in->i_cdev,
> +							     struct ctcu_byte_cntr, c_dev);
> +	struct tmc_drvdata *tmcdrvdata;
> +
> +	if (byte_cntr_data->read_active)
> +		return -EBUSY;
> +
> +	if (!byte_cntr_data->thresh_val || !byte_cntr_data->sink ||
> +	    (coresight_get_mode(byte_cntr_data->sink) !=  CS_MODE_SYSFS))
> +		return -EINVAL;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	enable_irq_wake(byte_cntr_data->byte_cntr_irq);
> +	fp->private_data = byte_cntr_data;
> +	nonseekable_open(in, fp);
> +	tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
> +	/*
> +	 * The original r_offset is the w_offset of the ETR buffer at the
> +	 * start of the byte-cntr.
> +	 */
> +	byte_cntr_data->r_offset = tmc_get_rwp_offset(tmcdrvdata);
> +	byte_cntr_data->total_size = 0;
> +	byte_cntr_data->read_active = true;
> +	byte_cntr_data->enable = true;
> +
> +	return 0;
> +}
> +
> +static const struct file_operations byte_cntr_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= ctcu_byte_cntr_open,
> +	.read		= ctcu_byte_cntr_read_etr_bytes,
> +	.release	= ctcu_byte_cntr_release,
> +};
> +
> +static int ctcu_byte_cntr_register_chardev(struct ctcu_byte_cntr *byte_cntr_data,
> +					   int port_num)
> +{
> +	struct device *device;
> +	dev_t devt;
> +	int ret;
> +
> +	cdev_init(&byte_cntr_data->c_dev, &byte_cntr_fops);
> +	devt = MKDEV(MAJOR(byte_cntr_base), MINOR(byte_cntr_base) + port_num);
> +	ret = cdev_add(&byte_cntr_data->c_dev, devt, 1);
> +	if (ret < 0)
> +		return -ENOMEM;
> +
> +	device = device_create(byte_cntr_class, NULL, devt, byte_cntr_data,
> +			       byte_cntr_data->name);
> +
> +	if (IS_ERR(device))
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static void ctcu_byte_cntr_unregister_chardev(struct ctcu_drvdata *drvdata)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	int i;
> +
> +	for (i = 0; i < ETR_MAX_NUM; i++) {
> +		byte_cntr_data = &drvdata->byte_cntr_data[i];
> +		device_destroy(byte_cntr_class, byte_cntr_data->c_dev.dev);
> +	}
> +}
> +
> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	struct device_node *nd = dev->of_node;
> +	int byte_cntr_irq, ret, i;
> +
> +	ret = alloc_chrdev_region(&byte_cntr_base, 0, ETR_MAX_NUM, BYTE_CNTR_CLASS_STR);
> +	if (ret < 0)
> +		return -ENOMEM;
> +
> +	byte_cntr_class = class_create(BYTE_CNTR_CLASS_STR);
> +	if (IS_ERR(byte_cntr_class)) {
> +		unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
> +		return -ENOMEM;
> +	}
> +
> +	for (i = 0; i < etr_num; i++) {
> +		byte_cntr_data = &drvdata->byte_cntr_data[i];
> +		byte_cntr_irq = of_irq_get_byname(nd, byte_cntr_data->irq_name);
> +		if (byte_cntr_irq < 0) {
> +			ret = byte_cntr_irq;
> +			goto err_exit;
> +		}
> +
> +		ret = devm_request_irq(dev, byte_cntr_irq, byte_cntr_handler,
> +				       IRQF_TRIGGER_RISING | IRQF_SHARED,
> +				       dev_name(dev), byte_cntr_data);
> +		if (ret) {
> +			dev_err(dev, "Failed to register IRQ for %s\n",
> +				byte_cntr_data->name);
> +			goto err_exit;
> +		}
> +
> +		ret = ctcu_byte_cntr_register_chardev(byte_cntr_data, i);
> +		if (ret) {
> +			dev_err(dev, "Failed to register chardev for %s\n",
> +				byte_cntr_data->name);
> +			goto err_exit;
> +		}
> +
> +		byte_cntr_data->byte_cntr_irq = byte_cntr_irq;
> +		atomic_set(&byte_cntr_data->irq_cnt, 0);
> +		init_waitqueue_head(&byte_cntr_data->wq);
> +	}
> +
> +	return 0;
> +
> +err_exit:
> +	ctcu_byte_cntr_unregister_chardev(drvdata);
> +	class_destroy(byte_cntr_class);
> +	unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
> +	return ret;
> +}
> +
> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata)
> +{
> +	ctcu_byte_cntr_unregister_chardev(drvdata);
> +	class_destroy(byte_cntr_class);
> +	unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
> +}
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> index da35d8b4d579..5782655a5f39 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> @@ -46,16 +46,24 @@ DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
>   #define CTCU_ATID_REG_BIT(traceid)	(traceid % 32)
>   #define CTCU_ATID_REG_SIZE		0x10
>   #define CTCU_ETR0_ATID0			0xf8
> +#define CTCU_ETR0_IRQCTRL		0x6c
>   #define CTCU_ETR1_ATID0			0x108
> +#define CTCU_ETR1_IRQCTRL		0x70
>   
>   static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
>   	{
> -		.atid_offset	= CTCU_ETR0_ATID0,
> -		.port_num	= 0,
> +		.atid_offset		= CTCU_ETR0_ATID0,
> +		.irq_ctrl_offset	= CTCU_ETR0_IRQCTRL,
> +		.irq_name		= "etr0",
> +		.byte_cntr_name		= "byte-cntr0",
> +		.port_num		= 0,
>   	},
>   	{
> -		.atid_offset	= CTCU_ETR1_ATID0,
> -		.port_num	= 1,
> +		.atid_offset		= CTCU_ETR1_ATID0,
> +		.irq_ctrl_offset	= CTCU_ETR1_IRQCTRL,
> +		.irq_name		= "etr1",
> +		.byte_cntr_name		= "byte-cntr1",
> +		.port_num		= 1,
>   	},
>   };
>   
> @@ -64,6 +72,69 @@ static const struct ctcu_config sa8775p_cfgs = {
>   	.num_etr_config	= ARRAY_SIZE(sa8775p_etr_cfgs),
>   };
>   
> +static ssize_t byte_cntr_val_show(struct device *dev, struct device_attribute *attr,
> +				  char *buf)
> +{
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	int i, len = 0;
> +
> +	for (i = 0; i < ETR_MAX_NUM; i++) {
> +		if (drvdata->byte_cntr_data[i].irq_ctrl_offset)
> +			len += scnprintf(buf + len, PAGE_SIZE - len, "%u ",
> +					 drvdata->byte_cntr_data[i].thresh_val);
> +	}
> +
> +	len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
> +
> +	return len;
> +}
> +
> +static ssize_t byte_cntr_val_store(struct device *dev, struct device_attribute *attr,
> +				   const char *buf, size_t size)
> +{
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	u32 thresh_vals[ETR_MAX_NUM] = { 0 };
> +	u32 irq_ctrl_offset;
> +	int num, i;
> +
> +	num = sscanf(buf, "%i %i", &thresh_vals[0], &thresh_vals[1]);
> +	if (num <= 0 || num > ETR_MAX_NUM)
> +		return -EINVAL;
> +
> +	/* Threshold 0 disables the interruption. */
> +	guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
> +	for (i = 0; i < num; i++) {
> +		/* A small threshold will result in a large number of interruptions */
> +		if (thresh_vals[i] && thresh_vals[i] < 4096)
> +			return -EINVAL;
> +
> +		if (drvdata->byte_cntr_data[i].irq_ctrl_offset) {
> +			drvdata->byte_cntr_data[i].thresh_val = thresh_vals[i];
> +			irq_ctrl_offset = drvdata->byte_cntr_data[i].irq_ctrl_offset;
> +			CS_UNLOCK(drvdata->base);
> +			writel_relaxed(thresh_vals[i], drvdata->base + irq_ctrl_offset);
> +			CS_LOCK(drvdata->base);
> +		}
> +	}
> +
> +	return size;
> +}
> +static DEVICE_ATTR_RW(byte_cntr_val);
> +
> +static struct attribute *ctcu_attrs[] = {
> +	&dev_attr_byte_cntr_val.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group ctcu_attr_grp = {
> +	.attrs = ctcu_attrs,
> +};
> +
> +static const struct attribute_group *ctcu_attr_grps[] = {
> +	&ctcu_attr_grp,
> +	NULL,
> +};
> +
>   static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset,
>   				       u8 bit, bool enable)
>   {
> @@ -122,7 +193,7 @@ static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, in
>    * Searching the sink device from helper's view in case there are multiple helper devices
>    * connected to the sink device.
>    */
> -static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
> +int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
>   {
>   	struct coresight_platform_data *pdata = helper->pdata;
>   	int i;
> @@ -160,6 +231,8 @@ static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *
>   {
>   	struct coresight_path *path = (struct coresight_path *)data;
>   
> +	ctcu_byte_cntr_start(csdev, path);
> +
>   	return ctcu_set_etr_traceid(csdev, path, true);
>   }
>   
> @@ -167,6 +240,8 @@ static int ctcu_disable(struct coresight_device *csdev, void *data)
>   {
>   	struct coresight_path *path = (struct coresight_path *)data;
>   
> +	ctcu_byte_cntr_stop(csdev, path);
> +
>   	return ctcu_set_etr_traceid(csdev, path, false);
>   }
>   
> @@ -188,7 +263,7 @@ static int ctcu_probe(struct platform_device *pdev)
>   	const struct ctcu_config *cfgs;
>   	struct ctcu_drvdata *drvdata;
>   	void __iomem *base;
> -	int i;
> +	int ret, i;
>   
>   	desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
>   	if (!desc.name)
> @@ -217,7 +292,14 @@ static int ctcu_probe(struct platform_device *pdev)
>   			for (i = 0; i < cfgs->num_etr_config; i++) {
>   				etr_cfg = &cfgs->etr_cfgs[i];
>   				drvdata->atid_offset[i] = etr_cfg->atid_offset;
> +				drvdata->byte_cntr_data[i].irq_name = etr_cfg->irq_name;
> +				drvdata->byte_cntr_data[i].name = etr_cfg->byte_cntr_name;
> +				drvdata->byte_cntr_data[i].irq_ctrl_offset =
> +					etr_cfg->irq_ctrl_offset;
>   			}
> +			ret = ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config);
> +			if (ret < 0)
> +				dev_warn(dev, "Byte cntr init failed\n");
>   		}
>   	}
>   
> @@ -229,6 +311,7 @@ static int ctcu_probe(struct platform_device *pdev)
>   	desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU;
>   	desc.pdata = pdata;
>   	desc.dev = dev;
> +	desc.groups = ctcu_attr_grps;
>   	desc.ops = &ctcu_ops;
>   	desc.access = CSDEV_ACCESS_IOMEM(base);
>   
> @@ -247,6 +330,7 @@ static void ctcu_remove(struct platform_device *pdev)
>   {
>   	struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
>   
> +	ctcu_byte_cntr_remove(drvdata);
>   	coresight_unregister(drvdata->csdev);
>   }
>   
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h
> index e9594c38dd91..e38535c91090 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu.h
> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
> @@ -5,6 +5,8 @@
>   
>   #ifndef _CORESIGHT_CTCU_H
>   #define _CORESIGHT_CTCU_H
> +#include <linux/cdev.h>
> +
>   #include "coresight-trace-id.h"
>   
>   /* Maximum number of supported ETR devices for a single CTCU. */
> @@ -13,10 +15,16 @@
>   /**
>    * struct ctcu_etr_config
>    * @atid_offset:	offset to the ATID0 Register.
> - * @port_num:		in-port number of CTCU device that connected to ETR.
> + * @irq_ctrl_offset:	offset to the BYTECNTRVAL register.
> + * @irq_name:		IRQ name in dt node.
> + * @byte_cntr_name:	name of the byte cntr device node.
> + * @port_num:		in-port number of the CTCU device that connected to ETR.
>    */
>   struct ctcu_etr_config {
>   	const u32 atid_offset;
> +	const u32 irq_ctrl_offset;
> +	const char *irq_name;
> +	const char *byte_cntr_name;
>   	const u32 port_num;
>   };
>   
> @@ -25,15 +33,64 @@ struct ctcu_config {
>   	int num_etr_config;
>   };
>   
> +/**
> + * struct ctcu_byte_cntr
> + * @c_dev:		cdev for byte_cntr.
> + * @sink		csdev of sink device.
> + * @enable:		indicates that byte_cntr function is enabled or not.
> + * @read_active:	indicates that byte-cntr node is opened or not.
> + * @thresh_val:		threshold to trigger a interruption.
> + * @total_size		total size of transferred data.
> + * @byte_cntr_irq:	IRQ number.
> + * @irq_cnt:		IRQ count.
> + * @wq:			workqueue of reading ETR data.
> + * @read_work:		work of reading ETR data.
> + * @spin_lock:		spinlock of byte cntr data.
> + * @r_offset:		offset of the pointer where reading begins.
> + * @w_offset:		offset of the write pointer in the ETR buffer when
> + *			the byte cntr is stopped.
> + * @irq_ctrl_offset:	offset to the BYTECNTRVAL Register.
> + * @name:		the name of byte cntr device node.
> + * @irq_name:		IRQ name in DT.
> + */
> +struct ctcu_byte_cntr {
> +	struct cdev		c_dev;
> +	struct coresight_device	*sink;
> +	bool			enable;
> +	bool			read_active;
> +	u32			thresh_val;
> +	u64			total_size;
> +	int			byte_cntr_irq;
> +	atomic_t		irq_cnt;
> +	wait_queue_head_t	wq;
> +	struct work_struct	read_work;
> +	raw_spinlock_t		spin_lock;
> +	long			r_offset;
> +	long			w_offset;
> +	u32			irq_ctrl_offset;
> +	const char		*name;
> +	const char		*irq_name;
> +};
> +
>   struct ctcu_drvdata {
>   	void __iomem		*base;
>   	struct clk		*apb_clk;
>   	struct device		*dev;
>   	struct coresight_device	*csdev;
> +	struct ctcu_byte_cntr   byte_cntr_data[ETR_MAX_NUM];
>   	raw_spinlock_t		spin_lock;
>   	u32			atid_offset[ETR_MAX_NUM];
>   	/* refcnt for each traceid of each sink */
>   	u8			traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
>   };
>   
> +/* Generic functions */
> +int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper);
> +
> +/* Byte-cntr functions */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path);
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path);
> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num);
> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata);
> +
>   #endif
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index ec636ab1fd75..5dc94e890927 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1040,14 +1040,15 @@ static void tmc_free_etr_buf(struct etr_buf *etr_buf)
>    * Returns: The size of the linear data available @pos, with *bufpp
>    * updated to point to the buffer.
>    */
> -static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
> -				    u64 offset, size_t len, char **bufpp)
> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
> +			     u64 offset, size_t len, char **bufpp)
>   {
>   	/* Adjust the length to limit this transaction to end of buffer */
>   	len = (len < (etr_buf->size - offset)) ? len : etr_buf->size - offset;
>   
>   	return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
>   }
> +EXPORT_SYMBOL_GPL(tmc_etr_buf_get_data);
>   
>   static inline s64
>   tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index baedb4dcfc3f..2fc77fd4ea25 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -443,5 +443,7 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>   				   enum cs_mode mode, void *data);
>   extern const struct attribute_group coresight_etr_group;
>   long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, size_t len,
> +			     char **bufpp);
>   
>   #endif



From Frank.li at nxp.com  Thu Mar 13 09:26:05 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 12:26:05 -0400
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250313160648.GA736867@bhelgaas>
References: <b425a7c7a7d6508daf23fe7046864a498029a7ac.camel@pengutronix.de>
 <20250313160648.GA736867@bhelgaas>
Message-ID: <Z9MHHU2Im7Eo0ETS@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 11:06:48AM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 09:54:25AM +0100, Lucas Stach wrote:
> > Am Mittwoch, dem 12.03.2025 um 10:22 -0400 schrieb Frank Li:
> > > On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> > > > Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > > > > -----Original Message-----
> > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > Sent: 2025?3?11? 23:55
> > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > > > > > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > > > > > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > hardcodes
> > > > > >
> > > > > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > > > > -----Original Message-----
> > > > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > > > Sent: 2025?3?10? 23:11
> > > > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > > > > > bhelgaas at google.com;
> > > > > > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > > > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > > > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > > > hardcodes
> > > > > > > >
> > > > > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > > > > ---
> > > > > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > @@ -41,7 +41,6 @@
> > > > > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > > > > 8)
> > > > > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > > > > >
> > > > > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > > > > platform_device
> > > > > > > > *pdev)
> > > > > > > > > ?	struct dw_pcie *pci;
> > > > > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > > > > ?	struct device_node *np;
> > > > > > > > > -	struct resource *dbi_base;
> > > > > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > > > > ?	int i, ret, req_cnt;
> > > > > > > > > ?	u16 val;
> > > > > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > > > > platform_device *pdev)
> > > > > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > > > > ?	}
> > > > > > > > >
> > > > > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > > > > 0,
> > > > > > > > &dbi_base);
> > > > > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > > > > -		return PTR_ERR(pci->dbi_base);
> > > > > > > >
> > > > > > > > This makes me wonder.
> > > > > > > >
> > > > > > > > IIUC this means that previously we set controller_id to
> > > > > > > > 1 if the first item in devicetree "reg" was 0x33c00000,
> > > > > > > > and now we will set controller_id to 1 if the devicetree
> > > > > > > > "linux,pci-domain" property is 1.  This is good, but I
> > > > > > > > think this new dependency on the correct
> > > > > > > > "linux,pci-domain" in devicetree should be mentioned in
> > > > > > > > the commit log.
> > > > > > > >
> > > > > > > > My bigger worry is that we no longer set pci->dbi_base
> > > > > > > > at all.  I see that the only use of pci->dbi_base in
> > > > > > > > pci-imx6.c was to determine the controller_id, but this
> > > > > > > > is a DWC-based driver, and the DWC core certainly uses
> > > > > > > > pci->dbi_base.  Are we sure that none of those DWC core
> > > > > > > > paths are important to pci-imx6.c?
> > > > > > >
> > > > > > > Thanks for your concerns.  Don't worry about the
> > > > > > > assignment of pci->dbi_base.  If pci-imx6.c driver doesn't
> > > > > > > set it. DWC core driver would set it when
> > > > > > > ?dw_pcie_get_resources() is invoked.
> > > > > >
> > > > > > Great, thanks!  Maybe we can amend the commit log to mention
> > > > > > that and the new "linux,pci-domain" dependency.
> > > > >
> > > > > How about the following updates of the commit log?
> > > > >
> > > > > Use the domain number replace the hardcodes to uniquely
> > > > > identify different controller on i.MX8MQ platforms. No
> > > > > function changes.  Please make sure the " linux,pci-domain" is
> > > > > set for i.MX8MQ correctly, since ?the controller id is relied
> > > > > on it totally.
> > > > >
> > > > This breaks running a new kernel on an old DT without the
> > > > linux,pci-domain property, which I'm absolutely no fan of. We
> > > > tried really hard to keep this way around working in the i.MX
> > > > world.
> > >
> > > 8MQ already add linux,pci-domain since Jan, 2021
> > >
> > > commit c0b70f05c87f3b09b391027c6f056d0facf331ef
> > > Author: Peng Fan <peng.fan at nxp.com>
> > > Date:   Fri Jan 15 11:26:57 2021 +0800
> > >
> > > Only missed is pcie-ep side, which have not been used at all boards dts
> > > file in upstream.
> >
> > I wasn't aware of this. 2021 is quite a while ago, so I suspect that
> > nobody is going to run a new kernel with a DT this old. I retract my
> > objection.
>
> Sounds good, thanks, Lucas.  We really do want to avoid breaking old
> DTs, so I appreciate your highlighting of it.  Even if we believe none
> of them will break, I think it's worth mentioning the
> 'linux,pci-domain' dependency and the commit that added it to the
> .dtsi in the commit log.

Yes, I think you can add it? some thing like

"linux,pci-domain" must match the PCIe controller instance sequence for the
i.MX8MQ platform.

Frank

>
> Bjorn


From ryan.roberts at arm.com  Thu Mar 13 09:28:55 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 16:28:55 +0000
Subject: [PATCH v3 3/3] arm64/mm: Elide tlbi in contpte_convert() under
 BBML2
In-Reply-To: <20250313104111.24196-5-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-5-miko.lenczewski@arm.com>
Message-ID: <548e5f51-a622-4117-a2b0-07947e5887db@arm.com>

On 13/03/2025 10:41, Miko?aj Lenczewski wrote:
> When converting a region via contpte_convert() to use mTHP, we have two
> different goals. We have to mark each entry as contiguous, and we would
> like to smear the dirty and young (access) bits across all entries in
> the contiguous block. Currently, we do this by first accumulating the
> dirty and young bits in the block, using an atomic
> __ptep_get_and_clear() and the relevant pte_{dirty,young}() calls,
> performing a tlbi, and finally smearing the correct bits across the
> block using __set_ptes().
> 
> This approach works fine for BBM level 0, but with support for BBM level
> 2 we are allowed to reorder the tlbi to after setting the pagetable
> entries. This reordering reduces the likelyhood of a concurrent page
> walk finding an invalid (not present) PTE. This reduces the likelyhood
> of a fault in other threads, and improves performance marginally
> (more so when there are more threads).

Just to add some extra clarity for the sake of the review; we expect that the
cost of the tlbi(s) is much greater than the cost of clearing and re-setting the
ptes. So by moving the tlbi(s) outside of the window where the ptes are invalid
(as bbml2 permits us to do) we greatly reduce the duration where the ptes are
invalid and therefore greatly reduce the chances of another thread taking a
fault on the temporarily invalid address...

> 
> If we support bbml2 without conflict aborts however, we can avoid the
> final flush altogether and have hardware manage the tlb entries for us.
> Avoiding flushes is a win.

...But because we are only allow-listing bbml2 implementations that don't raise
a conflict abort and instead automatically invalidate the conflicting entries in
HW, we can avoid that tlbi altogether.

> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

> ---
>  arch/arm64/mm/contpte.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
> index 55107d27d3f8..77ed03b30b72 100644
> --- a/arch/arm64/mm/contpte.c
> +++ b/arch/arm64/mm/contpte.c
> @@ -68,7 +68,8 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
>  			pte = pte_mkyoung(pte);
>  	}
>  
> -	__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
> +	if (!system_supports_bbml2_noabort())
> +		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
>  
>  	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
>  }



From anders.roxell at linaro.org  Thu Mar 13 09:30:11 2025
From: anders.roxell at linaro.org (Anders Roxell)
Date: Thu, 13 Mar 2025 17:30:11 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe path
In-Reply-To: <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
References: <cover.1740753261.git.robin.murphy@arm.com> <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com> <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com> <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
Message-ID: <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>

From: Robin Murphy <robin.murphy at arm.com>

> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
> [...]
> > This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
> > ("iommu: Get DT/ACPI parsing into the proper probe path"). In my tests I
> > found it breaks booting of ARM64 RK3568-based Odroid-M1 board
> > (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
> > relevant kernel log:
> 
> ...and the bug-flushing-out begins!
> 
> > Unable to handle kernel NULL pointer dereference at virtual address
> > 00000000000003e8
> > Mem abort info:
> >   ? ESR = 0x0000000096000004
> >   ? EC = 0x25: DABT (current EL), IL = 32 bits
> >   ? SET = 0, FnV = 0
> >   ? EA = 0, S1PTW = 0
> >   ? FSC = 0x04: level 0 translation fault
> > Data abort info:
> >   ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> >   ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> >   ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > [00000000000003e8] user address but active_mm is swapper
> > Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> > Modules linked in:
> > CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
> > Hardware name: Hardkernel ODROID-M1 (DT)
> > pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > pc : devm_kmalloc+0x2c/0x114
> > lr : rk_iommu_of_xlate+0x30/0x90
> > ...
> > Call trace:
> >   ?devm_kmalloc+0x2c/0x114 (P)
> >   ?rk_iommu_of_xlate+0x30/0x90
> 
> Yeah, looks like this is doing something a bit questionable which can't
> work properly. TBH the whole dma_dev thing could probably be cleaned up
> now that we have proper instances, but for now does this work?
> 
> (annoyingly none of my Rockchip boards are set up for testing right now, 
> but I might have time to dig one out later)
> 
> Thanks,
> Robin.
> 
> ----->8-----
> 
> Subject: [PATCH] iommu/rockchip: Allocate per-device data sensibly
> 
> Now that DT-based probing is finally happening in the right order again,
> it reveals an issue in Rockchip's of_xlate, which can now be called
> during registration, but is using the global dma_dev which is only
> assigned later. However, this makes little sense when we're already
> looking up the correct IOMMU device, who should logically be the owner
> of the devm allocation anyway.
> 
> Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe 
> path")
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

This patch fixed the boot on rockpi4.
Applied it ontop of next-20250313

Tested-by: Anders Roxell <anders.roxell at linaro.org>

Cheers,
Anders


From Frank.li at nxp.com  Thu Mar 13 09:33:10 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 12:33:10 -0400
Subject: [PATCH v4 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250313125746.2901904-3-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-3-florin.leotescu@oss.nxp.com>
Message-ID: <Z9MIxuelKSdT0rUK@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 02:57:45PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
>
> Introduce OF support for Microchip emc2305 pwm fan controller.
>
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/hwmon/emc2305.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
> index 4d39fbd83769..f8a4c76fcadd 100644
> --- a/drivers/hwmon/emc2305.c
> +++ b/drivers/hwmon/emc2305.c
> @@ -607,9 +607,16 @@ static void emc2305_remove(struct i2c_client *client)
>  		emc2305_unset_tz(dev);
>  }
>
> +static const struct of_device_id of_emc2305_match_table[] = {
> +	{ .compatible = "microchip,emc2305", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
> +
>  static struct i2c_driver emc2305_driver = {
>  	.driver = {
>  		.name = "emc2305",
> +		.of_match_table = of_emc2305_match_table,
>  	},
>  	.probe = emc2305_probe,
>  	.remove	  = emc2305_remove,
> --
> 2.34.1
>


From vladimir.oltean at nxp.com  Thu Mar 13 09:35:26 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 13 Mar 2025 18:35:26 +0200
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <20250311053830.1516523-2-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
Message-ID: <20250313163526.pqwp2wsfvio7avs6@skbuf>

On Tue, Mar 11, 2025 at 01:38:17PM +0800, Wei Fang wrote:
> +int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs, u32 *table,
> +				    int count, bool query)
> +{
> +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> +	struct rsst_req_update *requ;
> +	struct ntmp_req_by_eid *req;
> +	union netc_cbd cbd;
> +	int err, i;
> +	u32 len;
> +
> +	if (count != RSST_ENTRY_NUM)
> +		/* HW only takes in a full 64 entry table */
> +		return -EINVAL;
> +
> +	if (query)
> +		data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
> +			    RSST_CFGE_DATA_SIZE(count);
> +	else
> +		data.size = struct_size(requ, groups, count);
> +
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	/* Set the request data buffer */
> +	if (query) {
> +		ntmp_fill_crd_eid(req, cbdrs->tbl.rsst_ver, 0, 0, 0);
> +		len = NTMP_LEN(sizeof(*req), data.size);
> +		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> +					NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);

Please either use a commonly accepted abbreviation such as "hdr", or preferably,
just spell "header" as such. This reminded me of Kevin Malone's quote
"Why waste time say lot word when few word do trick?" :)

> +	} else {
> +		requ = (struct rsst_req_update *)req;
> +		ntmp_fill_crd_eid(&requ->rbe, cbdrs->tbl.rsst_ver, 0,
> +				  NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
> +		for (i = 0; i < count; i++)
> +			requ->groups[i] = (u8)(table[i]);
> +
> +		len = NTMP_LEN(data.size, 0);
> +		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> +					NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
> +	}
> +
> +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> +	if (err) {
> +		dev_err(cbdrs->dma_dev, "%s RSS table entry failed (%d)",
> +			query ? "Query" : "Update", err);
> +		goto end;
> +	}
> +
> +	if (query) {
> +		u8 *group = (u8 *)req;
> +
> +		group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
> +		for (i = 0; i < count; i++)
> +			table[i] = group[i];
> +	}
> +
> +end:
> +	ntmp_free_data_mem(&data);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(ntmp_rsst_query_or_update_entry);

Instead of exporting "query_or_update" mixed semantics, can you please
export two separate functions, one for "query" and the other for "update"?
For query=false, you can make the "table" argument const.

Also, from the looks of their implementation, there isn't much that is
common anyway.

> +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
> +{
> +	void *buf;
> +
> +	buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
> +				 &data->dma, GFP_ATOMIC);

Is there any call site that can't use sleeping allocations (GFP_KERNEL)?

> +	if (!buf)
> +		return -ENOMEM;
> +
> +	data->buf = buf;
> +	*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
> +
> +	return 0;
> +}
> +
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> new file mode 100644
> index 000000000000..45e4d083ab0a
> --- /dev/null
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> @@ -0,0 +1,63 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> +/*
> + * NTMP table request and response data buffer formats
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef __NTMP_PRIVATE_H
> +#define __NTMP_PRIVATE_H
> +
> +#include <linux/fsl/ntmp.h>
> +
> +struct ntmp_dma_buf {
> +	struct device *dev;
> +	size_t size;
> +	void *buf;
> +	dma_addr_t dma;
> +};
> +
> +struct common_req_data {

Some maintainers prefer to avoid definitions which "sound" generic, but truly
are driver-specific, and instead recommend to prefix their names with
some kind of driver specific indication
(example: https://lore.kernel.org/netdev/20190413205311.GC2268 at nanopsycho.orion/).

So, maybe something like "ntmp_common_req_data", "ntmp_common_resp_query", ...
would make that more clear?

> +	__le16 update_act;
> +	u8 dbg_opt;
> +	u8 tblv_qact;
> +#define NTMP_QUERY_ACT		GENMASK(3, 0)
> +#define NTMP_TBL_VER		GENMASK(7, 0)
> +#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
> +				 ((a) & NTMP_QUERY_ACT))

Can you please move #define macros out of structure definitions?

> +};
> +
> +struct common_resp_query {
> +	__le32 entry_id;
> +};
> +
> +struct common_resp_nq {
> +	__le32 status;
> +};
> +
> +/* Generic structure for request data by entry ID  */
> +struct ntmp_req_by_eid {
> +	struct common_req_data crd;
> +	__le32 entry_id;
> +};
> +
> +/* MAC Address Filter Table Request Data Buffer Format of Add action */
> +struct maft_req_add {
> +	struct ntmp_req_by_eid rbe;
> +	struct maft_keye_data keye;
> +	struct maft_cfge_data cfge;
> +};
> +
> +/* MAC Address Filter Table Response Data Buffer Format of Query action */
> +struct maft_resp_query {
> +	__le32 entry_id;
> +	struct maft_keye_data keye;
> +	struct maft_cfge_data cfge;
> +};
> +
> +/* RSS Table Request Data Buffer Format of Update action */
> +struct rsst_req_update {
> +	struct ntmp_req_by_eid rbe;
> +	u8 groups[];
> +};
> +
> +#endif
> diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> new file mode 100644
> index 000000000000..fe15e394c4a4
> --- /dev/null
> +++ b/include/linux/fsl/ntmp.h
> @@ -0,0 +1,174 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> +/* Copyright 2025 NXP */
> +#ifndef __NETC_NTMP_H
> +#define __NETC_NTMP_H
> +
> +#include <linux/bitops.h>
> +#include <linux/if_ether.h>
> +
> +#define NTMP_NULL_ENTRY_ID		0xffffffffU
> +#define NETC_CBDR_BD_NUM		256
> +
> +union netc_cbd {

Do you seriously need to export the netc_cbd definition outside of
drivers/net/ethernet/freescale/enetc/ntmp.c? I would say even if you do
(which this patch set doesn't appear to need), the NTMP library exports
an API which doesn't do a great job abstracting the information.

The question pertains to everything else that is exported to
include/linux/fsl/ntmp.h - what the API consumer sees. Is there a real
reason to export it? For many structures and macros, the answer seems no.

Even for cases like struct maft_keye_data which are only used by debugfs,
it still seems preferable to keep data encapsulation and offer a helper
function to retrieve a pointer to the MAC address from the MAFT entry.
Then, "struct maft_keye_data;" can simply be declared, without exposing
its full definition.

> +	struct {
> +		__le64 addr;
> +		__le32 len;
> +#define NTMP_RESP_LEN		GENMASK(19, 0)
> +#define NTMP_REQ_LEN		GENMASK(31, 20)
> +#define NTMP_LEN(req, resp)	(FIELD_PREP(NTMP_REQ_LEN, (req)) | \
> +				((resp) & NTMP_RESP_LEN))
> +		u8 cmd;
> +#define NTMP_CMD_DELETE		BIT(0)
> +#define NTMP_CMD_UPDATE		BIT(1)
> +#define NTMP_CMD_QUERY		BIT(2)
> +#define NTMP_CMD_ADD		BIT(3)
> +#define NTMP_CMD_QD		(NTMP_CMD_QUERY | NTMP_CMD_DELETE)
> +#define NTMP_CMD_QU		(NTMP_CMD_QUERY | NTMP_CMD_UPDATE)
> +#define NTMP_CMD_AU		(NTMP_CMD_ADD | NTMP_CMD_UPDATE)
> +#define NTMP_CMD_AQ		(NTMP_CMD_ADD | NTMP_CMD_QUERY)
> +#define NTMP_CMD_AQU		(NTMP_CMD_AQ | NTMP_CMD_UPDATE)
> +		u8 access_method;
> +#define NTMP_ACCESS_METHOD	GENMASK(7, 4)
> +#define NTMP_AM_ENTRY_ID	0
> +#define NTMP_AM_EXACT_KEY	1
> +#define NTMP_AM_SEARCH		2
> +#define NTMP_AM_TERNARY_KEY	3
> +		u8 table_id;
> +		u8 ver_cci_rr;
> +#define NTMP_HDR_VERSION	GENMASK(5, 0)
> +#define NTMP_HDR_VER2		2
> +#define NTMP_CCI		BIT(6)
> +#define NTMP_RR			BIT(7)
> +		__le32 resv[3];
> +		__le32 npf;
> +#define NTMP_NPF		BIT(15)
> +	} req_hdr;	/* NTMP Request Message Header Format */
> +
> +	struct {
> +		__le32 resv0[3];
> +		__le16 num_matched;
> +		__le16 error_rr;
> +#define NTMP_RESP_ERROR		GENMASK(11, 0)
> +#define NTMP_RESP_RR		BIT(15)
> +		__le32 resv1[4];
> +	} resp_hdr; /* NTMP Response Message Header Format */
> +};
> +
> +struct maft_keye_data {
> +	u8 mac_addr[ETH_ALEN];
> +	__le16 resv;
> +};
> +
> +struct maft_cfge_data {
> +	__le16 si_bitmap;
> +	__le16 resv;
> +};
> +
> +struct netc_cbdr_regs {
> +	void __iomem *pir;
> +	void __iomem *cir;
> +	void __iomem *mr;
> +
> +	void __iomem *bar0;
> +	void __iomem *bar1;
> +	void __iomem *lenr;
> +};
> +
> +struct netc_tbl_vers {
> +	u8 maft_ver;
> +	u8 rsst_ver;
> +};
> +
> +struct netc_cbdr {
> +	struct netc_cbdr_regs regs;
> +
> +	int bd_num;
> +	int next_to_use;
> +	int next_to_clean;
> +
> +	int dma_size;
> +	void *addr_base;
> +	void *addr_base_align;
> +	dma_addr_t dma_base;
> +	dma_addr_t dma_base_align;
> +
> +	spinlock_t ring_lock; /* Avoid race condition */

Can this description be more specific? This type of comment is as
useful as not having it. Make the reader understand what is serialized
with what, to prevent concurrent, non-atomic access to what resources.

> +};
> +
> +struct netc_cbdrs {
> +	int cbdr_num;	/* number of control BD ring */
> +	int cbdr_size;	/* number of BDs per control BD ring */
> +	struct device *dma_dev;
> +	struct netc_cbdr *ring;
> +	struct netc_tbl_vers tbl;
> +};
> +
> +enum netc_dev_type {
> +	NETC_DEV_ENETC,
> +	NETC_DEV_SWITCH
> +};

Can you delay the introduction of this distinction until when the
"dev_type" will actually be used for something, and it's clear to
reviewers what is the intention behind it? Currently the switch driver
does not exist, and this has no purpose.

> +
> +struct ntmp_priv {

Would it be better to name this "struct ntmp_client"? I don't really
understand the way in which it is "private".

I'm looking at this from an API perspective, and I don't really
understand which one is the "top-level" object for an NTMP consumer
driver. Is it ntmp_priv or netc_cbdrs? Logically, ntmp_priv encapsulates
netc_cbdrs, but I see that all functions take the smaller netc_cbdrs,
which I find unintuitive. Could you just perhaps squash them into a
single structure, if they in fact serve the same purpose?

> +	enum netc_dev_type dev_type;
> +	struct netc_cbdrs cbdrs;
> +};
> +
> +struct maft_entry_data {
> +	struct maft_keye_data keye;
> +	struct maft_cfge_data cfge;
> +};

> +static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
> +				   u8 tbl_ver, u32 entry_id, u32 req_len,
> +				   u32 resp_len)
> +{
> +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> +	struct ntmp_req_by_eid *req;
> +	union netc_cbd cbd;
> +	u32 len;
> +	int err;
> +
> +	if (entry_id == NTMP_NULL_ENTRY_ID)
> +		return 0;

What's the idea with the null entry ID? Why special-case it?

> +
> +	/* If the req_len is 0, indicates the requested length is the
> +	 * standard length.
> +	 */
> +	if (!req_len)
> +		req_len = sizeof(*req);

Objection: as submitted in this patch set, the req_len argument is _only_
passed as zero (the only caller is ntmp_maft_delete_entry()). I don't
know about downstream, but let's only add complexity that we need, when
we need it.

> +
> +	data.size = req_len >= resp_len ? req_len : resp_len;
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
> +	len = NTMP_LEN(req_len, resp_len);
> +	ntmp_fill_request_headr(&cbd, data.dma, len, tbl_id,
> +				NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
> +
> +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> +	if (err)
> +		dev_err(cbdrs->dma_dev, "Delete table (id: %d) entry failed: %d",
> +			tbl_id, err);
> +
> +	ntmp_free_data_mem(&data);
> +
> +	return err;
> +}
> +
> +static int ntmp_query_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
> +				  u32 len, struct ntmp_req_by_eid *req,
> +				  dma_addr_t dma, bool compare_eid)
> +{
> +	struct device *dev = cbdrs->dma_dev;
> +	struct common_resp_query *resp;
> +	int cmd = NTMP_CMD_QUERY;
> +	union netc_cbd cbd;
> +	u32 entry_id;
> +	int err;
> +
> +	entry_id = le32_to_cpu(req->entry_id);
> +	if (le16_to_cpu(req->crd.update_act))
> +		cmd = NTMP_CMD_QU;
> +
> +	/* Request header */
> +	ntmp_fill_request_headr(&cbd, dma, len, tbl_id,
> +				cmd, NTMP_AM_ENTRY_ID);
> +
> +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> +	if (err) {
> +		dev_err(dev, "Query table (id: %d) entry failed: %d\n",
> +			tbl_id, err);
> +		return err;
> +	}
> +
> +	/* For a few tables, the first field of its response data is not

s/its/their/

> +	 * entry_id, so directly return success.
> +	 */
> +	if (!compare_eid)
> +		return 0;
> +
> +	resp = (struct common_resp_query *)req;
> +	if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
> +		dev_err(dev, "Table (id: %d) query EID:0x%0x, response EID:0x%x\n",

Can you please put some spaces between ":" and "0".

> +			tbl_id, entry_id, le32_to_cpu(resp->entry_id));
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
> +			struct maft_entry_data *maft)
> +{
> +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> +	struct maft_req_add *req;
> +	union netc_cbd cbd;
> +	int err;
> +
> +	data.size = sizeof(*req);
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	/* Set mac address filter table request data buffer */
> +	ntmp_fill_crd_eid(&req->rbe, cbdrs->tbl.maft_ver, 0, 0, entry_id);
> +	req->keye = maft->keye;
> +	req->cfge = maft->cfge;
> +
> +	ntmp_fill_request_headr(&cbd, data.dma, NTMP_LEN(data.size, 0),
> +				NTMP_MAFT_ID, NTMP_CMD_ADD,
> +				NTMP_AM_ENTRY_ID);
> +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> +	if (err)
> +		dev_err(cbdrs->dma_dev, "Add MAFT entry failed (%d)", err);

Can you use symbolic error names? "Adding MAFT entry failed: %pe\n", ERR_PTR(err).
Also notice the missing \n in the error message..

Same comment for the error message in:
- ntmp_delete_entry_by_id()
- ntmp_rsst_query_or_update_entry() - which as per review feedback here
  should become 2 functions

> +
> +	ntmp_free_data_mem(&data);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
> +
> +int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
> +			  struct maft_entry_data *maft)
> +{
> +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> +	struct maft_resp_query *resp;
> +	struct ntmp_req_by_eid *req;
> +	u32 req_len = sizeof(*req);
> +	int err;
> +
> +	if (entry_id == NTMP_NULL_ENTRY_ID)
> +		return -EINVAL;
> +
> +	data.size = sizeof(*resp);
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	ntmp_fill_crd_eid(req, cbdrs->tbl.maft_ver, 0, 0, entry_id);
> +	err = ntmp_query_entry_by_id(cbdrs, NTMP_MAFT_ID,
> +				     NTMP_LEN(req_len, data.size),
> +				     req, data.dma, true);
> +	if (err)
> +		goto end;
> +
> +	resp = (struct maft_resp_query *)req;
> +	maft->keye = resp->keye;
> +	maft->cfge = resp->cfge;
> +
> +end:
> +	ntmp_free_data_mem(&data);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
> +
> +int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
> +{
> +	return ntmp_delete_entry_by_id(cbdrs, NTMP_MAFT_ID,
> +				       cbdrs->tbl.maft_ver,
> +				       entry_id, 0, 0);
> +}
> +EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);

> +static void netc_clean_cbdr(struct netc_cbdr *cbdr)
> +{
> +	union netc_cbd *cbd;
> +	int i;
> +
> +	i = cbdr->next_to_clean;
> +	while (netc_read(cbdr->regs.cir) != i) {
> +		cbd = netc_get_cbd(cbdr, i);
> +		memset(cbd, 0, sizeof(*cbd));
> +		i = (i + 1) % cbdr->bd_num;
> +	}
> +
> +	cbdr->next_to_clean = i;
> +}
> +
> +static struct netc_cbdr *netc_select_cbdr(struct netc_cbdrs *cbdrs)
> +{
> +	int i;
> +
> +	for (i = 0; i < cbdrs->cbdr_num; i++) {
> +		if (spin_is_locked(&cbdrs->ring[i].ring_lock))
> +			continue;
> +
> +		return &cbdrs->ring[i];
> +	}
> +
> +	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];

I think you need to be in a "preemption disabled" / "migration disable"
calling context for smp_processor_id() to be reliable. Otherwise, the
task can migrate to another CPU as soon as this function returns.

Anyway, much can be said about this, but currently it is useless
complexity, because the only user, enetc4_setup_cbdr(), sets
"cbdrs->cbdr_num = 1", which side-steps the entire netc_select_cbdr()
logic.

Please strip all unnecessary logic and only add it when the need
presents itself, so we can all assess whether the solution is
appropriate for that particular need.

> +}
> +
> +static int netc_xmit_ntmp_cmd(struct netc_cbdrs *cbdrs, union netc_cbd *cbd)
> +{
> +	union netc_cbd *cur_cbd;
> +	struct netc_cbdr *cbdr;
> +	int i, err;
> +	u16 status;
> +	u32 val;
> +
> +	if (cbdrs->cbdr_num == 1)
> +		cbdr = &cbdrs->ring[0];
> +	else
> +		cbdr = netc_select_cbdr(cbdrs);
> +
> +	spin_lock_bh(&cbdr->ring_lock);
> +
> +	if (unlikely(!netc_get_free_cbd_num(cbdr)))
> +		netc_clean_cbdr(cbdr);
> +
> +	i = cbdr->next_to_use;
> +	cur_cbd = netc_get_cbd(cbdr, i);
> +	*cur_cbd = *cbd;
> +
> +	/* Update producer index of both software and hardware */
> +	i = (i + 1) % cbdr->bd_num;
> +	cbdr->next_to_use = i;
> +	dma_wmb();

Can you place this dma_wmb() right next to the "*cur_cbd = *cbd" line,
to make it obvious that updating the producer index has nothing to do
with it? Or is there another reason for this ordering?

> +	netc_write(cbdr->regs.pir, i);
> +
> +	err = read_poll_timeout_atomic(netc_read, val, val == i,
> +				       10, NETC_CBDR_TIMEOUT, true,
> +				       cbdr->regs.cir);
> +	if (unlikely(err))
> +		goto cbdr_unlock;
> +
> +	dma_rmb();
> +	/* Get the writeback command BD, because the caller may need
> +	 * to check some other fields of the response header.
> +	 */
> +	*cbd = *cur_cbd;
> +
> +	/* Check the writeback error status */
> +	status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
> +	if (unlikely(status)) {
> +		err = -EIO;
> +		dev_err(cbdrs->dma_dev, "Command BD error: 0x%04x\n", status);
> +	}
> +
> +	netc_clean_cbdr(cbdr);
> +	dma_wmb();
> +
> +cbdr_unlock:
> +	spin_unlock_bh(&cbdr->ring_lock);
> +
> +	return err;
> +}


From Frank.li at nxp.com  Thu Mar 13 09:39:49 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 12:39:49 -0400
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
Message-ID: <Z9MKVd8NeLKNIkd2@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 02:57:44PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
>
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
>
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 104 ++++++++++++++++++
>  1 file changed, 104 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..3107fcafcf6a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,104 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +
> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>
> +
> +description:
> +  Microchip EMC2301/2/3/5 pwm controller which supports
> +  up to five programmable fan control circuits.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - microchip,emc2305
> +      - items:
> +          - enum:
> +              - microchip,emc2303
> +              - microchip,emc2302
> +              - microchip,emc2301
> +          - const: microchip,emc2305
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  '#pwm-cells':
> +    const: 2
> +
> +patternProperties:
> +  "^fan@[0-4]$":
> +    $ref: fan-common.yaml#
> +    unevaluatedProperties: false
> +    properties:
> +      reg:
> +        description:
> +          The fan number.
> +
> +    required:
> +      - reg
> +      - pwms
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        fan_controller: fan-controller at 2f {
> +            compatible = "microchip,emc2305";
> +            reg = <0x2f>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            #pwm-cells = <2>;
> +
> +            fan at 0 {
> +                #cooling-cells = <2>;
> +                reg = <0x0>;
> +                pwms = <&fan_controller 1 1>;
> +            };
> +
> +            fan at 1 {
> +                #cooling-cells = <2>;
> +                reg = <0x1>;
> +                pwms = <&fan_controller 1 1>;
> +            };
> +
> +            fan at 2 {
> +                #cooling-cells = <2>;
> +                reg = <0x2>;
> +                pwms = <&fan_controller 1 1>;
> +            };
> +
> +            fan at 3 {
> +                #cooling-cells = <2>;
> +                reg = <0x3>;
> +                pwms = <&fan_controller 1 1>;
> +            };
> +
> +            fan at 4 {
> +                #cooling-cells = <2>;
> +                reg = <0x4>;
> +                pwms = <&fan_controller 1 1>;
> +            };

I think one child node should be enough for example.

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> +        };
> +    };
> +...
> --
> 2.34.1
>


From lee at kernel.org  Thu Mar 13 09:40:08 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 16:40:08 +0000
Subject: [PATCH v3 2/8] mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250305094935.595667-3-fabrice.gasnier@foss.st.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-3-fabrice.gasnier@foss.st.com>
Message-ID: <20250313164008.GC3645863@google.com>

On Wed, 05 Mar 2025, Fabrice Gasnier wrote:

> Add support for STM32MP25 SoC.
> A new hardware configuration register (HWCFGR2) has been added, to gather
> number of capture/compare channels, autonomous mode and input capture
> capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
> supports a smaller set of features. This can now be read from HWCFGR
> registers.
> 
> Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
> Update the stm32_lptimer data struct so signal the number of
> capture/compare channels to the child devices.
> Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
> Changes in V2:
> - rely on fallback compatible as no specific .data is associated to the
>   driver. Compatibility is added by reading hardware configuration
>   registers.
> - read version register, to be used by clockevent child driver
> - rename register/bits definitions
> ---
>  drivers/mfd/stm32-lptimer.c       | 33 ++++++++++++++++++++++++++++-

Looks okay.

>  include/linux/mfd/stm32-lptimer.h | 35 ++++++++++++++++++++++++++++---

Assumingly this patch is not independent of the others?

-- 
Lee Jones [???]


From acarmina at redhat.com  Thu Mar 13 09:40:59 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Thu, 13 Mar 2025 17:40:59 +0100
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning backtraces
In-Reply-To: <20250313122503.GA7438@willie-the-truck>
References: <20250313114329.284104-1-acarmina@redhat.com> <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
Message-ID: <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>

Hello Will,

On Thu, Mar 13, 2025 at 1:25?PM Will Deacon <will at kernel.org> wrote:
>
> On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
> > diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
> > index 28be048db3f6..044c5e24a17d 100644
> > --- a/arch/arm64/include/asm/bug.h
> > +++ b/arch/arm64/include/asm/bug.h
> > @@ -11,8 +11,14 @@
> >
> >  #include <asm/asm-bug.h>
> >
> > +#ifdef HAVE_BUG_FUNCTION
> > +# define __BUG_FUNC  __func__
> > +#else
> > +# define __BUG_FUNC  NULL
> > +#endif
> > +
> >  #define __BUG_FLAGS(flags)                           \
> > -     asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
> > +     asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
>
> Why is 'i' the right asm constraint to use here? It seems a bit odd to
> use that for a pointer.

I received this code as legacy from a previous version.
In my review, I considered the case when HAVE_BUG_FUNCTION is defined:
Here, __BUG_FUNC is defined as __func__, which is the name of the
current function as a string literal.
Using the constraint "i" seems appropriate to me in this case.

However, when HAVE_BUG_FUNCTION is not defined:
__BUG_FUNC is defined as NULL. Initially, I considered it literal 0,
but after investigating your concern, I found:

```
$ echo -E "#include <stdio.h>\n#include <stddef.h>\nint main()
{\nreturn 0;\n}" | aarch64-linux-gnu-gcc -E -dM - | grep NULL
#define NULL ((void *)0)
```

I realized that NULL is actually a pointer that is not a link time
symbol, and using the "i" constraint with NULL may result in undefined
behavior.

Would the following alternative definition for __BUG_FUNC be more convincing?

```
#ifdef HAVE_BUG_FUNCTION
    #define __BUG_FUNC __func__
#else
    #define __BUG_FUNC (uintptr_t)0
#endif
```
Let me know your thoughts.

>
> Will
>



--
---
172



From lee at kernel.org  Thu Mar 13 09:42:11 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 16:42:11 +0000
Subject: [PATCH v3 00/21] Enable Power Modes Support for SAMA7D65 SoC
In-Reply-To: <cover.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <20250313164211.GD3645863@google.com>

On Thu, 27 Feb 2025, Ryan.Wanner at microchip.com wrote:

> From: Ryan Wanner <Ryan.Wanner at microchip.com>
> 
> This patch set adds support for low power modes for the SAMA7D65 SoC and
> the required components and changes for low power modes.
> 
> The series includes changes in the asm code to account for the addtional
> clocks that are in this SoC.
> 
> The Device tree additions are to enable all the components needed to
> keep the SoC in low power mode.
> 
> There are some DTB check warnings but that is due to the dt-binding not
> in the correct .yaml file format.
> 
> Changes v1 -> v2:
> - Add missing compatible for ddr3phy, it is now in both syscon sets.
> - Fix alphabetical ordering for sama7d65.
> - Remove the incorrect reorganizing patch.
> - Remove sama7g5-rtt as a compatible for sama7d65-rtt and add
>   sama7d65-rtt as a compatible wake up source in the pm driver.
> 
> Changes from v2 -> v3:
> - Correct mistake in v2 sfrbu dt-binding patch.
> - Correct incorrect dt-binding addition and formatting for rtc and rtt bindings.
> - Add missing SoB tag.
> - Cleaned up commit message for Backup mode to describe SHDWC is status
>   register is cleared for this SoC.
> - Cleaned up variable naming and usage for mcks. Changed the mcks number
>   to the correct number of clocks needed to be saved and corrected the
>   ASM code accordingly.
> - Removed the SHDWC from ULP0 wake-up source as it is not configured as
>   a valid wake-up source for ULP0.
> - Separated all the DTSI and DTS changes into individual patches.
> 
> 
> Li Bin (1):
>   ARM: at91: pm: fix at91_suspend_finish for ZQ calibration
> 
> Ryan Wanner (20):
>   dt-bindings: mfd: syscon: add microchip,sama7d65-ddr3phy
>   dt-bindings: mfd: syscon: add microchip,sama7d65-sfrbu

Ping me when these are ready to take.

>   dt-bindings: sram: Add microchip,sama7d65-sram
>   dt-bindings: power: reset: atmel,sama5d2-shdwc: Add
>     microchip,sama7d65-shdwc
>   dt-bindings: reset: atmel,at91sam9260-reset: add
>     microchip,sama7d65-rstc
>   dt-bindings: rtc: at91rm9200: add microchip,sama7d65-rtc
>   dt-bindings: at91rm9260-rtt: add microchip,sama7d65-rtt
>   ARM: at91: Add PM support to sama7d65
>   ARM: at91: pm: add DT compatible support for sama7d65
>   ARM: at91: PM: Add Backup mode for SAMA7D65
>   ARM: at91: pm: Enable ULP0/ULP1 for SAMA7D65
>   power: reset: at91-sama5d2_shdwc: Add sama7d65 PMC
>   ARM: dts: microchip: sama7d65: Add SRAM and DRAM components support
>   ARM: dts: microchip: sama7d65: Add Reset Controller to sama7d65 SoC
>   ARM: dts: microchip: sama7d65: Add Shutdown controller support
>   ARM: dts: microchip: sama7d65: Add RTT and GPBR Support for sama7d65
>     SoC
>   ARM: dts: microchip: sama7d65: Add RTC support for sama7d65
>   ARM: dts: microchip: sama7d65: Add SFRBU support to sama7d65
>   ARM: dts: microchip: sama7d65: Enable shutdown controller
>   ARM: dts: microchip: sama7d65: Add RTT timer to curiosity board
> 
>  .../devicetree/bindings/mfd/syscon.yaml       |   4 +
>  .../power/reset/atmel,sama5d2-shdwc.yaml      |   5 +
>  .../reset/atmel,at91sam9260-reset.yaml        |   3 +
>  .../bindings/rtc/atmel,at91rm9200-rtc.yaml    |   4 +-
>  .../bindings/rtc/atmel,at91sam9260-rtt.yaml   |   1 +
>  .../devicetree/bindings/sram/sram.yaml        |   1 +
>  .../dts/microchip/at91-sama7d65_curiosity.dts |  13 +++
>  arch/arm/boot/dts/microchip/sama7d65.dtsi     |  77 +++++++++++++
>  arch/arm/mach-at91/Kconfig                    |   1 +
>  arch/arm/mach-at91/pm.c                       |  47 +++++---
>  arch/arm/mach-at91/pm.h                       |   1 +
>  arch/arm/mach-at91/pm_data-offsets.c          |   2 +
>  arch/arm/mach-at91/pm_suspend.S               | 101 ++++++++++++++++--
>  drivers/power/reset/at91-sama5d2_shdwc.c      |   1 +
>  14 files changed, 238 insertions(+), 23 deletions(-)
> 
> -- 
> 2.43.0
> 

-- 
Lee Jones [???]


From mhklinux at outlook.com  Thu Mar 13 09:43:24 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Thu, 13 Mar 2025 16:43:24 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157C3F431CD26EDA05E4AD4D4D32@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 

I've done a partial review of the code in this patch.  See comments inline
as usual.

I'd like to still review most of the code in mshv_root_main.c, and maybe
some of mshv_synic.c and include/uapi/linux/mshv.c. I'll send a separate
email with those comments when I complete them. The patch is huge, so
I'm breaking my review comments into two parts.

I've glanced through mshv_eventfd.c, mshv_eventfd.h, and mshv_irq.c,
but I don't have enough knowledge/expertise in these areas to add any
useful comments, so I'm not planning to review them further.

> Provide a set of IOCTLs for creating and managing child partitions when
> running as root partition on Hyper-V. The new driver is enabled via
> CONFIG_MSHV_ROOT.
> 
> A brief overview of the interface:
> 
> MSHV_CREATE_PARTITION is the entry point, returning a file descriptor
> representing a child partition. IOCTLs on this fd can be used to map
> memory, create VPs, etc.
> 
> Creating a VP returns another file descriptor representing that VP which
> in turn has another set of corresponding IOCTLs for running the VP,
> getting/setting state, etc.
> 
> MSHV_ROOT_HVCALL is a generic "passthrough" hypercall IOCTL which can be
> used for a number of partition or VP hypercalls. This is for hypercalls
> that do not affect any state in the kernel driver, such as getting and
> setting VP registers and partition properties, translating addresses,
> etc. It is "passthrough" because the binary input and output for the
> hypercall is only interpreted by the VMM - the kernel driver does
> nothing but insert the VP and partition id where necessary (which are
> always in the same place), and execute the hypercall.
> 
> Co-developed-by: Wei Liu <wei.liu at kernel.org>
> Signed-off-by: Wei Liu <wei.liu at kernel.org>
> Co-developed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Signed-off-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Co-developed-by: Praveen K Paladugu <prapal at linux.microsoft.com>
> Signed-off-by: Praveen K Paladugu <prapal at linux.microsoft.com>
> Co-developed-by: Mukesh Rathor <mrathor at linux.microsoft.com>
> Signed-off-by: Mukesh Rathor <mrathor at linux.microsoft.com>
> Co-developed-by: Jinank Jain <jinankjain at microsoft.com>
> Signed-off-by: Jinank Jain <jinankjain at microsoft.com>
> Co-developed-by: Muminul Islam <muislam at microsoft.com>
> Signed-off-by: Muminul Islam <muislam at microsoft.com>
> Co-developed-by: Anirudh Rayabharam <anrayabh at linux.microsoft.com>
> Signed-off-by: Anirudh Rayabharam <anrayabh at linux.microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> ---
>  .../userspace-api/ioctl/ioctl-number.rst      |    2 +
>  drivers/hv/Makefile                           |    5 +-
>  drivers/hv/mshv.h                             |   30 +
>  drivers/hv/mshv_common.c                      |  161 ++
>  drivers/hv/mshv_eventfd.c                     |  833 ++++++
>  drivers/hv/mshv_eventfd.h                     |   71 +
>  drivers/hv/mshv_irq.c                         |  128 +
>  drivers/hv/mshv_portid_table.c                |   84 +
>  drivers/hv/mshv_root.h                        |  321 +++
>  drivers/hv/mshv_root_hv_call.c                |  876 +++++++
>  drivers/hv/mshv_root_main.c                   | 2329 +++++++++++++++++
>  drivers/hv/mshv_synic.c                       |  665 +++++
>  include/uapi/linux/mshv.h                     |  287 ++
>  13 files changed, 5791 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/hv/mshv.h
>  create mode 100644 drivers/hv/mshv_common.c
>  create mode 100644 drivers/hv/mshv_eventfd.c
>  create mode 100644 drivers/hv/mshv_eventfd.h
>  create mode 100644 drivers/hv/mshv_irq.c
>  create mode 100644 drivers/hv/mshv_portid_table.c
>  create mode 100644 drivers/hv/mshv_root.h
>  create mode 100644 drivers/hv/mshv_root_hv_call.c
>  create mode 100644 drivers/hv/mshv_root_main.c
>  create mode 100644 drivers/hv/mshv_synic.c
>  create mode 100644 include/uapi/linux/mshv.h
> 
> diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst
> b/Documentation/userspace-api/ioctl/ioctl-number.rst
> index 6d1465315df3..66dcfaae698b 100644
> --- a/Documentation/userspace-api/ioctl/ioctl-number.rst
> +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
> @@ -370,6 +370,8 @@ Code  Seq#    Include File                                           Comments
>  0xB7  all    uapi/linux/remoteproc_cdev.h                            <mailto:linux-
> remoteproc at vger.kernel.org>
>  0xB7  all    uapi/linux/nsfs.h                                       <mailto:Andrei Vagin
> <avagin at openvz.org>>
>  0xB8  01-02  uapi/misc/mrvl_cn10k_dpi.h                              Marvell CN10K DPI driver
> +0xB8  all    uapi/linux/mshv.h                                       Microsoft Hyper-V /dev/mshv driver

Hmmm. Doesn't this mean that the mshv ioctls overlap with the Marvell
CN10K DPI ioctls? Is that intentional? I thought the goal of the central
registry in ioctl-number.rst is to avoid overlap.

> +                                                                     <mailto:linux-hyperv at vger.kernel.org>
>  0xC0  00-0F  linux/usb/iowarrior.h
>  0xCA  00-0F  uapi/misc/cxl.h
>  0xCA  10-2F  uapi/misc/ocxl.h
> diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
> index 2b8dc954b350..976189c725dc 100644
> --- a/drivers/hv/Makefile
> +++ b/drivers/hv/Makefile
> @@ -2,6 +2,7 @@
>  obj-$(CONFIG_HYPERV)		+= hv_vmbus.o
>  obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
>  obj-$(CONFIG_HYPERV_BALLOON)	+= hv_balloon.o
> +obj-$(CONFIG_MSHV_ROOT)		+= mshv_root.o
> 
>  CFLAGS_hv_trace.o = -I$(src)
>  CFLAGS_hv_balloon.o = -I$(src)
> @@ -11,7 +12,9 @@ hv_vmbus-y := vmbus_drv.o \
>  		 channel_mgmt.o ring_buffer.o hv_trace.o
>  hv_vmbus-$(CONFIG_HYPERV_TESTING)	+= hv_debugfs.o
>  hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o
> +mshv_root-y := mshv_root_main.o mshv_synic.o mshv_eventfd.o mshv_irq.o \
> +	       mshv_root_hv_call.o mshv_portid_table.o
> 
>  # Code that must be built-in
>  obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o
> -obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o
> +obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o mshv_common.o
> diff --git a/drivers/hv/mshv.h b/drivers/hv/mshv.h
> new file mode 100644
> index 000000000000..0340a67acd0a
> --- /dev/null
> +++ b/drivers/hv/mshv.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, Microsoft Corporation.
> + */
> +
> +#ifndef _MSHV_H_
> +#define _MSHV_H_
> +
> +#include <linux/stddef.h>
> +#include <linux/string.h>
> +#include <hyperv/hvhdk.h>
> +
> +#define mshv_field_nonzero(STRUCT, MEMBER) \
> +	memchr_inv(&((STRUCT).MEMBER), \
> +		   0, sizeof_field(typeof(STRUCT), MEMBER))
> +
> +int hv_call_get_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +			     union hv_input_vtl input_vtl,
> +			     struct hv_register_assoc *registers);
> +
> +int hv_call_set_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +			     union hv_input_vtl input_vtl,
> +			     struct hv_register_assoc *registers);
> +
> +int hv_call_get_partition_property(u64 partition_id, u64 property_code,
> +				   u64 *property_value);
> +
> +int mshv_do_pre_guest_mode_work(ulong th_flags);
> +
> +#endif /* _MSHV_H */
> diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
> new file mode 100644
> index 000000000000..d97631dcbee1
> --- /dev/null
> +++ b/drivers/hv/mshv_common.c
> @@ -0,0 +1,161 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024, Microsoft Corporation.
> + *
> + * This file contains functions that are called from one or more modules: ROOT,
> + * DIAG, or VTL. If any of these modules are configured to build, this file is

What are the DIAG and VTL modules?  I see only a root module in the Makefile.

> + * built and just statically linked in.
> + *
> + * Authors: Microsoft Linux virtualization team
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <asm/mshyperv.h>
> +#include <linux/resume_user_mode.h>
> +
> +#include "mshv.h"
> +
> +#define HV_GET_REGISTER_BATCH_SIZE	\
> +	(HV_HYP_PAGE_SIZE / sizeof(union hv_register_value))
> +#define HV_SET_REGISTER_BATCH_SIZE	\
> +	((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_set_vp_registers)) \
> +		/ sizeof(struct hv_register_assoc))
> +
> +int hv_call_get_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +			     union hv_input_vtl input_vtl,
> +			     struct hv_register_assoc *registers)
> +{
> +	struct hv_input_get_vp_registers *input_page;
> +	union hv_register_value *output_page;
> +	u16 completed = 0;
> +	unsigned long remaining = count;
> +	int rep_count, i;
> +	u64 status = HV_STATUS_SUCCESS;
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +
> +	input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +	output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +	input_page->partition_id = partition_id;
> +	input_page->vp_index = vp_index;
> +	input_page->input_vtl.as_uint8 = input_vtl.as_uint8;
> +	input_page->rsvd_z8 = 0;
> +	input_page->rsvd_z16 = 0;
> +
> +	while (remaining) {
> +		rep_count = min(remaining, HV_GET_REGISTER_BATCH_SIZE);
> +		for (i = 0; i < rep_count; ++i)
> +			input_page->names[i] = registers[i].name;
> +
> +		status = hv_do_rep_hypercall(HVCALL_GET_VP_REGISTERS, rep_count,
> +					     0, input_page, output_page);
> +		if (!hv_result_success(status))
> +			break;
> +
> +		completed = hv_repcomp(status);
> +		for (i = 0; i < completed; ++i)
> +			registers[i].value = output_page[i];
> +
> +		registers += completed;
> +		remaining -= completed;
> +	}
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +EXPORT_SYMBOL_GPL(hv_call_get_vp_registers);
> +
> +int hv_call_set_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +			     union hv_input_vtl input_vtl,
> +			     struct hv_register_assoc *registers)
> +{
> +	struct hv_input_set_vp_registers *input_page;
> +	u16 completed = 0;
> +	unsigned long remaining = count;
> +	int rep_count;
> +	u64 status = HV_STATUS_SUCCESS;
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +	input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +	input_page->partition_id = partition_id;
> +	input_page->vp_index = vp_index;
> +	input_page->input_vtl.as_uint8 = input_vtl.as_uint8;
> +	input_page->rsvd_z8 = 0;
> +	input_page->rsvd_z16 = 0;
> +
> +	while (remaining) {
> +		rep_count = min(remaining, HV_SET_REGISTER_BATCH_SIZE);
> +		memcpy(input_page->elements, registers,
> +		       sizeof(struct hv_register_assoc) * rep_count);
> +
> +		status = hv_do_rep_hypercall(HVCALL_SET_VP_REGISTERS, rep_count,
> +					     0, input_page, NULL);
> +		if (!hv_result_success(status))
> +			break;
> +
> +		completed = hv_repcomp(status);
> +		registers += completed;
> +		remaining -= completed;
> +	}
> +
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +EXPORT_SYMBOL_GPL(hv_call_set_vp_registers);
> +
> +int hv_call_get_partition_property(u64 partition_id,
> +				   u64 property_code,
> +				   u64 *property_value)
> +{
> +	u64 status;
> +	unsigned long flags;
> +	struct hv_input_get_partition_property *input;
> +	struct hv_output_get_partition_property *output;
> +
> +	local_irq_save(flags);
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +	memset(input, 0, sizeof(*input));
> +	input->partition_id = partition_id;
> +	input->property_code = property_code;
> +	status = hv_do_hypercall(HVCALL_GET_PARTITION_PROPERTY, input, output);
> +
> +	if (!hv_result_success(status)) {
> +		local_irq_restore(flags);
> +		return hv_result_to_errno(status);
> +	}
> +	*property_value = output->property_value;
> +
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(hv_call_get_partition_property);
> +
> +/*
> + * Handle any pre-processing before going into the guest mode on this cpu, most
> + * notably call schedule(). Must be invoked with both preemption and
> + * interrupts enabled.
> + *
> + * Returns: 0 on success, -errno on error.
> + */
> +int mshv_do_pre_guest_mode_work(ulong th_flags)
> +{
> +	if (th_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
> +		return -EINTR;
> +
> +	if (th_flags & _TIF_NEED_RESCHED)
> +		schedule();
> +
> +	if (th_flags & _TIF_NOTIFY_RESUME)
> +		resume_user_mode_work(NULL);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(mshv_do_pre_guest_mode_work);
> diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c
> new file mode 100644
> index 000000000000..8dd22be2ca0b
> --- /dev/null
> +++ b/drivers/hv/mshv_eventfd.c
> @@ -0,0 +1,833 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * eventfd support for mshv
> + *
> + * Heavily inspired from KVM implementation of irqfd/ioeventfd. The basic
> + * framework code is taken from the kvm implementation.
> + *
> + * All credits to kvm developers.
> + */
> +
> +#include <linux/syscalls.h>
> +#include <linux/wait.h>
> +#include <linux/poll.h>
> +#include <linux/file.h>
> +#include <linux/list.h>
> +#include <linux/workqueue.h>
> +#include <linux/eventfd.h>
> +
> +#if IS_ENABLED(CONFIG_X86_64)
> +#include <asm/apic.h>
> +#endif
> +#include <asm/mshyperv.h>
> +
> +#include "mshv_eventfd.h"
> +#include "mshv.h"
> +#include "mshv_root.h"
> +
> +static struct workqueue_struct *irqfd_cleanup_wq;
> +
> +void mshv_register_irq_ack_notifier(struct mshv_partition *partition,
> +				    struct mshv_irq_ack_notifier *mian)
> +{
> +	mutex_lock(&partition->pt_irq_lock);
> +	hlist_add_head_rcu(&mian->link, &partition->irq_ack_notifier_list);
> +	mutex_unlock(&partition->pt_irq_lock);
> +}
> +
> +void mshv_unregister_irq_ack_notifier(struct mshv_partition *partition,
> +				      struct mshv_irq_ack_notifier *mian)
> +{
> +	mutex_lock(&partition->pt_irq_lock);
> +	hlist_del_init_rcu(&mian->link);
> +	mutex_unlock(&partition->pt_irq_lock);
> +	synchronize_rcu();
> +}
> +
> +bool mshv_notify_acked_gsi(struct mshv_partition *partition, int gsi)
> +{
> +	struct mshv_irq_ack_notifier *mian;
> +	bool acked = false;
> +
> +	rcu_read_lock();
> +	hlist_for_each_entry_rcu(mian, &partition->irq_ack_notifier_list,
> +				 link) {
> +		if (mian->irq_ack_gsi == gsi) {
> +			mian->irq_acked(mian);
> +			acked = true;
> +		}
> +	}
> +	rcu_read_unlock();
> +
> +	return acked;
> +}
> +
> +#if IS_ENABLED(CONFIG_ARM64)
> +static inline bool hv_should_clear_interrupt(enum hv_interrupt_type type)
> +{
> +	return false;
> +}
> +#elif IS_ENABLED(CONFIG_X86_64)
> +static inline bool hv_should_clear_interrupt(enum hv_interrupt_type type)
> +{
> +	return type == HV_X64_INTERRUPT_TYPE_EXTINT;
> +}
> +#endif
> +
> +static void mshv_irqfd_resampler_ack(struct mshv_irq_ack_notifier *mian)
> +{
> +	struct mshv_irqfd_resampler *resampler;
> +	struct mshv_partition *partition;
> +	struct mshv_irqfd *irqfd;
> +	int idx;
> +
> +	resampler = container_of(mian, struct mshv_irqfd_resampler,
> +				 rsmplr_notifier);
> +	partition = resampler->rsmplr_partn;
> +
> +	idx = srcu_read_lock(&partition->pt_irq_srcu);
> +
> +	hlist_for_each_entry_rcu(irqfd, &resampler->rsmplr_irqfd_list,
> +				 irqfd_resampler_hnode) {
> +		if (hv_should_clear_interrupt(irqfd->irqfd_lapic_irq.lapic_control.interrupt_type))
> +			hv_call_clear_virtual_interrupt(partition->pt_id);
> +
> +		eventfd_signal(irqfd->irqfd_resamplefd);
> +	}
> +
> +	srcu_read_unlock(&partition->pt_irq_srcu, idx);
> +}
> +
> +#if IS_ENABLED(CONFIG_X86_64)
> +static bool
> +mshv_vp_irq_vector_injected(union hv_vp_register_page_interrupt_vectors iv,
> +			    u32 vector)
> +{
> +	int i;
> +
> +	for (i = 0; i < iv.vector_count; i++) {
> +		if (iv.vector[i] == vector)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static int mshv_vp_irq_try_set_vector(struct mshv_vp *vp, u32 vector)
> +{
> +	union hv_vp_register_page_interrupt_vectors iv, new_iv;
> +
> +	iv = vp->vp_register_page->interrupt_vectors;
> +	new_iv = iv;
> +
> +	if (mshv_vp_irq_vector_injected(iv, vector))
> +		return 0;
> +
> +	if (iv.vector_count >= HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT)
> +		return -ENOSPC;
> +
> +	new_iv.vector[new_iv.vector_count++] = vector;
> +
> +	if (cmpxchg(&vp->vp_register_page->interrupt_vectors.as_uint64,
> +		    iv.as_uint64, new_iv.as_uint64) != iv.as_uint64)
> +		return -EAGAIN;
> +
> +	return 0;
> +}
> +
> +static int mshv_vp_irq_set_vector(struct mshv_vp *vp, u32 vector)
> +{
> +	int ret;
> +
> +	do {
> +		ret = mshv_vp_irq_try_set_vector(vp, vector);
> +	} while (ret == -EAGAIN && !need_resched());
> +
> +	return ret;
> +}
> +
> +/*
> + * Try to raise irq for guest via shared vector array. hyp does the actual
> + * inject of the interrupt.
> + */
> +static int mshv_try_assert_irq_fast(struct mshv_irqfd *irqfd)
> +{
> +	struct mshv_partition *partition = irqfd->irqfd_partn;
> +	struct mshv_lapic_irq *irq = &irqfd->irqfd_lapic_irq;
> +	struct mshv_vp *vp;
> +
> +	if (!(ms_hyperv.ext_features &
> +	      HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE))
> +		return -EOPNOTSUPP;
> +
> +	if (hv_scheduler_type != HV_SCHEDULER_TYPE_ROOT)
> +		return -EOPNOTSUPP;
> +
> +	if (irq->lapic_control.logical_dest_mode)
> +		return -EOPNOTSUPP;
> +
> +	vp = partition->pt_vp_array[irq->lapic_apic_id];
> +
> +	if (!vp->vp_register_page)
> +		return -EOPNOTSUPP;
> +
> +	if (mshv_vp_irq_set_vector(vp, irq->lapic_vector))
> +		return -EINVAL;
> +
> +	if (vp->run.flags.root_sched_dispatched &&
> +	    vp->vp_register_page->interrupt_vectors.as_uint64)
> +		return -EBUSY;
> +
> +	wake_up(&vp->run.vp_suspend_queue);
> +
> +	return 0;
> +}
> +#else /* CONFIG_X86_64 */
> +static int mshv_try_assert_irq_fast(struct mshv_irqfd *irqfd)
> +{
> +	return -EOPNOTSUPP;
> +}
> +#endif
> +
> +static void mshv_assert_irq_slow(struct mshv_irqfd *irqfd)
> +{
> +	struct mshv_partition *partition = irqfd->irqfd_partn;
> +	struct mshv_lapic_irq *irq = &irqfd->irqfd_lapic_irq;
> +	unsigned int seq;
> +	int idx;
> +
> +	WARN_ON(irqfd->irqfd_resampler &&
> +		!irq->lapic_control.level_triggered);
> +
> +	idx = srcu_read_lock(&partition->pt_irq_srcu);
> +	if (irqfd->irqfd_girq_ent.guest_irq_num) {
> +		if (!irqfd->irqfd_girq_ent.girq_entry_valid) {
> +			srcu_read_unlock(&partition->pt_irq_srcu, idx);
> +			return;
> +		}
> +
> +		do {
> +			seq = read_seqcount_begin(&irqfd->irqfd_irqe_sc);
> +		} while (read_seqcount_retry(&irqfd->irqfd_irqe_sc, seq));
> +	}
> +
> +	hv_call_assert_virtual_interrupt(irqfd->irqfd_partn->pt_id,
> +					 irq->lapic_vector, irq->lapic_apic_id,
> +					 irq->lapic_control);
> +	srcu_read_unlock(&partition->pt_irq_srcu, idx);
> +}
> +
> +static void mshv_irqfd_resampler_shutdown(struct mshv_irqfd *irqfd)
> +{
> +	struct mshv_irqfd_resampler *rp = irqfd->irqfd_resampler;
> +	struct mshv_partition *pt = rp->rsmplr_partn;
> +
> +	mutex_lock(&pt->irqfds_resampler_lock);
> +
> +	hlist_del_rcu(&irqfd->irqfd_resampler_hnode);
> +	synchronize_srcu(&pt->pt_irq_srcu);
> +
> +	if (hlist_empty(&rp->rsmplr_irqfd_list)) {
> +		hlist_del(&rp->rsmplr_hnode);
> +		mshv_unregister_irq_ack_notifier(pt, &rp->rsmplr_notifier);
> +		kfree(rp);
> +	}
> +
> +	mutex_unlock(&pt->irqfds_resampler_lock);
> +}
> +
> +/*
> + * Race-free decouple logic (ordering is critical)
> + */
> +static void mshv_irqfd_shutdown(struct work_struct *work)
> +{
> +	struct mshv_irqfd *irqfd =
> +			container_of(work, struct mshv_irqfd, irqfd_shutdown);
> +
> +	/*
> +	 * Synchronize with the wait-queue and unhook ourselves to prevent
> +	 * further events.
> +	 */
> +	remove_wait_queue(irqfd->irqfd_wqh, &irqfd->irqfd_wait);
> +
> +	if (irqfd->irqfd_resampler) {
> +		mshv_irqfd_resampler_shutdown(irqfd);
> +		eventfd_ctx_put(irqfd->irqfd_resamplefd);
> +	}
> +
> +	/*
> +	 * It is now safe to release the object's resources
> +	 */
> +	eventfd_ctx_put(irqfd->irqfd_eventfd_ctx);
> +	kfree(irqfd);
> +}
> +
> +/* assumes partition->pt_irqfds_lock is held */
> +static bool mshv_irqfd_is_active(struct mshv_irqfd *irqfd)
> +{
> +	return !hlist_unhashed(&irqfd->irqfd_hnode);
> +}
> +
> +/*
> + * Mark the irqfd as inactive and schedule it for removal
> + *
> + * assumes partition->pt_irqfds_lock is held
> + */
> +static void mshv_irqfd_deactivate(struct mshv_irqfd *irqfd)
> +{
> +	if (!mshv_irqfd_is_active(irqfd))
> +		return;
> +
> +	hlist_del(&irqfd->irqfd_hnode);
> +
> +	queue_work(irqfd_cleanup_wq, &irqfd->irqfd_shutdown);
> +}
> +
> +/*
> + * Called with wqh->lock held and interrupts disabled
> + */
> +static int mshv_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode,
> +			     int sync, void *key)
> +{
> +	struct mshv_irqfd *irqfd = container_of(wait, struct mshv_irqfd,
> +						irqfd_wait);
> +	unsigned long flags = (unsigned long)key;
> +	int idx;
> +	unsigned int seq;
> +	struct mshv_partition *pt = irqfd->irqfd_partn;
> +	int ret = 0;
> +
> +	if (flags & POLLIN) {
> +		u64 cnt;
> +
> +		eventfd_ctx_do_read(irqfd->irqfd_eventfd_ctx, &cnt);
> +		idx = srcu_read_lock(&pt->pt_irq_srcu);
> +		do {
> +			seq = read_seqcount_begin(&irqfd->irqfd_irqe_sc);
> +		} while (read_seqcount_retry(&irqfd->irqfd_irqe_sc, seq));
> +
> +		/* An event has been signaled, raise an interrupt */
> +		ret = mshv_try_assert_irq_fast(irqfd);
> +		if (ret)
> +			mshv_assert_irq_slow(irqfd);
> +
> +		srcu_read_unlock(&pt->pt_irq_srcu, idx);
> +
> +		ret = 1;
> +	}
> +
> +	if (flags & POLLHUP) {
> +		/* The eventfd is closing, detach from the partition */
> +		unsigned long flags;
> +
> +		spin_lock_irqsave(&pt->pt_irqfds_lock, flags);
> +
> +		/*
> +		 * We must check if someone deactivated the irqfd before
> +		 * we could acquire the pt_irqfds_lock since the item is
> +		 * deactivated from the mshv side before it is unhooked from
> +		 * the wait-queue.  If it is already deactivated, we can
> +		 * simply return knowing the other side will cleanup for us.
> +		 * We cannot race against the irqfd going away since the
> +		 * other side is required to acquire wqh->lock, which we hold
> +		 */
> +		if (mshv_irqfd_is_active(irqfd))
> +			mshv_irqfd_deactivate(irqfd);
> +
> +		spin_unlock_irqrestore(&pt->pt_irqfds_lock, flags);
> +	}
> +
> +	return ret;
> +}
> +
> +/* Must be called under pt_irqfds_lock */
> +static void mshv_irqfd_update(struct mshv_partition *pt,
> +			      struct mshv_irqfd *irqfd)
> +{
> +	write_seqcount_begin(&irqfd->irqfd_irqe_sc);
> +	irqfd->irqfd_girq_ent = mshv_ret_girq_entry(pt,
> +						    irqfd->irqfd_irqnum);
> +	mshv_copy_girq_info(&irqfd->irqfd_girq_ent, &irqfd->irqfd_lapic_irq);
> +	write_seqcount_end(&irqfd->irqfd_irqe_sc);
> +}
> +
> +void mshv_irqfd_routing_update(struct mshv_partition *pt)
> +{
> +	struct mshv_irqfd *irqfd;
> +
> +	spin_lock_irq(&pt->pt_irqfds_lock);
> +	hlist_for_each_entry(irqfd, &pt->pt_irqfds_list, irqfd_hnode)
> +		mshv_irqfd_update(pt, irqfd);
> +	spin_unlock_irq(&pt->pt_irqfds_lock);
> +}
> +
> +static void mshv_irqfd_queue_proc(struct file *file, wait_queue_head_t *wqh,
> +				  poll_table *polltbl)
> +{
> +	struct mshv_irqfd *irqfd =
> +			container_of(polltbl, struct mshv_irqfd, irqfd_polltbl);
> +
> +	irqfd->irqfd_wqh = wqh;
> +	add_wait_queue_priority(wqh, &irqfd->irqfd_wait);
> +}
> +
> +static int mshv_irqfd_assign(struct mshv_partition *pt,
> +			     struct mshv_user_irqfd *args)
> +{
> +	struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
> +	struct mshv_irqfd *irqfd, *tmp;
> +	unsigned int events;
> +	struct fd f;
> +	int ret;
> +	int idx;
> +
> +	irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
> +	if (!irqfd)
> +		return -ENOMEM;
> +
> +	irqfd->irqfd_partn = pt;
> +	irqfd->irqfd_irqnum = args->gsi;
> +	INIT_WORK(&irqfd->irqfd_shutdown, mshv_irqfd_shutdown);
> +	seqcount_spinlock_init(&irqfd->irqfd_irqe_sc, &pt->pt_irqfds_lock);
> +
> +	f = fdget(args->fd);
> +	if (!fd_file(f)) {
> +		ret = -EBADF;
> +		goto out;
> +	}
> +
> +	eventfd = eventfd_ctx_fileget(fd_file(f));
> +	if (IS_ERR(eventfd)) {
> +		ret = PTR_ERR(eventfd);
> +		goto fail;
> +	}
> +
> +	irqfd->irqfd_eventfd_ctx = eventfd;
> +
> +	if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE)) {
> +		struct mshv_irqfd_resampler *rp;
> +
> +		resamplefd = eventfd_ctx_fdget(args->resamplefd);
> +		if (IS_ERR(resamplefd)) {
> +			ret = PTR_ERR(resamplefd);
> +			goto fail;
> +		}
> +
> +		irqfd->irqfd_resamplefd = resamplefd;
> +
> +		mutex_lock(&pt->irqfds_resampler_lock);
> +
> +		hlist_for_each_entry(rp, &pt->irqfds_resampler_list,
> +				     rsmplr_hnode) {
> +			if (rp->rsmplr_notifier.irq_ack_gsi ==
> +							 irqfd->irqfd_irqnum) {
> +				irqfd->irqfd_resampler = rp;
> +				break;
> +			}
> +		}
> +
> +		if (!irqfd->irqfd_resampler) {
> +			rp = kzalloc(sizeof(*rp), GFP_KERNEL_ACCOUNT);
> +			if (!rp) {
> +				ret = -ENOMEM;
> +				mutex_unlock(&pt->irqfds_resampler_lock);
> +				goto fail;
> +			}
> +
> +			rp->rsmplr_partn = pt;
> +			INIT_HLIST_HEAD(&rp->rsmplr_irqfd_list);
> +			rp->rsmplr_notifier.irq_ack_gsi = irqfd->irqfd_irqnum;
> +			rp->rsmplr_notifier.irq_acked =
> +						      mshv_irqfd_resampler_ack;
> +
> +			hlist_add_head(&rp->rsmplr_hnode,
> +				       &pt->irqfds_resampler_list);
> +			mshv_register_irq_ack_notifier(pt,
> +						       &rp->rsmplr_notifier);
> +			irqfd->irqfd_resampler = rp;
> +		}
> +
> +		hlist_add_head_rcu(&irqfd->irqfd_resampler_hnode,
> +				   &irqfd->irqfd_resampler->rsmplr_irqfd_list);
> +
> +		mutex_unlock(&pt->irqfds_resampler_lock);
> +	}
> +
> +	/*
> +	 * Install our own custom wake-up handling so we are notified via
> +	 * a callback whenever someone signals the underlying eventfd
> +	 */
> +	init_waitqueue_func_entry(&irqfd->irqfd_wait, mshv_irqfd_wakeup);
> +	init_poll_funcptr(&irqfd->irqfd_polltbl, mshv_irqfd_queue_proc);
> +
> +	spin_lock_irq(&pt->pt_irqfds_lock);
> +	if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) &&
> +	    !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) {
> +		/*
> +		 * Resample Fd must be for level triggered interrupt
> +		 * Otherwise return with failure
> +		 */
> +		spin_unlock_irq(&pt->pt_irqfds_lock);
> +		ret = -EINVAL;
> +		goto fail;
> +	}
> +	ret = 0;
> +	hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) {
> +		if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx)
> +			continue;
> +		/* This fd is used for another irq already. */
> +		ret = -EBUSY;
> +		spin_unlock_irq(&pt->pt_irqfds_lock);
> +		goto fail;
> +	}
> +
> +	idx = srcu_read_lock(&pt->pt_irq_srcu);
> +	mshv_irqfd_update(pt, irqfd);
> +	hlist_add_head(&irqfd->irqfd_hnode, &pt->pt_irqfds_list);
> +	spin_unlock_irq(&pt->pt_irqfds_lock);
> +
> +	/*
> +	 * Check if there was an event already pending on the eventfd
> +	 * before we registered, and trigger it as if we didn't miss it.
> +	 */
> +	events = vfs_poll(fd_file(f), &irqfd->irqfd_polltbl);
> +
> +	if (events & POLLIN)
> +		mshv_assert_irq_slow(irqfd);
> +
> +	srcu_read_unlock(&pt->pt_irq_srcu, idx);
> +	/*
> +	 * do not drop the file until the irqfd is fully initialized, otherwise
> +	 * we might race against the POLLHUP
> +	 */
> +	fdput(f);
> +
> +	return 0;
> +
> +fail:
> +	if (irqfd->irqfd_resampler)
> +		mshv_irqfd_resampler_shutdown(irqfd);
> +
> +	if (resamplefd && !IS_ERR(resamplefd))
> +		eventfd_ctx_put(resamplefd);
> +
> +	if (eventfd && !IS_ERR(eventfd))
> +		eventfd_ctx_put(eventfd);
> +
> +	fdput(f);
> +
> +out:
> +	kfree(irqfd);
> +	return ret;
> +}
> +
> +/*
> + * shutdown any irqfd's that match fd+gsi
> + */
> +static int mshv_irqfd_deassign(struct mshv_partition *pt,
> +			       struct mshv_user_irqfd *args)
> +{
> +	struct mshv_irqfd *irqfd;
> +	struct hlist_node *n;
> +	struct eventfd_ctx *eventfd;
> +
> +	eventfd = eventfd_ctx_fdget(args->fd);
> +	if (IS_ERR(eventfd))
> +		return PTR_ERR(eventfd);
> +
> +	hlist_for_each_entry_safe(irqfd, n, &pt->pt_irqfds_list,
> +				  irqfd_hnode) {
> +		if (irqfd->irqfd_eventfd_ctx == eventfd &&
> +		    irqfd->irqfd_irqnum == args->gsi)
> +
> +			mshv_irqfd_deactivate(irqfd);
> +	}
> +
> +	eventfd_ctx_put(eventfd);
> +
> +	/*
> +	 * Block until we know all outstanding shutdown jobs have completed
> +	 * so that we guarantee there will not be any more interrupts on this
> +	 * gsi once this deassign function returns.
> +	 */
> +	flush_workqueue(irqfd_cleanup_wq);
> +
> +	return 0;
> +}
> +
> +int mshv_set_unset_irqfd(struct mshv_partition *pt,
> +			 struct mshv_user_irqfd *args)
> +{
> +	if (args->flags & ~MSHV_IRQFD_FLAGS_MASK)
> +		return -EINVAL;
> +
> +	if (args->flags & BIT(MSHV_IRQFD_BIT_DEASSIGN))
> +		return mshv_irqfd_deassign(pt, args);
> +
> +	return mshv_irqfd_assign(pt, args);
> +}
> +
> +/*
> + * This function is called as the mshv VM fd is being released.
> + * Shutdown all irqfds that still remain open
> + */
> +static void mshv_irqfd_release(struct mshv_partition *pt)
> +{
> +	struct mshv_irqfd *irqfd;
> +	struct hlist_node *n;
> +
> +	spin_lock_irq(&pt->pt_irqfds_lock);
> +
> +	hlist_for_each_entry_safe(irqfd, n, &pt->pt_irqfds_list, irqfd_hnode)
> +		mshv_irqfd_deactivate(irqfd);
> +
> +	spin_unlock_irq(&pt->pt_irqfds_lock);
> +
> +	/*
> +	 * Block until we know all outstanding shutdown jobs have completed
> +	 * since we do not take a mshv_partition* reference.
> +	 */
> +	flush_workqueue(irqfd_cleanup_wq);
> +}
> +
> +int mshv_irqfd_wq_init(void)
> +{
> +	irqfd_cleanup_wq = alloc_workqueue("mshv-irqfd-cleanup", 0, 0);
> +	if (!irqfd_cleanup_wq)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +void mshv_irqfd_wq_cleanup(void)
> +{
> +	destroy_workqueue(irqfd_cleanup_wq);
> +}
> +
> +/*
> + * --------------------------------------------------------------------
> + * ioeventfd: translate a MMIO memory write to an eventfd signal.
> + *
> + * userspace can register a MMIO address with an eventfd for receiving
> + * notification when the memory has been touched.
> + * --------------------------------------------------------------------
> + */
> +
> +static void ioeventfd_release(struct mshv_ioeventfd *p, u64 partition_id)
> +{
> +	if (p->iovntfd_doorbell_id > 0)
> +		mshv_unregister_doorbell(partition_id, p->iovntfd_doorbell_id);
> +	eventfd_ctx_put(p->iovntfd_eventfd);
> +	kfree(p);
> +}
> +
> +/* MMIO writes trigger an event if the addr/val match */
> +static void ioeventfd_mmio_write(int doorbell_id, void *data)
> +{
> +	struct mshv_partition *partition = (struct mshv_partition *)data;
> +	struct mshv_ioeventfd *p;
> +
> +	rcu_read_lock();
> +	hlist_for_each_entry_rcu(p, &partition->ioeventfds_list, iovntfd_hnode)
> +		if (p->iovntfd_doorbell_id == doorbell_id) {
> +			eventfd_signal(p->iovntfd_eventfd);
> +			break;
> +		}
> +
> +	rcu_read_unlock();
> +}
> +
> +static bool ioeventfd_check_collision(struct mshv_partition *pt,
> +				      struct mshv_ioeventfd *p)
> +	__must_hold(&pt->mutex)
> +{
> +	struct mshv_ioeventfd *_p;
> +
> +	hlist_for_each_entry(_p, &pt->ioeventfds_list, iovntfd_hnode)
> +		if (_p->iovntfd_addr == p->iovntfd_addr &&
> +		    _p->iovntfd_length == p->iovntfd_length &&
> +		    (_p->iovntfd_wildcard || p->iovntfd_wildcard ||
> +		     _p->iovntfd_datamatch == p->iovntfd_datamatch))
> +			return true;
> +
> +	return false;
> +}
> +
> +static int mshv_assign_ioeventfd(struct mshv_partition *pt,
> +				 struct mshv_user_ioeventfd *args)
> +	__must_hold(&pt->mutex)
> +{
> +	struct mshv_ioeventfd *p;
> +	struct eventfd_ctx *eventfd;
> +	u64 doorbell_flags = 0;
> +	int ret;
> +
> +	/* This mutex is currently protecting ioeventfd.items list */
> +	WARN_ON_ONCE(!mutex_is_locked(&pt->pt_mutex));
> +
> +	if (args->flags & BIT(MSHV_IOEVENTFD_BIT_PIO))
> +		return -EOPNOTSUPP;
> +
> +	/* must be natural-word sized */
> +	switch (args->len) {
> +	case 0:
> +		doorbell_flags = HV_DOORBELL_FLAG_TRIGGER_SIZE_ANY;
> +		break;
> +	case 1:
> +		doorbell_flags = HV_DOORBELL_FLAG_TRIGGER_SIZE_BYTE;
> +		break;
> +	case 2:
> +		doorbell_flags = HV_DOORBELL_FLAG_TRIGGER_SIZE_WORD;
> +		break;
> +	case 4:
> +		doorbell_flags = HV_DOORBELL_FLAG_TRIGGER_SIZE_DWORD;
> +		break;
> +	case 8:
> +		doorbell_flags = HV_DOORBELL_FLAG_TRIGGER_SIZE_QWORD;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/* check for range overflow */
> +	if (args->addr + args->len < args->addr)
> +		return -EINVAL;
> +
> +	/* check for extra flags that we don't understand */
> +	if (args->flags & ~MSHV_IOEVENTFD_FLAGS_MASK)
> +		return -EINVAL;
> +
> +	eventfd = eventfd_ctx_fdget(args->fd);
> +	if (IS_ERR(eventfd))
> +		return PTR_ERR(eventfd);
> +
> +	p = kzalloc(sizeof(*p), GFP_KERNEL);
> +	if (!p) {
> +		ret = -ENOMEM;
> +		goto fail;
> +	}
> +
> +	p->iovntfd_addr = args->addr;
> +	p->iovntfd_length  = args->len;
> +	p->iovntfd_eventfd = eventfd;
> +
> +	/* The datamatch feature is optional, otherwise this is a wildcard */
> +	if (args->flags & BIT(MSHV_IOEVENTFD_BIT_DATAMATCH)) {
> +		p->iovntfd_datamatch = args->datamatch;
> +	} else {
> +		p->iovntfd_wildcard = true;
> +		doorbell_flags |= HV_DOORBELL_FLAG_TRIGGER_ANY_VALUE;
> +	}
> +
> +	if (ioeventfd_check_collision(pt, p)) {
> +		ret = -EEXIST;
> +		goto unlock_fail;
> +	}
> +
> +	ret = mshv_register_doorbell(pt->pt_id, ioeventfd_mmio_write,
> +				     (void *)pt, p->iovntfd_addr,
> +				     p->iovntfd_datamatch, doorbell_flags);
> +	if (ret < 0)
> +		goto unlock_fail;
> +
> +	p->iovntfd_doorbell_id = ret;
> +
> +	hlist_add_head_rcu(&p->iovntfd_hnode, &pt->ioeventfds_list);
> +
> +	return 0;
> +
> +unlock_fail:
> +	kfree(p);
> +
> +fail:
> +	eventfd_ctx_put(eventfd);
> +
> +	return ret;
> +}
> +
> +static int mshv_deassign_ioeventfd(struct mshv_partition *pt,
> +				   struct mshv_user_ioeventfd *args)
> +	__must_hold(&pt->mutex)
> +{
> +	struct mshv_ioeventfd *p;
> +	struct eventfd_ctx *eventfd;
> +	struct hlist_node *n;
> +	int ret = -ENOENT;
> +
> +	/* This mutex is currently protecting ioeventfd.items list */
> +	WARN_ON_ONCE(!mutex_is_locked(&pt->pt_mutex));
> +
> +	eventfd = eventfd_ctx_fdget(args->fd);
> +	if (IS_ERR(eventfd))
> +		return PTR_ERR(eventfd);
> +
> +	hlist_for_each_entry_safe(p, n, &pt->ioeventfds_list, iovntfd_hnode) {
> +		bool wildcard = !(args->flags & BIT(MSHV_IOEVENTFD_BIT_DATAMATCH));
> +
> +		if (p->iovntfd_eventfd != eventfd  ||
> +		    p->iovntfd_addr != args->addr  ||
> +		    p->iovntfd_length != args->len ||
> +		    p->iovntfd_wildcard != wildcard)
> +			continue;
> +
> +		if (!p->iovntfd_wildcard &&
> +		    p->iovntfd_datamatch != args->datamatch)
> +			continue;
> +
> +		hlist_del_rcu(&p->iovntfd_hnode);
> +		synchronize_rcu();
> +		ioeventfd_release(p, pt->pt_id);
> +		ret = 0;
> +		break;
> +	}
> +
> +	eventfd_ctx_put(eventfd);
> +
> +	return ret;
> +}
> +
> +int mshv_set_unset_ioeventfd(struct mshv_partition *pt,
> +			     struct mshv_user_ioeventfd *args)
> +	__must_hold(&pt->mutex)
> +{
> +	if ((args->flags & ~MSHV_IOEVENTFD_FLAGS_MASK) ||
> +	    mshv_field_nonzero(*args, rsvd))
> +		return -EINVAL;
> +
> +	/* PIO not yet implemented */
> +	if (args->flags & BIT(MSHV_IOEVENTFD_BIT_PIO))
> +		return -EOPNOTSUPP;
> +
> +	if (args->flags & BIT(MSHV_IOEVENTFD_BIT_DEASSIGN))
> +		return mshv_deassign_ioeventfd(pt, args);
> +
> +	return mshv_assign_ioeventfd(pt, args);
> +}
> +
> +void mshv_eventfd_init(struct mshv_partition *pt)
> +{
> +	spin_lock_init(&pt->pt_irqfds_lock);
> +	INIT_HLIST_HEAD(&pt->pt_irqfds_list);
> +
> +	INIT_HLIST_HEAD(&pt->irqfds_resampler_list);
> +	mutex_init(&pt->irqfds_resampler_lock);
> +
> +	INIT_HLIST_HEAD(&pt->ioeventfds_list);
> +}
> +
> +void mshv_eventfd_release(struct mshv_partition *pt)
> +{
> +	struct hlist_head items;
> +	struct hlist_node *n;
> +	struct mshv_ioeventfd *p;
> +
> +	hlist_move_list(&pt->ioeventfds_list, &items);
> +	synchronize_rcu();
> +
> +	hlist_for_each_entry_safe(p, n, &items, iovntfd_hnode) {
> +		hlist_del(&p->iovntfd_hnode);
> +		ioeventfd_release(p, pt->pt_id);
> +	}
> +
> +	mshv_irqfd_release(pt);
> +}
> diff --git a/drivers/hv/mshv_eventfd.h b/drivers/hv/mshv_eventfd.h
> new file mode 100644
> index 000000000000..332e7670a344
> --- /dev/null
> +++ b/drivers/hv/mshv_eventfd.h
> @@ -0,0 +1,71 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * irqfd: Allows an fd to be used to inject an interrupt to the guest.
> + * ioeventfd: Allow an fd to be used to receive a signal from the guest.
> + * All credit goes to kvm developers.
> + */
> +
> +#ifndef __LINUX_MSHV_EVENTFD_H
> +#define __LINUX_MSHV_EVENTFD_H
> +
> +#include <linux/poll.h>
> +
> +#include "mshv.h"
> +#include "mshv_root.h"
> +
> +/* struct to contain list of irqfds sharing an irq. Updates are protected by
> + * partition.irqfds.resampler_lock
> + */
> +struct mshv_irqfd_resampler {
> +	struct mshv_partition	    *rsmplr_partn;
> +	struct hlist_head	     rsmplr_irqfd_list;
> +	struct mshv_irq_ack_notifier rsmplr_notifier;
> +	struct hlist_node	     rsmplr_hnode;
> +};
> +
> +struct mshv_irqfd {
> +	struct mshv_partition		    *irqfd_partn;
> +	struct eventfd_ctx		    *irqfd_eventfd_ctx;
> +	struct mshv_guest_irq_ent	     irqfd_girq_ent;
> +	seqcount_spinlock_t		     irqfd_irqe_sc;
> +	u32				     irqfd_irqnum;
> +	struct mshv_lapic_irq		     irqfd_lapic_irq;
> +	struct hlist_node		     irqfd_hnode;
> +	poll_table			     irqfd_polltbl;
> +	wait_queue_head_t		    *irqfd_wqh;
> +	wait_queue_entry_t		     irqfd_wait;
> +	struct work_struct		     irqfd_shutdown;
> +	struct mshv_irqfd_resampler	    *irqfd_resampler;
> +	struct eventfd_ctx		    *irqfd_resamplefd;
> +	struct hlist_node		     irqfd_resampler_hnode;
> +};
> +
> +void mshv_eventfd_init(struct mshv_partition *partition);
> +void mshv_eventfd_release(struct mshv_partition *partition);
> +
> +void mshv_register_irq_ack_notifier(struct mshv_partition *partition,
> +				    struct mshv_irq_ack_notifier *mian);
> +void mshv_unregister_irq_ack_notifier(struct mshv_partition *partition,
> +				      struct mshv_irq_ack_notifier *mian);
> +bool mshv_notify_acked_gsi(struct mshv_partition *partition, int gsi);
> +
> +int mshv_set_unset_irqfd(struct mshv_partition *partition,
> +			 struct mshv_user_irqfd *args);
> +
> +int mshv_irqfd_wq_init(void);
> +void mshv_irqfd_wq_cleanup(void);
> +
> +struct mshv_ioeventfd {
> +	struct hlist_node    iovntfd_hnode;
> +	u64		     iovntfd_addr;
> +	int		     iovntfd_length;
> +	struct eventfd_ctx  *iovntfd_eventfd;
> +	u64		     iovntfd_datamatch;
> +	int		     iovntfd_doorbell_id;
> +	bool		     iovntfd_wildcard;
> +};
> +
> +int mshv_set_unset_ioeventfd(struct mshv_partition *pt,
> +			     struct mshv_user_ioeventfd *args);
> +
> +#endif /* __LINUX_MSHV_EVENTFD_H */
> diff --git a/drivers/hv/mshv_irq.c b/drivers/hv/mshv_irq.c
> new file mode 100644
> index 000000000000..f956e125afb4
> --- /dev/null
> +++ b/drivers/hv/mshv_irq.c
> @@ -0,0 +1,128 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023, Microsoft Corporation.
> + *
> + * Authors:
> + *   Vineeth Remanan Pillai <viremana at linux.microsoft.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <asm/mshyperv.h>
> +
> +#include "mshv_eventfd.h"
> +#include "mshv.h"
> +#include "mshv_root.h"
> +
> +MODULE_AUTHOR("Microsoft");
> +MODULE_LICENSE("GPL");
> +
> +/* called from the ioctl code, user wants to update the guest irq table */
> +int mshv_update_routing_table(struct mshv_partition *partition,
> +			      const struct mshv_user_irq_entry *ue,
> +			      unsigned int numents)
> +{
> +	struct mshv_girq_routing_table *new = NULL, *old;
> +	u32 i, nr_rt_entries = 0;
> +	int r = 0;
> +
> +	if (numents == 0)
> +		goto swap_routes;
> +
> +	for (i = 0; i < numents; i++) {
> +		if (ue[i].gsi >= MSHV_MAX_GUEST_IRQS)
> +			return -EINVAL;
> +
> +		if (ue[i].address_hi)
> +			return -EINVAL;
> +
> +		nr_rt_entries = max(nr_rt_entries, ue[i].gsi);
> +	}
> +	nr_rt_entries += 1;
> +
> +	new = kzalloc(struct_size(new, mshv_girq_info_tbl, nr_rt_entries),
> +		      GFP_KERNEL_ACCOUNT);
> +	if (!new)
> +		return -ENOMEM;
> +
> +	new->num_rt_entries = nr_rt_entries;
> +	for (i = 0; i < numents; i++) {
> +		struct mshv_guest_irq_ent *girq;
> +
> +		girq = &new->mshv_girq_info_tbl[ue[i].gsi];
> +
> +		/*
> +		 * Allow only one to one mapping between GSI and MSI routing.
> +		 */
> +		if (girq->guest_irq_num != 0) {
> +			r = -EINVAL;
> +			goto out;
> +		}
> +
> +		girq->guest_irq_num = ue[i].gsi;
> +		girq->girq_addr_lo = ue[i].address_lo;
> +		girq->girq_addr_hi = ue[i].address_hi;
> +		girq->girq_irq_data = ue[i].data;
> +		girq->girq_entry_valid = true;
> +	}
> +
> +swap_routes:
> +	mutex_lock(&partition->pt_irq_lock);
> +	old = rcu_dereference_protected(partition->pt_girq_tbl, 1);
> +	rcu_assign_pointer(partition->pt_girq_tbl, new);
> +	mshv_irqfd_routing_update(partition);
> +	mutex_unlock(&partition->pt_irq_lock);
> +
> +	synchronize_srcu_expedited(&partition->pt_irq_srcu);
> +	new = old;
> +
> +out:
> +	kfree(new);
> +
> +	return r;
> +}
> +
> +/* vm is going away, kfree the irq routing table */
> +void mshv_free_routing_table(struct mshv_partition *partition)
> +{
> +	struct mshv_girq_routing_table *rt =
> +				   rcu_access_pointer(partition->pt_girq_tbl);
> +
> +	kfree(rt);
> +}
> +
> +struct mshv_guest_irq_ent
> +mshv_ret_girq_entry(struct mshv_partition *partition, u32 irqnum)
> +{
> +	struct mshv_guest_irq_ent entry = { 0 };
> +	struct mshv_girq_routing_table *girq_tbl;
> +
> +	girq_tbl = srcu_dereference_check(partition->pt_girq_tbl,
> +					  &partition->pt_irq_srcu,
> +					  lockdep_is_held(&partition->pt_irq_lock));
> +	if (!girq_tbl || irqnum >= girq_tbl->num_rt_entries) {
> +		/*
> +		 * Premature register_irqfd, setting valid_entry = 0
> +		 * would ignore this entry anyway
> +		 */
> +		entry.guest_irq_num = irqnum;
> +		return entry;
> +	}
> +
> +	return girq_tbl->mshv_girq_info_tbl[irqnum];
> +}
> +
> +void mshv_copy_girq_info(struct mshv_guest_irq_ent *ent,
> +			 struct mshv_lapic_irq *lirq)
> +{
> +	memset(lirq, 0, sizeof(*lirq));
> +	if (!ent || !ent->girq_entry_valid)
> +		return;
> +
> +	lirq->lapic_vector = ent->girq_irq_data & 0xFF;
> +	lirq->lapic_apic_id = (ent->girq_addr_lo >> 12) & 0xFF;
> +	lirq->lapic_control.interrupt_type = (ent->girq_irq_data & 0x700) >> 8;
> +	lirq->lapic_control.level_triggered = (ent->girq_irq_data >> 15) & 0x1;
> +	lirq->lapic_control.logical_dest_mode = (ent->girq_addr_lo >> 2) & 0x1;
> +}
> diff --git a/drivers/hv/mshv_portid_table.c b/drivers/hv/mshv_portid_table.c
> new file mode 100644
> index 000000000000..a40abde6fd15
> --- /dev/null
> +++ b/drivers/hv/mshv_portid_table.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/types.h>
> +#include <linux/version.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/idr.h>
> +#include <asm/mshyperv.h>
> +
> +#include "mshv.h"
> +#include "mshv_root.h"
> +
> +/*
> + * Ports and connections are hypervisor struct used for inter-partition
> + * communication. Port represents the source and connection represents
> + * the destination. Partitions are responsible for managing the port and
> + * connection ids.
> + *
> + */
> +
> +#define PORTID_MIN	1
> +#define PORTID_MAX	INT_MAX
> +
> +static DEFINE_IDR(port_table_idr);
> +
> +void
> +mshv_port_table_fini(void)
> +{
> +	struct port_table_info *port_info;
> +	unsigned long i, tmp;
> +
> +	idr_lock(&port_table_idr);
> +	if (!idr_is_empty(&port_table_idr)) {
> +		idr_for_each_entry_ul(&port_table_idr, port_info, tmp, i) {
> +			port_info = idr_remove(&port_table_idr, i);
> +			kfree_rcu(port_info, portbl_rcu);
> +		}
> +	}
> +	idr_unlock(&port_table_idr);
> +}
> +
> +int
> +mshv_portid_alloc(struct port_table_info *info)
> +{
> +	int ret = 0;
> +
> +	idr_lock(&port_table_idr);
> +	ret = idr_alloc(&port_table_idr, info, PORTID_MIN,
> +			PORTID_MAX, GFP_KERNEL);
> +	idr_unlock(&port_table_idr);
> +
> +	return ret;
> +}
> +
> +void
> +mshv_portid_free(int port_id)
> +{
> +	struct port_table_info *info;
> +
> +	idr_lock(&port_table_idr);
> +	info = idr_remove(&port_table_idr, port_id);
> +	WARN_ON(!info);
> +	idr_unlock(&port_table_idr);
> +
> +	synchronize_rcu();
> +	kfree(info);
> +}
> +
> +int
> +mshv_portid_lookup(int port_id, struct port_table_info *info)
> +{
> +	struct port_table_info *_info;
> +	int ret = -ENOENT;
> +
> +	rcu_read_lock();
> +	_info = idr_find(&port_table_idr, port_id);
> +	rcu_read_unlock();
> +
> +	if (_info) {
> +		*info = *_info;
> +		ret = 0;
> +	}
> +
> +	return ret;
> +}
> diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h
> new file mode 100644
> index 000000000000..f8d85db14db1
> --- /dev/null
> +++ b/drivers/hv/mshv_root.h
> @@ -0,0 +1,321 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, Microsoft Corporation.
> + */
> +
> +#ifndef _MSHV_ROOT_H_
> +#define _MSHV_ROOT_H_
> +
> +#include <linux/spinlock.h>
> +#include <linux/mutex.h>
> +#include <linux/semaphore.h>
> +#include <linux/sched.h>
> +#include <linux/srcu.h>
> +#include <linux/wait.h>
> +#include <linux/hashtable.h>
> +#include <linux/dev_printk.h>
> +#include <uapi/linux/mshv.h>
> +
> +/*
> + * Hypervisor must be between these version numbers (inclusive)
> + * to guarantee compatibility
> + */
> +#define MSHV_HV_MIN_VERSION		(27744)
> +#define MSHV_HV_MAX_VERSION		(27751)
> +
> +#define MSHV_MAX_VPS			256
> +
> +#define MSHV_PARTITIONS_HASH_BITS	9
> +
> +#define MSHV_PIN_PAGES_BATCH_SIZE	(0x10000000ULL / HV_HYP_PAGE_SIZE)
> +
> +struct mshv_vp {
> +	u32 vp_index;
> +	struct mshv_partition *vp_partition;
> +	struct mutex vp_mutex;
> +	struct hv_vp_register_page *vp_register_page;
> +	struct hv_message *vp_intercept_msg_page;
> +	void *vp_ghcb_page;
> +	struct hv_stats_page *vp_stats_pages[2];
> +	struct {
> +		atomic64_t vp_signaled_count;
> +		struct {
> +			u64 intercept_suspend: 1;
> +			u64 root_sched_blocked: 1; /* root scheduler only */
> +			u64 root_sched_dispatched: 1; /* root scheduler only */
> +			u64 reserved: 62;

Hmmm.  This looks like 65 bits allocated in a u64.

> +		} flags;
> +		unsigned int kicked_by_hv;
> +		wait_queue_head_t vp_suspend_queue;
> +	} run;
> +};
> +
> +#define vp_fmt(fmt) "p%lluvp%u: " fmt
> +#define vp_dev(v) ((v)->vp_partition->pt_module_dev)
> +#define vp_emerg(v, fmt, ...) \
> +	dev_emerg(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		  (v)->vp_index, ##__VA_ARGS__)
> +#define vp_crit(v, fmt, ...) \
> +	dev_crit(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		 (v)->vp_index, ##__VA_ARGS__)
> +#define vp_alert(v, fmt, ...) \
> +	dev_alert(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		  (v)->vp_index, ##__VA_ARGS__)
> +#define vp_err(v, fmt, ...) \
> +	dev_err(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		(v)->vp_index, ##__VA_ARGS__)
> +#define vp_warn(v, fmt, ...) \
> +	dev_warn(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		 (v)->vp_index, ##__VA_ARGS__)
> +#define vp_notice(v, fmt, ...) \
> +	dev_notice(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		   (v)->vp_index, ##__VA_ARGS__)
> +#define vp_info(v, fmt, ...) \
> +	dev_info(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		 (v)->vp_index, ##__VA_ARGS__)
> +#define vp_dbg(v, fmt, ...) \
> +	dev_dbg(vp_dev(v), vp_fmt(fmt), (v)->vp_partition->pt_id, \
> +		(v)->vp_index, ##__VA_ARGS__)
> +
> +struct mshv_mem_region {
> +	struct hlist_node hnode;
> +	u64 nr_pages;
> +	u64 start_gfn;
> +	u64 start_uaddr;
> +	u32 hv_map_flags;
> +	struct {
> +		u64 large_pages:  1; /* 2MiB */
> +		u64 range_pinned: 1;
> +		u64 reserved:	 62;
> +	} flags;
> +	struct mshv_partition *partition;
> +	struct page *pages[];
> +};
> +
> +struct mshv_irq_ack_notifier {
> +	struct hlist_node link;
> +	unsigned int irq_ack_gsi;
> +	void (*irq_acked)(struct mshv_irq_ack_notifier *mian);
> +};
> +
> +struct mshv_partition {
> +	struct device *pt_module_dev;
> +
> +	struct hlist_node pt_hnode;
> +	u64 pt_id;
> +	refcount_t pt_ref_count;
> +	struct mutex pt_mutex;
> +	struct hlist_head pt_mem_regions; // not ordered
> +
> +	u32 pt_vp_count;
> +	struct mshv_vp *pt_vp_array[MSHV_MAX_VPS];
> +
> +	struct mutex pt_irq_lock;
> +	struct srcu_struct pt_irq_srcu;
> +	struct hlist_head irq_ack_notifier_list;
> +
> +	struct hlist_head pt_devices;
> +
> +	/*
> +	 * Since MSHV does not support more than one async hypercall in flight

Wording is a bit messed up.  Drop the "Since"?

> +	 * for a single partition. Thus, it is okay to define per partition
> +	 * async hypercall status.
> +	 */
> +	struct completion async_hypercall;
> +	u64 async_hypercall_status;
> +
> +	spinlock_t	  pt_irqfds_lock;
> +	struct hlist_head pt_irqfds_list;
> +	struct mutex	  irqfds_resampler_lock;
> +	struct hlist_head irqfds_resampler_list;
> +
> +	struct hlist_head ioeventfds_list;
> +
> +	struct mshv_girq_routing_table __rcu *pt_girq_tbl;
> +	u64 isolation_type;
> +	bool import_completed;
> +	bool pt_initialized;
> +};
> +
> +#define pt_fmt(fmt) "p%llu: " fmt
> +#define pt_dev(p) ((p)->pt_module_dev)
> +#define pt_emerg(p, fmt, ...) \
> +	dev_emerg(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_crit(p, fmt, ...) \
> +	dev_crit(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_alert(p, fmt, ...) \
> +	dev_alert(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_err(p, fmt, ...) \
> +	dev_err(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_warn(p, fmt, ...) \
> +	dev_warn(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_notice(p, fmt, ...) \
> +	dev_notice(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_info(p, fmt, ...) \
> +	dev_info(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +#define pt_dbg(p, fmt, ...) \
> +	dev_dbg(pt_dev(p), pt_fmt(fmt), (p)->pt_id, ##__VA_ARGS__)
> +
> +struct mshv_lapic_irq {
> +	u32 lapic_vector;
> +	u64 lapic_apic_id;
> +	union hv_interrupt_control lapic_control;
> +};
> +
> +#define MSHV_MAX_GUEST_IRQS		4096
> +
> +/* representation of one guest irq entry, either msi or legacy */
> +struct mshv_guest_irq_ent {
> +	u32 girq_entry_valid;	/* vfio looks at this */
> +	u32 guest_irq_num;	/* a unique number for each irq */
> +	u32 girq_addr_lo;	/* guest irq msi address info */
> +	u32 girq_addr_hi;
> +	u32 girq_irq_data;	/* idt vector in some cases */
> +};
> +
> +struct mshv_girq_routing_table {
> +	u32 num_rt_entries;
> +	struct mshv_guest_irq_ent mshv_girq_info_tbl[];
> +};
> +
> +struct hv_synic_pages {
> +	struct hv_message_page *synic_message_page;
> +	struct hv_synic_event_flags_page *synic_event_flags_page;
> +	struct hv_synic_event_ring_page *synic_event_ring_page;
> +};
> +
> +struct mshv_root {
> +	struct hv_synic_pages __percpu *synic_pages;
> +	spinlock_t pt_ht_lock;
> +	DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS);
> +};
> +
> +/*
> + * Callback for doorbell events.
> + * NOTE: This is called in interrupt context. Callback
> + * should defer slow and sleeping logic to later.
> + */
> +typedef void (*doorbell_cb_t) (int doorbell_id, void *);
> +
> +/*
> + * port table information
> + */
> +struct port_table_info {
> +	struct rcu_head portbl_rcu;
> +	enum hv_port_type hv_port_type;
> +	union {
> +		struct {
> +			u64 reserved[2];
> +		} hv_port_message;
> +		struct {
> +			u64 reserved[2];
> +		} hv_port_event;
> +		struct {
> +			u64 reserved[2];
> +		} hv_port_monitor;
> +		struct {
> +			doorbell_cb_t doorbell_cb;
> +			void *data;
> +		} hv_port_doorbell;
> +	};
> +};
> +
> +int mshv_update_routing_table(struct mshv_partition *partition,
> +			      const struct mshv_user_irq_entry *entries,
> +			      unsigned int numents);
> +void mshv_free_routing_table(struct mshv_partition *partition);
> +
> +struct mshv_guest_irq_ent mshv_ret_girq_entry(struct mshv_partition *partition,
> +					      u32 irq_num);
> +
> +void mshv_copy_girq_info(struct mshv_guest_irq_ent *src_irq,
> +			 struct mshv_lapic_irq *dest_irq);
> +
> +void mshv_irqfd_routing_update(struct mshv_partition *partition);
> +
> +void mshv_port_table_fini(void);
> +int mshv_portid_alloc(struct port_table_info *info);
> +int mshv_portid_lookup(int port_id, struct port_table_info *info);
> +void mshv_portid_free(int port_id);
> +
> +int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb,
> +			   void *data, u64 gpa, u64 val, u64 flags);
> +void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid);
> +
> +void mshv_isr(void);
> +int mshv_synic_init(unsigned int cpu);
> +int mshv_synic_cleanup(unsigned int cpu);
> +
> +static inline bool mshv_partition_encrypted(struct mshv_partition *partition)
> +{
> +	return partition->isolation_type == HV_PARTITION_ISOLATION_TYPE_SNP;
> +}
> +
> +struct mshv_partition *mshv_partition_get(struct mshv_partition *partition);
> +void mshv_partition_put(struct mshv_partition *partition);
> +struct mshv_partition *mshv_partition_find(u64 partition_id) __must_hold(RCU);
> +
> +/* hypercalls */
> +
> +int hv_call_withdraw_memory(u64 count, int node, u64 partition_id);
> +int hv_call_create_partition(u64 flags,
> +			     struct hv_partition_creation_properties creation_properties,
> +			     union hv_partition_isolation_properties isolation_properties,
> +			     u64 *partition_id);
> +int hv_call_initialize_partition(u64 partition_id);
> +int hv_call_finalize_partition(u64 partition_id);
> +int hv_call_delete_partition(u64 partition_id);
> +int hv_call_map_mmio_pages(u64 partition_id, u64 gfn, u64 mmio_spa, u64 numpgs);
> +int hv_call_map_gpa_pages(u64 partition_id, u64 gpa_target, u64 page_count,
> +			  u32 flags, struct page **pages);
> +int hv_call_unmap_gpa_pages(u64 partition_id, u64 gpa_target, u64 page_count,
> +			    u32 flags);
> +int hv_call_delete_vp(u64 partition_id, u32 vp_index);
> +int hv_call_assert_virtual_interrupt(u64 partition_id, u32 vector,
> +				     u64 dest_addr,
> +				     union hv_interrupt_control control);
> +int hv_call_clear_virtual_interrupt(u64 partition_id);
> +int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
> +				  union hv_gpa_page_access_state_flags state_flags,
> +				  int *written_total,
> +				  union hv_gpa_page_access_state *states);
> +int hv_call_get_vp_state(u32 vp_index, u64 partition_id,
> +			 struct hv_vp_state_data state_data,
> +			 /* Choose between pages and ret_output */
> +			 u64 page_count, struct page **pages,
> +			 union hv_output_get_vp_state *ret_output);
> +int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
> +			 /* Choose between pages and bytes */
> +			 struct hv_vp_state_data state_data, u64 page_count,
> +			 struct page **pages, u32 num_bytes, u8 *bytes);
> +int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> +			      union hv_input_vtl input_vtl,
> +			      struct page **state_page);
> +int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> +				union hv_input_vtl input_vtl);
> +int hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,
> +			u64 connection_partition_id, struct hv_port_info *port_info,
> +			u8 port_vtl, u8 min_connection_vtl, int node);
> +int hv_call_delete_port(u64 port_partition_id, union hv_port_id port_id);
> +int hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id,
> +			 u64 connection_partition_id,
> +			 union hv_connection_id connection_id,
> +			 struct hv_connection_info *connection_info,
> +			 u8 connection_vtl, int node);
> +int hv_call_disconnect_port(u64 connection_partition_id,
> +			    union hv_connection_id connection_id);
> +int hv_call_notify_port_ring_empty(u32 sint_index);
> +int hv_call_map_stat_page(enum hv_stats_object_type type,
> +			  const union hv_stats_object_identity *identity,
> +			  void **addr);
> +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> +			    const union hv_stats_object_identity *identity);
> +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> +				   u64 page_struct_count, u32 host_access,
> +				   u32 flags, u8 acquire);
> +
> +extern struct mshv_root mshv_root;
> +extern enum hv_scheduler_type hv_scheduler_type;
> +extern u8 __percpu **hv_synic_eventring_tail;

Per comments on an earlier patch, the __percpu is in the wrong place.

> +
> +#endif /* _MSHV_ROOT_H_ */
> diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
> new file mode 100644
> index 000000000000..b3e5c652015d
> --- /dev/null
> +++ b/drivers/hv/mshv_root_hv_call.c
> @@ -0,0 +1,876 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023, Microsoft Corporation.
> + *
> + * Hypercall helper functions used by the mshv_root module.
> + *
> + * Authors:
> + *   Nuno Das Neves <nunodasneves at linux.microsoft.com>
> + *   Wei Liu <wei.liu at kernel.org>
> + *   Jinank Jain <jinankjain at microsoft.com>
> + *   Vineeth Remanan Pillai <viremana at linux.microsoft.com>
> + *   Asher Kariv <askariv at microsoft.com>
> + *   Muminul Islam <Muminul.Islam at microsoft.com>
> + *   Anatol Belski <anbelski at linux.microsoft.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <asm/mshyperv.h>
> +
> +#include "mshv_root.h"
> +
> +/* Determined empirically */
> +#define HV_INIT_PARTITION_DEPOSIT_PAGES 208
> +#define HV_MAP_GPA_DEPOSIT_PAGES	256
> +
> +#define HV_PAGE_COUNT_2M_ALIGNED(pg_count) (!((pg_count) & (0x200 - 1)))
> +
> +#define HV_WITHDRAW_BATCH_SIZE	(HV_HYP_PAGE_SIZE / sizeof(u64))
> +#define HV_MAP_GPA_BATCH_SIZE	\
> +	((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_map_gpa_pages)) \
> +		/ sizeof(u64))
> +#define HV_GET_VP_STATE_BATCH_SIZE	\
> +	((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_get_vp_state)) \
> +		/ sizeof(u64))
> +#define HV_SET_VP_STATE_BATCH_SIZE	\
> +	((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_set_vp_state)) \
> +		/ sizeof(u64))
> +#define HV_GET_GPA_ACCESS_STATES_BATCH_SIZE	\
> +	((HV_HYP_PAGE_SIZE - sizeof(union hv_gpa_page_access_state)) \
> +		/ sizeof(union hv_gpa_page_access_state))
> +#define HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT
> 	       \
> +	((HV_HYP_PAGE_SIZE -						       \
> +	  sizeof(struct hv_input_modify_sparse_spa_page_host_access)) /        \
> +	 sizeof(u64))
> +
> +int hv_call_withdraw_memory(u64 count, int node, u64 partition_id)
> +{
> +	struct hv_input_withdraw_memory *input_page;
> +	struct hv_output_withdraw_memory *output_page;
> +	struct page *page;
> +	u16 completed;
> +	unsigned long remaining = count;
> +	u64 status;
> +	int i;
> +	unsigned long flags;
> +
> +	page = alloc_page(GFP_KERNEL);
> +	if (!page)
> +		return -ENOMEM;
> +	output_page = page_address(page);
> +
> +	while (remaining) {
> +		local_irq_save(flags);
> +
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +		memset(input_page, 0, sizeof(*input_page));
> +		input_page->partition_id = partition_id;
> +		status = hv_do_rep_hypercall(HVCALL_WITHDRAW_MEMORY,
> +					     min(remaining, HV_WITHDRAW_BATCH_SIZE),
> +					     0, input_page, output_page);
> +
> +		local_irq_restore(flags);
> +
> +		completed = hv_repcomp(status);
> +
> +		for (i = 0; i < completed; i++)
> +			__free_page(pfn_to_page(output_page->gpa_page_list[i]));
> +
> +		if (!hv_result_success(status)) {
> +			if (hv_result(status) == HV_STATUS_NO_RESOURCES)
> +				status = HV_STATUS_SUCCESS;
> +			break;
> +		}
> +
> +		remaining -= completed;
> +	}
> +	free_page((unsigned long)output_page);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_create_partition(u64 flags,
> +			     struct hv_partition_creation_properties creation_properties,
> +			     union hv_partition_isolation_properties isolation_properties,
> +			     u64 *partition_id)
> +{
> +	struct hv_input_create_partition *input;
> +	struct hv_output_create_partition *output;
> +	u64 status;
> +	int ret;
> +	unsigned long irq_flags;
> +
> +	do {
> +		local_irq_save(irq_flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +		memset(input, 0, sizeof(*input));
> +		input->flags = flags;
> +		input->compatibility_version = HV_COMPATIBILITY_21_H2;
> +
> +		memcpy(&input->partition_creation_properties, &creation_properties,
> +		       sizeof(creation_properties));

This is an example of a generic question/concern that occurs in several places. By
doing a memcpy into the hypercall input, the assumption is that the creation
properties supplied by the caller have zeros in all the reserved or unused fields.
Is that a valid assumption?

> +
> +		memcpy(&input->isolation_properties, &isolation_properties,
> +		       sizeof(isolation_properties));
> +
> +		status = hv_do_hypercall(HVCALL_CREATE_PARTITION,
> +					 input, output);
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			if (hv_result_success(status))
> +				*partition_id = output->partition_id;
> +			local_irq_restore(irq_flags);
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		local_irq_restore(irq_flags);
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    hv_current_partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int hv_call_initialize_partition(u64 partition_id)
> +{
> +	struct hv_input_initialize_partition input;
> +	u64 status;
> +	int ret;
> +
> +	input.partition_id = partition_id;
> +
> +	ret = hv_call_deposit_pages(NUMA_NO_NODE, partition_id,
> +				    HV_INIT_PARTITION_DEPOSIT_PAGES);
> +	if (ret)
> +		return ret;
> +
> +	do {
> +		status = hv_do_fast_hypercall8(HVCALL_INITIALIZE_PARTITION,
> +					       *(u64 *)&input);
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE, partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int hv_call_finalize_partition(u64 partition_id)
> +{
> +	struct hv_input_finalize_partition input;
> +	u64 status;
> +
> +	input.partition_id = partition_id;
> +	status = hv_do_fast_hypercall8(HVCALL_FINALIZE_PARTITION,
> +				       *(u64 *)&input);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_delete_partition(u64 partition_id)
> +{
> +	struct hv_input_delete_partition input;
> +	u64 status;
> +
> +	input.partition_id = partition_id;
> +	status = hv_do_fast_hypercall8(HVCALL_DELETE_PARTITION, *(u64 *)&input);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +/* Ask the hypervisor to map guest ram pages or the guest mmio space */
> +static int hv_do_map_gpa_hcall(u64 partition_id, u64 gfn, u64 page_struct_count,
> +			       u32 flags, struct page **pages, u64 mmio_spa)
> +{
> +	struct hv_input_map_gpa_pages *input_page;
> +	u64 status, *pfnlist;
> +	unsigned long irq_flags, large_shift = 0;
> +	int ret = 0, done = 0;
> +	u64 page_count = page_struct_count;
> +
> +	if (page_count == 0 || (pages && mmio_spa))
> +		return -EINVAL;
> +
> +	if (flags & HV_MAP_GPA_LARGE_PAGE) {
> +		if (mmio_spa)
> +			return -EINVAL;
> +
> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> +			return -EINVAL;
> +
> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> +		page_count >>= large_shift;
> +	}
> +
> +	while (done < page_count) {
> +		ulong i, completed, remain = page_count - done;
> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
> +
> +		local_irq_save(irq_flags);
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +		input_page->target_partition_id = partition_id;
> +		input_page->target_gpa_base = gfn + (done << large_shift);
> +		input_page->map_flags = flags;
> +		pfnlist = input_page->source_gpa_page_list;
> +
> +		for (i = 0; i < rep_count; i++)
> +			if (flags & HV_MAP_GPA_NO_ACCESS) {
> +				pfnlist[i] = 0;
> +			} else if (pages) {
> +				u64 index = (done + i) << large_shift;
> +
> +				if (index >= page_struct_count) {

Can this test ever be true?  It looks like the pages array must
have space for each 4K page even if mapping in 2Meg granularity.
But only every 512th entry in the pages array is looked at
(which seems a little weird). But based on how rep_count is set up,
I don't see how the algorithm could go past the end of the pages
array.

> +					ret = -EINVAL;
> +					break;
> +				}
> +				pfnlist[i] = page_to_pfn(pages[index]);
> +			} else {
> +				pfnlist[i] = mmio_spa + done + i;
> +			}
> +		if (ret)
> +			break;

This test could also go away if the ret = -EINVAL error above can't
happen.

> +
> +		status = hv_do_rep_hypercall(HVCALL_MAP_GPA_PAGES, rep_count, 0,
> +					     input_page, NULL);
> +		local_irq_restore(irq_flags);
> +
> +		completed = hv_repcomp(status);
> +
> +		if (hv_result(status) == HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_call_deposit_pages(NUMA_NO_NODE, partition_id,
> +						    HV_MAP_GPA_DEPOSIT_PAGES);
> +			if (ret)
> +				break;
> +
> +		} else if (!hv_result_success(status)) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +
> +		done += completed;
> +	}
> +
> +	if (ret && done) {
> +		u32 unmap_flags = 0;
> +
> +		if (flags & HV_MAP_GPA_LARGE_PAGE)
> +			unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
> +		hv_call_unmap_gpa_pages(partition_id, gfn, done, unmap_flags);
> +	}
> +
> +	return ret;
> +}
> +
> +/* Ask the hypervisor to map guest ram pages */
> +int hv_call_map_gpa_pages(u64 partition_id, u64 gpa_target, u64 page_count,
> +			  u32 flags, struct page **pages)
> +{
> +	return hv_do_map_gpa_hcall(partition_id, gpa_target, page_count,
> +				   flags, pages, 0);
> +}
> +
> +/* Ask the hypervisor to map guest mmio space */
> +int hv_call_map_mmio_pages(u64 partition_id, u64 gfn, u64 mmio_spa, u64 numpgs)
> +{
> +	int i;
> +	u32 flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE |
> +		    HV_MAP_GPA_NOT_CACHED;
> +
> +	for (i = 0; i < numpgs; i++)
> +		if (page_is_ram(mmio_spa + i))

FWIW, doing this check one-page-at-a-time is somewhat expensive if numpgs
is large.  The underlying data structures should support doing a single range
check, but I haven't looked at whether functions exist to do such a range check.

> +			return -EINVAL;
> +
> +	return hv_do_map_gpa_hcall(partition_id, gfn, numpgs, flags, NULL,
> +				   mmio_spa);
> +}
> +
> +int hv_call_unmap_gpa_pages(u64 partition_id, u64 gfn, u64 page_count_4k,
> +			    u32 flags)
> +{
> +	struct hv_input_unmap_gpa_pages *input_page;
> +	u64 status, page_count = page_count_4k;
> +	unsigned long irq_flags, large_shift = 0;
> +	int ret = 0, done = 0;
> +
> +	if (page_count == 0)
> +		return -EINVAL;
> +
> +	if (flags & HV_UNMAP_GPA_LARGE_PAGE) {
> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> +			return -EINVAL;
> +
> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> +		page_count >>= large_shift;
> +	}
> +
> +	while (done < page_count) {
> +		ulong completed, remain = page_count - done;
> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);

Using HV_MAP_GPA_BATCH_SIZE seems a little weird here since there's
no input array and hence no constraint based on keeping input args to
just one page. Is it being used as an arbitrary limit so the rep_count
passed to the hypercall isn't "too large" for some definition of "too large"?
If that's the case, perhaps a separate #define and a comment would
make sense. I kept trying to figure out how the batch size for unmap was
related to the map hypercall, and I don't think there is any relationship.

> +
> +		local_irq_save(irq_flags);
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +		input_page->target_partition_id = partition_id;
> +		input_page->target_gpa_base = gfn + (done << large_shift);
> +		input_page->unmap_flags = flags;
> +		status = hv_do_rep_hypercall(HVCALL_UNMAP_GPA_PAGES, rep_count,
> +					     0, input_page, NULL);
> +		local_irq_restore(irq_flags);
> +
> +		completed = hv_repcomp(status);
> +		if (!hv_result_success(status)) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +
> +		done += completed;
> +	}
> +
> +	return ret;
> +}
> +
> +int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
> +				  union hv_gpa_page_access_state_flags state_flags,
> +				  int *written_total,
> +				  union hv_gpa_page_access_state *states)
> +{
> +	struct hv_input_get_gpa_pages_access_state *input_page;
> +	union hv_gpa_page_access_state *output_page;
> +	int completed = 0;
> +	unsigned long remaining = count;
> +	int rep_count, i;
> +	u64 status;
> +	unsigned long flags;
> +
> +	*written_total = 0;
> +	while (remaining) {
> +		local_irq_save(flags);
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +		input_page->partition_id = partition_id;
> +		input_page->hv_gpa_page_number = gpa_base_pfn + *written_total;
> +		input_page->flags = state_flags;
> +		rep_count = min(remaining, HV_GET_GPA_ACCESS_STATES_BATCH_SIZE);
> +
> +		status = hv_do_rep_hypercall(HVCALL_GET_GPA_PAGES_ACCESS_STATES, rep_count,
> +					     0, input_page, output_page);
> +		if (!hv_result_success(status)) {
> +			local_irq_restore(flags);
> +			break;
> +		}
> +		completed = hv_repcomp(status);
> +		for (i = 0; i < completed; ++i)
> +			states[i].as_uint8 = output_page[i].as_uint8;
> +
> +		states += completed;
> +		*written_total += completed;
> +		remaining -= completed;
> +		local_irq_restore(flags);

FWIW, this local_irq_restore() could move up three lines to before the progress
accounting is done.

> +	}
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_assert_virtual_interrupt(u64 partition_id, u32 vector,
> +				     u64 dest_addr,
> +				     union hv_interrupt_control control)
> +{
> +	struct hv_input_assert_virtual_interrupt *input;
> +	unsigned long flags;
> +	u64 status;
> +
> +	local_irq_save(flags);
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +	memset(input, 0, sizeof(*input));
> +	input->partition_id = partition_id;
> +	input->vector = vector;
> +	input->dest_addr = dest_addr;
> +	input->control = control;
> +	status = hv_do_hypercall(HVCALL_ASSERT_VIRTUAL_INTERRUPT, input, NULL);
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_delete_vp(u64 partition_id, u32 vp_index)
> +{
> +	union hv_input_delete_vp input = {};
> +	u64 status;
> +
> +	input.partition_id = partition_id;
> +	input.vp_index = vp_index;
> +
> +	status = hv_do_fast_hypercall16(HVCALL_DELETE_VP,
> +					input.as_uint64[0], input.as_uint64[1]);
> +
> +	return hv_result_to_errno(status);
> +}
> +EXPORT_SYMBOL_GPL(hv_call_delete_vp);
> +
> +int hv_call_get_vp_state(u32 vp_index, u64 partition_id,
> +			 struct hv_vp_state_data state_data,
> +			 /* Choose between pages and ret_output */
> +			 u64 page_count, struct page **pages,
> +			 union hv_output_get_vp_state *ret_output)
> +{
> +	struct hv_input_get_vp_state *input;
> +	union hv_output_get_vp_state *output;
> +	u64 status;
> +	int i;
> +	u64 control;
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	if (page_count > HV_GET_VP_STATE_BATCH_SIZE)
> +		return -EINVAL;
> +
> +	if (!page_count && !ret_output)
> +		return -EINVAL;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +		memset(input, 0, sizeof(*input));
> +		memset(output, 0, sizeof(*output));

Why is the output set to zero?  I would think Hyper-V is responsible for
ensuring that the output is properly populated, with unused fields/areas
set to zero.

> +
> +		input->partition_id = partition_id;
> +		input->vp_index = vp_index;
> +		input->state_data = state_data;
> +		for (i = 0; i < page_count; i++)
> +			input->output_data_pfns[i] = page_to_pfn(pages[i]);
> +
> +		control = (HVCALL_GET_VP_STATE) |
> +			  (page_count << HV_HYPERCALL_VARHEAD_OFFSET);
> +
> +		status = hv_do_hypercall(control, input, output);
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			if (hv_result_success(status) && ret_output)
> +				memcpy(ret_output, output, sizeof(*output));
> +
> +			local_irq_restore(flags);
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		local_irq_restore(flags);
> +
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
> +			 /* Choose between pages and bytes */
> +			 struct hv_vp_state_data state_data, u64 page_count,

The size of "struct hv_vp_state_data" looks to be 24 bytes (3 64-bit words).
Is there a reason to pass this by value instead of as a pointer? I guess it works
like this, but it seems atypical.

> +			 struct page **pages, u32 num_bytes, u8 *bytes)
> +{
> +	struct hv_input_set_vp_state *input;
> +	u64 status;
> +	int i;
> +	u64 control;
> +	unsigned long flags;
> +	int ret = 0;
> +	u16 varhead_sz;
> +
> +	if (page_count > HV_SET_VP_STATE_BATCH_SIZE)
> +		return -EINVAL;
> +	if (sizeof(*input) + num_bytes > HV_HYP_PAGE_SIZE)
> +		return -EINVAL;
> +
> +	if (num_bytes)
> +		/* round up to 8 and divide by 8 */
> +		varhead_sz = (num_bytes + 7) >> 3;
> +	else if (page_count)
> +		varhead_sz = page_count;
> +	else
> +		return -EINVAL;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		memset(input, 0, sizeof(*input));
> +
> +		input->partition_id = partition_id;
> +		input->vp_index = vp_index;
> +		input->state_data = state_data;
> +		if (num_bytes) {
> +			memcpy((u8 *)input->data, bytes, num_bytes);
> +		} else {
> +			for (i = 0; i < page_count; i++)
> +				input->data[i].pfns = page_to_pfn(pages[i]);
> +		}
> +
> +		control = (HVCALL_SET_VP_STATE) |
> +			  (varhead_sz << HV_HYPERCALL_VARHEAD_OFFSET);
> +
> +		status = hv_do_hypercall(control, input, NULL);
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			local_irq_restore(flags);
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		local_irq_restore(flags);
> +
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> +			      union hv_input_vtl input_vtl,
> +			      struct page **state_page)
> +{
> +	struct hv_input_map_vp_state_page *input;
> +	struct hv_output_map_vp_state_page *output;
> +	u64 status;
> +	int ret;
> +	unsigned long flags;
> +
> +	do {
> +		local_irq_save(flags);
> +
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +		input->partition_id = partition_id;
> +		input->vp_index = vp_index;
> +		input->type = type;
> +		input->input_vtl = input_vtl;
> +
> +		status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input, output);
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			if (hv_result_success(status))
> +				*state_page = pfn_to_page(output->map_location);
> +			local_irq_restore(flags);
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +
> +		local_irq_restore(flags);
> +
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE, partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> +				union hv_input_vtl input_vtl)
> +{
> +	unsigned long flags;
> +	u64 status;
> +	struct hv_input_unmap_vp_state_page *input;
> +
> +	local_irq_save(flags);
> +
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +	memset(input, 0, sizeof(*input));
> +
> +	input->partition_id = partition_id;
> +	input->vp_index = vp_index;
> +	input->type = type;
> +	input->input_vtl = input_vtl;
> +
> +	status = hv_do_hypercall(HVCALL_UNMAP_VP_STATE_PAGE, input, NULL);
> +
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_clear_virtual_interrupt(u64 partition_id)
> +{
> +	unsigned long flags;
> +	int status;
> +
> +	local_irq_save(flags);
> +	status = hv_do_fast_hypercall8(HVCALL_CLEAR_VIRTUAL_INTERRUPT,
> +				       partition_id) &
> +			HV_HYPERCALL_RESULT_MASK;

This "anding" with HV_HYPERCALL_RESULT_MASK should be removed.

> +	local_irq_restore(flags);

The irq save/restore isn't needed here since this is a fast hypercall and
per-cpu arg memory is not used.

> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,
> +		    u64 connection_partition_id,
> +		    struct hv_port_info *port_info,
> +		    u8 port_vtl, u8 min_connection_vtl, int node)
> +{
> +	struct hv_input_create_port *input;
> +	unsigned long flags;
> +	int ret = 0;
> +	int status;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		memset(input, 0, sizeof(*input));
> +
> +		input->port_partition_id = port_partition_id;
> +		input->port_id = port_id;
> +		input->connection_partition_id = connection_partition_id;
> +		input->port_info = *port_info;
> +		input->port_vtl = port_vtl;
> +		input->min_connection_vtl = min_connection_vtl;
> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> +		status = hv_do_hypercall(HVCALL_CREATE_PORT, input, NULL) &
> +			 HV_HYPERCALL_RESULT_MASK;

Use the hv_status checking macros instead of and'ing with
HV_HYPERCALL_RESULT_MASK.

> +		local_irq_restore(flags);
> +		if (status == HV_STATUS_SUCCESS)
> +			break;
> +
> +		if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE, port_partition_id, 1);
> +
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int
> +hv_call_delete_port(u64 port_partition_id, union hv_port_id port_id)
> +{
> +	union hv_input_delete_port input = { 0 };
> +	unsigned long flags;
> +	int status;
> +
> +	local_irq_save(flags);
> +	input.port_partition_id = port_partition_id;
> +	input.port_id = port_id;
> +	status = hv_do_fast_hypercall16(HVCALL_DELETE_PORT,
> +					input.as_uint64[0],
> +					input.as_uint64[1]) &
> +			HV_HYPERCALL_RESULT_MASK;
> +	local_irq_restore(flags);

Same a previous comment about and'ing.  And irq save/restore
isn't needed.

> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id,
> +		     u64 connection_partition_id,
> +		     union hv_connection_id connection_id,
> +		     struct hv_connection_info *connection_info,
> +		     u8 connection_vtl, int node)
> +{
> +	struct hv_input_connect_port *input;
> +	unsigned long flags;
> +	int ret = 0, status;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		memset(input, 0, sizeof(*input));
> +		input->port_partition_id = port_partition_id;
> +		input->port_id = port_id;
> +		input->connection_partition_id = connection_partition_id;
> +		input->connection_id = connection_id;
> +		input->connection_info = *connection_info;
> +		input->connection_vtl = connection_vtl;
> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> +		status = hv_do_hypercall(HVCALL_CONNECT_PORT, input, NULL) &
> +			 HV_HYPERCALL_RESULT_MASK;

Same here.  Use hv_* macros.

> +
> +		local_irq_restore(flags);
> +		if (status == HV_STATUS_SUCCESS)
> +			break;
> +
> +		if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    connection_partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int
> +hv_call_disconnect_port(u64 connection_partition_id,
> +			union hv_connection_id connection_id)
> +{
> +	union hv_input_disconnect_port input = { 0 };
> +	unsigned long flags;
> +	int status;
> +
> +	local_irq_save(flags);
> +	input.connection_partition_id = connection_partition_id;
> +	input.connection_id = connection_id;
> +	input.is_doorbell = 1;
> +	status = hv_do_fast_hypercall16(HVCALL_DISCONNECT_PORT,
> +					input.as_uint64[0],
> +					input.as_uint64[1]) &
> +			HV_HYPERCALL_RESULT_MASK;
> +	local_irq_restore(flags);

Same as above.

> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_notify_port_ring_empty(u32 sint_index)
> +{
> +	union hv_input_notify_port_ring_empty input = { 0 };
> +	unsigned long flags;
> +	int status;
> +
> +	local_irq_save(flags);
> +	input.sint_index = sint_index;
> +	status = hv_do_fast_hypercall8(HVCALL_NOTIFY_PORT_RING_EMPTY,
> +				       input.as_uint64) &
> +		 HV_HYPERCALL_RESULT_MASK;
> +	local_irq_restore(flags);

Same as above.

> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_map_stat_page(enum hv_stats_object_type type,
> +			  const union hv_stats_object_identity *identity,
> +			  void **addr)
> +{
> +	unsigned long flags;
> +	struct hv_input_map_stats_page *input;
> +	struct hv_output_map_stats_page *output;
> +	u64 status, pfn;
> +	int ret;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +		memset(input, 0, sizeof(*input));
> +		input->type = type;
> +		input->identity = *identity;
> +
> +		status = hv_do_hypercall(HVCALL_MAP_STATS_PAGE, input, output);
> +		pfn = output->map_location;
> +
> +		local_irq_restore(flags);
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			if (hv_result_success(status))
> +				break;
> +			return hv_result_to_errno(status);
> +		}
> +
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    hv_current_partition_id, 1);
> +		if (ret)
> +			return ret;
> +	} while (!ret);
> +
> +	*addr = page_address(pfn_to_page(pfn));
> +
> +	return ret;
> +}
> +
> +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> +			    const union hv_stats_object_identity *identity)
> +{
> +	unsigned long flags;
> +	struct hv_input_unmap_stats_page *input;
> +	u64 status;
> +
> +	local_irq_save(flags);
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +	memset(input, 0, sizeof(*input));
> +	input->type = type;
> +	input->identity = *identity;
> +
> +	status = hv_do_hypercall(HVCALL_UNMAP_STATS_PAGE, input, NULL);
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> +				   u64 page_struct_count, u32 host_access,
> +				   u32 flags, u8 acquire)
> +{
> +	struct hv_input_modify_sparse_spa_page_host_access *input_page;
> +	u64 status;
> +	int done = 0;
> +	unsigned long irq_flags, large_shift = 0;
> +	u64 page_count = page_struct_count;
> +	u16 code = acquire ? HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS :
> +			     HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS;
> +
> +	if (page_count == 0)
> +		return -EINVAL;
> +
> +	if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE) {
> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> +			return -EINVAL;
> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> +		page_count >>= large_shift;
> +	}
> +
> +	while (done < page_count) {
> +		ulong i, completed, remain = page_count - done;
> +		int rep_count = min(remain,
> +				HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT);
> +
> +		local_irq_save(irq_flags);
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		/*
> +		 * This is required to make sure that reserved field is set to
> +		 * zero, because MSHV has a check to make sure reserved bits are
> +		 * set to zero.
> +		 */

Is this comment about checking reserved bits unique to this hypercall? If not, it
seems a little odd to see this comment here, but not other places where the input
is zero'ed.

> +		memset(input_page, 0, sizeof(*input_page));
> +		/* Only set the partition id if you are making the pages
> +		 * exclusive
> +		 */
> +		if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE)
> +			input_page->partition_id = partition_id;
> +		input_page->flags = flags;
> +		input_page->host_access = host_access;
> +
> +		for (i = 0; i < rep_count; i++) {
> +			u64 index = (done + i) << large_shift;
> +
> +			if (index >= page_struct_count)
> +				return -EINVAL;

Can this test ever be true?

> +
> +			input_page->spa_page_list[i] =
> +						page_to_pfn(pages[index]);

When large_shift is non-zero, it seems weird to be skipping over most
of the entries in the "pages" array.  But maybe there's a reason for that.

> +		}
> +
> +		status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
> +					     NULL);
> +		local_irq_restore(irq_flags);
> +
> +		completed = hv_repcomp(status);
> +
> +		if (!hv_result_success(status))
> +			return hv_result_to_errno(status);
> +
> +		done += completed;
> +	}
> +
> +	return 0;
> +}

[snip the rest of the patch that I haven't reviewed yet]

Michael


From vladimir.oltean at nxp.com  Thu Mar 13 09:49:08 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Thu, 13 Mar 2025 18:49:08 +0200
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring
 support for i.MX95 ENETC
In-Reply-To: <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
Message-ID: <20250313164908.rdy3y77xno3fza3l@skbuf>

On Tue, Mar 11, 2025 at 01:38:18PM +0800, Wei Fang wrote:
> The command BD ring is used to configure functionality where the
> underlying resources may be shared between different entities or being
> too large to configure using direct registers (such as lookup tables).
> 
> Because the command BD and table formats of i.MX95 and LS1028A are very
> different, the software processing logic is also different. In order to
> ensure driver compatibility, struct enetc_si_ops is introduced. This
> structure defines some hooks shared by VSI and PSI. Different hardware
> driver will register different hooks, For example, setup_cbdr() is used
> to initialize the command BD ring, and teardown_cbdr() is used to free
> the command BD ring.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---
>  drivers/net/ethernet/freescale/enetc/enetc.h  | 27 +++++++--
>  .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 +++++++++++++++-
>  .../net/ethernet/freescale/enetc/enetc_cbdr.c | 55 +++++++++++++++++--
>  .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
>  .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
>  5 files changed, 136 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
> index 4ad4eb5c5a74..4ff0957e69be 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> @@ -8,6 +8,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/skbuff.h>
>  #include <linux/ethtool.h>
> +#include <linux/fsl/ntmp.h>
>  #include <linux/if_vlan.h>
>  #include <linux/phylink.h>
>  #include <linux/dim.h>
> @@ -266,6 +267,19 @@ struct enetc_platform_info {
>  	const struct enetc_drvdata *data;
>  };
>  
> +struct enetc_si;
> +
> +/*
> + * This structure defines the some common hooks for ENETC PSI and VSI.
> + * In addition, since VSI only uses the struct enetc_si as its private
> + * driver data, so this structure also define some hooks specifically
> + * for VSI. For VSI-specific hooks, the format is ?vf_*()?.
> + */
> +struct enetc_si_ops {
> +	int (*setup_cbdr)(struct enetc_si *si);
> +	void (*teardown_cbdr)(struct enetc_si *si);
> +};

I don't understand the need for si->ops->setup_cbdr() and si->ops->teardown_cbdr()?
Doesn't every call site know which kind of SI it is dealing with, and thus it can
appropriately call the direct symbol?
- the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
- the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()
What benefit is there to making an indirect function call?

At least that's what the current code does, I'm not sure if that is the intention.


From manivannan.sadhasivam at linaro.org  Thu Mar 13 09:53:11 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Thu, 13 Mar 2025 22:23:11 +0530
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
 <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
Message-ID: <20250313165311.2fj7aus3pcsg4m2c@thinkpad>

On Wed, Mar 05, 2025 at 11:20:22AM -0500, Frank Li wrote:

If you want a specific patch to be tested, you can add [PATCH RFT] tag.C

> According to code in drivers/pci/controller/dwc/pci-dra7xx.c
> 
> dra7xx_pcie_cpu_addr_fixup()
> {
> 	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
> }
> 
> PCI parent bus trim high 4 bits address to 0. Correct ranges in
> target-module at 51000000 to algin hardware behavior, which translate PCIe
> outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.
> 
> Set 'config' and 'addr_space' reg values to 0.
> Change parent bus address of downstream I/O and non-prefetchable memory to
> 0.
> 
> Ensure no functional impact on the final address translation result.
> 
> Prepare for the removal of the driver?s cpu_addr_fixup().
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> index b709703f6c0d4..9213fdd25330b 100644
> --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
> +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> @@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
>  			#size-cells = <1>;
>  			#address-cells = <1>;
>  			ranges = <0x51000000 0x51000000 0x3000>,
> -				 <0x20000000 0x20000000 0x10000000>;
> +				 <0x00000000 0x20000000 0x10000000>;

I'm not able to interpret this properly. So this essentially means that the
parent address 0x20000000 is mapped to child address 0x00000000. And the child
address is same for other controller as well.

Also, the cpu_addr_fixup() is doing the same by masking out the upper 4 bits. I
tried looking into the DRA7 TRM, but it says (ECAM_Param_Base_Addr +
0x20000000) where ECAM_Param_Base_Addr = 0x0000_0000 to 0x0FFF_F000.

I couldn't relate TRM with the cpu_addr_fixup() callback. Can someone from TI
shed light on this?

- Mani

-- 
????????? ????????


From lee at kernel.org  Thu Mar 13 09:56:15 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 16:56:15 +0000
Subject: (subset) [PATCH v2 1/2] dt-bindings: mfd: syscon: Add rk3528
 QoS register compatible
In-Reply-To: <20250306123809.273655-2-amadeus@jmu.edu.cn>
References: <20250306123809.273655-1-amadeus@jmu.edu.cn>
 <20250306123809.273655-2-amadeus@jmu.edu.cn>
Message-ID: <174188497549.3792331.5613971273362591228.b4-ty@kernel.org>

On Thu, 06 Mar 2025 20:38:08 +0800, Chukun Pan wrote:
> Document rk3528 compatible for QoS registers.
> 
> 

Applied, thanks!

[1/2] dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
      commit: 1c313607416052414ce94bc9bb27b688741cb30d

--
Lee Jones [???]



From 21cnbao at gmail.com  Thu Mar 13 09:58:00 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Fri, 14 Mar 2025 05:58:00 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <Z9MCwXzYDRJoTiIr@google.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com> <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
 <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com> <Z9MCwXzYDRJoTiIr@google.com>
Message-ID: <CAGsJ_4yaSx1vEiZdCouBveeH3D-bQDdvrhRpz=Kbvqn30Eh-nA@mail.gmail.com>

On Fri, Mar 14, 2025 at 5:07?AM Minchan Kim <minchan at kernel.org> wrote:
>
> On Thu, Mar 13, 2025 at 04:45:54PM +1300, Barry Song wrote:
> > On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
> > <senozhatsky at chromium.org> wrote:
> > >
> > > On (25/03/12 11:11), Minchan Kim wrote:
> > > > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > > > This patch series introduces a new mechanism called kcompressd to
> > > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > > main goal is to separate the tasks of page scanning and page compression
> > > > > into distinct processes or threads, thereby reducing the load on the
> > > > > kswapd thread and enhancing overall system performance under high memory
> > > > > pressure conditions.
> > > > >
> > > > > Problem:
> > > > >  In the current system, the kswapd thread is responsible for both
> > > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > > >  combined responsibility can lead to significant performance bottlenecks,
> > > > >  especially under high memory pressure. The kswapd thread becomes a
> > > > >  single point of contention, causing delays in memory reclaiming and
> > > > >  overall system performance degradation.
> > > >
> > > > Isn't it general problem if backend for swap is slow(but synchronous)?
> > > > I think zram need to support asynchrnous IO(can do introduce multiple
> > > > threads to compress batched pages) and doesn't declare it's
> > > > synchrnous device for the case.
> > >
> > > The current conclusion is that kcompressd will sit above zram,
> > > because zram is not the only compressing swap backend we have.
>
> Then, how handles the file IO case?

I didn't quite catch your question :-)

>
> >
> > also. it is not good to hack zram to be aware of if it is kswapd
> > , direct reclaim , proactive reclaim and block device with
> > mounted filesystem.
>
> Why shouldn't zram be aware of that instead of just introducing
> queues in the zram with multiple compression threads?
>

My view is the opposite of yours :-)

Integrating kswapd, direct reclaim, etc., into the zram driver
would violate layering principles. zram is purely a block device
driver, and how it is used should be handled separately. Callers have
greater flexibility to determine its usage, similar to how different
I/O models exist in user space.

Currently, Qun-Wei's patch checks whether the current thread is kswapd.
If it is, compression is performed asynchronously by threads;
otherwise, it is done in the current thread. In the future, we may
have additional reclaim threads, such as for damon or
madv_pageout, etc.

> >
> > so i am thinking sth as below
> >
> > page_io.c
> >
> > if (sync_device or zswap_enabled())
> >    schedule swap_writepage to a separate per-node thread
>
> I am not sure that's a good idea to mix a feature to solve different
> layers. That wouldn't be only swap problem. Such an parallelism under
> device  is common technique these days and it would help file IO cases.
>

zswap and zram share the same needs, and handling this in page_io
can benefit both through common code. It is up to the callers to decide
the I/O model.

I agree that "parallelism under the device" is a common technique,
but our case is different?the device achieves parallelism with
offload hardware, whereas we rely on CPUs, which can be scarce.
These threads may also preempt CPUs that are critically needed
by other non-compression tasks, and burst power consumption
can sometimes be difficult to control.

> Furthermore, it would open the chance for zram to try compress
> multiple pages at once.

We are already in this situation when multiple callers use zram simultaneously,
such as during direct reclaim or with a mounted filesystem.

Of course, this allows multiple pages to be compressed simultaneously,
even if the user is single-threaded. However, determining when to enable
these threads and whether they will be effective is challenging, as it
depends on system load. For example, Qun-Wei's patch chose not to use
threads for direct reclaim as, I guess,  it might be harmful.

Thanks
Barry


From lee at kernel.org  Thu Mar 13 10:02:13 2025
From: lee at kernel.org (Lee Jones)
Date: Thu, 13 Mar 2025 17:02:13 +0000
Subject: (subset) [PATCH v4 02/19] mfd: mt6397-core: Add mfd_cell for
 mt6359-accdet
In-Reply-To: <20250305-mt6359-accdet-dts-v4-2-e5ffa5ee9991@collabora.com>
References: <20250305-mt6359-accdet-dts-v4-0-e5ffa5ee9991@collabora.com>
 <20250305-mt6359-accdet-dts-v4-2-e5ffa5ee9991@collabora.com>
Message-ID: <174188533371.3796672.1232285311249129492.b4-ty@kernel.org>

On Wed, 05 Mar 2025 15:58:17 -0300, N?colas F. R. A. Prado wrote:
> Add an mfd_cell for mt6359-accdet and describe its IRQ resources to
> allow the mt6359-accdet driver to probe.
> 
> 

Applied, thanks!

[02/19] mfd: mt6397-core: Add mfd_cell for mt6359-accdet
        commit: 1b9e922a8df918812aff4090207abf4a8cb5aefa

--
Lee Jones [???]



From minchan at kernel.org  Thu Mar 13 09:07:29 2025
From: minchan at kernel.org (Minchan Kim)
Date: Thu, 13 Mar 2025 09:07:29 -0700
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com>
 <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
 <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com>
Message-ID: <Z9MCwXzYDRJoTiIr@google.com>

On Thu, Mar 13, 2025 at 04:45:54PM +1300, Barry Song wrote:
> On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
> <senozhatsky at chromium.org> wrote:
> >
> > On (25/03/12 11:11), Minchan Kim wrote:
> > > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > > This patch series introduces a new mechanism called kcompressd to
> > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > main goal is to separate the tasks of page scanning and page compression
> > > > into distinct processes or threads, thereby reducing the load on the
> > > > kswapd thread and enhancing overall system performance under high memory
> > > > pressure conditions.
> > > >
> > > > Problem:
> > > >  In the current system, the kswapd thread is responsible for both
> > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > >  combined responsibility can lead to significant performance bottlenecks,
> > > >  especially under high memory pressure. The kswapd thread becomes a
> > > >  single point of contention, causing delays in memory reclaiming and
> > > >  overall system performance degradation.
> > >
> > > Isn't it general problem if backend for swap is slow(but synchronous)?
> > > I think zram need to support asynchrnous IO(can do introduce multiple
> > > threads to compress batched pages) and doesn't declare it's
> > > synchrnous device for the case.
> >
> > The current conclusion is that kcompressd will sit above zram,
> > because zram is not the only compressing swap backend we have.

Then, how handles the file IO case?

> 
> also. it is not good to hack zram to be aware of if it is kswapd
> , direct reclaim , proactive reclaim and block device with
> mounted filesystem.

Why shouldn't zram be aware of that instead of just introducing
queues in the zram with multiple compression threads?

> 
> so i am thinking sth as below
> 
> page_io.c
> 
> if (sync_device or zswap_enabled())
>    schedule swap_writepage to a separate per-node thread

I am not sure that's a good idea to mix a feature to solve different
layers. That wouldn't be only swap problem. Such an parallelism under
device  is common technique these days and it would help file IO cases.

Furthermore, it would open the chance for zram to try compress
multiple pages at once.


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:28 +0100
Subject: Patch "KVM: arm64: Eagerly switch ZCR_EL{1,2}" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-8-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031328-playable-decorated-6f85@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Eagerly switch ZCR_EL{1,2}

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-eagerly-switch-zcr_el-1-2.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 13 00:49:53 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:16 +0000
Subject: KVM: arm64: Eagerly switch ZCR_EL{1,2}
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-8-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
(cherry picked from commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59)
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/fpsimd.c                 |   30 ----------------
 arch/arm64/kvm/hyp/entry.S              |    5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h |   59 ++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |   13 +++----
 arch/arm64/kvm/hyp/nvhe/switch.c        |   33 +++++++++++++++--
 arch/arm64/kvm/hyp/vhe/switch.c         |    4 ++
 6 files changed, 103 insertions(+), 41 deletions(-)

--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,6 +375,65 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -178,8 +179,12 @@ static void handle___kvm_vcpu_run(struct
 		sync_hyp_vcpu(hyp_vcpu);
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
+		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
+
 		/* The host is fully trusted, run its vCPU directly. */
-		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_guest(vcpu);
+		ret = __kvm_vcpu_run(vcpu);
+		fpsimd_lazy_switch_to_host(vcpu);
 	}
 
 out:
@@ -480,12 +485,6 @@ void handle_trap(struct kvm_cpu_context
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kv
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:28 +0100
Subject: Patch "KVM: arm64: Calculate cptr_el2 traps on activating traps" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-1-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031328-creature-hardship-32f5@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Calculate cptr_el2 traps on activating traps

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-124192-greg=kroah.com at vger.kernel.org Thu Mar 13 00:49:47 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:09 +0000
Subject: KVM: arm64: Calculate cptr_el2 traps on activating traps
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Fuad Tabba <tabba at google.com>,  James Clark <james.clark at linaro.org>
Message-ID: <20250312-stable-sve-6-13-v1-1-c7ba07a6f4f7 at kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    1 
 arch/arm64/kvm/arm.c              |    1 
 arch/arm64/kvm/hyp/nvhe/pkvm.c    |   30 ----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  |   51 +++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 51 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -708,7 +708,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1569,7 +1569,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -31,8 +31,6 @@ static void pvm_init_traps_aa64pfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -62,21 +60,10 @@ static void pvm_init_traps_aa64pfr0(stru
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -106,7 +93,6 @@ static void pvm_init_traps_aa64dfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -133,21 +119,12 @@ static void pvm_init_traps_aa64dfr0(stru
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -198,10 +175,6 @@ static void pvm_init_trap_regs(struct kv
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
@@ -236,7 +209,6 @@ static void pkvm_vcpu_reset_hcr(struct k
  */
 static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 	vcpu->arch.mdcr_el2 = 0;
 
 	pkvm_vcpu_reset_hcr(vcpu);
@@ -693,8 +665,6 @@ unlock:
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_ve
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
+
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Refactor exit handlers" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-6-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031329-runny-graveness-71eb@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Refactor exit handlers

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-refactor-exit-handlers.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 13 00:49:47 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:14 +0000
Subject: KVM: arm64: Refactor exit handlers
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-6-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -666,23 +666,16 @@ static bool kvm_hyp_handle_dabt_low(stru
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -712,20 +705,9 @@ static inline void synchronize_vcpu_psta
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -755,7 +737,7 @@ static inline bool fixup_guest_exit(stru
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_ex
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_ha
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Remove host FPSIMD saving for non-protected KVM" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-3-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031329-mullets-shining-4736@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove host FPSIMD saving for non-protected KVM

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-124194-greg=kroah.com at vger.kernel.org Thu Mar 13 00:50:09 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:11 +0000
Subject: KVM: arm64: Remove host FPSIMD saving for non-protected KVM
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-3-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[CPACR_EL1_ZEN -> CPACR_ELx_ZEN -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h       |   18 ++++--------------
 arch/arm64/kvm/arm.c                    |    8 --------
 arch/arm64/kvm/fpsimd.c                 |    2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h |   25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    8 --------
 7 files changed, 28 insertions(+), 63 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -613,23 +613,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
+	struct cpu_sve_state *sve_state;
 
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2468,14 +2468,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,7 +375,28 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -425,7 +446,7 @@ static bool kvm_hyp_handle_fpsimd(struct
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_v
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct k
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-5-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031329-glitter-stricken-345b@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 13 00:49:44 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:13 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-5-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   21 ---------------------
 2 files changed, 23 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-4-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031329-unstuck-scapegoat-1ed4@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-124195-greg=kroah.com at vger.kernel.org Thu Mar 13 00:50:19 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:12 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-4-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   16 ----------------
 2 files changed, 18 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-2-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031329-essay-escargot-b190@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-124193-greg=kroah.com at vger.kernel.org Thu Mar 13 00:49:59 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:10 +0000
Subject: KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Eric Auger <eauger at redhat.com>, Wilco Dijkstra <wilco.dijkstra at arm.com>,  Eric Auger <eric.auger at redhat.com>, Florian Weimer <fweimer at redhat.com>,  Fuad Tabba <tabba at google.com>, Jeremy Linton <jeremy.linton at arm.com>,  Paolo Bonzini <pbonzini at redhat.com>
Message-ID: <20250312-stable-sve-6-13-v1-2-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kernel/fpsimd.c |   25 -------------------------
 arch/arm64/kvm/fpsimd.c    |   35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1695,31 +1695,6 @@ void fpsimd_signal_preserve_current_stat
 }
 
 /*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
-/*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
  * this function.
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From gregkh at linuxfoundation.org  Thu Mar 13 09:09:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Thu, 13 Mar 2025 17:09:29 +0100
Subject: Patch "KVM: arm64: Mark some header functions as inline" has been added to the 6.13-stable tree
In-Reply-To: <20250312-stable-sve-6-13-v1-7-c7ba07a6f4f7@kernel.org>
Message-ID: <2025031328-breeding-auction-9fbd@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Mark some header functions as inline

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-mark-some-header-functions-as-inline.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 13 00:49:50 2025
From: Mark Brown <broonie at kernel.org>
Date: Wed, 12 Mar 2025 23:49:15 +0000
Subject: KVM: arm64: Mark some header functions as inline
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250312-stable-sve-6-13-v1-7-c7ba07a6f4f7 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -326,7 +326,7 @@ static inline bool __populate_fault_info
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -404,7 +404,7 @@ static void kvm_hyp_save_fpsimd_host(str
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -595,7 +595,7 @@ static bool handle_ampere1_tcr(struct kv
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -615,7 +615,7 @@ static bool kvm_hyp_handle_sysreg(struct
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -624,19 +624,18 @@ static bool kvm_hyp_handle_cp15_32(struc
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch


From ryan.roberts at arm.com  Thu Mar 13 09:13:22 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 16:13:22 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313104111.24196-3-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
Message-ID: <ea10caee-59ef-4a00-9b61-37cb0a379411@arm.com>

On 13/03/2025 10:41, Miko?aj Lenczewski wrote:
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for, as well as a kernel commandline parameter to optionally
> disable BBML2 altogether.
> 
> This is a system feature as we might have a big.LITTLE architecture
> where some cores support BBML2 and some don't, but we want all cores to
> be available and BBM to default to level 0 (as opposed to having cores
> without BBML2 not coming online).
> 
> To support BBML2 in as wide a range of contexts as we can, we want not
> only the architectural guarantees that BBML2 makes, but additionally
> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
> us having to prove that no recursive faults can be induced in any path
> that uses BBML2, allowing its use for arbitrary kernel mappings.
> Support detection of such CPUs.
> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>

I have 2 nits below, but with those resolved:

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

> ---
>  .../admin-guide/kernel-parameters.txt         |  3 +
>  arch/arm64/Kconfig                            | 11 +++
>  arch/arm64/include/asm/cpucaps.h              |  2 +
>  arch/arm64/include/asm/cpufeature.h           |  6 ++
>  arch/arm64/kernel/cpufeature.c                | 76 +++++++++++++++++++
>  arch/arm64/kernel/pi/idreg-override.c         |  2 +
>  arch/arm64/tools/cpucaps                      |  1 +
>  7 files changed, 101 insertions(+)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fb8752b42ec8..3e4cc917a07e 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -453,6 +453,9 @@
>  	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>  			32 bit applications.
>  
> +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> +			2 support
> +
>  	arm64.nobti	[ARM64] Unconditionally disable Branch Target
>  			Identification support
>  
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..49deda2b22ae 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>  	  The feature introduces new assembly instructions, and they were
>  	  support when binutils >= 2.30.
>  
> +config ARM64_BBML2_NOABORT
> +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
> +	default y
> +	help
> +	  FEAT_BBM provides detection of support levels for break-before-make
> +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
> +	  can be relaxed to improve performance. We additonally require the
> +	  property that the implementation cannot ever raise TLB Conflict Aborts.
> +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
> +	  even if the system supports BBM level 2.
> +
>  endmenu # "ARMv8.4 architectural features"
>  
>  menu "ARMv8.5 architectural features"
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 0b5ca6e0eb09..2d6db33d4e45 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>  		return IS_ENABLED(CONFIG_ARM64_PAN);
>  	case ARM64_HAS_EPAN:
>  		return IS_ENABLED(CONFIG_ARM64_EPAN);
> +	case ARM64_HAS_BBML2_NOABORT:
> +		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>  	case ARM64_SVE:
>  		return IS_ENABLED(CONFIG_ARM64_SVE);
>  	case ARM64_SME:
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index e0e4478f5fb5..7f5b220dacde 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -18,6 +18,7 @@
>  #define ARM64_SW_FEATURE_OVERRIDE_NOKASLR	0
>  #define ARM64_SW_FEATURE_OVERRIDE_HVHE		4
>  #define ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF	8
> +#define ARM64_SW_FEATURE_OVERRIDE_NOBBML2	12
>  
>  #ifndef __ASSEMBLY__
>  
> @@ -866,6 +867,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
>  	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>  }
>  
> +static inline bool system_supports_bbml2_noabort(void)
> +{
> +	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
> +}
> +
>  int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>  bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>  
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index d561cf3b8ac7..b936e0805161 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2176,6 +2176,76 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>  	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>  }
>  
> +static inline bool bbml2_possible(void)
> +{
> +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);

If you're going to keep this helper, I think it really needs to be:

return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) &&
       !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);

Then you would simplify the caller to remove it's own
IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) check.

But personally I would remove the helper and just fold the test into
has_bbml2_noabort().

Thanks,
Ryan

> +}
> +
> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> +{
> +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
> +	 * as possible. This list is therefore an allow-list of known-good
> +	 * implementations that both support bbml2 and additionally, fulfill the
> +	 * extra constraint of never generating TLB conflict aborts when using
> +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> +	 * kernel contexts difficult to prove safe against recursive aborts).
> +	 *
> +	 * Note that implementations can only be considered "known-good" if their
> +	 * implementors attest to the fact that the implementation never raises
> +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
> +	 */
> +	static const struct midr_range supports_bbml2_noabort_list[] = {
> +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> +		{}
> +	};
> +
> +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
> +}
> +
> +static inline unsigned int __cpu_read_midr(int cpu)

nit: why the double underscrore prefix?

> +{
> +	WARN_ON_ONCE(!cpu_online(cpu));
> +
> +	return per_cpu(cpu_data, cpu).reg_midr;
> +}
> +
> +static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
> +{
> +	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
> +		return false;
> +
> +	if (!bbml2_possible())
> +		return false;
> +
> +	if (scope & SCOPE_SYSTEM) {
> +		int cpu;
> +
> +		/* We are a boot CPU, and must verify that all enumerated boot
> +		 * CPUs have MIDR values within our allowlist. Otherwise, we do
> +		 * not allow the BBML2 feature to avoid potential faults when
> +		 * the insufficient CPUs access memory regions using BBML2
> +		 * semantics.
> +		 */
> +		for_each_online_cpu(cpu) {
> +			if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
> +				return false;
> +		}
> +
> +		return true;
> +	} else if (scope & SCOPE_LOCAL_CPU) {
> +		/* We are a hot-plugged CPU, so only need to check our MIDR.
> +		 * If we have the correct MIDR, but the kernel booted on an
> +		 * insufficient CPU, we will not use BBML2 (this is safe). If
> +		 * we have an incorrect MIDR, but the kernel booted on a
> +		 * sufficient CPU, we will not bring up this CPU.
> +		 */
> +		return cpu_has_bbml2_noabort(read_cpuid_id());
> +	}
> +
> +	return false;
> +}
> +
>  #ifdef CONFIG_ARM64_PAN
>  static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>  {
> @@ -2926,6 +2996,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.matches = has_cpuid_feature,
>  		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
>  	},
> +	{
> +		.desc = "BBM Level 2 without conflict abort",
> +		.capability = ARM64_HAS_BBML2_NOABORT,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.matches = has_bbml2_noabort,
> +	},
>  	{
>  		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
>  		.capability = ARM64_HAS_LPA2,
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f7..9728faa10390 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>  		{}
>  	},
>  };
> @@ -246,6 +247,7 @@ static const struct {
>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
>  };
>  
>  static int __init parse_hexdigit(const char *p, u64 *v)
> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
> index 1e65f2fb45bd..b03a375e5507 100644
> --- a/arch/arm64/tools/cpucaps
> +++ b/arch/arm64/tools/cpucaps
> @@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
>  HAS_ADDRESS_AUTH_IMP_DEF
>  HAS_AMU_EXTN
>  HAS_ARMv8_4_TTL
> +HAS_BBML2_NOABORT
>  HAS_CACHE_DIC
>  HAS_CACHE_IDC
>  HAS_CNP



From phasta at kernel.org  Thu Mar 13 09:14:20 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Thu, 13 Mar 2025 17:14:20 +0100
Subject: [PATCH net-next 0/3] Clean up deprecated PCI calls
Message-ID: <20250313161422.97174-2-phasta@kernel.org>

Spiritual successor of this older series, of which one patch has already
been merged [1]

P.

[1] https://lore.kernel.org/netdev/20250226085208.97891-1-phasta at kernel.org/

Philipp Stanner (3):
  stmmac: loongson: Remove surplus loop
  stmmac: Remove pcim_* functions for driver detach
  stmmac: Replace deprecated PCI functions

 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 27 +++++--------------
 .../net/ethernet/stmicro/stmmac/stmmac_pci.c  | 26 +++++-------------
 2 files changed, 13 insertions(+), 40 deletions(-)

-- 
2.48.1



From phasta at kernel.org  Thu Mar 13 09:14:21 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Thu, 13 Mar 2025 17:14:21 +0100
Subject: [PATCH net-next 1/3] stmmac: loongson: Remove surplus loop
In-Reply-To: <20250313161422.97174-2-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
Message-ID: <20250313161422.97174-3-phasta@kernel.org>

loongson_dwmac_probe() contains a loop which doesn't have an effect,
because it tries to call pcim_iomap_regions() with the same parameters
several times. The break statement at the loop's end furthermore ensures
that the loop only runs once anyways.

Remove the surplus loop.

Signed-off-by: Philipp Stanner <phasta at kernel.org>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
Tested-by: Henry Chen <chenx97 at aosc.io>
---
 .../net/ethernet/stmicro/stmmac/dwmac-loongson.c    | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 73a6715a93e6..e2959ac5c1ca 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -524,7 +524,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
 	struct loongson_data *ld;
-	int ret, i;
+	int ret;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -554,14 +554,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	pci_set_master(pdev);
 
 	/* Get the base address of device */
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
-		if (ret)
-			goto err_disable_device;
-		break;
-	}
+	ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
+	if (ret)
+		goto err_disable_device;
 
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
-- 
2.48.1



From phasta at kernel.org  Thu Mar 13 09:14:22 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Thu, 13 Mar 2025 17:14:22 +0100
Subject: [PATCH net-next 2/3] stmmac: Remove pcim_* functions for driver detach
In-Reply-To: <20250313161422.97174-2-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
Message-ID: <20250313161422.97174-4-phasta@kernel.org>

Functions prefixed with "pcim_" are managed devres functions which
perform automatic cleanup once the driver unloads. It is, thus, not
necessary to call any cleanup functions in remove() callbacks.

Remove the pcim_ cleanup function calls in the remove() callbacks.

Signed-off-by: Philipp Stanner <phasta at kernel.org>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
Tested-by: Henry Chen <chenx97 at aosc.io>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c |  8 --------
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c     | 12 +-----------
 2 files changed, 1 insertion(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index e2959ac5c1ca..5d7746d787ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -603,7 +603,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 	struct net_device *ndev = dev_get_drvdata(&pdev->dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct loongson_data *ld;
-	int i;
 
 	ld = priv->plat->bsp_priv;
 	stmmac_dvr_remove(&pdev->dev);
@@ -614,13 +613,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 	if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
 		loongson_dwmac_msi_clear(pdev);
 
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		pcim_iounmap_regions(pdev, BIT(i));
-		break;
-	}
-
 	pci_disable_device(pdev);
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 352b01678c22..1637c8139b9d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -226,21 +226,11 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  * stmmac_pci_remove
  *
  * @pdev: platform device pointer
- * Description: this function calls the main to free the net resources
- * and releases the PCI resources.
+ * Description: this function calls the main to free the net resources.
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
-	int i;
-
 	stmmac_dvr_remove(&pdev->dev);
-
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		pcim_iounmap_regions(pdev, BIT(i));
-		break;
-	}
 }
 
 static int __maybe_unused stmmac_pci_suspend(struct device *dev)
-- 
2.48.1



From phasta at kernel.org  Thu Mar 13 09:14:23 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Thu, 13 Mar 2025 17:14:23 +0100
Subject: [PATCH net-next 3/3] stmmac: Replace deprecated PCI functions
In-Reply-To: <20250313161422.97174-2-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
Message-ID: <20250313161422.97174-5-phasta@kernel.org>

From: Philipp Stanner <pstanner at redhat.com>

The PCI functions
  - pcim_iomap_regions() and
  - pcim_iomap_table()
have been deprecated.

Replace them with their successor function, pcim_iomap_region().

Make variable declaration order at closeby places comply with reverse
christmas tree order.

Signed-off-by: Philipp Stanner <pstanner at redhat.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
Tested-by: Henry Chen <chenx97 at aosc.io>
---
 .../net/ethernet/stmicro/stmmac/dwmac-loongson.c   |  8 +++-----
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c   | 14 ++++++--------
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 5d7746d787ac..25ef7b9c5dce 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -521,8 +521,8 @@ static int loongson_dwmac_acpi_config(struct pci_dev *pdev,
 static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct plat_stmmacenet_data *plat;
+	struct stmmac_resources res = {};
 	struct stmmac_pci_info *info;
-	struct stmmac_resources res;
 	struct loongson_data *ld;
 	int ret;
 
@@ -554,13 +554,11 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	pci_set_master(pdev);
 
 	/* Get the base address of device */
-	ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
+	res.addr = pcim_iomap_region(pdev, 0, DRIVER_NAME);
+	ret = PTR_ERR_OR_ZERO(res.addr);
 	if (ret)
 		goto err_disable_device;
 
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[0];
-
 	plat->bsp_priv = ld;
 	plat->setup = loongson_dwmac_setup;
 	ld->dev = &pdev->dev;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 1637c8139b9d..b7adda35b7b7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -155,9 +155,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 {
 	struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
 	struct plat_stmmacenet_data *plat;
-	struct stmmac_resources res;
-	int i;
+	struct stmmac_resources res = {};
 	int ret;
+	int i;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -188,13 +188,13 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 		return ret;
 	}
 
-	/* Get the base address of device */
+	/* The first BAR > 0 is the base IO addr of our device. */
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 		if (pci_resource_len(pdev, i) == 0)
 			continue;
-		ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
-		if (ret)
-			return ret;
+		res.addr = pcim_iomap_region(pdev, i, STMMAC_RESOURCE_NAME);
+		if (IS_ERR(res.addr))
+			return PTR_ERR(res.addr);
 		break;
 	}
 
@@ -204,8 +204,6 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		return ret;
 
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[i];
 	res.wol_irq = pdev->irq;
 	res.irq = pdev->irq;
 
-- 
2.48.1



From leo.yan at arm.com  Thu Mar 13 09:17:02 2025
From: leo.yan at arm.com (Leo Yan)
Date: Thu, 13 Mar 2025 16:17:02 +0000
Subject: [PATCH 7/7] coresight: Remove extern from function declarations
In-Reply-To: <20250211103945.967495-8-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-8-james.clark@linaro.org>
Message-ID: <20250313161702.GT9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:43AM +0000, James Clark wrote:
> 
> Function declarations are extern by default so remove the extra noise
> and inconsistency.

This change is consistent with the coding-style.rst:

  "Do not use the ``extern`` keyword with function declarations as
   this makes lines longer and isn't strictly necessary."

Reviewed-by: Leo Yan <leo.yan at arm.com>

> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-priv.h | 14 ++++-----
>  include/linux/coresight.h                    | 33 +++++++++-----------
>  2 files changed, 21 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index a83113225797..e09071a720f0 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -57,10 +57,8 @@ struct cs_off_attribute {
>         u32 off;
>  };
> 
> -extern ssize_t coresight_simple_show32(struct device *_dev,
> -                                    struct device_attribute *attr, char *buf);
> -extern ssize_t coresight_simple_show_pair(struct device *_dev,
> -                                    struct device_attribute *attr, char *buf);
> +ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
> +ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf);
> 
>  #define coresight_simple_reg32(name, offset)                           \
>         (&((struct cs_off_attribute[]) {                                \
> @@ -155,8 +153,8 @@ void coresight_remove_links(struct coresight_device *orig,
>  u32 coresight_get_sink_id(struct coresight_device *csdev);
> 
>  #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
> -extern int etm_readl_cp14(u32 off, unsigned int *val);
> -extern int etm_writel_cp14(u32 off, u32 val);
> +int etm_readl_cp14(u32 off, unsigned int *val);
> +int etm_writel_cp14(u32 off, u32 val);
>  #else
>  static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
>  static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
> @@ -167,8 +165,8 @@ struct cti_assoc_op {
>         void (*remove)(struct coresight_device *csdev);
>  };
> 
> -extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
> -extern void coresight_remove_cti_ops(void);
> +void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
> +void coresight_remove_cti_ops(void);
> 
>  /*
>   * Macros and inline functions to handle CoreSight UCI data and driver
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 11808aee9d1d..2b43698c0b25 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -642,26 +642,23 @@ static inline void coresight_set_mode(struct coresight_device *csdev,
>         local_set(&csdev->mode, new_mode);
>  }
> 
> -extern struct coresight_device *
> -coresight_register(struct coresight_desc *desc);
> -extern void coresight_unregister(struct coresight_device *csdev);
> -extern int coresight_enable_sysfs(struct coresight_device *csdev);
> -extern void coresight_disable_sysfs(struct coresight_device *csdev);
> -extern int coresight_timeout(struct csdev_access *csa, u32 offset,
> -                            int position, int value);
> -
> -extern int coresight_claim_device(struct coresight_device *csdev);
> -extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
> -
> -extern void coresight_disclaim_device(struct csdev_access *csa);
> -extern void coresight_disclaim_device_unlocked(struct csdev_access *csa);
> +struct coresight_device *coresight_register(struct coresight_desc *desc);
> +void coresight_unregister(struct coresight_device *csdev);
> +int coresight_enable_sysfs(struct coresight_device *csdev);
> +void coresight_disable_sysfs(struct coresight_device *csdev);
> +int coresight_timeout(struct csdev_access *csa, u32 offset, int position, int value);
> +
> +int coresight_claim_device(struct coresight_device *csdev);
> +int coresight_claim_device_unlocked(struct coresight_device *csdev);
> +
> +void coresight_disclaim_device(struct csdev_access *csa);
> +void coresight_disclaim_device_unlocked(struct csdev_access *csa);
>  int coresight_reset_claim_unlocked(struct csdev_access *csa);
>  int coresight_reset_claim(struct csdev_access *csa);
> 
> -extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
> -                                        struct device *dev);
> +char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev);
> 
> -extern bool coresight_loses_context_with_cpu(struct device *dev);
> +bool coresight_loses_context_with_cpu(struct device *dev);
> 
>  u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset);
>  u32 coresight_read32(struct coresight_device *csdev, u32 offset);
> @@ -674,8 +671,8 @@ void coresight_relaxed_write64(struct coresight_device *csdev,
>                                u64 val, u32 offset);
>  void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset);
> 
> -extern int coresight_get_cpu(struct device *dev);
> -extern int coresight_get_static_trace_id(struct device *dev, u32 *id);
> +int coresight_get_cpu(struct device *dev);
> +int coresight_get_static_trace_id(struct device *dev, u32 *id);
> 
>  struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
>  struct coresight_connection *
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From ryan.roberts at arm.com  Thu Mar 13 09:18:12 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 16:18:12 +0000
Subject: [PATCH v3 2/3] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250313104111.24196-4-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-4-miko.lenczewski@arm.com>
Message-ID: <07c36889-10d3-4944-a039-3a30fbdca883@arm.com>

On 13/03/2025 10:41, Miko?aj Lenczewski wrote:
> For supporting BBM Level 2 for userspace mappings, we want to ensure
> that the smmu also supports its own version of BBM Level 2. Luckily, the
> smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
> 0487K.a D8.16.2), so already guarantees that no aborts are raised when
> BBM level 2 is claimed.
> 
> Add the feature and testing for it under arm_smmu_sva_supported().
> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>

Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>

> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
>  3 files changed, 10 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> index 9ba596430e7c..6ba182572788 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
>  		feat_mask |= ARM_SMMU_FEAT_VAX;
>  	}
>  
> +	if (system_supports_bbml2_noabort())
> +		feat_mask |= ARM_SMMU_FEAT_BBML2;
> +
>  	if ((smmu->features & feat_mask) != feat_mask)
>  		return false;
>  
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 358072b4e293..dcee0bdec924 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
>  	if (FIELD_GET(IDR3_RIL, reg))
>  		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
>  
> +	if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
> +		smmu->features |= ARM_SMMU_FEAT_BBML2;
> +
>  	/* IDR5 */
>  	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
>  
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> index bd9d7c85576a..85eaf3ab88c2 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -60,6 +60,9 @@ struct arm_smmu_device;
>  #define ARM_SMMU_IDR3			0xc
>  #define IDR3_FWB			(1 << 8)
>  #define IDR3_RIL			(1 << 10)
> +#define IDR3_BBML			GENMASK(12, 11)
> +#define IDR3_BBML1			(1 << 11)
> +#define IDR3_BBML2			(2 << 11)
>  
>  #define ARM_SMMU_IDR5			0x14
>  #define IDR5_STALL_MAX			GENMASK(31, 16)
> @@ -754,6 +757,7 @@ struct arm_smmu_device {
>  #define ARM_SMMU_FEAT_HA		(1 << 21)
>  #define ARM_SMMU_FEAT_HD		(1 << 22)
>  #define ARM_SMMU_FEAT_S2FWB		(1 << 23)
> +#define ARM_SMMU_FEAT_BBML2		(1 << 24)
>  	u32				features;
>  
>  #define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)



From fabrice.gasnier at foss.st.com  Thu Mar 13 10:04:25 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 13 Mar 2025 18:04:25 +0100
Subject: [PATCH v3 4/8] clocksource: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <83283a94-6833-4d7d-8d89-6ba42b43b96c@linaro.org>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-5-fabrice.gasnier@foss.st.com>
 <83283a94-6833-4d7d-8d89-6ba42b43b96c@linaro.org>
Message-ID: <c0aec002-7889-4ec5-a438-e7e90d8da13f@foss.st.com>

On 3/7/25 16:12, Daniel Lezcano wrote:
> On 05/03/2025 10:49, Fabrice Gasnier wrote:
>> On stm32mp25, DIER (former IER) must only be modified when the lptimer
>> is enabled. On earlier SoCs, it must be only be modified when it is
>> disabled. Read the LPTIM_VERR register to properly manage the enable
>> state, before accessing IER.
>>
>> Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
>> ---
>> Changes in V2:
>> - rely on fallback compatible as no specific .data is associated to the
>> ?? driver. Use version data from MFD core.
>> - Added interrupt enable register access update in (missed in V1)
>> ---
>> ? drivers/clocksource/timer-stm32-lp.c | 26 ++++++++++++++++++++++----
>> ? 1 file changed, 22 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/clocksource/timer-stm32-lp.c
>> b/drivers/clocksource/timer-stm32-lp.c
>> index a4c95161cb22..96d975adf7a4 100644
>> --- a/drivers/clocksource/timer-stm32-lp.c
>> +++ b/drivers/clocksource/timer-stm32-lp.c
>> @@ -25,6 +25,7 @@ struct stm32_lp_private {
>> ????? struct clock_event_device clkevt;
>> ????? unsigned long period;
>> ????? struct device *dev;
>> +??? bool ier_wr_enabled;??? /* Enables LPTIMER before writing into
>> IER register */
>> ? };
>> ? ? static struct stm32_lp_private*
>> @@ -37,8 +38,15 @@ static int stm32_clkevent_lp_shutdown(struct
>> clock_event_device *clkevt)
>> ? {
>> ????? struct stm32_lp_private *priv = to_priv(clkevt);
>> ? -??? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
>> +??? /* Disable LPTIMER either before or after writing IER register
>> (else, keep it enabled) */
>> +??? if (!priv->ier_wr_enabled)
>> +??????? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
>> +
>> ????? regmap_write(priv->reg, STM32_LPTIM_IER, 0);
>> +
> 
> Why not encapsulate the function ?
> 
> ????regmap_write_ier(struct stm32_lp_private *priv, int value)
> ????{
> 
> ??????? /* A comment ... */
> ??????? if (!priv->ier_wr_enabled)
> ??????????? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
> 
> ??????? regmap_write(priv->reg, STM32_LPTIM_IER, value);
> 
> ??????? if (!priv->ier_wr_enabled)
> ??????????? regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
> ????}

Hi Daniel,

Thanks for your suggestion.

I've tried various factorization but can't really find something pretty
and easy to read.

I think I'll rather implement some dedicated ops in V4, for stm32mp25,
based on compatible data.
This would allow straight forward sequence, without dangling with enable
bit / flags. I also need to add some checks on new status flags. So this
will avoid to add complexity on existing routines.

Best Regards,
Fabrice

> 
> 
>> +??? if (priv->ier_wr_enabled)
>> +??????? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
>> +
> 
>> ????? /* clear pending flags */
>> ????? regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
>> ? @@ -51,12 +59,21 @@ static int stm32_clkevent_lp_set_timer(unsigned
>> long evt,
>> ? {
>> ????? struct stm32_lp_private *priv = to_priv(clkevt);
>> ? -??? /* disable LPTIMER to be able to write into IER register*/
>> -??? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
>> +??? if (!priv->ier_wr_enabled) {
>> +??????? /* Disable LPTIMER to be able to write into IER register */
>> +??????? regmap_write(priv->reg, STM32_LPTIM_CR, 0);
>> +??? } else {
>> +??????? /* Enable LPTIMER to be able to write into IER register */
>> +??????? regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
>> +??? }
>> +
>> ????? /* enable ARR interrupt */
>> ????? regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
>> +
>> ????? /* enable LPTIMER to be able to write into ARR register */
>> -??? regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
>> +??? if (!priv->ier_wr_enabled)
>> +??????? regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
>> +
>> ????? /* set next event counter */
>> ????? regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
>> ? @@ -151,6 +168,7 @@ static int stm32_clkevent_lp_probe(struct
>> platform_device *pdev)
>> ????????? return -ENOMEM;
>> ? ????? priv->reg = ddata->regmap;
>> +??? priv->ier_wr_enabled = ddata->version == STM32_LPTIM_VERR_23;
>> ????? ret = clk_prepare_enable(ddata->clk);
>> ????? if (ret)
>> ????????? return -EINVAL;
> 
> 


From fabrice.gasnier at foss.st.com  Thu Mar 13 10:07:16 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Thu, 13 Mar 2025 18:07:16 +0100
Subject: [PATCH v3 2/8] mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250313164008.GC3645863@google.com>
References: <20250305094935.595667-1-fabrice.gasnier@foss.st.com>
 <20250305094935.595667-3-fabrice.gasnier@foss.st.com>
 <20250313164008.GC3645863@google.com>
Message-ID: <c1cb926f-33b0-4433-b54d-954451ed32a8@foss.st.com>



On 3/13/25 17:40, Lee Jones wrote:
> On Wed, 05 Mar 2025, Fabrice Gasnier wrote:
> 
>> Add support for STM32MP25 SoC.
>> A new hardware configuration register (HWCFGR2) has been added, to gather
>> number of capture/compare channels, autonomous mode and input capture
>> capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
>> supports a smaller set of features. This can now be read from HWCFGR
>> registers.
>>
>> Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
>> Update the stm32_lptimer data struct so signal the number of
>> capture/compare channels to the child devices.
>> Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
>> ---
>> Changes in V2:
>> - rely on fallback compatible as no specific .data is associated to the
>>   driver. Compatibility is added by reading hardware configuration
>>   registers.
>> - read version register, to be used by clockevent child driver
>> - rename register/bits definitions
>> ---
>>  drivers/mfd/stm32-lptimer.c       | 33 ++++++++++++++++++++++++++++-
> 
> Looks okay.

Hi Lee,

Thanks for reviewing,

> 
>>  include/linux/mfd/stm32-lptimer.h | 35 ++++++++++++++++++++++++++++---
> 
> Assumingly this patch is not independent of the others?

Please hold on, I'll submit a V4, with some additional bit definition
for the clocksource driver (see my last reply to Daniel).

Best Regards,
Fabrice

> 


From kees at kernel.org  Thu Mar 13 10:17:49 2025
From: kees at kernel.org (Kees Cook)
Date: Thu, 13 Mar 2025 10:17:49 -0700
Subject: [PATCH v4 00/14] Add support for suppressing warning backtraces
In-Reply-To: <20250313114329.284104-1-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
Message-ID: <202503131016.5DCEAEC945@keescook>

On Thu, Mar 13, 2025 at 11:43:15AM +0000, Alessandro Carminati wrote:
> Some unit tests intentionally trigger warning backtraces by passing bad
> parameters to kernel API functions. Such unit tests typically check the
> return value from such calls, not the existence of the warning backtrace.

Thanks for picking this series back up! I honestly thought this had
already landed. :)

> With CONFIG_KUNIT enabled, image size increase with this series applied is
> approximately 1%. The image size increase (and with it the functionality
> introduced by this series) can be avoided by disabling
> CONFIG_KUNIT_SUPPRESS_BACKTRACE.

Yeah, as with my prior review, I'm a fan of this. It makes a bunch of my
very noisy tests much easier to deal with.

-Kees

-- 
Kees Cook


From luis.gerhorst at fau.de  Thu Mar 13 10:29:19 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:29:19 +0100
Subject: [PATCH bpf-next 03/11] bpf: Return -EFAULT on internal errors
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313172919.1103397-1-luis.gerhorst@fau.de>

This prevents us from trying to recover from these on speculative paths
in the future.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 6234d0bb59d6..eb65038682b0 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -11591,7 +11591,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 				verbose(env, "verifier internal error:");
 				verbose(env, "func %s has non-overwritten BPF_PTR_POISON return type\n",
 					func_id_name(func_id));
-				return -EINVAL;
+				return -EFAULT;
 			}
 			ret_btf = btf_vmlinux;
 			ret_btf_id = *fn->ret_btf_id;
@@ -15092,12 +15092,12 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
 	if (WARN_ON_ONCE(ptr_reg)) {
 		print_verifier_state(env, vstate, vstate->curframe, true);
 		verbose(env, "verifier internal error: unexpected ptr_reg\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 	if (WARN_ON(!src_reg)) {
 		print_verifier_state(env, vstate, vstate->curframe, true);
 		verbose(env, "verifier internal error: no src_reg\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 	err = adjust_scalar_min_max_vals(env, insn, dst_reg, *src_reg);
 	if (err)
-- 
2.48.1



From robin.murphy at arm.com  Thu Mar 13 10:31:03 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 17:31:03 +0000
Subject: [PATCH 0/3] Rockchip IOMMU fixes
Message-ID: <cover.1741886382.git.robin.murphy@arm.com>

Hi all,

I was expecting my DT probing change to flush out issues, and it seems
some weaknesses in rockchip-iommu were the first to show. The first two
patches here get things working again for me on my RK3399 NanoPC-T4
(with a console on HDMI exercising the VOP MMU), the 3rd patch just
finishes the cleanup since I was there and could test it.

Thanks,
Robin.

Robin Murphy (3):
  iommu/rockchip: Allocate per-device data sensibly
  iommu/rockchip: Register in a sensible order
  iommu/rockchip: Retire global dma_dev workaround

 drivers/iommu/rockchip-iommu.c | 61 +++++++++++++++-------------------
 1 file changed, 26 insertions(+), 35 deletions(-)

-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Thu Mar 13 10:31:04 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 17:31:04 +0000
Subject: [PATCH 1/3] iommu/rockchip: Allocate per-device data sensibly
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <771e91cf16b3048e93f657153b76905665878fa2.1741886382.git.robin.murphy@arm.com>

Now that DT-based probing is finally happening in the right order again,
it reveals an issue in Rockchip's of_xlate, which can now be called
during registration, but is using the global dma_dev which is only
assigned later. However, this makes little sense when we're already
looking up the correct IOMMU device, who should logically be the owner
of the devm allocation anyway.

Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Tested-by: Anders Roxell <anders.roxell at linaro.org>
Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path")
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/rockchip-iommu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 323cc665c357..48826d1ccfd8 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1148,12 +1148,12 @@ static int rk_iommu_of_xlate(struct device *dev,
 	struct platform_device *iommu_dev;
 	struct rk_iommudata *data;
 
-	data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
+	iommu_dev = of_find_device_by_node(args->np);
+
+	data = devm_kzalloc(&iommu_dev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	iommu_dev = of_find_device_by_node(args->np);
-
 	data->iommu = platform_get_drvdata(iommu_dev);
 	data->iommu->domain = &rk_identity_domain;
 	dev_iommu_priv_set(dev, data);
-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Thu Mar 13 10:31:05 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 17:31:05 +0000
Subject: [PATCH 2/3] iommu/rockchip: Register in a sensible order
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <e69532f00bf49d98322b96788edb7e2e305e4006.1741886382.git.robin.murphy@arm.com>

Currently Rockchip calls iommu_device_register() before it's finished
setting up the hardware and driver state, and as such it now gets
unhappy in various ways when registration starts working the way it was
always intended to, and probing client devices straight away. Reorder
the operations to ensure that what we're registering is a prepared and
functional IOMMU instance.

Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path")
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/rockchip-iommu.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 48826d1ccfd8..9d2120a9232a 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1256,14 +1256,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
-	if (err)
-		goto err_unprepare_clocks;
-
-	err = iommu_device_register(&iommu->iommu, &rk_iommu_ops, dev);
-	if (err)
-		goto err_remove_sysfs;
-
 	/*
 	 * Use the first registered IOMMU device for domain to use with DMA
 	 * API, since a domain might not physically correspond to a single
@@ -1290,12 +1282,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
 	dma_set_mask_and_coherent(dev, rk_ops->dma_bit_mask);
 
+	err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+	if (err)
+		goto err_pm_disable;
+
+	err = iommu_device_register(&iommu->iommu, &rk_iommu_ops, dev);
+	if (err)
+		goto err_remove_sysfs;
+
 	return 0;
-err_pm_disable:
-	pm_runtime_disable(dev);
 err_remove_sysfs:
 	iommu_device_sysfs_remove(&iommu->iommu);
-err_unprepare_clocks:
+err_pm_disable:
+	pm_runtime_disable(dev);
 	clk_bulk_unprepare(iommu->num_clocks, iommu->clocks);
 	return err;
 }
-- 
2.39.2.101.g768bb238c484.dirty



From robin.murphy at arm.com  Thu Mar 13 10:31:06 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 13 Mar 2025 17:31:06 +0000
Subject: [PATCH 3/3] iommu/rockchip: Retire global dma_dev workaround
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <25dc948a7d35c8142c5719ac22bc523f8524d006.1741886382.git.robin.murphy@arm.com>

The global dma_dev trick was mostly because the old domain_alloc op
provided no context, so no way to know which IOMMU was to own the
pagetable, or if a suitable one even existed at all. In the new
multi-instance world with domain_alloc_paging this is no longer a
concern - now we know that the given device must be associated with a
valid IOMMU instance which provided the op to call in the first place,
and therefore that instance can and should be the pagetable owner. To
avoid worrying about the lifetime and stability of the rk_domain->iommus
list, and keep the lookups simple and efficient, we'll still stash a
dma_dev pointer, but now it's accurately per-domain.

Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/rockchip-iommu.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9d2120a9232a..af4cc91b2bbf 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -88,6 +88,7 @@ struct rk_iommu_domain {
 	dma_addr_t dt_dma;
 	spinlock_t iommus_lock; /* lock for iommus list */
 	spinlock_t dt_lock; /* lock for modifying page directory table */
+	struct device *dma_dev;
 
 	struct iommu_domain domain;
 };
@@ -123,7 +124,6 @@ struct rk_iommudata {
 	struct rk_iommu *iommu;
 };
 
-static struct device *dma_dev;
 static const struct rk_iommu_ops *rk_ops;
 static struct iommu_domain rk_identity_domain;
 
@@ -132,7 +132,7 @@ static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
 {
 	size_t size = count * sizeof(u32); /* count of u32 entry */
 
-	dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
+	dma_sync_single_for_device(dom->dma_dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -734,9 +734,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
 	if (!page_table)
 		return ERR_PTR(-ENOMEM);
 
-	pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
-	if (dma_mapping_error(dma_dev, pt_dma)) {
-		dev_err(dma_dev, "DMA mapping error while allocating page table\n");
+	pt_dma = dma_map_single(rk_domain->dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+	if (dma_mapping_error(rk_domain->dma_dev, pt_dma)) {
+		dev_err(rk_domain->dma_dev, "DMA mapping error while allocating page table\n");
 		iommu_free_page(page_table);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -1051,9 +1051,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
 static struct iommu_domain *rk_iommu_domain_alloc_paging(struct device *dev)
 {
 	struct rk_iommu_domain *rk_domain;
-
-	if (!dma_dev)
-		return NULL;
+	struct rk_iommu *iommu;
 
 	rk_domain = kzalloc(sizeof(*rk_domain), GFP_KERNEL);
 	if (!rk_domain)
@@ -1068,10 +1066,12 @@ static struct iommu_domain *rk_iommu_domain_alloc_paging(struct device *dev)
 	if (!rk_domain->dt)
 		goto err_free_domain;
 
-	rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
+	iommu = rk_iommu_from_dev(dev);
+	rk_domain->dma_dev = iommu->dev;
+	rk_domain->dt_dma = dma_map_single(rk_domain->dma_dev, rk_domain->dt,
 					   SPAGE_SIZE, DMA_TO_DEVICE);
-	if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
-		dev_err(dma_dev, "DMA map error for DT\n");
+	if (dma_mapping_error(rk_domain->dma_dev, rk_domain->dt_dma)) {
+		dev_err(rk_domain->dma_dev, "DMA map error for DT\n");
 		goto err_free_dt;
 	}
 
@@ -1105,13 +1105,13 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
 		if (rk_dte_is_pt_valid(dte)) {
 			phys_addr_t pt_phys = rk_ops->pt_address(dte);
 			u32 *page_table = phys_to_virt(pt_phys);
-			dma_unmap_single(dma_dev, pt_phys,
+			dma_unmap_single(rk_domain->dma_dev, pt_phys,
 					 SPAGE_SIZE, DMA_TO_DEVICE);
 			iommu_free_page(page_table);
 		}
 	}
 
-	dma_unmap_single(dma_dev, rk_domain->dt_dma,
+	dma_unmap_single(rk_domain->dma_dev, rk_domain->dt_dma,
 			 SPAGE_SIZE, DMA_TO_DEVICE);
 	iommu_free_page(rk_domain->dt);
 
@@ -1256,14 +1256,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	/*
-	 * Use the first registered IOMMU device for domain to use with DMA
-	 * API, since a domain might not physically correspond to a single
-	 * IOMMU device..
-	 */
-	if (!dma_dev)
-		dma_dev = &pdev->dev;
-
 	pm_runtime_enable(dev);
 
 	for (i = 0; i < iommu->num_irq; i++) {
-- 
2.39.2.101.g768bb238c484.dirty



From minchan at kernel.org  Thu Mar 13 10:33:00 2025
From: minchan at kernel.org (Minchan Kim)
Date: Thu, 13 Mar 2025 10:33:00 -0700
Subject: [PATCH 0/2] Improve Zram by separating compression context from
 kswapd
In-Reply-To: <CAGsJ_4yaSx1vEiZdCouBveeH3D-bQDdvrhRpz=Kbvqn30Eh-nA@mail.gmail.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com>
 <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
 <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com>
 <Z9MCwXzYDRJoTiIr@google.com>
 <CAGsJ_4yaSx1vEiZdCouBveeH3D-bQDdvrhRpz=Kbvqn30Eh-nA@mail.gmail.com>
Message-ID: <Z9MWzDUxUigJrZXt@google.com>

On Fri, Mar 14, 2025 at 05:58:00AM +1300, Barry Song wrote:
> On Fri, Mar 14, 2025 at 5:07?AM Minchan Kim <minchan at kernel.org> wrote:
> >
> > On Thu, Mar 13, 2025 at 04:45:54PM +1300, Barry Song wrote:
> > > On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
> > > <senozhatsky at chromium.org> wrote:
> > > >
> > > > On (25/03/12 11:11), Minchan Kim wrote:
> > > > > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > > > > This patch series introduces a new mechanism called kcompressd to
> > > > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > > > main goal is to separate the tasks of page scanning and page compression
> > > > > > into distinct processes or threads, thereby reducing the load on the
> > > > > > kswapd thread and enhancing overall system performance under high memory
> > > > > > pressure conditions.
> > > > > >
> > > > > > Problem:
> > > > > >  In the current system, the kswapd thread is responsible for both
> > > > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > > > >  combined responsibility can lead to significant performance bottlenecks,
> > > > > >  especially under high memory pressure. The kswapd thread becomes a
> > > > > >  single point of contention, causing delays in memory reclaiming and
> > > > > >  overall system performance degradation.
> > > > >
> > > > > Isn't it general problem if backend for swap is slow(but synchronous)?
> > > > > I think zram need to support asynchrnous IO(can do introduce multiple
> > > > > threads to compress batched pages) and doesn't declare it's
> > > > > synchrnous device for the case.
> > > >
> > > > The current conclusion is that kcompressd will sit above zram,
> > > > because zram is not the only compressing swap backend we have.
> >
> > Then, how handles the file IO case?
> 
> I didn't quite catch your question :-)

Sorry for not clear.

What I meant was zram is also used for fs backend storage, not only
for swapbackend. The multiple simultaneous compression can help the case,
too.

> 
> >
> > >
> > > also. it is not good to hack zram to be aware of if it is kswapd
> > > , direct reclaim , proactive reclaim and block device with
> > > mounted filesystem.
> >
> > Why shouldn't zram be aware of that instead of just introducing
> > queues in the zram with multiple compression threads?
> >
> 
> My view is the opposite of yours :-)
> 
> Integrating kswapd, direct reclaim, etc., into the zram driver
> would violate layering principles. zram is purely a block device

That's the my question. What's the reason zram need to know about
kswapd, direct_reclaim and so on? I didn't understand your input.

> driver, and how it is used should be handled separately. Callers have
> greater flexibility to determine its usage, similar to how different
> I/O models exist in user space.
> 
> Currently, Qun-Wei's patch checks whether the current thread is kswapd.
> If it is, compression is performed asynchronously by threads;
> otherwise, it is done in the current thread. In the future, we may

Okay, then, why should we do that without following normal asynchrnous
disk storage? VM justs put the IO request and sometimes congestion
control. Why is other logic needed for the case?

> have additional reclaim threads, such as for damon or
> madv_pageout, etc.
> 
> > >
> > > so i am thinking sth as below
> > >
> > > page_io.c
> > >
> > > if (sync_device or zswap_enabled())
> > >    schedule swap_writepage to a separate per-node thread
> >
> > I am not sure that's a good idea to mix a feature to solve different
> > layers. That wouldn't be only swap problem. Such an parallelism under
> > device  is common technique these days and it would help file IO cases.
> >
> 
> zswap and zram share the same needs, and handling this in page_io
> can benefit both through common code. It is up to the callers to decide
> the I/O model.
> 
> I agree that "parallelism under the device" is a common technique,
> but our case is different?the device achieves parallelism with
> offload hardware, whereas we rely on CPUs, which can be scarce.
> These threads may also preempt CPUs that are critically needed
> by other non-compression tasks, and burst power consumption
> can sometimes be difficult to control.

That's general problem for common resources in the system and always
trace-off domain in the workload areas. Eng folks has tried to tune
them statically/dynamically depending on system behavior considering
what they priorites.

> 
> > Furthermore, it would open the chance for zram to try compress
> > multiple pages at once.
> 
> We are already in this situation when multiple callers use zram simultaneously,
> such as during direct reclaim or with a mounted filesystem.
> 
> Of course, this allows multiple pages to be compressed simultaneously,
> even if the user is single-threaded. However, determining when to enable
> these threads and whether they will be effective is challenging, as it
> depends on system load. For example, Qun-Wei's patch chose not to use
> threads for direct reclaim as, I guess,  it might be harmful.

Direct reclaim is already harmful and that's why VM has the logic 
to throttle writeback or other special logics for kswapd or direct
reclaim path for th IO, which could be applied into the zram, too.


From luis.gerhorst at fau.de  Thu Mar 13 10:33:26 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:33:26 +0100
Subject: [PATCH bpf-next 04/11] bpf, arm64, powerpc: Add bpf_jit_bypass_spec_v1/v4()
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313173326.1106442-1-luis.gerhorst@fau.de>

JITs can set bpf_jit_bypass_spec_v1/v4() if they want the verifier to
skip analysis/patching for the respective vulnerability. For v4, this
will reduce the number of barriers the verifier inserts. For v1, it
allows more programs to be accepted.

The primary motivation for this is to not regress unpriv BPF's
performance on ARM64 in a future commit where BPF_NOSPEC is also used
against Spectre v1.

This has the user-visible change that v1-induced rejections on
non-vulnerable PowerPC CPUs are avoided.

For now, this does not change the semantics of BPF_NOSPEC. It is still a
v4-only barrier and must not be implemented if bypass_spec_v4 is always
true for the arch. Changing it to a v1 AND v4-barrier is done in a
future commit.

As an alternative to bypass_spec_v1/v4, one could introduce NOSPEC_V1
AND NOSPEC_V4 instructions and allow backends to skip their lowering as
suggested by commit f5e81d111750 ("bpf: Introduce BPF nospec instruction
for mitigating Spectre v4"). Adding bpf_jit_bypass_spec_v1/v4() was
found to be preferrable for the following reason:

* bypass_spec_v1/v4 benefits non-vulnerable CPUs: Always performing the
  same analysis (not taking into account whether the current CPU is
  vulnerable), needlessly restricts users of CPUs that are not
  vulnerable. The only usecase for this would be portability-testing,
  but this can later be added easily when needed by allowing users to
  force bypass_spec_v1/v4 to false.

* Portability is still acceptable: Directly disabling the analysis
  instead of skipping the lowering of BPF_NOSPEC(_V1/V4) might allow
  programs on non-vulnerable CPUs to be accepted while the program will
  be rejected on vulnerable CPUs. With the fallback to speculation
  barriers for Spectre v1 implemented in a future commit, this will only
  affect programs that do variable stack-accesses or are very complex.

For PowerPC, the SEC_FTR checking in bpf_jit_bypass_spec_v4() is based
on the check that was previously located in the BPF_NOSPEC case.

For LoongArch, it would likely be safe to set both
bpf_jit_bypass_spec_v1() and _v4() according to
commit?a6f6a95f2580 ("LoongArch, bpf: Fix jit to skip speculation
barrier opcode"). This is omitted here as I am unable to do any testing
for LoongArch.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Cc: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 arch/arm64/net/bpf_jit_comp.c     | 21 ++++++++++++---------
 arch/powerpc/net/bpf_jit_comp64.c | 21 +++++++++++++++++----
 include/linux/bpf.h               | 11 +++++++++--
 kernel/bpf/core.c                 | 15 +++++++++++++++
 4 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 70d7c89d3ac9..0f617b55866e 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1583,15 +1583,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
 
 	/* speculation barrier */
 	case BPF_ST | BPF_NOSPEC:
-		/*
-		 * Nothing required here.
-		 *
-		 * In case of arm64, we rely on the firmware mitigation of
-		 * Speculative Store Bypass as controlled via the ssbd kernel
-		 * parameter. Whenever the mitigation is enabled, it works
-		 * for all of the kernel code with no need to provide any
-		 * additional instructions.
-		 */
+		/* See bpf_jit_bypass_spec_v4() */
 		break;
 
 	/* ST: *(size *)(dst + off) = imm */
@@ -2762,6 +2754,17 @@ bool bpf_jit_supports_percpu_insn(void)
 	return true;
 }
 
+bool bpf_jit_bypass_spec_v4(void)
+{
+	/* In case of arm64, we rely on the firmware mitigation of Speculative
+	 * Store Bypass as controlled via the ssbd kernel parameter. Whenever
+	 * the mitigation is enabled, it works for all of the kernel code with
+	 * no need to provide any additional instructions. Therefore, skip
+	 * inserting nospec insns against Spectre v4.
+	 */
+	return true;
+}
+
 bool bpf_jit_inlines_helper_call(s32 imm)
 {
 	switch (imm) {
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 233703b06d7c..b5339c541283 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -363,6 +363,23 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 	return 0;
 }
 
+bool bpf_jit_bypass_spec_v1(void)
+{
+#if defined(CONFIG_PPC_E500) || defined(CONFIG_PPC_BOOK3S_64)
+	return !(security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR));
+#else
+	return true;
+#endif
+}
+
+bool bpf_jit_bypass_spec_v4(void)
+{
+	return !(security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_STF_BARRIER) &&
+		 stf_barrier_type_get() != STF_BARRIER_NONE);
+}
+
 /*
  * We spill into the redzone always, even if the bpf program has its own stackframe.
  * Offsets hardcoded based on BPF_PPC_STACK_SAVE -- see bpf_jit_stack_local()
@@ -785,10 +802,6 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
 		 * BPF_ST NOSPEC (speculation barrier)
 		 */
 		case BPF_ST | BPF_NOSPEC:
-			if (!security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) ||
-					!security_ftr_enabled(SEC_FTR_STF_BARRIER))
-				break;
-
 			switch (stf_barrier) {
 			case STF_BARRIER_EIEIO:
 				EMIT(PPC_RAW_EIEIO() | 0x02000000);
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 7d55553de3fc..9a21e356e04e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2439,14 +2439,21 @@ static inline bool bpf_allow_uninit_stack(const struct bpf_token *token)
 	return bpf_token_capable(token, CAP_PERFMON);
 }
 
+bool bpf_jit_bypass_spec_v1(void);
+bool bpf_jit_bypass_spec_v4(void);
+
 static inline bool bpf_bypass_spec_v1(const struct bpf_token *token)
 {
-	return cpu_mitigations_off() || bpf_token_capable(token, CAP_PERFMON);
+	return bpf_jit_bypass_spec_v1() ||
+		cpu_mitigations_off() ||
+		bpf_token_capable(token, CAP_PERFMON);
 }
 
 static inline bool bpf_bypass_spec_v4(const struct bpf_token *token)
 {
-	return cpu_mitigations_off() || bpf_token_capable(token, CAP_PERFMON);
+	return bpf_jit_bypass_spec_v4() ||
+		cpu_mitigations_off() ||
+		bpf_token_capable(token, CAP_PERFMON);
 }
 
 int bpf_map_new_fd(struct bpf_map *map, int flags);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 62cb9557ad3b..a3e434851614 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -3024,6 +3024,21 @@ bool __weak bpf_jit_needs_zext(void)
 	return false;
 }
 
+/* By default, enable the verifier's mitigations against Spectre v1 and v4 for
+ * all archs. The value returned must not change at runtime as there is
+ * currently no support for reloading programs that were loaded without
+ * mitigations.
+ */
+bool __weak bpf_jit_bypass_spec_v1(void)
+{
+	return false;
+}
+
+bool __weak bpf_jit_bypass_spec_v4(void)
+{
+	return false;
+}
+
 /* Return true if the JIT inlines the call to the helper corresponding to
  * the imm.
  *
-- 
2.48.1



From maz at kernel.org  Thu Mar 13 10:34:46 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 17:34:46 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313104111.24196-3-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
	<20250313104111.24196-3-miko.lenczewski@arm.com>
Message-ID: <86ikocomvd.wl-maz@kernel.org>

On Thu, 13 Mar 2025 10:41:10 +0000,
Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> 
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f7..9728faa10390 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>  		{}
>  	},
>  };
> @@ -246,6 +247,7 @@ static const struct {
>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },

Why is that a SW feature? This looks very much like a HW feature to
me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
with it. Something like:

diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index c6b185b885f70..803a0c99f7b46 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
 	.override	= &id_aa64mmfr2_override,
 	.fields		= {
 		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
+		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
 		{}
 	},
 };
@@ -246,6 +247,7 @@ static const struct {
 	{ "rodata=off",			"arm64_sw.rodataoff=1" },
 	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
 	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
+	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
 };
 
 static int __init parse_hexdigit(const char *p, u64 *v)


Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From christopher.obbard at linaro.org  Thu Mar 13 10:34:46 2025
From: christopher.obbard at linaro.org (Christopher Obbard)
Date: Thu, 13 Mar 2025 17:34:46 +0000
Subject: [PATCH] arm64: defconfig: Enable Qualcomm interconnects as built-in
In-Reply-To: <Z9HjMyjzE9XlqrEj@x1>
References: <20250311-wip-obbardc-qcom-defconfig-interconnects-builtin-v1-1-675b6bc57176@linaro.org>
 <CACr-zFC=mPNeeHMp9XnSby+cMQaPWt_3s8iUiCN+EnVPeGad8Q@mail.gmail.com>
 <uljqxwfgl26txrfqvkvzzpj6qurgmwcbuot7gu2u6rwjaqgncb@jeuyi4mexjff>
 <CACr-zFDSFizYmrVN-dV334n1kq17UB9k4FxrV20NNQCQMhzrwg@mail.gmail.com>
 <92dd35a2-d1cc-4f2b-b3a8-5752ec33b0d3@kernel.org> <CACr-zFCYWEFPO8yExp_8hOQdVtC9Zwu1ZOZNksSeyyS6Ht0e9A@mail.gmail.com>
 <Z9HjMyjzE9XlqrEj@x1>
Message-ID: <CACr-zFAHGcQtwSz0EF0kt7_PUXxwi3GZY2BmAVedbLjh3+4LhA@mail.gmail.com>

Hi Brian,

On Wed, 12 Mar 2025 at 19:40, Brian Masney <bmasney at redhat.com> wrote:
>
> Hi Christopher,
>
> On Wed, Mar 12, 2025 at 12:10:56PM +0100, Christopher Obbard wrote:
> > For reference, I am working on updating initramfs generation tools in
> > Debian/Fedora to include the required interconnect modules. Currently
> > the interconnect drivers are built as modules in these distros, but
> > are not included in the initrd. That is where my confusion initially
> > stemmed from.
>
> From a Fedora and centos-stream-9/10 perspective, we have dracut
> updated so that the interconnect modules are included in the initramfs
> by default.
>
> https://github.com/dracutdevs/dracut/blob/master/modules.d/90kernel-modules/module-setup.sh#L74
>
> Let me know if you are seeing a specific issue with the initramfs on
> Fedora and I can help you.

Awesome, turns out I am wrong and the interconnect drivers are in fact
present in the latest nightly Fedora 42 image I am testing:

$ lsinitramfs initramfs-6.14.0-0.rc3.29.fc42.aarch64.img  | grep interconnect
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx/imx-interconnect.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx/imx8mm-interconnect.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx/imx8mn-interconnect.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx/imx8mp-interconnect.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/imx/imx8mq-interconnect.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/icc-osm-l3.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/icc-smd-rpm.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-msm8916.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-msm8953.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-msm8996.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-qcm2290.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sa8775p.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sc7280.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sc8180x.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sc8280xp.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sdm845.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sdx75.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sm6115.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sm8150.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sm8250.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-sm8450.ko.xz
usr/lib/modules/6.14.0-0.rc3.29.fc42.aarch64/kernel/drivers/interconnect/qcom/qnoc-x1e80100.ko.xz



Thanks,

Chris


From ryan.roberts at arm.com  Thu Mar 13 10:36:17 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 17:36:17 +0000
Subject: [v3 PATCH 0/6] arm64: support FEAT_BBM level 2 and large block
 mapping when rodata=full
In-Reply-To: <3750d3f8-17c6-4bb8-8107-215d442e4ec3@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <3750d3f8-17c6-4bb8-8107-215d442e4ec3@os.amperecomputing.com>
Message-ID: <2fb974bb-1470-4a5f-90d5-97456140c98f@arm.com>

On 13/03/2025 17:28, Yang Shi wrote:
> Hi Ryan,
> 
> I saw Miko posted a new spin of his patches. There are some slight changes that
> have impact to my patches (basically check the new boot parameter). Do you
> prefer I rebase my patches on top of his new spin right now then restart review
> from the new spin or review the current patches then solve the new review
> comments and rebase to Miko's new spin together?

Hi Yang,

Sorry I haven't got to reviewing this version yet, it's in my queue!

I'm happy to review against v3 as it is. I'm familiar with Miko's series and am
not too bothered about the integration with that; I think it's pretty straight
forward. I'm more interested in how you are handling the splitting, which I
think is the bulk of the effort.

I'm hoping to get to this next week before heading out to LSF/MM the following
week (might I see you there?)

Thanks,
Ryan


> 
> Thanks,
> Yang
> 
> 
> On 3/4/25 2:19 PM, Yang Shi wrote:
>> Changelog
>> =========
>> v3:
>> ?? * Rebased to v6.14-rc4.
>> ?? * Based on Miko's BBML2 cpufeature patch (https://lore.kernel.org/linux-
>> arm-kernel/20250228182403.6269-3-miko.lenczewski at arm.com/).
>> ???? Also included in this series in order to have the complete patchset.
>> ?? * Enhanced __create_pgd_mapping() to handle split as well per Ryan.
>> ?? * Supported CONT mappings per Ryan.
>> ?? * Supported asymmetric system by splitting kernel linear mapping if such
>> ???? system is detected per Ryan. I don't have such system to test, so the
>> ???? testing is done by hacking kernel to call linear mapping repainting
>> ???? unconditionally. The linear mapping doesn't have any block and cont
>> ???? mappings after booting.
>>
>> RFC v2:
>> ?? * Used allowlist to advertise BBM lv2 on the CPUs which can handle TLB
>> ???? conflict gracefully per Will Deacon
>> ?? * Rebased onto v6.13-rc5
>> ?? * https://lore.kernel.org/linux-arm-kernel/20250103011822.1257189-1-
>> yang at os.amperecomputing.com/
>>
>> RFC v1: https://lore.kernel.org/lkml/20241118181711.962576-1-
>> yang at os.amperecomputing.com/
>>
>> Description
>> ===========
>> When rodata=full kernel linear mapping is mapped by PTE due to arm's
>> break-before-make rule.
>>
>> A number of performance issues arise when the kernel linear map is using
>> PTE entries due to arm's break-before-make rule:
>> ?? - performance degradation
>> ?? - more TLB pressure
>> ?? - memory waste for kernel page table
>>
>> These issues can be avoided by specifying rodata=on the kernel command
>> line but this disables the alias checks on page table permissions and
>> therefore compromises security somewhat.
>>
>> With FEAT_BBM level 2 support it is no longer necessary to invalidate the
>> page table entry when changing page sizes.? This allows the kernel to
>> split large mappings after boot is complete.
>>
>> This patch adds support for splitting large mappings when FEAT_BBM level 2
>> is available and rodata=full is used. This functionality will be used
>> when modifying page permissions for individual page frames.
>>
>> Without FEAT_BBM level 2 we will keep the kernel linear map using PTEs
>> only.
>>
>> If the system is asymmetric, the kernel linear mapping may be repainted once
>> the BBML2 capability is finalized on all CPUs.? See patch #6 for more details.
>>
>> We saw significant performance increases in some benchmarks with
>> rodata=full without compromising the security features of the kernel.
>>
>> Testing
>> =======
>> The test was done on AmpereOne machine (192 cores, 1P) with 256GB memory and
>> 4K page size + 48 bit VA.
>>
>> Function test (4K/16K/64K page size)
>> ?? - Kernel boot.? Kernel needs change kernel linear mapping permission at
>> ???? boot stage, if the patch didn't work, kernel typically didn't boot.
>> ?? - Module stress from stress-ng. Kernel module load change permission for
>> ???? linear mapping.
>> ?? - A test kernel module which allocates 80% of total memory via vmalloc(),
>> ???? then change the vmalloc area permission to RO, this also change linear
>> ???? mapping permission to RO, then change it back before vfree(). Then launch
>> ???? a VM which consumes almost all physical memory.
>> ?? - VM with the patchset applied in guest kernel too.
>> ?? - Kernel build in VM with guest kernel which has this series applied.
>> ?? - rodata=on. Make sure other rodata mode is not broken.
>> ?? - Boot on the machine which doesn't support BBML2.
>>
>> Performance
>> ===========
>> Memory consumption
>> Before:
>> MemTotal:?????? 258988984 kB
>> MemFree:??????? 254821700 kB
>>
>> After:
>> MemTotal:?????? 259505132 kB
>> MemFree:??????? 255410264 kB
>>
>> Around 500MB more memory are free to use.? The larger the machine, the
>> more memory saved.
>>
>> Performance benchmarking
>> * Memcached
>> We saw performance degradation when running Memcached benchmark with
>> rodata=full vs rodata=on.? Our profiling pointed to kernel TLB pressure.
>> With this patchset we saw ops/sec is increased by around 3.5%, P99
>> latency is reduced by around 9.6%.
>> The gain mainly came from reduced kernel TLB misses.? The kernel TLB
>> MPKI is reduced by 28.5%.
>>
>> The benchmark data is now on par with rodata=on too.
>>
>> * Disk encryption (dm-crypt) benchmark
>> Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
>> encryption (by dm-crypt).
>> fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
>> ???? --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
>> ???? --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
>> ???? --name=iops-test-job --eta-newline=1 --size 100G
>>
>> The IOPS is increased by 90% - 150% (the variance is high, but the worst
>> number of good case is around 90% more than the best number of bad case).
>> The bandwidth is increased and the avg clat is reduced proportionally.
>>
>> * Sequential file read
>> Read 100G file sequentially on XFS (xfs_io read with page cache populated).
>> The bandwidth is increased by 150%.
>>
>>
>> Miko?aj Lenczewski (1):
>> ?????? arm64: Add BBM Level 2 cpu feature
>>
>> Yang Shi (5):
>> ?????? arm64: cpufeature: add AmpereOne to BBML2 allow list
>> ?????? arm64: mm: make __create_pgd_mapping() and helpers non-void
>> ?????? arm64: mm: support large block mapping when rodata=full
>> ?????? arm64: mm: support split CONT mappings
>> ?????? arm64: mm: split linear mapping if BBML2 is not supported on secondary
>> CPUs
>>
>> ? arch/arm64/Kconfig????????????????? |? 11 +++++
>> ? arch/arm64/include/asm/cpucaps.h??? |?? 2 +
>> ? arch/arm64/include/asm/cpufeature.h |? 15 ++++++
>> ? arch/arm64/include/asm/mmu.h??????? |?? 4 ++
>> ? arch/arm64/include/asm/pgtable.h??? |? 12 ++++-
>> ? arch/arm64/kernel/cpufeature.c????? |? 95 +++++++++++++++++++++++++++++++++++++
>> ? arch/arm64/mm/mmu.c???????????????? | 397 ++++++++++++++++++++++++++++++++++
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> ++++++++++++++++++++++-------------------
>> ? arch/arm64/mm/pageattr.c??????????? |? 37 ++++++++++++---
>> ? arch/arm64/tools/cpucaps??????????? |?? 1 +
>> ? 9 files changed, 518 insertions(+), 56 deletions(-)
>>
>>
> 



From quic_philber at quicinc.com  Thu Mar 13 10:36:56 2025
From: quic_philber at quicinc.com (Peter Hilber)
Date: Thu, 13 Mar 2025 18:36:56 +0100
Subject: [PATCH v6 0/4] Add virtio_rtc module
Message-ID: <20250313173707.1492-1-quic_philber@quicinc.com>

This series implements a driver for a virtio-rtc device conforming to spec
proposal v8 [1]. It includes a PTP clock driver and an RTC class driver
with alarm.

v6 updates
==========

v6 fixes the PTP clock name length, and a few style issues, some of which
resulted in warnings.

Overview
========

This patch series adds the virtio_rtc module, and related bugfixes. The
virtio_rtc module implements a driver compatible with the proposed Virtio
RTC device specification [1]. The Virtio RTC (Real Time Clock) device
provides information about current time. The device can provide different
clocks, e.g. for the UTC or TAI time standards, or for physical time
elapsed since some past epoch. The driver can read the clocks with simple
or more accurate methods. Optionally, the driver can set an alarm.

For the Virtio RTC device, there is currently a proprietary implementation,
which has been used for testing.

PTP clock interface
===================

virtio_rtc exposes clocks as PTP clocks to userspace, similar to ptp_kvm.
If both the Virtio RTC device and this driver have special support for the
current clocksource, time synchronization programs can use
cross-timestamping using ioctl PTP_SYS_OFFSET_PRECISE2 aka
PTP_SYS_OFFSET_PRECISE. Similar to ptp_kvm, system time synchronization
with single-digit ns precision is possible with a quiescent reference clock
(from the Virtio RTC device). This works even when the Virtio device
response is slow compared to ptp_kvm hypercalls.

The following illustrates a test using PTP_SYS_OFFSET_PRECISE, with
interspersed strace log and chrony [2] refclocks log, on arm64. In the
example, chrony tracks a virtio_rtc PTP clock ("PHCV", /dev/ptp0). The raw
offset between the virtio_rtc clock and CLOCK_REALTIME is 0 to 1 ns. At the
device side, the Virtio RTC device artificially delays both the clock read
request, and the response, by 50 ms. Cross-timestamp interpolation still
works with this delay. chrony also monitors a ptp_kvm clock ("PHCK",
/dev/ptp3) for comparison, which yields a similar offset.

	ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000329>
	===============================================================================
	   Date (UTC) Time         Refid  DP L P  Raw offset   Cooked offset      Disp.
	===============================================================================
	2023-06-29 18:49:55.595742 PHCK    0 N 0  1.000000e-09  8.717931e-10  5.500e-08
	2023-06-29 18:49:55.595742 PHCK    - N -       -        8.717931e-10  5.500e-08
	ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101545>
	2023-06-29 18:49:56.147766 PHCV    0 N 0  1.000000e-09  8.801870e-10  5.500e-08
	2023-06-29 18:49:56.147766 PHCV    - N -       -        8.801870e-10  5.500e-08
	ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000195>
	2023-06-29 18:49:56.202446 PHCK    0 N 0  1.000000e-09  7.364180e-10  5.500e-08
	2023-06-29 18:49:56.202446 PHCK    - N -       -        7.364180e-10  5.500e-08
	ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101484>
	2023-06-29 18:49:56.754641 PHCV    0 N 0  0.000000e+00 -2.617368e-10  5.500e-08
	2023-06-29 18:49:56.754641 PHCV    - N -       -       -2.617368e-10  5.500e-08
	ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000270>
	2023-06-29 18:49:56.809282 PHCK    0 N 0  1.000000e-09  7.779321e-10  5.500e-08
	2023-06-29 18:49:56.809282 PHCK    - N -       -        7.779321e-10  5.500e-08
	ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101510>
	2023-06-29 18:49:57.361376 PHCV    0 N 0  0.000000e+00 -2.198794e-10  5.500e-08
	2023-06-29 18:49:57.361376 PHCV    - N -       -       -2.198794e-10  5.500e-08

This patch series only adds special support for the Arm Generic Timer
clocksource. At the driver side, it should be easy to support more
clocksources.

Fallback PTP clock interface
----------------------------

Without special support for the current clocksource, time synchronization
programs can still use ioctl PTP_SYS_OFFSET_EXTENDED2 aka
PTP_SYS_OFFSET_EXTENDED. In this case, precision will generally be worse
and will depend on the Virtio device response characteristics.

The following illustrates a test using PTP_SYS_OFFSET_EXTENDED, with
interspersed strace log and chrony refclocks log, on x86-64 (with `ts'
values omitted):

	ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
	===============================================================================
	   Date (UTC) Time         Refid  DP L P  Raw offset   Cooked offset      Disp.
	===============================================================================
	2023-06-28 14:11:26.697782 PHCV    0 N 0  3.318200e-05  3.450891e-05  4.611e-06
	2023-06-28 14:11:26.697782 PHCV    - N -       -        3.450891e-05  4.611e-06
	ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
	2023-06-28 14:11:27.208763 PHCV    0 N 0 -3.792800e-05 -4.023965e-05  4.611e-06
	2023-06-28 14:11:27.208763 PHCV    - N -       -       -4.023965e-05  4.611e-06
	ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
	2023-06-28 14:11:27.722818 PHCV    0 N 0 -3.328600e-05 -3.134404e-05  4.611e-06
	2023-06-28 14:11:27.722818 PHCV    - N -       -       -3.134404e-05  4.611e-06
	ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
	2023-06-28 14:11:28.233572 PHCV    0 N 0 -4.966900e-05 -4.584331e-05  4.611e-06
	2023-06-28 14:11:28.233572 PHCV    - N -       -       -4.584331e-05  4.611e-06
	ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
	2023-06-28 14:11:28.742737 PHCV    0 N 0  4.902700e-05  5.361388e-05  4.611e-06
	2023-06-28 14:11:28.742737 PHCV    - N -       -        5.361388e-05  4.611e-06

PTP clock setup
---------------

The following udev rule can be used to get a symlink /dev/ptp_virtio to the
UTC clock:

	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 0/variant 0", SYMLINK += "ptp_virtio"

The following chrony configuration directive can then be added in
/etc/chrony/chrony.conf to synchronize to the Virtio UTC clock:

	refclock PHC /dev/ptp_virtio refid PHCV poll -1 dpoll -1

RTC interface
=============

This patch series adds virtio_rtc as a generic Virtio driver, including
both a PTP clock driver and an RTC class driver.

Feedback is greatly appreciated.

[1] https://lore.kernel.org/virtio-comment/20250306095112.1293-1-quic_philber at quicinc.com/
[2] https://chrony.tuxfamily.org/

Changelog
=========

v6:

- Shorten PTP clock names to always fit into 32 bytes.

- Fix sparse warning about endianness mismatch (Simon Horman).

- Do not mark comments missing parameter documentation as kernel doc (Simon
  Horman).

- Improve error status computation readability.

- Avoid conditional locking within a block.

v5:

- Update to virtio-rtc spec v7, essentially removing definitions.

- Fix multiple bugs after readying device during probe and restore.

- Actually initialize Virtio clock id for RTC class device.

- Add freeze/restore ops already in first patch.

- Minor changes:

  - Use new APIs devm_device_init_wakeup(), secs_to_jiffies().

  - Fix style issues.

  - Improve logging types and clarity.

  - Drop unnecessary memory barrier pair.

  - Return error status from device, whenever available.

v4:

- Update Virtio interface to spec v6.

- Distinguish UTC-like clocks by handling of leap seconds (spec v6).

- Do not create RTC class device for clocks which may step on leap seconds
  (Alexandre Belloni).

- Clear RTC class feature bit instead of defining reduced ops
  (Alexandre Belloni).

- For PTP clock name, always use numeric clock type, and numeric variant.

- Use macros for 64-bit divisions.

- Remove unnecessary memory barriers.

- Cosmetic improvements.

- Drop upstreamed timekeeping bugfixes from series.

v3:

- Update to conform to virtio spec RFC v3 (no significant behavioral
  changes).

- Add RTC class driver with alarm according to virtio spec RFC v3.

- For cross-timestamp corner case fix, switch back to v1 style closed
  interval test (Thomas Gleixner).

v2:

- Depend on patch series "treewide: Use clocksource id for
  get_device_system_crosststamp()" to avoid requiring a clocksource pointer
  with get_device_system_crosststamp().

- Assume Arm Generic Timer will use CP15 virtual counter. Drop
  arm_arch_timer helper functions (Marc Zyngier).

- Improve cross-timestamp fixes problem description and implementation
  (John Stultz).


Peter Hilber (4):
  virtio_rtc: Add module and driver core
  virtio_rtc: Add PTP clocks
  virtio_rtc: Add Arm Generic Timer cross-timestamping
  virtio_rtc: Add RTC class driver

 MAINTAINERS                          |    7 +
 drivers/virtio/Kconfig               |   64 ++
 drivers/virtio/Makefile              |    5 +
 drivers/virtio/virtio_rtc_arm.c      |   23 +
 drivers/virtio/virtio_rtc_class.c    |  262 +++++
 drivers/virtio/virtio_rtc_driver.c   | 1407 ++++++++++++++++++++++++++
 drivers/virtio/virtio_rtc_internal.h |  122 +++
 drivers/virtio/virtio_rtc_ptp.c      |  347 +++++++
 include/uapi/linux/virtio_rtc.h      |  237 +++++
 9 files changed, 2474 insertions(+)
 create mode 100644 drivers/virtio/virtio_rtc_arm.c
 create mode 100644 drivers/virtio/virtio_rtc_class.c
 create mode 100644 drivers/virtio/virtio_rtc_driver.c
 create mode 100644 drivers/virtio/virtio_rtc_internal.h
 create mode 100644 drivers/virtio/virtio_rtc_ptp.c
 create mode 100644 include/uapi/linux/virtio_rtc.h


base-commit: 9d8960672d63db4b3b04542f5622748b345c637a
-- 
2.43.0



From quic_philber at quicinc.com  Thu Mar 13 10:36:57 2025
From: quic_philber at quicinc.com (Peter Hilber)
Date: Thu, 13 Mar 2025 18:36:57 +0100
Subject: [PATCH v6 1/4] virtio_rtc: Add module and driver core
In-Reply-To: <20250313173707.1492-1-quic_philber@quicinc.com>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
Message-ID: <20250313173707.1492-2-quic_philber@quicinc.com>

Add the virtio_rtc module and driver core. The virtio_rtc module implements
a driver compatible with the proposed Virtio RTC device specification.
The Virtio RTC (Real Time Clock) device provides information about current
time. The device can provide different clocks, e.g. for the UTC or TAI time
standards, or for physical time elapsed since some past epoch. The driver
can read the clocks with simple or more accurate methods.

Implement the core, which interacts with the Virtio RTC device. Apart from
this, the core does not expose functionality outside of the virtio_rtc
module. Follow-up patches will expose PTP clocks and an RTC Class device.

Provide synchronous messaging, which is enough for the expected time
synchronization use cases through PTP clocks (similar to ptp_kvm) or RTC
Class device.

Signed-off-by: Peter Hilber <quic_philber at quicinc.com>
---

Notes:
    v6:
    
    - Fix sparse warning about endianness mismatch (Simon Horman).
    
    - Improve error status computation readability.
    
    v5:
    
    - Remove definitions dropped in virtio-rtc spec v7.
    
    - Fix style issues.
    
    - Add freeze/restore ops already in this patch.
    
    - Drop unnecessary memory barrier pair.
    
    - Return error status from device, whenever available.
    
    - Use secs_to_jiffies() macro.
    
    v4:
    
    - Update Virtio interface to spec v6.
    
    - Distinguish UTC-like clocks by handling of leap seconds (spec v6).
    
    - Remove unnecessary memory barriers.
    
    - Cosmetic improvements.
    
    v3:
    
    - merge readq and controlq into a single requestq (spec v3)
    
    - don't guard cross-timestamping with feature bit (spec v3)
    
    - pad message headers to 64 bits (spec v3)
    
    - reduce clock id to 16 bits (spec v3)
    
    - change Virtio status codes (spec v3)
    
    - use 'VIRTIO_RTC_REQ_' prefix for request messages (spec v3)

 MAINTAINERS                          |   7 +
 drivers/virtio/Kconfig               |  13 +
 drivers/virtio/Makefile              |   2 +
 drivers/virtio/virtio_rtc_driver.c   | 786 +++++++++++++++++++++++++++
 drivers/virtio/virtio_rtc_internal.h |  24 +
 include/uapi/linux/virtio_rtc.h      | 151 +++++
 6 files changed, 983 insertions(+)
 create mode 100644 drivers/virtio/virtio_rtc_driver.c
 create mode 100644 drivers/virtio/virtio_rtc_internal.h
 create mode 100644 include/uapi/linux/virtio_rtc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4ff26fa94895..3bdc21b47f87 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25201,6 +25201,13 @@ S:	Maintained
 F:	drivers/nvdimm/nd_virtio.c
 F:	drivers/nvdimm/virtio_pmem.c
 
+VIRTIO RTC DRIVER
+M:	Peter Hilber <quic_philber at quicinc.com>
+L:	virtualization at lists.linux.dev
+S:	Maintained
+F:	drivers/virtio/virtio_rtc_*
+F:	include/uapi/linux/virtio_rtc.h
+
 VIRTIO SOUND DRIVER
 M:	Anton Yakovlev <anton.yakovlev at opensynergy.com>
 M:	"Michael S. Tsirkin" <mst at redhat.com>
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 2eb747311bfd..83bcb06acb6c 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -188,4 +188,17 @@ config VIRTIO_DEBUG
 
 	  If unsure, say N.
 
+config VIRTIO_RTC
+	tristate "Virtio RTC driver"
+	depends on VIRTIO
+	depends on PTP_1588_CLOCK_OPTIONAL
+	help
+	 This driver provides current time from a Virtio RTC device. The driver
+	 provides the time through one or more clocks.
+
+	 To compile this code as a module, choose M here: the module will be
+	 called virtio_rtc.
+
+	 If unsure, say M.
+
 endif # VIRTIO_MENU
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 58b2b0489fc9..c41c4c0f9264 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -14,3 +14,5 @@ obj-$(CONFIG_VIRTIO_VDPA) += virtio_vdpa.o
 obj-$(CONFIG_VIRTIO_MEM) += virtio_mem.o
 obj-$(CONFIG_VIRTIO_DMA_SHARED_BUFFER) += virtio_dma_buf.o
 obj-$(CONFIG_VIRTIO_DEBUG) += virtio_debug.o
+obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o
+virtio_rtc-y := virtio_rtc_driver.o
diff --git a/drivers/virtio/virtio_rtc_driver.c b/drivers/virtio/virtio_rtc_driver.c
new file mode 100644
index 000000000000..c87ee4e63424
--- /dev/null
+++ b/drivers/virtio/virtio_rtc_driver.c
@@ -0,0 +1,786 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * virtio_rtc driver core
+ *
+ * Copyright (C) 2022-2024 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ids.h>
+
+#include <uapi/linux/virtio_rtc.h>
+
+#include "virtio_rtc_internal.h"
+
+/* virtqueue order */
+enum {
+	VIORTC_REQUESTQ,
+	VIORTC_MAX_NR_QUEUES,
+};
+
+/**
+ * struct viortc_vq - virtqueue abstraction
+ * @vq: virtqueue
+ * @lock: protects access to vq
+ */
+struct viortc_vq {
+	struct virtqueue *vq;
+	spinlock_t lock;
+};
+
+/**
+ * struct viortc_dev - virtio_rtc device data
+ * @vdev: virtio device
+ * @vqs: virtqueues
+ * @num_clocks: # of virtio_rtc clocks
+ */
+struct viortc_dev {
+	struct virtio_device *vdev;
+	struct viortc_vq vqs[VIORTC_MAX_NR_QUEUES];
+	u16 num_clocks;
+};
+
+/**
+ * struct viortc_msg - Message requested by driver, responded by device.
+ * @viortc: device data
+ * @req: request buffer
+ * @resp: response buffer
+ * @responded: vqueue callback signals response reception
+ * @refcnt: Message reference count, message and buffers will be deallocated
+ *	    once 0. refcnt is decremented in the vqueue callback and in the
+ *	    thread waiting on the responded completion.
+ *          If a message response wait function times out, the message will be
+ *          freed upon late reception (refcnt will reach 0 in the callback), or
+ *          device removal.
+ * @req_size: size of request in bytes
+ * @resp_cap: maximum size of response in bytes
+ * @resp_actual_size: actual size of response
+ */
+struct viortc_msg {
+	struct viortc_dev *viortc;
+	void *req;
+	void *resp;
+	struct completion responded;
+	refcount_t refcnt;
+	unsigned int req_size;
+	unsigned int resp_cap;
+	unsigned int resp_actual_size;
+};
+
+/**
+ * viortc_msg_init() - Allocate and initialize requestq message.
+ * @viortc: device data
+ * @msg_type: virtio_rtc message type
+ * @req_size: size of request buffer to be allocated
+ * @resp_cap: size of response buffer to be allocated
+ *
+ * Initializes the message refcnt to 2. The refcnt will be decremented once in
+ * the virtqueue callback, and once in the thread waiting on the message (on
+ * completion or timeout).
+ *
+ * Context: Process context.
+ * Return: non-NULL on success.
+ */
+static struct viortc_msg *viortc_msg_init(struct viortc_dev *viortc,
+					  u16 msg_type, unsigned int req_size,
+					  unsigned int resp_cap)
+{
+	struct device *dev = &viortc->vdev->dev;
+	struct virtio_rtc_req_head *req_head;
+	struct viortc_msg *msg;
+
+	msg = devm_kzalloc(dev, sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return NULL;
+
+	init_completion(&msg->responded);
+
+	msg->req = devm_kzalloc(dev, req_size, GFP_KERNEL);
+	if (!msg->req)
+		goto err_free_msg;
+
+	req_head = msg->req;
+
+	msg->resp = devm_kzalloc(dev, resp_cap, GFP_KERNEL);
+	if (!msg->resp)
+		goto err_free_msg_req;
+
+	msg->viortc = viortc;
+	msg->req_size = req_size;
+	msg->resp_cap = resp_cap;
+
+	refcount_set(&msg->refcnt, 2);
+
+	req_head->msg_type = virtio_cpu_to_le(msg_type, req_head->msg_type);
+
+	return msg;
+
+err_free_msg_req:
+	devm_kfree(dev, msg->req);
+
+err_free_msg:
+	devm_kfree(dev, msg);
+
+	return NULL;
+}
+
+/**
+ * viortc_msg_release() - Decrement message refcnt, potentially free message.
+ * @msg: message requested by driver
+ *
+ * Context: Any context.
+ */
+static void viortc_msg_release(struct viortc_msg *msg)
+{
+	struct device *dev;
+
+	if (refcount_dec_and_test(&msg->refcnt)) {
+		dev = &msg->viortc->vdev->dev;
+
+		devm_kfree(dev, msg->req);
+		devm_kfree(dev, msg->resp);
+		devm_kfree(dev, msg);
+	}
+}
+
+/**
+ * viortc_do_cb() - generic virtqueue callback logic
+ * @vq: virtqueue
+ * @handle_buf: function to process a used buffer
+ *
+ * Context: virtqueue callback, typically interrupt. Takes and releases vq lock.
+ */
+static void viortc_do_cb(struct virtqueue *vq,
+			 void (*handle_buf)(void *token, unsigned int len,
+					    struct virtqueue *vq,
+					    struct viortc_vq *viortc_vq,
+					    struct viortc_dev *viortc))
+{
+	struct viortc_dev *viortc = vq->vdev->priv;
+	struct viortc_vq *viortc_vq;
+	bool cb_enabled = true;
+	unsigned long flags;
+	unsigned int len;
+	void *token;
+
+	viortc_vq = &viortc->vqs[vq->index];
+
+	for (;;) {
+		spin_lock_irqsave(&viortc_vq->lock, flags);
+
+		if (cb_enabled) {
+			virtqueue_disable_cb(vq);
+			cb_enabled = false;
+		}
+
+		token = virtqueue_get_buf(vq, &len);
+		if (!token) {
+			if (virtqueue_enable_cb(vq)) {
+				spin_unlock_irqrestore(&viortc_vq->lock, flags);
+				return;
+			}
+			cb_enabled = true;
+		}
+
+		spin_unlock_irqrestore(&viortc_vq->lock, flags);
+
+		if (token)
+			handle_buf(token, len, vq, viortc_vq, viortc);
+	}
+}
+
+/**
+ * viortc_requestq_hdlr() - process a requestq used buffer
+ * @token: token identifying the buffer
+ * @len: bytes written by device
+ * @vq: virtqueue
+ * @viortc_vq: device specific data for virtqueue
+ * @viortc: device data
+ *
+ * Signals completion for each received message.
+ *
+ * Context: virtqueue callback
+ */
+static void viortc_requestq_hdlr(void *token, unsigned int len,
+				 struct virtqueue *vq,
+				 struct viortc_vq *viortc_vq,
+				 struct viortc_dev *viortc)
+{
+	struct viortc_msg *msg = token;
+
+	msg->resp_actual_size = len;
+
+	complete(&msg->responded);
+	viortc_msg_release(msg);
+}
+
+/**
+ * viortc_cb_requestq() - callback for requestq
+ * @vq: virtqueue
+ *
+ * Context: virtqueue callback
+ */
+static void viortc_cb_requestq(struct virtqueue *vq)
+{
+	viortc_do_cb(vq, viortc_requestq_hdlr);
+}
+
+/**
+ * viortc_get_resp_errno() - converts virtio_rtc errnos to system errnos
+ * @resp_head: message response header
+ *
+ * Return: negative system errno, or 0
+ */
+static int viortc_get_resp_errno(struct virtio_rtc_resp_head *resp_head)
+{
+	switch (virtio_le_to_cpu(resp_head->status)) {
+	case VIRTIO_RTC_S_OK:
+		return 0;
+	case VIRTIO_RTC_S_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case VIRTIO_RTC_S_EINVAL:
+		return -EINVAL;
+	case VIRTIO_RTC_S_ENODEV:
+		return -ENODEV;
+	case VIRTIO_RTC_S_EIO:
+	default:
+		return -EIO;
+	}
+}
+
+/**
+ * viortc_msg_xfer() - send message request, wait until message response
+ * @vq: virtqueue
+ * @msg: message with driver request
+ * @timeout_jiffies: message response timeout, 0 for no timeout
+ *
+ * Context: Process context. Takes and releases vq.lock. May sleep.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_msg_xfer(struct viortc_vq *vq, struct viortc_msg *msg,
+			   unsigned long timeout_jiffies)
+{
+	struct scatterlist out_sg[1];
+	struct scatterlist in_sg[1];
+	struct scatterlist *sgs[2];
+	unsigned long flags;
+	long timeout_ret;
+	bool notify;
+	int ret;
+
+	sgs[0] = out_sg;
+	sgs[1] = in_sg;
+
+	sg_init_one(out_sg, msg->req, msg->req_size);
+	sg_init_one(in_sg, msg->resp, msg->resp_cap);
+
+	spin_lock_irqsave(&vq->lock, flags);
+
+	ret = virtqueue_add_sgs(vq->vq, sgs, 1, 1, msg, GFP_ATOMIC);
+	if (ret) {
+		spin_unlock_irqrestore(&vq->lock, flags);
+		/*
+		 * Release in place of the response callback, which will never
+		 * come.
+		 */
+		viortc_msg_release(msg);
+		return ret;
+	}
+
+	notify = virtqueue_kick_prepare(vq->vq);
+
+	spin_unlock_irqrestore(&vq->lock, flags);
+
+	if (notify)
+		virtqueue_notify(vq->vq);
+
+	if (timeout_jiffies) {
+		timeout_ret = wait_for_completion_interruptible_timeout(
+			&msg->responded, timeout_jiffies);
+
+		if (!timeout_ret)
+			return -ETIMEDOUT;
+		else if (timeout_ret < 0)
+			return (int)timeout_ret;
+	} else {
+		ret = wait_for_completion_interruptible(&msg->responded);
+		if (ret)
+			return ret;
+	}
+
+	if (msg->resp_actual_size < sizeof(struct virtio_rtc_resp_head))
+		return -EINVAL;
+
+	ret = viortc_get_resp_errno(msg->resp);
+	if (ret)
+		return ret;
+
+	/*
+	 * There is not yet a case where returning a short message would make
+	 * sense, so consider any deviation an error.
+	 */
+	if (msg->resp_actual_size != msg->resp_cap)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * common message handle macros for messages of different types
+ */
+
+/**
+ * VIORTC_DECLARE_MSG_HDL_ONSTACK() - declare message handle on stack
+ * @hdl: message handle name
+ * @msg_id: message type id
+ * @msg_req: message request type
+ * @msg_resp: message response type
+ */
+#define VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, msg_id, msg_req, msg_resp)         \
+	struct {                                                               \
+		struct viortc_msg *msg;                                        \
+		msg_req *req;                                                  \
+		msg_resp *resp;                                                \
+		unsigned int req_size;                                         \
+		unsigned int resp_cap;                                         \
+		u16 msg_type;                                                  \
+	} hdl = {                                                              \
+		NULL, NULL, NULL, sizeof(msg_req), sizeof(msg_resp), (msg_id), \
+	}
+
+/**
+ * VIORTC_MSG() - extract message from message handle
+ * @hdl: message handle
+ *
+ * Return: struct viortc_msg
+ */
+#define VIORTC_MSG(hdl) ((hdl).msg)
+
+/**
+ * VIORTC_MSG_INIT() - initialize message handle
+ * @hdl: message handle
+ * @viortc: device data (struct viortc_dev *)
+ *
+ * Context: Process context.
+ * Return: 0 on success, -ENOMEM otherwise.
+ */
+#define VIORTC_MSG_INIT(hdl, viortc)                                         \
+	({                                                                   \
+		typeof(hdl) *_hdl = &(hdl);                                  \
+									     \
+		_hdl->msg = viortc_msg_init((viortc), _hdl->msg_type,        \
+					    _hdl->req_size, _hdl->resp_cap); \
+		if (_hdl->msg) {                                             \
+			_hdl->req = _hdl->msg->req;                          \
+			_hdl->resp = _hdl->msg->resp;                        \
+		}                                                            \
+		_hdl->msg ? 0 : -ENOMEM;                                     \
+	})
+
+/**
+ * VIORTC_MSG_WRITE() - write a request message field
+ * @hdl: message handle
+ * @dest_member: request message field name
+ * @src_ptr: pointer to data of compatible type
+ *
+ * Writes the field in little-endian format.
+ */
+#define VIORTC_MSG_WRITE(hdl, dest_member, src_ptr)                         \
+	do {                                                                \
+		typeof(hdl) _hdl = (hdl);                                   \
+		typeof(src_ptr) _src_ptr = (src_ptr);                       \
+									    \
+		/* Sanity check: must match the member's type */            \
+		typecheck(typeof(virtio_le_to_cpu(_hdl.req->dest_member)),  \
+			  *_src_ptr);                                       \
+									    \
+		_hdl.req->dest_member =                                     \
+			virtio_cpu_to_le(*_src_ptr, _hdl.req->dest_member); \
+	} while (0)
+
+/**
+ * VIORTC_MSG_READ() - read from a response message field
+ * @hdl: message handle
+ * @src_member: response message field name
+ * @dest_ptr: pointer to data of compatible type
+ *
+ * Converts from little-endian format and writes to dest_ptr.
+ */
+#define VIORTC_MSG_READ(hdl, src_member, dest_ptr)                          \
+	do {                                                                \
+		typeof(dest_ptr) _dest_ptr = (dest_ptr);                    \
+									    \
+		/* Sanity check: must match the member's type */            \
+		typecheck(typeof(virtio_le_to_cpu((hdl).resp->src_member)), \
+			  *_dest_ptr);                                      \
+									    \
+		*_dest_ptr = virtio_le_to_cpu((hdl).resp->src_member);      \
+	} while (0)
+
+/*
+ * read requests
+ */
+
+/** timeout for clock readings, where timeouts are considered non-fatal */
+#define VIORTC_MSG_READ_TIMEOUT secs_to_jiffies(60)
+
+/**
+ * viortc_read() - VIRTIO_RTC_REQ_READ wrapper
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ * @reading: clock reading [ns]
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+int viortc_read(struct viortc_dev *viortc, u16 vio_clk_id, u64 *reading)
+{
+	VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, VIRTIO_RTC_REQ_READ,
+				       struct virtio_rtc_req_read,
+				       struct virtio_rtc_resp_read);
+	int ret;
+
+	ret = VIORTC_MSG_INIT(hdl, viortc);
+	if (ret)
+		return ret;
+
+	VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
+
+	ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
+			      VIORTC_MSG_READ_TIMEOUT);
+	if (ret) {
+		dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
+			ret);
+		goto out_release;
+	}
+
+	VIORTC_MSG_READ(hdl, clock_reading, reading);
+
+out_release:
+	viortc_msg_release(VIORTC_MSG(hdl));
+
+	return ret;
+}
+
+/**
+ * viortc_read_cross() - VIRTIO_RTC_REQ_READ_CROSS wrapper
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ * @hw_counter: virtio_rtc HW counter type
+ * @reading: clock reading [ns]
+ * @cycles: HW counter cycles during clock reading
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+int viortc_read_cross(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
+		      u64 *reading, u64 *cycles)
+{
+	VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, VIRTIO_RTC_REQ_READ_CROSS,
+				       struct virtio_rtc_req_read_cross,
+				       struct virtio_rtc_resp_read_cross);
+	int ret;
+
+	ret = VIORTC_MSG_INIT(hdl, viortc);
+	if (ret)
+		return ret;
+
+	VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
+	VIORTC_MSG_WRITE(hdl, hw_counter, &hw_counter);
+
+	ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
+			      VIORTC_MSG_READ_TIMEOUT);
+	if (ret) {
+		dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
+			ret);
+		goto out_release;
+	}
+
+	VIORTC_MSG_READ(hdl, clock_reading, reading);
+	VIORTC_MSG_READ(hdl, counter_cycles, cycles);
+
+out_release:
+	viortc_msg_release(VIORTC_MSG(hdl));
+
+	return ret;
+}
+
+/*
+ * control requests
+ */
+
+/**
+ * viortc_cfg() - VIRTIO_RTC_REQ_CFG wrapper
+ * @viortc: device data
+ * @num_clocks: # of virtio_rtc clocks
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_cfg(struct viortc_dev *viortc, u16 *num_clocks)
+{
+	VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, VIRTIO_RTC_REQ_CFG,
+				       struct virtio_rtc_req_cfg,
+				       struct virtio_rtc_resp_cfg);
+	int ret;
+
+	ret = VIORTC_MSG_INIT(hdl, viortc);
+	if (ret)
+		return ret;
+
+	ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
+			      0);
+	if (ret) {
+		dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
+			ret);
+		goto out_release;
+	}
+
+	VIORTC_MSG_READ(hdl, num_clocks, num_clocks);
+
+out_release:
+	viortc_msg_release(VIORTC_MSG(hdl));
+
+	return ret;
+}
+
+/**
+ * viortc_clock_cap() - VIRTIO_RTC_REQ_CLOCK_CAP wrapper
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ * @type: virtio_rtc clock type
+ * @leap_second_smearing: virtio_rtc smearing variant
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_clock_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 *type,
+			    u8 *leap_second_smearing)
+{
+	VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, VIRTIO_RTC_REQ_CLOCK_CAP,
+				       struct virtio_rtc_req_clock_cap,
+				       struct virtio_rtc_resp_clock_cap);
+	int ret;
+
+	ret = VIORTC_MSG_INIT(hdl, viortc);
+	if (ret)
+		return ret;
+
+	VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
+
+	ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
+			      0);
+	if (ret) {
+		dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
+			ret);
+		goto out_release;
+	}
+
+	VIORTC_MSG_READ(hdl, type, type);
+	VIORTC_MSG_READ(hdl, leap_second_smearing, leap_second_smearing);
+
+out_release:
+	viortc_msg_release(VIORTC_MSG(hdl));
+
+	return ret;
+}
+
+/**
+ * viortc_cross_cap() - VIRTIO_RTC_REQ_CROSS_CAP wrapper
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ * @hw_counter: virtio_rtc HW counter type
+ * @supported: xtstamping is supported for the vio_clk_id/hw_counter pair
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+int viortc_cross_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
+		     bool *supported)
+{
+	VIORTC_DECLARE_MSG_HDL_ONSTACK(hdl, VIRTIO_RTC_REQ_CROSS_CAP,
+				       struct virtio_rtc_req_cross_cap,
+				       struct virtio_rtc_resp_cross_cap);
+	u8 flags;
+	int ret;
+
+	ret = VIORTC_MSG_INIT(hdl, viortc);
+	if (ret)
+		return ret;
+
+	VIORTC_MSG_WRITE(hdl, clock_id, &vio_clk_id);
+	VIORTC_MSG_WRITE(hdl, hw_counter, &hw_counter);
+
+	ret = viortc_msg_xfer(&viortc->vqs[VIORTC_REQUESTQ], VIORTC_MSG(hdl),
+			      0);
+	if (ret) {
+		dev_dbg(&viortc->vdev->dev, "%s: xfer returned %d\n", __func__,
+			ret);
+		goto out_release;
+	}
+
+	VIORTC_MSG_READ(hdl, flags, &flags);
+	*supported = !!(flags & VIRTIO_RTC_FLAG_CROSS_CAP);
+
+out_release:
+	viortc_msg_release(VIORTC_MSG(hdl));
+
+	return ret;
+}
+
+/*
+ * init, deinit
+ */
+
+/**
+ * viortc_clocks_init() - init local representations of virtio_rtc clocks
+ * @viortc: device data
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_clocks_init(struct viortc_dev *viortc)
+{
+	u16 num_clocks;
+	int ret;
+
+	ret = viortc_cfg(viortc, &num_clocks);
+	if (ret)
+		return ret;
+
+	if (num_clocks < 1) {
+		dev_err(&viortc->vdev->dev, "device reported 0 clocks\n");
+		return -ENODEV;
+	}
+
+	viortc->num_clocks = num_clocks;
+
+	/* In the future, PTP clocks will be initialized here. */
+	(void)viortc_clock_cap;
+
+	return ret;
+}
+
+/**
+ * viortc_init_vqs() - init virtqueues
+ * @viortc: device data
+ *
+ * Inits virtqueues and associated data.
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_init_vqs(struct viortc_dev *viortc)
+{
+	struct virtqueue *vqs[VIORTC_MAX_NR_QUEUES];
+	struct virtqueue_info vqs_info[] = {
+		{ "requestq", viortc_cb_requestq },
+	};
+	struct virtio_device *vdev = viortc->vdev;
+	int nr_queues, ret;
+
+	nr_queues = VIORTC_REQUESTQ + 1;
+
+	ret = virtio_find_vqs(vdev, nr_queues, vqs, vqs_info, NULL);
+	if (ret)
+		return ret;
+
+	viortc->vqs[VIORTC_REQUESTQ].vq = vqs[VIORTC_REQUESTQ];
+	spin_lock_init(&viortc->vqs[VIORTC_REQUESTQ].lock);
+
+	return 0;
+}
+
+/**
+ * viortc_probe() - probe a virtio_rtc virtio device
+ * @vdev: virtio device
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_probe(struct virtio_device *vdev)
+{
+	struct viortc_dev *viortc;
+	int ret;
+
+	viortc = devm_kzalloc(&vdev->dev, sizeof(*viortc), GFP_KERNEL);
+	if (!viortc)
+		return -ENOMEM;
+
+	vdev->priv = viortc;
+	viortc->vdev = vdev;
+
+	ret = viortc_init_vqs(viortc);
+	if (ret)
+		return ret;
+
+	virtio_device_ready(vdev);
+
+	ret = viortc_clocks_init(viortc);
+	if (ret)
+		goto err_reset_vdev;
+
+	return 0;
+
+err_reset_vdev:
+	virtio_reset_device(vdev);
+	vdev->config->del_vqs(vdev);
+
+	return ret;
+}
+
+/**
+ * viortc_remove() - remove a virtio_rtc virtio device
+ * @vdev: virtio device
+ */
+static void viortc_remove(struct virtio_device *vdev)
+{
+	/* In the future, PTP clocks will be deinitialized here. */
+
+	virtio_reset_device(vdev);
+	vdev->config->del_vqs(vdev);
+}
+
+static int viortc_freeze(struct virtio_device *dev)
+{
+	/*
+	 * Do not reset the device, so that the device may still wake up the
+	 * system through an alarmq notification.
+	 */
+
+	return 0;
+}
+
+static int viortc_restore(struct virtio_device *dev)
+{
+	struct viortc_dev *viortc = dev->priv;
+
+	return viortc_init_vqs(viortc);
+}
+
+static struct virtio_device_id id_table[] = {
+	{ VIRTIO_ID_CLOCK, VIRTIO_DEV_ANY_ID },
+	{ 0 },
+};
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+static struct virtio_driver virtio_rtc_drv = {
+	.driver.name = KBUILD_MODNAME,
+	.id_table = id_table,
+	.probe = viortc_probe,
+	.remove = viortc_remove,
+	.freeze = pm_sleep_ptr(viortc_freeze),
+	.restore = pm_sleep_ptr(viortc_restore),
+};
+
+module_virtio_driver(virtio_rtc_drv);
+
+MODULE_DESCRIPTION("Virtio RTC driver");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/virtio/virtio_rtc_internal.h b/drivers/virtio/virtio_rtc_internal.h
new file mode 100644
index 000000000000..9c249c15b68f
--- /dev/null
+++ b/drivers/virtio/virtio_rtc_internal.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * virtio_rtc internal interfaces
+ *
+ * Copyright (C) 2022-2023 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _VIRTIO_RTC_INTERNAL_H_
+#define _VIRTIO_RTC_INTERNAL_H_
+
+#include <linux/types.h>
+
+/* driver core IFs */
+
+struct viortc_dev;
+
+int viortc_read(struct viortc_dev *viortc, u16 vio_clk_id, u64 *reading);
+int viortc_read_cross(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
+		      u64 *reading, u64 *cycles);
+int viortc_cross_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
+		     bool *supported);
+
+#endif /* _VIRTIO_RTC_INTERNAL_H_ */
diff --git a/include/uapi/linux/virtio_rtc.h b/include/uapi/linux/virtio_rtc.h
new file mode 100644
index 000000000000..6b3af4e9bbfb
--- /dev/null
+++ b/include/uapi/linux/virtio_rtc.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * Copyright (C) 2022-2024 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _LINUX_VIRTIO_RTC_H
+#define _LINUX_VIRTIO_RTC_H
+
+#include <linux/types.h>
+
+/* read request message types */
+
+#define VIRTIO_RTC_REQ_READ			0x0001
+#define VIRTIO_RTC_REQ_READ_CROSS		0x0002
+
+/* control request message types */
+
+#define VIRTIO_RTC_REQ_CFG			0x1000
+#define VIRTIO_RTC_REQ_CLOCK_CAP		0x1001
+#define VIRTIO_RTC_REQ_CROSS_CAP		0x1002
+
+/* Message headers */
+
+/** common request header */
+struct virtio_rtc_req_head {
+	__le16 msg_type;
+	__u8 reserved[6];
+};
+
+/** common response header */
+struct virtio_rtc_resp_head {
+#define VIRTIO_RTC_S_OK			0
+#define VIRTIO_RTC_S_EOPNOTSUPP		2
+#define VIRTIO_RTC_S_ENODEV		3
+#define VIRTIO_RTC_S_EINVAL		4
+#define VIRTIO_RTC_S_EIO		5
+	__u8 status;
+	__u8 reserved[7];
+};
+
+/* read requests */
+
+/* VIRTIO_RTC_REQ_READ message */
+
+struct virtio_rtc_req_read {
+	struct virtio_rtc_req_head head;
+	__le16 clock_id;
+	__u8 reserved[6];
+};
+
+struct virtio_rtc_resp_read {
+	struct virtio_rtc_resp_head head;
+	__le64 clock_reading;
+};
+
+/* VIRTIO_RTC_REQ_READ_CROSS message */
+
+struct virtio_rtc_req_read_cross {
+	struct virtio_rtc_req_head head;
+	__le16 clock_id;
+/* Arm Generic Timer Counter-timer Virtual Count Register (CNTVCT_EL0) */
+#define VIRTIO_RTC_COUNTER_ARM_VCT	0
+/* x86 Time-Stamp Counter */
+#define VIRTIO_RTC_COUNTER_X86_TSC	1
+/* Invalid */
+#define VIRTIO_RTC_COUNTER_INVALID	0xFF
+	__u8 hw_counter;
+	__u8 reserved[5];
+};
+
+struct virtio_rtc_resp_read_cross {
+	struct virtio_rtc_resp_head head;
+	__le64 clock_reading;
+	__le64 counter_cycles;
+};
+
+/* control requests */
+
+/* VIRTIO_RTC_REQ_CFG message */
+
+struct virtio_rtc_req_cfg {
+	struct virtio_rtc_req_head head;
+	/* no request params */
+};
+
+struct virtio_rtc_resp_cfg {
+	struct virtio_rtc_resp_head head;
+	/** # of clocks -> clock ids < num_clocks are valid */
+	__le16 num_clocks;
+	__u8 reserved[6];
+};
+
+/* VIRTIO_RTC_REQ_CLOCK_CAP message */
+
+struct virtio_rtc_req_clock_cap {
+	struct virtio_rtc_req_head head;
+	__le16 clock_id;
+	__u8 reserved[6];
+};
+
+struct virtio_rtc_resp_clock_cap {
+	struct virtio_rtc_resp_head head;
+#define VIRTIO_RTC_CLOCK_UTC			0
+#define VIRTIO_RTC_CLOCK_TAI			1
+#define VIRTIO_RTC_CLOCK_MONOTONIC		2
+#define VIRTIO_RTC_CLOCK_UTC_SMEARED		3
+#define VIRTIO_RTC_CLOCK_UTC_MAYBE_SMEARED	4
+	__u8 type;
+#define VIRTIO_RTC_SMEAR_UNSPECIFIED	0
+#define VIRTIO_RTC_SMEAR_NOON_LINEAR	1
+#define VIRTIO_RTC_SMEAR_UTC_SLS	2
+	__u8 leap_second_smearing;
+	__u8 reserved[6];
+};
+
+/* VIRTIO_RTC_REQ_CROSS_CAP message */
+
+struct virtio_rtc_req_cross_cap {
+	struct virtio_rtc_req_head head;
+	__le16 clock_id;
+	__u8 hw_counter;
+	__u8 reserved[5];
+};
+
+struct virtio_rtc_resp_cross_cap {
+	struct virtio_rtc_resp_head head;
+#define VIRTIO_RTC_FLAG_CROSS_CAP	(1 << 0)
+	__u8 flags;
+	__u8 reserved[7];
+};
+
+/** Union of request types for requestq */
+union virtio_rtc_req_requestq {
+	struct virtio_rtc_req_read read;
+	struct virtio_rtc_req_read_cross read_cross;
+	struct virtio_rtc_req_cfg cfg;
+	struct virtio_rtc_req_clock_cap clock_cap;
+	struct virtio_rtc_req_cross_cap cross_cap;
+};
+
+/** Union of response types for requestq */
+union virtio_rtc_resp_requestq {
+	struct virtio_rtc_resp_read read;
+	struct virtio_rtc_resp_read_cross read_cross;
+	struct virtio_rtc_resp_cfg cfg;
+	struct virtio_rtc_resp_clock_cap clock_cap;
+	struct virtio_rtc_resp_cross_cap cross_cap;
+};
+
+#endif /* _LINUX_VIRTIO_RTC_H */
-- 
2.43.0



From luis.gerhorst at fau.de  Thu Mar 13 10:38:08 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:38:08 +0100
Subject: [PATCH bpf-next 05/11] bpf, arm64, powerpc: Change nospec to include v1 barrier
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313173808.1109600-1-luis.gerhorst@fau.de>

This changes the semantics of BPF_NOSPEC (previously a v4-only barrier)
to always emit a speculation barrier that works against both Spectre v1
AND v4. If mitigation is not needed on an architecture, the backend
should set bpf_jit_bypass_spec_v4/v1().

As of now, this commit only has the user-visible implication that unpriv
BPF's performance on PowerPC is reduced. This is required because we
have emit additional v1 barrier instructions for BPF_NOSPEC.

This commit is required for a future commit to allow us to rely on
BPF_NOSPEC for Spectre v1 mitigation. As of this commit, the feature
that nospec acts as a v1 barrier is unused.

Commit f5e81d111750 ("bpf: Introduce BPF nospec instruction for
mitigating Spectre v4") noted that mitigation instructions for v1 and v4
might be different on some archs. While this would potentially offer
improved performance on PowerPC, it was dismissed after the following
considerations:

* Only having one barrier simplifies the verifier and allows us to
  easily rely on v4-induced barriers for reducing the complexity of
  v1-induced speculative path verification.

* For the architectures that implemented BPF_NOSPEC, only PowerPC has
  distinct instructions for v1 and v4. Even there, some insns may be
  shared between the barriers for v1 and v4 (e.g., 'ori 31,31,0' and
  'sync'). If this is still found to impact performance in an
  unacceptable way, BPF_NOSPEC can be split into BPF_NOSPEC_V1 and
  BPF_NOSPEC_V4 later. As an optimization, we can already skip v1/v4
  insns from being emitted for PowerPC with this setup if
  bypass_spec_v1/v4 is set.

Vulnerability-status for BPF_NOSPEC-based Spectre mitigations (v4 as of
this commit, v1 in the future) is therefore:

* x86 (32-bit and 64-bit), ARM64, and PowerPC (64-bit): Mitigated - This
  patch implements BPF_NOSPEC for these architectures. The previous
  v4-only version was supported since commit f5e81d111750 ("bpf:
  Introduce BPF nospec instruction for mitigating Spectre v4") and
  commit b7540d625094 ("powerpc/bpf: Emit stf barrier instruction
  sequences for BPF_NOSPEC").

* LoongArch: Not Vulnerable - Commit a6f6a95f2580 ("LoongArch, bpf: Fix
  jit to skip speculation barrier opcode") is the only other past commit
  related to BPF_NOSPEC and indicates that the insn is not required
  there.

* MIPS: Vulnerable (if unprivileged BPF is enabled) -
  Commit?a6f6a95f2580 ("LoongArch, bpf: Fix jit to skip speculation
  barrier opcode") indicates that it is not vulnerable but this
  contradicts the kernel and Debian documentation. Therefore I assume
  that there exist vulnerable MIPS CPUs (but maybe not from Loongson?).
  In the future, BPF_NOSPEC could be implemented for MIPS based on the
  GCC speculation_barrier [1]. For now, we rely on unprivileged BPF
  being disabled by default.

* Other: Unknown - To the best of my knowledge there is no definitive
  information available that indicates that any other arch is
  vulnerable. They are therefore left untouched (BPF_NOSPEC is not
  implemented, but bypass_spec_v1/v4 is also not set).

I did the following testing to ensure the insn encoding is correct:

* ARM64:
  * 'dsb nsh; isb' was successfully tested with the BPF CI in [2]
  * 'sb' locally using QEMU v7.2.15 -cpu max (emitted sb insn is
    executed for example with './test_progs -t verifier_array_access')

* PowerPC: The following configs were tested locally with ppc64le QEMU
  v8.2 '-machine pseries -cpu POWER9':
  * STF_BARRIER_EIEIO + CONFIG_PPC_BOOK32_64
  * STF_BARRIER_SYNC_ORI (forced on) + CONFIG_PPC_BOOK32_64
  * STF_BARRIER_FALLBACK (forced on) + CONFIG_PPC_BOOK32_64
  * CONFIG_PPC_E500 (forced on) + STF_BARRIER_EIEIO
  * CONFIG_PPC_E500 (forced on) + STF_BARRIER_SYNC_ORI (forced on)
  * CONFIG_PPC_E500 (forced on) + STF_BARRIER_FALLBACK (forced on)
  * CONFIG_PPC_E500 (forced on) + STF_BARRIER_NONE (forced on)
  Most of those cobinations should not occur in practice, but I was not
  able to get an PPC e6500 rootfs (for testing PPC_E500 without forcing
  it on). In any case, this should ensure that there are no unexpected
  conflicts between the insns when combined like this. Individual v1/v4
  barriers were already emitted elsewhere.

[1] https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=29b74545531f6afbee9fc38c267524326dbfbedf
    ("MIPS: Add speculation_barrier support")
[2] https://github.com/kernel-patches/bpf/pull/8576

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Cc: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 arch/arm64/net/bpf_jit.h          |  5 +++
 arch/arm64/net/bpf_jit_comp.c     |  9 +++--
 arch/powerpc/net/bpf_jit_comp64.c | 58 ++++++++++++++++++++++---------
 include/linux/filter.h            |  2 +-
 kernel/bpf/core.c                 | 17 ++++-----
 5 files changed, 64 insertions(+), 27 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index a3b0e693a125..bbea4f36f9f2 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -325,4 +325,9 @@
 #define A64_MRS_SP_EL0(Rt) \
 	aarch64_insn_gen_mrs(Rt, AARCH64_INSN_SYSREG_SP_EL0)
 
+/* Barriers */
+#define A64_SB aarch64_insn_get_sb_value()
+#define A64_DSB_NSH (aarch64_insn_get_dsb_base_value() | 0x7 << 8)
+#define A64_ISB aarch64_insn_get_isb_value()
+
 #endif /* _BPF_JIT_H */
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 0f617b55866e..ccd6a2f31e35 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1581,9 +1581,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
 			return ret;
 		break;
 
-	/* speculation barrier */
+	/* speculation barrier against v1 and v4 */
 	case BPF_ST | BPF_NOSPEC:
-		/* See bpf_jit_bypass_spec_v4() */
+		if (alternative_has_cap_likely(ARM64_HAS_SB)) {
+			emit(A64_SB, ctx);
+		} else {
+			emit(A64_DSB_NSH, ctx);
+			emit(A64_ISB, ctx);
+		}
 		break;
 
 	/* ST: *(size *)(dst + off) = imm */
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index b5339c541283..c00951e2a50e 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -800,26 +800,52 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
 
 		/*
 		 * BPF_ST NOSPEC (speculation barrier)
+		 *
+		 * The following must act as a barrier against both Spectre v1
+		 * and v4 if we requested both mitigations. Therefore, also emit
+		 * 'isync; sync' on E500 or 'ori31' on BOOK3S_64 in addition to
+		 * the insns needed for a Spectre v4 barrier.
+		 *
+		 * If we requested only !bypass_spec_v1 OR only !bypass_spec_v4,
+		 * we can skip the respective other barrier type as an
+		 * optimization.
 		 */
 		case BPF_ST | BPF_NOSPEC:
-			switch (stf_barrier) {
-			case STF_BARRIER_EIEIO:
-				EMIT(PPC_RAW_EIEIO() | 0x02000000);
-				break;
-			case STF_BARRIER_SYNC_ORI:
+			bool sync_emitted = false;
+			bool ori31_emitted = false;
+#ifdef CONFIG_PPC_E500
+			if (!bpf_jit_bypass_spec_v1()) {
+				EMIT(PPC_RAW_ISYNC());
 				EMIT(PPC_RAW_SYNC());
-				EMIT(PPC_RAW_LD(tmp1_reg, _R13, 0));
-				EMIT(PPC_RAW_ORI(_R31, _R31, 0));
-				break;
-			case STF_BARRIER_FALLBACK:
-				ctx->seen |= SEEN_FUNC;
-				PPC_LI64(_R12, dereference_kernel_function_descriptor(bpf_stf_barrier));
-				EMIT(PPC_RAW_MTCTR(_R12));
-				EMIT(PPC_RAW_BCTRL());
-				break;
-			case STF_BARRIER_NONE:
-				break;
+				sync_emitted = true;
+			}
+#endif
+			if (!bpf_jit_bypass_spec_v4()) {
+				switch (stf_barrier) {
+				case STF_BARRIER_EIEIO:
+					EMIT(PPC_RAW_EIEIO() | 0x02000000);
+					break;
+				case STF_BARRIER_SYNC_ORI:
+					if (!sync_emitted)
+						EMIT(PPC_RAW_SYNC());
+					EMIT(PPC_RAW_LD(tmp1_reg, _R13, 0));
+					EMIT(PPC_RAW_ORI(_R31, _R31, 0));
+					ori31_emitted = true;
+					break;
+				case STF_BARRIER_FALLBACK:
+					ctx->seen |= SEEN_FUNC;
+					PPC_LI64(_R12, dereference_kernel_function_descriptor(bpf_stf_barrier));
+					EMIT(PPC_RAW_MTCTR(_R12));
+					EMIT(PPC_RAW_BCTRL());
+					break;
+				case STF_BARRIER_NONE:
+					break;
+				}
 			}
+#ifdef CONFIG_PPC_BOOK3S_64
+			if (!bpf_jit_bypass_spec_v1() && !ori31_emitted)
+				EMIT(PPC_RAW_ORI(_R31, _R31, 0));
+#endif
 			break;
 
 		/*
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 590476743f7a..9b933d459b7a 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -82,7 +82,7 @@ struct ctl_table_header;
 #define BPF_CALL_ARGS	0xe0
 
 /* unused opcode to mark speculation barrier for mitigating
- * Speculative Store Bypass
+ * Spectre v1 and v4
  */
 #define BPF_NOSPEC	0xc0
 
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index a3e434851614..eda82877169e 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2102,14 +2102,15 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 #undef COND_JMP
 	/* ST, STX and LDX*/
 	ST_NOSPEC:
-		/* Speculation barrier for mitigating Speculative Store Bypass.
-		 * In case of arm64, we rely on the firmware mitigation as
-		 * controlled via the ssbd kernel parameter. Whenever the
-		 * mitigation is enabled, it works for all of the kernel code
-		 * with no need to provide any additional instructions here.
-		 * In case of x86, we use 'lfence' insn for mitigation. We
-		 * reuse preexisting logic from Spectre v1 mitigation that
-		 * happens to produce the required code on x86 for v4 as well.
+		/* Speculation barrier for mitigating Speculative Store Bypass,
+		 * Bounds-Check Bypass and Type Confusion. In case of arm64, we
+		 * rely on the firmware mitigation as controlled via the ssbd
+		 * kernel parameter. Whenever the mitigation is enabled, it
+		 * works for all of the kernel code with no need to provide any
+		 * additional instructions here. In case of x86, we use 'lfence'
+		 * insn for mitigation. We reuse preexisting logic from Spectre
+		 * v1 mitigation that happens to produce the required code on
+		 * x86 for v4 as well.
 		 */
 		barrier_nospec();
 		CONT;
-- 
2.48.1



From quic_philber at quicinc.com  Thu Mar 13 10:36:59 2025
From: quic_philber at quicinc.com (Peter Hilber)
Date: Thu, 13 Mar 2025 18:36:59 +0100
Subject: [PATCH v6 3/4] virtio_rtc: Add Arm Generic Timer cross-timestamping
In-Reply-To: <20250313173707.1492-1-quic_philber@quicinc.com>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
Message-ID: <20250313173707.1492-4-quic_philber@quicinc.com>

For platforms using the Arm Generic Timer, add precise cross-timestamping
support to virtio_rtc.

Always report the CP15 virtual counter as the HW counter in use by
arm_arch_timer, since the Linux kernel's usage of the Arm Generic Timer
should always be compatible with this.

Signed-off-by: Peter Hilber <quic_philber at quicinc.com>
---

Notes:
    v4:
    
    - Update names and types to spec v6.
    
    v2:
    
    - Depend on prerequisite patch series "treewide: Use clocksource id for
      get_device_system_crosststamp()".
    
    - Return clocksource id instead of calling dropped arm_arch_timer helpers.
    
    - Always report the CP15 virtual counter to be in use by arm_arch_timer,
      since distinction of Arm physical and virtual counter appears unneeded
      after discussion with Marc Zyngier.

 drivers/virtio/Kconfig          | 13 +++++++++++++
 drivers/virtio/Makefile         |  1 +
 drivers/virtio/virtio_rtc_arm.c | 23 +++++++++++++++++++++++
 3 files changed, 37 insertions(+)
 create mode 100644 drivers/virtio/virtio_rtc_arm.c

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index a14a2b77e142..3d8b366c0625 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -221,6 +221,19 @@ config VIRTIO_RTC_PTP
 
 	 If unsure, say Y.
 
+config VIRTIO_RTC_ARM
+	bool "Virtio RTC cross-timestamping using Arm Generic Timer"
+	default y
+	depends on VIRTIO_RTC_PTP && ARM_ARCH_TIMER
+	help
+	 This enables Virtio RTC cross-timestamping using the Arm Generic Timer.
+	 It only has an effect if the Virtio RTC device also supports this. The
+	 cross-timestamp is available through the PTP clock driver precise
+	 cross-timestamp ioctl (PTP_SYS_OFFSET_PRECISE2 aka
+	 PTP_SYS_OFFSET_PRECISE).
+
+	 If unsure, say Y.
+
 endif # VIRTIO_RTC
 
 endif # VIRTIO_MENU
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 88d6fb8d4731..dbd77f124ba9 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_VIRTIO_DEBUG) += virtio_debug.o
 obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o
 virtio_rtc-y := virtio_rtc_driver.o
 virtio_rtc-$(CONFIG_VIRTIO_RTC_PTP) += virtio_rtc_ptp.o
+virtio_rtc-$(CONFIG_VIRTIO_RTC_ARM) += virtio_rtc_arm.o
diff --git a/drivers/virtio/virtio_rtc_arm.c b/drivers/virtio/virtio_rtc_arm.c
new file mode 100644
index 000000000000..211299d72870
--- /dev/null
+++ b/drivers/virtio/virtio_rtc_arm.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Provides cross-timestamp params for Arm.
+ *
+ * Copyright (C) 2022-2023 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clocksource_ids.h>
+
+#include <uapi/linux/virtio_rtc.h>
+
+#include "virtio_rtc_internal.h"
+
+/* see header for doc */
+
+int viortc_hw_xtstamp_params(u8 *hw_counter, enum clocksource_ids *cs_id)
+{
+	*hw_counter = VIRTIO_RTC_COUNTER_ARM_VCT;
+	*cs_id = CSID_ARM_ARCH_COUNTER;
+
+	return 0;
+}
-- 
2.43.0



From yang at os.amperecomputing.com  Thu Mar 13 10:21:51 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Thu, 13 Mar 2025 10:21:51 -0700
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313104111.24196-3-miko.lenczewski@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
Message-ID: <0abe8643-d4ea-4e77-bd77-afe07399eec9@os.amperecomputing.com>



On 3/13/25 3:41 AM, Miko?aj Lenczewski wrote:
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for, as well as a kernel commandline parameter to optionally
> disable BBML2 altogether.
>
> This is a system feature as we might have a big.LITTLE architecture
> where some cores support BBML2 and some don't, but we want all cores to
> be available and BBM to default to level 0 (as opposed to having cores
> without BBML2 not coming online).
>
> To support BBML2 in as wide a range of contexts as we can, we want not
> only the architectural guarantees that BBML2 makes, but additionally
> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
> us having to prove that no recursive faults can be induced in any path
> that uses BBML2, allowing its use for arbitrary kernel mappings.
> Support detection of such CPUs.
>
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> ---
>   .../admin-guide/kernel-parameters.txt         |  3 +
>   arch/arm64/Kconfig                            | 11 +++
>   arch/arm64/include/asm/cpucaps.h              |  2 +
>   arch/arm64/include/asm/cpufeature.h           |  6 ++
>   arch/arm64/kernel/cpufeature.c                | 76 +++++++++++++++++++
>   arch/arm64/kernel/pi/idreg-override.c         |  2 +
>   arch/arm64/tools/cpucaps                      |  1 +
>   7 files changed, 101 insertions(+)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fb8752b42ec8..3e4cc917a07e 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -453,6 +453,9 @@
>   	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>   			32 bit applications.
>   
> +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> +			2 support

Hi Miko,

A question about the kernel boot parameter. Can this parameter be used 
in early boot stage? A quick look at the code shows it should be ok, for 
example, cpu_has_bti() is called in map_kernel(). But I'd like to double 
check because my patchset needs to check this parameter in map_mem() to 
determine whether large block mapping can be used or not.

And a nit below.

> +
>   	arm64.nobti	[ARM64] Unconditionally disable Branch Target
>   			Identification support
>   
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..49deda2b22ae 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>   	  The feature introduces new assembly instructions, and they were
>   	  support when binutils >= 2.30.
>   
> +config ARM64_BBML2_NOABORT
> +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
> +	default y
> +	help
> +	  FEAT_BBM provides detection of support levels for break-before-make
> +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
> +	  can be relaxed to improve performance. We additonally require the
> +	  property that the implementation cannot ever raise TLB Conflict Aborts.
> +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
> +	  even if the system supports BBM level 2.
> +
>   endmenu # "ARMv8.4 architectural features"
>   
>   menu "ARMv8.5 architectural features"
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 0b5ca6e0eb09..2d6db33d4e45 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>   		return IS_ENABLED(CONFIG_ARM64_PAN);
>   	case ARM64_HAS_EPAN:
>   		return IS_ENABLED(CONFIG_ARM64_EPAN);
> +	case ARM64_HAS_BBML2_NOABORT:
> +		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>   	case ARM64_SVE:
>   		return IS_ENABLED(CONFIG_ARM64_SVE);
>   	case ARM64_SME:
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index e0e4478f5fb5..7f5b220dacde 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -18,6 +18,7 @@
>   #define ARM64_SW_FEATURE_OVERRIDE_NOKASLR	0
>   #define ARM64_SW_FEATURE_OVERRIDE_HVHE		4
>   #define ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF	8
> +#define ARM64_SW_FEATURE_OVERRIDE_NOBBML2	12
>   
>   #ifndef __ASSEMBLY__
>   
> @@ -866,6 +867,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
>   	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>   }
>   
> +static inline bool system_supports_bbml2_noabort(void)
> +{
> +	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
> +}
> +
>   int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>   bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>   
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index d561cf3b8ac7..b936e0805161 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2176,6 +2176,76 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>   	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>   }
>   
> +static inline bool bbml2_possible(void)
> +{
> +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
> +}

Can this be moved to cpufeature.h? My patch will use this, anyway I can 
do it in my patchset.

Thanks,
Yang

> +
> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> +{
> +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
> +	 * as possible. This list is therefore an allow-list of known-good
> +	 * implementations that both support bbml2 and additionally, fulfill the
> +	 * extra constraint of never generating TLB conflict aborts when using
> +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> +	 * kernel contexts difficult to prove safe against recursive aborts).
> +	 *
> +	 * Note that implementations can only be considered "known-good" if their
> +	 * implementors attest to the fact that the implementation never raises
> +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
> +	 */
> +	static const struct midr_range supports_bbml2_noabort_list[] = {
> +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> +		{}
> +	};
> +
> +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
> +}
> +
> +static inline unsigned int __cpu_read_midr(int cpu)
> +{
> +	WARN_ON_ONCE(!cpu_online(cpu));
> +
> +	return per_cpu(cpu_data, cpu).reg_midr;
> +}
> +
> +static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
> +{
> +	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
> +		return false;
> +
> +	if (!bbml2_possible())
> +		return false;
> +
> +	if (scope & SCOPE_SYSTEM) {
> +		int cpu;
> +
> +		/* We are a boot CPU, and must verify that all enumerated boot
> +		 * CPUs have MIDR values within our allowlist. Otherwise, we do
> +		 * not allow the BBML2 feature to avoid potential faults when
> +		 * the insufficient CPUs access memory regions using BBML2
> +		 * semantics.
> +		 */
> +		for_each_online_cpu(cpu) {
> +			if (!cpu_has_bbml2_noabort(__cpu_read_midr(cpu)))
> +				return false;
> +		}
> +
> +		return true;
> +	} else if (scope & SCOPE_LOCAL_CPU) {
> +		/* We are a hot-plugged CPU, so only need to check our MIDR.
> +		 * If we have the correct MIDR, but the kernel booted on an
> +		 * insufficient CPU, we will not use BBML2 (this is safe). If
> +		 * we have an incorrect MIDR, but the kernel booted on a
> +		 * sufficient CPU, we will not bring up this CPU.
> +		 */
> +		return cpu_has_bbml2_noabort(read_cpuid_id());
> +	}
> +
> +	return false;
> +}
> +
>   #ifdef CONFIG_ARM64_PAN
>   static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>   {
> @@ -2926,6 +2996,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.matches = has_cpuid_feature,
>   		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
>   	},
> +	{
> +		.desc = "BBM Level 2 without conflict abort",
> +		.capability = ARM64_HAS_BBML2_NOABORT,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.matches = has_bbml2_noabort,
> +	},
>   	{
>   		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
>   		.capability = ARM64_HAS_LPA2,
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f7..9728faa10390 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>   		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>   		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>   		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>   		{}
>   	},
>   };
> @@ -246,6 +247,7 @@ static const struct {
>   	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>   	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>   	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
>   };
>   
>   static int __init parse_hexdigit(const char *p, u64 *v)
> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
> index 1e65f2fb45bd..b03a375e5507 100644
> --- a/arch/arm64/tools/cpucaps
> +++ b/arch/arm64/tools/cpucaps
> @@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
>   HAS_ADDRESS_AUTH_IMP_DEF
>   HAS_AMU_EXTN
>   HAS_ARMv8_4_TTL
> +HAS_BBML2_NOABORT
>   HAS_CACHE_DIC
>   HAS_CACHE_IDC
>   HAS_CNP



From luis.gerhorst at fau.de  Thu Mar 13 10:21:16 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:21:16 +0100
Subject: [PATCH bpf-next 00/11] bpf: Mitigate Spectre v1 using barriers
Message-ID: <20250313172127.1098195-1-luis.gerhorst@fau.de>

This improves the expressiveness of unprivileged BPF by inserting
speculation barriers instead of rejecting the programs.

The approach was previously presented at LPC'24 [1] and RAID'24 [2].

To mitigate the Spectre v1 (PHT) vulnerability, the kernel rejects
potentially-dangerous unprivileged BPF programs as of
commit?9183671af6db ("bpf: Fix leakage under speculation on mispredicted
branches"). In [2], we have analyzed 364 object files from open source
projects (Linux Samples and Selftests, BCC, Loxilb, Cilium, libbpf
Examples, Parca, and Prevail) and found that this affects 31% to 54% of
programs.

To resolve this in the majority of cases this patchset adds a fall-back
for mitigating Spectre v1 using speculation barriers. The kernel still
optimistically attempts to verify all speculative paths but uses
speculation barriers against v1 when unsafe behavior is detected. This
allows for more programs to be accepted without disabling the BPF
Spectre mitigations (e.g., by setting cpu_mitigations_off()).

In [1] we have measured the overhead of this approach relative to having
mitigations off and including the upstream Spectre v4 mitigations. For
event tracing and stack-sampling profilers, we found that mitigations
increase BPF program execution time by 0% to 62%. For the Loxilb network
load balancer, we have measured a 14% slowdown in SCTP performance but
no significant slowdown for TCP. This overhead only applies to programs
that were previously rejected.

I reran the expressiveness-evaluation with v6.14 and made sure the main
results still match those from [1] and [2] (which used v6.5).

Main design decisions are:

* Do not use separate bytecode insns for v1 and v4 barriers. This
  simplifies the verifier significantly and has the only downside that
  performance on PowerPC is not as high as it could be.

* Allow archs to still disable v1/v4 mitigations separately by setting
  bpf_jit_bypass_spec_v1/v4(). This has the benefit that archs can
  benefit from improved BPF expressiveness / performance if they are not
  vulnerable (e.g., ARM64 for v4 in the kernel).

* Do not remove the empty BPF_NOSPEC implementation for backends for
  which it is unknown whether they are vulnerable to Spectre v1.

[1] https://lpc.events/event/18/contributions/1954/ ("Mitigating
    Spectre-PHT using Speculation Barriers in Linux eBPF")
[2] https://arxiv.org/pdf/2405.00078 ("VeriFence: Lightweight and
    Precise Spectre Defenses for Untrusted Linux Kernel Extensions")

Changes:
* RFC -> v1:
  - rebase to bpf-next-250313
  - tests: mark expected successes/new errors
  - add bpt_jit_bypass_spec_v1/v4() to avoid #ifdef in
    bpf_bypass_spec_v1/v4()
  - ensure that nospec with v1-support is implemented for archs for
    which GCC supports speculation barriers, except for MIPS
  - arm64: emit speculation barrier
  - powerpc: change nospec to include v1 barrier
  - discuss potential security (archs that do not impl. BPF nospec) and
    performance (only PowerPC) regressions

RFC: https://lore.kernel.org/bpf/20250224203619.594724-1-luis.gerhorst at fau.de/

Luis Gerhorst (11):
  bpf: Move insn if/else into do_check_insn()
  bpf: Return -EFAULT on misconfigurations
  bpf: Return -EFAULT on internal errors
  bpf, arm64, powerpc: Add bpf_jit_bypass_spec_v1/v4()
  bpf, arm64, powerpc: Change nospec to include v1 barrier
  bpf: Rename sanitize_stack_spill to nospec_result
  bpf: Fall back to nospec for Spectre v1
  bpf: Allow nospec-protected var-offset stack access
  bpf: Return PTR_ERR from push_stack()
  bpf: Fall back to nospec for sanitization-failures
  bpf: Fall back to nospec for spec path verification

 arch/arm64/net/bpf_jit.h                      |   5 +
 arch/arm64/net/bpf_jit_comp.c                 |  28 +-
 arch/powerpc/net/bpf_jit_comp64.c             |  79 +-
 include/linux/bpf.h                           |  11 +-
 include/linux/bpf_verifier.h                  |   3 +-
 include/linux/filter.h                        |   2 +-
 kernel/bpf/core.c                             |  32 +-
 kernel/bpf/verifier.c                         | 723 ++++++++++--------
 .../selftests/bpf/progs/verifier_and.c        |   3 +-
 .../selftests/bpf/progs/verifier_bounds.c     |  35 +-
 .../bpf/progs/verifier_bounds_deduction.c     |  43 +-
 .../selftests/bpf/progs/verifier_map_ptr.c    |  12 +-
 .../selftests/bpf/progs/verifier_movsx.c      |   6 +-
 .../selftests/bpf/progs/verifier_unpriv.c     |   3 +-
 .../bpf/progs/verifier_value_ptr_arith.c      |  50 +-
 .../selftests/bpf/verifier/dead_code.c        |   3 +-
 tools/testing/selftests/bpf/verifier/jmp32.c  |  33 +-
 tools/testing/selftests/bpf/verifier/jset.c   |  10 +-
 18 files changed, 630 insertions(+), 451 deletions(-)


base-commit: 46d38f489ef02175dcff1e03a849c226eb0729a6
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:21:17 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:21:17 +0100
Subject: [PATCH bpf-next 01/11] bpf: Move insn if/else into do_check_insn()
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313172127.1098195-2-luis.gerhorst@fau.de>

This is required to catch the errors later and fall back to a nospec if
on a speculative path.

Move code into do_check_insn(), replace
* "continue" with "return INSN_IDX_MODIFIED"
* "goto process_bpf_exit" with "return PROCESS_BPF_EXIT"
* "do_print_state = " with "*do_print_state = "

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 426 ++++++++++++++++++++++--------------------
 1 file changed, 224 insertions(+), 202 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 3303a3605ee8..199a6341ac82 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -19213,6 +19213,209 @@ static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type typ
 	return 0;
 }
 
+enum {
+	PROCESS_BPF_EXIT = 1,
+	INSN_IDX_MODIFIED
+};
+
+static int do_check_insn(struct bpf_verifier_env *env, struct bpf_insn *insn,
+			 bool pop_log, bool *do_print_state,
+			 struct bpf_reg_state *regs,
+			 struct bpf_verifier_state *state, int *prev_insn_idx)
+{
+	int err;
+	u8 class = BPF_CLASS(insn->code);
+	bool exception_exit = false;
+
+	if (class == BPF_ALU || class == BPF_ALU64) {
+		err = check_alu_op(env, insn);
+		if (err)
+			return err;
+
+	} else if (class == BPF_LDX) {
+		bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
+
+		/* Check for reserved fields is already done in
+		 * resolve_pseudo_ldimm64().
+		 */
+		err = check_load_mem(env, insn, false, is_ldsx, true, "ldx");
+		if (err)
+			return err;
+	} else if (class == BPF_STX) {
+		if (BPF_MODE(insn->code) == BPF_ATOMIC) {
+			err = check_atomic(env, insn);
+			if (err)
+				return err;
+			env->insn_idx++;
+			return INSN_IDX_MODIFIED;
+		}
+
+		if (BPF_MODE(insn->code) != BPF_MEM || insn->imm != 0) {
+			verbose(env, "BPF_STX uses reserved fields\n");
+			return -EINVAL;
+		}
+
+		err = check_store_reg(env, insn, false);
+		if (err)
+			return err;
+	} else if (class == BPF_ST) {
+		enum bpf_reg_type dst_reg_type;
+
+		if (BPF_MODE(insn->code) != BPF_MEM ||
+		    insn->src_reg != BPF_REG_0) {
+			verbose(env, "BPF_ST uses reserved fields\n");
+			return -EINVAL;
+		}
+		/* check src operand */
+		err = check_reg_arg(env, insn->dst_reg, SRC_OP);
+		if (err)
+			return err;
+
+		dst_reg_type = regs[insn->dst_reg].type;
+
+		/* check that memory (dst_reg + off) is writeable */
+		err = check_mem_access(env, env->insn_idx, insn->dst_reg,
+				       insn->off, BPF_SIZE(insn->code),
+				       BPF_WRITE, -1, false, false);
+		if (err)
+			return err;
+
+		err = save_aux_ptr_type(env, dst_reg_type, false);
+		if (err)
+			return err;
+	} else if (class == BPF_JMP || class == BPF_JMP32) {
+		u8 opcode = BPF_OP(insn->code);
+
+		env->jmps_processed++;
+		if (opcode == BPF_CALL) {
+			if (BPF_SRC(insn->code) != BPF_K ||
+			    (insn->src_reg != BPF_PSEUDO_KFUNC_CALL &&
+			     insn->off != 0) ||
+			    (insn->src_reg != BPF_REG_0 &&
+			     insn->src_reg != BPF_PSEUDO_CALL &&
+			     insn->src_reg != BPF_PSEUDO_KFUNC_CALL) ||
+			    insn->dst_reg != BPF_REG_0 || class == BPF_JMP32) {
+				verbose(env, "BPF_CALL uses reserved fields\n");
+				return -EINVAL;
+			}
+
+			if (env->cur_state->active_locks) {
+				if ((insn->src_reg == BPF_REG_0 && insn->imm != BPF_FUNC_spin_unlock) ||
+				    (insn->src_reg == BPF_PSEUDO_KFUNC_CALL &&
+				     (insn->off != 0 || !kfunc_spin_allowed(insn->imm)))) {
+					verbose(env,
+						"function calls are not allowed while holding a lock\n");
+					return -EINVAL;
+				}
+			}
+			if (insn->src_reg == BPF_PSEUDO_CALL) {
+				err = check_func_call(env, insn, &env->insn_idx);
+			} else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
+				err = check_kfunc_call(env, insn, &env->insn_idx);
+				if (!err && is_bpf_throw_kfunc(insn)) {
+					exception_exit = true;
+					goto process_bpf_exit_full;
+				}
+			} else {
+				err = check_helper_call(env, insn, &env->insn_idx);
+			}
+			if (err)
+				return err;
+
+			mark_reg_scratched(env, BPF_REG_0);
+		} else if (opcode == BPF_JA) {
+			if (BPF_SRC(insn->code) != BPF_K ||
+			    insn->src_reg != BPF_REG_0 ||
+			    insn->dst_reg != BPF_REG_0 ||
+			    (class == BPF_JMP && insn->imm != 0) ||
+			    (class == BPF_JMP32 && insn->off != 0)) {
+				verbose(env, "BPF_JA uses reserved fields\n");
+				return -EINVAL;
+			}
+
+			if (class == BPF_JMP)
+				env->insn_idx += insn->off + 1;
+			else
+				env->insn_idx += insn->imm + 1;
+			return INSN_IDX_MODIFIED;
+		} else if (opcode == BPF_EXIT) {
+			if (BPF_SRC(insn->code) != BPF_K ||
+			    insn->imm != 0 ||
+			    insn->src_reg != BPF_REG_0 ||
+			    insn->dst_reg != BPF_REG_0 ||
+			    class == BPF_JMP32) {
+				verbose(env, "BPF_EXIT uses reserved fields\n");
+				return -EINVAL;
+			}
+process_bpf_exit_full:
+			/* We must do check_reference_leak here before
+			 * prepare_func_exit to handle the case when
+			 * state->curframe > 0, it may be a callback function,
+			 * for which reference_state must match caller reference
+			 * state when it exits.
+			 */
+			err = check_resource_leak(env, exception_exit, !env->cur_state->curframe,
+						  "BPF_EXIT instruction in main prog");
+			if (err)
+				return err;
+
+			/* The side effect of the prepare_func_exit which is
+			 * being skipped is that it frees bpf_func_state.
+			 * Typically, process_bpf_exit will only be hit with
+			 * outermost exit. copy_verifier_state in pop_stack will
+			 * handle freeing of any extra bpf_func_state left over
+			 * from not processing all nested function exits. We
+			 * also skip return code checks as they are not needed
+			 * for exceptional exits.
+			 */
+			if (exception_exit)
+				return PROCESS_BPF_EXIT;
+
+			if (state->curframe) {
+				/* exit from nested function */
+				err = prepare_func_exit(env, &env->insn_idx);
+				if (err)
+					return err;
+				*do_print_state = true;
+				return INSN_IDX_MODIFIED;
+			}
+
+			err = check_return_code(env, BPF_REG_0, "R0");
+			if (err)
+				return err;
+			return PROCESS_BPF_EXIT;
+		} else {
+			err = check_cond_jmp_op(env, insn, &env->insn_idx);
+			if (err)
+				return err;
+		}
+	} else if (class == BPF_LD) {
+		u8 mode = BPF_MODE(insn->code);
+
+		if (mode == BPF_ABS || mode == BPF_IND) {
+			err = check_ld_abs(env, insn);
+			if (err)
+				return err;
+
+		} else if (mode == BPF_IMM) {
+			err = check_ld_imm(env, insn);
+			if (err)
+				return err;
+
+			env->insn_idx++;
+			sanitize_mark_insn_seen(env);
+		} else {
+			verbose(env, "invalid BPF_LD mode\n");
+			return -EINVAL;
+		}
+	} else {
+		verbose(env, "unknown insn class %d\n", class);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int do_check(struct bpf_verifier_env *env)
 {
 	bool pop_log = !(env->log.level & BPF_LOG_LEVEL2);
@@ -19224,9 +19427,7 @@ static int do_check(struct bpf_verifier_env *env)
 	int prev_insn_idx = -1;
 
 	for (;;) {
-		bool exception_exit = false;
 		struct bpf_insn *insn;
-		u8 class;
 		int err;
 
 		/* reset current history entry on each new instruction */
@@ -19240,7 +19441,6 @@ static int do_check(struct bpf_verifier_env *env)
 		}
 
 		insn = &insns[env->insn_idx];
-		class = BPF_CLASS(insn->code);
 
 		if (++env->insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
 			verbose(env,
@@ -19314,210 +19514,32 @@ static int do_check(struct bpf_verifier_env *env)
 		sanitize_mark_insn_seen(env);
 		prev_insn_idx = env->insn_idx;
 
-		if (class == BPF_ALU || class == BPF_ALU64) {
-			err = check_alu_op(env, insn);
-			if (err)
-				return err;
-
-		} else if (class == BPF_LDX) {
-			bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
-
-			/* Check for reserved fields is already done in
-			 * resolve_pseudo_ldimm64().
-			 */
-			err = check_load_mem(env, insn, false, is_ldsx, true,
-					     "ldx");
-			if (err)
-				return err;
-		} else if (class == BPF_STX) {
-			if (BPF_MODE(insn->code) == BPF_ATOMIC) {
-				err = check_atomic(env, insn);
-				if (err)
-					return err;
-				env->insn_idx++;
-				continue;
-			}
-
-			if (BPF_MODE(insn->code) != BPF_MEM || insn->imm != 0) {
-				verbose(env, "BPF_STX uses reserved fields\n");
-				return -EINVAL;
-			}
-
-			err = check_store_reg(env, insn, false);
-			if (err)
-				return err;
-		} else if (class == BPF_ST) {
-			enum bpf_reg_type dst_reg_type;
-
-			if (BPF_MODE(insn->code) != BPF_MEM ||
-			    insn->src_reg != BPF_REG_0) {
-				verbose(env, "BPF_ST uses reserved fields\n");
-				return -EINVAL;
-			}
-			/* check src operand */
-			err = check_reg_arg(env, insn->dst_reg, SRC_OP);
-			if (err)
-				return err;
-
-			dst_reg_type = regs[insn->dst_reg].type;
-
-			/* check that memory (dst_reg + off) is writeable */
-			err = check_mem_access(env, env->insn_idx, insn->dst_reg,
-					       insn->off, BPF_SIZE(insn->code),
-					       BPF_WRITE, -1, false, false);
-			if (err)
-				return err;
-
-			err = save_aux_ptr_type(env, dst_reg_type, false);
-			if (err)
-				return err;
-		} else if (class == BPF_JMP || class == BPF_JMP32) {
-			u8 opcode = BPF_OP(insn->code);
-
-			env->jmps_processed++;
-			if (opcode == BPF_CALL) {
-				if (BPF_SRC(insn->code) != BPF_K ||
-				    (insn->src_reg != BPF_PSEUDO_KFUNC_CALL
-				     && insn->off != 0) ||
-				    (insn->src_reg != BPF_REG_0 &&
-				     insn->src_reg != BPF_PSEUDO_CALL &&
-				     insn->src_reg != BPF_PSEUDO_KFUNC_CALL) ||
-				    insn->dst_reg != BPF_REG_0 ||
-				    class == BPF_JMP32) {
-					verbose(env, "BPF_CALL uses reserved fields\n");
-					return -EINVAL;
-				}
-
-				if (env->cur_state->active_locks) {
-					if ((insn->src_reg == BPF_REG_0 && insn->imm != BPF_FUNC_spin_unlock) ||
-					    (insn->src_reg == BPF_PSEUDO_KFUNC_CALL &&
-					     (insn->off != 0 || !kfunc_spin_allowed(insn->imm)))) {
-						verbose(env, "function calls are not allowed while holding a lock\n");
-						return -EINVAL;
-					}
-				}
-				if (insn->src_reg == BPF_PSEUDO_CALL) {
-					err = check_func_call(env, insn, &env->insn_idx);
-				} else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
-					err = check_kfunc_call(env, insn, &env->insn_idx);
-					if (!err && is_bpf_throw_kfunc(insn)) {
-						exception_exit = true;
-						goto process_bpf_exit_full;
-					}
-				} else {
-					err = check_helper_call(env, insn, &env->insn_idx);
-				}
-				if (err)
-					return err;
-
-				mark_reg_scratched(env, BPF_REG_0);
-			} else if (opcode == BPF_JA) {
-				if (BPF_SRC(insn->code) != BPF_K ||
-				    insn->src_reg != BPF_REG_0 ||
-				    insn->dst_reg != BPF_REG_0 ||
-				    (class == BPF_JMP && insn->imm != 0) ||
-				    (class == BPF_JMP32 && insn->off != 0)) {
-					verbose(env, "BPF_JA uses reserved fields\n");
-					return -EINVAL;
-				}
-
-				if (class == BPF_JMP)
-					env->insn_idx += insn->off + 1;
-				else
-					env->insn_idx += insn->imm + 1;
-				continue;
-
-			} else if (opcode == BPF_EXIT) {
-				if (BPF_SRC(insn->code) != BPF_K ||
-				    insn->imm != 0 ||
-				    insn->src_reg != BPF_REG_0 ||
-				    insn->dst_reg != BPF_REG_0 ||
-				    class == BPF_JMP32) {
-					verbose(env, "BPF_EXIT uses reserved fields\n");
-					return -EINVAL;
-				}
-process_bpf_exit_full:
-				/* We must do check_reference_leak here before
-				 * prepare_func_exit to handle the case when
-				 * state->curframe > 0, it may be a callback
-				 * function, for which reference_state must
-				 * match caller reference state when it exits.
-				 */
-				err = check_resource_leak(env, exception_exit, !env->cur_state->curframe,
-							  "BPF_EXIT instruction in main prog");
-				if (err)
-					return err;
-
-				/* The side effect of the prepare_func_exit
-				 * which is being skipped is that it frees
-				 * bpf_func_state. Typically, process_bpf_exit
-				 * will only be hit with outermost exit.
-				 * copy_verifier_state in pop_stack will handle
-				 * freeing of any extra bpf_func_state left over
-				 * from not processing all nested function
-				 * exits. We also skip return code checks as
-				 * they are not needed for exceptional exits.
-				 */
-				if (exception_exit)
-					goto process_bpf_exit;
-
-				if (state->curframe) {
-					/* exit from nested function */
-					err = prepare_func_exit(env, &env->insn_idx);
-					if (err)
-						return err;
-					do_print_state = true;
-					continue;
-				}
-
-				err = check_return_code(env, BPF_REG_0, "R0");
-				if (err)
-					return err;
+		err = do_check_insn(env, insn, pop_log, &do_print_state, regs, state,
+				    &prev_insn_idx);
+		if (err < 0) {
+			return err;
+		} else if (err == INSN_IDX_MODIFIED) {
+			continue;
+		} else if (err == PROCESS_BPF_EXIT) {
 process_bpf_exit:
-				mark_verifier_state_scratched(env);
-				update_branch_counts(env, env->cur_state);
-				err = pop_stack(env, &prev_insn_idx,
-						&env->insn_idx, pop_log);
-				if (err < 0) {
-					if (err != -ENOENT)
-						return err;
-					break;
-				} else {
-					if (WARN_ON_ONCE(env->cur_state->loop_entry)) {
-						verbose(env, "verifier bug: env->cur_state->loop_entry != NULL\n");
-						return -EFAULT;
-					}
-					do_print_state = true;
-					continue;
-				}
-			} else {
-				err = check_cond_jmp_op(env, insn, &env->insn_idx);
-				if (err)
-					return err;
-			}
-		} else if (class == BPF_LD) {
-			u8 mode = BPF_MODE(insn->code);
-
-			if (mode == BPF_ABS || mode == BPF_IND) {
-				err = check_ld_abs(env, insn);
-				if (err)
-					return err;
-
-			} else if (mode == BPF_IMM) {
-				err = check_ld_imm(env, insn);
-				if (err)
+			mark_verifier_state_scratched(env);
+			update_branch_counts(env, env->cur_state);
+			err = pop_stack(env, &prev_insn_idx, &env->insn_idx,
+					pop_log);
+			if (err < 0) {
+				if (err != -ENOENT)
 					return err;
-
-				env->insn_idx++;
-				sanitize_mark_insn_seen(env);
+				break;
 			} else {
-				verbose(env, "invalid BPF_LD mode\n");
-				return -EINVAL;
+				if (WARN_ON_ONCE(env->cur_state->loop_entry)) {
+					verbose(env, "verifier bug: env->cur_state->loop_entry != NULL\n");
+					return -EFAULT;
+				}
+				do_print_state = true;
+				continue;
 			}
-		} else {
-			verbose(env, "unknown insn class %d\n", class);
-			return -EINVAL;
 		}
+		WARN_ON_ONCE(err);
 
 		env->insn_idx++;
 	}
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:21:18 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:21:18 +0100
Subject: [PATCH bpf-next 02/11] bpf: Return -EFAULT on misconfigurations
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313172127.1098195-3-luis.gerhorst@fau.de>

Mark these cases as non-recoverable to later prevent them from being
cought when they occur during speculative path verification.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 199a6341ac82..6234d0bb59d6 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8889,7 +8889,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env,
 	if (!meta->map_ptr) {
 		/* kernel subsystem misconfigured verifier */
 		verbose(env, "invalid map_ptr to access map->type\n");
-		return -EACCES;
+		return -EFAULT;
 	}
 
 	switch (meta->map_ptr->map_type) {
@@ -9577,7 +9577,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 			 * that kernel subsystem misconfigured verifier
 			 */
 			verbose(env, "invalid map_ptr to access map->key\n");
-			return -EACCES;
+			return -EFAULT;
 		}
 		key_size = meta->map_ptr->key_size;
 		err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL);
@@ -9604,7 +9604,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 		if (!meta->map_ptr) {
 			/* kernel subsystem misconfigured verifier */
 			verbose(env, "invalid map_ptr to access map->value\n");
-			return -EACCES;
+			return -EFAULT;
 		}
 		meta->raw_mode = arg_type & MEM_UNINIT;
 		err = check_helper_mem_access(env, regno, meta->map_ptr->value_size,
@@ -10903,7 +10903,7 @@ record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
 
 	if (map == NULL) {
 		verbose(env, "kernel subsystem misconfigured verifier\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	/* In case of read-only, some additional restrictions
@@ -10942,7 +10942,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
 		return 0;
 	if (!map || map->map_type != BPF_MAP_TYPE_PROG_ARRAY) {
 		verbose(env, "kernel subsystem misconfigured verifier\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	reg = &regs[BPF_REG_3];
@@ -11196,7 +11196,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 	if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
 		verbose(env, "kernel subsystem misconfigured func %s#%d: r1 != ctx\n",
 			func_id_name(func_id), func_id);
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	memset(&meta, 0, sizeof(meta));
@@ -11498,7 +11498,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 		if (meta.map_ptr == NULL) {
 			verbose(env,
 				"kernel subsystem misconfigured verifier\n");
-			return -EINVAL;
+			return -EFAULT;
 		}
 
 		if (func_id == BPF_FUNC_map_lookup_elem &&
@@ -16528,7 +16528,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
 		dst_reg->type = CONST_PTR_TO_MAP;
 	} else {
 		verbose(env, "bpf verifier is misconfigured\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	return 0;
@@ -16575,7 +16575,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 
 	if (!env->ops->gen_ld_abs) {
 		verbose(env, "bpf verifier is misconfigured\n");
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	if (insn->dst_reg != BPF_REG_0 || insn->off != 0 ||
@@ -20614,7 +20614,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 						 -(subprogs[0].stack_depth + 8));
 		if (epilogue_cnt >= INSN_BUF_SIZE) {
 			verbose(env, "bpf verifier is misconfigured\n");
-			return -EINVAL;
+			return -EFAULT;
 		} else if (epilogue_cnt) {
 			/* Save the ARG_PTR_TO_CTX for the epilogue to use */
 			cnt = 0;
@@ -20637,13 +20637,13 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 	if (ops->gen_prologue || env->seen_direct_write) {
 		if (!ops->gen_prologue) {
 			verbose(env, "bpf verifier is misconfigured\n");
-			return -EINVAL;
+			return -EFAULT;
 		}
 		cnt = ops->gen_prologue(insn_buf, env->seen_direct_write,
 					env->prog);
 		if (cnt >= INSN_BUF_SIZE) {
 			verbose(env, "bpf verifier is misconfigured\n");
-			return -EINVAL;
+			return -EFAULT;
 		} else if (cnt) {
 			new_prog = bpf_patch_insn_data(env, 0, insn_buf, cnt);
 			if (!new_prog)
@@ -20800,7 +20800,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 
 			if (type == BPF_WRITE) {
 				verbose(env, "bpf verifier narrow ctx access misconfigured\n");
-				return -EINVAL;
+				return -EFAULT;
 			}
 
 			size_code = BPF_H;
@@ -20819,7 +20819,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 		if (cnt == 0 || cnt >= INSN_BUF_SIZE ||
 		    (ctx_field_size && !target_size)) {
 			verbose(env, "bpf verifier is misconfigured\n");
-			return -EINVAL;
+			return -EFAULT;
 		}
 
 		if (is_narrower_load && size < target_size) {
@@ -20827,7 +20827,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 				off, size, size_default) * 8;
 			if (shift && cnt + 1 >= INSN_BUF_SIZE) {
 				verbose(env, "bpf verifier narrow ctx load misconfigured\n");
-				return -EINVAL;
+				return -EFAULT;
 			}
 			if (ctx_field_size <= 4) {
 				if (shift)
@@ -21590,7 +21590,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
 			cnt = env->ops->gen_ld_abs(insn, insn_buf);
 			if (cnt == 0 || cnt >= INSN_BUF_SIZE) {
 				verbose(env, "bpf verifier is misconfigured\n");
-				return -EINVAL;
+				return -EFAULT;
 			}
 
 			new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
@@ -21926,7 +21926,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
 					goto patch_map_ops_generic;
 				if (cnt <= 0 || cnt >= INSN_BUF_SIZE) {
 					verbose(env, "bpf verifier is misconfigured\n");
-					return -EINVAL;
+					return -EFAULT;
 				}
 
 				new_prog = bpf_patch_insn_data(env, i + delta,
@@ -22286,7 +22286,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
 		    !map_ptr->ops->map_poke_untrack ||
 		    !map_ptr->ops->map_poke_run) {
 			verbose(env, "bpf verifier is misconfigured\n");
-			return -EINVAL;
+			return -EFAULT;
 		}
 
 		ret = map_ptr->ops->map_poke_track(map_ptr, prog->aux);
-- 
2.48.1



From mripard at kernel.org  Thu Mar 13 10:24:25 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Thu, 13 Mar 2025 18:24:25 +0100
Subject: [PATCH v4 00/14] Add support for suppressing warning backtraces
In-Reply-To: <202503131016.5DCEAEC945@keescook>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <202503131016.5DCEAEC945@keescook>
Message-ID: <20250313-abiding-vivid-robin-159dfa@houat>

Hi,

On Thu, Mar 13, 2025 at 10:17:49AM -0700, Kees Cook wrote:
> On Thu, Mar 13, 2025 at 11:43:15AM +0000, Alessandro Carminati wrote:
> > Some unit tests intentionally trigger warning backtraces by passing bad
> > parameters to kernel API functions. Such unit tests typically check the
> > return value from such calls, not the existence of the warning backtrace.
> 
> Thanks for picking this series back up! I honestly thought this had
> already landed. :)
> 
> > With CONFIG_KUNIT enabled, image size increase with this series applied is
> > approximately 1%. The image size increase (and with it the functionality
> > introduced by this series) can be avoided by disabling
> > CONFIG_KUNIT_SUPPRESS_BACKTRACE.
> 
> Yeah, as with my prior review, I'm a fan of this. It makes a bunch of my
> very noisy tests much easier to deal with.

And for the record, we're also affected by this in DRM and would very
much like to get it merged in one shape or another.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/f6035d16/attachment.sig>

From yang at os.amperecomputing.com  Thu Mar 13 10:28:10 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Thu, 13 Mar 2025 10:28:10 -0700
Subject: [v3 PATCH 0/6] arm64: support FEAT_BBM level 2 and large block
 mapping when rodata=full
In-Reply-To: <20250304222018.615808-1-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
Message-ID: <3750d3f8-17c6-4bb8-8107-215d442e4ec3@os.amperecomputing.com>

Hi Ryan,

I saw Miko posted a new spin of his patches. There are some slight 
changes that have impact to my patches (basically check the new boot 
parameter). Do you prefer I rebase my patches on top of his new spin 
right now then restart review from the new spin or review the current 
patches then solve the new review comments and rebase to Miko's new spin 
together?

Thanks,
Yang


On 3/4/25 2:19 PM, Yang Shi wrote:
> Changelog
> =========
> v3:
>    * Rebased to v6.14-rc4.
>    * Based on Miko's BBML2 cpufeature patch (https://lore.kernel.org/linux-arm-kernel/20250228182403.6269-3-miko.lenczewski at arm.com/).
>      Also included in this series in order to have the complete patchset.
>    * Enhanced __create_pgd_mapping() to handle split as well per Ryan.
>    * Supported CONT mappings per Ryan.
>    * Supported asymmetric system by splitting kernel linear mapping if such
>      system is detected per Ryan. I don't have such system to test, so the
>      testing is done by hacking kernel to call linear mapping repainting
>      unconditionally. The linear mapping doesn't have any block and cont
>      mappings after booting.
>
> RFC v2:
>    * Used allowlist to advertise BBM lv2 on the CPUs which can handle TLB
>      conflict gracefully per Will Deacon
>    * Rebased onto v6.13-rc5
>    * https://lore.kernel.org/linux-arm-kernel/20250103011822.1257189-1-yang at os.amperecomputing.com/
>
> RFC v1: https://lore.kernel.org/lkml/20241118181711.962576-1-yang at os.amperecomputing.com/
>
> Description
> ===========
> When rodata=full kernel linear mapping is mapped by PTE due to arm's
> break-before-make rule.
>
> A number of performance issues arise when the kernel linear map is using
> PTE entries due to arm's break-before-make rule:
>    - performance degradation
>    - more TLB pressure
>    - memory waste for kernel page table
>
> These issues can be avoided by specifying rodata=on the kernel command
> line but this disables the alias checks on page table permissions and
> therefore compromises security somewhat.
>
> With FEAT_BBM level 2 support it is no longer necessary to invalidate the
> page table entry when changing page sizes.  This allows the kernel to
> split large mappings after boot is complete.
>
> This patch adds support for splitting large mappings when FEAT_BBM level 2
> is available and rodata=full is used. This functionality will be used
> when modifying page permissions for individual page frames.
>
> Without FEAT_BBM level 2 we will keep the kernel linear map using PTEs
> only.
>
> If the system is asymmetric, the kernel linear mapping may be repainted once
> the BBML2 capability is finalized on all CPUs.  See patch #6 for more details.
>
> We saw significant performance increases in some benchmarks with
> rodata=full without compromising the security features of the kernel.
>
> Testing
> =======
> The test was done on AmpereOne machine (192 cores, 1P) with 256GB memory and
> 4K page size + 48 bit VA.
>
> Function test (4K/16K/64K page size)
>    - Kernel boot.  Kernel needs change kernel linear mapping permission at
>      boot stage, if the patch didn't work, kernel typically didn't boot.
>    - Module stress from stress-ng. Kernel module load change permission for
>      linear mapping.
>    - A test kernel module which allocates 80% of total memory via vmalloc(),
>      then change the vmalloc area permission to RO, this also change linear
>      mapping permission to RO, then change it back before vfree(). Then launch
>      a VM which consumes almost all physical memory.
>    - VM with the patchset applied in guest kernel too.
>    - Kernel build in VM with guest kernel which has this series applied.
>    - rodata=on. Make sure other rodata mode is not broken.
>    - Boot on the machine which doesn't support BBML2.
>
> Performance
> ===========
> Memory consumption
> Before:
> MemTotal:       258988984 kB
> MemFree:        254821700 kB
>
> After:
> MemTotal:       259505132 kB
> MemFree:        255410264 kB
>
> Around 500MB more memory are free to use.  The larger the machine, the
> more memory saved.
>
> Performance benchmarking
> * Memcached
> We saw performance degradation when running Memcached benchmark with
> rodata=full vs rodata=on.  Our profiling pointed to kernel TLB pressure.
> With this patchset we saw ops/sec is increased by around 3.5%, P99
> latency is reduced by around 9.6%.
> The gain mainly came from reduced kernel TLB misses.  The kernel TLB
> MPKI is reduced by 28.5%.
>
> The benchmark data is now on par with rodata=on too.
>
> * Disk encryption (dm-crypt) benchmark
> Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
> encryption (by dm-crypt).
> fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
>      --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
>      --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
>      --name=iops-test-job --eta-newline=1 --size 100G
>
> The IOPS is increased by 90% - 150% (the variance is high, but the worst
> number of good case is around 90% more than the best number of bad case).
> The bandwidth is increased and the avg clat is reduced proportionally.
>
> * Sequential file read
> Read 100G file sequentially on XFS (xfs_io read with page cache populated).
> The bandwidth is increased by 150%.
>
>
> Miko?aj Lenczewski (1):
>        arm64: Add BBM Level 2 cpu feature
>
> Yang Shi (5):
>        arm64: cpufeature: add AmpereOne to BBML2 allow list
>        arm64: mm: make __create_pgd_mapping() and helpers non-void
>        arm64: mm: support large block mapping when rodata=full
>        arm64: mm: support split CONT mappings
>        arm64: mm: split linear mapping if BBML2 is not supported on secondary CPUs
>
>   arch/arm64/Kconfig                  |  11 +++++
>   arch/arm64/include/asm/cpucaps.h    |   2 +
>   arch/arm64/include/asm/cpufeature.h |  15 ++++++
>   arch/arm64/include/asm/mmu.h        |   4 ++
>   arch/arm64/include/asm/pgtable.h    |  12 ++++-
>   arch/arm64/kernel/cpufeature.c      |  95 +++++++++++++++++++++++++++++++++++++
>   arch/arm64/mm/mmu.c                 | 397 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
>   arch/arm64/mm/pageattr.c            |  37 ++++++++++++---
>   arch/arm64/tools/cpucaps            |   1 +
>   9 files changed, 518 insertions(+), 56 deletions(-)
>
>



From quic_philber at quicinc.com  Thu Mar 13 10:36:58 2025
From: quic_philber at quicinc.com (Peter Hilber)
Date: Thu, 13 Mar 2025 18:36:58 +0100
Subject: [PATCH v6 2/4] virtio_rtc: Add PTP clocks
In-Reply-To: <20250313173707.1492-1-quic_philber@quicinc.com>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
Message-ID: <20250313173707.1492-3-quic_philber@quicinc.com>

Expose the virtio_rtc clocks as PTP clocks to userspace, similar to
ptp_kvm. virtio_rtc can expose multiple clocks, e.g. a UTC clock and a
monotonic clock.

Userspace should distinguish different clocks through the name assigned by
the driver. In particular, UTC-like clocks can also be distinguished by if
and how leap seconds are smeared. udev rules such as the following can be
used to get different symlinks for different clock types:

	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 0/variant 0", SYMLINK += "ptp_virtio"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 1/variant 0", SYMLINK += "ptp_virtio_tai"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 2/variant 0", SYMLINK += "ptp_virtio_monotonic"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 3/variant 0", SYMLINK += "ptp_virtio_smear_unspecified"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 3/variant 1", SYMLINK += "ptp_virtio_smear_noon_linear"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 3/variant 2", SYMLINK += "ptp_virtio_smear_sls"
	SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 4/variant 0", SYMLINK += "ptp_virtio_maybe_smeared"

The preferred PTP clock reading method is ioctl PTP_SYS_OFFSET_PRECISE2,
through the ptp_clock_info.getcrosststamp() op. For now,
PTP_SYS_OFFSET_PRECISE2 will return -EOPNOTSUPP through a weak function.
PTP_SYS_OFFSET_PRECISE2 requires cross-timestamping support for specific
clocksources, which will be added in the following. If the clocksource
specific code is enabled, check that the Virtio RTC device supports the
respective HW counter before obtaining an actual cross-timestamp from the
Virtio device.

The Virtio RTC device response time may be higher than the timekeeper
seqcount increment interval. Therefore, obtain the cross-timestamp before
calling get_device_system_crosststamp().

As a fallback, support the ioctl PTP_SYS_OFFSET_EXTENDED2 for all
platforms.

Assume that concurrency issues during PTP clock removal are avoided by the
posix_clock framework.

Kconfig recursive dependencies prevent virtio_rtc from implicitly enabling
PTP_1588_CLOCK, therefore just warn the user if PTP_1588_CLOCK is not
available. Since virtio_rtc should in the future also expose clocks as RTC
class devices, do not depend VIRTIO_RTC on PTP_1588_CLOCK.

Signed-off-by: Peter Hilber <quic_philber at quicinc.com>
---

Notes:
    v6:
    
    - Shorten PTP clock names to always fit into 32 bytes.
    
    - Do not mark comments missing parameter documentation as kernel doc (Simon
      Horman).
    
    v5:
    
    - Fix style issues.
    
    v4:
    
    - Distinguish UTC-like clocks by handling of leap seconds (spec v6).
    
    - For PTP clock name, always use numeric clock type, and numeric variant.
    
    - Update types to spec v6.
    
    - Cosmetic improvements.
    
    v3:
    
    - don't guard cross-timestamping with feature bit (spec v3)
    
    - reduce clock id to 16 bits (spec v3)
    
    v2:
    
    - Depend on prerequisite patch series "treewide: Use clocksource id for
      get_device_system_crosststamp()".
    
    - Check clocksource id before sending crosststamp message to device.
    
    - Do not support multiple hardware counters at runtime any more, since
      distinction of Arm physical and virtual counter appears unneeded after
      discussion with Marc Zyngier.

 drivers/virtio/Kconfig               |  24 +-
 drivers/virtio/Makefile              |   1 +
 drivers/virtio/virtio_rtc_driver.c   | 121 +++++++++-
 drivers/virtio/virtio_rtc_internal.h |  46 ++++
 drivers/virtio/virtio_rtc_ptp.c      | 347 +++++++++++++++++++++++++++
 5 files changed, 535 insertions(+), 4 deletions(-)
 create mode 100644 drivers/virtio/virtio_rtc_ptp.c

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 83bcb06acb6c..a14a2b77e142 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -194,11 +194,33 @@ config VIRTIO_RTC
 	depends on PTP_1588_CLOCK_OPTIONAL
 	help
 	 This driver provides current time from a Virtio RTC device. The driver
-	 provides the time through one or more clocks.
+	 provides the time through one or more clocks. The Virtio RTC PTP
+	 clocks must be enabled to expose the clocks to userspace.
 
 	 To compile this code as a module, choose M here: the module will be
 	 called virtio_rtc.
 
 	 If unsure, say M.
 
+if VIRTIO_RTC
+
+comment "WARNING: Consider enabling VIRTIO_RTC_PTP."
+	depends on !VIRTIO_RTC_PTP
+
+comment "Enable PTP_1588_CLOCK in order to enable VIRTIO_RTC_PTP."
+	depends on PTP_1588_CLOCK=n
+
+config VIRTIO_RTC_PTP
+	bool "Virtio RTC PTP clocks"
+	default y
+	depends on PTP_1588_CLOCK
+	help
+	 This exposes any Virtio RTC clocks as PTP Hardware Clocks (PHCs) to
+	 userspace. The PHC sysfs attribute "clock_name" describes the clock
+	 type.
+
+	 If unsure, say Y.
+
+endif # VIRTIO_RTC
+
 endif # VIRTIO_MENU
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index c41c4c0f9264..88d6fb8d4731 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_VIRTIO_DMA_SHARED_BUFFER) += virtio_dma_buf.o
 obj-$(CONFIG_VIRTIO_DEBUG) += virtio_debug.o
 obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o
 virtio_rtc-y := virtio_rtc_driver.o
+virtio_rtc-$(CONFIG_VIRTIO_RTC_PTP) += virtio_rtc_ptp.o
diff --git a/drivers/virtio/virtio_rtc_driver.c b/drivers/virtio/virtio_rtc_driver.c
index c87ee4e63424..dfe736581e85 100644
--- a/drivers/virtio/virtio_rtc_driver.c
+++ b/drivers/virtio/virtio_rtc_driver.c
@@ -38,11 +38,16 @@ struct viortc_vq {
  * struct viortc_dev - virtio_rtc device data
  * @vdev: virtio device
  * @vqs: virtqueues
+ * @clocks_to_unregister: Clock references, which are only used during device
+ *                        removal.
+ *			  For other uses, there would be a race between device
+ *			  creation and setting the pointers here.
  * @num_clocks: # of virtio_rtc clocks
  */
 struct viortc_dev {
 	struct virtio_device *vdev;
 	struct viortc_vq vqs[VIORTC_MAX_NR_QUEUES];
+	struct viortc_ptp_clock **clocks_to_unregister;
 	u16 num_clocks;
 };
 
@@ -638,6 +643,99 @@ int viortc_cross_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
  * init, deinit
  */
 
+/**
+ * viortc_init_ptp_clock() - init and register PTP clock
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ * @clock_type: virtio_rtc clock type
+ * @leap_second_smearing: virtio_rtc leap second smearing
+ *
+ * Context: Process context.
+ * Return: Positive if registered, zero if not supported by configuration,
+ *         negative error code otherwise.
+ */
+static int viortc_init_ptp_clock(struct viortc_dev *viortc, u16 vio_clk_id,
+				 u8 clock_type, u8 leap_second_smearing)
+{
+	struct device *dev = &viortc->vdev->dev;
+	char ptp_clock_name[PTP_CLOCK_NAME_LEN];
+	struct viortc_ptp_clock *vio_ptp;
+
+	snprintf(ptp_clock_name, PTP_CLOCK_NAME_LEN,
+		 "Virtio PTP type %d/variant %d", clock_type,
+		 leap_second_smearing);
+
+	vio_ptp = viortc_ptp_register(viortc, dev, vio_clk_id, ptp_clock_name);
+	if (IS_ERR(vio_ptp)) {
+		dev_err(dev, "failed to register PTP clock '%s'\n",
+			ptp_clock_name);
+		return PTR_ERR(vio_ptp);
+	}
+
+	viortc->clocks_to_unregister[vio_clk_id] = vio_ptp;
+
+	return !!vio_ptp;
+}
+
+/**
+ * viortc_init_clock() - init local representation of virtio_rtc clock
+ * @viortc: device data
+ * @vio_clk_id: virtio_rtc clock id
+ *
+ * Initializes PHC to represent virtio_rtc clock.
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_init_clock(struct viortc_dev *viortc, u16 vio_clk_id)
+{
+	u8 clock_type, leap_second_smearing;
+	bool is_exposed = false;
+	int ret;
+
+	ret = viortc_clock_cap(viortc, vio_clk_id, &clock_type,
+			       &leap_second_smearing);
+	if (ret)
+		return ret;
+
+	if (IS_ENABLED(CONFIG_VIRTIO_RTC_PTP)) {
+		ret = viortc_init_ptp_clock(viortc, vio_clk_id, clock_type,
+					    leap_second_smearing);
+		if (ret < 0)
+			return ret;
+		if (ret > 0)
+			is_exposed = true;
+	}
+
+	if (!is_exposed)
+		dev_warn(&viortc->vdev->dev,
+			 "cannot expose clock %d (type %d, variant %d) to userspace\n",
+			 vio_clk_id, clock_type, leap_second_smearing);
+
+	return 0;
+}
+
+/**
+ * viortc_clocks_deinit() - unregister PHCs
+ * @viortc: device data
+ */
+static void viortc_clocks_deinit(struct viortc_dev *viortc)
+{
+	struct viortc_ptp_clock *vio_ptp;
+	unsigned int i;
+
+	for (i = 0; i < viortc->num_clocks; i++) {
+		vio_ptp = viortc->clocks_to_unregister[i];
+
+		if (!vio_ptp)
+			continue;
+
+		viortc->clocks_to_unregister[i] = NULL;
+
+		WARN_ON(viortc_ptp_unregister(vio_ptp, &viortc->vdev->dev));
+	}
+}
+
 /**
  * viortc_clocks_init() - init local representations of virtio_rtc clocks
  * @viortc: device data
@@ -648,6 +746,7 @@ int viortc_cross_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
 static int viortc_clocks_init(struct viortc_dev *viortc)
 {
 	u16 num_clocks;
+	unsigned int i;
 	int ret;
 
 	ret = viortc_cfg(viortc, &num_clocks);
@@ -661,8 +760,22 @@ static int viortc_clocks_init(struct viortc_dev *viortc)
 
 	viortc->num_clocks = num_clocks;
 
-	/* In the future, PTP clocks will be initialized here. */
-	(void)viortc_clock_cap;
+	viortc->clocks_to_unregister =
+		devm_kcalloc(&viortc->vdev->dev, num_clocks,
+			     sizeof(*viortc->clocks_to_unregister), GFP_KERNEL);
+	if (!viortc->clocks_to_unregister)
+		return -ENOMEM;
+
+	for (i = 0; i < num_clocks; i++) {
+		ret = viortc_init_clock(viortc, i);
+		if (ret)
+			goto err_deinit_clocks;
+	}
+
+	return 0;
+
+err_deinit_clocks:
+	viortc_clocks_deinit(viortc);
 
 	return ret;
 }
@@ -741,7 +854,9 @@ static int viortc_probe(struct virtio_device *vdev)
  */
 static void viortc_remove(struct virtio_device *vdev)
 {
-	/* In the future, PTP clocks will be deinitialized here. */
+	struct viortc_dev *viortc = vdev->priv;
+
+	viortc_clocks_deinit(viortc);
 
 	virtio_reset_device(vdev);
 	vdev->config->del_vqs(vdev);
diff --git a/drivers/virtio/virtio_rtc_internal.h b/drivers/virtio/virtio_rtc_internal.h
index 9c249c15b68f..2e589903d04f 100644
--- a/drivers/virtio/virtio_rtc_internal.h
+++ b/drivers/virtio/virtio_rtc_internal.h
@@ -9,6 +9,7 @@
 #ifndef _VIRTIO_RTC_INTERNAL_H_
 #define _VIRTIO_RTC_INTERNAL_H_
 
+#include <linux/ptp_clock_kernel.h>
 #include <linux/types.h>
 
 /* driver core IFs */
@@ -21,4 +22,49 @@ int viortc_read_cross(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
 int viortc_cross_cap(struct viortc_dev *viortc, u16 vio_clk_id, u8 hw_counter,
 		     bool *supported);
 
+/* PTP IFs */
+
+struct viortc_ptp_clock;
+
+#if IS_ENABLED(CONFIG_VIRTIO_RTC_PTP)
+
+struct viortc_ptp_clock *viortc_ptp_register(struct viortc_dev *viortc,
+					     struct device *parent_dev,
+					     u16 vio_clk_id,
+					     const char *ptp_clock_name);
+int viortc_ptp_unregister(struct viortc_ptp_clock *vio_ptp,
+			  struct device *parent_dev);
+
+#else
+
+static inline struct viortc_ptp_clock *
+viortc_ptp_register(struct viortc_dev *viortc, struct device *parent_dev,
+		    u16 vio_clk_id, const char *ptp_clock_name)
+{
+	return NULL;
+}
+
+static inline int viortc_ptp_unregister(struct viortc_ptp_clock *vio_ptp,
+					struct device *parent_dev)
+{
+	return -ENODEV;
+}
+
+#endif
+
+/* HW counter IFs */
+
+/**
+ * viortc_hw_xtstamp_params() - get HW-specific xtstamp params
+ * @hw_counter: virtio_rtc HW counter type
+ * @cs_id: clocksource id corresponding to hw_counter
+ *
+ * Gets the HW-specific xtstamp params. Returns an error if the driver cannot
+ * support xtstamp.
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+int viortc_hw_xtstamp_params(u8 *hw_counter, enum clocksource_ids *cs_id);
+
 #endif /* _VIRTIO_RTC_INTERNAL_H_ */
diff --git a/drivers/virtio/virtio_rtc_ptp.c b/drivers/virtio/virtio_rtc_ptp.c
new file mode 100644
index 000000000000..f84599950cd4
--- /dev/null
+++ b/drivers/virtio/virtio_rtc_ptp.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Expose virtio_rtc clocks as PTP clocks.
+ *
+ * Copyright (C) 2022-2023 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Derived from ptp_kvm_common.c, virtual PTP 1588 clock for use with KVM
+ * guests.
+ *
+ * Copyright (C) 2017 Red Hat Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/ptp_clock_kernel.h>
+
+#include <uapi/linux/virtio_rtc.h>
+
+#include "virtio_rtc_internal.h"
+
+/**
+ * struct viortc_ptp_clock - PTP clock abstraction
+ * @ptp_clock: PTP clock handle for unregistering
+ * @viortc: virtio_rtc device data
+ * @ptp_info: PTP clock description
+ * @vio_clk_id: virtio_rtc clock id
+ * @have_cross: device supports crosststamp with available HW counter
+ */
+struct viortc_ptp_clock {
+	struct ptp_clock *ptp_clock;
+	struct viortc_dev *viortc;
+	struct ptp_clock_info ptp_info;
+	u16 vio_clk_id;
+	bool have_cross;
+};
+
+/**
+ * struct viortc_ptp_cross_ctx - context for get_device_system_crosststamp()
+ * @device_time: device clock reading
+ * @system_counterval: HW counter value at device_time
+ *
+ * Provides the already obtained crosststamp to get_device_system_crosststamp().
+ */
+struct viortc_ptp_cross_ctx {
+	ktime_t device_time;
+	struct system_counterval_t system_counterval;
+};
+
+/* Weak function in case get_device_system_crosststamp() is not supported */
+int __weak viortc_hw_xtstamp_params(u8 *hw_counter, enum clocksource_ids *cs_id)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
+ * viortc_ptp_get_time_fn() - callback for get_device_system_crosststamp()
+ * @device_time: device clock reading
+ * @system_counterval: HW counter value at device_time
+ * @ctx: context with already obtained crosststamp
+ *
+ * Return: zero (success).
+ */
+static int viortc_ptp_get_time_fn(ktime_t *device_time,
+				  struct system_counterval_t *system_counterval,
+				  void *ctx)
+{
+	struct viortc_ptp_cross_ctx *vio_ctx = ctx;
+
+	*device_time = vio_ctx->device_time;
+	*system_counterval = vio_ctx->system_counterval;
+
+	return 0;
+}
+
+/**
+ * viortc_ptp_do_xtstamp() - get crosststamp from device
+ * @vio_ptp: virtio_rtc PTP clock
+ * @hw_counter: virtio_rtc HW counter type
+ * @cs_id: clocksource id corresponding to hw_counter
+ * @ctx: context for get_device_system_crosststamp()
+ *
+ * Reads HW-specific crosststamp from device.
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_ptp_do_xtstamp(struct viortc_ptp_clock *vio_ptp,
+				 u8 hw_counter, enum clocksource_ids cs_id,
+				 struct viortc_ptp_cross_ctx *ctx)
+{
+	u64 max_ns, ns;
+	int ret;
+
+	ctx->system_counterval.cs_id = cs_id;
+
+	ret = viortc_read_cross(vio_ptp->viortc, vio_ptp->vio_clk_id,
+				hw_counter, &ns,
+				&ctx->system_counterval.cycles);
+	if (ret)
+		return ret;
+
+	max_ns = (u64)ktime_to_ns(KTIME_MAX);
+	if (ns > max_ns)
+		return -EINVAL;
+
+	ctx->device_time = ns_to_ktime(ns);
+
+	return 0;
+}
+
+/*
+ * PTP clock operations
+ */
+
+/**
+ * viortc_ptp_getcrosststamp() - PTP clock getcrosststamp op
+ * @ptp: PTP clock info
+ * @xtstamp: crosststamp
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
+				     struct system_device_crosststamp *xtstamp)
+{
+	struct viortc_ptp_clock *vio_ptp =
+		container_of(ptp, struct viortc_ptp_clock, ptp_info);
+	struct system_time_snapshot history_begin;
+	struct viortc_ptp_cross_ctx ctx;
+	enum clocksource_ids cs_id;
+	u8 hw_counter;
+	int ret;
+
+	if (!vio_ptp->have_cross)
+		return -EOPNOTSUPP;
+
+	ret = viortc_hw_xtstamp_params(&hw_counter, &cs_id);
+	if (ret)
+		return ret;
+
+	ktime_get_snapshot(&history_begin);
+	if (history_begin.cs_id != cs_id)
+		return -EOPNOTSUPP;
+
+	/*
+	 * Getting the timestamp can take many milliseconds with a slow Virtio
+	 * device. This is too long for viortc_ptp_get_time_fn() passed to
+	 * get_device_system_crosststamp(), which has to usually return before
+	 * the timekeeper seqcount increases (every tick or so).
+	 *
+	 * So, get the actual cross-timestamp first.
+	 */
+	ret = viortc_ptp_do_xtstamp(vio_ptp, hw_counter, cs_id, &ctx);
+	if (ret)
+		return ret;
+
+	ret = get_device_system_crosststamp(viortc_ptp_get_time_fn, &ctx,
+					    &history_begin, xtstamp);
+	if (ret)
+		pr_debug("%s: get_device_system_crosststamp() returned %d\n",
+			 __func__, ret);
+
+	return ret;
+}
+
+/* viortc_ptp_adjfine() - unsupported PTP clock adjfine op */
+static int viortc_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	return -EOPNOTSUPP;
+}
+
+/* viortc_ptp_adjtime() - unsupported PTP clock adjtime op */
+static int viortc_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	return -EOPNOTSUPP;
+}
+
+/* viortc_ptp_settime64() - unsupported PTP clock settime64 op */
+static int viortc_ptp_settime64(struct ptp_clock_info *ptp,
+				const struct timespec64 *ts)
+{
+	return -EOPNOTSUPP;
+}
+
+/*
+ * viortc_ptp_gettimex64() - PTP clock gettimex64 op
+ *
+ * Context: Process context.
+ */
+static int viortc_ptp_gettimex64(struct ptp_clock_info *ptp,
+				 struct timespec64 *ts,
+				 struct ptp_system_timestamp *sts)
+{
+	struct viortc_ptp_clock *vio_ptp =
+		container_of(ptp, struct viortc_ptp_clock, ptp_info);
+	int ret;
+	u64 ns;
+
+	ptp_read_system_prets(sts);
+	ret = viortc_read(vio_ptp->viortc, vio_ptp->vio_clk_id, &ns);
+	ptp_read_system_postts(sts);
+
+	if (ret)
+		return ret;
+
+	if (ns > (u64)S64_MAX)
+		return -EINVAL;
+
+	*ts = ns_to_timespec64((s64)ns);
+
+	return 0;
+}
+
+/* viortc_ptp_enable() - unsupported PTP clock enable op */
+static int viortc_ptp_enable(struct ptp_clock_info *ptp,
+			     struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+/*
+ * viortc_ptp_info_template - ptp_clock_info template
+ *
+ * The .name member will be set for individual virtio_rtc PTP clocks.
+ *
+ * The .getcrosststamp member will be cleared for PTP clocks not supporting
+ * crosststamp.
+ */
+static const struct ptp_clock_info viortc_ptp_info_template = {
+	.owner = THIS_MODULE,
+	/* .name is set according to clock type */
+	.adjfine = viortc_ptp_adjfine,
+	.adjtime = viortc_ptp_adjtime,
+	.gettimex64 = viortc_ptp_gettimex64,
+	.settime64 = viortc_ptp_settime64,
+	.enable = viortc_ptp_enable,
+	.getcrosststamp = viortc_ptp_getcrosststamp,
+};
+
+/**
+ * viortc_ptp_unregister() - PTP clock unregistering wrapper
+ * @vio_ptp: virtio_rtc PTP clock
+ * @parent_dev: parent device of PTP clock
+ *
+ * Return: Zero on success, negative error code otherwise.
+ */
+int viortc_ptp_unregister(struct viortc_ptp_clock *vio_ptp,
+			  struct device *parent_dev)
+{
+	int ret = ptp_clock_unregister(vio_ptp->ptp_clock);
+
+	if (!ret)
+		devm_kfree(parent_dev, vio_ptp);
+
+	return ret;
+}
+
+/**
+ * viortc_ptp_get_cross_cap() - get xtstamp support info from device
+ * @viortc: virtio_rtc device data
+ * @vio_ptp: virtio_rtc PTP clock abstraction
+ *
+ * Context: Process context.
+ * Return: Zero on success, negative error code otherwise.
+ */
+static int viortc_ptp_get_cross_cap(struct viortc_dev *viortc,
+				    struct viortc_ptp_clock *vio_ptp)
+{
+	enum clocksource_ids cs_id;
+	bool xtstamp_supported;
+	u8 hw_counter;
+	int ret;
+
+	ret = viortc_hw_xtstamp_params(&hw_counter, &cs_id);
+	if (ret) {
+		vio_ptp->have_cross = false;
+		return 0;
+	}
+
+	ret = viortc_cross_cap(viortc, vio_ptp->vio_clk_id, hw_counter,
+			       &xtstamp_supported);
+	if (ret)
+		return ret;
+
+	vio_ptp->have_cross = xtstamp_supported;
+
+	return 0;
+}
+
+/**
+ * viortc_ptp_register() - prepare and register PTP clock
+ * @viortc: virtio_rtc device data
+ * @parent_dev: parent device for PTP clock
+ * @vio_clk_id: id of virtio_rtc clock which backs PTP clock
+ * @ptp_clock_name: PTP clock name
+ *
+ * Context: Process context.
+ * Return: Pointer on success, ERR_PTR() otherwise; NULL if PTP clock support
+ *         not available.
+ */
+struct viortc_ptp_clock *viortc_ptp_register(struct viortc_dev *viortc,
+					     struct device *parent_dev,
+					     u16 vio_clk_id,
+					     const char *ptp_clock_name)
+{
+	struct viortc_ptp_clock *vio_ptp;
+	struct ptp_clock *ptp_clock;
+	ssize_t len;
+	int ret;
+
+	vio_ptp = devm_kzalloc(parent_dev, sizeof(*vio_ptp), GFP_KERNEL);
+	if (!vio_ptp)
+		return ERR_PTR(-ENOMEM);
+
+	vio_ptp->viortc = viortc;
+	vio_ptp->vio_clk_id = vio_clk_id;
+	vio_ptp->ptp_info = viortc_ptp_info_template;
+	len = strscpy(vio_ptp->ptp_info.name, ptp_clock_name,
+		      sizeof(vio_ptp->ptp_info.name));
+	if (len < 0) {
+		ret = len;
+		goto err_free_dev;
+	}
+
+	ret = viortc_ptp_get_cross_cap(viortc, vio_ptp);
+	if (ret)
+		goto err_free_dev;
+
+	if (!vio_ptp->have_cross)
+		vio_ptp->ptp_info.getcrosststamp = NULL;
+
+	ptp_clock = ptp_clock_register(&vio_ptp->ptp_info, parent_dev);
+	if (IS_ERR(ptp_clock))
+		goto err_on_register;
+
+	vio_ptp->ptp_clock = ptp_clock;
+
+	return vio_ptp;
+
+err_on_register:
+	ret = PTR_ERR(ptp_clock);
+
+err_free_dev:
+	devm_kfree(parent_dev, vio_ptp);
+	return ERR_PTR(ret);
+}
-- 
2.43.0



From ryan.roberts at arm.com  Thu Mar 13 11:17:02 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 18:17:02 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313181319.GB40525@mazurka.cambridge.arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <0abe8643-d4ea-4e77-bd77-afe07399eec9@os.amperecomputing.com>
 <20250313181319.GB40525@mazurka.cambridge.arm.com>
Message-ID: <83c04cc2-a170-4d4d-82e3-23aec9749352@arm.com>

On 13/03/2025 18:13, Miko?aj Lenczewski wrote:
> On Thu, Mar 13, 2025 at 10:21:51AM -0700, Yang Shi wrote:
>> On 3/13/25 3:41 AM, Miko?aj Lenczewski wrote:
>>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>>> index fb8752b42ec8..3e4cc917a07e 100644
>>> --- a/Documentation/admin-guide/kernel-parameters.txt
>>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>>> @@ -453,6 +453,9 @@
>>>   	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>>>   			32 bit applications.
>>>   
>>> +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
>>> +			2 support
>>
>> Hi Miko,
>>
>> A question about the kernel boot parameter. Can this parameter be used 
>> in early boot stage? A quick look at the code shows it should be ok, for 
>> example, cpu_has_bti() is called in map_kernel(). But I'd like to double 
>> check because my patchset needs to check this parameter in map_mem() to 
>> determine whether large block mapping can be used or not.
>>
>> And a nit below.
> 
> I will need to double check exactly when the arm64 software overrides
> are finalised, but as long as those values are finalised in / before (?)
> the early boot stage then it should be fine? Will reply again once I
> check and have an answer.

This will work fine. The override is setup in the PI code before start_kernel().

>    
>>> +static inline bool bbml2_possible(void)
>>> +{
>>> +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
>>> +}
>>
>> Can this be moved to cpufeature.h? My patch will use this, anyway I can 
>> do it in my patchset.

I'd prefer to do the moving as part of the series that needs it moved.

Thanks,
Ryan

>>
>> Thanks,
>> Yang
> 
> I can do so. In fact, on second thought, I will probably extend this to
> also include the `IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT)` check as well,
> and then move it to cpufeature.h, instead of folding said check into
> has_bbml2_noabort().
> 



From miko.lenczewski at arm.com  Thu Mar 13 11:20:26 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 13 Mar 2025 18:20:26 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <86ikocomvd.wl-maz@kernel.org>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <86ikocomvd.wl-maz@kernel.org>
Message-ID: <20250313182026.GC40525@mazurka.cambridge.arm.com>

On Thu, Mar 13, 2025 at 05:34:46PM +0000, Marc Zyngier wrote:
> On Thu, 13 Mar 2025 10:41:10 +0000,
> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> > 
> > diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> > index c6b185b885f7..9728faa10390 100644
> > --- a/arch/arm64/kernel/pi/idreg-override.c
> > +++ b/arch/arm64/kernel/pi/idreg-override.c
> > @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
> >  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
> >  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
> >  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> > +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
> >  		{}
> >  	},
> >  };
> > @@ -246,6 +247,7 @@ static const struct {
> >  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
> >  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
> >  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> > +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
> 
> Why is that a SW feature? This looks very much like a HW feature to
> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
> with it. Something like:
> 
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f70..803a0c99f7b46 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
>  	.override	= &id_aa64mmfr2_override,
>  	.fields		= {
>  		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
> +		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
>  		{}
>  	},
>  };
> @@ -246,6 +247,7 @@ static const struct {
>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
>  };
>  
>  static int __init parse_hexdigit(const char *p, u64 *v)
> 
> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.

Thanks for the review.

I think part of this confusion is due to me not including a changelog
(definitely something for the next respin!), but the discussion this
change is based on is found here:

https://lore.kernel.org/all/b46dc626-edc9-4d20-99d2-6cd08a01346c at os.amperecomputing.com/

Essentially, this is a SW feature because we do not check the
id_aa64mmfr2.bbm register as part of the has_bbml2_noabort() cpucap
matches filter. This is because certain hardware implementations
do not actually declare bbml2 via the hardware feature register, despite
implementing our bbml2_noabort feature, and certain hypervisor setups
might result in issues so we want to have an override to allow
potentially disabling the feature for generic kernels.

-- 
Kind regards,
Miko?aj Lenczewski


From ryan.roberts at arm.com  Thu Mar 13 11:22:00 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 13 Mar 2025 18:22:00 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <86ikocomvd.wl-maz@kernel.org>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <86ikocomvd.wl-maz@kernel.org>
Message-ID: <f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>

On 13/03/2025 17:34, Marc Zyngier wrote:
> On Thu, 13 Mar 2025 10:41:10 +0000,
> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
>>
>> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
>> index c6b185b885f7..9728faa10390 100644
>> --- a/arch/arm64/kernel/pi/idreg-override.c
>> +++ b/arch/arm64/kernel/pi/idreg-override.c
>> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
>> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>>  		{}
>>  	},
>>  };
>> @@ -246,6 +247,7 @@ static const struct {
>>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
>> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
> 
> Why is that a SW feature? This looks very much like a HW feature to
> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
> with it. Something like:

I think this implies that we would expect the BBM field to be advertising BBML2
support normally and we would check for that as part of the cpufeature
detection. That's how Miko was doing it in v2, but Yang pointed out that
AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
BBML2 in its MMFR2. So we don't want to check that field, and instead rely
solely on the MIDR allow-list + a command line override. It was me that
suggested putting that in the SW feature register, and I think that still sounds
like the right solution for this situation?

Thanks,
Ryan

> 
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f70..803a0c99f7b46 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
>  	.override	= &id_aa64mmfr2_override,
>  	.fields		= {
>  		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
> +		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
>  		{}
>  	},
>  };
> @@ -246,6 +247,7 @@ static const struct {
>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
>  };
>  
>  static int __init parse_hexdigit(const char *p, u64 *v)
> 
> 
> Thanks,
> 
> 	M.
> 



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:40 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:40 +0100
Subject: [PATCH net-next v3 1/7] net: ethtool: netlink: Allow per-netdevice DUMP operations
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-2-maxime.chevallier@bootlin.com>

We have a number of netlink commands in the ethnl family that may have
multiple objects to dump even for a single net_device, including :

 - PLCA, PSE-PD, phy: one message per PHY device
 - tsinfo: one message per timestamp source (netdev + phys)
 - rss: One per RSS context

To get this behaviour, these netlink commands need to roll a custom
->dumpit().

To prepare making per-netdev DUMP more generic in ethnl, introduce a
member in the ethnl ops to indicate if a given command may allow
pernetdev DUMPs (also referred to as filtered DUMPs).

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 45 +++++++++++++++++++++++++++++--------------
 net/ethtool/netlink.h |  2 ++
 2 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index a163d40c6431..7adede5e4ff1 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -587,21 +587,38 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 	int ret = 0;
 
 	rcu_read_lock();
-	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
-		dev_hold(dev);
+	if (ctx->req_info->dev) {
+		dev = ctx->req_info->dev;
 		rcu_read_unlock();
+		/* Filtered DUMP request targeted to a single netdev. We already
+		 * hold a ref to the netdev from ->start()
+		 */
+		ret = ethnl_default_dump_one(skb, dev, ctx,
+					     genl_info_dump(cb));
+		rcu_read_lock();
+		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
 
-		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
+		if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
+			ret = skb->len;
 
-		rcu_read_lock();
-		dev_put(dev);
+	} else {
+		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
+			dev_hold(dev);
+			rcu_read_unlock();
+
+			ret = ethnl_default_dump_one(skb, dev, ctx,
+						     genl_info_dump(cb));
+
+			rcu_read_lock();
+			dev_put(dev);
 
-		if (ret < 0 && ret != -EOPNOTSUPP) {
-			if (likely(skb->len))
-				ret = skb->len;
-			break;
+			if (ret < 0 && ret != -EOPNOTSUPP) {
+				if (likely(skb->len))
+					ret = skb->len;
+				break;
+			}
+			ret = 0;
 		}
-		ret = 0;
 	}
 	rcu_read_unlock();
 
@@ -635,10 +652,10 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	}
 
 	ret = ethnl_default_parse(req_info, &info->info, ops, false);
-	if (req_info->dev) {
-		/* We ignore device specification in dump requests but as the
-		 * same parser as for non-dump (doit) requests is used, it
-		 * would take reference to the device if it finds one
+	if (req_info->dev && !ops->allow_pernetdev_dump) {
+		/* We ignore device specification in unfiltered dump requests
+		 * but as the same parser as for non-dump (doit) requests is
+		 * used, it would take reference to the device if it finds one
 		 */
 		netdev_put(req_info->dev, &req_info->dev_tracker);
 		req_info->dev = NULL;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index ec6ab5443a6f..4aaa73282d6a 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -331,6 +331,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  * @req_info_size:    size of request info
  * @reply_data_size:  size of reply data
  * @allow_nodev_do:   allow non-dump request with no device identification
+ * @allow_pernetdev_dump: allow filtering dump requests with ifname/ifindex
  * @set_ntf_cmd:      notification to generate on changes (SET)
  * @parse_request:
  *	Parse request except common header (struct ethnl_req_info). Common
@@ -388,6 +389,7 @@ struct ethnl_request_ops {
 	unsigned int		req_info_size;
 	unsigned int		reply_data_size;
 	bool			allow_nodev_do;
+	bool			allow_pernetdev_dump;
 	u8			set_ntf_cmd;
 
 	int (*parse_request)(struct ethnl_req_info *req_info,
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:39 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:39 +0100
Subject: [PATCH net-next v3 0/7] net: ethtool: Introduce ethnl dump helpers
Message-ID: <20250313182647.250007-1-maxime.chevallier@bootlin.com>

Hi everyone,

This is V3 for the ethnl dump support, allowing better handling of
per-phy dump but also any other dump operation that needs to dump more
than one message per netdev.

Changes in V3:
 - Fixed some typos and xmas tree issues
 - Added a missing check for EOPNOTSUPP in patch 1
 - Added missing kdoc
 - Added missing comments in phy_reply_size

Changes in V2:
 - Rebased on the netdev_lock work by Stanislav and the fixes from Eric
 - Fixed a bissectability issue
 - Fixed kdoc for the new ethnl ops and fields

V1: https://lore.kernel.org/netdev/20250305141938.319282-1-maxime.chevallier at bootlin.com/
V2: https://lore.kernel.org/netdev/20250308155440.267782-1-maxime.chevallier at bootlin.com/

As of today when using ethnl's default ops, the DUMP requests will
simply perform a GET for each netdev.

That hits limitations for commands that may return multiple messages for
a single netdev, such as :

 - RSS (listing contexts)
 - All PHY-specific commands (PLCA, PSE-PD, phy)
 - tsinfo (one item for the netdev +  one per phy)

 Commands that need a non-default DUMP support have to re-implement
 ->dumpit() themselves, which prevents using most of ethnl's internal
 circuitry.

This series therefore introduces a better support for dump operations in
ethnl.

The patches 1 and 2 introduce the support for filtered DUMPs, where an
ifindex/ifname can be passed in the request header for the DUMP
operation. This is for when we want to dump everything a netdev
supports, but without doing so for every single netdev. ethtool's
"--show-phys ethX" option for example performs a filtered dump.

Patch 3 introduces 3 new ethnl ops : 
 ->dump_start() to initialize a dump context
 ->dump_one_dev(), that can be implemented per-command to dump
 everything on a given netdev
 ->dump_done() to release the context

The default behaviour for dumps remains the same, calling the whole
->doit() path for each netdev.

Patch 4 introduces a set of ->dump_start(), ->dump_one_dev() and
->dump_done() callback implementations that can simply be plugged into
the existing commands that list objects per-phy, making the 
phy-targeting command behaviour more coherent.

Patch 5 uses that new set of helpers to rewrite the phy.c support, which
now uses the regulat ethnl_ops instead of fully custom genl ops. This
one is the hardest to review, sorry about that, I couldn't really manage
to incrementally rework that file :(

Patches 6 and 7 are where the new dump infra shines, adding per-netdev
per-phy dump support for PLCA and PSE-PD.

We could also consider converting tsinfo/tsconfig, rss and tunnels to
these new ->dump_***() operations as well, but that's out of this
series' scope.

Thanks,

Maxime

Maxime Chevallier (7):
  net: ethtool: netlink: Allow per-netdevice DUMP operations
  net: ethtool: netlink: Rename ethnl_default_dump_one
  net: ethtool: netlink: Introduce command-specific dump_one_dev
  net: ethtool: netlink: Introduce per-phy DUMP helpers
  net: ethtool: phy: Convert the PHY_GET command to generic phy dump
  net: ethtool: plca: Use per-PHY DUMP operations
  net: ethtool: pse-pd: Use per-PHY DUMP operations

 net/ethtool/netlink.c | 190 +++++++++++++++++------
 net/ethtool/netlink.h |  47 +++++-
 net/ethtool/phy.c     | 344 ++++++++++++------------------------------
 net/ethtool/plca.c    |  12 ++
 net/ethtool/pse-pd.c  |   6 +
 5 files changed, 309 insertions(+), 290 deletions(-)

-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:41 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:41 +0100
Subject: [PATCH net-next v3 2/7] net: ethtool: netlink: Rename ethnl_default_dump_one
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-3-maxime.chevallier@bootlin.com>

As we work on getting more objects out of a per-netdev DUMP, rename
ethnl_default_dump_one() into ethnl_default_dump_one_dev(), making it
explicit that this dumps everything for one netdev.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 7adede5e4ff1..644c202d284d 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -540,9 +540,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
-				  const struct ethnl_dump_ctx *ctx,
-				  const struct genl_info *info)
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      const struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -593,8 +593,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 		/* Filtered DUMP request targeted to a single netdev. We already
 		 * hold a ref to the netdev from ->start()
 		 */
-		ret = ethnl_default_dump_one(skb, dev, ctx,
-					     genl_info_dump(cb));
+		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+						 genl_info_dump(cb));
 		rcu_read_lock();
 		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
 
@@ -606,8 +606,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
-			ret = ethnl_default_dump_one(skb, dev, ctx,
-						     genl_info_dump(cb));
+			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+							 genl_info_dump(cb));
 
 			rcu_read_lock();
 			dev_put(dev);
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:43 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:43 +0100
Subject: [PATCH net-next v3 4/7] net: ethtool: netlink: Introduce per-phy DUMP helpers
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-5-maxime.chevallier@bootlin.com>

As there are multiple ethnl commands that report messages based on
phy_device information, let's introduce a set of ethnl generic dump
helpers to allow DUMP support for each PHY on a given netdev.

This logic iterates over the phy_link_topology of each netdev (or a
single netdev for filtered DUMP), and call ethnl_default_dump_one() with
the req_info populated with ifindex + phyindex.

This allows re-using all the existing infra for phy-targetting commands
that already use ethnl generic helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 78 +++++++++++++++++++++++++++++++++++++++++++
 net/ethtool/netlink.h |  6 ++++
 2 files changed, 84 insertions(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 2dc6086e1ab5..821bc8b99306 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -560,6 +560,84 @@ static int ethnl_default_dump_one(struct sk_buff *skb,
 	return ret;
 }
 
+/* Specific context for phy-targeting command DUMP operatins. We keep in context
+ * the latest phy_index we dumped, in case of an interrupted DUMP.
+ */
+struct ethnl_dump_ctx_perphy {
+	unsigned long phy_index;
+};
+
+/**
+ * ethnl_dump_start_perphy() - Initialise a dump for PHY cmds
+ * @ctx: Generic ethnl dump context whose cmd_ctx will be initialized
+ *
+ * Initializes a dump context for ethnl commands that may return
+ * one message per PHY on a single netdev.
+ *
+ * Returns: 0 for success, a negative value for errors.
+ */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx;
+
+	dump_ctx = kzalloc(sizeof(*dump_ctx), GFP_KERNEL);
+	if (!dump_ctx)
+		return -ENOMEM;
+
+	ctx->cmd_ctx = dump_ctx;
+
+	return 0;
+}
+
+/**
+ * ethnl_dump_done_perphy() - Releases the per-phy dump context
+ * @ctx: Generic ethnl dump context whose cmd_ctx will be released
+ */
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx)
+{
+	kfree(ctx->cmd_ctx);
+}
+
+/**
+ * ethnl_dump_one_dev_perphy() - Dump all PHY-related messages for one netdev
+ * @skb: skb containing the DUMP result
+ * @ctx: Dump context. Will be kept across the DUMP operation.
+ * @info: Genl receive info
+ *
+ * Some commands are related to PHY devices attached to netdevs. As there may be
+ * multiple PHYs, this DUMP handler will populate the reply with one message per
+ * PHY on a single netdev.
+ *
+ * Returns: 0 for success or when nothing to do, a negative value otherwise.
+ */
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb,
+			      struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx = ctx->cmd_ctx;
+	struct net_device *dev = ctx->reply_data->dev;
+	struct phy_device_node *pdn;
+	int ret = 0;
+
+	if (!dev->link_topo)
+		return 0;
+
+	xa_for_each_start(&dev->link_topo->phys, dump_ctx->phy_index,
+			  pdn, dump_ctx->phy_index) {
+		ctx->req_info->phy_index = dump_ctx->phy_index;
+
+		/* We can re-use the original dump_one as ->prepare_data in
+		 * commands use ethnl_req_get_phydev(), which gets the PHY from
+		 * what's in req_info
+		 */
+		ret = ethnl_default_dump_one(skb, ctx, info);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
 				      struct ethnl_dump_ctx *ctx,
 				      const struct genl_info *info)
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 79fe98190c64..530a9b5c8b39 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -327,6 +327,12 @@ struct ethnl_dump_ctx {
 	void				*cmd_ctx;
 };
 
+/* Generic callbacks to be used by PHY targeting commands */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx);
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb, struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info);
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx);
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:42 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:42 +0100
Subject: [PATCH net-next v3 3/7] net: ethtool: netlink: Introduce command-specific dump_one_dev
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-4-maxime.chevallier@bootlin.com>

Prepare more generic ethnl DUMP hanldling, by allowing netlink commands
to register their own dump_one_dev() callback. This avoids having to
roll with a fully custom genl ->dumpit callback, allowing the re-use
of some ethnl plumbing.

Fallback to the default dump_one_dev behaviour when no custom callback
is found.

The command dump context is maintained within the ethnl_dump_ctx, that
we move in netlink.h so that command handlers can access it.

This context can be allocated/freed in new ->dump_start() and
->dump_done() callbacks.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c | 62 +++++++++++++++++++++++++------------------
 net/ethtool/netlink.h | 35 ++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 644c202d284d..2dc6086e1ab5 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -339,24 +339,6 @@ int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
 
 /* GET request helpers */
 
-/**
- * struct ethnl_dump_ctx - context structure for generic dumpit() callback
- * @ops:        request ops of currently processed message type
- * @req_info:   parsed request header of processed request
- * @reply_data: data needed to compose the reply
- * @pos_ifindex: saved iteration position - ifindex
- *
- * These parameters are kept in struct netlink_callback as context preserved
- * between iterations. They are initialized by ethnl_default_start() and used
- * in ethnl_default_dumpit() and ethnl_default_done().
- */
-struct ethnl_dump_ctx {
-	const struct ethnl_request_ops	*ops;
-	struct ethnl_req_info		*req_info;
-	struct ethnl_reply_data		*reply_data;
-	unsigned long			pos_ifindex;
-};
-
 static const struct ethnl_request_ops *
 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_STRSET_GET]	= &ethnl_strset_request_ops,
@@ -540,9 +522,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				      const struct ethnl_dump_ctx *ctx,
-				      const struct genl_info *info)
+static int ethnl_default_dump_one(struct sk_buff *skb,
+				  const struct ethnl_dump_ctx *ctx,
+				  const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -553,15 +535,15 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 	if (!ehdr)
 		return -EMSGSIZE;
 
-	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
 	rtnl_lock();
-	netdev_lock_ops(dev);
+	netdev_lock_ops(ctx->reply_data->dev);
 	ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
-	netdev_unlock_ops(dev);
+	netdev_unlock_ops(ctx->reply_data->dev);
 	rtnl_unlock();
 	if (ret < 0)
 		goto out;
-	ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
+	ret = ethnl_fill_reply_header(skb, ctx->reply_data->dev,
+				      ctx->ops->hdr_attr);
 	if (ret < 0)
 		goto out;
 	ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data);
@@ -569,11 +551,29 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 out:
 	if (ctx->ops->cleanup_data)
 		ctx->ops->cleanup_data(ctx->reply_data);
-	ctx->reply_data->dev = NULL;
+
 	if (ret < 0)
 		genlmsg_cancel(skb, ehdr);
 	else
 		genlmsg_end(skb, ehdr);
+
+	return ret;
+}
+
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
+{
+	int ret;
+
+	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
+
+	if (ctx->ops->dump_one_dev)
+		ret = ctx->ops->dump_one_dev(skb, ctx, info);
+	else
+		ret = ethnl_default_dump_one(skb, ctx, info);
+
+	ctx->reply_data->dev = NULL;
 	return ret;
 }
 
@@ -606,6 +606,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 			dev_hold(dev);
 			rcu_read_unlock();
 
+			ctx->req_info->dev = dev;
 			ret = ethnl_default_dump_one_dev(skb, dev, ctx,
 							 genl_info_dump(cb));
 
@@ -668,6 +669,12 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	ctx->reply_data = reply_data;
 	ctx->pos_ifindex = 0;
 
+	if (ctx->ops->dump_start) {
+		ret = ctx->ops->dump_start(ctx);
+		if (ret)
+			goto free_reply_data;
+	}
+
 	return 0;
 
 free_reply_data:
@@ -683,6 +690,9 @@ static int ethnl_default_done(struct netlink_callback *cb)
 {
 	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
 
+	if (ctx->ops->dump_done)
+		ctx->ops->dump_done(ctx);
+
 	kfree(ctx->reply_data);
 	kfree(ctx->req_info);
 
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 4aaa73282d6a..79fe98190c64 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -307,6 +307,26 @@ struct ethnl_reply_data {
 	struct net_device		*dev;
 };
 
+/**
+ * struct ethnl_dump_ctx - context structure for generic dumpit() callback
+ * @ops:        request ops of currently processed message type
+ * @req_info:   parsed request header of processed request
+ * @reply_data: data needed to compose the reply
+ * @pos_ifindex: saved iteration position - ifindex
+ * @cmd_ctx: command-specific context to maintain across the dump.
+ *
+ * These parameters are kept in struct netlink_callback as context preserved
+ * between iterations. They are initialized by ethnl_default_start() and used
+ * in ethnl_default_dumpit() and ethnl_default_done().
+ */
+struct ethnl_dump_ctx {
+	const struct ethnl_request_ops	*ops;
+	struct ethnl_req_info		*req_info;
+	struct ethnl_reply_data		*reply_data;
+	unsigned long			pos_ifindex;
+	void				*cmd_ctx;
+};
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
@@ -373,6 +393,15 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  *	 - 0 if no configuration has changed
  *	 - 1 if configuration changed and notification should be generated
  *	 - negative errno on errors
+ * @dump_start:
+ *	Optional callback to prepare a dump operation, should there be a need
+ *	to maintain some context across the dump.
+ * @dump_one_dev:
+ *	Optional callback to generate all messages for a given netdev. This
+ *	is relevant only when a request can produce different results for the
+ *	same netdev depending on command-specific attributes.
+ * @dump_done:
+ *	Optional callback to cleanup any context allocated in ->dump_start()
  *
  * Description of variable parts of GET request handling when using the
  * unified infrastructure. When used, a pointer to an instance of this
@@ -409,6 +438,12 @@ struct ethnl_request_ops {
 			    struct genl_info *info);
 	int (*set)(struct ethnl_req_info *req_info,
 		   struct genl_info *info);
+
+	int (*dump_start)(struct ethnl_dump_ctx *ctx);
+	int (*dump_one_dev)(struct sk_buff *skb,
+			    struct ethnl_dump_ctx *ctx,
+			    const struct genl_info *info);
+	void (*dump_done)(struct ethnl_dump_ctx *ctx);
 };
 
 /* request handlers */
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:44 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:44 +0100
Subject: [PATCH net-next v3 5/7] net: ethtool: phy: Convert the PHY_GET command to generic phy dump
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-6-maxime.chevallier@bootlin.com>

Now that we have an infrastructure in ethnl for perphy DUMPs, we can get
rid of the custom ->doit and ->dumpit to deal with PHY listing commands.

As most of the code was custom, this basically means re-writing how we
deal with PHY listing.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/netlink.c |   9 +-
 net/ethtool/netlink.h |   4 -
 net/ethtool/phy.c     | 344 ++++++++++++------------------------------
 3 files changed, 105 insertions(+), 252 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 821bc8b99306..b32ddfe7cf88 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -382,6 +382,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_MM_SET]		= &ethnl_mm_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_GET]	= &ethnl_tsconfig_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_SET]	= &ethnl_tsconfig_request_ops,
+	[ETHTOOL_MSG_PHY_GET]		= &ethnl_phy_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1374,10 +1375,10 @@ static const struct genl_ops ethtool_genl_ops[] = {
 	},
 	{
 		.cmd	= ETHTOOL_MSG_PHY_GET,
-		.doit	= ethnl_phy_doit,
-		.start	= ethnl_phy_start,
-		.dumpit	= ethnl_phy_dumpit,
-		.done	= ethnl_phy_done,
+		.doit	= ethnl_default_doit,
+		.start	= ethnl_default_start,
+		.dumpit	= ethnl_default_dumpit,
+		.done	= ethnl_default_done,
 		.policy = ethnl_phy_get_policy,
 		.maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1,
 	},
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 530a9b5c8b39..60f16090640f 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -542,10 +542,6 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info);
 int ethnl_rss_dump_start(struct netlink_callback *cb);
 int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_start(struct netlink_callback *cb);
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_done(struct netlink_callback *cb);
 int ethnl_tsinfo_start(struct netlink_callback *cb);
 int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_tsinfo_done(struct netlink_callback *cb);
diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c
index 1f590e8d75ed..88343fed7366 100644
--- a/net/ethtool/phy.c
+++ b/net/ethtool/phy.c
@@ -12,304 +12,160 @@
 #include <net/netdev_lock.h>
 
 struct phy_req_info {
-	struct ethnl_req_info		base;
-	struct phy_device_node		*pdn;
+	struct ethnl_req_info base;
 };
 
-#define PHY_REQINFO(__req_base) \
-	container_of(__req_base, struct phy_req_info, base)
+struct phy_reply_data {
+	struct ethnl_reply_data	base;
+	u32 phyindex;
+	char *drvname;
+	char *name;
+	unsigned int upstream_type;
+	char *upstream_sfp_name;
+	unsigned int upstream_index;
+	char *downstream_sfp_name;
+};
+
+#define PHY_REPDATA(__reply_base) \
+	container_of(__reply_base, struct phy_reply_data, base)
 
 const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1] = {
 	[ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
-/* Caller holds rtnl */
-static ssize_t
-ethnl_phy_reply_size(const struct ethnl_req_info *req_base,
-		     struct netlink_ext_ack *extack)
+static int phy_reply_size(const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 	size_t size = 0;
 
-	ASSERT_RTNL();
-
 	/* ETHTOOL_A_PHY_INDEX */
 	size += nla_total_size(sizeof(u32));
 
 	/* ETHTOOL_A_DRVNAME */
-	if (phydev->drv)
-		size += nla_total_size(strlen(phydev->drv->name) + 1);
+	if (rep_data->drvname)
+		size += nla_total_size(strlen(rep_data->drvname) + 1);
 
 	/* ETHTOOL_A_NAME */
-	size += nla_total_size(strlen(dev_name(&phydev->mdio.dev)) + 1);
+	size += nla_total_size(strlen(rep_data->name) + 1);
 
 	/* ETHTOOL_A_PHY_UPSTREAM_TYPE */
 	size += nla_total_size(sizeof(u32));
 
-	if (phy_on_sfp(phydev)) {
-		const char *upstream_sfp_name = sfp_get_name(pdn->parent_sfp_bus);
-
-		/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
-		if (upstream_sfp_name)
-			size += nla_total_size(strlen(upstream_sfp_name) + 1);
+	/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
+	if (rep_data->upstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->upstream_sfp_name) + 1);
 
-		/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	if (rep_data->upstream_index)
 		size += nla_total_size(sizeof(u32));
-	}
 
 	/* ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME */
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
-
-		if (sfp_name)
-			size += nla_total_size(strlen(sfp_name) + 1);
-	}
+	if (rep_data->downstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->downstream_sfp_name) + 1);
 
 	return size;
 }
 
-static int
-ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff *skb)
+static int phy_prepare_data(const struct ethnl_req_info *req_info,
+			    struct ethnl_reply_data *reply_data,
+			    const struct genl_info *info)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
-	enum phy_upstream ptype;
+	struct phy_link_topology *topo = reply_data->dev->link_topo;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
+	struct nlattr **tb = info->attrs;
+	struct phy_device_node *pdn;
+	struct phy_device *phydev;
 
-	ptype = pdn->upstream_type;
+	/* RTNL is held by the caller */
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
+				      info->extack);
+	if (IS_ERR_OR_NULL(phydev))
+		return -EOPNOTSUPP;
 
-	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, phydev->phyindex) ||
-	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, dev_name(&phydev->mdio.dev)) ||
-	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, ptype))
-		return -EMSGSIZE;
+	pdn = xa_load(&topo->phys, phydev->phyindex);
+	if (!pdn)
+		return -EOPNOTSUPP;
 
-	if (phydev->drv &&
-	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, phydev->drv->name))
-		return -EMSGSIZE;
+	rep_data->phyindex = phydev->phyindex;
+	rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
+	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+	rep_data->upstream_type = pdn->upstream_type;
 
-	if (ptype == PHY_UPSTREAM_PHY) {
+	if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
 		struct phy_device *upstream = pdn->upstream.phydev;
-		const char *sfp_upstream_name;
-
-		/* Parent index */
-		if (nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX, upstream->phyindex))
-			return -EMSGSIZE;
-
-		if (pdn->parent_sfp_bus) {
-			sfp_upstream_name = sfp_get_name(pdn->parent_sfp_bus);
-			if (sfp_upstream_name &&
-			    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
-					   sfp_upstream_name))
-				return -EMSGSIZE;
-		}
+		rep_data->upstream_index = upstream->phyindex;
 	}
 
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
+	if (pdn->parent_sfp_bus)
+		rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
+						      GFP_KERNEL);
 
-		if (sfp_name &&
-		    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
-				   sfp_name))
-			return -EMSGSIZE;
-	}
+	if (phydev->sfp_bus)
+		rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
+							GFP_KERNEL);
 
 	return 0;
 }
 
-static int ethnl_phy_parse_request(struct ethnl_req_info *req_base,
-				   struct nlattr **tb,
-				   struct netlink_ext_ack *extack)
+static int phy_fill_reply(struct sk_buff *skb,
+			  const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_link_topology *topo = req_base->dev->link_topo;
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device *phydev;
-
-	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PHY_HEADER,
-				      extack);
-	if (!phydev)
-		return 0;
-
-	if (IS_ERR(phydev))
-		return PTR_ERR(phydev);
-
-	if (!topo)
-		return 0;
-
-	req_info->pdn = xa_load(&topo->phys, phydev->phyindex);
-
-	return 0;
-}
-
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info)
-{
-	struct phy_req_info req_info = {};
-	struct nlattr **tb = info->attrs;
-	struct sk_buff *rskb;
-	void *reply_payload;
-	int reply_len;
-	int ret;
-
-	ret = ethnl_parse_header_dev_get(&req_info.base,
-					 tb[ETHTOOL_A_PHY_HEADER],
-					 genl_info_net(info), info->extack,
-					 true);
-	if (ret < 0)
-		return ret;
-
-	rtnl_lock();
-	netdev_lock_ops(req_info.base.dev);
-
-	ret = ethnl_phy_parse_request(&req_info.base, tb, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-
-	/* No PHY, return early */
-	if (!req_info.pdn)
-		goto err_unlock;
-
-	ret = ethnl_phy_reply_size(&req_info.base, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-	reply_len = ret + ethnl_reply_header_size();
-
-	rskb = ethnl_reply_init(reply_len, req_info.base.dev,
-				ETHTOOL_MSG_PHY_GET_REPLY,
-				ETHTOOL_A_PHY_HEADER,
-				info, &reply_payload);
-	if (!rskb) {
-		ret = -ENOMEM;
-		goto err_unlock;
-	}
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	ret = ethnl_phy_fill_reply(&req_info.base, rskb);
-	if (ret)
-		goto err_free_msg;
-
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	genlmsg_end(rskb, reply_payload);
-
-	return genlmsg_reply(rskb, info);
-
-err_free_msg:
-	nlmsg_free(rskb);
-err_unlock:
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	return ret;
-}
-
-struct ethnl_phy_dump_ctx {
-	struct phy_req_info	*phy_req_info;
-	unsigned long ifindex;
-	unsigned long phy_index;
-};
-
-int ethnl_phy_start(struct netlink_callback *cb)
-{
-	const struct genl_info *info = genl_info_dump(cb);
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	int ret;
+	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, rep_data->phyindex) ||
+	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, rep_data->name) ||
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, rep_data->upstream_type))
+		return -EMSGSIZE;
 
-	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+	if (rep_data->drvname &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, rep_data->drvname))
+		return -EMSGSIZE;
 
-	ctx->phy_req_info = kzalloc(sizeof(*ctx->phy_req_info), GFP_KERNEL);
-	if (!ctx->phy_req_info)
-		return -ENOMEM;
+	if (rep_data->upstream_index &&
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX,
+			rep_data->upstream_index))
+		return -EMSGSIZE;
 
-	ret = ethnl_parse_header_dev_get(&ctx->phy_req_info->base,
-					 info->attrs[ETHTOOL_A_PHY_HEADER],
-					 sock_net(cb->skb->sk), cb->extack,
-					 false);
-	ctx->ifindex = 0;
-	ctx->phy_index = 0;
+	if (rep_data->upstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+			   rep_data->upstream_sfp_name))
+		return -EMSGSIZE;
 
-	if (ret)
-		kfree(ctx->phy_req_info);
+	if (rep_data->downstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+			   rep_data->downstream_sfp_name))
+		return -EMSGSIZE;
 
-	return ret;
+	return 0;
 }
 
-int ethnl_phy_done(struct netlink_callback *cb)
+static void phy_cleanup_data(struct ethnl_reply_data *reply_data)
 {
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-
-	if (ctx->phy_req_info->base.dev)
-		ethnl_parse_header_dev_put(&ctx->phy_req_info->base);
-
-	kfree(ctx->phy_req_info);
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	return 0;
+	kfree(rep_data->drvname);
+	kfree(rep_data->name);
+	kfree(rep_data->upstream_sfp_name);
+	kfree(rep_data->downstream_sfp_name);
 }
 
-static int ethnl_phy_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				  struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct phy_req_info *pri = ctx->phy_req_info;
-	struct phy_device_node *pdn;
-	int ret = 0;
-	void *ehdr;
-
-	if (!dev->link_topo)
-		return 0;
-
-	xa_for_each_start(&dev->link_topo->phys, ctx->phy_index, pdn, ctx->phy_index) {
-		ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_PHY_GET_REPLY);
-		if (!ehdr) {
-			ret = -EMSGSIZE;
-			break;
-		}
-
-		ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_PHY_HEADER);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		pri->pdn = pdn;
-		ret = ethnl_phy_fill_reply(&pri->base, skb);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		genlmsg_end(skb, ehdr);
-	}
+const struct ethnl_request_ops ethnl_phy_request_ops = {
+	.request_cmd		= ETHTOOL_MSG_PHY_GET,
+	.reply_cmd		= ETHTOOL_MSG_PHY_GET_REPLY,
+	.hdr_attr		= ETHTOOL_A_PHY_HEADER,
+	.req_info_size		= sizeof(struct phy_req_info),
+	.reply_data_size	= sizeof(struct phy_reply_data),
 
-	return ret;
-}
+	.prepare_data		= phy_prepare_data,
+	.reply_size		= phy_reply_size,
+	.fill_reply		= phy_fill_reply,
+	.cleanup_data		= phy_cleanup_data,
 
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct net *net = sock_net(skb->sk);
-	struct net_device *dev;
-	int ret = 0;
-
-	rtnl_lock();
-
-	if (ctx->phy_req_info->base.dev) {
-		dev = ctx->phy_req_info->base.dev;
-		netdev_lock_ops(dev);
-		ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-		netdev_unlock_ops(dev);
-	} else {
-		for_each_netdev_dump(net, dev, ctx->ifindex) {
-			netdev_lock_ops(dev);
-			ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-			netdev_unlock_ops(dev);
-			if (ret)
-				break;
-
-			ctx->phy_index = 0;
-		}
-	}
-	rtnl_unlock();
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
 
-	return ret;
-}
+	.allow_pernetdev_dump	= true,
+};
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:45 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:45 +0100
Subject: [PATCH net-next v3 6/7] net: ethtool: plca: Use per-PHY DUMP operations
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-7-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PLCA-able PHY on the link.

This is done for both PLCA status and PLCA config.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/plca.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c
index e1f7820a6158..2148ff607561 100644
--- a/net/ethtool/plca.c
+++ b/net/ethtool/plca.c
@@ -191,6 +191,12 @@ const struct ethnl_request_ops ethnl_plca_cfg_request_ops = {
 
 	.set			= ethnl_set_plca,
 	.set_ntf_cmd		= ETHTOOL_MSG_PLCA_NTF,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
 
 // PLCA get status message -------------------------------------------------- //
@@ -268,4 +274,10 @@ const struct ethnl_request_ops ethnl_plca_status_request_ops = {
 	.prepare_data		= plca_get_status_prepare_data,
 	.reply_size		= plca_get_status_reply_size,
 	.fill_reply		= plca_get_status_fill_reply,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From maxime.chevallier at bootlin.com  Thu Mar 13 11:26:46 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Thu, 13 Mar 2025 19:26:46 +0100
Subject: [PATCH net-next v3 7/7] net: ethtool: pse-pd: Use per-PHY DUMP operations
In-Reply-To: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
Message-ID: <20250313182647.250007-8-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PSE PHY on the link.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
 net/ethtool/pse-pd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
index 4f6b99eab2a6..f3d14be8bdd9 100644
--- a/net/ethtool/pse-pd.c
+++ b/net/ethtool/pse-pd.c
@@ -314,4 +314,10 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
 
 	.set			= ethnl_set_pse,
 	/* PSE has no notification */
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From linux at roeck-us.net  Thu Mar 13 11:31:12 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 13 Mar 2025 11:31:12 -0700
Subject: [PATCH v4 00/14] Add support for suppressing warning backtraces
In-Reply-To: <20250313-abiding-vivid-robin-159dfa@houat>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <202503131016.5DCEAEC945@keescook>
 <20250313-abiding-vivid-robin-159dfa@houat>
Message-ID: <c8287bde-fa1c-4113-af22-4701d40d386e@roeck-us.net>

On Thu, Mar 13, 2025 at 06:24:25PM +0100, Maxime Ripard wrote:
> > 
> > Yeah, as with my prior review, I'm a fan of this. It makes a bunch of my
> > very noisy tests much easier to deal with.
> 
> And for the record, we're also affected by this in DRM and would very
> much like to get it merged in one shape or another.
> 

I was unable to get maintainers of major architectures interested enough
to provide feedback, and did not see a path forward. Maybe Alessandro
has more success than me.

Guenter


From maz at kernel.org  Thu Mar 13 11:36:10 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 18:36:10 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
	<20250313104111.24196-3-miko.lenczewski@arm.com>
	<86ikocomvd.wl-maz@kernel.org>
	<f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
Message-ID: <86h63wok11.wl-maz@kernel.org>

On Thu, 13 Mar 2025 18:22:00 +0000,
Ryan Roberts <ryan.roberts at arm.com> wrote:
> 
> On 13/03/2025 17:34, Marc Zyngier wrote:
> > On Thu, 13 Mar 2025 10:41:10 +0000,
> > Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> >>
> >> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> >> index c6b185b885f7..9728faa10390 100644
> >> --- a/arch/arm64/kernel/pi/idreg-override.c
> >> +++ b/arch/arm64/kernel/pi/idreg-override.c
> >> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
> >>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
> >>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
> >>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> >> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
> >>  		{}
> >>  	},
> >>  };
> >> @@ -246,6 +247,7 @@ static const struct {
> >>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
> >>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
> >>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> >> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
> > 
> > Why is that a SW feature? This looks very much like a HW feature to
> > me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
> > with it. Something like:
> 
> I think this implies that we would expect the BBM field to be advertising BBML2
> support normally and we would check for that as part of the cpufeature
> detection. That's how Miko was doing it in v2, but Yang pointed out that
> AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
> BBML2 in its MMFR2. So we don't want to check that field, and instead rely
> solely on the MIDR allow-list + a command line override. It was me that
> suggested putting that in the SW feature register, and I think that still sounds
> like the right solution for this situation?

I think this is mixing two different things:

- preventing BBM-L2 from being visible to the kernel: this is what my
  suggestion is doing by nuking an architectural feature in the
  relevant register

- random HW not correctly advertising what they are doing: this is an
  erratum workaround

I'd rather we don't conflate the two things, and make them very
explicitly distinct.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Thu Mar 13 11:39:48 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 13 Mar 2025 18:39:48 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313182026.GC40525@mazurka.cambridge.arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
	<20250313104111.24196-3-miko.lenczewski@arm.com>
	<86ikocomvd.wl-maz@kernel.org>
	<20250313182026.GC40525@mazurka.cambridge.arm.com>
Message-ID: <86frjgojuz.wl-maz@kernel.org>

On Thu, 13 Mar 2025 18:20:26 +0000,
Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> 
> On Thu, Mar 13, 2025 at 05:34:46PM +0000, Marc Zyngier wrote:
> > On Thu, 13 Mar 2025 10:41:10 +0000,
> > Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> > > 
> > > diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> > > index c6b185b885f7..9728faa10390 100644
> > > --- a/arch/arm64/kernel/pi/idreg-override.c
> > > +++ b/arch/arm64/kernel/pi/idreg-override.c
> > > @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
> > >  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
> > >  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
> > >  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> > > +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
> > >  		{}
> > >  	},
> > >  };
> > > @@ -246,6 +247,7 @@ static const struct {
> > >  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
> > >  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
> > >  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> > > +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
> > 
> > Why is that a SW feature? This looks very much like a HW feature to
> > me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
> > with it. Something like:
> > 
> > diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> > index c6b185b885f70..803a0c99f7b46 100644
> > --- a/arch/arm64/kernel/pi/idreg-override.c
> > +++ b/arch/arm64/kernel/pi/idreg-override.c
> > @@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
> >  	.override	= &id_aa64mmfr2_override,
> >  	.fields		= {
> >  		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
> > +		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
> >  		{}
> >  	},
> >  };
> > @@ -246,6 +247,7 @@ static const struct {
> >  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
> >  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
> >  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> > +	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
> >  };
> >  
> >  static int __init parse_hexdigit(const char *p, u64 *v)
> > 
> > 
> > Thanks,
> > 
> > 	M.
> > 
> > -- 
> > Without deviation from the norm, progress is not possible.
> 
> Thanks for the review.
> 
> I think part of this confusion is due to me not including a changelog
> (definitely something for the next respin!), but the discussion this
> change is based on is found here:
> 
> https://lore.kernel.org/all/b46dc626-edc9-4d20-99d2-6cd08a01346c at os.amperecomputing.com/
> 
> Essentially, this is a SW feature because we do not check the
> id_aa64mmfr2.bbm register as part of the has_bbml2_noabort() cpucap
> matches filter. This is because certain hardware implementations
> do not actually declare bbml2 via the hardware feature register, despite
> implementing our bbml2_noabort feature, and certain hypervisor setups
> might result in issues so we want to have an override to allow
> potentially disabling the feature for generic kernels.

I replied to Ryan on the same subject: not advertising a feature that
is actually supported is very much an erratum, and we should not
conflate feature control of an architecture feature (which is what the
ID override horror is doing) with implementation-specific workarounds.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From yang at os.amperecomputing.com  Thu Mar 13 10:40:00 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Thu, 13 Mar 2025 10:40:00 -0700
Subject: [v3 PATCH 0/6] arm64: support FEAT_BBM level 2 and large block
 mapping when rodata=full
In-Reply-To: <2fb974bb-1470-4a5f-90d5-97456140c98f@arm.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <3750d3f8-17c6-4bb8-8107-215d442e4ec3@os.amperecomputing.com>
 <2fb974bb-1470-4a5f-90d5-97456140c98f@arm.com>
Message-ID: <22b53cff-00db-48f1-b1e8-b11a54ebb147@os.amperecomputing.com>



On 3/13/25 10:36 AM, Ryan Roberts wrote:
> On 13/03/2025 17:28, Yang Shi wrote:
>> Hi Ryan,
>>
>> I saw Miko posted a new spin of his patches. There are some slight changes that
>> have impact to my patches (basically check the new boot parameter). Do you
>> prefer I rebase my patches on top of his new spin right now then restart review
>> from the new spin or review the current patches then solve the new review
>> comments and rebase to Miko's new spin together?
> Hi Yang,
>
> Sorry I haven't got to reviewing this version yet, it's in my queue!
>
> I'm happy to review against v3 as it is. I'm familiar with Miko's series and am
> not too bothered about the integration with that; I think it's pretty straight
> forward. I'm more interested in how you are handling the splitting, which I
> think is the bulk of the effort.

Yeah, sure, thank you.

>
> I'm hoping to get to this next week before heading out to LSF/MM the following
> week (might I see you there?)

Unfortunately I can't make it this year. Have a fun!

Thanks,
Yang

>
> Thanks,
> Ryan
>
>
>> Thanks,
>> Yang
>>
>>
>> On 3/4/25 2:19 PM, Yang Shi wrote:
>>> Changelog
>>> =========
>>> v3:
>>>  ?? * Rebased to v6.14-rc4.
>>>  ?? * Based on Miko's BBML2 cpufeature patch (https://lore.kernel.org/linux-
>>> arm-kernel/20250228182403.6269-3-miko.lenczewski at arm.com/).
>>>  ???? Also included in this series in order to have the complete patchset.
>>>  ?? * Enhanced __create_pgd_mapping() to handle split as well per Ryan.
>>>  ?? * Supported CONT mappings per Ryan.
>>>  ?? * Supported asymmetric system by splitting kernel linear mapping if such
>>>  ???? system is detected per Ryan. I don't have such system to test, so the
>>>  ???? testing is done by hacking kernel to call linear mapping repainting
>>>  ???? unconditionally. The linear mapping doesn't have any block and cont
>>>  ???? mappings after booting.
>>>
>>> RFC v2:
>>>  ?? * Used allowlist to advertise BBM lv2 on the CPUs which can handle TLB
>>>  ???? conflict gracefully per Will Deacon
>>>  ?? * Rebased onto v6.13-rc5
>>>  ?? * https://lore.kernel.org/linux-arm-kernel/20250103011822.1257189-1-
>>> yang at os.amperecomputing.com/
>>>
>>> RFC v1: https://lore.kernel.org/lkml/20241118181711.962576-1-
>>> yang at os.amperecomputing.com/
>>>
>>> Description
>>> ===========
>>> When rodata=full kernel linear mapping is mapped by PTE due to arm's
>>> break-before-make rule.
>>>
>>> A number of performance issues arise when the kernel linear map is using
>>> PTE entries due to arm's break-before-make rule:
>>>  ?? - performance degradation
>>>  ?? - more TLB pressure
>>>  ?? - memory waste for kernel page table
>>>
>>> These issues can be avoided by specifying rodata=on the kernel command
>>> line but this disables the alias checks on page table permissions and
>>> therefore compromises security somewhat.
>>>
>>> With FEAT_BBM level 2 support it is no longer necessary to invalidate the
>>> page table entry when changing page sizes.? This allows the kernel to
>>> split large mappings after boot is complete.
>>>
>>> This patch adds support for splitting large mappings when FEAT_BBM level 2
>>> is available and rodata=full is used. This functionality will be used
>>> when modifying page permissions for individual page frames.
>>>
>>> Without FEAT_BBM level 2 we will keep the kernel linear map using PTEs
>>> only.
>>>
>>> If the system is asymmetric, the kernel linear mapping may be repainted once
>>> the BBML2 capability is finalized on all CPUs.? See patch #6 for more details.
>>>
>>> We saw significant performance increases in some benchmarks with
>>> rodata=full without compromising the security features of the kernel.
>>>
>>> Testing
>>> =======
>>> The test was done on AmpereOne machine (192 cores, 1P) with 256GB memory and
>>> 4K page size + 48 bit VA.
>>>
>>> Function test (4K/16K/64K page size)
>>>  ?? - Kernel boot.? Kernel needs change kernel linear mapping permission at
>>>  ???? boot stage, if the patch didn't work, kernel typically didn't boot.
>>>  ?? - Module stress from stress-ng. Kernel module load change permission for
>>>  ???? linear mapping.
>>>  ?? - A test kernel module which allocates 80% of total memory via vmalloc(),
>>>  ???? then change the vmalloc area permission to RO, this also change linear
>>>  ???? mapping permission to RO, then change it back before vfree(). Then launch
>>>  ???? a VM which consumes almost all physical memory.
>>>  ?? - VM with the patchset applied in guest kernel too.
>>>  ?? - Kernel build in VM with guest kernel which has this series applied.
>>>  ?? - rodata=on. Make sure other rodata mode is not broken.
>>>  ?? - Boot on the machine which doesn't support BBML2.
>>>
>>> Performance
>>> ===========
>>> Memory consumption
>>> Before:
>>> MemTotal:?????? 258988984 kB
>>> MemFree:??????? 254821700 kB
>>>
>>> After:
>>> MemTotal:?????? 259505132 kB
>>> MemFree:??????? 255410264 kB
>>>
>>> Around 500MB more memory are free to use.? The larger the machine, the
>>> more memory saved.
>>>
>>> Performance benchmarking
>>> * Memcached
>>> We saw performance degradation when running Memcached benchmark with
>>> rodata=full vs rodata=on.? Our profiling pointed to kernel TLB pressure.
>>> With this patchset we saw ops/sec is increased by around 3.5%, P99
>>> latency is reduced by around 9.6%.
>>> The gain mainly came from reduced kernel TLB misses.? The kernel TLB
>>> MPKI is reduced by 28.5%.
>>>
>>> The benchmark data is now on par with rodata=on too.
>>>
>>> * Disk encryption (dm-crypt) benchmark
>>> Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
>>> encryption (by dm-crypt).
>>> fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
>>>  ???? --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
>>>  ???? --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
>>>  ???? --name=iops-test-job --eta-newline=1 --size 100G
>>>
>>> The IOPS is increased by 90% - 150% (the variance is high, but the worst
>>> number of good case is around 90% more than the best number of bad case).
>>> The bandwidth is increased and the avg clat is reduced proportionally.
>>>
>>> * Sequential file read
>>> Read 100G file sequentially on XFS (xfs_io read with page cache populated).
>>> The bandwidth is increased by 150%.
>>>
>>>
>>> Miko?aj Lenczewski (1):
>>>  ?????? arm64: Add BBM Level 2 cpu feature
>>>
>>> Yang Shi (5):
>>>  ?????? arm64: cpufeature: add AmpereOne to BBML2 allow list
>>>  ?????? arm64: mm: make __create_pgd_mapping() and helpers non-void
>>>  ?????? arm64: mm: support large block mapping when rodata=full
>>>  ?????? arm64: mm: support split CONT mappings
>>>  ?????? arm64: mm: split linear mapping if BBML2 is not supported on secondary
>>> CPUs
>>>
>>>  ? arch/arm64/Kconfig????????????????? |? 11 +++++
>>>  ? arch/arm64/include/asm/cpucaps.h??? |?? 2 +
>>>  ? arch/arm64/include/asm/cpufeature.h |? 15 ++++++
>>>  ? arch/arm64/include/asm/mmu.h??????? |?? 4 ++
>>>  ? arch/arm64/include/asm/pgtable.h??? |? 12 ++++-
>>>  ? arch/arm64/kernel/cpufeature.c????? |? 95 +++++++++++++++++++++++++++++++++++++
>>>  ? arch/arm64/mm/mmu.c???????????????? | 397 ++++++++++++++++++++++++++++++++++
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> ++++++++++++++++++++++-------------------
>>>  ? arch/arm64/mm/pageattr.c??????????? |? 37 ++++++++++++---
>>>  ? arch/arm64/tools/cpucaps??????????? |?? 1 +
>>>  ? 9 files changed, 518 insertions(+), 56 deletions(-)
>>>
>>>



From luis.gerhorst at fau.de  Thu Mar 13 10:41:44 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:41:44 +0100
Subject: [PATCH bpf-next 06/11] bpf: Rename sanitize_stack_spill to nospec_result
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313174149.1113165-1-luis.gerhorst@fau.de>

This is made to clarify that this flag will cause a nospec to be added
after this insn and can therefore be relied upon to reduce speculative
path analysis.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Cc: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 include/linux/bpf_verifier.h | 2 +-
 kernel/bpf/verifier.c        | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index d6cfc4ee6820..da586dd4703e 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -563,7 +563,7 @@ struct bpf_insn_aux_data {
 	u64 map_key_state; /* constant (32 bit) key tracking for maps */
 	int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
 	u32 seen; /* this insn was processed by the verifier at env->pass_cnt */
-	bool sanitize_stack_spill; /* subject to Spectre v4 sanitation */
+	bool nospec_result; /* result is unsafe under speculation, nospec must follow */
 	bool zext_dst; /* this insn zero extends dst reg */
 	bool needs_zext; /* alu op needs to clear upper bits */
 	bool storage_get_func_atomic; /* bpf_*_storage_get() with atomic memory alloc */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index eb65038682b0..4c1ed31d86af 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5007,7 +5007,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
 		}
 
 		if (sanitize)
-			env->insn_aux_data[insn_idx].sanitize_stack_spill = true;
+			env->insn_aux_data[insn_idx].nospec_result = true;
 	}
 
 	err = destroy_if_dynptr_stack_slot(env, state, spi);
@@ -20719,7 +20719,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 		}
 
 		if (type == BPF_WRITE &&
-		    env->insn_aux_data[i + delta].sanitize_stack_spill) {
+		    env->insn_aux_data[i + delta].nospec_result) {
 			struct bpf_insn patch[] = {
 				*insn,
 				BPF_ST_NOSPEC(),
-- 
2.48.1



From manivannan.sadhasivam at linaro.org  Thu Mar 13 10:44:16 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Thu, 13 Mar 2025 23:14:16 +0530
Subject: [PATCH 1/4] PCI: cadence: Add support to build pcie-cadence
 library as a kernel module
In-Reply-To: <20250307103128.3287497-2-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-2-s-vadapalli@ti.com>
Message-ID: <20250313174416.n3c4srf6hb2l3bvg@thinkpad>

On Fri, Mar 07, 2025 at 04:01:25PM +0530, Siddharth Vadapalli wrote:
> From: Kishon Vijay Abraham I <kishon at ti.com>
> 
> Currently, the Cadence PCIe controller driver can be built as a built-in
> module only. Since PCIe functionality is not a necessity for booting, add
> support to build the Cadence PCIe driver as a loadable module as well.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

> ---
>  drivers/pci/controller/cadence/Kconfig             |  6 +++---
>  drivers/pci/controller/cadence/pcie-cadence-ep.c   |  6 ++++++
>  drivers/pci/controller/cadence/pcie-cadence-host.c |  9 +++++++++
>  drivers/pci/controller/cadence/pcie-cadence.c      | 12 ++++++++++++
>  drivers/pci/controller/cadence/pcie-cadence.h      |  4 ++--
>  5 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
> index 8a0044bb3989..82b58096eea0 100644
> --- a/drivers/pci/controller/cadence/Kconfig
> +++ b/drivers/pci/controller/cadence/Kconfig
> @@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
>  	depends on PCI
>  
>  config PCIE_CADENCE
> -	bool
> +	tristate
>  
>  config PCIE_CADENCE_HOST
> -	bool
> +	tristate
>  	depends on OF
>  	select IRQ_DOMAIN

Even though this was added earlier, looks like not needed.

- Mani

-- 
????????? ????????


From luis.gerhorst at fau.de  Thu Mar 13 10:41:45 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:41:45 +0100
Subject: [PATCH bpf-next 07/11] bpf: Fall back to nospec for Spectre v1
In-Reply-To: <20250313174149.1113165-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
 <20250313174149.1113165-1-luis.gerhorst@fau.de>
Message-ID: <20250313174149.1113165-2-luis.gerhorst@fau.de>

This implements the core of the series and causes the verifier to fall
back to mitigating Spectre v1 using speculation barriers. The approach
was presented at LPC'24 [1] and RAID'24 [2].

This has the unfortunate consequence that Spectre v1 mitigations now
only support architectures which implement BPF_NOSPEC. Before this
commit, Spectre v1 mitigations prevented exploits by rejecting the
programs on all architectures. Because some JITs do not implement
BPF_NOSPEC, this patch therefore may regress unpriv BPF's security to a
limited extent:

* The regression is limited to systems vulnerable to Spectre v1, have
  unprivileged BPF enabled, and do NOT emit insns for BPF_NOSPEC. The
  latter is not the case for x86 64- and 32-bit, arm64, and powerpc
  64-bit and they are therefore not affected by the regression.
  According to commit a6f6a95f2580 ("LoongArch, bpf: Fix jit to skip
  speculation barrier opcode"), LoongArch is not vulnerable to Spectre
  v1 and therefore also not affected by the regression.

* To the best of my knowledge this regression may therefore only affect
  MIPS. This is deemed acceptable because unpriv BPF is still disabled
  there by default. As stated in a previous commit, BPF_NOSPEC could be
  implemented for MIPS based on GCC's speculation_barrier
  implementation.

* It is unclear which other architectures (besides x86 64- and 32-bit,
  ARM64, PowerPC 64-bit, LoongArch, and MIPS) supported by the kernel
  are vulnerable to Spectre v1. Also, it is not clear if barriers are
  available on these architectures. Implementing BPF_NOSPEC on these
  architectures therefore is non-trivial. Searching GCC and the kernel
  for speculation barrier implementations for these architectures
  yielded no result.

* If any of those regressed systems is also vulnerable to Spectre v4,
  the system was already vulnerable to Spectre v4 attacks based on
  unpriv BPF before this patch and the impact is therefore further
  limited.

As an alternative to regressing security, one could still reject
programs if the architecture does not emit BPF_NOSPEC (e.g., by removing
the empty BPF_NOSPEC-case from all JITs except for LoongArch where it
appears justified). However, this will cause rejections on these archs
that are likely unfounded in the vast majority of cases.

In the tests, some are now successful where we previously had a
false-positive (i.e., rejection). Change them to reflect where the
nospec should be inserted (as comment) and modify the error message if
the nospec is able to mitigate a problem that previously shadowed
another problem.

Briefly went through all the occurrences of EPERM, EINVAL, and EACCESS
in the verifier in order to validate that catching them like this makes
sense.

[1] https://lpc.events/event/18/contributions/1954/ ("Mitigating
    Spectre-PHT using Speculation Barriers in Linux eBPF")
[2] https://arxiv.org/pdf/2405.00078 ("VeriFence: Lightweight and
    Precise Spectre Defenses for Untrusted Linux Kernel Extensions")

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 include/linux/bpf_verifier.h                  |  1 +
 kernel/bpf/verifier.c                         | 68 +++++++++++++++++--
 .../selftests/bpf/progs/verifier_and.c        |  3 +-
 .../selftests/bpf/progs/verifier_bounds.c     | 30 ++++----
 .../selftests/bpf/progs/verifier_movsx.c      |  6 +-
 .../selftests/bpf/progs/verifier_unpriv.c     |  3 +-
 .../bpf/progs/verifier_value_ptr_arith.c      | 14 ++--
 .../selftests/bpf/verifier/dead_code.c        |  3 +-
 tools/testing/selftests/bpf/verifier/jmp32.c  | 33 +++------
 tools/testing/selftests/bpf/verifier/jset.c   | 10 ++-
 10 files changed, 115 insertions(+), 56 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index da586dd4703e..588c6ac79987 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -563,6 +563,7 @@ struct bpf_insn_aux_data {
 	u64 map_key_state; /* constant (32 bit) key tracking for maps */
 	int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
 	u32 seen; /* this insn was processed by the verifier at env->pass_cnt */
+	bool nospec; /* do not execute this instruction speculatively */
 	bool nospec_result; /* result is unsafe under speculation, nospec must follow */
 	bool zext_dst; /* this insn zero extends dst reg */
 	bool needs_zext; /* alu op needs to clear upper bits */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 4c1ed31d86af..8093a5bac4d1 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1990,6 +1990,18 @@ static int pop_stack(struct bpf_verifier_env *env, int *prev_insn_idx,
 	return 0;
 }
 
+static bool error_recoverable_with_nospec(int err)
+{
+	/* Should only return true for non-fatal errors that are allowed to
+	 * occur during speculative verification. For these we can insert a
+	 * nospec and the program might still be accepted. Do not include
+	 * something like ENOMEM because it is likely to re-occur for the next
+	 * architectural path once it has been recovered-from in all speculative
+	 * paths.
+	 */
+	return err == -EPERM || err == -EACCES || err == -EINVAL;
+}
+
 static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 					     int insn_idx, int prev_insn_idx,
 					     bool speculative)
@@ -11084,7 +11096,7 @@ static int check_get_func_ip(struct bpf_verifier_env *env)
 	return -ENOTSUPP;
 }
 
-static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env)
+static struct bpf_insn_aux_data *cur_aux(const struct bpf_verifier_env *env)
 {
 	return &env->insn_aux_data[env->insn_idx];
 }
@@ -13828,7 +13840,9 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
 static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env,
 				    const struct bpf_insn *insn)
 {
-	return env->bypass_spec_v1 || BPF_SRC(insn->code) == BPF_K;
+	return env->bypass_spec_v1 ||
+		BPF_SRC(insn->code) == BPF_K ||
+		cur_aux(env)->nospec;
 }
 
 static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux,
@@ -19514,13 +19528,34 @@ static int do_check(struct bpf_verifier_env *env)
 		sanitize_mark_insn_seen(env);
 		prev_insn_idx = env->insn_idx;
 
+		/* Reduce verification complexity by stopping speculative path
+		 * verification when a nospec is encountered.
+		 */
+		if (state->speculative && cur_aux(env)->nospec)
+			goto process_bpf_exit;
+
 		err = do_check_insn(env, insn, pop_log, &do_print_state, regs, state,
 				    &prev_insn_idx);
-		if (err < 0) {
+		if (state->speculative && error_recoverable_with_nospec(err)) {
+			/* Prevent this speculative path from ever reaching the
+			 * insn that would have been unsafe to execute.
+			 */
+			cur_aux(env)->nospec = true;
+			/* If it was an ADD/SUB insn, potentially remove any
+			 * markings for alu sanitization.
+			 */
+			cur_aux(env)->alu_state = 0;
+			goto process_bpf_exit;
+		} else if (err < 0) {
 			return err;
 		} else if (err == INSN_IDX_MODIFIED) {
 			continue;
 		} else if (err == PROCESS_BPF_EXIT) {
+			goto process_bpf_exit;
+		}
+		WARN_ON_ONCE(err);
+
+		if (state->speculative && cur_aux(env)->nospec_result) {
 process_bpf_exit:
 			mark_verifier_state_scratched(env);
 			update_branch_counts(env, env->cur_state);
@@ -19539,7 +19574,6 @@ static int do_check(struct bpf_verifier_env *env)
 				continue;
 			}
 		}
-		WARN_ON_ONCE(err);
 
 		env->insn_idx++;
 	}
@@ -20670,6 +20704,29 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 		bpf_convert_ctx_access_t convert_ctx_access;
 		u8 mode;
 
+		if (env->insn_aux_data[i + delta].nospec) {
+			WARN_ON_ONCE(env->insn_aux_data[i + delta].alu_state);
+			struct bpf_insn patch[] = {
+				BPF_ST_NOSPEC(),
+				*insn,
+			};
+
+			cnt = ARRAY_SIZE(patch);
+			new_prog = bpf_patch_insn_data(env, i + delta, patch, cnt);
+			if (!new_prog)
+				return -ENOMEM;
+
+			delta    += cnt - 1;
+			env->prog = new_prog;
+			insn      = new_prog->insnsi + i + delta;
+			/* This can not be easily merged with the
+			 * nospec_result-case, because an insn may require a
+			 * nospec before and after itself. Therefore also do not
+			 * 'continue' here but potentially apply further
+			 * patching to insn. *insn should equal patch[1] now.
+			 */
+		}
+
 		if (insn->code == (BPF_LDX | BPF_MEM | BPF_B) ||
 		    insn->code == (BPF_LDX | BPF_MEM | BPF_H) ||
 		    insn->code == (BPF_LDX | BPF_MEM | BPF_W) ||
@@ -20720,6 +20777,9 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
 
 		if (type == BPF_WRITE &&
 		    env->insn_aux_data[i + delta].nospec_result) {
+			/* nospec_result is only used to mitigate Spectre v4 and
+			 * to limit verification-time for Spectre v1.
+			 */
 			struct bpf_insn patch[] = {
 				*insn,
 				BPF_ST_NOSPEC(),
diff --git a/tools/testing/selftests/bpf/progs/verifier_and.c b/tools/testing/selftests/bpf/progs/verifier_and.c
index e97e518516b6..98bafce6d8f3 100644
--- a/tools/testing/selftests/bpf/progs/verifier_and.c
+++ b/tools/testing/selftests/bpf/progs/verifier_and.c
@@ -85,7 +85,7 @@ l0_%=:	r0 = r0;					\
 
 SEC("socket")
 __description("check known subreg with unknown reg")
-__success __failure_unpriv __msg_unpriv("R1 !read_ok")
+__success __success_unpriv
 __retval(0)
 __naked void known_subreg_with_unknown_reg(void)
 {
@@ -96,6 +96,7 @@ __naked void known_subreg_with_unknown_reg(void)
 	r0 &= 0xFFFF1234;				\
 	/* Upper bits are unknown but AND above masks out 1 zero'ing lower bits */\
 	if w0 < 1 goto l0_%=;				\
+	/* unpriv: nospec (inserted to prevent `R1 !read_ok'`) */\
 	r1 = *(u32*)(r1 + 512);				\
 l0_%=:	r0 = 0;						\
 	exit;						\
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
index 0eb33bb801b5..0488ef05a7a4 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
@@ -620,7 +620,7 @@ l1_%=:	exit;						\
 
 SEC("socket")
 __description("bounds check mixed 32bit and 64bit arithmetic. test1")
-__success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
+__success __success_unpriv
 __retval(0)
 __naked void _32bit_and_64bit_arithmetic_test1(void)
 {
@@ -636,6 +636,7 @@ __naked void _32bit_and_64bit_arithmetic_test1(void)
 	if w1 > 2 goto l0_%=;				\
 	goto l1_%=;					\
 l0_%=:	/* invalid ldx if bounds are lost above */	\
+	/* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\
 	r0 = *(u64*)(r0 - 1);				\
 l1_%=:	exit;						\
 "	::: __clobber_all);
@@ -643,7 +644,7 @@ l1_%=:	exit;						\
 
 SEC("socket")
 __description("bounds check mixed 32bit and 64bit arithmetic. test2")
-__success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
+__success __success_unpriv
 __retval(0)
 __naked void _32bit_and_64bit_arithmetic_test2(void)
 {
@@ -660,6 +661,7 @@ __naked void _32bit_and_64bit_arithmetic_test2(void)
 	if r1 > r2 goto l0_%=;				\
 	goto l1_%=;					\
 l0_%=:	/* invalid ldx if bounds are lost above */	\
+	/* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\
 	r0 = *(u64*)(r0 - 1);				\
 l1_%=:	exit;						\
 "	::: __clobber_all);
@@ -691,8 +693,7 @@ l0_%=:	r0 = 0;						\
 
 SEC("socket")
 __description("bounds check for reg = 0, reg xor 1")
-__success __failure_unpriv
-__msg_unpriv("R0 min value is outside of the allowed memory range")
+__success __success_unpriv
 __retval(0)
 __naked void reg_0_reg_xor_1(void)
 {
@@ -708,6 +709,7 @@ __naked void reg_0_reg_xor_1(void)
 l0_%=:	r1 = 0;						\
 	r1 ^= 1;					\
 	if r1 != 0 goto l1_%=;				\
+	/* unpriv: nospec (inserted to prevent `R0 min value is outside of the allowed memory range`) */\
 	r0 = *(u64*)(r0 + 8);				\
 l1_%=:	r0 = 0;						\
 	exit;						\
@@ -719,8 +721,7 @@ l1_%=:	r0 = 0;						\
 
 SEC("socket")
 __description("bounds check for reg32 = 0, reg32 xor 1")
-__success __failure_unpriv
-__msg_unpriv("R0 min value is outside of the allowed memory range")
+__success __success_unpriv
 __retval(0)
 __naked void reg32_0_reg32_xor_1(void)
 {
@@ -736,6 +737,7 @@ __naked void reg32_0_reg32_xor_1(void)
 l0_%=:	w1 = 0;						\
 	w1 ^= 1;					\
 	if w1 != 0 goto l1_%=;				\
+	/* unpriv: nospec (inserted to prevent `R0 min value is outside of the allowed memory range`) */\
 	r0 = *(u64*)(r0 + 8);				\
 l1_%=:	r0 = 0;						\
 	exit;						\
@@ -747,8 +749,7 @@ l1_%=:	r0 = 0;						\
 
 SEC("socket")
 __description("bounds check for reg = 2, reg xor 3")
-__success __failure_unpriv
-__msg_unpriv("R0 min value is outside of the allowed memory range")
+__success __success_unpriv
 __retval(0)
 __naked void reg_2_reg_xor_3(void)
 {
@@ -764,6 +765,7 @@ __naked void reg_2_reg_xor_3(void)
 l0_%=:	r1 = 2;						\
 	r1 ^= 3;					\
 	if r1 > 0 goto l1_%=;				\
+	/* unpriv: nospec (inserted to prevent `R0 min value is outside of the allowed memory range`) */\
 	r0 = *(u64*)(r0 + 8);				\
 l1_%=:	r0 = 0;						\
 	exit;						\
@@ -829,8 +831,7 @@ l1_%=:	r0 = 0;						\
 
 SEC("socket")
 __description("bounds check for reg > 0, reg xor 3")
-__success __failure_unpriv
-__msg_unpriv("R0 min value is outside of the allowed memory range")
+__success __success_unpriv
 __retval(0)
 __naked void reg_0_reg_xor_3(void)
 {
@@ -843,7 +844,8 @@ __naked void reg_0_reg_xor_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 != 0 goto l0_%=;				\
 	exit;						\
-l0_%=:	r1 = *(u64*)(r0 + 0);				\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R0 min value is outside of the allowed memory range`) */\
+	r1 = *(u64*)(r0 + 0);				\
 	if r1 <= 0 goto l1_%=;				\
 	r1 ^= 3;					\
 	if r1 >= 0 goto l1_%=;				\
@@ -858,8 +860,7 @@ l1_%=:	r0 = 0;						\
 
 SEC("socket")
 __description("bounds check for reg32 > 0, reg32 xor 3")
-__success __failure_unpriv
-__msg_unpriv("R0 min value is outside of the allowed memory range")
+__success __success_unpriv
 __retval(0)
 __naked void reg32_0_reg32_xor_3(void)
 {
@@ -872,7 +873,8 @@ __naked void reg32_0_reg32_xor_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 != 0 goto l0_%=;				\
 	exit;						\
-l0_%=:	r1 = *(u64*)(r0 + 0);				\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R0 min value is outside of the allowed memory range`) */\
+	r1 = *(u64*)(r0 + 0);				\
 	if w1 <= 0 goto l1_%=;				\
 	w1 ^= 3;					\
 	if w1 >= 0 goto l1_%=;				\
diff --git a/tools/testing/selftests/bpf/progs/verifier_movsx.c b/tools/testing/selftests/bpf/progs/verifier_movsx.c
index 994bbc346d25..5de9bcbe7425 100644
--- a/tools/testing/selftests/bpf/progs/verifier_movsx.c
+++ b/tools/testing/selftests/bpf/progs/verifier_movsx.c
@@ -245,7 +245,7 @@ l0_%=:							\
 SEC("socket")
 __description("MOV32SX, S8, var_off not u32_max, positive after s8 extension")
 __success __retval(0)
-__failure_unpriv __msg_unpriv("frame pointer is read only")
+__success_unpriv
 __naked void mov64sx_s32_varoff_2(void)
 {
 	asm volatile ("					\
@@ -257,6 +257,7 @@ __naked void mov64sx_s32_varoff_2(void)
 	w0 = 0;						\
 	exit;						\
 l0_%=:							\
+	/* nospec (inserted to prevent `frame pointer is read only`) */\
 	r10 = 1;					\
 	exit;						\
 "	:
@@ -267,7 +268,7 @@ l0_%=:							\
 SEC("socket")
 __description("MOV32SX, S8, var_off not u32_max, negative after s8 extension")
 __success __retval(0)
-__failure_unpriv __msg_unpriv("frame pointer is read only")
+__success_unpriv
 __naked void mov64sx_s32_varoff_3(void)
 {
 	asm volatile ("					\
@@ -280,6 +281,7 @@ __naked void mov64sx_s32_varoff_3(void)
 	w0 = 0;						\
 	exit;						\
 l0_%=:							\
+	/* nospec (inserted to prevent `frame pointer is read only`) */\
 	r10 = 1;					\
 	exit;						\
 "	:
diff --git a/tools/testing/selftests/bpf/progs/verifier_unpriv.c b/tools/testing/selftests/bpf/progs/verifier_unpriv.c
index a4a5e2071604..af35365558ce 100644
--- a/tools/testing/selftests/bpf/progs/verifier_unpriv.c
+++ b/tools/testing/selftests/bpf/progs/verifier_unpriv.c
@@ -572,7 +572,7 @@ l0_%=:	exit;						\
 
 SEC("socket")
 __description("alu32: mov u32 const")
-__success __failure_unpriv __msg_unpriv("R7 invalid mem access 'scalar'")
+__success __success_unpriv
 __retval(0)
 __naked void alu32_mov_u32_const(void)
 {
@@ -581,6 +581,7 @@ __naked void alu32_mov_u32_const(void)
 	w7 &= 1;					\
 	w0 = w7;					\
 	if r0 == 0 goto l0_%=;				\
+	/* unpriv: nospec (inserted to prevent `R7 invalid mem access 'scalar'`) */\
 	r0 = *(u64*)(r7 + 0);				\
 l0_%=:	exit;						\
 "	::: __clobber_all);
diff --git a/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c b/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
index 5ba6e53571c8..2acd7769bd91 100644
--- a/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
+++ b/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
@@ -398,7 +398,8 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: mixing value pointer and scalar, 1")
-__success __failure_unpriv __msg_unpriv("R2 pointer comparison prohibited")
+__success __failure_unpriv
+__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
 __retval(0)
 __naked void value_pointer_and_scalar_1(void)
 {
@@ -433,6 +434,7 @@ l2_%=:	/* common instruction */			\
 l3_%=:	/* branch B */					\
 	r0 = 0x13371337;				\
 	/* verifier follows fall-through */		\
+	/* unpriv: nospec (inserted to prevent `R2 pointer comparison prohibited`) */\
 	if r2 != 0x100000 goto l4_%=;			\
 	r0 = 0;						\
 	exit;						\
@@ -450,7 +452,8 @@ l4_%=:	/* fake-dead code; targeted from branch A to	\
 
 SEC("socket")
 __description("map access: mixing value pointer and scalar, 2")
-__success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
+__success __failure_unpriv
+__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
 __retval(0)
 __naked void value_pointer_and_scalar_2(void)
 {
@@ -466,6 +469,7 @@ __naked void value_pointer_and_scalar_2(void)
 	if r0 != 0 goto l0_%=;				\
 	exit;						\
 l0_%=:	/* load some number from the map into r1 */	\
+	/* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\
 	r1 = *(u8*)(r0 + 0);				\
 	/* depending on r1, branch: */			\
 	if r1 == 0 goto l1_%=;				\
@@ -1296,11 +1300,13 @@ l0_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: value_ptr -= unknown scalar, 2")
-__success __failure_unpriv
-__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
+__success __success_unpriv
 __retval(1)
 __naked void value_ptr_unknown_scalar_2_2(void)
 {
+	/* unpriv: nospec inserted by verifier to mitigate 'R0 pointer
+	 * arithmetic of map value goes out of range'.
+	 */
 	asm volatile ("					\
 	r1 = 0;						\
 	*(u64*)(r10 - 8) = r1;				\
diff --git a/tools/testing/selftests/bpf/verifier/dead_code.c b/tools/testing/selftests/bpf/verifier/dead_code.c
index ee454327e5c6..77207b498c6f 100644
--- a/tools/testing/selftests/bpf/verifier/dead_code.c
+++ b/tools/testing/selftests/bpf/verifier/dead_code.c
@@ -2,14 +2,13 @@
 	"dead code: start",
 	.insns = {
 	BPF_JMP_IMM(BPF_JA, 0, 0, 2),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_JMP_IMM(BPF_JA, 0, 0, 2),
 	BPF_MOV64_IMM(BPF_REG_0, 7),
 	BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 10, -4),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 7,
 },
diff --git a/tools/testing/selftests/bpf/verifier/jmp32.c b/tools/testing/selftests/bpf/verifier/jmp32.c
index 43776f6f92f4..91d83e9cb148 100644
--- a/tools/testing/selftests/bpf/verifier/jmp32.c
+++ b/tools/testing/selftests/bpf/verifier/jmp32.c
@@ -84,11 +84,10 @@
 	BPF_JMP32_IMM(BPF_JSET, BPF_REG_7, 0x10, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP32_IMM(BPF_JGE, BPF_REG_7, 0x10, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 },
 {
@@ -149,11 +148,10 @@
 	BPF_JMP32_IMM(BPF_JEQ, BPF_REG_7, 0x10, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP32_IMM(BPF_JSGE, BPF_REG_7, 0xf, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 },
 {
@@ -214,11 +212,10 @@
 	BPF_JMP32_IMM(BPF_JNE, BPF_REG_7, 0x10, 1),
 	BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x10, 1),
 	BPF_EXIT_INSN(),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 },
 {
@@ -283,11 +280,10 @@
 	BPF_JMP32_REG(BPF_JGE, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP32_IMM(BPF_JGE, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -354,11 +350,10 @@
 	BPF_JMP32_REG(BPF_JGT, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -425,11 +420,10 @@
 	BPF_JMP32_REG(BPF_JLE, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP32_IMM(BPF_JLE, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -496,11 +490,10 @@
 	BPF_JMP32_REG(BPF_JLT, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -567,11 +560,10 @@
 	BPF_JMP32_REG(BPF_JSGE, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JSGE, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -638,11 +630,10 @@
 	BPF_JMP32_REG(BPF_JSGT, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JSGT, BPF_REG_7, -2, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -709,11 +700,10 @@
 	BPF_JMP32_REG(BPF_JSLE, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JSLE, BPF_REG_7, 0x7ffffff0, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -780,11 +770,10 @@
 	BPF_JMP32_REG(BPF_JSLT, BPF_REG_7, BPF_REG_8, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP32_IMM(BPF_JSLT, BPF_REG_7, -1, 1),
+	/* unpriv: nospec (inserted to prevent "R0 invalid mem access 'scalar'") */
 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
-	.errstr_unpriv = "R0 invalid mem access 'scalar'",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 	.retval = 2,
 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
diff --git a/tools/testing/selftests/bpf/verifier/jset.c b/tools/testing/selftests/bpf/verifier/jset.c
index 11fc68da735e..e901eefd774a 100644
--- a/tools/testing/selftests/bpf/verifier/jset.c
+++ b/tools/testing/selftests/bpf/verifier/jset.c
@@ -78,12 +78,11 @@
 	.insns = {
 	BPF_MOV64_IMM(BPF_REG_0, 1),
 	BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	},
 	.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.retval = 1,
 	.result = ACCEPT,
 },
@@ -136,13 +135,12 @@
 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
 	BPF_ALU64_IMM(BPF_OR, BPF_REG_0, 2),
 	BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 3, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_MOV64_IMM(BPF_REG_0, 0),
 	BPF_EXIT_INSN(),
 	},
 	.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 },
 {
@@ -154,16 +152,16 @@
 	BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xff),
 	BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0xf0, 3),
 	BPF_JMP_IMM(BPF_JLT, BPF_REG_1, 0x10, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0x10, 1),
 	BPF_EXIT_INSN(),
 	BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0x10, 1),
+	/* unpriv: nospec (inserted to prevent "R9 !read_ok") */
 	BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
 	BPF_EXIT_INSN(),
 	},
 	.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
-	.errstr_unpriv = "R9 !read_ok",
-	.result_unpriv = REJECT,
 	.result = ACCEPT,
 },
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:41:46 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:41:46 +0100
Subject: [PATCH bpf-next 08/11] bpf: Allow nospec-protected var-offset stack access
In-Reply-To: <20250313174149.1113165-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
 <20250313174149.1113165-1-luis.gerhorst@fau.de>
Message-ID: <20250313174149.1113165-3-luis.gerhorst@fau.de>

Insert a nospec before the access to prevent it from ever using an index
that is subject to speculative scalar-confusion.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8093a5bac4d1..683a76aceffa 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7858,6 +7858,11 @@ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
 	}
 }
 
+static struct bpf_insn_aux_data *cur_aux(const struct bpf_verifier_env *env)
+{
+	return &env->insn_aux_data[env->insn_idx];
+}
+
 /* When register 'regno' is used to read the stack (either directly or through
  * a helper function) make sure that it's within stack boundary and, depending
  * on the access type and privileges, that all elements of the stack are
@@ -7897,18 +7902,18 @@ static int check_stack_range_initialized(
 	if (tnum_is_const(reg->var_off)) {
 		min_off = max_off = reg->var_off.value + off;
 	} else {
-		/* Variable offset is prohibited for unprivileged mode for
+		/* Variable offset requires a nospec for unprivileged mode for
 		 * simplicity since it requires corresponding support in
 		 * Spectre masking for stack ALU.
 		 * See also retrieve_ptr_limit().
 		 */
 		if (!env->bypass_spec_v1) {
-			char tn_buf[48];
-
-			tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
-			verbose(env, "R%d variable offset stack access prohibited for !root, var_off=%s\n",
-				regno, tn_buf);
-			return -EACCES;
+			/* Allow the access, but prevent it from using a
+			 * speculative offset using a nospec before the
+			 * dereference op.
+			 */
+			cur_aux(env)->nospec = true;
+			WARN_ON_ONCE(cur_aux(env)->alu_state);
 		}
 		/* Only initialized buffer on stack is allowed to be accessed
 		 * with variable offset. With uninitialized buffer it's hard to
@@ -11096,11 +11101,6 @@ static int check_get_func_ip(struct bpf_verifier_env *env)
 	return -ENOTSUPP;
 }
 
-static struct bpf_insn_aux_data *cur_aux(const struct bpf_verifier_env *env)
-{
-	return &env->insn_aux_data[env->insn_idx];
-}
-
 static bool loop_flag_is_zero(struct bpf_verifier_env *env)
 {
 	struct bpf_reg_state *regs = cur_regs(env);
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:41:47 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:41:47 +0100
Subject: [PATCH bpf-next 09/11] bpf: Return PTR_ERR from push_stack()
In-Reply-To: <20250313174149.1113165-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
 <20250313174149.1113165-1-luis.gerhorst@fau.de>
Message-ID: <20250313174149.1113165-4-luis.gerhorst@fau.de>

Main reason is, that it will later allow us to fall back to a nospec for
certain errors in push_stack().

This changes the sanitization-case to returning -ENOMEM. However, this
is more fitting as -EFAULT would indicate a verifier-internal bug.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 72 ++++++++++++++++++++++++++-----------------
 1 file changed, 43 insertions(+), 29 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 683a76aceffa..610f9567af7c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2011,8 +2011,10 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 	int err;
 
 	elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL);
-	if (!elem)
-		goto err;
+	if (!elem) {
+		err = -ENOMEM;
+		goto unrecoverable_err;
+	}
 
 	elem->insn_idx = insn_idx;
 	elem->prev_insn_idx = prev_insn_idx;
@@ -2022,12 +2024,19 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 	env->stack_size++;
 	err = copy_verifier_state(&elem->st, cur);
 	if (err)
-		goto err;
+		goto unrecoverable_err;
 	elem->st.speculative |= speculative;
 	if (env->stack_size > BPF_COMPLEXITY_LIMIT_JMP_SEQ) {
 		verbose(env, "The sequence of %d jumps is too complex.\n",
 			env->stack_size);
-		goto err;
+		/* Do not return -EINVAL to prevent main loop from trying to
+		 * mitigate this using nospec if we are on a speculative path.
+		 * If it was tried anyway, we would encounter an -ENOMEM (from
+		 * which we can not recover) again shortly on the next
+		 * non-speculative path that has to be checked.
+		 */
+		err = -ENOMEM;
+		goto unrecoverable_err;
 	}
 	if (elem->st.parent) {
 		++elem->st.parent->branches;
@@ -2042,12 +2051,14 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 		 */
 	}
 	return &elem->st;
-err:
+unrecoverable_err:
 	free_verifier_state(env->cur_state, true);
 	env->cur_state = NULL;
 	/* pop all elements and return */
 	while (!pop_stack(env, NULL, NULL, false));
-	return NULL;
+	WARN_ON_ONCE(err >= 0);
+	WARN_ON_ONCE(error_recoverable_with_nospec(err));
+	return ERR_PTR(err);
 }
 
 #define CALLER_SAVED_REGS 6
@@ -8856,8 +8867,8 @@ static int process_iter_next_call(struct bpf_verifier_env *env, int insn_idx,
 		prev_st = find_prev_entry(env, cur_st->parent, insn_idx);
 		/* branch out active iter state */
 		queued_st = push_stack(env, insn_idx + 1, insn_idx, false);
-		if (!queued_st)
-			return -ENOMEM;
+		if (IS_ERR(queued_st))
+			return PTR_ERR(queued_st);
 
 		queued_iter = get_iter_from_state(queued_st, meta);
 		queued_iter->iter.state = BPF_ITER_STATE_ACTIVE;
@@ -10440,8 +10451,8 @@ static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *ins
 	 * proceed with next instruction within current frame.
 	 */
 	callback_state = push_stack(env, env->subprog_info[subprog].start, insn_idx, false);
-	if (!callback_state)
-		return -ENOMEM;
+	if (IS_ERR(callback_state))
+		return PTR_ERR(callback_state);
 
 	err = setup_func_entry(env, subprog, insn_idx, set_callee_state_cb,
 			       callback_state);
@@ -13892,7 +13903,7 @@ sanitize_speculative_path(struct bpf_verifier_env *env,
 	struct bpf_reg_state *regs;
 
 	branch = push_stack(env, next_idx, curr_idx, true);
-	if (branch && insn) {
+	if (!IS_ERR(branch) && insn) {
 		regs = branch->frame[branch->curframe]->regs;
 		if (BPF_SRC(insn->code) == BPF_K) {
 			mark_reg_unknown(env, regs, insn->dst_reg);
@@ -13920,7 +13931,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 	u8 opcode = BPF_OP(insn->code);
 	u32 alu_state, alu_limit;
 	struct bpf_reg_state tmp;
-	bool ret;
+	struct bpf_verifier_state *branch;
 	int err;
 
 	if (can_skip_alu_sanitation(env, insn))
@@ -13993,11 +14004,11 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 		tmp = *dst_reg;
 		copy_register_state(dst_reg, ptr_reg);
 	}
-	ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
-					env->insn_idx);
-	if (!ptr_is_dst_reg && ret)
+	branch = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
+					   env->insn_idx);
+	if (!ptr_is_dst_reg && !IS_ERR(branch))
 		*dst_reg = tmp;
-	return !ret ? REASON_STACK : 0;
+	return IS_ERR(branch) ? REASON_STACK : 0;
 }
 
 static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
@@ -16246,8 +16257,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 
 		/* branch out 'fallthrough' insn as a new state to explore */
 		queued_st = push_stack(env, idx + 1, idx, false);
-		if (!queued_st)
-			return -ENOMEM;
+		if (IS_ERR(queued_st))
+			return PTR_ERR(queued_st);
 
 		queued_st->may_goto_depth++;
 		if (prev_st)
@@ -16311,10 +16322,12 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 		 * the fall-through branch for simulation under speculative
 		 * execution.
 		 */
-		if (!env->bypass_spec_v1 &&
-		    !sanitize_speculative_path(env, insn, *insn_idx + 1,
-					       *insn_idx))
-			return -EFAULT;
+		if (!env->bypass_spec_v1) {
+			struct bpf_verifier_state *branch = sanitize_speculative_path(
+				env, insn, *insn_idx + 1, *insn_idx);
+			if (IS_ERR(branch))
+				return PTR_ERR(branch);
+		}
 		if (env->log.level & BPF_LOG_LEVEL)
 			print_insn_state(env, this_branch, this_branch->curframe);
 		*insn_idx += insn->off;
@@ -16324,11 +16337,12 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 		 * program will go. If needed, push the goto branch for
 		 * simulation under speculative execution.
 		 */
-		if (!env->bypass_spec_v1 &&
-		    !sanitize_speculative_path(env, insn,
-					       *insn_idx + insn->off + 1,
-					       *insn_idx))
-			return -EFAULT;
+		if (!env->bypass_spec_v1) {
+			struct bpf_verifier_state *branch = sanitize_speculative_path(
+				env, insn, *insn_idx + insn->off + 1, *insn_idx);
+			if (IS_ERR(branch))
+				return PTR_ERR(branch);
+		}
 		if (env->log.level & BPF_LOG_LEVEL)
 			print_insn_state(env, this_branch, this_branch->curframe);
 		return 0;
@@ -16351,8 +16365,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 
 	other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx,
 				  false);
-	if (!other_branch)
-		return -EFAULT;
+	if (IS_ERR(other_branch))
+		return PTR_ERR(other_branch);
 	other_branch_regs = other_branch->frame[other_branch->curframe]->regs;
 
 	if (BPF_SRC(insn->code) == BPF_X) {
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:53:11 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:53:11 +0100
Subject: [PATCH bpf-next 10/11] bpf: Fall back to nospec for sanitization-failures
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <20250313175312.1120183-1-luis.gerhorst@fau.de>

ALU sanitization was introduced to ensure that a subsequent ptr access
can never go OOBs, even under speculation. This is required because we
currently allow speculative scalar confusion. This is the case because
Spectre v4 sanitization only adds a nospec after critical stores (e.g.,
scalar overwritten with a pointer).

If we add a nospec before the ALU op, none of the operands can be
subject to scalar confusion. As an ADD/SUB can not introduce scalar
confusion itself, the result will also not be subject to scalar
confusion. Therefore, the subsequent ptr access is always safe.

For REASON_STACK, we raise the error from push_stack() directly now.
This effectively only changes the error code from EACCES to
ENOMEM (which arguably also fits). Raising the push_stack() error allows
a future commit to fall back to nospec for certain errors from
push_stack() if on a speculative path.

Fall back to nospec directly for the remaining sanitization errs even if
we are not on a speculative path.

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c                         | 85 ++++++-------------
 .../selftests/bpf/progs/verifier_bounds.c     |  5 +-
 .../bpf/progs/verifier_bounds_deduction.c     | 43 ++++++----
 .../selftests/bpf/progs/verifier_map_ptr.c    | 12 ++-
 .../bpf/progs/verifier_value_ptr_arith.c      | 44 ++++++----
 5 files changed, 92 insertions(+), 97 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 610f9567af7c..03af82f52a02 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13809,14 +13809,6 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
 	return true;
 }
 
-enum {
-	REASON_BOUNDS	= -1,
-	REASON_TYPE	= -2,
-	REASON_PATHS	= -3,
-	REASON_LIMIT	= -4,
-	REASON_STACK	= -5,
-};
-
 static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
 			      u32 *alu_limit, bool mask_to_left)
 {
@@ -13839,11 +13831,13 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
 			     ptr_reg->umax_value) + ptr_reg->off;
 		break;
 	default:
-		return REASON_TYPE;
+		/* Register has pointer with unsupported alu operation. */
+		return -EOPNOTSUPP;
 	}
 
+	/* Register tried access beyond pointer bounds. */
 	if (ptr_limit >= max)
-		return REASON_LIMIT;
+		return -EOPNOTSUPP;
 	*alu_limit = ptr_limit;
 	return 0;
 }
@@ -13864,8 +13858,12 @@ static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux,
 	 */
 	if (aux->alu_state &&
 	    (aux->alu_state != alu_state ||
-	     aux->alu_limit != alu_limit))
-		return REASON_PATHS;
+	     aux->alu_limit != alu_limit)) {
+		/* Tried to perform alu op from different maps, paths or scalars */
+		aux->nospec = true;
+		aux->alu_state = 0;
+		return 0;
+	}
 
 	/* Corresponding fixup done in do_misc_fixups(). */
 	aux->alu_state = alu_state;
@@ -13946,16 +13944,24 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 
 	if (!commit_window) {
 		if (!tnum_is_const(off_reg->var_off) &&
-		    (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
-			return REASON_BOUNDS;
+		    (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) {
+			/* Register has unknown scalar with mixed signed bounds. */
+			aux->nospec = true;
+			aux->alu_state = 0;
+			return 0;
+		}
 
 		info->mask_to_left = (opcode == BPF_ADD &&  off_is_neg) ||
 				     (opcode == BPF_SUB && !off_is_neg);
 	}
 
 	err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
-	if (err < 0)
-		return err;
+	if (err) {
+		WARN_ON_ONCE(err != -EOPNOTSUPP);
+		aux->nospec = true;
+		aux->alu_state = 0;
+		return 0;
+	}
 
 	if (commit_window) {
 		/* In commit phase we narrow the masking window based on
@@ -14008,7 +14014,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 					   env->insn_idx);
 	if (!ptr_is_dst_reg && !IS_ERR(branch))
 		*dst_reg = tmp;
-	return IS_ERR(branch) ? REASON_STACK : 0;
+	return PTR_ERR_OR_ZERO(branch);
 }
 
 static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
@@ -14024,45 +14030,6 @@ static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
 		env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
 }
 
-static int sanitize_err(struct bpf_verifier_env *env,
-			const struct bpf_insn *insn, int reason,
-			const struct bpf_reg_state *off_reg,
-			const struct bpf_reg_state *dst_reg)
-{
-	static const char *err = "pointer arithmetic with it prohibited for !root";
-	const char *op = BPF_OP(insn->code) == BPF_ADD ? "add" : "sub";
-	u32 dst = insn->dst_reg, src = insn->src_reg;
-
-	switch (reason) {
-	case REASON_BOUNDS:
-		verbose(env, "R%d has unknown scalar with mixed signed bounds, %s\n",
-			off_reg == dst_reg ? dst : src, err);
-		break;
-	case REASON_TYPE:
-		verbose(env, "R%d has pointer with unsupported alu operation, %s\n",
-			off_reg == dst_reg ? src : dst, err);
-		break;
-	case REASON_PATHS:
-		verbose(env, "R%d tried to %s from different maps, paths or scalars, %s\n",
-			dst, op, err);
-		break;
-	case REASON_LIMIT:
-		verbose(env, "R%d tried to %s beyond pointer bounds, %s\n",
-			dst, op, err);
-		break;
-	case REASON_STACK:
-		verbose(env, "R%d could not be pushed for speculative verification, %s\n",
-			dst, err);
-		break;
-	default:
-		verbose(env, "verifier internal error: unknown reason (%d)\n",
-			reason);
-		break;
-	}
-
-	return -EACCES;
-}
-
 /* check that stack access falls within stack limits and that 'reg' doesn't
  * have a variable offset.
  *
@@ -14228,7 +14195,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 		ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
 				       &info, false);
 		if (ret < 0)
-			return sanitize_err(env, insn, ret, off_reg, dst_reg);
+			return ret;
 	}
 
 	switch (opcode) {
@@ -14356,7 +14323,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 		ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg,
 				       &info, true);
 		if (ret < 0)
-			return sanitize_err(env, insn, ret, off_reg, dst_reg);
+			return ret;
 	}
 
 	return 0;
@@ -14950,7 +14917,7 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 	if (sanitize_needed(opcode)) {
 		ret = sanitize_val_alu(env, insn);
 		if (ret < 0)
-			return sanitize_err(env, insn, ret, NULL, NULL);
+			return ret;
 	}
 
 	/* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops.
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
index 0488ef05a7a4..ad405a609db4 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
@@ -47,9 +47,12 @@ SEC("socket")
 __description("subtraction bounds (map value) variant 2")
 __failure
 __msg("R0 min value is negative, either use unsigned index or do a if (index >=0) check.")
-__msg_unpriv("R1 has unknown scalar with mixed signed bounds")
+__msg_unpriv("R0 pointer arithmetic of map value goes out of range, prohibited for !root")
 __naked void bounds_map_value_variant_2(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 has unknown scalar with mixed
+	 * signed bounds".
+	 */
 	asm volatile ("					\
 	r1 = 0;						\
 	*(u64*)(r10 - 8) = r1;				\
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds_deduction.c b/tools/testing/selftests/bpf/progs/verifier_bounds_deduction.c
index c506afbdd936..c2b5099fa208 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds_deduction.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds_deduction.c
@@ -8,21 +8,21 @@
 SEC("socket")
 __description("check deducing bounds from const, 1")
 __failure __msg("R0 tried to subtract pointer from scalar")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __naked void deducing_bounds_from_const_1(void)
 {
 	asm volatile ("					\
 	r0 = 1;						\
 	if r0 s>= 1 goto l0_%=;				\
-l0_%=:	r0 -= r1;					\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r0 -= r1;					\
 	exit;						\
 "	::: __clobber_all);
 }
 
 SEC("socket")
 __description("check deducing bounds from const, 2")
-__success __failure_unpriv
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__success __success_unpriv
 __retval(1)
 __naked void deducing_bounds_from_const_2(void)
 {
@@ -32,7 +32,8 @@ __naked void deducing_bounds_from_const_2(void)
 	exit;						\
 l0_%=:	if r0 s<= 1 goto l1_%=;				\
 	exit;						\
-l1_%=:	r1 -= r0;					\
+l1_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r1 -= r0;					\
 	exit;						\
 "	::: __clobber_all);
 }
@@ -40,21 +41,21 @@ l1_%=:	r1 -= r0;					\
 SEC("socket")
 __description("check deducing bounds from const, 3")
 __failure __msg("R0 tried to subtract pointer from scalar")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __naked void deducing_bounds_from_const_3(void)
 {
 	asm volatile ("					\
 	r0 = 0;						\
 	if r0 s<= 0 goto l0_%=;				\
-l0_%=:	r0 -= r1;					\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r0 -= r1;					\
 	exit;						\
 "	::: __clobber_all);
 }
 
 SEC("socket")
 __description("check deducing bounds from const, 4")
-__success __failure_unpriv
-__msg_unpriv("R6 has pointer with unsupported alu operation")
+__success __success_unpriv
 __retval(0)
 __naked void deducing_bounds_from_const_4(void)
 {
@@ -65,7 +66,8 @@ __naked void deducing_bounds_from_const_4(void)
 	exit;						\
 l0_%=:	if r0 s>= 0 goto l1_%=;				\
 	exit;						\
-l1_%=:	r6 -= r0;					\
+l1_%=:	/* unpriv: nospec (inserted to prevent `R6 has pointer with unsupported alu operation`) */\
+	r6 -= r0;					\
 	exit;						\
 "	::: __clobber_all);
 }
@@ -73,12 +75,13 @@ l1_%=:	r6 -= r0;					\
 SEC("socket")
 __description("check deducing bounds from const, 5")
 __failure __msg("R0 tried to subtract pointer from scalar")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __naked void deducing_bounds_from_const_5(void)
 {
 	asm volatile ("					\
 	r0 = 0;						\
 	if r0 s>= 1 goto l0_%=;				\
+	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
 	r0 -= r1;					\
 l0_%=:	exit;						\
 "	::: __clobber_all);
@@ -87,14 +90,15 @@ l0_%=:	exit;						\
 SEC("socket")
 __description("check deducing bounds from const, 6")
 __failure __msg("R0 tried to subtract pointer from scalar")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __naked void deducing_bounds_from_const_6(void)
 {
 	asm volatile ("					\
 	r0 = 0;						\
 	if r0 s>= 0 goto l0_%=;				\
 	exit;						\
-l0_%=:	r0 -= r1;					\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r0 -= r1;					\
 	exit;						\
 "	::: __clobber_all);
 }
@@ -102,14 +106,15 @@ l0_%=:	r0 -= r1;					\
 SEC("socket")
 __description("check deducing bounds from const, 7")
 __failure __msg("dereference of modified ctx ptr")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __flag(BPF_F_ANY_ALIGNMENT)
 __naked void deducing_bounds_from_const_7(void)
 {
 	asm volatile ("					\
 	r0 = %[__imm_0];				\
 	if r0 s>= 0 goto l0_%=;				\
-l0_%=:	r1 -= r0;					\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r1 -= r0;					\
 	r0 = *(u32*)(r1 + %[__sk_buff_mark]);		\
 	exit;						\
 "	:
@@ -121,13 +126,14 @@ l0_%=:	r1 -= r0;					\
 SEC("socket")
 __description("check deducing bounds from const, 8")
 __failure __msg("negative offset ctx ptr R1 off=-1 disallowed")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __flag(BPF_F_ANY_ALIGNMENT)
 __naked void deducing_bounds_from_const_8(void)
 {
 	asm volatile ("					\
 	r0 = %[__imm_0];				\
 	if r0 s>= 0 goto l0_%=;				\
+	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
 	r1 += r0;					\
 l0_%=:	r0 = *(u32*)(r1 + %[__sk_buff_mark]);		\
 	exit;						\
@@ -140,13 +146,14 @@ l0_%=:	r0 = *(u32*)(r1 + %[__sk_buff_mark]);		\
 SEC("socket")
 __description("check deducing bounds from const, 9")
 __failure __msg("R0 tried to subtract pointer from scalar")
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__failure_unpriv
 __naked void deducing_bounds_from_const_9(void)
 {
 	asm volatile ("					\
 	r0 = 0;						\
 	if r0 s>= 0 goto l0_%=;				\
-l0_%=:	r0 -= r1;					\
+l0_%=:	/* unpriv: nospec (inserted to prevent `R1 has pointer with unsupported alu operation`) */\
+	r0 -= r1;					\
 	exit;						\
 "	::: __clobber_all);
 }
diff --git a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
index 11a079145966..8d7cd5b82bbd 100644
--- a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+++ b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
@@ -110,11 +110,13 @@ __naked void ptr_read_ops_field_accepted(void)
 
 SEC("socket")
 __description("bpf_map_ptr: r = 0, map_ptr = map_ptr + r")
-__success __failure_unpriv
-__msg_unpriv("R1 has pointer with unsupported alu operation")
+__success __success_unpriv
 __retval(0)
 __naked void map_ptr_map_ptr_r(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 has pointer with unsupported
+	 * alu operation".
+	 */
 	asm volatile ("					\
 	r0 = 0;						\
 	*(u64*)(r10 - 8) = r0;				\
@@ -134,11 +136,13 @@ __naked void map_ptr_map_ptr_r(void)
 
 SEC("socket")
 __description("bpf_map_ptr: r = 0, r = r + map_ptr")
-__success __failure_unpriv
-__msg_unpriv("R0 has pointer with unsupported alu operation")
+__success __success_unpriv
 __retval(0)
 __naked void _0_r_r_map_ptr(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 has pointer with unsupported
+	 * alu operation".
+	 */
 	asm volatile ("					\
 	r0 = 0;						\
 	*(u64*)(r10 - 8) = r0;				\
diff --git a/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c b/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
index 2acd7769bd91..d1be1b6f4674 100644
--- a/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
+++ b/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c
@@ -41,11 +41,13 @@ struct {
 
 SEC("socket")
 __description("map access: known scalar += value_ptr unknown vs const")
-__success __failure_unpriv
-__msg_unpriv("R1 tried to add from different maps, paths or scalars")
+__success __success_unpriv
 __retval(1)
 __naked void value_ptr_unknown_vs_const(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 tried to add from different
+	 * maps, paths or scalars".
+	 */
 	asm volatile ("					\
 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 	r1 = 0;						\
@@ -79,11 +81,13 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: known scalar += value_ptr const vs unknown")
-__success __failure_unpriv
-__msg_unpriv("R1 tried to add from different maps, paths or scalars")
+__success __success_unpriv
 __retval(1)
 __naked void value_ptr_const_vs_unknown(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 tried to add from different
+	 * maps, paths or scalars".
+	 */
 	asm volatile ("					\
 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 	r1 = 0;						\
@@ -117,11 +121,13 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: known scalar += value_ptr const vs const (ne)")
-__success __failure_unpriv
-__msg_unpriv("R1 tried to add from different maps, paths or scalars")
+__success __success_unpriv
 __retval(1)
 __naked void ptr_const_vs_const_ne(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 tried to add from different
+	 * maps, paths or scalars".
+	 */
 	asm volatile ("					\
 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 	r1 = 0;						\
@@ -225,8 +231,7 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: known scalar += value_ptr unknown vs unknown (lt)")
-__success __failure_unpriv
-__msg_unpriv("R1 tried to add from different maps, paths or scalars")
+__success __success_unpriv
 __retval(1)
 __naked void ptr_unknown_vs_unknown_lt(void)
 {
@@ -251,7 +256,8 @@ l1_%=:	call %[bpf_map_lookup_elem];			\
 l3_%=:	r1 = 6;						\
 	r1 = -r1;					\
 	r1 &= 0x7;					\
-l4_%=:	r1 += r0;					\
+l4_%=:	/* unpriv: nospec (inserted to prevent `R1 tried to add from different maps, paths or scalars`) */\
+	r1 += r0;					\
 	r0 = *(u8*)(r1 + 0);				\
 l2_%=:	r0 = 1;						\
 	exit;						\
@@ -265,11 +271,13 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: known scalar += value_ptr unknown vs unknown (gt)")
-__success __failure_unpriv
-__msg_unpriv("R1 tried to add from different maps, paths or scalars")
+__success __success_unpriv
 __retval(1)
 __naked void ptr_unknown_vs_unknown_gt(void)
 {
+	/* unpriv: nospec inserted to prevent "R1 tried to add from different
+	 * maps, paths or scalars".
+	 */
 	asm volatile ("					\
 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 	r1 = 0;						\
@@ -398,11 +406,14 @@ l2_%=:	r0 = 1;						\
 
 SEC("socket")
 __description("map access: mixing value pointer and scalar, 1")
-__success __failure_unpriv
-__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
+__success __success_unpriv
 __retval(0)
 __naked void value_pointer_and_scalar_1(void)
 {
+	/* unpriv: nospec inserted to prevent "R2 tried to add from different
+	 * maps, paths or scalars, pointer arithmetic with it prohibited for
+	 * !root".
+	 */
 	asm volatile ("					\
 	/* load map value pointer into r0 and r2 */	\
 	r0 = 1;						\
@@ -452,11 +463,14 @@ l4_%=:	/* fake-dead code; targeted from branch A to	\
 
 SEC("socket")
 __description("map access: mixing value pointer and scalar, 2")
-__success __failure_unpriv
-__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
+__success __success_unpriv
 __retval(0)
 __naked void value_pointer_and_scalar_2(void)
 {
+	/* unpriv: nospec inserted to prevent "R2 tried to add from different
+	 * maps, paths or scalars, pointer arithmetic with it prohibited for
+	 * !root".
+	 */
 	asm volatile ("					\
 	/* load map value pointer into r0 and r2 */	\
 	r0 = 1;						\
-- 
2.48.1



From luis.gerhorst at fau.de  Thu Mar 13 10:53:12 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Thu, 13 Mar 2025 18:53:12 +0100
Subject: [PATCH bpf-next 11/11] bpf: Fall back to nospec for spec path verification
In-Reply-To: <20250313175312.1120183-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
 <20250313175312.1120183-1-luis.gerhorst@fau.de>
Message-ID: <20250313175312.1120183-2-luis.gerhorst@fau.de>

This trades verification complexity for runtime overheads due to the
nospec inserted because of the EINVAL.

With increased limits this allows applying mitigations to large BPF
progs such as the Parca Continuous Profiler's prog. However, this
requires a jump-seq limit of 256k. In any case, the same principle
should apply to smaller programs therefore include it even if the limit
stays at 8k for now. Most programs in [1] only require a limit of 32k.

[1] https://arxiv.org/pdf/2405.00078 ("VeriFence: Lightweight and
    Precise Spectre Defenses for Untrusted Linux Kernel Extensions")

Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
Acked-by: Henriette Herzog <henriette.herzog at rub.de>
Cc: Maximilian Ott <ott at cs.fau.de>
Cc: Milan Stephan <milan.stephan at fau.de>
---
 kernel/bpf/verifier.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 03af82f52a02..49c7e2608ccd 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -187,6 +187,7 @@ struct bpf_verifier_stack_elem {
 };
 
 #define BPF_COMPLEXITY_LIMIT_JMP_SEQ	8192
+#define BPF_COMPLEXITY_LIMIT_SPEC_V1_VERIFICATION	(BPF_COMPLEXITY_LIMIT_JMP_SEQ / 2)
 #define BPF_COMPLEXITY_LIMIT_STATES	64
 
 #define BPF_MAP_KEY_POISON	(1ULL << 63)
@@ -2010,6 +2011,19 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 	struct bpf_verifier_stack_elem *elem;
 	int err;
 
+	if (!env->bypass_spec_v1 &&
+	    cur->speculative &&
+	    env->stack_size > BPF_COMPLEXITY_LIMIT_SPEC_V1_VERIFICATION) {
+		/* Avoiding nested speculative path verification because we are
+		 * close to exceeding the jump sequence complexity limit. Will
+		 * instead insert a speculation barrier which will impact
+		 * performace. To improve performance, authors should reduce the
+		 * program's complexity. Barrier will be inserted in
+		 * do_check().
+		 */
+		return ERR_PTR(-EINVAL);
+	}
+
 	elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL);
 	if (!elem) {
 		err = -ENOMEM;
-- 
2.48.1



From festevam at gmail.com  Thu Mar 13 10:57:52 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 13 Mar 2025 14:57:52 -0300
Subject: [PATCH] ARM: dts: imx31/imx6: Use flash as the NOR node name
Message-ID: <20250313175752.1532299-1-festevam@gmail.com>

From: Fabio Estevam <festevam at denx.de>

According to mtd-physmap.yaml, 'nor' is not a valid node name.

Change it to 'flash' to fix the following dt-schema warning:

nor at 0,0: $nodename:0: 'nor at 0,0' does not match '^(flash|.*sram|nand)(@.*)?$'

Signed-off-by: Fabio Estevam <festevam at denx.de>
---
 arch/arm/boot/dts/nxp/imx/imx31-lite.dts         | 2 +-
 arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts      | 2 +-
 arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx31-lite.dts b/arch/arm/boot/dts/nxp/imx/imx31-lite.dts
index d17abdfb6330..630f8fa69ba8 100644
--- a/arch/arm/boot/dts/nxp/imx/imx31-lite.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx31-lite.dts
@@ -157,7 +157,7 @@ &uart3 {
 &weim {
 	status = "okay";
 
-	nor at 0,0 {
+	flash at 0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0x0 0x200000>;
 		bank-width = <2>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts
index f08b37010291..bba82126aaaa 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts
@@ -279,7 +279,7 @@ &weim {
 	ranges = <0 0 0x08000000 0x08000000>;
 	status = "okay";
 
-	nor at 0,0 {
+	flash at 0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0 0x02000000>;
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
index a381cb224c1e..2587d17c5918 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
@@ -854,7 +854,7 @@ &weim {
 	ranges = <0 0 0x08000000 0x08000000>;
 	status = "disabled"; /* pin conflict with SPI NOR */
 
-	nor at 0,0 {
+	flash at 0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0 0x02000000>;
 		#address-cells = <1>;
-- 
2.34.1



From ericwouds at gmail.com  Thu Mar 13 11:01:38 2025
From: ericwouds at gmail.com (Eric Woudstra)
Date: Thu, 13 Mar 2025 19:01:38 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <Z9IUrL0IHTKQMUvC@calendula>
References: <20250305102949.16370-1-ericwouds@gmail.com>
 <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com> <Z9DKxOnxr1fSv0On@calendula>
 <58cbe875-80e7-4a44-950b-b836b97f3259@gmail.com> <Z9IUrL0IHTKQMUvC@calendula>
Message-ID: <02b97708-1214-4fa4-a011-70388cff8f79@gmail.com>



On 3/13/25 12:11 AM, Pablo Neira Ayuso wrote:

>> What do you suggest?
> 
> Probably I can collect 4/15 and 5/15 from this series to be included
> in the next pull request, let me take a look. But it would be good to
> have tests for these two patches.
> 

These are not most important to bridge-fastpath, but it gives extra
possibilities. How about concentrating first on patch 2/15 (with 1/15
removing a warning and 3/15 cleaning up), adding nf_flow_encap_push()
for xmit direct? It is a vital patch for the bridge-fastpath.

Anyway, I will look into writing selftests for conntrack-bridge setup,
including various vlan setups. This will take me some time, which I
do not have in abundance, so for that I do not know if I get it done
before the merge window.



From mripard at kernel.org  Thu Mar 13 11:07:17 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Thu, 13 Mar 2025 19:07:17 +0100
Subject: [PATCH v6 14/26] drm/bridge: add support for refcounted DRM
 bridges
In-Reply-To: <20250313125656.70448d09@booty>
References: <20250206-hotplug-drm-bridge-v6-0-9d6f2c9c3058@bootlin.com>
 <20250206-hotplug-drm-bridge-v6-14-9d6f2c9c3058@bootlin.com>
 <20250207-ingenious-daffodil-dugong-51be57@houat>
 <20250313125656.70448d09@booty>
Message-ID: <20250313-flying-crab-of-diversity-fa1db0@houat>

On Thu, Mar 13, 2025 at 12:56:56PM +0100, Luca Ceresoli wrote:
> Hello Maxime,
> 
> On Fri, 7 Feb 2025 12:47:51 +0100
> Maxime Ripard <mripard at kernel.org> wrote:
> > On Thu, Feb 06, 2025 at 07:14:29PM +0100, Luca Ceresoli wrote:
> > > DRM bridges are currently considered as a fixed element of a DRM card, and
> > > thus their lifetime is assumed to extend for as long as the card
> > > exists. New use cases, such as hot-pluggable hardware with video bridges,
> > > require DRM bridges to be added and removed to a DRM card without tearing
> > > the card down. This is possible for connectors already (used by DP MST), so
> > > add this possibility to DRM bridges as well.
> > > 
> > > Implementation is based on drm_connector_init() as far as it makes sense,
> > > and differs when it doesn't. A difference is that bridges are not exposed
> > > to userspace, hence struct drm_bridge does not embed a struct
> > > drm_mode_object which would provide the refcount. Instead we add to struct
> > > drm_bridge a refcount field (we don't need other struct drm_mode_object
> > > fields here) and instead of using the drm_mode_object_*() functions we
> > > reimplement from those functions the few lines that drm_bridge needs for
> > > refcounting.
> > > 
> > > Also add a new devm_drm_bridge_alloc() macro to allocate a new refcounted
> > > bridge.
> > > 
> > > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>  
> > 
> > So, a couple of general comments:
> > 
> > - I've said it a couple of times already, but I really think you're
> >   making it harder than necessary for you here. This (and only this!)
> >   should be the very first series you should be pushing. The rest can
> >   only ever work if that work goes through, and it's already hard enough
> >   as it is. So, split that patch into a series of its own, get that
> >   merged, and then we will be able to deal with panels conversion and
> >   whatever. That's even more true with panels since there's ongoing work
> >   that will make it easier for you too. So the best thing here is
> >   probably to wait.
> > 
> > - This patch really needs to be split into several patches, something
> >   along the lines of:
> > 
> >   + Creating devm_drm_bridge_alloc()
> >   + Adding refcounting
> >   + Taking the references in all the needed places
> >   + Converting a bunch of drivers
> 
> After reading Anusha's "[PATCH RFC 0/2] drm/panel: Refcounted panel
> allocation" [0] I think I need a clarification about the 4 steps you had
> outlined in the above quoted text. Are you suggesting those are four
> _series_, and you'd want to see a series only creating
> devm_drm_bridge_alloc() as a first step, similarly to Anusha's work?
> 
> That was not my understanding so far, and so I've been working on a
> series containing all 4 items, and it's growing very long due to item 3
> needing to touch many dozen drivers which need to put a bridge (many
> are identical oneliner patches though).

I believe I've clarified it already in Anusha's series, but I think a
reasonable series for *early* work would be the bullet points 1, 2, a
bit of 3 and a bit of 4.

Once the API is agreed upon, 1, 2 and 4 should be in the same series. As
you've pointed out, item 3 can be large, so I don't really mind either
way.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250313/526b0cb7/attachment.sig>

From catalin.marinas at arm.com  Thu Mar 13 11:08:27 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 13 Mar 2025 18:08:27 +0000
Subject: [PATCH v2] arm64/kernel: Always use level 2 or higher for early mappings
In-Reply-To: <20250311073043.96795-2-ardb+git@google.com>
References: <20250311073043.96795-2-ardb+git@google.com>
Message-ID: <174188930050.275020.5161287876611864847.b4-ty@arm.com>

On Tue, 11 Mar 2025 08:30:44 +0100, Ard Biesheuvel wrote:
> The page table population code in map_range() uses a recursive algorithm
> to create the early mappings of the kernel, the DTB and the ID mapped
> text and data pages, and this fails to take into account that the way
> these page tables may be constructed is not precisely the same at each
> level. In particular, block mappings are not permitted at each level,
> and the code as it exists today might inadvertently create such a
> forbidden block mapping if it were used to map a region of the
> appropriate size and alignment.
> 
> [...]

Applied to arm64 (for-next/pgtable-cleanups), thanks!

[1/1] arm64/kernel: Always use level 2 or higher for early mappings
      https://git.kernel.org/arm64/c/bf25266f8382

-- 
Catalin



From miko.lenczewski at arm.com  Thu Mar 13 11:08:33 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 13 Mar 2025 18:08:33 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <ea10caee-59ef-4a00-9b61-37cb0a379411@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <ea10caee-59ef-4a00-9b61-37cb0a379411@arm.com>
Message-ID: <20250313180833.GA40525@mazurka.cambridge.arm.com>

On Thu, Mar 13, 2025 at 04:13:22PM +0000, Ryan Roberts wrote:
> On 13/03/2025 10:41, Miko?aj Lenczewski wrote: 
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index d561cf3b8ac7..b936e0805161 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -2176,6 +2176,76 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
> >  	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
> >  }
> >  
> > +static inline bool bbml2_possible(void)
> > +{
> > +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
> 
> If you're going to keep this helper, I think it really needs to be:
> 
> return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) &&
>        !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
> 
> Then you would simplify the caller to remove it's own
> IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) check.
> 
> But personally I would remove the helper and just fold the test into
> has_bbml2_noabort().
> 
> Thanks,
> Ryan

I was debating folding it into has_bbml2_noabort(), but went ahead and
implemented it separately to match hvhe_possible(), which was another sw
feature helper.

But I agree, folding it will be simpler and read just as easily (if not
easier). Will do so.

> > +}
> > +
> > +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> > +{
> > +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
> > +	 * as possible. This list is therefore an allow-list of known-good
> > +	 * implementations that both support bbml2 and additionally, fulfill the
> > +	 * extra constraint of never generating TLB conflict aborts when using
> > +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> > +	 * kernel contexts difficult to prove safe against recursive aborts).
> > +	 *
> > +	 * Note that implementations can only be considered "known-good" if their
> > +	 * implementors attest to the fact that the implementation never raises
> > +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
> > +	 */
> > +	static const struct midr_range supports_bbml2_noabort_list[] = {
> > +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> > +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> > +		{}
> > +	};
> > +
> > +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
> > +}
> > +
> > +static inline unsigned int __cpu_read_midr(int cpu)
> 
> nit: why the double underscrore prefix?

Again copying other helpers I saw that seemed to do similar things.
Didn't know if this was the expected style, so did as other helpers did.
Will remove.

Thank you for the review.

-- 
Kind regards,
Miko?aj Lenczewski


From leitao at debian.org  Thu Mar 13 11:09:01 2025
From: leitao at debian.org (Breno Leitao)
Date: Thu, 13 Mar 2025 11:09:01 -0700
Subject: [PATCH 2/2] arm64: Implement HAVE_LIVEPATCH
In-Reply-To: <20250308012742.3208215-3-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-3-song@kernel.org>
Message-ID: <20250313-grinning-giraffe-of-holiness-3dbda1@leitao>

On Fri, Mar 07, 2025 at 05:27:42PM -0800, Song Liu wrote:
> This is largely based on [1] by Suraj Jitindar Singh.
> 
> Test coverage:
> 
> - Passed manual tests with samples/livepatch.
> - Passed all but test-kprobe.sh in selftests/livepatch.
>   test-kprobe.sh is expected to fail, because arm64 doesn't have
>   KPROBES_ON_FTRACE.
> - Passed tests with kpatch-build [2]. (This version includes commits that
>   are not merged to upstream kpatch yet).
> 
> [1] https://lore.kernel.org/all/20210604235930.603-1-surajjs at amazon.com/
> [2] https://github.com/liu-song-6/kpatch/tree/fb-6.13
> Cc: Suraj Jitindar Singh <surajjs at amazon.com>
> Cc: Torsten Duwe <duwe at suse.de>
> Signed-off-by: Song Liu <song at kernel.org>

Tested-by: Breno Leitao <leitao at debian.org>

PS: I've tested this patchset with the examples from samples/ on a arm64
host, and they worked as expected.

Thanks
--breno


From leitao at debian.org  Thu Mar 13 11:12:48 2025
From: leitao at debian.org (Breno Leitao)
Date: Thu, 13 Mar 2025 11:12:48 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250308012742.3208215-2-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-2-song@kernel.org>
Message-ID: <20250313-angelic-coral-giraffe-dfa4f3@leitao>

On Fri, Mar 07, 2025 at 05:27:41PM -0800, Song Liu wrote:
> With proper exception boundary detection, it is possible to implment
> arch_stack_walk_reliable without sframe.
> 
> Note that, arch_stack_walk_reliable does not guarantee getting reliable
> stack in all scenarios. Instead, it can reliably detect when the stack
> trace is not reliable, which is enough to provide reliable livepatching.
> 
> This version has been inspired by Weinan Liu's patch [1].
> 
> [1] https://lore.kernel.org/live-patching/20250127213310.2496133-7-wnliu at google.com/
> Signed-off-by: Song Liu <song at kernel.org>

Tested-by: Breno Leitao <leitao at debian.org>

>  arch/arm64/Kconfig                         |  2 +-
>  arch/arm64/include/asm/stacktrace/common.h |  1 +
>  arch/arm64/kernel/stacktrace.c             | 44 +++++++++++++++++++++-
>  3 files changed, 45 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..ed4f7bf4a879 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -275,6 +275,7 @@ config ARM64
>  	select HAVE_SOFTIRQ_ON_OWN_STACK
>  	select USER_STACKTRACE_SUPPORT
>  	select VDSO_GETRANDOM
> +	select HAVE_RELIABLE_STACKTRACE

Can we really mark this is reliable stacktrace?  I am wondering
if we need an intermediate state (potentially reliable stacktrace?)
until we have a fully reliable stack unwinder.

Thanks for working on it.
--breno


From miko.lenczewski at arm.com  Thu Mar 13 11:13:19 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 13 Mar 2025 18:13:19 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <0abe8643-d4ea-4e77-bd77-afe07399eec9@os.amperecomputing.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <0abe8643-d4ea-4e77-bd77-afe07399eec9@os.amperecomputing.com>
Message-ID: <20250313181319.GB40525@mazurka.cambridge.arm.com>

On Thu, Mar 13, 2025 at 10:21:51AM -0700, Yang Shi wrote:
> On 3/13/25 3:41 AM, Miko?aj Lenczewski wrote:
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > index fb8752b42ec8..3e4cc917a07e 100644
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -453,6 +453,9 @@
> >   	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
> >   			32 bit applications.
> >   
> > +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> > +			2 support
> 
> Hi Miko,
> 
> A question about the kernel boot parameter. Can this parameter be used 
> in early boot stage? A quick look at the code shows it should be ok, for 
> example, cpu_has_bti() is called in map_kernel(). But I'd like to double 
> check because my patchset needs to check this parameter in map_mem() to 
> determine whether large block mapping can be used or not.
> 
> And a nit below.

I will need to double check exactly when the arm64 software overrides
are finalised, but as long as those values are finalised in / before (?)
the early boot stage then it should be fine? Will reply again once I
check and have an answer.
   
> > +static inline bool bbml2_possible(void)
> > +{
> > +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
> > +}
> 
> Can this be moved to cpufeature.h? My patch will use this, anyway I can 
> do it in my patchset.
> 
> Thanks,
> Yang

I can do so. In fact, on second thought, I will probably extend this to
also include the `IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT)` check as well,
and then move it to cpufeature.h, instead of folding said check into
has_bbml2_noabort().

-- 
Kind regards,
Miko?aj Lenczewski


From robh at kernel.org  Thu Mar 13 11:44:40 2025
From: robh at kernel.org (Rob Herring)
Date: Thu, 13 Mar 2025 13:44:40 -0500
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ
 number from DeviceTree
In-Reply-To: <20250307220304.247725-9-romank@linux.microsoft.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com> <20250307220304.247725-9-romank@linux.microsoft.com>
Message-ID: <CAL_JsqLmS4EEoPkOmaH6F_0XtQu5wkM-WEfxFvjLA=bJroEUVw@mail.gmail.com>

On Fri, Mar 7, 2025 at 4:03?PM Roman Kisel <romank at linux.microsoft.com> wrote:
>
> The VMBus driver uses ACPI for interrupt assignment on
> arm64 hence it won't function in the VTL mode where only
> DeviceTree can be used.
>
> Update the VMBus driver to discover interrupt configuration
> from DT.
>
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> ---
>  drivers/hv/vmbus_drv.c | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 75eb1390b45c..c8474b48dcd2 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -2345,6 +2345,36 @@ static int vmbus_acpi_add(struct platform_device *pdev)
>  }
>  #endif
>
> +static int __maybe_unused vmbus_set_irq(struct platform_device *pdev)
> +{
> +       struct irq_data *data;
> +       int irq;
> +       irq_hw_number_t hwirq;
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq == 0) {
> +               pr_err("VMBus interrupt mapping failure\n");
> +               return -EINVAL;
> +       }
> +       if (irq < 0) {
> +               pr_err("VMBus interrupt data can't be read from DeviceTree, error %d\n", irq);
> +               return irq;
> +       }

I don't think why you couldn't get the interrupt is important. Just
check for (irq <= 0) and be done with it. I'm not even sure if
returning 0 is possible now. There's a long history to that and
NO_IRQ.

Rob


From romank at linux.microsoft.com  Thu Mar 13 11:46:58 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Thu, 13 Mar 2025 11:46:58 -0700
Subject: [PATCH hyperv-next v5 08/11] Drivers: hv: vmbus: Get the IRQ
 number from DeviceTree
In-Reply-To: <CAL_JsqLmS4EEoPkOmaH6F_0XtQu5wkM-WEfxFvjLA=bJroEUVw@mail.gmail.com>
References: <20250307220304.247725-1-romank@linux.microsoft.com>
 <20250307220304.247725-9-romank@linux.microsoft.com>
 <CAL_JsqLmS4EEoPkOmaH6F_0XtQu5wkM-WEfxFvjLA=bJroEUVw@mail.gmail.com>
Message-ID: <81612b52-a47b-4d9c-9d50-c74ad66286d9@linux.microsoft.com>



On 3/13/2025 11:44 AM, Rob Herring wrote:
> On Fri, Mar 7, 2025 at 4:03?PM Roman Kisel <romank at linux.microsoft.com> wrote:

[...]

>> +       irq = platform_get_irq(pdev, 0);
>> +       if (irq == 0) {
>> +               pr_err("VMBus interrupt mapping failure\n");
>> +               return -EINVAL;
>> +       }
>> +       if (irq < 0) {
>> +               pr_err("VMBus interrupt data can't be read from DeviceTree, error %d\n", irq);
>> +               return irq;
>> +       }
> 
> I don't think why you couldn't get the interrupt is important. Just
> check for (irq <= 0) and be done with it. I'm not even sure if
> returning 0 is possible now. There's a long history to that and
> NO_IRQ.
> 

That will certainly make the code look much better!
Thank you very much for the idea!

> Rob

-- 
Thank you,
Roman



From heiko at sntech.de  Thu Mar 13 12:00:40 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 20:00:40 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores on
 RK3588j
In-Reply-To: <2cf3889741f84584d8f23a4407fed08e@manjaro.org>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <a56b59a21dc3c21192fe45197eee4865@manjaro.org>
 <2cf3889741f84584d8f23a4407fed08e@manjaro.org>
Message-ID: <3271211.5fSG56mABF@phil>

Am Donnerstag, 13. M?rz 2025, 11:42:17 MEZ schrieb Dragan Simic:
> Hello all,
> 
> On 2025-03-12 11:34, Dragan Simic wrote:
> > On 2025-03-12 11:15, Quentin Schulz wrote:
> >> On 2/16/25 1:32 PM, Alexey Charkov wrote:
> >>> On Sat, Feb 15, 2025 at 11:30?PM Heiko St?bner <heiko at sntech.de> 
> >>> wrote:
> >>>> Am Samstag, 15. Februar 2025, 19:59:44 MEZ schrieb Alexey Charkov:
> >>>>> On Tue, Feb 11, 2025 at 7:32?PM Quentin Schulz 
> >>>>> <quentin.schulz at cherry.de> wrote:
> >>>>>> On 6/17/24 8:28 PM, Alexey Charkov wrote:
> >> [...]
> >>>>>>> +     };
> >>>>>>> +
> >>>>>>> +     cluster2_opp_table: opp-table-cluster2 {
> >>>>>>> +             compatible = "operating-points-v2";
> >>>>>>> +             opp-shared;
> >>>>>>> +
> >>>>>>> +             opp-1416000000 {
> >>>>>>> +                     opp-hz = /bits/ 64 <1416000000>;
> >>>>>>> +                     opp-microvolt = <750000 750000 950000>;
> >>>>>>> +                     clock-latency-ns = <40000>;
> >>>>>>> +             };
> >>>>>>> +             opp-1608000000 {
> >>>>>>> +                     opp-hz = /bits/ 64 <1608000000>;
> >>>>>>> +                     opp-microvolt = <787500 787500 950000>;
> >>>>>>> +                     clock-latency-ns = <40000>;
> >>>>>>> +             };
> >>>>>>> +             opp-1800000000 {
> >>>>>>> +                     opp-hz = /bits/ 64 <1800000000>;
> >>>>>>> +                     opp-microvolt = <875000 875000 950000>;
> >>>>>>> +                     clock-latency-ns = <40000>;
> >>>>>>> +             };
> >>>>>>> +             opp-2016000000 {
> >>>>>>> +                     opp-hz = /bits/ 64 <2016000000>;
> >>>>>>> +                     opp-microvolt = <950000 950000 950000>;
> >>>>>>> +                     clock-latency-ns = <40000>;
> >>>>>>> +             };
> >>>>>> 
> >>>>>> opp-1800000000 and opp-2016000000 should be removed as well.
> >>>>>> 
> >>>>>> Did I misunderstand what Rockchip did here? Adding Kever in Cc at 
> >>>>>> least
> >>>>>> for awareness on Rockchip side :)
> >>>>>> 
> >>>>>> I guess another option could be to mark those above as
> >>>>>> 
> >>>>>> turbo-mode;
> >>>>>> 
> >>>>>> though no clue what this would entail. From a glance at cpufreq, 
> >>>>>> it
> >>>>>> seems that for Rockchip since we use the default cpufreq-dt, it 
> >>>>>> would
> >>>>>> mark those as unusable, so essentially a no-op, so better remove 
> >>>>>> them
> >>>>>> entirely?
> >>>>> 
> >>>>> I believe the opp core just marks 'turbo-mode' opps as
> >>>>> CPUFREQ_BOOST_FREQ, and cpufreq-dt only passes that flag along to 
> >>>>> the
> >>>>> cpufreq core. But then to actually use those boost frequencies I 
> >>>>> would
> >>>>> guess the governor needs to somehow know the power/thermal 
> >>>>> constraints
> >>>>> of the chip?.. Don't know where that is defined.
> >>>> 
> >>>> personally I don't believe in "boost" frequencies - except when they 
> >>>> are
> >>>> declared officially.
> >>>> 
> >>>> Rockchip for the longest time maintains that running the chip 
> >>>> outside
> >>>> the declared power/rate envelope can reduce its overall lifetime.
> >>>> 
> >>>> So for Rockchip in mainline a "it runs stable for me" has never been 
> >>>> a
> >>>> suitable reasoning ;-) .
> >>> 
> >>> My key concern here was perhaps that we are looking at a file inside
> >>> the Rockchip source tree which looks relevant by the name of it, but
> >>> doesn't actually get included anywhere for any of the boards. This 
> >>> may
> >>> or may not constitute an endorsement by Rockchip of any OPPs listed
> >>> there :-D
> >> 
> >> Rockchip support stated:
> >> 
> >> """
> >> If you run overdrive mode, you do not need to include rk3588j.dtsi,
> >> and you can change it to #incldue rk3588.dtsi to ensure that the
> >> maximum frequency can reach 2GHz
> >> 
> >> below picture from datasheet.
> >> """
> >> 
> >> The picture is the table 3-2 Recommended operating conditions, page 30
> >> from the RK3588J datasheet, e.g.
> >> https://www.lcsc.com/datasheet/lcsc_datasheet_2403201054_Rockchip-RK3588J_C22364189.pdf
> >> 
> >> What is overdrive?
> >> 
> >> """
> >> Overdrive mode brings higher frequency, and the voltage will increase
> >> accordingly. Under
> >> the overdrive mode for a long time, the chipset may shorten the
> >> lifetime, especially in high temperature condition
> >> """
> >> 
> >> according to the same datasheet, end of the same table, page 31.
> >> 
> >> so this seems like a turbo-mode frequency to me.
> >> 
> >> Additionally, the note for the "normal mode" (the one with the lower
> >> freqs) states:
> >> 
> >> """
> >> Normal mode means the chipset works under safety voltage and 
> >> frequency. For the
> >> industrial environment, highly recommend to keep in normal mode, the 
> >> lifetime is
> >> reasonably guaranteed.
> >> """
> >> 
> >> I believe "industrial environment" means RK3588J used in the
> >> temperatures that aren't OK for the standard RK3588 variant?
> > 
> > Thanks a lot for obtaining these clarifications!
> > 
> > Yes, I'd say that in this case "industrial environment" boils down
> > to the extended temperature range for the RK3588J variant.
> > 
> >>> I haven't seen a TRM for the J variant, nor do I have a board with
> >>> RK3588J to run tests, so it would be great if Kever could chime in
> >>> with how these OPPs are different from the others (or not).
> >>> 
> >>>> So while the situation might be strange for the rk3588j, I really 
> >>>> only want
> >>>> correct frequencies here please - not any pseudo "turbo freqs".
> >>>> 
> >>>> I don't care that much what people do on their own device{s/trees}, 
> >>>> but
> >>>> the devicetrees we supply centrally (and to u-boot, etc) should only
> >>>> contain frequencies vetted by the manufacturer.
> >>> 
> >>> Fair enough. Let's just try and get another data point on whether
> >>> these frequencies are vetted or not.
> >> 
> >> So the higher freqs seems to be vetted (and used by default on
> >> Rockchip's BSP kernel), it just feels like you aren't really supposed
> >> to run those higher frequencies all the time? And especially not in
> >> "industrial environment"?
> >> 
> >> I would assume we want to stay on the safer side and remove those
> >> higher frequencies? Heiko?
> > 
> > I agree, we should remove the higher-frequency OPPs.  I'd like
> > to go through everything once again in detail and prepare a patch
> > that removes the unsafe OPPs, and you could review it once it's
> > on the ML, to make sure it's fine.
> 
> Just as a note, everything above (and even a bit more) is confirmed
> and clearly described in the publicly available RK3588J datasheet,
> which I'll provide as a reference in my upcoming patch.

so just to reiterate my stance, in mainline I really only want frequencies
that are not possibly influencing the lifetime of the chip.

It doesn't even matter about the variant we're talking about being
industrial :-) . When someone is using mainline I want them to be
reasonable assured that we don't have stuff in here that may affect
the lifetime of their board.

All gambling on performance for possible lifetime reduction people
can do on their own ... for example with a dt-overlay ;-) .

So TL;DR, I agree to both Quentin and Dragan


Heiko




From heiko at sntech.de  Thu Mar 13 12:03:13 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 20:03:13 +0100
Subject: [PATCH] arm64: dts: rockchip: Enable HDMI audio output for ArmSoM Sige7
In-Reply-To: <20250312164056.3998224-1-liujianfeng1994@gmail.com>
References: <20250312164056.3998224-1-liujianfeng1994@gmail.com>
Message-ID: <174189257844.294070.2578524540715601524.b4-ty@sntech.de>


On Thu, 13 Mar 2025 00:40:49 +0800, Jianfeng Liu wrote:
> HDMI audio is available on the ArmSoM Sige7 HDMI TX port.
> Enable it for HDMI0 port.
> 
> 

Applied, thanks!

[1/1] arm64: dts: rockchip: Enable HDMI audio output for ArmSoM Sige7
      commit: e2759a8d452bcc1b64ecd4e819411fa26b6ed72e

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From ariel.dalessandro at collabora.com  Thu Mar 13 12:04:18 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Thu, 13 Mar 2025 16:04:18 -0300
Subject: [PATCH v1 5/6] drm/panfrost: Enable AARCH64_4K page table format
 on mediatek_mt8188
In-Reply-To: <20250311090649.0d15d74d@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-6-ariel.dalessandro@collabora.com>
 <20250311090649.0d15d74d@collabora.com>
Message-ID: <fa5ff28c-ffa0-47d7-9498-ef8b297c7afb@collabora.com>

Boris,

On 3/11/25 5:06 AM, Boris Brezillon wrote:
> On Mon, 10 Mar 2025 16:59:20 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> Now that Panfrost supports AARCH64_4K page table format, let's enable it
>> on Mediatek MT8188.
> 
> Can you maybe give more details on why this is needed
> (legacy shareability/cacheability not suitable for this GPU?)?

Ack, will expand in v2.

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From qperret at google.com  Thu Mar 13 12:08:20 2025
From: qperret at google.com (Quentin Perret)
Date: Thu, 13 Mar 2025 19:08:20 +0000
Subject: [PATCH] KVM: arm64: Drop sort_memblock_regions()
In-Reply-To: <20250311043718.91004-1-gshan@redhat.com>
References: <20250311043718.91004-1-gshan@redhat.com>
Message-ID: <Z9MtJPNm1pLATGo7@google.com>

On Tuesday 11 Mar 2025 at 14:37:18 (+1000), Gavin Shan wrote:
> Drop sort_memblock_regions() and avoid sorting the copied memory
> regions to be ascending order on their base addresses, because the
> source memory regions should have been sorted correctly when they
> are added by memblock_add() or its variants.
> 
> This is generally reverting commit a14307f5310c ("KVM: arm64: Sort
> the hypervisor memblocks"). No functional changes intended.

I think this was originally introduced in an early version of the code
where the reserved regions were also registered, hence requiring
sorting. But yes, with the code as it is today I can't see what would
break without it, so:

  Reviewed-by: Quentin Perret <qperret at google.com>

Thanks!
Quentin


From song at kernel.org  Thu Mar 13 12:10:56 2025
From: song at kernel.org (Song Liu)
Date: Thu, 13 Mar 2025 12:10:56 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250313-angelic-coral-giraffe-dfa4f3@leitao>
References: <20250308012742.3208215-1-song@kernel.org> <20250308012742.3208215-2-song@kernel.org>
 <20250313-angelic-coral-giraffe-dfa4f3@leitao>
Message-ID: <CAPhsuW4QjDx1_2xXVjPzy2HueR+ZGb-q=zsn4S-TYSp38Tp-Zg@mail.gmail.com>

On Thu, Mar 13, 2025 at 11:12?AM Breno Leitao <leitao at debian.org> wrote:
>
> On Fri, Mar 07, 2025 at 05:27:41PM -0800, Song Liu wrote:
> > With proper exception boundary detection, it is possible to implment
> > arch_stack_walk_reliable without sframe.
> >
> > Note that, arch_stack_walk_reliable does not guarantee getting reliable
> > stack in all scenarios. Instead, it can reliably detect when the stack
> > trace is not reliable, which is enough to provide reliable livepatching.
> >
> > This version has been inspired by Weinan Liu's patch [1].
> >
> > [1] https://lore.kernel.org/live-patching/20250127213310.2496133-7-wnliu at google.com/
> > Signed-off-by: Song Liu <song at kernel.org>
>
> Tested-by: Breno Leitao <leitao at debian.org>

Thanks for the testing!

>
> >  arch/arm64/Kconfig                         |  2 +-
> >  arch/arm64/include/asm/stacktrace/common.h |  1 +
> >  arch/arm64/kernel/stacktrace.c             | 44 +++++++++++++++++++++-
> >  3 files changed, 45 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 940343beb3d4..ed4f7bf4a879 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -275,6 +275,7 @@ config ARM64
> >       select HAVE_SOFTIRQ_ON_OWN_STACK
> >       select USER_STACKTRACE_SUPPORT
> >       select VDSO_GETRANDOM
> > +     select HAVE_RELIABLE_STACKTRACE
>
> Can we really mark this is reliable stacktrace?  I am wondering
> if we need an intermediate state (potentially reliable stacktrace?)
> until we have a fully reliable stack unwinder.

AFAICT, we do not expect arch_stack_walk_reliable() to always
return a reliable stack. Instead, it is expected to return -EINVAL if
the stack trace is not reliable. OTOH, arch_stack_walk() doesn't
warn the caller when the stack trace is not reliable. This is exactly
what we need for live patch: we just need to make the patch
transition when the stack trace is reliable and none of the functions
in the stack is being patched. If the stack trace is not reliable, we
will retry the transition at a later time.

Thanks,
Song


From qperret at google.com  Thu Mar 13 12:13:14 2025
From: qperret at google.com (Quentin Perret)
Date: Thu, 13 Mar 2025 19:13:14 +0000
Subject: [PATCH 4/6] KVM: arm64: Move hyp state to hyp_vmemmap
In-Reply-To: <Z8V6xOVCPp7OOX6g@google.com>
References: <20250227003310.367350-1-qperret@google.com>
 <20250227003310.367350-5-qperret@google.com>
 <Z8V6xOVCPp7OOX6g@google.com>
Message-ID: <Z9MuSsOQuTy1kAwK@google.com>

On Monday 03 Mar 2025 at 09:47:48 (+0000), Vincent Donnefort wrote:
> [...]
> 
> > diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
> > index 1a414288fe8c..955c431af5d0 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/setup.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/setup.c
> > @@ -194,16 +194,20 @@ static int fix_host_ownership_walker(const struct kvm_pgtable_visit_ctx *ctx,
> >  
> >  	/*
> >  	 * Adjust the host stage-2 mappings to match the ownership attributes
> > -	 * configured in the hypervisor stage-1.
> > +	 * configured in the hypervisor stage-1, and make sure to propagate them
> > +	 * to the hyp_vmemmap state.
> >  	 */
> >  	state = pkvm_getstate(kvm_pgtable_hyp_pte_prot(ctx->old));
> >  	switch (state) {
> >  	case PKVM_PAGE_OWNED:
> > +		set_hyp_state(phys, PKVM_PAGE_OWNED);
> >  		return host_stage2_set_owner_locked(phys, PAGE_SIZE, PKVM_ID_HYP);
> >  	case PKVM_PAGE_SHARED_OWNED:
> > +		set_hyp_state(phys, PKVM_PAGE_SHARED_OWNED);
> >  		set_host_state(phys, PKVM_PAGE_SHARED_BORROWED);
> >  		break;
> >  	case PKVM_PAGE_SHARED_BORROWED:
> > +		set_hyp_state(phys, PKVM_PAGE_SHARED_BORROWED);
> >  		set_host_state(phys, PKVM_PAGE_SHARED_OWNED);
> >  		break;
> >  	default:
> 
> Are the SHARED_OWNED/SHARED_BORROWED still relevant since the introduction of
> "KVM: arm64: Don't map 'kvm_vgic_global_state' at EL2 with pKVM"? It doesn't
> seem we have any !OWNED pages in the hyp anymore at setup, do we?

That's a good point. I personally don't hate that we have this code here
for completeness though -- it's simple enough that maintaining it isn't
too bad, and if we were to add shared pages in the future it would 'just
work'. But no strong opinion. I guess we could also remove this code as
a separate clean-up, this isn't specific to this series.

Thanks!
Quentin


From acme at kernel.org  Thu Mar 13 12:21:36 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Thu, 13 Mar 2025 16:21:36 -0300
Subject: [PATCH v5 09/11] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <20250308003209.234114-10-irogers@google.com>
References: <20250308003209.234114-1-irogers@google.com>
 <20250308003209.234114-10-irogers@google.com>
Message-ID: <Z9MwQJ5bRu6-N43w@x1>

On Fri, Mar 07, 2025 at 04:32:07PM -0800, Ian Rogers wrote:
> Switch to use the lookup table containing all architectures rather
> than tables matching the perf binary.
> 
> This fixes perf trace when executed on a 32-bit i386 binary on an
> x86-64 machine. Note in the following the system call names of the
> 32-bit i386 binary as seen by an x86-64 perf.
> 

Reproduced the results here:

root at number:/home/acme/c# file faccessat2
faccessat2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=8dafcc1549658d57248dce883e8ec7eea3d6e8a5, for GNU/Linux 3.2.0, not stripped
root at number:/home/acme/c#

root at number:/home/acme/c# strace ./faccessat2 |& head 
execve("./faccessat2", ["./faccessat2"], 0x7ffce63265e0 /* 39 vars */) = 0
[ Process PID=2552445 runs in 32 bit mode. ]
brk(NULL)                               = 0x849a000
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7fb3000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
statx(3, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, STATX_BASIC_STATS, {stx_mask=STATX_ALL|STATX_MNT_ID|STATX_SUBVOL, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=85091, ...}) = 0
mmap2(NULL, 85091, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7f9e000
close(3)                                = 0
openat(AT_FDCWD, "/lib/libc.so.6", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
root at number:/home/acme/c#

Before:

root at number:/home/acme/c# perf trace ./faccessat2 |& head
faccessat2(123, (null), X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) = -1
         ? (         ): faccessat2/2552543  ... [continued]: munmap())                                           = 0
     0.024 ( 0.002 ms): faccessat2/2552543 recvfrom(ubuf: 0x2, size: 4159848428, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f20000, addr: 0xe30, addr_len: 0xffcda98c) = 138993664
     0.047 ( 0.006 ms): faccessat2/2552543 lgetxattr(name: "", value: 0x3, size: 34)                             = 4159602688
     0.063 ( 0.003 ms): faccessat2/2552543 dup2(oldfd: -135160188, newfd: 4)                                     = -1 ENOENT (No such file or directory)
     0.071 ( 0.023 ms): faccessat2/2552543 preadv(fd: 4294967196, vec: 0xf7f16420, vlen: 557056, pos_h: 4159848428) = 3
     0.098 ( 0.004 ms): faccessat2/2552543 lgetxattr(name: "", value: 0x1, size: 2)                              = 4159516672
     0.104 ( 0.001 ms): faccessat2/2552543 lstat(filename: "", statbuf: 0x14c63)                                 = 0
     0.114 ( 0.004 ms): faccessat2/2552543 preadv(fd: 4294967196, vec: 0xf7ee8380, vlen: 557056, pos_h: 4159848428) = 3
     0.118 ( 0.002 ms): faccessat2/2552543 close(fd: 3)                                                          = 512
root at number:/home/acme/c# 

After:

root at number:/home/acme/c# perf trace ./faccessat2 |& head
faccessat2(123, (null), X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) = -1
sh: line 1: perf-read-vdso32: command not found
         ? (         ): faccessat2/2556897  ... [continued]: execve())                                           = 0
     0.028 ( 0.002 ms): faccessat2/2556897 brk()                                                                 = 0x8fe4000
     0.068 ( 0.003 ms): faccessat2/2556897 access(filename: 0xf7ff2e84, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.080 ( 0.005 ms): faccessat2/2556897 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.094 ( 0.001 ms): faccessat2/2556897 close(fd: 3)                                                          = 0
     0.103 ( 0.003 ms): faccessat2/2556897 openat(dfd: CWD, filename: "/lib/libc.so.6", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.108 ( 0.002 ms): faccessat2/2556897 read(fd: 3, buf: 0xffdd84b0, count: 512)                              = 512
     0.216 ( 0.001 ms): faccessat2/2556897 close(fd: 3)                                                          = 0
root at number:/home/acme/c#

And interestingly the openat syscall got its contents obtained via the
BPF augmenter... better to test this more thoroughly, but I think it
should come after this series lands.

- Arnaldo



From helgaas at kernel.org  Thu Mar 13 12:22:54 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 13 Mar 2025 14:22:54 -0500
Subject: [PATCH v11 04/11] PCI: dwc: Move devm_pci_alloc_host_bridge() to
 the beginning of dw_pcie_host_init()
In-Reply-To: <20250313-pci_fixup_addr-v11-4-01d2313502ab@nxp.com>
Message-ID: <20250313192254.GA745234@bhelgaas>

On Thu, Mar 13, 2025 at 11:38:40AM -0400, Frank Li wrote:
> Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init().
> Since devm_pci_alloc_host_bridge() is common code that doesn't depend on
> any DWC resource, moving it earlier improves code logic and readability.
> 
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index c57831902686e..52a441662cabe 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -452,6 +452,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  
>  	raw_spin_lock_init(&pp->lock);
>  
> +	bridge = devm_pci_alloc_host_bridge(dev, 0);
> +	if (!bridge)
> +		return bridge;

This returns NULL (0) where it previously returned -ENOMEM.  Callers
interpret zero as "success", so I think it should stil return -ENOMEM.

I tentatively changed it back to -ENOMEM locally, let me know if
that's wrong.

> +	pp->bridge = bridge;
> +
>  	ret = dw_pcie_get_resources(pci);
>  	if (ret)
>  		return ret;
> @@ -460,12 +466,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	if (ret)
>  		return ret;
>  
> -	bridge = devm_pci_alloc_host_bridge(dev, 0);
> -	if (!bridge)
> -		return -ENOMEM;
> -
> -	pp->bridge = bridge;
> -
>  	/* Get the I/O range from DT */
>  	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
>  	if (win) {
> 
> -- 
> 2.34.1
> 


From festevam at gmail.com  Thu Mar 13 12:29:43 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 13 Mar 2025 16:29:43 -0300
Subject: [PATCH] ARM: dts: imx: Fix the iim compatible string
Message-ID: <20250313192943.1547330-1-festevam@gmail.com>

Per imx-iim.yaml, the compatible string should only contain a single
entry.

Change it accordingly to fix the following dt-schema warnings:

efuse at 83f98000: compatible: ['fsl,imx51-iim', 'fsl,imx27-iim', 'syscon'] is too long

Signed-off-by: Fabio Estevam <festevam at gmail.com>
---
 arch/arm/boot/dts/nxp/imx/imx31.dtsi | 2 +-
 arch/arm/boot/dts/nxp/imx/imx51.dtsi | 2 +-
 arch/arm/boot/dts/nxp/imx/imx53.dtsi | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx31.dtsi b/arch/arm/boot/dts/nxp/imx/imx31.dtsi
index 00006c90d9a7..637415564c64 100644
--- a/arch/arm/boot/dts/nxp/imx/imx31.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx31.dtsi
@@ -218,7 +218,7 @@ spi2: spi at 50010000 {
 			};
 
 			iim: efuse at 5001c000 {
-				compatible = "fsl,imx31-iim", "fsl,imx27-iim";
+				compatible = "fsl,imx31-iim";
 				reg = <0x5001c000 0x1000>;
 				interrupts = <19>;
 				clocks = <&clks 25>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
index cc88da4d7785..5627c5a925ee 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
@@ -476,7 +476,7 @@ aipstz2: bridge at 83f00000 {
 			};
 
 			iim: efuse at 83f98000 {
-				compatible = "fsl,imx51-iim", "fsl,imx27-iim", "syscon";
+				compatible = "fsl,imx51-iim";
 				reg = <0x83f98000 0x4000>;
 				interrupts = <69>;
 				clocks = <&clks IMX5_CLK_IIM_GATE>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
index 845e2bf8460a..4829861ab488 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
@@ -668,7 +668,7 @@ aipstz2: bridge at 63f00000 {
 			};
 
 			iim: efuse at 63f98000 {
-				compatible = "fsl,imx53-iim", "fsl,imx27-iim", "syscon";
+				compatible = "fsl,imx53-iim";
 				reg = <0x63f98000 0x4000>;
 				interrupts = <69>;
 				clocks = <&clks IMX5_CLK_IIM_GATE>;
-- 
2.34.1



From will at kernel.org  Thu Mar 13 12:30:58 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 19:30:58 +0000
Subject: [syzbot] [arm?] WARNING in delayed_work_timer_fn
In-Reply-To: <20250214164556.GA13743@willie-the-truck>
References: <00000000000046efb605fec3def0@google.com>
 <675c28e0.050a0220.17d782.000d.GAE@google.com>
 <20250211111045.GA8885@willie-the-truck>
 <Z6u6MgaJWMpjCn4O@slm.duckdns.org>
 <20250214164556.GA13743@willie-the-truck>
Message-ID: <20250313193057.GA7784@willie-the-truck>

On Fri, Feb 14, 2025 at 04:45:57PM +0000, Will Deacon wrote:
> On Tue, Feb 11, 2025 at 10:59:30AM -1000, Tejun Heo wrote:
> > On Tue, Feb 11, 2025 at 11:10:46AM +0000, Will Deacon wrote:
> > > Given that this seems to explode a few times a month, I wonder if it's
> > > worth adding some instrumentation to e.g. dump the name of the workqueue?
> > 
> > It's usually most useful to print out the work function when identifying the
> > culprit. I'd be happy to take the patch.
> 
> Thanks, Tejun. I sent a patch adding some more diagnostics:
> 
> https://lore.kernel.org/r/20250214164349.13694-1-will at kernel.org

Ok, we have our first crash [1] with the new debug information:

[   77.133818][   T10] Bluetooth: hci3: Opcode 0x0c1a failed: -110
[   77.135329][   T10] Bluetooth: hci3: Error when powering off device on rfkill (-110)
[   77.143656][    C1] ------------[ cut here ]------------
[   77.145336][    C1] workqueue: cannot queue hci_cmd_timeout on wq hci3
[   77.147101][    C1] WARNING: CPU: 1 PID: 7433 at kernel/workqueue.c:2258 __queue_work+0xe94/0x1324
[   77.149301][    C1] Modules linked in:
[   77.150287][    C1] CPU: 1 UID: 0 PID: 7433 Comm: syz.2.193 Not tainted 6.14.0-rc5-syzkaller-g77c95b8c7a16 #0
[   77.152960][    C1] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025
[   77.155583][    C1] pstate: 604000c5 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   77.157546][    C1] pc : __queue_work+0xe94/0x1324
[   77.158811][    C1] lr : __queue_work+0xe94/0x1324
[   77.160114][    C1] sp : ffff800080017b40
[   77.161145][    C1] x29: ffff800080017b90 x28: dfff800000000000 x27: ffff700010002f88
[   77.163285][    C1] x26: ffff80008fbbd600 x25: ffff0000dacac800 x24: 0000000000000008
[   77.165326][    C1] x23: ffff0000dacac9c0 x22: 0000000000000100 x21: 1fffe0001b595938
[   77.167421][    C1] x20: ffff800092f09000 x19: ffff0000ecf20948 x18: 0000000000000008
[   77.169356][    C1] x17: 0000000000000000 x16: ffff80008b72ce6c x15: ffff700011f87b38
[   77.171279][    C1] x14: 1ffff00011f87b38 x13: 0000000000000004 x12: ffffffffffffffff
[   77.173271][    C1] x11: 0000000000000103 x10: 0000000000ff0100 x9 : d5bcdc7e4519df00
[   77.175255][    C1] x8 : d5bcdc7e4519df00 x7 : 0000000000000001 x6 : 0000000000000001
[   77.177277][    C1] x5 : ffff8000800172f8 x4 : ffff80008fcaf7c0 x3 : ffff8000804a7bb4
[   77.179372][    C1] x2 : 0000000000000000 x1 : 0000000100000101 x0 : 0000000000000000
[   77.181374][    C1] Call trace:
[   77.182230][    C1]  __queue_work+0xe94/0x1324 (P)
[   77.183476][    C1]  delayed_work_timer_fn+0x74/0x90
[   77.184755][    C1]  call_timer_fn+0x1b4/0x8b8
[   77.185932][    C1]  __run_timer_base+0x59c/0x7b4
[   77.187119][    C1]  run_timer_softirq+0xcc/0x194
[   77.188360][    C1]  handle_softirqs+0x320/0xd34
[   77.189576][    C1]  __do_softirq+0x14/0x20
[   77.190672][    C1]  ____do_softirq+0x14/0x20
[   77.191884][    C1]  call_on_irq_stack+0x24/0x4c
[   77.193050][    C1]  do_softirq_own_stack+0x20/0x2c
[   77.194311][    C1]  __irq_exit_rcu+0x1d8/0x544
[   77.195550][    C1]  irq_exit_rcu+0x14/0x84
[   77.196669][    C1]  el1_interrupt+0x38/0x68
[   77.197818][    C1]  el1h_64_irq_handler+0x18/0x24
[   77.199152][    C1]  el1h_64_irq+0x6c/0x70
[   77.200245][    C1]  lock_acquire+0x278/0x724 (P)
[   77.201520][    C1]  rcu_lock_acquire+0x44/0x54
[   77.202722][    C1]  page_ext_get+0x2c/0x2e8
[   77.203908][    C1]  page_table_check_set+0xa0/0x408
[   77.205117][    C1]  __page_table_check_ptes_set+0x2d0/0x398
[   77.206601][    C1]  set_pte_range+0x618/0x644
[   77.207792][    C1]  finish_fault+0x968/0xd6c
[   77.208968][    C1]  handle_pte_fault+0x3528/0x57b0
[   77.210314][    C1]  handle_mm_fault+0xfa8/0x188c
[   77.211592][    C1]  __get_user_pages+0x1878/0x3400
[   77.212967][    C1]  populate_vma_page_range+0x220/0x2f0
[   77.214435][    C1]  __mm_populate+0x240/0x3d8
[   77.215600][    C1]  vm_mmap_pgoff+0x304/0x3c4
[   77.216833][    C1]  ksys_mmap_pgoff+0xd0/0x5c8
[   77.218066][    C1]  __arm64_sys_mmap+0xf8/0x110
[   77.219195][    C1]  invoke_syscall+0x98/0x2b8
[   77.220453][    C1]  el0_svc_common+0x130/0x23c
[   77.221747][    C1]  do_el0_svc+0x48/0x58
[   77.222881][    C1]  el0_svc+0x54/0x168
[   77.223946][    C1]  el0t_64_sync_handler+0x84/0x108
[   77.225305][    C1]  el0t_64_sync+0x198/0x19c
[   77.226425][    C1] irq event stamp: 3967
[   77.227573][    C1] hardirqs last  enabled at (3966): [<ffff80008b7ec538>] _raw_spin_unlock_irqrestore+0x38/0x98
[   77.230143][    C1] hardirqs last disabled at (3967): [<ffff80008b7ec3e0>] _raw_spin_lock_irq+0x28/0x70
[   77.232639][    C1] softirqs last  enabled at (2318): [<ffff800080311b48>] handle_softirqs+0xb44/0xd34
[   77.235151][    C1] softirqs last disabled at (3923): [<ffff800080020dbc>] __do_softirq+0x14/0x20
[   77.237528][    C1] ---[ end trace 0000000000000000 ]---


So it looks like I was right about bluetooth (the work function is
"hci_cmd_timeout") but, unfortunately, "hci3" doesn't tell us much about
the client.

Perhaps the failed power-off right before the warning suggests that
we're not tearing down the wq properly on that error path? Let's see...

hci_rfkill_set_block() calls hci_dev_do_close() if the power-off fails.
That in turn cancels the delayed 'cmd_timer' work but only if HCI_UP is
not set in the device flags. But if hci_dev_do_poweroff() failed, HCI_UP
may well still be set. Then somehow the workqueue is destroyed, I guess
via hci_unregister_dev() setting HCI_UNREGISTER which enables
hci_release_dev() but at that point it's hard to know which bluetooth
driver is responsible.

Assuming hci_unregister_dev() is triggered via hci_dev_do_close()
closing the device, then unconditionally cancelling the delayed cmd work
when clearing HCI_UP sounds like a reasonable starter for ten?

Dunno, this is all guesswork in code that I'm not familiar with, so I'm
hoping somebody can tell me why I'm wrong :)

Will

--->8

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index dd770ef5ec36..d2623f6d0593 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5147,11 +5147,9 @@ int hci_dev_close_sync(struct hci_dev *hdev)
        }

        err = hci_dev_shutdown(hdev);
-
-       if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
-               cancel_delayed_work_sync(&hdev->cmd_timer);
+       cancel_delayed_work_sync(&hdev->cmd_timer);
+       if (!test_and_clear_bit(HCI_UP, &hdev->flags))
                return err;
-       }

        hci_leds_update_powered(hdev, false);
 


From dsimic at manjaro.org  Thu Mar 13 12:43:41 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Thu, 13 Mar 2025 20:43:41 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores
 on RK3588j
In-Reply-To: <3271211.5fSG56mABF@phil>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <a56b59a21dc3c21192fe45197eee4865@manjaro.org>
 <2cf3889741f84584d8f23a4407fed08e@manjaro.org> <3271211.5fSG56mABF@phil>
Message-ID: <80c7d9fcdd270df2c61fbd61eec44d70@manjaro.org>

Hello Heiko,

On 2025-03-13 20:00, Heiko Stuebner wrote:
> Am Donnerstag, 13. M?rz 2025, 11:42:17 MEZ schrieb Dragan Simic:
>> On 2025-03-12 11:34, Dragan Simic wrote:
>> > On 2025-03-12 11:15, Quentin Schulz wrote:
>> >> On 2/16/25 1:32 PM, Alexey Charkov wrote:
>> >>> On Sat, Feb 15, 2025 at 11:30?PM Heiko St?bner <heiko at sntech.de>
>> >>> wrote:
>> >>>> Am Samstag, 15. Februar 2025, 19:59:44 MEZ schrieb Alexey Charkov:
>> >>>>> On Tue, Feb 11, 2025 at 7:32?PM Quentin Schulz
>> >>>>> <quentin.schulz at cherry.de> wrote:
>> >>>>>> On 6/17/24 8:28 PM, Alexey Charkov wrote:
>> >> [...]
>> >>>>>>> +     };
>> >>>>>>> +
>> >>>>>>> +     cluster2_opp_table: opp-table-cluster2 {
>> >>>>>>> +             compatible = "operating-points-v2";
>> >>>>>>> +             opp-shared;
>> >>>>>>> +
>> >>>>>>> +             opp-1416000000 {
>> >>>>>>> +                     opp-hz = /bits/ 64 <1416000000>;
>> >>>>>>> +                     opp-microvolt = <750000 750000 950000>;
>> >>>>>>> +                     clock-latency-ns = <40000>;
>> >>>>>>> +             };
>> >>>>>>> +             opp-1608000000 {
>> >>>>>>> +                     opp-hz = /bits/ 64 <1608000000>;
>> >>>>>>> +                     opp-microvolt = <787500 787500 950000>;
>> >>>>>>> +                     clock-latency-ns = <40000>;
>> >>>>>>> +             };
>> >>>>>>> +             opp-1800000000 {
>> >>>>>>> +                     opp-hz = /bits/ 64 <1800000000>;
>> >>>>>>> +                     opp-microvolt = <875000 875000 950000>;
>> >>>>>>> +                     clock-latency-ns = <40000>;
>> >>>>>>> +             };
>> >>>>>>> +             opp-2016000000 {
>> >>>>>>> +                     opp-hz = /bits/ 64 <2016000000>;
>> >>>>>>> +                     opp-microvolt = <950000 950000 950000>;
>> >>>>>>> +                     clock-latency-ns = <40000>;
>> >>>>>>> +             };
>> >>>>>>
>> >>>>>> opp-1800000000 and opp-2016000000 should be removed as well.
>> >>>>>>
>> >>>>>> Did I misunderstand what Rockchip did here? Adding Kever in Cc at
>> >>>>>> least
>> >>>>>> for awareness on Rockchip side :)
>> >>>>>>
>> >>>>>> I guess another option could be to mark those above as
>> >>>>>>
>> >>>>>> turbo-mode;
>> >>>>>>
>> >>>>>> though no clue what this would entail. From a glance at cpufreq,
>> >>>>>> it
>> >>>>>> seems that for Rockchip since we use the default cpufreq-dt, it
>> >>>>>> would
>> >>>>>> mark those as unusable, so essentially a no-op, so better remove
>> >>>>>> them
>> >>>>>> entirely?
>> >>>>>
>> >>>>> I believe the opp core just marks 'turbo-mode' opps as
>> >>>>> CPUFREQ_BOOST_FREQ, and cpufreq-dt only passes that flag along to
>> >>>>> the
>> >>>>> cpufreq core. But then to actually use those boost frequencies I
>> >>>>> would
>> >>>>> guess the governor needs to somehow know the power/thermal
>> >>>>> constraints
>> >>>>> of the chip?.. Don't know where that is defined.
>> >>>>
>> >>>> personally I don't believe in "boost" frequencies - except when they
>> >>>> are
>> >>>> declared officially.
>> >>>>
>> >>>> Rockchip for the longest time maintains that running the chip
>> >>>> outside
>> >>>> the declared power/rate envelope can reduce its overall lifetime.
>> >>>>
>> >>>> So for Rockchip in mainline a "it runs stable for me" has never been
>> >>>> a
>> >>>> suitable reasoning ;-) .
>> >>>
>> >>> My key concern here was perhaps that we are looking at a file inside
>> >>> the Rockchip source tree which looks relevant by the name of it, but
>> >>> doesn't actually get included anywhere for any of the boards. This
>> >>> may
>> >>> or may not constitute an endorsement by Rockchip of any OPPs listed
>> >>> there :-D
>> >>
>> >> Rockchip support stated:
>> >>
>> >> """
>> >> If you run overdrive mode, you do not need to include rk3588j.dtsi,
>> >> and you can change it to #incldue rk3588.dtsi to ensure that the
>> >> maximum frequency can reach 2GHz
>> >>
>> >> below picture from datasheet.
>> >> """
>> >>
>> >> The picture is the table 3-2 Recommended operating conditions, page 30
>> >> from the RK3588J datasheet, e.g.
>> >> https://www.lcsc.com/datasheet/lcsc_datasheet_2403201054_Rockchip-RK3588J_C22364189.pdf
>> >>
>> >> What is overdrive?
>> >>
>> >> """
>> >> Overdrive mode brings higher frequency, and the voltage will increase
>> >> accordingly. Under
>> >> the overdrive mode for a long time, the chipset may shorten the
>> >> lifetime, especially in high temperature condition
>> >> """
>> >>
>> >> according to the same datasheet, end of the same table, page 31.
>> >>
>> >> so this seems like a turbo-mode frequency to me.
>> >>
>> >> Additionally, the note for the "normal mode" (the one with the lower
>> >> freqs) states:
>> >>
>> >> """
>> >> Normal mode means the chipset works under safety voltage and
>> >> frequency. For the
>> >> industrial environment, highly recommend to keep in normal mode, the
>> >> lifetime is
>> >> reasonably guaranteed.
>> >> """
>> >>
>> >> I believe "industrial environment" means RK3588J used in the
>> >> temperatures that aren't OK for the standard RK3588 variant?
>> >
>> > Thanks a lot for obtaining these clarifications!
>> >
>> > Yes, I'd say that in this case "industrial environment" boils down
>> > to the extended temperature range for the RK3588J variant.
>> >
>> >>> I haven't seen a TRM for the J variant, nor do I have a board with
>> >>> RK3588J to run tests, so it would be great if Kever could chime in
>> >>> with how these OPPs are different from the others (or not).
>> >>>
>> >>>> So while the situation might be strange for the rk3588j, I really
>> >>>> only want
>> >>>> correct frequencies here please - not any pseudo "turbo freqs".
>> >>>>
>> >>>> I don't care that much what people do on their own device{s/trees},
>> >>>> but
>> >>>> the devicetrees we supply centrally (and to u-boot, etc) should only
>> >>>> contain frequencies vetted by the manufacturer.
>> >>>
>> >>> Fair enough. Let's just try and get another data point on whether
>> >>> these frequencies are vetted or not.
>> >>
>> >> So the higher freqs seems to be vetted (and used by default on
>> >> Rockchip's BSP kernel), it just feels like you aren't really supposed
>> >> to run those higher frequencies all the time? And especially not in
>> >> "industrial environment"?
>> >>
>> >> I would assume we want to stay on the safer side and remove those
>> >> higher frequencies? Heiko?
>> >
>> > I agree, we should remove the higher-frequency OPPs.  I'd like
>> > to go through everything once again in detail and prepare a patch
>> > that removes the unsafe OPPs, and you could review it once it's
>> > on the ML, to make sure it's fine.
>> 
>> Just as a note, everything above (and even a bit more) is confirmed
>> and clearly described in the publicly available RK3588J datasheet,
>> which I'll provide as a reference in my upcoming patch.
> 
> so just to reiterate my stance, in mainline I really only want 
> frequencies
> that are not possibly influencing the lifetime of the chip.
> 
> It doesn't even matter about the variant we're talking about being
> industrial :-) . When someone is using mainline I want them to be
> reasonable assured that we don't have stuff in here that may affect
> the lifetime of their board.
> 
> All gambling on performance for possible lifetime reduction people
> can do on their own ... for example with a dt-overlay ;-) .
> 
> So TL;DR, I agree to both Quentin and Dragan

Thanks!  Indeed, we must provide only the OPPs that are declared
by the manufacturer to be always safe for the particular SoC
variant.  The RK3588J is actually a good example, because it, in
theory, can run safely at higher OPPs as well, but only when not
enjoying the extended temperature range that the RK3588J, as an
SoC variant targeted at industrial applications, is specifically
made (or binned) for.

Thus, we must support only the RK3588J OPPs that are declared to
be safe throughout the entire extended temperature range, while
anyone who actually can assure that their RK3588J-based board is
never going to run within the extended temperature range, probably
may safely apply an overlay that adds the higher OPPs.  As we
obviously can't know what will be the temperature conditions, we
may provide only the lower OPPs that are always safe.

I'll finish the patch and send it over tomorrow or so...  I still
need to go through the changes once again, to make 100% sure I've
missed nothing, and that I haven't included anything extraneous. :)


From acme at kernel.org  Thu Mar 13 12:49:52 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Thu, 13 Mar 2025 16:49:52 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9KFLGpenwOP32q3@google.com>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
Message-ID: <Z9M24AJzui9lFbGo@x1>

On Thu, Mar 13, 2025 at 12:11:40AM -0700, Namhyung Kim wrote:
> On Fri, Mar 07, 2025 at 04:31:58PM -0800, Ian Rogers wrote:
> > This work builds on the clean up of system call tables and removal of
> > libaudit by Charlie Jenkins <charlie at rivosinc.com>.
> > 
> > The system call table in perf trace is used to map system call numbers
> > to names and vice versa. Prior to these changes, a single table
> > matching the perf binary's build was present. The table would be
> > incorrect if tracing say a 32-bit binary from a 64-bit version of
> > perf, the names and numbers wouldn't match.
> > 
> > Change the build so that a single system call file is built and the
> > potentially multiple tables are identifiable from the ELF machine type
> > of the process being examined. To determine the ELF machine type, the
> > executable's maps are searched and the associated DSOs ELF headers are
> > read. When this fails and when live, /proc/pid/exe's ELF header is
> > read. Fallback to using the perf's binary type when unknown.
> 
> Now it works well for me!

Its working for me on x86_64 as well, I'm doing some more tests, the
container builds and will do 32-bit tracing on 64-bit ARM (rpi5 aarch64)
and then report results here, should be later today as the default
kernel for the rpi5 doesn't come with CONFIG_FTRACE_SYSCALLS=y and BTF,
so building one with it.

- Arnaldo


From namhyung at kernel.org  Thu Mar 13 12:55:56 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 13 Mar 2025 12:55:56 -0700
Subject: [PATCH v5 09/11] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <Z9MwQJ5bRu6-N43w@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <20250308003209.234114-10-irogers@google.com>
 <Z9MwQJ5bRu6-N43w@x1>
Message-ID: <Z9M4TIY9HstTLzNs@google.com>

On Thu, Mar 13, 2025 at 04:21:36PM -0300, Arnaldo Carvalho de Melo wrote:
> On Fri, Mar 07, 2025 at 04:32:07PM -0800, Ian Rogers wrote:
> > Switch to use the lookup table containing all architectures rather
> > than tables matching the perf binary.
> > 
> > This fixes perf trace when executed on a 32-bit i386 binary on an
> > x86-64 machine. Note in the following the system call names of the
> > 32-bit i386 binary as seen by an x86-64 perf.
> > 
> 
> Reproduced the results here:
> 
> root at number:/home/acme/c# file faccessat2
> faccessat2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=8dafcc1549658d57248dce883e8ec7eea3d6e8a5, for GNU/Linux 3.2.0, not stripped
> root at number:/home/acme/c#
> 
> root at number:/home/acme/c# strace ./faccessat2 |& head 
> execve("./faccessat2", ["./faccessat2"], 0x7ffce63265e0 /* 39 vars */) = 0
> [ Process PID=2552445 runs in 32 bit mode. ]
> brk(NULL)                               = 0x849a000
> mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7fb3000
> access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
> openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
> statx(3, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, STATX_BASIC_STATS, {stx_mask=STATX_ALL|STATX_MNT_ID|STATX_SUBVOL, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=85091, ...}) = 0
> mmap2(NULL, 85091, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7f9e000
> close(3)                                = 0
> openat(AT_FDCWD, "/lib/libc.so.6", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
> root at number:/home/acme/c#
> 
> Before:
> 
> root at number:/home/acme/c# perf trace ./faccessat2 |& head
> faccessat2(123, (null), X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) = -1
>          ? (         ): faccessat2/2552543  ... [continued]: munmap())                                           = 0
>      0.024 ( 0.002 ms): faccessat2/2552543 recvfrom(ubuf: 0x2, size: 4159848428, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f20000, addr: 0xe30, addr_len: 0xffcda98c) = 138993664
>      0.047 ( 0.006 ms): faccessat2/2552543 lgetxattr(name: "", value: 0x3, size: 34)                             = 4159602688
>      0.063 ( 0.003 ms): faccessat2/2552543 dup2(oldfd: -135160188, newfd: 4)                                     = -1 ENOENT (No such file or directory)
>      0.071 ( 0.023 ms): faccessat2/2552543 preadv(fd: 4294967196, vec: 0xf7f16420, vlen: 557056, pos_h: 4159848428) = 3
>      0.098 ( 0.004 ms): faccessat2/2552543 lgetxattr(name: "", value: 0x1, size: 2)                              = 4159516672
>      0.104 ( 0.001 ms): faccessat2/2552543 lstat(filename: "", statbuf: 0x14c63)                                 = 0
>      0.114 ( 0.004 ms): faccessat2/2552543 preadv(fd: 4294967196, vec: 0xf7ee8380, vlen: 557056, pos_h: 4159848428) = 3
>      0.118 ( 0.002 ms): faccessat2/2552543 close(fd: 3)                                                          = 512
> root at number:/home/acme/c# 
> 
> After:
> 
> root at number:/home/acme/c# perf trace ./faccessat2 |& head
> faccessat2(123, (null), X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) = -1
> sh: line 1: perf-read-vdso32: command not found
>          ? (         ): faccessat2/2556897  ... [continued]: execve())                                           = 0
>      0.028 ( 0.002 ms): faccessat2/2556897 brk()                                                                 = 0x8fe4000
>      0.068 ( 0.003 ms): faccessat2/2556897 access(filename: 0xf7ff2e84, mode: R)                                 = -1 ENOENT (No such file or directory)
>      0.080 ( 0.005 ms): faccessat2/2556897 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
>      0.094 ( 0.001 ms): faccessat2/2556897 close(fd: 3)                                                          = 0
>      0.103 ( 0.003 ms): faccessat2/2556897 openat(dfd: CWD, filename: "/lib/libc.so.6", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
>      0.108 ( 0.002 ms): faccessat2/2556897 read(fd: 3, buf: 0xffdd84b0, count: 512)                              = 512
>      0.216 ( 0.001 ms): faccessat2/2556897 close(fd: 3)                                                          = 0
> root at number:/home/acme/c#
> 
> And interestingly the openat syscall got its contents obtained via the
> BPF augmenter... better to test this more thoroughly, but I think it
> should come after this series lands.

Right, I don't see the filename in openat() in my tests.

openat() is 295 on i386 and that's preadv() on x86_64 so BPF won't try
to augment the argument.  I wonder how it can get the filename.  But
anyway we can take a look later.

Thanks,
Namhyung



From ilkka at os.amperecomputing.com  Thu Mar 13 13:15:59 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 13 Mar 2025 20:15:59 +0000
Subject: [PATCH 2/2] perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation
In-Reply-To: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
Message-ID: <20250313201559.11332-3-ilkka@os.amperecomputing.com>

frontend_bound metrics was miscalculated due to different scaling in
a couple of metrics it depends on. Change the scaling to match with
AmpereOne.

Fixes: 16438b652b46 ("perf vendor events arm64 AmpereOneX: Add core PMU events and metrics")
Signed-off-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>
---
 .../arch/arm64/ampere/ampereonex/metrics.json          | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
index c5d1d22bd034..5228f94a793f 100644
--- a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
+++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
@@ -229,19 +229,19 @@
     },
     {
         "MetricName": "slots_lost_misspeculation_fraction",
-        "MetricExpr": "(OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)",
+        "MetricExpr": "100 * (OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)",
         "BriefDescription": "Fraction of slots lost due to misspeculation",
         "DefaultMetricgroupName": "TopdownL1",
         "MetricGroup": "Default;TopdownL1",
-        "ScaleUnit": "100percent of slots"
+        "ScaleUnit": "1percent of slots"
     },
     {
         "MetricName": "retired_fraction",
-        "MetricExpr": "OP_RETIRED / (CPU_CYCLES * #slots)",
+        "MetricExpr": "100 * OP_RETIRED / (CPU_CYCLES * #slots)",
         "BriefDescription": "Fraction of slots retiring, useful work",
         "DefaultMetricgroupName": "TopdownL1",
         "MetricGroup": "Default;TopdownL1",
-        "ScaleUnit": "100percent of slots"
+        "ScaleUnit": "1percent of slots"
     },
     {
         "MetricName": "backend_core",
@@ -266,7 +266,7 @@
     },
     {
         "MetricName": "frontend_bandwidth",
-        "MetricExpr": "frontend_bound - frontend_latency",
+        "MetricExpr": "frontend_bound - 100 * frontend_latency",
         "BriefDescription": "Fraction of slots the CPU did not dispatch at full bandwidth - able to dispatch partial slots only (1, 2, or 3 uops)",
         "MetricGroup": "TopdownL2",
         "ScaleUnit": "1percent of slots"
-- 
2.47.0



From ilkka at os.amperecomputing.com  Thu Mar 13 13:15:57 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 13 Mar 2025 20:15:57 +0000
Subject: [PATCH 0/2] perf vendor events arm64: AmpereOne/AmpereOneX: Add a new errata and fix metrics calculations
Message-ID: <20250313201559.11332-1-ilkka@os.amperecomputing.com>

Add an errata reference to a impacted event and fix metrics calculation
caused by a scaling issue.

Ilkka Koskinen (2):
  perf vendor events arm64: AmpereOne/AmpereOneX: Mark LD_RETIRED
    impacted by errata
  perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation

 .../pmu-events/arch/arm64/ampere/ampereone/memory.json |  4 +++-
 .../arch/arm64/ampere/ampereonex/memory.json           |  4 +++-
 .../arch/arm64/ampere/ampereonex/metrics.json          | 10 +++++-----
 3 files changed, 11 insertions(+), 7 deletions(-)

-- 
2.47.0



From ilkka at os.amperecomputing.com  Thu Mar 13 13:15:58 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 13 Mar 2025 20:15:58 +0000
Subject: [PATCH 1/2] perf vendor events arm64: AmpereOne/AmpereOneX: Mark LD_RETIRED impacted by errata
In-Reply-To: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
Message-ID: <20250313201559.11332-2-ilkka@os.amperecomputing.com>

Atomic instructions are both memory-reading and memory-writing
instructions and so should be counted by both LD_RETIRED and ST_RETIRED
performance monitoring events. However LD_RETIRED does not count atomic
instructions.

Signed-off-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>
---
 tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json | 4 +++-
 .../perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json  | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
index 0711782bfa6b..13382d29b25f 100644
--- a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
+++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
@@ -1,6 +1,8 @@
 [
     {
-        "ArchStdEvent": "LD_RETIRED"
+        "ArchStdEvent": "LD_RETIRED",
+        "Errata": "Errata AC03_CPU_52",
+        "BriefDescription": "Instruction architecturally executed, condition code check pass, load. Impacted by errata -"
     },
     {
         "ArchStdEvent": "MEM_ACCESS_RD"
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json
index a211d94aacde..6c06bc928415 100644
--- a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json
+++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json
@@ -1,6 +1,8 @@
 [
     {
-        "ArchStdEvent": "LD_RETIRED"
+        "ArchStdEvent": "LD_RETIRED",
+        "Errata": "Errata AC04_CPU_21",
+        "BriefDescription": "Instruction architecturally executed, condition code check pass, load. Impacted by errata -"
     },
     {
         "ArchStdEvent": "MEM_ACCESS_RD"
-- 
2.47.0



From cki-project at redhat.com  Thu Mar 13 13:13:01 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 13 Mar 2025 20:13:01 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc6,
 upstream-arm-next, 059f6cbc)
Message-ID: <02465.125031316130400522@us-mta-617.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1715648401

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1715648401-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From acme at kernel.org  Thu Mar 13 13:20:09 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Thu, 13 Mar 2025 17:20:09 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9M24AJzui9lFbGo@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
Message-ID: <Z9M9-YhDJg3NgiUy@x1>

On Thu, Mar 13, 2025 at 04:49:52PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Mar 13, 2025 at 12:11:40AM -0700, Namhyung Kim wrote:
> > On Fri, Mar 07, 2025 at 04:31:58PM -0800, Ian Rogers wrote:
> > > This work builds on the clean up of system call tables and removal of
> > > libaudit by Charlie Jenkins <charlie at rivosinc.com>.
> > > 
> > > The system call table in perf trace is used to map system call numbers
> > > to names and vice versa. Prior to these changes, a single table
> > > matching the perf binary's build was present. The table would be
> > > incorrect if tracing say a 32-bit binary from a 64-bit version of
> > > perf, the names and numbers wouldn't match.
> > > 
> > > Change the build so that a single system call file is built and the
> > > potentially multiple tables are identifiable from the ELF machine type
> > > of the process being examined. To determine the ELF machine type, the
> > > executable's maps are searched and the associated DSOs ELF headers are
> > > read. When this fails and when live, /proc/pid/exe's ELF header is
> > > read. Fallback to using the perf's binary type when unknown.
> > 
> > Now it works well for me!
> 
> Its working for me on x86_64 as well, I'm doing some more tests, the
> container builds and will do 32-bit tracing on 64-bit ARM (rpi5 aarch64)
> and then report results here, should be later today as the default
> kernel for the rpi5 doesn't come with CONFIG_FTRACE_SYSCALLS=y and BTF,
> so building one with it.

Still building, but noticed this on x86_64:

105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : FAILED!


The first doesn?t help that much with verbose mode, haven't checked if
before this series it was failing :-\

root at x1:~# perf test -vvv 105
105: perf trace enum augmentation tests:
--- start ---
test child forked, pid 19411
Checking if vmlinux exists
Tracing syscall landlock_add_rule
---- end(-1) ----
105: perf trace enum augmentation tests                              : FAILED!
root at x1:~#

Ditto for 106:

root at x1:~# perf test -vv 106
106: perf trace BTF general tests:
--- start ---
test child forked, pid 19467
Checking if vmlinux BTF exists
Testing perf trace's string augmentation
Testing perf trace's buffer augmentation
Buffer augmentation test failed
---- end(-1) ----
106: perf trace BTF general tests                                    : FAILED!
root at x1:~# 

108 works when its the only test:

root at x1:~# perf test 108
108: perf trace record and replay                                    : Ok
root at x1:~# perf test 108
108: perf trace record and replay                                    : Ok
root at x1:~# perf test 108
108: perf trace record and replay                                    : Ok
root at x1:~#

I'll try to check what is happening with the first two later today.

- Arnaldo


From 21cnbao at gmail.com  Thu Mar 13 13:37:04 2025
From: 21cnbao at gmail.com (Barry Song)
Date: Fri, 14 Mar 2025 09:37:04 +1300
Subject: [PATCH 0/2] Improve Zram by separating compression context from kswapd
In-Reply-To: <Z9MWzDUxUigJrZXt@google.com>
References: <20250307120141.1566673-1-qun-wei.lin@mediatek.com>
 <Z9HOavSkFf01K9xh@google.com> <5gqqbq67th4xiufiw6j3ewih6htdepa4u5lfirdeffrui7hcdn@ly3re3vgez2g>
 <CAGsJ_4xwnVxn1odj=j+z0VXm1DRUmnhugnwCH-coqBLJweDu9Q@mail.gmail.com>
 <Z9MCwXzYDRJoTiIr@google.com> <CAGsJ_4yaSx1vEiZdCouBveeH3D-bQDdvrhRpz=Kbvqn30Eh-nA@mail.gmail.com>
 <Z9MWzDUxUigJrZXt@google.com>
Message-ID: <CAGsJ_4z9pSt=LdfDUmQ7YhNocE6CJGxEwighSygGZrDFSyKU+A@mail.gmail.com>

On Fri, Mar 14, 2025 at 6:33?AM Minchan Kim <minchan at kernel.org> wrote:
>
> On Fri, Mar 14, 2025 at 05:58:00AM +1300, Barry Song wrote:
> > On Fri, Mar 14, 2025 at 5:07?AM Minchan Kim <minchan at kernel.org> wrote:
> > >
> > > On Thu, Mar 13, 2025 at 04:45:54PM +1300, Barry Song wrote:
> > > > On Thu, Mar 13, 2025 at 4:09?PM Sergey Senozhatsky
> > > > <senozhatsky at chromium.org> wrote:
> > > > >
> > > > > On (25/03/12 11:11), Minchan Kim wrote:
> > > > > > On Fri, Mar 07, 2025 at 08:01:02PM +0800, Qun-Wei Lin wrote:
> > > > > > > This patch series introduces a new mechanism called kcompressd to
> > > > > > > improve the efficiency of memory reclaiming in the operating system. The
> > > > > > > main goal is to separate the tasks of page scanning and page compression
> > > > > > > into distinct processes or threads, thereby reducing the load on the
> > > > > > > kswapd thread and enhancing overall system performance under high memory
> > > > > > > pressure conditions.
> > > > > > >
> > > > > > > Problem:
> > > > > > >  In the current system, the kswapd thread is responsible for both
> > > > > > >  scanning the LRU pages and compressing pages into the ZRAM. This
> > > > > > >  combined responsibility can lead to significant performance bottlenecks,
> > > > > > >  especially under high memory pressure. The kswapd thread becomes a
> > > > > > >  single point of contention, causing delays in memory reclaiming and
> > > > > > >  overall system performance degradation.
> > > > > >
> > > > > > Isn't it general problem if backend for swap is slow(but synchronous)?
> > > > > > I think zram need to support asynchrnous IO(can do introduce multiple
> > > > > > threads to compress batched pages) and doesn't declare it's
> > > > > > synchrnous device for the case.
> > > > >
> > > > > The current conclusion is that kcompressd will sit above zram,
> > > > > because zram is not the only compressing swap backend we have.
> > >
> > > Then, how handles the file IO case?
> >
> > I didn't quite catch your question :-)
>
> Sorry for not clear.
>
> What I meant was zram is also used for fs backend storage, not only
> for swapbackend. The multiple simultaneous compression can help the case,
> too.

I agree that multiple asynchronous threads might transparently improve
userspace read/write performance with just one thread or a very few threads.
However, it's unclear how genuine the requirement is. On the other hand,
in such cases, userspace can always optimize read/write bandwidth, for
example, by using aio_write() or similar methods if they do care about
the read/write bandwidth.

Once the user has multiple threads (close to the number of CPU cores),
asynchronous multi-threading won't offer any benefit and will only result
in increased context switching. I guess that is caused by the fundamental
difference between zram and other real devices with hardware offloads -
that zram always relies on the CPU and operates synchronously(no
offload, no interrupt from HW to notify the completion of compression).

>
> >
> > >
> > > >
> > > > also. it is not good to hack zram to be aware of if it is kswapd
> > > > , direct reclaim , proactive reclaim and block device with
> > > > mounted filesystem.
> > >
> > > Why shouldn't zram be aware of that instead of just introducing
> > > queues in the zram with multiple compression threads?
> > >
> >
> > My view is the opposite of yours :-)
> >
> > Integrating kswapd, direct reclaim, etc., into the zram driver
> > would violate layering principles. zram is purely a block device
>
> That's the my question. What's the reason zram need to know about
> kswapd, direct_reclaim and so on? I didn't understand your input.

Qun-Wei's patch 2/2, which modifies the zram driver, contains the following
code within the zram driver:

+int schedule_bio_write(void *mem, struct bio *bio, compress_callback cb)
+{
+ ...
+
+        if (!nr_kcompressd || !current_is_kswapd())
+                 return -EBUSY;
+
+}

It's clear that Qun-Wei decided to disable asynchronous threading unless
the user is kswapd. Qun-Wei might be able to provide more insight on this
decision.

My guess is:

1. Determining the optimal number of threads is challenging due to varying
CPU topologies and software workloads. For example, if there are 8 threads
writing to zram, the default 4 threads might be slower than using all 8 threads
synchronously. For servers, we could have hundreds of CPUs.
On the other hand, if there is only one thread writing to zram, using 4 threads
might interfere with other workloads too much and cause the phone to heat up
quickly.

2. kswapd is the user that truly benefits from asynchronous threads. Since
it handles asynchronous memory reclamation, speeding up its process
reduces the likelihood of entering slowpath / direct reclamation. This is
where it has the greatest potential to make a positive impact.

>
> > driver, and how it is used should be handled separately. Callers have
> > greater flexibility to determine its usage, similar to how different
> > I/O models exist in user space.
> >
> > Currently, Qun-Wei's patch checks whether the current thread is kswapd.
> > If it is, compression is performed asynchronously by threads;
> > otherwise, it is done in the current thread. In the future, we may
>
> Okay, then, why should we do that without following normal asynchrnous
> disk storage? VM justs put the IO request and sometimes congestion
> control. Why is other logic needed for the case?

It seems there is still some uncertainty about why current_is_kswapd()
is necessary, so let's get input from Qun-Wei as well.

Despite all the discussions, one important point remains: zswap might
also need this asynchronous thread. For months, Yosry and Nhat have
been urging the zram and zswap teams to collaborate on those shared
requirements. Having one per-node thread for each kswapd could be the
low-hanging fruit for both zswap and zram.

Additionally, I don't see how the prototype I proposed here [1] would conflict
with potential future optimizations in zram, particularly those aimed at
improving filesystem read/write performance through multiple asynchronous
threads, if that is indeed a valid requirement.

[1] https://lore.kernel.org/lkml/20250313093005.13998-1-21cnbao at gmail.com/

>
> > have additional reclaim threads, such as for damon or
> > madv_pageout, etc.
> >
> > > >
> > > > so i am thinking sth as below
> > > >
> > > > page_io.c
> > > >
> > > > if (sync_device or zswap_enabled())
> > > >    schedule swap_writepage to a separate per-node thread
> > >
> > > I am not sure that's a good idea to mix a feature to solve different
> > > layers. That wouldn't be only swap problem. Such an parallelism under
> > > device  is common technique these days and it would help file IO cases.
> > >
> >
> > zswap and zram share the same needs, and handling this in page_io
> > can benefit both through common code. It is up to the callers to decide
> > the I/O model.
> >
> > I agree that "parallelism under the device" is a common technique,
> > but our case is different?the device achieves parallelism with
> > offload hardware, whereas we rely on CPUs, which can be scarce.
> > These threads may also preempt CPUs that are critically needed
> > by other non-compression tasks, and burst power consumption
> > can sometimes be difficult to control.
>
> That's general problem for common resources in the system and always
> trace-off domain in the workload areas. Eng folks has tried to tune
> them statically/dynamically depending on system behavior considering
> what they priorites.

Right, but haven't we yet taken on the task of tuning multi-threaded zram?

>
> >
> > > Furthermore, it would open the chance for zram to try compress
> > > multiple pages at once.
> >
> > We are already in this situation when multiple callers use zram simultaneously,
> > such as during direct reclaim or with a mounted filesystem.
> >
> > Of course, this allows multiple pages to be compressed simultaneously,
> > even if the user is single-threaded. However, determining when to enable
> > these threads and whether they will be effective is challenging, as it
> > depends on system load. For example, Qun-Wei's patch chose not to use
> > threads for direct reclaim as, I guess,  it might be harmful.
>
> Direct reclaim is already harmful and that's why VM has the logic
> to throttle writeback or other special logics for kswapd or direct
> reclaim path for th IO, which could be applied into the zram, too.

I'm not entirely sure that the existing congestion or throttled writeback
can automatically tune itself effectively with non-offload resources. For
offload resources, the number of queues and the bandwidth remain stable,
but for CPUs, they fluctuate based on changes in system workloads.

Thanks
Barry


From aweber.kernel at gmail.com  Thu Mar 13 13:39:05 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Thu, 13 Mar 2025 21:39:05 +0100
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <ef190ba8-a5c7-4a1a-90e6-2610de00e4ed@sirena.org.uk>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
 <20250313132036.GB3616286@google.com>
 <ef190ba8-a5c7-4a1a-90e6-2610de00e4ed@sirena.org.uk>
Message-ID: <f363c1ce-8612-476e-a5d5-c3cb358bf50a@gmail.com>

On 13.03.2025 14:25, Mark Brown wrote:
> On Thu, Mar 13, 2025 at 01:20:36PM +0000, Lee Jones wrote:
>> On Tue, 04 Mar 2025, Artur Weber wrote:
> 
>>> +	if (id != bcm590xx->pmu_id) {
>>> +		dev_err(bcm590xx->dev,
>>> +			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",
>>
>> Isn't it more likely that the H/W this is being executed on is
>> unsupported?  If so, say that instead.
> 
> Given that the compatibles are device specific the driver shouldn't be
> binding if the device is unsupported.

Yes, the intention here is just to make sure that the DT compatible and
hardware ID match. Unsupported hardware would not have a DT compatible.

Best regards
Artur


From dario.binacchi at amarulasolutions.com  Thu Mar 13 13:43:24 2025
From: dario.binacchi at amarulasolutions.com (Dario Binacchi)
Date: Thu, 13 Mar 2025 21:43:24 +0100
Subject: [PATCH] drm/mxsfb: fix missing rollback on failure in mxsfb_probe()
In-Reply-To: <468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>
References: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>
 <468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>
Message-ID: <CABGWkvqtj+05sdOuXg1WO99VNm9qdFgcYWEGuUPPZPoHZa6Dew@mail.gmail.com>

Hi All,

On Thu, Mar 13, 2025 at 3:40?PM Thomas Zimmermann <tzimmermann at suse.de> wrote:
>
> Hi
>
> Am 13.03.25 um 15:25 schrieb Luca Ceresoli:
> > When aperture_remove_all_conflicting_devices() fails, the current code
> > returns without going through the rollback actions at the end of the
> > function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
> > undone.
> >
> > Fix by using a goto statament, as done for the previous and following error
> > conditions.
> >
> > Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > ---
> > The offending commit is not yet merged into master, and even less in a
> > released kernel, so this does not need to go through stable.
> > ---
> >   drivers/gpu/drm/mxsfb/mxsfb_drv.c | 7 ++++---
> >   1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..b4273e678d26dbc3dee2014266d61470da4e8010 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > @@ -365,9 +365,10 @@ static int mxsfb_probe(struct platform_device *pdev)
> >        * located anywhere in RAM
> >        */
> >       ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
> > -     if (ret)
> > -             return dev_err_probe(&pdev->dev, ret,
> > -                                  "can't kick out existing framebuffers\n");
> > +     if (ret) {
> > +             dev_err_probe(&pdev->dev, ret, "can't kick out existing framebuffers\n");
> > +             goto err_unload;
> > +     }
>
> I must have missed that when I reviewed the patch. But this call should
> happen much earlier. right at the top of the probe function before
> drm_dev_alloc().

I had added the call to aperture_remove_all_conflicting_devices()
after mxsfb_load() to
keep the splash screen loaded by U-Boot. So, IMHO, it would be better
to add the
goto in case of an error rather than moving
aperture_remove_all_conflicting_devices()
to the beginning of the probe function.

Thanks and regards,
Dario

> Conflicting drivers need to be kicked out before
> setting up DRM. Could you please send a patch to move the call to the
> top? No extra cleanup would be required then.
>
> Best regards
> Thomas
>
> >
> >       ret = drm_dev_register(drm, 0);
> >       if (ret)
> >
> > ---
> > base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
> > change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34
> >
> > Best regards,
>
> --
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Frankenstrasse 146, 90461 Nuernberg, Germany
> GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
> HRB 36809 (AG Nuernberg)
>


-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi at amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info at amarulasolutions.com

www.amarulasolutions.com


From Frank.li at nxp.com  Thu Mar 13 13:45:26 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 16:45:26 -0400
Subject: [PATCH v11 04/11] PCI: dwc: Move devm_pci_alloc_host_bridge() to
 the beginning of dw_pcie_host_init()
In-Reply-To: <20250313192254.GA745234@bhelgaas>
References: <20250313-pci_fixup_addr-v11-4-01d2313502ab@nxp.com>
 <20250313192254.GA745234@bhelgaas>
Message-ID: <Z9ND5vARXpL8g1t/@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 02:22:54PM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 11:38:40AM -0400, Frank Li wrote:
> > Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init().
> > Since devm_pci_alloc_host_bridge() is common code that doesn't depend on
> > any DWC resource, moving it earlier improves code logic and readability.
> >
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> >  drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > index c57831902686e..52a441662cabe 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -452,6 +452,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> >
> >  	raw_spin_lock_init(&pp->lock);
> >
> > +	bridge = devm_pci_alloc_host_bridge(dev, 0);
> > +	if (!bridge)
> > +		return bridge;
>
> This returns NULL (0) where it previously returned -ENOMEM.  Callers
> interpret zero as "success", so I think it should stil return -ENOMEM.

It should be -ENOMEM. Sorry for that. Strange, not sure what happen when
I copy/past code.

Do you need respin it or you can fix it?

Frank

>
> I tentatively changed it back to -ENOMEM locally, let me know if
> that's wrong.
>
> > +	pp->bridge = bridge;
> > +
> >  	ret = dw_pcie_get_resources(pci);
> >  	if (ret)
> >  		return ret;
> > @@ -460,12 +466,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> >  	if (ret)
> >  		return ret;
> >
> > -	bridge = devm_pci_alloc_host_bridge(dev, 0);
> > -	if (!bridge)
> > -		return -ENOMEM;
> > -
> > -	pp->bridge = bridge;
> > -
> >  	/* Get the I/O range from DT */
> >  	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
> >  	if (win) {
> >
> > --
> > 2.34.1
> >


From acme at kernel.org  Thu Mar 13 13:47:27 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Thu, 13 Mar 2025 17:47:27 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9M9-YhDJg3NgiUy@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
Message-ID: <Z9NEX3j_1RUvaFI0@x1>

On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> Still building, but noticed this on x86_64:
> 
> 105: perf trace enum augmentation tests                              : FAILED!
> 106: perf trace BTF general tests                                    : FAILED!
> 107: perf trace exit race                                            : Ok
> 108: perf trace record and replay                                    : FAILED!
> 
> 
> The first doesn?t help that much with verbose mode, haven't checked if
> before this series it was failing :-\
> 
> root at x1:~# perf test -vvv 105
> 105: perf trace enum augmentation tests:
> --- start ---
> test child forked, pid 19411
> Checking if vmlinux exists
> Tracing syscall landlock_add_rule
> ---- end(-1) ----
> 105: perf trace enum augmentation tests                              : FAILED!
> root at x1:~#

So:

root at x1:~# perf trace -e landlock_add_rule perf test -w landlock
root at x1:~# 

But:

root at x1:~# perf trace perf test -w landlock |& grep landlock_add_rule
    26.120 ( 0.002 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7ffde75e2680, flags: 45) = -1 EINVAL (Invalid argument)
    26.124 ( 0.001 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffde75e2690, flags: 45) = -1 EINVAL (Invalid argument)
root at x1:~# 

-e is having some trouble, when no event is specified, then it works.

Something in the changes made to:

static int trace__parse_events_option(const struct option *opt, const char *str,
                                      int unset __maybe_unused)


- Arnaldo

More data:

root at x1:~# perf trace -vvv -e landlock_add_rule perf test -w landlock
Using CPUID GenuineIntel-6-BA-3
Opening: cpu/cycles/
------------------------------------------------------------
perf_event_attr:
  type                             0 (PERF_TYPE_HARDWARE)
  config                           0xa00000000 (cpu_atom/PERF_COUNT_HW_CPU_CYCLES/)
  disabled                         1
------------------------------------------------------------
sys_perf_event_open: pid 0  cpu -1  group_fd -1  flags 0x8 = 27
Opening: cpu/cycles/
------------------------------------------------------------
perf_event_attr:
  type                             0 (PERF_TYPE_HARDWARE)
  config                           0x400000000 (cpu_core/PERF_COUNT_HW_CPU_CYCLES/)
  disabled                         1
------------------------------------------------------------
sys_perf_event_open: pid 0  cpu -1  group_fd -1  flags 0x8 = 28
Opening: raw_syscalls:sys_enter
------------------------------------------------------------
perf_event_attr:
  type                             2 (PERF_TYPE_TRACEPOINT)
  size                             136
  config                           0x197 (raw_syscalls:sys_enter)
  { sample_period, sample_freq }   1
  sample_type                      IP|TID|TIME|ID|CPU|PERIOD|RAW
  read_format                      ID|LOST
  disabled                         1
  inherit                          1
  mmap                             1
  comm                             1
  enable_on_exec                   1
  task                             1
  sample_id_all                    1
  mmap2                            1
  comm_exec                        1
  ksymbol                          1
  bpf_event                        1
  { wakeup_events, wakeup_watermark } 1
------------------------------------------------------------
sys_perf_event_open: pid 19786  cpu 0  group_fd -1  flags 0x8 = 29
sys_perf_event_open: pid 19786  cpu 1  group_fd -1  flags 0x8 = 30
sys_perf_event_open: pid 19786  cpu 2  group_fd -1  flags 0x8 = 31
sys_perf_event_open: pid 19786  cpu 3  group_fd -1  flags 0x8 = 33
sys_perf_event_open: pid 19786  cpu 4  group_fd -1  flags 0x8 = 34
sys_perf_event_open: pid 19786  cpu 5  group_fd -1  flags 0x8 = 35
sys_perf_event_open: pid 19786  cpu 6  group_fd -1  flags 0x8 = 36
sys_perf_event_open: pid 19786  cpu 7  group_fd -1  flags 0x8 = 37
sys_perf_event_open: pid 19786  cpu 8  group_fd -1  flags 0x8 = 38
sys_perf_event_open: pid 19786  cpu 9  group_fd -1  flags 0x8 = 39
sys_perf_event_open: pid 19786  cpu 10  group_fd -1  flags 0x8 = 40
sys_perf_event_open: pid 19786  cpu 11  group_fd -1  flags 0x8 = 41
Opening: raw_syscalls:sys_exit
------------------------------------------------------------
perf_event_attr:
  type                             2 (PERF_TYPE_TRACEPOINT)
  size                             136
  config                           0x196 (raw_syscalls:sys_exit)
  { sample_period, sample_freq }   1
  sample_type                      IP|TID|TIME|ID|CPU|PERIOD|RAW
  read_format                      ID|LOST
  disabled                         1
  inherit                          1
  enable_on_exec                   1
  sample_id_all                    1
  { wakeup_events, wakeup_watermark } 1
------------------------------------------------------------
sys_perf_event_open: pid 19786  cpu 0  group_fd -1  flags 0x8 = 42
sys_perf_event_open: pid 19786  cpu 1  group_fd -1  flags 0x8 = 43
sys_perf_event_open: pid 19786  cpu 2  group_fd -1  flags 0x8 = 44
sys_perf_event_open: pid 19786  cpu 3  group_fd -1  flags 0x8 = 45
sys_perf_event_open: pid 19786  cpu 4  group_fd -1  flags 0x8 = 46
sys_perf_event_open: pid 19786  cpu 5  group_fd -1  flags 0x8 = 47
sys_perf_event_open: pid 19786  cpu 6  group_fd -1  flags 0x8 = 48
sys_perf_event_open: pid 19786  cpu 7  group_fd -1  flags 0x8 = 49
sys_perf_event_open: pid 19786  cpu 8  group_fd -1  flags 0x8 = 50
sys_perf_event_open: pid 19786  cpu 9  group_fd -1  flags 0x8 = 51
sys_perf_event_open: pid 19786  cpu 10  group_fd -1  flags 0x8 = 52
sys_perf_event_open: pid 19786  cpu 11  group_fd -1  flags 0x8 = 53
Opening: __augmented_syscalls__
------------------------------------------------------------
perf_event_attr:
  type                             1 (PERF_TYPE_SOFTWARE)
  size                             136
  config                           0xa (PERF_COUNT_SW_BPF_OUTPUT)
  { sample_period, sample_freq }   1
  sample_type                      IP|TID|TIME|ID|CPU|PERIOD|RAW
  read_format                      ID|LOST
  disabled                         1
  enable_on_exec                   1
  sample_id_all                    1
  { wakeup_events, wakeup_watermark } 1
------------------------------------------------------------
sys_perf_event_open: pid 19786  cpu 0  group_fd -1  flags 0x8 = 54
sys_perf_event_open: pid 19786  cpu 1  group_fd -1  flags 0x8 = 55
sys_perf_event_open: pid 19786  cpu 2  group_fd -1  flags 0x8 = 56
sys_perf_event_open: pid 19786  cpu 3  group_fd -1  flags 0x8 = 57
sys_perf_event_open: pid 19786  cpu 4  group_fd -1  flags 0x8 = 58
sys_perf_event_open: pid 19786  cpu 5  group_fd -1  flags 0x8 = 59
sys_perf_event_open: pid 19786  cpu 6  group_fd -1  flags 0x8 = 60
sys_perf_event_open: pid 19786  cpu 7  group_fd -1  flags 0x8 = 61
sys_perf_event_open: pid 19786  cpu 8  group_fd -1  flags 0x8 = 62
sys_perf_event_open: pid 19786  cpu 9  group_fd -1  flags 0x8 = 63
sys_perf_event_open: pid 19786  cpu 10  group_fd -1  flags 0x8 = 64
sys_perf_event_open: pid 19786  cpu 11  group_fd -1  flags 0x8 = 65
Problems reading syscall 156: 2 (No such file or directory)(_sysctl) information
Problems reading syscall 183: 2 (No such file or directory)(afs_syscall) information
Problems reading syscall 174: 2 (No such file or directory)(create_module) information
Problems reading syscall 214: 2 (No such file or directory)(epoll_ctl_old) information
Problems reading syscall 215: 2 (No such file or directory)(epoll_wait_old) information
Problems reading syscall 177: 2 (No such file or directory)(get_kernel_syms) information
Problems reading syscall 211: 2 (No such file or directory)(get_thread_area) information
Problems reading syscall 181: 2 (No such file or directory)(getpmsg) information
vmlinux BTF loaded
Problems reading syscall 212: 2 (No such file or directory)(lookup_dcookie) information
Problems reading syscall 180: 2 (No such file or directory)(nfsservctl) information
Problems reading syscall 182: 2 (No such file or directory)(putpmsg) information
Problems reading syscall 178: 2 (No such file or directory)(query_module) information
Problems reading syscall 185: 2 (No such file or directory)(security) information
Problems reading syscall 205: 2 (No such file or directory)(set_thread_area) information
Problems reading syscall 184: 2 (No such file or directory)(tuxcall) information
Problems reading syscall 134: 2 (No such file or directory)(uselib) information
Problems reading syscall 236: 2 (No such file or directory)(vserver) information
event qualifier tracepoint filter: id == 29098429
mmap size 528384B
libperf: mmap_per_cpu: nr cpu values 12 nr threads 1
libperf: idx 0: mmapping fd 29
<SNIP>
root at x1:~#

root at x1:~# cat /sys/kernel/tracing/events/syscalls/sys_enter_landlock_add_rule/id
1449
root at x1:~# perf trace -e landlock_add_rule perf test -w landlock
root at x1:~# strace -e landlock_add_rule perf test -w landlock
landlock_add_rule(11, LANDLOCK_RULE_PATH_BENEATH, {allowed_access=LANDLOCK_ACCESS_FS_READ_FILE, parent_fd=14}, 0x2d) = -1 EINVAL (Invalid argument)
landlock_add_rule(11, LANDLOCK_RULE_NET_PORT, {allowed_access=LANDLOCK_ACCESS_NET_CONNECT_TCP, port=19}, 0x2d) = -1 EINVAL (Invalid argument)
+++ exited with 0 +++
root at x1:~# 

root at x1:~# vim /tmp/build/perf-tools-next/trace/beauty/generated/syscalltbl.c
<SNIP>
static const char *const syscall_num_to_name_EM_X86_64[] = {
	[0] = "read",
	[1] = "write",
	[2] = "open",
<SNIP>
	[442] = "mount_setattr",
	[443] = "quotactl_fd",
	[444] = "landlock_create_ruleset",
	[445] = "landlock_add_rule",
	[446] = "landlock_restrict_self",
	[447] = "memfd_secret",
	[448] = "process_mrelease",
	[449] = "futex_waitv",
	[450] = "set_mempolicy_home_node",
<SNIP>
};
static const uint16_t syscall_sorted_names_EM_X86_64[] = {
	156,	/* _sysctl */
	43,	/* accept */
	288,	/* accept4 */
<SNIP>
	246,	/* kexec_load */
	250,	/* keyctl */
	62,	/* kill */
	445,	/* landlock_add_rule */
	444,	/* landlock_create_ruleset */
	446,	/* landlock_restrict_self */
	94,	/* lchown */
	192,	/* lgetxattr */
<SNIP>
};

<SNIP>

#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
       {
	      .num_to_name = syscall_num_to_name_EM_386,
	      .sorted_names = syscall_sorted_names_EM_386,
	      .e_machine = EM_386,
	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_EM_386),
	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_EM_386),
       },
       {
	      .num_to_name = syscall_num_to_name_EM_X86_64,
	      .sorted_names = syscall_sorted_names_EM_X86_64,
	      .e_machine = EM_X86_64,
	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_EM_X86_64),
	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_EM_X86_64),
       },
#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)

<SNIP>


From aweber.kernel at gmail.com  Thu Mar 13 13:49:30 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Thu, 13 Mar 2025 21:49:30 +0100
Subject: [PATCH v6 00/10] mfd: bcm590xx: Add support for BCM59054
In-Reply-To: <20250313132136.GC3616286@google.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250313132136.GC3616286@google.com>
Message-ID: <3a235d3c-0d23-4b19-a286-637e710b534e@gmail.com>

On 13.03.2025 14:21, Lee Jones wrote:
> 
> Besides my one comment, the MFD side looks okay.
> 
> So you still need ACKs from Mark and to rework Rob's suggestion.
> 

As far as I can tell, Rob retracted his suggestion and left his
Reviewed-By tag[1].

[1] https://lore.kernel.org/lkml/CAL_Jsq+Qsu-6Z72uXYKwc62idq2K169S1t0nUrrgNOyezgfYsA at mail.gmail.com/

Best regards
Artur


From dlechner at baylibre.com  Thu Mar 13 14:17:45 2025
From: dlechner at baylibre.com (David Lechner)
Date: Thu, 13 Mar 2025 16:17:45 -0500
Subject: [PATCH] ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX
In-Reply-To: <CAMRc=Mc7Xa58J55_kenkr2OA=ho6YH_gENOFEvAiA+q+p54dDQ@mail.gmail.com>
References: <20240401-da850-fix-select-da8xx-v1-1-a348ab91448f@baylibre.com>
 <CAMRc=Mc7Xa58J55_kenkr2OA=ho6YH_gENOFEvAiA+q+p54dDQ@mail.gmail.com>
Message-ID: <4866908a-2e93-4d19-aef3-5203e002a8cf@baylibre.com>

On 4/2/24 3:47 AM, Bartosz Golaszewski wrote:
> On Mon, Apr 1, 2024 at 5:10?PM David Lechner <dlechner at baylibre.com> wrote:
>>
>> Chips in the DA850 family need to have ARCH_DAVINCI_DA8XX to be selected
>> in order to enable some peripheral drivers.
>>
>> This was accidentally removed in a previous commit.
>>
>> Fixes: dec85a95167a ("ARM: davinci: clean up platform support")
>> Signed-off-by: David Lechner <dlechner at baylibre.com>
>> ---
>>  arch/arm/mach-davinci/Kconfig | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
>> index 2a8a9fe46586..3fa15f342240 100644
>> --- a/arch/arm/mach-davinci/Kconfig
>> +++ b/arch/arm/mach-davinci/Kconfig
>> @@ -27,6 +27,7 @@ config ARCH_DAVINCI_DA830
>>
>>  config ARCH_DAVINCI_DA850
>>         bool "DA850/OMAP-L138/AM18x based system"
>> +       select ARCH_DAVINCI_DA8XX
>>         select DAVINCI_CP_INTC
>>
>>  config ARCH_DAVINCI_DA8XX
>>
>> ---
>> base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
>> change-id: 20240401-da850-fix-select-da8xx-989725eec11f
> 
> Acked-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Hi Bartosz, here's an old one that never got picked up and I never got around
to resending. Can you pick it up along with the other davinci stuff you are
doing this cycle?


From helgaas at kernel.org  Thu Mar 13 14:25:55 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 13 Mar 2025 16:25:55 -0500
Subject: [PATCH v11 04/11] PCI: dwc: Move devm_pci_alloc_host_bridge() to
 the beginning of dw_pcie_host_init()
In-Reply-To: <Z9ND5vARXpL8g1t/@lizhi-Precision-Tower-5810>
Message-ID: <20250313212555.GA755531@bhelgaas>

On Thu, Mar 13, 2025 at 04:45:26PM -0400, Frank Li wrote:
> On Thu, Mar 13, 2025 at 02:22:54PM -0500, Bjorn Helgaas wrote:
> > On Thu, Mar 13, 2025 at 11:38:40AM -0400, Frank Li wrote:
> > > Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init().
> > > Since devm_pci_alloc_host_bridge() is common code that doesn't depend on
> > > any DWC resource, moving it earlier improves code logic and readability.
> > >
> > > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > > ---
> > >  drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
> > >  1 file changed, 6 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > index c57831902686e..52a441662cabe 100644
> > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -452,6 +452,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> > >
> > >  	raw_spin_lock_init(&pp->lock);
> > >
> > > +	bridge = devm_pci_alloc_host_bridge(dev, 0);
> > > +	if (!bridge)
> > > +		return bridge;
> >
> > This returns NULL (0) where it previously returned -ENOMEM.  Callers
> > interpret zero as "success", so I think it should stil return -ENOMEM.
> 
> It should be -ENOMEM. Sorry for that. Strange, not sure what happen when
> I copy/past code.
> 
> Do you need respin it or you can fix it?

I fixed it locally.  But you should fix it, too, in case we do another
spin for other reasons.

> > I tentatively changed it back to -ENOMEM locally, let me know if
> > that's wrong.
> >
> > > +	pp->bridge = bridge;
> > > +


From will at kernel.org  Thu Mar 13 14:56:23 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 21:56:23 +0000
Subject: [PATCH v2 2/4] arm64/sysreg: Enforce whole word match for
 open/close tokens
In-Reply-To: <20250115162600.2153226-3-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-3-james.clark@linaro.org>
Message-ID: <20250313215622.GA8101@willie-the-truck>

On Wed, Jan 15, 2025 at 04:25:56PM +0000, James Clark wrote:
> Opening and closing tokens can also match on words with common prefixes
> like "Endsysreg" vs "EndsysregFields". This could potentially make the
> script go wrong in weird ways so make it fall through to the fatal
> unhandled statement catcher if it doesn't fully match the current
> block.
> 
> Closing ones also get expect_fields(1) to ensure nothing other than
> whitespace follows.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  arch/arm64/tools/gen-sysreg.awk | 31 +++++++++++++++++--------------
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
> index 1a2afc9fdd42..f2a1732cb1f6 100755
> --- a/arch/arm64/tools/gen-sysreg.awk
> +++ b/arch/arm64/tools/gen-sysreg.awk
> @@ -111,7 +111,7 @@ END {
>  /^$/ { next }
>  /^[\t ]*#/ { next }
>  
> -/^SysregFields/ && block_current() == "Root" {
> +$1 == "SysregFields" && block_current() == "Root" {

Stylistic nit, but could you just do:

	/^SysregFields$/ && block_current() == "Root" {

instead? That way the diff is smaller (well, same number of lines) and
you avoid the ugly $1.

But I'm not an Orc, so who knows...

Will


From will at kernel.org  Thu Mar 13 14:56:54 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 21:56:54 +0000
Subject: [PATCH v2 1/4] arm64/sysreg: Fix unbalanced closing block
In-Reply-To: <20250115162600.2153226-2-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-2-james.clark@linaro.org>
Message-ID: <20250313215652.GB8101@willie-the-truck>

On Wed, Jan 15, 2025 at 04:25:55PM +0000, James Clark wrote:
> This is a sysreg block so close it with one. This doesn't make a
> difference to the output because the script only matches on the
> beginning of the word to close blocks which is correct by coincidence
> here.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  arch/arm64/tools/sysreg | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
> index 762ee084b37c..bbe7df69da9c 100644
> --- a/arch/arm64/tools/sysreg
> +++ b/arch/arm64/tools/sysreg
> @@ -2074,7 +2074,7 @@ EndEnum
>  Res0	4:2
>  Field	1	ExTRE
>  Field	0	E0TRE
> -EndSysregFields
> +EndSysreg
>  
>  Sysreg	SMPRI_EL1	3	0	1	2	4
>  Res0	63:4
> -- 
> 2.34.1

Acked-by: Will Deacon <will at kernel.org>

Will


From will at kernel.org  Thu Mar 13 14:58:41 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 21:58:41 +0000
Subject: [PATCH v2 3/4] arm64/sysreg: Sort sysreg by encoding
In-Reply-To: <20250115162600.2153226-4-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-4-james.clark@linaro.org>
Message-ID: <20250313215840.GC8101@willie-the-truck>

On Wed, Jan 15, 2025 at 04:25:57PM +0000, James Clark wrote:
> It's mostly been sorted by sysreg encoding, but not 100%. Sort it so
> new entries can be added without wondering where to put them.
> 
> The following python script was used to sort, keeping the top level
> SysregFields and comments next to their current Sysreg entries by
> splitting on "EndSysreg":
> 
>   # cat arch/arm64/tools/sysreg | python3 sort.py > sorted-sysreg
>   import sys, re
>   def key(block):
>           reg = r"\w+\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)"
>           match = re.search(reg, block)
>           sort_val = ''.join(f"{int(n):02d}" for n in match.groups())
>           return (sort_val, block)
>   sysreg = sys.stdin.read().split("\nEndSysreg\n")[:-1]
>   sysreg = sorted(sysreg, key=key)
>   print("\nEndSysreg\n".join(sysreg) + "\nEndSysreg")
> 
> Tested by diffing sorted outputs:
> 
>   $ diff <(sort arch/arm64/include/generated/asm/sysreg-defs.h)  \
>          <(sort before-sysreg-defs.h) -s
> 
>   Files /dev/fd/63 and /dev/fd/62 are identical
> 
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  arch/arm64/tools/sysreg | 1006 +++++++++++++++++++--------------------
>  1 file changed, 503 insertions(+), 503 deletions(-)

This looks like unnecessary pain for backporting...

What do we gain from sorting this?

Will


From helgaas at kernel.org  Thu Mar 13 15:04:50 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 13 Mar 2025 17:04:50 -0500
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250313-pci_fixup_addr-v11-6-01d2313502ab@nxp.com>
Message-ID: <20250313220450.GA755590@bhelgaas>

On Thu, Mar 13, 2025 at 11:38:42AM -0400, Frank Li wrote:
> The 'ranges' property at PCI controller parent bus can indicate address
> translation information. Most system's bus fabric use 1:1 map between input
> and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.

I think you've used reg["addr_space"] to get the offset for Endpoints
forever.

I just noticed that through v9, you used 'ranges' to get the offset
for the Root Complex (with "Add parent_bus_offset to resource_entry"),
and I think v10 switched to use reg["config"] instead.

I think I originally proposed the idea of "Add parent_bus_offset to
resource_entry" patch, but I think it turned out to be kind of an ugly
approach.

Anyway, IIUC this v11 patch actually uses reg["config"] to compute the
offset, not 'ranges', so we should probably update the subject and
commit log to reflect that, and maybe remove the now-unused bits of
the devicetree example.

I do worry a little bit about the assumption that the offset of
reg["config"] is the same as the offset of the other pieces.  The main
place we use the offset on RCs is for the ATU, and isn't the ATU in
the MemSpace area at 0x8000_0000 below?

It's great that in this case the 0x7ff0_0000 to 0x8ff0_0000 "config"
offset is the same as the 0x7000_0000 to 0x8000_0000 MemSpace offset,
but I don't know that this is guaranteed for all designs.

v9:
  [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
    https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-3-3c4bb506f665 at nxp.com
  [PATCH v9 5/7] PCI: dwc: ep: Add parent_bus_addr for outbound window
    https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-5-3c4bb506f665 at nxp.com

v10:
  [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to get rid of cpu_addr_fixup() callback
    https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-5-409dafc950d1 at nxp.com
  [PATCH v10 06/10] PCI: dwc: ep: Add parent_bus_addr for outbound window
    https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-6-409dafc950d1 at nxp.com

> See below diagram:
> 
>             ???????????                    ??????????????
>  ???????    ?         ? IA: 0x8ff8_0000    ?            ?
>  ? CPU ??????   ?????????????????????????  ? PCI        ?
>  ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
>   CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
> 0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
>             ?      ?  ?             ?   ?  ?            ?   PCI Addr
> 0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
>             ?         ?             ?      ?            ?    0
> 0x7000_0000??????????????????????   ?      ?            ?
>             ???????????         ?   ???????? CfgSpace  ???????????????
>              BUS Fabric         ?          ?            ?    0
>                                 ?          ?            ?
>                                 ???????????? MemSpace  ???????????????
>                         IA: 0x8000_0000    ?            ?  0x8000_0000
>                                            ??????????????
> 
> bus at 5f000000 {
> 	compatible = "simple-bus";
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 	ranges = <0x80000000 0x0 0x70000000 0x10000000>;
> 
> 	pcie at 5f010000 {
> 		compatible = "fsl,imx8q-pcie";
> 		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> 		reg-names = "dbi", "config";
> 		#address-cells = <3>;
> 		#size-cells = <2>;
> 		device_type = "pci";
> 		bus-range = <0x00 0xff>;
> 		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> 			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
> 	...
> 	};
> };
> 
> Term Intermediate address (IA) here means the address just before PCIe
> controller. After ATU use this IA instead CPU address, cpu_addr_fixup() can
> be removed.
> 
> Use reg-name "config" to detect parent_bus_addr_offset. Suppose the offset
> is the same for all kinds of address translation.
> 
> Just set parent_bus_offset, but doesn't use it, so no functional change
> intended yet.

> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -474,6 +474,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  		pp->io_base = pci_pio_to_address(win->res->start);
>  	}
>  
> +	/*
> +	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
> +	 * so have to call dw_pcie_init_parent_bus_offset() after init
> +	 * pp->io_base.
> +	 */
> +	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
> +	if (ret)
> +		return ret;
> +
>  	/* Set default bus ops */
>  	bridge->ops = &dw_pcie_ops;
>  	bridge->child_ops = &dw_child_pcie_ops;
> 
> -- 
> 2.34.1
> 


From akpm at linux-foundation.org  Thu Mar 13 15:05:05 2025
From: akpm at linux-foundation.org (Andrew Morton)
Date: Thu, 13 Mar 2025 15:05:05 -0700
Subject: [PATCH v4 00/14] Add support for suppressing warning backtraces
In-Reply-To: <c8287bde-fa1c-4113-af22-4701d40d386e@roeck-us.net>
References: <20250313114329.284104-1-acarmina@redhat.com>
	<202503131016.5DCEAEC945@keescook>
	<20250313-abiding-vivid-robin-159dfa@houat>
	<c8287bde-fa1c-4113-af22-4701d40d386e@roeck-us.net>
Message-ID: <20250313150505.cf1568bf7197a52a8ab302e6@linux-foundation.org>

On Thu, 13 Mar 2025 11:31:12 -0700 Guenter Roeck <linux at roeck-us.net> wrote:

> On Thu, Mar 13, 2025 at 06:24:25PM +0100, Maxime Ripard wrote:
> > > 
> > > Yeah, as with my prior review, I'm a fan of this. It makes a bunch of my
> > > very noisy tests much easier to deal with.
> > 
> > And for the record, we're also affected by this in DRM and would very
> > much like to get it merged in one shape or another.
> > 
> 
> I was unable to get maintainers of major architectures interested enough
> to provide feedback, and did not see a path forward. Maybe Alessandro
> has more success than me.

I'll put them into mm.git, to advance things a bit.

If someone wants to merge via a different tree, please speak up.

Hopefully the various arch maintainers will review at least their parts
of the series.



From will at kernel.org  Thu Mar 13 15:08:36 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 22:08:36 +0000
Subject: [BUG] ARM64 regression: NULL pointer dereference in
 arm_smccc_version_init+0x90/0x1ac
In-Reply-To: <Z6TqBQKSILZUnYbJ@NH27D9T0LF>
References: <Z5tuaxgDyFJPAvR0@J2N7QTR9R3>
 <Z5uTCnhfKo5D-_bV@NH27D9T0LF>
 <20250131124103.GA29766@willie-the-truck>
 <Z5zWMU4M_L5k6kII@J2N7QTR9R3>
 <20250204100014.GA777@willie-the-truck>
 <Z6OWxUFxkK9plrm0@NH27D9T0LF>
 <20250206131154.GD3204@willie-the-truck>
 <Z6TqBQKSILZUnYbJ@NH27D9T0LF>
Message-ID: <20250313220835.GD8101@willie-the-truck>

On Thu, Feb 06, 2025 at 05:57:41PM +0100, Emanuele Rocca wrote:
> On 2025-02-06 01:11, Will Deacon wrote:
> > In your screenshot, x6 looks like it's retained its poison value, but
> > that was the register being corrupted in the initial report. Maybe you
> > could share the diff you made?
> 
> Sure, please see [1]. A kernel built with that patch crashes and all
> registers retain their poison values.

Okey doke, at least it sounds like the firmware isn't taking advantage
of the broken spec, then.

In any case, I think the right way forward here is to use the
out-of-line 1.2 helpers whenever we can (the spectre mitigations can
stay as they are).

Will


From heiko at sntech.de  Thu Mar 13 15:14:15 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 13 Mar 2025 23:14:15 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250313071031.1840032-1-amadeus@jmu.edu.cn>
References: <7779050.EvYhyI6sBW@phil> <20250313071031.1840032-1-amadeus@jmu.edu.cn>
Message-ID: <1819496.VLH7GnMWUR@phil>

Hi,

Am Donnerstag, 13. M?rz 2025, 08:10:31 MEZ schrieb Chukun Pan:
> Hi,
> 
> > so yes of course the pinctrl needs to be default - simply because
> > that's the only pinctrl state mainline supports.
> 
> > But judging by the fact that you're discussing working vs. non-working
> > below, can you please check if we should drop the patch for 6.15 till
> > that is solved?
> 
> I suggest dropping this patch first, I will send v2
> when this issue is solved.

I've dropped the patch now.


Heiko




From alyssa at rosenzweig.io  Thu Mar 13 15:18:10 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Thu, 13 Mar 2025 18:18:10 -0400
Subject: [PATCH v2] drm: Add UAPI for the Asahi driver
Message-ID: <20250313-agx-uapi-v2-1-59cc53a59ea3@rosenzweig.io>

This adds the UAPI for the Asahi driver targeting the GPU in the Apple
M1 and M2 series systems on chip. The UAPI design is based on other
modern Vulkan-capable drivers, including Xe and Panthor. Memory
management is based on explicit VM management. Synchronization is
exclusively explicit sync.

This UAPI is validated against our open source Mesa stack, which is
fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
VM_BIND mechanism.

This patch adds the standalone UAPI header. It is implemented by an open
source DRM driver written in Rust. We fully intend to upstream this
driver when possible. However, as a production graphics driver, it
depends on a significant number of Rust abstractions that will take a
long time to upstream. In the mean time, our userspace is upstream in
Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
yet reviewed and merged in the upstream kernel. Although we ship a
patched Mesa in Fedora Asahi Remix, any containers shipping upstream
Mesa builds are broken for our users, including upstream Flatpak and
Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
and virglrenderer, which complicates bisects.

The intention in sending out this patch is for this UAPI to be
thoroughly reviewed. Once we as the DRM community are satisfied with the
UAPI, this header lands signifying that the UAPI is stable and must only
be evolved in backwards-compatible ways; it will be the UAPI implemented
in the DRM driver that eventually lands upstream. That promise lets us
enable upstream Mesa, solving all these issues while the upstream Rust
abstractions are developed.

https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v2 contains
the DRM driver implementing this proposed UAPI.

https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains
the Mesa patches to implement this proposed UAPI. It is mirrored at
https://github.com/alyssarosenzweig/mesa/tree/agx-uapi-v2 to allow
continued review during upcoming gitlab.freedesktop.org downtime.

That Linux and Mesa branch together give a complete graphics/compute
stack on top of this UAPI.

Co-developed-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
Changes in v2:
- Flatten submits. Previously, the submit ioctl pointed to an array of
  command structures, which each pointed to separate payload structures,
  which pointed to attachment structures. This is a lot of indirection,
  which complicates greatly virtgpu. In the new approach, the submit
  ioctl points to a single contiguous blob of plain-old-data, no CPU
  pointers, copied from userspace in one go and suitable as virtgpu wire
  protocol.
- Remove vm_page_size, userspace has to hardcode it anyway.
- Turn random #defines into enums for better kernel doc, etc.
- Improve comments, particularly around barriers[].
- Rename various flags/fields to better match canonical names when known
  (a lot of the names are pulled from the drivers/gpu/drm/imagination,
  naturally).
- Drop unnecessary encoder_id, cmd_id handles.
- Fix padding in submit ioctl (thanks Ryan).
- Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io
---
 Documentation/gpu/driver-uapi.rst |    5 +
 MAINTAINERS                       |    1 +
 include/uapi/drm/asahi_drm.h      | 1194 +++++++++++++++++++++++++++++++++++++
 3 files changed, 1200 insertions(+)

diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
--- a/Documentation/gpu/driver-uapi.rst
+++ b/Documentation/gpu/driver-uapi.rst
@@ -27,3 +27,8 @@ drm/xe uAPI
 ===========
 
 .. kernel-doc:: include/uapi/drm/xe_drm.h
+
+drm/asahi uAPI
+================
+
+.. kernel-doc:: include/uapi/drm/asahi_drm.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2256,6 +2256,7 @@ F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
 F:	include/linux/soc/apple/*
+F:	include/uapi/drm/asahi_drm.h
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson at axis.com>
diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
new file mode 100644
index 0000000000000000000000000000000000000000..951fe81866c90d8fca66456c113e618713130bac
--- /dev/null
+++ b/include/uapi/drm/asahi_drm.h
@@ -0,0 +1,1194 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) The Asahi Linux Contributors
+ * Copyright (C) 2018-2023 Collabora Ltd.
+ * Copyright (C) 2014-2018 Broadcom
+ */
+#ifndef _ASAHI_DRM_H_
+#define _ASAHI_DRM_H_
+
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * DOC: Introduction to the Asahi UAPI
+ *
+ * This documentation describes the Asahi IOCTLs.
+ *
+ * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
+ * from Panthor):
+ *
+ * - Structures must be aligned on 64-bit/8-byte. If the object is not
+ *   naturally aligned, a padding field must be added.
+ * - Fields must be explicitly aligned to their natural type alignment with
+ *   pad[0..N] fields.
+ * - All padding fields will be checked by the driver to make sure they are
+ *   zeroed.
+ * - Flags can be added, but not removed/replaced.
+ * - New fields can be added to the main structures (the structures
+ *   directly passed to the ioctl). Those fields can be added at the end of
+ *   the structure, or replace existing padding fields. Any new field being
+ *   added must preserve the behavior that existed before those fields were
+ *   added when a value of zero is passed.
+ * - New fields can be added to indirect objects (objects pointed by the
+ *   main structure), iff those objects are passed a size to reflect the
+ *   size known by the userspace driver (see
+ *   drm_asahi_command::cmd_buffer_size).
+ * - If the kernel driver is too old to know some fields, those will be
+ *   ignored if zero, and otherwise rejected (and so will be zero on output).
+ * - If userspace is too old to know some fields, those will be zeroed
+ *   (input) before the structure is parsed by the kernel driver.
+ * - Each new flag/field addition must come with a driver version update so
+ *   the userspace driver doesn't have to trial and error to know which
+ *   flags are supported.
+ * - Structures should not contain unions, as this would defeat the
+ *   extensibility of such structures.
+ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
+ *   at the end of the drm_asahi_ioctl_id enum.
+ */
+
+/**
+ * enum drm_asahi_ioctl_id - IOCTL IDs
+ *
+ * Place new ioctls at the end, don't re-order, don't replace or remove entries.
+ *
+ * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
+ * definitions instead.
+ */
+enum drm_asahi_ioctl_id {
+	/** @DRM_ASAHI_GET_PARAMS: Query device properties. */
+	DRM_ASAHI_GET_PARAMS = 0,
+
+	/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
+	DRM_ASAHI_VM_CREATE,
+
+	/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
+	DRM_ASAHI_VM_DESTROY,
+
+	/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
+	DRM_ASAHI_GEM_CREATE,
+
+	/**
+	 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
+	 * given GEM handle.
+	 */
+	DRM_ASAHI_GEM_MMAP_OFFSET,
+
+	/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
+	DRM_ASAHI_GEM_BIND,
+
+	/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
+	DRM_ASAHI_QUEUE_CREATE,
+
+	/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
+	DRM_ASAHI_QUEUE_DESTROY,
+
+	/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
+	DRM_ASAHI_SUBMIT,
+
+	/** @DRM_ASAHI_GET_TIME: Query device time. */
+	DRM_ASAHI_GET_TIME,
+
+	/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
+	DRM_ASAHI_GEM_BIND_OBJECT,
+};
+
+#define DRM_ASAHI_MAX_CLUSTERS	64
+
+/**
+ * struct drm_asahi_params_global - Global parameters.
+ *
+ * This struct may be queried by drm_asahi_get_params.
+ */
+struct drm_asahi_params_global {
+	/** @features: Feature bits from drm_asahi_feature */
+	__u64 features;
+
+	/** @gpu_generation: GPU generation, e.g. 13 for G13G */
+	__u32 gpu_generation;
+
+	/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
+	__u32 gpu_variant;
+
+	/**
+	 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
+	 * 0x21 for 'C1'
+	 */
+	__u32 gpu_revision;
+
+	/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
+	__u32 chip_id;
+
+	/** @num_dies: Number of dies in the SoC */
+	__u32 num_dies;
+
+	/** @num_clusters_total: Number of GPU clusters (across all dies) */
+	__u32 num_clusters_total;
+
+	/**
+	 * @num_cores_per_cluster: Number of logical cores per cluster
+	 * (including inactive/nonexistent)
+	 */
+	__u32 num_cores_per_cluster;
+
+	/** @num_frags_per_cluster: Number of frags per cluster */
+	__u32 num_frags_per_cluster;
+
+	/** @num_gps_per_cluster: Number of GPs per cluster */
+	__u32 num_gps_per_cluster;
+
+	/** @max_power_mw: Maximum GPU power consumption */
+	__u32 max_power_mw;
+
+	/** @core_masks: Bitmask of present/enabled cores per cluster */
+	__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
+
+	/** @timer_frequency_hz: Clock frequency for timestamps */
+	__u64 timer_frequency_hz;
+
+	/** @min_frequency_khz: Minimum GPU core clock frequency */
+	__u32 min_frequency_khz;
+
+	/** @max_frequency_khz: Maximum GPU core clock frequency */
+	__u32 max_frequency_khz;
+
+	/** @vm_user_start: VM user range start VMA */
+	__u64 vm_user_start;
+
+	/** @vm_user_end: VM user range end VMA */
+	__u64 vm_user_end;
+
+	/**
+	 * @vm_kernel_min_size: Minimum kernel VMA window size within user
+	 * range
+	 */
+	__u64 vm_kernel_min_size;
+
+	/**
+	 * @max_commands_per_submission: Maximum number of supported commands
+	 * per submission
+	 */
+	__u32 max_commands_per_submission;
+
+	/**
+	 * @max_attachments: Maximum number of drm_asahi_attachment's per
+	 * command
+	 */
+	__u32 max_attachments;
+
+	/**
+	 * @firmware_version: GPU firmware version, as 4 integers
+	 */
+	__u32 firmware_version[4];
+
+	/**
+	 * @user_timestamp_frequency_hz: Timebase frequency for user timestamps
+	 */
+	__u64 user_timestamp_frequency_hz;
+};
+
+/**
+ * enum drm_asahi_feature - Feature bits
+ *
+ * This covers only features that userspace cannot infer from the architecture
+ * version. Most features don't need to be here.
+ */
+enum drm_asahi_feature {
+	/**
+	 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
+	 * loads of unmapped memory will return zero. Shader stores to unmapped
+	 * memory will be silently discarded. Note that only shader load/store
+	 * is affected. Other hardware units are not affected, notably including
+	 * texture sampling.
+	 */
+	DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
+};
+
+/**
+ * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
+ */
+struct drm_asahi_get_params {
+	/** @param_group: Parameter group to fetch (MBZ) */
+	__u32 param_group;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @pointer: User pointer to write parameter struct */
+	__u64 pointer;
+
+	/** @size: Size of user buffer, max size supported on return */
+	__u64 size;
+};
+
+/**
+ * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
+ */
+struct drm_asahi_vm_create {
+	/** @kernel_start: Start of the kernel-reserved address range */
+	__u64 kernel_start;
+
+	/** @kernel_end: End of the kernel-reserved address range */
+	__u64 kernel_end;
+
+	/** @vm_id: Returned VM ID */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
+ */
+struct drm_asahi_vm_destroy {
+	/** @vm_id: VM ID to be destroyed */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_gem_flags - Flags for GEM creation
+ */
+enum drm_asahi_gem_flags {
+	/**
+	 * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
+	 *
+	 * Map as writeback instead of write-combine. This optimizes for CPU
+	 * reads.
+	 */
+	DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
+
+	/**
+	 * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
+	 */
+	DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
+};
+
+/**
+ * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
+ */
+struct drm_asahi_gem_create {
+	/** @size: Size of the BO */
+	__u64 size;
+
+	/** @flags: Combination of drm_asahi_gem_flags flags. */
+	__u32 flags;
+
+	/**
+	 * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
+	 */
+	__u32 vm_id;
+
+	/** @handle: Returned GEM handle for the BO */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_gem_mmap_offset - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
+ */
+struct drm_asahi_gem_mmap_offset {
+	/** @handle: Handle for the object being mapped. */
+	__u32 handle;
+
+	/** @flags: Must be zero */
+	__u32 flags;
+
+	/** @offset: The fake offset to use for subsequent mmap call */
+	__u64 offset;
+};
+
+/**
+ * enum drm_asahi_bind_op - Bind operation
+ */
+enum drm_asahi_bind_op {
+	/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
+	DRM_ASAHI_BIND_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
+	DRM_ASAHI_BIND_OP_UNBIND = 1,
+
+	/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */
+	DRM_ASAHI_BIND_OP_UNBIND_ALL = 2,
+};
+
+/**
+ * enum drm_asahi_bind_flags - Flags for GEM binding
+ */
+enum drm_asahi_bind_flags {
+	/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
+	DRM_ASAHI_BIND_READ = (1L << 0),
+
+	/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
+	DRM_ASAHI_BIND_WRITE = (1L << 1),
+
+	/**
+	 * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
+	 * across the VA range.
+	 *
+	 * This is useful to fill a VA range with scratch pages or zero pages.
+	 * It is intended as a mechanism to accelerate sparse.
+	 */
+	DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
+};
+
+/**
+ * struct drm_asahi_gem_bind - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND
+ */
+struct drm_asahi_gem_bind {
+	/** @op: Bind operation (enum drm_asahi_bind_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/**
+	 * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
+	 */
+	__u64 range;
+
+	/** @addr: Address to bind to (BIND or UNBIND only) */
+	__u64 addr;
+};
+
+/**
+ * enum drm_asahi_bind_object_op - Special object bind operation
+ */
+enum drm_asahi_bind_object_op {
+	/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
+};
+
+/**
+ * enum drm_asahi_bind_object_flags - Special object bind flags
+ */
+enum drm_asahi_bind_object_flags {
+	/**
+	 * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
+	 * buffer.
+	 */
+	DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
+};
+
+/**
+ * struct drm_asahi_gem_bind_object - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
+ */
+struct drm_asahi_gem_bind_object {
+	/** @op: Bind operation (enum drm_asahi_bind_object_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_object_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on (MBZ currently) */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/** @range: Number of bytes to bind/unbind (BIND only) */
+	__u64 range;
+
+	/** @object_handle: Object handle (out for BIND, in for UNBIND) */
+	__u32 object_handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_cmd_type - Command type
+ */
+enum drm_asahi_cmd_type {
+	/**
+	 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
+	 * subqueue. Combined vertex and fragment operation.
+	 *
+	 * Followed by a @drm_asahi_cmd_render payload.
+	 */
+	DRM_ASAHI_CMD_RENDER = 0,
+
+	/**
+	 * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
+	 *
+	 * Followed by a @drm_asahi_cmd_compute payload.
+	 */
+	DRM_ASAHI_CMD_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
+	 * attachments for subsequent vertex shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
+
+	/**
+	 * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
+	 * attachments for subsequent fragment shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
+
+	/**
+	 * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
+	 * attachments for subsequent compute shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
+};
+
+/**
+ * enum drm_asahi_queue_cap - Queue capabilities
+ */
+enum drm_asahi_queue_cap {
+	/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
+	DRM_ASAHI_QUEUE_CAP_RENDER	= (1UL << DRM_ASAHI_CMD_RENDER),
+
+	/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
+	DRM_ASAHI_QUEUE_CAP_COMPUTE	= (1UL << DRM_ASAHI_CMD_COMPUTE),
+};
+
+/**
+ * struct drm_asahi_queue_create - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_CREATE
+ */
+struct drm_asahi_queue_create {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @vm_id: The ID of the VM this queue is bound to */
+	__u32 vm_id;
+
+	/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
+	__u32 queue_caps;
+
+	/** @priority: Queue priority, 0-3 */
+	__u32 priority;
+
+	/** @queue_id: The returned queue ID */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_queue_destroy - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_DESTROY
+ */
+struct drm_asahi_queue_destroy {
+	/** @queue_id: The queue ID to be destroyed */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_sync_type - Sync item type
+ */
+enum drm_asahi_sync_type {
+	/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
+	DRM_ASAHI_SYNC_SYNCOBJ = 0,
+
+	/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
+	DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
+};
+
+/**
+ * struct drm_asahi_sync - Sync item
+ */
+struct drm_asahi_sync {
+	/** @sync_type: One of drm_asahi_sync_type */
+	__u32 sync_type;
+
+	/** @handle: The sync object handle */
+	__u32 handle;
+
+	/** @timeline_value: Timeline value for timeline sync objects */
+	__u64 timeline_value;
+};
+
+/**
+ * enum drm_asahi_subqueue - Subqueue within a queue
+ */
+enum drm_asahi_subqueue {
+	/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */
+	DRM_ASAHI_SUBQUEUE_RENDER = 0,
+
+	/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */
+	DRM_ASAHI_SUBQUEUE_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2
+	 * for struct alignment
+	 */
+	DRM_ASAHI_SUBQUEUE_COUNT = 2,
+};
+
+/**
+ * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
+ *
+ * This special value may be passed in to drm_asahi_command::barriers[] to
+ * indicate that the respective subqueue should not wait on any previous work.
+ */
+#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
+
+/**
+ * struct drm_asahi_cmd_header - Top level command structure
+ */
+struct drm_asahi_cmd_header {
+	/** @cmd_type: One of drm_asahi_cmd_type */
+	__u16 cmd_type;
+
+	/**
+	 * @size: Size of this command, not including this header.
+	 *
+	 * For hardware commands, this enables extensibility of commands without
+	 * requiring extra command types.  Passing a command that is shorter
+	 * than expected is explicitly allowed for backwards-compatability.
+	 * Truncated fields will be zeroed.
+	 *
+	 * For the synthetic attachment setting commands, this implicitly
+	 * encodes the number of attachments. These commands take multiple
+	 * fixed-size @drm_asahi_attachment structures as their payload, so size
+	 * equals number of attachments * sizeof(struct drm_asahi_attachment).
+	 */
+	__u16 size;
+
+	/**
+	 * @barriers: Array of command indices per subqueue to wait on.
+	 *
+	 * Barriers are indices relative to the beginning of a given submit. A
+	 * barrier of 0 waits on commands submitted to the subqueue in previous
+	 * submit ioctls. A barrier of N waits on N previous commands on the
+	 * subqueue within the current submit ioctl. As a special case, passing
+	 * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the
+	 * subqueue.
+	 *
+	 * Examples:
+	 *
+	 *   (0, 0): This waits on all previous work.
+	 *
+	 *   (NONE, 0): This waits on previously submitted compute commands but
+	 *   does not wait on any render commands.
+	 *
+	 *   (1, NONE): This waits on the first render command in the submit.
+	 *   This only makes sense if there are multiple render commands in the
+	 *   same submit.
+	 *
+	 * Barriers only make sense for hardware commands. Synthetic software
+	 * commands to set attachments must pass (NONE, NONE) here.
+	 */
+	__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT];
+};
+
+/**
+ * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
+ */
+struct drm_asahi_submit {
+	/**
+	 * @in_syncs: An optional array of drm_asahi_sync to wait on before
+	 * starting this job.
+	 */
+	__u64 in_syncs;
+
+	/**
+	 * @out_syncs: An optional array of drm_asahi_sync objects to signal
+	 * upon completion.
+	 */
+	__u64 out_syncs;
+
+	/**
+	 * @cmdbuf: Pointer to the command buffer to submit.
+	 *
+	 * This is a flat command buffer. By design, it contains no CPU
+	 * pointers, which makes it suitable for a virtgpu wire protocol without
+	 * requiring any serializing/deserializing step.
+	 *
+	 * It consists of a series of commands. Each command begins with a
+	 * fixed-size @drm_asahi_cmd_header and is followed by a variable-length
+	 * payload according to the type and size in the header.
+	 */
+	__u64 cmdbuf;
+
+	/** @flags: Flags for command submission (MBZ) */
+	__u32 flags;
+
+	/** @queue_id: The queue ID to be submitted to */
+	__u32 queue_id;
+
+	/**
+	 * @in_sync_count: Number of sync objects to wait on before starting
+	 * this job.
+	 */
+	__u32 in_sync_count;
+
+	/**
+	 * @out_sync_count: Number of sync objects to signal upon completion of
+	 * this job.
+	 */
+	__u32 out_sync_count;
+
+	/** @cmdbuf_size: Command buffer size in bytes */
+	__u32 cmdbuf_size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_attachment - Describe an "attachment".
+ *
+ * Attachments are any memory written by shaders, notably including render
+ * target attachments written by the end-of-tile program. This is purely a hint
+ * about the accessed memory regions. It is optional to specify, which is
+ * fortunate as it cannot be specified precisely with bindless access anyway.
+ * But where possible, it's probably a good idea for userspace to include these
+ * hints, forwarded to the firmware.
+ */
+struct drm_asahi_attachment {
+	/** @pointer: Base address of the attachment */
+	__u64 pointer;
+
+	/** @size: Size of the attachment in bytes */
+	__u64 size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @flags: MBZ */
+	__u32 flags;
+};
+
+enum drm_asahi_render_flags {
+	/**
+	 * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
+	 * memory.
+	 */
+	DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1UL << 0),
+
+	/**
+	 * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
+	 * This must be set when clearing render targets.
+	 */
+	DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1UL << 1),
+
+	/**
+	 * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
+	 * cluster (on multicluster GPUs)
+	 *
+	 * This harms performance but can workaround certain sync/coherency
+	 * bugs, and therefore is useful for debugging.
+	 */
+	DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1UL << 2),
+
+	/**
+	 * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
+	 *
+	 * Graphics specifications contain two alternate formulas for depth
+	 * bias, a float formula used with floating-point depth buffers and an
+	 * integer formula using with unorm depth buffers. This flag specifies
+	 * that the integer formula should be used. If omitted, the float
+	 * formula is used instead.
+	 *
+	 * This corresponds to bit 18 of the relevant hardware control register,
+	 * so we match that here for efficiency.
+	 */
+	DRM_ASAHI_RENDER_DBIAS_IS_INT = (1UL << 18),
+};
+
+/**
+ * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
+ *
+ * These fields correspond directly to hardware registers in the ZLS (Z
+ * Load/Store) unit. Together, they configure a single depth or stencil buffer.
+ * Typically, load/store/partial will all use the same values. However, the
+ * hardware does not require this.
+ */
+struct drm_asahi_zls_buffer {
+	/** @load: Base address of the buffer to load at the start */
+	__u64 load;
+
+	/** @store: Base address of the buffer to store at the end */
+	__u64 store;
+
+	/**
+	 * @partial: Base address of the buffer to load and store during a
+	 * partial render operation.
+	 */
+	__u64 partial;
+
+	/**
+	 * @comp_load: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_load;
+
+	/**
+	 * @comp_store: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_store;
+
+	/**
+	 * @comp_partial: If the partial render buffer is compressed, address of
+	 * the compression metadata section.
+	 */
+	__u64 comp_partial;
+
+	/**
+	 * @load_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the load buffer.
+	 */
+	__u32 load_stride;
+
+	/**
+	 * @store_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the store buffer.
+	 */
+	__u32 store_stride;
+
+	/**
+	 * @partial_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the partial render buffer.
+	 */
+	__u32 partial_stride;
+
+	/**
+	 * @comp_load_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the compression metadata for loads.
+	 */
+	__u32 comp_load_stride;
+
+	/**
+	 * @comp_store_stride: If layered rendering is enabled, the number of
+	 * bytes between each layer of the compression metadata for stores.
+	 */
+	__u32 comp_store_stride;
+
+	/**
+	 * @comp_partial_stride: If layered rendering is enabled, the number of
+	 * bytes between each layer of the compression metadata for partial
+	 * renders.
+	 */
+	__u32 comp_partial_stride;
+};
+
+/**
+ * struct drm_asahi_timestamp - Describe a timestamp write.
+ *
+ * The firmware can optionally write the GPU timestamp at render pass
+ * granularities, but it needs to be mapped specially via
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
+ * write as a handle-offset pair, rather than a GPU address like normal.
+ */
+struct drm_asahi_timestamp {
+	/**
+	 * @handle: Handle of the timestamp buffer, or 0 to skip this
+	 * timestamp. If nonzero, this must equal the value returned in
+	 * drm_asahi_gem_bind_object::object_handle.
+	 */
+	__u32 handle;
+
+	/** @offset: Offset to write into the timestamp buffer */
+	__u32 offset;
+};
+
+/**
+ * struct drm_asahi_timestamps - Describe timestamp writes.
+ *
+ * Each operation that can be timestamped, can be timestamped at the start and
+ * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
+ * together into drm_asahi_timestamps.
+ */
+struct drm_asahi_timestamps {
+	/** @start: Timestamp recorded at the start of the operation */
+	struct drm_asahi_timestamp start;
+
+	/** @end: Timestamp recorded at the end of the operation */
+	struct drm_asahi_timestamp end;
+};
+
+/**
+ * struct drm_asahi_helper_program - Describe helper program configuration.
+ *
+ * The helper program is a compute-like kernel required for various hardware
+ * functionality. Its most important role is dynamically allocating
+ * scratch/stack memory for individual subgroups, by partitioning a static
+ * allocation shared for the whole device. It is supplied by userspace via
+ * drm_asahi_helper_program and internally dispatched by the hardware as needed.
+ */
+struct drm_asahi_helper_program {
+	/**
+	 * @binary: USC address to the helper program binary. This is a tagged
+	 * pointer with configuration in the bottom bits.
+	 */
+	__u32 binary;
+
+	/** @cfg: Configuration bits for the helper program. */
+	__u32 cfg;
+
+	/**
+	 * @data: Data passed to the helper program. This value is not
+	 * interpreted by the kernel, firmware, or hardware in any way. It is
+	 * simply a sideband for userspace, set with the submit ioctl and read
+	 * via special registers inside the helper program.
+	 *
+	 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
+	 * actual arguments, which presumably don't fit in 64-bits.
+	 */
+	__u64 data;
+};
+
+/**
+ * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
+ *
+ * The background and end-of-tile programs are dispatched by the hardware at the
+ * beginning and end of rendering. As the hardware "tilebuffer" is simply local
+ * memory, these programs are necessary to implement API-level render targets.
+ * The fragment-like background program is responsible for loading either the
+ * clear colour or the existing render target contents, while the compute-like
+ * end-of-tile program stores the tilebuffer contents to memory.
+ */
+struct drm_asahi_bg_eot {
+	/**
+	 * @usc: USC address of the hardware USC words binding resources
+	 * (including images and uniforms) and the program itself. Note this is
+	 * an additional layer of indirection compared to the helper program,
+	 * avoiding the need for a sideband for data. This is a tagged pointer
+	 * with additional configuration in the bottom bits.
+	 */
+	__u32 usc;
+
+	/**
+	 * @rsrc_spec: Resource specifier for the program. This is a packed
+	 * hardware data structure describing the required number of registers,
+	 * uniforms, bound textures, and bound samplers.
+	 */
+	__u32 rsrc_spec;
+};
+
+/**
+ * struct drm_asahi_cmd_render - Command to submit 3D
+ *
+ * This command submits a single render pass. The hardware control stream may
+ * include many draws and subpasses, but within the command, the framebuffer
+ * dimensions and attachments are fixed.
+ *
+ * The hardware requires the firmware to set a large number of Control Registers
+ * setting up state at render pass granularity before each command rendering 3D.
+ * The firmware bundles this state into data structures. Unfortunately, we
+ * cannot expose either any of that directly to userspace, because the
+ * kernel-firmware ABI is not stable. Although we can guarantee the firmware
+ * updates in tandem with the kernel, we cannot break old userspace when
+ * upgrading the firmware and kernel. Therefore, we need to abstract well the
+ * data structures to avoid tying our hands with future firmwares.
+ *
+ * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
+ * control registers, marshalled via the firmware interface.
+ *
+ * The framebuffer/tilebuffer dimensions are also specified here. In addition to
+ * being passed to the firmware/hardware, the kernel requires these dimensions
+ * to calculate various essential tiling-related data structures. It is
+ * unfortunate that our submits are heavier than on vendors with saner
+ * hardware-software interfaces. The upshot is all of this information is
+ * readily available to userspace with all current APIs.
+ *
+ * It looks odd - but it's not overly burdensome and it ensures we can remain
+ * compatible with old userspace.
+ */
+struct drm_asahi_cmd_render {
+	/** @flags: Combination of drm_asahi_render_flags flags. */
+	__u64 flags;
+
+	/**
+	 * @ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU address
+	 * to the beginning of the VDM control stream.
+	 *
+	 * We don't prefix the name with "VDM", since render commands have only
+	 * a VDM control stream.
+	 */
+	__u64 ctrl_stream_base;
+
+	/**
+	 * @usc_exec_base: USC_EXEC_BASE_TA and USC_EXEC_BASE_ISP register
+	 * value. GPU base address for all USC binaries (shaders) used in this
+	 * command. USC addresses are 32-bit relative to this 64-bit base.
+	 */
+	__u64 usc_exec_base;
+
+	/** @vertex_helper: Helper program used for the vertex shader */
+	struct drm_asahi_helper_program vertex_helper;
+
+	/** @fragment_helper: Helper program used for the fragment shader */
+	struct drm_asahi_helper_program fragment_helper;
+
+	/**
+	 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
+	 * array of scissor descriptors indexed in the render pass.
+	 */
+	__u64 isp_scissor_base;
+
+	/**
+	 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
+	 * array of depth bias values indexed in the render pass.
+	 */
+	__u64 isp_dbias_base;
+
+	/**
+	 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
+	 * array of occlusion query results written by the render pass.
+	 */
+	__u64 isp_oclqry_base;
+
+	/** @depth: Physical buffers backing the logical depth buffer */
+	struct drm_asahi_zls_buffer depth;
+
+	/** @stencil: Physical buffers backing the logical stencil buffer */
+	struct drm_asahi_zls_buffer stencil;
+
+	/** @zls_ctrl: ZLS_CTRL register value */
+	__u64 zls_ctrl;
+
+	/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
+	__u64 ppp_multisamplectl;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/** @ppp_ctrl: PPP_CTRL register value */
+	__u32 ppp_ctrl;
+
+	/** @width_px: Framebuffer width in pixels */
+	__u16 width_px;
+
+	/** @height_px: Framebuffer height in pixels */
+	__u16 height_px;
+
+	/** @layers: Number of layers in the framebuffer */
+	__u16 layers;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u16 sampler_count;
+
+	/** @utile_width_px: Width of a logical tilebuffer tile in pixels */
+	__u8 utile_width_px;
+
+	/** @utile_height_px: Height of a logical tilebuffer tile in pixels */
+	__u8 utile_height_px;
+
+	/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
+	__u8 samples;
+
+	/** @sample_size_B: # of bytes in the tilebuffer required per sample. */
+	__u8 sample_size_B;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/**
+	 * @isp_merge_upper_x: 32-bit float used in the
+	 * hardware triangle merging. Calculate as:
+	 *
+	 *	tan(60 deg) * width
+	 *
+	 * Making these values UAPI avoids requiring floating-point calculations
+	 * in the kernel in the hot path.
+	 */
+	__u32 isp_merge_upper_x;
+
+	/**
+	 * @isp_merge_upper_y: 32-bit float. Calculate as:
+	 *
+	 *	tan(60 deg) * height
+	 *
+	 * See @isp_merge_upper_x.
+	 */
+	__u32 isp_merge_upper_y;
+
+	/**
+	 * @bg: Background program ran at the start of each tile at the start of
+	 * the render pass.
+	 */
+	struct drm_asahi_bg_eot bg;
+
+	/**
+	 * @eot: End-of-tile program ran at the end of each tile at the end of
+	 * the render pass.
+	 */
+	struct drm_asahi_bg_eot eot;
+
+	/**
+	 * @partial_bg: Background program ran at the start of each tile when
+	 * resuming the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_bg;
+
+	/**
+	 * @partial_eot: End-of-tile program ran at the end of each tile when
+	 * pausing the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_eot;
+
+	/**
+	 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
+	 * depth buffer width/height, which is allowed to differ from the
+	 * framebuffer width/height.
+	 */
+	__u32 isp_zls_pixels;
+
+	/**
+	 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
+	 * buffer clear value, encoded in the depth buffer's format: either a
+	 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
+	 */
+	__u32 isp_bgobjdepth;
+
+	/**
+	 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
+	 * contain the stencil buffer clear value.
+	 */
+	__u32 isp_bgobjvals;
+
+	/** @ts_vtx: Timestamps for the vertex portion of the render */
+	struct drm_asahi_timestamps ts_vtx;
+
+	/** @ts_frag: Timestamps for the fragment portion of the render */
+	struct drm_asahi_timestamps ts_frag;
+};
+
+/**
+ * struct drm_asahi_cmd_compute - Command to submit compute
+ *
+ * This command submits a control stream consisting of compute dispatches. There
+ * is essentially no limit on how many compute dispatches may be included in a
+ * single compute command, although timestamping only occurs at command
+ * granularity.
+ */
+struct drm_asahi_cmd_compute {
+	/** @flags: MBZ */
+	__u64 flags;
+
+	/**
+	 * @ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU address
+	 * to the beginning of the CDM control stream.
+	 *
+	 * We don't prefix the name with "CDM", since render commands have only
+	 * a CDM control stream.
+	 */
+	__u64 ctrl_stream_base;
+
+	/**
+	 * @ctrl_stream_end: GPU base address to the end of the hardware control
+	 * stream. Note this only considers the first contiguous segment of the
+	 * control stream, as the stream might jump elsewhere.
+	 */
+	__u64 ctrl_stream_end;
+
+	/**
+	 * @usc_exec_base: USC_EXEC_BASE_CP register value. GPU Base address for
+	 * all USC binaries (shaders) used in this command. USC addresses are
+	 * 32-bit relative to this 64-bit base.
+	 */
+	__u64 usc_exec_base;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u32 sampler_count;
+
+	/** @helper: Helper program used for this compute shader */
+	struct drm_asahi_helper_program helper;
+
+	/** @ts: Timestamps for the compute command */
+	struct drm_asahi_timestamps ts;
+};
+
+/**
+ * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
+ */
+struct drm_asahi_get_time {
+	/** @flags: MBZ. */
+	__u64 flags;
+
+	/** @gpu_timestamp: On return, the current GPU timestamp */
+	__u64 gpu_timestamp;
+};
+
+/**
+ * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
+ * @__access: Access type. Must be R, W or RW.
+ * @__id: One of the DRM_ASAHI_xxx id.
+ * @__type: Suffix of the type being passed to the IOCTL.
+ *
+ * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
+ * values instead.
+ *
+ * Return: An IOCTL number to be passed to ioctl() from userspace.
+ */
+#define DRM_IOCTL_ASAHI(__access, __id, __type) \
+	DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
+			   struct drm_asahi_ ## __type)
+
+/* Note: this is an enum so that it can be resolved by Rust bindgen. */
+enum {
+	DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
+	DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
+	DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
+	DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
+	DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
+	DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
+	DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
+	DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
+	DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
+	DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
+	DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _ASAHI_DRM_H_ */

---
base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
change-id: 20250307-agx-uapi-930579437f19

Best regards,
-- 
Alyssa Rosenzweig <alyssa at rosenzweig.io>



From will at kernel.org  Thu Mar 13 15:22:54 2025
From: will at kernel.org (Will Deacon)
Date: Thu, 13 Mar 2025 22:22:54 +0000
Subject: [PATCH 0/3] perf/arm_cspmu: Add PMEVFILT2R support
In-Reply-To: <cover.1741190362.git.robin.murphy@arm.com>
References: <cover.1741190362.git.robin.murphy@arm.com>
Message-ID: <174190170500.714070.6303342038303900840.b4-ty@kernel.org>

On Wed, 05 Mar 2025 16:10:05 +0000, Robin Murphy wrote:
> This is part of something I'm working towards, but I figure it stands
> up on its own enough to be worth getting out early. Compile-tested
> only, but it's straightforward enough that I'm confident.
> 
> Cheers,
> Robin.
> 
> [...]

Applied to will (for-next/perf), thanks!

[1/3] perf/arm_cspmu: Move register definitons to header
      https://git.kernel.org/will/c/862f7ad4d7fd
[2/3] perf/arm_cspmu: Generalise event filtering
      https://git.kernel.org/will/c/6de0298a3925
[3/3] perf/arm_cspmu: Add PMEVFILT2R support
      https://git.kernel.org/will/c/a28f3cbfd11f

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev


From jacob.e.keller at intel.com  Thu Mar 13 15:32:42 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Thu, 13 Mar 2025 15:32:42 -0700
Subject: [PATCH net-next 1/3] stmmac: loongson: Remove surplus loop
In-Reply-To: <20250313161422.97174-3-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
 <20250313161422.97174-3-phasta@kernel.org>
Message-ID: <b34176d5-532a-4aca-a8e2-69c32fe996c1@intel.com>



On 3/13/2025 9:14 AM, Philipp Stanner wrote:
> loongson_dwmac_probe() contains a loop which doesn't have an effect,
> because it tries to call pcim_iomap_regions() with the same parameters
> several times. The break statement at the loop's end furthermore ensures
> that the loop only runs once anyways.
> 
> Remove the surplus loop.
> 
> Signed-off-by: Philipp Stanner <phasta at kernel.org>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
> Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
> Tested-by: Henry Chen <chenx97 at aosc.io>
> ---
>  .../net/ethernet/stmicro/stmmac/dwmac-loongson.c    | 13 ++++---------
>  1 file changed, 4 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 73a6715a93e6..e2959ac5c1ca 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -524,7 +524,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
>  	struct loongson_data *ld;
> -	int ret, i;
> +	int ret;
>  
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
> @@ -554,14 +554,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	pci_set_master(pdev);
>  
>  	/* Get the base address of device */
> -	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> -		if (pci_resource_len(pdev, i) == 0)
> -			continue;
> -		ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
> -		if (ret)
> -			goto err_disable_device;
> -		break;
> -	}

This nonsensical code has been here since the beginning of the Loongson
support in commit 30bba69d7db4 ("stmmac: pci: Add dwmac support for
Loongson")

Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>


From jacob.e.keller at intel.com  Thu Mar 13 15:33:19 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Thu, 13 Mar 2025 15:33:19 -0700
Subject: [PATCH net-next 2/3] stmmac: Remove pcim_* functions for driver
 detach
In-Reply-To: <20250313161422.97174-4-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
 <20250313161422.97174-4-phasta@kernel.org>
Message-ID: <89d99e2f-1189-42dc-8284-bab874820aa4@intel.com>



On 3/13/2025 9:14 AM, Philipp Stanner wrote:
> Functions prefixed with "pcim_" are managed devres functions which
> perform automatic cleanup once the driver unloads. It is, thus, not
> necessary to call any cleanup functions in remove() callbacks.
> 
> Remove the pcim_ cleanup function calls in the remove() callbacks.
> 
> Signed-off-by: Philipp Stanner <phasta at kernel.org>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
> Tested-by: Henry Chen <chenx97 at aosc.io>
> ---

Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>


From jacob.e.keller at intel.com  Thu Mar 13 15:34:03 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Thu, 13 Mar 2025 15:34:03 -0700
Subject: [PATCH net-next 3/3] stmmac: Replace deprecated PCI functions
In-Reply-To: <20250313161422.97174-5-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
 <20250313161422.97174-5-phasta@kernel.org>
Message-ID: <8979079d-4afe-407f-ab49-85246601fea2@intel.com>



On 3/13/2025 9:14 AM, Philipp Stanner wrote:
> From: Philipp Stanner <pstanner at redhat.com>
> 
> The PCI functions
>   - pcim_iomap_regions() and
>   - pcim_iomap_table()
> have been deprecated.
> 
> Replace them with their successor function, pcim_iomap_region().
> 
> Make variable declaration order at closeby places comply with reverse
> christmas tree order.
> 
> Signed-off-by: Philipp Stanner <pstanner at redhat.com>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
> Tested-by: Henry Chen <chenx97 at aosc.io>
> ---
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>


From akpm at linux-foundation.org  Thu Mar 13 15:47:57 2025
From: akpm at linux-foundation.org (Andrew Morton)
Date: Thu, 13 Mar 2025 15:47:57 -0700
Subject: [PATCH v13 00/11] Support page table check on PowerPC
In-Reply-To: <006ac081cf0e130426bcf0ef777bed346f6df002.camel@linux.ibm.com>
References: <20250211161404.850215-1-ajd@linux.ibm.com>
	<006ac081cf0e130426bcf0ef777bed346f6df002.camel@linux.ibm.com>
Message-ID: <20250313154757.79dc20b347a0bee16f4fbd10@linux-foundation.org>

On Thu, 13 Mar 2025 13:54:39 +1100 Andrew Donnellan <ajd at linux.ibm.com> wrote:

> On Wed, 2025-02-12 at 03:13 +1100, Andrew Donnellan wrote:
> > Support page table check on all PowerPC platforms. This works by
> > serialising assignments, reassignments and clears of page table
> > entries at each level in order to ensure that anonymous mappings
> > have at most one writable consumer, and likewise that file-backed
> > mappings are not simultaneously also anonymous mappings.
> > 
> > In order to support this infrastructure, a number of stubs must be
> > defined for all powerpc platforms. Additionally, seperate
> > set_pte_at()
> > and set_pte_at_unchecked(), to allow for internal, uninstrumented
> > mappings.
> 
> Talking to Maddy about this off-list - given that this series touches
> on generic code and several architectures, would it be best to take it
> through the mm tree rather than powerpc?

Sure, I can do that.

Are the rest of the ppc team OK with these changes?  I'm not seeing
much acking from the usual suspects?


From jacob.e.keller at intel.com  Thu Mar 13 15:48:39 2025
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Thu, 13 Mar 2025 15:48:39 -0700
Subject: [PATCH net-next v2 0/9] net: stmmac: remove unnecessary
 of_get_phy_mode() calls
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <73e82f1f-e0cc-4b1e-8436-727a268933f6@intel.com>



On 3/12/2025 2:14 AM, Russell King (Oracle) wrote:
> Hi,
> 
> This series removes unnecessary of_get_phy_mode() calls from the stmmac
> glue drivers. stmmac_probe_config_dt() / devm_stmmac_probe_config_dt()
> already gets the interface mode using device_get_phy_mode() and stores
> it in plat_dat->phy_interface.
> 
> Therefore, glue drivers using of_get_phy_mode() are just duplicating
> the work that has already been done.
> 
> This series adjusts the glue drivers to remove their usage of
> of_get_phy_mode().
> 
> Changes in v2:
> - correct subject for patch 3
> - fix build error in patch 3
> - add attributations
> 

Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>

>  drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c | 21 +++++++++------------
>  drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 12 ++++--------
>  .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c    |  8 +-------
>  drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c |  6 +-----
>  .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c |  4 +---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c      |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c     | 12 ++++--------
>  drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c   |  8 +-------
>  drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c   |  6 +-----
>  9 files changed, 23 insertions(+), 56 deletions(-)
> 



From Frank.li at nxp.com  Thu Mar 13 15:56:17 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 18:56:17 -0400
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250313220450.GA755590@bhelgaas>
References: <20250313-pci_fixup_addr-v11-6-01d2313502ab@nxp.com>
 <20250313220450.GA755590@bhelgaas>
Message-ID: <Z9NikZqmmnkt/GQm@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 05:04:50PM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 11:38:42AM -0400, Frank Li wrote:
> > The 'ranges' property at PCI controller parent bus can indicate address
> > translation information. Most system's bus fabric use 1:1 map between input
> > and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.
>
> I think you've used reg["addr_space"] to get the offset for Endpoints
> forever.

Yes, it still need ranges informaiton at parent bus.

	bus at 000
	{
		ranges = <...>; [1] /* still need this */
		pcie {
			ranges = <...>;[2]
		};
		pcie-ep {};
	}

>
> I just noticed that through v9, you used 'ranges' to get the offset
> for the Root Complex (with "Add parent_bus_offset to resource_entry"),
> and I think v10 switched to use reg["config"] instead.
>
> I think I originally proposed the idea of "Add parent_bus_offset to
> resource_entry" patch, but I think it turned out to be kind of an ugly
> approach.
>
> Anyway, IIUC this v11 patch actually uses reg["config"] to compute the
> offset, not 'ranges', so we should probably update the subject and
> commit log to reflect that, and maybe remove the now-unused bits of
> the devicetree example.

We use reg["config"] to detect offset, but still need parent dts's ranges.
There are two ranges, one is at parent pci bus [1], the other is under
'pci bus' [2].

Although use reg["config"], but still need ranges [1]. And information at
ranges [2] also need be correct.

The whole devicetree example also validate to help write address translate
informaiton.

>
> I do worry a little bit about the assumption that the offset of
> reg["config"] is the same as the offset of the other pieces.  The main
> place we use the offset on RCs is for the ATU, and isn't the ATU in
> the MemSpace area at 0x8000_0000 below?

No, "Bus fabric" only decode input address from "0x7000_0000..UPLIMIT".
Then output address to 0x8000_0000..UPLIMIT. So below 0x8000_0000 never
happen.

>
> It's great that in this case the 0x7ff0_0000 to 0x8ff0_0000 "config"
> offset is the same as the 0x7000_0000 to 0x8000_0000 MemSpace offset,
> but I don't know that this is guaranteed for all designs.

So far, it is the same for use dwc chips. If we meet difference, we can
add later.

reg["config"] only simplied our implement base on the offset is the same.
But whole concept is unchanged.

Frank

>
> v9:
>   [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
>     https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-3-3c4bb506f665 at nxp.com
>   [PATCH v9 5/7] PCI: dwc: ep: Add parent_bus_addr for outbound window
>     https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-5-3c4bb506f665 at nxp.com
>
> v10:
>   [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to get rid of cpu_addr_fixup() callback
>     https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-5-409dafc950d1 at nxp.com
>   [PATCH v10 06/10] PCI: dwc: ep: Add parent_bus_addr for outbound window
>     https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-6-409dafc950d1 at nxp.com
>
> > See below diagram:
> >
> >             ???????????                    ??????????????
> >  ???????    ?         ? IA: 0x8ff8_0000    ?            ?
> >  ? CPU ??????   ?????????????????????????  ? PCI        ?
> >  ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
> >   CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
> > 0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
> >             ?      ?  ?             ?   ?  ?            ?   PCI Addr
> > 0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
> >             ?         ?             ?      ?            ?    0
> > 0x7000_0000??????????????????????   ?      ?            ?
> >             ???????????         ?   ???????? CfgSpace  ???????????????
> >              BUS Fabric         ?          ?            ?    0
> >                                 ?          ?            ?
> >                                 ???????????? MemSpace  ???????????????
> >                         IA: 0x8000_0000    ?            ?  0x8000_0000
> >                                            ??????????????
> >
> > bus at 5f000000 {
> > 	compatible = "simple-bus";
> > 	#address-cells = <1>;
> > 	#size-cells = <1>;
> > 	ranges = <0x80000000 0x0 0x70000000 0x10000000>;
> >
> > 	pcie at 5f010000 {
> > 		compatible = "fsl,imx8q-pcie";
> > 		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> > 		reg-names = "dbi", "config";
> > 		#address-cells = <3>;
> > 		#size-cells = <2>;
> > 		device_type = "pci";
> > 		bus-range = <0x00 0xff>;
> > 		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> > 			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
> > 	...
> > 	};
> > };
> >
> > Term Intermediate address (IA) here means the address just before PCIe
> > controller. After ATU use this IA instead CPU address, cpu_addr_fixup() can
> > be removed.
> >
> > Use reg-name "config" to detect parent_bus_addr_offset. Suppose the offset
> > is the same for all kinds of address translation.
> >
> > Just set parent_bus_offset, but doesn't use it, so no functional change
> > intended yet.
>
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -474,6 +474,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> >  		pp->io_base = pci_pio_to_address(win->res->start);
> >  	}
> >
> > +	/*
> > +	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
> > +	 * so have to call dw_pcie_init_parent_bus_offset() after init
> > +	 * pp->io_base.
> > +	 */
> > +	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
> > +	if (ret)
> > +		return ret;
> > +
> >  	/* Set default bus ops */
> >  	bridge->ops = &dw_pcie_ops;
> >  	bridge->child_ops = &dw_child_pcie_ops;
> >
> > --
> > 2.34.1
> >


From devnull+j.ne.posteo.net at kernel.org  Thu Mar 13 16:11:00 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Fri, 14 Mar 2025 00:11:00 +0100
Subject: [PATCH v2 2/2] arm64: dts: amlogic: Add Ugoos AM3
In-Reply-To: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>
References: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>
Message-ID: <20250314-ugoos-am3-v2-2-422104b0cec5@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC,
with a board design that is very close to the Q20x development boards.
The MMC max-frequency properties are copied from the downstream device
tree.

  https://ugoos.com/ugoos-am3-16g

The following functionality has been tested and is known to work:
 - debug serial port
 - "update" button inside the case
 - USB host mode, on all three ports
 - HDMI video/audio output
 - eMMC, MicroSD, and SDIO WLAN
 - S/PDIF audio output
 - Ethernet
 - Infrared remote control input

The following functionality doesn't seem to work:
 - USB role switching and device mode on the "OTG" port
 - case LED

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---

V2:
- Fix vendor name in patch subject
- Remove incorrect override of SDIO pwrseq reset line
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 +-
 .../arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts | 91 ++++++++++++++++++++++
 3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 2fbda8419c65a3056410ac45ca3ddaceb69ea4f5..bf2bc14528bfa27e8d6ae2730085fc356d6c6dd8 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -76,6 +76,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-libretech-pc.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
index 45ccddd1aaf0546632c81a52c8917a923beae883..4223b26f7d0f3aa47e42e9434d24f73b20441981 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
@@ -97,7 +97,7 @@ sdio_pwrseq: sdio-pwrseq {
 		clock-names = "ext_clock";
 	};
 
-	cvbs-connector {
+	cvbs_connector: cvbs-connector {
 		compatible = "composite-video-connector";
 
 		port {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
new file mode 100644
index 0000000000000000000000000000000000000000..ba871f3f53bb99b47b325bae228b59b722c5123b
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 J. Neusch?fer <j.ne at posteo.net>
+ *
+ * Debug UART (3.3V, 115200 baud) at the corner of the board:
+ *   (4) (3) (2) [1]
+ *   Vcc RXD TXD GND
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/amlogic,meson-g12a-gpio-intc.h>
+
+#include "meson-gxm.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "ugoos,am3", "amlogic,s912", "amlogic,meson-gxm";
+	model = "Ugoos AM3";
+
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 0>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1710000>;
+
+		button-function {
+			label = "Update";
+			linux,code = <KEY_VENDOR>;
+			press-threshold-microvolt = <10000>;
+		};
+	};
+};
+
+&cvbs_connector {
+	/* Not used on this board */
+	status = "disabled";
+};
+
+&ethmac {
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+
+	/* Select external PHY by default */
+	phy-handle = <&external_phy>;
+
+	amlogic,tx-delay-ns = <2>;
+
+	/* External PHY is in RGMII */
+	phy-mode = "rgmii";
+
+	status = "okay";
+};
+
+&external_mdio {
+	external_phy: ethernet-phy at 0 {
+		/* Realtek RTL8211F (0x001cc916) */
+		reg = <0>;
+
+		reset-assert-us = <10000>;
+		reset-deassert-us = <80000>;
+		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
+
+		interrupt-parent = <&gpio_intc>;
+		/* MAC_INTR on GPIOZ_15 */
+		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c_B {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c_b_pins>;
+
+	rtc: rtc at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+	};
+};
+
+/* WLAN: Atheros 10k (QCA9377) */
+&sd_emmc_a {
+	max-frequency = <200000000>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	max-frequency = <100000000>;
+};

-- 
2.48.0.rc1.219.gb6b6757d772




From devnull+j.ne.posteo.net at kernel.org  Thu Mar 13 16:10:58 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Fri, 14 Mar 2025 00:10:58 +0100
Subject: [PATCH v2 0/2] arm64: Device Tree for Ugoos AM3 board
Message-ID: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>

This patchset adds a device tree for Ugoos AM3, an Android TV box from
2018. Most hardware functionality has been tested, as noted in patch 2/2.

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
Changes in v2:
- fix vendor name in patch subjects
- fix mistake that made wifi not work
- apply Krzysztof's ACK to patch 1/2
- Link to v1: https://lore.kernel.org/r/20250309-ugoos-am3-v1-0-38cab5a4725b at posteo.net

---
J. Neusch?fer (2):
      dt-bindings: arm: amlogic: Add Ugoos AM3
      arm64: dts: amlogic: Add Ugoos AM3

 Documentation/devicetree/bindings/arm/amlogic.yaml |  1 +
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 +-
 .../arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts | 91 ++++++++++++++++++++++
 4 files changed, 94 insertions(+), 1 deletion(-)
---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20250222-ugoos-am3-f67413860434

Best regards,
-- 
J. Neusch?fer <j.ne at posteo.net>




From akpm at linux-foundation.org  Thu Mar 13 16:10:38 2025
From: akpm at linux-foundation.org (Andrew Morton)
Date: Thu, 13 Mar 2025 16:10:38 -0700
Subject: [PATCH v13 04/11] mm/page_table_check: Reinstate address
 parameter in [__]page_table_check_pud_clear()
In-Reply-To: <20250211161404.850215-5-ajd@linux.ibm.com>
References: <20250211161404.850215-1-ajd@linux.ibm.com>
	<20250211161404.850215-5-ajd@linux.ibm.com>
Message-ID: <20250313161038.8bd10fa54778e984d8f849d7@linux-foundation.org>

On Wed, 12 Feb 2025 03:13:57 +1100 Andrew Donnellan <ajd at linux.ibm.com> wrote:

> This reverts commit 931c38e16499 ("mm/page_table_check: remove unused
> parameter in [__]page_table_check_pud_clear").
> 
> Reinstate previously unused parameters for the purpose of supporting
> powerpc platforms, as many do not encode user/kernel ownership of the
> page in the pte, but instead in the address of the access.

My x86-64 allmodconfig exploded.

./arch/x86/include/asm/pgtable.h: In function 'pudp_establish':
./arch/x86/include/asm/pgtable.h:1443:46: error: passing argument 2 of 'page_table_check_pud_set' makes integer from pointer without a cast [-Werror=int-conversion]
 1443 |         page_table_check_pud_set(vma->vm_mm, pudp, pud);
      |                                              ^~~~
      |                                              |
      |                                              pud_t *



#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
static inline pud_t pudp_establish(struct vm_area_struct *vma,
                unsigned long address, pud_t *pudp, pud_t pud)
{
	page_table_check_pud_set(vma->vm_mm, pudp, pud);
	...


From devnull+j.ne.posteo.net at kernel.org  Thu Mar 13 16:10:59 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Fri, 14 Mar 2025 00:10:59 +0100
Subject: [PATCH v2 1/2] dt-bindings: arm: amlogic: Add Ugoos AM3
In-Reply-To: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>
References: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>
Message-ID: <20250314-ugoos-am3-v2-1-422104b0cec5@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC.

  https://ugoos.com/ugoos-am3-16g

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---

V2:
- fix vendor name in patch subject
- add Krzysztof's ACK
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 0647851ae1f55a27bfb148252532bcf15ca905bf..779568f158ce985e1d12fbee73418549cfc58705 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -127,6 +127,7 @@ properties:
               - minix,neo-u9h
               - nexbox,a1
               - tronsmart,vega-s96
+              - ugoos,am3
               - videostrong,gxm-kiii-pro
               - wetek,core2
           - const: amlogic,s912

-- 
2.48.0.rc1.219.gb6b6757d772




From andersson at kernel.org  Thu Mar 13 16:17:27 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Thu, 13 Mar 2025 18:17:27 -0500
Subject: [PATCH v6 06/10] dt-bindings: clock: Add Qualcomm QCS615
 Graphics clock controller
In-Reply-To: <d1814cd9-5c73-4ac5-a4ed-4cc2aae410d0@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>
 <20250313-graceful-jackdaw-of-opportunity-62996d@krzk-bin>
 <d1814cd9-5c73-4ac5-a4ed-4cc2aae410d0@quicinc.com>
Message-ID: <5tt4wli2yodoet2l6r7ksq3o743nmi75hfksakqaxre3gmyr2a@zdotamju5ndp>

On Thu, Mar 13, 2025 at 02:18:57PM +0530, Taniya Das wrote:
> 
> 
> On 3/13/2025 1:54 PM, Krzysztof Kozlowski wrote:
> > On Thu, Mar 13, 2025 at 12:29:43PM +0530, Taniya Das wrote:
> >  +
> >> +  '#reset-cells':
> >> +    const: 1
> >> +
> >> +  '#power-domain-cells':
> >> +    const: 1
> >> +
> >> +required:
> >> +  - compatible
> >> +  - reg
> >> +  - clocks
> >> +  - '#clock-cells'
> >> +  - '#reset-cells'
> >> +  - '#power-domain-cells'
> >> +
> > 
> > I don't get why this binding is different than others and you do not
> > reference qcom,gcc.yaml? Is it not applicable here? Other gpucc do
> > reference.
> > 
> 
> Yes, I will fix them and resend.
> 

What is it that you will fix and resend? This patch or all other cases?

Please stop just throwing stuff at the list and until something sticks,
talk with the people who review your patches.

Regards,
Bjorn

> > 
> > Best regards,
> > Krzysztof
> > 
> 


From andersson at kernel.org  Thu Mar 13 16:39:49 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Thu, 13 Mar 2025 18:39:49 -0500
Subject: [PATCH v6 01/10] clk: qcom: clk-alpha-pll: Add support for
 dynamic update for slewing PLLs
In-Reply-To: <20250313-qcs615-v5-mm-cc-v6-1-ebf4b9a5e916@quicinc.com>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-1-ebf4b9a5e916@quicinc.com>
Message-ID: <r6xikx2idlzwc4xl7doap3v5ug3a6qtg65jwqjuekiv7tvbwzn@5nk4c7nl2zws>

On Thu, Mar 13, 2025 at 12:29:38PM +0530, Taniya Das wrote:
> The alpha PLLs which slew to a new frequency at runtime would require
> the PLL to calibrate at the mid point of the VCO. Add the new PLL ops
> which can support the slewing of the PLL to a new frequency.
> 
> Reviewed-by: Imran Shaik <quic_imrashai at quicinc.com>
> Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
> ---
>  drivers/clk/qcom/clk-alpha-pll.c | 170 +++++++++++++++++++++++++++++++++++++++
>  drivers/clk/qcom/clk-alpha-pll.h |   1 +
>  2 files changed, 171 insertions(+)
> 
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index cec0afea8e446010f0d4140d4ef63121706dde47..7d784db8b7441e886d94ded1d3e3258dda46674c 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -2960,3 +2960,173 @@ const struct clk_ops clk_alpha_pll_regera_ops = {
>  	.set_rate = clk_zonda_pll_set_rate,
>  };
>  EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops);
> +
> +static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll)
> +{
> +	int ret;
> +	u32 val;
> +
> +	regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, PLL_UPDATE);
> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> +
> +	ret = wait_for_pll_update(pll);
> +	if (ret)
> +		return ret;
> +	/*
> +	 * Hardware programming mandates a wait of at least 570ns before polling the LOCK
> +	 * detect bit. Have a delay of 1us just to be safe.
> +	 */
> +	mb();
> +	udelay(1);
> +
> +	return wait_for_pll_enable_lock(pll);
> +}
> +
> +static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate,
> +					unsigned long parent_rate)
> +{
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	unsigned long freq_hz;
> +	const struct pll_vco *curr_vco, *vco;
> +	u32 l, alpha_width = pll_alpha_width(pll);
> +	u64 a;
> +
> +	freq_hz =  alpha_pll_round_rate(rate, parent_rate, &l, &a, alpha_width);

Double space here.

> +	if (freq_hz != rate) {
> +		pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
> +		return -EINVAL;
> +	}
> +
> +	curr_vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
> +	if (!curr_vco) {
> +		pr_err("alpha pll: not in a valid vco range\n");
> +		return -EINVAL;
> +	}
> +
> +	vco = alpha_pll_find_vco(pll, freq_hz);
> +	if (!vco) {
> +		pr_err("alpha pll: not in a valid vco range\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Dynamic pll update will not support switching frequencies across
> +	 * vco ranges. In those cases fall back to normal alpha set rate.
> +	 */
> +	if (curr_vco->val != vco->val)
> +		return clk_alpha_pll_set_rate(hw, rate, parent_rate);
> +
> +	a = a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);

Above this function is written to deal with both alpha bitwidths, but
here it's assumed to only be one of the cases.

It would be nice to get this cleaned up somehow, because we now have
this shift 6 times in slightly different forms.

> +
> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);

In a number of places in the driver alpha_width is compared to 32 bits
to see if this should be written or not. Perhaps that's not applicable
here, but again, if so then why is it dynamic above?


Also, how about upper_32_bits() and lower_32_bits() to make it clear
what's going on here?

> +
> +	/* Ensure that the write above goes through before proceeding. */

That's not what mb() does.

Regards,
Bjorn

> +	mb();
> +
> +	if (clk_hw_is_enabled(hw))
> +		return clk_alpha_pll_slew_update(pll);
> +
> +	return 0;
> +}
> +
> +/*
> + * Slewing plls should be bought up at frequency which is in the middle of the
> + * desired VCO range. So after bringing up the pll at calibration freq, set it
> + * back to desired frequency(that was set by previous clk_set_rate).
> + */
> +static int clk_alpha_pll_calibrate(struct clk_hw *hw)
> +{
> +	unsigned long calibration_freq, freq_hz;
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	struct clk_hw *parent;
> +	const struct pll_vco *vco;
> +	u32 l, alpha_width = pll_alpha_width(pll);
> +	int rc;
> +	u64 a;
> +
> +	parent = clk_hw_get_parent(hw);
> +	if (!parent) {
> +		pr_err("alpha pll: no valid parent found\n");
> +		return -EINVAL;
> +	}
> +
> +	vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
> +	if (!vco) {
> +		pr_err("alpha pll: not in a valid vco range\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * As during slewing plls vco_sel won't be allowed to change, vco table
> +	 * should have only one entry table, i.e. index = 0, find the
> +	 * calibration frequency.
> +	 */
> +	calibration_freq = (pll->vco_table[0].min_freq + pll->vco_table[0].max_freq) / 2;
> +
> +	freq_hz = alpha_pll_round_rate(calibration_freq, clk_hw_get_rate(parent),
> +					&l, &a, alpha_width);
> +	if (freq_hz != calibration_freq) {
> +		pr_err("alpha_pll: call clk_set_rate with rounded rates!\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Setup PLL for calibration frequency */
> +	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
> +
> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
> +
> +	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_VCO_MASK << PLL_VCO_SHIFT,
> +				vco->val << PLL_VCO_SHIFT);
> +
> +	/* Bringup the pll at calibration frequency */
> +	rc = clk_alpha_pll_enable(hw);
> +	if (rc) {
> +		pr_err("alpha pll calibration failed\n");
> +		return rc;
> +	}
> +
> +	/*
> +	 * PLL is already running at calibration frequency.
> +	 * So slew pll to the previously set frequency.
> +	 */
> +	freq_hz = alpha_pll_round_rate(clk_hw_get_rate(hw),
> +			clk_hw_get_rate(parent), &l, &a, alpha_width);
> +
> +	pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n",
> +		clk_hw_get_name(hw), clk_hw_get_rate(hw), freq_hz);
> +
> +	/* Setup the PLL for the new frequency */
> +	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
> +
> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
> +
> +	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_ALPHA_EN, PLL_ALPHA_EN);
> +
> +	return clk_alpha_pll_slew_update(pll);
> +}
> +
> +static int clk_alpha_pll_slew_enable(struct clk_hw *hw)
> +{
> +	int rc;
> +
> +	rc = clk_alpha_pll_calibrate(hw);
> +	if (rc)
> +		return rc;
> +
> +	return clk_alpha_pll_enable(hw);
> +}
> +
> +const struct clk_ops clk_alpha_pll_slew_ops = {
> +	.enable = clk_alpha_pll_slew_enable,
> +	.disable = clk_alpha_pll_disable,
> +	.recalc_rate = clk_alpha_pll_recalc_rate,
> +	.round_rate = clk_alpha_pll_round_rate,
> +	.set_rate = clk_alpha_pll_slew_set_rate,
> +};
> +EXPORT_SYMBOL(clk_alpha_pll_slew_ops);
> diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
> index 79aca8525262211ae5295245427d4540abf1e09a..1d19001605eb10fd8ae8041c56d951e928cbbe9f 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.h
> +++ b/drivers/clk/qcom/clk-alpha-pll.h
> @@ -204,6 +204,7 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
>  #define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
>  
>  extern const struct clk_ops clk_alpha_pll_regera_ops;
> +extern const struct clk_ops clk_alpha_pll_slew_ops;
>  
>  void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
>  			     const struct alpha_pll_config *config);
> 
> -- 
> 2.48.1
> 


From broonie at kernel.org  Thu Mar 13 17:35:16 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:16 +0000
Subject: [PATCH 6.12 4/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.ZEN
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-4-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 16 ----------------
 2 files changed, 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d8802490b25cba65369f03d94627a2624f14b072..1a126fa657fcde3433f37f3aaf464a5b6a5f095d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 2ee6bde85235581d6bc9cba7e578c55875b5d5a1..4127abfd319c2c683d2281efa52a6abe5fac67ee 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:17 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:17 +0000
Subject: [PATCH 6.12 5/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.SMEN
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-5-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 21 ---------------------
 2 files changed, 23 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1a126fa657fcde3433f37f3aaf464a5b6a5f095d..122a1e12582c0584bce86c5416ef7d150f90fe95 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 4127abfd319c2c683d2281efa52a6abe5fac67ee..f64724197958e0d8a4ec17deb1f9826ce3625eb7 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:18 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:18 +0000
Subject: [PATCH 6.12 6/8] KVM: arm64: Refactor exit handlers
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-6-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index a7f6a653f33718d1a25e232608e63ea287f2a672..e14aba19847f2c66c202a869b5173f25a9a7f66e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -635,23 +635,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -681,20 +674,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -724,7 +706,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7..ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index e7ca0424107adec2371ae4553ebab9857c60b6d9..46c1f5caf007331cdbbc806a184e9b4721042fc0 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:19 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:19 +0000
Subject: [PATCH 6.12 7/8] KVM: arm64: Mark some header functions as inline
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-7-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index e14aba19847f2c66c202a869b5173f25a9a7f66e..c1ab31429a0e5fab97cd06c3b7b6e378170bd99d 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -295,7 +295,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -373,7 +373,7 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -564,7 +564,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -584,7 +584,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -593,19 +593,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:12 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:12 +0000
Subject: [PATCH 6.12 0/8] KVM: arm64: Backport of SVE fixes to v6.12
Message-ID: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>

This series backports some recent fixes for SVE/KVM interactions from
Mark Rutland to v6.12.

Signed-off-by: Mark Brown <broonie at kernel.org>
---
Fuad Tabba (1):
      KVM: arm64: Calculate cptr_el2 traps on activating traps

Mark Rutland (7):
      KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
      KVM: arm64: Remove host FPSIMD saving for non-protected KVM
      KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
      KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
      KVM: arm64: Refactor exit handlers
      KVM: arm64: Mark some header functions as inline
      KVM: arm64: Eagerly switch ZCR_EL{1,2}

 arch/arm64/include/asm/kvm_host.h       |  25 ++----
 arch/arm64/kernel/fpsimd.c              |  25 ------
 arch/arm64/kvm/arm.c                    |   9 ---
 arch/arm64/kvm/fpsimd.c                 | 100 ++----------------------
 arch/arm64/kvm/hyp/entry.S              |   5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 133 ++++++++++++++++++++++---------
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  15 ++--
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  29 -------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 134 ++++++++++++++++++--------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  21 ++---
 10 files changed, 204 insertions(+), 292 deletions(-)
---
base-commit: e9cc806c0152fa9993f817cebf42989a3e2530bb
change-id: 20250227-stable-sve-6-12-777778ad28fb

Best regards,
-- 
Mark Brown <broonie at kernel.org>



From broonie at kernel.org  Thu Mar 13 17:35:13 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:13 +0000
Subject: [PATCH 6.12 1/8] KVM: arm64: Calculate cptr_el2 traps on
 activating traps
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-1-ddc16609d9ba@kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  1 -
 arch/arm64/kvm/arm.c              |  1 -
 arch/arm64/kvm/hyp/nvhe/pkvm.c    | 29 ----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  | 51 ++++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1bf70fa1045dcd6704bdcd233767cdb7522b316f..d148cf578cb84e7dec4d1add2afa60a3c7a1e041 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -697,7 +697,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3cf65daa75a51f71fa7168016f8c3d81dc326cca..e6f0443210a8b7a65f616b25b2e6f74a05683ed6 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1577,7 +1577,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 077d4098548d2c87abdd3931285d87798d63adb3..7c464340bcd078df58b74164707f263a6bdb0272 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -28,8 +28,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -59,21 +57,10 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -103,7 +90,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -130,21 +116,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -195,10 +172,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 /*
@@ -579,8 +552,6 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index cc69106734ca732ba9276ac1eaf84be3e7381648..81d933a71310fd1132b2450cd08108e071a2cf78 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
+
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:14 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:14 +0000
Subject: [PATCH 6.12 2/8] KVM: arm64: Unconditionally save+flush host
 FPSIMD/SVE/SME state
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-2-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 25 -------------------------
 arch/arm64/kvm/fpsimd.c    | 35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 6d21971ae5594f32947480cfa168db400a69a283..f38d22dac140f1b2a8de3f2f2ba1e5da22d2d1c8 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void)
 		sve_to_fpsimd(current);
 }
 
-/*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
 /*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index ea5484ce1f3ba3121b6938bda15f7a8057d49051..efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:15 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:15 +0000
Subject: [PATCH 6.12 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-3-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       | 20 +++++---------------
 arch/arm64/kvm/arm.c                    |  8 --------
 arch/arm64/kvm/fpsimd.c                 |  2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h | 25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  8 --------
 7 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d148cf578cb84e7dec4d1add2afa60a3c7a1e041..d8802490b25cba65369f03d94627a2624f14b072 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -602,23 +602,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
-
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	struct cpu_sve_state *sve_state;
+
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index e6f0443210a8b7a65f616b25b2e6f74a05683ed6..634d3f62481827a3bf3aba6bf78cafed71b5bd32 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2476,14 +2476,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5..2ee6bde85235581d6bc9cba7e578c55875b5d5a1 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 5310fe1da6165bcdedfb5ce61bce353e4c9dd58b..a7f6a653f33718d1a25e232608e63ea287f2a672 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,7 +344,28 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -394,7 +415,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index fefc89209f9e41c95478f6770881eb314a38b4c2..4e757a77322c9efc59cdff501745f7c80d452358 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 81d933a71310fd1132b2450cd08108e071a2cf78..3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 80581b1c399595fd64d0ccada498edac322480a6..e7ca0424107adec2371ae4553ebab9857c60b6d9 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 13 17:35:20 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 00:35:20 +0000
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
Message-ID: <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/fpsimd.c                 | 30 -----------------
 arch/arm64/kvm/hyp/entry.S              |  5 +++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 13 ++++----
 arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
 6 files changed, 103 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index f64724197958e0d8a4ec17deb1f9826ce3625eb7..3cbb999419af7bb31ce9cec2baafcad00491610a 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 4433a234aa9ba242f43b943d22011b5ddacd8af7..9f4e8d68ab505cf4a7aa8673643d9b47ca1bc7cb 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index c1ab31429a0e5fab97cd06c3b7b6e378170bd99d..cc9cb63959463a7ddb35d868b17e485b1223d507 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,6 +344,65 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 4e757a77322c9efc59cdff501745f7c80d452358..1c8e2ad32e8c396fc4b11d5fec2e86728f2829d9 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -176,8 +177,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
 		sync_hyp_vcpu(hyp_vcpu);
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
+		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
+
 		/* The host is fully trusted, run its vCPU directly. */
-		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_guest(vcpu);
+		ret = __kvm_vcpu_run(vcpu);
+		fpsimd_lazy_switch_to_host(vcpu);
 	}
 
 out:
@@ -486,12 +491,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494..a1245fa838319544f3770a05a58eeed5233f0324 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 46c1f5caf007331cdbbc806a184e9b4721042fc0..496abfd3646b9858e95e06a79edec11eee3a5893 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())

-- 
2.39.5



From sboyd at kernel.org  Thu Mar 13 17:54:45 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Thu, 13 Mar 2025 17:54:45 -0700
Subject: [PATCH] dt-bindings: reset: fix double id on rk3562-cru reset ids
In-Reply-To: <20250312215923.275625-1-heiko@sntech.de>
References: <20250312215923.275625-1-heiko@sntech.de>
Message-ID: <843824c0ef2e4cfc5307931c9a8aba2f.sboyd@kernel.org>

Quoting Heiko Stuebner (2025-03-12 14:59:23)
> Id 173 was accidentially used two times for SRST_P_DDR_HWLP and
> SRST_P_DDR_PHY. This makes both resets ambiguous and also causes build
> warnings like:
> 
> drivers/clk/rockchip/rst-rk3562.c:21:57: error: initialized field overwritten [-Werror=override-init]
>    21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
>       |                                                         ^
> drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
>   266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/clk/rockchip/rst-rk3562.c:21:57: note: (near initialization for 'rk3562_register_offset[173]')
>    21 | #define RK3562_DDRCRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000*4 + reg * 16 + bit)
>       |                                                         ^
> drivers/clk/rockchip/rst-rk3562.c:266:9: note: in expansion of macro 'RK3562_DDRCRU_RESET_OFFSET'
>   266 |         RK3562_DDRCRU_RESET_OFFSET(SRST_P_DDR_PHY, 0, 8),
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> To fix that issue give SRST_P_DDR_PHY a new and now unique id.
> 
> Reported-by: Stephen Boyd <sboyd at kernel.org>
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503121743.0zcDf6nE-lkp at intel.com/
> Fixes: dd113c4fefc8 ("dt-bindings: clock: Add RK3562 cru")
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---

Applied to clk-next


From sboyd at kernel.org  Thu Mar 13 18:02:01 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Thu, 13 Mar 2025 18:02:01 -0700
Subject: [PATCH v2] dt-bindings: clocks: atmel,at91rm9200-pmc: add missing compatibles
In-Reply-To: <20250213092728.11659-2-wsa+renesas@sang-engineering.com>
References: <20250213092728.11659-2-wsa+renesas@sang-engineering.com>
Message-ID: <da70e2f173b056154d906056469e13f9.sboyd@kernel.org>

Quoting Wolfram Sang (2025-02-13 01:26:34)
> The driver support more SoCs. Add the missing ones.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
> ---

Applied to clk-next


From chenyuan0y at gmail.com  Thu Mar 13 18:20:29 2025
From: chenyuan0y at gmail.com (Chenyuan Yang)
Date: Thu, 13 Mar 2025 20:20:29 -0500
Subject: [PATCH] drm/sun4i: backend: Fix error pointers in sun4i_backend_atomic_check
Message-ID: <20250314012029.668306-1-chenyuan0y@gmail.com>

The function sun4i_backend_atomic_check was dereferencing pointers
returned by drm_atomic_get_plane_state without checking for errors. This
could lead to undefined behavior if the function returns an error pointer.

This commit adds checks using IS_ERR to ensure that plane_state is
valid before dereferencing them.

Similar to commit da29abe71e16
("drm/amd/display: Fix error pointers in amdgpu_dm_crtc_mem_type_changed").

Fixes: 96180dde23b7 ("drm/sun4i: backend: Add a custom atomic_check for the frontend")
Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 2dded3b828df..a8e0e2123764 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -490,6 +490,10 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
 	drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
 		struct drm_plane_state *plane_state =
 			drm_atomic_get_plane_state(state, plane);
+
+		if (IS_ERR(plane_state))
+			return PTR_ERR(plane_state);
+
 		struct sun4i_layer_state *layer_state =
 			state_to_sun4i_layer_state(plane_state);
 		struct drm_framebuffer *fb = plane_state->fb;
-- 
2.34.1



From wei.fang at nxp.com  Thu Mar 13 18:28:48 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 14 Mar 2025 01:28:48 +0000
Subject: [PATCH v4 net-next 00/14] Add more feautues for ENETC v4 - round
 2
In-Reply-To: <20250313135041.uex3gvhpbmnh4hmp@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250313135041.uex3gvhpbmnh4hmp@skbuf>
Message-ID: <PAXPR04MB85101D921FD07B882E03216088D22@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:16PM +0800, Wei Fang wrote:
> > This patch set adds the following features.
> > 1. Compared with ENETC v1, the formats of tables and command BD of ENETC
> > v4 have changed significantly, and the two are not compatible. Therefore,
> > in order to support the NETC Table Management Protocol (NTMP) v2.0, we
> > introduced the netc-lib driver and added support for MAC address filter
> > table and RSS table.
> > 2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
> > 3. Add RSS support for i.MX95 ENETC PF.
> > 4. Add loopback support for i.MX95 ENETC PF.
> 
> Can you please fix the "feautues" typo in the cover letter title? It
> will get used for the merge commit.

Yes, sure, thanks for pointing this typo.


From quic_jiegan at quicinc.com  Thu Mar 13 18:59:47 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Fri, 14 Mar 2025 09:59:47 +0800
Subject: [PATCH v1 3/4] coresight: ctcu: Enable byte-cntr for TMC ETR
 devices
In-Reply-To: <7a65353d-aa18-4c63-abb9-46344de35fc4@arm.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-4-quic_jiegan@quicinc.com>
 <7a65353d-aa18-4c63-abb9-46344de35fc4@arm.com>
Message-ID: <2eb8a3fd-0366-4873-8536-644ce3684251@quicinc.com>



On 3/14/2025 12:24 AM, Suzuki K Poulose wrote:
> On 10/03/2025 09:04, Jie Gan wrote:
>> The byte-cntr function provided by the CTCU device is used to transfer 
>> data
>> from the ETR buffer to the userspace. An interrupt is triggered if the 
>> data
> 
> Why do we need a new device to transfer the data to userspace ?

Hi Suzuki Mike,

The purpose of the byte-cntr is for live debugging, allowing trace data 
to be read while the ETR is running and preventing the required trace 
data from being overwritten before output.

I realized that I forgot to introduce the function of the BYTECNTRCTL 
register.

There is a big concern that reading the etr_buf while the ETR is running 
is unsafe because the etr_buf is not synced, am right?

As I mentioned, we need program a value to the BYTECNTRCTL register. The 
hardware will count the bytes of the trace data that are routed to 
RAM(etr_buf).

The interrupt will be trigger once the counted bytes exceed the 
programmed value. Based on this concept, we can confirm this part of 
trace data is already in the etr_buf and is safe to read. So, it's safe 
for the read function only read this part of trace data in one 
shot(unlike tmc_read, the whole synced etr_buf).

That's how we expect the byte-cntr to work when reading the trace data 
from the etr_buf while the etr is running.

This also explains why we need a separate dev node to manage the read 
function for byte-cntr.

Thanks,
Jie


> 
>> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
>> handler counts the number of triggered interruptions and the read 
>> function
>> will read the data from the ETR buffer if the IRQ count is greater 
>> than 0.
>> Each successful read process will decrement the IRQ count by 1.
> 
> Having an interrupt is good, but see below.
> 
>>
>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>> ---
>> ? drivers/hwtracing/coresight/Makefile????????? |?? 2 +-
>> ? .../coresight/coresight-ctcu-byte-cntr.c????? | 339 ++++++++++++++++++
>> ? .../hwtracing/coresight/coresight-ctcu-core.c |? 96 ++++-
>> ? drivers/hwtracing/coresight/coresight-ctcu.h? |? 59 ++-
>> ? .../hwtracing/coresight/coresight-tmc-etr.c?? |?? 5 +-
>> ? drivers/hwtracing/coresight/coresight-tmc.h?? |?? 2 +
>> ? 6 files changed, 493 insertions(+), 10 deletions(-)
>> ? create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte- 
>> cntr.c
>>
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/ 
>> coresight/Makefile
>> index 8e62c3150aeb..c90a06768a18 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -52,4 +52,4 @@ coresight-cti-y := coresight-cti-core.o    
>> coresight-cti-platform.o \
>> ? obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>> ? obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>> ? obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>> -coresight-ctcu-y := coresight-ctcu-core.o
>> +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o
>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/ 
>> drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>> new file mode 100644
>> index 000000000000..0d16385663f5
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>> @@ -0,0 +1,339 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights 
>> reserved.
>> + */
>> +
>> +#include <linux/coresight.h>
>> +#include <linux/device.h>
>> +#include <linux/dma-mapping.h>
>> +#include <linux/fs.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/property.h>
>> +#include <linux/uaccess.h>
>> +
>> +#include "coresight-ctcu.h"
>> +#include "coresight-priv.h"
>> +#include "coresight-tmc.h"
>> +
>> +#define BYTE_CNTR_CLASS_STR "byte-cntr-class"
>> +
>> +static struct class *byte_cntr_class;
>> +static dev_t byte_cntr_base;
>> +
>> +static irqreturn_t byte_cntr_handler(int irq, void *data)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data = (struct ctcu_byte_cntr 
>> *)data;
>> +
>> +??? atomic_inc(&byte_cntr_data->irq_cnt);
>> +??? wake_up(&byte_cntr_data->wq);
>> +
>> +??? return IRQ_HANDLED;
>> +}
>> +
>> +/* Read the data from ETR's DDR buffer. */
>> +static void __ctcu_byte_cntr_read_etr_bytes(struct ctcu_byte_cntr 
>> *byte_cntr_data,
>> +??????????????????????? size_t *len, char **bufp)
>> +{
>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>> >sink->dev.parent);
>> +??? size_t actual, bytes = byte_cntr_data->thresh_val;
>> +??? struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
>> +??? long r_offset;
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? r_offset = byte_cntr_data->r_offset;
>> +??? if (*len >= bytes)
>> +??????? *len = bytes;
>> +??? else if ((r_offset % bytes) + *len > bytes)
>> +??????? *len = bytes - (r_offset % bytes);
>> +
>> +??? actual = tmc_etr_buf_get_data(etr_buf, r_offset, *len, bufp);
>> +??? *len = actual;
>> +??? if (actual == bytes || (actual + r_offset) % bytes == 0)
>> +??????? atomic_dec(&byte_cntr_data->irq_cnt);
>> +}
>> +
> 
> How can you safely read the ETR data while it is running ? You should
> stop the ETR and then provide the data. You could potentially do things
> like split the ETR buffer into two halves and switch the half used by
> the ETR on interrupt and expose this to user.
> 
> 
>> +/* Flush the remaining data in the ETR buffer after the byte cntr has 
>> stopped. */
>> +static ssize_t ctcu_flush_etr_buffer(struct ctcu_byte_cntr 
>> *byte_cntr_data, size_t len,
>> +???????????????????? char **bufpp)
>> +{
>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>> >sink->dev.parent);
>> +??? struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
>> +??? ssize_t read_len = 0, remaining_len;
>> +??? long r_offset, w_offset;
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? r_offset = byte_cntr_data->r_offset;
>> +??? w_offset = byte_cntr_data->w_offset;
>> +??? if (w_offset < r_offset)
>> +??????? remaining_len = tmcdrvdata->size + w_offset - r_offset;
>> +??? else
>> +??????? remaining_len = w_offset - r_offset;
>> +
>> +??? if (remaining_len > len)
>> +??????? remaining_len = len;
>> +
>> +??? if (remaining_len > 0)
>> +??????? read_len = tmc_etr_buf_get_data(etr_buf, r_offset, 
>> remaining_len, bufpp);
>> +
>> +??? return read_len;
>> +}
>> +
>> +static ssize_t ctcu_byte_cntr_copy_data(char __user *data, size_t 
>> len, char *bufp,
>> +??????????????????? struct ctcu_byte_cntr *byte_cntr_data,
>> +??????????????????? struct tmc_drvdata *tmcdrvdata)
>> +{
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? if (copy_to_user(data, bufp, len))
>> +??????? return -EFAULT;
>> +
>> +??? byte_cntr_data->total_size += len;
>> +??? if (byte_cntr_data->r_offset + len >= tmcdrvdata->size)
>> +??????? byte_cntr_data->r_offset = 0;
>> +??? else
>> +??????? byte_cntr_data->r_offset += len;
>> +
>> +??? return len;
>> +}
>> +
>> +/* The read function for /dev/byte-cntr%d */
> 
> WHY ? WHY can't the data be exported by the existing /dev/tmc_etr* ?
> 
>> +static ssize_t ctcu_byte_cntr_read_etr_bytes(struct file *fp, char 
>> __user *data,
>> +???????????????????????? size_t len, loff_t *ppos)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>> >sink->dev.parent);
>> +??? char *bufp = NULL;
>> +??? ssize_t read_len;
>> +
>> +??? if (!data)
>> +??????? return -EINVAL;
>> +
>> +??? /*
>> +???? * Flush the remaining data in the ETR buffer based on the write
>> +???? * offset of the ETR buffer when the byte cntr function has stopped.
>> +???? */
>> +??? if (!byte_cntr_data->read_active || !byte_cntr_data->enable) {
>> +??????? read_len = ctcu_flush_etr_buffer(byte_cntr_data, len, &bufp);
>> +??????? if (read_len > 0)
>> +??????????? return ctcu_byte_cntr_copy_data(data, read_len, bufp,
>> +??????????????????????????? byte_cntr_data, tmcdrvdata);
>> +
>> +??????? return -EINVAL;
>> +??? }
>> +
>> +??? if (!atomic_read(&byte_cntr_data->irq_cnt)) {
>> +??????? if (wait_event_interruptible(byte_cntr_data->wq,
>> +???????????????????????? atomic_read(&byte_cntr_data->irq_cnt) > 0 ||
>> +???????????????????????? !byte_cntr_data->enable))
>> +??????????? return -ERESTARTSYS;
>> +??? }
>> +
>> +??? __ctcu_byte_cntr_read_etr_bytes(byte_cntr_data, &len, &bufp);
>> +
>> +??? return ctcu_byte_cntr_copy_data(data, len, bufp, byte_cntr_data, 
>> tmcdrvdata);
>> +}
> 
> Could we not plug this into TMC-ETR read ?
> 
> NAK for a special file approach. As Mike mentioned you need to make sure 
> we are doing this safely.
> 
> Suzuki
> 
> 
> 
>> +
>> +/* Start the byte-cntr function when the path is enabled. */
>> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct 
>> coresight_path *path)
>> +{
>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +??? struct coresight_device *sink = coresight_get_sink(path);
>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>> +??? int port_num;
>> +
>> +??? if (!sink)
>> +??????? return;
>> +
>> +??? port_num = ctcu_get_active_port(sink, csdev);
>> +??? if (port_num < 0)
>> +??????? return;
>> +
>> +??? byte_cntr_data = &drvdata->byte_cntr_data[port_num];
>> +??? /* Don't start byte-cntr function when threshold is not set. */
>> +??? if (!byte_cntr_data->thresh_val)
>> +??????? return;
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>> +??? byte_cntr_data->sink = sink;
>> +??? byte_cntr_data->enable = true;
>> +}
>> +
>> +/* Stop the byte-cntr function when the path is disabled. */
>> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct 
>> coresight_path *path)
>> +{
>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +??? struct coresight_device *sink = coresight_get_sink(path);
>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>> +??? struct tmc_drvdata *tmcdrvdata;
>> +??? int port_num;
>> +
>> +??? if (!sink)
>> +??????? return;
>> +
>> +??? port_num = ctcu_get_active_port(sink, csdev);
>> +??? if (port_num < 0)
>> +??????? return;
>> +
>> +??? byte_cntr_data = &drvdata->byte_cntr_data[port_num];
>> +??? tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? /* Store the w_offset of the ETR buffer when stopping. */
>> +??? byte_cntr_data->w_offset = tmc_get_rwp_offset(tmcdrvdata);
>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>> +??? byte_cntr_data->read_active = false;
>> +??? byte_cntr_data->enable = false;
>> +??? /*
>> +???? * Wakeup once to force the read function to read the remaining
>> +???? * data of the ETR buffer.
>> +???? */
>> +??? wake_up(&byte_cntr_data->wq);
>> +}
>> +
>> +static int ctcu_byte_cntr_release(struct inode *in, struct file *fp)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
>> +??? struct device *dev = &byte_cntr_data->sink->dev;
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>> +??? byte_cntr_data->read_active = false;
>> +??? disable_irq_wake(byte_cntr_data->byte_cntr_irq);
>> +??? dev_dbg(dev, "send data total size: %llu bytes, r_offset: %ld 
>> w_offset: %ld\n",
>> +??????? byte_cntr_data->total_size, byte_cntr_data->r_offset,
>> +??????? byte_cntr_data->w_offset);
>> +
>> +??? return 0;
>> +}
>> +
>> +static int ctcu_byte_cntr_open(struct inode *in, struct file *fp)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data = container_of(in->i_cdev,
>> +???????????????????????????????? struct ctcu_byte_cntr, c_dev);
>> +??? struct tmc_drvdata *tmcdrvdata;
>> +
>> +??? if (byte_cntr_data->read_active)
>> +??????? return -EBUSY;
>> +
>> +??? if (!byte_cntr_data->thresh_val || !byte_cntr_data->sink ||
>> +??????? (coresight_get_mode(byte_cntr_data->sink) !=? CS_MODE_SYSFS))
>> +??????? return -EINVAL;
>> +
>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>> +??? enable_irq_wake(byte_cntr_data->byte_cntr_irq);
>> +??? fp->private_data = byte_cntr_data;
>> +??? nonseekable_open(in, fp);
>> +??? tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
>> +??? /*
>> +???? * The original r_offset is the w_offset of the ETR buffer at the
>> +???? * start of the byte-cntr.
>> +???? */
>> +??? byte_cntr_data->r_offset = tmc_get_rwp_offset(tmcdrvdata);
>> +??? byte_cntr_data->total_size = 0;
>> +??? byte_cntr_data->read_active = true;
>> +??? byte_cntr_data->enable = true;
>> +
>> +??? return 0;
>> +}
>> +
>> +static const struct file_operations byte_cntr_fops = {
>> +??? .owner??????? = THIS_MODULE,
>> +??? .open??????? = ctcu_byte_cntr_open,
>> +??? .read??????? = ctcu_byte_cntr_read_etr_bytes,
>> +??? .release??? = ctcu_byte_cntr_release,
>> +};
>> +
>> +static int ctcu_byte_cntr_register_chardev(struct ctcu_byte_cntr 
>> *byte_cntr_data,
>> +?????????????????????? int port_num)
>> +{
>> +??? struct device *device;
>> +??? dev_t devt;
>> +??? int ret;
>> +
>> +??? cdev_init(&byte_cntr_data->c_dev, &byte_cntr_fops);
>> +??? devt = MKDEV(MAJOR(byte_cntr_base), MINOR(byte_cntr_base) + 
>> port_num);
>> +??? ret = cdev_add(&byte_cntr_data->c_dev, devt, 1);
>> +??? if (ret < 0)
>> +??????? return -ENOMEM;
>> +
>> +??? device = device_create(byte_cntr_class, NULL, devt, byte_cntr_data,
>> +?????????????????? byte_cntr_data->name);
>> +
>> +??? if (IS_ERR(device))
>> +??????? return -ENOMEM;
>> +
>> +??? return 0;
>> +}
>> +
>> +static void ctcu_byte_cntr_unregister_chardev(struct ctcu_drvdata 
>> *drvdata)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>> +??? int i;
>> +
>> +??? for (i = 0; i < ETR_MAX_NUM; i++) {
>> +??????? byte_cntr_data = &drvdata->byte_cntr_data[i];
>> +??????? device_destroy(byte_cntr_class, byte_cntr_data->c_dev.dev);
>> +??? }
>> +}
>> +
>> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata 
>> *drvdata, int etr_num)
>> +{
>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>> +??? struct device_node *nd = dev->of_node;
>> +??? int byte_cntr_irq, ret, i;
>> +
>> +??? ret = alloc_chrdev_region(&byte_cntr_base, 0, ETR_MAX_NUM, 
>> BYTE_CNTR_CLASS_STR);
>> +??? if (ret < 0)
>> +??????? return -ENOMEM;
>> +
>> +??? byte_cntr_class = class_create(BYTE_CNTR_CLASS_STR);
>> +??? if (IS_ERR(byte_cntr_class)) {
>> +??????? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>> +??????? return -ENOMEM;
>> +??? }
>> +
>> +??? for (i = 0; i < etr_num; i++) {
>> +??????? byte_cntr_data = &drvdata->byte_cntr_data[i];
>> +??????? byte_cntr_irq = of_irq_get_byname(nd, byte_cntr_data->irq_name);
>> +??????? if (byte_cntr_irq < 0) {
>> +??????????? ret = byte_cntr_irq;
>> +??????????? goto err_exit;
>> +??????? }
>> +
>> +??????? ret = devm_request_irq(dev, byte_cntr_irq, byte_cntr_handler,
>> +?????????????????????? IRQF_TRIGGER_RISING | IRQF_SHARED,
>> +?????????????????????? dev_name(dev), byte_cntr_data);
>> +??????? if (ret) {
>> +??????????? dev_err(dev, "Failed to register IRQ for %s\n",
>> +??????????????? byte_cntr_data->name);
>> +??????????? goto err_exit;
>> +??????? }
>> +
>> +??????? ret = ctcu_byte_cntr_register_chardev(byte_cntr_data, i);
>> +??????? if (ret) {
>> +??????????? dev_err(dev, "Failed to register chardev for %s\n",
>> +??????????????? byte_cntr_data->name);
>> +??????????? goto err_exit;
>> +??????? }
>> +
>> +??????? byte_cntr_data->byte_cntr_irq = byte_cntr_irq;
>> +??????? atomic_set(&byte_cntr_data->irq_cnt, 0);
>> +??????? init_waitqueue_head(&byte_cntr_data->wq);
>> +??? }
>> +
>> +??? return 0;
>> +
>> +err_exit:
>> +??? ctcu_byte_cntr_unregister_chardev(drvdata);
>> +??? class_destroy(byte_cntr_class);
>> +??? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>> +??? return ret;
>> +}
>> +
>> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata)
>> +{
>> +??? ctcu_byte_cntr_unregister_chardev(drvdata);
>> +??? class_destroy(byte_cntr_class);
>> +??? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>> +}
>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/ 
>> drivers/hwtracing/coresight/coresight-ctcu-core.c
>> index da35d8b4d579..5782655a5f39 100644
>> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
>> @@ -46,16 +46,24 @@ DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
>> ? #define CTCU_ATID_REG_BIT(traceid)??? (traceid % 32)
>> ? #define CTCU_ATID_REG_SIZE??????? 0x10
>> ? #define CTCU_ETR0_ATID0??????????? 0xf8
>> +#define CTCU_ETR0_IRQCTRL??????? 0x6c
>> ? #define CTCU_ETR1_ATID0??????????? 0x108
>> +#define CTCU_ETR1_IRQCTRL??????? 0x70
>> ? static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
>> ????? {
>> -??????? .atid_offset??? = CTCU_ETR0_ATID0,
>> -??????? .port_num??? = 0,
>> +??????? .atid_offset??????? = CTCU_ETR0_ATID0,
>> +??????? .irq_ctrl_offset??? = CTCU_ETR0_IRQCTRL,
>> +??????? .irq_name??????? = "etr0",
>> +??????? .byte_cntr_name??????? = "byte-cntr0",
>> +??????? .port_num??????? = 0,
>> ????? },
>> ????? {
>> -??????? .atid_offset??? = CTCU_ETR1_ATID0,
>> -??????? .port_num??? = 1,
>> +??????? .atid_offset??????? = CTCU_ETR1_ATID0,
>> +??????? .irq_ctrl_offset??? = CTCU_ETR1_IRQCTRL,
>> +??????? .irq_name??????? = "etr1",
>> +??????? .byte_cntr_name??????? = "byte-cntr1",
>> +??????? .port_num??????? = 1,
>> ????? },
>> ? };
>> @@ -64,6 +72,69 @@ static const struct ctcu_config sa8775p_cfgs = {
>> ????? .num_etr_config??? = ARRAY_SIZE(sa8775p_etr_cfgs),
>> ? };
>> +static ssize_t byte_cntr_val_show(struct device *dev, struct 
>> device_attribute *attr,
>> +????????????????? char *buf)
>> +{
>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +??? int i, len = 0;
>> +
>> +??? for (i = 0; i < ETR_MAX_NUM; i++) {
>> +??????? if (drvdata->byte_cntr_data[i].irq_ctrl_offset)
>> +??????????? len += scnprintf(buf + len, PAGE_SIZE - len, "%u ",
>> +???????????????????? drvdata->byte_cntr_data[i].thresh_val);
>> +??? }
>> +
>> +??? len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
>> +
>> +??? return len;
>> +}
>> +
>> +static ssize_t byte_cntr_val_store(struct device *dev, struct 
>> device_attribute *attr,
>> +?????????????????? const char *buf, size_t size)
>> +{
>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +??? u32 thresh_vals[ETR_MAX_NUM] = { 0 };
>> +??? u32 irq_ctrl_offset;
>> +??? int num, i;
>> +
>> +??? num = sscanf(buf, "%i %i", &thresh_vals[0], &thresh_vals[1]);
>> +??? if (num <= 0 || num > ETR_MAX_NUM)
>> +??????? return -EINVAL;
>> +
>> +??? /* Threshold 0 disables the interruption. */
>> +??? guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
>> +??? for (i = 0; i < num; i++) {
>> +??????? /* A small threshold will result in a large number of 
>> interruptions */
>> +??????? if (thresh_vals[i] && thresh_vals[i] < 4096)
>> +??????????? return -EINVAL;
>> +
>> +??????? if (drvdata->byte_cntr_data[i].irq_ctrl_offset) {
>> +??????????? drvdata->byte_cntr_data[i].thresh_val = thresh_vals[i];
>> +??????????? irq_ctrl_offset = drvdata- 
>> >byte_cntr_data[i].irq_ctrl_offset;
>> +??????????? CS_UNLOCK(drvdata->base);
>> +??????????? writel_relaxed(thresh_vals[i], drvdata->base + 
>> irq_ctrl_offset);
>> +??????????? CS_LOCK(drvdata->base);
>> +??????? }
>> +??? }
>> +
>> +??? return size;
>> +}
>> +static DEVICE_ATTR_RW(byte_cntr_val);
>> +
>> +static struct attribute *ctcu_attrs[] = {
>> +??? &dev_attr_byte_cntr_val.attr,
>> +??? NULL,
>> +};
>> +
>> +static struct attribute_group ctcu_attr_grp = {
>> +??? .attrs = ctcu_attrs,
>> +};
>> +
>> +static const struct attribute_group *ctcu_attr_grps[] = {
>> +??? &ctcu_attr_grp,
>> +??? NULL,
>> +};
>> +
>> ? static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, 
>> u32 reg_offset,
>> ???????????????????????? u8 bit, bool enable)
>> ? {
>> @@ -122,7 +193,7 @@ static int __ctcu_set_etr_traceid(struct 
>> coresight_device *csdev, u8 traceid, in
>> ?? * Searching the sink device from helper's view in case there are 
>> multiple helper devices
>> ?? * connected to the sink device.
>> ?? */
>> -static int ctcu_get_active_port(struct coresight_device *sink, struct 
>> coresight_device *helper)
>> +int ctcu_get_active_port(struct coresight_device *sink, struct 
>> coresight_device *helper)
>> ? {
>> ????? struct coresight_platform_data *pdata = helper->pdata;
>> ????? int i;
>> @@ -160,6 +231,8 @@ static int ctcu_enable(struct coresight_device 
>> *csdev, enum cs_mode mode, void *
>> ? {
>> ????? struct coresight_path *path = (struct coresight_path *)data;
>> +??? ctcu_byte_cntr_start(csdev, path);
>> +
>> ????? return ctcu_set_etr_traceid(csdev, path, true);
>> ? }
>> @@ -167,6 +240,8 @@ static int ctcu_disable(struct coresight_device 
>> *csdev, void *data)
>> ? {
>> ????? struct coresight_path *path = (struct coresight_path *)data;
>> +??? ctcu_byte_cntr_stop(csdev, path);
>> +
>> ????? return ctcu_set_etr_traceid(csdev, path, false);
>> ? }
>> @@ -188,7 +263,7 @@ static int ctcu_probe(struct platform_device *pdev)
>> ????? const struct ctcu_config *cfgs;
>> ????? struct ctcu_drvdata *drvdata;
>> ????? void __iomem *base;
>> -??? int i;
>> +??? int ret, i;
>> ????? desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
>> ????? if (!desc.name)
>> @@ -217,7 +292,14 @@ static int ctcu_probe(struct platform_device *pdev)
>> ????????????? for (i = 0; i < cfgs->num_etr_config; i++) {
>> ????????????????? etr_cfg = &cfgs->etr_cfgs[i];
>> ????????????????? drvdata->atid_offset[i] = etr_cfg->atid_offset;
>> +??????????????? drvdata->byte_cntr_data[i].irq_name = etr_cfg->irq_name;
>> +??????????????? drvdata->byte_cntr_data[i].name = etr_cfg- 
>> >byte_cntr_name;
>> +??????????????? drvdata->byte_cntr_data[i].irq_ctrl_offset =
>> +??????????????????? etr_cfg->irq_ctrl_offset;
>> ????????????? }
>> +??????????? ret = ctcu_byte_cntr_init(dev, drvdata, cfgs- 
>> >num_etr_config);
>> +??????????? if (ret < 0)
>> +??????????????? dev_warn(dev, "Byte cntr init failed\n");
>> ????????? }
>> ????? }
>> @@ -229,6 +311,7 @@ static int ctcu_probe(struct platform_device *pdev)
>> ????? desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU;
>> ????? desc.pdata = pdata;
>> ????? desc.dev = dev;
>> +??? desc.groups = ctcu_attr_grps;
>> ????? desc.ops = &ctcu_ops;
>> ????? desc.access = CSDEV_ACCESS_IOMEM(base);
>> @@ -247,6 +330,7 @@ static void ctcu_remove(struct platform_device *pdev)
>> ? {
>> ????? struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
>> +??? ctcu_byte_cntr_remove(drvdata);
>> ????? coresight_unregister(drvdata->csdev);
>> ? }
>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/ 
>> hwtracing/coresight/coresight-ctcu.h
>> index e9594c38dd91..e38535c91090 100644
>> --- a/drivers/hwtracing/coresight/coresight-ctcu.h
>> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
>> @@ -5,6 +5,8 @@
>> ? #ifndef _CORESIGHT_CTCU_H
>> ? #define _CORESIGHT_CTCU_H
>> +#include <linux/cdev.h>
>> +
>> ? #include "coresight-trace-id.h"
>> ? /* Maximum number of supported ETR devices for a single CTCU. */
>> @@ -13,10 +15,16 @@
>> ? /**
>> ?? * struct ctcu_etr_config
>> ?? * @atid_offset:??? offset to the ATID0 Register.
>> - * @port_num:??????? in-port number of CTCU device that connected to 
>> ETR.
>> + * @irq_ctrl_offset:??? offset to the BYTECNTRVAL register.
>> + * @irq_name:??????? IRQ name in dt node.
>> + * @byte_cntr_name:??? name of the byte cntr device node.
>> + * @port_num:??????? in-port number of the CTCU device that connected 
>> to ETR.
>> ?? */
>> ? struct ctcu_etr_config {
>> ????? const u32 atid_offset;
>> +??? const u32 irq_ctrl_offset;
>> +??? const char *irq_name;
>> +??? const char *byte_cntr_name;
>> ????? const u32 port_num;
>> ? };
>> @@ -25,15 +33,64 @@ struct ctcu_config {
>> ????? int num_etr_config;
>> ? };
>> +/**
>> + * struct ctcu_byte_cntr
>> + * @c_dev:??????? cdev for byte_cntr.
>> + * @sink??????? csdev of sink device.
>> + * @enable:??????? indicates that byte_cntr function is enabled or not.
>> + * @read_active:??? indicates that byte-cntr node is opened or not.
>> + * @thresh_val:??????? threshold to trigger a interruption.
>> + * @total_size??????? total size of transferred data.
>> + * @byte_cntr_irq:??? IRQ number.
>> + * @irq_cnt:??????? IRQ count.
>> + * @wq:??????????? workqueue of reading ETR data.
>> + * @read_work:??????? work of reading ETR data.
>> + * @spin_lock:??????? spinlock of byte cntr data.
>> + * @r_offset:??????? offset of the pointer where reading begins.
>> + * @w_offset:??????? offset of the write pointer in the ETR buffer when
>> + *??????????? the byte cntr is stopped.
>> + * @irq_ctrl_offset:??? offset to the BYTECNTRVAL Register.
>> + * @name:??????? the name of byte cntr device node.
>> + * @irq_name:??????? IRQ name in DT.
>> + */
>> +struct ctcu_byte_cntr {
>> +??? struct cdev??????? c_dev;
>> +??? struct coresight_device??? *sink;
>> +??? bool??????????? enable;
>> +??? bool??????????? read_active;
>> +??? u32??????????? thresh_val;
>> +??? u64??????????? total_size;
>> +??? int??????????? byte_cntr_irq;
>> +??? atomic_t??????? irq_cnt;
>> +??? wait_queue_head_t??? wq;
>> +??? struct work_struct??? read_work;
>> +??? raw_spinlock_t??????? spin_lock;
>> +??? long??????????? r_offset;
>> +??? long??????????? w_offset;
>> +??? u32??????????? irq_ctrl_offset;
>> +??? const char??????? *name;
>> +??? const char??????? *irq_name;
>> +};
>> +
>> ? struct ctcu_drvdata {
>> ????? void __iomem??????? *base;
>> ????? struct clk??????? *apb_clk;
>> ????? struct device??????? *dev;
>> ????? struct coresight_device??? *csdev;
>> +??? struct ctcu_byte_cntr?? byte_cntr_data[ETR_MAX_NUM];
>> ????? raw_spinlock_t??????? spin_lock;
>> ????? u32??????????? atid_offset[ETR_MAX_NUM];
>> ????? /* refcnt for each traceid of each sink */
>> ????? u8??????????? traceid_refcnt[ETR_MAX_NUM] 
>> [CORESIGHT_TRACE_ID_RES_TOP];
>> ? };
>> +/* Generic functions */
>> +int ctcu_get_active_port(struct coresight_device *sink, struct 
>> coresight_device *helper);
>> +
>> +/* Byte-cntr functions */
>> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct 
>> coresight_path *path);
>> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct 
>> coresight_path *path);
>> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata 
>> *drvdata, int port_num);
>> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata);
>> +
>> ? #endif
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/ 
>> drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index ec636ab1fd75..5dc94e890927 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -1040,14 +1040,15 @@ static void tmc_free_etr_buf(struct etr_buf 
>> *etr_buf)
>> ?? * Returns: The size of the linear data available @pos, with *bufpp
>> ?? * updated to point to the buffer.
>> ?? */
>> -static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>> -??????????????????? u64 offset, size_t len, char **bufpp)
>> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>> +???????????????? u64 offset, size_t len, char **bufpp)
>> ? {
>> ????? /* Adjust the length to limit this transaction to end of buffer */
>> ????? len = (len < (etr_buf->size - offset)) ? len : etr_buf->size - 
>> offset;
>> ????? return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
>> ? }
>> +EXPORT_SYMBOL_GPL(tmc_etr_buf_get_data);
>> ? static inline s64
>> ? tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/ 
>> hwtracing/coresight/coresight-tmc.h
>> index baedb4dcfc3f..2fc77fd4ea25 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>> @@ -443,5 +443,7 @@ struct etr_buf *tmc_etr_get_buffer(struct 
>> coresight_device *csdev,
>> ???????????????????? enum cs_mode mode, void *data);
>> ? extern const struct attribute_group coresight_etr_group;
>> ? long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, 
>> size_t len,
>> +???????????????? char **bufpp);
>> ? #endif
> 



From dianders at chromium.org  Thu Mar 13 19:03:10 2025
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 13 Mar 2025 19:03:10 -0700
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <260393cc-614a-b5c1-0e04-8443e00a7991@huawei.com>
References: <20250307021811.46981-1-yangyicong@huawei.com> <20250307021811.46981-3-yangyicong@huawei.com>
 <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>
 <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com> <CAD=FV=Wy9-nDW-F+R1Aob6GOfP1Cnmr1gKkCO+WebA8ES7uu8A@mail.gmail.com>
 <260393cc-614a-b5c1-0e04-8443e00a7991@huawei.com>
Message-ID: <CAD=FV=XhMnGWAQ19n6_O2QTkXNu_+NkA+R=4X_w+-Vewpd55ng@mail.gmail.com>

Hi,

On Wed, Mar 12, 2025 at 12:48?AM Yicong Yang <yangyicong at huawei.com> wrote:
>
> >>>> +static int __init init_watchdog_freq_notifier(void)
> >>>> +{
> >>>> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
> >>>> +                                        CPUFREQ_POLICY_NOTIFIER);
> >>>> +}
> >>>> +core_initcall(init_watchdog_freq_notifier);
> >>>
> >>> I haven't dug into everything, but don't you have a potential blind
> >>> spot, though? What if the order is this:
> >>>
> >>> 1. hw_nmi_get_sample_period() is called
> >>> 2. cpufreq driver probes
> >>> 3. init_watchdog_freq_notifier() initcall runs
> >>>
> >>> Since the cpufreq driver proved before you registered for the
> >>> notifier, won't you miss the creation of the policy? Maybe instead of
> >>> registering for an initcall you should somehow trigger off the first
> >>> call to hw_nmi_get_sample_period() and register at that point in time?
> >>>
> >>
> >> for arm64 the watchdog_perf is registered after armv8 PMU driver's init,
> >> so the sequence is like:
> >>
> >> # core_initcall
> >> init_watchdog_freq_notifier()
> >> # device_initcall
> >> armv8_pmu_driver_init()
> >>   lockup_detector_retry_init()
> >>     schedule_work(&detector_work);
> >> # in detector work
> >> hw_nmi_get_sample_period() // notifier's already been registered
> >>
> >> so we'll always get the correct frequency, either by the cpufreq
> >> already registered or by the notifier which will update the
> >> frequency. Please correct me if I missed anything :)
> >
> > Hmm, OK. So this relies on the fact that because the
> > init_watchdog_freq_notifier() is at "core" level that it'll pretty
> > much init before any of the other things. This type of thing is always
> > a little fragile but I guess it's OK.
> >
> > What about if the order is different though? Again, I haven't traced
> > through it all, but I'm thinking:
> >
> > # core_initcall
> > init_watchdog_freq_notifier()
> > # device_initcall
> > <cpufreq driver policy is created>
> >
> > Now hardlockup_detector_perf_adjust_period() will be called before
> > armv8_pmu_driver_init(). Is that a problem?
>
> it doesn't matter, since in this situation:
>
> # device_initcall
> <cpufreq driver policy is created>
>   hardlockup_detector_perf_adjust_period()
>     if (!event) // armv8_pmu_driver_init() not called, not event created
>       return;
> # later after armv8_pmu_driver_init()
> hw_nmi_get_sample_period() // since cpufreq already been registered, we can
>                            // get the accurate cpufreq

Got it. Sorry for asking the dumb questions--I didn't have time to dig
through the code earlier this week. Yeah, looks like it should be OK.


> > I guess even worse would be if async probe was on and the cpufreq
> > driver and PMU driver were running at the same time?
> >
>
> I think there're 2 cases here:
> 1) cpufreq initialized before hw_nmi_get_sample_period() called, in which
>    case the cpufreq is accurate when create the event
> 2) hw_nmi_get_sample_period() called before cpufreq driver's initialized,
>    in which case we rely on the notifier call to adjust the event's period
>
> May need further check to see if there's any race window here, but the worst
> case will be using the inaccurate cpufreq (5GHz) for calculating the period.

OK, sure. _Maybe_ there could be some small race if these two things
are happening at exactly the same time on two different cores:

core 1:
* lockup_detector_delay_init()
* watchdog_hardlockup_probe()
* hardlockup_detector_event_create()
* hw_nmi_get_sample_period()
* No cpufreq driver, so returns SAFE_MAX_CPU_FREQ

core 2:
* cpufreq driver probes + policy is created
* "event" hasn't been created yet, so your new code is a no-op

core 1:
* event gets created based on SAFE_MAX_CPU_FREQ.

Did I get that right?

That doesn't feel _completely_ impossible especially since
lockup_detector_delay_init() is already running on a separate
workqueue. As you said, though, the worst case is it looks like we'll
just end up with how things were before your patch series.

In any case, I guess it's pretty unlikely, but maybe it wouldn't be
very hard to add a mutex in there? It doesn't feel like that would add
much overhead...

-Doug


From nunodasneves at linux.microsoft.com  Thu Mar 13 19:15:39 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Thu, 13 Mar 2025 19:15:39 -0700
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB4157C3F431CD26EDA05E4AD4D4D32@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157C3F431CD26EDA05E4AD4D4D32@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <adfdd111-f838-48a4-b77d-4207f3ab9976@linux.microsoft.com>

On 3/13/2025 9:43 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
>>
> 
> I've done a partial review of the code in this patch.  See comments inline
> as usual.
> 
> I'd like to still review most of the code in mshv_root_main.c, and maybe
> some of mshv_synic.c and include/uapi/linux/mshv.c. I'll send a separate
> email with those comments when I complete them. The patch is huge, so
> I'm breaking my review comments into two parts.
> 
> I've glanced through mshv_eventfd.c, mshv_eventfd.h, and mshv_irq.c,
> but I don't have enough knowledge/expertise in these areas to add any
> useful comments, so I'm not planning to review them further.
> 
Thanks for taking a look. Just so you know, I was getting ready to post v6 of
this patchset when I saw this email. So not all the comments will be addressed
in the next version, but I've noted them and I will keep an eye out for the
second part if you send it after v6 is posted.

<snip>
>> diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst
>> b/Documentation/userspace-api/ioctl/ioctl-number.rst
>> index 6d1465315df3..66dcfaae698b 100644
>> --- a/Documentation/userspace-api/ioctl/ioctl-number.rst
>> +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
>> @@ -370,6 +370,8 @@ Code  Seq#    Include File                                           Comments
>>  0xB7  all    uapi/linux/remoteproc_cdev.h                            <mailto:linux-
>> remoteproc at vger.kernel.org>
>>  0xB7  all    uapi/linux/nsfs.h                                       <mailto:Andrei Vagin
>> <avagin at openvz.org>>
>>  0xB8  01-02  uapi/misc/mrvl_cn10k_dpi.h                              Marvell CN10K DPI driver
>> +0xB8  all    uapi/linux/mshv.h                                       Microsoft Hyper-V /dev/mshv driver
> 
> Hmmm. Doesn't this mean that the mshv ioctls overlap with the Marvell
> CN10K DPI ioctls? Is that intentional? I thought the goal of the central
> registry in ioctl-number.rst is to avoid overlap.
> 
Yes, they overlap. In practice it really doesn't matter IMO - IOCTL numbers
are only interpreted by the driver of the device that the ioctl() syscall
is made on.

I believe the whole scheme to generate unique IOCTL numbers and try not to
overlap them was is some case I'm not familiar with - something like
multiple drivers handling IOCTLs on the same device FD? And maybe it's handy
in debugging if you see an IOCTL number in isolation and want to know where
it comes from?

On a practical note, we have been using this IOCTL range for some time
in other upstream code like our userspace rust library which interfaces with
this driver (https://github.com/rust-vmm/mshv). So it would also be nice to
keep that all working as much as possible with the kernel code that is on
this mailing list.

<snip>>> +#endif /* _MSHV_H */
>> diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
>> new file mode 100644
>> index 000000000000..d97631dcbee1
>> --- /dev/null
>> +++ b/drivers/hv/mshv_common.c
>> @@ -0,0 +1,161 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2024, Microsoft Corporation.
>> + *
>> + * This file contains functions that are called from one or more modules: ROOT,
>> + * DIAG, or VTL. If any of these modules are configured to build, this file is
> 
> What are the DIAG and VTL modules?  I see only a root module in the Makefile.
> 
Ah, yep, they are not in this patchset but will follow. I can remove thereferences to them here, and make this comment future tense: "functions that WILL
be called from one or more modules".

<snip>>> +
>> +struct mshv_vp {
>> +	u32 vp_index;
>> +	struct mshv_partition *vp_partition;
>> +	struct mutex vp_mutex;
>> +	struct hv_vp_register_page *vp_register_page;
>> +	struct hv_message *vp_intercept_msg_page;
>> +	void *vp_ghcb_page;
>> +	struct hv_stats_page *vp_stats_pages[2];
>> +	struct {
>> +		atomic64_t vp_signaled_count;
>> +		struct {
>> +			u64 intercept_suspend: 1;
>> +			u64 root_sched_blocked: 1; /* root scheduler only */
>> +			u64 root_sched_dispatched: 1; /* root scheduler only */
>> +			u64 reserved: 62;
> 
> Hmmm.  This looks like 65 bits allocated in a u64.
> 
Indeed it is, good catch

>> +
>> +	/*
>> +	 * Since MSHV does not support more than one async hypercall in flight
> 
> Wording is a bit messed up.  Drop the "Since"?
> 
Yep, thanks

>> +	 * for a single partition. Thus, it is okay to define per partition
>> +	 * async hypercall status.
>> +	 */
<snip>
>> +
>> +extern struct mshv_root mshv_root;
>> +extern enum hv_scheduler_type hv_scheduler_type;
>> +extern u8 __percpu **hv_synic_eventring_tail;
> 
> Per comments on an earlier patch, the __percpu is in the wrong place.
> 
Thanks, will fix here too.
<snip>>> +int hv_call_create_partition(u64 flags,
>> +			     struct hv_partition_creation_properties creation_properties,
>> +			     union hv_partition_isolation_properties isolation_properties,
>> +			     u64 *partition_id)
>> +{
>> +	struct hv_input_create_partition *input;
>> +	struct hv_output_create_partition *output;
>> +	u64 status;
>> +	int ret;
>> +	unsigned long irq_flags;
>> +
>> +	do {
>> +		local_irq_save(irq_flags);
>> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
>> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
>> +
>> +		memset(input, 0, sizeof(*input));
>> +		input->flags = flags;
>> +		input->compatibility_version = HV_COMPATIBILITY_21_H2;
>> +
>> +		memcpy(&input->partition_creation_properties, &creation_properties,
>> +		       sizeof(creation_properties));
> 
> This is an example of a generic question/concern that occurs in several places. By
> doing a memcpy into the hypercall input, the assumption is that the creation
> properties supplied by the caller have zeros in all the reserved or unused fields.
> Is that a valid assumption?
> 
When the entire struct is provided as a function parameter, I think it's a valid
assumption that that struct is initialized correctly by the caller.

The alternative (taking it to an extreme, in my opinion) is that we go through
each field in the parameters and assign them all individually, which could be quite
a lot of fields. E.g. going through all the bits in these structs with 60+ bitfields
and re-setting them here to be sure the reserved bits are 0.

>> +
>> +		memcpy(&input->isolation_properties, &isolation_properties,
>> +		       sizeof(isolation_properties));
>> +
>> +		status = hv_do_hypercall(HVCALL_CREATE_PARTITION,
>> +					 input, output);
<snip>>> +/* Ask the hypervisor to map guest ram pages or the guest mmio space */
>> +static int hv_do_map_gpa_hcall(u64 partition_id, u64 gfn, u64 page_struct_count,
>> +			       u32 flags, struct page **pages, u64 mmio_spa)
>> +{
>> +	struct hv_input_map_gpa_pages *input_page;
>> +	u64 status, *pfnlist;
>> +	unsigned long irq_flags, large_shift = 0;
>> +	int ret = 0, done = 0;
>> +	u64 page_count = page_struct_count;
>> +
>> +	if (page_count == 0 || (pages && mmio_spa))
>> +		return -EINVAL;
>> +
>> +	if (flags & HV_MAP_GPA_LARGE_PAGE) {
>> +		if (mmio_spa)
>> +			return -EINVAL;
>> +
>> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
>> +			return -EINVAL;
>> +
>> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
>> +		page_count >>= large_shift;
>> +	}
>> +
>> +	while (done < page_count) {
>> +		ulong i, completed, remain = page_count - done;
>> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
>> +
>> +		local_irq_save(irq_flags);
>> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
>> +
>> +		input_page->target_partition_id = partition_id;
>> +		input_page->target_gpa_base = gfn + (done << large_shift);
>> +		input_page->map_flags = flags;
>> +		pfnlist = input_page->source_gpa_page_list;
>> +
>> +		for (i = 0; i < rep_count; i++)
>> +			if (flags & HV_MAP_GPA_NO_ACCESS) {
>> +				pfnlist[i] = 0;
>> +			} else if (pages) {
>> +				u64 index = (done + i) << large_shift;
>> +
>> +				if (index >= page_struct_count) {
> 
> Can this test ever be true?  It looks like the pages array must
> have space for each 4K page even if mapping in 2Meg granularity.> But only every 512th entry in the pages array is looked at
> (which seems a little weird). But based on how rep_count is set up,
> I don't see how the algorithm could go past the end of the pages
> array.
> 
I don't think the test can actually be true - IIRC I wrote it as a kind
of "is my math correct?" sanity check, and there was a pr_err() or a
WARN()here in a previous iteration of the code.

The large page list is a bit weird - When we allocate the large pages in
the kernel, we get all the (4K) page structs for that range back from the
kernel, and we hang onto them. When mapping the large pages into the
hypervisor we just have to map the PFN of the first page of each 2M page,
hence the skipping.

Now I'm thinking about it again, maybe we can discard most of the 4K page
structs the kernel gives back and keep it as a packed array of the "head"
pages which are all we really need (and then also simplify this mapping
code and save some memory).

The current code was just the simplest way to add the large page
functionality on top of what we already had, but looks like it could
probably be improved.

>> +					ret = -EINVAL;
>> +					break;
>> +				}
>> +				pfnlist[i] = page_to_pfn(pages[index]);
>> +			} else {
>> +				pfnlist[i] = mmio_spa + done + i;
>> +			}
>> +		if (ret)
>> +			break;
> 
> This test could also go away if the ret = -EINVAL error above can't
> happen.
> 
Ack
<snip>
>> +
>> +/* Ask the hypervisor to map guest mmio space */
>> +int hv_call_map_mmio_pages(u64 partition_id, u64 gfn, u64 mmio_spa, u64 numpgs)
>> +{
>> +	int i;
>> +	u32 flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE |
>> +		    HV_MAP_GPA_NOT_CACHED;
>> +
>> +	for (i = 0; i < numpgs; i++)
>> +		if (page_is_ram(mmio_spa + i))
> 
> FWIW, doing this check one-page-at-a-time is somewhat expensive if numpgs
> is large.  The underlying data structures should support doing a single range
> check, but I haven't looked at whether functions exist to do such a range check.
> 
Indeed - I'll make a note to investigate, thanks.

>> +			return -EINVAL;
>> +
>> +	return hv_do_map_gpa_hcall(partition_id, gfn, numpgs, flags, NULL,
>> +				   mmio_spa);
>> +}
>> +
>> +int hv_call_unmap_gpa_pages(u64 partition_id, u64 gfn, u64 page_count_4k,
>> +			    u32 flags)
>> +{
>> +	struct hv_input_unmap_gpa_pages *input_page;
>> +	u64 status, page_count = page_count_4k;
>> +	unsigned long irq_flags, large_shift = 0;
>> +	int ret = 0, done = 0;
>> +
>> +	if (page_count == 0)
>> +		return -EINVAL;
>> +
>> +	if (flags & HV_UNMAP_GPA_LARGE_PAGE) {
>> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
>> +			return -EINVAL;
>> +
>> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
>> +		page_count >>= large_shift;
>> +	}
>> +
>> +	while (done < page_count) {
>> +		ulong completed, remain = page_count - done;
>> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
> 
> Using HV_MAP_GPA_BATCH_SIZE seems a little weird here since there's
> no input array and hence no constraint based on keeping input args to
> just one page. Is it being used as an arbitrary limit so the rep_count
> passed to the hypercall isn't "too large" for some definition of "too large"?
> If that's the case, perhaps a separate #define and a comment would
> make sense. I kept trying to figure out how the batch size for unmap was
> related to the map hypercall, and I don't think there is any relationship.
> 
I think batching this was intentional so that we can be sure to re-enable
interrupts periodically when unmapping an entire VM's worth of memory. That
said, as you know the hypercall will return if it takes longer than a certain
amount of time so I guess that is "built-in" in some sense.

I think keeping the batching, but #defining a specific value for unmap as you
suggest is a good idea.

I'd be inclined to use a similar number (something like 512).

>> +
>> +		local_irq_save(irq_flags);
>> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
>> +
>> +		input_page->target_partition_id = partition_id;
>> +		input_page->target_gpa_base = gfn + (done << large_shift);
>> +		input_page->unmap_flags = flags;
>> +		status = hv_do_rep_hypercall(HVCALL_UNMAP_GPA_PAGES, rep_count,
>> +					     0, input_page, NULL);
>> +		local_irq_restore(irq_flags);
>> +
>> +		completed = hv_repcomp(status);
>> +		if (!hv_result_success(status)) {
>> +			ret = hv_result_to_errno(status);
>> +			break;
>> +		}
>> +
>> +		done += completed;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
>> +				  union hv_gpa_page_access_state_flags state_flags,
>> +				  int *written_total,
>> +				  union hv_gpa_page_access_state *states)
>> +{
>> +	struct hv_input_get_gpa_pages_access_state *input_page;
>> +	union hv_gpa_page_access_state *output_page;
>> +	int completed = 0;
>> +	unsigned long remaining = count;
>> +	int rep_count, i;
>> +	u64 status;
>> +	unsigned long flags;
>> +
>> +	*written_total = 0;
>> +	while (remaining) {
>> +		local_irq_save(flags);
>> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
>> +		output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
>> +
>> +		input_page->partition_id = partition_id;
>> +		input_page->hv_gpa_page_number = gpa_base_pfn + *written_total;
>> +		input_page->flags = state_flags;
>> +		rep_count = min(remaining, HV_GET_GPA_ACCESS_STATES_BATCH_SIZE);
>> +
>> +		status = hv_do_rep_hypercall(HVCALL_GET_GPA_PAGES_ACCESS_STATES, rep_count,
>> +					     0, input_page, output_page);
>> +		if (!hv_result_success(status)) {
>> +			local_irq_restore(flags);
>> +			break;
>> +		}
>> +		completed = hv_repcomp(status);
>> +		for (i = 0; i < completed; ++i)
>> +			states[i].as_uint8 = output_page[i].as_uint8;
>> +
>> +		states += completed;
>> +		*written_total += completed;
>> +		remaining -= completed;
>> +		local_irq_restore(flags);
> 
> FWIW, this local_irq_restore() could move up three lines to before the progress
> accounting is done.
> 
Good point, thanks.
<snip>
>> +		memset(input, 0, sizeof(*input));
>> +		memset(output, 0, sizeof(*output));
> 
> Why is the output set to zero?  I would think Hyper-V is responsible for
> ensuring that the output is properly populated, with unused fields/areas
> set to zero.
> 
Overabundance of caution, I think! It doesn't need to be zeroed AFAIK.

I recently did a some cleanup (in our internal tree) to make sure we are
memset()ing the input and *not* memset()ing the output everywhere, but
it didn't make it into this series. There are a few more places like this.

<snip>
>> +
>> +int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
>> +			 /* Choose between pages and bytes */
>> +			 struct hv_vp_state_data state_data, u64 page_count,
> 
> The size of "struct hv_vp_state_data" looks to be 24 bytes (3 64-bit words).
> Is there a reason to pass this by value instead of as a pointer? I guess it works
> like this, but it seems atypical.
> 
No particular reason. I'm guessing the compiler will pass this by copying it to this
function's stack frame - 24 bytes is still rather small so I don't think it's an issue.

I'm also under the impression the compiler may optimize this to a pointer since it is
not modified?

I usually only pass a pointer (for read-only values) when it's something really
large that I *definitely* don't want to be copied on the stack (like, 100 bytes?).
In that case I probably only have a pointer to vmalloc'd/kalloc()'d memory anyway.

<snip>
>> +	local_irq_save(flags);
>> +	status = hv_do_fast_hypercall8(HVCALL_CLEAR_VIRTUAL_INTERRUPT,
>> +				       partition_id) &
>> +			HV_HYPERCALL_RESULT_MASK;
> 
> This "anding" with HV_HYPERCALL_RESULT_MASK should be removed.
> 
Yep, thanks.

>> +	local_irq_restore(flags);
> 
> The irq save/restore isn't needed here since this is a fast hypercall and
> per-cpu arg memory is not used.
> 
Agreed, will remove these for the fast hypercall sites.

<snip>
>> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
>> +		status = hv_do_hypercall(HVCALL_CREATE_PORT, input, NULL) &
>> +			 HV_HYPERCALL_RESULT_MASK;
> 
> Use the hv_status checking macros instead of and'ing with
> HV_HYPERCALL_RESULT_MASK.
> 
Thanks, these need a bit of cleanup.

<snip>
>> +	status = hv_do_fast_hypercall16(HVCALL_DELETE_PORT,
>> +					input.as_uint64[0],
>> +					input.as_uint64[1]) &
>> +			HV_HYPERCALL_RESULT_MASK;
>> +	local_irq_restore(flags);
> 
> Same a previous comment about and'ing.  And irq save/restore
> isn't needed.
> 
ack

<snip>
>> +		status = hv_do_hypercall(HVCALL_CONNECT_PORT, input, NULL) &
>> +			 HV_HYPERCALL_RESULT_MASK;
> 
> Same here.  Use hv_* macros.
> 
ack

<snip>
>> +	status = hv_do_fast_hypercall16(HVCALL_DISCONNECT_PORT,
>> +					input.as_uint64[0],
>> +					input.as_uint64[1]) &
>> +			HV_HYPERCALL_RESULT_MASK;
>> +	local_irq_restore(flags);
> 
> Same as above.
> 
ack

<snip>
>> +	local_irq_save(flags);
>> +	input.sint_index = sint_index;
>> +	status = hv_do_fast_hypercall8(HVCALL_NOTIFY_PORT_RING_EMPTY,
>> +				       input.as_uint64) &
>> +		 HV_HYPERCALL_RESULT_MASK;
>> +	local_irq_restore(flags);
> 
> Same as above.
> 
ack, and I'll double check we don't have other fast hypercall sites doing this

<snip>>> +		/*
>> +		 * This is required to make sure that reserved field is set to
>> +		 * zero, because MSHV has a check to make sure reserved bits are
>> +		 * set to zero.
>> +		 */
> 
> Is this comment about checking reserved bits unique to this hypercall? If not, it
> seems a little odd to see this comment here, but not other places where the input
> is zero'ed.
> 
I agree the comment isn't necessary - memset()ing the input to zero should be the
default policy. I'll remove it.

>> +		memset(input_page, 0, sizeof(*input_page));
>> +		/* Only set the partition id if you are making the pages
>> +		 * exclusive
>> +		 */
>> +		if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE)
>> +			input_page->partition_id = partition_id;
>> +		input_page->flags = flags;
>> +		input_page->host_access = host_access;
>> +
>> +		for (i = 0; i < rep_count; i++) {
>> +			u64 index = (done + i) << large_shift;
>> +
>> +			if (index >= page_struct_count)
>> +				return -EINVAL;
> 
> Can this test ever be true?
> 
See above in hv_do_map_gpa_hcall(), it's more of a sanity check or assert.

>> +
>> +			input_page->spa_page_list[i] =
>> +						page_to_pfn(pages[index]);
> 
> When large_shift is non-zero, it seems weird to be skipping over most
> of the entries in the "pages" array.  But maybe there's a reason for that.
> 
See above where we do the same thing in hv_do_map_gpa_hcall(). The hypervisor
only needs to see the "head" pages - the GPAs of the 2MB pages.

>> +		}
>> +
>> +		status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
>> +					     NULL);
>> +		local_irq_restore(irq_flags);
>> +
>> +		completed = hv_repcomp(status);
>> +
>> +		if (!hv_result_success(status))
>> +			return hv_result_to_errno(status);
>> +
>> +		done += completed;
>> +	}
>> +
>> +	return 0;
>> +}
> 
> [snip the rest of the patch that I haven't reviewed yet]
> 
> Michael



From dianders at chromium.org  Thu Mar 13 19:27:46 2025
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 13 Mar 2025 19:27:46 -0700
Subject: [PATCH v8 06/13] drm/bridge: analogix_dp: Add support to get
 panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-7-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com> <20250310104114.2608063-7-damon.ding@rock-chips.com>
Message-ID: <CAD=FV=V0Q5v6hcEFJqMfhCSQ80ki5SQRmrXvyeGCOQiFsXc28A@mail.gmail.com>

Hi,

On Mon, Mar 10, 2025 at 3:42?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>
> The main modification is moving the DP AUX initialization from function
> analogix_dp_bind() to analogix_dp_probe(). In order to get the EDID of
> eDP panel during probing, it is also needed to advance PM operations to
> ensure that eDP controller and phy are prepared for AUX transmission.
>
> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
>
> ---
>
> Changes in v4:
> - Use done_probing() to call drm_of_find_panel_or_bridge() and
>   component_add() when getting panel from the DP AUX bus
>
> Changes in v5:
> - Advance PM operations to make eDP AUX work well
>
> Changes in v6:
> - Use devm_pm_runtime_enable() instead of devm_add_action_or_reset()
> - Add a new function analogix_dp_remove() to ensure symmetry for PM
>   operations
>
> Changes in v7:
> - Fix the misspelling of word 'operations' in commit message
> - Remove the check related to CONFIG_PM
> - Remove the unnecessary call to pm_runtime_dont_use_autosuspend() if
>   devm_pm_runtime_enable() fails
> - Remove unnecessary function analogix_dp_remove()
> - Add new function analogix_dpaux_wait_hpd_asserted()
>
> Changes in v8:
> - Move the addition of the analogix_dpaux_wait_hpd_asserted() to the
>   other patch
> ---
>  .../drm/bridge/analogix/analogix_dp_core.c    | 20 ++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From dianders at chromium.org  Thu Mar 13 19:27:57 2025
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 13 Mar 2025 19:27:57 -0700
Subject: [PATCH v8 08/13] drm/rockchip: analogix_dp: Add support to get
 panel from the DP AUX bus
In-Reply-To: <20250310104114.2608063-9-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com> <20250310104114.2608063-9-damon.ding@rock-chips.com>
Message-ID: <CAD=FV=XYt894pPyvRxHAe1LjCXEorzB3xBkAKZzE6Fntfac5GQ@mail.gmail.com>

Hi,

On Mon, Mar 10, 2025 at 3:42?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>
> Move drm_of_find_panel_or_bridge() a little later and combine it with
> component_add() into a new function rockchip_dp_link_panel(). The function
> will serve as done_probing() callback of devm_of_dp_aux_populate_bus(),
> aiding to support for obtaining the eDP panel via the DP AUX bus.
>
> If failed to get the panel from the DP AUX bus, it will then try the other
> way to get panel information through the platform bus.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
>
> ---
>
> Changes in v4:
> - Use done_probing() to call drm_of_find_panel_or_bridge() and
>   component_add() when getting panel from the DP AUX bus
>
> Changes in v5:
> - Use the functions exported by the Analogix side to get the pointers of
>   struct analogix_dp_plat_data and struct drm_dp_aux.
> - Use dev_err() instead of drm_err() in rockchip_dp_poweron().
>
> Changes in v6:
> - Keep drm_err() in rockchip_dp_poweron()
> - Pass 'dp' in drm_...() rather than 'dp->drm_dev'
>
> Changes in v7:
> - Include the drm_dp_aux_bus.h for devm_of_dp_aux_populate_bus()
> - Use dev_err_probe() for the return value check of
>   devm_of_dp_aux_populate_bus()
> - Select DRM_DISPLAY_DP_AUX_BUS if ROCKCHIP_ANALOGIX_DP
> - Restore the error check for drm_of_find_panel_or_bridge() which was
>   removed by mistake
>
> Changes in v8:
> - Add comments when drm_of_find_panel_or_bridge() returns -ENODEV
> - Remove some redundant return cases
> - Add comments when devm_of_dp_aux_populate_bus() returns -ENODEV
> ---
>  drivers/gpu/drm/rockchip/Kconfig              |  1 +
>  .../gpu/drm/rockchip/analogix_dp-rockchip.c   | 42 +++++++++++++++----
>  2 files changed, 34 insertions(+), 9 deletions(-)

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From dianders at chromium.org  Thu Mar 13 19:27:51 2025
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 13 Mar 2025 19:27:51 -0700
Subject: [PATCH v8 07/13] drm/bridge: analogix_dp: Add support for &drm_dp_aux.wait_hpd_asserted()
In-Reply-To: <20250310104114.2608063-8-damon.ding@rock-chips.com>
References: <20250310104114.2608063-1-damon.ding@rock-chips.com> <20250310104114.2608063-8-damon.ding@rock-chips.com>
Message-ID: <CAD=FV=XigZ7k9ZmyT8wEeJKB79ef4ut7XrKdmXGqLbwdbxwe_w@mail.gmail.com>

Hi,

On Mon, Mar 10, 2025 at 3:42?AM Damon Ding <damon.ding at rock-chips.com> wrote:
>
> Add analogix_dpaux_wait_hpd_asserted() to help confirm the HPD state
> before doing AUX transfers.
>
> Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
> ---
>  .../drm/bridge/analogix/analogix_dp_core.c    | 21 +++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 2b76a9cf3bcb..b7e143b3ff75 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1548,6 +1548,26 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
>         return ret;
>  }
>
> +static int analogix_dpaux_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
> +{
> +       struct analogix_dp_device *dp = to_dp(aux);
> +       int val;
> +       int ret;
> +
> +       if (dp->force_hpd)
> +               return 0;

As mentioned previously [1], it's _possible_ that this should have a
delay like we had in sn65dsi86, though maybe that was to deal with
legacy device trees? It's been a while. Oh, I remember. It's because
even if HPD was hooked up to the controller like it's supposed to be
we don't actually implement HPD in the driver for the eDP controller
(long story). ...so we worked around that with a delay.

Right, so your code looks correct. :-)

[1] https://lore.kernel.org/r/CAD=FV=WoigDDTG6wTK0smsxASVfK5BzzW6KNpKWq97v4GAgvmw at mail.gmail.com

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From mhklinux at outlook.com  Thu Mar 13 20:27:59 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Fri, 14 Mar 2025 03:27:59 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <adfdd111-f838-48a4-b77d-4207f3ab9976@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157C3F431CD26EDA05E4AD4D4D32@SN6PR02MB4157.namprd02.prod.outlook.com>
 <adfdd111-f838-48a4-b77d-4207f3ab9976@linux.microsoft.com>
Message-ID: <SN6PR02MB41574CEB28BBC338EFBAE624D4D22@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Thursday, March 13, 2025 7:16 PM
> 
> On 3/13/2025 9:43 AM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday,
> February 26, 2025 3:08 PM
> >>
> >
> > I've done a partial review of the code in this patch.  See comments inline
> > as usual.
> >
> > I'd like to still review most of the code in mshv_root_main.c, and maybe
> > some of mshv_synic.c and include/uapi/linux/mshv.c. I'll send a separate
> > email with those comments when I complete them. The patch is huge, so
> > I'm breaking my review comments into two parts.
> >
> > I've glanced through mshv_eventfd.c, mshv_eventfd.h, and mshv_irq.c,
> > but I don't have enough knowledge/expertise in these areas to add any
> > useful comments, so I'm not planning to review them further.
> >
> Thanks for taking a look. Just so you know, I was getting ready to post v6 of
> this patchset when I saw this email. So not all the comments will be addressed
> in the next version, but I've noted them and I will keep an eye out for the
> second part if you send it after v6 is posted.

That's fine.

> 
> <snip>
> >> diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst
> >> b/Documentation/userspace-api/ioctl/ioctl-number.rst
> >> index 6d1465315df3..66dcfaae698b 100644
> >> --- a/Documentation/userspace-api/ioctl/ioctl-number.rst
> >> +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
> >> @@ -370,6 +370,8 @@ Code  Seq#    Include File                                           Comments
> >>  0xB7  all    uapi/linux/remoteproc_cdev.h                            <mailto:linux-
> >> remoteproc at vger.kernel.org>
> >>  0xB7  all    uapi/linux/nsfs.h                                       <mailto:Andrei Vagin
> >> <avagin at openvz.org>>
> >>  0xB8  01-02  uapi/misc/mrvl_cn10k_dpi.h                              Marvell CN10K DPI driver
> >> +0xB8  all    uapi/linux/mshv.h                                       Microsoft Hyper-V /dev/mshv driver
> >
> > Hmmm. Doesn't this mean that the mshv ioctls overlap with the Marvell
> > CN10K DPI ioctls? Is that intentional? I thought the goal of the central
> > registry in ioctl-number.rst is to avoid overlap.
> >
> Yes, they overlap. In practice it really doesn't matter IMO - IOCTL numbers
> are only interpreted by the driver of the device that the ioctl() syscall
> is made on.
> 
> I believe the whole scheme to generate unique IOCTL numbers and try not to
> overlap them was is some case I'm not familiar with - something like
> multiple drivers handling IOCTLs on the same device FD? And maybe it's handy
> in debugging if you see an IOCTL number in isolation and want to know where
> it comes from?

Yes, I think the debugging aspect is one that is mentioned in the text in
ioctl-number.rst. For example, maybe you want to filter the ioctl() system call
based on a particular ioctl value.

> 
> On a practical note, we have been using this IOCTL range for some time
> in other upstream code like our userspace rust library which interfaces with
> this driver (https://github.com/rust-vmm/mshv). So it would also be nice to
> keep that all working as much as possible with the kernel code that is on
> this mailing list.

I can see that having to change the ioctl values could be a pain. And apparently
there are already some historical overlaps. Also I saw that later in Patch 10 where
the mshv ioctls are defined, you have some overlaps just within the mshv space.
I don't really like the idea of having overlaps, either within the mshv space, or
with other drivers.  Doing a transition to non-overlapping values would probably
mean the driver having to accept both the "old" and "new" values for a while
until the rust library can be updated and deployed copies using the old values
go away.  It could be done in a relatively seamless fashion, but I can't really
make a strong argument that it would be worth the hassle.

> 
> <snip>>> +#endif /* _MSHV_H */
> >> diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
> >> new file mode 100644
> >> index 000000000000..d97631dcbee1
> >> --- /dev/null
> >> +++ b/drivers/hv/mshv_common.c
> >> @@ -0,0 +1,161 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (c) 2024, Microsoft Corporation.
> >> + *
> >> + * This file contains functions that are called from one or more modules: ROOT,
> >> + * DIAG, or VTL. If any of these modules are configured to build, this file is
> >
> > What are the DIAG and VTL modules?  I see only a root module in the Makefile.
> >
> Ah, yep, they are not in this patchset but will follow. I can remove thereferences to them
> here, and make this comment future tense: "functions that WILL
> be called from one or more modules".
> 
> <snip>>> +
> >> +struct mshv_vp {
> >> +	u32 vp_index;
> >> +	struct mshv_partition *vp_partition;
> >> +	struct mutex vp_mutex;
> >> +	struct hv_vp_register_page *vp_register_page;
> >> +	struct hv_message *vp_intercept_msg_page;
> >> +	void *vp_ghcb_page;
> >> +	struct hv_stats_page *vp_stats_pages[2];
> >> +	struct {
> >> +		atomic64_t vp_signaled_count;
> >> +		struct {
> >> +			u64 intercept_suspend: 1;
> >> +			u64 root_sched_blocked: 1; /* root scheduler only */
> >> +			u64 root_sched_dispatched: 1; /* root scheduler only */
> >> +			u64 reserved: 62;
> >
> > Hmmm.  This looks like 65 bits allocated in a u64.
> >
> Indeed it is, good catch
> 
> >> +
> >> +	/*
> >> +	 * Since MSHV does not support more than one async hypercall in flight
> >
> > Wording is a bit messed up.  Drop the "Since"?
> >
> Yep, thanks
> 
> >> +	 * for a single partition. Thus, it is okay to define per partition
> >> +	 * async hypercall status.
> >> +	 */
> <snip>
> >> +
> >> +extern struct mshv_root mshv_root;
> >> +extern enum hv_scheduler_type hv_scheduler_type;
> >> +extern u8 __percpu **hv_synic_eventring_tail;
> >
> > Per comments on an earlier patch, the __percpu is in the wrong place.
> >
> Thanks, will fix here too.
> <snip>>> +int hv_call_create_partition(u64 flags,
> >> +			     struct hv_partition_creation_properties creation_properties,
> >> +			     union hv_partition_isolation_properties isolation_properties,
> >> +			     u64 *partition_id)
> >> +{
> >> +	struct hv_input_create_partition *input;
> >> +	struct hv_output_create_partition *output;
> >> +	u64 status;
> >> +	int ret;
> >> +	unsigned long irq_flags;
> >> +
> >> +	do {
> >> +		local_irq_save(irq_flags);
> >> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> >> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> >> +
> >> +		memset(input, 0, sizeof(*input));
> >> +		input->flags = flags;
> >> +		input->compatibility_version = HV_COMPATIBILITY_21_H2;
> >> +
> >> +		memcpy(&input->partition_creation_properties, &creation_properties,
> >> +		       sizeof(creation_properties));
> >
> > This is an example of a generic question/concern that occurs in several places. By
> > doing a memcpy into the hypercall input, the assumption is that the creation
> > properties supplied by the caller have zeros in all the reserved or unused fields.
> > Is that a valid assumption?
> >
> When the entire struct is provided as a function parameter, I think it's a valid
> assumption that that struct is initialized correctly by the caller.
> 
> The alternative (taking it to an extreme, in my opinion) is that we go through
> each field in the parameters and assign them all individually, which could be quite
> a lot of fields. E.g. going through all the bits in these structs with 60+ bitfields
> and re-setting them here to be sure the reserved bits are 0.

Agreed -- I would not advocate the extreme alternative.  But perhaps the
requirement on the caller to correctly initialize all the memory should
be made more explicit in the cases where that's true.

> 
> >> +
> >> +		memcpy(&input->isolation_properties, &isolation_properties,
> >> +		       sizeof(isolation_properties));
> >> +
> >> +		status = hv_do_hypercall(HVCALL_CREATE_PARTITION,
> >> +					 input, output);

<snip>

> >> +/* Ask the hypervisor to map guest ram pages or the guest mmio space */
> >> +static int hv_do_map_gpa_hcall(u64 partition_id, u64 gfn, u64 page_struct_count,
> >> +			       u32 flags, struct page **pages, u64 mmio_spa)
> >> +{
> >> +	struct hv_input_map_gpa_pages *input_page;
> >> +	u64 status, *pfnlist;
> >> +	unsigned long irq_flags, large_shift = 0;
> >> +	int ret = 0, done = 0;
> >> +	u64 page_count = page_struct_count;
> >> +
> >> +	if (page_count == 0 || (pages && mmio_spa))
> >> +		return -EINVAL;
> >> +
> >> +	if (flags & HV_MAP_GPA_LARGE_PAGE) {
> >> +		if (mmio_spa)
> >> +			return -EINVAL;
> >> +
> >> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> >> +			return -EINVAL;
> >> +
> >> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> >> +		page_count >>= large_shift;
> >> +	}
> >> +
> >> +	while (done < page_count) {
> >> +		ulong i, completed, remain = page_count - done;
> >> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
> >> +
> >> +		local_irq_save(irq_flags);
> >> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> >> +
> >> +		input_page->target_partition_id = partition_id;
> >> +		input_page->target_gpa_base = gfn + (done << large_shift);
> >> +		input_page->map_flags = flags;
> >> +		pfnlist = input_page->source_gpa_page_list;
> >> +
> >> +		for (i = 0; i < rep_count; i++)
> >> +			if (flags & HV_MAP_GPA_NO_ACCESS) {
> >> +				pfnlist[i] = 0;
> >> +			} else if (pages) {
> >> +				u64 index = (done + i) << large_shift;
> >> +
> >> +				if (index >= page_struct_count) {
> >
> > Can this test ever be true?  It looks like the pages array must
> > have space for each 4K page even if mapping in 2Meg granularity.> But only every 512th
> entry in the pages array is looked at
> > (which seems a little weird). But based on how rep_count is set up,
> > I don't see how the algorithm could go past the end of the pages
> > array.
> >
> I don't think the test can actually be true - IIRC I wrote it as a kind
> of "is my math correct?" sanity check, and there was a pr_err() or a
> WARN()here in a previous iteration of the code.
> 
> The large page list is a bit weird - When we allocate the large pages in
> the kernel, we get all the (4K) page structs for that range back from the
> kernel, and we hang onto them. When mapping the large pages into the
> hypervisor we just have to map the PFN of the first page of each 2M page,
> hence the skipping.
> 
> Now I'm thinking about it again, maybe we can discard most of the 4K page
> structs the kernel gives back and keep it as a packed array of the "head"
> pages which are all we really need (and then also simplify this mapping
> code and save some memory).
> 
> The current code was just the simplest way to add the large page
> functionality on top of what we already had, but looks like it could
> probably be improved.
> 
> >> +					ret = -EINVAL;
> >> +					break;
> >> +				}
> >> +				pfnlist[i] = page_to_pfn(pages[index]);
> >> +			} else {
> >> +				pfnlist[i] = mmio_spa + done + i;
> >> +			}
> >> +		if (ret)
> >> +			break;
> >
> > This test could also go away if the ret = -EINVAL error above can't
> > happen.
> >
> Ack
> <snip>
> >> +
> >> +/* Ask the hypervisor to map guest mmio space */
> >> +int hv_call_map_mmio_pages(u64 partition_id, u64 gfn, u64 mmio_spa, u64 numpgs)
> >> +{
> >> +	int i;
> >> +	u32 flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE |
> >> +		    HV_MAP_GPA_NOT_CACHED;
> >> +
> >> +	for (i = 0; i < numpgs; i++)
> >> +		if (page_is_ram(mmio_spa + i))
> >
> > FWIW, doing this check one-page-at-a-time is somewhat expensive if numpgs
> > is large. The underlying data structures should support doing a single range
> > check, but I haven't looked at whether functions exist to do such a range check.
> >
> Indeed - I'll make a note to investigate, thanks.
> 
> >> +			return -EINVAL;
> >> +
> >> +	return hv_do_map_gpa_hcall(partition_id, gfn, numpgs, flags, NULL,
> >> +				   mmio_spa);
> >> +}
> >> +
> >> +int hv_call_unmap_gpa_pages(u64 partition_id, u64 gfn, u64 page_count_4k,
> >> +			    u32 flags)
> >> +{
> >> +	struct hv_input_unmap_gpa_pages *input_page;
> >> +	u64 status, page_count = page_count_4k;
> >> +	unsigned long irq_flags, large_shift = 0;
> >> +	int ret = 0, done = 0;
> >> +
> >> +	if (page_count == 0)
> >> +		return -EINVAL;
> >> +
> >> +	if (flags & HV_UNMAP_GPA_LARGE_PAGE) {
> >> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> >> +			return -EINVAL;
> >> +
> >> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> >> +		page_count >>= large_shift;
> >> +	}
> >> +
> >> +	while (done < page_count) {
> >> +		ulong completed, remain = page_count - done;
> >> +		int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
> >
> > Using HV_MAP_GPA_BATCH_SIZE seems a little weird here since there's
> > no input array and hence no constraint based on keeping input args to
> > just one page. Is it being used as an arbitrary limit so the rep_count
> > passed to the hypercall isn't "too large" for some definition of "too large"?
> > If that's the case, perhaps a separate #define and a comment would
> > make sense. I kept trying to figure out how the batch size for unmap was
> > related to the map hypercall, and I don't think there is any relationship.
> >
> I think batching this was intentional so that we can be sure to re-enable
> interrupts periodically when unmapping an entire VM's worth of memory. That
> said, as you know the hypercall will return if it takes longer than a certain
> amount of time so I guess that is "built-in" in some sense.
> 
> I think keeping the batching, but #defining a specific value for unmap as you
> suggest is a good idea.
> 
> I'd be inclined to use a similar number (something like 512).

Yes, I agree the batching should be kept because interrupts are disabled.
If the rep hypercall is taking a "long time", it will by itself come up for
air to allow taking interrupts. If interrupts were not disabled, that would
solve the problem. But with interrupts disabled, you do need some
batching.

Using a number like 512 makes sense to me. Just add a comment that
the value is somewhat arbitrary and only to allow for interrupts. It's
not based on memory space for input/output arguments like all the
other batch sizes.

> 
> >> +
> >> +		local_irq_save(irq_flags);
> >> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> >> +
> >> +		input_page->target_partition_id = partition_id;
> >> +		input_page->target_gpa_base = gfn + (done << large_shift);
> >> +		input_page->unmap_flags = flags;
> >> +		status = hv_do_rep_hypercall(HVCALL_UNMAP_GPA_PAGES, rep_count,
> >> +					     0, input_page, NULL);
> >> +		local_irq_restore(irq_flags);
> >> +
> >> +		completed = hv_repcomp(status);
> >> +		if (!hv_result_success(status)) {
> >> +			ret = hv_result_to_errno(status);
> >> +			break;
> >> +		}
> >> +
> >> +		done += completed;
> >> +	}
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
> >> +				  union hv_gpa_page_access_state_flags state_flags,
> >> +				  int *written_total,
> >> +				  union hv_gpa_page_access_state *states)
> >> +{
> >> +	struct hv_input_get_gpa_pages_access_state *input_page;
> >> +	union hv_gpa_page_access_state *output_page;
> >> +	int completed = 0;
> >> +	unsigned long remaining = count;
> >> +	int rep_count, i;
> >> +	u64 status;
> >> +	unsigned long flags;
> >> +
> >> +	*written_total = 0;
> >> +	while (remaining) {
> >> +		local_irq_save(flags);
> >> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> >> +		output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
> >> +
> >> +		input_page->partition_id = partition_id;
> >> +		input_page->hv_gpa_page_number = gpa_base_pfn + *written_total;
> >> +		input_page->flags = state_flags;
> >> +		rep_count = min(remaining, HV_GET_GPA_ACCESS_STATES_BATCH_SIZE);
> >> +
> >> +		status = hv_do_rep_hypercall(HVCALL_GET_GPA_PAGES_ACCESS_STATES,
> rep_count,
> >> +					     0, input_page, output_page);
> >> +		if (!hv_result_success(status)) {
> >> +			local_irq_restore(flags);
> >> +			break;
> >> +		}
> >> +		completed = hv_repcomp(status);
> >> +		for (i = 0; i < completed; ++i)
> >> +			states[i].as_uint8 = output_page[i].as_uint8;
> >> +
> >> +		states += completed;
> >> +		*written_total += completed;
> >> +		remaining -= completed;
> >> +		local_irq_restore(flags);
> >
> > FWIW, this local_irq_restore() could move up three lines to before the progress
> > accounting is done.
> >
> Good point, thanks.
> <snip>
> >> +		memset(input, 0, sizeof(*input));
> >> +		memset(output, 0, sizeof(*output));
> >
> > Why is the output set to zero?  I would think Hyper-V is responsible for
> > ensuring that the output is properly populated, with unused fields/areas
> > set to zero.
> >
> Overabundance of caution, I think! It doesn't need to be zeroed AFAIK.
> 
> I recently did a some cleanup (in our internal tree) to make sure we are
> memset()ing the input and *not* memset()ing the output everywhere, but
> it didn't make it into this series. There are a few more places like this.
> 
> <snip>
> >> +
> >> +int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
> >> +			 /* Choose between pages and bytes */
> >> +			 struct hv_vp_state_data state_data, u64 page_count,
> >
> > The size of "struct hv_vp_state_data" looks to be 24 bytes (3 64-bit words).
> > Is there a reason to pass this by value instead of as a pointer? I guess it works
> > like this, but it seems atypical.
> >
> No particular reason. I'm guessing the compiler will pass this by copying it to this
> function's stack frame - 24 bytes is still rather small so I don't think it's an issue.

Right, I think the code works as written. It's just atypical. When I see stuff that
doesn't fit the usual pattern, I always wonder "why?"  And if there's no good
reason "why", reverting to the usual pattern avoids somebody else wondering
"why" in the future. :-)  But you can leave it as is.

> 
> I'm also under the impression the compiler may optimize this to a pointer since it is
> not modified?

It might. I'm not sure.

> 
> I usually only pass a pointer (for read-only values) when it's something really
> large that I *definitely* don't want to be copied on the stack (like, 100 bytes?).
> In that case I probably only have a pointer to vmalloc'd/kalloc()'d memory anyway.
> 
> <snip>
> >> +	local_irq_save(flags);
> >> +	status = hv_do_fast_hypercall8(HVCALL_CLEAR_VIRTUAL_INTERRUPT,
> >> +				       partition_id) &
> >> +			HV_HYPERCALL_RESULT_MASK;
> >
> > This "anding" with HV_HYPERCALL_RESULT_MASK should be removed.
> >
> Yep, thanks.
> 
> >> +	local_irq_restore(flags);
> >
> > The irq save/restore isn't needed here since this is a fast hypercall and
> > per-cpu arg memory is not used.
> >
> Agreed, will remove these for the fast hypercall sites.
> 
> <snip>
> >> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> >> +		status = hv_do_hypercall(HVCALL_CREATE_PORT, input, NULL) &
> >> +			 HV_HYPERCALL_RESULT_MASK;
> >
> > Use the hv_status checking macros instead of and'ing with
> > HV_HYPERCALL_RESULT_MASK.
> >
> Thanks, these need a bit of cleanup.
> 
> <snip>
> >> +	status = hv_do_fast_hypercall16(HVCALL_DELETE_PORT,
> >> +					input.as_uint64[0],
> >> +					input.as_uint64[1]) &
> >> +			HV_HYPERCALL_RESULT_MASK;
> >> +	local_irq_restore(flags);
> >
> > Same a previous comment about and'ing.  And irq save/restore
> > isn't needed.
> >
> ack
> 
> <snip>
> >> +		status = hv_do_hypercall(HVCALL_CONNECT_PORT, input, NULL) &
> >> +			 HV_HYPERCALL_RESULT_MASK;
> >
> > Same here.  Use hv_* macros.
> >
> ack
> 
> <snip>
> >> +	status = hv_do_fast_hypercall16(HVCALL_DISCONNECT_PORT,
> >> +					input.as_uint64[0],
> >> +					input.as_uint64[1]) &
> >> +			HV_HYPERCALL_RESULT_MASK;
> >> +	local_irq_restore(flags);
> >
> > Same as above.
> >
> ack
> 
> <snip>
> >> +	local_irq_save(flags);
> >> +	input.sint_index = sint_index;
> >> +	status = hv_do_fast_hypercall8(HVCALL_NOTIFY_PORT_RING_EMPTY,
> >> +				       input.as_uint64) &
> >> +		 HV_HYPERCALL_RESULT_MASK;
> >> +	local_irq_restore(flags);
> >
> > Same as above.
> >
> ack, and I'll double check we don't have other fast hypercall sites doing this
> 
> <snip>>> +		/*
> >> +		 * This is required to make sure that reserved field is set to
> >> +		 * zero, because MSHV has a check to make sure reserved bits are
> >> +		 * set to zero.
> >> +		 */
> >
> > Is this comment about checking reserved bits unique to this hypercall? If not, it
> > seems a little odd to see this comment here, but not other places where the input
> > is zero'ed.
> >
> I agree the comment isn't necessary - memset()ing the input to zero should be the
> default policy. I'll remove it.

This is another case where something doesn't fit the usual pattern, and I wonder
"why". :-)

> 
> >> +		memset(input_page, 0, sizeof(*input_page));
> >> +		/* Only set the partition id if you are making the pages
> >> +		 * exclusive
> >> +		 */
> >> +		if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE)
> >> +			input_page->partition_id = partition_id;
> >> +		input_page->flags = flags;
> >> +		input_page->host_access = host_access;
> >> +
> >> +		for (i = 0; i < rep_count; i++) {
> >> +			u64 index = (done + i) << large_shift;
> >> +
> >> +			if (index >= page_struct_count)
> >> +				return -EINVAL;
> >
> > Can this test ever be true?
> >
> See above in hv_do_map_gpa_hcall(), it's more of a sanity check or assert.
> 
> >> +
> >> +			input_page->spa_page_list[i] =
> >> +						page_to_pfn(pages[index]);
> >
> > When large_shift is non-zero, it seems weird to be skipping over most
> > of the entries in the "pages" array.  But maybe there's a reason for that.
> >
> See above where we do the same thing in hv_do_map_gpa_hcall(). The hypervisor
> only needs to see the "head" pages - the GPAs of the 2MB pages.
> 
> >> +		}
> >> +
> >> +		status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
> >> +					     NULL);
> >> +		local_irq_restore(irq_flags);
> >> +
> >> +		completed = hv_repcomp(status);
> >> +
> >> +		if (!hv_result_success(status))
> >> +			return hv_result_to_errno(status);
> >> +
> >> +		done += completed;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >
> > [snip the rest of the patch that I haven't reviewed yet]
> >
> > Michael



From wei.fang at nxp.com  Thu Mar 13 20:38:18 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 14 Mar 2025 03:38:18 +0000
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250313163526.pqwp2wsfvio7avs6@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
Message-ID: <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:17PM +0800, Wei Fang wrote:
> > +int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs, u32 *table,
> > +				    int count, bool query)
> > +{
> > +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> > +	struct rsst_req_update *requ;
> > +	struct ntmp_req_by_eid *req;
> > +	union netc_cbd cbd;
> > +	int err, i;
> > +	u32 len;
> > +
> > +	if (count != RSST_ENTRY_NUM)
> > +		/* HW only takes in a full 64 entry table */
> > +		return -EINVAL;
> > +
> > +	if (query)
> > +		data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
> > +			    RSST_CFGE_DATA_SIZE(count);
> > +	else
> > +		data.size = struct_size(requ, groups, count);
> > +
> > +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> > +	if (err)
> > +		return err;
> > +
> > +	/* Set the request data buffer */
> > +	if (query) {
> > +		ntmp_fill_crd_eid(req, cbdrs->tbl.rsst_ver, 0, 0, 0);
> > +		len = NTMP_LEN(sizeof(*req), data.size);
> > +		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> > +					NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
> 
> Please either use a commonly accepted abbreviation such as "hdr", or
> preferably,
> just spell "header" as such. This reminded me of Kevin Malone's quote
> "Why waste time say lot word when few word do trick?" :)
> 

Sure, I will fix it.

> > +	} else {
> > +		requ = (struct rsst_req_update *)req;
> > +		ntmp_fill_crd_eid(&requ->rbe, cbdrs->tbl.rsst_ver, 0,
> > +				  NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
> > +		for (i = 0; i < count; i++)
> > +			requ->groups[i] = (u8)(table[i]);
> > +
> > +		len = NTMP_LEN(data.size, 0);
> > +		ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> > +					NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
> > +	}
> > +
> > +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> > +	if (err) {
> > +		dev_err(cbdrs->dma_dev, "%s RSS table entry failed (%d)",
> > +			query ? "Query" : "Update", err);
> > +		goto end;
> > +	}
> > +
> > +	if (query) {
> > +		u8 *group = (u8 *)req;
> > +
> > +		group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
> > +		for (i = 0; i < count; i++)
> > +			table[i] = group[i];
> > +	}
> > +
> > +end:
> > +	ntmp_free_data_mem(&data);
> > +
> > +	return err;
> > +}
> > +EXPORT_SYMBOL_GPL(ntmp_rsst_query_or_update_entry);
> 
> Instead of exporting "query_or_update" mixed semantics, can you please
> export two separate functions, one for "query" and the other for "update"?
> For query=false, you can make the "table" argument const.
> 
> Also, from the looks of their implementation, there isn't much that is
> common anyway.
> 

Okay, accept, I will split it into two functions.

> > +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void
> **buf_align)
> > +{
> > +	void *buf;
> > +
> > +	buf = dma_alloc_coherent(data->dev, data->size +
> NTMP_DATA_ADDR_ALIGN,
> > +				 &data->dma, GFP_ATOMIC);
> 
> Is there any call site that can't use sleeping allocations (GFP_KERNEL)?
> 

The initial reason was that we called ntmp_maft_add_entry() directly when
implementing ndo_set_rx_mode(), so we changed it to GFP_ATOMIC. Later,
we implemented ndo_set_rx_mode() using workqueue, so for the current
patch, we can change it back to GFP_KERNEL.

> > +	if (!buf)
> > +		return -ENOMEM;
> > +
> > +	data->buf = buf;
> > +	*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
> > +
> > +	return 0;
> > +}
> > +
> > diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> > new file mode 100644
> > index 000000000000..45e4d083ab0a
> > --- /dev/null
> > +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> > @@ -0,0 +1,63 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > +/*
> > + * NTMP table request and response data buffer formats
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#ifndef __NTMP_PRIVATE_H
> > +#define __NTMP_PRIVATE_H
> > +
> > +#include <linux/fsl/ntmp.h>
> > +
> > +struct ntmp_dma_buf {
> > +	struct device *dev;
> > +	size_t size;
> > +	void *buf;
> > +	dma_addr_t dma;
> > +};
> > +
> > +struct common_req_data {
> 
> Some maintainers prefer to avoid definitions which "sound" generic, but truly
> are driver-specific, and instead recommend to prefix their names with
> some kind of driver specific indication
> (example:
> https://lore.kernel.org/netdev/20190413205311.GC2268 at nanopsycho.orion/).
> 
> So, maybe something like "ntmp_common_req_data",
> "ntmp_common_resp_query", ...
> would make that more clear?
> 

I will rename these structs, thanks.

> > +	__le16 update_act;
> > +	u8 dbg_opt;
> > +	u8 tblv_qact;
> > +#define NTMP_QUERY_ACT		GENMASK(3, 0)
> > +#define NTMP_TBL_VER		GENMASK(7, 0)
> > +#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
> > +				 ((a) & NTMP_QUERY_ACT))
> 
> Can you please move #define macros out of structure definitions?

No, I think these macros in the structure can better reflect the specific
meaning of these members. We can intuitively see what the bits of
these members represent, rather than finding the definition of these
bits in RM or elsewhere.

> 
> > +};
> > +
> > +struct common_resp_query {
> > +	__le32 entry_id;
> > +};
> > +
> > +struct common_resp_nq {
> > +	__le32 status;
> > +};
> > +
> > +/* Generic structure for request data by entry ID  */
> > +struct ntmp_req_by_eid {
> > +	struct common_req_data crd;
> > +	__le32 entry_id;
> > +};
> > +
> > +/* MAC Address Filter Table Request Data Buffer Format of Add action */
> > +struct maft_req_add {
> > +	struct ntmp_req_by_eid rbe;
> > +	struct maft_keye_data keye;
> > +	struct maft_cfge_data cfge;
> > +};
> > +
> > +/* MAC Address Filter Table Response Data Buffer Format of Query action */
> > +struct maft_resp_query {
> > +	__le32 entry_id;
> > +	struct maft_keye_data keye;
> > +	struct maft_cfge_data cfge;
> > +};
> > +
> > +/* RSS Table Request Data Buffer Format of Update action */
> > +struct rsst_req_update {
> > +	struct ntmp_req_by_eid rbe;
> > +	u8 groups[];
> > +};
> > +
> > +#endif
> > diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> > new file mode 100644
> > index 000000000000..fe15e394c4a4
> > --- /dev/null
> > +++ b/include/linux/fsl/ntmp.h
> > @@ -0,0 +1,174 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > +/* Copyright 2025 NXP */
> > +#ifndef __NETC_NTMP_H
> > +#define __NETC_NTMP_H
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/if_ether.h>
> > +
> > +#define NTMP_NULL_ENTRY_ID		0xffffffffU
> > +#define NETC_CBDR_BD_NUM		256
> > +
> > +union netc_cbd {
> 
> Do you seriously need to export the netc_cbd definition outside of
> drivers/net/ethernet/freescale/enetc/ntmp.c? I would say even if you do
> (which this patch set doesn't appear to need), the NTMP library exports
> an API which doesn't do a great job abstracting the information.

Sorry, I was not aware of the netc_cbd could be moved to ntmp_private.h
as well.

> 
> The question pertains to everything else that is exported to
> include/linux/fsl/ntmp.h - what the API consumer sees. Is there a real
> reason to export it? For many structures and macros, the answer seems no.
> 
> Even for cases like struct maft_keye_data which are only used by debugfs,
> it still seems preferable to keep data encapsulation and offer a helper
> function to retrieve a pointer to the MAC address from the MAFT entry.
> Then, "struct maft_keye_data;" can simply be declared, without exposing
> its full definition.

ntmp_private.h is only used for ntmp driver, I don't want it to be included
by any enetc files. ntmp.h is used for both enetc and switch drivers, so we
need to add full definitions of the table data.

> 
> > +	struct {
> > +		__le64 addr;
> > +		__le32 len;
> > +#define NTMP_RESP_LEN		GENMASK(19, 0)
> > +#define NTMP_REQ_LEN		GENMASK(31, 20)
> > +#define NTMP_LEN(req, resp)	(FIELD_PREP(NTMP_REQ_LEN, (req)) | \
> > +				((resp) & NTMP_RESP_LEN))
> > +		u8 cmd;
> > +#define NTMP_CMD_DELETE		BIT(0)
> > +#define NTMP_CMD_UPDATE		BIT(1)
> > +#define NTMP_CMD_QUERY		BIT(2)
> > +#define NTMP_CMD_ADD		BIT(3)
> > +#define NTMP_CMD_QD		(NTMP_CMD_QUERY |
> NTMP_CMD_DELETE)
> > +#define NTMP_CMD_QU		(NTMP_CMD_QUERY |
> NTMP_CMD_UPDATE)
> > +#define NTMP_CMD_AU		(NTMP_CMD_ADD | NTMP_CMD_UPDATE)
> > +#define NTMP_CMD_AQ		(NTMP_CMD_ADD | NTMP_CMD_QUERY)
> > +#define NTMP_CMD_AQU		(NTMP_CMD_AQ | NTMP_CMD_UPDATE)
> > +		u8 access_method;
> > +#define NTMP_ACCESS_METHOD	GENMASK(7, 4)
> > +#define NTMP_AM_ENTRY_ID	0
> > +#define NTMP_AM_EXACT_KEY	1
> > +#define NTMP_AM_SEARCH		2
> > +#define NTMP_AM_TERNARY_KEY	3
> > +		u8 table_id;
> > +		u8 ver_cci_rr;
> > +#define NTMP_HDR_VERSION	GENMASK(5, 0)
> > +#define NTMP_HDR_VER2		2
> > +#define NTMP_CCI		BIT(6)
> > +#define NTMP_RR			BIT(7)
> > +		__le32 resv[3];
> > +		__le32 npf;
> > +#define NTMP_NPF		BIT(15)
> > +	} req_hdr;	/* NTMP Request Message Header Format */
> > +
> > +	struct {
> > +		__le32 resv0[3];
> > +		__le16 num_matched;
> > +		__le16 error_rr;
> > +#define NTMP_RESP_ERROR		GENMASK(11, 0)
> > +#define NTMP_RESP_RR		BIT(15)
> > +		__le32 resv1[4];
> > +	} resp_hdr; /* NTMP Response Message Header Format */
> > +};
> > +
> > +struct maft_keye_data {
> > +	u8 mac_addr[ETH_ALEN];
> > +	__le16 resv;
> > +};
> > +
> > +struct maft_cfge_data {
> > +	__le16 si_bitmap;
> > +	__le16 resv;
> > +};
> > +
> > +struct netc_cbdr_regs {
> > +	void __iomem *pir;
> > +	void __iomem *cir;
> > +	void __iomem *mr;
> > +
> > +	void __iomem *bar0;
> > +	void __iomem *bar1;
> > +	void __iomem *lenr;
> > +};
> > +
> > +struct netc_tbl_vers {
> > +	u8 maft_ver;
> > +	u8 rsst_ver;
> > +};
> > +
> > +struct netc_cbdr {
> > +	struct netc_cbdr_regs regs;
> > +
> > +	int bd_num;
> > +	int next_to_use;
> > +	int next_to_clean;
> > +
> > +	int dma_size;
> > +	void *addr_base;
> > +	void *addr_base_align;
> > +	dma_addr_t dma_base;
> > +	dma_addr_t dma_base_align;
> > +
> > +	spinlock_t ring_lock; /* Avoid race condition */
> 
> Can this description be more specific? This type of comment is as
> useful as not having it. Make the reader understand what is serialized
> with what, to prevent concurrent, non-atomic access to what resources.
> 
> > +};
> > +
> > +struct netc_cbdrs {
> > +	int cbdr_num;	/* number of control BD ring */
> > +	int cbdr_size;	/* number of BDs per control BD ring */
> > +	struct device *dma_dev;
> > +	struct netc_cbdr *ring;
> > +	struct netc_tbl_vers tbl;
> > +};
> > +
> > +enum netc_dev_type {
> > +	NETC_DEV_ENETC,
> > +	NETC_DEV_SWITCH
> > +};
> 
> Can you delay the introduction of this distinction until when the
> "dev_type" will actually be used for something, and it's clear to
> reviewers what is the intention behind it? Currently the switch driver
> does not exist, and this has no purpose.
> 

Okay, I will remove it.

> > +
> > +struct ntmp_priv {
> 
> Would it be better to name this "struct ntmp_client"? I don't really
> understand the way in which it is "private".

It refers to some private data of NTMP of different devices (enetc or
switches). Since the current patch is only a small part of NTMP, many
members have not been added to the structure. The following is the
definition in our downstream.

struct ntmp_priv {
	enum netc_dev_type dev_type;
	struct netc_cbdrs cbdrs;
	u32 errata;

	struct ntmp_caps caps;
	/* bitmap of table entry ID */
	unsigned long *ist_eid_bitmap;
	unsigned long *rpt_eid_bitmap;
	unsigned long *sgit_eid_bitmap;
	unsigned long *isct_eid_bitmap;
	unsigned long *sgclt_word_bitmap;
	unsigned long *ett_eid_bitmap;
	unsigned long *ect_eid_bitmap;
	u32 ett_bitmap_size;
	u32 ect_bitmap_size;

	struct hlist_head flower_list;
	struct mutex flower_lock; /* flower_list lock */

	u64 (*adjust_base_time)(struct ntmp_priv *priv, u64 bt, u32 ct);
	u32 (*get_tgst_free_words)(struct ntmp_priv *priv);
};

> 
> I'm looking at this from an API perspective, and I don't really
> understand which one is the "top-level" object for an NTMP consumer
> driver. Is it ntmp_priv or netc_cbdrs? Logically, ntmp_priv encapsulates
> netc_cbdrs, but I see that all functions take the smaller netc_cbdrs,
> which I find unintuitive. Could you just perhaps squash them into a
> single structure, if they in fact serve the same purpose?
> 
> > +	enum netc_dev_type dev_type;
> > +	struct netc_cbdrs cbdrs;
> > +};
> > +
> > +struct maft_entry_data {
> > +	struct maft_keye_data keye;
> > +	struct maft_cfge_data cfge;
> > +};
> 
> > +static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
> > +				   u8 tbl_ver, u32 entry_id, u32 req_len,
> > +				   u32 resp_len)
> > +{
> > +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> > +	struct ntmp_req_by_eid *req;
> > +	union netc_cbd cbd;
> > +	u32 len;
> > +	int err;
> > +
> > +	if (entry_id == NTMP_NULL_ENTRY_ID)
> > +		return 0;
> 
> What's the idea with the null entry ID? Why special-case it?
> 

Some functions are configured by multiple tables. If a table is
not needed in the current configuration, we may set its entry
id to NTMP_NULL_ENTRY_ID, indicating that the table is bypassed.
For the current patch, this condition can be removed.

> > +
> > +	/* If the req_len is 0, indicates the requested length is the
> > +	 * standard length.
> > +	 */
> > +	if (!req_len)
> > +		req_len = sizeof(*req);
> 
> Objection: as submitted in this patch set, the req_len argument is _only_
> passed as zero (the only caller is ntmp_maft_delete_entry()). I don't
> know about downstream, but let's only add complexity that we need, when
> we need it.
> 

Okay, I will remove it.

> > +
> > +	data.size = req_len >= resp_len ? req_len : resp_len;
> > +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> > +	if (err)
> > +		return err;
> > +
> > +	ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
> > +	len = NTMP_LEN(req_len, resp_len);
> > +	ntmp_fill_request_headr(&cbd, data.dma, len, tbl_id,
> > +				NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
> > +
> > +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> > +	if (err)
> > +		dev_err(cbdrs->dma_dev, "Delete table (id: %d) entry failed: %d",
> > +			tbl_id, err);
> > +
> > +	ntmp_free_data_mem(&data);
> > +
> > +	return err;
> > +}
> > +
> > +static int ntmp_query_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
> > +				  u32 len, struct ntmp_req_by_eid *req,
> > +				  dma_addr_t dma, bool compare_eid)
> > +{
> > +	struct device *dev = cbdrs->dma_dev;
> > +	struct common_resp_query *resp;
> > +	int cmd = NTMP_CMD_QUERY;
> > +	union netc_cbd cbd;
> > +	u32 entry_id;
> > +	int err;
> > +
> > +	entry_id = le32_to_cpu(req->entry_id);
> > +	if (le16_to_cpu(req->crd.update_act))
> > +		cmd = NTMP_CMD_QU;
> > +
> > +	/* Request header */
> > +	ntmp_fill_request_headr(&cbd, dma, len, tbl_id,
> > +				cmd, NTMP_AM_ENTRY_ID);
> > +
> > +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> > +	if (err) {
> > +		dev_err(dev, "Query table (id: %d) entry failed: %d\n",
> > +			tbl_id, err);
> > +		return err;
> > +	}
> > +
> > +	/* For a few tables, the first field of its response data is not
> 
> s/its/their/
> 
> > +	 * entry_id, so directly return success.
> > +	 */
> > +	if (!compare_eid)
> > +		return 0;
> > +
> > +	resp = (struct common_resp_query *)req;
> > +	if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
> > +		dev_err(dev, "Table (id: %d) query EID:0x%0x, response EID:0x%x\n",
> 
> Can you please put some spaces between ":" and "0".

Yes, sure.

> 
> > +			tbl_id, entry_id, le32_to_cpu(resp->entry_id));
> > +		return -EIO;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int ntmp_maft_add_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
> > +			struct maft_entry_data *maft)
> > +{
> > +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> > +	struct maft_req_add *req;
> > +	union netc_cbd cbd;
> > +	int err;
> > +
> > +	data.size = sizeof(*req);
> > +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> > +	if (err)
> > +		return err;
> > +
> > +	/* Set mac address filter table request data buffer */
> > +	ntmp_fill_crd_eid(&req->rbe, cbdrs->tbl.maft_ver, 0, 0, entry_id);
> > +	req->keye = maft->keye;
> > +	req->cfge = maft->cfge;
> > +
> > +	ntmp_fill_request_headr(&cbd, data.dma, NTMP_LEN(data.size, 0),
> > +				NTMP_MAFT_ID, NTMP_CMD_ADD,
> > +				NTMP_AM_ENTRY_ID);
> > +	err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> > +	if (err)
> > +		dev_err(cbdrs->dma_dev, "Add MAFT entry failed (%d)", err);
> 
> Can you use symbolic error names? "Adding MAFT entry failed: %pe\n",
> ERR_PTR(err).
> Also notice the missing \n in the error message..

Okay, thanks.

> 
> Same comment for the error message in:
> - ntmp_delete_entry_by_id()
> - ntmp_rsst_query_or_update_entry() - which as per review feedback here
>   should become 2 functions
> 
> > +
> > +	ntmp_free_data_mem(&data);
> > +
> > +	return err;
> > +}
> > +EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
> > +
> > +int ntmp_maft_query_entry(struct netc_cbdrs *cbdrs, u32 entry_id,
> > +			  struct maft_entry_data *maft)
> > +{
> > +	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> > +	struct maft_resp_query *resp;
> > +	struct ntmp_req_by_eid *req;
> > +	u32 req_len = sizeof(*req);
> > +	int err;
> > +
> > +	if (entry_id == NTMP_NULL_ENTRY_ID)
> > +		return -EINVAL;
> > +
> > +	data.size = sizeof(*resp);
> > +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> > +	if (err)
> > +		return err;
> > +
> > +	ntmp_fill_crd_eid(req, cbdrs->tbl.maft_ver, 0, 0, entry_id);
> > +	err = ntmp_query_entry_by_id(cbdrs, NTMP_MAFT_ID,
> > +				     NTMP_LEN(req_len, data.size),
> > +				     req, data.dma, true);
> > +	if (err)
> > +		goto end;
> > +
> > +	resp = (struct maft_resp_query *)req;
> > +	maft->keye = resp->keye;
> > +	maft->cfge = resp->cfge;
> > +
> > +end:
> > +	ntmp_free_data_mem(&data);
> > +
> > +	return err;
> > +}
> > +EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
> > +
> > +int ntmp_maft_delete_entry(struct netc_cbdrs *cbdrs, u32 entry_id)
> > +{
> > +	return ntmp_delete_entry_by_id(cbdrs, NTMP_MAFT_ID,
> > +				       cbdrs->tbl.maft_ver,
> > +				       entry_id, 0, 0);
> > +}
> > +EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);
> 
> > +static void netc_clean_cbdr(struct netc_cbdr *cbdr)
> > +{
> > +	union netc_cbd *cbd;
> > +	int i;
> > +
> > +	i = cbdr->next_to_clean;
> > +	while (netc_read(cbdr->regs.cir) != i) {
> > +		cbd = netc_get_cbd(cbdr, i);
> > +		memset(cbd, 0, sizeof(*cbd));
> > +		i = (i + 1) % cbdr->bd_num;
> > +	}
> > +
> > +	cbdr->next_to_clean = i;
> > +}
> > +
> > +static struct netc_cbdr *netc_select_cbdr(struct netc_cbdrs *cbdrs)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < cbdrs->cbdr_num; i++) {
> > +		if (spin_is_locked(&cbdrs->ring[i].ring_lock))
> > +			continue;
> > +
> > +		return &cbdrs->ring[i];
> > +	}
> > +
> > +	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];
> 
> I think you need to be in a "preemption disabled" / "migration disable"
> calling context for smp_processor_id() to be reliable. Otherwise, the
> task can migrate to another CPU as soon as this function returns.
> 

It does not matter, we just want to select a command BD ring when all
command BD rings are busy. So smp_processor_id() is just a parameter,
we can also use a random number.

> Anyway, much can be said about this, but currently it is useless
> complexity, because the only user, enetc4_setup_cbdr(), sets
> "cbdrs->cbdr_num = 1", which side-steps the entire netc_select_cbdr()
> logic.
> 
> Please strip all unnecessary logic and only add it when the need
> presents itself, so we can all assess whether the solution is
> appropriate for that particular need.
> 

Okay, agree

> > +}
> > +
> > +static int netc_xmit_ntmp_cmd(struct netc_cbdrs *cbdrs, union netc_cbd
> *cbd)
> > +{
> > +	union netc_cbd *cur_cbd;
> > +	struct netc_cbdr *cbdr;
> > +	int i, err;
> > +	u16 status;
> > +	u32 val;
> > +
> > +	if (cbdrs->cbdr_num == 1)
> > +		cbdr = &cbdrs->ring[0];
> > +	else
> > +		cbdr = netc_select_cbdr(cbdrs);
> > +
> > +	spin_lock_bh(&cbdr->ring_lock);
> > +
> > +	if (unlikely(!netc_get_free_cbd_num(cbdr)))
> > +		netc_clean_cbdr(cbdr);
> > +
> > +	i = cbdr->next_to_use;
> > +	cur_cbd = netc_get_cbd(cbdr, i);
> > +	*cur_cbd = *cbd;
> > +
> > +	/* Update producer index of both software and hardware */
> > +	i = (i + 1) % cbdr->bd_num;
> > +	cbdr->next_to_use = i;
> > +	dma_wmb();
> 
> Can you place this dma_wmb() right next to the "*cur_cbd = *cbd" line,
> to make it obvious that updating the producer index has nothing to do
> with it? Or is there another reason for this ordering?
> 

No special reason for this ordering, I will move it after "*cur_cbd = *cbd".

> > +	netc_write(cbdr->regs.pir, i);
> > +
> > +	err = read_poll_timeout_atomic(netc_read, val, val == i,
> > +				       10, NETC_CBDR_TIMEOUT, true,
> > +				       cbdr->regs.cir);
> > +	if (unlikely(err))
> > +		goto cbdr_unlock;
> > +
> > +	dma_rmb();
> > +	/* Get the writeback command BD, because the caller may need
> > +	 * to check some other fields of the response header.
> > +	 */
> > +	*cbd = *cur_cbd;
> > +
> > +	/* Check the writeback error status */
> > +	status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
> > +	if (unlikely(status)) {
> > +		err = -EIO;
> > +		dev_err(cbdrs->dma_dev, "Command BD error: 0x%04x\n", status);
> > +	}
> > +
> > +	netc_clean_cbdr(cbdr);
> > +	dma_wmb();
> > +
> > +cbdr_unlock:
> > +	spin_unlock_bh(&cbdr->ring_lock);
> > +
> > +	return err;
> > +}


From s-vadapalli at ti.com  Thu Mar 13 21:17:05 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 14 Mar 2025 09:47:05 +0530
Subject: [PATCH] PCI: j721e: Fix the value of linkdown_irq_regfield for
 J784S4
In-Reply-To: <20250313160215.GA736346@bhelgaas>
References: <20250313055519.j3bpvsm6govd5ytk@uda0492258>
 <20250313160215.GA736346@bhelgaas>
Message-ID: <20250314041705.v5j2fjulol5ywvyq@uda0492258>

On Thu, Mar 13, 2025 at 11:02:15AM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 11:25:19AM +0530, Siddharth Vadapalli wrote:
> > On Wed, Mar 12, 2025 at 11:16:00AM -0500, Bjorn Helgaas wrote:
> > > On Wed, Mar 05, 2025 at 06:50:18PM +0530, Siddharth Vadapalli wrote:
> > > > Commit under Fixes assigned the value of 'linkdown_irq_regfield' for the
> > > > J784S4 SoC as 'LINK_DOWN' which corresponds to BIT(1). However, according
> > > > to the Technical Reference Manual and Register Documentation for the J784S4
> > > > SoC [0], BIT(1) corresponds to "ENABLE_SYS_EN_PCIE_DPA_1" which is __NOT__
> > > > the field for the link-state interrupt. Instead, it is BIT(10) of the
> > > > "PCIE_INTD_ENABLE_REG_SYS_2" register that corresponds to the link-state
> > > > field named as "ENABLE_SYS_EN_PCIE_LINK_STATE".
> > > 
> > > I guess the reason we want this is that on J784S4, we ignore actual
> > > link-down interrupts (and we don't write STATUS_CLR_REG_SYS_2 to clear
> > > the interrupt indication, so maybe there's an interrupt storm), and we
> > > think some other interrupt (DPA_1, whatever that is) is actually a
> > > link-down interrupt?
> > 
> > While it is true that actual link-down interrupts are ignored, it is not
> > the case that there's an interrupt storm because the same incorrect macro
> > is used to enable the interrupt line. Since the enables an interrupt for
> > DPA_1 which never fires, we don't run into the situation where we are not
> > clearing the interrupt (the interrupt handler will look for the same
> > incorrect field to clear the interrupt if it does fire for DPA_1, but that
> > doesn't happen). The 'linkdown_irq_regfield' corresponds to the
> > "link-state" field not just in the J784S4 SoC, but in all SoCs supported by
> > the pci-j721e.c driver. It is only in J721E that it is BIT(1)
> > [LINK_DOWN macro], while in all other SoCs (J784S4 included), it is BIT(10)
> > [J7200_LINK_DOWN macro since it was first added for J7200 SoC]. Matt
> > probably referred to J721E's Technical Reference Manual and ended up
> > incorrectly assigning "LINK_DOWN", due to which the driver is enabling
> > the DPA_1 interrupt and the interrupt handler is also going to look for
> > the field corresponding to receiving an interrupt for DPA_1.
> 
> So I guess without this patch, we incorrectly ignore link-down
> interrupts on J784S4.  It's good to have a one-sentence motivation
> like that somewhere in the commit log that we can pull out and include
> in the merge commit log and the pull request.

Yes, we can prepend the following to the existing commit message:
"Link down interrupts on J784S4 SoC are missed because..."

resulting in the following updated paragraph in the commit message:
Link down interrupts on J784S4 SoC are missed because commit under Fixes
assigned the value of 'linkdown_irq_regfield' for the....


> 
> > I can only hope that the URL will redirect to the latest version of
> > the User Guide if at all it becomes invalid.
> 
> OK, thanks, I guess there's nothing more to do ;)  I guess that manual
> is not really designed for collaborative development.
> 
> Thanks for the patient hand holding!

:)

Regards,
Siddharth.


From wei.fang at nxp.com  Thu Mar 13 21:51:06 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 14 Mar 2025 04:51:06 +0000
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring support
 for i.MX95 ENETC
In-Reply-To: <20250313164908.rdy3y77xno3fza3l@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250313164908.rdy3y77xno3fza3l@skbuf>
Message-ID: <PAXPR04MB8510D3A2F2A792A89941A7FD88D22@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:18PM +0800, Wei Fang wrote:
> > The command BD ring is used to configure functionality where the
> > underlying resources may be shared between different entities or being
> > too large to configure using direct registers (such as lookup tables).
> >
> > Because the command BD and table formats of i.MX95 and LS1028A are very
> > different, the software processing logic is also different. In order to
> > ensure driver compatibility, struct enetc_si_ops is introduced. This
> > structure defines some hooks shared by VSI and PSI. Different hardware
> > driver will register different hooks, For example, setup_cbdr() is used
> > to initialize the command BD ring, and teardown_cbdr() is used to free
> > the command BD ring.
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.h  | 27 +++++++--
> >  .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 +++++++++++++++-
> >  .../net/ethernet/freescale/enetc/enetc_cbdr.c | 55 +++++++++++++++++--
> >  .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
> >  .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
> >  5 files changed, 136 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h
> b/drivers/net/ethernet/freescale/enetc/enetc.h
> > index 4ad4eb5c5a74..4ff0957e69be 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> > @@ -8,6 +8,7 @@
> >  #include <linux/dma-mapping.h>
> >  #include <linux/skbuff.h>
> >  #include <linux/ethtool.h>
> > +#include <linux/fsl/ntmp.h>
> >  #include <linux/if_vlan.h>
> >  #include <linux/phylink.h>
> >  #include <linux/dim.h>
> > @@ -266,6 +267,19 @@ struct enetc_platform_info {
> >  	const struct enetc_drvdata *data;
> >  };
> >
> > +struct enetc_si;
> > +
> > +/*
> > + * This structure defines the some common hooks for ENETC PSI and VSI.
> > + * In addition, since VSI only uses the struct enetc_si as its private
> > + * driver data, so this structure also define some hooks specifically
> > + * for VSI. For VSI-specific hooks, the format is ?vf_*()?.
> > + */
> > +struct enetc_si_ops {
> > +	int (*setup_cbdr)(struct enetc_si *si);
> > +	void (*teardown_cbdr)(struct enetc_si *si);
> > +};
> 
> I don't understand the need for si->ops->setup_cbdr() and
> si->ops->teardown_cbdr()?
> Doesn't every call site know which kind of SI it is dealing with, and thus it can
> appropriately call the direct symbol?
> - the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
> - the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()

Yes, for PSI we can use directly call these functions because they are different
drivers, but for VSI, v1 and v4 will use the same driver. I just want the PSI and
VSI to be consistent. If you don't like this, I can remove these interfaces from
the patch set, and add vf_setup_cbdr and vf_teardown_cbdr in the future when
I add the VF support for ENETC v4.

> What benefit is there to making an indirect function call?
> 
> At least that's what the current code does, I'm not sure if that is the intention.



From gregkh at linuxfoundation.org  Thu Mar 13 22:32:45 2025
From: gregkh at linuxfoundation.org (Greg KH)
Date: Fri, 14 Mar 2025 06:32:45 +0100
Subject: [PATCH 6.12 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250314-stable-sve-6-12-v1-3-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-3-ddc16609d9ba@kernel.org>
Message-ID: <2025031427-yiddish-unrented-2bc2@gregkh>

On Fri, Mar 14, 2025 at 12:35:15AM +0000, Mark Brown wrote:
> From: Mark Rutland <mark.rutland at arm.com>
> 
> Now that the host eagerly saves its own FPSIMD/SVE/SME state,
> non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
> and the code to do this is never used. Protected KVM still needs to
> save/restore the host FPSIMD/SVE state to avoid leaking guest state to
> the host (and to avoid revealing to the host whether the guest used
> FPSIMD/SVE/SME), and that code needs to be retained.
> 
> Remove the unused code and data structures.
> 
> To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
> VHE hyp code, the nVHE/hVHE version is moved into the shared switch
> header, where it is only invoked when KVM is in protected mode.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Reviewed-by: Mark Brown <broonie at kernel.org>
> Tested-by: Mark Brown <broonie at kernel.org>
> Acked-by: Will Deacon <will at kernel.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Fuad Tabba <tabba at google.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
> Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---

What is the upstream git id for this on?

thanks,

greg k-h


From namhyung at kernel.org  Thu Mar 13 22:45:49 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 13 Mar 2025 22:45:49 -0700
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9NEX3j_1RUvaFI0@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
Message-ID: <Z9PCjQ8PhOadVGQ8@google.com>

On Thu, Mar 13, 2025 at 05:47:27PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> > Still building, but noticed this on x86_64:
> > 
> > 105: perf trace enum augmentation tests                              : FAILED!
> > 106: perf trace BTF general tests                                    : FAILED!
> > 107: perf trace exit race                                            : Ok
> > 108: perf trace record and replay                                    : FAILED!
> > 
> > 
> > The first doesn?t help that much with verbose mode, haven't checked if
> > before this series it was failing :-\
> > 
> > root at x1:~# perf test -vvv 105
> > 105: perf trace enum augmentation tests:
> > --- start ---
> > test child forked, pid 19411
> > Checking if vmlinux exists
> > Tracing syscall landlock_add_rule
> > ---- end(-1) ----
> > 105: perf trace enum augmentation tests                              : FAILED!
> > root at x1:~#
> 
> So:
> 
> root at x1:~# perf trace -e landlock_add_rule perf test -w landlock
> root at x1:~# 
> 
> But:
> 
> root at x1:~# perf trace perf test -w landlock |& grep landlock_add_rule
>     26.120 ( 0.002 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7ffde75e2680, flags: 45) = -1 EINVAL (Invalid argument)
>     26.124 ( 0.001 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffde75e2690, flags: 45) = -1 EINVAL (Invalid argument)
> root at x1:~# 
> 
> -e is having some trouble, when no event is specified, then it works.
> 
> Something in the changes made to:
> 
> static int trace__parse_events_option(const struct option *opt, const char *str,
>                                       int unset __maybe_unused)

Thanks for the test, I think this should fix it:

Thanks,
Namhyung


---8<---
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index ace66e69c1bcde1e..67a8ec10e9e4bc8d 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -76,7 +76,7 @@ int syscalltbl__id(int e_machine, const char *name)
 {
        const struct syscalltbl *table = find_table(e_machine);
        struct syscall_cmp_key key;
-       const int *id;
+       const uint16_t *id;
 
        if (!table)
                return -1;



From hongxing.zhu at nxp.com  Thu Mar 13 23:01:04 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Fri, 14 Mar 2025 14:01:04 +0800
Subject: [PATCH v1] arm64: dts: imx95: Correct the range of PCIe app-reg region
Message-ID: <20250314060104.390065-1-hongxing.zhu@nxp.com>

Correct the range of PCIe app-reg region from 0x2000 to 0x4000 refer to
SerDes_SS memory map of i.MX95 Rerference Manual.

Fixes: 3b1d5deb29ff ("arm64: dts: imx95: add pcie[0,1] and pcie-ep[0,1] support")
Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx95.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index 6b8470cb3461..0e6a9e639d76 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -1542,7 +1542,7 @@ pcie0: pcie at 4c300000 {
 			reg = <0 0x4c300000 0 0x10000>,
 			      <0 0x60100000 0 0xfe00000>,
 			      <0 0x4c360000 0 0x10000>,
-			      <0 0x4c340000 0 0x2000>;
+			      <0 0x4c340000 0 0x4000>;
 			reg-names = "dbi", "config", "atu", "app";
 			ranges = <0x81000000 0x0 0x00000000 0x0 0x6ff00000 0 0x00100000>,
 				 <0x82000000 0x0 0x10000000 0x9 0x10000000 0 0x10000000>;
@@ -1582,7 +1582,7 @@ pcie0_ep: pcie-ep at 4c300000 {
 			reg = <0 0x4c300000 0 0x10000>,
 			      <0 0x4c360000 0 0x1000>,
 			      <0 0x4c320000 0 0x1000>,
-			      <0 0x4c340000 0 0x2000>,
+			      <0 0x4c340000 0 0x4000>,
 			      <0 0x4c370000 0 0x10000>,
 			      <0x9 0 1 0>;
 			reg-names = "dbi","atu", "dbi2", "app", "dma", "addr_space";
@@ -1609,7 +1609,7 @@ pcie1: pcie at 4c380000 {
 			reg = <0 0x4c380000 0 0x10000>,
 			      <8 0x80100000 0 0xfe00000>,
 			      <0 0x4c3e0000 0 0x10000>,
-			      <0 0x4c3c0000 0 0x2000>;
+			      <0 0x4c3c0000 0 0x4000>;
 			reg-names = "dbi", "config", "atu", "app";
 			ranges = <0x81000000 0 0x00000000 0x8 0x8ff00000 0 0x00100000>,
 				 <0x82000000 0 0x10000000 0xa 0x10000000 0 0x10000000>;
@@ -1649,7 +1649,7 @@ pcie1_ep: pcie-ep at 4c380000 {
 			reg = <0 0x4c380000 0 0x10000>,
 			      <0 0x4c3e0000 0 0x1000>,
 			      <0 0x4c3a0000 0 0x1000>,
-			      <0 0x4c3c0000 0 0x2000>,
+			      <0 0x4c3c0000 0 0x4000>,
 			      <0 0x4c3f0000 0 0x10000>,
 			      <0xa 0 1 0>;
 			reg-names = "dbi", "atu", "dbi2", "app", "dma", "addr_space";
-- 
2.37.1



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:11 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:11 +0200
Subject: [PATCH v2 07/10] drm/msm/dsi/phy: add configuration for SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-7-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Qualcomm SAR2130P requires slightly different setup for the DSI PHY. It
is a 5nm PHY (like SM8450), so supplies are the same, but the rest of
the configuration is the same as SM8550 DSI PHY.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c     |  2 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h     |  1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 23 +++++++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index c0bcc68289633fd7506ce4f1f963655d862e8f08..a58bafe9fe8635730cb82e8c82ec1ded394988cd 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
 	  .data = &dsi_phy_7nm_cfgs },
 	{ .compatible = "qcom,dsi-phy-7nm-8150",
 	  .data = &dsi_phy_7nm_8150_cfgs },
+	{ .compatible = "qcom,sar2130p-dsi-phy-5nm",
+	  .data = &dsi_phy_5nm_sar2130p_cfgs },
 	{ .compatible = "qcom,sc7280-dsi-phy-7nm",
 	  .data = &dsi_phy_7nm_7280_cfgs },
 	{ .compatible = "qcom,sm6375-dsi-phy-7nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 1925418d9999a24263d6621299cae78f1fb9455c..1ed08b56e056094bc0096d07d4470b89d9824060 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -59,6 +59,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index a92decbee5b5433853ed973747f7705d9079068d..cad55702746b8d35949d22090796cca60f03b9e1 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -1289,6 +1289,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = {
 	.quirks = DSI_PHY_7NM_QUIRK_V4_3,
 };
 
+const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = {
+	.has_phy_lane = true,
+	.regulator_data = dsi_phy_7nm_97800uA_regulators,
+	.num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators),
+	.ops = {
+		.enable = dsi_7nm_phy_enable,
+		.disable = dsi_7nm_phy_disable,
+		.pll_init = dsi_pll_7nm_init,
+		.save_pll_state = dsi_7nm_pll_save_state,
+		.restore_pll_state = dsi_7nm_pll_restore_state,
+		.set_continuous_clock = dsi_7nm_set_continuous_clock,
+	},
+	.min_pll_rate = 600000000UL,
+#ifdef CONFIG_64BIT
+	.max_pll_rate = 5000000000UL,
+#else
+	.max_pll_rate = ULONG_MAX,
+#endif
+	.io_start = { 0xae95000, 0xae97000 },
+	.num_dsi_phy = 2,
+	.quirks = DSI_PHY_7NM_QUIRK_V5_2,
+};
+
 const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = {
 	.has_phy_lane = true,
 	.regulator_data = dsi_phy_7nm_98400uA_regulators,

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:12 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:12 +0200
Subject: [PATCH v2 08/10] drm/msm/dpu: add catalog entry for SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-8-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add DPU driver support for the Qualcomm SAR2130P platform. It is mostly
the same as SM8550, minor differences in the CDP configuration.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 .../drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h   | 434 +++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c     |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h     |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c            |   1 +
 4 files changed, 437 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
new file mode 100644
index 0000000000000000000000000000000000000000..22dd16c6e210e9520ecb7a851bee402032fa1ee2
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_9_1_SAR2130P_H
+#define _DPU_9_1_SAR2130P_H
+
+static const struct dpu_caps sar2130p_dpu_caps = {
+	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+	.max_mixer_blendstages = 0xb,
+	.has_src_split = true,
+	.has_dim_layer = true,
+	.has_idle_pc = true,
+	.has_3d_merge = true,
+	.max_linewidth = 5120,
+	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg sar2130p_mdp = {
+	.name = "top_0",
+	.base = 0, .len = 0x494,
+	.features = BIT(DPU_MDP_PERIPH_0_REMOVED),
+	.clk_ctrls = {
+		[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+	},
+};
+
+/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */
+static const struct dpu_ctl_cfg sar2130p_ctl[] = {
+	{
+		.name = "ctl_0", .id = CTL_0,
+		.base = 0x15000, .len = 0x290,
+		.features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+	}, {
+		.name = "ctl_1", .id = CTL_1,
+		.base = 0x16000, .len = 0x290,
+		.features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY),
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+	}, {
+		.name = "ctl_2", .id = CTL_2,
+		.base = 0x17000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+	}, {
+		.name = "ctl_3", .id = CTL_3,
+		.base = 0x18000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+	}, {
+		.name = "ctl_4", .id = CTL_4,
+		.base = 0x19000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+	}, {
+		.name = "ctl_5", .id = CTL_5,
+		.base = 0x1a000, .len = 0x290,
+		.features = CTL_SM8550_MASK,
+		.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+	},
+};
+
+static const struct dpu_sspp_cfg sar2130p_sspp[] = {
+	{
+		.name = "sspp_0", .id = SSPP_VIG0,
+		.base = 0x4000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 0,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_1", .id = SSPP_VIG1,
+		.base = 0x6000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 4,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_2", .id = SSPP_VIG2,
+		.base = 0x8000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 8,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_3", .id = SSPP_VIG3,
+		.base = 0xa000, .len = 0x344,
+		.features = VIG_SDM845_MASK_SDMA,
+		.sblk = &dpu_vig_sblk_qseed3_3_2,
+		.xin_id = 12,
+		.type = SSPP_TYPE_VIG,
+	}, {
+		.name = "sspp_8", .id = SSPP_DMA0,
+		.base = 0x24000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 1,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_9", .id = SSPP_DMA1,
+		.base = 0x26000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 5,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_10", .id = SSPP_DMA2,
+		.base = 0x28000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 9,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_11", .id = SSPP_DMA3,
+		.base = 0x2a000, .len = 0x344,
+		.features = DMA_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 13,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_12", .id = SSPP_DMA4,
+		.base = 0x2c000, .len = 0x344,
+		.features = DMA_CURSOR_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 14,
+		.type = SSPP_TYPE_DMA,
+	}, {
+		.name = "sspp_13", .id = SSPP_DMA5,
+		.base = 0x2e000, .len = 0x344,
+		.features = DMA_CURSOR_SDM845_MASK_SDMA,
+		.sblk = &dpu_dma_sblk,
+		.xin_id = 15,
+		.type = SSPP_TYPE_DMA,
+	},
+};
+
+static const struct dpu_lm_cfg sar2130p_lm[] = {
+	{
+		.name = "lm_0", .id = LM_0,
+		.base = 0x44000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_1,
+		.pingpong = PINGPONG_0,
+		.dspp = DSPP_0,
+	}, {
+		.name = "lm_1", .id = LM_1,
+		.base = 0x45000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_0,
+		.pingpong = PINGPONG_1,
+		.dspp = DSPP_1,
+	}, {
+		.name = "lm_2", .id = LM_2,
+		.base = 0x46000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_3,
+		.pingpong = PINGPONG_2,
+		.dspp = DSPP_2,
+	}, {
+		.name = "lm_3", .id = LM_3,
+		.base = 0x47000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_2,
+		.pingpong = PINGPONG_3,
+		.dspp = DSPP_3,
+	}, {
+		.name = "lm_4", .id = LM_4,
+		.base = 0x48000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_5,
+		.pingpong = PINGPONG_4,
+	}, {
+		.name = "lm_5", .id = LM_5,
+		.base = 0x49000, .len = 0x320,
+		.features = MIXER_SDM845_MASK,
+		.sblk = &sdm845_lm_sblk,
+		.lm_pair = LM_4,
+		.pingpong = PINGPONG_5,
+	},
+};
+
+static const struct dpu_dspp_cfg sar2130p_dspp[] = {
+	{
+		.name = "dspp_0", .id = DSPP_0,
+		.base = 0x54000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_1", .id = DSPP_1,
+		.base = 0x56000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_2", .id = DSPP_2,
+		.base = 0x58000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	}, {
+		.name = "dspp_3", .id = DSPP_3,
+		.base = 0x5a000, .len = 0x1800,
+		.features = DSPP_SC7180_MASK,
+		.sblk = &sdm845_dspp_sblk,
+	},
+};
+static const struct dpu_pingpong_cfg sar2130p_pp[] = {
+	{
+		.name = "pingpong_0", .id = PINGPONG_0,
+		.base = 0x69000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_0,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+	}, {
+		.name = "pingpong_1", .id = PINGPONG_1,
+		.base = 0x6a000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_0,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+	}, {
+		.name = "pingpong_2", .id = PINGPONG_2,
+		.base = 0x6b000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_1,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+	}, {
+		.name = "pingpong_3", .id = PINGPONG_3,
+		.base = 0x6c000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_1,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+	}, {
+		.name = "pingpong_4", .id = PINGPONG_4,
+		.base = 0x6d000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_2,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
+	}, {
+		.name = "pingpong_5", .id = PINGPONG_5,
+		.base = 0x6e000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_2,
+		.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
+	}, {
+		.name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
+		.base = 0x66000, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_3,
+	}, {
+		.name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
+		.base = 0x66400, .len = 0,
+		.features = BIT(DPU_PINGPONG_DITHER),
+		.sblk = &sc7280_pp_sblk,
+		.merge_3d = MERGE_3D_3,
+	},
+};
+
+static const struct dpu_merge_3d_cfg sar2130p_merge_3d[] = {
+	{
+		.name = "merge_3d_0", .id = MERGE_3D_0,
+		.base = 0x4e000, .len = 0x8,
+	}, {
+		.name = "merge_3d_1", .id = MERGE_3D_1,
+		.base = 0x4f000, .len = 0x8,
+	}, {
+		.name = "merge_3d_2", .id = MERGE_3D_2,
+		.base = 0x50000, .len = 0x8,
+	}, {
+		.name = "merge_3d_3", .id = MERGE_3D_3,
+		.base = 0x66700, .len = 0x8,
+	},
+};
+
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sar2130p_dsc[] = {
+	{
+		.name = "dce_0_0", .id = DSC_0,
+		.base = 0x80000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2),
+		.sblk = &dsc_sblk_0,
+	}, {
+		.name = "dce_0_1", .id = DSC_1,
+		.base = 0x80000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2),
+		.sblk = &dsc_sblk_1,
+	}, {
+		.name = "dce_1_0", .id = DSC_2,
+		.base = 0x81000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+		.sblk = &dsc_sblk_0,
+	}, {
+		.name = "dce_1_1", .id = DSC_3,
+		.base = 0x81000, .len = 0x4,
+		.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+		.sblk = &dsc_sblk_1,
+	},
+};
+
+static const struct dpu_wb_cfg sar2130p_wb[] = {
+	{
+		.name = "wb_2", .id = WB_2,
+		.base = 0x65000, .len = 0x2c8,
+		.features = WB_SM8250_MASK,
+		.format_list = wb2_formats_rgb_yuv,
+		.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
+		.xin_id = 6,
+		.vbif_idx = VBIF_RT,
+		.maxlinewidth = 4096,
+		.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
+	},
+};
+
+static const struct dpu_intf_cfg sar2130p_intf[] = {
+	{
+		.name = "intf_0", .id = INTF_0,
+		.base = 0x34000, .len = 0x280,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DP,
+		.controller_id = MSM_DP_CONTROLLER_0,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+	}, {
+		.name = "intf_1", .id = INTF_1,
+		.base = 0x35000, .len = 0x300,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DSI,
+		.controller_id = MSM_DSI_CONTROLLER_0,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+		.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2),
+	}, {
+		.name = "intf_2", .id = INTF_2,
+		.base = 0x36000, .len = 0x300,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DSI,
+		.controller_id = MSM_DSI_CONTROLLER_1,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+		.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2),
+	}, {
+		.name = "intf_3", .id = INTF_3,
+		.base = 0x37000, .len = 0x280,
+		.features = INTF_SC7280_MASK,
+		.type = INTF_DP,
+		.controller_id = MSM_DP_CONTROLLER_1,
+		.prog_fetch_lines_worst_case = 24,
+		.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+		.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
+	},
+};
+
+static const struct dpu_perf_cfg sar2130p_perf_data = {
+	.max_bw_low = 13600000,
+	.max_bw_high = 18200000,
+	.min_core_ib = 2500000,
+	.min_llcc_ib = 0,
+	.min_dram_ib = 800000,
+	.min_prefill_lines = 35,
+	/* FIXME: lut tables */
+	.danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0},
+	.safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
+	.qos_lut_tbl = {
+		{.nentry = ARRAY_SIZE(sc7180_qos_linear),
+		.entries = sc7180_qos_linear
+		},
+		{.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+		.entries = sc7180_qos_macrotile
+		},
+		{.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+		.entries = sc7180_qos_nrt
+		},
+		/* TODO: macrotile-qseed is different from macrotile */
+	},
+	.cdp_cfg = {
+		{.rd_enable = 0, .wr_enable = 0},
+		{.rd_enable = 0, .wr_enable = 0}
+	},
+	.clk_inefficiency_factor = 105,
+	.bw_inefficiency_factor = 120,
+};
+
+static const struct dpu_mdss_version sar2130p_mdss_ver = {
+	.core_major_ver = 9,
+	.core_minor_ver = 1,
+};
+
+const struct dpu_mdss_cfg dpu_sar2130p_cfg = {
+	.mdss_ver = &sar2130p_mdss_ver,
+	.caps = &sar2130p_dpu_caps,
+	.mdp = &sar2130p_mdp,
+	.cdm = &dpu_cdm_5_x,
+	.ctl_count = ARRAY_SIZE(sar2130p_ctl),
+	.ctl = sar2130p_ctl,
+	.sspp_count = ARRAY_SIZE(sar2130p_sspp),
+	.sspp = sar2130p_sspp,
+	.mixer_count = ARRAY_SIZE(sar2130p_lm),
+	.mixer = sar2130p_lm,
+	.dspp_count = ARRAY_SIZE(sar2130p_dspp),
+	.dspp = sar2130p_dspp,
+	.pingpong_count = ARRAY_SIZE(sar2130p_pp),
+	.pingpong = sar2130p_pp,
+	.dsc_count = ARRAY_SIZE(sar2130p_dsc),
+	.dsc = sar2130p_dsc,
+	.merge_3d_count = ARRAY_SIZE(sar2130p_merge_3d),
+	.merge_3d = sar2130p_merge_3d,
+	.wb_count = ARRAY_SIZE(sar2130p_wb),
+	.wb = sar2130p_wb,
+	.intf_count = ARRAY_SIZE(sar2130p_intf),
+	.intf = sar2130p_intf,
+	.vbif_count = ARRAY_SIZE(sm8550_vbif),
+	.vbif = sm8550_vbif,
+	.perf = &sar2130p_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 64265ca4656a04d8c5a1d9582d7124c7eb897099..ce8d88e1d8b8bc6dea893f13a0449315ac8d2841 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -759,7 +759,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
 #include "catalog/dpu_8_4_sa8775p.h"
 
 #include "catalog/dpu_9_0_sm8550.h"
-
+#include "catalog/dpu_9_1_sar2130p.h"
 #include "catalog/dpu_9_2_x1e80100.h"
 
 #include "catalog/dpu_10_0_sm8650.h"
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 4cea19e1a20380c56ae014f2d33a6884a72e0ca0..e9b627e02c8996c8fb611e8e333a35e7ce9b8373 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -841,6 +841,7 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8953_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8996_cfg;
 extern const struct dpu_mdss_cfg dpu_msm8998_cfg;
+extern const struct dpu_mdss_cfg dpu_sar2130p_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm630_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm660_cfg;
 extern const struct dpu_mdss_cfg dpu_sdm845_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 3305ad0623ca41882db0172e65a9beb7ebe00b6c..1fd82b6747e9058ce11dc2620729921492d5ebdd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1512,6 +1512,7 @@ static const struct of_device_id dpu_dt_match[] = {
 	{ .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, },
 	{ .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, },
 	{ .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, },
+	{ .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, },
 	{ .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, },
 	{ .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, },
 	{ .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, },

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:13 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:13 +0200
Subject: [PATCH v2 09/10] iommu/arm-smmu-qcom: Add SAR2130P MDSS compatible
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-9-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add the SAR2130P compatible to clients compatible list, the device
require identity domain.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 59d02687280e8d37b5e944619fcfe4ebd1bd6926..ecc4a1bc9477b766f317a58ef8b5dbcfe448afa9 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -356,6 +356,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
 	{ .compatible = "qcom,mdp4" },
 	{ .compatible = "qcom,mdss" },
 	{ .compatible = "qcom,qcm2290-mdss" },
+	{ .compatible = "qcom,sar2130p-mdss" },
 	{ .compatible = "qcom,sc7180-mdss" },
 	{ .compatible = "qcom,sc7180-mss-pil" },
 	{ .compatible = "qcom,sc7280-mdss" },

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:04 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:04 +0200
Subject: [PATCH v2 00/10] drm/msm: add support for SAR2130P
Message-ID: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>

Add support for the Mobile Display SubSystem (MDSS) device present on
the Qualcomm SAR2130P platform. The MDSS device is similar to SM8550, it
features two MIPI DSI controllers, two MIPI DSI PHYs and one DisplayPort
controller.

Note, due to the technical limitations DP controller wasn't completely
evaluated.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
Changes in v2:
- In MDSS schema switched from list items to contains: (Krzyztof)
- In MDSS schema dropped extra empty lines (Krzysztof)
- Fixed .ubwc_bank_spread in msm_mdss. (LKP)
- Link to v1: https://lore.kernel.org/r/20250308-sar2130p-display-v1-0-1d4c30f43822 at linaro.org

---
Dmitry Baryshkov (10):
      dt-bindings: display/msm: dp-controller: describe SAR2130P
      dt-bindings: display/msm: dsi-controller-main: describe SAR2130P
      dt-bindings: display/msm: dsi-phy-7nm: describe SAR2130P
      dt-bindings: display/msm: qcom,sc7280-dpu: describe SAR2130P
      dt-bindings: display/msm: Add Qualcomm SAR2130P
      drm/msm/mdss: add SAR2130P device configuration
      drm/msm/dsi/phy: add configuration for SAR2130P
      drm/msm/dpu: add catalog entry for SAR2130P
      iommu/arm-smmu-qcom: Add SAR2130P MDSS compatible
      arm64: dts: qcom: sar2130p: add display nodes

 .../bindings/display/msm/dp-controller.yaml        |   1 +
 .../bindings/display/msm/dsi-controller-main.yaml  |   2 +
 .../bindings/display/msm/dsi-phy-7nm.yaml          |   1 +
 .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 439 +++++++++++++++++++++
 .../bindings/display/msm/qcom,sc7280-dpu.yaml      |   1 +
 arch/arm64/boot/dts/qcom/sar2130p.dtsi             | 394 ++++++++++++++++++
 .../drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h   | 434 ++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c     |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h     |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c            |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c              |   2 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h              |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c          |  23 ++
 drivers/gpu/drm/msm/msm_mdss.c                     |  11 +
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c         |   1 +
 15 files changed, 1313 insertions(+), 1 deletion(-)
---
base-commit: 613af589b566093ce7388bf3202fca70d742c166
change-id: 20250308-sar2130p-display-b0601fcfeb30

Best regards,
-- 
Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:05 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:05 +0200
Subject: [PATCH v2 01/10] dt-bindings: display/msm: dp-controller: describe
 SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-1-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe DisplayPort controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index e00b88332f2fed2fc33f6d72c5cc3d827cd7594e..246bbb509bea18bed32e3a442d0926a24498c960 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -31,6 +31,7 @@ properties:
           - qcom,sm8650-dp
       - items:
           - enum:
+              - qcom,sar2130p-dp
               - qcom,sm6350-dp
               - qcom,sm8150-dp
               - qcom,sm8250-dp

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:06 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:06 +0200
Subject: [PATCH v2 02/10] dt-bindings: display/msm: dsi-controller-main:
 describe SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-2-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe MIPI DSI controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 2aab33cd0017cd4a0c915b7297bb3952e62561fa..a3e05e34bf14dd5802fc538ca8b69846384f8742 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -23,6 +23,7 @@ properties:
               - qcom,msm8996-dsi-ctrl
               - qcom,msm8998-dsi-ctrl
               - qcom,qcm2290-dsi-ctrl
+              - qcom,sar2130p-dsi-ctrl
               - qcom,sc7180-dsi-ctrl
               - qcom,sc7280-dsi-ctrl
               - qcom,sdm660-dsi-ctrl
@@ -314,6 +315,7 @@ allOf:
           contains:
             enum:
               - qcom,msm8998-dsi-ctrl
+              - qcom,sar2130p-dsi-ctrl
               - qcom,sc7180-dsi-ctrl
               - qcom,sc7280-dsi-ctrl
               - qcom,sdm845-dsi-ctrl

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:07 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:07 +0200
Subject: [PATCH v2 03/10] dt-bindings: display/msm: dsi-phy-7nm: describe
 SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-3-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe MIPI DSI PHY present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
index 321470435e654f1d569fc54f6a810e3f70fb168c..f79be422b8892484216b407f7385789764c2de1b 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
@@ -17,6 +17,7 @@ properties:
     enum:
       - qcom,dsi-phy-7nm
       - qcom,dsi-phy-7nm-8150
+      - qcom,sar2130p-dsi-phy-5nm
       - qcom,sc7280-dsi-phy-7nm
       - qcom,sm6375-dsi-phy-7nm
       - qcom,sm8350-dsi-phy-5nm

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:08 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:08 +0200
Subject: [PATCH v2 04/10] dt-bindings: display/msm: qcom,sc7280-dpu:
 describe SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-4-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe DPU controller present on Qualcomm SAR2130P platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
index 6902795b4e2c249c2b543c1c5350f739a30553f2..df9ec15ad6c3ca1f77bebaab19ffa3adb985733d 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
@@ -17,6 +17,7 @@ $ref: /schemas/display/msm/dpu-common.yaml#
 properties:
   compatible:
     enum:
+      - qcom,sar2130p-dpu
       - qcom,sc7280-dpu
       - qcom,sc8280xp-dpu
       - qcom,sm8350-dpu

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:09 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:09 +0200
Subject: [PATCH v2 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-5-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Describe the Mobile Display SubSystem (MDSS) device present on the
Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
system level. SAR2130P features two DSI hosts and single DisplayPort
controller.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 439 +++++++++++++++++++++
 1 file changed, 439 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..870144b53cec9d3e0892276e14b49b745d021879
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.yaml
@@ -0,0 +1,439 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sar2130p-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SAR2130P Display MDSS
+
+maintainers:
+  - Dmitry Baryshkov <lumag at kernel.org>
+
+description:
+  SAR2310P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
+  DPU display controller, DSI and DP interfaces etc.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+  compatible:
+    const: qcom,sar2130p-mdss
+
+  clocks:
+    items:
+      - description: Display MDSS AHB
+      - description: Display AHB
+      - description: Display hf AXI
+      - description: Display core
+
+  iommus:
+    maxItems: 1
+
+  interconnects:
+    items:
+      - description: Interconnect path from mdp0 port to the data bus
+      - description: Interconnect path from CPU to the reg bus
+
+  interconnect-names:
+    items:
+      - const: mdp0-mem
+      - const: cpu-cfg
+
+patternProperties:
+  "^display-controller@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        const: qcom,sar2130p-dpu
+
+  "^displayport-controller@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        contains:
+          const: qcom,sar2130p-dp
+
+  "^dsi@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        contains:
+          const: qcom,sar2130p-dsi-ctrl
+
+  "^phy@[0-9a-f]+$":
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        const: qcom,sar2130p-dsi-phy-5nm
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/qcom,rpmhpd.h>
+    #include <dt-bindings/phy/phy-qcom-qmp.h>
+
+    display-subsystem at ae00000 {
+        compatible = "qcom,sar2130p-mdss";
+        reg = <0x0ae00000 0x1000>;
+        reg-names = "mdss";
+
+        interconnects = <&mmss_noc_master_mdp &mc_virt_slave_ebi1>,
+                        <&gem_noc_master_appss_proc &config_noc_slave_display_cfg>;
+        interconnect-names = "mdp0-mem", "cpu-cfg";
+
+        resets = <&dispcc_disp_cc_mdss_core_bcr>;
+
+        power-domains = <&dispcc_mdss_gdsc>;
+
+        clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                 <&gcc_gcc_disp_ahb_clk>,
+                 <&gcc_gcc_disp_hf_axi_clk>,
+                 <&dispcc_disp_cc_mdss_mdp_clk>;
+        clock-names = "iface", "bus", "nrt_bus", "core";
+
+        interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-controller;
+        #interrupt-cells = <1>;
+
+        iommus = <&apps_smmu 0x1c00 0x2>;
+
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        display-controller at ae01000 {
+            compatible = "qcom,sar2130p-dpu";
+            reg = <0x0ae01000 0x8f000>,
+                  <0x0aeb0000 0x2008>;
+            reg-names = "mdp", "vbif";
+
+            clocks = <&gcc_gcc_disp_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&dispcc_disp_cc_mdss_mdp_lut_clk>,
+                     <&dispcc_disp_cc_mdss_mdp_clk>,
+                     <&dispcc_disp_cc_mdss_vsync_clk>;
+            clock-names = "bus",
+                          "nrt_bus",
+                          "iface",
+                          "lut",
+                          "core",
+                          "vsync";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_vsync_clk>;
+            assigned-clock-rates = <19200000>;
+
+            operating-points-v2 = <&mdp_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            interrupt-parent = <&mdss>;
+            interrupts = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    dpu_intf0_out: endpoint {
+                        remote-endpoint = <&mdss_dp0_in>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    dpu_intf1_out: endpoint {
+                        remote-endpoint = <&mdss_dsi0_in>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <2>;
+
+                    dpu_intf2_out: endpoint {
+                        remote-endpoint = <&mdss_dsi1_in>;
+                    };
+                };
+            };
+
+            mdp_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-200000000 {
+                    opp-hz = /bits/ 64 <200000000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-325000000 {
+                    opp-hz = /bits/ 64 <325000000>;
+                    required-opps = <&rpmhpd_opp_svs>;
+                };
+
+                opp-375000000 {
+                    opp-hz = /bits/ 64 <375000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+
+                opp-514000000 {
+                    opp-hz = /bits/ 64 <514000000>;
+                    required-opps = <&rpmhpd_opp_nom>;
+                };
+            };
+        };
+
+        displayport-controller at ae90000 {
+            compatible = "qcom,sar2130p-dp",
+                         "qcom,sm8350-dp";
+            reg = <0xae90000 0x200>,
+                  <0xae90200 0x200>,
+                  <0xae90400 0xc00>,
+                  <0xae91000 0x400>,
+                  <0xae91400 0x400>;
+
+            interrupt-parent = <&mdss>;
+            interrupts = <12>;
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_aux_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_link_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
+                     <&dispcc_disp_cc_mdss_dptx0_pixel0_clk>;
+            clock-names = "core_iface",
+                          "core_aux",
+                          "ctrl_link",
+                          "ctrl_link_iface",
+                          "stream_pixel";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
+                              <&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>;
+            assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
+                                     <&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
+
+            phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
+            phy-names = "dp";
+
+            #sound-dai-cells = <0>;
+
+            operating-points-v2 = <&dp_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+                    mdss_dp0_in: endpoint {
+                        remote-endpoint = <&dpu_intf0_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+                    mdss_dp0_out: endpoint {
+                        remote-endpoint = <&usb_dp_qmpphy_dp_in>;
+                    };
+                };
+        };
+
+        dp_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-162000000 {
+                    opp-hz = /bits/ 64 <162000000>;
+                    required-opps = <&rpmhpd_opp_low_svs_d1>;
+                };
+
+                opp-270000000 {
+                    opp-hz = /bits/ 64 <270000000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-540000000 {
+                    opp-hz = /bits/ 64 <540000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+
+                opp-810000000 {
+                    opp-hz = /bits/ 64 <810000000>;
+                    required-opps = <&rpmhpd_opp_nom>;
+                };
+            };
+        };
+
+        dsi at ae94000 {
+            compatible = "qcom,sar2130p-dsi-ctrl",
+                         "qcom,mdss-dsi-ctrl";
+            reg = <0x0ae94000 0x400>;
+            reg-names = "dsi_ctrl";
+
+            interrupt-parent = <&mdss>;
+            interrupts = <4>;
+
+            clocks = <&dispcc_disp_cc_mdss_byte0_clk>,
+                     <&dispcc_disp_cc_mdss_byte0_intf_clk>,
+                     <&dispcc_disp_cc_mdss_pclk0_clk>,
+                     <&dispcc_disp_cc_mdss_esc0_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>;
+            clock-names = "byte",
+                          "byte_intf",
+                          "pixel",
+                          "core",
+                          "iface",
+                          "bus";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_byte0_clk_src>,
+                              <&dispcc_disp_cc_mdss_pclk0_clk_src>;
+            assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>;
+
+            operating-points-v2 = <&dsi_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            phys = <&mdss_dsi0_phy>;
+            phy-names = "dsi";
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    mdss_dsi0_in: endpoint {
+                        remote-endpoint = <&dpu_intf1_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    mdss_dsi0_out: endpoint {
+                    };
+                };
+            };
+
+            dsi_opp_table: opp-table {
+                compatible = "operating-points-v2";
+
+                opp-187500000 {
+                    opp-hz = /bits/ 64 <187500000>;
+                    required-opps = <&rpmhpd_opp_low_svs>;
+                };
+
+                opp-300000000 {
+                    opp-hz = /bits/ 64 <300000000>;
+                    required-opps = <&rpmhpd_opp_svs>;
+                };
+
+                opp-358000000 {
+                    opp-hz = /bits/ 64 <358000000>;
+                    required-opps = <&rpmhpd_opp_svs_l1>;
+                };
+            };
+        };
+
+        mdss_dsi0_phy: phy at ae94400 {
+            compatible = "qcom,sar2130p-dsi-phy-5nm";
+            reg = <0x0ae95000 0x200>,
+                  <0x0ae95200 0x280>,
+                  <0x0ae95500 0x400>;
+            reg-names = "dsi_phy",
+                        "dsi_phy_lane",
+                        "dsi_pll";
+
+            #clock-cells = <1>;
+            #phy-cells = <0>;
+
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&rpmhcc_rpmh_cxo_clk>;
+            clock-names = "iface", "ref";
+        };
+
+        dsi at ae96000 {
+            compatible = "qcom,sar2130p-dsi-ctrl",
+                         "qcom,mdss-dsi-ctrl";
+            reg = <0x0ae96000 0x400>;
+            reg-names = "dsi_ctrl";
+
+            interrupt-parent = <&mdss>;
+            interrupts = <5>;
+
+            clocks = <&dispcc_disp_cc_mdss_byte1_clk>,
+                     <&dispcc_disp_cc_mdss_byte1_intf_clk>,
+                     <&dispcc_disp_cc_mdss_pclk1_clk>,
+                     <&dispcc_disp_cc_mdss_esc1_clk>,
+                     <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&gcc_gcc_disp_hf_axi_clk>;
+            clock-names = "byte",
+                          "byte_intf",
+                          "pixel",
+                          "core",
+                          "iface",
+                          "bus";
+
+            assigned-clocks = <&dispcc_disp_cc_mdss_byte1_clk_src>,
+                              <&dispcc_disp_cc_mdss_pclk1_clk_src>;
+            assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>;
+
+            operating-points-v2 = <&dsi_opp_table>;
+            power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+            phys = <&mdss_dsi1_phy>;
+            phy-names = "dsi";
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port at 0 {
+                    reg = <0>;
+
+                    mdss_dsi1_in: endpoint {
+                        remote-endpoint = <&dpu_intf2_out>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <1>;
+
+                    mdss_dsi1_out: endpoint {
+                    };
+                };
+            };
+        };
+
+        mdss_dsi1_phy: phy at ae97000 {
+            compatible = "qcom,sar2130p-dsi-phy-5nm";
+            reg = <0x0ae97000 0x200>,
+                  <0x0ae97200 0x280>,
+                  <0x0ae97500 0x400>;
+            reg-names = "dsi_phy",
+                        "dsi_phy_lane",
+                        "dsi_pll";
+
+            #clock-cells = <1>;
+            #phy-cells = <0>;
+
+            clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
+                     <&rpmhcc_rpmh_cxo_clk>;
+            clock-names = "iface", "ref";
+        };
+    };
+...

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:10 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:10 +0200
Subject: [PATCH v2 06/10] drm/msm/mdss: add SAR2130P device configuration
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-6-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add compatible and device configuration for the Qualcomm SAR2130P
platform.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/gpu/drm/msm/msm_mdss.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index dcb49fd30402b80edd2cb5971f95a78eaad6081f..f706e44231a9c360ac4abe26e4050e416d8c3940 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -592,6 +592,16 @@ static const struct msm_mdss_data sa8775p_data = {
 	.reg_bus_bw = 74000,
 };
 
+static const struct msm_mdss_data sar2130p_data = {
+	.ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */
+	.ubwc_dec_version = UBWC_4_3,
+	.ubwc_swizzle = 6,
+	.ubwc_bank_spread = true,
+	.highest_bank_bit = 0,
+	.macrotile_mode = 1,
+	.reg_bus_bw = 74000,
+};
+
 static const struct msm_mdss_data sc7180_data = {
 	.ubwc_enc_version = UBWC_2_0,
 	.ubwc_dec_version = UBWC_2_0,
@@ -738,6 +748,7 @@ static const struct of_device_id mdss_dt_match[] = {
 	{ .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
 	{ .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
 	{ .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data },
+	{ .compatible = "qcom,sar2130p-mdss", .data = &sar2130p_data },
 	{ .compatible = "qcom,sdm670-mdss", .data = &sdm670_data },
 	{ .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
 	{ .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Thu Mar 13 23:09:14 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 14 Mar 2025 08:09:14 +0200
Subject: [PATCH v2 10/10] arm64: dts: qcom: sar2130p: add display nodes
In-Reply-To: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
References: <20250314-sar2130p-display-v2-0-31fa4502a850@oss.qualcomm.com>
Message-ID: <20250314-sar2130p-display-v2-10-31fa4502a850@oss.qualcomm.com>

From: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>

Add display controller, two DSI hosts, two DSI PHYs and a single DP
controller. Link DP to the QMP Combo PHY.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 arch/arm64/boot/dts/qcom/sar2130p.dtsi | 394 +++++++++++++++++++++++++++++++++
 1 file changed, 394 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sar2130p.dtsi b/arch/arm64/boot/dts/qcom/sar2130p.dtsi
index dd832e6816be85817fd1ecc853f8d4c800826bc4..4e1816fcda8168e98e27b8bc0f8b5150c03276d2 100644
--- a/arch/arm64/boot/dts/qcom/sar2130p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sar2130p.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/clock/qcom,sar2130p-gcc.h>
 #include <dt-bindings/clock/qcom,sar2130p-gpucc.h>
+#include <dt-bindings/clock/qcom,sm8550-dispcc.h>
 #include <dt-bindings/clock/qcom,sm8550-tcsr.h>
 #include <dt-bindings/dma/qcom-gpi.h>
 #include <dt-bindings/interconnect/qcom,icc.h>
@@ -1854,6 +1855,7 @@ port at 2 {
 					reg = <2>;
 
 					usb_dp_qmpphy_dp_in: endpoint {
+						remote-endpoint = <&mdss_dp0_out>;
 					};
 				};
 			};
@@ -1951,6 +1953,398 @@ usb_1_dwc3_ss: endpoint {
 			};
 		};
 
+		mdss: display-subsystem at ae00000 {
+			compatible = "qcom,sar2130p-mdss";
+			reg = <0x0 0x0ae00000 0x0 0x1000>;
+			reg-names = "mdss";
+
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+
+			clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+				 <&gcc GCC_DISP_AHB_CLK>,
+				 <&gcc GCC_DISP_HF_AXI_CLK>,
+				 <&dispcc DISP_CC_MDSS_MDP_CLK>;
+
+			resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
+
+			power-domains = <&dispcc MDSS_GDSC>;
+
+			interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ACTIVE_ONLY
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>,
+					<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+					 &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+			interconnect-names = "mdp0-mem", "cpu-cfg";
+
+			iommus = <&apps_smmu 0x2000 0x402>;
+
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			status = "disabled";
+
+			mdss_mdp: display-controller at ae01000 {
+				compatible = "qcom,sar2130p-dpu";
+				reg = <0x0 0x0ae01000 0x0 0x8f000>,
+				      <0x0 0x0aeb0000 0x0 0x2008>;
+				reg-names = "mdp",
+					    "vbif";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <0>;
+
+				clocks = <&gcc GCC_DISP_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+					 <&dispcc DISP_CC_MDSS_MDP_CLK>,
+					 <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+				clock-names = "bus",
+					      "nrt_bus",
+					      "iface",
+					      "lut",
+					      "core",
+					      "vsync";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+				assigned-clock-rates = <19200000>;
+
+				operating-points-v2 = <&mdp_opp_table>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						dpu_intf1_out: endpoint {
+							remote-endpoint = <&mdss_dsi0_in>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						dpu_intf2_out: endpoint {
+							remote-endpoint = <&mdss_dsi1_in>;
+						};
+					};
+
+					port at 2 {
+						reg = <2>;
+
+						dpu_intf0_out: endpoint {
+							remote-endpoint = <&mdss_dp0_in>;
+						};
+					};
+				};
+
+				mdp_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-200000000 {
+						opp-hz = /bits/ 64 <200000000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-325000000 {
+						opp-hz = /bits/ 64 <325000000>;
+						required-opps = <&rpmhpd_opp_svs>;
+					};
+
+					opp-514000000 {
+						opp-hz = /bits/ 64 <514000000>;
+						required-opps = <&rpmhpd_opp_turbo>;
+					};
+				};
+			};
+
+			mdss_dp0: displayport-controller at ae90000 {
+				compatible = "qcom,sar2130p-dp",
+					     "qcom,sm8350-dp";
+				reg = <0x0 0xae90000 0x0 0x200>,
+				      <0x0 0xae90200 0x0 0x200>,
+				      <0x0 0xae90400 0x0 0xc00>,
+				      <0x0 0xae91000 0x0 0x400>,
+				      <0x0 0xae91400 0x0 0x400>;
+				interrupt-parent = <&mdss>;
+				interrupts = <12>;
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_AUX_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK>;
+				clock-names = "core_iface",
+					      "core_aux",
+					      "ctrl_link",
+					      "ctrl_link_iface",
+					      "stream_pixel";
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>;
+				assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+							 <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+
+				phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
+				phy-names = "dp";
+
+				#sound-dai-cells = <0>;
+
+				operating-points-v2 = <&dp_opp_table>;
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						mdss_dp0_in: endpoint {
+							remote-endpoint = <&dpu_intf0_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						mdss_dp0_out: endpoint {
+							remote-endpoint = <&usb_dp_qmpphy_dp_in>;
+						};
+					};
+				};
+
+				dp_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-162000000 {
+						opp-hz = /bits/ 64 <162000000>;
+						required-opps = <&rpmhpd_opp_low_svs_d1>;
+					};
+
+					opp-270000000 {
+						opp-hz = /bits/ 64 <270000000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-540000000 {
+						opp-hz = /bits/ 64 <540000000>;
+						required-opps = <&rpmhpd_opp_svs_l1>;
+					};
+
+					opp-810000000 {
+						opp-hz = /bits/ 64 <810000000>;
+						required-opps = <&rpmhpd_opp_nom>;
+					};
+				};
+			};
+
+			mdss_dsi0: dsi at ae94000 {
+				compatible = "qcom,sar2130p-dsi-ctrl",
+					     "qcom,mdss-dsi-ctrl";
+				reg = <0x0 0x0ae94000 0x0 0x400>;
+				reg-names = "dsi_ctrl";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <4>;
+
+				clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+					 <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+					 <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>;
+				clock-names = "byte",
+					      "byte_intf",
+					      "pixel",
+					      "core",
+					      "iface",
+					      "bus";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+				assigned-clock-parents = <&mdss_dsi0_phy 0>,
+							 <&mdss_dsi0_phy 1>;
+
+				operating-points-v2 = <&mdss_dsi_opp_table>;
+
+				phys = <&mdss_dsi0_phy>;
+				phy-names = "dsi";
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+						mdss_dsi0_in: endpoint {
+							remote-endpoint = <&dpu_intf1_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+						mdss_dsi0_out: endpoint {
+						};
+					};
+				};
+
+				mdss_dsi_opp_table: opp-table {
+					compatible = "operating-points-v2";
+
+					opp-187500000 {
+						opp-hz = /bits/ 64 <187500000>;
+						required-opps = <&rpmhpd_opp_low_svs>;
+					};
+
+					opp-300000000 {
+						opp-hz = /bits/ 64 <300000000>;
+						required-opps = <&rpmhpd_opp_svs>;
+					};
+
+					opp-358000000 {
+						opp-hz = /bits/ 64 <358000000>;
+						required-opps = <&rpmhpd_opp_nom>;
+					};
+				};
+			};
+
+			mdss_dsi0_phy: phy at ae95000 {
+				compatible = "qcom,sar2130p-dsi-phy-5nm";
+				reg = <0x0 0x0ae95000 0x0 0x200>,
+				      <0x0 0x0ae95200 0x0 0x280>,
+				      <0x0 0x0ae95500 0x0 0x400>;
+				reg-names = "dsi_phy",
+					    "dsi_phy_lane",
+					    "dsi_pll";
+
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&rpmhcc RPMH_CXO_CLK>;
+				clock-names = "iface", "ref";
+
+				#clock-cells = <1>;
+				#phy-cells = <0>;
+
+				status = "disabled";
+			};
+
+			mdss_dsi1: dsi at ae96000 {
+				compatible = "qcom,sar2130p-dsi-ctrl",
+					     "qcom,mdss-dsi-ctrl";
+				reg = <0x0 0x0ae96000 0x0 0x400>;
+				reg-names = "dsi_ctrl";
+
+				interrupt-parent = <&mdss>;
+				interrupts = <5>;
+
+				clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
+					 <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+					 <&dispcc DISP_CC_MDSS_PCLK1_CLK>,
+					 <&dispcc DISP_CC_MDSS_ESC1_CLK>,
+					 <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&gcc GCC_DISP_HF_AXI_CLK>;
+				clock-names = "byte",
+					      "byte_intf",
+					      "pixel",
+					      "core",
+					      "iface",
+					      "bus";
+
+				power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+				assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+						  <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+				assigned-clock-parents = <&mdss_dsi1_phy 0>,
+							 <&mdss_dsi1_phy 1>;
+
+				operating-points-v2 = <&mdss_dsi_opp_table>;
+
+				phys = <&mdss_dsi1_phy>;
+				phy-names = "dsi";
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				status = "disabled";
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+						mdss_dsi1_in: endpoint {
+							remote-endpoint = <&dpu_intf2_out>;
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+						mdss_dsi1_out: endpoint {
+						};
+					};
+				};
+			};
+
+			mdss_dsi1_phy: phy at ae97000 {
+				compatible = "qcom,sar2130p-dsi-phy-5nm";
+				reg = <0x0 0x0ae97000 0x0 0x200>,
+				      <0x0 0x0ae97200 0x0 0x280>,
+				      <0x0 0x0ae97500 0x0 0x400>;
+				reg-names = "dsi_phy",
+					    "dsi_phy_lane",
+					    "dsi_pll";
+
+				clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+					 <&rpmhcc RPMH_CXO_CLK>;
+				clock-names = "iface", "ref";
+
+				#clock-cells = <1>;
+				#phy-cells = <0>;
+
+				status = "disabled";
+			};
+		};
+
+		dispcc: clock-controller at af00000 {
+			compatible = "qcom,sar2130p-dispcc";
+			reg = <0x0 0x0af00000 0x0 0x20000>;
+			clocks = <&rpmhcc RPMH_CXO_CLK>,
+				 <&rpmhcc RPMH_CXO_CLK_A>,
+				 <&gcc GCC_DISP_AHB_CLK>,
+				 <&sleep_clk>,
+				 <&mdss_dsi0_phy 0>,
+				 <&mdss_dsi0_phy 1>,
+				 <&mdss_dsi1_phy 0>,
+				 <&mdss_dsi1_phy 1>,
+				 <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+				 <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
+				 <0>, /* dp1 */
+				 <0>,
+				 <0>, /* dp2 */
+				 <0>,
+				 <0>, /* dp3 */
+				 <0>;
+			power-domains = <&rpmhpd RPMHPD_MMCX>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#power-domain-cells = <1>;
+		};
+
 		pdc: interrupt-controller at b220000 {
 			compatible = "qcom,sar2130p-pdc", "qcom,pdc";
 			reg = <0x0 0x0b220000 0x0 0x30000>, <0x0 0x174000f0 0x0 0x64>;

-- 
2.39.5



From danishanwar at ti.com  Thu Mar 13 23:45:34 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Fri, 14 Mar 2025 12:15:34 +0530
Subject: [PATCH net-next v2] net: ti: icssg-prueth: Add ICSSG FW Stats
In-Reply-To: <20250307083959.33098949@kernel.org>
References: <20250305111608.520042-1-danishanwar@ti.com>
 <20250306165513.541ff46e@kernel.org>
 <3931a391-3967-4260-a104-4eb313810c0d@ti.com>
 <20250307083959.33098949@kernel.org>
Message-ID: <c9e208e4-af14-424b-b09b-3e5068be2706@ti.com>



On 07/03/25 10:09 pm, Jakub Kicinski wrote:
> On Fri, 7 Mar 2025 16:00:40 +0530 MD Danish Anwar wrote:
>>> Thanks for the docs, it looks good. Now, do all of these get included
>>> in the standard stats returned by icssg_ndo_get_stats64 ?
>>> That's the primary source of information for the user regarding packet
>>> loss.  
>>
>> No, these are not reported via icssg_ndo_get_stats64.
>>
>> .ndo_get_stats64 populates stats that are part of `struct
>> rtnl_link_stats64`. icssg_ndo_get_stats64 populates those stats wherever
>> applicable. These firmware stats are not same as the ones defined in
>> `icssg_ndo_get_stats64` hence they are not populated. They are not
>> standard stats, they will be dumped by `ethtool -S`. Wherever there is a
>> standard stats, I will make sure it gets dumped from the standard
>> interface instead of `ethtool -S`
>>
>> Only below stats are included in the standard stats returned by
>> icssg_ndo_get_stats64
>> - rx_packets
>> - rx_bytes
>> - tx_packets
>> - tx_bytes
>> - rx_crc_errors
>> - rx_over_errors
>> - rx_multicast_frames
> 
> Yes, but if the stats you're adding here relate to packets sent /
> destined to the host which were lost you should include them
> in the aggregate rx_errors / rx_dropped / tx_errors / tx_dropped.
> I understand that there's unlikely to be a 1:1 match with specific
> stats.
> 

Sure, I will try to add such stats.

>>> This gets called by icssg_ndo_get_stats64() which is under RCU   
>>
>> Yes, this does get called by icssg_ndo_get_stats64(). Apart from that
>> there is a workqueue (`icssg_stats_work_handler`) that calls this API
>> periodically and updates the emac->stats and emac->pa_stats arrays.
>>
>>> protection and nothing else. I don't see any locking here, and  
>>
>> There is no locking here. I don't think this is related to the patch.
>> The API emac_update_hardware_stats() updates all the stats supported by
>> ICSSG not just standard stats.
> 
> Yes, I'm saying you should send a separate fix, not really related or
> blocking this patch (unless they conflict)
> 

Sure. I will send v3 of this and a fix to net to add spin_lock before
reading stats. I will try to make sure that they don't conflict so that
they can be merged parallelly.

>>> I hope the regmap doesn't sleep. cat /proc/net/dev to test.
>>> You probably need to send some fixes to net.  
>>
>> I checked cat /proc/net/dev and the stats shown there are not related to
>> the stats I am introducing in this series.
> 
> You misunderstood. I pointed that you so you can check on a debug
> kernel if there are any warnings (e.g. something tries to sleep
> since /proc/net/dev read is under RCU lock).
> 
>> The fix could be to add a lock in this function, but we have close to 90
>> stats and this function is called not only from icssg_ndo_get_stats64()
>> but from emac_get_ethtool_stats(). The function also gets called
>> periodically (Every 25 Seconds for 1G Link). I think every time locking
>> 90 regmap_reads() could result in performance degradation.
> 
> Correctness comes first.

Understood.

-- 
Thanks and Regards,
Danish


From s-vadapalli at ti.com  Thu Mar 13 23:46:42 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 14 Mar 2025 12:16:42 +0530
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <20250313165311.2fj7aus3pcsg4m2c@thinkpad>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
 <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
 <20250313165311.2fj7aus3pcsg4m2c@thinkpad>
Message-ID: <20250314064642.fyf3jqylmc6meft7@uda0492258>

On Thu, Mar 13, 2025 at 10:23:11PM +0530, Manivannan Sadhasivam wrote:

Hello Mani,

> On Wed, Mar 05, 2025 at 11:20:22AM -0500, Frank Li wrote:
> 
> If you want a specific patch to be tested, you can add [PATCH RFT] tag.C
> 
> > According to code in drivers/pci/controller/dwc/pci-dra7xx.c
> > 
> > dra7xx_pcie_cpu_addr_fixup()
> > {
> > 	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
> > }
> > 
> > PCI parent bus trim high 4 bits address to 0. Correct ranges in
> > target-module at 51000000 to algin hardware behavior, which translate PCIe
> > outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.
> > 
> > Set 'config' and 'addr_space' reg values to 0.
> > Change parent bus address of downstream I/O and non-prefetchable memory to
> > 0.
> > 
> > Ensure no functional impact on the final address translation result.
> > 
> > Prepare for the removal of the driver?s cpu_addr_fixup().
> > 
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> >  arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
> >  1 file changed, 9 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > index b709703f6c0d4..9213fdd25330b 100644
> > --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > @@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
> >  			#size-cells = <1>;
> >  			#address-cells = <1>;
> >  			ranges = <0x51000000 0x51000000 0x3000>,
> > -				 <0x20000000 0x20000000 0x10000000>;
> > +				 <0x00000000 0x20000000 0x10000000>;
> 
> I'm not able to interpret this properly. So this essentially means that the
> parent address 0x20000000 is mapped to child address 0x00000000. And the child
> address is same for other controller as well.
> 
> Also, the cpu_addr_fixup() is doing the same by masking out the upper 4 bits. I
> tried looking into the DRA7 TRM, but it says (ECAM_Param_Base_Addr +
> 0x20000000) where ECAM_Param_Base_Addr = 0x0000_0000 to 0x0FFF_F000.
> 
> I couldn't relate TRM with the cpu_addr_fixup() callback. Can someone from TI
> shed light on this?

A "git blame" on the line being modified in dra7.dtsi gives the
following commit:
https://github.com/torvalds/linux/commit/c761028ef5e2
prior to which the ranges is exactly the same as the one being added by
this patch.

The cpu_addr_fixup() function was introduced by the following commit:
https://github.com/torvalds/linux/commit/2ed6cc71e6f7
with the reason described in
Section 24.9.4.3.2 PCIe Controller Slave Port
of the T.R.M. at:
https://www.ti.com/lit/ug/spruic2d/spruic2d.pdf
---------------------------------------------------------------------------
NOTE:
The PCIe controller remains fully functional, and able to send transactions
to, for example, anywhere within the 64-bit PCIe memory space, with the
appropriate remapping of the 28-bit address by the outbound address
translation unit (iATU). The limitation is that the total size of addressed
PCIe regions (in config, memory, IO spaces) must be less than 2^28 bytes.
---------------------------------------------------------------------------

The entire sequence is:
0) dra7.dtsi had ranges which match the ranges in the current patch.
1) cpu_addr_fixup() was added by
https://github.com/torvalds/linux/commit/2ed6cc71e6f7
2) ranges was updated to <0x20000000 0x20000000 0x10000000> by:
https://github.com/torvalds/linux/commit/c761028ef5e2
3) ranges is being changed back to its original state of "0)" above.

cpu_addr_fixup() was introduced to remove the following:
	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
in dra7xx_pcie_host_init(). The reason for the above is mentioned in the
"NOTE" as:
---------------------------------------------------------------------------
The limitation is that the total size of addressed PCIe regions
(in config, memory, IO spaces) must be less than 2^28 bytes.
---------------------------------------------------------------------------

I am not sure if Frank is accounting for all of this in the current patch
as well as the dependent patch series associated with removing
cpu_addr_fixup().

Regarding testing the series, I unfortunately don't have the hardware so
I cannot test it.

Regards,
Siddharth.


From peng.fan at oss.nxp.com  Thu Mar 13 23:52:25 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Fri, 14 Mar 2025 14:52:25 +0800
Subject: [PATCH] soc: imx: Dump higher 64bits UID
Message-ID: <20250314065225.442717-1-peng.fan@oss.nxp.com>

From: Peng Fan <peng.fan at nxp.com>

i.MX8MP UID is actually 128bits and partitioned into two parts.
The 1st 64bits are at 0x410 and 0x420, and 2nd 64bits are at 0xE00
and 0xE10.

Dump the whole 128bits for i.MX8MP, by introducing soc_uid_h.

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/soc/imx/soc-imx8m.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
index 3ed8161d7d28..02d8c85e9a28 100644
--- a/drivers/soc/imx/soc-imx8m.c
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -24,13 +24,15 @@
 #define OCOTP_UID_HIGH			0x420
 
 #define IMX8MP_OCOTP_UID_OFFSET		0x10
+#define IMX8MP_OCOTP_UID_HIGH		0xE00
 
 /* Same as ANADIG_DIGPROG_IMX7D */
 #define ANADIG_DIGPROG_IMX8MM	0x800
 
 struct imx8_soc_data {
 	char *name;
-	int (*soc_revision)(u32 *socrev, u64 *socuid);
+	int (*soc_revision)(u32 *socrev, u64 *socuid, u64 *socuid_h);
+	bool uid_len_128;
 };
 
 #ifdef CONFIG_HAVE_ARM_SMCCC
@@ -49,7 +51,7 @@ static u32 imx8mq_soc_revision_from_atf(void)
 static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
 #endif
 
-static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
+static int imx8mq_soc_revision(u32 *socrev, u64 *socuid, u64 *socuid_h)
 {
 	struct device_node *np __free(device_node) =
 		of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
@@ -102,7 +104,7 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
 	return ret;
 }
 
-static int imx8mm_soc_uid(u64 *socuid)
+static int imx8mm_soc_uid(u64 *socuid, u64 *socuid_h)
 {
 	struct device_node *np __free(device_node) =
 		of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
@@ -131,6 +133,12 @@ static int imx8mm_soc_uid(u64 *socuid)
 	*socuid <<= 32;
 	*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
 
+	if (offset) {
+		*socuid_h = readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10);
+		*socuid_h <<= 32;
+		*socuid_h |= readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH);
+	}
+
 	clk_disable_unprepare(clk);
 	clk_put(clk);
 
@@ -139,7 +147,7 @@ static int imx8mm_soc_uid(u64 *socuid)
 	return ret;
 }
 
-static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
+static int imx8mm_soc_revision(u32 *socrev, u64 *socuid, u64 *socuid_h)
 {
 	struct device_node *np __free(device_node) =
 		of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
@@ -156,7 +164,7 @@ static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
 
 	iounmap(anatop_base);
 
-	return imx8mm_soc_uid(socuid);
+	return imx8mm_soc_uid(socuid, socuid_h);
 }
 
 static const struct imx8_soc_data imx8mq_soc_data = {
@@ -177,6 +185,7 @@ static const struct imx8_soc_data imx8mn_soc_data = {
 static const struct imx8_soc_data imx8mp_soc_data = {
 	.name = "i.MX8MP",
 	.soc_revision = imx8mm_soc_revision,
+	.uid_len_128 = true,
 };
 
 static __maybe_unused const struct of_device_id imx8_soc_match[] = {
@@ -211,7 +220,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
 	const struct of_device_id *id;
 	struct soc_device *soc_dev;
 	u32 soc_rev = 0;
-	u64 soc_uid = 0;
+	u64 soc_uid = 0, soc_uid_h = 0;
 	int ret;
 
 	soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -232,7 +241,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
 	if (data) {
 		soc_dev_attr->soc_id = data->name;
 		if (data->soc_revision) {
-			ret = data->soc_revision(&soc_rev, &soc_uid);
+			ret = data->soc_revision(&soc_rev, &soc_uid, &soc_uid_h);
 			if (ret)
 				return ret;
 		}
@@ -242,7 +251,11 @@ static int imx8m_soc_probe(struct platform_device *pdev)
 	if (!soc_dev_attr->revision)
 		return -ENOMEM;
 
-	soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
+	if (data && data->uid_len_128)
+		soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX%016llX",
+							soc_uid_h, soc_uid);
+	else
+		soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
 	if (!soc_dev_attr->serial_number)
 		return -ENOMEM;
 
-- 
2.37.1



From s-vadapalli at ti.com  Thu Mar 13 23:54:44 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 14 Mar 2025 12:24:44 +0530
Subject: [PATCH 1/4] PCI: cadence: Add support to build pcie-cadence
 library as a kernel module
In-Reply-To: <20250313174416.n3c4srf6hb2l3bvg@thinkpad>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-2-s-vadapalli@ti.com>
 <20250313174416.n3c4srf6hb2l3bvg@thinkpad>
Message-ID: <20250314065444.fmvhyqmuefnm4mcq@uda0492258>

On Thu, Mar 13, 2025 at 11:14:16PM +0530, Manivannan Sadhasivam wrote:

Hello Mani,

> On Fri, Mar 07, 2025 at 04:01:25PM +0530, Siddharth Vadapalli wrote:
> > From: Kishon Vijay Abraham I <kishon at ti.com>
> > 
> > Currently, the Cadence PCIe controller driver can be built as a built-in
> > module only. Since PCIe functionality is not a necessity for booting, add
> > support to build the Cadence PCIe driver as a loadable module as well.
> > 
> > Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> 
> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> 
> > ---
> >  drivers/pci/controller/cadence/Kconfig             |  6 +++---
> >  drivers/pci/controller/cadence/pcie-cadence-ep.c   |  6 ++++++
> >  drivers/pci/controller/cadence/pcie-cadence-host.c |  9 +++++++++
> >  drivers/pci/controller/cadence/pcie-cadence.c      | 12 ++++++++++++
> >  drivers/pci/controller/cadence/pcie-cadence.h      |  4 ++--
> >  5 files changed, 32 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
> > index 8a0044bb3989..82b58096eea0 100644
> > --- a/drivers/pci/controller/cadence/Kconfig
> > +++ b/drivers/pci/controller/cadence/Kconfig
> > @@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
> >  	depends on PCI
> >  
> >  config PCIE_CADENCE
> > -	bool
> > +	tristate
> >  
> >  config PCIE_CADENCE_HOST
> > -	bool
> > +	tristate
> >  	depends on OF
> >  	select IRQ_DOMAIN
> 
> Even though this was added earlier, looks like not needed.

Thank you for reviewing this patch.

drivers/pci/controller/cadence/Kconfig has the following:
...
	config PCIE_CADENCE_HOST
		bool
		depends on OF
		select IRQ_DOMAIN
		select PCIE_CADENCE
...
	config PCI_J721E_HOST
		bool "TI J721E PCIe controller (host mode)"
		depends on ARCH_K3 || COMPILE_TEST
		depends on OF
		select PCIE_CADENCE_HOST
		select PCI_J721E
...
So PCI_J721E_HOST selects PCIE_CADENCE_HOST which in turn selects
PCIE_CADENCE. As of now, none of these configs are enabled in
arm64-defconfig, and they also will not be accepted as built-in modules
as it will bloat the Linux Image for everyone. For that reason, they are
all being converted to loadable modules, and their configs will eventually
be enabled in arm64-defconfig as loadable modules.

Please let me know if I misunderstood your comment regarding the quoted
change not being required.

Regards,
Siddharth.


From liqiong at nfschina.com  Fri Mar 14 00:09:21 2025
From: liqiong at nfschina.com (Li Qiong)
Date: Fri, 14 Mar 2025 15:09:21 +0800
Subject: [PATCH] usb: remove the invalid comments
Message-ID: <20250314070921.355986-1-liqiong@nfschina.com>

These function don't return value, remove the invalid comments.

Signed-off-by: Li Qiong <liqiong at nfschina.com>
---
 drivers/usb/cdns3/cdns3-plat.c      | 2 --
 drivers/usb/gadget/udc/udc-xilinx.c | 2 --
 2 files changed, 4 deletions(-)

diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
index 59ec505e198a..735df88774e4 100644
--- a/drivers/usb/cdns3/cdns3-plat.c
+++ b/drivers/usb/cdns3/cdns3-plat.c
@@ -179,8 +179,6 @@ static int cdns3_plat_probe(struct platform_device *pdev)
 /**
  * cdns3_plat_remove() - unbind drd driver and clean up
  * @pdev: Pointer to Linux platform device
- *
- * Returns 0 on success otherwise negative errno
  */
 static void cdns3_plat_remove(struct platform_device *pdev)
 {
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index ae2aeb271897..fa94cc065274 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -2178,8 +2178,6 @@ static int xudc_probe(struct platform_device *pdev)
 /**
  * xudc_remove - Releases the resources allocated during the initialization.
  * @pdev: pointer to the platform device structure.
- *
- * Return: 0 always
  */
 static void xudc_remove(struct platform_device *pdev)
 {
-- 
2.30.2



From gregkh at linuxfoundation.org  Fri Mar 14 00:12:46 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Fri, 14 Mar 2025 08:12:46 +0100
Subject: [PATCH] usb: remove the invalid comments
In-Reply-To: <20250314070921.355986-1-liqiong@nfschina.com>
References: <20250314070921.355986-1-liqiong@nfschina.com>
Message-ID: <2025031430-poncho-aviator-8131@gregkh>

On Fri, Mar 14, 2025 at 03:09:21PM +0800, Li Qiong wrote:
> These function don't return value, remove the invalid comments.
> 
> Signed-off-by: Li Qiong <liqiong at nfschina.com>
> ---
>  drivers/usb/cdns3/cdns3-plat.c      | 2 --
>  drivers/usb/gadget/udc/udc-xilinx.c | 2 --

This should be 2 different patches, right?

thanks,

greg k-h


From mripard at kernel.org  Fri Mar 14 00:17:04 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 08:17:04 +0100
Subject: [PATCH] drm/sun4i: backend: Fix error pointers in
 sun4i_backend_atomic_check
In-Reply-To: <20250314012029.668306-1-chenyuan0y@gmail.com>
References: <20250314012029.668306-1-chenyuan0y@gmail.com>
Message-ID: <20250314-prophetic-attentive-platypus-3ab214@houat>

Hi,

On Thu, Mar 13, 2025 at 08:20:29PM -0500, Chenyuan Yang wrote:
> The function sun4i_backend_atomic_check was dereferencing pointers
> returned by drm_atomic_get_plane_state without checking for errors. This
> could lead to undefined behavior if the function returns an error pointer.
> 
> This commit adds checks using IS_ERR to ensure that plane_state is
> valid before dereferencing them.
> 
> Similar to commit da29abe71e16
> ("drm/amd/display: Fix error pointers in amdgpu_dm_crtc_mem_type_changed").
> 
> Fixes: 96180dde23b7 ("drm/sun4i: backend: Add a custom atomic_check for the frontend")
> Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_backend.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
> index 2dded3b828df..a8e0e2123764 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
> @@ -490,6 +490,10 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
>  	drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
>  		struct drm_plane_state *plane_state =
>  			drm_atomic_get_plane_state(state, plane);
> +
> +		if (IS_ERR(plane_state))
> +			return PTR_ERR(plane_state);
> +

This introduces a build warning. You shouldn't mix declarations and code.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/096cf63d/attachment.sig>

From liqiong at nfschina.com  Fri Mar 14 00:32:25 2025
From: liqiong at nfschina.com (liqiong)
Date: Fri, 14 Mar 2025 15:32:25 +0800
Subject: [PATCH] usb: remove the invalid comments
In-Reply-To: <2025031430-poncho-aviator-8131@gregkh>
Message-ID: <57885b0a-eb21-4eea-9b85-71a1fd8cd6a0@nfschina.com>



? 2025/3/14 15:12, Greg Kroah-Hartman ??:
> On Fri, Mar 14, 2025 at 03:09:21PM +0800, Li Qiong wrote:
>> These function don't return value, remove the invalid comments.
>>
>> Signed-off-by: Li Qiong <liqiong at nfschina.com>
>> ---
>>  drivers/usb/cdns3/cdns3-plat.c      | 2 --
>>  drivers/usb/gadget/udc/udc-xilinx.c | 2 --
> This should be 2 different patches, right?
Yeah, I will split this patch and send again.
thanks.



>
> thanks,
>
> greg k-h



From maz at kernel.org  Fri Mar 14 00:40:36 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 14 Mar 2025 07:40:36 +0000
Subject: [PATCH v2 2/4] arm64/sysreg: Enforce whole word match for
 open/close tokens
In-Reply-To: <20250313215622.GA8101@willie-the-truck>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-3-james.clark@linaro.org>
 <20250313215622.GA8101@willie-the-truck>
Message-ID: <36968527640d231882444ba7065317fe@kernel.org>

On 2025-03-13 21:56, Will Deacon wrote:
> On Wed, Jan 15, 2025 at 04:25:56PM +0000, James Clark wrote:
>> Opening and closing tokens can also match on words with common 
>> prefixes
>> like "Endsysreg" vs "EndsysregFields". This could potentially make the
>> script go wrong in weird ways so make it fall through to the fatal
>> unhandled statement catcher if it doesn't fully match the current
>> block.
>> 
>> Closing ones also get expect_fields(1) to ensure nothing other than
>> whitespace follows.
>> 
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>  arch/arm64/tools/gen-sysreg.awk | 31 +++++++++++++++++--------------
>>  1 file changed, 17 insertions(+), 14 deletions(-)
>> 
>> diff --git a/arch/arm64/tools/gen-sysreg.awk 
>> b/arch/arm64/tools/gen-sysreg.awk
>> index 1a2afc9fdd42..f2a1732cb1f6 100755
>> --- a/arch/arm64/tools/gen-sysreg.awk
>> +++ b/arch/arm64/tools/gen-sysreg.awk
>> @@ -111,7 +111,7 @@ END {
>>  /^$/ { next }
>>  /^[\t ]*#/ { next }
>> 
>> -/^SysregFields/ && block_current() == "Root" {
>> +$1 == "SysregFields" && block_current() == "Root" {
> 
> Stylistic nit, but could you just do:
> 
> 	/^SysregFields$/ && block_current() == "Root" {
> 
> instead? That way the diff is smaller (well, same number of lines) and
> you avoid the ugly $1.

The code is trying to match the first field of a line such as:

SysregFields	ZCR_ELx

while you seem to try and match a SysregFields all alone on a line.

That being said, my perl-foo is sub-zero, so I may be very wrong myself.

         M.
-- 
Jazz is not dead. It just smells funny...


From hejunhao3 at huawei.com  Fri Mar 14 00:44:43 2025
From: hejunhao3 at huawei.com (hejunhao)
Date: Fri, 14 Mar 2025 15:44:43 +0800
Subject: [PATCH] coresight: Fixes device's owner field for registered
 using coresight_init_driver()
In-Reply-To: <e2194d2a-0f51-4e59-a1ca-b4563b3389ec@arm.com>
References: <20240918035327.9710-1-hejunhao3@huawei.com>
 <e2194d2a-0f51-4e59-a1ca-b4563b3389ec@arm.com>
Message-ID: <c3744062-f7c1-82df-2fa1-591da3b2dc5e@huawei.com>

Hi Suzuki,

Could you confirm if this patch was queued in coresight/next or upstream 
of the mainline?

I couldn't find it in: kernel/git/coresight/linux.git or Kernel v6.14.0-rc4.

Maybe am I missing some information?

Best regards,
Junhao.


On 2024/9/18 16:29, Suzuki K Poulose wrote:
> On 18/09/2024 04:53, Junhao He wrote:
>> The coresight_init_driver() of the coresight-core module is called from
>> the sub coresgiht device (such as tmc/stm/funnle/...) module. It calls
>> amba_driver_register() and Platform_driver_register(), which are macro
>> functions that use the coresight-core's module to initialize the 
>> caller's
>> owner field.  Therefore, when the sub coresight device calls
>> coresight_init_driver(), an incorrect THIS_MODULE value is captured.
>>
>> The sub coesgiht modules can be removed while their callbacks are
>> running, resulting in a general protection failure.
>>
>> Add module parameter to coresight_init_driver() so can be called
>> with the module of the callback.
>>
>> Fixes: 075b7cd7ad7d ("coresight: Add helpers registering/removing 
>> both AMBA and platform drivers")
>> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
>
> Thanks for the fix, looks good to me. I will queue this for v6.13
>
> Suzuki
>
>> ---
>>   drivers/hwtracing/coresight/coresight-catu.c       | 2 +-
>>   drivers/hwtracing/coresight/coresight-core.c       | 6 +++---
>>   drivers/hwtracing/coresight/coresight-cpu-debug.c  | 3 ++-
>>   drivers/hwtracing/coresight/coresight-funnel.c     | 3 ++-
>>   drivers/hwtracing/coresight/coresight-replicator.c | 3 ++-
>>   drivers/hwtracing/coresight/coresight-stm.c        | 2 +-
>>   drivers/hwtracing/coresight/coresight-tmc-core.c   | 2 +-
>>   drivers/hwtracing/coresight/coresight-tpiu.c       | 2 +-
>>   include/linux/coresight.h                          | 2 +-
>>   9 files changed, 14 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-catu.c 
>> b/drivers/hwtracing/coresight/coresight-catu.c
>> index bfea880d6dfb..337668f9cfd4 100644
>> --- a/drivers/hwtracing/coresight/coresight-catu.c
>> +++ b/drivers/hwtracing/coresight/coresight-catu.c
>> @@ -702,7 +702,7 @@ static int __init catu_init(void)
>>   {
>>       int ret;
>>   -    ret = coresight_init_driver("catu", &catu_driver, 
>> &catu_platform_driver);
>> +    ret = coresight_init_driver("catu", &catu_driver, 
>> &catu_platform_driver, THIS_MODULE);
>>       tmc_etr_set_catu_ops(&etr_catu_buf_ops);
>>       return ret;
>>   }
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c 
>> b/drivers/hwtracing/coresight/coresight-core.c
>> index 9fc6f6b863e0..c546a417836c 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -1399,17 +1399,17 @@ module_init(coresight_init);
>>   module_exit(coresight_exit);
>>     int coresight_init_driver(const char *drv, struct amba_driver 
>> *amba_drv,
>> -              struct platform_driver *pdev_drv)
>> +              struct platform_driver *pdev_drv, struct module *owner)
>>   {
>>       int ret;
>>   -    ret = amba_driver_register(amba_drv);
>> +    ret = __amba_driver_register(amba_drv, owner);
>>       if (ret) {
>>           pr_err("%s: error registering AMBA driver\n", drv);
>>           return ret;
>>       }
>>   -    ret = platform_driver_register(pdev_drv);
>> +    ret = __platform_driver_register(pdev_drv, owner);
>>       if (!ret)
>>           return 0;
>>   diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c 
>> b/drivers/hwtracing/coresight/coresight-cpu-debug.c
>> index 75962dae9aa1..cc599c5ef4b2 100644
>> --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
>> +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
>> @@ -774,7 +774,8 @@ static struct platform_driver 
>> debug_platform_driver = {
>>     static int __init debug_init(void)
>>   {
>> -    return coresight_init_driver("debug", &debug_driver, 
>> &debug_platform_driver);
>> +    return coresight_init_driver("debug", &debug_driver, 
>> &debug_platform_driver,
>> +                     THIS_MODULE);
>>   }
>>     static void __exit debug_exit(void)
>> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c 
>> b/drivers/hwtracing/coresight/coresight-funnel.c
>> index 5a819c8970fb..8f451b051ddc 100644
>> --- a/drivers/hwtracing/coresight/coresight-funnel.c
>> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
>> @@ -433,7 +433,8 @@ static struct amba_driver dynamic_funnel_driver = {
>>     static int __init funnel_init(void)
>>   {
>> -    return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>> &funnel_driver);
>> +    return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>> &funnel_driver,
>> +                     THIS_MODULE);
>>   }
>>     static void __exit funnel_exit(void)
>> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c 
>> b/drivers/hwtracing/coresight/coresight-replicator.c
>> index 3e55be9c8418..f7607c72857c 100644
>> --- a/drivers/hwtracing/coresight/coresight-replicator.c
>> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
>> @@ -438,7 +438,8 @@ static struct amba_driver 
>> dynamic_replicator_driver = {
>>     static int __init replicator_init(void)
>>   {
>> -    return coresight_init_driver("replicator", 
>> &dynamic_replicator_driver, &replicator_driver);
>> +    return coresight_init_driver("replicator", 
>> &dynamic_replicator_driver, &replicator_driver,
>> +                     THIS_MODULE);
>>   }
>>     static void __exit replicator_exit(void)
>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c 
>> b/drivers/hwtracing/coresight/coresight-stm.c
>> index 117dbb484543..403eea8f95d4 100644
>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>> @@ -1046,7 +1046,7 @@ static struct platform_driver 
>> stm_platform_driver = {
>>     static int __init stm_init(void)
>>   {
>> -    return coresight_init_driver("stm", &stm_driver, 
>> &stm_platform_driver);
>> +    return coresight_init_driver("stm", &stm_driver, 
>> &stm_platform_driver, THIS_MODULE);
>>   }
>>     static void __exit stm_exit(void)
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c 
>> b/drivers/hwtracing/coresight/coresight-tmc-core.c
>> index b54562f392f3..e31e36635394 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
>> @@ -742,7 +742,7 @@ static struct platform_driver tmc_platform_driver 
>> = {
>>     static int __init tmc_init(void)
>>   {
>> -    return coresight_init_driver("tmc", &tmc_driver, 
>> &tmc_platform_driver);
>> +    return coresight_init_driver("tmc", &tmc_driver, 
>> &tmc_platform_driver, THIS_MODULE);
>>   }
>>     static void __exit tmc_exit(void)
>> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c 
>> b/drivers/hwtracing/coresight/coresight-tpiu.c
>> index b048e146fbb1..f9ecd05cbe5c 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
>> @@ -318,7 +318,7 @@ static struct platform_driver 
>> tpiu_platform_driver = {
>>     static int __init tpiu_init(void)
>>   {
>> -    return coresight_init_driver("tpiu", &tpiu_driver, 
>> &tpiu_platform_driver);
>> +    return coresight_init_driver("tpiu", &tpiu_driver, 
>> &tpiu_platform_driver, THIS_MODULE);
>>   }
>>     static void __exit tpiu_exit(void)
>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>> index f09ace92176e..e6c26952ddc2 100644
>> --- a/include/linux/coresight.h
>> +++ b/include/linux/coresight.h
>> @@ -660,7 +660,7 @@ coresight_find_output_type(struct 
>> coresight_platform_data *pdata,
>>                  union coresight_dev_subtype subtype);
>>     int coresight_init_driver(const char *drv, struct amba_driver 
>> *amba_drv,
>> -              struct platform_driver *pdev_drv);
>> +              struct platform_driver *pdev_drv, struct module *owner);
>>     void coresight_remove_driver(struct amba_driver *amba_drv,
>>                    struct platform_driver *pdev_drv);
>
>
> .
>



From tzimmermann at suse.de  Fri Mar 14 01:08:41 2025
From: tzimmermann at suse.de (Thomas Zimmermann)
Date: Fri, 14 Mar 2025 09:08:41 +0100
Subject: [PATCH] drm/mxsfb: fix missing rollback on failure in
 mxsfb_probe()
In-Reply-To: <CABGWkvqtj+05sdOuXg1WO99VNm9qdFgcYWEGuUPPZPoHZa6Dew@mail.gmail.com>
References: <20250313-mxsfb_probe-fix-rollback-on-error-v1-1-ad2fb79de4cb@bootlin.com>
 <468c6352-3301-4f0b-a2d4-d6a013417a0e@suse.de>
 <CABGWkvqtj+05sdOuXg1WO99VNm9qdFgcYWEGuUPPZPoHZa6Dew@mail.gmail.com>
Message-ID: <46140633-a41d-4498-bc78-e43a1bd6b348@suse.de>

Hi

Am 13.03.25 um 21:43 schrieb Dario Binacchi:
> Hi All,
>
> On Thu, Mar 13, 2025 at 3:40?PM Thomas Zimmermann <tzimmermann at suse.de> wrote:
>> Hi
>>
>> Am 13.03.25 um 15:25 schrieb Luca Ceresoli:
>>> When aperture_remove_all_conflicting_devices() fails, the current code
>>> returns without going through the rollback actions at the end of the
>>> function, thus the actions done by drm_dev_alloc() and mxsfb_load() are not
>>> undone.
>>>
>>> Fix by using a goto statament, as done for the previous and following error
>>> conditions.
>>>
>>> Fixes: c8e7b185d45b ("drm/mxsfb: Remove generic DRM drivers in probe function")
>>> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
>>> ---
>>> The offending commit is not yet merged into master, and even less in a
>>> released kernel, so this does not need to go through stable.
>>> ---
>>>    drivers/gpu/drm/mxsfb/mxsfb_drv.c | 7 ++++---
>>>    1 file changed, 4 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>>> index c183b1112bc4e9fe4f3b048a2b6e4c98d1d47cb3..b4273e678d26dbc3dee2014266d61470da4e8010 100644
>>> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>>> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
>>> @@ -365,9 +365,10 @@ static int mxsfb_probe(struct platform_device *pdev)
>>>         * located anywhere in RAM
>>>         */
>>>        ret = aperture_remove_all_conflicting_devices(mxsfb_driver.name);
>>> -     if (ret)
>>> -             return dev_err_probe(&pdev->dev, ret,
>>> -                                  "can't kick out existing framebuffers\n");
>>> +     if (ret) {
>>> +             dev_err_probe(&pdev->dev, ret, "can't kick out existing framebuffers\n");
>>> +             goto err_unload;
>>> +     }
>> I must have missed that when I reviewed the patch. But this call should
>> happen much earlier. right at the top of the probe function before
>> drm_dev_alloc().
> I had added the call to aperture_remove_all_conflicting_devices()
> after mxsfb_load() to
> keep the splash screen loaded by U-Boot. So, IMHO, it would be better
> to add the
> goto in case of an error rather than moving
> aperture_remove_all_conflicting_devices()
> to the beginning of the probe function.

But is that really safe?? Once you start touching any of the graphics 
registers, the previous framebuffer and display mode potentially becomes 
invalid. (Depends on the details of the driver and hardware, of course.)

Best regards
Thomas

>
> Thanks and regards,
> Dario
>
>> Conflicting drivers need to be kicked out before
>> setting up DRM. Could you please send a patch to move the call to the
>> top? No extra cleanup would be required then.
>>
>> Best regards
>> Thomas
>>
>>>        ret = drm_dev_register(drm, 0);
>>>        if (ret)
>>>
>>> ---
>>> base-commit: f9f087d946266bc5da7c3a17bd8fd9d01969e3cf
>>> change-id: 20250313-mxsfb_probe-fix-rollback-on-error-3074b9080f34
>>>
>>> Best regards,
>> --
>> --
>> Thomas Zimmermann
>> Graphics Driver Developer
>> SUSE Software Solutions Germany GmbH
>> Frankenstrasse 146, 90461 Nuernberg, Germany
>> GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
>> HRB 36809 (AG Nuernberg)
>>
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)



From oliver.upton at linux.dev  Fri Mar 14 01:10:49 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Fri, 14 Mar 2025 01:10:49 -0700
Subject: [PATCH v4 0/7] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250313-pmc-v4-0-2c976827118c@daynix.com>
References: <20250313-pmc-v4-0-2c976827118c@daynix.com>
Message-ID: <Z9PkchMNGN1cdLgJ@linux.dev>

Hi Akihiko,

On Thu, Mar 13, 2025 at 03:57:41PM +0900, Akihiko Odaki wrote:
> base-commit: da2f480cb24d39d480b1e235eda0dd2d01f8765b

I don't have this commit, what did you base this series on?

FWIW, the patches do not apply to a 6.14-rc* and seem to use something
older.

Thanks,
Oliver


From peng.fan at oss.nxp.com  Fri Mar 14 02:18:52 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Fri, 14 Mar 2025 17:18:52 +0800
Subject: [PATCH v10 11/18] clk: imx: add support for i.MX8MM anatop clock
 driver
In-Reply-To: <20250306112959.242131-12-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
 <20250306112959.242131-12-dario.binacchi@amarulasolutions.com>
Message-ID: <20250314091852.GA12210@nxa18884-linux>

On Thu, Mar 06, 2025 at 12:28:00PM +0100, Dario Binacchi wrote:
>Support NXP i.MX8M anatop PLL module which generates PLLs to CCM root.
>By doing so, we also simplify the CCM driver code. The changes are
>backward compatible.
>
>Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

Reviewed-by: Peng Fan <peng.fan at nxp.com>


From luca.ceresoli at bootlin.com  Fri Mar 14 01:11:20 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 09:11:20 +0100
Subject: [PATCH v6 14/26] drm/bridge: add support for refcounted DRM
 bridges
In-Reply-To: <20250313-flying-crab-of-diversity-fa1db0@houat>
References: <20250206-hotplug-drm-bridge-v6-0-9d6f2c9c3058@bootlin.com>
	<20250206-hotplug-drm-bridge-v6-14-9d6f2c9c3058@bootlin.com>
	<20250207-ingenious-daffodil-dugong-51be57@houat>
	<20250313125656.70448d09@booty>
	<20250313-flying-crab-of-diversity-fa1db0@houat>
Message-ID: <20250314091120.366b5fd7@booty>

Hello Maxime,

On Thu, 13 Mar 2025 19:07:17 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> On Thu, Mar 13, 2025 at 12:56:56PM +0100, Luca Ceresoli wrote:
> > Hello Maxime,
> > 
> > On Fri, 7 Feb 2025 12:47:51 +0100
> > Maxime Ripard <mripard at kernel.org> wrote:  
> > > On Thu, Feb 06, 2025 at 07:14:29PM +0100, Luca Ceresoli wrote:  
> > > > DRM bridges are currently considered as a fixed element of a DRM card, and
> > > > thus their lifetime is assumed to extend for as long as the card
> > > > exists. New use cases, such as hot-pluggable hardware with video bridges,
> > > > require DRM bridges to be added and removed to a DRM card without tearing
> > > > the card down. This is possible for connectors already (used by DP MST), so
> > > > add this possibility to DRM bridges as well.
> > > > 
> > > > Implementation is based on drm_connector_init() as far as it makes sense,
> > > > and differs when it doesn't. A difference is that bridges are not exposed
> > > > to userspace, hence struct drm_bridge does not embed a struct
> > > > drm_mode_object which would provide the refcount. Instead we add to struct
> > > > drm_bridge a refcount field (we don't need other struct drm_mode_object
> > > > fields here) and instead of using the drm_mode_object_*() functions we
> > > > reimplement from those functions the few lines that drm_bridge needs for
> > > > refcounting.
> > > > 
> > > > Also add a new devm_drm_bridge_alloc() macro to allocate a new refcounted
> > > > bridge.
> > > > 
> > > > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>    
> > > 
> > > So, a couple of general comments:
> > > 
> > > - I've said it a couple of times already, but I really think you're
> > >   making it harder than necessary for you here. This (and only this!)
> > >   should be the very first series you should be pushing. The rest can
> > >   only ever work if that work goes through, and it's already hard enough
> > >   as it is. So, split that patch into a series of its own, get that
> > >   merged, and then we will be able to deal with panels conversion and
> > >   whatever. That's even more true with panels since there's ongoing work
> > >   that will make it easier for you too. So the best thing here is
> > >   probably to wait.
> > > 
> > > - This patch really needs to be split into several patches, something
> > >   along the lines of:
> > > 
> > >   + Creating devm_drm_bridge_alloc()
> > >   + Adding refcounting
> > >   + Taking the references in all the needed places
> > >   + Converting a bunch of drivers  
> > 
> > After reading Anusha's "[PATCH RFC 0/2] drm/panel: Refcounted panel
> > allocation" [0] I think I need a clarification about the 4 steps you had
> > outlined in the above quoted text. Are you suggesting those are four
> > _series_, and you'd want to see a series only creating
> > devm_drm_bridge_alloc() as a first step, similarly to Anusha's work?
> > 
> > That was not my understanding so far, and so I've been working on a
> > series containing all 4 items, and it's growing very long due to item 3
> > needing to touch many dozen drivers which need to put a bridge (many
> > are identical oneliner patches though).  
> 
> I believe I've clarified it already in Anusha's series, but I think a

Yes, you have...

> reasonable series for *early* work would be the bullet points 1, 2, a
> bit of 3 and a bit of 4.

...but thanks for the extra clarification.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From Lu.Tang at mediatek.com  Fri Mar 14 00:32:26 2025
From: Lu.Tang at mediatek.com (Lu.Tang)
Date: Fri, 14 Mar 2025 15:32:26 +0800
Subject: [PATCH 0/5] Add PMIC and SPMI driver for mt8196
Message-ID: <20250314073307.25092-1-Lu.Tang@mediatek.com>

This series is based on linux-next.

Changes in v0:
- Modify SPMI driver for mt8196
- Add SPMI PMIC mfd driver
- Add PMIC regulator driver for mt8196

*** BLURB HERE ***

Lu.Tang (5):
  pmic: mediatek: Add pmic auxadc driver
  pmic: mediatek: Add pmic regulator driver
  pmic: mediatek: Add spmi pmic mfd driver
  spmi: mediatek: modify spmi dirver for mt8196
  dt-bindings: pmic: mediatek: Add pmic documents

 .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |   31 +
 .../bindings/input/mediatek,pmic-keys.yaml    |    1 +
 .../bindings/mfd/mediatek,mt6685.yaml         |   50 +
 .../bindings/mfd/mediatek,spmi-pmic.yaml      |  173 +++
 .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |    1 +
 drivers/iio/adc/Kconfig                       |   10 +
 drivers/iio/adc/Makefile                      |    1 +
 drivers/iio/adc/mtk-spmi-pmic-adc.c           |  576 +++++++++
 drivers/mfd/Kconfig                           |   26 +
 drivers/mfd/Makefile                          |    2 +
 drivers/mfd/mt6685-core.c                     |   83 ++
 drivers/mfd/mtk-spmi-pmic.c                   |  518 ++++++++
 drivers/regulator/Kconfig                     |   34 +
 drivers/regulator/Makefile                    |    3 +
 drivers/regulator/mt6316-regulator.c          |  381 ++++++
 drivers/regulator/mt6363-regulator.c          | 1106 +++++++++++++++++
 drivers/regulator/mt6373-regulator.c          |  826 ++++++++++++
 drivers/spmi/spmi-mtk-pmif.c                  | 1040 +++++++++++++++-
 include/linux/mfd/mt6363/core.h               |  134 ++
 include/linux/mfd/mt6363/registers.h          |  168 +++
 include/linux/mfd/mt6373/core.h               |   94 ++
 include/linux/mfd/mt6373/registers.h          |   53 +
 include/linux/regulator/mt6316-regulator.h    |   48 +
 include/linux/regulator/mt6363-regulator.h    |  424 +++++++
 include/linux/regulator/mt6373-regulator.h    |  318 +++++
 25 files changed, 6037 insertions(+), 64 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
 create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c
 create mode 100644 drivers/mfd/mt6685-core.c
 create mode 100644 drivers/mfd/mtk-spmi-pmic.c
 create mode 100644 drivers/regulator/mt6316-regulator.c
 create mode 100644 drivers/regulator/mt6363-regulator.c
 create mode 100644 drivers/regulator/mt6373-regulator.c
 create mode 100644 include/linux/mfd/mt6363/core.h
 create mode 100644 include/linux/mfd/mt6363/registers.h
 create mode 100644 include/linux/mfd/mt6373/core.h
 create mode 100644 include/linux/mfd/mt6373/registers.h
 create mode 100644 include/linux/regulator/mt6316-regulator.h
 create mode 100644 include/linux/regulator/mt6363-regulator.h
 create mode 100644 include/linux/regulator/mt6373-regulator.h

-- 
2.46.0



From Lu.Tang at mediatek.com  Fri Mar 14 00:32:27 2025
From: Lu.Tang at mediatek.com (Lu.Tang)
Date: Fri, 14 Mar 2025 15:32:27 +0800
Subject: [PATCH 1/5] pmic: mediatek: Add pmic auxadc driver
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <20250314073307.25092-2-Lu.Tang@mediatek.com>

From: "Lu.Tang" <lu.tang at mediatek.com>

Add pmic mt6363 and mt6373 auxadc driver

Signed-off-by: Lu Tang <lu.tang at mediatek.com>
---
 drivers/iio/adc/Kconfig             |  10 +
 drivers/iio/adc/Makefile            |   1 +
 drivers/iio/adc/mtk-spmi-pmic-adc.c | 576 ++++++++++++++++++++++++++++
 3 files changed, 587 insertions(+)
 create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 27413516216c..7c4b5f8f7209 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1039,6 +1039,16 @@ config MEDIATEK_MT6577_AUXADC
 	  This driver can also be built as a module. If so, the module will be
 	  called mt6577_auxadc.
 
+config MEDIATEK_SPMI_PMIC_ADC
+	tristate "MediaTek SPMI PMIC ADC Support"
+	depends on MFD_MTK_SPMI_PMIC
+	help
+	  Say yes here to enable support for MediaTek SPMI PMIC ADC.
+	  The driver supports multiple channels read.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called mtk-spmi-pmic-adc.
+
 config MEN_Z188_ADC
 	tristate "MEN 16z188 ADC IP Core support"
 	depends on MCB
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 9f26d5eca822..b3224abea040 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_MEDIATEK_MT6359_AUXADC) += mt6359-auxadc.o
 obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
 obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
 obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
+obj-$(CONFIG_MEDIATEK_SPMI_PMIC_ADC) += mtk-spmi-pmic-adc.o
 obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
 obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o
diff --git a/drivers/iio/adc/mtk-spmi-pmic-adc.c b/drivers/iio/adc/mtk-spmi-pmic-adc.c
new file mode 100644
index 000000000000..61e062bc8cf5
--- /dev/null
+++ b/drivers/iio/adc/mtk-spmi-pmic-adc.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mfd/mt6363/registers.h>
+#include <linux/mfd/mt6373/registers.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/property.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/syscore_ops.h>
+
+#include <dt-bindings/iio/mt635x-auxadc.h>
+
+#define AUXADC_RDY_BIT			BIT(15)
+
+#define AUXADC_DEF_R_RATIO		1
+#define AUXADC_DEF_AVG_NUM		32
+
+#define AUXADC_AVG_TIME_US		10
+#define AUXADC_POLL_DELAY_US		100
+#define AUXADC_TIMEOUT_US		32000
+#define VOLT_FULL			1840
+
+#define IMP_VOLT_FULL			18400
+#define IMIX_R_MIN_MOHM			100
+#define IMIX_R_CALI_CNT			2
+
+#define EXT_THR_PURES_SHIFT		3
+#define EXT_THR_SEL_MASK		0x1F
+
+#define DT_CHANNEL_CONVERT(val)		((val) & 0xFF)
+#define DT_PURES_CONVERT(val)		(((val) & 0xFF00) >> 8)
+
+struct pmic_adc_device {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex lock;
+	struct iio_chan_spec *iio_chans;
+	unsigned int nchannels;
+	const struct auxadc_info *info;
+	struct regulator *isink_load;
+	int imix_r;
+	int imp_curr;
+	int pre_uisoc;
+};
+
+static struct pmic_adc_device *imix_r_dev;
+
+/*
+ * @ch_name:	HW channel name
+ * @res:	ADC resolution
+ * @r_ratio:	resistance ratio, represented by r_ratio[0] / r_ratio[1]
+ * @avg_num:	sampling times of AUXADC measurements then average it
+ * @regs:	request and data output registers for this channel
+ */
+struct auxadc_channels {
+	enum iio_chan_type type;
+	long info_mask;
+	/* AUXADC channel attribute */
+	const char *ch_name;
+	unsigned char res;
+	unsigned char r_ratio[2];
+	unsigned short avg_num;
+	const struct auxadc_regs *regs;
+};
+
+#define AUXADC_CHANNEL(_ch_name, _res)	\
+	[AUXADC_##_ch_name] = {				\
+		.type = IIO_VOLTAGE,			\
+		.info_mask = BIT(IIO_CHAN_INFO_RAW) |		\
+			     BIT(IIO_CHAN_INFO_PROCESSED),	\
+		.ch_name = __stringify(_ch_name),	\
+		.res = _res,				\
+	}
+
+/*
+ * The array represents all possible AUXADC channels found
+ * in the supported PMICs.
+ */
+static struct auxadc_channels auxadc_chans[] = {
+	AUXADC_CHANNEL(BATADC, 15),
+	AUXADC_CHANNEL(VCDT, 12),
+	AUXADC_CHANNEL(BAT_TEMP, 12),
+	AUXADC_CHANNEL(CHIP_TEMP, 12),
+	AUXADC_CHANNEL(VCORE_TEMP, 12),
+	AUXADC_CHANNEL(VPROC_TEMP, 12),
+	AUXADC_CHANNEL(VGPU_TEMP, 12),
+	AUXADC_CHANNEL(ACCDET, 12),
+	AUXADC_CHANNEL(HPOFS_CAL, 15),
+	AUXADC_CHANNEL(VTREF, 12),
+	AUXADC_CHANNEL(VBIF, 12),
+	AUXADC_CHANNEL(IMP, 15),
+	[AUXADC_IMIX_R] = {
+		.type = IIO_RESISTANCE,
+		.info_mask = BIT(IIO_CHAN_INFO_RAW),
+		.ch_name = "IMIX_R",
+	},
+	AUXADC_CHANNEL(VSYSSNS, 15),
+	AUXADC_CHANNEL(VIN1, 15),
+	AUXADC_CHANNEL(VIN2, 15),
+	AUXADC_CHANNEL(VIN3, 15),
+	AUXADC_CHANNEL(VIN4, 15),
+	AUXADC_CHANNEL(VIN5, 15),
+	AUXADC_CHANNEL(VIN6, 15),
+	AUXADC_CHANNEL(VIN7, 15),
+};
+
+struct auxadc_regs {
+	unsigned int enable_reg;
+	unsigned int enable_mask;
+	unsigned int ready_reg;
+	unsigned int ready_mask;
+	unsigned int value_reg;
+	unsigned int ext_thr_sel;
+	u8 src_sel;
+};
+
+#define AUXADC_REG(_ch_name, _chip, _enable_reg, _enable_mask, _value_reg) \
+	[AUXADC_##_ch_name] = {				\
+		.enable_reg = _chip##_##_enable_reg,	\
+		.enable_mask = _enable_mask,		\
+		.ready_reg = _chip##_##_value_reg,	\
+		.ready_mask = AUXADC_RDY_BIT,		\
+		.value_reg = _chip##_##_value_reg,	\
+	}						\
+
+#define TIA_ADC_REG(_src_sel, _chip)	\
+	[AUXADC_VIN##_src_sel] = {			\
+		.enable_reg = _chip##_AUXADC_RQST1,	\
+		.enable_mask = BIT(4),			\
+		.ready_reg = _chip##_AUXADC_ADC_CH12_L,	\
+		.ready_mask = AUXADC_RDY_BIT,		\
+		.value_reg = _chip##_AUXADC_ADC_CH12_L,	\
+		.ext_thr_sel = _chip##_SDMADC_CON0,	\
+		.src_sel = _src_sel,			\
+	}						\
+
+static const struct auxadc_regs mt6363_auxadc_regs_tbl[] = {
+	AUXADC_REG(BATADC, MT6363, AUXADC_RQST0, BIT(0), AUXADC_ADC0_L),
+	AUXADC_REG(BAT_TEMP, MT6363, AUXADC_RQST0, BIT(3), AUXADC_ADC3_L),
+	AUXADC_REG(CHIP_TEMP, MT6363, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
+	AUXADC_REG(VCORE_TEMP, MT6363, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
+	AUXADC_REG(VPROC_TEMP, MT6363, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
+	AUXADC_REG(VGPU_TEMP, MT6363, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
+	AUXADC_REG(VTREF, MT6363, AUXADC_RQST1, BIT(3), AUXADC_ADC11_L),
+	[AUXADC_IMP] = {
+		.enable_reg = MT6363_AUXADC_IMP0,
+		.enable_mask = BIT(0),
+		.ready_reg = MT6363_AUXADC_IMP1,
+		.ready_mask = BIT(7),
+		.value_reg = MT6363_AUXADC_ADC42_L,
+	},
+	AUXADC_REG(VSYSSNS, MT6363, AUXADC_RQST1, BIT(6), AUXADC_ADC_CH14_L),
+	TIA_ADC_REG(1, MT6363),
+	TIA_ADC_REG(2, MT6363),
+	TIA_ADC_REG(3, MT6363),
+	TIA_ADC_REG(4, MT6363),
+	TIA_ADC_REG(5, MT6363),
+	TIA_ADC_REG(6, MT6363),
+	TIA_ADC_REG(7, MT6363),
+};
+
+static const struct auxadc_regs mt6373_auxadc_regs_tbl[] = {
+	AUXADC_REG(CHIP_TEMP, MT6373, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
+	AUXADC_REG(VCORE_TEMP, MT6373, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
+	AUXADC_REG(VPROC_TEMP, MT6373, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
+	AUXADC_REG(VGPU_TEMP, MT6373, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
+	TIA_ADC_REG(1, MT6373),
+	TIA_ADC_REG(2, MT6373),
+	TIA_ADC_REG(3, MT6373),
+	TIA_ADC_REG(4, MT6373),
+	TIA_ADC_REG(5, MT6373),
+};
+
+struct auxadc_info {
+	const struct auxadc_regs *regs_tbl;
+};
+
+static const struct auxadc_info mt6363_info = {
+	.regs_tbl = mt6363_auxadc_regs_tbl,
+};
+
+static const struct auxadc_info mt6373_info = {
+	.regs_tbl = mt6373_auxadc_regs_tbl,
+};
+
+#define regmap_bulk_read_poll_timeout(map, addr, val, val_count, cond, sleep_us, timeout_us) \
+({ \
+	u64 __timeout_us = (timeout_us); \
+	unsigned long __sleep_us = (sleep_us); \
+	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
+	int __ret; \
+	might_sleep_if(__sleep_us); \
+	for (;;) { \
+		__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
+		if (__ret) \
+			break; \
+		if (cond) \
+			break; \
+		if ((__timeout_us) && \
+		    ktime_compare(ktime_get(), __timeout) > 0) { \
+			__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
+			break; \
+		} \
+		if (__sleep_us) \
+			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+	} \
+	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+})
+
+/*
+ * @adc_dev:	 pointer to the struct pmic_adc_device
+ * @auxadc_chan: pointer to the struct auxadc_channels, it represents specific
+		 auxadc channel
+ * @val:	 pointer to output value
+ */
+static int get_auxadc_out(struct pmic_adc_device *adc_dev,
+			  int channel, int channel2, int *val)
+{
+	int ret;
+	u16 buf = 0;
+	const struct auxadc_channels *auxadc_chan = &auxadc_chans[channel];
+
+	if (!auxadc_chan->regs)
+		return -EINVAL;
+
+	if (auxadc_chan->regs->ext_thr_sel) {
+		buf = (channel2 << EXT_THR_PURES_SHIFT)
+			| auxadc_chan->regs->src_sel;
+		ret = regmap_update_bits(adc_dev->regmap,
+					 auxadc_chan->regs->ext_thr_sel,
+					 EXT_THR_SEL_MASK, buf);
+		if (ret < 0)
+			return ret;
+	}
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg,
+		     auxadc_chan->regs->enable_mask);
+	usleep_range(auxadc_chan->avg_num * AUXADC_AVG_TIME_US,
+		     (auxadc_chan->avg_num + 1) * AUXADC_AVG_TIME_US);
+
+	ret = regmap_bulk_read_poll_timeout(adc_dev->regmap,
+					    auxadc_chan->regs->value_reg,
+					    buf, 2,
+					    (buf & AUXADC_RDY_BIT),
+					    AUXADC_POLL_DELAY_US,
+					    AUXADC_TIMEOUT_US);
+	*val = buf & (BIT(auxadc_chan->res) - 1);
+	if (ret)
+		dev_err(adc_dev->dev, "%s ret error code:%d!\n", auxadc_chan->ch_name, ret);
+
+	/* set PURES to OPEN after measuring done */
+	if (auxadc_chan->regs->ext_thr_sel) {
+		buf = (ADC_PURES_OPEN << EXT_THR_PURES_SHIFT)
+			| auxadc_chan->regs->src_sel;
+		ret = regmap_update_bits(adc_dev->regmap,
+					 auxadc_chan->regs->ext_thr_sel,
+					 EXT_THR_SEL_MASK, buf);
+	}
+
+	return ret;
+}
+
+static int gauge_get_imp_ibat(void)
+{
+	struct power_supply *psy;
+	union power_supply_propval prop;
+	int ret;
+
+	psy = power_supply_get_by_name("mtk-gauge");
+	if (!psy)
+		return 0;
+
+	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
+	if (ret)
+		return ret;
+
+	power_supply_put(psy);
+	return prop.intval;
+}
+
+static int get_imp_out(struct pmic_adc_device *adc_dev, int *val)
+{
+	int ret;
+	unsigned int buf = 0;
+	const struct auxadc_channels *auxadc_chan = &auxadc_chans[AUXADC_IMP];
+
+	if (!auxadc_chan->regs)
+		return -EINVAL;
+
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg,
+		     auxadc_chan->regs->enable_mask);
+	ret = regmap_read_poll_timeout(adc_dev->regmap, auxadc_chan->regs->ready_reg,
+					   buf, buf & auxadc_chan->regs->ready_mask,
+					   AUXADC_POLL_DELAY_US,
+					   AUXADC_TIMEOUT_US);
+	if (ret) {
+		dev_err(adc_dev->dev, "%s %s ret error code:%d!\n",
+			__func__, auxadc_chan->ch_name, ret);
+		return ret;
+	}
+
+	ret = regmap_bulk_read(adc_dev->regmap, auxadc_chan->regs->value_reg, (u8 *) &buf, 2);
+	if (ret)
+		return ret;
+	*val = buf & (BIT(auxadc_chan->res) - 1);
+	adc_dev->imp_curr = gauge_get_imp_ibat();
+
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg, 0);
+
+	return 0;
+}
+
+static int pmic_adc_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct pmic_adc_device *adc_dev = iio_priv(indio_dev);
+	const struct auxadc_channels *auxadc_chan;
+	int auxadc_out = 0;
+	int ret = 0;
+
+	mutex_lock(&adc_dev->lock);
+	switch (chan->channel) {
+	case AUXADC_IMP:
+		ret = get_imp_out(adc_dev, &auxadc_out);
+		break;
+	case AUXADC_IMIX_R:
+		auxadc_out = adc_dev->imix_r;
+		break;
+	default:
+		ret = get_auxadc_out(adc_dev,
+				     chan->channel, chan->channel2,
+				     &auxadc_out);
+		break;
+	}
+	mutex_unlock(&adc_dev->lock);
+
+	if (ret && ret != -ETIMEDOUT)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_PROCESSED:
+		auxadc_chan = &auxadc_chans[chan->channel];
+		*val = auxadc_out * auxadc_chan->r_ratio[0] * VOLT_FULL;
+		*val = (*val / auxadc_chan->r_ratio[1]) >> auxadc_chan->res;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_RAW:
+		*val = auxadc_out;
+		ret = IIO_VAL_INT;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (chan->channel == AUXADC_IMP) {
+		*val2 = adc_dev->imp_curr;
+		ret = IIO_VAL_INT_MULTIPLE;
+	}
+
+	return ret;
+}
+
+static int pmic_adc_fwnode_xlate(struct iio_dev *indio_dev,
+			     const struct fwnode_reference_args *iiospec)
+{
+	int i;
+	int channel = DT_CHANNEL_CONVERT(iiospec->args[0]);
+	int channel2 = DT_PURES_CONVERT(iiospec->args[0]);
+
+	for (i = 0; i < indio_dev->num_channels; i++) {
+		if (indio_dev->channels[i].channel == channel &&
+		    indio_dev->channels[i].channel2 == channel2)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info pmic_adc_info = {
+	.read_raw = &pmic_adc_read_raw,
+	.fwnode_xlate = &pmic_adc_fwnode_xlate,
+};
+
+static int auxadc_init_imix_r(struct pmic_adc_device *adc_dev,
+			      struct device_node *imix_r_node)
+{
+	unsigned int val = 0;
+	int ret;
+
+	if (!adc_dev)
+		return -EINVAL;
+
+	adc_dev->isink_load = devm_regulator_get_exclusive(adc_dev->dev, "isink_load");
+	if (IS_ERR(adc_dev->isink_load)) {
+		dev_err(adc_dev->dev, "Failed to get isink_load regulator, ret=%d\n",
+			(int)PTR_ERR(adc_dev->isink_load));
+		return PTR_ERR(adc_dev->isink_load);
+	}
+
+	imix_r_dev = adc_dev;
+	if (imix_r_dev->imix_r)
+		return 0;
+
+	ret = of_property_read_u32(imix_r_node, "val", &val);
+	if (ret)
+		dev_notice(imix_r_dev->dev, "no imix_r, ret=%d\n", ret);
+	imix_r_dev->imix_r = (int)val;
+	imix_r_dev->pre_uisoc = 101;
+	return 0;
+}
+
+static int auxadc_get_data_from_dt(struct pmic_adc_device *adc_dev,
+				   struct iio_chan_spec *iio_chan,
+				   struct device_node *node)
+{
+	struct auxadc_channels *auxadc_chan;
+	unsigned int channel = 0;
+	unsigned int value = 0;
+	unsigned int val_arr[2] = {0};
+	int ret;
+
+	ret = of_property_read_u32(node, "channel", &channel);
+	if (ret) {
+		dev_err(adc_dev->dev, "invalid channel in node:%s\n",
+			   node->name);
+		return ret;
+	}
+	if (channel > AUXADC_CHAN_MAX) {
+		dev_err(adc_dev->dev, "invalid channel number %d in node:%s\n",
+			   channel, node->name);
+		return -EINVAL;
+	}
+	if (channel >= ARRAY_SIZE(auxadc_chans)) {
+		dev_err(adc_dev->dev, "channel number %d in node:%s not exists\n",
+			   channel, node->name);
+		return -EINVAL;
+	}
+	iio_chan->channel = channel;
+	iio_chan->datasheet_name = auxadc_chans[channel].ch_name;
+	iio_chan->info_mask_separate = auxadc_chans[channel].info_mask;
+	iio_chan->type = auxadc_chans[channel].type;
+	iio_chan->extend_name = node->name;
+	ret = of_property_read_u32(node, "pures", &value);
+	if (!ret)
+		iio_chan->channel2 = value;
+
+	if (channel == AUXADC_IMIX_R)
+		return auxadc_init_imix_r(adc_dev, node);
+
+	auxadc_chan = &auxadc_chans[channel];
+	auxadc_chan->regs = &adc_dev->info->regs_tbl[channel];
+
+	ret = of_property_read_u32_array(node, "resistance-ratio", val_arr, 2);
+	if (!ret) {
+		auxadc_chan->r_ratio[0] = val_arr[0];
+		auxadc_chan->r_ratio[1] = val_arr[1];
+	} else {
+		auxadc_chan->r_ratio[0] = AUXADC_DEF_R_RATIO;
+		auxadc_chan->r_ratio[1] = 1;
+	}
+
+	ret = of_property_read_u32(node, "avg-num", &value);
+	if (!ret)
+		auxadc_chan->avg_num = value;
+	else
+		auxadc_chan->avg_num = AUXADC_DEF_AVG_NUM;
+
+	return 0;
+}
+
+static int auxadc_parse_dt(struct pmic_adc_device *adc_dev,
+			   struct device_node *node)
+{
+	struct iio_chan_spec *iio_chan;
+	struct device_node *child;
+	unsigned int index = 0;
+	int ret;
+
+	adc_dev->nchannels = of_get_available_child_count(node);
+	if (!adc_dev->nchannels)
+		return -EINVAL;
+
+	adc_dev->iio_chans = devm_kcalloc(adc_dev->dev, adc_dev->nchannels,
+		sizeof(*adc_dev->iio_chans), GFP_KERNEL);
+	if (!adc_dev->iio_chans)
+		return -ENOMEM;
+	iio_chan = adc_dev->iio_chans;
+
+	for_each_available_child_of_node(node, child) {
+		ret = auxadc_get_data_from_dt(adc_dev, iio_chan, child);
+		if (ret < 0) {
+			of_node_put(child);
+			return ret;
+		}
+		iio_chan->indexed = 1;
+		iio_chan->address = index++;
+		iio_chan++;
+	}
+
+	return 0;
+}
+
+static int pmic_adc_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct pmic_adc_device *adc_dev;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	adc_dev = iio_priv(indio_dev);
+	adc_dev->dev = &pdev->dev;
+	adc_dev->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	mutex_init(&adc_dev->lock);
+	adc_dev->info = of_device_get_match_data(&pdev->dev);
+
+	ret = auxadc_parse_dt(adc_dev, node);
+	if (ret) {
+		dev_notice(&pdev->dev, "auxadc_parse_dt fail, ret=%d\n", ret);
+		return ret;
+	}
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->info = &pmic_adc_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = adc_dev->iio_chans;
+	indio_dev->num_channels = adc_dev->nchannels;
+
+	ret = devm_iio_device_register(&pdev->dev, indio_dev);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "failed to register iio device!\n");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "probe done\n");
+
+	return 0;
+}
+
+static const struct of_device_id pmic_adc_of_match[] = {
+	{ .compatible = "mediatek,mt6363-auxadc", .data = &mt6363_info, },
+	{ .compatible = "mediatek,mt6373-auxadc", .data = &mt6373_info, },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pmic_adc_of_match);
+
+static struct platform_driver pmic_adc_driver = {
+	.driver = {
+		.name = "mtk-spmi-pmic-adc",
+		.of_match_table = pmic_adc_of_match,
+	},
+	.probe	= pmic_adc_probe,
+};
+module_platform_driver(pmic_adc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek SPMI PMIC ADC Driver");
-- 
2.46.0



From Lu.Tang at mediatek.com  Fri Mar 14 00:32:30 2025
From: Lu.Tang at mediatek.com (Lu.Tang)
Date: Fri, 14 Mar 2025 15:32:30 +0800
Subject: [PATCH 4/5] spmi: mediatek: modify spmi dirver for mt8196
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <20250314073307.25092-5-Lu.Tang@mediatek.com>

From: "Lu.Tang" <lu.tang at mediatek.com>

Modify spmi driver for mt8196 pmic.
Add pmif_s/pmif_m controller and rcs irq handler.

Signed-off-by: Lu.Tang <lu.tang at mediatek.com>
---
 drivers/spmi/spmi-mtk-pmif.c | 1040 +++++++++++++++++++++++++++++++---
 1 file changed, 976 insertions(+), 64 deletions(-)

diff --git a/drivers/spmi/spmi-mtk-pmif.c b/drivers/spmi/spmi-mtk-pmif.c
index 160d36f7d238..36f7ef80e7c4 100644
--- a/drivers/spmi/spmi-mtk-pmif.c
+++ b/drivers/spmi/spmi-mtk-pmif.c
@@ -1,14 +1,20 @@
 // SPDX-License-Identifier: GPL-2.0
 //
-// Copyright (c) 2021 MediaTek Inc.
+// Copyright (c) 2024 MediaTek Inc.
 
 #include <linux/clk.h>
 #include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/sched/clock.h>
+#include <linux/sched/mm.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/spmi.h>
+#include <linux/irq.h>
 
 #define SWINF_IDLE	0x00
 #define SWINF_WFVLDCLR	0x06
@@ -21,14 +27,21 @@
 #define PMIF_CMD_EXT_REG_LONG	3
 
 #define PMIF_DELAY_US   10
-#define PMIF_TIMEOUT_US (10 * 1000)
+#define PMIF_TIMEOUT_US (100 * 1000)
 
 #define PMIF_CHAN_OFFSET 0x5
 
+#define PMIF_CAPS_VER_1 1
+#define PMIF_CAPS_VER_2 2
+
 #define PMIF_MAX_CLKS	3
 
 #define SPMI_OP_ST_BUSY 1
 
+#define SPMI_SOC_CHANNEL 2
+
+#define PMIF_IRQDESC(name) { #name, pmif_##name##_irq_handler, -1}
+
 struct ch_reg {
 	u32 ch_sta;
 	u32 wdata;
@@ -41,25 +54,53 @@ struct pmif_data {
 	const u32	*regs;
 	const u32	*spmimst_regs;
 	u32	soc_chan;
+	u32 caps;
 };
 
 struct pmif {
-	void __iomem	*base;
-	void __iomem	*spmimst_base;
+	void __iomem	*pmif_base[2];
+	void __iomem	*spmimst_base[2];
 	struct ch_reg	chan;
 	struct clk_bulk_data clks[PMIF_MAX_CLKS];
 	size_t nclks;
 	const struct pmif_data *data;
-	raw_spinlock_t lock;
+	raw_spinlock_t	lock_m;
+	raw_spinlock_t	lock_p;
+	struct spmi_controller  *spmic;
+	struct wakeup_source *pmif_m_Thread_lock;
+	struct wakeup_source *pmif_p_Thread_lock;
+	struct mutex pmif_m_mutex;
+	struct mutex pmif_p_mutex;
+	int		irq;
+	int		irq_p;
+	struct irq_domain	*domain;
+	struct irq_chip		irq_chip;
+	struct irq_chip		irq_chip_p;
+	int			rcs_irq;
+	int			rcs_irq_p;
+	struct mutex		rcs_m_irqlock;
+	struct mutex		rcs_p_irqlock;
+	bool	   *rcs_enable_hwirq;
+	int spmi_nack_irq;
+	int spmi_p_nack_irq;
 };
 
 static const char * const pmif_clock_names[] = {
 	"pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux",
 };
 
+struct pmif_irq_desc {
+	const char *name;
+	irq_handler_t irq_handler;
+	int irq;
+};
+
 enum pmif_regs {
 	PMIF_INIT_DONE,
 	PMIF_INF_EN,
+	MD_AUXADC_RDATA_0_ADDR,
+	MD_AUXADC_RDATA_1_ADDR,
+	MD_AUXADC_RDATA_2_ADDR,
 	PMIF_ARB_EN,
 	PMIF_CMDISSUE_EN,
 	PMIF_TIMER_CTRL,
@@ -103,6 +144,11 @@ enum pmif_regs {
 	PMIF_SWINF_3_RDATA_31_0,
 	PMIF_SWINF_3_ACC,
 	PMIF_SWINF_3_VLD_CLR,
+	PMIF_PMIC_SWINF_0_PER,
+	PMIF_PMIC_SWINF_1_PER,
+	PMIF_ACC_VIO_INFO_0,
+	PMIF_ACC_VIO_INFO_1,
+	PMIF_ACC_VIO_INFO_2,
 };
 
 static const u32 mt6873_regs[] = {
@@ -201,6 +247,63 @@ static const u32 mt8195_regs[] = {
 	[PMIF_SWINF_3_STA] = 0x08E8,
 };
 
+static const u32 mt6xxx_regs[] = {
+	[PMIF_INIT_DONE] =			0x0000,
+	[PMIF_INF_EN] =				0x0024,
+	[MD_AUXADC_RDATA_0_ADDR] =		0x0080,
+	[MD_AUXADC_RDATA_1_ADDR] =		0x0084,
+	[MD_AUXADC_RDATA_2_ADDR] =		0x0088,
+	[PMIF_ARB_EN] =				0x0150,
+	[PMIF_CMDISSUE_EN] =			0x03B8,
+	[PMIF_TIMER_CTRL] =			0x03E4,
+	[PMIF_SPI_MODE_CTRL] =			0x0408,
+	[PMIF_IRQ_EVENT_EN_0] =			0x0420,
+	[PMIF_IRQ_FLAG_0] =			0x0428,
+	[PMIF_IRQ_CLR_0] =			0x042C,
+	[PMIF_IRQ_EVENT_EN_1] =			0x0430,
+	[PMIF_IRQ_FLAG_1] =			0x0438,
+	[PMIF_IRQ_CLR_1] =			0x043C,
+	[PMIF_IRQ_EVENT_EN_2] =			0x0440,
+	[PMIF_IRQ_FLAG_2] =			0x0448,
+	[PMIF_IRQ_CLR_2] =			0x044C,
+	[PMIF_IRQ_EVENT_EN_3] =			0x0450,
+	[PMIF_IRQ_FLAG_3] =			0x0458,
+	[PMIF_IRQ_CLR_3] =			0x045C,
+	[PMIF_IRQ_EVENT_EN_4] =			0x0460,
+	[PMIF_IRQ_FLAG_4] =			0x0468,
+	[PMIF_IRQ_CLR_4] =			0x046C,
+	[PMIF_WDT_EVENT_EN_0] =			0x0474,
+	[PMIF_WDT_FLAG_0] =			0x0478,
+	[PMIF_WDT_EVENT_EN_1] =			0x047C,
+	[PMIF_WDT_FLAG_1] =			0x0480,
+	[PMIF_SWINF_0_ACC] =			0x0800,
+	[PMIF_SWINF_0_WDATA_31_0] =		0x0804,
+	[PMIF_SWINF_0_RDATA_31_0] =		0x0814,
+	[PMIF_SWINF_0_VLD_CLR] =		0x0824,
+	[PMIF_SWINF_0_STA] =			0x0828,
+	[PMIF_SWINF_1_ACC] =			0x0840,
+	[PMIF_SWINF_1_WDATA_31_0] =		0x0844,
+	[PMIF_SWINF_1_RDATA_31_0] =		0x0854,
+	[PMIF_SWINF_1_VLD_CLR] =		0x0864,
+	[PMIF_SWINF_1_STA] =			0x0868,
+	[PMIF_SWINF_2_ACC] =			0x0880,
+	[PMIF_SWINF_2_WDATA_31_0] =		0x0884,
+	[PMIF_SWINF_2_RDATA_31_0] =		0x0894,
+	[PMIF_SWINF_2_VLD_CLR] =		0x08A4,
+	[PMIF_SWINF_2_STA] =			0x08A8,
+	[PMIF_SWINF_3_ACC] =			0x08C0,
+	[PMIF_SWINF_3_WDATA_31_0] =		0x08C4,
+	[PMIF_SWINF_3_RDATA_31_0] =		0x08D4,
+	[PMIF_SWINF_3_VLD_CLR] =		0x08E4,
+	[PMIF_SWINF_3_STA] =			0x08E8,
+	[PMIF_PMIC_SWINF_0_PER] =		0x093C,
+	[PMIF_PMIC_SWINF_1_PER] =		0x0940,
+	[PMIF_ACC_VIO_INFO_0] =			0x0980,
+	[PMIF_ACC_VIO_INFO_1] =			0x0984,
+	[PMIF_ACC_VIO_INFO_2] =			0x0988,
+
+};
+
 enum spmi_regs {
 	SPMI_OP_ST_CTRL,
 	SPMI_GRP_ID_EN,
@@ -262,26 +365,132 @@ static const u32 mt8195_spmi_regs[] = {
 	[SPMI_MST_DBG] = 0x00FC,
 };
 
-static u32 pmif_readl(struct pmif *arb, enum pmif_regs reg)
+static const u32 mt6853_spmi_regs[] = {
+	[SPMI_OP_ST_CTRL] =	0x0000,
+	[SPMI_GRP_ID_EN] =	0x0004,
+	[SPMI_OP_ST_STA] =	0x0008,
+	[SPMI_MST_SAMPL] =	0x000C,
+	[SPMI_MST_REQ_EN] =	0x0010,
+	[SPMI_MST_RCS_CTRL] =	0x0014,
+	[SPMI_SLV_3_0_EINT] =	0x0020,
+	[SPMI_SLV_7_4_EINT] =	0x0024,
+	[SPMI_SLV_B_8_EINT] =	0x0028,
+	[SPMI_SLV_F_C_EINT] =	0x002C,
+	[SPMI_REC_CTRL] =	0x0040,
+	[SPMI_REC0] =		0x0044,
+	[SPMI_REC1] =		0x0048,
+	[SPMI_REC2] =		0x004C,
+	[SPMI_REC3] =		0x0050,
+	[SPMI_REC4] =		0x0054,
+	[SPMI_REC_CMD_DEC] =	0x005C,
+	[SPMI_DEC_DBG] =	0x00F8,
+	[SPMI_MST_DBG] =	0x00FC,
+};
+
+enum {
+	IRQ_LAT_LIMIT_REACHED = 6,
+	IRQ_HW_MONITOR = 7,
+	IRQ_WDT = 8,
+	/* MT6833/MT6877 series */
+	IRQ_HW_MONITOR_V3 = 12,
+	IRQ_WDT_V3 = 13,
+	IRQ_ALL_PMIC_MPU_VIO_V3 = 14,
+	/* MT6885/MT6873 series */
+	IRQ_PMIC_CMD_ERR_PARITY_ERR = 17,
+	IRQ_PMIF_ACC_VIO = 20,
+	IRQ_PMIC_ACC_VIO = 21,
+	/* MT6985/MT6897 */
+	IRQ_PMIF_ACC_VIO_V3 = 27,
+	/* MT6853 series */
+	IRQ_PMIF_ACC_VIO_V2 = 31,
+};
+
+enum {
+	IRQ_PMIC_ACC_VIO_V2 = 0,
+	IRQ_PMIF_SWINF_ACC_ERR_0 = 3,
+	IRQ_PMIF_SWINF_ACC_ERR_1 = 4,
+	IRQ_PMIF_SWINF_ACC_ERR_2 = 5,
+	IRQ_PMIF_SWINF_ACC_ERR_3 = 6,
+	IRQ_PMIF_SWINF_ACC_ERR_4 = 7,
+	IRQ_PMIF_SWINF_ACC_ERR_5 = 8,
+	IRQ_HW_MONITOR_V2 = 18,
+	IRQ_WDT_V2 = 19,
+	IRQ_ALL_PMIC_MPU_VIO_V2 = 20,
+	IRQ_PMIF_SWINF_ACC_ERR_0_V2 = 23,
+	IRQ_PMIF_SWINF_ACC_ERR_1_V2 = 24,
+	IRQ_PMIF_SWINF_ACC_ERR_2_V2 = 25,
+	IRQ_PMIF_SWINF_ACC_ERR_3_V2 = 26,
+	IRQ_PMIF_SWINF_ACC_ERR_4_V2 = 27,
+	IRQ_PMIF_SWINF_ACC_ERR_5_V2 = 28,
+	/* MT6983/MT6879 */
+	IRQ_HW_MONITOR_V4 = 29,
+	IRQ_WDT_V4 = 30,
+	IRQ_ALL_PMIC_MPU_VIO_V4 = 31,
+};
+
+struct spmi_dev {
+	int exist;
+	int slvid;
+	unsigned int path;
+	unsigned short hwcid_addr;
+	unsigned char hwcid_val;
+};
+
+static struct spmi_dev spmidev[16];
+
+static void spmi_dev_parse(struct platform_device *pdev)
 {
-	return readl(arb->base + arb->data->regs[reg]);
+	int i = 0, j = 0, ret = 0;
+	u32 spmi_dev_mask = 0;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "spmi-dev-mask",
+				  &spmi_dev_mask);
+	if (ret)
+		dev_info(&pdev->dev, "No spmi-dev-mask found in dts, default all PMIC on SPMI-M\n");
+
+	j = spmi_dev_mask;
+	for (i = 0; i < 16; i++) {
+		if (j & BIT(i))
+			spmidev[i].path = 1; /* slvid i is in path p */
+		else
+			spmidev[i].path = 0;
+	}
+}
+
+unsigned long long get_current_time_ms(void)
+{
+	unsigned long long cur_ts;
+
+	cur_ts = sched_clock();
+	do_div(cur_ts, 1000000);
+	return cur_ts;
 }
 
-static void pmif_writel(struct pmif *arb, u32 val, enum pmif_regs reg)
+static u32 pmif_readl(void __iomem *addr, struct pmif *arb, enum pmif_regs reg)
 {
-	writel(val, arb->base + arb->data->regs[reg]);
+	return readl(addr + arb->data->regs[reg]);
 }
 
-static void mtk_spmi_writel(struct pmif *arb, u32 val, enum spmi_regs reg)
+static void pmif_writel(void __iomem *addr, struct pmif *arb, u32 val, enum pmif_regs reg)
 {
-	writel(val, arb->spmimst_base + arb->data->spmimst_regs[reg]);
+	writel(val, addr + arb->data->regs[reg]);
 }
 
-static bool pmif_is_fsm_vldclr(struct pmif *arb)
+static void mtk_spmi_writel(void __iomem *addr, struct pmif *arb, u32 val, enum spmi_regs reg)
+{
+	writel(val, addr + arb->data->spmimst_regs[reg]);
+}
+
+static u32 mtk_spmi_readl(void __iomem *addr, struct pmif *arb, enum spmi_regs reg)
+{
+	return readl(addr + arb->data->spmimst_regs[reg]);
+}
+
+static bool pmif_is_fsm_vldclr(void __iomem *addr, struct pmif *arb)
 {
 	u32 reg_rdata;
 
-	reg_rdata = pmif_readl(arb, arb->chan.ch_sta);
+	reg_rdata = pmif_readl(addr, arb, arb->chan.ch_sta);
 
 	return GET_SWINF(reg_rdata) == SWINF_WFVLDCLR;
 }
@@ -298,8 +507,8 @@ static int pmif_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
 
 	cmd = opc - SPMI_CMD_RESET;
 
-	mtk_spmi_writel(arb, (cmd << 0x4) | sid, SPMI_OP_ST_CTRL);
-	ret = readl_poll_timeout_atomic(arb->spmimst_base + arb->data->spmimst_regs[SPMI_OP_ST_STA],
+	mtk_spmi_writel(arb->spmimst_base[spmidev[sid].path], arb, (cmd << 0x4) | sid, SPMI_OP_ST_CTRL);
+	ret = readl_poll_timeout_atomic(arb->spmimst_base[spmidev[sid].path] + arb->data->spmimst_regs[SPMI_OP_ST_STA],
 					rdata, (rdata & SPMI_OP_ST_BUSY) == SPMI_OP_ST_BUSY,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0)
@@ -315,7 +524,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	struct ch_reg *inf_reg;
 	int ret;
 	u32 data, cmd;
-	unsigned long flags;
+	unsigned long flags_m;
 
 	/* Check for argument validation. */
 	if (sid & ~0xf) {
@@ -336,31 +545,31 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	else
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&arb->lock, flags);
+	raw_spin_lock_irqsave(&arb->lock_m, flags_m);
 	/* Wait for Software Interface FSM state to be IDLE. */
 	inf_reg = &arb->chan;
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path] + arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_IDLE,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
 		/* set channel ready if the data has transferred */
-		if (pmif_is_fsm_vldclr(arb))
-			pmif_writel(arb, 1, inf_reg->ch_rdy);
-		raw_spin_unlock_irqrestore(&arb->lock, flags);
+		if (pmif_is_fsm_vldclr(arb->pmif_base[spmidev[sid].path], arb))
+			pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, inf_reg->ch_rdy);
+		raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
 		return ret;
 	}
 
 	/* Send the command. */
 	cmd = (opc << 30) | (sid << 24) | ((len - 1) << 16) | addr;
-	pmif_writel(arb, cmd, inf_reg->ch_send);
-	raw_spin_unlock_irqrestore(&arb->lock, flags);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, cmd, inf_reg->ch_send);
+	raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 
 	/*
 	 * Wait for Software Interface FSM state to be WFVLDCLR,
 	 * read the data and clear the valid flag.
 	 */
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path]  + arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_WFVLDCLR,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
@@ -368,9 +577,9 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 		return ret;
 	}
 
-	data = pmif_readl(arb, inf_reg->rdata);
+	data = pmif_readl(arb->pmif_base[spmidev[sid].path], arb, inf_reg->rdata);
 	memcpy(buf, &data, len);
-	pmif_writel(arb, 1, inf_reg->ch_rdy);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, inf_reg->ch_rdy);
 
 	return 0;
 }
@@ -382,7 +591,7 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	struct ch_reg *inf_reg;
 	int ret;
 	u32 data, wdata, cmd;
-	unsigned long flags;
+	unsigned long flags_m;
 
 	/* Check for argument validation. */
 	if (unlikely(sid & ~0xf)) {
@@ -409,27 +618,27 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	/* Set the write data. */
 	memcpy(&wdata, buf, len);
 
-	raw_spin_lock_irqsave(&arb->lock, flags);
+	raw_spin_lock_irqsave(&arb->lock_m, flags_m);
 	/* Wait for Software Interface FSM state to be IDLE. */
 	inf_reg = &arb->chan;
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path] + arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_IDLE,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
 		/* set channel ready if the data has transferred */
-		if (pmif_is_fsm_vldclr(arb))
-			pmif_writel(arb, 1, inf_reg->ch_rdy);
-		raw_spin_unlock_irqrestore(&arb->lock, flags);
+		if (pmif_is_fsm_vldclr(arb->pmif_base[spmidev[sid].path], arb))
+			pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, inf_reg->ch_rdy);
+		raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
 		return ret;
 	}
 
-	pmif_writel(arb, wdata, inf_reg->wdata);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, wdata, inf_reg->wdata);
 
 	/* Send the command. */
 	cmd = (opc << 30) | BIT(29) | (sid << 24) | ((len - 1) << 16) | addr;
-	pmif_writel(arb, cmd, inf_reg->ch_send);
-	raw_spin_unlock_irqrestore(&arb->lock, flags);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, cmd, inf_reg->ch_send);
+	raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 
 	return 0;
 }
@@ -437,15 +646,642 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 static const struct pmif_data mt6873_pmif_arb = {
 	.regs = mt6873_regs,
 	.spmimst_regs = mt6873_spmi_regs,
-	.soc_chan = 2,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_1,
 };
 
 static const struct pmif_data mt8195_pmif_arb = {
 	.regs = mt8195_regs,
 	.spmimst_regs = mt8195_spmi_regs,
-	.soc_chan = 2,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_1,
 };
+static const struct pmif_data mt6xxx_pmif_arb = {
+	.regs = mt6xxx_regs,
+	.spmimst_regs = mt6853_spmi_regs,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_2,
+};
+static void mtk_spmi_readl_datas(struct pmif *arb, int id, unsigned int *spmi_nack,
+		unsigned int *spmi_nack_data, unsigned int *spmi_rcs_nack,
+		unsigned int *spmi_debug_nack, unsigned int *spmi_mst_nack)
+{
+	if (id < 0 || id >= PMIF_CAPS_VER_2) {
+		dev_err(&arb->spmic->dev, "%s Invalid id: %d\n", __func__, id);
+		return;
+	}
+	*spmi_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC0);
+	*spmi_nack_data = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC1);
+	*spmi_rcs_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC_CMD_DEC);
+	*spmi_debug_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_DEC_DBG);
+	*spmi_mst_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_MST_DBG);
+}
+static irqreturn_t spmi_nack_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int sid = 0;
+	unsigned int spmi_nack = 0, spmi_p_nack = 0, spmi_nack_data = 0, spmi_p_nack_data = 0;
+	unsigned int spmi_rcs_nack = 0, spmi_debug_nack = 0, spmi_mst_nack = 0,
+		spmi_p_rcs_nack = 0, spmi_p_debug_nack = 0, spmi_p_mst_nack = 0;
+	u8 rdata = 0, rdata1 = 0;
+	unsigned short mt6316INTSTA = 0x240, hwcidaddr_mt6316 = 0x209, VIO18_SWITCH_6363 = 0x53,
+		hwcidaddr_mt6363 = 0x9;
+
+	mutex_lock(&arb->pmif_m_mutex);
+
+	mtk_spmi_readl_datas(arb, 0, &spmi_nack, &spmi_nack_data, &spmi_rcs_nack,
+		&spmi_debug_nack, &spmi_mst_nack);
+	if (!IS_ERR(arb->spmimst_base[1])) {
+		mtk_spmi_readl_datas(arb, 1, &spmi_p_nack, &spmi_p_nack_data, &spmi_p_rcs_nack,
+			&spmi_p_debug_nack, &spmi_p_mst_nack);
+	}
+	if ((spmi_nack & 0xD8) || (spmi_p_nack & 0xD8)) {
+		if (spmi_p_nack & 0xD8) {
+			for (sid = 0x8; sid >= 0x6; sid--) {
+				arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, sid,
+					mt6316INTSTA, &rdata, 1);
+				arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, sid,
+					hwcidaddr_mt6316, &rdata1, 1);
+				dev_notice(&arb->spmic->dev, "%s slvid 0x%x INT_RAW_STA 0x%x cid 0x%x\n",
+					__func__, sid, rdata, rdata1);
+			}
+		}
+		dev_notice(&arb->spmic->dev, "%s spmi transaction fail irq triggered", __func__);
+		dev_notice(&arb->spmic->dev, "SPMI_REC0 m/p:0x%x/0x%x SPMI_REC1 m/p 0x%x/0x%x\n",
+			spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+	}
+	if ((spmi_rcs_nack & 0xC0000) || (spmi_p_rcs_nack & 0xC0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_rcs transaction fail irq triggered SPMI_REC_CMD_DEC m/p:0x%x/0x%x\n",
+			__func__, spmi_rcs_nack, spmi_p_rcs_nack);
+	}
+	if ((spmi_debug_nack & 0xF0000) || (spmi_p_debug_nack & 0xF0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_debug_nack transaction fail irq triggered SPMI_DEC_DBG m/p: 0x%x/0x%x\n",
+			__func__, spmi_debug_nack, spmi_p_debug_nack);
+	}
+	if ((spmi_mst_nack & 0xC0000) || (spmi_p_mst_nack & 0xC0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_mst_nack transaction fail irq triggered SPMI_MST_DBG m/p: 0x%x/0x%x\n",
+		__func__, spmi_mst_nack, spmi_p_mst_nack);
+	}
 
+	if ((spmi_nack & 0x20) || (spmi_p_nack & 0x20)) {
+		dev_notice(&arb->spmic->dev, "%s spmi transaction fail (Read) irq triggered", __func__);
+		dev_notice(&arb->spmic->dev, "SPMI_REC0 m/p:0x%x/0x%x SPMI_REC1 m/p 0x%x/0x%x\n",
+			spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+	}
+
+	if ((spmi_nack & 0xF8) || (spmi_rcs_nack & 0xC0000) ||
+		(spmi_debug_nack & 0xF0000) || (spmi_mst_nack & 0xC0000)) {
+		mtk_spmi_writel(arb->spmimst_base[0], arb, 0x3, SPMI_REC_CTRL);
+	} else if ((spmi_p_nack & 0xF8) || (spmi_p_rcs_nack & 0xC0000) ||
+		(spmi_p_debug_nack & 0xF0000) || (spmi_p_mst_nack & 0xC0000)) {
+		if (spmi_p_nack & 0xD8) {
+			dev_notice(&arb->spmic->dev, "%s SPMI_REC0 m/p:0x%x/0x%x, SPMI_REC1 m/p:0x%x/0x%x\n",
+				__func__, spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+			dev_notice(&arb->spmic->dev, "%s SPMI_REC_CMD_DEC m/p:0x%x/0x%x\n", __func__,
+				spmi_rcs_nack, spmi_p_rcs_nack);
+			dev_notice(&arb->spmic->dev, "%s SPMI_DEC_DBG m/p:0x%x/0x%x\n", __func__,
+				spmi_debug_nack, spmi_p_debug_nack);
+			dev_notice(&arb->spmic->dev, "%s SPMI_MST_DBG m/p:0x%x/0x%x\n", __func__,
+				spmi_mst_nack, spmi_p_mst_nack);
+			arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, 0x4,
+				hwcidaddr_mt6363, &rdata, 1);
+			arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, 0x4,
+				VIO18_SWITCH_6363, &rdata1, 1);
+			dev_notice(&arb->spmic->dev, "%s 6363 CID/VIO18_SWITCH 0x%x/0x%x\n", __func__, rdata, rdata1);
+		}
+		mtk_spmi_writel(arb->spmimst_base[1], arb, 0x3, SPMI_REC_CTRL);
+	} else
+		dev_notice(&arb->spmic->dev, "%s IRQ not cleared\n", __func__);
+
+	mutex_unlock(&arb->pmif_m_mutex);
+
+	return IRQ_HANDLED;
+}
+static int spmi_nack_irq_register(struct platform_device *pdev,
+		struct pmif *arb, int irq)
+{
+	int ret = 0;
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+				spmi_nack_irq_handler,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_SHARED,
+				"spmi_nack_irq", arb);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "request %s irq fail\n",
+			"spmi_nack_irq");
+	}
+	return ret;
+}
+static void rcs_irq_lock(struct irq_data *data)
+{
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	mutex_lock(&arb->rcs_m_irqlock);
+}
+static void rcs_irq_sync_unlock(struct irq_data *data)
+{
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	mutex_unlock(&arb->rcs_m_irqlock);
+}
+static void rcs_irq_enable(struct irq_data *data)
+{
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	arb->rcs_enable_hwirq[hwirq] = true;
+}
+static void rcs_irq_disable(struct irq_data *data)
+{
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	arb->rcs_enable_hwirq[hwirq] = false;
+}
+static int rcs_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	return irq_set_irq_wake(arb->rcs_irq, on);
+}
+static int rcs_irq_p_set_wake(struct irq_data *data, unsigned int on)
+{
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	return irq_set_irq_wake(arb->rcs_irq_p, on);
+}
+static const struct irq_chip rcs_irq_chip = {
+	.name			= "rcs_irq",
+	.irq_bus_lock		= rcs_irq_lock,
+	.irq_bus_sync_unlock	= rcs_irq_sync_unlock,
+	.irq_enable		= rcs_irq_enable,
+	.irq_disable		= rcs_irq_disable,
+	.irq_set_wake 		= rcs_irq_set_wake,
+};
+
+static const struct irq_chip rcs_irq_chip_p = {
+	.name			= "rcs_irq_p",
+	.irq_bus_lock		= rcs_irq_lock,
+	.irq_bus_sync_unlock	= rcs_irq_sync_unlock,
+	.irq_enable		= rcs_irq_enable,
+	.irq_disable		= rcs_irq_disable,
+	.irq_set_wake 		= rcs_irq_p_set_wake,
+};
+static int rcs_irq_map(struct irq_domain *d, unsigned int virq,
+			irq_hw_number_t hw)
+{
+	struct pmif *arb = d->host_data;
+	irq_set_chip_data(virq, arb);
+	irq_set_chip(virq, &arb->irq_chip);
+	irq_set_nested_thread(virq, 1);
+	irq_set_parent(virq, arb->rcs_irq);
+	irq_set_noprobe(virq);
+	return 0;
+}
+static const struct irq_domain_ops rcs_irq_domain_ops = {
+	.map	= rcs_irq_map,
+	.xlate	= irq_domain_xlate_onetwocell,
+};
+static void pmif_lat_limit_reached_irq_handler(int irq, void *data)
+{
+}
+static void pmif_acc_vio_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF ACC violation debug info\n");
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF-M\n");
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_0 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_0));
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_1 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_1));
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_2 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_2));
+	if (!IS_ERR(arb->pmif_base[1])) {
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF-P\n");
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_0 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_0));
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_1 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_1));
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_2 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_2));
+	}
+}
+static void pmif_wdt_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	pmif_writel(arb->pmif_base[0], arb, 0x40000000, PMIF_IRQ_CLR_0);
+	if (!IS_ERR(arb->pmif_base[1]))
+		pmif_writel(arb->pmif_base[1], arb, 0x40000000, PMIF_IRQ_CLR_0);
+	dev_notice(&arb->spmic->dev, "[PMIF]:WDT IRQ HANDLER DONE\n");
+}
+static void pmif_pmif_acc_vio_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmif_acc_vio");
+#endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmif_acc_vio\n");
+}
+static void pmif_pmic_acc_vio_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmic_acc_vio");
+#endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmic_acc_vio\n");
+}
+static void pmif_cmd_err_parity_err_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:parity error");
+#endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:parity error\n");
+}
+static void pmif_hw_monitor_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmif_hw_monitor_match");
+#endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmif_hw_monitor_match\n");
+}
+static void pmif_swinf_acc_err_irq_handler(int irq, void *data, u32 val)
+{
+	struct pmif *arb = data;
+	pmif_writel(arb->pmif_base[0], arb, val, MD_AUXADC_RDATA_0_ADDR);
+	pmif_writel(arb->pmif_base[0], arb, (u32)get_current_time_ms(), MD_AUXADC_RDATA_1_ADDR);
+	if (!IS_ERR(arb->pmif_base[1])) {
+		pmif_writel(arb->pmif_base[1], arb, val, MD_AUXADC_RDATA_0_ADDR);
+		pmif_writel(arb->pmif_base[1], arb, (u32)get_current_time_ms(), MD_AUXADC_RDATA_1_ADDR);
+	}
+	dev_notice(&arb->spmic->dev, "[PMIF]:SWINF_ACC_ERR:%d\n", val);
+}
+static irqreturn_t pmif_event_0_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_0);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_0);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIF_ACC_VIO_V3:
+				pmif_acc_vio_irq_handler(irq, data);
+			break;
+			case IRQ_WDT_V4:
+				pmif_wdt_irq_handler(irq, data);
+			break;
+			case IRQ_ALL_PMIC_MPU_VIO_V4:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+			break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_0);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_0);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_1_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_1);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_1);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_1);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_1);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_2_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_2);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_2);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIC_CMD_ERR_PARITY_ERR:
+				pmif_cmd_err_parity_err_irq_handler(irq, data);
+			break;
+			case IRQ_PMIF_ACC_VIO_V2:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+			break;
+			case IRQ_PMIC_ACC_VIO:
+				pmif_pmic_acc_vio_irq_handler(irq, data);
+			break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_2);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_2);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_3_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_3);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_3);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIF_SWINF_ACC_ERR_0:
+			case IRQ_PMIF_SWINF_ACC_ERR_0_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x0);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_1:
+			case IRQ_PMIF_SWINF_ACC_ERR_1_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x1);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_2:
+			case IRQ_PMIF_SWINF_ACC_ERR_2_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x2);
+				break;
+			case IRQ_LAT_LIMIT_REACHED:
+			case IRQ_PMIF_SWINF_ACC_ERR_3_V2:
+				if (arb->data->caps == 1)
+					pmif_lat_limit_reached_irq_handler(irq, data);
+				else
+					pmif_swinf_acc_err_irq_handler(irq, data, 0x3);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_4:
+			case IRQ_PMIF_SWINF_ACC_ERR_4_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x4);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_5:
+			case IRQ_PMIF_SWINF_ACC_ERR_5_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x5);
+				break;
+			case IRQ_HW_MONITOR_V2:
+			case IRQ_HW_MONITOR_V3:
+				pmif_hw_monitor_irq_handler(irq, data);
+				break;
+			case IRQ_WDT_V2:
+			case IRQ_WDT_V3:
+				pmif_wdt_irq_handler(irq, data);
+				break;
+			case IRQ_PMIC_ACC_VIO_V2:
+				pmif_pmic_acc_vio_irq_handler(irq, data);
+				break;
+			case IRQ_ALL_PMIC_MPU_VIO_V2:
+			case IRQ_ALL_PMIC_MPU_VIO_V3:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+				break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n", __func__, idx);
+				break;
+			}
+			if (irq_f) {
+				if ((!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0))) &&
+					(!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0_V2))))
+					pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_3);
+			} else if (irq_f_p) {
+				if ((!(irq_f_p & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0))) &&
+					(!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0_V2))))
+					pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_3);
+			} else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_4_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_4);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_4);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_4);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_4);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static struct pmif_irq_desc pmif_event_irq[] = {
+	PMIF_IRQDESC(event_0),
+	PMIF_IRQDESC(event_1),
+	PMIF_IRQDESC(event_2),
+	PMIF_IRQDESC(event_3),
+	PMIF_IRQDESC(event_4),
+};
+static void pmif_irq_register(struct platform_device *pdev,
+		struct pmif *arb, int irq)
+{
+	int i = 0, ret = 0;
+	u32 irq_event_en[5] = {0};
+	for (i = 0; i < ARRAY_SIZE(pmif_event_irq); i++) {
+		if (!pmif_event_irq[i].name)
+			continue;
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+				pmif_event_irq[i].irq_handler,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_SHARED,
+				pmif_event_irq[i].name, arb);
+		if (ret < 0) {
+			dev_notice(&pdev->dev, "request %s irq fail\n",
+				pmif_event_irq[i].name);
+			continue;
+		}
+		pmif_event_irq[i].irq = irq;
+	}
+	ret = of_property_read_u32_array(pdev->dev.of_node, "irq-event-en",
+		irq_event_en, ARRAY_SIZE(irq_event_en));
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[0] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_0), PMIF_IRQ_EVENT_EN_0);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[1] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_1), PMIF_IRQ_EVENT_EN_1);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[2] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_2), PMIF_IRQ_EVENT_EN_2);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[3] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_3), PMIF_IRQ_EVENT_EN_3);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[4] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_4), PMIF_IRQ_EVENT_EN_4);
+	if (!IS_ERR(arb->pmif_base[1])) {
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[0] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_0), PMIF_IRQ_EVENT_EN_0);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[1] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_1), PMIF_IRQ_EVENT_EN_1);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[2] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_2), PMIF_IRQ_EVENT_EN_2);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[3] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_3), PMIF_IRQ_EVENT_EN_3);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[4] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_4), PMIF_IRQ_EVENT_EN_4);
+	}
+}
+static irqreturn_t rcs_irq_handler(int irq, void *data)
+{
+	struct pmif *arb = data;
+	unsigned int slv_irq_sta, slv_irq_sta_p;
+	int i;
+
+	for (i = 0; i < SPMI_MAX_SLAVE_ID; i++) {
+		slv_irq_sta = mtk_spmi_readl(arb->spmimst_base[0], arb, SPMI_SLV_3_0_EINT + (i / 4));
+		slv_irq_sta = (slv_irq_sta >> ((i % 4) * 8)) & 0xFF;
+		if (!IS_ERR(arb->spmimst_base[1])) {
+			slv_irq_sta_p = mtk_spmi_readl(arb->spmimst_base[1], arb, SPMI_SLV_3_0_EINT + (i / 4));
+			slv_irq_sta_p = (slv_irq_sta_p >> ((i % 4) * 8)) & 0xFF;
+		}
+		if (slv_irq_sta) {
+			mtk_spmi_writel(arb->spmimst_base[0], arb, (0xFF << ((i % 4) * 8)),
+					SPMI_SLV_3_0_EINT + (i / 4));
+			if (arb->rcs_enable_hwirq[i] && slv_irq_sta) {
+				dev_info(&arb->spmic->dev,
+					"hwirq=%d, sta=0x%x\n", i, slv_irq_sta);
+				handle_nested_irq(irq_find_mapping(arb->domain, i));
+			}
+		} else {
+			if (!IS_ERR(arb->spmimst_base[1])) {
+				mtk_spmi_writel(arb->spmimst_base[1], arb, (0xFF << ((i % 4) * 8)),
+					SPMI_SLV_3_0_EINT + (i / 4));
+				if (arb->rcs_enable_hwirq[i] && slv_irq_sta_p) {
+					dev_info(&arb->spmic->dev,
+						"hwirq=%d, sta=0x%x\n", i, slv_irq_sta_p);
+					handle_nested_irq(irq_find_mapping(arb->domain, i));
+				}
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+static int rcs_irq_register(struct platform_device *pdev,
+			    struct pmif *arb, int irq)
+{
+	int i, ret = 0;
+	mutex_init(&arb->rcs_m_irqlock);
+	mutex_init(&arb->rcs_p_irqlock);
+	arb->rcs_enable_hwirq = devm_kcalloc(&pdev->dev, SPMI_MAX_SLAVE_ID,
+					     sizeof(*arb->rcs_enable_hwirq),
+					     GFP_KERNEL);
+	if (!arb->rcs_enable_hwirq)
+		return -ENOMEM;
+	if (arb->rcs_irq == irq)
+		arb->irq_chip = rcs_irq_chip;
+	else if (arb->rcs_irq_p == irq)
+		arb->irq_chip_p = rcs_irq_chip_p;
+	else
+		dev_notice(&pdev->dev, "no rcs irq %d registered\n", irq);
+	arb->domain = irq_domain_add_linear(pdev->dev.of_node,
+					    SPMI_MAX_SLAVE_ID,
+					    &rcs_irq_domain_ops, arb);
+	if (!arb->domain) {
+		dev_notice(&pdev->dev, "Failed to create IRQ domain\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < SPMI_MAX_SLAVE_ID; i++) {
+		mtk_spmi_writel(arb->spmimst_base[0], arb, (0xFF << ((i % 4) * 8)),
+				SPMI_SLV_3_0_EINT + (i / 4));
+		if (!IS_ERR(arb->spmimst_base[1])) {
+			mtk_spmi_writel(arb->spmimst_base[1], arb, (0xFF << ((i % 4) * 8)),
+				SPMI_SLV_3_0_EINT + (i / 4));
+		}
+	}
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					rcs_irq_handler, IRQF_ONESHOT,
+					rcs_irq_chip.name, arb);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "Failed to request IRQ=%d, ret = %d\n",
+			   irq, ret);
+		return ret;
+	}
+	enable_irq_wake(irq);
+	return ret;
+}
 static int mtk_spmi_probe(struct platform_device *pdev)
 {
 	struct pmif *arb;
@@ -457,41 +1293,50 @@ static int mtk_spmi_probe(struct platform_device *pdev)
 	if (IS_ERR(ctrl))
 		return PTR_ERR(ctrl);
 
+	ctrl->cmd = pmif_arb_cmd;
+	ctrl->read_cmd = pmif_spmi_read_cmd;
+	ctrl->write_cmd = pmif_spmi_write_cmd;
 	arb = spmi_controller_get_drvdata(ctrl);
+	arb->spmic = ctrl;
 	arb->data = device_get_match_data(&pdev->dev);
 	if (!arb->data) {
 		dev_err(&pdev->dev, "Cannot get drv_data\n");
 		return -EINVAL;
 	}
 
-	arb->base = devm_platform_ioremap_resource_byname(pdev, "pmif");
-	if (IS_ERR(arb->base))
-		return PTR_ERR(arb->base);
-
-	arb->spmimst_base = devm_platform_ioremap_resource_byname(pdev, "spmimst");
-	if (IS_ERR(arb->spmimst_base))
-		return PTR_ERR(arb->spmimst_base);
-
-	arb->nclks = ARRAY_SIZE(pmif_clock_names);
-	for (i = 0; i < arb->nclks; i++)
-		arb->clks[i].id = pmif_clock_names[i];
-
-	err = clk_bulk_get(&pdev->dev, arb->nclks, arb->clks);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to get clocks: %d\n", err);
-		return err;
-	}
-
-	err = clk_bulk_prepare_enable(arb->nclks, arb->clks);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to enable clocks: %d\n", err);
-		goto err_put_clks;
+	arb->pmif_base[0] = devm_platform_ioremap_resource_byname(pdev, "pmif");
+	if (IS_ERR(arb->pmif_base[0]))
+		return PTR_ERR(arb->pmif_base[0]);
+
+	arb->spmimst_base[0] = devm_platform_ioremap_resource_byname(pdev, "spmimst");
+	if (IS_ERR(arb->spmimst_base[0]))
+		return PTR_ERR(arb->spmimst_base[0]);
+
+	arb->pmif_base[1] = devm_platform_ioremap_resource_byname(pdev, "pmif-p");
+	if (IS_ERR(arb->pmif_base[1]))
+		dev_notice(&pdev->dev, "[PMIF]:no pmif-p found\n");
+	arb->spmimst_base[1] = devm_platform_ioremap_resource_byname(pdev, "spmimst-p");
+	if (IS_ERR(arb->spmimst_base[1]))
+		dev_notice(&pdev->dev, "[PMIF]:no spmimst-p found\n");
+		if (arb->data->caps == 1) {
+
+		arb->nclks = ARRAY_SIZE(pmif_clock_names);
+		for (i = 0; i < arb->nclks; i++)
+			arb->clks[i].id = pmif_clock_names[i];
+
+		err = clk_bulk_get(&pdev->dev, arb->nclks, arb->clks);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to get clocks: %d\n", err);
+			return err;
+		}
+
+		err = clk_bulk_prepare_enable(arb->nclks, arb->clks);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to enable clocks: %d\n", err);
+			goto err_put_clks;
+		}
 	}
 
-	ctrl->cmd = pmif_arb_cmd;
-	ctrl->read_cmd = pmif_spmi_read_cmd;
-	ctrl->write_cmd = pmif_spmi_write_cmd;
-
 	chan_offset = PMIF_CHAN_OFFSET * arb->data->soc_chan;
 	arb->chan.ch_sta = PMIF_SWINF_0_STA + chan_offset;
 	arb->chan.wdata = PMIF_SWINF_0_WDATA_31_0 + chan_offset;
@@ -499,7 +1344,71 @@ static int mtk_spmi_probe(struct platform_device *pdev)
 	arb->chan.ch_send = PMIF_SWINF_0_ACC + chan_offset;
 	arb->chan.ch_rdy = PMIF_SWINF_0_VLD_CLR + chan_offset;
 
-	raw_spin_lock_init(&arb->lock);
+	raw_spin_lock_init(&arb->lock_m);
+	raw_spin_lock_init(&arb->lock_p);
+	arb->pmif_m_Thread_lock =
+		wakeup_source_register(NULL, "pmif_m wakelock");
+	arb->pmif_p_Thread_lock =
+		wakeup_source_register(NULL, "pmif_p wakelock");
+	mutex_init(&arb->pmif_m_mutex);
+	mutex_init(&arb->pmif_p_mutex);
+	if (arb->data->caps == 2) {
+		arb->irq = platform_get_irq_byname(pdev, "pmif_irq");
+		if (arb->irq < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get pmif_irq, ret = %d\n", arb->irq);
+		}
+		pmif_irq_register(pdev, arb, arb->irq);
+		arb->irq_p = platform_get_irq_byname(pdev, "pmif_p_irq");
+		if (arb->irq_p < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get pmif_p_irq, ret = %d\n", arb->irq_p);
+		}
+		pmif_irq_register(pdev, arb, arb->irq_p);
+		arb->rcs_irq = platform_get_irq_byname(pdev, "rcs_irq");
+		if (arb->rcs_irq < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get rcs_irq, ret = %d\n", arb->rcs_irq);
+		} else {
+			err = rcs_irq_register(pdev, arb, arb->rcs_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+				   "Failed to register rcs_irq, ret = %d\n", arb->rcs_irq);
+		}
+		arb->rcs_irq_p = platform_get_irq_byname(pdev, "rcs_irq_p");
+		if (arb->rcs_irq_p < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get rcs_irq_p, ret = %d\n", arb->rcs_irq_p);
+		} else {
+			err = rcs_irq_register(pdev, arb, arb->rcs_irq_p);
+			if (err)
+				dev_notice(&pdev->dev,
+				   "Failed to register rcs_irq_p, ret = %d\n", arb->rcs_irq_p);
+		}
+		arb->spmi_nack_irq = platform_get_irq_byname(pdev, "spmi_nack_irq");
+		if (arb->spmi_nack_irq < 0) {
+			dev_notice(&pdev->dev,
+				"Failed to get spmi_nack_irq, ret = %d\n", arb->spmi_nack_irq);
+		} else {
+			err = spmi_nack_irq_register(pdev, arb, arb->spmi_nack_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+					"Failed to register spmi_nack_irq, ret = %d\n",
+						 arb->spmi_nack_irq);
+		}
+		arb->spmi_p_nack_irq = platform_get_irq_byname(pdev, "spmi_p_nack_irq");
+		if (arb->spmi_p_nack_irq < 0) {
+			dev_notice(&pdev->dev,
+				"Failed to get spmi_p_nack_irq, ret = %d\n", arb->spmi_p_nack_irq);
+		} else {
+			err = spmi_nack_irq_register(pdev, arb, arb->spmi_p_nack_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+					"Failed to register spmi_p_nack_irq, ret = %d\n",
+						 arb->spmi_p_nack_irq);
+		}
+	}
+	spmi_dev_parse(pdev);
 
 	platform_set_drvdata(pdev, ctrl);
 
@@ -533,6 +1442,9 @@ static const struct of_device_id mtk_spmi_match_table[] = {
 	}, {
 		.compatible = "mediatek,mt8195-spmi",
 		.data = &mt8195_pmif_arb,
+	}, {
+		.compatible = "mediatek,mt8196-spmi",
+		.data = &mt6xxx_pmif_arb,
 	}, {
 		/* sentinel */
 	},
-- 
2.46.0



From Lu.Tang at mediatek.com  Fri Mar 14 00:32:29 2025
From: Lu.Tang at mediatek.com (Lu.Tang)
Date: Fri, 14 Mar 2025 15:32:29 +0800
Subject: [PATCH 3/5] pmic: mediatek: Add spmi pmic mfd driver
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <20250314073307.25092-4-Lu.Tang@mediatek.com>

From: "Lu.Tang" <lu.tang at mediatek.com>

Add spmi pmic mfd driver for mt8196

Signed-off-by: Lu Tang <lu.tang at mediatek.com>
---
 drivers/mfd/Kconfig                  |  26 ++
 drivers/mfd/Makefile                 |   2 +
 drivers/mfd/mt6685-core.c            |  83 +++++
 drivers/mfd/mtk-spmi-pmic.c          | 518 +++++++++++++++++++++++++++
 include/linux/mfd/mt6363/core.h      | 134 +++++++
 include/linux/mfd/mt6363/registers.h | 168 +++++++++
 include/linux/mfd/mt6373/core.h      |  94 +++++
 include/linux/mfd/mt6373/registers.h |  53 +++
 8 files changed, 1078 insertions(+)
 create mode 100644 drivers/mfd/mt6685-core.c
 create mode 100644 drivers/mfd/mtk-spmi-pmic.c
 create mode 100644 include/linux/mfd/mt6363/core.h
 create mode 100644 include/linux/mfd/mt6363/registers.h
 create mode 100644 include/linux/mfd/mt6373/core.h
 create mode 100644 include/linux/mfd/mt6373/registers.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d44c69bb3dfd..a62625566893 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1030,6 +1030,32 @@ config MFD_MT6397
 	  accessing the device; additional drivers must be enabled in order
 	  to use the functionality of the device.
 
+config MFD_MT6685
+	tristate "MT6685 SPMI PMIC"
+	depends on OF
+	depends on SPMI
+	select REGMAP_SPMI
+	select REGMAP_IRQ
+	help
+	  This enables support for the Mediatek SPMI PMICs.
+	  These PMICs are currently used with the Mediatek series of
+	  SoCs.  Note, that this will only be useful paired with descriptions
+	  of the independent functions as children nodes in the device tree.
+
+config MFD_MTK_SPMI_PMIC
+	tristate "Mediatek SPMI PMICs"
+	depends on OF
+	depends on SPMI
+	select REGMAP_SPMI
+	help
+	  This enables support for the Mediatek SPMI PMICs.
+	  These PMICs are currently used with the MT63xx series of
+	  SoCs.  Note, that this will only be useful paired with descriptions
+	  of the independent functions as children nodes in the device tree.
+
+	  Say M here if you want to include support for the SPMI PMIC
+	  series as a module.  The module will be called "mtk-spmi-pmic".
+
 config MFD_MENF21BMC
 	tristate "MEN 14F021P00 Board Management Controller Support"
 	depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9220eaf7cf12..b8cb34284e56 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -182,6 +182,8 @@ obj-$(CONFIG_MFD_MT6360)	+= mt6360-core.o
 obj-$(CONFIG_MFD_MT6370)	+= mt6370.o
 mt6397-objs			:= mt6397-core.o mt6397-irq.o mt6358-irq.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397.o
+obj-$(CONFIG_MFD_MT6685)	+= mt6685-core.o
+obj-$(CONFIG_MFD_MTK_SPMI_PMIC)	+= mtk-spmi-pmic.o
 
 pcf50633-objs			:= pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633.o
diff --git a/drivers/mfd/mt6685-core.c b/drivers/mfd/mt6685-core.c
new file mode 100644
index 000000000000..c71008184666
--- /dev/null
+++ b/drivers/mfd/mt6685-core.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+
+static const struct mfd_cell mt6685_devs[] = {
+	{
+		.name = "mt6685-clkbuf",
+		.of_compatible = "mediatek,mt6685-clkbuf",
+	}, {
+		.name = "mt6685-tb-clkbuf",
+		.of_compatible = "mediatek,mt6685-tb-clkbuf",
+	}, {
+		.name = "mt6685-rtc",
+		.of_compatible = "mediatek,mt6685-rtc",
+	}, {
+		.name = "mt6685-audclk",
+		.of_compatible = "mediatek,mt6685-audclk",
+	}, {
+		.name = "mt6685-consys",
+		.of_compatible = "mediatek,mt6685-consys",
+	}, {
+		.name = "mt6685-gps",
+		.of_compatible = "mediatek,mt6685-gps",
+	}
+};
+
+static const struct regmap_config spmi_regmap_config = {
+	.reg_bits	= 16,
+	.val_bits	= 8,
+	.max_register	= 0x2000,
+	.fast_io	= true,
+	.use_single_read = true,
+	.use_single_write = true
+};
+
+static int mt6685_spmi_probe(struct spmi_device *sdev)
+{
+	int ret;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&sdev->dev, "Failed to init mt6685 regmap: %ld\n", PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	ret = devm_mfd_add_devices(&sdev->dev, -1, mt6685_devs,
+				   ARRAY_SIZE(mt6685_devs), NULL, 0, NULL);
+	if (ret) {
+		dev_err(&sdev->dev, "Failed to add child devices: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id mt6685_id_table[] = {
+	{ .compatible = "mediatek,mt6685", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt6685_id_table);
+
+static struct spmi_driver mt6685_spmi_driver = {
+	.probe = mt6685_spmi_probe,
+	.driver = {
+		.name = "mt6685",
+		.of_match_table = mt6685_id_table,
+	},
+};
+module_spmi_driver(mt6685_spmi_driver);
+
+MODULE_DESCRIPTION("Mediatek SPMI MT6685 Clock IC driver");
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mtk-spmi-pmic.c b/drivers/mfd/mtk-spmi-pmic.c
new file mode 100644
index 000000000000..4c4bed5e991a
--- /dev/null
+++ b/drivers/mfd/mtk-spmi-pmic.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/mt6363/core.h>
+#include <linux/mfd/mt6363/registers.h>
+#include <linux/mfd/mt6373/core.h>
+#include <linux/mfd/mt6373/registers.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+
+#define MTK_SPMI_PMIC_REG_WIDTH	8
+#define PMIC_SWCID		0xB
+#define PMIC_MT6316_SWCID	0x20B
+#define RCS_INT_DONE		0x41B
+
+struct irq_top_t {
+	int hwirq_base;
+	unsigned int num_int_regs;
+	unsigned int en_reg;
+	unsigned int en_reg_shift;
+	unsigned int sta_reg;
+	unsigned int sta_reg_shift;
+	unsigned int top_offset;
+};
+
+struct mtk_spmi_pmic_data {
+	const struct mfd_cell *cells;
+	int cell_size;
+	unsigned int num_top;
+	unsigned int num_pmic_irqs;
+	unsigned short top_int_status_reg;
+	struct irq_top_t *pmic_ints;
+	unsigned int cid_addr;
+};
+
+struct pmic_core {
+	struct device *dev;
+	struct spmi_device *sdev;
+	struct regmap *regmap;
+	u16 chip_id;
+	int irq;
+	bool *enable_hwirq;
+	bool *cache_hwirq;
+	struct mutex irqlock;
+	struct irq_domain *irq_domain;
+	const struct mtk_spmi_pmic_data *chip_data;
+};
+
+static const struct resource mt6363_regulators_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VCN15_OC, "VCN15"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VCN13_OC, "VCN13"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF09_OC, "VRF09"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF12_OC, "VRF12"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF13_OC, "VRF13"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF18_OC, "VRF18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRFIO18_OC, "VRFIO18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VSRAM_MDFE_OC, "VSRAM_MDFE"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VTREF18_OC, "VTREF18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VSRAM_APU_OC, "VSRAM_APU"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VAUX18_OC, "VAUX18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VEMC_OC, "VEMC"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VUFS12_OC, "VUFS12"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VUFS18_OC, "VUFS18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VIO18_OC, "VIO18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VIO075_OC, "VIO075"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA12_1_OC, "VA12_1"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA12_2_OC, "VA12_2"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA15_OC, "VA15"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VM18_OC, "VM18"),
+};
+
+static const struct resource mt6363_keys_resources[] = {
+	DEFINE_RES_IRQ(MT6363_IRQ_PWRKEY),
+	DEFINE_RES_IRQ(MT6363_IRQ_HOMEKEY),
+	DEFINE_RES_IRQ(MT6363_IRQ_PWRKEY_R),
+	DEFINE_RES_IRQ(MT6363_IRQ_HOMEKEY_R),
+};
+
+static const struct resource mt6363_lvsys_notify_resources[] = {
+	/* MT6363 LVSYS interrupt name is contrary,
+	 * we name LVSYS_R to MT6363_IRQ_NI_LVSYS_INT_FALLING;
+	 * LVSYS_F to MT6363_IRQ_NI_LVSYS_INT_RISING
+	 */
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_NI_LVSYS_INT_FALLING, "LVSYS_R"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_NI_LVSYS_INT_RISING, "LVSYS_F"),
+};
+
+static const struct resource mt6373_regulators_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VUSB_OC, "VUSB"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VAUX18_OC, "VAUX18"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF13_AIF_OC, "VRF13_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF18_AIF_OC, "VRF18_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRFIO18_AIF_OC, "VRFIO18_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_1_OC, "VCN33_1"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_2_OC, "VCN33_2"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_3_OC, "VCN33_3"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN18IO_OC, "VCN18IO"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF09_AIF_OC, "VRF09_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF12_AIF_OC, "VRF12_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VANT18_OC, "VANT18"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VSRAM_DIGRF_AIF_OC, "VSRAM_DIGRF_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VEFUSE_OC, "VEFUSE"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VMCH_OC, "VMCH"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VMC_OC, "VMC"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VIBR_OC, "VIBR"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VIO28_OC, "VIO28"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VFP_OC, "VFP"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VTP_OC, "VTP"),
+};
+
+static const struct mfd_cell mt6363_devs[] = {
+	{
+		.name = "mt6363-auxadc",
+		.of_compatible = "mediatek,mt6363-auxadc",
+	}, {
+		.name = "mtk-dynamic-loading-throttling",
+		.of_compatible = "mediatek,mt6363-dynamic_loading_throttling",
+	}, {
+		.name = "mt6363-efuse",
+		.of_compatible = "mediatek,mt6363-efuse",
+	}, {
+		.name = "mt6363-regulator",
+		.num_resources = ARRAY_SIZE(mt6363_regulators_resources),
+		.resources = mt6363_regulators_resources,
+		.of_compatible = "mediatek,mt6363-regulator",
+	}, {
+		.name = "mtk-pmic-keys",
+		.num_resources = ARRAY_SIZE(mt6363_keys_resources),
+		.resources = mt6363_keys_resources,
+		.of_compatible = "mediatek,mt6363-keys"
+	}, {
+		.name = "mt6363-consys",
+		.of_compatible = "mediatek,mt6363-consys",
+	}, {
+		.name = "mt6363-lvsys-notify",
+		.num_resources = ARRAY_SIZE(mt6363_lvsys_notify_resources),
+		.resources = mt6363_lvsys_notify_resources,
+		.of_compatible = "mediatek,mt6363-lvsys-notify",
+	}, {
+		.name = "mt6363-pinctrl",
+		.of_compatible = "mediatek,mt6363-pinctrl",
+	},
+};
+
+static const struct mfd_cell mt6373_devs[] = {
+	{
+		.name = "mt6373-regulator",
+		.num_resources = ARRAY_SIZE(mt6373_regulators_resources),
+		.resources = mt6373_regulators_resources,
+		.of_compatible = "mediatek,mt6373-regulator",
+	}, {
+		.name = "mt6373-auxadc",
+		.of_compatible = "mediatek,mt6373-auxadc",
+	}, {
+		.name = "mt6373-efuse",
+		.of_compatible = "mediatek,mt6373-efuse",
+	}, {
+		.name = "mt6373-consys",
+		.of_compatible = "mediatek,mt6373-consys",
+	}, {
+		.name = "mt6373-pinctrl",
+		.of_compatible = "mediatek,mt6373-pinctrl",
+	},
+};
+
+static struct irq_top_t mt6363_ints[] = {
+	MT6363_TOP_GEN(BUCK),
+	MT6363_TOP_GEN(LDO),
+	MT6363_TOP_GEN(PSC),
+	MT6363_TOP_GEN(MISC),
+	MT6363_TOP_GEN(HK),
+	MT6363_TOP_GEN(BM),
+};
+
+
+static struct irq_top_t mt6373_ints[] = {
+	MT6373_TOP_GEN(BUCK),
+	MT6373_TOP_GEN(LDO),
+	MT6373_TOP_GEN(MISC),
+};
+
+static const struct mtk_spmi_pmic_data mt6316_data = {
+	.num_pmic_irqs = 0,
+	.cid_addr = PMIC_MT6316_SWCID,
+};
+
+static const struct mtk_spmi_pmic_data mt6363_data = {
+	.cells = mt6363_devs,
+	.cell_size = ARRAY_SIZE(mt6363_devs),
+	.num_top = ARRAY_SIZE(mt6363_ints),
+	.num_pmic_irqs = MT6363_IRQ_NR,
+	.top_int_status_reg = MT6363_TOP_INT_STATUS1,
+	.pmic_ints = mt6363_ints,
+};
+
+static const struct mtk_spmi_pmic_data mt6373_data = {
+	.cells = mt6373_devs,
+	.cell_size = ARRAY_SIZE(mt6373_devs),
+	.num_top = ARRAY_SIZE(mt6373_ints),
+	.num_pmic_irqs = MT6373_IRQ_NR,
+	.top_int_status_reg = MT6373_TOP_INT_STATUS1,
+	.pmic_ints = mt6373_ints,
+};
+
+static void mtk_spmi_pmic_irq_enable(struct irq_data *data)
+{
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	core->enable_hwirq[hwirq] = true;
+}
+
+static void mtk_spmi_pmic_irq_disable(struct irq_data *data)
+{
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	core->enable_hwirq[hwirq] = false;
+}
+
+static void mtk_spmi_pmic_irq_lock(struct irq_data *data)
+{
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&core->irqlock);
+}
+
+static void mtk_spmi_pmic_irq_sync_unlock(struct irq_data *data)
+{
+	unsigned int i, top_gp, gp_offset, en_reg, int_regs, shift;
+	struct irq_top_t *pmic_int;
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	for (i = 0; i < chip_data->num_pmic_irqs; i++) {
+		if (core->enable_hwirq[i] == core->cache_hwirq[i])
+			continue;
+
+		/* Find out the IRQ group */
+		top_gp = 0;
+		while ((top_gp + 1) < chip_data->num_top &&
+			i >= chip_data->pmic_ints[top_gp + 1].hwirq_base)
+			top_gp++;
+
+		pmic_int = &(chip_data->pmic_ints[top_gp]);
+		/* Find the IRQ registers */
+		gp_offset = i - pmic_int->hwirq_base;
+		int_regs = gp_offset / MTK_SPMI_PMIC_REG_WIDTH;
+		shift = gp_offset % MTK_SPMI_PMIC_REG_WIDTH;
+		en_reg = pmic_int->en_reg + (pmic_int->en_reg_shift * int_regs);
+
+		regmap_update_bits(core->regmap, en_reg, BIT(shift),
+				   core->enable_hwirq[i] << shift);
+		core->cache_hwirq[i] = core->enable_hwirq[i];
+	}
+	mutex_unlock(&core->irqlock);
+}
+
+static struct irq_chip mtk_spmi_pmic_irq_chip = {
+	.name = "spmi-pmic-irq",
+	.flags = IRQCHIP_SKIP_SET_WAKE,
+	.irq_enable = mtk_spmi_pmic_irq_enable,
+	.irq_disable = mtk_spmi_pmic_irq_disable,
+	.irq_bus_lock = mtk_spmi_pmic_irq_lock,
+	.irq_bus_sync_unlock = mtk_spmi_pmic_irq_sync_unlock,
+};
+
+static void mtk_spmi_pmic_irq_sp_handler(struct pmic_core *core,
+					 unsigned int top_gp)
+{
+	unsigned int irq_status = 0, sta_reg, status;
+	unsigned int hwirq, virq;
+	int ret, i, j;
+	struct irq_top_t *pmic_int;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	for (i = 0; i < chip_data->pmic_ints[top_gp].num_int_regs; i++) {
+		pmic_int = &(chip_data->pmic_ints[top_gp]);
+		sta_reg = pmic_int->sta_reg + (pmic_int->sta_reg_shift * i);
+
+		ret = regmap_read(core->regmap, sta_reg, &irq_status);
+		if (ret) {
+			dev_err(core->dev,
+				"Failed to read irq status: %d\n", ret);
+			return;
+		}
+
+		if (!irq_status)
+			continue;
+
+		status = irq_status;
+		do {
+			j = __ffs(status);
+
+			hwirq = pmic_int->hwirq_base + MTK_SPMI_PMIC_REG_WIDTH * i + j;
+
+			virq = irq_find_mapping(core->irq_domain, hwirq);
+			dev_info(core->dev, "[%x]Reg[0x%x]=0x%x,hwirq=%d\n",
+				 core->chip_id, sta_reg, irq_status, hwirq);
+			if (virq)
+				handle_nested_irq(virq);
+
+			status &= ~BIT(j);
+		} while (status);
+
+		regmap_write(core->regmap, sta_reg, irq_status);
+	}
+}
+
+static irqreturn_t mtk_spmi_pmic_irq_handler(int irq, void *data)
+{
+	int ret;
+	unsigned int bit, i, top_irq_status = 0;
+	struct pmic_core *core = data;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	ret = regmap_read(core->regmap, chip_data->top_int_status_reg,
+			  &top_irq_status);
+	if (ret) {
+		dev_err(core->dev,
+			"Failed to read status from the device, ret=%d\n", ret);
+		return IRQ_NONE;
+	}
+
+	dev_info(core->dev, "top_irq_sts:0x%x\n", top_irq_status);
+	for (i = 0; i < chip_data->num_top; i++) {
+		bit = BIT(chip_data->pmic_ints[i].top_offset);
+		if (top_irq_status & bit)
+			mtk_spmi_pmic_irq_sp_handler(core, i);
+	}
+
+	ret = regmap_write(core->regmap, RCS_INT_DONE, 1);
+	if (ret) {
+		dev_err(core->dev,
+			"Failed to clear RCS flag, ret=%d\n", ret);
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_spmi_pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+					irq_hw_number_t hw)
+{
+	struct pmic_core *core = d->host_data;
+
+	irq_set_chip_data(irq, core);
+	irq_set_chip_and_handler(irq, &mtk_spmi_pmic_irq_chip,
+				 handle_level_irq);
+	irq_set_nested_thread(irq, 1);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pmic_irq_domain_ops = {
+	.map = mtk_spmi_pmic_irq_domain_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int mtk_spmi_pmic_irq_init(struct pmic_core *core)
+{
+	int i, j, ret;
+	unsigned int en_reg, sta_reg;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	mutex_init(&core->irqlock);
+	core->enable_hwirq = devm_kcalloc(core->dev,
+					  chip_data->num_pmic_irqs,
+					  sizeof(bool), GFP_KERNEL);
+	if (!core->enable_hwirq)
+		return -ENOMEM;
+
+	core->cache_hwirq = devm_kcalloc(core->dev,
+					 chip_data->num_pmic_irqs,
+					 sizeof(bool), GFP_KERNEL);
+	if (!core->cache_hwirq)
+		return -ENOMEM;
+
+	/* Disable all interrupt for initializing */
+	for (i = 0; i < chip_data->num_top; i++) {
+		for (j = 0; j < chip_data->pmic_ints[i].num_int_regs; j++) {
+			en_reg = chip_data->pmic_ints[i].en_reg +
+				chip_data->pmic_ints[i].en_reg_shift * j;
+			regmap_write(core->regmap, en_reg, 0);
+			sta_reg = chip_data->pmic_ints[i].sta_reg +
+				chip_data->pmic_ints[i].sta_reg_shift * j;
+			regmap_write(core->regmap, sta_reg, 0xFF);
+		}
+	}
+	regmap_write(core->regmap, RCS_INT_DONE, 1);
+
+	core->irq_domain = irq_domain_add_linear(core->dev->of_node,
+						 chip_data->num_pmic_irqs,
+						 &pmic_irq_domain_ops,
+						 core);
+	if (!core->irq_domain) {
+		dev_err(core->dev, "Could not create IRQ domain\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_threaded_irq(core->dev, core->irq, NULL,
+					mtk_spmi_pmic_irq_handler, IRQF_ONESHOT,
+					mtk_spmi_pmic_irq_chip.name, core);
+	if (ret) {
+		dev_err(core->dev, "Failed to register IRQ=%d, ret=%d\n",
+			core->irq, ret);
+		return ret;
+	}
+
+	enable_irq_wake(core->irq);
+	return ret;
+}
+
+static const struct regmap_config spmi_regmap_config = {
+	.reg_bits	= 16,
+	.val_bits	= 8,
+	.max_register	= 0xffff,
+	.fast_io	= true,
+};
+
+static int mtk_spmi_pmic_probe(struct spmi_device *sdev)
+{
+	int ret;
+	unsigned int id;
+	struct device_node *np = sdev->dev.of_node;
+	struct pmic_core *core;
+	const struct mtk_spmi_pmic_data *chip_data;
+
+	core = devm_kzalloc(&sdev->dev, sizeof(*core), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	core->sdev = sdev;
+	core->dev = &sdev->dev;
+	chip_data = (struct mtk_spmi_pmic_data *)of_device_get_match_data(&sdev->dev);
+	if (!chip_data)
+		return -ENODEV;
+
+	core->chip_data = chip_data;
+	core->regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config);
+	if (IS_ERR(core->regmap))
+		return PTR_ERR(core->regmap);
+	if (chip_data->cid_addr)
+		ret = regmap_read(core->regmap, chip_data->cid_addr, &id);
+	else
+		ret = regmap_read(core->regmap, PMIC_SWCID, &id);
+	if (ret || id == 0) {
+		dev_err(&sdev->dev, "Failed to read chip id: %d\n", ret);
+		return ret;
+	}
+
+	core->chip_id = id;
+
+	if (chip_data->num_pmic_irqs) {
+		core->irq = of_irq_get(np, 0);
+		if (core->irq < 0)
+			dev_err(&sdev->dev, "Failed to get irq(%d)\n", core->irq);
+
+		ret = mtk_spmi_pmic_irq_init(core);
+		if (ret)
+			dev_err(&sdev->dev, "IRQ_init failed(%d)\n", core->irq);
+
+		ret = devm_mfd_add_devices(&sdev->dev, -1, chip_data->cells,
+					   chip_data->cell_size, NULL, 0,
+					   core->irq_domain);
+		if (ret) {
+			irq_domain_remove(core->irq_domain);
+			dev_err(&sdev->dev, "Failed to add mfd devices: %d\n", ret);
+			return ret;
+		}
+	} else {
+		ret = devm_of_platform_populate(&sdev->dev);
+		if (ret) {
+			dev_err(&sdev->dev, "Failed to platform populate: %d\n", ret);
+			return ret;
+		}
+	}
+
+	device_init_wakeup(&sdev->dev, true);
+
+	dev_dbg(&sdev->dev, "probe chip id=0x%x done\n", core->chip_id);
+
+	return ret;
+}
+
+static const struct of_device_id mtk_spmi_pmic_of_match[] = {
+	{ .compatible = "mediatek,mt6316", .data = &mt6316_data, },
+	{ .compatible = "mediatek,mt6363", .data = &mt6363_data, },
+	{ .compatible = "mediatek,mt6373", .data = &mt6373_data, },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mtk_spmi_pmic_of_match);
+
+static struct spmi_driver mtk_spmi_pmic_driver = {
+	.driver = {
+		.name = "mtk-spmi-pmic",
+		.of_match_table = of_match_ptr(mtk_spmi_pmic_of_match),
+	},
+	.probe = mtk_spmi_pmic_probe,
+};
+module_spmi_driver(mtk_spmi_pmic_driver);
+
+MODULE_DESCRIPTION("Mediatek SPMI PMIC driver");
+MODULE_ALIAS("spmi:spmi-pmic");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Argus Lin <argus.lin at mediatek.com>");
+MODULE_AUTHOR("Jeter Chen <jeter.chen at mediatek.com>");
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>");
diff --git a/include/linux/mfd/mt6363/core.h b/include/linux/mfd/mt6363/core.h
new file mode 100644
index 000000000000..3243a52da34d
--- /dev/null
+++ b/include/linux/mfd/mt6363/core.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6363_CORE_H__
+#define __MFD_MT6363_CORE_H__
+
+#define MT6363_REG_WIDTH 8
+
+enum mt6363_irq_top_status_shift {
+	MT6363_BUCK_TOP = 0,
+	MT6363_LDO_TOP,
+	MT6363_PSC_TOP,
+	MT6363_MISC_TOP,
+	MT6363_HK_TOP,
+	MT6363_SCK_TOP,
+	MT6363_BM_TOP,
+	MT6363_AUD_TOP,
+};
+
+enum mt6363_irq_numbers {
+	MT6363_IRQ_VS2_OC = 0,
+	MT6363_IRQ_VBUCK1_OC,
+	MT6363_IRQ_VBUCK2_OC,
+	MT6363_IRQ_VBUCK3_OC,
+	MT6363_IRQ_VBUCK4_OC,
+	MT6363_IRQ_VBUCK5_OC,
+	MT6363_IRQ_VBUCK6_OC,
+	MT6363_IRQ_VBUCK7_OC,
+	MT6363_IRQ_VS1_OC,
+	MT6363_IRQ_VS3_OC,
+	MT6363_IRQ_VCN15_OC = 16,
+	MT6363_IRQ_VCN13_OC,
+	MT6363_IRQ_VRF09_OC,
+	MT6363_IRQ_VRF12_OC,
+	MT6363_IRQ_VRF13_OC,
+	MT6363_IRQ_VRF18_OC,
+	MT6363_IRQ_VRFIO18_OC,
+	MT6363_IRQ_VSRAM_DIGRF_OC,
+	MT6363_IRQ_VSRAM_MDFE_OC,
+	MT6363_IRQ_VSRAM_MODEM_OC,
+	MT6363_IRQ_VTREF18_OC,
+	MT6363_IRQ_VSRAM_CPUB_OC,
+	MT6363_IRQ_VSRAM_CPUM_OC,
+	MT6363_IRQ_VSRAM_CPUL_OC,
+	MT6363_IRQ_VSRAM_APU_OC,
+	MT6363_IRQ_VAUX18_OC,
+	MT6363_IRQ_VEMC_OC,
+	MT6363_IRQ_VUFS12_OC,
+	MT6363_IRQ_VUFS18_OC,
+	MT6363_IRQ_VIO18_OC,
+	MT6363_IRQ_VIO075_OC,
+	MT6363_IRQ_VA12_1_OC,
+	MT6363_IRQ_VA12_2_OC,
+	MT6363_IRQ_VA15_OC,
+	MT6363_IRQ_VM18_OC,
+	MT6363_IRQ_PWRKEY = 48,
+	MT6363_IRQ_HOMEKEY,
+	MT6363_IRQ_HOMEKEY_2,
+	MT6363_IRQ_PWRKEY_R,
+	MT6363_IRQ_HOMEKEY_R,
+	MT6363_IRQ_HOMEKEY_2_R,
+	MT6363_IRQ_NI_LVSYS_INT_FALLING,
+	MT6363_IRQ_NI_LVSYS_INT_RISING,
+	MT6363_IRQ_CHRDET_LEVEL,
+	MT6363_IRQ_CHRDET_EDGE,
+	MT6363_IRQ_RCS0 = 64,
+	MT6363_IRQ_SPMI_CMD_ALERT,
+	MT6363_IRQ_BM_PROTREG = 70,
+	MT6363_IRQ_BUCK_PROTREG = 72,
+	MT6363_IRQ_LDO_PROTREG,
+	MT6363_IRQ_PSC_PROTREG,
+	MT6363_IRQ_PLT_PROTREG,
+	MT6363_IRQ_HK_PROTREG,
+	MT6363_IRQ_TOP_PROTREG = 79,
+	MT6363_IRQ_BAT_H,
+	MT6363_IRQ_BAT_L,
+	MT6363_IRQ_BAT2_H,
+	MT6363_IRQ_BAT2_L,
+	MT6363_IRQ_BAT_TEMP_H,
+	MT6363_IRQ_BAT_TEMP_L,
+	MT6363_IRQ_THR_H,
+	MT6363_IRQ_THR_L,
+	MT6363_IRQ_AUXADC_IMP,
+	MT6363_IRQ_NAG_C_DLTV,
+	MT6363_IRQ_FG_BAT_H = 88,
+	MT6363_IRQ_FG_BAT_L,
+	MT6363_IRQ_FG_CUR_H,
+	MT6363_IRQ_FG_CUR_L,
+	MT6363_IRQ_FG_ZCV,
+	MT6363_IRQ_FG_N_CHARGE_L = 95,
+	MT6363_IRQ_FG_IAVG_H,
+	MT6363_IRQ_FG_IAVG_L,
+	MT6363_IRQ_FG_DISCHARGE = 99,
+	MT6363_IRQ_FG_CHARGE,
+	MT6363_IRQ_BATON_LV = 104,
+	MT6363_IRQ_BATON_BAT_IN = 106,
+	MT6363_IRQ_BATON_BAT_OUT,
+	MT6363_IRQ_NR = 108,
+};
+
+#define MT6363_IRQ_BUCK_BASE MT6363_IRQ_VS2_OC
+#define MT6363_IRQ_LDO_BASE MT6363_IRQ_VCN15_OC
+#define MT6363_IRQ_PSC_BASE MT6363_IRQ_PWRKEY
+#define MT6363_IRQ_MISC_BASE MT6363_IRQ_RCS0
+#define MT6363_IRQ_HK_BASE MT6363_IRQ_BAT_H
+#define MT6363_IRQ_BM_BASE MT6363_IRQ_FG_BAT_H
+
+#define MT6363_IRQ_BUCK_BITS \
+	(MT6363_IRQ_VS3_OC - MT6363_IRQ_BUCK_BASE + 1)
+#define MT6363_IRQ_LDO_BITS \
+	(MT6363_IRQ_VM18_OC - MT6363_IRQ_LDO_BASE + 1)
+#define MT6363_IRQ_PSC_BITS \
+	(MT6363_IRQ_CHRDET_EDGE - MT6363_IRQ_PSC_BASE + 1)
+#define MT6363_IRQ_MISC_BITS \
+	(MT6363_IRQ_TOP_PROTREG - MT6363_IRQ_MISC_BASE + 1)
+#define MT6363_IRQ_HK_BITS \
+	(MT6363_IRQ_NAG_C_DLTV - MT6363_IRQ_HK_BASE + 1)
+#define MT6363_IRQ_BM_BITS \
+	(MT6363_IRQ_BATON_BAT_OUT - MT6363_IRQ_BM_BASE + 1)
+
+#define MT6363_TOP_GEN(sp) \
+{ \
+	.hwirq_base = MT6363_IRQ_##sp##_BASE, \
+	.num_int_regs =	((MT6363_IRQ_##sp##_BITS - 1) / MT6363_REG_WIDTH) + 1, \
+	.en_reg = MT6363_##sp##_TOP_INT_CON0, \
+	.en_reg_shift = 0x3, \
+	.sta_reg = MT6363_##sp##_TOP_INT_STATUS0, \
+	.sta_reg_shift = 0x1, \
+	.top_offset = MT6363_##sp##_TOP, \
+}
+
+#endif /* __MFD_MT6363_CORE_H__ */
diff --git a/include/linux/mfd/mt6363/registers.h b/include/linux/mfd/mt6363/registers.h
new file mode 100644
index 000000000000..e22ca686a7d0
--- /dev/null
+++ b/include/linux/mfd/mt6363/registers.h
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+
+#ifndef __MFD_MT6363_REGISTERS_H__
+#define __MFD_MT6363_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6363_TOPSTATUS		   (0x1e)
+#define MT6363_MISC_TOP_INT_CON0           (0x37)
+#define MT6363_MISC_TOP_INT_STATUS0        (0x43)
+#define MT6363_TOP_INT_STATUS1             (0x4e)
+#define MT6363_PSC_TOP_INT_CON0            (0x90f)
+#define MT6363_PSC_TOP_INT_STATUS0         (0x91b)
+#define MT6363_STRUP_CON11		   (0xa0e)
+#define MT6363_STRUP_CON12		   (0xa0f)
+#define MT6363_PCHR_VREF_ANA_CON1          (0xa89)
+#define MT6363_PCHR_VREF_ANA_CON2          (0xa8a)
+#define MT6363_BM_TOP_INT_CON0             (0xc24)
+#define MT6363_BM_TOP_INT_STATUS0          (0xc36)
+#define MT6363_HK_TOP_INT_CON0             (0xf92)
+#define MT6363_HK_TOP_INT_STATUS0          (0xf9e)
+#define MT6363_BUCK_TOP_INT_CON0           (0x1411)
+#define MT6363_BUCK_TOP_INT_STATUS0        (0x141d)
+#define MT6363_LDO_TOP_INT_CON0            (0x1b11)
+#define MT6363_LDO_TOP_INT_STATUS0         (0x1b29)
+
+/* voter */
+#define MT6363_BUCK_VS2_VOTER_CON0         (0x149a)
+#define MT6363_BUCK_VS2_VOTER_CON0_SET     (0x149b)
+#define MT6363_BUCK_VS2_VOTER_CON0_CLR     (0x149c)
+#define MT6363_BUCK_VS2_VOTER_CON1         (0x149d)
+#define MT6363_BUCK_VS2_VOTER_CON1_SET     (0x149e)
+#define MT6363_BUCK_VS2_VOTER_CON1_CLR     (0x149f)
+#define MT6363_BUCK_VS2_VOTER_CFG          (0x14a0)
+#define MT6363_BUCK_VS1_VOTER_CON0         (0x189a)
+#define MT6363_BUCK_VS1_VOTER_CON0_SET     (0x189b)
+#define MT6363_BUCK_VS1_VOTER_CON0_CLR     (0x189c)
+#define MT6363_BUCK_VS1_VOTER_CON1         (0x189d)
+#define MT6363_BUCK_VS1_VOTER_CON1_SET     (0x189e)
+#define MT6363_BUCK_VS1_VOTER_CON1_CLR     (0x189f)
+#define MT6363_BUCK_VS1_VOTER_CFG          (0x18a0)
+#define MT6363_BUCK_VS3_VOTER_CON0         (0x191a)
+#define MT6363_BUCK_VS3_VOTER_CON0_SET     (0x191b)
+#define MT6363_BUCK_VS3_VOTER_CON0_CLR     (0x191c)
+#define MT6363_BUCK_VS3_VOTER_CON1         (0x191d)
+#define MT6363_BUCK_VS3_VOTER_CON1_SET     (0x191e)
+#define MT6363_BUCK_VS3_VOTER_CON1_CLR     (0x191f)
+#define MT6363_BUCK_VS3_VOTER_CFG          (0x1920)
+
+#define MT6363_CHRDET_DEB_ADDR             MT6363_TOPSTATUS
+#define MT6363_CHRDET_DEB_MASK             (0x1)
+#define MT6363_CHRDET_DEB_SHIFT            (2)
+#define MT6363_RG_VBB_UVLO_VTHL_ADDR       MT6363_PCHR_VREF_ANA_CON1
+#define MT6363_RG_VBB_UVLO_VTHL_MASK       (0xF)
+#define MT6363_RG_VBB_UVLO_VTHL_SHIFT      (0)
+#define MT6363_RG_VSYS_UVLO_VTHL_ADDR      MT6363_PCHR_VREF_ANA_CON2
+#define MT6363_RG_VSYS_UVLO_VTHL_MASK      (0xF)
+#define MT6363_RG_VSYS_UVLO_VTHL_SHIFT     (0)
+
+#define MT6363_AUXADC_ADC0_L               (0x1088)
+#define MT6363_AUXADC_ADC3_L               (0x108e)
+#define MT6363_AUXADC_ADC4_L               (0x1090)
+#define MT6363_AUXADC_ADC11_L              (0x109e)
+#define MT6363_AUXADC_ADC38_L              (0x10c4)
+#define MT6363_AUXADC_ADC39_L              (0x10c6)
+#define MT6363_AUXADC_ADC40_L              (0x10c8)
+#define MT6363_AUXADC_ADC_CH12_L           (0x10d2)
+#define MT6363_AUXADC_ADC_CH14_L           (0x10d8)
+#define MT6363_AUXADC_ADC42_L              (0x10dc)
+#define MT6363_AUXADC_RQST0                (0x1108)
+#define MT6363_AUXADC_RQST1                (0x1109)
+#define MT6363_AUXADC_RQST3                (0x110c)
+#define MT6363_SDMADC_RQST0                (0x110e)
+#define MT6363_SDMADC_CON0                 (0x11c4)
+#define MT6363_AUXADC_IMP0                 (0x1208)
+#define MT6363_AUXADC_IMP1                 (0x1209)
+
+/* voter */
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CON0
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CON1
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CFG
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CON0
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CON1
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CFG
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CON0
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CON1
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CFG
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_SHIFT                (0)
+
+#endif /* __MFD_MT6363_REGISTERS_H__ */
+
diff --git a/include/linux/mfd/mt6373/core.h b/include/linux/mfd/mt6373/core.h
new file mode 100644
index 000000000000..dd77d8cf29a2
--- /dev/null
+++ b/include/linux/mfd/mt6373/core.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6373_CORE_H__
+#define __MFD_MT6373_CORE_H__
+
+#define MT6373_REG_WIDTH 8
+
+enum mt6373_irq_top_status_shift {
+	MT6373_BUCK_TOP = 0,
+	MT6373_LDO_TOP,
+	MT6373_PSC_TOP,
+	MT6373_MISC_TOP,
+	MT6373_HK_TOP,
+	MT6373_SCK_TOP,
+	MT6373_BM_TOP,
+	MT6373_AUD_TOP,
+};
+
+enum mt6373_irq_numbers {
+	MT6373_IRQ_VBUCK0_OC,
+	MT6373_IRQ_VBUCK1_OC,
+	MT6373_IRQ_VBUCK2_OC,
+	MT6373_IRQ_VBUCK3_OC,
+	MT6373_IRQ_VBUCK4_OC,
+	MT6373_IRQ_VBUCK5_OC,
+	MT6373_IRQ_VBUCK6_OC,
+	MT6373_IRQ_VBUCK7_OC,
+	MT6373_IRQ_VBUCK8_OC,
+	MT6373_IRQ_VBUCK9_OC,
+	MT6373_IRQ_VAUD18_OC = 16,
+	MT6373_IRQ_VUSB_OC,
+	MT6373_IRQ_VAUX18_OC,
+	MT6373_IRQ_VRF13_AIF_OC,
+	MT6373_IRQ_VRF18_AIF_OC,
+	MT6373_IRQ_VRFIO18_AIF_OC,
+	MT6373_IRQ_VCN33_1_OC,
+	MT6373_IRQ_VCN33_2_OC,
+	MT6373_IRQ_VCN33_3_OC,
+	MT6373_IRQ_VCN18IO_OC,
+	MT6373_IRQ_VRF09_AIF_OC,
+	MT6373_IRQ_VRF12_AIF_OC,
+	MT6373_IRQ_VANT18_OC,
+	MT6373_IRQ_VSRAM_DIGRF_AIF_OC,
+	MT6373_IRQ_VMDDR_OC,
+	MT6373_IRQ_VEFUSE_OC,
+	MT6373_IRQ_VMCH_OC,
+	MT6373_IRQ_VMC_OC,
+	MT6373_IRQ_VIBR_OC,
+	MT6373_IRQ_VIO28_OC,
+	MT6373_IRQ_VFP_OC,
+	MT6373_IRQ_VTP_OC,
+	MT6373_IRQ_VSIM1_OC,
+	MT6373_IRQ_VSIM2_OC,
+	MT6373_IRQ_RCS0 = 56,
+	MT6373_IRQ_SPMI_CMD_ALERT,
+	MT6373_IRQ_BM_PROTREG = 62,
+	MT6373_IRQ_VRC_PROTREG,
+	MT6373_IRQ_BUCK_PROTREG = 64,
+	MT6373_IRQ_LDO_PROTREG,
+	MT6373_IRQ_PSC_PROTREG,
+	MT6373_IRQ_PLT_PROTREG,
+	MT6373_IRQ_HK_PROTREG,
+	MT6373_IRQ_SCK_PROTREG,
+	MT6373_IRQ_XPP_PROTREG,
+	MT6373_IRQ_TOP_PROTREG,
+	MT6373_IRQ_NR = 72,
+};
+
+#define MT6373_IRQ_BUCK_BASE MT6373_IRQ_VBUCK0_OC
+#define MT6373_IRQ_LDO_BASE MT6373_IRQ_VAUD18_OC
+#define MT6373_IRQ_MISC_BASE MT6373_IRQ_RCS0
+
+#define MT6373_IRQ_BUCK_BITS \
+	(MT6373_IRQ_VBUCK9_OC - MT6373_IRQ_BUCK_BASE + 1)
+#define MT6373_IRQ_LDO_BITS \
+	(MT6373_IRQ_VSIM2_OC - MT6373_IRQ_LDO_BASE + 1)
+#define MT6373_IRQ_MISC_BITS \
+	(MT6373_IRQ_TOP_PROTREG - MT6373_IRQ_MISC_BASE + 1)
+
+#define MT6373_TOP_GEN(sp) \
+{ \
+	.hwirq_base = MT6373_IRQ_##sp##_BASE, \
+	.num_int_regs =	((MT6373_IRQ_##sp##_BITS - 1) / MT6373_REG_WIDTH) + 1, \
+	.en_reg = MT6373_##sp##_TOP_INT_CON0, \
+	.en_reg_shift = 0x3, \
+	.sta_reg = MT6373_##sp##_TOP_INT_STATUS0, \
+	.sta_reg_shift = 0x1, \
+	.top_offset = MT6373_##sp##_TOP, \
+}
+
+#endif /* __MFD_MT6373_CORE_H__ */
diff --git a/include/linux/mfd/mt6373/registers.h b/include/linux/mfd/mt6373/registers.h
new file mode 100644
index 000000000000..05aef78abfdf
--- /dev/null
+++ b/include/linux/mfd/mt6373/registers.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+
+#ifndef __MFD_MT6373_REGISTERS_H__
+#define __MFD_MT6373_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6373_TOPSTATUS                       0x1e
+#define MT6373_MISC_TOP_INT_CON0               0x3c
+#define MT6373_MISC_TOP_INT_CON1               0x3f
+#define MT6373_MISC_TOP_INT_STATUS0            0x48
+#define MT6373_MISC_TOP_INT_STATUS1            0x49
+#define MT6373_TOP_INT_MASK_CON0               0x4c
+#define MT6373_TOP_INT_MASK_CON0_SET           0x4d
+#define MT6373_TOP_INT_MASK_CON0_CLR           0x4e
+#define MT6373_TOP_INT_MASK_CON1               0x4f
+#define MT6373_TOP_INT_MASK_CON1_SET           0x50
+#define MT6373_TOP_INT_MASK_CON1_CLR           0x51
+#define MT6373_TOP_INT_STATUS0                 0x52
+#define MT6373_TOP_INT_STATUS1                 0x53
+#define MT6373_HK_TOP_INT_CON0                 0xf92
+#define MT6373_HK_TOP_INT_CON1                 0xf95
+#define MT6373_HK_TOP_INT_STATUS0              0xf9e
+#define MT6373_HK_TOP_INT_STATUS1              0xf9f
+#define MT6373_AUXADC_ADC4_L                   0x1090
+#define MT6373_AUXADC_ADC38_L                  0x10c4
+#define MT6373_AUXADC_ADC39_L                  0x10c6
+#define MT6373_AUXADC_ADC40_L                  0x10c8
+#define MT6373_AUXADC_ADC_CH12_L               0x10d2
+#define MT6373_AUXADC_ADC_CH12_H               0x10d3
+#define MT6373_AUXADC_RQST0                    0x1108
+#define MT6373_AUXADC_RQST1                    0x1109
+#define MT6373_AUXADC_RQST3                    0x110c
+#define MT6373_SDMADC_RQST0                    0x110e
+#define MT6373_SDMADC_CON0                     0x11c4
+#define MT6373_BUCK_TOP_INT_CON0               0x1411
+#define MT6373_BUCK_TOP_INT_CON1               0x1414
+#define MT6373_BUCK_TOP_INT_STATUS0            0x141d
+#define MT6373_BUCK_TOP_INT_STATUS1            0x141e
+#define MT6373_LDO_TOP_INT_CON0                0x1b10
+#define MT6373_LDO_TOP_INT_CON1                0x1b13
+#define MT6373_LDO_TOP_INT_CON2                0x1b16
+#define MT6373_LDO_TOP_INT_STATUS0             0x1b22
+#define MT6373_LDO_TOP_INT_STATUS1             0x1b23
+#define MT6373_LDO_TOP_INT_STATUS2             0x1b24
+#define MT6373_LDO_VMCH_CON0                   0x1cb1
+#define MT6373_LDO_VMCH_CON1                   0x1cb2
+#define MT6373_LDO_VMCH_CON2                   0x1cb3
+
+#endif /* __MFD_MT6373_REGISTERS_H__ */
-- 
2.46.0



From Lu.Tang at mediatek.com  Fri Mar 14 00:32:31 2025
From: Lu.Tang at mediatek.com (Lu.Tang)
Date: Fri, 14 Mar 2025 15:32:31 +0800
Subject: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <20250314073307.25092-6-Lu.Tang@mediatek.com>

Add new pmic mfd and adc documents for mt8196

Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>
---
 .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |  31 ++++
 .../bindings/input/mediatek,pmic-keys.yaml    |   1 +
 .../bindings/mfd/mediatek,mt6685.yaml         |  50 +++++
 .../bindings/mfd/mediatek,spmi-pmic.yaml      | 173 ++++++++++++++++++
 .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |   1 +
 5 files changed, 256 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
new file mode 100644
index 000000000000..250782ad7d01
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SPMI PMIC AUXADC
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description:
+  The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
+  in some MediaTek PMICs, performing various PMIC related measurements
+  such as battery and PMIC internal voltage regulators temperatures,
+  other than voltages for various PMIC internal components.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt6363-auxadc
+      - mediatek,mt6373-auxadc
+
+  "#io-channel-cells":
+    const: 1
+
+required:
+  - compatible
+  - "#io-channel-cells"
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index b95435bd6a9b..ce760039d4c2 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -31,6 +31,7 @@ properties:
       - mediatek,mt6358-keys
       - mediatek,mt6359-keys
       - mediatek,mt6397-keys
+      - mediatek,mt6363-keys
 
   power-off-time-sec: true
 
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
new file mode 100644
index 000000000000..d3276df8952b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt6685.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6685 Clock IC
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description: |
+  MT6685 is a clock IC.
+  Please see the sub-modules below for supported features.
+
+  MT6685 is a multifunction device with the following sub modules:
+  - RTC
+  - Clock
+
+properties:
+  compatible:
+    const: mediatek,mt6685
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    spmi {
+        mfd at 9 {
+            compatible = "mediatek,mt6685";
+            reg = <0x9 SPMI_USID>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
new file mode 100644
index 000000000000..a8f1231623cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SPMI PMICs multi-function device
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description: |
+  Some Mediatek PMICs are interfaced to the chip via the SPMI (System Power
+  Management Interface) bus.
+
+  The Mediatek SPMI series includes the MT6363, MT6373, MT6316 and other
+  PMICs.Please see the sub-modules below for supported features.
+
+   MT6363/MT6373 is a multifunction device with the following sub modules:
+  - Regulators
+  - ADC
+  - GPIO
+  - Keys
+   MT6316 is a multifunction device with the following sub modules:
+  - Regulators
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - mediatek,mt6363
+          - mediatek,mt6373
+          - mediatek,mt6316
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+  regulators:
+    type: object
+    description:
+      List of child nodes that specify the regulators.
+    additionalProperties: true
+
+    properties:
+      compatible:
+        oneOf:
+          - enum:
+              - mediatek,mt6363-regulator
+              - mediatek,mt6373-regulator
+              - mediatek,mt6316-regulator
+
+    required:
+      - compatible
+
+  adc:
+    type: object
+    $ref: /schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
+    unevaluatedProperties: false
+
+  keys:
+    type: object
+    $ref: /schemas/input/mediatek,pmic-keys.yaml
+    unevaluatedProperties: false
+    description:
+      Power and Home keys.
+
+  pinctrl:
+    type: object
+    $ref: /schemas/pinctrl/mediatek,mt65xx-pinctrl.yaml
+    unevaluatedProperties: false
+    description:
+      Pin controller
+
+required:
+  - compatible
+  - regulators
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    spmi {
+        main_pmic: pmic at 4 {
+            compatible = "mediatek,mt6363";
+            reg = <0x4 SPMI_USID>;
+            interrupts = <0x4 IRQ_TYPE_NONE>;
+            #address-cells = <0>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+
+            mt6363keys: keys {
+                compatible = "mediatek,mt6363-keys";
+                mediatek,long-press-mode = <1>;
+                power-off-time-sec = <0>;
+
+                power {
+                    linux,keycodes = <116>;
+                    wakeup-source;
+                };
+
+                home {
+                    linux,keycodes = <115>;
+                };
+            };
+
+            mt6363_pio: pinctrl {
+                compatible = "mediatek,mt6363-pinctrl";
+                gpio-controller;
+                #gpio-cells = <2>;
+            };
+
+            mt6363regulator: regulators {
+                compatible = "mediatek,mt6363-regulator";
+
+                mt6363_vs2: vs2 {
+                    regulator-name = "mt6363_vs2";
+                    regulator-allowed-modes = <0 1 2>;
+                    regulator-always-on;
+                    regulator-allow-set-load;
+                };
+
+                mt6363_vbuck1: vbuck1 {
+                    regulator-name = "mt6363_vbuck1";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck2: vbuck2 {
+                    regulator-name = "mt6363_vbuck2";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck3: vbuck3 {
+                    regulator-name = "mt6363_vbuck3";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck4: vbuck4 {
+                    regulator-name = "mt6363_vbuck4";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck5: vbuck5 {
+                    regulator-name = "mt6363_vbuck5";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck6: vbuck6 {
+                    regulator-name = "mt6363_vbuck6";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck7: vbuck7 {
+                    regulator-name = "mt6363_vbuck7";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                // ...
+
+                mt6363_isink_load: isink-load {
+                    regulator-name = "mt6363_isink_load";
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
index bccff08a5ba3..bf3ba58a7705 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
@@ -17,6 +17,7 @@ properties:
     enum:
       - mediatek,mt2701-pinctrl
       - mediatek,mt2712-pinctrl
+      - mediatek,mt6363-pinctrl
       - mediatek,mt6397-pinctrl
       - mediatek,mt7623-pinctrl
       - mediatek,mt8127-pinctrl
-- 
2.46.0



From fshao at chromium.org  Fri Mar 14 00:56:17 2025
From: fshao at chromium.org (Fei Shao)
Date: Fri, 14 Mar 2025 15:56:17 +0800
Subject: [PATCH] media: mediatek: vcodec: Correct vsi_core framebuffer size
Message-ID: <20250314075703.4167532-1-fshao@chromium.org>

The framebuffer size for decoder instances was being incorrectly set -
inst->vsi_core->fb.y.size was assigned twice consecutively.

Assign the second picinfo framebuffer size to the C framebuffer instead,
which appears to be the intended target based on the surrounding code.

Fixes: 2674486aac7d ("media: mediatek: vcodec: support stateless hevc decoder")
Signed-off-by: Fei Shao <fshao at chromium.org>
---

 .../mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
index aa721cc43647..2725db882e5b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
@@ -821,7 +821,7 @@ static int vdec_hevc_slice_setup_core_buffer(struct vdec_hevc_slice_inst *inst,
 	inst->vsi_core->fb.y.dma_addr = y_fb_dma;
 	inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
 	inst->vsi_core->fb.c.dma_addr = c_fb_dma;
-	inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
+	inst->vsi_core->fb.c.size = ctx->picinfo.fb_sz[1];
 
 	inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From lee at kernel.org  Fri Mar 14 01:00:22 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 14 Mar 2025 08:00:22 +0000
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <f363c1ce-8612-476e-a5d5-c3cb358bf50a@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
 <20250313132036.GB3616286@google.com>
 <ef190ba8-a5c7-4a1a-90e6-2610de00e4ed@sirena.org.uk>
 <f363c1ce-8612-476e-a5d5-c3cb358bf50a@gmail.com>
Message-ID: <20250314080022.GH3645863@google.com>

On Thu, 13 Mar 2025, Artur Weber wrote:

> On 13.03.2025 14:25, Mark Brown wrote:
> > On Thu, Mar 13, 2025 at 01:20:36PM +0000, Lee Jones wrote:
> > > On Tue, 04 Mar 2025, Artur Weber wrote:
> > 
> > > > +	if (id != bcm590xx->pmu_id) {
> > > > +		dev_err(bcm590xx->dev,
> > > > +			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",
> > > 
> > > Isn't it more likely that the H/W this is being executed on is
> > > unsupported?  If so, say that instead.
> > 
> > Given that the compatibles are device specific the driver shouldn't be
> > binding if the device is unsupported.
> 
> Yes, the intention here is just to make sure that the DT compatible and
> hardware ID match. Unsupported hardware would not have a DT compatible.

Right, so the user is utilising the correct compatible on the incorrect
(most likely unsupported) platform.  When using a supported DTB on
unknown hardware, the driver will bind but fail here.

-- 
Lee Jones [???]


From krzk at kernel.org  Fri Mar 14 01:01:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 14 Mar 2025 09:01:32 +0100
Subject: [PATCH v4 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
 <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>
Message-ID: <20250314-tested-husky-of-force-1ccdca@krzk-bin>

On Thu, Mar 13, 2025 at 05:05:35PM +0800, Kelvin Zhang wrote:
>  &apb {
> +	reset: reset-controller at 2000 {
> +		compatible = "amlogic,a4-reset",
> +			     "amlogic,meson-s4-reset";
> +		reg = <0x0 0x2000 0x0 0x98>;
> +		#reset-cells = <1>;
> +	};
> +

Why do you have on the bus devices with bus addressing and without it?
What sort of bus is it?

>  	periphs_pinctrl: pinctrl {
>  		compatible = "amlogic,pinctrl-a4";
>  		#address-cells = <2>;

Best regards,
Krzysztof



From liqiong at nfschina.com  Fri Mar 14 01:02:49 2025
From: liqiong at nfschina.com (Li Qiong)
Date: Fri, 14 Mar 2025 16:02:49 +0800
Subject: [PATCH v2 2/2] usb: gadget: udc-xilinx: Remove the invalid comment
In-Reply-To: <20250314080249.469307-1-liqiong@nfschina.com>
Message-ID: <20250314080249.469307-2-liqiong@nfschina.com>

The function don't return value, remove the invalid comment.

Signed-off-by: Li Qiong <liqiong at nfschina.com>
---
 drivers/usb/gadget/udc/udc-xilinx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index ae2aeb271897..fa94cc065274 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -2178,8 +2178,6 @@ static int xudc_probe(struct platform_device *pdev)
 /**
  * xudc_remove - Releases the resources allocated during the initialization.
  * @pdev: pointer to the platform device structure.
- *
- * Return: 0 always
  */
 static void xudc_remove(struct platform_device *pdev)
 {
-- 
2.30.2



From krzk at kernel.org  Fri Mar 14 01:07:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 14 Mar 2025 09:07:56 +0100
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
Message-ID: <20250314-encouraging-fabulous-ant-e1f7b0@krzk-bin>

On Thu, Mar 13, 2025 at 02:57:44PM +0200, florin.leotescu at oss.nxp.com wrote:
> +  '#size-cells':
> +    const: 0
> +
> +  '#pwm-cells':
> +    const: 2
> +
> +patternProperties:
> +  "^fan@[0-4]$":

Keep consistent quotes, either ' or "

> +    $ref: fan-common.yaml#
> +    unevaluatedProperties: false
> +    properties:
> +      reg:
> +        description:
> +          The fan number.
> +
> +    required:
> +      - reg
> +      - pwms
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        fan_controller: fan-controller at 2f {
> +            compatible = "microchip,emc2305";
> +            reg = <0x2f>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            #pwm-cells = <2>;
> +
> +            fan at 0 {
> +                #cooling-cells = <2>;
> +                reg = <0x0>;

Please follow DTS coding style, so reg is here the first property.

> +                pwms = <&fan_controller 1 1>;

It's the same PWM for all fans? So isn't it basically one fan? How do
you exactly control them independently, if the same PWM channel is used?

> +            };
> +
> +            fan at 1 {
> +                #cooling-cells = <2>;
> +                reg = <0x1>;
> +                pwms = <&fan_controller 1 1>;


Best regards,
Krzysztof



From peng.fan at oss.nxp.com  Fri Mar 14 02:20:06 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Fri, 14 Mar 2025 17:20:06 +0800
Subject: [PATCH v10 13/18] clk: imx: add support for i.MX8MP anatop clock
 driver
In-Reply-To: <20250306112959.242131-14-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
 <20250306112959.242131-14-dario.binacchi@amarulasolutions.com>
Message-ID: <20250314092006.GB12210@nxa18884-linux>

On Thu, Mar 06, 2025 at 12:28:02PM +0100, Dario Binacchi wrote:
>Support NXP i.MX8P anatop PLL module which generates PLLs to CCM root.
>By doing so, we also simplify the CCM driver code. The changes are
>backward compatible.
>
>Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

Reviewed-by: Peng Fan <peng.fan at nxp.com>


From peng.fan at oss.nxp.com  Fri Mar 14 02:21:29 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Fri, 14 Mar 2025 17:21:29 +0800
Subject: [PATCH v10 14/18] clk: imx8mp: rename ccm_base to base
In-Reply-To: <20250306112959.242131-15-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
 <20250306112959.242131-15-dario.binacchi@amarulasolutions.com>
Message-ID: <20250314092129.GC12210@nxa18884-linux>

On Thu, Mar 06, 2025 at 12:28:03PM +0100, Dario Binacchi wrote:
>The old code also accessed the anatop address space and therefore used
>the variables anatop_base and ccm_base to distinguish between the two
>address spaces. However, now that a specific anatop driver exists for
>the i.MX8MP platform, the variable ccm_base can be renamed to base, as
>is usually the case for the variable pointing to the memory region
>managed by a Linux driver.
>The patch does not introduce any functional changes.
>
>Signed-off-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>

Reviewed-by: Peng Fan <peng.fan at nxp.com>


From lihuafei1 at huawei.com  Fri Mar 14 09:21:36 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:36 +0800
Subject: [PATCH 6/7] perf annotate-data: Handle arm64 global variable access
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-7-lihuafei1@huawei.com>

Arm64 uses the 'adrp' and 'add' instructions to load the address of a
global variable. For example:

 adrp    x19, ffff8000819c3000
 add     x19, x19, #0x3e8
 <<after some sequence>>
 ldr     x22, [x19, #8]

Here, 'adrp' retrieves the base address of the page where the global
variable is located, and 'add' adds the offset within the page. If PMU
sampling occurs at the instruction 'ldr x22, [x19, #8]', we need to
trace the preceding 'adrp' and 'add' instructions to obtain the status
information of x19.

A new register status type 'TSR_KIND_GLOBAL_ADDR' is introduced,
indicating that the register holds the address of a global variable, and
this address is also stored in the 'type_state_reg' structure. After
obtaining the status information of x19, we use
get_global_var_type() to search for a matching global variable and
verify whether the returned offset is equal to 8. If it is, then we have
identified the data type and offset of the accessed global variable.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/arch/arm64/annotate/instructions.c | 90 ++++++++++++++++++-
 tools/perf/util/annotate-data.c               | 20 +++++
 tools/perf/util/annotate-data.h               |  2 +
 3 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index f70d93001fe7..f2053e7f60a8 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -262,6 +262,94 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
 	struct type_state_reg *tsr;
 	Dwarf_Die type_die;
 	int sreg, dreg;
+	u32 insn_offset = dl->al.offset;
+
+	/* Access global variables via PC relative addressing, for example:
+	 *
+	 *  adrp    x19, ffff800082074000
+	 *  add     x19, x19, #0x380
+	 *
+	 * The adrp instruction locates the page base address, and the add
+	 * instruction adds the offset within the page.
+	 */
+	if (!strncmp(dl->ins.name, "adrp", 4)) {
+		sreg = get_arm64_regnum(dl->ops.source.raw);
+		if (sreg < 0 || !has_reg_type(state, sreg))
+			return;
+
+		tsr = &state->regs[sreg];
+		tsr->ok = true;
+		tsr->kind = TSR_KIND_GLOBAL_ADDR;
+		/*
+		 * The default arm64_mov_ops has already parsed the adrp
+		 * instruction and saved the target address.
+		 */
+		tsr->addr = dl->ops.target.addr;
+
+		pr_debug_dtp("adrp [%x] global addr=%#"PRIx64" -> reg%d\n",
+			     insn_offset, tsr->addr, sreg);
+		return;
+	}
+
+	/* Add the offset within the page. */
+	if (!strncmp(dl->ins.name, "add", 3)) {
+		regmatch_t match[4];
+		char *ops = strdup(dl->ops.raw);
+		u64 offset;
+		static regex_t add_regex;
+		static bool regex_compiled;
+
+		/*
+		 * Matching the operand assembly syntax of the add instruction:
+		 *
+		 *  <Xd|SP>, <Xn|SP>, #<imm>
+		 */
+		if (!regex_compiled) {
+			regcomp(&add_regex,
+				"^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
+				REG_EXTENDED);
+			regex_compiled = true;
+		}
+
+		if (!ops)
+			return;
+
+		if (regexec(&add_regex, dl->ops.raw, 4, match, 0))
+			return;
+
+		/*
+		 * Parse the source register first. If it is not of the type
+		 * TSR_KIND_GLOBAL_ADDR, further parsing is not required.
+		 */
+		ops[match[2].rm_eo] = '\0';
+		sreg = get_arm64_regnum(ops + match[2].rm_so);
+		if (sreg < 0 || !has_reg_type(state, sreg) ||
+		    state->regs[sreg].kind != TSR_KIND_GLOBAL_ADDR) {
+			free(ops);
+			return;
+		}
+
+		ops[match[1].rm_eo] = '\0';
+		dreg = get_arm64_regnum(ops + match[1].rm_so);
+		if (dreg < 0 || !has_reg_type(state, dreg)) {
+			free(ops);
+			return;
+		}
+
+		ops[match[3].rm_eo] = '\0';
+		offset = strtoul(ops + match[3].rm_so, NULL, 16);
+
+		tsr = &state->regs[dreg];
+		tsr->ok = true;
+		tsr->kind = TSR_KIND_GLOBAL_ADDR;
+		tsr->addr = state->regs[sreg].addr + offset;
+
+		pr_debug_dtp("add [%x] global addr=%#"PRIx64"(reg%d) -> reg%d\n",
+			     insn_offset, tsr->addr, sreg, dreg);
+
+		free(ops);
+		return;
+	}
 
 	if (strncmp(dl->ins.name, "ld", 2))
 		return;
@@ -287,7 +375,7 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
 		tsr->ok = true;
 
 		pr_debug_dtp("load [%x] %#x(reg%d) -> reg%d",
-			     (u32)dl->al.offset, dst->offset, dreg, sreg);
+			     insn_offset, dst->offset, dreg, sreg);
 		pr_debug_type_name(&tsr->type, tsr->kind);
 	}
 }
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 2bc8d646eedc..aaca08bb9097 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -65,6 +65,9 @@ void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind)
 	case TSR_KIND_CANARY:
 		pr_info(" stack canary\n");
 		return;
+	case TSR_KIND_GLOBAL_ADDR:
+		pr_info(" global address\n");
+		return;
 	case TSR_KIND_TYPE:
 	default:
 		break;
@@ -1087,6 +1090,23 @@ static enum type_match_result check_matching_type(struct type_state *state,
 		return PERF_TMR_OK;
 	}
 
+	if (state->regs[reg].kind == TSR_KIND_GLOBAL_ADDR) {
+		int var_offset;
+		u64 var_addr;
+
+		pr_debug_dtp("global var by address");
+
+		var_addr = state->regs[reg].addr + dloc->op->offset;
+
+		if (get_global_var_type(cu_die, dloc, dloc->ip, var_addr,
+					&var_offset, type_die)) {
+			dloc->type_offset = var_offset;
+			return PERF_TMR_OK;
+		}
+
+		return PERF_TMR_BAIL_OUT;
+	}
+
 	if (state->regs[reg].kind == TSR_KIND_CANARY) {
 		pr_debug_dtp("stack canary");
 
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 717f394eb8f1..e3e877313207 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -36,6 +36,7 @@ enum type_state_kind {
 	TSR_KIND_CONST,
 	TSR_KIND_POINTER,
 	TSR_KIND_CANARY,
+	TSR_KIND_GLOBAL_ADDR,
 };
 
 /**
@@ -177,6 +178,7 @@ struct type_state_reg {
 	bool caller_saved;
 	u8 kind;
 	u8 copied_from;
+	u64 addr;
 };
 
 /* Type information in a stack location, dynamically allocated */
-- 
2.25.1



From lihuafei1 at huawei.com  Fri Mar 14 09:21:37 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:37 +0800
Subject: [PATCH 7/7] perf annotate-data: Handle the access to the 'current' pointer on arm64
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-8-lihuafei1@huawei.com>

According to the implementation of the 'current' macro on ARM64, the
sp_el0 register stores the pointer to the current task's task_struct.
For example:

 mrs x1, sp_el0
 ldr x2, [x1, #1896]

We can infer that the ldr instruction is accessing a member of the
task_struct structure at an offset of 1896. The key is to construct the
data type for x1. The instruction 'mrs x1, sp_el0' belongs to the inline
function get_current(). By finding the DIE of the inline function
through its instruction address, and then obtaining the DIE for its
return type, which should be 'struct task_struct *'. Then, we update the
register state of x1 with this type information.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/arch/arm64/annotate/instructions.c | 71 +++++++++++++++----
 1 file changed, 57 insertions(+), 14 deletions(-)

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index f2053e7f60a8..c5a0a6381547 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -263,6 +263,20 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
 	Dwarf_Die type_die;
 	int sreg, dreg;
 	u32 insn_offset = dl->al.offset;
+	static regex_t add_regex, mrs_regex;
+	static bool regex_compiled;
+
+	if (!regex_compiled) {
+		/*
+		 * Matching the operand assembly syntax of the add instruction:
+		 *
+		 *  <Xd|SP>, <Xn|SP>, #<imm>
+		 */
+		regcomp(&add_regex, "^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
+			REG_EXTENDED);
+		regcomp(&mrs_regex, "^(x[0-9]{1,2}), sp_el0", REG_EXTENDED);
+		regex_compiled = true;
+	}
 
 	/* Access global variables via PC relative addressing, for example:
 	 *
@@ -296,20 +310,6 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
 		regmatch_t match[4];
 		char *ops = strdup(dl->ops.raw);
 		u64 offset;
-		static regex_t add_regex;
-		static bool regex_compiled;
-
-		/*
-		 * Matching the operand assembly syntax of the add instruction:
-		 *
-		 *  <Xd|SP>, <Xn|SP>, #<imm>
-		 */
-		if (!regex_compiled) {
-			regcomp(&add_regex,
-				"^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
-				REG_EXTENDED);
-			regex_compiled = true;
-		}
 
 		if (!ops)
 			return;
@@ -351,6 +351,49 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
 		return;
 	}
 
+	if (!strncmp(dl->ins.name, "mrs", 3)) {
+		regmatch_t match[2];
+		char *ops = strdup(dl->ops.raw);
+		Dwarf_Die func_die;
+		Dwarf_Attribute attr;
+		u64 ip = dloc->ms->sym->start + dl->al.offset;
+		u64 pc = map__rip_2objdump(dloc->ms->map, ip);
+
+		if (!ops)
+			return;
+
+		if (regexec(&mrs_regex, dl->ops.raw, 2, match, 0))
+			return;
+
+		ops[match[1].rm_eo] = '\0';
+		sreg = get_arm64_regnum(ops + match[1].rm_so);
+		if (sreg < 0 || !has_reg_type(state, sreg)) {
+			free(ops);
+			return;
+		}
+
+		/*
+		 * Find the inline function 'get_current()' Dwarf_Die and
+		 * obtain its return value data type, which should be
+		 * 'struct task_struct *'.
+		 */
+		if (!die_find_inlinefunc(cu_die, pc, &func_die) ||
+		    !dwarf_attr_integrate(&func_die, DW_AT_type, &attr) ||
+		    !dwarf_formref_die(&attr, &type_die)) {
+			free(ops);
+			return;
+		}
+
+		tsr = &state->regs[sreg];
+		tsr->type = type_die;
+		tsr->kind = TSR_KIND_TYPE;
+		tsr->ok = true;
+
+		pr_debug_dtp("mrs sp_el0 [%x] -> reg%d", insn_offset, sreg);
+		free(ops);
+		return;
+	}
+
 	if (strncmp(dl->ins.name, "ld", 2))
 		return;
 
-- 
2.25.1



From lihuafei1 at huawei.com  Fri Mar 14 09:21:30 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:30 +0800
Subject: [PATCH 0/7] Add data type profiling support for arm64
Message-ID: <20250314162137.528204-1-lihuafei1@huawei.com>

Hi,

This patchset supports arm64 perf data type profiling. Data type
profiling was introduced by Namhyung [1], which associates PMU sampling
(here referring to memory access-related event sampling) with the
referenced data types, providing developers with an effective tool for
analyzing the impact of memory usage and layout. For more detailed
background, please refer to [2].

Namhyung initially supported this feature only on x86, and later Athira
added support for it on powerpc [3]. Unlike the x86 implementation, the
powerpc implementation parses operands directly from raw instruction
code instead of using the results from assembler disassembly. As Athira
mentioned, this is mainly because not all memory access instructions on
powerpc have explicit memory reference assembler notations '()' in their
assembly code. On arm64, all memory access instructions have the
notation '[]', so my implementation is similar to x86, using the
disassembly results from objdump, llvm, or libcapstone, and parsing
based on strings. I believe this has the advantage of reusing the
complex instruction parsing logic of the assembler, but it may not
perform as well as raw instruction parsing in terms of efficiency.

Below is a brief description of this patchset:
 - Patch 1 first identifies load and store instructions and provides a
   parsing function.
 - Patches 2-3 are refactoring patches. They primarily move the code for
   extracting registers and offsets to specific architecture
   implementations. Additionally, a new callback function
   'extract_reg_offset' is introduced to avoid having too many
   architecture-specific implementations in the function
   'annotate_get_insn_location()'.
 - Patch 4 implements the extract_reg_offset callback for arm64.
   Currently, it does not support parsing instructions with register
   pairs or register offsets in operands. Register pairs often appear in
   stack push/pop instructions, and register offsets are common when
   accessing per-CPU variables, both of which require special handling.
 - Patch 5 adds support for instruction tracing on arm64, primarily
   addressing the issue where DWARF does not generate information for
   intermediate pointers in pointer chains.
 - Patches 6-7 further enhance instruction tracing. Patch 6 supports
   parsing accesses to global variables, while Patch 7 focuses on
   resolving accesses to the kernel's current pointer.

There are still areas for improvement in the current implementation:
 - Support more types of memory access instructions, such as those
   involving register pairs and register offsets.
 - Handle all data processing instructions (e.g., mov, add), as these
   instructions can change the state of registers and may affect the
   accuracy of instruction tracking.
 - Supporting parsing of special memory access scenarios like per-CPU
   variables and arrays.

The patch set is based on 6.14-rc6 (commit 80e54e84911a). After applying
this patch set, the date type profiling results on arm64 are as follows
(SPE support is required):

 # perf mem record -a -K -- sleep 1
 # perf annotate --data-type --type-stat --stdio
 Only instruction-based sampling period is currently supported by Arm SPE.
 Annotate data type stats:
 total 556, ok 357 (64.2%), bad 199 (35.8%)
 -----------------------------------------------------------
         10 : no_sym
         36 : no_insn_ops
         65 : no_var
         70 : no_typeinfo
         18 : bad_offset
         59 : insn_track
 
 Annotate type: 'struct rq' in [kernel.kallsyms] (29 samples):
 ============================================================================
  Percent     offset       size  field
   100.00          0      0xe80  struct rq        {
     0.00          0        0x4      raw_spinlock_t      __lock {
     0.00          0        0x4          arch_spinlock_t raw_lock {
     0.00          0        0x4              union        {
     0.00          0        0x4                  atomic_t        val {
     0.00          0        0x4                      int counter;
                                                 };
     0.00          0        0x2                  struct   {
     0.00          0        0x1                      u8  locked;
     0.00        0x1        0x1                      u8  pending;
                                                 };
     0.00          0        0x4                  struct   {
     0.00          0        0x2                      u16 locked_pending;
     0.00        0x2        0x2                      u16 tail;
                                                 };
                                             };
                                         };
                                     };
    13.79        0x4        0x4      unsigned int        nr_running;
    13.79        0x8        0x4      unsigned int        nr_numa_running;
     0.00        0xc        0x4      unsigned int        nr_preferred_running;
     0.00       0x10        0x4      unsigned int        numa_migrate_on;
     0.00       0x18        0x8      long unsigned int   last_blocked_load_update_tick;
     0.00       0x20        0x4      unsigned int        has_blocked_load;
     0.00       0x40       0x20      call_single_data_t  nohz_csd {
     0.00       0x40       0x10          struct __call_single_node       node {
     0.00       0x40        0x8              struct llist_node   llist {
     0.00       0x40        0x8                  struct llist_node*      next;
                                             };
     0.00       0x48        0x4              union        {
     0.00       0x48        0x4                  unsigned int    u_flags;
     0.00       0x48        0x4                  atomic_t        a_flags {
     0.00       0x48        0x4                      int counter;
                                                 };
                                             };
     ...

Thanks,
Huafei

[1] https://lore.kernel.org/lkml/20231213001323.718046-1-namhyung at kernel.org/
[2] https://lwn.net/Articles/955709/
[3] https://lore.kernel.org/all/20240718084358.72242-1-atrajeev at linux.vnet.ibm.com/#r

Li Huafei (7):
  perf annotate: Handle arm64 load and store instructions
  perf annotate: Advance the mem_ref check to mov__parse()
  perf annotate: Add 'extract_reg_offset' callback function to extract
    register number and access offset
  perf annotate: Support for the 'extract_reg_offset' callback function
    in arm64
  perf annotate-data: Support instruction tracking for arm64
  perf annotate-data: Handle arm64 global variable access
  perf annotate-data: Handle the access to the 'current' pointer on
    arm64

 tools/perf/arch/arm64/annotate/instructions.c | 302 +++++++++++++++++-
 .../perf/arch/powerpc/annotate/instructions.c |  10 +
 tools/perf/arch/x86/annotate/instructions.c   |  99 ++++++
 tools/perf/util/Build                         |   1 +
 tools/perf/util/annotate-data.c               |  23 +-
 tools/perf/util/annotate-data.h               |   4 +-
 tools/perf/util/annotate.c                    | 112 +------
 tools/perf/util/disasm.c                      |  14 +
 tools/perf/util/disasm.h                      |   4 +
 tools/perf/util/dwarf-regs-arm64.c            |  25 ++
 tools/perf/util/include/dwarf-regs.h          |   7 +
 11 files changed, 490 insertions(+), 111 deletions(-)
 create mode 100644 tools/perf/util/dwarf-regs-arm64.c

-- 
2.25.1



From lihuafei1 at huawei.com  Fri Mar 14 09:21:32 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:32 +0800
Subject: [PATCH 2/7] perf annotate: Advance the mem_ref check to mov__parse()
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-3-lihuafei1@huawei.com>

Advance the mem_ref check on x86 to mov__parse(), along with the
multi_reg check, to make annotate_get_insn_location() more concise.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/util/annotate.c | 9 ++++-----
 tools/perf/util/disasm.c   | 8 ++++++++
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 31bb326b07a6..860ea6c72411 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -2442,18 +2442,17 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
 				continue;
 		}
 
+		op_loc->mem_ref = mem_ref;
+		op_loc->multi_regs = multi_regs;
+
 		/*
 		 * For powerpc, call get_powerpc_regs function which extracts the
 		 * required fields for op_loc, ie reg1, reg2, offset from the
 		 * raw instruction.
 		 */
 		if (arch__is(arch, "powerpc")) {
-			op_loc->mem_ref = mem_ref;
-			op_loc->multi_regs = multi_regs;
 			get_powerpc_regs(dl->raw.raw_insn, !i, op_loc);
-		} else if (strchr(insn_str, arch->objdump.memory_ref_char)) {
-			op_loc->mem_ref = true;
-			op_loc->multi_regs = multi_regs;
+		} else if (mem_ref) {
 			extract_reg_offset(arch, insn_str, op_loc);
 		} else {
 			char *s, *p = NULL;
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 50c5c206b70e..d91526cff9df 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -607,6 +607,12 @@ static bool check_multi_regs(struct arch *arch, const char *op)
 	return count > 1;
 }
 
+/* Check whether the operand accesses memory. */
+static bool check_memory_ref(struct arch *arch, const char *op)
+{
+	return strchr(op, arch->objdump.memory_ref_char) != NULL;
+}
+
 static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,
 		struct disasm_line *dl __maybe_unused)
 {
@@ -635,6 +641,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy
 	if (ops->source.raw == NULL)
 		return -1;
 
+	ops->source.mem_ref = check_memory_ref(arch, ops->source.raw);
 	ops->source.multi_regs = check_multi_regs(arch, ops->source.raw);
 
 	target = skip_spaces(++s);
@@ -657,6 +664,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy
 	if (ops->target.raw == NULL)
 		goto out_free_source;
 
+	ops->target.mem_ref = check_memory_ref(arch, ops->target.raw);
 	ops->target.multi_regs = check_multi_regs(arch, ops->target.raw);
 
 	if (comment == NULL)
-- 
2.25.1



From robh at kernel.org  Fri Mar 14 01:25:26 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 14 Mar 2025 03:25:26 -0500
Subject: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents
In-Reply-To: <20250314073307.25092-6-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-6-Lu.Tang@mediatek.com>
Message-ID: <174194072655.964967.9270640013940045148.robh@kernel.org>


On Fri, 14 Mar 2025 15:32:31 +0800, Lu.Tang wrote:
> Add new pmic mfd and adc documents for mt8196
> 
> Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>
> ---
>  .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |  31 ++++
>  .../bindings/input/mediatek,pmic-keys.yaml    |   1 +
>  .../bindings/mfd/mediatek,mt6685.yaml         |  50 +++++
>  .../bindings/mfd/mediatek,spmi-pmic.yaml      | 173 ++++++++++++++++++
>  .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |   1 +
>  5 files changed, 256 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dts:25.17-31: Warning (reg_format): /example-0/spmi/mfd at 9:reg: property has invalid length (8 bytes) (#address-cells == 2, #size-cells == 1)
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (pci_device_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (pci_device_bus_num): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (simple_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (i2c_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (spi_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dts:23.19-28.15: Warning (avoid_default_addr_size): /example-0/spmi/mfd at 9: Relying on default #address-cells value
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dts:23.19-28.15: Warning (avoid_default_addr_size): /example-0/spmi/mfd at 9: Relying on default #size-cells value
Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: Warning (unique_unit_address_if_enabled): Failed prerequisite 'avoid_default_addr_size'
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/mediatek,mt6685.example.dtb: mfd at 9: '#address-cells', '#size-cells', 'reg' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/mediatek,mt6685.yaml#
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dts:31.17-31: Warning (reg_format): /example-0/spmi/pmic at 4:reg: property has invalid length (8 bytes) (#address-cells == 2, #size-cells == 1)
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (pci_device_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (pci_device_bus_num): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (simple_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (i2c_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (spi_bus_reg): Failed prerequisite 'reg_format'
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dts:29.31-109.15: Warning (avoid_default_addr_size): /example-0/spmi/pmic at 4: Relying on default #address-cells value
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dts:29.31-109.15: Warning (avoid_default_addr_size): /example-0/spmi/pmic at 4: Relying on default #size-cells value
Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: Warning (unique_unit_address_if_enabled): Failed prerequisite 'avoid_default_addr_size'
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.example.dtb: pmic at 4: '#address-cells', 'reg' do not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250314073307.25092-6-Lu.Tang at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From wenst at chromium.org  Fri Mar 14 01:34:13 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Fri, 14 Mar 2025 16:34:13 +0800
Subject: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents
In-Reply-To: <20250314073307.25092-6-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com> <20250314073307.25092-6-Lu.Tang@mediatek.com>
Message-ID: <CAGXv+5GMgkCSthLgna-0DwyMbw5pOd-jLi_H2Gk+5U0sUsnAFQ@mail.gmail.com>

On Fri, Mar 14, 2025 at 4:03?PM Lu.Tang <Lu.Tang at mediatek.com> wrote:
>
> Add new pmic mfd and adc documents for mt8196
>
> Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>
> ---
>  .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |  31 ++++
>  .../bindings/input/mediatek,pmic-keys.yaml    |   1 +
>  .../bindings/mfd/mediatek,mt6685.yaml         |  50 +++++
>  .../bindings/mfd/mediatek,spmi-pmic.yaml      | 173 ++++++++++++++++++
>  .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |   1 +
>  5 files changed, 256 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
> new file mode 100644
> index 000000000000..250782ad7d01
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
> @@ -0,0 +1,31 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek SPMI PMIC AUXADC
> +
> +maintainers:
> +  - Lu Tang <lu.tang at mediatek.com>
> +
> +description:
> +  The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
> +  in some MediaTek PMICs, performing various PMIC related measurements
> +  such as battery and PMIC internal voltage regulators temperatures,
> +  other than voltages for various PMIC internal components.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - mediatek,mt6363-auxadc
> +      - mediatek,mt6373-auxadc
> +
> +  "#io-channel-cells":
> +    const: 1
> +
> +required:
> +  - compatible
> +  - "#io-channel-cells"
> +
> +additionalProperties: false

This is simply a sub-function of the PMIC, and is really not tied to
whatever interface the PMIC uses. Please integrate this into the existing
binding:

    Documentation/devicetree/bindings/iio/adc/mediatek,mt6359-auxadc.yaml

> diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> index b95435bd6a9b..ce760039d4c2 100644
> --- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> +++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
> @@ -31,6 +31,7 @@ properties:
>        - mediatek,mt6358-keys
>        - mediatek,mt6359-keys
>        - mediatek,mt6397-keys
> +      - mediatek,mt6363-keys
>
>    power-off-time-sec: true
>
> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
> new file mode 100644
> index 000000000000..d3276df8952b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
> @@ -0,0 +1,50 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/mediatek,mt6685.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT6685 Clock IC
> +
> +maintainers:
> +  - Lu Tang <lu.tang at mediatek.com>
> +
> +description: |
> +  MT6685 is a clock IC.
> +  Please see the sub-modules below for supported features.
> +
> +  MT6685 is a multifunction device with the following sub modules:
> +  - RTC
> +  - Clock
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt6685
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  interrupt-controller: true
> +
> +  "#interrupt-cells":
> +    const: 2
> +
> +required:
> +  - compatible
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/spmi/spmi.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    spmi {
> +        mfd at 9 {
> +            compatible = "mediatek,mt6685";
> +            reg = <0x9 SPMI_USID>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +        };
> +    };
> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
> new file mode 100644
> index 000000000000..a8f1231623cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
> @@ -0,0 +1,173 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek SPMI PMICs multi-function device
> +
> +maintainers:
> +  - Lu Tang <lu.tang at mediatek.com>
> +
> +description: |
> +  Some Mediatek PMICs are interfaced to the chip via the SPMI (System Power
> +  Management Interface) bus.
> +
> +  The Mediatek SPMI series includes the MT6363, MT6373, MT6316 and other
> +  PMICs.Please see the sub-modules below for supported features.
> +
> +   MT6363/MT6373 is a multifunction device with the following sub modules:
> +  - Regulators
> +  - ADC
> +  - GPIO
> +  - Keys


> +   MT6316 is a multifunction device with the following sub modules:
> +  - Regulators

Then it is not multifunctional. Please move this to the MT6315
binding:

    Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml

Also, you have not covered regulator bindings in this series.


ChenYu

> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - mediatek,mt6363
> +          - mediatek,mt6373
> +          - mediatek,mt6316
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  interrupt-controller: true
> +
> +  "#interrupt-cells":
> +    const: 2
> +
> +  regulators:
> +    type: object
> +    description:
> +      List of child nodes that specify the regulators.
> +    additionalProperties: true
> +
> +    properties:
> +      compatible:
> +        oneOf:
> +          - enum:
> +              - mediatek,mt6363-regulator
> +              - mediatek,mt6373-regulator
> +              - mediatek,mt6316-regulator
> +
> +    required:
> +      - compatible
> +
> +  adc:
> +    type: object
> +    $ref: /schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
> +    unevaluatedProperties: false
> +
> +  keys:
> +    type: object
> +    $ref: /schemas/input/mediatek,pmic-keys.yaml
> +    unevaluatedProperties: false
> +    description:
> +      Power and Home keys.
> +
> +  pinctrl:
> +    type: object
> +    $ref: /schemas/pinctrl/mediatek,mt65xx-pinctrl.yaml
> +    unevaluatedProperties: false
> +    description:
> +      Pin controller
> +
> +required:
> +  - compatible
> +  - regulators
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/spmi/spmi.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    spmi {
> +        main_pmic: pmic at 4 {
> +            compatible = "mediatek,mt6363";
> +            reg = <0x4 SPMI_USID>;
> +            interrupts = <0x4 IRQ_TYPE_NONE>;
> +            #address-cells = <0>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +
> +            mt6363keys: keys {
> +                compatible = "mediatek,mt6363-keys";
> +                mediatek,long-press-mode = <1>;
> +                power-off-time-sec = <0>;
> +
> +                power {
> +                    linux,keycodes = <116>;
> +                    wakeup-source;
> +                };
> +
> +                home {
> +                    linux,keycodes = <115>;
> +                };
> +            };
> +
> +            mt6363_pio: pinctrl {
> +                compatible = "mediatek,mt6363-pinctrl";
> +                gpio-controller;
> +                #gpio-cells = <2>;
> +            };
> +
> +            mt6363regulator: regulators {
> +                compatible = "mediatek,mt6363-regulator";
> +
> +                mt6363_vs2: vs2 {
> +                    regulator-name = "mt6363_vs2";
> +                    regulator-allowed-modes = <0 1 2>;
> +                    regulator-always-on;
> +                    regulator-allow-set-load;
> +                };
> +
> +                mt6363_vbuck1: vbuck1 {
> +                    regulator-name = "mt6363_vbuck1";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck2: vbuck2 {
> +                    regulator-name = "mt6363_vbuck2";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck3: vbuck3 {
> +                    regulator-name = "mt6363_vbuck3";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck4: vbuck4 {
> +                    regulator-name = "mt6363_vbuck4";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck5: vbuck5 {
> +                    regulator-name = "mt6363_vbuck5";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck6: vbuck6 {
> +                    regulator-name = "mt6363_vbuck6";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                mt6363_vbuck7: vbuck7 {
> +                    regulator-name = "mt6363_vbuck7";
> +                    regulator-allowed-modes = <0 1 2>;
> +                };
> +
> +                // ...
> +
> +                mt6363_isink_load: isink-load {
> +                    regulator-name = "mt6363_isink_load";
> +                };
> +            };
> +        };
> +    };
> diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> index bccff08a5ba3..bf3ba58a7705 100644
> --- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> @@ -17,6 +17,7 @@ properties:
>      enum:
>        - mediatek,mt2701-pinctrl
>        - mediatek,mt2712-pinctrl
> +      - mediatek,mt6363-pinctrl
>        - mediatek,mt6397-pinctrl
>        - mediatek,mt7623-pinctrl
>        - mediatek,mt8127-pinctrl
> --
> 2.46.0
>
>


From lihuafei1 at huawei.com  Fri Mar 14 09:21:34 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:34 +0800
Subject: [PATCH 4/7] perf annotate: Support for the 'extract_reg_offset' callback function in arm64
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-5-lihuafei1@huawei.com>

At present, only the following two addressing modes are supported:

 1. Base register only (no offset): [base{, #0}]
 2. Base plus offset (immediate): [base{, #imm}]

For addressing modes where the offset needs to be calculated from the
register value, it is difficult to know the specific value of the offset
register, making it impossible to calculate the offset.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/arch/arm64/annotate/instructions.c | 62 +++++++++++++++++++
 tools/perf/util/Build                         |  1 +
 tools/perf/util/disasm.c                      |  1 +
 tools/perf/util/dwarf-regs-arm64.c            | 25 ++++++++
 tools/perf/util/include/dwarf-regs.h          |  7 +++
 5 files changed, 96 insertions(+)
 create mode 100644 tools/perf/util/dwarf-regs-arm64.c

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index c212eb7341bd..54497b72a5c5 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -188,3 +188,65 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 	free(arm);
 	return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
 }
+
+
+/*
+ * Get the base register number and access offset in load/store instructions.
+ * At present, only the following two addressing modes are supported:
+ *
+ *  1. Base register only (no offset): [base{, #0}]
+ *  2. Base plus offset (immediate): [base{, #imm}]
+ *
+ * For addressing modes where the offset needs to be calculated from the
+ * register value, it is difficult to know the specific value of the offset
+ * register, making it impossible to calculate the offset.
+ *
+ * Fills @reg and @offset when return 0.
+ */
+static int
+extract_reg_offset_arm64(struct arch *arch __maybe_unused,
+			 struct disasm_line *dl __maybe_unused,
+			 const char *insn_str, int insn_ops __maybe_unused,
+			 struct annotated_op_loc *op_loc)
+{
+	char *str;
+	regmatch_t match[4];
+	static regex_t reg_off_regex;
+	static bool regex_compiled;
+
+	if (!regex_compiled) {
+		regcomp(&reg_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
+			REG_EXTENDED);
+		regex_compiled = true;
+	}
+
+	if (!op_loc->mem_ref)
+		return 0;
+
+	if (regexec(&reg_off_regex, insn_str, 4, match, 0))
+		return -1;
+
+	str = strdup(insn_str);
+	if (!str)
+		return -1;
+
+	/* Get the base register number. */
+	str[match[1].rm_eo] = '\0';
+	op_loc->reg1 = get_arm64_regnum(str + match[1].rm_so);
+
+	/*
+	 * If there is an immediate offset, match[2] records the start and end
+	 * positions of "#imm".
+	 */
+	if (match[2].rm_so == -1) {
+		free(str);
+		return 0;
+	}
+
+	/* Get the immediate offset. */
+	str[match[3].rm_eo] = '\0';
+	op_loc->offset = strtol(str + match[3].rm_so, NULL, 0);
+
+	free(str);
+	return 0;
+}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 5ec97e8d6b6d..d408cbe94fdd 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -210,6 +210,7 @@ perf-util-$(CONFIG_LIBDW) += dwarf-regs.o
 perf-util-$(CONFIG_LIBDW) += dwarf-regs-csky.o
 perf-util-$(CONFIG_LIBDW) += dwarf-regs-powerpc.o
 perf-util-$(CONFIG_LIBDW) += dwarf-regs-x86.o
+perf-util-$(CONFIG_LIBDW) += dwarf-regs-arm64.o
 perf-util-$(CONFIG_LIBDW) += debuginfo.o
 perf-util-$(CONFIG_LIBDW) += annotate-data.o
 
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 905eceb824a4..1035c60a8545 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -128,6 +128,7 @@ static struct arch architectures[] = {
 	{
 		.name = "arm64",
 		.init = arm64__annotate_init,
+		.extract_reg_offset = extract_reg_offset_arm64,
 	},
 	{
 		.name = "csky",
diff --git a/tools/perf/util/dwarf-regs-arm64.c b/tools/perf/util/dwarf-regs-arm64.c
new file mode 100644
index 000000000000..edf41c059967
--- /dev/null
+++ b/tools/perf/util/dwarf-regs-arm64.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (c) 2025  Huawei Inc, Li Huafei <lihuafei1 at huawei.com>
+ */
+#include <errno.h>
+#include <string.h>
+#include <dwarf-regs.h>
+
+int get_arm64_regnum(const char *name)
+{
+	int reg;
+
+	if (!strcmp(name, "sp"))
+		return 31;
+
+	if (*name != 'x' && *name != 'w')
+		return -EINVAL;
+
+	name++;
+	reg = strtol(name, NULL, 0);
+
+	return reg >= 0 && reg <= 30 ? reg : -EINVAL;
+}
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 6f1b9f6b2466..81cc5f69a391 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -101,6 +101,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine, unsigned int
 
 int get_x86_regnum(const char *name);
 
+int get_arm64_regnum(const char *name);
+
 #if !defined(__x86_64__) && !defined(__i386__)
 int get_arch_regnum(const char *name);
 #endif
@@ -128,6 +130,11 @@ static inline void get_powerpc_regs(u32 raw_insn __maybe_unused, int is_source _
 {
 	return;
 }
+
+static inline int get_arm64_regnum(const char *name __maybe_unused)
+{
+	return -1;
+}
 #endif
 
 #endif
-- 
2.25.1



From wenst at chromium.org  Fri Mar 14 01:26:27 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Fri, 14 Mar 2025 16:26:27 +0800
Subject: [PATCH 2/5] pmic: mediatek: Add pmic regulator driver
In-Reply-To: <20250314073307.25092-3-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com> <20250314073307.25092-3-Lu.Tang@mediatek.com>
Message-ID: <CAGXv+5FKLz2sK5UOwtj33xZEh6kKznSAdeHhc6d0oSxbQqpEmA@mail.gmail.com>

On Fri, Mar 14, 2025 at 3:58?PM Lu.Tang <Lu.Tang at mediatek.com> wrote:
>
> From: "Lu.Tang" <lu.tang at mediatek.com>
>
> Add pmic mt6316/mt6373/mt6363 regulator driver

Please split this into one patch per PMIC. That will make the patch
size much more manageable. And the patch subject should just say what
PMIC is added.

> Signed-off-by: Lu Tang <lu.tang at mediatek.com>
> ---
>  drivers/regulator/Kconfig                  |   34 +
>  drivers/regulator/Makefile                 |    3 +
>  drivers/regulator/mt6316-regulator.c       |  381 +++++++

How much of the MT6316 driver is the same or similar to MT6315?
AFAICT they are both 4 buck regulators where some of the outputs
can be combined into a polyphase output.

>  drivers/regulator/mt6363-regulator.c       | 1106 ++++++++++++++++++++
>  drivers/regulator/mt6373-regulator.c       |  826 +++++++++++++++
>  include/linux/regulator/mt6316-regulator.h |   48 +
>  include/linux/regulator/mt6363-regulator.h |  424 ++++++++
>  include/linux/regulator/mt6373-regulator.h |  318 ++++++
>  8 files changed, 3140 insertions(+)
>  create mode 100644 drivers/regulator/mt6316-regulator.c
>  create mode 100644 drivers/regulator/mt6363-regulator.c
>  create mode 100644 drivers/regulator/mt6373-regulator.c
>  create mode 100644 include/linux/regulator/mt6316-regulator.h
>  create mode 100644 include/linux/regulator/mt6363-regulator.h
>  create mode 100644 include/linux/regulator/mt6373-regulator.h
>
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index 39297f7d8177..7b2d47fee535 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -853,6 +853,16 @@ config REGULATOR_MT6315
>           This driver supports the control of different power rails of device
>           through regulator interface.
>
> +config REGULATOR_MT6316
> +       tristate "MediaTek MT6316 PMIC"
> +       depends on SPMI
> +       select REGMAP_SPMI
> +       help
> +         Say y here to select this option to enable the power regulator of
> +         MediaTek MT6316 PMIC.
> +         This driver supports the control of different power rails of device
> +         through regulator interface.
> +
>  config REGULATOR_MT6323
>         tristate "MediaTek MT6323 PMIC"
>         depends on MFD_MT6397
> @@ -916,6 +926,18 @@ config REGULATOR_MT6360
>           2-channel buck with Thermal Shutdown and Overload Protection
>           6-channel High PSRR and Low Dropout LDO.
>
> +config REGULATOR_MT6363
> +       tristate "MT6363 SPMI Regulator driver"
> +       depends on MFD_MTK_SPMI_PMIC
> +       help
> +         Say y here to select this option to enable the power regulator of
> +         MediaTek MT6363 PMIC.
> +         This driver supports the control of different power rails of device
> +         through regulator interface.
> +
> +         The driver can also be build as a module.
> +         If so, the module will be called mt6363_regulator
> +
>  config REGULATOR_MT6370
>         tristate "MT6370 SubPMIC Regulator"
>         depends on MFD_MT6370
> @@ -924,6 +946,18 @@ config REGULATOR_MT6370
>           This driver supports the control for DisplayBias voltages and one
>           general purpose LDO which is commonly used to drive the vibrator.
>
> +config REGULATOR_MT6373
> +       tristate "MT6373 SPMI Regulator driver"
> +       depends on MFD_MTK_SPMI_PMIC
> +       help
> +         Say y here to select this option to enable the power regulator of
> +         MediaTek MT6373 PMIC.
> +         This driver supports the control of different power rails of device
> +         through regulator interface.
> +
> +         The driver can also be build as a module.
> +         If so, the module will be called mt6373_regulator
> +
>  config REGULATOR_MT6380
>         tristate "MediaTek MT6380 PMIC"
>         depends on MTK_PMIC_WRAP
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 3d5a803dce8a..b54a64522499 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -102,6 +102,7 @@ obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
>  obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
>  obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6316) += mt6316-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o
> @@ -109,7 +110,9 @@ obj-$(CONFIG_REGULATOR_MT6357)      += mt6357-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6373) += mt6373-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
>  obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
> diff --git a/drivers/regulator/mt6316-regulator.c b/drivers/regulator/mt6316-regulator.c
> new file mode 100644
> index 000000000000..1c069a0d4cff
> --- /dev/null
> +++ b/drivers/regulator/mt6316-regulator.c
> @@ -0,0 +1,381 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2024 MediaTek Inc.
> +
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/regulator/mt6316-regulator.h>
> +#include <linux/regulator/of_regulator.h>
> +
> +#define SET_OFFSET     0x1
> +#define CLR_OFFSET     0x2
> +
> +#define MT6316_REG_WIDTH       8
> +
> +#define MT6316_BUCK_MODE_AUTO          0
> +#define MT6316_BUCK_MODE_FORCE_PWM     1
> +#define MT6316_BUCK_MODE_NORMAL                0
> +#define MT6316_BUCK_MODE_LP            2
> +
> +#define BUCK_PHASE_3                   3
> +#define BUCK_PHASE_4                   4
> +
> +struct mt6316_regulator_info {
> +       struct regulator_desc desc;
> +       u32 da_reg;
> +       u32 qi;
> +       u32 modeset_reg;
> +       u32 modeset_mask;
> +       u32 lp_mode_reg;
> +       u32 lp_mode_mask;
> +       u32 lp_mode_shift;
> +};
> +
> +struct mt6316_init_data {
> +       u32 id;
> +       u32 size;
> +};
> +
> +struct mt6316_chip {
> +       struct device *dev;
> +       struct regmap *regmap;
> +       u32 slave_id;
> +};
> +
> +#define MT_BUCK(match, _name, volt_ranges, _bid, _vsel)        \
> +[MT6316_ID_##_name] = {                                        \
> +       .desc = {                                       \
> +               .name = #_name,                         \
> +               .of_match = of_match_ptr(match),        \
> +               .ops = &mt6316_volt_range_ops,          \
> +               .type = REGULATOR_VOLTAGE,              \
> +               .id = MT6316_ID_##_name,                \
> +               .owner = THIS_MODULE,                   \
> +               .n_voltages = 0x1ff,                    \
> +               .linear_ranges = volt_ranges,           \
> +               .n_linear_ranges = ARRAY_SIZE(volt_ranges),\
> +               .vsel_reg = _vsel,                      \
> +               .vsel_mask = 0xff,                      \
> +               .enable_reg = MT6316_BUCK_TOP_CON0,     \
> +               .enable_mask = BIT(_bid - 1),           \
> +               .of_map_mode = mt6316_map_mode,         \
> +       },                                              \
> +       .da_reg = MT6316_VBUCK##_bid##_DBG8,            \
> +       .qi = BIT(0),                                   \
> +       .lp_mode_reg = MT6316_BUCK_TOP_CON1,            \
> +       .lp_mode_mask = BIT(_bid - 1),                  \
> +       .lp_mode_shift = _bid - 1,                      \
> +       .modeset_reg = MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0,\
> +       .modeset_mask = BIT(_bid - 1),                  \
> +}
> +
> +static const struct linear_range mt_volt_range1[] = {
> +       REGULATOR_LINEAR_RANGE(0, 0, 0x1fe, 2500),
> +};
> +
> +static int mt6316_regulator_enable(struct regulator_dev *rdev)
> +{
> +       return regmap_write(rdev->regmap, rdev->desc->enable_reg + SET_OFFSET,
> +                           rdev->desc->enable_mask);
> +}
> +
> +static int mt6316_regulator_disable(struct regulator_dev *rdev)
> +{
> +       return regmap_write(rdev->regmap, rdev->desc->enable_reg + CLR_OFFSET,
> +                           rdev->desc->enable_mask);
> +}
> +
> +static unsigned int mt6316_map_mode(u32 mode)
> +{
> +       switch (mode) {
> +       case MT6316_BUCK_MODE_AUTO:
> +               return REGULATOR_MODE_NORMAL;
> +       case MT6316_BUCK_MODE_FORCE_PWM:
> +               return REGULATOR_MODE_FAST;
> +       case MT6316_BUCK_MODE_LP:
> +               return REGULATOR_MODE_IDLE;
> +       default:
> +               return REGULATOR_MODE_INVALID;
> +       }
> +}
> +
> +static int mt6316_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
> +{
> +       unsigned short reg_val = 0;
> +       int ret = 0;
> +
> +       reg_val = ((selector & 0x1) << 8) | (selector >> 1);
> +       ret = regmap_bulk_write(rdev->regmap, rdev->desc->vsel_reg, (u8 *) &reg_val, 2);
> +
> +       return ret;
> +}
> +
> +static int mt6316_regulator_get_voltage_sel(struct regulator_dev *rdev)
> +{
> +       int ret = 0;
> +       unsigned int reg_val = 0;
> +
> +       ret = regmap_bulk_read(rdev->regmap, rdev->desc->vsel_reg, (u8 *) &reg_val, 2);
> +       if (ret != 0) {
> +               dev_err(&rdev->dev, "Failed to get mt6316 regulator voltage: %d\n", ret);
> +               return ret;
> +       }
> +       ret = ((reg_val >> 8) & 0x1) + ((reg_val & rdev->desc->vsel_mask) << 1);
> +
> +       return ret;
> +}
> +
> +static unsigned int mt6316_regulator_get_mode(struct regulator_dev *rdev)
> +{
> +       struct mt6316_regulator_info *info;
> +       int ret = 0, regval = 0;
> +       u32 modeset_mask;
> +
> +       info = container_of(rdev->desc, struct mt6316_regulator_info, desc);
> +       ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
> +       if (ret != 0) {
> +               dev_err(&rdev->dev, "Failed to get mt6316 buck mode: %d\n", ret);
> +               return ret;
> +       }
> +
> +       modeset_mask = info->modeset_mask;
> +
> +       if ((regval & modeset_mask) == modeset_mask)
> +               return REGULATOR_MODE_FAST;
> +
> +       ret = regmap_read(rdev->regmap, info->lp_mode_reg, &regval);
> +       if (ret != 0) {
> +               dev_err(&rdev->dev, "Failed to get mt6316 buck lp mode: %d\n", ret);
> +               return ret;
> +       }
> +
> +       if (regval & info->lp_mode_mask)
> +               return REGULATOR_MODE_IDLE;
> +       else
> +               return REGULATOR_MODE_NORMAL;
> +}
> +
> +static int mt6316_regulator_set_mode(struct regulator_dev *rdev, u32 mode)
> +{
> +       struct mt6316_regulator_info *info;
> +       int ret = 0, val, curr_mode;
> +       u32 modeset_mask;
> +
> +       info = container_of(rdev->desc, struct mt6316_regulator_info, desc);
> +       modeset_mask = info->modeset_mask;
> +
> +       curr_mode = mt6316_regulator_get_mode(rdev);
> +       switch (mode) {
> +       case REGULATOR_MODE_FAST:
> +               ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
> +                                        modeset_mask, modeset_mask);
> +               break;
> +       case REGULATOR_MODE_NORMAL:
> +               if (curr_mode == REGULATOR_MODE_FAST) {
> +                       ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
> +                                                modeset_mask, 0);
> +               } else if (curr_mode == REGULATOR_MODE_IDLE) {
> +                       ret = regmap_update_bits(rdev->regmap, info->lp_mode_reg,
> +                                                info->lp_mode_mask, 0);
> +                       usleep_range(100, 110);
> +               }
> +               break;
> +       case REGULATOR_MODE_IDLE:
> +               val = MT6316_BUCK_MODE_LP >> 1;
> +               val <<= info->lp_mode_shift;
> +               ret = regmap_update_bits(rdev->regmap, info->lp_mode_reg, info->lp_mode_mask, val);
> +               break;
> +       default:
> +               ret = -EINVAL;
> +               goto err_mode;
> +       }
> +
> +err_mode:
> +       if (ret != 0) {
> +               dev_err(&rdev->dev, "Failed to set mt6316 buck mode: %d\n", ret);
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int mt6316_get_status(struct regulator_dev *rdev)
> +{
> +       int ret = 0;
> +       u32 regval = 0;
> +       struct mt6316_regulator_info *info;
> +
> +       info = container_of(rdev->desc, struct mt6316_regulator_info, desc);
> +       ret = regmap_read(rdev->regmap, info->da_reg, &regval);
> +       if (ret != 0) {
> +               dev_notice(&rdev->dev, "Failed to get enable reg: %d\n", ret);
> +               return ret;
> +       }
> +
> +       return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
> +}
> +
> +static void mt6316_buck_phase_init(struct mt6316_chip *chip, unsigned int *s6_buck_phase)
> +{
> +       int ret = 0;
> +       u32 val = 0;
> +
> +       ret = regmap_read(chip->regmap, MT6316_BUCK_TOP_4PHASE_TOP_ELR_0, &val);
> +       if (ret) {
> +               dev_err(chip->dev, "Failed to get mt6316 buck phase: %d\n", ret);
> +               return;
> +       }
> +
> +       dev_info(chip->dev, "S%d RG_4PH_CONFIG:%d\n", chip->slave_id, val);
> +       if (chip->slave_id == MT6316_SLAVE_ID_6)
> +               *s6_buck_phase = val;
> +}
> +
> +static const struct regulator_ops mt6316_volt_range_ops = {
> +       .list_voltage = regulator_list_voltage_linear_range,
> +       .map_voltage = regulator_map_voltage_linear_range,
> +       .set_voltage_sel = mt6316_regulator_set_voltage_sel,
> +       .get_voltage_sel = mt6316_regulator_get_voltage_sel,
> +       .set_voltage_time_sel = regulator_set_voltage_time_sel,
> +       .enable = mt6316_regulator_enable,
> +       .disable = mt6316_regulator_disable,
> +       .is_enabled = regulator_is_enabled_regmap,
> +       .get_status = mt6316_get_status,
> +       .set_mode = mt6316_regulator_set_mode,
> +       .get_mode = mt6316_regulator_get_mode,
> +};
> +
> +static struct mt6316_regulator_info mt6316_regulators[] = {
> +       MT_BUCK("vbuck1", VBUCK1, mt_volt_range1, 1, MT6316_BUCK_TOP_ELR0),
> +       MT_BUCK("vbuck2", VBUCK2, mt_volt_range1, 2, MT6316_BUCK_TOP_ELR2),
> +       MT_BUCK("vbuck3", VBUCK3, mt_volt_range1, 3, MT6316_BUCK_TOP_ELR4),
> +       MT_BUCK("vbuck4", VBUCK4, mt_volt_range1, 4, MT6316_BUCK_TOP_ELR6),
> +};
> +
> +static struct mt6316_init_data mt6316_3_init_data = {
> +       .id = MT6316_SLAVE_ID_3,
> +       .size = MT6316_ID_3_MAX,
> +};
> +
> +static struct mt6316_init_data mt6316_6_init_data = {
> +       .id = MT6316_SLAVE_ID_6,
> +       .size = MT6316_ID_6_MAX,
> +};
> +
> +static struct mt6316_init_data mt6316_7_init_data = {
> +       .id = MT6316_SLAVE_ID_7,
> +       .size = MT6316_ID_7_MAX,
> +};
> +
> +static struct mt6316_init_data mt6316_8_init_data = {
> +       .id = MT6316_SLAVE_ID_8,
> +       .size = MT6316_ID_8_MAX,
> +};
> +
> +static struct mt6316_init_data mt6316_15_init_data = {
> +       .id = MT6316_SLAVE_ID_15,
> +       .size = MT6316_ID_15_MAX,
> +};
> +
> +static const struct of_device_id mt6316_of_match[] = {
> +       {
> +               .compatible = "mediatek,mt6316-3-regulator",
> +               .data = &mt6316_3_init_data,
> +       }, {
> +               .compatible = "mediatek,mt6316-6-regulator",
> +               .data = &mt6316_6_init_data,
> +       }, {
> +               .compatible = "mediatek,mt6316-7-regulator",
> +               .data = &mt6316_7_init_data,
> +       }, {
> +               .compatible = "mediatek,mt6316-8-regulator",
> +               .data = &mt6316_8_init_data,
> +       }, {
> +               .compatible = "mediatek,mt6316-15-regulator",
> +               .data = &mt6316_15_init_data,
> +       }, {
> +               /* sentinel */
> +       },
> +};
> +MODULE_DEVICE_TABLE(of, mt6316_of_match);
> +
> +static int mt6316_regulator_probe(struct platform_device *pdev)
> +{
> +       const struct of_device_id *of_id;
> +       struct device *dev = &pdev->dev;
> +       struct regmap *regmap;
> +       struct mt6316_init_data *pdata;
> +       struct mt6316_chip *chip;
> +       struct regulator_config config = {};
> +       struct regulator_dev *rdev;
> +       struct device_node *node = pdev->dev.of_node;
> +       u32 val = 0;
> +       int i;
> +       unsigned int s6_buck_phase;
> +
> +       regmap = dev_get_regmap(dev->parent, NULL);
> +       if (!regmap)
> +               return -ENODEV;
> +
> +       chip = devm_kzalloc(dev, sizeof(struct mt6316_chip), GFP_KERNEL);
> +       if (!chip)
> +               return -ENOMEM;

Replace the following block:

> +       of_id = of_match_device(mt6316_of_match, dev);
> +       if (!of_id || !of_id->data)
> +               return -ENODEV;
> +
> +       pdata = (struct mt6316_init_data *)of_id->data;

with

    pdata = of_device_get_match_data(dev);

pdata should never be NULL since the driver is probed only when an
OF match happens, and all the entries in mt6316_of_match[] have .data
set.

> +       chip->slave_id = pdata->id;

If the ID is supposed to be the SPMI ID, then there should be no
reason to tie it to the compatible string. Simply get the ID from
the device tree.

> +       if (!of_property_read_u32(node, "buck-size", &val))
> +               pdata->size = val;

As mentioned in downstream review, the chip has 4 buck regulators,
regardless of whether they are being used or not. This is not the
right way to describe unused regulators.

> +       chip->dev = dev;
> +       chip->regmap = regmap;
> +       dev_set_drvdata(dev, chip);
> +
> +       dev->fwnode = &(dev->of_node->fwnode);
> +       if (dev->fwnode && !dev->fwnode->dev)
> +               dev->fwnode->dev = dev;
> +
> +       config.dev = dev;
> +       config.driver_data = pdata;
> +       config.regmap = regmap;
> +
> +       mt6316_buck_phase_init(chip, &s6_buck_phase);
> +       for (i = 0; i < pdata->size; i++) {
> +               if (pdata->id == MT6316_SLAVE_ID_6 &&
> +                   s6_buck_phase == BUCK_PHASE_4 &&
> +                   (mt6316_regulators + i)->desc.id == MT6316_ID_VBUCK3) {
> +                       dev_info(dev, "skip registering %s.\n", (mt6316_regulators + i)->desc.name);
> +                       continue;
> +               }
> +
> +               rdev = devm_regulator_register(dev, &(mt6316_regulators + i)->desc, &config);
> +               if (IS_ERR(rdev)) {
> +                       dev_err(dev, "failed to register %s\n", (mt6316_regulators + i)->desc.name);
> +                       continue;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static struct platform_driver mt6316_regulator_driver = {

The MT6316 only has regulators. Why does it need to go through another
layer, instead of this driver being the SPMI driver?

> +       .driver         = {
> +               .name   = "mt6316-regulator",
> +               .of_match_table = mt6316_of_match,
> +       },
> +       .probe = mt6316_regulator_probe,
> +};
> +
> +module_platform_driver(mt6316_regulator_driver);
> +
> +MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>");
> +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6316 PMIC");
> +MODULE_LICENSE("GPL");

[...]

Skipping the other two PMICs for now.

> diff --git a/include/linux/regulator/mt6316-regulator.h b/include/linux/regulator/mt6316-regulator.h
> new file mode 100644
> index 000000000000..dd11b3d856fd
> --- /dev/null
> +++ b/include/linux/regulator/mt6316-regulator.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2024 MediaTek Inc.
> + */
> +
> +#ifndef __LINUX_REGULATOR_MT6316_H
> +#define __LINUX_REGULATOR_MT6316_H
> +
> +#define MT6316_SLAVE_ID_3      3
> +#define MT6316_SLAVE_ID_6      6
> +#define MT6316_SLAVE_ID_7      7
> +#define MT6316_SLAVE_ID_8      8
> +#define MT6316_SLAVE_ID_15     15
> +
> +#define MT6316_ID_3_MAX                3
> +#define MT6316_ID_6_MAX                3
> +#define MT6316_ID_7_MAX                3
> +#define MT6316_ID_8_MAX                3
> +#define MT6316_ID_15_MAX       2
> +
> +enum {
> +       MT6316_ID_VBUCK1 = 0,
> +       MT6316_ID_VBUCK2,
> +       MT6316_ID_VBUCK3,
> +       MT6316_ID_VBUCK4,
> +       MT6316_ID_MAX,
> +};
> +
> +/* Register */
> +#define MT6316_TOP_CFG_ELR4                    0x143
> +#define MT6316_BUCK_TOP_CON0                   0x1440
> +#define MT6316_BUCK_TOP_CON1                   0x1443
> +#define MT6316_BUCK_TOP_ELR0                   0x1448
> +#define MT6316_BUCK_TOP_ELR2                   0x144A
> +#define MT6316_BUCK_TOP_ELR4                   0x144C
> +#define MT6316_BUCK_TOP_ELR6                   0x144E
> +#define MT6316_VBUCK1_DBG4                     0x14A4
> +#define MT6316_VBUCK1_DBG8                     0x14A8
> +#define MT6316_VBUCK2_DBG4                     0x1524
> +#define MT6316_VBUCK2_DBG8                     0x1528
> +#define MT6316_VBUCK3_DBG4                     0x15A4
> +#define MT6316_VBUCK3_DBG8                     0x15A8
> +#define MT6316_VBUCK4_DBG4                     0x1624
> +#define MT6316_VBUCK4_DBG8                     0x1628
> +#define MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0     0x1688
> +#define MT6316_BUCK_TOP_4PHASE_TOP_ELR_0       0x1690
> +
> +#endif /* __LINUX_REGULATOR_MT6316_H */

AFAICT, no part of this file is used by other parts of the kernel. It
can be moved under drivers/regulator/, or even recombined with the
.c file.


Thanks
ChenYu


From peng.fan at oss.nxp.com  Fri Mar 14 02:35:03 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Fri, 14 Mar 2025 17:35:03 +0800
Subject: [PATCH v10 00/18] Support spread spectrum clocking for i.MX8M
 PLLs
In-Reply-To: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
References: <20250306112959.242131-1-dario.binacchi@amarulasolutions.com>
Message-ID: <20250314093503.GD12210@nxa18884-linux>

On Thu, Mar 06, 2025 at 12:27:49PM +0100, Dario Binacchi wrote:
>This version keeps the version v9 patches that can be merged and
>removes the patches that will need to be modified in case Peng's
>PR https://github.com/devicetree-org/dt-schema/pull/154 is accepted.
>The idea is to speed up the merging of the patches in the series
>that have already been reviewed and are not dependent on the
>introduction of the assigned-clocks-sscs property, and postpone
>the patches for spread spectrum to a future series once it becomes
>clear what needs to be done.
>
Although I give R-b, there is an idea just come out in my mind that this
might break OS distribution that use firmware(e.g. U-Boot) to publish
device tree for Linux Kernel, such as ARM System-Ready complaint OS.
I overlooked this point in previous patchset reviewing.

Since this patchset is to move anatop stuff to a new driver to reflect
the HW truth.  And requires new entries in CCM node, so old bootloader
with new kernel will not boot for OS distribution, such as Fedora/openSuse.

Not sure how to keep backwards support as before. Leave to maintainers
to say if they are ok with this.

Regards,
Peng


From wenst at chromium.org  Fri Mar 14 01:27:32 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Fri, 14 Mar 2025 16:27:32 +0800
Subject: [PATCH 0/5] Add PMIC and SPMI driver for mt8196
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <CAGXv+5EzdMtOXotGUNdwdP-cKPwMccH6kGDifpg+WgjX_2z2VQ@mail.gmail.com>

On Fri, Mar 14, 2025 at 3:56?PM Lu.Tang <Lu.Tang at mediatek.com> wrote:
>
> This series is based on linux-next.
>
> Changes in v0:
> - Modify SPMI driver for mt8196
> - Add SPMI PMIC mfd driver
> - Add PMIC regulator driver for mt8196
>
> *** BLURB HERE ***
>
> Lu.Tang (5):
>   pmic: mediatek: Add pmic auxadc driver
>   pmic: mediatek: Add pmic regulator driver
>   pmic: mediatek: Add spmi pmic mfd driver
>   spmi: mediatek: modify spmi dirver for mt8196
>   dt-bindings: pmic: mediatek: Add pmic documents

You are adding three PMICs at the same time. Please separate each
patch in this series so that it is one patch per type per PMIC.

ChenYu


>  .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |   31 +
>  .../bindings/input/mediatek,pmic-keys.yaml    |    1 +
>  .../bindings/mfd/mediatek,mt6685.yaml         |   50 +
>  .../bindings/mfd/mediatek,spmi-pmic.yaml      |  173 +++
>  .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |    1 +
>  drivers/iio/adc/Kconfig                       |   10 +
>  drivers/iio/adc/Makefile                      |    1 +
>  drivers/iio/adc/mtk-spmi-pmic-adc.c           |  576 +++++++++
>  drivers/mfd/Kconfig                           |   26 +
>  drivers/mfd/Makefile                          |    2 +
>  drivers/mfd/mt6685-core.c                     |   83 ++
>  drivers/mfd/mtk-spmi-pmic.c                   |  518 ++++++++
>  drivers/regulator/Kconfig                     |   34 +
>  drivers/regulator/Makefile                    |    3 +
>  drivers/regulator/mt6316-regulator.c          |  381 ++++++
>  drivers/regulator/mt6363-regulator.c          | 1106 +++++++++++++++++
>  drivers/regulator/mt6373-regulator.c          |  826 ++++++++++++
>  drivers/spmi/spmi-mtk-pmif.c                  | 1040 +++++++++++++++-
>  include/linux/mfd/mt6363/core.h               |  134 ++
>  include/linux/mfd/mt6363/registers.h          |  168 +++
>  include/linux/mfd/mt6373/core.h               |   94 ++
>  include/linux/mfd/mt6373/registers.h          |   53 +
>  include/linux/regulator/mt6316-regulator.h    |   48 +
>  include/linux/regulator/mt6363-regulator.h    |  424 +++++++
>  include/linux/regulator/mt6373-regulator.h    |  318 +++++
>  25 files changed, 6037 insertions(+), 64 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
>  create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
>  create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c
>  create mode 100644 drivers/mfd/mt6685-core.c
>  create mode 100644 drivers/mfd/mtk-spmi-pmic.c
>  create mode 100644 drivers/regulator/mt6316-regulator.c
>  create mode 100644 drivers/regulator/mt6363-regulator.c
>  create mode 100644 drivers/regulator/mt6373-regulator.c
>  create mode 100644 include/linux/mfd/mt6363/core.h
>  create mode 100644 include/linux/mfd/mt6363/registers.h
>  create mode 100644 include/linux/mfd/mt6373/core.h
>  create mode 100644 include/linux/mfd/mt6373/registers.h
>  create mode 100644 include/linux/regulator/mt6316-regulator.h
>  create mode 100644 include/linux/regulator/mt6363-regulator.h
>  create mode 100644 include/linux/regulator/mt6373-regulator.h
>
> --
> 2.46.0
>
>


From lihuisong at huawei.com  Fri Mar 14 01:28:56 2025
From: lihuisong at huawei.com (Huisong Li)
Date: Fri, 14 Mar 2025 16:28:56 +0800
Subject: [PATCH] soc: hisilicon: kunpeng_hccs: Fix incorrect string assembly
Message-ID: <20250314082856.3257783-1-lihuisong@huawei.com>

String assembly should use sysfs_emit_at() instead of sysfs_emit().

Signed-off-by: Huisong Li <lihuisong at huawei.com>
---
 drivers/soc/hisilicon/kunpeng_hccs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 8aa8dec14911..444a8f59b7da 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1539,8 +1539,8 @@ static ssize_t used_types_show(struct kobject *kobj,
 	u16 i;
 
 	for (i = 0; i < hdev->used_type_num - 1; i++)
-		len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name);
-	len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name);
+		len += sysfs_emit_at(buf, len, "%s ", hdev->type_name_maps[i].name);
+	len += sysfs_emit_at(buf, len, "%s\n", hdev->type_name_maps[i].name);
 
 	return len;
 }
-- 
2.33.0



From kw at linux.com  Fri Mar 14 01:37:30 2025
From: kw at linux.com (Krzysztof Wilczynski)
Date: Fri, 14 Mar 2025 17:37:30 +0900
Subject: [PATCH v7 08/11] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <d1362766e3e966f78591129de918046a4b892c18.1738963156.git.andrea.porta@suse.com>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <d1362766e3e966f78591129de918046a4b892c18.1738963156.git.andrea.porta@suse.com>
Message-ID: <20250314083730.GC234496@rocinante>

Hello,

Even though this is not for the PCI sub-system directly, I had a very brief
look over the code.  I hope you don't mind.

As such, a few nit picks, nothing blocking.

> +# RaspberryPi RP1 misc device

Would this be better if it matched the "tristate" description below?

> +config MISC_RP1
> +	tristate "RaspberryPi RP1 PCIe support"
> +	depends on OF_IRQ && OF_OVERLAY && PCI_MSI && PCI_QUIRKS
> +	select PCI_DYNAMIC_OF_NODES
> +	help
> +	  Support the RP1 peripheral chip found on Raspberry Pi 5 board.
> +
> +	  This device supports several sub-devices including e.g. Ethernet
> +	  controller, USB controller, I2C, SPI and UART.
> +
> +	  The driver is responsible for enabling the DT node once the PCIe
> +	  endpoint has been configured, and handling interrupts.
> +
> +	  This driver uses an overlay to load other drivers to support for
> +	  RP1 internal sub-devices.

> +/* the dts overlay is included from the dts directory so

  /*
   * The dts overlay is included from the dts directory so

To make the code comment match rest of the style.

> +/*
> + * Copyright (c) 2018-24 Raspberry Pi Ltd.
> + * All rights reserved.

  Copyright (c) 2018-2025 Raspberry Pi Ltd.

To spell the current year fully, plus update it to 2025 already.

I would also add an extra newline here to split the two apart a bit.

> +	if (pci_resource_len(pdev, 1) <= 0x10000) {
> +		dev_err(&pdev->dev,
> +			"Not initialised - is the firmware running?\n");
> +		return -EINVAL;
> +	}

The American spelling in the above might be better.  But I don't have
strong opinions here.  It seems more popular in error messages.

> +	err = pci_alloc_irq_vectors(pdev, RP1_INT_END, RP1_INT_END,
> +				    PCI_IRQ_MSIX);
> +	if (err < 0) {
> +		return dev_err_probe(&pdev->dev, err,
> +				     "pci_alloc_irq_vectors failed");

Missing a new line at the end, but also...

  return dev_err_probe(&pdev->dev, err,
		       "Failed to allocate MSI-X vectors\n");

Or, something like this over this the function name.  Perhaps exposing
error code could be useful to the end user? If so then something like this:

  return dev_err_probe(&pdev->dev, err,
		       "Failed to allocate MSI-X vectors, err=%d\n", err);

Here and other errors where appropriate.

> +	for (i = 0; i < RP1_INT_END; i++) {
> +		unsigned int irq = irq_create_mapping(rp1->domain, i);
> +
> +		if (!irq) {
> +			dev_err(&pdev->dev, "failed to create irq mapping\n");

  dev_err(&pdev->dev, "Failed to create IRQ mapping\n");

To make the error message capitalisation consistent.

> +static const struct pci_device_id dev_id_table[] = {
> +	{ PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), },
> +	{ 0, }

  { }

Would probably be sufficient.

> +MODULE_AUTHOR("Phil Elwell <phil at raspberrypi.com>");
> +MODULE_AUTHOR("Andrea della Porta <andrea.porta at suse.com>");
> +MODULE_DESCRIPTION("RP1 wrapper");

  RaspberryPi RP1 misc device

To match the Kconfig comment in the above description or the one from the
"tristate" also in Kconfig.

Thank you for all the work here!

	Krzysztof


From lihuafei1 at huawei.com  Fri Mar 14 09:21:33 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:33 +0800
Subject: [PATCH 3/7] perf annotate: Add 'extract_reg_offset' callback function to extract register number and access offset
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-4-lihuafei1@huawei.com>

The assembly syntax for memory access instructions varies significantly
across different architectures, which makes it difficult to reuse the
code for extracting register numbers and access offsets in the function
annotate_get_insn_location().

To simplify the code, the extraction of register numbers and access
offsets from operands is written as a callback function for the
architecture, facilitating the implementation of architecture-specific
extraction logic.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 .../perf/arch/powerpc/annotate/instructions.c |  10 ++
 tools/perf/arch/x86/annotate/instructions.c   |  99 ++++++++++++++++
 tools/perf/util/annotate.c                    | 107 +-----------------
 tools/perf/util/disasm.c                      |   2 +
 tools/perf/util/disasm.h                      |   4 +
 5 files changed, 117 insertions(+), 105 deletions(-)

diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
index ca567cfdcbdb..fd6516890f3b 100644
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ b/tools/perf/arch/powerpc/annotate/instructions.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/compiler.h>
+#include <dwarf-regs.h>
 
 static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
 {
@@ -315,3 +316,12 @@ static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 
 	return 0;
 }
+
+static int extract_reg_offset_powerpc(struct arch *arch __maybe_unused,
+				      struct disasm_line *dl,
+				      const char *insn_str __maybe_unused, int insn_ops,
+				      struct annotated_op_loc *op_loc)
+{
+	get_powerpc_regs(dl->raw.raw_insn, insn_ops == INSN_OP_SOURCE, op_loc);
+	return 0;
+}
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index ae94b1f0b9cc..83e0fc4b9788 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -596,3 +596,102 @@ static void update_insn_state_x86(struct type_state *state,
 	/* Case 4. memory to memory transfers (not handled for now) */
 }
 #endif
+
+/*
+ * Get register number and access offset from the given instruction.
+ * It assumes AT&T x86 asm format like OFFSET(REG).  Maybe it needs
+ * to revisit the format when it handles different architecture.
+ * Fills @reg and @offset when return 0.
+ */
+static int extract_reg_offset(struct arch *arch, const char *str,
+			      struct annotated_op_loc *op_loc)
+{
+	char *p;
+	char *regname;
+
+	if (arch->objdump.register_char == 0)
+		return -1;
+
+	/*
+	 * It should start from offset, but it's possible to skip 0
+	 * in the asm.  So 0(%rax) should be same as (%rax).
+	 *
+	 * However, it also start with a segment select register like
+	 * %gs:0x18(%rbx).  In that case it should skip the part.
+	 */
+	if (*str == arch->objdump.register_char) {
+		/* FIXME: Handle other segment registers */
+		if (!strncmp(str, "%gs:", 4))
+			op_loc->segment = INSN_SEG_X86_GS;
+
+		while (*str && !isdigit(*str) &&
+		       *str != arch->objdump.memory_ref_char)
+			str++;
+	}
+
+	op_loc->offset = strtol(str, &p, 0);
+
+	p = strchr(p, arch->objdump.register_char);
+	if (p == NULL)
+		return -1;
+
+	regname = strdup(p);
+	if (regname == NULL)
+		return -1;
+
+	op_loc->reg1 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
+	free(regname);
+
+	/* Get the second register */
+	if (op_loc->multi_regs) {
+		p = strchr(p + 1, arch->objdump.register_char);
+		if (p == NULL)
+			return -1;
+
+		regname = strdup(p);
+		if (regname == NULL)
+			return -1;
+
+		op_loc->reg2 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
+		free(regname);
+	}
+	return 0;
+}
+
+static int extract_reg_offset_x86(struct arch *arch, struct disasm_line *dl __maybe_unused,
+				  const char *insn_str, int insn_ops __maybe_unused,
+				  struct annotated_op_loc *op_loc)
+{
+	if (insn_str == NULL)
+		return 0;
+
+	if (op_loc->mem_ref) {
+		extract_reg_offset(arch, insn_str, op_loc);
+	} else {
+		char *s, *p = NULL;
+
+		/* FIXME: Handle other segment registers */
+		if (!strncmp(insn_str, "%gs:", 4)) {
+			op_loc->segment = INSN_SEG_X86_GS;
+			op_loc->offset = strtol(insn_str + 4, &p, 0);
+			if (p && p != insn_str + 4)
+				op_loc->imm = true;
+			return 0;
+		}
+
+		s = strdup(insn_str);
+		if (s == NULL)
+			return -1;
+
+		if (*s == arch->objdump.register_char)
+			op_loc->reg1 = get_dwarf_regnum(s, arch->e_machine, arch->e_flags);
+		else if (*s == arch->objdump.imm_char) {
+			op_loc->offset = strtol(s + 1, &p, 0);
+			if (p && p != s + 1)
+				op_loc->imm = true;
+		}
+		free(s);
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 860ea6c72411..288200e4b2b5 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -2318,69 +2318,6 @@ int annotate_check_args(void)
 	return 0;
 }
 
-/*
- * Get register number and access offset from the given instruction.
- * It assumes AT&T x86 asm format like OFFSET(REG).  Maybe it needs
- * to revisit the format when it handles different architecture.
- * Fills @reg and @offset when return 0.
- */
-static int extract_reg_offset(struct arch *arch, const char *str,
-			      struct annotated_op_loc *op_loc)
-{
-	char *p;
-	char *regname;
-
-	if (arch->objdump.register_char == 0)
-		return -1;
-
-	/*
-	 * It should start from offset, but it's possible to skip 0
-	 * in the asm.  So 0(%rax) should be same as (%rax).
-	 *
-	 * However, it also start with a segment select register like
-	 * %gs:0x18(%rbx).  In that case it should skip the part.
-	 */
-	if (*str == arch->objdump.register_char) {
-		if (arch__is(arch, "x86")) {
-			/* FIXME: Handle other segment registers */
-			if (!strncmp(str, "%gs:", 4))
-				op_loc->segment = INSN_SEG_X86_GS;
-		}
-
-		while (*str && !isdigit(*str) &&
-		       *str != arch->objdump.memory_ref_char)
-			str++;
-	}
-
-	op_loc->offset = strtol(str, &p, 0);
-
-	p = strchr(p, arch->objdump.register_char);
-	if (p == NULL)
-		return -1;
-
-	regname = strdup(p);
-	if (regname == NULL)
-		return -1;
-
-	op_loc->reg1 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
-	free(regname);
-
-	/* Get the second register */
-	if (op_loc->multi_regs) {
-		p = strchr(p + 1, arch->objdump.register_char);
-		if (p == NULL)
-			return -1;
-
-		regname = strdup(p);
-		if (regname == NULL)
-			return -1;
-
-		op_loc->reg2 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
-		free(regname);
-	}
-	return 0;
-}
-
 /**
  * annotate_get_insn_location - Get location of instruction
  * @arch: the architecture info
@@ -2437,51 +2374,11 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
 		op_loc->reg1 = -1;
 		op_loc->reg2 = -1;
 
-		if (insn_str == NULL) {
-			if (!arch__is(arch, "powerpc"))
-				continue;
-		}
-
 		op_loc->mem_ref = mem_ref;
 		op_loc->multi_regs = multi_regs;
 
-		/*
-		 * For powerpc, call get_powerpc_regs function which extracts the
-		 * required fields for op_loc, ie reg1, reg2, offset from the
-		 * raw instruction.
-		 */
-		if (arch__is(arch, "powerpc")) {
-			get_powerpc_regs(dl->raw.raw_insn, !i, op_loc);
-		} else if (mem_ref) {
-			extract_reg_offset(arch, insn_str, op_loc);
-		} else {
-			char *s, *p = NULL;
-
-			if (arch__is(arch, "x86")) {
-				/* FIXME: Handle other segment registers */
-				if (!strncmp(insn_str, "%gs:", 4)) {
-					op_loc->segment = INSN_SEG_X86_GS;
-					op_loc->offset = strtol(insn_str + 4,
-								&p, 0);
-					if (p && p != insn_str + 4)
-						op_loc->imm = true;
-					continue;
-				}
-			}
-
-			s = strdup(insn_str);
-			if (s == NULL)
-				return -1;
-
-			if (*s == arch->objdump.register_char)
-				op_loc->reg1 = get_dwarf_regnum(s, arch->e_machine, arch->e_flags);
-			else if (*s == arch->objdump.imm_char) {
-				op_loc->offset = strtol(s + 1, &p, 0);
-				if (p && p != s + 1)
-					op_loc->imm = true;
-			}
-			free(s);
-		}
+		if (arch->extract_reg_offset(arch, dl, insn_str, i, op_loc))
+			return -1;
 	}
 
 	return 0;
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index d91526cff9df..905eceb824a4 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -155,6 +155,7 @@ static struct arch architectures[] = {
 #ifdef HAVE_LIBDW_SUPPORT
 		.update_insn_state = update_insn_state_x86,
 #endif
+		.extract_reg_offset = extract_reg_offset_x86,
 	},
 	{
 		.name = "powerpc",
@@ -162,6 +163,7 @@ static struct arch architectures[] = {
 #ifdef HAVE_LIBDW_SUPPORT
 		.update_insn_state = update_insn_state_powerpc,
 #endif
+		.extract_reg_offset = extract_reg_offset_powerpc,
 	},
 	{
 		.name = "riscv64",
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index c135db2416b5..44ac5aa892f7 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -16,6 +16,7 @@ struct symbol;
 struct data_loc_info;
 struct type_state;
 struct disasm_line;
+struct annotated_op_loc;
 
 struct arch {
 	const char	*name;
@@ -44,6 +45,9 @@ struct arch {
 				struct data_loc_info *dloc, Dwarf_Die *cu_die,
 				struct disasm_line *dl);
 #endif
+	int		(*extract_reg_offset)(struct arch *arch, struct disasm_line *dl,
+					      const char *insn_str, int insn_ops,
+					      struct annotated_op_loc *op_loc);
 	/** @e_machine: ELF machine associated with arch. */
 	unsigned int e_machine;
 	/** @e_flags: Optional ELF flags associated with arch. */
-- 
2.25.1



From lihuafei1 at huawei.com  Fri Mar 14 09:21:31 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:31 +0800
Subject: [PATCH 1/7] perf annotate: Handle arm64 load and store instructions
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-2-lihuafei1@huawei.com>

Add ldst_ops to handle load and store instructions in order to parse
the data types and offsets associated with PMU events for memory access
instructions. There are many variants of load and store instructions in
ARM64, making it difficult to match all of these instruction names
completely. Therefore, only the instruction prefixes are matched. The
prefix 'ld|st' covers most of the memory access instructions, 'cas|swp'
matches atomic instructions, and 'prf' matches memory prefetch
instructions.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/arch/arm64/annotate/instructions.c | 67 ++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index d465d093e7eb..c212eb7341bd 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -6,7 +6,8 @@
 
 struct arm64_annotate {
 	regex_t call_insn,
-		jump_insn;
+		jump_insn,
+		ldst_insn; /* load and store instruction */
 };
 
 static int arm64_mov__parse(struct arch *arch __maybe_unused,
@@ -67,6 +68,57 @@ static struct ins_ops arm64_mov_ops = {
 	.scnprintf = mov__scnprintf,
 };
 
+static int arm64_ldst__parse(struct arch *arch __maybe_unused,
+			     struct ins_operands *ops,
+			     struct map_symbol *ms __maybe_unused,
+			     struct disasm_line *dl __maybe_unused)
+{
+	char *s, *target;
+
+	/*
+	 * The part starting from the memory access annotation '[' is parsed
+	 * as 'target', while the part before it is parsed as 'source'.
+	 */
+	target = s = strchr(ops->raw, '[');
+	if (!s)
+		return -1;
+
+	while (s > ops->raw && *s != ',')
+		--s;
+
+	if (s == ops->raw)
+		return -1;
+
+	*s = '\0';
+	ops->source.raw = strdup(ops->raw);
+
+	*s = ',';
+	if (!ops->source.raw)
+		return -1;
+
+	ops->target.raw = strdup(target);
+	if (!ops->target.raw) {
+		zfree(ops->source.raw);
+		return -1;
+	}
+	ops->target.mem_ref = true;
+
+	return 0;
+}
+
+static int ldst__scnprintf(struct ins *ins, char *bf, size_t size,
+			   struct ins_operands *ops, int max_ins_name)
+{
+	return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
+			 ops->source.name ?: ops->source.raw,
+			 ops->target.name ?: ops->target.raw);
+}
+
+static struct ins_ops arm64_ldst_ops = {
+	.parse	   = arm64_ldst__parse,
+	.scnprintf = ldst__scnprintf,
+};
+
 static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
 {
 	struct arm64_annotate *arm = arch->priv;
@@ -77,6 +129,8 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
 		ops = &jump_ops;
 	else if (!regexec(&arm->call_insn, name, 2, match, 0))
 		ops = &call_ops;
+	else if (!regexec(&arm->ldst_insn, name, 2, match, 0))
+		ops = &arm64_ldst_ops;
 	else if (!strcmp(name, "ret"))
 		ops = &ret_ops;
 	else
@@ -107,6 +161,15 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 		      REG_EXTENDED);
 	if (err)
 		goto out_free_call;
+	/*
+	 * The ARM64 architecture has many variants of load/store instructions.
+	 * It is quite challenging to match all of them completely. Here, we
+	 * only match the prefixes of these instructions.
+	 */
+	err = regcomp(&arm->ldst_insn, "^(ld|st|cas|prf|swp)",
+		      REG_EXTENDED);
+	if (err)
+		goto out_free_jump;
 
 	arch->initialized = true;
 	arch->priv	  = arm;
@@ -117,6 +180,8 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 	arch->e_flags = 0;
 	return 0;
 
+out_free_jump:
+	regfree(&arm->jump_insn);
 out_free_call:
 	regfree(&arm->call_insn);
 out_free_arm:
-- 
2.25.1



From lihuafei1 at huawei.com  Fri Mar 14 09:21:35 2025
From: lihuafei1 at huawei.com (Li Huafei)
Date: Sat, 15 Mar 2025 00:21:35 +0800
Subject: [PATCH 5/7] perf annotate-data: Support instruction tracking for arm64
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <20250314162137.528204-6-lihuafei1@huawei.com>

Support for arm64 instruction tracing. This patch addresses the scenario
where type information cannot be found during multi-level pointer
references. For example, consider the vfs_ioctl() function:

 long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
     int error = -ENOTTY;

     if (!filp->f_op->unlocked_ioctl)
         goto out;

     error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
     if (error == -ENOIOCTLCMD)
         error = -ENOTTY;
 out:
     return error;
 }

The 'SYSCALL_DEFINE3(ioctl)' inlines vfs_ioctl, and the assembly
instructions for 'if (!filp->f_op->unlocked_ioctl)' are as follows:

 ldr     x0, [x21, #16]
 ldr     x3, [x0, #80]
 cbz     x3, ffff80008048e9a4

The first instruction loads the 'filp->f_op' pointer, and the second
instruction loads the 'filp->f_op->unlocked_ioctl' pointer. DWARF
generates type information for x21, but not for x0. Therefore, if
PMU sampling occurs on the second instruction, the corresponding data
type cannot be obtained. However, by using the type information and
offset from x21 in the first ldr instruction, we can infer the type
of x0 and, combined with the offset, resolve the accessed data member.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 tools/perf/arch/arm64/annotate/instructions.c | 44 ++++++++++++++++++-
 tools/perf/util/annotate-data.c               |  3 +-
 tools/perf/util/annotate-data.h               |  2 +-
 tools/perf/util/disasm.c                      |  3 ++
 4 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 54497b72a5c5..f70d93001fe7 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -215,7 +215,8 @@ extract_reg_offset_arm64(struct arch *arch __maybe_unused,
 	static bool regex_compiled;
 
 	if (!regex_compiled) {
-		regcomp(&reg_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
+		regcomp(&reg_off_regex,
+			"^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
 			REG_EXTENDED);
 		regex_compiled = true;
 	}
@@ -250,3 +251,44 @@ extract_reg_offset_arm64(struct arch *arch __maybe_unused,
 	free(str);
 	return 0;
 }
+
+#ifdef HAVE_LIBDW_SUPPORT
+static void
+update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
+			Dwarf_Die * cu_die __maybe_unused, struct disasm_line *dl)
+{
+	struct annotated_insn_loc loc;
+	struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
+	struct type_state_reg *tsr;
+	Dwarf_Die type_die;
+	int sreg, dreg;
+
+	if (strncmp(dl->ins.name, "ld", 2))
+		return;
+
+	if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
+		return;
+
+	sreg = get_arm64_regnum(dl->ops.source.raw);
+	if (sreg < 0)
+		return;
+	if (!has_reg_type(state, sreg))
+		return;
+
+	dreg = dst->reg1;
+	if (has_reg_type(state, dreg) && state->regs[dreg].ok &&
+	    state->regs[dreg].kind == TSR_KIND_TYPE &&
+	    dwarf_tag(&state->regs[dreg].type) == DW_TAG_pointer_type &&
+	    die_deref_ptr_type(&state->regs[dreg].type,
+			       dst->offset, &type_die)) {
+		tsr = &state->regs[sreg];
+		tsr->type = type_die;
+		tsr->kind = TSR_KIND_TYPE;
+		tsr->ok = true;
+
+		pr_debug_dtp("load [%x] %#x(reg%d) -> reg%d",
+			     (u32)dl->al.offset, dst->offset, dreg, sreg);
+		pr_debug_type_name(&tsr->type, tsr->kind);
+	}
+}
+#endif
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 976abedca09e..2bc8d646eedc 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -1293,7 +1293,8 @@ static enum type_match_result find_data_type_insn(struct data_loc_info *dloc,
 
 static int arch_supports_insn_tracking(struct data_loc_info *dloc)
 {
-	if ((arch__is(dloc->arch, "x86")) || (arch__is(dloc->arch, "powerpc")))
+	if ((arch__is(dloc->arch, "x86")) || (arch__is(dloc->arch, "powerpc")) ||
+	    (arch__is(dloc->arch, "arm64")))
 		return 1;
 	return 0;
 }
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 98c80b2268dd..717f394eb8f1 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -190,7 +190,7 @@ struct type_state_stack {
 };
 
 /* FIXME: This should be arch-dependent */
-#ifdef __powerpc__
+#if defined(__powerpc__) || defined(__aarch64__)
 #define TYPE_STATE_MAX_REGS  32
 #else
 #define TYPE_STATE_MAX_REGS  16
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 1035c60a8545..540981c155f9 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -129,6 +129,9 @@ static struct arch architectures[] = {
 		.name = "arm64",
 		.init = arm64__annotate_init,
 		.extract_reg_offset = extract_reg_offset_arm64,
+#ifdef HAVE_LIBDW_SUPPORT
+		.update_insn_state = update_insn_state_arm64,
+#endif
 	},
 	{
 		.name = "csky",
-- 
2.25.1



From lee at kernel.org  Fri Mar 14 01:42:27 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 14 Mar 2025 08:42:27 +0000
Subject: [PATCH v6 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <20250314080022.GH3645863@google.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com>
 <20250304-bcm59054-v6-6-ae8302358443@gmail.com>
 <20250313132036.GB3616286@google.com>
 <ef190ba8-a5c7-4a1a-90e6-2610de00e4ed@sirena.org.uk>
 <f363c1ce-8612-476e-a5d5-c3cb358bf50a@gmail.com>
 <20250314080022.GH3645863@google.com>
Message-ID: <20250314084227.GJ3645863@google.com>

On Fri, 14 Mar 2025, Lee Jones wrote:

> On Thu, 13 Mar 2025, Artur Weber wrote:
> 
> > On 13.03.2025 14:25, Mark Brown wrote:
> > > On Thu, Mar 13, 2025 at 01:20:36PM +0000, Lee Jones wrote:
> > > > On Tue, 04 Mar 2025, Artur Weber wrote:
> > > 
> > > > > +	if (id != bcm590xx->pmu_id) {
> > > > > +		dev_err(bcm590xx->dev,
> > > > > +			"Incorrect ID for %s: expected %x, got %x. Check your DT compatible.\n",
> > > > 
> > > > Isn't it more likely that the H/W this is being executed on is
> > > > unsupported?  If so, say that instead.
> > > 
> > > Given that the compatibles are device specific the driver shouldn't be
> > > binding if the device is unsupported.
> > 
> > Yes, the intention here is just to make sure that the DT compatible and
> > hardware ID match. Unsupported hardware would not have a DT compatible.
> 
> Right, so the user is utilising the correct compatible on the incorrect
> (most likely unsupported) platform.  When using a supported DTB on
> unknown hardware, the driver will bind but fail here.

If you simply drop the unnecessary "Check your DT compatible." part, not
only does it tidy up the print / line, it also covers more bases.

-- 
Lee Jones [???]


From angelogioacchino.delregno at collabora.com  Fri Mar 14 01:53:25 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Fri, 14 Mar 2025 09:53:25 +0100
Subject: [PATCH 1/5] pmic: mediatek: Add pmic auxadc driver
In-Reply-To: <20250314073307.25092-2-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-2-Lu.Tang@mediatek.com>
Message-ID: <90d1c0f2-b037-482e-a569-f75b713e3a71@collabora.com>

Il 14/03/25 08:32, Lu.Tang ha scritto:
> From: "Lu.Tang" <lu.tang at mediatek.com>
> 
> Add pmic mt6363 and mt6373 auxadc driver
> 

Can't you just add MT6363 and MT6373 support to the already present
mt6359-auxadc driver?!

Regards,
Angelo




From Lu.Tang at mediatek.com  Fri Mar 14 02:01:38 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:01:38 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggNC81XSBzcG1pOiBtZWRpYXRlazogbW9kaWZ5IHNw?=
 =?utf-8?Q?mi_dirver_for_mt8196?=
In-Reply-To: <20250314073307.25092-5-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-5-Lu.Tang@mediatek.com>
Message-ID: <SEZPR03MB689159D57E9A3C6310FF02B480D22@SEZPR03MB6891.apcprd03.prod.outlook.com>

Update email address

-----????-----
???: Lu.Tang <Lu.Tang at mediatek.com> 
????: 2025?3?14? 15:33
???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
??: [PATCH 4/5] spmi: mediatek: modify spmi dirver for mt8196

From: "Lu.Tang" <lu.tang at mediatek.com>

Modify spmi driver for mt8196 pmic.
Add pmif_s/pmif_m controller and rcs irq handler.

Signed-off-by: Lu.Tang <lu.tang at mediatek.com>
---
 drivers/spmi/spmi-mtk-pmif.c | 1040 +++++++++++++++++++++++++++++++---
 1 file changed, 976 insertions(+), 64 deletions(-)

diff --git a/drivers/spmi/spmi-mtk-pmif.c b/drivers/spmi/spmi-mtk-pmif.c index 160d36f7d238..36f7ef80e7c4 100644
--- a/drivers/spmi/spmi-mtk-pmif.c
+++ b/drivers/spmi/spmi-mtk-pmif.c
@@ -1,14 +1,20 @@
 // SPDX-License-Identifier: GPL-2.0
 //
-// Copyright (c) 2021 MediaTek Inc.
+// Copyright (c) 2024 MediaTek Inc.
 
 #include <linux/clk.h>
 #include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/sched/clock.h>
+#include <linux/sched/mm.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/spmi.h>
+#include <linux/irq.h>
 
 #define SWINF_IDLE	0x00
 #define SWINF_WFVLDCLR	0x06
@@ -21,14 +27,21 @@
 #define PMIF_CMD_EXT_REG_LONG	3
 
 #define PMIF_DELAY_US   10
-#define PMIF_TIMEOUT_US (10 * 1000)
+#define PMIF_TIMEOUT_US (100 * 1000)
 
 #define PMIF_CHAN_OFFSET 0x5
 
+#define PMIF_CAPS_VER_1 1
+#define PMIF_CAPS_VER_2 2
+
 #define PMIF_MAX_CLKS	3
 
 #define SPMI_OP_ST_BUSY 1
 
+#define SPMI_SOC_CHANNEL 2
+
+#define PMIF_IRQDESC(name) { #name, pmif_##name##_irq_handler, -1}
+
 struct ch_reg {
 	u32 ch_sta;
 	u32 wdata;
@@ -41,25 +54,53 @@ struct pmif_data {
 	const u32	*regs;
 	const u32	*spmimst_regs;
 	u32	soc_chan;
+	u32 caps;
 };
 
 struct pmif {
-	void __iomem	*base;
-	void __iomem	*spmimst_base;
+	void __iomem	*pmif_base[2];
+	void __iomem	*spmimst_base[2];
 	struct ch_reg	chan;
 	struct clk_bulk_data clks[PMIF_MAX_CLKS];
 	size_t nclks;
 	const struct pmif_data *data;
-	raw_spinlock_t lock;
+	raw_spinlock_t	lock_m;
+	raw_spinlock_t	lock_p;
+	struct spmi_controller  *spmic;
+	struct wakeup_source *pmif_m_Thread_lock;
+	struct wakeup_source *pmif_p_Thread_lock;
+	struct mutex pmif_m_mutex;
+	struct mutex pmif_p_mutex;
+	int		irq;
+	int		irq_p;
+	struct irq_domain	*domain;
+	struct irq_chip		irq_chip;
+	struct irq_chip		irq_chip_p;
+	int			rcs_irq;
+	int			rcs_irq_p;
+	struct mutex		rcs_m_irqlock;
+	struct mutex		rcs_p_irqlock;
+	bool	   *rcs_enable_hwirq;
+	int spmi_nack_irq;
+	int spmi_p_nack_irq;
 };
 
 static const char * const pmif_clock_names[] = {
 	"pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux",  };
 
+struct pmif_irq_desc {
+	const char *name;
+	irq_handler_t irq_handler;
+	int irq;
+};
+
 enum pmif_regs {
 	PMIF_INIT_DONE,
 	PMIF_INF_EN,
+	MD_AUXADC_RDATA_0_ADDR,
+	MD_AUXADC_RDATA_1_ADDR,
+	MD_AUXADC_RDATA_2_ADDR,
 	PMIF_ARB_EN,
 	PMIF_CMDISSUE_EN,
 	PMIF_TIMER_CTRL,
@@ -103,6 +144,11 @@ enum pmif_regs {
 	PMIF_SWINF_3_RDATA_31_0,
 	PMIF_SWINF_3_ACC,
 	PMIF_SWINF_3_VLD_CLR,
+	PMIF_PMIC_SWINF_0_PER,
+	PMIF_PMIC_SWINF_1_PER,
+	PMIF_ACC_VIO_INFO_0,
+	PMIF_ACC_VIO_INFO_1,
+	PMIF_ACC_VIO_INFO_2,
 };
 
 static const u32 mt6873_regs[] = {
@@ -201,6 +247,63 @@ static const u32 mt8195_regs[] = {
 	[PMIF_SWINF_3_STA] = 0x08E8,
 };
 
+static const u32 mt6xxx_regs[] = {
+	[PMIF_INIT_DONE] =			0x0000,
+	[PMIF_INF_EN] =				0x0024,
+	[MD_AUXADC_RDATA_0_ADDR] =		0x0080,
+	[MD_AUXADC_RDATA_1_ADDR] =		0x0084,
+	[MD_AUXADC_RDATA_2_ADDR] =		0x0088,
+	[PMIF_ARB_EN] =				0x0150,
+	[PMIF_CMDISSUE_EN] =			0x03B8,
+	[PMIF_TIMER_CTRL] =			0x03E4,
+	[PMIF_SPI_MODE_CTRL] =			0x0408,
+	[PMIF_IRQ_EVENT_EN_0] =			0x0420,
+	[PMIF_IRQ_FLAG_0] =			0x0428,
+	[PMIF_IRQ_CLR_0] =			0x042C,
+	[PMIF_IRQ_EVENT_EN_1] =			0x0430,
+	[PMIF_IRQ_FLAG_1] =			0x0438,
+	[PMIF_IRQ_CLR_1] =			0x043C,
+	[PMIF_IRQ_EVENT_EN_2] =			0x0440,
+	[PMIF_IRQ_FLAG_2] =			0x0448,
+	[PMIF_IRQ_CLR_2] =			0x044C,
+	[PMIF_IRQ_EVENT_EN_3] =			0x0450,
+	[PMIF_IRQ_FLAG_3] =			0x0458,
+	[PMIF_IRQ_CLR_3] =			0x045C,
+	[PMIF_IRQ_EVENT_EN_4] =			0x0460,
+	[PMIF_IRQ_FLAG_4] =			0x0468,
+	[PMIF_IRQ_CLR_4] =			0x046C,
+	[PMIF_WDT_EVENT_EN_0] =			0x0474,
+	[PMIF_WDT_FLAG_0] =			0x0478,
+	[PMIF_WDT_EVENT_EN_1] =			0x047C,
+	[PMIF_WDT_FLAG_1] =			0x0480,
+	[PMIF_SWINF_0_ACC] =			0x0800,
+	[PMIF_SWINF_0_WDATA_31_0] =		0x0804,
+	[PMIF_SWINF_0_RDATA_31_0] =		0x0814,
+	[PMIF_SWINF_0_VLD_CLR] =		0x0824,
+	[PMIF_SWINF_0_STA] =			0x0828,
+	[PMIF_SWINF_1_ACC] =			0x0840,
+	[PMIF_SWINF_1_WDATA_31_0] =		0x0844,
+	[PMIF_SWINF_1_RDATA_31_0] =		0x0854,
+	[PMIF_SWINF_1_VLD_CLR] =		0x0864,
+	[PMIF_SWINF_1_STA] =			0x0868,
+	[PMIF_SWINF_2_ACC] =			0x0880,
+	[PMIF_SWINF_2_WDATA_31_0] =		0x0884,
+	[PMIF_SWINF_2_RDATA_31_0] =		0x0894,
+	[PMIF_SWINF_2_VLD_CLR] =		0x08A4,
+	[PMIF_SWINF_2_STA] =			0x08A8,
+	[PMIF_SWINF_3_ACC] =			0x08C0,
+	[PMIF_SWINF_3_WDATA_31_0] =		0x08C4,
+	[PMIF_SWINF_3_RDATA_31_0] =		0x08D4,
+	[PMIF_SWINF_3_VLD_CLR] =		0x08E4,
+	[PMIF_SWINF_3_STA] =			0x08E8,
+	[PMIF_PMIC_SWINF_0_PER] =		0x093C,
+	[PMIF_PMIC_SWINF_1_PER] =		0x0940,
+	[PMIF_ACC_VIO_INFO_0] =			0x0980,
+	[PMIF_ACC_VIO_INFO_1] =			0x0984,
+	[PMIF_ACC_VIO_INFO_2] =			0x0988,
+
+};
+
 enum spmi_regs {
 	SPMI_OP_ST_CTRL,
 	SPMI_GRP_ID_EN,
@@ -262,26 +365,132 @@ static const u32 mt8195_spmi_regs[] = {
 	[SPMI_MST_DBG] = 0x00FC,
 };
 
-static u32 pmif_readl(struct pmif *arb, enum pmif_regs reg)
+static const u32 mt6853_spmi_regs[] = {
+	[SPMI_OP_ST_CTRL] =	0x0000,
+	[SPMI_GRP_ID_EN] =	0x0004,
+	[SPMI_OP_ST_STA] =	0x0008,
+	[SPMI_MST_SAMPL] =	0x000C,
+	[SPMI_MST_REQ_EN] =	0x0010,
+	[SPMI_MST_RCS_CTRL] =	0x0014,
+	[SPMI_SLV_3_0_EINT] =	0x0020,
+	[SPMI_SLV_7_4_EINT] =	0x0024,
+	[SPMI_SLV_B_8_EINT] =	0x0028,
+	[SPMI_SLV_F_C_EINT] =	0x002C,
+	[SPMI_REC_CTRL] =	0x0040,
+	[SPMI_REC0] =		0x0044,
+	[SPMI_REC1] =		0x0048,
+	[SPMI_REC2] =		0x004C,
+	[SPMI_REC3] =		0x0050,
+	[SPMI_REC4] =		0x0054,
+	[SPMI_REC_CMD_DEC] =	0x005C,
+	[SPMI_DEC_DBG] =	0x00F8,
+	[SPMI_MST_DBG] =	0x00FC,
+};
+
+enum {
+	IRQ_LAT_LIMIT_REACHED = 6,
+	IRQ_HW_MONITOR = 7,
+	IRQ_WDT = 8,
+	/* MT6833/MT6877 series */
+	IRQ_HW_MONITOR_V3 = 12,
+	IRQ_WDT_V3 = 13,
+	IRQ_ALL_PMIC_MPU_VIO_V3 = 14,
+	/* MT6885/MT6873 series */
+	IRQ_PMIC_CMD_ERR_PARITY_ERR = 17,
+	IRQ_PMIF_ACC_VIO = 20,
+	IRQ_PMIC_ACC_VIO = 21,
+	/* MT6985/MT6897 */
+	IRQ_PMIF_ACC_VIO_V3 = 27,
+	/* MT6853 series */
+	IRQ_PMIF_ACC_VIO_V2 = 31,
+};
+
+enum {
+	IRQ_PMIC_ACC_VIO_V2 = 0,
+	IRQ_PMIF_SWINF_ACC_ERR_0 = 3,
+	IRQ_PMIF_SWINF_ACC_ERR_1 = 4,
+	IRQ_PMIF_SWINF_ACC_ERR_2 = 5,
+	IRQ_PMIF_SWINF_ACC_ERR_3 = 6,
+	IRQ_PMIF_SWINF_ACC_ERR_4 = 7,
+	IRQ_PMIF_SWINF_ACC_ERR_5 = 8,
+	IRQ_HW_MONITOR_V2 = 18,
+	IRQ_WDT_V2 = 19,
+	IRQ_ALL_PMIC_MPU_VIO_V2 = 20,
+	IRQ_PMIF_SWINF_ACC_ERR_0_V2 = 23,
+	IRQ_PMIF_SWINF_ACC_ERR_1_V2 = 24,
+	IRQ_PMIF_SWINF_ACC_ERR_2_V2 = 25,
+	IRQ_PMIF_SWINF_ACC_ERR_3_V2 = 26,
+	IRQ_PMIF_SWINF_ACC_ERR_4_V2 = 27,
+	IRQ_PMIF_SWINF_ACC_ERR_5_V2 = 28,
+	/* MT6983/MT6879 */
+	IRQ_HW_MONITOR_V4 = 29,
+	IRQ_WDT_V4 = 30,
+	IRQ_ALL_PMIC_MPU_VIO_V4 = 31,
+};
+
+struct spmi_dev {
+	int exist;
+	int slvid;
+	unsigned int path;
+	unsigned short hwcid_addr;
+	unsigned char hwcid_val;
+};
+
+static struct spmi_dev spmidev[16];
+
+static void spmi_dev_parse(struct platform_device *pdev)
 {
-	return readl(arb->base + arb->data->regs[reg]);
+	int i = 0, j = 0, ret = 0;
+	u32 spmi_dev_mask = 0;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "spmi-dev-mask",
+				  &spmi_dev_mask);
+	if (ret)
+		dev_info(&pdev->dev, "No spmi-dev-mask found in dts, default all PMIC 
+on SPMI-M\n");
+
+	j = spmi_dev_mask;
+	for (i = 0; i < 16; i++) {
+		if (j & BIT(i))
+			spmidev[i].path = 1; /* slvid i is in path p */
+		else
+			spmidev[i].path = 0;
+	}
+}
+
+unsigned long long get_current_time_ms(void) {
+	unsigned long long cur_ts;
+
+	cur_ts = sched_clock();
+	do_div(cur_ts, 1000000);
+	return cur_ts;
 }
 
-static void pmif_writel(struct pmif *arb, u32 val, enum pmif_regs reg)
+static u32 pmif_readl(void __iomem *addr, struct pmif *arb, enum 
+pmif_regs reg)
 {
-	writel(val, arb->base + arb->data->regs[reg]);
+	return readl(addr + arb->data->regs[reg]);
 }
 
-static void mtk_spmi_writel(struct pmif *arb, u32 val, enum spmi_regs reg)
+static void pmif_writel(void __iomem *addr, struct pmif *arb, u32 val, 
+enum pmif_regs reg)
 {
-	writel(val, arb->spmimst_base + arb->data->spmimst_regs[reg]);
+	writel(val, addr + arb->data->regs[reg]);
 }
 
-static bool pmif_is_fsm_vldclr(struct pmif *arb)
+static void mtk_spmi_writel(void __iomem *addr, struct pmif *arb, u32 
+val, enum spmi_regs reg) {
+	writel(val, addr + arb->data->spmimst_regs[reg]); }
+
+static u32 mtk_spmi_readl(void __iomem *addr, struct pmif *arb, enum 
+spmi_regs reg) {
+	return readl(addr + arb->data->spmimst_regs[reg]); }
+
+static bool pmif_is_fsm_vldclr(void __iomem *addr, struct pmif *arb)
 {
 	u32 reg_rdata;
 
-	reg_rdata = pmif_readl(arb, arb->chan.ch_sta);
+	reg_rdata = pmif_readl(addr, arb, arb->chan.ch_sta);
 
 	return GET_SWINF(reg_rdata) == SWINF_WFVLDCLR;  } @@ -298,8 +507,8 @@ static int pmif_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
 
 	cmd = opc - SPMI_CMD_RESET;
 
-	mtk_spmi_writel(arb, (cmd << 0x4) | sid, SPMI_OP_ST_CTRL);
-	ret = readl_poll_timeout_atomic(arb->spmimst_base + arb->data->spmimst_regs[SPMI_OP_ST_STA],
+	mtk_spmi_writel(arb->spmimst_base[spmidev[sid].path], arb, (cmd << 0x4) | sid, SPMI_OP_ST_CTRL);
+	ret = readl_poll_timeout_atomic(arb->spmimst_base[spmidev[sid].path] + 
+arb->data->spmimst_regs[SPMI_OP_ST_STA],
 					rdata, (rdata & SPMI_OP_ST_BUSY) == SPMI_OP_ST_BUSY,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0)
@@ -315,7 +524,7 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	struct ch_reg *inf_reg;
 	int ret;
 	u32 data, cmd;
-	unsigned long flags;
+	unsigned long flags_m;
 
 	/* Check for argument validation. */
 	if (sid & ~0xf) {
@@ -336,31 +545,31 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	else
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&arb->lock, flags);
+	raw_spin_lock_irqsave(&arb->lock_m, flags_m);
 	/* Wait for Software Interface FSM state to be IDLE. */
 	inf_reg = &arb->chan;
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path] + 
+arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_IDLE,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
 		/* set channel ready if the data has transferred */
-		if (pmif_is_fsm_vldclr(arb))
-			pmif_writel(arb, 1, inf_reg->ch_rdy);
-		raw_spin_unlock_irqrestore(&arb->lock, flags);
+		if (pmif_is_fsm_vldclr(arb->pmif_base[spmidev[sid].path], arb))
+			pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, inf_reg->ch_rdy);
+		raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
 		return ret;
 	}
 
 	/* Send the command. */
 	cmd = (opc << 30) | (sid << 24) | ((len - 1) << 16) | addr;
-	pmif_writel(arb, cmd, inf_reg->ch_send);
-	raw_spin_unlock_irqrestore(&arb->lock, flags);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, cmd, inf_reg->ch_send);
+	raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 
 	/*
 	 * Wait for Software Interface FSM state to be WFVLDCLR,
 	 * read the data and clear the valid flag.
 	 */
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path]  + 
+arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_WFVLDCLR,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
@@ -368,9 +577,9 @@ static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 		return ret;
 	}
 
-	data = pmif_readl(arb, inf_reg->rdata);
+	data = pmif_readl(arb->pmif_base[spmidev[sid].path], arb, 
+inf_reg->rdata);
 	memcpy(buf, &data, len);
-	pmif_writel(arb, 1, inf_reg->ch_rdy);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, 
+inf_reg->ch_rdy);
 
 	return 0;
 }
@@ -382,7 +591,7 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	struct ch_reg *inf_reg;
 	int ret;
 	u32 data, wdata, cmd;
-	unsigned long flags;
+	unsigned long flags_m;
 
 	/* Check for argument validation. */
 	if (unlikely(sid & ~0xf)) {
@@ -409,27 +618,27 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	/* Set the write data. */
 	memcpy(&wdata, buf, len);
 
-	raw_spin_lock_irqsave(&arb->lock, flags);
+	raw_spin_lock_irqsave(&arb->lock_m, flags_m);
 	/* Wait for Software Interface FSM state to be IDLE. */
 	inf_reg = &arb->chan;
-	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
+	ret = readl_poll_timeout_atomic(arb->pmif_base[spmidev[sid].path] + 
+arb->data->regs[inf_reg->ch_sta],
 					data, GET_SWINF(data) == SWINF_IDLE,
 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
 	if (ret < 0) {
 		/* set channel ready if the data has transferred */
-		if (pmif_is_fsm_vldclr(arb))
-			pmif_writel(arb, 1, inf_reg->ch_rdy);
-		raw_spin_unlock_irqrestore(&arb->lock, flags);
+		if (pmif_is_fsm_vldclr(arb->pmif_base[spmidev[sid].path], arb))
+			pmif_writel(arb->pmif_base[spmidev[sid].path], arb, 1, inf_reg->ch_rdy);
+		raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
 		return ret;
 	}
 
-	pmif_writel(arb, wdata, inf_reg->wdata);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, wdata, 
+inf_reg->wdata);
 
 	/* Send the command. */
 	cmd = (opc << 30) | BIT(29) | (sid << 24) | ((len - 1) << 16) | addr;
-	pmif_writel(arb, cmd, inf_reg->ch_send);
-	raw_spin_unlock_irqrestore(&arb->lock, flags);
+	pmif_writel(arb->pmif_base[spmidev[sid].path], arb, cmd, inf_reg->ch_send);
+	raw_spin_unlock_irqrestore(&arb->lock_m, flags_m);
 
 	return 0;
 }
@@ -437,15 +646,642 @@ static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,  static const struct pmif_data mt6873_pmif_arb = {
 	.regs = mt6873_regs,
 	.spmimst_regs = mt6873_spmi_regs,
-	.soc_chan = 2,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_1,
 };
 
 static const struct pmif_data mt8195_pmif_arb = {
 	.regs = mt8195_regs,
 	.spmimst_regs = mt8195_spmi_regs,
-	.soc_chan = 2,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_1,
 };
+static const struct pmif_data mt6xxx_pmif_arb = {
+	.regs = mt6xxx_regs,
+	.spmimst_regs = mt6853_spmi_regs,
+	.soc_chan = SPMI_SOC_CHANNEL,
+	.caps = PMIF_CAPS_VER_2,
+};
+static void mtk_spmi_readl_datas(struct pmif *arb, int id, unsigned int *spmi_nack,
+		unsigned int *spmi_nack_data, unsigned int *spmi_rcs_nack,
+		unsigned int *spmi_debug_nack, unsigned int *spmi_mst_nack) {
+	if (id < 0 || id >= PMIF_CAPS_VER_2) {
+		dev_err(&arb->spmic->dev, "%s Invalid id: %d\n", __func__, id);
+		return;
+	}
+	*spmi_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC0);
+	*spmi_nack_data = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC1);
+	*spmi_rcs_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_REC_CMD_DEC);
+	*spmi_debug_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, SPMI_DEC_DBG);
+	*spmi_mst_nack = mtk_spmi_readl(arb->spmimst_base[id], arb, 
+SPMI_MST_DBG); } static irqreturn_t spmi_nack_irq_handler(int irq, void 
+*data) {
+	struct pmif *arb = data;
+	int sid = 0;
+	unsigned int spmi_nack = 0, spmi_p_nack = 0, spmi_nack_data = 0, spmi_p_nack_data = 0;
+	unsigned int spmi_rcs_nack = 0, spmi_debug_nack = 0, spmi_mst_nack = 0,
+		spmi_p_rcs_nack = 0, spmi_p_debug_nack = 0, spmi_p_mst_nack = 0;
+	u8 rdata = 0, rdata1 = 0;
+	unsigned short mt6316INTSTA = 0x240, hwcidaddr_mt6316 = 0x209, VIO18_SWITCH_6363 = 0x53,
+		hwcidaddr_mt6363 = 0x9;
+
+	mutex_lock(&arb->pmif_m_mutex);
+
+	mtk_spmi_readl_datas(arb, 0, &spmi_nack, &spmi_nack_data, &spmi_rcs_nack,
+		&spmi_debug_nack, &spmi_mst_nack);
+	if (!IS_ERR(arb->spmimst_base[1])) {
+		mtk_spmi_readl_datas(arb, 1, &spmi_p_nack, &spmi_p_nack_data, &spmi_p_rcs_nack,
+			&spmi_p_debug_nack, &spmi_p_mst_nack);
+	}
+	if ((spmi_nack & 0xD8) || (spmi_p_nack & 0xD8)) {
+		if (spmi_p_nack & 0xD8) {
+			for (sid = 0x8; sid >= 0x6; sid--) {
+				arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, sid,
+					mt6316INTSTA, &rdata, 1);
+				arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, sid,
+					hwcidaddr_mt6316, &rdata1, 1);
+				dev_notice(&arb->spmic->dev, "%s slvid 0x%x INT_RAW_STA 0x%x cid 0x%x\n",
+					__func__, sid, rdata, rdata1);
+			}
+		}
+		dev_notice(&arb->spmic->dev, "%s spmi transaction fail irq triggered", __func__);
+		dev_notice(&arb->spmic->dev, "SPMI_REC0 m/p:0x%x/0x%x SPMI_REC1 m/p 0x%x/0x%x\n",
+			spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+	}
+	if ((spmi_rcs_nack & 0xC0000) || (spmi_p_rcs_nack & 0xC0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_rcs transaction fail irq triggered SPMI_REC_CMD_DEC m/p:0x%x/0x%x\n",
+			__func__, spmi_rcs_nack, spmi_p_rcs_nack);
+	}
+	if ((spmi_debug_nack & 0xF0000) || (spmi_p_debug_nack & 0xF0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_debug_nack transaction fail irq triggered SPMI_DEC_DBG m/p: 0x%x/0x%x\n",
+			__func__, spmi_debug_nack, spmi_p_debug_nack);
+	}
+	if ((spmi_mst_nack & 0xC0000) || (spmi_p_mst_nack & 0xC0000)) {
+		dev_notice(&arb->spmic->dev, "%s spmi_mst_nack transaction fail irq triggered SPMI_MST_DBG m/p: 0x%x/0x%x\n",
+		__func__, spmi_mst_nack, spmi_p_mst_nack);
+	}
 
+	if ((spmi_nack & 0x20) || (spmi_p_nack & 0x20)) {
+		dev_notice(&arb->spmic->dev, "%s spmi transaction fail (Read) irq triggered", __func__);
+		dev_notice(&arb->spmic->dev, "SPMI_REC0 m/p:0x%x/0x%x SPMI_REC1 m/p 0x%x/0x%x\n",
+			spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+	}
+
+	if ((spmi_nack & 0xF8) || (spmi_rcs_nack & 0xC0000) ||
+		(spmi_debug_nack & 0xF0000) || (spmi_mst_nack & 0xC0000)) {
+		mtk_spmi_writel(arb->spmimst_base[0], arb, 0x3, SPMI_REC_CTRL);
+	} else if ((spmi_p_nack & 0xF8) || (spmi_p_rcs_nack & 0xC0000) ||
+		(spmi_p_debug_nack & 0xF0000) || (spmi_p_mst_nack & 0xC0000)) {
+		if (spmi_p_nack & 0xD8) {
+			dev_notice(&arb->spmic->dev, "%s SPMI_REC0 m/p:0x%x/0x%x, SPMI_REC1 m/p:0x%x/0x%x\n",
+				__func__, spmi_nack, spmi_p_nack, spmi_nack_data, spmi_p_nack_data);
+			dev_notice(&arb->spmic->dev, "%s SPMI_REC_CMD_DEC m/p:0x%x/0x%x\n", __func__,
+				spmi_rcs_nack, spmi_p_rcs_nack);
+			dev_notice(&arb->spmic->dev, "%s SPMI_DEC_DBG m/p:0x%x/0x%x\n", __func__,
+				spmi_debug_nack, spmi_p_debug_nack);
+			dev_notice(&arb->spmic->dev, "%s SPMI_MST_DBG m/p:0x%x/0x%x\n", __func__,
+				spmi_mst_nack, spmi_p_mst_nack);
+			arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, 0x4,
+				hwcidaddr_mt6363, &rdata, 1);
+			arb->spmic->read_cmd(arb->spmic, SPMI_CMD_EXT_READL, 0x4,
+				VIO18_SWITCH_6363, &rdata1, 1);
+			dev_notice(&arb->spmic->dev, "%s 6363 CID/VIO18_SWITCH 0x%x/0x%x\n", __func__, rdata, rdata1);
+		}
+		mtk_spmi_writel(arb->spmimst_base[1], arb, 0x3, SPMI_REC_CTRL);
+	} else
+		dev_notice(&arb->spmic->dev, "%s IRQ not cleared\n", __func__);
+
+	mutex_unlock(&arb->pmif_m_mutex);
+
+	return IRQ_HANDLED;
+}
+static int spmi_nack_irq_register(struct platform_device *pdev,
+		struct pmif *arb, int irq)
+{
+	int ret = 0;
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+				spmi_nack_irq_handler,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_SHARED,
+				"spmi_nack_irq", arb);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "request %s irq fail\n",
+			"spmi_nack_irq");
+	}
+	return ret;
+}
+static void rcs_irq_lock(struct irq_data *data) {
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	mutex_lock(&arb->rcs_m_irqlock);
+}
+static void rcs_irq_sync_unlock(struct irq_data *data) {
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	mutex_unlock(&arb->rcs_m_irqlock);
+}
+static void rcs_irq_enable(struct irq_data *data) {
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	arb->rcs_enable_hwirq[hwirq] = true;
+}
+static void rcs_irq_disable(struct irq_data *data) {
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	arb->rcs_enable_hwirq[hwirq] = false;
+}
+static int rcs_irq_set_wake(struct irq_data *data, unsigned int on) {
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	return irq_set_irq_wake(arb->rcs_irq, on); } static int 
+rcs_irq_p_set_wake(struct irq_data *data, unsigned int on) {
+	struct pmif *arb = irq_data_get_irq_chip_data(data);
+	return irq_set_irq_wake(arb->rcs_irq_p, on); } static const struct 
+irq_chip rcs_irq_chip = {
+	.name			= "rcs_irq",
+	.irq_bus_lock		= rcs_irq_lock,
+	.irq_bus_sync_unlock	= rcs_irq_sync_unlock,
+	.irq_enable		= rcs_irq_enable,
+	.irq_disable		= rcs_irq_disable,
+	.irq_set_wake 		= rcs_irq_set_wake,
+};
+
+static const struct irq_chip rcs_irq_chip_p = {
+	.name			= "rcs_irq_p",
+	.irq_bus_lock		= rcs_irq_lock,
+	.irq_bus_sync_unlock	= rcs_irq_sync_unlock,
+	.irq_enable		= rcs_irq_enable,
+	.irq_disable		= rcs_irq_disable,
+	.irq_set_wake 		= rcs_irq_p_set_wake,
+};
+static int rcs_irq_map(struct irq_domain *d, unsigned int virq,
+			irq_hw_number_t hw)
+{
+	struct pmif *arb = d->host_data;
+	irq_set_chip_data(virq, arb);
+	irq_set_chip(virq, &arb->irq_chip);
+	irq_set_nested_thread(virq, 1);
+	irq_set_parent(virq, arb->rcs_irq);
+	irq_set_noprobe(virq);
+	return 0;
+}
+static const struct irq_domain_ops rcs_irq_domain_ops = {
+	.map	= rcs_irq_map,
+	.xlate	= irq_domain_xlate_onetwocell,
+};
+static void pmif_lat_limit_reached_irq_handler(int irq, void *data) { } 
+static void pmif_acc_vio_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF ACC violation debug info\n");
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF-M\n");
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_0 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_0));
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_1 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_1));
+	dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_2 = 0x%x\n", pmif_readl(arb->pmif_base[0],
+		arb, PMIF_ACC_VIO_INFO_2));
+	if (!IS_ERR(arb->pmif_base[1])) {
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF-P\n");
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_0 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_0));
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_1 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_1));
+		dev_notice(&arb->spmic->dev, "[PMIF]:PMIF_ACC_VIO_INFO_2 = 0x%x\n", pmif_readl(arb->pmif_base[1],
+			arb, PMIF_ACC_VIO_INFO_2));
+	}
+}
+static void pmif_wdt_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	pmif_writel(arb->pmif_base[0], arb, 0x40000000, PMIF_IRQ_CLR_0);
+	if (!IS_ERR(arb->pmif_base[1]))
+		pmif_writel(arb->pmif_base[1], arb, 0x40000000, PMIF_IRQ_CLR_0);
+	dev_notice(&arb->spmic->dev, "[PMIF]:WDT IRQ HANDLER DONE\n"); } 
+static void pmif_pmif_acc_vio_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmif_acc_vio"); #endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmif_acc_vio\n"); } static void 
+pmif_pmic_acc_vio_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmic_acc_vio"); #endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmic_acc_vio\n"); } static void 
+pmif_cmd_err_parity_err_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:parity error"); #endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:parity error\n"); } static void 
+pmif_hw_monitor_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+#if (IS_ENABLED(CONFIG_MTK_AEE_FEATURE))
+	aee_kernel_warning("PMIF", "PMIF:pmif_hw_monitor_match"); #endif
+	dev_notice(&arb->spmic->dev, "[PMIF]:pmif_hw_monitor_match\n");
+}
+static void pmif_swinf_acc_err_irq_handler(int irq, void *data, u32 
+val) {
+	struct pmif *arb = data;
+	pmif_writel(arb->pmif_base[0], arb, val, MD_AUXADC_RDATA_0_ADDR);
+	pmif_writel(arb->pmif_base[0], arb, (u32)get_current_time_ms(), MD_AUXADC_RDATA_1_ADDR);
+	if (!IS_ERR(arb->pmif_base[1])) {
+		pmif_writel(arb->pmif_base[1], arb, val, MD_AUXADC_RDATA_0_ADDR);
+		pmif_writel(arb->pmif_base[1], arb, (u32)get_current_time_ms(), MD_AUXADC_RDATA_1_ADDR);
+	}
+	dev_notice(&arb->spmic->dev, "[PMIF]:SWINF_ACC_ERR:%d\n", val); } 
+static irqreturn_t pmif_event_0_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_0);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_0);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIF_ACC_VIO_V3:
+				pmif_acc_vio_irq_handler(irq, data);
+			break;
+			case IRQ_WDT_V4:
+				pmif_wdt_irq_handler(irq, data);
+			break;
+			case IRQ_ALL_PMIC_MPU_VIO_V4:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+			break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_0);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_0);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_1_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_1);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_1);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_1);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_1);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_2_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_2);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_2);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIC_CMD_ERR_PARITY_ERR:
+				pmif_cmd_err_parity_err_irq_handler(irq, data);
+			break;
+			case IRQ_PMIF_ACC_VIO_V2:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+			break;
+			case IRQ_PMIC_ACC_VIO:
+				pmif_pmic_acc_vio_irq_handler(irq, data);
+			break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_2);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_2);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_3_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_3);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_3);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			case IRQ_PMIF_SWINF_ACC_ERR_0:
+			case IRQ_PMIF_SWINF_ACC_ERR_0_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x0);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_1:
+			case IRQ_PMIF_SWINF_ACC_ERR_1_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x1);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_2:
+			case IRQ_PMIF_SWINF_ACC_ERR_2_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x2);
+				break;
+			case IRQ_LAT_LIMIT_REACHED:
+			case IRQ_PMIF_SWINF_ACC_ERR_3_V2:
+				if (arb->data->caps == 1)
+					pmif_lat_limit_reached_irq_handler(irq, data);
+				else
+					pmif_swinf_acc_err_irq_handler(irq, data, 0x3);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_4:
+			case IRQ_PMIF_SWINF_ACC_ERR_4_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x4);
+				break;
+			case IRQ_PMIF_SWINF_ACC_ERR_5:
+			case IRQ_PMIF_SWINF_ACC_ERR_5_V2:
+				pmif_swinf_acc_err_irq_handler(irq, data, 0x5);
+				break;
+			case IRQ_HW_MONITOR_V2:
+			case IRQ_HW_MONITOR_V3:
+				pmif_hw_monitor_irq_handler(irq, data);
+				break;
+			case IRQ_WDT_V2:
+			case IRQ_WDT_V3:
+				pmif_wdt_irq_handler(irq, data);
+				break;
+			case IRQ_PMIC_ACC_VIO_V2:
+				pmif_pmic_acc_vio_irq_handler(irq, data);
+				break;
+			case IRQ_ALL_PMIC_MPU_VIO_V2:
+			case IRQ_ALL_PMIC_MPU_VIO_V3:
+				pmif_pmif_acc_vio_irq_handler(irq, data);
+				break;
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n", __func__, idx);
+				break;
+			}
+			if (irq_f) {
+				if ((!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0))) &&
+					(!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0_V2))))
+					pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_3);
+			} else if (irq_f_p) {
+				if ((!(irq_f_p & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0))) &&
+					(!(irq_f & (0x1 << IRQ_PMIF_SWINF_ACC_ERR_0_V2))))
+					pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_3);
+			} else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static irqreturn_t pmif_event_4_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	int irq_f = 0, irq_f_p = 0, idx = 0;
+	__pm_stay_awake(arb->pmif_m_Thread_lock);
+	mutex_lock(&arb->pmif_m_mutex);
+	irq_f = pmif_readl(arb->pmif_base[0], arb, PMIF_IRQ_FLAG_4);
+	if (!IS_ERR(arb->pmif_base[1]))
+		irq_f_p = pmif_readl(arb->pmif_base[1], arb, PMIF_IRQ_FLAG_4);
+	if ((irq_f == 0) && (irq_f_p == 0)) {
+		mutex_unlock(&arb->pmif_m_mutex);
+		__pm_relax(arb->pmif_m_Thread_lock);
+		return IRQ_NONE;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		if (((irq_f & (0x1 << idx)) != 0) || ((irq_f_p & (0x1 << idx)) != 0)) {
+			switch (idx) {
+			default:
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] triggered\n",
+					__func__, idx);
+			break;
+			}
+			if (irq_f)
+				pmif_writel(arb->pmif_base[0], arb, irq_f, PMIF_IRQ_CLR_4);
+			else if (irq_f_p)
+				pmif_writel(arb->pmif_base[1], arb, irq_f_p, PMIF_IRQ_CLR_4);
+			else
+				dev_notice(&arb->spmic->dev, "%s IRQ[%d] is not cleared due to empty flags\n",
+					__func__, idx);
+			break;
+		}
+	}
+	mutex_unlock(&arb->pmif_m_mutex);
+	__pm_relax(arb->pmif_m_Thread_lock);
+	return IRQ_HANDLED;
+}
+static struct pmif_irq_desc pmif_event_irq[] = {
+	PMIF_IRQDESC(event_0),
+	PMIF_IRQDESC(event_1),
+	PMIF_IRQDESC(event_2),
+	PMIF_IRQDESC(event_3),
+	PMIF_IRQDESC(event_4),
+};
+static void pmif_irq_register(struct platform_device *pdev,
+		struct pmif *arb, int irq)
+{
+	int i = 0, ret = 0;
+	u32 irq_event_en[5] = {0};
+	for (i = 0; i < ARRAY_SIZE(pmif_event_irq); i++) {
+		if (!pmif_event_irq[i].name)
+			continue;
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+				pmif_event_irq[i].irq_handler,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_SHARED,
+				pmif_event_irq[i].name, arb);
+		if (ret < 0) {
+			dev_notice(&pdev->dev, "request %s irq fail\n",
+				pmif_event_irq[i].name);
+			continue;
+		}
+		pmif_event_irq[i].irq = irq;
+	}
+	ret = of_property_read_u32_array(pdev->dev.of_node, "irq-event-en",
+		irq_event_en, ARRAY_SIZE(irq_event_en));
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[0] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_0), PMIF_IRQ_EVENT_EN_0);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[1] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_1), PMIF_IRQ_EVENT_EN_1);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[2] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_2), PMIF_IRQ_EVENT_EN_2);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[3] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_3), PMIF_IRQ_EVENT_EN_3);
+	pmif_writel(arb->pmif_base[0], arb, irq_event_en[4] | pmif_readl(arb->pmif_base[0],
+		arb, PMIF_IRQ_EVENT_EN_4), PMIF_IRQ_EVENT_EN_4);
+	if (!IS_ERR(arb->pmif_base[1])) {
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[0] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_0), PMIF_IRQ_EVENT_EN_0);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[1] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_1), PMIF_IRQ_EVENT_EN_1);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[2] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_2), PMIF_IRQ_EVENT_EN_2);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[3] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_3), PMIF_IRQ_EVENT_EN_3);
+		pmif_writel(arb->pmif_base[1], arb, irq_event_en[4] | pmif_readl(arb->pmif_base[1],
+			arb, PMIF_IRQ_EVENT_EN_4), PMIF_IRQ_EVENT_EN_4);
+	}
+}
+static irqreturn_t rcs_irq_handler(int irq, void *data) {
+	struct pmif *arb = data;
+	unsigned int slv_irq_sta, slv_irq_sta_p;
+	int i;
+
+	for (i = 0; i < SPMI_MAX_SLAVE_ID; i++) {
+		slv_irq_sta = mtk_spmi_readl(arb->spmimst_base[0], arb, SPMI_SLV_3_0_EINT + (i / 4));
+		slv_irq_sta = (slv_irq_sta >> ((i % 4) * 8)) & 0xFF;
+		if (!IS_ERR(arb->spmimst_base[1])) {
+			slv_irq_sta_p = mtk_spmi_readl(arb->spmimst_base[1], arb, SPMI_SLV_3_0_EINT + (i / 4));
+			slv_irq_sta_p = (slv_irq_sta_p >> ((i % 4) * 8)) & 0xFF;
+		}
+		if (slv_irq_sta) {
+			mtk_spmi_writel(arb->spmimst_base[0], arb, (0xFF << ((i % 4) * 8)),
+					SPMI_SLV_3_0_EINT + (i / 4));
+			if (arb->rcs_enable_hwirq[i] && slv_irq_sta) {
+				dev_info(&arb->spmic->dev,
+					"hwirq=%d, sta=0x%x\n", i, slv_irq_sta);
+				handle_nested_irq(irq_find_mapping(arb->domain, i));
+			}
+		} else {
+			if (!IS_ERR(arb->spmimst_base[1])) {
+				mtk_spmi_writel(arb->spmimst_base[1], arb, (0xFF << ((i % 4) * 8)),
+					SPMI_SLV_3_0_EINT + (i / 4));
+				if (arb->rcs_enable_hwirq[i] && slv_irq_sta_p) {
+					dev_info(&arb->spmic->dev,
+						"hwirq=%d, sta=0x%x\n", i, slv_irq_sta_p);
+					handle_nested_irq(irq_find_mapping(arb->domain, i));
+				}
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+static int rcs_irq_register(struct platform_device *pdev,
+			    struct pmif *arb, int irq)
+{
+	int i, ret = 0;
+	mutex_init(&arb->rcs_m_irqlock);
+	mutex_init(&arb->rcs_p_irqlock);
+	arb->rcs_enable_hwirq = devm_kcalloc(&pdev->dev, SPMI_MAX_SLAVE_ID,
+					     sizeof(*arb->rcs_enable_hwirq),
+					     GFP_KERNEL);
+	if (!arb->rcs_enable_hwirq)
+		return -ENOMEM;
+	if (arb->rcs_irq == irq)
+		arb->irq_chip = rcs_irq_chip;
+	else if (arb->rcs_irq_p == irq)
+		arb->irq_chip_p = rcs_irq_chip_p;
+	else
+		dev_notice(&pdev->dev, "no rcs irq %d registered\n", irq);
+	arb->domain = irq_domain_add_linear(pdev->dev.of_node,
+					    SPMI_MAX_SLAVE_ID,
+					    &rcs_irq_domain_ops, arb);
+	if (!arb->domain) {
+		dev_notice(&pdev->dev, "Failed to create IRQ domain\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < SPMI_MAX_SLAVE_ID; i++) {
+		mtk_spmi_writel(arb->spmimst_base[0], arb, (0xFF << ((i % 4) * 8)),
+				SPMI_SLV_3_0_EINT + (i / 4));
+		if (!IS_ERR(arb->spmimst_base[1])) {
+			mtk_spmi_writel(arb->spmimst_base[1], arb, (0xFF << ((i % 4) * 8)),
+				SPMI_SLV_3_0_EINT + (i / 4));
+		}
+	}
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					rcs_irq_handler, IRQF_ONESHOT,
+					rcs_irq_chip.name, arb);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "Failed to request IRQ=%d, ret = %d\n",
+			   irq, ret);
+		return ret;
+	}
+	enable_irq_wake(irq);
+	return ret;
+}
 static int mtk_spmi_probe(struct platform_device *pdev)  {
 	struct pmif *arb;
@@ -457,41 +1293,50 @@ static int mtk_spmi_probe(struct platform_device *pdev)
 	if (IS_ERR(ctrl))
 		return PTR_ERR(ctrl);
 
+	ctrl->cmd = pmif_arb_cmd;
+	ctrl->read_cmd = pmif_spmi_read_cmd;
+	ctrl->write_cmd = pmif_spmi_write_cmd;
 	arb = spmi_controller_get_drvdata(ctrl);
+	arb->spmic = ctrl;
 	arb->data = device_get_match_data(&pdev->dev);
 	if (!arb->data) {
 		dev_err(&pdev->dev, "Cannot get drv_data\n");
 		return -EINVAL;
 	}
 
-	arb->base = devm_platform_ioremap_resource_byname(pdev, "pmif");
-	if (IS_ERR(arb->base))
-		return PTR_ERR(arb->base);
-
-	arb->spmimst_base = devm_platform_ioremap_resource_byname(pdev, "spmimst");
-	if (IS_ERR(arb->spmimst_base))
-		return PTR_ERR(arb->spmimst_base);
-
-	arb->nclks = ARRAY_SIZE(pmif_clock_names);
-	for (i = 0; i < arb->nclks; i++)
-		arb->clks[i].id = pmif_clock_names[i];
-
-	err = clk_bulk_get(&pdev->dev, arb->nclks, arb->clks);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to get clocks: %d\n", err);
-		return err;
-	}
-
-	err = clk_bulk_prepare_enable(arb->nclks, arb->clks);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to enable clocks: %d\n", err);
-		goto err_put_clks;
+	arb->pmif_base[0] = devm_platform_ioremap_resource_byname(pdev, "pmif");
+	if (IS_ERR(arb->pmif_base[0]))
+		return PTR_ERR(arb->pmif_base[0]);
+
+	arb->spmimst_base[0] = devm_platform_ioremap_resource_byname(pdev, "spmimst");
+	if (IS_ERR(arb->spmimst_base[0]))
+		return PTR_ERR(arb->spmimst_base[0]);
+
+	arb->pmif_base[1] = devm_platform_ioremap_resource_byname(pdev, "pmif-p");
+	if (IS_ERR(arb->pmif_base[1]))
+		dev_notice(&pdev->dev, "[PMIF]:no pmif-p found\n");
+	arb->spmimst_base[1] = devm_platform_ioremap_resource_byname(pdev, "spmimst-p");
+	if (IS_ERR(arb->spmimst_base[1]))
+		dev_notice(&pdev->dev, "[PMIF]:no spmimst-p found\n");
+		if (arb->data->caps == 1) {
+
+		arb->nclks = ARRAY_SIZE(pmif_clock_names);
+		for (i = 0; i < arb->nclks; i++)
+			arb->clks[i].id = pmif_clock_names[i];
+
+		err = clk_bulk_get(&pdev->dev, arb->nclks, arb->clks);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to get clocks: %d\n", err);
+			return err;
+		}
+
+		err = clk_bulk_prepare_enable(arb->nclks, arb->clks);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to enable clocks: %d\n", err);
+			goto err_put_clks;
+		}
 	}
 
-	ctrl->cmd = pmif_arb_cmd;
-	ctrl->read_cmd = pmif_spmi_read_cmd;
-	ctrl->write_cmd = pmif_spmi_write_cmd;
-
 	chan_offset = PMIF_CHAN_OFFSET * arb->data->soc_chan;
 	arb->chan.ch_sta = PMIF_SWINF_0_STA + chan_offset;
 	arb->chan.wdata = PMIF_SWINF_0_WDATA_31_0 + chan_offset; @@ -499,7 +1344,71 @@ static int mtk_spmi_probe(struct platform_device *pdev)
 	arb->chan.ch_send = PMIF_SWINF_0_ACC + chan_offset;
 	arb->chan.ch_rdy = PMIF_SWINF_0_VLD_CLR + chan_offset;
 
-	raw_spin_lock_init(&arb->lock);
+	raw_spin_lock_init(&arb->lock_m);
+	raw_spin_lock_init(&arb->lock_p);
+	arb->pmif_m_Thread_lock =
+		wakeup_source_register(NULL, "pmif_m wakelock");
+	arb->pmif_p_Thread_lock =
+		wakeup_source_register(NULL, "pmif_p wakelock");
+	mutex_init(&arb->pmif_m_mutex);
+	mutex_init(&arb->pmif_p_mutex);
+	if (arb->data->caps == 2) {
+		arb->irq = platform_get_irq_byname(pdev, "pmif_irq");
+		if (arb->irq < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get pmif_irq, ret = %d\n", arb->irq);
+		}
+		pmif_irq_register(pdev, arb, arb->irq);
+		arb->irq_p = platform_get_irq_byname(pdev, "pmif_p_irq");
+		if (arb->irq_p < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get pmif_p_irq, ret = %d\n", arb->irq_p);
+		}
+		pmif_irq_register(pdev, arb, arb->irq_p);
+		arb->rcs_irq = platform_get_irq_byname(pdev, "rcs_irq");
+		if (arb->rcs_irq < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get rcs_irq, ret = %d\n", arb->rcs_irq);
+		} else {
+			err = rcs_irq_register(pdev, arb, arb->rcs_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+				   "Failed to register rcs_irq, ret = %d\n", arb->rcs_irq);
+		}
+		arb->rcs_irq_p = platform_get_irq_byname(pdev, "rcs_irq_p");
+		if (arb->rcs_irq_p < 0) {
+			dev_notice(&pdev->dev,
+				   "Failed to get rcs_irq_p, ret = %d\n", arb->rcs_irq_p);
+		} else {
+			err = rcs_irq_register(pdev, arb, arb->rcs_irq_p);
+			if (err)
+				dev_notice(&pdev->dev,
+				   "Failed to register rcs_irq_p, ret = %d\n", arb->rcs_irq_p);
+		}
+		arb->spmi_nack_irq = platform_get_irq_byname(pdev, "spmi_nack_irq");
+		if (arb->spmi_nack_irq < 0) {
+			dev_notice(&pdev->dev,
+				"Failed to get spmi_nack_irq, ret = %d\n", arb->spmi_nack_irq);
+		} else {
+			err = spmi_nack_irq_register(pdev, arb, arb->spmi_nack_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+					"Failed to register spmi_nack_irq, ret = %d\n",
+						 arb->spmi_nack_irq);
+		}
+		arb->spmi_p_nack_irq = platform_get_irq_byname(pdev, "spmi_p_nack_irq");
+		if (arb->spmi_p_nack_irq < 0) {
+			dev_notice(&pdev->dev,
+				"Failed to get spmi_p_nack_irq, ret = %d\n", arb->spmi_p_nack_irq);
+		} else {
+			err = spmi_nack_irq_register(pdev, arb, arb->spmi_p_nack_irq);
+			if (err)
+				dev_notice(&pdev->dev,
+					"Failed to register spmi_p_nack_irq, ret = %d\n",
+						 arb->spmi_p_nack_irq);
+		}
+	}
+	spmi_dev_parse(pdev);
 
 	platform_set_drvdata(pdev, ctrl);
 
@@ -533,6 +1442,9 @@ static const struct of_device_id mtk_spmi_match_table[] = {
 	}, {
 		.compatible = "mediatek,mt8195-spmi",
 		.data = &mt8195_pmif_arb,
+	}, {
+		.compatible = "mediatek,mt8196-spmi",
+		.data = &mt6xxx_pmif_arb,
 	}, {
 		/* sentinel */
 	},
--
2.46.0


From Lu.Tang at mediatek.com  Fri Mar 14 02:01:59 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:01:59 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggMy81XSBwbWljOiBtZWRpYXRlazogQWRkIHNwbWkg?=
 =?utf-8?Q?pmic_mfd_driver?=
In-Reply-To: <20250314073307.25092-4-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-4-Lu.Tang@mediatek.com>
Message-ID: <SEZPR03MB6891D404A7AA2BC5244A992A80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>

Update email address

-----????-----
???: Lu.Tang <Lu.Tang at mediatek.com> 
????: 2025?3?14? 15:32
???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
??: [PATCH 3/5] pmic: mediatek: Add spmi pmic mfd driver

From: "Lu.Tang" <lu.tang at mediatek.com>

Add spmi pmic mfd driver for mt8196

Signed-off-by: Lu Tang <lu.tang at mediatek.com>
---
 drivers/mfd/Kconfig                  |  26 ++
 drivers/mfd/Makefile                 |   2 +
 drivers/mfd/mt6685-core.c            |  83 +++++
 drivers/mfd/mtk-spmi-pmic.c          | 518 +++++++++++++++++++++++++++
 include/linux/mfd/mt6363/core.h      | 134 +++++++
 include/linux/mfd/mt6363/registers.h | 168 +++++++++
 include/linux/mfd/mt6373/core.h      |  94 +++++
 include/linux/mfd/mt6373/registers.h |  53 +++
 8 files changed, 1078 insertions(+)
 create mode 100644 drivers/mfd/mt6685-core.c  create mode 100644 drivers/mfd/mtk-spmi-pmic.c  create mode 100644 include/linux/mfd/mt6363/core.h  create mode 100644 include/linux/mfd/mt6363/registers.h
 create mode 100644 include/linux/mfd/mt6373/core.h  create mode 100644 include/linux/mfd/mt6373/registers.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d44c69bb3dfd..a62625566893 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1030,6 +1030,32 @@ config MFD_MT6397
 	  accessing the device; additional drivers must be enabled in order
 	  to use the functionality of the device.
 
+config MFD_MT6685
+	tristate "MT6685 SPMI PMIC"
+	depends on OF
+	depends on SPMI
+	select REGMAP_SPMI
+	select REGMAP_IRQ
+	help
+	  This enables support for the Mediatek SPMI PMICs.
+	  These PMICs are currently used with the Mediatek series of
+	  SoCs.  Note, that this will only be useful paired with descriptions
+	  of the independent functions as children nodes in the device tree.
+
+config MFD_MTK_SPMI_PMIC
+	tristate "Mediatek SPMI PMICs"
+	depends on OF
+	depends on SPMI
+	select REGMAP_SPMI
+	help
+	  This enables support for the Mediatek SPMI PMICs.
+	  These PMICs are currently used with the MT63xx series of
+	  SoCs.  Note, that this will only be useful paired with descriptions
+	  of the independent functions as children nodes in the device tree.
+
+	  Say M here if you want to include support for the SPMI PMIC
+	  series as a module.  The module will be called "mtk-spmi-pmic".
+
 config MFD_MENF21BMC
 	tristate "MEN 14F021P00 Board Management Controller Support"
 	depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9220eaf7cf12..b8cb34284e56 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -182,6 +182,8 @@ obj-$(CONFIG_MFD_MT6360)	+= mt6360-core.o
 obj-$(CONFIG_MFD_MT6370)	+= mt6370.o
 mt6397-objs			:= mt6397-core.o mt6397-irq.o mt6358-irq.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397.o
+obj-$(CONFIG_MFD_MT6685)	+= mt6685-core.o
+obj-$(CONFIG_MFD_MTK_SPMI_PMIC)	+= mtk-spmi-pmic.o
 
 pcf50633-objs			:= pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633.o
diff --git a/drivers/mfd/mt6685-core.c b/drivers/mfd/mt6685-core.c new file mode 100644 index 000000000000..c71008184666
--- /dev/null
+++ b/drivers/mfd/mt6685-core.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+
+static const struct mfd_cell mt6685_devs[] = {
+	{
+		.name = "mt6685-clkbuf",
+		.of_compatible = "mediatek,mt6685-clkbuf",
+	}, {
+		.name = "mt6685-tb-clkbuf",
+		.of_compatible = "mediatek,mt6685-tb-clkbuf",
+	}, {
+		.name = "mt6685-rtc",
+		.of_compatible = "mediatek,mt6685-rtc",
+	}, {
+		.name = "mt6685-audclk",
+		.of_compatible = "mediatek,mt6685-audclk",
+	}, {
+		.name = "mt6685-consys",
+		.of_compatible = "mediatek,mt6685-consys",
+	}, {
+		.name = "mt6685-gps",
+		.of_compatible = "mediatek,mt6685-gps",
+	}
+};
+
+static const struct regmap_config spmi_regmap_config = {
+	.reg_bits	= 16,
+	.val_bits	= 8,
+	.max_register	= 0x2000,
+	.fast_io	= true,
+	.use_single_read = true,
+	.use_single_write = true
+};
+
+static int mt6685_spmi_probe(struct spmi_device *sdev) {
+	int ret;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&sdev->dev, "Failed to init mt6685 regmap: %ld\n", PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	ret = devm_mfd_add_devices(&sdev->dev, -1, mt6685_devs,
+				   ARRAY_SIZE(mt6685_devs), NULL, 0, NULL);
+	if (ret) {
+		dev_err(&sdev->dev, "Failed to add child devices: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id mt6685_id_table[] = {
+	{ .compatible = "mediatek,mt6685", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt6685_id_table);
+
+static struct spmi_driver mt6685_spmi_driver = {
+	.probe = mt6685_spmi_probe,
+	.driver = {
+		.name = "mt6685",
+		.of_match_table = mt6685_id_table,
+	},
+};
+module_spmi_driver(mt6685_spmi_driver);
+
+MODULE_DESCRIPTION("Mediatek SPMI MT6685 Clock IC driver"); 
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>"); MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mtk-spmi-pmic.c b/drivers/mfd/mtk-spmi-pmic.c new file mode 100644 index 000000000000..4c4bed5e991a
--- /dev/null
+++ b/drivers/mfd/mtk-spmi-pmic.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/mt6363/core.h>
+#include <linux/mfd/mt6363/registers.h> #include 
+<linux/mfd/mt6373/core.h> #include <linux/mfd/mt6373/registers.h> 
+#include <linux/module.h> #include <linux/mutex.h> #include 
+<linux/of_device.h> #include <linux/of_platform.h> #include 
+<linux/of_irq.h> #include <linux/regmap.h> #include <linux/spmi.h>
+
+#define MTK_SPMI_PMIC_REG_WIDTH	8
+#define PMIC_SWCID		0xB
+#define PMIC_MT6316_SWCID	0x20B
+#define RCS_INT_DONE		0x41B
+
+struct irq_top_t {
+	int hwirq_base;
+	unsigned int num_int_regs;
+	unsigned int en_reg;
+	unsigned int en_reg_shift;
+	unsigned int sta_reg;
+	unsigned int sta_reg_shift;
+	unsigned int top_offset;
+};
+
+struct mtk_spmi_pmic_data {
+	const struct mfd_cell *cells;
+	int cell_size;
+	unsigned int num_top;
+	unsigned int num_pmic_irqs;
+	unsigned short top_int_status_reg;
+	struct irq_top_t *pmic_ints;
+	unsigned int cid_addr;
+};
+
+struct pmic_core {
+	struct device *dev;
+	struct spmi_device *sdev;
+	struct regmap *regmap;
+	u16 chip_id;
+	int irq;
+	bool *enable_hwirq;
+	bool *cache_hwirq;
+	struct mutex irqlock;
+	struct irq_domain *irq_domain;
+	const struct mtk_spmi_pmic_data *chip_data; };
+
+static const struct resource mt6363_regulators_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VCN15_OC, "VCN15"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VCN13_OC, "VCN13"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF09_OC, "VRF09"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF12_OC, "VRF12"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF13_OC, "VRF13"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRF18_OC, "VRF18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VRFIO18_OC, "VRFIO18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VSRAM_MDFE_OC, "VSRAM_MDFE"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VTREF18_OC, "VTREF18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VSRAM_APU_OC, "VSRAM_APU"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VAUX18_OC, "VAUX18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VEMC_OC, "VEMC"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VUFS12_OC, "VUFS12"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VUFS18_OC, "VUFS18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VIO18_OC, "VIO18"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VIO075_OC, "VIO075"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA12_1_OC, "VA12_1"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA12_2_OC, "VA12_2"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VA15_OC, "VA15"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_VM18_OC, "VM18"), };
+
+static const struct resource mt6363_keys_resources[] = {
+	DEFINE_RES_IRQ(MT6363_IRQ_PWRKEY),
+	DEFINE_RES_IRQ(MT6363_IRQ_HOMEKEY),
+	DEFINE_RES_IRQ(MT6363_IRQ_PWRKEY_R),
+	DEFINE_RES_IRQ(MT6363_IRQ_HOMEKEY_R),
+};
+
+static const struct resource mt6363_lvsys_notify_resources[] = {
+	/* MT6363 LVSYS interrupt name is contrary,
+	 * we name LVSYS_R to MT6363_IRQ_NI_LVSYS_INT_FALLING;
+	 * LVSYS_F to MT6363_IRQ_NI_LVSYS_INT_RISING
+	 */
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_NI_LVSYS_INT_FALLING, "LVSYS_R"),
+	DEFINE_RES_IRQ_NAMED(MT6363_IRQ_NI_LVSYS_INT_RISING, "LVSYS_F"), };
+
+static const struct resource mt6373_regulators_resources[] = {
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VUSB_OC, "VUSB"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VAUX18_OC, "VAUX18"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF13_AIF_OC, "VRF13_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF18_AIF_OC, "VRF18_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRFIO18_AIF_OC, "VRFIO18_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_1_OC, "VCN33_1"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_2_OC, "VCN33_2"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN33_3_OC, "VCN33_3"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VCN18IO_OC, "VCN18IO"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF09_AIF_OC, "VRF09_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VRF12_AIF_OC, "VRF12_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VANT18_OC, "VANT18"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VSRAM_DIGRF_AIF_OC, "VSRAM_DIGRF_AIF"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VEFUSE_OC, "VEFUSE"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VMCH_OC, "VMCH"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VMC_OC, "VMC"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VIBR_OC, "VIBR"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VIO28_OC, "VIO28"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VFP_OC, "VFP"),
+	DEFINE_RES_IRQ_NAMED(MT6373_IRQ_VTP_OC, "VTP"), };
+
+static const struct mfd_cell mt6363_devs[] = {
+	{
+		.name = "mt6363-auxadc",
+		.of_compatible = "mediatek,mt6363-auxadc",
+	}, {
+		.name = "mtk-dynamic-loading-throttling",
+		.of_compatible = "mediatek,mt6363-dynamic_loading_throttling",
+	}, {
+		.name = "mt6363-efuse",
+		.of_compatible = "mediatek,mt6363-efuse",
+	}, {
+		.name = "mt6363-regulator",
+		.num_resources = ARRAY_SIZE(mt6363_regulators_resources),
+		.resources = mt6363_regulators_resources,
+		.of_compatible = "mediatek,mt6363-regulator",
+	}, {
+		.name = "mtk-pmic-keys",
+		.num_resources = ARRAY_SIZE(mt6363_keys_resources),
+		.resources = mt6363_keys_resources,
+		.of_compatible = "mediatek,mt6363-keys"
+	}, {
+		.name = "mt6363-consys",
+		.of_compatible = "mediatek,mt6363-consys",
+	}, {
+		.name = "mt6363-lvsys-notify",
+		.num_resources = ARRAY_SIZE(mt6363_lvsys_notify_resources),
+		.resources = mt6363_lvsys_notify_resources,
+		.of_compatible = "mediatek,mt6363-lvsys-notify",
+	}, {
+		.name = "mt6363-pinctrl",
+		.of_compatible = "mediatek,mt6363-pinctrl",
+	},
+};
+
+static const struct mfd_cell mt6373_devs[] = {
+	{
+		.name = "mt6373-regulator",
+		.num_resources = ARRAY_SIZE(mt6373_regulators_resources),
+		.resources = mt6373_regulators_resources,
+		.of_compatible = "mediatek,mt6373-regulator",
+	}, {
+		.name = "mt6373-auxadc",
+		.of_compatible = "mediatek,mt6373-auxadc",
+	}, {
+		.name = "mt6373-efuse",
+		.of_compatible = "mediatek,mt6373-efuse",
+	}, {
+		.name = "mt6373-consys",
+		.of_compatible = "mediatek,mt6373-consys",
+	}, {
+		.name = "mt6373-pinctrl",
+		.of_compatible = "mediatek,mt6373-pinctrl",
+	},
+};
+
+static struct irq_top_t mt6363_ints[] = {
+	MT6363_TOP_GEN(BUCK),
+	MT6363_TOP_GEN(LDO),
+	MT6363_TOP_GEN(PSC),
+	MT6363_TOP_GEN(MISC),
+	MT6363_TOP_GEN(HK),
+	MT6363_TOP_GEN(BM),
+};
+
+
+static struct irq_top_t mt6373_ints[] = {
+	MT6373_TOP_GEN(BUCK),
+	MT6373_TOP_GEN(LDO),
+	MT6373_TOP_GEN(MISC),
+};
+
+static const struct mtk_spmi_pmic_data mt6316_data = {
+	.num_pmic_irqs = 0,
+	.cid_addr = PMIC_MT6316_SWCID,
+};
+
+static const struct mtk_spmi_pmic_data mt6363_data = {
+	.cells = mt6363_devs,
+	.cell_size = ARRAY_SIZE(mt6363_devs),
+	.num_top = ARRAY_SIZE(mt6363_ints),
+	.num_pmic_irqs = MT6363_IRQ_NR,
+	.top_int_status_reg = MT6363_TOP_INT_STATUS1,
+	.pmic_ints = mt6363_ints,
+};
+
+static const struct mtk_spmi_pmic_data mt6373_data = {
+	.cells = mt6373_devs,
+	.cell_size = ARRAY_SIZE(mt6373_devs),
+	.num_top = ARRAY_SIZE(mt6373_ints),
+	.num_pmic_irqs = MT6373_IRQ_NR,
+	.top_int_status_reg = MT6373_TOP_INT_STATUS1,
+	.pmic_ints = mt6373_ints,
+};
+
+static void mtk_spmi_pmic_irq_enable(struct irq_data *data) {
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	core->enable_hwirq[hwirq] = true;
+}
+
+static void mtk_spmi_pmic_irq_disable(struct irq_data *data) {
+	unsigned int hwirq = irqd_to_hwirq(data);
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	core->enable_hwirq[hwirq] = false;
+}
+
+static void mtk_spmi_pmic_irq_lock(struct irq_data *data) {
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&core->irqlock);
+}
+
+static void mtk_spmi_pmic_irq_sync_unlock(struct irq_data *data) {
+	unsigned int i, top_gp, gp_offset, en_reg, int_regs, shift;
+	struct irq_top_t *pmic_int;
+	struct pmic_core *core = irq_data_get_irq_chip_data(data);
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	for (i = 0; i < chip_data->num_pmic_irqs; i++) {
+		if (core->enable_hwirq[i] == core->cache_hwirq[i])
+			continue;
+
+		/* Find out the IRQ group */
+		top_gp = 0;
+		while ((top_gp + 1) < chip_data->num_top &&
+			i >= chip_data->pmic_ints[top_gp + 1].hwirq_base)
+			top_gp++;
+
+		pmic_int = &(chip_data->pmic_ints[top_gp]);
+		/* Find the IRQ registers */
+		gp_offset = i - pmic_int->hwirq_base;
+		int_regs = gp_offset / MTK_SPMI_PMIC_REG_WIDTH;
+		shift = gp_offset % MTK_SPMI_PMIC_REG_WIDTH;
+		en_reg = pmic_int->en_reg + (pmic_int->en_reg_shift * int_regs);
+
+		regmap_update_bits(core->regmap, en_reg, BIT(shift),
+				   core->enable_hwirq[i] << shift);
+		core->cache_hwirq[i] = core->enable_hwirq[i];
+	}
+	mutex_unlock(&core->irqlock);
+}
+
+static struct irq_chip mtk_spmi_pmic_irq_chip = {
+	.name = "spmi-pmic-irq",
+	.flags = IRQCHIP_SKIP_SET_WAKE,
+	.irq_enable = mtk_spmi_pmic_irq_enable,
+	.irq_disable = mtk_spmi_pmic_irq_disable,
+	.irq_bus_lock = mtk_spmi_pmic_irq_lock,
+	.irq_bus_sync_unlock = mtk_spmi_pmic_irq_sync_unlock, };
+
+static void mtk_spmi_pmic_irq_sp_handler(struct pmic_core *core,
+					 unsigned int top_gp)
+{
+	unsigned int irq_status = 0, sta_reg, status;
+	unsigned int hwirq, virq;
+	int ret, i, j;
+	struct irq_top_t *pmic_int;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	for (i = 0; i < chip_data->pmic_ints[top_gp].num_int_regs; i++) {
+		pmic_int = &(chip_data->pmic_ints[top_gp]);
+		sta_reg = pmic_int->sta_reg + (pmic_int->sta_reg_shift * i);
+
+		ret = regmap_read(core->regmap, sta_reg, &irq_status);
+		if (ret) {
+			dev_err(core->dev,
+				"Failed to read irq status: %d\n", ret);
+			return;
+		}
+
+		if (!irq_status)
+			continue;
+
+		status = irq_status;
+		do {
+			j = __ffs(status);
+
+			hwirq = pmic_int->hwirq_base + MTK_SPMI_PMIC_REG_WIDTH * i + j;
+
+			virq = irq_find_mapping(core->irq_domain, hwirq);
+			dev_info(core->dev, "[%x]Reg[0x%x]=0x%x,hwirq=%d\n",
+				 core->chip_id, sta_reg, irq_status, hwirq);
+			if (virq)
+				handle_nested_irq(virq);
+
+			status &= ~BIT(j);
+		} while (status);
+
+		regmap_write(core->regmap, sta_reg, irq_status);
+	}
+}
+
+static irqreturn_t mtk_spmi_pmic_irq_handler(int irq, void *data) {
+	int ret;
+	unsigned int bit, i, top_irq_status = 0;
+	struct pmic_core *core = data;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	ret = regmap_read(core->regmap, chip_data->top_int_status_reg,
+			  &top_irq_status);
+	if (ret) {
+		dev_err(core->dev,
+			"Failed to read status from the device, ret=%d\n", ret);
+		return IRQ_NONE;
+	}
+
+	dev_info(core->dev, "top_irq_sts:0x%x\n", top_irq_status);
+	for (i = 0; i < chip_data->num_top; i++) {
+		bit = BIT(chip_data->pmic_ints[i].top_offset);
+		if (top_irq_status & bit)
+			mtk_spmi_pmic_irq_sp_handler(core, i);
+	}
+
+	ret = regmap_write(core->regmap, RCS_INT_DONE, 1);
+	if (ret) {
+		dev_err(core->dev,
+			"Failed to clear RCS flag, ret=%d\n", ret);
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_spmi_pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+					irq_hw_number_t hw)
+{
+	struct pmic_core *core = d->host_data;
+
+	irq_set_chip_data(irq, core);
+	irq_set_chip_and_handler(irq, &mtk_spmi_pmic_irq_chip,
+				 handle_level_irq);
+	irq_set_nested_thread(irq, 1);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pmic_irq_domain_ops = {
+	.map = mtk_spmi_pmic_irq_domain_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int mtk_spmi_pmic_irq_init(struct pmic_core *core) {
+	int i, j, ret;
+	unsigned int en_reg, sta_reg;
+	const struct mtk_spmi_pmic_data *chip_data = core->chip_data;
+
+	mutex_init(&core->irqlock);
+	core->enable_hwirq = devm_kcalloc(core->dev,
+					  chip_data->num_pmic_irqs,
+					  sizeof(bool), GFP_KERNEL);
+	if (!core->enable_hwirq)
+		return -ENOMEM;
+
+	core->cache_hwirq = devm_kcalloc(core->dev,
+					 chip_data->num_pmic_irqs,
+					 sizeof(bool), GFP_KERNEL);
+	if (!core->cache_hwirq)
+		return -ENOMEM;
+
+	/* Disable all interrupt for initializing */
+	for (i = 0; i < chip_data->num_top; i++) {
+		for (j = 0; j < chip_data->pmic_ints[i].num_int_regs; j++) {
+			en_reg = chip_data->pmic_ints[i].en_reg +
+				chip_data->pmic_ints[i].en_reg_shift * j;
+			regmap_write(core->regmap, en_reg, 0);
+			sta_reg = chip_data->pmic_ints[i].sta_reg +
+				chip_data->pmic_ints[i].sta_reg_shift * j;
+			regmap_write(core->regmap, sta_reg, 0xFF);
+		}
+	}
+	regmap_write(core->regmap, RCS_INT_DONE, 1);
+
+	core->irq_domain = irq_domain_add_linear(core->dev->of_node,
+						 chip_data->num_pmic_irqs,
+						 &pmic_irq_domain_ops,
+						 core);
+	if (!core->irq_domain) {
+		dev_err(core->dev, "Could not create IRQ domain\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_threaded_irq(core->dev, core->irq, NULL,
+					mtk_spmi_pmic_irq_handler, IRQF_ONESHOT,
+					mtk_spmi_pmic_irq_chip.name, core);
+	if (ret) {
+		dev_err(core->dev, "Failed to register IRQ=%d, ret=%d\n",
+			core->irq, ret);
+		return ret;
+	}
+
+	enable_irq_wake(core->irq);
+	return ret;
+}
+
+static const struct regmap_config spmi_regmap_config = {
+	.reg_bits	= 16,
+	.val_bits	= 8,
+	.max_register	= 0xffff,
+	.fast_io	= true,
+};
+
+static int mtk_spmi_pmic_probe(struct spmi_device *sdev) {
+	int ret;
+	unsigned int id;
+	struct device_node *np = sdev->dev.of_node;
+	struct pmic_core *core;
+	const struct mtk_spmi_pmic_data *chip_data;
+
+	core = devm_kzalloc(&sdev->dev, sizeof(*core), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	core->sdev = sdev;
+	core->dev = &sdev->dev;
+	chip_data = (struct mtk_spmi_pmic_data *)of_device_get_match_data(&sdev->dev);
+	if (!chip_data)
+		return -ENODEV;
+
+	core->chip_data = chip_data;
+	core->regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config);
+	if (IS_ERR(core->regmap))
+		return PTR_ERR(core->regmap);
+	if (chip_data->cid_addr)
+		ret = regmap_read(core->regmap, chip_data->cid_addr, &id);
+	else
+		ret = regmap_read(core->regmap, PMIC_SWCID, &id);
+	if (ret || id == 0) {
+		dev_err(&sdev->dev, "Failed to read chip id: %d\n", ret);
+		return ret;
+	}
+
+	core->chip_id = id;
+
+	if (chip_data->num_pmic_irqs) {
+		core->irq = of_irq_get(np, 0);
+		if (core->irq < 0)
+			dev_err(&sdev->dev, "Failed to get irq(%d)\n", core->irq);
+
+		ret = mtk_spmi_pmic_irq_init(core);
+		if (ret)
+			dev_err(&sdev->dev, "IRQ_init failed(%d)\n", core->irq);
+
+		ret = devm_mfd_add_devices(&sdev->dev, -1, chip_data->cells,
+					   chip_data->cell_size, NULL, 0,
+					   core->irq_domain);
+		if (ret) {
+			irq_domain_remove(core->irq_domain);
+			dev_err(&sdev->dev, "Failed to add mfd devices: %d\n", ret);
+			return ret;
+		}
+	} else {
+		ret = devm_of_platform_populate(&sdev->dev);
+		if (ret) {
+			dev_err(&sdev->dev, "Failed to platform populate: %d\n", ret);
+			return ret;
+		}
+	}
+
+	device_init_wakeup(&sdev->dev, true);
+
+	dev_dbg(&sdev->dev, "probe chip id=0x%x done\n", core->chip_id);
+
+	return ret;
+}
+
+static const struct of_device_id mtk_spmi_pmic_of_match[] = {
+	{ .compatible = "mediatek,mt6316", .data = &mt6316_data, },
+	{ .compatible = "mediatek,mt6363", .data = &mt6363_data, },
+	{ .compatible = "mediatek,mt6373", .data = &mt6373_data, },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mtk_spmi_pmic_of_match);
+
+static struct spmi_driver mtk_spmi_pmic_driver = {
+	.driver = {
+		.name = "mtk-spmi-pmic",
+		.of_match_table = of_match_ptr(mtk_spmi_pmic_of_match),
+	},
+	.probe = mtk_spmi_pmic_probe,
+};
+module_spmi_driver(mtk_spmi_pmic_driver);
+
+MODULE_DESCRIPTION("Mediatek SPMI PMIC driver"); 
+MODULE_ALIAS("spmi:spmi-pmic"); MODULE_LICENSE("GPL"); 
+MODULE_AUTHOR("Argus Lin <argus.lin at mediatek.com>"); 
+MODULE_AUTHOR("Jeter Chen <jeter.chen at mediatek.com>"); 
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>");
diff --git a/include/linux/mfd/mt6363/core.h b/include/linux/mfd/mt6363/core.h new file mode 100644 index 000000000000..3243a52da34d
--- /dev/null
+++ b/include/linux/mfd/mt6363/core.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6363_CORE_H__
+#define __MFD_MT6363_CORE_H__
+
+#define MT6363_REG_WIDTH 8
+
+enum mt6363_irq_top_status_shift {
+	MT6363_BUCK_TOP = 0,
+	MT6363_LDO_TOP,
+	MT6363_PSC_TOP,
+	MT6363_MISC_TOP,
+	MT6363_HK_TOP,
+	MT6363_SCK_TOP,
+	MT6363_BM_TOP,
+	MT6363_AUD_TOP,
+};
+
+enum mt6363_irq_numbers {
+	MT6363_IRQ_VS2_OC = 0,
+	MT6363_IRQ_VBUCK1_OC,
+	MT6363_IRQ_VBUCK2_OC,
+	MT6363_IRQ_VBUCK3_OC,
+	MT6363_IRQ_VBUCK4_OC,
+	MT6363_IRQ_VBUCK5_OC,
+	MT6363_IRQ_VBUCK6_OC,
+	MT6363_IRQ_VBUCK7_OC,
+	MT6363_IRQ_VS1_OC,
+	MT6363_IRQ_VS3_OC,
+	MT6363_IRQ_VCN15_OC = 16,
+	MT6363_IRQ_VCN13_OC,
+	MT6363_IRQ_VRF09_OC,
+	MT6363_IRQ_VRF12_OC,
+	MT6363_IRQ_VRF13_OC,
+	MT6363_IRQ_VRF18_OC,
+	MT6363_IRQ_VRFIO18_OC,
+	MT6363_IRQ_VSRAM_DIGRF_OC,
+	MT6363_IRQ_VSRAM_MDFE_OC,
+	MT6363_IRQ_VSRAM_MODEM_OC,
+	MT6363_IRQ_VTREF18_OC,
+	MT6363_IRQ_VSRAM_CPUB_OC,
+	MT6363_IRQ_VSRAM_CPUM_OC,
+	MT6363_IRQ_VSRAM_CPUL_OC,
+	MT6363_IRQ_VSRAM_APU_OC,
+	MT6363_IRQ_VAUX18_OC,
+	MT6363_IRQ_VEMC_OC,
+	MT6363_IRQ_VUFS12_OC,
+	MT6363_IRQ_VUFS18_OC,
+	MT6363_IRQ_VIO18_OC,
+	MT6363_IRQ_VIO075_OC,
+	MT6363_IRQ_VA12_1_OC,
+	MT6363_IRQ_VA12_2_OC,
+	MT6363_IRQ_VA15_OC,
+	MT6363_IRQ_VM18_OC,
+	MT6363_IRQ_PWRKEY = 48,
+	MT6363_IRQ_HOMEKEY,
+	MT6363_IRQ_HOMEKEY_2,
+	MT6363_IRQ_PWRKEY_R,
+	MT6363_IRQ_HOMEKEY_R,
+	MT6363_IRQ_HOMEKEY_2_R,
+	MT6363_IRQ_NI_LVSYS_INT_FALLING,
+	MT6363_IRQ_NI_LVSYS_INT_RISING,
+	MT6363_IRQ_CHRDET_LEVEL,
+	MT6363_IRQ_CHRDET_EDGE,
+	MT6363_IRQ_RCS0 = 64,
+	MT6363_IRQ_SPMI_CMD_ALERT,
+	MT6363_IRQ_BM_PROTREG = 70,
+	MT6363_IRQ_BUCK_PROTREG = 72,
+	MT6363_IRQ_LDO_PROTREG,
+	MT6363_IRQ_PSC_PROTREG,
+	MT6363_IRQ_PLT_PROTREG,
+	MT6363_IRQ_HK_PROTREG,
+	MT6363_IRQ_TOP_PROTREG = 79,
+	MT6363_IRQ_BAT_H,
+	MT6363_IRQ_BAT_L,
+	MT6363_IRQ_BAT2_H,
+	MT6363_IRQ_BAT2_L,
+	MT6363_IRQ_BAT_TEMP_H,
+	MT6363_IRQ_BAT_TEMP_L,
+	MT6363_IRQ_THR_H,
+	MT6363_IRQ_THR_L,
+	MT6363_IRQ_AUXADC_IMP,
+	MT6363_IRQ_NAG_C_DLTV,
+	MT6363_IRQ_FG_BAT_H = 88,
+	MT6363_IRQ_FG_BAT_L,
+	MT6363_IRQ_FG_CUR_H,
+	MT6363_IRQ_FG_CUR_L,
+	MT6363_IRQ_FG_ZCV,
+	MT6363_IRQ_FG_N_CHARGE_L = 95,
+	MT6363_IRQ_FG_IAVG_H,
+	MT6363_IRQ_FG_IAVG_L,
+	MT6363_IRQ_FG_DISCHARGE = 99,
+	MT6363_IRQ_FG_CHARGE,
+	MT6363_IRQ_BATON_LV = 104,
+	MT6363_IRQ_BATON_BAT_IN = 106,
+	MT6363_IRQ_BATON_BAT_OUT,
+	MT6363_IRQ_NR = 108,
+};
+
+#define MT6363_IRQ_BUCK_BASE MT6363_IRQ_VS2_OC #define 
+MT6363_IRQ_LDO_BASE MT6363_IRQ_VCN15_OC #define MT6363_IRQ_PSC_BASE 
+MT6363_IRQ_PWRKEY #define MT6363_IRQ_MISC_BASE MT6363_IRQ_RCS0 #define 
+MT6363_IRQ_HK_BASE MT6363_IRQ_BAT_H #define MT6363_IRQ_BM_BASE 
+MT6363_IRQ_FG_BAT_H
+
+#define MT6363_IRQ_BUCK_BITS \
+	(MT6363_IRQ_VS3_OC - MT6363_IRQ_BUCK_BASE + 1) #define 
+MT6363_IRQ_LDO_BITS \
+	(MT6363_IRQ_VM18_OC - MT6363_IRQ_LDO_BASE + 1) #define 
+MT6363_IRQ_PSC_BITS \
+	(MT6363_IRQ_CHRDET_EDGE - MT6363_IRQ_PSC_BASE + 1) #define 
+MT6363_IRQ_MISC_BITS \
+	(MT6363_IRQ_TOP_PROTREG - MT6363_IRQ_MISC_BASE + 1) #define 
+MT6363_IRQ_HK_BITS \
+	(MT6363_IRQ_NAG_C_DLTV - MT6363_IRQ_HK_BASE + 1) #define 
+MT6363_IRQ_BM_BITS \
+	(MT6363_IRQ_BATON_BAT_OUT - MT6363_IRQ_BM_BASE + 1)
+
+#define MT6363_TOP_GEN(sp) \
+{ \
+	.hwirq_base = MT6363_IRQ_##sp##_BASE, \
+	.num_int_regs =	((MT6363_IRQ_##sp##_BITS - 1) / MT6363_REG_WIDTH) + 1, \
+	.en_reg = MT6363_##sp##_TOP_INT_CON0, \
+	.en_reg_shift = 0x3, \
+	.sta_reg = MT6363_##sp##_TOP_INT_STATUS0, \
+	.sta_reg_shift = 0x1, \
+	.top_offset = MT6363_##sp##_TOP, \
+}
+
+#endif /* __MFD_MT6363_CORE_H__ */
diff --git a/include/linux/mfd/mt6363/registers.h b/include/linux/mfd/mt6363/registers.h
new file mode 100644
index 000000000000..e22ca686a7d0
--- /dev/null
+++ b/include/linux/mfd/mt6363/registers.h
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+
+#ifndef __MFD_MT6363_REGISTERS_H__
+#define __MFD_MT6363_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6363_TOPSTATUS		   (0x1e)
+#define MT6363_MISC_TOP_INT_CON0           (0x37)
+#define MT6363_MISC_TOP_INT_STATUS0        (0x43)
+#define MT6363_TOP_INT_STATUS1             (0x4e)
+#define MT6363_PSC_TOP_INT_CON0            (0x90f)
+#define MT6363_PSC_TOP_INT_STATUS0         (0x91b)
+#define MT6363_STRUP_CON11		   (0xa0e)
+#define MT6363_STRUP_CON12		   (0xa0f)
+#define MT6363_PCHR_VREF_ANA_CON1          (0xa89)
+#define MT6363_PCHR_VREF_ANA_CON2          (0xa8a)
+#define MT6363_BM_TOP_INT_CON0             (0xc24)
+#define MT6363_BM_TOP_INT_STATUS0          (0xc36)
+#define MT6363_HK_TOP_INT_CON0             (0xf92)
+#define MT6363_HK_TOP_INT_STATUS0          (0xf9e)
+#define MT6363_BUCK_TOP_INT_CON0           (0x1411)
+#define MT6363_BUCK_TOP_INT_STATUS0        (0x141d)
+#define MT6363_LDO_TOP_INT_CON0            (0x1b11)
+#define MT6363_LDO_TOP_INT_STATUS0         (0x1b29)
+
+/* voter */
+#define MT6363_BUCK_VS2_VOTER_CON0         (0x149a)
+#define MT6363_BUCK_VS2_VOTER_CON0_SET     (0x149b)
+#define MT6363_BUCK_VS2_VOTER_CON0_CLR     (0x149c)
+#define MT6363_BUCK_VS2_VOTER_CON1         (0x149d)
+#define MT6363_BUCK_VS2_VOTER_CON1_SET     (0x149e)
+#define MT6363_BUCK_VS2_VOTER_CON1_CLR     (0x149f)
+#define MT6363_BUCK_VS2_VOTER_CFG          (0x14a0)
+#define MT6363_BUCK_VS1_VOTER_CON0         (0x189a)
+#define MT6363_BUCK_VS1_VOTER_CON0_SET     (0x189b)
+#define MT6363_BUCK_VS1_VOTER_CON0_CLR     (0x189c)
+#define MT6363_BUCK_VS1_VOTER_CON1         (0x189d)
+#define MT6363_BUCK_VS1_VOTER_CON1_SET     (0x189e)
+#define MT6363_BUCK_VS1_VOTER_CON1_CLR     (0x189f)
+#define MT6363_BUCK_VS1_VOTER_CFG          (0x18a0)
+#define MT6363_BUCK_VS3_VOTER_CON0         (0x191a)
+#define MT6363_BUCK_VS3_VOTER_CON0_SET     (0x191b)
+#define MT6363_BUCK_VS3_VOTER_CON0_CLR     (0x191c)
+#define MT6363_BUCK_VS3_VOTER_CON1         (0x191d)
+#define MT6363_BUCK_VS3_VOTER_CON1_SET     (0x191e)
+#define MT6363_BUCK_VS3_VOTER_CON1_CLR     (0x191f)
+#define MT6363_BUCK_VS3_VOTER_CFG          (0x1920)
+
+#define MT6363_CHRDET_DEB_ADDR             MT6363_TOPSTATUS
+#define MT6363_CHRDET_DEB_MASK             (0x1)
+#define MT6363_CHRDET_DEB_SHIFT            (2)
+#define MT6363_RG_VBB_UVLO_VTHL_ADDR       MT6363_PCHR_VREF_ANA_CON1
+#define MT6363_RG_VBB_UVLO_VTHL_MASK       (0xF)
+#define MT6363_RG_VBB_UVLO_VTHL_SHIFT      (0)
+#define MT6363_RG_VSYS_UVLO_VTHL_ADDR      MT6363_PCHR_VREF_ANA_CON2
+#define MT6363_RG_VSYS_UVLO_VTHL_MASK      (0xF)
+#define MT6363_RG_VSYS_UVLO_VTHL_SHIFT     (0)
+
+#define MT6363_AUXADC_ADC0_L               (0x1088)
+#define MT6363_AUXADC_ADC3_L               (0x108e)
+#define MT6363_AUXADC_ADC4_L               (0x1090)
+#define MT6363_AUXADC_ADC11_L              (0x109e)
+#define MT6363_AUXADC_ADC38_L              (0x10c4)
+#define MT6363_AUXADC_ADC39_L              (0x10c6)
+#define MT6363_AUXADC_ADC40_L              (0x10c8)
+#define MT6363_AUXADC_ADC_CH12_L           (0x10d2)
+#define MT6363_AUXADC_ADC_CH14_L           (0x10d8)
+#define MT6363_AUXADC_ADC42_L              (0x10dc)
+#define MT6363_AUXADC_RQST0                (0x1108)
+#define MT6363_AUXADC_RQST1                (0x1109)
+#define MT6363_AUXADC_RQST3                (0x110c)
+#define MT6363_SDMADC_RQST0                (0x110e)
+#define MT6363_SDMADC_CON0                 (0x11c4)
+#define MT6363_AUXADC_IMP0                 (0x1208)
+#define MT6363_AUXADC_IMP1                 (0x1209)
+
+/* voter */
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CON0
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CON1
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS2_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS2_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS2_VOTER_CFG
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS2_VOTER_VOSEL_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CON0
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CON1
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS1_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS1_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS1_VOTER_CFG
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS1_VOTER_VOSEL_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CON0
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON0_SET
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON0_CLR
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_MASK             (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_LO_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CON1
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_MASK                 (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SHIFT                (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON1_SET
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_MASK             (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_SET_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_ADDR             \
+	MT6363_BUCK_VS3_VOTER_CON1_CLR
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_MASK             (0xF)
+#define MT6363_RG_BUCK_VS3_VOTER_EN_HI_CLR_SHIFT            (0)
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_ADDR                 \
+	MT6363_BUCK_VS3_VOTER_CFG
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_MASK                 (0xFF)
+#define MT6363_RG_BUCK_VS3_VOTER_VOSEL_SHIFT                (0)
+
+#endif /* __MFD_MT6363_REGISTERS_H__ */
+
diff --git a/include/linux/mfd/mt6373/core.h b/include/linux/mfd/mt6373/core.h new file mode 100644 index 000000000000..dd77d8cf29a2
--- /dev/null
+++ b/include/linux/mfd/mt6373/core.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MFD_MT6373_CORE_H__
+#define __MFD_MT6373_CORE_H__
+
+#define MT6373_REG_WIDTH 8
+
+enum mt6373_irq_top_status_shift {
+	MT6373_BUCK_TOP = 0,
+	MT6373_LDO_TOP,
+	MT6373_PSC_TOP,
+	MT6373_MISC_TOP,
+	MT6373_HK_TOP,
+	MT6373_SCK_TOP,
+	MT6373_BM_TOP,
+	MT6373_AUD_TOP,
+};
+
+enum mt6373_irq_numbers {
+	MT6373_IRQ_VBUCK0_OC,
+	MT6373_IRQ_VBUCK1_OC,
+	MT6373_IRQ_VBUCK2_OC,
+	MT6373_IRQ_VBUCK3_OC,
+	MT6373_IRQ_VBUCK4_OC,
+	MT6373_IRQ_VBUCK5_OC,
+	MT6373_IRQ_VBUCK6_OC,
+	MT6373_IRQ_VBUCK7_OC,
+	MT6373_IRQ_VBUCK8_OC,
+	MT6373_IRQ_VBUCK9_OC,
+	MT6373_IRQ_VAUD18_OC = 16,
+	MT6373_IRQ_VUSB_OC,
+	MT6373_IRQ_VAUX18_OC,
+	MT6373_IRQ_VRF13_AIF_OC,
+	MT6373_IRQ_VRF18_AIF_OC,
+	MT6373_IRQ_VRFIO18_AIF_OC,
+	MT6373_IRQ_VCN33_1_OC,
+	MT6373_IRQ_VCN33_2_OC,
+	MT6373_IRQ_VCN33_3_OC,
+	MT6373_IRQ_VCN18IO_OC,
+	MT6373_IRQ_VRF09_AIF_OC,
+	MT6373_IRQ_VRF12_AIF_OC,
+	MT6373_IRQ_VANT18_OC,
+	MT6373_IRQ_VSRAM_DIGRF_AIF_OC,
+	MT6373_IRQ_VMDDR_OC,
+	MT6373_IRQ_VEFUSE_OC,
+	MT6373_IRQ_VMCH_OC,
+	MT6373_IRQ_VMC_OC,
+	MT6373_IRQ_VIBR_OC,
+	MT6373_IRQ_VIO28_OC,
+	MT6373_IRQ_VFP_OC,
+	MT6373_IRQ_VTP_OC,
+	MT6373_IRQ_VSIM1_OC,
+	MT6373_IRQ_VSIM2_OC,
+	MT6373_IRQ_RCS0 = 56,
+	MT6373_IRQ_SPMI_CMD_ALERT,
+	MT6373_IRQ_BM_PROTREG = 62,
+	MT6373_IRQ_VRC_PROTREG,
+	MT6373_IRQ_BUCK_PROTREG = 64,
+	MT6373_IRQ_LDO_PROTREG,
+	MT6373_IRQ_PSC_PROTREG,
+	MT6373_IRQ_PLT_PROTREG,
+	MT6373_IRQ_HK_PROTREG,
+	MT6373_IRQ_SCK_PROTREG,
+	MT6373_IRQ_XPP_PROTREG,
+	MT6373_IRQ_TOP_PROTREG,
+	MT6373_IRQ_NR = 72,
+};
+
+#define MT6373_IRQ_BUCK_BASE MT6373_IRQ_VBUCK0_OC #define 
+MT6373_IRQ_LDO_BASE MT6373_IRQ_VAUD18_OC #define MT6373_IRQ_MISC_BASE 
+MT6373_IRQ_RCS0
+
+#define MT6373_IRQ_BUCK_BITS \
+	(MT6373_IRQ_VBUCK9_OC - MT6373_IRQ_BUCK_BASE + 1) #define 
+MT6373_IRQ_LDO_BITS \
+	(MT6373_IRQ_VSIM2_OC - MT6373_IRQ_LDO_BASE + 1) #define 
+MT6373_IRQ_MISC_BITS \
+	(MT6373_IRQ_TOP_PROTREG - MT6373_IRQ_MISC_BASE + 1)
+
+#define MT6373_TOP_GEN(sp) \
+{ \
+	.hwirq_base = MT6373_IRQ_##sp##_BASE, \
+	.num_int_regs =	((MT6373_IRQ_##sp##_BITS - 1) / MT6373_REG_WIDTH) + 1, \
+	.en_reg = MT6373_##sp##_TOP_INT_CON0, \
+	.en_reg_shift = 0x3, \
+	.sta_reg = MT6373_##sp##_TOP_INT_STATUS0, \
+	.sta_reg_shift = 0x1, \
+	.top_offset = MT6373_##sp##_TOP, \
+}
+
+#endif /* __MFD_MT6373_CORE_H__ */
diff --git a/include/linux/mfd/mt6373/registers.h b/include/linux/mfd/mt6373/registers.h
new file mode 100644
index 000000000000..05aef78abfdf
--- /dev/null
+++ b/include/linux/mfd/mt6373/registers.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+
+#ifndef __MFD_MT6373_REGISTERS_H__
+#define __MFD_MT6373_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6373_TOPSTATUS                       0x1e
+#define MT6373_MISC_TOP_INT_CON0               0x3c
+#define MT6373_MISC_TOP_INT_CON1               0x3f
+#define MT6373_MISC_TOP_INT_STATUS0            0x48
+#define MT6373_MISC_TOP_INT_STATUS1            0x49
+#define MT6373_TOP_INT_MASK_CON0               0x4c
+#define MT6373_TOP_INT_MASK_CON0_SET           0x4d
+#define MT6373_TOP_INT_MASK_CON0_CLR           0x4e
+#define MT6373_TOP_INT_MASK_CON1               0x4f
+#define MT6373_TOP_INT_MASK_CON1_SET           0x50
+#define MT6373_TOP_INT_MASK_CON1_CLR           0x51
+#define MT6373_TOP_INT_STATUS0                 0x52
+#define MT6373_TOP_INT_STATUS1                 0x53
+#define MT6373_HK_TOP_INT_CON0                 0xf92
+#define MT6373_HK_TOP_INT_CON1                 0xf95
+#define MT6373_HK_TOP_INT_STATUS0              0xf9e
+#define MT6373_HK_TOP_INT_STATUS1              0xf9f
+#define MT6373_AUXADC_ADC4_L                   0x1090
+#define MT6373_AUXADC_ADC38_L                  0x10c4
+#define MT6373_AUXADC_ADC39_L                  0x10c6
+#define MT6373_AUXADC_ADC40_L                  0x10c8
+#define MT6373_AUXADC_ADC_CH12_L               0x10d2
+#define MT6373_AUXADC_ADC_CH12_H               0x10d3
+#define MT6373_AUXADC_RQST0                    0x1108
+#define MT6373_AUXADC_RQST1                    0x1109
+#define MT6373_AUXADC_RQST3                    0x110c
+#define MT6373_SDMADC_RQST0                    0x110e
+#define MT6373_SDMADC_CON0                     0x11c4
+#define MT6373_BUCK_TOP_INT_CON0               0x1411
+#define MT6373_BUCK_TOP_INT_CON1               0x1414
+#define MT6373_BUCK_TOP_INT_STATUS0            0x141d
+#define MT6373_BUCK_TOP_INT_STATUS1            0x141e
+#define MT6373_LDO_TOP_INT_CON0                0x1b10
+#define MT6373_LDO_TOP_INT_CON1                0x1b13
+#define MT6373_LDO_TOP_INT_CON2                0x1b16
+#define MT6373_LDO_TOP_INT_STATUS0             0x1b22
+#define MT6373_LDO_TOP_INT_STATUS1             0x1b23
+#define MT6373_LDO_TOP_INT_STATUS2             0x1b24
+#define MT6373_LDO_VMCH_CON0                   0x1cb1
+#define MT6373_LDO_VMCH_CON1                   0x1cb2
+#define MT6373_LDO_VMCH_CON2                   0x1cb3
+
+#endif /* __MFD_MT6373_REGISTERS_H__ */
--
2.46.0


From thomas.richard at bootlin.com  Fri Mar 14 02:03:01 2025
From: thomas.richard at bootlin.com (Thomas Richard)
Date: Fri, 14 Mar 2025 10:03:01 +0100
Subject: [PATCH 4/4] PCI: j721e: Add support to build as a loadable module
In-Reply-To: <20250307103128.3287497-5-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-5-s-vadapalli@ti.com>
Message-ID: <88b3ecbe-32b6-4310-afb9-da19a2d0506a@bootlin.com>

> +
> +	if (pcie->reset_gpio) {
> +		msleep(PCIE_T_PVPERL_MS);
> +		gpiod_set_value_cansleep(pcie->reset_gpio, 1);
> +	}
> +
> +	if (pcie->refclk)
> +		clk_disable_unprepare(pcie->refclk);
>  

Hello Siddharth,

I think clk_disable_unprepare() is a no-op if the clock is NULL, so the
if statement is useless.

https://elixir.bootlin.com/linux/v6.14-rc6/source/include/linux/clk.h#L1157
https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/clk/clk.c#L1237
https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/clk/clk.c#L1099

Regards,

Thomas




From Lu.Tang at mediatek.com  Fri Mar 14 02:01:11 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:01:11 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggNS81XSBkdC1iaW5kaW5nczogcG1pYzogbWVkaWF0?=
 =?utf-8?Q?ek:_Add_pmic_documents?=
In-Reply-To: <20250314073307.25092-6-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-6-Lu.Tang@mediatek.com>
Message-ID: <SEZPR03MB6891E21CD04880AB1AC91BFC80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>

Update email

-----????-----
???: Lu.Tang <Lu.Tang at mediatek.com> 
????: 2025?3?14? 15:33
???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
??: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents

Add new pmic mfd and adc documents for mt8196

Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>
---
 .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |  31 ++++
 .../bindings/input/mediatek,pmic-keys.yaml    |   1 +
 .../bindings/mfd/mediatek,mt6685.yaml         |  50 +++++
 .../bindings/mfd/mediatek,spmi-pmic.yaml      | 173 ++++++++++++++++++
 .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |   1 +
 5 files changed, 256 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
new file mode 100644
index 000000000000..250782ad7d01
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxad
+++ c.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2
+---
+$id: 
+http://devicetree.org/schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SPMI PMIC AUXADC
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description:
+  The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
+  in some MediaTek PMICs, performing various PMIC related measurements
+  such as battery and PMIC internal voltage regulators temperatures,
+  other than voltages for various PMIC internal components.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt6363-auxadc
+      - mediatek,mt6373-auxadc
+
+  "#io-channel-cells":
+    const: 1
+
+required:
+  - compatible
+  - "#io-channel-cells"
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index b95435bd6a9b..ce760039d4c2 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -31,6 +31,7 @@ properties:
       - mediatek,mt6358-keys
       - mediatek,mt6359-keys
       - mediatek,mt6397-keys
+      - mediatek,mt6363-keys
 
   power-off-time-sec: true
 
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
new file mode 100644
index 000000000000..d3276df8952b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt6685.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6685 Clock IC
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description: |
+  MT6685 is a clock IC.
+  Please see the sub-modules below for supported features.
+
+  MT6685 is a multifunction device with the following sub modules:
+  - RTC
+  - Clock
+
+properties:
+  compatible:
+    const: mediatek,mt6685
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    spmi {
+        mfd at 9 {
+            compatible = "mediatek,mt6685";
+            reg = <0x9 SPMI_USID>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
new file mode 100644
index 000000000000..a8f1231623cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SPMI PMICs multi-function device
+
+maintainers:
+  - Lu Tang <lu.tang at mediatek.com>
+
+description: |
+  Some Mediatek PMICs are interfaced to the chip via the SPMI (System 
+Power
+  Management Interface) bus.
+
+  The Mediatek SPMI series includes the MT6363, MT6373, MT6316 and 
+ other  PMICs.Please see the sub-modules below for supported features.
+
+   MT6363/MT6373 is a multifunction device with the following sub modules:
+  - Regulators
+  - ADC
+  - GPIO
+  - Keys
+   MT6316 is a multifunction device with the following sub modules:
+  - Regulators
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - mediatek,mt6363
+          - mediatek,mt6373
+          - mediatek,mt6316
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+  regulators:
+    type: object
+    description:
+      List of child nodes that specify the regulators.
+    additionalProperties: true
+
+    properties:
+      compatible:
+        oneOf:
+          - enum:
+              - mediatek,mt6363-regulator
+              - mediatek,mt6373-regulator
+              - mediatek,mt6316-regulator
+
+    required:
+      - compatible
+
+  adc:
+    type: object
+    $ref: /schemas/iio/adc/mediatek,spmi-pmic-auxadc.yaml#
+    unevaluatedProperties: false
+
+  keys:
+    type: object
+    $ref: /schemas/input/mediatek,pmic-keys.yaml
+    unevaluatedProperties: false
+    description:
+      Power and Home keys.
+
+  pinctrl:
+    type: object
+    $ref: /schemas/pinctrl/mediatek,mt65xx-pinctrl.yaml
+    unevaluatedProperties: false
+    description:
+      Pin controller
+
+required:
+  - compatible
+  - regulators
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/spmi/spmi.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    spmi {
+        main_pmic: pmic at 4 {
+            compatible = "mediatek,mt6363";
+            reg = <0x4 SPMI_USID>;
+            interrupts = <0x4 IRQ_TYPE_NONE>;
+            #address-cells = <0>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+
+            mt6363keys: keys {
+                compatible = "mediatek,mt6363-keys";
+                mediatek,long-press-mode = <1>;
+                power-off-time-sec = <0>;
+
+                power {
+                    linux,keycodes = <116>;
+                    wakeup-source;
+                };
+
+                home {
+                    linux,keycodes = <115>;
+                };
+            };
+
+            mt6363_pio: pinctrl {
+                compatible = "mediatek,mt6363-pinctrl";
+                gpio-controller;
+                #gpio-cells = <2>;
+            };
+
+            mt6363regulator: regulators {
+                compatible = "mediatek,mt6363-regulator";
+
+                mt6363_vs2: vs2 {
+                    regulator-name = "mt6363_vs2";
+                    regulator-allowed-modes = <0 1 2>;
+                    regulator-always-on;
+                    regulator-allow-set-load;
+                };
+
+                mt6363_vbuck1: vbuck1 {
+                    regulator-name = "mt6363_vbuck1";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck2: vbuck2 {
+                    regulator-name = "mt6363_vbuck2";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck3: vbuck3 {
+                    regulator-name = "mt6363_vbuck3";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck4: vbuck4 {
+                    regulator-name = "mt6363_vbuck4";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck5: vbuck5 {
+                    regulator-name = "mt6363_vbuck5";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck6: vbuck6 {
+                    regulator-name = "mt6363_vbuck6";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                mt6363_vbuck7: vbuck7 {
+                    regulator-name = "mt6363_vbuck7";
+                    regulator-allowed-modes = <0 1 2>;
+                };
+
+                // ...
+
+                mt6363_isink_load: isink-load {
+                    regulator-name = "mt6363_isink_load";
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
index bccff08a5ba3..bf3ba58a7705 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.
+++ yaml
@@ -17,6 +17,7 @@ properties:
     enum:
       - mediatek,mt2701-pinctrl
       - mediatek,mt2712-pinctrl
+      - mediatek,mt6363-pinctrl
       - mediatek,mt6397-pinctrl
       - mediatek,mt7623-pinctrl
       - mediatek,mt8127-pinctrl
--
2.46.0


From Lu.Tang at mediatek.com  Fri Mar 14 02:04:59 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:04:59 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggMS81XSBwbWljOiBtZWRpYXRlazogQWRkIHBtaWMg?=
 =?utf-8?Q?auxadc_driver?=
In-Reply-To: <20250314073307.25092-2-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-2-Lu.Tang@mediatek.com>
Message-ID: <SEZPR03MB6891229DDEDC8FB1EC1F135880D22@SEZPR03MB6891.apcprd03.prod.outlook.com>


Update email address

-----????-----
???: Lu.Tang <Lu.Tang at mediatek.com> 
????: 2025?3?14? 15:32
???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
??: [PATCH 1/5] pmic: mediatek: Add pmic auxadc driver

From: "Lu.Tang" <lu.tang at mediatek.com>

Add pmic mt6363 and mt6373 auxadc driver

Signed-off-by: Lu Tang <lu.tang at mediatek.com>
---
 drivers/iio/adc/Kconfig             |  10 +
 drivers/iio/adc/Makefile            |   1 +
 drivers/iio/adc/mtk-spmi-pmic-adc.c | 576 ++++++++++++++++++++++++++++
 3 files changed, 587 insertions(+)
 create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 27413516216c..7c4b5f8f7209 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1039,6 +1039,16 @@ config MEDIATEK_MT6577_AUXADC
 	  This driver can also be built as a module. If so, the module will be
 	  called mt6577_auxadc.
 
+config MEDIATEK_SPMI_PMIC_ADC
+	tristate "MediaTek SPMI PMIC ADC Support"
+	depends on MFD_MTK_SPMI_PMIC
+	help
+	  Say yes here to enable support for MediaTek SPMI PMIC ADC.
+	  The driver supports multiple channels read.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called mtk-spmi-pmic-adc.
+
 config MEN_Z188_ADC
 	tristate "MEN 16z188 ADC IP Core support"
 	depends on MCB
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 9f26d5eca822..b3224abea040 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_MEDIATEK_MT6359_AUXADC) += mt6359-auxadc.o
 obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
 obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
 obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
+obj-$(CONFIG_MEDIATEK_SPMI_PMIC_ADC) += mtk-spmi-pmic-adc.o
 obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
 obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o diff --git a/drivers/iio/adc/mtk-spmi-pmic-adc.c b/drivers/iio/adc/mtk-spmi-pmic-adc.c
new file mode 100644
index 000000000000..61e062bc8cf5
--- /dev/null
+++ b/drivers/iio/adc/mtk-spmi-pmic-adc.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mfd/mt6363/registers.h> #include 
+<linux/mfd/mt6373/registers.h> #include <linux/module.h> #include 
+<linux/of.h> #include <linux/of_device.h> #include <linux/property.h> 
+#include <linux/platform_device.h> #include <linux/power_supply.h> 
+#include <linux/regmap.h> #include <linux/regulator/consumer.h> 
+#include <linux/syscore_ops.h>
+
+#include <dt-bindings/iio/mt635x-auxadc.h>
+
+#define AUXADC_RDY_BIT			BIT(15)
+
+#define AUXADC_DEF_R_RATIO		1
+#define AUXADC_DEF_AVG_NUM		32
+
+#define AUXADC_AVG_TIME_US		10
+#define AUXADC_POLL_DELAY_US		100
+#define AUXADC_TIMEOUT_US		32000
+#define VOLT_FULL			1840
+
+#define IMP_VOLT_FULL			18400
+#define IMIX_R_MIN_MOHM			100
+#define IMIX_R_CALI_CNT			2
+
+#define EXT_THR_PURES_SHIFT		3
+#define EXT_THR_SEL_MASK		0x1F
+
+#define DT_CHANNEL_CONVERT(val)		((val) & 0xFF)
+#define DT_PURES_CONVERT(val)		(((val) & 0xFF00) >> 8)
+
+struct pmic_adc_device {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex lock;
+	struct iio_chan_spec *iio_chans;
+	unsigned int nchannels;
+	const struct auxadc_info *info;
+	struct regulator *isink_load;
+	int imix_r;
+	int imp_curr;
+	int pre_uisoc;
+};
+
+static struct pmic_adc_device *imix_r_dev;
+
+/*
+ * @ch_name:	HW channel name
+ * @res:	ADC resolution
+ * @r_ratio:	resistance ratio, represented by r_ratio[0] / r_ratio[1]
+ * @avg_num:	sampling times of AUXADC measurements then average it
+ * @regs:	request and data output registers for this channel
+ */
+struct auxadc_channels {
+	enum iio_chan_type type;
+	long info_mask;
+	/* AUXADC channel attribute */
+	const char *ch_name;
+	unsigned char res;
+	unsigned char r_ratio[2];
+	unsigned short avg_num;
+	const struct auxadc_regs *regs;
+};
+
+#define AUXADC_CHANNEL(_ch_name, _res)	\
+	[AUXADC_##_ch_name] = {				\
+		.type = IIO_VOLTAGE,			\
+		.info_mask = BIT(IIO_CHAN_INFO_RAW) |		\
+			     BIT(IIO_CHAN_INFO_PROCESSED),	\
+		.ch_name = __stringify(_ch_name),	\
+		.res = _res,				\
+	}
+
+/*
+ * The array represents all possible AUXADC channels found
+ * in the supported PMICs.
+ */
+static struct auxadc_channels auxadc_chans[] = {
+	AUXADC_CHANNEL(BATADC, 15),
+	AUXADC_CHANNEL(VCDT, 12),
+	AUXADC_CHANNEL(BAT_TEMP, 12),
+	AUXADC_CHANNEL(CHIP_TEMP, 12),
+	AUXADC_CHANNEL(VCORE_TEMP, 12),
+	AUXADC_CHANNEL(VPROC_TEMP, 12),
+	AUXADC_CHANNEL(VGPU_TEMP, 12),
+	AUXADC_CHANNEL(ACCDET, 12),
+	AUXADC_CHANNEL(HPOFS_CAL, 15),
+	AUXADC_CHANNEL(VTREF, 12),
+	AUXADC_CHANNEL(VBIF, 12),
+	AUXADC_CHANNEL(IMP, 15),
+	[AUXADC_IMIX_R] = {
+		.type = IIO_RESISTANCE,
+		.info_mask = BIT(IIO_CHAN_INFO_RAW),
+		.ch_name = "IMIX_R",
+	},
+	AUXADC_CHANNEL(VSYSSNS, 15),
+	AUXADC_CHANNEL(VIN1, 15),
+	AUXADC_CHANNEL(VIN2, 15),
+	AUXADC_CHANNEL(VIN3, 15),
+	AUXADC_CHANNEL(VIN4, 15),
+	AUXADC_CHANNEL(VIN5, 15),
+	AUXADC_CHANNEL(VIN6, 15),
+	AUXADC_CHANNEL(VIN7, 15),
+};
+
+struct auxadc_regs {
+	unsigned int enable_reg;
+	unsigned int enable_mask;
+	unsigned int ready_reg;
+	unsigned int ready_mask;
+	unsigned int value_reg;
+	unsigned int ext_thr_sel;
+	u8 src_sel;
+};
+
+#define AUXADC_REG(_ch_name, _chip, _enable_reg, _enable_mask, _value_reg) \
+	[AUXADC_##_ch_name] = {				\
+		.enable_reg = _chip##_##_enable_reg,	\
+		.enable_mask = _enable_mask,		\
+		.ready_reg = _chip##_##_value_reg,	\
+		.ready_mask = AUXADC_RDY_BIT,		\
+		.value_reg = _chip##_##_value_reg,	\
+	}						\
+
+#define TIA_ADC_REG(_src_sel, _chip)	\
+	[AUXADC_VIN##_src_sel] = {			\
+		.enable_reg = _chip##_AUXADC_RQST1,	\
+		.enable_mask = BIT(4),			\
+		.ready_reg = _chip##_AUXADC_ADC_CH12_L,	\
+		.ready_mask = AUXADC_RDY_BIT,		\
+		.value_reg = _chip##_AUXADC_ADC_CH12_L,	\
+		.ext_thr_sel = _chip##_SDMADC_CON0,	\
+		.src_sel = _src_sel,			\
+	}						\
+
+static const struct auxadc_regs mt6363_auxadc_regs_tbl[] = {
+	AUXADC_REG(BATADC, MT6363, AUXADC_RQST0, BIT(0), AUXADC_ADC0_L),
+	AUXADC_REG(BAT_TEMP, MT6363, AUXADC_RQST0, BIT(3), AUXADC_ADC3_L),
+	AUXADC_REG(CHIP_TEMP, MT6363, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
+	AUXADC_REG(VCORE_TEMP, MT6363, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
+	AUXADC_REG(VPROC_TEMP, MT6363, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
+	AUXADC_REG(VGPU_TEMP, MT6363, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
+	AUXADC_REG(VTREF, MT6363, AUXADC_RQST1, BIT(3), AUXADC_ADC11_L),
+	[AUXADC_IMP] = {
+		.enable_reg = MT6363_AUXADC_IMP0,
+		.enable_mask = BIT(0),
+		.ready_reg = MT6363_AUXADC_IMP1,
+		.ready_mask = BIT(7),
+		.value_reg = MT6363_AUXADC_ADC42_L,
+	},
+	AUXADC_REG(VSYSSNS, MT6363, AUXADC_RQST1, BIT(6), AUXADC_ADC_CH14_L),
+	TIA_ADC_REG(1, MT6363),
+	TIA_ADC_REG(2, MT6363),
+	TIA_ADC_REG(3, MT6363),
+	TIA_ADC_REG(4, MT6363),
+	TIA_ADC_REG(5, MT6363),
+	TIA_ADC_REG(6, MT6363),
+	TIA_ADC_REG(7, MT6363),
+};
+
+static const struct auxadc_regs mt6373_auxadc_regs_tbl[] = {
+	AUXADC_REG(CHIP_TEMP, MT6373, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
+	AUXADC_REG(VCORE_TEMP, MT6373, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
+	AUXADC_REG(VPROC_TEMP, MT6373, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
+	AUXADC_REG(VGPU_TEMP, MT6373, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
+	TIA_ADC_REG(1, MT6373),
+	TIA_ADC_REG(2, MT6373),
+	TIA_ADC_REG(3, MT6373),
+	TIA_ADC_REG(4, MT6373),
+	TIA_ADC_REG(5, MT6373),
+};
+
+struct auxadc_info {
+	const struct auxadc_regs *regs_tbl;
+};
+
+static const struct auxadc_info mt6363_info = {
+	.regs_tbl = mt6363_auxadc_regs_tbl,
+};
+
+static const struct auxadc_info mt6373_info = {
+	.regs_tbl = mt6373_auxadc_regs_tbl,
+};
+
+#define regmap_bulk_read_poll_timeout(map, addr, val, val_count, cond, 
+sleep_us, timeout_us) \ ({ \
+	u64 __timeout_us = (timeout_us); \
+	unsigned long __sleep_us = (sleep_us); \
+	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
+	int __ret; \
+	might_sleep_if(__sleep_us); \
+	for (;;) { \
+		__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
+		if (__ret) \
+			break; \
+		if (cond) \
+			break; \
+		if ((__timeout_us) && \
+		    ktime_compare(ktime_get(), __timeout) > 0) { \
+			__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
+			break; \
+		} \
+		if (__sleep_us) \
+			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+	} \
+	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+})
+
+/*
+ * @adc_dev:	 pointer to the struct pmic_adc_device
+ * @auxadc_chan: pointer to the struct auxadc_channels, it represents specific
+		 auxadc channel
+ * @val:	 pointer to output value
+ */
+static int get_auxadc_out(struct pmic_adc_device *adc_dev,
+			  int channel, int channel2, int *val) {
+	int ret;
+	u16 buf = 0;
+	const struct auxadc_channels *auxadc_chan = &auxadc_chans[channel];
+
+	if (!auxadc_chan->regs)
+		return -EINVAL;
+
+	if (auxadc_chan->regs->ext_thr_sel) {
+		buf = (channel2 << EXT_THR_PURES_SHIFT)
+			| auxadc_chan->regs->src_sel;
+		ret = regmap_update_bits(adc_dev->regmap,
+					 auxadc_chan->regs->ext_thr_sel,
+					 EXT_THR_SEL_MASK, buf);
+		if (ret < 0)
+			return ret;
+	}
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg,
+		     auxadc_chan->regs->enable_mask);
+	usleep_range(auxadc_chan->avg_num * AUXADC_AVG_TIME_US,
+		     (auxadc_chan->avg_num + 1) * AUXADC_AVG_TIME_US);
+
+	ret = regmap_bulk_read_poll_timeout(adc_dev->regmap,
+					    auxadc_chan->regs->value_reg,
+					    buf, 2,
+					    (buf & AUXADC_RDY_BIT),
+					    AUXADC_POLL_DELAY_US,
+					    AUXADC_TIMEOUT_US);
+	*val = buf & (BIT(auxadc_chan->res) - 1);
+	if (ret)
+		dev_err(adc_dev->dev, "%s ret error code:%d!\n", 
+auxadc_chan->ch_name, ret);
+
+	/* set PURES to OPEN after measuring done */
+	if (auxadc_chan->regs->ext_thr_sel) {
+		buf = (ADC_PURES_OPEN << EXT_THR_PURES_SHIFT)
+			| auxadc_chan->regs->src_sel;
+		ret = regmap_update_bits(adc_dev->regmap,
+					 auxadc_chan->regs->ext_thr_sel,
+					 EXT_THR_SEL_MASK, buf);
+	}
+
+	return ret;
+}
+
+static int gauge_get_imp_ibat(void)
+{
+	struct power_supply *psy;
+	union power_supply_propval prop;
+	int ret;
+
+	psy = power_supply_get_by_name("mtk-gauge");
+	if (!psy)
+		return 0;
+
+	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
+	if (ret)
+		return ret;
+
+	power_supply_put(psy);
+	return prop.intval;
+}
+
+static int get_imp_out(struct pmic_adc_device *adc_dev, int *val) {
+	int ret;
+	unsigned int buf = 0;
+	const struct auxadc_channels *auxadc_chan = &auxadc_chans[AUXADC_IMP];
+
+	if (!auxadc_chan->regs)
+		return -EINVAL;
+
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg,
+		     auxadc_chan->regs->enable_mask);
+	ret = regmap_read_poll_timeout(adc_dev->regmap, auxadc_chan->regs->ready_reg,
+					   buf, buf & auxadc_chan->regs->ready_mask,
+					   AUXADC_POLL_DELAY_US,
+					   AUXADC_TIMEOUT_US);
+	if (ret) {
+		dev_err(adc_dev->dev, "%s %s ret error code:%d!\n",
+			__func__, auxadc_chan->ch_name, ret);
+		return ret;
+	}
+
+	ret = regmap_bulk_read(adc_dev->regmap, auxadc_chan->regs->value_reg, (u8 *) &buf, 2);
+	if (ret)
+		return ret;
+	*val = buf & (BIT(auxadc_chan->res) - 1);
+	adc_dev->imp_curr = gauge_get_imp_ibat();
+
+	regmap_write(adc_dev->regmap,
+		     auxadc_chan->regs->enable_reg, 0);
+
+	return 0;
+}
+
+static int pmic_adc_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask) {
+	struct pmic_adc_device *adc_dev = iio_priv(indio_dev);
+	const struct auxadc_channels *auxadc_chan;
+	int auxadc_out = 0;
+	int ret = 0;
+
+	mutex_lock(&adc_dev->lock);
+	switch (chan->channel) {
+	case AUXADC_IMP:
+		ret = get_imp_out(adc_dev, &auxadc_out);
+		break;
+	case AUXADC_IMIX_R:
+		auxadc_out = adc_dev->imix_r;
+		break;
+	default:
+		ret = get_auxadc_out(adc_dev,
+				     chan->channel, chan->channel2,
+				     &auxadc_out);
+		break;
+	}
+	mutex_unlock(&adc_dev->lock);
+
+	if (ret && ret != -ETIMEDOUT)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_PROCESSED:
+		auxadc_chan = &auxadc_chans[chan->channel];
+		*val = auxadc_out * auxadc_chan->r_ratio[0] * VOLT_FULL;
+		*val = (*val / auxadc_chan->r_ratio[1]) >> auxadc_chan->res;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_RAW:
+		*val = auxadc_out;
+		ret = IIO_VAL_INT;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (chan->channel == AUXADC_IMP) {
+		*val2 = adc_dev->imp_curr;
+		ret = IIO_VAL_INT_MULTIPLE;
+	}
+
+	return ret;
+}
+
+static int pmic_adc_fwnode_xlate(struct iio_dev *indio_dev,
+			     const struct fwnode_reference_args *iiospec) {
+	int i;
+	int channel = DT_CHANNEL_CONVERT(iiospec->args[0]);
+	int channel2 = DT_PURES_CONVERT(iiospec->args[0]);
+
+	for (i = 0; i < indio_dev->num_channels; i++) {
+		if (indio_dev->channels[i].channel == channel &&
+		    indio_dev->channels[i].channel2 == channel2)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info pmic_adc_info = {
+	.read_raw = &pmic_adc_read_raw,
+	.fwnode_xlate = &pmic_adc_fwnode_xlate, };
+
+static int auxadc_init_imix_r(struct pmic_adc_device *adc_dev,
+			      struct device_node *imix_r_node) {
+	unsigned int val = 0;
+	int ret;
+
+	if (!adc_dev)
+		return -EINVAL;
+
+	adc_dev->isink_load = devm_regulator_get_exclusive(adc_dev->dev, "isink_load");
+	if (IS_ERR(adc_dev->isink_load)) {
+		dev_err(adc_dev->dev, "Failed to get isink_load regulator, ret=%d\n",
+			(int)PTR_ERR(adc_dev->isink_load));
+		return PTR_ERR(adc_dev->isink_load);
+	}
+
+	imix_r_dev = adc_dev;
+	if (imix_r_dev->imix_r)
+		return 0;
+
+	ret = of_property_read_u32(imix_r_node, "val", &val);
+	if (ret)
+		dev_notice(imix_r_dev->dev, "no imix_r, ret=%d\n", ret);
+	imix_r_dev->imix_r = (int)val;
+	imix_r_dev->pre_uisoc = 101;
+	return 0;
+}
+
+static int auxadc_get_data_from_dt(struct pmic_adc_device *adc_dev,
+				   struct iio_chan_spec *iio_chan,
+				   struct device_node *node)
+{
+	struct auxadc_channels *auxadc_chan;
+	unsigned int channel = 0;
+	unsigned int value = 0;
+	unsigned int val_arr[2] = {0};
+	int ret;
+
+	ret = of_property_read_u32(node, "channel", &channel);
+	if (ret) {
+		dev_err(adc_dev->dev, "invalid channel in node:%s\n",
+			   node->name);
+		return ret;
+	}
+	if (channel > AUXADC_CHAN_MAX) {
+		dev_err(adc_dev->dev, "invalid channel number %d in node:%s\n",
+			   channel, node->name);
+		return -EINVAL;
+	}
+	if (channel >= ARRAY_SIZE(auxadc_chans)) {
+		dev_err(adc_dev->dev, "channel number %d in node:%s not exists\n",
+			   channel, node->name);
+		return -EINVAL;
+	}
+	iio_chan->channel = channel;
+	iio_chan->datasheet_name = auxadc_chans[channel].ch_name;
+	iio_chan->info_mask_separate = auxadc_chans[channel].info_mask;
+	iio_chan->type = auxadc_chans[channel].type;
+	iio_chan->extend_name = node->name;
+	ret = of_property_read_u32(node, "pures", &value);
+	if (!ret)
+		iio_chan->channel2 = value;
+
+	if (channel == AUXADC_IMIX_R)
+		return auxadc_init_imix_r(adc_dev, node);
+
+	auxadc_chan = &auxadc_chans[channel];
+	auxadc_chan->regs = &adc_dev->info->regs_tbl[channel];
+
+	ret = of_property_read_u32_array(node, "resistance-ratio", val_arr, 2);
+	if (!ret) {
+		auxadc_chan->r_ratio[0] = val_arr[0];
+		auxadc_chan->r_ratio[1] = val_arr[1];
+	} else {
+		auxadc_chan->r_ratio[0] = AUXADC_DEF_R_RATIO;
+		auxadc_chan->r_ratio[1] = 1;
+	}
+
+	ret = of_property_read_u32(node, "avg-num", &value);
+	if (!ret)
+		auxadc_chan->avg_num = value;
+	else
+		auxadc_chan->avg_num = AUXADC_DEF_AVG_NUM;
+
+	return 0;
+}
+
+static int auxadc_parse_dt(struct pmic_adc_device *adc_dev,
+			   struct device_node *node)
+{
+	struct iio_chan_spec *iio_chan;
+	struct device_node *child;
+	unsigned int index = 0;
+	int ret;
+
+	adc_dev->nchannels = of_get_available_child_count(node);
+	if (!adc_dev->nchannels)
+		return -EINVAL;
+
+	adc_dev->iio_chans = devm_kcalloc(adc_dev->dev, adc_dev->nchannels,
+		sizeof(*adc_dev->iio_chans), GFP_KERNEL);
+	if (!adc_dev->iio_chans)
+		return -ENOMEM;
+	iio_chan = adc_dev->iio_chans;
+
+	for_each_available_child_of_node(node, child) {
+		ret = auxadc_get_data_from_dt(adc_dev, iio_chan, child);
+		if (ret < 0) {
+			of_node_put(child);
+			return ret;
+		}
+		iio_chan->indexed = 1;
+		iio_chan->address = index++;
+		iio_chan++;
+	}
+
+	return 0;
+}
+
+static int pmic_adc_probe(struct platform_device *pdev) {
+	struct device_node *node = pdev->dev.of_node;
+	struct pmic_adc_device *adc_dev;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	adc_dev = iio_priv(indio_dev);
+	adc_dev->dev = &pdev->dev;
+	adc_dev->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	mutex_init(&adc_dev->lock);
+	adc_dev->info = of_device_get_match_data(&pdev->dev);
+
+	ret = auxadc_parse_dt(adc_dev, node);
+	if (ret) {
+		dev_notice(&pdev->dev, "auxadc_parse_dt fail, ret=%d\n", ret);
+		return ret;
+	}
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->info = &pmic_adc_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = adc_dev->iio_chans;
+	indio_dev->num_channels = adc_dev->nchannels;
+
+	ret = devm_iio_device_register(&pdev->dev, indio_dev);
+	if (ret < 0) {
+		dev_notice(&pdev->dev, "failed to register iio device!\n");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "probe done\n");
+
+	return 0;
+}
+
+static const struct of_device_id pmic_adc_of_match[] = {
+	{ .compatible = "mediatek,mt6363-auxadc", .data = &mt6363_info, },
+	{ .compatible = "mediatek,mt6373-auxadc", .data = &mt6373_info, },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pmic_adc_of_match);
+
+static struct platform_driver pmic_adc_driver = {
+	.driver = {
+		.name = "mtk-spmi-pmic-adc",
+		.of_match_table = pmic_adc_of_match,
+	},
+	.probe	= pmic_adc_probe,
+};
+module_platform_driver(pmic_adc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lu Tang <lu.tang at mediatek.com>"); 
+MODULE_DESCRIPTION("MediaTek SPMI PMIC ADC Driver");
--
2.46.0


From Lu.Tang at mediatek.com  Fri Mar 14 02:06:14 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:06:14 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggMC81XSBBZGQgUE1JQyBhbmQgU1BNSSBkcml2ZXIg?=
 =?utf-8?Q?for_mt8196?=
In-Reply-To: <20250314073307.25092-1-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
Message-ID: <SEZPR03MB6891C5D6CBC04C756B78209280D22@SEZPR03MB6891.apcprd03.prod.outlook.com>


Update email address

-----????-----
???: Lu.Tang <Lu.Tang at mediatek.com> 
????: 2025?3?14? 15:32
???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
??: [PATCH 0/5] Add PMIC and SPMI driver for mt8196

This series is based on linux-next.

Changes in v0:
- Modify SPMI driver for mt8196
- Add SPMI PMIC mfd driver
- Add PMIC regulator driver for mt8196

*** BLURB HERE ***

Lu.Tang (5):
  pmic: mediatek: Add pmic auxadc driver
  pmic: mediatek: Add pmic regulator driver
  pmic: mediatek: Add spmi pmic mfd driver
  spmi: mediatek: modify spmi dirver for mt8196
  dt-bindings: pmic: mediatek: Add pmic documents

 .../iio/adc/mediatek,spmi-pmic-auxadc.yaml    |   31 +
 .../bindings/input/mediatek,pmic-keys.yaml    |    1 +
 .../bindings/mfd/mediatek,mt6685.yaml         |   50 +
 .../bindings/mfd/mediatek,spmi-pmic.yaml      |  173 +++
 .../pinctrl/mediatek,mt65xx-pinctrl.yaml      |    1 +
 drivers/iio/adc/Kconfig                       |   10 +
 drivers/iio/adc/Makefile                      |    1 +
 drivers/iio/adc/mtk-spmi-pmic-adc.c           |  576 +++++++++
 drivers/mfd/Kconfig                           |   26 +
 drivers/mfd/Makefile                          |    2 +
 drivers/mfd/mt6685-core.c                     |   83 ++
 drivers/mfd/mtk-spmi-pmic.c                   |  518 ++++++++
 drivers/regulator/Kconfig                     |   34 +
 drivers/regulator/Makefile                    |    3 +
 drivers/regulator/mt6316-regulator.c          |  381 ++++++
 drivers/regulator/mt6363-regulator.c          | 1106 +++++++++++++++++
 drivers/regulator/mt6373-regulator.c          |  826 ++++++++++++
 drivers/spmi/spmi-mtk-pmif.c                  | 1040 +++++++++++++++-
 include/linux/mfd/mt6363/core.h               |  134 ++
 include/linux/mfd/mt6363/registers.h          |  168 +++
 include/linux/mfd/mt6373/core.h               |   94 ++
 include/linux/mfd/mt6373/registers.h          |   53 +
 include/linux/regulator/mt6316-regulator.h    |   48 +
 include/linux/regulator/mt6363-regulator.h    |  424 +++++++
 include/linux/regulator/mt6373-regulator.h    |  318 +++++
 25 files changed, 6037 insertions(+), 64 deletions(-)  create mode 100644 Documentation/devicetree/bindings/iio/adc/mediatek,spmi-pmic-auxadc.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6685.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
 create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c
 create mode 100644 drivers/mfd/mt6685-core.c  create mode 100644 drivers/mfd/mtk-spmi-pmic.c  create mode 100644 drivers/regulator/mt6316-regulator.c
 create mode 100644 drivers/regulator/mt6363-regulator.c
 create mode 100644 drivers/regulator/mt6373-regulator.c
 create mode 100644 include/linux/mfd/mt6363/core.h  create mode 100644 include/linux/mfd/mt6363/registers.h
 create mode 100644 include/linux/mfd/mt6373/core.h  create mode 100644 include/linux/mfd/mt6373/registers.h
 create mode 100644 include/linux/regulator/mt6316-regulator.h
 create mode 100644 include/linux/regulator/mt6363-regulator.h
 create mode 100644 include/linux/regulator/mt6373-regulator.h

--
2.46.0


From s-vadapalli at ti.com  Fri Mar 14 02:07:09 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Fri, 14 Mar 2025 14:37:09 +0530
Subject: [PATCH 4/4] PCI: j721e: Add support to build as a loadable module
In-Reply-To: <88b3ecbe-32b6-4310-afb9-da19a2d0506a@bootlin.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-5-s-vadapalli@ti.com>
 <88b3ecbe-32b6-4310-afb9-da19a2d0506a@bootlin.com>
Message-ID: <20250314090709.oaaxhapvg4fxdjc7@uda0492258>

On Fri, Mar 14, 2025 at 10:03:01AM +0100, Thomas Richard wrote:

Hello Thomas,

> > +
> > +	if (pcie->reset_gpio) {
> > +		msleep(PCIE_T_PVPERL_MS);
> > +		gpiod_set_value_cansleep(pcie->reset_gpio, 1);
> > +	}
> > +
> > +	if (pcie->refclk)
> > +		clk_disable_unprepare(pcie->refclk);
> >  
> 
> Hello Siddharth,
> 
> I think clk_disable_unprepare() is a no-op if the clock is NULL, so the
> if statement is useless.
> 
> https://elixir.bootlin.com/linux/v6.14-rc6/source/include/linux/clk.h#L1157
> https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/clk/clk.c#L1237
> https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/clk/clk.c#L1099

Thank you for pointing it out. I will drop the unnecessary check in the
next version. I will wait for feedback on other patches in this series
before I post the next version.

Regards,
Siddharth.


From chaitanya.kumar.borah at intel.com  Fri Mar 14 02:17:40 2025
From: chaitanya.kumar.borah at intel.com (Borah, Chaitanya Kumar)
Date: Fri, 14 Mar 2025 09:17:40 +0000
Subject: Regression on linux-next (next-20250312)
Message-ID: <SJ1PR11MB61295DE21A1184AEE0786E25B9D22@SJ1PR11MB6129.namprd11.prod.outlook.com>

Hello Robin,

Hope you are doing well. I am Chaitanya from the linux graphics team in Intel.

This mail is regarding a regression we are seeing in our CI runs[1] on linux-next repository.

Since the version next-20250312 [2], we are seeing the following regression

`````````````````````````````````````````````````````````````````````````````````
<4>[    6.246790] reg-dummy reg-dummy: late IOMMU probe at driver bind, something fishy here!
<4>[    6.246812] WARNING: CPU: 0 PID: 1 at drivers/iommu/iommu.c:449 __iommu_probe_device+0x140/0x570
<4>[    6.246822] Modules linked in:
<4>[    6.246830] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc6-next-20250312-next-20250312-g9fbcd7b32bf7+ #1
<4>[    6.246838] Hardware name: Intel Corporation Arrow Lake Client Platform/MTL-S UDIMM 2DPC EVCRB, BIOS MTLSFWI1.R00.4400.D85.2410100007 10/10/2024
<4>[    6.246847] RIP: 0010:__iommu_probe_device+0x140/0x570
`````````````````````````````````````````````````````````````````````````````````
Details log can be found in [3].

After bisecting the tree, the following patch [4] seems to be the first "bad" commit

`````````````````````````````````````````````````````````````````````````````````````````````````````````
commit bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c
Author: Robin Murphy mailto:robin.murphy at arm.com
Date:   Fri Feb 28 15:46:33 2025 +0000

    iommu: Get DT/ACPI parsing into the proper probe path

`````````````````````````````````````````````````````````````````````````````````````````````````````````

We also verified that if we revert the patch the issue is not seen.

Could you please check why the patch causes this regression and provide a fix if necessary?

Thank you.

Regards

Chaitanya

[1] https://intel-gfx-ci.01.org/tree/linux-next/combined-alt.html?
[2] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312
[3] https://intel-gfx-ci.01.org/tree/linux-next/next-20250312/bat-arls-6/boot0.txt
[4] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312&id=bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c



From ryan.roberts at arm.com  Fri Mar 14 02:18:43 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 09:18:43 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <86h63wok11.wl-maz@kernel.org>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <86ikocomvd.wl-maz@kernel.org> <f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
 <86h63wok11.wl-maz@kernel.org>
Message-ID: <4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>

On 13/03/2025 18:36, Marc Zyngier wrote:
> On Thu, 13 Mar 2025 18:22:00 +0000,
> Ryan Roberts <ryan.roberts at arm.com> wrote:
>>
>> On 13/03/2025 17:34, Marc Zyngier wrote:
>>> On Thu, 13 Mar 2025 10:41:10 +0000,
>>> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
>>>>
>>>> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
>>>> index c6b185b885f7..9728faa10390 100644
>>>> --- a/arch/arm64/kernel/pi/idreg-override.c
>>>> +++ b/arch/arm64/kernel/pi/idreg-override.c
>>>> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>>>>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>>>>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>>>>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
>>>> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>>>>  		{}
>>>>  	},
>>>>  };
>>>> @@ -246,6 +247,7 @@ static const struct {
>>>>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>>>>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>>>>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
>>>> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
>>>
>>> Why is that a SW feature? This looks very much like a HW feature to
>>> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
>>> with it. Something like:
>>
>> I think this implies that we would expect the BBM field to be advertising BBML2
>> support normally and we would check for that as part of the cpufeature
>> detection. That's how Miko was doing it in v2, but Yang pointed out that
>> AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
>> BBML2 in its MMFR2. So we don't want to check that field, and instead rely
>> solely on the MIDR allow-list + a command line override. It was me that
>> suggested putting that in the SW feature register, and I think that still sounds
>> like the right solution for this situation?
> 
> I think this is mixing two different things:
> 
> - preventing BBM-L2 from being visible to the kernel: this is what my
>   suggestion is doing by nuking an architectural feature in the
>   relevant register
> 
> - random HW not correctly advertising what they are doing: this is an
>   erratum workaround
> 
> I'd rather we don't conflate the two things, and make them very
> explicitly distinct.

It all sounds so obvious when you put it like that! :)

I'm guessing there is a layer where the workaround can be applied to the
sanitised feature registers on a per-cpu basis and that won't affect this global
override which will remain as an overlay on top? If so then that sounds perfect
(you can probably tell I find the whole feature management framework rather
inpeneterable). That workaround would be added as part of Yang's series anyway.

So sounds like we are back to testing MMFR2.BBM in the matches function, with
the addition of Maz's proposal above. Sorry for sending you round the houses, Miko.

Thanks,
Ryan

> 
> Thanks,
> 
> 	M.
> 



From Lu.Tang at mediatek.com  Fri Mar 14 02:21:30 2025
From: Lu.Tang at mediatek.com (=?utf-8?B?THUgVGFuZyAo5rGk55KQKQ==?=)
Date: Fri, 14 Mar 2025 09:21:30 +0000
Subject: =?utf-8?B?5Zue5aSNOiBbUEFUQ0ggMS81XSBwbWljOiBtZWRpYXRlazogQWRkIHBtaWMg?=
 =?utf-8?Q?auxadc_driver?=
In-Reply-To: <90d1c0f2-b037-482e-a569-f75b713e3a71@collabora.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-2-Lu.Tang@mediatek.com>
 <90d1c0f2-b037-482e-a569-f75b713e3a71@collabora.com>
Message-ID: <SEZPR03MB68910F9B60DAF0060440503980D22@SEZPR03MB6891.apcprd03.prod.outlook.com>

Update email

-----????-----
???: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> 
????: 2025?3?14? 16:53
???: Lu Tang (??) <Lu.Tang at mediatek.com>; Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>
??: Re: [PATCH 1/5] pmic: mediatek: Add pmic auxadc driver


External email : Please do not click links or open attachments until you have verified the sender or the content.


Il 14/03/25 08:32, Lu.Tang ha scritto:
> From: "Lu.Tang" <lu.tang at mediatek.com>
>
> Add pmic mt6363 and mt6373 auxadc driver
>

Can't you just add MT6363 and MT6373 support to the already present mt6359-auxadc driver?!

Regards,
Angelo



From ryan.roberts at arm.com  Fri Mar 14 02:26:56 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 09:26:56 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250313180833.GA40525@mazurka.cambridge.arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <ea10caee-59ef-4a00-9b61-37cb0a379411@arm.com>
 <20250313180833.GA40525@mazurka.cambridge.arm.com>
Message-ID: <d3a15aaf-16a6-4a88-a6c5-9b9afaa5f370@arm.com>

On 13/03/2025 18:08, Miko?aj Lenczewski wrote:
> On Thu, Mar 13, 2025 at 04:13:22PM +0000, Ryan Roberts wrote:
>> On 13/03/2025 10:41, Miko?aj Lenczewski wrote: 
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index d561cf3b8ac7..b936e0805161 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -2176,6 +2176,76 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>>>  	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>>>  }
>>>  
>>> +static inline bool bbml2_possible(void)
>>> +{
>>> +	return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
>>
>> If you're going to keep this helper, I think it really needs to be:
>>
>> return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) &&
>>        !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2);
>>
>> Then you would simplify the caller to remove it's own
>> IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) check.
>>
>> But personally I would remove the helper and just fold the test into
>> has_bbml2_noabort().
>>
>> Thanks,
>> Ryan
> 
> I was debating folding it into has_bbml2_noabort(), but went ahead and
> implemented it separately to match hvhe_possible(), which was another sw
> feature helper.

hvhe_possible() is a .matches function, so there is nothing to fold it into.

> 
> But I agree, folding it will be simpler and read just as easily (if not
> easier). Will do so.
> 
>>> +}
>>> +
>>> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>>> +{
>>> +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
>>> +	 * as possible. This list is therefore an allow-list of known-good
>>> +	 * implementations that both support bbml2 and additionally, fulfill the
>>> +	 * extra constraint of never generating TLB conflict aborts when using
>>> +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
>>> +	 * kernel contexts difficult to prove safe against recursive aborts).
>>> +	 *
>>> +	 * Note that implementations can only be considered "known-good" if their
>>> +	 * implementors attest to the fact that the implementation never raises
>>> +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
>>> +	 */
>>> +	static const struct midr_range supports_bbml2_noabort_list[] = {
>>> +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
>>> +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
>>> +		{}
>>> +	};
>>> +
>>> +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
>>> +}
>>> +
>>> +static inline unsigned int __cpu_read_midr(int cpu)
>>
>> nit: why the double underscrore prefix?
> 
> Again copying other helpers I saw that seemed to do similar things.
> Didn't know if this was the expected style, so did as other helpers did.
> Will remove.

Often those double underscores are used when you have a public function wrapping
into a private function, like this:

static void __do_a_thing(bool modify_behaviour_in_some_way);

void do_a_thing(void)
{
	__do_a_thing(false);
}

I'm sure the coding style offers a better explanation.

Thanks,
Ryan

> 
> Thank you for the review.
> 



From yangyicong at huawei.com  Fri Mar 14 02:33:54 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 14 Mar 2025 17:33:54 +0800
Subject: [PATCH 2/2] arm64/watchdog_hld: Add a cpufreq notifier for update
 watchdog thresh
In-Reply-To: <CAD=FV=XhMnGWAQ19n6_O2QTkXNu_+NkA+R=4X_w+-Vewpd55ng@mail.gmail.com>
References: <20250307021811.46981-1-yangyicong@huawei.com>
 <20250307021811.46981-3-yangyicong@huawei.com>
 <CAD=FV=XLn9Dz8rhRnjTKdbbeS3YP+XZFzpSV0C6+DakWOUmMpA@mail.gmail.com>
 <99a3afd4-6e16-0f39-9d2a-f629457dd756@huawei.com>
 <CAD=FV=Wy9-nDW-F+R1Aob6GOfP1Cnmr1gKkCO+WebA8ES7uu8A@mail.gmail.com>
 <260393cc-614a-b5c1-0e04-8443e00a7991@huawei.com>
 <CAD=FV=XhMnGWAQ19n6_O2QTkXNu_+NkA+R=4X_w+-Vewpd55ng@mail.gmail.com>
Message-ID: <1ec5d92d-a9d9-82a4-7630-1fc0b2311ed3@huawei.com>

On 2025/3/14 10:03, Doug Anderson wrote:
> Hi,
> 
> On Wed, Mar 12, 2025 at 12:48?AM Yicong Yang <yangyicong at huawei.com> wrote:
>>
>>>>>> +static int __init init_watchdog_freq_notifier(void)
>>>>>> +{
>>>>>> +       return cpufreq_register_notifier(&watchdog_freq_notifier,
>>>>>> +                                        CPUFREQ_POLICY_NOTIFIER);
>>>>>> +}
>>>>>> +core_initcall(init_watchdog_freq_notifier);
>>>>>
>>>>> I haven't dug into everything, but don't you have a potential blind
>>>>> spot, though? What if the order is this:
>>>>>
>>>>> 1. hw_nmi_get_sample_period() is called
>>>>> 2. cpufreq driver probes
>>>>> 3. init_watchdog_freq_notifier() initcall runs
>>>>>
>>>>> Since the cpufreq driver proved before you registered for the
>>>>> notifier, won't you miss the creation of the policy? Maybe instead of
>>>>> registering for an initcall you should somehow trigger off the first
>>>>> call to hw_nmi_get_sample_period() and register at that point in time?
>>>>>
>>>>
>>>> for arm64 the watchdog_perf is registered after armv8 PMU driver's init,
>>>> so the sequence is like:
>>>>
>>>> # core_initcall
>>>> init_watchdog_freq_notifier()
>>>> # device_initcall
>>>> armv8_pmu_driver_init()
>>>>   lockup_detector_retry_init()
>>>>     schedule_work(&detector_work);
>>>> # in detector work
>>>> hw_nmi_get_sample_period() // notifier's already been registered
>>>>
>>>> so we'll always get the correct frequency, either by the cpufreq
>>>> already registered or by the notifier which will update the
>>>> frequency. Please correct me if I missed anything :)
>>>
>>> Hmm, OK. So this relies on the fact that because the
>>> init_watchdog_freq_notifier() is at "core" level that it'll pretty
>>> much init before any of the other things. This type of thing is always
>>> a little fragile but I guess it's OK.
>>>
>>> What about if the order is different though? Again, I haven't traced
>>> through it all, but I'm thinking:
>>>
>>> # core_initcall
>>> init_watchdog_freq_notifier()
>>> # device_initcall
>>> <cpufreq driver policy is created>
>>>
>>> Now hardlockup_detector_perf_adjust_period() will be called before
>>> armv8_pmu_driver_init(). Is that a problem?
>>
>> it doesn't matter, since in this situation:
>>
>> # device_initcall
>> <cpufreq driver policy is created>
>>   hardlockup_detector_perf_adjust_period()
>>     if (!event) // armv8_pmu_driver_init() not called, not event created
>>       return;
>> # later after armv8_pmu_driver_init()
>> hw_nmi_get_sample_period() // since cpufreq already been registered, we can
>>                            // get the accurate cpufreq
> 
> Got it. Sorry for asking the dumb questions--I didn't have time to dig
> through the code earlier this week. Yeah, looks like it should be OK.
> 
> 
>>> I guess even worse would be if async probe was on and the cpufreq
>>> driver and PMU driver were running at the same time?
>>>
>>
>> I think there're 2 cases here:
>> 1) cpufreq initialized before hw_nmi_get_sample_period() called, in which
>>    case the cpufreq is accurate when create the event
>> 2) hw_nmi_get_sample_period() called before cpufreq driver's initialized,
>>    in which case we rely on the notifier call to adjust the event's period
>>
>> May need further check to see if there's any race window here, but the worst
>> case will be using the inaccurate cpufreq (5GHz) for calculating the period.
> 
> OK, sure. _Maybe_ there could be some small race if these two things
> are happening at exactly the same time on two different cores:
> 
> core 1:
> * lockup_detector_delay_init()
> * watchdog_hardlockup_probe()
> * hardlockup_detector_event_create()
> * hw_nmi_get_sample_period()
> * No cpufreq driver, so returns SAFE_MAX_CPU_FREQ
> 
> core 2:
> * cpufreq driver probes + policy is created
> * "event" hasn't been created yet, so your new code is a no-op
> 
> core 1:
> * event gets created based on SAFE_MAX_CPU_FREQ.
> 
> Did I get that right?
> 

I think yes, should exist theoretically.

> That doesn't feel _completely_ impossible especially since
> lockup_detector_delay_init() is already running on a separate
> workqueue. As you said, though, the worst case is it looks like we'll
> just end up with how things were before your patch series.
> 
> In any case, I guess it's pretty unlikely, but maybe it wouldn't be
> very hard to add a mutex in there? It doesn't feel like that would add
> much overhead...
> 

I'll see how to do the synchronization here. I need to look a bit deeper into
the cpufreq core. Will update in the next version.

Thanks.




From robin.murphy at arm.com  Fri Mar 14 02:36:03 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 14 Mar 2025 09:36:03 +0000
Subject: Regression on linux-next (next-20250312)
In-Reply-To: <SJ1PR11MB61295DE21A1184AEE0786E25B9D22@SJ1PR11MB6129.namprd11.prod.outlook.com>
References: <SJ1PR11MB61295DE21A1184AEE0786E25B9D22@SJ1PR11MB6129.namprd11.prod.outlook.com>
Message-ID: <f2e3c123-6d58-4560-be4f-b9171c0d9c73@arm.com>

On 2025-03-14 9:17 am, Borah, Chaitanya Kumar wrote:
> Hello Robin,
> 
> Hope you are doing well. I am Chaitanya from the linux graphics team in Intel.
> 
> This mail is regarding a regression we are seeing in our CI runs[1] on linux-next repository.
> 
> Since the version next-20250312 [2], we are seeing the following regression
> 
> `````````````````````````````````````````````````````````````````````````````````
> <4>[    6.246790] reg-dummy reg-dummy: late IOMMU probe at driver bind, something fishy here!
> <4>[    6.246812] WARNING: CPU: 0 PID: 1 at drivers/iommu/iommu.c:449 __iommu_probe_device+0x140/0x570
> <4>[    6.246822] Modules linked in:
> <4>[    6.246830] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc6-next-20250312-next-20250312-g9fbcd7b32bf7+ #1
> <4>[    6.246838] Hardware name: Intel Corporation Arrow Lake Client Platform/MTL-S UDIMM 2DPC EVCRB, BIOS MTLSFWI1.R00.4400.D85.2410100007 10/10/2024
> <4>[    6.246847] RIP: 0010:__iommu_probe_device+0x140/0x570
> `````````````````````````````````````````````````````````````````````````````````
> Details log can be found in [3].
> 
> After bisecting the tree, the following patch [4] seems to be the first "bad" commit
> 
> `````````````````````````````````````````````````````````````````````````````````````````````````````````
> commit bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c
> Author: Robin Murphy mailto:robin.murphy at arm.com
> Date:   Fri Feb 28 15:46:33 2025 +0000
> 
>      iommu: Get DT/ACPI parsing into the proper probe path
> 
> `````````````````````````````````````````````````````````````````````````````````````````````````````````
> 
> We also verified that if we revert the patch the issue is not seen.
> 
> Could you please check why the patch causes this regression and provide a fix if necessary?

Yes, the warnings are false positives, and the fix is already in today's 
-next, see 73d2f10957f5 ("iommu: Don't warn prematurely about dodgy 
probes"). Sorry for the disruption.

Thanks,
Robin.

> 
> Thank you.
> 
> Regards
> 
> Chaitanya
> 
> [1] https://intel-gfx-ci.01.org/tree/linux-next/combined-alt.html?
> [2] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312
> [3] https://intel-gfx-ci.01.org/tree/linux-next/next-20250312/bat-arls-6/boot0.txt
> [4] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312&id=bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c
> 



From lee at kernel.org  Fri Mar 14 02:47:31 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 14 Mar 2025 09:47:31 +0000
Subject: =?utf-8?B?5Zue5aSN?= =?utf-8?Q?=3A?= [PATCH 3/5] pmic: mediatek:
 Add spmi pmic mfd driver
In-Reply-To: <SEZPR03MB6891D404A7AA2BC5244A992A80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-4-Lu.Tang@mediatek.com>
 <SEZPR03MB6891D404A7AA2BC5244A992A80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
Message-ID: <20250314094731.GA3890718@google.com>

On Fri, 14 Mar 2025, Lu Tang (??) wrote:

> Update email address

What is this?

Please refrain from top-posting.

> -----????-----
> ???: Lu.Tang <Lu.Tang at mediatek.com> 
> ????: 2025?3?14? 15:32
> ???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
> ??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
> ??: [PATCH 3/5] pmic: mediatek: Add spmi pmic mfd driver

Fix your mailer.  Headers have no place in the body of an email.

> From: "Lu.Tang" <lu.tang at mediatek.com>
> 
> Add spmi pmic mfd driver for mt8196

7 words for a 900 line change is not going to fly.

What is this device?  What does it provide?  What are its dependencies?

Etc.

> Signed-off-by: Lu Tang <lu.tang at mediatek.com>
> ---
>  drivers/mfd/Kconfig                  |  26 ++
>  drivers/mfd/Makefile                 |   2 +
>  drivers/mfd/mt6685-core.c            |  83 +++++
>  drivers/mfd/mtk-spmi-pmic.c          | 518 +++++++++++++++++++++++++++
>  include/linux/mfd/mt6363/core.h      | 134 +++++++
>  include/linux/mfd/mt6363/registers.h | 168 +++++++++
>  include/linux/mfd/mt6373/core.h      |  94 +++++
>  include/linux/mfd/mt6373/registers.h |  53 +++
>  8 files changed, 1078 insertions(+)
>  create mode 100644 drivers/mfd/mt6685-core.c  create mode 100644 drivers/mfd/mtk-spmi-pmic.c  create mode 100644 include/linux/mfd/mt6363/core.h  create mode 100644 include/linux/mfd/mt6363/registers.h
>  create mode 100644 include/linux/mfd/mt6373/core.h  create mode 100644 include/linux/mfd/mt6373/registers.h

Please try again.

-- 
Lee Jones [???]


From zhangfei.gao at linaro.org  Fri Mar 14 02:48:09 2025
From: zhangfei.gao at linaro.org (Zhangfei Gao)
Date: Fri, 14 Mar 2025 17:48:09 +0800
Subject: Regression on linux-next (next-20250312)
In-Reply-To: <SJ1PR11MB61295DE21A1184AEE0786E25B9D22@SJ1PR11MB6129.namprd11.prod.outlook.com>
References: <SJ1PR11MB61295DE21A1184AEE0786E25B9D22@SJ1PR11MB6129.namprd11.prod.outlook.com>
Message-ID: <CABQgh9HBqbJYnUqJzG+nOY=B8nQ-8Scy8i0ctszBm8rzpocNFw@mail.gmail.com>

Hi, Borah

On Fri, 14 Mar 2025 at 17:18, Borah, Chaitanya Kumar
<chaitanya.kumar.borah at intel.com> wrote:
>
> Hello Robin,
>
> Hope you are doing well. I am Chaitanya from the linux graphics team in Intel.
>
> This mail is regarding a regression we are seeing in our CI runs[1] on linux-next repository.
>
> Since the version next-20250312 [2], we are seeing the following regression
>
> `````````````````````````````````````````````````````````````````````````````````
> <4>[    6.246790] reg-dummy reg-dummy: late IOMMU probe at driver bind, something fishy here!
> <4>[    6.246812] WARNING: CPU: 0 PID: 1 at drivers/iommu/iommu.c:449 __iommu_probe_device+0x140/0x570
> <4>[    6.246822] Modules linked in:
> <4>[    6.246830] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc6-next-20250312-next-20250312-g9fbcd7b32bf7+ #1
> <4>[    6.246838] Hardware name: Intel Corporation Arrow Lake Client Platform/MTL-S UDIMM 2DPC EVCRB, BIOS MTLSFWI1.R00.4400.D85.2410100007 10/10/2024
> <4>[    6.246847] RIP: 0010:__iommu_probe_device+0x140/0x570
> `````````````````````````````````````````````````````````````````````````````````
> Details log can be found in [3].
>
> After bisecting the tree, the following patch [4] seems to be the first "bad" commit
>
> `````````````````````````````````````````````````````````````````````````````````````````````````````````
> commit bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c
> Author: Robin Murphy mailto:robin.murphy at arm.com
> Date:   Fri Feb 28 15:46:33 2025 +0000
>
>     iommu: Get DT/ACPI parsing into the proper probe path
>
> `````````````````````````````````````````````````````````````````````````````````````````````````````````
>
> We also verified that if we revert the patch the issue is not seen.
>
> Could you please check why the patch causes this regression and provide a fix if necessary?

I just send one fix caused by this patch
Just FYI

[PATCH] PCI: declare quirk_huawei_pcie_sva as FIXUP_HEADER

"bcb81ac6ae3c iommu: Get DT/ACPI parsing into the proper probe path"
changes arm_smmu_probe_device sequence.

From
pci_bus_add_device(virtfn)
-> pci_fixup_device(pci_fixup_final, dev)
-> arm_smmu_probe_device

To
pci_device_add(virtfn, virtfn->bus)
-> pci_fixup_device(pci_fixup_header, dev)
-> arm_smmu_probe_device

So declare the fixup as pci_fixup_header to take effect
before arm_smmu_probe_device.

If your system has fixup, it may need a change '
from
DECLARE_PCI_FIXUP_FINAL
to
DECLARE_PCI_FIXUP_HEADER

Thanks


>
> Thank you.
>
> Regards
>
> Chaitanya
>
> [1] https://intel-gfx-ci.01.org/tree/linux-next/combined-alt.html?
> [2] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312
> [3] https://intel-gfx-ci.01.org/tree/linux-next/next-20250312/bat-arls-6/boot0.txt
> [4] https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20250312&id=bcb81ac6ae3c2ef95b44e7b54c3c9522364a245c
>
>


From leo.yan at arm.com  Fri Mar 14 02:50:25 2025
From: leo.yan at arm.com (Leo Yan)
Date: Fri, 14 Mar 2025 09:50:25 +0000
Subject: [PATCH 6/7] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250211103945.967495-7-james.clark@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-7-james.clark@linaro.org>
Message-ID: <20250314095025.GW9682@e132581.arm.com>

On Tue, Feb 11, 2025 at 10:39:42AM +0000, James Clark wrote:
> 
> These are all static and in one compilation unit so the inline has no
> effect on the binary.

I read the doc coding-style.rst, the section "15) The inline disease",
my understanding is though the inline is not encouraged, I prefer we can
follow up the rule:

  A reasonable rule of thumb is to not put inline at functions that have more
  than 3 lines of code in them. An exception to this rule are the cases where
  a parameter is known to be a compile time constant, and as a result of this
  constantness you *know* the compiler will be able to optimize most of your
  function away at compile time. For a good example of this later case, see
  the kmalloc() inline function.

> Except if FTRACE is enabled, then some functions
> which were already not inlined now get the nops added which allows them
> to be traced.

I understand it is a side effect that we cannot use function tracer for
inline functions.  This is not a big issue for me, as we still can use
"perf probe" and trace_printk() for debugging.

Thanks,
Leo

> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-catu.c  | 11 ++++----
>  drivers/hwtracing/coresight/coresight-core.c  | 16 ++++++------
>  drivers/hwtracing/coresight/coresight-etb10.c |  2 +-
>  .../coresight/coresight-etm4x-core.c          |  8 +++---
>  .../coresight/coresight-etm4x-sysfs.c         |  4 +--
>  .../hwtracing/coresight/coresight-platform.c  | 26 +++++++++----------
>  .../coresight/coresight-replicator.c          |  2 +-
>  drivers/hwtracing/coresight/coresight-stm.c   |  6 ++---
>  .../coresight/coresight-syscfg-configfs.c     |  2 +-
>  .../hwtracing/coresight/coresight-tmc-core.c  |  8 +++---
>  .../hwtracing/coresight/coresight-tmc-etr.c   | 16 +++++-------
>  drivers/hwtracing/coresight/coresight-trbe.c  | 18 ++++++-------
>  12 files changed, 58 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index 575c2d247a90..ffa08ea3c296 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -113,9 +113,8 @@ typedef u64 cate_t;
>   * containing the data page pointer for @offset. If @daddrp is not NULL,
>   * @daddrp points the DMA address of the beginning of the table.
>   */
> -static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
> -                                    unsigned long offset,
> -                                    dma_addr_t *daddrp)
> +static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
> +                             dma_addr_t *daddrp)
>  {
>         unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
>         unsigned int table_nr, pg_idx, pg_offset;
> @@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
>  }
> 
>  #else
> -static inline void catu_dump_table(struct tmc_sg_table *catu_table)
> +static void catu_dump_table(struct tmc_sg_table *catu_table)
>  {
>  }
>  #endif
> 
> -static inline cate_t catu_make_entry(dma_addr_t addr)
> +static cate_t catu_make_entry(dma_addr_t addr)
>  {
>         return addr ? CATU_VALID_ENTRY(addr) : 0;
>  }
> @@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
>  };
> 
> 
> -static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
> +static int catu_wait_for_ready(struct catu_drvdata *drvdata)
>  {
>         struct csdev_access *csa = &drvdata->csdev->access;
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 97f33ffad05e..396218819f26 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -127,20 +127,20 @@ coresight_find_out_connection(struct coresight_device *csdev,
>         return ERR_PTR(-ENODEV);
>  }
> 
> -static inline u32 coresight_read_claim_tags(struct csdev_access *csa)
> +static u32 coresight_read_claim_tags(struct csdev_access *csa)
>  {
>         return FIELD_GET(CORESIGHT_CLAIM_MASK,
>                          csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMCLR));
>  }
> 
> -static inline void coresight_set_self_claim_tag(struct csdev_access *csa)
> +static void coresight_set_self_claim_tag(struct csdev_access *csa)
>  {
>         csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>                                      CORESIGHT_CLAIMSET);
>         isb();
>  }
> 
> -static inline void coresight_clear_self_claim_tag(struct csdev_access *csa)
> +static void coresight_clear_self_claim_tag(struct csdev_access *csa)
>  {
>         csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>                                      CORESIGHT_CLAIMCLR);
> @@ -610,7 +610,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
>   * Return true in successful case and power up the device.
>   * Return false when failed to get reference of module.
>   */
> -static inline bool coresight_get_ref(struct coresight_device *csdev)
> +static bool coresight_get_ref(struct coresight_device *csdev)
>  {
>         struct device *dev = csdev->dev.parent;
> 
> @@ -629,7 +629,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
>   *
>   * @csdev: The coresight device to decrement a reference from.
>   */
> -static inline void coresight_put_ref(struct coresight_device *csdev)
> +static void coresight_put_ref(struct coresight_device *csdev)
>  {
>         struct device *dev = csdev->dev.parent;
> 
> @@ -808,7 +808,7 @@ void coresight_release_path(struct list_head *path)
>  }
> 
>  /* return true if the device is a suitable type for a default sink */
> -static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
> +static bool coresight_is_def_sink_type(struct coresight_device *csdev)
>  {
>         /* sink & correct subtype */
>         if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
> @@ -1362,8 +1362,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
>   *
>   * Returns the index of the entry, when found. Otherwise, -ENOENT.
>   */
> -static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
> -                                             struct fwnode_handle *fwnode)
> +static int coresight_search_device_idx(struct coresight_dev_list *dict,
> +                                      struct fwnode_handle *fwnode)
>  {
>         int i;
> 
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index b598b2c0c9bb..de6d3a6fb828 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -95,7 +95,7 @@ struct etb_drvdata {
>  static int etb_set_buffer(struct coresight_device *csdev,
>                           struct perf_output_handle *handle);
> 
> -static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
> +static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
>  {
>         return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 3609bb74c4ec..9e7d423c1ae9 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
>   *             TRCIDR4.NUMPC > 0b0000 .
>   *             TRCSSCSR<n>.PC == 0b1
>   */
> -static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> +static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
>  {
>         return (n < drvdata->nr_ss_cmp) &&
>                drvdata->nr_pe &&
> @@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
>         isb();
>  }
> 
> -static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
> +static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
>                                       struct csdev_access *csa)
>  {
>         WARN_ON(drvdata->cpu != smp_processor_id());
> @@ -1035,7 +1035,7 @@ static const struct coresight_ops etm4_cs_ops = {
>         .source_ops     = &etm4_source_ops,
>  };
> 
> -static inline bool cpu_supports_sysreg_trace(void)
> +static bool cpu_supports_sysreg_trace(void)
>  {
>         u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
> 
> @@ -1343,7 +1343,7 @@ static void etm4_init_arch_data(void *info)
>         cpu_detect_trace_filtering(drvdata);
>  }
> 
> -static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
> +static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
>  {
>         return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index a9f19629f3f8..0465c32f7ed4 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
>         return reg.data;
>  }
> 
> -static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
> +static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
>  {
>         struct dev_ext_attribute *eattr;
> 
> @@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
>         return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
>  }
> 
> -static inline bool
> +static bool
>  etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
>  {
>         switch (offset) {
> diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> index 8192ba3279f0..0db64c5f4995 100644
> --- a/drivers/hwtracing/coresight/coresight-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-platform.c
> @@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
>  EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
> 
>  #ifdef CONFIG_OF
> -static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
> +static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
>  {
>         return of_property_read_bool(ep, "slave-mode");
>  }
> @@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
>         return parent;
>  }
> 
> -static inline struct device_node *
> +static struct device_node *
>  of_coresight_get_output_ports_node(const struct device_node *node)
>  {
>         return of_get_child_by_name(node, "out-ports");
> @@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
>         return 0;
>  }
>  #else
> -static inline int
> +static int
>  of_get_coresight_platform_data(struct device *dev,
>                                struct coresight_platform_data *pdata)
>  {
>         return -ENOENT;
>  }
> 
> -static inline int of_coresight_get_cpu(struct device *dev)
> +static int of_coresight_get_cpu(struct device *dev)
>  {
>         return -ENODEV;
>  }
> @@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
>  #define ACPI_CORESIGHT_LINK_SLAVE      0
>  #define ACPI_CORESIGHT_LINK_MASTER     1
> 
> -static inline bool is_acpi_guid(const union acpi_object *obj)
> +static bool is_acpi_guid(const union acpi_object *obj)
>  {
>         return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
>  }
> @@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
>   * acpi_guid_matches   - Checks if the given object is a GUID object and
>   * that it matches the supplied the GUID.
>   */
> -static inline bool acpi_guid_matches(const union acpi_object *obj,
> +static bool acpi_guid_matches(const union acpi_object *obj,
>                                    const guid_t *guid)
>  {
>         return is_acpi_guid(obj) &&
>                guid_equal((guid_t *)obj->buffer.pointer, guid);
>  }
> 
> -static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
> +static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
>  {
>         return acpi_guid_matches(obj, &acpi_graph_uuid);
>  }
> 
> -static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
> +static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
>  {
>         return acpi_guid_matches(obj, &coresight_graph_uuid);
>  }
> 
> -static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
> +static bool is_acpi_coresight_graph(const union acpi_object *obj)
>  {
>         const union acpi_object *graphid, *guid, *links;
> 
> @@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
>   *     }, // End of ACPI Graph Property
>   *  })
>   */
> -static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
> +static bool acpi_validate_dsd_graph(const union acpi_object *graph)
>  {
>         int i, n;
>         const union acpi_object *rev, *nr_graphs;
> @@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
>         return NULL;
>  }
> 
> -static inline bool
> +static bool
>  acpi_validate_coresight_graph(const union acpi_object *cs_graph)
>  {
>         int nlinks;
> @@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
> 
>  #else
> 
> -static inline int
> +static int
>  acpi_get_coresight_platform_data(struct device *dev,
>                                  struct coresight_platform_data *pdata)
>  {
>         return -ENOENT;
>  }
> 
> -static inline int acpi_coresight_get_cpu(struct device *dev)
> +static int acpi_coresight_get_cpu(struct device *dev)
>  {
>         return -ENODEV;
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
> index 679a36effbe8..9f27374f1310 100644
> --- a/drivers/hwtracing/coresight/coresight-replicator.c
> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
> @@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
>  /*
>   * replicator_reset : Reset the replicator configuration to sane values.
>   */
> -static inline void replicator_reset(struct replicator_drvdata *drvdata)
> +static void replicator_reset(struct replicator_drvdata *drvdata)
>  {
>         if (drvdata->base)
>                 dynamic_replicator_reset(drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> index b581a30a1cd9..5decc87d1fba 100644
> --- a/drivers/hwtracing/coresight/coresight-stm.c
> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> @@ -290,7 +290,7 @@ static const struct coresight_ops stm_cs_ops = {
>         .source_ops     = &stm_source_ops,
>  };
> 
> -static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
> +static bool stm_addr_unaligned(const void *addr, u8 write_bytes)
>  {
>         return ((unsigned long)addr & (write_bytes - 1));
>  }
> @@ -674,7 +674,7 @@ static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)
>         return of_address_to_resource(np, index, res);
>  }
>  #else
> -static inline int of_stm_get_stimulus_area(struct device *dev,
> +static int of_stm_get_stimulus_area(struct device *dev,
>                                            struct resource *res)
>  {
>         return -ENOENT;
> @@ -718,7 +718,7 @@ static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)
>         return rc;
>  }
>  #else
> -static inline int acpi_stm_get_stimulus_area(struct device *dev,
> +static int acpi_stm_get_stimulus_area(struct device *dev,
>                                              struct resource *res)
>  {
>         return -ENOENT;
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> index 213b4159b062..2b40e556be87 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> @@ -10,7 +10,7 @@
>  #include "coresight-syscfg-configfs.h"
> 
>  /* create a default ci_type. */
> -static inline struct config_item_type *cscfg_create_ci_type(void)
> +static struct config_item_type *cscfg_create_ci_type(void)
>  {
>         struct config_item_type *ci_type;
> 
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index 5ac4e3c706ac..2e3354b5c5c7 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -164,8 +164,8 @@ static int tmc_open(struct inode *inode, struct file *file)
>         return 0;
>  }
> 
> -static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
> -                                         loff_t pos, size_t len, char **bufpp)
> +static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len,
> +                                  char **bufpp)
>  {
>         switch (drvdata->config_type) {
>         case TMC_CONFIG_TYPE_ETB:
> @@ -359,7 +359,7 @@ static const struct attribute_group *coresight_etr_groups[] = {
>         NULL,
>  };
> 
> -static inline bool tmc_etr_can_use_sg(struct device *dev)
> +static bool tmc_etr_can_use_sg(struct device *dev)
>  {
>         int ret;
>         u8 val_u8;
> @@ -389,7 +389,7 @@ static inline bool tmc_etr_can_use_sg(struct device *dev)
>         return false;
>  }
> 
> -static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
> +static bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
>  {
>         u32 auth = readl_relaxed(drvdata->base + TMC_AUTHSTATUS);
> 
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 7ba4f79191de..0d4e3af0d4b5 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -124,7 +124,7 @@ struct etr_sg_table {
>   * If we spill over to a new page for mapping 1 entry, we could as
>   * well replace the link entry of the previous page with the last entry.
>   */
> -static inline unsigned long __attribute_const__
> +static unsigned long __attribute_const__
>  tmc_etr_sg_table_entries(int nr_pages)
>  {
>         unsigned long nr_sgpages = nr_pages * ETR_SG_PAGES_PER_SYSPAGE;
> @@ -238,13 +238,13 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
>         return -ENOMEM;
>  }
> 
> -static inline long
> +static long
>  tmc_sg_get_data_page_offset(struct tmc_sg_table *sg_table, dma_addr_t addr)
>  {
>         return tmc_pages_get_offset(&sg_table->data_pages, addr);
>  }
> 
> -static inline void tmc_free_table_pages(struct tmc_sg_table *sg_table)
> +static void tmc_free_table_pages(struct tmc_sg_table *sg_table)
>  {
>         if (sg_table->table_vaddr)
>                 vunmap(sg_table->table_vaddr);
> @@ -480,7 +480,7 @@ static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table)
>         dev_dbg(sg_table->dev, "******* End of Table *****\n");
>  }
>  #else
> -static inline void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
> +static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
>  #endif
> 
>  /*
> @@ -815,10 +815,8 @@ void tmc_etr_remove_catu_ops(void)
>  }
>  EXPORT_SYMBOL_GPL(tmc_etr_remove_catu_ops);
> 
> -static inline int tmc_etr_mode_alloc_buf(int mode,
> -                                        struct tmc_drvdata *drvdata,
> -                                        struct etr_buf *etr_buf, int node,
> -                                        void **pages)
> +static int tmc_etr_mode_alloc_buf(int mode, struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
> +                                 int node, void **pages)
>  {
>         int rc = -EINVAL;
> 
> @@ -936,7 +934,7 @@ static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>         return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
>  }
> 
> -static inline s64
> +static s64
>  tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
>  {
>         ssize_t len;
> diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
> index 919804b12a67..e9a19ef52359 100644
> --- a/drivers/hwtracing/coresight/coresight-trbe.c
> +++ b/drivers/hwtracing/coresight/coresight-trbe.c
> @@ -159,22 +159,22 @@ static void trbe_check_errata(struct trbe_cpudata *cpudata)
>         }
>  }
> 
> -static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
> +static bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
>  {
>         return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata);
>  }
> 
> -static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
> +static bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
>  {
>         return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE);
>  }
> 
> -static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
> +static bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
>  {
>         return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE);
>  }
> 
> -static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
> +static bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
>  {
>         /*
>          * Errata affected TRBE implementation will need TSB CSYNC and
> @@ -184,7 +184,7 @@ static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
>         return trbe_has_erratum(cpudata, TRBE_NEEDS_DRAIN_AFTER_DISABLE);
>  }
> 
> -static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
> +static bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
>  {
>         /*
>          * Errata affected TRBE implementation will need an additional
> @@ -195,7 +195,7 @@ static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudat
>         return trbe_has_erratum(cpudata, TRBE_NEEDS_CTXT_SYNC_AFTER_ENABLE);
>  }
> 
> -static inline bool trbe_is_broken(struct trbe_cpudata *cpudata)
> +static bool trbe_is_broken(struct trbe_cpudata *cpudata)
>  {
>         return trbe_has_erratum(cpudata, TRBE_IS_BROKEN);
>  }
> @@ -207,13 +207,13 @@ static int trbe_alloc_node(struct perf_event *event)
>         return cpu_to_node(event->cpu);
>  }
> 
> -static inline void trbe_drain_buffer(void)
> +static void trbe_drain_buffer(void)
>  {
>         tsb_csync();
>         dsb(nsh);
>  }
> 
> -static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
> +static void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
>  {
>         /*
>          * Enable the TRBE without clearing LIMITPTR which
> @@ -229,7 +229,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
>                 isb();
>  }
> 
> -static inline void set_trbe_disabled(struct trbe_cpudata *cpudata)
> +static void set_trbe_disabled(struct trbe_cpudata *cpudata)
>  {
>         u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
> 
> --
> 2.34.1
> 
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org


From maz at kernel.org  Fri Mar 14 03:11:08 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 14 Mar 2025 10:11:08 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
	<20250313104111.24196-3-miko.lenczewski@arm.com>
	<86ikocomvd.wl-maz@kernel.org>
	<f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
	<86h63wok11.wl-maz@kernel.org>
	<4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>
Message-ID: <86ecyzorb7.wl-maz@kernel.org>

On Fri, 14 Mar 2025 09:18:43 +0000,
Ryan Roberts <ryan.roberts at arm.com> wrote:
> 
> On 13/03/2025 18:36, Marc Zyngier wrote:
> > On Thu, 13 Mar 2025 18:22:00 +0000,
> > Ryan Roberts <ryan.roberts at arm.com> wrote:
> >>
> >> On 13/03/2025 17:34, Marc Zyngier wrote:
> >>> On Thu, 13 Mar 2025 10:41:10 +0000,
> >>> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
> >>>>
> >>>> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> >>>> index c6b185b885f7..9728faa10390 100644
> >>>> --- a/arch/arm64/kernel/pi/idreg-override.c
> >>>> +++ b/arch/arm64/kernel/pi/idreg-override.c
> >>>> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
> >>>>  		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
> >>>>  		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
> >>>>  		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
> >>>> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
> >>>>  		{}
> >>>>  	},
> >>>>  };
> >>>> @@ -246,6 +247,7 @@ static const struct {
> >>>>  	{ "rodata=off",			"arm64_sw.rodataoff=1" },
> >>>>  	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
> >>>>  	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> >>>> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
> >>>
> >>> Why is that a SW feature? This looks very much like a HW feature to
> >>> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
> >>> with it. Something like:
> >>
> >> I think this implies that we would expect the BBM field to be advertising BBML2
> >> support normally and we would check for that as part of the cpufeature
> >> detection. That's how Miko was doing it in v2, but Yang pointed out that
> >> AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
> >> BBML2 in its MMFR2. So we don't want to check that field, and instead rely
> >> solely on the MIDR allow-list + a command line override. It was me that
> >> suggested putting that in the SW feature register, and I think that still sounds
> >> like the right solution for this situation?
> > 
> > I think this is mixing two different things:
> > 
> > - preventing BBM-L2 from being visible to the kernel: this is what my
> >   suggestion is doing by nuking an architectural feature in the
> >   relevant register
> > 
> > - random HW not correctly advertising what they are doing: this is an
> >   erratum workaround
> > 
> > I'd rather we don't conflate the two things, and make them very
> > explicitly distinct.
> 
> It all sounds so obvious when you put it like that! :)
> 
> I'm guessing there is a layer where the workaround can be applied to the
> sanitised feature registers on a per-cpu basis and that won't affect this global
> override which will remain as an overlay on top? If so then that sounds perfect
> (you can probably tell I find the whole feature management framework rather
> inpeneterable).

You and I, brother... The only person who actually understands what's
in that file is Suzuki.

> That workaround would be added as part of Yang's series anyway.

Yup, that's what I'd expect. Ideally tied to an erratum number so that
we have an actual promise from the vendor that their implementation is
actually BBM-L2 compliant despite the idreg breakage.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From brgl at bgdev.pl  Fri Mar 14 02:58:29 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Fri, 14 Mar 2025 10:58:29 +0100
Subject: [PATCH] ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX
In-Reply-To: <4866908a-2e93-4d19-aef3-5203e002a8cf@baylibre.com>
References: <20240401-da850-fix-select-da8xx-v1-1-a348ab91448f@baylibre.com>
 <CAMRc=Mc7Xa58J55_kenkr2OA=ho6YH_gENOFEvAiA+q+p54dDQ@mail.gmail.com> <4866908a-2e93-4d19-aef3-5203e002a8cf@baylibre.com>
Message-ID: <CAMRc=Md=Qz1AEToj4ebg-0HTDgKm=pfDhvmJs7Hngt2x_CpWSA@mail.gmail.com>

On Thu, Mar 13, 2025 at 10:17?PM David Lechner <dlechner at baylibre.com> wrote:
>
> On 4/2/24 3:47 AM, Bartosz Golaszewski wrote:
> > On Mon, Apr 1, 2024 at 5:10?PM David Lechner <dlechner at baylibre.com> wrote:
> >>
> >> Chips in the DA850 family need to have ARCH_DAVINCI_DA8XX to be selected
> >> in order to enable some peripheral drivers.
> >>
> >> This was accidentally removed in a previous commit.
> >>
> >> Fixes: dec85a95167a ("ARM: davinci: clean up platform support")
> >> Signed-off-by: David Lechner <dlechner at baylibre.com>
> >> ---
> >>  arch/arm/mach-davinci/Kconfig | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
> >> index 2a8a9fe46586..3fa15f342240 100644
> >> --- a/arch/arm/mach-davinci/Kconfig
> >> +++ b/arch/arm/mach-davinci/Kconfig
> >> @@ -27,6 +27,7 @@ config ARCH_DAVINCI_DA830
> >>
> >>  config ARCH_DAVINCI_DA850
> >>         bool "DA850/OMAP-L138/AM18x based system"
> >> +       select ARCH_DAVINCI_DA8XX
> >>         select DAVINCI_CP_INTC
> >>
> >>  config ARCH_DAVINCI_DA8XX
> >>
> >> ---
> >> base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
> >> change-id: 20240401-da850-fix-select-da8xx-989725eec11f
> >
> > Acked-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
>
> Hi Bartosz, here's an old one that never got picked up and I never got around
> to resending. Can you pick it up along with the other davinci stuff you are
> doing this cycle?

I already sent out my PR for this cycle. Maybe Arnd can pick it up
directly? Otherwise, remind me after the merge window.

Bartosz


From linus.walleij at linaro.org  Fri Mar 14 02:58:29 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 10:58:29 +0100
Subject: [PATCH v4 0/3] Add EINT support for multiple addresses
In-Reply-To: <20250225140732.21557-1-ot_chhao.chang@mediatek.com>
References: <20250225140732.21557-1-ot_chhao.chang@mediatek.com>
Message-ID: <CACRpkdYSNMV2jymbHaxRp-PmzbbkEJ_eUcT20whYw3gdhEGOGg@mail.gmail.com>

Hi Hao,

thanks for your patches!

On Tue, Feb 25, 2025 at 3:07?PM Hao Chang <ot_chhao.chang at mediatek.com> wrote:

> This patch depends on
> [v3,2/2] pinctrl: mediatek: add mt8196 driver
> [v3,1/2] dt-bindings: pinctrl: mediatek: add support for mt8196
>
> Please also accept this patch together with [1]
> to avoid build and dt binding check error.
> [1]https://patchwork.kernel.org/project/linux-mediatek/list/?series=&submitter=215008&state=&q=v3&archive=&delegate=

Since the dependence series is not finished I can't apply these
patches either, do you want to send an independent version of these
patches so we merge them *first* since they seem finished?

Then the mt8196 series can rebase on your patches in v6.15-rc1
instead.

Just send a version based on v6.14-rc1 and I will apply it.

Yours,
Linus Walleij


From sudeep.holla at arm.com  Fri Mar 14 02:58:51 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 14 Mar 2025 09:58:51 +0000
Subject: [PATCH] pmdomain: arm: scmi_pm_domain: Remove redundant state verification
Message-ID: <20250314095851.443979-1-sudeep.holla@arm.com>

Currently, scmi_pd_power() explicitly verifies whether the requested
power state was applied by calling state_get(). While this check could
detect failures where the state was not properly updated, ensuring
correctness is the responsibility of the SCMI firmware.

Removing this redundant state_get() call eliminates an unnecessary
round-trip to the firmware, improving efficiency. Any mismatches
between the requested and actual states should be handled by the SCMI
firmware, which must return a failure if state_set() is unsuccessful.

Additionally, in some cases, checking the state after powering off a
domain may be unreliable or unsafe, depending on the firmware
implementation.

This patch removes the redundant verification, simplifying the function
without compromising correctness.

Cc: Peng Fan <peng.fan at nxp.com>
Cc: Ulf Hansson <ulf.hansson at linaro.org>
Cc: Cristian Marussi <cristian.marussi at arm.com>
Reported-and-tested-by: Ranjani Vaidyanathan <ranjani.vaidyanathan at nxp.com>
Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/pmdomain/arm/scmi_pm_domain.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
index 86b531e15b85..2a213c218126 100644
--- a/drivers/pmdomain/arm/scmi_pm_domain.c
+++ b/drivers/pmdomain/arm/scmi_pm_domain.c
@@ -24,8 +24,7 @@ struct scmi_pm_domain {
 
 static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
 {
-	int ret;
-	u32 state, ret_state;
+	u32 state;
 	struct scmi_pm_domain *pd = to_scmi_pd(domain);
 
 	if (power_on)
@@ -33,13 +32,7 @@ static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
 	else
 		state = SCMI_POWER_STATE_GENERIC_OFF;
 
-	ret = power_ops->state_set(pd->ph, pd->domain, state);
-	if (!ret)
-		ret = power_ops->state_get(pd->ph, pd->domain, &ret_state);
-	if (!ret && state != ret_state)
-		return -EIO;
-
-	return ret;
+	return power_ops->state_set(pd->ph, pd->domain, state);
 }
 
 static int scmi_pd_power_on(struct generic_pm_domain *domain)
-- 
2.34.1



From ulf.hansson at linaro.org  Fri Mar 14 03:00:54 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 14 Mar 2025 11:00:54 +0100
Subject: [PATCH 0/4] pmdomain/cpuidle-psci: Improve domain-idlestate statistics
Message-ID: <20250314100103.1294715-1-ulf.hansson@linaro.org>

This series improves and extends the support for domain-idlestates statistic
for genpd and the cpuidle-psci-domain. More information is available in each
commit message.

Please help to review and test!

Kind regards
Ulf Hansson

Ulf Hansson (4):
  pmdomain: core: Add genpd helper to correct the usage/rejected
    counters
  cpuidle: psci: Move the per CPU variable domain_state to a struct
  cpuidle: psci: Correct the domain-idlestate statistics in debugfs
  pmdomain: core: Add residency reflection for domain-idlestates to
    debugfs

 drivers/cpuidle/cpuidle-psci-domain.c |  2 +-
 drivers/cpuidle/cpuidle-psci.c        | 40 ++++++++++++-----
 drivers/cpuidle/cpuidle-psci.h        |  4 +-
 drivers/pmdomain/core.c               | 65 +++++++++++++++++++++++++--
 drivers/pmdomain/governor.c           |  2 +
 include/linux/pm_domain.h             | 10 +++++
 6 files changed, 106 insertions(+), 17 deletions(-)

-- 
2.43.0



From ulf.hansson at linaro.org  Fri Mar 14 03:00:55 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 14 Mar 2025 11:00:55 +0100
Subject: [PATCH 1/4] pmdomain: core: Add genpd helper to correct the usage/rejected counters
In-Reply-To: <20250314100103.1294715-1-ulf.hansson@linaro.org>
References: <20250314100103.1294715-1-ulf.hansson@linaro.org>
Message-ID: <20250314100103.1294715-2-ulf.hansson@linaro.org>

In the cpuidle-psci-domain case the ->power_off() callback is usually
returning zero to indicate success. This is because the actual call to the
PSCI FW to enter the selected domain-idlestate, needs to be done after the
->power_off() callback has returned.

When the call to the PSCI FW fails, this leads to receiving an incorrect
tracking of the usage/rejected counts for the selected domain-idlestate.
In other words, the presented debug-statistics for genpd may look better
than what the actually are.

To allow a better correctness of the data, let's add a new genpd helper
function, which enables the caller adjust the usage/rejected counters for a
domain-idlestate, in cases of errors during power-off.

Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
---
 drivers/pmdomain/core.c   | 25 +++++++++++++++++++++++++
 include/linux/pm_domain.h |  6 ++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index 9b2f28b34bb5..c79ef6e3ab85 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -728,6 +728,31 @@ int dev_pm_genpd_rpm_always_on(struct device *dev, bool on)
 }
 EXPORT_SYMBOL_GPL(dev_pm_genpd_rpm_always_on);
 
+/**
+ * pm_genpd_inc_rejected() - Adjust the rejected/usage counts for an idle-state.
+ *
+ * @genpd: The PM domain the idle-state belongs to.
+ * @state_idx: The index of the idle-state that failed.
+ *
+ * In some special cases the ->power_off() callback is asynchronously powering
+ * off the PM domain, leading to that it may return zero to indicate success,
+ * even though the actual power-off could fail. To account for this correctly in
+ * the rejected/usage counts for the idle-state statistics, users can call this
+ * function to adjust the values.
+ *
+ * It is assumed that the users guarantee that the genpd doesn't get removed
+ * while this routine is getting called.
+ */
+void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
+			   unsigned int state_idx)
+{
+	genpd_lock(genpd);
+	genpd->states[genpd->state_idx].rejected++;
+	genpd->states[genpd->state_idx].usage--;
+	genpd_unlock(genpd);
+}
+EXPORT_SYMBOL_GPL(pm_genpd_inc_rejected);
+
 static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
 {
 	unsigned int state_idx = genpd->state_idx;
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index d56a78af4af1..6e808aeecbcb 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -285,6 +285,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 int pm_genpd_init(struct generic_pm_domain *genpd,
 		  struct dev_power_governor *gov, bool is_off);
 int pm_genpd_remove(struct generic_pm_domain *genpd);
+void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
+			   unsigned int state_idx);
 struct device *dev_to_genpd_dev(struct device *dev);
 int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
 int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb);
@@ -336,6 +338,10 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
 	return -EOPNOTSUPP;
 }
 
+static inline void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
+					 unsigned int state_idx)
+{ }
+
 static inline struct device *dev_to_genpd_dev(struct device *dev)
 {
 	return ERR_PTR(-EOPNOTSUPP);
-- 
2.43.0



From ulf.hansson at linaro.org  Fri Mar 14 03:00:56 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 14 Mar 2025 11:00:56 +0100
Subject: [PATCH 2/4] cpuidle: psci: Move the per CPU variable domain_state to a struct
In-Reply-To: <20250314100103.1294715-1-ulf.hansson@linaro.org>
References: <20250314100103.1294715-1-ulf.hansson@linaro.org>
Message-ID: <20250314100103.1294715-3-ulf.hansson@linaro.org>

To prepare to extend the per CPU variable domain_state to include more
data, let's move it into a struct. A subsequent change will add the new
data. This change have no intended functional impact.

Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
---
 drivers/cpuidle/cpuidle-psci.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index dd8d776d6e39..1aff1ec555d5 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -36,19 +36,28 @@ struct psci_cpuidle_data {
 	struct device *dev;
 };
 
+struct psci_cpuidle_domain_state {
+	u32 state;
+};
+
 static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
-static DEFINE_PER_CPU(u32, domain_state);
+static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
 static bool psci_cpuidle_use_syscore;
 static bool psci_cpuidle_use_cpuhp;
 
 void psci_set_domain_state(u32 state)
 {
-	__this_cpu_write(domain_state, state);
+	__this_cpu_write(psci_domain_state.state, state);
 }
 
 static inline u32 psci_get_domain_state(void)
 {
-	return __this_cpu_read(domain_state);
+	return __this_cpu_read(psci_domain_state.state);
+}
+
+static inline void psci_clear_domain_state(void)
+{
+	__this_cpu_write(psci_domain_state.state, 0);
 }
 
 static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
@@ -87,7 +96,7 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
 	cpu_pm_exit();
 
 	/* Clear the domain state to start fresh when back from idle. */
-	psci_set_domain_state(0);
+	psci_clear_domain_state();
 	return ret;
 }
 
@@ -121,7 +130,7 @@ static int psci_idle_cpuhp_down(unsigned int cpu)
 	if (pd_dev) {
 		pm_runtime_put_sync(pd_dev);
 		/* Clear domain state to start fresh at next online. */
-		psci_set_domain_state(0);
+		psci_clear_domain_state();
 	}
 
 	return 0;
@@ -147,7 +156,7 @@ static void psci_idle_syscore_switch(bool suspend)
 
 			/* Clear domain state to re-start fresh. */
 			if (!cleared) {
-				psci_set_domain_state(0);
+				psci_clear_domain_state();
 				cleared = true;
 			}
 		}
-- 
2.43.0



From ulf.hansson at linaro.org  Fri Mar 14 03:00:57 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 14 Mar 2025 11:00:57 +0100
Subject: [PATCH 3/4] cpuidle: psci: Correct the domain-idlestate statistics in debugfs
In-Reply-To: <20250314100103.1294715-1-ulf.hansson@linaro.org>
References: <20250314100103.1294715-1-ulf.hansson@linaro.org>
Message-ID: <20250314100103.1294715-4-ulf.hansson@linaro.org>

When trying to enter a domain-idlestate, we may occasionally fail to enter
the state, which is informed to us by psci_cpu_suspend_enter() returning an
error-code. In these cases, our corresponding genpd->power_off() callback
has already returned zero to indicate success, leading to getting
in-correct domain-idlestate statistics in debugfs for the genpd in
question.

Let's fix this by making use of the new pm_genpd_inc_rejected() helper, as
it allows us to correct the domain-idlestate statistics for this type of
scenario.

Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
---
 drivers/cpuidle/cpuidle-psci-domain.c |  2 +-
 drivers/cpuidle/cpuidle-psci.c        | 27 +++++++++++++++++----------
 drivers/cpuidle/cpuidle-psci.h        |  4 +++-
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index 5fb5228f6bf1..2041f59116ce 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -43,7 +43,7 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
 
 	/* OSI mode is enabled, set the corresponding domain state. */
 	pd_state = state->data;
-	psci_set_domain_state(*pd_state);
+	psci_set_domain_state(pd, pd->state_idx, *pd_state);
 
 	return 0;
 }
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 1aff1ec555d5..26a0885444c4 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -37,6 +37,8 @@ struct psci_cpuidle_data {
 };
 
 struct psci_cpuidle_domain_state {
+	struct generic_pm_domain *pd;
+	unsigned int state_idx;
 	u32 state;
 };
 
@@ -45,14 +47,14 @@ static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
 static bool psci_cpuidle_use_syscore;
 static bool psci_cpuidle_use_cpuhp;
 
-void psci_set_domain_state(u32 state)
+void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
+			   u32 state)
 {
-	__this_cpu_write(psci_domain_state.state, state);
-}
+	struct psci_cpuidle_domain_state *ds = this_cpu_ptr(&psci_domain_state);
 
-static inline u32 psci_get_domain_state(void)
-{
-	return __this_cpu_read(psci_domain_state.state);
+	ds->pd = pd;
+	ds->state_idx = state_idx;
+	ds->state = state;
 }
 
 static inline void psci_clear_domain_state(void)
@@ -67,7 +69,8 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
 	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
 	u32 *states = data->psci_states;
 	struct device *pd_dev = data->dev;
-	u32 state;
+	struct psci_cpuidle_domain_state *ds;
+	u32 state = states[idx];
 	int ret;
 
 	ret = cpu_pm_enter();
@@ -80,9 +83,9 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
 	else
 		pm_runtime_put_sync_suspend(pd_dev);
 
-	state = psci_get_domain_state();
-	if (!state)
-		state = states[idx];
+	ds = this_cpu_ptr(&psci_domain_state);
+	if (ds->state)
+		state = ds->state;
 
 	trace_psci_domain_idle_enter(dev->cpu, state, s2idle);
 	ret = psci_cpu_suspend_enter(state) ? -1 : idx;
@@ -95,6 +98,10 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
 
 	cpu_pm_exit();
 
+	/* Correct domain-idlestate statistics if we failed to enter. */
+	if (ret == -1 && ds->state)
+		pm_genpd_inc_rejected(ds->pd, ds->state_idx);
+
 	/* Clear the domain state to start fresh when back from idle. */
 	psci_clear_domain_state();
 	return ret;
diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
index ef004ec7a7c5..d29cbd796cd5 100644
--- a/drivers/cpuidle/cpuidle-psci.h
+++ b/drivers/cpuidle/cpuidle-psci.h
@@ -4,8 +4,10 @@
 #define __CPUIDLE_PSCI_H
 
 struct device_node;
+struct generic_pm_domain;
 
-void psci_set_domain_state(u32 state);
+void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
+			   u32 state);
 int psci_dt_parse_state_node(struct device_node *np, u32 *state);
 
 #endif /* __CPUIDLE_PSCI_H */
-- 
2.43.0



From ulf.hansson at linaro.org  Fri Mar 14 03:00:58 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 14 Mar 2025 11:00:58 +0100
Subject: [PATCH 4/4] pmdomain: core: Add residency reflection for domain-idlestates to debugfs
In-Reply-To: <20250314100103.1294715-1-ulf.hansson@linaro.org>
References: <20250314100103.1294715-1-ulf.hansson@linaro.org>
Message-ID: <20250314100103.1294715-5-ulf.hansson@linaro.org>

For regular cpuidle states we are reflecting over the selected/entered
state to see if the sleep-duration meets the residency for the state. The
output from the reflection is an "above" value to indicate the number of
times the state was too deep and a "below" value for the number of times it
was too shallow.

Let's implement the similar thing for genpd's domain-idlestates along with
genpd's governor and put the information in the genpd's debugfs.

Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
---
 drivers/pmdomain/core.c     | 40 ++++++++++++++++++++++++++++++++++---
 drivers/pmdomain/governor.c |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index c79ef6e3ab85..3327de2f9ed2 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -304,10 +304,40 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd)
 
 	genpd->accounting_time = now;
 }
+
+static void genpd_reflect_residency(struct generic_pm_domain *genpd)
+{
+	struct genpd_governor_data *gd = genpd->gd;
+	struct genpd_power_state *state, *next_state;
+	unsigned int state_idx;
+	s64 sleep_ns, target_ns;
+
+	if (!gd || !gd->reflect_residency)
+		return;
+
+	sleep_ns = ktime_to_ns(ktime_sub(ktime_get(), gd->last_enter));
+	state_idx = genpd->state_idx;
+	state = &genpd->states[state_idx];
+	target_ns = state->power_off_latency_ns + state->residency_ns;
+
+	if (sleep_ns < target_ns) {
+		state->above++;
+	} else if (state_idx < (genpd->state_count -1)) {
+		next_state = &genpd->states[state_idx + 1];
+		target_ns = next_state->power_off_latency_ns +
+			next_state->residency_ns;
+
+		if (sleep_ns >= target_ns)
+			state->below++;
+	}
+
+	gd->reflect_residency = false;
+}
 #else
 static inline void genpd_debug_add(struct generic_pm_domain *genpd) {}
 static inline void genpd_debug_remove(struct generic_pm_domain *genpd) {}
 static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {}
+static inline void genpd_reflect_residency(struct generic_pm_domain *genpd) {}
 #endif
 
 static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd,
@@ -982,6 +1012,9 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
 	if (genpd_status_on(genpd))
 		return 0;
 
+	/* Reflect over the entered idle-states residency for debugfs. */
+	genpd_reflect_residency(genpd);
+
 	/*
 	 * The list is guaranteed not to change while the loop below is being
 	 * executed, unless one of the parents' .power_on() callbacks fiddles
@@ -3517,7 +3550,7 @@ static int idle_states_show(struct seq_file *s, void *data)
 	if (ret)
 		return -ERESTARTSYS;
 
-	seq_puts(s, "State          Time Spent(ms) Usage          Rejected\n");
+	seq_puts(s, "State          Time Spent(ms) Usage      Rejected   Above      Below\n");
 
 	for (i = 0; i < genpd->state_count; i++) {
 		struct genpd_power_state *state = &genpd->states[i];
@@ -3537,9 +3570,10 @@ static int idle_states_show(struct seq_file *s, void *data)
 			snprintf(state_name, ARRAY_SIZE(state_name), "S%-13d", i);
 
 		do_div(idle_time, NSEC_PER_MSEC);
-		seq_printf(s, "%-14s %-14llu %-14llu %llu\n",
+		seq_printf(s, "%-14s %-14llu %-10llu %-10llu %-10llu %llu\n",
 			   state->name ?: state_name, idle_time,
-			   state->usage, state->rejected);
+			   state->usage, state->rejected, state->above,
+			   state->below);
 	}
 
 	genpd_unlock(genpd);
diff --git a/drivers/pmdomain/governor.c b/drivers/pmdomain/governor.c
index d1a10eeebd16..c1e148657c87 100644
--- a/drivers/pmdomain/governor.c
+++ b/drivers/pmdomain/governor.c
@@ -392,6 +392,8 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
 		if (idle_duration_ns >= (genpd->states[i].residency_ns +
 		    genpd->states[i].power_off_latency_ns)) {
 			genpd->state_idx = i;
+			genpd->gd->last_enter = now;
+			genpd->gd->reflect_residency = true;
 			return true;
 		}
 	} while (--i >= 0);
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 6e808aeecbcb..0b18160901a2 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -142,6 +142,8 @@ struct genpd_governor_data {
 	bool max_off_time_changed;
 	ktime_t next_wakeup;
 	ktime_t next_hrtimer;
+	ktime_t last_enter;
+	bool reflect_residency;
 	bool cached_power_down_ok;
 	bool cached_power_down_state_idx;
 };
@@ -153,6 +155,8 @@ struct genpd_power_state {
 	s64 residency_ns;
 	u64 usage;
 	u64 rejected;
+	u64 above;
+	u64 below;
 	struct fwnode_handle *fwnode;
 	u64 idle_time;
 	void *data;
-- 
2.43.0



From Jonathan.Cameron at huawei.com  Fri Mar 14 03:01:36 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Fri, 14 Mar 2025 10:01:36 +0000
Subject: [PATCH] soc: hisilicon: kunpeng_hccs: Fix incorrect string
 assembly
In-Reply-To: <20250314082856.3257783-1-lihuisong@huawei.com>
References: <20250314082856.3257783-1-lihuisong@huawei.com>
Message-ID: <20250314100136.0000416f@huawei.com>

On Fri, 14 Mar 2025 16:28:56 +0800
Huisong Li <lihuisong at huawei.com> wrote:

> String assembly should use sysfs_emit_at() instead of sysfs_emit().
> 
> Signed-off-by: Huisong Li <lihuisong at huawei.com>
Fixes tag?

Otherwise looks good to me.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>

> ---
>  drivers/soc/hisilicon/kunpeng_hccs.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
> index 8aa8dec14911..444a8f59b7da 100644
> --- a/drivers/soc/hisilicon/kunpeng_hccs.c
> +++ b/drivers/soc/hisilicon/kunpeng_hccs.c
> @@ -1539,8 +1539,8 @@ static ssize_t used_types_show(struct kobject *kobj,
>  	u16 i;
>  
>  	for (i = 0; i < hdev->used_type_num - 1; i++)
> -		len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name);
> -	len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name);
> +		len += sysfs_emit_at(buf, len, "%s ", hdev->type_name_maps[i].name);
> +	len += sysfs_emit_at(buf, len, "%s\n", hdev->type_name_maps[i].name);
>  
>  	return len;
>  }



From lihuisong at huawei.com  Fri Mar 14 03:08:15 2025
From: lihuisong at huawei.com (lihuisong (C))
Date: Fri, 14 Mar 2025 18:08:15 +0800
Subject: [PATCH] soc: hisilicon: kunpeng_hccs: Fix incorrect string
 assembly
In-Reply-To: <20250314100136.0000416f@huawei.com>
References: <20250314082856.3257783-1-lihuisong@huawei.com>
 <20250314100136.0000416f@huawei.com>
Message-ID: <40b9c172-2bbb-a048-643b-1493aa874b65@huawei.com>


? 2025/3/14 18:01, Jonathan Cameron ??:
> On Fri, 14 Mar 2025 16:28:56 +0800
> Huisong Li <lihuisong at huawei.com> wrote:
>
>> String assembly should use sysfs_emit_at() instead of sysfs_emit().
>>
>> Signed-off-by: Huisong Li <lihuisong at huawei.com>
> Fixes tag?
ok, will add it.
>
> Otherwise looks good to me.
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
>
>> ---
>>   drivers/soc/hisilicon/kunpeng_hccs.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
>> index 8aa8dec14911..444a8f59b7da 100644
>> --- a/drivers/soc/hisilicon/kunpeng_hccs.c
>> +++ b/drivers/soc/hisilicon/kunpeng_hccs.c
>> @@ -1539,8 +1539,8 @@ static ssize_t used_types_show(struct kobject *kobj,
>>   	u16 i;
>>   
>>   	for (i = 0; i < hdev->used_type_num - 1; i++)
>> -		len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name);
>> -	len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name);
>> +		len += sysfs_emit_at(buf, len, "%s ", hdev->type_name_maps[i].name);
>> +	len += sysfs_emit_at(buf, len, "%s\n", hdev->type_name_maps[i].name);
>>   
>>   	return len;
>>   }
> .


From linus.walleij at linaro.org  Fri Mar 14 03:08:13 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 11:08:13 +0100
Subject: [RESEND PATCH v6 2/3] dt-bindings: pinctrl: at91-pio4: add microchip,sama7d65-pinctrl
In-Reply-To: <821255840c09d8d9cebbb1f2daaedd8a7c138875.1736522006.git.Ryan.Wanner@microchip.com>
References: <cover.1736522006.git.Ryan.Wanner@microchip.com> <821255840c09d8d9cebbb1f2daaedd8a7c138875.1736522006.git.Ryan.Wanner@microchip.com>
Message-ID: <CACRpkdYYeC+2G0u0LYSUjAX_ex7MjWLhEcu7QdNXudj8BEO4PQ@mail.gmail.com>

On Thu, Mar 6, 2025 at 5:03?PM <Ryan.Wanner at microchip.com> wrote:

> From: Dharma Balasubiramani <dharma.b at microchip.com>
>
> Add pinctrl bindings for microchip sama7d65 SoC.
>
> Signed-off-by: Dharma Balasubiramani <dharma.b at microchip.com>
> Signed-off-by: Ryan Wanner <Ryan.Wanner at microchip.com>
> Acked-by: Rob Herring (Arm) <robh at kernel.org>

This patch applied to the pinctrl tree.

Yours,
Linus Walleij


From lihuisong at huawei.com  Fri Mar 14 03:01:43 2025
From: lihuisong at huawei.com (Huisong Li)
Date: Fri, 14 Mar 2025 18:01:43 +0800
Subject: [PATCH v2] soc: hisilicon: kunpeng_hccs: Fix incorrect string assembly
Message-ID: <20250314100143.3377268-1-lihuisong@huawei.com>

String assembly should use sysfs_emit_at() instead of sysfs_emit().

Fixes: 23fe8112a231 ("soc: hisilicon: kunpeng_hccs: Add used HCCS types sysfs")
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Huisong Li <lihuisong at huawei.com>
---
 drivers/soc/hisilicon/kunpeng_hccs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 8aa8dec14911..444a8f59b7da 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1539,8 +1539,8 @@ static ssize_t used_types_show(struct kobject *kobj,
 	u16 i;
 
 	for (i = 0; i < hdev->used_type_num - 1; i++)
-		len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name);
-	len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name);
+		len += sysfs_emit_at(buf, len, "%s ", hdev->type_name_maps[i].name);
+	len += sysfs_emit_at(buf, len, "%s\n", hdev->type_name_maps[i].name);
 
 	return len;
 }
-- 
2.33.0



From liqiong at nfschina.com  Fri Mar 14 03:16:39 2025
From: liqiong at nfschina.com (Li Qiong)
Date: Fri, 14 Mar 2025 18:16:39 +0800
Subject: [PATCH v3 2/2] usb: gadget: udc-xilinx: Remove the invalid comment
In-Reply-To: <20250314101639.424013-1-liqiong@nfschina.com>
Message-ID: <20250314101639.424013-2-liqiong@nfschina.com>

The function don't return value, remove the invalid comment.

Signed-off-by: Li Qiong <liqiong at nfschina.com>
---
v2: Split the first patch to two patches.
v3: Add changes from the previous version.

 drivers/usb/gadget/udc/udc-xilinx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index ae2aeb271897..fa94cc065274 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -2178,8 +2178,6 @@ static int xudc_probe(struct platform_device *pdev)
 /**
  * xudc_remove - Releases the resources allocated during the initialization.
  * @pdev: pointer to the platform device structure.
- *
- * Return: 0 always
  */
 static void xudc_remove(struct platform_device *pdev)
 {
-- 
2.30.2



From linus.walleij at linaro.org  Fri Mar 14 03:21:44 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 11:21:44 +0100
Subject: [PATCH 06/14] ASoC: mediatek: mt8196: support audio GPIO control
In-Reply-To: <20250307124841.23777-7-darren.ye@mediatek.com>
References: <20250307124841.23777-1-darren.ye@mediatek.com> <20250307124841.23777-7-darren.ye@mediatek.com>
Message-ID: <CACRpkdZ=a0mbir=D3dCSPns1TC_OVWMMTXJKcTYOJeNy7aQ7NQ@mail.gmail.com>

Hi Darren,

thanks for your patch!

On Fri, Mar 7, 2025 at 1:49?PM Darren.Ye <darren.ye at mediatek.com> wrote:

> From: Darren Ye <darren.ye at mediatek.com>
>
> Implement mode switching for audio GPIO.
>
> Signed-off-by: Darren Ye <darren.ye at mediatek.com>

> +#include <linux/gpio.h>

Please don't include this legacy header. I don't think you even need it,
you are not using any gpio_ symbols at all.

> +#include <linux/pinctrl/consumer.h>

You don't seem to use anything from this include either.

Find more specific headers if you need the code to compile.

I think you should drop both, the name "GPIO" in this file is a bit confusing
because it's not very generic but dealing with audio IO routing. But I guess
it is what Mediatek calls it.

Yours,
Linus Walleij


From danishanwar at ti.com  Fri Mar 14 03:27:21 2025
From: danishanwar at ti.com (MD Danish Anwar)
Date: Fri, 14 Mar 2025 15:57:21 +0530
Subject: [PATCH net] net: ti: icssg-prueth: Add lock to stats
Message-ID: <20250314102721.1394366-1-danishanwar@ti.com>

Currently the API emac_update_hardware_stats() reads different ICSSG
stats without any lock protection.

This API gets called by .ndo_get_stats64() which is only under RCU
protection and nothing else. Add lock to this API so that the reading of
statistics happens during lock.

Fixes: c1e10d5dc7a1 ("net: ti: icssg-prueth: Add ICSSG Stats")
Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
---
NOTE: This was suggested by Jakub Kicinski <kuba at kernel.org> [1] to get
this as bug fix in net during upstreaming of FW Stats for ICSSG driver
This patch doesn't depend on [1] and can be applied cleanly on net/main

[1] https://lore.kernel.org/all/20250306165513.541ff46e at kernel.org/

 drivers/net/ethernet/ti/icssg/icssg_prueth.c | 1 +
 drivers/net/ethernet/ti/icssg/icssg_prueth.h | 2 ++
 drivers/net/ethernet/ti/icssg/icssg_stats.c  | 4 ++++
 3 files changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 00ed97860547..9a75733e3f8f 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -1679,6 +1679,7 @@ static int prueth_probe(struct platform_device *pdev)
 	}
 
 	spin_lock_init(&prueth->vtbl_lock);
+	spin_lock_init(&prueth->stats_lock);
 	/* setup netdev interfaces */
 	if (eth0_node) {
 		ret = prueth_netdev_init(prueth, eth0_node);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 329b46e9ee53..f41786b05741 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -305,6 +305,8 @@ struct prueth {
 	int default_vlan;
 	/** @vtbl_lock: Lock for vtbl in shared memory */
 	spinlock_t vtbl_lock;
+	/** @stats_lock: Lock for reading icssg stats */
+	spinlock_t stats_lock;
 };
 
 struct emac_tx_ts_response {
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c
index 8800bd3a8d07..6f0edae38ea2 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
@@ -26,6 +26,8 @@ void emac_update_hardware_stats(struct prueth_emac *emac)
 	u32 val, reg;
 	int i;
 
+	spin_lock(&prueth->stats_lock);
+
 	for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++) {
 		regmap_read(prueth->miig_rt,
 			    base + icssg_all_miig_stats[i].offset,
@@ -51,6 +53,8 @@ void emac_update_hardware_stats(struct prueth_emac *emac)
 			emac->pa_stats[i] += val;
 		}
 	}
+
+	spin_unlock(&prueth->stats_lock);
 }
 
 void icssg_stats_work_handler(struct work_struct *work)

base-commit: 4003c9e78778e93188a09d6043a74f7154449d43
-- 
2.34.1



From peng.fan at nxp.com  Fri Mar 14 03:29:00 2025
From: peng.fan at nxp.com (Peng Fan)
Date: Fri, 14 Mar 2025 10:29:00 +0000
Subject: [PATCH] pmdomain: arm: scmi_pm_domain: Remove redundant state
 verification
In-Reply-To: <20250314095851.443979-1-sudeep.holla@arm.com>
References: <20250314095851.443979-1-sudeep.holla@arm.com>
Message-ID: <PAXPR04MB8459F43DF554C008CD97FF3488D22@PAXPR04MB8459.eurprd04.prod.outlook.com>

> Subject: [PATCH] pmdomain: arm: scmi_pm_domain: Remove
> redundant state verification
> 
> Currently, scmi_pd_power() explicitly verifies whether the requested
> power state was applied by calling state_get(). While this check could
> detect failures where the state was not properly updated, ensuring
> correctness is the responsibility of the SCMI firmware.
> 
> Removing this redundant state_get() call eliminates an unnecessary
> round-trip to the firmware, improving efficiency. Any mismatches
> between the requested and actual states should be handled by the
> SCMI firmware, which must return a failure if state_set() is unsuccessful.
> 
> Additionally, in some cases, checking the state after powering off a
> domain may be unreliable or unsafe, depending on the firmware
> implementation.
> 
> This patch removes the redundant verification, simplifying the function
> without compromising correctness.
> 
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Ulf Hansson <ulf.hansson at linaro.org>
> Cc: Cristian Marussi <cristian.marussi at arm.com>
> Reported-and-tested-by: Ranjani Vaidyanathan
> <ranjani.vaidyanathan at nxp.com>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---

Reviewed-by: Peng Fan <peng.fan at nxp.com>


From linus.walleij at linaro.org  Fri Mar 14 03:38:47 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 11:38:47 +0100
Subject: [PATCH 1/2] dt-bindings: pinctrl: airoha: Add missing gpio-ranges property
In-Reply-To: <20250307-en7581-gpio-range-v1-1-de1262105428@kernel.org>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org> <20250307-en7581-gpio-range-v1-1-de1262105428@kernel.org>
Message-ID: <CACRpkdZpj9q+yH7VEQJ=tOjpR6S3GTeHbyYpqaTYxCOJgGd7+w@mail.gmail.com>

On Fri, Mar 7, 2025 at 6:08?PM Lorenzo Bianconi <lorenzo at kernel.org> wrote:

> Introduce leftover gpio-ranges property for Airoha EN7581 pinctrl binding
>
> Fixes: d0c15cb96b74 ("dt-bindings: pinctrl: airoha: Add EN7581 pinctrl")
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>

This patch 1/2 applied to the pinctrl tree.

Please funnel 2/2 through the SoC tree.

Yours,
Linus Walleij


From suzuki.poulose at arm.com  Fri Mar 14 03:38:59 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 14 Mar 2025 10:38:59 +0000
Subject: [PATCH] coresight: Fixes device's owner field for registered
 using coresight_init_driver()
In-Reply-To: <c3744062-f7c1-82df-2fa1-591da3b2dc5e@huawei.com>
References: <20240918035327.9710-1-hejunhao3@huawei.com>
 <e2194d2a-0f51-4e59-a1ca-b4563b3389ec@arm.com>
 <c3744062-f7c1-82df-2fa1-591da3b2dc5e@huawei.com>
Message-ID: <1a030491-5bc6-4122-baed-faf123f0f872@arm.com>

Hi

On 14/03/2025 07:44, hejunhao wrote:
> Hi Suzuki,
> 
> Could you confirm if this patch was queued in coresight/next or upstream 
> of the mainline?
> 
> I couldn't find it in: kernel/git/coresight/linux.git or Kernel v6.14.0- 
> rc4.
> 
> Maybe am I missing some information?

Apologies, I missed queueing this. That said, I have a minor comment on 
the patch below.

> 
> Best regards,
> Junhao.
> 
> 
> On 2024/9/18 16:29, Suzuki K Poulose wrote:
>> On 18/09/2024 04:53, Junhao He wrote:
>>> The coresight_init_driver() of the coresight-core module is called from
>>> the sub coresgiht device (such as tmc/stm/funnle/...) module. It calls
>>> amba_driver_register() and Platform_driver_register(), which are macro
>>> functions that use the coresight-core's module to initialize the 
>>> caller's
>>> owner field.? Therefore, when the sub coresight device calls
>>> coresight_init_driver(), an incorrect THIS_MODULE value is captured.
>>>
>>> The sub coesgiht modules can be removed while their callbacks are
>>> running, resulting in a general protection failure.
>>>
>>> Add module parameter to coresight_init_driver() so can be called
>>> with the module of the callback.
>>>
>>> Fixes: 075b7cd7ad7d ("coresight: Add helpers registering/removing 
>>> both AMBA and platform drivers")
>>> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
>>
>> Thanks for the fix, looks good to me. I will queue this for v6.13
>>
>> Suzuki
>>
>>> ---
>>> ? drivers/hwtracing/coresight/coresight-catu.c?????? | 2 +-
>>> ? drivers/hwtracing/coresight/coresight-core.c?????? | 6 +++---
>>> ? drivers/hwtracing/coresight/coresight-cpu-debug.c? | 3 ++-
>>> ? drivers/hwtracing/coresight/coresight-funnel.c???? | 3 ++-
>>> ? drivers/hwtracing/coresight/coresight-replicator.c | 3 ++-
>>> ? drivers/hwtracing/coresight/coresight-stm.c??????? | 2 +-
>>> ? drivers/hwtracing/coresight/coresight-tmc-core.c?? | 2 +-
>>> ? drivers/hwtracing/coresight/coresight-tpiu.c?????? | 2 +-
>>> ? include/linux/coresight.h????????????????????????? | 2 +-
>>> ? 9 files changed, 14 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/ 
>>> hwtracing/coresight/coresight-catu.c
>>> index bfea880d6dfb..337668f9cfd4 100644
>>> --- a/drivers/hwtracing/coresight/coresight-catu.c
>>> +++ b/drivers/hwtracing/coresight/coresight-catu.c
>>> @@ -702,7 +702,7 @@ static int __init catu_init(void)
>>> ? {
>>> ????? int ret;
>>> ? -??? ret = coresight_init_driver("catu", &catu_driver, 
>>> &catu_platform_driver);
>>> +??? ret = coresight_init_driver("catu", &catu_driver, 
>>> &catu_platform_driver, THIS_MODULE);
>>> ????? tmc_etr_set_catu_ops(&etr_catu_buf_ops);
>>> ????? return ret;
>>> ? }
>>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>>> hwtracing/coresight/coresight-core.c
>>> index 9fc6f6b863e0..c546a417836c 100644
>>> --- a/drivers/hwtracing/coresight/coresight-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>>> @@ -1399,17 +1399,17 @@ module_init(coresight_init);
>>> ? module_exit(coresight_exit);
>>> ??? int coresight_init_driver(const char *drv, struct amba_driver 
>>> *amba_drv,
>>> -????????????? struct platform_driver *pdev_drv)
>>> +????????????? struct platform_driver *pdev_drv, struct module *owner)
>>> ? {
>>> ????? int ret;
>>> ? -??? ret = amba_driver_register(amba_drv);
>>> +??? ret = __amba_driver_register(amba_drv, owner);
>>> ????? if (ret) {
>>> ????????? pr_err("%s: error registering AMBA driver\n", drv);
>>> ????????? return ret;
>>> ????? }
>>> ? -??? ret = platform_driver_register(pdev_drv);
>>> +??? ret = __platform_driver_register(pdev_drv, owner);
>>> ????? if (!ret)
>>> ????????? return 0;
>>> ? diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/ 
>>> drivers/hwtracing/coresight/coresight-cpu-debug.c
>>> index 75962dae9aa1..cc599c5ef4b2 100644
>>> --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
>>> +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
>>> @@ -774,7 +774,8 @@ static struct platform_driver 
>>> debug_platform_driver = {
>>> ??? static int __init debug_init(void)
>>> ? {
>>> -??? return coresight_init_driver("debug", &debug_driver, 
>>> &debug_platform_driver);
>>> +??? return coresight_init_driver("debug", &debug_driver, 
>>> &debug_platform_driver,
>>> +???????????????????? THIS_MODULE);

minor nit:

Could we make the coresight_init_driver() a static inline or even a
macro to automatically add the THIS_MODULE param ?

Something like:

#define coresight_init_driver(name, amba_drv, pdev_drv)
	coresight_init_driver_owner(name, amba_drv, pdev_drv, THIS_MODULE)

I could respin this and queue the change.


Suzuki


>>> ? }
>>> ??? static void __exit debug_exit(void)
>>> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/ 
>>> drivers/hwtracing/coresight/coresight-funnel.c
>>> index 5a819c8970fb..8f451b051ddc 100644
>>> --- a/drivers/hwtracing/coresight/coresight-funnel.c
>>> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
>>> @@ -433,7 +433,8 @@ static struct amba_driver dynamic_funnel_driver = {
>>> ??? static int __init funnel_init(void)
>>> ? {
>>> -??? return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>>> &funnel_driver);
>>> +??? return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>>> &funnel_driver,
>>> +???????????????????? THIS_MODULE);
>>> ? }
>>> ??? static void __exit funnel_exit(void)
>>> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/ 
>>> drivers/hwtracing/coresight/coresight-replicator.c
>>> index 3e55be9c8418..f7607c72857c 100644
>>> --- a/drivers/hwtracing/coresight/coresight-replicator.c
>>> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
>>> @@ -438,7 +438,8 @@ static struct amba_driver 
>>> dynamic_replicator_driver = {
>>> ??? static int __init replicator_init(void)
>>> ? {
>>> -??? return coresight_init_driver("replicator", 
>>> &dynamic_replicator_driver, &replicator_driver);
>>> +??? return coresight_init_driver("replicator", 
>>> &dynamic_replicator_driver, &replicator_driver,
>>> +???????????????????? THIS_MODULE);
>>> ? }
>>> ??? static void __exit replicator_exit(void)
>>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/ 
>>> hwtracing/coresight/coresight-stm.c
>>> index 117dbb484543..403eea8f95d4 100644
>>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>>> @@ -1046,7 +1046,7 @@ static struct platform_driver 
>>> stm_platform_driver = {
>>> ??? static int __init stm_init(void)
>>> ? {
>>> -??? return coresight_init_driver("stm", &stm_driver, 
>>> &stm_platform_driver);
>>> +??? return coresight_init_driver("stm", &stm_driver, 
>>> &stm_platform_driver, THIS_MODULE);
>>> ? }
>>> ??? static void __exit stm_exit(void)
>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/ 
>>> drivers/hwtracing/coresight/coresight-tmc-core.c
>>> index b54562f392f3..e31e36635394 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
>>> @@ -742,7 +742,7 @@ static struct platform_driver tmc_platform_driver 
>>> = {
>>> ??? static int __init tmc_init(void)
>>> ? {
>>> -??? return coresight_init_driver("tmc", &tmc_driver, 
>>> &tmc_platform_driver);
>>> +??? return coresight_init_driver("tmc", &tmc_driver, 
>>> &tmc_platform_driver, THIS_MODULE);
>>> ? }
>>> ??? static void __exit tmc_exit(void)
>>> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/ 
>>> hwtracing/coresight/coresight-tpiu.c
>>> index b048e146fbb1..f9ecd05cbe5c 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
>>> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
>>> @@ -318,7 +318,7 @@ static struct platform_driver 
>>> tpiu_platform_driver = {
>>> ??? static int __init tpiu_init(void)
>>> ? {
>>> -??? return coresight_init_driver("tpiu", &tpiu_driver, 
>>> &tpiu_platform_driver);
>>> +??? return coresight_init_driver("tpiu", &tpiu_driver, 
>>> &tpiu_platform_driver, THIS_MODULE);
>>> ? }
>>> ??? static void __exit tpiu_exit(void)
>>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>>> index f09ace92176e..e6c26952ddc2 100644
>>> --- a/include/linux/coresight.h
>>> +++ b/include/linux/coresight.h
>>> @@ -660,7 +660,7 @@ coresight_find_output_type(struct 
>>> coresight_platform_data *pdata,
>>> ???????????????? union coresight_dev_subtype subtype);
>>> ??? int coresight_init_driver(const char *drv, struct amba_driver 
>>> *amba_drv,
>>> -????????????? struct platform_driver *pdev_drv);
>>> +????????????? struct platform_driver *pdev_drv, struct module *owner);
>>> ??? void coresight_remove_driver(struct amba_driver *amba_drv,
>>> ?????????????????? struct platform_driver *pdev_drv);
>>
>>
>> .
>>
> 



From kevin_chen at aspeedtech.com  Fri Mar 14 03:39:59 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 10:39:59 +0000
Subject: [PATCH v2 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <142a2edc-a668-4a6a-a4e8-eff3e8bf9e91@kernel.org>
References: <20250304104434.481429-1-kevin_chen@aspeedtech.com>
 <20250304104434.481429-3-kevin_chen@aspeedtech.com>
 <142a2edc-a668-4a6a-a4e8-eff3e8bf9e91@kernel.org>
Message-ID: <PSAPR06MB49492B48614D381498502A9089D22@PSAPR06MB4949.apcprd06.prod.outlook.com>

> On 04/03/2025 11:44, Kevin Chen wrote:
> > The AST2600 has PCC controller in LPC, placed in LPC node.
> >
> > Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> > ---
> >  arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> > index 8ed715bd53aa..87dcacb78692 100644
> > --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> > +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> > @@ -626,6 +626,13 @@ lpc_snoop: lpc-snoop at 80 {
> >  					status = "disabled";
> >  				};
> >
> > +				lpc_pcc: lpc-pcc at 0 {
> > +					compatible = "aspeed,ast2600-lpc-pcc";
> > +					reg = <0x0 0x140>;
> > +					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> > +					status = "disabled";
> 
> Incomplete. Your driver clearly bails on missing ports...
Agree.

> 
> Best regards,
> Krzysztof

From linus.walleij at linaro.org  Fri Mar 14 03:40:43 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 11:40:43 +0100
Subject: [PATCH 0/2] Add gpio-ranges property for EN7581 gpio controller
In-Reply-To: <Z9CYEZloamPhVdBS@lore-desk>
References: <20250307-en7581-gpio-range-v1-0-de1262105428@kernel.org> <Z9CYEZloamPhVdBS@lore-desk>
Message-ID: <CACRpkdagLPe8Mt1imjeBhMuxn5rUMMgsF0KceQpGyQE9ECoJGg@mail.gmail.com>

On Tue, Mar 11, 2025 at 9:07?PM Lorenzo Bianconi <lorenzo at kernel.org> wrote:

> is it fine if this series goes via linux-mediatek tree?
> en7581_pinctrl node is only defined there for the moment.

I applied 1/2 to the pinctrl tree.

Take 2/2 through the mediatek tree.

It will all land nicely upstream and works in linux-next.

Yours,
Linus Walleij


From dan.carpenter at linaro.org  Fri Mar 14 03:54:01 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 14 Mar 2025 13:54:01 +0300
Subject: [bug report] arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT in
 [pmd|pud]_mkhuge()
Message-ID: <d7902504-1ed4-452f-9b08-148f6b8b69fd@stanley.mountain>

Hello Anshuman Khandual,

Commit 1601df9e366e ("arm64/mm: Clear PXX_TYPE_MASK and set
PXD_TYPE_SECT in [pmd|pud]_mkhuge()") from Feb 21, 2025 (linux-next),
leads to the following (unpublished) Smatch static checker warning:

arch/arm64/include/asm/pgtable.h:587 pmd_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'
arch/arm64/include/asm/pgtable.h:626 pud_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'

arch/arm64/include/asm/pgtable.h
    579 static inline pmd_t pmd_mkhuge(pmd_t pmd)
    580 {
    581         /*
    582          * It's possible that the pmd is present-invalid on entry
    583          * and in that case it needs to remain present-invalid on
    584          * exit. So ensure the VALID bit does not get modified.
    585          */
    586         pmdval_t mask = PMD_TYPE_MASK & ~PTE_VALID;
--> 587         pmdval_t val = PMD_TYPE_SECT & ~PTE_VALID;

This is "1 & ~1".  I see the comment, but I'm too stupid to know even
after reading he comment whether it's intentional or not.  :P

    588 
    589         return __pmd((pmd_val(pmd) & ~mask) | val);
    590 }

regards,
dan carpenter


From dan.carpenter at linaro.org  Fri Mar 14 03:55:10 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 14 Mar 2025 13:55:10 +0300
Subject: [PATCH next] Coresight: Fix a NULL vs IS_ERR() bug in probe
Message-ID: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>

The devm_platform_get_and_ioremap_resource() function doesn't
return NULL, it returns error pointers.  Update the checking to
match.

Fixes: f78d206f3d73 ("Coresight: Add Coresight TMC Control Unit driver")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/hwtracing/coresight/coresight-ctcu-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index da35d8b4d579..c6bafc96db96 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -204,8 +204,8 @@ static int ctcu_probe(struct platform_device *pdev)
 	dev->platform_data = pdata;
 
 	base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
-	if (!base)
-		return -ENOMEM;
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	drvdata->apb_clk = coresight_get_enable_apb_pclk(dev);
 	if (IS_ERR(drvdata->apb_clk))
-- 
2.47.2



From kevin_chen at aspeedtech.com  Fri Mar 14 03:56:53 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 10:56:53 +0000
Subject: [PATCH v3 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <0e30c12f-5ac5-4008-8cc8-ec4111520655@kernel.org>
References: <20250310114839.3098148-1-kevin_chen@aspeedtech.com>
 <20250310114839.3098148-4-kevin_chen@aspeedtech.com>
 <0e30c12f-5ac5-4008-8cc8-ec4111520655@kernel.org>
Message-ID: <PSAPR06MB4949A7F02A7780572DCD87F389D22@PSAPR06MB4949.apcprd06.prod.outlook.com>

> On 10/03/2025 12:48, Kevin Chen wrote:
> > +static int aspeed_pcc_probe(struct platform_device *pdev) {
> > +	int rc;
> > +	struct aspeed_pcc_ctrl *pcc;
> > +	struct device *dev = &pdev->dev;
> > +	uint32_t fifo_size = PAGE_SIZE;
> > +
> > +	pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL);
> > +	if (!pcc)
> > +		return -ENOMEM;
> > +
> > +	pcc->regmap = syscon_node_to_regmap(dev->parent->of_node);
> > +	if (IS_ERR(pcc->regmap)) {
> > +		dev_err(dev, "Couldn't get regmap\n");
> 
> return dev_err_probe() is not suitable?
Agree. Change to " dev_err_probe(dev, PTR_ERR(pcc->regmap),"Couldn't get regmap\n");"?

> 
> > +		return -ENODEV;
> 
> Why overriding error code?

> 
> > +	}
> > +
> > +	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
> > +	if (rc) {
> > +		dev_err(dev, "no pcc ports configured\n");
> > +		return -ENODEV;
> 
> Why overriding error code?
Agree.

> 
> You got this comment already at v2.
Sorry, I already checked the comment in v2.

> 
> > +	}
> > +
> > +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> > +	if (rc) {
> > +		dev_err(dev, "cannot set 64-bits DMA mask\n");
> > +		return rc;
> > +	}
> > +
> > +	pcc->dma.size = PCC_DMA_BUFSZ;
> > +	pcc->dma.virt = dmam_alloc_coherent(dev,
> > +					    pcc->dma.size,
> > +					    &pcc->dma.addr,
> > +					    GFP_KERNEL);
> > +	if (!pcc->dma.virt) {
> > +		dev_err(dev, "cannot allocate DMA buffer\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
> > +	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
> > +	if (rc) {
> 
> Drop {}
Agree.
> 
> > +		return -ENOMEM;
> > +	}
> > +
> 
> Please run scripts/checkpatch.pl and fix reported warnings. After that, run also
> `scripts/checkpatch.pl --strict` and (probably) fix more warnings. Some
> warnings can be ignored, especially from --strict run, but the code here looks
> like it needs a fix. Feel free to get in touch if the warning is not clear.
Agree.

> 
> 
> 
> Best regards,
> Krzysztof

From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:13 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:13 +0100
Subject: [PATCH v7 00/11] drm/bridge: add devm_drm_bridge_alloc() with
 bridge refcount
Message-ID: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>

This series improves the way DRM bridges are allocated and initialized and
makes them reference-counted. The goal of reference counting is to avoid
use-after-free by drivers which got a pointer to a bridge and keep it
stored and used even after the bridge has been deallocated.

The overall goal is supporting Linux devices with a DRM pipeline whose
final components can be hot-plugged and hot-unplugged, including one or
more bridges. For more details see the big picture [0].

DRM bridge drivers will have to be adapted to the new API, which is pretty
simple for most cases. Refcounting will have to be adopted on the two
sides: all functions returning a bridge pointer and all code obtaining such
a pointer. This series has just an overview of some of those conversions,
because for now the main goal is to agree on the API.

Series layout:

 1. Add the new API and refcounting:

    drm/bridge: add devm_drm_bridge_alloc()
    drm/bridge: add support for refcounting

 2. get/put the reference in basic operations in the bridge core:

    drm/bridge: get/put the bridge reference in drm_bridge_add/remove()
    drm/bridge: get/put the bridge reference in drm_bridge_attach/detach()

 3. as an example of changes for bridge consumers, get a reference for the
    bridge returned by drm_bridge_chain_get_first_bridge(), have it put by
    all callers (all users will be covered later on separately):

    drm/bridge: add a cleanup action for scope-based drm_bridge_put() invocation
    drm/bridge: get the bridge returned by drm_bridge_chain_get_first_bridge()
    drm/mxsfb: put the bridge returned by drm_bridge_chain_get_first_bridge()
    drm/atomic-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()
    drm/probe-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()

 4. convert a few bridge drivers (bridge providers) to the new API:

    drm/bridge: ti-sn65dsi83: use dynamic lifetime management
    drm/bridge: samsung-dsim: use dynamic lifetime management

This work was formerly a part of my v6 DRM bridge hotplug series[0], now
split as a standalone series with many improvements, hence the "v7" version
number.

[0] https://lore.kernel.org/dri-devel/20250206-hotplug-drm-bridge-v6-0-9d6f2c9c3058 at bootlin.com/

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
Luca Ceresoli (11):
      drm/bridge: add devm_drm_bridge_alloc()
      drm/bridge: add support for refcounting
      drm/bridge: get/put the bridge reference in drm_bridge_add/remove()
      drm/bridge: get/put the bridge reference in drm_bridge_attach/detach()
      drm/bridge: add a cleanup action for scope-based drm_bridge_put() invocation
      drm/bridge: get the bridge returned by drm_bridge_chain_get_first_bridge()
      drm/mxsfb: put the bridge returned by drm_bridge_chain_get_first_bridge()
      drm/atomic-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()
      drm/probe-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()
      drm/bridge: ti-sn65dsi83: use dynamic lifetime management
      drm/bridge: samsung-dsim: use dynamic lifetime management

 drivers/gpu/drm/bridge/samsung-dsim.c |   7 +-
 drivers/gpu/drm/bridge/ti-sn65dsi83.c |   7 +-
 drivers/gpu/drm/drm_atomic_helper.c   |   5 ++
 drivers/gpu/drm/drm_bridge.c          |  74 +++++++++++++++++++--
 drivers/gpu/drm/drm_probe_helper.c    |   1 +
 drivers/gpu/drm/mxsfb/lcdif_kms.c     |   3 +-
 include/drm/drm_bridge.h              | 119 +++++++++++++++++++++++++++++++++-
 7 files changed, 201 insertions(+), 15 deletions(-)
---
base-commit: 9e6d91c60b0d64a4f945663993b3bbf4f3fb7392
change-id: 20250314-drm-bridge-refcount-58d9503503f6

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:14 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:14 +0100
Subject: [PATCH v7 01/11] drm/bridge: add devm_drm_bridge_alloc()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-1-152571f8c694@bootlin.com>

Add a macro to allocate and initialize a DRM bridge embedded within a
private driver struct.

Compared to current practice, which is based on [devm_]kzalloc() allocation
followed by open-coded initialization of fields, this allows to have a
common and explicit API to allocate and initialize DRM bridges.

Besides being useful to consolidate bridge driver code, this is a
fundamental step in preparation for adding dynamic lifetime to bridges
based on refcount.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v7:
- in v6 this was part of "drm/bridge: add support for refcounted DRM
  bridges", now split to a separate patch
---
 drivers/gpu/drm/drm_bridge.c | 22 ++++++++++++++++++++++
 include/drm/drm_bridge.h     | 17 +++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index ea9525ec16b5272d12a21a66913ada38e74e80bc..96df717b2caeb41d45346ded576eaeb2806fd051 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -199,6 +199,28 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
+			      const struct drm_bridge_funcs *funcs)
+{
+	void *container;
+	struct drm_bridge *bridge;
+
+	if (!funcs) {
+		dev_warn(dev, "Missing funcs pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	container = devm_kzalloc(dev, size, GFP_KERNEL);
+	if (!container)
+		return ERR_PTR(-ENOMEM);
+
+	bridge = container + offset;
+	bridge->funcs = funcs;
+
+	return container;
+}
+EXPORT_SYMBOL(__devm_drm_bridge_alloc);
+
 /**
  * drm_bridge_add - add the given bridge to the global bridge list
  *
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index b0d86a685a41e3172e0aa15d1c9a5ae8e959255a..dae463b30542d586a595b67f7bdf5a5e898e9572 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -941,6 +941,23 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
 	return container_of(priv, struct drm_bridge, base);
 }
 
+void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
+			      const struct drm_bridge_funcs *funcs);
+
+/**
+ * devm_drm_bridge_alloc - Allocate and initialize a bridge
+ * @dev: struct device of the bridge device
+ * @type: the type of the struct which contains struct &drm_bridge
+ * @member: the name of the &drm_bridge within @type
+ * @funcs: callbacks for this bridge
+ *
+ * Returns:
+ * Pointer to new bridge, or ERR_PTR on failure.
+ */
+#define devm_drm_bridge_alloc(dev, type, member, funcs) \
+	((type *)__devm_drm_bridge_alloc(dev, sizeof(type), \
+					 offsetof(type, member), funcs))
+
 void drm_bridge_add(struct drm_bridge *bridge);
 int devm_drm_bridge_add(struct device *dev, struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:15 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:15 +0100
Subject: [PATCH v7 02/11] drm/bridge: add support for refcounting
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-2-152571f8c694@bootlin.com>

DRM bridges are currently considered as a fixed element of a DRM card, and
thus their lifetime is assumed to extend for as long as the card
exists. New use cases, such as hot-pluggable hardware with video bridges,
require DRM bridges to be added to and removed from a DRM card without
tearing the card down. This is possible for connectors already (used by DP
MST), it is now needed for DRM bridges as well.

As a first preliminary step, make bridges reference-counted to allow a
struct drm_bridge (along with the private driver structure embedding it) to
stay allocated even after the driver has been removed, until the last
reference is put.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v7:
 - export drm_bridge_put_void
 - struct drm_bridge: use container pointer instead of container_offset
 - remove drm_bridge_is_refcounted()
 - remove all DRM_DEBUG()s
 - drm_bridge_get/put: accept NULL pointer and return the bridge pointer to
   allow pass-through calls
 - extract to separate patches:
    - the addition of drm_bridge_alloc
    - the addition of drm_bridge_get/put() to drm_bridge_add/remove()
    - the addition of drm_bridge_get/put() to drm_bridge_attach/detach()
 - fix a typo, slightly improve kerneldoc

Changes in v6:
 - use drm_warn, not WARN_ON (Jani Nikula)
 - Add devm_drm_bridge_alloc() to replace drm_bridge_init() (similar to
   drmm_encoder_alloc)
 - Remove .destroy func: deallocation is done via the struct offset
   computed by the devm_drm_bridge_alloc() macro
 - use fixed free callback, as the same callback is used in all cases
   anyway (remove free_cb, add bool is_refcounted)
 - add drm_bridge_get/put() to drm_bridge_attach/detach() (add the bridge
   to a list)
 - make some DRM_DEBUG() strings more informative

This patch was added in v5.
---
 drivers/gpu/drm/drm_bridge.c | 33 +++++++++++++++-
 include/drm/drm_bridge.h     | 91 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 96df717b2caeb41d45346ded576eaeb2806fd051..2ba0dac9bfc2dfd709d5e2457d69067c7324972c 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -199,23 +199,54 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+void __drm_bridge_free(struct kref *kref)
+{
+	struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
+
+	kfree(bridge->container);
+}
+EXPORT_SYMBOL(__drm_bridge_free);
+
+/**
+ * drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
+ *
+ * @data: pointer to @struct drm_bridge, cast to a void pointer
+ *
+ * Wrapper of drm_bridge_put() to be used when a function taking a void
+ * pointer is needed, for example as a devm action.
+ */
+void drm_bridge_put_void(void *data)
+{
+	struct drm_bridge *bridge = (struct drm_bridge *)data;
+
+	drm_bridge_put(bridge);
+}
+EXPORT_SYMBOL(drm_bridge_put_void);
+
 void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
 			      const struct drm_bridge_funcs *funcs)
 {
 	void *container;
 	struct drm_bridge *bridge;
+	int err;
 
 	if (!funcs) {
 		dev_warn(dev, "Missing funcs pointer\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	container = devm_kzalloc(dev, size, GFP_KERNEL);
+	container = kzalloc(size, GFP_KERNEL);
 	if (!container)
 		return ERR_PTR(-ENOMEM);
 
 	bridge = container + offset;
+	bridge->container = container;
 	bridge->funcs = funcs;
+	kref_init(&bridge->refcount);
+
+	err = devm_add_action_or_reset(dev, drm_bridge_put_void, bridge);
+	if (err)
+		return ERR_PTR(err);
 
 	return container;
 }
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index dae463b30542d586a595b67f7bdf5a5e898e9572..5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -840,6 +840,17 @@ struct drm_bridge {
 	const struct drm_bridge_timings *timings;
 	/** @funcs: control functions */
 	const struct drm_bridge_funcs *funcs;
+
+	/**
+	 * @container: Pointer to the private driver struct embedding this
+	 * @struct drm_bridge.
+	 */
+	void *container;
+	/**
+	 * @refcount: reference count of users referencing this bridge.
+	 */
+	struct kref refcount;
+
 	/** @driver_private: pointer to the bridge driver's internal context */
 	void *driver_private;
 	/** @ops: bitmask of operations supported by the bridge */
@@ -941,6 +952,82 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
 	return container_of(priv, struct drm_bridge, base);
 }
 
+void __drm_bridge_free(struct kref *kref);
+
+/**
+ * drm_bridge_get - Acquire a bridge reference
+ * @bridge: DRM bridge
+ *
+ * This function increments the bridge's refcount.
+ *
+ * Returns:
+ * Pointer to @bridge.
+ */
+static inline struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge)
+{
+	if (!bridge)
+		return bridge;
+
+	kref_get(&bridge->refcount);
+
+	return bridge;
+}
+
+/**
+ * drm_bridge_put - Release a bridge reference
+ * @bridge: DRM bridge
+ *
+ * This function decrements the bridge's reference count and frees the
+ * object if the reference count drops to zero.
+ *
+ * See also drm_bridge_put_and_clear() which is more handy in many cases.
+ *
+ * Returns:
+ * Pointer to @bridge.
+ */
+static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
+{
+	if (!bridge)
+		return bridge;
+
+	kref_put(&bridge->refcount, __drm_bridge_free);
+
+	return bridge;
+}
+
+void drm_bridge_put_void(void *data);
+
+/**
+ * drm_bridge_put_and_clear - Given a bridge pointer, clear the pointer
+ *                            then put the bridge
+ *
+ * @bridge_pp: pointer to pointer to a struct drm_bridge
+ *
+ * Helper to put a DRM bridge (whose pointer is passed), but only after
+ * setting its pointer to NULL. Useful for drivers having struct drm_bridge
+ * pointers they need to dispose of, without leaving a use-after-free
+ * window where the pointed bridge might have been freed while still
+ * holding a pointer to it.
+ *
+ * For example a driver having this private struct::
+ *
+ *     struct my_bridge {
+ *         struct drm_bridge *remote_bridge;
+ *         ...
+ *     };
+ *
+ * can dispose of remote_bridge using::
+ *
+ *     drm_bridge_put_and_clear(&my_bridge->remote_bridge);
+ */
+static inline void drm_bridge_put_and_clear(struct drm_bridge **bridge_pp)
+{
+	struct drm_bridge *bridge = *bridge_pp;
+
+	*bridge_pp = NULL;
+	drm_bridge_put(bridge);
+}
+
 void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
 			      const struct drm_bridge_funcs *funcs);
 
@@ -951,6 +1038,10 @@ void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
  * @member: the name of the &drm_bridge within @type
  * @funcs: callbacks for this bridge
  *
+ * The returned refcount is initialized to 1. This reference will be
+ * automatically dropped via devm (by calling drm_bridge_put()) when @dev
+ * is removed.
+ *
  * Returns:
  * Pointer to new bridge, or ERR_PTR on failure.
  */

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:16 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:16 +0100
Subject: [PATCH v7 03/11] drm/bridge: get/put the bridge reference in
 drm_bridge_add/remove()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-3-152571f8c694@bootlin.com>

drm_bridge_add() adds the bridge to the global bridge_list, so take a
reference for that. Vice versa in drm_bridge_remove().

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v7:
- in v6 this was part of "drm/bridge: add support for refcounted DRM
  bridges", now split to a separate patch
---
 drivers/gpu/drm/drm_bridge.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 2ba0dac9bfc2dfd709d5e2457d69067c7324972c..72fa51d4dd2337f97c2bd65cfabf9cee05b661b4 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -259,6 +259,8 @@ EXPORT_SYMBOL(__devm_drm_bridge_alloc);
  */
 void drm_bridge_add(struct drm_bridge *bridge)
 {
+	drm_bridge_get(bridge);
+
 	mutex_init(&bridge->hpd_mutex);
 
 	if (bridge->ops & DRM_BRIDGE_OP_HDMI)
@@ -306,6 +308,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 	mutex_unlock(&bridge_lock);
 
 	mutex_destroy(&bridge->hpd_mutex);
+
+	drm_bridge_put(bridge);
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:17 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:17 +0100
Subject: [PATCH v7 04/11] drm/bridge: get/put the bridge reference in
 drm_bridge_attach/detach()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-4-152571f8c694@bootlin.com>

drm_bridge_attach() adds the bridge to the encoder chain, so take a
reference for that. Vice versa in drm_bridge_detach().

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v7:
- in v6 this was part of "drm/bridge: add support for refcounted DRM
  bridges", now split to a separate patch
---
 drivers/gpu/drm/drm_bridge.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 72fa51d4dd2337f97c2bd65cfabf9cee05b661b4..da85694e9310f1f910bc8a5aa5d95a91d9254888 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -370,11 +370,17 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 	if (!encoder || !bridge)
 		return -EINVAL;
 
-	if (previous && (!previous->dev || previous->encoder != encoder))
-		return -EINVAL;
+	drm_bridge_get(bridge);
 
-	if (bridge->dev)
-		return -EBUSY;
+	if (previous && (!previous->dev || previous->encoder != encoder)) {
+		ret = -EINVAL;
+		goto err_put_bridge;
+	}
+
+	if (bridge->dev) {
+		ret = -EBUSY;
+		goto err_put_bridge;
+	}
 
 	bridge->dev = encoder->dev;
 	bridge->encoder = encoder;
@@ -423,6 +429,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 			      "failed to attach bridge %pOF to encoder %s\n",
 			      bridge->of_node, encoder->name);
 
+err_put_bridge:
+	drm_bridge_put(bridge);
 	return ret;
 }
 EXPORT_SYMBOL(drm_bridge_attach);
@@ -443,6 +451,7 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 
 	list_del(&bridge->chain_node);
 	bridge->dev = NULL;
+	drm_bridge_put(bridge);
 }
 
 /**

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:18 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:18 +0100
Subject: [PATCH v7 05/11] drm/bridge: add a cleanup action for scope-based
 drm_bridge_put() invocation
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-5-152571f8c694@bootlin.com>

Many functions get a drm_bridge pointer, only use it in the function body
(or a smaller scope such as a loop body), and don't store it. In these
cases they always need to drm_bridge_put() it before returning (or exiting
the scope).

Some of those functions have complex code paths with multiple return points
or loop break/continue. This makes adding drm_bridge_put() in the right
places tricky, ugly and error prone in case of future code changes.

Others use the bridge pointer in the return statement and would need to
split the return line to fit the drm_bridge_put, which is a bit annoying:

  -return some_thing(bridge);
  +ret = some_thing(bridge);
  +drm_bridge_put(bridge);
  +return ret;

To make it easier for all of them to put the bridge reference correctly
without complicating code, define a scope-based cleanup action to be used
with __free().

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v7.
---
 include/drm/drm_bridge.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47..a5accd64c364ebb57903ae1e7459034ad9ebf4f3 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -23,6 +23,7 @@
 #ifndef __DRM_BRIDGE_H__
 #define __DRM_BRIDGE_H__
 
+#include <linux/cleanup.h>
 #include <linux/ctype.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -995,6 +996,9 @@ static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
 	return bridge;
 }
 
+/* Cleanup action for use with __free() */
+DEFINE_FREE(drm_bridge_put, struct drm_bridge *, if (_T) drm_bridge_put(_T))
+
 void drm_bridge_put_void(void *data);
 
 /**

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:19 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:19 +0100
Subject: [PATCH v7 06/11] drm/bridge: get the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-6-152571f8c694@bootlin.com>

drm_bridge_chain_get_first_bridge() returns a bridge pointer that the
caller could hold for a long time. Increment the refcount of the returned
bridge and document it must be put by the caller.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v7.
---
 include/drm/drm_bridge.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index a5accd64c364ebb57903ae1e7459034ad9ebf4f3..d9777d5f2e9ef006f0062e4507bce99df4146cd9 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -1105,6 +1105,9 @@ drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
  * drm_bridge_chain_get_first_bridge() - Get the first bridge in the chain
  * @encoder: encoder object
  *
+ * The refcount of the returned bridge is incremented. Use drm_bridge_put()
+ * when done with it.
+ *
  * RETURNS:
  * the first bridge in the chain, or NULL if @encoder has no bridge attached
  * to it.
@@ -1112,8 +1115,8 @@ drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
 static inline struct drm_bridge *
 drm_bridge_chain_get_first_bridge(struct drm_encoder *encoder)
 {
-	return list_first_entry_or_null(&encoder->bridge_chain,
-					struct drm_bridge, chain_node);
+	return drm_bridge_get(list_first_entry_or_null(&encoder->bridge_chain,
+						       struct drm_bridge, chain_node));
 }
 
 /**

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:20 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:20 +0100
Subject: [PATCH v7 07/11] drm/mxsfb: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-7-152571f8c694@bootlin.com>

The bridge returned by drm_bridge_chain_get_first_bridge() is
refcounted. Put it when done. Use a scope-based free action to catch all
the code paths.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v7.
---
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index dbd42cc1da87f82ef9cd4ccc70cdecbe56035174..21311cf5efee7d26c80316bffe80dd2bfed02238 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -433,7 +433,6 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_bridge_state *bridge_state;
-	struct drm_bridge *bridge;
 	u32 bus_format, bus_flags;
 	bool format_set = false, flags_set = false;
 	int ret, i;
@@ -448,6 +447,8 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
 
 	/* Try to find consistent bus format and flags across first bridges. */
 	for_each_new_connector_in_state(state, connector, connector_state, i) {
+		struct drm_bridge *bridge __free(drm_bridge_put) = NULL;
+
 		if (!connector_state->crtc)
 			continue;
 

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:21 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:21 +0100
Subject: [PATCH v7 08/11] drm/atomic-helper: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-8-152571f8c694@bootlin.com>

The bridge returned by drm_bridge_chain_get_first_bridge() is
refcounted. Put it when done.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Note: I suspect most or all of the involved functions here could just
receive the encoder instead of the first bridge in the chain, and then walk
the encoder chain on their own. For the sake of simplicity and to show how
to put a bridge in general I've kept this patch in this form, for the time
being.

This patch was added in v7.
---
 drivers/gpu/drm/drm_atomic_helper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5302ab3248985d3e0a47e40fd3deb7ad0d9f775b..fcd9139ef98e9f57659b7e447cf57702e99a5165 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -455,6 +455,7 @@ mode_fixup(struct drm_atomic_state *state)
 		ret = drm_atomic_bridge_chain_check(bridge,
 						    new_crtc_state,
 						    new_conn_state);
+		drm_bridge_put(bridge);
 		if (ret) {
 			drm_dbg_atomic(encoder->dev, "Bridge atomic check failed\n");
 			return ret;
@@ -526,6 +527,7 @@ static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
 	bridge = drm_bridge_chain_get_first_bridge(encoder);
 	ret = drm_bridge_chain_mode_valid(bridge, &connector->display_info,
 					  mode);
+	drm_bridge_put(bridge);
 	if (ret != MODE_OK) {
 		drm_dbg_atomic(encoder->dev, "[BRIDGE] mode_valid() failed\n");
 		return ret;
@@ -1226,6 +1228,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *state)
 		}
 
 		drm_atomic_bridge_chain_post_disable(bridge, state);
+		drm_bridge_put(bridge);
 	}
 
 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1433,6 +1436,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *state)
 
 		bridge = drm_bridge_chain_get_first_bridge(encoder);
 		drm_bridge_chain_mode_set(bridge, mode, adjusted_mode);
+		drm_bridge_put(bridge);
 	}
 }
 
@@ -1564,6 +1568,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		}
 
 		drm_atomic_bridge_chain_enable(bridge, state);
+		drm_bridge_put(bridge);
 	}
 
 	drm_atomic_helper_commit_writebacks(dev, state);

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:23 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:23 +0100
Subject: [PATCH v7 10/11] drm/bridge: ti-sn65dsi83: use dynamic lifetime
 management
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-10-152571f8c694@bootlin.com>

Allow this bridge to be removable without dangling pointers and
use-after-free, together with proper use of drm_bridge_get() and _put() by
consumers.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v7: none

Changed in v6:
 - Update to use devm_drm_bridge_alloc(), remove .destroy

This patch was added in v5.
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 5f8bfeeb553f970671a602fcf2594016243b9db2..bc092fb926563439e316c2cb5a817bd938093df4 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -952,9 +952,9 @@ static int sn65dsi83_probe(struct i2c_client *client)
 	struct sn65dsi83 *ctx;
 	int ret;
 
-	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
+	ctx = devm_drm_bridge_alloc(dev, struct sn65dsi83, bridge, &sn65dsi83_funcs);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
 
 	ctx->dev = dev;
 	INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work);
@@ -994,7 +994,6 @@ static int sn65dsi83_probe(struct i2c_client *client)
 	dev_set_drvdata(dev, ctx);
 	i2c_set_clientdata(client, ctx);
 
-	ctx->bridge.funcs = &sn65dsi83_funcs;
 	ctx->bridge.of_node = dev->of_node;
 	ctx->bridge.pre_enable_prev_first = true;
 	ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS;

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:22 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:22 +0100
Subject: [PATCH v7 09/11] drm/probe-helper: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-9-152571f8c694@bootlin.com>

The bridge returned by drm_bridge_chain_get_first_bridge() is
refcounted. Put it when done.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v7.
---
 drivers/gpu/drm/drm_probe_helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 7ba16323e7c2f4bc7ec61f96b01ddfe28461b6a0..15525124ee66b512979e5c4774dd765618bd15d7 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -119,6 +119,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
 		*status = drm_bridge_chain_mode_valid(bridge,
 						      &connector->display_info,
 						      mode);
+		drm_bridge_put(bridge);
 		if (*status != MODE_OK) {
 			/* There is also no point in continuing for crtc check
 			 * here. */

-- 
2.48.1



From luca.ceresoli at bootlin.com  Fri Mar 14 03:31:24 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 14 Mar 2025 11:31:24 +0100
Subject: [PATCH v7 11/11] drm/bridge: samsung-dsim: use dynamic lifetime
 management
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-drm-bridge-refcount-v7-11-152571f8c694@bootlin.com>

Allow this bridge to be removable without dangling pointers and
use-after-free, together with proper use of drm_bridge_get() and _put() by
consumers.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v7.
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 54de6ed2fae81bc13301a6b1ee8f38183a3118b6..3d41db7a0ceeddccc1a89a2ff1f38fe10ec6acfe 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1935,9 +1935,9 @@ int samsung_dsim_probe(struct platform_device *pdev)
 	struct samsung_dsim *dsi;
 	int ret, i;
 
-	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
-	if (!dsi)
-		return -ENOMEM;
+	dsi = devm_drm_bridge_alloc(dev, struct samsung_dsim, bridge, &samsung_dsim_bridge_funcs);
+	if (IS_ERR(dsi))
+		return PTR_ERR(dsi);
 
 	init_completion(&dsi->completed);
 	spin_lock_init(&dsi->transfer_lock);
@@ -2007,7 +2007,6 @@ int samsung_dsim_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
-	dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 

-- 
2.48.1



From krzk at kernel.org  Fri Mar 14 03:32:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 14 Mar 2025 11:32:13 +0100
Subject: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents
In-Reply-To: <20250314073307.25092-6-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-6-Lu.Tang@mediatek.com>
Message-ID: <19ddb133-7f11-4c1b-b0e1-91523d42040c@kernel.org>

On 14/03/2025 08:32, Lu.Tang wrote:

Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

There is no subsystem "pmic".

> Add new pmic mfd and adc documents for mt8196
> 
> Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>

Are you sure Latin transcription of your name includes '.' or you just
copy-paste email address?


...

> +  - Lu Tang <lu.tang at mediatek.com>
> +
> +description:
> +  The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
> +  in some MediaTek PMICs, performing various PMIC related measurements
> +  such as battery and PMIC internal voltage regulators temperatures,
> +  other than voltages for various PMIC internal components.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - mediatek,mt6363-auxadc
> +      - mediatek,mt6373-auxadc

Just fold the device to the parent node.



..



> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
> new file mode 100644
> index 000000000000..a8f1231623cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml

Filename matching one of the compatibles, e.g. the oldest one.

> @@ -0,0 +1,173 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek SPMI PMICs multi-function device
> +
> +maintainers:
> +  - Lu Tang <lu.tang at mediatek.com>
> +
> +description: |
> +  Some Mediatek PMICs are interfaced to the chip via the SPMI (System Power
> +  Management Interface) bus.
> +
> +  The Mediatek SPMI series includes the MT6363, MT6373, MT6316 and other
> +  PMICs.Please see the sub-modules below for supported features.
> +
> +   MT6363/MT6373 is a multifunction device with the following sub modules:
> +  - Regulators
> +  - ADC
> +  - GPIO
> +  - Keys
> +   MT6316 is a multifunction device with the following sub modules:
> +  - Regulators

I don't get why they are in the same schema. It would result in
unnecessary big if:then with half of children not applicable for other
variants.

> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - mediatek,mt6363
> +          - mediatek,mt6373
> +          - mediatek,mt6316
Sort these with alphanumeric order.

Best regards,
Krzysztof


From linus.walleij at linaro.org  Fri Mar 14 03:35:45 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 14 Mar 2025 11:35:45 +0100
Subject: [PATCH next] pinctrl: bcm281xx: Add missing assignment in bcm21664_pinctrl_lock_all()
In-Reply-To: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
References: <dfc15d59-7fa9-4f96-aacb-37c3df6d420d@stanley.mountain>
Message-ID: <CACRpkdYkvTr9ijyEVSzevHdHFDb0iJTOzCS_3gQG0eNcpR7tcw@mail.gmail.com>

On Mon, Mar 10, 2025 at 11:48?AM Dan Carpenter <dan.carpenter at linaro.org> wrote:

> The next line checks if this regmap_write() failed, but it doesn't
> work because the assignment was accidentally left out.  Add the
> assignment.
>
> Fixes: 60d69769c851 ("pinctrl: bcm281xx: Add support for BCM21664 pinmux")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>

Patch applied!

Yours,
Linus Walleij


From angelogioacchino.delregno at collabora.com  Fri Mar 14 03:35:56 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Fri, 14 Mar 2025 11:35:56 +0100
Subject: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents
In-Reply-To: <19ddb133-7f11-4c1b-b0e1-91523d42040c@kernel.org>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-6-Lu.Tang@mediatek.com>
 <19ddb133-7f11-4c1b-b0e1-91523d42040c@kernel.org>
Message-ID: <d4b3bc28-b96b-4b11-a99d-d3492ad19438@collabora.com>

Il 14/03/25 11:32, Krzysztof Kozlowski ha scritto:
> On 14/03/2025 08:32, Lu.Tang wrote:
> 
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
> 
> There is no subsystem "pmic".
> 
>> Add new pmic mfd and adc documents for mt8196
>>
>> Signed-off-by: Lu.Tang <Lu.Tang at mediatek.com>
> 
> Are you sure Latin transcription of your name includes '.' or you just
> copy-paste email address?
> 
> 
> ...
> 
>> +  - Lu Tang <lu.tang at mediatek.com>
>> +
>> +description:
>> +  The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
>> +  in some MediaTek PMICs, performing various PMIC related measurements
>> +  such as battery and PMIC internal voltage regulators temperatures,
>> +  other than voltages for various PMIC internal components.
>> +
>> +properties:
>> +  compatible:
>> +    enum:
>> +      - mediatek,mt6363-auxadc
>> +      - mediatek,mt6373-auxadc
> 
> Just fold the device to the parent node.
> 
> 
> 
> ..
> 
> 
> 
>> diff --git a/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
>> new file mode 100644
>> index 000000000000..a8f1231623cf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/mediatek,spmi-pmic.yaml
> 
> Filename matching one of the compatibles, e.g. the oldest one.
> 

Yeah but besides that I don't see valid reasons why this should be a different
binding (and also why this should use a different driver, fwiw) - when it can
most probably just extend the current PMIC MFD driver... and the same goes for
the PMIC AUXADC: there's a mt6359-auxadc binding and driver that can be extended
to 6363 and 6373 rather easily.

There's nothing "really special" about those.....

Cheers

>> @@ -0,0 +1,173 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/mfd/mediatek,spmi-pmic.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: MediaTek SPMI PMICs multi-function device
>> +
>> +maintainers:
>> +  - Lu Tang <lu.tang at mediatek.com>
>> +
>> +description: |
>> +  Some Mediatek PMICs are interfaced to the chip via the SPMI (System Power
>> +  Management Interface) bus.
>> +
>> +  The Mediatek SPMI series includes the MT6363, MT6373, MT6316 and other
>> +  PMICs.Please see the sub-modules below for supported features.
>> +
>> +   MT6363/MT6373 is a multifunction device with the following sub modules:
>> +  - Regulators
>> +  - ADC
>> +  - GPIO
>> +  - Keys
>> +   MT6316 is a multifunction device with the following sub modules:
>> +  - Regulators
> 
> I don't get why they are in the same schema. It would result in
> unnecessary big if:then with half of children not applicable for other
> variants.
> 
>> +
>> +properties:
>> +  compatible:
>> +    oneOf:
>> +      - enum:
>> +          - mediatek,mt6363
>> +          - mediatek,mt6373
>> +          - mediatek,mt6316
> Sort these with alphanumeric order.
> 
> Best regards,
> Krzysztof





From ryan.roberts at arm.com  Fri Mar 14 03:58:08 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 10:58:08 +0000
Subject: [v3 PATCH 2/6] arm64: cpufeature: add AmpereOne to BBML2 allow
 list
In-Reply-To: <20250304222018.615808-3-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-3-yang@os.amperecomputing.com>
Message-ID: <36c70203-5203-44a1-bc08-479334b730c7@arm.com>

On 04/03/2025 22:19, Yang Shi wrote:
> AmpereOne supports BBML2 without conflict abort, add to the allow list.
> 
> Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
> ---
>  arch/arm64/kernel/cpufeature.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 7934c6dd493e..bf3df8407ca3 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2192,6 +2192,8 @@ static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>  	static const struct midr_range supports_bbml2_noabort_list[] = {
>  		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
>  		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> +		MIDR_ALL_VERSIONS(MIDR_AMPERE1),
> +		MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
>  		{}
>  	};
>  

Miko's series will move back to additionally checking MMFR2.BBM, so you will
need to add an erratum workaround for these CPUs to set MMFR2.BBM=2 in the
per-cpu "sanitised" feature register. See:

https://lore.kernel.org/linux-arm-kernel/86ecyzorb7.wl-maz at kernel.org/

Thanks,
Ryan



From maz at kernel.org  Fri Mar 14 04:07:01 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 14 Mar 2025 11:07:01 +0000
Subject: [PATCH 2/6] KVM: arm64: Use 0b11 for encoding PKVM_NOPAGE
In-Reply-To: <20250227003310.367350-3-qperret@google.com>
References: <20250227003310.367350-1-qperret@google.com>
	<20250227003310.367350-3-qperret@google.com>
Message-ID: <86cyejooq2.wl-maz@kernel.org>

On Thu, 27 Feb 2025 00:33:06 +0000,
Quentin Perret <qperret at google.com> wrote:
> 
> The page ownership state encoded as 0b11 is currently considered
> reserved for future use, and PKVM_NOPAGE uses bit 2. In order to
> simplify the relocation of the hyp ownership state into the
> vmemmap in later patches, let's use the 'reserved' encoding for
> the PKVM_NOPAGE state. The struct hyp_page layout isn't guaranteed
> stable at all, so there is no real reason to have 'reserved' encodings.
> 
> No functional changes intended.
> 
> Signed-off-by: Quentin Perret <qperret at google.com>
> ---
>  arch/arm64/kvm/hyp/include/nvhe/memory.h | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> index 34233d586060..642b5e05fe77 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> @@ -13,18 +13,15 @@
>   *   01: The page is owned by the page-table owner, but is shared
>   *       with another entity.
>   *   10: The page is shared with, but not owned by the page-table owner.
> - *   11: Reserved for future use (lending).
>   */
>  enum pkvm_page_state {
>  	PKVM_PAGE_OWNED			= 0ULL,
>  	PKVM_PAGE_SHARED_OWNED		= BIT(0),
>  	PKVM_PAGE_SHARED_BORROWED	= BIT(1),
> -	__PKVM_PAGE_RESERVED		= BIT(0) | BIT(1),
>  
>  	/* Meta-states which aren't encoded directly in the PTE's SW bits */
> -	PKVM_NOPAGE			= BIT(2),
> +	PKVM_NOPAGE			= BIT(0) | BIT(1),

Isn't this comment stale now?

	M.

-- 
Without deviation from the norm, progress is not possible.


From will at kernel.org  Fri Mar 14 04:14:58 2025
From: will at kernel.org (Will Deacon)
Date: Fri, 14 Mar 2025 11:14:58 +0000
Subject: [PATCH v2 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <CA+EHjTwHb9mDj20WxeqKky6oAfRDV2R7iiQpwmuBmdZ4aWuS4A@mail.gmail.com>
References: <20250226215520.1759218-1-tabba@google.com>
 <20250226215520.1759218-4-tabba@google.com>
 <Z8ISLxQRcsx2uuHw@google.com>
 <CA+EHjTympdi0wei2Qx=hF2cYvHpzE0sWto2ypcJB3ddmonTROg@mail.gmail.com>
 <20250303191811.GA30361@willie-the-truck>
 <CA+EHjTySqDHDpOy=Vix5ZaNKWg61coySvV3Yk=+i0p8vg3mXTQ@mail.gmail.com>
 <20250303214947.GA30619@willie-the-truck>
 <CA+EHjTzZQ6UnOdaqpZ86JNiY=Gr_UoBAjZxk4CS3Q6nMJYdV2w@mail.gmail.com>
 <20250312152903.GA6488@willie-the-truck>
 <CA+EHjTwHb9mDj20WxeqKky6oAfRDV2R7iiQpwmuBmdZ4aWuS4A@mail.gmail.com>
Message-ID: <20250314111457.GA8834@willie-the-truck>

On Wed, Mar 12, 2025 at 03:31:17PM +0000, Fuad Tabba wrote:
> On Wed, 12 Mar 2025 at 15:29, Will Deacon <will at kernel.org> wrote:
> > On Tue, Mar 04, 2025 at 12:33:27PM +0000, Fuad Tabba wrote:
> > > If you agree, I could whip up something and send it soon.
> >
> > Yeah, I think we should fix this as a separate series and drop the
> > WRITE_ONCE() from this patch.
> 
> I'll send a fix soon.
> 
> Oliver, would you like me to respin this series, or can you drop the
> WRITE_ONCE()?

With the WRITE_ONCE() dropped:

Acked-by: Will Deacon <will at kernel.org>

Cheers,

Will


From tabba at google.com  Fri Mar 14 04:18:31 2025
From: tabba at google.com (Fuad Tabba)
Date: Fri, 14 Mar 2025 11:18:31 +0000
Subject: [PATCH v3 3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to
 separate function
In-Reply-To: <20250314111832.4137161-1-tabba@google.com>
References: <20250314111832.4137161-1-tabba@google.com>
Message-ID: <20250314111832.4137161-4-tabba@google.com>

Move the code that creates and initializes the hyp view of a vcpu
in pKVM to its own function. This is meant to make the transition
to initializing every vcpu individually clearer.

Acked-by: Will Deacon <will at kernel.org>
Reviewed-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Fuad Tabba <tabba at google.com>
---
 arch/arm64/kvm/pkvm.c | 48 ++++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 26 deletions(-)

diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 930b677eb9b0..74cf5d87e77b 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -113,6 +113,24 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 	free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
 }
 
+static int __pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
+{
+	size_t hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
+	pkvm_handle_t handle = vcpu->kvm->arch.pkvm.handle;
+	void *hyp_vcpu;
+	int ret;
+
+	hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
+	if (!hyp_vcpu)
+		return -ENOMEM;
+
+	ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, vcpu, hyp_vcpu);
+	if (ret)
+		free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
+
+	return ret;
+}
+
 /*
  * Allocates and donates memory for hypervisor VM structs at EL2.
  *
@@ -125,9 +143,8 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
  */
 static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 {
-	size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
+	size_t pgd_sz, hyp_vm_sz;
 	struct kvm_vcpu *host_vcpu;
-	pkvm_handle_t handle;
 	void *pgd, *hyp_vm;
 	unsigned long idx;
 	int ret;
@@ -161,33 +178,12 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 	if (ret < 0)
 		goto free_vm;
 
-	handle = ret;
+	host_kvm->arch.pkvm.handle = ret;
 
-	host_kvm->arch.pkvm.handle = handle;
-
-	/* Donate memory for the vcpus at hyp and initialize it. */
-	hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
 	kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
-		void *hyp_vcpu;
-
-		/* Indexing of the vcpus to be sequential starting at 0. */
-		if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
-			ret = -EINVAL;
-			goto destroy_vm;
-		}
-
-		hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
-		if (!hyp_vcpu) {
-			ret = -ENOMEM;
-			goto destroy_vm;
-		}
-
-		ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, host_vcpu,
-					hyp_vcpu);
-		if (ret) {
-			free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
+		ret = __pkvm_create_hyp_vcpu(host_vcpu);
+		if (ret)
 			goto destroy_vm;
-		}
 	}
 
 	return 0;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From tabba at google.com  Fri Mar 14 04:18:32 2025
From: tabba at google.com (Fuad Tabba)
Date: Fri, 14 Mar 2025 11:18:32 +0000
Subject: [PATCH v3 4/4] KVM: arm64: Create each pKVM hyp vcpu after its
 corresponding host vcpu
In-Reply-To: <20250314111832.4137161-1-tabba@google.com>
References: <20250314111832.4137161-1-tabba@google.com>
Message-ID: <20250314111832.4137161-5-tabba@google.com>

Instead of creating and initializing _all_ hyp vcpus in pKVM when
the first host vcpu runs for the first time, initialize _each_
hyp vcpu in conjunction with its corresponding host vcpu.

Some of the host vcpu state (e.g., system registers and traps
values) is not initialized until the first time the host vcpu is
run. Therefore, initializing a hyp vcpu before its corresponding
host vcpu has run for the first time might not view the complete
host state of these vcpus.

Additionally, this behavior is inline with non-protected modes.

Acked-by: Will Deacon <will at kernel.org>
Reviewed-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Fuad Tabba <tabba at google.com>
---
 arch/arm64/include/asm/kvm_host.h      |  2 +
 arch/arm64/include/asm/kvm_pkvm.h      |  1 +
 arch/arm64/kvm/arm.c                   |  4 ++
 arch/arm64/kvm/hyp/include/nvhe/pkvm.h |  6 ---
 arch/arm64/kvm/hyp/nvhe/pkvm.c         | 54 +++++++++++++++-----------
 arch/arm64/kvm/pkvm.c                  | 28 ++++++-------
 6 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d919557af5e5..31b21cf8118a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -869,6 +869,8 @@ struct kvm_vcpu_arch {
 #define VCPU_INITIALIZED	__vcpu_single_flag(cflags, BIT(0))
 /* SVE config completed */
 #define VCPU_SVE_FINALIZED	__vcpu_single_flag(cflags, BIT(1))
+/* pKVM VCPU setup completed */
+#define VCPU_PKVM_FINALIZED	__vcpu_single_flag(cflags, BIT(2))
 
 /* Exception pending */
 #define PENDING_EXCEPTION	__vcpu_single_flag(iflags, BIT(0))
diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h
index eb65f12e81d9..abd693ce5b93 100644
--- a/arch/arm64/include/asm/kvm_pkvm.h
+++ b/arch/arm64/include/asm/kvm_pkvm.h
@@ -19,6 +19,7 @@
 int pkvm_init_host_vm(struct kvm *kvm);
 int pkvm_create_hyp_vm(struct kvm *kvm);
 void pkvm_destroy_hyp_vm(struct kvm *kvm);
+int pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu);
 
 /*
  * This functions as an allow-list of protected VM capabilities.
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0160b4924351..6acd8b924210 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -843,6 +843,10 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 		ret = pkvm_create_hyp_vm(kvm);
 		if (ret)
 			return ret;
+
+		ret = pkvm_create_hyp_vcpu(vcpu);
+		if (ret)
+			return ret;
 	}
 
 	mutex_lock(&kvm->arch.config_lock);
diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
index e42bf68c8848..ce31d3b73603 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
@@ -43,12 +43,6 @@ struct pkvm_hyp_vm {
 	struct hyp_pool pool;
 	hyp_spinlock_t lock;
 
-	/*
-	 * The number of vcpus initialized and ready to run.
-	 * Modifying this is protected by 'vm_table_lock'.
-	 */
-	unsigned int nr_vcpus;
-
 	/* Array of the hyp vCPU structures for this VM. */
 	struct pkvm_hyp_vcpu *vcpus[];
 };
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 6efb9bf56180..4ef3748dc660 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -245,10 +245,12 @@ struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle,
 
 	hyp_spin_lock(&vm_table_lock);
 	hyp_vm = get_vm_by_handle(handle);
-	if (!hyp_vm || hyp_vm->nr_vcpus <= vcpu_idx)
+	if (!hyp_vm || hyp_vm->kvm.created_vcpus <= vcpu_idx)
 		goto unlock;
 
 	hyp_vcpu = hyp_vm->vcpus[vcpu_idx];
+	if (!hyp_vcpu)
+		goto unlock;
 
 	/* Ensure vcpu isn't loaded on more than one cpu simultaneously. */
 	if (unlikely(hyp_vcpu->loaded_hyp_vcpu)) {
@@ -367,8 +369,14 @@ static void unpin_host_vcpus(struct pkvm_hyp_vcpu *hyp_vcpus[],
 {
 	int i;
 
-	for (i = 0; i < nr_vcpus; i++)
-		unpin_host_vcpu(hyp_vcpus[i]->host_vcpu);
+	for (i = 0; i < nr_vcpus; i++) {
+		struct pkvm_hyp_vcpu *hyp_vcpu = hyp_vcpus[i];
+
+		if (!hyp_vcpu)
+			continue;
+
+		unpin_host_vcpu(hyp_vcpu->host_vcpu);
+	}
 }
 
 static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
@@ -392,24 +400,18 @@ static void pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_vcpu *
 
 static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
 			      struct pkvm_hyp_vm *hyp_vm,
-			      struct kvm_vcpu *host_vcpu,
-			      unsigned int vcpu_idx)
+			      struct kvm_vcpu *host_vcpu)
 {
 	int ret = 0;
 
 	if (hyp_pin_shared_mem(host_vcpu, host_vcpu + 1))
 		return -EBUSY;
 
-	if (host_vcpu->vcpu_idx != vcpu_idx) {
-		ret = -EINVAL;
-		goto done;
-	}
-
 	hyp_vcpu->host_vcpu = host_vcpu;
 
 	hyp_vcpu->vcpu.kvm = &hyp_vm->kvm;
 	hyp_vcpu->vcpu.vcpu_id = READ_ONCE(host_vcpu->vcpu_id);
-	hyp_vcpu->vcpu.vcpu_idx = vcpu_idx;
+	hyp_vcpu->vcpu.vcpu_idx = READ_ONCE(host_vcpu->vcpu_idx);
 
 	hyp_vcpu->vcpu.arch.hw_mmu = &hyp_vm->kvm.arch.mmu;
 	hyp_vcpu->vcpu.arch.cflags = READ_ONCE(host_vcpu->arch.cflags);
@@ -647,27 +649,28 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		goto unlock;
 	}
 
-	idx = hyp_vm->nr_vcpus;
+	ret = init_pkvm_hyp_vcpu(hyp_vcpu, hyp_vm, host_vcpu);
+	if (ret)
+		goto unlock;
+
+	idx = hyp_vcpu->vcpu.vcpu_idx;
 	if (idx >= hyp_vm->kvm.created_vcpus) {
 		ret = -EINVAL;
 		goto unlock;
 	}
 
-	ret = init_pkvm_hyp_vcpu(hyp_vcpu, hyp_vm, host_vcpu, idx);
-	if (ret)
+	if (hyp_vm->vcpus[idx]) {
+		ret = -EINVAL;
 		goto unlock;
+	}
 
 	hyp_vm->vcpus[idx] = hyp_vcpu;
-	hyp_vm->nr_vcpus++;
 unlock:
 	hyp_spin_unlock(&vm_table_lock);
 
-	if (ret) {
+	if (ret)
 		unmap_donated_memory(hyp_vcpu, sizeof(*hyp_vcpu));
-		return ret;
-	}
-
-	return 0;
+	return ret;
 }
 
 static void
@@ -713,12 +716,17 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
 	/* Reclaim guest pages (including page-table pages) */
 	mc = &host_kvm->arch.pkvm.teardown_mc;
 	reclaim_guest_pages(hyp_vm, mc);
-	unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->nr_vcpus);
+	unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->kvm.created_vcpus);
 
 	/* Push the metadata pages to the teardown memcache */
-	for (idx = 0; idx < hyp_vm->nr_vcpus; ++idx) {
+	for (idx = 0; idx < hyp_vm->kvm.created_vcpus; ++idx) {
 		struct pkvm_hyp_vcpu *hyp_vcpu = hyp_vm->vcpus[idx];
-		struct kvm_hyp_memcache *vcpu_mc = &hyp_vcpu->vcpu.arch.pkvm_memcache;
+		struct kvm_hyp_memcache *vcpu_mc;
+
+		if (!hyp_vcpu)
+			continue;
+
+		vcpu_mc = &hyp_vcpu->vcpu.arch.pkvm_memcache;
 
 		while (vcpu_mc->nr_pages) {
 			void *addr = pop_hyp_memcache(vcpu_mc, hyp_phys_to_virt);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 74cf5d87e77b..fc6b5df309dd 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -125,7 +125,9 @@ static int __pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
 		return -ENOMEM;
 
 	ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, vcpu, hyp_vcpu);
-	if (ret)
+	if (!ret)
+		vcpu_set_flag(vcpu, VCPU_PKVM_FINALIZED);
+	else
 		free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
 
 	return ret;
@@ -144,9 +146,7 @@ static int __pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
 static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 {
 	size_t pgd_sz, hyp_vm_sz;
-	struct kvm_vcpu *host_vcpu;
 	void *pgd, *hyp_vm;
-	unsigned long idx;
 	int ret;
 
 	if (host_kvm->created_vcpus < 1)
@@ -180,17 +180,7 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
 
 	host_kvm->arch.pkvm.handle = ret;
 
-	kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
-		ret = __pkvm_create_hyp_vcpu(host_vcpu);
-		if (ret)
-			goto destroy_vm;
-	}
-
 	return 0;
-
-destroy_vm:
-	__pkvm_destroy_hyp_vm(host_kvm);
-	return ret;
 free_vm:
 	free_pages_exact(hyp_vm, hyp_vm_sz);
 free_pgd:
@@ -210,6 +200,18 @@ int pkvm_create_hyp_vm(struct kvm *host_kvm)
 	return ret;
 }
 
+int pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
+{
+	int ret = 0;
+
+	mutex_lock(&vcpu->kvm->arch.config_lock);
+	if (!vcpu_get_flag(vcpu, VCPU_PKVM_FINALIZED))
+		ret = __pkvm_create_hyp_vcpu(vcpu);
+	mutex_unlock(&vcpu->kvm->arch.config_lock);
+
+	return ret;
+}
+
 void pkvm_destroy_hyp_vm(struct kvm *host_kvm)
 {
 	mutex_lock(&host_kvm->arch.config_lock);
-- 
2.49.0.rc1.451.g8f38331e32-goog



From lpieralisi at kernel.org  Fri Mar 14 04:19:31 2025
From: lpieralisi at kernel.org (Lorenzo Pieralisi)
Date: Fri, 14 Mar 2025 12:19:31 +0100
Subject: [PATCH v9 2/5] firmware: psci: Read and use vendor reset types
In-Reply-To: <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
 <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>
Message-ID: <Z9QQw6BcE7IXzu+r@lpieralisi>

On Mon, Mar 03, 2025 at 01:08:31PM -0800, Elliot Berman wrote:
> From: Elliot Berman <elliot.berman at oss.qualcomm.com>
> 
> SoC vendors have different types of resets and are controlled through
> various registers. For instance, Qualcomm chipsets can reboot to a
> "download mode" that allows a RAM dump to be collected. Another example
> is they also support writing a cookie that can be read by bootloader
> during next boot. PSCI offers a mechanism, SYSTEM_RESET2, for these
> vendor reset types to be implemented without requiring drivers for every
> register/cookie.
> 
> Add support in PSCI to statically map reboot mode commands from
> userspace to a vendor reset and cookie value using the device tree.

I have managed to discuss a little bit this patchset over the last
few days and I think we have defined a plan going forward.

A point that was raised is:

https://man7.org/linux/man-pages/man2/reboot.2.html

LINUX_REBOOT_CMD_RESTART2 *arg command, what is it supposed to
represent ?

Is it the mode the system should reboot into OR it is the
actual command to be issued (which is what this patchset
implements) ?

LINUX_REBOOT_CMD_RESTART "..a default restart..."

It is unclear what "default" means. We wonder whether the
reboot_mode variable was introduced to _define_ that "default".

So, in short, my aim is trying to decouple reboot_mode from the
LINUX_REBOOT_CMD_RESTART2 *arg command.

I believe that adding a sysfs interface to reboot-mode driver
infrastructure would be useful, so that the commands would
be exposed to userspace and userspace can set the *arg command
specifically to issue a given reset/mode.

I wonder why this is not already in place for eg syscon-reboot-mode
resets, how does user space issue a command in those systems if the
available commands aren't exposed to userspace ?

Is there a kernel entity exposing those "modes" to userspace, somehow ?

> A separate initcall is needed to parse the devicetree, instead of using
> psci_dt_init because mm isn't sufficiently set up to allocate memory.
> 
> Reboot mode framework is close but doesn't quite fit with the
> design and requirements for PSCI SYSTEM_RESET2. Some of these issues can
> be solved but doesn't seem reasonable in sum:
>  1. reboot mode registers against the reboot_notifier_list, which is too
>     early to call SYSTEM_RESET2. PSCI would need to remember the reset
>     type from the reboot-mode framework callback and use it
>     psci_sys_reset.
>  2. reboot mode assumes only one cookie/parameter is described in the
>     device tree. SYSTEM_RESET2 uses 2: one for the type and one for
>     cookie.

This can be changed and I think it should, so that the reboot modes
are exposed to user space and PSCI can use that.

>  3. psci cpuidle driver already registers a driver against the
>     arm,psci-1.0 compatible. Refactoring would be needed to have both a
>     cpuidle and reboot-mode driver.
> 
> Signed-off-by: Elliot Berman <elliot.berman at oss.qualcomm.com>
> ---
>  drivers/firmware/psci/psci.c | 105 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 105 insertions(+)
> 
> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index a1ebbe9b73b136218e9d9f9b8daa7756b3ab2fbe..6f8c47deaec0225f26704e1f3bcad52603127a85 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
> @@ -80,6 +80,14 @@ static u32 psci_cpu_suspend_feature;
>  static bool psci_system_reset2_supported;
>  static bool psci_system_off2_hibernate_supported;
>  
> +struct psci_reset_param {
> +	const char *mode;
> +	u32 reset_type;
> +	u32 cookie;
> +};
> +static struct psci_reset_param *psci_reset_params __ro_after_init;
> +static size_t num_psci_reset_params __ro_after_init;
> +
>  static inline bool psci_has_ext_power_state(void)
>  {
>  	return psci_cpu_suspend_feature &
> @@ -306,9 +314,39 @@ static int get_set_conduit_method(const struct device_node *np)
>  	return 0;
>  }
>  
> +static int psci_vendor_system_reset2(const char *cmd)
> +{
> +	unsigned long ret;
> +	size_t i;
> +
> +	for (i = 0; i < num_psci_reset_params; i++) {
> +		if (!strcmp(psci_reset_params[i].mode, cmd)) {
> +			ret = invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2),
> +					     psci_reset_params[i].reset_type,
> +					     psci_reset_params[i].cookie, 0);
> +			/*
> +			 * if vendor reset fails, log it and fall back to
> +			 * architecture reset types

That's not what the code does.

> +			 */
> +			pr_err("failed to perform reset \"%s\": %ld\n", cmd,
> +			       (long)ret);
> +			return 0;
> +		}
> +	}
> +
> +	return -ENOENT;
> +}
> +
>  static int psci_sys_reset(struct notifier_block *nb, unsigned long action,
>  			  void *data)
>  {
> +	/*
> +	 * try to do the vendor system_reset2
> +	 * If there wasn't a matching command, fall back to architectural resets
> +	 */
> +	if (data && !psci_vendor_system_reset2(data))
> +		return NOTIFY_DONE;
> +
>  	if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
>  	    psci_system_reset2_supported) {
>  		/*
> @@ -795,6 +833,73 @@ static const struct of_device_id psci_of_match[] __initconst = {
>  	{},
>  };
>  
> +#define REBOOT_PREFIX "mode-"
> +
> +static int __init psci_init_system_reset2_modes(void)
> +{
> +	const size_t len = strlen(REBOOT_PREFIX);
> +	struct psci_reset_param *param;
> +	struct device_node *psci_np __free(device_node) = NULL;
> +	struct device_node *np __free(device_node) = NULL;
> +	struct property *prop;
> +	size_t count = 0;
> +	u32 magic[2];
> +	int num;
> +
> +	if (!psci_system_reset2_supported)
> +		return 0;
> +
> +	psci_np = of_find_matching_node(NULL, psci_of_match);
> +	if (!psci_np)
> +		return 0;
> +
> +	np = of_find_node_by_name(psci_np, "reset-types");
> +	if (!np)
> +		return 0;

Related to my initial question above. If LINUX_REBOOT_CMD_RESTART2 *arg command,
is the actual reset to be issued, should we add a default mode "cold"
and, if SYSTEM_RESET2 is supported, a "warm" reset mode too ?

It all boils down to what *arg represents - adding "cold" and "warm"
modes would remove the dependency on reboot_mode for resets issued
through LINUX_REBOOT_CMD_RESTART2, the question is whether this
is the correct thing to do.

Comments very welcome.

Thanks,
Lorenzo

> +
> +	for_each_property_of_node(np, prop) {
> +		if (strncmp(prop->name, REBOOT_PREFIX, len))
> +			continue;
> +		num = of_property_count_u32_elems(np, prop->name);
> +		if (num != 1 && num != 2)
> +			continue;
> +
> +		count++;
> +	}
> +
> +	param = psci_reset_params =
> +		kcalloc(count, sizeof(*psci_reset_params), GFP_KERNEL);
> +	if (!psci_reset_params)
> +		return -ENOMEM;
> +
> +	for_each_property_of_node(np, prop) {
> +		if (strncmp(prop->name, REBOOT_PREFIX, len))
> +			continue;
> +
> +		num = of_property_read_variable_u32_array(np, prop->name, magic,
> +							  1, ARRAY_SIZE(magic));
> +		if (num < 0) {
> +			pr_warn("Failed to parse vendor reboot mode %s\n",
> +				param->mode);
> +			kfree_const(param->mode);
> +			continue;
> +		}
> +
> +		param->mode = kstrdup_const(prop->name + len, GFP_KERNEL);
> +		if (!param->mode)
> +			continue;
> +
> +		/* Force reset type to be in vendor space */
> +		param->reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic[0];
> +		param->cookie = num > 1 ? magic[1] : 0;
> +		param++;
> +		num_psci_reset_params++;
> +	}
> +
> +	return 0;
> +}
> +arch_initcall(psci_init_system_reset2_modes);
> +
>  int __init psci_dt_init(void)
>  {
>  	struct device_node *np;
> 
> -- 
> 2.34.1
> 


From kevin_chen at aspeedtech.com  Fri Mar 14 04:21:10 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 19:21:10 +0800
Subject: [PATCH v4 0/3] Add AST2600 LPC PCC support
Message-ID: <20250314112113.953238-1-kevin_chen@aspeedtech.com>

--
v4
aspeed-lpc-pcc.c:
 -- Remove the debug message in the aspeed_lpc_pcc_probe.
 -- Add pcc-ports in the aspeed-g6.dtsi.

v3
aspeed-lpc-pcc.c:
 -- Add ida_free and fix the dev usage with removing some debug messages.
aspeed-lpc.yaml:
 -- Add description about the pcc-ports usage.

v2:
 -- Change driver path to drivers/misc

Kevin Chen (3):
  dt-binding: aspeed: Add LPC PCC controller
  ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
  soc: aspeed: lpc-pcc: Add PCC controller support

 .../devicetree/bindings/mfd/aspeed-lpc.yaml   |  38 ++
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi       |   8 +
 drivers/misc/Kconfig                          |  10 +
 drivers/misc/Makefile                         |   1 +
 drivers/misc/aspeed-lpc-pcc.c                 | 437 ++++++++++++++++++
 5 files changed, 494 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

-- 
2.34.1



From kevin_chen at aspeedtech.com  Fri Mar 14 04:21:11 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 19:21:11 +0800
Subject: [PATCH v4 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
Message-ID: <20250314112113.953238-2-kevin_chen@aspeedtech.com>

Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
index 5dfe77aca167..178c151a19ba 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
@@ -149,6 +149,37 @@ patternProperties:
       - interrupts
       - snoop-ports
 
+  "^lpc-pcc@[0-9a-f]+$":
+    type: object
+    additionalProperties: false
+
+    description:
+      The LPC pcc interface allows the BMC to listen on and record the data
+      bytes written by the Host to the targeted LPC I/O pots.
+
+    properties:
+      compatible:
+        items:
+          - enum:
+              - aspeed,ast2600-lpc-pcc
+
+      reg:
+        maxItems: 1
+
+      interrupts:
+        maxItems: 1
+
+      pcc-ports:
+        $ref: /schemas/types.yaml#/definitions/uint32-array
+        description:
+          As a device handshake with a host using the port-mmaped I/O in x86
+          architecture, need to handle specific which port I/O address for use.
+
+    required:
+      - compatible
+      - interrupts
+      - pcc-ports
+
   "^uart-routing@[0-9a-f]+$":
     $ref: /schemas/soc/aspeed/uart-routing.yaml#
     description: The UART routing control under LPC register space
@@ -176,6 +207,13 @@ examples:
         #size-cells = <1>;
         ranges = <0x0 0x1e789000 0x1000>;
 
+        lpc_pcc: lpc-pcc at 0 {
+            compatible = "aspeed,ast2600-lpc-pcc";
+            reg = <0x0 0x140>;
+            interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+            pcc-ports = <0x80>;
+        };
+
         lpc_ctrl: lpc-ctrl at 80 {
             compatible = "aspeed,ast2600-lpc-ctrl";
             reg = <0x80 0x80>;
-- 
2.34.1



From kevin_chen at aspeedtech.com  Fri Mar 14 04:21:12 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 19:21:12 +0800
Subject: [PATCH v4 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
Message-ID: <20250314112113.953238-3-kevin_chen@aspeedtech.com>

The AST2600 has PCC controller in LPC, placed in LPC node.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 8ed715bd53aa..f238337e02da 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -626,6 +626,14 @@ lpc_snoop: lpc-snoop at 80 {
 					status = "disabled";
 				};
 
+				lpc_pcc: lpc-pcc at 0 {
+					compatible = "aspeed,ast2600-lpc-pcc";
+					reg = <0x0 0x140>;
+					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+					pcc-ports = <0x80>;
+					status = "disabled";
+				};
+
 				lhc: lhc at a0 {
 					compatible = "aspeed,ast2600-lhc";
 					reg = <0xa0 0x24 0xc8 0x8>;
-- 
2.34.1



From kevin_chen at aspeedtech.com  Fri Mar 14 04:21:13 2025
From: kevin_chen at aspeedtech.com (Kevin Chen)
Date: Fri, 14 Mar 2025 19:21:13 +0800
Subject: [PATCH v4 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
Message-ID: <20250314112113.953238-4-kevin_chen@aspeedtech.com>

Add LPC PCC controller driver to support POST code capture.

Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
---
 drivers/misc/Kconfig          |  10 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/aspeed-lpc-pcc.c | 437 ++++++++++++++++++++++++++++++++++
 3 files changed, 448 insertions(+)
 create mode 100644 drivers/misc/aspeed-lpc-pcc.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 56bc72c7ce4a..35c1d2e0c271 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -50,6 +50,16 @@ config AD525X_DPOT_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
+config ASPEED_LPC_PCC
+	tristate "Aspeed Post Code Capture support"
+	select REGMAP
+	select MFD_SYSCON
+	default ARCH_ASPEED
+	help
+	  Provides a driver to control the LPC PCC interface,
+	  allowing the BMC to capture post code written by the
+	  the host to an arbitrary LPC I/O port.
+
 config DUMMY_IRQ
 	tristate "Dummy IRQ handler"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 545aad06d088..4762da7804bf 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_IBMVMC)		+= ibmvmc.o
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
+obj-$(CONFIG_ASPEED_LPC_PCC)	+= aspeed-lpc-pcc.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
diff --git a/drivers/misc/aspeed-lpc-pcc.c b/drivers/misc/aspeed-lpc-pcc.c
new file mode 100644
index 000000000000..61c76cb176bc
--- /dev/null
+++ b/drivers/misc/aspeed-lpc-pcc.c
@@ -0,0 +1,437 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/kfifo.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regmap.h>
+#include <linux/dma-mapping.h>
+#include <linux/sizes.h>
+
+#define DEVICE_NAME "aspeed-lpc-pcc"
+
+static DEFINE_IDA(aspeed_pcc_ida);
+
+#define HICR5	0x80
+#define HICR5_EN_SNP0W			BIT(0)
+#define HICR5_EN_SNP1W			BIT(2)
+#define HICR6	0x084
+#define   HICR6_EN2BMODE		BIT(19)
+#define SNPWADR	0x090
+#define PCCR6	0x0c4
+#define   PCCR6_DMA_CUR_ADDR		GENMASK(27, 0)
+#define PCCR4	0x0d0
+#define   PCCR4_DMA_ADDRL_MASK		GENMASK(31, 0)
+#define   PCCR4_DMA_ADDRL_SHIFT		0
+#define PCCR5	0x0d4
+#define   PCCR5_DMA_ADDRH_MASK		GENMASK(27, 24)
+#define   PCCR5_DMA_ADDRH_SHIFT		24
+#define   PCCR5_DMA_LEN_MASK		GENMASK(23, 0)
+#define   PCCR5_DMA_LEN_SHIFT		0
+#define HICRB	0x100
+#define   HICRB_ENSNP0D			BIT(14)
+#define   HICRB_ENSNP1D			BIT(15)
+#define PCCR0	0x130
+#define   PCCR0_EN_DMA_INT		BIT(31)
+#define   PCCR0_EN_DMA_MODE		BIT(14)
+#define   PCCR0_ADDR_SEL_MASK		GENMASK(13, 12)
+#define   PCCR0_ADDR_SEL_SHIFT		12
+#define   PCCR0_RX_TRIG_LVL_MASK	GENMASK(10, 8)
+#define   PCCR0_RX_TRIG_LVL_SHIFT	8
+#define   PCCR0_CLR_RX_FIFO		BIT(7)
+#define   PCCR0_MODE_SEL_MASK		GENMASK(5, 4)
+#define   PCCR0_MODE_SEL_SHIFT		4
+#define   PCCR0_EN_RX_TMOUT_INT		BIT(2)
+#define   PCCR0_EN_RX_AVAIL_INT		BIT(1)
+#define   PCCR0_EN			BIT(0)
+#define PCCR1	0x134
+#define   PCCR1_BASE_ADDR_MASK		GENMASK(15, 0)
+#define   PCCR1_BASE_ADDR_SHIFT		0
+#define   PCCR1_DONT_CARE_BITS_MASK	GENMASK(21, 16)
+#define   PCCR1_DONT_CARE_BITS_SHIFT	16
+#define PCCR2	0x138
+#define   PCCR2_INT_STATUS_PATTERN_B	BIT(16)
+#define   PCCR2_INT_STATUS_PATTERN_A	BIT(8)
+#define   PCCR2_INT_STATUS_DMA_DONE	BIT(4)
+#define   PCCR2_INT_STATUS_DATA_RDY	PCCR2_INT_STATUS_DMA_DONE
+#define   PCCR2_INT_STATUS_RX_OVER	BIT(3)
+#define   PCCR2_INT_STATUS_RX_TMOUT	BIT(2)
+#define   PCCR2_INT_STATUS_RX_AVAIL	BIT(1)
+#define PCCR3	0x13c
+#define   PCCR3_FIFO_DATA_MASK		GENMASK(7, 0)
+
+#define PCC_DMA_BUFSZ	(256 * SZ_1K)
+
+enum pcc_fifo_threshold {
+	PCC_FIFO_THR_1_BYTE,
+	PCC_FIFO_THR_1_EIGHTH,
+	PCC_FIFO_THR_2_EIGHTH,
+	PCC_FIFO_THR_3_EIGHTH,
+	PCC_FIFO_THR_4_EIGHTH,
+	PCC_FIFO_THR_5_EIGHTH,
+	PCC_FIFO_THR_6_EIGHTH,
+	PCC_FIFO_THR_7_EIGHTH,
+	PCC_FIFO_THR_8_EIGHTH,
+};
+
+enum pcc_record_mode {
+	PCC_REC_1B,
+	PCC_REC_2B,
+	PCC_REC_4B,
+	PCC_REC_FULL,
+};
+
+enum pcc_port_hbits_select {
+	PCC_PORT_HBITS_SEL_NONE,
+	PCC_PORT_HBITS_SEL_45,
+	PCC_PORT_HBITS_SEL_67,
+	PCC_PORT_HBITS_SEL_89,
+};
+
+struct aspeed_pcc_dma {
+	uint32_t rptr;
+	uint8_t *virt;
+	dma_addr_t addr;
+	uint32_t size;
+};
+
+struct aspeed_pcc_ctrl {
+	struct device *dev;
+	struct regmap *regmap;
+	int irq;
+	uint32_t port;
+	struct aspeed_pcc_dma dma;
+	struct kfifo fifo;
+	wait_queue_head_t wq;
+	struct miscdevice mdev;
+	int mdev_id;
+};
+
+static inline bool is_valid_rec_mode(uint32_t mode)
+{
+	return (mode > PCC_REC_FULL) ? false : true;
+}
+
+static inline bool is_valid_high_bits_select(uint32_t sel)
+{
+	return (sel > PCC_PORT_HBITS_SEL_89) ? false : true;
+}
+
+static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	int rc;
+	unsigned int copied;
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	if (kfifo_is_empty(&pcc->fifo)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		rc = wait_event_interruptible(pcc->wq,
+					      !kfifo_is_empty(&pcc->fifo));
+		if (rc == -ERESTARTSYS)
+			return -EINTR;
+	}
+
+	rc = kfifo_to_user(&pcc->fifo, buffer, count, &copied);
+
+	return rc ? rc : copied;
+}
+
+static __poll_t aspeed_pcc_file_poll(struct file *file,
+				     struct poll_table_struct *pt)
+{
+	struct aspeed_pcc_ctrl *pcc = container_of(file->private_data,
+					      struct aspeed_pcc_ctrl,
+					      mdev);
+
+	poll_wait(file, &pcc->wq, pt);
+
+	return !kfifo_is_empty(&pcc->fifo) ? POLLIN : 0;
+}
+
+static const struct file_operations pcc_fops = {
+	.owner = THIS_MODULE,
+	.read = aspeed_pcc_file_read,
+	.poll = aspeed_pcc_file_poll,
+};
+
+static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg)
+{
+	uint32_t reg, rptr, wptr;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+	struct kfifo *fifo = &pcc->fifo;
+
+	regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_INT_STATUS_DMA_DONE);
+
+	regmap_read(pcc->regmap, PCCR6, &reg);
+	wptr = (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR);
+	rptr = pcc->dma.rptr;
+
+	do {
+		if (kfifo_is_full(fifo))
+			kfifo_skip(fifo);
+
+		kfifo_put(fifo, pcc->dma.virt[rptr]);
+
+		rptr = (rptr + 1) % pcc->dma.size;
+	} while (rptr != wptr);
+
+	pcc->dma.rptr = rptr;
+
+	wake_up_interruptible(&pcc->wq);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t aspeed_pcc_isr(int irq, void *arg)
+{
+	uint32_t sts;
+	struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg;
+
+	regmap_read(pcc->regmap, PCCR2, &sts);
+
+	if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT |
+		     PCCR2_INT_STATUS_RX_AVAIL |
+		     PCCR2_INT_STATUS_DMA_DONE)))
+		return IRQ_NONE;
+
+	return aspeed_pcc_dma_isr(irq, arg);
+}
+
+/*
+ * A2600-15 AP note
+ *
+ * SW workaround to prevent generating Non-Fatal-Error (NFE)
+ * eSPI response when PCC is used for port I/O byte snooping
+ * over eSPI.
+ */
+static int aspeed_a2600_15(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	u32 hicr5_en, hicrb_en;
+
+	/* abort if snoop is enabled */
+	regmap_read(pcc->regmap, HICR5, &hicr5_en);
+	if (hicr5_en & (HICR5_EN_SNP0W | HICR5_EN_SNP1W)) {
+		dev_err(dev, "A2600-15 should be applied with snoop disabled\n");
+		return -EPERM;
+	}
+
+	/* set SNPWADR of snoop device */
+	regmap_write(pcc->regmap, SNPWADR, pcc->port | ((pcc->port + 2) << 16));
+
+	/* set HICRB[15:14]=11b to enable ACCEPT response for SNPWADR */
+	hicrb_en = HICRB_ENSNP0D | HICRB_ENSNP1D;
+	regmap_update_bits(pcc->regmap, HICRB, hicrb_en, hicrb_en);
+
+	/* set HICR6[19] to extend SNPWADR to 2x range */
+	regmap_update_bits(pcc->regmap, HICR6, HICR6_EN2BMODE, HICR6_EN2BMODE);
+
+	return 0;
+}
+
+static int aspeed_pcc_enable(struct aspeed_pcc_ctrl *pcc, struct device *dev)
+{
+	int rc;
+
+	rc = aspeed_a2600_15(pcc, dev);
+	if (rc)
+		return rc;
+
+	/* record mode: Set 2-Byte mode. */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_MODE_SEL_MASK,
+			   PCC_REC_2B << PCCR0_MODE_SEL_SHIFT);
+
+	/* port address */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_BASE_ADDR_MASK,
+			   pcc->port << PCCR1_BASE_ADDR_SHIFT);
+
+	/* Set address high bits selection to 0b01 for address bit[5:4] */
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_ADDR_SEL_MASK,
+			   PCC_PORT_HBITS_SEL_45 << PCCR0_ADDR_SEL_SHIFT);
+
+	/* Set LPC don't care address to 0x3 for port 80~83h */
+	regmap_update_bits(pcc->regmap, PCCR1,
+			   PCCR1_DONT_CARE_BITS_MASK,
+			   0x3 << PCCR1_DONT_CARE_BITS_SHIFT);
+
+	/* set DMA ring buffer size and enable interrupts */
+	regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff);
+#ifdef CONFIG_ARM64
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK,
+			   (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT);
+#endif
+	regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK,
+			   (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT);
+	regmap_update_bits(pcc->regmap, PCCR0,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE,
+			   PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE);
+
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN, PCCR0_EN);
+
+	return 0;
+}
+
+static int aspeed_pcc_disable(struct aspeed_pcc_ctrl *pcc)
+{
+	/* Disable PCC and DMA Mode for safety */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN |  PCCR0_EN_DMA_MODE, 0);
+
+	/* Clear Rx FIFO. */
+	regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1);
+
+	/* Clear All interrupts status. */
+	regmap_write(pcc->regmap, PCCR2,
+		     PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE |
+		     PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B);
+
+	return 0;
+}
+
+static int aspeed_pcc_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct aspeed_pcc_ctrl *pcc;
+	struct device *dev = &pdev->dev;
+	uint32_t fifo_size = PAGE_SIZE;
+
+	pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL);
+	if (!pcc)
+		return -ENOMEM;
+
+	pcc->regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(pcc->regmap))
+		return dev_err_probe(dev, PTR_ERR(pcc->regmap), "Couldn't get regmap\n");
+
+	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
+	if (rc) {
+		dev_err(dev, "no pcc ports configured\n");
+		return rc;
+	}
+
+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+	if (rc) {
+		dev_err(dev, "cannot set 64-bits DMA mask\n");
+		return rc;
+	}
+
+	pcc->dma.size = PCC_DMA_BUFSZ;
+	pcc->dma.virt = dmam_alloc_coherent(dev,
+					    pcc->dma.size,
+					    &pcc->dma.addr,
+					    GFP_KERNEL);
+	if (!pcc->dma.virt) {
+		dev_err(dev, "cannot allocate DMA buffer\n");
+		return -ENOMEM;
+	}
+
+	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
+	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
+	if (rc)
+		return rc;
+
+	/* Disable PCC to clean up DMA buffer before request IRQ. */
+	rc = aspeed_pcc_disable(pcc);
+	if (rc) {
+		dev_err(dev, "Couldn't disable PCC\n");
+		goto err_free_kfifo;
+	}
+
+	pcc->irq = platform_get_irq(pdev, 0);
+	if (pcc->irq < 0) {
+		rc = pcc->irq;
+		goto err_free_kfifo;
+	}
+
+	rc = devm_request_irq(dev, pcc->irq, aspeed_pcc_isr, 0, DEVICE_NAME, pcc);
+	if (rc < 0) {
+		dev_err(dev, "Couldn't request IRQ %d\n", pcc->irq);
+		goto err_free_kfifo;
+	}
+
+	init_waitqueue_head(&pcc->wq);
+
+	pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL);
+	if (pcc->mdev_id < 0) {
+		dev_err(dev, "Couldn't allocate ID\n");
+		goto err_free_kfifo;
+	}
+
+	pcc->mdev.parent = dev;
+	pcc->mdev.minor = MISC_DYNAMIC_MINOR;
+	pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME,
+					pcc->mdev_id);
+	pcc->mdev.fops = &pcc_fops;
+	rc = misc_register(&pcc->mdev);
+	if (rc) {
+		dev_err(dev, "Couldn't register misc device\n");
+		goto err_free_ida;
+	}
+
+	rc = aspeed_pcc_enable(pcc, dev);
+	if (rc) {
+		dev_err(dev, "Couldn't enable PCC\n");
+		goto err_dereg_mdev;
+	}
+
+	dev_set_drvdata(dev, pcc);
+
+	return 0;
+
+err_dereg_mdev:
+	misc_deregister(&pcc->mdev);
+
+err_free_ida:
+	ida_free(&aspeed_pcc_ida, pcc->mdev_id);
+
+err_free_kfifo:
+	kfifo_free(&pcc->fifo);
+
+	return rc;
+}
+
+static void aspeed_pcc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev);
+
+	kfifo_free(&pcc->fifo);
+	ida_free(&aspeed_pcc_ida, pcc->mdev_id);
+	misc_deregister(&pcc->mdev);
+}
+
+static const struct of_device_id aspeed_pcc_table[] = {
+	{ .compatible = "aspeed,ast2600-lpc-pcc" },
+};
+
+static struct platform_driver aspeed_pcc_driver = {
+	.driver = {
+		.name = "aspeed-pcc",
+		.of_match_table = aspeed_pcc_table,
+	},
+	.probe = aspeed_pcc_probe,
+	.remove = aspeed_pcc_remove,
+};
+
+module_platform_driver(aspeed_pcc_driver);
+
+MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang at aspeedtech.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Aspeed Post Code Capture");
-- 
2.34.1



From maz at kernel.org  Fri Mar 14 04:31:36 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 14 Mar 2025 11:31:36 +0000
Subject: [PATCH 4/6] KVM: arm64: Move hyp state to hyp_vmemmap
In-Reply-To: <20250227003310.367350-5-qperret@google.com>
References: <20250227003310.367350-1-qperret@google.com>
	<20250227003310.367350-5-qperret@google.com>
Message-ID: <86bju3onl3.wl-maz@kernel.org>

On Thu, 27 Feb 2025 00:33:08 +0000,
Quentin Perret <qperret at google.com> wrote:
> 
> Tracking the hypervisor's ownership state into struct hyp_page has
> several benefits, including allowing far more efficient lookups (no
> page-table walk needed) and de-corelating the state from the presence
> of a mapping. This will later allow to map pages into EL2 stage-1 less
> proactively which is generally a good thing for security. And in the
> future this will help with tracking the state of pages mapped into the
> hypervisor's private range without requiring an alias into the 'linear
> map' range.
> 
> Signed-off-by: Quentin Perret <qperret at google.com>
> ---
>  arch/arm64/kvm/hyp/include/nvhe/memory.h | 20 +++++++++-
>  arch/arm64/kvm/hyp/nvhe/mem_protect.c    | 51 ++++++++++++------------
>  arch/arm64/kvm/hyp/nvhe/setup.c          |  6 ++-
>  3 files changed, 49 insertions(+), 28 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> index 4a3c55d26ef3..cc4c01158368 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> @@ -22,6 +22,7 @@ enum pkvm_page_state {
>  	/* Meta-states which aren't encoded directly in the PTE's SW bits */
>  	PKVM_NOPAGE			= BIT(0) | BIT(1),
>  };
> +#define PKVM_PAGE_STATE_MASK		(BIT(0) | BIT(1))
>  
>  #define PKVM_PAGE_STATE_PROT_MASK	(KVM_PGTABLE_PROT_SW0 | KVM_PGTABLE_PROT_SW1)
>  static inline enum kvm_pgtable_prot pkvm_mkstate(enum kvm_pgtable_prot prot,
> @@ -42,7 +43,14 @@ struct hyp_page {
>  	u8 order;
>  
>  	/* Host (non-meta) state. Guarded by the host stage-2 lock. */
> -	unsigned __host_state : 8;
> +	unsigned __host_state : 4;
> +
> +	/*
> +	 * Complement of the hyp (non-meta) state. Guarded by the hyp stage-1 lock. We use the
> +	 * complement so that the initial 0 in __hyp_state_comp (due to the entire vmemmap starting
> +	 * off zeroed) encodes PKVM_NOPAGE.
> +	 */
> +	unsigned __hyp_state_comp : 4;
>  
>  	u32 host_share_guest_count;
>  };
> @@ -89,6 +97,16 @@ static inline void set_host_state(phys_addr_t phys, enum pkvm_page_state state)
>  	hyp_phys_to_page(phys)->__host_state = state;
>  }
>  
> +static inline enum pkvm_page_state get_hyp_state(phys_addr_t phys)
> +{
> +	return hyp_phys_to_page(phys)->__hyp_state_comp ^ PKVM_PAGE_STATE_MASK;
> +}
> +
> +static inline void set_hyp_state(phys_addr_t phys, enum pkvm_page_state state)
> +{
> +	hyp_phys_to_page(phys)->__hyp_state_comp = state ^ PKVM_PAGE_STATE_MASK;
> +}
> +
>  /*
>   * Refcounting for 'struct hyp_page'.
>   * hyp_pool::lock must be held if atomic access to the refcount is required.
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index a45ffdec7612..3ab8c81500c2 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -642,24 +642,24 @@ static int __host_set_page_state_range(u64 addr, u64 size,
>  	return 0;
>  }
>  
> -static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte, u64 addr)
> +static void __hyp_set_page_state_range(phys_addr_t phys, u64 size, enum pkvm_page_state state)
>  {
> -	if (!kvm_pte_valid(pte))
> -		return PKVM_NOPAGE;
> +	phys_addr_t end = phys + size;
>  
> -	return pkvm_getstate(kvm_pgtable_hyp_pte_prot(pte));
> +	for (; phys < end; phys += PAGE_SIZE)
> +		set_hyp_state(phys, state);
>  }
>  
> -static int __hyp_check_page_state_range(u64 addr, u64 size,
> -					enum pkvm_page_state state)
> +static int __hyp_check_page_state_range(phys_addr_t phys, u64 size, enum pkvm_page_state state)
>  {
> -	struct check_walk_data d = {
> -		.desired	= state,
> -		.get_page_state	= hyp_get_page_state,
> -	};
> +	phys_addr_t end = phys + size;
> +
> +	for (; phys < end; phys += PAGE_SIZE) {
> +		if (get_hyp_state(phys) != state)
> +			return -EPERM;
> +	}
>  
> -	hyp_assert_lock_held(&pkvm_pgd_lock);
> -	return check_page_state_range(&pkvm_pgtable, addr, size, &d);
> +	return 0;
>  }
>  
>  static enum pkvm_page_state guest_get_page_state(kvm_pte_t pte, u64 addr)
> @@ -687,7 +687,6 @@ int __pkvm_host_share_hyp(u64 pfn)
>  {
>  	u64 phys = hyp_pfn_to_phys(pfn);
>  	void *virt = __hyp_va(phys);
> -	enum kvm_pgtable_prot prot;
>  	u64 size = PAGE_SIZE;
>  	int ret;
>  
> @@ -698,13 +697,13 @@ int __pkvm_host_share_hyp(u64 pfn)
>  	if (ret)
>  		goto unlock;
>  	if (IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) {
> -		ret = __hyp_check_page_state_range((u64)virt, size, PKVM_NOPAGE);
> +		ret = __hyp_check_page_state_range(phys, size, PKVM_NOPAGE);

OK, I think I finally clicked here. Does it mean that all the tracking
is now done in terms of PAs instead of VAs?

>  		if (ret)
>  			goto unlock;
>  	}
>  
> -	prot = pkvm_mkstate(PAGE_HYP, PKVM_PAGE_SHARED_BORROWED);
> -	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, prot));
> +	__hyp_set_page_state_range(phys, size, PKVM_PAGE_SHARED_BORROWED);
> +	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, PAGE_HYP));

And this is the split between the state now being kept in the on a PA
base and the actual mapping that is now only takes the page attributes
and no SW bits?

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From will at kernel.org  Fri Mar 14 04:31:38 2025
From: will at kernel.org (Will Deacon)
Date: Fri, 14 Mar 2025 11:31:38 +0000
Subject: [PATCH v2 2/4] arm64/sysreg: Enforce whole word match for
 open/close tokens
In-Reply-To: <36968527640d231882444ba7065317fe@kernel.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-3-james.clark@linaro.org>
 <20250313215622.GA8101@willie-the-truck>
 <36968527640d231882444ba7065317fe@kernel.org>
Message-ID: <20250314113137.GA8865@willie-the-truck>

On Fri, Mar 14, 2025 at 07:40:36AM +0000, Marc Zyngier wrote:
> On 2025-03-13 21:56, Will Deacon wrote:
> > On Wed, Jan 15, 2025 at 04:25:56PM +0000, James Clark wrote:
> > > Opening and closing tokens can also match on words with common
> > > prefixes
> > > like "Endsysreg" vs "EndsysregFields". This could potentially make the
> > > script go wrong in weird ways so make it fall through to the fatal
> > > unhandled statement catcher if it doesn't fully match the current
> > > block.
> > > 
> > > Closing ones also get expect_fields(1) to ensure nothing other than
> > > whitespace follows.
> > > 
> > > Signed-off-by: James Clark <james.clark at linaro.org>
> > > ---
> > >  arch/arm64/tools/gen-sysreg.awk | 31 +++++++++++++++++--------------
> > >  1 file changed, 17 insertions(+), 14 deletions(-)
> > > 
> > > diff --git a/arch/arm64/tools/gen-sysreg.awk
> > > b/arch/arm64/tools/gen-sysreg.awk
> > > index 1a2afc9fdd42..f2a1732cb1f6 100755
> > > --- a/arch/arm64/tools/gen-sysreg.awk
> > > +++ b/arch/arm64/tools/gen-sysreg.awk
> > > @@ -111,7 +111,7 @@ END {
> > >  /^$/ { next }
> > >  /^[\t ]*#/ { next }
> > > 
> > > -/^SysregFields/ && block_current() == "Root" {
> > > +$1 == "SysregFields" && block_current() == "Root" {
> > 
> > Stylistic nit, but could you just do:
> > 
> > 	/^SysregFields$/ && block_current() == "Root" {
> > 
> > instead? That way the diff is smaller (well, same number of lines) and
> > you avoid the ugly $1.
> 
> The code is trying to match the first field of a line such as:
> 
> SysregFields	ZCR_ELx
> 
> while you seem to try and match a SysregFields all alone on a line.
> 
> That being said, my perl-foo is sub-zero, so I may be very wrong myself.


Ah, and this is *awk* so $1 is the first field.

So my suggestion is totally broken and the original patch looks correct:

Acked-by: Will Deacon <will at kernel.org>

Will


From vladimir.oltean at nxp.com  Fri Mar 14 04:18:01 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Fri, 14 Mar 2025 13:18:01 +0200
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring
 support for i.MX95 ENETC
In-Reply-To: <PAXPR04MB8510D3A2F2A792A89941A7FD88D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250313164908.rdy3y77xno3fza3l@skbuf>
 <PAXPR04MB8510D3A2F2A792A89941A7FD88D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250314111801.2oela3qoi5qrl6el@skbuf>

On Fri, Mar 14, 2025 at 06:51:06AM +0200, Wei Fang wrote:
> > I don't understand the need for si->ops->setup_cbdr() and
> > si->ops->teardown_cbdr()?
> > Doesn't every call site know which kind of SI it is dealing with, and thus it can
> > appropriately call the direct symbol?
> > - the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
> > - the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()
> 
> Yes, for PSI we can use directly call these functions because they are different
> drivers, but for VSI, v1 and v4 will use the same driver. I just want the PSI and
> VSI to be consistent. If you don't like this, I can remove these interfaces from
> the patch set, and add vf_setup_cbdr and vf_teardown_cbdr in the future when
> I add the VF support for ENETC v4.

It's not that I don't like them, the point is rather simple: as far as
this patch set is concerned, converting direct function calls to
indirect ones is an unfinished idea. It needs to be evaluated in full
context, which is not present here - as you say, v4 VSIs need to be
further modified to call a different set of operations - but right now,
they call a single set of CBDR functions. Changes which require
subsequent patch sets in order to make any sense at all are discouraged.

Given the fact that the PSI code paths still don't benefit from an
indirect function call in any way, I would in principle recommend to
keep calling their CBDR methods directly. For VSIs I don't know which is
preferable (if-else vs function pointer), I need to see that code first.


From tabba at google.com  Fri Mar 14 04:18:28 2025
From: tabba at google.com (Fuad Tabba)
Date: Fri, 14 Mar 2025 11:18:28 +0000
Subject: [PATCH v3 0/4] KVM: arm64: Fix initializing HCRX_EL2 and other traps
 in pKVM
Message-ID: <20250314111832.4137161-1-tabba@google.com>

Changes since v2 [1]:
- Remove WRITE_ONCE when setting hyp handle (Quentin)
- Rebase on Linux 6.14-rc6

For context, please refer to v1 [2].

Cheers,
/fuad

[1] https://lore.kernel.org/all/20250226215520.1759218-1-tabba at google.com
[2] https://lore.kernel.org/all/20250214150258.464798-1-tabba at google.com/

Fuad Tabba (4):
  KVM: arm64: Factor out setting HCRX_EL2 traps into separate function
  KVM: arm64: Initialize HCRX_EL2 traps in pKVM
  KVM: arm64: Factor out pKVM hyp vcpu creation to separate function
  KVM: arm64: Create each pKVM hyp vcpu after its corresponding host
    vcpu

 arch/arm64/include/asm/kvm_emulate.h   | 24 +++++++++
 arch/arm64/include/asm/kvm_host.h      |  2 +
 arch/arm64/include/asm/kvm_pkvm.h      |  1 +
 arch/arm64/kvm/arm.c                   |  4 ++
 arch/arm64/kvm/hyp/include/nvhe/pkvm.h |  6 ---
 arch/arm64/kvm/hyp/nvhe/pkvm.c         | 62 ++++++++++++++---------
 arch/arm64/kvm/pkvm.c                  | 70 +++++++++++++-------------
 arch/arm64/kvm/sys_regs.c              | 20 +-------
 8 files changed, 104 insertions(+), 85 deletions(-)


base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
-- 
2.49.0.rc1.451.g8f38331e32-goog



From tabba at google.com  Fri Mar 14 04:18:29 2025
From: tabba at google.com (Fuad Tabba)
Date: Fri, 14 Mar 2025 11:18:29 +0000
Subject: [PATCH v3 1/4] KVM: arm64: Factor out setting HCRX_EL2 traps into
 separate function
In-Reply-To: <20250314111832.4137161-1-tabba@google.com>
References: <20250314111832.4137161-1-tabba@google.com>
Message-ID: <20250314111832.4137161-2-tabba@google.com>

Factor out the code for setting a vcpu's HCRX_EL2 traps in to a
separate inline function. This allows us to share the logic with
pKVM when setting the traps in protected mode.

No functional change intended.

Reviewed-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Fuad Tabba <tabba at google.com>
---
 arch/arm64/include/asm/kvm_emulate.h | 24 ++++++++++++++++++++++++
 arch/arm64/kvm/sys_regs.c            | 20 +-------------------
 2 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 78ec1ef2cfe8..31c8497372d0 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -649,4 +649,28 @@ static inline bool guest_hyp_sve_traps_enabled(const struct kvm_vcpu *vcpu)
 {
 	return __guest_hyp_cptr_xen_trap_enabled(vcpu, ZEN);
 }
+
+static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+
+	if (cpus_have_final_cap(ARM64_HAS_HCX)) {
+		/*
+		 * In general, all HCRX_EL2 bits are gated by a feature.
+		 * The only reason we can set SMPME without checking any
+		 * feature is that its effects are not directly observable
+		 * from the guest.
+		 */
+		vcpu->arch.hcrx_el2 = HCRX_EL2_SMPME;
+
+		if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
+			vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
+
+		if (kvm_has_tcr2(kvm))
+			vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
+
+		if (kvm_has_fpmr(kvm))
+			vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM;
+	}
+}
 #endif /* __ARM64_KVM_EMULATE_H__ */
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 82430c1e1dd0..16ce5f584e7c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -4971,25 +4971,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
 	mutex_lock(&kvm->arch.config_lock);
 	vcpu_set_hcr(vcpu);
 	vcpu_set_ich_hcr(vcpu);
-
-	if (cpus_have_final_cap(ARM64_HAS_HCX)) {
-		/*
-		 * In general, all HCRX_EL2 bits are gated by a feature.
-		 * The only reason we can set SMPME without checking any
-		 * feature is that its effects are not directly observable
-		 * from the guest.
-		 */
-		vcpu->arch.hcrx_el2 = HCRX_EL2_SMPME;
-
-		if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
-			vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
-
-		if (kvm_has_tcr2(kvm))
-			vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
-
-		if (kvm_has_fpmr(kvm))
-			vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM;
-	}
+	vcpu_set_hcrx(vcpu);
 
 	if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
 		goto out;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From tabba at google.com  Fri Mar 14 04:18:30 2025
From: tabba at google.com (Fuad Tabba)
Date: Fri, 14 Mar 2025 11:18:30 +0000
Subject: [PATCH v3 2/4] KVM: arm64: Initialize HCRX_EL2 traps in pKVM
In-Reply-To: <20250314111832.4137161-1-tabba@google.com>
References: <20250314111832.4137161-1-tabba@google.com>
Message-ID: <20250314111832.4137161-3-tabba@google.com>

Initialize and set the traps controlled by the HCRX_EL2 in pKVM.

Reviewed-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Fuad Tabba <tabba at google.com>
---
 arch/arm64/kvm/hyp/nvhe/pkvm.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 3927fe52a3dd..6efb9bf56180 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -166,8 +166,13 @@ static int pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu)
 
 	pkvm_vcpu_reset_hcr(vcpu);
 
-	if ((!pkvm_hyp_vcpu_is_protected(hyp_vcpu)))
+	if ((!pkvm_hyp_vcpu_is_protected(hyp_vcpu))) {
+		struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
+
+		/* Trust the host for non-protected vcpu features. */
+		vcpu->arch.hcrx_el2 = host_vcpu->arch.hcrx_el2;
 		return 0;
+	}
 
 	ret = pkvm_check_pvm_cpu_features(vcpu);
 	if (ret)
@@ -175,6 +180,7 @@ static int pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu)
 
 	pvm_init_traps_hcr(vcpu);
 	pvm_init_traps_mdcr(vcpu);
+	vcpu_set_hcrx(vcpu);
 
 	return 0;
 }
-- 
2.49.0.rc1.451.g8f38331e32-goog



From lee at kernel.org  Fri Mar 14 04:35:51 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 14 Mar 2025 11:35:51 +0000
Subject: [net-next PATCH v12 09/13] mfd: an8855: Add support for Airoha
 AN8855 Switch MFD
In-Reply-To: <20250309172717.9067-10-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-10-ansuelsmth@gmail.com>
Message-ID: <20250314113551.GK3890718@google.com>

On Sun, 09 Mar 2025, Christian Marangi wrote:

> Add support for Airoha AN8855 Switch MFD that provide support for a DSA

Drop all references to MFD.

It doesn't exist.  It is a figment of your (and my) imagination.

> switch and a NVMEM provider. Also provide support for a virtual MDIO
> passthrough as the PHYs address for the switch are shared with the switch
> address.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  MAINTAINERS                 |   1 +
>  drivers/mfd/Kconfig         |  10 +
>  drivers/mfd/Makefile        |   1 +
>  drivers/mfd/airoha-an8855.c | 445 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 457 insertions(+)
>  create mode 100644 drivers/mfd/airoha-an8855.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b7075425c94e..5844addbda2b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -730,6 +730,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
>  F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
>  F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
>  F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
> +F:	drivers/mfd/airoha-an8855.c
>  
>  AIROHA ETHERNET DRIVER
>  M:	Lorenzo Bianconi <lorenzo at kernel.org>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6b0682af6e32..1b5abe5e2694 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -53,6 +53,16 @@ config MFD_ALTERA_SYSMGR
>  	  using regmap_mmio accesses for ARM32 parts and SMC calls to
>  	  EL3 for ARM64 parts.
>  
> +config MFD_AIROHA_AN8855

Should this be EN?


> +	tristate "Airoha AN8855 Switch MFD"
> +	select MFD_CORE
> +	select MDIO_DEVICE
> +	depends on NETDEVICES && OF
> +	help
> +	  Support for the Airoha AN8855 Switch MFD. This is a SoC Switch

Nit: "an SoC".

What kind of switch?

> +	  that provides various peripherals. Currently it provides a

Which other peripherals?

> +	  DSA switch and a NVMEM provider.
> +
>  config MFD_ACT8945A
>  	tristate "Active-semi ACT8945A"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 9220eaf7cf12..37677f65a981 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
>  obj-$(CONFIG_MFD_88PM800)	+= 88pm800.o 88pm80x.o
>  obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
>  obj-$(CONFIG_MFD_88PM886_PMIC)	+= 88pm886.o
> +obj-$(CONFIG_MFD_AIROHA_AN8855)	+= airoha-an8855.o
>  obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
>  obj-$(CONFIG_MFD_SM501)		+= sm501.o
>  obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835-pm.o
> diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
> new file mode 100644
> index 000000000000..0a6440bd4118
> --- /dev/null
> +++ b/drivers/mfd/airoha-an8855.c
> @@ -0,0 +1,445 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * MFD driver for Airoha AN8855 Switch

No such thing as an MFD driver.

Core is sometimes used in place of a better name.

> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mdio.h>
> +#include <linux/mdio/mdio-regmap.h>
> +#include <linux/module.h>
> +#include <linux/phy.h>
> +#include <linux/regmap.h>
> +
> +/* Register for hw trap status */

Ironically, this is probably the most readable name, yet it is the only
one graced with a comment.  Also 'hw' is an abbreviation, so it should be
HW or H/W or better yet hardware.

> +#define AN8855_HWTRAP			0x1000009c
> +
> +#define AN8855_CREV			0x10005000

Chip?

> +#define   AN8855_ID			0x8855

What kid of ID?  Chip, revision, model, serial?

> +#define AN8855_RG_GPHY_AFE_PWD		0x1028c840

No idea!

> +/* MII Registers */
> +#define AN8855_PHY_SELECT_PAGE		0x1f
> +#define   AN8855_PHY_PAGE		GENMASK(2, 0)
> +#define   AN8855_PHY_PAGE_STANDARD	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
> +#define   AN8855_PHY_PAGE_EXTENDED_1	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
> +#define   AN8855_PHY_PAGE_EXTENDED_4	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
> +
> +/* MII Registers Page 4 */
> +#define AN8855_PBUS_MODE		0x10
> +#define   AN8855_PBUS_MODE_ADDR_FIXED	0x0
> +#define AN8855_PBUS_MODE_ADDR_INCR	BIT(15)
> +#define AN8855_PBUS_WR_ADDR_HIGH	0x11
> +#define AN8855_PBUS_WR_ADDR_LOW		0x12
> +#define AN8855_PBUS_WR_DATA_HIGH	0x13
> +#define AN8855_PBUS_WR_DATA_LOW		0x14
> +#define AN8855_PBUS_RD_ADDR_HIGH	0x15
> +#define AN8855_PBUS_RD_ADDR_LOW		0x16
> +#define AN8855_PBUS_RD_DATA_HIGH	0x17
> +#define AN8855_PBUS_RD_DATA_LOW		0x18
> +
> +struct an8855_mfd_priv {

It's not an "mfd".

> +	struct mii_bus *bus;
> +
> +	unsigned int switch_addr;
> +	u16 current_page;
> +};
> +
> +static const struct mfd_cell an8855_mfd_devs[] = {

"_child_" or "_sub_" or drop it entirely.

> +	{
> +		.name = "an8855-efuse",
> +		.of_compatible = "airoha,an8855-efuse",
> +	}, {
> +		.name = "an8855-switch",
> +		.of_compatible = "airoha,an8855-switch",
> +	}, {
> +		.name = "an8855-mdio",
> +		.of_compatible = "airoha,an8855-mdio",
> +	}
> +};
> +
> +static int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id,
> +			       u8 page) __must_hold(&priv->bus->mdio_lock)
> +{
> +	struct mii_bus *bus = priv->bus;
> +	int ret;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page);

Calling functions with '__' is a red flag.

> +	if (ret < 0)
> +		dev_err_ratelimited(&bus->dev,
> +				    "failed to set an8855 mii page\n");

Use 100-chars if it avoids these kind of line breaks.

> +	/* Cache current page if next mii read/write is for switch */

MII here?

"this switch"?

I don't see any checks here - how do we know if it is for switch or not?

> +	priv->current_page = page;
> +	return ret < 0 ? ret : 0;

You already check for 'ret < 0' at the call sites, so this little dance
is superfluous.

> +}
> +
> +static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
> +			     u32 *val) __must_hold(&bus->mdio_lock)
> +{
> +	int lo, hi, ret;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> +			      AN8855_PBUS_MODE_ADDR_FIXED);

100-chars.

> +	if (ret < 0)
> +		goto err;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
> +			      upper_16_bits(reg));
> +	if (ret < 0)
> +		goto err;

'\n'

> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
> +			      lower_16_bits(reg));
> +	if (ret < 0)
> +		goto err;
> +
> +	hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
> +	if (hi < 0) {
> +		ret = hi;
> +		goto err;
> +	}

'\n'

> +	lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
> +	if (lo < 0) {
> +		ret = lo;
> +		goto err;
> +	}
> +
> +	*val = ((u16)hi << 16) | ((u16)lo & 0xffff);
> +
> +	return 0;
> +err:
> +	dev_err_ratelimited(&bus->dev,
> +			    "failed to read an8855 register\n");

dev_err() will already print out the an8855 part.

> +	return ret;
> +}
> +
> +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
> +{
> +	struct an8855_mfd_priv *priv = ctx;
> +	struct mii_bus *bus = priv->bus;
> +	u16 addr = priv->switch_addr;
> +	int ret;
> +
> +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);

guard()?

> +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> +	if (ret < 0)
> +		goto exit;
> +
> +	ret = an8855_mii_read32(bus, addr, reg, val);
> +
> +exit:
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return ret < 0 ? ret : 0;
> +}
> +
> +static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
> +			      u32 val) __must_hold(&bus->mdio_lock)
> +{
> +	int ret;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> +			      AN8855_PBUS_MODE_ADDR_FIXED);
> +	if (ret < 0)
> +		goto err;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
> +			      upper_16_bits(reg));
> +	if (ret < 0)
> +		goto err;
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
> +			      lower_16_bits(reg));
> +	if (ret < 0)
> +		goto err;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
> +			      upper_16_bits(val));
> +	if (ret < 0)
> +		goto err;
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
> +			      lower_16_bits(val));
> +	if (ret < 0)
> +		goto err;
> +
> +	return 0;
> +err:
> +	dev_err_ratelimited(&bus->dev,
> +			    "failed to write an8855 register\n");
> +	return ret;
> +}
> +
> +static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
> +{
> +	struct an8855_mfd_priv *priv = ctx;
> +	struct mii_bus *bus = priv->bus;
> +	u16 addr = priv->switch_addr;
> +	int ret;
> +
> +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> +	if (ret < 0)
> +		goto exit;
> +
> +	ret = an8855_mii_write32(bus, addr, reg, val);
> +
> +exit:
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return ret < 0 ? ret : 0;

Doesn't the caller already expect possible >0 results?

> +}
> +
> +static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
> +				     uint32_t write_val)
> +{
> +	struct an8855_mfd_priv *priv = ctx;
> +	struct mii_bus *bus = priv->bus;
> +	u16 addr = priv->switch_addr;
> +	u32 val;
> +	int ret;
> +
> +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> +	if (ret < 0)
> +		goto exit;
> +
> +	ret = an8855_mii_read32(bus, addr, reg, &val);
> +	if (ret < 0)
> +		goto exit;
> +
> +	val &= ~mask;
> +	val |= write_val;
> +	ret = an8855_mii_write32(bus, addr, reg, val);
> +
> +exit:
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return ret < 0 ? ret : 0;
> +}
> +
> +static const struct regmap_range an8855_readable_ranges[] = {
> +	regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
> +	regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
> +	regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
> +	regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
> +	regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
> +	regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
> +	regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
> +	regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
> +	regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
> +	regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
> +	regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
> +	regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
> +	regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
> +	regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
> +	regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
> +	regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
> +	regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
> +	regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
> +	regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
> +	regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
> +	regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
> +	regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
> +	regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
> +	regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
> +	regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
> +	regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
> +	regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
> +};
> +
> +static const struct regmap_access_table an8855_readable_table = {
> +	.yes_ranges = an8855_readable_ranges,
> +	.n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
> +};
> +
> +static const struct regmap_config an8855_regmap_config = {
> +	.name = "switch",
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0xbfffffff,
> +	.reg_read = an8855_regmap_read,
> +	.reg_write = an8855_regmap_write,
> +	.reg_update_bits = an8855_regmap_update_bits,
> +	.disable_locking = true,
> +	.rd_table = &an8855_readable_table,
> +};
> +
> +static int an855_regmap_phy_reset_page(struct an8855_mfd_priv *priv,
> +				       int phy) __must_hold(&priv->bus->mdio_lock)
> +{
> +	/* Check PHY page only for addr shared with switch */
> +	if (phy != priv->switch_addr)
> +		return 0;
> +
> +	/* Don't restore page if it's not set to switch page */
> +	if (priv->current_page != FIELD_GET(AN8855_PHY_PAGE,
> +					    AN8855_PHY_PAGE_EXTENDED_4))
> +		return 0;
> +
> +	/* Restore page to 0, PHY might change page right after but that
> +	 * will be ignored as it won't be a switch page.
> +	 */

Use proper multi-line comments please.

> +	return an8855_mii_set_page(priv, phy, AN8855_PHY_PAGE_STANDARD);
> +}
> +
> +static int an8855_regmap_phy_read(void *ctx, uint32_t reg, uint32_t *val)
> +{
> +	struct an8855_mfd_priv *priv = ctx;
> +	struct mii_bus *bus = priv->bus;
> +	u16 phy_id, addr;
> +	int ret;
> +
> +	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
> +	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
> +
> +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	ret = an855_regmap_phy_reset_page(priv, phy_id);
> +	if (ret)
> +		goto exit;
> +
> +	ret = __mdiobus_read(priv->bus, phy_id, addr);
> +
> +exit:
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	*val = ret;
> +	return 0;
> +}
> +
> +static int an8855_regmap_phy_write(void *ctx, uint32_t reg, uint32_t val)
> +{
> +	struct an8855_mfd_priv *priv = ctx;
> +	struct mii_bus *bus = priv->bus;
> +	u16 phy_id, addr;
> +	int ret;
> +
> +	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
> +	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
> +
> +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	ret = an855_regmap_phy_reset_page(priv, phy_id);
> +	if (ret)
> +		goto exit;
> +
> +	ret = __mdiobus_write(priv->bus, phy_id, addr, val);
> +
> +exit:
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return ret;
> +}
> +
> +/* Regmap for MDIO Passtrough
> + * PHY Addr and PHY Reg are encoded in the regmap register.
> + */
> +static const struct regmap_config an8855_regmap_phy_config = {
> +	.name = "phy",
> +	.reg_bits = 20,
> +	.val_bits = 16,
> +	.reg_stride = 1,
> +	.max_register = MDIO_REGMAP_PHY_ADDR | MDIO_REGMAP_PHY_REG,
> +	.reg_read = an8855_regmap_phy_read,
> +	.reg_write = an8855_regmap_phy_write,
> +	.disable_locking = true,
> +};
> +
> +static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
> +{
> +	u32 id;
> +	int ret;
> +
> +	ret = regmap_read(regmap, AN8855_CREV, &id);
> +	if (ret)
> +		return ret;
> +
> +	if (id != AN8855_ID) {
> +		dev_err(dev, "Switch ID detected %x but expected %x\n",

"Detected Switch ID %x but %x was expected"

Or

"Expected Switch ID %x but %x was detected"

> +			id, AN8855_ID);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int an8855_mfd_probe(struct mdio_device *mdiodev)
> +{
> +	struct regmap *regmap, *regmap_phy;
> +	struct device *dev = &mdiodev->dev;
> +	struct an8855_mfd_priv *priv;
> +	struct gpio_desc *reset_gpio;
> +	u32 val;
> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->bus = mdiodev->bus;
> +	priv->switch_addr = mdiodev->addr;
> +	/* no DMA for mdiobus, mute warning for DMA mask not set */

Nit: Please start sentences with uppercase chars.

> +	dev->dma_mask = &dev->coherent_dma_mask;
> +
> +	regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
> +	if (IS_ERR(regmap))
> +		return dev_err_probe(dev, PTR_ERR(regmap),
> +				     "regmap initialization failed\n");
> +
> +	regmap_phy = devm_regmap_init(dev, NULL, priv, &an8855_regmap_phy_config);
> +	if (IS_ERR(regmap_phy))
> +		return dev_err_probe(dev, PTR_ERR(regmap_phy),
> +				     "regmap phy initialization failed\n");
> +
> +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(reset_gpio))
> +		return PTR_ERR(reset_gpio);
> +
> +	if (reset_gpio) {
> +		usleep_range(100000, 150000);
> +		gpiod_set_value_cansleep(reset_gpio, 0);
> +		usleep_range(100000, 150000);
> +		gpiod_set_value_cansleep(reset_gpio, 1);
> +
> +		/* Poll HWTRAP reg to wait for Switch to fully Init */
> +		ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
> +					       val, 20, 200000);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = an8855_read_switch_id(dev, regmap);
> +	if (ret)
> +		return ret;
> +
> +	/* Release global PHY power down */
> +	ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
> +	if (ret)
> +		return ret;
> +
> +	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_mfd_devs,
> +				    ARRAY_SIZE(an8855_mfd_devs), NULL, 0,
> +				    NULL);
> +}
> +
> +static const struct of_device_id an8855_mfd_of_match[] = {
> +	{ .compatible = "airoha,an8855" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, an8855_mfd_of_match);
> +
> +static struct mdio_driver an8855_mfd_driver = {
> +	.probe = an8855_mfd_probe,
> +	.mdiodrv.driver = {
> +		.name = "an8855",
> +		.of_match_table = an8855_mfd_of_match,
> +	},
> +};
> +mdio_module_driver(an8855_mfd_driver);
> +
> +MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
> +MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
> +MODULE_LICENSE("GPL");
> -- 
> 2.48.1
> 

-- 
Lee Jones [???]


From ryan.roberts at arm.com  Fri Mar 14 04:51:16 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 11:51:16 +0000
Subject: [v3 PATCH 3/6] arm64: mm: make __create_pgd_mapping() and helpers
 non-void
In-Reply-To: <20250304222018.615808-4-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-4-yang@os.amperecomputing.com>
Message-ID: <172bf7a8-4533-4627-83d2-552e4681c360@arm.com>

On 04/03/2025 22:19, Yang Shi wrote:
> The later patch will enhance __create_pgd_mapping() and related helpers
> to split kernel linear mapping, it requires have return value.  So make
> __create_pgd_mapping() and helpers non-void functions.
> 
> And move the BUG_ON() out of page table alloc helper since failing
> splitting kernel linear mapping is not fatal and can be handled by the
> callers in the later patch.  Have BUG_ON() after
> __create_pgd_mapping_locked() returns to keep the current callers behavior
> intact.
> 
> Suggested-by: Ryan Roberts <ryan.roberts at arm.com>
> Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
> ---
>  arch/arm64/mm/mmu.c | 127 ++++++++++++++++++++++++++++++--------------
>  1 file changed, 86 insertions(+), 41 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b4df5bc5b1b8..dccf0877285b 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -189,11 +189,11 @@ static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
>  	} while (ptep++, addr += PAGE_SIZE, addr != end);
>  }
>  
> -static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
> -				unsigned long end, phys_addr_t phys,
> -				pgprot_t prot,
> -				phys_addr_t (*pgtable_alloc)(int),
> -				int flags)
> +static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
> +			       unsigned long end, phys_addr_t phys,
> +			       pgprot_t prot,
> +			       phys_addr_t (*pgtable_alloc)(int),
> +			       int flags)
>  {
>  	unsigned long next;
>  	pmd_t pmd = READ_ONCE(*pmdp);
> @@ -208,6 +208,8 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  			pmdval |= PMD_TABLE_PXN;
>  		BUG_ON(!pgtable_alloc);
>  		pte_phys = pgtable_alloc(PAGE_SHIFT);
> +		if (!pte_phys)
> +			return -ENOMEM;

nit: personally I'd prefer to see a "goto out" and funnel all to a single return
statement. You do that in some functions (via loop break), but would be cleaner
if consistent.

If pgtable_alloc() is modified to return int (see my comment at the bottom),
this becomes:

ret = pgtable_alloc(PAGE_SHIFT, &pte_phys);
if (ret)
	goto out;


>  		ptep = pte_set_fixmap(pte_phys);
>  		init_clear_pgtable(ptep);
>  		ptep += pte_index(addr);
> @@ -239,13 +241,16 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  	 * walker.
>  	 */
>  	pte_clear_fixmap();
> +
> +	return 0;
>  }
>  
> -static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
> -		     phys_addr_t phys, pgprot_t prot,
> -		     phys_addr_t (*pgtable_alloc)(int), int flags)
> +static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
> +		    phys_addr_t phys, pgprot_t prot,
> +		    phys_addr_t (*pgtable_alloc)(int), int flags)
>  {
>  	unsigned long next;
> +	int ret = 0;
>  
>  	do {
>  		pmd_t old_pmd = READ_ONCE(*pmdp);
> @@ -264,22 +269,27 @@ static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>  			BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd),
>  						      READ_ONCE(pmd_val(*pmdp))));
>  		} else {
> -			alloc_init_cont_pte(pmdp, addr, next, phys, prot,
> +			ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot,
>  					    pgtable_alloc, flags);
> +			if (ret)
> +				break;
>  
>  			BUG_ON(pmd_val(old_pmd) != 0 &&
>  			       pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp)));
>  		}
>  		phys += next - addr;
>  	} while (pmdp++, addr = next, addr != end);
> +
> +	return ret;
>  }
>  
> -static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
> -				unsigned long end, phys_addr_t phys,
> -				pgprot_t prot,
> -				phys_addr_t (*pgtable_alloc)(int), int flags)
> +static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
> +			       unsigned long end, phys_addr_t phys,
> +			       pgprot_t prot,
> +			       phys_addr_t (*pgtable_alloc)(int), int flags)
>  {
>  	unsigned long next;
> +	int ret = 0;
>  	pud_t pud = READ_ONCE(*pudp);
>  	pmd_t *pmdp;
>  
> @@ -295,6 +305,8 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>  			pudval |= PUD_TABLE_PXN;
>  		BUG_ON(!pgtable_alloc);
>  		pmd_phys = pgtable_alloc(PMD_SHIFT);
> +		if (!pmd_phys)
> +			return -ENOMEM;
>  		pmdp = pmd_set_fixmap(pmd_phys);
>  		init_clear_pgtable(pmdp);
>  		pmdp += pmd_index(addr);
> @@ -314,21 +326,26 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>  		    (flags & NO_CONT_MAPPINGS) == 0)
>  			__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>  
> -		init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
> +		ret = init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
> +		if (ret)
> +			break;
>  
>  		pmdp += pmd_index(next) - pmd_index(addr);
>  		phys += next - addr;
>  	} while (addr = next, addr != end);
>  
>  	pmd_clear_fixmap();
> +
> +	return ret;
>  }
>  
> -static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
> -			   phys_addr_t phys, pgprot_t prot,
> -			   phys_addr_t (*pgtable_alloc)(int),
> -			   int flags)
> +static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
> +			  phys_addr_t phys, pgprot_t prot,
> +			  phys_addr_t (*pgtable_alloc)(int),
> +			  int flags)
>  {
>  	unsigned long next;
> +	int ret = 0;
>  	p4d_t p4d = READ_ONCE(*p4dp);
>  	pud_t *pudp;
>  
> @@ -340,6 +357,8 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  			p4dval |= P4D_TABLE_PXN;
>  		BUG_ON(!pgtable_alloc);
>  		pud_phys = pgtable_alloc(PUD_SHIFT);
> +		if (!pud_phys)
> +			return -ENOMEM;
>  		pudp = pud_set_fixmap(pud_phys);
>  		init_clear_pgtable(pudp);
>  		pudp += pud_index(addr);
> @@ -369,8 +388,10 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  			BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
>  						      READ_ONCE(pud_val(*pudp))));
>  		} else {
> -			alloc_init_cont_pmd(pudp, addr, next, phys, prot,
> +			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
>  					    pgtable_alloc, flags);
> +			if (ret)
> +				break;
>  
>  			BUG_ON(pud_val(old_pud) != 0 &&
>  			       pud_val(old_pud) != READ_ONCE(pud_val(*pudp)));
> @@ -379,14 +400,17 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  	} while (pudp++, addr = next, addr != end);
>  
>  	pud_clear_fixmap();
> +
> +	return ret;
>  }
>  
> -static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
> -			   phys_addr_t phys, pgprot_t prot,
> -			   phys_addr_t (*pgtable_alloc)(int),
> -			   int flags)
> +static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
> +			  phys_addr_t phys, pgprot_t prot,
> +			  phys_addr_t (*pgtable_alloc)(int),
> +			  int flags)
>  {
>  	unsigned long next;
> +	int ret = 0;
>  	pgd_t pgd = READ_ONCE(*pgdp);
>  	p4d_t *p4dp;
>  
> @@ -398,6 +422,8 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  			pgdval |= PGD_TABLE_PXN;
>  		BUG_ON(!pgtable_alloc);
>  		p4d_phys = pgtable_alloc(P4D_SHIFT);
> +		if (!p4d_phys)
> +			return -ENOMEM;
>  		p4dp = p4d_set_fixmap(p4d_phys);
>  		init_clear_pgtable(p4dp);
>  		p4dp += p4d_index(addr);
> @@ -412,8 +438,10 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  
>  		next = p4d_addr_end(addr, end);
>  
> -		alloc_init_pud(p4dp, addr, next, phys, prot,
> +		ret = alloc_init_pud(p4dp, addr, next, phys, prot,
>  			       pgtable_alloc, flags);
> +		if (ret)
> +			break;
>  
>  		BUG_ON(p4d_val(old_p4d) != 0 &&
>  		       p4d_val(old_p4d) != READ_ONCE(p4d_val(*p4dp)));
> @@ -422,23 +450,26 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  	} while (p4dp++, addr = next, addr != end);
>  
>  	p4d_clear_fixmap();
> +
> +	return ret;
>  }
>  
> -static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
> -					unsigned long virt, phys_addr_t size,
> -					pgprot_t prot,
> -					phys_addr_t (*pgtable_alloc)(int),
> -					int flags)
> +static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
> +				       unsigned long virt, phys_addr_t size,
> +				       pgprot_t prot,
> +				       phys_addr_t (*pgtable_alloc)(int),
> +				       int flags)
>  {
>  	unsigned long addr, end, next;
>  	pgd_t *pgdp = pgd_offset_pgd(pgdir, virt);
> +	int ret = 0;
>  
>  	/*
>  	 * If the virtual and physical address don't have the same offset
>  	 * within a page, we cannot map the region as the caller expects.
>  	 */
>  	if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
> -		return;
> +		return -EINVAL;
>  
>  	phys &= PAGE_MASK;
>  	addr = virt & PAGE_MASK;
> @@ -446,29 +477,38 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
>  
>  	do {
>  		next = pgd_addr_end(addr, end);
> -		alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
> +		ret = alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
>  			       flags);
> +		if (ret)
> +			break;
>  		phys += next - addr;
>  	} while (pgdp++, addr = next, addr != end);
> +
> +	return ret;
>  }
>  
> -static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
> -				 unsigned long virt, phys_addr_t size,
> -				 pgprot_t prot,
> -				 phys_addr_t (*pgtable_alloc)(int),
> -				 int flags)
> +static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
> +				unsigned long virt, phys_addr_t size,
> +				pgprot_t prot,
> +				phys_addr_t (*pgtable_alloc)(int),
> +				int flags)
>  {
> +	int ret;
> +
>  	mutex_lock(&fixmap_lock);
> -	__create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
> +	ret = __create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
>  				    pgtable_alloc, flags);
> +	BUG_ON(ret);

This function now returns an error, but also BUGs on ret!=0. For this patch, I'd
suggest keeping this function as void.

But I believe there is a pre-existing bug in arch_add_memory(). That's called at
runtime so if __create_pgd_mapping() fails and BUGs, it will take down a running
system.

With this foundational patch, we can fix that with an additional patch to pass
along the error code instead of BUGing in that case. arch_add_memory() would
need to unwind whatever __create_pgd_mapping() managed to do before the memory
allocation failure (presumably unmapping and freeing any allocated tables). I'm
happy to do this as a follow up patch.

>  	mutex_unlock(&fixmap_lock);
> +
> +	return ret;
>  }
>  
>  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>  extern __alias(__create_pgd_mapping_locked)
> -void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
> -			     phys_addr_t size, pgprot_t prot,
> -			     phys_addr_t (*pgtable_alloc)(int), int flags);
> +int create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
> +			    phys_addr_t size, pgprot_t prot,
> +			    phys_addr_t (*pgtable_alloc)(int), int flags);

create_kpti_ng_temp_pgd() now returns error instead of BUGing on allocation
failure, but I don't see a change to handle that error. You'll want to update
__kpti_install_ng_mappings() to BUG on error.

>  #endif
>  
>  static phys_addr_t __pgd_pgtable_alloc(int shift)
> @@ -476,13 +516,17 @@ static phys_addr_t __pgd_pgtable_alloc(int shift)
>  	/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
>  	void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL & ~__GFP_ZERO);
>  
> -	BUG_ON(!ptr);
> +	if (!ptr)
> +		return 0;

0 is a valid (though unlikely) physical address. I guess you could technically
encode like ERR_PTR(), but since you are returning phys_addr_t and not a
pointer, then perhaps it will be clearer to make this return int and accept a
pointer to a phys_addr_t, which it will populate on success?

> +
>  	return __pa(ptr);
>  }
>  
>  static phys_addr_t pgd_pgtable_alloc(int shift)
>  {
>  	phys_addr_t pa = __pgd_pgtable_alloc(shift);
> +	if (!pa)
> +		goto out;

This would obviously need to be fixed up as per above.

>  	struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa));
>  
>  	/*
> @@ -498,6 +542,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
>  	else if (shift == PMD_SHIFT)
>  		BUG_ON(!pagetable_pmd_ctor(ptdesc));
>  
> +out:
>  	return pa;
>  }
>  

You have left early_pgtable_alloc() to panic() on allocation failure. Given we
can now unwind the stack with error code, I think it would be more consistent to
also allow early_pgtable_alloc() to return error.

Thanks,
Ryan



From manivannan.sadhasivam at linaro.org  Fri Mar 14 04:52:12 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Fri, 14 Mar 2025 17:22:12 +0530
Subject: [PATCH v3 0/2] PCI: dw-rockchip: hide broken ATS cap in EP-mode
In-Reply-To: <20250310094826.842681-4-cassel@kernel.org>
References: <20250310094826.842681-4-cassel@kernel.org>
Message-ID: <20250314115212.ywlee4vyuxyq4x6s@thinkpad>

On Mon, Mar 10, 2025 at 10:48:26AM +0100, Niklas Cassel wrote:
> Hello there,
> 
> Address Translation Services (ATS) is broken on rk3588 when running the
> PCIe controller in Endpoint Mode.
> 
> This causes IOTLB invalidation timeout errors on the host side when using
> and rk3588 in Endpoint Mode, and you are unable to run pci_endpoint_test.
> 
> Solve this by hiding the ATS capability.
> With this, we do not get any IOTLB invalidation timeouts, and we can run
> pci_endpoint_test successfully.
> 

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> 
> Changes since v2:
> -Added missing EXPORT_SYMBOL_GPL().
> 
> 
> Niklas Cassel (2):
>   PCI: dwc: ep: Add dw_pcie_ep_hide_ext_capability()
>   PCI: dw-rockchip: Hide broken ATS capability
> 
>  .../pci/controller/dwc/pcie-designware-ep.c   | 39 +++++++++++++++++++
>  drivers/pci/controller/dwc/pcie-designware.h  |  7 ++++
>  drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++
>  3 files changed, 73 insertions(+)
> 
> -- 
> 2.48.1
> 

-- 
????????? ????????


From mark.rutland at arm.com  Fri Mar 14 05:02:11 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 14 Mar 2025 12:02:11 +0000
Subject: [PATCH v2 1/4] arm64/sysreg: Fix unbalanced closing block
In-Reply-To: <20250115162600.2153226-2-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-2-james.clark@linaro.org>
Message-ID: <Z9Qaw_EVGVdv3Qyh@J2N7QTR9R3.cambridge.arm.com>

On Wed, Jan 15, 2025 at 04:25:55PM +0000, James Clark wrote:
> This is a sysreg block so close it with one. This doesn't make a
> difference to the output because the script only matches on the
> beginning of the word to close blocks which is correct by coincidence
> here.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> ---
>  arch/arm64/tools/sysreg | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
> index 762ee084b37c..bbe7df69da9c 100644
> --- a/arch/arm64/tools/sysreg
> +++ b/arch/arm64/tools/sysreg
> @@ -2074,7 +2074,7 @@ EndEnum
>  Res0	4:2
>  Field	1	ExTRE
>  Field	0	E0TRE
> -EndSysregFields
> +EndSysreg
>  
>  Sysreg	SMPRI_EL1	3	0	1	2	4
>  Res0	63:4
> -- 
> 2.34.1
> 


From ilias.apalodimas at linaro.org  Fri Mar 14 05:00:33 2025
From: ilias.apalodimas at linaro.org (Ilias Apalodimas)
Date: Fri, 14 Mar 2025 14:00:33 +0200
Subject: [PATCH net-next 3/7] net: netsec: Add metadata support for xdp mode
In-Reply-To: <20250311-mvneta-xdp-meta-v1-3-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org> <20250311-mvneta-xdp-meta-v1-3-36cf1c99790e@kernel.org>
Message-ID: <CAC_iWjKRLs4POP3TQ0XrXUiBmW0D5qD0JYh=UxqAytXjPvRmGw@mail.gmail.com>

On Tue, 11 Mar 2025 at 14:19, Lorenzo Bianconi <lorenzo at kernel.org> wrote:
>
> Set metadata size building the skb from xdp_buff in netsec driver
>
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> ---
>  drivers/net/ethernet/socionext/netsec.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
> index dc99821c6226fbaece65c8ade23899f610b44a9a..ee890de69ffe795dbdcc5331e36be86769f0d9a6 100644
> --- a/drivers/net/ethernet/socionext/netsec.c
> +++ b/drivers/net/ethernet/socionext/netsec.c
> @@ -970,7 +970,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
>                 struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
>                 struct netsec_desc *desc = &dring->desc[idx];
>                 struct page *page = virt_to_page(desc->addr);
> -               u32 xdp_result = NETSEC_XDP_PASS;
> +               u32 metasize, xdp_result = NETSEC_XDP_PASS;
>                 struct sk_buff *skb = NULL;
>                 u16 pkt_len, desc_len;
>                 dma_addr_t dma_handle;
> @@ -1019,7 +1019,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
>                 prefetch(desc->addr);
>
>                 xdp_prepare_buff(&xdp, desc->addr, NETSEC_RXBUF_HEADROOM,
> -                                pkt_len, false);
> +                                pkt_len, true);
>
>                 if (xdp_prog) {
>                         xdp_result = netsec_run_xdp(priv, xdp_prog, &xdp);
> @@ -1048,6 +1048,9 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
>
>                 skb_reserve(skb, xdp.data - xdp.data_hard_start);
>                 skb_put(skb, xdp.data_end - xdp.data);
> +               metasize = xdp.data - xdp.data_meta;
> +               if (metasize)
> +                       skb_metadata_set(skb, metasize);
>                 skb->protocol = eth_type_trans(skb, priv->ndev);
>
>                 if (priv->rx_cksum_offload_flag &&
>
> --
> 2.48.1
>

Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>


From mark.rutland at arm.com  Fri Mar 14 05:01:11 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 14 Mar 2025 12:01:11 +0000
Subject: [PATCH v2 2/4] arm64/sysreg: Enforce whole word match for
 open/close tokens
In-Reply-To: <20250115162600.2153226-3-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-3-james.clark@linaro.org>
Message-ID: <Z9Qah4N93Mhqr3-V@J2N7QTR9R3.cambridge.arm.com>

On Wed, Jan 15, 2025 at 04:25:56PM +0000, James Clark wrote:
> Opening and closing tokens can also match on words with common prefixes
> like "Endsysreg" vs "EndsysregFields". This could potentially make the
> script go wrong in weird ways so make it fall through to the fatal
> unhandled statement catcher if it doesn't fully match the current
> block.
> 
> Closing ones also get expect_fields(1) to ensure nothing other than
> whitespace follows.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

In retrospect, this is what I should have wirrten originally. Thanks for
the fix!

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> ---
>  arch/arm64/tools/gen-sysreg.awk | 31 +++++++++++++++++--------------
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
> index 1a2afc9fdd42..f2a1732cb1f6 100755
> --- a/arch/arm64/tools/gen-sysreg.awk
> +++ b/arch/arm64/tools/gen-sysreg.awk
> @@ -111,7 +111,7 @@ END {
>  /^$/ { next }
>  /^[\t ]*#/ { next }
>  
> -/^SysregFields/ && block_current() == "Root" {
> +$1 == "SysregFields" && block_current() == "Root" {
>  	block_push("SysregFields")
>  
>  	expect_fields(2)
> @@ -127,7 +127,8 @@ END {
>  	next
>  }
>  
> -/^EndSysregFields/ && block_current() == "SysregFields" {
> +$1 == "EndSysregFields" && block_current() == "SysregFields" {
> +	expect_fields(1)
>  	if (next_bit > 0)
>  		fatal("Unspecified bits in " reg)
>  
> @@ -145,7 +146,7 @@ END {
>  	next
>  }
>  
> -/^Sysreg/ && block_current() == "Root" {
> +$1 == "Sysreg" && block_current() == "Root" {
>  	block_push("Sysreg")
>  
>  	expect_fields(7)
> @@ -177,7 +178,8 @@ END {
>  	next
>  }
>  
> -/^EndSysreg/ && block_current() == "Sysreg" {
> +$1 == "EndSysreg" && block_current() == "Sysreg" {
> +	expect_fields(1)
>  	if (next_bit > 0)
>  		fatal("Unspecified bits in " reg)
>  
> @@ -206,7 +208,7 @@ END {
>  
>  # Currently this is effectivey a comment, in future we may want to emit
>  # defines for the fields.
> -(/^Fields/ || /^Mapping/) && block_current() == "Sysreg" {
> +($1 == "Fields" || $1 == "Mapping") && block_current() == "Sysreg" {
>  	expect_fields(2)
>  
>  	if (next_bit != 63)
> @@ -224,7 +226,7 @@ END {
>  }
>  
>  
> -/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	expect_fields(2)
>  	parse_bitdef(reg, "RES0", $2)
>  	field = "RES0_" msb "_" lsb
> @@ -234,7 +236,7 @@ END {
>  	next
>  }
>  
> -/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	expect_fields(2)
>  	parse_bitdef(reg, "RES1", $2)
>  	field = "RES1_" msb "_" lsb
> @@ -244,7 +246,7 @@ END {
>  	next
>  }
>  
> -/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	expect_fields(2)
>  	parse_bitdef(reg, "UNKN", $2)
>  	field = "UNKN_" msb "_" lsb
> @@ -254,7 +256,7 @@ END {
>  	next
>  }
>  
> -/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	expect_fields(3)
>  	field = $3
>  	parse_bitdef(reg, field, $2)
> @@ -265,14 +267,14 @@ END {
>  	next
>  }
>  
> -/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	expect_fields(2)
>  	parse_bitdef(reg, field, $2)
>  
>  	next
>  }
>  
> -/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	block_push("Enum")
>  
>  	expect_fields(3)
> @@ -285,7 +287,7 @@ END {
>  	next
>  }
>  
> -/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	block_push("Enum")
>  
>  	expect_fields(3)
> @@ -298,7 +300,7 @@ END {
>  	next
>  }
>  
> -/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
> +$1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
>  	block_push("Enum")
>  
>  	expect_fields(3)
> @@ -310,7 +312,8 @@ END {
>  	next
>  }
>  
> -/^EndEnum/ && block_current() == "Enum" {
> +$1 == "EndEnum" && block_current() == "Enum" {
> +	expect_fields(1)
>  
>  	field = null
>  	msb = null
> -- 
> 2.34.1
> 


From cristian.marussi at arm.com  Fri Mar 14 05:03:38 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Fri, 14 Mar 2025 12:03:38 +0000
Subject: [PATCH] pmdomain: arm: scmi_pm_domain: Remove redundant state
 verification
In-Reply-To: <20250314095851.443979-1-sudeep.holla@arm.com>
References: <20250314095851.443979-1-sudeep.holla@arm.com>
Message-ID: <Z9QbGiuK9XTEpAdE@pluto>

On Fri, Mar 14, 2025 at 09:58:51AM +0000, Sudeep Holla wrote:
> Currently, scmi_pd_power() explicitly verifies whether the requested
> power state was applied by calling state_get(). While this check could
> detect failures where the state was not properly updated, ensuring
> correctness is the responsibility of the SCMI firmware.
> 
> Removing this redundant state_get() call eliminates an unnecessary
> round-trip to the firmware, improving efficiency. Any mismatches
> between the requested and actual states should be handled by the SCMI
> firmware, which must return a failure if state_set() is unsuccessful.
> 
> Additionally, in some cases, checking the state after powering off a
> domain may be unreliable or unsafe, depending on the firmware
> implementation.
> 
> This patch removes the redundant verification, simplifying the function
> without compromising correctness.
> 
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Ulf Hansson <ulf.hansson at linaro.org>
> Cc: Cristian Marussi <cristian.marussi at arm.com>
> Reported-and-tested-by: Ranjani Vaidyanathan <ranjani.vaidyanathan at nxp.com>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
>  drivers/pmdomain/arm/scmi_pm_domain.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
> index 86b531e15b85..2a213c218126 100644
> --- a/drivers/pmdomain/arm/scmi_pm_domain.c
> +++ b/drivers/pmdomain/arm/scmi_pm_domain.c
> @@ -24,8 +24,7 @@ struct scmi_pm_domain {
>  
>  static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
>  {
> -	int ret;
> -	u32 state, ret_state;
> +	u32 state;
>  	struct scmi_pm_domain *pd = to_scmi_pd(domain);
>  
>  	if (power_on)
> @@ -33,13 +32,7 @@ static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
>  	else
>  		state = SCMI_POWER_STATE_GENERIC_OFF;
>  
> -	ret = power_ops->state_set(pd->ph, pd->domain, state);
> -	if (!ret)
> -		ret = power_ops->state_get(pd->ph, pd->domain, &ret_state);
> -	if (!ret && state != ret_state)
> -		return -EIO;
> -
> -	return ret;
> +	return power_ops->state_set(pd->ph, pd->domain, state);
>  }

...not sure about the history of this but it would have also definitely
failed consistently on any systen where the SCMI Server exposes resources
physical states (an IMPDEF behaviour), so that after a successfull set_OFF
on a shared resource a subsequent get() could return that the resource is
still physically ON if it was still needed by the other agennts sharing it...

LGTM.
Reviewed-by: Cristian Marussi <cristian.marussi at arm.com>

Thanks,
Cristian


From krzk at kernel.org  Fri Mar 14 05:15:52 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 14 Mar 2025 13:15:52 +0100
Subject: =?UTF-8?B?UmU6IOWbnuWkjTogW1BBVENIIDEvNV0gcG1pYzogbWVkaWF0ZWs6IEFk?=
 =?UTF-8?Q?d_pmic_auxadc_driver?=
In-Reply-To: <SEZPR03MB68910F9B60DAF0060440503980D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-2-Lu.Tang@mediatek.com>
 <90d1c0f2-b037-482e-a569-f75b713e3a71@collabora.com>
 <SEZPR03MB68910F9B60DAF0060440503980D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
Message-ID: <b4318673-f2b6-4740-ba80-32bb33e91f3f@kernel.org>

On 14/03/2025 10:21, Lu Tang (??) wrote:
> Update email
> 
You just sent 10 emails like this to everyone. This is pointless, don't.

Best regards,
Krzysztof


From suzuki.poulose at arm.com  Fri Mar 14 05:33:48 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 14 Mar 2025 12:33:48 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <86ikocomvd.wl-maz@kernel.org> <f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
 <86h63wok11.wl-maz@kernel.org> <4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>
Message-ID: <3bba7adb-392b-4024-984f-b6f0f0f88629@arm.com>

On 14/03/2025 09:18, Ryan Roberts wrote:
> On 13/03/2025 18:36, Marc Zyngier wrote:
>> On Thu, 13 Mar 2025 18:22:00 +0000,
>> Ryan Roberts <ryan.roberts at arm.com> wrote:
>>>
>>> On 13/03/2025 17:34, Marc Zyngier wrote:
>>>> On Thu, 13 Mar 2025 10:41:10 +0000,
>>>> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
>>>>>
>>>>> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
>>>>> index c6b185b885f7..9728faa10390 100644
>>>>> --- a/arch/arm64/kernel/pi/idreg-override.c
>>>>> +++ b/arch/arm64/kernel/pi/idreg-override.c
>>>>> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
>>>>>   		FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>>>>>   		FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>>>>>   		FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
>>>>> +		FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>>>>>   		{}
>>>>>   	},
>>>>>   };
>>>>> @@ -246,6 +247,7 @@ static const struct {
>>>>>   	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>>>>>   	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>>>>>   	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
>>>>> +	{ "arm64.nobbml2",		"arm64_sw.nobbml2=1" },
>>>>
>>>> Why is that a SW feature? This looks very much like a HW feature to
>>>> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
>>>> with it. Something like:
>>>
>>> I think this implies that we would expect the BBM field to be advertising BBML2
>>> support normally and we would check for that as part of the cpufeature
>>> detection. That's how Miko was doing it in v2, but Yang pointed out that
>>> AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
>>> BBML2 in its MMFR2. So we don't want to check that field, and instead rely
>>> solely on the MIDR allow-list + a command line override. It was me that
>>> suggested putting that in the SW feature register, and I think that still sounds
>>> like the right solution for this situation?
>>
>> I think this is mixing two different things:
>>
>> - preventing BBM-L2 from being visible to the kernel: this is what my
>>    suggestion is doing by nuking an architectural feature in the
>>    relevant register
>>
>> - random HW not correctly advertising what they are doing: this is an
>>    erratum workaround
>>
>> I'd rather we don't conflate the two things, and make them very
>> explicitly distinct.
> 
> It all sounds so obvious when you put it like that! :)
> 
> I'm guessing there is a layer where the workaround can be applied to the
> sanitised feature registers on a per-cpu basis and that won't affect this global
> override which will remain as an overlay on top? If so then that sounds perfect
> (you can probably tell I find the whole feature management framework rather
> inpeneterable). That workaround would be added as part of Yang's series anyway.

Unfortunately, there is no easy way to fix this via the normal erratum
workaround "capability". The sanitised feature registers are handled
separately (initialised via init_cpu_features() for boot CPU and
sanitised eachtime via update_cpu_features).

Also we do not "enable" any capability (i.e. calling cpu_enable())
until the very end, after the CPUs are all brought up (except for boot 
CPUs).

But it may be possible to "fix up" the BBML2 feature in
cpuinfo_store_*cpu(), without using the "enable" call back.

Something like:

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 285d7d538342..8c23adbe29f8 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -479,7 +479,11 @@ static void __cpuinfo_store_cpu(struct 
cpuinfo_arm64 *info)
         info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
         info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
         info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);

+	/*
+	 * The CPU cap is not detected system wide, but we are able to
+	 * check if this CPU is affected by the Erratum.
+	 */
+       if (this_cpu_has_cap(AMPERE_ONE_ERRATUM_BBML2))
+               // Fixup  info->reg_id_aa64_mmfr2 with BBML2.
+
         info->reg_id_aa64mmfr3 = read_cpuid(ID_AA64MMFR3_EL1);
         info->reg_id_aa64mmfr4 = read_cpuid(ID_AA64MMFR4_EL1);
         info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
         info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);

Suzuki

> 
> So sounds like we are back to testing MMFR2.BBM in the matches function, with
> the addition of Maz's proposal above. Sorry for sending you round the houses, Miko.
> 
> Thanks,
> Ryan
> 
>>
>> Thanks,
>>
>> 	M.
>>
> 



From vladimir.oltean at nxp.com  Fri Mar 14 05:37:15 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Fri, 14 Mar 2025 14:37:15 +0200
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250314123715.fivq2cbczd4khxkk@skbuf>

On Fri, Mar 14, 2025 at 05:38:18AM +0200, Wei Fang wrote:
> > > +	__le16 update_act;
> > > +	u8 dbg_opt;
> > > +	u8 tblv_qact;
> > > +#define NTMP_QUERY_ACT		GENMASK(3, 0)
> > > +#define NTMP_TBL_VER		GENMASK(7, 0)
> > > +#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
> > > +				 ((a) & NTMP_QUERY_ACT))
> > 
> > Can you please move #define macros out of structure definitions?
> 
> No, I think these macros in the structure can better reflect the specific
> meaning of these members. We can intuitively see what the bits of
> these members represent, rather than finding the definition of these
> bits in RM or elsewhere.

I mean, I was just suggesting to group the macros with the macros, and
the struct fields with the struct fields. Mixing them together looks a
bit messy to me. Even worse in the definition of "union netc_cbd" which
IMO needs to be reconsidered a bit (a hint given below).

But you mention "intuitive" definitions without having to go to the RM.
If I look just at the definitions, I see that NTMP_QUERY_ACT and NTMP_TBL_VER
overlap, and that NTMP_TBLV_QACT() just ORs them together. How does that work?
Shouldn't NTMP_TBL_VER() have been GENMASK(7, 4)? If I do open the RM
and go to the "Generic NTMP Request Data Buffer Format" section, that
table does seem to agree with me.

The "normal" way to give more meaning to struct fields is to define them
as enum values. That doesn't work with "packed" field definitions as you
have here, which I agree is a challenge. But it is one of the reasons
why I tried to develop an API together with Jacob Keller which tries to
address this, by allowing you to define the structures in an "unpacked"
format, and have a separate data structure which informs the CPU how
that structure maps over the buffer layout.

Below is an example to illustrate this for the case of NTMP request buffers.
Note that the example is incomplete and doesn't even compile, because I
haven't even converted all ntmp_fill_crd_eid() callers - I don't want to
waste too much time doing that in case you disagree, but it's still
enough to show what I'm talking about. Disclaimer: I didn't even _try_
to compile it - it may contain bugs.

-- >8 --
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index c8efbb6f2055..35d5cf21f6f4 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -17,6 +17,7 @@ config NXP_ENETC_PF_COMMON
 
 config NXP_NETC_LIB
 	tristate
+	select PACKING
 	help
 	  This module provides common functionalities for both ENETC and NETC
 	  Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
index df10f2f310c1..f96cfca92a1c 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp.c
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -180,7 +180,7 @@ static int netc_xmit_ntmp_cmd(struct netc_cbdrs *cbdrs, union netc_cbd *cbd)
 	return err;
 }
 
-static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
+static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, ntmp_common_req_msg_data_buf *buf_align)
 {
 	void *buf;
 
@@ -221,18 +221,24 @@ static void ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
 	cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
 }
 
-static void ntmp_fill_crd(struct common_req_data *crd,
-			  u8 tblv, u8 qa, u16 ua)
+static const struct packed_field_u8 ntmp_common_req_fields[] = {
+	PACKED_FIELD(31, 28, struct ntmp_common_req_data, table_version),
+	PACKED_FIELD(27, 24, struct ntmp_common_req_data, query_actions),
+	PACKED_FIELD(15, 0, struct ntmp_common_req_data, update_actions),
+};
+
+static void ntmp_fill_crd(ntmp_common_req_msg_data_buf *buf,
+			  const struct common_req_data *crd)
 {
-	crd->update_act = cpu_to_le16(ua);
-	crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
+	pack_fields(buf, sizeof(*buf), crd, ntmp_common_req_fields,
+		    QUIRK_LITTLE_ENDIAN);
 }
 
-static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
-			      u8 qa, u16 ua, u32 entry_id)
+static void ntmp_fill_crd_eid(struct ntmp_common_req_msg_data_buf *buf,
+			      const struct ntmp_req_by_eid *rbe)
 {
-	ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
-	rbe->entry_id = cpu_to_le32(entry_id);
+	ntmp_fill_crd(buf, &rbe->crd);
+	pack(buf + 1, rbe->entry_id, 31, 0);
 }
 
 static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
@@ -240,7 +246,13 @@ static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
 				   u32 resp_len)
 {
 	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
-	struct ntmp_req_by_eid *req;
+	struct ntmp_req_by_eid req = {
+		.crd = {
+			.table_version = tbl_ver,
+		},
+		.entry_id = entry_id,
+	};
+	ntmp_common_req_msg_data_buf buf;
 	union netc_cbd cbd;
 	u32 len;
 	int err;
@@ -255,7 +267,7 @@ static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
 		req_len = sizeof(*req);
 
 	data.size = req_len >= resp_len ? req_len : resp_len;
-	err = ntmp_alloc_data_mem(&data, (void **)&req);
+	err = ntmp_alloc_data_mem(&data, &buf);
 	if (err)
 		return err;
 
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
index 45e4d083ab0a..e68b2a060176 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -16,14 +16,14 @@ struct ntmp_dma_buf {
 	dma_addr_t dma;
 };
 
-struct common_req_data {
-	__le16 update_act;
-	u8 dbg_opt;
-	u8 tblv_qact;
-#define NTMP_QUERY_ACT		GENMASK(3, 0)
-#define NTMP_TBL_VER		GENMASK(7, 0)
-#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
-				 ((a) & NTMP_QUERY_ACT))
+#define NTMP_COMMON_REQ_MSG_DATA_BUFSZ	4
+
+typedef struct __packed { u8 buf[NTMP_COMMON_REQ_MSG_DATA_BUFSZ]; } ntmp_common_req_msg_data_buf;
+
+struct ntmp_common_req_data {
+	u16 update_actions;
+	u8 query_actions;
+	u8 table_version;
 };
 
 struct common_resp_query {
@@ -36,8 +36,8 @@ struct common_resp_nq {
 
 /* Generic structure for request data by entry ID  */
 struct ntmp_req_by_eid {
-	struct common_req_data crd;
-	__le32 entry_id;
+	struct ntmp_common_req_data crd;
+	u32 entry_id;
 };
 
 /* MAC Address Filter Table Request Data Buffer Format of Add action */
-- >8 --

Some remarks:
 - The fact that struct ntmp_common_req_data is an unpacked structure
   now means that the layout of fields is completely decoupled from the
   layout of the data buffer. You can make each field an enum type if
   you want, which I didn't do here.
 - You don't have to access its fields with le32_to_cpu() and friends,
   it's implicitly in CPU endianness.
 - The API is tolerant of the case where the CPU is in a different
   endianness from ENETC.
 - The API protects you against overlapping PACKED_FIELD() definitions,
   and gives a compile-time error if it detects an overlap.
 - The API allows you to define buffers of any size you want, and the
   bit field ranges vary according to the buffer size you chose. Notice
   how you are grouping two fields within the "u8 tblv_qact" field, and
   their offsets are 7-4 and 3-0, respectively, within that u8, but in
   the PACKED_FIELD() definition you can make them 31-28 and 27-24, just
   like in the RM.
 - struct ntmp_req_by_eid and struct ntmp_common_req_data don't have to
   be distinct structures. You can call pack_fields() and pack only a
   subset of the fields of an unpacked structure. Then pack the rest
   with explicit pack() calls, or not pack them at all.

I just want to present this alternative because I believe it offers some
distinct advantages which may be useful here. But note that just
"QUIRK_LITTLE_ENDIAN" may be wrong for NTMP. You need to see whether you
also need QUIRK_LSW32_IS_FIRST or not. For buffers up to 32 bits,
QUIRK_LSW32_IS_FIRST makes no difference, only for buffers larger than that.

> > The question pertains to everything else that is exported to
> > include/linux/fsl/ntmp.h - what the API consumer sees. Is there a real
> > reason to export it? For many structures and macros, the answer seems no.
> > 
> > Even for cases like struct maft_keye_data which are only used by debugfs,
> > it still seems preferable to keep data encapsulation and offer a helper
> > function to retrieve a pointer to the MAC address from the MAFT entry.
> > Then, "struct maft_keye_data;" can simply be declared, without exposing
> > its full definition.
> 
> ntmp_private.h is only used for ntmp driver, I don't want it to be included
> by any enetc files. ntmp.h is used for both enetc and switch drivers, so we
> need to add full definitions of the table data.

And I agree with you, I also don't want ntmp_private.h to be exposed to
the NTMP API consumers, and I wasn't suggesting that. I just want the
NTMP API to spare consumer drivers of the gory details, like for example
the buffer layout of a MAC filtering entry, reserved fields, things like
that. What I was saying is to keep the buffer layout private to
ntmp_private.h, and expose a more abstract data structure to API
consumers.

> > > +struct ntmp_priv {
> > 
> > Would it be better to name this "struct ntmp_client"? I don't really
> > understand the way in which it is "private".
> 
> It refers to some private data of NTMP of different devices (enetc or
> switches). Since the current patch is only a small part of NTMP, many
> members have not been added to the structure. The following is the
> definition in our downstream.
> 
> struct ntmp_priv {
> 	enum netc_dev_type dev_type;
> 	struct netc_cbdrs cbdrs;
> 	u32 errata;
> 
> 	struct ntmp_caps caps;
> 	/* bitmap of table entry ID */
> 	unsigned long *ist_eid_bitmap;
> 	unsigned long *rpt_eid_bitmap;
> 	unsigned long *sgit_eid_bitmap;
> 	unsigned long *isct_eid_bitmap;
> 	unsigned long *sgclt_word_bitmap;
> 	unsigned long *ett_eid_bitmap;
> 	unsigned long *ect_eid_bitmap;
> 	u32 ett_bitmap_size;
> 	u32 ect_bitmap_size;
> 
> 	struct hlist_head flower_list;
> 	struct mutex flower_lock; /* flower_list lock */
> 
> 	u64 (*adjust_base_time)(struct ntmp_priv *priv, u64 bt, u32 ct);
> 	u32 (*get_tgst_free_words)(struct ntmp_priv *priv);
> };

Thank you for posting the downstream layout of struct ntmp_priv which I
was already aware of. What I was saying is that the word "private" means
an aspect of the implementation which is hidden from other code layers.
There's nothing "private" here if the NTMP layer has access to the
definition of this structure. I was asking whether you agree that it's
more adequate to name this structure "ntmp_client", since it represents
the data associated with a consumer of the NTMP API - a NETC SI or (in
the future) the switch. Or some other name. But the word "private" seems
misused.

> > What's the idea with the null entry ID? Why special-case it?
> > 
> 
> Some functions are configured by multiple tables. If a table is
> not needed in the current configuration, we may set its entry
> id to NTMP_NULL_ENTRY_ID, indicating that the table is bypassed.
> For the current patch, this condition can be removed.

Ok, thank you.

> > > +	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];
> > 
> > I think you need to be in a "preemption disabled" / "migration disable"
> > calling context for smp_processor_id() to be reliable. Otherwise, the
> > task can migrate to another CPU as soon as this function returns.
> > 
> 
> It does not matter, we just want to select a command BD ring when all
> command BD rings are busy. So smp_processor_id() is just a parameter,
> we can also use a random number.

Ok.

> > Can you place this dma_wmb() right next to the "*cur_cbd = *cbd" line,
> > to make it obvious that updating the producer index has nothing to do
> > with it? Or is there another reason for this ordering?
> > 
> 
> No special reason for this ordering, I will move it after "*cur_cbd = *cbd".

Thanks, I appreciate it.


From anshuman.khandual at arm.com  Fri Mar 14 05:35:34 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Fri, 14 Mar 2025 18:05:34 +0530
Subject: [PATCH v4] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <20250312-james-cs-kunit-test-v4-1-ae3dd718a26a@linaro.org>
References: <20250312-james-cs-kunit-test-v4-1-ae3dd718a26a@linaro.org>
Message-ID: <48b192c7-4250-4e11-8dcd-b147dd8c0a28@arm.com>

On 3/12/25 16:01, James Clark wrote:
> Add a test to confirm that default sink selection skips over an ETF
> and returns an ETR even if it's further away.
> 
> This also makes it easier to add new unit tests in the future.

The test overall looks good but there are some comments below.

> 
> Reviewed-by: Leo Yan <leo.yan at arm.com>
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
> Changes in v4:
> - Rename etm to src now that it's not CORESIGHT_DEV_SUBTYPE_SOURCE_PROC
> - Remove the now empty src_ops too
> - Fix a rebase mistake in the Makefile that removed CTCU
> - Link to v3: https://lore.kernel.org/r/20250312-james-cs-kunit-test-v3-1-dcfb69730161 at linaro.org
> 
> Changes in v3:
> - Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
>   (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
>   when TRBE sinks are registered. This also removes the need for the
>   fake CPU ID callback.
> - Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test-v2-1-83ba682b976c at linaro.org
> 
> Changes in v2:
> - Let devm free everything rather than doing individual kfrees:
>   "Like with managed drivers, KUnit-managed fake devices are
>   automatically cleaned up when the test finishes, but can be manually
>   cleaned up early with kunit_device_unregister()."
> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
> ---
>  drivers/hwtracing/coresight/Kconfig                |  9 +++
>  drivers/hwtracing/coresight/Makefile               |  1 +
>  drivers/hwtracing/coresight/coresight-core.c       |  1 +
>  .../hwtracing/coresight/coresight-kunit-tests.c    | 74 ++++++++++++++++++++++
>  4 files changed, 85 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index ecd7086a5b83..f064e3d172b3 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>  
>  	  To compile this driver as a module, choose M here: the module will be
>  	  called coresight-dummy.
> +
> +config CORESIGHT_KUNIT_TESTS
> +	  tristate "Enable Coresight unit tests"
> +	  depends on KUNIT
> +	  default KUNIT_ALL_TESTS
> +	  help
> +	    Enable Coresight unit tests. Only useful for development and not
> +	    intended for production.

The description sounds adequate given that more unit tests might be added later.

> +
>  endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 8e62c3150aeb..4e6ea5b05b01 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -53,3 +53,4 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>  obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>  obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>  coresight-ctcu-y := coresight-ctcu-core.o
> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index fb43ef6a3b1f..47af75ba7a00 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>  	}
>  	return csdev->def_sink;
>  }
> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);

This symbol needs exporting given that the kunit test here can also be built
as a module.

>  
>  static int coresight_remove_sink_ref(struct device *dev, void *data)
>  {
> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> new file mode 100644
> index 000000000000..c8f361767c45
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
> @@ -0,0 +1,74 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +#include <kunit/device.h>
> +#include <linux/coresight.h>
> +
> +#include "coresight-priv.h"
> +
> +static struct coresight_device *coresight_test_device(struct device *dev)
> +{
> +	struct coresight_device *csdev = devm_kcalloc(dev, 1,
> +						     sizeof(struct coresight_device),
> +						     GFP_KERNEL);
> +	csdev->pdata = devm_kcalloc(dev, 1,
> +				   sizeof(struct coresight_platform_data),
> +				   GFP_KERNEL);

Guess both these memory allocations gets freed up here automatically
via kunit_device's device framework when the test suit exits ?

> +	return csdev;
> +}
> +
> +static void test_default_sink(struct kunit *test)
> +{
> +	/*
> +	 * Source -> ETF -> ETR -> CATU
> +	 *                   ^
> +	 *                   | default
> +	 */

Should some more random path combinations involving ETR and ETF along with
other coresight devices also be tested where ETR gets selected as default ?

> +	struct device *dev = kunit_device_register(test, "coresight_kunit");
> +	struct coresight_device *src = coresight_test_device(dev),
> +				*etf = coresight_test_device(dev),
> +				*etr = coresight_test_device(dev),
> +				*catu = coresight_test_device(dev);
> +	struct coresight_connection conn = {};
> +
> +	src->type = CORESIGHT_DEV_TYPE_SOURCE;
> +	/*
> +	 * Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
> +	 * a TRBE sink if one is registered.

Probably this should be tested as well i.e when TRBE sink is also available
and it gets picked up as a default.

> +	 */
> +	src->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
> +	etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
> +	etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
> +	etr->type = CORESIGHT_DEV_TYPE_SINK;
> +	etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
> +	catu->type = CORESIGHT_DEV_TYPE_HELPER;
> +
> +	conn.src_dev = src;
> +	conn.dest_dev = etf;
> +	coresight_add_out_conn(dev, src->pdata, &conn);
> +
> +	conn.src_dev = etf;
> +	conn.dest_dev = etr;
> +	coresight_add_out_conn(dev, etf->pdata, &conn);
> +
> +	conn.src_dev = etr;
> +	conn.dest_dev = catu;
> +	coresight_add_out_conn(dev, etr->pdata, &conn);
> +
> +	KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(src), etr);
> +}
> +
> +static struct kunit_case coresight_testcases[] = {
> +	KUNIT_CASE(test_default_sink),
> +	{}
> +};
> +
> +static struct kunit_suite coresight_test_suite = {
> +	.name = "coresight_test_suite",
> +	.test_cases = coresight_testcases,
> +};
> +
> +kunit_test_suites(&coresight_test_suite);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("James Clark <james.clark at linaro.org>");
> +MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
> 
> ---
> base-commit: 3eadce8308bc8d808fd9e3a9d211c84215087451
> change-id: 20250305-james-cs-kunit-test-3af1df2401e6
> 
> Best regards,


From pablo at netfilter.org  Fri Mar 14 05:37:43 2025
From: pablo at netfilter.org (Pablo Neira Ayuso)
Date: Fri, 14 Mar 2025 13:37:43 +0100
Subject: [PATCH v9 nf 00/15] bridge-fastpath and related improvements
In-Reply-To: <02b97708-1214-4fa4-a011-70388cff8f79@gmail.com>
References: <20250305102949.16370-1-ericwouds@gmail.com>
 <897ade0e-a4d0-47d0-8bf7-e5888ef45a61@gmail.com>
 <Z9DKxOnxr1fSv0On@calendula>
 <58cbe875-80e7-4a44-950b-b836b97f3259@gmail.com>
 <Z9IUrL0IHTKQMUvC@calendula>
 <02b97708-1214-4fa4-a011-70388cff8f79@gmail.com>
Message-ID: <Z9QjF5LhavodVA4Y@calendula>

On Thu, Mar 13, 2025 at 07:01:38PM +0100, Eric Woudstra wrote:
> 
> 
> On 3/13/25 12:11 AM, Pablo Neira Ayuso wrote:
> 
> >> What do you suggest?
> > 
> > Probably I can collect 4/15 and 5/15 from this series to be included
> > in the next pull request, let me take a look. But it would be good to
> > have tests for these two patches.
> > 
> 
> These are not most important to bridge-fastpath, but it gives extra
> possibilities. How about concentrating first on patch 2/15 (with 1/15
> removing a warning and 3/15 cleaning up), adding nf_flow_encap_push()
> for xmit direct? It is a vital patch for the bridge-fastpath.

I see cleanup patch 3/15 is a consequence of 2/15, let me take a look.

> Anyway, I will look into writing selftests for conntrack-bridge setup,
> including various vlan setups. This will take me some time, which I
> do not have in abundance, so for that I do not know if I get it done
> before the merge window.

There is tools/testing/selftests/net/netfilter/nft_flowtable.sh that
can possibly be extended to improve coverage.

Thanks.


From ryan.roberts at arm.com  Fri Mar 14 06:12:58 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 13:12:58 +0000
Subject: [PATCH v3 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <3bba7adb-392b-4024-984f-b6f0f0f88629@arm.com>
References: <20250313104111.24196-2-miko.lenczewski@arm.com>
 <20250313104111.24196-3-miko.lenczewski@arm.com>
 <86ikocomvd.wl-maz@kernel.org> <f244c20e-e11c-477b-9487-cb6738c028ca@arm.com>
 <86h63wok11.wl-maz@kernel.org> <4998dd9b-106d-4ca7-be88-5330429dcfe8@arm.com>
 <3bba7adb-392b-4024-984f-b6f0f0f88629@arm.com>
Message-ID: <e36a3e64-5e40-456f-903c-0ac540932e6d@arm.com>

On 14/03/2025 12:33, Suzuki K Poulose wrote:
> On 14/03/2025 09:18, Ryan Roberts wrote:
>> On 13/03/2025 18:36, Marc Zyngier wrote:
>>> On Thu, 13 Mar 2025 18:22:00 +0000,
>>> Ryan Roberts <ryan.roberts at arm.com> wrote:
>>>>
>>>> On 13/03/2025 17:34, Marc Zyngier wrote:
>>>>> On Thu, 13 Mar 2025 10:41:10 +0000,
>>>>> Miko?aj Lenczewski <miko.lenczewski at arm.com> wrote:
>>>>>>
>>>>>> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/
>>>>>> idreg-override.c
>>>>>> index c6b185b885f7..9728faa10390 100644
>>>>>> --- a/arch/arm64/kernel/pi/idreg-override.c
>>>>>> +++ b/arch/arm64/kernel/pi/idreg-override.c
>>>>>> @@ -209,6 +209,7 @@ static const struct ftr_set_desc sw_features
>>>>>> __prel64_initconst = {
>>>>>> ????????? FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
>>>>>> ????????? FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
>>>>>> ????????? FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
>>>>>> +??????? FIELD("nobbml2", ARM64_SW_FEATURE_OVERRIDE_NOBBML2, NULL),
>>>>>> ????????? {}
>>>>>> ????? },
>>>>>> ? };
>>>>>> @@ -246,6 +247,7 @@ static const struct {
>>>>>> ????? { "rodata=off",??????????? "arm64_sw.rodataoff=1" },
>>>>>> ????? { "arm64.nolva",??????? "id_aa64mmfr2.varange=0" },
>>>>>> ????? { "arm64.no32bit_el0",??????? "id_aa64pfr0.el0=1" },
>>>>>> +??? { "arm64.nobbml2",??????? "arm64_sw.nobbml2=1" },
>>>>>
>>>>> Why is that a SW feature? This looks very much like a HW feature to
>>>>> me, and you should instead mask out ID_AA64MMFR2_EL1.BBM, and be done
>>>>> with it. Something like:
>>>>
>>>> I think this implies that we would expect the BBM field to be advertising BBML2
>>>> support normally and we would check for that as part of the cpufeature
>>>> detection. That's how Miko was doing it in v2, but Yang pointed out that
>>>> AmpereOne, which supports BBML2+NOABORT semantics, doesn't actually advertise
>>>> BBML2 in its MMFR2. So we don't want to check that field, and instead rely
>>>> solely on the MIDR allow-list + a command line override. It was me that
>>>> suggested putting that in the SW feature register, and I think that still
>>>> sounds
>>>> like the right solution for this situation?
>>>
>>> I think this is mixing two different things:
>>>
>>> - preventing BBM-L2 from being visible to the kernel: this is what my
>>> ?? suggestion is doing by nuking an architectural feature in the
>>> ?? relevant register
>>>
>>> - random HW not correctly advertising what they are doing: this is an
>>> ?? erratum workaround
>>>
>>> I'd rather we don't conflate the two things, and make them very
>>> explicitly distinct.
>>
>> It all sounds so obvious when you put it like that! :)
>>
>> I'm guessing there is a layer where the workaround can be applied to the
>> sanitised feature registers on a per-cpu basis and that won't affect this global
>> override which will remain as an overlay on top? If so then that sounds perfect
>> (you can probably tell I find the whole feature management framework rather
>> inpeneterable). That workaround would be added as part of Yang's series anyway.
> 
> Unfortunately, there is no easy way to fix this via the normal erratum
> workaround "capability". The sanitised feature registers are handled
> separately (initialised via init_cpu_features() for boot CPU and
> sanitised eachtime via update_cpu_features).
> 
> Also we do not "enable" any capability (i.e. calling cpu_enable())
> until the very end, after the CPUs are all brought up (except for boot CPUs).
> 
> But it may be possible to "fix up" the BBML2 feature in
> cpuinfo_store_*cpu(), without using the "enable" call back.
> 
> Something like:
> 
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 285d7d538342..8c23adbe29f8 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -479,7 +479,11 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
> ??????? info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
> ??????? info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
> ??????? info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
> 
> +??? /*
> +???? * The CPU cap is not detected system wide, but we are able to
> +???? * check if this CPU is affected by the Erratum.
> +???? */
> +?????? if (this_cpu_has_cap(AMPERE_ONE_ERRATUM_BBML2))
> +?????????????? // Fixup? info->reg_id_aa64_mmfr2 with BBML2.
> +
> ??????? info->reg_id_aa64mmfr3 = read_cpuid(ID_AA64MMFR3_EL1);
> ??????? info->reg_id_aa64mmfr4 = read_cpuid(ID_AA64MMFR4_EL1);
> ??????? info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
> ??????? info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
> 

This is the type of thing I was imagining, thanks!

> Suzuki
> 
>>
>> So sounds like we are back to testing MMFR2.BBM in the matches function, with
>> the addition of Maz's proposal above. Sorry for sending you round the houses,
>> Miko.
>>
>> Thanks,
>> Ryan
>>
>>>
>>> Thanks,
>>>
>>> ????M.
>>>
>>
> 



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:29 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:29 +0100
Subject: [PATCH 4/5] media: vcodec: Implement manual request completion
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b@collabora.com>

Rework how requests are completed in the MediaTek VCodec driver, by
implementing the new manual request completion feature, which allows to
keep a request open while allowing to add new bitstream data.
This is useful in this case, because the hardware has a LAT and a core
decode work, after the LAT decode the bitstream isn't required anymore
so the source buffer can be set done and the request stays open until
the core decode work finishes.

Signed-off-by: Sebastian Fricke <sebastian.fricke at collabora.com>
---
 .../mediatek/vcodec/common/mtk_vcodec_cmn_drv.h    | 13 ++++++
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c       |  4 +-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c   | 52 ++++++++++++++++++++++
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h   |  4 ++
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c      | 46 +++++++++----------
 5 files changed, 94 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_cmn_drv.h b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_cmn_drv.h
index 6087e27bd604d24e5d37b48de5bb37eab86fc1ab..81ec5beecfaed239ed70bee3460aae27e476231c 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_cmn_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_cmn_drv.h
@@ -105,6 +105,19 @@ enum mtk_instance_state {
 	MTK_STATE_ABORT = 4,
 };
 
+/**
+ * enum mtk_request_state - Stages of processing a request
+ * MTK_REQUEST_RECEIVED: Hardware prepared for the LAT decode
+ * MTK_REQUEST_DONE_WITH_BITSTREAM: LAT decode finished, the bitstream is not
+ *				    needed anymore
+ * MTK_REQUEST_COMPLETE: CORE decode finished
+ */
+enum mtk_request_state {
+	MTK_REQUEST_RECEIVED = 0,
+	MTK_REQUEST_LAT_DONE = 1,
+	MTK_REQUEST_CORE_DONE = 2,
+};
+
 enum mtk_fmt_type {
 	MTK_FMT_DEC = 0,
 	MTK_FMT_ENC = 1,
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 98838217b97d45ed2b5431fdf87c94e0ff79fc57..036ad191a9c3e644fe99b4ce25d6a089292f1e57 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -889,8 +889,10 @@ void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
 					src_buf->vb2_buf.req_obj.req;
 				v4l2_m2m_buf_done(src_buf,
 						VB2_BUF_STATE_ERROR);
-				if (req)
+				if (req) {
 					v4l2_ctrl_request_complete(req, &ctx->ctrl_hdl);
+					media_request_manual_complete(req);
+				}
 			}
 		}
 		return;
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index 9247d92d431d8570609423156b989878f7901f1c..d9c7aaec0c4515cb73b80c913b1ad5b08392dd18 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -26,6 +26,58 @@
 #include "mtk_vcodec_dec_pm.h"
 #include "../common/mtk_vcodec_intr.h"
 
+const char *state_to_str(enum mtk_request_state state)
+{
+	switch (state) {
+	case MTK_REQUEST_RECEIVED:
+		return "RECEIVED";
+	case MTK_REQUEST_LAT_DONE:
+		return "LAT_DONE";
+	case MTK_REQUEST_CORE_DONE:
+		return "CORE_DONE";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+int mtk_vcodec_complete(struct mtk_vcodec_dec_ctx *ctx, enum mtk_request_state state,
+			enum vb2_buffer_state buffer_state, struct media_request *src_buf_req)
+{
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+
+	mutex_lock(&ctx->lock);
+
+	if (ctx->req_state >= state) {
+		mutex_unlock(&ctx->lock);
+		return -EINVAL;
+	}
+
+	switch (ctx->req_state) {
+	case MTK_REQUEST_RECEIVED:
+		v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl);
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(src_buf, buffer_state);
+		ctx->req_state = MTK_REQUEST_LAT_DONE;
+		if (state == MTK_REQUEST_LAT_DONE)
+			break;
+		fallthrough;
+	case MTK_REQUEST_LAT_DONE:
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(dst_buf, buffer_state);
+		media_request_manual_complete(src_buf_req);
+		ctx->req_state = MTK_REQUEST_CORE_DONE;
+		break;
+	default:
+		break;
+	}
+
+	mtk_v4l2_vdec_dbg(3, ctx, "Switch state from %s to %s.\n",
+			  state_to_str(ctx->req_state), state_to_str(state));
+	ctx->req_state = state;
+	mutex_unlock(&ctx->lock);
+	return 0;
+}
+
 static int mtk_vcodec_get_hw_count(struct mtk_vcodec_dec_ctx *ctx, struct mtk_vcodec_dec_dev *dev)
 {
 	switch (dev->vdec_pdata->hw_arch) {
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
index ac568ed14fa257d25b533b6fd6b3cd341227ecc2..21c2301363d0151ba3cf384a2a32fff9f5d46034 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
@@ -185,6 +185,7 @@ struct mtk_vcodec_dec_ctx {
 	struct mtk_q_data q_data[2];
 	int id;
 	enum mtk_instance_state state;
+	enum mtk_request_state req_state;
 
 	const struct vdec_common_if *dec_if;
 	void *drv_handle;
@@ -326,6 +327,9 @@ wake_up_dec_ctx(struct mtk_vcodec_dec_ctx *ctx, unsigned int reason, unsigned in
 	wake_up_interruptible(&ctx->queue[hw_id]);
 }
 
+int mtk_vcodec_complete(struct mtk_vcodec_dec_ctx *ctx, enum mtk_request_state state,
+			enum vb2_buffer_state buffer_state, struct media_request *src_buf_req);
+
 #define mtk_vdec_err(ctx, fmt, args...)                               \
 	mtk_vcodec_err((ctx)->id, (ctx)->dev->plat_dev, fmt, ##args)
 
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index afa224da0f4165cf5701d6861f1f787c6317bfe4..9187d7bcfc8aea17f3fc98d94419777d8026db51 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -247,7 +247,6 @@ static const struct v4l2_frmsize_stepwise stepwise_fhd = {
 static void mtk_vdec_stateless_cap_to_disp(struct mtk_vcodec_dec_ctx *ctx, int error,
 					   struct media_request *src_buf_req)
 {
-	struct vb2_v4l2_buffer *vb2_dst;
 	enum vb2_buffer_state state;
 
 	if (error)
@@ -255,17 +254,7 @@ static void mtk_vdec_stateless_cap_to_disp(struct mtk_vcodec_dec_ctx *ctx, int e
 	else
 		state = VB2_BUF_STATE_DONE;
 
-	vb2_dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
-	if (vb2_dst) {
-		v4l2_m2m_buf_done(vb2_dst, state);
-		mtk_v4l2_vdec_dbg(2, ctx, "free frame buffer id:%d to done list",
-				  vb2_dst->vb2_buf.index);
-	} else {
-		mtk_v4l2_vdec_err(ctx, "dst buffer is NULL");
-	}
-
-	if (src_buf_req)
-		v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl);
+	mtk_vcodec_complete(ctx, MTK_REQUEST_CORE_DONE, state, src_buf_req);
 }
 
 static struct vdec_fb *vdec_get_cap_buffer(struct mtk_vcodec_dec_ctx *ctx)
@@ -308,6 +297,7 @@ static void vb2ops_vdec_buf_request_complete(struct vb2_buffer *vb)
 	struct mtk_vcodec_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 
 	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_hdl);
+	media_request_manual_complete(vb->req_obj.req);
 }
 
 static void mtk_vdec_worker(struct work_struct *work)
@@ -358,12 +348,17 @@ static void mtk_vdec_worker(struct work_struct *work)
 	else
 		mtk_v4l2_vdec_err(ctx, "vb2 buffer media request is NULL");
 
+	mutex_lock(&ctx->lock);
+	ctx->req_state = MTK_REQUEST_RECEIVED;
+	mutex_unlock(&ctx->lock);
+
 	ret = vdec_if_decode(ctx, bs_src, NULL, &res_chg);
+
 	if (ret && ret != -EAGAIN) {
 		mtk_v4l2_vdec_err(ctx,
-				  "[%d] decode src_buf[%d] sz=0x%zx pts=%llu ret=%d res_chg=%d",
+				  "[%d] decode src_buf[%d] sz=0x%zx pts=%llu res_chg=%d ret=%d",
 				  ctx->id, vb2_src->index, bs_src->size,
-				  vb2_src->timestamp, ret, res_chg);
+				  vb2_src->timestamp, res_chg, ret);
 		if (ret == -EIO) {
 			mutex_lock(&ctx->lock);
 			dec_buf_src->error = true;
@@ -372,18 +367,15 @@ static void mtk_vdec_worker(struct work_struct *work)
 	}
 
 	state = ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE;
+	if (ret != -EAGAIN)
+		mtk_vcodec_complete(ctx, MTK_REQUEST_LAT_DONE, state, src_buf_req);
+
 	if (!IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch) ||
 	    ctx->current_codec == V4L2_PIX_FMT_VP8_FRAME) {
-		v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx, state);
-		if (src_buf_req)
-			v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl);
-	} else {
-		if (ret != -EAGAIN) {
-			v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-			v4l2_m2m_buf_done(vb2_v4l2_src, state);
-		}
-		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_vcodec_complete(ctx, MTK_REQUEST_CORE_DONE, state, src_buf_req);
 	}
+
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
 }
 
 static void vb2ops_vdec_stateless_buf_queue(struct vb2_buffer *vb)
@@ -731,9 +723,15 @@ static int fops_media_request_validate(struct media_request *mreq)
 	return vb2_request_validate(mreq);
 }
 
+static void fops_media_request_queue(struct media_request *mreq)
+{
+	media_request_mark_manual_completion(mreq);
+	v4l2_m2m_request_queue(mreq);
+}
+
 const struct media_device_ops mtk_vcodec_media_ops = {
 	.req_validate	= fops_media_request_validate,
-	.req_queue	= v4l2_m2m_request_queue,
+	.req_queue	= fops_media_request_queue,
 };
 
 static void mtk_vcodec_add_formats(unsigned int fourcc,

-- 
2.34.1



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:30 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:30 +0100
Subject: [PATCH 5/5] media: mtk-vcodec: Don't try to decode 422/444 VP9
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-5-5e277a3d695b@collabora.com>

From: Nicolas Dufresne <nicolas.dufresne at collabora.com>

This is not supported by the hardware and trying to decode
these leads to LAT timeout errors.

Signed-off-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index 9187d7bcfc8aea17f3fc98d94419777d8026db51..3dbd251034b85e521c3c93538d9ecf9078ef3820 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -496,6 +496,12 @@ static int mtk_vdec_s_ctrl(struct v4l2_ctrl *ctrl)
 			mtk_v4l2_vdec_err(ctx, "VP9: bit_depth:%d", frame->bit_depth);
 			return -EINVAL;
 		}
+
+		if (!(frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) ||
+		    !(frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)) {
+			mtk_v4l2_vdec_err(ctx, "VP9: only 420 subsampling is supported");
+			return -EINVAL;
+		}
 		break;
 	case V4L2_CID_STATELESS_AV1_SEQUENCE:
 		seq = (struct v4l2_ctrl_av1_sequence *)hdr_ctrl->p_new.p;

-- 
2.34.1



From ryan.roberts at arm.com  Fri Mar 14 06:29:05 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 13:29:05 +0000
Subject: [v3 PATCH 4/6] arm64: mm: support large block mapping when
 rodata=full
In-Reply-To: <20250304222018.615808-5-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-5-yang@os.amperecomputing.com>
Message-ID: <f745ab79-55e7-406a-a3cb-9f85fa461444@arm.com>

On 04/03/2025 22:19, Yang Shi wrote:
> When rodata=full is specified, kernel linear mapping has to be mapped at
> PTE level since large page table can't be split due to break-before-make
> rule on ARM64.
> 
> This resulted in a couple of problems:
>   - performance degradation
>   - more TLB pressure
>   - memory waste for kernel page table
> 
> With FEAT_BBM level 2 support, splitting large block page table to
> smaller ones doesn't need to make the page table entry invalid anymore.
> This allows kernel split large block mapping on the fly.
> 
> Add kernel page table split support and use large block mapping by
> default when FEAT_BBM level 2 is supported for rodata=full.  When
> changing permissions for kernel linear mapping, the page table will be
> split to PTE level.
> 
> The machine without FEAT_BBM level 2 will fallback to have kernel linear
> mapping PTE-mapped when rodata=full.
> 
> With this we saw significant performance boost with some benchmarks and
> much less memory consumption on my AmpereOne machine (192 cores, 1P) with
> 256GB memory.
> 
> * Memory use after boot
> Before:
> MemTotal:       258988984 kB
> MemFree:        254821700 kB
> 
> After:
> MemTotal:       259505132 kB
> MemFree:        255410264 kB
> 
> Around 500MB more memory are free to use.  The larger the machine, the
> more memory saved.
> 
> * Memcached
> We saw performance degradation when running Memcached benchmark with
> rodata=full vs rodata=on.  Our profiling pointed to kernel TLB pressure.
> With this patchset we saw ops/sec is increased by around 3.5%, P99
> latency is reduced by around 9.6%.
> The gain mainly came from reduced kernel TLB misses.  The kernel TLB
> MPKI is reduced by 28.5%.
> 
> The benchmark data is now on par with rodata=on too.
> 
> * Disk encryption (dm-crypt) benchmark
> Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
> encryption (by dm-crypt).
> fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
>     --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
>     --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
>     --name=iops-test-job --eta-newline=1 --size 100G
> 
> The IOPS is increased by 90% - 150% (the variance is high, but the worst
> number of good case is around 90% more than the best number of bad case).
> The bandwidth is increased and the avg clat is reduced proportionally.
> 
> * Sequential file read
> Read 100G file sequentially on XFS (xfs_io read with page cache populated).
> The bandwidth is increased by 150%.
> 
> Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
> ---
>  arch/arm64/include/asm/cpufeature.h |  10 ++
>  arch/arm64/include/asm/mmu.h        |   1 +
>  arch/arm64/include/asm/pgtable.h    |   7 +-
>  arch/arm64/kernel/cpufeature.c      |   2 +-
>  arch/arm64/mm/mmu.c                 | 169 +++++++++++++++++++++++++++-
>  arch/arm64/mm/pageattr.c            |  35 +++++-
>  6 files changed, 211 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 108ef3fbbc00..e24edc32b0bd 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -871,6 +871,16 @@ static inline bool system_supports_bbml2_noabort(void)
>  	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
>  }
>  
> +bool cpu_has_bbml2_noabort(unsigned int cpu_midr);
> +/*
> + * Called at early boot stage on boot CPU before cpu info and cpu feature
> + * are ready.
> + */
> +static inline bool bbml2_noabort_available(void)
> +{
> +	return cpu_has_bbml2_noabort(read_cpuid_id());

You'll want to incorporate the IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) and
arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2) checks from
Miko's new series to avoid block mappings when BBML2 is disabled. (that second
check will change a bit based on Maz's feedback against Miko's v3).

Hopefully we can factor out into a common helper that is used by Miko's stuff too?

> +}
> +
>  int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>  bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>  
> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> index 662471cfc536..d658a33df266 100644
> --- a/arch/arm64/include/asm/mmu.h
> +++ b/arch/arm64/include/asm/mmu.h
> @@ -71,6 +71,7 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
>  			       pgprot_t prot, bool page_mappings_only);
>  extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
>  extern void mark_linear_text_alias_ro(void);
> +extern int split_linear_mapping(unsigned long start, unsigned long end);
>  
>  /*
>   * This check is triggered during the early boot before the cpufeature
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index 0b2a2ad1b9e8..ed2fc1dcf7ae 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -749,7 +749,7 @@ static inline bool in_swapper_pgdir(void *addr)
>  	        ((unsigned long)swapper_pg_dir & PAGE_MASK);
>  }
>  
> -static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
> +static inline void __set_pmd_nosync(pmd_t *pmdp, pmd_t pmd)
>  {
>  #ifdef __PAGETABLE_PMD_FOLDED
>  	if (in_swapper_pgdir(pmdp)) {
> @@ -759,6 +759,11 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
>  #endif /* __PAGETABLE_PMD_FOLDED */
>  
>  	WRITE_ONCE(*pmdp, pmd);
> +}
> +
> +static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
> +{
> +	__set_pmd_nosync(pmdp, pmd);
>  
>  	if (pmd_valid(pmd)) {
>  		dsb(ishst);
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index bf3df8407ca3..d39637d5aeab 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2176,7 +2176,7 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>  	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>  }
>  
> -static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> +bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>  {
>  	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
>  	 * as possible. This list is therefore an allow-list of known-good
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index dccf0877285b..ad0f1cc55e3a 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -45,6 +45,7 @@
>  #define NO_BLOCK_MAPPINGS	BIT(0)
>  #define NO_CONT_MAPPINGS	BIT(1)
>  #define NO_EXEC_MAPPINGS	BIT(2)	/* assumes FEAT_HPDS is not used */
> +#define SPLIT_MAPPINGS		BIT(3)
>  
>  u64 kimage_voffset __ro_after_init;
>  EXPORT_SYMBOL(kimage_voffset);
> @@ -166,6 +167,73 @@ static void init_clear_pgtable(void *table)
>  	dsb(ishst);
>  }
>  
> +static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
> +		     phys_addr_t (*pgtable_alloc)(int))
> +{
> +	unsigned long pfn;
> +	pgprot_t prot;
> +	phys_addr_t pte_phys;
> +	pte_t *ptep;
> +
> +	if (!pmd_leaf(pmdval))
> +		return 0;
> +
> +	pfn = pmd_pfn(pmdval);
> +	prot = pmd_pgprot(pmdval);
> +
> +	pte_phys = pgtable_alloc(PAGE_SHIFT);
> +	if (!pte_phys)
> +		return -ENOMEM;
> +
> +	ptep = (pte_t *)phys_to_virt(pte_phys);
> +	init_clear_pgtable(ptep);

No need for this, you're about to fill the table with ptes so clearing it is a
waste of time.

> +	prot = __pgprot(pgprot_val(prot) | PTE_TYPE_PAGE);

This happen to work for D64 pgtables because of the way the bits are arranged.
But it won't work for D128 (when we get there). We are in the process of
cleaning up the code base to make it D128 ready. So let's fix this now:

	prot = __pgprot(pgprot_val(prot) & ~PMD_TYPE_MASK) | PTE_TYPE_PAGE);

nit: I'd move this up, next to the "prot = pmd_pgprot(pmdval);" line.

> +	for (int i = 0; i < PTRS_PER_PTE; i++, ptep++)
> +		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));

nit: you're incrementing ptep but adding i to pfn. Why not just increment pfn too?

> +
> +	dsb(ishst);
> +
> +	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(pte_phys),
> +		__pgprot(PMD_TYPE_TABLE)));

You're missing some required pgprot flags and it would be better to follow what
alloc_init_cont_pte() does in general. Something like:

	pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
	if (flags & NO_EXEC_MAPPINGS)
		pmdval |= PMD_TABLE_PXN;
	__pmd_populate(pmdp, pte_phys, pmdval);

> +
> +	return 0;
> +}
> +
> +static int split_pud(pud_t *pudp, pud_t pudval,
> +		     phys_addr_t (*pgtable_alloc)(int))

All the same comments for split_pmd() apply here too.

> +{
> +	unsigned long pfn;
> +	pgprot_t prot;
> +	pmd_t *pmdp;
> +	phys_addr_t pmd_phys;
> +	unsigned int step;
> +
> +	if (!pud_leaf(pudval))
> +		return 0;
> +
> +	pfn = pud_pfn(pudval);
> +	prot = pud_pgprot(pudval);
> +	step = PMD_SIZE >> PAGE_SHIFT;
> +
> +	pmd_phys = pgtable_alloc(PMD_SHIFT);
> +	if (!pmd_phys)
> +		return -ENOMEM;
> +
> +	pmdp = (pmd_t *)phys_to_virt(pmd_phys);
> +	init_clear_pgtable(pmdp);
> +	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
> +		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
> +		pfn += step;
> +	}
> +
> +	dsb(ishst);
> +
> +	set_pud(pudp, pfn_pud(__phys_to_pfn(pmd_phys),
> +		__pgprot(PUD_TYPE_TABLE)));
> +
> +	return 0;
> +}
> +
>  static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
>  		     phys_addr_t phys, pgprot_t prot)
>  {
> @@ -251,12 +319,21 @@ static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>  {
>  	unsigned long next;
>  	int ret = 0;
> +	bool split = flags & SPLIT_MAPPINGS;
>  
>  	do {
>  		pmd_t old_pmd = READ_ONCE(*pmdp);
>  
>  		next = pmd_addr_end(addr, end);
>  
> +		if (split) {

I think this should be:

		if (flags & SPLIT_MAPPINGS &&
		    pmd_leaf(old_pmd) &&
		    next < addr + PMD_SIZE) {

So we only attempt a split if its a leaf and the leaf is not fully contained by
the range. Your current code is always splitting even if the block mapping is
fully contained which seems a waste. And if the pmd is not a leaf (either not
present or a table) split_pmd will currently do nothing and return 0, so there
is no opportunity to install mappings or visit the ptes.

> +			ret = split_pmd(pmdp, old_pmd, pgtable_alloc);

But... do we need the special split_pmd() and split_pud() functions at all?
Can't we just allocate a new table here, then let the existing code populate it,
then replace the block mapping with the table mapping? Same goes for huge puds.
If you take this approach, I think a lot of the code below will significantly
simplify.

> +			if (ret)
> +				break;
> +
> +			continue;
> +		}
> +
>  		/* try section mapping first */
>  		if (((addr | next | phys) & ~PMD_MASK) == 0 &&
>  		    (flags & NO_BLOCK_MAPPINGS) == 0) {

You'll want to modify this last bit to avoid setting up a block mapping if we
are trying to split?

		    (flags & (NO_BLOCK_MAPPINGS | SPLIT_MAPPINGS) == 0) {

Or perhaps it's an error to call this without NO_BLOCK_MAPPINGS if
SPLIT_MAPPINGS is specified? Or perhaps we don't even need SPLIT_MAPPINGS, and
NO_BLOCK_MAPPINGS means we will split if we find any block mappings? (similarly
for NO_CONT_MAPPINGS)?

> @@ -292,11 +369,19 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>  	int ret = 0;
>  	pud_t pud = READ_ONCE(*pudp);
>  	pmd_t *pmdp;
> +	bool split = flags & SPLIT_MAPPINGS;
>  
>  	/*
>  	 * Check for initial section mappings in the pgd/pud.
>  	 */
>  	BUG_ON(pud_sect(pud));
> +
> +	if (split) {
> +		BUG_ON(pud_none(pud));
> +		pmdp = pmd_offset(pudp, addr);
> +		goto split_pgtable;
> +	}
> +
>  	if (pud_none(pud)) {
>  		pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
>  		phys_addr_t pmd_phys;
> @@ -316,6 +401,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>  		pmdp = pmd_set_fixmap_offset(pudp, addr);
>  	}
>  
> +split_pgtable:
>  	do {
>  		pgprot_t __prot = prot;
>  
> @@ -334,7 +420,8 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>  		phys += next - addr;
>  	} while (addr = next, addr != end);
>  
> -	pmd_clear_fixmap();
> +	if (!split)
> +		pmd_clear_fixmap();
>  
>  	return ret;
>  }
> @@ -348,6 +435,13 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  	int ret = 0;
>  	p4d_t p4d = READ_ONCE(*p4dp);
>  	pud_t *pudp;
> +	bool split = flags & SPLIT_MAPPINGS;
> +
> +	if (split) {
> +		BUG_ON(p4d_none(p4d));
> +		pudp = pud_offset(p4dp, addr);
> +		goto split_pgtable;
> +	}
>  
>  	if (p4d_none(p4d)) {
>  		p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
> @@ -368,11 +462,25 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  		pudp = pud_set_fixmap_offset(p4dp, addr);
>  	}
>  
> +split_pgtable:
>  	do {
>  		pud_t old_pud = READ_ONCE(*pudp);
>  
>  		next = pud_addr_end(addr, end);
>  
> +		if (split) {
> +			ret = split_pud(pudp, old_pud, pgtable_alloc);
> +			if (ret)
> +				break;
> +
> +			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
> +						  pgtable_alloc, flags);
> +			if (ret)
> +				break;
> +
> +			continue;
> +		}
> +
>  		/*
>  		 * For 4K granule only, attempt to put down a 1GB block
>  		 */
> @@ -399,7 +507,8 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  		phys += next - addr;
>  	} while (pudp++, addr = next, addr != end);
>  
> -	pud_clear_fixmap();
> +	if (!split)
> +		pud_clear_fixmap();
>  
>  	return ret;
>  }
> @@ -413,6 +522,13 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  	int ret = 0;
>  	pgd_t pgd = READ_ONCE(*pgdp);
>  	p4d_t *p4dp;
> +	bool split = flags & SPLIT_MAPPINGS;
> +
> +	if (split) {
> +		BUG_ON(pgd_none(pgd));
> +		p4dp = p4d_offset(pgdp, addr);
> +		goto split_pgtable;
> +	}
>  
>  	if (pgd_none(pgd)) {
>  		pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF;
> @@ -433,6 +549,7 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  		p4dp = p4d_set_fixmap_offset(pgdp, addr);
>  	}
>  
> +split_pgtable:
>  	do {
>  		p4d_t old_p4d = READ_ONCE(*p4dp);
>  
> @@ -449,7 +566,8 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>  		phys += next - addr;
>  	} while (p4dp++, addr = next, addr != end);
>  
> -	p4d_clear_fixmap();
> +	if (!split)
> +		p4d_clear_fixmap();
>  
>  	return ret;
>  }
> @@ -546,6 +664,23 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
>  	return pa;
>  }
>  
> +int split_linear_mapping(unsigned long start, unsigned long end)
> +{
> +	int ret = 0;
> +
> +	if (!system_supports_bbml2_noabort())
> +		return 0;
> +
> +	mmap_write_lock(&init_mm);
> +	ret = __create_pgd_mapping_locked(init_mm.pgd, virt_to_phys((void *)start),
> +					  start, (end - start), __pgprot(0),
> +					  __pgd_pgtable_alloc, SPLIT_MAPPINGS);
> +	mmap_write_unlock(&init_mm);
> +	flush_tlb_kernel_range(start, end);
> +
> +	return ret;
> +}
> +
>  /*
>   * This function can only be used to modify existing table entries,
>   * without allocating new levels of table. Note that this permits the
> @@ -665,6 +800,24 @@ static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) {
>  
>  #endif /* CONFIG_KFENCE */
>  
> +static inline bool force_pte_mapping(void)
> +{
> +	/*
> +	 * Can't use cpufeature API to determine whether BBML2 supported
> +	 * or not since cpufeature have not been finalized yet.
> +	 *
> +	 * Checking the boot CPU only for now.  If the boot CPU has
> +	 * BBML2, paint linear mapping with block mapping.  If it turns
> +	 * out the secondary CPUs don't support BBML2 once cpufeature is
> +	 * fininalized, the linear mapping will be repainted with PTE
> +	 * mapping.
> +	 */
> +	return (rodata_full && !bbml2_noabort_available()) ||
> +		debug_pagealloc_enabled() ||
> +		arm64_kfence_can_set_direct_map() ||
> +		is_realm_world();
> +}
> +
>  static void __init map_mem(pgd_t *pgdp)
>  {
>  	static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN);
> @@ -690,9 +843,12 @@ static void __init map_mem(pgd_t *pgdp)
>  
>  	early_kfence_pool = arm64_kfence_alloc_pool();
>  
> -	if (can_set_direct_map())
> +	if (force_pte_mapping())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> +	if (rodata_full)
> +		flags |= NO_CONT_MAPPINGS;
> +
>  	/*
>  	 * Take care not to create a writable alias for the
>  	 * read-only text and rodata sections of the kernel image.
> @@ -1388,9 +1544,12 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  
>  	VM_BUG_ON(!mhp_range_allowed(start, size, true));
>  
> -	if (can_set_direct_map())
> +	if (force_pte_mapping())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> +	if (rodata_full)
> +		flags |= NO_CONT_MAPPINGS;
> +
>  	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
>  			     size, params->pgprot, __pgd_pgtable_alloc,
>  			     flags);
> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
> index 39fd1f7ff02a..5d42d87ea7e1 100644
> --- a/arch/arm64/mm/pageattr.c
> +++ b/arch/arm64/mm/pageattr.c
> @@ -10,6 +10,7 @@
>  #include <linux/vmalloc.h>
>  
>  #include <asm/cacheflush.h>
> +#include <asm/mmu.h>
>  #include <asm/pgtable-prot.h>
>  #include <asm/set_memory.h>
>  #include <asm/tlbflush.h>
> @@ -80,8 +81,9 @@ static int change_memory_common(unsigned long addr, int numpages,
>  	unsigned long start = addr;
>  	unsigned long size = PAGE_SIZE * numpages;
>  	unsigned long end = start + size;
> +	unsigned long l_start;
>  	struct vm_struct *area;
> -	int i;
> +	int i, ret;
>  
>  	if (!PAGE_ALIGNED(addr)) {
>  		start &= PAGE_MASK;
> @@ -118,7 +120,12 @@ static int change_memory_common(unsigned long addr, int numpages,
>  	if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
>  			    pgprot_val(clear_mask) == PTE_RDONLY)) {
>  		for (i = 0; i < area->nr_pages; i++) {
> -			__change_memory_common((u64)page_address(area->pages[i]),
> +			l_start = (u64)page_address(area->pages[i]);
> +			ret = split_linear_mapping(l_start, l_start + PAGE_SIZE);

This isn't quite aligned with how I was thinking about it. You still have 2
passes here; one to split the range to base pages, then another to modify the
permissions.

I was thinking we could use the table walker in mmu.c to achieve 2 benefits:

  - Do both operations in a single pass (a bit like how calling
update_mapping_prot() will update the protections on an existing mapping, and
the table walker will split when it comes across a huge page)

  - Only split when needed; if the whole huge page is contained within the
range, then there is no need to split in the first place.

We could then split vmalloc regions for free using this infrastructure too.

Although there is a wrinkle that the mmu.c table walker only accepts a pgprot
and can't currently handle a set_mask/clear_mask. I guess that could be added,
but it starts to get a bit busy. I think this generic infra would be useful
though. What do you think?

[...]

Thanks,
Ryan



From ryan.roberts at arm.com  Fri Mar 14 06:33:06 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Fri, 14 Mar 2025 13:33:06 +0000
Subject: [v3 PATCH 5/6] arm64: mm: support split CONT mappings
In-Reply-To: <20250304222018.615808-6-yang@os.amperecomputing.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-6-yang@os.amperecomputing.com>
Message-ID: <fe8ced5d-c9d8-479b-9088-e0294565cb95@arm.com>

On 04/03/2025 22:19, Yang Shi wrote:
> Add split CONT mappings support in order to support CONT mappings for
> direct map.  This should help reduce TLB pressure further.
> 
> When splitting PUD, all PMDs will have CONT bit set since the leaf PUD
> must be naturally aligned.  When splitting PMD, all PTEs will have CONT
> bit set since the leaf PMD must be naturally aligned too, but the PMDs
> in the cont range of split PMD will have CONT bit cleared.  Splitting
> CONT PTEs by clearing CONT bit for all PTEs in the range.

My expectation is that this patch is not needed if you take the approach of
reusing the existing code to generate the new lower parts of the hierachy as
suggested in the previous patch.

Thanks,
Ryan

> 
> Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
> ---
>  arch/arm64/include/asm/pgtable.h |  5 ++
>  arch/arm64/mm/mmu.c              | 82 ++++++++++++++++++++++++++------
>  arch/arm64/mm/pageattr.c         |  2 +
>  3 files changed, 75 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index ed2fc1dcf7ae..3c6ef47f5813 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -290,6 +290,11 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
>  	return __pmd(pmd_val(pmd) | PMD_SECT_CONT);
>  }
>  
> +static inline pmd_t pmd_mknoncont(pmd_t pmd)
> +{
> +	return __pmd(pmd_val(pmd) & ~PMD_SECT_CONT);
> +}
> +
>  static inline pte_t pte_mkdevmap(pte_t pte)
>  {
>  	return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index ad0f1cc55e3a..d4dfeabc80e9 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -167,19 +167,36 @@ static void init_clear_pgtable(void *table)
>  	dsb(ishst);
>  }
>  
> +static void split_cont_pte(pte_t *ptep)
> +{
> +	pte_t *_ptep = PTR_ALIGN_DOWN(ptep, sizeof(*ptep) * CONT_PTES);
> +	pte_t _pte;
> +	for (int i = 0; i < CONT_PTES; i++, _ptep++) {
> +		_pte = READ_ONCE(*_ptep);
> +		_pte = pte_mknoncont(_pte);
> +		__set_pte_nosync(_ptep, _pte);
> +	}
> +
> +	dsb(ishst);
> +	isb();
> +}
> +
>  static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
> -		     phys_addr_t (*pgtable_alloc)(int))
> +		     phys_addr_t (*pgtable_alloc)(int), int flags)
>  {
>  	unsigned long pfn;
>  	pgprot_t prot;
>  	phys_addr_t pte_phys;
>  	pte_t *ptep;
> +	bool cont;
> +	int i;
>  
>  	if (!pmd_leaf(pmdval))
>  		return 0;
>  
>  	pfn = pmd_pfn(pmdval);
>  	prot = pmd_pgprot(pmdval);
> +	cont = pgprot_val(prot) & PTE_CONT;
>  
>  	pte_phys = pgtable_alloc(PAGE_SHIFT);
>  	if (!pte_phys)
> @@ -188,11 +205,27 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
>  	ptep = (pte_t *)phys_to_virt(pte_phys);
>  	init_clear_pgtable(ptep);
>  	prot = __pgprot(pgprot_val(prot) | PTE_TYPE_PAGE);
> -	for (int i = 0; i < PTRS_PER_PTE; i++, ptep++)
> +
> +	/* It must be naturally aligned if PMD is leaf */
> +	if ((flags & NO_CONT_MAPPINGS) == 0)
> +		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
> +
> +	for (i = 0; i < PTRS_PER_PTE; i++, ptep++)
>  		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));
>  
>  	dsb(ishst);
>  
> +	/* Clear CONT bit for the PMDs in the range */
> +	if (cont) {
> +		pmd_t *_pmdp, _pmd;
> +		_pmdp = PTR_ALIGN_DOWN(pmdp, sizeof(*pmdp) * CONT_PMDS);
> +		for (i = 0; i < CONT_PMDS; i++, _pmdp++) {
> +			_pmd = READ_ONCE(*_pmdp);
> +			_pmd = pmd_mknoncont(_pmd);
> +			set_pmd(_pmdp, _pmd);
> +		}
> +	}
> +
>  	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(pte_phys),
>  		__pgprot(PMD_TYPE_TABLE)));
>  
> @@ -200,7 +233,7 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
>  }
>  
>  static int split_pud(pud_t *pudp, pud_t pudval,
> -		     phys_addr_t (*pgtable_alloc)(int))
> +		     phys_addr_t (*pgtable_alloc)(int), int flags)
>  {
>  	unsigned long pfn;
>  	pgprot_t prot;
> @@ -221,6 +254,11 @@ static int split_pud(pud_t *pudp, pud_t pudval,
>  
>  	pmdp = (pmd_t *)phys_to_virt(pmd_phys);
>  	init_clear_pgtable(pmdp);
> +
> +	/* It must be naturally aligned if PUD is leaf */
> +	if ((flags & NO_CONT_MAPPINGS) == 0)
> +		prot = __pgprot(pgprot_val(prot) | PTE_CONT);
> +
>  	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
>  		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
>  		pfn += step;
> @@ -235,11 +273,18 @@ static int split_pud(pud_t *pudp, pud_t pudval,
>  }
>  
>  static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
> -		     phys_addr_t phys, pgprot_t prot)
> +		     phys_addr_t phys, pgprot_t prot, int flags)
>  {
>  	do {
>  		pte_t old_pte = __ptep_get(ptep);
>  
> +		if (flags & SPLIT_MAPPINGS) {
> +			if (pte_cont(old_pte))
> +				split_cont_pte(ptep);
> +
> +			continue;
> +		}
> +
>  		/*
>  		 * Required barriers to make this visible to the table walker
>  		 * are deferred to the end of alloc_init_cont_pte().
> @@ -266,8 +311,16 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  	unsigned long next;
>  	pmd_t pmd = READ_ONCE(*pmdp);
>  	pte_t *ptep;
> +	bool split = flags & SPLIT_MAPPINGS;
>  
>  	BUG_ON(pmd_sect(pmd));
> +
> +	if (split) {
> +		BUG_ON(pmd_none(pmd));
> +		ptep = pte_offset_kernel(pmdp, addr);
> +		goto split_pgtable;
> +	}
> +
>  	if (pmd_none(pmd)) {
>  		pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
>  		phys_addr_t pte_phys;
> @@ -287,6 +340,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  		ptep = pte_set_fixmap_offset(pmdp, addr);
>  	}
>  
> +split_pgtable:
>  	do {
>  		pgprot_t __prot = prot;
>  
> @@ -297,7 +351,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  		    (flags & NO_CONT_MAPPINGS) == 0)
>  			__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>  
> -		init_pte(ptep, addr, next, phys, __prot);
> +		init_pte(ptep, addr, next, phys, __prot, flags);
>  
>  		ptep += pte_index(next) - pte_index(addr);
>  		phys += next - addr;
> @@ -308,7 +362,8 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>  	 * ensure that all previous pgtable writes are visible to the table
>  	 * walker.
>  	 */
> -	pte_clear_fixmap();
> +	if (!split)
> +		pte_clear_fixmap();
>  
>  	return 0;
>  }
> @@ -327,7 +382,12 @@ static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>  		next = pmd_addr_end(addr, end);
>  
>  		if (split) {
> -			ret = split_pmd(pmdp, old_pmd, pgtable_alloc);
> +			ret = split_pmd(pmdp, old_pmd, pgtable_alloc, flags);
> +			if (ret)
> +				break;
> +
> +			ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot,
> +						  pgtable_alloc, flags);
>  			if (ret)
>  				break;
>  
> @@ -469,7 +529,7 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>  		next = pud_addr_end(addr, end);
>  
>  		if (split) {
> -			ret = split_pud(pudp, old_pud, pgtable_alloc);
> +			ret = split_pud(pudp, old_pud, pgtable_alloc, flags);
>  			if (ret)
>  				break;
>  
> @@ -846,9 +906,6 @@ static void __init map_mem(pgd_t *pgdp)
>  	if (force_pte_mapping())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> -	if (rodata_full)
> -		flags |= NO_CONT_MAPPINGS;
> -
>  	/*
>  	 * Take care not to create a writable alias for the
>  	 * read-only text and rodata sections of the kernel image.
> @@ -1547,9 +1604,6 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  	if (force_pte_mapping())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> -	if (rodata_full)
> -		flags |= NO_CONT_MAPPINGS;
> -
>  	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
>  			     size, params->pgprot, __pgd_pgtable_alloc,
>  			     flags);
> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
> index 5d42d87ea7e1..25c068712cb5 100644
> --- a/arch/arm64/mm/pageattr.c
> +++ b/arch/arm64/mm/pageattr.c
> @@ -43,6 +43,8 @@ static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
>  	struct page_change_data *cdata = data;
>  	pte_t pte = __ptep_get(ptep);
>  
> +	BUG_ON(pte_cont(pte));
> +
>  	pte = clear_pte_bit(pte, cdata->clear_mask);
>  	pte = set_pte_bit(pte, cdata->set_mask);
>  



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:26 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:26 +0100
Subject: [PATCH 1/5] media: mc: add manual request completion
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-1-5e277a3d695b@collabora.com>

From: Hans Verkuil <hverkuil at xs4all.nl>

By default when the last request object is completed, the whole
request completes as well.

But sometimes you want to manually complete a request in a driver,
so add a manual complete mode for this.

In req_queue the driver marks the request for manual completion by
calling media_request_mark_manual_completion, and when the driver
wants to manually complete the request it calls
media_request_manual_complete().

Signed-off-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
---
 drivers/media/mc/mc-request.c | 38 ++++++++++++++++++++++++++++++++++++--
 include/media/media-request.h | 36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
index 5edfc2791ce7c7485def5db675bbf53ee223d837..398d0806d1d274eb8c454fc5c37b77476abe1e74 100644
--- a/drivers/media/mc/mc-request.c
+++ b/drivers/media/mc/mc-request.c
@@ -54,6 +54,7 @@ static void media_request_clean(struct media_request *req)
 	req->access_count = 0;
 	WARN_ON(req->num_incomplete_objects);
 	req->num_incomplete_objects = 0;
+	req->manual_completion = false;
 	wake_up_interruptible_all(&req->poll_wait);
 }
 
@@ -313,6 +314,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
 	req->mdev = mdev;
 	req->state = MEDIA_REQUEST_STATE_IDLE;
 	req->num_incomplete_objects = 0;
+	req->manual_completion = false;
 	kref_init(&req->kref);
 	INIT_LIST_HEAD(&req->objects);
 	spin_lock_init(&req->lock);
@@ -459,7 +461,7 @@ void media_request_object_unbind(struct media_request_object *obj)
 
 	req->num_incomplete_objects--;
 	if (req->state == MEDIA_REQUEST_STATE_QUEUED &&
-	    !req->num_incomplete_objects) {
+	    !req->num_incomplete_objects && !req->manual_completion) {
 		req->state = MEDIA_REQUEST_STATE_COMPLETE;
 		completed = true;
 		wake_up_interruptible_all(&req->poll_wait);
@@ -488,7 +490,7 @@ void media_request_object_complete(struct media_request_object *obj)
 	    WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
 		goto unlock;
 
-	if (!--req->num_incomplete_objects) {
+	if (!--req->num_incomplete_objects && !req->manual_completion) {
 		req->state = MEDIA_REQUEST_STATE_COMPLETE;
 		wake_up_interruptible_all(&req->poll_wait);
 		completed = true;
@@ -499,3 +501,35 @@ void media_request_object_complete(struct media_request_object *obj)
 		media_request_put(req);
 }
 EXPORT_SYMBOL_GPL(media_request_object_complete);
+
+void media_request_manual_complete(struct media_request *req)
+{
+	unsigned long flags;
+	bool completed = false;
+
+	if (WARN_ON(!req))
+		return;
+	if (WARN_ON(!req->manual_completion))
+		return;
+
+	spin_lock_irqsave(&req->lock, flags);
+	if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
+		goto unlock;
+
+	req->manual_completion = false;
+	/*
+	 * It is expected that all other objects in this request are
+	 * completed when this function is called. WARN if that is
+	 * not the case.
+	 */
+	if (!WARN_ON(req->num_incomplete_objects)) {
+		req->state = MEDIA_REQUEST_STATE_COMPLETE;
+		wake_up_interruptible_all(&req->poll_wait);
+		completed = true;
+	}
+unlock:
+	spin_unlock_irqrestore(&req->lock, flags);
+	if (completed)
+		media_request_put(req);
+}
+EXPORT_SYMBOL_GPL(media_request_manual_complete);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index d4ac557678a78372222704400c8c96cf3150b9d9..645d18907be7148ca50dcc9248ff06bd8ccdf953 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -56,6 +56,10 @@ struct media_request_object;
  * @access_count: count the number of request accesses that are in progress
  * @objects: List of @struct media_request_object request objects
  * @num_incomplete_objects: The number of incomplete objects in the request
+ * @manual_completion: if true, then the request won't be marked as completed
+ * when @num_incomplete_objects reaches 0. Call media_request_manual_complete()
+ * to set this field to false and complete the request
+ * if @num_incomplete_objects == 0.
  * @poll_wait: Wait queue for poll
  * @lock: Serializes access to this struct
  */
@@ -68,6 +72,7 @@ struct media_request {
 	unsigned int access_count;
 	struct list_head objects;
 	unsigned int num_incomplete_objects;
+	bool manual_completion;
 	wait_queue_head_t poll_wait;
 	spinlock_t lock;
 };
@@ -218,6 +223,35 @@ media_request_get_by_fd(struct media_device *mdev, int request_fd);
 int media_request_alloc(struct media_device *mdev,
 			int *alloc_fd);
 
+/**
+ * media_request_mark_manual_completion - Set manual_completion to true
+ *
+ * @req: The request
+ *
+ * Mark that the request has to be manually completed by calling
+ * media_request_manual_complete().
+ *
+ * This function should be called in the req_queue callback.
+ */
+static inline void
+media_request_mark_manual_completion(struct media_request *req)
+{
+	req->manual_completion = true;
+}
+
+/**
+ * media_request_manual_complete - Set manual_completion to false
+ *
+ * @req: The request
+ *
+ * Set @manual_completion to false, and if @num_incomplete_objects
+ * is 0, then mark the request as completed.
+ *
+ * If there are still incomplete objects in the request, then
+ * WARN for that since that suggests a driver error.
+ */
+void media_request_manual_complete(struct media_request *req);
+
 #else
 
 static inline void media_request_get(struct media_request *req)
@@ -336,7 +370,7 @@ void media_request_object_init(struct media_request_object *obj);
  * @req: The media request
  * @ops: The object ops for this object
  * @priv: A driver-specific priv pointer associated with this object
- * @is_buffer: Set to true if the object a buffer object.
+ * @is_buffer: Set to true if the object is a buffer object.
  * @obj: The object
  *
  * Bind this object to the request and set the ops and priv values of

-- 
2.34.1



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:25 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:25 +0100
Subject: [PATCH 0/5] Add manual request completion to the MediaTek VCodec
 driver
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>

This set introduces the manual request completion API by the author Hans
Verkuil and implements it within the MediaTek VCodec driver.

Why is this needed?

The VCodec driver supports a hardware containing two separate cores, the
CORE and the LAT, these are working in a serial manner without this
series. This series solves two issues, the first being that the current
code runs into a problem, that occurs when the last request object is
unbound from the request, before the v4l2_ctrl_request_complete function
is called, causing an implicit transition to the COMPLETE state.
This issues has been found in applications which didn't attach the
controls for the very first request (which is supposed to enable the
driver to sniff out the correct formats, etc.).
The second issue is that the VCodec driver can not utilize the full
performance of both cores, when the LAT core has to wait for the CORE
core to finishing processing the decode. Thus by enabling the LAT core
to process the next bitstream, right after processing the last we can
increase the performance of the driver.
With the manual request completion API, we can separate the
completion of the request objects of a request and from the completion
of the request itself, which allows to send a new bitstream after the
LAT core has processed the previous and while the CORE core decodes the
previous bitstream, so both cores can work in a parallel manner, but
while keeping the request alive during both steps.

A new state machine for the VCodec driver ensures, that all necessary
processing steps are handled in the correct order depending on the
current step in the execution. This state machine has been added to each
request to ensure that new requests do not alter the state of still
ongoing requests.

Additionally, this series adds a small patch to avoid trying to handle a
scenario, which is not supported by the hardware and thus runs into a
timeout.

Signed-off-by: Sebastian Fricke <sebastian.fricke at collabora.com>
---
Hans Verkuil (3):
      media: mc: add manual request completion
      media: vicodec: add support for manual completion
      media: mc: add debugfs node to keep track of requests

Nicolas Dufresne (1):
      media: mtk-vcodec: Don't try to decode 422/444 VP9

Sebastian Fricke (1):
      media: vcodec: Implement manual request completion

 drivers/media/mc/mc-device.c                       | 30 +++++++++++++
 drivers/media/mc/mc-devnode.c                      |  5 +++
 drivers/media/mc/mc-request.c                      | 44 +++++++++++++++++-
 .../mediatek/vcodec/common/mtk_vcodec_cmn_drv.h    | 13 ++++++
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c       |  4 +-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c   | 52 ++++++++++++++++++++++
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h   |  4 ++
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c      | 52 ++++++++++++----------
 drivers/media/test-drivers/vicodec/vicodec-core.c  | 21 +++++++--
 include/media/media-device.h                       |  9 ++++
 include/media/media-devnode.h                      |  4 ++
 include/media/media-request.h                      | 38 +++++++++++++++-
 12 files changed, 244 insertions(+), 32 deletions(-)
---
base-commit: f2151613e040973c868d28c8b00885dfab69eb75
change-id: 20250312-sebastianfricke-vcodec_manual_request_completion_with_state_machine-6362c7f80a14

Best regards,
-- 
Sebastian Fricke <sebastian.fricke at collabora.com>



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:27 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:27 +0100
Subject: [PATCH 2/5] media: vicodec: add support for manual completion
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-2-5e277a3d695b@collabora.com>

From: Hans Verkuil <hverkuil at xs4all.nl>

Manually complete the requests: this tests the manual completion
code.

Signed-off-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
---
 drivers/media/test-drivers/vicodec/vicodec-core.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c
index c45f5cf12ded3c8b57483b148bf7bbffb8a458c5..88cb6e6a713f08bd4f412ca2940b1309bb87513b 100644
--- a/drivers/media/test-drivers/vicodec/vicodec-core.c
+++ b/drivers/media/test-drivers/vicodec/vicodec-core.c
@@ -448,8 +448,10 @@ static void device_run(void *priv)
 	ctx->comp_magic_cnt = 0;
 	ctx->comp_has_frame = false;
 	spin_unlock(ctx->lock);
-	if (ctx->is_stateless && src_req)
+	if (ctx->is_stateless && src_req) {
 		v4l2_ctrl_request_complete(src_req, &ctx->hdl);
+		media_request_manual_complete(src_req);
+	}
 
 	if (ctx->is_enc)
 		v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx);
@@ -1525,8 +1527,12 @@ static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
 			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 		if (vbuf == NULL)
 			return;
-		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
-					   &ctx->hdl);
+		if (ctx->is_stateless && V4L2_TYPE_IS_OUTPUT(q->type)) {
+			struct media_request *req = vbuf->vb2_buf.req_obj.req;
+
+			v4l2_ctrl_request_complete(req, &ctx->hdl);
+			media_request_manual_complete(req);
+		}
 		spin_lock(ctx->lock);
 		v4l2_m2m_buf_done(vbuf, state);
 		spin_unlock(ctx->lock);
@@ -1679,6 +1685,7 @@ static void vicodec_buf_request_complete(struct vb2_buffer *vb)
 	struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 
 	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
+	media_request_manual_complete(vb->req_obj.req);
 }
 
 
@@ -2010,6 +2017,12 @@ static int vicodec_request_validate(struct media_request *req)
 	return vb2_request_validate(req);
 }
 
+static void vicodec_request_queue(struct media_request *req)
+{
+	media_request_mark_manual_completion(req);
+	v4l2_m2m_request_queue(req);
+}
+
 static const struct v4l2_file_operations vicodec_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vicodec_open,
@@ -2030,7 +2043,7 @@ static const struct video_device vicodec_videodev = {
 
 static const struct media_device_ops vicodec_m2m_media_ops = {
 	.req_validate	= vicodec_request_validate,
-	.req_queue	= v4l2_m2m_request_queue,
+	.req_queue	= vicodec_request_queue,
 };
 
 static const struct v4l2_m2m_ops m2m_ops = {

-- 
2.34.1



From sebastian.fricke at collabora.com  Fri Mar 14 06:26:28 2025
From: sebastian.fricke at collabora.com (Sebastian Fricke)
Date: Fri, 14 Mar 2025 14:26:28 +0100
Subject: [PATCH 3/5] media: mc: add debugfs node to keep track of requests
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
Message-ID: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-3-5e277a3d695b@collabora.com>

From: Hans Verkuil <hverkuil at xs4all.nl>

Keep track of the number of requests and request objects of a media
device. Helps to verify that all request-related memory is freed.

Signed-off-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
---
 drivers/media/mc/mc-device.c  | 30 ++++++++++++++++++++++++++++++
 drivers/media/mc/mc-devnode.c |  5 +++++
 drivers/media/mc/mc-request.c |  6 ++++++
 include/media/media-device.h  |  9 +++++++++
 include/media/media-devnode.h |  4 ++++
 include/media/media-request.h |  2 ++
 6 files changed, 56 insertions(+)

diff --git a/drivers/media/mc/mc-device.c b/drivers/media/mc/mc-device.c
index c0dd4ae5722725f1744bc6fd6282d5c765438059..5a458160200afb540d8014fed42d8bf2dab9c8c3 100644
--- a/drivers/media/mc/mc-device.c
+++ b/drivers/media/mc/mc-device.c
@@ -679,6 +679,23 @@ void media_device_unregister_entity(struct media_entity *entity)
 }
 EXPORT_SYMBOL_GPL(media_device_unregister_entity);
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Log the state of media requests.
+ * Very useful for debugging.
+ */
+static int media_device_requests(struct seq_file *file, void *priv)
+{
+	struct media_device *dev = dev_get_drvdata(file->private);
+
+	seq_printf(file, "number of requests: %d\n",
+		   atomic_read(&dev->num_requests));
+	seq_printf(file, "number of request objects: %d\n",
+		   atomic_read(&dev->num_request_objects));
+	return 0;
+}
+#endif
+
 void media_device_init(struct media_device *mdev)
 {
 	INIT_LIST_HEAD(&mdev->entities);
@@ -697,6 +714,9 @@ void media_device_init(struct media_device *mdev)
 		media_set_bus_info(mdev->bus_info, sizeof(mdev->bus_info),
 				   mdev->dev);
 
+	atomic_set(&mdev->num_requests, 0);
+	atomic_set(&mdev->num_request_objects, 0);
+
 	dev_dbg(mdev->dev, "Media device initialized\n");
 }
 EXPORT_SYMBOL_GPL(media_device_init);
@@ -748,6 +768,15 @@ int __must_check __media_device_register(struct media_device *mdev,
 
 	dev_dbg(mdev->dev, "Media device registered\n");
 
+#ifdef CONFIG_DEBUG_FS
+	if (!media_debugfs_root)
+		media_debugfs_root = debugfs_create_dir("media", NULL);
+	mdev->media_dir = debugfs_create_dir(dev_name(&devnode->dev),
+					     media_debugfs_root);
+	debugfs_create_devm_seqfile(&devnode->dev, "requests",
+				    mdev->media_dir, media_device_requests);
+#endif
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
@@ -824,6 +853,7 @@ void media_device_unregister(struct media_device *mdev)
 
 	dev_dbg(mdev->dev, "Media device unregistered\n");
 
+	debugfs_remove_recursive(mdev->media_dir);
 	device_remove_file(&mdev->devnode->dev, &dev_attr_model);
 	media_devnode_unregister(mdev->devnode);
 	/* devnode free is handled in media_devnode_*() */
diff --git a/drivers/media/mc/mc-devnode.c b/drivers/media/mc/mc-devnode.c
index 56444edaf13651874331e7c04e86b0a585067d38..d0a8bcc11dd6350fdbc04add70f62de2c5f01178 100644
--- a/drivers/media/mc/mc-devnode.c
+++ b/drivers/media/mc/mc-devnode.c
@@ -45,6 +45,9 @@ static dev_t media_dev_t;
 static DEFINE_MUTEX(media_devnode_lock);
 static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
 
+/* debugfs */
+struct dentry *media_debugfs_root;
+
 /* Called when the last user of the media device exits. */
 static void media_devnode_release(struct device *cd)
 {
@@ -236,6 +239,7 @@ int __must_check media_devnode_register(struct media_device *mdev,
 	if (devnode->parent)
 		devnode->dev.parent = devnode->parent;
 	dev_set_name(&devnode->dev, "media%d", devnode->minor);
+	dev_set_drvdata(&devnode->dev, mdev);
 	device_initialize(&devnode->dev);
 
 	/* Part 2: Initialize the character device */
@@ -313,6 +317,7 @@ static int __init media_devnode_init(void)
 
 static void __exit media_devnode_exit(void)
 {
+	debugfs_remove_recursive(media_debugfs_root);
 	bus_unregister(&media_bus_type);
 	unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
 }
diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
index 398d0806d1d274eb8c454fc5c37b77476abe1e74..829e35a5d56d41c52cc583cdea1c959bcb4fce60 100644
--- a/drivers/media/mc/mc-request.c
+++ b/drivers/media/mc/mc-request.c
@@ -75,6 +75,7 @@ static void media_request_release(struct kref *kref)
 		mdev->ops->req_free(req);
 	else
 		kfree(req);
+	atomic_dec(&mdev->num_requests);
 }
 
 void media_request_put(struct media_request *req)
@@ -326,6 +327,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
 
 	snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
 		 atomic_inc_return(&mdev->request_id), fd);
+	atomic_inc(&mdev->num_requests);
 	dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);
 
 	fd_install(fd, filp);
@@ -349,10 +351,12 @@ static void media_request_object_release(struct kref *kref)
 	struct media_request_object *obj =
 		container_of(kref, struct media_request_object, kref);
 	struct media_request *req = obj->req;
+	struct media_device *mdev = obj->mdev;
 
 	if (WARN_ON(req))
 		media_request_object_unbind(obj);
 	obj->ops->release(obj);
+	atomic_dec(&mdev->num_request_objects);
 }
 
 struct media_request_object *
@@ -417,6 +421,7 @@ int media_request_object_bind(struct media_request *req,
 	obj->req = req;
 	obj->ops = ops;
 	obj->priv = priv;
+	obj->mdev = req->mdev;
 
 	if (is_buffer)
 		list_add_tail(&obj->list, &req->objects);
@@ -424,6 +429,7 @@ int media_request_object_bind(struct media_request *req,
 		list_add(&obj->list, &req->objects);
 	req->num_incomplete_objects++;
 	ret = 0;
+	atomic_inc(&obj->mdev->num_request_objects);
 
 unlock:
 	spin_unlock_irqrestore(&req->lock, flags);
diff --git a/include/media/media-device.h b/include/media/media-device.h
index 53d2a16a70b0d9d6e5cc28fe1fc5d5ef384410d5..749c327e3c582c3c583e0394468321ccd6160da5 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -11,6 +11,7 @@
 #ifndef _MEDIA_DEVICE_H
 #define _MEDIA_DEVICE_H
 
+#include <linux/atomic.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
@@ -106,6 +107,9 @@ struct media_device_ops {
  * @ops:	Operation handler callbacks
  * @req_queue_mutex: Serialise the MEDIA_REQUEST_IOC_QUEUE ioctl w.r.t.
  *		     other operations that stop or start streaming.
+ * @num_requests: number of associated requests
+ * @num_request_objects: number of associated request objects
+ * @media_dir:	DebugFS media directory
  * @request_id: Used to generate unique request IDs
  *
  * This structure represents an abstract high-level media device. It allows easy
@@ -179,6 +183,11 @@ struct media_device {
 	const struct media_device_ops *ops;
 
 	struct mutex req_queue_mutex;
+	atomic_t num_requests;
+	atomic_t num_request_objects;
+
+	/* debugfs */
+	struct dentry *media_dir;
 	atomic_t request_id;
 };
 
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
index d27c1c646c2805171be3997d72210dd4d1a38e32..dbcabeffcb572ae707f5fe1f51ff719d451c6784 100644
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -20,9 +20,13 @@
 #include <linux/fs.h>
 #include <linux/device.h>
 #include <linux/cdev.h>
+#include <linux/debugfs.h>
 
 struct media_device;
 
+/* debugfs top-level media directory */
+extern struct dentry *media_debugfs_root;
+
 /*
  * Flag to mark the media_devnode struct as registered. Drivers must not touch
  * this flag directly, it will be set and cleared by media_devnode_register and
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 645d18907be7148ca50dcc9248ff06bd8ccdf953..c8dad380c40767f192f30dcf1c69b9ad1310f449 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -290,6 +290,7 @@ struct media_request_object_ops {
  * struct media_request_object - An opaque object that belongs to a media
  *				 request
  *
+ * @mdev: Media device this object belongs to
  * @ops: object's operations
  * @priv: object's priv pointer
  * @req: the request this object belongs to (can be NULL)
@@ -301,6 +302,7 @@ struct media_request_object_ops {
  * another struct that contains the actual data for this request object.
  */
 struct media_request_object {
+	struct media_device *mdev;
 	const struct media_request_object_ops *ops;
 	void *priv;
 	struct media_request *req;

-- 
2.34.1



From will at kernel.org  Fri Mar 14 06:34:09 2025
From: will at kernel.org (Will Deacon)
Date: Fri, 14 Mar 2025 13:34:09 +0000
Subject: [PATCH] KVM: arm64: Tear down vGIC on failed vCPU creation
Message-ID: <20250314133409.9123-1-will@kernel.org>

If kvm_arch_vcpu_create() fails to share the vCPU page with the
hypervisor, we propagate the error back to the ioctl but leave the
vGIC vCPU data initialised. Note only does this leak the corresponding
memory when the vCPU is destroyed but it can also lead to use-after-free
if the redistributor device handling tries to walk into the vCPU.

Add the missing cleanup to kvm_arch_vcpu_create(), ensuring that the
vGIC vCPU structures are destroyed on error.

Cc: <stable at vger.kernel.org>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Quentin Perret <qperret at google.com>
Signed-off-by: Will Deacon <will at kernel.org>
---

It's hard to come up with a "Fixes:" tag for this. Prior to 3f868e142c0b
("KVM: arm64: Introduce kvm_share_hyp()"), create_hyp_mappings() could
still have failed, although if you go back before 66c57edd3bc7 ("KVM:
arm64: Restrict EL2 stage-1 changes in protected mode") then it's
vanishingly unlikely.

 arch/arm64/kvm/arm.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b8e55a441282..fa71cee02faa 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -466,7 +466,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 	if (err)
 		return err;
 
-	return kvm_share_hyp(vcpu, vcpu + 1);
+	err = kvm_share_hyp(vcpu, vcpu + 1);
+	if (err)
+		kvm_vgic_vcpu_destroy(vcpu);
+
+	return err;
 }
 
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
-- 
2.49.0.rc1.451.g8f38331e32-goog



From thomas.gessler at brueckmann-gmbh.de  Fri Mar 14 06:48:47 2025
From: thomas.gessler at brueckmann-gmbh.de (Thomas Gessler)
Date: Fri, 14 Mar 2025 14:48:47 +0100
Subject: [PATCH] dmaengine: xilinx_dma: Set dma_device directions
Message-ID: <20250314134849.703819-1-thomas.gessler@brueckmann-gmbh.de>

Coalesce the direction bits from the enabled TX and/or RX channels into
the directions bit mask of dma_device. Without this mask set,
dma_get_slave_caps() in the DMAEngine fails, which prevents the driver
from being used with an IIO DMAEngine buffer.

Signed-off-by: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>
---
 drivers/dma/xilinx/xilinx_dma.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 108a7287f4cd..641aaf0c0f1c 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -3205,6 +3205,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		}
 	}
 
+	for (i = 0; i < xdev->dma_config->max_channels; i++)
+		if (xdev->chan[i])
+			xdev->common.directions |= xdev->chan[i]->direction;
+
 	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		for (i = 0; i < xdev->dma_config->max_channels; i++)
 			if (xdev->chan[i])
-- 
2.43.0



From thomas.gessler at brueckmann-gmbh.de  Fri Mar 14 06:47:15 2025
From: thomas.gessler at brueckmann-gmbh.de (Thomas Gessler)
Date: Fri, 14 Mar 2025 14:47:15 +0100
Subject: [PATCH] dmaengine: xilinx_dma: Set max segment size
Message-ID: <20250314134717.703287-1-thomas.gessler@brueckmann-gmbh.de>

Set the maximumg DMA segment size from the actual core configuration
value. Without this setting, the default value of 64 KiB is reported,
and larger sizes cannot be used for IIO DMAEngine buffers.

Signed-off-by: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>
---
 drivers/dma/xilinx/xilinx_dma.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 108a7287f4cd..4b4a299e3807 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -3114,6 +3114,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		}
 	}
 
+	dma_set_max_seg_size(xdev->dev, xdev->max_buffer_len);
+
 	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		xdev->has_axistream_connected =
 			of_property_read_bool(node, "xlnx,axistream-connected");
-- 
2.43.0



From wei.fang at nxp.com  Fri Mar 14 06:48:21 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 14 Mar 2025 13:48:21 +0000
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250314123715.fivq2cbczd4khxkk@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314123715.fivq2cbczd4khxkk@skbuf>
Message-ID: <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>



Best Regards,
Wei Fang

> -----Original Message-----
> From: Vladimir Oltean <vladimir.oltean at nxp.com>
> On Fri, Mar 14, 2025 at 05:38:18AM +0200, Wei Fang wrote:
> > > > +	__le16 update_act;
> > > > +	u8 dbg_opt;
> > > > +	u8 tblv_qact;
> > > > +#define NTMP_QUERY_ACT		GENMASK(3, 0)
> > > > +#define NTMP_TBL_VER		GENMASK(7, 0)
> > > > +#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
> > > > +				 ((a) & NTMP_QUERY_ACT))
> > >
> > > Can you please move #define macros out of structure definitions?
> >
> > No, I think these macros in the structure can better reflect the specific
> > meaning of these members. We can intuitively see what the bits of
> > these members represent, rather than finding the definition of these
> > bits in RM or elsewhere.
> 
> I mean, I was just suggesting to group the macros with the macros, and
> the struct fields with the struct fields. Mixing them together looks a
> bit messy to me. Even worse in the definition of "union netc_cbd" which
> IMO needs to be reconsidered a bit (a hint given below).

I think this is a matter of personal preference. I was inspired by some
of Intel's structure definitions. I think this method allows me to quickly
understand what fields the member consists of and what bits each field
occupies.

> 
> But you mention "intuitive" definitions without having to go to the RM.
> If I look just at the definitions, I see that NTMP_QUERY_ACT and
> NTMP_TBL_VER
> overlap, and that NTMP_TBLV_QACT() just ORs them together. How does that
> work?
> Shouldn't NTMP_TBL_VER() have been GENMASK(7, 4)? If I do open the RM

I must admit that it is my fault, so yes, NTMP_TBL_VER should be GENMASK(7, 4).
I will fix it, thanks for pointing this.

> and go to the "Generic NTMP Request Data Buffer Format" section, that
> table does seem to agree with me.
> 
> The "normal" way to give more meaning to struct fields is to define them
> as enum values. That doesn't work with "packed" field definitions as you
> have here, which I agree is a challenge. But it is one of the reasons
> why I tried to develop an API together with Jacob Keller which tries to
> address this, by allowing you to define the structures in an "unpacked"
> format, and have a separate data structure which informs the CPU how
> that structure maps over the buffer layout.
> 
> Below is an example to illustrate this for the case of NTMP request buffers.
> Note that the example is incomplete and doesn't even compile, because I
> haven't even converted all ntmp_fill_crd_eid() callers - I don't want to
> waste too much time doing that in case you disagree, but it's still
> enough to show what I'm talking about. Disclaimer: I didn't even _try_
> to compile it - it may contain bugs.
> 
> -- >8 --
> diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig
> b/drivers/net/ethernet/freescale/enetc/Kconfig
> index c8efbb6f2055..35d5cf21f6f4 100644
> --- a/drivers/net/ethernet/freescale/enetc/Kconfig
> +++ b/drivers/net/ethernet/freescale/enetc/Kconfig
> @@ -17,6 +17,7 @@ config NXP_ENETC_PF_COMMON
> 
>  config NXP_NETC_LIB
>  	tristate
> +	select PACKING
>  	help
>  	  This module provides common functionalities for both ENETC and NETC
>  	  Switch, such as NETC Table Management Protocol (NTMP) 2.0,
> common tc
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c
> b/drivers/net/ethernet/freescale/enetc/ntmp.c
> index df10f2f310c1..f96cfca92a1c 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
> @@ -180,7 +180,7 @@ static int netc_xmit_ntmp_cmd(struct netc_cbdrs
> *cbdrs, union netc_cbd *cbd)
>  	return err;
>  }
> 
> -static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void
> **buf_align)
> +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data,
> ntmp_common_req_msg_data_buf *buf_align)
>  {
>  	void *buf;
> 
> @@ -221,18 +221,24 @@ static void ntmp_fill_request_headr(union netc_cbd
> *cbd, dma_addr_t dma,
>  	cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
>  }
> 
> -static void ntmp_fill_crd(struct common_req_data *crd,
> -			  u8 tblv, u8 qa, u16 ua)
> +static const struct packed_field_u8 ntmp_common_req_fields[] = {
> +	PACKED_FIELD(31, 28, struct ntmp_common_req_data, table_version),
> +	PACKED_FIELD(27, 24, struct ntmp_common_req_data, query_actions),
> +	PACKED_FIELD(15, 0, struct ntmp_common_req_data, update_actions),
> +};
> +
> +static void ntmp_fill_crd(ntmp_common_req_msg_data_buf *buf,
> +			  const struct common_req_data *crd)
>  {
> -	crd->update_act = cpu_to_le16(ua);
> -	crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
> +	pack_fields(buf, sizeof(*buf), crd, ntmp_common_req_fields,
> +		    QUIRK_LITTLE_ENDIAN);
>  }
> 
> -static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
> -			      u8 qa, u16 ua, u32 entry_id)
> +static void ntmp_fill_crd_eid(struct ntmp_common_req_msg_data_buf *buf,
> +			      const struct ntmp_req_by_eid *rbe)
>  {
> -	ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
> -	rbe->entry_id = cpu_to_le32(entry_id);
> +	ntmp_fill_crd(buf, &rbe->crd);
> +	pack(buf + 1, rbe->entry_id, 31, 0);
>  }
> 
>  static int ntmp_delete_entry_by_id(struct netc_cbdrs *cbdrs, int tbl_id,
> @@ -240,7 +246,13 @@ static int ntmp_delete_entry_by_id(struct
> netc_cbdrs *cbdrs, int tbl_id,
>  				   u32 resp_len)
>  {
>  	struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> -	struct ntmp_req_by_eid *req;
> +	struct ntmp_req_by_eid req = {
> +		.crd = {
> +			.table_version = tbl_ver,
> +		},
> +		.entry_id = entry_id,
> +	};
> +	ntmp_common_req_msg_data_buf buf;
>  	union netc_cbd cbd;
>  	u32 len;
>  	int err;
> @@ -255,7 +267,7 @@ static int ntmp_delete_entry_by_id(struct netc_cbdrs
> *cbdrs, int tbl_id,
>  		req_len = sizeof(*req);
> 
>  	data.size = req_len >= resp_len ? req_len : resp_len;
> -	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	err = ntmp_alloc_data_mem(&data, &buf);
>  	if (err)
>  		return err;
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> index 45e4d083ab0a..e68b2a060176 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> @@ -16,14 +16,14 @@ struct ntmp_dma_buf {
>  	dma_addr_t dma;
>  };
> 
> -struct common_req_data {
> -	__le16 update_act;
> -	u8 dbg_opt;
> -	u8 tblv_qact;
> -#define NTMP_QUERY_ACT		GENMASK(3, 0)
> -#define NTMP_TBL_VER		GENMASK(7, 0)
> -#define NTMP_TBLV_QACT(v, a)	(FIELD_PREP(NTMP_TBL_VER, (v)) | \
> -				 ((a) & NTMP_QUERY_ACT))
> +#define NTMP_COMMON_REQ_MSG_DATA_BUFSZ	4
> +
> +typedef struct __packed { u8
> buf[NTMP_COMMON_REQ_MSG_DATA_BUFSZ]; }
> ntmp_common_req_msg_data_buf;
> +
> +struct ntmp_common_req_data {
> +	u16 update_actions;
> +	u8 query_actions;
> +	u8 table_version;
>  };
> 
>  struct common_resp_query {
> @@ -36,8 +36,8 @@ struct common_resp_nq {
> 
>  /* Generic structure for request data by entry ID  */
>  struct ntmp_req_by_eid {
> -	struct common_req_data crd;
> -	__le32 entry_id;
> +	struct ntmp_common_req_data crd;
> +	u32 entry_id;
>  };
> 
>  /* MAC Address Filter Table Request Data Buffer Format of Add action */
> -- >8 --
> 
> Some remarks:
>  - The fact that struct ntmp_common_req_data is an unpacked structure
>    now means that the layout of fields is completely decoupled from the
>    layout of the data buffer. You can make each field an enum type if
>    you want, which I didn't do here.
>  - You don't have to access its fields with le32_to_cpu() and friends,
>    it's implicitly in CPU endianness.
>  - The API is tolerant of the case where the CPU is in a different
>    endianness from ENETC.
>  - The API protects you against overlapping PACKED_FIELD() definitions,
>    and gives a compile-time error if it detects an overlap.
>  - The API allows you to define buffers of any size you want, and the
>    bit field ranges vary according to the buffer size you chose. Notice
>    how you are grouping two fields within the "u8 tblv_qact" field, and
>    their offsets are 7-4 and 3-0, respectively, within that u8, but in
>    the PACKED_FIELD() definition you can make them 31-28 and 27-24, just
>    like in the RM.
>  - struct ntmp_req_by_eid and struct ntmp_common_req_data don't have to
>    be distinct structures. You can call pack_fields() and pack only a
>    subset of the fields of an unpacked structure. Then pack the rest
>    with explicit pack() calls, or not pack them at all.
> 
> I just want to present this alternative because I believe it offers some
> distinct advantages which may be useful here. But note that just
> "QUIRK_LITTLE_ENDIAN" may be wrong for NTMP. You need to see whether
> you
> also need QUIRK_LSW32_IS_FIRST or not. For buffers up to 32 bits,
> QUIRK_LSW32_IS_FIRST makes no difference, only for buffers larger than that.
> 

Thanks, but we have added fully NTMP support in downstream, it's a great
challenge for me to convert it to the 'packing' method. I don't think I have
too much time to do this conversion. And I also need some time to figure
out how to use it and whether it is worth doing so.

> > > The question pertains to everything else that is exported to
> > > include/linux/fsl/ntmp.h - what the API consumer sees. Is there a real
> > > reason to export it? For many structures and macros, the answer seems no.
> > >
> > > Even for cases like struct maft_keye_data which are only used by debugfs,
> > > it still seems preferable to keep data encapsulation and offer a helper
> > > function to retrieve a pointer to the MAC address from the MAFT entry.
> > > Then, "struct maft_keye_data;" can simply be declared, without exposing
> > > its full definition.
> >
> > ntmp_private.h is only used for ntmp driver, I don't want it to be included
> > by any enetc files. ntmp.h is used for both enetc and switch drivers, so we
> > need to add full definitions of the table data.
> 
> And I agree with you, I also don't want ntmp_private.h to be exposed to
> the NTMP API consumers, and I wasn't suggesting that. I just want the
> NTMP API to spare consumer drivers of the gory details, like for example
> the buffer layout of a MAC filtering entry, reserved fields, things like
> that. What I was saying is to keep the buffer layout private to
> ntmp_private.h, and expose a more abstract data structure to API
> consumers.
> 

Sorry, I don't fully understand, for example, if we place the definition
of "struct maft_keye_data" in ntmp_private.h, how does the debugfs
get the information from "struct maft_keye_data"? Add a helper function
in the NTMP driver and export it to enetc driver? And how does
enetc4_pf_add_si_mac_exact_filter() to set the mac address to "struct
maft_keye_data", add another helper? If so, I think it is more complicated.

> > > > +struct ntmp_priv {
> > >
> > > Would it be better to name this "struct ntmp_client"? I don't really
> > > understand the way in which it is "private".
> >
> > It refers to some private data of NTMP of different devices (enetc or
> > switches). Since the current patch is only a small part of NTMP, many
> > members have not been added to the structure. The following is the
> > definition in our downstream.
> >
> > struct ntmp_priv {
> > 	enum netc_dev_type dev_type;
> > 	struct netc_cbdrs cbdrs;
> > 	u32 errata;
> >
> > 	struct ntmp_caps caps;
> > 	/* bitmap of table entry ID */
> > 	unsigned long *ist_eid_bitmap;
> > 	unsigned long *rpt_eid_bitmap;
> > 	unsigned long *sgit_eid_bitmap;
> > 	unsigned long *isct_eid_bitmap;
> > 	unsigned long *sgclt_word_bitmap;
> > 	unsigned long *ett_eid_bitmap;
> > 	unsigned long *ect_eid_bitmap;
> > 	u32 ett_bitmap_size;
> > 	u32 ect_bitmap_size;
> >
> > 	struct hlist_head flower_list;
> > 	struct mutex flower_lock; /* flower_list lock */
> >
> > 	u64 (*adjust_base_time)(struct ntmp_priv *priv, u64 bt, u32 ct);
> > 	u32 (*get_tgst_free_words)(struct ntmp_priv *priv);
> > };
> 
> Thank you for posting the downstream layout of struct ntmp_priv which I
> was already aware of. What I was saying is that the word "private" means
> an aspect of the implementation which is hidden from other code layers.
> There's nothing "private" here if the NTMP layer has access to the
> definition of this structure. I was asking whether you agree that it's
> more adequate to name this structure "ntmp_client", since it represents
> the data associated with a consumer of the NTMP API - a NETC SI or (in
> the future) the switch. Or some other name. But the word "private" seems
> misused.
> 

Okay, it seems to make you feel confused, let me rename it later, how about
"ntmp_user"?

> > > What's the idea with the null entry ID? Why special-case it?
> > >
> >
> > Some functions are configured by multiple tables. If a table is
> > not needed in the current configuration, we may set its entry
> > id to NTMP_NULL_ENTRY_ID, indicating that the table is bypassed.
> > For the current patch, this condition can be removed.
> 
> Ok, thank you.
> 
> > > > +	return &cbdrs->ring[smp_processor_id() % cbdrs->cbdr_num];
> > >
> > > I think you need to be in a "preemption disabled" / "migration disable"
> > > calling context for smp_processor_id() to be reliable. Otherwise, the
> > > task can migrate to another CPU as soon as this function returns.
> > >
> >
> > It does not matter, we just want to select a command BD ring when all
> > command BD rings are busy. So smp_processor_id() is just a parameter,
> > we can also use a random number.
> 
> Ok.
> 
> > > Can you place this dma_wmb() right next to the "*cur_cbd = *cbd" line,
> > > to make it obvious that updating the producer index has nothing to do
> > > with it? Or is there another reason for this ordering?
> > >
> >
> > No special reason for this ordering, I will move it after "*cur_cbd = *cbd".
> 
> Thanks, I appreciate it.


From adrian.hunter at intel.com  Fri Mar 14 06:50:42 2025
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Fri, 14 Mar 2025 15:50:42 +0200
Subject: [RFC PATCH] mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
In-Reply-To: <20250310140707.23459-1-balejk@matfyz.cz>
References: <20250310140707.23459-1-balejk@matfyz.cz>
Message-ID: <df48092d-2192-4f80-9951-70e321d28aff@intel.com>

On 10/03/25 16:07, Karel Balej wrote:
> Set the MMC_CAP_NEED_RSP_BUSY capability for the sdhci-pxav3 host to
> prevent conversion of R1B responses to R1. Without this, the eMMC card
> in the samsung,coreprimevelte smartphone using the Marvell PXA1908 SoC
> with this mmc host doesn't probe with the ETIMEDOUT error originating in
> __mmc_poll_for_busy.
> 
> Note that the other issues reported for this phone and host, namely
> floods of "Tuning failed, falling back to fixed sampling clock" dmesg
> messages for the eMMC and unstable SDIO are not mitigated by this
> change.
> 
> Link: https://lore.kernel.org/r/20200310153340.5593-1-ulf.hansson at linaro.org/
> Link: https://lore.kernel.org/r/D7204PWIGQGI.1FRFQPPIEE2P9 at matfyz.cz/
> Link: https://lore.kernel.org/r/20250115-pxa1908-lkml-v14-0-847d24f3665a at skole.hr/
> Cc: Duje Mihanovi? <duje.mihanovic at skole.hr>
> Cc: stable at vger.kernel.org
> Signed-off-by: Karel Balej <balejk at matfyz.cz>

There doesn't seem to be much interest in this driver except from
Karel Balej and it looks OK, so:

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-pxav3.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
> index 990723a008ae..3fb56face3d8 100644
> --- a/drivers/mmc/host/sdhci-pxav3.c
> +++ b/drivers/mmc/host/sdhci-pxav3.c
> @@ -399,6 +399,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
>  	if (!IS_ERR(pxa->clk_core))
>  		clk_prepare_enable(pxa->clk_core);
>  
> +	host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
>  	/* enable 1/8V DDR capable */
>  	host->mmc->caps |= MMC_CAP_1_8V_DDR;
>  



From wei.fang at nxp.com  Fri Mar 14 06:56:06 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Fri, 14 Mar 2025 13:56:06 +0000
Subject: [PATCH v4 net-next 02/14] net: enetc: add command BD ring support
 for i.MX95 ENETC
In-Reply-To: <20250314111801.2oela3qoi5qrl6el@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250311053830.1516523-3-wei.fang@nxp.com>
 <20250313164908.rdy3y77xno3fza3l@skbuf>
 <PAXPR04MB8510D3A2F2A792A89941A7FD88D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314111801.2oela3qoi5qrl6el@skbuf>
Message-ID: <PAXPR04MB8510E0C6A4EE36B2155D813B88D22@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Fri, Mar 14, 2025 at 06:51:06AM +0200, Wei Fang wrote:
> > > I don't understand the need for si->ops->setup_cbdr() and
> > > si->ops->teardown_cbdr()?
> > > Doesn't every call site know which kind of SI it is dealing with, and thus it
> can
> > > appropriately call the direct symbol?
> > > - the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
> > > - the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()
> >
> > Yes, for PSI we can use directly call these functions because they are different
> > drivers, but for VSI, v1 and v4 will use the same driver. I just want the PSI and
> > VSI to be consistent. If you don't like this, I can remove these interfaces from
> > the patch set, and add vf_setup_cbdr and vf_teardown_cbdr in the future
> when
> > I add the VF support for ENETC v4.
> 
> It's not that I don't like them, the point is rather simple: as far as
> this patch set is concerned, converting direct function calls to
> indirect ones is an unfinished idea. It needs to be evaluated in full
> context, which is not present here - as you say, v4 VSIs need to be
> further modified to call a different set of operations - but right now,
> they call a single set of CBDR functions. Changes which require
> subsequent patch sets in order to make any sense at all are discouraged.
> 
> Given the fact that the PSI code paths still don't benefit from an
> indirect function call in any way, I would in principle recommend to
> keep calling their CBDR methods directly. For VSIs I don't know which is
> preferable (if-else vs function pointer), I need to see that code first.

Okay, let's keep directly calls in v1 and v4 PSI drivers. Regarding to the
VSI, some people don't like if-else because they think we may have v5,
v6, v7 in the future which may use different version of command BD ring,
so they prefer function pointer. But for trivial, like different register offsets
for different ENETC versions. I think if-else is enough.



From qperret at google.com  Fri Mar 14 07:06:48 2025
From: qperret at google.com (Quentin Perret)
Date: Fri, 14 Mar 2025 14:06:48 +0000
Subject: [PATCH 4/6] KVM: arm64: Move hyp state to hyp_vmemmap
In-Reply-To: <86bju3onl3.wl-maz@kernel.org>
References: <20250227003310.367350-1-qperret@google.com>
 <20250227003310.367350-5-qperret@google.com>
 <86bju3onl3.wl-maz@kernel.org>
Message-ID: <Z9Q3-FM-QwiIn9gh@google.com>

On Friday 14 Mar 2025 at 11:31:36 (+0000), Marc Zyngier wrote:
> On Thu, 27 Feb 2025 00:33:08 +0000,
> Quentin Perret <qperret at google.com> wrote:
> > @@ -698,13 +697,13 @@ int __pkvm_host_share_hyp(u64 pfn)
> >  	if (ret)
> >  		goto unlock;
> >  	if (IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) {
> > -		ret = __hyp_check_page_state_range((u64)virt, size, PKVM_NOPAGE);
> > +		ret = __hyp_check_page_state_range(phys, size, PKVM_NOPAGE);
> 
> OK, I think I finally clicked here. Does it mean that all the tracking
> is now done in terms of PAs instead of VAs?

Yep, that's exactly that. The hyp_vmemmap is indexed by pfn, so I felt
that the conversion to a PA-based tracking made sense. That also make it
clear that the 'hyp state' is not a property of a mapping, but really of
the underlying physical page.

> >  		if (ret)
> >  			goto unlock;
> >  	}
> >  
> > -	prot = pkvm_mkstate(PAGE_HYP, PKVM_PAGE_SHARED_BORROWED);
> > -	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, prot));
> > +	__hyp_set_page_state_range(phys, size, PKVM_PAGE_SHARED_BORROWED);
> > +	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, PAGE_HYP));
> 
> And this is the split between the state now being kept in the on a PA
> base and the actual mapping that is now only takes the page attributes
> and no SW bits?

Precisely, and the next patch in this series takes advantage of the
fact that we're now de-correlating the hyp state from the presence of a
hyp s1 mapping in the linear map range. In the future there'll be more
use-cases for this I think (e.g. the hyp allocator where we'll have
pages owned by the hypervisor but only mapped in the 'private' range,
things like that).

Thanks,
Quentin


From qperret at google.com  Fri Mar 14 07:13:39 2025
From: qperret at google.com (Quentin Perret)
Date: Fri, 14 Mar 2025 14:13:39 +0000
Subject: [PATCH 2/6] KVM: arm64: Use 0b11 for encoding PKVM_NOPAGE
In-Reply-To: <86cyejooq2.wl-maz@kernel.org>
References: <20250227003310.367350-1-qperret@google.com>
 <20250227003310.367350-3-qperret@google.com>
 <86cyejooq2.wl-maz@kernel.org>
Message-ID: <Z9Q5k5C50Meeog9q@google.com>

On Friday 14 Mar 2025 at 11:07:01 (+0000), Marc Zyngier wrote:
> On Thu, 27 Feb 2025 00:33:06 +0000,
> Quentin Perret <qperret at google.com> wrote:
> > 
> > The page ownership state encoded as 0b11 is currently considered
> > reserved for future use, and PKVM_NOPAGE uses bit 2. In order to
> > simplify the relocation of the hyp ownership state into the
> > vmemmap in later patches, let's use the 'reserved' encoding for
> > the PKVM_NOPAGE state. The struct hyp_page layout isn't guaranteed
> > stable at all, so there is no real reason to have 'reserved' encodings.
> > 
> > No functional changes intended.
> > 
> > Signed-off-by: Quentin Perret <qperret at google.com>
> > ---
> >  arch/arm64/kvm/hyp/include/nvhe/memory.h | 5 +----
> >  1 file changed, 1 insertion(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > index 34233d586060..642b5e05fe77 100644
> > --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > @@ -13,18 +13,15 @@
> >   *   01: The page is owned by the page-table owner, but is shared
> >   *       with another entity.
> >   *   10: The page is shared with, but not owned by the page-table owner.
> > - *   11: Reserved for future use (lending).
> >   */
> >  enum pkvm_page_state {
> >  	PKVM_PAGE_OWNED			= 0ULL,
> >  	PKVM_PAGE_SHARED_OWNED		= BIT(0),
> >  	PKVM_PAGE_SHARED_BORROWED	= BIT(1),
> > -	__PKVM_PAGE_RESERVED		= BIT(0) | BIT(1),
> >  
> >  	/* Meta-states which aren't encoded directly in the PTE's SW bits */
> > -	PKVM_NOPAGE			= BIT(2),
> > +	PKVM_NOPAGE			= BIT(0) | BIT(1),
> 
> Isn't this comment stale now?

I believe it still applies to guest stage-2 page-tables as the three
other states above are still stored into PTE SW bits (well, sort of,
only SHARED_BORROWED is at the moment as we don't supported protected
VMs, but OWNED and SHARED_OWNED will be a thing for protected). NOPAGE
is still the only one that is a bit different and doesn't go there.

With that said, the comment could be made more explicit about that and
explain this is now guest s2 only. Happy to spin another version of the
series with that changed if that helps.

Thanks!
Quentin


From sakari.ailus at linux.intel.com  Fri Mar 14 07:13:53 2025
From: sakari.ailus at linux.intel.com (Sakari Ailus)
Date: Fri, 14 Mar 2025 14:13:53 +0000
Subject: [PATCH 3/5] media: mc: add debugfs node to keep track of requests
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-3-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-0-5e277a3d695b@collabora.com>
 <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-3-5e277a3d695b@collabora.com>
Message-ID: <Z9Q5oTXEPPIoGWgE@kekkonen.localdomain>

Hi Sebastian,

On Fri, Mar 14, 2025 at 02:26:28PM +0100, Sebastian Fricke wrote:
> From: Hans Verkuil <hverkuil at xs4all.nl>
> 
> Keep track of the number of requests and request objects of a media
> device. Helps to verify that all request-related memory is freed.
> 
> Signed-off-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
> ---
>  drivers/media/mc/mc-device.c  | 30 ++++++++++++++++++++++++++++++
>  drivers/media/mc/mc-devnode.c |  5 +++++
>  drivers/media/mc/mc-request.c |  6 ++++++
>  include/media/media-device.h  |  9 +++++++++
>  include/media/media-devnode.h |  4 ++++
>  include/media/media-request.h |  2 ++
>  6 files changed, 56 insertions(+)
> 
> diff --git a/drivers/media/mc/mc-device.c b/drivers/media/mc/mc-device.c
> index c0dd4ae5722725f1744bc6fd6282d5c765438059..5a458160200afb540d8014fed42d8bf2dab9c8c3 100644
> --- a/drivers/media/mc/mc-device.c
> +++ b/drivers/media/mc/mc-device.c
> @@ -679,6 +679,23 @@ void media_device_unregister_entity(struct media_entity *entity)
>  }
>  EXPORT_SYMBOL_GPL(media_device_unregister_entity);
>  
> +#ifdef CONFIG_DEBUG_FS
> +/*
> + * Log the state of media requests.
> + * Very useful for debugging.
> + */
> +static int media_device_requests(struct seq_file *file, void *priv)
> +{
> +	struct media_device *dev = dev_get_drvdata(file->private);

Hmm. Can't you obtain struct media_device via struct device (dev field in
struct media_devnode is what I believe you have here)?

> +
> +	seq_printf(file, "number of requests: %d\n",
> +		   atomic_read(&dev->num_requests));
> +	seq_printf(file, "number of request objects: %d\n",
> +		   atomic_read(&dev->num_request_objects));
> +	return 0;
> +}
> +#endif
> +
>  void media_device_init(struct media_device *mdev)
>  {
>  	INIT_LIST_HEAD(&mdev->entities);
> @@ -697,6 +714,9 @@ void media_device_init(struct media_device *mdev)
>  		media_set_bus_info(mdev->bus_info, sizeof(mdev->bus_info),
>  				   mdev->dev);
>  
> +	atomic_set(&mdev->num_requests, 0);
> +	atomic_set(&mdev->num_request_objects, 0);
> +
>  	dev_dbg(mdev->dev, "Media device initialized\n");
>  }
>  EXPORT_SYMBOL_GPL(media_device_init);
> @@ -748,6 +768,15 @@ int __must_check __media_device_register(struct media_device *mdev,
>  
>  	dev_dbg(mdev->dev, "Media device registered\n");
>  
> +#ifdef CONFIG_DEBUG_FS
> +	if (!media_debugfs_root)
> +		media_debugfs_root = debugfs_create_dir("media", NULL);
> +	mdev->media_dir = debugfs_create_dir(dev_name(&devnode->dev),
> +					     media_debugfs_root);
> +	debugfs_create_devm_seqfile(&devnode->dev, "requests",
> +				    mdev->media_dir, media_device_requests);
> +#endif
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(__media_device_register);
> @@ -824,6 +853,7 @@ void media_device_unregister(struct media_device *mdev)
>  
>  	dev_dbg(mdev->dev, "Media device unregistered\n");
>  
> +	debugfs_remove_recursive(mdev->media_dir);
>  	device_remove_file(&mdev->devnode->dev, &dev_attr_model);
>  	media_devnode_unregister(mdev->devnode);
>  	/* devnode free is handled in media_devnode_*() */
> diff --git a/drivers/media/mc/mc-devnode.c b/drivers/media/mc/mc-devnode.c
> index 56444edaf13651874331e7c04e86b0a585067d38..d0a8bcc11dd6350fdbc04add70f62de2c5f01178 100644
> --- a/drivers/media/mc/mc-devnode.c
> +++ b/drivers/media/mc/mc-devnode.c
> @@ -45,6 +45,9 @@ static dev_t media_dev_t;
>  static DEFINE_MUTEX(media_devnode_lock);
>  static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
>  
> +/* debugfs */
> +struct dentry *media_debugfs_root;
> +
>  /* Called when the last user of the media device exits. */
>  static void media_devnode_release(struct device *cd)
>  {
> @@ -236,6 +239,7 @@ int __must_check media_devnode_register(struct media_device *mdev,
>  	if (devnode->parent)
>  		devnode->dev.parent = devnode->parent;
>  	dev_set_name(&devnode->dev, "media%d", devnode->minor);
> +	dev_set_drvdata(&devnode->dev, mdev);
>  	device_initialize(&devnode->dev);
>  
>  	/* Part 2: Initialize the character device */
> @@ -313,6 +317,7 @@ static int __init media_devnode_init(void)
>  
>  static void __exit media_devnode_exit(void)
>  {
> +	debugfs_remove_recursive(media_debugfs_root);
>  	bus_unregister(&media_bus_type);
>  	unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
>  }
> diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
> index 398d0806d1d274eb8c454fc5c37b77476abe1e74..829e35a5d56d41c52cc583cdea1c959bcb4fce60 100644
> --- a/drivers/media/mc/mc-request.c
> +++ b/drivers/media/mc/mc-request.c
> @@ -75,6 +75,7 @@ static void media_request_release(struct kref *kref)
>  		mdev->ops->req_free(req);
>  	else
>  		kfree(req);
> +	atomic_dec(&mdev->num_requests);
>  }
>  
>  void media_request_put(struct media_request *req)
> @@ -326,6 +327,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
>  
>  	snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
>  		 atomic_inc_return(&mdev->request_id), fd);
> +	atomic_inc(&mdev->num_requests);
>  	dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);
>  
>  	fd_install(fd, filp);
> @@ -349,10 +351,12 @@ static void media_request_object_release(struct kref *kref)
>  	struct media_request_object *obj =
>  		container_of(kref, struct media_request_object, kref);
>  	struct media_request *req = obj->req;
> +	struct media_device *mdev = obj->mdev;
>  
>  	if (WARN_ON(req))
>  		media_request_object_unbind(obj);
>  	obj->ops->release(obj);
> +	atomic_dec(&mdev->num_request_objects);
>  }
>  
>  struct media_request_object *
> @@ -417,6 +421,7 @@ int media_request_object_bind(struct media_request *req,
>  	obj->req = req;
>  	obj->ops = ops;
>  	obj->priv = priv;
> +	obj->mdev = req->mdev;
>  
>  	if (is_buffer)
>  		list_add_tail(&obj->list, &req->objects);
> @@ -424,6 +429,7 @@ int media_request_object_bind(struct media_request *req,
>  		list_add(&obj->list, &req->objects);
>  	req->num_incomplete_objects++;
>  	ret = 0;
> +	atomic_inc(&obj->mdev->num_request_objects);
>  
>  unlock:
>  	spin_unlock_irqrestore(&req->lock, flags);
> diff --git a/include/media/media-device.h b/include/media/media-device.h
> index 53d2a16a70b0d9d6e5cc28fe1fc5d5ef384410d5..749c327e3c582c3c583e0394468321ccd6160da5 100644
> --- a/include/media/media-device.h
> +++ b/include/media/media-device.h
> @@ -11,6 +11,7 @@
>  #ifndef _MEDIA_DEVICE_H
>  #define _MEDIA_DEVICE_H
>  
> +#include <linux/atomic.h>
>  #include <linux/list.h>
>  #include <linux/mutex.h>
>  #include <linux/pci.h>
> @@ -106,6 +107,9 @@ struct media_device_ops {
>   * @ops:	Operation handler callbacks
>   * @req_queue_mutex: Serialise the MEDIA_REQUEST_IOC_QUEUE ioctl w.r.t.
>   *		     other operations that stop or start streaming.
> + * @num_requests: number of associated requests
> + * @num_request_objects: number of associated request objects
> + * @media_dir:	DebugFS media directory
>   * @request_id: Used to generate unique request IDs
>   *
>   * This structure represents an abstract high-level media device. It allows easy
> @@ -179,6 +183,11 @@ struct media_device {
>  	const struct media_device_ops *ops;
>  
>  	struct mutex req_queue_mutex;
> +	atomic_t num_requests;
> +	atomic_t num_request_objects;
> +
> +	/* debugfs */
> +	struct dentry *media_dir;
>  	atomic_t request_id;
>  };
>  
> diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
> index d27c1c646c2805171be3997d72210dd4d1a38e32..dbcabeffcb572ae707f5fe1f51ff719d451c6784 100644
> --- a/include/media/media-devnode.h
> +++ b/include/media/media-devnode.h
> @@ -20,9 +20,13 @@
>  #include <linux/fs.h>
>  #include <linux/device.h>
>  #include <linux/cdev.h>
> +#include <linux/debugfs.h>
>  
>  struct media_device;
>  
> +/* debugfs top-level media directory */
> +extern struct dentry *media_debugfs_root;
> +
>  /*
>   * Flag to mark the media_devnode struct as registered. Drivers must not touch
>   * this flag directly, it will be set and cleared by media_devnode_register and
> diff --git a/include/media/media-request.h b/include/media/media-request.h
> index 645d18907be7148ca50dcc9248ff06bd8ccdf953..c8dad380c40767f192f30dcf1c69b9ad1310f449 100644
> --- a/include/media/media-request.h
> +++ b/include/media/media-request.h
> @@ -290,6 +290,7 @@ struct media_request_object_ops {
>   * struct media_request_object - An opaque object that belongs to a media
>   *				 request
>   *
> + * @mdev: Media device this object belongs to
>   * @ops: object's operations
>   * @priv: object's priv pointer
>   * @req: the request this object belongs to (can be NULL)
> @@ -301,6 +302,7 @@ struct media_request_object_ops {
>   * another struct that contains the actual data for this request object.
>   */
>  struct media_request_object {
> +	struct media_device *mdev;
>  	const struct media_request_object_ops *ops;
>  	void *priv;
>  	struct media_request *req;
> 

-- 
Regards,

Sakari Ailus


From Frank.li at nxp.com  Fri Mar 14 07:16:03 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 14 Mar 2025 10:16:03 -0400
Subject: [PATCH v1] arm64: dts: imx95: Correct the range of PCIe app-reg
 region
In-Reply-To: <20250314060104.390065-1-hongxing.zhu@nxp.com>
References: <20250314060104.390065-1-hongxing.zhu@nxp.com>
Message-ID: <Z9Q6I2roECiCkXG9@lizhi-Precision-Tower-5810>

On Fri, Mar 14, 2025 at 02:01:04PM +0800, Richard Zhu wrote:
> Correct the range of PCIe app-reg region from 0x2000 to 0x4000 refer to
> SerDes_SS memory map of i.MX95 Rerference Manual.
>
> Fixes: 3b1d5deb29ff ("arm64: dts: imx95: add pcie[0,1] and pcie-ep[0,1] support")
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  arch/arm64/boot/dts/freescale/imx95.dtsi | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
> index 6b8470cb3461..0e6a9e639d76 100644
> --- a/arch/arm64/boot/dts/freescale/imx95.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
> @@ -1542,7 +1542,7 @@ pcie0: pcie at 4c300000 {
>  			reg = <0 0x4c300000 0 0x10000>,
>  			      <0 0x60100000 0 0xfe00000>,
>  			      <0 0x4c360000 0 0x10000>,
> -			      <0 0x4c340000 0 0x2000>;
> +			      <0 0x4c340000 0 0x4000>;
>  			reg-names = "dbi", "config", "atu", "app";
>  			ranges = <0x81000000 0x0 0x00000000 0x0 0x6ff00000 0 0x00100000>,
>  				 <0x82000000 0x0 0x10000000 0x9 0x10000000 0 0x10000000>;
> @@ -1582,7 +1582,7 @@ pcie0_ep: pcie-ep at 4c300000 {
>  			reg = <0 0x4c300000 0 0x10000>,
>  			      <0 0x4c360000 0 0x1000>,
>  			      <0 0x4c320000 0 0x1000>,
> -			      <0 0x4c340000 0 0x2000>,
> +			      <0 0x4c340000 0 0x4000>,
>  			      <0 0x4c370000 0 0x10000>,
>  			      <0x9 0 1 0>;
>  			reg-names = "dbi","atu", "dbi2", "app", "dma", "addr_space";
> @@ -1609,7 +1609,7 @@ pcie1: pcie at 4c380000 {
>  			reg = <0 0x4c380000 0 0x10000>,
>  			      <8 0x80100000 0 0xfe00000>,
>  			      <0 0x4c3e0000 0 0x10000>,
> -			      <0 0x4c3c0000 0 0x2000>;
> +			      <0 0x4c3c0000 0 0x4000>;
>  			reg-names = "dbi", "config", "atu", "app";
>  			ranges = <0x81000000 0 0x00000000 0x8 0x8ff00000 0 0x00100000>,
>  				 <0x82000000 0 0x10000000 0xa 0x10000000 0 0x10000000>;
> @@ -1649,7 +1649,7 @@ pcie1_ep: pcie-ep at 4c380000 {
>  			reg = <0 0x4c380000 0 0x10000>,
>  			      <0 0x4c3e0000 0 0x1000>,
>  			      <0 0x4c3a0000 0 0x1000>,
> -			      <0 0x4c3c0000 0 0x2000>,
> +			      <0 0x4c3c0000 0 0x4000>,
>  			      <0 0x4c3f0000 0 0x10000>,
>  			      <0xa 0 1 0>;
>  			reg-names = "dbi", "atu", "dbi2", "app", "dma", "addr_space";
> --
> 2.37.1
>


From catalin.marinas at arm.com  Fri Mar 14 07:40:13 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 14:40:13 +0000
Subject: [PATCH 6.12 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <2025031427-yiddish-unrented-2bc2@gregkh>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-3-ddc16609d9ba@kernel.org>
 <2025031427-yiddish-unrented-2bc2@gregkh>
Message-ID: <Z9Q_zW_mM-v2iPHC@arm.com>

On Fri, Mar 14, 2025 at 06:32:45AM +0100, Greg Kroah-Hartman wrote:
> On Fri, Mar 14, 2025 at 12:35:15AM +0000, Mark Brown wrote:
> > From: Mark Rutland <mark.rutland at arm.com>
> > 
> > Now that the host eagerly saves its own FPSIMD/SVE/SME state,
> > non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
> > and the code to do this is never used. Protected KVM still needs to
> > save/restore the host FPSIMD/SVE state to avoid leaking guest state to
> > the host (and to avoid revealing to the host whether the guest used
> > FPSIMD/SVE/SME), and that code needs to be retained.
> > 
> > Remove the unused code and data structures.
> > 
> > To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
> > VHE hyp code, the nVHE/hVHE version is moved into the shared switch
> > header, where it is only invoked when KVM is in protected mode.
> > 
> > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> > Reviewed-by: Mark Brown <broonie at kernel.org>
> > Tested-by: Mark Brown <broonie at kernel.org>
> > Acked-by: Will Deacon <will at kernel.org>
> > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > Cc: Fuad Tabba <tabba at google.com>
> > Cc: Marc Zyngier <maz at kernel.org>
> > Cc: Oliver Upton <oliver.upton at linux.dev>
> > Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
> > Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > Signed-off-by: Mark Brown <broonie at kernel.org>
> > ---
> 
> What is the upstream git id for this on?

It seems to be 8eca7f6d5100 ("KVM: arm64: Remove host FPSIMD saving for
non-protected KVM").

-- 
Catalin


From monstr at monstr.eu  Fri Mar 14 07:46:51 2025
From: monstr at monstr.eu (Michal Simek)
Date: Fri, 14 Mar 2025 15:46:51 +0100
Subject: [GIT PULL] arm64: dts: ZynqMP DT changes for v6.15
Message-ID: <CAHTX3d+u1VmxP4vm0peQS-ST7o0BuCpKUPRVCSLMfAAb=eV3Xg@mail.gmail.com>

Hi,

please pull these patches to your tree. One new Versal NET board is added but
the most useful change is to start to use constants out of dt binding.
There will be followup
patches to migrate all SOC specific constants.

Thanks,
Michal

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://github.com/Xilinx/linux-xlnx.git tags/zynqmp-dt-for-6.14

for you to fetch changes up to f0ceedd52a69a8bf63778b1fe9e1c10e02ecd3fd:

  dt-bindings: xilinx: Deprecate header with firmware constants
(2025-02-21 07:58:35 +0100)

----------------------------------------------------------------
arm64: ZynqMP DT changes for 6.15

- Align clock nodes with DT binding
- Add the first VN-X Versal NET board
- Move constants out of DT bindings

----------------------------------------------------------------
Michal Simek (3):
      arm64: versal-net: Add description for b2197-00 revA board
      arm64: zynqmp: Use DT header for firmware constants
      dt-bindings: xilinx: Deprecate header with firmware constants

Naman Trivedi (1):
      arm64: zynqmp: add clock-output-names property in clock nodes

Shubhrajyoti Datta (1):
      dt-bindings: soc: Add new VN-X board description based on Versal NET

 Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml             |   4 +-
 Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml |   3 +-
 Documentation/devicetree/bindings/iio/adc/xlnx,zynqmp-ams.yaml        |   3 +-
 Documentation/devicetree/bindings/net/cdns,macb.yaml                  |   7 +-
 Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml              |  11 +-
 Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml            |   3 +-
 Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml                |   3 +-
 arch/arm64/boot/dts/xilinx/Makefile                                   |   2 +
 arch/arm64/boot/dts/xilinx/versal-net-clk.dtsi
| 231 ++++++
 arch/arm64/boot/dts/xilinx/versal-net-vn-x-b2197-01-revA.dts          | 116 +++
 arch/arm64/boot/dts/xilinx/versal-net.dtsi
| 752 ++++++++++++++++++++
 arch/arm64/boot/dts/xilinx/xlnx-zynqmp-clk.h
| 126 ++++
 arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi                        |  17 +-
 include/dt-bindings/clock/xlnx-zynqmp-clk.h                           |   7 +
 14 files changed, 1262 insertions(+), 23 deletions(-)
 create mode 100644 arch/arm64/boot/dts/xilinx/versal-net-clk.dtsi
 create mode 100644 arch/arm64/boot/dts/xilinx/versal-net-vn-x-b2197-01-revA.dts
 create mode 100644 arch/arm64/boot/dts/xilinx/versal-net.dtsi
 create mode 100644 arch/arm64/boot/dts/xilinx/xlnx-zynqmp-clk.h
---
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs


From mathis.foerst at mt.com  Fri Mar 14 07:46:08 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 14 Mar 2025 15:46:08 +0100
Subject: [PATCH v2 0/1] media: imx: csi: Parse link configuration from fw_node
Message-ID: <20250314144609.219486-1-mathis.foerst@mt.com>

Hi,

this patch fixes the imx-media-csi driver to work with camera drivers that
do not implement the subdev-pad-operation "get_mbus_format".

Changelog:
v1 -> v2:
- Factor out the function "csi_parse_upstream_fw_link_config" for better
readability.

It's the follow up of this discussion:
https://lore.kernel.org/linux-media/Z8AoA6WjbXQufqR6 at kekkonen.localdomain/

I tested the changes successfully on an i.MX6DL with an MT9M114 and an
MT9V032 camera. They both use the parallel camera interface.
Sadly, I don't have the hardware to test with a MIPI CSI-2 camera.

Best regards,
Mathis Foerst


Mathis Foerst (1):
  media: imx: csi: Parse link configuration from fw_node

 drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
 1 file changed, 32 insertions(+), 4 deletions(-)


base-commit: ac9c34d1e45a4c25174ced4fc0cfc33ff3ed08c7
-- 
2.34.1



From mathis.foerst at mt.com  Fri Mar 14 07:46:09 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 14 Mar 2025 15:46:09 +0100
Subject: [PATCH v2 1/1] media: imx: csi: Parse link configuration from fw_node
In-Reply-To: <20250314144609.219486-1-mathis.foerst@mt.com>
References: <20250314144609.219486-1-mathis.foerst@mt.com>
Message-ID: <20250314144609.219486-2-mathis.foerst@mt.com>

The imx-media-csi driver requires upstream camera drivers to implement
the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
implement this function are not usable on the i.MX6.

The docs for get_mbus_config [1] say:
@get_mbus_config: get the media bus configuration of a remote sub-device.
            The media bus configuration is usually retrieved from the
            firmware interface at sub-device probe time, immediately
            applied to the hardware and eventually adjusted by the
            driver.

Currently, the imx-media-csi driver is not incorporating the information
from the firmware interface and therefore relies on the implementation of
get_mbus_config by the camera driver.

To be compatible with camera drivers not implementing get_mbus_config
(which is the usual case), use the bus information from the fw interface:

The camera does not necessarily has a direct media bus link to the CSI as
the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
between them on the media pipeline.
The CSI driver already implements the functionality to find the connected
camera sub-device to call get_mbus_config on it.

At this point the driver is modified as follows:
In the case that get_mbus_config is not implemented by the upstream
camera, try to get its endpoint configuration from the firmware interface
usign v4l2_fwnode_endpoint_parse.
For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
configuration.
For all other mbus_types, return an error.

Note that parsing the mbus_config from the fw interface is not done during
probing because the camera that's connected to the CSI can change based on
the selected input of the video-mux at runtime.

[0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
[1] include/media/v4l2-subdev.h - line 814

Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
---
 drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 3edbc57be2ca..394a9321a10b 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 {
 	struct v4l2_subdev *sd, *remote_sd;
 	struct media_pad *remote_pad;
+	struct fwnode_handle *ep_node;
+	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
 	int ret;
 
 	if (!priv->src_sd)
@@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 
 	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
 			       remote_pad->index, mbus_cfg);
-	if (ret == -ENOIOCTLCMD)
-		v4l2_err(&priv->sd,
-			 "entity %s does not implement get_mbus_config()\n",
-			 remote_pad->entity->name);
+	if (ret == -ENOIOCTLCMD) {
+		/*
+		 * If the upstream sd does not implement get_mbus_config,
+		 * try to parse the link configuration from its fw_node
+		 */
+		ep_node = fwnode_graph_get_endpoint_by_id(dev_fwnode(remote_sd->dev),
+							  0, 0,
+							  FWNODE_GRAPH_ENDPOINT_NEXT);
+		if (!ep_node)
+			return -ENOTCONN;
+
+		ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
+		fwnode_handle_put(ep_node);
+		if (ret)
+			return ret;
 
+		mbus_cfg->type = ep.bus_type;
+		switch (ep.bus_type) {
+		case V4L2_MBUS_PARALLEL:
+		case V4L2_MBUS_BT656:
+			mbus_cfg->bus.parallel = ep.bus.parallel;
+			break;
+		case V4L2_MBUS_CSI2_DPHY:
+			mbus_cfg->bus.mipi_csi2 = ep.bus.mipi_csi2;
+			break;
+		default:
+			v4l2_err(&priv->sd, "Unsupported mbus_type: %i\n",
+				 ep.bus_type);
+			return -EINVAL;
+		}
+	}
 	return ret;
 }
 
-- 
2.34.1



From mike.leach at linaro.org  Fri Mar 14 07:50:00 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 14 Mar 2025 14:50:00 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <20250109171956.3535294-1-yeoreum.yun@arm.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
Message-ID: <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>

Hi,

On Thu, 9 Jan 2025 at 17:20, Yeoreum Yun <yeoreum.yun at arm.com> wrote:
>
> While enable active config via cscfg_csdev_enable_active_config(),
> active config could be deactivated via configfs' sysfs interface.
> This could make UAF issue in below scenario:
>
> CPU0                                          CPU1
> (sysfs enable)                                load module
>                                               cscfg_load_config_sets()
>                                               activate config. // sysfs
>                                               (sys_active_cnt == 1)
> ...
> cscfg_csdev_enable_active_config()
>   lock(csdev->cscfg_csdev_lock)
>   // here load config activate by CPU1
>   unlock(csdev->cscfg_csdev_lock)
>
>                                               deactivate config // sysfs
>                                               (sys_activec_cnt == 0)
>                                               cscfg_unload_config_sets()
>                                               unload module
>
>   // access to config_desc which freed
>   // while unloading module.
>   cfs_csdev_enable_config
>
> To address this, use cscfg_config_desc's active_cnt as a reference count
> which will be holded when
>     - activate the config.
>     - enable the activated config.
> and put the module reference when config_active_cnt == 0.
>
> Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
> ---
> from v2 to v3:
>     - add cscfg_config_desc_get()/put() (from Suzuki).
>     - remove sys_enable_cnt.
>
> from v1 to v2:
>     - modify commit message.
> ---
>  .../hwtracing/coresight/coresight-config.h    |  2 +-
>  .../coresight/coresight-etm4x-core.c          |  3 +
>  .../hwtracing/coresight/coresight-syscfg.c    | 55 ++++++++++++++-----
>  3 files changed, 44 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
> index b9ebc9fcfb7f..90fd937d3bd8 100644
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
>   * @feats_csdev:references to the device features to enable.
>   */
>  struct cscfg_config_csdev {
> -       const struct cscfg_config_desc *config_desc;
> +       struct cscfg_config_desc *config_desc;
>         struct coresight_device *csdev;
>         bool enabled;
>         struct list_head node;
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 86893115df17..6218ef40acbc 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -986,6 +986,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
>         smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
>
>         raw_spin_unlock(&drvdata->spinlock);
> +
> +       cscfg_csdev_disable_active_config(csdev);
> +
>         cpus_read_unlock();
>
>         /*
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
> index a70c1454b410..8766f72db33e 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg.c
> @@ -391,14 +391,17 @@ static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info)
>  static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner)
>  {
>         struct cscfg_config_csdev *config_csdev, *tmp;
> +       unsigned long flags;
>
>         if (list_empty(&csdev->config_csdev_list))
>                 return;
>
> +       raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
>         list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
>                 if (config_csdev->config_desc->load_owner == load_owner)
>                         list_del(&config_csdev->node);
>         }
> +       raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
>  }
>
>  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
>  }
>  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
>
> +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> +{
> +       if (enable)
> +               return atomic_inc_not_zero(&config_desc->active_cnt);
> +

Not sure why we have an "enable" parameter here - it completely
changes the meaning of the function - with no comment at the start.

>From where it is called it makes figuring out the logic confusing.

Just keep the "get" functionality and drop the parameter & the nz check.

> +       /* when activate config */
> +
> +       /* must ensure that config cannot be unloaded in use */
> +       if (cscfg_owner_get(config_desc->load_owner))
> +               return false;
> +
> +       atomic_inc(&config_desc->active_cnt);
> +
> +       return true;
> +}
> +
> +static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
> +{
> +       if (!atomic_dec_return(&config_desc->active_cnt))
> +               cscfg_owner_put(config_desc->load_owner);
> +}
> +
>  /*
>   * This activate configuration for either perf or sysfs. Perf can have multiple
>   * active configs, selected per event, sysfs is limited to one.
> @@ -890,22 +915,17 @@ static int _cscfg_activate_config(unsigned long cfg_hash)
>                         if (config_desc->available == false)
>                                 return -EBUSY;
>
> -                       /* must ensure that config cannot be unloaded in use */
> -                       err = cscfg_owner_get(config_desc->load_owner);
> -                       if (err)
> +                       if (!cscfg_config_desc_get(config_desc, false)) {

Drop the false parameter here.

> +                               err = -EINVAL;
>                                 break;
> +                       }
> +
>                         /*
>                          * increment the global active count - control changes to
>                          * active configurations
>                          */
>                         atomic_inc(&cscfg_mgr->sys_active_cnt);
>
> -                       /*
> -                        * mark the descriptor as active so enable config on a
> -                        * device instance will use it
> -                        */
> -                       atomic_inc(&config_desc->active_cnt);
> -
>                         err = 0;
>                         dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
>                         break;
> @@ -920,9 +940,8 @@ static void _cscfg_deactivate_config(unsigned long cfg_hash)
>
>         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
>                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> -                       atomic_dec(&config_desc->active_cnt);
>                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> -                       cscfg_owner_put(config_desc->load_owner);
> +                       cscfg_config_desc_put(config_desc);
>                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
>                         break;
>                 }
> @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
>                                      unsigned long cfg_hash, int preset)
>  {
>         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> -       const struct cscfg_config_desc *config_desc;
> +       struct cscfg_config_desc *config_desc;
>         unsigned long flags;
>         int err = 0;
>
> @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
>         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
>         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
>                 config_desc = config_csdev_item->config_desc;
> -               if ((atomic_read(&config_desc->active_cnt)) &&
> -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> +                               cscfg_config_desc_get(config_desc, true)) {

This obfuscates the logic of the comparisons without good reason. With
the true parameter, the function does no "get" operation but just
replicates the logic being replaced - checking the active_cnt is
non-zero.

Restore this to the original logic to make it readable again

Regards

Mike

>                         config_csdev_active = config_csdev_item;
>                         csdev->active_cscfg_ctxt = (void *)config_csdev_active;
>                         break;
> @@ -1097,7 +1116,11 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
>                                 err = -EBUSY;
>                         raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
>                 }
> +
> +               if (err)
> +                       cscfg_config_desc_put(config_desc);
>         }
> +
>         return err;
>  }
>  EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
> @@ -1136,8 +1159,10 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
>         raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
>
>         /* true if there was an enabled active config */
> -       if (config_csdev)
> +       if (config_csdev) {
>                 cscfg_csdev_disable_config(config_csdev);
> +               cscfg_config_desc_put(config_csdev->config_desc);
> +       }
>  }
>  EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
>
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From monstr at monstr.eu  Fri Mar 14 07:54:16 2025
From: monstr at monstr.eu (Michal Simek)
Date: Fri, 14 Mar 2025 15:54:16 +0100
Subject: [GIT PULL] ARM: zynq: dts: changes for 6.15
Message-ID: <CAHTX3d+DZo3thrakBf=QCq91QFeChoizuhVa6oBBj9E+sdEXAQ@mail.gmail.com>

Hi,

please pull these patches to your tree. The most of them are just
aligning current descriptions with DT schema while also adding some
description used in U-Boot which also went to DT schema (like u-boot
node and QSPIs).

Thanks,
Michal


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://github.com/Xilinx/linux-xlnx.git tags/zynq-dt-for-6.15

for you to fetch changes up to 6fd90200aae269daa2f0e86be7bf50246837f9f4:

  ARM: zynq: Do not define address/size-cells for nand-controller
(2025-02-04 09:32:09 +0100)

----------------------------------------------------------------
arm64: Zynq DT changes for 6.15

- Align platforms with dt-schema
- Describe QSPI

----------------------------------------------------------------
Michal Simek (13):
      ARM: zynq: Remove deprecated device_type property
      ARM: zynq: DT: List OCM memory for all platforms
      ARM: zynq: Mark boot-phase-specific device nodes
      ARM: zynq: Wire smcc with nand/nor memories on zc770 platform
      ARM: zynq: Define u-boot bootscrip addr via DT
      ARM: zynq: Point via nvmem0 alias to eeprom on zc702/zc706
      ARM: zynq: Define rtc alias on zc702/zc706
      ARM: zynq: Rename i2c?-gpio to i2c?-gpio-grp
      ARM: zynq: Fix fpga region DT nodes name
      ARM: zynq: Enable QSPIs on platforms
      ARM: zynq: Add sdhci to alias node
      ARM: zynq: Remove ethernet0 alias from Microzed
      ARM: zynq: Do not define address/size-cells for nand-controller

Sai Krishna Potthuri (1):
      ARM: zynq: Replace 'io-standard' with 'power-source' property

 arch/arm/boot/dts/xilinx/zynq-7000.dtsi         | 33 +++++++-
 arch/arm/boot/dts/xilinx/zynq-cc108.dts         | 41 +++++++++-
 arch/arm/boot/dts/xilinx/zynq-ebaz4205.dts      |  2 +
 arch/arm/boot/dts/xilinx/zynq-microzed.dts      | 10 ++-
 arch/arm/boot/dts/xilinx/zynq-parallella.dts    |  1 -
 arch/arm/boot/dts/xilinx/zynq-zc702.dts         | 85 +++++++++++++-------
 arch/arm/boot/dts/xilinx/zynq-zc706.dts         | 67 ++++++++++++---
 arch/arm/boot/dts/xilinx/zynq-zc770-xm010.dts   | 39 ++++++++-
 arch/arm/boot/dts/xilinx/zynq-zc770-xm011.dts   | 31 +++++++
 arch/arm/boot/dts/xilinx/zynq-zc770-xm012.dts   | 35 ++++++++
 arch/arm/boot/dts/xilinx/zynq-zc770-xm013.dts   | 41 +++++++++-
 arch/arm/boot/dts/xilinx/zynq-zed.dts           | 43 +++++++++-
 arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi |  8 ++
 arch/arm/boot/dts/xilinx/zynq-zybo-z7.dts       | 10 ++-
 arch/arm/boot/dts/xilinx/zynq-zybo.dts          |  9 ++-
 15 files changed, 404 insertions(+), 51 deletions(-)


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs


From zoie.lin at mediatek.com  Fri Mar 14 07:53:43 2025
From: zoie.lin at mediatek.com (Zoie Lin)
Date: Fri, 14 Mar 2025 22:53:43 +0800
Subject: [PATCH v5 1/1] i2c: mediatek: add runtime PM operations and bus regulator control
Message-ID: <20250314145407.2900190-1-zoie.lin@mediatek.com>

Introduce support for runtime PM operations in
the I2C driver, enabling runtime suspend and resume functionality.

Although in most platforms, the bus power of i2c is always
on, some platforms disable the i2c bus power in order to meet
low power request.

This implementation includes bus regulator control to facilitate
proper handling of the bus power based on platform requirements.

Signed-off-by: Zoie Lin <zoie.lin at mediatek.com>
---
 drivers/i2c/busses/i2c-mt65xx.c | 74 ++++++++++++++++++++++++++++-----
 1 file changed, 63 insertions(+), 11 deletions(-)

This series is based on linux-next, tag: next-20250314

Changes in v5:
- Add pm runtime autosuspend setting to 250ms
- Add error message for clock enable failure

Changes in v4:
- Removed unnecessary variable initialization.
- Removed unnecessary brackets.
- Corrected grammar issues in the commit message.
- Confirmed autosuspend delay is not necessary.

Changes in v3:
- Removed the autosuspend functionality
- Resumed the I2C bus in mtk_i2c_resume_noirq() 

Changes in v2:
- Author name modification
- Replacement of pm runtime API
- Removal of redundant error messages
- Return value adjustment
- Add runtime pm status check

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 5bd342047d59..a630733a8890 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -1245,8 +1246,8 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	int left_num = num;
 	struct mtk_i2c *i2c = i2c_get_adapdata(adap);
 
-	ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
-	if (ret)
+	ret = pm_runtime_resume_and_get(i2c->dev);
+	if (ret < 0)
 		return ret;
 
 	i2c->auto_restart = i2c->dev_comp->auto_restart;
@@ -1299,7 +1300,9 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	ret = num;
 
 err_exit:
-	clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	pm_runtime_mark_last_busy(i2c->dev);
+	pm_runtime_put_autosuspend(i2c->dev);
+
 	return ret;
 }
 
@@ -1370,6 +1373,38 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
 	return 0;
 }
 
+static int mtk_i2c_runtime_suspend(struct device *dev)
+{
+	struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+	clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	if (i2c->adap.bus_regulator)
+		regulator_disable(i2c->adap.bus_regulator);
+
+	return 0;
+}
+
+static int mtk_i2c_runtime_resume(struct device *dev)
+{
+	int ret;
+	struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+	if (i2c->adap.bus_regulator) {
+		ret = regulator_enable(i2c->adap.bus_regulator);
+		if (ret) {
+			dev_err(dev, "enable regulator failed!\n");
+			return ret;
+		}
+	}
+
+	ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	if (ret)
+		if (i2c->adap.bus_regulator)
+			regulator_disable(i2c->adap.bus_regulator);
+
+	return ret;
+}
+
 static int mtk_i2c_probe(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -1472,13 +1507,19 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	ret = clk_bulk_prepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
 	if (ret) {
 		dev_err(&pdev->dev, "clock enable failed!\n");
 		return ret;
 	}
+
+	platform_set_drvdata(pdev, i2c);
+
+	ret = mtk_i2c_runtime_resume(i2c->dev);
+	if (ret < 0)
+		goto err_clk_bulk_unprepare;
 	mtk_i2c_init_hw(i2c);
-	clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	mtk_i2c_runtime_suspend(i2c->dev);
 
 	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
 			       IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
@@ -1486,19 +1527,22 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev,
 			"Request I2C IRQ %d fail\n", irq);
-		goto err_bulk_unprepare;
+		goto err_clk_bulk_unprepare;
 	}
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
 
 	i2c_set_adapdata(&i2c->adap, i2c);
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret)
-		goto err_bulk_unprepare;
-
-	platform_set_drvdata(pdev, i2c);
+		goto err_pm_runtime_disable;
 
 	return 0;
 
-err_bulk_unprepare:
+err_pm_runtime_disable:
+	pm_runtime_disable(&pdev->dev);
+err_clk_bulk_unprepare:
 	clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
 
 	return ret;
@@ -1510,6 +1554,7 @@ static void mtk_i2c_remove(struct platform_device *pdev)
 
 	i2c_del_adapter(&i2c->adap);
 
+	pm_runtime_disable(&pdev->dev);
 	clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
 }
 
@@ -1518,6 +1563,10 @@ static int mtk_i2c_suspend_noirq(struct device *dev)
 	struct mtk_i2c *i2c = dev_get_drvdata(dev);
 
 	i2c_mark_adapter_suspended(&i2c->adap);
+
+	if (!pm_runtime_status_suspended(dev))
+		mtk_i2c_runtime_suspend(dev);
+
 	clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
 
 	return 0;
@@ -1536,7 +1585,8 @@ static int mtk_i2c_resume_noirq(struct device *dev)
 
 	mtk_i2c_init_hw(i2c);
 
-	clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+	if (pm_runtime_status_suspended(dev))
+		mtk_i2c_runtime_resume(dev);
 
 	i2c_mark_adapter_resumed(&i2c->adap);
 
@@ -1546,6 +1596,8 @@ static int mtk_i2c_resume_noirq(struct device *dev)
 static const struct dev_pm_ops mtk_i2c_pm = {
 	NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq,
 				  mtk_i2c_resume_noirq)
+	SET_RUNTIME_PM_OPS(mtk_i2c_runtime_suspend, mtk_i2c_runtime_resume,
+			   NULL)
 };
 
 static struct platform_driver mtk_i2c_driver = {
-- 
2.45.2



From dev at folker-schwesinger.de  Fri Mar 14 08:09:15 2025
From: dev at folker-schwesinger.de (Folker Schwesinger)
Date: Fri, 14 Mar 2025 15:09:15 +0000
Subject: [PATCH] dmaengine: xilinx_dma: Set dma_device directions
In-Reply-To: <20250314134849.703819-1-thomas.gessler@brueckmann-gmbh.de>
References: <20250314134849.703819-1-thomas.gessler@brueckmann-gmbh.de>
Message-ID: <D8G31H1FDKXJ.3C3P6GDB2JBW@folker-schwesinger.de>

On Fri Mar 14, 2025 at 2:48 PM CET, Thomas Gessler wrote:
> Coalesce the direction bits from the enabled TX and/or RX channels into
> the directions bit mask of dma_device. Without this mask set,
> dma_get_slave_caps() in the DMAEngine fails, which prevents the driver
> from being used with an IIO DMAEngine buffer.
>
> Signed-off-by: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>

Tested-by: Folker Schwesinger <dev at folker-schwesinger.de>

> ---
>  drivers/dma/xilinx/xilinx_dma.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 108a7287f4cd..641aaf0c0f1c 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -3205,6 +3205,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> +	for (i = 0; i < xdev->dma_config->max_channels; i++)
> +		if (xdev->chan[i])
> +			xdev->common.directions |= xdev->chan[i]->direction;
> +
>  	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
>  		for (i = 0; i < xdev->dma_config->max_channels; i++)
>  			if (xdev->chan[i])



From dev at folker-schwesinger.de  Fri Mar 14 08:10:04 2025
From: dev at folker-schwesinger.de (Folker Schwesinger)
Date: Fri, 14 Mar 2025 15:10:04 +0000
Subject: [PATCH] dmaengine: xilinx_dma: Set max segment size
In-Reply-To: <20250314134717.703287-1-thomas.gessler@brueckmann-gmbh.de>
References: <20250314134717.703287-1-thomas.gessler@brueckmann-gmbh.de>
Message-ID: <D8G323LHQBTV.5LVSPQ3DF2NQ@folker-schwesinger.de>

On Fri Mar 14, 2025 at 2:47 PM CET, Thomas Gessler wrote:
> Set the maximumg DMA segment size from the actual core configuration
> value. Without this setting, the default value of 64 KiB is reported,
> and larger sizes cannot be used for IIO DMAEngine buffers.
>
> Signed-off-by: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>

Tested-by: Folker Schwesinger <dev at folker-schwesinger.de>

> ---
>  drivers/dma/xilinx/xilinx_dma.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 108a7287f4cd..4b4a299e3807 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -3114,6 +3114,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> +	dma_set_max_seg_size(xdev->dev, xdev->max_buffer_len);
> +
>  	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
>  		xdev->has_axistream_connected =
>  			of_property_read_bool(node, "xlnx,axistream-connected");



From daniel.baluta at nxp.com  Fri Mar 14 08:17:19 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Fri, 14 Mar 2025 17:17:19 +0200
Subject: [PATCH] remoteproc: imx_dsp_rproc: Document run_stall struct member
Message-ID: <20250314151720.1793719-1-daniel.baluta@nxp.com>

Add documentation for 'run_stall' imx_dsp_rproc struct member.
This also fixes the following warning:

warning: Function parameter or struct member 'run_stall'
not described in 'imx_dsp_rproc'

Fixes: 0184b4fdbad1 ("imx_dsp_rproc: Use reset controller API to control the DSP")
Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503142125.IE33sCto-lkp at intel.com/
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 drivers/remoteproc/imx_dsp_rproc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index bc60edcdd661..90cb1fc13e71 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -96,6 +96,7 @@ enum imx_dsp_rp_mbox_messages {
 /**
  * struct imx_dsp_rproc - DSP remote processor state
  * @regmap: regmap handler
+ * @run_stall: reset control handle used for Run/Stall operation
  * @rproc: rproc handler
  * @dsp_dcfg: device configuration pointer
  * @clks: clocks needed by this device
-- 
2.43.0



From mike.looijmans at topic.nl  Fri Mar 14 07:59:02 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Fri, 14 Mar 2025 15:59:02 +0100
Subject: [PATCH] pcie-xilinx: Support reset GPIO and wait for link-up status
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.c4ab15e9-561e-402d-bf39-9e852485e4fa@emailsignatures365.codetwo.com>
Message-ID: <20250314145933.27902-1-mike.looijmans@topic.nl>

Support providing the PERST reset signal through a devicetree binding.
Thus the system no longer relies on external components to perform the
bus reset.

When the driver loads, the transceiver may still be in the state of
setting up a link. Wait for that to complete before continuing. This
fixes that the PCIe core does not work when loading the PL bitstream
from userspace. There's only milliseconds between the FPGA boot and the
core initializing in that case, and the link won't be up yet. The design
works when the FPGA was programmed in the bootloader, as that will give
the system hundreds of milliseconds to boot.

As the PCIe spec mentions about 120 ms time to establish a link, we'll
allow up to 200ms before giving up.

Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

 drivers/pci/controller/pcie-xilinx.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index 0b534f73a942..cd09deba0ddc 100644
--- a/drivers/pci/controller/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
@@ -15,8 +15,10 @@
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/iopoll.h>
 #include <linux/msi.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
@@ -126,6 +128,14 @@ static inline bool xilinx_pcie_link_up(struct xilinx_pcie *pcie)
 		XILINX_PCIE_REG_PSCR_LNKUP) ? 1 : 0;
 }
 
+static int xilinx_pci_wait_link_up(struct xilinx_pcie *pcie)
+{
+	u32 val;
+
+	return readl_poll_timeout(pcie->reg_base + XILINX_PCIE_REG_PSCR, val,
+			(val & XILINX_PCIE_REG_PSCR_LNKUP), 2000, 200000);
+}
+
 /**
  * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
  * @pcie: PCIe port information
@@ -492,8 +502,21 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie *pcie)
 static void xilinx_pcie_init_port(struct xilinx_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
+	struct gpio_desc *perst_gpio;
+
+	perst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(perst_gpio)) {
+		dev_err(dev, "gpio request failed: %d\n", PTR_ERR(perst_gpio));
+		perst_gpio = NULL;
+	}
+
+	if (perst_gpio) {
+		usleep_range(10, 20); /* Assert the reset for ~10 us */
+		gpiod_set_value_cansleep(perst_gpio, 0);
+		usleep_range(1000, 2000);
+	}
 
-	if (xilinx_pcie_link_up(pcie))
+	if (!xilinx_pci_wait_link_up(pcie))
 		dev_info(dev, "PCIe Link is UP\n");
 	else
 		dev_info(dev, "PCIe Link is DOWN\n");
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From mathis.foerst at mt.com  Fri Mar 14 08:01:07 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 14 Mar 2025 16:01:07 +0100
Subject: [PATCH v3 0/1] media: imx: csi: Parse link configuration from fw_node
Message-ID: <20250314150108.254535-1-mathis.foerst@mt.com>

Hi,

this patch fixes the imx-media-csi driver to work with camera drivers that
do not implement the subdev-pad-operation "get_mbus_format".

Changelog:
v2 -> v3:
- Factor out the function "csi_parse_upstream_fw_link_config" for better
readability.

v1 -> v2:
- No changes (I submitted the wrong patch. I'm sorry for that)

It's the follow up of this discussion:
https://lore.kernel.org/linux-media/Z8AoA6WjbXQufqR6 at kekkonen.localdomain/

I tested the changes successfully on an i.MX6DL with an MT9M114 and an
MT9V032 camera. They both use the parallel camera interface.
Sadly, I don't have the hardware to test with a MIPI CSI-2 camera.

Best regards,
Mathis Foerst

Mathis Foerst (1):
  media: imx: csi: Parse link configuration from fw_node

 drivers/staging/media/imx/imx-media-csi.c | 45 +++++++++++++++++++++--
 1 file changed, 42 insertions(+), 3 deletions(-)


base-commit: ac9c34d1e45a4c25174ced4fc0cfc33ff3ed08c7
-- 
2.34.1



From mathis.foerst at mt.com  Fri Mar 14 08:01:08 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 14 Mar 2025 16:01:08 +0100
Subject: [PATCH v3 1/1] media: imx: csi: Parse link configuration from fw_node
In-Reply-To: <20250314150108.254535-1-mathis.foerst@mt.com>
References: <20250314150108.254535-1-mathis.foerst@mt.com>
Message-ID: <20250314150108.254535-2-mathis.foerst@mt.com>

The imx-media-csi driver requires upstream camera drivers to implement
the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
implement this function are not usable on the i.MX6.

The docs for get_mbus_config [1] say:
@get_mbus_config: get the media bus configuration of a remote sub-device.
            The media bus configuration is usually retrieved from the
            firmware interface at sub-device probe time, immediately
            applied to the hardware and eventually adjusted by the
            driver.

Currently, the imx-media-csi driver is not incorporating the information
from the firmware interface and therefore relies on the implementation of
get_mbus_config by the camera driver.

To be compatible with camera drivers not implementing get_mbus_config
(which is the usual case), use the bus information from the fw interface:

The camera does not necessarily has a direct media bus link to the CSI as
the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
between them on the media pipeline.
The CSI driver already implements the functionality to find the connected
camera sub-device to call get_mbus_config on it.

At this point the driver is modified as follows:
In the case that get_mbus_config is not implemented by the upstream
camera, try to get its endpoint configuration from the firmware interface
usign v4l2_fwnode_endpoint_parse.
For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
configuration.
For all other mbus_types, return an error.

Note that parsing the mbus_config from the fw interface is not done during
probing because the camera that's connected to the CSI can change based on
the selected input of the video-mux at runtime.

[0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
[1] include/media/v4l2-subdev.h - line 814

Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
---
 drivers/staging/media/imx/imx-media-csi.c | 45 +++++++++++++++++++++--
 1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 3edbc57be2ca..e642b4cc6182 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -158,6 +158,42 @@ static inline bool requires_passthrough(struct v4l2_mbus_config *mbus_cfg,
 		 infmt->code != MEDIA_BUS_FMT_YUYV8_2X8);
 }
 
+static int csi_parse_upstream_fw_link_config(struct csi_priv *priv,
+					     struct v4l2_subdev *remote_sd,
+					     struct v4l2_mbus_config *mbus_cfg)
+{
+	struct fwnode_handle *ep_node;
+	struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
+	int ret;
+
+	ep_node = fwnode_graph_get_endpoint_by_id(dev_fwnode(remote_sd->dev),
+						  0, 0,
+						  FWNODE_GRAPH_ENDPOINT_NEXT);
+	if (!ep_node)
+		return -ENOTCONN;
+
+	ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
+	fwnode_handle_put(ep_node);
+	if (ret)
+		return ret;
+
+	mbus_cfg->type = ep.bus_type;
+	switch (ep.bus_type) {
+	case V4L2_MBUS_PARALLEL:
+	case V4L2_MBUS_BT656:
+		mbus_cfg->bus.parallel = ep.bus.parallel;
+		break;
+	case V4L2_MBUS_CSI2_DPHY:
+		mbus_cfg->bus.mipi_csi2 = ep.bus.mipi_csi2;
+		break;
+	default:
+		v4l2_err(&priv->sd, "Unsupported mbus_type: %i\n",
+			 ep.bus_type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /*
  * Queries the media bus config of the upstream entity that provides data to
  * the CSI. This will either be the entity directly upstream from the CSI-2
@@ -211,9 +247,12 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
 			       remote_pad->index, mbus_cfg);
 	if (ret == -ENOIOCTLCMD)
-		v4l2_err(&priv->sd,
-			 "entity %s does not implement get_mbus_config()\n",
-			 remote_pad->entity->name);
+		/*
+		 * If the upstream sd does not implement get_mbus_config,
+		 * try to parse the link configuration from its fw_node
+		 */
+		ret = csi_parse_upstream_fw_link_config(priv, remote_sd,
+							mbus_cfg);
 
 	return ret;
 }
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Fri Mar 14 08:02:43 2025
From: florin.leotescu at oss.nxp.com (Florin Leotescu (OSS))
Date: Fri, 14 Mar 2025 15:02:43 +0000
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250314-encouraging-fabulous-ant-e1f7b0@krzk-bin>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
 <20250314-encouraging-fabulous-ant-e1f7b0@krzk-bin>
Message-ID: <DU7PR04MB11163B2B2D8D429B2667DAA65FFD22@DU7PR04MB11163.eurprd04.prod.outlook.com>

>> +  '#size-cells':
>> +    const: 0
>> +
>> +  '#pwm-cells':
>> +    const: 2
>> +
>> +patternProperties:
>> +  "^fan@[0-4]$":
> 
> Keep consistent quotes, either ' or "
>

Thank you! I will correct that.

>> +    $ref: fan-common.yaml#
>> +    unevaluatedProperties: false
>> +    properties:
>> +      reg:
>> +        description:
>> +          The fan number.
>> +
>> +    required:
>> +      - reg
>> +      - pwms
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    i2c {
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +
>> +        fan_controller: fan-controller at 2f {
>> +            compatible = "microchip,emc2305";
>> +            reg = <0x2f>;
>> +            #address-cells = <1>;
>> +            #size-cells = <0>;
>> +            #pwm-cells = <2>;
>> +
>> +            fan at 0 {
>> +                #cooling-cells = <2>;
>> +                reg = <0x0>;
>
> Please follow DTS coding style, so reg is here the first property.
>

Ok, I will correct it. Thanks!

>> +                pwms = <&fan_controller 1 1>;
>
> It's the same PWM for all fans? So isn't it basically one fan? How do you exactly control them independently, if the same PWM channel is used?
>

It is the same PWM controller, but each fan has a different PWM channel. According to datasheet, the EMC2305 could control up to five programmable fan control circuits.
The driver will parse all fan child nodes during probe and use reg to differentiate the channels, similar as it is done on max6639 hwmon driver. 
The 'pwms' arguments in the example are used to select the polarity and pwm output, which will be parsed in the driver to generate the bits for the registers used to select pwm output and pwm polarity. 
(... <&fan_controller [pwm_polarity] [pwm_output]> ...).  Now, I realized that I should use: <&fan_controller [pwm_channel] [pwm_frequency] [pwm_polarity] [pwm_output]>. I will also document the arguments in #pwm-cells description. 
Thanks!

>> +            };
>> +
>> +            fan at 1 {
>> +                #cooling-cells = <2>;
>> +                reg = <0x1>;
>> +                pwms = <&fan_controller 1 1>;

Best regards,
Florin

From Frank.li at nxp.com  Fri Mar 14 08:03:00 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 14 Mar 2025 11:03:00 -0400
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <20250314064642.fyf3jqylmc6meft7@uda0492258>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
 <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
 <20250313165311.2fj7aus3pcsg4m2c@thinkpad>
 <20250314064642.fyf3jqylmc6meft7@uda0492258>
Message-ID: <Z9RFJDdnoU+aKwF7@lizhi-Precision-Tower-5810>

On Fri, Mar 14, 2025 at 12:16:42PM +0530, Siddharth Vadapalli wrote:
> On Thu, Mar 13, 2025 at 10:23:11PM +0530, Manivannan Sadhasivam wrote:
>
> Hello Mani,
>
> > On Wed, Mar 05, 2025 at 11:20:22AM -0500, Frank Li wrote:
> >
> > If you want a specific patch to be tested, you can add [PATCH RFT] tag.C
> >
> > > According to code in drivers/pci/controller/dwc/pci-dra7xx.c
> > >
> > > dra7xx_pcie_cpu_addr_fixup()
> > > {
> > > 	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
> > > }
> > >
> > > PCI parent bus trim high 4 bits address to 0. Correct ranges in
> > > target-module at 51000000 to algin hardware behavior, which translate PCIe
> > > outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.
> > >
> > > Set 'config' and 'addr_space' reg values to 0.
> > > Change parent bus address of downstream I/O and non-prefetchable memory to
> > > 0.
> > >
> > > Ensure no functional impact on the final address translation result.
> > >
> > > Prepare for the removal of the driver?s cpu_addr_fixup().
> > >
> > > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > > ---
> > >  arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
> > >  1 file changed, 9 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > index b709703f6c0d4..9213fdd25330b 100644
> > > --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > @@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
> > >  			#size-cells = <1>;
> > >  			#address-cells = <1>;
> > >  			ranges = <0x51000000 0x51000000 0x3000>,
> > > -				 <0x20000000 0x20000000 0x10000000>;
> > > +				 <0x00000000 0x20000000 0x10000000>;
> >
> > I'm not able to interpret this properly. So this essentially means that the
> > parent address 0x20000000 is mapped to child address 0x00000000. And the child
> > address is same for other controller as well.
> >
> > Also, the cpu_addr_fixup() is doing the same by masking out the upper 4 bits. I
> > tried looking into the DRA7 TRM, but it says (ECAM_Param_Base_Addr +
> > 0x20000000) where ECAM_Param_Base_Addr = 0x0000_0000 to 0x0FFF_F000.
> >
> > I couldn't relate TRM with the cpu_addr_fixup() callback. Can someone from TI
> > shed light on this?
>
> A "git blame" on the line being modified in dra7.dtsi gives the
> following commit:
> https://github.com/torvalds/linux/commit/c761028ef5e2
> prior to which the ranges is exactly the same as the one being added by
> this patch.

Okay, original one correct reflect hardware behavior.

>
> The cpu_addr_fixup() function was introduced by the following commit:
> https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> with the reason described in
> Section 24.9.4.3.2 PCIe Controller Slave Port
> of the T.R.M. at:
> https://www.ti.com/lit/ug/spruic2d/spruic2d.pdf
> ---------------------------------------------------------------------------
> NOTE:
> The PCIe controller remains fully functional, and able to send transactions
> to, for example, anywhere within the 64-bit PCIe memory space, with the
> appropriate remapping of the 28-bit address by the outbound address
> translation unit (iATU). The limitation is that the total size of addressed
> PCIe regions (in config, memory, IO spaces) must be less than 2^28 bytes.
> ---------------------------------------------------------------------------
>
> The entire sequence is:
> 0) dra7.dtsi had ranges which match the ranges in the current patch.
> 1) cpu_addr_fixup() was added by
> https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> 2) ranges was updated to <0x20000000 0x20000000 0x10000000> by:
> https://github.com/torvalds/linux/commit/c761028ef5e2

Actually this patch is not necessary, with cpu_addr_fixup(), it should
work with/without c761028ef5e2 change because it just the use CPU physical
address, the finial result is exact same.

> 3) ranges is being changed back to its original state of "0)" above.
>
> cpu_addr_fixup() was introduced to remove the following:
> 	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
> in dra7xx_pcie_host_init(). The reason for the above is mentioned in the
> "NOTE" as:
> ---------------------------------------------------------------------------
> The limitation is that the total size of addressed PCIe regions
> (in config, memory, IO spaces) must be less than 2^28 bytes.
> ---------------------------------------------------------------------------
>

That is functional equal.

> I am not sure if Frank is accounting for all of this in the current patch
> as well as the dependent patch series associated with removing
> cpu_addr_fixup().

I have not track back the history. I think before
https://github.com/torvalds/linux/commit/c761028ef5e2 is correct reflect
hardware behavor. axi at 0 trim down 4 bits before send to PCI controller.

The commit message of c761028ef5e2

"In order to update pcie to probe with ti-sysc and genpd, let's update the
pcie ranges to not use address 0 for 0x20000000 and 0x30000000. The range
for 0 is typically used for child devices as the offset from the module
base. In the following patches, we will update pcie to probe with ti-sysc,
and the patches become a bit confusing to read compared to other similar
modules unless we update the ranges first. So let's just use the full
addresses for ranges for the 0x20000000 and 0x30000000 ranges."

I think maybe only ti's bus fabric do address translation at that time, and
DT team and dwc pci driver never consider that before. Now more vendor bus
fabric do address translation. So needn't every platform driver consider it
but it require DTB reflect hardware behavor correctly.

We may revert patch c761028ef5e2 firstly, after some time later, we can
cleanup cpu_addr_fixup().

It will be wondful, if someone help test it.

Frank
>
> Regarding testing the series, I unfortunately don't have the hardware so
> I cannot test it.
>
> Regards,
> Siddharth.


From mike.looijmans at topic.nl  Fri Mar 14 08:04:18 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Fri, 14 Mar 2025 16:04:18 +0100
Subject: [PATCH] phy-zynqmp: Postpone getting clock rate until actually needed
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.7a5992b5-aa78-4b18-bf5c-70f893b58f48@emailsignatures365.codetwo.com>
Message-ID: <20250314150431.28319-1-mike.looijmans@topic.nl>

At probe time the driver would display the following error and abort:
  xilinx-psgtr fd400000.phy: Invalid rate 0 for reference clock 0

This issue was that at probe time, the system has not decided yet whether
the GTR is to be used for SATA (150MHz) or PCIe (100 MHz). The driver
doesn't need to know the clock frequency at that point yet, so wait until
the lane is actually being initialized before requesting the clock rate
setting.

Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

 drivers/phy/xilinx/phy-zynqmp.c | 61 ++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index 05a4a59f7c40..e29e3e51d380 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -222,7 +222,6 @@ struct xpsgtr_phy {
  * @siou: siou base address
  * @gtr_mutex: mutex for locking
  * @phys: PHY lanes
- * @refclk_sscs: spread spectrum settings for the reference clocks
  * @clk: reference clocks
  * @tx_term_fix: fix for GT issue
  * @saved_icm_cfg0: stored value of ICM CFG0 register
@@ -235,7 +234,6 @@ struct xpsgtr_dev {
 	void __iomem *siou;
 	struct mutex gtr_mutex; /* mutex for locking */
 	struct xpsgtr_phy phys[NUM_LANES];
-	const struct xpsgtr_ssc *refclk_sscs[NUM_LANES];
 	struct clk *clk[NUM_LANES];
 	bool tx_term_fix;
 	unsigned int saved_icm_cfg0;
@@ -398,13 +396,40 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
 	return ret;
 }
 
+/* Get the spread spectrum (SSC) settings for the reference clock rate */
+static const struct xpsgtr_ssc *xpsgtr_find_sscs(struct xpsgtr_phy *gtr_phy)
+{
+	unsigned long rate;
+	struct clk *clk;
+	unsigned int i;
+
+	clk = gtr_phy->dev->clk[gtr_phy->refclk];
+	rate = clk_get_rate(clk);
+
+	for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
+		/* Allow an error of 100 ppm */
+		unsigned long error = ssc_lookup[i].refclk_rate / 10000;
+
+		if (abs(rate - ssc_lookup[i].refclk_rate) < error)
+			return &ssc_lookup[i];
+	}
+
+	dev_err(gtr_phy->dev->dev, "Invalid rate %lu for reference clock %u\n",
+		rate, gtr_phy->refclk);
+
+	return NULL;
+}
+
 /* Configure PLL and spread-sprectrum clock. */
 static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
 {
 	const struct xpsgtr_ssc *ssc;
 	u32 step_size;
 
-	ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk];
+	ssc = xpsgtr_find_sscs(gtr_phy);
+	if (!ssc)
+		return;
+
 	step_size = ssc->step_size;
 
 	xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane),
@@ -823,8 +848,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
 	}
 
 	refclk = args->args[3];
-	if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) ||
-	    !gtr_dev->refclk_sscs[refclk]) {
+	if (refclk >= ARRAY_SIZE(gtr_dev->clk)) {
 		dev_err(dev, "Invalid reference clock number %u\n", refclk);
 		return ERR_PTR(-EINVAL);
 	}
@@ -928,9 +952,7 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
 {
 	unsigned int refclk;
 
-	for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->refclk_sscs); ++refclk) {
-		unsigned long rate;
-		unsigned int i;
+	for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->clk); ++refclk) {
 		struct clk *clk;
 		char name[8];
 
@@ -946,29 +968,6 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
 			continue;
 
 		gtr_dev->clk[refclk] = clk;
-
-		/*
-		 * Get the spread spectrum (SSC) settings for the reference
-		 * clock rate.
-		 */
-		rate = clk_get_rate(clk);
-
-		for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
-			/* Allow an error of 100 ppm */
-			unsigned long error = ssc_lookup[i].refclk_rate / 10000;
-
-			if (abs(rate - ssc_lookup[i].refclk_rate) < error) {
-				gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i];
-				break;
-			}
-		}
-
-		if (i == ARRAY_SIZE(ssc_lookup)) {
-			dev_err(gtr_dev->dev,
-				"Invalid rate %lu for reference clock %u\n",
-				rate, refclk);
-			return -EINVAL;
-		}
 	}
 
 	return 0;
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From monstr at monstr.eu  Fri Mar 14 08:05:32 2025
From: monstr at monstr.eu (Michal Simek)
Date: Fri, 14 Mar 2025 16:05:32 +0100
Subject: [GIT PULL] arm64: ZynqMP SoC changes for v6.15
Message-ID: <CAHTX3d+T+_zvwAVqGO+J_+Yia+wXAGsaEbPi1ye1AUYXoq6dmw@mail.gmail.com>

Hi,

please pull this patch to your tree. Tree is based on v6.13-rc1 but
that shouldn't be a problem.
There is no conflict with the latest Linus tree and also don't see any
issue with Linux next.
The patch is pretty much cleanup because firmware is not using that
parameters anyway.

Thanks,
Michal


The following changes since commit 40384c840ea1944d7c5a392e8975ed088ecf0b37:

  Linux 6.13-rc1 (2024-12-01 14:28:56 -0800)

are available in the Git repository at:

  https://github.com/Xilinx/linux-xlnx.git tags/zynqmp-soc-for-6.15

for you to fetch changes up to 5abc174016052caff1bcf4cedb159bd388411e98:

  firmware: xilinx: Dont send linux address to get fpga config get
status (2025-02-17 15:40:01 +0100)

----------------------------------------------------------------
arm64: ZynqMP SoC changes for 6.15

- Align fpga config status with firmware

----------------------------------------------------------------
Siva Durga Prasad Paladugu (1):
      firmware: xilinx: Dont send linux address to get fpga config get status

 drivers/firmware/xilinx/zynqmp.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs


From broonie at kernel.org  Fri Mar 14 08:07:43 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 15:07:43 +0000
Subject: [PATCH 6.12 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <Z9Q_zW_mM-v2iPHC@arm.com>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-3-ddc16609d9ba@kernel.org>
 <2025031427-yiddish-unrented-2bc2@gregkh>
 <Z9Q_zW_mM-v2iPHC@arm.com>
Message-ID: <fb6255b7-0ba2-45a3-93fd-2ebebfac61be@sirena.org.uk>

On Fri, Mar 14, 2025 at 02:40:13PM +0000, Catalin Marinas wrote:
> On Fri, Mar 14, 2025 at 06:32:45AM +0100, Greg Kroah-Hartman wrote:

> > What is the upstream git id for this on?

> It seems to be 8eca7f6d5100 ("KVM: arm64: Remove host FPSIMD saving for
> non-protected KVM").

Yes, sorry.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/6ca59bb4/attachment.sig>

From linux at roeck-us.net  Fri Mar 14 08:17:11 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 14 Mar 2025 08:17:11 -0700
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <DU7PR04MB11163B2B2D8D429B2667DAA65FFD22@DU7PR04MB11163.eurprd04.prod.outlook.com>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
 <20250314-encouraging-fabulous-ant-e1f7b0@krzk-bin>
 <DU7PR04MB11163B2B2D8D429B2667DAA65FFD22@DU7PR04MB11163.eurprd04.prod.outlook.com>
Message-ID: <c3d438aa-504f-4d13-909e-ed9be0394b75@roeck-us.net>

On 3/14/25 08:02, Florin Leotescu (OSS) wrote:
>>> +  '#size-cells':
>>> +    const: 0
>>> +
>>> +  '#pwm-cells':
>>> +    const: 2
>>> +
>>> +patternProperties:
>>> +  "^fan@[0-4]$":
>>
>> Keep consistent quotes, either ' or "
>>
> 
> Thank you! I will correct that.
> 
>>> +    $ref: fan-common.yaml#
>>> +    unevaluatedProperties: false
>>> +    properties:
>>> +      reg:
>>> +        description:
>>> +          The fan number.
>>> +
>>> +    required:
>>> +      - reg
>>> +      - pwms
>>> +
>>> +required:
>>> +  - compatible
>>> +  - reg
>>> +
>>> +additionalProperties: false
>>> +
>>> +examples:
>>> +  - |
>>> +    i2c {
>>> +        #address-cells = <1>;
>>> +        #size-cells = <0>;
>>> +
>>> +        fan_controller: fan-controller at 2f {
>>> +            compatible = "microchip,emc2305";
>>> +            reg = <0x2f>;
>>> +            #address-cells = <1>;
>>> +            #size-cells = <0>;
>>> +            #pwm-cells = <2>;
>>> +
>>> +            fan at 0 {
>>> +                #cooling-cells = <2>;
>>> +                reg = <0x0>;
>>
>> Please follow DTS coding style, so reg is here the first property.
>>
> 
> Ok, I will correct it. Thanks!
> 
>>> +                pwms = <&fan_controller 1 1>;
>>
>> It's the same PWM for all fans? So isn't it basically one fan? How do you exactly control them independently, if the same PWM channel is used?
>>
> 
> It is the same PWM controller, but each fan has a different PWM channel. According to datasheet, the EMC2305 could control up to five programmable fan control circuits.
> The driver will parse all fan child nodes during probe and use reg to differentiate the channels, similar as it is done on max6639 hwmon driver.
> The 'pwms' arguments in the example are used to select the polarity and pwm output, which will be parsed in the driver to generate the bits for the registers used to select pwm output and pwm polarity.
> (... <&fan_controller [pwm_polarity] [pwm_output]> ...).  Now, I realized that I should use: <&fan_controller [pwm_channel] [pwm_frequency] [pwm_polarity] [pwm_output]>. I will also document the arguments in #pwm-cells description.
> Thanks!
> 

Please also document that the channel assignment is fixed. Technically it
doesn't even make sense to specify the pwm channel (it is fixed and
matches "reg"). I don't know if the channel number can be omitted from pwms.
All you really need is polarity, frequency, and output type.

I am not really sure what to do if the channel number is mandatory.
If it is, I'd suggest to document it as mandated but not needed/used,
and then ignore it in the code.

Thanks,
Guenter



From Frank.li at nxp.com  Fri Mar 14 08:21:19 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 14 Mar 2025 11:21:19 -0400
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <Z9NikZqmmnkt/GQm@lizhi-Precision-Tower-5810>
References: <20250313-pci_fixup_addr-v11-6-01d2313502ab@nxp.com>
 <20250313220450.GA755590@bhelgaas>
 <Z9NikZqmmnkt/GQm@lizhi-Precision-Tower-5810>
Message-ID: <Z9RJbyoFdkiYHXu9@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 06:56:17PM -0400, Frank Li wrote:
> On Thu, Mar 13, 2025 at 05:04:50PM -0500, Bjorn Helgaas wrote:
> > On Thu, Mar 13, 2025 at 11:38:42AM -0400, Frank Li wrote:
> > > The 'ranges' property at PCI controller parent bus can indicate address
> > > translation information. Most system's bus fabric use 1:1 map between input
> > > and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.
> >
> > I think you've used reg["addr_space"] to get the offset for Endpoints
> > forever.
>
> Yes, it still need ranges informaiton at parent bus.
>
> 	bus at 000
> 	{
> 		ranges = <...>; [1] /* still need this */
> 		pcie {
> 			ranges = <...>;[2]
> 		};
> 		pcie-ep {};
> 	}
>
> >
> > I just noticed that through v9, you used 'ranges' to get the offset
> > for the Root Complex (with "Add parent_bus_offset to resource_entry"),
> > and I think v10 switched to use reg["config"] instead.
> >
> > I think I originally proposed the idea of "Add parent_bus_offset to
> > resource_entry" patch, but I think it turned out to be kind of an ugly
> > approach.
> >
> > Anyway, IIUC this v11 patch actually uses reg["config"] to compute the
> > offset, not 'ranges', so we should probably update the subject and
> > commit log to reflect that, and maybe remove the now-unused bits of
> > the devicetree example.
>
> We use reg["config"] to detect offset, but still need parent dts's ranges.
> There are two ranges, one is at parent pci bus [1], the other is under
> 'pci bus' [2].

Beside, luckly dwc use reg["config"] to indicate config space. but dt also
define ranges [2] under pcie node, which can also include 'config's space.

cadence also use reg["cfg"] to do that.
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");

I am not sure why both choose use reg[] instead of [2]ranges under
pcie node. But the result make our situation simpler.

Frank

>
> Although use reg["config"], but still need ranges [1]. And information at
> ranges [2] also need be correct.
>
> The whole devicetree example also validate to help write address translate
> informaiton.
>
> >
> > I do worry a little bit about the assumption that the offset of
> > reg["config"] is the same as the offset of the other pieces.  The main
> > place we use the offset on RCs is for the ATU, and isn't the ATU in
> > the MemSpace area at 0x8000_0000 below?
>
> No, "Bus fabric" only decode input address from "0x7000_0000..UPLIMIT".
> Then output address to 0x8000_0000..UPLIMIT. So below 0x8000_0000 never
> happen.
>
> >
> > It's great that in this case the 0x7ff0_0000 to 0x8ff0_0000 "config"
> > offset is the same as the 0x7000_0000 to 0x8000_0000 MemSpace offset,
> > but I don't know that this is guaranteed for all designs.
>
> So far, it is the same for use dwc chips. If we meet difference, we can
> add later.
>
> reg["config"] only simplied our implement base on the offset is the same.
> But whole concept is unchanged.
>
> Frank
>
> >
> > v9:
> >   [PATCH v9 3/7] PCI: Add parent_bus_offset to resource_entry
> >     https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-3-3c4bb506f665 at nxp.com
> >   [PATCH v9 5/7] PCI: dwc: ep: Add parent_bus_addr for outbound window
> >     https://lore.kernel.org/r/20250128-pci_fixup_addr-v9-5-3c4bb506f665 at nxp.com
> >
> > v10:
> >   [PATCH v10 05/10] PCI: dwc: Use devicetree 'ranges' property to get rid of cpu_addr_fixup() callback
> >     https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-5-409dafc950d1 at nxp.com
> >   [PATCH v10 06/10] PCI: dwc: ep: Add parent_bus_addr for outbound window
> >     https://lore.kernel.org/r/20250310-pci_fixup_addr-v10-6-409dafc950d1 at nxp.com
> >
> > > See below diagram:
> > >
> > >             ???????????                    ??????????????
> > >  ???????    ?         ? IA: 0x8ff8_0000    ?            ?
> > >  ? CPU ??????   ?????????????????????????  ? PCI        ?
> > >  ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
> > >   CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
> > > 0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
> > >             ?      ?  ?             ?   ?  ?            ?   PCI Addr
> > > 0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
> > >             ?         ?             ?      ?            ?    0
> > > 0x7000_0000??????????????????????   ?      ?            ?
> > >             ???????????         ?   ???????? CfgSpace  ???????????????
> > >              BUS Fabric         ?          ?            ?    0
> > >                                 ?          ?            ?
> > >                                 ???????????? MemSpace  ???????????????
> > >                         IA: 0x8000_0000    ?            ?  0x8000_0000
> > >                                            ??????????????
> > >
> > > bus at 5f000000 {
> > > 	compatible = "simple-bus";
> > > 	#address-cells = <1>;
> > > 	#size-cells = <1>;
> > > 	ranges = <0x80000000 0x0 0x70000000 0x10000000>;
> > >
> > > 	pcie at 5f010000 {
> > > 		compatible = "fsl,imx8q-pcie";
> > > 		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> > > 		reg-names = "dbi", "config";
> > > 		#address-cells = <3>;
> > > 		#size-cells = <2>;
> > > 		device_type = "pci";
> > > 		bus-range = <0x00 0xff>;
> > > 		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> > > 			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
> > > 	...
> > > 	};
> > > };
> > >
> > > Term Intermediate address (IA) here means the address just before PCIe
> > > controller. After ATU use this IA instead CPU address, cpu_addr_fixup() can
> > > be removed.
> > >
> > > Use reg-name "config" to detect parent_bus_addr_offset. Suppose the offset
> > > is the same for all kinds of address translation.
> > >
> > > Just set parent_bus_offset, but doesn't use it, so no functional change
> > > intended yet.
> >
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -474,6 +474,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
> > >  		pp->io_base = pci_pio_to_address(win->res->start);
> > >  	}
> > >
> > > +	/*
> > > +	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
> > > +	 * so have to call dw_pcie_init_parent_bus_offset() after init
> > > +	 * pp->io_base.
> > > +	 */
> > > +	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > >  	/* Set default bus ops */
> > >  	bridge->ops = &dw_pcie_ops;
> > >  	bridge->child_ops = &dw_child_pcie_ops;
> > >
> > > --
> > > 2.34.1
> > >


From nicolas.frattaroli at collabora.com  Fri Mar 14 08:24:08 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Fri, 14 Mar 2025 16:24:08 +0100
Subject: [PATCH 0/3] Rockchip IOMMU fixes
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <13295142.O9o76ZdvQC@workhorse>

On Thursday, 13 March 2025 18:31:03 Central European Standard Time Robin 
Murphy wrote:
> Hi all,
> 
> I was expecting my DT probing change to flush out issues, and it seems
> some weaknesses in rockchip-iommu were the first to show. The first two
> patches here get things working again for me on my RK3399 NanoPC-T4
> (with a console on HDMI exercising the VOP MMU), the 3rd patch just
> finishes the cleanup since I was there and could test it.
> 
> Thanks,
> Robin.
> 
> Robin Murphy (3):
>   iommu/rockchip: Allocate per-device data sensibly
>   iommu/rockchip: Register in a sensible order
>   iommu/rockchip: Retire global dma_dev workaround
> 
>  drivers/iommu/rockchip-iommu.c | 61 +++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 35 deletions(-)

Tested this series on an RK3576, which indeed fixes the boot panic I get with 
next-20250314. After looking at the patches with the full function context, I 
can't see any obvious issues.

For the whole series:

Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
Tested-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>

Kind regards,
Nicolas Frattaroli




From YeoReum.Yun at arm.com  Fri Mar 14 08:24:58 2025
From: YeoReum.Yun at arm.com (Yeo Reum Yun)
Date: Fri, 14 Mar 2025 15:24:58 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
 <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
Message-ID: <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>

Hi, Mike.

> >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> >  }
> >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> >
> > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > +{
> > +       if (enable)
> > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > +
>
> Not sure why we have an "enable" parameter here - it completely
> changes the meaning of the function - with no comment at the start.

Sorry. But what I intended is to distinguish
    - activation of config
    - enable of activated config.
Because, current coresight doesn't grab the module reference on enable of activate config,
But It grabs that reference only in activation.
That's why I used to "enable" parameter to distinguish this
while I integrate with module_owner count.

> >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > -                       atomic_dec(&config_desc->active_cnt);
> >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > -                       cscfg_owner_put(config_desc->load_owner);
> > +                       cscfg_config_desc_put(config_desc);
> >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> >                         break;
> >                 }
> > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> >                                      unsigned long cfg_hash, int preset)
> >  {
> >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > -       const struct cscfg_config_desc *config_desc;
> > +       struct cscfg_config_desc *config_desc;
> >         unsigned long flags;
> >         int err = 0;
> >
> > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> >                 config_desc = config_csdev_item->config_desc;
> > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > +                               cscfg_config_desc_get(config_desc, true)) {
> >
> This obfuscates the logic of the comparisons without good reason. With
> the true parameter, the function does no "get" operation but just
> replicates the logic being replaced - checking the active_cnt is
> non-zero.
>
> Restore this to the original logic to make it readable again

It's not a replicates of comparsion logic, but if true,
It get the reference of active_cnt but not get module reference.
The fundemental fault in the UAF becase of just "atomic_read()"
so, it should hold reference in here.

So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
I think there're two way to modfiy.

    1. cscfg_config_desc_get()/put() always grab/drop the module count. 
    2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
        with cscfg_owner_get()/put()
 
Any thougt?

Thanks!

 


From mathis.foerst at mt.com  Fri Mar 14 08:26:14 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 14 Mar 2025 16:26:14 +0100
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z86-AFnPQ2wXKidi@valkosipuli.retiisi.eu>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
 <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
 <Z8r21Z2HthBwGDSq@mt.com>
 <Z86-AFnPQ2wXKidi@valkosipuli.retiisi.eu>
Message-ID: <Z9RKllMJ0Duac83Y@mt.com>

On Mon, Mar 10, 2025 at 10:25:04AM +0000, Sakari Ailus wrote:
Hi Sakari,

> Hi Mathis,
> 
> On Fri, Mar 07, 2025 at 02:38:29PM +0100, Mathis Foerst wrote:
> > Hi Sakari, Hi Dan,
> > 
> > thanks a lot for your feedback.
> > 
> > On Thu, Mar 06, 2025 at 09:13:46PM +0000, Sakari Ailus wrote:
> > > Hi Dan,
> > > 
> > > On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> > > > On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > > > > Hi Mathis,
> > > > > 
> > > > > Thanks for the patch.
> > > > > 
> > > > > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > > > > The imx-media-csi driver requires upstream camera drivers to implement
> > > > > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > > > > implement this function are not usable on the i.MX6.
> > > > > > 
> > > > > > The docs for get_mbus_config [1] say:
> > > > > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > > > > >             The media bus configuration is usually retrieved from the
> > > > > >             firmware interface at sub-device probe time, immediately
> > > > > >             applied to the hardware and eventually adjusted by the
> > > > > >             driver.
> > > > > > 
> > > > > > Currently, the imx-media-csi driver is not incorporating the information
> > > > > > from the firmware interface and therefore relies on the implementation of
> > > > > > get_mbus_config by the camera driver.
> > > > > > 
> > > > > > To be compatible with camera drivers not implementing get_mbus_config
> > > > > > (which is the usual case), use the bus information from the fw interface:
> > > > > > 
> > > > > > The camera does not necessarily has a direct media bus link to the CSI as
> > > > > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > > > > between them on the media pipeline.
> > > > > > The CSI driver already implements the functionality to find the connected
> > > > > > camera sub-device to call get_mbus_config on it.
> > > > > > 
> > > > > > At this point the driver is modified as follows:
> > > > > > In the case that get_mbus_config is not implemented by the upstream
> > > > > > camera, try to get its endpoint configuration from the firmware interface
> > > > > > usign v4l2_fwnode_endpoint_parse.
> > > > > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > > > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > > > > configuration.
> > > > > > For all other mbus_types, return an error.
> > > > > > 
> > > > > > Note that parsing the mbus_config from the fw interface is not done during
> > > > > > probing because the camera that's connected to the CSI can change based on
> > > > > > the selected input of the video-mux at runtime.
> > > > > > 
> > > > > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > > > > [1] include/media/v4l2-subdev.h - line 814
> > > > > > 
> > > > > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > > > > ---
> > > > > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > > > > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > index 3edbc57be2ca..394a9321a10b 100644
> > > > > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > > > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > >  {
> > > > > >  	struct v4l2_subdev *sd, *remote_sd;
> > > > > >  	struct media_pad *remote_pad;
> > > > > > +	struct fwnode_handle *ep_node;
> > > > > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > > > > 
> > > > > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > > > > field to zero this way is redundant, just use {}.
> > > > > 
> > > > 
> > > > I was going to respond in much the same way.  This is equivalen to:
> > > > 
> > > > struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
> > > 
> > > Thinking about this in a context of parsing the endpoint, in fact the
> > > bus_type should be specified. Presumably the hardware is D-PHY, so the
> > > correct value would be V4L2_MBUS_CSI2_DPHY. This way
> > > v4l2_fwnode_endpoint_parse() doesn't need to guess.
> > 
> > I think we must use "bus_type = V4L2_MBUS_UNKNOWN" here:
> > 
> > The i.MX6 has two types of camera interfaces: Parallel and MIPI CSI-2.
> > They are connected either directly or via a video-mux to the CSIs
> > (See IMX6DQRM.pdf - Figure 9-3 for the connection diagram)
> > 
> > Pre-defining V4L2_MBUS_CSI2_DPHY here would let
> > v4l2_fwnode_endpoint_parse() fail if the camera uses the parallel bus.
> > 
> > We could distinguish between MIPI CSI-2 and Parallel input by checking
> > the grp_id of the upstream device like it's already done in
> > csi_get_upstream_mbus_config().
> > But for the Parallel case we still can't know if we should set bus_type
> > to V4L2_MBUS_PARALLEL or to V4L2_MBUS_BT656 - the i.MX6 supports both
> > formats on the parallel interface.
> > 
> > That's why I would argue that v4l2_fwnode_endpoint_parse() must figure
> > out the bus_type from the fw node.
> 
> Right, nowadays you can indeed do this -- it wasn't a long ago when you
> couldn't. I presume the bindings do specify the bus-type property is
> mandatory? Where are the bindings btw.?
> 

>From my understanding, it's not even required to set the bus-type as 
v4l2_fwnode_endpoint_parse() will try to parse the endpoint first as a
CSI-2 bus and in case of failure as a Parallel bus if the bus-type is
unknown (see drivers/media/v4l2-core/v4l2-fwnode.c#L493).

About the bindings:

There are bindings for the MIPI CSI-2 receiver:
Documentation/devicetree/bindings/media/imx.txt
I think here it's not necessary to make the bus-type property mandatory
as the imx6-mipi-csi2 driver enforces V4L2_MBUS_CSI2_DPHY anyhow
(see drivers/staging/media/imx/imx6-mipi-csi2.c#L677).

For the case of a camera with parallel bus, the camera endpoint is
connected to a video-mux and not directly to the CSI. Therefore, we cannot
make the bus-type property mandatory on this endpoint as it this wouldn't
apply to other use-cases of video-mux.

> > 
> > > 
> > > > 
> > > > > >  	int ret;
> > > > > >  
> > > > > >  	if (!priv->src_sd)
> > > > > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > >  
> > > > > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > > > > >  			       remote_pad->index, mbus_cfg);
> > > > > > -	if (ret == -ENOIOCTLCMD)
> > > > > > -		v4l2_err(&priv->sd,
> > > > > > -			 "entity %s does not implement get_mbus_config()\n",
> > > > > > -			 remote_pad->entity->name);
> > > > > > +	if (ret == -ENOIOCTLCMD) {
> > > > > 
> > > > > 	if (!ret)
> > > > > 		return 0;
> > > > > 
> > > > > And you can unindent the rest.
> > > > 
> > > > I was going to say this too but then I thought actually this needs to
> > > > be:
> > > > 
> > > > 	if (ret != -ENOIOCTLCMD)
> > > > 		return ret;
> > > > 
> > > > Which is weird.  Better to break all the new code into a separate
> > > > helper function.
> > > > 
> > > > 	if (ret == -ENOIOCTLCMD)
> > > > 		ret = parse_fw_link_config_stuff();
> > > > 
> > > > 	return ret;
> > 
> > Good point. I factored out a helper function as suggested.
> > 
> > > 
> > > Indeed. get_mbus_config() presumably wouldn't return an error but
> > > correctness is usually a good idea.
> > > 
> 
> -- 
> Regards,
> 
> Sakari Ailus

Best regards,
Mathis Foerst


From jbrunet at baylibre.com  Fri Mar 14 08:32:17 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 14 Mar 2025 16:32:17 +0100
Subject: [PATCH] clk: amlogic: a1: fix a typo
In-Reply-To: <20241231062552.2982266-1-jian.hu@amlogic.com>
References: <20241231062552.2982266-1-jian.hu@amlogic.com>
Message-ID: <174196633722.1526311.3272915728848116488.b4-ty@baylibre.com>

Applied to clk-meson (clk-meson-next), thanks!

[1/1] clk: amlogic: a1: fix a typo
      https://github.com/BayLibre/clk-meson/commit/b3c221e752c4

Best regards,
--
Jerome



From peter.griffin at linaro.org  Fri Mar 14 08:38:01 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 14 Mar 2025 15:38:01 +0000
Subject: [PATCH 0/2] Add dma-coherent for gs101 UFS dt node
Message-ID: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>

ufs-exynos driver enables the shareability option for gs101 which
means the descriptors need to be allocated as cacheable.

Fix the DT node and update bindings to add the dma-coherent property.

This fixes the UFS stability issues we have seen with the upstream
UFS driver.

Note this DT fix can go in independently of the other UFS fixes series
I sent recently [1], as the bootloader already leaves the sharability
bits enabled.

regards,

Peter

[1] https://lore.kernel.org/linux-scsi/20250226220414.343659-1-peter.griffin at linaro.org/

To: Andr? Draszik <andre.draszik at linaro.org>
To: Tudor Ambarus <tudor.ambarus at linaro.org>
To: Rob Herring <robh at kernel.org>
To: Krzysztof Kozlowski <krzk+dt at kernel.org>
To: Conor Dooley <conor+dt at kernel.org>
To: Alim Akhtar <alim.akhtar at samsung.com>
To: Avri Altman <avri.altman at wdc.com>
To: Bart Van Assche <bvanassche at acm.org>
To: Martin K. Petersen <martin.petersen at oracle.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-scsi at vger.kernel.org
Cc: kernel-team at android.com
Cc: willmcvicker at google.com

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Peter Griffin (2):
      arm64: dts: exynos: gs101: ufs: add dma-coherent property
      scsi: ufs: dt-bindings: exynos: add dma-coherent property for gs101

 Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml | 2 ++
 arch/arm64/boot/dts/exynos/google/gs101.dtsi                  | 1 +
 2 files changed, 3 insertions(+)
---
base-commit: b323d8e7bc03d27dec646bfdccb7d1a92411f189
change-id: 20250314-ufs-dma-coherent-980f2467690d

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From peter.griffin at linaro.org  Fri Mar 14 08:38:02 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 14 Mar 2025 15:38:02 +0000
Subject: [PATCH 1/2] arm64: dts: exynos: gs101: ufs: add dma-coherent
 property
In-Reply-To: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
Message-ID: <20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro.org>

ufs-exynos driver configures the sysreg shareability as
cacheable for gs101 so we need to set the dma-coherent
property so the descriptors are also allocated cacheable.

This fixes the UFS stability issues we have seen with
the upstream UFS driver on gs101.

Fixes: 4c65d7054b4c ("arm64: dts: exynos: gs101: Add ufs and ufs-phy dt nodes")
Cc: stable at vger.kernel.org
Suggested-by: Will McVicker <willmcvicker at google.com>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm64/boot/dts/exynos/google/gs101.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/exynos/google/gs101.dtsi b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
index c5335dd59dfe9fcf8c64d66a466799600f8447b0..cf30128ef004568f01b1c7150c5585ba267d64bc 100644
--- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi
+++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
@@ -1360,6 +1360,7 @@ ufs_0: ufs at 14700000 {
 				 <&cmu_hsi2 CLK_GOUT_HSI2_SYSREG_HSI2_PCLK>;
 			clock-names = "core_clk", "sclk_unipro_main", "fmp",
 				      "aclk", "pclk", "sysreg";
+			dma-coherent;
 			freq-table-hz = <0 0>, <0 0>, <0 0>, <0 0>, <0 0>, <0 0>;
 			pinctrl-0 = <&ufs_rst_n &ufs_refclk_out>;
 			pinctrl-names = "default";

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Fri Mar 14 08:38:03 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 14 Mar 2025 15:38:03 +0000
Subject: [PATCH 2/2] scsi: ufs: dt-bindings: exynos: add dma-coherent
 property for gs101
In-Reply-To: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
Message-ID: <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org>

dma-coherent property is required for gs101 as ufs-exynos enables
sharability.

Fixes: 438e23b61cd4 ("scsi: ufs: dt-bindings: exynos: Add gs101 compatible")
Cc: stable at vger.kernel.org
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
index 720879820f6616a30cae2db3d4d2d22e847666c4..5dbb7f6a8c354b82685c521e70655e106f702a8d 100644
--- a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
+++ b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
@@ -96,6 +96,8 @@ allOf:
         clock-names:
           minItems: 6
 
+        dma-coherent: true
+
     else:
       properties:
         clocks:

-- 
2.49.0.rc1.451.g8f38331e32-goog



From arnd at kernel.org  Fri Mar 14 08:35:37 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Fri, 14 Mar 2025 16:35:37 +0100
Subject: [PATCH] reset: imx: fix incorrect module device table
Message-ID: <20250314153541.3555813-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

The ID table is for of_device_id, not platform_device_id:

ERROR: modpost: drivers/reset/reset-imx-scu: type mismatch between imx_scu_reset_ids[] and MODULE_DEVICE_TABLE(platform, ...)

Fixes: 6b64fde5c183 ("reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/reset/reset-imx-scu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/reset/reset-imx-scu.c b/drivers/reset/reset-imx-scu.c
index d3074eaad4c9..919fc29f944c 100644
--- a/drivers/reset/reset-imx-scu.c
+++ b/drivers/reset/reset-imx-scu.c
@@ -85,7 +85,7 @@ static const struct of_device_id imx_scu_reset_ids[] = {
 	{ .compatible = "fsl,imx-scu-reset", },
 	{}
 };
-MODULE_DEVICE_TABLE(platform, imx_scu_reset_ids);
+MODULE_DEVICE_TABLE(of, imx_scu_reset_ids);
 
 static struct platform_driver imx_scu_reset_driver = {
 	.probe          = imx_scu_reset_probe,
-- 
2.39.5



From nicolas.frattaroli at collabora.com  Fri Mar 14 08:35:50 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Fri, 14 Mar 2025 16:35:50 +0100
Subject: [PATCH] arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5
 gmac0
Message-ID: <20250314-rk3576-sige5-eth-clk-begone-v1-1-2858338fc555@collabora.com>

The GPIO3 A4 pin on the ArmSoM Sige5 is routed to the 40-pin GPIO
header. This pin can serve a variety of functions, including ones of
questionable use to us on a GPIO header such as the 25MHz clock of the
ethernet controller.

Unfortunately, this is the precise function that it is being claimed for
by the gmac0 node in the Sige5 board dts, meaning it can't be used for
anything else despite serving no useful function in this role. Since it
goes through a RS0108 bidirectional voltage level translator with a
maximum data rate of 24Mbit/s in push-pull mode and 2Mbit/s data rate in
open-drain mode, it's doubtful as to whether the 25MHz clock signal
would even survive to the actual user-accessible pin it terminates in.

Remove it to leave the pin for users to play with. It's infinitely more
useful as a GPIO or even as a PWM.

Fixes: 40f742b07ab2 ("arm64: dts: rockchip: Add rk3576-armsom-sige5 board")
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
While working on a PWM driver for RK3576 and needing a PWM pin to test
with, I noticed this questionable pinctrl assignment.
---
 arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
index 78798b0722a3f36831b1d2c9f29acb83910631cf..828bde7fab68dc6bcbd13d75c8a72540b3666071 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
@@ -194,8 +194,7 @@ &gmac0 {
 		     &eth0m0_tx_bus2
 		     &eth0m0_rx_bus2
 		     &eth0m0_rgmii_clk
-		     &eth0m0_rgmii_bus
-		     &ethm0_clk0_25m_out>;
+		     &eth0m0_rgmii_bus>;
 
 	phy-handle = <&rgmii_phy0>;
 	status = "okay";

---
base-commit: 40a111d0a777f60b71369d835cfe46308a212235
change-id: 20250314-rk3576-sige5-eth-clk-begone-31d19a7c1e68

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From amadeus at jmu.edu.cn  Fri Mar 14 08:40:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Fri, 14 Mar 2025 23:40:02 +0800
Subject: [PATCH 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <22d849c3-8a0d-4704-b69c-8019c7f70ca7@kwiboo.se>
References: <22d849c3-8a0d-4704-b69c-8019c7f70ca7@kwiboo.se>
Message-ID: <20250314154002.1844394-1-amadeus@jmu.edu.cn>

Hi,

> Interesting, good that it works with the updated U-Boot. Main change
> compared to v1 is that it now use clock/reset id and DT closer to what
> has been merged in mainline Linux. It also has DT params to help
> initialize the two pwm regulators used by these boards.
>
> I will try with the old v1 U-Boot series and see if I can replicated
> your issue.

Hi, I found the reason. I did some experiments today:

pwm-regulator  pwm1 | pwm2 | pwm3
-----------------------------------
ArmSoM Sige1 |      | work | work |
Radxa E20C   | work | hang |      |
other 3528   | work | hang |      |

This looks weird, so I tested it further:

In the new series of u-boot:
```
--- a/arch/arm/dts/rk3528-radxa-e20c-u-boot.dtsi
+++ b/arch/arm/dts/rk3528-radxa-e20c-u-boot.dtsi
@@ -8,9 +8,9 @@
 };
 
 &vdd_arm {
-	regulator-init-microvolt = <953000>;
+	status = "disabled"; # Cancel changes, pwm works
 };
 
 &vdd_logic {
-	regulator-init-microvolt = <900000>;
+	status = "disabled"; # Cancel changes, kernel hang
 };
```

I looked at schematic and found an interesting thing:
1. ArmSoM Sige1 schematic: VDD_LOGIC Default 0.901V
2. Radxa E20C schematic: VDD_LOGIC No default voltage

Therefore, the default voltage of VDD_LOGIC (supply to
GPU and LOGIC) needs to be set to 0.9V when initializing.

This can be done by hardware or software (such as u-boot)
Should we support this in the kernel driver of regulator?

Thanks,
Chukun

--
2.25.1



From sakari.ailus at iki.fi  Fri Mar 14 08:48:52 2025
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Fri, 14 Mar 2025 15:48:52 +0000
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z9RKllMJ0Duac83Y@mt.com>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
 <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
 <Z8r21Z2HthBwGDSq@mt.com>
 <Z86-AFnPQ2wXKidi@valkosipuli.retiisi.eu>
 <Z9RKllMJ0Duac83Y@mt.com>
Message-ID: <Z9RP5K59sZwuphIc@valkosipuli.retiisi.eu>

Hi Mathis,

On Fri, Mar 14, 2025 at 04:26:14PM +0100, Mathis Foerst wrote:
> On Mon, Mar 10, 2025 at 10:25:04AM +0000, Sakari Ailus wrote:
> Hi Sakari,
> 
> > Hi Mathis,
> > 
> > On Fri, Mar 07, 2025 at 02:38:29PM +0100, Mathis Foerst wrote:
> > > Hi Sakari, Hi Dan,
> > > 
> > > thanks a lot for your feedback.
> > > 
> > > On Thu, Mar 06, 2025 at 09:13:46PM +0000, Sakari Ailus wrote:
> > > > Hi Dan,
> > > > 
> > > > On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> > > > > On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > > > > > Hi Mathis,
> > > > > > 
> > > > > > Thanks for the patch.
> > > > > > 
> > > > > > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > > > > > The imx-media-csi driver requires upstream camera drivers to implement
> > > > > > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > > > > > implement this function are not usable on the i.MX6.
> > > > > > > 
> > > > > > > The docs for get_mbus_config [1] say:
> > > > > > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > > > > > >             The media bus configuration is usually retrieved from the
> > > > > > >             firmware interface at sub-device probe time, immediately
> > > > > > >             applied to the hardware and eventually adjusted by the
> > > > > > >             driver.
> > > > > > > 
> > > > > > > Currently, the imx-media-csi driver is not incorporating the information
> > > > > > > from the firmware interface and therefore relies on the implementation of
> > > > > > > get_mbus_config by the camera driver.
> > > > > > > 
> > > > > > > To be compatible with camera drivers not implementing get_mbus_config
> > > > > > > (which is the usual case), use the bus information from the fw interface:
> > > > > > > 
> > > > > > > The camera does not necessarily has a direct media bus link to the CSI as
> > > > > > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > > > > > between them on the media pipeline.
> > > > > > > The CSI driver already implements the functionality to find the connected
> > > > > > > camera sub-device to call get_mbus_config on it.
> > > > > > > 
> > > > > > > At this point the driver is modified as follows:
> > > > > > > In the case that get_mbus_config is not implemented by the upstream
> > > > > > > camera, try to get its endpoint configuration from the firmware interface
> > > > > > > usign v4l2_fwnode_endpoint_parse.
> > > > > > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > > > > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > > > > > configuration.
> > > > > > > For all other mbus_types, return an error.
> > > > > > > 
> > > > > > > Note that parsing the mbus_config from the fw interface is not done during
> > > > > > > probing because the camera that's connected to the CSI can change based on
> > > > > > > the selected input of the video-mux at runtime.
> > > > > > > 
> > > > > > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > > > > > [1] include/media/v4l2-subdev.h - line 814
> > > > > > > 
> > > > > > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > > > > > ---
> > > > > > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > > > > > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > index 3edbc57be2ca..394a9321a10b 100644
> > > > > > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > > >  {
> > > > > > >  	struct v4l2_subdev *sd, *remote_sd;
> > > > > > >  	struct media_pad *remote_pad;
> > > > > > > +	struct fwnode_handle *ep_node;
> > > > > > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > > > > > 
> > > > > > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > > > > > field to zero this way is redundant, just use {}.
> > > > > > 
> > > > > 
> > > > > I was going to respond in much the same way.  This is equivalen to:
> > > > > 
> > > > > struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
> > > > 
> > > > Thinking about this in a context of parsing the endpoint, in fact the
> > > > bus_type should be specified. Presumably the hardware is D-PHY, so the
> > > > correct value would be V4L2_MBUS_CSI2_DPHY. This way
> > > > v4l2_fwnode_endpoint_parse() doesn't need to guess.
> > > 
> > > I think we must use "bus_type = V4L2_MBUS_UNKNOWN" here:
> > > 
> > > The i.MX6 has two types of camera interfaces: Parallel and MIPI CSI-2.
> > > They are connected either directly or via a video-mux to the CSIs
> > > (See IMX6DQRM.pdf - Figure 9-3 for the connection diagram)
> > > 
> > > Pre-defining V4L2_MBUS_CSI2_DPHY here would let
> > > v4l2_fwnode_endpoint_parse() fail if the camera uses the parallel bus.
> > > 
> > > We could distinguish between MIPI CSI-2 and Parallel input by checking
> > > the grp_id of the upstream device like it's already done in
> > > csi_get_upstream_mbus_config().
> > > But for the Parallel case we still can't know if we should set bus_type
> > > to V4L2_MBUS_PARALLEL or to V4L2_MBUS_BT656 - the i.MX6 supports both
> > > formats on the parallel interface.
> > > 
> > > That's why I would argue that v4l2_fwnode_endpoint_parse() must figure
> > > out the bus_type from the fw node.
> > 
> > Right, nowadays you can indeed do this -- it wasn't a long ago when you
> > couldn't. I presume the bindings do specify the bus-type property is
> > mandatory? Where are the bindings btw.?
> > 
> 
> From my understanding, it's not even required to set the bus-type as 
> v4l2_fwnode_endpoint_parse() will try to parse the endpoint first as a
> CSI-2 bus and in case of failure as a Parallel bus if the bus-type is
> unknown (see drivers/media/v4l2-core/v4l2-fwnode.c#L493).

It only exists for compatibility with old drivers. Do not add new users for
this code.

> 
> About the bindings:
> 
> There are bindings for the MIPI CSI-2 receiver:
> Documentation/devicetree/bindings/media/imx.txt
> I think here it's not necessary to make the bus-type property mandatory
> as the imx6-mipi-csi2 driver enforces V4L2_MBUS_CSI2_DPHY anyhow
> (see drivers/staging/media/imx/imx6-mipi-csi2.c#L677).

That seems to document a CSI-2 to parallel bridge, with support for four
virtual channels. I'd suppose you parse the ports knowing which interface
they use.

> 
> For the case of a camera with parallel bus, the camera endpoint is
> connected to a video-mux and not directly to the CSI. Therefore, we cannot
> make the bus-type property mandatory on this endpoint as it this wouldn't
> apply to other use-cases of video-mux.
> 
> > > 
> > > > 
> > > > > 
> > > > > > >  	int ret;
> > > > > > >  
> > > > > > >  	if (!priv->src_sd)
> > > > > > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > > >  
> > > > > > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > > > > > >  			       remote_pad->index, mbus_cfg);
> > > > > > > -	if (ret == -ENOIOCTLCMD)
> > > > > > > -		v4l2_err(&priv->sd,
> > > > > > > -			 "entity %s does not implement get_mbus_config()\n",
> > > > > > > -			 remote_pad->entity->name);
> > > > > > > +	if (ret == -ENOIOCTLCMD) {
> > > > > > 
> > > > > > 	if (!ret)
> > > > > > 		return 0;
> > > > > > 
> > > > > > And you can unindent the rest.
> > > > > 
> > > > > I was going to say this too but then I thought actually this needs to
> > > > > be:
> > > > > 
> > > > > 	if (ret != -ENOIOCTLCMD)
> > > > > 		return ret;
> > > > > 
> > > > > Which is weird.  Better to break all the new code into a separate
> > > > > helper function.
> > > > > 
> > > > > 	if (ret == -ENOIOCTLCMD)
> > > > > 		ret = parse_fw_link_config_stuff();
> > > > > 
> > > > > 	return ret;
> > > 
> > > Good point. I factored out a helper function as suggested.
> > > 
> > > > 
> > > > Indeed. get_mbus_config() presumably wouldn't return an error but
> > > > correctness is usually a good idea.
> > > > 
> > 

-- 
Regards,

Sakari Ailus


From arnd at kernel.org  Fri Mar 14 08:49:59 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Fri, 14 Mar 2025 16:49:59 +0100
Subject: [PATCH] net: airoha: fix CONFIG_DEBUG_FS check
Message-ID: <20250314155009.4114308-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

The #if check causes a build failure when CONFIG_DEBUG_FS is turned
off:

In file included from drivers/net/ethernet/airoha/airoha_eth.c:17:
drivers/net/ethernet/airoha/airoha_eth.h:543:5: error: "CONFIG_DEBUG_FS" is not defined, evaluates to 0 [-Werror=undef]
  543 | #if CONFIG_DEBUG_FS
      |     ^~~~~~~~~~~~~~~

Replace it with the correct #ifdef.

Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index f66b9b736b94..60690b685710 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -540,7 +540,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth);
 struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
 						  u32 hash);
 
-#if CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
 int airoha_ppe_debugfs_init(struct airoha_ppe *ppe);
 #else
 static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
-- 
2.39.5



From bigeasy at linutronix.de  Fri Mar 14 09:08:05 2025
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Fri, 14 Mar 2025 17:08:05 +0100
Subject: [PATCH v4 4/9] arm64: Rely on generic printing of preemption model.
In-Reply-To: <20250314160810.2373416-1-bigeasy@linutronix.de>
References: <20250314160810.2373416-1-bigeasy@linutronix.de>
Message-ID: <20250314160810.2373416-5-bigeasy@linutronix.de>

__die() invokes later show_regs() -> show_regs_print_info() which prints
the current preemption model.
Remove it from the initial line.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Acked-by: Will Deacon <will at kernel.org>
Acked-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 arch/arm64/kernel/traps.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 4e26bd356a482..529cff825531c 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -172,14 +172,6 @@ static void dump_kernel_instr(const char *lvl, struct pt_regs *regs)
 	printk("%sCode: %s\n", lvl, str);
 }
 
-#ifdef CONFIG_PREEMPT
-#define S_PREEMPT " PREEMPT"
-#elif defined(CONFIG_PREEMPT_RT)
-#define S_PREEMPT " PREEMPT_RT"
-#else
-#define S_PREEMPT ""
-#endif
-
 #define S_SMP " SMP"
 
 static int __die(const char *str, long err, struct pt_regs *regs)
@@ -187,7 +179,7 @@ static int __die(const char *str, long err, struct pt_regs *regs)
 	static int die_counter;
 	int ret;
 
-	pr_emerg("Internal error: %s: %016lx [#%d]" S_PREEMPT S_SMP "\n",
+	pr_emerg("Internal error: %s: %016lx [#%d] " S_SMP "\n",
 		 str, err, ++die_counter);
 
 	/* trap and error numbers are mostly meaningless on ARM */
-- 
2.47.2



From bigeasy at linutronix.de  Fri Mar 14 09:08:04 2025
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Fri, 14 Mar 2025 17:08:04 +0100
Subject: [PATCH v4 3/9] arm: Rely on generic printing of preemption model.
In-Reply-To: <20250314160810.2373416-1-bigeasy@linutronix.de>
References: <20250314160810.2373416-1-bigeasy@linutronix.de>
Message-ID: <20250314160810.2373416-4-bigeasy@linutronix.de>

__die() invokes later __show_regs() -> show_regs_print_info() which
prints the current preemption model.
Remove it from the initial line.

Cc: linux-arm-kernel at lists.infradead.org
Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 arch/arm/kernel/traps.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6ea645939573f..afbd2ebe5c39d 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -258,13 +258,6 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
 	barrier();
 }
 
-#ifdef CONFIG_PREEMPT
-#define S_PREEMPT " PREEMPT"
-#elif defined(CONFIG_PREEMPT_RT)
-#define S_PREEMPT " PREEMPT_RT"
-#else
-#define S_PREEMPT ""
-#endif
 #ifdef CONFIG_SMP
 #define S_SMP " SMP"
 #else
@@ -282,8 +275,8 @@ static int __die(const char *str, int err, struct pt_regs *regs)
 	static int die_counter;
 	int ret;
 
-	pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP S_ISA "\n",
-	         str, err, ++die_counter);
+	pr_emerg("Internal error: %s: %x [#%d]" S_SMP S_ISA "\n",
+		 str, err, ++die_counter);
 
 	/* trap and error numbers are mostly meaningless on ARM */
 	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 09:09:17 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 13:09:17 -0300
Subject: [PATCH v1 5/6] drm/panfrost: Enable AARCH64_4K page table format
 on mediatek_mt8188
In-Reply-To: <55b8bc40-0a29-46c2-ba5d-c7cc7742cf5f@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-6-ariel.dalessandro@collabora.com>
 <55b8bc40-0a29-46c2-ba5d-c7cc7742cf5f@collabora.com>
Message-ID: <2c82edc7-fd39-4e81-95b5-f43467fd166f@collabora.com>

Angelo,

On 3/11/25 6:09 AM, AngeloGioacchino Del Regno wrote:
> Il 10/03/25 20:59, Ariel D'Alessandro ha scritto:
>> Now that Panfrost supports AARCH64_4K page table format, let's enable it
>> on Mediatek MT8188.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> ---
>> ? drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
>> ? 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/ 
>> drm/panfrost/panfrost_drv.c
>> index 0f3935556ac76..d7b8bded6d784 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
>> @@ -824,6 +824,7 @@ static const struct panfrost_compatible 
>> mediatek_mt8188_data = {
>> ????? .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
>> ????? .pm_domain_names = mediatek_mt8183_pm_domains,
>> ????? .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
>> +??? .gpu_configs = BIT(GPU_CONFIG_AARCH64_4K),
>> ? };
>> ? static const char * const mediatek_mt8192_supplies[] = { "mali", 
>> NULL };
> 
> Didn't that work on MT8195/8395 as well? I also recall hearing that it 
> was somewhat
> giving ever-so-slightly better performance?

Running glmark2-es2-drm [0] benchmark, reported the same performance 
("glmark2 Score") on both configurations, before and after this 
patchset. Tested on a Mediatek Genio 1200 EVK board.

To avoid holding this longer, I'll add it to patchset v2, and let's 
continue discussion there in any case.

[0] https://github.com/glmark2/glmark2

> 
> If it does, please enable it on 8195 as well :-)
> 
> also s/mediatek_mt8188/MediaTek MT8188/g

Ack.

> 
> ...and btw
> Reviewed-by: AngeloGioacchino Del Regno 
> <angelogioacchino.delregno at collabora.com>

Thanks!

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From broonie at kernel.org  Fri Mar 14 08:52:48 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 15:52:48 +0000
Subject: (subset) [PATCH v3 0/5] ASoC: sun4i-codec: add headphone
 dectection for Anbernic RG35XX devices
In-Reply-To: <20250214220247.10810-1-ryan@testtoast.com>
References: <20250214220247.10810-1-ryan@testtoast.com>
Message-ID: <174196756840.19728.17664266192768404946.b4-ty@kernel.org>

On Sat, 15 Feb 2025 11:02:22 +1300, Ryan Walklin wrote:
> V3 of this patch adding headphone jack detection support to the Anbernic RGnnXX series of handhelds. V3 corrects my misunderstanding of derivation of ALSA UCM file paths, and adds recieved Reviewed-by and Tested-by tags. Thanks to those that have reviewed and fed back on previous versions.
> 
> Original message below:
> 
> This series adds the required device tree bindings to describe GPIOs for jack detection in the sun4i-codec driver, adds support for jack detection to the codec machine driver, and describes the hardware configuration in the RG35XX DTS. The existing speaker amplifier GPIO pin can then be used in concert with jack detection to enable userspace sound servers (via an ALSA UCM configuration) to disable the speaker route when headphones are connected.
> 
> Thanks to Chris Morgan for his assistance putting this series together.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/5] ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios
      commit: 7bda89a2489fb012c4c63f3338827ad1f35c8880
[2/5] ASoC: sun4i-codec: correct dapm widgets and controls for h616
      commit: ae5f76d4044d1580849316c49290678605e0889d
[3/5] ASoC: sun4i-codec: support hp-det-gpios property
      commit: a149377c033afe6557c50892ebbfc0e8b7e2e253
[5/5] ASoC: sun4i-codec: add h616 card long_name
      commit: d389719fb4ece17ea28c0cf908066815d3ab0e25

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From broonie at kernel.org  Fri Mar 14 08:53:00 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 15:53:00 +0000
Subject: (subset) [PATCH v2 00/12] arm64: dts: freescale: Add support
 for the GOcontroll Moduline Display
In-Reply-To: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
Message-ID: <174196758090.19958.7850853709519472369.b4-ty@kernel.org>

On Wed, 26 Feb 2025 15:19:11 +0100, Maud Spierings wrote:
> Add inital support for 2 variants of the Moduline Display controller.
> This system is powered by the Ka-Ro Electronics tx8p-ml81 COM, which
> features an imx8mp SoC.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[02/12] dt-bindings: vendor-prefixes: add GOcontroll
        commit: 5f0d2de417166698c8eba433b696037ce04730da
[03/12] dt-bindings: connector: Add the GOcontroll Moduline module slot bindings
        commit: 43fd4d2f4f9df4ae1f6493d51cdd2687f325a225
[06/12] MAINTAINERS: add maintainer for the GOcontroll Moduline module slot
        commit: 8f1cc5242544052e4be037861abc8bc2b89cabda
[12/12] spi: spidev: Add an entry for the gocontroll moduline module slot
        commit: 10254a6c6073b0be171d434a3aeeff0256e59443

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From broonie at kernel.org  Fri Mar 14 08:53:05 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 14 Mar 2025 15:53:05 +0000
Subject: [PATCH] dt-bindings: spi: add compatibles for mt7988
In-Reply-To: <20241109105029.52748-1-linux@fw-web.de>
References: <20241109105029.52748-1-linux@fw-web.de>
Message-ID: <174196758592.19958.17138223278523726564.b4-ty@kernel.org>

On Sat, 09 Nov 2024 11:50:28 +0100, Frank Wunderlich wrote:
> MT7988 has 2 different spi controllers. Add their compatibles.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] dt-bindings: spi: add compatibles for mt7988
      commit: 3b2e1b87ad0870ad37ee8f2ca0ea6ede19a29795

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From andre.draszik at linaro.org  Fri Mar 14 08:56:24 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Fri, 14 Mar 2025 15:56:24 +0000
Subject: [PATCH 1/2] arm64: dts: exynos: gs101: ufs: add dma-coherent
 property
In-Reply-To: <20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
	 <20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro.org>
Message-ID: <8ccfdccefaf0cd651a3f085aa78227907f03a478.camel@linaro.org>

On Fri, 2025-03-14 at 15:38 +0000, Peter Griffin wrote:
> ufs-exynos driver configures the sysreg shareability as
> cacheable for gs101 so we need to set the dma-coherent
> property so the descriptors are also allocated cacheable.
> 
> This fixes the UFS stability issues we have seen with
> the upstream UFS driver on gs101.
> 
> Fixes: 4c65d7054b4c ("arm64: dts: exynos: gs101: Add ufs and ufs-phy dt nodes")
> Cc: stable at vger.kernel.org
> Suggested-by: Will McVicker <willmcvicker at google.com>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>

Tested-by: Andr? Draszik <andre.draszik at linaro.org>
Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>



From mike.looijmans at topic.nl  Fri Mar 14 08:56:07 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Fri, 14 Mar 2025 16:56:07 +0100
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
Message-ID: <20250314155706.31058-1-mike.looijmans@topic.nl>

Set the gpio to "high" on acquisition, instead of acquiring it in low
state and then immediately setting it high again. This prevents a
short "spike" on the reset signal.

Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

 drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index a33a42ba0249..a159a511483b 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 
 skip_usb3_phy:
 	/* ulpi reset via gpio-modepin or gpio-framework driver */
-	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(reset_gpio)) {
 		return dev_err_probe(dev, PTR_ERR(reset_gpio),
 				     "Failed to request reset GPIO\n");
@@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 
 	if (reset_gpio) {
 		/* Toggle ulpi to reset the phy. */
-		gpiod_set_value_cansleep(reset_gpio, 1);
 		usleep_range(5000, 10000);
 		gpiod_set_value_cansleep(reset_gpio, 0);
 		usleep_range(5000, 10000);
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From andre.draszik at linaro.org  Fri Mar 14 08:59:43 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Fri, 14 Mar 2025 15:59:43 +0000
Subject: [PATCH 2/2] scsi: ufs: dt-bindings: exynos: add dma-coherent
 property for gs101
In-Reply-To: <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
	 <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org>
Message-ID: <931e5e0b07d598912712b091d99a636b796fe19f.camel@linaro.org>

Hi Pete,

On Fri, 2025-03-14 at 15:38 +0000, Peter Griffin wrote:
> dma-coherent property is required for gs101 as ufs-exynos enables
> sharability.
> 
> Fixes: 438e23b61cd4 ("scsi: ufs: dt-bindings: exynos: Add gs101 compatible")
> Cc: stable at vger.kernel.org
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
> ?Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml | 2 ++
> ?1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml b/Documentation/devicetree/bindings/ufs/samsung,exynos-
> ufs.yaml
> index 720879820f6616a30cae2db3d4d2d22e847666c4..5dbb7f6a8c354b82685c521e70655e106f702a8d 100644
> --- a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
> +++ b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
> @@ -96,6 +96,8 @@ allOf:
> ???????? clock-names:
> ?????????? minItems: 6
> ?
> +??????? dma-coherent: true
> +

This is allowed globally already in this file. Did you meant to make it 'required'?

Cheers,
Andre'

> ???? else:
> ?????? properties:
> ???????? clocks:
> 



From chenyuan0y at gmail.com  Fri Mar 14 09:00:26 2025
From: chenyuan0y at gmail.com (Chenyuan Yang)
Date: Fri, 14 Mar 2025 11:00:26 -0500
Subject: [PATCH] drm/sun4i: backend: Fix error pointers in sun4i_backend_atomic_check
In-Reply-To: <20250314-prophetic-attentive-platypus-3ab214@houat>
References: <20250314012029.668306-1-chenyuan0y@gmail.com> <20250314-prophetic-attentive-platypus-3ab214@houat>
Message-ID: <CALGdzurT1_fY_o8Hv92j4+XFQHu1iHRzqVtZAM8upHYBPfA1BA@mail.gmail.com>

HI Maxime.

Thanks so much for pointing that out!

How about such a patch?

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c
b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 2dded3b828df..5ad0e90d3e6b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -490,9 +490,14 @@ static int sun4i_backend_atomic_check(struct
sunxi_engine *engine,
  drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
  struct drm_plane_state *plane_state =
  drm_atomic_get_plane_state(state, plane);
- struct sun4i_layer_state *layer_state =
- state_to_sun4i_layer_state(plane_state);
- struct drm_framebuffer *fb = plane_state->fb;
+ struct sun4i_layer_state *layer_state = NULL;
+ struct drm_framebuffer *fb = NULL;
+
+ if (IS_ERR(plane_state))
+ return PTR_ERR(plane_state);
+
+ layer_state = state_to_sun4i_layer_state(plane_state);
+ fb = plane_state->fb;

  if (!sun4i_backend_plane_is_supported(plane_state,
        &layer_state->uses_frontend))
-- 

-Chenyuan

On Fri, Mar 14, 2025 at 2:17?AM Maxime Ripard <mripard at kernel.org> wrote:
>
> Hi,
>
> On Thu, Mar 13, 2025 at 08:20:29PM -0500, Chenyuan Yang wrote:
> > The function sun4i_backend_atomic_check was dereferencing pointers
> > returned by drm_atomic_get_plane_state without checking for errors. This
> > could lead to undefined behavior if the function returns an error pointer.
> >
> > This commit adds checks using IS_ERR to ensure that plane_state is
> > valid before dereferencing them.
> >
> > Similar to commit da29abe71e16
> > ("drm/amd/display: Fix error pointers in amdgpu_dm_crtc_mem_type_changed").
> >
> > Fixes: 96180dde23b7 ("drm/sun4i: backend: Add a custom atomic_check for the frontend")
> > Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_backend.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
> > index 2dded3b828df..a8e0e2123764 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
> > @@ -490,6 +490,10 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
> >       drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
> >               struct drm_plane_state *plane_state =
> >                       drm_atomic_get_plane_state(state, plane);
> > +
> > +             if (IS_ERR(plane_state))
> > +                     return PTR_ERR(plane_state);
> > +
>
> This introduces a build warning. You shouldn't mix declarations and code.
>
> Maxime


From bvanassche at acm.org  Fri Mar 14 09:00:45 2025
From: bvanassche at acm.org (Bart Van Assche)
Date: Fri, 14 Mar 2025 09:00:45 -0700
Subject: [PATCH 0/2] Add dma-coherent for gs101 UFS dt node
In-Reply-To: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
Message-ID: <0d7a8cad-adfc-4cac-bcc6-65d1f9c86b43@acm.org>

On 3/14/25 8:38 AM, Peter Griffin wrote:
> ufs-exynos driver enables the shareability option for gs101 which
> means the descriptors need to be allocated as cacheable.

Shouldn't that code be modified such that the shareability option is
only set if the dma-coherent property is present in the device tree?

Thanks,

Bart.


From arnd at kernel.org  Fri Mar 14 09:02:44 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Fri, 14 Mar 2025 17:02:44 +0100
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
Message-ID: <20250314160248.502324-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

On 32-bit architectures, the new calculation causes a build failure:

ld.lld-21: error: undefined symbol: __aeabi_uldivmod

Since neither value is ever larger than a register, cast both
sides into a uintptr_t.

Fixes: 5c03f9f4d362 ("watchdog: aspeed: Update bootstatus handling")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/watchdog/aspeed_wdt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
index 369635b38ca0..837e15701c0e 100644
--- a/drivers/watchdog/aspeed_wdt.c
+++ b/drivers/watchdog/aspeed_wdt.c
@@ -254,7 +254,7 @@ static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
 
 	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
+		idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res);
 	}
 
 	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
-- 
2.39.5



From will at kernel.org  Fri Mar 14 09:04:59 2025
From: will at kernel.org (Will Deacon)
Date: Fri, 14 Mar 2025 16:04:59 +0000
Subject: [GIT PULL] arm64 fixes for -rc7
Message-ID: <20250314160458.GA9438@willie-the-truck>

Hi Linus,

Please pull this pair of arm64 mm fixes for -rc7.

Summary in the tag, but the main one is a horrible macro fix for our
TLB flushing code which resulted in over-invalidation on the MMU
notifier path.

Cheers,

Will

--->8

The following changes since commit eed6bfa8b28230382b797a88569f2c7569a1a419:

  arm64: hugetlb: Fix flush_hugetlb_tlb_range() invalidation level (2025-02-27 17:40:58 +0000)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes

for you to fetch changes up to f7edb07ad7c66eab3dce57384f33b9799d579133:

  Fix mmu notifiers for range-based invalidates (2025-03-11 11:37:43 +0000)

----------------------------------------------------------------
arm64 fixes for -rc7

- Fix population of the vmemmap for regions of memory that are smaller
  than a section (128 MiB)

- Fix range-based TLB over-invalidation when invoked via a MMU notifier

----------------------------------------------------------------
Piotr Jaroszynski (1):
      Fix mmu notifiers for range-based invalidates

Zhenhua Huang (1):
      arm64: mm: Populate vmemmap at the page level if not section aligned

 arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++----------
 arch/arm64/mm/mmu.c               |  5 ++++-
 2 files changed, 16 insertions(+), 11 deletions(-)


From p.zabel at pengutronix.de  Fri Mar 14 09:05:08 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 14 Mar 2025 17:05:08 +0100
Subject: [PATCH] reset: imx: fix incorrect module device table
In-Reply-To: <20250314153541.3555813-1-arnd@kernel.org>
References: <20250314153541.3555813-1-arnd@kernel.org>
Message-ID: <9bd42362c798cc3339ab9b34b32a9eb7eb4d1ba7.camel@pengutronix.de>

On Fr, 2025-03-14 at 16:35 +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> The ID table is for of_device_id, not platform_device_id:
> 
> ERROR: modpost: drivers/reset/reset-imx-scu: type mismatch between imx_scu_reset_ids[] and MODULE_DEVICE_TABLE(platform, ...)
> 
> Fixes: 6b64fde5c183 ("reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Applied to reset/next, thanks!

[1/1] reset: imx: fix incorrect module device table
      https://git.pengutronix.de/cgit/pza/linux/commit/?id=c361baf67200

regards
Philipp


From festevam at gmail.com  Fri Mar 14 09:15:37 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 14 Mar 2025 13:15:37 -0300
Subject: [PATCH] ARM64: dts: imx8mp-evk: add ecspi2 support
In-Reply-To: <Z8oqhGmVOBCPlJUI@lizhi-Precision-Tower-5810>
References: <20250306222359.797855-1-Frank.Li@nxp.com> <CAOMZO5CL-qQSHuSoCtb+f_mqNG8vu4tTVDi-ThoHq+m9SeagxA@mail.gmail.com>
 <Z8oqhGmVOBCPlJUI@lizhi-Precision-Tower-5810>
Message-ID: <CAOMZO5A9ggneYjfR=R4kY7DY-BC2pMh+ayiPEtOTOipCdtBWvg@mail.gmail.com>

On Thu, Mar 6, 2025 at 8:06?PM Frank Li <Frank.li at nxp.com> wrote:

> Thanks! It is actually to get spidev. From commit message, I don't know
> what next steps should be did, use "rohm,bh2228fv" or other method to
> support spidev?

You can add a specific spidev entry. Take a look at:

https://web.git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git/commit/?id=10254a6c6073b0be171d434a3aeeff0256e59443
or
https://web.git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git/commit/?id=9783da2384c5623d376e4641bbce9339be1001eb


From steven.price at arm.com  Fri Mar 14 09:17:28 2025
From: steven.price at arm.com (Steven Price)
Date: Fri, 14 Mar 2025 16:17:28 +0000
Subject: [PATCH v1 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250310195921.157511-2-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-2-ariel.dalessandro@collabora.com>
Message-ID: <25408ea8-475a-424e-8fb4-8c6772de63bb@arm.com>

On 10/03/2025 19:59, Ariel D'Alessandro wrote:
> Panfrost does not support uncached mappings, so flag them properly. Also
> flag the pages that are mapped as response to a page fault as cached.

As I understand it the hardware only sort-of supports uncached mappings.
The legacy page table format has two options: cached, or "implementation
defined" (ARM_MALI_LPAE_MEMATTR_IMP_DEF). When selecting IMP_DEF that
means that the internal units signal to the cache whether a particular
access should be cached or not. I believe the theory is that they can
decide whether it makes sense to store in the cache or not.

Having said all that, I have never observed any actual performance
difference and I suspect it won't make any actual difference. And of
course the AArch64 page tables need this to be set. I just thought I
should explain the background and that this wasn't wrong for the legacy
page tables.

Reviewed-by: Steven Price <steven.price at arm.com>

Steve

> Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index b91019cd5acb1..9e6f198ef5c1b 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
>  	struct drm_gem_object *obj = &shmem->base;
>  	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
>  	struct sg_table *sgt;
> -	int prot = IOMMU_READ | IOMMU_WRITE;
> +	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
>  
>  	if (WARN_ON(mapping->active))
>  		return 0;
> @@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
>  		goto err_map;
>  
>  	mmu_map_sg(pfdev, bomapping->mmu, addr,
> -		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
> +		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
>  
>  	bomapping->active = true;
>  	bo->heap_rss_size += SZ_2M;



From sebastien.szymanski at armadeus.com  Fri Mar 14 09:20:38 2025
From: sebastien.szymanski at armadeus.com (=?utf-8?q?S=C3=A9bastien_Szymanski?=)
Date: Fri, 14 Mar 2025 17:20:38 +0100
Subject: [PATCH] ARM: dts: opos6ul: add ksz8081 phy properties
Message-ID: <20250314-opos6ul-fix-ethernet-v1-1-1c0172949b40@armadeus.com>

Commit c7e73b5051d6 ("ARM: imx: mach-imx6ul: remove 14x14 EVK specific
PHY fixup") removed a PHY fixup that setted the clock mode and the LED
mode.
Make the Ethernet interface work again by doing as advised in the
commit's log, set clock mode and the LED mode in the device tree.

Fixes: c7e73b5051d6 ("ARM: imx: mach-imx6ul: remove 14x14 EVK specific PHY fixup")
Signed-off-by: S?bastien Szymanski <sebastien.szymanski at armadeus.com>
---
 arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi
index f2386dcb9ff2c0c11e00069b81689c81af7f5446..dda4fa91b2f2cc28ef59e2d6513dc1732982feea 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi
@@ -40,6 +40,9 @@ ethphy1: ethernet-phy at 1 {
 			reg = <1>;
 			interrupt-parent = <&gpio4>;
 			interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+			micrel,led-mode = <1>;
+			clocks = <&clks IMX6UL_CLK_ENET_REF>;
+			clock-names = "rmii-ref";
 			status = "okay";
 		};
 	};

---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250314-opos6ul-fix-ethernet-1390c556f3b8

Best regards,
-- 
S?bastien Szymanski <sebastien.szymanski at armadeus.com>



From steven.price at arm.com  Fri Mar 14 09:25:24 2025
From: steven.price at arm.com (Steven Price)
Date: Fri, 14 Mar 2025 16:25:24 +0000
Subject: [PATCH v1 6/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature
 flag on Bifrost models
In-Reply-To: <20250310195921.157511-7-ariel.dalessandro@collabora.com>
References: <20250310195921.157511-1-ariel.dalessandro@collabora.com>
 <20250310195921.157511-7-ariel.dalessandro@collabora.com>
Message-ID: <f575f3f0-b6cb-4ef6-a522-0ddced78476f@arm.com>

On 10/03/2025 19:59, Ariel D'Alessandro wrote:
> Set this feature flag on all Mali Bifrost platforms as the MMU supports
> AARCH64 4K page table format.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

Reviewed-by: Steven Price <steven.price at arm.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
> index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_features.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_features.h
> @@ -54,6 +54,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g72 (\
> @@ -64,6 +65,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g51 hw_features_g72
> @@ -77,6 +79,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
>  	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>  
>  #define hw_features_g76 (\



From arnd at arndb.de  Fri Mar 14 09:31:44 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 14 Mar 2025 17:31:44 +0100
Subject: [PATCH v9 2/5] firmware: psci: Read and use vendor reset types
In-Reply-To: <Z9QQw6BcE7IXzu+r@lpieralisi>
References: <20250303-arm-psci-system_reset2-vendor-reboots-v9-0-b2cf4a20feda@oss.qualcomm.com>
 <20250303-arm-psci-system_reset2-vendor-reboots-v9-2-b2cf4a20feda@oss.qualcomm.com>
 <Z9QQw6BcE7IXzu+r@lpieralisi>
Message-ID: <a9d8d9aa-f63c-481e-b051-a3da0adb3c66@app.fastmail.com>

On Fri, Mar 14, 2025, at 12:19, Lorenzo Pieralisi wrote:
> On Mon, Mar 03, 2025 at 01:08:31PM -0800, Elliot Berman wrote:
>> From: Elliot Berman <elliot.berman at oss.qualcomm.com>
>> 
>> SoC vendors have different types of resets and are controlled through
>> various registers. For instance, Qualcomm chipsets can reboot to a
>> "download mode" that allows a RAM dump to be collected. Another example
>> is they also support writing a cookie that can be read by bootloader
>> during next boot. PSCI offers a mechanism, SYSTEM_RESET2, for these
>> vendor reset types to be implemented without requiring drivers for every
>> register/cookie.
>> 
>> Add support in PSCI to statically map reboot mode commands from
>> userspace to a vendor reset and cookie value using the device tree.
>
> I have managed to discuss a little bit this patchset over the last
> few days and I think we have defined a plan going forward.
>
> A point that was raised is:
>
> https://man7.org/linux/man-pages/man2/reboot.2.html
>
> LINUX_REBOOT_CMD_RESTART2 *arg command, what is it supposed to
> represent ?
>
> Is it the mode the system should reboot into OR it is the
> actual command to be issued (which is what this patchset
> implements) ?
>
> LINUX_REBOOT_CMD_RESTART "..a default restart..."
>
> It is unclear what "default" means. We wonder whether the
> reboot_mode variable was introduced to _define_ that "default".

I think the reboot_mode predates the 'cmd' argument: linux-2.1.30
introduced LINUX_REBOOT_CMD_RESTART2 and it already had
the warm/cold/bios/hard options for i386 reboot. I think the
argument went unused for a while after it got introduced though.

> So, in short, my aim is trying to decouple reboot_mode from the
> LINUX_REBOOT_CMD_RESTART2 *arg command.
>
> I believe that adding a sysfs interface to reboot-mode driver
> infrastructure would be useful, so that the commands would
> be exposed to userspace and userspace can set the *arg command
> specifically to issue a given reset/mode.
>
> I wonder why this is not already in place for eg syscon-reboot-mode
> resets, how does user space issue a command in those systems if the
> available commands aren't exposed to userspace ?
>
> Is there a kernel entity exposing those "modes" to userspace, somehow ?

Don't know one either.

>> A separate initcall is needed to parse the devicetree, instead of using
>> psci_dt_init because mm isn't sufficiently set up to allocate memory.
>> 
>> Reboot mode framework is close but doesn't quite fit with the
>> design and requirements for PSCI SYSTEM_RESET2. Some of these issues can
>> be solved but doesn't seem reasonable in sum:
>>  1. reboot mode registers against the reboot_notifier_list, which is too
>>     early to call SYSTEM_RESET2. PSCI would need to remember the reset
>>     type from the reboot-mode framework callback and use it
>>     psci_sys_reset.
>>  2. reboot mode assumes only one cookie/parameter is described in the
>>     device tree. SYSTEM_RESET2 uses 2: one for the type and one for
>>     cookie.
>
> This can be changed and I think it should, so that the reboot modes
> are exposed to user space and PSCI can use that.

Can we try to call them 'arguments' rather than 'modes' while discussing?
I think it's way too easy to confuse them otherwise.

>> +	psci_np = of_find_matching_node(NULL, psci_of_match);
>> +	if (!psci_np)
>> +		return 0;
>> +
>> +	np = of_find_node_by_name(psci_np, "reset-types");
>> +	if (!np)
>> +		return 0;
>
> Related to my initial question above. If LINUX_REBOOT_CMD_RESTART2 *arg command,
> is the actual reset to be issued, should we add a default mode "cold"
> and, if SYSTEM_RESET2 is supported, a "warm" reset mode too ?
>
> It all boils down to what *arg represents - adding "cold" and "warm"
> modes would remove the dependency on reboot_mode for resets issued
> through LINUX_REBOOT_CMD_RESTART2, the question is whether this
> is the correct thing to do.
>
> Comments very welcome.

It would make some sense to me to treat all psci reboot as "warm" and
not do anything here if reboot="cold" is set: those would have to
be backed by a hardware specific driver.

A related problem is how to determine when to use UEFI reboot: at the
moment arm64 tries the UEFI runtime interface before it even attempts
any of the notifiers, so PSCI reboot won't ever be used if UEFI is
present.

     Arnd


From andre.draszik at linaro.org  Fri Mar 14 09:40:00 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 14 Mar 2025 16:40:00 +0000
Subject: [PATCH 0/3] firmware: exynos-acpm: read fix & reduce log verbosity
Message-ID: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>

While trying to use the ACPM driver, I stubmbled across two issues:

    * acpm_pmic_bulk_read() doesn't return the correct register values
    * superfluous log messages during boot

The patches attached are the result and hopefully self-explanatory.

This driver only exists in linux-next at the moment.

Cheers,
Andre'

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Andr? Draszik (3):
      firmware: exynos-acpm: fix reading longer results
      firmware: exynos-acpm: silence EPROBE_DEFER error on boot
      firmware: exynos-acpm: convert to dev_err_probe() in client API

 drivers/firmware/samsung/exynos-acpm-pmic.c | 16 ++++++++--------
 drivers/firmware/samsung/exynos-acpm.c      | 13 ++++++-------
 2 files changed, 14 insertions(+), 15 deletions(-)
---
base-commit: 0226d0ce98a477937ed295fb7df4cc30b46fc304
change-id: 20250314-acpm-fixes-348c058476a7

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Fri Mar 14 09:40:01 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 14 Mar 2025 16:40:01 +0000
Subject: [PATCH 1/3] firmware: exynos-acpm: fix reading longer results
In-Reply-To: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
Message-ID: <20250314-acpm-fixes-v1-1-ab03ca8e723f@linaro.org>

ACPM commands that return more than 8 bytes currently don't work
correctly, as this driver ignores any such returned bytes.

This is evident in at least acpm_pmic_bulk_read(), where up to 8
registers can be read back and those 8 register values are placed
starting at &xfer->rxd[8].

The reason is that xfter->rxlen is initialized with the size of a
pointer (8 bytes), rather than the size of the byte array that pointer
points to (16 bytes)

Update the code such that we set the number of bytes expected to be the
size of the rx buffer.

Note1: While different commands have different lengths rx buffers, we
have to specify the same length for all rx buffers since acpm_get_rx()
assumes they're all the same length.

Note2: The different commands also have different lengths tx buffers,
but before switching the code to use the minimum possible length, some
more testing would have to be done to ensure this works correctly in
all situations. It seems wiser to just apply this fix here without
additional logic changes for now.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
issue is in linux-next only afaics at this stage, as driver is not
merged into Linus' tree yet
---
 drivers/firmware/samsung/exynos-acpm-pmic.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.c b/drivers/firmware/samsung/exynos-acpm-pmic.c
index 85e90d236da21ed76f7adba59caec165138ad313..39b33a356ebd240506b6390163229a70a2d1fe68 100644
--- a/drivers/firmware/samsung/exynos-acpm-pmic.c
+++ b/drivers/firmware/samsung/exynos-acpm-pmic.c
@@ -43,13 +43,13 @@ static inline u32 acpm_pmic_get_bulk(u32 data, unsigned int i)
 	return (data >> (ACPM_PMIC_BULK_SHIFT * i)) & ACPM_PMIC_BULK_MASK;
 }
 
-static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd,
+static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
 			       unsigned int acpm_chan_id)
 {
 	xfer->txd = cmd;
 	xfer->rxd = cmd;
-	xfer->txlen = sizeof(cmd);
-	xfer->rxlen = sizeof(cmd);
+	xfer->txlen = cmdlen;
+	xfer->rxlen = cmdlen;
 	xfer->acpm_chan_id = acpm_chan_id;
 }
 
@@ -71,7 +71,7 @@ int acpm_pmic_read_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_read_cmd(cmd, type, reg, chan);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -104,7 +104,7 @@ int acpm_pmic_bulk_read(const struct acpm_handle *handle,
 		return -EINVAL;
 
 	acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -144,7 +144,7 @@ int acpm_pmic_write_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_write_cmd(cmd, type, reg, chan, value);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -184,7 +184,7 @@ int acpm_pmic_bulk_write(const struct acpm_handle *handle,
 		return -EINVAL;
 
 	acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -214,7 +214,7 @@ int acpm_pmic_update_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)

-- 
2.49.0.rc1.451.g8f38331e32-goog



From andre.draszik at linaro.org  Fri Mar 14 09:40:02 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 14 Mar 2025 16:40:02 +0000
Subject: [PATCH 2/3] firmware: exynos-acpm: silence EPROBE_DEFER error on
 boot
In-Reply-To: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
Message-ID: <20250314-acpm-fixes-v1-2-ab03ca8e723f@linaro.org>

This driver emits error messages when client drivers are trying to get
an interface handle to this driver here before this driver has
completed _probe().

Given this driver returns -EPROBE_DEFER in that case, this is not an
error and shouldn't be emitted to the log, so just remove them.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
issue is in linux-next only afaics at this stage, as driver is not
merged into Linus' tree yet
---
 drivers/firmware/samsung/exynos-acpm.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..48f1e3cacaa709ae703115169df138b659ddae44 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -690,14 +690,11 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
 
 	acpm = platform_get_drvdata(pdev);
 	if (!acpm) {
-		dev_err(dev, "Cannot get drvdata from %s\n",
-			dev_name(&pdev->dev));
 		platform_device_put(pdev);
 		return ERR_PTR(-EPROBE_DEFER);
 	}
 
 	if (!try_module_get(pdev->dev.driver->owner)) {
-		dev_err(dev, "Cannot get module reference.\n");
 		platform_device_put(pdev);
 		return ERR_PTR(-EPROBE_DEFER);
 	}

-- 
2.49.0.rc1.451.g8f38331e32-goog



From andre.draszik at linaro.org  Fri Mar 14 09:40:03 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 14 Mar 2025 16:40:03 +0000
Subject: [PATCH 3/3] firmware: exynos-acpm: convert to dev_err_probe() in
 client API
In-Reply-To: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
Message-ID: <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>

dev_err_probe() exists to simplify code and unify error messages by
using its message template.

Convert the remaining dev_err() in acpm_get_by_phandle() to
dev_err_probe().

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/firmware/samsung/exynos-acpm.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 48f1e3cacaa709ae703115169df138b659ddae44..03f907a95c6acd66d89cd8af2f52e7c6dadf492a 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -701,12 +701,14 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
 
 	link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
 	if (!link) {
-		dev_err(&pdev->dev,
-			"Failed to create device link to consumer %s.\n",
-			dev_name(dev));
+		int ret = -EINVAL;
+
+		dev_err_probe(&pdev->dev, ret,
+			      "Failed to create device link to consumer %s.\n",
+			      dev_name(dev));
 		platform_device_put(pdev);
 		module_put(pdev->dev.driver->owner);
-		return ERR_PTR(-EINVAL);
+		return ERR_PTR(ret);
 	}
 
 	return &acpm->handle;

-- 
2.49.0.rc1.451.g8f38331e32-goog



From Frank.li at nxp.com  Fri Mar 14 09:42:29 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 14 Mar 2025 12:42:29 -0400
Subject: [PATCh v3 2/3] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <20250313071628.729168-3-ping.bai@nxp.com>
References: <20250313071628.729168-1-ping.bai@nxp.com>
 <20250313071628.729168-3-ping.bai@nxp.com>
Message-ID: <Z9RcdQbJYUk+SPte@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 03:16:27PM +0800, Jacky Bai wrote:
> Add the minimal dtsi support for i.MX943. i.MX943 is the
> first SoC of i.MX94 Family, create a common dtsi for the
> whole i.MX94 family, and the specific dtsi part for i.MX943.
>
> The clock, power domain and perf index need to be used by
> the device nodes for resource reference, add them along
> with the dtsi support.
>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v3 changes:
>   - remove the blank line
>   - add PAD config macro define as suggested by Frank Li
>   - update the device nodes compatible strings for imx94 as suggested by Krzysztof
>
>  - v2 changes:
>   - remove the unnecessary macro define in clock header as suggested by Krzysztof
>   - split the dtsi into imx94.dtsi and imx943.dtsi
>   - use low case in the pinfunc header as Frank suggested
>   - reorder the device nodes and properties
> ---
...
> +		aips2: bus at 42000000 {
> +			compatible = "fsl,aips-bus", "simple-bus";
> +			reg = <0x0 0x42000000 0x0 0x800000>;
> +			ranges = <0x42000000 0x0 0x42000000 0x8000000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +
> +			edma2: dma-controller at 42000000 {
> +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> +				reg = <0x42000000 0x210000>;
> +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> +				clock-names = "dma";
> +				#dma-cells = <3>;
> +				dma-channels = <64>;
> +				interrupts-extended = <&a55_irqsteer 0>, <&a55_irqsteer 1>, <&a55_irqsteer 2>,
> +					<&a55_irqsteer 3>, <&a55_irqsteer 4>, <&a55_irqsteer 5>,

Does below method work?

interrupt-parent = <&a55_irqsteer>
interrupts = <3>, <4>, <5>, ....

> +					<&a55_irqsteer 6>, <&a55_irqsteer 7>, <&a55_irqsteer 8>,
> +					<&a55_irqsteer 9>, <&a55_irqsteer 10>, <&a55_irqsteer 11>,
> +					<&a55_irqsteer 12>, <&a55_irqsteer 13>, <&a55_irqsteer 14>,
> +					<&a55_irqsteer 15>, <&a55_irqsteer 16>, <&a55_irqsteer 17>,
> +					<&a55_irqsteer 18>, <&a55_irqsteer 19>, <&a55_irqsteer 20>,
> +					<&a55_irqsteer 21>, <&a55_irqsteer 22>, <&a55_irqsteer 23>,
> +					<&a55_irqsteer 24>, <&a55_irqsteer 25>, <&a55_irqsteer 26>,
> +					<&a55_irqsteer 27>, <&a55_irqsteer 28>, <&a55_irqsteer 29>,
> +					<&a55_irqsteer 30>, <&a55_irqsteer 31>, <&a55_irqsteer 64>,
> +					<&a55_irqsteer 65>, <&a55_irqsteer 66>, <&a55_irqsteer 67>,
> +					<&a55_irqsteer 68>, <&a55_irqsteer 69>, <&a55_irqsteer 70>,
> +					<&a55_irqsteer 71>, <&a55_irqsteer 72>, <&a55_irqsteer 73>,
> +					<&a55_irqsteer 74>, <&a55_irqsteer 75>, <&a55_irqsteer 76>,
> +					<&a55_irqsteer 77>, <&a55_irqsteer 78>, <&a55_irqsteer 79>,
> +					<&a55_irqsteer 80>, <&a55_irqsteer 81>, <&a55_irqsteer 82>,
> +					<&a55_irqsteer 83>, <&a55_irqsteer 84>, <&a55_irqsteer 85>,
> +					<&a55_irqsteer 86>, <&a55_irqsteer 87>, <&a55_irqsteer 88>,

> +		cpu0: cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x0>;

I remember compatible is first property, then reg.

Frank
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l0>;
> +		};
> +
> +		cpu1: cpu at 100 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x100>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l1>;
> +		};
> +
> +		cpu2: cpu at 200 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x200>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l2>;
> +		};
> +
> +		cpu3: cpu at 300 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a55";
> +			reg = <0x300>;
> +			enable-method = "psci";
> +			#cooling-cells = <2>;
> +			cpu-idle-states = <&cpu_pd_wait>;
> +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> +			power-domain-names = "perf";
> +			i-cache-size = <32768>;
> +			i-cache-line-size = <64>;
> +			i-cache-sets = <128>;
> +			d-cache-size = <32768>;
> +			d-cache-line-size = <64>;
> +			d-cache-sets = <128>;
> +			next-level-cache = <&l2_cache_l3>;
> +		};
> +
> +		l2_cache_l0: l2-cache-l0 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l1: l2-cache-l1 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l2: l2-cache-l2 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l2_cache_l3: l2-cache-l3 {
> +			compatible = "cache";
> +			cache-size = <65536>;
> +			cache-line-size = <64>;
> +			cache-sets = <256>;
> +			cache-level = <2>;
> +			cache-unified;
> +			next-level-cache = <&l3_cache>;
> +		};
> +
> +		l3_cache: l3-cache {
> +			compatible = "cache";
> +			cache-size = <1048576>;
> +			cache-line-size = <64>;
> +			cache-sets = <1024>;
> +			cache-level = <3>;
> +			cache-unified;
> +		};
> +	};
> +};
> --
> 2.34.1
>


From p.zabel at pengutronix.de  Fri Mar 14 09:44:01 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 14 Mar 2025 17:44:01 +0100
Subject: [GIT PULL] Reset controller fixes for v6.14
Message-ID: <20250314164401.743984-1-p.zabel@pengutronix.de>

Dear arm-soc maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.pengutronix.de/pza/linux.git tags/reset-fixes-for-v6.14

for you to fetch changes up to 0e2268f88bb27ef14ac3de1bc4df29ff12bb28cb:

  reset: mchp: sparx5: Fix for lan966x (2025-03-13 09:40:26 +0100)

----------------------------------------------------------------
Reset controller fixes for v6.14

* Fix lan966x boot with internal CPU by stopping reset-microchip-sparx5
  from indirectly calling devm_request_mem_region() on a memory region
  shared with other devices.

----------------------------------------------------------------
Horatiu Vultur (1):
      reset: mchp: sparx5: Fix for lan966x

 drivers/reset/reset-microchip-sparx5.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)


From p.zabel at pengutronix.de  Fri Mar 14 09:44:06 2025
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 14 Mar 2025 17:44:06 +0100
Subject: [GIT PULL] Reset controller updates for v6.15
Message-ID: <20250314164406.744117-1-p.zabel@pengutronix.de>

Dear arm-soc maintainers,

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.pengutronix.de/pza/linux.git tags/reset-for-v6.15

for you to fetch changes up to c361baf67200a79c878d72cc879b1217c52cec96:

  reset: imx: fix incorrect module device table (2025-03-14 16:46:15 +0100)

----------------------------------------------------------------
Reset controller updates for v6.15

* Add missing microchip,sam9x7-rstc compatible to device tree binding
  documentation.
* Add SCU reset driver for i.MX8QXP and i.MX8QM.

----------------------------------------------------------------
Arnd Bergmann (1):
      reset: imx: fix incorrect module device table

Frank Li (2):
      dt-bindings: firmware: imx: add property reset-controller
      reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM

Varshini Rajendran (1):
      dt-bindings: reset: atmel,at91sam9260-reset: add sam9x7

 .../devicetree/bindings/firmware/fsl,scu.yaml      |  12 +++
 .../bindings/reset/atmel,at91sam9260-reset.yaml    |   4 +
 drivers/reset/Kconfig                              |   7 ++
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-imx-scu.c                      | 101 +++++++++++++++++++++
 5 files changed, 125 insertions(+)
 create mode 100644 drivers/reset/reset-imx-scu.c


From acme at kernel.org  Fri Mar 14 10:10:54 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Fri, 14 Mar 2025 14:10:54 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9PCjQ8PhOadVGQ8@google.com>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
Message-ID: <Z9RjHpEJGWtj8PAM@x1>

On Thu, Mar 13, 2025 at 10:45:49PM -0700, Namhyung Kim wrote:
> On Thu, Mar 13, 2025 at 05:47:27PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> > > Still building, but noticed this on x86_64:
> > > 
> > > 105: perf trace enum augmentation tests                              : FAILED!
> > > 106: perf trace BTF general tests                                    : FAILED!
> > > 107: perf trace exit race                                            : Ok
> > > 108: perf trace record and replay                                    : FAILED!
> > > 
> > > 
> > > The first doesn?t help that much with verbose mode, haven't checked if
> > > before this series it was failing :-\
> > > 
> > > root at x1:~# perf test -vvv 105
> > > 105: perf trace enum augmentation tests:
> > > --- start ---
> > > test child forked, pid 19411
> > > Checking if vmlinux exists
> > > Tracing syscall landlock_add_rule
> > > ---- end(-1) ----
> > > 105: perf trace enum augmentation tests                              : FAILED!
> > > root at x1:~#
> > 
> > So:
> > 
> > root at x1:~# perf trace -e landlock_add_rule perf test -w landlock
> > root at x1:~# 
> > 
> > But:
> > 
> > root at x1:~# perf trace perf test -w landlock |& grep landlock_add_rule
> >     26.120 ( 0.002 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7ffde75e2680, flags: 45) = -1 EINVAL (Invalid argument)
> >     26.124 ( 0.001 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffde75e2690, flags: 45) = -1 EINVAL (Invalid argument)
> > root at x1:~# 
> > 
> > -e is having some trouble, when no event is specified, then it works.
> > 
> > Something in the changes made to:
> > 
> > static int trace__parse_events_option(const struct option *opt, const char *str,
> >                                       int unset __maybe_unused)
> 
> Thanks for the test, I think this should fix it:
> 

Well, not really:

root at number:~# perf trace -e landlock_add_rule perf test -w landlock
perf: Segmentation fault
Obtained 10 stack frames.
perf() [0x5be761]
perf() [0x5be7f9]
/lib64/libc.so.6(+0x40fd0) [0x7fe005c4efd0]
perf() [0x491bc1]
perf() [0x497090]
perf() [0x4973ab]
perf() [0x413483]
/lib64/libc.so.6(+0x2a088) [0x7fe005c38088]
/lib64/libc.so.6(__libc_start_main+0x8b) [0x7fe005c3814b]
perf() [0x413ad5]
Segmentation fault (core dumped)
root at number:~#

Time for me to test another patch from Ian, the one symbolizing the
above backtrace...

- Arnaldo


> 
> 
> ---8<---
> diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
> index ace66e69c1bcde1e..67a8ec10e9e4bc8d 100644
> --- a/tools/perf/util/syscalltbl.c
> +++ b/tools/perf/util/syscalltbl.c
> @@ -76,7 +76,7 @@ int syscalltbl__id(int e_machine, const char *name)
>  {
>         const struct syscalltbl *table = find_table(e_machine);
>         struct syscall_cmp_key key;
> -       const int *id;
> +       const uint16_t *id;
>  
>         if (!table)
>                 return -1;


From andre.przywara at arm.com  Fri Mar 14 10:12:35 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 14 Mar 2025 17:12:35 +0000
Subject: [PATCH v3 03/15] dt-bindings: watchdog: sunxi: add Allwinner
 A523 compatible string
In-Reply-To: <20250307005712.16828-4-andre.przywara@arm.com>
References: <20250307005712.16828-1-andre.przywara@arm.com>
	<20250307005712.16828-4-andre.przywara@arm.com>
Message-ID: <20250314171235.25db7044@donnerap.manchester.arm.com>

On Fri, 7 Mar 2025 00:57:00 +0000
Andre Przywara <andre.przywara at arm.com> wrote:

Hi Wim, Guenter,

> The Allwinner A523 SoC features a watchdog similar to the one used in
> previous SoCs, but moves some registers around (by just one word), making
> it incompatible to existing IPs.
> 
> Add the new name to the list of compatible string, and also to the list
> of IP requiring two clock inputs.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Acked-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>

is there any chance that this DT binding patch (and patch 04/15, touching
the actual driver) would make it into -next any time soon, and hopefully
into v6.15? From what I can see it's the only binding left before the
sunxi maintainers can merge the devicetree patches for this new SoC (most
others are in, pinctrl and NMI should show up in the next days).

Let me know if I can help with anything or if you need more information!

Thanks,
Andre

> ---
>  .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml   | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> index 64c8f73938099..b35ac03d51727 100644
> --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> @@ -32,6 +32,7 @@ properties:
>        - items:
>            - const: allwinner,sun20i-d1-wdt-reset
>            - const: allwinner,sun20i-d1-wdt
> +      - const: allwinner,sun55i-a523-wdt
>  
>    reg:
>      maxItems: 1
> @@ -60,6 +61,7 @@ if:
>            - allwinner,sun20i-d1-wdt-reset
>            - allwinner,sun50i-r329-wdt
>            - allwinner,sun50i-r329-wdt-reset
> +          - allwinner,sun55i-a523-wdt
>  
>  then:
>    properties:



From willmcvicker at google.com  Fri Mar 14 10:14:13 2025
From: willmcvicker at google.com (William McVicker)
Date: Fri, 14 Mar 2025 10:14:13 -0700
Subject: [PATCH 1/2] arm64: dts: exynos: gs101: ufs: add dma-coherent
 property
In-Reply-To: <20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
 <20250314-ufs-dma-coherent-v1-1-bdf9f9be2919@linaro.org>
Message-ID: <Z9Rj5T8il4rZAsoq@google.com>

On 03/14/2025, Peter Griffin wrote:
> ufs-exynos driver configures the sysreg shareability as
> cacheable for gs101 so we need to set the dma-coherent
> property so the descriptors are also allocated cacheable.
> 
> This fixes the UFS stability issues we have seen with
> the upstream UFS driver on gs101.
> 
> Fixes: 4c65d7054b4c ("arm64: dts: exynos: gs101: Add ufs and ufs-phy dt nodes")
> Cc: stable at vger.kernel.org
> Suggested-by: Will McVicker <willmcvicker at google.com>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>

Tested-by: Will McVicker <willmcvicker at google.com>

Verified I can properly boot to Android recovery with UFS probing and mounting
the partitions in the fstab.

Can you send this to 6.12 stable as well since this is fixing booting issues
with Android?

Thanks,
Will

> ---
>  arch/arm64/boot/dts/exynos/google/gs101.dtsi | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/boot/dts/exynos/google/gs101.dtsi b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
> index c5335dd59dfe9fcf8c64d66a466799600f8447b0..cf30128ef004568f01b1c7150c5585ba267d64bc 100644
> --- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi
> +++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
> @@ -1360,6 +1360,7 @@ ufs_0: ufs at 14700000 {
>  				 <&cmu_hsi2 CLK_GOUT_HSI2_SYSREG_HSI2_PCLK>;
>  			clock-names = "core_clk", "sclk_unipro_main", "fmp",
>  				      "aclk", "pclk", "sysreg";
> +			dma-coherent;
>  			freq-table-hz = <0 0>, <0 0>, <0 0>, <0 0>, <0 0>, <0 0>;
>  			pinctrl-0 = <&ufs_rst_n &ufs_refclk_out>;
>  			pinctrl-names = "default";
> 
> -- 
> 2.49.0.rc1.451.g8f38331e32-goog
> 


From willmcvicker at google.com  Fri Mar 14 10:16:49 2025
From: willmcvicker at google.com (William McVicker)
Date: Fri, 14 Mar 2025 10:16:49 -0700
Subject: [PATCH 0/2] Add dma-coherent for gs101 UFS dt node
In-Reply-To: <0d7a8cad-adfc-4cac-bcc6-65d1f9c86b43@acm.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
 <0d7a8cad-adfc-4cac-bcc6-65d1f9c86b43@acm.org>
Message-ID: <Z9RkgY3gnx6Xp0nc@google.com>

On 03/14/2025, Bart Van Assche wrote:
> On 3/14/25 8:38 AM, Peter Griffin wrote:
> > ufs-exynos driver enables the shareability option for gs101 which
> > means the descriptors need to be allocated as cacheable.
> 
> Shouldn't that code be modified such that the shareability option is
> only set if the dma-coherent property is present in the device tree?

That's what we do downstream and would fix any issues when booting with an
older DT that doesn't have the `dma-coherent` property set. So I agree that
would be a worthy fix (which I did verify fixes the stability issues).

Regards,
Will

> 
> Thanks,
> 
> Bart.


From acme at kernel.org  Fri Mar 14 10:26:41 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Fri, 14 Mar 2025 14:26:41 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9RjHpEJGWtj8PAM@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
 <Z9RjHpEJGWtj8PAM@x1>
Message-ID: <Z9Rm0W6YLpxKIcI1@x1>

On Fri, Mar 14, 2025 at 02:10:57PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Mar 13, 2025 at 10:45:49PM -0700, Namhyung Kim wrote:
> > On Thu, Mar 13, 2025 at 05:47:27PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > Still building, but noticed this on x86_64:
> > > > 
> > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > 106: perf trace BTF general tests                                    : FAILED!
> > > > 107: perf trace exit race                                            : Ok
> > > > 108: perf trace record and replay                                    : FAILED!
> > > > 
> > > > 
> > > > The first doesn?t help that much with verbose mode, haven't checked if
> > > > before this series it was failing :-\
> > > > 
> > > > root at x1:~# perf test -vvv 105
> > > > 105: perf trace enum augmentation tests:
> > > > --- start ---
> > > > test child forked, pid 19411
> > > > Checking if vmlinux exists
> > > > Tracing syscall landlock_add_rule
> > > > ---- end(-1) ----
> > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > root at x1:~#
> > > 
> > > So:
> > > 
> > > root at x1:~# perf trace -e landlock_add_rule perf test -w landlock
> > > root at x1:~# 
> > > 
> > > But:
> > > 
> > > root at x1:~# perf trace perf test -w landlock |& grep landlock_add_rule
> > >     26.120 ( 0.002 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7ffde75e2680, flags: 45) = -1 EINVAL (Invalid argument)
> > >     26.124 ( 0.001 ms): perf/19791 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffde75e2690, flags: 45) = -1 EINVAL (Invalid argument)
> > > root at x1:~# 
> > > 
> > > -e is having some trouble, when no event is specified, then it works.
> > > 
> > > Something in the changes made to:
> > > 
> > > static int trace__parse_events_option(const struct option *opt, const char *str,
> > >                                       int unset __maybe_unused)
> > 
> > Thanks for the test, I think this should fix it:
> > 
> 
> Well, not really:
> 
> root at number:~# perf trace -e landlock_add_rule perf test -w landlock
> perf: Segmentation fault
> Obtained 10 stack frames.
> perf() [0x5be761]
> perf() [0x5be7f9]
> /lib64/libc.so.6(+0x40fd0) [0x7fe005c4efd0]
> perf() [0x491bc1]
> perf() [0x497090]
> perf() [0x4973ab]
> perf() [0x413483]
> /lib64/libc.so.6(+0x2a088) [0x7fe005c38088]
> /lib64/libc.so.6(__libc_start_main+0x8b) [0x7fe005c3814b]
> perf() [0x413ad5]
> Segmentation fault (core dumped)
> root at number:~#
> 
> Time for me to test another patch from Ian, the one symbolizing the
> above backtrace...
> 
> Worked, but didn't help as much, with gdb:
> 
> (gdb) run trace -e landlock_add_rule perf test -w landlock
> Starting program: /root/bin/perf trace -e landlock_add_rule perf test -w landlock
> 
> This GDB supports auto-downloading debuginfo from the following URLs:
>   <https://debuginfod.fedoraproject.org/>
> Enable debuginfod for this session? (y or [n]) y
> Debuginfod has been enabled.
> To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
> Downloading 53.88 K separate debug info for system-supplied DSO at 0x7ffff7fc6000
> Downloading 458.26 K separate debug info for /lib64/libtracefs.so.1                                                                                                                            
> [Thread debugging using libthread_db enabled]                                                                                                                                                  
> Using host libthread_db library "/lib64/libthread_db.so.1".
> [Detaching after fork from child process 39141]
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x00000000004d0e56 in trace__find_usable_bpf_prog_entry (trace=0x7fffffffa510, sc=0x10fb7b0) at builtin-trace.c:3882
> 3882				bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
> (gdb) p field
> $1 = (struct tep_format_field *) 0x64656e6769736e75
> (gdb) bt
> #0  0x00000000004d0e56 in trace__find_usable_bpf_prog_entry (trace=0x7fffffffa510, sc=0x10fb7b0) at builtin-trace.c:3882
> #1  0x00000000004cf3de in trace__init_syscalls_bpf_prog_array_maps (trace=0x7fffffffa510, e_machine=62) at builtin-trace.c:4040
> #2  0x00000000004bf626 in trace__run (trace=0x7fffffffa510, argc=4, argv=0x7fffffffde40) at builtin-trace.c:4473
> #3  0x00000000004bb7a9 in cmd_trace (argc=4, argv=0x7fffffffde40) at builtin-trace.c:5741
> #4  0x00000000004d873f in run_builtin (p=0xf83d48 <commands+648>, argc=7, argv=0x7fffffffde40) at perf.c:351
> #5  0x00000000004d7df3 in handle_internal_command (argc=7, argv=0x7fffffffde40) at perf.c:404
> #6  0x00000000004d860f in run_argv (argcp=0x7fffffffdc7c, argv=0x7fffffffdc70) at perf.c:448
> #7  0x00000000004d7a4f in main (argc=7, argv=0x7fffffffde40) at perf.c:556
> (gdb) list -10
> 3867		return NULL;
> 3868	
> 3869	try_to_find_pair:
> 3870		for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
> 3871			int id = syscalltbl__id_at_idx(sc->e_machine, i);
> 3872			struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
> 3873			struct bpf_program *pair_prog;
> 3874			bool is_candidate = false;
> 3875	
> 3876			if (pair == NULL || pair == sc ||
> (gdb)

Humm

(gdb) p i
$1 = 147
(gdb) p num_idx
$2 = 379
(gdb) p id
$3 = 192
(gdb) p pair
$4 = (struct syscall *) 0x10fe8f0
(gdb) p *pair
$5 = {e_machine = 62, id = 192, tp_format = 0x10f6c00, nr_args = 3, args_size = 48, bpf_prog = {sys_enter = 0x0, sys_exit = 0x0}, is_exit = false, is_open = false, nonexistent = false, 
  use_btf = false, args = 0x10f9480, name = 0x814406 "lgetxattr", fmt = 0x0, arg_fmt = 0x10fa0a0}
(gdb) p sc
$6 = (struct syscall *) 0x10fb7b0
(gdb) p sc->args
$7 = (struct tep_format_field *) 0x64656e6769736e75
(gdb) p *pair
$8 = {e_machine = 62, id = 192, tp_format = 0x10f6c00, nr_args = 3, args_size = 48, bpf_prog = {sys_enter = 0x0, sys_exit = 0x0}, is_exit = false, is_open = false, nonexistent = false, 
  use_btf = false, args = 0x10f9480, name = 0x814406 "lgetxattr", fmt = 0x0, arg_fmt = 0x10fa0a0}
(gdb)

it finds the pair, but then its sc->args has a bogus pointer... I'll see
where this isn't being initialized...

- Arnaldo


From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:51 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:51 +0100
Subject: [PATCH v4 8/8] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-9-fabrice.gasnier@foss.st.com>

During the low power modes the generic ARM timer is deactivated, so the
the tick broadcast is used, based on LPTIMER3 which is clocked by LSE on
STMicroelectronics boards.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1..242115863ab4 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -190,6 +190,14 @@ &i2c8 {
 	status = "disabled";
 };
 
+/* use LPTIMER with tick broadcast for suspend mode */
+&lptimer3 {
+	status = "okay";
+	timer {
+		status = "okay";
+	};
+};
+
 &rtc {
 	status = "okay";
 };
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:44 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:44 +0100
Subject: [PATCH v4 1/8] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-2-fabrice.gasnier@foss.st.com>

Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
STM32MP25 SoC. Some features has been updated or added to the low-power
timer:
- new capture compare channels
- up to two PWM channels
- PWM input capture
- peripheral interconnect in stm32mp25 has been updated (new triggers).
- registers/bits has been added or revisited (IER access).
So introduce a new compatible to handle this diversity.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V4:
- Add Rob's Reviewed-by tag
Changes in V3:
- Fix yaml indentation issue found by Rob's bot
Changes in V2:
- Use fallback compatibles, along with stm32mp25 specific compatible
- trigger identifier can be up to 4 (e.g. from LPTIM1..5)
---
 .../bindings/mfd/st,stm32-lptimer.yaml        | 40 ++++++++++++++++---
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index d41308856408..4eabafb8079d 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -21,7 +21,12 @@ maintainers:
 
 properties:
   compatible:
-    const: st,stm32-lptimer
+    oneOf:
+      - items:
+          - const: st,stm32mp25-lptimer
+          - const: st,stm32-lptimer
+      - items:
+          - const: st,stm32-lptimer
 
   reg:
     maxItems: 1
@@ -48,13 +53,21 @@ properties:
     minItems: 1
     maxItems: 2
 
+  power-domains:
+    maxItems: 1
+
   pwm:
     type: object
     additionalProperties: false
 
     properties:
       compatible:
-        const: st,stm32-pwm-lp
+        oneOf:
+          - items:
+              - const: st,stm32mp25-pwm-lp
+              - const: st,stm32-pwm-lp
+          - items:
+              - const: st,stm32-pwm-lp
 
       "#pwm-cells":
         const: 3
@@ -69,7 +82,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-counter
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-counter
+              - const: st,stm32-lptimer-counter
+          - items:
+              - const: st,stm32-lptimer-counter
 
     required:
       - compatible
@@ -80,7 +98,12 @@ properties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-timer
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-timer
+              - const: st,stm32-lptimer-timer
+          - items:
+              - const: st,stm32-lptimer-timer
 
     required:
       - compatible
@@ -92,13 +115,18 @@ patternProperties:
 
     properties:
       compatible:
-        const: st,stm32-lptimer-trigger
+        oneOf:
+          - items:
+              - const: st,stm32mp25-lptimer-trigger
+              - const: st,stm32-lptimer-trigger
+          - items:
+              - const: st,stm32-lptimer-trigger
 
       reg:
         description: Identify trigger hardware block.
         items:
           minimum: 0
-          maximum: 2
+          maximum: 4
 
     required:
       - compatible
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:49 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:49 +0100
Subject: [PATCH v4 6/8] arm64: defconfig: enable STM32 LP timer clockevent driver
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-7-fabrice.gasnier@foss.st.com>

Enable the STM32 LP timer MFD core and clockevent drivers used on
STM32MP257F-EV1 board, for PSCI OSI.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in v2:
- dropped unused IIO trigger, PWM and counter driver unused on upstream
board currently, as advised by Krzysztof
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1f25423de383..b29b2350ae27 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -775,6 +775,7 @@ CONFIG_MFD_TI_LP873X=m
 CONFIG_MFD_TPS65219=y
 CONFIG_MFD_TPS6594_I2C=m
 CONFIG_MFD_ROHM_BD718XX=y
+CONFIG_MFD_STM32_LPTIMER=m
 CONFIG_MFD_WCD934X=m
 CONFIG_MFD_KHADAS_MCU=m
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -1401,6 +1402,7 @@ CONFIG_CLK_RENESAS_VBATTB=m
 CONFIG_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_TEGRA186_TIMER=y
+CONFIG_CLKSRC_STM32_LP=y
 CONFIG_RENESAS_OSTM=y
 CONFIG_ARM_MHU=y
 CONFIG_IMX_MBOX=y
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:43 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:43 +0100
Subject: [PATCH v4 0/8] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
Message-ID: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>

This series adds support for STM32MP25 to MFD PWM, IIO, counter and
clocksource low-power timer (LPTIM) drivers.
This new variant is managed by using a new DT compatible string, hardware
configuration and version registers.
It comes with a slightly updated register set, some new features and new
interconnect signals inside the SoC.
Same feature list as on STM32MP1x is supported currently.
The device tree files add all instances in stm32mp251 dtsi file.

Changes in V4
---
- Simplify IIO trigger driver as per Jonathan's comments.
- Rework clocksource driver: encapsulate mp25 changes in separate function
  after Daniel's suggestion.
- Add some definitions to MFD header.

Changes in V3
---
- Yaml indentation issue fixed, reported by Rob's bot

Changes in V2
---
- Review comments from Krzysztof
  - Adopt compatible fallback in dt-bindings and driver
  - drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
  - counter driver: no update (patch dropped)
  - defconfig: only enable the necessary config for upstream board
  - add lptimer DT node in stm32mp257f-ev1 board
- Add missing management of IER access for stm32mp25

Fabrice Gasnier (7):
  dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
  mfd: stm32-lptimer: add support for stm32mp25
  clocksource: stm32-lptimer: add support for stm32mp25
  pwm: stm32-lp: add support for stm32mp25
  arm64: defconfig: enable STM32 LP timer clockevent driver
  arm64: dts: st: add low-power timer nodes on stm32mp251
  arm64: dts: st: use lptimer3 as tick broadcast source on
    stm32mp257f-ev1

Olivier Moysan (1):
  iio: trigger: stm32-lptimer: add support for stm32mp25

 .../bindings/mfd/st,stm32-lptimer.yaml        |  40 +++-
 arch/arm64/boot/dts/st/stm32mp251.dtsi        | 177 ++++++++++++++
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts    |   8 +
 arch/arm64/configs/defconfig                  |   2 +
 drivers/clocksource/timer-stm32-lp.c          |  51 +++-
 drivers/iio/trigger/stm32-lptimer-trigger.c   |  75 ++++--
 drivers/mfd/stm32-lptimer.c                   |  33 ++-
 drivers/pwm/pwm-stm32-lp.c                    | 219 +++++++++++++++---
 include/linux/iio/timer/stm32-lptim-trigger.h |   9 +
 include/linux/mfd/stm32-lptimer.h             |  37 ++-
 10 files changed, 594 insertions(+), 57 deletions(-)

-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:45 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:45 +0100
Subject: [PATCH v4 2/8] mfd: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-3-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC.
A new hardware configuration register (HWCFGR2) has been added, to gather
number of capture/compare channels, autonomous mode and input capture
capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
supports a smaller set of features. This can now be read from HWCFGR
registers.

Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
Update the stm32_lptimer data struct so signal the number of
capture/compare channels to the child devices.
Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V4:
- Add DIEROK, ARROK status flags, and their clear flags.
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Compatibility is added by reading hardware configuration
  registers.
- read version register, to be used by clockevent child driver
- rename register/bits definitions
---
 drivers/mfd/stm32-lptimer.c       | 33 ++++++++++++++++++++++++++-
 include/linux/mfd/stm32-lptimer.h | 37 ++++++++++++++++++++++++++++---
 2 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c
index b2704a9809c7..09073dbc9c80 100644
--- a/drivers/mfd/stm32-lptimer.c
+++ b/drivers/mfd/stm32-lptimer.c
@@ -6,6 +6,7 @@
  * Inspired by Benjamin Gaignard's stm32-timers driver
  */
 
+#include <linux/bitfield.h>
 #include <linux/mfd/stm32-lptimer.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
@@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
 	return 0;
 }
 
+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
+{
+	u32 val;
+	int ret;
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
+	if (ret)
+		return ret;
+
+	/* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
+	if (ret)
+		return ret;
+
+	/* Fallback to legacy init if HWCFGR isn't present */
+	if (!val)
+		return stm32_lptimer_detect_encoder(ddata);
+
+	ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
+
+	ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
+	if (ret)
+		return ret;
+
+	/* Number of capture/compare channels */
+	ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
+
+	return 0;
+}
+
 static int stm32_lptimer_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
 	if (IS_ERR(ddata->clk))
 		return PTR_ERR(ddata->clk);
 
-	ret = stm32_lptimer_detect_encoder(ddata);
+	ret = stm32_lptimer_detect_hwcfgr(ddata);
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h
index 06d3f11dc3c9..a592c8dc716d 100644
--- a/include/linux/mfd/stm32-lptimer.h
+++ b/include/linux/mfd/stm32-lptimer.h
@@ -17,20 +17,30 @@
 #define STM32_LPTIM_IER		0x08	/* Interrupt Enable Reg      */
 #define STM32_LPTIM_CFGR	0x0C	/* Configuration Reg         */
 #define STM32_LPTIM_CR		0x10	/* Control Reg               */
-#define STM32_LPTIM_CMP		0x14	/* Compare Reg               */
+#define STM32_LPTIM_CMP		0x14	/* Compare Reg (MP25 CCR1)   */
 #define STM32_LPTIM_ARR		0x18	/* Autoreload Reg            */
 #define STM32_LPTIM_CNT		0x1C	/* Counter Reg               */
+#define STM32_LPTIM_CCMR1	0x2C	/* Capture/Compare Mode MP25 */
+#define STM32_LPTIM_CCR2	0x34	/* Compare Reg2 MP25         */
+
+#define STM32_LPTIM_HWCFGR2	0x3EC	/* Hardware configuration register 2 - MP25 */
+#define STM32_LPTIM_HWCFGR1	0x3F0	/* Hardware configuration register 1 - MP15 */
+#define STM32_LPTIM_VERR	0x3F4	/* Version identification register - MP15 */
 
 /* STM32_LPTIM_ISR - bit fields */
+#define STM32_LPTIM_DIEROK_ARROK	(BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2_ARROK		(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOK_ARROK		GENMASK(4, 3)
 #define STM32_LPTIM_ARROK		BIT(4)
 #define STM32_LPTIM_CMPOK		BIT(3)
 
 /* STM32_LPTIM_ICR - bit fields */
-#define STM32_LPTIM_ARRMCF		BIT(1)
+#define STM32_LPTIM_DIEROKCF_ARROKCF	(BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2OKCF_ARROKCF	(BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOKCF_ARROKCF	GENMASK(4, 3)
+#define STM32_LPTIM_ARRMCF		BIT(1)
 
-/* STM32_LPTIM_IER - bit flieds */
+/* STM32_LPTIM_IER - bit fields */
 #define STM32_LPTIM_ARRMIE	BIT(1)
 
 /* STM32_LPTIM_CR - bit fields */
@@ -53,16 +63,37 @@
 /* STM32_LPTIM_ARR */
 #define STM32_LPTIM_MAX_ARR	0xFFFF
 
+/* STM32_LPTIM_CCMR1 */
+#define STM32_LPTIM_CC2P	GENMASK(19, 18)
+#define STM32_LPTIM_CC2E	BIT(17)
+#define STM32_LPTIM_CC2SEL	BIT(16)
+#define STM32_LPTIM_CC1P	GENMASK(3, 2)
+#define STM32_LPTIM_CC1E	BIT(1)
+#define STM32_LPTIM_CC1SEL	BIT(0)
+
+/* STM32_LPTIM_HWCFGR1 */
+#define STM32_LPTIM_HWCFGR1_ENCODER	BIT(16)
+
+/* STM32_LPTIM_HWCFGR2 */
+#define STM32_LPTIM_HWCFGR2_CHAN_NUM	GENMASK(3, 0)
+
+/* STM32_LPTIM_VERR */
+#define STM32_LPTIM_VERR_23	0x23	/* STM32MP25 */
+
 /**
  * struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
  * @clk: clock reference for this instance
  * @regmap: register map reference for this instance
  * @has_encoder: indicates this Low-Power Timer supports encoder mode
+ * @num_cc_chans: indicates the number of capture/compare channels
+ * @version: indicates the major and minor revision of the controller
  */
 struct stm32_lptimer {
 	struct clk *clk;
 	struct regmap *regmap;
 	bool has_encoder;
+	unsigned int num_cc_chans;
+	u32 version;
 };
 
 #endif
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:46 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:46 +0100
Subject: [PATCH v4 3/8] iio: trigger: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-4-fabrice.gasnier@foss.st.com>

From: Olivier Moysan <olivier.moysan at foss.st.com>

Add support for STM32MP25 SoC. Use newly introduced compatible to handle
this new HW variant. Add new trigger definitions that can be used by the
stm32 analog-to-digital converter. Use compatible data to identify them.

Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in v4:
- Jonathan's comment: simplify infrastructure by keeping
  devm_iio_trigger_register. Don't need to cast compatible data.
---
 drivers/iio/trigger/stm32-lptimer-trigger.c   | 75 ++++++++++++++-----
 include/linux/iio/timer/stm32-lptim-trigger.h |  9 +++
 2 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c
index f1e18913236a..3dcc8d2fe093 100644
--- a/drivers/iio/trigger/stm32-lptimer-trigger.c
+++ b/drivers/iio/trigger/stm32-lptimer-trigger.c
@@ -16,16 +16,43 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 
-/* List Low-Power Timer triggers */
-static const char * const stm32_lptim_triggers[] = {
-	LPTIM1_OUT,
-	LPTIM2_OUT,
-	LPTIM3_OUT,
+/* Maximum triggers + one trailing null entry to indicate the end of array */
+#define MAX_TRIGGERS 3
+
+struct stm32_lptim_cfg {
+	const char * const (*triggers)[MAX_TRIGGERS];
+	unsigned int nb_triggers;
+};
+
+/* List Low-Power Timer triggers for H7, MP13, MP15 */
+static const char * const stm32_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_OUT,},
+	{ LPTIM2_OUT,},
+	{ LPTIM3_OUT,},
+};
+
+/* List Low-Power Timer triggers for STM32MP25 */
+static const char * const stm32mp25_lptim_triggers[][MAX_TRIGGERS] = {
+	{ LPTIM1_CH1, LPTIM1_CH2, },
+	{ LPTIM2_CH1, LPTIM2_CH2, },
+	{ LPTIM3_CH1,},
+	{ LPTIM4_CH1,},
+	{ LPTIM5_OUT,},
+};
+
+static const struct stm32_lptim_cfg stm32mp15_lptim_cfg = {
+	.triggers = stm32_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32_lptim_triggers),
+};
+
+static const struct stm32_lptim_cfg stm32mp25_lptim_cfg = {
+	.triggers = stm32mp25_lptim_triggers,
+	.nb_triggers = ARRAY_SIZE(stm32mp25_lptim_triggers),
 };
 
 struct stm32_lptim_trigger {
 	struct device *dev;
-	const char *trg;
+	const char * const *triggers;
 };
 
 static int stm32_lptim_validate_device(struct iio_trigger *trig,
@@ -56,22 +83,33 @@ EXPORT_SYMBOL(is_stm32_lptim_trigger);
 
 static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv)
 {
-	struct iio_trigger *trig;
+	const char * const *cur = priv->triggers;
+	int ret;
 
-	trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg);
-	if  (!trig)
-		return -ENOMEM;
+	while (cur && *cur) {
+		struct iio_trigger *trig;
 
-	trig->dev.parent = priv->dev->parent;
-	trig->ops = &stm32_lptim_trigger_ops;
-	iio_trigger_set_drvdata(trig, priv);
+		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
+		if  (!trig)
+			return -ENOMEM;
 
-	return devm_iio_trigger_register(priv->dev, trig);
+		trig->dev.parent = priv->dev->parent;
+		trig->ops = &stm32_lptim_trigger_ops;
+		iio_trigger_set_drvdata(trig, priv);
+
+		ret = devm_iio_trigger_register(priv->dev, trig);
+		if (ret)
+			return ret;
+		cur++;
+	}
+
+	return 0;
 }
 
 static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 {
 	struct stm32_lptim_trigger *priv;
+	struct stm32_lptim_cfg const *lptim_cfg;
 	u32 index;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -81,17 +119,20 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev)
 	if (device_property_read_u32(&pdev->dev, "reg", &index))
 		return -EINVAL;
 
-	if (index >= ARRAY_SIZE(stm32_lptim_triggers))
+	lptim_cfg = device_get_match_data(&pdev->dev);
+
+	if (index >= lptim_cfg->nb_triggers)
 		return -EINVAL;
 
 	priv->dev = &pdev->dev;
-	priv->trg = stm32_lptim_triggers[index];
+	priv->triggers = lptim_cfg->triggers[index];
 
 	return stm32_lptim_setup_trig(priv);
 }
 
 static const struct of_device_id stm32_lptim_trig_of_match[] = {
-	{ .compatible = "st,stm32-lptimer-trigger", },
+	{ .compatible = "st,stm32-lptimer-trigger", .data = &stm32mp15_lptim_cfg },
+	{ .compatible = "st,stm32mp25-lptimer-trigger", .data = &stm32mp25_lptim_cfg},
 	{},
 };
 MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match);
diff --git a/include/linux/iio/timer/stm32-lptim-trigger.h b/include/linux/iio/timer/stm32-lptim-trigger.h
index a34dcf6a6001..ce3cf0addb2e 100644
--- a/include/linux/iio/timer/stm32-lptim-trigger.h
+++ b/include/linux/iio/timer/stm32-lptim-trigger.h
@@ -14,6 +14,15 @@
 #define LPTIM1_OUT	"lptim1_out"
 #define LPTIM2_OUT	"lptim2_out"
 #define LPTIM3_OUT	"lptim3_out"
+#define LPTIM4_OUT	"lptim4_out"
+#define LPTIM5_OUT	"lptim5_out"
+
+#define LPTIM1_CH1	"lptim1_ch1"
+#define LPTIM1_CH2	"lptim1_ch2"
+#define LPTIM2_CH1	"lptim2_ch1"
+#define LPTIM2_CH2	"lptim2_ch2"
+#define LPTIM3_CH1	"lptim3_ch1"
+#define LPTIM4_CH1	"lptim4_ch1"
 
 #if IS_REACHABLE(CONFIG_IIO_STM32_LPTIMER_TRIGGER)
 bool is_stm32_lptim_trigger(struct iio_trigger *trig);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:48 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:48 +0100
Subject: [PATCH v4 5/8] pwm: stm32-lp: add support for stm32mp25
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-6-fabrice.gasnier@foss.st.com>

Add support for STM32MP25 SoC. A new compatible has been added to the
dt-bindings. It represents handle new features, registers and bits
diversity.
It isn't used currently in the driver, as matching is done by retrieving
MFD parent data.

New dedicated capture/compare channels has been added: e.g. a new compare
register for channel 2. Some controls (polarity / cc channel enable) are
handled in CCMR register on this new variant (instead of wavepol bit).

So, Low-power timer can now have up to two PWM outputs. Use device data
from the MFD parent to configure the number of PWM channels e.g. 'npwm'.

Update current get_state() and apply() ops to support either:
- one PWM channel (as on older revision, or LPTIM5 on STM32MP25)
- two PWM channels (e.g. LPTIM1/2/3/4 on STM32MP25 that has the full
  feature set)
Introduce new routines to manage common prescaler, reload register and
global enable bit.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Matching is achieved by using MFD parent data.
- renamed registers/bits defintions
---
 drivers/pwm/pwm-stm32-lp.c | 219 ++++++++++++++++++++++++++++++++-----
 1 file changed, 193 insertions(+), 26 deletions(-)

diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 5832dce8ed9d..4789eafb8bac 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -20,6 +20,7 @@
 struct stm32_pwm_lp {
 	struct clk *clk;
 	struct regmap *regmap;
+	unsigned int num_cc_chans;
 };
 
 static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
@@ -30,13 +31,101 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
 /* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
 #define STM32_LPTIM_MAX_PRESCALER	128
 
+static int stm32_pwm_lp_update_allowed(struct stm32_pwm_lp *priv, int channel)
+{
+	int ret;
+	u32 ccmr1;
+	unsigned long ccmr;
+
+	/* Only one PWM on this LPTIMER: enable, prescaler and reload value can be changed */
+	if (!priv->num_cc_chans)
+		return true;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+	ccmr = ccmr1 & (STM32_LPTIM_CC1E | STM32_LPTIM_CC2E);
+
+	/* More than one channel enabled: enable, prescaler or ARR value can't be changed */
+	if (bitmap_weight(&ccmr, sizeof(u32) * BITS_PER_BYTE) > 1)
+		return false;
+
+	/*
+	 * Only one channel is enabled (or none): check status on the other channel, to
+	 * report if enable, prescaler or ARR value can be changed.
+	 */
+	if (channel)
+		return !(ccmr1 & STM32_LPTIM_CC1E);
+	else
+		return !(ccmr1 & STM32_LPTIM_CC2E);
+}
+
+static int stm32_pwm_lp_compare_channel_apply(struct stm32_pwm_lp *priv, int channel,
+					      bool enable, enum pwm_polarity polarity)
+{
+	u32 ccmr1, val, mask;
+	bool reenable;
+	int ret;
+
+	/* No dedicated CC channel: nothing to do */
+	if (!priv->num_cc_chans)
+		return 0;
+
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+	if (ret)
+		return ret;
+
+	if (channel) {
+		/* Must disable CC channel (CCxE) to modify polarity (CCxP), then re-enable */
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC2E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC2P, ccmr1));
+
+		mask = STM32_LPTIM_CC2SEL | STM32_LPTIM_CC2E | STM32_LPTIM_CC2P;
+		val = FIELD_PREP(STM32_LPTIM_CC2P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC2E, enable);
+	} else {
+		reenable = (enable && FIELD_GET(STM32_LPTIM_CC1E, ccmr1)) &&
+			(polarity != FIELD_GET(STM32_LPTIM_CC1P, ccmr1));
+
+		mask = STM32_LPTIM_CC1SEL | STM32_LPTIM_CC1E | STM32_LPTIM_CC1P;
+		val = FIELD_PREP(STM32_LPTIM_CC1P, polarity);
+		val |= FIELD_PREP(STM32_LPTIM_CC1E, enable);
+	}
+
+	if (reenable) {
+		u32 cfgr, presc;
+		unsigned long rate;
+		unsigned int delay_us;
+
+		ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1,
+					 channel ? STM32_LPTIM_CC2E : STM32_LPTIM_CC1E, 0);
+		if (ret)
+			return ret;
+		/*
+		 * After a write to the LPTIM_CCMRx register, a new write operation can only be
+		 * performed after a delay of at least (PRESC ? 3) clock cycles
+		 */
+		ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+		if (ret)
+			return ret;
+		presc = FIELD_GET(STM32_LPTIM_PRESC, cfgr);
+		rate = clk_get_rate(priv->clk) >> presc;
+		if (!rate)
+			return -EINVAL;
+		delay_us = 3 * DIV_ROUND_UP(USEC_PER_SEC, rate);
+		usleep_range(delay_us, delay_us * 2);
+	}
+
+	return regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1, mask, val);
+}
+
 static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			      const struct pwm_state *state)
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long long prd, div, dty;
 	struct pwm_state cstate;
-	u32 val, mask, cfgr, presc = 0;
+	u32 arr, val, mask, cfgr, presc = 0;
 	bool reenable;
 	int ret;
 
@@ -45,10 +134,28 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	if (!state->enabled) {
 		if (cstate.enabled) {
-			/* Disable LP timer */
-			ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+			/* Disable CC channel if any */
+			ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, false,
+								 state->polarity);
 			if (ret)
 				return ret;
+			ret = regmap_write(priv->regmap, pwm->hwpwm ?
+					   STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, 0);
+			if (ret)
+				return ret;
+
+			/* Check if the timer can be disabled */
+			ret = stm32_pwm_lp_update_allowed(priv, pwm->hwpwm);
+			if (ret < 0)
+				return ret;
+
+			if (ret) {
+				/* Disable LP timer */
+				ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+				if (ret)
+					return ret;
+			}
+
 			/* disable clock to PWM counter */
 			clk_disable(priv->clk);
 		}
@@ -79,6 +186,23 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	dty = prd * state->duty_cycle;
 	do_div(dty, state->period);
 
+	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+	if (ret)
+		return ret;
+
+	/*
+	 * When there are several channels, they share the same prescaler and reload value.
+	 * Check if this can be changed, or the values are the same for all channels.
+	 */
+	if (!stm32_pwm_lp_update_allowed(priv, pwm->hwpwm)) {
+		ret = regmap_read(priv->regmap, STM32_LPTIM_ARR, &arr);
+		if (ret)
+			return ret;
+
+		if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || (arr != prd - 1))
+			return -EBUSY;
+	}
+
 	if (!cstate.enabled) {
 		/* enable clock to drive PWM counter */
 		ret = clk_enable(priv->clk);
@@ -86,15 +210,20 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			return ret;
 	}
 
-	ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
-	if (ret)
-		goto err;
-
 	if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||
-	    (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {
+	    ((FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity) && !priv->num_cc_chans)) {
 		val = FIELD_PREP(STM32_LPTIM_PRESC, presc);
-		val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
-		mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;
+		mask = STM32_LPTIM_PRESC;
+
+		if (!priv->num_cc_chans) {
+			/*
+			 * WAVPOL bit is only available when no capature compare channel is used,
+			 * e.g. on LPTIMER instances that have only one output channel. CCMR1 is
+			 * used otherwise.
+			 */
+			val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
+			mask |= STM32_LPTIM_WAVPOL;
+		}
 
 		/* Must disable LP timer to modify CFGR */
 		reenable = true;
@@ -120,20 +249,27 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (ret)
 		goto err;
 
-	ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));
+	/* Write CMP/CCRx register and ensure it's been properly written */
+	ret = regmap_write(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP,
+			   prd - (1 + dty));
 	if (ret)
 		goto err;
 
-	/* ensure CMP & ARR registers are properly written */
-	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
+	/* ensure ARR and CMP/CCRx registers are properly written */
+	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, pwm->hwpwm ?
+				       (val & STM32_LPTIM_CMP2_ARROK) == STM32_LPTIM_CMP2_ARROK :
 				       (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
 				       100, 1000);
 	if (ret) {
 		dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
 		goto err;
 	}
-	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
-			   STM32_LPTIM_CMPOKCF_ARROKCF);
+	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, pwm->hwpwm ?
+			   STM32_LPTIM_CMP2OKCF_ARROKCF : STM32_LPTIM_CMPOKCF_ARROKCF);
+	if (ret)
+		goto err;
+
+	ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, true, state->polarity);
 	if (ret)
 		goto err;
 
@@ -161,11 +297,22 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 {
 	struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
 	unsigned long rate = clk_get_rate(priv->clk);
-	u32 val, presc, prd;
+	u32 val, presc, prd, ccmr1;
+	bool enabled;
 	u64 tmp;
 
 	regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
-	state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+	if (priv->num_cc_chans) {
+		/* There's a CC chan, need to also check if it's enabled */
+		regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+		if (pwm->hwpwm)
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC2E, ccmr1);
+		else
+			enabled &= !!FIELD_GET(STM32_LPTIM_CC1E, ccmr1);
+	}
+	state->enabled = enabled;
+
 	/* Keep PWM counter clock refcount in sync with PWM initial state */
 	if (state->enabled) {
 		int ret = clk_enable(priv->clk);
@@ -176,14 +323,21 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
 
 	regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);
 	presc = FIELD_GET(STM32_LPTIM_PRESC, val);
-	state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	if (priv->num_cc_chans) {
+		if (pwm->hwpwm)
+			state->polarity = FIELD_GET(STM32_LPTIM_CC2P, ccmr1);
+		else
+			state->polarity = FIELD_GET(STM32_LPTIM_CC1P, ccmr1);
+	} else {
+		state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+	}
 
 	regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);
 	tmp = prd + 1;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
 
-	regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);
+	regmap_read(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, &val);
 	tmp = prd - val;
 	tmp = (tmp << presc) * NSEC_PER_SEC;
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
@@ -201,15 +355,25 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
 	struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
 	struct stm32_pwm_lp *priv;
 	struct pwm_chip *chip;
+	unsigned int npwm;
 	int ret;
 
-	chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+	if (!ddata->num_cc_chans) {
+		/* No dedicated CC channel, so there's only one PWM channel */
+		npwm = 1;
+	} else {
+		/* There are dedicated CC channels, each with one PWM output */
+		npwm = ddata->num_cc_chans;
+	}
+
+	chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*priv));
 	if (IS_ERR(chip))
 		return PTR_ERR(chip);
 	priv = to_stm32_pwm_lp(chip);
 
 	priv->regmap = ddata->regmap;
 	priv->clk = ddata->clk;
+	priv->num_cc_chans = ddata->num_cc_chans;
 	chip->ops = &stm32_pwm_lp_ops;
 
 	ret = devm_pwmchip_add(&pdev->dev, chip);
@@ -225,12 +389,15 @@ static int stm32_pwm_lp_suspend(struct device *dev)
 {
 	struct pwm_chip *chip = dev_get_drvdata(dev);
 	struct pwm_state state;
-
-	pwm_get_state(&chip->pwms[0], &state);
-	if (state.enabled) {
-		dev_err(dev, "The consumer didn't stop us (%s)\n",
-			chip->pwms[0].label);
-		return -EBUSY;
+	unsigned int i;
+
+	for (i = 0; i < chip->npwm; i++) {
+		pwm_get_state(&chip->pwms[i], &state);
+		if (state.enabled) {
+			dev_err(dev, "The consumer didn't stop us (%s)\n",
+				chip->pwms[i].label);
+			return -EBUSY;
+		}
 	}
 
 	return pinctrl_pm_select_sleep_state(dev);
-- 
2.25.1



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:47 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:47 +0100
Subject: [PATCH v4 4/8] clocksource: stm32-lptimer: add support for stm32mp25
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-5-fabrice.gasnier@foss.st.com>

On stm32mp25, DIER (former IER) must only be modified when the lptimer
is enabled. On earlier SoCs, it must be only be modified when it is
disabled. There's also a new DIEROK flag, to ensure register access
has completed.
Add a new "set_evt" routine to be used on stm32mp25, called depending
on the version register, read by the MFD core (LPTIM_VERR).

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V4:
- Daniel suggests to encapsulate IER write into a separate function
  that manages the enabling/disabling of the LP timer. In addition,
  DIEROK and ARROK flags checks have been added. So adopt a new routine
  to set the event into ARR register and enable the interrupt.
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
  driver. Use version data from MFD core.
- Added interrupt enable register access update in (missed in V1)
---
 drivers/clocksource/timer-stm32-lp.c | 51 +++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index 928da2f6de69..e58932300fb4 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -27,6 +27,7 @@ struct stm32_lp_private {
 	u32 psc;
 	struct device *dev;
 	struct clk *clk;
+	u32 version;
 };
 
 static struct stm32_lp_private*
@@ -47,12 +48,37 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
 	return 0;
 }
 
-static int stm32_clkevent_lp_set_timer(unsigned long evt,
-				       struct clock_event_device *clkevt,
-				       int is_periodic)
+static int stm32mp25_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
 {
-	struct stm32_lp_private *priv = to_priv(clkevt);
+	int ret;
+	u32 val;
+
+	/* Enable LPTIMER to be able to write into IER and ARR registers */
+	regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+	/* set next event counter */
+	regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
+	/* enable ARR interrupt */
+	regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
+
+	/* Poll DIEROK and ARROK to ensure register access has completed */
+	ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val,
+					      (val & STM32_LPTIM_DIEROK_ARROK) ==
+					      STM32_LPTIM_DIEROK_ARROK,
+					      10, 500);
+	if (ret) {
+		dev_err(priv->dev, "access to LPTIM timed out\n");
+		/* Disable LPTIMER */
+		regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+		return ret;
+	}
+	/* Clear DIEROK and ARROK flags */
+	regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF);
+
+	return 0;
+}
 
+static void stm32_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
+{
 	/* disable LPTIMER to be able to write into IER register*/
 	regmap_write(priv->reg, STM32_LPTIM_CR, 0);
 	/* enable ARR interrupt */
@@ -61,6 +87,22 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
 	regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
 	/* set next event counter */
 	regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
+}
+
+static int stm32_clkevent_lp_set_timer(unsigned long evt,
+				       struct clock_event_device *clkevt,
+				       int is_periodic)
+{
+	struct stm32_lp_private *priv = to_priv(clkevt);
+	int ret;
+
+	if (priv->version == STM32_LPTIM_VERR_23) {
+		ret = stm32mp25_clkevent_lp_set_evt(priv, evt);
+		if (ret)
+			return ret;
+	} else {
+		stm32_clkevent_lp_set_evt(priv, evt);
+	}
 
 	/* start counter */
 	if (is_periodic)
@@ -176,6 +218,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	priv->reg = ddata->regmap;
+	priv->version = ddata->version;
 	priv->clk = ddata->clk;
 	ret = clk_prepare_enable(priv->clk);
 	if (ret)
-- 
2.25.1



From linux at roeck-us.net  Fri Mar 14 10:37:17 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 14 Mar 2025 10:37:17 -0700
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
In-Reply-To: <20250314160248.502324-1-arnd@kernel.org>
References: <20250314160248.502324-1-arnd@kernel.org>
Message-ID: <9ff3ba59-be59-4a2e-ac1a-5ce23b1b3fba@roeck-us.net>

On 3/14/25 09:02, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> On 32-bit architectures, the new calculation causes a build failure:
> 
> ld.lld-21: error: undefined symbol: __aeabi_uldivmod
> 
> Since neither value is ever larger than a register, cast both
> sides into a uintptr_t.
> 
> Fixes: 5c03f9f4d362 ("watchdog: aspeed: Update bootstatus handling")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>   drivers/watchdog/aspeed_wdt.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> index 369635b38ca0..837e15701c0e 100644
> --- a/drivers/watchdog/aspeed_wdt.c
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -254,7 +254,7 @@ static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
>   
>   	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
>   		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
> +		idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res);
>   	}
>   
>   	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
Does that help if the pointers are 64-bit on a 32-bit platform (multi_v7_lpae_defconfig) ?

Guenter



From arnd at arndb.de  Fri Mar 14 10:39:25 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 14 Mar 2025 18:39:25 +0100
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
In-Reply-To: <9ff3ba59-be59-4a2e-ac1a-5ce23b1b3fba@roeck-us.net>
References: <20250314160248.502324-1-arnd@kernel.org>
 <9ff3ba59-be59-4a2e-ac1a-5ce23b1b3fba@roeck-us.net>
Message-ID: <71b81647-aa39-4c33-b92f-2c9e6d1e606d@app.fastmail.com>

On Fri, Mar 14, 2025, at 18:37, Guenter Roeck wrote:
> On 3/14/25 09:02, Arnd Bergmann wrote:
>>   
>>   	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
>>   		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
>> +		idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res);
>>   	}
>>   
>>   	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
> Does that help if the pointers are 64-bit on a 32-bit platform 
> (multi_v7_lpae_defconfig) ?

Yes, that is the problem: resource_size() returns a resource_size_t,
so this is a 32-bit by 64-bit division.

Pointers are always 32-bit, CONFIG_LPAE only changes phys_addr_t
and resource_size_t.

     Arnd


From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:52 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:52 -0300
Subject: [PATCH v2 0/6] drm/panfrost: Add support for AARCH64_4K page table format
Message-ID: <20250314173858.212264-1-ariel.dalessandro@collabora.com>

Hi all,

This is a new iteration on Panfrost support for AARCH64_4K page table
format. The main reason behind this patchset is that MediaTek MT8188 SoC
(ARM Mali-G57 MC3 GPU) constantly faults due to the actual Panfrost cache
configuration.

Currently, Panfrost only supports MMU configuration in "LEGACY" (as Bifrost
calls it) mode, a (modified) version of LPAE "Large Physical Address
Extension", which in Linux we've called "mali_lpae".

This patchset adds support for conditionally enabling AARCH64_4K page table
format. To achieve that, a "GPU optional quirks" field was added to
`struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

The patchset only enables the new format on Mediatek MT8188 and MT8192,
which have been tested on a Mediatek Genio 700 EVK (MT8390) and Mediatek
Genio 1200 EVK (MT8395) boards respectively.

Thanks!

Changes in v2:
* Dropped panfrost_mmu_enable/disable unification.
* Rename gpu_configs as gpu_quirks.
* Added error handling on page table not properly aligned.
* Enabled AARCH64_4K format on MediaTek MT8192 as well.
* Minor fixes.

Changes in v1:
* Added "Set IOMMU_CACHE flag" patch.
* Replaced `panfrost_mmu->enable()` function pointer by `cfg` struct
prepared during init time.
* Made mali_lpae/aarch64_4k name more clear.
* Added GPU_CONFIG_AARCH64_4K flag to enable AARCH64_4K page table
  format.
* Enabled AARCH64_4K mode only on mediatek-mt8188.

Ariel D'Alessandro (6):
  drm/panfrost: Set IOMMU_CACHE flag
  drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
  drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost
    models
  drm/panfrost: Add support for AARCH64_4K page table format
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192

 drivers/gpu/drm/panfrost/panfrost_device.h   |  16 ++
 drivers/gpu/drm/panfrost/panfrost_drv.c      |   2 +
 drivers/gpu/drm/panfrost/panfrost_features.h |   3 +
 drivers/gpu/drm/panfrost/panfrost_mmu.c      | 146 +++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h     |  36 +++++
 5 files changed, 190 insertions(+), 13 deletions(-)

-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:53 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:53 -0300
Subject: [PATCH v2 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-2-ariel.dalessandro@collabora.com>

Panfrost does not support uncached mappings, so flag them properly. Also
flag the pages that are mapped as response to a page fault as cached.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index b91019cd5acb1..9e6f198ef5c1b 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 	struct drm_gem_object *obj = &shmem->base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
-	int prot = IOMMU_READ | IOMMU_WRITE;
+	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
 
 	if (WARN_ON(mapping->active))
 		return 0;
@@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
 		goto err_map;
 
 	mmu_map_sg(pfdev, bomapping->mmu, addr,
-		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
 
 	bomapping->active = true;
 	bo->heap_rss_size += SZ_2M;
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:54 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:54 -0300
Subject: [PATCH v2 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-3-ariel.dalessandro@collabora.com>

As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
which makes code easier to read and reuse.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 9e6f198ef5c1b..294f86b3c25e7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
 
 struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
+	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
+	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 
 	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
 		.pgsize_bitmap	= SZ_4K | SZ_2M,
-		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
-		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
+		.ias		= va_bits,
+		.oas		= pa_bits,
 		.coherent_walk	= pfdev->coherent,
 		.tlb		= &mmu_tlb_ops,
 		.iommu_dev	= pfdev->dev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index c7bba476ab3f3..b5f279a19a084 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -16,6 +16,8 @@
 #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
 
 #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
+#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
+#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
 #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
 #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
 
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:55 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:55 -0300
Subject: [PATCH v2 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost models
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-4-ariel.dalessandro@collabora.com>

Set this feature flag on all Mali Bifrost platforms as the MMU supports
AARCH64 4K page table format.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_features.h
+++ b/drivers/gpu/drm/panfrost/panfrost_features.h
@@ -54,6 +54,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g72 (\
@@ -64,6 +65,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g51 hw_features_g72
@@ -77,6 +79,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
 	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g76 (\
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:56 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:56 -0300
Subject: [PATCH v2 4/6] drm/panfrost: Add support for AARCH64_4K page table format
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-5-ariel.dalessandro@collabora.com>

Currently, Panfrost only supports MMU configuration in "LEGACY" (as
Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called "mali_lpae".

This commit adds support for conditionally enabling AARCH64_4K page
table format. To achieve that, a "GPU optional quirks" field was added
to `struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
 drivers/gpu/drm/panfrost/panfrost_mmu.c    | 136 +++++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
 3 files changed, 177 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index cffcb0ac7c111..ad95f2ed31d9a 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
 	GPU_PM_VREG_OFF,
 };
 
+/**
+ * enum panfrost_gpu_quirks - GPU optional quirks
+ * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
+ */
+enum panfrost_gpu_quirks {
+	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
+};
+
 struct panfrost_features {
 	u16 id;
 	u16 revision;
@@ -95,6 +103,9 @@ struct panfrost_compatible {
 
 	/* Allowed PM features */
 	u8 pm_features;
+
+	/* GPU configuration quirks */
+	u8 gpu_quirks;
 };
 
 struct panfrost_device {
@@ -162,6 +173,11 @@ struct panfrost_mmu {
 	int as;
 	atomic_t as_count;
 	struct list_head list;
+	struct {
+		u64 transtab;
+		u64 memattr;
+		u64 transcfg;
+	} cfg;
 };
 
 struct panfrost_engine_usage {
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 294f86b3c25e7..f24c23e1f67b8 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -26,6 +26,48 @@
 #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define mmu_read(dev, reg) readl(dev->iomem + reg)
 
+static u64 mair_to_memattr(u64 mair, bool coherent)
+{
+	u64 memattr = 0;
+	u32 i;
+
+	for (i = 0; i < 8; i++) {
+		u8 in_attr = mair >> (8 * i), out_attr;
+		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
+
+		/* For caching to be enabled, inner and outer caching policy
+		 * have to be both write-back, if one of them is write-through
+		 * or non-cacheable, we just choose non-cacheable. Device
+		 * memory is also translated to non-cacheable.
+		 */
+		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
+				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
+		} else {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
+			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
+			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
+			 * to Mali's internal-shareable mode. As per the Mali
+			 * Spec, inner and outer-shareable modes aren't allowed
+			 * for WB memory when coherency is disabled.
+			 * Use SH_CPU_INNER mode when coherency is enabled, so
+			 * that SH_IS actually maps to the standard definition of
+			 * inner-shareable.
+			 */
+			if (!coherent)
+				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
+			else
+				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
+		}
+
+		memattr |= (u64)out_attr << (8 * i);
+	}
+
+	return memattr;
+}
+
 static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
 {
 	int ret;
@@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
+	u64 transtab = mmu->cfg.transtab;
+	u64 memattr = mmu->cfg.memattr;
+	u64 transcfg = mmu->cfg.transcfg;
 
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
@@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
@@ -152,9 +197,66 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
+static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	/* TODO: The following fields are duplicated between the MMU and Page
+	 * Table config structs. Ideally, should be kept in one place.
+	 */
+	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
+	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
+	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
+
+	return 0;
+}
+
+static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
+				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
+		return -EINVAL;
+
+	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+
+	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
+					   pgtbl_cfg->coherent_walk);
+
+	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
+			    AS_TRANSCFG_PTW_RA |
+			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
+			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
+	if (pgtbl_cfg->coherent_walk)
+		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
+
+	return 0;
+}
+
+static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
+				  enum io_pgtable_fmt fmt)
+{
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		return mmu_cfg_init_aarch64_4k(mmu);
+	case ARM_MALI_LPAE:
+		return mmu_cfg_init_mali_lpae(mmu);
+	default:
+		/* This should never happen */
+		return drm_WARN_ON(pfdev->ddev, -EINVAL);
+	}
+}
+
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as;
@@ -618,6 +720,18 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
 	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
+	enum io_pgtable_fmt fmt;
+
+	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
+		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
+			dev_err_once(pfdev->dev,
+				     "AARCH64_4K page table not supported\n");
+			return ERR_PTR(-EINVAL);
+		}
+		fmt = ARM_64_LPAE_S1;
+	} else {
+		fmt = ARM_MALI_LPAE;
+	}
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
 	if (!mmu)
@@ -642,16 +756,20 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 		.iommu_dev	= pfdev->dev,
 	};
 
-	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
-					      mmu);
-	if (!mmu->pgtbl_ops) {
-		kfree(mmu);
-		return ERR_PTR(-EINVAL);
-	}
+	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
+	if (!mmu->pgtbl_ops)
+		goto err_free_mmu;
+
+	if (panfrost_mmu_cfg_init(mmu, fmt))
+		goto err_free_mmu;
 
 	kref_init(&mmu->refcount);
 
 	return mmu;
+
+err_free_mmu:
+	kfree(mmu);
+	return ERR_PTR(-EINVAL);
 }
 
 static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index b5f279a19a084..2b8f1617b8369 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -301,6 +301,17 @@
 #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
 #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
+							 ((w) ? BIT(0) : 0) | \
+							 ((r) ? BIT(1) : 0))
+#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
+#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
+#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
 #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
 #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
 #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
@@ -311,6 +322,24 @@
 /* Additional Bifrost AS registers */
 #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
 #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
+#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
+#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
+#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
+#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
+#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
+#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
+#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
+#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
+#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
+#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
+#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
+#define   AS_TRANSCFG_PTW_RA				BIT(30)
+#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
+#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
+#define   AS_TRANSCFG_WXN				BIT(35)
+#define   AS_TRANSCFG_XREADABLE				BIT(36)
 #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
@@ -326,6 +355,11 @@
 #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
 #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
 
+/*
+ * Begin AARCH64_4K MMU TRANSTAB register values
+ */
+#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
+
 #define AS_STATUS_AS_ACTIVE			0x01
 
 #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:57 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:57 -0300
Subject: [PATCH v2 5/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-6-ariel.dalessandro@collabora.com>

MediaTek MT8188 SoC has an ARM Mali-G57 MC3 GPU (Valhall-JM), which
constantly faults with the current panfrost support.

For instance, running `glmark2-es2-drm` benchmark test:
```
[   79.617461] panfrost 13000000.gpu: js fault, js=1, status=JOB_BUS_FAULT, head=0xaadc380, tail=0xaadc380
[   80.119811] panfrost 13000000.gpu: gpu sched timeout, js=0, config=0x7300, status=0x58, head=0xaaca180, tail=0xaaca180, sched_job=000000002fd03ccc
[   80.129083] panfrost 13000000.gpu: Unhandled Page fault in AS0 at VA 0x0000000000000000
[   80.129083] Reason: TODO
[   80.129083] raw fault status: 0x1C2
[   80.129083] decoded fault status: SLAVE FAULT
[   80.129083] exception type 0xC2: TRANSLATION_FAULT_2
[   80.129083] access type 0x1: EXECUTE
[   80.129083] source id 0x0
```

Note that current panfrost mode (Mali LPAE - LEGACY) only allows to
specify write-cache or implementation-defined as the caching policy,
probably not matching the right configuration. As depicted in the source
code:

drivers/iommu/io-pgtable-arm.c:
```
* MEMATTR: Mali has no actual notion of a non-cacheable type, so the
* best we can do is mimic the out-of-tree driver and hope that the
* "implementation-defined caching policy" is good enough...
```

Now that Panfrost supports AARCH64_4K page table format, let's enable it
on Mediatek MT8188 and configure the cache/shareability policies
properly.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 0f3935556ac76..e854f290858f9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
 	.pm_domain_names = mediatek_mt8183_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
-- 
2.47.2



From ariel.dalessandro at collabora.com  Fri Mar 14 10:38:58 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Fri, 14 Mar 2025 14:38:58 -0300
Subject: [PATCH v2 6/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192
In-Reply-To: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
Message-ID: <20250314173858.212264-7-ariel.dalessandro@collabora.com>

MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
Panfrost supports AARCH64_4K page table format, let's enable it on this
SoC.

Running glmark2-es2-drm [0] benchmark, reported the same performance
score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.

[0] https://github.com/glmark2/glmark2

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index e854f290858f9..ef30d314b2281 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -836,6 +836,7 @@ static const struct panfrost_compatible mediatek_mt8192_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains),
 	.pm_domain_names = mediatek_mt8192_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const struct of_device_id dt_match[] = {
-- 
2.47.2



From namhyung at kernel.org  Fri Mar 14 10:43:40 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Fri, 14 Mar 2025 10:43:40 -0700
Subject: [PATCH] perf script: Fix typo in branch event mask
In-Reply-To: <20250312075636.429127-1-yujie.liu@intel.com>
References: <20250312075636.429127-1-yujie.liu@intel.com>
Message-ID: <174197422088.4059945.167819241578952524.b4-ty@kernel.org>

On Wed, 12 Mar 2025 15:56:36 +0800, Yujie Liu wrote:
> BRACH -> BRANCH
> 
> 
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From catalin.marinas at arm.com  Fri Mar 14 10:52:04 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 17:52:04 +0000
Subject: [bug report] arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT
 in [pmd|pud]_mkhuge()
In-Reply-To: <d7902504-1ed4-452f-9b08-148f6b8b69fd@stanley.mountain>
References: <d7902504-1ed4-452f-9b08-148f6b8b69fd@stanley.mountain>
Message-ID: <Z9RsxL98s23mvqJa@arm.com>

On Fri, Mar 14, 2025 at 01:54:01PM +0300, Dan Carpenter wrote:
> Hello Anshuman Khandual,
> 
> Commit 1601df9e366e ("arm64/mm: Clear PXX_TYPE_MASK and set
> PXD_TYPE_SECT in [pmd|pud]_mkhuge()") from Feb 21, 2025 (linux-next),
> leads to the following (unpublished) Smatch static checker warning:
> 
> arch/arm64/include/asm/pgtable.h:587 pmd_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'
> arch/arm64/include/asm/pgtable.h:626 pud_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'
> 
> arch/arm64/include/asm/pgtable.h
>     579 static inline pmd_t pmd_mkhuge(pmd_t pmd)
>     580 {
>     581         /*
>     582          * It's possible that the pmd is present-invalid on entry
>     583          * and in that case it needs to remain present-invalid on
>     584          * exit. So ensure the VALID bit does not get modified.
>     585          */
>     586         pmdval_t mask = PMD_TYPE_MASK & ~PTE_VALID;
> --> 587         pmdval_t val = PMD_TYPE_SECT & ~PTE_VALID;
> 
> This is "1 & ~1".  I see the comment, but I'm too stupid to know even
> after reading he comment whether it's intentional or not.  :P
> 
>     588 
>     589         return __pmd((pmd_val(pmd) & ~mask) | val);
>     590 }

Prior to the above commit, the code was:

#define pmd_mkhuge(pmd)			(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))

So just clearing a bit. That's why the reworked code has val 0 in the
current configuration. This may change with support for 128-bit PTEs
though, different format.

The comment is about preserving the PTE_VALID bit in the original pmd
value, so it's masked out of both mask and val.

It's good that smatch catches these though. Any way to mark a false
positive?

-- 
Catalin


From linux at roeck-us.net  Fri Mar 14 10:54:32 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 14 Mar 2025 10:54:32 -0700
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
In-Reply-To: <71b81647-aa39-4c33-b92f-2c9e6d1e606d@app.fastmail.com>
References: <20250314160248.502324-1-arnd@kernel.org>
 <9ff3ba59-be59-4a2e-ac1a-5ce23b1b3fba@roeck-us.net>
 <71b81647-aa39-4c33-b92f-2c9e6d1e606d@app.fastmail.com>
Message-ID: <32e3fd04-d44a-4923-8323-02c53e8dbe82@roeck-us.net>

On 3/14/25 10:39, Arnd Bergmann wrote:
> On Fri, Mar 14, 2025, at 18:37, Guenter Roeck wrote:
>> On 3/14/25 09:02, Arnd Bergmann wrote:
>>>    
>>>    	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
>>>    		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> -		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
>>> +		idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res);
>>>    	}
>>>    
>>>    	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
>> Does that help if the pointers are 64-bit on a 32-bit platform
>> (multi_v7_lpae_defconfig) ?
> 
> Yes, that is the problem: resource_size() returns a resource_size_t,
> so this is a 32-bit by 64-bit division.
> 
> Pointers are always 32-bit, CONFIG_LPAE only changes phys_addr_t
> and resource_size_t.
> 
Ok. Thanks for the clarification.

Guenter




From linux at roeck-us.net  Fri Mar 14 10:55:05 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 14 Mar 2025 10:55:05 -0700
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
In-Reply-To: <20250314160248.502324-1-arnd@kernel.org>
References: <20250314160248.502324-1-arnd@kernel.org>
Message-ID: <e53b32db-7059-4167-992e-d461a996b122@roeck-us.net>

On 3/14/25 09:02, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> On 32-bit architectures, the new calculation causes a build failure:
> 
> ld.lld-21: error: undefined symbol: __aeabi_uldivmod
> 
> Since neither value is ever larger than a register, cast both
> sides into a uintptr_t.
> 
> Fixes: 5c03f9f4d362 ("watchdog: aspeed: Update bootstatus handling")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Reviewed-by: Guenter Roeck <linux at roeck-us.net>

> ---
>   drivers/watchdog/aspeed_wdt.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> index 369635b38ca0..837e15701c0e 100644
> --- a/drivers/watchdog/aspeed_wdt.c
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -254,7 +254,7 @@ static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
>   
>   	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
>   		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
> +		idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res);
>   	}
>   
>   	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);



From mripard at kernel.org  Fri Mar 14 10:58:48 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 17:58:48 +0000
Subject: [PATCH v7 01/11] drm/bridge: add devm_drm_bridge_alloc()
In-Reply-To: <20250314-drm-bridge-refcount-v7-1-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-1-152571f8c694@bootlin.com>
Message-ID: <ab48cc194d9fc1f5d3fc7846abbf4cce@kernel.org>

On Fri, 14 Mar 2025 11:31:14 +0100, Luca Ceresoli wrote:
> Add a macro to allocate and initialize a DRM bridge embedded within a
> private driver struct.
> 
> Compared to current practice, which is based on [devm_]kzalloc() allocation
> followed by open-coded initialization of fields, this allows to have a
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From rmk+kernel at armlinux.org.uk  Fri Mar 14 11:02:39 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 14 Mar 2025 18:02:39 +0000
Subject: [PATCH net-next] net: stmmac: remove redundant racy tear-down in
 stmmac_dvr_remove()
Message-ID: <E1tt9Ml-006xIA-EF@rmk-PC.armlinux.org.uk>

While the network device is registered, it is published to userspace,
and thus userspace can change its state. This means calling
functions such as stmmac_stop_all_dma() and stmmac_mac_set() are
racy.

Moreover, unregister_netdev() will unpublish the network device, and
then if appropriate call the .ndo_stop() method, which is
stmmac_release(). This will first call phylink_stop() which will
synchronously take the link down, resulting in stmmac_mac_link_down()
and stmmac_mac_set(, false) being called.

stmmac_release() will also call stmmac_stop_all_dma().

Consequently, neither of these two functions need to called prior
to unregister_netdev() as that will safely call paths that will
result in this work being done if necessary.

Remove these redundant racy calls.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Furong Xu <0x1207 at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fa1d7d3a2f43..c2ee6c0af3fd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7768,8 +7768,6 @@ void stmmac_dvr_remove(struct device *dev)
 
 	pm_runtime_get_sync(dev);
 
-	stmmac_stop_all_dma(priv);
-	stmmac_mac_set(priv, priv->ioaddr, false);
 	unregister_netdev(ndev);
 
 #ifdef CONFIG_DEBUG_FS
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Fri Mar 14 11:02:44 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 14 Mar 2025 18:02:44 +0000
Subject: [PATCH net-next] net: stmmac: remove unnecessary stmmac_mac_set() in
 stmmac_release()
Message-ID: <E1tt9Mq-006xIG-IC@rmk-PC.armlinux.org.uk>

stmmac_release() calls phylink_stop() and then goes on to call
stmmac_mac_set(, false). However, phylink_stop() will call
stmmac_mac_link_down() before returning, which will do this work.
Remove this unnecessary call.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Tested-by: Furong Xu <0x1207 at gmail.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c2ee6c0af3fd..839ecebf5f5f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -4129,9 +4129,6 @@ static int stmmac_release(struct net_device *dev)
 	/* Release and free the Rx/Tx resources */
 	free_dma_desc_resources(priv, &priv->dma_conf);
 
-	/* Disable the MAC Rx/Tx */
-	stmmac_mac_set(priv, priv->ioaddr, false);
-
 	/* Powerdown Serdes if there is */
 	if (priv->plat->serdes_powerdown)
 		priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
-- 
2.30.2



From mripard at kernel.org  Fri Mar 14 11:04:40 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 19:04:40 +0100
Subject: [PATCH v7 02/11] drm/bridge: add support for refcounting
In-Reply-To: <20250314-drm-bridge-refcount-v7-2-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-drm-bridge-refcount-v7-2-152571f8c694@bootlin.com>
Message-ID: <20250314-amorphous-congenial-woodlouse-f50bde@houat>

On Fri, Mar 14, 2025 at 11:31:15AM +0100, Luca Ceresoli wrote:
> DRM bridges are currently considered as a fixed element of a DRM card, and
> thus their lifetime is assumed to extend for as long as the card
> exists. New use cases, such as hot-pluggable hardware with video bridges,
> require DRM bridges to be added to and removed from a DRM card without
> tearing the card down. This is possible for connectors already (used by DP
> MST), it is now needed for DRM bridges as well.
> 
> As a first preliminary step, make bridges reference-counted to allow a
> struct drm_bridge (along with the private driver structure embedding it) to
> stay allocated even after the driver has been removed, until the last
> reference is put.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> ---
> 
> Changes in v7:
>  - export drm_bridge_put_void
>  - struct drm_bridge: use container pointer instead of container_offset
>  - remove drm_bridge_is_refcounted()
>  - remove all DRM_DEBUG()s
>  - drm_bridge_get/put: accept NULL pointer and return the bridge pointer to
>    allow pass-through calls
>  - extract to separate patches:
>     - the addition of drm_bridge_alloc
>     - the addition of drm_bridge_get/put() to drm_bridge_add/remove()
>     - the addition of drm_bridge_get/put() to drm_bridge_attach/detach()
>  - fix a typo, slightly improve kerneldoc
> 
> Changes in v6:
>  - use drm_warn, not WARN_ON (Jani Nikula)
>  - Add devm_drm_bridge_alloc() to replace drm_bridge_init() (similar to
>    drmm_encoder_alloc)
>  - Remove .destroy func: deallocation is done via the struct offset
>    computed by the devm_drm_bridge_alloc() macro
>  - use fixed free callback, as the same callback is used in all cases
>    anyway (remove free_cb, add bool is_refcounted)
>  - add drm_bridge_get/put() to drm_bridge_attach/detach() (add the bridge
>    to a list)
>  - make some DRM_DEBUG() strings more informative
> 
> This patch was added in v5.
> ---
>  drivers/gpu/drm/drm_bridge.c | 33 +++++++++++++++-
>  include/drm/drm_bridge.h     | 91 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 123 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 96df717b2caeb41d45346ded576eaeb2806fd051..2ba0dac9bfc2dfd709d5e2457d69067c7324972c 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -199,23 +199,54 @@
>  static DEFINE_MUTEX(bridge_lock);
>  static LIST_HEAD(bridge_list);
>  
> +void __drm_bridge_free(struct kref *kref)
> +{
> +	struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
> +
> +	kfree(bridge->container);
> +}
> +EXPORT_SYMBOL(__drm_bridge_free);
> +
> +/**
> + * drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
> + *
> + * @data: pointer to @struct drm_bridge, cast to a void pointer
> + *
> + * Wrapper of drm_bridge_put() to be used when a function taking a void
> + * pointer is needed, for example as a devm action.
> + */
> +void drm_bridge_put_void(void *data)
> +{
> +	struct drm_bridge *bridge = (struct drm_bridge *)data;
> +
> +	drm_bridge_put(bridge);
> +}
> +EXPORT_SYMBOL(drm_bridge_put_void);
> +
>  void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
>  			      const struct drm_bridge_funcs *funcs)
>  {
>  	void *container;
>  	struct drm_bridge *bridge;
> +	int err;
>  
>  	if (!funcs) {
>  		dev_warn(dev, "Missing funcs pointer\n");
>  		return ERR_PTR(-EINVAL);
>  	}
>  
> -	container = devm_kzalloc(dev, size, GFP_KERNEL);
> +	container = kzalloc(size, GFP_KERNEL);
>  	if (!container)
>  		return ERR_PTR(-ENOMEM);
>  
>  	bridge = container + offset;
> +	bridge->container = container;
>  	bridge->funcs = funcs;
> +	kref_init(&bridge->refcount);
> +
> +	err = devm_add_action_or_reset(dev, drm_bridge_put_void, bridge);
> +	if (err)
> +		return ERR_PTR(err);
>  
>  	return container;
>  }
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index dae463b30542d586a595b67f7bdf5a5e898e9572..5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -840,6 +840,17 @@ struct drm_bridge {
>  	const struct drm_bridge_timings *timings;
>  	/** @funcs: control functions */
>  	const struct drm_bridge_funcs *funcs;
> +
> +	/**
> +	 * @container: Pointer to the private driver struct embedding this
> +	 * @struct drm_bridge.
> +	 */
> +	void *container;

newline here

> +	/**
> +	 * @refcount: reference count of users referencing this bridge.
> +	 */
> +	struct kref refcount;
> +
>  	/** @driver_private: pointer to the bridge driver's internal context */
>  	void *driver_private;
>  	/** @ops: bitmask of operations supported by the bridge */
> @@ -941,6 +952,82 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
>  	return container_of(priv, struct drm_bridge, base);
>  }
>  
> +void __drm_bridge_free(struct kref *kref);
> +
> +/**
> + * drm_bridge_get - Acquire a bridge reference
> + * @bridge: DRM bridge
> + *
> + * This function increments the bridge's refcount.
> + *
> + * Returns:
> + * Pointer to @bridge.
> + */
> +static inline struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge)
> +{
> +	if (!bridge)
> +		return bridge;
> +
> +	kref_get(&bridge->refcount);
> +
> +	return bridge;
> +}
> +
> +/**
> + * drm_bridge_put - Release a bridge reference
> + * @bridge: DRM bridge
> + *
> + * This function decrements the bridge's reference count and frees the
> + * object if the reference count drops to zero.
> + *
> + * See also drm_bridge_put_and_clear() which is more handy in many cases.
> + *
> + * Returns:
> + * Pointer to @bridge.
> + */
> +static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
> +{
> +	if (!bridge)
> +		return bridge;
> +
> +	kref_put(&bridge->refcount, __drm_bridge_free);
> +
> +	return bridge;
> +}

I'm not sure we discussed it already, but why do you need to put both
drm_bridge_get and drm_bridge_put into the header, and thus export
__drm_bridge_free?

I'd expect both to be in drm_bridge.c?

> +
> +void drm_bridge_put_void(void *data);
> +
> +/**
> + * drm_bridge_put_and_clear - Given a bridge pointer, clear the pointer
> + *                            then put the bridge
> + *
> + * @bridge_pp: pointer to pointer to a struct drm_bridge
> + *
> + * Helper to put a DRM bridge (whose pointer is passed), but only after
> + * setting its pointer to NULL. Useful for drivers having struct drm_bridge
> + * pointers they need to dispose of, without leaving a use-after-free
> + * window where the pointed bridge might have been freed while still
> + * holding a pointer to it.
> + *
> + * For example a driver having this private struct::
> + *
> + *     struct my_bridge {
> + *         struct drm_bridge *remote_bridge;
> + *         ...
> + *     };
> + *
> + * can dispose of remote_bridge using::
> + *
> + *     drm_bridge_put_and_clear(&my_bridge->remote_bridge);
> + */
> +static inline void drm_bridge_put_and_clear(struct drm_bridge **bridge_pp)
> +{
> +	struct drm_bridge *bridge = *bridge_pp;
> +
> +	*bridge_pp = NULL;
> +	drm_bridge_put(bridge);
> +}

I'm not convinced we need that one for now, and it doesn't look like
there's a user for it in your series, so I'd rather introduce it once we
actually need it.

>  void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
>  			      const struct drm_bridge_funcs *funcs);
>  
> @@ -951,6 +1038,10 @@ void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
>   * @member: the name of the &drm_bridge within @type
>   * @funcs: callbacks for this bridge
>   *
> + * The returned refcount is initialized to 1.

I'm confused, there's no returned refcount here? Or did you mean the
returned bridge refcount?

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/677aba80/attachment.sig>

From mripard at kernel.org  Fri Mar 14 11:04:54 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:04:54 +0000
Subject: [PATCH v7 03/11] drm/bridge: get/put the bridge reference in
 drm_bridge_add/remove()
In-Reply-To: <20250314-drm-bridge-refcount-v7-3-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-3-152571f8c694@bootlin.com>
Message-ID: <4199151804db21307707fc7e023d10d7@kernel.org>

On Fri, 14 Mar 2025 11:31:16 +0100, Luca Ceresoli wrote:
> drm_bridge_add() adds the bridge to the global bridge_list, so take a
> reference for that. Vice versa in drm_bridge_remove().
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:05:30 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:05:30 +0000
Subject: [PATCH v7 04/11] drm/bridge: get/put the bridge reference in
 drm_bridge_attach/detach()
In-Reply-To: <20250314-drm-bridge-refcount-v7-4-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-4-152571f8c694@bootlin.com>
Message-ID: <50d94c0223e60881c014bddd55382692@kernel.org>

On Fri, 14 Mar 2025 11:31:17 +0100, Luca Ceresoli wrote:
> drm_bridge_attach() adds the bridge to the encoder chain, so take a
> reference for that. Vice versa in drm_bridge_detach().
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:08:22 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 19:08:22 +0100
Subject: [PATCH v7 05/11] drm/bridge: add a cleanup action for
 scope-based drm_bridge_put() invocation
In-Reply-To: <20250314-drm-bridge-refcount-v7-5-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-drm-bridge-refcount-v7-5-152571f8c694@bootlin.com>
Message-ID: <20250314-banana-toucanet-of-masquerade-8eeb4e@houat>

On Fri, Mar 14, 2025 at 11:31:18AM +0100, Luca Ceresoli wrote:
> Many functions get a drm_bridge pointer, only use it in the function body
> (or a smaller scope such as a loop body), and don't store it. In these
> cases they always need to drm_bridge_put() it before returning (or exiting
> the scope).
> 
> Some of those functions have complex code paths with multiple return points
> or loop break/continue. This makes adding drm_bridge_put() in the right
> places tricky, ugly and error prone in case of future code changes.
> 
> Others use the bridge pointer in the return statement and would need to
> split the return line to fit the drm_bridge_put, which is a bit annoying:
> 
>   -return some_thing(bridge);
>   +ret = some_thing(bridge);
>   +drm_bridge_put(bridge);
>   +return ret;
> 
> To make it easier for all of them to put the bridge reference correctly
> without complicating code, define a scope-based cleanup action to be used
> with __free().
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> ---
> 
> This patch was added in v7.
> ---
>  include/drm/drm_bridge.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47..a5accd64c364ebb57903ae1e7459034ad9ebf4f3 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -23,6 +23,7 @@
>  #ifndef __DRM_BRIDGE_H__
>  #define __DRM_BRIDGE_H__
>  
> +#include <linux/cleanup.h>
>  #include <linux/ctype.h>
>  #include <linux/list.h>
>  #include <linux/mutex.h>
> @@ -995,6 +996,9 @@ static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
>  	return bridge;
>  }
>  
> +/* Cleanup action for use with __free() */
> +DEFINE_FREE(drm_bridge_put, struct drm_bridge *, if (_T) drm_bridge_put(_T))
> +

IIRC, drm_bridge_put already checks for the pointer being null before
dereferencing it, right? Then we can probably simplify the macro here.

Either way,

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/d456ed06/attachment.sig>

From mripard at kernel.org  Fri Mar 14 11:10:41 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 19:10:41 +0100
Subject: [PATCH v7 06/11] drm/bridge: get the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-6-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-drm-bridge-refcount-v7-6-152571f8c694@bootlin.com>
Message-ID: <20250314-aspiring-myrtle-husky-a5f4ac@houat>

On Fri, Mar 14, 2025 at 11:31:19AM +0100, Luca Ceresoli wrote:
> drm_bridge_chain_get_first_bridge() returns a bridge pointer that the
> caller could hold for a long time. Increment the refcount of the returned
> bridge and document it must be put by the caller.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> ---
> 
> This patch was added in v7.
> ---
>  include/drm/drm_bridge.h | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index a5accd64c364ebb57903ae1e7459034ad9ebf4f3..d9777d5f2e9ef006f0062e4507bce99df4146cd9 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -1105,6 +1105,9 @@ drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
>   * drm_bridge_chain_get_first_bridge() - Get the first bridge in the chain
>   * @encoder: encoder object
>   *
> + * The refcount of the returned bridge is incremented. Use drm_bridge_put()
> + * when done with it.
> + *
>   * RETURNS:
>   * the first bridge in the chain, or NULL if @encoder has no bridge attached
>   * to it.
> @@ -1112,8 +1115,8 @@ drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
>  static inline struct drm_bridge *
>  drm_bridge_chain_get_first_bridge(struct drm_encoder *encoder)
>  {
> -	return list_first_entry_or_null(&encoder->bridge_chain,
> -					struct drm_bridge, chain_node);
> +	return drm_bridge_get(list_first_entry_or_null(&encoder->bridge_chain,
> +						       struct drm_bridge, chain_node));
>  }

We'll need to modify drm_bridge_get_next_bridge, drm_bridge_get_prev_bridge, and
drm_for_each_bridge_in_chain in a similar manner, but for this one

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/6053d810/attachment.sig>

From mripard at kernel.org  Fri Mar 14 11:11:51 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:11:51 +0000
Subject: [PATCH v7 07/11] drm/mxsfb: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-7-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-7-152571f8c694@bootlin.com>
Message-ID: <0cc45a0aae50ab25262691c7145082e1@kernel.org>

On Fri, 14 Mar 2025 11:31:20 +0100, Luca Ceresoli wrote:
> The bridge returned by drm_bridge_chain_get_first_bridge() is
> refcounted. Put it when done. Use a scope-based free action to catch all
> the code paths.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:12:12 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:12:12 +0000
Subject: [PATCH v7 08/11] drm/atomic-helper: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-8-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-8-152571f8c694@bootlin.com>
Message-ID: <1da3c1ee7b8c39e200437ac622238221@kernel.org>

On Fri, 14 Mar 2025 11:31:21 +0100, Luca Ceresoli wrote:
> The bridge returned by drm_bridge_chain_get_first_bridge() is
> refcounted. Put it when done.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:12:56 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:12:56 +0000
Subject: [PATCH v7 09/11] drm/probe-helper: put the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-drm-bridge-refcount-v7-9-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-9-152571f8c694@bootlin.com>
Message-ID: <0cea0c073dfc52c20f583d64b51d7951@kernel.org>

On Fri, 14 Mar 2025 11:31:22 +0100, Luca Ceresoli wrote:
> The bridge returned by drm_bridge_chain_get_first_bridge() is
> refcounted. Put it when done.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:17:17 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:17:17 +0000
Subject: [PATCH v7 10/11] drm/bridge: ti-sn65dsi83: use dynamic lifetime
 management
In-Reply-To: <20250314-drm-bridge-refcount-v7-10-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-10-152571f8c694@bootlin.com>
Message-ID: <028ca14a547f52456a10529508cb0207@kernel.org>

On Fri, 14 Mar 2025 11:31:23 +0100, Luca Ceresoli wrote:
> Allow this bridge to be removable without dangling pointers and
> use-after-free, together with proper use of drm_bridge_get() and _put() by
> consumers.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From mripard at kernel.org  Fri Mar 14 11:18:15 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 18:18:15 +0000
Subject: [PATCH v7 11/11] drm/bridge: samsung-dsim: use dynamic lifetime
 management
In-Reply-To: <20250314-drm-bridge-refcount-v7-11-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-11-152571f8c694@bootlin.com>
Message-ID: <6d7ef2d51bc98436fcfc7fa9076514ec@kernel.org>

On Fri, 14 Mar 2025 11:31:24 +0100, Luca Ceresoli wrote:
> Allow this bridge to be removable without dangling pointers and
> use-after-free, together with proper use of drm_bridge_get() and _put() by
> consumers.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From suzuki.poulose at arm.com  Fri Mar 14 10:33:04 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 14 Mar 2025 17:33:04 +0000
Subject: [PATCH v1 3/4] coresight: ctcu: Enable byte-cntr for TMC ETR
 devices
In-Reply-To: <2eb8a3fd-0366-4873-8536-644ce3684251@quicinc.com>
References: <20250310090407.2069489-1-quic_jiegan@quicinc.com>
 <20250310090407.2069489-4-quic_jiegan@quicinc.com>
 <7a65353d-aa18-4c63-abb9-46344de35fc4@arm.com>
 <2eb8a3fd-0366-4873-8536-644ce3684251@quicinc.com>
Message-ID: <4de623e7-0404-46aa-ad39-65615b8ac79d@arm.com>

On 14/03/2025 01:59, Jie Gan wrote:
> 
> 
> On 3/14/2025 12:24 AM, Suzuki K Poulose wrote:
>> On 10/03/2025 09:04, Jie Gan wrote:
>>> The byte-cntr function provided by the CTCU device is used to 
>>> transfer data
>>> from the ETR buffer to the userspace. An interrupt is triggered if 
>>> the data
>>
>> Why do we need a new device to transfer the data to userspace ?
> 
> Hi Suzuki Mike,
> 
> The purpose of the byte-cntr is for live debugging, allowing trace data 
> to be read while the ETR is running and preventing the required trace 
> data from being overwritten before output.
> 
> I realized that I forgot to introduce the function of the BYTECNTRCTL 
> register.
> 
> There is a big concern that reading the etr_buf while the ETR is running 
> is unsafe because the etr_buf is not synced, am right?

Unsafe to read the buffer, written to by the ETR.

> 
> As I mentioned, we need program a value to the BYTECNTRCTL register. The 
> hardware will count the bytes of the trace data that are routed to 
> RAM(etr_buf).
> 
> The interrupt will be trigger once the counted bytes exceed the 
> programmed value. Based on this concept, we can confirm this part of 
> trace data is already in the etr_buf and is safe to read. So, it's safe 
> for the read function only read this part of trace data in one 
> shot(unlike tmc_read, the whole synced etr_buf).

Since the ETR is used in CIRCULAR buffer mode, what is the guarantee
that it is not overwritten while you are reading ?

> 
> That's how we expect the byte-cntr to work when reading the trace data 
> from the etr_buf while the etr is running.

We understood the functionality of byte-counter, but we think :

1. What you are doing is not safe. ETR can overwrite while you may be 
reading.
2. Adding another "character" file to expose the "same" data.

What we would like to see :

1. Solve the problem of ETR writing into the etr_buf, while you are
copying it. This could be via:

a. Stop the ETR while you are copying the buffer
  OR
b. Split the "buffer" available for ETR to two or more parts, limiting
    the ETR to only allowing writing to one part. On interrupt, disable
    the interrupt, and modify the ETR to use the next part. Now you can
    safely expose the "finished" part to the user.

2. Don't add another file. Use the existing one.

> 
> This also explains why we need a separate dev node to manage the read 
> function for byte-cntr.

No, you don't.


Suzuki


> 
> Thanks,
> Jie
> 
> 
>>
>>> size exceeds the threshold set in the BYTECNTRVAL register. The 
>>> interrupt
>>> handler counts the number of triggered interruptions and the read 
>>> function
>>> will read the data from the ETR buffer if the IRQ count is greater 
>>> than 0.
>>> Each successful read process will decrement the IRQ count by 1.
>>
>> Having an interrupt is good, but see below.
>>
>>>
>>> Signed-off-by: Jie Gan <quic_jiegan at quicinc.com>
>>> ---
>>> ? drivers/hwtracing/coresight/Makefile????????? |?? 2 +-
>>> ? .../coresight/coresight-ctcu-byte-cntr.c????? | 339 ++++++++++++++++++
>>> ? .../hwtracing/coresight/coresight-ctcu-core.c |? 96 ++++-
>>> ? drivers/hwtracing/coresight/coresight-ctcu.h? |? 59 ++-
>>> ? .../hwtracing/coresight/coresight-tmc-etr.c?? |?? 5 +-
>>> ? drivers/hwtracing/coresight/coresight-tmc.h?? |?? 2 +
>>> ? 6 files changed, 493 insertions(+), 10 deletions(-)
>>> ? create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte- 
>>> cntr.c
>>>
>>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/ 
>>> hwtracing/ coresight/Makefile
>>> index 8e62c3150aeb..c90a06768a18 100644
>>> --- a/drivers/hwtracing/coresight/Makefile
>>> +++ b/drivers/hwtracing/coresight/Makefile
>>> @@ -52,4 +52,4 @@ coresight-cti-y := coresight-cti-core.o coresight- 
>>> cti-platform.o \
>>> ? obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>>> ? obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>>> ? obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>>> -coresight-ctcu-y := coresight-ctcu-core.o
>>> +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o
>>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c 
>>> b/ drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>>> new file mode 100644
>>> index 000000000000..0d16385663f5
>>> --- /dev/null
>>> +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
>>> @@ -0,0 +1,339 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights 
>>> reserved.
>>> + */
>>> +
>>> +#include <linux/coresight.h>
>>> +#include <linux/device.h>
>>> +#include <linux/dma-mapping.h>
>>> +#include <linux/fs.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/of_irq.h>
>>> +#include <linux/property.h>
>>> +#include <linux/uaccess.h>
>>> +
>>> +#include "coresight-ctcu.h"
>>> +#include "coresight-priv.h"
>>> +#include "coresight-tmc.h"
>>> +
>>> +#define BYTE_CNTR_CLASS_STR "byte-cntr-class"
>>> +
>>> +static struct class *byte_cntr_class;
>>> +static dev_t byte_cntr_base;
>>> +
>>> +static irqreturn_t byte_cntr_handler(int irq, void *data)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data = (struct ctcu_byte_cntr 
>>> *)data;
>>> +
>>> +??? atomic_inc(&byte_cntr_data->irq_cnt);
>>> +??? wake_up(&byte_cntr_data->wq);
>>> +
>>> +??? return IRQ_HANDLED;
>>> +}
>>> +
>>> +/* Read the data from ETR's DDR buffer. */
>>> +static void __ctcu_byte_cntr_read_etr_bytes(struct ctcu_byte_cntr 
>>> *byte_cntr_data,
>>> +??????????????????????? size_t *len, char **bufp)
>>> +{
>>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>>> >sink->dev.parent);
>>> +??? size_t actual, bytes = byte_cntr_data->thresh_val;
>>> +??? struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
>>> +??? long r_offset;
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? r_offset = byte_cntr_data->r_offset;
>>> +??? if (*len >= bytes)
>>> +??????? *len = bytes;
>>> +??? else if ((r_offset % bytes) + *len > bytes)
>>> +??????? *len = bytes - (r_offset % bytes);
>>> +
>>> +??? actual = tmc_etr_buf_get_data(etr_buf, r_offset, *len, bufp);
>>> +??? *len = actual;
>>> +??? if (actual == bytes || (actual + r_offset) % bytes == 0)
>>> +??????? atomic_dec(&byte_cntr_data->irq_cnt);
>>> +}
>>> +
>>
>> How can you safely read the ETR data while it is running ? You should
>> stop the ETR and then provide the data. You could potentially do things
>> like split the ETR buffer into two halves and switch the half used by
>> the ETR on interrupt and expose this to user.
>>
>>
>>> +/* Flush the remaining data in the ETR buffer after the byte cntr 
>>> has stopped. */
>>> +static ssize_t ctcu_flush_etr_buffer(struct ctcu_byte_cntr 
>>> *byte_cntr_data, size_t len,
>>> +???????????????????? char **bufpp)
>>> +{
>>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>>> >sink->dev.parent);
>>> +??? struct etr_buf *etr_buf = tmcdrvdata->sysfs_buf;
>>> +??? ssize_t read_len = 0, remaining_len;
>>> +??? long r_offset, w_offset;
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? r_offset = byte_cntr_data->r_offset;
>>> +??? w_offset = byte_cntr_data->w_offset;
>>> +??? if (w_offset < r_offset)
>>> +??????? remaining_len = tmcdrvdata->size + w_offset - r_offset;
>>> +??? else
>>> +??????? remaining_len = w_offset - r_offset;
>>> +
>>> +??? if (remaining_len > len)
>>> +??????? remaining_len = len;
>>> +
>>> +??? if (remaining_len > 0)
>>> +??????? read_len = tmc_etr_buf_get_data(etr_buf, r_offset, 
>>> remaining_len, bufpp);
>>> +
>>> +??? return read_len;
>>> +}
>>> +
>>> +static ssize_t ctcu_byte_cntr_copy_data(char __user *data, size_t 
>>> len, char *bufp,
>>> +??????????????????? struct ctcu_byte_cntr *byte_cntr_data,
>>> +??????????????????? struct tmc_drvdata *tmcdrvdata)
>>> +{
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? if (copy_to_user(data, bufp, len))
>>> +??????? return -EFAULT;
>>> +
>>> +??? byte_cntr_data->total_size += len;
>>> +??? if (byte_cntr_data->r_offset + len >= tmcdrvdata->size)
>>> +??????? byte_cntr_data->r_offset = 0;
>>> +??? else
>>> +??????? byte_cntr_data->r_offset += len;
>>> +
>>> +??? return len;
>>> +}
>>> +
>>> +/* The read function for /dev/byte-cntr%d */
>>
>> WHY ? WHY can't the data be exported by the existing /dev/tmc_etr* ?
>>
>>> +static ssize_t ctcu_byte_cntr_read_etr_bytes(struct file *fp, char 
>>> __user *data,
>>> +???????????????????????? size_t len, loff_t *ppos)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
>>> +??? struct tmc_drvdata *tmcdrvdata = dev_get_drvdata(byte_cntr_data- 
>>> >sink->dev.parent);
>>> +??? char *bufp = NULL;
>>> +??? ssize_t read_len;
>>> +
>>> +??? if (!data)
>>> +??????? return -EINVAL;
>>> +
>>> +??? /*
>>> +???? * Flush the remaining data in the ETR buffer based on the write
>>> +???? * offset of the ETR buffer when the byte cntr function has 
>>> stopped.
>>> +???? */
>>> +??? if (!byte_cntr_data->read_active || !byte_cntr_data->enable) {
>>> +??????? read_len = ctcu_flush_etr_buffer(byte_cntr_data, len, &bufp);
>>> +??????? if (read_len > 0)
>>> +??????????? return ctcu_byte_cntr_copy_data(data, read_len, bufp,
>>> +??????????????????????????? byte_cntr_data, tmcdrvdata);
>>> +
>>> +??????? return -EINVAL;
>>> +??? }
>>> +
>>> +??? if (!atomic_read(&byte_cntr_data->irq_cnt)) {
>>> +??????? if (wait_event_interruptible(byte_cntr_data->wq,
>>> +???????????????????????? atomic_read(&byte_cntr_data->irq_cnt) > 0 ||
>>> +???????????????????????? !byte_cntr_data->enable))
>>> +??????????? return -ERESTARTSYS;
>>> +??? }
>>> +
>>> +??? __ctcu_byte_cntr_read_etr_bytes(byte_cntr_data, &len, &bufp);
>>> +
>>> +??? return ctcu_byte_cntr_copy_data(data, len, bufp, byte_cntr_data, 
>>> tmcdrvdata);
>>> +}
>>
>> Could we not plug this into TMC-ETR read ?
>>
>> NAK for a special file approach. As Mike mentioned you need to make 
>> sure we are doing this safely.
>>
>> Suzuki
>>
>>
>>
>>> +
>>> +/* Start the byte-cntr function when the path is enabled. */
>>> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct 
>>> coresight_path *path)
>>> +{
>>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>>> +??? struct coresight_device *sink = coresight_get_sink(path);
>>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>>> +??? int port_num;
>>> +
>>> +??? if (!sink)
>>> +??????? return;
>>> +
>>> +??? port_num = ctcu_get_active_port(sink, csdev);
>>> +??? if (port_num < 0)
>>> +??????? return;
>>> +
>>> +??? byte_cntr_data = &drvdata->byte_cntr_data[port_num];
>>> +??? /* Don't start byte-cntr function when threshold is not set. */
>>> +??? if (!byte_cntr_data->thresh_val)
>>> +??????? return;
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>>> +??? byte_cntr_data->sink = sink;
>>> +??? byte_cntr_data->enable = true;
>>> +}
>>> +
>>> +/* Stop the byte-cntr function when the path is disabled. */
>>> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct 
>>> coresight_path *path)
>>> +{
>>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>>> +??? struct coresight_device *sink = coresight_get_sink(path);
>>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>>> +??? struct tmc_drvdata *tmcdrvdata;
>>> +??? int port_num;
>>> +
>>> +??? if (!sink)
>>> +??????? return;
>>> +
>>> +??? port_num = ctcu_get_active_port(sink, csdev);
>>> +??? if (port_num < 0)
>>> +??????? return;
>>> +
>>> +??? byte_cntr_data = &drvdata->byte_cntr_data[port_num];
>>> +??? tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? /* Store the w_offset of the ETR buffer when stopping. */
>>> +??? byte_cntr_data->w_offset = tmc_get_rwp_offset(tmcdrvdata);
>>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>>> +??? byte_cntr_data->read_active = false;
>>> +??? byte_cntr_data->enable = false;
>>> +??? /*
>>> +???? * Wakeup once to force the read function to read the remaining
>>> +???? * data of the ETR buffer.
>>> +???? */
>>> +??? wake_up(&byte_cntr_data->wq);
>>> +}
>>> +
>>> +static int ctcu_byte_cntr_release(struct inode *in, struct file *fp)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data = fp->private_data;
>>> +??? struct device *dev = &byte_cntr_data->sink->dev;
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? atomic_set(&byte_cntr_data->irq_cnt, 0);
>>> +??? byte_cntr_data->read_active = false;
>>> +??? disable_irq_wake(byte_cntr_data->byte_cntr_irq);
>>> +??? dev_dbg(dev, "send data total size: %llu bytes, r_offset: %ld 
>>> w_offset: %ld\n",
>>> +??????? byte_cntr_data->total_size, byte_cntr_data->r_offset,
>>> +??????? byte_cntr_data->w_offset);
>>> +
>>> +??? return 0;
>>> +}
>>> +
>>> +static int ctcu_byte_cntr_open(struct inode *in, struct file *fp)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data = container_of(in->i_cdev,
>>> +???????????????????????????????? struct ctcu_byte_cntr, c_dev);
>>> +??? struct tmc_drvdata *tmcdrvdata;
>>> +
>>> +??? if (byte_cntr_data->read_active)
>>> +??????? return -EBUSY;
>>> +
>>> +??? if (!byte_cntr_data->thresh_val || !byte_cntr_data->sink ||
>>> +??????? (coresight_get_mode(byte_cntr_data->sink) !=? CS_MODE_SYSFS))
>>> +??????? return -EINVAL;
>>> +
>>> +??? guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
>>> +??? enable_irq_wake(byte_cntr_data->byte_cntr_irq);
>>> +??? fp->private_data = byte_cntr_data;
>>> +??? nonseekable_open(in, fp);
>>> +??? tmcdrvdata = dev_get_drvdata(byte_cntr_data->sink->dev.parent);
>>> +??? /*
>>> +???? * The original r_offset is the w_offset of the ETR buffer at the
>>> +???? * start of the byte-cntr.
>>> +???? */
>>> +??? byte_cntr_data->r_offset = tmc_get_rwp_offset(tmcdrvdata);
>>> +??? byte_cntr_data->total_size = 0;
>>> +??? byte_cntr_data->read_active = true;
>>> +??? byte_cntr_data->enable = true;
>>> +
>>> +??? return 0;
>>> +}
>>> +
>>> +static const struct file_operations byte_cntr_fops = {
>>> +??? .owner??????? = THIS_MODULE,
>>> +??? .open??????? = ctcu_byte_cntr_open,
>>> +??? .read??????? = ctcu_byte_cntr_read_etr_bytes,
>>> +??? .release??? = ctcu_byte_cntr_release,
>>> +};
>>> +
>>> +static int ctcu_byte_cntr_register_chardev(struct ctcu_byte_cntr 
>>> *byte_cntr_data,
>>> +?????????????????????? int port_num)
>>> +{
>>> +??? struct device *device;
>>> +??? dev_t devt;
>>> +??? int ret;
>>> +
>>> +??? cdev_init(&byte_cntr_data->c_dev, &byte_cntr_fops);
>>> +??? devt = MKDEV(MAJOR(byte_cntr_base), MINOR(byte_cntr_base) + 
>>> port_num);
>>> +??? ret = cdev_add(&byte_cntr_data->c_dev, devt, 1);
>>> +??? if (ret < 0)
>>> +??????? return -ENOMEM;
>>> +
>>> +??? device = device_create(byte_cntr_class, NULL, devt, byte_cntr_data,
>>> +?????????????????? byte_cntr_data->name);
>>> +
>>> +??? if (IS_ERR(device))
>>> +??????? return -ENOMEM;
>>> +
>>> +??? return 0;
>>> +}
>>> +
>>> +static void ctcu_byte_cntr_unregister_chardev(struct ctcu_drvdata 
>>> *drvdata)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>>> +??? int i;
>>> +
>>> +??? for (i = 0; i < ETR_MAX_NUM; i++) {
>>> +??????? byte_cntr_data = &drvdata->byte_cntr_data[i];
>>> +??????? device_destroy(byte_cntr_class, byte_cntr_data->c_dev.dev);
>>> +??? }
>>> +}
>>> +
>>> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata 
>>> *drvdata, int etr_num)
>>> +{
>>> +??? struct ctcu_byte_cntr *byte_cntr_data;
>>> +??? struct device_node *nd = dev->of_node;
>>> +??? int byte_cntr_irq, ret, i;
>>> +
>>> +??? ret = alloc_chrdev_region(&byte_cntr_base, 0, ETR_MAX_NUM, 
>>> BYTE_CNTR_CLASS_STR);
>>> +??? if (ret < 0)
>>> +??????? return -ENOMEM;
>>> +
>>> +??? byte_cntr_class = class_create(BYTE_CNTR_CLASS_STR);
>>> +??? if (IS_ERR(byte_cntr_class)) {
>>> +??????? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>>> +??????? return -ENOMEM;
>>> +??? }
>>> +
>>> +??? for (i = 0; i < etr_num; i++) {
>>> +??????? byte_cntr_data = &drvdata->byte_cntr_data[i];
>>> +??????? byte_cntr_irq = of_irq_get_byname(nd, byte_cntr_data- 
>>> >irq_name);
>>> +??????? if (byte_cntr_irq < 0) {
>>> +??????????? ret = byte_cntr_irq;
>>> +??????????? goto err_exit;
>>> +??????? }
>>> +
>>> +??????? ret = devm_request_irq(dev, byte_cntr_irq, byte_cntr_handler,
>>> +?????????????????????? IRQF_TRIGGER_RISING | IRQF_SHARED,
>>> +?????????????????????? dev_name(dev), byte_cntr_data);
>>> +??????? if (ret) {
>>> +??????????? dev_err(dev, "Failed to register IRQ for %s\n",
>>> +??????????????? byte_cntr_data->name);
>>> +??????????? goto err_exit;
>>> +??????? }
>>> +
>>> +??????? ret = ctcu_byte_cntr_register_chardev(byte_cntr_data, i);
>>> +??????? if (ret) {
>>> +??????????? dev_err(dev, "Failed to register chardev for %s\n",
>>> +??????????????? byte_cntr_data->name);
>>> +??????????? goto err_exit;
>>> +??????? }
>>> +
>>> +??????? byte_cntr_data->byte_cntr_irq = byte_cntr_irq;
>>> +??????? atomic_set(&byte_cntr_data->irq_cnt, 0);
>>> +??????? init_waitqueue_head(&byte_cntr_data->wq);
>>> +??? }
>>> +
>>> +??? return 0;
>>> +
>>> +err_exit:
>>> +??? ctcu_byte_cntr_unregister_chardev(drvdata);
>>> +??? class_destroy(byte_cntr_class);
>>> +??? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>>> +??? return ret;
>>> +}
>>> +
>>> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata)
>>> +{
>>> +??? ctcu_byte_cntr_unregister_chardev(drvdata);
>>> +??? class_destroy(byte_cntr_class);
>>> +??? unregister_chrdev_region(byte_cntr_base, ETR_MAX_NUM);
>>> +}
>>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/ 
>>> drivers/hwtracing/coresight/coresight-ctcu-core.c
>>> index da35d8b4d579..5782655a5f39 100644
>>> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
>>> @@ -46,16 +46,24 @@ DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
>>> ? #define CTCU_ATID_REG_BIT(traceid)??? (traceid % 32)
>>> ? #define CTCU_ATID_REG_SIZE??????? 0x10
>>> ? #define CTCU_ETR0_ATID0??????????? 0xf8
>>> +#define CTCU_ETR0_IRQCTRL??????? 0x6c
>>> ? #define CTCU_ETR1_ATID0??????????? 0x108
>>> +#define CTCU_ETR1_IRQCTRL??????? 0x70
>>> ? static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
>>> ????? {
>>> -??????? .atid_offset??? = CTCU_ETR0_ATID0,
>>> -??????? .port_num??? = 0,
>>> +??????? .atid_offset??????? = CTCU_ETR0_ATID0,
>>> +??????? .irq_ctrl_offset??? = CTCU_ETR0_IRQCTRL,
>>> +??????? .irq_name??????? = "etr0",
>>> +??????? .byte_cntr_name??????? = "byte-cntr0",
>>> +??????? .port_num??????? = 0,
>>> ????? },
>>> ????? {
>>> -??????? .atid_offset??? = CTCU_ETR1_ATID0,
>>> -??????? .port_num??? = 1,
>>> +??????? .atid_offset??????? = CTCU_ETR1_ATID0,
>>> +??????? .irq_ctrl_offset??? = CTCU_ETR1_IRQCTRL,
>>> +??????? .irq_name??????? = "etr1",
>>> +??????? .byte_cntr_name??????? = "byte-cntr1",
>>> +??????? .port_num??????? = 1,
>>> ????? },
>>> ? };
>>> @@ -64,6 +72,69 @@ static const struct ctcu_config sa8775p_cfgs = {
>>> ????? .num_etr_config??? = ARRAY_SIZE(sa8775p_etr_cfgs),
>>> ? };
>>> +static ssize_t byte_cntr_val_show(struct device *dev, struct 
>>> device_attribute *attr,
>>> +????????????????? char *buf)
>>> +{
>>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> +??? int i, len = 0;
>>> +
>>> +??? for (i = 0; i < ETR_MAX_NUM; i++) {
>>> +??????? if (drvdata->byte_cntr_data[i].irq_ctrl_offset)
>>> +??????????? len += scnprintf(buf + len, PAGE_SIZE - len, "%u ",
>>> +???????????????????? drvdata->byte_cntr_data[i].thresh_val);
>>> +??? }
>>> +
>>> +??? len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
>>> +
>>> +??? return len;
>>> +}
>>> +
>>> +static ssize_t byte_cntr_val_store(struct device *dev, struct 
>>> device_attribute *attr,
>>> +?????????????????? const char *buf, size_t size)
>>> +{
>>> +??? struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> +??? u32 thresh_vals[ETR_MAX_NUM] = { 0 };
>>> +??? u32 irq_ctrl_offset;
>>> +??? int num, i;
>>> +
>>> +??? num = sscanf(buf, "%i %i", &thresh_vals[0], &thresh_vals[1]);
>>> +??? if (num <= 0 || num > ETR_MAX_NUM)
>>> +??????? return -EINVAL;
>>> +
>>> +??? /* Threshold 0 disables the interruption. */
>>> +??? guard(raw_spinlock_irqsave)(&drvdata->spin_lock);
>>> +??? for (i = 0; i < num; i++) {
>>> +??????? /* A small threshold will result in a large number of 
>>> interruptions */
>>> +??????? if (thresh_vals[i] && thresh_vals[i] < 4096)
>>> +??????????? return -EINVAL;
>>> +
>>> +??????? if (drvdata->byte_cntr_data[i].irq_ctrl_offset) {
>>> +??????????? drvdata->byte_cntr_data[i].thresh_val = thresh_vals[i];
>>> +??????????? irq_ctrl_offset = drvdata- 
>>> >byte_cntr_data[i].irq_ctrl_offset;
>>> +??????????? CS_UNLOCK(drvdata->base);
>>> +??????????? writel_relaxed(thresh_vals[i], drvdata->base + 
>>> irq_ctrl_offset);
>>> +??????????? CS_LOCK(drvdata->base);
>>> +??????? }
>>> +??? }
>>> +
>>> +??? return size;
>>> +}
>>> +static DEVICE_ATTR_RW(byte_cntr_val);
>>> +
>>> +static struct attribute *ctcu_attrs[] = {
>>> +??? &dev_attr_byte_cntr_val.attr,
>>> +??? NULL,
>>> +};
>>> +
>>> +static struct attribute_group ctcu_attr_grp = {
>>> +??? .attrs = ctcu_attrs,
>>> +};
>>> +
>>> +static const struct attribute_group *ctcu_attr_grps[] = {
>>> +??? &ctcu_attr_grp,
>>> +??? NULL,
>>> +};
>>> +
>>> ? static void ctcu_program_atid_register(struct ctcu_drvdata 
>>> *drvdata, u32 reg_offset,
>>> ???????????????????????? u8 bit, bool enable)
>>> ? {
>>> @@ -122,7 +193,7 @@ static int __ctcu_set_etr_traceid(struct 
>>> coresight_device *csdev, u8 traceid, in
>>> ?? * Searching the sink device from helper's view in case there are 
>>> multiple helper devices
>>> ?? * connected to the sink device.
>>> ?? */
>>> -static int ctcu_get_active_port(struct coresight_device *sink, 
>>> struct coresight_device *helper)
>>> +int ctcu_get_active_port(struct coresight_device *sink, struct 
>>> coresight_device *helper)
>>> ? {
>>> ????? struct coresight_platform_data *pdata = helper->pdata;
>>> ????? int i;
>>> @@ -160,6 +231,8 @@ static int ctcu_enable(struct coresight_device 
>>> *csdev, enum cs_mode mode, void *
>>> ? {
>>> ????? struct coresight_path *path = (struct coresight_path *)data;
>>> +??? ctcu_byte_cntr_start(csdev, path);
>>> +
>>> ????? return ctcu_set_etr_traceid(csdev, path, true);
>>> ? }
>>> @@ -167,6 +240,8 @@ static int ctcu_disable(struct coresight_device 
>>> *csdev, void *data)
>>> ? {
>>> ????? struct coresight_path *path = (struct coresight_path *)data;
>>> +??? ctcu_byte_cntr_stop(csdev, path);
>>> +
>>> ????? return ctcu_set_etr_traceid(csdev, path, false);
>>> ? }
>>> @@ -188,7 +263,7 @@ static int ctcu_probe(struct platform_device *pdev)
>>> ????? const struct ctcu_config *cfgs;
>>> ????? struct ctcu_drvdata *drvdata;
>>> ????? void __iomem *base;
>>> -??? int i;
>>> +??? int ret, i;
>>> ????? desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
>>> ????? if (!desc.name)
>>> @@ -217,7 +292,14 @@ static int ctcu_probe(struct platform_device *pdev)
>>> ????????????? for (i = 0; i < cfgs->num_etr_config; i++) {
>>> ????????????????? etr_cfg = &cfgs->etr_cfgs[i];
>>> ????????????????? drvdata->atid_offset[i] = etr_cfg->atid_offset;
>>> +??????????????? drvdata->byte_cntr_data[i].irq_name = etr_cfg- 
>>> >irq_name;
>>> +??????????????? drvdata->byte_cntr_data[i].name = etr_cfg- 
>>> >byte_cntr_name;
>>> +??????????????? drvdata->byte_cntr_data[i].irq_ctrl_offset =
>>> +??????????????????? etr_cfg->irq_ctrl_offset;
>>> ????????????? }
>>> +??????????? ret = ctcu_byte_cntr_init(dev, drvdata, cfgs- 
>>> >num_etr_config);
>>> +??????????? if (ret < 0)
>>> +??????????????? dev_warn(dev, "Byte cntr init failed\n");
>>> ????????? }
>>> ????? }
>>> @@ -229,6 +311,7 @@ static int ctcu_probe(struct platform_device *pdev)
>>> ????? desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU;
>>> ????? desc.pdata = pdata;
>>> ????? desc.dev = dev;
>>> +??? desc.groups = ctcu_attr_grps;
>>> ????? desc.ops = &ctcu_ops;
>>> ????? desc.access = CSDEV_ACCESS_IOMEM(base);
>>> @@ -247,6 +330,7 @@ static void ctcu_remove(struct platform_device 
>>> *pdev)
>>> ? {
>>> ????? struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
>>> +??? ctcu_byte_cntr_remove(drvdata);
>>> ????? coresight_unregister(drvdata->csdev);
>>> ? }
>>> diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/ 
>>> hwtracing/coresight/coresight-ctcu.h
>>> index e9594c38dd91..e38535c91090 100644
>>> --- a/drivers/hwtracing/coresight/coresight-ctcu.h
>>> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
>>> @@ -5,6 +5,8 @@
>>> ? #ifndef _CORESIGHT_CTCU_H
>>> ? #define _CORESIGHT_CTCU_H
>>> +#include <linux/cdev.h>
>>> +
>>> ? #include "coresight-trace-id.h"
>>> ? /* Maximum number of supported ETR devices for a single CTCU. */
>>> @@ -13,10 +15,16 @@
>>> ? /**
>>> ?? * struct ctcu_etr_config
>>> ?? * @atid_offset:??? offset to the ATID0 Register.
>>> - * @port_num:??????? in-port number of CTCU device that connected to 
>>> ETR.
>>> + * @irq_ctrl_offset:??? offset to the BYTECNTRVAL register.
>>> + * @irq_name:??????? IRQ name in dt node.
>>> + * @byte_cntr_name:??? name of the byte cntr device node.
>>> + * @port_num:??????? in-port number of the CTCU device that 
>>> connected to ETR.
>>> ?? */
>>> ? struct ctcu_etr_config {
>>> ????? const u32 atid_offset;
>>> +??? const u32 irq_ctrl_offset;
>>> +??? const char *irq_name;
>>> +??? const char *byte_cntr_name;
>>> ????? const u32 port_num;
>>> ? };
>>> @@ -25,15 +33,64 @@ struct ctcu_config {
>>> ????? int num_etr_config;
>>> ? };
>>> +/**
>>> + * struct ctcu_byte_cntr
>>> + * @c_dev:??????? cdev for byte_cntr.
>>> + * @sink??????? csdev of sink device.
>>> + * @enable:??????? indicates that byte_cntr function is enabled or not.
>>> + * @read_active:??? indicates that byte-cntr node is opened or not.
>>> + * @thresh_val:??????? threshold to trigger a interruption.
>>> + * @total_size??????? total size of transferred data.
>>> + * @byte_cntr_irq:??? IRQ number.
>>> + * @irq_cnt:??????? IRQ count.
>>> + * @wq:??????????? workqueue of reading ETR data.
>>> + * @read_work:??????? work of reading ETR data.
>>> + * @spin_lock:??????? spinlock of byte cntr data.
>>> + * @r_offset:??????? offset of the pointer where reading begins.
>>> + * @w_offset:??????? offset of the write pointer in the ETR buffer when
>>> + *??????????? the byte cntr is stopped.
>>> + * @irq_ctrl_offset:??? offset to the BYTECNTRVAL Register.
>>> + * @name:??????? the name of byte cntr device node.
>>> + * @irq_name:??????? IRQ name in DT.
>>> + */
>>> +struct ctcu_byte_cntr {
>>> +??? struct cdev??????? c_dev;
>>> +??? struct coresight_device??? *sink;
>>> +??? bool??????????? enable;
>>> +??? bool??????????? read_active;
>>> +??? u32??????????? thresh_val;
>>> +??? u64??????????? total_size;
>>> +??? int??????????? byte_cntr_irq;
>>> +??? atomic_t??????? irq_cnt;
>>> +??? wait_queue_head_t??? wq;
>>> +??? struct work_struct??? read_work;
>>> +??? raw_spinlock_t??????? spin_lock;
>>> +??? long??????????? r_offset;
>>> +??? long??????????? w_offset;
>>> +??? u32??????????? irq_ctrl_offset;
>>> +??? const char??????? *name;
>>> +??? const char??????? *irq_name;
>>> +};
>>> +
>>> ? struct ctcu_drvdata {
>>> ????? void __iomem??????? *base;
>>> ????? struct clk??????? *apb_clk;
>>> ????? struct device??????? *dev;
>>> ????? struct coresight_device??? *csdev;
>>> +??? struct ctcu_byte_cntr?? byte_cntr_data[ETR_MAX_NUM];
>>> ????? raw_spinlock_t??????? spin_lock;
>>> ????? u32??????????? atid_offset[ETR_MAX_NUM];
>>> ????? /* refcnt for each traceid of each sink */
>>> ????? u8??????????? traceid_refcnt[ETR_MAX_NUM] 
>>> [CORESIGHT_TRACE_ID_RES_TOP];
>>> ? };
>>> +/* Generic functions */
>>> +int ctcu_get_active_port(struct coresight_device *sink, struct 
>>> coresight_device *helper);
>>> +
>>> +/* Byte-cntr functions */
>>> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct 
>>> coresight_path *path);
>>> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct 
>>> coresight_path *path);
>>> +int ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata 
>>> *drvdata, int port_num);
>>> +void ctcu_byte_cntr_remove(struct ctcu_drvdata *drvdata);
>>> +
>>> ? #endif
>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/ 
>>> drivers/hwtracing/coresight/coresight-tmc-etr.c
>>> index ec636ab1fd75..5dc94e890927 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>>> @@ -1040,14 +1040,15 @@ static void tmc_free_etr_buf(struct etr_buf 
>>> *etr_buf)
>>> ?? * Returns: The size of the linear data available @pos, with *bufpp
>>> ?? * updated to point to the buffer.
>>> ?? */
>>> -static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>>> -??????????????????? u64 offset, size_t len, char **bufpp)
>>> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>>> +???????????????? u64 offset, size_t len, char **bufpp)
>>> ? {
>>> ????? /* Adjust the length to limit this transaction to end of buffer */
>>> ????? len = (len < (etr_buf->size - offset)) ? len : etr_buf->size - 
>>> offset;
>>> ????? return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
>>> ? }
>>> +EXPORT_SYMBOL_GPL(tmc_etr_buf_get_data);
>>> ? static inline s64
>>> ? tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/ 
>>> hwtracing/coresight/coresight-tmc.h
>>> index baedb4dcfc3f..2fc77fd4ea25 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>>> @@ -443,5 +443,7 @@ struct etr_buf *tmc_etr_get_buffer(struct 
>>> coresight_device *csdev,
>>> ???????????????????? enum cs_mode mode, void *data);
>>> ? extern const struct attribute_group coresight_etr_group;
>>> ? long tmc_get_rwp_offset(struct tmc_drvdata *drvdata);
>>> +ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, 
>>> size_t len,
>>> +???????????????? char **bufpp);
>>> ? #endif
>>
> 



From fabrice.gasnier at foss.st.com  Fri Mar 14 10:14:50 2025
From: fabrice.gasnier at foss.st.com (Fabrice Gasnier)
Date: Fri, 14 Mar 2025 18:14:50 +0100
Subject: [PATCH v4 7/8] arm64: dts: st: add low-power timer nodes on stm32mp251
In-Reply-To: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
Message-ID: <20250314171451.3497789-8-fabrice.gasnier@foss.st.com>

Add low-power timer (LPTimer) support on STM32MP25 SoC.
The full feature set is implemented in LPTIM1/2/3/4. LPTIM5 supports a
smaller set of features (no capture/compare) channel. Still, LPTIM5 can
be used as single PWM, counter, trigger or timer.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
---
Changes in V2:
- Adopt two compatibles: newly introduced "st,stm32mp25-..." compatible,
  and fallback "st,stm32-...".
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 +++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008..505176276e72 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -238,6 +238,78 @@ rifsc: bus at 42080000 {
 			#access-controller-cells = <1>;
 			ranges;
 
+			lptimer1: timer at 40090000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x40090000 0x400>;
+				interrupts-extended = <&exti1 47 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM1>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 17>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 0 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <0>;
+					status = "disabled";
+				};
+			};
+
+			lptimer2: timer at 400a0000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x400a0000 0x400>;
+				interrupts-extended = <&exti1 48 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM2>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 18>;
+				power-domains = <&RET_PD>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 1 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <1>;
+					status = "disabled";
+				};
+			};
+
 			i2s2: audio-controller at 400b0000 {
 				compatible = "st,stm32mp25-i2s";
 				reg = <0x400b0000 0x400>;
@@ -799,6 +871,111 @@ i2c8: i2c at 46040000 {
 				status = "disabled";
 			};
 
+			lptimer3: timer at 46050000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46050000 0x400>;
+				interrupts-extended = <&exti2 29 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM3>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 19>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 2 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <2>;
+					status = "disabled";
+				};
+			};
+
+			lptimer4: timer at 46060000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46060000 0x400>;
+				interrupts-extended = <&exti2 30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM4>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 20>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 3 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <3>;
+					status = "disabled";
+				};
+			};
+
+			lptimer5: timer at 46070000 {
+				compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+				reg = <0x46070000 0x400>;
+				interrupts-extended = <&exti2 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_LPTIM5>;
+				clock-names = "mux";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&rifsc 21>;
+				wakeup-source;
+				status = "disabled";
+
+				counter {
+					compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+
+				pwm {
+					compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer {
+					compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+					status = "disabled";
+				};
+
+				trigger at 4 {
+					compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+
 			csi: csi at 48020000 {
 				compatible = "st,stm32mp25-csi";
 				reg = <0x48020000 0x2000>;
-- 
2.25.1



From mripard at kernel.org  Fri Mar 14 11:21:01 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 14 Mar 2025 19:21:01 +0100
Subject: [PATCH v7 00/11] drm/bridge: add devm_drm_bridge_alloc() with
 bridge refcount
In-Reply-To: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
Message-ID: <20250314-daft-woodoo-cheetah-e029c5@houat>

Hi,

On Fri, Mar 14, 2025 at 11:31:13AM +0100, Luca Ceresoli wrote:
> This series improves the way DRM bridges are allocated and initialized and
> makes them reference-counted. The goal of reference counting is to avoid
> use-after-free by drivers which got a pointer to a bridge and keep it
> stored and used even after the bridge has been deallocated.
> 
> The overall goal is supporting Linux devices with a DRM pipeline whose
> final components can be hot-plugged and hot-unplugged, including one or
> more bridges. For more details see the big picture [0].
> 
> DRM bridge drivers will have to be adapted to the new API, which is pretty
> simple for most cases. Refcounting will have to be adopted on the two
> sides: all functions returning a bridge pointer and all code obtaining such
> a pointer. This series has just an overview of some of those conversions,
> because for now the main goal is to agree on the API.
> 
> Series layout:
> 
>  1. Add the new API and refcounting:
> 
>     drm/bridge: add devm_drm_bridge_alloc()
>     drm/bridge: add support for refcounting
> 
>  2. get/put the reference in basic operations in the bridge core:
> 
>     drm/bridge: get/put the bridge reference in drm_bridge_add/remove()
>     drm/bridge: get/put the bridge reference in drm_bridge_attach/detach()
> 
>  3. as an example of changes for bridge consumers, get a reference for the
>     bridge returned by drm_bridge_chain_get_first_bridge(), have it put by
>     all callers (all users will be covered later on separately):
> 
>     drm/bridge: add a cleanup action for scope-based drm_bridge_put() invocation
>     drm/bridge: get the bridge returned by drm_bridge_chain_get_first_bridge()
>     drm/mxsfb: put the bridge returned by drm_bridge_chain_get_first_bridge()
>     drm/atomic-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()
>     drm/probe-helper: put the bridge returned by drm_bridge_chain_get_first_bridge()
> 
>  4. convert a few bridge drivers (bridge providers) to the new API:
> 
>     drm/bridge: ti-sn65dsi83: use dynamic lifetime management
>     drm/bridge: samsung-dsim: use dynamic lifetime management
> 
> This work was formerly a part of my v6 DRM bridge hotplug series[0], now
> split as a standalone series with many improvements, hence the "v7" version
> number.

Except for one patch where I had comments, I think the series is in
excellent shape. We're still missing a couple of things to close this
topic though:

  - Converting the other bridge iterators/accessors to take / put the references
  - Mass converting the drivers to devm_drm_bridge_alloc
  - Documenting somewhere (possibly in drm_bridge_init?) that it really
    shouldn't be used anymore

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/9af0b727/attachment.sig>

From catalin.marinas at arm.com  Fri Mar 14 11:37:39 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 18:37:39 +0000
Subject: [PATCH V3] arm64/mm: Define PTDESC_ORDER
In-Reply-To: <20250311045710.550625-1-anshuman.khandual@arm.com>
References: <20250311045710.550625-1-anshuman.khandual@arm.com>
Message-ID: <174197745246.735540.15365076503205188211.b4-ty@arm.com>

On Tue, 11 Mar 2025 10:27:10 +0530, Anshuman Khandual wrote:
> Address bytes shifted with a single 64 bit page table entry (any page table
> level) has been always hard coded as 3 (aka 2^3 = 8). Although intuitive it
> is not very readable or easy to reason about. Besides it is going to change
> with D128, where each 128 bit page table entry will shift address bytes by
> 4 (aka 2^4 = 16) instead.
> 
> Let's just formalise this address bytes shift value into a new macro called
> PTDESC_ORDER establishing a logical abstraction, thus improving readability
> as well. While here re-organize EARLY_LEVEL macro along with its dependents
> for better clarity. This does not cause any functional change. Also replace
> all (PAGE_SHIFT - PTDESC_ORDER) instances with PTDESC_TABLE_SHIFT.
> 
> [...]

Applied to arm64 (for-next/pgtable-cleanups), thanks!

[1/1] arm64/mm: Define PTDESC_ORDER
      https://git.kernel.org/arm64/c/51ecb29f7a65

-- 
Catalin



From catalin.marinas at arm.com  Fri Mar 14 11:37:25 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 18:37:25 +0000
Subject: [PATCH 0/4] arm64: mitigate CVE-2024-7881 in the absence of firmware mitigation
In-Reply-To: <20250128155428.210645-1-mark.rutland@arm.com>
References: <20250128155428.210645-1-mark.rutland@arm.com>
Message-ID: <174197730164.734861.6726211221092480832.b4-ty@arm.com>

On Tue, 28 Jan 2025 15:54:24 +0000, Mark Rutland wrote:
> On some CPUs from Arm Ltd, it is possible for unprivileged code to cause
> a hardware prefetcher to form an address using the contents of a memory
> location which is accessible by privileged accesses in the active
> translation regime, potentially leaking the contents of this memory
> location via a side channel. This has been assigned CVE-2024-7881:
> 
>   https://developer.arm.com/Arm%20Security%20Center/Arm%20CPU%20Vulnerability%20CVE-2024-7881
> 
> [...]

Applied to arm64 (for-next/leaky-prefetcher), thanks!

There hasn't been much review (thanks Oliver for looking at the KVM
bits) and there's some implied work that can go on top of this series.
But the patches looked fine to me, so I queued them. Mark or others,
please shout if you'd like them dropped, they are on a branch.

[1/4] arm64: cpufeature: rename unmap_kernel_at_el0() -> needs_kpti()
      https://git.kernel.org/arm64/c/174ade921138
[2/4] arm64: cpufeature: factor out cpu_is_meltdown_safe()
      https://git.kernel.org/arm64/c/f4fe70cd8522
[3/4] arm64: cpufeature: mitigate CVE-2024-7881
      https://git.kernel.org/arm64/c/837dfd070e94
[4/4] KVM: arm64: expose SMCCC_ARCH_WORKAROUND_4 to guests
      https://git.kernel.org/arm64/c/d2c173acbf93

-- 
Catalin



From catalin.marinas at arm.com  Fri Mar 14 11:37:59 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 18:37:59 +0000
Subject: [PATCH v12 0/4] Support SMT control on arm64
In-Reply-To: <20250311075143.61078-1-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
Message-ID: <174197746840.735682.9575626401918508908.b4-ty@arm.com>

On Tue, 11 Mar 2025 15:51:39 +0800, Yicong Yang wrote:
> The core CPU control framework supports runtime SMT control which
> is not yet supported on arm64. Besides the general vulnerabilities
> concerns we want this runtime control on our arm64 server for:
> 
> - better single CPU performance in some cases
> - saving overall power consumption
> 
> [...]

Applied to arm64 (for-next/smt-control), thanks!

[1/4] cpu/SMT: Provide a default topology_is_primary_thread()
      https://git.kernel.org/arm64/c/4b455f59945a
[2/4] arch_topology: Support SMT control for OF based system
      https://git.kernel.org/arm64/c/5deb9c789ae4
[3/4] arm64: topology: Support SMT control on ACPI based system
      https://git.kernel.org/arm64/c/e6b18ebfaf63
[4/4] arm64: Kconfig: Enable HOTPLUG_SMT
      https://git.kernel.org/arm64/c/eed4583bcf9a

-- 
Catalin



From catalin.marinas at arm.com  Fri Mar 14 11:42:42 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 18:42:42 +0000
Subject: [PATCH v4 0/5] arm64: errata: Rework Spectre BHB mitigations to not assume "safe"
In-Reply-To: <20250107200715.422172-1-dianders@chromium.org>
References: <20250107200715.422172-1-dianders@chromium.org>
Message-ID: <174197748983.735859.13306599472795958808.b4-ty@arm.com>

On Tue, 07 Jan 2025 12:05:57 -0800, Douglas Anderson wrote:
> Recently I realized that a device with some Qualcomm Kryo 4xx cores
> reported in `lscpu` that it was _not_ vulnerable to Spectre BHB. This
> seemed unlikely to me.
> 
> I wrote up a patch series to attempt (with a lot of guesswork) to add
> Qualcomm cores to the tables governing how the Spectre BHB mitigation
> worked.
> 
> [...]

Applied to arm64 (for-next/spectre-bhb-assume-vulnerable), thanks!

As per Will's suggestion at the end of last year:

https://lore.kernel.org/r/20241219175128.GA25477 at willie-the-truck/

Doug has reworked the code to assume vulnerable by default. James did
suggest some splitting of patch 2 but given that Doug doesn't have time
for a respin I decided to queue the patches. If anyone has a strong
opinion, please let me know (and reworking the series is welcomed).

[1/5] arm64: errata: Add QCOM_KRYO_4XX_GOLD to the spectre_bhb_k24_list
      https://git.kernel.org/arm64/c/ed1ce841245d
[2/5] arm64: errata: Assume that unknown CPUs _are_ vulnerable to Spectre BHB
      https://git.kernel.org/arm64/c/e403e8538359
[3/5] arm64: errata: Add KRYO 2XX/3XX/4XX silver cores to Spectre BHB safe list
      https://git.kernel.org/arm64/c/0c9fc6e652cd
[4/5] arm64: cputype: Add MIDR_CORTEX_A76AE
      https://git.kernel.org/arm64/c/a9b5bd81b294
[5/5] arm64: errata: Add newer ARM cores to the spectre_bhb_loop_affected() lists
      https://git.kernel.org/arm64/c/a5951389e58d

-- 
Catalin



From catalin.marinas at arm.com  Fri Mar 14 11:43:39 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 14 Mar 2025 18:43:39 +0000
Subject: (subset) [PATCH v2 0/4] arm64/sysreg: Sort sysreg by encoding
In-Reply-To: <20250115162600.2153226-1-james.clark@linaro.org>
References: <20250115162600.2153226-1-james.clark@linaro.org>
Message-ID: <174197777060.737113.10729866203138129273.b4-ty@arm.com>

On Wed, 15 Jan 2025 16:25:54 +0000, James Clark wrote:
> A few small fixes and then sort and ensure sysreg remains sorted due to
> the discussion here [1].
> 
> Applies to next-20250115 for the review but I can repost after rc1.
> 
> Changes since v1:
> 
> [...]

Applied to arm64 (for-next/sysreg), thanks!

I'm not convinced about sorting, it makes backporting hard. Most likely
it would also conflict with other patches already queued. So I only
applied the first two patches.

[1/4] arm64/sysreg: Fix unbalanced closing block
      https://git.kernel.org/arm64/c/00cb1e01cd29
[2/4] arm64/sysreg: Enforce whole word match for open/close tokens
      https://git.kernel.org/arm64/c/2fdbf2ff3884

-- 
Catalin



From lorenzo at kernel.org  Fri Mar 14 12:02:15 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 14 Mar 2025 20:02:15 +0100
Subject: [PATCH] net: airoha: fix CONFIG_DEBUG_FS check
In-Reply-To: <20250314155009.4114308-1-arnd@kernel.org>
References: <20250314155009.4114308-1-arnd@kernel.org>
Message-ID: <Z9R9NxIsMAyUZFYf@lore-desk>

> From: Arnd Bergmann <arnd at arndb.de>
> 
> The #if check causes a build failure when CONFIG_DEBUG_FS is turned
> off:
> 
> In file included from drivers/net/ethernet/airoha/airoha_eth.c:17:
> drivers/net/ethernet/airoha/airoha_eth.h:543:5: error: "CONFIG_DEBUG_FS" is not defined, evaluates to 0 [-Werror=undef]
>   543 | #if CONFIG_DEBUG_FS
>       |     ^~~~~~~~~~~~~~~
> 
> Replace it with the correct #ifdef.
> 
> Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Acked-by: Lorenzo Bianconi <lorenzo at kernel.org>

> ---
>  drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index f66b9b736b94..60690b685710 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -540,7 +540,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth);
>  struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
>  						  u32 hash);
>  
> -#if CONFIG_DEBUG_FS
> +#ifdef CONFIG_DEBUG_FS
>  int airoha_ppe_debugfs_init(struct airoha_ppe *ppe);
>  #else
>  static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
> -- 
> 2.39.5
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250314/0f2e5c00/attachment.sig>

From andrew at lunn.ch  Fri Mar 14 12:16:58 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 14 Mar 2025 20:16:58 +0100
Subject: [net-next PATCH v12 09/13] mfd: an8855: Add support for Airoha
 AN8855 Switch MFD
In-Reply-To: <20250309172717.9067-10-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-10-ansuelsmth@gmail.com>
Message-ID: <2253e19b-2115-441e-b78a-3c10d61f2fad@lunn.ch>

> +static int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id,

phy_id is a bit of an odd name. __mdiobus_write() expects addr, since
at this level, it is just a device on a bus. We have no idea if it is
a PHY, or an Ethernet switch, or anything else.

> +			       u8 page) __must_hold(&priv->bus->mdio_lock)
> +{
> +	struct mii_bus *bus = priv->bus;
> +	int ret;
> +
> +	ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page);
> +	if (ret < 0)
> +		dev_err_ratelimited(&bus->dev,
> +				    "failed to set an8855 mii page\n");
> +
> +	/* Cache current page if next mii read/write is for switch */
> +	priv->current_page = page;
> +	return ret < 0 ? ret : 0;

__mdiobus_write() should only return -ve error code, or 0. So you
don't need this.

	Andrew


From nunodasneves at linux.microsoft.com  Fri Mar 14 12:25:32 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:25:32 -0700
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <fcd132af-03e4-496d-ba70-0097e90a83cf@oss.qualcomm.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <fcd132af-03e4-496d-ba70-0097e90a83cf@oss.qualcomm.com>
Message-ID: <c480e790-0abb-41af-a0cb-e358ff7b671f@linux.microsoft.com>

On 3/11/2025 11:01 AM, Jeff Johnson wrote:
> On 2/26/25 15:08, Nuno Das Neves wrote:
> ...
>> +
>> +MODULE_AUTHOR("Microsoft");
>> +MODULE_LICENSE("GPL");
>> +
> 
> Since commit 1fffe7a34c89 ("script: modpost: emit a warning when the
> description is missing"), a module without a MODULE_DESCRIPTION() will
> result in a warning with make W=1. Please add a MODULE_DESCRIPTION()
> to avoid this warning.
> 
> This is a canned review based upon finding a MODULE_LICENSE without a
> MODULE_DESCRIPTION.
> 
> /jeff

Thanks Jeff. Fixed in v6.

Nuno


From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:54 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:54 -0700
Subject: [PATCH v6 08/10] x86: hyperv: Add mshv_handler() irq handler and setup function
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-9-git-send-email-nunodasneves@linux.microsoft.com>

Add mshv_handler() to process messages related to managing guest
partitions such as intercepts, doorbells, and scheduling messages.

In a (non-nested) root partition, the same interrupt vector is shared
between the vmbus and mshv_root drivers.

Introduce a stub for mshv_handler() and call it in
sysvec_hyperv_callback alongside vmbus_handler().

Even though both handlers will be called for every Hyper-V interrupt,
the messages for each driver are delivered to different offsets
within the SYNIC message page, so they won't step on each other.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Wei Liu <wei.liu at kernel.org>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
 drivers/hv/hv_common.c         | 5 +++++
 include/asm-generic/mshyperv.h | 1 +
 3 files changed, 15 insertions(+)

diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index fcd0e066d9bd..3e2533954675 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
 }
 EXPORT_SYMBOL_GPL(hv_set_msr);
 
+static void (*mshv_handler)(void);
 static void (*vmbus_handler)(void);
 static void (*hv_stimer0_handler)(void);
 static void (*hv_kexec_handler)(void);
@@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
 	inc_irq_stat(irq_hv_callback_count);
+	if (mshv_handler)
+		mshv_handler();
+
 	if (vmbus_handler)
 		vmbus_handler();
 
@@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
 	set_irq_regs(old_regs);
 }
 
+void hv_setup_mshv_handler(void (*handler)(void))
+{
+	mshv_handler = handler;
+}
+
 void hv_setup_vmbus_handler(void (*handler)(void))
 {
 	vmbus_handler = handler;
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 3cd9b96ffc67..b3b11be11650 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -680,6 +680,11 @@ void __weak hv_remove_vmbus_handler(void)
 }
 EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
 
+void __weak hv_setup_mshv_handler(void (*handler)(void))
+{
+}
+EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
+
 void __weak hv_setup_kexec_handler(void (*handler)(void))
 {
 }
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 8519b8ec8e9d..ccccb1cbf7df 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
 void hv_remove_kexec_handler(void);
 void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
 void hv_remove_crash_handler(void);
+void hv_setup_mshv_handler(void (*handler)(void));
 
 extern int vmbus_interrupt;
 extern int vmbus_irq;
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:55 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:55 -0700
Subject: [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-10-git-send-email-nunodasneves@linux.microsoft.com>

A few additional definitions are required for the mshv driver code
(to follow). Introduce those here and clean up a little bit while
at it.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 include/hyperv/hvgdk_mini.h |  72 ++++++++++++++++++--
 include/hyperv/hvhdk.h      | 132 ++++++++++++++++++++++++++++++++++--
 include/hyperv/hvhdk_mini.h |  91 +++++++++++++++++++++++++
 3 files changed, 284 insertions(+), 11 deletions(-)

diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
index 58895883f636..735329859f21 100644
--- a/include/hyperv/hvgdk_mini.h
+++ b/include/hyperv/hvgdk_mini.h
@@ -13,7 +13,7 @@ struct hv_u128 {
 	u64 high_part;
 } __packed;
 
-/* NOTE: when adding below, update hv_status_to_string() */
+/* NOTE: when adding below, update hv_result_to_string() */
 #define HV_STATUS_SUCCESS			    0x0
 #define HV_STATUS_INVALID_HYPERCALL_CODE	    0x2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT	    0x3
@@ -51,6 +51,7 @@ struct hv_u128 {
 #define HV_HYP_PAGE_SHIFT		12
 #define HV_HYP_PAGE_SIZE		BIT(HV_HYP_PAGE_SHIFT)
 #define HV_HYP_PAGE_MASK		(~(HV_HYP_PAGE_SIZE - 1))
+#define HV_HYP_LARGE_PAGE_SHIFT		21
 
 #define HV_PARTITION_ID_INVALID		((u64)0)
 #define HV_PARTITION_ID_SELF		((u64)-1)
@@ -374,6 +375,10 @@ union hv_hypervisor_version_info {
 #define HV_SHARED_GPA_BOUNDARY_ACTIVE			BIT(5)
 #define HV_SHARED_GPA_BOUNDARY_BITS			GENMASK(11, 6)
 
+/* HYPERV_CPUID_FEATURES.ECX bits. */
+#define HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE	BIT(9)
+#define HV_VP_GHCB_ROOT_MAPPING_AVAILABLE		BIT(10)
+
 enum hv_isolation_type {
 	HV_ISOLATION_TYPE_NONE	= 0,	/* HV_PARTITION_ISOLATION_TYPE_NONE */
 	HV_ISOLATION_TYPE_VBS	= 1,
@@ -436,10 +441,13 @@ union hv_vp_assist_msr_contents {	 /* HV_REGISTER_VP_ASSIST_PAGE */
 #define HVCALL_WITHDRAW_MEMORY				0x0049
 #define HVCALL_MAP_GPA_PAGES				0x004b
 #define HVCALL_UNMAP_GPA_PAGES				0x004c
+#define HVCALL_INSTALL_INTERCEPT			0x004d
 #define HVCALL_CREATE_VP				0x004e
 #define HVCALL_DELETE_VP				0x004f
 #define HVCALL_GET_VP_REGISTERS				0x0050
 #define HVCALL_SET_VP_REGISTERS				0x0051
+#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS		0x0052
+#define HVCALL_CLEAR_VIRTUAL_INTERRUPT			0x0056
 #define HVCALL_DELETE_PORT				0x0058
 #define HVCALL_DISCONNECT_PORT				0x005b
 #define HVCALL_POST_MESSAGE				0x005c
@@ -447,12 +455,15 @@ union hv_vp_assist_msr_contents {	 /* HV_REGISTER_VP_ASSIST_PAGE */
 #define HVCALL_POST_DEBUG_DATA				0x0069
 #define HVCALL_RETRIEVE_DEBUG_DATA			0x006a
 #define HVCALL_RESET_DEBUG_SESSION			0x006b
+#define HVCALL_MAP_STATS_PAGE				0x006c
+#define HVCALL_UNMAP_STATS_PAGE				0x006d
 #define HVCALL_ADD_LOGICAL_PROCESSOR			0x0076
 #define HVCALL_GET_SYSTEM_PROPERTY			0x007b
 #define HVCALL_MAP_DEVICE_INTERRUPT			0x007c
 #define HVCALL_UNMAP_DEVICE_INTERRUPT			0x007d
 #define HVCALL_RETARGET_INTERRUPT			0x007e
 #define HVCALL_NOTIFY_PORT_RING_EMPTY			0x008b
+#define HVCALL_REGISTER_INTERCEPT_RESULT		0x0091
 #define HVCALL_ASSERT_VIRTUAL_INTERRUPT			0x0094
 #define HVCALL_CREATE_PORT				0x0095
 #define HVCALL_CONNECT_PORT				0x0096
@@ -460,12 +471,18 @@ union hv_vp_assist_msr_contents {	 /* HV_REGISTER_VP_ASSIST_PAGE */
 #define HVCALL_GET_VP_ID_FROM_APIC_ID			0x009a
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE	0x00af
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST	0x00b0
+#define HVCALL_SIGNAL_EVENT_DIRECT			0x00c0
+#define HVCALL_POST_MESSAGE_DIRECT			0x00c1
 #define HVCALL_DISPATCH_VP				0x00c2
+#define HVCALL_GET_GPA_PAGES_ACCESS_STATES		0x00c9
+#define HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d7
+#define HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS	0x00d8
 #define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY	0x00db
 #define HVCALL_MAP_VP_STATE_PAGE			0x00e1
 #define HVCALL_UNMAP_VP_STATE_PAGE			0x00e2
 #define HVCALL_GET_VP_STATE				0x00e3
 #define HVCALL_SET_VP_STATE				0x00e4
+#define HVCALL_GET_VP_CPUID_VALUES			0x00f4
 #define HVCALL_MMIO_READ				0x0106
 #define HVCALL_MMIO_WRITE				0x0107
 
@@ -775,10 +792,10 @@ struct hv_message_page {
 
 /* Define timer message payload structure. */
 struct hv_timer_message_payload {
-	__u32 timer_index;
-	__u32 reserved;
-	__u64 expiration_time;	/* When the timer expired */
-	__u64 delivery_time;	/* When the message was delivered */
+	u32 timer_index;
+	u32 reserved;
+	u64 expiration_time;	/* When the timer expired */
+	u64 delivery_time;	/* When the message was delivered */
 } __packed;
 
 struct hv_x64_segment_register {
@@ -807,6 +824,8 @@ struct hv_x64_table_register {
 	u64 base;
 } __packed;
 
+#define HV_NORMAL_VTL	0
+
 union hv_input_vtl {
 	u8 as_uint8;
 	struct {
@@ -1325,6 +1344,49 @@ struct hv_retarget_device_interrupt {	 /* HV_INPUT_RETARGET_DEVICE_INTERRUPT */
 	struct hv_device_interrupt_target int_target;
 } __packed __aligned(8);
 
+enum hv_intercept_type {
+#if defined(CONFIG_X86)
+	HV_INTERCEPT_TYPE_X64_IO_PORT			= 0x00000000,
+	HV_INTERCEPT_TYPE_X64_MSR			= 0x00000001,
+	HV_INTERCEPT_TYPE_X64_CPUID			= 0x00000002,
+#endif
+	HV_INTERCEPT_TYPE_EXCEPTION			= 0x00000003,
+	/* Used to be HV_INTERCEPT_TYPE_REGISTER */
+	HV_INTERCEPT_TYPE_RESERVED0			= 0x00000004,
+	HV_INTERCEPT_TYPE_MMIO				= 0x00000005,
+#if defined(CONFIG_X86)
+	HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID		= 0x00000006,
+	HV_INTERCEPT_TYPE_X64_APIC_SMI			= 0x00000007,
+#endif
+	HV_INTERCEPT_TYPE_HYPERCALL			= 0x00000008,
+#if defined(CONFIG_X86)
+	HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI		= 0x00000009,
+	HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ	= 0x0000000A,
+	HV_INTERCEPT_TYPE_X64_APIC_WRITE		= 0x0000000B,
+	HV_INTERCEPT_TYPE_X64_MSR_INDEX			= 0x0000000C,
+#endif
+	HV_INTERCEPT_TYPE_MAX,
+	HV_INTERCEPT_TYPE_INVALID			= 0xFFFFFFFF,
+};
+
+union hv_intercept_parameters {
+	/*  HV_INTERCEPT_PARAMETERS is defined to be an 8-byte field. */
+	u64 as_uint64;
+#if defined(CONFIG_X86)
+	/* HV_INTERCEPT_TYPE_X64_IO_PORT */
+	u16 io_port;
+	/* HV_INTERCEPT_TYPE_X64_CPUID */
+	u32 cpuid_index;
+	/* HV_INTERCEPT_TYPE_X64_APIC_WRITE */
+	u32 apic_write_mask;
+	/* HV_INTERCEPT_TYPE_EXCEPTION */
+	u16 exception_vector;
+	/* HV_INTERCEPT_TYPE_X64_MSR_INDEX */
+	u32 msr_index;
+#endif
+	/* N.B. Other intercept types do not have any parameters. */
+};
+
 /* Data structures for HVCALL_MMIO_READ and HVCALL_MMIO_WRITE */
 #define HV_HYPERCALL_MMIO_MAX_DATA_LENGTH 64
 
diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
index 64407c2a3809..b4067ada02cf 100644
--- a/include/hyperv/hvhdk.h
+++ b/include/hyperv/hvhdk.h
@@ -19,11 +19,24 @@
 
 #define HV_VP_REGISTER_PAGE_VERSION_1	1u
 
+#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT		7
+
+union hv_vp_register_page_interrupt_vectors {
+	u64 as_uint64;
+	struct {
+		u8 vector_count;
+		u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
+	} __packed;
+};
+
 struct hv_vp_register_page {
 	u16 version;
 	u8 isvalid;
 	u8 rsvdz;
 	u32 dirty;
+
+#if IS_ENABLED(CONFIG_X86)
+
 	union {
 		struct {
 			/* General purpose registers
@@ -95,6 +108,22 @@ struct hv_vp_register_page {
 	union hv_x64_pending_interruption_register pending_interruption;
 	union hv_x64_interrupt_state_register interrupt_state;
 	u64 instruction_emulation_hints;
+	u64 xfem;
+
+	/*
+	 * Fields from this point are not included in the register page save chunk.
+	 * The reserved field is intended to maintain alignment for unsaved fields.
+	 */
+	u8 reserved1[0x100];
+
+	/*
+	 * Interrupts injected as part of HvCallDispatchVp.
+	 */
+	union hv_vp_register_page_interrupt_vectors interrupt_vectors;
+
+#elif IS_ENABLED(CONFIG_ARM64)
+	/* Not yet supported in ARM */
+#endif
 } __packed;
 
 #define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
@@ -299,10 +328,11 @@ union hv_partition_isolation_properties {
 #define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED   0x2
 
 /* Note: Exo partition is enabled by default */
-#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION                    BIT(8)
-#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED                    BIT(13)
-#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED   BIT(19)
-#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE                   BIT(22)
+#define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED		BIT(4)
+#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION			BIT(8)
+#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED			BIT(13)
+#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED	BIT(19)
+#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE			BIT(22)
 
 struct hv_input_create_partition {
 	u64 flags;
@@ -349,13 +379,23 @@ struct hv_input_set_partition_property {
 enum hv_vp_state_page_type {
 	HV_VP_STATE_PAGE_REGISTERS = 0,
 	HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1,
+	HV_VP_STATE_PAGE_GHCB = 2,
 	HV_VP_STATE_PAGE_COUNT
 };
 
 struct hv_input_map_vp_state_page {
 	u64 partition_id;
 	u32 vp_index;
-	u32 type; /* enum hv_vp_state_page_type */
+	u16 type; /* enum hv_vp_state_page_type */
+	union hv_input_vtl input_vtl;
+	union {
+		u8 as_uint8;
+		struct {
+			u8 map_location_provided : 1;
+			u8 reserved : 7;
+		};
+	} flags;
+	u64 requested_map_location;
 } __packed;
 
 struct hv_output_map_vp_state_page {
@@ -365,7 +405,14 @@ struct hv_output_map_vp_state_page {
 struct hv_input_unmap_vp_state_page {
 	u64 partition_id;
 	u32 vp_index;
-	u32 type; /* enum hv_vp_state_page_type */
+	u16 type; /* enum hv_vp_state_page_type */
+	union hv_input_vtl input_vtl;
+	u8 reserved0;
+} __packed;
+
+struct hv_x64_apic_eoi_message {
+	u32 vp_index;
+	u32 interrupt_vector;
 } __packed;
 
 struct hv_opaque_intercept_message {
@@ -515,6 +562,13 @@ struct hv_synthetic_timers_state {
 	u64 reserved[5];
 } __packed;
 
+struct hv_async_completion_message_payload {
+	u64 partition_id;
+	u32 status;
+	u32 completion_count;
+	u64 sub_status;
+} __packed;
+
 union hv_input_delete_vp {
 	u64 as_uint64[2];
 	struct {
@@ -649,6 +703,57 @@ struct hv_input_set_vp_state {
 	union hv_input_set_vp_state_data data[];
 } __packed;
 
+union hv_x64_vp_execution_state {
+	u16 as_uint16;
+	struct {
+		u16 cpl:2;
+		u16 cr0_pe:1;
+		u16 cr0_am:1;
+		u16 efer_lma:1;
+		u16 debug_active:1;
+		u16 interruption_pending:1;
+		u16 vtl:4;
+		u16 enclave_mode:1;
+		u16 interrupt_shadow:1;
+		u16 virtualization_fault_active:1;
+		u16 reserved:2;
+	} __packed;
+};
+
+struct hv_x64_intercept_message_header {
+	u32 vp_index;
+	u8 instruction_length:4;
+	u8 cr8:4; /* Only set for exo partitions */
+	u8 intercept_access_type;
+	union hv_x64_vp_execution_state execution_state;
+	struct hv_x64_segment_register cs_segment;
+	u64 rip;
+	u64 rflags;
+} __packed;
+
+union hv_x64_memory_access_info {
+	u8 as_uint8;
+	struct {
+		u8 gva_valid:1;
+		u8 gva_gpa_valid:1;
+		u8 hypercall_output_pending:1;
+		u8 tlb_locked_no_overlay:1;
+		u8 reserved:4;
+	} __packed;
+};
+
+struct hv_x64_memory_intercept_message {
+	struct hv_x64_intercept_message_header header;
+	u32 cache_type; /* enum hv_cache_type */
+	u8 instruction_byte_count;
+	union hv_x64_memory_access_info memory_access_info;
+	u8 tpr_priority;
+	u8 reserved1;
+	u64 guest_virtual_address;
+	u64 guest_physical_address;
+	u8 instruction_bytes[16];
+} __packed;
+
 /*
  * Dispatch state for the VP communicated by the hypervisor to the
  * VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
@@ -716,6 +821,7 @@ static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message) ==
 #define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH		0x8
 #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH	0x10
 #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH	0x20
+#define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION	0x40
 
 struct hv_input_dispatch_vp {
 	u64 partition_id;
@@ -730,4 +836,18 @@ struct hv_output_dispatch_vp {
 	u32 dispatch_event; /* enum hv_vp_dispatch_event */
 } __packed;
 
+struct hv_input_modify_sparse_spa_page_host_access {
+	u32 host_access : 2;
+	u32 reserved : 30;
+	u32 flags;
+	u64 partition_id;
+	u64 spa_page_list[];
+} __packed;
+
+/* hv_input_modify_sparse_spa_page_host_access flags */
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE  0x1
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED     0x2
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE      0x4
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE       0x8
+
 #endif /* _HV_HVHDK_H */
diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h
index f8a39d3e9ce6..42e7876455b5 100644
--- a/include/hyperv/hvhdk_mini.h
+++ b/include/hyperv/hvhdk_mini.h
@@ -36,6 +36,52 @@ enum hv_scheduler_type {
 	HV_SCHEDULER_TYPE_MAX
 };
 
+/* HV_STATS_AREA_TYPE */
+enum hv_stats_area_type {
+	HV_STATS_AREA_SELF = 0,
+	HV_STATS_AREA_PARENT = 1,
+	HV_STATS_AREA_INTERNAL = 2,
+	HV_STATS_AREA_COUNT
+};
+
+enum hv_stats_object_type {
+	HV_STATS_OBJECT_HYPERVISOR		= 0x00000001,
+	HV_STATS_OBJECT_LOGICAL_PROCESSOR	= 0x00000002,
+	HV_STATS_OBJECT_PARTITION		= 0x00010001,
+	HV_STATS_OBJECT_VP			= 0x00010002
+};
+
+union hv_stats_object_identity {
+	/* hv_stats_hypervisor */
+	struct {
+		u8 reserved[15];
+		u8 stats_area_type;
+	} __packed hv;
+
+	/* hv_stats_logical_processor */
+	struct {
+		u32 lp_index;
+		u8 reserved[11];
+		u8 stats_area_type;
+	} __packed lp;
+
+	/* hv_stats_partition */
+	struct {
+		u64 partition_id;
+		u8  reserved[7];
+		u8  stats_area_type;
+	} __packed partition;
+
+	/* hv_stats_vp */
+	struct {
+		u64 partition_id;
+		u32 vp_index;
+		u16 flags;
+		u8  reserved;
+		u8  stats_area_type;
+	} __packed vp;
+};
+
 enum hv_partition_property_code {
 	/* Privilege properties */
 	HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS			= 0x00010000,
@@ -47,19 +93,45 @@ enum hv_partition_property_code {
 
 	/* Compatibility properties */
 	HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES		= 0x00060002,
+	HV_PARTITION_PROPERTY_XSAVE_STATES                      = 0x00060007,
 	HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE		= 0x00060008,
 	HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY		= 0x00060009,
 };
 
+enum hv_snp_status {
+	HV_SNP_STATUS_NONE = 0,
+	HV_SNP_STATUS_AVAILABLE = 1,
+	HV_SNP_STATUS_INCOMPATIBLE = 2,
+	HV_SNP_STATUS_PSP_UNAVAILABLE = 3,
+	HV_SNP_STATUS_PSP_INIT_FAILED = 4,
+	HV_SNP_STATUS_PSP_BAD_FW_VERSION = 5,
+	HV_SNP_STATUS_BAD_CONFIGURATION = 6,
+	HV_SNP_STATUS_PSP_FW_UPDATE_IN_PROGRESS = 7,
+	HV_SNP_STATUS_PSP_RB_INIT_FAILED = 8,
+	HV_SNP_STATUS_PSP_PLATFORM_STATUS_FAILED = 9,
+	HV_SNP_STATUS_PSP_INIT_LATE_FAILED = 10,
+};
+
 enum hv_system_property {
 	/* Add more values when needed */
 	HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15,
+	HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21,
+};
+
+enum hv_dynamic_processor_feature_property {
+	/* Add more values when needed */
+	HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13,
+	HV_X64_DYNAMIC_PROCESSOR_FEATURE_SNP_STATUS = 16,
 };
 
 struct hv_input_get_system_property {
 	u32 property_id; /* enum hv_system_property */
 	union {
 		u32 as_uint32;
+#if IS_ENABLED(CONFIG_X86)
+		/* enum hv_dynamic_processor_feature_property */
+		u32 hv_processor_feature;
+#endif
 		/* More fields to be filled in when needed */
 	};
 } __packed;
@@ -67,9 +139,28 @@ struct hv_input_get_system_property {
 struct hv_output_get_system_property {
 	union {
 		u32 scheduler_type; /* enum hv_scheduler_type */
+#if IS_ENABLED(CONFIG_X86)
+		u64 hv_processor_feature_value;
+#endif
 	};
 } __packed;
 
+struct hv_input_map_stats_page {
+	u32 type; /* enum hv_stats_object_type */
+	u32 padding;
+	union hv_stats_object_identity identity;
+} __packed;
+
+struct hv_output_map_stats_page {
+	u64 map_location;
+} __packed;
+
+struct hv_input_unmap_stats_page {
+	u32 type; /* enum hv_stats_object_type */
+	u32 padding;
+	union hv_stats_object_identity identity;
+} __packed;
+
 struct hv_proximity_domain_flags {
 	u32 proximity_preferred : 1;
 	u32 reserved : 30;
-- 
2.34.1



From andrew at lunn.ch  Fri Mar 14 12:34:58 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 14 Mar 2025 20:34:58 +0100
Subject: [net-next PATCH v12 09/13] mfd: an8855: Add support for Airoha
 AN8855 Switch MFD
In-Reply-To: <20250314113551.GK3890718@google.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-10-ansuelsmth@gmail.com>
 <20250314113551.GK3890718@google.com>
Message-ID: <49d2cfed-cb31-438d-9736-6d8e0bb24041@lunn.ch>

> > +static int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id,
> > +			       u8 page) __must_hold(&priv->bus->mdio_lock)
> > +{
> > +	struct mii_bus *bus = priv->bus;
> > +	int ret;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page);
> 
> Calling functions with '__' is a red flag.

In this case, it is correct. It was probably a bad decision to call
this __mdiobus_write() in the first place, but we were not expecting
it to be used in real driver code, just in core code, where calls to
it are wrapped with a mutex lock/unlock.

But drivers started to need to perform multiple read/write operations
in an atomic sequence, so they started doing there own taking of the
lock, and using these unlocked low level helpers.

We should probably rename __mdiobus_write() to _mdiobus_write() to
avoid compiler namespace issues.

> > +	if (ret < 0)
> > +		dev_err_ratelimited(&bus->dev,
> > +				    "failed to set an8855 mii page\n");
> 
> Use 100-chars if it avoids these kind of line breaks.

I _guess_ the code is following networking coding style, even though
it is outside of normal networking directories. netdev keeps with the
old 80 limit.

> > +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 addr = priv->switch_addr;
> > +	int ret;
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> 
> guard()?

netdev people consider guard() too magical. scoped_guard() is however
O.K.

> > +	return ret < 0 ? ret : 0;
> 
> Doesn't the caller already expect possible >0 results?

It should not happen. Networking has a very small number of functions
which do return 1 on a different sort of success. Such functions are
generally called foo_changed(), e.g. mdiobus_modify_changed(). This
will do a read/modify/write. If it did not need to modify anything,
because of the current value, it will return 0. If something did
actually change, it returns 1. If something did actually change, you
sometimes need to take further actions. But many callers don't care,
so we have wrappers e.g. mdiobus_modify() calls
mdiobus_modify_changed() and then converts 0 or 1 to just 0. I'm
guessing this code copied such a helper when it should not of done.

	Andrew


From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:47 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:47 -0700
Subject: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>

Introduce hv_status_printk() macros as a convenience to log hypercall
errors, formatting them with the status code (HV_STATUS_*) as a raw hex
value and also as a string, which saves some time while debugging.

Create a table of HV_STATUS_ codes with strings and mapped errnos, and
use it for hv_result_to_string() and hv_result_to_errno().

Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
irqdomain.c hypercalls to aid debugging in the root partition.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
---
 arch/x86/hyperv/irqdomain.c    |   6 +-
 drivers/hv/hv_common.c         | 129 ++++++++++++++++++++++++---------
 drivers/hv/hv_proc.c           |  10 +--
 drivers/iommu/hyperv-iommu.c   |   4 +-
 include/asm-generic/mshyperv.h |  13 ++++
 5 files changed, 118 insertions(+), 44 deletions(-)

diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
index 64b921360b0f..31f0d29cbc5e 100644
--- a/arch/x86/hyperv/irqdomain.c
+++ b/arch/x86/hyperv/irqdomain.c
@@ -64,7 +64,7 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,
 	local_irq_restore(flags);
 
 	if (!hv_result_success(status))
-		pr_err("%s: hypercall failed, status %lld\n", __func__, status);
+		hv_status_err(status, "\n");
 
 	return hv_result(status);
 }
@@ -224,7 +224,7 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 		kfree(stored_entry);
 
 		if (status != HV_STATUS_SUCCESS) {
-			pr_debug("%s: failed to unmap, status %lld", __func__, status);
+			hv_status_debug(status, "failed to unmap\n");
 			return;
 		}
 	}
@@ -273,7 +273,7 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
 	status = hv_unmap_msi_interrupt(dev, &old_entry);
 
 	if (status != HV_STATUS_SUCCESS)
-		pr_err("%s: hypercall failed, status %lld\n", __func__, status);
+		hv_status_err(status, "\n");
 }
 
 static void hv_msi_free_irq(struct irq_domain *domain,
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 9804adb4cc56..885bbc3d86d8 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -684,40 +684,6 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
 }
 EXPORT_SYMBOL_GPL(hv_tdx_hypercall);
 
-/* Convert a hypercall result into a linux-friendly error code. */
-int hv_result_to_errno(u64 status)
-{
-	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
-	if (unlikely(status == U64_MAX))
-		return -EOPNOTSUPP;
-	/*
-	 * A failed hypercall is usually only recoverable (or loggable) near
-	 * the call site where the HV_STATUS_* code is known. So the errno
-	 * it gets converted to is not too useful further up the stack.
-	 * Provide a few mappings that could be useful, and revert to -EIO
-	 * as a fallback.
-	 */
-	switch (hv_result(status)) {
-	case HV_STATUS_SUCCESS:
-		return 0;
-	case HV_STATUS_INVALID_HYPERCALL_CODE:
-	case HV_STATUS_INVALID_HYPERCALL_INPUT:
-	case HV_STATUS_INVALID_PARAMETER:
-	case HV_STATUS_INVALID_PARTITION_ID:
-	case HV_STATUS_INVALID_VP_INDEX:
-	case HV_STATUS_INVALID_PORT_ID:
-	case HV_STATUS_INVALID_CONNECTION_ID:
-	case HV_STATUS_INVALID_LP_INDEX:
-	case HV_STATUS_INVALID_REGISTER_VALUE:
-		return -EINVAL;
-	case HV_STATUS_INSUFFICIENT_MEMORY:
-		return -ENOMEM;
-	default:
-		break;
-	}
-	return -EIO;
-}
-
 void hv_identify_partition_type(void)
 {
 	/* Assume guest role */
@@ -740,3 +706,98 @@ void hv_identify_partition_type(void)
 			pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
 	}
 }
+
+struct hv_status_info {
+	char *string;
+	int errno;
+	u16 code;
+};
+
+/*
+ * Note on the errno mappings:
+ * A failed hypercall is usually only recoverable (or loggable) near
+ * the call site where the HV_STATUS_* code is known. So the errno
+ * it gets converted to is not too useful further up the stack.
+ * Provide a few mappings that could be useful, and revert to -EIO
+ * as a fallback.
+ */
+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
+	_STATUS_INFO(HV_STATUS_SUCCESS,				0),
+	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PARAMETER,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_ACCESS_DENIED,			-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE,		-EIO),
+	_STATUS_INFO(HV_STATUS_OPERATION_DENIED,		-EIO),
+	_STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY,		-EIO),
+	_STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE,	-EIO),
+	_STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY,		-ENOMEM),
+	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_VP_INDEX,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_NOT_FOUND,			-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PORT_ID,			-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS,		-EIO),
+	_STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_VP_STATE,		-EIO),
+	_STATUS_INFO(HV_STATUS_NO_RESOURCES,			-EIO),
+	_STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED,	-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EIO),
+	_STATUS_INFO(HV_STATUS_OPERATION_FAILED,		-EIO),
+	_STATUS_INFO(HV_STATUS_TIME_OUT,			-EIO),
+	_STATUS_INFO(HV_STATUS_CALL_PENDING,			-EIO),
+	_STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,		-EIO),
+#undef _STATUS_INFO
+};
+
+static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
+{
+	int i;
+	u16 code = hv_result(hv_status);
+
+	for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+		const struct hv_status_info *info = &hv_status_infos[i];
+
+		if (info->code == code)
+			return info;
+	}
+
+	return NULL;
+}
+
+/* Convert a hypercall result into a linux-friendly error code. */
+int hv_result_to_errno(u64 status)
+{
+	const struct hv_status_info *info;
+
+	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
+	if (unlikely(status == U64_MAX))
+		return -EOPNOTSUPP;
+
+	info = find_hv_status_info(status);
+	if (info)
+		return info->errno;
+
+	return -EIO;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_errno);
+
+const char *hv_result_to_string(u64 status)
+{
+	const struct hv_status_info *info;
+
+	if (unlikely(status == U64_MAX))
+		return "Hypercall page missing!";
+
+	info = find_hv_status_info(status);
+	if (info)
+		return info->string;
+
+	return "Unknown";
+}
+EXPORT_SYMBOL_GPL(hv_result_to_string);
diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
index 2fae18e4f7d2..605999f10e17 100644
--- a/drivers/hv/hv_proc.c
+++ b/drivers/hv/hv_proc.c
@@ -87,7 +87,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
 				     page_count, 0, input_page, NULL);
 	local_irq_restore(flags);
 	if (!hv_result_success(status)) {
-		pr_err("Failed to deposit pages: %lld\n", status);
+		hv_status_err(status, "\n");
 		ret = hv_result_to_errno(status);
 		goto err_free_allocations;
 	}
@@ -137,8 +137,8 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
 
 		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
 			if (!hv_result_success(status)) {
-				pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
-				       lp_index, apic_id, status);
+				hv_status_err(status, "cpu %u apic ID: %u\n",
+					      lp_index, apic_id);
 				ret = hv_result_to_errno(status);
 			}
 			break;
@@ -179,8 +179,8 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
 
 		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
 			if (!hv_result_success(status)) {
-				pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
-				       vp_index, flags, status);
+				hv_status_err(status, "vcpu: %u, lp: %u\n",
+					      vp_index, flags);
 				ret = hv_result_to_errno(status);
 			}
 			break;
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
index 53e4b37716af..761ab647f372 100644
--- a/drivers/iommu/hyperv-iommu.c
+++ b/drivers/iommu/hyperv-iommu.c
@@ -217,7 +217,7 @@ hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
 		status = hv_unmap_ioapic_interrupt(ioapic_id, &entry);
 
 		if (status != HV_STATUS_SUCCESS)
-			pr_debug("%s: unexpected unmap status %lld\n", __func__, status);
+			hv_status_debug(status, "failed to unmap\n");
 
 		data->entry.ioapic_rte.as_uint64 = 0;
 		data->entry.source = 0; /* Invalid source */
@@ -228,7 +228,7 @@ hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
 					vector, &entry);
 
 	if (status != HV_STATUS_SUCCESS) {
-		pr_err("%s: map hypercall failed, status %lld\n", __func__, status);
+		hv_status_err(status, "map failed\n");
 		return;
 	}
 
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index b13b0cda4ac8..250c65236919 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -298,6 +298,19 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
 	return __cpumask_to_vpset(vpset, cpus, func);
 }
 
+#define _hv_status_fmt(fmt) "%s: Hyper-V status: %#x = %s: " fmt
+#define hv_status_printk(level, status, fmt, ...) \
+do { \
+	u64 __status = (status); \
+	pr_##level(_hv_status_fmt(fmt), __func__, hv_result(__status), \
+		   hv_result_to_string(__status), ##__VA_ARGS__); \
+} while (0)
+#define hv_status_err(status, fmt, ...) \
+	hv_status_printk(err, status, fmt, ##__VA_ARGS__)
+#define hv_status_debug(status, fmt, ...) \
+	hv_status_printk(debug, status, fmt, ##__VA_ARGS__)
+
+const char *hv_result_to_string(u64 hv_status);
 int hv_result_to_errno(u64 status);
 void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
 bool hv_is_hyperv_initialized(void);
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:46 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:46 -0700
Subject: [PATCH v6 00/10] Introduce /dev/mshv root partition driver
Message-ID: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>

This series introduces support for creating and running guest virtual
machines while running on the Microsoft Hypervisor[0] as root partition.
This is done via an IOCTL interface accessed through /dev/mshv, similar to
/dev/kvm. Another series introducing this support was previously posted in
2021[1], and versions 1-4 of this series were posted in 2023[2].

Patches 1-4 are small refactors and additions to Hyper-V code.
Patches 5-6 just export some definitions needed by /dev/mshv.
Patches 7-9 introduce some functionality and definitions in common code, that
are specific to the driver.
Patch 10 contains the driver code.

-----------------
[0] "Hyper-V" is more well-known, but it really refers to the whole stack
    including the hypervisor and other components that run in Windows
    kernel and userspace.
[1] Previous /dev/mshv patch series (2021) and discussion:
https://lore.kernel.org/linux-hyperv/1632853875-20261-1-git-send-email-nunodasneves at linux.microsoft.com/
[2] v4 (2023):
https://lore.kernel.org/linux-hyperv/1696010501-24584-1-git-send-email-nunodasneves at linux.microsoft.com/

-----------------
Changes since v5:
* Rework patch 1:
 1. Introduce hv_status_printk() logging macros which print the raw HV_STATUS_
    code along with string [Roman Kisel]
 2. Iterate over an array of data items to get the string and errno for the
    hv_result_to_*() functions. [Michael Kelley]
 3. Use hv_status_printk() to log errors in hyperv/irqdomain.c and
    hyperv-iommu.c [Easwar Hariharan]
* Minor cleanup, improvements, and commit wording changes in patches 2, 3, 4, 6
  [Roman Kisel, Easwar Hariharan, Michael Kelley]
* Fix issues with declaration and lifecycle of hv_synic_eventring_tail in patch
  7 [Michael Kelley]
* Improve detail and clarity of commit message in patch 8 [Michael Kelley]
* Minor cleanups in patch 9 - uapi types -> kernel types, #ifdef CONFIG_X86_64
  -> CONFIG_X86 for consistency, fix HVCALL_* ordering, remove redundant
  __packed, use explicit enum value [Stanislav Kinsburskii, Easwar Hariharan,
  Michael Kelley, Tianyu Lan]
* Minor fixes and cleanup in patch 10 [Michael Kelley]
* Add MODULE_DESCRIPTION() to patch 10 [Jeff Johnson]

Changes since v4:
* Slim down the IOCTL interface significantly, via several means:
  1. Use generic "passthrough" call MSHV_ROOT_HVCALL to replace many ioctls.
  2. Use MSHV_* versions of some of the HV_* definitions.
  3. Move hv headers out of uapi altogether, into include/hyperv/, see:
https://lore.kernel.org/linux-hyperv/1732577084-2122-1-git-send-email-nunodasneves at linux.microsoft.com/
* Remove mshv_vtl module altogther, it will be posted in followup series
  * Also remove the parent "mshv" module which didn't serve much purpose
* Update and refactor parts of the driver code for clarity, extensibility

Changes since v3 (summarized):
* Clean up the error and debug logging:
  1. Add a set of macros vp_*() and partition_*() which call the equivalent
     dev_*(), passing the device from the partition struct
     * The new macros also print the partition and vp ids to aid debugging
	   and reduce repeated code
  2. Use dev_*() (mostly via the new macros) instead of pr_*() *almost*
  everywhere - in interrupt context we can't always get the device struct
  3. Remove pr_*() logging from hv_call.c and mshv_root_hv_call.c

Changes since v2 (summarized):
* Fix many checkpatch.pl --strict style issues
* Initialize status in get/set registers hypercall helpers
* Add missing return on error in get_vp_signaled_count

Changes since v1 (summarized):
* Clean up formatting, commit messages

Nuno Das Neves (9):
  hyperv: Log hypercall status codes as strings
  arm64/hyperv: Add some missing functions to arm64
  hyperv: Introduce hv_recommend_using_aeoi()
  acpi: numa: Export node_to_pxm()
  Drivers: hv: Export some functions for use by root partition module
  Drivers: hv: Introduce per-cpu event ring tail
  x86: hyperv: Add mshv_handler() irq handler and setup function
  hyperv: Add definitions for root partition driver to hv headers
  Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs

Stanislav Kinsburskii (1):
  x86/mshyperv: Add support for extended Hyper-V features

 .../userspace-api/ioctl/ioctl-number.rst      |    2 +
 arch/arm64/hyperv/hv_core.c                   |   17 +
 arch/arm64/hyperv/mshyperv.c                  |    1 +
 arch/arm64/include/asm/mshyperv.h             |   13 +
 arch/x86/hyperv/irqdomain.c                   |    6 +-
 arch/x86/kernel/cpu/mshyperv.c                |   16 +-
 drivers/acpi/numa/srat.c                      |    1 +
 drivers/hv/Makefile                           |    5 +-
 drivers/hv/hv.c                               |   12 +-
 drivers/hv/hv_common.c                        |  175 +-
 drivers/hv/hv_proc.c                          |   13 +-
 drivers/hv/mshv.h                             |   30 +
 drivers/hv/mshv_common.c                      |  161 ++
 drivers/hv/mshv_eventfd.c                     |  833 ++++++
 drivers/hv/mshv_eventfd.h                     |   71 +
 drivers/hv/mshv_irq.c                         |  124 +
 drivers/hv/mshv_portid_table.c                |   84 +
 drivers/hv/mshv_root.h                        |  308 +++
 drivers/hv/mshv_root_hv_call.c                |  852 ++++++
 drivers/hv/mshv_root_main.c                   | 2333 +++++++++++++++++
 drivers/hv/mshv_synic.c                       |  665 +++++
 drivers/iommu/hyperv-iommu.c                  |    4 +-
 include/asm-generic/mshyperv.h                |   34 +-
 include/hyperv/hvgdk_mini.h                   |   72 +-
 include/hyperv/hvhdk.h                        |  132 +-
 include/hyperv/hvhdk_mini.h                   |   91 +
 include/uapi/linux/mshv.h                     |  287 ++
 27 files changed, 6266 insertions(+), 76 deletions(-)
 create mode 100644 drivers/hv/mshv.h
 create mode 100644 drivers/hv/mshv_common.c
 create mode 100644 drivers/hv/mshv_eventfd.c
 create mode 100644 drivers/hv/mshv_eventfd.h
 create mode 100644 drivers/hv/mshv_irq.c
 create mode 100644 drivers/hv/mshv_portid_table.c
 create mode 100644 drivers/hv/mshv_root.h
 create mode 100644 drivers/hv/mshv_root_hv_call.c
 create mode 100644 drivers/hv/mshv_root_main.c
 create mode 100644 drivers/hv/mshv_synic.c
 create mode 100644 include/uapi/linux/mshv.h

-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:49 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:49 -0700
Subject: [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-4-git-send-email-nunodasneves@linux.microsoft.com>

These non-nested msr and fast hypercall functions are present in x86,
but they must be available in both architectures for the root partition
driver code.

While at it, remove the redundant 'extern' keywords from the
hv_do_hypercall() variants in asm-generic/mshyperv.h.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/hyperv/hv_core.c       | 17 +++++++++++++++++
 arch/arm64/include/asm/mshyperv.h | 13 +++++++++++++
 include/asm-generic/mshyperv.h    |  6 ++++--
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 69004f619c57..e33a9e3c366a 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
 }
 EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
 
+/*
+ * hv_do_fast_hypercall16 -- Invoke the specified hypercall
+ * with arguments in registers instead of physical memory.
+ * Avoids the overhead of virt_to_phys for simple hypercalls.
+ */
+u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
+{
+	struct arm_smccc_res	res;
+	u64			control;
+
+	control = (u64)code | HV_HYPERCALL_FAST_BIT;
+
+	arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
+	return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
+
 /*
  * Set a single VP register to a 64-bit value.
  */
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index 2e2f83bafcfb..b721d3134ab6 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -40,6 +40,19 @@ static inline u64 hv_get_msr(unsigned int reg)
 	return hv_get_vpreg(reg);
 }
 
+/*
+ * Nested is not supported on arm64
+ */
+static inline void hv_set_non_nested_msr(unsigned int reg, u64 value)
+{
+	hv_set_msr(reg, value);
+}
+
+static inline u64 hv_get_non_nested_msr(unsigned int reg)
+{
+	return hv_get_msr(reg);
+}
+
 /* SMCCC hypercall parameters */
 #define HV_SMCCC_FUNC_NUMBER	1
 #define HV_FUNC_ID	ARM_SMCCC_CALL_VAL(			\
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index c8043efabf5a..c3697bc0598d 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -70,8 +70,10 @@ extern enum hv_partition_type hv_curr_partition_type;
 extern void * __percpu *hyperv_pcpu_input_arg;
 extern void * __percpu *hyperv_pcpu_output_arg;
 
-extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
-extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
+u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
+u64 hv_do_fast_hypercall8(u16 control, u64 input8);
+u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
+
 bool hv_isolation_type_snp(void);
 bool hv_isolation_type_tdx(void);
 
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:50 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:50 -0700
Subject: [PATCH v6 04/10] hyperv: Introduce hv_recommend_using_aeoi()
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-5-git-send-email-nunodasneves@linux.microsoft.com>

Factor out the check for enabling auto eoi, to be reused in root
partition code.

No functional changes.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 drivers/hv/hv.c                | 12 +-----------
 include/asm-generic/mshyperv.h | 13 +++++++++++++
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index a38f84548bc2..308c8f279df8 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -313,17 +313,7 @@ void hv_synic_enable_regs(unsigned int cpu)
 
 	shared_sint.vector = vmbus_interrupt;
 	shared_sint.masked = false;
-
-	/*
-	 * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
-	 * it doesn't provide a recommendation flag and AEOI must be disabled.
-	 */
-#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
-	shared_sint.auto_eoi =
-			!(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
-#else
-	shared_sint.auto_eoi = 0;
-#endif
+	shared_sint.auto_eoi = hv_recommend_using_aeoi();
 	hv_set_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
 	/* Enable the global synic bit */
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index c3697bc0598d..8519b8ec8e9d 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -77,6 +77,19 @@ u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
 bool hv_isolation_type_snp(void);
 bool hv_isolation_type_tdx(void);
 
+/*
+ * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
+ * it doesn't provide a recommendation flag and AEOI must be disabled.
+ */
+static inline bool hv_recommend_using_aeoi(void)
+{
+#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
+	return !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
+#else
+	return false;
+#endif
+}
+
 static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node)
 {
 	struct hv_proximity_domain_info pxm_info = {};
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:48 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:48 -0700
Subject: [PATCH v6 02/10] x86/mshyperv: Add support for extended Hyper-V features
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-3-git-send-email-nunodasneves@linux.microsoft.com>

From: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>

Extend the "ms_hyperv_info" structure to include a new field,
"ext_features", for capturing extended Hyper-V features.
Update the "ms_hyperv_init_platform" function to retrieve these features
using the cpuid instruction and include them in the informational output.

Signed-off-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>
Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 arch/x86/kernel/cpu/mshyperv.c | 6 ++++--
 include/asm-generic/mshyperv.h | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 4f01f424ea5b..fd285b18d6b4 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -434,13 +434,15 @@ static void __init ms_hyperv_init_platform(void)
 	 */
 	ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
 	ms_hyperv.priv_high = cpuid_ebx(HYPERV_CPUID_FEATURES);
+	ms_hyperv.ext_features = cpuid_ecx(HYPERV_CPUID_FEATURES);
 	ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
 	ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
 	hv_max_functions_eax = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS);
 
-	pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n",
-		ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
+	pr_info("Hyper-V: privilege flags low %#x, high %#x, ext %#x, hints %#x, misc %#x\n",
+		ms_hyperv.features, ms_hyperv.priv_high,
+		ms_hyperv.ext_features, ms_hyperv.hints,
 		ms_hyperv.misc_features);
 
 	ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 250c65236919..c8043efabf5a 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -36,6 +36,7 @@ enum hv_partition_type {
 struct ms_hyperv_info {
 	u32 features;
 	u32 priv_high;
+	u32 ext_features;
 	u32 misc_features;
 	u32 hints;
 	u32 nested_features;
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:52 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:52 -0700
Subject: [PATCH v6 06/10] Drivers: hv: Export some functions for use by root partition module
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-7-git-send-email-nunodasneves@linux.microsoft.com>

hv_get_hypervisor_version(), hv_call_deposit_pages(), and
hv_call_create_vp(), are all needed in-module with CONFIG_MSHV_ROOT=m.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at microsoft.linux.com>
Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 arch/arm64/hyperv/mshyperv.c   | 1 +
 arch/x86/kernel/cpu/mshyperv.c | 1 +
 drivers/hv/hv_proc.c           | 3 ++-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 2265ea5ce5ad..4e27cc29c79e 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -26,6 +26,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
 
 static int __init hyperv_init(void)
 {
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index fd285b18d6b4..fcd0e066d9bd 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -420,6 +420,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
 
 static void __init ms_hyperv_init_platform(void)
 {
diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
index 605999f10e17..7d7ecb6f6137 100644
--- a/drivers/hv/hv_proc.c
+++ b/drivers/hv/hv_proc.c
@@ -107,6 +107,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
 	kfree(counts);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
 
 int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
 {
@@ -191,4 +192,4 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
 
 	return ret;
 }
-
+EXPORT_SYMBOL_GPL(hv_call_create_vp);
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:51 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:51 -0700
Subject: [PATCH v6 05/10] acpi: numa: Export node_to_pxm()
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-6-git-send-email-nunodasneves@linux.microsoft.com>

node_to_pxm() is used by hv_numa_node_to_pxm_info().
That helper will be used by Hyper-V root partition module code
when CONFIG_MSHV_ROOT=m.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 drivers/acpi/numa/srat.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
index 00ac0d7bb8c9..ce815d7cb8f6 100644
--- a/drivers/acpi/numa/srat.c
+++ b/drivers/acpi/numa/srat.c
@@ -51,6 +51,7 @@ int node_to_pxm(int node)
 		return PXM_INVAL;
 	return node_to_pxm_map[node];
 }
+EXPORT_SYMBOL_GPL(node_to_pxm);
 
 static void __acpi_map_pxm_to_node(int pxm, int node)
 {
-- 
2.34.1



From nunodasneves at linux.microsoft.com  Fri Mar 14 12:28:53 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 14 Mar 2025 12:28:53 -0700
Subject: [PATCH v6 07/10] Drivers: hv: Introduce per-cpu event ring tail
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1741980536-3865-8-git-send-email-nunodasneves@linux.microsoft.com>

Add a pointer hv_synic_eventring_tail to track the tail pointer for the
SynIC event ring buffer for each SINT.

This will be used by the mshv driver, but must be tracked independently
since the driver module could be removed and re-inserted.

Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
Reviewed-by: Wei Liu <wei.liu at kernel.org>
Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
---
 drivers/hv/hv_common.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 885bbc3d86d8..3cd9b96ffc67 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
 
 static struct ctl_table_header *hv_ctl_table_hdr;
 
+/*
+ * Per-cpu array holding the tail pointer for the SynIC event ring buffer
+ * for each SINT.
+ *
+ * We cannot maintain this in mshv driver because the tail pointer should
+ * persist even if the mshv driver is unloaded.
+ */
+u8 * __percpu *hv_synic_eventring_tail;
+EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
+
 /*
  * Hyper-V specific initialization and shutdown code that is
  * common across all architectures.  Called from architecture
@@ -90,6 +100,9 @@ void __init hv_common_free(void)
 
 	free_percpu(hyperv_pcpu_input_arg);
 	hyperv_pcpu_input_arg = NULL;
+
+	free_percpu(hv_synic_eventring_tail);
+	hv_synic_eventring_tail = NULL;
 }
 
 /*
@@ -372,6 +385,11 @@ int __init hv_common_init(void)
 		BUG_ON(!hyperv_pcpu_output_arg);
 	}
 
+	if (hv_root_partition()) {
+		hv_synic_eventring_tail = alloc_percpu(u8 *);
+		BUG_ON(!hv_synic_eventring_tail);
+	}
+
 	hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
 				    GFP_KERNEL);
 	if (!hv_vp_index) {
@@ -460,11 +478,12 @@ void __init ms_hyperv_late_init(void)
 int hv_common_cpu_init(unsigned int cpu)
 {
 	void **inputarg, **outputarg;
+	u8 **synic_eventring_tail;
 	u64 msr_vp_index;
 	gfp_t flags;
 	const int pgcount = hv_output_page_exists() ? 2 : 1;
 	void *mem;
-	int ret;
+	int ret = 0;
 
 	/* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
 	flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
@@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
 	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
 
 	/*
-	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
-	 * allocated if this CPU was previously online and then taken offline
+	 * The per-cpu memory is already allocated if this CPU was previously
+	 * online and then taken offline
 	 */
 	if (!*inputarg) {
 		mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
@@ -520,11 +539,21 @@ int hv_common_cpu_init(unsigned int cpu)
 	if (msr_vp_index > hv_max_vp_index)
 		hv_max_vp_index = msr_vp_index;
 
-	return 0;
+	if (hv_root_partition()) {
+		synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
+		*synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
+						sizeof(u8), flags);
+		/* No need to unwind any of the above on failure here */
+		if (unlikely(!*synic_eventring_tail))
+			ret = -ENOMEM;
+	}
+
+	return ret;
 }
 
 int hv_common_cpu_die(unsigned int cpu)
 {
+	u8 **synic_eventring_tail;
 	/*
 	 * The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory
 	 * is not freed when the CPU goes offline as the hyperv_pcpu_input_arg
@@ -537,6 +566,10 @@ int hv_common_cpu_die(unsigned int cpu)
 	 * originally allocated memory is reused in hv_common_cpu_init().
 	 */
 
+	synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail);
+	kfree(*synic_eventring_tail);
+	*synic_eventring_tail = NULL;
+
 	return 0;
 }
 
-- 
2.34.1



From andrew at lunn.ch  Fri Mar 14 12:41:33 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 14 Mar 2025 20:41:33 +0100
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
 <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
 <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>
Message-ID: <0c6cb801-5592-4449-b776-a337161b3326@lunn.ch>

On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > + * read/write register are encoded in the regmap register
> > > + * by placing the register in the first 16 bits and the PHY address
> > > + * right after.
> > > + */
> > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > 
> > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > and then 16 bits of register address - significant in that order. Can
> > we adjust the mask for the PHY address later to add the MMD between
> > the PHY address and register number?
> >
> 
> Honestly to future proof this, I think a good idea might be to add
> helper to encode these info and use Clause 45 format even for C22.
> Maybe we can use an extra bit to signal if the format is C22 or C45.
> 
> BIT(26) 0: C22 1:C45
> GENMASK(25, 21) PHY ADDR
> GENMASK(20, 16) MMD ADDR
> GENMASK(15, 0) REG

If you look back at older kernels, there was some helpers to do
something like this, but the C22/C45 was in bit 31. When i cleaned up
MDIO drivers to have separate C22 and C45 read/write functions, they
become redundant and they were removed. You might want to bring them
back again.

	Andrew


From andersson at kernel.org  Fri Mar 14 13:01:03 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Fri, 14 Mar 2025 15:01:03 -0500
Subject: (subset) [PATCH v15 00/10] Coresight: Add Coresight TMC Control Unit driver
In-Reply-To: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
References: <20250303032931.2500935-1-quic_jiegan@quicinc.com>
Message-ID: <174198247887.1604753.1605423266163412383.b4-ty@kernel.org>


On Mon, 03 Mar 2025 11:29:21 +0800, Jie Gan wrote:
> From: Jie Gan <jie.gan at oss.qualcomm.com>
> 
> The Coresight TMC Control Unit(CTCU) device hosts miscellaneous configuration
> registers to control various features related to TMC ETR device.
> 
> The CTCU device works as a helper device physically connected to the TMC ETR device.
> ---------------------------------------------------------
>              |ETR0|             |ETR1|
>               . \                 / .
>               .  \               /  .
>               .   \             /   .
>               .    \           /    .
> ---------------------------------------------------
> ETR0ATID0-ETR0ATID3     CTCU    ETR1ATID0-ETR1ATID3
> ---------------------------------------------------
> Each ETR has four ATID registers with 128 bits long in total.
> e.g. ETR0ATID0-ETR0ATID3 registers are used by ETR0 device.
> 
> [...]

Applied, thanks!

[10/10] arm64: dts: qcom: sa8775p: Add CTCU and ETR nodes
        commit: 05ed68070d7a061f62f502d07f883c05dc666990

Best regards,
-- 
Bjorn Andersson <andersson at kernel.org>


From andersson at kernel.org  Fri Mar 14 13:01:12 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Fri, 14 Mar 2025 15:01:12 -0500
Subject: (subset) [PATCH v6 0/2] Add support for GPU SMMU on QCS8300
In-Reply-To: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
References: <20250310-b4-branch-gfx-smmu-v6-0-15c60b8abd99@quicinc.com>
Message-ID: <174198247897.1604753.3634981110002933426.b4-ty@kernel.org>


On Mon, 10 Mar 2025 16:48:33 +0530, Pratyush Brahma wrote:
> Enable GPU SMMU function on QCS8300 platform. GPU SMMU is required
> for address translation in GPU device.
> 
> 

Applied, thanks!

[2/2] arm64: dts: qcom: qcs8300: Add device node for gfx_smmu
      commit: 28ef67df3658365b0a8ae6b54c800e70b0216778

Best regards,
-- 
Bjorn Andersson <andersson at kernel.org>


From mathieu.poirier at linaro.org  Fri Mar 14 13:18:19 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Fri, 14 Mar 2025 14:18:19 -0600
Subject: [PATCH] remoteproc: imx_dsp_rproc: Document run_stall struct
 member
In-Reply-To: <20250314151720.1793719-1-daniel.baluta@nxp.com>
References: <20250314151720.1793719-1-daniel.baluta@nxp.com>
Message-ID: <Z9SPC1Rl28NKjFTV@p14s>

On Fri, Mar 14, 2025 at 05:17:19PM +0200, Daniel Baluta wrote:
> Add documentation for 'run_stall' imx_dsp_rproc struct member.
> This also fixes the following warning:
> 
> warning: Function parameter or struct member 'run_stall'
> not described in 'imx_dsp_rproc'
> 
> Fixes: 0184b4fdbad1 ("imx_dsp_rproc: Use reset controller API to control the DSP")
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503142125.IE33sCto-lkp at intel.com/
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
>  drivers/remoteproc/imx_dsp_rproc.c | 1 +
>  1 file changed, 1 insertion(+)
>

Applied.

> diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
> index bc60edcdd661..90cb1fc13e71 100644
> --- a/drivers/remoteproc/imx_dsp_rproc.c
> +++ b/drivers/remoteproc/imx_dsp_rproc.c
> @@ -96,6 +96,7 @@ enum imx_dsp_rp_mbox_messages {
>  /**
>   * struct imx_dsp_rproc - DSP remote processor state
>   * @regmap: regmap handler
> + * @run_stall: reset control handle used for Run/Stall operation
>   * @rproc: rproc handler
>   * @dsp_dcfg: device configuration pointer
>   * @clks: clocks needed by this device
> -- 
> 2.43.0
> 


From torvalds at linux-foundation.org  Fri Mar 14 13:34:57 2025
From: torvalds at linux-foundation.org (Linus Torvalds)
Date: Fri, 14 Mar 2025 10:34:57 -1000
Subject: [GIT PULL] arm64 fixes for -rc7
In-Reply-To: <20250314160458.GA9438@willie-the-truck>
References: <20250314160458.GA9438@willie-the-truck>
Message-ID: <CAHk-=wgiX0q0WCL+SFwVCYtG7JR3=2Rshse-5J3AO2Y4AgT7Jw@mail.gmail.com>

On Fri, 14 Mar 2025 at 06:05, Will Deacon <will at kernel.org> wrote:
>
> Summary in the tag, but the main one is a horrible macro fix for our
> TLB flushing code which resulted in over-invalidation on the MMU
> notifier path.

>From a quick look, that macro is still quite broken. Maybe not in ways
that matter, but still...

In particular, the 'stride' argument is used multiple times, and
without parentheses.

The 'lpa' argument is also used multiple times, and the input to that
is typically something like kvm_lpa2_is_enabled(), so I think it
potentially generates lots of pointless duplicate code with that
BUG_ON() in system_supports_lpa2() -> cpus_have_final_cap().

Maybe the compiler figures it out. But that macro is bad, bad, bad.
When it looks like a function, it should act like a function, and not
evaluate its arguments multiple times.

The most immediate bug may have been fixed, but not the actual real
horror of that thing.

             Linus


From acme at kernel.org  Fri Mar 14 13:48:12 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Fri, 14 Mar 2025 17:48:12 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9Rm0W6YLpxKIcI1@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
 <Z9RjHpEJGWtj8PAM@x1>
 <Z9Rm0W6YLpxKIcI1@x1>
Message-ID: <Z9SWDGsdgagMr8PV@x1>

On Fri, Mar 14, 2025 at 02:26:41PM -0300, Arnaldo Carvalho de Melo wrote:
> it finds the pair, but then its sc->args has a bogus pointer... I'll see
> where this isn't being initialized...

Breakpoint 4, trace__find_usable_bpf_prog_entry (trace=0x7fffffffa510, sc=0x1046f10) at builtin-trace.c:3874
3874			bool is_candidate = false;
(gdb) n
3876			if (pair == NULL || pair == sc ||
(gdb) p pair
$7 = (struct syscall *) 0x1083c50
(gdb) p pair->name
$8 = 0x81478e "accept4"
(gdb) n
3877			    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
(gdb) p i
$9 = 1
(gdb) n
3876			if (pair == NULL || pair == sc ||
(gdb) n
3880			printf("sc=%p\n", sc); fflush(stdout);
(gdb) n
sc=0x1046f10
3881			printf("sc->name=%p\n", sc->name); fflush(stdout);
(gdb) n
sc->name=0x6c66202c786c3830
3882			printf("sc->nr_args=%d, sc->args=%p\n", sc->nr_args, sc->args); fflush(stdout);
(gdb) p sc->nr_args
$10 = 1935635045
(gdb) p sc->args
$11 = (struct tep_format_field *) 0x257830203a6e656c
(gdb) p *sc
$12 = {e_machine = 540697702, id = 807761968, tp_format = 0x657075202c786c38, nr_args = 1935635045, args_size = 1634427759, bpf_prog = {sys_enter = 0x257830203a726464, 
    sys_exit = 0x7075202c786c3830}, is_exit = 101, is_open = 101, nonexistent = 114, use_btf = 95, args = 0x257830203a6e656c, 
  name = 0x6c66202c786c3830 <error: Cannot access memory at address 0x6c66202c786c3830>, fmt = 0x257830203a736761, arg_fmt = 0x786c3830}
(gdb) 

Ok, ran out of time, but if I simple avoid the second loop in:

static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)


I.e. the one that starts with:

        /*
         * Now lets do a second pass looking for enabled syscalls without
         * an augmenter that have a signature that is a superset of another
         * syscall with an augmenter so that we can auto-reuse it.

This:

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e0434f7dc67cb988..3664bb512c70cabf 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3989,6 +3989,8 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
                        goto out;
        }
 
+       return 0;
+
        /*
         * Now lets do a second pass looking for enabled syscalls without
         * an augmenter that have a signature that is a superset of another
? [acme at toolbox perf-tools-next]$ 


Then all works, we don't reuse any BPF program, but then that is an
heuristic anyway, that is tried becuase landlock_add_rule has a pointer
argument:

root at number:~# perf trace -e landlock_add_rule perf test -w landlock
     0.000 ( 0.003 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7fff6f2bb550, flags: 45) = -1 EINVAL (Invalid argument)
     0.004 ( 0.001 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7fff6f2bb540, flags: 45) = -1 EINVAL (Invalid argument)
root at number:~# perf test enum
105: perf trace enum augmentation tests                              : Ok
root at number:~#

So its some sort of syncronization on the various new tables, sorted by
name, etc that then when iterating over the syscalls ends up using a sc
that is not initialized.

- Arnaldo


From linux at armlinux.org.uk  Fri Mar 14 14:01:56 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 14 Mar 2025 21:01:56 +0000
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <0c6cb801-5592-4449-b776-a337161b3326@lunn.ch>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
 <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
 <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>
 <0c6cb801-5592-4449-b776-a337161b3326@lunn.ch>
Message-ID: <Z9SZRDykbTwvGW6S@shell.armlinux.org.uk>

On Fri, Mar 14, 2025 at 08:41:33PM +0100, Andrew Lunn wrote:
> On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> > On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > > + * read/write register are encoded in the regmap register
> > > > + * by placing the register in the first 16 bits and the PHY address
> > > > + * right after.
> > > > + */
> > > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > > 
> > > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > > and then 16 bits of register address - significant in that order. Can
> > > we adjust the mask for the PHY address later to add the MMD between
> > > the PHY address and register number?
> > >
> > 
> > Honestly to future proof this, I think a good idea might be to add
> > helper to encode these info and use Clause 45 format even for C22.
> > Maybe we can use an extra bit to signal if the format is C22 or C45.
> > 
> > BIT(26) 0: C22 1:C45
> > GENMASK(25, 21) PHY ADDR
> > GENMASK(20, 16) MMD ADDR
> > GENMASK(15, 0) REG
> 
> If you look back at older kernels, there was some helpers to do
> something like this, but the C22/C45 was in bit 31. When i cleaned up
> MDIO drivers to have separate C22 and C45 read/write functions, they
> become redundant and they were removed. You might want to bring them
> back again.

I'd prefer we didn't bring that abomination back. The detail about how
things are stored in regmap should be internal within regmap, and I
think it would be better to have an API presented that takes sensible
parameters, rather than something that's been encoded.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From pr-tracker-bot at kernel.org  Fri Mar 14 14:03:41 2025
From: pr-tracker-bot at kernel.org (pr-tracker-bot at kernel.org)
Date: Fri, 14 Mar 2025 21:03:41 +0000
Subject: [GIT PULL] arm64 fixes for -rc7
In-Reply-To: <20250314160458.GA9438@willie-the-truck>
References: <20250314160458.GA9438@willie-the-truck>
Message-ID: <174198622151.2382486.16421451040430592857.pr-tracker-bot@kernel.org>

The pull request you sent on Fri, 14 Mar 2025 16:04:59 +0000:

> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/ef9248676f81c0342d6e8f90a380a9e0b8c25280

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


From robh at kernel.org  Fri Mar 14 14:06:52 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 14 Mar 2025 16:06:52 -0500
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
Message-ID: <20250314210652.GA2300828-robh@kernel.org>

On Wed, Feb 26, 2025 at 03:19:14PM +0100, Maud Spierings wrote:
> Add the bindings that describe a GOcontroll Moduline module slot. This
> slot provides all the interfaces to interface with a Moduline compatible
> IO module. The actual module is not reasonable to describe as it can be
> swapped at will, with this connector the driver will be able to probe
> for a module on boot.
> 
> The connector consists of 2 parts, one part for interfacing with the SoC
> and main board, the other part has 13 IO channels for the module to
> interact with the outside world. The functions of these IO channels are
> determined by the type of module in the slot. The IO on the SoC side is
> as follows:
> 
>  - a 3v3 supply, this tends to be the logic level of the module and its
>    microcontroller
>  - a 5v0 supply, this can be used to power low power peripherals on the
>    module
>  - a 6v-8v supply, this can be used for high power peripherals on the
>    module
>  - a 6v-30v supply, this tends to be a dirty supply that comes from the
>    controller supply after some circuit protection, or is the same as
>    the 6v-8v supply.
>  - an SPI bus which carries the communication between the SoC and the
>    microcontroller on the module.
>  - an I2C bus shared between the SoC and all module slots which can
>    carry direct module-to-module communication.
>  - a reset line
>  - an interrupt line that indicates a clear to transmit signal
>  - a sync line shared between the SoC and all module slots which could
>    be used to synchronize modules for time sensitive IO spread across
>    modules.
>  - a SMBus alert line that is shared between the modules but is not
>    connected to the SoC so that is ignored.
> 
> A slot-number property is used to identify the physical location of a
> module slot. Without it, it would be impossible to identify which module
> to control if there are multiple of one type, to address the desired IO.

Is that for a person to identify slots or s/w? If just a person, we 
generally use 'label' as in a sticker on the connector. If s/w, we 
generally try to avoid made up indexing in DT though there are some 
exceptions.

> 
> Signed-off-by: Maud Spierings <maudspierings at gocontroll.com>
> ---
>  .../connector/gocontroll,moduline-module-slot.yaml | 88 ++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml b/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..a16ae2762d160180d5b163e20f5294235e65053b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml
> @@ -0,0 +1,88 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/connector/gocontroll,moduline-module-slot.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: GOcontroll Moduline Module slot
> +
> +maintainers:
> +  - Maud Spierings <maudspierings at gocontroll.com>
> +
> +description:
> +  The GOcontroll Moduline module slot represents a connector that fullfills the
> +  Moduline slot specification, and can thus house any IO module that is also
> +  built to this spec.
> +
> +properties:
> +  compatible:
> +    const: gocontroll,moduline-module-slot
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    description: indicates readiness, high means busy.
> +    maxItems: 1
> +  reset-gpios:
> +    description: resets the module, active low.
> +    maxItems: 1
> +  sync-gpios:
> +    description: sync line between all module slots.
> +    maxItems: 1
> +
> +  vdd-supply:
> +    description: low power 3v3 supply generally for the microcontroller.
> +  vddp-supply:
> +    description: medium power 5v0 supply for on module low power peripherals.
> +  vddhpp-supply:
> +    description: high power 6v-8v supply for on module high power peripherals.
> +  power-supply:
> +    description: high power 6v-30v supply for high power module circuits.
> +
> +  i2c-bus:
> +    description: i2c bus shared between module slots and the SoC
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  slot-number:
> +    description:
> +      The number of the module slot representing the location of on the pcb.
> +      This enables access to the modules based on slot location.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +
> +  spi-max-frequency: true
> +
> +required:
> +  - compatible
> +  - reg
> +  - reset-gpios
> +  - interrupts
> +  - sync-gpios
> +  - i2c-bus
> +  - slot-number
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    spi {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        connector at 0 {

I find this being a SPI device a bit strange. Is there a defined SPI 
device that every slot is going to have? Or the connector has SPI 
interface and *anything* could be attached on it?

> +            reg = <0>;
> +            compatible = "gocontroll,moduline-module-slot";
> +            reset-gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
> +            sync-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
> +            interrupt-parent = <&gpio4>;
> +            interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
> +            vdd-supply = <&reg_3v3_per>;
> +            vddp-supply = <&reg_5v0>;
> +            vddhpp-supply = <&reg_6v4>;
> +            i2c-bus = <&i2c2>;
> +            slot-number = <1>;
> +        };
> +    };
> 
> -- 
> 2.48.1
> 


From Thinh.Nguyen at synopsys.com  Fri Mar 14 14:14:25 2025
From: Thinh.Nguyen at synopsys.com (Thinh Nguyen)
Date: Fri, 14 Mar 2025 21:14:25 +0000
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <20250314155706.31058-1-mike.looijmans@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
Message-ID: <20250314211411.l5taj5nysvcalfyz@synopsys.com>

On Fri, Mar 14, 2025, Mike Looijmans wrote:
> Set the gpio to "high" on acquisition, instead of acquiring it in low
> state and then immediately setting it high again. This prevents a
> short "spike" on the reset signal.

How does this affect the current programming flow beside preventing a
spike to the reset signal?

> 
> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> ---
> 
>  drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> index a33a42ba0249..a159a511483b 100644
> --- a/drivers/usb/dwc3/dwc3-xilinx.c
> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>  
>  skip_usb3_phy:
>  	/* ulpi reset via gpio-modepin or gpio-framework driver */
> -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>  	if (IS_ERR(reset_gpio)) {
>  		return dev_err_probe(dev, PTR_ERR(reset_gpio),
>  				     "Failed to request reset GPIO\n");
> @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>  
>  	if (reset_gpio) {
>  		/* Toggle ulpi to reset the phy. */

Does the comment above still apply?

> -		gpiod_set_value_cansleep(reset_gpio, 1);
>  		usleep_range(5000, 10000);

Do we still need this usleep_range here?

BR,
Thinh

>  		gpiod_set_value_cansleep(reset_gpio, 0);
>  		usleep_range(5000, 10000);
> -- 
> 2.43.0
> 
> 
> Met vriendelijke groet / kind regards,
> 
> Mike Looijmans
> System Expert
> 
> 
> TOPIC Embedded Products B.V.
> Materiaalweg 4, 5681 RJ Best
> The Netherlands
> 
> T: +31 (0) 499 33 69 69
> E: mike.looijmans at topic.nl
> W: https://urldefense.com/v3/__http://www.topic.nl__;!!A4F2R9G_pg!dt2SxHPWske2gY2PNQ9GrJEr5lXXkUCMb5CMBd2ymPEYpU1TEemM__y9_6QwiMTyCIX9wXKKAOzhX5Ex5x5FWa1QV5I98u0$ 
> 
> Please consider the environment before printing this e-mail

From ansuelsmth at gmail.com  Fri Mar 14 14:19:29 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Fri, 14 Mar 2025 22:19:29 +0100
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <Z9SZRDykbTwvGW6S@shell.armlinux.org.uk>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
 <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
 <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>
 <0c6cb801-5592-4449-b776-a337161b3326@lunn.ch>
 <Z9SZRDykbTwvGW6S@shell.armlinux.org.uk>
Message-ID: <67d49d64.050a0220.35694d.b7ab@mx.google.com>

On Fri, Mar 14, 2025 at 09:01:56PM +0000, Russell King (Oracle) wrote:
> On Fri, Mar 14, 2025 at 08:41:33PM +0100, Andrew Lunn wrote:
> > On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> > > On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > > > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > > > + * read/write register are encoded in the regmap register
> > > > > + * by placing the register in the first 16 bits and the PHY address
> > > > > + * right after.
> > > > > + */
> > > > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > > > 
> > > > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > > > and then 16 bits of register address - significant in that order. Can
> > > > we adjust the mask for the PHY address later to add the MMD between
> > > > the PHY address and register number?
> > > >
> > > 
> > > Honestly to future proof this, I think a good idea might be to add
> > > helper to encode these info and use Clause 45 format even for C22.
> > > Maybe we can use an extra bit to signal if the format is C22 or C45.
> > > 
> > > BIT(26) 0: C22 1:C45
> > > GENMASK(25, 21) PHY ADDR
> > > GENMASK(20, 16) MMD ADDR
> > > GENMASK(15, 0) REG
> > 
> > If you look back at older kernels, there was some helpers to do
> > something like this, but the C22/C45 was in bit 31. When i cleaned up
> > MDIO drivers to have separate C22 and C45 read/write functions, they
> > become redundant and they were removed. You might want to bring them
> > back again.
> 
> I'd prefer we didn't bring that abomination back. The detail about how
> things are stored in regmap should be internal within regmap, and I
> think it would be better to have an API presented that takes sensible
> parameters, rather than something that's been encoded.
>

Well problem is that regmap_write and regmap_read will take max 2 value
at the very end (reg and value) so it's really a matter of making the
encoding part internal but encoding it can't be skipped.

You are suggesting to introduce additional API like

mdio_regmap_write(regmap, phy, addr, val);
mdio_mmd_regmap_write(regmap, phy, mmd, addr, val);

And the encoding is done internally?

My concern is the decoding part from the .write/read_bits regmap OPs.
I guess for that also some helper should be exposed (to keep the
decoding/encoding internal to the driver and not expose the
_abomination_)

What do you think?

-- 
	Ansuel


From dianders at chromium.org  Fri Mar 14 14:58:36 2025
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 14 Mar 2025 14:58:36 -0700
Subject: [PATCH 1/8] dt-bindings: HID: i2c-hid: elan: Introduce Elan eKTH8D18
In-Reply-To: <20250312104344.3084425-2-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org> <20250312104344.3084425-2-wenst@chromium.org>
Message-ID: <CAD=FV=X14XEdikE3hP4y53uZec12O_ZPtU+GyJ+Tf8R3DK89AA@mail.gmail.com>

Hi,


On Wed, Mar 12, 2025 at 3:43?AM Chen-Yu Tsai <wenst at chromium.org> wrote:
>
> The Elan eKTH8D18 touchscreen controller is an I2C HID device with a
> longer boot-up time. Power sequence timing wise it is compatible with
> the eKTH6A12NAY, with a power-on delay of at least 5ms, 20ms
> out-of-reset for I2C ack response, and 150ms out-of-reset for I2C HID
> enumeration. Enumeration and subsequent operation follows the I2C HID
> standard. The eKTH6A12NAY requires longer times for both parts.

Somehow the last sentence above confused me. Can it just be dropped?
All you care about is that the new trackpad matches the timings for
"eKTH6A12NAY". Not sure what you mean by "eKTH6A12NAY" needing
"longer" timings.


> Add a compatible string for it with the ekth6a12nay one as a fallback.
>
> Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
> ---
>  .../bindings/input/elan,ekth6915.yaml         | 29 ++++++++++++++++---
>  1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> index cb3e1801b0d3..81c391952ccc 100644
> --- a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> +++ b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> @@ -4,14 +4,14 @@
>  $id: http://devicetree.org/schemas/input/elan,ekth6915.yaml#
>  $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Elan eKTH6915 touchscreen controller
> +title: Elan I2C-HID touchscreen controllers
>
>  maintainers:
>    - Douglas Anderson <dianders at chromium.org>
>
>  description:
> -  Supports the Elan eKTH6915 touchscreen controller.
> -  This touchscreen controller uses the i2c-hid protocol with a reset GPIO.
> +  Supports the Elan eKTH6915 and other I2C-HID touchscreen controllers.
> +  These touchscreen controller use the i2c-hid protocol with a reset GPIO.
>
>  allOf:
>    - $ref: /schemas/input/touchscreen/touchscreen.yaml#
> @@ -23,12 +23,18 @@ properties:
>            - enum:
>                - elan,ekth5015m
>            - const: elan,ekth6915
> +      - items:
> +          - enum:
> +              - elan,ekth8d18
> +          - const: elan,ekth6a12nay

The "enum" above is weird, but it matches what we did for
"elan,ekth5015m" so I guess it's fine? I'd leave it up to bindings
maintainers. I guess the assumption is that we might add additional
touchscreens to the list...


>    reg:
> -    const: 0x10
> +    enum:
> +      - 0x10
> +      - 0x16

Again happy to leave it to the bindings maintainers, but _maybe_ just
drop the "reg" parts here and below. It doesn't really have to be part
of the bindings.


From helgaas at kernel.org  Fri Mar 14 15:10:59 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri, 14 Mar 2025 17:10:59 -0500
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <Z9RJbyoFdkiYHXu9@lizhi-Precision-Tower-5810>
Message-ID: <20250314221059.GA806127@bhelgaas>

On Fri, Mar 14, 2025 at 11:21:19AM -0400, Frank Li wrote:
> On Thu, Mar 13, 2025 at 06:56:17PM -0400, Frank Li wrote:
> > On Thu, Mar 13, 2025 at 05:04:50PM -0500, Bjorn Helgaas wrote:
> > > On Thu, Mar 13, 2025 at 11:38:42AM -0400, Frank Li wrote:
> > > > The 'ranges' property at PCI controller parent bus can indicate address
> > > > translation information. Most system's bus fabric use 1:1 map between input
> > > > and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.
> > >
> > > I think you've used reg["addr_space"] to get the offset for Endpoints
> > > forever.
> >
> > Yes, it still need ranges informaiton at parent bus.
> >
> > 	bus at 000
> > 	{
> > 		ranges = <...>; [1] /* still need this */
> > 		pcie {
> > 			ranges = <...>;[2]
> > 		};
> > 		pcie-ep {};
> > 	}

Yes, of course. I'm just making the point that the subject/commit log
says this patch uses 'ranges' but in fact it uses 'reg'.

> > > I just noticed that through v9, you used 'ranges' to get the offset
> > > for the Root Complex (with "Add parent_bus_offset to resource_entry"),
> > > and I think v10 switched to use reg["config"] instead.
> > >
> > > I think I originally proposed the idea of "Add parent_bus_offset to
> > > resource_entry" patch, but I think it turned out to be kind of an ugly
> > > approach.
> > >
> > > Anyway, IIUC this v11 patch actually uses reg["config"] to compute the
> > > offset, not 'ranges', so we should probably update the subject and
> > > commit log to reflect that, and maybe remove the now-unused bits of
> > > the devicetree example.
> >
> > We use reg["config"] to detect offset, but still need parent dts's ranges.
> > There are two ranges, one is at parent pci bus [1], the other is under
> > 'pci bus' [2].
> 
> Beside, luckly dwc use reg["config"] to indicate config space. but dt also
> define ranges [2] under pcie node, which can also include 'config's space.
> 
> cadence also use reg["cfg"] to do that.
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
> 
> I am not sure why both choose use reg[] instead of [2]ranges under
> pcie node. But the result make our situation simpler.
> 
> > Although use reg["config"], but still need ranges [1]. And information at
> > ranges [2] also need be correct.
> >
> > The whole devicetree example also validate to help write address translate
> > informaiton.
> >
> > > I do worry a little bit about the assumption that the offset of
> > > reg["config"] is the same as the offset of the other pieces.  The main
> > > place we use the offset on RCs is for the ATU, and isn't the ATU in
> > > the MemSpace area at 0x8000_0000 below?
> >
> > No, "Bus fabric" only decode input address from "0x7000_0000..UPLIMIT".
> > Then output address to 0x8000_0000..UPLIMIT. So below 0x8000_0000 never
> > happen.

Minor miscommunication, I think.   I didn't mean there were addresses
smaller than 0x8000_0000; I meant that in the picture, MemSpace at
0x8000_0000 is below CfgSpace at 0x8ff0_0000.  The important point is
that CfgSpace is a separate region from MemSpace, and we're applying
the CfgSpace offset to the ATU in MemSpace.

I think it's OK to assume that for now.  AFAICS there is nothing in
devicetree that explicitly mentions the ATU input address space; it's
just implicitly part of the intermediate address space described by
the bus at 5f000000 'ranges'.

> > > It's great that in this case the 0x7ff0_0000 to 0x8ff0_0000 "config"
> > > offset is the same as the 0x7000_0000 to 0x8000_0000 MemSpace offset,
> > > but I don't know that this is guaranteed for all designs.
> >
> > So far, it is the same for use dwc chips. If we meet difference, we can
> > add later.
> >
> > reg["config"] only simplied our implement base on the offset is the same.
> > But whole concept is unchanged.

> > > > See below diagram:
> > > >
> > > >             ???????????                    ??????????????
> > > >  ???????    ?         ? IA: 0x8ff8_0000    ?            ?
> > > >  ? CPU ??????   ?????????????????????????  ? PCI        ?
> > > >  ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
> > > >   CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
> > > > 0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
> > > >             ?      ?  ?             ?   ?  ?            ?   PCI Addr
> > > > 0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
> > > >             ?         ?             ?      ?            ?    0
> > > > 0x7000_0000??????????????????????   ?      ?            ?
> > > >             ???????????         ?   ???????? CfgSpace  ???????????????
> > > >              BUS Fabric         ?          ?            ?    0
> > > >                                 ?          ?            ?
> > > >                                 ???????????? MemSpace  ???????????????
> > > >                         IA: 0x8000_0000    ?            ?  0x8000_0000
> > > >                                            ??????????????
> > > >
> > > > bus at 5f000000 {
> > > > 	compatible = "simple-bus";
> > > > 	#address-cells = <1>;
> > > > 	#size-cells = <1>;
> > > > 	ranges = <0x80000000 0x0 0x70000000 0x10000000>;
> > > >
> > > > 	pcie at 5f010000 {
> > > > 		compatible = "fsl,imx8q-pcie";
> > > > 		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> > > > 		reg-names = "dbi", "config";

> > > > 		#address-cells = <3>;
> > > > 		#size-cells = <2>;
> > > > 		device_type = "pci";
> > > > 		bus-range = <0x00 0xff>;
> > > > 		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> > > > 			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;

Of course we need this 'ranges' to describe the translation between
intermediate addresses and PCI bus addresses.  My point is that this
is not relevant to the parent bus offset we're computing in this
patch.

So I think for purposes of this patch, we can omit pcie at 5f010000
#address-cells and everything after it.

Bjorn


From linux at armlinux.org.uk  Fri Mar 14 15:25:22 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 14 Mar 2025 22:25:22 +0000
Subject: [net-next PATCH v12 07/13] net: mdio: regmap: add support for
 multiple valid addr
In-Reply-To: <67d49d64.050a0220.35694d.b7ab@mx.google.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-8-ansuelsmth@gmail.com>
 <Z83RsW1_bzoEWheo@shell.armlinux.org.uk>
 <67cdd3c9.df0a0220.1c827e.b244@mx.google.com>
 <0c6cb801-5592-4449-b776-a337161b3326@lunn.ch>
 <Z9SZRDykbTwvGW6S@shell.armlinux.org.uk>
 <67d49d64.050a0220.35694d.b7ab@mx.google.com>
Message-ID: <Z9Ss0qrxCcEbyJY7@shell.armlinux.org.uk>

On Fri, Mar 14, 2025 at 10:19:29PM +0100, Christian Marangi wrote:
> On Fri, Mar 14, 2025 at 09:01:56PM +0000, Russell King (Oracle) wrote:
> > I'd prefer we didn't bring that abomination back. The detail about how
> > things are stored in regmap should be internal within regmap, and I
> > think it would be better to have an API presented that takes sensible
> > parameters, rather than something that's been encoded.
> 
> Well problem is that regmap_write and regmap_read will take max 2 value
> at the very end (reg and value) so it's really a matter of making the
> encoding part internal but encoding it can't be skipped.
> 
> You are suggesting to introduce additional API like
> 
> mdio_regmap_write(regmap, phy, addr, val);
> mdio_mmd_regmap_write(regmap, phy, mmd, addr, val);
> 
> And the encoding is done internally?

Yes, because littering drivers with the details of the conversion is
unreasonable.

> My concern is the decoding part from the .write/read_bits regmap OPs.
> I guess for that also some helper should be exposed (to keep the
> decoding/encoding internal to the driver and not expose the
> _abomination_)

Sadly, I don't think that's something we can get away from, but we
should make it _easy_ for people to get it right.

>From what I remember from the days of shoe-horning C45 into the C22
MDIO API, encoding and/or decoding addresses was buggy because people
would use the wrong encoders and decoders.

For example, we had MDIO drivers using mdio_phy_id_is_c45() to test
whether the access being requested was C45 - mdio_phy_id_is_c45() is
for the _userspace_ MII API encoding (struct mii_ioctl_data), not the
kernel space. Kernel space used:

-#define MII_ADDR_C45 (1<<30)
-#define MII_DEVADDR_C45_SHIFT  16
-#define MII_REGADDR_C45_MASK   GENMASK(15, 0)

to encode into the register number argument vs the userspace encoding
into the phy_id member of struct mii_ioctl_data:

#define MDIO_PHY_ID_C45                 0x8000
#define MDIO_PHY_ID_PRTAD               0x03e0
#define MDIO_PHY_ID_DEVAD               0x001f

which is what the mdio_phy_id_*() accessors are using. The two
approaches are incompatible, and using the userspace one in a MDIO
driver wasn't going to work correctly - but people did it.

This is one of the reasons I hated the old MDIO API, and why we now
have separate C22 and C45 interfaces in the driver code.

This is exactly why I don't like reintroducing a new set of "massage
the package, mmd and address into some single integer representation"
and "decode a single integer into their respective parts" - we've
been here before, it's lead to problems because driver authors can't
grasp what the right approach is, and it results in bugs.

Given the history here, my personal opinion would be... if regmap can't
cope with MDIO devices having a three-part address without requiring
callers to flatten it first, and then have various regmap drivers
unflatten it, then regmap is unsuitable to be used with MDIO and ought
not be used.

So, this encoding/decoding is a problem that should be solved entirely
within regmap, and not spread out into users of regmap and drivers
behind regmap. Anything else is, IMHO, insane.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From eddyz87 at gmail.com  Fri Mar 14 15:47:00 2025
From: eddyz87 at gmail.com (Eduard Zingerman)
Date: Fri, 14 Mar 2025 15:47:00 -0700
Subject: [PATCH bpf-next 01/11] bpf: Move insn if/else into
 do_check_insn()
In-Reply-To: <20250313172127.1098195-2-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	 <20250313172127.1098195-2-luis.gerhorst@fau.de>
Message-ID: <293dbe3950a782b8eb3b87b71d7a967e120191fd.camel@gmail.com>

On Thu, 2025-03-13 at 18:21 +0100, Luis Gerhorst wrote:
> This is required to catch the errors later and fall back to a nospec if
> on a speculative path.
> 
> Move code into do_check_insn(), replace
> * "continue" with "return INSN_IDX_MODIFIED"
> * "goto process_bpf_exit" with "return PROCESS_BPF_EXIT"
> * "do_print_state = " with "*do_print_state = "
> 
> Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
> Acked-by: Henriette Herzog <henriette.herzog at rub.de>
> Cc: Maximilian Ott <ott at cs.fau.de>
> Cc: Milan Stephan <milan.stephan at fau.de>
> ---

This refactoring is a long overdue, thank you!
A few nits below.

[...]

> +		err = do_check_insn(env, insn, pop_log, &do_print_state, regs, state,
> +				    &prev_insn_idx);

- `regs` remains declared in do_check(), while nothing prevents
  pushing its declaration to do_check_insn().
- `state` is `env->cur_state`, so I'd avoid passing it as a parameter
  (just to reduce count);
- `prev_insn_idx` is unused by `do_check_insn`;
- `pop_log` is not used by `do_check_insn`;
- given that `insn` is presumed to correspond to `env->insn_idx` in
  many places down the stack not sure about this parameter.

> +		if (err < 0) {
> +			return err;
> +		} else if (err == INSN_IDX_MODIFIED) {

Also, I'd get rid of `INSN_IDX_MODIFIED` and move `env->insn_idx++`
into `do_check_insn()`. This would save a few mental cycles when
looking at the code with full patch-set applied:

		} else if (err == INSN_IDX_MODIFIED) {
			continue;
		} else if (err == PROCESS_BPF_EXIT) {
			goto process_bpf_exit;
		}
		WARN_ON_ONCE(err);

		if (state->speculative && cur_aux(env)->nospec_result) {
			... bunch of actions ...
		}

		env->insn_idx++;

One needs to stop for a moment and think why "bunch of actions" is
performed for regular index increment, but not for INSN_IDX_MODIFIED.

> +			continue;
> +		} else if (err == PROCESS_BPF_EXIT) {

[...]



From qasdev00 at gmail.com  Fri Mar 14 16:01:02 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Fri, 14 Mar 2025 23:01:02 +0000
Subject: [PATCH] iommu: apple-dart: fix potential null pointer deref
Message-ID: <20250314230102.11008-1-qasdev00@gmail.com>

If kzalloc() fails, accessing cfg->supports_bypass causes a null pointer dereference. 

Fix by checking for NULL immediately after allocation and returning -ENOMEM.

Fixes: 3bc0102835f6 ("iommu: apple-dart: Allow mismatched bypass support")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/iommu/apple-dart.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 13ccb801f52a..e13501541fdd 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -797,12 +797,11 @@ static int apple_dart_of_xlate(struct device *dev,
 
 	if (!cfg) {
 		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
-
+		if (!cfg)
+			return -ENOMEM;
 		/* Will be ANDed with DART capabilities */
 		cfg->supports_bypass = true;
 	}
-	if (!cfg)
-		return -ENOMEM;
 	dev_iommu_priv_set(dev, cfg);
 
 	cfg_dart = cfg->stream_maps[0].dart;
-- 
2.39.5



From oliver.upton at linux.dev  Fri Mar 14 16:11:40 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Fri, 14 Mar 2025 16:11:40 -0700
Subject: [PATCH v3 0/4] KVM: arm64: Fix initializing HCRX_EL2 and other traps in pKVM
In-Reply-To: <20250314111832.4137161-1-tabba@google.com>
References: <20250314111832.4137161-1-tabba@google.com>
Message-ID: <174199388872.1347355.17256091490684730021.b4-ty@linux.dev>

On Fri, 14 Mar 2025 11:18:28 +0000, Fuad Tabba wrote:
> Changes since v2 [1]:
> - Remove WRITE_ONCE when setting hyp handle (Quentin)
> - Rebase on Linux 6.14-rc6
> 
> For context, please refer to v1 [2].
> 
> Cheers,
> /fuad
> 
> [...]

Applied to next, thanks!

[1/4] KVM: arm64: Factor out setting HCRX_EL2 traps into separate function
      https://git.kernel.org/kvmarm/kvmarm/c/44f979bf434e
[2/4] KVM: arm64: Initialize HCRX_EL2 traps in pKVM
      https://git.kernel.org/kvmarm/kvmarm/c/066daa8d3bc2
[3/4] KVM: arm64: Factor out pKVM hyp vcpu creation to separate function
      https://git.kernel.org/kvmarm/kvmarm/c/8b21fb47c778
[4/4] KVM: arm64: Create each pKVM hyp vcpu after its corresponding host vcpu
      https://git.kernel.org/kvmarm/kvmarm/c/1eab115486c5

--
Best,
Oliver


From oliver.upton at linux.dev  Fri Mar 14 16:11:41 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Fri, 14 Mar 2025 16:11:41 -0700
Subject: [PATCH v4 0/3] Count pKVM stage-2 usage in secondary pagetable stat
In-Reply-To: <20250313114038.1502357-1-vdonnefort@google.com>
References: <20250313114038.1502357-1-vdonnefort@google.com>
Message-ID: <174199388869.1347355.3257172566547296474.b4-ty@linux.dev>

On Thu, 13 Mar 2025 11:40:35 +0000, Vincent Donnefort wrote:
> This series allows to count stage-2 related memory when using pKVM. The
> value can be found in the /proc/meminfo field SecPageTables.
> 
> Changes since v3: https://lore.kernel.org/all/20250307113411.469018-1-vdonnefort at google.com/
>   - Remove unnecessary void * cast (Marc)
>   - Rename reclaim_guest_pages() -> reclaim_pgtable_pages() (Marc)
>   - Remove unnecessary PAGE_ALIGN(pgd_sz)
> 
> [...]

Applied to next, thanks!

[1/3] KVM: arm64: Add flags to kvm_hyp_memcache
      https://git.kernel.org/kvmarm/kvmarm/c/cf2d228da9a8
[2/3] KVM: arm64: Distinct pKVM teardown memcache for stage-2
      https://git.kernel.org/kvmarm/kvmarm/c/8c0d7d14c5cd
[3/3] KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats
      https://git.kernel.org/kvmarm/kvmarm/c/79ea66231599

--
Best,
Oliver


From alyssa at rosenzweig.io  Fri Mar 14 16:23:16 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Fri, 14 Mar 2025 19:23:16 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
Message-ID: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>

This adds the UAPI for the Asahi driver targeting the GPU in the Apple
M1 and M2 series systems on chip. The UAPI design is based on other
modern Vulkan-capable drivers, including Xe and Panthor. Memory
management is based on explicit VM management. Synchronization is
exclusively explicit sync.

This UAPI is validated against our open source Mesa stack, which is
fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
VM_BIND mechanism.

This patch adds the standalone UAPI header. It is implemented by an open
source DRM driver written in Rust. We fully intend to upstream this
driver when possible. However, as a production graphics driver, it
depends on a significant number of Rust abstractions that will take a
long time to upstream. In the mean time, our userspace is upstream in
Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
yet reviewed and merged in the upstream kernel. Although we ship a
patched Mesa in Fedora Asahi Remix, any containers shipping upstream
Mesa builds are broken for our users, including upstream Flatpak and
Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
and virglrenderer, which complicates bisects.

The intention in sending out this patch is for this UAPI to be
thoroughly reviewed. Once we as the DRM community are satisfied with the
UAPI, this header lands signifying that the UAPI is stable and must only
be evolved in backwards-compatible ways; it will be the UAPI implemented
in the DRM driver that eventually lands upstream. That promise lets us
enable upstream Mesa, solving all these issues while the upstream Rust
abstractions are developed.

https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v3 contains
the DRM driver implementing this proposed UAPI.

https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains
the Mesa patches to implement this proposed UAPI. It is mirrored at
https://github.com/alyssarosenzweig/mesa/tree/agx-uapi-v3 to allow
continued review during upcoming gitlab.freedesktop.org downtime.

That Linux and Mesa branch together give a complete graphics/compute
stack on top of this UAPI.

Co-developed-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
Changes in v3:
- Merge load/store/partial fields for depth/stencil as discussed with
  Faith. This shrinks the submit a lot with little loss of
  functionality. There's maaaybe a use case for splitting out depth load
  base (only) later. But it's easier to add uAPI than remove it!
- Make usc_exec_base per-queue instead of per-command. No use case for
  doing it finer grained, and this shrinks the submits and simplifies
  userspace handling.
- Improve descriptions.
- Reorder/shrink fields to remove padding.
- Use full names for vdm/cdm_ctrl_stream_base
- Link to v2: https://lore.kernel.org/r/20250313-agx-uapi-v2-1-59cc53a59ea3 at rosenzweig.io

Changes in v2:
- Flatten submits. Previously, the submit ioctl pointed to an array of
  command structures, which each pointed to separate payload structures,
  which pointed to attachment structures. This is a lot of indirection,
  which complicates greatly virtgpu. In the new approach, the submit
  ioctl points to a single contiguous blob of plain-old-data, no CPU
  pointers, copied from userspace in one go and suitable as virtgpu wire
  protocol.
- Remove vm_page_size, userspace has to hardcode it anyway.
- Turn random #defines into enums for better kernel doc, etc.
- Improve comments, particularly around barriers[].
- Rename various flags/fields to better match canonical names when known
  (a lot of the names are pulled from the drivers/gpu/drm/imagination,
  naturally).
- Drop unnecessary encoder_id, cmd_id handles.
- Fix padding in submit ioctl (thanks Ryan).
- Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io
---
 Documentation/gpu/driver-uapi.rst |    5 +
 MAINTAINERS                       |    1 +
 include/uapi/drm/asahi_drm.h      | 1123 +++++++++++++++++++++++++++++++++++++
 3 files changed, 1129 insertions(+)

diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
--- a/Documentation/gpu/driver-uapi.rst
+++ b/Documentation/gpu/driver-uapi.rst
@@ -27,3 +27,8 @@ drm/xe uAPI
 ===========
 
 .. kernel-doc:: include/uapi/drm/xe_drm.h
+
+drm/asahi uAPI
+================
+
+.. kernel-doc:: include/uapi/drm/asahi_drm.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2256,6 +2256,7 @@ F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
 F:	include/linux/soc/apple/*
+F:	include/uapi/drm/asahi_drm.h
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson at axis.com>
diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
new file mode 100644
index 0000000000000000000000000000000000000000..8954e71f0592c09c84da1b0783d973e0637b5559
--- /dev/null
+++ b/include/uapi/drm/asahi_drm.h
@@ -0,0 +1,1123 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) The Asahi Linux Contributors
+ * Copyright (C) 2018-2023 Collabora Ltd.
+ * Copyright (C) 2014-2018 Broadcom
+ */
+#ifndef _ASAHI_DRM_H_
+#define _ASAHI_DRM_H_
+
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * DOC: Introduction to the Asahi UAPI
+ *
+ * This documentation describes the Asahi IOCTLs.
+ *
+ * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
+ * from Panthor):
+ *
+ * - Structures must be aligned on 64-bit/8-byte. If the object is not
+ *   naturally aligned, a padding field must be added.
+ * - Fields must be explicitly aligned to their natural type alignment with
+ *   pad[0..N] fields.
+ * - All padding fields will be checked by the driver to make sure they are
+ *   zeroed.
+ * - Flags can be added, but not removed/replaced.
+ * - New fields can be added to the main structures (the structures
+ *   directly passed to the ioctl). Those fields can be added at the end of
+ *   the structure, or replace existing padding fields. Any new field being
+ *   added must preserve the behavior that existed before those fields were
+ *   added when a value of zero is passed.
+ * - New fields can be added to indirect objects (objects pointed by the
+ *   main structure), iff those objects are passed a size to reflect the
+ *   size known by the userspace driver (see
+ *   drm_asahi_command::cmd_buffer_size).
+ * - If the kernel driver is too old to know some fields, those will be
+ *   ignored if zero, and otherwise rejected (and so will be zero on output).
+ * - If userspace is too old to know some fields, those will be zeroed
+ *   (input) before the structure is parsed by the kernel driver.
+ * - Each new flag/field addition must come with a driver version update so
+ *   the userspace driver doesn't have to trial and error to know which
+ *   flags are supported.
+ * - Structures should not contain unions, as this would defeat the
+ *   extensibility of such structures.
+ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
+ *   at the end of the drm_asahi_ioctl_id enum.
+ */
+
+/**
+ * enum drm_asahi_ioctl_id - IOCTL IDs
+ *
+ * Place new ioctls at the end, don't re-order, don't replace or remove entries.
+ *
+ * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
+ * definitions instead.
+ */
+enum drm_asahi_ioctl_id {
+	/** @DRM_ASAHI_GET_PARAMS: Query device properties. */
+	DRM_ASAHI_GET_PARAMS = 0,
+
+	/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
+	DRM_ASAHI_VM_CREATE,
+
+	/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
+	DRM_ASAHI_VM_DESTROY,
+
+	/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
+	DRM_ASAHI_GEM_CREATE,
+
+	/**
+	 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
+	 * given GEM handle.
+	 */
+	DRM_ASAHI_GEM_MMAP_OFFSET,
+
+	/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
+	DRM_ASAHI_GEM_BIND,
+
+	/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
+	DRM_ASAHI_QUEUE_CREATE,
+
+	/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
+	DRM_ASAHI_QUEUE_DESTROY,
+
+	/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
+	DRM_ASAHI_SUBMIT,
+
+	/** @DRM_ASAHI_GET_TIME: Query device time. */
+	DRM_ASAHI_GET_TIME,
+
+	/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
+	DRM_ASAHI_GEM_BIND_OBJECT,
+};
+
+#define DRM_ASAHI_MAX_CLUSTERS	64
+
+/**
+ * struct drm_asahi_params_global - Global parameters.
+ *
+ * This struct may be queried by drm_asahi_get_params.
+ */
+struct drm_asahi_params_global {
+	/** @features: Feature bits from drm_asahi_feature */
+	__u64 features;
+
+	/** @gpu_generation: GPU generation, e.g. 13 for G13G */
+	__u32 gpu_generation;
+
+	/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
+	__u32 gpu_variant;
+
+	/**
+	 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
+	 * 0x21 for 'C1'
+	 */
+	__u32 gpu_revision;
+
+	/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
+	__u32 chip_id;
+
+	/** @num_dies: Number of dies in the SoC */
+	__u32 num_dies;
+
+	/** @num_clusters_total: Number of GPU clusters (across all dies) */
+	__u32 num_clusters_total;
+
+	/**
+	 * @num_cores_per_cluster: Number of logical cores per cluster
+	 * (including inactive/nonexistent)
+	 */
+	__u32 num_cores_per_cluster;
+
+	/** @num_frags_per_cluster: Number of frags per cluster */
+	__u32 num_frags_per_cluster;
+
+	/** @num_gps_per_cluster: Number of GPs per cluster */
+	__u32 num_gps_per_cluster;
+
+	/** @max_power_mw: Maximum GPU power consumption */
+	__u32 max_power_mw;
+
+	/** @core_masks: Bitmask of present/enabled cores per cluster */
+	__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
+
+	/** @timer_frequency_hz: Clock frequency for timestamps */
+	__u64 timer_frequency_hz;
+
+	/** @min_frequency_khz: Minimum GPU core clock frequency */
+	__u32 min_frequency_khz;
+
+	/** @max_frequency_khz: Maximum GPU core clock frequency */
+	__u32 max_frequency_khz;
+
+	/** @vm_user_start: VM user range start VMA */
+	__u64 vm_user_start;
+
+	/** @vm_user_end: VM user range end VMA */
+	__u64 vm_user_end;
+
+	/**
+	 * @vm_kernel_min_size: Minimum kernel VMA window size within user
+	 * range
+	 */
+	__u64 vm_kernel_min_size;
+
+	/**
+	 * @max_commands_per_submission: Maximum number of supported commands
+	 * per submission
+	 */
+	__u32 max_commands_per_submission;
+
+	/**
+	 * @max_attachments: Maximum number of drm_asahi_attachment's per
+	 * command
+	 */
+	__u32 max_attachments;
+
+	/**
+	 * @firmware_version: GPU firmware version, as 4 integers
+	 */
+	__u32 firmware_version[4];
+
+	/**
+	 * @user_timestamp_frequency_hz: Timebase frequency for user timestamps
+	 */
+	__u64 user_timestamp_frequency_hz;
+};
+
+/**
+ * enum drm_asahi_feature - Feature bits
+ *
+ * This covers only features that userspace cannot infer from the architecture
+ * version. Most features don't need to be here.
+ */
+enum drm_asahi_feature {
+	/**
+	 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
+	 * loads of unmapped memory will return zero. Shader stores to unmapped
+	 * memory will be silently discarded. Note that only shader load/store
+	 * is affected. Other hardware units are not affected, notably including
+	 * texture sampling.
+	 */
+	DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
+};
+
+/**
+ * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
+ */
+struct drm_asahi_get_params {
+	/** @param_group: Parameter group to fetch (MBZ) */
+	__u32 param_group;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @pointer: User pointer to write parameter struct */
+	__u64 pointer;
+
+	/** @size: Size of user buffer, max size supported on return */
+	__u64 size;
+};
+
+/**
+ * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
+ */
+struct drm_asahi_vm_create {
+	/** @kernel_start: Start of the kernel-reserved address range */
+	__u64 kernel_start;
+
+	/** @kernel_end: End of the kernel-reserved address range */
+	__u64 kernel_end;
+
+	/** @vm_id: Returned VM ID */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
+ */
+struct drm_asahi_vm_destroy {
+	/** @vm_id: VM ID to be destroyed */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_gem_flags - Flags for GEM creation
+ */
+enum drm_asahi_gem_flags {
+	/**
+	 * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
+	 *
+	 * Map as writeback instead of write-combine. This optimizes for CPU
+	 * reads.
+	 */
+	DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
+
+	/**
+	 * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
+	 */
+	DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
+};
+
+/**
+ * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
+ */
+struct drm_asahi_gem_create {
+	/** @size: Size of the BO */
+	__u64 size;
+
+	/** @flags: Combination of drm_asahi_gem_flags flags. */
+	__u32 flags;
+
+	/**
+	 * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
+	 */
+	__u32 vm_id;
+
+	/** @handle: Returned GEM handle for the BO */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_gem_mmap_offset - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
+ */
+struct drm_asahi_gem_mmap_offset {
+	/** @handle: Handle for the object being mapped. */
+	__u32 handle;
+
+	/** @flags: Must be zero */
+	__u32 flags;
+
+	/** @offset: The fake offset to use for subsequent mmap call */
+	__u64 offset;
+};
+
+/**
+ * enum drm_asahi_bind_op - Bind operation
+ */
+enum drm_asahi_bind_op {
+	/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
+	DRM_ASAHI_BIND_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
+	DRM_ASAHI_BIND_OP_UNBIND = 1,
+
+	/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */
+	DRM_ASAHI_BIND_OP_UNBIND_ALL = 2,
+};
+
+/**
+ * enum drm_asahi_bind_flags - Flags for GEM binding
+ */
+enum drm_asahi_bind_flags {
+	/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
+	DRM_ASAHI_BIND_READ = (1L << 0),
+
+	/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
+	DRM_ASAHI_BIND_WRITE = (1L << 1),
+
+	/**
+	 * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
+	 * across the VA range.
+	 *
+	 * This is useful to fill a VA range with scratch pages or zero pages.
+	 * It is intended as a mechanism to accelerate sparse.
+	 */
+	DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
+};
+
+/**
+ * struct drm_asahi_gem_bind - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND
+ */
+struct drm_asahi_gem_bind {
+	/** @op: Bind operation (enum drm_asahi_bind_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/**
+	 * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
+	 */
+	__u64 range;
+
+	/** @addr: Address to bind to (BIND or UNBIND only) */
+	__u64 addr;
+};
+
+/**
+ * enum drm_asahi_bind_object_op - Special object bind operation
+ */
+enum drm_asahi_bind_object_op {
+	/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
+};
+
+/**
+ * enum drm_asahi_bind_object_flags - Special object bind flags
+ */
+enum drm_asahi_bind_object_flags {
+	/**
+	 * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
+	 * buffer.
+	 */
+	DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
+};
+
+/**
+ * struct drm_asahi_gem_bind_object - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
+ */
+struct drm_asahi_gem_bind_object {
+	/** @op: Bind operation (enum drm_asahi_bind_object_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_object_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on (MBZ currently) */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/** @range: Number of bytes to bind/unbind (BIND only) */
+	__u64 range;
+
+	/** @object_handle: Object handle (out for BIND, in for UNBIND) */
+	__u32 object_handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_cmd_type - Command type
+ */
+enum drm_asahi_cmd_type {
+	/**
+	 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
+	 * subqueue. Combined vertex and fragment operation.
+	 *
+	 * Followed by a @drm_asahi_cmd_render payload.
+	 */
+	DRM_ASAHI_CMD_RENDER = 0,
+
+	/**
+	 * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
+	 *
+	 * Followed by a @drm_asahi_cmd_compute payload.
+	 */
+	DRM_ASAHI_CMD_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
+	 * attachments for subsequent vertex shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
+
+	/**
+	 * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
+	 * attachments for subsequent fragment shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
+
+	/**
+	 * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
+	 * attachments for subsequent compute shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
+};
+
+/**
+ * enum drm_asahi_queue_cap - Queue capabilities
+ */
+enum drm_asahi_queue_cap {
+	/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
+	DRM_ASAHI_QUEUE_CAP_RENDER	= (1UL << DRM_ASAHI_CMD_RENDER),
+
+	/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
+	DRM_ASAHI_QUEUE_CAP_COMPUTE	= (1UL << DRM_ASAHI_CMD_COMPUTE),
+};
+
+/**
+ * struct drm_asahi_queue_create - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_CREATE
+ */
+struct drm_asahi_queue_create {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @vm_id: The ID of the VM this queue is bound to */
+	__u32 vm_id;
+
+	/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
+	__u32 queue_caps;
+
+	/** @priority: Queue priority, 0-3 */
+	__u32 priority;
+
+	/** @queue_id: The returned queue ID */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/**
+	 * @usc_exec_base: GPU base address for all USC binaries (shaders) on
+	 * this queue. USC addresses are 32-bit relative to this 64-bit base.
+	 *
+	 * This sets the following registers on all queue commands:
+	 *
+	 *	USC_EXEC_BASE_TA  (vertex)
+	 *	USC_EXEC_BASE_ISP (fragment)
+	 *	USC_EXEC_BASE_CP  (compute)
+	 *
+	 * While the hardware lets us configure these independently per command,
+	 * we do not have a use case for this. Instead, we expect userspace to
+	 * fix a 4GiB VA carveout for USC memory and pass its base address here.
+	 */
+	__u64 usc_exec_base;
+};
+
+/**
+ * struct drm_asahi_queue_destroy - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_DESTROY
+ */
+struct drm_asahi_queue_destroy {
+	/** @queue_id: The queue ID to be destroyed */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_sync_type - Sync item type
+ */
+enum drm_asahi_sync_type {
+	/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
+	DRM_ASAHI_SYNC_SYNCOBJ = 0,
+
+	/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
+	DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
+};
+
+/**
+ * struct drm_asahi_sync - Sync item
+ */
+struct drm_asahi_sync {
+	/** @sync_type: One of drm_asahi_sync_type */
+	__u32 sync_type;
+
+	/** @handle: The sync object handle */
+	__u32 handle;
+
+	/** @timeline_value: Timeline value for timeline sync objects */
+	__u64 timeline_value;
+};
+
+/**
+ * enum drm_asahi_subqueue - Subqueue within a queue
+ */
+enum drm_asahi_subqueue {
+	/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */
+	DRM_ASAHI_SUBQUEUE_RENDER = 0,
+
+	/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */
+	DRM_ASAHI_SUBQUEUE_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2
+	 * for struct alignment
+	 */
+	DRM_ASAHI_SUBQUEUE_COUNT = 2,
+};
+
+/**
+ * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
+ *
+ * This special value may be passed in to drm_asahi_command::barriers[] to
+ * indicate that the respective subqueue should not wait on any previous work.
+ */
+#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
+
+/**
+ * struct drm_asahi_cmd_header - Top level command structure
+ */
+struct drm_asahi_cmd_header {
+	/** @cmd_type: One of drm_asahi_cmd_type */
+	__u16 cmd_type;
+
+	/**
+	 * @size: Size of this command, not including this header.
+	 *
+	 * For hardware commands, this enables extensibility of commands without
+	 * requiring extra command types.  Passing a command that is shorter
+	 * than expected is explicitly allowed for backwards-compatability.
+	 * Truncated fields will be zeroed.
+	 *
+	 * For the synthetic attachment setting commands, this implicitly
+	 * encodes the number of attachments. These commands take multiple
+	 * fixed-size @drm_asahi_attachment structures as their payload, so size
+	 * equals number of attachments * sizeof(struct drm_asahi_attachment).
+	 */
+	__u16 size;
+
+	/**
+	 * @barriers: Array of command indices per subqueue to wait on.
+	 *
+	 * Barriers are indices relative to the beginning of a given submit. A
+	 * barrier of 0 waits on commands submitted to the subqueue in previous
+	 * submit ioctls. A barrier of N waits on N previous commands on the
+	 * subqueue within the current submit ioctl. As a special case, passing
+	 * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the
+	 * subqueue.
+	 *
+	 * Examples:
+	 *
+	 *   (0, 0): This waits on all previous work.
+	 *
+	 *   (NONE, 0): This waits on previously submitted compute commands but
+	 *   does not wait on any render commands.
+	 *
+	 *   (1, NONE): This waits on the first render command in the submit.
+	 *   This only makes sense if there are multiple render commands in the
+	 *   same submit.
+	 *
+	 * Barriers only make sense for hardware commands. Synthetic software
+	 * commands to set attachments must pass (NONE, NONE) here.
+	 */
+	__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT];
+};
+
+/**
+ * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
+ */
+struct drm_asahi_submit {
+	/**
+	 * @in_syncs: An optional array of drm_asahi_sync to wait on before
+	 * starting this job.
+	 */
+	__u64 in_syncs;
+
+	/**
+	 * @out_syncs: An optional array of drm_asahi_sync objects to signal
+	 * upon completion.
+	 */
+	__u64 out_syncs;
+
+	/**
+	 * @cmdbuf: Pointer to the command buffer to submit.
+	 *
+	 * This is a flat command buffer. By design, it contains no CPU
+	 * pointers, which makes it suitable for a virtgpu wire protocol without
+	 * requiring any serializing/deserializing step.
+	 *
+	 * It consists of a series of commands. Each command begins with a
+	 * fixed-size @drm_asahi_cmd_header and is followed by a variable-length
+	 * payload according to the type and size in the header.
+	 */
+	__u64 cmdbuf;
+
+	/** @flags: Flags for command submission (MBZ) */
+	__u32 flags;
+
+	/** @queue_id: The queue ID to be submitted to */
+	__u32 queue_id;
+
+	/**
+	 * @in_sync_count: Number of sync objects to wait on before starting
+	 * this job.
+	 */
+	__u32 in_sync_count;
+
+	/**
+	 * @out_sync_count: Number of sync objects to signal upon completion of
+	 * this job.
+	 */
+	__u32 out_sync_count;
+
+	/** @cmdbuf_size: Command buffer size in bytes */
+	__u32 cmdbuf_size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_attachment - Describe an "attachment".
+ *
+ * Attachments are any memory written by shaders, notably including render
+ * target attachments written by the end-of-tile program. This is purely a hint
+ * about the accessed memory regions. It is optional to specify, which is
+ * fortunate as it cannot be specified precisely with bindless access anyway.
+ * But where possible, it's probably a good idea for userspace to include these
+ * hints, forwarded to the firmware.
+ */
+struct drm_asahi_attachment {
+	/** @pointer: Base address of the attachment */
+	__u64 pointer;
+
+	/** @size: Size of the attachment in bytes */
+	__u64 size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @flags: MBZ */
+	__u32 flags;
+};
+
+enum drm_asahi_render_flags {
+	/**
+	 * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
+	 * memory.
+	 */
+	DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0),
+
+	/**
+	 * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
+	 * This must be set when clearing render targets.
+	 */
+	DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1),
+
+	/**
+	 * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
+	 * cluster (on multicluster GPUs)
+	 *
+	 * This harms performance but can workaround certain sync/coherency
+	 * bugs, and therefore is useful for debugging.
+	 */
+	DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2),
+
+	/**
+	 * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
+	 *
+	 * Graphics specifications contain two alternate formulas for depth
+	 * bias, a float formula used with floating-point depth buffers and an
+	 * integer formula using with unorm depth buffers. This flag specifies
+	 * that the integer formula should be used. If omitted, the float
+	 * formula is used instead.
+	 *
+	 * This corresponds to bit 18 of the relevant hardware control register,
+	 * so we match that here for efficiency.
+	 */
+	DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18),
+};
+
+/**
+ * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
+ *
+ * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit.
+ * There are three hardware registers for each field respectively for loads,
+ * stores, and partial renders. In practice, it makes sense to set all to the
+ * same values, except in exceptional cases not yet implemented in userspace, so
+ * we do not duplicate here for simplicity/efficiency.
+ */
+struct drm_asahi_zls_buffer {
+	/** @base: Base address of the buffer */
+	__u64 base;
+
+	/**
+	 * @comp_base: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_base;
+
+	/**
+	 * @stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the buffer.
+	 */
+	__u32 stride;
+
+	/**
+	 * @comp_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the compression metadata.
+	 */
+	__u32 comp_stride;
+};
+
+/**
+ * struct drm_asahi_timestamp - Describe a timestamp write.
+ *
+ * The firmware can optionally write the GPU timestamp at render pass
+ * granularities, but it needs to be mapped specially via
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
+ * write as a handle-offset pair, rather than a GPU address like normal.
+ */
+struct drm_asahi_timestamp {
+	/**
+	 * @handle: Handle of the timestamp buffer, or 0 to skip this
+	 * timestamp. If nonzero, this must equal the value returned in
+	 * drm_asahi_gem_bind_object::object_handle.
+	 */
+	__u32 handle;
+
+	/** @offset: Offset to write into the timestamp buffer */
+	__u32 offset;
+};
+
+/**
+ * struct drm_asahi_timestamps - Describe timestamp writes.
+ *
+ * Each operation that can be timestamped, can be timestamped at the start and
+ * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
+ * together into drm_asahi_timestamps.
+ */
+struct drm_asahi_timestamps {
+	/** @start: Timestamp recorded at the start of the operation */
+	struct drm_asahi_timestamp start;
+
+	/** @end: Timestamp recorded at the end of the operation */
+	struct drm_asahi_timestamp end;
+};
+
+/**
+ * struct drm_asahi_helper_program - Describe helper program configuration.
+ *
+ * The helper program is a compute-like kernel required for various hardware
+ * functionality. Its most important role is dynamically allocating
+ * scratch/stack memory for individual subgroups, by partitioning a static
+ * allocation shared for the whole device. It is supplied by userspace via
+ * drm_asahi_helper_program and internally dispatched by the hardware as needed.
+ */
+struct drm_asahi_helper_program {
+	/**
+	 * @binary: USC address to the helper program binary. This is a tagged
+	 * pointer with configuration in the bottom bits.
+	 */
+	__u32 binary;
+
+	/** @cfg: Configuration bits for the helper program. */
+	__u32 cfg;
+
+	/**
+	 * @data: Data passed to the helper program. This value is not
+	 * interpreted by the kernel, firmware, or hardware in any way. It is
+	 * simply a sideband for userspace, set with the submit ioctl and read
+	 * via special registers inside the helper program.
+	 *
+	 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
+	 * actual arguments, which presumably don't fit in 64-bits.
+	 */
+	__u64 data;
+};
+
+/**
+ * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
+ *
+ * The background and end-of-tile programs are dispatched by the hardware at the
+ * beginning and end of rendering. As the hardware "tilebuffer" is simply local
+ * memory, these programs are necessary to implement API-level render targets.
+ * The fragment-like background program is responsible for loading either the
+ * clear colour or the existing render target contents, while the compute-like
+ * end-of-tile program stores the tilebuffer contents to memory.
+ */
+struct drm_asahi_bg_eot {
+	/**
+	 * @usc: USC address of the hardware USC words binding resources
+	 * (including images and uniforms) and the program itself. Note this is
+	 * an additional layer of indirection compared to the helper program,
+	 * avoiding the need for a sideband for data. This is a tagged pointer
+	 * with additional configuration in the bottom bits.
+	 */
+	__u32 usc;
+
+	/**
+	 * @rsrc_spec: Resource specifier for the program. This is a packed
+	 * hardware data structure describing the required number of registers,
+	 * uniforms, bound textures, and bound samplers.
+	 */
+	__u32 rsrc_spec;
+};
+
+/**
+ * struct drm_asahi_cmd_render - Command to submit 3D
+ *
+ * This command submits a single render pass. The hardware control stream may
+ * include many draws and subpasses, but within the command, the framebuffer
+ * dimensions and attachments are fixed.
+ *
+ * The hardware requires the firmware to set a large number of Control Registers
+ * setting up state at render pass granularity before each command rendering 3D.
+ * The firmware bundles this state into data structures. Unfortunately, we
+ * cannot expose either any of that directly to userspace, because the
+ * kernel-firmware ABI is not stable. Although we can guarantee the firmware
+ * updates in tandem with the kernel, we cannot break old userspace when
+ * upgrading the firmware and kernel. Therefore, we need to abstract well the
+ * data structures to avoid tying our hands with future firmwares.
+ *
+ * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
+ * control registers, marshalled via the firmware interface.
+ *
+ * The framebuffer/tilebuffer dimensions are also specified here. In addition to
+ * being passed to the firmware/hardware, the kernel requires these dimensions
+ * to calculate various essential tiling-related data structures. It is
+ * unfortunate that our submits are heavier than on vendors with saner
+ * hardware-software interfaces. The upshot is all of this information is
+ * readily available to userspace with all current APIs.
+ *
+ * It looks odd - but it's not overly burdensome and it ensures we can remain
+ * compatible with old userspace.
+ */
+struct drm_asahi_cmd_render {
+	/** @flags: Combination of drm_asahi_render_flags flags. */
+	__u32 flags;
+
+	/**
+	 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
+	 * depth/stencil width/height, which may differ from the framebuffer
+	 * width/height.
+	 */
+	__u32 isp_zls_pixels;
+
+	/**
+	 * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU
+	 * address to the beginning of the VDM control stream.
+	 */
+	__u64 vdm_ctrl_stream_base;
+
+	/** @vertex_helper: Helper program used for the vertex shader */
+	struct drm_asahi_helper_program vertex_helper;
+
+	/** @fragment_helper: Helper program used for the fragment shader */
+	struct drm_asahi_helper_program fragment_helper;
+
+	/**
+	 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
+	 * array of scissor descriptors indexed in the render pass.
+	 */
+	__u64 isp_scissor_base;
+
+	/**
+	 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
+	 * array of depth bias values indexed in the render pass.
+	 */
+	__u64 isp_dbias_base;
+
+	/**
+	 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
+	 * array of occlusion query results written by the render pass.
+	 */
+	__u64 isp_oclqry_base;
+
+	/** @depth: Depth buffer */
+	struct drm_asahi_zls_buffer depth;
+
+	/** @stencil: Stencil buffer */
+	struct drm_asahi_zls_buffer stencil;
+
+	/** @zls_ctrl: ZLS_CTRL register value */
+	__u64 zls_ctrl;
+
+	/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
+	__u64 ppp_multisamplectl;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/** @ppp_ctrl: PPP_CTRL register value */
+	__u32 ppp_ctrl;
+
+	/** @width_px: Framebuffer width in pixels */
+	__u16 width_px;
+
+	/** @height_px: Framebuffer height in pixels */
+	__u16 height_px;
+
+	/** @layers: Number of layers in the framebuffer */
+	__u16 layers;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u16 sampler_count;
+
+	/** @utile_width_px: Width of a logical tilebuffer tile in pixels */
+	__u8 utile_width_px;
+
+	/** @utile_height_px: Height of a logical tilebuffer tile in pixels */
+	__u8 utile_height_px;
+
+	/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
+	__u8 samples;
+
+	/** @sample_size_B: # of bytes in the tilebuffer required per sample. */
+	__u8 sample_size_B;
+
+	/**
+	 * @isp_merge_upper_x: 32-bit float used in the hardware triangle
+	 * merging. Calculate as: tan(60 deg) * width.
+	 *
+	 * Making these values UAPI avoids requiring floating-point calculations
+	 * in the kernel in the hot path.
+	 */
+	__u32 isp_merge_upper_x;
+
+	/**
+	 * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height.
+	 * See @isp_merge_upper_x.
+	 */
+	__u32 isp_merge_upper_y;
+
+	/** @bg: Background program run for each tile at the start */
+	struct drm_asahi_bg_eot bg;
+
+	/** @eot: End-of-tile program ran for each tile at the end */
+	struct drm_asahi_bg_eot eot;
+
+	/**
+	 * @partial_bg: Background program ran at the start of each tile when
+	 * resuming the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_bg;
+
+	/**
+	 * @partial_eot: End-of-tile program ran at the end of each tile when
+	 * pausing the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_eot;
+
+	/**
+	 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
+	 * buffer clear value, encoded in the depth buffer's format: either a
+	 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
+	 */
+	__u32 isp_bgobjdepth;
+
+	/**
+	 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
+	 * contain the stencil buffer clear value.
+	 */
+	__u32 isp_bgobjvals;
+
+	/** @ts_vtx: Timestamps for the vertex portion of the render */
+	struct drm_asahi_timestamps ts_vtx;
+
+	/** @ts_frag: Timestamps for the fragment portion of the render */
+	struct drm_asahi_timestamps ts_frag;
+};
+
+/**
+ * struct drm_asahi_cmd_compute - Command to submit compute
+ *
+ * This command submits a control stream consisting of compute dispatches. There
+ * is essentially no limit on how many compute dispatches may be included in a
+ * single compute command, although timestamps are at command granularity.
+ */
+struct drm_asahi_cmd_compute {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u32 sampler_count;
+
+	/**
+	 * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU
+	 * address to the beginning of the CDM control stream.
+	 */
+	__u64 cdm_ctrl_stream_base;
+
+	/**
+	 * @cdm_ctrl_stream_end: GPU base address to the end of the hardware
+	 * control stream. Note this only considers the first contiguous segment
+	 * of the control stream, as the stream might jump elsewhere.
+	 */
+	__u64 cdm_ctrl_stream_end;
+
+	/** @sampler_heap: Base address of the sampler heap. */
+	__u64 sampler_heap;
+
+	/** @helper: Helper program used for this compute shader */
+	struct drm_asahi_helper_program helper;
+
+	/** @ts: Timestamps for the compute command */
+	struct drm_asahi_timestamps ts;
+};
+
+/**
+ * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
+ */
+struct drm_asahi_get_time {
+	/** @flags: MBZ. */
+	__u64 flags;
+
+	/** @gpu_timestamp: On return, the current GPU timestamp */
+	__u64 gpu_timestamp;
+};
+
+/**
+ * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
+ * @__access: Access type. Must be R, W or RW.
+ * @__id: One of the DRM_ASAHI_xxx id.
+ * @__type: Suffix of the type being passed to the IOCTL.
+ *
+ * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
+ * values instead.
+ *
+ * Return: An IOCTL number to be passed to ioctl() from userspace.
+ */
+#define DRM_IOCTL_ASAHI(__access, __id, __type) \
+	DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
+			   struct drm_asahi_ ## __type)
+
+/* Note: this is an enum so that it can be resolved by Rust bindgen. */
+enum {
+	DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
+	DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
+	DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
+	DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
+	DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
+	DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
+	DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
+	DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
+	DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
+	DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
+	DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _ASAHI_DRM_H_ */

---
base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
change-id: 20250307-agx-uapi-930579437f19

Best regards,
-- 
Alyssa Rosenzweig <alyssa at rosenzweig.io>



From Frank.li at nxp.com  Fri Mar 14 16:21:22 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 14 Mar 2025 19:21:22 -0400
Subject: [PATCH v11 06/11] PCI: dwc: Use devicetree 'ranges' property to
 get rid of cpu_addr_fixup() callback
In-Reply-To: <20250314221059.GA806127@bhelgaas>
References: <Z9RJbyoFdkiYHXu9@lizhi-Precision-Tower-5810>
 <20250314221059.GA806127@bhelgaas>
Message-ID: <Z9S58n/6cE5QFRUD@lizhi-Precision-Tower-5810>

On Fri, Mar 14, 2025 at 05:10:59PM -0500, Bjorn Helgaas wrote:
> On Fri, Mar 14, 2025 at 11:21:19AM -0400, Frank Li wrote:
> > On Thu, Mar 13, 2025 at 06:56:17PM -0400, Frank Li wrote:
> > > On Thu, Mar 13, 2025 at 05:04:50PM -0500, Bjorn Helgaas wrote:
> > > > On Thu, Mar 13, 2025 at 11:38:42AM -0400, Frank Li wrote:
> > > > > The 'ranges' property at PCI controller parent bus can indicate address
> > > > > translation information. Most system's bus fabric use 1:1 map between input
> > > > > and output address. but some hardware like i.MX8QXP doesn't use 1:1 map.
> > > >
> > > > I think you've used reg["addr_space"] to get the offset for Endpoints
> > > > forever.
> > >
> > > Yes, it still need ranges informaiton at parent bus.
> > >
> > > 	bus at 000
> > > 	{
> > > 		ranges = <...>; [1] /* still need this */
> > > 		pcie {
> > > 			ranges = <...>;[2]
> > > 		};
> > > 		pcie-ep {};
> > > 	}
>
> Yes, of course. I'm just making the point that the subject/commit log
> says this patch uses 'ranges' but in fact it uses 'reg'.

Actaully my means: 'ranges' in subject means parent bus's ranges. Anyway
how about:

Use reg['config'] dettect parent_bus_offset to get rid of cpu_addr_fixup() callback

>
> > > > I just noticed that through v9, you used 'ranges' to get the offset
> > > > for the Root Complex (with "Add parent_bus_offset to resource_entry"),
> > > > and I think v10 switched to use reg["config"] instead.
> > > >
> > > > I think I originally proposed the idea of "Add parent_bus_offset to
> > > > resource_entry" patch, but I think it turned out to be kind of an ugly
> > > > approach.
> > > >
> > > > Anyway, IIUC this v11 patch actually uses reg["config"] to compute the
> > > > offset, not 'ranges', so we should probably update the subject and
> > > > commit log to reflect that, and maybe remove the now-unused bits of
> > > > the devicetree example.
> > >
> > > We use reg["config"] to detect offset, but still need parent dts's ranges.
> > > There are two ranges, one is at parent pci bus [1], the other is under
> > > 'pci bus' [2].
> >
> > Beside, luckly dwc use reg["config"] to indicate config space. but dt also
> > define ranges [2] under pcie node, which can also include 'config's space.
> >
> > cadence also use reg["cfg"] to do that.
> > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
> >
> > I am not sure why both choose use reg[] instead of [2]ranges under
> > pcie node. But the result make our situation simpler.
> >
> > > Although use reg["config"], but still need ranges [1]. And information at
> > > ranges [2] also need be correct.
> > >
> > > The whole devicetree example also validate to help write address translate
> > > informaiton.
> > >
> > > > I do worry a little bit about the assumption that the offset of
> > > > reg["config"] is the same as the offset of the other pieces.  The main
> > > > place we use the offset on RCs is for the ATU, and isn't the ATU in
> > > > the MemSpace area at 0x8000_0000 below?
> > >
> > > No, "Bus fabric" only decode input address from "0x7000_0000..UPLIMIT".
> > > Then output address to 0x8000_0000..UPLIMIT. So below 0x8000_0000 never
> > > happen.
>
> Minor miscommunication, I think.   I didn't mean there were addresses
> smaller than 0x8000_0000; I meant that in the picture, MemSpace at
> 0x8000_0000 is below CfgSpace at 0x8ff0_0000.  The important point is
> that CfgSpace is a separate region from MemSpace, and we're applying
> the CfgSpace offset to the ATU in MemSpace.
>
> I think it's OK to assume that for now.  AFAICS there is nothing in
> devicetree that explicitly mentions the ATU input address space; it's
> just implicitly part of the intermediate address space described by
> the bus at 5f000000 'ranges'.

Actually 'ranges' means address tranlation from child node to parent node.
that should means address to ATU input. It will be good if docuemnt
somewhere. Do you think where should document?

>
> > > > It's great that in this case the 0x7ff0_0000 to 0x8ff0_0000 "config"
> > > > offset is the same as the 0x7000_0000 to 0x8000_0000 MemSpace offset,
> > > > but I don't know that this is guaranteed for all designs.
> > >
> > > So far, it is the same for use dwc chips. If we meet difference, we can
> > > add later.
> > >
> > > reg["config"] only simplied our implement base on the offset is the same.
> > > But whole concept is unchanged.
>
> > > > > See below diagram:
> > > > >
> > > > >             ???????????                    ??????????????
> > > > >  ???????    ?         ? IA: 0x8ff8_0000    ?            ?
> > > > >  ? CPU ??????   ?????????????????????????  ? PCI        ?
> > > > >  ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
> > > > >   CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
> > > > > 0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
> > > > >             ?      ?  ?             ?   ?  ?            ?   PCI Addr
> > > > > 0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
> > > > >             ?         ?             ?      ?            ?    0
> > > > > 0x7000_0000??????????????????????   ?      ?            ?
> > > > >             ???????????         ?   ???????? CfgSpace  ???????????????
> > > > >              BUS Fabric         ?          ?            ?    0
> > > > >                                 ?          ?            ?
> > > > >                                 ???????????? MemSpace  ???????????????
> > > > >                         IA: 0x8000_0000    ?            ?  0x8000_0000
> > > > >                                            ??????????????
> > > > >
> > > > > bus at 5f000000 {
> > > > > 	compatible = "simple-bus";
> > > > > 	#address-cells = <1>;
> > > > > 	#size-cells = <1>;
> > > > > 	ranges = <0x80000000 0x0 0x70000000 0x10000000>;
> > > > >
> > > > > 	pcie at 5f010000 {
> > > > > 		compatible = "fsl,imx8q-pcie";
> > > > > 		reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> > > > > 		reg-names = "dbi", "config";
>
> > > > > 		#address-cells = <3>;
> > > > > 		#size-cells = <2>;
> > > > > 		device_type = "pci";
> > > > > 		bus-range = <0x00 0xff>;
> > > > > 		ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> > > > > 			 <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
>
> Of course we need this 'ranges' to describe the translation between
> intermediate addresses and PCI bus addresses.  My point is that this
> is not relevant to the parent bus offset we're computing in this
> patch.
>
> So I think for purposes of this patch, we can omit pcie at 5f010000
> #address-cells and everything after it.
>

Okay, we can remove it.

Frank

> Bjorn


From eddyz87 at gmail.com  Fri Mar 14 16:40:08 2025
From: eddyz87 at gmail.com (Eduard Zingerman)
Date: Fri, 14 Mar 2025 16:40:08 -0700
Subject: [PATCH bpf-next 00/11] bpf: Mitigate Spectre v1 using barriers
In-Reply-To: <20250313172127.1098195-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
Message-ID: <f6f08d64c777a6022771ab0adf96cefb6b631d75.camel@gmail.com>

On Thu, 2025-03-13 at 18:21 +0100, Luis Gerhorst wrote:
> This improves the expressiveness of unprivileged BPF by inserting
> speculation barriers instead of rejecting the programs.
> 
> The approach was previously presented at LPC'24 [1] and RAID'24 [2].
> 
> To mitigate the Spectre v1 (PHT) vulnerability, the kernel rejects
> potentially-dangerous unprivileged BPF programs as of
> commit?9183671af6db ("bpf: Fix leakage under speculation on mispredicted
> branches"). In [2], we have analyzed 364 object files from open source
> projects (Linux Samples and Selftests, BCC, Loxilb, Cilium, libbpf
> Examples, Parca, and Prevail) and found that this affects 31% to 54% of
> programs.
> 
> To resolve this in the majority of cases this patchset adds a fall-back
> for mitigating Spectre v1 using speculation barriers. The kernel still
> optimistically attempts to verify all speculative paths but uses
> speculation barriers against v1 when unsafe behavior is detected. This
> allows for more programs to be accepted without disabling the BPF
> Spectre mitigations (e.g., by setting cpu_mitigations_off()).
> 
> In [1] we have measured the overhead of this approach relative to having
> mitigations off and including the upstream Spectre v4 mitigations. For
> event tracing and stack-sampling profilers, we found that mitigations
> increase BPF program execution time by 0% to 62%. For the Loxilb network
> load balancer, we have measured a 14% slowdown in SCTP performance but
> no significant slowdown for TCP. This overhead only applies to programs
> that were previously rejected.
> 
> I reran the expressiveness-evaluation with v6.14 and made sure the main
> results still match those from [1] and [2] (which used v6.5).
> 
> Main design decisions are:
> 
> * Do not use separate bytecode insns for v1 and v4 barriers. This
>   simplifies the verifier significantly and has the only downside that
>   performance on PowerPC is not as high as it could be.
> 
> * Allow archs to still disable v1/v4 mitigations separately by setting
>   bpf_jit_bypass_spec_v1/v4(). This has the benefit that archs can
>   benefit from improved BPF expressiveness / performance if they are not
>   vulnerable (e.g., ARM64 for v4 in the kernel).
> 
> * Do not remove the empty BPF_NOSPEC implementation for backends for
>   which it is unknown whether they are vulnerable to Spectre v1.

[...]

I think it would be good to have some tests checking that nospec
instructions are inserted in expected locations.
Could you please take look at use of __xlated tag in e.g.
tools/testing/selftests/bpf/progs/verifier_sdiv.c ?

[...]



From robh at kernel.org  Fri Mar 14 16:43:31 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 14 Mar 2025 18:43:31 -0500
Subject: [PATCH 2/8] dt-bindings: arm: mediatek: Merge MT8186 Voltorb
 entries
In-Reply-To: <20250312104344.3084425-3-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
 <20250312104344.3084425-3-wenst@chromium.org>
Message-ID: <174199581084.2541058.17920956442449315665.robh@kernel.org>


On Wed, 12 Mar 2025 18:43:36 +0800, Chen-Yu Tsai wrote:
> There are only two different SKUs of Voltorb, and the only difference
> between them is whether a touchscreen is present or not. This can be
> detected by a simple I2C transfer to the address, instead of having
> separate compatible strings and device trees.
> 
> Drop the SKU-specific compatible strings and just keep the generic
> "google,voltorb" one.
> 
> Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
> ---
>  Documentation/devicetree/bindings/arm/mediatek.yaml | 3 ---
>  1 file changed, 3 deletions(-)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Fri Mar 14 16:42:48 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 14 Mar 2025 18:42:48 -0500
Subject: [PATCH 1/8] dt-bindings: HID: i2c-hid: elan: Introduce Elan
 eKTH8D18
In-Reply-To: <CAD=FV=X14XEdikE3hP4y53uZec12O_ZPtU+GyJ+Tf8R3DK89AA@mail.gmail.com>
References: <20250312104344.3084425-1-wenst@chromium.org>
 <20250312104344.3084425-2-wenst@chromium.org>
 <CAD=FV=X14XEdikE3hP4y53uZec12O_ZPtU+GyJ+Tf8R3DK89AA@mail.gmail.com>
Message-ID: <20250314234248.GA2536020-robh@kernel.org>

On Fri, Mar 14, 2025 at 02:58:36PM -0700, Doug Anderson wrote:
> Hi,
> 
> 
> On Wed, Mar 12, 2025 at 3:43?AM Chen-Yu Tsai <wenst at chromium.org> wrote:
> >
> > The Elan eKTH8D18 touchscreen controller is an I2C HID device with a
> > longer boot-up time. Power sequence timing wise it is compatible with
> > the eKTH6A12NAY, with a power-on delay of at least 5ms, 20ms
> > out-of-reset for I2C ack response, and 150ms out-of-reset for I2C HID
> > enumeration. Enumeration and subsequent operation follows the I2C HID
> > standard. The eKTH6A12NAY requires longer times for both parts.
> 
> Somehow the last sentence above confused me. Can it just be dropped?
> All you care about is that the new trackpad matches the timings for
> "eKTH6A12NAY". Not sure what you mean by "eKTH6A12NAY" needing
> "longer" timings.
> 
> 
> > Add a compatible string for it with the ekth6a12nay one as a fallback.
> >
> > Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
> > ---
> >  .../bindings/input/elan,ekth6915.yaml         | 29 ++++++++++++++++---
> >  1 file changed, 25 insertions(+), 4 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> > index cb3e1801b0d3..81c391952ccc 100644
> > --- a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> > +++ b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml
> > @@ -4,14 +4,14 @@
> >  $id: http://devicetree.org/schemas/input/elan,ekth6915.yaml#
> >  $schema: http://devicetree.org/meta-schemas/core.yaml#
> >
> > -title: Elan eKTH6915 touchscreen controller
> > +title: Elan I2C-HID touchscreen controllers
> >
> >  maintainers:
> >    - Douglas Anderson <dianders at chromium.org>
> >
> >  description:
> > -  Supports the Elan eKTH6915 touchscreen controller.
> > -  This touchscreen controller uses the i2c-hid protocol with a reset GPIO.
> > +  Supports the Elan eKTH6915 and other I2C-HID touchscreen controllers.
> > +  These touchscreen controller use the i2c-hid protocol with a reset GPIO.
> >
> >  allOf:
> >    - $ref: /schemas/input/touchscreen/touchscreen.yaml#
> > @@ -23,12 +23,18 @@ properties:
> >            - enum:
> >                - elan,ekth5015m
> >            - const: elan,ekth6915
> > +      - items:
> > +          - enum:
> > +              - elan,ekth8d18
> > +          - const: elan,ekth6a12nay
> 
> The "enum" above is weird, but it matches what we did for
> "elan,ekth5015m" so I guess it's fine? I'd leave it up to bindings
> maintainers. I guess the assumption is that we might add additional
> touchscreens to the list...

Yes, but up to you all if that's a valid assumption.

> 
> 
> >    reg:
> > -    const: 0x10
> > +    enum:
> > +      - 0x10
> > +      - 0x16
> 
> Again happy to leave it to the bindings maintainers, but _maybe_ just
> drop the "reg" parts here and below. It doesn't really have to be part
> of the bindings.

I tend to agree. Sometimes we list I2C addresses as that is part of the 
device whereas elsewhere it is not. I don't know that it's worth the 
if/then schema in this case. 

Rob


From cki-project at redhat.com  Fri Mar 14 16:43:04 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 14 Mar 2025 23:43:04 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc6,
 upstream-arm-next, a5618886)
Message-ID: <18060.125031419430600617@us-mta-30.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1717825191

One or more kernel builds failed:
    We also see the following known issues which are not related to your changes:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1717825191-aarch64-kernel
                   Issue: [upstream] error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization]
                          https://gitlab.com/cki-project/infrastructure/-/issues/473


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From robh at kernel.org  Fri Mar 14 16:43:43 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 14 Mar 2025 18:43:43 -0500
Subject: [PATCH 3/8] dt-bindings: arm: mediatek: Add MT8186 Squirtle
 Chromebooks
In-Reply-To: <20250312104344.3084425-4-wenst@chromium.org>
References: <20250312104344.3084425-1-wenst@chromium.org>
 <20250312104344.3084425-4-wenst@chromium.org>
Message-ID: <174199582298.2541457.8793216796013121859.robh@kernel.org>


On Wed, 12 Mar 2025 18:43:37 +0800, Chen-Yu Tsai wrote:
> Add an entry for the MT8186 based Squirtle Chromebooks, also known as the
> Acer Chromebook Spin 311 (R724T). The device is a 2-in-1 convertible.
> 
> Signed-off-by: Chen-Yu Tsai <wenst at chromium.org>
> ---
>  Documentation/devicetree/bindings/arm/mediatek.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From memxor at gmail.com  Fri Mar 14 16:49:51 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 00:49:51 +0100
Subject: [PATCH bpf-next v3 00/25] Resilient Queued Spin Lock
In-Reply-To: <20250303152305.3195648-1-memxor@gmail.com>
References: <20250303152305.3195648-1-memxor@gmail.com>
Message-ID: <CAP01T75iEw0mU6LeigHMp06DGsgZHp7UWY422xZtX1U7tVHa0Q@mail.gmail.com>

On Mon, 3 Mar 2025 at 16:23, Kumar Kartikeya Dwivedi <memxor at gmail.com> wrote:
>
>

Hello,

In v4, we will fix a couple of issues noticed in patchwork, where the
locktorture patch breaks bisection and needs to be ordered after the
Makefile change (patch 17 and 18 need to be swapped), but the biggest
change is that we will move rqspinlock implementation under
kernel/bpf/ to make it clear that it should be used by the BPF
subsystem only.

Thanks

>
> Introduction
> ------------
>
> This patch set introduces Resilient Queued Spin Lock (or rqspinlock with
> res_spin_lock() and res_spin_unlock() APIs).
>
> [...]


From alyssa at rosenzweig.io  Fri Mar 14 16:51:44 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Fri, 14 Mar 2025 19:51:44 -0400
Subject: [PATCH] iommu: apple-dart: fix potential null pointer deref
In-Reply-To: <20250314230102.11008-1-qasdev00@gmail.com>
References: <20250314230102.11008-1-qasdev00@gmail.com>
Message-ID: <Z9TBEAJkOrHIWype@blossom>

Reviewed-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>

Le Fri , Mar 14, 2025 at 11:01:02PM +0000, Qasim Ijaz a ?crit :
> If kzalloc() fails, accessing cfg->supports_bypass causes a null pointer dereference. 
> 
> Fix by checking for NULL immediately after allocation and returning -ENOMEM.
> 
> Fixes: 3bc0102835f6 ("iommu: apple-dart: Allow mismatched bypass support")
> Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> ---
>  drivers/iommu/apple-dart.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
> index 13ccb801f52a..e13501541fdd 100644
> --- a/drivers/iommu/apple-dart.c
> +++ b/drivers/iommu/apple-dart.c
> @@ -797,12 +797,11 @@ static int apple_dart_of_xlate(struct device *dev,
>  
>  	if (!cfg) {
>  		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
> -
> +		if (!cfg)
> +			return -ENOMEM;
>  		/* Will be ANDed with DART capabilities */
>  		cfg->supports_bypass = true;
>  	}
> -	if (!cfg)
> -		return -ENOMEM;
>  	dev_iommu_priv_set(dev, cfg);
>  
>  	cfg_dart = cfg->stream_maps[0].dart;
> -- 
> 2.39.5
> 


From romank at linux.microsoft.com  Fri Mar 14 17:19:26 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:26 -0700
Subject: [PATCH hyperv-next v6 06/11] arm64, x86: hyperv: Report the VTL the system boots in
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-7-romank@linux.microsoft.com>

The hyperv guest code might run in various Virtual Trust Levels.

Report the level when the kernel boots in the non-default (0)
one.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 arch/arm64/hyperv/mshyperv.c | 2 ++
 arch/x86/hyperv/hv_vtl.c     | 7 ++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index f251a08ada5b..ecbd2f5c955e 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -110,6 +110,8 @@ static int __init hyperv_init(void)
 	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
 		hv_get_partition_id();
 	ms_hyperv.vtl = get_vtl();
+	if (ms_hyperv.vtl > 0) /* non default VTL */
+		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
 
 	ms_hyperv_late_init();
 
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 582fe820e29c..038c896fdd60 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -55,7 +55,12 @@ static void  __noreturn hv_vtl_restart(char __maybe_unused *cmd)
 
 void __init hv_vtl_init_platform(void)
 {
-	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
+	/*
+	 * This function is a no-op if the VTL mode is not enabled.
+	 * If it is, this function runs if and only the kernel boots in
+	 * VTL2 which the x86 hv initialization path makes sure of.
+	 */
+	pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
 
 	x86_platform.realmode_reserve = x86_init_noop;
 	x86_platform.realmode_init = x86_init_noop;
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:28 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:28 -0700
Subject: [PATCH hyperv-next v6 08/11] Drivers: hv: vmbus: Get the IRQ number from DeviceTree
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-9-romank@linux.microsoft.com>

The VMBus driver uses ACPI for interrupt assignment on
arm64 hence it won't function in the VTL mode where only
DeviceTree can be used.

Update the VMBus driver to discover interrupt configuration
from DT.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 drivers/hv/vmbus_drv.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 22afebfc28ff..e8f2c3e92d1f 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2345,6 +2345,31 @@ static int vmbus_acpi_add(struct platform_device *pdev)
 }
 #endif
 
+static int vmbus_set_irq(struct platform_device *pdev)
+{
+	struct irq_data *data;
+	int irq;
+	irq_hw_number_t hwirq;
+
+	irq = platform_get_irq(pdev, 0);
+	/* platform_get_irq() may not return 0. */
+	if (irq < 0)
+		return irq;
+
+	data = irq_get_irq_data(irq);
+	if (!data) {
+		pr_err("No interrupt data for VMBus virq %d\n", irq);
+		return -ENODEV;
+	}
+	hwirq = irqd_to_hwirq(data);
+
+	vmbus_irq = irq;
+	vmbus_interrupt = hwirq;
+	pr_debug("VMBus virq %d, hwirq %d\n", vmbus_irq, vmbus_interrupt);
+
+	return 0;
+}
+
 static int vmbus_device_add(struct platform_device *pdev)
 {
 	struct resource **cur_res = &hyperv_mmio;
@@ -2359,6 +2384,11 @@ static int vmbus_device_add(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (!__is_defined(HYPERVISOR_CALLBACK_VECTOR))
+		ret = vmbus_set_irq(pdev);
+	if (ret)
+		return ret;
+
 	for_each_of_range(&parser, &range) {
 		struct resource *res;
 
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:27 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:27 -0700
Subject: [PATCH hyperv-next v6 07/11] dt-bindings: microsoft,vmbus: Add interrupt and DMA coherence properties
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-8-romank@linux.microsoft.com>

To boot in the VTL mode, VMBus on arm64 needs interrupt description
which the binding documentation lacks. The transactions on the bus are
DMA coherent which is not mentioned as well.

Add the interrupt property and the DMA coherence property to the VMBus
binding. Update the example to match that. Fix typos.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 .../bindings/bus/microsoft,vmbus.yaml           | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
index a8d40c766dcd..ca288ea54b34 100644
--- a/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
+++ b/Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
@@ -10,8 +10,8 @@ maintainers:
   - Saurabh Sengar <ssengar at linux.microsoft.com>
 
 description:
-  VMBus is a software bus that implement the protocols for communication
-  between the root or host OS and guest OSs (virtual machines).
+  VMBus is a software bus that implements the protocols for communication
+  between the root or host OS and guest OS'es (virtual machines).
 
 properties:
   compatible:
@@ -25,9 +25,17 @@ properties:
   '#size-cells':
     const: 1
 
+  dma-coherent: true
+
+  interrupts:
+    maxItems: 1
+    description: |
+      This interrupt is used to report a message from the host.
+
 required:
   - compatible
   - ranges
+  - interrupts
   - '#address-cells'
   - '#size-cells'
 
@@ -35,6 +43,8 @@ additionalProperties: false
 
 examples:
   - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
     soc {
         #address-cells = <2>;
         #size-cells = <1>;
@@ -49,6 +59,9 @@ examples:
                 #address-cells = <2>;
                 #size-cells = <1>;
                 ranges = <0x0f 0xf0000000 0x0f 0xf0000000 0x10000000>;
+                dma-coherent;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_PPI 2 IRQ_TYPE_EDGE_RISING>;
             };
         };
     };
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:30 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:30 -0700
Subject: [PATCH hyperv-next v6 10/11] ACPI: irq: Introduce  acpi_get_gsi_dispatcher()
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-11-romank@linux.microsoft.com>

Using acpi_irq_create_hierarchy() in the cases where the code
also handles OF leads to code duplication as the ACPI subsystem
doesn't provide means to compute the IRQ domain parent whereas
the OF does.

Introduce acpi_get_gsi_dispatcher() so that the drivers relying
on both ACPI and OF may use irq_domain_create_hierarchy() in the
common code paths.

No functional changes.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 drivers/acpi/irq.c   | 15 +++++++++++++--
 include/linux/acpi.h |  5 ++++-
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 1687483ff319..8eb09e45e5c5 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -12,7 +12,7 @@
 
 enum acpi_irq_model_id acpi_irq_model;
 
-static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi);
+static acpi_gsi_domain_disp_fn acpi_get_gsi_domain_id;
 static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi);
 
 /**
@@ -307,12 +307,23 @@ EXPORT_SYMBOL_GPL(acpi_irq_get);
  *	for a given GSI
  */
 void __init acpi_set_irq_model(enum acpi_irq_model_id model,
-			       struct fwnode_handle *(*fn)(u32))
+	acpi_gsi_domain_disp_fn fn)
 {
 	acpi_irq_model = model;
 	acpi_get_gsi_domain_id = fn;
 }
 
+/**
+ * acpi_get_gsi_dispatcher - Returns dispatcher function that
+ *                           computes the domain fwnode for a
+ *                           given GSI.
+ */
+acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void)
+{
+	return acpi_get_gsi_domain_id;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gsi_dispatcher);
+
 /**
  * acpi_set_gsi_to_irq_fallback - Register a GSI transfer
  * callback to fallback to arch specified implementation.
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4e495b29c640..abc51288e867 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -336,8 +336,11 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
+typedef struct fwnode_handle *(*acpi_gsi_domain_disp_fn)(u32);
+
 void acpi_set_irq_model(enum acpi_irq_model_id model,
-			struct fwnode_handle *(*)(u32));
+	acpi_gsi_domain_disp_fn fn);
+acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void);
 void acpi_set_gsi_to_irq_fallback(u32 (*)(u32));
 
 struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:29 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:29 -0700
Subject: [PATCH hyperv-next v6 09/11] Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-10-romank@linux.microsoft.com>

The ARM64 PCI code for hyperv needs to know the VMBus root
device, and it is private.

Provide a function that returns it. Rename it from "hv_dev"
as "hv_dev" as a symbol is very overloaded. No functional
changes.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 drivers/hv/vmbus_drv.c | 23 +++++++++++++++--------
 include/linux/hyperv.h |  2 ++
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e8f2c3e92d1f..df18b4070b01 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -45,7 +45,8 @@ struct vmbus_dynid {
 	struct hv_vmbus_device_id id;
 };
 
-static struct device  *hv_dev;
+/* VMBus Root Device */
+static struct device  *vmbus_root_device;
 
 static int hyperv_cpuhp_online;
 
@@ -80,9 +81,15 @@ static struct resource *fb_mmio;
 static struct resource *hyperv_mmio;
 static DEFINE_MUTEX(hyperv_mmio_lock);
 
+struct device *hv_get_vmbus_root_device(void)
+{
+	return vmbus_root_device;
+}
+EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
+
 static int vmbus_exists(void)
 {
-	if (hv_dev == NULL)
+	if (vmbus_root_device == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -861,7 +868,7 @@ static int vmbus_dma_configure(struct device *child_device)
 	 * On x86/x64 coherence is assumed and these calls have no effect.
 	 */
 	hv_setup_dma_ops(child_device,
-		device_get_dma_attr(hv_dev) == DEV_DMA_COHERENT);
+		device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
 	return 0;
 }
 
@@ -1930,7 +1937,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
 		     &child_device_obj->channel->offermsg.offer.if_instance);
 
 	child_device_obj->device.bus = &hv_bus;
-	child_device_obj->device.parent = hv_dev;
+	child_device_obj->device.parent = vmbus_root_device;
 	child_device_obj->device.release = vmbus_device_release;
 
 	child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
@@ -2292,7 +2299,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
 	struct acpi_device *ancestor;
 	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
 
-	hv_dev = &device->dev;
+	vmbus_root_device = &device->dev;
 
 	/*
 	 * Older versions of Hyper-V for ARM64 fail to include the _CCA
@@ -2378,7 +2385,7 @@ static int vmbus_device_add(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	int ret;
 
-	hv_dev = &pdev->dev;
+	vmbus_root_device = &pdev->dev;
 
 	ret = of_range_parser_init(&parser, np);
 	if (ret)
@@ -2696,7 +2703,7 @@ static int __init hv_acpi_init(void)
 	if (ret)
 		return ret;
 
-	if (!hv_dev) {
+	if (!vmbus_root_device) {
 		ret = -ENODEV;
 		goto cleanup;
 	}
@@ -2727,7 +2734,7 @@ static int __init hv_acpi_init(void)
 
 cleanup:
 	platform_driver_unregister(&vmbus_platform_driver);
-	hv_dev = NULL;
+	vmbus_root_device = NULL;
 	return ret;
 }
 
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 675959fb97ba..1f310fbbc4f9 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1277,6 +1277,8 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
 	return dev_get_drvdata(&dev->device);
 }
 
+struct device *hv_get_vmbus_root_device(void);
+
 struct hv_ring_buffer_debug_info {
 	u32 current_interrupt_mask;
 	u32 current_read_index;
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:25 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:25 -0700
Subject: [PATCH hyperv-next v6 05/11] arm64: hyperv: Initialize the Virtual Trust Level field
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-6-romank@linux.microsoft.com>

Various parts of the hyperv code need to know what VTL
the kernel runs at, most notably VMBus needs that to
establish communication with the host.

Initialize the Virtual Trust Level field to enable
booting in the Virtual Trust Level.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 arch/arm64/hyperv/mshyperv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index c5b03d3af7c5..f251a08ada5b 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -109,6 +109,7 @@ static int __init hyperv_init(void)
 
 	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
 		hv_get_partition_id();
+	ms_hyperv.vtl = get_vtl();
 
 	ms_hyperv_late_init();
 
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:31 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:31 -0700
Subject: [PATCH hyperv-next v6 11/11] PCI: hv: Get vPCI MSI IRQ domain from DeviceTree
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-12-romank@linux.microsoft.com>

The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
arm64. It won't be able to do that in the VTL mode where only DeviceTree
can be used.

Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
case, too.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/pci/controller/pci-hyperv.c | 73 ++++++++++++++++++++++++++---
 1 file changed, 67 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 6084b38bdda1..cbff19e8a07c 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -50,6 +50,7 @@
 #include <linux/irqdomain.h>
 #include <linux/acpi.h>
 #include <linux/sizes.h>
+#include <linux/of_irq.h>
 #include <asm/mshyperv.h>
 
 /*
@@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
 	int ret;
 
 	fwspec.fwnode = domain->parent->fwnode;
-	fwspec.param_count = 2;
-	fwspec.param[0] = hwirq;
-	fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+	if (is_of_node(fwspec.fwnode)) {
+		/* SPI lines for OF translations start at offset 32 */
+		fwspec.param_count = 3;
+		fwspec.param[0] = 0;
+		fwspec.param[1] = hwirq - 32;
+		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else {
+		fwspec.param_count = 2;
+		fwspec.param[0] = hwirq;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+	}
 
 	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
 	if (ret)
@@ -887,10 +896,47 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
 	.activate = hv_pci_vec_irq_domain_activate,
 };
 
+#ifdef CONFIG_OF
+
+static struct irq_domain *hv_pci_of_irq_domain_parent(void)
+{
+	struct device_node *parent;
+	struct irq_domain *domain;
+
+	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
+	if (!parent)
+		return NULL;
+	domain = irq_find_host(parent);
+	of_node_put(parent);
+
+	return domain;
+}
+
+#endif
+
+#ifdef CONFIG_ACPI
+
+static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
+{
+	struct irq_domain *domain;
+	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
+
+	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
+		return NULL;
+	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
+	if (!gsi_domain_disp_fn)
+		return NULL;
+	return irq_find_matching_fwnode(gsi_domain_disp_fn(0),
+				     DOMAIN_BUS_ANY);
+}
+
+#endif
+
 static int hv_pci_irqchip_init(void)
 {
 	static struct hv_pci_chip_data *chip_data;
 	struct fwnode_handle *fn = NULL;
+	struct irq_domain *irq_domain_parent = NULL;
 	int ret = -ENOMEM;
 
 	chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
@@ -907,9 +953,24 @@ static int hv_pci_irqchip_init(void)
 	 * way to ensure that all the corresponding devices are also gone and
 	 * no interrupts will be generated.
 	 */
-	hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
-							  fn, &hv_pci_domain_ops,
-							  chip_data);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled)
+		irq_domain_parent = hv_pci_acpi_irq_domain_parent();
+#endif
+#if defined(CONFIG_OF)
+	if (!irq_domain_parent)
+		irq_domain_parent = hv_pci_of_irq_domain_parent();
+#endif
+	if (!irq_domain_parent) {
+		WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
+		ret = -EINVAL;
+		goto free_chip;
+	}
+
+	hv_msi_gic_irq_domain = irq_domain_create_hierarchy(
+		irq_domain_parent, 0, HV_PCI_MSI_SPI_NR,
+		fn, &hv_pci_domain_ops,
+		chip_data);
 
 	if (!hv_msi_gic_irq_domain) {
 		pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:20 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:20 -0700
Subject: [PATCH hyperv-next v6 00/11] arm64: hyperv: Support Virtual Trust Level Boot
Message-ID: <20250315001931.631210-1-romank@linux.microsoft.com>

This patch set allows the Hyper-V code to boot on ARM64 inside a Virtual Trust
Level. These levels are a part of the Virtual Secure Mode documented in the
Top-Level Functional Specification available at
https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm.

The OpenHCL paravisor https://github.com/microsoft/openvmm/tree/main/openhcl
can serve as a practical application of these patches on ARM64.

For validation, I built kernels for the {x86_64, ARM64} x {VTL0, VTL2} set with
a small initrd embedded into the kernel and booted VMs managed by Hyper-V and
OpenVMM off of that.

Starting from V5, the patch series includes a non-functional change to KVM on
arm64 which I tested as well.

[V6]
    - Use more intuitive Kconfig update.
    - Remove ifdef for getting IRQ number
    ** Thank you, Arnd! **

    - Simplify code for finding the parent IRQ domain.
    ** Thank you, Bjorn! **

    - Remove a superfluous check.
    ** Thank you, Dan! **

    - Make the commit title and descrtiption legible.
    - Don't set additionalProperties to true.
    ** Thank you, Krzysztof! **

    - Fix spelling in the commit title and description.
    - Trade-offs for options in Kconfig.
    - Export the new symbol as hyperv-pci can be built as a module.
    ** Thank you, Michael! **

    - Simplify code for getting IRQ number.
    ** Thank you, Rob! **

    - Add comment to clarify when running in VTL mode is reported.
    ** Thank you, Wei! **

[V5]
  https://lore.kernel.org/linux-hyperv/20250307220304.247725-1-romank at linux.microsoft.com/
    - Provide and use a common SMCCC-based infra for the arm64 hypervisor guests
      to detect hypervisor presence.
    ** Thank you, Arnd! **

    - Fix line wraps to follow the rest of the code.
    - Open-code getting IRQ domain parent in the ACPI case to make the code
      better.
    ** Thank you, Bjorn! **

    - Test the binding with the latest dtschema.
    - Clean up the commit title and description.
    - Use proper defines for known constants.
    ** Thank you, Krzysztof! **

    - Extend comment on why ACPI v6 is checked for.
    - Reorder patches to make sure that even with partial series application
      the compilation succeeds.
    - Report VTL the kernel runs in.
    - Use "X86_64" in Kconfig rather than "X86".
    - Extract a non-functional change for hv_get_vmbus_root_device() into
      a separate patch.
    ** Thank you, Michael! **

[V4]
    https://lore.kernel.org/linux-hyperv/20250212014321.1108840-1-romank at linux.microsoft.com/
    - Fixed wording to match acronyms defined in the "Terms and Abbreviations"
      section of the SMCCC specification throughout the patch series.
      **Thank you, Michael!**

    - Replaced the hypervisor ID containing ASCII with an UUID as
      required by the specification.
      **Thank you, Michael!**

    - Added an explicit check for `SMCCC_RET_NOT_SUPPORTED` when discovering the
      hypervisor presence to make the backward compatibility obvious.
      **Thank you, Saurabh!**

    - Split the fix for `get_vtl(void)` out to make it easier to backport.
    - Refactored the configuration options as requested to eliminate the risk
      of building non-functional kernels with randomly selected options.
      **Thank you, Michael!**

    - Refactored the changes not to introduce an additional file with
      a one-line function.
      **Thank you, Wei!**

    - Fixed change description for the VMBus DeviceTree changes, used
      `scripts/get_maintainers.pl` on the latest kernel to get the up-to-date list
      of maintainers as requested.
      **Thank you, Krzysztof!**

    - Removed the added (paranoidal+superfluous) checks for DMA coherence in the
      VMBus driver and instead relied on the DMA and the OF subsystem code.
      **Thank you, Arnd, Krzysztof, Michael!**

    - Used another set of APIs for discovering the hardware interrupt number
      in the VMBus driver to be able to build the driver as a module.
      **Thank you, Michael, Saurabh!**

    - Renamed the newly introduced `get_vmbus_root_device(void)` function to
      `hv_get_vmbus_root_device(void)` as requested.
      **Thank you, Wei!**

    - Applied the suggested small-scale refactoring to simplify changes to the Hyper-V
      PCI driver. Taking the offered liberty of doing the large scale refactoring
      in another patch series.
      **Thank you, Michael!**

    - Added a fix for the issue discovered internally where the CPU would not
      get the interrupt from a PCI device attached to VTL2 as the shared peripheral
      interrupt number (SPI) was not offset by 32 (the first valid SPI number).
      **Thank you, Brian!**

[V3]
    https://lore.kernel.org/lkml/20240726225910.1912537-1-romank at linux.microsoft.com/
    - Employed the SMCCC function recently implemented in the Microsoft Hyper-V
      hypervisor to detect running on Hyper-V/arm64. No dependence on ACPI/DT is
      needed anymore although the source code still falls back to ACPI as the new
      hypervisor might be available only in the Windows Insiders channel just
      yet.
    - As a part of the above, refactored detecting the hypervisor via ACPI FADT.
    - There was a suggestion to explore whether it is feasible or not to express
      that ACPI must be absent for the VTL mode and present for the regular guests
      in the Hyper-V Kconfig file.
      My current conclusion is that this will require refactoring in many places.
      That becomes especially convoluted on x86_64 due to the MSI and APIC
      dependencies. I'd ask to let us tackle that in another patch series (or chalk
      up to nice-have's rather than fires to put out) to separate concerns and
      decrease chances of breakage.
    - While refactoring `get_vtl(void)` and the related code, fixed the hypercall
      output address not to overlap with the input as the Hyper-V TLFS mandates:
      "The input and output parameter lists cannot overlap or cross page boundaries."
      See https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercall-interface
      for more.
      Some might argue that should've been a topic for a separate patch series;
      I'd counter that the change is well-contained (one line), has no dependencies,
      and makes the code legal.
    - Made the VTL boot code (c)leaner as was suggested.
    - Set DMA cache coherency for the VMBus.
    - Updated DT bindings in the VMBus documentation (separated out into a new patch).
    - Fixed `vmbus_set_irq` to use the API that works both for the ACPI and OF.
    - Reworked setting up the vPCI MSI IRQ domain in the non-ACPI case. The logic
      looks a bit fiddly/ad-hoc as I couldn't find the API that would fit the bill.
      Added comments to explain myself.

[V2]
    https://lore.kernel.org/all/20240514224508.212318-1-romank at linux.microsoft.com/
    - Decreased number of #ifdef's
    - Updated the wording in the commit messages to adhere to the guidlines
    - Sending to the correct set of maintainers and mail lists

[V1]
    https://lore.kernel.org/all/20240510160602.1311352-1-romank at linux.microsoft.com/

Roman Kisel (11):
  arm64: kvm, smccc: Introduce and use API for detecting hypervisor
    presence
  arm64: hyperv: Use SMCCC to detect hypervisor presence
  Drivers: hv: Enable VTL mode for arm64
  Drivers: hv: Provide arch-neutral implementation of get_vtl()
  arm64: hyperv: Initialize the Virtual Trust Level field
  arm64, x86: hyperv: Report the VTL the system boots in
  dt-bindings: microsoft,vmbus: Add interrupt and DMA coherence
    properties
  Drivers: hv: vmbus: Get the IRQ number from DeviceTree
  Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
  ACPI: irq: Introduce  acpi_get_gsi_dispatcher()
  PCI: hv: Get vPCI MSI IRQ domain from DeviceTree

 .../bindings/bus/microsoft,vmbus.yaml         | 17 ++++-
 arch/arm64/hyperv/mshyperv.c                  | 46 ++++++++++--
 arch/arm64/kvm/hypercalls.c                   |  5 +-
 arch/x86/hyperv/hv_init.c                     | 34 ---------
 arch/x86/hyperv/hv_vtl.c                      |  7 +-
 drivers/acpi/irq.c                            | 15 +++-
 drivers/firmware/smccc/kvm_guest.c            | 10 +--
 drivers/firmware/smccc/smccc.c                | 19 +++++
 drivers/hv/Kconfig                            |  6 +-
 drivers/hv/hv_common.c                        | 31 ++++++++
 drivers/hv/vmbus_drv.c                        | 53 ++++++++++++--
 drivers/pci/controller/pci-hyperv.c           | 73 +++++++++++++++++--
 include/asm-generic/mshyperv.h                |  6 ++
 include/hyperv/hvgdk_mini.h                   |  2 +-
 include/linux/acpi.h                          |  5 +-
 include/linux/arm-smccc.h                     | 55 +++++++++++++-
 include/linux/hyperv.h                        |  2 +
 17 files changed, 307 insertions(+), 79 deletions(-)


base-commit: d9608f6dc3e3229a40e1db1dab573d6882f38c2a
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:22 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:22 -0700
Subject: [PATCH hyperv-next v6 02/11] arm64: hyperv: Use SMCCC to detect hypervisor presence
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-3-romank@linux.microsoft.com>

The arm64 Hyper-V startup path relies on ACPI to detect
running under a Hyper-V compatible hypervisor. That
doesn't work on non-ACPI systems.

Hoist the ACPI detection logic into a separate function. Then
use the vendor-specific hypervisor service call (implemented
recently in Hyper-V) via SMCCC in the non-ACPI case.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
---
 arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 2265ea5ce5ad..c5b03d3af7c5 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
 	return 0;
 }
 
+static bool __init hyperv_detect_via_acpi(void)
+{
+	if (acpi_disabled)
+		return false;
+#if IS_ENABLED(CONFIG_ACPI)
+	/*
+	 * Hypervisor ID is only available in ACPI v6+, and the
+	 * structure layout was extended in v6 to accommodate that
+	 * new field.
+	 *
+	 * At the very minimum, this check makes sure not to read
+	 * past the FADT structure.
+	 *
+	 * It is also needed to catch running in some unknown
+	 * non-Hyper-V environment that has ACPI 5.x or less.
+	 * In such a case, it can't be Hyper-V.
+	 */
+	if (acpi_gbl_FADT.header.revision < 6)
+		return false;
+	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
+#else
+	return false;
+#endif
+}
+
+static bool __init hyperv_detect_via_smccc(void)
+{
+	uuid_t hyperv_uuid = UUID_INIT(
+		0x4d32ba58, 0x4764, 0xcd24,
+		0x75, 0x6c, 0xef, 0x8e,
+		0x24, 0x70, 0x59, 0x16);
+
+	return arm_smccc_hyp_present(&hyperv_uuid);
+}
+
 static int __init hyperv_init(void)
 {
 	struct hv_get_vp_registers_output	result;
@@ -35,13 +70,11 @@ static int __init hyperv_init(void)
 
 	/*
 	 * Allow for a kernel built with CONFIG_HYPERV to be running in
-	 * a non-Hyper-V environment, including on DT instead of ACPI.
+	 * a non-Hyper-V environment.
+	 *
 	 * In such cases, do nothing and return success.
 	 */
-	if (acpi_disabled)
-		return 0;
-
-	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
+	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
 		return 0;
 
 	/* Setup the guest ID */
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:21 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:21 -0700
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and use API for detecting hypervisor presence
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-2-romank@linux.microsoft.com>

The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
private, and it follows the SMCCC specification. Other existing and
emerging hypervisor guest implementations can and should use that
standard approach as well.

Factor out a common infrastructure that the guests can use, update KVM
to employ the new API. The central notion of the SMCCC method is the
UUID of the hypervisor, and the API follows that.

No functional changes. Validated with a KVM/arm64 guest.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Acked-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm64/kvm/hypercalls.c        |  5 +--
 drivers/firmware/smccc/kvm_guest.c | 10 ++----
 drivers/firmware/smccc/smccc.c     | 19 +++++++++++
 include/linux/arm-smccc.h          | 55 +++++++++++++++++++++++++++---
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 27ce4cb44904..92b9bc1ea8e8 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -353,10 +353,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
 			val[0] = gpa;
 		break;
 	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
-		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
-		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
-		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
-		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
+		UUID_TO_SMCCC_RES(ARM_SMCCC_VENDOR_HYP_UID_KVM, val);
 		break;
 	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
 		val[0] = smccc_feat->vendor_hyp_bmap;
diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
index f3319be20b36..b5084b309ea0 100644
--- a/drivers/firmware/smccc/kvm_guest.c
+++ b/drivers/firmware/smccc/kvm_guest.c
@@ -14,17 +14,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
 
 void __init kvm_init_hyp_services(void)
 {
+	uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
 	struct arm_smccc_res res;
 	u32 val[4];
 
-	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
-		return;
-
-	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
-	if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
-	    res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
-	    res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
-	    res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
+	if (!arm_smccc_hyp_present(&kvm_uuid))
 		return;
 
 	memset(&res, 0, sizeof(res));
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
index a74600d9f2d7..7399f27d58e5 100644
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -67,6 +67,25 @@ s32 arm_smccc_get_soc_id_revision(void)
 }
 EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
 
+bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
+{
+	struct arm_smccc_res res = {};
+
+	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
+		return false;
+	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
+	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+		return false;
+
+	return ({
+		const uuid_t uuid = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
+		const bool present = uuid_equal(&uuid, hyp_uuid);
+
+		present;
+	});
+}
+EXPORT_SYMBOL_GPL(arm_smccc_hyp_present);
+
 static int __init smccc_devices_init(void)
 {
 	struct platform_device *pdev;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 67f6fdf2e7cd..726f18221f1c 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -7,6 +7,11 @@
 
 #include <linux/args.h>
 #include <linux/init.h>
+
+#ifndef __ASSEMBLER__
+#include <linux/uuid.h>
+#endif
+
 #include <uapi/linux/const.h>
 
 /*
@@ -107,10 +112,10 @@
 			   ARM_SMCCC_FUNC_QUERY_CALL_UID)
 
 /* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0	0xb66fb428U
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1	0xe911c52eU
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2	0x564bcaa9U
-#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3	0x743a004dU
+#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
+	0xb66fb428, 0xc52e, 0xe911, \
+	0xa9, 0xca, 0x4b, 0x56, \
+	0x4d, 0x00, 0x3a, 0x74)
 
 /* KVM "vendor specific" services */
 #define ARM_SMCCC_KVM_FUNC_FEATURES		0
@@ -333,6 +338,48 @@ s32 arm_smccc_get_soc_id_version(void);
  */
 s32 arm_smccc_get_soc_id_revision(void);
 
+#ifndef __ASSEMBLER__
+
+/**
+ * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
+ *
+ * Returns `true` if the hypervisor advertises its presence via SMCCC.
+ *
+ * When the function returns `false`, the caller shall not assume that
+ * there is no hypervisor running. Instead, the caller must fall back to
+ * other approaches if any are available.
+ */
+bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);
+
+#define SMCCC_RES_TO_UUID(r0, r1, r2, r3) \
+	UUID_INIT( \
+		cpu_to_le32(lower_32_bits(r0)), \
+		cpu_to_le32(lower_32_bits(r1)) & 0xffff, \
+		cpu_to_le32(lower_32_bits(r1)) >> 16, \
+		cpu_to_le32(lower_32_bits(r2)) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 8) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 16) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r2)) >> 24) & 0xff, \
+		cpu_to_le32(lower_32_bits(r3)) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 8) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 16) & 0xff, \
+		(cpu_to_le32(lower_32_bits(r3)) >> 24) & 0xff \
+	)
+
+#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
+		const uuid_t uuid = uuid_init; \
+		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
+						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24)); \
+		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
+						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24)); \
+		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
+						((uuid.b[10]) << 16) | ((uuid.b[11]) << 24)); \
+		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
+						((uuid.b[14]) << 16) | ((uuid.b[15]) << 24)); \
+	} while (0)
+
+#endif /* !__ASSEMBLER__ */
+
 /**
  * struct arm_smccc_res - Result from SMC/HVC call
  * @a0-a3 result values from registers 0 to 3
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:23 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:23 -0700
Subject: [PATCH hyperv-next v6 03/11] Drivers: hv: Enable VTL mode for arm64
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-4-romank@linux.microsoft.com>

Kconfig dependencies for arm64 guests on Hyper-V require that be
ACPI enabled, and limit VTL mode to x86/x64. To enable VTL mode
on arm64 as well, update the dependencies. Since VTL mode requires
DeviceTree instead of ACPI, don?t require arm64 guests on Hyper-V
to have ACPI unconditionally.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
---
 drivers/hv/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 794e88e9dc6b..11b07a6d594a 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -5,7 +5,7 @@ menu "Microsoft Hyper-V guest support"
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
 	depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
-		|| (ACPI && ARM64 && !CPU_BIG_ENDIAN)
+		|| (ARM64 && !CPU_BIG_ENDIAN)
 	select PARAVIRT
 	select X86_HV_CALLBACK_VECTOR if X86
 	select OF_EARLY_FLATTREE if OF
@@ -15,7 +15,7 @@ config HYPERV
 
 config HYPERV_VTL_MODE
 	bool "Enable Linux to boot in VTL context"
-	depends on X86_64 && HYPERV
+	depends on HYPERV
 	depends on SMP
 	default n
 	help
@@ -31,7 +31,7 @@ config HYPERV_VTL_MODE
 
 	  Select this option to build a Linux kernel to run at a VTL other than
 	  the normal VTL0, which currently is only VTL2.  This option
-	  initializes the x86 platform for VTL2, and adds the ability to boot
+	  initializes the kernel to run in VTL2, and adds the ability to boot
 	  secondary CPUs directly into 64-bit context as required for VTLs other
 	  than 0.  A kernel built with this option must run at VTL2, and will
 	  not run as a normal guest.
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:19:24 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:19:24 -0700
Subject: [PATCH hyperv-next v6 04/11] Drivers: hv: Provide arch-neutral implementation of get_vtl()
In-Reply-To: <20250315001931.631210-1-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
Message-ID: <20250315001931.631210-5-romank@linux.microsoft.com>

To run in the VTL mode, Hyper-V drivers have to know what
VTL the system boots in, and the arm64/hyperv code does not
have the means to compute that.

Refactor the code to hoist the function that detects VTL,
make it arch-neutral to be able to employ it to get the VTL
on arm64.

Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux at outlook.com>
Reviewed-by: Tianyu Lan <tiala at microsoft.com>
---
 arch/x86/hyperv/hv_init.c      | 34 ----------------------------------
 drivers/hv/hv_common.c         | 31 +++++++++++++++++++++++++++++++
 include/asm-generic/mshyperv.h |  6 ++++++
 include/hyperv/hvgdk_mini.h    |  2 +-
 4 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index ddeb40930bc8..3b569291dfed 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -390,40 +390,6 @@ static void __init hv_stimer_setup_percpu_clockev(void)
 		old_setup_percpu_clockev();
 }
 
-#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
-static u8 __init get_vtl(void)
-{
-	u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
-	struct hv_input_get_vp_registers *input;
-	struct hv_output_get_vp_registers *output;
-	unsigned long flags;
-	u64 ret;
-
-	local_irq_save(flags);
-	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
-	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
-
-	memset(input, 0, struct_size(input, names, 1));
-	input->partition_id = HV_PARTITION_ID_SELF;
-	input->vp_index = HV_VP_INDEX_SELF;
-	input->input_vtl.as_uint8 = 0;
-	input->names[0] = HV_REGISTER_VSM_VP_STATUS;
-
-	ret = hv_do_hypercall(control, input, output);
-	if (hv_result_success(ret)) {
-		ret = output->values[0].reg8 & HV_X64_VTL_MASK;
-	} else {
-		pr_err("Failed to get VTL(error: %lld) exiting...\n", ret);
-		BUG();
-	}
-
-	local_irq_restore(flags);
-	return ret;
-}
-#else
-static inline u8 get_vtl(void) { return 0; }
-#endif
-
 /*
  * This function is to be invoked early in the boot sequence after the
  * hypervisor has been detected.
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 9804adb4cc56..dce4b34e293b 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -304,6 +304,37 @@ void __init hv_get_partition_id(void)
 		pr_err("Hyper-V: failed to get partition ID: %#x\n",
 		       hv_result(status));
 }
+#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
+u8 __init get_vtl(void)
+{
+	u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
+	struct hv_input_get_vp_registers *input;
+	struct hv_output_get_vp_registers *output;
+	unsigned long flags;
+	u64 ret;
+
+	local_irq_save(flags);
+	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
+	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
+
+	memset(input, 0, struct_size(input, names, 1));
+	input->partition_id = HV_PARTITION_ID_SELF;
+	input->vp_index = HV_VP_INDEX_SELF;
+	input->input_vtl.as_uint8 = 0;
+	input->names[0] = HV_REGISTER_VSM_VP_STATUS;
+
+	ret = hv_do_hypercall(control, input, output);
+	if (hv_result_success(ret)) {
+		ret = output->values[0].reg8 & HV_VTL_MASK;
+	} else {
+		pr_err("Failed to get VTL(error: %lld) exiting...\n", ret);
+		BUG();
+	}
+
+	local_irq_restore(flags);
+	return ret;
+}
+#endif
 
 int __init hv_common_init(void)
 {
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index b13b0cda4ac8..c5150a2b12d6 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -348,4 +348,10 @@ static inline int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u3
 }
 #endif /* CONFIG_MSHV_ROOT */
 
+#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
+u8 __init get_vtl(void);
+#else
+static inline u8 get_vtl(void) { return 0; }
+#endif
+
 #endif
diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
index 58895883f636..98aa64e8844c 100644
--- a/include/hyperv/hvgdk_mini.h
+++ b/include/hyperv/hvgdk_mini.h
@@ -1202,7 +1202,7 @@ struct hv_send_ipi {	 /* HV_INPUT_SEND_SYNTHETIC_CLUSTER_IPI */
 	u64 cpu_mask;
 } __packed;
 
-#define	HV_X64_VTL_MASK			GENMASK(3, 0)
+#define	HV_VTL_MASK			GENMASK(3, 0)
 
 /* Hyper-V memory host visibility */
 enum hv_mem_host_visibility {
-- 
2.43.0



From romank at linux.microsoft.com  Fri Mar 14 17:27:59 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Fri, 14 Mar 2025 17:27:59 -0700
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and use
 API for detecting hypervisor presence
In-Reply-To: <20250315001931.631210-2-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-2-romank@linux.microsoft.com>
Message-ID: <96bc4caf-b79a-4111-bafa-a7662260f4be@linux.microsoft.com>



On 3/14/2025 5:19 PM, Roman Kisel wrote:
> The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
> private, and it follows the SMCCC specification. Other existing and
> emerging hypervisor guest implementations can and should use that
> standard approach as well.
> 
> Factor out a common infrastructure that the guests can use, update KVM
> to employ the new API. The central notion of the SMCCC method is the
> UUID of the hypervisor, and the API follows that.
> 
> No functional changes. Validated with a KVM/arm64 guest.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Acked-by: Arnd Bergmann <arnd at arndb.de>

While the change is Acked, here is the caveat maybe.

This patch produces warnings wtih sparse and CHECK_ENDING.
That said, the kernel build produces a whole lot more other warnings
from building with sparse by itself and/or with CHECK_ENDING.

I am not sure how to proceed with that, thinking I should
not add warnings yet at the same time there are many others.
Not certain if folks take these signals as fyi or blockers.

Decided to send V6 to trim the V5 discussion threads by implementing
suggestions and fixes.

> ---
>   arch/arm64/kvm/hypercalls.c        |  5 +--
>   drivers/firmware/smccc/kvm_guest.c | 10 ++----
>   drivers/firmware/smccc/smccc.c     | 19 +++++++++++
>   include/linux/arm-smccc.h          | 55 +++++++++++++++++++++++++++---
>   4 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
> index 27ce4cb44904..92b9bc1ea8e8 100644
> --- a/arch/arm64/kvm/hypercalls.c
> +++ b/arch/arm64/kvm/hypercalls.c
> @@ -353,10 +353,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
>   			val[0] = gpa;
>   		break;
>   	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
> -		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
> -		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
> -		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
> -		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
> +		UUID_TO_SMCCC_RES(ARM_SMCCC_VENDOR_HYP_UID_KVM, val);
>   		break;
>   	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
>   		val[0] = smccc_feat->vendor_hyp_bmap;
> diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
> index f3319be20b36..b5084b309ea0 100644
> --- a/drivers/firmware/smccc/kvm_guest.c
> +++ b/drivers/firmware/smccc/kvm_guest.c
> @@ -14,17 +14,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
>   
>   void __init kvm_init_hyp_services(void)
>   {
> +	uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
>   	struct arm_smccc_res res;
>   	u32 val[4];
>   
> -	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> -		return;
> -
> -	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> -	if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
> -	    res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
> -	    res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
> -	    res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
> +	if (!arm_smccc_hyp_present(&kvm_uuid))
>   		return;
>   
>   	memset(&res, 0, sizeof(res));
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index a74600d9f2d7..7399f27d58e5 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
> @@ -67,6 +67,25 @@ s32 arm_smccc_get_soc_id_revision(void)
>   }
>   EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
>   
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> +{
> +	struct arm_smccc_res res = {};
> +
> +	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> +		return false;
> +	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> +	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> +		return false;
> +
> +	return ({
> +		const uuid_t uuid = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
> +		const bool present = uuid_equal(&uuid, hyp_uuid);
> +
> +		present;
> +	});
> +}
> +EXPORT_SYMBOL_GPL(arm_smccc_hyp_present);
> +
>   static int __init smccc_devices_init(void)
>   {
>   	struct platform_device *pdev;
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 67f6fdf2e7cd..726f18221f1c 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -7,6 +7,11 @@
>   
>   #include <linux/args.h>
>   #include <linux/init.h>
> +
> +#ifndef __ASSEMBLER__
> +#include <linux/uuid.h>
> +#endif
> +
>   #include <uapi/linux/const.h>
>   
>   /*
> @@ -107,10 +112,10 @@
>   			   ARM_SMCCC_FUNC_QUERY_CALL_UID)
>   
>   /* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0	0xb66fb428U
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1	0xe911c52eU
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2	0x564bcaa9U
> -#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3	0x743a004dU
> +#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
> +	0xb66fb428, 0xc52e, 0xe911, \
> +	0xa9, 0xca, 0x4b, 0x56, \
> +	0x4d, 0x00, 0x3a, 0x74)
>   
>   /* KVM "vendor specific" services */
>   #define ARM_SMCCC_KVM_FUNC_FEATURES		0
> @@ -333,6 +338,48 @@ s32 arm_smccc_get_soc_id_version(void);
>    */
>   s32 arm_smccc_get_soc_id_revision(void);
>   
> +#ifndef __ASSEMBLER__
> +
> +/**
> + * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> + *
> + * Returns `true` if the hypervisor advertises its presence via SMCCC.
> + *
> + * When the function returns `false`, the caller shall not assume that
> + * there is no hypervisor running. Instead, the caller must fall back to
> + * other approaches if any are available.
> + */
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);
> +
> +#define SMCCC_RES_TO_UUID(r0, r1, r2, r3) \
> +	UUID_INIT( \
> +		cpu_to_le32(lower_32_bits(r0)), \
> +		cpu_to_le32(lower_32_bits(r1)) & 0xffff, \
> +		cpu_to_le32(lower_32_bits(r1)) >> 16, \
> +		cpu_to_le32(lower_32_bits(r2)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 24) & 0xff, \
> +		cpu_to_le32(lower_32_bits(r3)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 24) & 0xff \
> +	)
> +
> +#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
> +		const uuid_t uuid = uuid_init; \
> +		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
> +						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24)); \
> +		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
> +						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24)); \
> +		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
> +						((uuid.b[10]) << 16) | ((uuid.b[11]) << 24)); \
> +		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
> +						((uuid.b[14]) << 16) | ((uuid.b[15]) << 24)); \
> +	} while (0)
> +
> +#endif /* !__ASSEMBLER__ */
> +
>   /**
>    * struct arm_smccc_res - Result from SMC/HVC call
>    * @a0-a3 result values from registers 0 to 3

-- 
Thank you,
Roman



From namhyung at kernel.org  Fri Mar 14 18:11:58 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Fri, 14 Mar 2025 18:11:58 -0700
Subject: [PATCH v2] perf libunwind: Fixup conversion
 perf_sample->user_regs to a pointer
In-Reply-To: <20250313033121.758978-1-irogers@google.com>
References: <20250313033121.758978-1-irogers@google.com>
Message-ID: <Z9TT3tGq4TJ76Tm9@google.com>

On Wed, Mar 12, 2025 at 08:31:21PM -0700, Ian Rogers wrote:
> From: Arnaldo Carvalho de Melo <acme at redhat.com>
> 
> The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
> the changes to a file, resulting in this problem:
> 
>   $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
>   <SNIP>
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
>   <SNIP>
>   util/unwind-libunwind-local.c: In function ?access_mem?:
>   util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
>     582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
>         |                                                        ^
>         |                                                        ->
>   util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
>     587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
>         |                                      ^~~~~~~~~~~~~~~~~~~~~~
>         |                                      |
>         |                                      struct regs_dump **
> <SNIP>
>   ? [acme at toolbox perf-tools-next]$ git bisect bad
>   dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
>   commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
>   Author: Ian Rogers <irogers at google.com>
>   Date:   Mon Jan 13 11:43:45 2025 -0800
> 
>       perf sample: Make user_regs and intr_regs optional
> 
> Detected using:
> 
>   make -C tools/perf build-test
> 
> Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
> Cc: Adrian Hunter <adrian.hunter at intel.com>
> Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
> Cc: Andi Kleen <ak at linux.intel.com>
> Cc: Charlie Jenkins <charlie at rivosinc.com>
> Cc: Ian Rogers <irogers at google.com>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: James Clark <james.clark at linaro.org>
> Cc: John Garry <john.g.garry at oracle.com>
> Cc: Kan Liang <kan.liang at linux.intel.com>
> Cc: Leo Yan <leo.yan at linux.dev>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Michael Petlan <mpetlan at redhat.com>
> Cc: Namhyung Kim <namhyung at kernel.org>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Tavian Barnes <tavianator at tavianator.com>
> Cc: Veronika Molnarova <vmolnaro at redhat.com>
> Cc: coresight at lists.linaro.org
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>
> Reviewed-by: Ian Rogers <irogers at google.com>

I think you need to add your own Signed-off-by in this case.
I'll change it for you, ok?

Thanks,
Namhyung


> ---
> v2: Ensure user_regs isn't NULL when read, spotted by Namhyung.
> ---
>  tools/perf/util/unwind-libunwind-local.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
> index 16c2b03831f3..5f4387e2423a 100644
> --- a/tools/perf/util/unwind-libunwind-local.c
> +++ b/tools/perf/util/unwind-libunwind-local.c
> @@ -579,12 +579,12 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
>  	int ret;
>  
>  	/* Don't support write, probably not needed. */
> -	if (__write || !stack || !ui->sample->user_regs.regs) {
> +	if (__write || !stack || !ui->sample->user_regs || !ui->sample->user_regs->regs) {
>  		*valp = 0;
>  		return 0;
>  	}
>  
> -	ret = perf_reg_value(&start, &ui->sample->user_regs,
> +	ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample),
>  			     perf_arch_reg_sp(arch));
>  	if (ret)
>  		return ret;
> @@ -628,7 +628,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>  		return 0;
>  	}
>  
> -	if (!ui->sample->user_regs.regs) {
> +	if (!ui->sample->user_regs || !ui->sample->user_regs->regs) {
>  		*valp = 0;
>  		return 0;
>  	}
> @@ -637,7 +637,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
>  	if (id < 0)
>  		return -EINVAL;
>  
> -	ret = perf_reg_value(&val, &ui->sample->user_regs, id);
> +	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id);
>  	if (ret) {
>  		if (!ui->best_effort)
>  			pr_err("unwind: can't read reg %d\n", regnum);
> @@ -741,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
>  	unw_cursor_t c;
>  	int ret, i = 0;
>  
> -	ret = perf_reg_value(&val, &ui->sample->user_regs,
> +	ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample),
>  			     perf_arch_reg_ip(arch));
>  	if (ret)
>  		return ret;
> @@ -808,7 +808,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
>  		.best_effort  = best_effort
>  	};
>  
> -	if (!data->user_regs.regs)
> +	if (!data->user_regs || !data->user_regs->regs)
>  		return -EINVAL;
>  
>  	if (max_stack <= 0)
> -- 
> 2.49.0.rc0.332.g42c0ae87b1-goog
> 


From maudspierings at gocontroll.com  Sat Mar 15 00:33:47 2025
From: maudspierings at gocontroll.com (Maud Spierings | GOcontroll)
Date: Sat, 15 Mar 2025 07:33:47 +0000
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <20250314210652.GA2300828-robh@kernel.org>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
 <20250314210652.GA2300828-robh@kernel.org>
Message-ID: <ac1ccbbe6a4048a79210c6676a8aa691PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>

From:?Rob Herring <robh at kernel.org>
Sent:?Friday, March 14, 2025 10:06 PM
?
>On Wed, Feb 26, 2025 at 03:19:14PM +0100, Maud Spierings wrote:
>> Add the bindings that describe a GOcontroll Moduline module slot. This
>> slot provides all the interfaces to interface with a Moduline compatible
>> IO module. The actual module is not reasonable to describe as it can be
>> swapped at will, with this connector the driver will be able to probe
>> for a module on boot.
>>
>> The connector consists of 2 parts, one part for interfacing with the SoC
>> and main board, the other part has 13 IO channels for the module to
>> interact with the outside world. The functions of these IO channels are
>> determined by the type of module in the slot. The IO on the SoC side is
>> as follows:
>>
>> ?- a 3v3 supply, this tends to be the logic level of the module and its
>> ? ?microcontroller
>> ?- a 5v0 supply, this can be used to power low power peripherals on the
>> ? ?module
>> ?- a 6v-8v supply, this can be used for high power peripherals on the
>> ? ?module
>> ?- a 6v-30v supply, this tends to be a dirty supply that comes from the
>> ? ?controller supply after some circuit protection, or is the same as
>> ? ?the 6v-8v supply.
>> ?- an SPI bus which carries the communication between the SoC and the
>> ? ?microcontroller on the module.
>> ?- an I2C bus shared between the SoC and all module slots which can
>> ? ?carry direct module-to-module communication.
>> ?- a reset line
>> ?- an interrupt line that indicates a clear to transmit signal
>> ?- a sync line shared between the SoC and all module slots which could
>> ? ?be used to synchronize modules for time sensitive IO spread across
>> ? ?modules.
>> ?- a SMBus alert line that is shared between the modules but is not
>> ? ?connected to the SoC so that is ignored.
>>
>> A slot-number property is used to identify the physical location of a
>> module slot. Without it, it would be impossible to identify which module
>> to control if there are multiple of one type, to address the desired IO.
>
>Is that for a person to identify slots or s/w? If just a person, we
>generally use 'label' as in a sticker on the connector. If s/w, we
>generally try to avoid made up indexing in DT though there are some
>exceptions.

I guess both, I am not quite sure how the uapi will look like eventually.
Right now we just kind of know that spidev1.0 is slot 1 etc.

Maybe label: true could be enough but that seems to generic, it allows too
much wiggle room, if there is an eventual library that uses the kernel
uapi instead of the spidev interface it must be consistent. Or can the
label be restricted to being "moduleslot#"? I feel that numbers best
represent the way we lay out these module slots, and will provide the best
interface.

>> Signed-off-by: Maud Spierings <maudspierings at gocontroll.com>
>> ---
>> ?.../connector/gocontroll,moduline-module-slot.yaml | 88 ++++++++++++++++++++++
>> ?1 file changed, 88 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml b/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..a16ae2762d160180d5b163e20f5294235e65053b
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml
>> @@ -0,0 +1,88 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/connector/gocontroll,moduline-module-slot.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: GOcontroll Moduline Module slot
>> +
>> +maintainers:
>> + ?- Maud Spierings <maudspierings at gocontroll.com>
>> +
>> +description:
>> + ?The GOcontroll Moduline module slot represents a connector that fullfills the
>> + ?Moduline slot specification, and can thus house any IO module that is also
>> + ?built to this spec.
>> +
>> +properties:
>> + ?compatible:
>> + ? ?const: gocontroll,moduline-module-slot
>> +
>> + ?reg:
>> + ? ?maxItems: 1
>> +
>> + ?interrupts:
>> + ? ?description: indicates readiness, high means busy.
>> + ? ?maxItems: 1
>> + ?reset-gpios:
>> + ? ?description: resets the module, active low.
>> + ? ?maxItems: 1
>> + ?sync-gpios:
>> + ? ?description: sync line between all module slots.
>> + ? ?maxItems: 1
>> +
>> + ?vdd-supply:
>> + ? ?description: low power 3v3 supply generally for the microcontroller.
>> + ?vddp-supply:
>> + ? ?description: medium power 5v0 supply for on module low power peripherals.
>> + ?vddhpp-supply:
>> + ? ?description: high power 6v-8v supply for on module high power peripherals.
>> + ?power-supply:
>> + ? ?description: high power 6v-30v supply for high power module circuits.
>> +
>> + ?i2c-bus:
>> + ? ?description: i2c bus shared between module slots and the SoC
>> + ? ?$ref: /schemas/types.yaml#/definitions/phandle
>> +
>> + ?slot-number:
>> + ? ?description:
>> + ? ? ?The number of the module slot representing the location of on the pcb.
>> + ? ? ?This enables access to the modules based on slot location.
>> + ? ?$ref: /schemas/types.yaml#/definitions/uint32
>> +
>> + ?spi-max-frequency: true
>> +
>> +required:
>> + ?- compatible
>> + ?- reg
>> + ?- reset-gpios
>> + ?- interrupts
>> + ?- sync-gpios
>> + ?- i2c-bus
>> + ?- slot-number
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> + ?- |
>> + ? ?#include <dt-bindings/gpio/gpio.h>
>> + ? ?#include <dt-bindings/interrupt-controller/irq.h>
>> +
>> + ? ?spi {
>> + ? ? ? ?#address-cells = <1>;
>> + ? ? ? ?#size-cells = <0>;
>> +
>> + ? ? ? ?connector at 0 {
>
>I find this being a SPI device a bit strange. Is there a defined SPI
>device that every slot is going to have? Or the connector has SPI
>interface and *anything* could be attached on it?

So a module slot is like a pcie slot, it can be occupied or not, and when
it is occupied it can be any kind of module, but it can at least only be
one module, there is no hub like functionality.

On this module is a microcontroller or perhaps even an FPGA in the future
which is the spi-device, it has the miso, mosi, sclk and cs hooked up to
it.

For now this tends to be some kind of stm32f4xx, but it is very much not
set in stone. The only thing sure is there is some kind of module
controller that is hooked up to the spi device when a module is present.

So I would say it is option 2 of what you ask. But the 'anything' is
restricted to module compatible with the standard, its not just going to?
be some IC like an ADC chip like the mcp3004 that we use on the mainboard.

>> + ? ? ? ? ? ?reg = <0>;
>> + ? ? ? ? ? ?compatible = "gocontroll,moduline-module-slot";
>> + ? ? ? ? ? ?reset-gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
>> + ? ? ? ? ? ?sync-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
>> + ? ? ? ? ? ?interrupt-parent = <&gpio4>;
>> + ? ? ? ? ? ?interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
>> + ? ? ? ? ? ?vdd-supply = <&reg_3v3_per>;
>> + ? ? ? ? ? ?vddp-supply = <&reg_5v0>;
>> + ? ? ? ? ? ?vddhpp-supply = <&reg_6v4>;
>> + ? ? ? ? ? ?i2c-bus = <&i2c2>;
>> + ? ? ? ? ? ?slot-number = <1>;
>> + ? ? ? ?};
>> + ? ?};
>>
>> --
>> 2.48.1
>>

I hope this cleared everything up and the bindings are still okay

Kind Regards,
Maud

From eddyz87 at gmail.com  Sat Mar 15 01:06:05 2025
From: eddyz87 at gmail.com (Eduard Zingerman)
Date: Sat, 15 Mar 2025 01:06:05 -0700
Subject: [PATCH bpf-next 02/11] bpf: Return -EFAULT on misconfigurations
In-Reply-To: <20250313172127.1098195-3-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	 <20250313172127.1098195-3-luis.gerhorst@fau.de>
Message-ID: <785b4531ce3b44a84059a4feb4ba458c68fce719.camel@gmail.com>

On Thu, 2025-03-13 at 18:21 +0100, Luis Gerhorst wrote:
> Mark these cases as non-recoverable to later prevent them from being
> cought when they occur during speculative path verification.
> 
> Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
> Acked-by: Henriette Herzog <henriette.herzog at rub.de>
> Cc: Maximilian Ott <ott at cs.fau.de>
> Cc: Milan Stephan <milan.stephan at fau.de>
> ---

The only pace I'm aware of that might act upon specific error code
from verifier syscall is libbpf. Looking through libbpf code, it seems
that this change does not interfere with libbpf.

Reviewed-by: Eduard Zingerman <eddyz87 at gmail.com>

[...]



From eddyz87 at gmail.com  Sat Mar 15 01:07:01 2025
From: eddyz87 at gmail.com (Eduard Zingerman)
Date: Sat, 15 Mar 2025 01:07:01 -0700
Subject: [PATCH bpf-next 03/11] bpf: Return -EFAULT on internal errors
In-Reply-To: <20250313172919.1103397-1-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	 <20250313172919.1103397-1-luis.gerhorst@fau.de>
Message-ID: <46a0770582be4f8f80701aca4eb17b1706609033.camel@gmail.com>

On Thu, 2025-03-13 at 18:29 +0100, Luis Gerhorst wrote:
> This prevents us from trying to recover from these on speculative paths
> in the future.
> 
> Signed-off-by: Luis Gerhorst <luis.gerhorst at fau.de>
> Acked-by: Henriette Herzog <henriette.herzog at rub.de>
> Cc: Maximilian Ott <ott at cs.fau.de>
> Cc: Milan Stephan <milan.stephan at fau.de>
> ---

Same as for previous patch.

Reviewed-by: Eduard Zingerman <eddyz87 at gmail.com>

[...]



From jonas at kwiboo.se  Sat Mar 15 01:20:07 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sat, 15 Mar 2025 09:20:07 +0100
Subject: [PATCH v3 3/6] thermal: rockchip: Support RK3576 SoC in the
 thermal driver
In-Reply-To: <20250228-rk3576-tsadc-upstream-v3-3-4bfbb3b699b9@collabora.com>
References: <20250228-rk3576-tsadc-upstream-v3-0-4bfbb3b699b9@collabora.com>
 <20250228-rk3576-tsadc-upstream-v3-3-4bfbb3b699b9@collabora.com>
Message-ID: <6c355664-50dd-4efd-94b7-9d93c02d3e80@kwiboo.se>

Hi Nicolas,

On 2025-02-28 21:06, Nicolas Frattaroli wrote:
> From: Ye Zhang <ye.zhang at rock-chips.com>
> 
> The RK3576 SoC has six TS-ADC channels: TOP, BIG_CORE, LITTLE_CORE,
> DDR, NPU and GPU.
> 
> Signed-off-by: Ye Zhang <ye.zhang at rock-chips.com>
> [ported to mainline, reworded commit message]
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> ---
>  drivers/thermal/rockchip_thermal.c | 42 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
> index a8ad85feb68fbb7ec8d79602b16c47838ecb3c00..bec1930bebd87859a7e519cfc9f05e10b1c31e87 100644
> --- a/drivers/thermal/rockchip_thermal.c
> +++ b/drivers/thermal/rockchip_thermal.c
> @@ -1061,6 +1061,22 @@ static void rk_tsadcv3_tshut_mode(int chn, void __iomem *regs,
>  	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
>  }
>  
> +static void rk_tsadcv4_tshut_mode(int chn, void __iomem *regs,
> +				  enum tshut_mode mode)
> +{
> +	u32 val_gpio, val_cru;
> +
> +	if (mode == TSHUT_MODE_GPIO) {
> +		val_gpio = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
> +		val_cru = TSADCV2_INT_SRC_EN_MASK(chn);
> +	} else {
> +		val_cru = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
> +		val_gpio = TSADCV2_INT_SRC_EN_MASK(chn);
> +	}
> +	writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN);
> +	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
> +}

This function is identical to rk_tsadcv3_tshut_mode() in mainline.

Should the v3 function be renamed to v4 in mainline to match vendor
kernel to avoid confusion?

> +
>  static const struct rockchip_tsadc_chip px30_tsadc_data = {
>  	/* cpu, gpu */
>  	.chn_offset = 0,
> @@ -1284,6 +1300,28 @@ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
>  	},
>  };
>  
> +static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
> +	/* top, big_core, little_core, ddr, npu, gpu */
> +	.chn_offset = 0,
> +	.chn_num = 6, /* six channels for tsadc */
> +	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
> +	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
> +	.tshut_temp = 95000,

Here the default is GPIO and 95 deg, in DT node the default is override
to CRU and 120 deg.

Any reason that is not the default here?

Regards,
Jonas

> +	.initialize = rk_tsadcv8_initialize,
> +	.irq_ack = rk_tsadcv4_irq_ack,
> +	.control = rk_tsadcv4_control,
> +	.get_temp = rk_tsadcv4_get_temp,
> +	.set_alarm_temp = rk_tsadcv3_alarm_temp,
> +	.set_tshut_temp = rk_tsadcv3_tshut_temp,
> +	.set_tshut_mode = rk_tsadcv4_tshut_mode,
> +	.table = {
> +		.id = rk3588_code_table,
> +		.length = ARRAY_SIZE(rk3588_code_table),
> +		.data_mask = TSADCV4_DATA_MASK,
> +		.mode = ADC_INCREMENT,
> +	},
> +};
> +
>  static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
>  	/* top, big_core0, big_core1, little_core, center, gpu, npu */
>  	.chn_offset = 0,
> @@ -1342,6 +1380,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
>  		.compatible = "rockchip,rk3568-tsadc",
>  		.data = (void *)&rk3568_tsadc_data,
>  	},
> +	{
> +		.compatible = "rockchip,rk3576-tsadc",
> +		.data = (void *)&rk3576_tsadc_data,
> +	},
>  	{
>  		.compatible = "rockchip,rk3588-tsadc",
>  		.data = (void *)&rk3588_tsadc_data,
> 



From lkp at intel.com  Sat Mar 15 01:24:59 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 15 Mar 2025 16:24:59 +0800
Subject: [PATCH 4/5] media: vcodec: Implement manual request completion
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b@collabora.com>
Message-ID: <202503151605.1d1dDLuM-lkp@intel.com>

Hi Sebastian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f2151613e040973c868d28c8b00885dfab69eb75]

url:    https://github.com/intel-lab-lkp/linux/commits/Sebastian-Fricke/media-mc-add-manual-request-completion/20250314-213005
base:   f2151613e040973c868d28c8b00885dfab69eb75
patch link:    https://lore.kernel.org/r/20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b%40collabora.com
patch subject: [PATCH 4/5] media: vcodec: Implement manual request completion
config: x86_64-buildonly-randconfig-003-20250315 (https://download.01.org/0day-ci/archive/20250315/202503151605.1d1dDLuM-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
rustc: rustc 1.78.0 (9b00956e5 2024-04-29)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250315/202503151605.1d1dDLuM-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503151605.1d1dDLuM-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c:29:13: warning: no previous prototype for function 'state_to_str' [-Wmissing-prototypes]
      29 | const char *state_to_str(enum mtk_request_state state)
         |             ^
   drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c:29:7: note: declare 'static' if the function is not intended to be used outside of this translation unit
      29 | const char *state_to_str(enum mtk_request_state state)
         |       ^
         | static 
   1 warning generated.


vim +/state_to_str +29 drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c

    28	
  > 29	const char *state_to_str(enum mtk_request_state state)
    30	{
    31		switch (state) {
    32		case MTK_REQUEST_RECEIVED:
    33			return "RECEIVED";
    34		case MTK_REQUEST_LAT_DONE:
    35			return "LAT_DONE";
    36		case MTK_REQUEST_CORE_DONE:
    37			return "CORE_DONE";
    38		default:
    39			return "UNKNOWN";
    40		}
    41	}
    42	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From dan.carpenter at linaro.org  Sat Mar 15 01:28:25 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Sat, 15 Mar 2025 11:28:25 +0300
Subject: [bug report] arm64/mm: Clear PXX_TYPE_MASK and set PXD_TYPE_SECT
 in [pmd|pud]_mkhuge()
In-Reply-To: <Z9RsxL98s23mvqJa@arm.com>
References: <d7902504-1ed4-452f-9b08-148f6b8b69fd@stanley.mountain>
 <Z9RsxL98s23mvqJa@arm.com>
Message-ID: <f8cf7bf8-4162-4846-bdcb-4793e4aeb439@stanley.mountain>

On Fri, Mar 14, 2025 at 05:52:04PM +0000, Catalin Marinas wrote:
> On Fri, Mar 14, 2025 at 01:54:01PM +0300, Dan Carpenter wrote:
> > Hello Anshuman Khandual,
> > 
> > Commit 1601df9e366e ("arm64/mm: Clear PXX_TYPE_MASK and set
> > PXD_TYPE_SECT in [pmd|pud]_mkhuge()") from Feb 21, 2025 (linux-next),
> > leads to the following (unpublished) Smatch static checker warning:
> > 
> > arch/arm64/include/asm/pgtable.h:587 pmd_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'
> > arch/arm64/include/asm/pgtable.h:626 pud_mkhuge() warn: odd binop '0x1 & 0xfffffffffffffffe'
> > 
> > arch/arm64/include/asm/pgtable.h
> >     579 static inline pmd_t pmd_mkhuge(pmd_t pmd)
> >     580 {
> >     581         /*
> >     582          * It's possible that the pmd is present-invalid on entry
> >     583          * and in that case it needs to remain present-invalid on
> >     584          * exit. So ensure the VALID bit does not get modified.
> >     585          */
> >     586         pmdval_t mask = PMD_TYPE_MASK & ~PTE_VALID;
> > --> 587         pmdval_t val = PMD_TYPE_SECT & ~PTE_VALID;
> > 
> > This is "1 & ~1".  I see the comment, but I'm too stupid to know even
> > after reading he comment whether it's intentional or not.  :P
> > 
> >     588 
> >     589         return __pmd((pmd_val(pmd) & ~mask) | val);
> >     590 }
> 
> Prior to the above commit, the code was:
> 
> #define pmd_mkhuge(pmd)			(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
> 
> So just clearing a bit. That's why the reworked code has val 0 in the
> current configuration. This may change with support for 128-bit PTEs
> though, different format.
> 
> The comment is about preserving the PTE_VALID bit in the original pmd
> value, so it's masked out of both mask and val.
> 
> It's good that smatch catches these though. Any way to mark a false
> positive?

In the kernel, all old warnings are false positives.  We're good at
fixing things.  People can look it up on lore and find this thread
if they have questions.

regards,
dan carpenter



From boris.brezillon at collabora.com  Sat Mar 15 01:43:38 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Sat, 15 Mar 2025 09:43:38 +0100
Subject: [PATCH v2 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250314173858.212264-5-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
	<20250314173858.212264-5-ariel.dalessandro@collabora.com>
Message-ID: <20250315094338.5f402426@collabora.com>

On Fri, 14 Mar 2025 14:38:56 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> Address Extension", which in Linux we've called "mali_lpae".
> 
> This commit adds support for conditionally enabling AARCH64_4K page
> table format. To achieve that, a "GPU optional quirks" field was added
> to `struct panfrost_features` with the related flag.
> 
> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> the HW_FEATURE_AARCH64_MMU feature flag present.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>  drivers/gpu/drm/panfrost/panfrost_mmu.c    | 136 +++++++++++++++++++--
>  drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>  3 files changed, 177 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> index cffcb0ac7c111..ad95f2ed31d9a 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>  	GPU_PM_VREG_OFF,
>  };
>  
> +/**
> + * enum panfrost_gpu_quirks - GPU optional quirks
> + * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
> + */
> +enum panfrost_gpu_quirks {
> +	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
> +};
> +
>  struct panfrost_features {
>  	u16 id;
>  	u16 revision;
> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>  
>  	/* Allowed PM features */
>  	u8 pm_features;
> +
> +	/* GPU configuration quirks */
> +	u8 gpu_quirks;
>  };
>  
>  struct panfrost_device {
> @@ -162,6 +173,11 @@ struct panfrost_mmu {
>  	int as;
>  	atomic_t as_count;
>  	struct list_head list;
> +	struct {
> +		u64 transtab;
> +		u64 memattr;
> +		u64 transcfg;
> +	} cfg;
>  };
>  
>  struct panfrost_engine_usage {
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 294f86b3c25e7..f24c23e1f67b8 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -26,6 +26,48 @@
>  #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
>  #define mmu_read(dev, reg) readl(dev->iomem + reg)
>  
> +static u64 mair_to_memattr(u64 mair, bool coherent)
> +{
> +	u64 memattr = 0;
> +	u32 i;
> +
> +	for (i = 0; i < 8; i++) {
> +		u8 in_attr = mair >> (8 * i), out_attr;
> +		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
> +
> +		/* For caching to be enabled, inner and outer caching policy
> +		 * have to be both write-back, if one of them is write-through
> +		 * or non-cacheable, we just choose non-cacheable. Device
> +		 * memory is also translated to non-cacheable.
> +		 */
> +		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
> +				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
> +		} else {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
> +			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
> +			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
> +			 * to Mali's internal-shareable mode. As per the Mali
> +			 * Spec, inner and outer-shareable modes aren't allowed
> +			 * for WB memory when coherency is disabled.
> +			 * Use SH_CPU_INNER mode when coherency is enabled, so
> +			 * that SH_IS actually maps to the standard definition of
> +			 * inner-shareable.
> +			 */
> +			if (!coherent)
> +				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
> +			else
> +				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
> +		}
> +
> +		memattr |= (u64)out_attr << (8 * i);
> +	}
> +
> +	return memattr;
> +}
> +
>  static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
>  {
>  	int ret;
> @@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>  static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
>  	int as_nr = mmu->as;
> -	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> -	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> -	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
> +	u64 transtab = mmu->cfg.transtab;
> +	u64 memattr = mmu->cfg.memattr;
> +	u64 transcfg = mmu->cfg.transcfg;
>  
>  	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>  
> @@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>  
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
> +
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>  }
>  
> @@ -152,9 +197,66 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
>  
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
> +
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>  }
>  
> +static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	/* TODO: The following fields are duplicated between the MMU and Page
> +	 * Table config structs. Ideally, should be kept in one place.
> +	 */
> +	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
> +	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
> +	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
> +
> +	return 0;
> +}
> +
> +static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
> +				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
> +		return -EINVAL;
> +
> +	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> +
> +	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
> +					   pgtbl_cfg->coherent_walk);
> +
> +	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
> +			    AS_TRANSCFG_PTW_RA |
> +			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
> +			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
> +	if (pgtbl_cfg->coherent_walk)
> +		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
> +
> +	return 0;
> +}
> +
> +static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
> +				  enum io_pgtable_fmt fmt)
> +{
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	switch (fmt) {
> +	case ARM_64_LPAE_S1:
> +		return mmu_cfg_init_aarch64_4k(mmu);
> +	case ARM_MALI_LPAE:
> +		return mmu_cfg_init_mali_lpae(mmu);
> +	default:
> +		/* This should never happen */
> +		return drm_WARN_ON(pfdev->ddev, -EINVAL);
> +	}
> +}
> +
>  u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
>  	int as;
> @@ -618,6 +720,18 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>  	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
>  	struct panfrost_mmu *mmu;
> +	enum io_pgtable_fmt fmt;
> +
> +	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
> +			dev_err_once(pfdev->dev,
> +				     "AARCH64_4K page table not supported\n");
> +			return ERR_PTR(-EINVAL);
> +		}
> +		fmt = ARM_64_LPAE_S1;
> +	} else {
> +		fmt = ARM_MALI_LPAE;
> +	}
>  
>  	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>  	if (!mmu)
> @@ -642,16 +756,20 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  		.iommu_dev	= pfdev->dev,
>  	};
>  
> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
> -					      mmu);
> -	if (!mmu->pgtbl_ops) {
> -		kfree(mmu);
> -		return ERR_PTR(-EINVAL);
> -	}
> +	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
> +	if (!mmu->pgtbl_ops)
> +		goto err_free_mmu;
> +
> +	if (panfrost_mmu_cfg_init(mmu, fmt))
> +		goto err_free_mmu;

How about propagating the error returned by panfrost_mmu_cfg_init()
instead of assuming it's always -EINVAL on failure? Oh, and you need to
call free_io_pgtable_ops(), not just kfree().

With this addressed, this is

Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>

>  
>  	kref_init(&mmu->refcount);
>  
>  	return mmu;
> +
> +err_free_mmu:
> +	kfree(mmu);
> +	return ERR_PTR(-EINVAL);
>  }
>  
>  static const char *access_type_name(struct panfrost_device *pfdev,
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index b5f279a19a084..2b8f1617b8369 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -301,6 +301,17 @@
>  #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
>  #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
>  #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
> +							 ((w) ? BIT(0) : 0) | \
> +							 ((r) ? BIT(1) : 0))
> +#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
> +#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
> +#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
>  #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
>  #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
>  #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
> @@ -311,6 +322,24 @@
>  /* Additional Bifrost AS registers */
>  #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
>  #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
> +#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
> +#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
> +#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
> +#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
> +#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
> +#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
> +#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
> +#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
> +#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
> +#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
> +#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
> +#define   AS_TRANSCFG_PTW_RA				BIT(30)
> +#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
> +#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
> +#define   AS_TRANSCFG_WXN				BIT(35)
> +#define   AS_TRANSCFG_XREADABLE				BIT(36)
>  #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
>  #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>  
> @@ -326,6 +355,11 @@
>  #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
>  #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
>  
> +/*
> + * Begin AARCH64_4K MMU TRANSTAB register values
> + */
> +#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
> +
>  #define AS_STATUS_AS_ACTIVE			0x01
>  
>  #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)



From boris.brezillon at collabora.com  Sat Mar 15 01:46:57 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Sat, 15 Mar 2025 09:46:57 +0100
Subject: [PATCH v2 5/6] drm/panfrost: Force AARCH64_4K page table format
 on MediaTek MT8188
In-Reply-To: <20250314173858.212264-6-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
	<20250314173858.212264-6-ariel.dalessandro@collabora.com>
Message-ID: <20250315094657.7939e532@collabora.com>

On Fri, 14 Mar 2025 14:38:57 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> MediaTek MT8188 SoC has an ARM Mali-G57 MC3 GPU (Valhall-JM), which
> constantly faults with the current panfrost support.
> 
> For instance, running `glmark2-es2-drm` benchmark test:
> ```
> [   79.617461] panfrost 13000000.gpu: js fault, js=1, status=JOB_BUS_FAULT, head=0xaadc380, tail=0xaadc380
> [   80.119811] panfrost 13000000.gpu: gpu sched timeout, js=0, config=0x7300, status=0x58, head=0xaaca180, tail=0xaaca180, sched_job=000000002fd03ccc
> [   80.129083] panfrost 13000000.gpu: Unhandled Page fault in AS0 at VA 0x0000000000000000
> [   80.129083] Reason: TODO
> [   80.129083] raw fault status: 0x1C2
> [   80.129083] decoded fault status: SLAVE FAULT
> [   80.129083] exception type 0xC2: TRANSLATION_FAULT_2
> [   80.129083] access type 0x1: EXECUTE
> [   80.129083] source id 0x0
> ```
> 
> Note that current panfrost mode (Mali LPAE - LEGACY) only allows to
> specify write-cache or implementation-defined as the caching policy,
> probably not matching the right configuration. As depicted in the source
> code:
> 
> drivers/iommu/io-pgtable-arm.c:
> ```
> * MEMATTR: Mali has no actual notion of a non-cacheable type, so the
> * best we can do is mimic the out-of-tree driver and hope that the
> * "implementation-defined caching policy" is good enough...
> ```
> 
> Now that Panfrost supports AARCH64_4K page table format, let's enable it
> on Mediatek MT8188 and configure the cache/shareability policies
> properly.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 0f3935556ac76..e854f290858f9 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
>  	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
>  	.pm_domain_names = mediatek_mt8183_pm_domains,
>  	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
> +	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
>  };
>  
>  static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };



From boris.brezillon at collabora.com  Sat Mar 15 01:47:22 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Sat, 15 Mar 2025 09:47:22 +0100
Subject: [PATCH v2 6/6] drm/panfrost: Force AARCH64_4K page table format
 on MediaTek MT8192
In-Reply-To: <20250314173858.212264-7-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
	<20250314173858.212264-7-ariel.dalessandro@collabora.com>
Message-ID: <20250315094722.4c4804c6@collabora.com>

On Fri, 14 Mar 2025 14:38:58 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
> Panfrost supports AARCH64_4K page table format, let's enable it on this
> SoC.
> 
> Running glmark2-es2-drm [0] benchmark, reported the same performance
> score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
> this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.
> 
> [0] https://github.com/glmark2/glmark2
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index e854f290858f9..ef30d314b2281 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -836,6 +836,7 @@ static const struct panfrost_compatible mediatek_mt8192_data = {
>  	.num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains),
>  	.pm_domain_names = mediatek_mt8192_pm_domains,
>  	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
> +	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
>  };
>  
>  static const struct of_device_id dt_match[] = {



From herbert at gondor.apana.org.au  Sat Mar 15 02:16:56 2025
From: herbert at gondor.apana.org.au (Herbert Xu)
Date: Sat, 15 Mar 2025 17:16:56 +0800
Subject: [PATCH v2] dt-bindings: rng: rockchip,rk3588-rng: Drop
 unnecessary status from example
In-Reply-To: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
References: <20250307093309.44950-1-krzysztof.kozlowski@linaro.org>
Message-ID: <Z9VFiLMFtzBMIAtQ@gondor.apana.org.au>

On Fri, Mar 07, 2025 at 10:33:09AM +0100, Krzysztof Kozlowski wrote:
> Device nodes are enabled by default, so no need for 'status = "okay"' in
> the DTS example.
> 
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> ---
> 
> Changes in v2:
> 1. Drop unnecessary full stop in subject prefix after ':'.
> 2. Add Rb tag.
> ---
>  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
>  1 file changed, 1 deletion(-)

Patch applied.  Thanks.

Please disregard the previous reply incorrectly sent for v1.
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


From akihiko.odaki at daynix.com  Sat Mar 15 02:12:09 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:09 +0900
Subject: [PATCH v5 0/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Message-ID: <20250315-pmc-v5-0-ecee87dab216@daynix.com>

Prepare vPMC registers for user-initiated changes after first run. This
is important specifically for debugging Windows on QEMU with GDB; QEMU
tries to write back all visible registers when resuming the VM execution
with GDB, corrupting the PMU state. Windows always uses the PMU so this
can cause adverse effects on that particular OS.

This series also contains patch "KVM: arm64: PMU: Set raw values from
user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
changes made for the mentioned registers in the past. It is necessary
to migrate the PMU state properly on Firecracker, QEMU, and crosvm.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
Changes in v5:
- Rebased.
- Link to v4: https://lore.kernel.org/r/20250313-pmc-v4-0-2c976827118c at daynix.com

Changes in v4:
- Reverted changes for functions implementing ioctls in patch
  "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
- Removed kvm_pmu_vcpu_reset().
- Reordered function calls in kvm_vcpu_reload_pmu() for better style.
- Link to v3: https://lore.kernel.org/r/20250312-pmc-v3-0-0411cab5dc3d at daynix.com

Changes in v3:
- Added patch "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
- Added an explanation of this path series' motivation to each patch.
- Explained why userspace register writes and register reset should be
  covered in patch "KVM: arm64: PMU: Reload when user modifies
  registers".
- Marked patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" for stable.
- Reoreded so that patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" would come first.
- Added patch "KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking
  PMCNTENSET_EL0".
- Added patch "KVM: arm64: Reload PMCNTENSET_EL0".
- Link to v2: https://lore.kernel.org/r/20250307-pmc-v2-0-6c3375a5f1e4 at daynix.com

Changes in v2:
- Changed to utilize KVM_REQ_RELOAD_PMU as suggested by Oliver Upton.
- Added patch "KVM: arm64: PMU: Reload when user modifies registers"
  to cover more registers.
- Added patch "KVM: arm64: PMU: Set raw values from user to
  PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}".
- Link to v1: https://lore.kernel.org/r/20250302-pmc-v1-1-caff989093dc at daynix.com

---
Akihiko Odaki (5):
      KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
      KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
      KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
      KVM: arm64: PMU: Reload when user modifies registers
      KVM: arm64: PMU: Reload when resetting

 arch/arm64/kvm/arm.c            | 17 ++++++++-----
 arch/arm64/kvm/emulate-nested.c |  6 +++--
 arch/arm64/kvm/pmu-emul.c       | 56 +++++++++++------------------------------
 arch/arm64/kvm/reset.c          |  3 ---
 arch/arm64/kvm/sys_regs.c       | 52 ++++++++++++++++++++++----------------
 include/kvm/arm_pmu.h           |  4 +--
 6 files changed, 62 insertions(+), 76 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250302-pmc-b90a86af945c

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From akihiko.odaki at daynix.com  Sat Mar 15 02:12:10 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:10 +0900
Subject: [PATCH v5 1/5] KVM: arm64: PMU: Set raw values from user to
 PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <20250315-pmc-v5-1-ecee87dab216@daynix.com>

Commit a45f41d754e0 ("KVM: arm64: Add {get,set}_user for
PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}") changed KVM_SET_ONE_REG to update
the mentioned registers in a way matching with the behavior of guest
register writes. This is a breaking change of a UAPI though the new
semantics looks cleaner and VMMs are not prepared for this.

Firecracker, QEMU, and crosvm perform migration by listing registers
with KVM_GET_REG_LIST, getting their values with KVM_GET_ONE_REG and
setting them with KVM_SET_ONE_REG. This algorithm assumes
KVM_SET_ONE_REG restores the values retrieved with KVM_GET_ONE_REG
without any alteration. However, bit operations added by the earlier
commit do not preserve the values retried with KVM_GET_ONE_REG and
potentially break migration.

Remove the bit operations that alter the values retrieved with
KVM_GET_ONE_REG.

Cc: stable at vger.kernel.org
Fixes: a45f41d754e0 ("KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
Acked-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/sys_regs.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 82430c1e1dd0..ffee72fd1273 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1051,26 +1051,9 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
 static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
 {
-	bool set;
-
-	val &= kvm_pmu_accessible_counter_mask(vcpu);
-
-	switch (r->reg) {
-	case PMOVSSET_EL0:
-		/* CRm[1] being set indicates a SET register, and CLR otherwise */
-		set = r->CRm & 2;
-		break;
-	default:
-		/* Op2[0] being set indicates a SET register, and CLR otherwise */
-		set = r->Op2 & 1;
-		break;
-	}
-
-	if (set)
-		__vcpu_sys_reg(vcpu, r->reg) |= val;
-	else
-		__vcpu_sys_reg(vcpu, r->reg) &= ~val;
+	u64 mask = kvm_pmu_accessible_counter_mask(vcpu);
 
+	__vcpu_sys_reg(vcpu, r->reg) = val & mask;
 	return 0;
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Sat Mar 15 02:12:11 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:11 +0900
Subject: [PATCH v5 2/5] KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <20250315-pmc-v5-2-ecee87dab216@daynix.com>

Many functions in pmu-emul.c checks kvm_vcpu_has_pmu(vcpu). A favorable
interpretation is defensive programming, but it also has downsides:

- It is confusing as it implies these functions are called without PMU
  although most of them are called only when a PMU is present.

- It makes semantics of functions fuzzy. For example, calling
  kvm_pmu_disable_counter_mask() without PMU may result in no-op as
  there are no enabled counters, but it's unclear what
  kvm_pmu_get_counter_value() returns when there is no PMU.

- It allows callers without checking kvm_vcpu_has_pmu(vcpu), but it is
  often wrong to call these functions without PMU.

- It is error-prone to duplicate kvm_vcpu_has_pmu(vcpu) checks into
  multiple functions. Many functions are called for system registers,
  and the system register infrastructure already employs less
  error-prone, comprehensive checks.

Check kvm_vcpu_has_pmu(vcpu) in callers of these functions instead,
and remove the obsolete checks from pmu-emul.c. The only exceptions are
the functions that implement ioctls as they have definitive semantics
even when the PMU is not present.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/arm.c            | 17 +++++++++++------
 arch/arm64/kvm/emulate-nested.c |  6 ++++--
 arch/arm64/kvm/pmu-emul.c       | 26 +-------------------------
 arch/arm64/kvm/sys_regs.c       |  6 ++++--
 4 files changed, 20 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0160b4924351..caa1357fa367 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -835,9 +835,11 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
-	ret = kvm_arm_pmu_v3_enable(vcpu);
-	if (ret)
-		return ret;
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		ret = kvm_arm_pmu_v3_enable(vcpu);
+		if (ret)
+			return ret;
+	}
 
 	if (is_protected_kvm_enabled()) {
 		ret = pkvm_create_hyp_vm(kvm);
@@ -1148,7 +1150,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		 */
 		preempt_disable();
 
-		kvm_pmu_flush_hwstate(vcpu);
+		if (kvm_vcpu_has_pmu(vcpu))
+			kvm_pmu_flush_hwstate(vcpu);
 
 		local_irq_disable();
 
@@ -1167,7 +1170,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		if (ret <= 0 || kvm_vcpu_exit_request(vcpu, &ret)) {
 			vcpu->mode = OUTSIDE_GUEST_MODE;
 			isb(); /* Ensure work in x_flush_hwstate is committed */
-			kvm_pmu_sync_hwstate(vcpu);
+			if (kvm_vcpu_has_pmu(vcpu))
+				kvm_pmu_sync_hwstate(vcpu);
 			if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
 				kvm_timer_sync_user(vcpu);
 			kvm_vgic_sync_hwstate(vcpu);
@@ -1197,7 +1201,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		 * that the vgic can properly sample the updated state of the
 		 * interrupt line.
 		 */
-		kvm_pmu_sync_hwstate(vcpu);
+		if (kvm_vcpu_has_pmu(vcpu))
+			kvm_pmu_sync_hwstate(vcpu);
 
 		/*
 		 * Sync the vgic state before syncing the timer state because
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 607d37bab70b..9293fb078fc6 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2516,7 +2516,8 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
 	kvm_arch_vcpu_load(vcpu, smp_processor_id());
 	preempt_enable();
 
-	kvm_pmu_nested_transition(vcpu);
+	if (kvm_vcpu_has_pmu(vcpu))
+		kvm_pmu_nested_transition(vcpu);
 }
 
 static void kvm_inject_el2_exception(struct kvm_vcpu *vcpu, u64 esr_el2,
@@ -2599,7 +2600,8 @@ static int kvm_inject_nested(struct kvm_vcpu *vcpu, u64 esr_el2,
 	kvm_arch_vcpu_load(vcpu, smp_processor_id());
 	preempt_enable();
 
-	kvm_pmu_nested_transition(vcpu);
+	if (kvm_vcpu_has_pmu(vcpu))
+		kvm_pmu_nested_transition(vcpu);
 
 	return 1;
 }
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 6c5950b9ceac..98fdc65f5b24 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -150,9 +150,6 @@ static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
  */
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	return kvm_pmu_get_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
 }
 
@@ -191,9 +188,6 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
  */
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
@@ -350,7 +344,7 @@ void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu) || !val)
+	if (!val)
 		return;
 
 	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) {
@@ -401,9 +395,6 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
 	bool overflow;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	overflow = kvm_pmu_overflow_status(vcpu);
 	if (pmu->irq_level == overflow)
 		return;
@@ -599,9 +590,6 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
 {
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	/* Fixup PMCR_EL0 to reconcile the PMU version and the LP bit */
 	if (!kvm_has_feat(vcpu->kvm, ID_AA64DFR0_EL1, PMUVer, V3P5))
 		val &= ~ARMV8_PMU_PMCR_LP;
@@ -766,9 +754,6 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
 	struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, select_idx);
 	u64 reg;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	reg = counter_index_to_evtreg(pmc->idx);
 	__vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm);
 
@@ -848,9 +833,6 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
 	u64 val, mask = 0;
 	int base, i, nr_events;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!pmceid1) {
 		val = read_sysreg(pmceid0_el0);
 		/* always support CHAIN */
@@ -900,9 +882,6 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
 
 int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 {
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return 0;
-
 	if (!vcpu->arch.pmu.created)
 		return -EINVAL;
 
@@ -1231,9 +1210,6 @@ void kvm_pmu_nested_transition(struct kvm_vcpu *vcpu)
 	unsigned long mask;
 	int i;
 
-	if (!kvm_vcpu_has_pmu(vcpu))
-		return;
-
 	mask = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
 	for_each_set_bit(i, &mask, 32) {
 		struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index ffee72fd1273..e8e9c781a929 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1853,12 +1853,14 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu,
 				      const struct sys_reg_desc *rd)
 {
-	u8 perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
+	u8 perfmon;
 	u64 val = read_sanitised_ftr_reg(SYS_ID_DFR0_EL1);
 
 	val &= ~ID_DFR0_EL1_PerfMon_MASK;
-	if (kvm_vcpu_has_pmu(vcpu))
+	if (kvm_vcpu_has_pmu(vcpu)) {
+		perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit());
 		val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon);
+	}
 
 	val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, Debugv8p8);
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Sat Mar 15 02:12:12 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:12 +0900
Subject: [PATCH v5 3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <20250315-pmc-v5-3-ecee87dab216@daynix.com>

Reload the perf event when setting the vPMU counter (vPMC) registers
(PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

It is also important to keep the correct state even if userspace writes
them after first run, specifically when debugging Windows on QEMU with
GDB; QEMU tries to write back all visible registers when resuming the VM
execution with GDB, corrupting the PMU state. Windows always uses the
PMU so this can cause adverse effects on that particular OS.

Fix this by releasing the current perf event and trigger recreating one
with KVM_REQ_RELOAD_PMU.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 13 +++++++++++++
 arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
 include/kvm/arm_pmu.h     |  2 ++
 3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 98fdc65f5b24..593216bc14f0 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -191,6 +191,19 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
 }
 
+/**
+ * kvm_pmu_set_counter_value_user - set PMU counter value from user
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ * @val: The counter value
+ */
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+{
+	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+}
+
 /**
  * kvm_pmu_release_perf_event - remove the perf event
  * @pmc: The PMU counter pointer
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e8e9c781a929..4d1ef47d0049 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -960,6 +960,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 	return 0;
 }
 
+static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+			  u64 val)
+{
+	u64 idx;
+
+	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+		/* PMCCNTR_EL0 */
+		idx = ARMV8_PMU_CYCLE_IDX;
+	else
+		/* PMEVCNTRn_EL0 */
+		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+	kvm_pmu_set_counter_value_user(vcpu, idx, val);
+	return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      const struct sys_reg_desc *r)
@@ -1238,6 +1254,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 #define PMU_PMEVCNTR_EL0(n)						\
 	{ PMU_SYS_REG(PMEVCNTRn_EL0(n)),				\
 	  .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,		\
+	  .set_user = set_pmu_evcntr,					\
 	  .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -2835,7 +2852,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  .access = access_pmceid, .reset = NULL },
 	{ PMU_SYS_REG(PMCCNTR_EL0),
 	  .access = access_pmu_evcntr, .reset = reset_unknown,
-	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
+	  .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
+	  .set_user = set_pmu_evcntr },
 	{ PMU_SYS_REG(PMXEVTYPER_EL0),
 	  .access = access_pmu_evtyper, .reset = NULL },
 	{ PMU_SYS_REG(PMXEVCNTR_EL0),
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 147bd3ee4f7b..b6d0a682505d 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -47,8 +47,10 @@ static __always_inline bool kvm_arm_support_pmu_v3(void)
 #define kvm_arm_pmu_irq_initialized(v)	((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
+void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu);
+u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);

-- 
2.48.1



From akihiko.odaki at daynix.com  Sat Mar 15 02:12:13 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:13 +0900
Subject: [PATCH v5 4/5] KVM: arm64: PMU: Reload when user modifies
 registers
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <20250315-pmc-v5-4-ecee87dab216@daynix.com>

Commit d0c94c49792c ("KVM: arm64: Restore PMU configuration on first
run") added the code to reload the PMU configuration on first run.

It is also important to keep the correct state even if system registers
are modified after first run, specifically when debugging Windows on
QEMU with GDB; QEMU tries to write back all visible registers when
resuming the VM execution with GDB, corrupting the PMU state. Windows
always uses the PMU so this can cause adverse effects on that particular
OS.

The usual register writes and reset are already handled independently,
but register writes from userspace are not covered.
Trigger the code to reload the PMU configuration for them instead so
that PMU configuration changes made by users will be applied also after
the first run.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 3 ---
 arch/arm64/kvm/sys_regs.c | 4 ++++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 593216bc14f0..8e10124a7420 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -917,9 +917,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
 		   return -EINVAL;
 	}
 
-	/* One-off reload of the PMU on first run */
-	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 4d1ef47d0049..727579acc7f6 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1070,6 +1070,8 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
 	u64 mask = kvm_pmu_accessible_counter_mask(vcpu);
 
 	__vcpu_sys_reg(vcpu, r->reg) = val & mask;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 
@@ -1228,6 +1230,8 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
 		val |= ARMV8_PMU_PMCR_LC;
 
 	__vcpu_sys_reg(vcpu, r->reg) = val;
+	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
 	return 0;
 }
 

-- 
2.48.1



From akihiko.odaki at daynix.com  Sat Mar 15 02:12:14 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Sat, 15 Mar 2025 18:12:14 +0900
Subject: [PATCH v5 5/5] KVM: arm64: PMU: Reload when resetting
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <20250315-pmc-v5-5-ecee87dab216@daynix.com>

Replace kvm_pmu_vcpu_reset() with the generic PMU reloading mechanism to
ensure the consistency with system registers and to reduce code size.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/pmu-emul.c | 14 --------------
 arch/arm64/kvm/reset.c    |  3 ---
 arch/arm64/kvm/sys_regs.c |  3 +++
 include/kvm/arm_pmu.h     |  2 --
 4 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 8e10124a7420..aae5713d8993 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -254,20 +254,6 @@ void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
 		pmu->pmc[i].idx = i;
 }
 
-/**
- * kvm_pmu_vcpu_reset - reset pmu state for cpu
- * @vcpu: The vcpu pointer
- *
- */
-void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
-{
-	unsigned long mask = kvm_pmu_implemented_counter_mask(vcpu);
-	int i;
-
-	for_each_set_bit(i, &mask, 32)
-		kvm_pmu_stop_counter(kvm_vcpu_idx_to_pmc(vcpu, i));
-}
-
 /**
  * kvm_pmu_vcpu_destroy - free perf event of PMU for cpu
  * @vcpu: The vcpu pointer
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 803e11b0dc8f..f82fcc614e13 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -196,9 +196,6 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 	vcpu->arch.reset_state.reset = false;
 	spin_unlock(&vcpu->arch.mp_state_lock);
 
-	/* Reset PMU outside of the non-preemptible section */
-	kvm_pmu_vcpu_reset(vcpu);
-
 	preempt_disable();
 	loaded = (vcpu->cpu != -1);
 	if (loaded)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 727579acc7f6..14f66c7a4545 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -4480,6 +4480,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 	}
 
 	set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
+
+	if (kvm_vcpu_has_pmu(vcpu))
+		kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 }
 
 /**
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index b6d0a682505d..d6ad13925978 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -53,7 +53,6 @@ u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
 void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
-void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val);
 void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu);
@@ -126,7 +125,6 @@ static inline u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu)
 	return 0;
 }
 static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
-static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
 static inline void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) {}

-- 
2.48.1



From herbert at gondor.apana.org.au  Sat Mar 15 02:15:44 2025
From: herbert at gondor.apana.org.au (Herbert Xu)
Date: Sat, 15 Mar 2025 17:15:44 +0800
Subject: [PATCH] dt-bindings: rng: rockchip,rk3588-rng.: Drop unnecessary
 status from example
In-Reply-To: <20250307081406.35242-1-krzysztof.kozlowski@linaro.org>
References: <20250307081406.35242-1-krzysztof.kozlowski@linaro.org>
Message-ID: <Z9VFQOjcFxJLAlfr@gondor.apana.org.au>

On Fri, Mar 07, 2025 at 09:14:06AM +0100, Krzysztof Kozlowski wrote:
> Device nodes are enabled by default, so no need for 'status = "okay"' in
> the DTS example.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  Documentation/devicetree/bindings/rng/rockchip,rk3588-rng.yaml | 1 -
>  1 file changed, 1 deletion(-)

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


From o.rempel at pengutronix.de  Sat Mar 15 02:25:40 2025
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Sat, 15 Mar 2025 10:25:40 +0100
Subject: [PATCH] ARM: dts: opos6ul: add ksz8081 phy properties
In-Reply-To: <20250314-opos6ul-fix-ethernet-v1-1-1c0172949b40@armadeus.com>
References: <20250314-opos6ul-fix-ethernet-v1-1-1c0172949b40@armadeus.com>
Message-ID: <Z9VHlE-5lvtoYFYb@pengutronix.de>

On Fri, Mar 14, 2025 at 05:20:38PM +0100, S?bastien Szymanski wrote:
> Commit c7e73b5051d6 ("ARM: imx: mach-imx6ul: remove 14x14 EVK specific
> PHY fixup") removed a PHY fixup that setted the clock mode and the LED
> mode.
> Make the Ethernet interface work again by doing as advised in the
> commit's log, set clock mode and the LED mode in the device tree.
> 
> Fixes: c7e73b5051d6 ("ARM: imx: mach-imx6ul: remove 14x14 EVK specific PHY fixup")
> Signed-off-by: S?bastien Szymanski <sebastien.szymanski at armadeus.com>

Looks good to me. Thank you!
Reviewed by: Oleksij Rempel <o.rempel at pengutronix.de>

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sdl at nppct.ru  Sat Mar 15 03:29:01 2025
From: sdl at nppct.ru (Alexey Nepomnyashih)
Date: Sat, 15 Mar 2025 10:29:01 +0000
Subject: [PATCH 6.1] media: mediatek: vcodec: Fix VP8 stateless decoder smatch warning
Message-ID: <20250315102903.3634639-1-sdl@nppct.ru>

From: Yunfei Dong <yunfei.dong at mediatek.com>

commit b113bc7c0e83b32f4dd2d291a2b6c4803e0a2c44 upstream.

Fix a smatch static checker warning on vdec_vp8_req_if.c.
Which leads to a kernel crash when fb is NULL.

Fixes: 7a7ae26fd458 ("media: mediatek: vcodec: support stateless VP8 decoding")
Signed-off-by: Yunfei Dong <yunfei.dong at mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Signed-off-by: Sebastian Fricke <sebastian.fricke at collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco at xs4all.nl>
[ Alexey Nepomnyashih: changed mtk_vdec_err() to mtk_vcodec_err. ]
Signed-off-by: Alexey Nepomnyashih <sdl at nppct.ru>
---
 .../platform/mediatek/vcodec/vdec/vdec_vp8_req_if.c    | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_req_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_req_if.c
index e1fe2603e92e..22d8f178b04d 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_req_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp8_req_if.c
@@ -336,14 +336,18 @@ static int vdec_vp8_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
 	src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
 
 	fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
-	dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
+	if (!fb) {
+		mtk_vcodec_err(inst, "fb buffer is NULL");
+		return -ENOMEM;
+	}
 
-	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
+	y_fb_dma = fb->base_y.dma_addr;
 	if (inst->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
 		c_fb_dma = y_fb_dma +
 			inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h;
 	else
-		c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+		c_fb_dma = fb->base_c.dma_addr;
 
 	inst->vsi->dec.bs_dma = (u64)bs->dma_addr;
 	inst->vsi->dec.bs_sz = bs->size;
-- 
2.43.0



From lkp at intel.com  Sat Mar 15 03:36:04 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 15 Mar 2025 18:36:04 +0800
Subject: [PATCH 4/5] media: vcodec: Implement manual request completion
In-Reply-To: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b@collabora.com>
References: <20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b@collabora.com>
Message-ID: <202503151824.EfaOfTwf-lkp@intel.com>

Hi Sebastian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f2151613e040973c868d28c8b00885dfab69eb75]

url:    https://github.com/intel-lab-lkp/linux/commits/Sebastian-Fricke/media-mc-add-manual-request-completion/20250314-213005
base:   f2151613e040973c868d28c8b00885dfab69eb75
patch link:    https://lore.kernel.org/r/20250314-sebastianfricke-vcodec_manual_request_completion_with_state_machine-v1-4-5e277a3d695b%40collabora.com
patch subject: [PATCH 4/5] media: vcodec: Implement manual request completion
config: arm-randconfig-001-20250315 (https://download.01.org/0day-ci/archive/20250315/202503151824.EfaOfTwf-lkp at intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250315/202503151824.EfaOfTwf-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503151824.EfaOfTwf-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c:29:13: warning: no previous prototype for 'state_to_str' [-Wmissing-prototypes]
      29 | const char *state_to_str(enum mtk_request_state state)
         |             ^~~~~~~~~~~~


vim +/state_to_str +29 drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c

    28	
  > 29	const char *state_to_str(enum mtk_request_state state)
    30	{
    31		switch (state) {
    32		case MTK_REQUEST_RECEIVED:
    33			return "RECEIVED";
    34		case MTK_REQUEST_LAT_DONE:
    35			return "LAT_DONE";
    36		case MTK_REQUEST_CORE_DONE:
    37			return "CORE_DONE";
    38		default:
    39			return "UNKNOWN";
    40		}
    41	}
    42	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From ansuelsmth at gmail.com  Sat Mar 15 03:52:59 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 11:52:59 +0100
Subject: [net-next PATCH v12 09/13] mfd: an8855: Add support for Airoha
 AN8855 Switch MFD
In-Reply-To: <20250314113551.GK3890718@google.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-10-ansuelsmth@gmail.com>
 <20250314113551.GK3890718@google.com>
Message-ID: <67d55c0e.7b0a0220.32becc.f4d0@mx.google.com>

On Fri, Mar 14, 2025 at 11:35:51AM +0000, Lee Jones wrote:
> On Sun, 09 Mar 2025, Christian Marangi wrote:
> 
> > Add support for Airoha AN8855 Switch MFD that provide support for a DSA
> 
> Drop all references to MFD.
> 
> It doesn't exist.  It is a figment of your (and my) imagination.
> 
> > switch and a NVMEM provider. Also provide support for a virtual MDIO
> > passthrough as the PHYs address for the switch are shared with the switch
> > address.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
> >  MAINTAINERS                 |   1 +
> >  drivers/mfd/Kconfig         |  10 +
> >  drivers/mfd/Makefile        |   1 +
> >  drivers/mfd/airoha-an8855.c | 445 ++++++++++++++++++++++++++++++++++++
> >  4 files changed, 457 insertions(+)
> >  create mode 100644 drivers/mfd/airoha-an8855.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index b7075425c94e..5844addbda2b 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -730,6 +730,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
> >  F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
> >  F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> >  F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
> > +F:	drivers/mfd/airoha-an8855.c
> >  
> >  AIROHA ETHERNET DRIVER
> >  M:	Lorenzo Bianconi <lorenzo at kernel.org>
> > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > index 6b0682af6e32..1b5abe5e2694 100644
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -53,6 +53,16 @@ config MFD_ALTERA_SYSMGR
> >  	  using regmap_mmio accesses for ARM32 parts and SMC calls to
> >  	  EL3 for ARM64 parts.
> >  
> > +config MFD_AIROHA_AN8855
> 
> Should this be EN?
>

In official internal documentation this is referenced with AN8855...

EN stands for EcoNet, Airoha then brought it so there currently a mix of
name with old driver using EN and new one AN. This switch is new enough
to use AN.

> 
> > +	tristate "Airoha AN8855 Switch MFD"
> > +	select MFD_CORE
> > +	select MDIO_DEVICE
> > +	depends on NETDEVICES && OF
> > +	help
> > +	  Support for the Airoha AN8855 Switch MFD. This is a SoC Switch
> 
> Nit: "an SoC".
> 
> What kind of switch?
> 
> > +	  that provides various peripherals. Currently it provides a
> 
> Which other peripherals?
> 
> > +	  DSA switch and a NVMEM provider.
> > +
> >  config MFD_ACT8945A
> >  	tristate "Active-semi ACT8945A"
> >  	select MFD_CORE
> > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> > index 9220eaf7cf12..37677f65a981 100644
> > --- a/drivers/mfd/Makefile
> > +++ b/drivers/mfd/Makefile
> > @@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
> >  obj-$(CONFIG_MFD_88PM800)	+= 88pm800.o 88pm80x.o
> >  obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
> >  obj-$(CONFIG_MFD_88PM886_PMIC)	+= 88pm886.o
> > +obj-$(CONFIG_MFD_AIROHA_AN8855)	+= airoha-an8855.o
> >  obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
> >  obj-$(CONFIG_MFD_SM501)		+= sm501.o
> >  obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835-pm.o
> > diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
> > new file mode 100644
> > index 000000000000..0a6440bd4118
> > --- /dev/null
> > +++ b/drivers/mfd/airoha-an8855.c
> > @@ -0,0 +1,445 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * MFD driver for Airoha AN8855 Switch
> 
> No such thing as an MFD driver.
> 
> Core is sometimes used in place of a better name.
> 
> > + */
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/mfd/core.h>
> > +#include <linux/mdio.h>
> > +#include <linux/mdio/mdio-regmap.h>
> > +#include <linux/module.h>
> > +#include <linux/phy.h>
> > +#include <linux/regmap.h>
> > +
> > +/* Register for hw trap status */
> 
> Ironically, this is probably the most readable name, yet it is the only
> one graced with a comment.  Also 'hw' is an abbreviation, so it should be
> HW or H/W or better yet hardware.
> 
> > +#define AN8855_HWTRAP			0x1000009c
> > +
> > +#define AN8855_CREV			0x10005000
> 
> Chip?
> 
> > +#define   AN8855_ID			0x8855
> 
> What kid of ID?  Chip, revision, model, serial?
> 
> > +#define AN8855_RG_GPHY_AFE_PWD		0x1028c840
> 
> No idea!
> 

There magic name are the 1:1 map of the register on the internal
documentation. Honestly it would put more harm than good to rename these
register to a more symbolic name since it would make it even harder to
find them.

> > +/* MII Registers */
> > +#define AN8855_PHY_SELECT_PAGE		0x1f
> > +#define   AN8855_PHY_PAGE		GENMASK(2, 0)
> > +#define   AN8855_PHY_PAGE_STANDARD	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
> > +#define   AN8855_PHY_PAGE_EXTENDED_1	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
> > +#define   AN8855_PHY_PAGE_EXTENDED_4	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
> > +
> > +/* MII Registers Page 4 */
> > +#define AN8855_PBUS_MODE		0x10
> > +#define   AN8855_PBUS_MODE_ADDR_FIXED	0x0
> > +#define AN8855_PBUS_MODE_ADDR_INCR	BIT(15)
> > +#define AN8855_PBUS_WR_ADDR_HIGH	0x11
> > +#define AN8855_PBUS_WR_ADDR_LOW		0x12
> > +#define AN8855_PBUS_WR_DATA_HIGH	0x13
> > +#define AN8855_PBUS_WR_DATA_LOW		0x14
> > +#define AN8855_PBUS_RD_ADDR_HIGH	0x15
> > +#define AN8855_PBUS_RD_ADDR_LOW		0x16
> > +#define AN8855_PBUS_RD_DATA_HIGH	0x17
> > +#define AN8855_PBUS_RD_DATA_LOW		0x18
> > +
> > +struct an8855_mfd_priv {
> 
> It's not an "mfd".
> 
> > +	struct mii_bus *bus;
> > +
> > +	unsigned int switch_addr;
> > +	u16 current_page;
> > +};
> > +
> > +static const struct mfd_cell an8855_mfd_devs[] = {
> 
> "_child_" or "_sub_" or drop it entirely.
> 
> > +	{
> > +		.name = "an8855-efuse",
> > +		.of_compatible = "airoha,an8855-efuse",
> > +	}, {
> > +		.name = "an8855-switch",
> > +		.of_compatible = "airoha,an8855-switch",
> > +	}, {
> > +		.name = "an8855-mdio",
> > +		.of_compatible = "airoha,an8855-mdio",
> > +	}
> > +};
> > +
> > +static int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id,
> > +			       u8 page) __must_hold(&priv->bus->mdio_lock)
> > +{
> > +	struct mii_bus *bus = priv->bus;
> > +	int ret;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page);
> 
> Calling functions with '__' is a red flag.
> 

As already explained it's an unlucky name, __ was used at times
probably to stress that this is an internal variant with no lock and
should be used ONLY when actually intended (this is the case as the
function enforce locking with the __must_hold)

> > +	if (ret < 0)
> > +		dev_err_ratelimited(&bus->dev,
> > +				    "failed to set an8855 mii page\n");
> 
> Use 100-chars if it avoids these kind of line breaks.
> 
> > +	/* Cache current page if next mii read/write is for switch */
> 
> MII here?
> 
> "this switch"?
> 
> I don't see any checks here - how do we know if it is for switch or not?
> 

Check is done in an855_regmap_phy_reset_page.

> > +	priv->current_page = page;
> > +	return ret < 0 ? ret : 0;
> 
> You already check for 'ret < 0' at the call sites, so this little dance
> is superfluous.
> 
> > +}
> > +
> > +static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
> > +			     u32 *val) __must_hold(&bus->mdio_lock)
> > +{
> > +	int lo, hi, ret;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> > +			      AN8855_PBUS_MODE_ADDR_FIXED);
> 
> 100-chars.
> 
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
> > +			      upper_16_bits(reg));
> > +	if (ret < 0)
> > +		goto err;
> 
> '\n'
> 

The idea for these operation without extra line were to pack the upper
and lower part to form the full 32bit value. But ok will split.

> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
> > +			      lower_16_bits(reg));
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
> > +	if (hi < 0) {
> > +		ret = hi;
> > +		goto err;
> > +	}
> 
> '\n'
> 
> > +	lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
> > +	if (lo < 0) {
> > +		ret = lo;
> > +		goto err;
> > +	}
> > +
> > +	*val = ((u16)hi << 16) | ((u16)lo & 0xffff);
> > +
> > +	return 0;
> > +err:
> > +	dev_err_ratelimited(&bus->dev,
> > +			    "failed to read an8855 register\n");
> 
> dev_err() will already print out the an8855 part.
> 
> > +	return ret;
> > +}
> > +
> > +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 addr = priv->switch_addr;
> > +	int ret;
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> 
> guard()?
> 

Problem is that we can't even use scoped_guard as there isn't a variant
with MUTEX_NESTED. This patch is already bit enough that I didn't want
to pollute it more for it. If it's not a problem I will send a followup
later.

> > +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> > +	if (ret < 0)
> > +		goto exit;
> > +
> > +	ret = an8855_mii_read32(bus, addr, reg, val);
> > +
> > +exit:
> > +	mutex_unlock(&bus->mdio_lock);
> > +
> > +	return ret < 0 ? ret : 0;
> > +}
> > +
> > +static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
> > +			      u32 val) __must_hold(&bus->mdio_lock)
> > +{
> > +	int ret;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
> > +			      AN8855_PBUS_MODE_ADDR_FIXED);
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
> > +			      upper_16_bits(reg));
> > +	if (ret < 0)
> > +		goto err;
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
> > +			      lower_16_bits(reg));
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
> > +			      upper_16_bits(val));
> > +	if (ret < 0)
> > +		goto err;
> > +	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
> > +			      lower_16_bits(val));
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	return 0;
> > +err:
> > +	dev_err_ratelimited(&bus->dev,
> > +			    "failed to write an8855 register\n");
> > +	return ret;
> > +}
> > +
> > +static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 addr = priv->switch_addr;
> > +	int ret;
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> > +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> > +	if (ret < 0)
> > +		goto exit;
> > +
> > +	ret = an8855_mii_write32(bus, addr, reg, val);
> > +
> > +exit:
> > +	mutex_unlock(&bus->mdio_lock);
> > +
> > +	return ret < 0 ? ret : 0;
> 
> Doesn't the caller already expect possible >0 results?
> 
> > +}
> > +
> > +static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
> > +				     uint32_t write_val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 addr = priv->switch_addr;
> > +	u32 val;
> > +	int ret;
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> > +	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
> > +	if (ret < 0)
> > +		goto exit;
> > +
> > +	ret = an8855_mii_read32(bus, addr, reg, &val);
> > +	if (ret < 0)
> > +		goto exit;
> > +
> > +	val &= ~mask;
> > +	val |= write_val;
> > +	ret = an8855_mii_write32(bus, addr, reg, val);
> > +
> > +exit:
> > +	mutex_unlock(&bus->mdio_lock);
> > +
> > +	return ret < 0 ? ret : 0;
> > +}
> > +
> > +static const struct regmap_range an8855_readable_ranges[] = {
> > +	regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
> > +	regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
> > +	regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
> > +	regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
> > +	regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
> > +	regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
> > +	regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
> > +	regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
> > +	regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
> > +	regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
> > +	regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
> > +	regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
> > +	regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
> > +	regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
> > +	regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
> > +	regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
> > +	regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
> > +	regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
> > +	regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
> > +	regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
> > +	regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
> > +	regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
> > +	regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
> > +	regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
> > +	regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
> > +	regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
> > +	regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
> > +};
> > +
> > +static const struct regmap_access_table an8855_readable_table = {
> > +	.yes_ranges = an8855_readable_ranges,
> > +	.n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
> > +};
> > +
> > +static const struct regmap_config an8855_regmap_config = {
> > +	.name = "switch",
> > +	.reg_bits = 32,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +	.max_register = 0xbfffffff,
> > +	.reg_read = an8855_regmap_read,
> > +	.reg_write = an8855_regmap_write,
> > +	.reg_update_bits = an8855_regmap_update_bits,
> > +	.disable_locking = true,
> > +	.rd_table = &an8855_readable_table,
> > +};
> > +
> > +static int an855_regmap_phy_reset_page(struct an8855_mfd_priv *priv,
> > +				       int phy) __must_hold(&priv->bus->mdio_lock)
> > +{
> > +	/* Check PHY page only for addr shared with switch */
> > +	if (phy != priv->switch_addr)
> > +		return 0;
> > +
> > +	/* Don't restore page if it's not set to switch page */
> > +	if (priv->current_page != FIELD_GET(AN8855_PHY_PAGE,
> > +					    AN8855_PHY_PAGE_EXTENDED_4))
> > +		return 0;
> > +
> > +	/* Restore page to 0, PHY might change page right after but that
> > +	 * will be ignored as it won't be a switch page.
> > +	 */
> 
> Use proper multi-line comments please.
> 
> > +	return an8855_mii_set_page(priv, phy, AN8855_PHY_PAGE_STANDARD);
> > +}
> > +
> > +static int an8855_regmap_phy_read(void *ctx, uint32_t reg, uint32_t *val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 phy_id, addr;
> > +	int ret;
> > +
> > +	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
> > +	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> > +	ret = an855_regmap_phy_reset_page(priv, phy_id);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = __mdiobus_read(priv->bus, phy_id, addr);
> > +
> > +exit:
> > +	mutex_unlock(&bus->mdio_lock);
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	*val = ret;
> > +	return 0;
> > +}
> > +
> > +static int an8855_regmap_phy_write(void *ctx, uint32_t reg, uint32_t val)
> > +{
> > +	struct an8855_mfd_priv *priv = ctx;
> > +	struct mii_bus *bus = priv->bus;
> > +	u16 phy_id, addr;
> > +	int ret;
> > +
> > +	phy_id = FIELD_GET(MDIO_REGMAP_PHY_ADDR, reg);
> > +	addr = FIELD_GET(MDIO_REGMAP_PHY_REG, reg);
> > +
> > +	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
> > +	ret = an855_regmap_phy_reset_page(priv, phy_id);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = __mdiobus_write(priv->bus, phy_id, addr, val);
> > +
> > +exit:
> > +	mutex_unlock(&bus->mdio_lock);
> > +
> > +	return ret;
> > +}
> > +
> > +/* Regmap for MDIO Passtrough
> > + * PHY Addr and PHY Reg are encoded in the regmap register.
> > + */
> > +static const struct regmap_config an8855_regmap_phy_config = {
> > +	.name = "phy",
> > +	.reg_bits = 20,
> > +	.val_bits = 16,
> > +	.reg_stride = 1,
> > +	.max_register = MDIO_REGMAP_PHY_ADDR | MDIO_REGMAP_PHY_REG,
> > +	.reg_read = an8855_regmap_phy_read,
> > +	.reg_write = an8855_regmap_phy_write,
> > +	.disable_locking = true,
> > +};
> > +
> > +static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
> > +{
> > +	u32 id;
> > +	int ret;
> > +
> > +	ret = regmap_read(regmap, AN8855_CREV, &id);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (id != AN8855_ID) {
> > +		dev_err(dev, "Switch ID detected %x but expected %x\n",
> 
> "Detected Switch ID %x but %x was expected"
> 
> Or
> 
> "Expected Switch ID %x but %x was detected"
> 
> > +			id, AN8855_ID);
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int an8855_mfd_probe(struct mdio_device *mdiodev)
> > +{
> > +	struct regmap *regmap, *regmap_phy;
> > +	struct device *dev = &mdiodev->dev;
> > +	struct an8855_mfd_priv *priv;
> > +	struct gpio_desc *reset_gpio;
> > +	u32 val;
> > +	int ret;
> > +
> > +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->bus = mdiodev->bus;
> > +	priv->switch_addr = mdiodev->addr;
> > +	/* no DMA for mdiobus, mute warning for DMA mask not set */
> 
> Nit: Please start sentences with uppercase chars.
> 
> > +	dev->dma_mask = &dev->coherent_dma_mask;
> > +
> > +	regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
> > +	if (IS_ERR(regmap))
> > +		return dev_err_probe(dev, PTR_ERR(regmap),
> > +				     "regmap initialization failed\n");
> > +
> > +	regmap_phy = devm_regmap_init(dev, NULL, priv, &an8855_regmap_phy_config);
> > +	if (IS_ERR(regmap_phy))
> > +		return dev_err_probe(dev, PTR_ERR(regmap_phy),
> > +				     "regmap phy initialization failed\n");
> > +
> > +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > +	if (IS_ERR(reset_gpio))
> > +		return PTR_ERR(reset_gpio);
> > +
> > +	if (reset_gpio) {
> > +		usleep_range(100000, 150000);
> > +		gpiod_set_value_cansleep(reset_gpio, 0);
> > +		usleep_range(100000, 150000);
> > +		gpiod_set_value_cansleep(reset_gpio, 1);
> > +
> > +		/* Poll HWTRAP reg to wait for Switch to fully Init */
> > +		ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
> > +					       val, 20, 200000);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	ret = an8855_read_switch_id(dev, regmap);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Release global PHY power down */
> > +	ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_mfd_devs,
> > +				    ARRAY_SIZE(an8855_mfd_devs), NULL, 0,
> > +				    NULL);
> > +}
> > +
> > +static const struct of_device_id an8855_mfd_of_match[] = {
> > +	{ .compatible = "airoha,an8855" },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, an8855_mfd_of_match);
> > +
> > +static struct mdio_driver an8855_mfd_driver = {
> > +	.probe = an8855_mfd_probe,
> > +	.mdiodrv.driver = {
> > +		.name = "an8855",
> > +		.of_match_table = an8855_mfd_of_match,
> > +	},
> > +};
> > +mdio_module_driver(an8855_mfd_driver);
> > +
> > +MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
> > +MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.48.1
> > 
> 
> -- 
> Lee Jones [???]

-- 
	Ansuel


From lorenzo at kernel.org  Sat Mar 15 05:04:20 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Sat, 15 Mar 2025 13:04:20 +0100
Subject: [PATCH net-next v2] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
Message-ID: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>

The system occasionally crashes dereferencing a NULL pointer when it is
forwarding constant, high load bidirectional traffic.

[ 2149.913414] Unable to handle kernel read from unreadable memory at virtual address 0000000000000000
[ 2149.925812] Mem abort info:
[ 2149.928713]   ESR = 0x0000000096000005
[ 2149.932762]   EC = 0x25: DABT (current EL), IL = 32 bits
[ 2149.938429]   SET = 0, FnV = 0
[ 2149.941814]   EA = 0, S1PTW = 0
[ 2149.945187]   FSC = 0x05: level 1 translation fault
[ 2149.950348] Data abort info:
[ 2149.953472]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
[ 2149.959243]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 2149.964593]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 2149.970243] user pgtable: 4k pages, 39-bit VAs, pgdp=000000008b507000
[ 2149.977068] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
[ 2149.986062] Internal error: Oops: 0000000096000005 [#1] SMP
[ 2150.082282]  arht_wrapper(O) i2c_core arht_hook(O) crc32_generic
[ 2150.177623] CPU: 0 PID: 38 Comm: kworker/u9:1 Tainted: G           O       6.6.73 #0
[ 2150.185362] Hardware name: Airoha AN7581 Evaluation Board (DT)
[ 2150.191189] Workqueue: nf_ft_offload_add nf_flow_rule_route_ipv6 [nf_flow_table]
[ 2150.198653] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 2150.205615] pc : airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
[ 2150.211882] lr : airoha_ppe_flow_offload_replace.isra.0+0x6cc/0xc54
[ 2150.218149] sp : ffffffc080e8ba10
[ 2150.221456] x29: ffffffc080e8bae0 x28: ffffff80080b0000 x27: 0000000000000000
[ 2150.228591] x26: ffffff8001c70020 x25: 0000000000000002 x24: 0000000000000000
[ 2150.235727] x23: 0000000061000000 x22: 00000000ffffffed x21: ffffffc080e8bbb0
[ 2150.242862] x20: ffffff8001c70000 x19: 0000000000000008 x18: 0000000000000000
[ 2150.249998] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
[ 2150.257133] x14: 0000000000000001 x13: 0000000000000008 x12: 0101010101010101
[ 2150.264268] x11: 7f7f7f7f7f7f7f7f x10: 0000000000000041 x9 : 0000000000000000
[ 2150.271404] x8 : ffffffc080e8bad8 x7 : 0000000000000000 x6 : 0000000000000015
[ 2150.278540] x5 : ffffffc080e8ba4e x4 : 0000000000000004 x3 : 0000000000000000
[ 2150.285675] x2 : 0000000000000008 x1 : 00000000080b0000 x0 : 0000000000000000
[ 2150.292811] Call trace:
[ 2150.295250]  airoha_ppe_flow_offload_replace.isra.0+0x6dc/0xc54
[ 2150.301171]  airoha_ppe_setup_tc_block_cb+0x7c/0x8b4
[ 2150.306135]  nf_flow_offload_ip_hook+0x710/0x874 [nf_flow_table]
[ 2150.312168]  nf_flow_rule_route_ipv6+0x53c/0x580 [nf_flow_table]
[ 2150.318200]  process_one_work+0x178/0x2f0
[ 2150.322211]  worker_thread+0x2e4/0x4cc
[ 2150.325953]  kthread+0xd8/0xdc
[ 2150.329008]  ret_from_fork+0x10/0x20
[ 2150.332589] Code: b9007bf7 b4001e9c f9448380 b9491381 (f9400000)
[ 2150.338681] ---[ end trace 0000000000000000 ]---
[ 2150.343298] Kernel panic - not syncing: Oops: Fatal exception
[ 2150.349035] SMP: stopping secondary CPUs
[ 2150.352954] Kernel Offset: disabled
[ 2150.356438] CPU features: 0x0,00000000,00000000,1000400b
[ 2150.361743] Memory Limit: none

Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
routine.

Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support")
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
Changes in v2:
- Avoid checking netdev_priv pointer since it is always not NULL
- Link to v1: https://lore.kernel.org/r/20250312-airoha-flowtable-null-ptr-fix-v1-1-6363fab884d0 at kernel.org
---
 drivers/net/ethernet/airoha/airoha_eth.c | 13 +++++++++++++
 drivers/net/ethernet/airoha/airoha_eth.h |  3 +++
 drivers/net/ethernet/airoha/airoha_ppe.c | 10 ++++++++--
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index c0a642568ac115ea9df6fbaf7133627a4405a36c..bf9c882e9c8b087dbf5e907636547a0117d1b96a 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2454,6 +2454,19 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
 	}
 }
 
+int airoha_is_valid_gdm_port(struct airoha_eth *eth,
+			     struct airoha_gdm_port *port)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+		if (eth->ports[i] == port)
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int airoha_alloc_gdm_port(struct airoha_eth *eth,
 				 struct device_node *np, int index)
 {
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index f66b9b736b9447b31afc036eb906d0a1c617e132..c7d4f124d11481cd31c1566936cd47e3446877c0 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
 #define airoha_qdma_clear(qdma, offset, val)			\
 	airoha_rmw((qdma)->regs, (offset), (val), 0)
 
+int airoha_is_valid_gdm_port(struct airoha_eth *eth,
+			     struct airoha_gdm_port *port);
+
 void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
 int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 				 void *cb_priv);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 8b55e871352d359fa692c253d3f3315c619472b3..65833e2058194a64569eafec08b80df8190bba6c 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
 #endif
 }
 
-static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
+static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
+					struct airoha_foe_entry *hwe,
 					struct net_device *dev, int type,
 					struct airoha_flow_data *data,
 					int l4proto)
@@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
 	if (dev) {
 		struct airoha_gdm_port *port = netdev_priv(dev);
 		u8 pse_port;
+		int err;
+
+		err = airoha_is_valid_gdm_port(eth, port);
+		if (err)
+			return err;
 
 		if (dsa_port >= 0)
 			pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
@@ -633,7 +639,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
 	    !is_valid_ether_addr(data.eth.h_dest))
 		return -EINVAL;
 
-	err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
+	err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
 					   &data, l4proto);
 	if (err)
 		return err;

---
base-commit: bfc6c67ec2d64d0ca4e5cc3e1ac84298a10b8d62
change-id: 20250312-airoha-flowtable-null-ptr-fix-a4656d12546a

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From festevam at gmail.com  Sat Mar 15 05:08:41 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Sat, 15 Mar 2025 09:08:41 -0300
Subject: [PATCH] ARM: dts: imx51-digi-connectcore-som: Fix MMX7455 compatible
Message-ID: <20250315120841.1836214-1-festevam@gmail.com>

From: Fabio Estevam <festevam at denx.de>

According to fsl,mma7455.yaml, the correct compatible string is
"fsl,mma7455".

Change it accordingly to fix the following dt-schema warning:

failed to match any schema with compatible: ['fsl,mma7455l']

Signed-off-by: Fabio Estevam <festevam at denx.de>
---
 arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
index dc72a2d14960..1980f751f161 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
@@ -165,7 +165,7 @@ &i2c2 {
 	mma7455l at 1d {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_mma7455l>;
-		compatible = "fsl,mma7455l";
+		compatible = "fsl,mma7455";
 		reg = <0x1d>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>, <6 IRQ_TYPE_LEVEL_HIGH>;
-- 
2.34.1



From festevam at gmail.com  Sat Mar 15 05:10:54 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Sat, 15 Mar 2025 09:10:54 -0300
Subject: [PATCH v2] ARM: dts: imx51-digi-connectcore-som: Fix MMA7455 compatible
Message-ID: <20250315121054.1836483-1-festevam@gmail.com>

From: Fabio Estevam <festevam at denx.de>

According to fsl,mma7455.yaml, the correct compatible string is
"fsl,mma7455".

Change it accordingly to fix the following dt-schema warning:

failed to match any schema with compatible: ['fsl,mma7455l']

Signed-off-by: Fabio Estevam <festevam at denx.de>
---
Changes since v1:
- Fix MMA7455 typo in Subject.

 arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
index dc72a2d14960..1980f751f161 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
@@ -165,7 +165,7 @@ &i2c2 {
 	mma7455l at 1d {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_mma7455l>;
-		compatible = "fsl,mma7455l";
+		compatible = "fsl,mma7455";
 		reg = <0x1d>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>, <6 IRQ_TYPE_LEVEL_HIGH>;
-- 
2.34.1



From jic23 at kernel.org  Sat Mar 15 05:50:28 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 15 Mar 2025 12:50:28 +0000
Subject: [PATCH 1/5] pmic: mediatek: Add pmic auxadc driver
In-Reply-To: <20250314073307.25092-2-Lu.Tang@mediatek.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
	<20250314073307.25092-2-Lu.Tang@mediatek.com>
Message-ID: <20250315125028.038fc488@jic23-huawei>

On Fri, 14 Mar 2025 15:32:27 +0800
Lu.Tang <Lu.Tang at mediatek.com> wrote:

> From: "Lu.Tang" <lu.tang at mediatek.com>
> 
> Add pmic mt6363 and mt6373 auxadc driver

On assumption that there is good reason to not combine this with existing
driver I'll give it a quick review.  Definitely confirm why this can't
be combined with existing driver though before looking at this.

Jonathan


> 
> Signed-off-by: Lu Tang <lu.tang at mediatek.com>
> ---
>  drivers/iio/adc/Kconfig             |  10 +
>  drivers/iio/adc/Makefile            |   1 +
>  drivers/iio/adc/mtk-spmi-pmic-adc.c | 576 ++++++++++++++++++++++++++++
>  3 files changed, 587 insertions(+)
>  create mode 100644 drivers/iio/adc/mtk-spmi-pmic-adc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 27413516216c..7c4b5f8f7209 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -1039,6 +1039,16 @@ config MEDIATEK_MT6577_AUXADC
>  	  This driver can also be built as a module. If so, the module will be
>  	  called mt6577_auxadc.
>  
> +config MEDIATEK_SPMI_PMIC_ADC

Clearly a history of non compatible mediatek parts so it is probably better
to just name this after one of the supported parts than it is to use
a generic name.

> +	tristate "MediaTek SPMI PMIC ADC Support"
> +	depends on MFD_MTK_SPMI_PMIC
> +	help
> +	  Say yes here to enable support for MediaTek SPMI PMIC ADC.
> +	  The driver supports multiple channels read.
> +
> +	  This driver can also be built as a module. If so, the module will be
> +	  called mtk-spmi-pmic-adc.
> +

> diff --git a/drivers/iio/adc/mtk-spmi-pmic-adc.c b/drivers/iio/adc/mtk-spmi-pmic-adc.c
> new file mode 100644
> index 000000000000..61e062bc8cf5
> --- /dev/null
> +++ b/drivers/iio/adc/mtk-spmi-pmic-adc.c
> @@ -0,0 +1,576 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2024 MediaTek Inc.

Update?

> + */
> +
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/iio/iio.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/mt6363/registers.h>
> +#include <linux/mfd/mt6373/registers.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
These shouldn't be used.
> +#include <linux/property.h>
only this should be so the of includes should be dropped.
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/syscore_ops.h>
> +
> +#include <dt-bindings/iio/mt635x-auxadc.h>


> +
> +#define AUXADC_RDY_BIT			BIT(15)
> +
> +#define AUXADC_DEF_R_RATIO		1
> +#define AUXADC_DEF_AVG_NUM		32
> +
> +#define AUXADC_AVG_TIME_US		10
> +#define AUXADC_POLL_DELAY_US		100
> +#define AUXADC_TIMEOUT_US		32000
These aren't really magic values so the only benefit in a define
would be to put a comment giving a spec reference next to them.
If not consider just putting the values inline.

> +#define VOLT_FULL			1840

Prefix all defines with something related to the driver.
MT8195_AUXADC_xx
That avoid potential aliasing that can occur with generic names.

> +
> +#define IMP_VOLT_FULL			18400
> +#define IMIX_R_MIN_MOHM			100
> +#define IMIX_R_CALI_CNT			2
> +
> +#define EXT_THR_PURES_SHIFT		3
> +#define EXT_THR_SEL_MASK		0x1F
> +
> +#define DT_CHANNEL_CONVERT(val)		((val) & 0xFF)
> +#define DT_PURES_CONVERT(val)		(((val) & 0xFF00) >> 8)
> +
> +struct pmic_adc_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct mutex lock;
All locks must have comment describing the scope of data they protect.
> +	struct iio_chan_spec *iio_chans;

Looks like some of these only exist to avoid passing more variables
into the dt parsing function.  Make them local to the caller of that
and pass them in.  We should not have them in here.

> +	unsigned int nchannels;
> +	const struct auxadc_info *info;
> +	struct regulator *isink_load;
> +	int imix_r;
> +	int imp_curr;
> +	int pre_uisoc;
> +};
> +
> +static struct pmic_adc_device *imix_r_dev;
> +
> +/*

Make this correct kernel-doc. It nearly is already!

> + * @ch_name:	HW channel name
> + * @res:	ADC resolution
> + * @r_ratio:	resistance ratio, represented by r_ratio[0] / r_ratio[1]
> + * @avg_num:	sampling times of AUXADC measurements then average it
> + * @regs:	request and data output registers for this channel
> + */
> +struct auxadc_channels {
> +	enum iio_chan_type type;

Random things aren't documented. Document all structure elements.

> +	long info_mask;
> +	/* AUXADC channel attribute */
> +	const char *ch_name;
> +	unsigned char res;
> +	unsigned char r_ratio[2];
> +	unsigned short avg_num;
> +	const struct auxadc_regs *regs;
> +};
> +
> +#define AUXADC_CHANNEL(_ch_name, _res)	\
> +	[AUXADC_##_ch_name] = {				\
> +		.type = IIO_VOLTAGE,			\
> +		.info_mask = BIT(IIO_CHAN_INFO_RAW) |		\
> +			     BIT(IIO_CHAN_INFO_PROCESSED),	\

We almost never allow both raw and processed. There are a few exceptions
to that rule though. Why does it make sense here?

> +		.ch_name = __stringify(_ch_name),	\
> +		.res = _res,				\
> +	}
> +
> +/*
> + * The array represents all possible AUXADC channels found
> + * in the supported PMICs.
> + */
> +static struct auxadc_channels auxadc_chans[] = {
> +	AUXADC_CHANNEL(BATADC, 15),
> +	AUXADC_CHANNEL(VCDT, 12),
> +	AUXADC_CHANNEL(BAT_TEMP, 12),
> +	AUXADC_CHANNEL(CHIP_TEMP, 12),
> +	AUXADC_CHANNEL(VCORE_TEMP, 12),
> +	AUXADC_CHANNEL(VPROC_TEMP, 12),
> +	AUXADC_CHANNEL(VGPU_TEMP, 12),
> +	AUXADC_CHANNEL(ACCDET, 12),
> +	AUXADC_CHANNEL(HPOFS_CAL, 15),
> +	AUXADC_CHANNEL(VTREF, 12),
> +	AUXADC_CHANNEL(VBIF, 12),
> +	AUXADC_CHANNEL(IMP, 15),
> +	[AUXADC_IMIX_R] = {
> +		.type = IIO_RESISTANCE,
> +		.info_mask = BIT(IIO_CHAN_INFO_RAW),
> +		.ch_name = "IMIX_R",
> +	},
> +	AUXADC_CHANNEL(VSYSSNS, 15),
> +	AUXADC_CHANNEL(VIN1, 15),
> +	AUXADC_CHANNEL(VIN2, 15),
> +	AUXADC_CHANNEL(VIN3, 15),
> +	AUXADC_CHANNEL(VIN4, 15),
> +	AUXADC_CHANNEL(VIN5, 15),
> +	AUXADC_CHANNEL(VIN6, 15),
> +	AUXADC_CHANNEL(VIN7, 15),
> +};
> +
> +struct auxadc_regs {
> +	unsigned int enable_reg;
> +	unsigned int enable_mask;
> +	unsigned int ready_reg;
> +	unsigned int ready_mask;
> +	unsigned int value_reg;
> +	unsigned int ext_thr_sel;
> +	u8 src_sel;
> +};
> +
> +#define AUXADC_REG(_ch_name, _chip, _enable_reg, _enable_mask, _value_reg) \
> +	[AUXADC_##_ch_name] = {				\
> +		.enable_reg = _chip##_##_enable_reg,	\
> +		.enable_mask = _enable_mask,		\
> +		.ready_reg = _chip##_##_value_reg,	\
> +		.ready_mask = AUXADC_RDY_BIT,		\
> +		.value_reg = _chip##_##_value_reg,	\
> +	}						\
Should be no \ on last line.

> +
> +#define TIA_ADC_REG(_src_sel, _chip)	\
> +	[AUXADC_VIN##_src_sel] = {			\
> +		.enable_reg = _chip##_AUXADC_RQST1,	\
> +		.enable_mask = BIT(4),			\
> +		.ready_reg = _chip##_AUXADC_ADC_CH12_L,	\
> +		.ready_mask = AUXADC_RDY_BIT,		\
> +		.value_reg = _chip##_AUXADC_ADC_CH12_L,	\
> +		.ext_thr_sel = _chip##_SDMADC_CON0,	\
> +		.src_sel = _src_sel,			\
> +	}						\
same here.

> +
> +static const struct auxadc_regs mt6363_auxadc_regs_tbl[] = {
> +	AUXADC_REG(BATADC, MT6363, AUXADC_RQST0, BIT(0), AUXADC_ADC0_L),
> +	AUXADC_REG(BAT_TEMP, MT6363, AUXADC_RQST0, BIT(3), AUXADC_ADC3_L),
> +	AUXADC_REG(CHIP_TEMP, MT6363, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
> +	AUXADC_REG(VCORE_TEMP, MT6363, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
> +	AUXADC_REG(VPROC_TEMP, MT6363, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
> +	AUXADC_REG(VGPU_TEMP, MT6363, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
> +	AUXADC_REG(VTREF, MT6363, AUXADC_RQST1, BIT(3), AUXADC_ADC11_L),
> +	[AUXADC_IMP] = {
> +		.enable_reg = MT6363_AUXADC_IMP0,
> +		.enable_mask = BIT(0),
> +		.ready_reg = MT6363_AUXADC_IMP1,
> +		.ready_mask = BIT(7),
> +		.value_reg = MT6363_AUXADC_ADC42_L,
> +	},
> +	AUXADC_REG(VSYSSNS, MT6363, AUXADC_RQST1, BIT(6), AUXADC_ADC_CH14_L),
> +	TIA_ADC_REG(1, MT6363),
> +	TIA_ADC_REG(2, MT6363),
> +	TIA_ADC_REG(3, MT6363),
> +	TIA_ADC_REG(4, MT6363),
> +	TIA_ADC_REG(5, MT6363),
> +	TIA_ADC_REG(6, MT6363),
> +	TIA_ADC_REG(7, MT6363),
> +};
> +
> +static const struct auxadc_regs mt6373_auxadc_regs_tbl[] = {
> +	AUXADC_REG(CHIP_TEMP, MT6373, AUXADC_RQST0, BIT(4), AUXADC_ADC4_L),
> +	AUXADC_REG(VCORE_TEMP, MT6373, AUXADC_RQST3, BIT(0), AUXADC_ADC38_L),
> +	AUXADC_REG(VPROC_TEMP, MT6373, AUXADC_RQST3, BIT(1), AUXADC_ADC39_L),
> +	AUXADC_REG(VGPU_TEMP, MT6373, AUXADC_RQST3, BIT(2), AUXADC_ADC40_L),
> +	TIA_ADC_REG(1, MT6373),
> +	TIA_ADC_REG(2, MT6373),
> +	TIA_ADC_REG(3, MT6373),
> +	TIA_ADC_REG(4, MT6373),
> +	TIA_ADC_REG(5, MT6373),
> +};
> +
> +struct auxadc_info {
> +	const struct auxadc_regs *regs_tbl;
> +};
> +
> +static const struct auxadc_info mt6363_info = {
> +	.regs_tbl = mt6363_auxadc_regs_tbl,
> +};
> +
> +static const struct auxadc_info mt6373_info = {
> +	.regs_tbl = mt6373_auxadc_regs_tbl,
> +};
> +
> +#define regmap_bulk_read_poll_timeout(map, addr, val, val_count, cond, sleep_us, timeout_us) \

This looks generic so shouldn't be in a driver.  Either propose it
for the regmap core, or give it a non generic driver specific name.

> +({ \
> +	u64 __timeout_us = (timeout_us); \
> +	unsigned long __sleep_us = (sleep_us); \
> +	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
> +	int __ret; \
> +	might_sleep_if(__sleep_us); \
> +	for (;;) { \
> +		__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
> +		if (__ret) \
> +			break; \
> +		if (cond) \
> +			break; \
> +		if ((__timeout_us) && \
> +		    ktime_compare(ktime_get(), __timeout) > 0) { \
> +			__ret = regmap_bulk_read((map), (addr), (u8 *) &(val), val_count); \
> +			break; \
> +		} \
> +		if (__sleep_us) \
> +			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
> +	} \
> +	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
> +})
> +
> +/*
For this sort of text make it all kernel-doc style and run the script
on the file to make sure no warnings / errors.

> + * @adc_dev:	 pointer to the struct pmic_adc_device
> + * @auxadc_chan: pointer to the struct auxadc_channels, it represents specific
> +		 auxadc channel
> + * @val:	 pointer to output value
> + */
> +static int get_auxadc_out(struct pmic_adc_device *adc_dev,
> +			  int channel, int channel2, int *val)

For example these parameters are different from the docs and
the kernel-doc script would point that out for you.

> +{
> +	int ret;
> +	u16 buf = 0;
> +	const struct auxadc_channels *auxadc_chan = &auxadc_chans[channel];
> +
> +	if (!auxadc_chan->regs)
> +		return -EINVAL;

Why would that happen?  Don't defend against things that can't occur.

> +
> +	if (auxadc_chan->regs->ext_thr_sel) {
> +		buf = (channel2 << EXT_THR_PURES_SHIFT)
> +			| auxadc_chan->regs->src_sel;

FIELD_PREP plus use appropriate mask not shift.  Also apply
FIELD_PREP() for the src_sel.

Avoids anyone needing to check values are in range or where the
various register fields are.

> +		ret = regmap_update_bits(adc_dev->regmap,
> +					 auxadc_chan->regs->ext_thr_sel,
> +					 EXT_THR_SEL_MASK, buf);
> +		if (ret < 0)
> +			return ret;
> +	}
> +	regmap_write(adc_dev->regmap,
Check for errors.

> +		     auxadc_chan->regs->enable_reg,
> +		     auxadc_chan->regs->enable_mask);
> +	usleep_range(auxadc_chan->avg_num * AUXADC_AVG_TIME_US,
> +		     (auxadc_chan->avg_num + 1) * AUXADC_AVG_TIME_US);
> +
> +	ret = regmap_bulk_read_poll_timeout(adc_dev->regmap,
> +					    auxadc_chan->regs->value_reg,
> +					    buf, 2,

buf should be u16 and use sizeof(buf) for that 2.

> +					    (buf & AUXADC_RDY_BIT),
brackets add nothing.
> +					    AUXADC_POLL_DELAY_US,
> +					    AUXADC_TIMEOUT_US);
> +	*val = buf & (BIT(auxadc_chan->res) - 1);
> +	if (ret)
> +		dev_err(adc_dev->dev, "%s ret error code:%d!\n", auxadc_chan->ch_name, ret);
> +
> +	/* set PURES to OPEN after measuring done */
> +	if (auxadc_chan->regs->ext_thr_sel) {
> +		buf = (ADC_PURES_OPEN << EXT_THR_PURES_SHIFT)
> +			| auxadc_chan->regs->src_sel;
FIELD_PREP() for both of those.

> +		ret = regmap_update_bits(adc_dev->regmap,
> +					 auxadc_chan->regs->ext_thr_sel,
> +					 EXT_THR_SEL_MASK, buf);

Overwrite the earlier error potentially which is not something we normally
want to do as can make debugging harder.

> +	}
> +
> +	return ret;
> +}
> +
> +static int gauge_get_imp_ibat(void)
> +{
> +	struct power_supply *psy;
> +	union power_supply_propval prop;
> +	int ret;
> +
> +	psy = power_supply_get_by_name("mtk-gauge");
> +	if (!psy)
> +		return 0;
> +
> +	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
> +	if (ret)
> +		return ret;
> +
> +	power_supply_put(psy);
> +	return prop.intval;
> +}
> +
> +static int get_imp_out(struct pmic_adc_device *adc_dev, int *val)
> +{
> +	int ret;
> +	unsigned int buf = 0;
> +	const struct auxadc_channels *auxadc_chan = &auxadc_chans[AUXADC_IMP];
> +
> +	if (!auxadc_chan->regs)
> +		return -EINVAL;
> +
> +	regmap_write(adc_dev->regmap,

Probably worth a local variable for the regmap to shorten some lines.

> +		     auxadc_chan->regs->enable_reg,
> +		     auxadc_chan->regs->enable_mask);

Check for errors.

> +	ret = regmap_read_poll_timeout(adc_dev->regmap, auxadc_chan->regs->ready_reg,
> +					   buf, buf & auxadc_chan->regs->ready_mask,
> +					   AUXADC_POLL_DELAY_US,
> +					   AUXADC_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(adc_dev->dev, "%s %s ret error code:%d!\n",
> +			__func__, auxadc_chan->ch_name, ret);
No need for the __func__ in here.  Say what failed in the error message.
> +		return ret;
> +	}
> +
> +	ret = regmap_bulk_read(adc_dev->regmap, auxadc_chan->regs->value_reg, (u8 *) &buf, 2);

Why cast to u8 *?  It takes a void * and you never need to cast to that.
However, you also shouldn't be doing a 2 byte read into a integer.  Use a u16
and get the size with appropriate sizeof()



> +	if (ret)
> +		return ret;
> +	*val = buf & (BIT(auxadc_chan->res) - 1);
> +	adc_dev->imp_curr = gauge_get_imp_ibat();
> +
> +	regmap_write(adc_dev->regmap,
> +		     auxadc_chan->regs->enable_reg, 0);

Check for errors.

> +
> +	return 0;
> +}
> +
> +static int pmic_adc_read_raw(struct iio_dev *indio_dev,

All functions should be prefixed with driver name. Avoids
potential clashes if generic stuff ends up in headers later.

> +			     struct iio_chan_spec const *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct pmic_adc_device *adc_dev = iio_priv(indio_dev);
> +	const struct auxadc_channels *auxadc_chan;
> +	int auxadc_out = 0;
> +	int ret = 0;
> +
> +	mutex_lock(&adc_dev->lock);
consider pushing the lock down into the various implementations.
> +	switch (chan->channel) {
> +	case AUXADC_IMP:
> +		ret = get_imp_out(adc_dev, &auxadc_out);
> +		break;
> +	case AUXADC_IMIX_R:
> +		auxadc_out = adc_dev->imix_r;
> +		break;
> +	default:
> +		ret = get_auxadc_out(adc_dev,
> +				     chan->channel, chan->channel2,
> +				     &auxadc_out);
> +		break;
> +	}
> +	mutex_unlock(&adc_dev->lock);
> +
> +	if (ret && ret != -ETIMEDOUT)
> +		return ret;

Why would you carry on if it timed out?

> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_PROCESSED:
> +		auxadc_chan = &auxadc_chans[chan->channel];
> +		*val = auxadc_out * auxadc_chan->r_ratio[0] * VOLT_FULL;
> +		*val = (*val / auxadc_chan->r_ratio[1]) >> auxadc_chan->res;
This looks linear - in which case why not leave the maths to userspace
and provide IIO_CHAN_INFO_SCALE + _RAW

> +		ret = IIO_VAL_INT;
> +		break;
> +	case IIO_CHAN_INFO_RAW:

Why provide this at all if you are providing processed output.

> +		*val = auxadc_out;
> +		ret = IIO_VAL_INT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (chan->channel == AUXADC_IMP) {
> +		*val2 = adc_dev->imp_curr;
> +		ret = IIO_VAL_INT_MULTIPLE;
> +	}
> +
> +	return ret;
> +}

> +
> +static const struct iio_info pmic_adc_info = {
> +	.read_raw = &pmic_adc_read_raw,
> +	.fwnode_xlate = &pmic_adc_fwnode_xlate,
> +};
> +
> +static int auxadc_init_imix_r(struct pmic_adc_device *adc_dev,
> +			      struct device_node *imix_r_node)
> +{
> +	unsigned int val = 0;
> +	int ret;
> +
> +	if (!adc_dev)
> +		return -EINVAL;
> +
> +	adc_dev->isink_load = devm_regulator_get_exclusive(adc_dev->dev, "isink_load");
> +	if (IS_ERR(adc_dev->isink_load)) {
> +		dev_err(adc_dev->dev, "Failed to get isink_load regulator, ret=%d\n",
> +			(int)PTR_ERR(adc_dev->isink_load));
> +		return PTR_ERR(adc_dev->isink_load);

Use dev_err_probe() which will also pretty print the return value so remember to
drop that bit.

> +	}
> +
> +	imix_r_dev = adc_dev;
> +	if (imix_r_dev->imix_r)
> +		return 0;
> +
> +	ret = of_property_read_u32(imix_r_node, "val", &val);
> +	if (ret)
> +		dev_notice(imix_r_dev->dev, "no imix_r, ret=%d\n", ret);
> +	imix_r_dev->imix_r = (int)val;
> +	imix_r_dev->pre_uisoc = 101;
> +	return 0;
> +}
> +
> +static int auxadc_get_data_from_dt(struct pmic_adc_device *adc_dev,

from_fw() and use the generic property.h accessors, not the dt specific ones.

> +				   struct iio_chan_spec *iio_chan,
> +				   struct device_node *node)
> +{
> +	struct auxadc_channels *auxadc_chan;
> +	unsigned int channel = 0;
> +	unsigned int value = 0;
> +	unsigned int val_arr[2] = {0};
> +	int ret;
> +
> +	ret = of_property_read_u32(node, "channel", &channel);

That doesn't looks like a standard dt binding. why do you need it
vs what is in adc.yaml?  Probably just reg is enough.


> +	if (ret) {
> +		dev_err(adc_dev->dev, "invalid channel in node:%s\n",
> +			   node->name);

use return dev_err_probe() for all error prints that are part of probe.
Gives prettier printing and other benefits in some cases.

> +		return ret;
> +	}
> +	if (channel > AUXADC_CHAN_MAX) {
> +		dev_err(adc_dev->dev, "invalid channel number %d in node:%s\n",
> +			   channel, node->name);
> +		return -EINVAL;
> +	}
> +	if (channel >= ARRAY_SIZE(auxadc_chans)) {
> +		dev_err(adc_dev->dev, "channel number %d in node:%s not exists\n",
> +			   channel, node->name);
> +		return -EINVAL;
> +	}
> +	iio_chan->channel = channel;
> +	iio_chan->datasheet_name = auxadc_chans[channel].ch_name;
> +	iio_chan->info_mask_separate = auxadc_chans[channel].info_mask;
> +	iio_chan->type = auxadc_chans[channel].type;
> +	iio_chan->extend_name = node->name;

No. This is almost never used in a modern driver as it makes for really nasty
userspace ABI.  Use label if you need to mark a channel as something specific.

> +	ret = of_property_read_u32(node, "pures", &value);

I have no idea what this one is or why you'd put anything in channel2 for
a single ended ADC channel with no modifier.


> +	if (!ret)
> +		iio_chan->channel2 = value;
> +
> +	if (channel == AUXADC_IMIX_R)
> +		return auxadc_init_imix_r(adc_dev, node);
> +
> +	auxadc_chan = &auxadc_chans[channel];
> +	auxadc_chan->regs = &adc_dev->info->regs_tbl[channel];
> +
> +	ret = of_property_read_u32_array(node, "resistance-ratio", val_arr, 2);

Interesting but not standard DT binding. In general this seems to have no connect
to the dt bindings in this seris.

> +	if (!ret) {
> +		auxadc_chan->r_ratio[0] = val_arr[0];
> +		auxadc_chan->r_ratio[1] = val_arr[1];
> +	} else {
> +		auxadc_chan->r_ratio[0] = AUXADC_DEF_R_RATIO;
> +		auxadc_chan->r_ratio[1] = 1;
> +	}
> +
> +	ret = of_property_read_u32(node, "avg-num", &value);

Also not a standing binding and rarely found in DT because it
is usually a policy decision on noise vs sampling rate and exposed as
oversampling control to userspace.

> +	if (!ret)
> +		auxadc_chan->avg_num = value;
> +	else
> +		auxadc_chan->avg_num = AUXADC_DEF_AVG_NUM;
> +
> +	return 0;
> +}
> +
> +static int auxadc_parse_dt(struct pmic_adc_device *adc_dev,

parse_fw() as you'll be using generic accessors thoughout.

> +			   struct device_node *node)
> +{
> +	struct iio_chan_spec *iio_chan;
> +	struct device_node *child;
> +	unsigned int index = 0;
> +	int ret;
> +
> +	adc_dev->nchannels = of_get_available_child_count(node);

Use generic property accessors, not of specific ones (property.h)

> +	if (!adc_dev->nchannels)
> +		return -EINVAL;
> +
> +	adc_dev->iio_chans = devm_kcalloc(adc_dev->dev, adc_dev->nchannels,
> +		sizeof(*adc_dev->iio_chans), GFP_KERNEL);
> +	if (!adc_dev->iio_chans)
> +		return -ENOMEM;
> +	iio_chan = adc_dev->iio_chans;
> +
> +	for_each_available_child_of_node(node, child) {
> +		ret = auxadc_get_data_from_dt(adc_dev, iio_chan, child);
> +		if (ret < 0) {
> +			of_node_put(child);
> +			return ret;
> +		}
> +		iio_chan->indexed = 1;
> +		iio_chan->address = index++;
> +		iio_chan++;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pmic_adc_probe(struct platform_device *pdev)
> +{
> +	struct device_node *node = pdev->dev.of_node;
> +	struct pmic_adc_device *adc_dev;
> +	struct iio_dev *indio_dev;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	adc_dev = iio_priv(indio_dev);
> +	adc_dev->dev = &pdev->dev;
> +	adc_dev->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	mutex_init(&adc_dev->lock);
In new drivers I prefer to see
	ret = devm_mutex_init()
	if (ret)
		return ret;

Brings only a minor debug benefit, but the cost of getting that is
low so it is a nice thing to have!

> +	adc_dev->info = of_device_get_match_data(&pdev->dev);
> +
> +	ret = auxadc_parse_dt(adc_dev, node);
> +	if (ret) {
> +		dev_notice(&pdev->dev, "auxadc_parse_dt fail, ret=%d\n", ret);
> +		return ret;
> +	}
> +
> +	indio_dev->dev.parent = &pdev->dev;

No need for that - it's done the IIO core.

> +	indio_dev->name = dev_name(&pdev->dev);

This needs to be the part number, not come from the device name which can
be very different depending on how the device is created etc.
So just hard code the part number in the info structure and set it here.


> +	indio_dev->info = &pmic_adc_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = adc_dev->iio_chans;
> +	indio_dev->num_channels = adc_dev->nchannels;
> +
> +	ret = devm_iio_device_register(&pdev->dev, indio_dev);
> +	if (ret < 0) {
> +		dev_notice(&pdev->dev, "failed to register iio device!\n");
dev_err() given if you manage to hit here you definitely have an error.
Same for other error paths.

> +		return ret;
> +	}
> +
> +	dev_dbg(&pdev->dev, "probe done\n");
No purpose in this one.  It is very easy to see if probe succeeded without it.
> +
> +	return 0;
> +}



From jic23 at kernel.org  Sat Mar 15 05:56:15 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 15 Mar 2025 12:56:15 +0000
Subject: [PATCH v4 3/8] iio: trigger: stm32-lptimer: add support for
 stm32mp25
In-Reply-To: <20250314171451.3497789-4-fabrice.gasnier@foss.st.com>
References: <20250314171451.3497789-1-fabrice.gasnier@foss.st.com>
	<20250314171451.3497789-4-fabrice.gasnier@foss.st.com>
Message-ID: <20250315125615.065a2e74@jic23-huawei>

On Fri, 14 Mar 2025 18:14:46 +0100
Fabrice Gasnier <fabrice.gasnier at foss.st.com> wrote:

> From: Olivier Moysan <olivier.moysan at foss.st.com>
> 
> Add support for STM32MP25 SoC. Use newly introduced compatible to handle
> this new HW variant. Add new trigger definitions that can be used by the
> stm32 analog-to-digital converter. Use compatible data to identify them.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>

How do you want this to merge?   If it's going through mfd because
of dependencies, then
Acked-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>

I haven't checked if there are any dependencies so shout if I should
pick this up directly for next cycle.

Thanks,

Jonathan


> ---
> Changes in v4:
> - Jonathan's comment: simplify infrastructure by keeping
>   devm_iio_trigger_register. Don't need to cast compatible data.
> ---
>  drivers/iio/trigger/stm32-lptimer-trigger.c   | 75 ++++++++++++++-----
>  include/linux/iio/timer/stm32-lptim-trigger.h |  9 +++
>  2 files changed, 67 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c
> index f1e18913236a..3dcc8d2fe093 100644
> --- a/drivers/iio/trigger/stm32-lptimer-trigger.c
> +++ b/drivers/iio/trigger/stm32-lptimer-trigger.c
> @@ -16,16 +16,43 @@
>  #include <linux/platform_device.h>
>  #include <linux/property.h>
>  
> -/* List Low-Power Timer triggers */
> -static const char * const stm32_lptim_triggers[] = {
> -	LPTIM1_OUT,
> -	LPTIM2_OUT,
> -	LPTIM3_OUT,
> +/* Maximum triggers + one trailing null entry to indicate the end of array */
> +#define MAX_TRIGGERS 3
> +
> +struct stm32_lptim_cfg {
> +	const char * const (*triggers)[MAX_TRIGGERS];
> +	unsigned int nb_triggers;
> +};
> +
> +/* List Low-Power Timer triggers for H7, MP13, MP15 */
> +static const char * const stm32_lptim_triggers[][MAX_TRIGGERS] = {
> +	{ LPTIM1_OUT,},
> +	{ LPTIM2_OUT,},
> +	{ LPTIM3_OUT,},
> +};
> +
> +/* List Low-Power Timer triggers for STM32MP25 */
> +static const char * const stm32mp25_lptim_triggers[][MAX_TRIGGERS] = {
> +	{ LPTIM1_CH1, LPTIM1_CH2, },
> +	{ LPTIM2_CH1, LPTIM2_CH2, },
> +	{ LPTIM3_CH1,},
> +	{ LPTIM4_CH1,},
> +	{ LPTIM5_OUT,},
> +};
> +
> +static const struct stm32_lptim_cfg stm32mp15_lptim_cfg = {
> +	.triggers = stm32_lptim_triggers,
> +	.nb_triggers = ARRAY_SIZE(stm32_lptim_triggers),
> +};
> +
> +static const struct stm32_lptim_cfg stm32mp25_lptim_cfg = {
> +	.triggers = stm32mp25_lptim_triggers,
> +	.nb_triggers = ARRAY_SIZE(stm32mp25_lptim_triggers),
>  };
>  
>  struct stm32_lptim_trigger {
>  	struct device *dev;
> -	const char *trg;
> +	const char * const *triggers;
>  };
>  
>  static int stm32_lptim_validate_device(struct iio_trigger *trig,
> @@ -56,22 +83,33 @@ EXPORT_SYMBOL(is_stm32_lptim_trigger);
>  
>  static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv)
>  {
> -	struct iio_trigger *trig;
> +	const char * const *cur = priv->triggers;
> +	int ret;
>  
> -	trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg);
> -	if  (!trig)
> -		return -ENOMEM;
> +	while (cur && *cur) {
> +		struct iio_trigger *trig;
>  
> -	trig->dev.parent = priv->dev->parent;
> -	trig->ops = &stm32_lptim_trigger_ops;
> -	iio_trigger_set_drvdata(trig, priv);
> +		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
> +		if  (!trig)
> +			return -ENOMEM;
>  
> -	return devm_iio_trigger_register(priv->dev, trig);
> +		trig->dev.parent = priv->dev->parent;
> +		trig->ops = &stm32_lptim_trigger_ops;
> +		iio_trigger_set_drvdata(trig, priv);
> +
> +		ret = devm_iio_trigger_register(priv->dev, trig);
> +		if (ret)
> +			return ret;
> +		cur++;
> +	}
> +
> +	return 0;
>  }
>  
>  static int stm32_lptim_trigger_probe(struct platform_device *pdev)
>  {
>  	struct stm32_lptim_trigger *priv;
> +	struct stm32_lptim_cfg const *lptim_cfg;
>  	u32 index;
>  
>  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> @@ -81,17 +119,20 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev)
>  	if (device_property_read_u32(&pdev->dev, "reg", &index))
>  		return -EINVAL;
>  
> -	if (index >= ARRAY_SIZE(stm32_lptim_triggers))
> +	lptim_cfg = device_get_match_data(&pdev->dev);
> +
> +	if (index >= lptim_cfg->nb_triggers)
>  		return -EINVAL;
>  
>  	priv->dev = &pdev->dev;
> -	priv->trg = stm32_lptim_triggers[index];
> +	priv->triggers = lptim_cfg->triggers[index];
>  
>  	return stm32_lptim_setup_trig(priv);
>  }
>  
>  static const struct of_device_id stm32_lptim_trig_of_match[] = {
> -	{ .compatible = "st,stm32-lptimer-trigger", },
> +	{ .compatible = "st,stm32-lptimer-trigger", .data = &stm32mp15_lptim_cfg },
> +	{ .compatible = "st,stm32mp25-lptimer-trigger", .data = &stm32mp25_lptim_cfg},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match);
> diff --git a/include/linux/iio/timer/stm32-lptim-trigger.h b/include/linux/iio/timer/stm32-lptim-trigger.h
> index a34dcf6a6001..ce3cf0addb2e 100644
> --- a/include/linux/iio/timer/stm32-lptim-trigger.h
> +++ b/include/linux/iio/timer/stm32-lptim-trigger.h
> @@ -14,6 +14,15 @@
>  #define LPTIM1_OUT	"lptim1_out"
>  #define LPTIM2_OUT	"lptim2_out"
>  #define LPTIM3_OUT	"lptim3_out"
> +#define LPTIM4_OUT	"lptim4_out"
> +#define LPTIM5_OUT	"lptim5_out"
> +
> +#define LPTIM1_CH1	"lptim1_ch1"
> +#define LPTIM1_CH2	"lptim1_ch2"
> +#define LPTIM2_CH1	"lptim2_ch1"
> +#define LPTIM2_CH2	"lptim2_ch2"
> +#define LPTIM3_CH1	"lptim3_ch1"
> +#define LPTIM4_CH1	"lptim4_ch1"
>  
>  #if IS_REACHABLE(CONFIG_IIO_STM32_LPTIMER_TRIGGER)
>  bool is_stm32_lptim_trigger(struct iio_trigger *trig);



From arnd at arndb.de  Sat Mar 15 06:12:24 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Sat, 15 Mar 2025 14:12:24 +0100
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and use API for
 detecting hypervisor presence
In-Reply-To: <96bc4caf-b79a-4111-bafa-a7662260f4be@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-2-romank@linux.microsoft.com>
 <96bc4caf-b79a-4111-bafa-a7662260f4be@linux.microsoft.com>
Message-ID: <50ec2615-97cf-423d-bfe6-f65092a14348@app.fastmail.com>

On Sat, Mar 15, 2025, at 01:27, Roman Kisel wrote:
> On 3/14/2025 5:19 PM, Roman Kisel wrote:
>
> While the change is Acked, here is the caveat maybe.
>
> This patch produces warnings wtih sparse and CHECK_ENDING.
> That said, the kernel build produces a whole lot more other warnings
> from building with sparse by itself and/or with CHECK_ENDING.
>
> I am not sure how to proceed with that, thinking I should
> not add warnings yet at the same time there are many others.
> Not certain if folks take these signals as fyi or blockers.

It would be best not to add warnigns. There is slow progress on
fixing all the endianess warnings and I hope this can eventually
complete, so even if there are many existing ones please try to
keep new code clean.

     Arnd


From andrew at lunn.ch  Sat Mar 15 06:58:18 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Sat, 15 Mar 2025 14:58:18 +0100
Subject: [PATCH net-next v2] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>
References: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>
Message-ID: <b647d3c2-171e-43ea-9329-ea37093f5dec@lunn.ch>

> Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> routine.

A more interesting question is, why do you see an invalid port? Is the
hardware broken? Something not correctly configured? Are you just
papering over the crack?

> -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> +					struct airoha_foe_entry *hwe,
>  					struct net_device *dev, int type,
>  					struct airoha_flow_data *data,
>  					int l4proto)
> @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
>  	if (dev) {
>  		struct airoha_gdm_port *port = netdev_priv(dev);

If port is invalid, is dev also invalid? And if dev is invalid, could
dereferencing it to get priv cause an opps?

	Andrew


From luis.gerhorst at fau.de  Sat Mar 15 07:35:23 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Sat, 15 Mar 2025 15:35:23 +0100
Subject: [PATCH bpf-next 01/11] bpf: Move insn if/else into do_check_insn()
In-Reply-To: <293dbe3950a782b8eb3b87b71d7a967e120191fd.camel@gmail.com>
	(Eduard Zingerman's message of "Fri, 14 Mar 2025 15:47:00 -0700")
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	<20250313172127.1098195-2-luis.gerhorst@fau.de>
	<293dbe3950a782b8eb3b87b71d7a967e120191fd.camel@gmail.com>
Message-ID: <874izus6ok.fsf@fau.de>

Eduard Zingerman <eddyz87 at gmail.com> writes:
> On Thu, 2025-03-13 at 18:21 +0100, Luis Gerhorst wrote:
>> +		err = do_check_insn(env, insn, pop_log, &do_print_state, regs, state,
>> +				    &prev_insn_idx);
>
> - `regs` remains declared in do_check(), while nothing prevents
>   pushing its declaration to do_check_insn().
> - `state` is `env->cur_state`, so I'd avoid passing it as a parameter
>   (just to reduce count);
> - `prev_insn_idx` is unused by `do_check_insn`;
> - `pop_log` is not used by `do_check_insn`;

Changed for v2, thank you very much.

> - given that `insn` is presumed to correspond to `env->insn_idx` in
>   many places down the stack not sure about this parameter.

I don't have a strong opinion on this either. Unless someone objects I
will keep it as it matches the other check_*() functions like this.

>> +		if (err < 0) {
>> +			return err;
>> +		} else if (err == INSN_IDX_MODIFIED) {
>
> Also, I'd get rid of `INSN_IDX_MODIFIED` and move `env->insn_idx++`
> into `do_check_insn()`. This would save a few mental cycles when
> looking at the code with full patch-set applied:
>
> 		} else if (err == INSN_IDX_MODIFIED) {
> 			continue;
> 		} else if (err == PROCESS_BPF_EXIT) {
> 			goto process_bpf_exit;
> 		}
> 		WARN_ON_ONCE(err);
>
> 		if (state->speculative && cur_aux(env)->nospec_result) {
> 			... bunch of actions ...
> 		}
>
> 		env->insn_idx++;
>
> One needs to stop for a moment and think why "bunch of actions" is
> performed for regular index increment, but not for INSN_IDX_MODIFIED.

That certainly makes it more readable. I changed it for v2.

If we have an instruction that does not simply do `insn_idx++` but
jumps, the `nospec_result` check should never trigger. Otherwise, the
patched nospec might be skipped. Currently, this is satisfied because
`nospec_result` is only used for store-instructions. I will add a
comment and WARN_ON_ONCE to document that for v2.


From lorenzo at kernel.org  Sat Mar 15 07:59:46 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Sat, 15 Mar 2025 15:59:46 +0100
Subject: [PATCH net-next v2] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <b647d3c2-171e-43ea-9329-ea37093f5dec@lunn.ch>
References: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>
 <b647d3c2-171e-43ea-9329-ea37093f5dec@lunn.ch>
Message-ID: <Z9WV4mNwG04JRbZg@lore-desk>

> > Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> > routine.
> 
> A more interesting question is, why do you see an invalid port? Is the
> hardware broken? Something not correctly configured? Are you just
> papering over the crack?
> 
> > -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> > +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> > +					struct airoha_foe_entry *hwe,
> >  					struct net_device *dev, int type,
> >  					struct airoha_flow_data *data,
> >  					int l4proto)
> > @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> >  	if (dev) {
> >  		struct airoha_gdm_port *port = netdev_priv(dev);
> 
> If port is invalid, is dev also invalid? And if dev is invalid, could
> dereferencing it to get priv cause an opps?

I do not think this is a hw problem. Running bidirectional high load traffic,
I got the sporadic crash reported above. In particular, netfilter runs
airoha_ppe_flow_offload_replace() providing the egress net_device pointer used
in airoha_ppe_foe_entry_prepare(). Debugging with gdb, I discovered the system
crashes dereferencing port pointer in airoha_ppe_foe_entry_prepare() (even if
dev pointer is not NULL). Adding this sanity check makes the system stable.
Please note a similar check is available even in mtk driver [0].

Regards,
Lorenzo

[0] https://github.com/torvalds/linux/blob/master/drivers/net/ethernet/mediatek/mtk_ppe_offload.c#L220

> 
> 	Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250315/87965d5b/attachment.sig>

From luis.gerhorst at fau.de  Sat Mar 15 08:20:39 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Sat, 15 Mar 2025 16:20:39 +0100
Subject: [PATCH bpf-next 00/11] bpf: Mitigate Spectre v1 using barriers
In-Reply-To: <f6f08d64c777a6022771ab0adf96cefb6b631d75.camel@gmail.com>
	(Eduard Zingerman's message of "Fri, 14 Mar 2025 16:40:08 -0700")
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	<f6f08d64c777a6022771ab0adf96cefb6b631d75.camel@gmail.com>
Message-ID: <87seneqq0o.fsf@fau.de>

Eduard Zingerman <eddyz87 at gmail.com> writes:
> I think it would be good to have some tests checking that nospec
> instructions are inserted in expected locations.
> Could you please take look at use of __xlated tag in e.g.
> tools/testing/selftests/bpf/progs/verifier_sdiv.c ?

That looks very promising, I will look into it for v2. Thanks for the
pointer.

I guess it might be worth it to add __xlated to at least on test per
nospec-related code path. If there are other rewrites at play that will
make it harder to adapt the tests when the other rewrite is ever
changed, but it might also help in catching interactions between the
other rewrites and the nospec.

Also, thanks for the review of patches 2 and 3.


From ansuelsmth at gmail.com  Sat Mar 15 08:43:41 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:41 +0100
Subject: [net-next PATCH v13 01/14] dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-2-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Switch EFUSE used to calibrate
internal PHYs and store additional configuration info.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/nvmem/airoha,an8855-efuse.yaml   | 123 ++++++++++++++++++
 MAINTAINERS                                   |   8 ++
 2 files changed, 131 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml

diff --git a/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
new file mode 100644
index 000000000000..9802d9ea2176
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/airoha,an8855-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch EFUSE
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description:
+  Airoha AN8855 EFUSE used to calibrate internal PHYs and store additional
+  configuration info.
+
+$ref: nvmem.yaml#
+
+properties:
+  compatible:
+    const: airoha,an8855-efuse
+
+  '#nvmem-cell-cells':
+    const: 0
+
+required:
+  - compatible
+  - '#nvmem-cell-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    efuse {
+        compatible = "airoha,an8855-efuse";
+
+        #nvmem-cell-cells = <0>;
+
+        nvmem-layout {
+            compatible = "fixed-layout";
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            shift_sel_port0_tx_a: shift-sel-port0-tx-a at c {
+               reg = <0xc 0x4>;
+            };
+
+            shift_sel_port0_tx_b: shift-sel-port0-tx-b at 10 {
+                reg = <0x10 0x4>;
+            };
+
+            shift_sel_port0_tx_c: shift-sel-port0-tx-c at 14 {
+                reg = <0x14 0x4>;
+            };
+
+            shift_sel_port0_tx_d: shift-sel-port0-tx-d at 18 {
+               reg = <0x18 0x4>;
+            };
+
+            shift_sel_port1_tx_a: shift-sel-port1-tx-a at 1c {
+               reg = <0x1c 0x4>;
+            };
+
+            shift_sel_port1_tx_b: shift-sel-port1-tx-b at 20 {
+               reg = <0x20 0x4>;
+            };
+
+            shift_sel_port1_tx_c: shift-sel-port1-tx-c at 24 {
+               reg = <0x24 0x4>;
+            };
+
+            shift_sel_port1_tx_d: shift-sel-port1-tx-d at 28 {
+               reg = <0x28 0x4>;
+            };
+
+            shift_sel_port2_tx_a: shift-sel-port2-tx-a at 2c {
+                reg = <0x2c 0x4>;
+            };
+
+            shift_sel_port2_tx_b: shift-sel-port2-tx-b at 30 {
+                reg = <0x30 0x4>;
+            };
+
+            shift_sel_port2_tx_c: shift-sel-port2-tx-c at 34 {
+                reg = <0x34 0x4>;
+            };
+
+            shift_sel_port2_tx_d: shift-sel-port2-tx-d at 38 {
+                reg = <0x38 0x4>;
+            };
+
+            shift_sel_port3_tx_a: shift-sel-port3-tx-a at 4c {
+                reg = <0x4c 0x4>;
+            };
+
+            shift_sel_port3_tx_b: shift-sel-port3-tx-b at 50 {
+                reg = <0x50 0x4>;
+            };
+
+            shift_sel_port3_tx_c: shift-sel-port3-tx-c at 54 {
+               reg = <0x54 0x4>;
+            };
+
+            shift_sel_port3_tx_d: shift-sel-port3-tx-d at 58 {
+               reg = <0x58 0x4>;
+            };
+
+            shift_sel_port4_tx_a: shift-sel-port4-tx-a at 5c {
+                reg = <0x5c 0x4>;
+            };
+
+            shift_sel_port4_tx_b: shift-sel-port4-tx-b at 60 {
+                reg = <0x60 0x4>;
+            };
+
+            shift_sel_port4_tx_c: shift-sel-port4-tx-c at 64 {
+                reg = <0x64 0x4>;
+            };
+
+            shift_sel_port4_tx_d: shift-sel-port4-tx-d at 68 {
+                reg = <0x68 0x4>;
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index ffbcd072fb14..576fa7eb7b55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -719,6 +719,14 @@ S:	Supported
 F:	fs/aio.c
 F:	include/linux/*aio*.h
 
+AIROHA DSA DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
+L:	netdev at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:40 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:40 +0100
Subject: [net-next PATCH v13 00/14] net: dsa: Add Airoha AN8855 support
Message-ID: <20250315154407.26304-1-ansuelsmth@gmail.com>

This small series add the initial support for the Airoha AN8855 Switch.

It's a 5 port Gigabit Switch with SGMII/HSGMII upstream port.

This is starting to get in the wild and there are already some router
having this switch chip.

It's conceptually similar to mediatek switch but register and bits
are different. And there is that massive Hell that is the PCS
configuration.
Saddly for that part we have absolutely NO documentation currently.

There is this special thing where PHY needs to be calibrated with values
from the switch efuse. (the thing have a whole cpu timer and MCU)

>From v8 Driver is now evaluated with Kernel selftest scripts for DSA:

Additional info about the test bridge_vlan_aware.sh.

It was discovered that the Airoha Switch (and probably the Mediatek one
that produce the same test results) hardcode checking for 802.1ad when
the port is configured in VLAN-Aware mode (aka Security mode).

In such mode, both 802.1q and 802.1ad TPID are checked, hence the
bridge_vlan_aware.sh test fails as packets with 802.1ad TPID are rejected
(in the case where a wrong VLAN ID is forwarded)

This was confirmed by Airoha and multiple try were done to try to
workaround this problem. No solution were found to this as ACL mechanism
can't work on receiving packets and the Switch doesn't support turning off
this.

The current driver is in use from 2 month on OpenWrt with all kind of
scenario confirming working in VLAN bridge. By tweaking the
bridge_vlan_aware.sh test with setting the TPID to 0x9100, the test
correctly pass as packets gets classified as untagged and the default PVID
applied. It's also confirmed that switch correctly parse the 802.1ad tag
and make the packet pass only when allowed by VLAN table rules.

Output local_termination.sh
TEST: lan2: Unicast IPv4 to primary MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to macvlan MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address                     [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address, promisc            [ OK ]
TEST: lan2: Unicast IPv4 to unknown MAC address, allmulti           [ OK ]
TEST: lan2: Multicast IPv4 to joined group                          [ OK ]
TEST: lan2: Multicast IPv4 to unknown group                         [XFAIL]
        reception succeeded, but should have failed
TEST: lan2: Multicast IPv4 to unknown group, promisc                [ OK ]
TEST: lan2: Multicast IPv4 to unknown group, allmulti               [ OK ]
TEST: lan2: Multicast IPv6 to joined group                          [ OK ]
TEST: lan2: Multicast IPv6 to unknown group                         [XFAIL]
        reception succeeded, but should have failed
TEST: lan2: Multicast IPv6 to unknown group, promisc                [ OK ]
TEST: lan2: Multicast IPv6 to unknown group, allmulti               [ OK ]
TEST: lan2: 1588v2 over L2 transport, Sync                          [ OK ]
TEST: lan2: 1588v2 over L2 transport, Follow-Up                     [ OK ]
TEST: lan2: 1588v2 over L2 transport, Peer Delay Request            [ OK ]
TEST: lan2: 1588v2 over IPv4, Sync                                  [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv4, Follow-Up                             [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv4, Peer Delay Request                    [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Sync                                  [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Follow-Up                             [FAIL]
        reception failed
TEST: lan2: 1588v2 over IPv6, Peer Delay Request                    [FAIL]
        reception failed
TEST: vlan_filtering=0 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to joined group       [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to joined group       [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=0 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to joined group       [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to joined group       [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group      [XFAIL]
        reception succeeded, but should have failed
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: vlan_filtering=1 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN upper: Unicast IPv4 to primary MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to macvlan MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address               [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address, promisc      [ OK ]
TEST: VLAN upper: Unicast IPv4 to unknown MAC address, allmulti     [ OK ]
TEST: VLAN upper: Multicast IPv4 to joined group                    [ OK ]
TEST: VLAN upper: Multicast IPv4 to unknown group                   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN upper: Multicast IPv4 to unknown group, promisc          [ OK ]
TEST: VLAN upper: Multicast IPv4 to unknown group, allmulti         [ OK ]
TEST: VLAN upper: Multicast IPv6 to joined group                    [ OK ]
TEST: VLAN upper: Multicast IPv6 to unknown group                   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN upper: Multicast IPv6 to unknown group, promisc          [ OK ]
TEST: VLAN upper: Multicast IPv6 to unknown group, allmulti         [ OK ]
TEST: VLAN upper: 1588v2 over L2 transport, Sync                    [ OK ]
TEST: VLAN upper: 1588v2 over L2 transport, Follow-Up               [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over L2 transport, Peer Delay Request      [ OK ]
TEST: VLAN upper: 1588v2 over IPv4, Sync                            [FAIL]
        reception failed
;TEST: VLAN upper: 1588v2 over IPv4, Follow-Up                       [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv4, Peer Delay Request              [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Sync                            [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Follow-Up                       [FAIL]
        reception failed
TEST: VLAN upper: 1588v2 over IPv6, Peer Delay Request              [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Sync   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Follow-Up   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over L2 transport, Peer Delay Request   [ OK ]
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv4, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridged port: 1588v2 over IPv6, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address   [FAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Unicast IPv4 to unknown MAC address, allmulti   [FAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Sync   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Follow-Up   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over L2 transport, Peer Delay Request   [ OK ]
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv4, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Sync   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Follow-Up   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=1 bridged port: 1588v2 over IPv6, Peer Delay Request   [FAIL]
        reception failed
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=0 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to primary MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to macvlan MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Unicast IPv4 to unknown MAC address, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv4 to unknown group, allmulti   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to joined group   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group   [XFAIL]
        reception succeeded, but should have failed
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group, promisc   [ OK ]
TEST: VLAN over vlan_filtering=1 bridge: Multicast IPv6 to unknown group, allmulti   [ OK ]

Output bridge_vlan_unaware.sh
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: FDB learning                                                  [ OK ]
TEST: Unknown unicast flood                                         [ OK ]
TEST: Unregistered multicast flood                                  [ OK ]

Output bridge_vlan_aware.sh
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: FDB learning                                                  [ OK ]
TEST: Unknown unicast flood                                         [ OK ]
TEST: Unregistered multicast flood                                  [ OK ]
INFO: Add and delete a VLAN on bridge port lan2
TEST: ping                                                          [ OK ]
TEST: ping6                                                         [ OK ]
TEST: Externally learned FDB entry - ageing & roaming               [ OK ]
TEST: FDB entry in PVID for VLAN-tagged with other TPID             [FAIL]
        FDB entry was not learned when it should
TEST: Reception of VLAN with other TPID as untagged                 [FAIL]
        Packet was not forwarded when it should
TEST: Reception of VLAN with other TPID as untagged (no PVID)       [FAIL]
        Packet was forwarded when should not

[ For Vladimir, I still have to implement fdb_isolation but posting to
start the ball rolling for the multiple subsystem this patch affect
and for the dubious DT schema ]

Changes v13:
- Reimplement tx_lpi OPs
- Rework mdio-regmap to internally encode/decode address
- Fix error in Documentation
- Drop ext-surge property (assume calibration with declared nvmem cell)
- Fix comments from Lee on MFD driver
- Improve print error and drop extra space in DSA driver
Changes v12:
- Update on top of net-next
- Add additional info on conver-letter about slefttests and HW limitation
- Introduce mdio-regmap generalization for multiple address
- Drop dev flags and define PHY calibration in PHY node directly
Changes v11:
- Address reviews from Christophe (spell mistake + dev_err_probe)
- Fix kconfig dependency for MFD driver (depends on MDIO_DEVICE instead of MDIO)
  (indirectly fix link error for mdio APIs)
- Fix copy-paste error for MFD driver of_table
- Fix compilation error for PHY (move NVMEM to .config)
- Drop unneeded NVMEM node from MDIO example schema (from Andrew)
- Adapt MFD example schema to MDIO reg property restrictions
Changes v10:
- Entire rework to MFD + split to MDIO, EFUSE, SWITCH separate drivers
- Drop EEE OPs (while Russell finish RFC for EEE changes)
- Use new pcs_inpand OPs
- Drop AN restart function and move to pcs_config
- Enable assisted_learning and disable CPU learn (preparation for fdb_isolation)
- Move EFUSE read in Internal PHY driver to .config to handle EPROBE_DEFER
  (needed now that NVMEM driver is register externally instead of internally to switch
   node)
Changes v9:
- Error out on using 5G speed as currently not supported
- Add missing MAC_2500FD in phylink mac_capabilities
- Add comment and improve if condition for an8855_phylink_mac_config
Changes v8:
- Add port Fast Age support
- Add support for Port Isolation
- Use correct register for Learning Disable
- Add support for Ageing Time OP
- Set default PVID to 0 by default
- Add mdb OPs
- Add port change MTU
- Fix support for Upper VLAN
Changes v7:
- Fix devm_dsa_register_switch wrong export symbol
Changes v6:
- Drop standard MIB and handle with ethtool OPs (as requested by Jakub)
- Cosmetic: use bool instead of 0 or 1
Changes v5:
- Add devm_dsa_register_switch() patch
- Add Reviewed-by tag for DT patch
Changes v4:
- Set regmap readable_table static (mute compilation warning)
- Add support for port_bridge flags (LEARNING, FLOOD)
- Reset fdb struct in fdb_dump
- Drop support_asym_pause in port_enable
- Add define for get_phy_flags
- Fix bug for port not inititially part of a bridge
  (in an8855_setup the port matrix was always cleared but
   the CPU port was never initially added)
- Disable learning and flood for user port by default
- Set CPU port to flood and learning by default
- Correctly AND force duplex and flow control in an8855_phylink_mac_link_up
- Drop RGMII from pcs_config
- Check ret in "Disable AN if not in autoneg"
- Use devm_mutex_init
- Fix typo for AN8855_PORT_CHECK_MODE
- Better define AN8855_STP_LISTENING = AN8855_STP_BLOCKING
- Fix typo in AN8855_PHY_EN_DOWN_SHIFT
- Use paged helper for PHY
- Skip calibration in config_init if priv not defined
Changes v3:
- Out of RFC
- Switch PHY code to select_page API
- Better describe masks and bits in PHY driver for ADC register
- Drop raw values and use define for mii read/write
- Switch to absolute PHY address
- Replace raw values with mask and bits for pcs_config
- Fix typo for ext-surge property name
- Drop support for relocating Switch base PHY address on the bus
Changes v2:
- Drop mutex guard patch
- Drop guard usage in DSA driver
- Use __mdiobus_write/read
- Check return condition and return errors for mii read/write
- Fix wrong logic for EEE
- Fix link_down (don't force link down with autoneg)
- Fix forcing speed on sgmii autoneg
- Better document link speed for sgmii reg
- Use standard define for sgmii reg
- Imlement nvmem support to expose switch EFUSE
- Rework PHY calibration with the use of NVMEM producer/consumer
- Update DT with new NVMEM property
- Move aneg validation for 2500-basex in pcs_config
- Move r50Ohm table and function to PHY driver

Christian Marangi (14):
  dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE
  dt-bindings: net: Document support for Airoha AN8855 Switch Virtual
    MDIO
  dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
  dt-bindings: net: Document support for AN8855 Switch Internal PHY
  dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
  net: mdio: regmap: prepare support for multiple valid addr
  net: mdio: regmap: add support for C45 read/write
  net: mdio: regmap: add support for multiple valid addr
  net: mdio: regmap: add OF support
  mfd: an8855: Add support for Airoha AN8855 Switch MFD
  net: mdio: Add Airoha AN8855 Switch MDIO Passtrough
  nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE
  net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver
  net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY

 .../bindings/mfd/airoha,an8855.yaml           |  182 ++
 .../bindings/net/airoha,an8855-mdio.yaml      |   56 +
 .../bindings/net/airoha,an8855-phy.yaml       |   83 +
 .../net/dsa/airoha,an8855-switch.yaml         |   86 +
 .../bindings/nvmem/airoha,an8855-efuse.yaml   |  123 +
 MAINTAINERS                                   |   18 +
 drivers/mfd/Kconfig                           |   12 +
 drivers/mfd/Makefile                          |    1 +
 drivers/mfd/airoha-an8855.c                   |  429 +++
 drivers/net/dsa/Kconfig                       |    9 +
 drivers/net/dsa/Makefile                      |    1 +
 drivers/net/dsa/an8855.c                      | 2395 +++++++++++++++++
 drivers/net/dsa/an8855.h                      |  773 ++++++
 drivers/net/mdio/Kconfig                      |   10 +
 drivers/net/mdio/Makefile                     |    1 +
 drivers/net/mdio/mdio-an8855.c                |   49 +
 drivers/net/mdio/mdio-regmap.c                |  188 +-
 drivers/net/phy/Kconfig                       |    5 +
 drivers/net/phy/Makefile                      |    1 +
 drivers/net/phy/air_an8855.c                  |  261 ++
 drivers/nvmem/Kconfig                         |   11 +
 drivers/nvmem/Makefile                        |    2 +
 drivers/nvmem/an8855-efuse.c                  |   63 +
 include/linux/mdio/mdio-regmap.h              |   16 +
 24 files changed, 4761 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 create mode 100644 drivers/mfd/airoha-an8855.c
 create mode 100644 drivers/net/dsa/an8855.c
 create mode 100644 drivers/net/dsa/an8855.h
 create mode 100644 drivers/net/mdio/mdio-an8855.c
 create mode 100644 drivers/net/phy/air_an8855.c
 create mode 100644 drivers/nvmem/an8855-efuse.c

-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:42 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:42 +0100
Subject: [net-next PATCH v13 02/14] dt-bindings: net: Document support for Airoha AN8855 Switch Virtual MDIO
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-3-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Virtual MDIO Passtrough. This is needed
as AN8855 require special handling as the same address on the MDIO bus is
shared for both Switch and PHY and special handling for the page
configuration is needed to switch accessing to Switch address space
or PHY.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/net/airoha,an8855-mdio.yaml      | 56 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml

diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
new file mode 100644
index 000000000000..3078277bf478
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-mdio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 MDIO Passtrough
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description:
+  Airoha AN8855 Virtual MDIO Passtrough. This is needed as AN8855
+  require special handling as the same address on the MDIO bus is
+  shared for both Switch and PHY and special handling for the page
+  configuration is needed to switch accessing to Switch address space
+  or PHY.
+
+$ref: /schemas/net/mdio.yaml#
+
+properties:
+  compatible:
+    const: airoha,an8855-mdio
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        compatible = "airoha,an8855-mdio";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        internal_phy1: phy at 1 {
+            reg = <1>;
+        };
+
+        internal_phy2: phy at 2 {
+            reg = <2>;
+        };
+
+        internal_phy3: phy at 3 {
+            reg = <3>;
+        };
+
+        internal_phy4: phy at 4 {
+            reg = <4>;
+        };
+
+        internal_phy5: phy at 5 {
+            reg = <5>;
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 576fa7eb7b55..1e8055b5e162 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -725,6 +725,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
 AIROHA ETHERNET DRIVER
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:49 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:49 +0100
Subject: [net-next PATCH v13 09/14] net: mdio: regmap: add OF support
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-10-ansuelsmth@gmail.com>

Permit to pass a device tree node to mdio regmap config and use
the OF variant of mdiobus_register.

This is done to autoprobe PHY defined in device tree as the current
mdiobus_register only permits probing PHY using the MDIO mask value.

Previous implementation is not changed as of_mdiobus_register fallback
to mdiobus_register if the passed device tree pointer is NULL.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 2 +-
 include/linux/mdio/mdio-regmap.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index ed0443eb039f..8e89068c844d 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -143,7 +143,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	else
 		mii->phy_mask = ~0;
 
-	rc = devm_mdiobus_register(dev, mii);
+	rc = devm_of_mdiobus_register(dev, mii, config->np);
 	if (rc) {
 		dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc);
 		return ERR_PTR(rc);
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index bb0e7dc9c0dc..228f12e90750 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -14,6 +14,7 @@ struct regmap;
 
 struct mdio_regmap_config {
 	struct device *parent;
+	struct device_node *np;
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:50 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:50 +0100
Subject: [net-next PATCH v13 10/14] mfd: an8855: Add support for Airoha AN8855 Switch MFD
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-11-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Switch MFD that provide support for a DSA
switch and a NVMEM provider. Also provide support for a virtual MDIO
passthrough as the PHYs address for the switch are shared with the switch
address.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                 |   1 +
 drivers/mfd/Kconfig         |  12 +
 drivers/mfd/Makefile        |   1 +
 drivers/mfd/airoha-an8855.c | 429 ++++++++++++++++++++++++++++++++++++
 4 files changed, 443 insertions(+)
 create mode 100644 drivers/mfd/airoha-an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 65709e47adc7..aec293953382 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -730,6 +730,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+F:	drivers/mfd/airoha-an8855.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6b0682af6e32..ebdced27e96a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -53,6 +53,18 @@ config MFD_ALTERA_SYSMGR
 	  using regmap_mmio accesses for ARM32 parts and SMC calls to
 	  EL3 for ARM64 parts.
 
+config MFD_AIROHA_AN8855
+	tristate "Airoha AN8855 Switch Core"
+	select MFD_CORE
+	select MDIO_DEVICE
+	depends on NETDEVICES && OF
+	help
+	  Support for the Airoha AN8855 Switch Core. This is an SoC
+	  that provides various peripherals, to count, i2c, an Ethrnet
+	  Switch, a CPU timer, GPIO, eFUSE.
+
+	  Currently it provides a DSA switch and a NVMEM provider.
+
 config MFD_ACT8945A
 	tristate "Active-semi ACT8945A"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9220eaf7cf12..37677f65a981 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
 obj-$(CONFIG_MFD_88PM800)	+= 88pm800.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM886_PMIC)	+= 88pm886.o
+obj-$(CONFIG_MFD_AIROHA_AN8855)	+= airoha-an8855.o
 obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835-pm.o
diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c
new file mode 100644
index 000000000000..fb2edf3132f9
--- /dev/null
+++ b/drivers/mfd/airoha-an8855.c
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Core driver for Airoha AN8855 Switch
+ */
+
+#include <linux/bitfield.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/core.h>
+#include <linux/mdio.h>
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+
+/* Register for HW trap status */
+#define AN8855_HWTRAP			0x1000009c
+
+#define AN8855_CREV			0x10005000
+#define   AN8855_ID			0x8855
+
+#define AN8855_RG_GPHY_AFE_PWD		0x1028c840
+
+/* MII Registers */
+#define AN8855_PHY_SELECT_PAGE		0x1f
+#define   AN8855_PHY_PAGE		GENMASK(2, 0)
+#define   AN8855_PHY_PAGE_STANDARD	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define   AN8855_PHY_PAGE_EXTENDED_1	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+#define   AN8855_PHY_PAGE_EXTENDED_4	FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
+
+/* MII Registers Page 4 */
+#define AN8855_PBUS_MODE		0x10
+#define   AN8855_PBUS_MODE_ADDR_FIXED	0x0
+#define AN8855_PBUS_MODE_ADDR_INCR	BIT(15)
+#define AN8855_PBUS_WR_ADDR_HIGH	0x11
+#define AN8855_PBUS_WR_ADDR_LOW		0x12
+#define AN8855_PBUS_WR_DATA_HIGH	0x13
+#define AN8855_PBUS_WR_DATA_LOW		0x14
+#define AN8855_PBUS_RD_ADDR_HIGH	0x15
+#define AN8855_PBUS_RD_ADDR_LOW		0x16
+#define AN8855_PBUS_RD_DATA_HIGH	0x17
+#define AN8855_PBUS_RD_DATA_LOW		0x18
+
+struct an8855_core_priv {
+	struct mii_bus *bus;
+
+	unsigned int switch_addr;
+	u16 current_page;
+};
+
+static const struct mfd_cell an8855_core_childs[] = {
+	{
+		.name = "an8855-efuse",
+		.of_compatible = "airoha,an8855-efuse",
+	}, {
+		.name = "an8855-switch",
+		.of_compatible = "airoha,an8855-switch",
+	}, {
+		.name = "an8855-mdio",
+		.of_compatible = "airoha,an8855-mdio",
+	}
+};
+
+static int an8855_mii_set_page(struct an8855_core_priv *priv, u8 addr,
+			       u8 page) __must_hold(&priv->bus->mdio_lock)
+{
+	struct mii_bus *bus = priv->bus;
+	int ret;
+
+	ret = __mdiobus_write(bus, addr, AN8855_PHY_SELECT_PAGE, page);
+	if (ret) {
+		dev_err_ratelimited(&bus->dev, "failed to set mii page\n");
+		return ret;
+	}
+
+	/* Cache current page if next MII read/write is for Switch page */
+	priv->current_page = page;
+	return 0;
+}
+
+static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg,
+			     u32 *val) __must_hold(&bus->mdio_lock)
+{
+	int lo, hi, ret;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+			      AN8855_PBUS_MODE_ADDR_FIXED);
+	if (ret)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH,
+			      upper_16_bits(reg));
+	if (ret)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW,
+			      lower_16_bits(reg));
+	if (ret)
+		goto err;
+
+	hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH);
+	if (hi < 0) {
+		ret = hi;
+		goto err;
+	}
+
+	lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW);
+	if (lo < 0) {
+		ret = lo;
+		goto err;
+	}
+
+	*val = ((u16)hi << 16) | ((u16)lo & 0xffff);
+
+	return 0;
+err:
+	dev_err_ratelimited(&bus->dev, "failed to read register\n");
+	return ret;
+}
+
+static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+	struct an8855_core_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret < 0)
+		goto exit;
+
+	ret = an8855_mii_read32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg,
+			      u32 val) __must_hold(&bus->mdio_lock)
+{
+	int ret;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE,
+			      AN8855_PBUS_MODE_ADDR_FIXED);
+	if (ret)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH,
+			      upper_16_bits(reg));
+	if (ret)
+		goto err;
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW,
+			      lower_16_bits(reg));
+	if (ret)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH,
+			      upper_16_bits(val));
+	if (ret)
+		goto err;
+
+	ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW,
+			      lower_16_bits(val));
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_err_ratelimited(&bus->dev,
+			    "failed to write an8855 register\n");
+	return ret;
+}
+
+static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val)
+{
+	struct an8855_core_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret)
+		goto exit;
+
+	ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask,
+				     uint32_t write_val)
+{
+	struct an8855_core_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	u16 addr = priv->switch_addr;
+	u32 val;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4);
+	if (ret)
+		goto exit;
+
+	ret = an8855_mii_read32(bus, addr, reg, &val);
+	if (ret < 0)
+		goto exit;
+
+	val &= ~mask;
+	val |= write_val;
+	ret = an8855_mii_write32(bus, addr, reg, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret < 0 ? ret : 0;
+}
+
+static const struct regmap_range an8855_readable_ranges[] = {
+	regmap_reg_range(0x10000000, 0x10000fff), /* SCU */
+	regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */
+	regmap_reg_range(0x10002000, 0x10002fff), /* MCU */
+	regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */
+	regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */
+	regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */
+	regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */
+	regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */
+	regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */
+	regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */
+	regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */
+	regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */
+	regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */
+	regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */
+	regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */
+	regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */
+	regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */
+	regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */
+	regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */
+	regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */
+	regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */
+	regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */
+	regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */
+	regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */
+	regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */
+	regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */
+	regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */
+};
+
+static const struct regmap_access_table an8855_readable_table = {
+	.yes_ranges = an8855_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges),
+};
+
+static const struct regmap_config an8855_regmap_config = {
+	.name = "switch",
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0xbfffffff,
+	.reg_read = an8855_regmap_read,
+	.reg_write = an8855_regmap_write,
+	.reg_update_bits = an8855_regmap_update_bits,
+	.disable_locking = true,
+	.rd_table = &an8855_readable_table,
+};
+
+static int an855_regmap_phy_reset_page(struct an8855_core_priv *priv,
+				       int phy) __must_hold(&priv->bus->mdio_lock)
+{
+	/* Check PHY page only for addr shared with switch */
+	if (phy != priv->switch_addr)
+		return 0;
+
+	/* Don't restore page if it's not set to Switch page */
+	if (priv->current_page != FIELD_GET(AN8855_PHY_PAGE,
+					    AN8855_PHY_PAGE_EXTENDED_4))
+		return 0;
+
+	/*
+	 * Restore page to 0, PHY might change page right after but that
+	 * will be ignored as it won't be a switch page.
+	 */
+	return an8855_mii_set_page(priv, phy, AN8855_PHY_PAGE_STANDARD);
+}
+
+static int an8855_regmap_phy_read(void *ctx, int addr, int regnum)
+{
+	struct an8855_core_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an855_regmap_phy_reset_page(priv, addr);
+	if (ret)
+		goto exit;
+
+	ret = __mdiobus_read(priv->bus, addr, regnum);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret;
+}
+
+static int an8855_regmap_phy_write(void *ctx, int addr, int regnum, u16 val)
+{
+	struct an8855_core_priv *priv = ctx;
+	struct mii_bus *bus = priv->bus;
+	int ret;
+
+	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+	ret = an855_regmap_phy_reset_page(priv, addr);
+	if (ret)
+		goto exit;
+
+	ret = __mdiobus_write(priv->bus, addr, regnum, val);
+
+exit:
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret;
+}
+
+static const struct mdio_regmap_init_config an8855_regmap_phy_config = {
+	.name = "phy",
+	.mdio_read = an8855_regmap_phy_read,
+	.mdio_write = an8855_regmap_phy_write,
+};
+
+static int an8855_read_switch_id(struct device *dev, struct regmap *regmap)
+{
+	u32 id;
+	int ret;
+
+	ret = regmap_read(regmap, AN8855_CREV, &id);
+	if (ret)
+		return ret;
+
+	if (id != AN8855_ID) {
+		dev_err(dev, "Detected Switch ID %x but %x was expected\n",
+			id, AN8855_ID);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int an8855_core_probe(struct mdio_device *mdiodev)
+{
+	struct regmap *regmap, *regmap_phy;
+	struct device *dev = &mdiodev->dev;
+	struct an8855_core_priv *priv;
+	struct gpio_desc *reset_gpio;
+	u32 val;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->bus = mdiodev->bus;
+	priv->switch_addr = mdiodev->addr;
+	/* No DMA for mdiobus, mute warning for DMA mask not set */
+	dev->dma_mask = &dev->coherent_dma_mask;
+
+	regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "regmap initialization failed\n");
+
+	regmap_phy = devm_mdio_regmap_init(dev, priv, &an8855_regmap_phy_config);
+	if (IS_ERR(regmap_phy))
+		return dev_err_probe(dev, PTR_ERR(regmap_phy),
+				     "regmap phy initialization failed\n");
+
+	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(reset_gpio))
+		return PTR_ERR(reset_gpio);
+
+	if (reset_gpio) {
+		usleep_range(100000, 150000);
+		gpiod_set_value_cansleep(reset_gpio, 0);
+		usleep_range(100000, 150000);
+		gpiod_set_value_cansleep(reset_gpio, 1);
+
+		/* Poll HWTRAP reg to wait for Switch to fully Init */
+		ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
+					       val, 20, 200000);
+		if (ret)
+			return ret;
+	}
+
+	ret = an8855_read_switch_id(dev, regmap);
+	if (ret)
+		return ret;
+
+	/* Release global PHY power down */
+	ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
+	if (ret)
+		return ret;
+
+	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_core_childs,
+				    ARRAY_SIZE(an8855_core_childs), NULL, 0,
+				    NULL);
+}
+
+static const struct of_device_id an8855_core_of_match[] = {
+	{ .compatible = "airoha,an8855" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_core_of_match);
+
+static struct mdio_driver an8855_core_driver = {
+	.probe = an8855_core_probe,
+	.mdiodrv.driver = {
+		.name = "an8855",
+		.of_match_table = an8855_core_of_match,
+	},
+};
+mdio_module_driver(an8855_core_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:51 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:51 +0100
Subject: [net-next PATCH v13 11/14] net: mdio: Add Airoha AN8855 Switch MDIO Passtrough
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-12-ansuelsmth@gmail.com>

Add Airoha AN8855 Switch driver to register a MDIO passtrough as switch
address is shared with the internal PHYs and require additional page
handling.

This requires the upper Switch MFD to be probed and init to actually
work.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                    |  1 +
 drivers/net/mdio/Kconfig       | 10 +++++++
 drivers/net/mdio/Makefile      |  1 +
 drivers/net/mdio/mdio-an8855.c | 49 ++++++++++++++++++++++++++++++++++
 4 files changed, 61 insertions(+)
 create mode 100644 drivers/net/mdio/mdio-an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index aec293953382..f4c8054d3980 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -731,6 +731,7 @@ F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 F:	drivers/mfd/airoha-an8855.c
+F:	drivers/net/mdio/mdio-an8855.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 4a7a303be2f7..e31a37064934 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -61,6 +61,16 @@ config MDIO_XGENE
 	  This module provides a driver for the MDIO busses found in the
 	  APM X-Gene SoC's.
 
+config MDIO_AN8855
+	tristate "Airoha AN8855 Switch MDIO bus controller"
+	depends on MFD_AIROHA_AN8855
+	depends on OF_MDIO
+	select MDIO_REGMAP
+	help
+	  This module provides a driver for the Airoha AN8855 Switch
+	  that requires a MDIO passtrough as switch address is shared
+	  with the internal PHYs and requires additional page handling.
+
 config MDIO_ASPEED
 	tristate "ASPEED MDIO bus controller"
 	depends on ARCH_ASPEED || COMPILE_TEST
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 1015f0db4531..546c4e55b475 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_ACPI_MDIO)		+= acpi_mdio.o
 obj-$(CONFIG_FWNODE_MDIO)	+= fwnode_mdio.o
 obj-$(CONFIG_OF_MDIO)		+= of_mdio.o
 
+obj-$(CONFIG_MDIO_AN8855)		+= mdio-an8855.o
 obj-$(CONFIG_MDIO_ASPEED)		+= mdio-aspeed.o
 obj-$(CONFIG_MDIO_BCM_IPROC)		+= mdio-bcm-iproc.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)		+= mdio-bcm-unimac.o
diff --git a/drivers/net/mdio/mdio-an8855.c b/drivers/net/mdio/mdio-an8855.c
new file mode 100644
index 000000000000..22d199942f1c
--- /dev/null
+++ b/drivers/net/mdio/mdio-an8855.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MDIO passthrough driver for Airoha AN8855 Switch
+ */
+
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static int an8855_mdio_probe(struct platform_device *pdev)
+{
+	struct mdio_regmap_config mrc = { };
+	struct device *dev = &pdev->dev;
+	struct mii_bus *bus;
+
+	mrc.regmap = dev_get_regmap(dev->parent, "phy");
+	mrc.parent = dev;
+	mrc.valid_addr_mask = GENMASK(31, 0);
+	mrc.support_encoded_addr = true;
+	mrc.autoscan = true;
+	mrc.np = dev->of_node;
+	snprintf(mrc.name, MII_BUS_ID_SIZE, KBUILD_MODNAME);
+
+	bus = devm_mdio_regmap_register(dev, &mrc);
+	if (IS_ERR(bus))
+		return dev_err_probe(dev, PTR_ERR(bus), "failed to register MDIO bus\n");
+
+	return 0;
+}
+
+static const struct of_device_id an8855_mdio_of_match[] = {
+	{ .compatible = "airoha,an8855-mdio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_mdio_of_match);
+
+static struct platform_driver an8855_mdio_driver = {
+	.probe	= an8855_mdio_probe,
+	.driver = {
+		.name = "an8855-mdio",
+		.of_match_table = an8855_mdio_of_match,
+	},
+};
+module_platform_driver(an8855_mdio_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 MDIO passthrough");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:43 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:43 +0100
Subject: [net-next PATCH v13 03/14] dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-4-ansuelsmth@gmail.com>

Document support for Airoha AN8855 5-port Gigabit Switch.

It does expose the 5 Internal PHYs on the MDIO bus and each port
can access the Switch register space by configurting the PHY page.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../net/dsa/airoha,an8855-switch.yaml         | 86 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml

diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
new file mode 100644
index 000000000000..fbb9219fadae
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Gigabit Switch
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 is a 5-port Gigabit Switch.
+
+  It does expose the 5 Internal PHYs on the MDIO bus and each port
+  can access the Switch register space by configurting the PHY page.
+
+$ref: dsa.yaml#/$defs/ethernet-ports
+
+properties:
+  compatible:
+    const: airoha,an8855-switch
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    ethernet-switch {
+        compatible = "airoha,an8855-switch";
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port at 0 {
+                reg = <0>;
+                label = "lan1";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy1>;
+            };
+
+            port at 1 {
+                reg = <1>;
+                label = "lan2";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy2>;
+            };
+
+            port at 2 {
+                reg = <2>;
+                label = "lan3";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy3>;
+            };
+
+            port at 3 {
+                reg = <3>;
+                label = "lan4";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy4>;
+            };
+
+            port at 4 {
+                reg = <4>;
+                label = "wan";
+                phy-mode = "internal";
+                phy-handle = <&internal_phy5>;
+            };
+
+            port at 5 {
+                reg = <5>;
+                label = "cpu";
+                ethernet = <&gmac0>;
+                phy-mode = "2500base-x";
+
+                fixed-link {
+                    speed = <2500>;
+                    full-duplex;
+                    pause;
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 1e8055b5e162..696ad8465ea8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -726,6 +726,7 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
 AIROHA ETHERNET DRIVER
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:44 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:44 +0100
Subject: [net-next PATCH v13 04/14] dt-bindings: net: Document support for AN8855 Switch Internal PHY
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-5-ansuelsmth@gmail.com>

Document support for AN8855 Switch Internal PHY.

Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
PHYs on the MDIO bus.

Each PHY might need to be calibrated to correctly work with the
use of the eFUSE provided by the Switch SoC. This can be enabled by
defining in the PHY node the NVMEM cell properties.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/net/airoha,an8855-phy.yaml       | 83 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 84 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml

diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
new file mode 100644
index 000000000000..d2f86116badf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch Internal PHY
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
+  PHYs on the MDIO bus.
+
+  Each PHY might need to be calibrated to correctly work with the
+  use of the eFUSE provided by the Switch SoC.
+
+allOf:
+  - $ref: ethernet-phy.yaml#
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - ethernet-phy-idc0ff.0410
+  required:
+    - compatible
+
+properties:
+  reg:
+    maxItems: 1
+
+  nvmem-cells:
+    items:
+      - description: phandle to SoC eFUSE tx_a
+      - description: phandle to SoC eFUSE tx_b
+      - description: phandle to SoC eFUSE tx_c
+      - description: phandle to SoC eFUSE tx_d
+
+  nvmem-cell-names:
+    items:
+      - const: tx_a
+      - const: tx_b
+      - const: tx_c
+      - const: tx_d
+
+required:
+  - compatible
+  - reg
+
+dependentRequired:
+  nvmem-cells: [ nvmem-cell-names ]
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet-phy at 1 {
+            compatible = "ethernet-phy-idc0ff.0410",
+                         "ethernet-phy-ieee802.3-c45";
+
+            reg = <1>;
+        };
+
+        ethernet-phy at 2 {
+            compatible = "ethernet-phy-idc0ff.0410",
+                         "ethernet-phy-ieee802.3-c45";
+
+            reg = <2>;
+
+            nvmem-cells = <&shift_sel_port0_tx_a>,
+                          <&shift_sel_port0_tx_b>,
+                          <&shift_sel_port0_tx_c>,
+                          <&shift_sel_port0_tx_d>;
+            nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 696ad8465ea8..45f4bb8deb0d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -726,6 +726,7 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:45 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:45 +0100
Subject: [net-next PATCH v13 05/14] dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-6-ansuelsmth@gmail.com>

Document support for Airoha AN8855 Switch SoC. This SoC expose various
peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.

It does also support i2c and timers but those are not currently
supported/used.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/mfd/airoha,an8855.yaml           | 182 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 183 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml

diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
new file mode 100644
index 000000000000..a59a23056b3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN8855 Switch SoC
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  Airoha AN8855 Switch is a SoC that expose various peripherals like an
+  Ethernet Switch, a NVMEM provider and Ethernet PHYs.
+
+  It does also support i2c and timers but those are not currently
+  supported/used.
+
+properties:
+  compatible:
+    const: airoha,an8855
+
+  reg:
+    maxItems: 1
+
+  reset-gpios: true
+
+  efuse:
+    type: object
+    $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
+    description:
+      EFUSE exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
+
+  ethernet-switch:
+    type: object
+    $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
+    description:
+      Switch exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
+
+  mdio:
+    type: object
+    $ref: /schemas/net/airoha,an8855-mdio.yaml
+    description:
+      MDIO exposed by the Airoha AN8855 Switch. This child node definition
+      should follow the bindings specified in
+      Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        soc at 1 {
+            compatible = "airoha,an8855";
+            reg = <1>;
+
+            reset-gpios = <&pio 39 0>;
+
+            efuse {
+                compatible = "airoha,an8855-efuse";
+
+                #nvmem-cell-cells = <0>;
+
+                nvmem-layout {
+                    compatible = "fixed-layout";
+                    #address-cells = <1>;
+                    #size-cells = <1>;
+
+                    shift_sel_port0_tx_a: shift-sel-port0-tx-a at c {
+                       reg = <0xc 0x4>;
+                    };
+
+                    shift_sel_port0_tx_b: shift-sel-port0-tx-b at 10 {
+                        reg = <0x10 0x4>;
+                    };
+
+                    shift_sel_port0_tx_c: shift-sel-port0-tx-c at 14 {
+                        reg = <0x14 0x4>;
+                    };
+
+                    shift_sel_port0_tx_d: shift-sel-port0-tx-d at 18 {
+                       reg = <0x18 0x4>;
+                    };
+
+                    shift_sel_port1_tx_a: shift-sel-port1-tx-a at 1c {
+                        reg = <0x1c 0x4>;
+                    };
+
+                    shift_sel_port1_tx_b: shift-sel-port1-tx-b at 20 {
+                        reg = <0x20 0x4>;
+                    };
+
+                    shift_sel_port1_tx_c: shift-sel-port1-tx-c at 24 {
+                       reg = <0x24 0x4>;
+                    };
+
+                    shift_sel_port1_tx_d: shift-sel-port1-tx-d at 28 {
+                        reg = <0x28 0x4>;
+                    };
+                };
+            };
+
+            ethernet-switch {
+                compatible = "airoha,an8855-switch";
+
+                ports {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
+                    port at 0 {
+                        reg = <0>;
+                        label = "lan1";
+                        phy-mode = "internal";
+                        phy-handle = <&internal_phy1>;
+                    };
+
+                    port at 1 {
+                        reg = <1>;
+                        label = "lan2";
+                        phy-mode = "internal";
+                        phy-handle = <&internal_phy2>;
+                    };
+
+                    port at 5 {
+                        reg = <5>;
+                        label = "cpu";
+                        ethernet = <&gmac0>;
+                        phy-mode = "2500base-x";
+
+                        fixed-link {
+                            speed = <2500>;
+                            full-duplex;
+                            pause;
+                        };
+                    };
+                };
+            };
+
+            mdio {
+                compatible = "airoha,an8855-mdio";
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                internal_phy1: phy at 1 {
+                  compatible = "ethernet-phy-idc0ff.0410",
+                               "ethernet-phy-ieee802.3-c45";
+                  reg = <1>;
+
+                  nvmem-cells = <&shift_sel_port0_tx_a>,
+                      <&shift_sel_port0_tx_b>,
+                      <&shift_sel_port0_tx_c>,
+                      <&shift_sel_port0_tx_d>;
+                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+                };
+
+                internal_phy2: phy at 2 {
+                  compatible = "ethernet-phy-idc0ff.0410",
+                               "ethernet-phy-ieee802.3-c45";
+                  reg = <2>;
+
+                  nvmem-cells = <&shift_sel_port1_tx_a>,
+                      <&shift_sel_port1_tx_b>,
+                      <&shift_sel_port1_tx_c>,
+                      <&shift_sel_port1_tx_d>;
+                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 45f4bb8deb0d..65709e47adc7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -725,6 +725,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 L:	netdev at vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
 F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
 F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:46 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:46 +0100
Subject: [net-next PATCH v13 06/14] net: mdio: regmap: prepare support for multiple valid addr
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-7-ansuelsmth@gmail.com>

Rework the valid_addr and convert it to a mask in preparation for mdio
regmap to support multiple valid addr in the case the regmap can support
it.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 8a742a8d6387..810ba0a736f0 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -19,7 +19,7 @@
 
 struct mdio_regmap_priv {
 	struct regmap *regmap;
-	u8 valid_addr;
+	u32 valid_addr_mask;
 };
 
 static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
@@ -28,7 +28,7 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
 	unsigned int val;
 	int ret;
 
-	if (ctx->valid_addr != addr)
+	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
 	ret = regmap_read(ctx->regmap, regnum, &val);
@@ -43,7 +43,7 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
 {
 	struct mdio_regmap_priv *ctx = bus->priv;
 
-	if (ctx->valid_addr != addr)
+	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
 	return regmap_write(ctx->regmap, regnum, val);
@@ -65,7 +65,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 
 	mr = mii->priv;
 	mr->regmap = config->regmap;
-	mr->valid_addr = config->valid_addr;
+	mr->valid_addr_mask = BIT(config->valid_addr);
 
 	mii->name = DRV_NAME;
 	strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
@@ -74,7 +74,7 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	mii->write = mdio_regmap_write_c22;
 
 	if (config->autoscan)
-		mii->phy_mask = ~BIT(config->valid_addr);
+		mii->phy_mask = ~mr->valid_addr_mask;
 	else
 		mii->phy_mask = ~0;
 
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:47 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:47 +0100
Subject: [net-next PATCH v13 07/14] net: mdio: regmap: add support for C45 read/write
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-8-ansuelsmth@gmail.com>

Add support for C45 read/write for mdio regmap. This can be done
by enabling the support_encoded_addr bool in mdio regmap config and by
using the new API devm_mdio_regmap_init to init a regmap.

To support C45, additional info needs to be appended to the regmap
address passed to regmap OPs.

The logic applied to the regmap address value:
- First the regnum value (20, 16)
- Second the devnum value (25, 21)
- A bit to signal if it's C45 (26)

devm_mdio_regmap_init MUST be used to register a regmap for this to
correctly handle internally the encode/decode of the address.

Drivers needs to define a mdio_regmap_init_config where an optional regmap
name can be defined and MUST define C22 OPs (mdio_read/write).
To support C45 operation also C45 OPs (mdio_read/write_c45).

The regmap from devm_mdio_regmap_init will internally decode the encoded
regmap address and extract the various info (addr, devnum if C45 and
regnum). It will then call the related OP and pass the extracted values to
the function.

Example for a C45 read operation:
- With an encoded address with C45 bit enabled, it will call the
  .mdio_read_c45 and addr, devnum and regnum will be passed.
  .mdio_read_c45 will then return the val and val will be stored in the
  regmap_read pointer and will return 0. If .mdio_read_c45 returns
  any error, then the regmap_read will return such error.

With support_encoded_addr enabled, also C22 will encode the address in
the regmap address and .mdio_read/write will called accordingly similar
to C45 operation.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 170 +++++++++++++++++++++++++++++--
 include/linux/mdio/mdio-regmap.h |  14 +++
 2 files changed, 176 insertions(+), 8 deletions(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 810ba0a736f0..f263e4ae2477 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -15,22 +15,72 @@
 #include <linux/regmap.h>
 #include <linux/mdio/mdio-regmap.h>
 
+#define MDIO_REGMAP_C45			BIT(26)
+#define MDIO_REGMAP_ADDR		GENMASK(25, 21)
+#define MDIO_REGMAP_DEVNUM		GENMASK(20, 16)
+#define MDIO_REGMAP_REGNUM		GENMASK(15, 0)
+
 #define DRV_NAME "mdio-regmap"
 
 struct mdio_regmap_priv {
+	void *ctx;
+
+	const struct mdio_regmap_init_config *config;
+};
+
+struct mdio_regmap_mii_priv {
 	struct regmap *regmap;
 	u32 valid_addr_mask;
+	bool encode_addr;
 };
 
-static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
+static int mdio_regmap_mii_read_c22(struct mii_bus *bus, int addr, int regnum)
+{
+	struct mdio_regmap_mii_priv *ctx = bus->priv;
+	unsigned int val;
+	int ret;
+
+	if (!(ctx->valid_addr_mask & BIT(addr)))
+		return -ENODEV;
+
+	if (ctx->encode_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_ADDR, addr);
+
+	ret = regmap_read(ctx->regmap, regnum, &val);
+	if (ret < 0)
+		return ret;
+
+	return val;
+}
+
+static int mdio_regmap_mii_write_c22(struct mii_bus *bus, int addr, int regnum,
+				     u16 val)
 {
-	struct mdio_regmap_priv *ctx = bus->priv;
+	struct mdio_regmap_mii_priv *ctx = bus->priv;
+
+	if (!(ctx->valid_addr_mask & BIT(addr)))
+		return -ENODEV;
+
+	if (ctx->encode_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_ADDR, addr);
+
+	return regmap_write(ctx->regmap, regnum, val);
+}
+
+static int mdio_regmap_mii_read_c45(struct mii_bus *bus, int addr, int devnum,
+				    int regnum)
+{
+	struct mdio_regmap_mii_priv *ctx = bus->priv;
 	unsigned int val;
 	int ret;
 
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	regnum |= MDIO_REGMAP_C45;
+	regnum |= FIELD_PREP(MDIO_REGMAP_ADDR, addr);
+	regnum |= FIELD_PREP(MDIO_REGMAP_DEVNUM, devnum);
+
 	ret = regmap_read(ctx->regmap, regnum, &val);
 	if (ret < 0)
 		return ret;
@@ -38,21 +88,25 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
 	return val;
 }
 
-static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
-				 u16 val)
+static int mdio_regmap_mii_write_c45(struct mii_bus *bus, int addr, int devnum,
+				     int regnum, u16 val)
 {
-	struct mdio_regmap_priv *ctx = bus->priv;
+	struct mdio_regmap_mii_priv *ctx = bus->priv;
 
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	regnum |= MDIO_REGMAP_C45;
+	regnum |= FIELD_PREP(MDIO_REGMAP_ADDR, addr);
+	regnum |= FIELD_PREP(MDIO_REGMAP_DEVNUM, devnum);
+
 	return regmap_write(ctx->regmap, regnum, val);
 }
 
 struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 					  const struct mdio_regmap_config *config)
 {
-	struct mdio_regmap_priv *mr;
+	struct mdio_regmap_mii_priv *mr;
 	struct mii_bus *mii;
 	int rc;
 
@@ -66,12 +120,17 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	mr = mii->priv;
 	mr->regmap = config->regmap;
 	mr->valid_addr_mask = BIT(config->valid_addr);
+	mr->encode_addr = config->support_encoded_addr;
 
 	mii->name = DRV_NAME;
 	strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
 	mii->parent = config->parent;
-	mii->read = mdio_regmap_read_c22;
-	mii->write = mdio_regmap_write_c22;
+	mii->read = mdio_regmap_mii_read_c22;
+	mii->write = mdio_regmap_mii_write_c22;
+	if (config->support_encoded_addr) {
+		mii->read_c45 = mdio_regmap_mii_read_c45;
+		mii->write_c45 = mdio_regmap_mii_write_c45;
+	}
 
 	if (config->autoscan)
 		mii->phy_mask = ~mr->valid_addr_mask;
@@ -88,6 +147,101 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_mdio_regmap_register);
 
+static int mdio_regmap_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+	const struct mdio_regmap_init_config *config;
+	struct mdio_regmap_priv *priv = context;
+	int addr, regnum;
+	int ret;
+
+	config = priv->config;
+
+	addr = FIELD_GET(MDIO_REGMAP_ADDR, reg);
+	regnum = FIELD_GET(MDIO_REGMAP_REGNUM, reg);
+
+	if (reg & MDIO_REGMAP_C45) {
+		int devnum;
+
+		if (!config->mdio_write_c45)
+			return -EOPNOTSUPP;
+
+		devnum = FIELD_GET(MDIO_REGMAP_DEVNUM, reg);
+		ret = config->mdio_read_c45(priv->ctx, addr, devnum, regnum);
+	} else {
+		ret = config->mdio_read(priv->ctx, addr, regnum);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+	return 0;
+}
+
+static int mdio_regmap_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+	const struct mdio_regmap_init_config *config;
+	struct mdio_regmap_priv *priv = context;
+	int addr, regnum;
+
+	config = priv->config;
+
+	addr = FIELD_GET(MDIO_REGMAP_ADDR, reg);
+	regnum = FIELD_GET(MDIO_REGMAP_REGNUM, reg);
+
+	if (reg & MDIO_REGMAP_C45) {
+		int devnum;
+
+		if (!config->mdio_write_c45)
+			return -EOPNOTSUPP;
+
+		devnum = FIELD_GET(MDIO_REGMAP_DEVNUM, reg);
+		return config->mdio_write_c45(priv->ctx, addr, devnum, regnum, val);
+	}
+
+	return config->mdio_write(priv->ctx, addr, regnum, val);
+}
+
+static const struct regmap_config mdio_regmap_default_config = {
+	.reg_bits = 26,
+	.val_bits = 16,
+	.reg_stride = 1,
+	.max_register = MDIO_REGMAP_C45 | MDIO_REGMAP_ADDR |
+			MDIO_REGMAP_DEVNUM | MDIO_REGMAP_REGNUM,
+	.reg_read = mdio_regmap_reg_read,
+	.reg_write = mdio_regmap_reg_write,
+	/* Locking MUST be handled in mdio_write/read(_c45) */
+	.disable_locking = true,
+};
+
+struct regmap *devm_mdio_regmap_init(struct device *dev, void *priv,
+				     const struct mdio_regmap_init_config *config)
+{
+	struct mdio_regmap_priv *mdio_regmap_priv;
+	struct regmap_config regmap_config;
+
+	/* Validate config */
+	if (!config->mdio_read || !config->mdio_write) {
+		dev_err(dev, ".mdio_read and .mdio_write MUST be defined in config\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mdio_regmap_priv = devm_kzalloc(dev, sizeof(*mdio_regmap_priv),
+					GFP_KERNEL);
+	if (!mdio_regmap_priv)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&regmap_config, &mdio_regmap_default_config, sizeof(regmap_config));
+	regmap_config.name = config->name;
+
+	mdio_regmap_priv->ctx = priv;
+	mdio_regmap_priv->config = config;
+
+	return devm_regmap_init(dev, NULL, mdio_regmap_priv,
+				&regmap_config);
+}
+EXPORT_SYMBOL_GPL(devm_mdio_regmap_init);
+
 MODULE_DESCRIPTION("MDIO API over regmap");
 MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier at bootlin.com>");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 679d9069846b..504fa2046043 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -17,10 +17,24 @@ struct mdio_regmap_config {
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
+	/* devm_mdio_regmap_init is required with this enabled */
+	bool support_encoded_addr;
 	bool autoscan;
 };
 
 struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 					  const struct mdio_regmap_config *config);
 
+struct mdio_regmap_init_config {
+	const char *name;
+
+	int (*mdio_read)(void *ctx, int addr, int regnum);
+	int (*mdio_write)(void *ctx, int addr, int regnum, u16 val);
+	int (*mdio_read_c45)(void *ctx, int addr, int devnum, int regnum);
+	int (*mdio_write_c45)(void *ctx, int addr, int devnum, int regnum, u16 val);
+};
+
+struct regmap *devm_mdio_regmap_init(struct device *dev, void *priv,
+				     const struct mdio_regmap_init_config *config);
+
 #endif
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:48 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:48 +0100
Subject: [net-next PATCH v13 08/14] net: mdio: regmap: add support for multiple valid addr
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-9-ansuelsmth@gmail.com>

Add support for multiple valid addr for mdio regmap. This can be done by
defining the new valid_addr_mask value in the mdio regmap config.

This makes use of the new implementation used by C45 to encode
additional info in the regmap address to support multiple MDIO address.

To actually use this, support_encoded_addr MUST be enabled and
(indirectly) devm_mdio_regmap_init must be used to create the regmap.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 8 +++++++-
 include/linux/mdio/mdio-regmap.h | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index f263e4ae2477..ed0443eb039f 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -113,13 +113,19 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 	if (!config->parent)
 		return ERR_PTR(-EINVAL);
 
+	if (config->valid_addr_mask && !config->support_encoded_addr) {
+		dev_err(dev, "encoded address support is required to support multiple MDIO address\n");
+		return ERR_PTR(-EINVAL);
+	}
+
 	mii = devm_mdiobus_alloc_size(config->parent, sizeof(*mr));
 	if (!mii)
 		return ERR_PTR(-ENOMEM);
 
 	mr = mii->priv;
 	mr->regmap = config->regmap;
-	mr->valid_addr_mask = BIT(config->valid_addr);
+	mr->valid_addr_mask = config->valid_addr_mask ? config->valid_addr_mask :
+							BIT(config->valid_addr);
 	mr->encode_addr = config->support_encoded_addr;
 
 	mii->name = DRV_NAME;
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 504fa2046043..bb0e7dc9c0dc 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -17,6 +17,7 @@ struct mdio_regmap_config {
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
+	u32 valid_addr_mask;
 	/* devm_mdio_regmap_init is required with this enabled */
 	bool support_encoded_addr;
 	bool autoscan;
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:52 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:52 +0100
Subject: [net-next PATCH v13 12/14] nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-13-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Switch EFUSE. These EFUSE might be used
for calibration data for the internal switch PHYs.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                  |  1 +
 drivers/nvmem/Kconfig        | 11 +++++++
 drivers/nvmem/Makefile       |  2 ++
 drivers/nvmem/an8855-efuse.c | 63 ++++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+)
 create mode 100644 drivers/nvmem/an8855-efuse.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f4c8054d3980..2cc8871186d5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -732,6 +732,7 @@ F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
 F:	Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml
 F:	drivers/mfd/airoha-an8855.c
 F:	drivers/net/mdio/mdio-an8855.c
+F:	drivers/nvmem/an8855-efuse.c
 
 AIROHA ETHERNET DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 8671b7c974b9..ca96c6ea685a 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -28,6 +28,17 @@ source "drivers/nvmem/layouts/Kconfig"
 
 # Devices
 
+config NVMEM_AN8855_EFUSE
+	tristate "Airoha AN8855 eFuse support"
+	depends on MFD_AIROHA_AN8855 || COMPILE_TEST
+	help
+	  Say y here to enable support for reading eFuses on Airoha AN8855
+	  Switch. These are e.g. used to store factory programmed
+	  calibration data required for the PHY.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called nvmem-an8855-efuse.
+
 config NVMEM_APPLE_EFUSES
 	tristate "Apple eFuse support"
 	depends on ARCH_APPLE || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 5b77bbb6488b..c732132c0e45 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -10,6 +10,8 @@ nvmem_layouts-y			:= layouts.o
 obj-y				+= layouts/
 
 # Devices
+obj-$(CONFIG_NVMEM_AN8855_EFUSE)	+= nvmem-an8855-efuse.o
+nvmem-an8855-efuse-y 			:= an8855-efuse.o
 obj-$(CONFIG_NVMEM_APPLE_EFUSES)	+= nvmem-apple-efuses.o
 nvmem-apple-efuses-y 			:= apple-efuses.o
 obj-$(CONFIG_NVMEM_BCM_OCOTP)		+= nvmem-bcm-ocotp.o
diff --git a/drivers/nvmem/an8855-efuse.c b/drivers/nvmem/an8855-efuse.c
new file mode 100644
index 000000000000..cd1564379098
--- /dev/null
+++ b/drivers/nvmem/an8855-efuse.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Airoha AN8855 Switch EFUSE Driver
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define AN8855_EFUSE_CELL		50
+
+#define AN8855_EFUSE_DATA0		0x1000a500
+#define   AN8855_EFUSE_R50O		GENMASK(30, 24)
+
+static int an8855_efuse_read(void *context, unsigned int offset,
+			     void *val, size_t bytes)
+{
+	struct regmap *regmap = context;
+
+	return regmap_bulk_read(regmap, AN8855_EFUSE_DATA0 + offset,
+				val, bytes / sizeof(u32));
+}
+
+static int an8855_efuse_probe(struct platform_device *pdev)
+{
+	struct nvmem_config an8855_nvmem_config = {
+		.name = "an8855-efuse",
+		.size = AN8855_EFUSE_CELL * sizeof(u32),
+		.stride = sizeof(u32),
+		.word_size = sizeof(u32),
+		.reg_read = an8855_efuse_read,
+	};
+	struct device *dev = &pdev->dev;
+	struct nvmem_device *nvmem;
+
+	/* Assign NVMEM priv to MFD regmap */
+	an8855_nvmem_config.priv = dev_get_regmap(dev->parent, "switch");
+	an8855_nvmem_config.dev = dev;
+	nvmem = devm_nvmem_register(dev, &an8855_nvmem_config);
+
+	return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static const struct of_device_id an8855_efuse_of_match[] = {
+	{ .compatible = "airoha,an8855-efuse", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, an8855_efuse_of_match);
+
+static struct platform_driver an8855_efuse_driver = {
+	.probe = an8855_efuse_probe,
+	.driver = {
+		.name = "an8855-efuse",
+		.of_match_table = an8855_efuse_of_match,
+	},
+};
+module_platform_driver(an8855_efuse_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_DESCRIPTION("Driver for AN8855 Switch EFUSE");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Sat Mar 15 08:43:54 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Sat, 15 Mar 2025 16:43:54 +0100
Subject: [net-next PATCH v13 14/14] net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY
In-Reply-To: <20250315154407.26304-1-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
Message-ID: <20250315154407.26304-15-ansuelsmth@gmail.com>

Add support for Airoha AN8855 Internal Switch Gigabit PHY.

This is a simple PHY driver to configure and calibrate the PHY for the
AN8855 Switch with the use of NVMEM cells.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                  |   1 +
 drivers/net/phy/Kconfig      |   5 +
 drivers/net/phy/Makefile     |   1 +
 drivers/net/phy/air_an8855.c | 261 +++++++++++++++++++++++++++++++++++
 4 files changed, 268 insertions(+)
 create mode 100644 drivers/net/phy/air_an8855.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e285fa2702f5..41fb4d0d7fdb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -734,6 +734,7 @@ F:	drivers/mfd/airoha-an8855.c
 F:	drivers/net/dsa/an8855.c
 F:	drivers/net/dsa/an8855.h
 F:	drivers/net/mdio/mdio-an8855.c
+F:	drivers/net/phy/air_an8855.c
 F:	drivers/nvmem/an8855-efuse.c
 
 AIROHA ETHERNET DRIVER
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d29f9f7fd2e1..e96f61b8eaba 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -79,6 +79,11 @@ config SFP
 
 comment "MII PHY device drivers"
 
+config AIR_AN8855_PHY
+	tristate "Airoha AN8855 Internal Gigabit PHY"
+	help
+	  Currently supports the internal Airoha AN8855 Switch PHY.
+
 config AIR_EN8811H_PHY
 	tristate "Airoha EN8811H 2.5 Gigabit PHY"
 	help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 8f9ba5e8290d..d4f537ba006c 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -36,6 +36,7 @@ obj-y				+= $(sfp-obj-y) $(sfp-obj-m)
 
 obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
+obj-$(CONFIG_AIR_AN8855_PHY)   += air_an8855.o
 obj-$(CONFIG_AIR_EN8811H_PHY)   += air_en8811h.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_AMCC_QT2025_PHY)	+= qt2025.o
diff --git a/drivers/net/phy/air_an8855.c b/drivers/net/phy/air_an8855.c
new file mode 100644
index 000000000000..a740dbaacf9a
--- /dev/null
+++ b/drivers/net/phy/air_an8855.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+
+#define AN8855_PHY_SELECT_PAGE			0x1f
+#define   AN8855_PHY_PAGE			GENMASK(2, 0)
+#define   AN8855_PHY_PAGE_STANDARD		FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
+#define   AN8855_PHY_PAGE_EXTENDED_1		FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
+
+/* MII Registers Page 1 */
+#define AN8855_PHY_EXT_REG_14			0x14
+#define   AN8855_PHY_EN_DOWN_SHIFT		BIT(4)
+
+/* R50 Calibration regs in MDIO_MMD_VEND1 */
+#define AN8855_PHY_R500HM_RSEL_TX_AB		0x174
+#define AN8855_PHY_R50OHM_RSEL_TX_A_EN		BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_A		GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_B_EN		BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_B		GENMASK(6, 0)
+#define AN8855_PHY_R500HM_RSEL_TX_CD		0x175
+#define AN8855_PHY_R50OHM_RSEL_TX_C_EN		BIT(15)
+#define AN8855_PHY_R50OHM_RSEL_TX_C		GENMASK(14, 8)
+#define AN8855_PHY_R50OHM_RSEL_TX_D_EN		BIT(7)
+#define AN8855_PHY_R50OHM_RSEL_TX_D		GENMASK(6, 0)
+
+#define AN8855_SWITCH_EFUSE_R50O		GENMASK(30, 24)
+
+/* PHY TX PAIR DELAY SELECT Register */
+#define AN8855_PHY_TX_PAIR_DLY_SEL_GBE		0x013
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE GENMASK(14, 12)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_B_GBE GENMASK(10, 8)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE GENMASK(6, 4)
+#define   AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_D_GBE GENMASK(2, 0)
+/* PHY ADC Register */
+#define AN8855_PHY_RXADC_CTRL			0x0d8
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A	BIT(12)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_B	BIT(8)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C	BIT(4)
+#define   AN8855_PHY_RG_AD_SAMNPLE_PHSEL_D	BIT(0)
+#define AN8855_PHY_RXADC_REV_0			0x0d9
+#define   AN8855_PHY_RG_AD_RESERVE0_A		GENMASK(15, 8)
+#define   AN8855_PHY_RG_AD_RESERVE0_B		GENMASK(7, 0)
+#define AN8855_PHY_RXADC_REV_1			0x0da
+#define   AN8855_PHY_RG_AD_RESERVE0_C		GENMASK(15, 8)
+#define   AN8855_PHY_RG_AD_RESERVE0_D		GENMASK(7, 0)
+
+#define AN8855_PHY_ID				0xc0ff0410
+
+struct air_an8855_priv {
+	bool needs_calibration;
+};
+
+static const u8 dsa_r50ohm_table[] = {
+	127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+	127, 127, 127, 127, 127, 127, 127, 126, 122, 117,
+	112, 109, 104, 101,  97,  94,  90,  88,  84,  80,
+	78,  74,  72,  68,  66,  64,  61,  58,  56,  53,
+	51,  48,  47,  44,  42,  40,  38,  36,  34,  32,
+	31,  28,  27,  24,  24,  22,  20,  18,  16,  16,
+	14,  12,  11,   9
+};
+
+static int en8855_get_r50ohm_val(struct device *dev, const char *calib_name,
+				 u8 *dest)
+{
+	u32 shift_sel, val;
+	int ret;
+	int i;
+
+	ret = nvmem_cell_read_u32(dev, calib_name, &val);
+	if (ret)
+		return ret;
+
+	shift_sel = FIELD_GET(AN8855_SWITCH_EFUSE_R50O, val);
+	for (i = 0; i < ARRAY_SIZE(dsa_r50ohm_table); i++)
+		if (dsa_r50ohm_table[i] == shift_sel)
+			break;
+
+	if (i < 8 || i >= ARRAY_SIZE(dsa_r50ohm_table))
+		*dest = dsa_r50ohm_table[25];
+	else
+		*dest = dsa_r50ohm_table[i - 8];
+
+	return 0;
+}
+
+static int an8855_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct air_an8855_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->needs_calibration = of_property_present(dev->of_node,
+						      "nvmem-cells");
+
+	phydev->priv = priv;
+
+	return 0;
+}
+
+static int an8855_get_downshift(struct phy_device *phydev, u8 *data)
+{
+	int val;
+
+	val = phy_read_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, AN8855_PHY_EXT_REG_14);
+	if (val < 0)
+		return val;
+
+	*data = val & AN8855_PHY_EN_DOWN_SHIFT ? DOWNSHIFT_DEV_DEFAULT_COUNT :
+						 DOWNSHIFT_DEV_DISABLE;
+
+	return 0;
+}
+
+static int an8855_set_downshift(struct phy_device *phydev, u8 cnt)
+{
+	u16 ds = cnt != DOWNSHIFT_DEV_DISABLE ? AN8855_PHY_EN_DOWN_SHIFT : 0;
+
+	return phy_modify_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1,
+				AN8855_PHY_EXT_REG_14, AN8855_PHY_EN_DOWN_SHIFT,
+				ds);
+}
+
+static int an8855_config_init(struct phy_device *phydev)
+{
+	struct air_an8855_priv *priv = phydev->priv;
+	struct device *dev = &phydev->mdio.dev;
+	int ret;
+
+	/* Enable HW auto downshift */
+	ret = an8855_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);
+	if (ret)
+		return ret;
+
+	if (priv->needs_calibration) {
+		u8 calibration_data[4];
+
+		ret = en8855_get_r50ohm_val(dev, "tx_a", &calibration_data[0]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_b", &calibration_data[1]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_c", &calibration_data[2]);
+		if (ret)
+			return ret;
+
+		ret = en8855_get_r50ohm_val(dev, "tx_d", &calibration_data[3]);
+		if (ret)
+			return ret;
+
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_AB,
+				     AN8855_PHY_R50OHM_RSEL_TX_A | AN8855_PHY_R50OHM_RSEL_TX_B,
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_A, calibration_data[0]) |
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_B, calibration_data[1]));
+		if (ret)
+			return ret;
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_CD,
+				     AN8855_PHY_R50OHM_RSEL_TX_C | AN8855_PHY_R50OHM_RSEL_TX_D,
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_C, calibration_data[2]) |
+				     FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_D, calibration_data[3]));
+		if (ret)
+			return ret;
+	}
+
+	/* Apply values to reduce signal noise */
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_TX_PAIR_DLY_SEL_GBE,
+			    FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE, 0x4) |
+			    FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE, 0x4));
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_CTRL,
+			    AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A |
+			    AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C);
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_0,
+			    FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_A, 0x1));
+	if (ret)
+		return ret;
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_1,
+			    FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_C, 0x1));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int an8855_get_tunable(struct phy_device *phydev,
+			      struct ethtool_tunable *tuna, void *data)
+{
+	switch (tuna->id) {
+	case ETHTOOL_PHY_DOWNSHIFT:
+		return an8855_get_downshift(phydev, data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int an8855_set_tunable(struct phy_device *phydev,
+			      struct ethtool_tunable *tuna, const void *data)
+{
+	switch (tuna->id) {
+	case ETHTOOL_PHY_DOWNSHIFT:
+		return an8855_set_downshift(phydev, *(const u8 *)data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int an8855_read_page(struct phy_device *phydev)
+{
+	return __phy_read(phydev, AN8855_PHY_SELECT_PAGE);
+}
+
+static int an8855_write_page(struct phy_device *phydev, int page)
+{
+	return __phy_write(phydev, AN8855_PHY_SELECT_PAGE, page);
+}
+
+static struct phy_driver an8855_driver[] = {
+{
+	PHY_ID_MATCH_EXACT(AN8855_PHY_ID),
+	.name			= "Airoha AN8855 internal PHY",
+	/* PHY_GBIT_FEATURES */
+	.flags			= PHY_IS_INTERNAL,
+	.probe			= an8855_probe,
+	.config_init		= an8855_config_init,
+	.soft_reset		= genphy_soft_reset,
+	.get_tunable		= an8855_get_tunable,
+	.set_tunable		= an8855_set_tunable,
+	.suspend		= genphy_suspend,
+	.resume			= genphy_resume,
+	.read_page		= an8855_read_page,
+	.write_page		= an8855_write_page,
+}, };
+
+module_phy_driver(an8855_driver);
+
+static struct mdio_device_id __maybe_unused an8855_tbl[] = {
+	{ PHY_ID_MATCH_EXACT(AN8855_PHY_ID) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(mdio, an8855_tbl);
+
+MODULE_DESCRIPTION("Airoha AN8855 PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From heiko at sntech.de  Sat Mar 15 08:46:57 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 15 Mar 2025 16:46:57 +0100
Subject: [GIT PULL] Rockchip dts64 changes for 6.15 #2
Message-ID: <23866869.6Emhk5qWAg@phil>

Hi soc maintainers,

please find below some additional Rockchip changes for for 6.15 .
And I think with that I'll call it done, and have everything else
wait for after the merge-window.


Please pull.
Thanks
Heiko


The following changes since commit ba82f56bbf20e4166c988621cd0507509872848e:

  arm64: dts: rockchip: Add SPI NOR device on the ROCK 4D (2025-03-08 18:19:59 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.15-rockchip-dts64-2

for you to fetch changes up to 73d246b4402c3356f6b3d13665de3a51eea7b555:

  arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0 (2025-03-15 15:49:00 +0100)

----------------------------------------------------------------
New peripheral the sdhci controller on rk3528. Enablement of hdmi and hdmi
audio on a number of additional boards. Better handling for scmi shared
memory on rk3568 and a fix for the used SCMI clock ids on rk3576.
As well as some fixes that were a bit late for trying to stuff them into
6.14 at this late stage of the cycle.

----------------------------------------------------------------
Chen-Yu Tsai (1):
      arm64: dts: rockchip: Remove bluetooth node from rock-3a

Chukun Pan (1):
      arm64: dts: rockchip: Move rk356x scmi SHMEM to reserved memory

Jianfeng Liu (3):
      arm64: dts: rockchip: Add AP6275P wireless support to ArmSoM Sige7
      arm64: dts: rockchip: Enable HDMI audio output for ArmSoM Sige7
      arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max

Jimmy Hon (4):
      arm64: dts: rockchip: Enable HDMI0 audio output for Orange Pi 5/5B
      arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Max
      arm64: dts: rockchip: Enable HDMI1 on Orange Pi 5 Plus
      arm64: dts: rockchip: Enable HDMI audio outputs for Orange Pi 5 Plus

Jonas Karlman (2):
      arm64: dts: rockchip: Add SDHCI controller for RK3528
      arm64: dts: rockchip: Enable onboard eMMC on Radxa E20C

Nicolas Frattaroli (3):
      dt-bindings: clock: rk3576: add SCMI clocks
      arm64: dts: rockchip: fix RK3576 SCMI clock IDs
      arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0

Yao Zi (1):
      arm64: dts: rockchip: Fix PWM pinctrl names

 arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts     |  2 +-
 arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts    |  4 +-
 arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi   |  2 +-
 arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts | 15 ++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi           | 24 ++++++++++
 arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts    | 14 ------
 arch/arm64/boot/dts/rockchip/rk356x-base.dtsi      | 25 +++++-----
 .../boot/dts/rockchip/rk3576-armsom-sige5.dts      |  3 +-
 arch/arm64/boot/dts/rockchip/rk3576.dtsi           | 18 ++++----
 .../boot/dts/rockchip/rk3588-armsom-sige7.dts      | 24 ++++++++++
 .../dts/rockchip/rk3588-orangepi-5-compact.dtsi    |  2 +-
 .../boot/dts/rockchip/rk3588-orangepi-5-max.dts    | 16 +++++++
 .../boot/dts/rockchip/rk3588-orangepi-5-plus.dts   | 54 ++++++++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts |  2 +-
 .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi      |  8 ++++
 include/dt-bindings/clock/rockchip,rk3576-cru.h    |  5 ++
 16 files changed, 174 insertions(+), 44 deletions(-)





From robh at kernel.org  Sat Mar 15 10:12:13 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sat, 15 Mar 2025 12:12:13 -0500
Subject: [net-next PATCH v13 05/14] dt-bindings: mfd: Document support
 for Airoha AN8855 Switch SoC
In-Reply-To: <20250315154407.26304-6-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
 <20250315154407.26304-6-ansuelsmth@gmail.com>
Message-ID: <174205873356.67148.10337205475865865960.robh@kernel.org>


On Sat, 15 Mar 2025 16:43:45 +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 Switch SoC. This SoC expose various
> peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> 
> It does also support i2c and timers but those are not currently
> supported/used.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/mfd/airoha,an8855.yaml           | 182 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 183 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 1: $nodename:0: 'phy at 1' does not match '^ethernet-phy(@[a-f0-9]+)?$'
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 1: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 2: $nodename:0: 'phy at 2' does not match '^ethernet-phy(@[a-f0-9]+)?$'
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/airoha,an8855.example.dtb: phy at 2: Unevaluated properties are not allowed ('compatible' was unexpected)
	from schema $id: http://devicetree.org/schemas/net/airoha,an8855-phy.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250315154407.26304-6-ansuelsmth at gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From lkp at intel.com  Sat Mar 15 10:59:01 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 16 Mar 2025 01:59:01 +0800
Subject: [soc:arm/fixes] BUILD SUCCESS
 45d5fe1c53baaed1fb3043f45d1e15ebb4bbe86a
Message-ID: <202503160155.OCXP2ee7-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git arm/fixes
branch HEAD: 45d5fe1c53baaed1fb3043f45d1e15ebb4bbe86a  ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX

elapsed time: 1445m

configs tested: 88
configs skipped: 3

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                            allyesconfig    gcc-14.2.0
arc                              allmodconfig    gcc-13.2.0
arc                              allyesconfig    gcc-13.2.0
arc                   randconfig-001-20250315    gcc-13.2.0
arc                   randconfig-002-20250315    gcc-13.2.0
arm                              allyesconfig    gcc-14.2.0
arm                   randconfig-001-20250315    gcc-14.2.0
arm                   randconfig-002-20250315    clang-21
arm                   randconfig-003-20250315    clang-21
arm                   randconfig-004-20250315    gcc-14.2.0
arm64                            allmodconfig    clang-18
arm64                 randconfig-001-20250315    gcc-14.2.0
arm64                 randconfig-002-20250315    gcc-14.2.0
arm64                 randconfig-003-20250315    clang-16
arm64                 randconfig-004-20250315    gcc-14.2.0
csky                  randconfig-001-20250315    gcc-14.2.0
csky                  randconfig-002-20250315    gcc-14.2.0
hexagon                          allmodconfig    clang-21
hexagon                          allyesconfig    clang-18
hexagon               randconfig-001-20250315    clang-21
hexagon               randconfig-002-20250315    clang-17
i386                             allmodconfig    gcc-12
i386                              allnoconfig    gcc-12
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250315    gcc-12
i386        buildonly-randconfig-002-20250315    clang-19
i386        buildonly-randconfig-003-20250315    clang-19
i386        buildonly-randconfig-004-20250315    clang-19
i386        buildonly-randconfig-005-20250315    gcc-11
i386        buildonly-randconfig-006-20250315    gcc-12
i386                                defconfig    clang-19
loongarch             randconfig-001-20250315    gcc-14.2.0
loongarch             randconfig-002-20250315    gcc-14.2.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250315    gcc-14.2.0
nios2                 randconfig-002-20250315    gcc-14.2.0
openrisc                          allnoconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                randconfig-001-20250315    gcc-14.2.0
parisc                randconfig-002-20250315    gcc-14.2.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc               randconfig-001-20250315    clang-21
powerpc               randconfig-002-20250315    gcc-14.2.0
powerpc               randconfig-003-20250315    clang-18
powerpc64             randconfig-001-20250315    gcc-14.2.0
powerpc64             randconfig-002-20250315    clang-18
powerpc64             randconfig-003-20250315    gcc-14.2.0
riscv                             allnoconfig    gcc-14.2.0
riscv                 randconfig-001-20250315    gcc-14.2.0
riscv                 randconfig-002-20250315    gcc-14.2.0
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250315    clang-19
s390                  randconfig-002-20250315    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250315    gcc-14.2.0
sh                    randconfig-002-20250315    gcc-14.2.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250315    gcc-14.2.0
sparc                 randconfig-002-20250315    gcc-14.2.0
sparc64               randconfig-001-20250315    gcc-14.2.0
sparc64               randconfig-002-20250315    gcc-14.2.0
um                               allmodconfig    clang-21
um                                allnoconfig    clang-18
um                               allyesconfig    gcc-12
um                    randconfig-001-20250315    gcc-12
um                    randconfig-002-20250315    clang-18
x86_64                            allnoconfig    clang-19
x86_64                           allyesconfig    clang-19
x86_64      buildonly-randconfig-001-20250315    gcc-12
x86_64      buildonly-randconfig-002-20250315    clang-19
x86_64      buildonly-randconfig-003-20250315    clang-19
x86_64      buildonly-randconfig-004-20250315    clang-19
x86_64      buildonly-randconfig-005-20250315    clang-19
x86_64      buildonly-randconfig-006-20250315    gcc-12
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250315    gcc-14.2.0
xtensa                randconfig-002-20250315    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Sat Mar 15 10:59:56 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 16 Mar 2025 01:59:56 +0800
Subject: [soc:for-next] BUILD SUCCESS
 69e7831ba231cdf8db6d2119f118e8ec9fa2ee8f
Message-ID: <202503160150.sCvYuOsU-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
branch HEAD: 69e7831ba231cdf8db6d2119f118e8ec9fa2ee8f  Merge branch 'arm/fixes' into for-next

elapsed time: 1445m

configs tested: 93
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
alpha                            allyesconfig    gcc-14.2.0
arc                              allmodconfig    gcc-13.2.0
arc                               allnoconfig    gcc-13.2.0
arc                              allyesconfig    gcc-13.2.0
arc                   randconfig-001-20250315    gcc-13.2.0
arc                   randconfig-002-20250315    gcc-13.2.0
arm                              allmodconfig    gcc-14.2.0
arm                              allyesconfig    gcc-14.2.0
arm                   randconfig-001-20250315    gcc-14.2.0
arm                   randconfig-002-20250315    clang-21
arm                   randconfig-003-20250315    clang-21
arm                   randconfig-004-20250315    gcc-14.2.0
arm64                            allmodconfig    clang-18
arm64                 randconfig-001-20250315    gcc-14.2.0
arm64                 randconfig-002-20250315    gcc-14.2.0
arm64                 randconfig-003-20250315    clang-16
arm64                 randconfig-004-20250315    gcc-14.2.0
csky                  randconfig-001-20250315    gcc-14.2.0
csky                  randconfig-002-20250315    gcc-14.2.0
hexagon                          allmodconfig    clang-21
hexagon                          allyesconfig    clang-18
hexagon               randconfig-001-20250315    clang-21
hexagon               randconfig-002-20250315    clang-17
i386                              allnoconfig    gcc-12
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250315    gcc-12
i386        buildonly-randconfig-002-20250315    clang-19
i386        buildonly-randconfig-003-20250315    clang-19
i386        buildonly-randconfig-004-20250315    clang-19
i386        buildonly-randconfig-005-20250315    gcc-11
i386        buildonly-randconfig-006-20250315    gcc-12
i386                                defconfig    clang-19
loongarch                        allmodconfig    gcc-14.2.0
loongarch             randconfig-001-20250315    gcc-14.2.0
loongarch             randconfig-002-20250315    gcc-14.2.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250315    gcc-14.2.0
nios2                 randconfig-002-20250315    gcc-14.2.0
openrisc                          allnoconfig    gcc-14.2.0
openrisc                            defconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                              defconfig    gcc-14.2.0
parisc                randconfig-001-20250315    gcc-14.2.0
parisc                randconfig-002-20250315    gcc-14.2.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc               randconfig-001-20250315    clang-21
powerpc               randconfig-002-20250315    gcc-14.2.0
powerpc               randconfig-003-20250315    clang-18
powerpc64             randconfig-001-20250315    gcc-14.2.0
powerpc64             randconfig-002-20250315    clang-18
powerpc64             randconfig-003-20250315    gcc-14.2.0
riscv                             allnoconfig    gcc-14.2.0
riscv                 randconfig-001-20250315    gcc-14.2.0
riscv                 randconfig-002-20250315    gcc-14.2.0
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250315    clang-19
s390                  randconfig-002-20250315    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250315    gcc-14.2.0
sh                    randconfig-002-20250315    gcc-14.2.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250315    gcc-14.2.0
sparc                 randconfig-002-20250315    gcc-14.2.0
sparc64               randconfig-001-20250315    gcc-14.2.0
sparc64               randconfig-002-20250315    gcc-14.2.0
um                               allmodconfig    clang-21
um                                allnoconfig    clang-18
um                               allyesconfig    gcc-12
um                    randconfig-001-20250315    gcc-12
um                    randconfig-002-20250315    clang-18
x86_64                            allnoconfig    clang-19
x86_64                           allyesconfig    clang-19
x86_64      buildonly-randconfig-001-20250315    gcc-12
x86_64      buildonly-randconfig-002-20250315    clang-19
x86_64      buildonly-randconfig-003-20250315    clang-19
x86_64      buildonly-randconfig-004-20250315    clang-19
x86_64      buildonly-randconfig-005-20250315    clang-19
x86_64      buildonly-randconfig-006-20250315    gcc-12
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250315    gcc-14.2.0
xtensa                randconfig-002-20250315    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From jic23 at kernel.org  Sat Mar 15 11:28:06 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 15 Mar 2025 18:28:06 +0000
Subject: [PATCH v6 00/10] Support ROHM BD79124 ADC
In-Reply-To: <e685d31c-8cdc-4732-b3a8-8e70a6f82578@gmail.com>
References: <cover.1741610847.git.mazziesaccount@gmail.com>
	<20250310202738.13301548@jic23-huawei>
	<e685d31c-8cdc-4732-b3a8-8e70a6f82578@gmail.com>
Message-ID: <20250315182806.653bd71c@jic23-huawei>

On Tue, 11 Mar 2025 07:49:35 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> On 10/03/2025 22:27, Jonathan Cameron wrote:
> > On Mon, 10 Mar 2025 14:53:50 +0200
> > Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> >   
> >> Support ROHM BD79124 ADC.
> >>
> >> This series adds also couple of IIO ADC helper functions for parsing the
> >> channel information from the device tree. There are also new helpers
> >> included for iterating and counting firmware child nodes with a specific
> >> name.
> >>
> >> Series does also convert couple of drivers to use these helpers. The
> >> rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.
> >>
> >> The gianfar driver under net and the thp7312 under media/i2c are added as
> >> first users of the newly added "named child node" -helpers.
> >>
> >> There has been some discussion about how useful these ADC helpers are,
> >> and whether they should support also differential and single ended channel
> >> configurations. This version does not include support for those - with the
> >> benefit of reduced complexity and easier to use API.
> >>
> >> NOTE: Patches 4,5,9 and 10 are untested as I lack of relevant HW.
> >> They have been compile tested only.  
> > This probably wants an update.  Also, 00/10? There are only 8 that I can see.  
> 
> That's odd.
> There should be 10 in total. And the 4, 5, 9 and 10 was updated.
> 
> 9/10:
> https://lore.kernel.org/all/1c4b9b4ceb1995bce76a0ddef0e04ad0d1d81190.1741610847.git.mazziesaccount at gmail.com/
> 
> 10/10:
> https://lore.kernel.org/all/ab79cf4415d21ff2854fee4f4189fac555c30b7a.1741610847.git.mazziesaccount at gmail.com/
> 
> Perhaps it's because of the "net-next" in subject?
> 
Nope. My filters broke the series up into different directories.

Thanks,

Jonathan

> Yours,
> 	-- Matti



From jic23 at kernel.org  Sat Mar 15 11:40:28 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sat, 15 Mar 2025 18:40:28 +0000
Subject: [PATCH] iio: adc: rockchip: Fix clock initialization sequence
In-Reply-To: <10623626.nUPlyArG6x@phil>
References: <20250312062016.137821-1-xxm@rock-chips.com>
	<10623626.nUPlyArG6x@phil>
Message-ID: <20250315184028.46053659@jic23-huawei>

On Wed, 12 Mar 2025 08:00:54 +0100
Heiko Stuebner <heiko at sntech.de> wrote:

> Am Mittwoch, 12. M?rz 2025, 07:20:16 MEZ schrieb Simon Xue:
> > clock_set_rate should be executed after devm_clk_get_enabled.
> > 
> > Fixes: 97ad10bb2901 ("iio: adc: rockchip_saradc: Make use of devm_clk_get_enabled")
> > Signed-off-by: Simon Xue <xxm at rock-chips.com>  
> 
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
ouch.

Applied and marked for stable.

Thanks,

Jonathan

> 
> > ---
> >  drivers/iio/adc/rockchip_saradc.c | 17 ++++++++---------
> >  1 file changed, 8 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
> > index a29e54754c8f..ab4de67fb135 100644
> > --- a/drivers/iio/adc/rockchip_saradc.c
> > +++ b/drivers/iio/adc/rockchip_saradc.c
> > @@ -480,15 +480,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
> >  	if (info->reset)
> >  		rockchip_saradc_reset_controller(info->reset);
> >  
> > -	/*
> > -	 * Use a default value for the converter clock.
> > -	 * This may become user-configurable in the future.
> > -	 */
> > -	ret = clk_set_rate(info->clk, info->data->clk_rate);
> > -	if (ret < 0)
> > -		return dev_err_probe(&pdev->dev, ret,
> > -				     "failed to set adc clk rate\n");
> > -
> >  	ret = regulator_enable(info->vref);
> >  	if (ret < 0)
> >  		return dev_err_probe(&pdev->dev, ret,
> > @@ -515,6 +506,14 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
> >  	if (IS_ERR(info->clk))
> >  		return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
> >  				     "failed to get adc clock\n");
> > +	/*
> > +	 * Use a default value for the converter clock.
> > +	 * This may become user-configurable in the future.
> > +	 */
> > +	ret = clk_set_rate(info->clk, info->data->clk_rate);
> > +	if (ret < 0)
> > +		return dev_err_probe(&pdev->dev, ret,
> > +				     "failed to set adc clk rate\n");
> >  
> >  	platform_set_drvdata(pdev, indio_dev);
> >  
> >   
> 
> 
> 
> 



From helgaas at kernel.org  Sat Mar 15 11:49:03 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 13:49:03 -0500
Subject: [PATCH hyperv-next v6 11/11] PCI: hv: Get vPCI MSI IRQ domain
 from DeviceTree
In-Reply-To: <20250315001931.631210-12-romank@linux.microsoft.com>
Message-ID: <20250315184903.GA848938@bhelgaas>

On Fri, Mar 14, 2025 at 05:19:31PM -0700, Roman Kisel wrote:
> The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
> arm64. It won't be able to do that in the VTL mode where only DeviceTree
> can be used.
> 
> Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
> case, too.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>

Acked-by: Bjorn Helgaas <bhelgaas at google.com>

Looks good to me; trivial whitespace comment below.

> ---
>  drivers/pci/controller/pci-hyperv.c | 73 ++++++++++++++++++++++++++---
>  1 file changed, 67 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
> index 6084b38bdda1..cbff19e8a07c 100644
> --- a/drivers/pci/controller/pci-hyperv.c
> +++ b/drivers/pci/controller/pci-hyperv.c
> @@ -50,6 +50,7 @@
>  #include <linux/irqdomain.h>
>  #include <linux/acpi.h>
>  #include <linux/sizes.h>
> +#include <linux/of_irq.h>
>  #include <asm/mshyperv.h>
>  
>  /*
> @@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
>  	int ret;
>  
>  	fwspec.fwnode = domain->parent->fwnode;
> -	fwspec.param_count = 2;
> -	fwspec.param[0] = hwirq;
> -	fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +	if (is_of_node(fwspec.fwnode)) {
> +		/* SPI lines for OF translations start at offset 32 */
> +		fwspec.param_count = 3;
> +		fwspec.param[0] = 0;
> +		fwspec.param[1] = hwirq - 32;
> +		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> +	} else {
> +		fwspec.param_count = 2;
> +		fwspec.param[0] = hwirq;
> +		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +	}
>  
>  	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
>  	if (ret)
> @@ -887,10 +896,47 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
>  	.activate = hv_pci_vec_irq_domain_activate,
>  };
>  
> +#ifdef CONFIG_OF
> +
> +static struct irq_domain *hv_pci_of_irq_domain_parent(void)
> +{
> +	struct device_node *parent;
> +	struct irq_domain *domain;
> +
> +	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
> +	if (!parent)
> +		return NULL;
> +	domain = irq_find_host(parent);
> +	of_node_put(parent);
> +
> +	return domain;
> +}
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +
> +static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
> +{
> +	struct irq_domain *domain;
> +	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
> +
> +	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
> +		return NULL;
> +	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
> +	if (!gsi_domain_disp_fn)
> +		return NULL;
> +	return irq_find_matching_fwnode(gsi_domain_disp_fn(0),
> +				     DOMAIN_BUS_ANY);
> +}
> +
> +#endif
> +
>  static int hv_pci_irqchip_init(void)
>  {
>  	static struct hv_pci_chip_data *chip_data;
>  	struct fwnode_handle *fn = NULL;
> +	struct irq_domain *irq_domain_parent = NULL;
>  	int ret = -ENOMEM;
>  
>  	chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
> @@ -907,9 +953,24 @@ static int hv_pci_irqchip_init(void)
>  	 * way to ensure that all the corresponding devices are also gone and
>  	 * no interrupts will be generated.
>  	 */
> -	hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
> -							  fn, &hv_pci_domain_ops,
> -							  chip_data);
> +#ifdef CONFIG_ACPI
> +	if (!acpi_disabled)
> +		irq_domain_parent = hv_pci_acpi_irq_domain_parent();
> +#endif
> +#if defined(CONFIG_OF)
> +	if (!irq_domain_parent)
> +		irq_domain_parent = hv_pci_of_irq_domain_parent();
> +#endif
> +	if (!irq_domain_parent) {
> +		WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
> +		ret = -EINVAL;
> +		goto free_chip;
> +	}
> +
> +	hv_msi_gic_irq_domain = irq_domain_create_hierarchy(
> +		irq_domain_parent, 0, HV_PCI_MSI_SPI_NR,
> +		fn, &hv_pci_domain_ops,
> +		chip_data);

This is a different style of indenting the parameters than other
similar cases in this file, which line up parameters on subsequent
lines under the open parenthesis.

>  	if (!hv_msi_gic_irq_domain) {
>  		pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
> -- 
> 2.43.0
> 


From lkp at intel.com  Sat Mar 15 12:41:53 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 16 Mar 2025 03:41:53 +0800
Subject: [PATCH v3 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250310114839.3098148-4-kevin_chen@aspeedtech.com>
References: <20250310114839.3098148-4-kevin_chen@aspeedtech.com>
Message-ID: <202503160530.EkUNSrkh-lkp@intel.com>

Hi Kevin,

kernel test robot noticed the following build errors:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on char-misc/char-misc-next char-misc/char-misc-linus lee-leds/for-leds-next lee-mfd/for-mfd-next robh/for-next lee-mfd/for-mfd-fixes linus/master v6.14-rc6 next-20250314]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kevin-Chen/dt-binding-aspeed-Add-LPC-PCC-controller/20250310-195011
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250310114839.3098148-4-kevin_chen%40aspeedtech.com
patch subject: [PATCH v3 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
config: s390-randconfig-002-20250316 (https://download.01.org/0day-ci/archive/20250316/202503160530.EkUNSrkh-lkp at intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250316/202503160530.EkUNSrkh-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503160530.EkUNSrkh-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/mfd/syscon.c:157:2: error: call to undeclared function 'iounmap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
           iounmap(base);
           ^
   arch/s390/include/asm/io.h:31:17: note: expanded from macro 'iounmap'
   #define iounmap iounmap
                   ^
   1 error generated.

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for MFD_SYSCON
   Depends on [n]: HAS_IOMEM [=n]
   Selected by [y]:
   - ASPEED_LPC_PCC [=y]


vim +/iounmap +157 drivers/mfd/syscon.c

87d687301f38072 Dong Aisheng        2012-09-05   39  
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05   40  static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
87d687301f38072 Dong Aisheng        2012-09-05   41  {
a00406b71c5f08f Fabrice Gasnier     2018-12-12   42  	struct clk *clk;
bdb0066df96e74a Pankaj Dubey        2014-09-30   43  	struct regmap *regmap;
bdb0066df96e74a Pankaj Dubey        2014-09-30   44  	void __iomem *base;
db2fb60cd35d2d0 Damien Riegel       2015-11-30   45  	u32 reg_io_width;
bdb0066df96e74a Pankaj Dubey        2014-09-30   46  	int ret;
bdb0066df96e74a Pankaj Dubey        2014-09-30   47  	struct regmap_config syscon_config = syscon_regmap_config;
ca668f0edfae654 Philipp Zabel       2016-01-29   48  	struct resource res;
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05   49  	struct reset_control *reset;
bdb0066df96e74a Pankaj Dubey        2014-09-30   50  
805f7aaf7fee14a Rob Herring (Arm    2024-12-17   51) 	WARN_ON(!mutex_is_locked(&syscon_list_lock));
805f7aaf7fee14a Rob Herring (Arm    2024-12-17   52) 
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07   53  	struct syscon *syscon __free(kfree) = kzalloc(sizeof(*syscon), GFP_KERNEL);
bdb0066df96e74a Pankaj Dubey        2014-09-30   54  	if (!syscon)
bdb0066df96e74a Pankaj Dubey        2014-09-30   55  		return ERR_PTR(-ENOMEM);
bdb0066df96e74a Pankaj Dubey        2014-09-30   56  
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07   57  	if (of_address_to_resource(np, 0, &res))
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07   58  		return ERR_PTR(-ENOMEM);
ca668f0edfae654 Philipp Zabel       2016-01-29   59  
452d07413954ef3 Hector Martin       2021-08-23   60  	base = of_iomap(np, 0);
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07   61  	if (!base)
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07   62  		return ERR_PTR(-ENOMEM);
bdb0066df96e74a Pankaj Dubey        2014-09-30   63  
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   64  	/* Parse the device's DT node for an endianness specification */
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   65  	if (of_property_read_bool(np, "big-endian"))
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   66  		syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   67  	else if (of_property_read_bool(np, "little-endian"))
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   68  		syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   69  	else if (of_property_read_bool(np, "native-endian"))
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   70  		syscon_config.val_format_endian = REGMAP_ENDIAN_NATIVE;
ca4582c286aa446 Jason A. Donenfeld  2022-10-08   71  
db2fb60cd35d2d0 Damien Riegel       2015-11-30   72  	/*
db2fb60cd35d2d0 Damien Riegel       2015-11-30   73  	 * search for reg-io-width property in DT. If it is not provided,
db2fb60cd35d2d0 Damien Riegel       2015-11-30   74  	 * default to 4 bytes. regmap_init_mmio will return an error if values
db2fb60cd35d2d0 Damien Riegel       2015-11-30   75  	 * are invalid so there is no need to check them here.
db2fb60cd35d2d0 Damien Riegel       2015-11-30   76  	 */
db2fb60cd35d2d0 Damien Riegel       2015-11-30   77  	ret = of_property_read_u32(np, "reg-io-width", &reg_io_width);
db2fb60cd35d2d0 Damien Riegel       2015-11-30   78  	if (ret)
db2fb60cd35d2d0 Damien Riegel       2015-11-30   79  		reg_io_width = 4;
db2fb60cd35d2d0 Damien Riegel       2015-11-30   80  
3bafc09e779710a Baolin Wang         2017-12-25   81  	ret = of_hwspin_lock_get_id(np, 0);
3bafc09e779710a Baolin Wang         2017-12-25   82  	if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
3bafc09e779710a Baolin Wang         2017-12-25   83  		syscon_config.use_hwlock = true;
3bafc09e779710a Baolin Wang         2017-12-25   84  		syscon_config.hwlock_id = ret;
3bafc09e779710a Baolin Wang         2017-12-25   85  		syscon_config.hwlock_mode = HWLOCK_IRQSTATE;
3bafc09e779710a Baolin Wang         2017-12-25   86  	} else if (ret < 0) {
3bafc09e779710a Baolin Wang         2017-12-25   87  		switch (ret) {
3bafc09e779710a Baolin Wang         2017-12-25   88  		case -ENOENT:
3bafc09e779710a Baolin Wang         2017-12-25   89  			/* Ignore missing hwlock, it's optional. */
3bafc09e779710a Baolin Wang         2017-12-25   90  			break;
3bafc09e779710a Baolin Wang         2017-12-25   91  		default:
3bafc09e779710a Baolin Wang         2017-12-25   92  			pr_err("Failed to retrieve valid hwlock: %d\n", ret);
df561f6688fef77 Gustavo A. R. Silva 2020-08-23   93  			fallthrough;
3bafc09e779710a Baolin Wang         2017-12-25   94  		case -EPROBE_DEFER:
3bafc09e779710a Baolin Wang         2017-12-25   95  			goto err_regmap;
3bafc09e779710a Baolin Wang         2017-12-25   96  		}
3bafc09e779710a Baolin Wang         2017-12-25   97  	}
3bafc09e779710a Baolin Wang         2017-12-25   98  
7ff7d5ffb7259f7 Andy Shevchenko     2022-05-31   99  	syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@%pa", np, &res.start);
41673c66b3d0c09 Kunwu Chan          2023-12-04  100  	if (!syscon_config.name) {
41673c66b3d0c09 Kunwu Chan          2023-12-04  101  		ret = -ENOMEM;
41673c66b3d0c09 Kunwu Chan          2023-12-04  102  		goto err_regmap;
41673c66b3d0c09 Kunwu Chan          2023-12-04  103  	}
db2fb60cd35d2d0 Damien Riegel       2015-11-30  104  	syscon_config.reg_stride = reg_io_width;
db2fb60cd35d2d0 Damien Riegel       2015-11-30  105  	syscon_config.val_bits = reg_io_width * 8;
ca668f0edfae654 Philipp Zabel       2016-01-29  106  	syscon_config.max_register = resource_size(&res) - reg_io_width;
2e63d6fa113d362 Nishanth Menon      2024-09-03  107  	if (!syscon_config.max_register)
2e63d6fa113d362 Nishanth Menon      2024-09-03  108  		syscon_config.max_register_is_0 = true;
db2fb60cd35d2d0 Damien Riegel       2015-11-30  109  
bdb0066df96e74a Pankaj Dubey        2014-09-30  110  	regmap = regmap_init_mmio(NULL, base, &syscon_config);
56a1188159cb2b8 Limeng              2021-04-07  111  	kfree(syscon_config.name);
bdb0066df96e74a Pankaj Dubey        2014-09-30  112  	if (IS_ERR(regmap)) {
bdb0066df96e74a Pankaj Dubey        2014-09-30  113  		pr_err("regmap init failed\n");
bdb0066df96e74a Pankaj Dubey        2014-09-30  114  		ret = PTR_ERR(regmap);
bdb0066df96e74a Pankaj Dubey        2014-09-30  115  		goto err_regmap;
bdb0066df96e74a Pankaj Dubey        2014-09-30  116  	}
bdb0066df96e74a Pankaj Dubey        2014-09-30  117  
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  118  	if (check_res) {
a00406b71c5f08f Fabrice Gasnier     2018-12-12  119  		clk = of_clk_get(np, 0);
a00406b71c5f08f Fabrice Gasnier     2018-12-12  120  		if (IS_ERR(clk)) {
a00406b71c5f08f Fabrice Gasnier     2018-12-12  121  			ret = PTR_ERR(clk);
a00406b71c5f08f Fabrice Gasnier     2018-12-12  122  			/* clock is optional */
a00406b71c5f08f Fabrice Gasnier     2018-12-12  123  			if (ret != -ENOENT)
a00406b71c5f08f Fabrice Gasnier     2018-12-12  124  				goto err_clk;
a00406b71c5f08f Fabrice Gasnier     2018-12-12  125  		} else {
a00406b71c5f08f Fabrice Gasnier     2018-12-12  126  			ret = regmap_mmio_attach_clk(regmap, clk);
a00406b71c5f08f Fabrice Gasnier     2018-12-12  127  			if (ret)
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  128  				goto err_attach_clk;
a00406b71c5f08f Fabrice Gasnier     2018-12-12  129  		}
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  130  
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  131  		reset = of_reset_control_get_optional_exclusive(np, NULL);
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  132  		if (IS_ERR(reset)) {
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  133  			ret = PTR_ERR(reset);
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  134  			goto err_attach_clk;
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  135  		}
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  136  
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  137  		ret = reset_control_deassert(reset);
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  138  		if (ret)
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  139  			goto err_reset;
39233b7c611248c Paul Cercueil       2019-07-24  140  	}
a00406b71c5f08f Fabrice Gasnier     2018-12-12  141  
bdb0066df96e74a Pankaj Dubey        2014-09-30  142  	syscon->regmap = regmap;
bdb0066df96e74a Pankaj Dubey        2014-09-30  143  	syscon->np = np;
bdb0066df96e74a Pankaj Dubey        2014-09-30  144  
bdb0066df96e74a Pankaj Dubey        2014-09-30  145  	list_add_tail(&syscon->list, &syscon_list);
87d687301f38072 Dong Aisheng        2012-09-05  146  
82f898f47112bc7 Krzysztof Kozlowski 2024-07-07  147  	return_ptr(syscon);
bdb0066df96e74a Pankaj Dubey        2014-09-30  148  
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  149  err_reset:
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  150  	reset_control_put(reset);
7d1e3bd94828ad9 Jeremy Kerr         2023-01-05  151  err_attach_clk:
a00406b71c5f08f Fabrice Gasnier     2018-12-12  152  	if (!IS_ERR(clk))
a00406b71c5f08f Fabrice Gasnier     2018-12-12  153  		clk_put(clk);
a00406b71c5f08f Fabrice Gasnier     2018-12-12  154  err_clk:
a00406b71c5f08f Fabrice Gasnier     2018-12-12  155  	regmap_exit(regmap);
bdb0066df96e74a Pankaj Dubey        2014-09-30  156  err_regmap:
bdb0066df96e74a Pankaj Dubey        2014-09-30 @157  	iounmap(base);
bdb0066df96e74a Pankaj Dubey        2014-09-30  158  	return ERR_PTR(ret);
87d687301f38072 Dong Aisheng        2012-09-05  159  }
87d687301f38072 Dong Aisheng        2012-09-05  160  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From helgaas at kernel.org  Sat Mar 15 13:15:40 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:40 -0500
Subject: [PATCH v12 05/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-6-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

Return the offset from CPU physical address to the parent bus address of
the specified element of the devicetree 'reg' property.

[bhelgaas: return offset, split .cpu_addr_fixup() checking and debug to
separate patch]
Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware.c | 23 ++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 9d0a5f75effc..0a35e36da703 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -16,6 +16,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 #include <linux/types.h>
@@ -1105,3 +1106,25 @@ void dw_pcie_setup(struct dw_pcie *pci)
 
 	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
 }
+
+resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
+					  const char *reg_name,
+					  resource_size_t cpu_phy_addr)
+{
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	int index;
+	u64 reg_addr;
+
+	/* Look up reg_name address on parent bus */
+	index = of_property_match_string(np, "reg-names", reg_name);
+
+	if (index < 0) {
+		dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
+		return 0;
+	}
+
+	of_property_read_reg(np, index, &reg_addr, NULL);
+
+	return cpu_phy_addr - reg_addr;
+}
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index d0d8c622a6e8..16548b01347d 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -500,6 +500,9 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
+resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
+					  const char *reg_name,
+					  resource_size_t cpu_phy_addr);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:41 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:41 -0500
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-7-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
is a hard-coded way to get the parent bus address corresponding to a CPU
physical address.

Add debug code to compare the address from .cpu_addr_fixup() with the
address from devicetree.  If they match, warn that .cpu_addr_fixup() is
redundant and should be removed; if they differ, warn that something is
wrong with the devicetree.

If .cpu_addr_fixup() is not implemented, the parent bus address should be
identical to the CPU physical address because we previously ignored the
parent bus address from devicetree.  If the devicetree has a different
parent bus address, warn about it being broken.

[bhelgaas: split debug to separate patch for easier future revert, commit
log]
Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware.c | 26 +++++++++++++++++++-
 drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 0a35e36da703..985264c88b92 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
 	int index;
-	u64 reg_addr;
+	u64 reg_addr, fixup_addr;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
 
 	/* Look up reg_name address on parent bus */
 	index = of_property_match_string(np, "reg-names", reg_name);
@@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
 
 	of_property_read_reg(np, index, &reg_addr, NULL);
 
+	fixup = pci->ops->cpu_addr_fixup;
+	if (fixup) {
+		fixup_addr = fixup(pci, cpu_phy_addr);
+		if (reg_addr == fixup_addr) {
+			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
+				 cpu_phy_addr, reg_name, index,
+				 fixup_addr, fixup);
+		} else {
+			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
+				 cpu_phy_addr, reg_name,
+				 index, fixup_addr);
+			reg_addr = fixup_addr;
+		}
+	} else if (!pci->use_parent_dt_ranges) {
+		if (reg_addr != cpu_phy_addr) {
+			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
+				 cpu_phy_addr, reg_addr);
+			return 0;
+		}
+	}
+
+	dev_info(dev, "%s parent bus offset is %#010llx\n",
+		 reg_name, cpu_phy_addr - reg_addr);
 	return cpu_phy_addr - reg_addr;
 }
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 16548b01347d..f08d2852cfd5 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -465,6 +465,19 @@ struct dw_pcie {
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
 	bool			suspended;
+
+	/*
+	 * If iATU input addresses are offset from CPU physical addresses,
+	 * we previously required .cpu_addr_fixup() to convert them.  We
+	 * now rely on the devicetree instead.  If .cpu_addr_fixup()
+	 * exists, we compare its results with devicetree.
+	 *
+	 * If .cpu_addr_fixup() does not exist, we assume the offset is
+	 * zero and warn if devicetree claims otherwise.  If we know all
+	 * devicetrees correctly describe the offset, set
+	 * use_parent_dt_ranges to true to avoid this warning.
+	 */
+	bool			use_parent_dt_ranges;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:42 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:42 -0500
Subject: [PATCH v12 07/13] PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr offset
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-8-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

The 'ranges' property of a PCI controller's parent can indicate address
translation information. Most system use 1:1 map between CPU physical and
PCI controller input addresses.

But some hardware, like i.MX8QXP, doesn't use 1:1 map.  See below diagram:

              ???????????                    ??????????????
   ???????    ?         ? IA: 0x8ff8_0000    ?            ?
   ? CPU ??????   ?????????????????????????  ? PCI        ?
   ???????    ?   ?     ? IA: 0x8ff0_0000 ?  ?            ?
    CPU Addr  ?   ?  ??????????????????   ?  ? Controller ?
  0x7ff8_0000??????  ?  ?             ?   ?  ?            ?
              ?      ?  ?             ?   ?  ?            ?   PCI Addr
  0x7ff0_0000?????????  ?             ?   ???? IOSpace   ???????????????
              ?         ?             ?      ?            ?    0
  0x7000_0000??????????????????????   ?      ?            ?
              ???????????         ?   ???????? CfgSpace  ???????????????
               Bus Fabric         ?          ?            ?    0
                                  ?          ?            ?
                                  ???????????? MemSpace  ???????????????
                          IA: 0x8000_0000    ?            ?  0x8000_0000
                                             ??????????????

  bus at 5f000000 {
          compatible = "simple-bus";
          #address-cells = <1>;
          #size-cells = <1>;
          ranges = <0x80000000 0x0 0x70000000 0x10000000>;

          pcie at 5f010000 {
                  compatible = "fsl,imx8q-pcie";
                  reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
                  reg-names = "dbi", "config";
                  ...
          };
  };

Intermediate address (IA) here means the PCIe controller input address.
The pcie at 5f010000 'reg[config]' address is the parent bus (PCIe controller
input) address of CfgSpace.

The ATU in MemSpace is not explicitly described via devicetree, so we
assume the offset from CPU address to intermediate MemSpace address is the
same as that for CfgSpace.

We could use bus at 5f000000 'ranges' for the same purpose.

Set parent_bus_offset using dw_pcie_init_parent_bus_offset().  The
parent_bus_offset is not used yet, so no functional change intended.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-6-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 6 ++++++
 drivers/pci/controller/dwc/pcie-designware.h      | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 9ce06b1ee266..9e38ac7d1bcb 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -452,6 +452,12 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
 		pp->io_base = pci_pio_to_address(win->res->start);
 	}
 
+	/*
+	 * visconti_pcie_cpu_addr_fixup() uses pp->io_base, so we have to
+	 * call dw_pcie_parent_bus_offset() after setting pp->io_base.
+	 */
+	pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "config",
+							   pp->cfg0_base);
 	return 0;
 }
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index f08d2852cfd5..741c46926ce2 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -445,6 +445,7 @@ struct dw_pcie {
 	void __iomem		*atu_base;
 	resource_size_t		atu_phys_addr;
 	size_t			atu_size;
+	resource_size_t		parent_bus_offset;
 	u32			num_ib_windows;
 	u32			num_ob_windows;
 	u32			region_align;
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:43 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:43 -0500
Subject: [PATCH v12 08/13] PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-9-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

Move devm_pci_epc_create() to the beginning of dw_pcie_ep_init().

devm_pci_epc_create() is generic code that doesn't depend on any DWC
resource, so moving it earlier keeps all the subsequent devicetree-related
code together.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 .../pci/controller/dwc/pcie-designware-ep.c    | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 80ac2f9e88eb..100d26466f05 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -904,6 +904,15 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 
 	INIT_LIST_HEAD(&ep->func_list);
 
+	epc = devm_pci_epc_create(dev, &epc_ops);
+	if (IS_ERR(epc)) {
+		dev_err(dev, "Failed to create epc device\n");
+		return PTR_ERR(epc);
+	}
+
+	ep->epc = epc;
+	epc_set_drvdata(epc, ep);
+
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
 		return ret;
@@ -918,15 +927,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	if (ep->ops->pre_init)
 		ep->ops->pre_init(ep);
 
-	epc = devm_pci_epc_create(dev, &epc_ops);
-	if (IS_ERR(epc)) {
-		dev_err(dev, "Failed to create epc device\n");
-		return PTR_ERR(epc);
-	}
-
-	ep->epc = epc;
-	epc_set_drvdata(epc, ep);
-
 	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
 	if (ret < 0)
 		epc->max_functions = 1;
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:44 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:44 -0500
Subject: [PATCH v12 09/13] PCI: dwc: ep: Consolidate devicetree handling in dw_pcie_ep_get_resources()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-10-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

Consolidate devicetree resource handling in dw_pcie_ep_get_resources().
No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 .../pci/controller/dwc/pcie-designware-ep.c   | 68 +++++++++++--------
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 100d26466f05..2db834345ec2 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -883,35 +883,15 @@ void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_linkdown);
 
-/**
- * dw_pcie_ep_init - Initialize the endpoint device
- * @ep: DWC EP device
- *
- * Initialize the endpoint device. Allocate resources and create the EPC
- * device with the endpoint framework.
- *
- * Return: 0 if success, errno otherwise.
- */
-int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
 {
-	int ret;
-	struct resource *res;
-	struct pci_epc *epc;
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 	struct device *dev = pci->dev;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct device_node *np = dev->of_node;
-
-	INIT_LIST_HEAD(&ep->func_list);
-
-	epc = devm_pci_epc_create(dev, &epc_ops);
-	if (IS_ERR(epc)) {
-		dev_err(dev, "Failed to create epc device\n");
-		return PTR_ERR(epc);
-	}
-
-	ep->epc = epc;
-	epc_set_drvdata(epc, ep);
+	struct pci_epc *epc = ep->epc;
+	struct resource *res;
+	int ret;
 
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
@@ -924,13 +904,47 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->phys_base = res->start;
 	ep->addr_size = resource_size(res);
 
-	if (ep->ops->pre_init)
-		ep->ops->pre_init(ep);
-
 	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
 	if (ret < 0)
 		epc->max_functions = 1;
 
+	return 0;
+}
+
+/**
+ * dw_pcie_ep_init - Initialize the endpoint device
+ * @ep: DWC EP device
+ *
+ * Initialize the endpoint device. Allocate resources and create the EPC
+ * device with the endpoint framework.
+ *
+ * Return: 0 if success, errno otherwise.
+ */
+int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+	int ret;
+	struct pci_epc *epc;
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	struct device *dev = pci->dev;
+
+	INIT_LIST_HEAD(&ep->func_list);
+
+	epc = devm_pci_epc_create(dev, &epc_ops);
+	if (IS_ERR(epc)) {
+		dev_err(dev, "Failed to create epc device\n");
+		return PTR_ERR(epc);
+	}
+
+	ep->epc = epc;
+	epc_set_drvdata(epc, ep);
+
+	ret = dw_pcie_ep_get_resources(ep);
+	if (ret)
+		return ret;
+
+	if (ep->ops->pre_init)
+		ep->ops->pre_init(ep);
+
 	ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
 			       ep->page_size);
 	if (ret < 0) {
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:45 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:45 -0500
Subject: [PATCH v12 10/13] PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU addr offset
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-11-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

                   Endpoint
  ?????????????????????????????????????????????????
  ?                             pcie-ep at 5f010000  ?
  ?                             ???????????????????
  ?                             ?   Endpoint     ??
  ?                             ?   PCIe         ??
  ?                             ?   Controller   ??
  ?           bus at 5f000000      ?             ??????????
  ?           ????????????      ?             ?  ??dynamically
  ?           ?          ? Outbound Transfer  ?  ??allocated
  ????????    ?  Bus     ???????? ATU  ????????  ??PCI Addr
  ??     ?    ?  Fabric  ?Bus   ?                ??
  ?? CPU ??????          ?Addr  ?                ??
  ??     ?CPU ?          ?0x8000_0000            ??
  ????????Addr????????????      ?                ??
  ?       0x7000_0000           ???????????????????
  ?????????????????????????????????????????????????

  bus at 5f000000 {
          compatible = "simple-bus";
          ranges = <0x80000000 0x0 0x70000000 0x10000000>;

          pcie-ep at 5f010000 {
                  reg = <0x80000000 0x10000000>;
                  reg-names ="addr_space";
                  ...
          };
          ...
  };

In the diagram above, CPU writes data to outbound window address
0x7000_0000, and the bus fabric maps it to 0x8000_0000. The ATU uses
bus address 0x8000_0000 as input address and maps to some PCI address
dynamically allocated by a PCI device driver on the host side.

The pcie-ep at 5f010000 'reg[addr_space]' is the parent bus address of the
PCIe controller input, including the ATU.

Set parent_bus_offset, the offset from the CPU address to the PCIe
controller input address using dw_pcie_init_parent_bus_offset().  The
parent_bus_offset is not used yet, so no functional change intended.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-7-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
[bhelgaas: commit log]
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 2db834345ec2..bb87d0c5c665 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -904,6 +904,13 @@ static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
 	ep->phys_base = res->start;
 	ep->addr_size = resource_size(res);
 
+	/*
+	 * artpec6_pcie_cpu_addr_fixup() uses ep->phys_base, so call
+	 * dw_pcie_parent_bus_offset() after setting ep->phys_base.
+	 */
+	pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "addr_space",
+							   ep->phys_base);
+
 	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
 	if (ret < 0)
 		epc->max_functions = 1;
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:46 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:46 -0500
Subject: [PATCH v12 11/13] PCI: dwc: ep: Ensure proper iteration over outbound map windows
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-12-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

Most systems' PCIe outbound map windows have non-zero physical addresses,
but the possibility of encountering zero increased after following commit
("PCI: dwc: Use parent_bus_offset").

'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
some hardware, which trims high address bits through bus fabric before
sending to the PCIe controller.

Replace the iteration logic with 'for_each_set_bit()' to ensure only
allocated map windows are iterated when determining the ATU index from a
given address.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-8-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index bb87d0c5c665..2ef9964fa080 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
 	u32 index;
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	for (index = 0; index < pci->num_ob_windows; index++) {
+	for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
 		if (ep->outbound_addr[index] != addr)
 			continue;
 		*atu_index = index;
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:47 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:47 -0500
Subject: [PATCH v12 12/13] PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-13-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

We know the parent_bus_offset, either computed from a DT reg property (the
offset is the CPU physical addr - the 'config'/'addr_space' address on the
parent bus) or from a .cpu_addr_fixup() (which may have used a host bridge
window offset).

Apply that parent_bus_offset instead of calling .cpu_addr_fixup() when
programming the ATU.

This assumes all intermediate addresses are at the same offset from the CPU
physical addresses.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-9-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
[bhelgaas: commit log]
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  5 +++--
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 drivers/pci/controller/dwc/pcie-designware.c      |  3 ---
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 2ef9964fa080..c1feaadb046a 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -314,7 +314,8 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
-	ret = dw_pcie_find_index(ep, addr, &atu_index);
+	ret = dw_pcie_find_index(ep, addr - pci->parent_bus_offset,
+				 &atu_index);
 	if (ret < 0)
 		return;
 
@@ -333,7 +334,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.parent_bus_addr = addr;
+	atu.parent_bus_addr = addr - pci->parent_bus_offset;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 9e38ac7d1bcb..d760abcbb785 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -635,7 +635,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.parent_bus_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base - pci->parent_bus_offset;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -660,7 +660,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -686,7 +686,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.parent_bus_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -755,7 +755,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.parent_bus_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -777,7 +777,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.parent_bus_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -921,7 +921,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.parent_bus_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 985264c88b92..d9d2090f380c 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -475,9 +475,6 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 	u32 retries, val;
 	u64 limit_addr;
 
-	if (pci->ops && pci->ops->cpu_addr_fixup)
-		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
-
 	limit_addr = parent_bus_addr + atu->size - 1;
 
 	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:35 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:35 -0500
Subject: [PATCH v12 00/13] PCI: Use device bus range info to cleanup RC Host/EP pci_fixup_addr()
Message-ID: <20250315201548.858189-1-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

This is a v12 based on Frank's v11 series.

v11 https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-0-01d2313502ab at nxp.com
    
Changes from v11:
  - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init(), before
    any devicetree-related code
  - Call devm_pci_epc_create() early in dw_pcie_ep_init(), before any
    devicetree-related code
  - Consolidate devicetree-related code in dw_pcie_host_get_resources() and
    dw_pcie_ep_get_resources()
  - Integrate dw_pcie_cfg0_setup() into dw_pcie_host_get_resources()
  - Convert dw_pcie_init_parent_bus_offset() to dw_pcie_parent_bus_offset()
    which returns the offset rather than setting it internally
  - Split the debug comparison of devicetree info with .cpu_addr_fixup() to
    separate patch so we can easily revert it later
  - Drop "cpu_addr_fixup() usage detected" warning since we always warn
    about something in that case anyway

Any comments welcome.


Bjorn Helgaas (3):
  PCI: dwc: Consolidate devicetree handling in
    dw_pcie_host_get_resources()
  PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init()
  PCI: dwc: ep: Consolidate devicetree handling in
    dw_pcie_ep_get_resources()

Frank Li (10):
  PCI: dwc: Use resource start as iomap() input in
    dw_pcie_pme_turn_off()
  PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
  PCI: dwc: Call devm_pci_alloc_host_bridge() early in
    dw_pcie_host_init()
  PCI: dwc: Add dw_pcie_parent_bus_offset()
  PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug
  PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr
    offset
  PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU
    addr offset
  PCI: dwc: ep: Ensure proper iteration over outbound map windows
  PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup()
  PCI: imx6: Remove cpu_addr_fixup()

 drivers/pci/controller/dwc/pci-imx6.c         | 18 +---
 .../pci/controller/dwc/pcie-designware-ep.c   | 74 +++++++++++------
 .../pci/controller/dwc/pcie-designware-host.c | 57 ++++++++-----
 drivers/pci/controller/dwc/pcie-designware.c  | 82 ++++++++++++++-----
 drivers/pci/controller/dwc/pcie-designware.h  | 24 +++++-
 5 files changed, 171 insertions(+), 84 deletions(-)

-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:36 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:36 -0500
Subject: [PATCH v12 01/13] PCI: dwc: Use resource start as iomap() input in dw_pcie_pme_turn_off()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-2-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

The msg_res region translates writes into PCIe Message TLPs. Previously we
mapped this region using atu.cpu_addr, the input address programmed into
the ATU.

"cpu_addr" is a misnomer because when a bus fabric translates addresses
between the CPU and the ATU, the ATU input address is different from the
CPU address.  A future patch will rename "cpu_addr" and correct the value
to be the ATU input address instead of the CPU physical address.

Map the msg_res region before writing to it using the msg_res resource
start, a CPU physical address.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-1-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ffaded8f2df7..ae3fd2a5dbf8 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -908,7 +908,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	if (ret)
 		return ret;
 
-	mem = ioremap(atu.cpu_addr, pci->region_align);
+	mem = ioremap(pci->pp.msg_res->start, pci->region_align);
 	if (!mem)
 		return -ENOMEM;
 
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:37 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:37 -0500
Subject: [PATCH v12 02/13] PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-3-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

Rename 'cpu_addr' to 'parent_bus_addr' in the DesignWare ATU configuration.

The ATU translates parent bus addresses to PCI addresses, which are often
the same as CPU addresses but can differ in systems where the bus fabric
translates addresses before passing them to the PCIe controller. This
renaming clarifies the purpose and avoids confusion.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-2-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 .../pci/controller/dwc/pcie-designware-ep.c   |  8 ++---
 .../pci/controller/dwc/pcie-designware-host.c | 12 +++----
 drivers/pci/controller/dwc/pcie-designware.c  | 34 +++++++++----------
 drivers/pci/controller/dwc/pcie-designware.h  |  7 ++--
 4 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 8e07d432e74f..80ac2f9e88eb 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -128,7 +128,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 }
 
 static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
-				  dma_addr_t cpu_addr, enum pci_barno bar,
+				  dma_addr_t parent_bus_addr, enum pci_barno bar,
 				  size_t size)
 {
 	int ret;
@@ -146,7 +146,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
 	}
 
 	ret = dw_pcie_prog_ep_inbound_atu(pci, func_no, free_win, type,
-					  cpu_addr, bar, size);
+					  parent_bus_addr, bar, size);
 	if (ret < 0) {
 		dev_err(pci->dev, "Failed to program IB window\n");
 		return ret;
@@ -181,7 +181,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
 		return ret;
 
 	set_bit(free_win, ep->ob_window_map);
-	ep->outbound_addr[free_win] = atu->cpu_addr;
+	ep->outbound_addr[free_win] = atu->parent_bus_addr;
 
 	return 0;
 }
@@ -333,7 +333,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 
 	atu.func_no = func_no;
 	atu.type = PCIE_ATU_TYPE_MEM;
-	atu.cpu_addr = addr;
+	atu.parent_bus_addr = addr;
 	atu.pci_addr = pci_addr;
 	atu.size = size;
 	ret = dw_pcie_ep_outbound_atu(ep, &atu);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ae3fd2a5dbf8..1206b26bff3f 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -616,7 +616,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
 		type = PCIE_ATU_TYPE_CFG1;
 
 	atu.type = type;
-	atu.cpu_addr = pp->cfg0_base;
+	atu.parent_bus_addr = pp->cfg0_base;
 	atu.pci_addr = busdev;
 	atu.size = pp->cfg0_size;
 
@@ -641,7 +641,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -667,7 +667,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
 
 	if (pp->cfg0_io_shared) {
 		atu.type = PCIE_ATU_TYPE_IO;
-		atu.cpu_addr = pp->io_base;
+		atu.parent_bus_addr = pp->io_base;
 		atu.pci_addr = pp->io_bus_addr;
 		atu.size = pp->io_size;
 
@@ -736,7 +736,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 
 		atu.index = i;
 		atu.type = PCIE_ATU_TYPE_MEM;
-		atu.cpu_addr = entry->res->start;
+		atu.parent_bus_addr = entry->res->start;
 		atu.pci_addr = entry->res->start - entry->offset;
 
 		/* Adjust iATU size if MSG TLP region was allocated before */
@@ -758,7 +758,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
 		if (pci->num_ob_windows > ++i) {
 			atu.index = i;
 			atu.type = PCIE_ATU_TYPE_IO;
-			atu.cpu_addr = pp->io_base;
+			atu.parent_bus_addr = pp->io_base;
 			atu.pci_addr = pp->io_bus_addr;
 			atu.size = pp->io_size;
 
@@ -902,7 +902,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
 	atu.size = resource_size(pci->pp.msg_res);
 	atu.index = pci->pp.msg_atu_index;
 
-	atu.cpu_addr = pci->pp.msg_res->start;
+	atu.parent_bus_addr = pci->pp.msg_res->start;
 
 	ret = dw_pcie_prog_outbound_atu(pci, &atu);
 	if (ret)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 145e7f579072..9d0a5f75effc 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -470,25 +470,25 @@ static inline u32 dw_pcie_enable_ecrc(u32 val)
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu)
 {
-	u64 cpu_addr = atu->cpu_addr;
+	u64 parent_bus_addr = atu->parent_bus_addr;
 	u32 retries, val;
 	u64 limit_addr;
 
 	if (pci->ops && pci->ops->cpu_addr_fixup)
-		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
+		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
 
-	limit_addr = cpu_addr + atu->size - 1;
+	limit_addr = parent_bus_addr + atu->size - 1;
 
-	if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {
 		return -EINVAL;
 	}
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT,
 			      lower_32_bits(limit_addr));
@@ -502,7 +502,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      upper_32_bits(atu->pci_addr));
 
 	val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no);
-	if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&
+	if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
 	    dw_pcie_ver_is_ge(pci, 460A))
 		val |= PCIE_ATU_INCREASE_REGION_SIZE;
 	if (dw_pcie_ver_is(pci, 490A))
@@ -545,13 +545,13 @@ static inline void dw_pcie_writel_atu_ib(struct dw_pcie *pci, u32 index, u32 reg
 }
 
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size)
+			     u64 parent_bus_addr, u64 pci_addr, u64 size)
 {
 	u64 limit_addr = pci_addr + size - 1;
 	u32 retries, val;
 
 	if ((limit_addr & ~pci->region_limit) != (pci_addr & ~pci->region_limit) ||
-	    !IS_ALIGNED(cpu_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, pci->region_align) ||
 	    !IS_ALIGNED(pci_addr, pci->region_align) || !size) {
 		return -EINVAL;
 	}
@@ -568,9 +568,9 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 				      upper_32_bits(limit_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	val = type;
 	if (upper_32_bits(limit_addr) > upper_32_bits(pci_addr) &&
@@ -597,18 +597,18 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
 }
 
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size)
+				int type, u64 parent_bus_addr, u8 bar, size_t size)
 {
 	u32 retries, val;
 
-	if (!IS_ALIGNED(cpu_addr, pci->region_align) ||
-	    !IS_ALIGNED(cpu_addr, size))
+	if (!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
+	    !IS_ALIGNED(parent_bus_addr, size))
 		return -EINVAL;
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET,
-			      lower_32_bits(cpu_addr));
+			      lower_32_bits(parent_bus_addr));
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET,
-			      upper_32_bits(cpu_addr));
+			      upper_32_bits(parent_bus_addr));
 
 	dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, type |
 			      PCIE_ATU_FUNC_NUM(func_no));
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 501d9ddfea16..d0d8c622a6e8 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -343,7 +343,7 @@ struct dw_pcie_ob_atu_cfg {
 	u8 func_no;
 	u8 code;
 	u8 routing;
-	u64 cpu_addr;
+	u64 parent_bus_addr;
 	u64 pci_addr;
 	u64 size;
 };
@@ -491,9 +491,10 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
 int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
 			      const struct dw_pcie_ob_atu_cfg *atu);
 int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
-			     u64 cpu_addr, u64 pci_addr, u64 size);
+			     u64 parent_bus_addr, u64 pci_addr, u64 size);
 int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
-				int type, u64 cpu_addr, u8 bar, size_t size);
+				int type, u64 parent_bus_addr,
+				u8 bar, size_t size);
 void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
 void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:38 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:38 -0500
Subject: [PATCH v12 03/13] PCI: dwc: Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-4-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

Move devm_pci_alloc_host_bridge() to the beginning of dw_pcie_host_init().

devm_pci_alloc_host_bridge() is generic code that doesn't depend on any DWC
resource, so moving it earlier keeps all the subsequent devicetree-related
code together.

[bhelgaas: reorder earlier in series]
Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-4-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 1206b26bff3f..5636243fb90e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -431,6 +431,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 
 	raw_spin_lock_init(&pp->lock);
 
+	bridge = devm_pci_alloc_host_bridge(dev, 0);
+	if (!bridge)
+		return -ENOMEM;
+
+	pp->bridge = bridge;
+
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
 		return ret;
@@ -448,12 +454,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (IS_ERR(pp->va_cfg0_base))
 		return PTR_ERR(pp->va_cfg0_base);
 
-	bridge = devm_pci_alloc_host_bridge(dev, 0);
-	if (!bridge)
-		return -ENOMEM;
-
-	pp->bridge = bridge;
-
 	/* Get the I/O range from DT */
 	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
 	if (win) {
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:39 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:39 -0500
Subject: [PATCH v12 04/13] PCI: dwc: Consolidate devicetree handling in dw_pcie_host_get_resources()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-5-helgaas@kernel.org>

From: Bjorn Helgaas <bhelgaas at google.com>

Consolidate devicetree resource handling in dw_pcie_host_get_resources().
No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
---
 .../pci/controller/dwc/pcie-designware-host.c | 37 +++++++++++++------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 5636243fb90e..9ce06b1ee266 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -418,25 +418,15 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 	}
 }
 
-int dw_pcie_host_init(struct dw_pcie_rp *pp)
+static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
-	struct device_node *np = dev->of_node;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct resource_entry *win;
-	struct pci_host_bridge *bridge;
 	struct resource *res;
 	int ret;
 
-	raw_spin_lock_init(&pp->lock);
-
-	bridge = devm_pci_alloc_host_bridge(dev, 0);
-	if (!bridge)
-		return -ENOMEM;
-
-	pp->bridge = bridge;
-
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
 		return ret;
@@ -455,13 +445,36 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 		return PTR_ERR(pp->va_cfg0_base);
 
 	/* Get the I/O range from DT */
-	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
+	win = resource_list_first_type(&pp->bridge->windows, IORESOURCE_IO);
 	if (win) {
 		pp->io_size = resource_size(win->res);
 		pp->io_bus_addr = win->res->start - win->offset;
 		pp->io_base = pci_pio_to_address(win->res->start);
 	}
 
+	return 0;
+}
+
+int dw_pcie_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	struct pci_host_bridge *bridge;
+	int ret;
+
+	raw_spin_lock_init(&pp->lock);
+
+	bridge = devm_pci_alloc_host_bridge(dev, 0);
+	if (!bridge)
+		return -ENOMEM;
+
+	pp->bridge = bridge;
+
+	ret = dw_pcie_host_get_resources(pp);
+	if (ret)
+		return ret;
+
 	/* Set default bus ops */
 	bridge->ops = &dw_pcie_ops;
 	bridge->child_ops = &dw_child_pcie_ops;
-- 
2.34.1



From helgaas at kernel.org  Sat Mar 15 13:15:48 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 15:15:48 -0500
Subject: [PATCH v12 13/13] PCI: imx6: Remove cpu_addr_fixup()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315201548.858189-14-helgaas@kernel.org>

From: Frank Li <Frank.Li at nxp.com>

Remove cpu_addr_fixup() because dwc common driver already handle address
translation.

Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-11-01d2313502ab at nxp.com
Signed-off-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
Acked-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 18 +-----------------
 1 file changed, 1 insertion(+), 17 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 90ace941090f..d1eb535df73e 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1217,22 +1217,6 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
 		regulator_disable(imx_pcie->vpcie);
 }
 
-static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
-{
-	struct imx_pcie *imx_pcie = to_imx_pcie(pcie);
-	struct dw_pcie_rp *pp = &pcie->pp;
-	struct resource_entry *entry;
-
-	if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_CPU_ADDR_FIXUP))
-		return cpu_addr;
-
-	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
-	if (!entry)
-		return cpu_addr;
-
-	return cpu_addr - entry->offset;
-}
-
 /*
  * In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
  * register is reserved, so the generic DWC implementation of sending the
@@ -1263,7 +1247,6 @@ static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
 static const struct dw_pcie_ops dw_pcie_ops = {
 	.start_link = imx_pcie_start_link,
 	.stop_link = imx_pcie_stop_link,
-	.cpu_addr_fixup = imx_pcie_cpu_addr_fixup,
 };
 
 static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
@@ -1645,6 +1628,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	pci->use_parent_dt_ranges = true;
 	if (imx_pcie->drvdata->mode == DW_PCIE_EP_TYPE) {
 		ret = imx_add_pcie_ep(imx_pcie, pdev);
 		if (ret < 0)
-- 
2.34.1



From cfsworks at gmail.com  Sat Mar 15 13:48:52 2025
From: cfsworks at gmail.com (Sam Edwards)
Date: Sat, 15 Mar 2025 13:48:52 -0700
Subject: [PATCH] arm64: dts: rockchip: Allow Turing RK1 cooling fan to spin down
Message-ID: <20250315204852.1247992-1-CFSworks@gmail.com>

The RK3588 thermal sensor driver only receives interrupts when a
higher-temperature threshold is crossed; it cannot notify when the
sensor cools back off. As a result, the driver must poll for temperature
changes to detect when the conditions for a thermal trip are no longer
met. However, it only does so if the DT enables polling.

Before this patch, the RK1 DT did not enable polling, causing the fan to
continue running at the speed corresponding to the highest temperature
reached.

Follow suit with similar RK3588 boards by setting a polling-delay of
1000ms, enabling the driver to detect when the sensor cools back off,
allowing the fan speed to decrease as appropriate.

Fixes: 7c8ec5e6b9d6 ("arm64: dts: rockchip: Enable automatic fan control on Turing RK1")
Signed-off-by: Sam Edwards <CFSworks at gmail.com>
---
 arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
index 6bc46734cc14..0270bffce195 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
@@ -214,6 +214,8 @@ rgmii_phy: ethernet-phy at 1 {
 };
 
 &package_thermal {
+	polling-delay = <1000>;
+
 	trips {
 		package_active1: trip-active1 {
 			temperature = <45000>;
-- 
2.45.3



From helgaas at kernel.org  Sat Mar 15 15:31:31 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Sat, 15 Mar 2025 17:31:31 -0500
Subject: [PATCH v12 00/13] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250315223131.GA866374@bhelgaas>

On Sat, Mar 15, 2025 at 03:15:35PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
> 
> This is a v12 based on Frank's v11 series.
> 
> v11 https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-0-01d2313502ab at nxp.com
>     
> Changes from v11:
>   - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init(), before
>     any devicetree-related code
>   - Call devm_pci_epc_create() early in dw_pcie_ep_init(), before any
>     devicetree-related code
>   - Consolidate devicetree-related code in dw_pcie_host_get_resources() and
>     dw_pcie_ep_get_resources()
>   - Integrate dw_pcie_cfg0_setup() into dw_pcie_host_get_resources()
>   - Convert dw_pcie_init_parent_bus_offset() to dw_pcie_parent_bus_offset()
>     which returns the offset rather than setting it internally
>   - Split the debug comparison of devicetree info with .cpu_addr_fixup() to
>     separate patch so we can easily revert it later
>   - Drop "cpu_addr_fixup() usage detected" warning since we always warn
>     about something in that case anyway

FWIW, here's the diff from v11 to v12:

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index e333855633a7..c1feaadb046a 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -884,26 +884,15 @@ void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_linkdown);
 
-/**
- * dw_pcie_ep_init - Initialize the endpoint device
- * @ep: DWC EP device
- *
- * Initialize the endpoint device. Allocate resources and create the EPC
- * device with the endpoint framework.
- *
- * Return: 0 if success, errno otherwise.
- */
-int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
 {
-	int ret;
-	struct resource *res;
-	struct pci_epc *epc;
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 	struct device *dev = pci->dev;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct device_node *np = dev->of_node;
-
-	INIT_LIST_HEAD(&ep->func_list);
+	struct pci_epc *epc = ep->epc;
+	struct resource *res;
+	int ret;
 
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
@@ -917,15 +906,36 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->addr_size = resource_size(res);
 
 	/*
-	 * artpec6_pcie_cpu_addr_fixup() use ep->phys_base. so call
-	 * dw_pcie_init_parent_bus_offset after init ep->phys_base.
+	 * artpec6_pcie_cpu_addr_fixup() uses ep->phys_base, so call
+	 * dw_pcie_parent_bus_offset() after setting ep->phys_base.
 	 */
-	ret = dw_pcie_init_parent_bus_offset(pci, "addr_space", ep->phys_base);
-	if (ret)
-		return ret;
+	pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "addr_space",
+							   ep->phys_base);
 
-	if (ep->ops->pre_init)
-		ep->ops->pre_init(ep);
+	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
+	if (ret < 0)
+		epc->max_functions = 1;
+
+	return 0;
+}
+
+/**
+ * dw_pcie_ep_init - Initialize the endpoint device
+ * @ep: DWC EP device
+ *
+ * Initialize the endpoint device. Allocate resources and create the EPC
+ * device with the endpoint framework.
+ *
+ * Return: 0 if success, errno otherwise.
+ */
+int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+	int ret;
+	struct pci_epc *epc;
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	struct device *dev = pci->dev;
+
+	INIT_LIST_HEAD(&ep->func_list);
 
 	epc = devm_pci_epc_create(dev, &epc_ops);
 	if (IS_ERR(epc)) {
@@ -936,9 +946,12 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 	ep->epc = epc;
 	epc_set_drvdata(epc, ep);
 
-	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
-	if (ret < 0)
-		epc->max_functions = 1;
+	ret = dw_pcie_ep_get_resources(ep);
+	if (ret)
+		return ret;
+
+	if (ep->ops->pre_init)
+		ep->ops->pre_init(ep);
 
 	ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
 			       ep->page_size);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 3e7df3d2ac26..d760abcbb785 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -392,29 +392,6 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
 	return 0;
 }
 
-static int dw_pcie_cfg0_setup(struct dw_pcie_rp *pp)
-{
-	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-	struct device *dev = pci->dev;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct resource *res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
-	if (!res) {
-		dev_err(dev, "Missing \"config\" reg space\n");
-		return -ENODEV;
-	}
-
-	pp->cfg0_size = resource_size(res);
-	pp->cfg0_base = res->start;
-
-	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
-	if (IS_ERR(pp->va_cfg0_base))
-		return PTR_ERR(pp->va_cfg0_base);
-
-	return 0;
-}
-
 static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -441,33 +418,34 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
 	}
 }
 
-int dw_pcie_host_init(struct dw_pcie_rp *pp)
+static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
-	struct device_node *np = dev->of_node;
+	struct platform_device *pdev = to_platform_device(dev);
 	struct resource_entry *win;
-	struct pci_host_bridge *bridge;
+	struct resource *res;
 	int ret;
 
-	raw_spin_lock_init(&pp->lock);
-
-	bridge = devm_pci_alloc_host_bridge(dev, 0);
-	if (!bridge)
-		return bridge;
-
-	pp->bridge = bridge;
-
 	ret = dw_pcie_get_resources(pci);
 	if (ret)
 		return ret;
 
-	ret = dw_pcie_cfg0_setup(pp);
-	if (ret)
-		return ret;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+	if (!res) {
+		dev_err(dev, "Missing \"config\" reg space\n");
+		return -ENODEV;
+	}
+
+	pp->cfg0_size = resource_size(res);
+	pp->cfg0_base = res->start;
+
+	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
+	if (IS_ERR(pp->va_cfg0_base))
+		return PTR_ERR(pp->va_cfg0_base);
 
 	/* Get the I/O range from DT */
-	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
+	win = resource_list_first_type(&pp->bridge->windows, IORESOURCE_IO);
 	if (win) {
 		pp->io_size = resource_size(win->res);
 		pp->io_bus_addr = win->res->start - win->offset;
@@ -475,11 +453,31 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	}
 
 	/*
-	 * visconti_pcie_cpu_addr_fixup() use pp->io_base,
-	 * so have to call dw_pcie_init_parent_bus_offset() after init
-	 * pp->io_base.
+	 * visconti_pcie_cpu_addr_fixup() uses pp->io_base, so we have to
+	 * call dw_pcie_parent_bus_offset() after setting pp->io_base.
 	 */
-	ret = dw_pcie_init_parent_bus_offset(pci, "config", pp->cfg0_base);
+	pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "config",
+							   pp->cfg0_base);
+	return 0;
+}
+
+int dw_pcie_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct device_node *np = dev->of_node;
+	struct pci_host_bridge *bridge;
+	int ret;
+
+	raw_spin_lock_init(&pp->lock);
+
+	bridge = devm_pci_alloc_host_bridge(dev, 0);
+	if (!bridge)
+		return -ENOMEM;
+
+	pp->bridge = bridge;
+
+	ret = dw_pcie_host_get_resources(pp);
 	if (ret)
 		return ret;
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index d4dc8bf06d4c..d9d2090f380c 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1104,51 +1104,48 @@ void dw_pcie_setup(struct dw_pcie *pci)
 	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
 }
 
-int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
-				   resource_size_t cpu_phy_addr)
+resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
+					  const char *reg_name,
+					  resource_size_t cpu_phy_addr)
 {
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
-	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
-	u64 reg_addr, fixup_addr;
 	int index;
+	u64 reg_addr, fixup_addr;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
 
 	/* Look up reg_name address on parent bus */
 	index = of_property_match_string(np, "reg-names", reg_name);
 
 	if (index < 0) {
-		dev_err(dev, "Missed reg-name: %s, Broken DTB file\n", reg_name);
-		return -EINVAL;
+		dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
+		return 0;
 	}
 
 	of_property_read_reg(np, index, &reg_addr, NULL);
 
 	fixup = pci->ops->cpu_addr_fixup;
 	if (fixup) {
-		dev_warn(pci->dev, "cpu_addr_fixup() usage detected. Please fix your DTB!\n");
-
 		fixup_addr = fixup(pci, cpu_phy_addr);
 		if (reg_addr == fixup_addr) {
 			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
 				 cpu_phy_addr, reg_name, index,
 				 fixup_addr, fixup);
 		} else {
-			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; DT is broken\n",
+			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
 				 cpu_phy_addr, reg_name,
 				 index, fixup_addr);
 			reg_addr = fixup_addr;
 		}
 	} else if (!pci->use_parent_dt_ranges) {
 		if (reg_addr != cpu_phy_addr) {
-			dev_warn(dev, "Your DTB try to use fake translation, Please check parent's ranges property. cpu physical addr: %#010llx, parent bus addr: %#010llx",
+			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
 				 cpu_phy_addr, reg_addr);
 			return 0;
 		}
 	}
 
-	pci->parent_bus_offset = cpu_phy_addr - reg_addr;
 	dev_info(dev, "%s parent bus offset is %#010llx\n",
-		 reg_name, pci->parent_bus_offset);
-
-	return 0;
+		 reg_name, cpu_phy_addr - reg_addr);
+	return cpu_phy_addr - reg_addr;
 }
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index bfed9d45aba9..741c46926ce2 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -466,13 +466,17 @@ struct dw_pcie {
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
 	bool			suspended;
+
 	/*
-	 * This flag indicates that the vendor driver uses devicetree 'ranges'
-	 * property to allow iATU to use the Intermediate Address (IA) for
-	 * outbound mapping.
+	 * If iATU input addresses are offset from CPU physical addresses,
+	 * we previously required .cpu_addr_fixup() to convert them.  We
+	 * now rely on the devicetree instead.  If .cpu_addr_fixup()
+	 * exists, we compare its results with devicetree.
 	 *
-	 * If use_parent_dt_ranges is false, warning will print if IA is not
-	 * equal to cpu physical address. Indicate dtb use a fake translation.
+	 * If .cpu_addr_fixup() does not exist, we assume the offset is
+	 * zero and warn if devicetree claims otherwise.  If we know all
+	 * devicetrees correctly describe the offset, set
+	 * use_parent_dt_ranges to true to avoid this warning.
 	 */
 	bool			use_parent_dt_ranges;
 };
@@ -510,8 +514,9 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
-int dw_pcie_init_parent_bus_offset(struct dw_pcie *pci, const char *reg_name,
-				   resource_size_t cpu_phy_addr);
+resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
+					  const char *reg_name,
+					  resource_size_t cpu_phy_addr);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {


From namhyung at kernel.org  Sat Mar 15 16:02:35 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Sat, 15 Mar 2025 16:02:35 -0700
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9SWDGsdgagMr8PV@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
 <Z9RjHpEJGWtj8PAM@x1>
 <Z9Rm0W6YLpxKIcI1@x1>
 <Z9SWDGsdgagMr8PV@x1>
Message-ID: <Z9YHCzINiu4uBQ8B@google.com>

On Fri, Mar 14, 2025 at 05:48:12PM -0300, Arnaldo Carvalho de Melo wrote:
> On Fri, Mar 14, 2025 at 02:26:41PM -0300, Arnaldo Carvalho de Melo wrote:
> > it finds the pair, but then its sc->args has a bogus pointer... I'll see
> > where this isn't being initialized...
> 
> Breakpoint 4, trace__find_usable_bpf_prog_entry (trace=0x7fffffffa510, sc=0x1046f10) at builtin-trace.c:3874
> 3874			bool is_candidate = false;
> (gdb) n
> 3876			if (pair == NULL || pair == sc ||
> (gdb) p pair
> $7 = (struct syscall *) 0x1083c50
> (gdb) p pair->name
> $8 = 0x81478e "accept4"
> (gdb) n
> 3877			    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
> (gdb) p i
> $9 = 1
> (gdb) n
> 3876			if (pair == NULL || pair == sc ||
> (gdb) n
> 3880			printf("sc=%p\n", sc); fflush(stdout);
> (gdb) n
> sc=0x1046f10
> 3881			printf("sc->name=%p\n", sc->name); fflush(stdout);
> (gdb) n
> sc->name=0x6c66202c786c3830
> 3882			printf("sc->nr_args=%d, sc->args=%p\n", sc->nr_args, sc->args); fflush(stdout);
> (gdb) p sc->nr_args
> $10 = 1935635045
> (gdb) p sc->args
> $11 = (struct tep_format_field *) 0x257830203a6e656c
> (gdb) p *sc
> $12 = {e_machine = 540697702, id = 807761968, tp_format = 0x657075202c786c38, nr_args = 1935635045, args_size = 1634427759, bpf_prog = {sys_enter = 0x257830203a726464, 
>     sys_exit = 0x7075202c786c3830}, is_exit = 101, is_open = 101, nonexistent = 114, use_btf = 95, args = 0x257830203a6e656c, 
>   name = 0x6c66202c786c3830 <error: Cannot access memory at address 0x6c66202c786c3830>, fmt = 0x257830203a736761, arg_fmt = 0x786c3830}
> (gdb) 
> 
> Ok, ran out of time, but if I simple avoid the second loop in:
> 
> static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
> 
> 
> I.e. the one that starts with:
> 
>         /*
>          * Now lets do a second pass looking for enabled syscalls without
>          * an augmenter that have a signature that is a superset of another
>          * syscall with an augmenter so that we can auto-reuse it.
> 
> This:
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index e0434f7dc67cb988..3664bb512c70cabf 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -3989,6 +3989,8 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
>                         goto out;
>         }
>  
> +       return 0;
> +
>         /*
>          * Now lets do a second pass looking for enabled syscalls without
>          * an augmenter that have a signature that is a superset of another
> ? [acme at toolbox perf-tools-next]$ 
> 
> 
> Then all works, we don't reuse any BPF program, but then that is an
> heuristic anyway, that is tried becuase landlock_add_rule has a pointer
> argument:
> 
> root at number:~# perf trace -e landlock_add_rule perf test -w landlock
>      0.000 ( 0.003 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7fff6f2bb550, flags: 45) = -1 EINVAL (Invalid argument)
>      0.004 ( 0.001 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7fff6f2bb540, flags: 45) = -1 EINVAL (Invalid argument)
> root at number:~# perf test enum
> 105: perf trace enum augmentation tests                              : Ok
> root at number:~#
> 
> So its some sort of syncronization on the various new tables, sorted by
> name, etc that then when iterating over the syscalls ends up using a sc
> that is not initialized.

Right, I've realized that calling trace__syscall_info() can invalidate
the existing sc since it calls trace__find_syscall() which reallocates
and resorts the syscall table.  That's why it was ok when no filter was
used since it'd allocate the whole table in the first pass.  Otherwise
it looks for a pair syscall while holding the original sc but calling
the function would invalidate the sc.

What about this (on top of my earlier fix)?

Thanks,
Namhyung


---8<---
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 49199d753b7cafbf..da0ddc713e6b35da 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2506,10 +2506,12 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
 	};
 	struct syscall *sc, *tmp;
 
-	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
-		     sizeof(struct syscall), syscall__cmp);
-	if (sc)
-		return sc;
+	if (trace->syscalls.table) {
+		sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+			     sizeof(struct syscall), syscall__cmp);
+		if (sc)
+			return sc;
+	}
 
 	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
 			   sizeof(struct syscall));
@@ -3855,6 +3857,10 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, i
 
 static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
 {
+	int orig_id = sc->id;
+	const char *orig_name = sc->name;
+	int e_machine = sc->e_machine;
+	struct tep_format_field *args = sc->args;
 	struct tep_format_field *field, *candidate_field;
 	/*
 	 * We're only interested in syscalls that have a pointer:
@@ -3866,18 +3872,19 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 
 	return NULL;
 
+	/* calling trace__syscall_info() may invalidate 'sc' */
 try_to_find_pair:
-	for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
-		int id = syscalltbl__id_at_idx(sc->e_machine, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(e_machine, i);
+		struct syscall *pair = trace__syscall_info(trace, NULL, e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
-		if (pair == NULL || pair == sc ||
+		if (pair == NULL || pair->id == orig_id ||
 		    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
 			continue;
 
-		for (field = sc->args, candidate_field = pair->args;
+		for (field = args, candidate_field = pair->args;
 		     field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
 			bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
 			     candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3944,7 +3951,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 				goto next_candidate;
 		}
 
-		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name);
+		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, orig_name);
 		return pair_prog;
 	next_candidate:
 		continue;
@@ -4041,6 +4048,11 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
 		if (pair_prog == NULL)
 			continue;
 
+		/*
+		 * Get syscall info again as find usable entry above might
+		 * modify the syscall table and shuffle it.
+		 */
+		sc = trace__syscall_info(trace, NULL, e_machine, key);
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*



From lkp at intel.com  Sat Mar 15 17:04:08 2025
From: lkp at intel.com (kernel test robot)
Date: Sun, 16 Mar 2025 08:04:08 +0800
Subject: [soc:k3/dt] BUILD SUCCESS
 377fde74eae4abcbcd5475676d58fb595a07ff85
Message-ID: <202503160859.nqoAvZQO-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git k3/dt
branch HEAD: 377fde74eae4abcbcd5475676d58fb595a07ff85  arm64: dts: ti: k3-am62a-phycore-som: Reorder properties per DTS coding style

elapsed time: 1445m

configs tested: 153
configs skipped: 130

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                   allnoconfig    gcc-14.2.0
alpha                  allyesconfig    clang-21
alpha                     defconfig    gcc-14.2.0
arc                    allmodconfig    clang-18
arc                     allnoconfig    gcc-14.2.0
arc                    allyesconfig    clang-18
arc                       defconfig    gcc-14.2.0
arc         randconfig-001-20250315    gcc-14.2.0
arc         randconfig-002-20250315    gcc-14.2.0
arm                    allmodconfig    clang-18
arm                     allnoconfig    gcc-14.2.0
arm                    allyesconfig    clang-18
arm                       defconfig    gcc-14.2.0
arm            footbridge_defconfig    gcc-14.2.0
arm                 imxrt_defconfig    gcc-14.2.0
arm         randconfig-001-20250315    gcc-14.2.0
arm         randconfig-002-20250315    gcc-14.2.0
arm         randconfig-003-20250315    gcc-14.2.0
arm         randconfig-004-20250315    gcc-14.2.0
arm64                  allmodconfig    clang-18
arm64                   allnoconfig    gcc-14.2.0
arm64                     defconfig    gcc-14.2.0
arm64       randconfig-001-20250315    gcc-14.2.0
arm64       randconfig-002-20250315    gcc-14.2.0
arm64       randconfig-003-20250315    clang-16
arm64       randconfig-003-20250315    gcc-14.2.0
arm64       randconfig-004-20250315    gcc-14.2.0
csky                    allnoconfig    gcc-14.2.0
csky                      defconfig    gcc-14.2.0
csky        randconfig-001-20250315    gcc-14.2.0
csky        randconfig-002-20250315    gcc-14.2.0
hexagon                allmodconfig    clang-21
hexagon                 allnoconfig    gcc-14.2.0
hexagon                allyesconfig    clang-21
hexagon                   defconfig    gcc-14.2.0
hexagon     randconfig-001-20250315    gcc-14.2.0
hexagon     randconfig-002-20250315    gcc-14.2.0
i386                   allmodconfig    clang-19
i386                    allnoconfig    clang-19
i386                   allyesconfig    clang-19
i386                      defconfig    clang-19
i386        randconfig-001-20250316    gcc-12
i386        randconfig-002-20250316    gcc-12
i386        randconfig-003-20250316    gcc-12
i386        randconfig-004-20250316    gcc-12
i386        randconfig-005-20250316    gcc-12
i386        randconfig-006-20250316    gcc-12
i386        randconfig-007-20250316    gcc-12
i386        randconfig-011-20250315    gcc-12
i386        randconfig-012-20250315    gcc-12
i386        randconfig-013-20250315    gcc-12
i386        randconfig-014-20250315    gcc-12
i386        randconfig-015-20250315    gcc-12
i386        randconfig-016-20250315    gcc-12
i386        randconfig-017-20250315    gcc-12
loongarch              allmodconfig    gcc-14.2.0
loongarch               allnoconfig    gcc-14.2.0
loongarch                 defconfig    gcc-14.2.0
loongarch   randconfig-001-20250315    gcc-14.2.0
loongarch   randconfig-002-20250315    gcc-14.2.0
m68k                   allmodconfig    gcc-14.2.0
m68k                   allyesconfig    gcc-14.2.0
m68k               apollo_defconfig    clang-17
m68k                      defconfig    gcc-14.2.0
m68k              m5272c3_defconfig    clang-17
microblaze             allmodconfig    gcc-14.2.0
microblaze             allyesconfig    gcc-14.2.0
microblaze                defconfig    gcc-14.2.0
mips              maltaup_defconfig    gcc-14.2.0
mips                rb532_defconfig    clang-17
nios2                     defconfig    gcc-14.2.0
nios2       randconfig-001-20250315    gcc-14.2.0
nios2       randconfig-002-20250315    gcc-14.2.0
openrisc               allyesconfig    gcc-14.2.0
openrisc                  defconfig    gcc-12
parisc                 allmodconfig    gcc-14.2.0
parisc                 allyesconfig    gcc-14.2.0
parisc                    defconfig    gcc-12
parisc      generic-64bit_defconfig    clang-17
parisc      randconfig-001-20250315    gcc-14.2.0
parisc      randconfig-002-20250315    gcc-14.2.0
parisc64                  defconfig    gcc-14.2.0
powerpc                allmodconfig    gcc-14.2.0
powerpc                allyesconfig    gcc-14.2.0
powerpc        mpc885_ads_defconfig    clang-17
powerpc          mvme5100_defconfig    gcc-14.2.0
powerpc     randconfig-001-20250315    gcc-14.2.0
powerpc     randconfig-002-20250315    gcc-14.2.0
powerpc     randconfig-003-20250315    gcc-14.2.0
powerpc          sam440ep_defconfig    clang-17
powerpc64   randconfig-001-20250315    gcc-14.2.0
powerpc64   randconfig-002-20250315    gcc-14.2.0
powerpc64   randconfig-003-20250315    gcc-14.2.0
riscv                  allmodconfig    gcc-14.2.0
riscv                  allyesconfig    gcc-14.2.0
riscv                     defconfig    gcc-12
riscv       randconfig-001-20250316    gcc-14.2.0
riscv       randconfig-002-20250316    gcc-14.2.0
s390                   allmodconfig    gcc-14.2.0
s390                   allyesconfig    gcc-14.2.0
s390                      defconfig    gcc-12
s390        randconfig-001-20250316    gcc-14.2.0
s390        randconfig-002-20250316    gcc-14.2.0
sh                     allmodconfig    gcc-14.2.0
sh                     allyesconfig    gcc-14.2.0
sh               apsh4a3a_defconfig    gcc-14.2.0
sh                        defconfig    gcc-12
sh                r7785rp_defconfig    gcc-14.2.0
sh          randconfig-001-20250316    gcc-14.2.0
sh          randconfig-002-20250316    gcc-14.2.0
sh                sdk7786_defconfig    clang-17
sh                   shx3_defconfig    gcc-14.2.0
sparc                  allmodconfig    gcc-14.2.0
sparc       randconfig-001-20250316    gcc-14.2.0
sparc       randconfig-002-20250316    gcc-14.2.0
sparc64                   defconfig    gcc-12
sparc64     randconfig-001-20250316    gcc-14.2.0
sparc64     randconfig-002-20250316    gcc-14.2.0
um                     allmodconfig    clang-21
um                     allyesconfig    clang-21
um                        defconfig    gcc-12
um                   i386_defconfig    gcc-12
um          randconfig-001-20250316    gcc-14.2.0
um          randconfig-002-20250316    gcc-14.2.0
um                 x86_64_defconfig    clang-17
um                 x86_64_defconfig    gcc-12
x86_64                  allnoconfig    clang-19
x86_64                 allyesconfig    clang-19
x86_64                    defconfig    clang-19
x86_64                        kexec    clang-19
x86_64      randconfig-001-20250316    gcc-12
x86_64      randconfig-002-20250316    gcc-12
x86_64      randconfig-003-20250316    gcc-12
x86_64      randconfig-004-20250316    gcc-12
x86_64      randconfig-005-20250316    gcc-12
x86_64      randconfig-006-20250316    gcc-12
x86_64      randconfig-007-20250316    gcc-12
x86_64      randconfig-008-20250316    gcc-12
x86_64      randconfig-071-20250315    clang-19
x86_64      randconfig-072-20250315    clang-19
x86_64      randconfig-073-20250315    clang-19
x86_64      randconfig-074-20250315    clang-19
x86_64      randconfig-075-20250315    clang-19
x86_64      randconfig-076-20250315    clang-19
x86_64      randconfig-077-20250315    clang-19
x86_64      randconfig-078-20250315    clang-19
x86_64                     rhel-9.4    clang-19
x86_64                 rhel-9.4-bpf    clang-18
x86_64               rhel-9.4-kunit    clang-18
x86_64                 rhel-9.4-ltp    clang-18
x86_64                rhel-9.4-rust    clang-18
xtensa      randconfig-001-20250316    gcc-14.2.0
xtensa      randconfig-002-20250316    gcc-14.2.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From Frank.li at nxp.com  Sat Mar 15 18:18:52 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:18:52 -0400
Subject: [PATCH v12 04/13] PCI: dwc: Consolidate devicetree handling in
 dw_pcie_host_get_resources()
In-Reply-To: <20250315201548.858189-5-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-5-helgaas@kernel.org>
Message-ID: <Z9Ym/MROIgAOvk+8@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:39PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
>
> Consolidate devicetree resource handling in dw_pcie_host_get_resources().
> No functional change intended.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  .../pci/controller/dwc/pcie-designware-host.c | 37 +++++++++++++------
>  1 file changed, 25 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 5636243fb90e..9ce06b1ee266 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -418,25 +418,15 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
>  	}
>  }
>
> -int dw_pcie_host_init(struct dw_pcie_rp *pp)
> +static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>  	struct device *dev = pci->dev;
> -	struct device_node *np = dev->of_node;
>  	struct platform_device *pdev = to_platform_device(dev);
>  	struct resource_entry *win;
> -	struct pci_host_bridge *bridge;
>  	struct resource *res;
>  	int ret;
>
> -	raw_spin_lock_init(&pp->lock);
> -
> -	bridge = devm_pci_alloc_host_bridge(dev, 0);
> -	if (!bridge)
> -		return -ENOMEM;
> -
> -	pp->bridge = bridge;
> -
>  	ret = dw_pcie_get_resources(pci);
>  	if (ret)
>  		return ret;
> @@ -455,13 +445,36 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  		return PTR_ERR(pp->va_cfg0_base);
>
>  	/* Get the I/O range from DT */
> -	win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
> +	win = resource_list_first_type(&pp->bridge->windows, IORESOURCE_IO);
>  	if (win) {
>  		pp->io_size = resource_size(win->res);
>  		pp->io_bus_addr = win->res->start - win->offset;
>  		pp->io_base = pci_pio_to_address(win->res->start);
>  	}
>
> +	return 0;
> +}
> +
> +int dw_pcie_host_init(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	struct device *dev = pci->dev;
> +	struct device_node *np = dev->of_node;
> +	struct pci_host_bridge *bridge;
> +	int ret;
> +
> +	raw_spin_lock_init(&pp->lock);
> +
> +	bridge = devm_pci_alloc_host_bridge(dev, 0);
> +	if (!bridge)
> +		return -ENOMEM;
> +
> +	pp->bridge = bridge;
> +
> +	ret = dw_pcie_host_get_resources(pp);
> +	if (ret)
> +		return ret;
> +
>  	/* Set default bus ops */
>  	bridge->ops = &dw_pcie_ops;
>  	bridge->child_ops = &dw_child_pcie_ops;
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:20:42 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:20:42 -0400
Subject: [PATCH v12 05/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
In-Reply-To: <20250315201548.858189-6-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-6-helgaas@kernel.org>
Message-ID: <Z9YnajnFGpULuTKf@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:40PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
>
> Return the offset from CPU physical address to the parent bus address of
> the specified element of the devicetree 'reg' property.
>
> [bhelgaas: return offset, split .cpu_addr_fixup() checking and debug to
> separate patch]
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---

look good!

>  drivers/pci/controller/dwc/pcie-designware.c | 23 ++++++++++++++++++++
>  drivers/pci/controller/dwc/pcie-designware.h |  3 +++
>  2 files changed, 26 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 9d0a5f75effc..0a35e36da703 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -16,6 +16,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/ioport.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
>  #include <linux/platform_device.h>
>  #include <linux/sizes.h>
>  #include <linux/types.h>
> @@ -1105,3 +1106,25 @@ void dw_pcie_setup(struct dw_pcie *pci)
>
>  	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
>  }
> +
> +resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> +					  const char *reg_name,
> +					  resource_size_t cpu_phy_addr)
> +{
> +	struct device *dev = pci->dev;
> +	struct device_node *np = dev->of_node;
> +	int index;
> +	u64 reg_addr;
> +
> +	/* Look up reg_name address on parent bus */
> +	index = of_property_match_string(np, "reg-names", reg_name);
> +
> +	if (index < 0) {
> +		dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
> +		return 0;
> +	}
> +
> +	of_property_read_reg(np, index, &reg_addr, NULL);
> +
> +	return cpu_phy_addr - reg_addr;
> +}
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index d0d8c622a6e8..16548b01347d 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -500,6 +500,9 @@ void dw_pcie_setup(struct dw_pcie *pci);
>  void dw_pcie_iatu_detect(struct dw_pcie *pci);
>  int dw_pcie_edma_detect(struct dw_pcie *pci);
>  void dw_pcie_edma_remove(struct dw_pcie *pci);
> +resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> +					  const char *reg_name,
> +					  resource_size_t cpu_phy_addr);
>
>  static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
>  {
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:23:06 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:23:06 -0400
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <20250315201548.858189-7-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-7-helgaas@kernel.org>
Message-ID: <Z9Yn+uY63X3Qm8ZZ@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
>
> dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> is a hard-coded way to get the parent bus address corresponding to a CPU
> physical address.
>
> Add debug code to compare the address from .cpu_addr_fixup() with the
> address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> redundant and should be removed; if they differ, warn that something is
> wrong with the devicetree.
>
> If .cpu_addr_fixup() is not implemented, the parent bus address should be
> identical to the CPU physical address because we previously ignored the
> parent bus address from devicetree.  If the devicetree has a different
> parent bus address, warn about it being broken.
>
> [bhelgaas: split debug to separate patch for easier future revert, commit
> log]
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware.c | 26 +++++++++++++++++++-
>  drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++++
>  2 files changed, 38 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 0a35e36da703..985264c88b92 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>  	struct device *dev = pci->dev;
>  	struct device_node *np = dev->of_node;
>  	int index;
> -	u64 reg_addr;
> +	u64 reg_addr, fixup_addr;
> +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
>
>  	/* Look up reg_name address on parent bus */
>  	index = of_property_match_string(np, "reg-names", reg_name);
> @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>
>  	of_property_read_reg(np, index, &reg_addr, NULL);
>
> +	fixup = pci->ops->cpu_addr_fixup;
> +	if (fixup) {
> +		fixup_addr = fixup(pci, cpu_phy_addr);
> +		if (reg_addr == fixup_addr) {
> +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
> +				 cpu_phy_addr, reg_name, index,
> +				 fixup_addr, fixup);
> +		} else {
> +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> +				 cpu_phy_addr, reg_name,
> +				 index, fixup_addr);
> +			reg_addr = fixup_addr;
> +		}
> +	} else if (!pci->use_parent_dt_ranges) {
> +		if (reg_addr != cpu_phy_addr) {
> +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> +				 cpu_phy_addr, reg_addr);
> +			return 0;
> +		}
> +	}
> +
> +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> +		 reg_name, cpu_phy_addr - reg_addr);
>  	return cpu_phy_addr - reg_addr;
>  }
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 16548b01347d..f08d2852cfd5 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -465,6 +465,19 @@ struct dw_pcie {
>  	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
>  	struct gpio_desc		*pe_rst;
>  	bool			suspended;
> +
> +	/*
> +	 * If iATU input addresses are offset from CPU physical addresses,
> +	 * we previously required .cpu_addr_fixup() to convert them.  We
> +	 * now rely on the devicetree instead.  If .cpu_addr_fixup()
> +	 * exists, we compare its results with devicetree.
> +	 *
> +	 * If .cpu_addr_fixup() does not exist, we assume the offset is
> +	 * zero and warn if devicetree claims otherwise.  If we know all
> +	 * devicetrees correctly describe the offset, set
> +	 * use_parent_dt_ranges to true to avoid this warning.
> +	 */
> +	bool			use_parent_dt_ranges;

Look good.

Frank

>  };
>
>  #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:24:14 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:24:14 -0400
Subject: [PATCH v12 08/13] PCI: dwc: ep: Call epc_create() early in
 dw_pcie_ep_init()
In-Reply-To: <20250315201548.858189-9-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-9-helgaas@kernel.org>
Message-ID: <Z9YoPgphIhYDmOga@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:43PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
>
> Move devm_pci_epc_create() to the beginning of dw_pcie_ep_init().
>
> devm_pci_epc_create() is generic code that doesn't depend on any DWC
> resource, so moving it earlier keeps all the subsequent devicetree-related
> code together.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  .../pci/controller/dwc/pcie-designware-ep.c    | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 80ac2f9e88eb..100d26466f05 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -904,6 +904,15 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>
>  	INIT_LIST_HEAD(&ep->func_list);
>
> +	epc = devm_pci_epc_create(dev, &epc_ops);
> +	if (IS_ERR(epc)) {
> +		dev_err(dev, "Failed to create epc device\n");
> +		return PTR_ERR(epc);
> +	}
> +
> +	ep->epc = epc;
> +	epc_set_drvdata(epc, ep);
> +
>  	ret = dw_pcie_get_resources(pci);
>  	if (ret)
>  		return ret;
> @@ -918,15 +927,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>  	if (ep->ops->pre_init)
>  		ep->ops->pre_init(ep);
>
> -	epc = devm_pci_epc_create(dev, &epc_ops);
> -	if (IS_ERR(epc)) {
> -		dev_err(dev, "Failed to create epc device\n");
> -		return PTR_ERR(epc);
> -	}
> -
> -	ep->epc = epc;
> -	epc_set_drvdata(epc, ep);
> -
>  	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
>  	if (ret < 0)
>  		epc->max_functions = 1;
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:26:56 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:26:56 -0400
Subject: [PATCH v12 09/13] PCI: dwc: ep: Consolidate devicetree handling
 in dw_pcie_ep_get_resources()
In-Reply-To: <20250315201548.858189-10-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-10-helgaas@kernel.org>
Message-ID: <Z9Yo4PeBH49EXPkg@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:44PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
>
> Consolidate devicetree resource handling in dw_pcie_ep_get_resources().
> No functional change intended.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>  .../pci/controller/dwc/pcie-designware-ep.c   | 68 +++++++++++--------
>  1 file changed, 41 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 100d26466f05..2db834345ec2 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -883,35 +883,15 @@ void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep)
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_linkdown);
>
> -/**
> - * dw_pcie_ep_init - Initialize the endpoint device
> - * @ep: DWC EP device
> - *
> - * Initialize the endpoint device. Allocate resources and create the EPC
> - * device with the endpoint framework.
> - *
> - * Return: 0 if success, errno otherwise.
> - */
> -int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> +static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
>  {
> -	int ret;
> -	struct resource *res;
> -	struct pci_epc *epc;
>  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>  	struct device *dev = pci->dev;
>  	struct platform_device *pdev = to_platform_device(dev);
>  	struct device_node *np = dev->of_node;
> -
> -	INIT_LIST_HEAD(&ep->func_list);
> -
> -	epc = devm_pci_epc_create(dev, &epc_ops);
> -	if (IS_ERR(epc)) {
> -		dev_err(dev, "Failed to create epc device\n");
> -		return PTR_ERR(epc);
> -	}
> -
> -	ep->epc = epc;
> -	epc_set_drvdata(epc, ep);
> +	struct pci_epc *epc = ep->epc;
> +	struct resource *res;
> +	int ret;
>
>  	ret = dw_pcie_get_resources(pci);
>  	if (ret)
> @@ -924,13 +904,47 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>  	ep->phys_base = res->start;
>  	ep->addr_size = resource_size(res);
>
> -	if (ep->ops->pre_init)
> -		ep->ops->pre_init(ep);
> -
>  	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
>  	if (ret < 0)
>  		epc->max_functions = 1;
>
> +	return 0;
> +}
> +
> +/**
> + * dw_pcie_ep_init - Initialize the endpoint device
> + * @ep: DWC EP device
> + *
> + * Initialize the endpoint device. Allocate resources and create the EPC
> + * device with the endpoint framework.
> + *
> + * Return: 0 if success, errno otherwise.
> + */
> +int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> +{
> +	int ret;
> +	struct pci_epc *epc;
> +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> +	struct device *dev = pci->dev;
> +
> +	INIT_LIST_HEAD(&ep->func_list);
> +
> +	epc = devm_pci_epc_create(dev, &epc_ops);
> +	if (IS_ERR(epc)) {
> +		dev_err(dev, "Failed to create epc device\n");
> +		return PTR_ERR(epc);
> +	}
> +
> +	ep->epc = epc;
> +	epc_set_drvdata(epc, ep);
> +
> +	ret = dw_pcie_ep_get_resources(ep);
> +	if (ret)
> +		return ret;
> +
> +	if (ep->ops->pre_init)
> +		ep->ops->pre_init(ep);
> +
>  	ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
>  			       ep->page_size);
>  	if (ret < 0) {
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:32:50 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:32:50 -0400
Subject: [PATCH v12 10/13] PCI: dwc: ep: Use devicetree 'reg[addr_space]'
 to derive CPU -> ATU addr offset
In-Reply-To: <20250315201548.858189-11-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-11-helgaas@kernel.org>
Message-ID: <Z9YqQm12WY13obkd@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:45PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
>
>                    Endpoint
>   ?????????????????????????????????????????????????
>   ?                             pcie-ep at 5f010000  ?
>   ?                             ???????????????????
>   ?                             ?   Endpoint     ??
>   ?                             ?   PCIe         ??
>   ?                             ?   Controller   ??
>   ?           bus at 5f000000      ?             ??????????
>   ?           ????????????      ?             ?  ??dynamically
>   ?           ?          ? Outbound Transfer  ?  ??allocated
>   ????????    ?  Bus     ???????? ATU  ????????  ??PCI Addr
>   ??     ?    ?  Fabric  ?Bus   ?                ??
>   ?? CPU ??????          ?Addr  ?                ??
>   ??     ?CPU ?          ?0x8000_0000            ??
>   ????????Addr????????????      ?                ??
>   ?       0x7000_0000           ???????????????????
>   ?????????????????????????????????????????????????
>
>   bus at 5f000000 {
>           compatible = "simple-bus";
>           ranges = <0x80000000 0x0 0x70000000 0x10000000>;
>
>           pcie-ep at 5f010000 {
>                   reg = <0x80000000 0x10000000>;
>                   reg-names ="addr_space";
>                   ...
>           };
>           ...
>   };
>
> In the diagram above, CPU writes data to outbound window address
> 0x7000_0000, and the bus fabric maps it to 0x8000_0000. The ATU uses
> bus address 0x8000_0000 as input address and maps to some PCI address
> dynamically allocated by a PCI device driver on the host side.
>
> The pcie-ep at 5f010000 'reg[addr_space]' is the parent bus address of the
> PCIe controller input, including the ATU.

how about

The pcie-ep at 5f010000 'reg[addr_space]' is the parent bus address, which is
input of PCIe controller including the ATU.

Frank

>
> Set parent_bus_offset, the offset from the CPU address to the PCIe
> controller input address using dw_pcie_init_parent_bus_offset().  The
> parent_bus_offset is not used yet, so no functional change intended.
>
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-7-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> [bhelgaas: commit log]
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---

>  drivers/pci/controller/dwc/pcie-designware-ep.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 2db834345ec2..bb87d0c5c665 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -904,6 +904,13 @@ static int dw_pcie_ep_get_resources(struct dw_pcie_ep *ep)
>  	ep->phys_base = res->start;
>  	ep->addr_size = resource_size(res);
>
> +	/*
> +	 * artpec6_pcie_cpu_addr_fixup() uses ep->phys_base, so call
> +	 * dw_pcie_parent_bus_offset() after setting ep->phys_base.
> +	 */
> +	pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "addr_space",
> +							   ep->phys_base);
> +
>  	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
>  	if (ret < 0)
>  		epc->max_functions = 1;
> --
> 2.34.1
>


From Frank.li at nxp.com  Sat Mar 15 18:34:57 2025
From: Frank.li at nxp.com (Frank Li)
Date: Sat, 15 Mar 2025 21:34:57 -0400
Subject: [PATCH v12 12/13] PCI: dwc: Use parent_bus_offset to remove need
 for .cpu_addr_fixup()
In-Reply-To: <20250315201548.858189-13-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-13-helgaas@kernel.org>
Message-ID: <Z9YqwXG5yrQX8Mep@lizhi-Precision-Tower-5810>

On Sat, Mar 15, 2025 at 03:15:47PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
>
> We know the parent_bus_offset, either computed from a DT reg property (the
> offset is the CPU physical addr - the 'config'/'addr_space' address on the
> parent bus) or from a .cpu_addr_fixup() (which may have used a host bridge
> window offset).
>
> Apply that parent_bus_offset instead of calling .cpu_addr_fixup() when
> programming the ATU.
>
> This assumes all intermediate addresses are at the same offset from the CPU
> physical addresses.
>
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-9-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> [bhelgaas: commit log]
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>

look good

Frank
> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c   |  5 +++--
>  drivers/pci/controller/dwc/pcie-designware-host.c | 12 ++++++------
>  drivers/pci/controller/dwc/pcie-designware.c      |  3 ---
>  3 files changed, 9 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 2ef9964fa080..c1feaadb046a 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -314,7 +314,8 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
>  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
>  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>
> -	ret = dw_pcie_find_index(ep, addr, &atu_index);
> +	ret = dw_pcie_find_index(ep, addr - pci->parent_bus_offset,
> +				 &atu_index);
>  	if (ret < 0)
>  		return;
>
> @@ -333,7 +334,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
>
>  	atu.func_no = func_no;
>  	atu.type = PCIE_ATU_TYPE_MEM;
> -	atu.parent_bus_addr = addr;
> +	atu.parent_bus_addr = addr - pci->parent_bus_offset;
>  	atu.pci_addr = pci_addr;
>  	atu.size = size;
>  	ret = dw_pcie_ep_outbound_atu(ep, &atu);
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 9e38ac7d1bcb..d760abcbb785 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -635,7 +635,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
>  		type = PCIE_ATU_TYPE_CFG1;
>
>  	atu.type = type;
> -	atu.parent_bus_addr = pp->cfg0_base;
> +	atu.parent_bus_addr = pp->cfg0_base - pci->parent_bus_offset;
>  	atu.pci_addr = busdev;
>  	atu.size = pp->cfg0_size;
>
> @@ -660,7 +660,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
>
>  	if (pp->cfg0_io_shared) {
>  		atu.type = PCIE_ATU_TYPE_IO;
> -		atu.parent_bus_addr = pp->io_base;
> +		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
>  		atu.pci_addr = pp->io_bus_addr;
>  		atu.size = pp->io_size;
>
> @@ -686,7 +686,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
>
>  	if (pp->cfg0_io_shared) {
>  		atu.type = PCIE_ATU_TYPE_IO;
> -		atu.parent_bus_addr = pp->io_base;
> +		atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
>  		atu.pci_addr = pp->io_bus_addr;
>  		atu.size = pp->io_size;
>
> @@ -755,7 +755,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
>
>  		atu.index = i;
>  		atu.type = PCIE_ATU_TYPE_MEM;
> -		atu.parent_bus_addr = entry->res->start;
> +		atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
>  		atu.pci_addr = entry->res->start - entry->offset;
>
>  		/* Adjust iATU size if MSG TLP region was allocated before */
> @@ -777,7 +777,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
>  		if (pci->num_ob_windows > ++i) {
>  			atu.index = i;
>  			atu.type = PCIE_ATU_TYPE_IO;
> -			atu.parent_bus_addr = pp->io_base;
> +			atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
>  			atu.pci_addr = pp->io_bus_addr;
>  			atu.size = pp->io_size;
>
> @@ -921,7 +921,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
>  	atu.size = resource_size(pci->pp.msg_res);
>  	atu.index = pci->pp.msg_atu_index;
>
> -	atu.parent_bus_addr = pci->pp.msg_res->start;
> +	atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
>
>  	ret = dw_pcie_prog_outbound_atu(pci, &atu);
>  	if (ret)
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 985264c88b92..d9d2090f380c 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -475,9 +475,6 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
>  	u32 retries, val;
>  	u64 limit_addr;
>
> -	if (pci->ops && pci->ops->cpu_addr_fixup)
> -		parent_bus_addr = pci->ops->cpu_addr_fixup(pci, parent_bus_addr);
> -
>  	limit_addr = parent_bus_addr + atu->size - 1;
>
>  	if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
> --
> 2.34.1
>


From memxor at gmail.com  Sat Mar 15 21:05:31 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:31 -0700
Subject: [PATCH bpf-next v4 15/25] rqspinlock: Add helper to print a splat on timeout or deadlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-16-memxor@gmail.com>

Whenever a timeout and a deadlock occurs, we would want to print a
message to the dmesg console, including the CPU where the event
occurred, the list of locks in the held locks table, and the stack trace
of the caller, which allows determining where exactly in the slow path
the waiter timed out or detected a deadlock.

Splats are limited to atmost one per-CPU during machine uptime, and a
lock is acquired to ensure that no interleaving occurs when a concurrent
set of CPUs conflict and enter a deadlock situation and start printing
data.

Later patches will use this to inspect return value of rqspinlock API
and then report a violation if necessary.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/rqspinlock.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index ed21ee010063..ad0fc35c647e 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -196,6 +196,35 @@ static noinline int check_deadlock_ABBA(rqspinlock_t *lock, u32 mask,
 	return 0;
 }
 
+static DEFINE_PER_CPU(int, report_nest_cnt);
+static DEFINE_PER_CPU(bool, report_flag);
+static arch_spinlock_t report_lock;
+
+static void rqspinlock_report_violation(const char *s, void *lock)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (this_cpu_inc_return(report_nest_cnt) != 1) {
+		this_cpu_dec(report_nest_cnt);
+		return;
+	}
+	if (this_cpu_read(report_flag))
+		goto end;
+	this_cpu_write(report_flag, true);
+	arch_spin_lock(&report_lock);
+
+	pr_err("CPU %d: %s", smp_processor_id(), s);
+	pr_info("Held locks: %d\n", rqh->cnt + 1);
+	pr_info("Held lock[%2d] = 0x%px\n", 0, lock);
+	for (int i = 0; i < min(RES_NR_HELD, rqh->cnt); i++)
+		pr_info("Held lock[%2d] = 0x%px\n", i + 1, rqh->locks[i]);
+	dump_stack();
+
+	arch_spin_unlock(&report_lock);
+end:
+	this_cpu_dec(report_nest_cnt);
+}
+
 static noinline int check_deadlock(rqspinlock_t *lock, u32 mask,
 				   struct rqspinlock_timeout *ts)
 {
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:32 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:32 -0700
Subject: [PATCH bpf-next v4 16/25] rqspinlock: Add macros for rqspinlock usage
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-17-memxor@gmail.com>

Introduce helper macros that wrap around the rqspinlock slow path and
provide an interface analogous to the raw_spin_lock API. Note that
in case of error conditions, preemption and IRQ disabling is
automatically unrolled before returning the error back to the caller.

Ensure that in absence of CONFIG_QUEUED_SPINLOCKS support, we fallback
to the test-and-set implementation.

Add some comments describing the subtle memory ordering logic during
unlock, and why it's safe.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 87 ++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index a837c6b6abd9..23abd0b8d0f9 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -153,4 +153,91 @@ static __always_inline void release_held_lock_entry(void)
 	this_cpu_dec(rqspinlock_held_locks.cnt);
 }
 
+#ifdef CONFIG_QUEUED_SPINLOCKS
+
+/**
+ * res_spin_lock - acquire a queued spinlock
+ * @lock: Pointer to queued spinlock structure
+ *
+ * Return:
+ * * 0		- Lock was acquired successfully.
+ * * -EDEADLK	- Lock acquisition failed because of AA/ABBA deadlock.
+ * * -ETIMEDOUT - Lock acquisition failed because of timeout.
+ */
+static __always_inline int res_spin_lock(rqspinlock_t *lock)
+{
+	int val = 0;
+
+	if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL))) {
+		grab_held_lock_entry(lock);
+		return 0;
+	}
+	return resilient_queued_spin_lock_slowpath(lock, val);
+}
+
+#else
+
+#define res_spin_lock(lock) resilient_tas_spin_lock(lock)
+
+#endif /* CONFIG_QUEUED_SPINLOCKS */
+
+static __always_inline void res_spin_unlock(rqspinlock_t *lock)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (unlikely(rqh->cnt > RES_NR_HELD))
+		goto unlock;
+	WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL);
+unlock:
+	/*
+	 * Release barrier, ensures correct ordering. See release_held_lock_entry
+	 * for details.  Perform release store instead of queued_spin_unlock,
+	 * since we use this function for test-and-set fallback as well. When we
+	 * have CONFIG_QUEUED_SPINLOCKS=n, we clear the full 4-byte lockword.
+	 *
+	 * Like release_held_lock_entry, we can do the release before the dec.
+	 * We simply care about not seeing the 'lock' in our table from a remote
+	 * CPU once the lock has been released, which doesn't rely on the dec.
+	 *
+	 * Unlike smp_wmb(), release is not a two way fence, hence it is
+	 * possible for a inc to move up and reorder with our clearing of the
+	 * entry. This isn't a problem however, as for a misdiagnosis of ABBA,
+	 * the remote CPU needs to hold this lock, which won't be released until
+	 * the store below is done, which would ensure the entry is overwritten
+	 * to NULL, etc.
+	 */
+	smp_store_release(&lock->locked, 0);
+	this_cpu_dec(rqspinlock_held_locks.cnt);
+}
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+#define raw_res_spin_lock_init(lock) ({ *(lock) = (rqspinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; })
+#else
+#define raw_res_spin_lock_init(lock) ({ *(lock) = (rqspinlock_t){0}; })
+#endif
+
+#define raw_res_spin_lock(lock)                    \
+	({                                         \
+		int __ret;                         \
+		preempt_disable();                 \
+		__ret = res_spin_lock(lock);	   \
+		if (__ret)                         \
+			preempt_enable();          \
+		__ret;                             \
+	})
+
+#define raw_res_spin_unlock(lock) ({ res_spin_unlock(lock); preempt_enable(); })
+
+#define raw_res_spin_lock_irqsave(lock, flags)    \
+	({                                        \
+		int __ret;                        \
+		local_irq_save(flags);            \
+		__ret = raw_res_spin_lock(lock);  \
+		if (__ret)                        \
+			local_irq_restore(flags); \
+		__ret;                            \
+	})
+
+#define raw_res_spin_unlock_irqrestore(lock, flags) ({ raw_res_spin_unlock(lock); local_irq_restore(flags); })
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:33 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:33 -0700
Subject: [PATCH bpf-next v4 17/25] rqspinlock: Add entry to Makefile, MAINTAINERS
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-18-memxor@gmail.com>

Ensure that the rqspinlock code is only built when the BPF subsystem is
compiled in. Depending on queued spinlock support, we may or may not end
up building the queued spinlock slowpath, and instead fallback to the
test-and-set implementation. Also add entries to MAINTAINERS file.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 MAINTAINERS                | 2 ++
 include/asm-generic/Kbuild | 1 +
 kernel/bpf/Makefile        | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3864d473f52f..c545cd149cd1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4297,6 +4297,8 @@ F:	include/uapi/linux/filter.h
 F:	kernel/bpf/
 F:	kernel/trace/bpf_trace.c
 F:	lib/buildid.c
+F:	arch/*/include/asm/rqspinlock.h
+F:	include/asm-generic/rqspinlock.h
 F:	lib/test_bpf.c
 F:	net/bpf/
 F:	net/core/filter.c
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index 1b43c3a77012..8675b7b4ad23 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -45,6 +45,7 @@ mandatory-y += pci.h
 mandatory-y += percpu.h
 mandatory-y += pgalloc.h
 mandatory-y += preempt.h
+mandatory-y += rqspinlock.h
 mandatory-y += runtime-const.h
 mandatory-y += rwonce.h
 mandatory-y += sections.h
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 410028633621..70502f038b92 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o
 obj-${CONFIG_BPF_LSM}	  += bpf_inode_storage.o
 obj-$(CONFIG_BPF_SYSCALL) += disasm.o mprog.o
 obj-$(CONFIG_BPF_JIT) += trampoline.o
-obj-$(CONFIG_BPF_SYSCALL) += btf.o memalloc.o
+obj-$(CONFIG_BPF_SYSCALL) += btf.o memalloc.o rqspinlock.o
 ifeq ($(CONFIG_MMU)$(CONFIG_64BIT),yy)
 obj-$(CONFIG_BPF_SYSCALL) += arena.o range_tree.o
 endif
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:34 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:34 -0700
Subject: [PATCH bpf-next v4 18/25] rqspinlock: Add locktorture support
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-19-memxor@gmail.com>

Introduce locktorture support for rqspinlock using the newly added
macros as the first in-kernel user and consumer. Guard the code with
CONFIG_BPF_SYSCALL ifdef since rqspinlock is not available otherwise.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/locktorture.c | 57 ++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index cc33470f4de9..ce0362f0a871 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -362,6 +362,60 @@ static struct lock_torture_ops raw_spin_lock_irq_ops = {
 	.name		= "raw_spin_lock_irq"
 };
 
+#ifdef CONFIG_BPF_SYSCALL
+
+#include <asm/rqspinlock.h>
+static rqspinlock_t rqspinlock;
+
+static int torture_raw_res_spin_write_lock(int tid __maybe_unused)
+{
+	raw_res_spin_lock(&rqspinlock);
+	return 0;
+}
+
+static void torture_raw_res_spin_write_unlock(int tid __maybe_unused)
+{
+	raw_res_spin_unlock(&rqspinlock);
+}
+
+static struct lock_torture_ops raw_res_spin_lock_ops = {
+	.writelock	= torture_raw_res_spin_write_lock,
+	.write_delay	= torture_spin_lock_write_delay,
+	.task_boost     = torture_rt_boost,
+	.writeunlock	= torture_raw_res_spin_write_unlock,
+	.readlock       = NULL,
+	.read_delay     = NULL,
+	.readunlock     = NULL,
+	.name		= "raw_res_spin_lock"
+};
+
+static int torture_raw_res_spin_write_lock_irq(int tid __maybe_unused)
+{
+	unsigned long flags;
+
+	raw_res_spin_lock_irqsave(&rqspinlock, flags);
+	cxt.cur_ops->flags = flags;
+	return 0;
+}
+
+static void torture_raw_res_spin_write_unlock_irq(int tid __maybe_unused)
+{
+	raw_res_spin_unlock_irqrestore(&rqspinlock, cxt.cur_ops->flags);
+}
+
+static struct lock_torture_ops raw_res_spin_lock_irq_ops = {
+	.writelock	= torture_raw_res_spin_write_lock_irq,
+	.write_delay	= torture_spin_lock_write_delay,
+	.task_boost     = torture_rt_boost,
+	.writeunlock	= torture_raw_res_spin_write_unlock_irq,
+	.readlock       = NULL,
+	.read_delay     = NULL,
+	.readunlock     = NULL,
+	.name		= "raw_res_spin_lock_irq"
+};
+
+#endif
+
 static DEFINE_RWLOCK(torture_rwlock);
 
 static int torture_rwlock_write_lock(int tid __maybe_unused)
@@ -1168,6 +1222,9 @@ static int __init lock_torture_init(void)
 		&lock_busted_ops,
 		&spin_lock_ops, &spin_lock_irq_ops,
 		&raw_spin_lock_ops, &raw_spin_lock_irq_ops,
+#ifdef CONFIG_BPF_SYSCALL
+		&raw_res_spin_lock_ops, &raw_res_spin_lock_irq_ops,
+#endif
 		&rw_lock_ops, &rw_lock_irq_ops,
 		&mutex_lock_ops,
 		&ww_mutex_lock_ops,
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:35 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:35 -0700
Subject: [PATCH bpf-next v4 19/25] bpf: Convert hashtab.c to rqspinlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-20-memxor@gmail.com>

Convert hashtab.c from raw_spinlock to rqspinlock, and drop the hashed
per-cpu counter crud from the code base which is no longer necessary.

Closes: https://lore.kernel.org/bpf/675302fd.050a0220.2477f.0004.GAE at google.com
Closes: https://lore.kernel.org/bpf/000000000000b3e63e061eed3f6b at google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/hashtab.c | 102 ++++++++++++++-----------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)

diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 877298133fda..5a5adc66b8e2 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -16,6 +16,7 @@
 #include "bpf_lru_list.h"
 #include "map_in_map.h"
 #include <linux/bpf_mem_alloc.h>
+#include <asm/rqspinlock.h>
 
 #define HTAB_CREATE_FLAG_MASK						\
 	(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE |	\
@@ -78,7 +79,7 @@
  */
 struct bucket {
 	struct hlist_nulls_head head;
-	raw_spinlock_t raw_lock;
+	rqspinlock_t raw_lock;
 };
 
 #define HASHTAB_MAP_LOCK_COUNT 8
@@ -104,8 +105,6 @@ struct bpf_htab {
 	u32 n_buckets;	/* number of hash buckets */
 	u32 elem_size;	/* size of each element in bytes */
 	u32 hashrnd;
-	struct lock_class_key lockdep_key;
-	int __percpu *map_locked[HASHTAB_MAP_LOCK_COUNT];
 };
 
 /* each htab element is struct htab_elem + key + value */
@@ -140,45 +139,26 @@ static void htab_init_buckets(struct bpf_htab *htab)
 
 	for (i = 0; i < htab->n_buckets; i++) {
 		INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
-		raw_spin_lock_init(&htab->buckets[i].raw_lock);
-		lockdep_set_class(&htab->buckets[i].raw_lock,
-					  &htab->lockdep_key);
+		raw_res_spin_lock_init(&htab->buckets[i].raw_lock);
 		cond_resched();
 	}
 }
 
-static inline int htab_lock_bucket(const struct bpf_htab *htab,
-				   struct bucket *b, u32 hash,
-				   unsigned long *pflags)
+static inline int htab_lock_bucket(struct bucket *b, unsigned long *pflags)
 {
 	unsigned long flags;
+	int ret;
 
-	hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
-
-	preempt_disable();
-	local_irq_save(flags);
-	if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) {
-		__this_cpu_dec(*(htab->map_locked[hash]));
-		local_irq_restore(flags);
-		preempt_enable();
-		return -EBUSY;
-	}
-
-	raw_spin_lock(&b->raw_lock);
+	ret = raw_res_spin_lock_irqsave(&b->raw_lock, flags);
+	if (ret)
+		return ret;
 	*pflags = flags;
-
 	return 0;
 }
 
-static inline void htab_unlock_bucket(const struct bpf_htab *htab,
-				      struct bucket *b, u32 hash,
-				      unsigned long flags)
+static inline void htab_unlock_bucket(struct bucket *b, unsigned long flags)
 {
-	hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
-	raw_spin_unlock(&b->raw_lock);
-	__this_cpu_dec(*(htab->map_locked[hash]));
-	local_irq_restore(flags);
-	preempt_enable();
+	raw_res_spin_unlock_irqrestore(&b->raw_lock, flags);
 }
 
 static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node);
@@ -483,14 +463,12 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 	bool percpu_lru = (attr->map_flags & BPF_F_NO_COMMON_LRU);
 	bool prealloc = !(attr->map_flags & BPF_F_NO_PREALLOC);
 	struct bpf_htab *htab;
-	int err, i;
+	int err;
 
 	htab = bpf_map_area_alloc(sizeof(*htab), NUMA_NO_NODE);
 	if (!htab)
 		return ERR_PTR(-ENOMEM);
 
-	lockdep_register_key(&htab->lockdep_key);
-
 	bpf_map_init_from_attr(&htab->map, attr);
 
 	if (percpu_lru) {
@@ -536,15 +514,6 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 	if (!htab->buckets)
 		goto free_elem_count;
 
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++) {
-		htab->map_locked[i] = bpf_map_alloc_percpu(&htab->map,
-							   sizeof(int),
-							   sizeof(int),
-							   GFP_USER);
-		if (!htab->map_locked[i])
-			goto free_map_locked;
-	}
-
 	if (htab->map.map_flags & BPF_F_ZERO_SEED)
 		htab->hashrnd = 0;
 	else
@@ -607,15 +576,12 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 free_map_locked:
 	if (htab->use_percpu_counter)
 		percpu_counter_destroy(&htab->pcount);
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++)
-		free_percpu(htab->map_locked[i]);
 	bpf_map_area_free(htab->buckets);
 	bpf_mem_alloc_destroy(&htab->pcpu_ma);
 	bpf_mem_alloc_destroy(&htab->ma);
 free_elem_count:
 	bpf_map_free_elem_count(&htab->map);
 free_htab:
-	lockdep_unregister_key(&htab->lockdep_key);
 	bpf_map_area_free(htab);
 	return ERR_PTR(err);
 }
@@ -820,7 +786,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 	b = __select_bucket(htab, tgt_l->hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, tgt_l->hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return false;
 
@@ -831,7 +797,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 			break;
 		}
 
-	htab_unlock_bucket(htab, b, tgt_l->hash, flags);
+	htab_unlock_bucket(b, flags);
 
 	if (l == tgt_l)
 		check_and_free_fields(htab, l);
@@ -1150,7 +1116,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 		 */
 	}
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1201,7 +1167,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 			check_and_free_fields(htab, l_old);
 		}
 	}
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	if (l_old) {
 		if (old_map_ptr)
 			map->ops->map_fd_put_ptr(map, old_map_ptr, true);
@@ -1210,7 +1176,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 	}
 	return 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	return ret;
 }
 
@@ -1257,7 +1223,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 	copy_map_value(&htab->map,
 		       l_new->key + round_up(map->key_size, 8), value);
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		goto err_lock_bucket;
 
@@ -1278,7 +1244,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 	ret = 0;
 
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 
 err_lock_bucket:
 	if (ret)
@@ -1315,7 +1281,7 @@ static long __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1340,7 +1306,7 @@ static long __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
 	}
 	ret = 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	return ret;
 }
 
@@ -1381,7 +1347,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 			return -ENOMEM;
 	}
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		goto err_lock_bucket;
 
@@ -1405,7 +1371,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 	}
 	ret = 0;
 err:
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 err_lock_bucket:
 	if (l_new) {
 		bpf_map_dec_elem_count(&htab->map);
@@ -1447,7 +1413,7 @@ static long htab_map_delete_elem(struct bpf_map *map, void *key)
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1457,7 +1423,7 @@ static long htab_map_delete_elem(struct bpf_map *map, void *key)
 	else
 		ret = -ENOENT;
 
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 
 	if (l)
 		free_htab_elem(htab, l);
@@ -1483,7 +1449,7 @@ static long htab_lru_map_delete_elem(struct bpf_map *map, void *key)
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &flags);
+	ret = htab_lock_bucket(b, &flags);
 	if (ret)
 		return ret;
 
@@ -1494,7 +1460,7 @@ static long htab_lru_map_delete_elem(struct bpf_map *map, void *key)
 	else
 		ret = -ENOENT;
 
-	htab_unlock_bucket(htab, b, hash, flags);
+	htab_unlock_bucket(b, flags);
 	if (l)
 		htab_lru_push_free(htab, l);
 	return ret;
@@ -1561,7 +1527,6 @@ static void htab_map_free_timers_and_wq(struct bpf_map *map)
 static void htab_map_free(struct bpf_map *map)
 {
 	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-	int i;
 
 	/* bpf_free_used_maps() or close(map_fd) will trigger this map_free callback.
 	 * bpf_free_used_maps() is called after bpf prog is no longer executing.
@@ -1586,9 +1551,6 @@ static void htab_map_free(struct bpf_map *map)
 	bpf_mem_alloc_destroy(&htab->ma);
 	if (htab->use_percpu_counter)
 		percpu_counter_destroy(&htab->pcount);
-	for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++)
-		free_percpu(htab->map_locked[i]);
-	lockdep_unregister_key(&htab->lockdep_key);
 	bpf_map_area_free(htab);
 }
 
@@ -1631,7 +1593,7 @@ static int __htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key,
 	b = __select_bucket(htab, hash);
 	head = &b->head;
 
-	ret = htab_lock_bucket(htab, b, hash, &bflags);
+	ret = htab_lock_bucket(b, &bflags);
 	if (ret)
 		return ret;
 
@@ -1668,7 +1630,7 @@ static int __htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key,
 	hlist_nulls_del_rcu(&l->hash_node);
 
 out_unlock:
-	htab_unlock_bucket(htab, b, hash, bflags);
+	htab_unlock_bucket(b, bflags);
 
 	if (l) {
 		if (is_lru_map)
@@ -1790,7 +1752,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 	head = &b->head;
 	/* do not grab the lock unless need it (bucket_cnt > 0). */
 	if (locked) {
-		ret = htab_lock_bucket(htab, b, batch, &flags);
+		ret = htab_lock_bucket(b, &flags);
 		if (ret) {
 			rcu_read_unlock();
 			bpf_enable_instrumentation();
@@ -1813,7 +1775,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		/* Note that since bucket_cnt > 0 here, it is implicit
 		 * that the locked was grabbed, so release it.
 		 */
-		htab_unlock_bucket(htab, b, batch, flags);
+		htab_unlock_bucket(b, flags);
 		rcu_read_unlock();
 		bpf_enable_instrumentation();
 		goto after_loop;
@@ -1824,7 +1786,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		/* Note that since bucket_cnt > 0 here, it is implicit
 		 * that the locked was grabbed, so release it.
 		 */
-		htab_unlock_bucket(htab, b, batch, flags);
+		htab_unlock_bucket(b, flags);
 		rcu_read_unlock();
 		bpf_enable_instrumentation();
 		kvfree(keys);
@@ -1887,7 +1849,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
 		dst_val += value_size;
 	}
 
-	htab_unlock_bucket(htab, b, batch, flags);
+	htab_unlock_bucket(b, flags);
 	locked = false;
 
 	while (node_to_free) {
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:36 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:36 -0700
Subject: [PATCH bpf-next v4 20/25] bpf: Convert percpu_freelist.c to rqspinlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-21-memxor@gmail.com>

Convert the percpu_freelist.c code to use rqspinlock, and remove the
extralist fallback and trylock-based acquisitions to avoid deadlocks.

Key thing to note is the retained while (true) loop to search through
other CPUs when failing to push a node due to locking errors. This
retains the behavior of the old code, where it would keep trying until
it would be able to successfully push the node back into the freelist of
a CPU.

Technically, we should start iteration for this loop from
raw_smp_processor_id() + 1, but to avoid hitting the edge of nr_cpus,
we skip execution in the loop body instead.

Closes: https://lore.kernel.org/bpf/CAPPBnEa1_pZ6W24+WwtcNFvTUHTHO7KUmzEbOcMqxp+m2o15qQ at mail.gmail.com
Closes: https://lore.kernel.org/bpf/CAPPBnEYm+9zduStsZaDnq93q1jPLqO-PiKX9jy0MuL8LCXmCrQ at mail.gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/percpu_freelist.c | 113 ++++++++---------------------------
 kernel/bpf/percpu_freelist.h |   4 +-
 2 files changed, 27 insertions(+), 90 deletions(-)

diff --git a/kernel/bpf/percpu_freelist.c b/kernel/bpf/percpu_freelist.c
index 034cf87b54e9..632762b57299 100644
--- a/kernel/bpf/percpu_freelist.c
+++ b/kernel/bpf/percpu_freelist.c
@@ -14,11 +14,9 @@ int pcpu_freelist_init(struct pcpu_freelist *s)
 	for_each_possible_cpu(cpu) {
 		struct pcpu_freelist_head *head = per_cpu_ptr(s->freelist, cpu);
 
-		raw_spin_lock_init(&head->lock);
+		raw_res_spin_lock_init(&head->lock);
 		head->first = NULL;
 	}
-	raw_spin_lock_init(&s->extralist.lock);
-	s->extralist.first = NULL;
 	return 0;
 }
 
@@ -34,58 +32,39 @@ static inline void pcpu_freelist_push_node(struct pcpu_freelist_head *head,
 	WRITE_ONCE(head->first, node);
 }
 
-static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
+static inline bool ___pcpu_freelist_push(struct pcpu_freelist_head *head,
 					 struct pcpu_freelist_node *node)
 {
-	raw_spin_lock(&head->lock);
-	pcpu_freelist_push_node(head, node);
-	raw_spin_unlock(&head->lock);
-}
-
-static inline bool pcpu_freelist_try_push_extra(struct pcpu_freelist *s,
-						struct pcpu_freelist_node *node)
-{
-	if (!raw_spin_trylock(&s->extralist.lock))
+	if (raw_res_spin_lock(&head->lock))
 		return false;
-
-	pcpu_freelist_push_node(&s->extralist, node);
-	raw_spin_unlock(&s->extralist.lock);
+	pcpu_freelist_push_node(head, node);
+	raw_res_spin_unlock(&head->lock);
 	return true;
 }
 
-static inline void ___pcpu_freelist_push_nmi(struct pcpu_freelist *s,
-					     struct pcpu_freelist_node *node)
+void __pcpu_freelist_push(struct pcpu_freelist *s,
+			struct pcpu_freelist_node *node)
 {
-	int cpu, orig_cpu;
+	struct pcpu_freelist_head *head;
+	int cpu;
 
-	orig_cpu = raw_smp_processor_id();
-	while (1) {
-		for_each_cpu_wrap(cpu, cpu_possible_mask, orig_cpu) {
-			struct pcpu_freelist_head *head;
+	if (___pcpu_freelist_push(this_cpu_ptr(s->freelist), node))
+		return;
 
+	while (true) {
+		for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
+			if (cpu == raw_smp_processor_id())
+				continue;
 			head = per_cpu_ptr(s->freelist, cpu);
-			if (raw_spin_trylock(&head->lock)) {
-				pcpu_freelist_push_node(head, node);
-				raw_spin_unlock(&head->lock);
-				return;
-			}
-		}
-
-		/* cannot lock any per cpu lock, try extralist */
-		if (pcpu_freelist_try_push_extra(s, node))
+			if (raw_res_spin_lock(&head->lock))
+				continue;
+			pcpu_freelist_push_node(head, node);
+			raw_res_spin_unlock(&head->lock);
 			return;
+		}
 	}
 }
 
-void __pcpu_freelist_push(struct pcpu_freelist *s,
-			struct pcpu_freelist_node *node)
-{
-	if (in_nmi())
-		___pcpu_freelist_push_nmi(s, node);
-	else
-		___pcpu_freelist_push(this_cpu_ptr(s->freelist), node);
-}
-
 void pcpu_freelist_push(struct pcpu_freelist *s,
 			struct pcpu_freelist_node *node)
 {
@@ -120,71 +99,29 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
 
 static struct pcpu_freelist_node *___pcpu_freelist_pop(struct pcpu_freelist *s)
 {
+	struct pcpu_freelist_node *node = NULL;
 	struct pcpu_freelist_head *head;
-	struct pcpu_freelist_node *node;
 	int cpu;
 
 	for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
 		head = per_cpu_ptr(s->freelist, cpu);
 		if (!READ_ONCE(head->first))
 			continue;
-		raw_spin_lock(&head->lock);
+		if (raw_res_spin_lock(&head->lock))
+			continue;
 		node = head->first;
 		if (node) {
 			WRITE_ONCE(head->first, node->next);
-			raw_spin_unlock(&head->lock);
+			raw_res_spin_unlock(&head->lock);
 			return node;
 		}
-		raw_spin_unlock(&head->lock);
+		raw_res_spin_unlock(&head->lock);
 	}
-
-	/* per cpu lists are all empty, try extralist */
-	if (!READ_ONCE(s->extralist.first))
-		return NULL;
-	raw_spin_lock(&s->extralist.lock);
-	node = s->extralist.first;
-	if (node)
-		WRITE_ONCE(s->extralist.first, node->next);
-	raw_spin_unlock(&s->extralist.lock);
-	return node;
-}
-
-static struct pcpu_freelist_node *
-___pcpu_freelist_pop_nmi(struct pcpu_freelist *s)
-{
-	struct pcpu_freelist_head *head;
-	struct pcpu_freelist_node *node;
-	int cpu;
-
-	for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
-		head = per_cpu_ptr(s->freelist, cpu);
-		if (!READ_ONCE(head->first))
-			continue;
-		if (raw_spin_trylock(&head->lock)) {
-			node = head->first;
-			if (node) {
-				WRITE_ONCE(head->first, node->next);
-				raw_spin_unlock(&head->lock);
-				return node;
-			}
-			raw_spin_unlock(&head->lock);
-		}
-	}
-
-	/* cannot pop from per cpu lists, try extralist */
-	if (!READ_ONCE(s->extralist.first) || !raw_spin_trylock(&s->extralist.lock))
-		return NULL;
-	node = s->extralist.first;
-	if (node)
-		WRITE_ONCE(s->extralist.first, node->next);
-	raw_spin_unlock(&s->extralist.lock);
 	return node;
 }
 
 struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
 {
-	if (in_nmi())
-		return ___pcpu_freelist_pop_nmi(s);
 	return ___pcpu_freelist_pop(s);
 }
 
diff --git a/kernel/bpf/percpu_freelist.h b/kernel/bpf/percpu_freelist.h
index 3c76553cfe57..914798b74967 100644
--- a/kernel/bpf/percpu_freelist.h
+++ b/kernel/bpf/percpu_freelist.h
@@ -5,15 +5,15 @@
 #define __PERCPU_FREELIST_H__
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
+#include <asm/rqspinlock.h>
 
 struct pcpu_freelist_head {
 	struct pcpu_freelist_node *first;
-	raw_spinlock_t lock;
+	rqspinlock_t lock;
 };
 
 struct pcpu_freelist {
 	struct pcpu_freelist_head __percpu *freelist;
-	struct pcpu_freelist_head extralist;
 };
 
 struct pcpu_freelist_node {
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:37 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:37 -0700
Subject: [PATCH bpf-next v4 21/25] bpf: Convert lpm_trie.c to rqspinlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-22-memxor@gmail.com>

Convert all LPM trie usage of raw_spinlock to rqspinlock.

Note that rcu_dereference_protected in trie_delete_elem is switched over
to plain rcu_dereference, the RCU read lock should be held from BPF
program side or eBPF syscall path, and the trie->lock is just acquired
before the dereference. It is not clear the reason the protected variant
was used from the commit history, but the above reasoning makes sense so
switch over.

Closes: https://lore.kernel.org/lkml/000000000000adb08b061413919e at google.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/lpm_trie.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index e8a772e64324..be66d7e520e0 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -15,6 +15,7 @@
 #include <net/ipv6.h>
 #include <uapi/linux/btf.h>
 #include <linux/btf_ids.h>
+#include <asm/rqspinlock.h>
 #include <linux/bpf_mem_alloc.h>
 
 /* Intermediate node */
@@ -36,7 +37,7 @@ struct lpm_trie {
 	size_t				n_entries;
 	size_t				max_prefixlen;
 	size_t				data_size;
-	raw_spinlock_t			lock;
+	rqspinlock_t			lock;
 };
 
 /* This trie implements a longest prefix match algorithm that can be used to
@@ -342,7 +343,9 @@ static long trie_update_elem(struct bpf_map *map,
 	if (!new_node)
 		return -ENOMEM;
 
-	raw_spin_lock_irqsave(&trie->lock, irq_flags);
+	ret = raw_res_spin_lock_irqsave(&trie->lock, irq_flags);
+	if (ret)
+		goto out_free;
 
 	new_node->prefixlen = key->prefixlen;
 	RCU_INIT_POINTER(new_node->child[0], NULL);
@@ -356,8 +359,7 @@ static long trie_update_elem(struct bpf_map *map,
 	 */
 	slot = &trie->root;
 
-	while ((node = rcu_dereference_protected(*slot,
-					lockdep_is_held(&trie->lock)))) {
+	while ((node = rcu_dereference(*slot))) {
 		matchlen = longest_prefix_match(trie, node, key);
 
 		if (node->prefixlen != matchlen ||
@@ -442,8 +444,8 @@ static long trie_update_elem(struct bpf_map *map,
 	rcu_assign_pointer(*slot, im_node);
 
 out:
-	raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
-
+	raw_res_spin_unlock_irqrestore(&trie->lock, irq_flags);
+out_free:
 	if (ret)
 		bpf_mem_cache_free(&trie->ma, new_node);
 	bpf_mem_cache_free_rcu(&trie->ma, free_node);
@@ -467,7 +469,9 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	if (key->prefixlen > trie->max_prefixlen)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&trie->lock, irq_flags);
+	ret = raw_res_spin_lock_irqsave(&trie->lock, irq_flags);
+	if (ret)
+		return ret;
 
 	/* Walk the tree looking for an exact key/length match and keeping
 	 * track of the path we traverse.  We will need to know the node
@@ -478,8 +482,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	trim = &trie->root;
 	trim2 = trim;
 	parent = NULL;
-	while ((node = rcu_dereference_protected(
-		       *trim, lockdep_is_held(&trie->lock)))) {
+	while ((node = rcu_dereference(*trim))) {
 		matchlen = longest_prefix_match(trie, node, key);
 
 		if (node->prefixlen != matchlen ||
@@ -543,7 +546,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
 	free_node = node;
 
 out:
-	raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
+	raw_res_spin_unlock_irqrestore(&trie->lock, irq_flags);
 
 	bpf_mem_cache_free_rcu(&trie->ma, free_parent);
 	bpf_mem_cache_free_rcu(&trie->ma, free_node);
@@ -592,7 +595,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
 			  offsetof(struct bpf_lpm_trie_key_u8, data);
 	trie->max_prefixlen = trie->data_size * 8;
 
-	raw_spin_lock_init(&trie->lock);
+	raw_res_spin_lock_init(&trie->lock);
 
 	/* Allocate intermediate and leaf nodes from the same allocator */
 	leaf_size = sizeof(struct lpm_trie_node) + trie->data_size +
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:38 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:38 -0700
Subject: [PATCH bpf-next v4 22/25] bpf: Introduce rqspinlock kfuncs
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-23-memxor@gmail.com>

Introduce four new kfuncs, bpf_res_spin_lock, and bpf_res_spin_unlock,
and their irqsave/irqrestore variants, which wrap the rqspinlock APIs.
bpf_res_spin_lock returns a conditional result, depending on whether the
lock was acquired (NULL is returned when lock acquisition succeeds,
non-NULL upon failure). The memory pointed to by the returned pointer
upon failure can be dereferenced after the NULL check to obtain the
error code.

Instead of using the old bpf_spin_lock type, introduce a new type with
the same layout, and the same alignment, but a different name to avoid
type confusion.

Preemption is disabled upon successful lock acquisition, however IRQs
are not. Special kfuncs can be introduced later to allow disabling IRQs
when taking a spin lock. Resilient locks are safe against AA deadlocks,
hence not disabling IRQs currently does not allow violation of kernel
safety.

__irq_flag annotation is used to accept IRQ flags for the IRQ-variants,
with the same semantics as existing bpf_local_irq_{save, restore}.

These kfuncs will require additional verifier-side support in subsequent
commits, to allow programs to hold multiple locks at the same time.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h |  7 +++
 include/linux/bpf.h              |  1 +
 kernel/bpf/rqspinlock.c          | 78 ++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 23abd0b8d0f9..6d4244d643df 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -23,6 +23,13 @@ struct rqspinlock {
 	};
 };
 
+/* Even though this is same as struct rqspinlock, we need to emit a distinct
+ * type in BTF for BPF programs.
+ */
+struct bpf_res_spin_lock {
+	u32 val;
+};
+
 struct qspinlock;
 #ifdef CONFIG_QUEUED_SPINLOCKS
 typedef struct qspinlock rqspinlock_t;
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 0d7b70124d81..a6bc687d6300 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -30,6 +30,7 @@
 #include <linux/static_call.h>
 #include <linux/memcontrol.h>
 #include <linux/cfi.h>
+#include <asm/rqspinlock.h>
 
 struct bpf_verifier_env;
 struct bpf_verifier_log;
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index ad0fc35c647e..cf417a736559 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -15,6 +15,8 @@
 
 #include <linux/smp.h>
 #include <linux/bug.h>
+#include <linux/bpf.h>
+#include <linux/err.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
@@ -690,3 +692,79 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
 
 #endif /* CONFIG_QUEUED_SPINLOCKS */
+
+__bpf_kfunc_start_defs();
+
+#define REPORT_STR(ret) ({ ret == -ETIMEDOUT ? "Timeout detected" : "AA or ABBA deadlock detected"; })
+
+__bpf_kfunc int bpf_res_spin_lock(struct bpf_res_spin_lock *lock)
+{
+	int ret;
+
+	BUILD_BUG_ON(sizeof(rqspinlock_t) != sizeof(struct bpf_res_spin_lock));
+	BUILD_BUG_ON(__alignof__(rqspinlock_t) != __alignof__(struct bpf_res_spin_lock));
+
+	preempt_disable();
+	ret = res_spin_lock((rqspinlock_t *)lock);
+	if (unlikely(ret)) {
+		preempt_enable();
+		rqspinlock_report_violation(REPORT_STR(ret), lock);
+		return ret;
+	}
+	return 0;
+}
+
+__bpf_kfunc void bpf_res_spin_unlock(struct bpf_res_spin_lock *lock)
+{
+	res_spin_unlock((rqspinlock_t *)lock);
+	preempt_enable();
+}
+
+__bpf_kfunc int bpf_res_spin_lock_irqsave(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag)
+{
+	u64 *ptr = (u64 *)flags__irq_flag;
+	unsigned long flags;
+	int ret;
+
+	preempt_disable();
+	local_irq_save(flags);
+	ret = res_spin_lock((rqspinlock_t *)lock);
+	if (unlikely(ret)) {
+		local_irq_restore(flags);
+		preempt_enable();
+		rqspinlock_report_violation(REPORT_STR(ret), lock);
+		return ret;
+	}
+	*ptr = flags;
+	return 0;
+}
+
+__bpf_kfunc void bpf_res_spin_unlock_irqrestore(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag)
+{
+	u64 *ptr = (u64 *)flags__irq_flag;
+	unsigned long flags = *ptr;
+
+	res_spin_unlock((rqspinlock_t *)lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+
+__bpf_kfunc_end_defs();
+
+BTF_KFUNCS_START(rqspinlock_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_res_spin_lock, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_res_spin_unlock)
+BTF_ID_FLAGS(func, bpf_res_spin_lock_irqsave, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_res_spin_unlock_irqrestore)
+BTF_KFUNCS_END(rqspinlock_kfunc_ids)
+
+static const struct btf_kfunc_id_set rqspinlock_kfunc_set = {
+	.owner = THIS_MODULE,
+	.set = &rqspinlock_kfunc_ids,
+};
+
+static __init int rqspinlock_register_kfuncs(void)
+{
+	return register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, &rqspinlock_kfunc_set);
+}
+late_initcall(rqspinlock_register_kfuncs);
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:39 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:39 -0700
Subject: [PATCH bpf-next v4 23/25] bpf: Implement verifier support for rqspinlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-24-memxor@gmail.com>

Introduce verifier-side support for rqspinlock kfuncs. The first step is
allowing bpf_res_spin_lock type to be defined in map values and
allocated objects, so BTF-side is updated with a new BPF_RES_SPIN_LOCK
field to recognize and validate.

Any object cannot have both bpf_spin_lock and bpf_res_spin_lock, only
one of them (and at most one of them per-object, like before) must be
present. The bpf_res_spin_lock can also be used to protect objects that
require lock protection for their kfuncs, like BPF rbtree and linked
list.

The verifier plumbing to simulate success and failure cases when calling
the kfuncs is done by pushing a new verifier state to the verifier state
stack which will verify the failure case upon calling the kfunc. The
path where success is indicated creates all lock reference state and IRQ
state (if necessary for irqsave variants). In the case of failure, the
state clears the registers r0-r5, sets the return value, and skips kfunc
processing, proceeding to the next instruction.

When marking the return value for success case, the value is marked as
0, and for the failure case as [-MAX_ERRNO, -1]. Then, in the program,
whenever user checks the return value as 'if (ret)' or 'if (ret < 0)'
the verifier never traverses such branches for success cases, and would
be aware that the lock is not held in such cases.

We push the kfunc state in check_kfunc_call whenever rqspinlock kfuncs
are invoked. We introduce a kfunc_class state to avoid mixing lock
irqrestore kfuncs with IRQ state created by bpf_local_irq_save.

With all this infrastructure, these kfuncs become usable in programs
while satisfying all safety properties required by the kernel.

Acked-by: Eduard Zingerman <eddyz87 at gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/linux/bpf.h          |   9 ++
 include/linux/bpf_verifier.h |  16 ++-
 kernel/bpf/btf.c             |  26 ++++-
 kernel/bpf/syscall.c         |   6 +-
 kernel/bpf/verifier.c        | 219 ++++++++++++++++++++++++++++-------
 5 files changed, 231 insertions(+), 45 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index a6bc687d6300..c59384f62da0 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -205,6 +205,7 @@ enum btf_field_type {
 	BPF_REFCOUNT   = (1 << 9),
 	BPF_WORKQUEUE  = (1 << 10),
 	BPF_UPTR       = (1 << 11),
+	BPF_RES_SPIN_LOCK = (1 << 12),
 };
 
 typedef void (*btf_dtor_kfunc_t)(void *);
@@ -240,6 +241,7 @@ struct btf_record {
 	u32 cnt;
 	u32 field_mask;
 	int spin_lock_off;
+	int res_spin_lock_off;
 	int timer_off;
 	int wq_off;
 	int refcount_off;
@@ -315,6 +317,8 @@ static inline const char *btf_field_type_name(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return "bpf_spin_lock";
+	case BPF_RES_SPIN_LOCK:
+		return "bpf_res_spin_lock";
 	case BPF_TIMER:
 		return "bpf_timer";
 	case BPF_WORKQUEUE:
@@ -347,6 +351,8 @@ static inline u32 btf_field_type_size(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return sizeof(struct bpf_spin_lock);
+	case BPF_RES_SPIN_LOCK:
+		return sizeof(struct bpf_res_spin_lock);
 	case BPF_TIMER:
 		return sizeof(struct bpf_timer);
 	case BPF_WORKQUEUE:
@@ -377,6 +383,8 @@ static inline u32 btf_field_type_align(enum btf_field_type type)
 	switch (type) {
 	case BPF_SPIN_LOCK:
 		return __alignof__(struct bpf_spin_lock);
+	case BPF_RES_SPIN_LOCK:
+		return __alignof__(struct bpf_res_spin_lock);
 	case BPF_TIMER:
 		return __alignof__(struct bpf_timer);
 	case BPF_WORKQUEUE:
@@ -420,6 +428,7 @@ static inline void bpf_obj_init_field(const struct btf_field *field, void *addr)
 	case BPF_RB_ROOT:
 		/* RB_ROOT_CACHED 0-inits, no need to do anything after memset */
 	case BPF_SPIN_LOCK:
+	case BPF_RES_SPIN_LOCK:
 	case BPF_TIMER:
 	case BPF_WORKQUEUE:
 	case BPF_KPTR_UNREF:
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index d6cfc4ee6820..bc073a48aed9 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -115,6 +115,14 @@ struct bpf_reg_state {
 			int depth:30;
 		} iter;
 
+		/* For irq stack slots */
+		struct {
+			enum {
+				IRQ_NATIVE_KFUNC,
+				IRQ_LOCK_KFUNC,
+			} kfunc_class;
+		} irq;
+
 		/* Max size from any of the above. */
 		struct {
 			unsigned long raw1;
@@ -255,9 +263,11 @@ struct bpf_reference_state {
 	 * default to pointer reference on zero initialization of a state.
 	 */
 	enum ref_state_type {
-		REF_TYPE_PTR	= 1,
-		REF_TYPE_IRQ	= 2,
-		REF_TYPE_LOCK	= 3,
+		REF_TYPE_PTR		= (1 << 1),
+		REF_TYPE_IRQ		= (1 << 2),
+		REF_TYPE_LOCK		= (1 << 3),
+		REF_TYPE_RES_LOCK 	= (1 << 4),
+		REF_TYPE_RES_LOCK_IRQ	= (1 << 5),
 	} type;
 	/* Track each reference created with a unique id, even if the same
 	 * instruction creates the reference multiple times (eg, via CALL).
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 519e3f5e9c10..f7a2bfb0c11a 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3481,6 +3481,15 @@ static int btf_get_field_type(const struct btf *btf, const struct btf_type *var_
 			goto end;
 		}
 	}
+	if (field_mask & BPF_RES_SPIN_LOCK) {
+		if (!strcmp(name, "bpf_res_spin_lock")) {
+			if (*seen_mask & BPF_RES_SPIN_LOCK)
+				return -E2BIG;
+			*seen_mask |= BPF_RES_SPIN_LOCK;
+			type = BPF_RES_SPIN_LOCK;
+			goto end;
+		}
+	}
 	if (field_mask & BPF_TIMER) {
 		if (!strcmp(name, "bpf_timer")) {
 			if (*seen_mask & BPF_TIMER)
@@ -3659,6 +3668,7 @@ static int btf_find_field_one(const struct btf *btf,
 
 	switch (field_type) {
 	case BPF_SPIN_LOCK:
+	case BPF_RES_SPIN_LOCK:
 	case BPF_TIMER:
 	case BPF_WORKQUEUE:
 	case BPF_LIST_NODE:
@@ -3952,6 +3962,7 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 		return ERR_PTR(-ENOMEM);
 
 	rec->spin_lock_off = -EINVAL;
+	rec->res_spin_lock_off = -EINVAL;
 	rec->timer_off = -EINVAL;
 	rec->wq_off = -EINVAL;
 	rec->refcount_off = -EINVAL;
@@ -3979,6 +3990,11 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 			/* Cache offset for faster lookup at runtime */
 			rec->spin_lock_off = rec->fields[i].offset;
 			break;
+		case BPF_RES_SPIN_LOCK:
+			WARN_ON_ONCE(rec->spin_lock_off >= 0);
+			/* Cache offset for faster lookup at runtime */
+			rec->res_spin_lock_off = rec->fields[i].offset;
+			break;
 		case BPF_TIMER:
 			WARN_ON_ONCE(rec->timer_off >= 0);
 			/* Cache offset for faster lookup at runtime */
@@ -4022,9 +4038,15 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 		rec->cnt++;
 	}
 
+	if (rec->spin_lock_off >= 0 && rec->res_spin_lock_off >= 0) {
+		ret = -EINVAL;
+		goto end;
+	}
+
 	/* bpf_{list_head, rb_node} require bpf_spin_lock */
 	if ((btf_record_has_field(rec, BPF_LIST_HEAD) ||
-	     btf_record_has_field(rec, BPF_RB_ROOT)) && rec->spin_lock_off < 0) {
+	     btf_record_has_field(rec, BPF_RB_ROOT)) &&
+		 (rec->spin_lock_off < 0 && rec->res_spin_lock_off < 0)) {
 		ret = -EINVAL;
 		goto end;
 	}
@@ -5637,7 +5659,7 @@ btf_parse_struct_metas(struct bpf_verifier_log *log, struct btf *btf)
 
 		type = &tab->types[tab->cnt];
 		type->btf_id = i;
-		record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE |
+		record = btf_parse_fields(btf, t, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK | BPF_LIST_HEAD | BPF_LIST_NODE |
 						  BPF_RB_ROOT | BPF_RB_NODE | BPF_REFCOUNT |
 						  BPF_KPTR, t->size);
 		/* The record cannot be unset, treat it as an error if so */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6a8f20ee2851..dba2628fe9a5 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -648,6 +648,7 @@ void btf_record_free(struct btf_record *rec)
 		case BPF_RB_ROOT:
 		case BPF_RB_NODE:
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 		case BPF_TIMER:
 		case BPF_REFCOUNT:
 		case BPF_WORKQUEUE:
@@ -700,6 +701,7 @@ struct btf_record *btf_record_dup(const struct btf_record *rec)
 		case BPF_RB_ROOT:
 		case BPF_RB_NODE:
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 		case BPF_TIMER:
 		case BPF_REFCOUNT:
 		case BPF_WORKQUEUE:
@@ -777,6 +779,7 @@ void bpf_obj_free_fields(const struct btf_record *rec, void *obj)
 
 		switch (fields[i].type) {
 		case BPF_SPIN_LOCK:
+		case BPF_RES_SPIN_LOCK:
 			break;
 		case BPF_TIMER:
 			bpf_timer_cancel_and_free(field_ptr);
@@ -1212,7 +1215,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
 		return -EINVAL;
 
 	map->record = btf_parse_fields(btf, value_type,
-				       BPF_SPIN_LOCK | BPF_TIMER | BPF_KPTR | BPF_LIST_HEAD |
+				       BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK | BPF_TIMER | BPF_KPTR | BPF_LIST_HEAD |
 				       BPF_RB_ROOT | BPF_REFCOUNT | BPF_WORKQUEUE | BPF_UPTR,
 				       map->value_size);
 	if (!IS_ERR_OR_NULL(map->record)) {
@@ -1231,6 +1234,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
 			case 0:
 				continue;
 			case BPF_SPIN_LOCK:
+			case BPF_RES_SPIN_LOCK:
 				if (map->map_type != BPF_MAP_TYPE_HASH &&
 				    map->map_type != BPF_MAP_TYPE_ARRAY &&
 				    map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 3303a3605ee8..29121ad32a89 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -456,7 +456,7 @@ static bool subprog_is_exc_cb(struct bpf_verifier_env *env, int subprog)
 
 static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
 {
-	return btf_record_has_field(reg_btf_record(reg), BPF_SPIN_LOCK);
+	return btf_record_has_field(reg_btf_record(reg), BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK);
 }
 
 static bool type_is_rdonly_mem(u32 type)
@@ -1155,7 +1155,8 @@ static int release_irq_state(struct bpf_verifier_state *state, int id);
 
 static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 				     struct bpf_kfunc_call_arg_meta *meta,
-				     struct bpf_reg_state *reg, int insn_idx)
+				     struct bpf_reg_state *reg, int insn_idx,
+				     int kfunc_class)
 {
 	struct bpf_func_state *state = func(env, reg);
 	struct bpf_stack_state *slot;
@@ -1177,6 +1178,7 @@ static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 	st->type = PTR_TO_STACK; /* we don't have dedicated reg type */
 	st->live |= REG_LIVE_WRITTEN;
 	st->ref_obj_id = id;
+	st->irq.kfunc_class = kfunc_class;
 
 	for (i = 0; i < BPF_REG_SIZE; i++)
 		slot->slot_type[i] = STACK_IRQ_FLAG;
@@ -1185,7 +1187,8 @@ static int mark_stack_slot_irq_flag(struct bpf_verifier_env *env,
 	return 0;
 }
 
-static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+				      int kfunc_class)
 {
 	struct bpf_func_state *state = func(env, reg);
 	struct bpf_stack_state *slot;
@@ -1199,6 +1202,15 @@ static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_r
 	slot = &state->stack[spi];
 	st = &slot->spilled_ptr;
 
+	if (st->irq.kfunc_class != kfunc_class) {
+		const char *flag_kfunc = st->irq.kfunc_class == IRQ_NATIVE_KFUNC ? "native" : "lock";
+		const char *used_kfunc = kfunc_class == IRQ_NATIVE_KFUNC ? "native" : "lock";
+
+		verbose(env, "irq flag acquired by %s kfuncs cannot be restored with %s kfuncs\n",
+			flag_kfunc, used_kfunc);
+		return -EINVAL;
+	}
+
 	err = release_irq_state(env->cur_state, st->ref_obj_id);
 	WARN_ON_ONCE(err && err != -EACCES);
 	if (err) {
@@ -1609,7 +1621,7 @@ static struct bpf_reference_state *find_lock_state(struct bpf_verifier_state *st
 	for (i = 0; i < state->acquired_refs; i++) {
 		struct bpf_reference_state *s = &state->refs[i];
 
-		if (s->type != type)
+		if (!(s->type & type))
 			continue;
 
 		if (s->id == id && s->ptr == ptr)
@@ -8204,6 +8216,12 @@ static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg
 	return err;
 }
 
+enum {
+	PROCESS_SPIN_LOCK = (1 << 0),
+	PROCESS_RES_LOCK  = (1 << 1),
+	PROCESS_LOCK_IRQ  = (1 << 2),
+};
+
 /* Implementation details:
  * bpf_map_lookup returns PTR_TO_MAP_VALUE_OR_NULL.
  * bpf_obj_new returns PTR_TO_BTF_ID | MEM_ALLOC | PTR_MAYBE_NULL.
@@ -8226,30 +8244,33 @@ static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg
  * env->cur_state->active_locks remembers which map value element or allocated
  * object got locked and clears it after bpf_spin_unlock.
  */
-static int process_spin_lock(struct bpf_verifier_env *env, int regno,
-			     bool is_lock)
+static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
 {
+	bool is_lock = flags & PROCESS_SPIN_LOCK, is_res_lock = flags & PROCESS_RES_LOCK;
+	const char *lock_str = is_res_lock ? "bpf_res_spin" : "bpf_spin";
 	struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
 	struct bpf_verifier_state *cur = env->cur_state;
 	bool is_const = tnum_is_const(reg->var_off);
+	bool is_irq = flags & PROCESS_LOCK_IRQ;
 	u64 val = reg->var_off.value;
 	struct bpf_map *map = NULL;
 	struct btf *btf = NULL;
 	struct btf_record *rec;
+	u32 spin_lock_off;
 	int err;
 
 	if (!is_const) {
 		verbose(env,
-			"R%d doesn't have constant offset. bpf_spin_lock has to be at the constant offset\n",
-			regno);
+			"R%d doesn't have constant offset. %s_lock has to be at the constant offset\n",
+			regno, lock_str);
 		return -EINVAL;
 	}
 	if (reg->type == PTR_TO_MAP_VALUE) {
 		map = reg->map_ptr;
 		if (!map->btf) {
 			verbose(env,
-				"map '%s' has to have BTF in order to use bpf_spin_lock\n",
-				map->name);
+				"map '%s' has to have BTF in order to use %s_lock\n",
+				map->name, lock_str);
 			return -EINVAL;
 		}
 	} else {
@@ -8257,36 +8278,53 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
 	}
 
 	rec = reg_btf_record(reg);
-	if (!btf_record_has_field(rec, BPF_SPIN_LOCK)) {
-		verbose(env, "%s '%s' has no valid bpf_spin_lock\n", map ? "map" : "local",
-			map ? map->name : "kptr");
+	if (!btf_record_has_field(rec, is_res_lock ? BPF_RES_SPIN_LOCK : BPF_SPIN_LOCK)) {
+		verbose(env, "%s '%s' has no valid %s_lock\n", map ? "map" : "local",
+			map ? map->name : "kptr", lock_str);
 		return -EINVAL;
 	}
-	if (rec->spin_lock_off != val + reg->off) {
-		verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock' that is at %d\n",
-			val + reg->off, rec->spin_lock_off);
+	spin_lock_off = is_res_lock ? rec->res_spin_lock_off : rec->spin_lock_off;
+	if (spin_lock_off != val + reg->off) {
+		verbose(env, "off %lld doesn't point to 'struct %s_lock' that is at %d\n",
+			val + reg->off, lock_str, spin_lock_off);
 		return -EINVAL;
 	}
 	if (is_lock) {
 		void *ptr;
+		int type;
 
 		if (map)
 			ptr = map;
 		else
 			ptr = btf;
 
-		if (cur->active_locks) {
-			verbose(env,
-				"Locking two bpf_spin_locks are not allowed\n");
-			return -EINVAL;
+		if (!is_res_lock && cur->active_locks) {
+			if (find_lock_state(env->cur_state, REF_TYPE_LOCK, 0, NULL)) {
+				verbose(env,
+					"Locking two bpf_spin_locks are not allowed\n");
+				return -EINVAL;
+			}
+		} else if (is_res_lock && cur->active_locks) {
+			if (find_lock_state(env->cur_state, REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ, reg->id, ptr)) {
+				verbose(env, "Acquiring the same lock again, AA deadlock detected\n");
+				return -EINVAL;
+			}
 		}
-		err = acquire_lock_state(env, env->insn_idx, REF_TYPE_LOCK, reg->id, ptr);
+
+		if (is_res_lock && is_irq)
+			type = REF_TYPE_RES_LOCK_IRQ;
+		else if (is_res_lock)
+			type = REF_TYPE_RES_LOCK;
+		else
+			type = REF_TYPE_LOCK;
+		err = acquire_lock_state(env, env->insn_idx, type, reg->id, ptr);
 		if (err < 0) {
 			verbose(env, "Failed to acquire lock state\n");
 			return err;
 		}
 	} else {
 		void *ptr;
+		int type;
 
 		if (map)
 			ptr = map;
@@ -8294,12 +8332,18 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
 			ptr = btf;
 
 		if (!cur->active_locks) {
-			verbose(env, "bpf_spin_unlock without taking a lock\n");
+			verbose(env, "%s_unlock without taking a lock\n", lock_str);
 			return -EINVAL;
 		}
 
-		if (release_lock_state(env->cur_state, REF_TYPE_LOCK, reg->id, ptr)) {
-			verbose(env, "bpf_spin_unlock of different lock\n");
+		if (is_res_lock && is_irq)
+			type = REF_TYPE_RES_LOCK_IRQ;
+		else if (is_res_lock)
+			type = REF_TYPE_RES_LOCK;
+		else
+			type = REF_TYPE_LOCK;
+		if (release_lock_state(cur, type, reg->id, ptr)) {
+			verbose(env, "%s_unlock of different lock\n", lock_str);
 			return -EINVAL;
 		}
 
@@ -9625,11 +9669,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 			return -EACCES;
 		}
 		if (meta->func_id == BPF_FUNC_spin_lock) {
-			err = process_spin_lock(env, regno, true);
+			err = process_spin_lock(env, regno, PROCESS_SPIN_LOCK);
 			if (err)
 				return err;
 		} else if (meta->func_id == BPF_FUNC_spin_unlock) {
-			err = process_spin_lock(env, regno, false);
+			err = process_spin_lock(env, regno, 0);
 			if (err)
 				return err;
 		} else {
@@ -11511,7 +11555,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 		regs[BPF_REG_0].map_uid = meta.map_uid;
 		regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag;
 		if (!type_may_be_null(ret_flag) &&
-		    btf_record_has_field(meta.map_ptr->record, BPF_SPIN_LOCK)) {
+		    btf_record_has_field(meta.map_ptr->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
 			regs[BPF_REG_0].id = ++env->id_gen;
 		}
 		break;
@@ -11683,10 +11727,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 /* mark_btf_func_reg_size() is used when the reg size is determined by
  * the BTF func_proto's return value size and argument.
  */
-static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
-				   size_t reg_size)
+static void __mark_btf_func_reg_size(struct bpf_verifier_env *env, struct bpf_reg_state *regs,
+				     u32 regno, size_t reg_size)
 {
-	struct bpf_reg_state *reg = &cur_regs(env)[regno];
+	struct bpf_reg_state *reg = &regs[regno];
 
 	if (regno == BPF_REG_0) {
 		/* Function return value */
@@ -11704,6 +11748,12 @@ static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
 	}
 }
 
+static void mark_btf_func_reg_size(struct bpf_verifier_env *env, u32 regno,
+				   size_t reg_size)
+{
+	return __mark_btf_func_reg_size(env, cur_regs(env), regno, reg_size);
+}
+
 static bool is_kfunc_acquire(struct bpf_kfunc_call_arg_meta *meta)
 {
 	return meta->kfunc_flags & KF_ACQUIRE;
@@ -11841,6 +11891,7 @@ enum {
 	KF_ARG_RB_ROOT_ID,
 	KF_ARG_RB_NODE_ID,
 	KF_ARG_WORKQUEUE_ID,
+	KF_ARG_RES_SPIN_LOCK_ID,
 };
 
 BTF_ID_LIST(kf_arg_btf_ids)
@@ -11850,6 +11901,7 @@ BTF_ID(struct, bpf_list_node)
 BTF_ID(struct, bpf_rb_root)
 BTF_ID(struct, bpf_rb_node)
 BTF_ID(struct, bpf_wq)
+BTF_ID(struct, bpf_res_spin_lock)
 
 static bool __is_kfunc_ptr_arg_type(const struct btf *btf,
 				    const struct btf_param *arg, int type)
@@ -11898,6 +11950,11 @@ static bool is_kfunc_arg_wq(const struct btf *btf, const struct btf_param *arg)
 	return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_WORKQUEUE_ID);
 }
 
+static bool is_kfunc_arg_res_spin_lock(const struct btf *btf, const struct btf_param *arg)
+{
+	return __is_kfunc_ptr_arg_type(btf, arg, KF_ARG_RES_SPIN_LOCK_ID);
+}
+
 static bool is_kfunc_arg_callback(struct bpf_verifier_env *env, const struct btf *btf,
 				  const struct btf_param *arg)
 {
@@ -11969,6 +12026,7 @@ enum kfunc_ptr_arg_type {
 	KF_ARG_PTR_TO_MAP,
 	KF_ARG_PTR_TO_WORKQUEUE,
 	KF_ARG_PTR_TO_IRQ_FLAG,
+	KF_ARG_PTR_TO_RES_SPIN_LOCK,
 };
 
 enum special_kfunc_type {
@@ -12007,6 +12065,10 @@ enum special_kfunc_type {
 	KF_bpf_iter_num_destroy,
 	KF_bpf_set_dentry_xattr,
 	KF_bpf_remove_dentry_xattr,
+	KF_bpf_res_spin_lock,
+	KF_bpf_res_spin_unlock,
+	KF_bpf_res_spin_lock_irqsave,
+	KF_bpf_res_spin_unlock_irqrestore,
 };
 
 BTF_SET_START(special_kfunc_set)
@@ -12096,6 +12158,10 @@ BTF_ID(func, bpf_remove_dentry_xattr)
 BTF_ID_UNUSED
 BTF_ID_UNUSED
 #endif
+BTF_ID(func, bpf_res_spin_lock)
+BTF_ID(func, bpf_res_spin_unlock)
+BTF_ID(func, bpf_res_spin_lock_irqsave)
+BTF_ID(func, bpf_res_spin_unlock_irqrestore)
 
 static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
 {
@@ -12189,6 +12255,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
 	if (is_kfunc_arg_irq_flag(meta->btf, &args[argno]))
 		return KF_ARG_PTR_TO_IRQ_FLAG;
 
+	if (is_kfunc_arg_res_spin_lock(meta->btf, &args[argno]))
+		return KF_ARG_PTR_TO_RES_SPIN_LOCK;
+
 	if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) {
 		if (!btf_type_is_struct(ref_t)) {
 			verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n",
@@ -12296,13 +12365,19 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 			     struct bpf_kfunc_call_arg_meta *meta)
 {
 	struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
+	int err, kfunc_class = IRQ_NATIVE_KFUNC;
 	bool irq_save;
-	int err;
 
-	if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_save]) {
+	if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_save] ||
+	    meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave]) {
 		irq_save = true;
-	} else if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_restore]) {
+		if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])
+			kfunc_class = IRQ_LOCK_KFUNC;
+	} else if (meta->func_id == special_kfunc_list[KF_bpf_local_irq_restore] ||
+		   meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore]) {
 		irq_save = false;
+		if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore])
+			kfunc_class = IRQ_LOCK_KFUNC;
 	} else {
 		verbose(env, "verifier internal error: unknown irq flags kfunc\n");
 		return -EFAULT;
@@ -12318,7 +12393,7 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 		if (err)
 			return err;
 
-		err = mark_stack_slot_irq_flag(env, meta, reg, env->insn_idx);
+		err = mark_stack_slot_irq_flag(env, meta, reg, env->insn_idx, kfunc_class);
 		if (err)
 			return err;
 	} else {
@@ -12332,7 +12407,7 @@ static int process_irq_flag(struct bpf_verifier_env *env, int regno,
 		if (err)
 			return err;
 
-		err = unmark_stack_slot_irq_flag(env, reg);
+		err = unmark_stack_slot_irq_flag(env, reg, kfunc_class);
 		if (err)
 			return err;
 	}
@@ -12459,7 +12534,8 @@ static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_
 
 	if (!env->cur_state->active_locks)
 		return -EINVAL;
-	s = find_lock_state(env->cur_state, REF_TYPE_LOCK, id, ptr);
+	s = find_lock_state(env->cur_state, REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
+			    id, ptr);
 	if (!s) {
 		verbose(env, "held lock and object are not in the same allocation\n");
 		return -EINVAL;
@@ -12495,9 +12571,18 @@ static bool is_bpf_graph_api_kfunc(u32 btf_id)
 	       btf_id == special_kfunc_list[KF_bpf_refcount_acquire_impl];
 }
 
+static bool is_bpf_res_spin_lock_kfunc(u32 btf_id)
+{
+	return btf_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_unlock] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave] ||
+	       btf_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore];
+}
+
 static bool kfunc_spin_allowed(u32 btf_id)
 {
-	return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id);
+	return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id) ||
+	       is_bpf_res_spin_lock_kfunc(btf_id);
 }
 
 static bool is_sync_callback_calling_kfunc(u32 btf_id)
@@ -12929,6 +13014,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
 		case KF_ARG_PTR_TO_CONST_STR:
 		case KF_ARG_PTR_TO_WORKQUEUE:
 		case KF_ARG_PTR_TO_IRQ_FLAG:
+		case KF_ARG_PTR_TO_RES_SPIN_LOCK:
 			break;
 		default:
 			WARN_ON_ONCE(1);
@@ -13227,6 +13313,28 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
 			if (ret < 0)
 				return ret;
 			break;
+		case KF_ARG_PTR_TO_RES_SPIN_LOCK:
+		{
+			int flags = PROCESS_RES_LOCK;
+
+			if (reg->type != PTR_TO_MAP_VALUE && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
+				verbose(env, "arg#%d doesn't point to map value or allocated object\n", i);
+				return -EINVAL;
+			}
+
+			if (!is_bpf_res_spin_lock_kfunc(meta->func_id))
+				return -EFAULT;
+			if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+			    meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])
+				flags |= PROCESS_SPIN_LOCK;
+			if (meta->func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave] ||
+			    meta->func_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore])
+				flags |= PROCESS_LOCK_IRQ;
+			ret = process_spin_lock(env, regno, flags);
+			if (ret < 0)
+				return ret;
+			break;
+		}
 		}
 	}
 
@@ -13312,6 +13420,33 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 
 	insn_aux->is_iter_next = is_iter_next_kfunc(&meta);
 
+	if (!insn->off &&
+	    (insn->imm == special_kfunc_list[KF_bpf_res_spin_lock] ||
+	     insn->imm == special_kfunc_list[KF_bpf_res_spin_lock_irqsave])) {
+		struct bpf_verifier_state *branch;
+		struct bpf_reg_state *regs;
+
+		branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
+		if (!branch) {
+			verbose(env, "failed to push state for failed lock acquisition\n");
+			return -ENOMEM;
+		}
+
+		regs = branch->frame[branch->curframe]->regs;
+
+		/* Clear r0-r5 registers in forked state */
+		for (i = 0; i < CALLER_SAVED_REGS; i++)
+			mark_reg_not_init(env, regs, caller_saved[i]);
+
+		mark_reg_unknown(env, regs, BPF_REG_0);
+		err = __mark_reg_s32_range(env, regs, BPF_REG_0, -MAX_ERRNO, -1);
+		if (err) {
+			verbose(env, "failed to mark s32 range for retval in forked state for lock\n");
+			return err;
+		}
+		__mark_btf_func_reg_size(env, regs, BPF_REG_0, sizeof(u32));
+	}
+
 	if (is_kfunc_destructive(&meta) && !capable(CAP_SYS_BOOT)) {
 		verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capability\n");
 		return -EACCES;
@@ -13482,6 +13617,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 
 	if (btf_type_is_scalar(t)) {
 		mark_reg_unknown(env, regs, BPF_REG_0);
+		if (meta.btf == btf_vmlinux && (meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
+		    meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave]))
+			__mark_reg_const_zero(env, &regs[BPF_REG_0]);
 		mark_btf_func_reg_size(env, BPF_REG_0, t->size);
 	} else if (btf_type_is_ptr(t)) {
 		ptr_type = btf_type_skip_modifiers(desc_btf, t->type, &ptr_type_id);
@@ -18417,7 +18555,8 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
 		case STACK_IRQ_FLAG:
 			old_reg = &old->stack[spi].spilled_ptr;
 			cur_reg = &cur->stack[spi].spilled_ptr;
-			if (!check_ids(old_reg->ref_obj_id, cur_reg->ref_obj_id, idmap))
+			if (!check_ids(old_reg->ref_obj_id, cur_reg->ref_obj_id, idmap) ||
+			    old_reg->irq.kfunc_class != cur_reg->irq.kfunc_class)
 				return false;
 			break;
 		case STACK_MISC:
@@ -18461,6 +18600,8 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
 		case REF_TYPE_IRQ:
 			break;
 		case REF_TYPE_LOCK:
+		case REF_TYPE_RES_LOCK:
+		case REF_TYPE_RES_LOCK_IRQ:
 			if (old->refs[i].ptr != cur->refs[i].ptr)
 				return false;
 			break;
@@ -19746,7 +19887,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 		}
 	}
 
-	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
+	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
 		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
 			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
 			return -EINVAL;
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:17 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:17 -0700
Subject: [PATCH bpf-next v4 01/25] locking: Move MCS struct definition to public header
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-2-memxor@gmail.com>

Move the definition of the struct mcs_spinlock from the private
mcs_spinlock.h header in kernel/locking to the mcs_spinlock.h
asm-generic header, since we will need to reference it from the
qspinlock.h header in subsequent commits.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/mcs_spinlock.h | 6 ++++++
 kernel/locking/mcs_spinlock.h      | 6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/asm-generic/mcs_spinlock.h b/include/asm-generic/mcs_spinlock.h
index 10cd4ffc6ba2..39c94012b88a 100644
--- a/include/asm-generic/mcs_spinlock.h
+++ b/include/asm-generic/mcs_spinlock.h
@@ -1,6 +1,12 @@
 #ifndef __ASM_MCS_SPINLOCK_H
 #define __ASM_MCS_SPINLOCK_H
 
+struct mcs_spinlock {
+	struct mcs_spinlock *next;
+	int locked; /* 1 if lock acquired */
+	int count;  /* nesting count, see qspinlock.c */
+};
+
 /*
  * Architectures can define their own:
  *
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
index 85251d8771d9..16160ca8907f 100644
--- a/kernel/locking/mcs_spinlock.h
+++ b/kernel/locking/mcs_spinlock.h
@@ -15,12 +15,6 @@
 
 #include <asm/mcs_spinlock.h>
 
-struct mcs_spinlock {
-	struct mcs_spinlock *next;
-	int locked; /* 1 if lock acquired */
-	int count;  /* nesting count, see qspinlock.c */
-};
-
 #ifndef arch_mcs_spin_lock_contended
 /*
  * Using smp_cond_load_acquire() provides the acquire semantics
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:16 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:16 -0700
Subject: [PATCH bpf-next v4 00/25] Resilient Queued Spin Lock
Message-ID: <20250316040541.108729-1-memxor@gmail.com>

Changelog:
----------
v3 -> v4
v4: https://lore.kernel.org/bpf/20250303152305.3195648-1-memxor at gmail.com

 * Fix bisectability problem by reordering locktorture commit before
   Makefile commit.
 * Add EXPORT_SYMBOL_GPL to all used symbols and variables by consumers.
 * Skip BPF selftest when nrprocs < 2.
 * Fix kdoc to describe return value for res_spin_lock, slowpath.
 * Move kernel/locking/rqspinlock.{c,h} to kernel/bpf/rqspinlock.{c,h}.

v2 -> v3
v2: https://lore.kernel.org/bpf/20250206105435.2159977-1-memxor at gmail.com

 * Add ifdef's to fallback to Ankur's patch when it gets in, until then
   copy-paste the implementation.
 * Change the meaning of RES_DEF_TIMEOUT from two critical section
   lengths to one for clarity, and use RES_DEF_TIMEOUT * 2 where needed.
 * Use NSEC_PER_SEC as timeout for TAS fallback.
 * Add Closes: tags for known syzbot reports.
 * Change timeout for TAS fallback to 1 second.
 * Fix more kernel test robot errors.
 * More comments about smp_wmb in release_held_lock_entry interaction.
 * Change RES_NR_HELD to 31.
 * Address comments from Peter, Eduard, Alexei.

v1 -> v2
v1: https://lore.kernel.org/bpf/20250107140004.2732830-1-memxor at gmail.com

 * Address nits from Waiman and Peter
 * Fix arm64 WFE bug pointed out by Peter.
 * Fix incorrect memory ordering in release_held_lock_entry, and
   document subtleties. Explain why release is sufficient in unlock
   but not in release_held_lock_entry.
 * Remove dependence on CONFIG_QUEUED_SPINLOCKS and introduce a
   test-and-set fallback when queued spinlock support is missing on an
   architecture.
 * Enforce FIFO ordering for BPF program spin unlocks.
 * Address comments from Eduard on verifier plumbing.
 * Add comments as suggested by Waiman.
 * Refactor paravirt TAS lock to use the implemented TAS fallback.
 * Use rqspinlock_t as the type throughout so that it can be replaced
   with a non-qspinlock type in case of fallback.
 * Testing and benchmarking on arm64, added numbers to the cover letter.
 * Fix kernel test robot errors.
 * Fix a BPF selftest bug leading to spurious failures on arm64.

Introduction
------------

This patch set introduces Resilient Queued Spin Lock (or rqspinlock with
res_spin_lock() and res_spin_unlock() APIs).

This is a qspinlock variant which recovers the kernel from a stalled
state when the lock acquisition path cannot make forward progress. This
can occur when a lock acquisition attempt enters a deadlock situation
(e.g. AA, or ABBA), or more generally, when the owner of the lock (which
we?re trying to acquire) isn?t making forward progress.

The cover letter provides an overview of the motivation, design, and
alternative approaches. We then provide evaluation numbers showcasing
that while rqspinlock incurs overhead, the performance of rqspinlock
approaches that of the normal qspinlock used by the kernel.

The evaluations for rqspinlock were performed by replacing the default
qspinlock implementation with it and booting the kernel to run the
experiments. Support for locktorture is also included with numbers in
this series.

The cover letter's design section provides an overview of the
algorithmic approach. A technical document describing the implementation
in more detail is available here:
https://github.com/kkdwivedi/rqspinlock/blob/main/rqspinlock.pdf

We have a WIP TLA+ proof for liveness and mutual exclusion of rqspinlock
built on top of the qspinlock TLA+ proof from Catalin Marinas [3]. We
will share more details and the links in the near future.

Motivation
----------

In regular kernel code, usage of locks is assumed to be correct, so as
to avoid deadlocks and stalls by construction, however, the same is not
true for BPF programs. Users write normal C code and the in-kernel eBPF
runtime ensures the safety of the kernel by rejecting unsafe programs.
Users can upload programs that use locks in an improper fashion, and may
cause deadlocks when these programs run inside the kernel. The verifier
is responsible for rejecting such programs from being loaded into the
kernel.

Until now, the eBPF verifier ensured deadlock safety by only permitting
one lock acquisition at a time, and by preventing any functions to be
called from within the critical section. Additionally, only a few
restricted program types are allowed to call spin locks. As the usage of
eBPF grows (e.g. with sched_ext) beyond its conventional application in
networking, tracing, and security, the limitations on locking are
becoming a bottleneck for users.

The rqspinlock implementation allows us to permit more flexible locking
patterns in BPF programs, without limiting them to the subset that can
be proven safe statically (which is fairly small, and requires complex
static analysis), while ensuring that the kernel will recover in case we
encounter a locking violation at runtime. We make a tradeoff here by
accepting programs that may potentially have deadlocks, and recover the
kernel quickly at runtime to ensure availability.

Additionally, eBPF programs attached to different parts of the kernel
can introduce new control flow into the kernel, which increases the
likelihood of deadlocks in code not written to handle reentrancy. There
have been multiple syzbot reports surfacing deadlocks in internal kernel
code due to the diverse ways in which eBPF programs can be attached to
different parts of the kernel.  By switching the BPF subsystem?s lock
usage to rqspinlock, all of these issues can be mitigated at runtime.

This spin lock implementation allows BPF maps to become safer and remove
mechanisms that have fallen short in assuring safety when nesting
programs in arbitrary ways in the same context or across different
contexts. The red diffs due to patches 16-18 demonstrate this
simplification.

>  kernel/bpf/hashtab.c         | 102 ++++++++++++++++++++++++++++++++--------------------------...
>  kernel/bpf/lpm_trie.c        |  25 ++++++++++++++-----------
>  kernel/bpf/percpu_freelist.c | 113 +++++++++++++++++++++++++---------------------------------...
>  kernel/bpf/percpu_freelist.h |   4 ++--
>  4 files changed, 73 insertions(+), 171 deletions(-)

Design
------

Deadlocks mostly manifest as stalls in the waiting loops of the
qspinlock slow path. Thus, using stalls as a signal for deadlocks avoids
introducing cost to the normal fast path, and ensures bounded
termination of the waiting loop. Our recovery algorithm is focused on
terminating the waiting loops of the qspinlock algorithm when it gets
stuck, and implementing bespoke recovery procedures for each class of
waiter to restore the lock to a usable state. Deadlock detection is the
main mechanism used to provide faster recovery, with the timeout
mechanism acting as a final line of defense.

Deadlock Detection
~~~~~~~~~~~~~~~~~~
We handle two cases of deadlocks: AA deadlocks (attempts to acquire the
same lock again), and ABBA deadlocks (attempts to acquire two locks in
the opposite order from two distinct threads). Variants of ABBA
deadlocks may be encountered with more than two locks being held in the
incorrect order. These are not diagnosed explicitly, as they reduce to
ABBA deadlocks.

Deadlock detection is triggered immediately when beginning the waiting
loop of a lock slow path.

While timeouts ensure that any waiting loops in the locking slow path
terminate and return to the caller, it can be excessively long in some
situations. While the default timeout is short (0.5s), a stall for this
duration inside the kernel can set off alerts for latency-critical
services with strict SLOs.  Ideally, the kernel should recover from an
undesired state of the lock as soon as possible.

A multi-step strategy is used to recover the kernel from waiting loops
in the locking algorithm which may fail to terminate in a bounded amount
of time.

 * Each CPU maintains a table of held locks. Entries are inserted and
   removed upon entry into lock, and exit from unlock, respectively.
 * Deadlock detection for AA locks is thus simple: we have an AA
   deadlock if we find a held lock entry for the lock we?re attempting
   to acquire on the same CPU.
 * During deadlock detection for ABBA, we search through the tables of
   all other CPUs to find situations where we are holding a lock the
   remote CPU is attempting to acquire, and they are holding a lock we
   are attempting to acquire. Upon encountering such a condition, we
   report an ABBA deadlock.
 * We divide the duration between entry time point into the waiting loop
   and the timeout time point into intervals of 1 ms, and perform
   deadlock detection until timeout happens. Upon entry into the slow
   path, and then completion of each 1 ms interval, we perform detection
   of both AA and ABBA deadlocks. In the event that deadlock detection
   yields a positive result, the recovery happens sooner than the
   timeout.  Otherwise, it happens as a last resort upon completion of
   the timeout.

Timeouts
~~~~~~~~
Timeouts act as final line of defense against stalls for waiting loops.
The ?ktime_get_mono_fast_ns? function is used to poll for the current
time, and it is compared to the timestamp indicating the end time in the
waiter loop. Each waiting loop is instrumented to check an extra
condition using a macro. Internally, the macro implementation amortizes
the checking of the timeout to avoid sampling the clock in every
iteration.  Precisely, the timeout checks are invoked every 64k
iterations.

Recovery
~~~~~~~~
There is extensive literature in academia on designing locks that
support timeouts [0][1], as timeouts can be used as a proxy for
detecting the presence of deadlocks and recovering from them, without
maintaining explicit metadata to construct a waits-for relationship
between two threads at runtime.

In case of rqspinlock, the key simplification in our algorithm comes
from the fact that upon a timeout, waiters always leave the queue in
FIFO order.  As such, the timeout is only enforced by the head of the
wait queue, while other waiters rely on the head to signal them when a
timeout has occurred and when they need to exit. We don?t have to
implement complex algorithms and do not need extra synchronization for
waiters in the middle of the queue timing out before their predecessor
or successor, unlike previous approaches [0][1].

There are three forms of waiters in the original queued spin lock
algorithm.  The first is the waiter which acquires the pending bit and
spins on the lock word without forming a wait queue. The second is the
head waiter that is the first waiter heading the wait queue. The third
form is of all the non-head waiters queued behind the head, waiting to
be signalled through their MCS node to overtake the responsibility of
the head.

In rqspinlock's recovery algorithm, we are concerned with the second and
third kind. First, we augment the waiting loop of the head of the wait
queue with a timeout. When this timeout happens, all waiters part of the
wait queue will abort their lock acquisition attempts. This happens in
three steps.

 * First, the head breaks out of its loop waiting for pending and locked
   bits to turn to 0, and non-head waiters break out of their MCS node
   spin (more on that later).
 * Next, every waiter (head or non-head) attempts to check whether they
   are also the tail waiter, in such a case they attempt to zero out the
   tail word and allow a new queue to be built up for this lock. If they
   succeed, they have no one to signal next in the queue to stop
   spinning.
 * Otherwise, they signal the MCS node of the next waiter to break out
   of its spin and try resetting the tail word back to 0. This goes on
   until the tail waiter is found. In case of races, the new tail will
   be responsible for performing the same task, as the old tail will
   then fail to reset the tail word and wait for its next pointer to be
   updated before it signals the new tail to do the same.

Timeout Bound
~~~~~~~~~~~~~
The timeout is applied by two types of waiters: the pending bit waiter
and the wait queue head waiter. As such, for the pending waiter, only
the lock owner is ahead of it, and for the wait queue head waiter, only
the lock owner and the pending waiter take precedence in executing their
critical sections.

We define the timeout value to span at most 1 critical section length,
and then use the appropriate value (default, or default x 2) depending
on if we are the pending waiter or head of wait queue.

Therefore, the waiting loop wait can span at most 2 critical section
lengths, and thus, it is unaffected by the amount of contention or the
number of CPUs on the host. Non-head waiters simply wait for the wait
queue head to signal them on a timeout.

In Meta's production, we have noticed uncore PMU reads and SMIs
consuming tens of msecs. While these events are rare, a 0.25 second
timeout should absorb such tail events and not raise false alarms for
timeouts. We will continue monitoring this in production and adjust the
timeout if necessary in the future.

More details of the recovery algorithm is described in patch 9 and a
detailed description is available at [2].

Alternatives
------------

Lockdep: We do not rely on the lockdep facility for reporting violations
for primarily two reasons:

* Overhead: The lockdep infrastructure can add significant overhead to
  the lock acquisition path, and is not recommended for use in
  production due to this reason. While the report is more useful and
  exhaustive, the overhead can be prohibitive, especially as BPF
  programs run in hot paths of the kernel.  Moreover, it also increases
  the size of the lock word to store extra metadata, which is not
  feasible for BPF spin locks that are 4-bytes in size today (similar to
  qspinlock).

* Debug Tool: Lockdep is intended to be used as a debugging facility,
  providing extra context to the user about the locking violations
  occurring during runtime. It is always turned off on all production
  kernels, therefore isn?t available most of the time.

We require a mechanism for detecting common variants of deadlocks that
is always available in production kernels and never turned off. At the
same time, it must not introduce overhead in terms of time (for the slow
path) and memory (for the lock word size).

Evaluation
----------

We run benchmarks that stress locking scalability and perform comparison
against the baseline (qspinlock). For the rqspinlock case, we replace
the default qspinlock with it in the kernel, such that all spin locks in
the kernel use the rqspinlock slow path. As such, benchmarks that stress
kernel spin locks end up exercising rqspinlock.

Evaluation setup
~~~~~~~~~~~~~~~~

We set the CPU governor to performance for all experiments.

Note: Numbers for arm64 have been obtained without the no-WFE fallback
in this series, to perform a fair comparison with the WFE using
qspinlock baseline.

x86_64:

Intel Xeon Platinum 8468 (Sapphire Rapids)
96 cores (48 x 2 sockets)
2 threads per core, 0-95, siblings from 96-191
2 NUMA nodes (every 48 cores), 2 LLCs (every 48 cores), 1 LLC per NUMA node
Hyperthreading enabled

arm64:

Ampere Max Neoverse-N1 256-Core Processor
256 cores (128 cores x 2 sockets)
1 thread per core
2 NUMA nodes (every 128 cores), 1 L2 per core (256 instances), no shared L3
No hyperthreading available

The locktorture experiment is run for 30 seconds.
Average of 25 runs is used for will-it-scale, after an initial warm up.

More information on the locks contended in the will-it-scale experiments
is available in the evaluation section of the CNA paper, in table 1 [4].

Legend:
 QL - qspinlock (avg. throughput)
 RQL - rqspinlock (avg. throughput)

Results
~~~~~~~

locktorture - x86_64

Threads QL		RQL		Speedup
-----------------------------------------------
1	46910437	45057327	0.96
2	29871063	25085034	0.84
4	13876024	19242776	1.39
8	14638499	13346847	0.91
16	14380506	14104716	0.98
24	17278144	15293077	0.89
32	19494283	17826675	0.91
40	27760955	21002910	0.76
48	28638897	26432549	0.92
56	29336194	26512029	0.9
64	30040731	27421403	0.91
72	29523599	27010618	0.91
80	28846738	27885141	0.97
88	29277418	25963753	0.89
96	28472339	27423865	0.96
104	28093317	26634895	0.95
112	29914000	27872339	0.93
120	29199580	26682695	0.91
128	27755880	27314662	0.98
136	30349095	27092211	0.89
144	29193933	27805445	0.95
152	28956663	26071497	0.9
160	28950009	28183864	0.97
168	29383520	28135091	0.96
176	28475883	27549601	0.97
184	31958138	28602434	0.89
192	31342633	33394385	1.07

will-it-scale open1_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	1396323.92	7373.12		0.53	1366616.8	4152.08		0.3	0.98
2	1844403.8	3165.26		0.17	1700301.96	2396.58		0.14	0.92
4	2370590.6	24545.54	1.04	1655872.32	47938.71	2.9	0.7
8	2185227.04	9537.9		0.44	1691205.16	9783.25		0.58	0.77
16	2110672.36	10972.99	0.52	1781696.24	15021.43	0.84	0.84
24	1655042.72	18037.23	1.09	2165125.4	5422.54		0.25	1.31
32	1738928.24	7166.64		0.41	1829468.24	9081.59		0.5	1.05
40	1854430.52	6148.24		0.33	1731062.28	3311.95		0.19	0.93
48	1766529.96	5063.86		0.29	1749375.28	2311.27		0.13	0.99
56	1303016.28	6168.4		0.47	1452656		7695.29		0.53	1.11
64	1169557.96	4353.67		0.37	1287370.56	8477.2		0.66	1.1
72	1036023.4	7116.53		0.69	1135513.92	9542.55		0.84	1.1
80	1097913.64	11356		1.03	1176864.8	6771.41		0.58	1.07
88	1123907.36	12843.13	1.14	1072416.48	7412.25		0.69	0.95
96	1166981.52	9402.71		0.81	1129678.76	9499.14		0.84	0.97
104	1108954.04	8171.46		0.74	1032044.44	7840.17		0.76	0.93
112	1000777.76	8445.7		0.84	1078498.8	6551.47		0.61	1.08
120	1029448.4	6992.29		0.68	1093743		8378.94		0.77	1.06
128	1106670.36	10102.15	0.91	1241438.68	23212.66	1.87	1.12
136	1183776.88	6394.79		0.54	1116799.64	18111.38	1.62	0.94
144	1201122		25917.69	2.16	1301779.96	15792.6		1.21	1.08
152	1099737.08	13567.82	1.23	1053647.2	12704.29	1.21	0.96
160	1031186.32	9048.07		0.88	1069961.4	8293.18		0.78	1.04
168	1068817		16486.06	1.54	1096495.36	14021.93	1.28	1.03
176	966633.96	9623.27		1	1081129.84	9474.81		0.88	1.12
184	1004419.04	12111.11	1.21	1037771.24	12001.66	1.16	1.03
192	1088858.08	16522.93	1.52	1027943.12	14238.57	1.39	0.94

will-it-scale open2_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	1337797.76	4649.19		0.35	1332609.4	3813.14		0.29	1
2	1598300.2	1059.93		0.07	1771891.36	5667.12		0.32	1.11
4	1736573.76	13025.33	0.75	1396901.2	2682.46		0.19	0.8
8	1794367.84	4879.6		0.27	1917478.56	3751.98		0.2	1.07
16	1990998.44	8332.78		0.42	1864165.56	9648.59		0.52	0.94
24	1868148.56	4248.23		0.23	1710136.68	2760.58		0.16	0.92
32	1955180		6719		0.34	1936149.88	1980.87		0.1	0.99
40	1769646.4	4686.54		0.26	1729653.68	4551.22		0.26	0.98
48	1724861.16	4056.66		0.24	1764900		971.11		0.06	1.02
56	1318568		7758.86		0.59	1385660.84	7039.8		0.51	1.05
64	1143290.28	5351.43		0.47	1316686.6	5597.69		0.43	1.15
72	1196762.68	10655.67	0.89	1230173.24	9858.2		0.8	1.03
80	1126308.24	6901.55		0.61	1085391.16	7444.34		0.69	0.96
88	1035672.96	5452.95		0.53	1035541.52	8095.33		0.78	1
96	1030203.36	6735.71		0.65	1020113.48	8683.13		0.85	0.99
104	1039432.88	6583.59		0.63	1083902.48	5775.72		0.53	1.04
112	1113609.04	4380.62		0.39	1072010.36	8983.14		0.84	0.96
120	1109420.96	7183.5		0.65	1079424.12	10929.97	1.01	0.97
128	1095400.04	4274.6		0.39	1095475.2	12042.02	1.1	1
136	1071605.4	11103.73	1.04	1114757.2	10516.55	0.94	1.04
144	1104147.2	9714.75		0.88	1044954.16	7544.2		0.72	0.95
152	1164280.24	13386.15	1.15	1101213.92	11568.49	1.05	0.95
160	1084892.04	7941.25		0.73	1152273.76	9593.38		0.83	1.06
168	983654.76	11772.85	1.2	1111772.28	9806.83		0.88	1.13
176	1087544.24	11262.35	1.04	1077507.76	9442.02		0.88	0.99
184	1101682.4	24701.68	2.24	1095223.2	16707.29	1.53	0.99
192	983712.08	13453.59	1.37	1051244.2	15662.05	1.49	1.07

will-it-scale lock1_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	4307484.96	3959.31		0.09	4252908.56	10375.78	0.24	0.99
2	7701844.32	4169.88		0.05	7219233.52	6437.11		0.09	0.94
4	14781878.72	22854.85	0.15	15260565.12	37305.71	0.24	1.03
8	12949698.64	99270.42	0.77	9954660.4	142805.68	1.43	0.77
16	12947690.64	72977.27	0.56	10865245.12	49520.31	0.46	0.84
24	11142990.64	33200.39	0.3	11444391.68	37884.46	0.33	1.03
32	9652335.84	22369.48	0.23	9344086.72	21639.22	0.23	0.97
40	9185931.12	5508.96		0.06	8881506.32	5072.33		0.06	0.97
48	9084385.36	10871.05	0.12	8863579.12	4583.37		0.05	0.98
56	6595540.96	33100.59	0.5	6640389.76	46619.96	0.7	1.01
64	5946726.24	47160.5		0.79	6572155.84	91973.73	1.4	1.11
72	6744894.72	43166.65	0.64	5991363.36	80637.56	1.35	0.89
80	6234502.16	118983.16	1.91	5157894.32	73592.72	1.43	0.83
88	5053879.6	199713.75	3.95	4479758.08	36202.27	0.81	0.89
96	5184302.64	99199.89	1.91	5249210.16	122348.69	2.33	1.01
104	4612391.92	40803.05	0.88	4850209.6	26813.28	0.55	1.05
112	4809209.68	24070.68	0.5	4869477.84	27489.04	0.56	1.01
120	5130746.4	34265.5		0.67	4620047.12	44229.54	0.96	0.9
128	5376465.28	95028.05	1.77	4781179.6	43700.93	0.91	0.89
136	5453742.4	86718.87	1.59	5412457.12	40339.68	0.75	0.99
144	5805040.72	84669.31	1.46	5595382.48	68701.65	1.23	0.96
152	5842897.36	31120.33	0.53	5787587.12	43521.68	0.75	0.99
160	5837665.12	14179.44	0.24	5118808.72	45193.23	0.88	0.88
168	5660332.72	27467.09	0.49	5104959.04	40891.75	0.8	0.9
176	5180312.24	28656.39	0.55	4718407.6	58734.13	1.24	0.91
184	4706824.16	50469.31	1.07	4692962.64	92266.85	1.97	1
192	5126054.56	51082.02	1	4680866.8	58743.51	1.25	0.91

will-it-scale lock2_threads - x86_64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	4316091.2	4933.28		0.11	4293104		30369.71	0.71	0.99
2	3500046.4	19852.62	0.57	4507627.76	23667.66	0.53	1.29
4	3639098.96	26370.65	0.72	3673166.32	30822.71	0.84	1.01
8	3714548.56	49953.44	1.34	4055818.56	71630.41	1.77	1.09
16	4188724.64	105414.49	2.52	4316077.12	68956.15	1.6	1.03
24	3737908.32	47391.46	1.27	3762254.56	55345.7		1.47	1.01
32	3820952.8	45207.66	1.18	3710368.96	52651.92	1.42	0.97
40	3791280.8	28630.55	0.76	3661933.52	37671.27	1.03	0.97
48	3765721.84	59553.83	1.58	3604738.64	50861.36	1.41	0.96
56	3175505.76	64336.17	2.03	2771022.48	66586.99	2.4	0.87
64	2620294.48	71651.34	2.73	2650171.68	44810.83	1.69	1.01
72	2861893.6	86542.61	3.02	2537437.2	84571.75	3.33	0.89
80	2976297.2	83566.43	2.81	2645132.8	85992.34	3.25	0.89
88	2547724.8	102014.36	4	2336852.16	80570.25	3.45	0.92
96	2945310.32	82673.25	2.81	2513316.96	45741.81	1.82	0.85
104	3028818.64	90643.36	2.99	2581787.52	52967.48	2.05	0.85
112	2546264.16	102605.82	4.03	2118812.64	62043.19	2.93	0.83
120	2917334.64	112220.01	3.85	2720418.64	64035.96	2.35	0.93
128	2906621.84	69428.1		2.39	2795310.32	56736.87	2.03	0.96
136	2841833.76	105541.11	3.71	3063404.48	62288.94	2.03	1.08
144	3032822.32	134796.56	4.44	3169985.6	149707.83	4.72	1.05
152	2557694.96	62218.15	2.43	2469887.6	68343.78	2.77	0.97
160	2810214.72	61468.79	2.19	2323768.48	54226.71	2.33	0.83
168	2651146.48	76573.27	2.89	2385936.64	52433.98	2.2	0.9
176	2720616.32	89026.19	3.27	2941400.08	59296.64	2.02	1.08
184	2696086		88541.24	3.28	2598225.2	76365.7		2.94	0.96
192	2908194.48	87023.91	2.99	2377677.68	53299.82	2.24	0.82

locktorture - arm64

Threads QL		RQL		Speedup
-----------------------------------------------
1	43320464	44718174	1.03
2	21056971	29255448	1.39
4	16040120	11563981	0.72
8	12786398	12838909	1
16	13646408	13436730	0.98
24	13597928	13669457	1.01
32	16456220	14600324	0.89
40	16667726	13883101	0.83
48	14347691	14608641	1.02
56	15624580	15180758	0.97
64	18105114	16009137	0.88
72	16606438	14772256	0.89
80	16550202	14124056	0.85
88	16716082	15930618	0.95
96	16489242	16817657	1.02
104	17915808	17165324	0.96
112	17217482	21343282	1.24
120	20449845	20576123	1.01
128	18700902	20286275	1.08
136	17913378	21142921	1.18
144	18225673	18971921	1.04
152	18374206	19229854	1.05
160	23136514	20129504	0.87
168	21096269	17167777	0.81
176	21376794	21594914	1.01
184	23542989	20638298	0.88
192	22793754	20655980	0.91
200	20933027	19628316	0.94
208	23105684	25572720	1.11
216	24158081	23173848	0.96
224	23388984	22485353	0.96
232	21916401	23899343	1.09
240	22292129	22831784	1.02
248	25812762	22636787	0.88
256	24294738	26127113	1.08

will-it-scale open1_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	844452.32	801		0.09	804936.92	900.25		0.11	0.95
2	1309419.08	9495.78		0.73	1265080.24	3171.13		0.25	0.97
4	2113074.24	5363.19		0.25	2041158.28	7883.65		0.39	0.97
8	1916650.96	15749.86	0.82	2039850.04	7562.87		0.37	1.06
16	1835540.72	12940.45	0.7	1937398.56	11461.15	0.59	1.06
24	1876760.48	12581.67	0.67	1966659.16	10012.69	0.51	1.05
32	1834525.6	5571.08		0.3	1929180.4	6221.96		0.32	1.05
40	1851592.76	7848.18		0.42	1937504.44	5991.55		0.31	1.05
48	1845067		4118.68		0.22	1773331.56	6068.23		0.34	0.96
56	1742709.36	6874.03		0.39	1716184.92	6713.16		0.39	0.98
64	1685339.72	6688.91		0.4	1676046.16	5844.06		0.35	0.99
72	1694838.84	2433.41		0.14	1821189.6	2906.89		0.16	1.07
80	1738778.68	2916.74		0.17	1729212.6	3714.41		0.21	0.99
88	1753131.76	2734.34		0.16	1713294.32	4652.82		0.27	0.98
96	1694112.52	4449.69		0.26	1714438.36	5621.66		0.33	1.01
104	1780279.76	2420.52		0.14	1767679.12	3067.66		0.17	0.99
112	1700284.72	9796.23		0.58	1796674.6	4066.06		0.23	1.06
120	1760466.72	3978.65		0.23	1704706.08	4080.04		0.24	0.97
128	1634067.96	5187.94		0.32	1764115.48	3545.02		0.2	1.08
136	1170303.84	7602.29		0.65	1227188.04	8090.84		0.66	1.05
144	953186.16	7859.02		0.82	964822.08	10536.61	1.09	1.01
152	818893.96	7238.86		0.88	853412.44	5932.25		0.7	1.04
160	707460.48	3868.26		0.55	746985.68	10363.03	1.39	1.06
168	658380.56	4938.77		0.75	672101.12	5442.95		0.81	1.02
176	614692.04	3137.74		0.51	615143.36	6197.19		1.01	1
184	574808.88	4741.61		0.82	592395.08	8840.92		1.49	1.03
192	548142.92	6116.31		1.12	571299.68	8388.56		1.47	1.04
200	511621.96	2182.33		0.43	532144.88	5467.04		1.03	1.04
208	506583.32	6834.39		1.35	521427.08	10318.65	1.98	1.03
216	480438.04	3608.96		0.75	510697.76	8086.47		1.58	1.06
224	470644.96	3451.35		0.73	467433.92	5008.59		1.07	0.99
232	466973.72	6599.97		1.41	444345.92	2144.96		0.48	0.95
240	442927.68	2351.56		0.53	440503.56	4289.01		0.97	0.99
248	432991.16	5829.92		1.35	445462.6	5944.03		1.33	1.03
256	409455.44	1430.5		0.35	422219.4	4007.04		0.95	1.03

will-it-scale open2_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	818645.4	1097.02		0.13	774110.24	1562.45		0.2	0.95
2	1281013.04	2188.78		0.17	1238346.24	2149.97		0.17	0.97
4	2058514.16	13105.36	0.64	1985375		3204.48		0.16	0.96
8	1920414.8	16154.63	0.84	1911667.92	8882.98		0.46	1
16	1943729.68	8714.38		0.45	1978946.72	7465.65		0.38	1.02
24	1915846.88	7749.9		0.4	1914442.72	9841.71		0.51	1
32	1964695.92	8854.83		0.45	1914650.28	9357.82		0.49	0.97
40	1845071.12	5103.26		0.28	1891685.44	4278.34		0.23	1.03
48	1838897.6	5123.61		0.28	1843498.2	5391.94		0.29	1
56	1823768.32	3214.14		0.18	1736477.48	5675.49		0.33	0.95
64	1627162.36	3528.1		0.22	1685727.16	6102.63		0.36	1.04
72	1725320.16	4709.83		0.27	1710174.4	6707.54		0.39	0.99
80	1692288.44	9110.89		0.54	1773676.24	4327.94		0.24	1.05
88	1725496.64	4249.71		0.25	1695173.84	5097.14		0.3	0.98
96	1766093.08	2280.09		0.13	1732782.64	3606.1		0.21	0.98
104	1647753		2926.83		0.18	1710876.4	4416.04		0.26	1.04
112	1763785.52	3838.26		0.22	1803813.76	1859.2		0.1	1.02
120	1684095.16	2385.31		0.14	1766903.08	3258.34		0.18	1.05
128	1733528.56	2800.62		0.16	1677446.32	3201.14		0.19	0.97
136	1179187.84	6804.86		0.58	1241839.52	10698.51	0.86	1.05
144	969456.36	6421.85		0.66	1018441.96	8732.19		0.86	1.05
152	839295.64	10422.66	1.24	817531.92	6778.37		0.83	0.97
160	743010.72	6957.98		0.94	749291.16	9388.47		1.25	1.01
168	666049.88	13159.73	1.98	689408.08	10192.66	1.48	1.04
176	609185.56	5685.18		0.93	653744.24	10847.35	1.66	1.07
184	602232.08	12089.72	2.01	597718.6	13856.45	2.32	0.99
192	563919.32	9870.46		1.75	560080.4	8388.47		1.5	0.99
200	522396.28	4155.61		0.8	539168.64	10456.64	1.94	1.03
208	520328.28	9353.14		1.8	510011.4	6061.19		1.19	0.98
216	479797.72	5824.58		1.21	486955.32	4547.05		0.93	1.01
224	467943.8	4484.86		0.96	473252.76	5608.58		1.19	1.01
232	456914.24	3129.5		0.68	457463.2	7474.83		1.63	1
240	450535		5149.78		1.14	437653.56	4604.92		1.05	0.97
248	435475.2	2350.87		0.54	435589.24	6176.01		1.42	1
256	416737.88	2592.76		0.62	424178.28	3932.2		0.93	1.02

will-it-scale lock1_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	2512077.52	3026.1		0.12	2085365.92	1612.44		0.08	0.83
2	4840180.4	3646.31		0.08	4326922.24	3802.17		0.09	0.89
4	9358779.44	6673.07		0.07	8467588.56	5577.05		0.07	0.9
8	9374436.88	18826.26	0.2	8635110.16	4217.66		0.05	0.92
16	9527184.08	14111.94	0.15	8561174.16	3258.6		0.04	0.9
24	8873099.76	17242.32	0.19	9286778.72	4124.51		0.04	1.05
32	8457640.4	10790.92	0.13	8700401.52	5110		0.06	1.03
40	8478771.76	13250.8		0.16	8746198.16	7606.42		0.09	1.03
48	8329097.76	7958.92		0.1	8774265.36	6082.08		0.07	1.05
56	8330143.04	11586.93	0.14	8472426.48	7402.13		0.09	1.02
64	8334684.08	10478.03	0.13	7979193.52	8436.63		0.11	0.96
72	7941815.52	16031.38	0.2	8016885.52	12640.56	0.16	1.01
80	8042221.68	10219.93	0.13	8072222.88	12479.54	0.15	1
88	8190336.8	10751.38	0.13	8432977.6	11865.67	0.14	1.03
96	8235010.08	7267.8		0.09	8022101.28	11910.63	0.15	0.97
104	8154434.08	7770.8		0.1	7987812		7647.42		0.1	0.98
112	7738464.56	11067.72	0.14	7968483.92	20632.93	0.26	1.03
120	8228919.36	10395.79	0.13	8304329.28	11913.76	0.14	1.01
128	7798646.64	8877.8		0.11	8197938.4	7527.81		0.09	1.05
136	5567293.68	66259.82	1.19	5642017.12	126584.59	2.24	1.01
144	4425655.52	55729.96	1.26	4519874.64	82996.01	1.84	1.02
152	3871300.8	77793.78	2.01	3850025.04	80167.3		2.08	0.99
160	3558041.68	55108.3		1.55	3495924.96	83626.42	2.39	0.98
168	3302042.72	45011.89	1.36	3298002.8	59393.64	1.8	1
176	3066165.2	34896.54	1.14	3063027.44	58219.26	1.9	1
184	2817899.6	43585.27	1.55	2859393.84	45258.03	1.58	1.01
192	2690403.76	42236.77	1.57	2630652.24	35953.13	1.37	0.98
200	2563141.44	28145.43	1.1	2539964.32	38556.52	1.52	0.99
208	2502968.8	27687.81	1.11	2477757.28	28240.81	1.14	0.99
216	2474917.76	24128.71	0.97	2483161.44	32198.37	1.3	1
224	2386874.72	32954.66	1.38	2398068.48	37667.29	1.57	1
232	2379248.24	27413.4		1.15	2327601.68	24565.28	1.06	0.98
240	2302146.64	19914.19	0.87	2236074.64	20968.17	0.94	0.97
248	2241798.32	21542.52	0.96	2173312.24	26498.36	1.22	0.97
256	2198765.12	20832.66	0.95	2136159.52	25027.96	1.17	0.97

will-it-scale lock2_threads - arm64

Threads QL      	QL stddev       stddev% RQL     	RQL stddev      stddev% Speedup
-----------------------------------------------------------------------------------------------
1	2499414.32	1932.27		0.08	2075704.8	24589.71	1.18	0.83
2	3887820		34198.36	0.88	4057432.64	11896.04	0.29	1.04
4	3445307.6	7958.3		0.23	3869960.4	3788.5		0.1	1.12
8	4310597.2	14405.9		0.33	3931319.76	5845.33		0.15	0.91
16	3995159.84	22621.85	0.57	3953339.68	15668.9		0.4	0.99
24	4048456.88	22956.51	0.57	3887812.64	30584.77	0.79	0.96
32	3974808.64	20465.87	0.51	3718778.08	27407.24	0.74	0.94
40	3941154.88	15136.68	0.38	3551464.24	33378.67	0.94	0.9
48	3725436.32	17090.67	0.46	3714356.08	19035.26	0.51	1
56	3558449.44	10123.46	0.28	3449656.08	36476.87	1.06	0.97
64	3514616.08	16470.99	0.47	3493197.04	25639.82	0.73	0.99
72	3461700.88	16780.97	0.48	3376565.04	16930.19	0.5	0.98
80	3797008.64	17599.05	0.46	3505856.16	34320.34	0.98	0.92
88	3737459.44	10774.93	0.29	3631757.68	24231.29	0.67	0.97
96	3612816.16	21865.86	0.61	3545354.56	16391.15	0.46	0.98
104	3765167.36	17763.8		0.47	3466467.12	22235.45	0.64	0.92
112	3713386		15455.21	0.42	3402210		18349.66	0.54	0.92
120	3699986.08	15153.08	0.41	3580303.92	19823.01	0.55	0.97
128	3648694.56	11891.62	0.33	3426445.28	22993.32	0.67	0.94
136	800046.88	6039.73		0.75	784412.16	9062.03		1.16	0.98
144	769483.36	5231.74		0.68	714132.8	8953.57		1.25	0.93
152	821081.52	4249.12		0.52	743694.64	8155.18		1.1	0.91
160	789040.16	9187.4		1.16	834865.44	6159.29		0.74	1.06
168	867742.4	8967.66		1.03	734905.36	15582.75	2.12	0.85
176	838650.32	7949.72		0.95	846939.68	8959.8		1.06	1.01
184	854984.48	19475.51	2.28	794549.92	11924.54	1.5	0.93
192	846262.32	13795.86	1.63	899915.12	8639.82		0.96	1.06
200	942602.16	12665.42	1.34	900385.76	8592.23		0.95	0.96
208	954183.68	12853.22	1.35	1166186.96	13045.03	1.12	1.22
216	929319.76	10157.79	1.09	926773.76	10577.01	1.14	1
224	967896.56	9819.6		1.01	951144.32	12343.83	1.3	0.98
232	990621.12	7771.97		0.78	916361.2	17878.44	1.95	0.93
240	995285.04	20104.22	2.02	972119.6	12856.42	1.32	0.98
248	1029436		20404.97	1.98	965301.28	11102.95	1.15	0.94
256	1038724.8	19201.03	1.85	1029942.08	12563.07	1.22	0.99

Written By
----------
Alexei Starovoitov <ast at kernel.org>
Kumar Kartikeya Dwivedi <memxor at gmail.com>

  [0]: https://www.cs.rochester.edu/research/synchronization/pseudocode/timeout.html
  [1]: https://dl.acm.org/doi/10.1145/571825.571830
  [2]: https://github.com/kkdwivedi/rqspinlock/blob/main/rqspinlock.pdf
  [3]: https://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/kernel-tla.git/plain/qspinlock.tla
  [4]: https://arxiv.org/pdf/1810.05600

Kumar Kartikeya Dwivedi (25):
  locking: Move MCS struct definition to public header
  locking: Move common qspinlock helpers to a private header
  locking: Allow obtaining result of arch_mcs_spin_lock_contended
  locking: Copy out qspinlock.c to kernel/bpf/rqspinlock.c
  rqspinlock: Add rqspinlock.h header
  rqspinlock: Drop PV and virtualization support
  rqspinlock: Add support for timeouts
  rqspinlock: Hardcode cond_acquire loops for arm64
  rqspinlock: Protect pending bit owners from stalls
  rqspinlock: Protect waiters in queue from stalls
  rqspinlock: Protect waiters in trylock fallback from stalls
  rqspinlock: Add deadlock detection and recovery
  rqspinlock: Add a test-and-set fallback
  rqspinlock: Add basic support for CONFIG_PARAVIRT
  rqspinlock: Add helper to print a splat on timeout or deadlock
  rqspinlock: Add macros for rqspinlock usage
  rqspinlock: Add entry to Makefile, MAINTAINERS
  rqspinlock: Add locktorture support
  bpf: Convert hashtab.c to rqspinlock
  bpf: Convert percpu_freelist.c to rqspinlock
  bpf: Convert lpm_trie.c to rqspinlock
  bpf: Introduce rqspinlock kfuncs
  bpf: Implement verifier support for rqspinlock
  bpf: Maintain FIFO property for rqspinlock unlock
  selftests/bpf: Add tests for rqspinlock

 MAINTAINERS                                   |   2 +
 arch/arm64/include/asm/rqspinlock.h           |  93 +++
 arch/x86/include/asm/rqspinlock.h             |  33 +
 include/asm-generic/Kbuild                    |   1 +
 include/asm-generic/mcs_spinlock.h            |   6 +
 include/asm-generic/rqspinlock.h              | 250 ++++++
 include/linux/bpf.h                           |  10 +
 include/linux/bpf_verifier.h                  |  19 +-
 kernel/bpf/Makefile                           |   2 +-
 kernel/bpf/btf.c                              |  26 +-
 kernel/bpf/hashtab.c                          | 102 +--
 kernel/bpf/lpm_trie.c                         |  25 +-
 kernel/bpf/percpu_freelist.c                  | 113 +--
 kernel/bpf/percpu_freelist.h                  |   4 +-
 kernel/bpf/rqspinlock.c                       | 770 ++++++++++++++++++
 kernel/bpf/rqspinlock.h                       |  48 ++
 kernel/bpf/syscall.c                          |   6 +-
 kernel/bpf/verifier.c                         | 248 +++++-
 kernel/locking/lock_events_list.h             |   5 +
 kernel/locking/locktorture.c                  |  57 ++
 kernel/locking/mcs_spinlock.h                 |  10 +-
 kernel/locking/qspinlock.c                    | 193 +----
 kernel/locking/qspinlock.h                    | 200 +++++
 .../selftests/bpf/prog_tests/res_spin_lock.c  |  98 +++
 tools/testing/selftests/bpf/progs/irq.c       |  53 ++
 .../selftests/bpf/progs/res_spin_lock.c       | 143 ++++
 .../selftests/bpf/progs/res_spin_lock_fail.c  | 244 ++++++
 27 files changed, 2344 insertions(+), 417 deletions(-)
 create mode 100644 arch/arm64/include/asm/rqspinlock.h
 create mode 100644 arch/x86/include/asm/rqspinlock.h
 create mode 100644 include/asm-generic/rqspinlock.h
 create mode 100644 kernel/bpf/rqspinlock.c
 create mode 100644 kernel/bpf/rqspinlock.h
 create mode 100644 kernel/locking/qspinlock.h
 create mode 100644 tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock_fail.c


base-commit: 812f7702d83d84cdf776d75e2ba5386de9e8acc0
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:18 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:18 -0700
Subject: [PATCH bpf-next v4 02/25] locking: Move common qspinlock helpers to a private header
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-3-memxor@gmail.com>

Move qspinlock helper functions that encode, decode tail word, set and
clear the pending and locked bits, and other miscellaneous definitions
and macros to a private header. To this end, create a qspinlock.h header
file in kernel/locking. Subsequent commits will introduce a modified
qspinlock slow path function, thus moving shared code to a private
header will help minimize unnecessary code duplication.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/qspinlock.c | 193 +----------------------------------
 kernel/locking/qspinlock.h | 200 +++++++++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+), 188 deletions(-)
 create mode 100644 kernel/locking/qspinlock.h

diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 7d96bed718e4..af8d122bb649 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -25,8 +25,9 @@
 #include <trace/events/lock.h>
 
 /*
- * Include queued spinlock statistics code
+ * Include queued spinlock definitions and statistics code
  */
+#include "qspinlock.h"
 #include "qspinlock_stat.h"
 
 /*
@@ -67,36 +68,6 @@
  */
 
 #include "mcs_spinlock.h"
-#define MAX_NODES	4
-
-/*
- * On 64-bit architectures, the mcs_spinlock structure will be 16 bytes in
- * size and four of them will fit nicely in one 64-byte cacheline. For
- * pvqspinlock, however, we need more space for extra data. To accommodate
- * that, we insert two more long words to pad it up to 32 bytes. IOW, only
- * two of them can fit in a cacheline in this case. That is OK as it is rare
- * to have more than 2 levels of slowpath nesting in actual use. We don't
- * want to penalize pvqspinlocks to optimize for a rare case in native
- * qspinlocks.
- */
-struct qnode {
-	struct mcs_spinlock mcs;
-#ifdef CONFIG_PARAVIRT_SPINLOCKS
-	long reserved[2];
-#endif
-};
-
-/*
- * The pending bit spinning loop count.
- * This heuristic is used to limit the number of lockword accesses
- * made by atomic_cond_read_relaxed when waiting for the lock to
- * transition out of the "== _Q_PENDING_VAL" state. We don't spin
- * indefinitely because there's no guarantee that we'll make forward
- * progress.
- */
-#ifndef _Q_PENDING_LOOPS
-#define _Q_PENDING_LOOPS	1
-#endif
 
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
@@ -106,161 +77,7 @@ struct qnode {
  *
  * PV doubles the storage and uses the second cacheline for PV state.
  */
-static DEFINE_PER_CPU_ALIGNED(struct qnode, qnodes[MAX_NODES]);
-
-/*
- * We must be able to distinguish between no-tail and the tail at 0:0,
- * therefore increment the cpu number by one.
- */
-
-static inline __pure u32 encode_tail(int cpu, int idx)
-{
-	u32 tail;
-
-	tail  = (cpu + 1) << _Q_TAIL_CPU_OFFSET;
-	tail |= idx << _Q_TAIL_IDX_OFFSET; /* assume < 4 */
-
-	return tail;
-}
-
-static inline __pure struct mcs_spinlock *decode_tail(u32 tail)
-{
-	int cpu = (tail >> _Q_TAIL_CPU_OFFSET) - 1;
-	int idx = (tail &  _Q_TAIL_IDX_MASK) >> _Q_TAIL_IDX_OFFSET;
-
-	return per_cpu_ptr(&qnodes[idx].mcs, cpu);
-}
-
-static inline __pure
-struct mcs_spinlock *grab_mcs_node(struct mcs_spinlock *base, int idx)
-{
-	return &((struct qnode *)base + idx)->mcs;
-}
-
-#define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK)
-
-#if _Q_PENDING_BITS == 8
-/**
- * clear_pending - clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,* -> *,0,*
- */
-static __always_inline void clear_pending(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->pending, 0);
-}
-
-/**
- * clear_pending_set_locked - take ownership and clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,0 -> *,0,1
- *
- * Lock stealing is not allowed if this function is used.
- */
-static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->locked_pending, _Q_LOCKED_VAL);
-}
-
-/*
- * xchg_tail - Put in the new queue tail code word & retrieve previous one
- * @lock : Pointer to queued spinlock structure
- * @tail : The new queue tail code word
- * Return: The previous queue tail code word
- *
- * xchg(lock, tail), which heads an address dependency
- *
- * p,*,* -> n,*,* ; prev = xchg(lock, node)
- */
-static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
-{
-	/*
-	 * We can use relaxed semantics since the caller ensures that the
-	 * MCS node is properly initialized before updating the tail.
-	 */
-	return (u32)xchg_relaxed(&lock->tail,
-				 tail >> _Q_TAIL_OFFSET) << _Q_TAIL_OFFSET;
-}
-
-#else /* _Q_PENDING_BITS == 8 */
-
-/**
- * clear_pending - clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,* -> *,0,*
- */
-static __always_inline void clear_pending(struct qspinlock *lock)
-{
-	atomic_andnot(_Q_PENDING_VAL, &lock->val);
-}
-
-/**
- * clear_pending_set_locked - take ownership and clear the pending bit.
- * @lock: Pointer to queued spinlock structure
- *
- * *,1,0 -> *,0,1
- */
-static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
-{
-	atomic_add(-_Q_PENDING_VAL + _Q_LOCKED_VAL, &lock->val);
-}
-
-/**
- * xchg_tail - Put in the new queue tail code word & retrieve previous one
- * @lock : Pointer to queued spinlock structure
- * @tail : The new queue tail code word
- * Return: The previous queue tail code word
- *
- * xchg(lock, tail)
- *
- * p,*,* -> n,*,* ; prev = xchg(lock, node)
- */
-static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
-{
-	u32 old, new;
-
-	old = atomic_read(&lock->val);
-	do {
-		new = (old & _Q_LOCKED_PENDING_MASK) | tail;
-		/*
-		 * We can use relaxed semantics since the caller ensures that
-		 * the MCS node is properly initialized before updating the
-		 * tail.
-		 */
-	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
-
-	return old;
-}
-#endif /* _Q_PENDING_BITS == 8 */
-
-/**
- * queued_fetch_set_pending_acquire - fetch the whole lock value and set pending
- * @lock : Pointer to queued spinlock structure
- * Return: The previous lock value
- *
- * *,*,* -> *,1,*
- */
-#ifndef queued_fetch_set_pending_acquire
-static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock)
-{
-	return atomic_fetch_or_acquire(_Q_PENDING_VAL, &lock->val);
-}
-#endif
-
-/**
- * set_locked - Set the lock bit and own the lock
- * @lock: Pointer to queued spinlock structure
- *
- * *,*,0 -> *,0,1
- */
-static __always_inline void set_locked(struct qspinlock *lock)
-{
-	WRITE_ONCE(lock->locked, _Q_LOCKED_VAL);
-}
-
+static DEFINE_PER_CPU_ALIGNED(struct qnode, qnodes[_Q_MAX_NODES]);
 
 /*
  * Generate the native code for queued_spin_unlock_slowpath(); provide NOPs for
@@ -410,7 +227,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
 	 * any MCS node. This is not the most elegant solution, but is
 	 * simple enough.
 	 */
-	if (unlikely(idx >= MAX_NODES)) {
+	if (unlikely(idx >= _Q_MAX_NODES)) {
 		lockevent_inc(lock_no_node);
 		while (!queued_spin_trylock(lock))
 			cpu_relax();
@@ -465,7 +282,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
 	 * head of the waitqueue.
 	 */
 	if (old & _Q_TAIL_MASK) {
-		prev = decode_tail(old);
+		prev = decode_tail(old, qnodes);
 
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
diff --git a/kernel/locking/qspinlock.h b/kernel/locking/qspinlock.h
new file mode 100644
index 000000000000..d4ceb9490365
--- /dev/null
+++ b/kernel/locking/qspinlock.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Queued spinlock defines
+ *
+ * This file contains macro definitions and functions shared between different
+ * qspinlock slow path implementations.
+ */
+#ifndef __LINUX_QSPINLOCK_H
+#define __LINUX_QSPINLOCK_H
+
+#include <asm-generic/percpu.h>
+#include <linux/percpu-defs.h>
+#include <asm-generic/qspinlock.h>
+#include <asm-generic/mcs_spinlock.h>
+
+#define _Q_MAX_NODES	4
+
+/*
+ * The pending bit spinning loop count.
+ * This heuristic is used to limit the number of lockword accesses
+ * made by atomic_cond_read_relaxed when waiting for the lock to
+ * transition out of the "== _Q_PENDING_VAL" state. We don't spin
+ * indefinitely because there's no guarantee that we'll make forward
+ * progress.
+ */
+#ifndef _Q_PENDING_LOOPS
+#define _Q_PENDING_LOOPS	1
+#endif
+
+/*
+ * On 64-bit architectures, the mcs_spinlock structure will be 16 bytes in
+ * size and four of them will fit nicely in one 64-byte cacheline. For
+ * pvqspinlock, however, we need more space for extra data. To accommodate
+ * that, we insert two more long words to pad it up to 32 bytes. IOW, only
+ * two of them can fit in a cacheline in this case. That is OK as it is rare
+ * to have more than 2 levels of slowpath nesting in actual use. We don't
+ * want to penalize pvqspinlocks to optimize for a rare case in native
+ * qspinlocks.
+ */
+struct qnode {
+	struct mcs_spinlock mcs;
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+	long reserved[2];
+#endif
+};
+
+/*
+ * We must be able to distinguish between no-tail and the tail at 0:0,
+ * therefore increment the cpu number by one.
+ */
+
+static inline __pure u32 encode_tail(int cpu, int idx)
+{
+	u32 tail;
+
+	tail  = (cpu + 1) << _Q_TAIL_CPU_OFFSET;
+	tail |= idx << _Q_TAIL_IDX_OFFSET; /* assume < 4 */
+
+	return tail;
+}
+
+static inline __pure struct mcs_spinlock *decode_tail(u32 tail, struct qnode *qnodes)
+{
+	int cpu = (tail >> _Q_TAIL_CPU_OFFSET) - 1;
+	int idx = (tail &  _Q_TAIL_IDX_MASK) >> _Q_TAIL_IDX_OFFSET;
+
+	return per_cpu_ptr(&qnodes[idx].mcs, cpu);
+}
+
+static inline __pure
+struct mcs_spinlock *grab_mcs_node(struct mcs_spinlock *base, int idx)
+{
+	return &((struct qnode *)base + idx)->mcs;
+}
+
+#define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK)
+
+#if _Q_PENDING_BITS == 8
+/**
+ * clear_pending - clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,* -> *,0,*
+ */
+static __always_inline void clear_pending(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->pending, 0);
+}
+
+/**
+ * clear_pending_set_locked - take ownership and clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,0 -> *,0,1
+ *
+ * Lock stealing is not allowed if this function is used.
+ */
+static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->locked_pending, _Q_LOCKED_VAL);
+}
+
+/*
+ * xchg_tail - Put in the new queue tail code word & retrieve previous one
+ * @lock : Pointer to queued spinlock structure
+ * @tail : The new queue tail code word
+ * Return: The previous queue tail code word
+ *
+ * xchg(lock, tail), which heads an address dependency
+ *
+ * p,*,* -> n,*,* ; prev = xchg(lock, node)
+ */
+static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
+{
+	/*
+	 * We can use relaxed semantics since the caller ensures that the
+	 * MCS node is properly initialized before updating the tail.
+	 */
+	return (u32)xchg_relaxed(&lock->tail,
+				 tail >> _Q_TAIL_OFFSET) << _Q_TAIL_OFFSET;
+}
+
+#else /* _Q_PENDING_BITS == 8 */
+
+/**
+ * clear_pending - clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,* -> *,0,*
+ */
+static __always_inline void clear_pending(struct qspinlock *lock)
+{
+	atomic_andnot(_Q_PENDING_VAL, &lock->val);
+}
+
+/**
+ * clear_pending_set_locked - take ownership and clear the pending bit.
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,1,0 -> *,0,1
+ */
+static __always_inline void clear_pending_set_locked(struct qspinlock *lock)
+{
+	atomic_add(-_Q_PENDING_VAL + _Q_LOCKED_VAL, &lock->val);
+}
+
+/**
+ * xchg_tail - Put in the new queue tail code word & retrieve previous one
+ * @lock : Pointer to queued spinlock structure
+ * @tail : The new queue tail code word
+ * Return: The previous queue tail code word
+ *
+ * xchg(lock, tail)
+ *
+ * p,*,* -> n,*,* ; prev = xchg(lock, node)
+ */
+static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail)
+{
+	u32 old, new;
+
+	old = atomic_read(&lock->val);
+	do {
+		new = (old & _Q_LOCKED_PENDING_MASK) | tail;
+		/*
+		 * We can use relaxed semantics since the caller ensures that
+		 * the MCS node is properly initialized before updating the
+		 * tail.
+		 */
+	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
+
+	return old;
+}
+#endif /* _Q_PENDING_BITS == 8 */
+
+/**
+ * queued_fetch_set_pending_acquire - fetch the whole lock value and set pending
+ * @lock : Pointer to queued spinlock structure
+ * Return: The previous lock value
+ *
+ * *,*,* -> *,1,*
+ */
+#ifndef queued_fetch_set_pending_acquire
+static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock)
+{
+	return atomic_fetch_or_acquire(_Q_PENDING_VAL, &lock->val);
+}
+#endif
+
+/**
+ * set_locked - Set the lock bit and own the lock
+ * @lock: Pointer to queued spinlock structure
+ *
+ * *,*,0 -> *,0,1
+ */
+static __always_inline void set_locked(struct qspinlock *lock)
+{
+	WRITE_ONCE(lock->locked, _Q_LOCKED_VAL);
+}
+
+#endif /* __LINUX_QSPINLOCK_H */
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:19 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:19 -0700
Subject: [PATCH bpf-next v4 03/25] locking: Allow obtaining result of arch_mcs_spin_lock_contended
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-4-memxor@gmail.com>

To support upcoming changes that require inspecting the return value
once the conditional waiting loop in arch_mcs_spin_lock_contended
terminates, modify the macro to preserve the result of
smp_cond_load_acquire. This enables checking the return value as needed,
which will help disambiguate the MCS node?s locked state in future
patches.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/locking/mcs_spinlock.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
index 16160ca8907f..5c92ba199b90 100644
--- a/kernel/locking/mcs_spinlock.h
+++ b/kernel/locking/mcs_spinlock.h
@@ -24,9 +24,7 @@
  * spinning, and smp_cond_load_acquire() provides that behavior.
  */
 #define arch_mcs_spin_lock_contended(l)					\
-do {									\
-	smp_cond_load_acquire(l, VAL);					\
-} while (0)
+	smp_cond_load_acquire(l, VAL)
 #endif
 
 #ifndef arch_mcs_spin_unlock_contended
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:20 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:20 -0700
Subject: [PATCH bpf-next v4 04/25] locking: Copy out qspinlock.c to kernel/bpf/rqspinlock.c
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-5-memxor@gmail.com>

In preparation for introducing a new lock implementation, Resilient
Queued Spin Lock, or rqspinlock, we first begin our modifications by
using the existing qspinlock.c code as the base. Simply copy the code to
a new file and rename functions and variables from 'queued' to
'resilient_queued'.

Since we place the file in kernel/bpf, include needs to be relative.

This helps each subsequent commit in clearly showing how and where the
code is being changed. The only change after a literal copy in this
commit is renaming the functions where necessary, and rename qnodes to
rqnodes. Let's also use EXPORT_SYMBOL_GPL for rqspinlock slowpath.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/rqspinlock.c | 410 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 410 insertions(+)
 create mode 100644 kernel/bpf/rqspinlock.c

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
new file mode 100644
index 000000000000..762108cb0f38
--- /dev/null
+++ b/kernel/bpf/rqspinlock.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Resilient Queued Spin Lock
+ *
+ * (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ * (C) Copyright 2013-2014,2018 Red Hat, Inc.
+ * (C) Copyright 2015 Intel Corp.
+ * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP
+ *
+ * Authors: Waiman Long <longman at redhat.com>
+ *          Peter Zijlstra <peterz at infradead.org>
+ */
+
+#ifndef _GEN_PV_LOCK_SLOWPATH
+
+#include <linux/smp.h>
+#include <linux/bug.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/mutex.h>
+#include <linux/prefetch.h>
+#include <asm/byteorder.h>
+#include <asm/qspinlock.h>
+#include <trace/events/lock.h>
+
+/*
+ * Include queued spinlock definitions and statistics code
+ */
+#include "../locking/qspinlock.h"
+#include "../locking/qspinlock_stat.h"
+
+/*
+ * The basic principle of a queue-based spinlock can best be understood
+ * by studying a classic queue-based spinlock implementation called the
+ * MCS lock. A copy of the original MCS lock paper ("Algorithms for Scalable
+ * Synchronization on Shared-Memory Multiprocessors by Mellor-Crummey and
+ * Scott") is available at
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=206115
+ *
+ * This queued spinlock implementation is based on the MCS lock, however to
+ * make it fit the 4 bytes we assume spinlock_t to be, and preserve its
+ * existing API, we must modify it somehow.
+ *
+ * In particular; where the traditional MCS lock consists of a tail pointer
+ * (8 bytes) and needs the next pointer (another 8 bytes) of its own node to
+ * unlock the next pending (next->locked), we compress both these: {tail,
+ * next->locked} into a single u32 value.
+ *
+ * Since a spinlock disables recursion of its own context and there is a limit
+ * to the contexts that can nest; namely: task, softirq, hardirq, nmi. As there
+ * are at most 4 nesting levels, it can be encoded by a 2-bit number. Now
+ * we can encode the tail by combining the 2-bit nesting level with the cpu
+ * number. With one byte for the lock value and 3 bytes for the tail, only a
+ * 32-bit word is now needed. Even though we only need 1 bit for the lock,
+ * we extend it to a full byte to achieve better performance for architectures
+ * that support atomic byte write.
+ *
+ * We also change the first spinner to spin on the lock bit instead of its
+ * node; whereby avoiding the need to carry a node from lock to unlock, and
+ * preserving existing lock API. This also makes the unlock code simpler and
+ * faster.
+ *
+ * N.B. The current implementation only supports architectures that allow
+ *      atomic operations on smaller 8-bit and 16-bit data types.
+ *
+ */
+
+#include "../locking/mcs_spinlock.h"
+
+/*
+ * Per-CPU queue node structures; we can never have more than 4 nested
+ * contexts: task, softirq, hardirq, nmi.
+ *
+ * Exactly fits one 64-byte cacheline on a 64-bit architecture.
+ *
+ * PV doubles the storage and uses the second cacheline for PV state.
+ */
+static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
+
+/*
+ * Generate the native code for resilient_queued_spin_unlock_slowpath(); provide NOPs
+ * for all the PV callbacks.
+ */
+
+static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
+static __always_inline void __pv_wait_node(struct mcs_spinlock *node,
+					   struct mcs_spinlock *prev) { }
+static __always_inline void __pv_kick_node(struct qspinlock *lock,
+					   struct mcs_spinlock *node) { }
+static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
+						   struct mcs_spinlock *node)
+						   { return 0; }
+
+#define pv_enabled()		false
+
+#define pv_init_node		__pv_init_node
+#define pv_wait_node		__pv_wait_node
+#define pv_kick_node		__pv_kick_node
+#define pv_wait_head_or_lock	__pv_wait_head_or_lock
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+#define resilient_queued_spin_lock_slowpath	native_resilient_queued_spin_lock_slowpath
+#endif
+
+#endif /* _GEN_PV_LOCK_SLOWPATH */
+
+/**
+ * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
+ * @lock: Pointer to queued spinlock structure
+ * @val: Current value of the queued spinlock 32-bit word
+ *
+ * (queue tail, pending bit, lock value)
+ *
+ *              fast     :    slow                                  :    unlock
+ *                       :                                          :
+ * uncontended  (0,0,0) -:--> (0,0,1) ------------------------------:--> (*,*,0)
+ *                       :       | ^--------.------.             /  :
+ *                       :       v           \      \            |  :
+ * pending               :    (0,1,1) +--> (0,1,0)   \           |  :
+ *                       :       | ^--'              |           |  :
+ *                       :       v                   |           |  :
+ * uncontended           :    (n,x,y) +--> (n,0,0) --'           |  :
+ *   queue               :       | ^--'                          |  :
+ *                       :       v                               |  :
+ * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
+ *   queue               :         ^--'                             :
+ */
+void __lockfunc resilient_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
+{
+	struct mcs_spinlock *prev, *next, *node;
+	u32 old, tail;
+	int idx;
+
+	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
+
+	if (pv_enabled())
+		goto pv_queue;
+
+	if (virt_spin_lock(lock))
+		return;
+
+	/*
+	 * Wait for in-progress pending->locked hand-overs with a bounded
+	 * number of spins so that we guarantee forward progress.
+	 *
+	 * 0,1,0 -> 0,0,1
+	 */
+	if (val == _Q_PENDING_VAL) {
+		int cnt = _Q_PENDING_LOOPS;
+		val = atomic_cond_read_relaxed(&lock->val,
+					       (VAL != _Q_PENDING_VAL) || !cnt--);
+	}
+
+	/*
+	 * If we observe any contention; queue.
+	 */
+	if (val & ~_Q_LOCKED_MASK)
+		goto queue;
+
+	/*
+	 * trylock || pending
+	 *
+	 * 0,0,* -> 0,1,* -> 0,0,1 pending, trylock
+	 */
+	val = queued_fetch_set_pending_acquire(lock);
+
+	/*
+	 * If we observe contention, there is a concurrent locker.
+	 *
+	 * Undo and queue; our setting of PENDING might have made the
+	 * n,0,0 -> 0,0,0 transition fail and it will now be waiting
+	 * on @next to become !NULL.
+	 */
+	if (unlikely(val & ~_Q_LOCKED_MASK)) {
+
+		/* Undo PENDING if we set it. */
+		if (!(val & _Q_PENDING_MASK))
+			clear_pending(lock);
+
+		goto queue;
+	}
+
+	/*
+	 * We're pending, wait for the owner to go away.
+	 *
+	 * 0,1,1 -> *,1,0
+	 *
+	 * this wait loop must be a load-acquire such that we match the
+	 * store-release that clears the locked bit and create lock
+	 * sequentiality; this is because not all
+	 * clear_pending_set_locked() implementations imply full
+	 * barriers.
+	 */
+	if (val & _Q_LOCKED_MASK)
+		smp_cond_load_acquire(&lock->locked, !VAL);
+
+	/*
+	 * take ownership and clear the pending bit.
+	 *
+	 * 0,1,0 -> 0,0,1
+	 */
+	clear_pending_set_locked(lock);
+	lockevent_inc(lock_pending);
+	return;
+
+	/*
+	 * End of pending bit optimistic spinning and beginning of MCS
+	 * queuing.
+	 */
+queue:
+	lockevent_inc(lock_slowpath);
+pv_queue:
+	node = this_cpu_ptr(&rqnodes[0].mcs);
+	idx = node->count++;
+	tail = encode_tail(smp_processor_id(), idx);
+
+	trace_contention_begin(lock, LCB_F_SPIN);
+
+	/*
+	 * 4 nodes are allocated based on the assumption that there will
+	 * not be nested NMIs taking spinlocks. That may not be true in
+	 * some architectures even though the chance of needing more than
+	 * 4 nodes will still be extremely unlikely. When that happens,
+	 * we fall back to spinning on the lock directly without using
+	 * any MCS node. This is not the most elegant solution, but is
+	 * simple enough.
+	 */
+	if (unlikely(idx >= _Q_MAX_NODES)) {
+		lockevent_inc(lock_no_node);
+		while (!queued_spin_trylock(lock))
+			cpu_relax();
+		goto release;
+	}
+
+	node = grab_mcs_node(node, idx);
+
+	/*
+	 * Keep counts of non-zero index values:
+	 */
+	lockevent_cond_inc(lock_use_node2 + idx - 1, idx);
+
+	/*
+	 * Ensure that we increment the head node->count before initialising
+	 * the actual node. If the compiler is kind enough to reorder these
+	 * stores, then an IRQ could overwrite our assignments.
+	 */
+	barrier();
+
+	node->locked = 0;
+	node->next = NULL;
+	pv_init_node(node);
+
+	/*
+	 * We touched a (possibly) cold cacheline in the per-cpu queue node;
+	 * attempt the trylock once more in the hope someone let go while we
+	 * weren't watching.
+	 */
+	if (queued_spin_trylock(lock))
+		goto release;
+
+	/*
+	 * Ensure that the initialisation of @node is complete before we
+	 * publish the updated tail via xchg_tail() and potentially link
+	 * @node into the waitqueue via WRITE_ONCE(prev->next, node) below.
+	 */
+	smp_wmb();
+
+	/*
+	 * Publish the updated tail.
+	 * We have already touched the queueing cacheline; don't bother with
+	 * pending stuff.
+	 *
+	 * p,*,* -> n,*,*
+	 */
+	old = xchg_tail(lock, tail);
+	next = NULL;
+
+	/*
+	 * if there was a previous node; link it and wait until reaching the
+	 * head of the waitqueue.
+	 */
+	if (old & _Q_TAIL_MASK) {
+		prev = decode_tail(old, rqnodes);
+
+		/* Link @node into the waitqueue. */
+		WRITE_ONCE(prev->next, node);
+
+		pv_wait_node(node, prev);
+		arch_mcs_spin_lock_contended(&node->locked);
+
+		/*
+		 * While waiting for the MCS lock, the next pointer may have
+		 * been set by another lock waiter. We optimistically load
+		 * the next pointer & prefetch the cacheline for writing
+		 * to reduce latency in the upcoming MCS unlock operation.
+		 */
+		next = READ_ONCE(node->next);
+		if (next)
+			prefetchw(next);
+	}
+
+	/*
+	 * we're at the head of the waitqueue, wait for the owner & pending to
+	 * go away.
+	 *
+	 * *,x,y -> *,0,0
+	 *
+	 * this wait loop must use a load-acquire such that we match the
+	 * store-release that clears the locked bit and create lock
+	 * sequentiality; this is because the set_locked() function below
+	 * does not imply a full barrier.
+	 *
+	 * The PV pv_wait_head_or_lock function, if active, will acquire
+	 * the lock and return a non-zero value. So we have to skip the
+	 * atomic_cond_read_acquire() call. As the next PV queue head hasn't
+	 * been designated yet, there is no way for the locked value to become
+	 * _Q_SLOW_VAL. So both the set_locked() and the
+	 * atomic_cmpxchg_relaxed() calls will be safe.
+	 *
+	 * If PV isn't active, 0 will be returned instead.
+	 *
+	 */
+	if ((val = pv_wait_head_or_lock(lock, node)))
+		goto locked;
+
+	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
+
+locked:
+	/*
+	 * claim the lock:
+	 *
+	 * n,0,0 -> 0,0,1 : lock, uncontended
+	 * *,*,0 -> *,*,1 : lock, contended
+	 *
+	 * If the queue head is the only one in the queue (lock value == tail)
+	 * and nobody is pending, clear the tail code and grab the lock.
+	 * Otherwise, we only need to grab the lock.
+	 */
+
+	/*
+	 * In the PV case we might already have _Q_LOCKED_VAL set, because
+	 * of lock stealing; therefore we must also allow:
+	 *
+	 * n,0,1 -> 0,0,1
+	 *
+	 * Note: at this point: (val & _Q_PENDING_MASK) == 0, because of the
+	 *       above wait condition, therefore any concurrent setting of
+	 *       PENDING will make the uncontended transition fail.
+	 */
+	if ((val & _Q_TAIL_MASK) == tail) {
+		if (atomic_try_cmpxchg_relaxed(&lock->val, &val, _Q_LOCKED_VAL))
+			goto release; /* No contention */
+	}
+
+	/*
+	 * Either somebody is queued behind us or _Q_PENDING_VAL got set
+	 * which will then detect the remaining tail and queue behind us
+	 * ensuring we'll see a @next.
+	 */
+	set_locked(lock);
+
+	/*
+	 * contended path; wait for next if not observed yet, release.
+	 */
+	if (!next)
+		next = smp_cond_load_relaxed(&node->next, (VAL));
+
+	arch_mcs_spin_unlock_contended(&next->locked);
+	pv_kick_node(lock, next);
+
+release:
+	trace_contention_end(lock, 0);
+
+	/*
+	 * release the node
+	 */
+	__this_cpu_dec(rqnodes[0].mcs.count);
+}
+EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
+
+/*
+ * Generate the paravirt code for resilient_queued_spin_unlock_slowpath().
+ */
+#if !defined(_GEN_PV_LOCK_SLOWPATH) && defined(CONFIG_PARAVIRT_SPINLOCKS)
+#define _GEN_PV_LOCK_SLOWPATH
+
+#undef  pv_enabled
+#define pv_enabled()	true
+
+#undef pv_init_node
+#undef pv_wait_node
+#undef pv_kick_node
+#undef pv_wait_head_or_lock
+
+#undef  resilient_queued_spin_lock_slowpath
+#define resilient_queued_spin_lock_slowpath	__pv_resilient_queued_spin_lock_slowpath
+
+#include "../locking/qspinlock_paravirt.h"
+#include "rqspinlock.c"
+
+bool nopvspin;
+static __init int parse_nopvspin(char *arg)
+{
+	nopvspin = true;
+	return 0;
+}
+early_param("nopvspin", parse_nopvspin);
+#endif
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:21 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:21 -0700
Subject: [PATCH bpf-next v4 05/25] rqspinlock: Add rqspinlock.h header
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-6-memxor@gmail.com>

This header contains the public declarations usable in the rest of the
kernel for rqspinlock.

Let's also type alias qspinlock to rqspinlock_t to ensure consistent use
of the new lock type. We want to remove dependence on the qspinlock type
in later patches as we need to provide a test-and-set fallback, hence
begin abstracting away from now onwards.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 19 +++++++++++++++++++
 kernel/bpf/rqspinlock.c          |  3 ++-
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 include/asm-generic/rqspinlock.h

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
new file mode 100644
index 000000000000..22f8094d0550
--- /dev/null
+++ b/include/asm-generic/rqspinlock.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Resilient Queued Spin Lock
+ *
+ * (C) Copyright 2024-2025 Meta Platforms, Inc. and affiliates.
+ *
+ * Authors: Kumar Kartikeya Dwivedi <memxor at gmail.com>
+ */
+#ifndef __ASM_GENERIC_RQSPINLOCK_H
+#define __ASM_GENERIC_RQSPINLOCK_H
+
+#include <linux/types.h>
+
+struct qspinlock;
+typedef struct qspinlock rqspinlock_t;
+
+extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+
+#endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 762108cb0f38..93e31633c2aa 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -23,6 +23,7 @@
 #include <asm/byteorder.h>
 #include <asm/qspinlock.h>
 #include <trace/events/lock.h>
+#include <asm/rqspinlock.h>
 
 /*
  * Include queued spinlock definitions and statistics code
@@ -127,7 +128,7 @@ static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
  * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
  *   queue               :         ^--'                             :
  */
-void __lockfunc resilient_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
+void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
 	u32 old, tail;
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:22 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:22 -0700
Subject: [PATCH bpf-next v4 06/25] rqspinlock: Drop PV and virtualization support
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-7-memxor@gmail.com>

Changes to rqspinlock in subsequent commits will be algorithmic
modifications, which won't remain in agreement with the implementations
of paravirt spin lock and virt_spin_lock support. These future changes
include measures for terminating waiting loops in slow path after a
certain point. While using a fair lock like qspinlock directly inside
virtual machines leads to suboptimal performance under certain
conditions, we cannot use the existing virtualization support before we
make it resilient as well.  Therefore, drop it for now.

Note that we need to drop qspinlock_stat.h, as it's only relevant in
case of CONFIG_PARAVIRT_SPINLOCKS=y, but we need to keep lock_events.h
in the includes, which was indirectly pulled in before.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/rqspinlock.c | 91 +----------------------------------------
 1 file changed, 1 insertion(+), 90 deletions(-)

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 93e31633c2aa..c2646cffc59e 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -11,8 +11,6 @@
  *          Peter Zijlstra <peterz at infradead.org>
  */
 
-#ifndef _GEN_PV_LOCK_SLOWPATH
-
 #include <linux/smp.h>
 #include <linux/bug.h>
 #include <linux/cpumask.h>
@@ -29,7 +27,7 @@
  * Include queued spinlock definitions and statistics code
  */
 #include "../locking/qspinlock.h"
-#include "../locking/qspinlock_stat.h"
+#include "../locking/lock_events.h"
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -75,38 +73,9 @@
  * contexts: task, softirq, hardirq, nmi.
  *
  * Exactly fits one 64-byte cacheline on a 64-bit architecture.
- *
- * PV doubles the storage and uses the second cacheline for PV state.
  */
 static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 
-/*
- * Generate the native code for resilient_queued_spin_unlock_slowpath(); provide NOPs
- * for all the PV callbacks.
- */
-
-static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
-static __always_inline void __pv_wait_node(struct mcs_spinlock *node,
-					   struct mcs_spinlock *prev) { }
-static __always_inline void __pv_kick_node(struct qspinlock *lock,
-					   struct mcs_spinlock *node) { }
-static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
-						   struct mcs_spinlock *node)
-						   { return 0; }
-
-#define pv_enabled()		false
-
-#define pv_init_node		__pv_init_node
-#define pv_wait_node		__pv_wait_node
-#define pv_kick_node		__pv_kick_node
-#define pv_wait_head_or_lock	__pv_wait_head_or_lock
-
-#ifdef CONFIG_PARAVIRT_SPINLOCKS
-#define resilient_queued_spin_lock_slowpath	native_resilient_queued_spin_lock_slowpath
-#endif
-
-#endif /* _GEN_PV_LOCK_SLOWPATH */
-
 /**
  * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
  * @lock: Pointer to queued spinlock structure
@@ -136,12 +105,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
-	if (pv_enabled())
-		goto pv_queue;
-
-	if (virt_spin_lock(lock))
-		return;
-
 	/*
 	 * Wait for in-progress pending->locked hand-overs with a bounded
 	 * number of spins so that we guarantee forward progress.
@@ -212,7 +175,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 queue:
 	lockevent_inc(lock_slowpath);
-pv_queue:
 	node = this_cpu_ptr(&rqnodes[0].mcs);
 	idx = node->count++;
 	tail = encode_tail(smp_processor_id(), idx);
@@ -251,7 +213,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	node->locked = 0;
 	node->next = NULL;
-	pv_init_node(node);
 
 	/*
 	 * We touched a (possibly) cold cacheline in the per-cpu queue node;
@@ -288,7 +249,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
 
-		pv_wait_node(node, prev);
 		arch_mcs_spin_lock_contended(&node->locked);
 
 		/*
@@ -312,23 +272,9 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * store-release that clears the locked bit and create lock
 	 * sequentiality; this is because the set_locked() function below
 	 * does not imply a full barrier.
-	 *
-	 * The PV pv_wait_head_or_lock function, if active, will acquire
-	 * the lock and return a non-zero value. So we have to skip the
-	 * atomic_cond_read_acquire() call. As the next PV queue head hasn't
-	 * been designated yet, there is no way for the locked value to become
-	 * _Q_SLOW_VAL. So both the set_locked() and the
-	 * atomic_cmpxchg_relaxed() calls will be safe.
-	 *
-	 * If PV isn't active, 0 will be returned instead.
-	 *
 	 */
-	if ((val = pv_wait_head_or_lock(lock, node)))
-		goto locked;
-
 	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
 
-locked:
 	/*
 	 * claim the lock:
 	 *
@@ -341,11 +287,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 
 	/*
-	 * In the PV case we might already have _Q_LOCKED_VAL set, because
-	 * of lock stealing; therefore we must also allow:
-	 *
-	 * n,0,1 -> 0,0,1
-	 *
 	 * Note: at this point: (val & _Q_PENDING_MASK) == 0, because of the
 	 *       above wait condition, therefore any concurrent setting of
 	 *       PENDING will make the uncontended transition fail.
@@ -369,7 +310,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		next = smp_cond_load_relaxed(&node->next, (VAL));
 
 	arch_mcs_spin_unlock_contended(&next->locked);
-	pv_kick_node(lock, next);
 
 release:
 	trace_contention_end(lock, 0);
@@ -380,32 +320,3 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	__this_cpu_dec(rqnodes[0].mcs.count);
 }
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
-
-/*
- * Generate the paravirt code for resilient_queued_spin_unlock_slowpath().
- */
-#if !defined(_GEN_PV_LOCK_SLOWPATH) && defined(CONFIG_PARAVIRT_SPINLOCKS)
-#define _GEN_PV_LOCK_SLOWPATH
-
-#undef  pv_enabled
-#define pv_enabled()	true
-
-#undef pv_init_node
-#undef pv_wait_node
-#undef pv_kick_node
-#undef pv_wait_head_or_lock
-
-#undef  resilient_queued_spin_lock_slowpath
-#define resilient_queued_spin_lock_slowpath	__pv_resilient_queued_spin_lock_slowpath
-
-#include "../locking/qspinlock_paravirt.h"
-#include "rqspinlock.c"
-
-bool nopvspin;
-static __init int parse_nopvspin(char *arg)
-{
-	nopvspin = true;
-	return 0;
-}
-early_param("nopvspin", parse_nopvspin);
-#endif
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:23 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:23 -0700
Subject: [PATCH bpf-next v4 07/25] rqspinlock: Add support for timeouts
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-8-memxor@gmail.com>

Introduce policy macro RES_CHECK_TIMEOUT which can be used to detect
when the timeout has expired for the slow path to return an error. It
depends on being passed two variables initialized to 0: ts, ret. The
'ts' parameter is of type rqspinlock_timeout.

This macro resolves to the (ret) expression so that it can be used in
statements like smp_cond_load_acquire to break the waiting loop
condition.

The 'spin' member is used to amortize the cost of checking time by
dispatching to the implementation every 64k iterations. The
'timeout_end' member is used to keep track of the timestamp that denotes
the end of the waiting period. The 'ret' parameter denotes the status of
the timeout, and can be checked in the slow path to detect timeouts
after waiting loops.

The 'duration' member is used to store the timeout duration for each
waiting loop. The default timeout value defined in the header
(RES_DEF_TIMEOUT) is 0.25 seconds.

This macro will be used as a condition for waiting loops in the slow
path.  Since each waiting loop applies a fresh timeout using the same
rqspinlock_timeout, we add a new RES_RESET_TIMEOUT as well to ensure the
values can be easily reinitialized to the default state.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h |  6 +++++
 kernel/bpf/rqspinlock.c          | 45 ++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 22f8094d0550..5dd4dd8aee69 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -10,10 +10,16 @@
 #define __ASM_GENERIC_RQSPINLOCK_H
 
 #include <linux/types.h>
+#include <vdso/time64.h>
 
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
 
 extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 
+/*
+ * Default timeout for waiting loops is 0.25 seconds
+ */
+#define RES_DEF_TIMEOUT (NSEC_PER_SEC / 4)
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index c2646cffc59e..0d8964b4d44a 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -6,9 +6,11 @@
  * (C) Copyright 2013-2014,2018 Red Hat, Inc.
  * (C) Copyright 2015 Intel Corp.
  * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP
+ * (C) Copyright 2024-2025 Meta Platforms, Inc. and affiliates.
  *
  * Authors: Waiman Long <longman at redhat.com>
  *          Peter Zijlstra <peterz at infradead.org>
+ *          Kumar Kartikeya Dwivedi <memxor at gmail.com>
  */
 
 #include <linux/smp.h>
@@ -22,6 +24,7 @@
 #include <asm/qspinlock.h>
 #include <trace/events/lock.h>
 #include <asm/rqspinlock.h>
+#include <linux/timekeeping.h>
 
 /*
  * Include queued spinlock definitions and statistics code
@@ -68,6 +71,45 @@
 
 #include "../locking/mcs_spinlock.h"
 
+struct rqspinlock_timeout {
+	u64 timeout_end;
+	u64 duration;
+	u16 spin;
+};
+
+static noinline int check_timeout(struct rqspinlock_timeout *ts)
+{
+	u64 time = ktime_get_mono_fast_ns();
+
+	if (!ts->timeout_end) {
+		ts->timeout_end = time + ts->duration;
+		return 0;
+	}
+
+	if (time > ts->timeout_end)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+#define RES_CHECK_TIMEOUT(ts, ret)                    \
+	({                                            \
+		if (!(ts).spin++)                     \
+			(ret) = check_timeout(&(ts)); \
+		(ret);                                \
+	})
+
+/*
+ * Initialize the 'spin' member.
+ */
+#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 1; })
+
+/*
+ * We only need to reset 'timeout_end', 'spin' will just wrap around as necessary.
+ * Duration is defined for each spin attempt, so set it here.
+ */
+#define RES_RESET_TIMEOUT(ts, _duration) ({ (ts).timeout_end = 0; (ts).duration = _duration; })
+
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
  * contexts: task, softirq, hardirq, nmi.
@@ -100,11 +142,14 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
+	struct rqspinlock_timeout ts;
 	u32 old, tail;
 	int idx;
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
+	RES_INIT_TIMEOUT(ts);
+
 	/*
 	 * Wait for in-progress pending->locked hand-overs with a bounded
 	 * number of spins so that we guarantee forward progress.
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:24 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:24 -0700
Subject: [PATCH bpf-next v4 08/25] rqspinlock: Hardcode cond_acquire loops for arm64
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-9-memxor@gmail.com>

Currently, for rqspinlock usage, the implementation of
smp_cond_load_acquire (and thus, atomic_cond_read_acquire) are
susceptible to stalls on arm64, because they do not guarantee that the
conditional expression will be repeatedly invoked if the address being
loaded from is not written to by other CPUs. When support for
event-streams is absent (which unblocks stuck WFE-based loops every
~100us), we may end up being stuck forever.

This causes a problem for us, as we need to repeatedly invoke the
RES_CHECK_TIMEOUT in the spin loop to break out when the timeout
expires.

Let us import the smp_cond_load_acquire_timewait implementation Ankur is
proposing in [0], and then fallback to it once it is merged.

While we rely on the implementation to amortize the cost of sampling
check_timeout for us, it will not happen when event stream support is
unavailable. This is not the common case, and it would be difficult to
fit our logic in the time_expr_ns >= time_limit_ns comparison, hence
just let it be.

  [0]: https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora at oracle.com

Cc: Ankur Arora <ankur.a.arora at oracle.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 arch/arm64/include/asm/rqspinlock.h | 93 +++++++++++++++++++++++++++++
 kernel/bpf/rqspinlock.c             | 15 +++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm64/include/asm/rqspinlock.h

diff --git a/arch/arm64/include/asm/rqspinlock.h b/arch/arm64/include/asm/rqspinlock.h
new file mode 100644
index 000000000000..5b80785324b6
--- /dev/null
+++ b/arch/arm64/include/asm/rqspinlock.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RQSPINLOCK_H
+#define _ASM_RQSPINLOCK_H
+
+#include <asm/barrier.h>
+
+/*
+ * Hardcode res_smp_cond_load_acquire implementations for arm64 to a custom
+ * version based on [0]. In rqspinlock code, our conditional expression involves
+ * checking the value _and_ additionally a timeout. However, on arm64, the
+ * WFE-based implementation may never spin again if no stores occur to the
+ * locked byte in the lock word. As such, we may be stuck forever if
+ * event-stream based unblocking is not available on the platform for WFE spin
+ * loops (arch_timer_evtstrm_available).
+ *
+ * Once support for smp_cond_load_acquire_timewait [0] lands, we can drop this
+ * copy-paste.
+ *
+ * While we rely on the implementation to amortize the cost of sampling
+ * cond_expr for us, it will not happen when event stream support is
+ * unavailable, time_expr check is amortized. This is not the common case, and
+ * it would be difficult to fit our logic in the time_expr_ns >= time_limit_ns
+ * comparison, hence just let it be. In case of event-stream, the loop is woken
+ * up at microsecond granularity.
+ *
+ * [0]: https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora at oracle.com
+ */
+
+#ifndef smp_cond_load_acquire_timewait
+
+#define smp_cond_time_check_count	200
+
+#define __smp_cond_load_relaxed_spinwait(ptr, cond_expr, time_expr_ns,	\
+					 time_limit_ns) ({		\
+	typeof(ptr) __PTR = (ptr);					\
+	__unqual_scalar_typeof(*ptr) VAL;				\
+	unsigned int __count = 0;					\
+	for (;;) {							\
+		VAL = READ_ONCE(*__PTR);				\
+		if (cond_expr)						\
+			break;						\
+		cpu_relax();						\
+		if (__count++ < smp_cond_time_check_count)		\
+			continue;					\
+		if ((time_expr_ns) >= (time_limit_ns))			\
+			break;						\
+		__count = 0;						\
+	}								\
+	(typeof(*ptr))VAL;						\
+})
+
+#define __smp_cond_load_acquire_timewait(ptr, cond_expr,		\
+					 time_expr_ns, time_limit_ns)	\
+({									\
+	typeof(ptr) __PTR = (ptr);					\
+	__unqual_scalar_typeof(*ptr) VAL;				\
+	for (;;) {							\
+		VAL = smp_load_acquire(__PTR);				\
+		if (cond_expr)						\
+			break;						\
+		__cmpwait_relaxed(__PTR, VAL);				\
+		if ((time_expr_ns) >= (time_limit_ns))			\
+			break;						\
+	}								\
+	(typeof(*ptr))VAL;						\
+})
+
+#define smp_cond_load_acquire_timewait(ptr, cond_expr,			\
+				      time_expr_ns, time_limit_ns)	\
+({									\
+	__unqual_scalar_typeof(*ptr) _val;				\
+	int __wfe = arch_timer_evtstrm_available();			\
+									\
+	if (likely(__wfe)) {						\
+		_val = __smp_cond_load_acquire_timewait(ptr, cond_expr,	\
+							time_expr_ns,	\
+							time_limit_ns);	\
+	} else {							\
+		_val = __smp_cond_load_relaxed_spinwait(ptr, cond_expr,	\
+							time_expr_ns,	\
+							time_limit_ns);	\
+		smp_acquire__after_ctrl_dep();				\
+	}								\
+	(typeof(*ptr))_val;						\
+})
+
+#endif
+
+#define res_smp_cond_load_acquire_timewait(v, c) smp_cond_load_acquire_timewait(v, c, 0, 1)
+
+#include <asm-generic/rqspinlock.h>
+
+#endif /* _ASM_RQSPINLOCK_H */
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 0d8964b4d44a..d429b923b58f 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -92,12 +92,21 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
 	return 0;
 }
 
+/*
+ * Do not amortize with spins when res_smp_cond_load_acquire is defined,
+ * as the macro does internal amortization for us.
+ */
+#ifndef res_smp_cond_load_acquire
 #define RES_CHECK_TIMEOUT(ts, ret)                    \
 	({                                            \
 		if (!(ts).spin++)                     \
 			(ret) = check_timeout(&(ts)); \
 		(ret);                                \
 	})
+#else
+#define RES_CHECK_TIMEOUT(ts, ret, mask)	      \
+	({ (ret) = check_timeout(&(ts)); })
+#endif
 
 /*
  * Initialize the 'spin' member.
@@ -118,6 +127,12 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
  */
 static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
 
+#ifndef res_smp_cond_load_acquire
+#define res_smp_cond_load_acquire(v, c) smp_cond_load_acquire(v, c)
+#endif
+
+#define res_atomic_cond_read_acquire(v, c) res_smp_cond_load_acquire(&(v)->counter, (c))
+
 /**
  * resilient_queued_spin_lock_slowpath - acquire the queued spinlock
  * @lock: Pointer to queued spinlock structure
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:25 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:25 -0700
Subject: [PATCH bpf-next v4 09/25] rqspinlock: Protect pending bit owners from stalls
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-10-memxor@gmail.com>

The pending bit is used to avoid queueing in case the lock is
uncontended, and has demonstrated benefits for the 2 contender scenario,
esp. on x86. In case the pending bit is acquired and we wait for the
locked bit to disappear, we may get stuck due to the lock owner not
making progress. Hence, this waiting loop must be protected with a
timeout check.

To perform a graceful recovery once we decide to abort our lock
acquisition attempt in this case, we must unset the pending bit since we
own it. All waiters undoing their changes and exiting gracefully allows
the lock word to be restored to the unlocked state once all participants
(owner, waiters) have been recovered, and the lock remains usable.
Hence, set the pending bit back to zero before returning to the caller.

Introduce a lockevent (rqspinlock_lock_timeout) to capture timeout
event statistics.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h  |  2 +-
 kernel/bpf/rqspinlock.c           | 32 ++++++++++++++++++++++++++-----
 kernel/locking/lock_events_list.h |  5 +++++
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 5dd4dd8aee69..9bd11cb7acd6 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -15,7 +15,7 @@
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
 
-extern void resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 
 /*
  * Default timeout for waiting loops is 0.25 seconds
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index d429b923b58f..262294cfd36f 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -138,6 +138,10 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
  * @lock: Pointer to queued spinlock structure
  * @val: Current value of the queued spinlock 32-bit word
  *
+ * Return:
+ * * 0		- Lock was acquired successfully.
+ * * -ETIMEDOUT - Lock acquisition failed because of timeout.
+ *
  * (queue tail, pending bit, lock value)
  *
  *              fast     :    slow                                  :    unlock
@@ -154,12 +158,12 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
  * contended             :    (*,x,y) +--> (*,0,0) ---> (*,0,1) -'  :
  *   queue               :         ^--'                             :
  */
-void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
+int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 {
 	struct mcs_spinlock *prev, *next, *node;
 	struct rqspinlock_timeout ts;
+	int idx, ret = 0;
 	u32 old, tail;
-	int idx;
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
@@ -217,8 +221,25 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * clear_pending_set_locked() implementations imply full
 	 * barriers.
 	 */
-	if (val & _Q_LOCKED_MASK)
-		smp_cond_load_acquire(&lock->locked, !VAL);
+	if (val & _Q_LOCKED_MASK) {
+		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
+		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret));
+	}
+
+	if (ret) {
+		/*
+		 * We waited for the locked bit to go back to 0, as the pending
+		 * waiter, but timed out. We need to clear the pending bit since
+		 * we own it. Once a stuck owner has been recovered, the lock
+		 * must be restored to a valid state, hence removing the pending
+		 * bit is necessary.
+		 *
+		 * *,1,* -> *,0,*
+		 */
+		clear_pending(lock);
+		lockevent_inc(rqspinlock_lock_timeout);
+		return ret;
+	}
 
 	/*
 	 * take ownership and clear the pending bit.
@@ -227,7 +248,7 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	clear_pending_set_locked(lock);
 	lockevent_inc(lock_pending);
-	return;
+	return 0;
 
 	/*
 	 * End of pending bit optimistic spinning and beginning of MCS
@@ -378,5 +399,6 @@ void __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * release the node
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 97fb6f3f840a..c5286249994d 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -49,6 +49,11 @@ LOCK_EVENT(lock_use_node4)	/* # of locking ops that use 4th percpu node */
 LOCK_EVENT(lock_no_node)	/* # of locking ops w/o using percpu node    */
 #endif /* CONFIG_QUEUED_SPINLOCKS */
 
+/*
+ * Locking events for Resilient Queued Spin Lock
+ */
+LOCK_EVENT(rqspinlock_lock_timeout)	/* # of locking ops that timeout	*/
+
 /*
  * Locking events for rwsem
  */
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:26 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:26 -0700
Subject: [PATCH bpf-next v4 10/25] rqspinlock: Protect waiters in queue from stalls
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-11-memxor@gmail.com>

Implement the wait queue cleanup algorithm for rqspinlock. There are
three forms of waiters in the original queued spin lock algorithm. The
first is the waiter which acquires the pending bit and spins on the lock
word without forming a wait queue. The second is the head waiter that is
the first waiter heading the wait queue. The third form is of all the
non-head waiters queued behind the head, waiting to be signalled through
their MCS node to overtake the responsibility of the head.

In this commit, we are concerned with the second and third kind. First,
we augment the waiting loop of the head of the wait queue with a
timeout. When this timeout happens, all waiters part of the wait queue
will abort their lock acquisition attempts. This happens in three steps.
First, the head breaks out of its loop waiting for pending and locked
bits to turn to 0, and non-head waiters break out of their MCS node spin
(more on that later). Next, every waiter (head or non-head) attempts to
check whether they are also the tail waiter, in such a case they attempt
to zero out the tail word and allow a new queue to be built up for this
lock. If they succeed, they have no one to signal next in the queue to
stop spinning. Otherwise, they signal the MCS node of the next waiter to
break out of its spin and try resetting the tail word back to 0. This
goes on until the tail waiter is found. In case of races, the new tail
will be responsible for performing the same task, as the old tail will
then fail to reset the tail word and wait for its next pointer to be
updated before it signals the new tail to do the same.

We terminate the whole wait queue because of two main reasons. Firstly,
we eschew per-waiter timeouts with one applied at the head of the wait
queue.  This allows everyone to break out faster once we've seen the
owner / pending waiter not responding for the timeout duration from the
head.  Secondly, it avoids complicated synchronization, because when not
leaving in FIFO order, prev's next pointer needs to be fixed up etc.

Lastly, all of these waiters release the rqnode and return to the
caller. This patch underscores the point that rqspinlock's timeout does
not apply to each waiter individually, and cannot be relied upon as an
upper bound. It is possible for the rqspinlock waiters to return early
from a failed lock acquisition attempt as soon as stalls are detected.

The head waiter cannot directly WRITE_ONCE the tail to zero, as it may
race with a concurrent xchg and a non-head waiter linking its MCS node
to the head's MCS node through 'prev->next' assignment.

One notable thing is that we must use RES_DEF_TIMEOUT * 2 as our maximum
duration for the waiting loop (for the wait queue head), since we may
have both the owner and pending bit waiter ahead of us, and in the worst
case, need to span their maximum permitted critical section lengths.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/rqspinlock.c | 55 ++++++++++++++++++++++++++++++++++++++---
 kernel/bpf/rqspinlock.h | 48 +++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 3 deletions(-)
 create mode 100644 kernel/bpf/rqspinlock.h

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 262294cfd36f..65c2b41d8937 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -77,6 +77,8 @@ struct rqspinlock_timeout {
 	u16 spin;
 };
 
+#define RES_TIMEOUT_VAL	2
+
 static noinline int check_timeout(struct rqspinlock_timeout *ts)
 {
 	u64 time = ktime_get_mono_fast_ns();
@@ -325,12 +327,18 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * head of the waitqueue.
 	 */
 	if (old & _Q_TAIL_MASK) {
+		int val;
+
 		prev = decode_tail(old, rqnodes);
 
 		/* Link @node into the waitqueue. */
 		WRITE_ONCE(prev->next, node);
 
-		arch_mcs_spin_lock_contended(&node->locked);
+		val = arch_mcs_spin_lock_contended(&node->locked);
+		if (val == RES_TIMEOUT_VAL) {
+			ret = -EDEADLK;
+			goto waitq_timeout;
+		}
 
 		/*
 		 * While waiting for the MCS lock, the next pointer may have
@@ -353,8 +361,49 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * store-release that clears the locked bit and create lock
 	 * sequentiality; this is because the set_locked() function below
 	 * does not imply a full barrier.
+	 *
+	 * We use RES_DEF_TIMEOUT * 2 as the duration, as RES_DEF_TIMEOUT is
+	 * meant to span maximum allowed time per critical section, and we may
+	 * have both the owner of the lock and the pending bit waiter ahead of
+	 * us.
 	 */
-	val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK));
+	RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT * 2);
+	val = res_atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK) ||
+					   RES_CHECK_TIMEOUT(ts, ret));
+
+waitq_timeout:
+	if (ret) {
+		/*
+		 * If the tail is still pointing to us, then we are the final waiter,
+		 * and are responsible for resetting the tail back to 0. Otherwise, if
+		 * the cmpxchg operation fails, we signal the next waiter to take exit
+		 * and try the same. For a waiter with tail node 'n':
+		 *
+		 * n,*,* -> 0,*,*
+		 *
+		 * When performing cmpxchg for the whole word (NR_CPUS > 16k), it is
+		 * possible locked/pending bits keep changing and we see failures even
+		 * when we remain the head of wait queue. However, eventually,
+		 * pending bit owner will unset the pending bit, and new waiters
+		 * will queue behind us. This will leave the lock owner in
+		 * charge, and it will eventually either set locked bit to 0, or
+		 * leave it as 1, allowing us to make progress.
+		 *
+		 * We terminate the whole wait queue for two reasons. Firstly,
+		 * we eschew per-waiter timeouts with one applied at the head of
+		 * the wait queue.  This allows everyone to break out faster
+		 * once we've seen the owner / pending waiter not responding for
+		 * the timeout duration from the head.  Secondly, it avoids
+		 * complicated synchronization, because when not leaving in FIFO
+		 * order, prev's next pointer needs to be fixed up etc.
+		 */
+		if (!try_cmpxchg_tail(lock, tail, 0)) {
+			next = smp_cond_load_relaxed(&node->next, VAL);
+			WRITE_ONCE(next->locked, RES_TIMEOUT_VAL);
+		}
+		lockevent_inc(rqspinlock_lock_timeout);
+		goto release;
+	}
 
 	/*
 	 * claim the lock:
@@ -399,6 +448,6 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 * release the node
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
diff --git a/kernel/bpf/rqspinlock.h b/kernel/bpf/rqspinlock.h
new file mode 100644
index 000000000000..5d8cb1b1aab4
--- /dev/null
+++ b/kernel/bpf/rqspinlock.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Resilient Queued Spin Lock defines
+ *
+ * (C) Copyright 2024-2025 Meta Platforms, Inc. and affiliates.
+ *
+ * Authors: Kumar Kartikeya Dwivedi <memxor at gmail.com>
+ */
+#ifndef __LINUX_RQSPINLOCK_H
+#define __LINUX_RQSPINLOCK_H
+
+#include "../locking/qspinlock.h"
+
+/*
+ * try_cmpxchg_tail - Return result of cmpxchg of tail word with a new value
+ * @lock: Pointer to queued spinlock structure
+ * @tail: The tail to compare against
+ * @new_tail: The new queue tail code word
+ * Return: Bool to indicate whether the cmpxchg operation succeeded
+ *
+ * This is used by the head of the wait queue to clean up the queue.
+ * Provides relaxed ordering, since observers only rely on initialized
+ * state of the node which was made visible through the xchg_tail operation,
+ * i.e. through the smp_wmb preceding xchg_tail.
+ *
+ * We avoid using 16-bit cmpxchg, which is not available on all architectures.
+ */
+static __always_inline bool try_cmpxchg_tail(struct qspinlock *lock, u32 tail, u32 new_tail)
+{
+	u32 old, new;
+
+	old = atomic_read(&lock->val);
+	do {
+		/*
+		 * Is the tail part we compare to already stale? Fail.
+		 */
+		if ((old & _Q_TAIL_MASK) != tail)
+			return false;
+		/*
+		 * Encode latest locked/pending state for new tail.
+		 */
+		new = (old & _Q_LOCKED_PENDING_MASK) | new_tail;
+	} while (!atomic_try_cmpxchg_relaxed(&lock->val, &old, new));
+
+	return true;
+}
+
+#endif /* __LINUX_RQSPINLOCK_H */
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:27 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:27 -0700
Subject: [PATCH bpf-next v4 11/25] rqspinlock: Protect waiters in trylock fallback from stalls
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-12-memxor@gmail.com>

When we run out of maximum rqnodes, the original queued spin lock slow
path falls back to a try lock. In such a case, we are again susceptible
to stalls in case the lock owner fails to make progress. We use the
timeout as a fallback to break out of this loop and return to the
caller. This is a fallback for an extreme edge case, when on the same
CPU we run out of all 4 qnodes. When could this happen? We are in slow
path in task context, we get interrupted by an IRQ, which while in the
slow path gets interrupted by an NMI, whcih in the slow path gets
another nested NMI, which enters the slow path. All of the interruptions
happen after node->count++.

We use RES_DEF_TIMEOUT as our spinning duration, but in the case of this
fallback, no fairness is guaranteed, so the duration may be too small
for contended cases, as the waiting time is not bounded. Since this is
an extreme corner case, let's just prefer timing out instead of
attempting to spin for longer.

Reviewed-by: Barret Rhoden <brho at google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 kernel/bpf/rqspinlock.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 65c2b41d8937..361d452f027c 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -275,8 +275,14 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	if (unlikely(idx >= _Q_MAX_NODES)) {
 		lockevent_inc(lock_no_node);
-		while (!queued_spin_trylock(lock))
+		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
+		while (!queued_spin_trylock(lock)) {
+			if (RES_CHECK_TIMEOUT(ts, ret)) {
+				lockevent_inc(rqspinlock_lock_timeout);
+				break;
+			}
 			cpu_relax();
+		}
 		goto release;
 	}
 
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:28 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:28 -0700
Subject: [PATCH bpf-next v4 12/25] rqspinlock: Add deadlock detection and recovery
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-13-memxor@gmail.com>

While the timeout logic provides guarantees for the waiter's forward
progress, the time until a stalling waiter unblocks can still be long.
The default timeout of 1/4 sec can be excessively long for some use
cases.  Additionally, custom timeouts may exacerbate recovery time.

Introduce logic to detect common cases of deadlocks and perform quicker
recovery. This is done by dividing the time from entry into the locking
slow path until the timeout into intervals of 1 ms. Then, after each
interval elapses, deadlock detection is performed, while also polling
the lock word to ensure we can quickly break out of the detection logic
and proceed with lock acquisition.

A 'held_locks' table is maintained per-CPU where the entry at the bottom
denotes a lock being waited for or already taken. Entries coming before
it denote locks that are already held. The current CPU's table can thus
be looked at to detect AA deadlocks. The tables from other CPUs can be
looked at to discover ABBA situations. Finally, when a matching entry
for the lock being taken on the current CPU is found on some other CPU,
a deadlock situation is detected. This function can take a long time,
therefore the lock word is constantly polled in each loop iteration to
ensure we can preempt detection and proceed with lock acquisition, using
the is_lock_released check.

We set 'spin' member of rqspinlock_timeout struct to 0 to trigger
deadlock checks immediately to perform faster recovery.

Note: Extending lock word size by 4 bytes to record owner CPU can allow
faster detection for ABBA. It is typically the owner which participates
in a ABBA situation. However, to keep compatibility with existing lock
words in the kernel (struct qspinlock), and given deadlocks are a rare
event triggered by bugs, we choose to favor compatibility over faster
detection.

The release_held_lock_entry function requires an smp_wmb, while the
release store on unlock will provide the necessary ordering for us. Add
comments to document the subtleties of why this is correct. It is
possible for stores to be reordered still, but in the context of the
deadlock detection algorithm, a release barrier is sufficient and
needn't be stronger for unlock's case.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 100 +++++++++++++++++
 kernel/bpf/rqspinlock.c          | 187 ++++++++++++++++++++++++++++---
 2 files changed, 273 insertions(+), 14 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 9bd11cb7acd6..34c3dcb4299e 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <vdso/time64.h>
+#include <linux/percpu.h>
 
 struct qspinlock;
 typedef struct qspinlock rqspinlock_t;
@@ -22,4 +23,103 @@ extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
  */
 #define RES_DEF_TIMEOUT (NSEC_PER_SEC / 4)
 
+/*
+ * Choose 31 as it makes rqspinlock_held cacheline-aligned.
+ */
+#define RES_NR_HELD 31
+
+struct rqspinlock_held {
+	int cnt;
+	void *locks[RES_NR_HELD];
+};
+
+DECLARE_PER_CPU_ALIGNED(struct rqspinlock_held, rqspinlock_held_locks);
+
+static __always_inline void grab_held_lock_entry(void *lock)
+{
+	int cnt = this_cpu_inc_return(rqspinlock_held_locks.cnt);
+
+	if (unlikely(cnt > RES_NR_HELD)) {
+		/* Still keep the inc so we decrement later. */
+		return;
+	}
+
+	/*
+	 * Implied compiler barrier in per-CPU operations; otherwise we can have
+	 * the compiler reorder inc with write to table, allowing interrupts to
+	 * overwrite and erase our write to the table (as on interrupt exit it
+	 * will be reset to NULL).
+	 *
+	 * It is fine for cnt inc to be reordered wrt remote readers though,
+	 * they won't observe our entry until the cnt update is visible, that's
+	 * all.
+	 */
+	this_cpu_write(rqspinlock_held_locks.locks[cnt - 1], lock);
+}
+
+/*
+ * We simply don't support out-of-order unlocks, and keep the logic simple here.
+ * The verifier prevents BPF programs from unlocking out-of-order, and the same
+ * holds for in-kernel users.
+ *
+ * It is possible to run into misdetection scenarios of AA deadlocks on the same
+ * CPU, and missed ABBA deadlocks on remote CPUs if this function pops entries
+ * out of order (due to lock A, lock B, unlock A, unlock B) pattern. The correct
+ * logic to preserve right entries in the table would be to walk the array of
+ * held locks and swap and clear out-of-order entries, but that's too
+ * complicated and we don't have a compelling use case for out of order unlocking.
+ */
+static __always_inline void release_held_lock_entry(void)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+	if (unlikely(rqh->cnt > RES_NR_HELD))
+		goto dec;
+	WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL);
+dec:
+	/*
+	 * Reordering of clearing above with inc and its write in
+	 * grab_held_lock_entry that came before us (in same acquisition
+	 * attempt) is ok, we either see a valid entry or NULL when it's
+	 * visible.
+	 *
+	 * But this helper is invoked when we unwind upon failing to acquire the
+	 * lock. Unlike the unlock path which constitutes a release store after
+	 * we clear the entry, we need to emit a write barrier here. Otherwise,
+	 * we may have a situation as follows:
+	 *
+	 * <error> for lock B
+	 * release_held_lock_entry
+	 *
+	 * try_cmpxchg_acquire for lock A
+	 * grab_held_lock_entry
+	 *
+	 * Lack of any ordering means reordering may occur such that dec, inc
+	 * are done before entry is overwritten. This permits a remote lock
+	 * holder of lock B (which this CPU failed to acquire) to now observe it
+	 * as being attempted on this CPU, and may lead to misdetection (if this
+	 * CPU holds a lock it is attempting to acquire, leading to false ABBA
+	 * diagnosis).
+	 *
+	 * In case of unlock, we will always do a release on the lock word after
+	 * releasing the entry, ensuring that other CPUs cannot hold the lock
+	 * (and make conclusions about deadlocks) until the entry has been
+	 * cleared on the local CPU, preventing any anomalies. Reordering is
+	 * still possible there, but a remote CPU cannot observe a lock in our
+	 * table which it is already holding, since visibility entails our
+	 * release store for the said lock has not retired.
+	 *
+	 * In theory we don't have a problem if the dec and WRITE_ONCE above get
+	 * reordered with each other, we either notice an empty NULL entry on
+	 * top (if dec succeeds WRITE_ONCE), or a potentially stale entry which
+	 * cannot be observed (if dec precedes WRITE_ONCE).
+	 *
+	 * Emit the write barrier _before_ the dec, this permits dec-inc
+	 * reordering but that is harmless as we'd have new entry set to NULL
+	 * already, i.e. they cannot precede the NULL store above.
+	 */
+	smp_wmb();
+	this_cpu_dec(rqspinlock_held_locks.cnt);
+}
+
 #endif /* __ASM_GENERIC_RQSPINLOCK_H */
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 361d452f027c..bddbcc47d38f 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -31,6 +31,7 @@
  */
 #include "../locking/qspinlock.h"
 #include "../locking/lock_events.h"
+#include "rqspinlock.h"
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -74,16 +75,147 @@
 struct rqspinlock_timeout {
 	u64 timeout_end;
 	u64 duration;
+	u64 cur;
 	u16 spin;
 };
 
 #define RES_TIMEOUT_VAL	2
 
-static noinline int check_timeout(struct rqspinlock_timeout *ts)
+DEFINE_PER_CPU_ALIGNED(struct rqspinlock_held, rqspinlock_held_locks);
+EXPORT_SYMBOL_GPL(rqspinlock_held_locks);
+
+static bool is_lock_released(rqspinlock_t *lock, u32 mask, struct rqspinlock_timeout *ts)
+{
+	if (!(atomic_read_acquire(&lock->val) & (mask)))
+		return true;
+	return false;
+}
+
+static noinline int check_deadlock_AA(rqspinlock_t *lock, u32 mask,
+				      struct rqspinlock_timeout *ts)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+	int cnt = min(RES_NR_HELD, rqh->cnt);
+
+	/*
+	 * Return an error if we hold the lock we are attempting to acquire.
+	 * We'll iterate over max 32 locks; no need to do is_lock_released.
+	 */
+	for (int i = 0; i < cnt - 1; i++) {
+		if (rqh->locks[i] == lock)
+			return -EDEADLK;
+	}
+	return 0;
+}
+
+/*
+ * This focuses on the most common case of ABBA deadlocks (or ABBA involving
+ * more locks, which reduce to ABBA). This is not exhaustive, and we rely on
+ * timeouts as the final line of defense.
+ */
+static noinline int check_deadlock_ABBA(rqspinlock_t *lock, u32 mask,
+					struct rqspinlock_timeout *ts)
+{
+	struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+	int rqh_cnt = min(RES_NR_HELD, rqh->cnt);
+	void *remote_lock;
+	int cpu;
+
+	/*
+	 * Find the CPU holding the lock that we want to acquire. If there is a
+	 * deadlock scenario, we will read a stable set on the remote CPU and
+	 * find the target. This would be a constant time operation instead of
+	 * O(NR_CPUS) if we could determine the owning CPU from a lock value, but
+	 * that requires increasing the size of the lock word.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct rqspinlock_held *rqh_cpu = per_cpu_ptr(&rqspinlock_held_locks, cpu);
+		int real_cnt = READ_ONCE(rqh_cpu->cnt);
+		int cnt = min(RES_NR_HELD, real_cnt);
+
+		/*
+		 * Let's ensure to break out of this loop if the lock is available for
+		 * us to potentially acquire.
+		 */
+		if (is_lock_released(lock, mask, ts))
+			return 0;
+
+		/*
+		 * Skip ourselves, and CPUs whose count is less than 2, as they need at
+		 * least one held lock and one acquisition attempt (reflected as top
+		 * most entry) to participate in an ABBA deadlock.
+		 *
+		 * If cnt is more than RES_NR_HELD, it means the current lock being
+		 * acquired won't appear in the table, and other locks in the table are
+		 * already held, so we can't determine ABBA.
+		 */
+		if (cpu == smp_processor_id() || real_cnt < 2 || real_cnt > RES_NR_HELD)
+			continue;
+
+		/*
+		 * Obtain the entry at the top, this corresponds to the lock the
+		 * remote CPU is attempting to acquire in a deadlock situation,
+		 * and would be one of the locks we hold on the current CPU.
+		 */
+		remote_lock = READ_ONCE(rqh_cpu->locks[cnt - 1]);
+		/*
+		 * If it is NULL, we've raced and cannot determine a deadlock
+		 * conclusively, skip this CPU.
+		 */
+		if (!remote_lock)
+			continue;
+		/*
+		 * Find if the lock we're attempting to acquire is held by this CPU.
+		 * Don't consider the topmost entry, as that must be the latest lock
+		 * being held or acquired.  For a deadlock, the target CPU must also
+		 * attempt to acquire a lock we hold, so for this search only 'cnt - 1'
+		 * entries are important.
+		 */
+		for (int i = 0; i < cnt - 1; i++) {
+			if (READ_ONCE(rqh_cpu->locks[i]) != lock)
+				continue;
+			/*
+			 * We found our lock as held on the remote CPU.  Is the
+			 * acquisition attempt on the remote CPU for a lock held
+			 * by us?  If so, we have a deadlock situation, and need
+			 * to recover.
+			 */
+			for (int i = 0; i < rqh_cnt - 1; i++) {
+				if (rqh->locks[i] == remote_lock)
+					return -EDEADLK;
+			}
+			/*
+			 * Inconclusive; retry again later.
+			 */
+			return 0;
+		}
+	}
+	return 0;
+}
+
+static noinline int check_deadlock(rqspinlock_t *lock, u32 mask,
+				   struct rqspinlock_timeout *ts)
+{
+	int ret;
+
+	ret = check_deadlock_AA(lock, mask, ts);
+	if (ret)
+		return ret;
+	ret = check_deadlock_ABBA(lock, mask, ts);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
+				  struct rqspinlock_timeout *ts)
 {
 	u64 time = ktime_get_mono_fast_ns();
+	u64 prev = ts->cur;
 
 	if (!ts->timeout_end) {
+		ts->cur = time;
 		ts->timeout_end = time + ts->duration;
 		return 0;
 	}
@@ -91,6 +223,15 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
 	if (time > ts->timeout_end)
 		return -ETIMEDOUT;
 
+	/*
+	 * A millisecond interval passed from last time? Trigger deadlock
+	 * checks.
+	 */
+	if (prev + NSEC_PER_MSEC < time) {
+		ts->cur = time;
+		return check_deadlock(lock, mask, ts);
+	}
+
 	return 0;
 }
 
@@ -99,21 +240,22 @@ static noinline int check_timeout(struct rqspinlock_timeout *ts)
  * as the macro does internal amortization for us.
  */
 #ifndef res_smp_cond_load_acquire
-#define RES_CHECK_TIMEOUT(ts, ret)                    \
-	({                                            \
-		if (!(ts).spin++)                     \
-			(ret) = check_timeout(&(ts)); \
-		(ret);                                \
+#define RES_CHECK_TIMEOUT(ts, ret, mask)                              \
+	({                                                            \
+		if (!(ts).spin++)                                     \
+			(ret) = check_timeout((lock), (mask), &(ts)); \
+		(ret);                                                \
 	})
 #else
-#define RES_CHECK_TIMEOUT(ts, ret, mask)	      \
+#define RES_CHECK_TIMEOUT(ts, ret, mask)			      \
 	({ (ret) = check_timeout(&(ts)); })
 #endif
 
 /*
  * Initialize the 'spin' member.
+ * Set spin member to 0 to trigger AA/ABBA checks immediately.
  */
-#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 1; })
+#define RES_INIT_TIMEOUT(ts) ({ (ts).spin = 0; })
 
 /*
  * We only need to reset 'timeout_end', 'spin' will just wrap around as necessary.
@@ -142,6 +284,7 @@ static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]);
  *
  * Return:
  * * 0		- Lock was acquired successfully.
+ * * -EDEADLK	- Lock acquisition failed because of AA/ABBA deadlock.
  * * -ETIMEDOUT - Lock acquisition failed because of timeout.
  *
  * (queue tail, pending bit, lock value)
@@ -212,6 +355,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		goto queue;
 	}
 
+	/*
+	 * Grab an entry in the held locks array, to enable deadlock detection.
+	 */
+	grab_held_lock_entry(lock);
+
 	/*
 	 * We're pending, wait for the owner to go away.
 	 *
@@ -225,7 +373,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	if (val & _Q_LOCKED_MASK) {
 		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
-		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret));
+		res_smp_cond_load_acquire(&lock->locked, !VAL || RES_CHECK_TIMEOUT(ts, ret, _Q_LOCKED_MASK));
 	}
 
 	if (ret) {
@@ -240,7 +388,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		 */
 		clear_pending(lock);
 		lockevent_inc(rqspinlock_lock_timeout);
-		return ret;
+		goto err_release_entry;
 	}
 
 	/*
@@ -258,6 +406,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 queue:
 	lockevent_inc(lock_slowpath);
+	/*
+	 * Grab deadlock detection entry for the queue path.
+	 */
+	grab_held_lock_entry(lock);
+
 	node = this_cpu_ptr(&rqnodes[0].mcs);
 	idx = node->count++;
 	tail = encode_tail(smp_processor_id(), idx);
@@ -277,9 +430,9 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 		lockevent_inc(lock_no_node);
 		RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT);
 		while (!queued_spin_trylock(lock)) {
-			if (RES_CHECK_TIMEOUT(ts, ret)) {
+			if (RES_CHECK_TIMEOUT(ts, ret, ~0u)) {
 				lockevent_inc(rqspinlock_lock_timeout);
-				break;
+				goto err_release_node;
 			}
 			cpu_relax();
 		}
@@ -375,7 +528,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT * 2);
 	val = res_atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK) ||
-					   RES_CHECK_TIMEOUT(ts, ret));
+					   RES_CHECK_TIMEOUT(ts, ret, _Q_LOCKED_PENDING_MASK));
 
 waitq_timeout:
 	if (ret) {
@@ -408,7 +561,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 			WRITE_ONCE(next->locked, RES_TIMEOUT_VAL);
 		}
 		lockevent_inc(rqspinlock_lock_timeout);
-		goto release;
+		goto err_release_node;
 	}
 
 	/*
@@ -455,5 +608,11 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	 */
 	__this_cpu_dec(rqnodes[0].mcs.count);
 	return ret;
+err_release_node:
+	trace_contention_end(lock, ret);
+	__this_cpu_dec(rqnodes[0].mcs.count);
+err_release_entry:
+	release_held_lock_entry();
+	return ret;
 }
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:29 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:29 -0700
Subject: [PATCH bpf-next v4 13/25] rqspinlock: Add a test-and-set fallback
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-14-memxor@gmail.com>

Include a test-and-set fallback when queued spinlock support is not
available. Introduce a rqspinlock type to act as a fallback when
qspinlock support is absent.

Include ifdef guards to ensure the slow path in this file is only
compiled when CONFIG_QUEUED_SPINLOCKS=y. Subsequent patches will add
further logic to ensure fallback to the test-and-set implementation
when queued spinlock support is unavailable on an architecture.

Unlike other waiting loops in rqspinlock code, the one for test-and-set
has no theoretical upper bound under contention, therefore we need a
longer timeout than usual. Bump it up to a second in this case.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/asm-generic/rqspinlock.h | 17 ++++++++++++
 kernel/bpf/rqspinlock.c          | 46 ++++++++++++++++++++++++++++++--
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 34c3dcb4299e..12f72c4a97cd 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -12,11 +12,28 @@
 #include <linux/types.h>
 #include <vdso/time64.h>
 #include <linux/percpu.h>
+#ifdef CONFIG_QUEUED_SPINLOCKS
+#include <asm/qspinlock.h>
+#endif
+
+struct rqspinlock {
+	union {
+		atomic_t val;
+		u32 locked;
+	};
+};
 
 struct qspinlock;
+#ifdef CONFIG_QUEUED_SPINLOCKS
 typedef struct qspinlock rqspinlock_t;
+#else
+typedef struct rqspinlock rqspinlock_t;
+#endif
 
+extern int resilient_tas_spin_lock(rqspinlock_t *lock);
+#ifdef CONFIG_QUEUED_SPINLOCKS
 extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
+#endif
 
 /*
  * Default timeout for waiting loops is 0.25 seconds
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index bddbcc47d38f..714dfab5caa8 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -21,7 +21,9 @@
 #include <linux/mutex.h>
 #include <linux/prefetch.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_QUEUED_SPINLOCKS
 #include <asm/qspinlock.h>
+#endif
 #include <trace/events/lock.h>
 #include <asm/rqspinlock.h>
 #include <linux/timekeeping.h>
@@ -29,9 +31,12 @@
 /*
  * Include queued spinlock definitions and statistics code
  */
+#ifdef CONFIG_QUEUED_SPINLOCKS
 #include "../locking/qspinlock.h"
 #include "../locking/lock_events.h"
 #include "rqspinlock.h"
+#include "../locking/mcs_spinlock.h"
+#endif
 
 /*
  * The basic principle of a queue-based spinlock can best be understood
@@ -70,8 +75,6 @@
  *
  */
 
-#include "../locking/mcs_spinlock.h"
-
 struct rqspinlock_timeout {
 	u64 timeout_end;
 	u64 duration;
@@ -263,6 +266,43 @@ static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
  */
 #define RES_RESET_TIMEOUT(ts, _duration) ({ (ts).timeout_end = 0; (ts).duration = _duration; })
 
+/*
+ * Provide a test-and-set fallback for cases when queued spin lock support is
+ * absent from the architecture.
+ */
+int __lockfunc resilient_tas_spin_lock(rqspinlock_t *lock)
+{
+	struct rqspinlock_timeout ts;
+	int val, ret = 0;
+
+	RES_INIT_TIMEOUT(ts);
+	grab_held_lock_entry(lock);
+
+	/*
+	 * Since the waiting loop's time is dependent on the amount of
+	 * contention, a short timeout unlike rqspinlock waiting loops
+	 * isn't enough. Choose a second as the timeout value.
+	 */
+	RES_RESET_TIMEOUT(ts, NSEC_PER_SEC);
+retry:
+	val = atomic_read(&lock->val);
+
+	if (val || !atomic_try_cmpxchg(&lock->val, &val, 1)) {
+		if (RES_CHECK_TIMEOUT(ts, ret, ~0u))
+			goto out;
+		cpu_relax();
+		goto retry;
+	}
+
+	return 0;
+out:
+	release_held_lock_entry();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(resilient_tas_spin_lock);
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+
 /*
  * Per-CPU queue node structures; we can never have more than 4 nested
  * contexts: task, softirq, hardirq, nmi.
@@ -616,3 +656,5 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath);
+
+#endif /* CONFIG_QUEUED_SPINLOCKS */
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:30 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:30 -0700
Subject: [PATCH bpf-next v4 14/25] rqspinlock: Add basic support for CONFIG_PARAVIRT
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-15-memxor@gmail.com>

We ripped out PV and virtualization related bits from rqspinlock in an
earlier commit, however, a fair lock performs poorly within a virtual
machine when the lock holder is preempted. As such, retain the
virt_spin_lock fallback to test and set lock, but with timeout and
deadlock detection. We can do this by simply depending on the
resilient_tas_spin_lock implementation from the previous patch.

We don't integrate support for CONFIG_PARAVIRT_SPINLOCKS yet, as that
requires more involved algorithmic changes and introduces more
complexity. It can be done when the need arises in the future.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 arch/x86/include/asm/rqspinlock.h | 33 +++++++++++++++++++++++++++++++
 include/asm-generic/rqspinlock.h  | 14 +++++++++++++
 kernel/bpf/rqspinlock.c           |  3 +++
 3 files changed, 50 insertions(+)
 create mode 100644 arch/x86/include/asm/rqspinlock.h

diff --git a/arch/x86/include/asm/rqspinlock.h b/arch/x86/include/asm/rqspinlock.h
new file mode 100644
index 000000000000..24a885449ee6
--- /dev/null
+++ b/arch/x86/include/asm/rqspinlock.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_RQSPINLOCK_H
+#define _ASM_X86_RQSPINLOCK_H
+
+#include <asm/paravirt.h>
+
+#ifdef CONFIG_PARAVIRT
+DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
+
+#define resilient_virt_spin_lock_enabled resilient_virt_spin_lock_enabled
+static __always_inline bool resilient_virt_spin_lock_enabled(void)
+{
+       return static_branch_likely(&virt_spin_lock_key);
+}
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+typedef struct qspinlock rqspinlock_t;
+#else
+typedef struct rqspinlock rqspinlock_t;
+#endif
+extern int resilient_tas_spin_lock(rqspinlock_t *lock);
+
+#define resilient_virt_spin_lock resilient_virt_spin_lock
+static inline int resilient_virt_spin_lock(rqspinlock_t *lock)
+{
+	return resilient_tas_spin_lock(lock);
+}
+
+#endif /* CONFIG_PARAVIRT */
+
+#include <asm-generic/rqspinlock.h>
+
+#endif /* _ASM_X86_RQSPINLOCK_H */
diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h
index 12f72c4a97cd..a837c6b6abd9 100644
--- a/include/asm-generic/rqspinlock.h
+++ b/include/asm-generic/rqspinlock.h
@@ -35,6 +35,20 @@ extern int resilient_tas_spin_lock(rqspinlock_t *lock);
 extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val);
 #endif
 
+#ifndef resilient_virt_spin_lock_enabled
+static __always_inline bool resilient_virt_spin_lock_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef resilient_virt_spin_lock
+static __always_inline int resilient_virt_spin_lock(rqspinlock_t *lock)
+{
+	return 0;
+}
+#endif
+
 /*
  * Default timeout for waiting loops is 0.25 seconds
  */
diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 714dfab5caa8..ed21ee010063 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -352,6 +352,9 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
+	if (resilient_virt_spin_lock_enabled())
+		return resilient_virt_spin_lock(lock);
+
 	RES_INIT_TIMEOUT(ts);
 
 	/*
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:40 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:40 -0700
Subject: [PATCH bpf-next v4 24/25] bpf: Maintain FIFO property for rqspinlock unlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-25-memxor@gmail.com>

Since out-of-order unlocks are unsupported for rqspinlock, and irqsave
variants enforce strict FIFO ordering anyway, make the same change for
normal non-irqsave variants, such that FIFO ordering is enforced.

Two new verifier state fields (active_lock_id, active_lock_ptr) are used
to denote the top of the stack, and prev_id and prev_ptr are ascertained
whenever popping the topmost entry through an unlock.

Take special care to make these fields part of the state comparison in
refsafe.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 include/linux/bpf_verifier.h |  3 +++
 kernel/bpf/verifier.c        | 33 ++++++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index bc073a48aed9..9734544b6957 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -268,6 +268,7 @@ struct bpf_reference_state {
 		REF_TYPE_LOCK		= (1 << 3),
 		REF_TYPE_RES_LOCK 	= (1 << 4),
 		REF_TYPE_RES_LOCK_IRQ	= (1 << 5),
+		REF_TYPE_LOCK_MASK	= REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
 	} type;
 	/* Track each reference created with a unique id, even if the same
 	 * instruction creates the reference multiple times (eg, via CALL).
@@ -434,6 +435,8 @@ struct bpf_verifier_state {
 	u32 active_locks;
 	u32 active_preempt_locks;
 	u32 active_irq_id;
+	u32 active_lock_id;
+	void *active_lock_ptr;
 	bool active_rcu_lock;
 
 	bool speculative;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 29121ad32a89..4057081e996f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1428,6 +1428,8 @@ static int copy_reference_state(struct bpf_verifier_state *dst, const struct bpf
 	dst->active_preempt_locks = src->active_preempt_locks;
 	dst->active_rcu_lock = src->active_rcu_lock;
 	dst->active_irq_id = src->active_irq_id;
+	dst->active_lock_id = src->active_lock_id;
+	dst->active_lock_ptr = src->active_lock_ptr;
 	return 0;
 }
 
@@ -1527,6 +1529,8 @@ static int acquire_lock_state(struct bpf_verifier_env *env, int insn_idx, enum r
 	s->ptr = ptr;
 
 	state->active_locks++;
+	state->active_lock_id = id;
+	state->active_lock_ptr = ptr;
 	return 0;
 }
 
@@ -1577,16 +1581,24 @@ static bool find_reference_state(struct bpf_verifier_state *state, int ptr_id)
 
 static int release_lock_state(struct bpf_verifier_state *state, int type, int id, void *ptr)
 {
+	void *prev_ptr = NULL;
+	u32 prev_id = 0;
 	int i;
 
 	for (i = 0; i < state->acquired_refs; i++) {
-		if (state->refs[i].type != type)
-			continue;
-		if (state->refs[i].id == id && state->refs[i].ptr == ptr) {
+		if (state->refs[i].type == type && state->refs[i].id == id &&
+		    state->refs[i].ptr == ptr) {
 			release_reference_state(state, i);
 			state->active_locks--;
+			/* Reassign active lock (id, ptr). */
+			state->active_lock_id = prev_id;
+			state->active_lock_ptr = prev_ptr;
 			return 0;
 		}
+		if (state->refs[i].type & REF_TYPE_LOCK_MASK) {
+			prev_id = state->refs[i].id;
+			prev_ptr = state->refs[i].ptr;
+		}
 	}
 	return -EINVAL;
 }
@@ -8342,6 +8354,14 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
 			type = REF_TYPE_RES_LOCK;
 		else
 			type = REF_TYPE_LOCK;
+		if (!find_lock_state(cur, type, reg->id, ptr)) {
+			verbose(env, "%s_unlock of different lock\n", lock_str);
+			return -EINVAL;
+		}
+		if (reg->id != cur->active_lock_id || ptr != cur->active_lock_ptr) {
+			verbose(env, "%s_unlock cannot be out of order\n", lock_str);
+			return -EINVAL;
+		}
 		if (release_lock_state(cur, type, reg->id, ptr)) {
 			verbose(env, "%s_unlock of different lock\n", lock_str);
 			return -EINVAL;
@@ -12534,8 +12554,7 @@ static int check_reg_allocation_locked(struct bpf_verifier_env *env, struct bpf_
 
 	if (!env->cur_state->active_locks)
 		return -EINVAL;
-	s = find_lock_state(env->cur_state, REF_TYPE_LOCK | REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ,
-			    id, ptr);
+	s = find_lock_state(env->cur_state, REF_TYPE_LOCK_MASK, id, ptr);
 	if (!s) {
 		verbose(env, "held lock and object are not in the same allocation\n");
 		return -EINVAL;
@@ -18591,6 +18610,10 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
 	if (!check_ids(old->active_irq_id, cur->active_irq_id, idmap))
 		return false;
 
+	if (!check_ids(old->active_lock_id, cur->active_lock_id, idmap) ||
+	    old->active_lock_ptr != cur->active_lock_ptr)
+		return false;
+
 	for (i = 0; i < old->acquired_refs; i++) {
 		if (!check_ids(old->refs[i].id, cur->refs[i].id, idmap) ||
 		    old->refs[i].type != cur->refs[i].type)
-- 
2.47.1



From memxor at gmail.com  Sat Mar 15 21:05:41 2025
From: memxor at gmail.com (Kumar Kartikeya Dwivedi)
Date: Sat, 15 Mar 2025 21:05:41 -0700
Subject: [PATCH bpf-next v4 25/25] selftests/bpf: Add tests for rqspinlock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <20250316040541.108729-26-memxor@gmail.com>

Introduce selftests that trigger AA, ABBA deadlocks, and test the edge
case where the held locks table runs out of entries, since we then
fallback to the timeout as the final line of defense. Also exercise
verifier's AA detection where applicable.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor at gmail.com>
---
 .../selftests/bpf/prog_tests/res_spin_lock.c  |  98 +++++++
 tools/testing/selftests/bpf/progs/irq.c       |  53 ++++
 .../selftests/bpf/progs/res_spin_lock.c       | 143 ++++++++++
 .../selftests/bpf/progs/res_spin_lock_fail.c  | 244 ++++++++++++++++++
 4 files changed, 538 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock.c
 create mode 100644 tools/testing/selftests/bpf/progs/res_spin_lock_fail.c

diff --git a/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c b/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
new file mode 100644
index 000000000000..115287ba441b
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/res_spin_lock.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024-2025 Meta Platforms, Inc. and affiliates. */
+#include <test_progs.h>
+#include <network_helpers.h>
+#include <sys/sysinfo.h>
+
+#include "res_spin_lock.skel.h"
+#include "res_spin_lock_fail.skel.h"
+
+void test_res_spin_lock_failure(void)
+{
+	RUN_TESTS(res_spin_lock_fail);
+}
+
+static volatile int skip;
+
+static void *spin_lock_thread(void *arg)
+{
+	int err, prog_fd = *(u32 *) arg;
+	LIBBPF_OPTS(bpf_test_run_opts, topts,
+		.data_in = &pkt_v4,
+		.data_size_in = sizeof(pkt_v4),
+		.repeat = 10000,
+	);
+
+	while (!READ_ONCE(skip)) {
+		err = bpf_prog_test_run_opts(prog_fd, &topts);
+		ASSERT_OK(err, "test_run");
+		ASSERT_OK(topts.retval, "test_run retval");
+	}
+	pthread_exit(arg);
+}
+
+void test_res_spin_lock_success(void)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts,
+		.data_in = &pkt_v4,
+		.data_size_in = sizeof(pkt_v4),
+		.repeat = 1,
+	);
+	struct res_spin_lock *skel;
+	pthread_t thread_id[16];
+	int prog_fd, i, err;
+	void *ret;
+
+	if (get_nprocs() < 2) {
+		test__skip();
+		return;
+	}
+
+	skel = res_spin_lock__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "res_spin_lock__open_and_load"))
+		return;
+	/* AA deadlock */
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	ASSERT_OK(err, "error");
+	ASSERT_OK(topts.retval, "retval");
+
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_held_lock_max);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	ASSERT_OK(err, "error");
+	ASSERT_OK(topts.retval, "retval");
+
+	/* Multi-threaded ABBA deadlock. */
+
+	prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_AB);
+	for (i = 0; i < 16; i++) {
+		int err;
+
+		err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd);
+		if (!ASSERT_OK(err, "pthread_create"))
+			goto end;
+	}
+
+	topts.retval = 0;
+	topts.repeat = 1000;
+	int fd = bpf_program__fd(skel->progs.res_spin_lock_test_BA);
+	while (!topts.retval && !err && !READ_ONCE(skel->bss->err)) {
+		err = bpf_prog_test_run_opts(fd, &topts);
+	}
+
+	WRITE_ONCE(skip, true);
+
+	for (i = 0; i < 16; i++) {
+		if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join"))
+			goto end;
+		if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd"))
+			goto end;
+	}
+
+	ASSERT_EQ(READ_ONCE(skel->bss->err), -EDEADLK, "timeout err");
+	ASSERT_OK(err, "err");
+	ASSERT_EQ(topts.retval, -EDEADLK, "timeout");
+end:
+	res_spin_lock__destroy(skel);
+	return;
+}
diff --git a/tools/testing/selftests/bpf/progs/irq.c b/tools/testing/selftests/bpf/progs/irq.c
index 298d48d7886d..74d912b22de9 100644
--- a/tools/testing/selftests/bpf/progs/irq.c
+++ b/tools/testing/selftests/bpf/progs/irq.c
@@ -11,6 +11,9 @@ extern void bpf_local_irq_save(unsigned long *) __weak __ksym;
 extern void bpf_local_irq_restore(unsigned long *) __weak __ksym;
 extern int bpf_copy_from_user_str(void *dst, u32 dst__sz, const void *unsafe_ptr__ign, u64 flags) __weak __ksym;
 
+struct bpf_res_spin_lock lockA __hidden SEC(".data.A");
+struct bpf_res_spin_lock lockB __hidden SEC(".data.B");
+
 SEC("?tc")
 __failure __msg("arg#0 doesn't point to an irq flag on stack")
 int irq_save_bad_arg(struct __sk_buff *ctx)
@@ -510,4 +513,54 @@ int irq_sleepable_global_subprog_indirect(void *ctx)
 	return 0;
 }
 
+SEC("?tc")
+__failure __msg("cannot restore irq state out of order")
+int irq_ooo_lock_cond_inv(struct __sk_buff *ctx)
+{
+	unsigned long flags1, flags2;
+
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags1))
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&lockB, &flags2)) {
+		bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+		return 0;
+	}
+
+	bpf_res_spin_unlock_irqrestore(&lockB, &flags1);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags2);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("function calls are not allowed")
+int irq_wrong_kfunc_class_1(struct __sk_buff *ctx)
+{
+	unsigned long flags1;
+
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags1))
+		return 0;
+	/* For now, bpf_local_irq_restore is not allowed in critical section,
+	 * but this test ensures error will be caught with kfunc_class when it's
+	 * opened up. Tested by temporarily permitting this kfunc in critical
+	 * section.
+	 */
+	bpf_local_irq_restore(&flags1);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("function calls are not allowed")
+int irq_wrong_kfunc_class_2(struct __sk_buff *ctx)
+{
+	unsigned long flags1, flags2;
+
+	bpf_local_irq_save(&flags1);
+	if (bpf_res_spin_lock_irqsave(&lockA, &flags2))
+		return 0;
+	bpf_local_irq_restore(&flags2);
+	bpf_res_spin_unlock_irqrestore(&lockA, &flags1);
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/res_spin_lock.c b/tools/testing/selftests/bpf/progs/res_spin_lock.c
new file mode 100644
index 000000000000..b33385dfbd35
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/res_spin_lock.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024-2025 Meta Platforms, Inc. and affiliates. */
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+#define EDEADLK 35
+#define ETIMEDOUT 110
+
+struct arr_elem {
+	struct bpf_res_spin_lock lock;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 64);
+	__type(key, int);
+	__type(value, struct arr_elem);
+} arrmap SEC(".maps");
+
+struct bpf_res_spin_lock lockA __hidden SEC(".data.A");
+struct bpf_res_spin_lock lockB __hidden SEC(".data.B");
+
+SEC("tc")
+int res_spin_lock_test(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem1, *elem2;
+	int r;
+
+	elem1 = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem1)
+		return -1;
+	elem2 = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem2)
+		return -1;
+
+	r = bpf_res_spin_lock(&elem1->lock);
+	if (r)
+		return r;
+	if (!bpf_res_spin_lock(&elem2->lock)) {
+		bpf_res_spin_unlock(&elem2->lock);
+		bpf_res_spin_unlock(&elem1->lock);
+		return -1;
+	}
+	bpf_res_spin_unlock(&elem1->lock);
+	return 0;
+}
+
+SEC("tc")
+int res_spin_lock_test_AB(struct __sk_buff *ctx)
+{
+	int r;
+
+	r = bpf_res_spin_lock(&lockA);
+	if (r)
+		return !r;
+	/* Only unlock if we took the lock. */
+	if (!bpf_res_spin_lock(&lockB))
+		bpf_res_spin_unlock(&lockB);
+	bpf_res_spin_unlock(&lockA);
+	return 0;
+}
+
+int err;
+
+SEC("tc")
+int res_spin_lock_test_BA(struct __sk_buff *ctx)
+{
+	int r;
+
+	r = bpf_res_spin_lock(&lockB);
+	if (r)
+		return !r;
+	if (!bpf_res_spin_lock(&lockA))
+		bpf_res_spin_unlock(&lockA);
+	else
+		err = -EDEADLK;
+	bpf_res_spin_unlock(&lockB);
+	return err ?: 0;
+}
+
+SEC("tc")
+int res_spin_lock_test_held_lock_max(struct __sk_buff *ctx)
+{
+	struct bpf_res_spin_lock *locks[48] = {};
+	struct arr_elem *e;
+	u64 time_beg, time;
+	int ret = 0, i;
+
+	_Static_assert(ARRAY_SIZE(((struct rqspinlock_held){}).locks) == 31,
+		       "RES_NR_HELD assumed to be 31");
+
+	for (i = 0; i < 34; i++) {
+		int key = i;
+
+		/* We cannot pass in i as it will get spilled/filled by the compiler and
+		 * loses bounds in verifier state.
+		 */
+		e = bpf_map_lookup_elem(&arrmap, &key);
+		if (!e)
+			return 1;
+		locks[i] = &e->lock;
+	}
+
+	for (; i < 48; i++) {
+		int key = i - 2;
+
+		/* We cannot pass in i as it will get spilled/filled by the compiler and
+		 * loses bounds in verifier state.
+		 */
+		e = bpf_map_lookup_elem(&arrmap, &key);
+		if (!e)
+			return 1;
+		locks[i] = &e->lock;
+	}
+
+	time_beg = bpf_ktime_get_ns();
+	for (i = 0; i < 34; i++) {
+		if (bpf_res_spin_lock(locks[i]))
+			goto end;
+	}
+
+	/* Trigger AA, after exhausting entries in the held lock table. This
+	 * time, only the timeout can save us, as AA detection won't succeed.
+	 */
+	if (!bpf_res_spin_lock(locks[34])) {
+		bpf_res_spin_unlock(locks[34]);
+		ret = 1;
+		goto end;
+	}
+
+end:
+	for (i = i - 1; i >= 0; i--)
+		bpf_res_spin_unlock(locks[i]);
+	time = bpf_ktime_get_ns() - time_beg;
+	/* Time spent should be easily above our limit (1/4 s), since AA
+	 * detection won't be expedited due to lack of held lock entry.
+	 */
+	return ret ?: (time > 1000000000 / 4 ? 0 : 1);
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c b/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c
new file mode 100644
index 000000000000..330682a88c16
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024-2025 Meta Platforms, Inc. and affiliates. */
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
+#include "bpf_experimental.h"
+
+struct arr_elem {
+	struct bpf_res_spin_lock lock;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 1);
+	__type(key, int);
+	__type(value, struct arr_elem);
+} arrmap SEC(".maps");
+
+long value;
+
+struct bpf_spin_lock lock __hidden SEC(".data.A");
+struct bpf_res_spin_lock res_lock __hidden SEC(".data.B");
+
+SEC("?tc")
+__failure __msg("point to map value or allocated object")
+int res_spin_lock_arg(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock((struct bpf_res_spin_lock *)bpf_core_cast(&elem->lock, struct __sk_buff));
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("AA deadlock detected")
+int res_spin_lock_AA(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock(&elem->lock);
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("AA deadlock detected")
+int res_spin_lock_cond_AA(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock))
+		return 0;
+	bpf_res_spin_lock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_mismatch_1(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock))
+		return 0;
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_mismatch_2(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	bpf_res_spin_unlock(&elem->lock);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_irq_mismatch_1(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_local_irq_save(&f1);
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("unlock of different lock")
+int res_spin_lock_irq_mismatch_2(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&res_lock, &f1))
+		return 0;
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__success
+int res_spin_lock_ooo(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock(&res_lock))
+		return 0;
+	if (bpf_res_spin_lock(&elem->lock)) {
+		bpf_res_spin_unlock(&res_lock);
+		return 0;
+	}
+	bpf_res_spin_unlock(&elem->lock);
+	bpf_res_spin_unlock(&res_lock);
+	return 0;
+}
+
+SEC("?tc")
+__success
+int res_spin_lock_ooo_irq(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	unsigned long f1, f2;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&res_lock, &f1))
+		return 0;
+	if (bpf_res_spin_lock_irqsave(&elem->lock, &f2)) {
+		bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+		/* We won't have a unreleased IRQ flag error here. */
+		return 0;
+	}
+	bpf_res_spin_unlock_irqrestore(&elem->lock, &f2);
+	bpf_res_spin_unlock_irqrestore(&res_lock, &f1);
+	return 0;
+}
+
+struct bpf_res_spin_lock lock1 __hidden SEC(".data.OO1");
+struct bpf_res_spin_lock lock2 __hidden SEC(".data.OO2");
+
+SEC("?tc")
+__failure __msg("bpf_res_spin_unlock cannot be out of order")
+int res_spin_lock_ooo_unlock(struct __sk_buff *ctx)
+{
+	if (bpf_res_spin_lock(&lock1))
+		return 0;
+	if (bpf_res_spin_lock(&lock2)) {
+		bpf_res_spin_unlock(&lock1);
+		return 0;
+	}
+	bpf_res_spin_unlock(&lock1);
+	bpf_res_spin_unlock(&lock2);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("off 1 doesn't point to 'struct bpf_res_spin_lock' that is at 0")
+int res_spin_lock_bad_off(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem)
+		return 0;
+	bpf_res_spin_lock((void *)&elem->lock + 1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("R1 doesn't have constant offset. bpf_res_spin_lock has to be at the constant offset")
+int res_spin_lock_var_off(struct __sk_buff *ctx)
+{
+	struct arr_elem *elem;
+	u64 val = value;
+
+	elem = bpf_map_lookup_elem(&arrmap, &(int){0});
+	if (!elem) {
+		// FIXME: Only inline assembly use in assert macro doesn't emit
+		//	  BTF definition.
+		bpf_throw(0);
+		return 0;
+	}
+	bpf_assert_range(val, 0, 40);
+	bpf_res_spin_lock((void *)&value + val);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("map 'res_spin.bss' has no valid bpf_res_spin_lock")
+int res_spin_lock_no_lock_map(struct __sk_buff *ctx)
+{
+	bpf_res_spin_lock((void *)&value + 1);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("local 'kptr' has no valid bpf_res_spin_lock")
+int res_spin_lock_no_lock_kptr(struct __sk_buff *ctx)
+{
+	struct { int i; } *p = bpf_obj_new(typeof(*p));
+
+	if (!p)
+		return 0;
+	bpf_res_spin_lock((void *)p);
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.47.1



From danct12 at riseup.net  Sat Mar 15 22:03:43 2025
From: danct12 at riseup.net (Dang Huynh)
Date: Sun, 16 Mar 2025 05:03:43 +0000
Subject: [PATCH 0/3] Rockchip IOMMU fixes
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <7951915.lOV4Wx5bFT@melttower>

On Thursday, March 13, 2025 5:31:03?PM UTC Robin Murphy wrote:
> Hi all,
> 
> I was expecting my DT probing change to flush out issues, and it seems
> some weaknesses in rockchip-iommu were the first to show. The first two
> patches here get things working again for me on my RK3399 NanoPC-T4
> (with a console on HDMI exercising the VOP MMU), the 3rd patch just
> finishes the cleanup since I was there and could test it.
> 
> Thanks,
> Robin.
> 
> Robin Murphy (3):
>   iommu/rockchip: Allocate per-device data sensibly
>   iommu/rockchip: Register in a sensible order
>   iommu/rockchip: Retire global dma_dev workaround
> 
>  drivers/iommu/rockchip-iommu.c | 61 +++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 35 deletions(-)

Tested this series on a RK3566 device and this fixed kernel panic/oops on boot 
since next-20250314.

For the whole series:

Tested-by: Dang Huynh <danct12 at riseup.net>




From gregkh at linuxfoundation.org  Sun Mar 16 01:02:06 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Sun, 16 Mar 2025 09:02:06 +0100
Subject: Patch "Fix mmu notifiers for range-based invalidates" has been added to the 6.12-stable tree
Message-ID: <2025031606-duh-scanning-bea0@gregkh>


This is a note to let you know that I've just added the patch titled

    Fix mmu notifiers for range-based invalidates

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     fix-mmu-notifiers-for-range-based-invalidates.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From f7edb07ad7c66eab3dce57384f33b9799d579133 Mon Sep 17 00:00:00 2001
From: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Date: Tue, 4 Mar 2025 00:51:27 -0800
Subject: Fix mmu notifiers for range-based invalidates

From: Piotr Jaroszynski <pjaroszynski at nvidia.com>

commit f7edb07ad7c66eab3dce57384f33b9799d579133 upstream.

Update the __flush_tlb_range_op macro not to modify its parameters as
these are unexepcted semantics. In practice, this fixes the call to
mmu_notifier_arch_invalidate_secondary_tlbs() in
__flush_tlb_range_nosync() to use the correct range instead of an empty
range with start=end. The empty range was (un)lucky as it results in
taking the invalidate-all path that doesn't cause correctness issues,
but can certainly result in suboptimal perf.

This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
invalidate_range() when invalidating TLBs") when the call to the
notifiers was added to __flush_tlb_range(). It predates the addition of
the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") that made the
bug hard to spot.

Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Alistair Popple <apopple at nvidia.com>
Cc: Raghavendra Rao Ananta <rananta at google.com>
Cc: SeongJae Park <sj at kernel.org>
Cc: Jason Gunthorpe <jgg at nvidia.com>
Cc: John Hubbard <jhubbard at nvidia.com>
Cc: Nicolin Chen <nicolinc at nvidia.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: linux-mm at kvack.org
Cc: linux-kernel at vger.kernel.org
Cc: stable at vger.kernel.org
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Reviewed-by: Alistair Popple <apopple at nvidia.com>
Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski at nvidia.com
Signed-off-by: Will Deacon <will at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/tlbflush.h |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(s
 #define __flush_tlb_range_op(op, start, pages, stride,			\
 				asid, tlb_level, tlbi_user, lpa2)	\
 do {									\
+	typeof(start) __flush_start = start;				\
+	typeof(pages) __flush_pages = pages;				\
 	int num = 0;							\
 	int scale = 3;							\
 	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 	unsigned long addr;						\
 									\
-	while (pages > 0) {						\
+	while (__flush_pages > 0) {					\
 		if (!system_supports_tlb_range() ||			\
-		    pages == 1 ||					\
-		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
-			addr = __TLBI_VADDR(start, asid);		\
+		    __flush_pages == 1 ||				\
+		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
+			addr = __TLBI_VADDR(__flush_start, asid);	\
 			__tlbi_level(op, addr, tlb_level);		\
 			if (tlbi_user)					\
 				__tlbi_user_level(op, addr, tlb_level);	\
-			start += stride;				\
-			pages -= stride >> PAGE_SHIFT;			\
+			__flush_start += stride;			\
+			__flush_pages -= stride >> PAGE_SHIFT;		\
 			continue;					\
 		}							\
 									\
-		num = __TLBI_RANGE_NUM(pages, scale);			\
+		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
+			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 						scale, num, tlb_level);	\
 			__tlbi(r##op, addr);				\
 			if (tlbi_user)					\
 				__tlbi_user(r##op, addr);		\
-			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			pages -= __TLBI_RANGE_PAGES(num, scale);	\
+			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 		}							\
 		scale--;						\
 	}								\


Patches currently in stable-queue which might be from pjaroszynski at nvidia.com are

queue-6.12/fix-mmu-notifiers-for-range-based-invalidates.patch


From gregkh at linuxfoundation.org  Sun Mar 16 01:02:17 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Sun, 16 Mar 2025 09:02:17 +0100
Subject: Patch "Fix mmu notifiers for range-based invalidates" has been added to the 6.13-stable tree
Message-ID: <2025031617-swept-encounter-c305@gregkh>


This is a note to let you know that I've just added the patch titled

    Fix mmu notifiers for range-based invalidates

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     fix-mmu-notifiers-for-range-based-invalidates.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From f7edb07ad7c66eab3dce57384f33b9799d579133 Mon Sep 17 00:00:00 2001
From: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Date: Tue, 4 Mar 2025 00:51:27 -0800
Subject: Fix mmu notifiers for range-based invalidates

From: Piotr Jaroszynski <pjaroszynski at nvidia.com>

commit f7edb07ad7c66eab3dce57384f33b9799d579133 upstream.

Update the __flush_tlb_range_op macro not to modify its parameters as
these are unexepcted semantics. In practice, this fixes the call to
mmu_notifier_arch_invalidate_secondary_tlbs() in
__flush_tlb_range_nosync() to use the correct range instead of an empty
range with start=end. The empty range was (un)lucky as it results in
taking the invalidate-all path that doesn't cause correctness issues,
but can certainly result in suboptimal perf.

This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
invalidate_range() when invalidating TLBs") when the call to the
notifiers was added to __flush_tlb_range(). It predates the addition of
the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") that made the
bug hard to spot.

Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Alistair Popple <apopple at nvidia.com>
Cc: Raghavendra Rao Ananta <rananta at google.com>
Cc: SeongJae Park <sj at kernel.org>
Cc: Jason Gunthorpe <jgg at nvidia.com>
Cc: John Hubbard <jhubbard at nvidia.com>
Cc: Nicolin Chen <nicolinc at nvidia.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: linux-mm at kvack.org
Cc: linux-kernel at vger.kernel.org
Cc: stable at vger.kernel.org
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Reviewed-by: Alistair Popple <apopple at nvidia.com>
Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski at nvidia.com
Signed-off-by: Will Deacon <will at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/tlbflush.h |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(s
 #define __flush_tlb_range_op(op, start, pages, stride,			\
 				asid, tlb_level, tlbi_user, lpa2)	\
 do {									\
+	typeof(start) __flush_start = start;				\
+	typeof(pages) __flush_pages = pages;				\
 	int num = 0;							\
 	int scale = 3;							\
 	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 	unsigned long addr;						\
 									\
-	while (pages > 0) {						\
+	while (__flush_pages > 0) {					\
 		if (!system_supports_tlb_range() ||			\
-		    pages == 1 ||					\
-		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
-			addr = __TLBI_VADDR(start, asid);		\
+		    __flush_pages == 1 ||				\
+		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
+			addr = __TLBI_VADDR(__flush_start, asid);	\
 			__tlbi_level(op, addr, tlb_level);		\
 			if (tlbi_user)					\
 				__tlbi_user_level(op, addr, tlb_level);	\
-			start += stride;				\
-			pages -= stride >> PAGE_SHIFT;			\
+			__flush_start += stride;			\
+			__flush_pages -= stride >> PAGE_SHIFT;		\
 			continue;					\
 		}							\
 									\
-		num = __TLBI_RANGE_NUM(pages, scale);			\
+		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
+			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 						scale, num, tlb_level);	\
 			__tlbi(r##op, addr);				\
 			if (tlbi_user)					\
 				__tlbi_user(r##op, addr);		\
-			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			pages -= __TLBI_RANGE_PAGES(num, scale);	\
+			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 		}							\
 		scale--;						\
 	}								\


Patches currently in stable-queue which might be from pjaroszynski at nvidia.com are

queue-6.13/fix-mmu-notifiers-for-range-based-invalidates.patch


From jic23 at kernel.org  Sun Mar 16 02:38:12 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 16 Mar 2025 09:38:12 +0000
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
	<c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
Message-ID: <20250316093752.0eacaa16@jic23-huawei>

On Thu, 13 Mar 2025 09:18:18 +0200
Matti Vaittinen <mazziesaccount at gmail.com> wrote:

> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
> 
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
> 
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.
I suspect we'll need the addition of an optional trailing timestamp
channel at somepoint. But we can add that when we need it as only
matters for drivers doing iio_push_to_buffers_with_timestamp()

Otherwise no additional comments from me.


From jic23 at kernel.org  Sun Mar 16 02:41:12 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 16 Mar 2025 09:41:12 +0000
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <Z9LQ0O34EUM8WZku@smile.fi.intel.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
	<df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
	<Z9LQ0O34EUM8WZku@smile.fi.intel.com>
Message-ID: <20250316094112.6731bd01@jic23-huawei>

On Thu, 13 Mar 2025 14:34:24 +0200
Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:

> On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
> > The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
> > help drivers avoid open-coding the for_each_node -loop for getting the
> > channel IDs. The helper provides standard way to detect the ADC channel
> > nodes (by the node name), and a standard way to convert the "reg"
> > -properties to channel identification numbers, used in the struct
> > iio_chan_spec. Furthermore, the helper can optionally check the found
> > channel IDs are smaller than given maximum. This is useful for callers
> > which later use the IDs for example for indexing a channel data array.
> > 
> > The original driver treated all found child nodes as channel nodes. The
> > new helper requires channel nodes to be named channel[@N]. This should
> > help avoid problems with devices which may contain also other but ADC
> > child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
> > string didn't reveal any in-tree .dts with channel nodes named
> > otherwise. Also, same grep shows all the in-tree .dts seem to have
> > channel IDs between 0..num of channels.
> > 
> > Use the new helper.  
> 
> ...
> 
> > +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
> > +				&sun20i_gpadc_chan_template, -1, &channels);
> > +	if (num_channels < 0)
> > +		return num_channels;
> > +
> >  	if (num_channels == 0)
> >  		return dev_err_probe(dev, -ENODEV, "no channel children\n");  
> 
> Note, this what I would expected in your helper to see, i.e. separated cases
> for < 0 (error code) and == 0, no channels.
> 
> Also, are all users going to have this check? Usually in other similar APIs
> we return -ENOENT. And user won't need to have an additional check in case of
> 0 being considered as an error case too.
In a few cases we'll need to do the dance the other way in the caller.
So specifically check for -ENOENT and not treat it as an error.

That stems from channel nodes being optionally added to drivers after
they have been around a while (usually to add more specific configuration)
and needing to maintain old behaviour of presenting all channels with default
settings.

I agree that returning -ENOENT is a reasonable way to handle this.

Jonathan

> 
> 
> 
> 



From wahrenst at gmx.net  Sun Mar 16 02:52:58 2025
From: wahrenst at gmx.net (Stefan Wahren)
Date: Sun, 16 Mar 2025 10:52:58 +0100
Subject: [PATCH v2 5/5] arm: dts: bcm2711-rpi: Add HEVC decoder node
In-Reply-To: <20250206-media-rpi-hevc-dec-v2-5-69353c8805b2@raspberrypi.com>
References: <20250206-media-rpi-hevc-dec-v2-0-69353c8805b2@raspberrypi.com>
 <20250206-media-rpi-hevc-dec-v2-5-69353c8805b2@raspberrypi.com>
Message-ID: <9a23c31d-e26f-4bc1-9759-5b6b4340a588@gmx.net>

Hi Dave,

Am 06.02.25 um 19:02 schrieb Dave Stevenson:
> Add the configuration information for the HEVC decoder.
>
> Signed-off-by: Dave Stevenson <dave.stevenson at raspberrypi.com>
> ---
>   arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi | 4 ++++
>   arch/arm/boot/dts/broadcom/bcm2711.dtsi     | 9 +++++++++
>   2 files changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi
> index 6bf4241fe3b7..56c633005941 100644
> --- a/arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi
> +++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi
> @@ -105,3 +105,7 @@ &vchiq {
>   &xhci {
>   	power-domains = <&power RPI_POWER_DOMAIN_USB>;
>   };
> +
> +&hevc_dec {
> +	clocks = <&firmware_clocks 11>;
> +};
the node ref should be in alphabetical order, so please add after hdmi1.
> diff --git a/arch/arm/boot/dts/broadcom/bcm2711.dtsi b/arch/arm/boot/dts/broadcom/bcm2711.dtsi
> index e4e42af21ef3..2931d93ba184 100644
> --- a/arch/arm/boot/dts/broadcom/bcm2711.dtsi
> +++ b/arch/arm/boot/dts/broadcom/bcm2711.dtsi
> @@ -628,6 +628,15 @@ v3d: gpu at 7ec00000 {
>   			resets = <&pm BCM2835_RESET_V3D>;
>   			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
>   		};
> +
> +		hevc_dec: codec at 7eb10000 {
Please put the node before V3D to keep the register order.
> +			compatible = "raspberrypi,hevc-dec";
> +			reg = <0x0 0x7eb00000  0x10000>, /* HEVC */
> +			      <0x0 0x7eb10000  0x1000>;  /* INTC */
Since the reg-names are provided, there is no need for these comments.
> +			reg-names = "hevc",
> +				    "intc";
> +			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
> +		};
>   	};
>   };
>
>



From pchelkin at ispras.ru  Sun Mar 16 03:26:53 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun, 16 Mar 2025 13:26:53 +0300
Subject: [PATCH v2 0/3] usb: chipidea: ci_hdrc_imx: fix some issues in probe/remove
Message-ID: <20250316102658.490340-1-pchelkin@ispras.ru>

The first patch fixes a rather recently introduced bug leading to the
driver oopsing on removal in case of non-usbmisc devices.

The other ones perform error path fixes in the probe function.

Link to v1
https://lore.kernel.org/linux-usb/20250309175805.661684-1-pchelkin at ispras.ru/t/#u

Fedor Pchelkin (3):
  usb: chipidea: ci_hdrc_imx: fix usbmisc handling
  usb: chipidea: ci_hdrc_imx: fix call balance of regulator routines
  usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling

 drivers/usb/chipidea/ci_hdrc_imx.c | 44 +++++++++++++++++++++---------
 1 file changed, 31 insertions(+), 13 deletions(-)

-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar 16 03:26:55 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun, 16 Mar 2025 13:26:55 +0300
Subject: [PATCH v2 2/3] usb: chipidea: ci_hdrc_imx: fix call balance of regulator routines
In-Reply-To: <20250316102658.490340-1-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
Message-ID: <20250316102658.490340-3-pchelkin@ispras.ru>

Upon encountering errors during the HSIC pinctrl handling section the
regulator should be disabled.

Use devm_add_action_or_reset() to let the regulator-disabling routine be
handled by device resource management stack.

Found by Linux Verification Center (linuxtesting.org).

Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
v2: simplify the patch taking advantage of devm-helper (Frank Li)

It looks like devm_regulator_get_enable_optional() exists for this very
use case utilized in the driver but it's not present in old supported
stable kernels and I may say those dependency-patches wouldn't apply there
cleanly. So fix the problem first, further code simplification is a
subject to cleanup patch.

 drivers/usb/chipidea/ci_hdrc_imx.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 619779eef333..d942b3c72640 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -336,6 +336,13 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
 	return ret;
 }
 
+static void ci_hdrc_imx_disable_regulator(void *arg)
+{
+	struct ci_hdrc_imx_data *data = arg;
+
+	regulator_disable(data->hsic_pad_regulator);
+}
+
 static int ci_hdrc_imx_probe(struct platform_device *pdev)
 {
 	struct ci_hdrc_imx_data *data;
@@ -394,6 +401,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 					"Failed to enable HSIC pad regulator\n");
 				goto err_put;
 			}
+			ret = devm_add_action_or_reset(dev,
+					ci_hdrc_imx_disable_regulator, data);
+			if (ret) {
+				dev_err(dev,
+					"Failed to add regulator devm action\n");
+				goto err_put;
+			}
 		}
 	}
 
@@ -432,11 +446,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
 	ret = imx_get_clks(dev);
 	if (ret)
-		goto disable_hsic_regulator;
+		goto qos_remove_request;
 
 	ret = imx_prepare_enable_clks(dev);
 	if (ret)
-		goto disable_hsic_regulator;
+		goto qos_remove_request;
 
 	ret = clk_prepare_enable(data->clk_wakeup);
 	if (ret)
@@ -526,10 +540,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	clk_disable_unprepare(data->clk_wakeup);
 err_wakeup_clk:
 	imx_disable_unprepare_clks(dev);
-disable_hsic_regulator:
-	if (data->hsic_pad_regulator)
-		/* don't overwrite original ret (cf. EPROBE_DEFER) */
-		regulator_disable(data->hsic_pad_regulator);
+qos_remove_request:
 	if (pdata.flags & CI_HDRC_PMQOS)
 		cpu_latency_qos_remove_request(&data->pm_qos_req);
 	data->ci_pdev = NULL;
@@ -557,8 +568,6 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
 		clk_disable_unprepare(data->clk_wakeup);
 		if (data->plat_data->flags & CI_HDRC_PMQOS)
 			cpu_latency_qos_remove_request(&data->pm_qos_req);
-		if (data->hsic_pad_regulator)
-			regulator_disable(data->hsic_pad_regulator);
 	}
 	if (data->usbmisc_data)
 		put_device(data->usbmisc_data->dev);
-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar 16 03:26:56 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun, 16 Mar 2025 13:26:56 +0300
Subject: [PATCH v2 3/3] usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling
In-Reply-To: <20250316102658.490340-1-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
Message-ID: <20250316102658.490340-4-pchelkin@ispras.ru>

usb_phy_init() may return an error code if e.g. its implementation fails
to prepare/enable some clocks. And properly rollback on probe error path
by calling the counterpart usb_phy_shutdown().

Found by Linux Verification Center (linuxtesting.org).

Fixes: be9cae2479f4 ("usb: chipidea: imx: Fix ULPI on imx53")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index d942b3c72640..4f8bfd242b59 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -484,7 +484,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	    of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
 		pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
 		data->override_phy_control = true;
-		usb_phy_init(pdata.usb_phy);
+		ret = usb_phy_init(pdata.usb_phy);
+		if (ret) {
+			dev_err(dev, "Failed to init phy\n");
+			goto err_clk;
+		}
 	}
 
 	if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
@@ -493,7 +497,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	ret = imx_usbmisc_init(data->usbmisc_data);
 	if (ret) {
 		dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
-		goto err_clk;
+		goto phy_shutdown;
 	}
 
 	data->ci_pdev = ci_hdrc_add_device(dev,
@@ -502,7 +506,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(data->ci_pdev)) {
 		ret = PTR_ERR(data->ci_pdev);
 		dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
-		goto err_clk;
+		goto phy_shutdown;
 	}
 
 	if (data->usbmisc_data) {
@@ -536,6 +540,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
 disable_device:
 	ci_hdrc_remove_device(data->ci_pdev);
+phy_shutdown:
+	if (data->override_phy_control)
+		usb_phy_shutdown(data->phy);
 err_clk:
 	clk_disable_unprepare(data->clk_wakeup);
 err_wakeup_clk:
-- 
2.48.1



From pchelkin at ispras.ru  Sun Mar 16 03:26:54 2025
From: pchelkin at ispras.ru (Fedor Pchelkin)
Date: Sun, 16 Mar 2025 13:26:54 +0300
Subject: [PATCH v2 1/3] usb: chipidea: ci_hdrc_imx: fix usbmisc handling
In-Reply-To: <20250316102658.490340-1-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
Message-ID: <20250316102658.490340-2-pchelkin@ispras.ru>

usbmisc is an optional device property so it is totally valid for the
corresponding data->usbmisc_data to have a NULL value.

Check that before dereferencing the pointer.

Found by Linux Verification Center (linuxtesting.org) with Svace static
analysis tool.

Fixes: 74adad500346 ("usb: chipidea: ci_hdrc_imx: decrement device's refcount in .remove() and in the error path of .probe()")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 1a7fc638213e..619779eef333 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -534,7 +534,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 		cpu_latency_qos_remove_request(&data->pm_qos_req);
 	data->ci_pdev = NULL;
 err_put:
-	put_device(data->usbmisc_data->dev);
+	if (data->usbmisc_data)
+		put_device(data->usbmisc_data->dev);
 	return ret;
 }
 
@@ -559,7 +560,8 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
 		if (data->hsic_pad_regulator)
 			regulator_disable(data->hsic_pad_regulator);
 	}
-	put_device(data->usbmisc_data->dev);
+	if (data->usbmisc_data)
+		put_device(data->usbmisc_data->dev);
 }
 
 static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
-- 
2.48.1



From maz at kernel.org  Sun Mar 16 03:33:10 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 16 Mar 2025 10:33:10 +0000
Subject: [PATCH v5 0/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <86a59lnu3d.wl-maz@kernel.org>

On Sat, 15 Mar 2025 09:12:09 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> Prepare vPMC registers for user-initiated changes after first run. This
> is important specifically for debugging Windows on QEMU with GDB; QEMU
> tries to write back all visible registers when resuming the VM execution
> with GDB, corrupting the PMU state. Windows always uses the PMU so this
> can cause adverse effects on that particular OS.
> 
> This series also contains patch "KVM: arm64: PMU: Set raw values from
> user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
> changes made for the mentioned registers in the past. It is necessary
> to migrate the PMU state properly on Firecracker, QEMU, and crosvm.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
> ---
> Changes in v5:
> - Rebased.
> - Link to v4: https://lore.kernel.org/r/20250313-pmc-v4-0-2c976827118c at daynix.com
> 
> Changes in v4:
> - Reverted changes for functions implementing ioctls in patch
>   "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
> - Removed kvm_pmu_vcpu_reset().
> - Reordered function calls in kvm_vcpu_reload_pmu() for better style.
> - Link to v3: https://lore.kernel.org/r/20250312-pmc-v3-0-0411cab5dc3d at daynix.com
> 
> Changes in v3:
> - Added patch "KVM: arm64: PMU: Assume PMU presence in pmu-emul.c".
> - Added an explanation of this path series' motivation to each patch.
> - Explained why userspace register writes and register reset should be
>   covered in patch "KVM: arm64: PMU: Reload when user modifies
>   registers".
> - Marked patch "KVM: arm64: PMU: Set raw values from user to
>   PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" for stable.
> - Reoreded so that patch "KVM: arm64: PMU: Set raw values from user to
>   PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}" would come first.
> - Added patch "KVM: arm64: PMU: Call kvm_pmu_handle_pmcr() after masking
>   PMCNTENSET_EL0".
> - Added patch "KVM: arm64: Reload PMCNTENSET_EL0".
> - Link to v2: https://lore.kernel.org/r/20250307-pmc-v2-0-6c3375a5f1e4 at daynix.com
> 
> Changes in v2:
> - Changed to utilize KVM_REQ_RELOAD_PMU as suggested by Oliver Upton.
> - Added patch "KVM: arm64: PMU: Reload when user modifies registers"
>   to cover more registers.
> - Added patch "KVM: arm64: PMU: Set raw values from user to
>   PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}".
> - Link to v1: https://lore.kernel.org/r/20250302-pmc-v1-1-caff989093dc at daynix.com
> 
> ---
> Akihiko Odaki (5):
>       KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
>       KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
>       KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
>       KVM: arm64: PMU: Reload when user modifies registers
>       KVM: arm64: PMU: Reload when resetting
> 
>  arch/arm64/kvm/arm.c            | 17 ++++++++-----
>  arch/arm64/kvm/emulate-nested.c |  6 +++--
>  arch/arm64/kvm/pmu-emul.c       | 56 +++++++++++------------------------------
>  arch/arm64/kvm/reset.c          |  3 ---
>  arch/arm64/kvm/sys_regs.c       | 52 ++++++++++++++++++++++----------------
>  include/kvm/arm_pmu.h           |  4 +--
>  6 files changed, 62 insertions(+), 76 deletions(-)

Reviewed-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Sun Mar 16 03:38:21 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 16 Mar 2025 10:38:21 +0000
Subject: [PATCH] KVM: arm64: Tear down vGIC on failed vCPU creation
In-Reply-To: <20250314133409.9123-1-will@kernel.org>
References: <20250314133409.9123-1-will@kernel.org>
Message-ID: <868qp5ntuq.wl-maz@kernel.org>

On Fri, 14 Mar 2025 13:34:09 +0000,
Will Deacon <will at kernel.org> wrote:
> 
> If kvm_arch_vcpu_create() fails to share the vCPU page with the
> hypervisor, we propagate the error back to the ioctl but leave the
> vGIC vCPU data initialised. Note only does this leak the corresponding
> memory when the vCPU is destroyed but it can also lead to use-after-free
> if the redistributor device handling tries to walk into the vCPU.
> 
> Add the missing cleanup to kvm_arch_vcpu_create(), ensuring that the
> vGIC vCPU structures are destroyed on error.
> 
> Cc: <stable at vger.kernel.org>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Cc: Quentin Perret <qperret at google.com>
> Signed-off-by: Will Deacon <will at kernel.org>
> ---
> 
> It's hard to come up with a "Fixes:" tag for this. Prior to 3f868e142c0b
> ("KVM: arm64: Introduce kvm_share_hyp()"), create_hyp_mappings() could
> still have failed, although if you go back before 66c57edd3bc7 ("KVM:
> arm64: Restrict EL2 stage-1 changes in protected mode") then it's
> vanishingly unlikely.
> 
>  arch/arm64/kvm/arm.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index b8e55a441282..fa71cee02faa 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -466,7 +466,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
>  	if (err)
>  		return err;
>  
> -	return kvm_share_hyp(vcpu, vcpu + 1);
> +	err = kvm_share_hyp(vcpu, vcpu + 1);
> +	if (err)
> +		kvm_vgic_vcpu_destroy(vcpu);
> +
> +	return err;
>  }
>  
>  void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)

Reviewed-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Sun Mar 16 04:03:05 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 16 Mar 2025 11:03:05 +0000
Subject: [PATCH 2/6] KVM: arm64: Use 0b11 for encoding PKVM_NOPAGE
In-Reply-To: <Z9Q5k5C50Meeog9q@google.com>
References: <20250227003310.367350-1-qperret@google.com>
	<20250227003310.367350-3-qperret@google.com>
	<86cyejooq2.wl-maz@kernel.org>
	<Z9Q5k5C50Meeog9q@google.com>
Message-ID: <867c4pnspi.wl-maz@kernel.org>

On Fri, 14 Mar 2025 14:13:39 +0000,
Quentin Perret <qperret at google.com> wrote:
> 
> On Friday 14 Mar 2025 at 11:07:01 (+0000), Marc Zyngier wrote:
> > On Thu, 27 Feb 2025 00:33:06 +0000,
> > Quentin Perret <qperret at google.com> wrote:
> > > 
> > > The page ownership state encoded as 0b11 is currently considered
> > > reserved for future use, and PKVM_NOPAGE uses bit 2. In order to
> > > simplify the relocation of the hyp ownership state into the
> > > vmemmap in later patches, let's use the 'reserved' encoding for
> > > the PKVM_NOPAGE state. The struct hyp_page layout isn't guaranteed
> > > stable at all, so there is no real reason to have 'reserved' encodings.
> > > 
> > > No functional changes intended.
> > > 
> > > Signed-off-by: Quentin Perret <qperret at google.com>
> > > ---
> > >  arch/arm64/kvm/hyp/include/nvhe/memory.h | 5 +----
> > >  1 file changed, 1 insertion(+), 4 deletions(-)
> > > 
> > > diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > > index 34233d586060..642b5e05fe77 100644
> > > --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > > +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h
> > > @@ -13,18 +13,15 @@
> > >   *   01: The page is owned by the page-table owner, but is shared
> > >   *       with another entity.
> > >   *   10: The page is shared with, but not owned by the page-table owner.
> > > - *   11: Reserved for future use (lending).
> > >   */
> > >  enum pkvm_page_state {
> > >  	PKVM_PAGE_OWNED			= 0ULL,
> > >  	PKVM_PAGE_SHARED_OWNED		= BIT(0),
> > >  	PKVM_PAGE_SHARED_BORROWED	= BIT(1),
> > > -	__PKVM_PAGE_RESERVED		= BIT(0) | BIT(1),
> > >  
> > >  	/* Meta-states which aren't encoded directly in the PTE's SW bits */
> > > -	PKVM_NOPAGE			= BIT(2),
> > > +	PKVM_NOPAGE			= BIT(0) | BIT(1),
> > 
> > Isn't this comment stale now?
> 
> I believe it still applies to guest stage-2 page-tables as the three
> other states above are still stored into PTE SW bits (well, sort of,
> only SHARED_BORROWED is at the moment as we don't supported protected
> VMs, but OWNED and SHARED_OWNED will be a thing for protected). NOPAGE
> is still the only one that is a bit different and doesn't go there.
>
> With that said, the comment could be made more explicit about that and
> explain this is now guest s2 only. Happy to spin another version of the
> series with that changed if that helps.

Right. It is slightly misleading that we end-up with two notions of
state:

- the per-mapping state encoded in the PTs
- the per-page state encoded in the vmemmap

The two are obviously related, but it is all a bit confusing for the
unsuspecting reader. There is no urgency to address this, but maybe
it'd be good to clarify this aspect in the future (no need to respin
on that account).

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Sun Mar 16 04:08:06 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 16 Mar 2025 11:08:06 +0000
Subject: [PATCH 4/6] KVM: arm64: Move hyp state to hyp_vmemmap
In-Reply-To: <Z9Q3-FM-QwiIn9gh@google.com>
References: <20250227003310.367350-1-qperret@google.com>
	<20250227003310.367350-5-qperret@google.com>
	<86bju3onl3.wl-maz@kernel.org>
	<Z9Q3-FM-QwiIn9gh@google.com>
Message-ID: <865xk9nsh5.wl-maz@kernel.org>

On Fri, 14 Mar 2025 14:06:48 +0000,
Quentin Perret <qperret at google.com> wrote:
> 
> On Friday 14 Mar 2025 at 11:31:36 (+0000), Marc Zyngier wrote:
> > On Thu, 27 Feb 2025 00:33:08 +0000,
> > Quentin Perret <qperret at google.com> wrote:
> > > @@ -698,13 +697,13 @@ int __pkvm_host_share_hyp(u64 pfn)
> > >  	if (ret)
> > >  		goto unlock;
> > >  	if (IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) {
> > > -		ret = __hyp_check_page_state_range((u64)virt, size, PKVM_NOPAGE);
> > > +		ret = __hyp_check_page_state_range(phys, size, PKVM_NOPAGE);
> > 
> > OK, I think I finally clicked here. Does it mean that all the tracking
> > is now done in terms of PAs instead of VAs?
> 
> Yep, that's exactly that. The hyp_vmemmap is indexed by pfn, so I felt
> that the conversion to a PA-based tracking made sense. That also make it
> clear that the 'hyp state' is not a property of a mapping, but really of
> the underlying physical page.

It indeed makes sense. It is just that it took me some time to realise
the extent of the change.

> 
> > >  		if (ret)
> > >  			goto unlock;
> > >  	}
> > >  
> > > -	prot = pkvm_mkstate(PAGE_HYP, PKVM_PAGE_SHARED_BORROWED);
> > > -	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, prot));
> > > +	__hyp_set_page_state_range(phys, size, PKVM_PAGE_SHARED_BORROWED);
> > > +	WARN_ON(pkvm_create_mappings_locked(virt, virt + size, PAGE_HYP));
> > 
> > And this is the split between the state now being kept in the on a PA
> > base and the actual mapping that is now only takes the page attributes
> > and no SW bits?
> 
> Precisely, and the next patch in this series takes advantage of the
> fact that we're now de-correlating the hyp state from the presence of a
> hyp s1 mapping in the linear map range. In the future there'll be more
> use-cases for this I think (e.g. the hyp allocator where we'll have
> pages owned by the hypervisor but only mapped in the 'private' range,
> things like that).

Yup, that's probably the correct direction of travel. The hypervisor
shouldn't need to map everything -- quite the opposite actually.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Sun Mar 16 04:12:17 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sun, 16 Mar 2025 11:12:17 +0000
Subject: [PATCH 0/6] Move pKVM ownership state to hyp_vmemmap
In-Reply-To: <20250227003310.367350-1-qperret@google.com>
References: <20250227003310.367350-1-qperret@google.com>
Message-ID: <864iztnsa6.wl-maz@kernel.org>

On Thu, 27 Feb 2025 00:33:04 +0000,
Quentin Perret <qperret at google.com> wrote:
> 
> Hi all,
> 
> This series moves the hypervisor's ownership state to the hyp_vmemmap,
> as discussed in [1]. The two main benefits are:
> 
>  1. much cheaper hyp state lookups, since we can avoid the hyp stage-1
>     page-table walk;
> 
>  2. de-correlates the hyp state from the presence of a mapping in the
>     linear map range of the hypervisor; which enables a bunch of
>     clean-ups in the existing code and will simplify the introduction of
>     other features in the future (hyp tracing, ...)
> 
> Patch 01 is a self-sufficient cleanup that I found thanks to patch 05.
> Patches 02-04 implement the aforementioned migration of the hyp state
> to the vmemmap. Patches 05 and 06 are cleanups enabled by that
> migration.
> 
> Patches based on 6.14-rc4, tested on Qemu.
> 
> Thanks!
> Quentin
> 
> [1] https://lore.kernel.org/kvmarm/Z79ZJVOHtNu6YsVt at google.com/
> 
> Fuad Tabba (1):
>   KVM: arm64: Track SVE state in the hypervisor vcpu structure
> 
> Quentin Perret (5):
>   KVM: arm64: Use 0b11 for encoding PKVM_NOPAGE
>   KVM: arm64: Introduce {get,set}_host_state() helpers
>   KVM: arm64: Move hyp state to hyp_vmemmap
>   KVM: arm64: Defer EL2 stage-1 mapping on share
>   KVM: arm64: Unconditionally cross check hyp state
> 
>  arch/arm64/include/asm/kvm_host.h        |  12 +--
>  arch/arm64/kvm/hyp/include/nvhe/memory.h |  35 ++++++--
>  arch/arm64/kvm/hyp/nvhe/hyp-main.c       |   4 -
>  arch/arm64/kvm/hyp/nvhe/mem_protect.c    | 106 ++++++++++++-----------
>  arch/arm64/kvm/hyp/nvhe/pkvm.c           |  54 ++++++++++--
>  arch/arm64/kvm/hyp/nvhe/setup.c          |  10 ++-
>  6 files changed, 147 insertions(+), 74 deletions(-)
> 

Reviewed-by: Marc Zyngier <maz at kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.


From krzysztof.kozlowski at linaro.org  Sun Mar 16 07:31:07 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 15:31:07 +0100
Subject: [GIT PULL] pinctrl: samsung: drivers for v6.15
Message-ID: <20250316143108.17045-1-krzysztof.kozlowski@linaro.org>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git tags/samsung-pinctrl-6.15

for you to fetch changes up to 701d0e910955627734917c3587258aa7e73068bb:

  pinctrl: samsung: add support for eint_fltcon_offset (2025-03-11 20:37:29 +0100)

----------------------------------------------------------------
Samsung pinctrl drivers changes for v6.15

1. Add pin controller drivers for newly usptreamed Samsung Exynos2200
   and Exynos7870.
2. Correct filter configuration offset of some of Google GS101 SoC pin
   banks, which later is supposed to be used during system
   suspend/resume.

----------------------------------------------------------------
Ivaylo Ivanov (3):
      dt-bindings: pinctrl: samsung: add exynos2200-wakeup-eint compatible
      dt-bindings: pinctrl: samsung: add exynos2200 compatible
      pinctrl: samsung: add exynos2200 SoC pinctrl configuration

Kaustabh Chakraborty (3):
      dt-bindings: pinctrl: samsung: add exynos7870-pinctrl compatible
      dt-bindings: pinctrl: samsung: add exynos7870-wakeup-eint compatible
      pinctrl: samsung: add support for exynos7870 pinctrl

Peter Griffin (1):
      pinctrl: samsung: add support for eint_fltcon_offset

 .../pinctrl/samsung,pinctrl-wakeup-interrupt.yaml  |   3 +
 .../bindings/pinctrl/samsung,pinctrl.yaml          |   2 +
 drivers/pinctrl/samsung/pinctrl-exynos-arm64.c     | 405 ++++++++++++++++++---
 drivers/pinctrl/samsung/pinctrl-exynos.h           |  41 +++
 drivers/pinctrl/samsung/pinctrl-samsung.c          |   5 +
 drivers/pinctrl/samsung/pinctrl-samsung.h          |   6 +
 6 files changed, 413 insertions(+), 49 deletions(-)


From vz at mleia.com  Sun Mar 16 07:39:45 2025
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Sun, 16 Mar 2025 16:39:45 +0200
Subject: [PATCH] nvmem: lpc18xx_eeprom: Convert to platform remove
 callback returning void
In-Reply-To: <a7ae0d780ac580ebfed59d197ae1e6486c74ed54.1709886922.git.u.kleine-koenig@pengutronix.de>
References: <a7ae0d780ac580ebfed59d197ae1e6486c74ed54.1709886922.git.u.kleine-koenig@pengutronix.de>
Message-ID: <0f6e358a-c723-400c-a619-b2672a893b60@mleia.com>

On 3/8/24 10:51, Uwe Kleine-K?nig wrote:
> The .remove() callback for a platform driver returns an int which makes
> many driver authors wrongly assume it's possible to do error handling by
> returning an error code. However the value returned is ignored (apart
> from emitting a warning) and this typically results in resource leaks.
> 
> To improve here there is a quest to make the remove callback return
> void. In the first step of this quest all drivers are converted to
> .remove_new(), which already returns void. Eventually after all drivers
> are converted, .remove_new() will be renamed to .remove().
> 
> Trivially convert this driver from always returning zero in the remove
> callback to the void returning variant.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>

Reviewed-by: Vladimir Zapolskiy <vz at mleia.com>

Thank you for the change!

--
Best wishes,
Vladimir


From krzysztof.kozlowski at linaro.org  Sun Mar 16 07:42:20 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 15:42:20 +0100
Subject: [GIT PULL] dts: cleanups for v6.15
Message-ID: <20250316144221.18240-1-krzysztof.kozlowski@linaro.org>

Hi,

One ARM and one Loongson cleanup. I gave half a year for Loongson to explain
the spidev, but no responses were posted, so I just applied the patch:
https://lore.kernel.org/all/20240717-preacher-sandal-2aeffa322b9f at spud/

Best regards,
Krzysztof


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-dt.git tags/dt-cleanup-6.15

for you to fetch changes up to 854a080f0b73ff966a813ec2dc53891831daa28d:

  loongarch: dts: remove non-existent DAC from 2k1000-ref (2025-02-12 21:48:51 +0100)

----------------------------------------------------------------
Minor improvements inDTS for v6.15

1. ARM Cirrus EP7211: Align GPIO node name to match what bindings
   expect.

2. Loongson 2K1000: Drop incorrect spidev description, by pretending to
   have there something else.  This will have impact on the users of
   DTS, because spidev will stop working, however no counter-proposals
   of fixing this or even explaining this were proposed for half a year
   after the patch was posted.  Therefore drop incorrect hardware
   description, hoping affected users will come if proper one, if needed.

----------------------------------------------------------------
Conor Dooley (1):
      loongarch: dts: remove non-existent DAC from 2k1000-ref

Krzysztof Kozlowski (1):
      ARM: dts: cirrus: ep7211: Align GPIO hog name with bindings

 arch/arm/boot/dts/cirrus/ep7211-edb7211.dts     | 2 +-
 arch/loongarch/boot/dts/loongson-2k1000-ref.dts | 5 -----
 2 files changed, 1 insertion(+), 6 deletions(-)


From alexander.sverdlin at gmail.com  Sun Mar 16 08:13:10 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 15:13:10 -0000
Subject: [PATCH v4 0/7] arm64 support for Milk-V Duo Module 01 EVB
Message-ID: <20250213182210.2098718-1-alexander.sverdlin@gmail.com>

This series adds very basic support for Milk-V Duo Module 01 EVB [1] in
arm64 mode. The SoC (SG2000) is dual-arch, RiscV and ARM64, the latter has
been chosen because the upstream toolchain can be utilized.

Sophgo SG2000 seems to be a continuation of the Cvitek CV18xx series, same
peripherals with an addition of ARM64 core. Therefore it would be
beneficial not to copy-paste the peripherals' device-tree, but rather split
the most suitable riscv DT into ARCH-specific and peripherals parts and
just include the latter on the arm64 side.

This series adds the device-tree for Milk-V Duo Module 01 EVB, which
in turn contains Milk-V Duo Module 01 (separate .dtsi) on it, which has
SG2000 SoC inside (separate .dtsi).

This series has been tested with Sophgo-provided U-Boot binary [2]: it
boots from SD card; pinctrl, serial, GPIO drivers are functional (same
as for RiscV-based CV18xx SoCs).

Partial SoC documentation is available [3].

This series lacks the support of:
- USB
- Audio
- Ethernet
- WiFi
- Bluetooth
- eMMC
- Video
- "reboot" functionality

It would probably make sense that the series will go into ARM SOC tree.

Changelog:
v4:
- minimized patch 1/7 (cleanups dropped)
- cv18xx-cpu-intc.dtsi instead of cv18xx-cpu.dtsi+cv18xx-intc.dtsi in
patch 1/7
v3:
- &cpus node has been moved into cv18xx-cpu.dtsi, &plic and &clint nodes
were moved into cv18xx-intc.dtsi to reduce code duplication;
v2:
- dropped all patches related to the new reboot driver and corresponding DT
and bindings;
- grouped DT-related and config-related patches together;
- added patch moving sophgo.yaml from riscv into soc (to share it with
ARM); added SG2000 SoC and Milk-V Duo Module 01 EVB into it;
- other changes are documented in the corresponding patches;

[1] https://milkv.io/docs/duo/getting-started/duo-module-01
[2] https://github.com/milkv-duo/duo-buildroot-sdk-v2/releases/
[3] https://github.com/sophgo/sophgo-doc/releases/download/sg2000-trm-v1.01/sg2000_trm_en.pdf

Alexander Sverdlin (7):
  riscv: dts: sophgo: cv18xx: Move RiscV-specific part into SoCs' .dtsi
    files
  dt-bindings: soc: sophgo: Move SoCs/boards from riscv into soc, add
    SG2000
  arm64: dts: sophgo: Add initial SG2000 SoC device tree
  arm64: dts: sophgo: Add Duo Module 01
  arm64: dts: sophgo: Add Duo Module 01 Evaluation Board
  arm64: Add SOPHGO SOC family Kconfig support
  arm64: defconfig: Enable rudimentary Sophgo SG2000 support

 .../{riscv => soc/sophgo}/sophgo.yaml         |  7 +-
 arch/arm64/Kconfig.platforms                  |  6 ++
 arch/arm64/boot/dts/Makefile                  |  1 +
 arch/arm64/boot/dts/sophgo/Makefile           |  2 +
 .../sophgo/sg2000-milkv-duo-module-01-evb.dts | 31 +++++++
 .../sophgo/sg2000-milkv-duo-module-01.dtsi    | 85 +++++++++++++++++
 arch/arm64/boot/dts/sophgo/sg2000.dtsi        | 75 +++++++++++++++
 arch/arm64/configs/defconfig                  |  4 +
 arch/riscv/boot/dts/sophgo/cv1800b.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv1812h.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv181x.dtsi        |  2 +-
 .../boot/dts/sophgo/cv18xx-cpu-intc.dtsi      | 54 +++++++++++
 arch/riscv/boot/dts/sophgo/cv18xx.dtsi        | 91 +++++--------------
 arch/riscv/boot/dts/sophgo/sg2002.dtsi        |  5 +
 14 files changed, 303 insertions(+), 70 deletions(-)
 rename Documentation/devicetree/bindings/{riscv => soc/sophgo}/sophgo.yaml (80%)
 create mode 100644 arch/arm64/boot/dts/sophgo/Makefile
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000.dtsi
 create mode 100644 arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi

-- 
2.48.1



From krzk at kernel.org  Sun Mar 16 10:01:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 18:01:02 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <67d0862f.df0a0220.375bd.6b15@mx.google.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-10-ansuelsmth@gmail.com>
 <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>
 <67d0862f.df0a0220.375bd.6b15@mx.google.com>
Message-ID: <4a9ac302-dfbe-4d76-a634-a445957c313c@kernel.org>

On 11/03/2025 19:51, Christian Marangi wrote:
>>
>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>> +    enum: [0, 1]
>>
>> I don't understand why do you need index property here (which are
>> usually not allowed).
>>
> 
> Eh... As said in the description this is really to differentiate the 2
> different physical port...
> 
> Each port have a dedicated oscillator for calibration and these
> calibration are identified by an offset (all placed one after another in
> a separate register space).

So different oscillators? Then describe the oscillator and its differences.

Different programing model? Different compatible.

Other difference? Depending what is the difference.

But there is no such thing as "different port ID" based on your
description above. You just claimed that they are different, but you do
not put that difference to hardware description. Instead you encode that
difference in the drivers and it should be opposite. The DTS, so the
hardware description, should tell you the difference. And I am sorry,
but in 99% of cases "I am the first phy" and "I am the second" is not
the actual difference we are interested in.

> 
> Oscillator 0 for physical port 0
> Oscillator 1 for physcial port 1
> 
> And model this is a bit problematic without an additional property, any
> hint for this?
> 
Best regards,
Krzysztof


From krzk at kernel.org  Sun Mar 16 10:11:31 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 18:11:31 +0100
Subject: [PATCH 05/13] dt-bindings: mfd: add Documentation for Airoha
 EN7581 SCU
In-Reply-To: <67d08a4f.7b0a0220.8fe9e.44fd@mx.google.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-6-ansuelsmth@gmail.com>
 <c1227083-a4ea-4dac-a9db-d6a5386c0437@kernel.org>
 <67cec328.170a0220.27ecbc.9c6e@mx.google.com>
 <026296c8-a460-43ca-a423-0fa38269fbc2@kernel.org>
 <67d08a4f.7b0a0220.8fe9e.44fd@mx.google.com>
Message-ID: <2a5e25ad-92a6-4e25-a2b7-198b3ad84d2f@kernel.org>

On 11/03/2025 20:09, Christian Marangi wrote:
>>
>> This does not explain that binding said "This node defines the System
>> Control Unit".
>>
>> So what are you adding here if not SCU?
>>
> 
> With "This node defines the System Control Unit" I mean, the entire
> register space of the IP block is defined and each child specifically
> define each part of the IP block.

And the binding said - "this is the SCU". Now you claim that the binding
which said "this is the SCU" is not the SCU but a part of it.


> 
>>>
>>> The driver solution for this is syscon and the simple-mfd node
>>> structure.
>>
>> Let's keep driver entirely separate, we don't talk about them and mixing
>> arguments won't make it easier.
>>
> 
> Ok.
> 
>>>
>>> Now the main problem is how to modle this in DT. There are lots of case
>>> where the simple-mfd model is used (like the one proposed) but probably
>>> this is not accepted anymore. But again this should be clearly stated or
>>> we have a chicken-egg problem when other devs implement similar thing and
>>> have to implement simple MFD driver to handle this. (and driver
>>> maintainers say "Use the simple-mfd model like it was already done)
>>
>> simple-mfd has nothing to do here. Describe the hardware - what is the SCU?
>>
>>
> 
> As I said below, SCU is just the name used in Airoha Documentation for
> this IP block. In this register space there are multiple things so it's
> not strictly a clock-controller (as it's currently defined)
> 
> It was proposed as clock-controller previously as we weren't aware this
> IP block was used also for other usage that a strict clock controller.


I am pretty sure everyone was, just drivers were developed for current
needs and then binding was adjusted to match drivers.

> 
>>>
>>> For this specific case (and to give an answer to the clock patch after
>>> this) the problem is that this register space was originally used only
>>> to control the clock and I wasn't aware that it was also used to control
>>> USB. Now that I'm implementing support for it, the disaster happened.
>>>
>>> So In short SCU is lots of thing, both a system-controller, a
>>> clock-controller and even a reset-controller.
>>
>> And you have bindings for that already. Done.
>>
> 
> It's currently defined in DTS as clock-controller, should we change it
> to system-controller to make it more clear?

It does not matter for this discussion about bindings, it is just a
name. You can rename it, sure, although also a bit of a churn since this
device has a "clock controller" as one of its main features. And "system
controller" is also way generic.

BTW, it is frequent (e.g. all Qcom platforms, many Allwiner and
Mediatek) that clock controller is also reset or power domain controllers.


> 
>>>
>>> To make it short, 2 different solution:
>>> 1. We can keep the current node structure of the node-controller and add a
>>> child node for the SSR part (with a dedicated compatible).
>>
>> No, you do not add child nodes just because you want some drivers.
>>
>> What is SSR? How is it a device?
> 
> SSR is the name used in Documentation for the register used to configure
> the Serdes and PCIe port.

Register(s) for configuring something is not a device.

> 
>>
>>> 2. Those property need to be be defined in the clock-controller node?
>>
>> In the SCU node. Do you have only one SCU or more?
> 
> Strictly speaking it's one register space. One clock-controller, one
> reset-controller and one set of SSR registers, and from what I can
> understand it's ALWAYS "One device/compatible for Register space"

No, it's not the reason. You define children if they are distinctive. By
distinction I mean some sort of controllable resources which they need
independently of parent. No resources here, except address space, which
seems superficial choice.



> 
> The simple-mfd pattern can't really work for case like this where in one
> register space there are multiple stuff.

We agreed not to talk about simple-mfd, but answering this: yes, but
because your split is neither necessary nor really accurate.

> 
> Is everything clear now?
> 
> To summarize:
> - no child nodes
> - add additional property for SSR in the SCU .yaml

Yes.

Unless I made mistake here in the judgement, but that will be easier to
spot after seeing entire binding/DTS for this device.

Best regards,
Krzysztof


From gregory.clement at bootlin.com  Sun Mar 16 10:12:12 2025
From: gregory.clement at bootlin.com (Gregory CLEMENT)
Date: Sun, 16 Mar 2025 18:12:12 +0100
Subject: [GIT PULL] ARM: mvebu: dt64 for v6.15 (#1)
Message-ID: <87wmco99xv.fsf@BLaptop.bootlin.com>

Hi,

Here is the first pull request for dt64 for mvebu for v6.15.

Gregory

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git tags/mvebu-dt64-6.15-1

for you to fetch changes up to ed9c2b28ebef3333f25cefdc2ef37ee1f05cad95:

  arm64: dts: marvell: Use preferred node names for "simple-bus" (2025-03-15 11:27:04 +0100)

----------------------------------------------------------------
mvebu dt64 for 6.15 (part 1)

device tree clean-up fomr DT maintainers

----------------------------------------------------------------
Krzysztof Kozlowski (3):
      arm64: dts: marvell: armada-8040: Align GPIO hog name with bindings
      ARM: dts: marvell: kirkwood-openrd: Align GPIO hog name with bindings
      ARM: dts: marvell: armada: Align GPIO hog name with bindings

Rob Herring (Arm) (9):
      dt-bindings: marvell: armada-37xx: Add glinet,gl-mv1000 compatible
      dt-bindings: marvell: armada-7k-8k: Move Armada 8KPlus to schema
      dt-bindings: marvell: armada-7k-8k: Add missing 7040 and 8040 board compatibles
      arm64: dts: marvell: Drop incomplete root compatible/model properties
      arm64: dts: marvell: Fix missing/incorrect "marvell,armada3710" compatible
      arm64: dts: marvell: Add missing board compatible for IEI-Puzzle-M801
      arm64: dts: marvell: Move arch timer and pmu nodes to top-level
      arm64: dts: marvell: Drop unused CP11X_TYPE define
      arm64: dts: marvell: Use preferred node names for "simple-bus"

 .../bindings/arm/marvell/armada-37xx.yaml          |  1 +
 .../bindings/arm/marvell/armada-7k-8k.yaml         | 25 ++++++++++++++++
 .../devicetree/bindings/arm/marvell/armada-8kp.txt | 15 ----------
 .../boot/dts/marvell/armada-385-clearfog-gtr.dtsi  |  8 +++---
 .../boot/dts/marvell/armada-388-clearfog-base.dts  |  2 +-
 arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi     |  4 +--
 arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi      |  2 +-
 arch/arm64/boot/dts/marvell/armada-371x.dtsi       | 17 -----------
 arch/arm64/boot/dts/marvell/armada-3720-db.dts     |  2 +-
 .../dts/marvell/armada-3720-espressobin-emmc.dts   |  2 +-
 .../dts/marvell/armada-3720-espressobin-ultra.dts  |  2 +-
 .../marvell/armada-3720-espressobin-v7-emmc.dts    |  2 +-
 .../dts/marvell/armada-3720-espressobin-v7.dts     |  2 +-
 .../boot/dts/marvell/armada-3720-espressobin.dts   |  2 +-
 .../boot/dts/marvell/armada-3720-gl-mv1000.dts     |  2 +-
 .../boot/dts/marvell/armada-3720-turris-mox.dts    |  2 +-
 arch/arm64/boot/dts/marvell/armada-372x.dtsi       |  3 --
 arch/arm64/boot/dts/marvell/armada-37xx.dtsi       |  4 +--
 arch/arm64/boot/dts/marvell/armada-7020.dtsi       |  6 ----
 arch/arm64/boot/dts/marvell/armada-7040.dtsi       |  6 ----
 arch/arm64/boot/dts/marvell/armada-8020.dtsi       |  6 ----
 .../dts/marvell/armada-8040-clearfog-gt-8k.dts     |  8 +++---
 .../boot/dts/marvell/armada-8040-puzzle-m801.dts   |  2 +-
 arch/arm64/boot/dts/marvell/armada-8040.dtsi       |  6 ----
 arch/arm64/boot/dts/marvell/armada-8080.dtsi       |  6 ----
 arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi |  3 --
 arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi |  3 --
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi      |  6 ----
 arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi |  3 --
 arch/arm64/boot/dts/marvell/armada-ap807.dtsi      |  6 ----
 arch/arm64/boot/dts/marvell/armada-ap80x.dtsi      | 33 +++++++++++-----------
 .../dts/marvell/armada-ap810-ap0-octa-core.dtsi    |  1 -
 arch/arm64/boot/dts/marvell/armada-ap810-ap0.dtsi  | 24 ++++++++--------
 arch/arm64/boot/dts/marvell/armada-cp110.dtsi      |  4 ---
 arch/arm64/boot/dts/marvell/armada-cp115.dtsi      |  4 ---
 arch/arm64/boot/dts/marvell/armada-cp11x.dtsi      |  4 +--
 arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi     |  3 --
 37 files changed, 78 insertions(+), 153 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/arm/marvell/armada-8kp.txt
 delete mode 100644 arch/arm64/boot/dts/marvell/armada-371x.dtsi

-- 
Gr?gory CLEMENT, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From vkoul at kernel.org  Sun Mar 16 10:19:55 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Sun, 16 Mar 2025 22:49:55 +0530
Subject: [PATCH v8 0/2] MIPI DSI phy for rk3588
In-Reply-To: <20250313134035.278133-1-heiko@sntech.de>
References: <20250313134035.278133-1-heiko@sntech.de>
Message-ID: <174214559552.644495.17738101369641908083.b4-ty@kernel.org>


On Thu, 13 Mar 2025 14:40:30 +0100, Heiko Stuebner wrote:
> This adds the phy driver need for DSI output on rk3588.
> 
> The phy itself is used for both DSI output and CSI input, though the
> CSI part for the whole chain needs a lot more work, so is left out for
> now and only the DSI part implemented.
> 
> This allows the rk3588 with its current VOP support to drive a DSI display
> using the DSI2 controller driver I'll submit in a next step.
> 
> [...]

Applied, thanks!

[1/2] dt-bindings: phy: Add Rockchip MIPI C-/D-PHY schema
      commit: 301587cf4e771aca8c5ee05a6ba8d7d8f548e478
[2/2] phy: rockchip: Add Samsung MIPI D-/C-PHY driver
      commit: b2a1a2ae7818c9d8da12bf7b1983c8b9f5fb712b

Best regards,
-- 
~Vinod




From vkoul at kernel.org  Sun Mar 16 10:19:59 2025
From: vkoul at kernel.org (Vinod Koul)
Date: Sun, 16 Mar 2025 22:49:59 +0530
Subject: [PATCH v2 1/2] dt-bindings: phy: rockchip: Add rk3562
 naneng-combophy compatible
In-Reply-To: <20250227110836.2343158-1-kever.yang@rock-chips.com>
References: <20250227110836.2343158-1-kever.yang@rock-chips.com>
Message-ID: <174214559984.644495.8037439258836601775.b4-ty@kernel.org>


On Thu, 27 Feb 2025 19:08:35 +0800, Kever Yang wrote:
> rk3562 use the same Naneng Combo Phy driver as rk3568.
> 
> 

Applied, thanks!

[1/2] dt-bindings: phy: rockchip: Add rk3562 naneng-combophy compatible
      commit: 86ae168934098be744cd5a8470544165f0054d0b
[2/2] phy: rockchip-naneng-combo: Support rk3562
      commit: f13bff25161b8a0a9d716764ebe57334d496c6d9

Best regards,
-- 
~Vinod




From krzk at kernel.org  Sun Mar 16 10:31:16 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 18:31:16 +0100
Subject: [PATCH v4 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <c3d438aa-504f-4d13-909e-ed9be0394b75@roeck-us.net>
References: <20250313125746.2901904-1-florin.leotescu@oss.nxp.com>
 <20250313125746.2901904-2-florin.leotescu@oss.nxp.com>
 <20250314-encouraging-fabulous-ant-e1f7b0@krzk-bin>
 <DU7PR04MB11163B2B2D8D429B2667DAA65FFD22@DU7PR04MB11163.eurprd04.prod.outlook.com>
 <c3d438aa-504f-4d13-909e-ed9be0394b75@roeck-us.net>
Message-ID: <c3ba9ee6-15ec-4824-a74f-c02b40144d46@kernel.org>

On 14/03/2025 16:17, Guenter Roeck wrote:
>>>> +                pwms = <&fan_controller 1 1>;
>>>
>>> It's the same PWM for all fans? So isn't it basically one fan? How do you exactly control them independently, if the same PWM channel is used?
>>>
>>
>> It is the same PWM controller, but each fan has a different PWM channel. According to datasheet, the EMC2305 could control up to five programmable fan control circuits.
>> The driver will parse all fan child nodes during probe and use reg to differentiate the channels, similar as it is done on max6639 hwmon driver.
>> The 'pwms' arguments in the example are used to select the polarity and pwm output, which will be parsed in the driver to generate the bits for the registers used to select pwm output and pwm polarity.
>> (... <&fan_controller [pwm_polarity] [pwm_output]> ...).  Now, I realized that I should use: <&fan_controller [pwm_channel] [pwm_frequency] [pwm_polarity] [pwm_output]>. I will also document the arguments in #pwm-cells description.
>> Thanks!
>>
> 
> Please also document that the channel assignment is fixed. Technically it
> doesn't even make sense to specify the pwm channel (it is fixed and
> matches "reg"). I don't know if the channel number can be omitted from pwms.
> All you really need is polarity, frequency, and output type.
> 
> I am not really sure what to do if the channel number is mandatory.
> If it is, I'd suggest to document it as mandated but not needed/used,
> and then ignore it in the code.

Skipping channel would be fine for me, but then mention this in the
'reg' description.



Best regards,
Krzysztof


From krzk at kernel.org  Sun Mar 16 10:36:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 16 Mar 2025 18:36:53 +0100
Subject: [PATCH hyperv-next v6 07/11] dt-bindings: microsoft,vmbus: Add
 interrupt and DMA coherence properties
In-Reply-To: <20250315001931.631210-8-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-8-romank@linux.microsoft.com>
Message-ID: <20250316-versed-trogon-of-serendipity-bf7ea7@krzk-bin>

On Fri, Mar 14, 2025 at 05:19:27PM -0700, Roman Kisel wrote:
>  
> +  dma-coherent: true
> +
> +  interrupts:

> +    maxItems: 1
> +    description: |
> +      This interrupt is used to report a message from the host.

These could be just two lines:

items:
  - description: Interrupt used to report a message from the host.

(and note that just like we do not use "This" in commit msg, there is
really no benefit of using it in hardware descruption for simple
statements)

Regardless:

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From aweber.kernel at gmail.com  Sun Mar 16 11:18:56 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:56 +0100
Subject: [PATCH v7 08/10] regulator: bcm590xx: Store regulator descriptions
 in table
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-8-4281126be1b8@gmail.com>

Instead of filling in the regulator description programatically,
store the data in a struct. This will make it a bit nicer to
introduce support for other BCM590xx chips besides the BCM59056.

To do this, add a new struct type, bcm590xx_reg_data, to store
all of the necessary information. Drop the old IS_LDO, IS_GPLDO...
macros in favor of the "type" field in this struct. Adapt the
old bcm590xx_reg struct to the new types.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Adapt to changes in MFD header

Changes in v5:
- Move the bcm590xx_regmap_type enum to the bcm590xx.h header
- Rename bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Replace incorrect return in regmap selection error handling
- Use switch statement for regmap selection

Changes in v3:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 473 ++++++++++++++++++++++-----------
 include/linux/mfd/bcm590xx.h           |   6 +
 2 files changed, 322 insertions(+), 157 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index a17311fa30e4d48c0a4925778d7bed486ac7a982..c2427ea166626bdc1eb7cfb99997d95e5125ed91 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -20,6 +20,18 @@
 
 /* I2C slave 0 registers */
 #define BCM590XX_RFLDOPMCTRL1	0x60
+#define BCM590XX_CAMLDO1PMCTRL1	0x62
+#define BCM590XX_CAMLDO2PMCTRL1	0x64
+#define BCM590XX_SIMLDO1PMCTRL1	0x66
+#define BCM590XX_SIMLDO2PMCTRL1	0x68
+#define BCM590XX_SDLDOPMCTRL1	0x6a
+#define BCM590XX_SDXLDOPMCTRL1	0x6c
+#define BCM590XX_MMCLDO1PMCTRL1	0x6e
+#define BCM590XX_MMCLDO2PMCTRL1	0x70
+#define BCM590XX_AUDLDOPMCTRL1	0x72
+#define BCM590XX_MICLDOPMCTRL1	0x74
+#define BCM590XX_USBLDOPMCTRL1	0x76
+#define BCM590XX_VIBLDOPMCTRL1	0x78
 #define BCM590XX_IOSR1PMCTRL1	0x7a
 #define BCM590XX_IOSR2PMCTRL1	0x7c
 #define BCM590XX_CSRPMCTRL1	0x7e
@@ -28,7 +40,25 @@
 #define BCM590XX_MSRPMCTRL1	0x8a
 #define BCM590XX_VSRPMCTRL1	0x8e
 #define BCM590XX_RFLDOCTRL	0x96
+#define BCM590XX_CAMLDO1CTRL	0x97
+#define BCM590XX_CAMLDO2CTRL	0x98
+#define BCM590XX_SIMLDO1CTRL	0x99
+#define BCM590XX_SIMLDO2CTRL	0x9a
+#define BCM590XX_SDLDOCTRL	0x9b
+#define BCM590XX_SDXLDOCTRL	0x9c
+#define BCM590XX_MMCLDO1CTRL	0x9d
+#define BCM590XX_MMCLDO2CTRL	0x9e
+#define BCM590XX_AUDLDOCTRL	0x9f
+#define BCM590XX_MICLDOCTRL	0xa0
+#define BCM590XX_USBLDOCTRL	0xa1
+#define BCM590XX_VIBLDOCTRL	0xa2
 #define BCM590XX_CSRVOUT1	0xc0
+#define BCM590XX_IOSR1VOUT1	0xc3
+#define BCM590XX_IOSR2VOUT1	0xc6
+#define BCM590XX_MSRVOUT1	0xc9
+#define BCM590XX_SDSR1VOUT1	0xcc
+#define BCM590XX_SDSR2VOUT1	0xcf
+#define BCM590XX_VSRVOUT1	0xd2
 
 /* I2C slave 1 registers */
 #define BCM590XX_GPLDO5PMCTRL1	0x16
@@ -94,11 +124,6 @@
 
 #define BCM590XX_NUM_REGS	27
 
-#define BCM590XX_REG_IS_LDO(n)	(n < BCM590XX_REG_CSR)
-#define BCM590XX_REG_IS_GPLDO(n) \
-	((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
-#define BCM590XX_REG_IS_VBUS(n)	(n == BCM590XX_REG_VBUS)
-
 /* LDO group A: supported voltages in microvolts */
 static const unsigned int ldo_a_table[] = {
 	1200000, 1800000, 2500000, 2700000, 2800000,
@@ -111,10 +136,6 @@ static const unsigned int ldo_c_table[] = {
 	2900000, 3000000, 3300000,
 };
 
-static const unsigned int ldo_vbus[] = {
-	5000000,
-};
-
 /* DCDC group CSR: supported voltages in microvolts */
 static const struct linear_range dcdc_csr_ranges[] = {
 	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
@@ -137,115 +158,25 @@ static const struct linear_range dcdc_sdsr1_ranges[] = {
 	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
 };
 
-struct bcm590xx_info {
-	const char *name;
-	const char *vin_name;
-	u8 n_voltages;
-	const unsigned int *volt_table;
-	u8 n_linear_ranges;
-	const struct linear_range *linear_ranges;
+enum bcm590xx_reg_type {
+	BCM590XX_REG_TYPE_LDO,
+	BCM590XX_REG_TYPE_GPLDO,
+	BCM590XX_REG_TYPE_SR,
+	BCM590XX_REG_TYPE_VBUS
 };
 
-#define BCM590XX_REG_TABLE(_name, _table) \
-	{ \
-		.name = #_name, \
-		.n_voltages = ARRAY_SIZE(_table), \
-		.volt_table = _table, \
-	}
-
-#define BCM590XX_REG_RANGES(_name, _ranges) \
-	{ \
-		.name = #_name, \
-		.n_voltages = 64, \
-		.n_linear_ranges = ARRAY_SIZE(_ranges), \
-		.linear_ranges = _ranges, \
-	}
-
-static struct bcm590xx_info bcm590xx_regs[] = {
-	BCM590XX_REG_TABLE(rfldo, ldo_a_table),
-	BCM590XX_REG_TABLE(camldo1, ldo_c_table),
-	BCM590XX_REG_TABLE(camldo2, ldo_c_table),
-	BCM590XX_REG_TABLE(simldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(simldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(sdldo, ldo_c_table),
-	BCM590XX_REG_TABLE(sdxldo, ldo_a_table),
-	BCM590XX_REG_TABLE(mmcldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(mmcldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(audldo, ldo_a_table),
-	BCM590XX_REG_TABLE(micldo, ldo_a_table),
-	BCM590XX_REG_TABLE(usbldo, ldo_a_table),
-	BCM590XX_REG_TABLE(vibldo, ldo_c_table),
-	BCM590XX_REG_RANGES(csr, dcdc_csr_ranges),
-	BCM590XX_REG_RANGES(iosr1, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(iosr2, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(msr, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
-	BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
-	BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
-	BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
-	BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
-	BCM590XX_REG_TABLE(vbus, ldo_vbus),
+struct bcm590xx_reg_data {
+	enum bcm590xx_reg_type type;
+	enum bcm590xx_regmap_type regmap;
+	const struct regulator_desc desc;
 };
 
 struct bcm590xx_reg {
-	struct regulator_desc *desc;
 	struct bcm590xx *mfd;
+	unsigned int n_regulators;
+	const struct bcm590xx_reg_data *regs;
 };
 
-static int bcm590xx_get_vsel_register(int id)
-{
-	if (BCM590XX_REG_IS_LDO(id))
-		return BCM590XX_RFLDOCTRL + id;
-	else if (BCM590XX_REG_IS_GPLDO(id))
-		return BCM590XX_GPLDO1CTRL + id;
-	else
-		return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
-}
-
-static int bcm590xx_get_enable_register(int id)
-{
-	int reg = 0;
-
-	if (BCM590XX_REG_IS_LDO(id))
-		reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
-	else if (BCM590XX_REG_IS_GPLDO(id))
-		reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
-	else
-		switch (id) {
-		case BCM590XX_REG_CSR:
-			reg = BCM590XX_CSRPMCTRL1;
-			break;
-		case BCM590XX_REG_IOSR1:
-			reg = BCM590XX_IOSR1PMCTRL1;
-			break;
-		case BCM590XX_REG_IOSR2:
-			reg = BCM590XX_IOSR2PMCTRL1;
-			break;
-		case BCM590XX_REG_MSR:
-			reg = BCM590XX_MSRPMCTRL1;
-			break;
-		case BCM590XX_REG_SDSR1:
-			reg = BCM590XX_SDSR1PMCTRL1;
-			break;
-		case BCM590XX_REG_SDSR2:
-			reg = BCM590XX_SDSR2PMCTRL1;
-			break;
-		case BCM590XX_REG_VSR:
-			reg = BCM590XX_VSRPMCTRL1;
-			break;
-		case BCM590XX_REG_VBUS:
-			reg = BCM590XX_OTG_CTRL;
-			break;
-		}
-
-
-	return reg;
-}
-
 static const struct regulator_ops bcm590xx_ops_ldo = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
@@ -272,73 +203,301 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 	.disable		= regulator_disable_regmap,
 };
 
+#define BCM590XX_REG_DESC(_name, _name_lower)				\
+	.id = BCM590XX_REG_##_name,					\
+	.name = #_name_lower,						\
+	.of_match = of_match_ptr(#_name_lower),				\
+	.regulators_node = of_match_ptr("regulators"),			\
+	.type = REGULATOR_VOLTAGE,					\
+	.owner = THIS_MODULE						\
+
+#define BCM590XX_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_REG_DESC(_name, _name_lower),				\
+	.ops = &bcm590xx_ops_ldo,					\
+	.n_voltages = ARRAY_SIZE(_table),				\
+	.volt_table = _table,						\
+	.vsel_reg = BCM590XX_##_name##CTRL,				\
+	.vsel_mask = BCM590XX_LDO_VSEL_MASK,				\
+	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_mask = BCM590XX_REG_ENABLE,				\
+	.enable_is_inverted = true
+
+#define BCM590XX_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_REG_DESC(_name, _name_lower),				\
+	.ops = &bcm590xx_ops_dcdc,					\
+	.n_voltages = 64,						\
+	.linear_ranges = _ranges,					\
+	.n_linear_ranges = ARRAY_SIZE(_ranges),				\
+	.vsel_reg = BCM590XX_##_name##VOUT1,				\
+	.vsel_mask = BCM590XX_SR_VSEL_MASK,				\
+	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_mask = BCM590XX_REG_ENABLE,				\
+	.enable_is_inverted = true
+
+static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(RFLDO, rfldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SDLDO, sdldo, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(AUDLDO, audldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(MICLDO, micldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(USBLDO, usbldo, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM590XX_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM590XX_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM590XX_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
 static int bcm590xx_probe(struct platform_device *pdev)
 {
 	struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
 	struct bcm590xx_reg *pmu;
+	const struct bcm590xx_reg_data *info;
 	struct regulator_config config = { };
-	struct bcm590xx_info *info;
 	struct regulator_dev *rdev;
-	int i;
+	unsigned int i;
 
 	pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
 	if (!pmu)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
+	pmu->n_regulators = BCM590XX_NUM_REGS;
+	pmu->regs = bcm590xx_regs;
 
 	platform_set_drvdata(pdev, pmu);
 
-	pmu->desc = devm_kcalloc(&pdev->dev,
-				 BCM590XX_NUM_REGS,
-				 sizeof(struct regulator_desc),
-				 GFP_KERNEL);
-	if (!pmu->desc)
-		return -ENOMEM;
-
-	info = bcm590xx_regs;
-
-	for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) {
-		/* Register the regulators */
-		pmu->desc[i].name = info->name;
-		pmu->desc[i].of_match = of_match_ptr(info->name);
-		pmu->desc[i].regulators_node = of_match_ptr("regulators");
-		pmu->desc[i].supply_name = info->vin_name;
-		pmu->desc[i].id = i;
-		pmu->desc[i].volt_table = info->volt_table;
-		pmu->desc[i].n_voltages = info->n_voltages;
-		pmu->desc[i].linear_ranges = info->linear_ranges;
-		pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
-
-		if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
-			pmu->desc[i].ops = &bcm590xx_ops_ldo;
-			pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
-		} else if (BCM590XX_REG_IS_VBUS(i))
-			pmu->desc[i].ops = &bcm590xx_ops_vbus;
-		else {
-			pmu->desc[i].ops = &bcm590xx_ops_dcdc;
-			pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
-		}
-
-		if (BCM590XX_REG_IS_VBUS(i))
-			pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
-		else {
-			pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
-			pmu->desc[i].enable_is_inverted = true;
-			pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
-		}
-		pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
-		pmu->desc[i].type = REGULATOR_VOLTAGE;
-		pmu->desc[i].owner = THIS_MODULE;
+	/* Register the regulators */
+	for (i = 0; i < pmu->n_regulators; i++) {
+		info = &pmu->regs[i];
 
 		config.dev = bcm590xx->dev;
 		config.driver_data = pmu;
-		if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
-			config.regmap = bcm590xx->regmap_sec;
-		else
+
+		switch (info->regmap) {
+		case BCM590XX_REGMAP_PRI:
 			config.regmap = bcm590xx->regmap_pri;
+			break;
+		case BCM590XX_REGMAP_SEC:
+			config.regmap = bcm590xx->regmap_sec;
+			break;
+		default:
+			dev_err(bcm590xx->dev,
+				"invalid regmap for %s regulator; this is a driver bug\n",
+				pdev->name);
+			return -EINVAL;
+		}
 
-		rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
+		rdev = devm_regulator_register(&pdev->dev, &info->desc,
 					       &config);
 		if (IS_ERR(rdev))
 			return dev_err_probe(bcm590xx->dev, PTR_ERR(rdev),
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index fbc458e94bef923ca1b69afe2cac944adf6fedf8..5a5783abd47b9a6bb6f9bb3a8cafddbd01aa7fcc 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -27,6 +27,12 @@
 #define BCM59056_REV_DIGITAL_B0		2
 #define BCM59056_REV_ANALOG_B0		2
 
+/* regmap types */
+enum bcm590xx_regmap_type {
+	BCM590XX_REGMAP_PRI,
+	BCM590XX_REGMAP_SEC,
+};
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:57 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:57 +0100
Subject: [PATCH v7 09/10] regulator: bcm590xx: Rename BCM59056-specific
 data as such
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-9-4281126be1b8@gmail.com>

Previously, the driver used the BCM590XX prefix for register data
specific to the BCM59056. As we will be introducing other regulators
to this driver as well, make the BCM59056-specific values use the
BCM59056 prefix.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v5:
- Adapt to rename of bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Drop unused BCM590XX_MAX_NUM_REGS constant

Changes in v3:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 369 +++++++++++++++++----------------
 1 file changed, 189 insertions(+), 180 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index c2427ea166626bdc1eb7cfb99997d95e5125ed91..f35b2b72e46f70496e16be5244529a5d95d0546d 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -18,146 +18,11 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
 
-/* I2C slave 0 registers */
-#define BCM590XX_RFLDOPMCTRL1	0x60
-#define BCM590XX_CAMLDO1PMCTRL1	0x62
-#define BCM590XX_CAMLDO2PMCTRL1	0x64
-#define BCM590XX_SIMLDO1PMCTRL1	0x66
-#define BCM590XX_SIMLDO2PMCTRL1	0x68
-#define BCM590XX_SDLDOPMCTRL1	0x6a
-#define BCM590XX_SDXLDOPMCTRL1	0x6c
-#define BCM590XX_MMCLDO1PMCTRL1	0x6e
-#define BCM590XX_MMCLDO2PMCTRL1	0x70
-#define BCM590XX_AUDLDOPMCTRL1	0x72
-#define BCM590XX_MICLDOPMCTRL1	0x74
-#define BCM590XX_USBLDOPMCTRL1	0x76
-#define BCM590XX_VIBLDOPMCTRL1	0x78
-#define BCM590XX_IOSR1PMCTRL1	0x7a
-#define BCM590XX_IOSR2PMCTRL1	0x7c
-#define BCM590XX_CSRPMCTRL1	0x7e
-#define BCM590XX_SDSR1PMCTRL1	0x82
-#define BCM590XX_SDSR2PMCTRL1	0x86
-#define BCM590XX_MSRPMCTRL1	0x8a
-#define BCM590XX_VSRPMCTRL1	0x8e
-#define BCM590XX_RFLDOCTRL	0x96
-#define BCM590XX_CAMLDO1CTRL	0x97
-#define BCM590XX_CAMLDO2CTRL	0x98
-#define BCM590XX_SIMLDO1CTRL	0x99
-#define BCM590XX_SIMLDO2CTRL	0x9a
-#define BCM590XX_SDLDOCTRL	0x9b
-#define BCM590XX_SDXLDOCTRL	0x9c
-#define BCM590XX_MMCLDO1CTRL	0x9d
-#define BCM590XX_MMCLDO2CTRL	0x9e
-#define BCM590XX_AUDLDOCTRL	0x9f
-#define BCM590XX_MICLDOCTRL	0xa0
-#define BCM590XX_USBLDOCTRL	0xa1
-#define BCM590XX_VIBLDOCTRL	0xa2
-#define BCM590XX_CSRVOUT1	0xc0
-#define BCM590XX_IOSR1VOUT1	0xc3
-#define BCM590XX_IOSR2VOUT1	0xc6
-#define BCM590XX_MSRVOUT1	0xc9
-#define BCM590XX_SDSR1VOUT1	0xcc
-#define BCM590XX_SDSR2VOUT1	0xcf
-#define BCM590XX_VSRVOUT1	0xd2
-
-/* I2C slave 1 registers */
-#define BCM590XX_GPLDO5PMCTRL1	0x16
-#define BCM590XX_GPLDO6PMCTRL1	0x18
-#define BCM590XX_GPLDO1CTRL	0x1a
-#define BCM590XX_GPLDO2CTRL	0x1b
-#define BCM590XX_GPLDO3CTRL	0x1c
-#define BCM590XX_GPLDO4CTRL	0x1d
-#define BCM590XX_GPLDO5CTRL	0x1e
-#define BCM590XX_GPLDO6CTRL	0x1f
-#define BCM590XX_OTG_CTRL	0x40
-#define BCM590XX_GPLDO1PMCTRL1	0x57
-#define BCM590XX_GPLDO2PMCTRL1	0x59
-#define BCM590XX_GPLDO3PMCTRL1	0x5b
-#define BCM590XX_GPLDO4PMCTRL1	0x5d
-
 #define BCM590XX_REG_ENABLE	BIT(7)
 #define BCM590XX_VBUS_ENABLE	BIT(2)
 #define BCM590XX_LDO_VSEL_MASK	GENMASK(5, 3)
 #define BCM590XX_SR_VSEL_MASK	GENMASK(5, 0)
 
-/*
- * RFLDO to VSR regulators are
- * accessed via I2C slave 0
- */
-
-/* LDO regulator IDs */
-#define BCM590XX_REG_RFLDO	0
-#define BCM590XX_REG_CAMLDO1	1
-#define BCM590XX_REG_CAMLDO2	2
-#define BCM590XX_REG_SIMLDO1	3
-#define BCM590XX_REG_SIMLDO2	4
-#define BCM590XX_REG_SDLDO	5
-#define BCM590XX_REG_SDXLDO	6
-#define BCM590XX_REG_MMCLDO1	7
-#define BCM590XX_REG_MMCLDO2	8
-#define BCM590XX_REG_AUDLDO	9
-#define BCM590XX_REG_MICLDO	10
-#define BCM590XX_REG_USBLDO	11
-#define BCM590XX_REG_VIBLDO	12
-
-/* DCDC regulator IDs */
-#define BCM590XX_REG_CSR	13
-#define BCM590XX_REG_IOSR1	14
-#define BCM590XX_REG_IOSR2	15
-#define BCM590XX_REG_MSR	16
-#define BCM590XX_REG_SDSR1	17
-#define BCM590XX_REG_SDSR2	18
-#define BCM590XX_REG_VSR	19
-
-/*
- * GPLDO1 to VBUS regulators are
- * accessed via I2C slave 1
- */
-
-#define BCM590XX_REG_GPLDO1	20
-#define BCM590XX_REG_GPLDO2	21
-#define BCM590XX_REG_GPLDO3	22
-#define BCM590XX_REG_GPLDO4	23
-#define BCM590XX_REG_GPLDO5	24
-#define BCM590XX_REG_GPLDO6	25
-#define BCM590XX_REG_VBUS	26
-
-#define BCM590XX_NUM_REGS	27
-
-/* LDO group A: supported voltages in microvolts */
-static const unsigned int ldo_a_table[] = {
-	1200000, 1800000, 2500000, 2700000, 2800000,
-	2900000, 3000000, 3300000,
-};
-
-/* LDO group C: supported voltages in microvolts */
-static const unsigned int ldo_c_table[] = {
-	3100000, 1800000, 2500000, 2700000, 2800000,
-	2900000, 3000000, 3300000,
-};
-
-/* DCDC group CSR: supported voltages in microvolts */
-static const struct linear_range dcdc_csr_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
-	REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
-	REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
-};
-
-/* DCDC group IOSR1: supported voltages in microvolts */
-static const struct linear_range dcdc_iosr1_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
-	REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
-	REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
-	REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
-};
-
-/* DCDC group SDSR1: supported voltages in microvolts */
-static const struct linear_range dcdc_sdsr1_ranges[] = {
-	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
-	REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
-	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
-};
-
 enum bcm590xx_reg_type {
 	BCM590XX_REG_TYPE_LDO,
 	BCM590XX_REG_TYPE_GPLDO,
@@ -203,43 +68,187 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 	.disable		= regulator_disable_regmap,
 };
 
-#define BCM590XX_REG_DESC(_name, _name_lower)				\
-	.id = BCM590XX_REG_##_name,					\
+#define BCM590XX_REG_DESC(_model, _name, _name_lower)			\
+	.id = _model##_REG_##_name,					\
 	.name = #_name_lower,						\
 	.of_match = of_match_ptr(#_name_lower),				\
 	.regulators_node = of_match_ptr("regulators"),			\
 	.type = REGULATOR_VOLTAGE,					\
 	.owner = THIS_MODULE						\
 
-#define BCM590XX_LDO_DESC(_name, _name_lower, _table)			\
-	BCM590XX_REG_DESC(_name, _name_lower),				\
+#define BCM590XX_LDO_DESC(_model, _model_lower, _name, _name_lower, _table) \
+	BCM590XX_REG_DESC(_model, _name, _name_lower),			\
 	.ops = &bcm590xx_ops_ldo,					\
-	.n_voltages = ARRAY_SIZE(_table),				\
-	.volt_table = _table,						\
-	.vsel_reg = BCM590XX_##_name##CTRL,				\
+	.n_voltages = ARRAY_SIZE(_model_lower##_##_table),		\
+	.volt_table = _model_lower##_##_table,				\
+	.vsel_reg = _model##_##_name##CTRL,				\
 	.vsel_mask = BCM590XX_LDO_VSEL_MASK,				\
-	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_reg = _model##_##_name##PMCTRL1,			\
 	.enable_mask = BCM590XX_REG_ENABLE,				\
 	.enable_is_inverted = true
 
-#define BCM590XX_SR_DESC(_name, _name_lower, _ranges)			\
-	BCM590XX_REG_DESC(_name, _name_lower),				\
+#define BCM590XX_SR_DESC(_model, _model_lower, _name, _name_lower, _ranges) \
+	BCM590XX_REG_DESC(_model, _name, _name_lower),			\
 	.ops = &bcm590xx_ops_dcdc,					\
 	.n_voltages = 64,						\
-	.linear_ranges = _ranges,					\
-	.n_linear_ranges = ARRAY_SIZE(_ranges),				\
-	.vsel_reg = BCM590XX_##_name##VOUT1,				\
+	.linear_ranges = _model_lower##_##_ranges,			\
+	.n_linear_ranges = ARRAY_SIZE(_model_lower##_##_ranges),	\
+	.vsel_reg = _model##_##_name##VOUT1,				\
 	.vsel_mask = BCM590XX_SR_VSEL_MASK,				\
-	.enable_reg = BCM590XX_##_name##PMCTRL1,			\
+	.enable_reg = _model##_##_name##PMCTRL1,			\
 	.enable_mask = BCM590XX_REG_ENABLE,				\
 	.enable_is_inverted = true
 
-static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
+#define BCM59056_REG_DESC(_name, _name_lower)				\
+	BCM590XX_REG_DESC(BCM59056, _name, _name_lower)
+#define BCM59056_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_LDO_DESC(BCM59056, bcm59056, _name, _name_lower, _table)
+#define BCM59056_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_SR_DESC(BCM59056, bcm59056, _name, _name_lower, _ranges)
+
+/* BCM59056 data */
+
+/* I2C slave 0 registers */
+#define BCM59056_RFLDOPMCTRL1	0x60
+#define BCM59056_CAMLDO1PMCTRL1	0x62
+#define BCM59056_CAMLDO2PMCTRL1	0x64
+#define BCM59056_SIMLDO1PMCTRL1	0x66
+#define BCM59056_SIMLDO2PMCTRL1	0x68
+#define BCM59056_SDLDOPMCTRL1	0x6a
+#define BCM59056_SDXLDOPMCTRL1	0x6c
+#define BCM59056_MMCLDO1PMCTRL1	0x6e
+#define BCM59056_MMCLDO2PMCTRL1	0x70
+#define BCM59056_AUDLDOPMCTRL1	0x72
+#define BCM59056_MICLDOPMCTRL1	0x74
+#define BCM59056_USBLDOPMCTRL1	0x76
+#define BCM59056_VIBLDOPMCTRL1	0x78
+#define BCM59056_IOSR1PMCTRL1	0x7a
+#define BCM59056_IOSR2PMCTRL1	0x7c
+#define BCM59056_CSRPMCTRL1	0x7e
+#define BCM59056_SDSR1PMCTRL1	0x82
+#define BCM59056_SDSR2PMCTRL1	0x86
+#define BCM59056_MSRPMCTRL1	0x8a
+#define BCM59056_VSRPMCTRL1	0x8e
+#define BCM59056_RFLDOCTRL	0x96
+#define BCM59056_CAMLDO1CTRL	0x97
+#define BCM59056_CAMLDO2CTRL	0x98
+#define BCM59056_SIMLDO1CTRL	0x99
+#define BCM59056_SIMLDO2CTRL	0x9a
+#define BCM59056_SDLDOCTRL	0x9b
+#define BCM59056_SDXLDOCTRL	0x9c
+#define BCM59056_MMCLDO1CTRL	0x9d
+#define BCM59056_MMCLDO2CTRL	0x9e
+#define BCM59056_AUDLDOCTRL	0x9f
+#define BCM59056_MICLDOCTRL	0xa0
+#define BCM59056_USBLDOCTRL	0xa1
+#define BCM59056_VIBLDOCTRL	0xa2
+#define BCM59056_CSRVOUT1	0xc0
+#define BCM59056_IOSR1VOUT1	0xc3
+#define BCM59056_IOSR2VOUT1	0xc6
+#define BCM59056_MSRVOUT1	0xc9
+#define BCM59056_SDSR1VOUT1	0xcc
+#define BCM59056_SDSR2VOUT1	0xcf
+#define BCM59056_VSRVOUT1	0xd2
+
+/* I2C slave 1 registers */
+#define BCM59056_GPLDO5PMCTRL1	0x16
+#define BCM59056_GPLDO6PMCTRL1	0x18
+#define BCM59056_GPLDO1CTRL	0x1a
+#define BCM59056_GPLDO2CTRL	0x1b
+#define BCM59056_GPLDO3CTRL	0x1c
+#define BCM59056_GPLDO4CTRL	0x1d
+#define BCM59056_GPLDO5CTRL	0x1e
+#define BCM59056_GPLDO6CTRL	0x1f
+#define BCM59056_OTG_CTRL	0x40
+#define BCM59056_GPLDO1PMCTRL1	0x57
+#define BCM59056_GPLDO2PMCTRL1	0x59
+#define BCM59056_GPLDO3PMCTRL1	0x5b
+#define BCM59056_GPLDO4PMCTRL1	0x5d
+
+/*
+ * RFLDO to VSR regulators are
+ * accessed via I2C slave 0
+ */
+
+/* LDO regulator IDs */
+#define BCM59056_REG_RFLDO	0
+#define BCM59056_REG_CAMLDO1	1
+#define BCM59056_REG_CAMLDO2	2
+#define BCM59056_REG_SIMLDO1	3
+#define BCM59056_REG_SIMLDO2	4
+#define BCM59056_REG_SDLDO	5
+#define BCM59056_REG_SDXLDO	6
+#define BCM59056_REG_MMCLDO1	7
+#define BCM59056_REG_MMCLDO2	8
+#define BCM59056_REG_AUDLDO	9
+#define BCM59056_REG_MICLDO	10
+#define BCM59056_REG_USBLDO	11
+#define BCM59056_REG_VIBLDO	12
+
+/* DCDC regulator IDs */
+#define BCM59056_REG_CSR	13
+#define BCM59056_REG_IOSR1	14
+#define BCM59056_REG_IOSR2	15
+#define BCM59056_REG_MSR	16
+#define BCM59056_REG_SDSR1	17
+#define BCM59056_REG_SDSR2	18
+#define BCM59056_REG_VSR	19
+
+/*
+ * GPLDO1 to VBUS regulators are
+ * accessed via I2C slave 1
+ */
+
+#define BCM59056_REG_GPLDO1	20
+#define BCM59056_REG_GPLDO2	21
+#define BCM59056_REG_GPLDO3	22
+#define BCM59056_REG_GPLDO4	23
+#define BCM59056_REG_GPLDO5	24
+#define BCM59056_REG_GPLDO6	25
+#define BCM59056_REG_VBUS	26
+
+#define BCM59056_NUM_REGS	27
+
+/* LDO group A: supported voltages in microvolts */
+static const unsigned int bcm59056_ldo_a_table[] = {
+	1200000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group C: supported voltages in microvolts */
+static const unsigned int bcm59056_ldo_c_table[] = {
+	3100000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* DCDC group CSR: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_csr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
+	REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
+	REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
+};
+
+/* DCDC group IOSR1: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_iosr1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
+	REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
+};
+
+/* DCDC group SDSR1: supported voltages in microvolts */
+static const struct linear_range bcm59056_dcdc_sdsr1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
+	REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
+	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
+};
+
+static const struct bcm590xx_reg_data bcm59056_regs[BCM59056_NUM_REGS] = {
 	{
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(RFLDO, rfldo, ldo_a_table),
+			BCM59056_LDO_DESC(RFLDO, rfldo, ldo_a_table),
 		},
 	},
 
@@ -247,7 +256,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
+			BCM59056_LDO_DESC(CAMLDO1, camldo1, ldo_c_table),
 		},
 	},
 
@@ -255,7 +264,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
+			BCM59056_LDO_DESC(CAMLDO2, camldo2, ldo_c_table),
 		},
 	},
 
@@ -263,7 +272,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
+			BCM59056_LDO_DESC(SIMLDO1, simldo1, ldo_a_table),
 		},
 	},
 
@@ -271,7 +280,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
+			BCM59056_LDO_DESC(SIMLDO2, simldo2, ldo_a_table),
 		},
 	},
 
@@ -279,7 +288,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SDLDO, sdldo, ldo_c_table),
+			BCM59056_LDO_DESC(SDLDO, sdldo, ldo_c_table),
 		},
 	},
 
@@ -287,7 +296,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
+			BCM59056_LDO_DESC(SDXLDO, sdxldo, ldo_a_table),
 		},
 	},
 
@@ -295,7 +304,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
+			BCM59056_LDO_DESC(MMCLDO1, mmcldo1, ldo_a_table),
 		},
 	},
 
@@ -303,7 +312,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
+			BCM59056_LDO_DESC(MMCLDO2, mmcldo2, ldo_a_table),
 		},
 	},
 
@@ -311,7 +320,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(AUDLDO, audldo, ldo_a_table),
+			BCM59056_LDO_DESC(AUDLDO, audldo, ldo_a_table),
 		},
 	},
 
@@ -319,7 +328,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(MICLDO, micldo, ldo_a_table),
+			BCM59056_LDO_DESC(MICLDO, micldo, ldo_a_table),
 		},
 	},
 
@@ -327,7 +336,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(USBLDO, usbldo, ldo_a_table),
+			BCM59056_LDO_DESC(USBLDO, usbldo, ldo_a_table),
 		},
 	},
 
@@ -335,7 +344,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_LDO,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
+			BCM59056_LDO_DESC(VIBLDO, vibldo, ldo_c_table),
 		},
 	},
 
@@ -343,7 +352,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(CSR, csr, dcdc_csr_ranges),
+			BCM59056_SR_DESC(CSR, csr, dcdc_csr_ranges),
 		},
 	},
 
@@ -351,7 +360,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(IOSR1, iosr1, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -359,7 +368,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(IOSR2, iosr2, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -367,7 +376,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(MSR, msr, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -375,7 +384,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
+			BCM59056_SR_DESC(SDSR1, sdsr1, dcdc_sdsr1_ranges),
 		},
 	},
 
@@ -383,7 +392,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(SDSR2, sdsr2, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -391,7 +400,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_SR,
 		.regmap = BCM590XX_REGMAP_PRI,
 		.desc = {
-			BCM590XX_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
+			BCM59056_SR_DESC(VSR, vsr, dcdc_iosr1_ranges),
 		},
 	},
 
@@ -399,7 +408,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO1, gpldo1, ldo_a_table),
 		},
 	},
 
@@ -407,7 +416,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO2, gpldo2, ldo_a_table),
 		},
 	},
 
@@ -415,7 +424,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO3, gpldo3, ldo_a_table),
 		},
 	},
 
@@ -423,7 +432,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO4, gpldo4, ldo_a_table),
 		},
 	},
 
@@ -431,7 +440,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO5, gpldo5, ldo_a_table),
 		},
 	},
 
@@ -439,7 +448,7 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_GPLDO,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
+			BCM59056_LDO_DESC(GPLDO6, gpldo6, ldo_a_table),
 		},
 	},
 
@@ -447,11 +456,11 @@ static const struct bcm590xx_reg_data bcm590xx_regs[BCM590XX_NUM_REGS] = {
 		.type = BCM590XX_REG_TYPE_VBUS,
 		.regmap = BCM590XX_REGMAP_SEC,
 		.desc = {
-			BCM590XX_REG_DESC(VBUS, vbus),
+			BCM59056_REG_DESC(VBUS, vbus),
 			.ops = &bcm590xx_ops_vbus,
 			.n_voltages = 1,
 			.fixed_uV = 5000000,
-			.enable_reg = BCM590XX_OTG_CTRL,
+			.enable_reg = BCM59056_OTG_CTRL,
 			.enable_mask = BCM590XX_VBUS_ENABLE,
 		},
 	},
@@ -471,8 +480,8 @@ static int bcm590xx_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
-	pmu->n_regulators = BCM590XX_NUM_REGS;
-	pmu->regs = bcm590xx_regs;
+	pmu->n_regulators = BCM59056_NUM_REGS;
+	pmu->regs = bcm59056_regs;
 
 	platform_set_drvdata(pdev, pmu);
 

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:48 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:48 +0100
Subject: [PATCH v7 00/10] mfd: bcm590xx: Add support for BCM59054
Message-ID: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>

Add support for the BCM59054 MFD to the bcm590xx driver and fix a
couple of small bugs in it that also affected the already supported
BCM59056.

While we're at it - convert the devicetree bindings to YAML format
and drop the bcm59056 DTS in favor of describing the PMU in users'
DTS files, as is done for most other MFDs.

The BCM59054 is fairly similar to the BCM59056, with the primary
difference being the different number and layout of regulators.
It is primarily used in devices using the BCM21664 and BCM23550
chipsets.

This patchset has been tested on a Samsung Galaxy Grand Neo
(baffinlite rev02; DTS not in mainline yet) with a BCM59054 PMIC.
Testing on a BCM59056 would be appreciated.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v7:
- Return -ENODEV on PMU ID mismatch
- Drop "Check your DT compatible" from ID mismatch error message
- Pick up Reviewed-by trailers from Rob on DT bindings
- Link to v6: https://lore.kernel.org/r/20250304-bcm59054-v6-0-ae8302358443 at gmail.com

Changes in v6:
- Rename mfd/brcm,bcm590xx.yaml to mfd/brcm,bcm59056.yaml again
- Use PMU ID value as device type
- Rename rev_dig and rev_ana to rev_digital and rev_analog
- Link to v5: https://lore.kernel.org/r/20250221-bcm59054-v5-0-065f516a9042 at gmail.com

Changes in v5:
- Make regulator binding descriptions reference mfd/brcm,bcm590xx.yaml
  instead of mfd/brcm,bcm59056.yaml
- Move regmap type enum to common MFD header
- Link to v4: https://lore.kernel.org/r/20250215-bcm59054-v4-0-dbfb2d76a855 at gmail.com

Changes in v4:
- Fix yamllint warnings in DT bindings
- Address miscelaneous review comments related to DT bindings
  - Note that I did not end up moving the regulator refs from
    allOf compatible matches; I explained my reasoning in [1].
    [1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/
- Add PMU ID/revision parsing to MFD driver
- Fix instances of regulator data not matching vendor kernel for
  BCM59054
- Use different voltage table for BCM59054 VSR reg based on PMU
  revision
- Link to v3: https://lore.kernel.org/r/20250131-bcm59054-v3-0-bbac52a84787 at gmail.com

Changes in v3:
- Split out regulator DT bindings into separate YAML
- Use tables of regulator info instead of get_XXX_register, reg_is_XXX
  functions
- Drop "regulator: bcm590xx: Add proper handling for PMMODE registers";
  it adds unnecessary noise to the series and will be submitted separately
- Link to v2: https://lore.kernel.org/r/20231030-bcm59054-v2-0-5fa4011aa5ba at gmail.com

Changes in v2:
- Fixed BCM59054 ID being passed to BCM59056 function in the
  regulator driver
- Dropped linux-rpi-kernel from the CC list
- Link to v1: https://lore.kernel.org/r/20231030-bcm59054-v1-0-3517f980c1e3 at gmail.com

---
Artur Weber (10):
      dt-bindings: mfd: brcm,bcm59056: Convert to YAML
      dt-bindings: mfd: brcm,bcm59056: Add compatible for BCM59054
      ARM: dts: Drop DTS for BCM59056 PMU
      mfd: bcm590xx: Drop unused "id" member of bcm590xx MFD struct
      mfd: bcm590xx: Add support for multiple device types + BCM59054 compatible
      mfd: bcm590xx: Add PMU ID/revision parsing function
      regulator: bcm590xx: Use dev_err_probe for regulator register error
      regulator: bcm590xx: Store regulator descriptions in table
      regulator: bcm590xx: Rename BCM59056-specific data as such
      regulator: bcm590xx: Add support for BCM59054 regulators

 .../devicetree/bindings/mfd/brcm,bcm59056.txt      |   39 -
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     |   76 ++
 .../bindings/regulator/brcm,bcm59054.yaml          |   56 +
 .../bindings/regulator/brcm,bcm59056.yaml          |   51 +
 arch/arm/boot/dts/broadcom/bcm28155-ap.dts         |   68 +-
 arch/arm/boot/dts/broadcom/bcm59056.dtsi           |   91 --
 drivers/mfd/bcm590xx.c                             |   75 +-
 drivers/regulator/bcm590xx-regulator.c             | 1289 ++++++++++++++++----
 include/linux/mfd/bcm590xx.h                       |   28 +-
 9 files changed, 1366 insertions(+), 407 deletions(-)
---
base-commit: ffd294d346d185b70e28b1a28abe367bbfe53c04
change-id: 20240816-bcm59054-a880695e41e8

Best regards,
-- 
Artur Weber <aweber.kernel at gmail.com>



From aweber.kernel at gmail.com  Sun Mar 16 11:18:49 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:49 +0100
Subject: [PATCH v7 01/10] dt-bindings: mfd: brcm,bcm59056: Convert to YAML
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-1-4281126be1b8@gmail.com>

Convert devicetree bindings for the Broadcom BCM59056 PMU MFD from
TXT to YAML format. This patch does not change any functionality;
the bindings remain the same.

The bindings have been split into two parts: the MFD binding and
a separate binding for the regulator node, to simplify the addition
of other models later (which have different regulators).

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml

Changes in v5:
- Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
  regulator binding description

Changes in v4:
- Made $ref use full schema path
- Cleaned up example
- Dropped regulator name list comment
- Changed description of regulator binding to mention BCM59056
  explicitly
- Changed "Power Management IC" to "Power Management Unit" to match
  official Broadcom naming
- Renamed mfd/brcm,bcm59056.yaml to mfd/brcm,bcm590xx.yaml

Changes in v3:
- Moved regulator node to separate binding
- Removed quotes around compatibles/vbus property
- Style fixes for example
---
 .../devicetree/bindings/mfd/brcm,bcm59056.txt      | 39 ----------------
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 54 ++++++++++++++++++++++
 .../bindings/regulator/brcm,bcm59056.yaml          | 51 ++++++++++++++++++++
 3 files changed, 105 insertions(+), 39 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt
deleted file mode 100644
index be51a15e05f926913b3a473648d977b25f1a2fbc..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt
+++ /dev/null
@@ -1,39 +0,0 @@
--------------------------------
-BCM590xx Power Management Units
--------------------------------
-
-Required properties:
-- compatible: "brcm,bcm59056"
-- reg: I2C slave address
-- interrupts: interrupt for the PMU. Generic interrupt client node bindings
-  are described in interrupt-controller/interrupts.txt
-
-------------------
-Voltage Regulators
-------------------
-
-Optional child nodes:
-- regulators: container node for regulators following the generic
-  regulator binding in regulator/regulator.txt
-
-  The valid regulator node names for BCM59056 are:
-  	rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
-	mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
-	csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr,
-	gpldo1, gpldo2, gpldo3, gpldo4, gpldo5, gpldo6,
-	vbus
-
-Example:
-	pmu: bcm59056 at 8 {
-		compatible = "brcm,bcm59056";
-		reg = <0x08>;
-		interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
-		regulators {
-			rfldo_reg: rfldo {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3300000>;
-			};
-
-			...
-		};
-	};
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b387ef9885c3ac524e0782545dbca9c0e81a556c
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/brcm,bcm59056.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM590xx Power Management Units
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+properties:
+  compatible:
+    const: brcm,bcm59056
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  regulators:
+    type: object
+    $ref: /schemas/regulator/brcm,bcm59056.yaml#
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic at 8 {
+            compatible = "brcm,bcm59056";
+            reg = <0x08>;
+            interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+
+            regulators {
+                rfldo {
+                    regulator-min-microvolt = <1200000>;
+                    regulator-max-microvolt = <3300000>;
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7a5e36394d216232e0a2070fb20d09dcc1ea8056
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/brcm,bcm59056.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/brcm,bcm59056.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM59056 Power Management Unit regulators
+
+description: |
+  This is a part of device tree bindings for the BCM59056 power
+  management unit.
+
+  See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
+  additional information and example.
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+patternProperties:
+  "^(cam|sim|mmc)ldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(rf|sd|sdx|aud|mic|usb|vib)ldo$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(c|m|v)sr$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(io|sd)sr[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^gpldo[1-6]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+properties:
+  vbus:
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+additionalProperties: false

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:50 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:50 +0100
Subject: [PATCH v7 02/10] dt-bindings: mfd: brcm,bcm59056: Add compatible
 for BCM59054
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-2-4281126be1b8@gmail.com>

The BCM59054 MFD is fairly similar to the BCM59056, and will use
the same driver. Add compatible and specify the allowed regulator
nodes.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Replace mfd/brcm,bcm590xx.yaml with mfd/brcm,bcm59056.yaml

Changes in v5:
- Replace mfd/brcm,bcm59056.yaml with mfd/brcm,bcm590xx.yaml in
  regulator bindings description

Changes in v4:
- Fix yamllint errors (missing unevaluatedProperties)
- Drop comment with regulator name list
- Use full schema paths for $reg
- Change description of regulator binding to mention BCM59054
  explicitly
- Drop quotes around vbus reg name
- Change "Power Management IC" to "Power Management Unit" to match
  official Broadcom naming

Note that I did not end up moving the regulator refs from
allOf compatible matches; I explained my reasoning in [1].

[1] https://lore.kernel.org/lkml/ab853605-859d-44c6-8cbd-44391cd677e6 at gmail.com/

Changes in v3:
- Split regulator node into separate file
- Removed quotes around compatible
---
 .../devicetree/bindings/mfd/brcm,bcm59056.yaml     | 26 +++++++++-
 .../bindings/regulator/brcm,bcm59054.yaml          | 56 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
index b387ef9885c3ac524e0782545dbca9c0e81a556c..b67d7a723fc242869e5bdc6b3602785f62af45bd 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: brcm,bcm59056
+    enum:
+      - brcm,bcm59054
+      - brcm,bcm59056
 
   reg:
     maxItems: 1
@@ -21,7 +23,6 @@ properties:
 
   regulators:
     type: object
-    $ref: /schemas/regulator/brcm,bcm59056.yaml#
 
 required:
   - compatible
@@ -30,6 +31,27 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: brcm,bcm59054
+    then:
+      properties:
+        regulators:
+          $ref: /schemas/regulator/brcm,bcm59054.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: brcm,bcm59056
+    then:
+      properties:
+        regulators:
+          $ref: /schemas/regulator/brcm,bcm59056.yaml#
+
 examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
diff --git a/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml b/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5b46d7fca05e21aa1eae991b5f9f60b444f20c1c
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/brcm,bcm59054.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/brcm,bcm59054.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM59054 Power Management Unit regulators
+
+description: |
+  This is a part of device tree bindings for the BCM59054 power
+  management unit.
+
+  See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
+  additional information and example.
+
+maintainers:
+  - Artur Weber <aweber.kernel at gmail.com>
+
+patternProperties:
+  "^(cam|sim|mmc)ldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(rf|sd|sdx|aud|mic|usb|vib|tcx)ldo$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(c|mm|v)sr$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^(io|sd)sr[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^gpldo[1-3]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+  "^lvldo[1-2]$":
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+properties:
+  vbus:
+    type: object
+    $ref: /schemas/regulator/regulator.yaml#
+    unevaluatedProperties: false
+
+additionalProperties: false

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:51 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:51 +0100
Subject: [PATCH v7 03/10] ARM: dts: Drop DTS for BCM59056 PMU
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-3-4281126be1b8@gmail.com>

The BCM59056 PMU has its own separate DTSI, meant to be included
in a DTS file after defining the pmu node on some I2C bus.

This seems rather unintuitive; drop the DTS in favor of adding the
BCM59056 PMU node directly into the device DTS files.

If the amount of subdevices supported by the BCM590xx grows, and
a common device tree turns out to be beneficial, it can be reintroduced
in the future.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v4:
- PMIC -> PMU in commit message
---
 arch/arm/boot/dts/broadcom/bcm28155-ap.dts | 68 +++++++++++-----------
 arch/arm/boot/dts/broadcom/bcm59056.dtsi   | 91 ------------------------------
 2 files changed, 32 insertions(+), 127 deletions(-)

diff --git a/arch/arm/boot/dts/broadcom/bcm28155-ap.dts b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
index 2f3634545e64978888cd0b47fd5647a5e2eb8e07..cefaa9a3c45c9c90bffc08f739161d8ea21d98dd 100644
--- a/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
+++ b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts
@@ -37,7 +37,39 @@ &pmu_bsc {
 	status = "okay";
 
 	pmu: pmu at 8 {
+		compatible = "brcm,bcm59056";
+		interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
 		reg = <0x08>;
+
+		regulators {
+			camldo1_reg: camldo1 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			sdldo_reg: sdldo {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			sdxldo_reg: sdxldo {
+				regulator-min-microvolt = <2700000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			usbldo_reg: usbldo {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			iosr1_reg: iosr1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
 	};
 };
 
@@ -74,39 +106,3 @@ &usbotg {
 &usbphy {
 	status = "okay";
 };
-
-#include "bcm59056.dtsi"
-
-&pmu {
-	compatible = "brcm,bcm59056";
-	interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
-	regulators {
-		camldo1_reg: camldo1 {
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		sdldo_reg: sdldo {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-		};
-
-		sdxldo_reg: sdxldo {
-			regulator-min-microvolt = <2700000>;
-			regulator-max-microvolt = <3300000>;
-		};
-
-		usbldo_reg: usbldo {
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		iosr1_reg: iosr1 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			regulator-always-on;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/broadcom/bcm59056.dtsi b/arch/arm/boot/dts/broadcom/bcm59056.dtsi
deleted file mode 100644
index a9bb7ad81378d88811c4473763c579d3d2c006a1..0000000000000000000000000000000000000000
--- a/arch/arm/boot/dts/broadcom/bcm59056.dtsi
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
-* Copyright 2014 Linaro Limited
-* Author: Matt Porter <mporter at linaro.org>
-*/
-
-&pmu {
-	compatible = "brcm,bcm59056";
-	regulators {
-		rfldo_reg: rfldo {
-		};
-
-		camldo1_reg: camldo1 {
-		};
-
-		camldo2_reg: camldo2 {
-		};
-
-		simldo1_reg: simldo1 {
-		};
-
-		simldo2_reg: simldo2 {
-		};
-
-		sdldo_reg: sdldo {
-		};
-
-		sdxldo_reg: sdxldo {
-		};
-
-		mmcldo1_reg: mmcldo1 {
-		};
-
-		mmcldo2_reg: mmcldo2 {
-		};
-
-		audldo_reg: audldo {
-		};
-
-		micldo_reg: micldo {
-		};
-
-		usbldo_reg: usbldo {
-		};
-
-		vibldo_reg: vibldo {
-		};
-
-		csr_reg: csr {
-		};
-
-		iosr1_reg: iosr1 {
-		};
-
-		iosr2_reg: iosr2 {
-		};
-
-		msr_reg: msr {
-		};
-
-		sdsr1_reg: sdsr1 {
-		};
-
-		sdsr2_reg: sdsr2 {
-		};
-
-		vsr_reg: vsr {
-		};
-
-		gpldo1_reg: gpldo1 {
-		};
-
-		gpldo2_reg: gpldo2 {
-		};
-
-		gpldo3_reg: gpldo3 {
-		};
-
-		gpldo4_reg: gpldo4 {
-		};
-
-		gpldo5_reg: gpldo5 {
-		};
-
-		gpldo6_reg: gpldo6 {
-		};
-
-		vbus_reg: vbus {
-		};
-	};
-};

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:52 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:52 +0100
Subject: [PATCH v7 04/10] mfd: bcm590xx: Drop unused "id" member of
 bcm590xx MFD struct
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-4-4281126be1b8@gmail.com>

The "id" member of the bcm590xx struct is unused and will be confusing
once we add an actual PMU ID storage value. Drop it; a replacement
will be introduced in a future commit.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Add this commit
---
 include/linux/mfd/bcm590xx.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index 6b8791da6119b22514447bf1572238b71c8b0e97..c614d1b1d8a217ac2f212908a4c19ae71fa56f63 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -23,7 +23,6 @@ struct bcm590xx {
 	struct i2c_client *i2c_sec;
 	struct regmap *regmap_pri;
 	struct regmap *regmap_sec;
-	unsigned int id;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:53 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:53 +0100
Subject: [PATCH v7 05/10] mfd: bcm590xx: Add support for multiple device
 types + BCM59054 compatible
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-5-4281126be1b8@gmail.com>

The BCM59054 is another chip from the BCM590xx line of PMUs, commonly
used on devices with the BCM21664/BCM23550 chipsets.

Prepare the BCM590xx driver for supporting other devices by adding the
PMUID register values for supported chip types and store them in the
MFD data struct as "pmu_id". (These will be checked against the actual
PMUID register values in a later commit.)

Then, add a DT compatible for the BCM59054, and provide the PMU ID as
OF match data.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- Move PMUID value to MFD header
- Use PMUID value as OF data/device type value
- Add bcm59054 to I2C ID table

Changes in v4:
- Rewrite commit message description
- Rename "device_type" member to "dev_type"
- Drop awkward line break to fit function call
- Add PMU ID/revision parsing function

Changes in v3:
- Fix compilation warning about device_type pointer cast type
- Name the device types enum and use it as the type in the MFD struct
---
 drivers/mfd/bcm590xx.c       | 12 +++++++++++-
 include/linux/mfd/bcm590xx.h |  7 +++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 8b56786d85d0182acf91da203b5f943556c08422..4620eed0066fbf1dd691a2e392e967747b4d125b 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -50,6 +50,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 	bcm590xx->dev = &i2c_pri->dev;
 	bcm590xx->i2c_pri = i2c_pri;
 
+	bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);
+
 	bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,
 						 &bcm590xx_regmap_config_pri);
 	if (IS_ERR(bcm590xx->regmap_pri)) {
@@ -91,12 +93,20 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 }
 
 static const struct of_device_id bcm590xx_of_match[] = {
-	{ .compatible = "brcm,bcm59056" },
+	{
+		.compatible = "brcm,bcm59054",
+		.data = (void *)BCM590XX_PMUID_BCM59054,
+	},
+	{
+		.compatible = "brcm,bcm59056",
+		.data = (void *)BCM590XX_PMUID_BCM59056,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
 
 static const struct i2c_device_id bcm590xx_i2c_id[] = {
+	{ "bcm59054" },
 	{ "bcm59056" },
 	{ }
 };
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index c614d1b1d8a217ac2f212908a4c19ae71fa56f63..8d146e3b102a7dbce6f4dbab9f8ae5a9c4e68c0e 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -13,6 +13,10 @@
 #include <linux/i2c.h>
 #include <linux/regmap.h>
 
+/* PMU ID register values; also used as device type */
+#define BCM590XX_PMUID_BCM59054		0x54
+#define BCM590XX_PMUID_BCM59056		0x56
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0
@@ -23,6 +27,9 @@ struct bcm590xx {
 	struct i2c_client *i2c_sec;
 	struct regmap *regmap_pri;
 	struct regmap *regmap_sec;
+
+	/* PMU ID value; also used as device type */
+	u8 pmu_id;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:54 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:54 +0100
Subject: [PATCH v7 06/10] mfd: bcm590xx: Add PMU ID/revision parsing
 function
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-6-4281126be1b8@gmail.com>

The BCM590xx PMUs have two I2C registers for reading the PMU ID
and revision. The revision is useful for subdevice drivers, since
different revisions may have slight differences in behavior (for
example - BCM59054 has different regulator configurations for
revision A0 and A1).

Check the PMU ID register and make sure it matches the DT compatible.
Fetch the digital and analog revision from the PMUREV register
so that it can be used in subdevice drivers.

Also add some known revision values to bcm590xx.h, for convenience
when writing subdevice drivers.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v7:
- Return -ENODEV on PMU ID mismatch
- Drop "Check your DT compatible" from ID mismatch error message

Changes in v6:
- Adapt to PMUID being passed as device type value
- Rename rev_dig and rev_ana to rev_digital and rev_analog
- Rewrite commit message

Changes in v5:
- Add REG_ prefix to register offset constant names

Changes in v4:
- Added this commit
---
 drivers/mfd/bcm590xx.c       | 63 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/bcm590xx.h | 14 ++++++++++
 2 files changed, 77 insertions(+)

diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 4620eed0066fbf1dd691a2e392e967747b4d125b..140107263599777b30cce4cfc0f86a9278907d34 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -17,6 +17,15 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+/* Under primary I2C address: */
+#define BCM590XX_REG_PMUID		0x1e
+
+#define BCM590XX_REG_PMUREV		0x1f
+#define BCM590XX_PMUREV_DIG_MASK	0xF
+#define BCM590XX_PMUREV_DIG_SHIFT	0
+#define BCM590XX_PMUREV_ANA_MASK	0xF0
+#define BCM590XX_PMUREV_ANA_SHIFT	4
+
 static const struct mfd_cell bcm590xx_devs[] = {
 	{
 		.name = "bcm590xx-vregs",
@@ -37,6 +46,56 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+/* Map PMU ID value to model name string */
+static const char * const bcm590xx_names[] = {
+	[BCM590XX_PMUID_BCM59054] = "BCM59054",
+	[BCM590XX_PMUID_BCM59056] = "BCM59056",
+};
+
+/*
+ * Parse the version from version registers and make sure it matches
+ * the device type passed to the compatible.
+ */
+static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)
+{
+	unsigned int id, rev;
+	int ret;
+
+	/* Get PMU ID and verify that it matches compatible */
+	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);
+	if (ret) {
+		dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);
+		return ret;
+	}
+
+	if (id != bcm590xx->pmu_id) {
+		dev_err(bcm590xx->dev,
+			"Incorrect ID for %s: expected %x, got %x.\n",
+			bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);
+		return -ENODEV;
+	}
+
+	/* Get PMU revision and store it in the info struct */
+	ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);
+	if (ret) {
+		dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n",
+			ret);
+		return ret;
+	}
+
+	bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK)
+				     >> BCM590XX_PMUREV_DIG_SHIFT;
+
+	bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK)
+				    >> BCM590XX_PMUREV_ANA_SHIFT;
+
+	dev_info(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",
+		 id, bcm590xx_names[id],
+		 bcm590xx->rev_digital, bcm590xx->rev_analog);
+
+	return 0;
+}
+
 static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 {
 	struct bcm590xx *bcm590xx;
@@ -78,6 +137,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 		goto err;
 	}
 
+	ret = bcm590xx_parse_version(bcm590xx);
+	if (ret)
+		goto err;
+
 	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
 				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
 	if (ret < 0) {
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index 8d146e3b102a7dbce6f4dbab9f8ae5a9c4e68c0e..fbc458e94bef923ca1b69afe2cac944adf6fedf8 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -17,6 +17,16 @@
 #define BCM590XX_PMUID_BCM59054		0x54
 #define BCM590XX_PMUID_BCM59056		0x56
 
+/* Known chip revision IDs */
+#define BCM59054_REV_DIGITAL_A1		1
+#define BCM59054_REV_ANALOG_A1		2
+
+#define BCM59056_REV_DIGITAL_A0		1
+#define BCM59056_REV_ANALOG_A0		1
+
+#define BCM59056_REV_DIGITAL_B0		2
+#define BCM59056_REV_ANALOG_B0		2
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI	0xe7
 #define BCM590XX_MAX_REGISTER_SEC	0xf0
@@ -30,6 +40,10 @@ struct bcm590xx {
 
 	/* PMU ID value; also used as device type */
 	u8 pmu_id;
+
+	/* Chip revision, read from PMUREV reg */
+	u8 rev_digital;
+	u8 rev_analog;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:55 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:55 +0100
Subject: [PATCH v7 07/10] regulator: bcm590xx: Use dev_err_probe for
 regulator register error
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-7-4281126be1b8@gmail.com>

Instead of calling dev_err() and returning PTR_ERR(...) separately, use
a single "return dev_err_probe" statement.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v4:
- Added this commit
---
 drivers/regulator/bcm590xx-regulator.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 9f0cda46b01506080ae5fa709104a8df4d174a8d..a17311fa30e4d48c0a4925778d7bed486ac7a982 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -340,12 +340,10 @@ static int bcm590xx_probe(struct platform_device *pdev)
 
 		rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
 					       &config);
-		if (IS_ERR(rdev)) {
-			dev_err(bcm590xx->dev,
-				"failed to register %s regulator\n",
-				pdev->name);
-			return PTR_ERR(rdev);
-		}
+		if (IS_ERR(rdev))
+			return dev_err_probe(bcm590xx->dev, PTR_ERR(rdev),
+					     "failed to register %s regulator\n",
+					     pdev->name);
 	}
 
 	return 0;

-- 
2.48.1



From aweber.kernel at gmail.com  Sun Mar 16 11:18:58 2025
From: aweber.kernel at gmail.com (Artur Weber)
Date: Sun, 16 Mar 2025 19:18:58 +0100
Subject: [PATCH v7 10/10] regulator: bcm590xx: Add support for BCM59054
 regulators
In-Reply-To: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
References: <20250316-bcm59054-v7-0-4281126be1b8@gmail.com>
Message-ID: <20250316-bcm59054-v7-10-4281126be1b8@gmail.com>

The BCM59056 and BCM59054 are very similar in terms of regulators. Add
the register definitions for the BCM59054 and enable support for it in
the driver.

Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
---
Changes in v6:
- dev_type -> pmu_id conversion, rev_ana -> rev_analog rename

Changes in v5:
- Adapt to regmap type enum being moved/value names being renamed
- Adapt to rename of bcm590xx_reg_info to bcm590xx_reg_data

Changes in v4:
- Lock MICLDO at 1.8v to match vendor kernel behavior
- Set different voltage table for VSR based on PMU revision
- Fix incorrect table being used for LVLDO1
- Add missing newline to "unknown device type" error message

Changes in v3:
- Adapt to regulator info being moved to tables
---
 drivers/regulator/bcm590xx-regulator.c | 649 ++++++++++++++++++++++++++++++++-
 1 file changed, 647 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index f35b2b72e46f70496e16be5244529a5d95d0546d..50414f4cb10958bb33a9fcfa5ed5aaecde9d0715 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -52,6 +52,17 @@ static const struct regulator_ops bcm590xx_ops_ldo = {
 	.map_voltage		= regulator_map_voltage_iterate,
 };
 
+/*
+ * LDO ops without voltage selection, used for MICLDO on BCM59054.
+ * (These are currently the same as VBUS ops, but will be different
+ * in the future once full PMMODE support is implemented.)
+ */
+static const struct regulator_ops bcm590xx_ops_ldo_novolt = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+};
+
 static const struct regulator_ops bcm590xx_ops_dcdc = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
@@ -106,6 +117,13 @@ static const struct regulator_ops bcm590xx_ops_vbus = {
 #define BCM59056_SR_DESC(_name, _name_lower, _ranges)			\
 	BCM590XX_SR_DESC(BCM59056, bcm59056, _name, _name_lower, _ranges)
 
+#define BCM59054_REG_DESC(_name, _name_lower)				\
+	BCM590XX_REG_DESC(BCM59054, _name, _name_lower)
+#define BCM59054_LDO_DESC(_name, _name_lower, _table)			\
+	BCM590XX_LDO_DESC(BCM59054, bcm59054, _name, _name_lower, _table)
+#define BCM59054_SR_DESC(_name, _name_lower, _ranges)			\
+	BCM590XX_SR_DESC(BCM59054, bcm59054, _name, _name_lower, _ranges)
+
 /* BCM59056 data */
 
 /* I2C slave 0 registers */
@@ -466,6 +484,617 @@ static const struct bcm590xx_reg_data bcm59056_regs[BCM59056_NUM_REGS] = {
 	},
 };
 
+/* BCM59054 data */
+
+/* I2C slave 0 registers */
+#define BCM59054_RFLDOPMCTRL1	0x60
+#define BCM59054_CAMLDO1PMCTRL1	0x62
+#define BCM59054_CAMLDO2PMCTRL1	0x64
+#define BCM59054_SIMLDO1PMCTRL1	0x66
+#define BCM59054_SIMLDO2PMCTRL1	0x68
+#define BCM59054_SDLDOPMCTRL1	0x6a
+#define BCM59054_SDXLDOPMCTRL1	0x6c
+#define BCM59054_MMCLDO1PMCTRL1	0x6e
+#define BCM59054_MMCLDO2PMCTRL1	0x70
+#define BCM59054_AUDLDOPMCTRL1	0x72
+#define BCM59054_MICLDOPMCTRL1	0x74
+#define BCM59054_USBLDOPMCTRL1	0x76
+#define BCM59054_VIBLDOPMCTRL1	0x78
+#define BCM59054_IOSR1PMCTRL1	0x7a
+#define BCM59054_IOSR2PMCTRL1	0x7c
+#define BCM59054_CSRPMCTRL1	0x7e
+#define BCM59054_SDSR1PMCTRL1	0x82
+#define BCM59054_SDSR2PMCTRL1	0x86
+#define BCM59054_MMSRPMCTRL1	0x8a
+#define BCM59054_VSRPMCTRL1	0x8e
+#define BCM59054_RFLDOCTRL	0x96
+#define BCM59054_CAMLDO1CTRL	0x97
+#define BCM59054_CAMLDO2CTRL	0x98
+#define BCM59054_SIMLDO1CTRL	0x99
+#define BCM59054_SIMLDO2CTRL	0x9a
+#define BCM59054_SDLDOCTRL	0x9b
+#define BCM59054_SDXLDOCTRL	0x9c
+#define BCM59054_MMCLDO1CTRL	0x9d
+#define BCM59054_MMCLDO2CTRL	0x9e
+#define BCM59054_AUDLDOCTRL	0x9f
+#define BCM59054_MICLDOCTRL	0xa0
+#define BCM59054_USBLDOCTRL	0xa1
+#define BCM59054_VIBLDOCTRL	0xa2
+#define BCM59054_CSRVOUT1	0xc0
+#define BCM59054_IOSR1VOUT1	0xc3
+#define BCM59054_IOSR2VOUT1	0xc6
+#define BCM59054_MMSRVOUT1	0xc9
+#define BCM59054_SDSR1VOUT1	0xcc
+#define BCM59054_SDSR2VOUT1	0xcf
+#define BCM59054_VSRVOUT1	0xd2
+
+/* I2C slave 1 registers */
+#define BCM59054_LVLDO1PMCTRL1	0x16
+#define BCM59054_LVLDO2PMCTRL1	0x18
+#define BCM59054_GPLDO1CTRL	0x1a
+#define BCM59054_GPLDO2CTRL	0x1b
+#define BCM59054_GPLDO3CTRL	0x1c
+#define BCM59054_TCXLDOCTRL	0x1d
+#define BCM59054_LVLDO1CTRL	0x1e
+#define BCM59054_LVLDO2CTRL	0x1f
+#define BCM59054_OTG_CTRL	0x40
+#define BCM59054_GPLDO1PMCTRL1	0x57
+#define BCM59054_GPLDO2PMCTRL1	0x59
+#define BCM59054_GPLDO3PMCTRL1	0x5b
+#define BCM59054_TCXLDOPMCTRL1	0x5d
+
+/*
+ * RFLDO to VSR regulators are
+ * accessed via I2C slave 0
+ */
+
+/* LDO regulator IDs */
+#define BCM59054_REG_RFLDO	0
+#define BCM59054_REG_CAMLDO1	1
+#define BCM59054_REG_CAMLDO2	2
+#define BCM59054_REG_SIMLDO1	3
+#define BCM59054_REG_SIMLDO2	4
+#define BCM59054_REG_SDLDO	5
+#define BCM59054_REG_SDXLDO	6
+#define BCM59054_REG_MMCLDO1	7
+#define BCM59054_REG_MMCLDO2	8
+#define BCM59054_REG_AUDLDO	9
+#define BCM59054_REG_MICLDO	10
+#define BCM59054_REG_USBLDO	11
+#define BCM59054_REG_VIBLDO	12
+
+/* DCDC regulator IDs */
+#define BCM59054_REG_CSR	13
+#define BCM59054_REG_IOSR1	14
+#define BCM59054_REG_IOSR2	15
+#define BCM59054_REG_MMSR	16
+#define BCM59054_REG_SDSR1	17
+#define BCM59054_REG_SDSR2	18
+#define BCM59054_REG_VSR	19
+
+/*
+ * GPLDO1 to VBUS regulators are
+ * accessed via I2C slave 1
+ */
+
+#define BCM59054_REG_GPLDO1	20
+#define BCM59054_REG_GPLDO2	21
+#define BCM59054_REG_GPLDO3	22
+#define BCM59054_REG_TCXLDO	23
+#define BCM59054_REG_LVLDO1	24
+#define BCM59054_REG_LVLDO2	25
+#define BCM59054_REG_VBUS	26
+
+#define BCM59054_NUM_REGS	27
+
+/* LDO group 1: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_1_table[] = {
+	1200000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group 2: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_2_table[] = {
+	3100000, 1800000, 2500000, 2700000, 2800000,
+	2900000, 3000000, 3300000,
+};
+
+/* LDO group 3: supported voltages in microvolts */
+static const unsigned int bcm59054_ldo_3_table[] = {
+	1000000, 1107000, 1143000, 1214000, 1250000,
+	1464000, 1500000, 1786000,
+};
+
+/* DCDC group SR: supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_sr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(0, 0, 1, 0),
+	REGULATOR_LINEAR_RANGE(860000, 2, 60, 10000),
+	REGULATOR_LINEAR_RANGE(1500000, 61, 61, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 62, 62, 0),
+	REGULATOR_LINEAR_RANGE(900000, 63, 63, 0),
+};
+
+/* DCDC group VSR (BCM59054A1): supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_vsr_a1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(0, 0, 1, 0),
+	REGULATOR_LINEAR_RANGE(860000, 2, 59, 10000),
+	REGULATOR_LINEAR_RANGE(1700000, 60, 60, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 61, 61, 0),
+	REGULATOR_LINEAR_RANGE(1800000, 62, 62, 0),
+	REGULATOR_LINEAR_RANGE(1600000, 63, 63, 0),
+};
+
+/* DCDC group CSR: supported voltages in microvolts */
+static const struct linear_range bcm59054_dcdc_csr_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 1, 100000),
+	REGULATOR_LINEAR_RANGE(860000, 2, 60, 10000),
+	REGULATOR_LINEAR_RANGE(900000, 61, 63, 0),
+};
+
+static const struct bcm590xx_reg_data bcm59054_regs[BCM59054_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(RFLDO, rfldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO1, camldo1, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO2, camldo2, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO1, simldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO2, simldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDLDO, sdldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDXLDO, sdxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO1, mmcldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO2, mmcldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(AUDLDO, audldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_REG_DESC(MICLDO, micldo),
+			.ops = &bcm590xx_ops_ldo_novolt,
+			/* MICLDO is locked at 1.8V */
+			.n_voltages = 1,
+			.fixed_uV = 1800000,
+			.enable_reg = BCM59054_MICLDOPMCTRL1,
+			.enable_mask = BCM590XX_REG_ENABLE,
+			.enable_is_inverted = true,
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(USBLDO, usbldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(VIBLDO, vibldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR1, iosr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR2, iosr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(MMSR, mmsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR1, sdsr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR2, sdsr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(VSR, vsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO1, gpldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO2, gpldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO3, gpldo3, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(TCXLDO, tcxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO1, lvldo1, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO2, lvldo2, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM59054_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
+/*
+ * BCM59054A1 regulators; same as previous revision, but with different
+ * VSR voltage table.
+ */
+static const struct bcm590xx_reg_data bcm59054_a1_regs[BCM59054_NUM_REGS] = {
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(RFLDO, rfldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO1, camldo1, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(CAMLDO2, camldo2, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO1, simldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SIMLDO2, simldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDLDO, sdldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(SDXLDO, sdxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO1, mmcldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(MMCLDO2, mmcldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(AUDLDO, audldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_REG_DESC(MICLDO, micldo),
+			.ops = &bcm590xx_ops_ldo_novolt,
+			/* MICLDO is locked at 1.8V */
+			.n_voltages = 1,
+			.fixed_uV = 1800000,
+			.enable_reg = BCM59054_MICLDOPMCTRL1,
+			.enable_mask = BCM590XX_REG_ENABLE,
+			.enable_is_inverted = true,
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(USBLDO, usbldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_LDO,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_LDO_DESC(VIBLDO, vibldo, ldo_2_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(CSR, csr, dcdc_csr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR1, iosr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(IOSR2, iosr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(MMSR, mmsr, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR1, sdsr1, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(SDSR2, sdsr2, dcdc_sr_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_SR,
+		.regmap = BCM590XX_REGMAP_PRI,
+		.desc = {
+			BCM59054_SR_DESC(VSR, vsr, dcdc_vsr_a1_ranges),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO1, gpldo1, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO2, gpldo2, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(GPLDO3, gpldo3, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(TCXLDO, tcxldo, ldo_1_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO1, lvldo1, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_GPLDO,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_LDO_DESC(LVLDO2, lvldo2, ldo_3_table),
+		},
+	},
+
+	{
+		.type = BCM590XX_REG_TYPE_VBUS,
+		.regmap = BCM590XX_REGMAP_SEC,
+		.desc = {
+			BCM59054_REG_DESC(VBUS, vbus),
+			.ops = &bcm590xx_ops_vbus,
+			.n_voltages = 1,
+			.fixed_uV = 5000000,
+			.enable_reg = BCM59054_OTG_CTRL,
+			.enable_mask = BCM590XX_VBUS_ENABLE,
+		},
+	},
+};
+
 static int bcm590xx_probe(struct platform_device *pdev)
 {
 	struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
@@ -480,8 +1109,24 @@ static int bcm590xx_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	pmu->mfd = bcm590xx;
-	pmu->n_regulators = BCM59056_NUM_REGS;
-	pmu->regs = bcm59056_regs;
+
+	switch (pmu->mfd->pmu_id) {
+	case BCM590XX_PMUID_BCM59054:
+		pmu->n_regulators = BCM59054_NUM_REGS;
+		if (pmu->mfd->rev_analog == BCM59054_REV_ANALOG_A1)
+			pmu->regs = bcm59054_a1_regs;
+		else
+			pmu->regs = bcm59054_regs;
+		break;
+	case BCM590XX_PMUID_BCM59056:
+		pmu->n_regulators = BCM59056_NUM_REGS;
+		pmu->regs = bcm59056_regs;
+		break;
+	default:
+		dev_err(bcm590xx->dev,
+			"unknown device type, could not initialize\n");
+		return -EINVAL;
+	}
 
 	platform_set_drvdata(pdev, pmu);
 

-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:36 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:36 +0100
Subject: [PATCH v5 6/7] arm64: Add SOPHGO SOC family Kconfig support
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-7-alexander.sverdlin@gmail.com>

First user will be Aarch64 core within SG2000 SoC.

Reviewed-by: Chen Wang <unicorn_wang at outlook.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
v3:
v2:
- shortened the help message (mirrored from RiscV ARCH now);
- select ARCH_HAS_RESET_CONTROLLER instead of RESET_CONTROLLER;
- moved CLK_SOPHGO_CV1800 selection into defconfig;

 arch/arm64/Kconfig.platforms | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 8b76821f190f..af74bcc3c861 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -307,6 +307,12 @@ config ARCH_INTEL_SOCFPGA
 	  Stratix 10 (ex. Altera), Stratix10 Software Virtual Platform,
 	  Agilex and eASIC N5X.
 
+config ARCH_SOPHGO
+	bool "Sophgo SoCs"
+	select ARCH_HAS_RESET_CONTROLLER
+	help
+	  This enables support for Sophgo SoC platform hardware.
+
 config ARCH_STM32
 	bool "STMicroelectronics STM32 SoC Family"
 	select GPIOLIB
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:37 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:37 +0100
Subject: [PATCH v5 7/7] arm64: defconfig: Enable rudimentary Sophgo SG2000 support
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-8-alexander.sverdlin@gmail.com>

Enable ARCH_SOPHGO, pinctrl (built-in, required to boot), ADC as module.
This defconfig is able to boot from SD card on Milk-V Duo Module 01
evalboard.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
v3:
v2:
- moved CLK_SOPHGO_CV1800 from Kconfig.platforms here;

 arch/arm64/configs/defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index bde1287ad9a7..9c01f5333f0f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -66,6 +66,7 @@ CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_INTEL_SOCFPGA=y
+CONFIG_ARCH_SOPHGO=y
 CONFIG_ARCH_STM32=y
 CONFIG_ARCH_SYNQUACER=y
 CONFIG_ARCH_TEGRA=y
@@ -652,6 +653,7 @@ CONFIG_PINCTRL_SM8450_LPASS_LPI=m
 CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
 CONFIG_PINCTRL_SM8550_LPASS_LPI=m
 CONFIG_PINCTRL_SM8650_LPASS_LPI=m
+CONFIG_PINCTRL_SOPHGO_SG2000=y
 CONFIG_GPIO_ALTERA=m
 CONFIG_GPIO_DAVINCI=y
 CONFIG_GPIO_DWAPB=y
@@ -1409,6 +1411,7 @@ CONFIG_QCOM_HFPLL=y
 CONFIG_CLK_GFM_LPASS_SM8250=m
 CONFIG_CLK_RCAR_USB2_CLOCK_SEL=y
 CONFIG_CLK_RENESAS_VBATTB=m
+CONFIG_CLK_SOPHGO_CV1800=y
 CONFIG_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_TEGRA186_TIMER=y
@@ -1528,6 +1531,7 @@ CONFIG_QCOM_SPMI_VADC=m
 CONFIG_QCOM_SPMI_ADC5=m
 CONFIG_ROCKCHIP_SARADC=m
 CONFIG_RZG2L_ADC=m
+CONFIG_SOPHGO_CV1800B_ADC=m
 CONFIG_TI_ADS1015=m
 CONFIG_TI_AM335X_ADC=m
 CONFIG_IIO_CROS_EC_SENSORS_CORE=m
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:30 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:30 +0100
Subject: [PATCH v5 0/7] arm64 support for Milk-V Duo Module 01 EVB
Message-ID: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>

This series adds very basic support for Milk-V Duo Module 01 EVB [1] in
arm64 mode. The SoC (SG2000) is dual-arch, RiscV and ARM64, the latter has
been chosen because the upstream toolchain can be utilized.

Sophgo SG2000 seems to be a continuation of the Cvitek CV18xx series, same
peripherals with an addition of ARM64 core. Therefore it would be
beneficial not to copy-paste the peripherals' device-tree, but rather split
the most suitable riscv DT into ARCH-specific and peripherals parts and
just include the latter on the arm64 side.

This series adds the device-tree for Milk-V Duo Module 01 EVB, which
in turn contains Milk-V Duo Module 01 (separate .dtsi) on it, which has
SG2000 SoC inside (separate .dtsi).

This series has been tested with Sophgo-provided U-Boot binary [2]: it
boots from SD card; pinctrl, serial, GPIO drivers are functional (same
as for RiscV-based CV18xx SoCs).

Partial SoC documentation is available [3].

This series lacks the support of:
- USB
- Audio
- Ethernet
- WiFi
- Bluetooth
- eMMC
- Video

Changelog:
v5:
- PSCI node in DT
v4:
- minimized patch 1/7 (cleanups dropped)
- cv18xx-cpu-intc.dtsi instead of cv18xx-cpu.dtsi+cv18xx-intc.dtsi in
patch 1/7
v3:
- &cpus node has been moved into cv18xx-cpu.dtsi, &plic and &clint nodes
were moved into cv18xx-intc.dtsi to reduce code duplication;
v2:
- dropped all patches related to the new reboot driver and corresponding DT
and bindings;
- grouped DT-related and config-related patches together;
- added patch moving sophgo.yaml from riscv into soc (to share it with
ARM); added SG2000 SoC and Milk-V Duo Module 01 EVB into it;
- other changes are documented in the corresponding patches;

[1] https://milkv.io/docs/duo/getting-started/duo-module-01
[2] https://github.com/milkv-duo/duo-buildroot-sdk-v2/releases/
[3] https://github.com/sophgo/sophgo-doc/releases/download/sg2000-trm-v1.01/sg2000_trm_en.pdf

Alexander Sverdlin (7):
  riscv: dts: sophgo: cv18xx: Move RiscV-specific part into SoCs' .dtsi
    files
  dt-bindings: soc: sophgo: Move SoCs/boards from riscv into soc, add
    SG2000
  arm64: dts: sophgo: Add initial SG2000 SoC device tree
  arm64: dts: sophgo: Add Duo Module 01
  arm64: dts: sophgo: Add Duo Module 01 Evaluation Board
  arm64: Add SOPHGO SOC family Kconfig support
  arm64: defconfig: Enable rudimentary Sophgo SG2000 support

 .../{riscv => soc/sophgo}/sophgo.yaml         |  7 +-
 arch/arm64/Kconfig.platforms                  |  6 ++
 arch/arm64/boot/dts/Makefile                  |  1 +
 arch/arm64/boot/dts/sophgo/Makefile           |  2 +
 .../sophgo/sg2000-milkv-duo-module-01-evb.dts | 31 +++++++
 .../sophgo/sg2000-milkv-duo-module-01.dtsi    | 85 +++++++++++++++++
 arch/arm64/boot/dts/sophgo/sg2000.dtsi        | 81 +++++++++++++++++
 arch/arm64/configs/defconfig                  |  4 +
 arch/riscv/boot/dts/sophgo/cv1800b.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv1812h.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv181x.dtsi        |  2 +-
 .../boot/dts/sophgo/cv18xx-cpu-intc.dtsi      | 54 +++++++++++
 arch/riscv/boot/dts/sophgo/cv18xx.dtsi        | 91 +++++--------------
 arch/riscv/boot/dts/sophgo/sg2002.dtsi        |  5 +
 14 files changed, 309 insertions(+), 70 deletions(-)
 rename Documentation/devicetree/bindings/{riscv => soc/sophgo}/sophgo.yaml (80%)
 create mode 100644 arch/arm64/boot/dts/sophgo/Makefile
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000.dtsi
 create mode 100644 arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi

-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:31 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:31 +0100
Subject: [PATCH v5 1/7] riscv: dts: sophgo: cv18xx: Move RiscV-specific part into SoCs' .dtsi files
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-2-alexander.sverdlin@gmail.com>

Make the peripheral device tree re-usable on ARM64 platform by moving CPU
core and interrupt controllers' parts into new cv18xx-cpu.dtsi and
cv18xx-intc.dtsi.

Add SOC_PERIPHERAL_IRQ() macro which explicitly maps peripheral nubering
into "plic" interrupt-controller numbering.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
- cleanups dropped
- cv18xx-cpu-intc.dtsi instead of cv18xx-cpu.dtsi+cv18xx-intc.dtsi
v3:
- &cpus node has been moved into cv18xx-cpu.dtsi, &plic and &clint nodes
were moved into cv18xx-intc.dtsi to reduce code duplication;
v2:
- instead of carving out peripherals' part, carve out ARCH-specifics (CPU
core, interrupt controllers) and spread them among 3 SoC .dtsi files which
included cv18xx.dtsi;
- define a label for the "soc" node and use it in the newly introduced DTs;

 arch/riscv/boot/dts/sophgo/cv1800b.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv1812h.dtsi       |  5 +
 arch/riscv/boot/dts/sophgo/cv181x.dtsi        |  2 +-
 .../boot/dts/sophgo/cv18xx-cpu-intc.dtsi      | 54 +++++++++++
 arch/riscv/boot/dts/sophgo/cv18xx.dtsi        | 91 +++++--------------
 arch/riscv/boot/dts/sophgo/sg2002.dtsi        |  5 +
 6 files changed, 93 insertions(+), 69 deletions(-)
 create mode 100644 arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi

diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
index aa1f5df100f0..e5494f0f1f45 100644
--- a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
@@ -3,8 +3,11 @@
  * Copyright (C) 2023 Jisheng Zhang <jszhang at kernel.org>
  */
 
+#define SOC_PERIPHERAL_IRQ(nr)	((nr) + 16)
+
 #include <dt-bindings/pinctrl/pinctrl-cv1800b.h>
 #include "cv18xx.dtsi"
+#include "cv18xx-cpu-intc.dtsi"
 
 / {
 	compatible = "sophgo,cv1800b";
@@ -15,6 +18,8 @@ memory at 80000000 {
 	};
 
 	soc {
+		dma-noncoherent;
+
 		pinctrl: pinctrl at 3001000 {
 			compatible = "sophgo,cv1800b-pinctrl";
 			reg = <0x03001000 0x1000>,
diff --git a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
index 8a1b95c5116b..96e1a2f14d3e 100644
--- a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
@@ -3,9 +3,12 @@
  * Copyright (C) 2023 Inochi Amaoto <inochiama at outlook.com>
  */
 
+#define SOC_PERIPHERAL_IRQ(nr)	((nr) + 16)
+
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/pinctrl-cv1812h.h>
 #include "cv18xx.dtsi"
+#include "cv18xx-cpu-intc.dtsi"
 #include "cv181x.dtsi"
 
 / {
@@ -17,6 +20,8 @@ memory at 80000000 {
 	};
 
 	soc {
+		dma-noncoherent;
+
 		pinctrl: pinctrl at 3001000 {
 			compatible = "sophgo,cv1812h-pinctrl";
 			reg = <0x03001000 0x1000>,
diff --git a/arch/riscv/boot/dts/sophgo/cv181x.dtsi b/arch/riscv/boot/dts/sophgo/cv181x.dtsi
index 5fd14dd1b14f..bbdb30653e9a 100644
--- a/arch/riscv/boot/dts/sophgo/cv181x.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv181x.dtsi
@@ -11,7 +11,7 @@ soc {
 		emmc: mmc at 4300000 {
 			compatible = "sophgo,cv1800b-dwcmshc";
 			reg = <0x4300000 0x1000>;
-			interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(18) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_AXI4_EMMC>,
 				 <&clk CLK_EMMC>;
 			clock-names = "core", "bus";
diff --git a/arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi
new file mode 100644
index 000000000000..5e5d163e79d4
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 Jisheng Zhang <jszhang at kernel.org>
+ * Copyright (C) 2023 Inochi Amaoto <inochiama at outlook.com>
+ */
+
+/ {
+	cpus: cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		timebase-frequency = <25000000>;
+
+		cpu0: cpu at 0 {
+			compatible = "thead,c906", "riscv";
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <512>;
+			d-cache-size = <65536>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <128>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			riscv,isa = "rv64imafdc";
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu0_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+};
+
+&soc {
+	interrupt-parent = <&plic>;
+
+	plic: interrupt-controller at 70000000 {
+		reg = <0x70000000 0x4000000>;
+		interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
+		interrupt-controller;
+		#address-cells = <0>;
+		#interrupt-cells = <2>;
+		riscv,ndev = <101>;
+	};
+
+	clint: timer at 74000000 {
+		reg = <0x74000000 0x10000>;
+		interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+	};
+};
diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
index c18822ec849f..62c1464a0490 100644
--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
@@ -12,47 +12,16 @@ / {
 	#address-cells = <1>;
 	#size-cells = <1>;
 
-	cpus: cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		timebase-frequency = <25000000>;
-
-		cpu0: cpu at 0 {
-			compatible = "thead,c906", "riscv";
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-block-size = <64>;
-			d-cache-sets = <512>;
-			d-cache-size = <65536>;
-			i-cache-block-size = <64>;
-			i-cache-sets = <128>;
-			i-cache-size = <32768>;
-			mmu-type = "riscv,sv39";
-			riscv,isa = "rv64imafdc";
-			riscv,isa-base = "rv64i";
-			riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
-					       "zifencei", "zihpm";
-
-			cpu0_intc: interrupt-controller {
-				compatible = "riscv,cpu-intc";
-				interrupt-controller;
-				#interrupt-cells = <1>;
-			};
-		};
-	};
-
 	osc: oscillator {
 		compatible = "fixed-clock";
 		clock-output-names = "osc_25m";
 		#clock-cells = <0>;
 	};
 
-	soc {
+	soc: soc {
 		compatible = "simple-bus";
-		interrupt-parent = <&plic>;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		dma-noncoherent;
 		ranges;
 
 		clk: clock-controller at 3002000 {
@@ -75,7 +44,7 @@ porta: gpio-controller at 0 {
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <SOC_PERIPHERAL_IRQ(44) IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -93,7 +62,7 @@ portb: gpio-controller at 0 {
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupts = <61 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <SOC_PERIPHERAL_IRQ(45) IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -111,7 +80,7 @@ portc: gpio-controller at 0 {
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -129,7 +98,7 @@ portd: gpio-controller at 0 {
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupts = <63 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <SOC_PERIPHERAL_IRQ(47) IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -137,7 +106,7 @@ saradc: adc at 30f0000 {
 			compatible = "sophgo,cv1800b-saradc";
 			reg = <0x030f0000 0x1000>;
 			clocks = <&clk CLK_SARADC>;
-			interrupts = <100 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(84) IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			status = "disabled";
@@ -162,7 +131,7 @@ i2c0: i2c at 4000000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>, <&clk CLK_APB_I2C0>;
 			clock-names = "ref", "pclk";
-			interrupts = <49 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -173,7 +142,7 @@ i2c1: i2c at 4010000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>, <&clk CLK_APB_I2C1>;
 			clock-names = "ref", "pclk";
-			interrupts = <50 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -184,7 +153,7 @@ i2c2: i2c at 4020000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>, <&clk CLK_APB_I2C2>;
 			clock-names = "ref", "pclk";
-			interrupts = <51 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(35) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -195,7 +164,7 @@ i2c3: i2c at 4030000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>, <&clk CLK_APB_I2C3>;
 			clock-names = "ref", "pclk";
-			interrupts = <52 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(36) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -206,14 +175,14 @@ i2c4: i2c at 4040000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_I2C>, <&clk CLK_APB_I2C4>;
 			clock-names = "ref", "pclk";
-			interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(37) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
 		uart0: serial at 4140000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x04140000 0x100>;
-			interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_UART0>, <&clk CLK_APB_UART0>;
 			clock-names = "baudclk", "apb_pclk";
 			reg-shift = <2>;
@@ -224,7 +193,7 @@ uart0: serial at 4140000 {
 		uart1: serial at 4150000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x04150000 0x100>;
-			interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_UART1>, <&clk CLK_APB_UART1>;
 			clock-names = "baudclk", "apb_pclk";
 			reg-shift = <2>;
@@ -235,7 +204,7 @@ uart1: serial at 4150000 {
 		uart2: serial at 4160000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x04160000 0x100>;
-			interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_UART2>, <&clk CLK_APB_UART2>;
 			clock-names = "baudclk", "apb_pclk";
 			reg-shift = <2>;
@@ -246,7 +215,7 @@ uart2: serial at 4160000 {
 		uart3: serial at 4170000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x04170000 0x100>;
-			interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_UART3>, <&clk CLK_APB_UART3>;
 			clock-names = "baudclk", "apb_pclk";
 			reg-shift = <2>;
@@ -261,7 +230,7 @@ spi0: spi at 4180000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_SPI>, <&clk CLK_APB_SPI0>;
 			clock-names = "ssi_clk", "pclk";
-			interrupts = <54 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(38) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -272,7 +241,7 @@ spi1: spi at 4190000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_SPI>, <&clk CLK_APB_SPI1>;
 			clock-names = "ssi_clk", "pclk";
-			interrupts = <55 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(39) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -283,7 +252,7 @@ spi2: spi at 41a0000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_SPI>, <&clk CLK_APB_SPI2>;
 			clock-names = "ssi_clk", "pclk";
-			interrupts = <56 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -294,14 +263,14 @@ spi3: spi at 41b0000 {
 			#size-cells = <0>;
 			clocks = <&clk CLK_SPI>, <&clk CLK_APB_SPI3>;
 			clock-names = "ssi_clk", "pclk";
-			interrupts = <57 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
 		uart4: serial at 41c0000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x041c0000 0x100>;
-			interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(32) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>;
 			clock-names = "baudclk", "apb_pclk";
 			reg-shift = <2>;
@@ -312,7 +281,7 @@ uart4: serial at 41c0000 {
 		sdhci0: mmc at 4310000 {
 			compatible = "sophgo,cv1800b-dwcmshc";
 			reg = <0x4310000 0x1000>;
-			interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(20) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_AXI4_SD0>,
 				 <&clk CLK_SD0>;
 			clock-names = "core", "bus";
@@ -322,7 +291,7 @@ sdhci0: mmc at 4310000 {
 		sdhci1: mmc at 4320000 {
 			compatible = "sophgo,cv1800b-dwcmshc";
 			reg = <0x4320000 0x1000>;
-			interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(22) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_AXI4_SD1>,
 				 <&clk CLK_SD1>;
 			clock-names = "core", "bus";
@@ -332,7 +301,7 @@ sdhci1: mmc at 4320000 {
 		dmac: dma-controller at 4330000 {
 			compatible = "snps,axi-dma-1.01a";
 			reg = <0x04330000 0x1000>;
-			interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <SOC_PERIPHERAL_IRQ(13) IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk CLK_SDMA_AXI>, <&clk CLK_SDMA_AXI>;
 			clock-names = "core-clk", "cfgr-clk";
 			#dma-cells = <1>;
@@ -344,19 +313,5 @@ dmac: dma-controller at 4330000 {
 			snps,data-width = <4>;
 			status = "disabled";
 		};
-
-		plic: interrupt-controller at 70000000 {
-			reg = <0x70000000 0x4000000>;
-			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			riscv,ndev = <101>;
-		};
-
-		clint: timer at 74000000 {
-			reg = <0x74000000 0x10000>;
-			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
-		};
 	};
 };
diff --git a/arch/riscv/boot/dts/sophgo/sg2002.dtsi b/arch/riscv/boot/dts/sophgo/sg2002.dtsi
index 7f79de33163c..a0cb8080dfa5 100644
--- a/arch/riscv/boot/dts/sophgo/sg2002.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2002.dtsi
@@ -3,9 +3,12 @@
  * Copyright (C) 2024 Thomas Bonnefille <thomas.bonnefille at bootlin.com>
  */
 
+#define SOC_PERIPHERAL_IRQ(nr)	((nr) + 16)
+
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/pinctrl-sg2002.h>
 #include "cv18xx.dtsi"
+#include "cv18xx-cpu-intc.dtsi"
 #include "cv181x.dtsi"
 
 / {
@@ -17,6 +20,8 @@ memory at 80000000 {
 	};
 
 	soc {
+		dma-noncoherent;
+
 		pinctrl: pinctrl at 3001000 {
 			compatible = "sophgo,sg2002-pinctrl";
 			reg = <0x03001000 0x1000>,
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:32 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:32 +0100
Subject: [PATCH v5 2/7] dt-bindings: soc: sophgo: Move SoCs/boards from riscv into soc, add SG2000
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-3-alexander.sverdlin@gmail.com>

Move sophgo.yaml from riscv into soc/sophgo so that it can be shared for
all SoCs containing ARM cores as well. This already applies to SG2002.

Add SG2000 SoC, Milk-V Duo Module 01 and Milk-V Module 01 EVB.

Reviewed-by: Chen Wang <unicorn_wang at outlook.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
v3:
v2:
- patch introduced

 .../devicetree/bindings/{riscv => soc/sophgo}/sophgo.yaml  | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
 rename Documentation/devicetree/bindings/{riscv => soc/sophgo}/sophgo.yaml (80%)

diff --git a/Documentation/devicetree/bindings/riscv/sophgo.yaml b/Documentation/devicetree/bindings/soc/sophgo/sophgo.yaml
similarity index 80%
rename from Documentation/devicetree/bindings/riscv/sophgo.yaml
rename to Documentation/devicetree/bindings/soc/sophgo/sophgo.yaml
index a14cb10ff3f0..5d73d0ccc547 100644
--- a/Documentation/devicetree/bindings/riscv/sophgo.yaml
+++ b/Documentation/devicetree/bindings/soc/sophgo/sophgo.yaml
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/riscv/sophgo.yaml#
+$id: http://devicetree.org/schemas/soc/sophgo/sophgo.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Sophgo SoC-based boards
@@ -26,6 +26,11 @@ properties:
           - enum:
               - sophgo,huashan-pi
           - const: sophgo,cv1812h
+      - items:
+          - enum:
+              - milkv,duo-module-01-evb
+          - const: milkv,duo-module-01
+          - const: sophgo,sg2000
       - items:
           - enum:
               - sipeed,licheerv-nano-b
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:33 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:33 +0100
Subject: [PATCH v5 3/7] arm64: dts: sophgo: Add initial SG2000 SoC device tree
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-4-alexander.sverdlin@gmail.com>

Add initial device tree for the SG2000 SoC by SOPHGO (from ARM64 PoV).

Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
- PSCI node and enable-method
v4:
v3:
v2:
- relocated "memory" node according to DT coding style;
- moved GIC node into "soc";
- referring "soc" by label;

 arch/arm64/boot/dts/sophgo/sg2000.dtsi | 81 ++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000.dtsi

diff --git a/arch/arm64/boot/dts/sophgo/sg2000.dtsi b/arch/arm64/boot/dts/sophgo/sg2000.dtsi
new file mode 100644
index 000000000000..7051007ec7ea
--- /dev/null
+++ b/arch/arm64/boot/dts/sophgo/sg2000.dtsi
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+#define SOC_PERIPHERAL_IRQ(nr)		GIC_SPI (nr)
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <riscv/sophgo/cv18xx.dtsi>
+#include <riscv/sophgo/cv181x.dtsi>
+
+/ {
+	compatible = "sophgo,sg2000";
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			next-level-cache = <&l2>;
+		};
+
+		l2: l2-cache {
+			compatible = "cache";
+			cache-level = <2>;
+			cache-unified;
+			cache-size = <0x20000>;
+		};
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512MiB */
+	};
+
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2", "arm,psci";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+		always-on;
+		clock-frequency = <25000000>;
+	};
+};
+
+&soc {
+	gic: interrupt-controller at 1f01000 {
+		compatible = "arm,cortex-a15-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x01f01000 0x1000>,
+		      <0x01f02000 0x2000>;
+	};
+
+	pinctrl: pinctrl at 3001000 {
+		compatible = "sophgo,sg2000-pinctrl";
+		reg = <0x03001000 0x1000>,
+		      <0x05027000 0x1000>;
+		reg-names = "sys", "rtc";
+	};
+};
+
+&clk {
+	compatible = "sophgo,sg2000-clk";
+};
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:34 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:34 +0100
Subject: [PATCH v5 4/7] arm64: dts: sophgo: Add Duo Module 01
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-5-alexander.sverdlin@gmail.com>

The Duo Module 01 is a compact module with integrated SG2000,
WI-FI6/BTDM5.4, and eMMC.
Add only support for UART and SDHCI.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
v3:
v2:
- sorted all nodes according to DT coding style;
- added "compatible" property;
- renamed the new .dtsi not to use underscores;
- added status = "okay" instead of deleting it;

 .../sophgo/sg2000-milkv-duo-module-01.dtsi    | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi

diff --git a/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi b/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi
new file mode 100644
index 000000000000..bb52cdad990a
--- /dev/null
+++ b/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+#include <dt-bindings/pinctrl/pinctrl-sg2000.h>
+#include "sg2000.dtsi"
+
+/ {
+	model = "Milk-V Duo Module 01";
+	compatible = "milkv,duo-module-01", "sophgo,sg2000";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+};
+
+&osc {
+	clock-frequency = <25000000>;
+};
+
+&pinctrl {
+	sdhci0_cfg: sdhci0-cfg {
+		sdhci0-cd-pins {
+			pinmux = <PINMUX(PIN_SD0_CD, 0)>;
+			bias-pull-up;
+			drive-strength-microamp = <10800>;
+			power-source = <3300>;
+		};
+
+		sdhci0-clk-pins {
+			pinmux = <PINMUX(PIN_SD0_CLK, 0)>;
+			bias-pull-up;
+			drive-strength-microamp = <16100>;
+			power-source = <3300>;
+		};
+
+		sdhci0-cmd-pins {
+			pinmux = <PINMUX(PIN_SD0_CMD, 0)>;
+			bias-pull-up;
+			drive-strength-microamp = <10800>;
+			power-source = <3300>;
+		};
+
+		sdhci0-data-pins {
+			pinmux = <PINMUX(PIN_SD0_D0, 0)>,
+				 <PINMUX(PIN_SD0_D1, 0)>,
+				 <PINMUX(PIN_SD0_D2, 0)>,
+				 <PINMUX(PIN_SD0_D3, 0)>;
+			bias-pull-up;
+			drive-strength-microamp = <10800>;
+			power-source = <3300>;
+		};
+	};
+
+	uart0_cfg: uart0-cfg {
+		uart0-pins {
+			pinmux = <PINMUX(PIN_UART0_TX, 0)>,
+				 <PINMUX(PIN_UART0_RX, 0)>;
+			bias-pull-up;
+			drive-strength-microamp = <10800>;
+			power-source = <3300>;
+		};
+	};
+};
+
+&emmc {
+	bus-width = <4>;
+	no-1-8-v;
+	cap-mmc-hw-reset;
+	no-sd;
+	no-sdio;
+	non-removable;
+	status = "okay";
+};
+
+/* Wi-Fi */
+&sdhci1 {
+	bus-width = <4>;
+	cap-sdio-irq;
+	no-mmc;
+	no-sd;
+	non-removable;
+};
-- 
2.48.1



From alexander.sverdlin at gmail.com  Sun Mar 16 11:56:35 2025
From: alexander.sverdlin at gmail.com (Alexander Sverdlin)
Date: Sun, 16 Mar 2025 19:56:35 +0100
Subject: [PATCH v5 5/7] arm64: dts: sophgo: Add Duo Module 01 Evaluation Board
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <20250316185640.3750873-6-alexander.sverdlin@gmail.com>

Duo Module 01 Evaluation Board contains Sophgo Duo Module 01
SMD SoM, Ethernet+USB switch, microSD slot, etc...
Add only support for UART0 (console) and microSD slot.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin at gmail.com>
---
Changelog:
v5:
v4:
v3:
v2:
- sorted all nodes according to DT coding style;
- added "compatible" property;
- renamed the new .dts not to use underscores;
- added status = "okay" instead of deleting it;

 arch/arm64/boot/dts/Makefile                  |  1 +
 arch/arm64/boot/dts/sophgo/Makefile           |  2 ++
 .../sophgo/sg2000-milkv-duo-module-01-evb.dts | 31 +++++++++++++++++++
 3 files changed, 34 insertions(+)
 create mode 100644 arch/arm64/boot/dts/sophgo/Makefile
 create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 79b73a21ddc2..3a32b157ac8c 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -28,6 +28,7 @@ subdir-y += realtek
 subdir-y += renesas
 subdir-y += rockchip
 subdir-y += socionext
+subdir-y += sophgo
 subdir-y += sprd
 subdir-y += st
 subdir-y += synaptics
diff --git a/arch/arm64/boot/dts/sophgo/Makefile b/arch/arm64/boot/dts/sophgo/Makefile
new file mode 100644
index 000000000000..94f52cd7d994
--- /dev/null
+++ b/arch/arm64/boot/dts/sophgo/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SOPHGO) += sg2000-milkv-duo-module-01-evb.dtb
diff --git a/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts b/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts
new file mode 100644
index 000000000000..b1f8a5787861
--- /dev/null
+++ b/arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/dts-v1/;
+
+#include "sg2000-milkv-duo-module-01.dtsi"
+
+/ {
+	model = "Milk-V Duo Module 01 Evaluation Board";
+	compatible = "milkv,duo-module-01-evb", "milkv,duo-module-01", "sophgo,sg2000";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	pinctrl-0 = <&uart0_cfg>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	no-1-8-v;
+	no-mmc;
+	no-sdio;
+	disable-wp;
+	pinctrl-0 = <&sdhci0_cfg>;
+	pinctrl-names = "default";
+	status = "okay";
+};
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar 16 12:18:58 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 16 Mar 2025 19:18:58 +0000
Subject: [PATCH] nvmem: rockchip-otp: Handle internal word_size in main reg_read op
Message-ID: <20250316191900.1858944-1-jonas@kwiboo.se>

Rockchip SoCs RK3576 and RK3588 read data from the OTP using 32-bit
words instead of normal 8-bit bytes. Similar RK3506, RK3528, RK3562 and
RK3568 will read data from OTP using 16-bit words.

The nvmem core stride and word_size cannot fully be used as cells is not
always aligned. Continue to report a stride=1 and word_size=1 in
nvmem_config and instead handle use of SoC specific word_size internally
in the driver.

Move current SoC specific word_size handling from the RK3588 read_reg
operation to the main read_reg operation to help simplify the SoC
specific read_reg operation and allow code reuse in a future RK3568
reg_read operation.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
This closely matches how I refactored the Rockchip eFUSE and OTP driver
in mainline U-Boot to handle word/block reads back in 2023, see [1].

[1] http://lore.kernel.org/r/20230222224436.1570224-3-jonas at kwiboo.se/
---
 drivers/nvmem/rockchip-otp.c | 72 ++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 32 deletions(-)

diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index d88f12c53242..45bbb6147fb7 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -59,7 +59,6 @@
 #define RK3588_OTPC_AUTO_EN		0x08
 #define RK3588_OTPC_INT_ST		0x84
 #define RK3588_OTPC_DOUT0		0x20
-#define RK3588_NBYTES			4
 #define RK3588_BURST_NUM		1
 #define RK3588_BURST_SHIFT		8
 #define RK3588_ADDR_SHIFT		16
@@ -69,6 +68,7 @@
 struct rockchip_data {
 	int size;
 	int read_offset;
+	int word_size;
 	const char * const *clks;
 	int num_clks;
 	nvmem_reg_read_t reg_read;
@@ -185,48 +185,28 @@ static int px30_otp_read(void *context, unsigned int offset,
 }
 
 static int rk3588_otp_read(void *context, unsigned int offset,
-			   void *val, size_t bytes)
+			   void *val, size_t count)
 {
 	struct rockchip_otp *otp = context;
-	unsigned int addr_start, addr_end, addr_len;
-	int ret, i = 0;
-	u32 data;
-	u8 *buf;
-
-	addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
-	addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
-	addr_len = addr_end - addr_start;
-	addr_start += otp->data->read_offset / RK3588_NBYTES;
-
-	buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+	u32 *buf = val;
+	int ret;
 
-	while (addr_len--) {
-		writel((addr_start << RK3588_ADDR_SHIFT) |
+	while (count--) {
+		writel((offset++ << RK3588_ADDR_SHIFT) |
 		       (RK3588_BURST_NUM << RK3588_BURST_SHIFT),
 		       otp->base + RK3588_OTPC_AUTO_CTRL);
 		writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
 
 		ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
 					       RK3588_RD_DONE);
-		if (ret < 0) {
+		if (ret) {
 			dev_err(otp->dev, "timeout during read setup\n");
-			goto read_end;
+			return ret;
 		}
 
-		data = readl(otp->base + RK3588_OTPC_DOUT0);
-		memcpy(&buf[i], &data, RK3588_NBYTES);
-
-		i += RK3588_NBYTES;
-		addr_start++;
+		*buf++ = readl(otp->base + RK3588_OTPC_DOUT0);
 	}
 
-	memcpy(val, buf + offset % RK3588_NBYTES, bytes);
-
-read_end:
-	kfree(buf);
-
 	return ret;
 }
 
@@ -234,7 +214,7 @@ static int rockchip_otp_read(void *context, unsigned int offset,
 			     void *val, size_t bytes)
 {
 	struct rockchip_otp *otp = context;
-	int ret;
+	int ret, word_size;
 
 	if (!otp->data || !otp->data->reg_read)
 		return -EINVAL;
@@ -245,8 +225,34 @@ static int rockchip_otp_read(void *context, unsigned int offset,
 		return ret;
 	}
 
-	ret = otp->data->reg_read(context, offset, val, bytes);
+	offset += otp->data->read_offset;
+	word_size = otp->data->word_size;
+
+	if (word_size > 1) {
+		unsigned int addr_start, addr_end;
+		size_t count;
+		u8 *buf;
+
+		addr_start = offset / word_size;
+		addr_end = DIV_ROUND_UP(offset + bytes, word_size);
+		count = addr_end - addr_start;
+
+		buf = kzalloc(array_size(count, word_size), GFP_KERNEL);
+		if (!buf) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		ret = otp->data->reg_read(context, addr_start, buf, count);
+		if (!ret)
+			memcpy(val, buf + (offset % word_size), bytes);
+
+		kfree(buf);
+	} else {
+		ret = otp->data->reg_read(context, offset, val, bytes);
+	}
 
+err:
 	clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
 
 	return ret;
@@ -259,7 +265,7 @@ static struct nvmem_config otp_config = {
 	.type = NVMEM_TYPE_OTP,
 	.read_only = true,
 	.stride = 1,
-	.word_size = 1,
+	.word_size = sizeof(u8),
 	.reg_read = rockchip_otp_read,
 };
 
@@ -277,6 +283,7 @@ static const struct rockchip_data px30_data = {
 static const struct rockchip_data rk3576_data = {
 	.size = 0x100,
 	.read_offset = 0x700,
+	.word_size = sizeof(u32),
 	.clks = px30_otp_clocks,
 	.num_clks = ARRAY_SIZE(px30_otp_clocks),
 	.reg_read = rk3588_otp_read,
@@ -289,6 +296,7 @@ static const char * const rk3588_otp_clocks[] = {
 static const struct rockchip_data rk3588_data = {
 	.size = 0x400,
 	.read_offset = 0xc00,
+	.word_size = sizeof(u32),
 	.clks = rk3588_otp_clocks,
 	.num_clks = ARRAY_SIZE(rk3588_otp_clocks),
 	.reg_read = rk3588_otp_read,
-- 
2.48.1



From jonas at kwiboo.se  Sun Mar 16 14:25:53 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 16 Mar 2025 22:25:53 +0100
Subject: [PATCH v2 3/3] nvmem: rockchip-otp: Add support for rk3562
In-Reply-To: <20250227110804.2342976-3-kever.yang@rock-chips.com>
References: <20250227110804.2342976-1-kever.yang@rock-chips.com>
 <20250227110804.2342976-3-kever.yang@rock-chips.com>
Message-ID: <7e5ff689-c013-47c2-982b-e7f4c1d233ca@kwiboo.se>

Hi Kever,

On 2025-02-27 12:08, Kever Yang wrote:
> From: Finley Xiao <finley.xiao at rock-chips.com>
> 
> This adds the necessary data for handling otp on the rk3562.
> 
> Signed-off-by: Finley Xiao <finley.xiao at rock-chips.com>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  drivers/nvmem/rockchip-otp.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
> index a04bce89ecc8..6f86cf8ec390 100644
> --- a/drivers/nvmem/rockchip-otp.c
> +++ b/drivers/nvmem/rockchip-otp.c
> @@ -341,6 +341,17 @@ static const struct rockchip_data px30_data = {
>  	.reg_read = px30_otp_read,
>  };
>  
> +static const char * const rk3562_otp_clocks[] = {
> +	"usr", "sbpi", "apb_pclk", "phy",
> +};

These are the same clocks as used for rk3568 below.

> +
> +static const struct rockchip_data rk3562_data = {
> +	.size = 0x80,
> +	.clks = rk3562_otp_clocks,
> +	.num_clks = ARRAY_SIZE(rk3562_otp_clocks),
> +	.reg_read = rk3568_otp_read,
> +};
> +
>  static const char * const rk3568_otp_clocks[] = {
>  	"usr", "sbpi", "apb_pclk", "phy",
>  };
> @@ -372,6 +383,10 @@ static const struct of_device_id rockchip_otp_match[] = {
>  		.compatible = "rockchip,rk3308-otp",
>  		.data = &px30_data,
>  	},
> +	{
> +		.compatible = "rockchip,rk3562-otp",
> +		.data = &rk3562_data,

Here we can use rk3568_data directly without having to add a new
rk3562_data struct.

Regards,
Jonas

> +	},
>  	{
>  		.compatible = "rockchip,rk3568-otp",
>  		.data = &rk3568_data,



From jonas at kwiboo.se  Sun Mar 16 14:52:07 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 16 Mar 2025 22:52:07 +0100
Subject: [PATCH v2 2/3] nvmem: rockchip-otp: Add support for rk3568-otp
In-Reply-To: <20250227110804.2342976-2-kever.yang@rock-chips.com>
References: <20250227110804.2342976-1-kever.yang@rock-chips.com>
 <20250227110804.2342976-2-kever.yang@rock-chips.com>
Message-ID: <8c697031-9978-40cd-a1e0-f40552db9107@kwiboo.se>

Hi Kever,

On 2025-02-27 12:08, Kever Yang wrote:
> From: Finley Xiao <finley.xiao at rock-chips.com>
> 
> This adds the necessary data for handling efuse on the rk3568.
> 
> Signed-off-by: Finley Xiao <finley.xiao at rock-chips.com>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  drivers/nvmem/rockchip-otp.c | 82 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 82 insertions(+)
> 
> diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
> index ebc3f0b24166..a04bce89ecc8 100644
> --- a/drivers/nvmem/rockchip-otp.c
> +++ b/drivers/nvmem/rockchip-otp.c
> @@ -27,6 +27,7 @@
>  #define OTPC_USER_CTRL			0x0100
>  #define OTPC_USER_ADDR			0x0104
>  #define OTPC_USER_ENABLE		0x0108
> +#define OTPC_USER_QP			0x0120
>  #define OTPC_USER_Q			0x0124
>  #define OTPC_INT_STATUS			0x0304
>  #define OTPC_SBPI_CMD0_OFFSET		0x1000
> @@ -53,6 +54,8 @@
>  #define SBPI_ENABLE_MASK		GENMASK(16, 16)
>  
>  #define OTPC_TIMEOUT			10000
> +#define OTPC_TIMEOUT_PROG		100000

This is not used anywhere in this patch, please drop it.

> +#define RK3568_NBYTES			2
>  
>  /* RK3588 Register */
>  #define RK3588_OTPC_AUTO_CTRL		0x04
> @@ -184,6 +187,70 @@ static int px30_otp_read(void *context, unsigned int offset,
>  	return ret;
>  }
>  
> +static int rk3568_otp_read(void *context, unsigned int offset, void *val,
> +			   size_t bytes)
> +{
> +	struct rockchip_otp *otp = context;
> +	unsigned int addr_start, addr_end, addr_offset, addr_len;
> +	unsigned int otp_qp;
> +	u32 out_value;
> +	u8 *buf;
> +	int ret = 0, i = 0;
> +
> +	addr_start = rounddown(offset, RK3568_NBYTES) / RK3568_NBYTES;
> +	addr_end = roundup(offset + bytes, RK3568_NBYTES) / RK3568_NBYTES;
> +	addr_offset = offset % RK3568_NBYTES;
> +	addr_len = addr_end - addr_start;
> +
> +	buf = kzalloc(array3_size(addr_len, RK3568_NBYTES, sizeof(*buf)),
> +		      GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	ret = rockchip_otp_reset(otp);
> +	if (ret) {
> +		dev_err(otp->dev, "failed to reset otp phy\n");
> +		return ret;

This is leaking the kzalloc memory above.

> +	}
> +
> +	ret = rockchip_otp_ecc_enable(otp, true);
> +	if (ret < 0) {
> +		dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
> +		return ret;

Same here.

> +	}
> +
> +	writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
> +	udelay(5);
> +	while (addr_len--) {
> +		writel(addr_start++ | OTPC_USER_ADDR_MASK,
> +		       otp->base + OTPC_USER_ADDR);
> +		writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
> +		       otp->base + OTPC_USER_ENABLE);
> +		ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE);
> +		if (ret < 0) {
> +			dev_err(otp->dev, "timeout during read setup\n");
> +			goto read_end;
> +		}
> +		otp_qp = readl(otp->base + OTPC_USER_QP);
> +		if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) {
> +			ret = -EIO;
> +			dev_err(otp->dev, "ecc check error during read setup\n");
> +			goto read_end;
> +		}
> +		out_value = readl(otp->base + OTPC_USER_Q);
> +		memcpy(&buf[i], &out_value, RK3568_NBYTES);
> +		i += RK3568_NBYTES;
> +	}
> +
> +	memcpy(val, buf + addr_offset, bytes);
> +
> +read_end:
> +	writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
> +	kfree(buf);
> +
> +	return ret;
> +}

This can be simplified if this is rebased on top of "nvmem: rockchip-otp:
Handle internal word_size in main reg_read op" [1].

[1] https://lore.kernel.org/r/20250316191900.1858944-1-jonas at kwiboo.se

Something like following could be squashed in with this:

diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index ea48d51bc2ff..0991a4047bec 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -54,8 +54,6 @@
 #define SBPI_ENABLE_MASK		GENMASK(16, 16)
 
 #define OTPC_TIMEOUT			10000
-#define OTPC_TIMEOUT_PROG		100000
-#define RK3568_NBYTES			2
 
 /* RK3588 Register */
 #define RK3588_OTPC_AUTO_CTRL		0x04
@@ -188,24 +186,12 @@ static int px30_otp_read(void *context, unsigned int offset,
 }
 
 static int rk3568_otp_read(void *context, unsigned int offset, void *val,
-			   size_t bytes)
+			   size_t count)
 {
 	struct rockchip_otp *otp = context;
-	unsigned int addr_start, addr_end, addr_offset, addr_len;
-	unsigned int otp_qp;
-	u32 out_value;
-	u8 *buf;
-	int ret = 0, i = 0;
-
-	addr_start = rounddown(offset, RK3568_NBYTES) / RK3568_NBYTES;
-	addr_end = roundup(offset + bytes, RK3568_NBYTES) / RK3568_NBYTES;
-	addr_offset = offset % RK3568_NBYTES;
-	addr_len = addr_end - addr_start;
-
-	buf = kzalloc(array3_size(addr_len, RK3568_NBYTES, sizeof(*buf)),
-		      GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+	u16 *buf = val;
+	u32 otp_qp;
+	int ret;
 
 	ret = rockchip_otp_reset(otp);
 	if (ret) {
@@ -214,39 +200,39 @@ static int rk3568_otp_read(void *context, unsigned int offset, void *val,
 	}
 
 	ret = rockchip_otp_ecc_enable(otp, true);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
 		return ret;
 	}
 
 	writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
 	udelay(5);
-	while (addr_len--) {
-		writel(addr_start++ | OTPC_USER_ADDR_MASK,
+
+	while (count--) {
+		writel(offset++ | OTPC_USER_ADDR_MASK,
 		       otp->base + OTPC_USER_ADDR);
 		writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
 		       otp->base + OTPC_USER_ENABLE);
-		ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE);
-		if (ret < 0) {
+
+		ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS,
+					       OTPC_USER_DONE);
+		if (ret) {
 			dev_err(otp->dev, "timeout during read setup\n");
 			goto read_end;
 		}
+
 		otp_qp = readl(otp->base + OTPC_USER_QP);
 		if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) {
 			ret = -EIO;
 			dev_err(otp->dev, "ecc check error during read setup\n");
 			goto read_end;
 		}
-		out_value = readl(otp->base + OTPC_USER_Q);
-		memcpy(&buf[i], &out_value, RK3568_NBYTES);
-		i += RK3568_NBYTES;
-	}
 
-	memcpy(val, buf + addr_offset, bytes);
+		*buf++ = readl(otp->base + OTPC_USER_Q);
+	}
 
 read_end:
 	writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
-	kfree(buf);
 
 	return ret;
 }

> +
>  static int rk3588_otp_read(void *context, unsigned int offset,
>  			   void *val, size_t bytes)
>  {
> @@ -274,6 +341,17 @@ static const struct rockchip_data px30_data = {
>  	.reg_read = px30_otp_read,
>  };
>  
> +static const char * const rk3568_otp_clocks[] = {
> +	"usr", "sbpi", "apb_pclk", "phy",

Why do we change from using the "otp"-name for the main clock?

I suggest we keep the main clock named "otp" instead of "usr" for
consistency.

> +};
> +
> +static const struct rockchip_data rk3568_data = {
> +	.size = 0x80,

If this is rebased on top of [1] you should also add:

	.word_size = sizeof(u16),

Above suggested changes can also be found in a FIXUP commit at my
linux-rockchip tree of pending RK3528 patches [2].

[2] https://github.com/Kwiboo/linux-rockchip/commits/next-20250314-rk3528/

Regards,
Jonas

> +	.clks = rk3568_otp_clocks,
> +	.num_clks = ARRAY_SIZE(rk3568_otp_clocks),
> +	.reg_read = rk3568_otp_read,
> +};
> +
>  static const char * const rk3588_otp_clocks[] = {
>  	"otp", "apb_pclk", "phy", "arb",
>  };
> @@ -294,6 +372,10 @@ static const struct of_device_id rockchip_otp_match[] = {
>  		.compatible = "rockchip,rk3308-otp",
>  		.data = &px30_data,
>  	},
> +	{
> +		.compatible = "rockchip,rk3568-otp",
> +		.data = &rk3568_data,
> +	},
>  	{
>  		.compatible = "rockchip,rk3588-otp",
>  		.data = &rk3588_data,



From sfr at canb.auug.org.au  Sun Mar 16 16:26:51 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Mon, 17 Mar 2025 10:26:51 +1100
Subject: linux-next: duplicate patch in the drivers-memory-fixes tree
Message-ID: <20250317102651.37c64e42@canb.auug.org.au>

Hi all,

The following commit is also in the arm-soc-fixes tree as a different
commit (but the same patch):

  304e6c02b76f ("memory: omap-gpmc: drop no compatible check")

This is commit

  edcccc6892f6 ("memory: omap-gpmc: drop no compatible check")

in the arm-soc-fixes tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/4db5125f/attachment.sig>

From jonas at kwiboo.se  Sun Mar 16 17:00:42 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 17 Mar 2025 01:00:42 +0100
Subject: [PATCH v2 1/3] dt-bindings: nvmem: rockchip,otp: Add support for
 rk3562 and rk3568
In-Reply-To: <20250227110804.2342976-1-kever.yang@rock-chips.com>
References: <20250227110804.2342976-1-kever.yang@rock-chips.com>
Message-ID: <05ddd536-cf14-4ae0-b092-51a0c536f16e@kwiboo.se>

Hi Kever,

On 2025-02-27 12:08, Kever Yang wrote:
> Add compatible entry for the otp controller in rk3562 and rk3568, add schema
> for different clock names for new entry.
> 
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
> 
> Changes in v2:
> - Update the commit message and add maxItems in schema.
> 
>  .../bindings/nvmem/rockchip,otp.yaml          | 53 ++++++++++++++++---
>  1 file changed, 46 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> index a44d44b32809..7572f4a1d73b 100644
> --- a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> +++ b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
> @@ -14,6 +14,8 @@ properties:
>      enum:
>        - rockchip,px30-otp
>        - rockchip,rk3308-otp
> +      - rockchip,rk3562-otp
> +      - rockchip,rk3568-otp
>        - rockchip,rk3588-otp
>  
>    reg:
> @@ -25,19 +27,15 @@ properties:
>  
>    clock-names:
>      minItems: 3
> -    items:
> -      - const: otp
> -      - const: apb_pclk
> -      - const: phy
> -      - const: arb
> +    maxItems: 4
>  
>    resets:
>      minItems: 1
> -    maxItems: 3
> +    maxItems: 4
>  
>    reset-names:
>      minItems: 1
> -    maxItems: 3
> +    maxItems: 4

For clock-names above and reset-names we could possible skip the
min/max-items, e.g. something like:

  clock-names: true
  reset-names: true

and then only keep the items prop in the different conditions below.

>  
>  required:
>    - compatible
> @@ -62,12 +60,45 @@ allOf:
>        properties:
>          clocks:
>            maxItems: 3
> +        clock-names:
> +          items:
> +            - const: otp
> +            - const: apb_pclk
> +            - const: phy
>          resets:
>            maxItems: 1
>          reset-names:
>            items:
>              - const: phy
>  
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - rockchip,rk3562-otp
> +              - rockchip,rk3568-otp
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 4
> +          maxItems: 4
> +        clock-names:
> +          items:
> +            - const: usr

Why do we not use the name "otp" here ? For px30 and rk3308 the clock is
named clk_otp_usr and we still use the "otp" name.

> +            - const: sbpi
> +            - const: apb_pclk
> +            - const: phy
> +        resets:
> +          minItems: 4
> +          maxItems: 4
> +        reset-names:
> +          items:
> +            - const: usr

Same here.

This needs to be rebased to also include rk3576 clock-names.

I prepared a FIXUP commit at [1] with the suggested changes, feel free
to squash any changes you agree with in a v3.

I am planing to send out a OTP series for RK3528, and that will depend
on next revision of this series :-)

[1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250314-rk3528/

Regards,
Jonas

> +            - const: sbpi
> +            - const: apb
> +            - const: phy
> +
>    - if:
>        properties:
>          compatible:
> @@ -78,8 +109,16 @@ allOf:
>        properties:
>          clocks:
>            minItems: 4
> +          maxItems: 4
> +        clock-names:
> +          items:
> +            - const: otp
> +            - const: apb_pclk
> +            - const: phy
> +            - const: arb
>          resets:
>            minItems: 3
> +          maxItems: 3
>          reset-names:
>            items:
>              - const: otp



From quic_jiegan at quicinc.com  Sun Mar 16 18:07:08 2025
From: quic_jiegan at quicinc.com (Jie Gan)
Date: Mon, 17 Mar 2025 09:07:08 +0800
Subject: [PATCH next] Coresight: Fix a NULL vs IS_ERR() bug in probe
In-Reply-To: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
References: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
Message-ID: <f4d4a369-427b-4fb3-9d49-84f2a0f45aff@quicinc.com>



On 3/14/2025 6:55 PM, Dan Carpenter wrote:
> The devm_platform_get_and_ioremap_resource() function doesn't
> return NULL, it returns error pointers.  Update the checking to
> match.
> 
> Fixes: f78d206f3d73 ("Coresight: Add Coresight TMC Control Unit driver")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
>   drivers/hwtracing/coresight/coresight-ctcu-core.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> index da35d8b4d579..c6bafc96db96 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> @@ -204,8 +204,8 @@ static int ctcu_probe(struct platform_device *pdev)
>   	dev->platform_data = pdata;
>   
>   	base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
> -	if (!base)
> -		return -ENOMEM;
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
>   
>   	drvdata->apb_clk = coresight_get_enable_apb_pclk(dev);
>   	if (IS_ERR(drvdata->apb_clk))

Thanks for fix it. Looks good to me.

Reviewed-by: Jie Gan <quic_jiegan at quicinc.com>

Jie



From peter.chen at cixtech.com  Sun Mar 16 18:38:23 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 17 Mar 2025 09:38:23 +0800
Subject: [PATCH v4 0/6] arm64: Introduce CIX P1 (SKY1) SoC
In-Reply-To: <Z8-LpRCQfsVfDYtm@nchen-desktop>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <Z8-LpRCQfsVfDYtm@nchen-desktop>
Message-ID: <Z9d9D2X8V5A8Na3e@nchen-desktop>

On 25-03-11 09:02:29, Peter Chen wrote:
> On 25-03-05 13:38:17, Peter Chen wrote:
> > Cixtech P1 (internal name sky1) is high performance generic Armv9 SoC.
> > Orion O6 is the world's first open source Arm V9 Motherboard built by
> > Radxa. You could find brief introduction for SoC and related boards at:
> > https://radxa.com/products/orion/o6#overview
> > 
> > In this series, we add initial SoC and board support for Kernel building.
> > Patch 1-2: Add dt-binding doc for CIX and its sky1 SoC
> > Patch 3: add related maintainers entry
> > Patch 4-5: add Arm64 build support
> > Patch 6: add initial dts support for SoC and Orion O6 board
> > 
> > To run upstream kernel at Orion O6 board, you need to use BIOS
> > released by Radxa:
> > https://docs.radxa.com/en/orion/o6/bios/install-bios
> > 
> > Changes for v4:
> > - Move add MAINTAINERS entry patch to the last, and add two dts files entry in it. 
> > - Add three Krzysztof Kozlowski's Reviewed-by Tags
> > - For sky1.dtsi, makes below changes:
> > 	- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
> > 	get its handle
> > 	- Remove gic-v3's #redistributor-regions and redistributor-stride properties
> > 	- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
> > 	- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
> > 	- Remove timer's clock frequency due to firmware has already set it
> 
> Hi Arnd,
> 
> I assume this series (all patches) will go your tree, right?
> 

A gentle ping, thanks.

Peter

> Peter
> 
> > 
> > Changes for v3:
> > - Patch 1: Add Krzysztof Kozlowski's Acked-by Tag
> > - Patch 2: Add Krzysztof Kozlowski's Reviewed-by Tag
> > - Patch 6: Fix two dts coding sytle issues
> > 
> > Changes for v2:
> > - Pass dts build check with below commands:
> > make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=vendor-prefixes.yaml
> > make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=arm/cix.yaml
> > make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
> > - Re-order the patch set, and move vendor-perfixes to the 1st patch.
> > - Patch 4: Ordered Kconfig config entry by alpha-numerically
> > - Patch 5: Corrects the Ack tag's name
> > - Patch 6: see below.
> > 1) Corrects the SoF tag's name
> > 2) Fix several coding sytle issues
> > 3) move linux,cma node to dts file
> > 4) delete memory node, memory size is passed by firmware
> > 5) delete uart2 node which will be added in future patches
> > 6) Improve for pmu and cpu node to stands for more specific cpu model
> > 7) Improve the timer node and add hypervisor virtual timer irq
> > 
> > Fugang Duan (1):
> >   arm64: Kconfig: add ARCH_CIX for cix silicons
> > 
> > Peter Chen (5):
> >   dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
> >   dt-bindings: arm: add CIX P1 (SKY1) SoC
> >   arm64: defconfig: Enable CIX SoC
> >   arm64: dts: cix: add initial CIX P1(SKY1) dts support
> >   MAINTAINERS: Add CIX SoC maintainer entry
> > 
> >  .../devicetree/bindings/arm/cix.yaml          |  26 ++
> >  .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
> >  MAINTAINERS                                   |  10 +
> >  arch/arm64/Kconfig.platforms                  |   6 +
> >  arch/arm64/boot/dts/Makefile                  |   1 +
> >  arch/arm64/boot/dts/cix/Makefile              |   2 +
> >  arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |  26 ++
> >  arch/arm64/boot/dts/cix/sky1.dtsi             | 222 ++++++++++++++++++
> >  arch/arm64/configs/defconfig                  |   1 +
> >  9 files changed, 296 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml
> >  create mode 100644 arch/arm64/boot/dts/cix/Makefile
> >  create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> >  create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi
> > 
> > -- 
> > 2.25.1
> > 
> 
> -- 
> 
> Best regards,
> Peter

-- 

Best regards,
Peter


From peter.chen at kernel.org  Sun Mar 16 18:53:52 2025
From: peter.chen at kernel.org (Peter Chen (CIX))
Date: Mon, 17 Mar 2025 09:53:52 +0800
Subject: [PATCH v2 1/3] usb: chipidea: ci_hdrc_imx: fix usbmisc handling
In-Reply-To: <20250316102658.490340-2-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
 <20250316102658.490340-2-pchelkin@ispras.ru>
Message-ID: <20250317015352.GA218167@nchen-desktop>

On 25-03-16 13:26:54, Fedor Pchelkin wrote:
> usbmisc is an optional device property so it is totally valid for the
> corresponding data->usbmisc_data to have a NULL value.
> 
> Check that before dereferencing the pointer.
> 
> Found by Linux Verification Center (linuxtesting.org) with Svace static
> analysis tool.
> 
> Fixes: 74adad500346 ("usb: chipidea: ci_hdrc_imx: decrement device's refcount in .remove() and in the error path of .probe()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>

Acked-by: Peter Chen <peter.chen at kernel.org>

Peter
> ---
>  drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index 1a7fc638213e..619779eef333 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -534,7 +534,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  		cpu_latency_qos_remove_request(&data->pm_qos_req);
>  	data->ci_pdev = NULL;
>  err_put:
> -	put_device(data->usbmisc_data->dev);
> +	if (data->usbmisc_data)
> +		put_device(data->usbmisc_data->dev);
>  	return ret;
>  }
>  
> @@ -559,7 +560,8 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
>  		if (data->hsic_pad_regulator)
>  			regulator_disable(data->hsic_pad_regulator);
>  	}
> -	put_device(data->usbmisc_data->dev);
> +	if (data->usbmisc_data)
> +		put_device(data->usbmisc_data->dev);
>  }
>  
>  static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
> -- 
> 2.48.1
> 

-- 

Best regards,
Peter


From peter.chen at kernel.org  Sun Mar 16 18:54:37 2025
From: peter.chen at kernel.org (Peter Chen (CIX))
Date: Mon, 17 Mar 2025 09:54:37 +0800
Subject: [PATCH v2 2/3] usb: chipidea: ci_hdrc_imx: fix call balance of
 regulator routines
In-Reply-To: <20250316102658.490340-3-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
 <20250316102658.490340-3-pchelkin@ispras.ru>
Message-ID: <20250317015437.GB218167@nchen-desktop>

On 25-03-16 13:26:55, Fedor Pchelkin wrote:
> Upon encountering errors during the HSIC pinctrl handling section the
> regulator should be disabled.
> 
> Use devm_add_action_or_reset() to let the regulator-disabling routine be
> handled by device resource management stack.
> 
> Found by Linux Verification Center (linuxtesting.org).
> 
> Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional")
> Cc: stable at vger.kernel.org
> Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>

Acked-by: Peter Chen <peter.chen at kernel.org>


> ---
> v2: simplify the patch taking advantage of devm-helper (Frank Li)
> 
> It looks like devm_regulator_get_enable_optional() exists for this very
> use case utilized in the driver but it's not present in old supported
> stable kernels and I may say those dependency-patches wouldn't apply there
> cleanly. So fix the problem first, further code simplification is a
> subject to cleanup patch.
> 
>  drivers/usb/chipidea/ci_hdrc_imx.c | 25 +++++++++++++++++--------
>  1 file changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index 619779eef333..d942b3c72640 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -336,6 +336,13 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
>  	return ret;
>  }
>  
> +static void ci_hdrc_imx_disable_regulator(void *arg)
> +{
> +	struct ci_hdrc_imx_data *data = arg;
> +
> +	regulator_disable(data->hsic_pad_regulator);
> +}
> +
>  static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  {
>  	struct ci_hdrc_imx_data *data;
> @@ -394,6 +401,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  					"Failed to enable HSIC pad regulator\n");
>  				goto err_put;
>  			}
> +			ret = devm_add_action_or_reset(dev,
> +					ci_hdrc_imx_disable_regulator, data);
> +			if (ret) {
> +				dev_err(dev,
> +					"Failed to add regulator devm action\n");
> +				goto err_put;
> +			}
>  		}
>  	}
>  
> @@ -432,11 +446,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  
>  	ret = imx_get_clks(dev);
>  	if (ret)
> -		goto disable_hsic_regulator;
> +		goto qos_remove_request;
>  
>  	ret = imx_prepare_enable_clks(dev);
>  	if (ret)
> -		goto disable_hsic_regulator;
> +		goto qos_remove_request;
>  
>  	ret = clk_prepare_enable(data->clk_wakeup);
>  	if (ret)
> @@ -526,10 +540,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  	clk_disable_unprepare(data->clk_wakeup);
>  err_wakeup_clk:
>  	imx_disable_unprepare_clks(dev);
> -disable_hsic_regulator:
> -	if (data->hsic_pad_regulator)
> -		/* don't overwrite original ret (cf. EPROBE_DEFER) */
> -		regulator_disable(data->hsic_pad_regulator);
> +qos_remove_request:
>  	if (pdata.flags & CI_HDRC_PMQOS)
>  		cpu_latency_qos_remove_request(&data->pm_qos_req);
>  	data->ci_pdev = NULL;
> @@ -557,8 +568,6 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
>  		clk_disable_unprepare(data->clk_wakeup);
>  		if (data->plat_data->flags & CI_HDRC_PMQOS)
>  			cpu_latency_qos_remove_request(&data->pm_qos_req);
> -		if (data->hsic_pad_regulator)
> -			regulator_disable(data->hsic_pad_regulator);
>  	}
>  	if (data->usbmisc_data)
>  		put_device(data->usbmisc_data->dev);
> -- 
> 2.48.1
> 

-- 

Best regards,
Peter


From peter.chen at kernel.org  Sun Mar 16 18:56:01 2025
From: peter.chen at kernel.org (Peter Chen (CIX))
Date: Mon, 17 Mar 2025 09:56:01 +0800
Subject: [PATCH v2 3/3] usb: chipidea: ci_hdrc_imx: implement
 usb_phy_init() error handling
In-Reply-To: <20250316102658.490340-4-pchelkin@ispras.ru>
References: <20250316102658.490340-1-pchelkin@ispras.ru>
 <20250316102658.490340-4-pchelkin@ispras.ru>
Message-ID: <20250317015601.GC218167@nchen-desktop>

On 25-03-16 13:26:56, Fedor Pchelkin wrote:
> usb_phy_init() may return an error code if e.g. its implementation fails
> to prepare/enable some clocks. And properly rollback on probe error path
> by calling the counterpart usb_phy_shutdown().
> 
> Found by Linux Verification Center (linuxtesting.org).
> 
> Fixes: be9cae2479f4 ("usb: chipidea: imx: Fix ULPI on imx53")
> Cc: stable at vger.kernel.org
> Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>

Acked-by: Peter Chen <peter.chen at kernel.org>

> ---
>  drivers/usb/chipidea/ci_hdrc_imx.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index d942b3c72640..4f8bfd242b59 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -484,7 +484,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  	    of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
>  		pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
>  		data->override_phy_control = true;
> -		usb_phy_init(pdata.usb_phy);
> +		ret = usb_phy_init(pdata.usb_phy);
> +		if (ret) {
> +			dev_err(dev, "Failed to init phy\n");
> +			goto err_clk;
> +		}
>  	}
>  
>  	if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
> @@ -493,7 +497,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  	ret = imx_usbmisc_init(data->usbmisc_data);
>  	if (ret) {
>  		dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
> -		goto err_clk;
> +		goto phy_shutdown;
>  	}
>  
>  	data->ci_pdev = ci_hdrc_add_device(dev,
> @@ -502,7 +506,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  	if (IS_ERR(data->ci_pdev)) {
>  		ret = PTR_ERR(data->ci_pdev);
>  		dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
> -		goto err_clk;
> +		goto phy_shutdown;
>  	}
>  
>  	if (data->usbmisc_data) {
> @@ -536,6 +540,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>  
>  disable_device:
>  	ci_hdrc_remove_device(data->ci_pdev);
> +phy_shutdown:
> +	if (data->override_phy_control)
> +		usb_phy_shutdown(data->phy);
>  err_clk:
>  	clk_disable_unprepare(data->clk_wakeup);
>  err_wakeup_clk:
> -- 
> 2.48.1
> 

-- 

Best regards,
Peter


From anshuman.khandual at arm.com  Sun Mar 16 19:13:33 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 17 Mar 2025 07:43:33 +0530
Subject: [PATCH next] Coresight: Fix a NULL vs IS_ERR() bug in probe
In-Reply-To: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
References: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
Message-ID: <a636ce0d-a5cf-4718-9d39-1a6e74bdea5f@arm.com>



On 3/14/25 16:25, Dan Carpenter wrote:
> The devm_platform_get_and_ioremap_resource() function doesn't
> return NULL, it returns error pointers.  Update the checking to
> match.
> 
> Fixes: f78d206f3d73 ("Coresight: Add Coresight TMC Control Unit driver")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-ctcu-core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> index da35d8b4d579..c6bafc96db96 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> @@ -204,8 +204,8 @@ static int ctcu_probe(struct platform_device *pdev)
>  	dev->platform_data = pdata;
>  
>  	base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
> -	if (!base)
> -		return -ENOMEM;
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
>  
>  	drvdata->apb_clk = coresight_get_enable_apb_pclk(dev);
>  	if (IS_ERR(drvdata->apb_clk))

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>


From Crystal.Guo at mediatek.com  Sun Mar 16 19:30:45 2025
From: Crystal.Guo at mediatek.com (=?utf-8?B?Q3J5c3RhbCBHdW8gKOmDreaZtik=?=)
Date: Mon, 17 Mar 2025 02:30:45 +0000
Subject: [v2,1/2] memory/mediatek: Add an interface to get current DDR
 data rate
In-Reply-To: <10163a0b-5865-4088-b38b-6c5680548fc4@collabora.com>
References: <20250207014437.17920-1-crystal.guo@mediatek.com>
	 <20250207014437.17920-2-crystal.guo@mediatek.com>
	 <10163a0b-5865-4088-b38b-6c5680548fc4@collabora.com>
Message-ID: <c8c1acb3651ba2d06db17d4d7ee9ad50786c5fcb.camel@mediatek.com>

On Tue, 2025-03-04 at 15:59 +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 07/02/25 02:42, Crystal Guo ha scritto:
> > Add MediaTek DRAMC driver to provide an interface that can
> > obtain current DDR data rate.
> > 
> > Reported-by: kernel test robot <lkp at intel.com>
> > Closes: 
> > https://lore.kernel.org/oe-kbuild-all/202412210955.FvO0Pee3-lkp at intel
> > .
> > com/
> > Signed-off-by: Crystal Guo <crystal.guo at mediatek.com>
> > ---
> >   drivers/memory/Kconfig              |   1 +
> >   drivers/memory/Makefile             |   1 +
> >   drivers/memory/mediatek/Kconfig     |  21 +++
> >   drivers/memory/mediatek/Makefile    |   2 +
> >   drivers/memory/mediatek/mtk-dramc.c | 196
> > ++++++++++++++++++++++++++++
> >   5 files changed, 221 insertions(+)
> >   create mode 100644 drivers/memory/mediatek/Kconfig
> >   create mode 100644 drivers/memory/mediatek/Makefile
> >   create mode 100644 drivers/memory/mediatek/mtk-dramc.c
> > 
> > diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> > index c82d8d8a16ea..b1698549ff81 100644
> > --- a/drivers/memory/Kconfig
> > +++ b/drivers/memory/Kconfig
> > @@ -227,5 +227,6 @@ config STM32_FMC2_EBI
> > 
> >   source "drivers/memory/samsung/Kconfig"
> >   source "drivers/memory/tegra/Kconfig"
> > +source "drivers/memory/mediatek/Kconfig"
> > 
> >   endif
> > diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> > index d2e6ca9abbe0..c0facf529803 100644
> > --- a/drivers/memory/Makefile
> > +++ b/drivers/memory/Makefile
> > @@ -27,6 +27,7 @@ obj-$(CONFIG_STM32_FMC2_EBI)        += stm32-
> > fmc2-ebi.o
> > 
> >   obj-$(CONFIG_SAMSUNG_MC)    += samsung/
> >   obj-$(CONFIG_TEGRA_MC)              += tegra/
> > +obj-$(CONFIG_MEDIATEK_MC)    += mediatek/
> >   obj-$(CONFIG_TI_EMIF_SRAM)  += ti-emif-sram.o
> >   obj-$(CONFIG_FPGA_DFL_EMIF) += dfl-emif.o
> > 
> > diff --git a/drivers/memory/mediatek/Kconfig
> > b/drivers/memory/mediatek/Kconfig
> > new file mode 100644
> > index 000000000000..3f238e0d9647
> > --- /dev/null
> > +++ b/drivers/memory/mediatek/Kconfig
> > @@ -0,0 +1,21 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +config MEDIATEK_MC
> > +     bool "MediaTek Memory Controller support"
> > +     help
> > +       This option allows to enable MediaTek memory controller
> > drivers,
> > +       which may include controllers for DRAM or others.
> > +       Select Y here if you need support for MediaTek memory
> > controller.
> > +       If you don't need, select N.
> > +
> > +if MEDIATEK_MC
> > +
> > +config MTK_DRAMC
> > +     tristate "MediaTek DRAMC driver"
> > +     default y
> > +     help
> > +       This option selects the MediaTek DRAMC driver, which
> > provides
> > +       an interface for reporting the current data rate of DRAM.
> > +       Select Y here if you need support for the MediaTek DRAMC
> > driver.
> > +       If you don't need, select N.
> > +
> > +endif
> > diff --git a/drivers/memory/mediatek/Makefile
> > b/drivers/memory/mediatek/Makefile
> > new file mode 100644
> > index 000000000000..a1395fc55b41
> > --- /dev/null
> > +++ b/drivers/memory/mediatek/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +obj-$(CONFIG_MTK_DRAMC)              += mtk-dramc.o
> > diff --git a/drivers/memory/mediatek/mtk-dramc.c
> > b/drivers/memory/mediatek/mtk-dramc.c
> > new file mode 100644
> > index 000000000000..d452483a98ce
> > --- /dev/null
> > +++ b/drivers/memory/mediatek/mtk-dramc.c
> > @@ -0,0 +1,196 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + */
> > +#include <linux/bitops.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/device.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/printk.h>
> > +
> > +#define POSDIV_PURIFY        BIT(2)
> > +#define PREDIV               7
> > +#define REF_FREQUENCY        26
> 
> REF_FREQUENCY should be platform data, not a definition, as this is
> different in other SoCs.
> 

Understood, it will be updated in the next version.

> > +#define SHUFFLE_OFFSET       0x700
> > +
> > +/*--------------------------------------------------------------
> > ------------*/
> > +/* Register
> > Offset                                                          */
> > +/*--------------------------------------------------------------
> > ------------*/
> > +#define DPHY_DVFS_STA                0x0e98
> > +#define APHY_PHYPLL2         0x0908
> > +#define APHY_CLRPLL2         0x0928
> > +#define APHY_PHYPLL3         0x090c
> > +#define APHY_CLRPLL3         0x092c
> > +#define APHY_PHYPLL4         0x0910
> > +#define APHY_ARPI0           0x0d94
> > +#define APHY_CA_ARDLL1               0x0d08
> > +#define APHY_B0_TX0          0x0dc4
> 
> Aren't those also SoC-dependant?

Yes, I will move those to platform data in the next version.

> 
> enum mtk_dramc_reg_index {
>         DRAMC_DPHY_DVFS_STA,
>         DRAMC_APHY_SHU_PHYPLL2,
>         ....etc
> }
> 
> static const u16 mtk_dramc_regs_mt8195[] = {
>         [DRAMC_DPHY_DVFS_STA] = 0x50c, /* ddrphy_config_NAO */
>         [DRAMC_APHY_SHU_PHYPLL2] = 0x704,
>         [DRAMC_APHY_SHU_CLRPLL2] = 0x724,
>         [DRAMC_APHY_SHU_PHYPLL3] = 0x708,
>         [DRAMC_APHY_SHU_CLRPLL3] = 0x728,
>         [DRAMC_APHY_SHU_PHYPLL4] = 0x70c,
>         ...etc
> }
> 
> static const u16 mtk_dramc_regs_mt8196[] = {
>         [DRAMC_DPHY_DVFS_STA] = 0xe98, /* ddrphy_config_misc */
>         [DRAMC_APHY_SHU_PHYPLL2] = 0x908,
>         [DRAMC_APHY_SHU_CLRPLL2] = 0x928,
>         .... etc
> }
> 
> > +
> > +/*--------------------------------------------------------------
> > ------------*/
> > +/* Register
> > Mask                                                            */
> > +/*--------------------------------------------------------------
> > ------------*/
> > +#define DPHY_DVFS_SHU_LV     GENMASK(15, 14)
> > +#define DPHY_DVFS_PLL_SEL    GENMASK(25, 25)
> > +#define APHY_PLL2_SDMPCW     GENMASK(18, 3)
> > +#define APHY_PLL3_POSDIV     GENMASK(13, 11)
> > +#define APHY_PLL4_FBKSEL     GENMASK(6, 6)
> > +#define APHY_ARPI0_SOPEN     GENMASK(26, 26)
> > +#define APHY_ARDLL1_CK_EN    GENMASK(0, 0)
> > +#define APHY_B0_TX0_SER_MODE GENMASK(4, 3)
> 
> And those masks should also be platform data, as those are also
> different
> in other SoCs.
> 

Yes, I will move those masks to platform data in the next version.

> > +
> > +static unsigned int read_reg_field(void __iomem *base, unsigned
> > int offset, unsigned int mask)
> > +{
> > +     unsigned int val = readl(base + offset);
> > +     unsigned int shift = __ffs(mask);
> > +
> > +     return (val & mask) >> shift;
> > +}
> > +
> > +struct mtk_dramc_pdata {
> > +     unsigned int fmeter_version;
> 
> u8 fmeter_version;
> u8 ref_freq_mhz;
> const u16 *regs;
> 
> ...etc etc
> 

Ok, I will update the platform data in the next version.

> 
> > +};
> > +
> > +struct mtk_dramc_dev_t {
> > +     void __iomem *anaphy_base;
> > +     void __iomem *ddrphy_base;
> > +     const struct mtk_dramc_pdata *pdata;
> > +};
> > +
> > +static int mtk_dramc_probe(struct platform_device *pdev)
> > +{
> > +     struct mtk_dramc_dev_t *dramc;
> > +     const struct mtk_dramc_pdata *pdata;
> > +     int ret;
> > +
> > +     dramc = devm_kzalloc(&pdev->dev, sizeof(struct
> > mtk_dramc_dev_t), GFP_KERNEL);
> > +     if (!dramc)
> > +             return dev_err_probe(&pdev->dev, -ENOMEM, "Failed to
> > allocate memory\n");
> > +
> > +     pdata = of_device_get_match_data(&pdev->dev);
> > +     if (!pdata)
> > +             return dev_err_probe(&pdev->dev, -EINVAL, "No
> > platform data available\n");
> > +
> > +     dramc->pdata = pdata;
> > +
> > +     dramc->anaphy_base = devm_platform_ioremap_resource(pdev, 0);
> > +     if (IS_ERR(dramc->anaphy_base)) {
> > +             ret = PTR_ERR(dramc->anaphy_base);
> > +             return dev_err_probe(&pdev->dev, ret, "Unable to map
> > DDRPHY NAO base\n");
> > +     }
> > +
> > +     dramc->ddrphy_base = devm_platform_ioremap_resource(pdev, 1);
> > +     if (IS_ERR(dramc->ddrphy_base)) {
> > +             ret = PTR_ERR(dramc->ddrphy_base);
> > +             return dev_err_probe(&pdev->dev, ret, "Unable to map
> > DDRPHY AO base\n");
> > +     }
> > +
> > +     platform_set_drvdata(pdev, dramc);
> > +     return 0;
> > +}
> > +
> > +static unsigned int mtk_fmeter_v1(struct mtk_dramc_dev_t *dramc)
> > +{
> > +     unsigned int shu_level, pll_sel, offset;
> > +     unsigned int sdmpcw, posdiv, ckdiv4, fbksel, sopen, async_ca,
> > ser_mode;
> > +     unsigned int perdiv_freq, posdiv_freq, vco_freq;
> > +     unsigned int final_rate;
> > +
> > +     shu_level = read_reg_field(dramc->ddrphy_base, DPHY_DVFS_STA,
> > DPHY_DVFS_SHU_LV);
> > +     pll_sel = read_reg_field(dramc->ddrphy_base, DPHY_DVFS_STA,
> > DPHY_DVFS_PLL_SEL);
> > +     offset = SHUFFLE_OFFSET * shu_level;
> > +
> > +     sdmpcw = read_reg_field(dramc->anaphy_base,
> > +                             ((pll_sel == 0) ? APHY_PHYPLL2 :
> > APHY_CLRPLL2) + offset,
> > +                             APHY_PLL2_SDMPCW);
> > +     posdiv = read_reg_field(dramc->anaphy_base,
> > +                             ((pll_sel == 0) ? APHY_PHYPLL3 :
> > APHY_CLRPLL3) + offset,
> > +                             APHY_PLL3_POSDIV);
> > +     fbksel = read_reg_field(dramc->anaphy_base, APHY_PHYPLL4 +
> > offset, APHY_PLL4_FBKSEL);
> > +     sopen = read_reg_field(dramc->anaphy_base, APHY_ARPI0 +
> > offset, APHY_ARPI0_SOPEN);
> > +     async_ca = read_reg_field(dramc->anaphy_base, APHY_CA_ARDLL1
> > + offset, APHY_ARDLL1_CK_EN);
> > +     ser_mode = read_reg_field(dramc->anaphy_base, APHY_B0_TX0 +
> > offset, APHY_B0_TX0_SER_MODE);
> > +
> > +     ckdiv4 = (ser_mode == 1) ? 1 : 0;
> > +     posdiv &= ~(POSDIV_PURIFY);
> > +
> > +     perdiv_freq = REF_FREQUENCY * (sdmpcw >> PREDIV);
> 
> s/perdiv/prediv/g

Thank you for the reminder, will make the correction in the next
version.

> 
> > +     posdiv_freq = (perdiv_freq >> posdiv) >> 1;
> > +     vco_freq = posdiv_freq << fbksel;
> > +     final_rate = vco_freq >> ckdiv4;
> > +
> 
> there's also one case in which `final_rate >>= 2`... please check if
> it is
> applicable to this driver (it should).
> 
> Cheers,
> Angelo

 
The variable name 'clkdiv4' might be misleading.
As its value can only be 1 or 0, the actual DDR data rate can be
obtained by 'final_rate = vco_freq >> clkdiv' (except when 'sopen == 1
&& async_ca == 1'), thus 'final_rate >>= 2' is not needed.
Renaming 'clkdiv4' to 'clkdiv' might be more appropriate.

Thanks,
Crystal

> 
> > +     if (sopen == 1 && async_ca == 1)
> > +             final_rate >>= 1;
> > +
> > +     return final_rate;
> > +}
> > +
> > +/*
> > + * mtk_dramc_get_data_rate - calculate DRAM data rate
> > + *
> > + * Returns DRAM data rate (MB/s)
> > + */
> > +static unsigned int mtk_dramc_get_data_rate(struct device *dev)
> > +{
> > +     struct mtk_dramc_dev_t *dramc_dev = dev_get_drvdata(dev);
> > +
> > +     if (!dramc_dev) {
> > +             dev_err(dev, "DRAMC device data not found\n");
> > +             return -EINVAL;
> > +     }
> > +
> > +     if (dramc_dev->pdata) {
> > +             if (dramc_dev->pdata->fmeter_version == 1)
> > +                     return mtk_fmeter_v1(dramc_dev);
> > +
> > +             dev_err(dev, "Unsupported fmeter version\n");
> > +             return -EINVAL;
> > +     }
> > +     dev_err(dev, "DRAMC platform data not found\n");
> > +     return -EINVAL;
> > +}
> > +
> > +static ssize_t dram_data_rate_show(struct device *dev,
> > +                                struct device_attribute *attr,
> > char *buf)
> > +{
> > +     return snprintf(buf, PAGE_SIZE, "DRAM data rate = %u\n",
> > +                     mtk_dramc_get_data_rate(dev));
> > +}
> > +
> > +static DEVICE_ATTR_RO(dram_data_rate);
> > +
> > +static struct attribute *mtk_dramc_attrs[] = {
> > +     &dev_attr_dram_data_rate.attr,
> > +     NULL
> > +};
> > +ATTRIBUTE_GROUPS(mtk_dramc);
> > +
> > +static const struct mtk_dramc_pdata dramc_pdata_mt8196 = {
> > +     .fmeter_version = 1
> > +};
> > +
> > +static const struct of_device_id mtk_dramc_of_ids[] = {
> > +     { .compatible = "mediatek,mt8196-dramc", .data =
> > &dramc_pdata_mt8196 },
> > +     {}
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_dramc_of_ids);
> > +
> > +static struct platform_driver mtk_dramc_driver = {
> > +     .probe = mtk_dramc_probe,
> > +     .driver = {
> > +             .name = "mtk_dramc_drv",
> > +             .of_match_table = mtk_dramc_of_ids,
> > +             .dev_groups = mtk_dramc_groups,
> > +     },
> > +};
> > +
> > +module_platform_driver(mtk_dramc_driver);
> > +
> > +MODULE_AUTHOR("Crystal Guo <crystal.guo at mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek DRAM Controller Driver");
> > +MODULE_LICENSE("GPL");
> 
> 

From kelvin.zhang at amlogic.com  Sun Mar 16 19:49:52 2025
From: kelvin.zhang at amlogic.com (Kelvin Zhang)
Date: Mon, 17 Mar 2025 10:49:52 +0800
Subject: [PATCH v4 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <20250314-tested-husky-of-force-1ccdca@krzk-bin>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
 <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>
 <20250314-tested-husky-of-force-1ccdca@krzk-bin>
Message-ID: <3dceafbf-49d4-4084-bfae-74384e187941@amlogic.com>

On 2025/3/14 16:01, Krzysztof Kozlowski wrote:
> 
> On Thu, Mar 13, 2025 at 05:05:35PM +0800, Kelvin Zhang wrote:
>>   &apb {
>> +     reset: reset-controller at 2000 {
>> +             compatible = "amlogic,a4-reset",
>> +                          "amlogic,meson-s4-reset";
>> +             reg = <0x0 0x2000 0x0 0x98>;
>> +             #reset-cells = <1>;
>> +     };
>> +
> 
> Why do you have on the bus devices with bus addressing and without it?
> What sort of bus is it?

Are you referring to the 'apb'?
If so, the 'apb' bus is defined in 
arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi.

apb: bus at fe000000 {
         compatible = "simple-bus";
         reg = <0x0 0xfe000000 0x0 0x480000>;
         #address-cells = <2>;
         #size-cells = <2>;
         ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;

> 
>>        periphs_pinctrl: pinctrl {
>>                compatible = "amlogic,pinctrl-a4";
>>                #address-cells = <2>;
> 
> Best regards,
> Krzysztof
> 

-- 
Best regards,

Kelvin Zhang



From andersson at kernel.org  Sun Mar 16 19:56:00 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Sun, 16 Mar 2025 21:56:00 -0500
Subject: [PATCH v14 0/2] media: qcom: camss: Add sc7280 support
In-Reply-To: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
References: <20250208225143.2868279-1-quic_vikramsa@quicinc.com>
Message-ID: <174218015892.1913428.13707146883622182488.b4-ty@kernel.org>


On Sun, 09 Feb 2025 04:21:41 +0530, Vikram Sharma wrote:
> SC7280 is a Qualcomm SoC. This series adds support to bring up the CSIPHY,
> CSID, VFE/RDI interfaces in SC7280.
> 
> SC7280 provides
> - 3 x VFE, 3 RDI per VFE
> - 2 x VFE Lite, 4 RDI per VFE
> - 3 x CSID
> - 2 x CSID Lite
> - 5 x CSI PHY
> 
> [...]

Applied, thanks!

[1/2] arm64: dts: qcom: sc7280: Add support for camss
      commit: d4da3adfc560fcb55578f8564d9f5a972507b118
[2/2] arm64: dts: qcom: qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine
      commit: 39e6ca14ace9d138e40ddd42313c2649a6f3e69f

Best regards,
-- 
Bjorn Andersson <andersson at kernel.org>


From jacky_chou at aspeedtech.com  Sun Mar 16 19:59:19 2025
From: jacky_chou at aspeedtech.com (Jacky Chou)
Date: Mon, 17 Mar 2025 10:59:19 +0800
Subject: [net-next 1/4] ARM: dts: aspeed-g6:add scu to mac for RGMII delay
In-Reply-To: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
Message-ID: <20250317025922.1526937-2-jacky_chou@aspeedtech.com>

The RGMII delay of AST2600 MAC is configured in SCU
register, so add scu regmap into mac node.

Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 8ed715bd53aa..17e979d616dc 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -236,6 +236,7 @@ mac0: ethernet at 1e660000 {
 			reg = <0x1e660000 0x180>;
 			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>;
+			scu = <&syscon>;
 			status = "disabled";
 		};
 
@@ -244,6 +245,7 @@ mac1: ethernet at 1e680000 {
 			reg = <0x1e680000 0x180>;
 			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&syscon ASPEED_CLK_GATE_MAC2CLK>;
+			scu = <&syscon>;
 			status = "disabled";
 		};
 
@@ -252,6 +254,7 @@ mac2: ethernet at 1e670000 {
 			reg = <0x1e670000 0x180>;
 			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&syscon ASPEED_CLK_GATE_MAC3CLK>;
+			scu = <&syscon>;
 			status = "disabled";
 		};
 
@@ -260,6 +263,7 @@ mac3: ethernet at 1e690000 {
 			reg = <0x1e690000 0x180>;
 			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>;
+			scu = <&syscon>;
 			status = "disabled";
 		};
 
-- 
2.34.1



From jacky_chou at aspeedtech.com  Sun Mar 16 19:59:20 2025
From: jacky_chou at aspeedtech.com (Jacky Chou)
Date: Mon, 17 Mar 2025 10:59:20 +0800
Subject: [net-next 2/4] ARM: dts: ast2600-evb: add default RGMII delay
In-Reply-To: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
Message-ID: <20250317025922.1526937-3-jacky_chou@aspeedtech.com>

Use tx-internal-delay-ps and rx-internal-delay-ps to
configure the RGMII delay on MAC.
And add default value for AST2600 MAC in dts.
Refer to faraday,ftgmac100yaml to know how to configure
the RGMII delay.

Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts
index de83c0eb1d6e..1db1f2a02d91 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts
@@ -126,6 +126,9 @@ &mac0 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&ethphy0>;
 
+	tx-internal-delay-ps = <16>;
+	rx-internal-delay-ps = <10>;
+
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_rgmii1_default>;
 };
@@ -137,6 +140,9 @@ &mac1 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&ethphy1>;
 
+	tx-internal-delay-ps = <16>;
+	rx-internal-delay-ps = <10>;
+
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_rgmii2_default>;
 };
@@ -147,6 +153,9 @@ &mac2 {
 	phy-mode = "rgmii";
 	phy-handle = <&ethphy2>;
 
+	tx-internal-delay-ps = <8>;
+	rx-internal-delay-ps = <4>;
+
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_rgmii3_default>;
 };
@@ -157,6 +166,9 @@ &mac3 {
 	phy-mode = "rgmii";
 	phy-handle = <&ethphy3>;
 
+	tx-internal-delay-ps = <8>;
+	rx-internal-delay-ps = <4>;
+
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_rgmii4_default>;
 };
-- 
2.34.1



From jacky_chou at aspeedtech.com  Sun Mar 16 19:59:21 2025
From: jacky_chou at aspeedtech.com (Jacky Chou)
Date: Mon, 17 Mar 2025 10:59:21 +0800
Subject: [net-next 3/4] dt-bindings: net: ftgmac100: add rgmii delay properties
In-Reply-To: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
Message-ID: <20250317025922.1526937-4-jacky_chou@aspeedtech.com>

Add tx-internal-delay-ps and rx-internal-delay-ps to
configure the RGMII delay for MAC. According to
ethernet-controller.yaml, they use for RGMII TX and RX delay.

In Aspeed desgin, the RGMII delay is a number of ps as unit to
set delay, do not use one ps as unit. The values are different
from each MAC. So, here describes the property values
as index to configure corresponding scu register.

Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
---
 .../bindings/net/faraday,ftgmac100.yaml          | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
index 55d6a8379025..c5904aa84e05 100644
--- a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
+++ b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
@@ -66,6 +66,20 @@ properties:
     type: boolean
     deprecated: true
 
+  rx-internal-delay-ps:
+    description:
+       Setting this property to a non-zero number sets the RX internal delay
+       for the MAC. Use this property value as a index not a ps unit to
+       configure the corresponding delay register field. And the index range is
+       0 to 63.
+
+  tx-internal-delay-ps:
+    description:
+       Setting this property to a non-zero number sets the TX internal delay
+       for the MAC. Use this property value as a index not a ps unit to
+       configure the corresponding delay register field. And the index range is
+       0 to 63.
+
   mdio:
     $ref: /schemas/net/mdio.yaml#
 
@@ -102,4 +116,4 @@ examples:
                 reg = <1>;
             };
         };
-    };
+    };
\ No newline at end of file
-- 
2.34.1



From jacky_chou at aspeedtech.com  Sun Mar 16 19:59:18 2025
From: jacky_chou at aspeedtech.com (Jacky Chou)
Date: Mon, 17 Mar 2025 10:59:18 +0800
Subject: [net-next 0/4] Add AST2600 RGMII delay into ftgmac100
Message-ID: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>

In AST2600, the RGMII delay is configured in SCU.
Add the properties according ethernet-controller.yaml into AST2600 dts
and dtsi, and add these in the ftgmac100 driver and yaml to configure and
describe how to use.
Now, just support for AST2600 and the other platforms will be ignored
the RGMII delay setting according to compatible.

Jacky Chou (4):
  ARM: dts: aspeed-g6:add scu to mac for RGMII delay
  ARM: dts: ast2600-evb: add default RGMII delay
  dt-bindings: net: ftgmac100: add rgmii delay properties
  net: ftgmac100: add RGMII delay for AST2600

 .../bindings/net/faraday,ftgmac100.yaml       | 16 +++-
 .../boot/dts/aspeed/aspeed-ast2600-evb.dts    | 12 +++
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi       |  4 +
 drivers/net/ethernet/faraday/ftgmac100.c      | 88 +++++++++++++++++++
 drivers/net/ethernet/faraday/ftgmac100.h      | 12 +++
 5 files changed, 131 insertions(+), 1 deletion(-)

-- 
2.34.1



From jacky_chou at aspeedtech.com  Sun Mar 16 19:59:22 2025
From: jacky_chou at aspeedtech.com (Jacky Chou)
Date: Mon, 17 Mar 2025 10:59:22 +0800
Subject: [net-next 4/4] net: ftgmac100: add RGMII delay for AST2600
In-Reply-To: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
Message-ID: <20250317025922.1526937-5-jacky_chou@aspeedtech.com>

Use rx-internal-delay-ps and tx-internal-delay-ps
properties to configue the RGMII delay into corresponding register of
scu. Currently, the ftgmac100 driver only configures on AST2600 and will
be by pass the other platforms.
The details are in faraday,ftgmac100.yaml.

Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
---
 drivers/net/ethernet/faraday/ftgmac100.c | 88 ++++++++++++++++++++++++
 drivers/net/ethernet/faraday/ftgmac100.h | 12 ++++
 2 files changed, 100 insertions(+)

diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 17ec35e75a65..ea2061488cba 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -27,6 +27,9 @@
 #include <linux/phy_fixed.h>
 #include <net/ip.h>
 #include <net/ncsi.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
 
 #include "ftgmac100.h"
 
@@ -1812,6 +1815,88 @@ static bool ftgmac100_has_child_node(struct device_node *np, const char *name)
 	return ret;
 }
 
+static void ftgmac100_set_internal_delay(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct net_device *netdev;
+	struct ftgmac100 *priv;
+	struct regmap *scu;
+	u32 rgmii_tx_delay, rgmii_rx_delay;
+	u32 dly_reg, tx_dly_mask, rx_dly_mask;
+	int tx, rx;
+
+	netdev = platform_get_drvdata(pdev);
+	priv = netdev_priv(netdev);
+
+	tx = of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay);
+	rx = of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_rx_delay);
+
+	if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
+		/* According to mac base address to get mac index */
+		switch (priv->res->start) {
+		case 0x1e660000:
+			dly_reg = AST2600_MAC12_CLK_DLY;
+			tx_dly_mask = AST2600_MAC1_TX_DLY;
+			rx_dly_mask = AST2600_MAC1_RX_DLY;
+			rgmii_tx_delay = FIELD_PREP(AST2600_MAC1_TX_DLY, rgmii_tx_delay);
+			rgmii_rx_delay = FIELD_PREP(AST2600_MAC1_RX_DLY, rgmii_rx_delay);
+			break;
+		case 0x1e680000:
+			dly_reg = AST2600_MAC12_CLK_DLY;
+			tx_dly_mask = AST2600_MAC2_TX_DLY;
+			rx_dly_mask = AST2600_MAC2_RX_DLY;
+			rgmii_tx_delay = FIELD_PREP(AST2600_MAC2_TX_DLY, rgmii_tx_delay);
+			rgmii_rx_delay = FIELD_PREP(AST2600_MAC2_RX_DLY, rgmii_rx_delay);
+			break;
+		case 0x1e670000:
+			dly_reg = AST2600_MAC34_CLK_DLY;
+			tx_dly_mask = AST2600_MAC3_TX_DLY;
+			rx_dly_mask = AST2600_MAC3_RX_DLY;
+			rgmii_tx_delay = FIELD_PREP(AST2600_MAC3_TX_DLY, rgmii_tx_delay);
+			rgmii_rx_delay = FIELD_PREP(AST2600_MAC3_RX_DLY, rgmii_rx_delay);
+			break;
+		case 0x1e690000:
+			dly_reg = AST2600_MAC34_CLK_DLY;
+			tx_dly_mask = AST2600_MAC4_TX_DLY;
+			rx_dly_mask = AST2600_MAC4_RX_DLY;
+			rgmii_tx_delay = FIELD_PREP(AST2600_MAC4_TX_DLY, rgmii_tx_delay);
+			rgmii_rx_delay = FIELD_PREP(AST2600_MAC4_RX_DLY, rgmii_rx_delay);
+			break;
+		default:
+			dev_warn(&pdev->dev, "Invalid mac base address");
+			return;
+		}
+	} else {
+		return;
+	}
+
+	scu = syscon_regmap_lookup_by_phandle(np, "scu");
+	if (IS_ERR(scu)) {
+		dev_warn(&pdev->dev, "failed to map scu base");
+		return;
+	}
+
+	if (!tx) {
+		/* Use tx-internal-delay-ps as index to configure tx delay
+		 * into scu register.
+		 */
+		if (rgmii_tx_delay > 64)
+			dev_warn(&pdev->dev, "Get invalid tx delay value");
+		else
+			regmap_update_bits(scu, dly_reg, tx_dly_mask, rgmii_tx_delay);
+	}
+
+	if (!rx) {
+		/* Use rx-internal-delay-ps as index to configure rx delay
+		 * into scu register.
+		 */
+		if (rgmii_tx_delay > 64)
+			dev_warn(&pdev->dev, "Get invalid rx delay value");
+		else
+			regmap_update_bits(scu, dly_reg, rx_dly_mask, rgmii_rx_delay);
+	}
+}
+
 static int ftgmac100_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1977,6 +2062,9 @@ static int ftgmac100_probe(struct platform_device *pdev)
 		if (of_device_is_compatible(np, "aspeed,ast2600-mac"))
 			iowrite32(FTGMAC100_TM_DEFAULT,
 				  priv->base + FTGMAC100_OFFSET_TM);
+
+		/* Configure RGMII delay if there are the corresponding properties */
+		ftgmac100_set_internal_delay(pdev);
 	}
 
 	/* Default ring sizes */
diff --git a/drivers/net/ethernet/faraday/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h
index 4968f6f0bdbc..d464d287502c 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.h
+++ b/drivers/net/ethernet/faraday/ftgmac100.h
@@ -271,4 +271,16 @@ struct ftgmac100_rxdes {
 #define FTGMAC100_RXDES1_UDP_CHKSUM_ERR	(1 << 26)
 #define FTGMAC100_RXDES1_IP_CHKSUM_ERR	(1 << 27)
 
+/* Aspeed SCU */
+#define AST2600_MAC12_CLK_DLY	0x340
+#define AST2600_MAC1_TX_DLY		GENMASK(5, 0)
+#define AST2600_MAC1_RX_DLY		GENMASK(17, 12)
+#define AST2600_MAC2_TX_DLY		GENMASK(11, 6)
+#define AST2600_MAC2_RX_DLY		GENMASK(23, 18)
+#define AST2600_MAC34_CLK_DLY	0x350
+#define AST2600_MAC3_TX_DLY		AST2600_MAC1_TX_DLY
+#define AST2600_MAC3_RX_DLY		AST2600_MAC1_RX_DLY
+#define AST2600_MAC4_TX_DLY		AST2600_MAC2_TX_DLY
+#define AST2600_MAC4_RX_DLY		AST2600_MAC2_RX_DLY
+
 #endif /* __FTGMAC100_H */
-- 
2.34.1



From sfr at canb.auug.org.au  Sun Mar 16 20:34:31 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Mon, 17 Mar 2025 14:34:31 +1100
Subject: linux-next: manual merge of the backlight tree with the
 arm-soc-fixes tree
Message-ID: <20250317143431.00ba29bc@canb.auug.org.au>

Hi all,

Today's linux-next merge of the backlight tree got a conflict in:

  MAINTAINERS

between commit:

  4fa911d2d4cf ("MAINTAINERS: Add apple-spi driver & binding files")

from the arm-soc-fixes tree and commit:

  d1ebaf003a06 ("MAINTAINERS: Add entries for Apple DWI backlight controller")

from the backlight tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc MAINTAINERS
index 55e367614f61,a576324807f5..000000000000
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -2266,7 -2254,7 +2267,8 @@@ F:	drivers/nvmem/apple-efuses.
  F:	drivers/pinctrl/pinctrl-apple-gpio.c
  F:	drivers/pwm/pwm-apple.c
  F:	drivers/soc/apple/*
 +F:	drivers/spi/spi-apple.c
+ F:	drivers/video/backlight/apple_dwi_bl.c
  F:	drivers/watchdog/apple_wdt.c
  F:	include/dt-bindings/interrupt-controller/apple-aic.h
  F:	include/dt-bindings/pinctrl/apple.h
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/903cbd12/attachment.sig>

From robh at kernel.org  Sun Mar 16 21:31:42 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Sun, 16 Mar 2025 23:31:42 -0500
Subject: [net-next 3/4] dt-bindings: net: ftgmac100: add rgmii delay
 properties
In-Reply-To: <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
Message-ID: <174218590293.2844402.7312672269180234107.robh@kernel.org>


On Mon, 17 Mar 2025 10:59:21 +0800, Jacky Chou wrote:
> Add tx-internal-delay-ps and rx-internal-delay-ps to
> configure the RGMII delay for MAC. According to
> ethernet-controller.yaml, they use for RGMII TX and RX delay.
> 
> In Aspeed desgin, the RGMII delay is a number of ps as unit to
> set delay, do not use one ps as unit. The values are different
> from each MAC. So, here describes the property values
> as index to configure corresponding scu register.
> 
> Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
> ---
>  .../bindings/net/faraday,ftgmac100.yaml          | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml:71:8: [warning] wrong indentation: expected 6 but found 7 (indentation)
./Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml:78:8: [warning] wrong indentation: expected 6 but found 7 (indentation)
./Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml:119:7: [error] no new line character at the end of file (new-line-at-end-of-file)

dtschema/dtc warnings/errors:

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250317025922.1526937-4-jacky_chou at aspeedtech.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From ankita at nvidia.com  Sun Mar 16 22:55:55 2025
From: ankita at nvidia.com (Ankit Agrawal)
Date: Mon, 17 Mar 2025 05:55:55 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <87tt7y7j6r.wl-maz@kernel.org>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<86r033olwv.wl-maz@kernel.org>
	<SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
Message-ID: <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>

>> For my education, what is an accepted way to communicate this? Please let
>> me know if there are any relevant examples that you may be aware of.
>
> A KVM capability is what is usually needed.

I see. If IIUC, this would involve a corresponding Qemu (usermode) change
to fetch the new KVM cap. Then it could fail in case the FWB is not
supported with some additional conditions (so that the currently supported
configs with !FWB won't break on usermode). 

The proposed code change is to map in S2 as NORMAL when vma flags
has VM_PFNMAP. However, Qemu cannot know that driver is mapping
with PFNMAP or not. So how may Qemu decide whether it is okay to
fail for !FWB or not?

> This must be checked at the point of memslot creation, and return an
> error at that point. Memslots are all about stage-2, so it makes sense
> to check it there.

Ack, will add the check.

>
>??????? M.
>
> --
> Without deviation from the norm, progress is not possible.

From viresh.kumar at linaro.org  Sun Mar 16 23:01:10 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Mon, 17 Mar 2025 11:31:10 +0530
Subject: [PATCH v3] cpufreq: Init cpufreq only for present CPUs
In-Reply-To: <20250313013928.529926-1-ping.bai@nxp.com>
References: <20250313013928.529926-1-ping.bai@nxp.com>
Message-ID: <20250317060110.tvjat7ugmaceayyk@vireshk-i7>

On 13-03-25, 09:39, Jacky Bai wrote:
> for_each_possible_cpu() is currently used to initialize cpufreq.
> However, in cpu_dev_register_generic(), for_each_present_cpu()
> is used to register CPU devices which means the CPU devices are
> only registered for present CPUs and not all possible CPUs.
> 
> With nosmp or maxcpus=0, only the boot CPU is present, lead
> to the cpufreq probe failure or defer probe due to no cpu device
> available for not present CPUs.
> 
> Change for_each_possible_cpu() to for_each_present_cpu() in the
> above cpufreq drivers to ensure it only registers cpufreq for
> CPUs that are actually present.
> 
> Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
> Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
> Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> ---
>  - v3 changes:
>   - refine the changlog to drop the changed driver list.

Applied. Thanks.

-- 
viresh


From anshuman.khandual at arm.com  Sun Mar 16 23:18:16 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 17 Mar 2025 11:48:16 +0530
Subject: [PATCH 0/2] mm/ptdump: Drop assumption that pxd_val() is u64
Message-ID: <20250317061818.16244-1-anshuman.khandual@arm.com>

Last argument passed down in note_page() is u64 assuming pxd_val() returned
value (all page table levels) is 64 bit - which might not be the case going
ahead when D128 page tables is enabled on arm64 platform. Besides pxd_val()
is very platform specific and its type should not be assumed in generic MM.

This series splits note_page() into individual page table level specific
callbacks which accepts corresponding pxd_t page table entry as an argument
instead and later all subscribing platforms could derive pxd_val() from the
entries as required and proceed as before.

Page table entry's value, mask and protection are represented with pteval_t
not u64 that has been assumed while dumping the page table entries on arm64
platform. Replace such u64 instances with pteval_t instead as expected.

This series has been tested on arm64 platform but it does build on other
relevant platforms (v6.14-rc7).

Changes in V1:

- Added note_page_flush() callback and implemented the same on all
  subscribing platforms
- Moved note_page() argument change from u64 to pteval_t on arm64 platform
  from second patch to the first patch instead

Changes in RFC:

https://lore.kernel.org/all/20250310095902.390664-1-anshuman.khandual at arm.com/

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Steven Price <steven.price at arm.com>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
Cc: Nicholas Piggin <npiggin at gmail.com>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Gerald Schaefer <gerald.schaefer at linux.ibm.com>
Cc: Heiko Carstens <hca at linux.ibm.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-mm at kvack.org

Anshuman Khandual (2):
  mm/ptdump: Split note_page() into level specific callbacks
  arm64/ptdump: Replace u64 with pteval_t

 arch/arm64/include/asm/ptdump.h | 24 ++++++++++++----
 arch/arm64/mm/ptdump.c          | 50 ++++++++++++++++++++++++++++++---
 arch/powerpc/mm/ptdump/ptdump.c | 46 ++++++++++++++++++++++++++++--
 arch/riscv/mm/ptdump.c          | 46 ++++++++++++++++++++++++++++--
 arch/s390/mm/dump_pagetables.c  | 46 ++++++++++++++++++++++++++++--
 arch/x86/mm/dump_pagetables.c   | 39 ++++++++++++++++++++++++-
 include/linux/ptdump.h          |  9 ++++--
 mm/ptdump.c                     | 42 ++++++++++++++++++++-------
 8 files changed, 272 insertions(+), 30 deletions(-)

-- 
2.25.1



From anshuman.khandual at arm.com  Sun Mar 16 23:18:17 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 17 Mar 2025 11:48:17 +0530
Subject: [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks
In-Reply-To: <20250317061818.16244-1-anshuman.khandual@arm.com>
References: <20250317061818.16244-1-anshuman.khandual@arm.com>
Message-ID: <20250317061818.16244-2-anshuman.khandual@arm.com>

Last argument passed down in note_page() is u64 assuming pxd_val() returned
value (all page table levels) is 64 bit - which might not be the case going
ahead when D128 page tables is enabled on arm64 platform. Besides pxd_val()
is very platform specific and its type should not be assumed in generic MM.

Split note_page() into individual page table level specific callbacks which
accepts corresponding pxd_t argument instead and then subscribing platforms
just derive pxd_val() from the entries as required and proceed as earlier.

Also add a note_page_flush() callback for flushing the last page table page
that was being handled earlier via level = -1.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
Cc: Nicholas Piggin <npiggin at gmail.com>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Gerald Schaefer <gerald.schaefer at linux.ibm.com>
Cc: Heiko Carstens <hca at linux.ibm.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-mm at kvack.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
 arch/arm64/include/asm/ptdump.h | 16 +++++++++--
 arch/arm64/mm/ptdump.c          | 48 ++++++++++++++++++++++++++++++---
 arch/powerpc/mm/ptdump/ptdump.c | 46 +++++++++++++++++++++++++++++--
 arch/riscv/mm/ptdump.c          | 46 +++++++++++++++++++++++++++++--
 arch/s390/mm/dump_pagetables.c  | 46 +++++++++++++++++++++++++++++--
 arch/x86/mm/dump_pagetables.c   | 39 ++++++++++++++++++++++++++-
 include/linux/ptdump.h          |  9 ++++---
 mm/ptdump.c                     | 42 ++++++++++++++++++++++-------
 8 files changed, 267 insertions(+), 25 deletions(-)

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index 6cf4aae05219..e5da9ce8a515 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -59,7 +59,13 @@ struct ptdump_pg_state {
 
 void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
 void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
-	       u64 val);
+	       pteval_t val);
+void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte);
+void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
+void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud);
+void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
+void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
+void note_page_flush(struct ptdump_state *st);
 #ifdef CONFIG_PTDUMP_DEBUGFS
 #define EFI_RUNTIME_MAP_END	DEFAULT_MAP_WINDOW_64
 void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
@@ -69,7 +75,13 @@ static inline void ptdump_debugfs_register(struct ptdump_info *info,
 #endif /* CONFIG_PTDUMP_DEBUGFS */
 #else
 static inline void note_page(struct ptdump_state *pt_st, unsigned long addr,
-			     int level, u64 val) { }
+			     int level, pteval_t val) { }
+static inline void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte) { }
+static inline void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd) { }
+static inline void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud) { }
+static inline void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d) { }
+static inline void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd) { }
+static inline void note_page_flush(struct ptdump_state *st) { }
 #endif /* CONFIG_PTDUMP_CORE */
 
 #endif /* __ASM_PTDUMP_H */
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 688fbe0271ca..fd1610b4fd15 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -189,7 +189,7 @@ static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr)
 }
 
 void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
-	       u64 val)
+	       pteval_t val)
 {
 	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
 	struct ptdump_pg_level *pg_level = st->pg_level;
@@ -251,6 +251,38 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 
 }
 
+void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
+void note_page_flush(struct ptdump_state *pt_st)
+{
+	pte_t pte_zero = {0};
+
+	note_page(pt_st, 0, -1, pte_val(pte_zero));
+}
+
 void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 {
 	unsigned long end = ~0UL;
@@ -266,7 +298,12 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 		.pg_level = &kernel_pg_levels[0],
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]){
 				{info->base_addr, end},
 				{0, 0}
@@ -303,7 +340,12 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]) {
 				{_PAGE_OFFSET(vabits_actual), ~0UL},
 				{0, 0}
diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index 9dc239967b77..b2358d794855 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -298,6 +298,38 @@ static void populate_markers(void)
 #endif
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
+static void note_page_flush(struct ptdump_state *pt_st)
+{
+	pte_t pte_zero = {0};
+
+	note_page(pt_st, 0, -1, pte_val(pte_zero));
+}
+
 static int ptdump_show(struct seq_file *m, void *v)
 {
 	struct pg_state st = {
@@ -305,7 +337,12 @@ static int ptdump_show(struct seq_file *m, void *v)
 		.marker = address_markers,
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = ptdump_range,
 		}
 	};
@@ -338,7 +375,12 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = ptdump_range,
 		}
 	};
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
index 9d5f657a251b..32922550a50a 100644
--- a/arch/riscv/mm/ptdump.c
+++ b/arch/riscv/mm/ptdump.c
@@ -318,6 +318,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
+static void note_page_flush(struct ptdump_state *pt_st)
+{
+	pte_t pte_zero = {0};
+
+	note_page(pt_st, 0, -1, pte_val(pte_zero));
+}
+
 static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
 {
 	struct pg_state st = {
@@ -325,7 +357,12 @@ static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
 		.marker = pinfo->markers,
 		.level = -1,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]) {
 				{pinfo->base_addr, pinfo->end},
 				{0, 0}
@@ -347,7 +384,12 @@ bool ptdump_check_wx(void)
 		.level = -1,
 		.check_wx = true,
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]) {
 				{KERN_VIRT_START, ULONG_MAX},
 				{0, 0}
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index fa54f3bc0c8d..e7cc52542f71 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -145,11 +145,48 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
+static void note_page_flush(struct ptdump_state *pt_st)
+{
+	pte_t pte_zero = {0};
+
+	note_page(pt_st, 0, -1, pte_val(pte_zero));
+}
+
 bool ptdump_check_wx(void)
 {
 	struct pg_state st = {
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]) {
 				{.start = 0, .end = max_addr},
 				{.start = 0, .end = 0},
@@ -188,7 +225,12 @@ static int ptdump_show(struct seq_file *m, void *v)
 {
 	struct pg_state st = {
 		.ptdump = {
-			.note_page = note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.range = (struct ptdump_range[]) {
 				{.start = 0, .end = max_addr},
 				{.start = 0, .end = 0},
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 89079ea73e65..2e1c2d006ace 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -362,6 +362,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	}
 }
 
+static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
+{
+	note_page(pt_st, addr, 4, pte_val(pte));
+}
+
+static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
+{
+	note_page(pt_st, addr, 3, pmd_val(pmd));
+}
+
+static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
+{
+	note_page(pt_st, addr, 2, pud_val(pud));
+}
+
+static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
+{
+	note_page(pt_st, addr, 1, p4d_val(p4d));
+}
+
+static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
+{
+	note_page(pt_st, addr, 0, pgd_val(pgd));
+}
+
+static void note_page_flush(struct ptdump_state *pt_st)
+{
+	pte_t pte_zero = {0};
+
+	note_page(pt_st, 0, -1, pte_val(pte_zero));
+}
+
 bool ptdump_walk_pgd_level_core(struct seq_file *m,
 				struct mm_struct *mm, pgd_t *pgd,
 				bool checkwx, bool dmesg)
@@ -378,7 +410,12 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m,
 
 	struct pg_state st = {
 		.ptdump = {
-			.note_page	= note_page,
+			.note_page_pte = note_page_pte,
+			.note_page_pmd = note_page_pmd,
+			.note_page_pud = note_page_pud,
+			.note_page_p4d = note_page_p4d,
+			.note_page_pgd = note_page_pgd,
+			.note_page_flush = note_page_flush,
 			.effective_prot = effective_prot,
 			.range		= ptdump_ranges
 		},
diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h
index 8dbd51ea8626..1c1eb1fae199 100644
--- a/include/linux/ptdump.h
+++ b/include/linux/ptdump.h
@@ -11,9 +11,12 @@ struct ptdump_range {
 };
 
 struct ptdump_state {
-	/* level is 0:PGD to 4:PTE, or -1 if unknown */
-	void (*note_page)(struct ptdump_state *st, unsigned long addr,
-			  int level, u64 val);
+	void (*note_page_pte)(struct ptdump_state *st, unsigned long addr, pte_t pte);
+	void (*note_page_pmd)(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
+	void (*note_page_pud)(struct ptdump_state *st, unsigned long addr, pud_t pud);
+	void (*note_page_p4d)(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
+	void (*note_page_pgd)(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
+	void (*note_page_flush)(struct ptdump_state *st);
 	void (*effective_prot)(struct ptdump_state *st, int level, u64 val);
 	const struct ptdump_range *range;
 };
diff --git a/mm/ptdump.c b/mm/ptdump.c
index 106e1d66e9f9..706cfc19439b 100644
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -18,7 +18,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk,
 {
 	struct ptdump_state *st = walk->private;
 
-	st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0]));
+	st->note_page_pte(st, addr, kasan_early_shadow_pte[0]);
 
 	walk->action = ACTION_CONTINUE;
 
@@ -42,7 +42,7 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr,
 		st->effective_prot(st, 0, pgd_val(val));
 
 	if (pgd_leaf(val)) {
-		st->note_page(st, addr, 0, pgd_val(val));
+		st->note_page_pgd(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -65,7 +65,7 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr,
 		st->effective_prot(st, 1, p4d_val(val));
 
 	if (p4d_leaf(val)) {
-		st->note_page(st, addr, 1, p4d_val(val));
+		st->note_page_p4d(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -88,7 +88,7 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr,
 		st->effective_prot(st, 2, pud_val(val));
 
 	if (pud_leaf(val)) {
-		st->note_page(st, addr, 2, pud_val(val));
+		st->note_page_pud(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -109,7 +109,7 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr,
 	if (st->effective_prot)
 		st->effective_prot(st, 3, pmd_val(val));
 	if (pmd_leaf(val)) {
-		st->note_page(st, addr, 3, pmd_val(val));
+		st->note_page_pmd(st, addr, val);
 		walk->action = ACTION_CONTINUE;
 	}
 
@@ -125,7 +125,7 @@ static int ptdump_pte_entry(pte_t *pte, unsigned long addr,
 	if (st->effective_prot)
 		st->effective_prot(st, 4, pte_val(val));
 
-	st->note_page(st, addr, 4, pte_val(val));
+	st->note_page_pte(st, addr, val);
 
 	return 0;
 }
@@ -134,9 +134,31 @@ static int ptdump_hole(unsigned long addr, unsigned long next,
 		       int depth, struct mm_walk *walk)
 {
 	struct ptdump_state *st = walk->private;
-
-	st->note_page(st, addr, depth, 0);
-
+	pte_t pte_zero = {0};
+	pmd_t pmd_zero = {0};
+	pud_t pud_zero = {0};
+	p4d_t p4d_zero = {0};
+	pgd_t pgd_zero = {0};
+
+	switch (depth) {
+	case 4:
+		st->note_page_pte(st, addr, pte_zero);
+		break;
+	case 3:
+		st->note_page_pmd(st, addr, pmd_zero);
+		break;
+	case 2:
+		st->note_page_pud(st, addr, pud_zero);
+		break;
+	case 1:
+		st->note_page_p4d(st, addr, p4d_zero);
+		break;
+	case 0:
+		st->note_page_pgd(st, addr, pgd_zero);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
@@ -162,7 +184,7 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
 	mmap_write_unlock(mm);
 
 	/* Flush out the last page */
-	st->note_page(st, 0, -1, 0);
+	st->note_page_flush(st);
 }
 
 static int check_wx_show(struct seq_file *m, void *v)
-- 
2.25.1



From anshuman.khandual at arm.com  Sun Mar 16 23:18:18 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 17 Mar 2025 11:48:18 +0530
Subject: [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t
In-Reply-To: <20250317061818.16244-1-anshuman.khandual@arm.com>
References: <20250317061818.16244-1-anshuman.khandual@arm.com>
Message-ID: <20250317061818.16244-3-anshuman.khandual@arm.com>

Page table entry's value, mask and protection are represented with pteval_t
data type format not u64 that has been assumed while dumping the page table
entries. Replace all such u64 instances with pteval_t instead as required.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Marc Zyngier <maz at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
---
 arch/arm64/include/asm/ptdump.h | 8 ++++----
 arch/arm64/mm/ptdump.c          | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index e5da9ce8a515..476a870489b9 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -24,8 +24,8 @@ struct ptdump_info {
 };
 
 struct ptdump_prot_bits {
-	u64		mask;
-	u64		val;
+	pteval_t	mask;
+	pteval_t	val;
 	const char	*set;
 	const char	*clear;
 };
@@ -34,7 +34,7 @@ struct ptdump_pg_level {
 	const struct ptdump_prot_bits *bits;
 	char name[4];
 	int num;
-	u64 mask;
+	pteval_t mask;
 };
 
 /*
@@ -51,7 +51,7 @@ struct ptdump_pg_state {
 	const struct mm_struct *mm;
 	unsigned long start_address;
 	int level;
-	u64 current_prot;
+	pteval_t current_prot;
 	bool check_wx;
 	unsigned long wx_pages;
 	unsigned long uxn_pages;
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index fd1610b4fd15..a5651be95868 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
 	struct ptdump_pg_level *pg_level = st->pg_level;
 	static const char units[] = "KMGTPE";
-	u64 prot = 0;
+	pteval_t prot = 0;
 
 	/* check if the current level has been folded dynamically */
 	if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) ||
-- 
2.25.1



From jirislaby at kernel.org  Sun Mar 16 23:21:23 2025
From: jirislaby at kernel.org (Jiri Slaby)
Date: Mon, 17 Mar 2025 07:21:23 +0100
Subject: [PATCH linux-next] ASoC: use sysfs_emit() instead of scnprintf().
In-Reply-To: <20250315141546004ww7-8GUuuRfAQIb8b4KYZ@zte.com.cn>
References: <20250315141546004ww7-8GUuuRfAQIb8b4KYZ@zte.com.cn>
Message-ID: <10eecd8c-52b8-4050-8b1d-f612f4ffc653@kernel.org>

On 15. 03. 25, 7:15, xie.ludan at zte.com.cn wrote:
> From: XieLudan <xie.ludan at zte.com.cn>
> 
> 
> Follow the advice in Documentation/filesystems/sysfs.rst:
> 
> show() should only use sysfs_emit() or sysfs_emit_at() when formatting
> 
> the value to be returned to user space.
> 
> 
> Signed-off-by: XieLudan <xie.ludan at zte.com.cn>
> 
> ---
> 
>  ?sound/soc/fsl/imx-audmux.c | 26 +++++++++++---------------
> 
>  ?1 file changed, 11 insertions(+), 15 deletions(-)
> 
> 
> diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
> 
> index cc2918ee2cf5..6062503d3543 100644
> 
> --- a/sound/soc/fsl/imx-audmux.c
> 
> +++ b/sound/soc/fsl/imx-audmux.c
> 
> @@ -77,45 +77,41 @@ static ssize_t audmux_read_file(struct file *file, 
> char __user *user_buf,
> 
> ret = sysfs_emit(buf, "PDCR: %08x\nPTCR: %08x\n", pdcr, ptcr);
> 
> if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
> 
> -ret += scnprintf(buf + ret, PAGE_SIZE - ret,
> 
> +ret += sysfs_emit(buf + ret,

This is wrong too [1].

[1] 
https://lore.kernel.org/all/9c552d9a-2d46-4069-a9c4-35fab857bfc3 at kernel.org/

regards,
-- 
js
suse labs



From mike.looijmans at topic.nl  Sun Mar 16 23:21:21 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Mon, 17 Mar 2025 07:21:21 +0100
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <20250314211411.l5taj5nysvcalfyz@synopsys.com>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
 <20250314211411.l5taj5nysvcalfyz@synopsys.com>
Message-ID: <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>

On 14-03-2025 22:14, Thinh Nguyen wrote:
> On Fri, Mar 14, 2025, Mike Looijmans wrote:
>> Set the gpio to "high" on acquisition, instead of acquiring it in low
>> state and then immediately setting it high again. This prevents a
>> short "spike" on the reset signal.
> How does this affect the current programming flow beside preventing a
> spike to the reset signal?

I don't understand your question. What "programming flow" are you 
referring to?

The reset sequence was just plain wrong, the issue is almost the same as 
the one described in this commit:
e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"

Note that I see this high-low-high-low double reset toggle in many 
Xilinx software drivers, they seem to teach that at the Xilinx academy 
or so.


>> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
>> ---
>>
>>   drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
>>   1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
>> index a33a42ba0249..a159a511483b 100644
>> --- a/drivers/usb/dwc3/dwc3-xilinx.c
>> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
>> @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>>   
>>   skip_usb3_phy:
>>   	/* ulpi reset via gpio-modepin or gpio-framework driver */
>> -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>> +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>>   	if (IS_ERR(reset_gpio)) {
>>   		return dev_err_probe(dev, PTR_ERR(reset_gpio),
>>   				     "Failed to request reset GPIO\n");
>> @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>>   
>>   	if (reset_gpio) {
>>   		/* Toggle ulpi to reset the phy. */
> Does the comment above still apply?
Now you mention it, the comment never made any sense anyway.


>> -		gpiod_set_value_cansleep(reset_gpio, 1);
>>   		usleep_range(5000, 10000);
> Do we still need this usleep_range here?

Yes, this is the "reset active" time.



>
> BR,
> Thinh
>
>>   		gpiod_set_value_cansleep(reset_gpio, 0);
>>   		usleep_range(5000, 10000);
>> -- 
>> 2.43.0
>>
>>
>> Met vriendelijke groet / kind regards,
>>
>> Mike Looijmans
>>
>>

-- 
Mike Looijmans
System Expert

TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl





From quic_tdas at quicinc.com  Sun Mar 16 23:34:17 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Mon, 17 Mar 2025 12:04:17 +0530
Subject: [PATCH v6 06/10] dt-bindings: clock: Add Qualcomm QCS615 Graphics
 clock controller
In-Reply-To: <5tt4wli2yodoet2l6r7ksq3o743nmi75hfksakqaxre3gmyr2a@zdotamju5ndp>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-6-ebf4b9a5e916@quicinc.com>
 <20250313-graceful-jackdaw-of-opportunity-62996d@krzk-bin>
 <d1814cd9-5c73-4ac5-a4ed-4cc2aae410d0@quicinc.com>
 <5tt4wli2yodoet2l6r7ksq3o743nmi75hfksakqaxre3gmyr2a@zdotamju5ndp>
Message-ID: <523b6f39-41b7-41cd-b793-7b768cc71064@quicinc.com>



On 3/14/2025 4:47 AM, Bjorn Andersson wrote:
> On Thu, Mar 13, 2025 at 02:18:57PM +0530, Taniya Das wrote:
>>
>>
>> On 3/13/2025 1:54 PM, Krzysztof Kozlowski wrote:
>>> On Thu, Mar 13, 2025 at 12:29:43PM +0530, Taniya Das wrote:
>>>  +
>>>> +  '#reset-cells':
>>>> +    const: 1
>>>> +
>>>> +  '#power-domain-cells':
>>>> +    const: 1
>>>> +
>>>> +required:
>>>> +  - compatible
>>>> +  - reg
>>>> +  - clocks
>>>> +  - '#clock-cells'
>>>> +  - '#reset-cells'
>>>> +  - '#power-domain-cells'
>>>> +
>>>
>>> I don't get why this binding is different than others and you do not
>>> reference qcom,gcc.yaml? Is it not applicable here? Other gpucc do
>>> reference.
>>>
>>
>> Yes, I will fix them and resend.
>>
> 
> What is it that you will fix and resend? This patch or all other cases?
> 
> Please stop just throwing stuff at the list and until something sticks,
> talk with the people who review your patches.
> 

Bjorn, I will fix all of them in the series and send out.

> Regards,
> Bjorn
> 
>>>
>>> Best regards,
>>> Krzysztof
>>>
>>



From quic_tdas at quicinc.com  Sun Mar 16 23:40:13 2025
From: quic_tdas at quicinc.com (Taniya Das)
Date: Mon, 17 Mar 2025 12:10:13 +0530
Subject: [PATCH v6 01/10] clk: qcom: clk-alpha-pll: Add support for
 dynamic update for slewing PLLs
In-Reply-To: <r6xikx2idlzwc4xl7doap3v5ug3a6qtg65jwqjuekiv7tvbwzn@5nk4c7nl2zws>
References: <20250313-qcs615-v5-mm-cc-v6-0-ebf4b9a5e916@quicinc.com>
 <20250313-qcs615-v5-mm-cc-v6-1-ebf4b9a5e916@quicinc.com>
 <r6xikx2idlzwc4xl7doap3v5ug3a6qtg65jwqjuekiv7tvbwzn@5nk4c7nl2zws>
Message-ID: <fce2fe9e-5c1b-4fa9-b6ca-0a4ab5133e5a@quicinc.com>



On 3/14/2025 5:09 AM, Bjorn Andersson wrote:
> On Thu, Mar 13, 2025 at 12:29:38PM +0530, Taniya Das wrote:
>> The alpha PLLs which slew to a new frequency at runtime would require
>> the PLL to calibrate at the mid point of the VCO. Add the new PLL ops
>> which can support the slewing of the PLL to a new frequency.
>>
>> Reviewed-by: Imran Shaik <quic_imrashai at quicinc.com>
>> Signed-off-by: Taniya Das <quic_tdas at quicinc.com>
>> ---
>>  drivers/clk/qcom/clk-alpha-pll.c | 170 +++++++++++++++++++++++++++++++++++++++
>>  drivers/clk/qcom/clk-alpha-pll.h |   1 +
>>  2 files changed, 171 insertions(+)
>>
>> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
>> index cec0afea8e446010f0d4140d4ef63121706dde47..7d784db8b7441e886d94ded1d3e3258dda46674c 100644
>> --- a/drivers/clk/qcom/clk-alpha-pll.c
>> +++ b/drivers/clk/qcom/clk-alpha-pll.c
>> @@ -2960,3 +2960,173 @@ const struct clk_ops clk_alpha_pll_regera_ops = {
>>  	.set_rate = clk_zonda_pll_set_rate,
>>  };
>>  EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops);
>> +
>> +static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll)
>> +{
>> +	int ret;
>> +	u32 val;
>> +
>> +	regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, PLL_UPDATE);
>> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
>> +
>> +	ret = wait_for_pll_update(pll);
>> +	if (ret)
>> +		return ret;
>> +	/*
>> +	 * Hardware programming mandates a wait of at least 570ns before polling the LOCK
>> +	 * detect bit. Have a delay of 1us just to be safe.
>> +	 */
>> +	mb();
>> +	udelay(1);
>> +
>> +	return wait_for_pll_enable_lock(pll);
>> +}
>> +
>> +static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate,
>> +					unsigned long parent_rate)
>> +{
>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>> +	unsigned long freq_hz;
>> +	const struct pll_vco *curr_vco, *vco;
>> +	u32 l, alpha_width = pll_alpha_width(pll);
>> +	u64 a;
>> +
>> +	freq_hz =  alpha_pll_round_rate(rate, parent_rate, &l, &a, alpha_width);
> 
> Double space here.

Sure, needs a fix.

> 
>> +	if (freq_hz != rate) {
>> +		pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	curr_vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
>> +	if (!curr_vco) {
>> +		pr_err("alpha pll: not in a valid vco range\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	vco = alpha_pll_find_vco(pll, freq_hz);
>> +	if (!vco) {
>> +		pr_err("alpha pll: not in a valid vco range\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/*
>> +	 * Dynamic pll update will not support switching frequencies across
>> +	 * vco ranges. In those cases fall back to normal alpha set rate.
>> +	 */
>> +	if (curr_vco->val != vco->val)
>> +		return clk_alpha_pll_set_rate(hw, rate, parent_rate);
>> +
>> +	a = a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
> 
> Above this function is written to deal with both alpha bitwidths, but
> here it's assumed to only be one of the cases.
> 
> It would be nice to get this cleaned up somehow, because we now have
> this shift 6 times in slightly different forms.
> 

I will check if I can clean up.

>> +
>> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
> 
> In a number of places in the driver alpha_width is compared to 32 bits
> to see if this should be written or not. Perhaps that's not applicable
> here, but again, if so then why is it dynamic above?
> 
> 
> Also, how about upper_32_bits() and lower_32_bits() to make it clear
> what's going on here?
> 

Sure.


>> +
>> +	/* Ensure that the write above goes through before proceeding. */
> 
> That's not what mb() does.
> 
> Regards,
> Bjorn
> 
>> +	mb();
>> +
>> +	if (clk_hw_is_enabled(hw))
>> +		return clk_alpha_pll_slew_update(pll);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Slewing plls should be bought up at frequency which is in the middle of the
>> + * desired VCO range. So after bringing up the pll at calibration freq, set it
>> + * back to desired frequency(that was set by previous clk_set_rate).
>> + */
>> +static int clk_alpha_pll_calibrate(struct clk_hw *hw)
>> +{
>> +	unsigned long calibration_freq, freq_hz;
>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>> +	struct clk_hw *parent;
>> +	const struct pll_vco *vco;
>> +	u32 l, alpha_width = pll_alpha_width(pll);
>> +	int rc;
>> +	u64 a;
>> +
>> +	parent = clk_hw_get_parent(hw);
>> +	if (!parent) {
>> +		pr_err("alpha pll: no valid parent found\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
>> +	if (!vco) {
>> +		pr_err("alpha pll: not in a valid vco range\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/*
>> +	 * As during slewing plls vco_sel won't be allowed to change, vco table
>> +	 * should have only one entry table, i.e. index = 0, find the
>> +	 * calibration frequency.
>> +	 */
>> +	calibration_freq = (pll->vco_table[0].min_freq + pll->vco_table[0].max_freq) / 2;
>> +
>> +	freq_hz = alpha_pll_round_rate(calibration_freq, clk_hw_get_rate(parent),
>> +					&l, &a, alpha_width);
>> +	if (freq_hz != calibration_freq) {
>> +		pr_err("alpha_pll: call clk_set_rate with rounded rates!\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Setup PLL for calibration frequency */
>> +	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
>> +
>> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
>> +
>> +	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_VCO_MASK << PLL_VCO_SHIFT,
>> +				vco->val << PLL_VCO_SHIFT);
>> +
>> +	/* Bringup the pll at calibration frequency */
>> +	rc = clk_alpha_pll_enable(hw);
>> +	if (rc) {
>> +		pr_err("alpha pll calibration failed\n");
>> +		return rc;
>> +	}
>> +
>> +	/*
>> +	 * PLL is already running at calibration frequency.
>> +	 * So slew pll to the previously set frequency.
>> +	 */
>> +	freq_hz = alpha_pll_round_rate(clk_hw_get_rate(hw),
>> +			clk_hw_get_rate(parent), &l, &a, alpha_width);
>> +
>> +	pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n",
>> +		clk_hw_get_name(hw), clk_hw_get_rate(hw), freq_hz);
>> +
>> +	/* Setup the PLL for the new frequency */
>> +	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
>> +
>> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
>> +
>> +	regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_ALPHA_EN, PLL_ALPHA_EN);
>> +
>> +	return clk_alpha_pll_slew_update(pll);
>> +}
>> +
>> +static int clk_alpha_pll_slew_enable(struct clk_hw *hw)
>> +{
>> +	int rc;
>> +
>> +	rc = clk_alpha_pll_calibrate(hw);
>> +	if (rc)
>> +		return rc;
>> +
>> +	return clk_alpha_pll_enable(hw);
>> +}
>> +
>> +const struct clk_ops clk_alpha_pll_slew_ops = {
>> +	.enable = clk_alpha_pll_slew_enable,
>> +	.disable = clk_alpha_pll_disable,
>> +	.recalc_rate = clk_alpha_pll_recalc_rate,
>> +	.round_rate = clk_alpha_pll_round_rate,
>> +	.set_rate = clk_alpha_pll_slew_set_rate,
>> +};
>> +EXPORT_SYMBOL(clk_alpha_pll_slew_ops);
>> diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
>> index 79aca8525262211ae5295245427d4540abf1e09a..1d19001605eb10fd8ae8041c56d951e928cbbe9f 100644
>> --- a/drivers/clk/qcom/clk-alpha-pll.h
>> +++ b/drivers/clk/qcom/clk-alpha-pll.h
>> @@ -204,6 +204,7 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
>>  #define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
>>  
>>  extern const struct clk_ops clk_alpha_pll_regera_ops;
>> +extern const struct clk_ops clk_alpha_pll_slew_ops;
>>  
>>  void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
>>  			     const struct alpha_pll_config *config);
>>
>> -- 
>> 2.48.1
>>



From radhey.shyam.pandey at amd.com  Sun Mar 16 23:48:26 2025
From: radhey.shyam.pandey at amd.com (Pandey, Radhey Shyam)
Date: Mon, 17 Mar 2025 06:48:26 +0000
Subject: [PATCH] dmaengine: xilinx_dma: Set dma_device directions
In-Reply-To: <20250314134849.703819-1-thomas.gessler@brueckmann-gmbh.de>
References: <20250314134849.703819-1-thomas.gessler@brueckmann-gmbh.de>
Message-ID: <MN0PR12MB59531CAA16616476F2E09EFBB7DF2@MN0PR12MB5953.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>
> Sent: Friday, March 14, 2025 7:19 PM
> To: dmaengine at vger.kernel.org
> Cc: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>; Vinod Koul
> <vkoul at kernel.org>; Simek, Michal <michal.simek at amd.com>; Marek Vasut
> <marex at denx.de>; Pandey, Radhey Shyam <radhey.shyam.pandey at amd.com>;
> Uwe Kleine-K?nig <u.kleine-koenig at baylibre.com>; linux-arm-
> kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: [PATCH] dmaengine: xilinx_dma: Set dma_device directions
>
> Coalesce the direction bits from the enabled TX and/or RX channels into
> the directions bit mask of dma_device. Without this mask set,
> dma_get_slave_caps() in the DMAEngine fails, which prevents the driver
> from being used with an IIO DMAEngine buffer.
>
> Signed-off-by: Thomas Gessler <thomas.gessler at brueckmann-gmbh.de>

Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey at amd.com>
Thanks!

> ---
>  drivers/dma/xilinx/xilinx_dma.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 108a7287f4cd..641aaf0c0f1c 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -3205,6 +3205,10 @@ static int xilinx_dma_probe(struct platform_device
> *pdev)
>               }
>       }
>
> +     for (i = 0; i < xdev->dma_config->max_channels; i++)
> +             if (xdev->chan[i])
> +                     xdev->common.directions |= xdev->chan[i]->direction;
> +
>       if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
>               for (i = 0; i < xdev->dma_config->max_channels; i++)
>                       if (xdev->chan[i])
> --
> 2.43.0



From amadeus at jmu.edu.cn  Mon Mar 17 00:00:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Mon, 17 Mar 2025 15:00:02 +0800
Subject: [PATCH 3/7] pinctrl: rockchip: Add support for RK3528
In-Reply-To: <20250228064024.3200000-4-jonas@kwiboo.se>
References: <20250228064024.3200000-4-jonas@kwiboo.se>
Message-ID: <20250317070002.707674-1-amadeus@jmu.edu.cn>

Hi,

> Add gpio and pinctrl support for the 5 GPIO banks on RK3528.

https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/blob/rk3528/drivers/pinctrl/rockchip/pinctrl-rk3528.c#L204-L207

I noticed that there is a little difference between u-boot and kernel
pinctrl driver. Does kernel need to sync this changes from u-boot?

```
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 930c454e0cec..c77d9a6cd535 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -3070,6 +3070,7 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
 
 	data >>= bit;
 	switch (ctrl->type) {
+	case RK3528:
 	case RK3562:
 	case RK3568:
 		return data & ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1);
@@ -3100,6 +3101,7 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
 
 	/* enable the write to the equivalent lower bits */
 	switch (ctrl->type) {
+	case RK3528:
 	case RK3562:
 	case RK3568:
 		data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
```

Thanks,
Chukun

--
2.25.1



From mazziesaccount at gmail.com  Mon Mar 17 00:11:08 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 09:11:08 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <20250316094112.6731bd01@jic23-huawei>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQ0O34EUM8WZku@smile.fi.intel.com> <20250316094112.6731bd01@jic23-huawei>
Message-ID: <50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>

On 16/03/2025 11:41, Jonathan Cameron wrote:
> On Thu, 13 Mar 2025 14:34:24 +0200
> Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:
> 
>> On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
>>> The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
>>> help drivers avoid open-coding the for_each_node -loop for getting the
>>> channel IDs. The helper provides standard way to detect the ADC channel
>>> nodes (by the node name), and a standard way to convert the "reg"
>>> -properties to channel identification numbers, used in the struct
>>> iio_chan_spec. Furthermore, the helper can optionally check the found
>>> channel IDs are smaller than given maximum. This is useful for callers
>>> which later use the IDs for example for indexing a channel data array.
>>>
>>> The original driver treated all found child nodes as channel nodes. The
>>> new helper requires channel nodes to be named channel[@N]. This should
>>> help avoid problems with devices which may contain also other but ADC
>>> child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
>>> string didn't reveal any in-tree .dts with channel nodes named
>>> otherwise. Also, same grep shows all the in-tree .dts seem to have
>>> channel IDs between 0..num of channels.
>>>
>>> Use the new helper.
>>
>> ...
>>
>>> +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
>>> +				&sun20i_gpadc_chan_template, -1, &channels);
>>> +	if (num_channels < 0)
>>> +		return num_channels;
>>> +
>>>   	if (num_channels == 0)
>>>   		return dev_err_probe(dev, -ENODEV, "no channel children\n");
>>
>> Note, this what I would expected in your helper to see, i.e. separated cases
>> for < 0 (error code) and == 0, no channels.
>>
>> Also, are all users going to have this check? Usually in other similar APIs
>> we return -ENOENT. And user won't need to have an additional check in case of
>> 0 being considered as an error case too.
> In a few cases we'll need to do the dance the other way in the caller.
> So specifically check for -ENOENT and not treat it as an error.
> 
> That stems from channel nodes being optionally added to drivers after
> they have been around a while (usually to add more specific configuration)
> and needing to maintain old behaviour of presenting all channels with default
> settings.
> 
> I agree that returning -ENOENT is a reasonable way to handle this.

I agree - but I'm going to use -ENODEV instead of -ENOENT because that's 
what the current callers return if they find no channels. That way the 
drivers can return the value directly without converting -ENOENT to -ENODEV.

Yours,
	-- Matti


From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:55 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:55 +0800
Subject: [PATCH 4/7] dt-bindings: serial: amlogic,meson-uart: Add
 compatible string for S6/S7/S7D
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-4-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Amlogic S6/S7/7D SoCs uses the same UART controller as S4 SoCs and G12A.
There is no need for an extra compatible line in the driver, but
add S6/S7/S7D compatible line for documentation.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
index 0565fb7649c5..d8ad1bb6172d 100644
--- a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
@@ -56,6 +56,9 @@ properties:
         items:
           - enum:
               - amlogic,a4-uart
+              - amlogic,s6-uart
+              - amlogic,s7-uart
+              - amlogic,s7d-uart
               - amlogic,t7-uart
           - const: amlogic,meson-s4-uart
 

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:56 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:56 +0800
Subject: [PATCH 5/7] arm64: dts: add support for S6 based Amlogic BL209
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-5-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Amlogic S6 is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Add basic support for the S6 based Amlogic BL209 board, which describes
the following components: CPU, GIC, IRQ, Timer and UART.
These are capable of booting up into the serial console.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../boot/dts/amlogic/amlogic-s6-s905x5-bl209.dts   | 42 ++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s6.dtsi        | 97 ++++++++++++++++++++++
 3 files changed, 140 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 2fbda8419c65..a1ad8fa9999f 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_MESON) += amlogic-a4-a113l2-ba400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-a5-a113x2-av400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c308l-aw419.dtb
+dtb-$(CONFIG_ARCH_MESON) += amlogic-s6-s905x5-bl209.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-an400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-khadas-vim4.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s6-s905x5-bl209.dts b/arch/arm64/boot/dts/amlogic/amlogic-s6-s905x5-bl209.dts
new file mode 100644
index 000000000000..c45b22651798
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s6-s905x5-bl209.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "amlogic-s6.dtsi"
+/ {
+	model = "Amlogic S905X5 BL209 Development Board";
+	compatible = "amlogic,bl209", "amlogic,s6";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart_b;
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x000000 0x0 0xe0000000>,
+		      <0x1 0x000000 0x0 0x20000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 27 MiB reserved for ARM Trusted Firmware */
+		secmon_reserved: secmon at 5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x0 0x05000000 0x0 0x1b00000>;
+			no-map;
+		};
+	};
+};
+
+&uart_b {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s6.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-s6.dtsi
new file mode 100644
index 000000000000..a8c90245c42a
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s6.dtsi
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+/ {
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at ff200000 {
+			compatible = "arm,gic-v3";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xff200000 0 0x10000>,
+			      <0x0 0xff240000 0 0x80000>;
+			interrupts = <GIC_PPI 9 0xf04>;
+		};
+
+		apb: bus at fe000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xfe000000 0x0 0x480000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
+
+			uart_b: serial at 7a000 {
+				compatible = "amlogic,s6-uart",
+					     "amlogic,meson-s4-uart";
+				reg = <0x0 0x7a000 0x0 0x18>;
+				interrupts = <GIC_SPI 169 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>, <&xtal>, <&xtal>;
+				clock-names = "xtal", "pclk", "baud";
+				status = "disabled";
+			};
+		};
+	};
+};

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:51 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:51 +0800
Subject: [PATCH 0/7] Baisc devicetree support for Amlogic S6 S7 and S7D
Message-ID: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>

Amlogic S6 S7 and S7D are application processors designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Add the new S6 SoC/board device tree bindings.
Add the new S7 SoC/board device tree bindings.
Add the new S7D SoC/board device tree bindings.

Add basic support for the S6 based Amlogic BL209 board, which describes
the following components: CPU, GIC, IRQ, Timer and UART. These are capable of
booting up into the serial console.

Add basic support for the S7 based Amlogic BP201 board, which describes
the following components: CPU, GIC, IRQ, Timer and UART. These are capable of
booting up into the serial console.

Add basic support for the S7D based Amlogic BM202 board, which describes
the following components: CPU, GIC, IRQ, Timer and UART. These are capable of
booting up into the serial console.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Xianwei Zhao (7):
      dt-bindings: arm: amlogic: add S6 support
      dt-bindings: arm: amlogic: add S7 support
      dt-bindings: arm: amlogic: add S7D support
      dt-bindings: serial: amlogic,meson-uart: Add compatible string for S6/S7/S7D
      arm64: dts: add support for S6 based Amlogic BL209
      arm64: dts: add support for S7 based Amlogic BP201
      arm64: dts: add support for S7D based Amlogic BM202

 Documentation/devicetree/bindings/arm/amlogic.yaml | 18 ++++
 .../bindings/serial/amlogic,meson-uart.yaml        |  3 +
 arch/arm64/boot/dts/amlogic/Makefile               |  3 +
 .../boot/dts/amlogic/amlogic-s6-s905x5-bl209.dts   | 42 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s6.dtsi        | 97 +++++++++++++++++++++
 .../boot/dts/amlogic/amlogic-s7-s805x3-bp201.dts   | 41 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s7.dtsi        | 99 ++++++++++++++++++++++
 .../boot/dts/amlogic/amlogic-s7d-s905x5m-bm202.dts | 41 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s7d.dtsi       | 99 ++++++++++++++++++++++
 9 files changed, 443 insertions(+)
---
base-commit: 73e4ffb27bb8a093d557bb2dac1a271474cca99c
change-id: 20250221-s6-s7-basic-f300c30877e6

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:54 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:54 +0800
Subject: [PATCH 3/7] dt-bindings: arm: amlogic: add S7D support
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-3-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Document the new S7D SoC/board device tree bindings.

Amlogic S7D is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 9a6e98b55685..0c84c56855ba 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -249,6 +249,12 @@ properties:
               - amlogic,bp201
           - const: amlogic,s7
 
+      - description: Boards with the Amlogic S7D S905X5M SoC
+        items:
+          - enum:
+              - amlogic,bm202
+          - const: amlogic,s7d
+
       - description: Boards with the Amlogic T7 A311D2 SoC
         items:
           - enum:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:53 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:53 +0800
Subject: [PATCH 2/7] dt-bindings: arm: amlogic: add S7 support
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-2-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Document the new S7 SoC/board device tree bindings.

Amlogic S7 is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 67423c838719..9a6e98b55685 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -243,6 +243,12 @@ properties:
               - amlogic,bl209
           - const: amlogic,s6
 
+      - description: Boards with the Amlogic S7 S805X3 SoC
+        items:
+          - enum:
+              - amlogic,bp201
+          - const: amlogic,s7
+
       - description: Boards with the Amlogic T7 A311D2 SoC
         items:
           - enum:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:58 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:58 +0800
Subject: [PATCH 7/7] arm64: dts: add support for S7D based Amlogic BM202
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-7-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Amlogic S7D is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Add basic support for the S7D based Amlogic BM202 board, Reusing
S7 basic components: CPU, GIC, IRQ, Timer and UART.
These are capable of booting up into the serial console.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../boot/dts/amlogic/amlogic-s7d-s905x5m-bm202.dts | 41 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s7d.dtsi       | 99 ++++++++++++++++++++++
 3 files changed, 141 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 29e1c7b9ee31..8c16c22c7b8e 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c308l-aw419.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-s6-s905x5-bl209.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-s7-s805x3-bp201.dtb
+dtb-$(CONFIG_ARCH_MESON) += amlogic-s7d-s905x5m-bm202.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-an400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-khadas-vim4.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s7d-s905x5m-bm202.dts b/arch/arm64/boot/dts/amlogic/amlogic-s7d-s905x5m-bm202.dts
new file mode 100644
index 000000000000..2933fcdbc8ef
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s7d-s905x5m-bm202.dts
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "amlogic-s7d.dtsi"
+/ {
+	model = "Amlogic S905X5M BM202 Development Board";
+	compatible = "amlogic,bm202", "amlogic,s7d";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart_b;
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 36 MiB reserved for ARM Trusted Firmware */
+		secmon_reserved: secmon at 5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x0 0x05000000 0x0 0x2400000>;
+			no-map;
+		};
+	};
+};
+
+&uart_b {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s7d.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-s7d.dtsi
new file mode 100644
index 000000000000..e1099bc1535d
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s7d.dtsi
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+		};
+
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at fff01000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xfff01000 0 0x1000>,
+			      <0x0 0xfff02000 0 0x0100>;
+			interrupts = <GIC_PPI 9 0xf04>;
+		};
+
+		apb: bus at fe000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xfe000000 0x0 0x480000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
+
+			uart_b: serial at 7a000 {
+				compatible = "amlogic,s7d-uart",
+					     "amlogic,meson-s4-uart";
+				reg = <0x0 0x7a000 0x0 0x18>;
+				interrupts = <GIC_SPI 169 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>, <&xtal>, <&xtal>;
+				clock-names = "xtal", "pclk", "baud";
+				status = "disabled";
+			};
+		};
+	};
+};

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:52 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:52 +0800
Subject: [PATCH 1/7] dt-bindings: arm: amlogic: add S6 support
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-1-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Document the new S6 SoC/board device tree bindings.

Amlogic S6 is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 0647851ae1f5..67423c838719 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -237,6 +237,12 @@ properties:
               - amlogic,aq222
           - const: amlogic,s4
 
+      - description: Boards with the Amlogic S6 S905X5 SoC
+        items:
+          - enum:
+              - amlogic,bl209
+          - const: amlogic,s6
+
       - description: Boards with the Amlogic T7 A311D2 SoC
         items:
           - enum:

-- 
2.37.1




From devnull+xianwei.zhao.amlogic.com at kernel.org  Mon Mar 17 00:16:57 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Mon, 17 Mar 2025 15:16:57 +0800
Subject: [PATCH 6/7] arm64: dts: add support for S7 based Amlogic BP201
In-Reply-To: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
Message-ID: <20250317-s6-s7-basic-v1-6-d653384e41f3@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Amlogic S7 is an advanced application processor designed for
hybrid OTT/IP Set Top Box and high-end media box applications.

Add basic support for the S7 based Amlogic BP201 board, which describes
the following components: CPU, GIC, IRQ, Timer and UART.
These are capable of booting up into the serial console.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../boot/dts/amlogic/amlogic-s7-s805x3-bp201.dts   | 41 +++++++++
 arch/arm64/boot/dts/amlogic/amlogic-s7.dtsi        | 99 ++++++++++++++++++++++
 3 files changed, 141 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index a1ad8fa9999f..29e1c7b9ee31 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_MESON) += amlogic-a5-a113x2-av400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c308l-aw419.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-s6-s905x5-bl209.dtb
+dtb-$(CONFIG_ARCH_MESON) += amlogic-s7-s805x3-bp201.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-an400.dtb
 dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-khadas-vim4.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s7-s805x3-bp201.dts b/arch/arm64/boot/dts/amlogic/amlogic-s7-s805x3-bp201.dts
new file mode 100644
index 000000000000..7fd4ac9321a6
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s7-s805x3-bp201.dts
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "amlogic-s7.dtsi"
+/ {
+	model = "Amlogic S805X3 BP201 Development Board";
+	compatible = "amlogic,bp201", "amlogic,s7";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart_b;
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 35 MiB reserved for ARM Trusted Firmware */
+		secmon_reserved: secmon at 5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x0 0x05000000 0x0 0x2300000>;
+			no-map;
+		};
+	};
+};
+
+&uart_b {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-s7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-s7.dtsi
new file mode 100644
index 000000000000..f0c172681bd1
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-s7.dtsi
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Amlogic, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a55";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+		};
+
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at fff01000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xfff01000 0 0x1000>,
+			      <0x0 0xfff02000 0 0x0100>;
+			interrupts = <GIC_PPI 9 0xf04>;
+		};
+
+		apb: bus at fe000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xfe000000 0x0 0x480000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
+
+			uart_b: serial at 7a000 {
+				compatible = "amlogic,s7-uart",
+					     "amlogic,meson-s4-uart";
+				reg = <0x0 0x7a000 0x0 0x18>;
+				interrupts = <GIC_SPI 169 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>, <&xtal>, <&xtal>;
+				clock-names = "xtal", "pclk", "baud";
+				status = "disabled";
+			};
+		};
+	};
+};

-- 
2.37.1




From krzk at kernel.org  Mon Mar 17 00:28:45 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 08:28:45 +0100
Subject: [PATCH v4 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <3dceafbf-49d4-4084-bfae-74384e187941@amlogic.com>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
 <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>
 <20250314-tested-husky-of-force-1ccdca@krzk-bin>
 <3dceafbf-49d4-4084-bfae-74384e187941@amlogic.com>
Message-ID: <4cec908c-1412-4e18-959d-b71c9ec21eb4@kernel.org>

On 17/03/2025 03:49, Kelvin Zhang wrote:
>>
>> Why do you have on the bus devices with bus addressing and without it?
>> What sort of bus is it?
> 
> Are you referring to the 'apb'?
> If so, the 'apb' bus is defined in 
> arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi.
> 
> apb: bus at fe000000 {
>          compatible = "simple-bus";
>          reg = <0x0 0xfe000000 0x0 0x480000>;
>          #address-cells = <2>;
>          #size-cells = <2>;
>          ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
> 
>>
>>>        periphs_pinctrl: pinctrl {

Then what the heck is this?

>>>                compatible = "amlogic,pinctrl-a4";
>>>                #address-cells = <2>;
>>
>> Best regards,
>> Krzysztof
>>
> 


Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 17 00:32:19 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 08:32:19 +0100
Subject: [net-next 3/4] dt-bindings: net: ftgmac100: add rgmii delay
 properties
In-Reply-To: <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
Message-ID: <0d5cf176-f084-467b-b4a1-9a1f862d0781@kernel.org>

On 17/03/2025 03:59, Jacky Chou wrote:
> Add tx-internal-delay-ps and rx-internal-delay-ps to

Please wrap code according to the preferred limit expressed in Kernel
coding style (checkpatch is not a coding style description, but only a
tool).  However don't wrap blindly (see Kernel coding style).

> configure the RGMII delay for MAC. According to
> ethernet-controller.yaml, they use for RGMII TX and RX delay.
> 
> In Aspeed desgin, the RGMII delay is a number of ps as unit to
> set delay, do not use one ps as unit. The values are different
> from each MAC. So, here describes the property values
> as index to configure corresponding scu register.
> 
> Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
> ---

...

>    mdio:
>      $ref: /schemas/net/mdio.yaml#
>  
> @@ -102,4 +116,4 @@ examples:
>                  reg = <1>;
>              };
>          };
> -    };
> +    };
> \ No newline at end of file


This was neither tested nor reviewed by you before sending.


Best regards,
Krzysztof


From neil.armstrong at linaro.org  Mon Mar 17 00:34:49 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 08:34:49 +0100
Subject: [PATCH v4 0/4] Add GPIO interrupt support for Amlogic A4 and A5
 SoCs
In-Reply-To: <87h64022hz.ffs@tglx>
References: <20250307-irqchip-gpio-a4-a5-v4-0-d03a9424151b@amlogic.com>
 <87h64022hz.ffs@tglx>
Message-ID: <0475a736-92bc-4cf8-be89-d8161fed5075@linaro.org>

Hi,

On 10/03/2025 18:56, Thomas Gleixner wrote:
> On Fri, Mar 07 2025 at 16:49, Xianwei Zhao via wrote:
>> Xianwei Zhao (4):
>>        dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
>>        irqchip: Add support for Amlogic A4 and A5 SoCs
>>        arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
>>        arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
>>
>>   .../amlogic,meson-gpio-intc.yaml                   | 19 ++++++++-
>>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 19 +++++++++
>>   arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 ++++++
>>   drivers/irqchip/irq-meson-gpio.c                   | 45 +++++++++++++++++-----
> 
> I can't take that through the irqchip tree as the amlogic dtsi files are
> new and in Neil's for-next branch.
> 
> Neil, feel free to pick the lot up, I don't have conflicting changes for
> that driver sitting in my tree. I'll reply to the irqchip patch seperately.

Ack, I'll pick the whole serie in my tree.

Thx,
Neil

> 
> Thanks,
> 
>          tglx



From m.szyprowski at samsung.com  Mon Mar 17 00:37:04 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 17 Mar 2025 08:37:04 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
	<e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
	<CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
	<9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
	<417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
	<bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
	<016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
	<b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>
Message-ID: <cdc333e4-25bb-4171-9f6e-01f1de947db3@samsung.com>

On 13.03.2025 15:12, Robin Murphy wrote:
> On 2025-03-13 1:06 pm, Robin Murphy wrote:
>> On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
>>> On 13.03.2025 12:01, Robin Murphy wrote:
>>>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>>>> [...]
>>>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my 
>>>>> tests I
>>>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>>>> relevant kernel log:
>>>>
>>>> ...and the bug-flushing-out begins!
>>>>
>>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>>> 00000000000003e8
>>>>> Mem abort info:
>>>>> ?? ? ESR = 0x0000000096000004
>>>>> ?? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>>> ?? ? SET = 0, FnV = 0
>>>>> ?? ? EA = 0, S1PTW = 0
>>>>> ?? ? FSC = 0x04: level 0 translation fault
>>>>> Data abort info:
>>>>> ?? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>>> ?? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>>> ?? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>>> [00000000000003e8] user address but active_mm is swapper
>>>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>>>> Modules linked in:
>>>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>> pc : devm_kmalloc+0x2c/0x114
>>>>> lr : rk_iommu_of_xlate+0x30/0x90
>>>>> ...
>>>>> Call trace:
>>>>> ?? ?devm_kmalloc+0x2c/0x114 (P)
>>>>> ?? ?rk_iommu_of_xlate+0x30/0x90
>>>>
>>>> Yeah, looks like this is doing something a bit questionable which 
>>>> can't
>>>> work properly. TBH the whole dma_dev thing could probably be 
>>>> cleaned up
>>>> now that we have proper instances, but for now does this work?
>>>
>>> Yes, this patch fixes the problem I've observed.
>>>
>>> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>
>>> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver 
>>> and
>>> I doubt it can be cleaned up.
>>
>> On the contrary I suspect they both can - it all dates back to when 
>> we had the single global platform bus iommu_ops and the SoC drivers 
>> were forced to bodge their own notion of multiple instances, but with 
>> the modern core code, ops are always called via a valid IOMMU 
>> instance or domain, so in principle it should always be possible to 
>> get at an appropriate IOMMU device now. IIRC it was mostly about 
>> allocating and DMA-mapping the pagetables in domain_alloc, where the 
>> private notion of instances didn't have enough information, but 
>> domain_alloc_paging solves that.
>
> Bah, in fact I think I am going to have to do that now, since although 
> it doesn't crash, rk_domain_alloc_paging() will also be failing for 
> the same reason. Time to find a PSU for the RK3399 board, I guess...
>
> (Or maybe just move the dma_dev assignment earlier to match Exynos?)

Well I just found that Exynos IOMMU is also broken on some on my test 
boards. It looks that the runtime pm links are somehow not correctly 
established. I will try to analyze this later in the afternoon.


Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From jens.wiklander at linaro.org  Mon Mar 17 00:42:01 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Mon, 17 Mar 2025 08:42:01 +0100
Subject: [PATCH v6 03/10] optee: account for direction while converting parameters
In-Reply-To: <Z9K2RQYuXSJc8Y1E@sumit-X1>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org> <Z9K2RQYuXSJc8Y1E@sumit-X1>
Message-ID: <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com>

Hi Sumit,

On Thu, Mar 13, 2025 at 11:41?AM Sumit Garg <sumit.garg at kernel.org> wrote:
>
> Hi Jens,
>
> On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> > The OP-TEE backend driver has two internal function pointers to convert
> > between the subsystem type struct tee_param and the OP-TEE type struct
> > optee_msg_param.
> >
> > The conversion is done from one of the types to the other, which is then
> > involved in some operation and finally converted back to the original
> > type. When converting to prepare the parameters for the operation, all
> > fields must be taken into account, but then converting back, it's enough
> > to update only out-values and out-sizes. So, an update_out parameter is
> > added to the conversion functions to tell if all or only some fields
> > must be copied.
> >
> > This is needed in a later patch where it might get confusing when
> > converting back in from_msg_param() callback since an allocated
> > restricted SHM can be using the sec_world_id of the used restricted
> > memory pool and that doesn't translate back well.
> >
> > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > ---
> >  drivers/tee/optee/call.c          | 10 ++--
> >  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
> >  drivers/tee/optee/optee_private.h | 42 +++++++++++------
> >  drivers/tee/optee/rpc.c           | 31 +++++++++----
> >  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
> >  5 files changed, 144 insertions(+), 58 deletions(-)
> >
> > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > index 16eb953e14bb..f1533b894726 100644
> > --- a/drivers/tee/optee/call.c
> > +++ b/drivers/tee/optee/call.c
> > @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
> >       export_uuid(msg_arg->params[1].u.octets, &client_uuid);
> >
> >       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> > -                                   arg->num_params, param);
> > +                                   arg->num_params, param,
> > +                                   false /*!update_out*/);
> >       if (rc)
> >               goto out;
> >
> > @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
> >       }
> >
> >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > -                                    msg_arg->params + 2)) {
> > +                                    msg_arg->params + 2,
> > +                                    true /*update_out*/)) {
> >               arg->ret = TEEC_ERROR_COMMUNICATION;
> >               arg->ret_origin = TEEC_ORIGIN_COMMS;
> >               /* Close session again to avoid leakage */
> > @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> >       msg_arg->cancel_id = arg->cancel_id;
> >
> >       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> > -                                   param);
> > +                                   param, false /*!update_out*/);
> >       if (rc)
> >               goto out;
> >
> > @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> >       }
> >
> >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > -                                    msg_arg->params)) {
> > +                                    msg_arg->params, true /*update_out*/)) {
> >               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
> >               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
> >       }
> > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > index 4ca1d5161b82..e4b08cd195f3 100644
> > --- a/drivers/tee/optee/ffa_abi.c
> > +++ b/drivers/tee/optee/ffa_abi.c
> > @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
> >   */
> >
> >  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > -                                u32 attr, const struct optee_msg_param *mp)
> > +                                u32 attr, const struct optee_msg_param *mp,
> > +                                bool update_out)
> >  {
> >       struct tee_shm *shm = NULL;
> >       u64 offs_high = 0;
> >       u64 offs_low = 0;
> >
> > +     if (update_out) {
> > +             if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> > +                     return;
> > +             goto out;
> > +     }
> > +
> >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> >                 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> > -     p->u.memref.size = mp->u.fmem.size;
> >
> >       if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
> >               shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> > @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> >               offs_high = mp->u.fmem.offs_high;
> >       }
> >       p->u.memref.shm_offs = offs_low | offs_high << 32;
> > +out:
> > +     p->u.memref.size = mp->u.fmem.size;
> >  }
> >
> >  /**
> > @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> >   * @params:  subsystem internal parameter representation
> >   * @num_params:      number of elements in the parameter arrays
> >   * @msg_params:      OPTEE_MSG parameters
> > + * @update_out: update parameter for output only
> >   *
> >   * Returns 0 on success or <0 on failure
> >   */
> >  static int optee_ffa_from_msg_param(struct optee *optee,
> >                                   struct tee_param *params, size_t num_params,
> > -                                 const struct optee_msg_param *msg_params)
> > +                                 const struct optee_msg_param *msg_params,
> > +                                 bool update_out)
> >  {
> >       size_t n;
> >
> > @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> >
> >               switch (attr) {
> >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > +                     if (update_out)
> > +                             break;
> >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> >                       memset(&p->u, 0, sizeof(p->u));
> >                       break;
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > -                     optee_from_msg_param_value(p, attr, mp);
> > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> >                       break;
> >               case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
> >               case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
> >               case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> > -                     from_msg_param_ffa_mem(optee, p, attr, mp);
> > +                     from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
> >                       break;
> >               default:
> >                       return -EINVAL;
> > @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> >  }
> >
> >  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > -                             const struct tee_param *p)
> > +                             const struct tee_param *p, bool update_out)
> >  {
> >       struct tee_shm *shm = p->u.memref.shm;
> >
> > +     if (update_out) {
> > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > +                     return 0;
> > +             goto out;
> > +     }
> > +
> >       mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
> >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> >
> > @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> >               memset(&mp->u, 0, sizeof(mp->u));
> >               mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
> >       }
> > +out:
> >       mp->u.fmem.size = p->u.memref.size;
> >
> >       return 0;
> > @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> >   * @optee:   main service struct
> >   * @msg_params:      OPTEE_MSG parameters
> >   * @num_params:      number of elements in the parameter arrays
> > - * @params:  subsystem itnernal parameter representation
> > + * @params:  subsystem internal parameter representation
> > + * @update_out: update parameter for output only
> >   * Returns 0 on success or <0 on failure
> >   */
> >  static int optee_ffa_to_msg_param(struct optee *optee,
> >                                 struct optee_msg_param *msg_params,
> >                                 size_t num_params,
> > -                               const struct tee_param *params)
> > +                               const struct tee_param *params,
> > +                               bool update_out)
> >  {
> >       size_t n;
> >
> > @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
> >
> >               switch (p->attr) {
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > +                     if (update_out)
> > +                             break;
> >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> >                       memset(&mp->u, 0, sizeof(mp->u));
> >                       break;
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > -                     optee_to_msg_param_value(mp, p);
> > +                     optee_to_msg_param_value(mp, p, update_out);
> >                       break;
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > -                     if (to_msg_param_ffa_mem(mp, p))
> > +                     if (to_msg_param_ffa_mem(mp, p, update_out))
> >                               return -EINVAL;
> >                       break;
> >               default:
>
> Can we rather handle it as follows to improve code readability and
> maintainence long term? Ditto for all other places.
>
> static int optee_ffa_to_msg_param(struct optee *optee,
>                                   struct optee_msg_param *msg_params,
>                                   size_t num_params,
>                                   const struct tee_param *params,
>                                   bool update_out)
> {
>         size_t n;
>
>         for (n = 0; n < num_params; n++) {
>                 const struct tee_param *p = params + n;
>                 struct optee_msg_param *mp = msg_params + n;
>
>                 if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
>                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
>                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
>                     continue;

You're missing updating the length field for memrefs.

Cheers,
Jens

>
>                 switch (p->attr) {
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
>                         mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
>                         memset(&mp->u, 0, sizeof(mp->u));
>                         break;
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
>                         optee_to_msg_param_value(mp, p);
>                         break;
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
>                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
>                         if (to_msg_param_ffa_mem(mp, p))
>                                 return -EINVAL;
>                         break;
>                 default:
>                         return -EINVAL;
>                 }
>         }
>
>         return 0;
> }
>
> -Sumit
>
> > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > index dc0f355ef72a..20eda508dbac 100644
> > --- a/drivers/tee/optee/optee_private.h
> > +++ b/drivers/tee/optee/optee_private.h
> > @@ -185,10 +185,12 @@ struct optee_ops {
> >                               bool system_thread);
> >       int (*to_msg_param)(struct optee *optee,
> >                           struct optee_msg_param *msg_params,
> > -                         size_t num_params, const struct tee_param *params);
> > +                         size_t num_params, const struct tee_param *params,
> > +                         bool update_out);
> >       int (*from_msg_param)(struct optee *optee, struct tee_param *params,
> >                             size_t num_params,
> > -                           const struct optee_msg_param *msg_params);
> > +                           const struct optee_msg_param *msg_params,
> > +                           bool update_out);
> >  };
> >
> >  /**
> > @@ -316,23 +318,35 @@ void optee_release(struct tee_context *ctx);
> >  void optee_release_supp(struct tee_context *ctx);
> >
> >  static inline void optee_from_msg_param_value(struct tee_param *p, u32 attr,
> > -                                           const struct optee_msg_param *mp)
> > +                                           const struct optee_msg_param *mp,
> > +                                           bool update_out)
> >  {
> > -     p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
> > -               attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> > -     p->u.value.a = mp->u.value.a;
> > -     p->u.value.b = mp->u.value.b;
> > -     p->u.value.c = mp->u.value.c;
> > +     if (!update_out)
> > +             p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
> > +                       attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> > +
> > +     if (attr == OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT ||
> > +         attr == OPTEE_MSG_ATTR_TYPE_VALUE_INOUT || !update_out) {
> > +             p->u.value.a = mp->u.value.a;
> > +             p->u.value.b = mp->u.value.b;
> > +             p->u.value.c = mp->u.value.c;
> > +     }
> >  }
> >
> >  static inline void optee_to_msg_param_value(struct optee_msg_param *mp,
> > -                                         const struct tee_param *p)
> > +                                         const struct tee_param *p,
> > +                                         bool update_out)
> >  {
> > -     mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
> > -                TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
> > -     mp->u.value.a = p->u.value.a;
> > -     mp->u.value.b = p->u.value.b;
> > -     mp->u.value.c = p->u.value.c;
> > +     if (!update_out)
> > +             mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
> > +                        TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
> > +
> > +     if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
> > +         p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || !update_out) {
> > +             mp->u.value.a = p->u.value.a;
> > +             mp->u.value.b = p->u.value.b;
> > +             mp->u.value.c = p->u.value.c;
> > +     }
> >  }
> >
> >  void optee_cq_init(struct optee_call_queue *cq, int thread_count);
> > diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
> > index ebbbd42b0e3e..580e6b9b0606 100644
> > --- a/drivers/tee/optee/rpc.c
> > +++ b/drivers/tee/optee/rpc.c
> > @@ -63,7 +63,7 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
> >       }
> >
> >       if (optee->ops->from_msg_param(optee, params, arg->num_params,
> > -                                    arg->params))
> > +                                    arg->params, false /*!update_out*/))
> >               goto bad;
> >
> >       for (i = 0; i < arg->num_params; i++) {
> > @@ -107,7 +107,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
> >       } else {
> >               params[3].u.value.a = msg.len;
> >               if (optee->ops->to_msg_param(optee, arg->params,
> > -                                          arg->num_params, params))
> > +                                          arg->num_params, params,
> > +                                          true /*update_out*/))
> >                       arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               else
> >                       arg->ret = TEEC_SUCCESS;
> > @@ -188,6 +189,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
> >  static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
> >                               struct optee_msg_arg *arg)
> >  {
> > +     bool update_out = false;
> >       struct tee_param *params;
> >
> >       arg->ret_origin = TEEC_ORIGIN_COMMS;
> > @@ -200,15 +202,21 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
> >       }
> >
> >       if (optee->ops->from_msg_param(optee, params, arg->num_params,
> > -                                    arg->params)) {
> > +                                    arg->params, update_out)) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               goto out;
> >       }
> >
> >       arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
> >
> > +     /*
> > +      * Special treatment for OPTEE_RPC_CMD_SHM_ALLOC since input is a
> > +      * value type, but the output is a memref type.
> > +      */
> > +     if (arg->cmd != OPTEE_RPC_CMD_SHM_ALLOC)
> > +             update_out = true;
> >       if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
> > -                                  params))
> > +                                  params, update_out))
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >  out:
> >       kfree(params);
> > @@ -270,7 +278,7 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
> >
> >       if (arg->num_params != ARRAY_SIZE(params) ||
> >           optee->ops->from_msg_param(optee, params, arg->num_params,
> > -                                    arg->params) ||
> > +                                    arg->params, false /*!update_out*/) ||
> >           params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               return;
> > @@ -280,7 +288,8 @@ static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
> >       params[0].u.value.b = 0;
> >       params[0].u.value.c = 0;
> >       if (optee->ops->to_msg_param(optee, arg->params,
> > -                                  arg->num_params, params)) {
> > +                                  arg->num_params, params,
> > +                                  true /*update_out*/)) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               return;
> >       }
> > @@ -324,7 +333,7 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
> >
> >       if (arg->num_params != ARRAY_SIZE(params) ||
> >           optee->ops->from_msg_param(optee, params, arg->num_params,
> > -                                    arg->params) ||
> > +                                    arg->params, false /*!update_out*/) ||
> >           params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
> >           params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> > @@ -358,7 +367,8 @@ static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
> >       params[0].u.value.b = rdev->descr.capacity;
> >       params[0].u.value.c = rdev->descr.reliable_wr_count;
> >       if (optee->ops->to_msg_param(optee, arg->params,
> > -                                  arg->num_params, params)) {
> > +                                  arg->num_params, params,
> > +                                  true /*update_out*/)) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               return;
> >       }
> > @@ -384,7 +394,7 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
> >
> >       if (arg->num_params != ARRAY_SIZE(params) ||
> >           optee->ops->from_msg_param(optee, params, arg->num_params,
> > -                                    arg->params) ||
> > +                                    arg->params, false /*!update_out*/) ||
> >           params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
> >           params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> > @@ -401,7 +411,8 @@ static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
> >               goto out;
> >       }
> >       if (optee->ops->to_msg_param(optee, arg->params,
> > -                                  arg->num_params, params)) {
> > +                                  arg->num_params, params,
> > +                                  true /*update_out*/)) {
> >               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >               goto out;
> >       }
> > diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> > index 165fadd9abc9..cfdae266548b 100644
> > --- a/drivers/tee/optee/smc_abi.c
> > +++ b/drivers/tee/optee/smc_abi.c
> > @@ -81,20 +81,26 @@ static int optee_cpuhp_disable_pcpu_irq(unsigned int cpu)
> >   */
> >
> >  static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
> > -                               const struct optee_msg_param *mp)
> > +                               const struct optee_msg_param *mp,
> > +                               bool update_out)
> >  {
> >       struct tee_shm *shm;
> >       phys_addr_t pa;
> >       int rc;
> >
> > +     if (update_out) {
> > +             if (attr == OPTEE_MSG_ATTR_TYPE_TMEM_INPUT)
> > +                     return 0;
> > +             goto out;
> > +     }
> > +
> >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> >                 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
> > -     p->u.memref.size = mp->u.tmem.size;
> >       shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
> >       if (!shm) {
> >               p->u.memref.shm_offs = 0;
> >               p->u.memref.shm = NULL;
> > -             return 0;
> > +             goto out;
> >       }
> >
> >       rc = tee_shm_get_pa(shm, 0, &pa);
> > @@ -103,18 +109,25 @@ static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
> >
> >       p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
> >       p->u.memref.shm = shm;
> > -
> > +out:
> > +     p->u.memref.size = mp->u.tmem.size;
> >       return 0;
> >  }
> >
> >  static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
> > -                                const struct optee_msg_param *mp)
> > +                                const struct optee_msg_param *mp,
> > +                                bool update_out)
> >  {
> >       struct tee_shm *shm;
> >
> > +     if (update_out) {
> > +             if (attr == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT)
> > +                     return;
> > +             goto out;
> > +     }
> > +
> >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> >                 attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
> > -     p->u.memref.size = mp->u.rmem.size;
> >       shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
> >
> >       if (shm) {
> > @@ -124,6 +137,8 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
> >               p->u.memref.shm_offs = 0;
> >               p->u.memref.shm = NULL;
> >       }
> > +out:
> > +     p->u.memref.size = mp->u.rmem.size;
> >  }
> >
> >  /**
> > @@ -133,11 +148,13 @@ static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
> >   * @params:  subsystem internal parameter representation
> >   * @num_params:      number of elements in the parameter arrays
> >   * @msg_params:      OPTEE_MSG parameters
> > + * @update_out:      update parameter for output only
> >   * Returns 0 on success or <0 on failure
> >   */
> >  static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
> >                               size_t num_params,
> > -                             const struct optee_msg_param *msg_params)
> > +                             const struct optee_msg_param *msg_params,
> > +                             bool update_out)
> >  {
> >       int rc;
> >       size_t n;
> > @@ -149,25 +166,27 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
> >
> >               switch (attr) {
> >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > +                     if (update_out)
> > +                             break;
> >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> >                       memset(&p->u, 0, sizeof(p->u));
> >                       break;
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > -                     optee_from_msg_param_value(p, attr, mp);
> > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> >                       break;
> >               case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
> >               case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
> >               case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
> > -                     rc = from_msg_param_tmp_mem(p, attr, mp);
> > +                     rc = from_msg_param_tmp_mem(p, attr, mp, update_out);
> >                       if (rc)
> >                               return rc;
> >                       break;
> >               case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
> >               case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
> >               case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
> > -                     from_msg_param_reg_mem(p, attr, mp);
> > +                     from_msg_param_reg_mem(p, attr, mp, update_out);
> >                       break;
> >
> >               default:
> > @@ -178,20 +197,25 @@ static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
> >  }
> >
> >  static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
> > -                             const struct tee_param *p)
> > +                             const struct tee_param *p, bool update_out)
> >  {
> >       int rc;
> >       phys_addr_t pa;
> >
> > +     if (update_out) {
> > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > +                     return 0;
> > +             goto out;
> > +     }
> > +
> >       mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
> >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> >
> >       mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
> > -     mp->u.tmem.size = p->u.memref.size;
> >
> >       if (!p->u.memref.shm) {
> >               mp->u.tmem.buf_ptr = 0;
> > -             return 0;
> > +             goto out;
> >       }
> >
> >       rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
> > @@ -201,19 +225,27 @@ static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
> >       mp->u.tmem.buf_ptr = pa;
> >       mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
> >                   OPTEE_MSG_ATTR_CACHE_SHIFT;
> > -
> > +out:
> > +     mp->u.tmem.size = p->u.memref.size;
> >       return 0;
> >  }
> >
> >  static int to_msg_param_reg_mem(struct optee_msg_param *mp,
> > -                             const struct tee_param *p)
> > +                             const struct tee_param *p, bool update_out)
> >  {
> > +     if (update_out) {
> > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > +                     return 0;
> > +             goto out;
> > +     }
> > +
> >       mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
> >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> >
> >       mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
> > -     mp->u.rmem.size = p->u.memref.size;
> >       mp->u.rmem.offs = p->u.memref.shm_offs;
> > +out:
> > +     mp->u.rmem.size = p->u.memref.size;
> >       return 0;
> >  }
> >
> > @@ -223,11 +255,13 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
> >   * @msg_params:      OPTEE_MSG parameters
> >   * @num_params:      number of elements in the parameter arrays
> >   * @params:  subsystem itnernal parameter representation
> > + * @update_out:      update parameter for output only
> >   * Returns 0 on success or <0 on failure
> >   */
> >  static int optee_to_msg_param(struct optee *optee,
> >                             struct optee_msg_param *msg_params,
> > -                           size_t num_params, const struct tee_param *params)
> > +                           size_t num_params, const struct tee_param *params,
> > +                           bool update_out)
> >  {
> >       int rc;
> >       size_t n;
> > @@ -238,21 +272,23 @@ static int optee_to_msg_param(struct optee *optee,
> >
> >               switch (p->attr) {
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > +                     if (update_out)
> > +                             break;
> >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> >                       memset(&mp->u, 0, sizeof(mp->u));
> >                       break;
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > -                     optee_to_msg_param_value(mp, p);
> > +                     optee_to_msg_param_value(mp, p, update_out);
> >                       break;
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> >                       if (tee_shm_is_dynamic(p->u.memref.shm))
> > -                             rc = to_msg_param_reg_mem(mp, p);
> > +                             rc = to_msg_param_reg_mem(mp, p, update_out);
> >                       else
> > -                             rc = to_msg_param_tmp_mem(mp, p);
> > +                             rc = to_msg_param_tmp_mem(mp, p, update_out);
> >                       if (rc)
> >                               return rc;
> >                       break;
> > --
> > 2.43.0
> >


From krzk at kernel.org  Mon Mar 17 00:45:52 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 08:45:52 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
Message-ID: <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>

On 05/03/2025 10:35, Ryan Chen wrote:
>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>> AST2600-i2cv2
>>
>> On 27/02/2025 09:19, Ryan Chen wrote:
>>>>
>>>>
>>>>> aspeed,enable-byte:
>>>>> Force i2c controller use byte mode transfer. the byte mode transfer
>>>>> will send i2c data each byte by byte, inlcude address read/write.
>>>>
>>>> Isn't this standard FIFO mode?
>>> Yes, it is.
>>>>
>>>> Why anyone would need to enable byte mode for given board?
>>> By default, it is buffer-mode, for performance, I don't want user enable
>> byte-mode, it will increase CPU utilize.
>>> But someone want to be force enable byte-mode, so I add properties.
>>> https://patchwork.ozlabs.org/project/linux-aspeed/patch/20241007035235
>>> .2254138-3-ryan_chen at aspeedtech.com/
>>
>>
>> I don't see the reason why this would be a board property.
>>
>> I understood need for DMA because it is shared and only some of the
>> controllers can use it. But why choice between buffer and FIFO depending on
>> hardware?
> 
> By default, the I2C controller runs in buffer mode. Each i2c bus have 16bytes buffer to transmit data.
> Enabling byte mode will increases CPU utilization, so it is not recommended. 
> However, some user might require forcing byte mode, so I added this property to allow that.


You are not answering the question. I asked why the choice depends on
hardware and you answer "user might required".

Do you understand that this is about hardware, not user choices?


>>
>>
>>>>
>>>>>
>>>>>>
>>>>>>> +      may require a DTS to manually allocate which controller can
>>>>>>> + use
>>>>>> DMA mode.
>>>>>>> +      The "aspeed,enable-dma" property allows control of this.
>>>>>>> +
>>>>>>> +      In cases where one the hardware design results in a specific
>>>>>>> +      controller handling a larger amount of data, a DTS would likely
>>>>>>> +      enable DMA mode for that one controller.
>>>>>>> +
>>>>>>> +  aspeed,enable-byte:
>>>>>>> +    type: boolean
>>>>>>> +    description: |
>>>>>>> +      I2C bus enable byte mode transfer.
>>>>>>
>>>>>> No, either this is expressed as lack of dma mode property or if you
>>>>>> have three modes, then rather some enum (aspeed,transfer-mode ?)
>>>>>
>>>>> Thanks suggestion, I will using an enum property like
>>>>> aspeed,transfer-mode
>>>> instead.
>>>>>>
>>>>>>
>>>>>>
>>>>>>> +
>>>>>>> +  aspeed,global-regs:
>>>>>>> +    $ref: /schemas/types.yaml#/definitions/phandle
>>>>>>> +    description: The phandle of i2c global register node.
>>>>>>
>>>>>> For what? Same question as usual: do not repeat property name, but
>>>>>> say what is this used for and what exactly it points to.
>>>>>>
>>>>>> s/i2c/I2C/ but then what is "I2C global register node"? This is how
>>>>>> you call your device in datasheet?
>>>>>>
>>>>> I do descript in cover, should add into the yaml file ?
>>>>
>>>>
>>>> Again, cover letter does not matter. Your hardware must be explained here.
>>> Will add into commit.
>>>>
>>>>>
>>>>> aspeed,global-regs:
>>>>> This global register is needed, global register is setting for new
>>>>> clock divide control, and new register set control.
>>>>
>>>> So this means you implement clock controller via syscon?
>>> No, it is just mode switch. It also explain in cover. I will add it in commit.
>>> The legacy register layout is mix controller/target register control together.
>> The following is add more detail description about new register layout. And
>> new feature set add for register.
>>>>
>>>>>
>>>>>>
>>>>>>> +
>>>>>>>  required:
>>>>>>>    - reg
>>>>>>>    - compatible
>>>>>>>    - clocks
>>>>>>>    - resets
>>>>>>>
>>>>>>> +allOf:
>>>>>>> +  - $ref: /schemas/i2c/i2c-controller.yaml#
>>>>>>> +  - if:
>>>>>>> +      properties:
>>>>>>> +        compatible:
>>>>>>> +          contains:
>>>>>>> +            const: aspeed,ast2600-i2cv2
>>>>>>
>>>>>> NAK, undocumented compatible.
>>>>>
>>>>> Sorry, I should add what kind of document about this compatible?
>>>>
>>>> You cannot add new compatibles without documenting them.
>>>> Documentation is in the form of DT schema and each compatible must be
>>>> listed (in some
>>>> way) in compatible property description.
>>>
>>> Sorry, do you mean, I add following in yaml or commit message?
>>
>> You need to list this in compatibles first.
> 
> I will add it in compatible in next submit.
> 
> 	enum:
> 		-aspeed,ast2600-i2cv2
>>
>>>
>>> This series add AST2600 i2cv2 new register set driver. The i2cv2 driver is new
>> register set that have new clock divider option for more flexiable generation.
>> And also have separate i2c controller and target register set for control, patch
>> #2 is i2c controller driver only, patch #3 is add i2c target mode driver.
>>
>> All this describes driver, not hardware.
> 
> Sorry, the cover letter description the register. I will add int in commit message.
> 
> -Add new clock divider option for more flexible and accurate clock rate
> generation -Add tCKHighMin timing to guarantee SCL high pulse width.
> -Add support dual pool buffer mode, split 32 bytes pool buffer of each
> device into 2 x 16 bytes for Tx and Rx individually.
> -Increase DMA buffer size to 4096 bytes and support byte alignment.
> -Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
> -Re-define registers for separating controller and target mode control.
> -Support 4 individual DMA buffers for controller Tx and Rx,
> target Tx and Rx.
> 
> And following is new register set for package transfer sequence.
> -New Master operation mode:
>  S -> Aw -> P
>  S -> Aw -> TxD -> P
>  S -> Ar -> RxD -> P
>  S -> Aw -> RxD -> Sr -> Ar -> TxD -> P
> -Bus SDA lock auto-release capability for new controller DMA command mode.
> -Bus auto timeout for new controller/target DMA mode.
> 
> The following is two versus register layout.
> Old:
> {I2CD00}: Function Control Register
> {I2CD04}: Clock and AC Timing Control Register
> {I2CD08}: Clock and AC Timing Control Register
> {I2CD0C}: Interrupt Control Register
> {I2CD10}: Interrupt Status Register
> {I2CD14}: Command/Status Register
> {I2CD18}: Slave Device Address Register
> {I2CD1C}: Pool Buffer Control Register
> {I2CD20}: Transmit/Receive Byte Buffer Register
> {I2CD24}: DMA Mode Buffer Address Register
> {I2CD28}: DMA Transfer Length Register
> {I2CD2C}: Original DMA Mode Buffer Address Setting
> {I2CD30}: Original DMA Transfer Length Setting and Final Status
> 
> New Register mode
> {I2CC00}: Master/Slave Function Control Register
> {I2CC04}: Master/Slave Clock and AC Timing Control Register
> {I2CC08}: Master/Slave Transmit/Receive Byte Buffer Register
> {I2CC0C}: Master/Slave Pool Buffer Control Register
> {I2CM10}: Master Interrupt Control Register
> {I2CM14}: Master Interrupt Status Register
> {I2CM18}: Master Command/Status Register
> {I2CM1C}: Master DMA Buffer Length Register
> {I2CS20}: Slave~ Interrupt Control Register
> {I2CS24}: Slave~ Interrupt Status Register
> {I2CS28}: Slave~ Command/Status Register
> {I2CS2C}: Slave~ DMA Buffer Length Register
> {I2CM30}: Master DMA Mode Tx Buffer Base Address
> {I2CM34}: Master DMA Mode Rx Buffer Base Address
> {I2CS38}: Slave~ DMA Mode Tx Buffer Base Address
> {I2CS3C}: Slave~ DMA Mode Rx Buffer Base Address
> {I2CS40}: Slave Device Address Register
> {I2CM48}: Master DMA Length Status Register
> {I2CS4C}: Slave  DMA Length Status Register
> {I2CC50}: Current DMA Operating Address Status
> {I2CC54}: Current DMA Operating Length  Status

I don't understand anything from that and how is this relevant to our
discussion.

> 
>>
>>>
>>> The legacy register layout is mix controller/target register control together.
>> The following is add more detail description about new register layout. And
>> new feature set add for register.
>>>
>>> -Add new clock divider option for more flexible and accurate clock rate
>> generation -Add tCKHighMin timing to guarantee SCL high pulse width.
>>> -Add support dual pool buffer mode, split 32 bytes pool buffer of each device
>> into 2 x 16 bytes for Tx and Rx individually.
>>> -Increase DMA buffer size to 4096 bytes and support byte alignment.
>>> -Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
>>> -Re-define registers for separating controller and target mode control.
>>> -Support 4 individual DMA buffers for controller Tx and Rx, target Tx and Rx.
>>
>> Does it mean hardware changed on AST2600? 
> No Hw change, it is different mode setting will have another mode register setting.
> Mode setting is in global register, I will add in next commit message

Neither this.

So it seems you describe already existing and documented I2C, but for
some reason you want second compatible. The problem is that you do not
provide reason from the point of view of bindings.

To summarize: what your users want - don't care. Start properly
describing hardware and your SoC.


> 
> I2CG00: Device Master Mode Interrupt Status Register (I2CG0C[3]=1)
> I2CG00: Device Master/Slave Mode Interrupt Status Register (I2CG0C[3]=0)
> I2CG04: Device Slave Mode Interrupt Status Register
> I2CG0C: Global Control Register
> I2CG10: New Clock Divider Control Register (I2CG0C[1] = 1)
> 
>> Or these are different devices
>> than aspeed,ast2600-i2c-bus? If this is not a different device, how one SoC can
>> have two different flavors of same device in the same instance?
> 
> When global setting for new, will new register mapping, no setting will keep old register mapping.


I cannot parse this.


Best regards,
Krzysztof


From neil.armstrong at linaro.org  Mon Mar 17 00:44:03 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 08:44:03 +0100
Subject: (subset) [PATCH v5 0/4] Add GPIO interrupt support for Amlogic
 A4 and A5 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <174219744301.3089961.6347213266646956468.b4-ty@linaro.org>

Hi,

On Tue, 11 Mar 2025 11:08:26 +0800, Xianwei Zhao wrote:
> This patch adds GPIO interrupt support for Amlogic A4 and A5 SoCs
> 
> 

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.15/drivers)

[1/4] dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
      https://git.kernel.org/amlogic/c/40f4152442f72748ce883ca53ca80961e433701c
[2/4] irqchip: Add support for Amlogic A4 and A5 SoCs
      https://git.kernel.org/amlogic/c/bbd6fcc76b39502767e213ad24a349205cf75e96

These changes has been applied on the intermediate git tree [1].

The v6.15/drivers branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From neil.armstrong at linaro.org  Mon Mar 17 00:45:25 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 08:45:25 +0100
Subject: (subset) [PATCH v5 0/4] Add GPIO interrupt support for Amlogic
 A4 and A5 SoCs
In-Reply-To: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
References: <20250311-irqchip-gpio-a4-a5-v5-0-ca4cc276c18c@amlogic.com>
Message-ID: <174219752573.3092000.16919170480596322661.b4-ty@linaro.org>

Hi,

On Tue, 11 Mar 2025 11:08:26 +0800, Xianwei Zhao wrote:
> This patch adds GPIO interrupt support for Amlogic A4 and A5 SoCs
> 
> 

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.15/arm64-dt)

[3/4] arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
      https://git.kernel.org/amlogic/c/31c6bc1948b5a0a0d7679cf948351156608ec148
[4/4] arm64: dts: Add gpio_intc node for Amlogic A5 SoCs
      https://git.kernel.org/amlogic/c/454e0353b226a47f3c3369b17c7a4893f74e29cd

These changes has been applied on the intermediate git tree [1].

The v6.15/arm64-dt branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From krzk at kernel.org  Mon Mar 17 00:48:03 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 08:48:03 +0100
Subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
 mode driver
In-Reply-To: <Z8GuOT5bJL7CdXX6@smile.fi.intel.com>
References: <20250224055936.1804279-3-ryan_chen@aspeedtech.com>
 <202502280902.U0gLDhve-lkp@intel.com> <Z8GuOT5bJL7CdXX6@smile.fi.intel.com>
Message-ID: <fec0a1c8-251b-491e-893d-11a8186a2128@kernel.org>

On 28/02/2025 13:38, Andy Shevchenko wrote:
> On Fri, Feb 28, 2025 at 09:28:59AM +0800, kernel test robot wrote:
>> Hi Ryan,
>>
>> kernel test robot noticed the following build warnings:
>>
>> [auto build test WARNING on andi-shyti/i2c/i2c-host]
>> [also build test WARNING on linus/master v6.14-rc4 next-20250227]
>> [If your patch is applied to the wrong git tree, kindly drop us a note.
>> And when submitting patch, we suggest to use '--base' as documented in
>> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>>
>> url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-i2c-aspeed-support-for-AST2600-i2cv2/20250224-140221
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git i2c/i2c-host
>> patch link:    https://lore.kernel.org/r/20250224055936.1804279-3-ryan_chen%40aspeedtech.com
>> patch subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register mode driver
>> config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gLDhve-lkp at intel.com/config)
>> compiler: mips-linux-gcc (GCC) 14.2.0
>> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gLDhve-lkp at intel.com/reproduce)
>>
>> If you fix the issue in a separate patch/commit (i.e. not just a new version of
>> the same patch/commit), kindly add following tags
>> | Reported-by: kernel test robot <lkp at intel.com>
>> | Closes: https://lore.kernel.org/oe-kbuild-all/202502280902.U0gLDhve-lkp at intel.com/
>>
>> All warnings (new ones prefixed by >>):
> 
> My gosh, this is valid report. But it looks like a preexisted issue.
> Can somebody fix this, please?


That was three weeks ago and still no responses from Aspeed or
contributors from here.

I think this tells a lot about aspeedtech.com patchsets on the list.

Best regards,
Krzysztof


From andriy.shevchenko at linux.intel.com  Mon Mar 17 00:51:54 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 17 Mar 2025 09:51:54 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQ0O34EUM8WZku@smile.fi.intel.com>
 <20250316094112.6731bd01@jic23-huawei>
 <50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>
Message-ID: <Z9fUmo5wp3EcNWzm@smile.fi.intel.com>

On Mon, Mar 17, 2025 at 09:11:08AM +0200, Matti Vaittinen wrote:
> On 16/03/2025 11:41, Jonathan Cameron wrote:
> > On Thu, 13 Mar 2025 14:34:24 +0200
> > Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:
> > > On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:

...

> > > > +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
> > > > +				&sun20i_gpadc_chan_template, -1, &channels);
> > > > +	if (num_channels < 0)
> > > > +		return num_channels;
> > > > +
> > > >   	if (num_channels == 0)
> > > >   		return dev_err_probe(dev, -ENODEV, "no channel children\n");
> > > 
> > > Note, this what I would expected in your helper to see, i.e. separated cases
> > > for < 0 (error code) and == 0, no channels.
> > > 
> > > Also, are all users going to have this check? Usually in other similar APIs
> > > we return -ENOENT. And user won't need to have an additional check in case of
> > > 0 being considered as an error case too.
> > In a few cases we'll need to do the dance the other way in the caller.
> > So specifically check for -ENOENT and not treat it as an error.
> > 
> > That stems from channel nodes being optionally added to drivers after
> > they have been around a while (usually to add more specific configuration)
> > and needing to maintain old behaviour of presenting all channels with default
> > settings.
> > 
> > I agree that returning -ENOENT is a reasonable way to handle this.
> 
> I agree - but I'm going to use -ENODEV instead of -ENOENT because that's
> what the current callers return if they find no channels. That way the
> drivers can return the value directly without converting -ENOENT to -ENODEV.

ENODEV can be easily clashed with other irrelevant cases, ENOENT is the correct
error code. If drivers return this instead of another error code, nothing bad
happen, it's not an ABI path, correct?

-- 
With Best Regards,
Andy Shevchenko




From peter.griffin at linaro.org  Mon Mar 17 00:57:30 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Mon, 17 Mar 2025 07:57:30 +0000
Subject: [PATCH 0/2] Add dma-coherent for gs101 UFS dt node
In-Reply-To: <0d7a8cad-adfc-4cac-bcc6-65d1f9c86b43@acm.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org> <0d7a8cad-adfc-4cac-bcc6-65d1f9c86b43@acm.org>
Message-ID: <CADrjBPrU1Prw9NmWrVQff+X6VTY4PXEr_BH2Z0DuAr=uiaOsGQ@mail.gmail.com>

Hi Bart,

Thanks for the review.

On Fri, 14 Mar 2025 at 16:01, Bart Van Assche <bvanassche at acm.org> wrote:
>
> On 3/14/25 8:38 AM, Peter Griffin wrote:
> > ufs-exynos driver enables the shareability option for gs101 which
> > means the descriptors need to be allocated as cacheable.
>
> Shouldn't that code be modified such that the shareability option is
> only set if the dma-coherent property is present in the device tree?

Yes, I plan to add an extra patch that does what you describe into the
v2 of the UFS fixes series [1] likely later today.

I sent this out separately for Krzysztof's Exynos DT tree in the hope
he will pick it up in the next -rc as this patch fixes how the driver
is configured today, and is also still the configuration we want once
the driver changes land. I should have made that a bit clearer in the
cover letter :)

Thanks,

Peter

[1] https://lore.kernel.org/linux-scsi/20250226220414.343659-1-peter.griffin at linaro.org/


From andriy.shevchenko at linux.intel.com  Mon Mar 17 01:00:04 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 17 Mar 2025 10:00:04 +0200
Subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
 mode driver
In-Reply-To: <fec0a1c8-251b-491e-893d-11a8186a2128@kernel.org>
References: <20250224055936.1804279-3-ryan_chen@aspeedtech.com>
 <202502280902.U0gLDhve-lkp@intel.com>
 <Z8GuOT5bJL7CdXX6@smile.fi.intel.com>
 <fec0a1c8-251b-491e-893d-11a8186a2128@kernel.org>
Message-ID: <Z9fWhGDrUbAmGRl0@smile.fi.intel.com>

On Mon, Mar 17, 2025 at 08:48:03AM +0100, Krzysztof Kozlowski wrote:
> On 28/02/2025 13:38, Andy Shevchenko wrote:
> > On Fri, Feb 28, 2025 at 09:28:59AM +0800, kernel test robot wrote:
> >> Hi Ryan,
> >>
> >> kernel test robot noticed the following build warnings:
> >>
> >> [auto build test WARNING on andi-shyti/i2c/i2c-host]
> >> [also build test WARNING on linus/master v6.14-rc4 next-20250227]
> >> [If your patch is applied to the wrong git tree, kindly drop us a note.
> >> And when submitting patch, we suggest to use '--base' as documented in
> >> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> >>
> >> url:    https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-i2c-aspeed-support-for-AST2600-i2cv2/20250224-140221
> >> base:   https://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git i2c/i2c-host
> >> patch link:    https://lore.kernel.org/r/20250224055936.1804279-3-ryan_chen%40aspeedtech.com
> >> patch subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register mode driver
> >> config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gLDhve-lkp at intel.com/config)
> >> compiler: mips-linux-gcc (GCC) 14.2.0
> >> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gLDhve-lkp at intel.com/reproduce)
> >>
> >> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> >> the same patch/commit), kindly add following tags
> >> | Reported-by: kernel test robot <lkp at intel.com>
> >> | Closes: https://lore.kernel.org/oe-kbuild-all/202502280902.U0gLDhve-lkp at intel.com/
> >>
> >> All warnings (new ones prefixed by >>):
> > 
> > My gosh, this is valid report. But it looks like a preexisted issue.
> > Can somebody fix this, please?
> 
> 
> That was three weeks ago and still no responses from Aspeed or
> contributors from here.
> 
> I think this tells a lot about aspeedtech.com patchsets on the list.

Yeah...

-- 
With Best Regards,
Andy Shevchenko




From jonas at kwiboo.se  Mon Mar 17 01:01:25 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 17 Mar 2025 09:01:25 +0100
Subject: [PATCH 3/7] pinctrl: rockchip: Add support for RK3528
In-Reply-To: <20250317070002.707674-1-amadeus@jmu.edu.cn>
References: <20250228064024.3200000-4-jonas@kwiboo.se>
 <20250317070002.707674-1-amadeus@jmu.edu.cn>
Message-ID: <da550920-bb2e-4032-82a9-1bf02aae9e17@kwiboo.se>

Hi Chukun,

On 2025-03-17 08:00, Chukun Pan wrote:
> Hi,
> 
>> Add gpio and pinctrl support for the 5 GPIO banks on RK3528.
> 
> https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/blob/rk3528/drivers/pinctrl/rockchip/pinctrl-rk3528.c#L204-L207
> 
> I noticed that there is a little difference between u-boot and kernel
> pinctrl driver. Does kernel need to sync this changes from u-boot?

RK3568_SCHMITT_BITS_PER_PIN is defined as 2 and RK3528_SMT_BITS_PER_PIN
as 1 so I think this code is correct, however I can probably update the
U-Boot code to use similar pattern as in Linux driver before sending a
new revision of the U-Boot series (probably after v6.15-rc1-dts).

Regards,
Jonas

> 
> ```
> diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
> index 930c454e0cec..c77d9a6cd535 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.c
> +++ b/drivers/pinctrl/pinctrl-rockchip.c
> @@ -3070,6 +3070,7 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
>  
>  	data >>= bit;
>  	switch (ctrl->type) {
> +	case RK3528:
>  	case RK3562:
>  	case RK3568:
>  		return data & ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1);
> @@ -3100,6 +3101,7 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
>  
>  	/* enable the write to the equivalent lower bits */
>  	switch (ctrl->type) {
> +	case RK3528:
>  	case RK3562:
>  	case RK3568:
>  		data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> ```
> 
> Thanks,
> Chukun
> 
> --
> 2.25.1
> 



From andyshrk at 163.com  Mon Mar 17 01:20:39 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 17 Mar 2025 16:20:39 +0800
Subject: [PATCH] drm/rockchip: dw_hdmi_qp: Fix io init for dw_hdmi_qp_rockchip_resume
Message-ID: <20250317082047.564404-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Use cfg->ctrl_ops->io_init callback make it work for all platform.

Fixes: 3f60dbd40d3f ("drm/rockchip: dw_hdmi_qp: Add platform ctrl callback")
Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 .../gpu/drm/rockchip/dw_hdmi_qp-rockchip.c    | 23 +++----------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 3d1dddb34603..631a7080862b 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -600,27 +600,10 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
 {
 	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
-	u32 val;
-
-	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
-	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
-	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
-	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
-	regmap_write(hdmi->vo_regmap,
-		     hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
-		     val);
-
-	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
-			    RK3588_SET_HPD_PATH_MASK);
-	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+	const struct rockchip_hdmi_qp_cfg *cfg;
 
-	if (hdmi->port_id)
-		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
-				    RK3588_HDMI1_GRANT_SEL);
-	else
-		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
-				    RK3588_HDMI0_GRANT_SEL);
-	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+	cfg = of_device_get_match_data(dev);
+	cfg->ctrl_ops->io_init(hdmi);
 
 	dw_hdmi_qp_resume(dev, hdmi->hdmi);
 
-- 
2.43.0



From mazziesaccount at gmail.com  Mon Mar 17 01:22:11 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 10:22:11 +0200
Subject: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <20250316093752.0eacaa16@jic23-huawei>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <c8899e8c535a1d93cd7588b7c160eb0fae5d26d2.1741849323.git.mazziesaccount@gmail.com>
 <20250316093752.0eacaa16@jic23-huawei>
Message-ID: <66a93de8-f5a2-4ffd-9c97-c646934cc90d@gmail.com>

On 16/03/2025 11:38, Jonathan Cameron wrote:
> On Thu, 13 Mar 2025 09:18:18 +0200
> Matti Vaittinen <mazziesaccount at gmail.com> wrote:
> 
>> There are ADC ICs which may have some of the AIN pins usable for other
>> functions. These ICs may have some of the AIN pins wired so that they
>> should not be used for ADC.
>>
>> (Preferred?) way for marking pins which can be used as ADC inputs is to
>> add corresponding channels at N nodes in the device tree as described in
>> the ADC binding yaml.
>>
>> Add couple of helper functions which can be used to retrieve the channel
>> information from the device node.
> I suspect we'll need the addition of an optional trailing timestamp
> channel at somepoint. But we can add that when we need it as only
> matters for drivers doing iio_push_to_buffers_with_timestamp()

This is true. That'll enable using this for devices with buffers - which 
is not possible right now as most buffer users do timestamps. I'll leave 
adding the parameter to first buffered user though, but I think it's 
good to say out loud this is doable :) Thanks!

> Otherwise no additional comments from me.

Yours,
	-- Matti


From nicolas.frattaroli at collabora.com  Mon Mar 17 01:28:55 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 09:28:55 +0100
Subject: [PATCH v3 3/6] thermal: rockchip: Support RK3576 SoC in the thermal
 driver
In-Reply-To: <6c355664-50dd-4efd-94b7-9d93c02d3e80@kwiboo.se>
References: <20250228-rk3576-tsadc-upstream-v3-0-4bfbb3b699b9@collabora.com>
 <20250228-rk3576-tsadc-upstream-v3-3-4bfbb3b699b9@collabora.com>
 <6c355664-50dd-4efd-94b7-9d93c02d3e80@kwiboo.se>
Message-ID: <4994384.31r3eYUQgx@workhorse>

On Saturday, 15 March 2025 09:20:07 Central European Standard Time Jonas 
Karlman wrote:
> Hi Nicolas,

Hi Jonas,

> 
> On 2025-02-28 21:06, Nicolas Frattaroli wrote:
> > From: Ye Zhang <ye.zhang at rock-chips.com>
> > 
> > The RK3576 SoC has six TS-ADC channels: TOP, BIG_CORE, LITTLE_CORE,
> > DDR, NPU and GPU.
> > 
> > Signed-off-by: Ye Zhang <ye.zhang at rock-chips.com>
> > [ported to mainline, reworded commit message]
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
> > ---
> > 
> >  drivers/thermal/rockchip_thermal.c | 42
> >  ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
> > 
> > diff --git a/drivers/thermal/rockchip_thermal.c
> > b/drivers/thermal/rockchip_thermal.c index
> > a8ad85feb68fbb7ec8d79602b16c47838ecb3c00..bec1930bebd87859a7e519cfc9f05e1
> > 0b1c31e87 100644 --- a/drivers/thermal/rockchip_thermal.c
> > +++ b/drivers/thermal/rockchip_thermal.c
> > @@ -1061,6 +1061,22 @@ static void rk_tsadcv3_tshut_mode(int chn, void
> > __iomem *regs,> 
> >  	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
> >  
> >  }
> > 
> > +static void rk_tsadcv4_tshut_mode(int chn, void __iomem *regs,
> > +				  enum tshut_mode mode)
> > +{
> > +	u32 val_gpio, val_cru;
> > +
> > +	if (mode == TSHUT_MODE_GPIO) {
> > +		val_gpio = TSADCV2_INT_SRC_EN(chn) | 
TSADCV2_INT_SRC_EN_MASK(chn);
> > +		val_cru = TSADCV2_INT_SRC_EN_MASK(chn);
> > +	} else {
> > +		val_cru = TSADCV2_INT_SRC_EN(chn) | 
TSADCV2_INT_SRC_EN_MASK(chn);
> > +		val_gpio = TSADCV2_INT_SRC_EN_MASK(chn);
> > +	}
> > +	writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN);
> > +	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
> > +}
> 
> This function is identical to rk_tsadcv3_tshut_mode() in mainline.
> 
> Should the v3 function be renamed to v4 in mainline to match vendor
> kernel to avoid confusion?

Good catch. Yes, I'll add a patch to rename the function before introducing 
new changes in v4, and get rid of the duplicate function.

> 
> > +
> > 
> >  static const struct rockchip_tsadc_chip px30_tsadc_data = {
> >  
> >  	/* cpu, gpu */
> >  	.chn_offset = 0,
> > 
> > @@ -1284,6 +1300,28 @@ static const struct rockchip_tsadc_chip
> > rk3568_tsadc_data = {> 
> >  	},
> >  
> >  };
> > 
> > +static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
> > +	/* top, big_core, little_core, ddr, npu, gpu */
> > +	.chn_offset = 0,
> > +	.chn_num = 6, /* six channels for tsadc */
> > +	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC 
*/
> > +	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
> > +	.tshut_temp = 95000,
> 
> Here the default is GPIO and 95 deg, in DT node the default is override
> to CRU and 120 deg.
> 
> Any reason that is not the default here?

No reason, other than that this is what most Rockchip SoCs seem to do. RK3588 
does the same thing. The hardware power-on-reset state is to not have any 
tshut, so whatever the "default" should be is entirely made up by the driver 
in either case.

For the sake of being consistent, I'll keep it the same in v4, as RK3588 does. 
Otherwise, we'll have RK3576 and RK3588 do different things. If someone wants 
to change the default, then ideally this would be done in a follow-up series 
to make it consistent for all SoCs.

If that's alright with you, then I'll send out a v4.

> 
> Regards,
> Jonas
> 

Regards,
Nicolas Frattaroli

> > +	.initialize = rk_tsadcv8_initialize,
> > +	.irq_ack = rk_tsadcv4_irq_ack,
> > +	.control = rk_tsadcv4_control,
> > +	.get_temp = rk_tsadcv4_get_temp,
> > +	.set_alarm_temp = rk_tsadcv3_alarm_temp,
> > +	.set_tshut_temp = rk_tsadcv3_tshut_temp,
> > +	.set_tshut_mode = rk_tsadcv4_tshut_mode,
> > +	.table = {
> > +		.id = rk3588_code_table,
> > +		.length = ARRAY_SIZE(rk3588_code_table),
> > +		.data_mask = TSADCV4_DATA_MASK,
> > +		.mode = ADC_INCREMENT,
> > +	},
> > +};
> > +
> > 
> >  static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
> >  
> >  	/* top, big_core0, big_core1, little_core, center, gpu, npu */
> >  	.chn_offset = 0,
> > 
> > @@ -1342,6 +1380,10 @@ static const struct of_device_id
> > of_rockchip_thermal_match[] = {> 
> >  		.compatible = "rockchip,rk3568-tsadc",
> >  		.data = (void *)&rk3568_tsadc_data,
> >  	
> >  	},
> > 
> > +	{
> > +		.compatible = "rockchip,rk3576-tsadc",
> > +		.data = (void *)&rk3576_tsadc_data,
> > +	},
> > 
> >  	{
> >  	
> >  		.compatible = "rockchip,rk3588-tsadc",
> >  		.data = (void *)&rk3588_tsadc_data,






From jjian.zhou at mediatek.com  Mon Mar 17 01:38:08 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 16:38:08 +0800
Subject: [PATCH RFC v2 2/3] firmware: mediatek: Add VCP IPC protocol interface
In-Reply-To: <20250317083822.891-1-jjian.zhou@mediatek.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
Message-ID: <20250317083822.891-3-jjian.zhou@mediatek.com>

Some of mediatek processors contain the Risc-V coprocessor.

The communication between Host CPU and vcp firmware is
taking place using a shared memory area for message passing.

VCP IPC protocol offers (send/recv) interfaces using
mediatek-mailbox APIs.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 4 files changed, 642 insertions(+)
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 37e43f287e78..98c4ff667836 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -179,6 +179,15 @@ config MTK_ADSP_IPC
 	  ADSP exists on some mtk processors.
 	  Client might use shared memory to exchange information with ADSP.
 
+config MTK_VCP_IPC
+	tristate "MTK VCP IPC Protocol driver"
+	depends on MTK_VCP_MBOX
+	help
+	  Say yes here to add support for the MediaTek VCP IPC
+	  between host AP (Linux) and the firmware running on VCP.
+	  VCP exists on some mtk processors.
+	  Client might use shared memory to exchange information with VCP.
+
 config SYSFB
 	bool
 	select BOOT_VESA_SUPPORT
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 91efcc868a05..2b9894e5169a 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
 obj-$(CONFIG_MTK_ADSP_IPC)	+= mtk-adsp-ipc.o
+obj-$(CONFIG_MTK_VCP_IPC)	+= mtk-vcp-ipc.o
 obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
 obj-$(CONFIG_FW_CFG_SYSFS)	+= qemu_fw_cfg.o
 obj-$(CONFIG_SYSFB)		+= sysfb.o
diff --git a/drivers/firmware/mtk-vcp-ipc.c b/drivers/firmware/mtk-vcp-ipc.c
new file mode 100644
index 000000000000..744937c56b67
--- /dev/null
+++ b/drivers/firmware/mtk-vcp-ipc.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/firmware/mediatek/mtk-vcp-ipc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/sched/clock.h>
+#include <linux/time64.h>
+#include <linux/vmalloc.h>
+
+/**
+ * struct mtk_ipi_chan_table - channel table that belong to mtk_ipi_device
+ * @mbox: the mbox channel number
+ * @mbox_pin_cb: callback function
+ * @holder: keep 1 if there are ipi waiters (to wait the reply)
+ * @ipi_record: timestamp of each ipi transmission stage
+ * @pin_buf: buffer point
+ * @prdata: private data
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @notify: completion notify process
+ * @send_ofs: message offset in the slots of a mbox
+ * @send_index: bit offset in the mbox
+ * @msg_zie: slot size of the ipi message
+ *
+ * All of these data should be initialized by mtk_ipi_device_register()
+ */
+struct mtk_ipi_chan_table {
+	u32 mbox;
+	mbox_pin_cb_t mbox_pin_cb;
+	atomic_t holder;
+	void *pin_buf;
+	void *prdata;
+	u32 recv_opt;
+	struct completion notify;
+	/* define a mutex for remote response */
+	struct mutex mutex_send;
+	u32 send_ofs;
+	u32 send_index;
+	u32 msg_size;
+};
+
+/**
+ * mbox information
+ *
+ * @mbdev: mbox device
+ * @mbox_id: mbox id
+ * @slot: how many slots that mbox used
+ * @opt: option for tx mode, 0:mbox, 1:share memory 2:queue
+ * @base: mbox base address
+ * @mbox_client: mbox client
+ * @mbox_chan: mbox channel
+ */
+struct mtk_mbox_info {
+	struct mtk_vcp_ipc *vcp_ipc;
+	u32 mbox_id;
+	u32 slot;
+	u32 opt;
+	/* lock of mbox */
+	spinlock_t mbox_lock;
+	struct mbox_client cl;
+	struct mbox_chan *ch;
+	struct mtk_ipi_info ipi_info;
+};
+
+static const char * const mbox_names[VCP_MBOX_NUM] = {
+	"mbox0", "mbox1", "mbox2", "mbox3", "mbox4"
+};
+
+/**
+ * mtk_vcp_ipc_recv - recv callback used by MTK VCP mailbox
+ *
+ * @c: mbox client
+ * @msg: message received
+ *
+ * Users of VCP IPC will need to provide handle_reply and handle_request
+ * callbacks.
+ */
+static void mtk_vcp_ipc_recv(struct mbox_client *c, void *msg)
+{
+	struct mtk_mbox_info *minfo = container_of(c, struct mtk_mbox_info, cl);
+	struct mtk_vcp_ipc *vcp_ipc = minfo->vcp_ipc;
+	struct mtk_ipi_info *ipi_info = msg;
+	struct mtk_ipi_device *ipidev = vcp_ipc->ipi_priv;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_mbox_recv_table *mbox_recv;
+	u32 id;
+
+	/* execute all receive pin handler */
+	for (id = 0; id < vcp_ipc->mbdev->recv_count; id++) {
+		mbox_recv = &vcp_ipc->mbdev->recv_table[id];
+		if (mbox_recv->mbox_id != minfo->mbox_id)
+			continue;
+
+		if (!(BIT(mbox_recv->pin_index) & ipi_info->irq_status))
+			continue;
+
+		table = &ipidev->table[mbox_recv->ipi_id];
+		if (!table->pin_buf) {
+			dev_err(vcp_ipc->dev, "IPI%d buf is null.\n",
+				mbox_recv->ipi_id);
+			continue;
+		}
+
+		memcpy(table->pin_buf,
+		       ipi_info->msg + mbox_recv->offset * MBOX_SLOT_SIZE,
+		       mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		if (!mbox_recv->recv_opt && table->mbox_pin_cb)
+			table->mbox_pin_cb(mbox_recv->ipi_id,
+					   table->prdata,
+					   table->pin_buf,
+					   mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		/* notify task */
+		if (table->recv_opt == MBOX_RECV_MESSAGE ||
+		    atomic_read(&table->holder))
+			complete(&table->notify);
+	}
+}
+
+/*
+ * mtk_vcp_ipc_send - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 id, void *data, u32 len)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	mutex_unlock(&table[id].mutex_send);
+	if (ret < 0) {
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send);
+
+/*
+ * mtk_vcp_ipc_send_compl - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ * @timeout_ms:
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 id,
+			   void *data, u32 len, u32 timeout_ms)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	atomic_inc(&table[id].holder);
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	if (ret < 0) {
+		atomic_set(&table[id].holder, 0);
+		mutex_unlock(&table[id].mutex_send);
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	/* wait for completion */
+	ret = wait_for_completion_timeout(&table[id].notify,
+					  msecs_to_jiffies(timeout_ms));
+	atomic_set(&table[id].holder, 0);
+	if (ret > 0)
+		ret = IPI_ACTION_DONE;
+
+	mutex_unlock(&table[id].mutex_send);
+
+	return ret;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send_compl);
+
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+	if (!msg)
+		return IPI_NO_MSGBUF;
+
+	if (ipidev->table[id].pin_buf)
+		return IPI_ALREADY_USED;
+	ipidev->table[id].mbox_pin_cb = cb;
+	ipidev->table[id].pin_buf = msg;
+	ipidev->table[id].prdata = prdata;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_register);
+
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int id)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+
+	/* Drop the ipi and reset the record */
+	complete(&ipidev->table[id].notify);
+
+	ipidev->table[id].mbox_pin_cb = NULL;
+	ipidev->table[id].pin_buf = NULL;
+	ipidev->table[id].prdata = NULL;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_unregister);
+
+static void mtk_fill_in_entry(struct mtk_ipi_chan_table *entry, const u32 ipi_id,
+			      const struct mtk_mbox_table *mbdev)
+{
+	const struct mtk_mbox_send_table *mbox_send = mbdev->send_table;
+	u32 index;
+
+	for (index = 0; index < mbdev->send_count; index++) {
+		if (ipi_id != mbox_send[index].ipi_id)
+			continue;
+
+		entry->send_ofs = mbox_send[index].offset;
+		entry->send_index = mbox_send[index].pin_index;
+		entry->msg_size = mbox_send[index].msg_size;
+		entry->mbox = mbox_send[index].mbox_id;
+		return;
+	}
+
+	entry->mbox = -ENOENT;
+}
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count, struct mtk_vcp_ipc *vcp_ipc)
+{
+	struct mtk_ipi_chan_table *ipi_chan_table;
+	struct mtk_mbox_table *mbdev;
+	u32 index;
+
+	if (!vcp_ipc || !ipidev)
+		return -EINVAL;
+
+	ipi_chan_table = kcalloc(ipi_chan_count,
+				 sizeof(struct mtk_ipi_chan_table), GFP_KERNEL);
+	if (!ipi_chan_table)
+		return -ENOMEM;
+
+	mbdev = vcp_ipc->mbdev;
+	vcp_ipc->ipi_priv = (void *)ipidev;
+	ipidev->table = ipi_chan_table;
+	ipidev->vcp_ipc = vcp_ipc;
+
+	for (index = 0; index < ipi_chan_count; index++) {
+		atomic_set(&ipi_chan_table[index].holder, 0);
+		mutex_init(&ipi_chan_table[index].mutex_send);
+		init_completion(&ipi_chan_table[index].notify);
+		mtk_fill_in_entry(&ipi_chan_table[index], index, mbdev);
+	}
+
+	ipidev->ipi_inited = 1;
+
+	dev_dbg(vcp_ipc->dev, "%s (with %d IPI) has registered.\n",
+		ipidev->name, ipi_chan_count);
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_device_register);
+
+static int setup_mbox_table(struct mtk_mbox_table *mbdev, u32 mbox)
+{
+	struct mtk_mbox_send_table *mbox_send = &mbdev->send_table[0];
+	struct mtk_mbox_recv_table *mbox_recv = &mbdev->recv_table[0];
+	u32 i, last_ofs = 0, last_idx = 0, last_slot = 0, last_sz = 0;
+
+	for (i = 0; i < mbdev->send_count; i++) {
+		if (mbox == mbox_send[i].mbox_id) {
+			mbox_send[i].offset = last_ofs + last_slot;
+			mbox_send[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_send[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_send[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_send[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	for (i = 0; i < mbdev->recv_count; i++) {
+		if (mbox == mbox_recv[i].mbox_id) {
+			mbox_recv[i].offset = last_ofs + last_slot;
+			mbox_recv[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_recv[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_recv[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_recv[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	if (last_idx > MBOX_MAX_PIN || (last_ofs + last_slot) > MAX_SLOT_NUM)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mtk_vcp_ipc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mbox_client *cl;
+	struct mtk_mbox_info *minfo;
+	int ret;
+	u32 mbox, i;
+	struct mtk_mbox_table *mbox_data = dev_get_platdata(dev);
+
+	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
+	vcp_ipc = devm_kzalloc(dev, sizeof(*vcp_ipc), GFP_KERNEL);
+	if (!vcp_ipc)
+		return -ENOMEM;
+
+	if (!mbox_data) {
+		dev_err(dev, "No platform data available\n");
+		return -EINVAL;
+	}
+	vcp_ipc->mbdev = mbox_data;
+
+	/* alloc and init mmup_mbox_info */
+	vcp_ipc->info_table = vzalloc(sizeof(*vcp_ipc->info_table) * VCP_MBOX_NUM);
+	if (!vcp_ipc->info_table)
+		return -ENOMEM;
+
+	/* create mbox dev */
+	for (mbox = 0; mbox < VCP_MBOX_NUM; mbox++) {
+		minfo = &vcp_ipc->info_table[mbox];
+		minfo->mbox_id = mbox;
+		minfo->vcp_ipc = vcp_ipc;
+		spin_lock_init(&minfo->mbox_lock);
+
+		ret = setup_mbox_table(vcp_ipc->mbdev, mbox);
+		if (ret)
+			return ret;
+
+		cl = &minfo->cl;
+		cl->dev = &pdev->dev;
+		cl->tx_block = false;
+		cl->knows_txdone = false;
+		cl->tx_prepare = NULL;
+		cl->rx_callback = mtk_vcp_ipc_recv;
+		minfo->ch = mbox_request_channel_byname(cl, mbox_names[mbox]);
+		if (IS_ERR(minfo->ch)) {
+			ret = PTR_ERR(minfo->ch);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to request mbox channel %s ret %d\n",
+					mbox_names[mbox], ret);
+
+			for (i = 0; i < mbox; i++) {
+				minfo = &vcp_ipc->info_table[i];
+				mbox_free_channel(minfo->ch);
+			}
+
+			vfree(vcp_ipc->info_table);
+			return ret;
+		}
+	}
+
+	vcp_ipc->dev = dev;
+	dev_set_drvdata(dev, vcp_ipc);
+	dev_dbg(dev, "MTK VCP IPC initialized\n");
+
+	return 0;
+}
+
+static void mtk_vcp_ipc_remove(struct platform_device *pdev)
+{
+	struct mtk_vcp_ipc *vcp_ipc = dev_get_drvdata(&pdev->dev);
+	struct mtk_mbox_info *minfo;
+	int i;
+
+	for (i = 0; i < VCP_MBOX_NUM; i++) {
+		minfo = &vcp_ipc->info_table[i];
+		mbox_free_channel(minfo->ch);
+	}
+
+	vfree(vcp_ipc->info_table);
+}
+
+static struct platform_driver mtk_vcp_ipc_driver = {
+	.probe = mtk_vcp_ipc_probe,
+	.remove = mtk_vcp_ipc_remove,
+	.driver = {
+		.name = "mtk-vcp-ipc",
+	},
+};
+builtin_platform_driver(mtk_vcp_ipc_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek VCP IPC Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/mediatek/mtk-vcp-ipc.h b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
new file mode 100644
index 000000000000..dc34b0ba9dd8
--- /dev/null
+++ b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_IPC_H__
+#define __MTK_VCP_IPC_H__
+
+#include <linux/completion.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* IPI result definition */
+#define IPI_ACTION_DONE	  0
+#define IPI_DEV_ILLEGAL	 -1 /* ipi device is not initialized */
+#define IPI_ALREADY_USED	 -2 /* the ipi has be registered */
+#define IPI_UNAVAILABLE	 -3 /* the ipi can't be found */
+#define IPI_NO_MSGBUF		 -4 /* receiver doesn't have message buffer */
+#define IPI_MSG_TOO_BIG		 -5 /* message length is larger than defined */
+#define IPI_MBOX_ERR		-99 /* some error from rpmsg layer */
+
+/* mbox recv action definition */
+enum mtk_ipi_recv_opt {
+	MBOX_RECV_MESSAGE  = 0,
+	MBOX_RECV_ACK      = 1,
+};
+
+/* mbox table item number definition */
+#define send_item_num	3
+#define recv_item_num	4
+#define VCP_MBOX_NUM	5
+
+/* mbox slot size definition: 1 slot for 4 bytes */
+#define MBOX_SLOT_SIZE	0x4
+#define MBOX_MAX_PIN	32
+#define VCP_MBOX_NUM	5
+#define MBOX_SLOT_ALIGN	2
+
+struct mtk_vcp_ipc;
+struct mtk_ipi_chan_table;
+
+typedef int (*mbox_pin_cb_t)(u32 ipi_id, void *prdata, void *data, u32 len);
+
+/**
+ * mbox pin structure, this is for send definition,
+ * @offset: message offset in the slots of a mbox
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_send_table {
+	u32 offset;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * mbox pin structure, this is for receive definition,
+ * @offset: message offset in the slots of a mbox
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_recv_table {
+	u32 offset;
+	u32 recv_opt;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * struct mtk_ipi_device - device for represent the tinysys using mtk ipi
+ * @name: name of tinysys device
+ * @id: device id (used to match between rpmsg drivers and devices)
+ * @vcp_ipc: vcp ipc structure for tinysys device
+ * @table: channel table with endpoint & channel_info & mbox_pin info
+ * @prdata: private data for the callback use
+ * @ipi_inited: set when vcp_ipi_device_register() done
+ */
+struct mtk_ipi_device  {
+	const char *name;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mtk_ipi_chan_table *table;
+	void *prdata;
+	int ipi_inited;
+};
+
+/**
+ * The mtk_mbox_table is a structure used to record the send
+ * table and recv table. The send table is used to record
+ * the feature ID and size of the sent data. The recv table
+ * is used to record the feature ID and size of the received
+ * data, and whether a callback needs to be invoked.
+ *
+ * Following are platform specific interfacer
+ * @recv_table: structure mtk_mbox_recv_table
+ * @send_table: structure mtk_mbox_send_table
+ * @recv_count: receive feature number in this channel
+ * @send_count: send feature number in this channel
+ */
+struct mtk_mbox_table {
+	struct mtk_mbox_recv_table recv_table[32];
+	struct mtk_mbox_send_table send_table[32];
+	u32 recv_count;
+	u32 send_count;
+};
+
+/**
+ * Mbox is a dedicate hardware of a tinysys consists of:
+ * 1) a share memory tightly coupled to the tinysys
+ * 2) several IRQs
+ *
+ * Following are platform specific interface
+ * @dev: vcp device
+ * @name: identity of the device
+ * @info_table: mbox info structure
+ * @ipi_priv: private data for synchronization layer
+ * @mbox_id: mbox number
+ * @mbdev: mtk_mbox_table structure
+ */
+struct mtk_vcp_ipc {
+	struct device *dev;
+	const char *name;
+	struct mtk_mbox_info *info_table;
+	void *ipi_priv;
+	void *mbox_id;
+	struct mtk_mbox_table *mbdev;
+};
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count,
+				struct mtk_vcp_ipc *vcp_ipc);
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 ipi_id,
+		     void *data, u32 len);
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 ipi_id,
+			   void *data, u32 len, u32 timeout_ms);
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int ipi_id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg);
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int ipi_id);
+
+#endif
-- 
2.45.2



From jjian.zhou at mediatek.com  Mon Mar 17 01:38:09 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 16:38:09 +0800
Subject: [PATCH RFC v2 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document
In-Reply-To: <20250317083822.891-1-jjian.zhou@mediatek.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
Message-ID: <20250317083822.891-4-jjian.zhou@mediatek.com>

This patch adds document for mediatek vcp mbox.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml

diff --git a/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
new file mode 100644
index 000000000000..bd1b024e22f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/mtk,mt8196-vcp-mbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Video Companion Processor (VCP) mailbox
+
+maintainers:
+  - Jjian Zhou <Jjian.Zhou at mediatek.com>
+
+description:
+  The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
+  messages through 64 32-bit wide registers. It has 32 interrupt vectors in
+  either direction for signalling purposes.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8196-vcp-mbox
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  "#mbox-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - "#mbox-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    mailbox at 31b80000 {
+        compatible = "mediatek,mt8196-vcp-mbox";
+        reg = <0x31b80000 0x1000>;
+        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
+        #mbox-cells = <0>;
+    };
-- 
2.45.2



From adrian.liszka at novaplan.pl  Mon Mar 17 01:41:05 2025
From: adrian.liszka at novaplan.pl (Adrian Liszka)
Date: Mon, 17 Mar 2025 08:41:05 GMT
Subject: =?UTF-8?Q?Prosz=C4=99_o_kontakt?=
Message-ID: <20250317084500-0.1.kg.1gqnp.0.c6u3c02iwj@novaplan.pl>

Dzie? dobry,

Czy jest mo?liwo?? nawi?zania wsp??pracy z Pa?stwem?

Z ch?ci? porozmawiam z osob? zajmuj?c? si? dzia?aniami zwi?zanymi ze sprzeda??.

Pomagamy skutecznie pozyskiwa? nowych klient?w.

Zapraszam do kontaktu.


Z pozdrowieniami
Adrian Liszka


From jjian.zhou at mediatek.com  Mon Mar 17 01:38:06 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 16:38:06 +0800
Subject: [PATCH RFC v2 0/3] add VCP mailbox and IPC driver
Message-ID: <20250317083822.891-1-jjian.zhou@mediatek.com>

The VCP mailbox has 5 groups. Each group has corresponding interrupts,
registers, and 64 slots (each slot is 4 bytes). Since different features
share one of the mailbox groups, the VCP mailbox needs to establish a
send table and a receive table. The send table is used to record the
feature ID, mailbox ID, and the number of slots occupied. The receive table
is used to record the feature ID, mailbox ID, the number of slots occupied,
and the receive options. The API setup_mbox_table in mtk-vcp-ipc.c calculates
the slot offset and pin index for each feature ID based on the mailbox ID and
slot number in the send and receive tables (several slots form a pin, and
each pin can trigger an interrupt). These descriptions are written in the
mtk-vcp-ipc.c file -- we call it the IPC layer.

We have two questions:
How should we describe the mailbox and IPI?
Can the intermediate IPC layer be rewritten as a virtual mailbox layer?

Example of send and recve table:
Operation | mbox_id | ipi_id | msg_size | align_size | slot_ofs | pin_index |  notes
send          0          0       18          18           0          0
recv          0          1       18          18          18          9
send          1         15        8           8           0          0
send          1         16       18          18           8          4
send          1          9        2           2          26         13
recv          1         15        8           8          28         14       ack of send ipi_id=15
recv          1         17       18          18          36         18
recv          1         10        2           2          54         27       ack of send ipi_id=2
send          2         11       18          18           0          0
send          2          2        2           2          18          9
send          2          3        3           4          20         10
send          2         32        2           2          24         12
recv          2         12       18          18          26         13
recv          2          5        1           2          44         22
recv          2          2        1           2          46         23

Recv ipi_id=2 is the ack of send ipi_id=2(The ipi_id=15 is the same.)

Jjian Zhou (3):
  mailbox: mediatek: Add mtk-vcp-mailbox driver
  firmware: mediatek: Add vcp ipc protocol interface
  dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document

 .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml |  49 ++
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 drivers/mailbox/Kconfig                       |   9 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c             | 179 +++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 include/linux/mailbox/mtk-vcp-mailbox.h       |  34 ++
 9 files changed, 915 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

-- 
2.45.2



From jjian.zhou at mediatek.com  Mon Mar 17 01:38:07 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 16:38:07 +0800
Subject: [PATCH RFC v2 1/3] mailbox: mediatek: Add mtk-vcp-mailbox driver
In-Reply-To: <20250317083822.891-1-jjian.zhou@mediatek.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
Message-ID: <20250317083822.891-2-jjian.zhou@mediatek.com>

Add mtk-vcp-mailbox driver to support the communication with
VCP remote microprocessor.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/mailbox/Kconfig                 |   9 ++
 drivers/mailbox/Makefile                |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c       | 179 ++++++++++++++++++++++++
 include/linux/mailbox/mtk-vcp-mailbox.h |  34 +++++
 4 files changed, 224 insertions(+)
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ed52db272f4d..ffc4a5491462 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -275,6 +275,15 @@ config MTK_CMDQ_MBOX
 	  critical time limitation, such as updating display configuration
 	  during the vblank.
 
+config MTK_VCP_MBOX
+	tristate "MediaTek VCP Mailbox Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  Say yes here to add support for the MediaTek VCP mailbox driver.
+	  The mailbox implementation provides access from the application
+	  processor to the MediaTek Video Processing Unit.
+	  If unsure say N.
+
 config ZYNQMP_IPI_MBOX
 	tristate "Xilinx ZynqMP IPI Mailbox"
 	depends on ARCH_ZYNQMP && OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 9a1542b55539..75a200a9d2d2 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -59,6 +59,8 @@ obj-$(CONFIG_MTK_ADSP_MBOX)	+= mtk-adsp-mailbox.o
 
 obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o
 
+obj-$(CONFIG_MTK_VCP_MBOX)	+= mtk-vcp-mailbox.o
+
 obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o
 
 obj-$(CONFIG_SUN6I_MSGBOX)	+= sun6i-msgbox.o
diff --git a/drivers/mailbox/mtk-vcp-mailbox.c b/drivers/mailbox/mtk-vcp-mailbox.c
new file mode 100644
index 000000000000..fd7a123c71c8
--- /dev/null
+++ b/drivers/mailbox/mtk-vcp-mailbox.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Corporation. All rights reserved.
+ * Author: Jjian Zhou <jjian.zhou. at mediatek.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct mtk_vcp_mbox_priv {
+	void __iomem *base;
+	struct device *dev;
+	struct mbox_controller mbox;
+	const struct mtk_vcp_mbox_cfg *cfg;
+	struct mtk_ipi_info ipi_recv;
+};
+
+struct mtk_vcp_mbox_cfg {
+	u32 set_in;
+	u32 clr_out;
+};
+
+static inline struct mtk_vcp_mbox_priv *get_mtk_vcp_mbox_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct mtk_vcp_mbox_priv, mbox);
+}
+
+static irqreturn_t mtk_vcp_mbox_irq_thread(int irq, void *data)
+{
+	struct mbox_chan *chan = data;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+
+	/* get irq status */
+	priv->ipi_recv.irq_status = readl(priv->base + priv->cfg->clr_out);
+
+	__ioread32_copy(priv->ipi_recv.msg, priv->base, MAX_SLOT_NUM);
+
+	mbox_chan_received_data(chan, &priv->ipi_recv);
+
+	/* clear irq status */
+	writel(priv->ipi_recv.irq_status, priv->base + priv->cfg->clr_out);
+
+	return IRQ_HANDLED;
+}
+
+static struct mbox_chan *mtk_vcp_mbox_xlate(struct mbox_controller *mbox,
+					    const struct of_phandle_args *sp)
+{
+	if (sp->args_count)
+		return NULL;
+
+	return mbox->chans;
+}
+
+static int mtk_vcp_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	struct mtk_ipi_info *ipi_info = data;
+	u32 status;
+
+	if (!ipi_info->msg) {
+		dev_err(priv->dev, "msg buffer is NULL.\n");
+		return -ENOMEM;
+	}
+
+	status = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	if (status) {
+		dev_err(priv->dev, "mailbox IPI %d is busy.\n", ipi_info->id);
+		return -EBUSY;
+	}
+
+	if (ipi_info->slot_ofs + ipi_info->len > MBOX_SLOT_MAX_SIZE)
+		return -EINVAL;
+	__iowrite32_copy(priv->base + ipi_info->slot_ofs, ipi_info->msg,
+			 ipi_info->len);
+
+	writel(BIT(ipi_info->index), priv->base + priv->cfg->set_in);
+
+	return 0;
+}
+
+static bool mtk_vcp_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	struct mtk_ipi_info *ipi_info = chan->active_req;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	u32 op;
+
+	op = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	return !op;
+}
+
+static const struct mbox_chan_ops mtk_vcp_mbox_chan_ops = {
+	.send_data	= mtk_vcp_mbox_send_data,
+	.last_tx_done	= mtk_vcp_mbox_last_tx_done,
+};
+
+static int mtk_vcp_mbox_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_mbox_priv *priv;
+	struct mbox_controller *mbox;
+	int ret, irq;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	mbox = &priv->mbox;
+	mbox->dev = dev;
+	mbox->ops = &mtk_vcp_mbox_chan_ops;
+	mbox->txdone_irq = false;
+	mbox->txdone_poll = true;
+	mbox->of_xlate = mtk_vcp_mbox_xlate;
+	mbox->num_chans = 1;
+	mbox->chans = devm_kzalloc(dev, sizeof(*mbox->chans), GFP_KERNEL);
+	if (!mbox->chans)
+		return -ENOMEM;
+
+	priv->ipi_recv.msg = devm_kzalloc(dev, sizeof(u8) * MBOX_SLOT_MAX_SIZE,
+					  GFP_KERNEL);
+	if (!priv->ipi_recv.msg)
+		return -ENOMEM;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->cfg = of_device_get_match_data(dev);
+	if (!priv->cfg)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_threaded_irq(dev, irq, NULL,
+					mtk_vcp_mbox_irq_thread, IRQF_ONESHOT,
+					dev_name(dev), mbox->chans);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);
+
+	dev_dbg(dev, "MTK VCP mailbox initialized\n");
+
+	return devm_mbox_controller_register(dev, &priv->mbox);
+}
+
+static const struct mtk_vcp_mbox_cfg mt8196_cfg = {
+	.set_in		= 0x100,
+	.clr_out	= 0x10C,
+};
+
+static const struct of_device_id mtk_vcp_mbox_of_match[] = {
+	{ .compatible = "mediatek,mt8196-vcp-mbox", .data = &mt8196_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_vcp_mbox_of_match);
+
+static struct platform_driver mtk_vcp_mbox_driver = {
+	.probe		= mtk_vcp_mbox_probe,
+	.driver = {
+		.name	= "mtk_vcp_mbox",
+		.of_match_table = mtk_vcp_mbox_of_match,
+	},
+};
+module_platform_driver(mtk_vcp_mbox_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MTK VCP Mailbox Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mailbox/mtk-vcp-mailbox.h b/include/linux/mailbox/mtk-vcp-mailbox.h
new file mode 100644
index 000000000000..953499b7cfeb
--- /dev/null
+++ b/include/linux/mailbox/mtk-vcp-mailbox.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_MAILBOX_H__
+#define __MTK_VCP_MAILBOX_H__
+
+#define MBOX_SLOT_MAX_SIZE	0x100 /* mbox max slot size */
+#define MAX_SLOT_NUM	64
+
+/**
+ * struct mtk_ipi_info - channel table that belong to mtk_ipi_device
+ * @msg: The share buffer between IPC and mailbox driver
+ * @len: Message length
+ * @id: IPI number
+ * @recv_opt: Recv option,  0:receive ,1: response
+ * @index: The pin groups number of the mailbox channel
+ * @slot_ofs: Slot offset of the mailbox channel
+ * @irq_status: Indicate which pin groups triggered the interrupt
+ *
+ * It is used between IPC with mailbox driver.
+ */
+struct mtk_ipi_info {
+	void *msg;
+	u32 len;
+	u32 id;
+	u32 recv_opt;
+	u32 index;
+	u32 slot_ofs;
+	u32 irq_status;
+};
+
+#endif
-- 
2.45.2



From mazziesaccount at gmail.com  Mon Mar 17 01:42:07 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 10:42:07 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <Z9fUmo5wp3EcNWzm@smile.fi.intel.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQ0O34EUM8WZku@smile.fi.intel.com> <20250316094112.6731bd01@jic23-huawei>
 <50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>
 <Z9fUmo5wp3EcNWzm@smile.fi.intel.com>
Message-ID: <0db2a42f-d393-4e75-afbf-cf30c0e06cce@gmail.com>

On 17/03/2025 09:51, Andy Shevchenko wrote:
> On Mon, Mar 17, 2025 at 09:11:08AM +0200, Matti Vaittinen wrote:
>> On 16/03/2025 11:41, Jonathan Cameron wrote:
>>> On Thu, 13 Mar 2025 14:34:24 +0200
>>> Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:
>>>> On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
> 
> ...
> 
>>>>> +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
>>>>> +				&sun20i_gpadc_chan_template, -1, &channels);
>>>>> +	if (num_channels < 0)
>>>>> +		return num_channels;
>>>>> +
>>>>>    	if (num_channels == 0)
>>>>>    		return dev_err_probe(dev, -ENODEV, "no channel children\n");
>>>>
>>>> Note, this what I would expected in your helper to see, i.e. separated cases
>>>> for < 0 (error code) and == 0, no channels.
>>>>
>>>> Also, are all users going to have this check? Usually in other similar APIs
>>>> we return -ENOENT. And user won't need to have an additional check in case of
>>>> 0 being considered as an error case too.
>>> In a few cases we'll need to do the dance the other way in the caller.
>>> So specifically check for -ENOENT and not treat it as an error.
>>>
>>> That stems from channel nodes being optionally added to drivers after
>>> they have been around a while (usually to add more specific configuration)
>>> and needing to maintain old behaviour of presenting all channels with default
>>> settings.
>>>
>>> I agree that returning -ENOENT is a reasonable way to handle this.
>>
>> I agree - but I'm going to use -ENODEV instead of -ENOENT because that's
>> what the current callers return if they find no channels. That way the
>> drivers can return the value directly without converting -ENOENT to -ENODEV.
> 
> ENODEV can be easily clashed with other irrelevant cases,

Can you please explain what cases?

> ENOENT is the correct
> error code.

I kind of agree if we look this from the fwnode perspective. But, when 
we look this from the intended user's perspective, I can very well 
understand the -ENODEV. Returning -ENODEV from ADC driver's probe which 
can't find any of the channels feels correct to me.

> If drivers return this instead of another error code, nothing bad
> happen, it's not an ABI path, correct?

I don't know if failure returned from a probe is an ABI. I still feel 
-ENODEV is correct value, and I don't want to change it for existing 
users - and I think also new ADC drivers should use -ENODEV if they find 
no channels at all.

Besides that I think -ENODEV to be right, changing it to -ENOENT for 
existing callers requires a buy-in from Jonathan (and/or) the driver 
maintainers.

Yours,
	-- Matti


From maxime.chevallier at bootlin.com  Mon Mar 17 01:53:33 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 17 Mar 2025 09:53:33 +0100
Subject: [net-next 4/4] net: ftgmac100: add RGMII delay for AST2600
In-Reply-To: <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
	<20250317025922.1526937-5-jacky_chou@aspeedtech.com>
Message-ID: <20250317095229.6f8754dd@fedora.home>

Hi,

On Mon, 17 Mar 2025 10:59:22 +0800
Jacky Chou <jacky_chou at aspeedtech.com> wrote:

> Use rx-internal-delay-ps and tx-internal-delay-ps
> properties to configue the RGMII delay into corresponding register of
> scu. Currently, the ftgmac100 driver only configures on AST2600 and will
> be by pass the other platforms.
> The details are in faraday,ftgmac100.yaml.
> 
> Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
> ---
>  drivers/net/ethernet/faraday/ftgmac100.c | 88 ++++++++++++++++++++++++
>  drivers/net/ethernet/faraday/ftgmac100.h | 12 ++++
>  2 files changed, 100 insertions(+)
> 
> diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
> index 17ec35e75a65..ea2061488cba 100644
> --- a/drivers/net/ethernet/faraday/ftgmac100.c
> +++ b/drivers/net/ethernet/faraday/ftgmac100.c
> @@ -27,6 +27,9 @@
>  #include <linux/phy_fixed.h>
>  #include <net/ip.h>
>  #include <net/ncsi.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/bitfield.h>
>  
>  #include "ftgmac100.h"
>  
> @@ -1812,6 +1815,88 @@ static bool ftgmac100_has_child_node(struct device_node *np, const char *name)
>  	return ret;
>  }
>  
> +static void ftgmac100_set_internal_delay(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct net_device *netdev;
> +	struct ftgmac100 *priv;
> +	struct regmap *scu;
> +	u32 rgmii_tx_delay, rgmii_rx_delay;
> +	u32 dly_reg, tx_dly_mask, rx_dly_mask;
> +	int tx, rx;

Please use the reverse christmas tree notation, sorting declarations by
descending line length

> +	netdev = platform_get_drvdata(pdev);
> +	priv = netdev_priv(netdev);
> +
> +	tx = of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay);
> +	rx = of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_rx_delay);
> +
> +	if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
> +		/* According to mac base address to get mac index */
> +		switch (priv->res->start) {
> +		case 0x1e660000:
> +			dly_reg = AST2600_MAC12_CLK_DLY;
> +			tx_dly_mask = AST2600_MAC1_TX_DLY;
> +			rx_dly_mask = AST2600_MAC1_RX_DLY;
> +			rgmii_tx_delay = FIELD_PREP(AST2600_MAC1_TX_DLY, rgmii_tx_delay);
> +			rgmii_rx_delay = FIELD_PREP(AST2600_MAC1_RX_DLY, rgmii_rx_delay);
> +			break;
> +		case 0x1e680000:
> +			dly_reg = AST2600_MAC12_CLK_DLY;
> +			tx_dly_mask = AST2600_MAC2_TX_DLY;
> +			rx_dly_mask = AST2600_MAC2_RX_DLY;
> +			rgmii_tx_delay = FIELD_PREP(AST2600_MAC2_TX_DLY, rgmii_tx_delay);
> +			rgmii_rx_delay = FIELD_PREP(AST2600_MAC2_RX_DLY, rgmii_rx_delay);
> +			break;
> +		case 0x1e670000:
> +			dly_reg = AST2600_MAC34_CLK_DLY;
> +			tx_dly_mask = AST2600_MAC3_TX_DLY;
> +			rx_dly_mask = AST2600_MAC3_RX_DLY;
> +			rgmii_tx_delay = FIELD_PREP(AST2600_MAC3_TX_DLY, rgmii_tx_delay);
> +			rgmii_rx_delay = FIELD_PREP(AST2600_MAC3_RX_DLY, rgmii_rx_delay);
> +			break;
> +		case 0x1e690000:
> +			dly_reg = AST2600_MAC34_CLK_DLY;
> +			tx_dly_mask = AST2600_MAC4_TX_DLY;
> +			rx_dly_mask = AST2600_MAC4_RX_DLY;
> +			rgmii_tx_delay = FIELD_PREP(AST2600_MAC4_TX_DLY, rgmii_tx_delay);
> +			rgmii_rx_delay = FIELD_PREP(AST2600_MAC4_RX_DLY, rgmii_rx_delay);
> +			break;
> +		default:
> +			dev_warn(&pdev->dev, "Invalid mac base address");
> +			return;

There has to be a better way that directly looking up the base address.
Maybe you need an extra DT property ?

> +		}
> +	} else {
> +		return;
> +	}
> +
> +	scu = syscon_regmap_lookup_by_phandle(np, "scu");
> +	if (IS_ERR(scu)) {
> +		dev_warn(&pdev->dev, "failed to map scu base");
> +		return;
> +	}
> +
> +	if (!tx) {
> +		/* Use tx-internal-delay-ps as index to configure tx delay
> +		 * into scu register.
> +		 */

So this goes completely against the naming of the property. It has the
-ps suffix, so you would expect to have picoseconds values passed, and
not an arbiraty index.

Take a look at other drivers, you should accept picseconds values from
these properties, then compute the relevant index in the driver. That
index should be something internal to your driver.

An example here :

https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c#L51

> +		if (rgmii_tx_delay > 64)
> +			dev_warn(&pdev->dev, "Get invalid tx delay value");
> +		else
> +			regmap_update_bits(scu, dly_reg, tx_dly_mask, rgmii_tx_delay);
> +	}
> +
> +	if (!rx) {
> +		/* Use rx-internal-delay-ps as index to configure rx delay
> +		 * into scu register.
> +		 */
> +		if (rgmii_tx_delay > 64)
> +			dev_warn(&pdev->dev, "Get invalid rx delay value");
> +		else
> +			regmap_update_bits(scu, dly_reg, rx_dly_mask, rgmii_rx_delay);
> +	}
> +}
> +
>  static int ftgmac100_probe(struct platform_device *pdev)
>  {
>  	struct resource *res;
> @@ -1977,6 +2062,9 @@ static int ftgmac100_probe(struct platform_device *pdev)
>  		if (of_device_is_compatible(np, "aspeed,ast2600-mac"))
>  			iowrite32(FTGMAC100_TM_DEFAULT,
>  				  priv->base + FTGMAC100_OFFSET_TM);
> +
> +		/* Configure RGMII delay if there are the corresponding properties */
> +		ftgmac100_set_internal_delay(pdev);
>  	}
>  
>  	/* Default ring sizes */
> diff --git a/drivers/net/ethernet/faraday/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h
> index 4968f6f0bdbc..d464d287502c 100644
> --- a/drivers/net/ethernet/faraday/ftgmac100.h
> +++ b/drivers/net/ethernet/faraday/ftgmac100.h
> @@ -271,4 +271,16 @@ struct ftgmac100_rxdes {
>  #define FTGMAC100_RXDES1_UDP_CHKSUM_ERR	(1 << 26)
>  #define FTGMAC100_RXDES1_IP_CHKSUM_ERR	(1 << 27)
>  
> +/* Aspeed SCU */
> +#define AST2600_MAC12_CLK_DLY	0x340
> +#define AST2600_MAC1_TX_DLY		GENMASK(5, 0)
> +#define AST2600_MAC1_RX_DLY		GENMASK(17, 12)
> +#define AST2600_MAC2_TX_DLY		GENMASK(11, 6)
> +#define AST2600_MAC2_RX_DLY		GENMASK(23, 18)
> +#define AST2600_MAC34_CLK_DLY	0x350
> +#define AST2600_MAC3_TX_DLY		AST2600_MAC1_TX_DLY
> +#define AST2600_MAC3_RX_DLY		AST2600_MAC1_RX_DLY
> +#define AST2600_MAC4_TX_DLY		AST2600_MAC2_TX_DLY
> +#define AST2600_MAC4_RX_DLY		AST2600_MAC2_RX_DLY
> +
>  #endif /* __FTGMAC100_H */

Maxime


From krzk at kernel.org  Mon Mar 17 01:57:57 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 09:57:57 +0100
Subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
 mode driver
In-Reply-To: <OS8PR06MB7541B15342ED1C92579AE18DF2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-3-ryan_chen@aspeedtech.com>
 <202502280902.U0gLDhve-lkp@intel.com> <Z8GuOT5bJL7CdXX6@smile.fi.intel.com>
 <fec0a1c8-251b-491e-893d-11a8186a2128@kernel.org>
 <Z9fWhGDrUbAmGRl0@smile.fi.intel.com>
 <OS8PR06MB7541B15342ED1C92579AE18DF2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
Message-ID: <e0d80130-ab5e-4e0b-8d74-ccc94d084192@kernel.org>

On 17/03/2025 09:51, Ryan Chen wrote:
>> Subject: Re: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
>> mode driver
>>
>> On Mon, Mar 17, 2025 at 08:48:03AM +0100, Krzysztof Kozlowski wrote:
>>> On 28/02/2025 13:38, Andy Shevchenko wrote:
>>>> On Fri, Feb 28, 2025 at 09:28:59AM +0800, kernel test robot wrote:
>>>>> Hi Ryan,
>>>>>
>>>>> kernel test robot noticed the following build warnings:
>>>>>
>>>>> [auto build test WARNING on andi-shyti/i2c/i2c-host] [also build
>>>>> test WARNING on linus/master v6.14-rc4 next-20250227] [If your
>>>>> patch is applied to the wrong git tree, kindly drop us a note.
>>>>> And when submitting patch, we suggest to use '--base' as documented
>>>>> in
>>>>> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>>>>>
>>>>> url:
>> https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-i2c-asp
>> eed-support-for-AST2600-i2cv2/20250224-140221
>>>>> base:
>> https://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git i2c/i2c-host
>>>>> patch link:
>> https://lore.kernel.org/r/20250224055936.1804279-3-ryan_chen%40aspeedtec
>> h.com
>>>>> patch subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new
>>>>> register mode driver
>>>>> config: mips-allyesconfig
>>>>> (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gL
>>>>> Dhve-lkp at intel.com/config)
>>>>> compiler: mips-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1
>>>>> build):
>>>>> (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gL
>>>>> Dhve-lkp at intel.com/reproduce)
>>>>>
>>>>> If you fix the issue in a separate patch/commit (i.e. not just a
>>>>> new version of the same patch/commit), kindly add following tags
>>>>> | Reported-by: kernel test robot <lkp at intel.com>
>>>>> | Closes:
>>>>> | https://lore.kernel.org/oe-kbuild-all/202502280902.U0gLDhve-lkp at i
>>>>> | ntel.com/
>>>>>
>>>>> All warnings (new ones prefixed by >>):
>>>>
>>>> My gosh, this is valid report. But it looks like a preexisted issue.
>>>> Can somebody fix this, please?
>>>
>>>
>>> That was three weeks ago and still no responses from Aspeed or
>>> contributors from here.
>>>
>>> I think this tells a lot about aspeedtech.com patchsets on the list.
>>
> Sorry, I don't aware this is my patches issue, could you tell me what build instruction can reproduce this?

Everything is explained in the email. You do not need two people
explaining the report, just read the report.

Best regards,
Krzysztof


From alb3rt0.m3rciai at gmail.com  Mon Mar 17 01:47:53 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Mon, 17 Mar 2025 09:47:53 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
Message-ID: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>

While playing with linux-next and imx93-11x11-evk via NFS and TFTP
I found that the dwmac-imx, nvmem-imx-ocotp-ele drivers by default are
not builtin then the I was not able to reach userland. 

The following configs were needed to reach my goal:
CONFIG_DWMAC_IMX8=y
CONFIG_STMMAC_ETH=y
CONFIG_NVMEM_IMX_OCOTP_ELE=y

is that something expected?

Regards,
Alberto


From angelogioacchino.delregno at collabora.com  Mon Mar 17 01:49:49 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 17 Mar 2025 09:49:49 +0100
Subject: [PATCH v2 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250314173858.212264-5-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
 <20250314173858.212264-5-ariel.dalessandro@collabora.com>
Message-ID: <e217363f-5492-486e-8063-8e3eed047b00@collabora.com>

Il 14/03/25 18:38, Ariel D'Alessandro ha scritto:
> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> Address Extension", which in Linux we've called "mali_lpae".
> 
> This commit adds support for conditionally enabling AARCH64_4K page
> table format. To achieve that, a "GPU optional quirks" field was added
> to `struct panfrost_features` with the related flag.
> 
> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> the HW_FEATURE_AARCH64_MMU feature flag present.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

I would've preferred the LEGACY format to be a quirk, instead of AARCH64, but
okay.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar 17 01:50:06 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 17 Mar 2025 09:50:06 +0100
Subject: [PATCH v2 6/6] drm/panfrost: Force AARCH64_4K page table format
 on MediaTek MT8192
In-Reply-To: <20250314173858.212264-7-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
 <20250314173858.212264-7-ariel.dalessandro@collabora.com>
Message-ID: <0cd19f91-2726-419c-ba92-fdb8e7a38377@collabora.com>

Il 14/03/25 18:38, Ariel D'Alessandro ha scritto:
> MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
> Panfrost supports AARCH64_4K page table format, let's enable it on this
> SoC.
> 
> Running glmark2-es2-drm [0] benchmark, reported the same performance
> score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
> this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.
> 
> [0] https://github.com/glmark2/glmark2
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar 17 01:50:08 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 17 Mar 2025 09:50:08 +0100
Subject: [PATCH v2 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature
 flag on Bifrost models
In-Reply-To: <20250314173858.212264-4-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
 <20250314173858.212264-4-ariel.dalessandro@collabora.com>
Message-ID: <d0a85b86-2876-4ab1-ba0d-92611f37b8fc@collabora.com>

Il 14/03/25 18:38, Ariel D'Alessandro ha scritto:
> Set this feature flag on all Mali Bifrost platforms as the MMU supports
> AARCH64 4K page table format.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
> Reviewed-by: Steven Price <steven.price at arm.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From angelogioacchino.delregno at collabora.com  Mon Mar 17 01:50:08 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 17 Mar 2025 09:50:08 +0100
Subject: [PATCH v2 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS
 macros
In-Reply-To: <20250314173858.212264-3-ariel.dalessandro@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
 <20250314173858.212264-3-ariel.dalessandro@collabora.com>
Message-ID: <1a98bd80-5ce9-4085-95d9-9faa93293647@collabora.com>

Il 14/03/25 18:38, Ariel D'Alessandro ha scritto:
> As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
> which makes code easier to read and reuse.
> 
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
> Reviewed-by: Steven Price <steven.price at arm.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From ryan_chen at aspeedtech.com  Mon Mar 17 01:51:30 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Mon, 17 Mar 2025 08:51:30 +0000
Subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
 mode driver
In-Reply-To: <Z9fWhGDrUbAmGRl0@smile.fi.intel.com>
References: <20250224055936.1804279-3-ryan_chen@aspeedtech.com>
 <202502280902.U0gLDhve-lkp@intel.com> <Z8GuOT5bJL7CdXX6@smile.fi.intel.com>
 <fec0a1c8-251b-491e-893d-11a8186a2128@kernel.org>
 <Z9fWhGDrUbAmGRl0@smile.fi.intel.com>
Message-ID: <OS8PR06MB7541B15342ED1C92579AE18DF2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new register
> mode driver
> 
> On Mon, Mar 17, 2025 at 08:48:03AM +0100, Krzysztof Kozlowski wrote:
> > On 28/02/2025 13:38, Andy Shevchenko wrote:
> > > On Fri, Feb 28, 2025 at 09:28:59AM +0800, kernel test robot wrote:
> > >> Hi Ryan,
> > >>
> > >> kernel test robot noticed the following build warnings:
> > >>
> > >> [auto build test WARNING on andi-shyti/i2c/i2c-host] [also build
> > >> test WARNING on linus/master v6.14-rc4 next-20250227] [If your
> > >> patch is applied to the wrong git tree, kindly drop us a note.
> > >> And when submitting patch, we suggest to use '--base' as documented
> > >> in
> > >> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> > >>
> > >> url:
> https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-i2c-asp
> eed-support-for-AST2600-i2cv2/20250224-140221
> > >> base:
> https://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git i2c/i2c-host
> > >> patch link:
> https://lore.kernel.org/r/20250224055936.1804279-3-ryan_chen%40aspeedtec
> h.com
> > >> patch subject: [PATCH v16 2/3] i2c: aspeed: support AST2600 i2c new
> > >> register mode driver
> > >> config: mips-allyesconfig
> > >> (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gL
> > >> Dhve-lkp at intel.com/config)
> > >> compiler: mips-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1
> > >> build):
> > >> (https://download.01.org/0day-ci/archive/20250228/202502280902.U0gL
> > >> Dhve-lkp at intel.com/reproduce)
> > >>
> > >> If you fix the issue in a separate patch/commit (i.e. not just a
> > >> new version of the same patch/commit), kindly add following tags
> > >> | Reported-by: kernel test robot <lkp at intel.com>
> > >> | Closes:
> > >> | https://lore.kernel.org/oe-kbuild-all/202502280902.U0gLDhve-lkp at i
> > >> | ntel.com/
> > >>
> > >> All warnings (new ones prefixed by >>):
> > >
> > > My gosh, this is valid report. But it looks like a preexisted issue.
> > > Can somebody fix this, please?
> >
> >
> > That was three weeks ago and still no responses from Aspeed or
> > contributors from here.
> >
> > I think this tells a lot about aspeedtech.com patchsets on the list.
> 
Sorry, I don't aware this is my patches issue, could you tell me what build instruction can reproduce this?

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



From krzk at kernel.org  Mon Mar 17 02:00:19 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 10:00:19 +0100
Subject: [PATCH RFC v2 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <20250317083822.891-4-jjian.zhou@mediatek.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
 <20250317083822.891-4-jjian.zhou@mediatek.com>
Message-ID: <df592920-cdf3-40fe-8357-2fbdfc0afd78@kernel.org>

On 17/03/2025 09:38, Jjian Zhou wrote:
> This patch adds document for mediatek vcp mbox.
> 
> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> ---
>  .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49 +++++++++++++++++++

Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

>  1 file changed, 49 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml

Filename based on compatible. You already got this comment. Copy paste
your filename here:

<here goes filename>

and here your compatible:

<here goes compatible>

Are the the same?

Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 17 02:12:09 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 10:12:09 +0100
Subject: [PATCH v4 1/3] dt-binding: aspeed: Add LPC PCC controller
In-Reply-To: <20250314112113.953238-2-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
 <20250314112113.953238-2-kevin_chen@aspeedtech.com>
Message-ID: <20250317-hypnotic-boobook-of-discussion-fdfe94@krzk-bin>

On Fri, Mar 14, 2025 at 07:21:11PM +0800, Kevin Chen wrote:
> Add dt-bindings for Aspeed for Aspeed LPC POST code capture controller.
> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> ---
>  .../devicetree/bindings/mfd/aspeed-lpc.yaml   | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 

Nothing improved. You already got comment that nothing improved and
you... send the same.

NAK

Instead of selectively ignoring comments, go back to review and
implement each of them.

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 17 02:13:04 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 10:13:04 +0100
Subject: [PATCH v4 2/3] ARM: dts: aspeed-g6: Add AST2600 LPC PCC support
In-Reply-To: <20250314112113.953238-3-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
 <20250314112113.953238-3-kevin_chen@aspeedtech.com>
Message-ID: <20250317-chital-of-unusual-force-a4b7b7@krzk-bin>

On Fri, Mar 14, 2025 at 07:21:12PM +0800, Kevin Chen wrote:
> The AST2600 has PCC controller in LPC, placed in LPC node.
> 
> Signed-off-by: Kevin Chen <kevin_chen at aspeedtech.com>
> ---
>  arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> index 8ed715bd53aa..f238337e02da 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
> @@ -626,6 +626,14 @@ lpc_snoop: lpc-snoop at 80 {
>  					status = "disabled";
>  				};
>  
> +				lpc_pcc: lpc-pcc at 0 {
> +					compatible = "aspeed,ast2600-lpc-pcc";
> +					reg = <0x0 0x140>;
> +					interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
> +					pcc-ports = <0x80>;

So this is 0x80 for entire SoC, then it is implied by compatible, no?

> +					status = "disabled";

Where is any DTS user of this device?

Best regards,
Krzysztof



From eddyz87 at gmail.com  Mon Mar 17 02:19:08 2025
From: eddyz87 at gmail.com (Eduard Zingerman)
Date: Mon, 17 Mar 2025 02:19:08 -0700
Subject: [PATCH bpf-next 09/11] bpf: Return PTR_ERR from push_stack()
In-Reply-To: <20250313174149.1113165-4-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	 <20250313174149.1113165-1-luis.gerhorst@fau.de>
	 <20250313174149.1113165-4-luis.gerhorst@fau.de>
Message-ID: <9083b52fd4a2d7a5a0473e858042c277c883f8b0.camel@gmail.com>

On Thu, 2025-03-13 at 18:41 +0100, Luis Gerhorst wrote:

[...]

> @@ -2011,8 +2011,10 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
>  	int err;
>  
>  	elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL);
> -	if (!elem)
> -		goto err;
> +	if (!elem) {
> +		err = -ENOMEM;
> +		goto unrecoverable_err;
> +	}

Could you please point me to a location, where exact error code
returned by updated push_stack() matters?
I checked push_stack() callgraph (in the attachment), but can't find
anything.

>  
>  	elem->insn_idx = insn_idx;
>  	elem->prev_insn_idx = prev_insn_idx;
> @@ -2022,12 +2024,19 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,

[...]

-------------- next part --------------
A non-text attachment was scrubbed...
Name: push_stack.dot
Type: text/vnd.graphviz
Size: 1706 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/d0766c57/attachment.dot>

From ryan_chen at aspeedtech.com  Mon Mar 17 02:21:57 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Mon, 17 Mar 2025 09:21:57 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
Message-ID: <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 05/03/2025 10:35, Ryan Chen wrote:
> >> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >> AST2600-i2cv2
> >>
> >> On 27/02/2025 09:19, Ryan Chen wrote:
> >>>>
> >>>>
> >>>>> aspeed,enable-byte:
> >>>>> Force i2c controller use byte mode transfer. the byte mode
> >>>>> transfer will send i2c data each byte by byte, inlcude address
> read/write.
> >>>>
> >>>> Isn't this standard FIFO mode?
> >>> Yes, it is.
> >>>>
> >>>> Why anyone would need to enable byte mode for given board?
> >>> By default, it is buffer-mode, for performance, I don't want user
> >>> enable
> >> byte-mode, it will increase CPU utilize.
> >>> But someone want to be force enable byte-mode, so I add properties.
> >>> https://patchwork.ozlabs.org/project/linux-aspeed/patch/202410070352
> >>> 35 .2254138-3-ryan_chen at aspeedtech.com/
> >>
> >>
> >> I don't see the reason why this would be a board property.
> >>
> >> I understood need for DMA because it is shared and only some of the
> >> controllers can use it. But why choice between buffer and FIFO
> >> depending on hardware?
> >
> > By default, the I2C controller runs in buffer mode. Each i2c bus have 16bytes
> buffer to transmit data.
> > Enabling byte mode will increases CPU utilization, so it is not recommended.
> > However, some user might require forcing byte mode, so I added this
> property to allow that.
> 
> 
> You are not answering the question. I asked why the choice depends on
> hardware and you answer "user might required".
> 
> Do you understand that this is about hardware, not user choices?

The AST2600 I2C controller support 3 modes. 1. Byte mode, 2.buffer mode. 3.dma mode.
Which Buffer vs byte mode. is buffer mode have 16 bytes buffer for each i2c transition.
Byte mode is 1 by 1 transfer.
So, my original submit patch is only for buffer/dma mode selection in property.
But someone in review feedback want to use byte mode, so I add byte mode property now.
If not acceptable, I can keep buffer/dma two mode selection in property.

> 
> 
> >>
> >>
> >>>>
> >>>>>
> >>>>>>
> >>>>>>> +      may require a DTS to manually allocate which controller
> >>>>>>> + can use
> >>>>>> DMA mode.
> >>>>>>> +      The "aspeed,enable-dma" property allows control of this.
> >>>>>>> +
> >>>>>>> +      In cases where one the hardware design results in a specific
> >>>>>>> +      controller handling a larger amount of data, a DTS would
> likely
> >>>>>>> +      enable DMA mode for that one controller.
> >>>>>>> +
> >>>>>>> +  aspeed,enable-byte:
> >>>>>>> +    type: boolean
> >>>>>>> +    description: |
> >>>>>>> +      I2C bus enable byte mode transfer.
> >>>>>>
> >>>>>> No, either this is expressed as lack of dma mode property or if
> >>>>>> you have three modes, then rather some enum (aspeed,transfer-mode
> >>>>>> ?)
> >>>>>
> >>>>> Thanks suggestion, I will using an enum property like
> >>>>> aspeed,transfer-mode
> >>>> instead.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>> +
> >>>>>>> +  aspeed,global-regs:
> >>>>>>> +    $ref: /schemas/types.yaml#/definitions/phandle
> >>>>>>> +    description: The phandle of i2c global register node.
> >>>>>>
> >>>>>> For what? Same question as usual: do not repeat property name,
> >>>>>> but say what is this used for and what exactly it points to.
> >>>>>>
> >>>>>> s/i2c/I2C/ but then what is "I2C global register node"? This is
> >>>>>> how you call your device in datasheet?
> >>>>>>
> >>>>> I do descript in cover, should add into the yaml file ?
> >>>>
> >>>>
> >>>> Again, cover letter does not matter. Your hardware must be explained
> here.
> >>> Will add into commit.
> >>>>
> >>>>>
> >>>>> aspeed,global-regs:
> >>>>> This global register is needed, global register is setting for new
> >>>>> clock divide control, and new register set control.
> >>>>
> >>>> So this means you implement clock controller via syscon?
> >>> No, it is just mode switch. It also explain in cover. I will add it in commit.
> >>> The legacy register layout is mix controller/target register control together.
> >> The following is add more detail description about new register
> >> layout. And new feature set add for register.
> >>>>
> >>>>>
> >>>>>>
> >>>>>>> +
> >>>>>>>  required:
> >>>>>>>    - reg
> >>>>>>>    - compatible
> >>>>>>>    - clocks
> >>>>>>>    - resets
> >>>>>>>
> >>>>>>> +allOf:
> >>>>>>> +  - $ref: /schemas/i2c/i2c-controller.yaml#
> >>>>>>> +  - if:
> >>>>>>> +      properties:
> >>>>>>> +        compatible:
> >>>>>>> +          contains:
> >>>>>>> +            const: aspeed,ast2600-i2cv2
> >>>>>>
> >>>>>> NAK, undocumented compatible.
> >>>>>
> >>>>> Sorry, I should add what kind of document about this compatible?
> >>>>
> >>>> You cannot add new compatibles without documenting them.
> >>>> Documentation is in the form of DT schema and each compatible must
> >>>> be listed (in some
> >>>> way) in compatible property description.
> >>>
> >>> Sorry, do you mean, I add following in yaml or commit message?
> >>
> >> You need to list this in compatibles first.
> >
> > I will add it in compatible in next submit.
> >
> > 	enum:
> > 		-aspeed,ast2600-i2cv2
> >>
> >>>
> >>> This series add AST2600 i2cv2 new register set driver. The i2cv2
> >>> driver is new
> >> register set that have new clock divider option for more flexiable
> generation.
> >> And also have separate i2c controller and target register set for
> >> control, patch
> >> #2 is i2c controller driver only, patch #3 is add i2c target mode driver.
> >>
> >> All this describes driver, not hardware.
> >
> > Sorry, the cover letter description the register. I will add int in commit
> message.
> >
> > -Add new clock divider option for more flexible and accurate clock
> > rate generation -Add tCKHighMin timing to guarantee SCL high pulse width.
> > -Add support dual pool buffer mode, split 32 bytes pool buffer of each
> > device into 2 x 16 bytes for Tx and Rx individually.
> > -Increase DMA buffer size to 4096 bytes and support byte alignment.
> > -Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
> > -Re-define registers for separating controller and target mode control.
> > -Support 4 individual DMA buffers for controller Tx and Rx, target Tx
> > and Rx.
> >
> > And following is new register set for package transfer sequence.
> > -New Master operation mode:
> >  S -> Aw -> P
> >  S -> Aw -> TxD -> P
> >  S -> Ar -> RxD -> P
> >  S -> Aw -> RxD -> Sr -> Ar -> TxD -> P -Bus SDA lock auto-release
> > capability for new controller DMA command mode.
> > -Bus auto timeout for new controller/target DMA mode.
> >
> > The following is two versus register layout.
> > Old:
> > {I2CD00}: Function Control Register
> > {I2CD04}: Clock and AC Timing Control Register
> > {I2CD08}: Clock and AC Timing Control Register
> > {I2CD0C}: Interrupt Control Register
> > {I2CD10}: Interrupt Status Register
> > {I2CD14}: Command/Status Register
> > {I2CD18}: Slave Device Address Register
> > {I2CD1C}: Pool Buffer Control Register
> > {I2CD20}: Transmit/Receive Byte Buffer Register
> > {I2CD24}: DMA Mode Buffer Address Register
> > {I2CD28}: DMA Transfer Length Register
> > {I2CD2C}: Original DMA Mode Buffer Address Setting
> > {I2CD30}: Original DMA Transfer Length Setting and Final Status
> >
> > New Register mode
> > {I2CC00}: Master/Slave Function Control Register
> > {I2CC04}: Master/Slave Clock and AC Timing Control Register
> > {I2CC08}: Master/Slave Transmit/Receive Byte Buffer Register
> > {I2CC0C}: Master/Slave Pool Buffer Control Register
> > {I2CM10}: Master Interrupt Control Register
> > {I2CM14}: Master Interrupt Status Register
> > {I2CM18}: Master Command/Status Register
> > {I2CM1C}: Master DMA Buffer Length Register
> > {I2CS20}: Slave~ Interrupt Control Register
> > {I2CS24}: Slave~ Interrupt Status Register
> > {I2CS28}: Slave~ Command/Status Register
> > {I2CS2C}: Slave~ DMA Buffer Length Register
> > {I2CM30}: Master DMA Mode Tx Buffer Base Address
> > {I2CM34}: Master DMA Mode Rx Buffer Base Address
> > {I2CS38}: Slave~ DMA Mode Tx Buffer Base Address
> > {I2CS3C}: Slave~ DMA Mode Rx Buffer Base Address
> > {I2CS40}: Slave Device Address Register
> > {I2CM48}: Master DMA Length Status Register
> > {I2CS4C}: Slave  DMA Length Status Register
> > {I2CC50}: Current DMA Operating Address Status
> > {I2CC54}: Current DMA Operating Length  Status
> 
> I don't understand anything from that and how is this relevant to our
> discussion.

Sorry, I don't catch your wanted. 
I assume you want to know new mode register set compare original register set.
> 
> >
> >>
> >>>
> >>> The legacy register layout is mix controller/target register control together.
> >> The following is add more detail description about new register
> >> layout. And new feature set add for register.
> >>>
> >>> -Add new clock divider option for more flexible and accurate clock
> >>> rate
> >> generation -Add tCKHighMin timing to guarantee SCL high pulse width.
> >>> -Add support dual pool buffer mode, split 32 bytes pool buffer of
> >>> each device
> >> into 2 x 16 bytes for Tx and Rx individually.
> >>> -Increase DMA buffer size to 4096 bytes and support byte alignment.
> >>> -Re-define the base address of BUS1 ~ BUS16 and Pool buffer.
> >>> -Re-define registers for separating controller and target mode control.
> >>> -Support 4 individual DMA buffers for controller Tx and Rx, target Tx and
> Rx.
> >>
> >> Does it mean hardware changed on AST2600?
> > No Hw change, it is different mode setting will have another mode register
> setting.
> > Mode setting is in global register, I will add in next commit message
> 
> Neither this.
> 
> So it seems you describe already existing and documented I2C, but for some
> reason you want second compatible. The problem is that you do not provide
> reason from the point of view of bindings.
> 
> To summarize: what your users want - don't care. Start properly describing
> hardware and your SoC.

OK, for ast2600 i2c controller have two register mode setting.
One, I call it is old register setting, that is right now i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus",
And there have a global register that can set i2c controller as new mode register set. 
That I am going to drive. That I post is all register in new an old register list.

For example, 
Global register [2] = 0 => i2c present as old register set
Global register [2] = 1 => i2c present as new register set
> 
> 
> >
> > I2CG00: Device Master Mode Interrupt Status Register (I2CG0C[3]=1)
> > I2CG00: Device Master/Slave Mode Interrupt Status Register
> > (I2CG0C[3]=0)
> > I2CG04: Device Slave Mode Interrupt Status Register
> > I2CG0C: Global Control Register
> > I2CG10: New Clock Divider Control Register (I2CG0C[1] = 1)
> >
> >> Or these are different devices
> >> than aspeed,ast2600-i2c-bus? If this is not a different device, how
> >> one SoC can have two different flavors of same device in the same instance?
> >
> > When global setting for new, will new register mapping, no setting will keep
> old register mapping.
> 
> 
> I cannot parse this.
> 
> 
> Best regards,
> Krzysztof

From ryan.roberts at arm.com  Mon Mar 17 02:28:48 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 17 Mar 2025 09:28:48 +0000
Subject: [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t
In-Reply-To: <20250317061818.16244-3-anshuman.khandual@arm.com>
References: <20250317061818.16244-1-anshuman.khandual@arm.com>
 <20250317061818.16244-3-anshuman.khandual@arm.com>
Message-ID: <16c12c3f-f2c2-45fa-9db6-4dfaeb002059@arm.com>

On 17/03/2025 06:18, Anshuman Khandual wrote:
> Page table entry's value, mask and protection are represented with pteval_t
> data type format not u64 that has been assumed while dumping the page table
> entries. Replace all such u64 instances with pteval_t instead as required.
> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
>  arch/arm64/include/asm/ptdump.h | 8 ++++----
>  arch/arm64/mm/ptdump.c          | 2 +-
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
> index e5da9ce8a515..476a870489b9 100644
> --- a/arch/arm64/include/asm/ptdump.h
> +++ b/arch/arm64/include/asm/ptdump.h
> @@ -24,8 +24,8 @@ struct ptdump_info {
>  };
>  
>  struct ptdump_prot_bits {
> -	u64		mask;
> -	u64		val;
> +	pteval_t	mask;
> +	pteval_t	val;

Given Ard's suggestion of using "ptdesc" as a generic term for PTDESC_SHIFT (or
PTDESC_ORDER, or whatever we ended up calling it), I wonder if it would be
cleaner to do the same with the types? We could have a ptdesc_t, which is
typedef'ed as u64 (or u128), then pteval_t, pmdval_t, ..., could all be
typedef'ed as ptdesc_t. Then for code that just wants a generic pgtable
descriptor value, we can use that type to indicate that it can be at any level.

Thanks,
Ryan

>  	const char	*set;
>  	const char	*clear;
>  };
> @@ -34,7 +34,7 @@ struct ptdump_pg_level {
>  	const struct ptdump_prot_bits *bits;
>  	char name[4];
>  	int num;
> -	u64 mask;
> +	pteval_t mask;
>  };
>  
>  /*
> @@ -51,7 +51,7 @@ struct ptdump_pg_state {
>  	const struct mm_struct *mm;
>  	unsigned long start_address;
>  	int level;
> -	u64 current_prot;
> +	pteval_t current_prot;
>  	bool check_wx;
>  	unsigned long wx_pages;
>  	unsigned long uxn_pages;
> diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
> index fd1610b4fd15..a5651be95868 100644
> --- a/arch/arm64/mm/ptdump.c
> +++ b/arch/arm64/mm/ptdump.c
> @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
>  	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
>  	struct ptdump_pg_level *pg_level = st->pg_level;
>  	static const char units[] = "KMGTPE";
> -	u64 prot = 0;
> +	pteval_t prot = 0;
>  
>  	/* check if the current level has been folded dynamically */
>  	if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) ||



From geert at linux-m68k.org  Mon Mar 17 02:30:28 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 17 Mar 2025 10:30:28 +0100
Subject: [PATCH] arm64: dts: renesas: r8a779f4: Add UFS tuning parameters
 in E-FUSE
In-Reply-To: <3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas@glider.be>
References: <3e4fca228eb049d54a1ae520104558505dbdf803.1741179629.git.geert+renesas@glider.be>
Message-ID: <CAMuHMdVPcDZsMsjc8WdVC7vnt_BPVNwiXyB+AEzO04f2eq5cmg@mail.gmail.com>

On Wed, 5 Mar 2025 at 14:35, Geert Uytterhoeven <geert+renesas at glider.be> wrote:
> Describe the location in the E-FUSE block of the PLL and AFE tuning
> parameters for the Universal Flash Storage controller.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>

Thanks, will queue in renesas-devel for v6.16.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From csokas.bence at prolan.hu  Mon Mar 17 02:34:42 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 17 Mar 2025 10:34:42 +0100
Subject: [PATCH v5 1/2] pm: runtime: Add new devm functions
In-Reply-To: <20250317093445.361821-1-csokas.bence@prolan.hu>
References: <20250317093445.361821-1-csokas.bence@prolan.hu>
Message-ID: <20250317093445.361821-2-csokas.bence@prolan.hu>

Add `devm_pm_runtime_set_active()` and
`devm_pm_runtime_get_noresume()` for
simplifying common use cases in drivers.

Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---
 drivers/base/power/runtime.c | 36 ++++++++++++++++++++++++++++++++++++
 include/linux/pm_runtime.h   |  4 ++++
 2 files changed, 40 insertions(+)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 9589ccb0fda2..821a8b4961d4 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1568,6 +1568,24 @@ void pm_runtime_enable(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(pm_runtime_enable);
 
+static void pm_runtime_set_suspended_action(void *data)
+{
+	pm_runtime_set_suspended(data);
+}
+
+/**
+ * devm_pm_runtime_set_active - devres-enabled version of pm_runtime_set_active.
+ *
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_set_active(struct device *dev)
+{
+	pm_runtime_set_active(dev);
+
+	return devm_add_action_or_reset(dev, pm_runtime_set_suspended_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_set_active);
+
 static void pm_runtime_disable_action(void *data)
 {
 	pm_runtime_dont_use_autosuspend(data);
@@ -1590,6 +1608,24 @@ int devm_pm_runtime_enable(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
 
+static void pm_runtime_put_noidle_action(void *data)
+{
+	pm_runtime_put_noidle(data);
+}
+
+/**
+ * devm_pm_runtime_get_noresume - devres-enabled version of pm_runtime_get_noresume.
+ *
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_get_noresume(struct device *dev)
+{
+	pm_runtime_get_noresume(dev);
+
+	return devm_add_action_or_reset(dev, pm_runtime_put_noidle_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_get_noresume);
+
 /**
  * pm_runtime_forbid - Block runtime PM of a device.
  * @dev: Device to handle.
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 7fb5a459847e..364355da349a 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -96,7 +96,9 @@ extern void pm_runtime_new_link(struct device *dev);
 extern void pm_runtime_drop_link(struct device_link *link);
 extern void pm_runtime_release_supplier(struct device_link *link);
 
+int devm_pm_runtime_set_active(struct device *dev);
 extern int devm_pm_runtime_enable(struct device *dev);
+int devm_pm_runtime_get_noresume(struct device *dev);
 
 /**
  * pm_suspend_ignore_children - Set runtime PM behavior regarding children.
@@ -294,7 +296,9 @@ static inline bool pm_runtime_blocked(struct device *dev) { return true; }
 static inline void pm_runtime_allow(struct device *dev) {}
 static inline void pm_runtime_forbid(struct device *dev) {}
 
+static inline int devm_pm_runtime_set_active(struct device *dev) { return 0; }
 static inline int devm_pm_runtime_enable(struct device *dev) { return 0; }
+static inline int devm_pm_runtime_get_noresume(struct device *dev) { return 0; }
 
 static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {}
 static inline void pm_runtime_get_noresume(struct device *dev) {}
-- 
2.48.1




From csokas.bence at prolan.hu  Mon Mar 17 02:34:41 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 17 Mar 2025 10:34:41 +0100
Subject: [PATCH v5 0/2] Add more devm_ functions to fix PM imbalance in spi/atmel-quadspi.c
Message-ID: <20250317093445.361821-1-csokas.bence@prolan.hu>

The probe() function of the atmel-quadspi driver got quite convoluted,
especially since the addition of SAMA7G5 support, that was forward-ported
from an older vendor kernel. During the port, a bug was introduced, where
the PM get() and put() calls were imbalanced. To alleivate this - and
similar problems in the future - an effort was made to migrate as many
functions as possible, to their devm_ managed counterparts. The few
functions, which did not yet have a devm_ variant, are added in patch 1 of
this series. Patch 2 then uses these APIs to fix the probe() function.

Change in v4:
* the DMA cleanup was split out and will be submitted separately for 6.15

Change in v5:
* rebased to linux-pm/linux-next, will now target 6.15

Links to previous versions:
pre-series:
https://lore.kernel.org/linux-kernel/20250114222851.1023194-1-csokas.bence at prolan.hu/
v1:
https://lore.kernel.org/linux-kernel/20250115160244.1102881-1-csokas.bence at prolan.hu/
v2:
https://lore.kernel.org/linux-kernel/20250124085221.766303-8-csokas.bence at prolan.hu/
v3:
https://lore.kernel.org/linux-kernel/20250207124802.165408-1-csokas.bence at prolan.hu/
v4:
https://lore.kernel.org/linux-kernel/20250210111008.248929-1-csokas.bence at prolan.hu/

Bence Cs?k?s (2):
  pm: runtime: Add new devm functions
  spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API

 drivers/base/power/runtime.c | 36 ++++++++++++++++++++++++++++++++++++
 drivers/spi/atmel-quadspi.c  | 18 +++++-------------
 include/linux/pm_runtime.h   |  4 ++++
 3 files changed, 45 insertions(+), 13 deletions(-)

-- 
2.48.1




From andriy.shevchenko at linux.intel.com  Mon Mar 17 02:27:37 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 17 Mar 2025 11:27:37 +0200
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <0db2a42f-d393-4e75-afbf-cf30c0e06cce@gmail.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
 <df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
 <Z9LQ0O34EUM8WZku@smile.fi.intel.com>
 <20250316094112.6731bd01@jic23-huawei>
 <50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>
 <Z9fUmo5wp3EcNWzm@smile.fi.intel.com>
 <0db2a42f-d393-4e75-afbf-cf30c0e06cce@gmail.com>
Message-ID: <Z9frCUqRTD0i1Faq@smile.fi.intel.com>

On Mon, Mar 17, 2025 at 10:42:07AM +0200, Matti Vaittinen wrote:
> On 17/03/2025 09:51, Andy Shevchenko wrote:
> > On Mon, Mar 17, 2025 at 09:11:08AM +0200, Matti Vaittinen wrote:
> > > On 16/03/2025 11:41, Jonathan Cameron wrote:
> > > > On Thu, 13 Mar 2025 14:34:24 +0200
> > > > Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:
> > > > > On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:

...

> > > > > > +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
> > > > > > +				&sun20i_gpadc_chan_template, -1, &channels);
> > > > > > +	if (num_channels < 0)
> > > > > > +		return num_channels;
> > > > > > +
> > > > > >    	if (num_channels == 0)
> > > > > >    		return dev_err_probe(dev, -ENODEV, "no channel children\n");
> > > > > 
> > > > > Note, this what I would expected in your helper to see, i.e. separated cases
> > > > > for < 0 (error code) and == 0, no channels.
> > > > > 
> > > > > Also, are all users going to have this check? Usually in other similar APIs
> > > > > we return -ENOENT. And user won't need to have an additional check in case of
> > > > > 0 being considered as an error case too.
> > > > In a few cases we'll need to do the dance the other way in the caller.
> > > > So specifically check for -ENOENT and not treat it as an error.
> > > > 
> > > > That stems from channel nodes being optionally added to drivers after
> > > > they have been around a while (usually to add more specific configuration)
> > > > and needing to maintain old behaviour of presenting all channels with default
> > > > settings.
> > > > 
> > > > I agree that returning -ENOENT is a reasonable way to handle this.
> > > 
> > > I agree - but I'm going to use -ENODEV instead of -ENOENT because that's
> > > what the current callers return if they find no channels. That way the
> > > drivers can return the value directly without converting -ENOENT to -ENODEV.
> > 
> > ENODEV can be easily clashed with other irrelevant cases,
> 
> Can you please explain what cases?

When it's a code path that returns the same error code for something different.

> > ENOENT is the correct
> > error code.
> 
> I kind of agree if we look this from the fwnode perspective. But, when we
> look this from the intended user's perspective, I can very well understand
> the -ENODEV. Returning -ENODEV from ADC driver's probe which can't find any
> of the channels feels correct to me.

Okay, it seems we have got yet another disagreement as I think this has to
be ENOENT. Because this is related to the firmware description and not real
hardware discovery path. If it is the latter, I may fully agree on ENODEV
choice. But AFAICS it's not the case here.

> > If drivers return this instead of another error code, nothing bad
> > happen, it's not an ABI path, correct?
> 
> I don't know if failure returned from a probe is an ABI. I still feel
> -ENODEV is correct value,

And I have the opposite opinion. I think ENODEV is _incorrect_ choice
in this case.

> and I don't want to change it for existing users -
> and I think also new ADC drivers should use -ENODEV if they find no channels
> at all.

Again, the problem is that you are trying to apply the error code for HW to the
information that comes from FW.

> Besides that I think -ENODEV to be right, changing it to -ENOENT for
> existing callers requires a buy-in from Jonathan (and/or) the driver
> maintainers.

Yeah, will wait for Jonathan to judge, but I think you can find rationale above.

-- 
With Best Regards,
Andy Shevchenko




From maz at kernel.org  Mon Mar 17 02:27:52 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 17 Mar 2025 09:27:52 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>
	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<86r033olwv.wl-maz@kernel.org>
	<SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<87tt7y7j6r.wl-maz@kernel.org>
	<SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
Message-ID: <8634fcnh0n.wl-maz@kernel.org>

On Mon, 17 Mar 2025 05:55:55 +0000,
Ankit Agrawal <ankita at nvidia.com> wrote:
> 
> >> For my education, what is an accepted way to communicate this? Please let
> >> me know if there are any relevant examples that you may be aware of.
> >
> > A KVM capability is what is usually needed.
> 
> I see. If IIUC, this would involve a corresponding Qemu (usermode) change
> to fetch the new KVM cap. Then it could fail in case the FWB is not
> supported with some additional conditions (so that the currently supported
> configs with !FWB won't break on usermode). 
> 
> The proposed code change is to map in S2 as NORMAL when vma flags
> has VM_PFNMAP. However, Qemu cannot know that driver is mapping
> with PFNMAP or not. So how may Qemu decide whether it is okay to
> fail for !FWB or not?

This is not about FWB as far as userspace is concerned. This is about
PFNMAP as non-device memory. If the host doesn't have FWB, then the
"PFNMAP as non-device memory" capability doesn't exist, and userspace
fails early.

Userspace must also have some knowledge of what device it obtains the
mapping from, and whether that device requires some extra host
capability to be assigned to the guest.

You can then check whether the VMA associated with the memslot is
PFNMAP or not, if the memslot has been enabled for PFNMAP mappings
(either globally or on a per-memslot basis, I don't really care).

	M.

-- 
Without deviation from the norm, progress is not possible.


From vladimir.oltean at nxp.com  Mon Mar 17 02:28:08 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 11:28:08 +0200
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314123715.fivq2cbczd4khxkk@skbuf>
 <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250317092808.jel2au3cgfwblaxk@skbuf>

Hi Wei,

On Fri, Mar 14, 2025 at 03:48:21PM +0200, Wei Fang wrote:
> > I mean, I was just suggesting to group the macros with the macros, and
> > the struct fields with the struct fields. Mixing them together looks a
> > bit messy to me. Even worse in the definition of "union netc_cbd" which
> > IMO needs to be reconsidered a bit (a hint given below).
> 
> I think this is a matter of personal preference. I was inspired by some
> of Intel's structure definitions. I think this method allows me to quickly
> understand what fields the member consists of and what bits each field
> occupies.
(...)
> Thanks, but we have added fully NTMP support in downstream, it's a great
> challenge for me to convert it to the 'packing' method. I don't think I have
> too much time to do this conversion. And I also need some time to figure
> out how to use it and whether it is worth doing so.

Ok, I'm not forcing you to use pack_fields(), but given the fact that
bit field overlap is now something that has to be manually checked, and
a bug of this kind already exists in this set, you will have to wait for
me, or other reviewers, to go through the bit field definitions from the
entire set.

> > And I agree with you, I also don't want ntmp_private.h to be exposed to
> > the NTMP API consumers, and I wasn't suggesting that. I just want the
> > NTMP API to spare consumer drivers of the gory details, like for example
> > the buffer layout of a MAC filtering entry, reserved fields, things like
> > that. What I was saying is to keep the buffer layout private to
> > ntmp_private.h, and expose a more abstract data structure to API
> > consumers.
> 
> Sorry, I don't fully understand, for example, if we place the definition
> of "struct maft_keye_data" in ntmp_private.h, how does the debugfs
> get the information from "struct maft_keye_data"? Add a helper function
> in the NTMP driver and export it to enetc driver? And how does
> enetc4_pf_add_si_mac_exact_filter() to set the mac address to "struct
> maft_keye_data", add another helper? If so, I think it is more complicated.

Well, my complaint, which has to do with style and personal preference,
is that exposing packed data structures to NTMP API clients puts an
unnecessary burden on them. For example, NTMP users have to call cpu_to_le16()
to populate data.cfge.si_bitmap. A bug in the packed layout will
potentially have to be fixed in multiple places. The two options for a
more high-level NTMP API that I see are:
- You expose pointers to the packed data structures, but API functions
  provide getters and setters, and the exact buffer layout is only known
  to the NTMP layer.
- The API functions expose "unpacked" data structures, which are more
  abstract and don't contain reserved fields and are in CPU native
  endianness, and the NTMP layer packs them to buffers, either using
  pack_fields() or manually.

Claudiu, what do you think? I can withdraw the request to hide packed
MAFT (and other) struct definitions from include/linux/fsl/ntmp.h if you
think they're fine there.

> > Thank you for posting the downstream layout of struct ntmp_priv which I
> > was already aware of. What I was saying is that the word "private" means
> > an aspect of the implementation which is hidden from other code layers.
> > There's nothing "private" here if the NTMP layer has access to the
> > definition of this structure. I was asking whether you agree that it's
> > more adequate to name this structure "ntmp_client", since it represents
> > the data associated with a consumer of the NTMP API - a NETC SI or (in
> > the future) the switch. Or some other name. But the word "private" seems
> > misused.
> 
> Okay, it seems to make you feel confused, let me rename it later, how about
> "ntmp_user"?

"ntmp_user" works for me better than "ntmp_priv", thanks. Are you also
going to make the API functions from include/linux/fsl/ntmp.h take
"struct ntmp_user *" as first argument, rather than "struct netc_cbdrs *"?


From csokas.bence at prolan.hu  Mon Mar 17 02:34:43 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 17 Mar 2025 10:34:43 +0100
Subject: [PATCH v5 2/2] spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API
In-Reply-To: <20250317093445.361821-1-csokas.bence@prolan.hu>
References: <20250317093445.361821-1-csokas.bence@prolan.hu>
Message-ID: <20250317093445.361821-3-csokas.bence@prolan.hu>

Fix unbalanced PM in error path of `atmel_qspi_probe()`
by using `devm_pm_runtime_*()` functions.

Reported-by: Alexander Dahl <ada at thorsis.com>
Closes: https://lore.kernel.org/linux-spi/20250110-paycheck-irregular-bcddab1276c7 at thorsis.com/
Fixes: 5af42209a4d2 ("spi: atmel-quadspi: Add support for sama7g5 QSPI")
Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---
 drivers/spi/atmel-quadspi.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index d8c9be64d006..ddd12600a6f1 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1439,22 +1439,18 @@ static int atmel_qspi_probe(struct platform_device *pdev)
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
 	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_noresume(&pdev->dev);
+	devm_pm_runtime_set_active(&pdev->dev);
+	devm_pm_runtime_enable(&pdev->dev);
+	devm_pm_runtime_get_noresume(&pdev->dev);
 
 	err = atmel_qspi_init(aq);
 	if (err)
 		goto dma_release;
 
 	err = spi_register_controller(ctrl);
-	if (err) {
-		pm_runtime_put_noidle(&pdev->dev);
-		pm_runtime_disable(&pdev->dev);
-		pm_runtime_set_suspended(&pdev->dev);
-		pm_runtime_dont_use_autosuspend(&pdev->dev);
+	if (err)
 		goto dma_release;
-	}
+
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
 
@@ -1533,10 +1529,6 @@ static void atmel_qspi_remove(struct platform_device *pdev)
 		 */
 		dev_warn(&pdev->dev, "Failed to resume device on remove\n");
 	}
-
-	pm_runtime_disable(&pdev->dev);
-	pm_runtime_dont_use_autosuspend(&pdev->dev);
-	pm_runtime_put_noidle(&pdev->dev);
 }
 
 static int __maybe_unused atmel_qspi_suspend(struct device *dev)
-- 
2.48.1




From vladimir.oltean at nxp.com  Mon Mar 17 02:42:59 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 11:42:59 +0200
Subject: [PATCH v4 net-next 03/14] net: enetc: move generic MAC filterng
 interfaces to enetc-core
In-Reply-To: <20250311053830.1516523-4-wei.fang@nxp.com>
 <20250311053830.1516523-4-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-4-wei.fang@nxp.com>
 <20250311053830.1516523-4-wei.fang@nxp.com>
Message-ID: <20250317094259.b6mwygvr75lxgkwh@skbuf>

title: s/filterng/filtering/

On Tue, Mar 11, 2025 at 01:38:19PM +0800, Wei Fang wrote:
> Although only ENETC PF can access the MAC address filter table, the table
> entries can specify MAC address filtering for one or more SIs based on
> SI_BITMAP, which means that the table also supports MAC address filtering
> for VFs.
> 
> Currently, only the ENETC v1 PF driver supports MAC address filtering. In
> order to add the MAC address filtering support for the ENETC v4 PF driver
> and VF driver in the future, the relevant generic interfaces are moved to
> the enetc-core driver. At the same time, the struct enetc_mac_filter is
> moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
> PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
> MAC address filtering.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---

For this series I don't see any VF implementation of ndo_set_rx_mode().
I don't think you have to move struct enetc_mac_filter from struct enetc_pf
to struct enetc_si, so please don't do that until there is a justification
for it that is contained in the same patch set, and the two can be
evaluated together.

Moving enetc_add_mac_addr_ht_filter() and enetc_reset_mac_addr_filter()
to enetc.c seems fine.


From m.felsch at pengutronix.de  Mon Mar 17 02:45:18 2025
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 17 Mar 2025 10:45:18 +0100
Subject: [PATCH] soc: imx: Dump higher 64bits UID
In-Reply-To: <20250314065225.442717-1-peng.fan@oss.nxp.com>
References: <20250314065225.442717-1-peng.fan@oss.nxp.com>
Message-ID: <20250317094518.yf2hbq5sjl7lgfwb@pengutronix.de>

Hi Peng,

On 25-03-14, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan at nxp.com>
> 
> i.MX8MP UID is actually 128bits and partitioned into two parts.
> The 1st 64bits are at 0x410 and 0x420, and 2nd 64bits are at 0xE00
> and 0xE10.
> 
> Dump the whole 128bits for i.MX8MP, by introducing soc_uid_h.

Thanks for taking care of this :) We noticed that this is crucial for
burning the field-return fuse to keep the LOCK fuse unlocked.

> Signed-off-by: Peng Fan <peng.fan at nxp.com>
> ---
>  drivers/soc/imx/soc-imx8m.c | 29 +++++++++++++++++++++--------
>  1 file changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
> index 3ed8161d7d28..02d8c85e9a28 100644
> --- a/drivers/soc/imx/soc-imx8m.c
> +++ b/drivers/soc/imx/soc-imx8m.c
> @@ -24,13 +24,15 @@
>  #define OCOTP_UID_HIGH			0x420
>  
>  #define IMX8MP_OCOTP_UID_OFFSET		0x10
> +#define IMX8MP_OCOTP_UID_HIGH		0xE00
>  
>  /* Same as ANADIG_DIGPROG_IMX7D */
>  #define ANADIG_DIGPROG_IMX8MM	0x800
>  
>  struct imx8_soc_data {
>  	char *name;
> -	int (*soc_revision)(u32 *socrev, u64 *socuid);
> +	int (*soc_revision)(u32 *socrev, u64 *socuid, u64 *socuid_h);
> +	bool uid_len_128;

Albeit your patch is not wrong, it could be far simpler if we redefine
the soc_revision to serial_number. This way each SoC can specify 
the dedicated mechanism of setting the serial number. Going this way we
need two patches, the first one is converting the logic and the 2nd one
is adding a dedicated hook for the i.MX8MP.

Regards,
  Marco

>  };
>  
>  #ifdef CONFIG_HAVE_ARM_SMCCC
> @@ -49,7 +51,7 @@ static u32 imx8mq_soc_revision_from_atf(void)
>  static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
>  #endif
>  
> -static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
> +static int imx8mq_soc_revision(u32 *socrev, u64 *socuid, u64 *socuid_h)
>  {
>  	struct device_node *np __free(device_node) =
>  		of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
> @@ -102,7 +104,7 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
>  	return ret;
>  }
>  
> -static int imx8mm_soc_uid(u64 *socuid)
> +static int imx8mm_soc_uid(u64 *socuid, u64 *socuid_h)
>  {
>  	struct device_node *np __free(device_node) =
>  		of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
> @@ -131,6 +133,12 @@ static int imx8mm_soc_uid(u64 *socuid)
>  	*socuid <<= 32;
>  	*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
>  
> +	if (offset) {
> +		*socuid_h = readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10);
> +		*socuid_h <<= 32;
> +		*socuid_h |= readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH);
> +	}
> +
>  	clk_disable_unprepare(clk);
>  	clk_put(clk);
>  
> @@ -139,7 +147,7 @@ static int imx8mm_soc_uid(u64 *socuid)
>  	return ret;
>  }
>  
> -static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
> +static int imx8mm_soc_revision(u32 *socrev, u64 *socuid, u64 *socuid_h)
>  {
>  	struct device_node *np __free(device_node) =
>  		of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
> @@ -156,7 +164,7 @@ static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
>  
>  	iounmap(anatop_base);
>  
> -	return imx8mm_soc_uid(socuid);
> +	return imx8mm_soc_uid(socuid, socuid_h);
>  }
>  
>  static const struct imx8_soc_data imx8mq_soc_data = {
> @@ -177,6 +185,7 @@ static const struct imx8_soc_data imx8mn_soc_data = {
>  static const struct imx8_soc_data imx8mp_soc_data = {
>  	.name = "i.MX8MP",
>  	.soc_revision = imx8mm_soc_revision,
> +	.uid_len_128 = true,
>  };
>  
>  static __maybe_unused const struct of_device_id imx8_soc_match[] = {
> @@ -211,7 +220,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
>  	const struct of_device_id *id;
>  	struct soc_device *soc_dev;
>  	u32 soc_rev = 0;
> -	u64 soc_uid = 0;
> +	u64 soc_uid = 0, soc_uid_h = 0;
>  	int ret;
>  
>  	soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
> @@ -232,7 +241,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
>  	if (data) {
>  		soc_dev_attr->soc_id = data->name;
>  		if (data->soc_revision) {
> -			ret = data->soc_revision(&soc_rev, &soc_uid);
> +			ret = data->soc_revision(&soc_rev, &soc_uid, &soc_uid_h);
>  			if (ret)
>  				return ret;
>  		}
> @@ -242,7 +251,11 @@ static int imx8m_soc_probe(struct platform_device *pdev)
>  	if (!soc_dev_attr->revision)
>  		return -ENOMEM;
>  
> -	soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
> +	if (data && data->uid_len_128)
> +		soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX%016llX",
> +							soc_uid_h, soc_uid);
> +	else
> +		soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
>  	if (!soc_dev_attr->serial_number)
>  		return -ENOMEM;
>  
> -- 
> 2.37.1
> 
> 
> 


From xianwei.zhao at amlogic.com  Mon Mar 17 02:51:46 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Mon, 17 Mar 2025 17:51:46 +0800
Subject: [PATCH v4 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <4cec908c-1412-4e18-959d-b71c9ec21eb4@kernel.org>
References: <20250313-a4-a5-reset-v4-0-8076f684d6cf@amlogic.com>
 <20250313-a4-a5-reset-v4-2-8076f684d6cf@amlogic.com>
 <20250314-tested-husky-of-force-1ccdca@krzk-bin>
 <3dceafbf-49d4-4084-bfae-74384e187941@amlogic.com>
 <4cec908c-1412-4e18-959d-b71c9ec21eb4@kernel.org>
Message-ID: <bea10706-46db-4162-abc5-24e0051d4051@amlogic.com>

Hi Krzysztof,

On 2025/3/17 15:28, Krzysztof Kozlowski wrote:
> [ EXTERNAL EMAIL ]
> 
> On 17/03/2025 03:49, Kelvin Zhang wrote:
>>>
>>> Why do you have on the bus devices with bus addressing and without it?
>>> What sort of bus is it?
>>
>> Are you referring to the 'apb'?
>> If so, the 'apb' bus is defined in
>> arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi.
>>
>> apb: bus at fe000000 {
>>           compatible = "simple-bus";
>>           reg = <0x0 0xfe000000 0x0 0x480000>;
>>           #address-cells = <2>;
>>           #size-cells = <2>;
>>           ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>>
>>>
>>>>         periphs_pinctrl: pinctrl {
> 
> Then what the heck is this?
> 

I will fix it and add the unit address to the pinctrl node.

>>>>                 compatible = "amlogic,pinctrl-a4";
>>>>                 #address-cells = <2>;
>>>
>>> Best regards,
>>> Krzysztof
>>>
>>
> 
> 
> Best regards,
> Krzysztof
> 
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic


From wei.fang at nxp.com  Mon Mar 17 02:55:26 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Mon, 17 Mar 2025 09:55:26 +0000
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250317092808.jel2au3cgfwblaxk@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314123715.fivq2cbczd4khxkk@skbuf>
 <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250317092808.jel2au3cgfwblaxk@skbuf>
Message-ID: <PAXPR04MB85102185D0A4C30F0688AA5488DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Fri, Mar 14, 2025 at 03:48:21PM +0200, Wei Fang wrote:
> > > I mean, I was just suggesting to group the macros with the macros, and
> > > the struct fields with the struct fields. Mixing them together looks a
> > > bit messy to me. Even worse in the definition of "union netc_cbd" which
> > > IMO needs to be reconsidered a bit (a hint given below).
> >
> > I think this is a matter of personal preference. I was inspired by some
> > of Intel's structure definitions. I think this method allows me to quickly
> > understand what fields the member consists of and what bits each field
> > occupies.
> (...)
> > Thanks, but we have added fully NTMP support in downstream, it's a great
> > challenge for me to convert it to the 'packing' method. I don't think I have
> > too much time to do this conversion. And I also need some time to figure
> > out how to use it and whether it is worth doing so.
> 
> Ok, I'm not forcing you to use pack_fields(), but given the fact that
> bit field overlap is now something that has to be manually checked, and
> a bug of this kind already exists in this set, you will have to wait for
> me, or other reviewers, to go through the bit field definitions from the
> entire set.
> 
> > > And I agree with you, I also don't want ntmp_private.h to be exposed to
> > > the NTMP API consumers, and I wasn't suggesting that. I just want the
> > > NTMP API to spare consumer drivers of the gory details, like for example
> > > the buffer layout of a MAC filtering entry, reserved fields, things like
> > > that. What I was saying is to keep the buffer layout private to
> > > ntmp_private.h, and expose a more abstract data structure to API
> > > consumers.
> >
> > Sorry, I don't fully understand, for example, if we place the definition
> > of "struct maft_keye_data" in ntmp_private.h, how does the debugfs
> > get the information from "struct maft_keye_data"? Add a helper function
> > in the NTMP driver and export it to enetc driver? And how does
> > enetc4_pf_add_si_mac_exact_filter() to set the mac address to "struct
> > maft_keye_data", add another helper? If so, I think it is more complicated.
> 
> Well, my complaint, which has to do with style and personal preference,
> is that exposing packed data structures to NTMP API clients puts an
> unnecessary burden on them. For example, NTMP users have to call
> cpu_to_le16()
> to populate data.cfge.si_bitmap. A bug in the packed layout will
> potentially have to be fixed in multiple places. The two options for a
> more high-level NTMP API that I see are:
> - You expose pointers to the packed data structures, but API functions
>   provide getters and setters, and the exact buffer layout is only known
>   to the NTMP layer.
> - The API functions expose "unpacked" data structures, which are more
>   abstract and don't contain reserved fields and are in CPU native
>   endianness, and the NTMP layer packs them to buffers, either using
>   pack_fields() or manually.
> 

Actually I did this is the original version, I mean in downstream kernel 6.6
tree. I add a "ntmp_mfe" in ntmp.h like below

struct ntmp_mfe {
	u8 mac[ETH_ALEN];
	u16 si_bitmap;
};

And the conversion was done by the NTMP driver. But then I found that this was
very troublesome. We get data from kernel "struct A,B,C", then the enetc driver
converts them to "struct D", and finally the ntmp driver converts it to "struct E".
So I thought why don't we convert "struct A,B,C" to "struct E" from the beginning?
After all, these data structures are only used by enetc and netc switch drivers, so
in kernel 6.12, I changed it to the current way.

> Claudiu, what do you think? I can withdraw the request to hide packed
> MAFT (and other) struct definitions from include/linux/fsl/ntmp.h if you
> think they're fine there.
> 
> > > Thank you for posting the downstream layout of struct ntmp_priv which I
> > > was already aware of. What I was saying is that the word "private" means
> > > an aspect of the implementation which is hidden from other code layers.
> > > There's nothing "private" here if the NTMP layer has access to the
> > > definition of this structure. I was asking whether you agree that it's
> > > more adequate to name this structure "ntmp_client", since it represents
> > > the data associated with a consumer of the NTMP API - a NETC SI or (in
> > > the future) the switch. Or some other name. But the word "private" seems
> > > misused.
> >
> > Okay, it seems to make you feel confused, let me rename it later, how about
> > "ntmp_user"?
> 
> "ntmp_user" works for me better than "ntmp_priv", thanks. Are you also
> going to make the API functions from include/linux/fsl/ntmp.h take
> "struct ntmp_user *" as first argument, rather than "struct netc_cbdrs *"?

I think we do not need to keep "struct netc_cbdrs", it can be integrated into
"struct ntmp_user".



From dietmar.eggemann at arm.com  Mon Mar 17 02:56:43 2025
From: dietmar.eggemann at arm.com (Dietmar Eggemann)
Date: Mon, 17 Mar 2025 10:56:43 +0100
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <20250311075143.61078-3-yangyicong@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-3-yangyicong@huawei.com>
Message-ID: <2bd3aa0a-d700-46bf-81d1-a5fb0364d1e0@arm.com>

On 11/03/2025 08:51, Yicong Yang wrote:
> From: Yicong Yang <yangyicong at hisilicon.com>
> 
> On building the topology from the devicetree, we've already gotten the
> SMT thread number of each core. Update the largest SMT thread number
> and enable the SMT control by the end of topology parsing.
> 
> The framework's SMT control provides two interface to the users [1]
> through /sys/devices/system/cpu/smt/control:
> 1) enable SMT by writing "on" and disable by "off"
> 2) enable SMT by writing max_thread_number or disable by writing 1
> 
> Both method support to completely disable/enable the SMT cores so both
> work correctly for symmetric SMT platform and asymmetric platform with
> non-SMT and one type SMT cores like:
> core A: 1 thread
> core B: X (X!=1) threads
> 
> Note that for a theoretically possible multiple SMT-X (X>1) core
> platform the SMT control is also supported as expected but only
> by writing the "on/off" method.

Here we still have a little misunderstanding. IMHO, even on such a
system 2) would work too.

My qemu example with SMT-1, SMT-2 and SMT-4 in one system from your v11:

# cat /proc/schedstat | grep -v "^v\|^t" | awk '{print $1" "$2" "$3}'
cpu0 0 0
domain0 MC ff
cpu1 0 0
domain0 MC ff
cpu2 0 0
domain0 SMT 0c
domain1 MC ff
cpu3 0 0
domain0 SMT 0c
domain1 MC ff
cpu4 0 0
domain0 SMT f0
domain1 MC ff
cpu5 0 0
domain0 SMT f0
domain1 MC ff
cpu6 0 0
domain0 SMT f0
domain1 MC ff
cpu7 0 0
domain0 SMT f0
domain1 MC ff

# cat /proc/cpuinfo | grep ^processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3
processor	: 4
processor	: 5
processor	: 6
processor	: 7

# echo 1 > /sys/devices/system/cpu/smt/control

# cat /proc/cpuinfo | grep ^processor
processor	: 0
processor	: 1
processor	: 2
processor	: 4

# echo 4 > /sys/devices/system/cpu/smt/control

# cat /proc/cpuinfo | grep ^processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3
processor	: 4
processor	: 5
processor	: 6
processor	: 7

Whats doesn't work is to echoing a '2' but that's not
'max_thread_number' of the system.

[...]


From vladimir.oltean at nxp.com  Mon Mar 17 03:00:37 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 12:00:37 +0200
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib
 driver to support NTMP
In-Reply-To: <PAXPR04MB85102185D0A4C30F0688AA5488DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314123715.fivq2cbczd4khxkk@skbuf>
 <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250317092808.jel2au3cgfwblaxk@skbuf>
 <PAXPR04MB85102185D0A4C30F0688AA5488DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250317100037.7o7r7gch433s5lq4@skbuf>

On Mon, Mar 17, 2025 at 11:55:26AM +0200, Wei Fang wrote:
> Actually I did this is the original version, I mean in downstream kernel 6.6
> tree. I add a "ntmp_mfe" in ntmp.h like below
> 
> struct ntmp_mfe {
> 	u8 mac[ETH_ALEN];
> 	u16 si_bitmap;
> };
> 
> And the conversion was done by the NTMP driver. But then I found that this was
> very troublesome. We get data from kernel "struct A,B,C", then the enetc driver
> converts them to "struct D", and finally the ntmp driver converts it to "struct E".
> So I thought why don't we convert "struct A,B,C" to "struct E" from the beginning?
> After all, these data structures are only used by enetc and netc switch drivers, so
> in kernel 6.12, I changed it to the current way.

I understand. With pack_fields(), "struct E" (the packed representation
of "struct D") doesn't explicitly exist, just an abstract type
representing the u8 *buffer, and the struct packed_field_u8 array[]
which is hidden inside the NTMP layer.


From wei.fang at nxp.com  Mon Mar 17 03:00:56 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Mon, 17 Mar 2025 10:00:56 +0000
Subject: [PATCH v4 net-next 03/14] net: enetc: move generic MAC filterng
 interfaces to enetc-core
In-Reply-To: <20250317094259.b6mwygvr75lxgkwh@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-4-wei.fang@nxp.com>
 <20250311053830.1516523-4-wei.fang@nxp.com>
 <20250317094259.b6mwygvr75lxgkwh@skbuf>
Message-ID: <PAXPR04MB85106C0A4AB17B67A5A4982F88DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> title: s/filterng/filtering/
> 
> On Tue, Mar 11, 2025 at 01:38:19PM +0800, Wei Fang wrote:
> > Although only ENETC PF can access the MAC address filter table, the table
> > entries can specify MAC address filtering for one or more SIs based on
> > SI_BITMAP, which means that the table also supports MAC address filtering
> > for VFs.
> >
> > Currently, only the ENETC v1 PF driver supports MAC address filtering. In
> > order to add the MAC address filtering support for the ENETC v4 PF driver
> > and VF driver in the future, the relevant generic interfaces are moved to
> > the enetc-core driver. At the same time, the struct enetc_mac_filter is
> > moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
> > PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
> > MAC address filtering.
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> 
> For this series I don't see any VF implementation of ndo_set_rx_mode().
> I don't think you have to move struct enetc_mac_filter from struct enetc_pf
> to struct enetc_si, so please don't do that until there is a justification
> for it that is contained in the same patch set, and the two can be
> evaluated together.

Okay, I will keep them in "struct enetc_pf". :)
> 
> Moving enetc_add_mac_addr_ht_filter() and enetc_reset_mac_addr_filter()
> to enetc.c seems fine.



From angelogioacchino.delregno at collabora.com  Mon Mar 17 03:07:47 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 17 Mar 2025 11:07:47 +0100
Subject: [PATCH RFC v2 0/3] add VCP mailbox and IPC driver
In-Reply-To: <20250317083822.891-1-jjian.zhou@mediatek.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
Message-ID: <375d5281-41f5-49e8-ac20-d58931c0c1f9@collabora.com>

Il 17/03/25 09:38, Jjian Zhou ha scritto:
> The VCP mailbox has 5 groups. Each group has corresponding interrupts,
> registers, and 64 slots (each slot is 4 bytes). Since different features
> share one of the mailbox groups, the VCP mailbox needs to establish a
> send table and a receive table. The send table is used to record the
> feature ID, mailbox ID, and the number of slots occupied. The receive table
> is used to record the feature ID, mailbox ID, the number of slots occupied,
> and the receive options. The API setup_mbox_table in mtk-vcp-ipc.c calculates
> the slot offset and pin index for each feature ID based on the mailbox ID and
> slot number in the send and receive tables (several slots form a pin, and
> each pin can trigger an interrupt). These descriptions are written in the
> mtk-vcp-ipc.c file -- we call it the IPC layer.
> 
> We have two questions:
> How should we describe the mailbox and IPI?
> Can the intermediate IPC layer be rewritten as a virtual mailbox layer?
> 

So, for this remote processor messaging system you have:
  - Dynamic channel allocation
    - Each channel has its own endpoint
    - Each channel has its own interrupt
  - Data send operation
    - Both with and without ACK indication from the remote processor
    - To channel -> endpoint
  - Data receive operation
    - From channel <- endpoint
    - When interrupt fires
    - Could use polling to avoid blocking in a few cases
  - A custom message structure not adhering to any standard

Check drivers/rpmsg/ :-)

On MediaTek platforms, there are many IPI to handle in many subsystems for
all of the remote processors that are integrated in the SoC and, at this
point, you might as well just aggregate all of the inter processor communication
stuff in one place, having an API that is made just exactly for that, instead
of keeping to duplicate the IPI stuff over and over (and yes I know that for each
remote processor the TX/RX is slightly different).

If you aggregate the IPI messaging in one place, maintenance is going to be easier,
and we stop getting duplication... more or less like it was done with the mtk_scp
IPI and mtk-vcodec .. and that's also something that is partially handled as RPMSG
because, well, it is a remote processor messaging driver.

Just to make people understand *how heavily* MediaTek SoCs rely on IPI, there's
a *partial* list of SoC IPs that use IPI communcation:

thermal, ccu, ccd, tinysys, vcp, atsp, sspm, slbc, mcupm, npu, mvpu, aps, mdla,
qos, audio, cm_mgr.... and... again, it's a partial list!

That said... any other opinion from anyone else?

Cheers,
Angelo

> Example of send and recve table:
> Operation | mbox_id | ipi_id | msg_size | align_size | slot_ofs | pin_index |  notes
> send          0          0       18          18           0          0
> recv          0          1       18          18          18          9
> send          1         15        8           8           0          0
> send          1         16       18          18           8          4
> send          1          9        2           2          26         13
> recv          1         15        8           8          28         14       ack of send ipi_id=15
> recv          1         17       18          18          36         18
> recv          1         10        2           2          54         27       ack of send ipi_id=2
> send          2         11       18          18           0          0
> send          2          2        2           2          18          9
> send          2          3        3           4          20         10
> send          2         32        2           2          24         12
> recv          2         12       18          18          26         13
> recv          2          5        1           2          44         22
> recv          2          2        1           2          46         23
> 
> Recv ipi_id=2 is the ack of send ipi_id=2(The ipi_id=15 is the same.)
> 
> Jjian Zhou (3):
>    mailbox: mediatek: Add mtk-vcp-mailbox driver
>    firmware: mediatek: Add vcp ipc protocol interface
>    dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document
> 
>   .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml |  49 ++
>   drivers/firmware/Kconfig                      |   9 +
>   drivers/firmware/Makefile                     |   1 +
>   drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
>   drivers/mailbox/Kconfig                       |   9 +
>   drivers/mailbox/Makefile                      |   2 +
>   drivers/mailbox/mtk-vcp-mailbox.c             | 179 +++++++
>   include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
>   include/linux/mailbox/mtk-vcp-mailbox.h       |  34 ++
>   9 files changed, 915 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
>   create mode 100644 drivers/firmware/mtk-vcp-ipc.c
>   create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
>   create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
>   create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h
> 





From suzuki.poulose at arm.com  Mon Mar 17 03:07:56 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Mon, 17 Mar 2025 10:07:56 +0000
Subject: [PATCH next] Coresight: Fix a NULL vs IS_ERR() bug in probe
In-Reply-To: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
References: <dab039b9-d58a-41be-92f0-ff209cfabfe2@stanley.mountain>
Message-ID: <174220604251.188899.14799232628969384481.b4-ty@arm.com>


On Fri, 14 Mar 2025 13:55:10 +0300, Dan Carpenter wrote:
> The devm_platform_get_and_ioremap_resource() function doesn't
> return NULL, it returns error pointers.  Update the checking to
> match.
> 
> 

Applied, thanks!

[1/1] Coresight: Fix a NULL vs IS_ERR() bug in probe
      (no commit info)

Best regards,
-- 
Suzuki K Poulose <suzuki.poulose at arm.com>


From m-malladi at ti.com  Mon Mar 17 03:15:47 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 17 Mar 2025 15:45:47 +0530
Subject: [PATCH net-next 0/3] Bug fixes from XDP and perout series
Message-ID: <20250317101551.1005706-1-m-malladi@ti.com>

This patch series consists of bug fixes from the features which recently
got merged into net-next, and haven't been merged to net tree yet.

Patch 2/3 and 3/3 are bug fixes reported by Dan Carpenter
<dan.carpenter at linaro.org> using Smatch static checker.

Meghana Malladi (3):
  net: ti: prueth: Fix kernel warning while bringing down network
    interface
  net: ti: prueth: Fix possible NULL pointer dereference inside
    emac_xmit_xdp_frame()
  net: ti: icss-iep: Fix possible NULL pointer dereference for perout
    request

 drivers/net/ethernet/ti/icssg/icss_iep.c     | 4 ++++
 drivers/net/ethernet/ti/icssg/icssg_common.c | 9 ++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)


base-commit: bfc6c67ec2d64d0ca4e5cc3e1ac84298a10b8d62
-- 
2.43.0



From m-malladi at ti.com  Mon Mar 17 03:15:49 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 17 Mar 2025 15:45:49 +0530
Subject: [PATCH net-next 2/3] net: ti: prueth: Fix possible NULL pointer dereference inside emac_xmit_xdp_frame()
In-Reply-To: <20250317101551.1005706-1-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
Message-ID: <20250317101551.1005706-3-m-malladi@ti.com>

There is an error check inside emac_xmit_xdp_frame() function which
is called when the driver wants to transmit XDP frame, to check if
the allocated tx descriptor is NULL, if true to exit and return
ICSSG_XDP_CONSUMED implying failure in transmission.

In this case trying to free a descriptor which is NULL will result
in kernel crash due to NULL pointer dereference. Fix this error handling
and increase netdev tx_dropped stats in the caller of this function
if the function returns ICSSG_XDP_CONSUMED.

Fixes: 62aa3246f462 ("net: ti: icssg-prueth: Add XDP support")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
 drivers/net/ethernet/ti/icssg/icssg_common.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index afa01c22dee8..f0224576b95f 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -584,7 +584,7 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
 	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
 	if (!first_desc) {
 		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
-		goto drop_free_descs;	/* drop */
+		return ICSSG_XDP_CONSUMED;	/* drop */
 	}
 
 	if (page) { /* already DMA mapped by page_pool */
@@ -672,8 +672,10 @@ static u32 emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
 
 		q_idx = smp_processor_id() % emac->tx_ch_num;
 		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
-		if (result == ICSSG_XDP_CONSUMED)
+		if (result == ICSSG_XDP_CONSUMED) {
+			ndev->stats.tx_dropped++;
 			goto drop;
+		}
 
 		dev_sw_netstats_rx_add(ndev, xdpf->len);
 		return result;
-- 
2.43.0



From m-malladi at ti.com  Mon Mar 17 03:15:50 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 17 Mar 2025 15:45:50 +0530
Subject: [PATCH net-next 3/3] net: ti: icss-iep: Fix possible NULL pointer dereference for perout request
In-Reply-To: <20250317101551.1005706-1-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
Message-ID: <20250317101551.1005706-4-m-malladi@ti.com>

Whenever there is a perout request from the user application,
kernel receives req structure containing the configuration info
for that req. Add NULL pointer handling for perout request if
that req struct points to NULL.

Fixes: e5b456a14215 ("net: ti: icss-iep: Add pwidth configuration for perout signal")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
 drivers/net/ethernet/ti/icssg/icss_iep.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index b4a34c57b7b4..aeebdc4c121e 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -498,6 +498,10 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
 {
 	int ret = 0;
 
+	/* Return error if the req is NULL */
+	if (!req)
+		return -EINVAL;
+
 	/* Reject requests with unsupported flags */
 	if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
 			  PTP_PEROUT_PHASE))
-- 
2.43.0



From m-malladi at ti.com  Mon Mar 17 03:15:48 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Mon, 17 Mar 2025 15:45:48 +0530
Subject: [PATCH net-next 1/3] net: ti: prueth: Fix kernel warning while bringing down network interface
In-Reply-To: <20250317101551.1005706-1-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
Message-ID: <20250317101551.1005706-2-m-malladi@ti.com>

During network interface initialization, the NIC driver needs to register
its Rx queue with the XDP, to ensure the incoming XDP buffer carries a
pointer reference to this info and is stored inside xdp_rxq_info.

While this struct isn't tied to XDP prog, if there are any changes in
Rx queue, the NIC driver needs to stop the Rx queue by unregistering
with XDP before purging and reallocating memory. Drop page_pool destroy
during Rx channel reset and this is already handled by XDP during
xdp_rxq_info_unreg (Rx queue unregister), failing to do will cause the
following warning:

[  271.494611] ------------[ cut here ]------------
[  271.494629] WARNING: CPU: 0 PID: 2453 at /net/core/page_pool.c:1108 0xffff8000808d5f60

Fixes: 46eeb90f03e0 ("net: ti: icssg-prueth: Use page_pool API for RX buffer allocation")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
---
 drivers/net/ethernet/ti/icssg/icssg_common.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index df5da7a98abf..afa01c22dee8 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -1216,9 +1216,6 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
 					  prueth_rx_cleanup, !!i);
 	if (disable)
 		k3_udma_glue_disable_rx_chn(chn->rx_chn);
-
-	page_pool_destroy(chn->pg_pool);
-	chn->pg_pool = NULL;
 }
 EXPORT_SYMBOL_GPL(prueth_reset_rx_chan);
 
-- 
2.43.0



From sre at kernel.org  Mon Mar 17 03:16:31 2025
From: sre at kernel.org (Sebastian Reichel)
Date: Mon, 17 Mar 2025 11:16:31 +0100
Subject: [PATCH] drm/rockchip: dw_hdmi_qp: Fix io init for
 dw_hdmi_qp_rockchip_resume
In-Reply-To: <20250317082047.564404-1-andyshrk@163.com>
References: <20250317082047.564404-1-andyshrk@163.com>
Message-ID: <p53hbl4vt7vy6srctswjpmlj2rsvnyop4zcszlwrwdd4nogsj3@utqc25oaccfb>

Hi,

On Mon, Mar 17, 2025 at 04:20:39PM +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> Use cfg->ctrl_ops->io_init callback make it work for all platform.
> 
> Fixes: 3f60dbd40d3f ("drm/rockchip: dw_hdmi_qp: Add platform ctrl callback")
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---

It also gets rid of code duplication :)

> 
>  .../gpu/drm/rockchip/dw_hdmi_qp-rockchip.c    | 23 +++----------------
>  1 file changed, 3 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> index 3d1dddb34603..631a7080862b 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> @@ -600,27 +600,10 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
>  static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
>  {
>  	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
> -	u32 val;
> -
> -	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
> -	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
> -	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
> -	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
> -	regmap_write(hdmi->vo_regmap,
> -		     hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
> -		     val);
> -
> -	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
> -			    RK3588_SET_HPD_PATH_MASK);
> -	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
> +	const struct rockchip_hdmi_qp_cfg *cfg;
>  
> -	if (hdmi->port_id)
> -		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
> -				    RK3588_HDMI1_GRANT_SEL);
> -	else
> -		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
> -				    RK3588_HDMI0_GRANT_SEL);
> -	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
> +	cfg = of_device_get_match_data(dev);
> +	cfg->ctrl_ops->io_init(hdmi);

I think it would be better to store the ctrl_ops (or io_init)
callback in struct rockchip_hdmi_qp during driver probe and avoid
another lookup of the match_data, which involves string comparisons.

Otherwise:

Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

Greetings,

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/082c1d6c/attachment.sig>

From broonie at kernel.org  Mon Mar 17 03:17:33 2025
From: broonie at kernel.org (Mark Brown)
Date: Mon, 17 Mar 2025 10:17:33 +0000
Subject: [PATCH] ASoC: mt8365: remove unnecessary NULL check before
 clk_disable_unprepare()
In-Reply-To: <20250312032600.1235158-1-nichen@iscas.ac.cn>
References: <20250312032600.1235158-1-nichen@iscas.ac.cn>
Message-ID: <174220665367.86423.10873134642092088398.b4-ty@kernel.org>

On Wed, 12 Mar 2025 11:26:00 +0800, Chen Ni wrote:
> clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL.
> Remove unneeded NULL check for clk here.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: mt8365: remove unnecessary NULL check before clk_disable_unprepare()
      commit: f37ab219a3336ef787ce4babd20510f060f6f48d

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From tudor.ambarus at linaro.org  Mon Mar 17 03:23:11 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 17 Mar 2025 10:23:11 +0000
Subject: [PATCH 1/3] firmware: exynos-acpm: fix reading longer results
In-Reply-To: <20250314-acpm-fixes-v1-1-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
 <20250314-acpm-fixes-v1-1-ab03ca8e723f@linaro.org>
Message-ID: <5918c64f-856b-4820-b35b-538ffdd9ac6a@linaro.org>



On 3/14/25 4:40 PM, Andr? Draszik wrote:
> ACPM commands that return more than 8 bytes currently don't work
> correctly, as this driver ignores any such returned bytes.
> 
> This is evident in at least acpm_pmic_bulk_read(), where up to 8
> registers can be read back and those 8 register values are placed
> starting at &xfer->rxd[8].
> 
> The reason is that xfter->rxlen is initialized with the size of a
> pointer (8 bytes), rather than the size of the byte array that pointer
> points to (16 bytes)
> 
> Update the code such that we set the number of bytes expected to be the
> size of the rx buffer.
> 
> Note1: While different commands have different lengths rx buffers, we
> have to specify the same length for all rx buffers since acpm_get_rx()
> assumes they're all the same length.
> 
> Note2: The different commands also have different lengths tx buffers,
> but before switching the code to use the minimum possible length, some
> more testing would have to be done to ensure this works correctly in
> all situations. It seems wiser to just apply this fix here without
> additional logic changes for now.
> 
> Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>


From tudor.ambarus at linaro.org  Mon Mar 17 03:26:44 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 17 Mar 2025 10:26:44 +0000
Subject: [PATCH 2/3] firmware: exynos-acpm: silence EPROBE_DEFER error on
 boot
In-Reply-To: <20250314-acpm-fixes-v1-2-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
 <20250314-acpm-fixes-v1-2-ab03ca8e723f@linaro.org>
Message-ID: <638cf070-9fd1-416e-8172-75f189ab0dfe@linaro.org>



On 3/14/25 4:40 PM, Andr? Draszik wrote:
> This driver emits error messages when client drivers are trying to get
> an interface handle to this driver here before this driver has
> completed _probe().
> 
> Given this driver returns -EPROBE_DEFER in that case, this is not an
> error and shouldn't be emitted to the log, so just remove them.
> 
> Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>


From andyshrk at 163.com  Mon Mar 17 03:27:53 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 17 Mar 2025 18:27:53 +0800
Subject: [PATCH v2] drm/rockchip: dw_hdmi_qp: Fix io init for dw_hdmi_qp_rockchip_resume
Message-ID: <20250317102757.565679-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Use cfg->ctrl_ops->io_init callback make it work for all platform.
And it's also gets rid of code duplication

Fixes: 3f60dbd40d3f ("drm/rockchip: dw_hdmi_qp: Add platform ctrl callback")
Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel at collabora.com>

---

Changes in v2:
- Store the ctrl_ops in struct rockchip_hdmi_qp

 .../gpu/drm/rockchip/dw_hdmi_qp-rockchip.c    | 23 +++----------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 3d1dddb34603..7d531b6f4c09 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -94,6 +94,7 @@ struct rockchip_hdmi_qp {
 	struct gpio_desc *enable_gpio;
 	struct delayed_work hpd_work;
 	int port_id;
+	const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
 };
 
 struct rockchip_hdmi_qp_ctrl_ops {
@@ -461,6 +462,7 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
 		return -ENODEV;
 	}
 
+	hdmi->ctrl_ops = cfg->ctrl_ops;
 	hdmi->dev = &pdev->dev;
 	hdmi->port_id = -ENODEV;
 
@@ -600,27 +602,8 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
 {
 	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
-	u32 val;
 
-	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
-	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
-	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
-	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
-	regmap_write(hdmi->vo_regmap,
-		     hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
-		     val);
-
-	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
-			    RK3588_SET_HPD_PATH_MASK);
-	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
-
-	if (hdmi->port_id)
-		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
-				    RK3588_HDMI1_GRANT_SEL);
-	else
-		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
-				    RK3588_HDMI0_GRANT_SEL);
-	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+	hdmi->ctrl_ops->io_init(hdmi);
 
 	dw_hdmi_qp_resume(dev, hdmi->hdmi);
 
-- 
2.43.0



From ping.bai at nxp.com  Mon Mar 17 03:31:46 2025
From: ping.bai at nxp.com (Jacky Bai)
Date: Mon, 17 Mar 2025 10:31:46 +0000
Subject: [PATCh v3 2/3] arm64: dts: freescale: Add basic dtsi for imx943
In-Reply-To: <Z9RcdQbJYUk+SPte@lizhi-Precision-Tower-5810>
References: <20250313071628.729168-1-ping.bai@nxp.com>
 <20250313071628.729168-3-ping.bai@nxp.com>
 <Z9RcdQbJYUk+SPte@lizhi-Precision-Tower-5810>
Message-ID: <AS8PR04MB86426A8CA71C7F4A27A2860887DF2@AS8PR04MB8642.eurprd04.prod.outlook.com>

> Subject: Re: [PATCh v3 2/3] arm64: dts: freescale: Add basic dtsi for imx943
> 
> On Thu, Mar 13, 2025 at 03:16:27PM +0800, Jacky Bai wrote:
> > Add the minimal dtsi support for i.MX943. i.MX943 is the first SoC of
> > i.MX94 Family, create a common dtsi for the whole i.MX94 family, and
> > the specific dtsi part for i.MX943.
> >
> > The clock, power domain and perf index need to be used by the device
> > nodes for resource reference, add them along with the dtsi support.
> >
> > Signed-off-by: Jacky Bai <ping.bai at nxp.com>
> > ---
> >  - v3 changes:
> >   - remove the blank line
> >   - add PAD config macro define as suggested by Frank Li
> >   - update the device nodes compatible strings for imx94 as suggested
> > by Krzysztof
> >
> >  - v2 changes:
> >   - remove the unnecessary macro define in clock header as suggested by
> Krzysztof
> >   - split the dtsi into imx94.dtsi and imx943.dtsi
> >   - use low case in the pinfunc header as Frank suggested
> >   - reorder the device nodes and properties
> > ---
> ...
> > +		aips2: bus at 42000000 {
> > +			compatible = "fsl,aips-bus", "simple-bus";
> > +			reg = <0x0 0x42000000 0x0 0x800000>;
> > +			ranges = <0x42000000 0x0 0x42000000 0x8000000>;
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +
> > +			edma2: dma-controller at 42000000 {
> > +				compatible = "fsl,imx94-edma5", "fsl,imx95-edma5";
> > +				reg = <0x42000000 0x210000>;
> > +				clocks = <&scmi_clk IMX94_CLK_BUSWAKEUP>;
> > +				clock-names = "dma";
> > +				#dma-cells = <3>;
> > +				dma-channels = <64>;
> > +				interrupts-extended = <&a55_irqsteer 0>, <&a55_irqsteer
> 1>, <&a55_irqsteer 2>,
> > +					<&a55_irqsteer 3>, <&a55_irqsteer 4>,
> <&a55_irqsteer 5>,
> 
> Does below method work?
> 
> interrupt-parent = <&a55_irqsteer>
> interrupts = <3>, <4>, <5>, ....
> 

edma driver can not parse the irq correctly. The err irq is connected to GIC, not irqsteer.

> > +					<&a55_irqsteer 6>, <&a55_irqsteer 7>,
> <&a55_irqsteer 8>,
> > +					<&a55_irqsteer 9>, <&a55_irqsteer 10>,
> <&a55_irqsteer 11>,
> > +					<&a55_irqsteer 12>, <&a55_irqsteer 13>,
> <&a55_irqsteer 14>,
> > +					<&a55_irqsteer 15>, <&a55_irqsteer 16>,
> <&a55_irqsteer 17>,
> > +					<&a55_irqsteer 18>, <&a55_irqsteer 19>,
> <&a55_irqsteer 20>,
> > +					<&a55_irqsteer 21>, <&a55_irqsteer 22>,
> <&a55_irqsteer 23>,
> > +					<&a55_irqsteer 24>, <&a55_irqsteer 25>,
> <&a55_irqsteer 26>,
> > +					<&a55_irqsteer 27>, <&a55_irqsteer 28>,
> <&a55_irqsteer 29>,
> > +					<&a55_irqsteer 30>, <&a55_irqsteer 31>,
> <&a55_irqsteer 64>,
> > +					<&a55_irqsteer 65>, <&a55_irqsteer 66>,
> <&a55_irqsteer 67>,
> > +					<&a55_irqsteer 68>, <&a55_irqsteer 69>,
> <&a55_irqsteer 70>,
> > +					<&a55_irqsteer 71>, <&a55_irqsteer 72>,
> <&a55_irqsteer 73>,
> > +					<&a55_irqsteer 74>, <&a55_irqsteer 75>,
> <&a55_irqsteer 76>,
> > +					<&a55_irqsteer 77>, <&a55_irqsteer 78>,
> <&a55_irqsteer 79>,
> > +					<&a55_irqsteer 80>, <&a55_irqsteer 81>,
> <&a55_irqsteer 82>,
> > +					<&a55_irqsteer 83>, <&a55_irqsteer 84>,
> <&a55_irqsteer 85>,
> > +					<&a55_irqsteer 86>, <&a55_irqsteer 87>,
> <&a55_irqsteer 88>,
> 
> > +		cpu0: cpu at 0 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x0>;
> 
> I remember compatible is first property, then reg.
> 

Will change it as you suggested if no other comments for the order of device type and compatible.

BR

> Frank
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l0>;
> > +		};
> > +
> > +		cpu1: cpu at 100 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x100>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l1>;
> > +		};
> > +
> > +		cpu2: cpu at 200 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x200>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l2>;
> > +		};
> > +
> > +		cpu3: cpu at 300 {
> > +			device_type = "cpu";
> > +			compatible = "arm,cortex-a55";
> > +			reg = <0x300>;
> > +			enable-method = "psci";
> > +			#cooling-cells = <2>;
> > +			cpu-idle-states = <&cpu_pd_wait>;
> > +			power-domains = <&scmi_perf IMX94_PERF_A55>;
> > +			power-domain-names = "perf";
> > +			i-cache-size = <32768>;
> > +			i-cache-line-size = <64>;
> > +			i-cache-sets = <128>;
> > +			d-cache-size = <32768>;
> > +			d-cache-line-size = <64>;
> > +			d-cache-sets = <128>;
> > +			next-level-cache = <&l2_cache_l3>;
> > +		};
> > +
> > +		l2_cache_l0: l2-cache-l0 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l1: l2-cache-l1 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l2: l2-cache-l2 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l2_cache_l3: l2-cache-l3 {
> > +			compatible = "cache";
> > +			cache-size = <65536>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <256>;
> > +			cache-level = <2>;
> > +			cache-unified;
> > +			next-level-cache = <&l3_cache>;
> > +		};
> > +
> > +		l3_cache: l3-cache {
> > +			compatible = "cache";
> > +			cache-size = <1048576>;
> > +			cache-line-size = <64>;
> > +			cache-sets = <1024>;
> > +			cache-level = <3>;
> > +			cache-unified;
> > +		};
> > +	};
> > +};
> > --
> > 2.34.1
> >


From sudeep.holla at arm.com  Mon Mar 17 03:31:20 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:20 +0000
Subject: [PATCH v2 0/5] firmware: arm_scmi: Minor cleanups in the scmi bus
 layer
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>

These cleanup centralizes error logging for SCMI device creation into a
single helper function, _scmi_device_create(), consolidates the device
matching logic into a single function, and ensures that devices must
have a name for registration, removing support for unnamed devices while
matching the devices and drivers for probing. It ensures the transport
devices are excluded from the bus matching and the correct assignment
of parent device for the arm-scmi platform device created in the
transport drivers.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
Changes in v2:
- Added exclusion of transport devices from bus matching
- Added correct assignment of parent to arm-scmi platform device
- Link to v1: https://lore.kernel.org/r/20250312-b4-scmi_minor_cleanup-v1-0-c62c6cb4111a at arm.com

---
Sudeep Holla (5):
      firmware: arm_scmi: Ensure scmi_devices are always matched by name as well
      firmware: arm_scmi: Refactor device matching logic to eliminate duplication
      firmware: arm_scmi: Refactor error logging from SCMI device creation to single helper
      firmware: arm_scmi: Assign correct parent to arm-scmi platform device
      firmware: arm_scmi: Exclude transport devices from bus matching

 drivers/firmware/arm_scmi/bus.c    | 79 ++++++++++++++++++++------------------
 drivers/firmware/arm_scmi/common.h |  1 +
 drivers/firmware/arm_scmi/driver.c | 13 ++-----
 3 files changed, 46 insertions(+), 47 deletions(-)
---
base-commit: 80e54e84911a923c40d7bee33a34c1b4be148d7a
change-id: 20250312-b4-scmi_minor_cleanup-8f85228d435c
-- 
Regards,
Sudeep



From sudeep.holla at arm.com  Mon Mar 17 03:31:21 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:21 +0000
Subject: [PATCH v2 1/5] firmware: arm_scmi: Ensure scmi_devices are always
 matched by name as well
In-Reply-To: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
References: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-1-f4be99bd9864@arm.com>

Currently, devices without a name in the id_table cannot register drivers,
and no scmi_device is created without a name via scmi_device_create().
However, the function __scmi_device_create() allows devices with no name,
which are then labeled as "unknown."

Removes support for matching scmi_device instances without a name,
ensuring consistency across the driver registration and probing process.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a3386bf36de508d312e2c4fa2e27ba62ba3776a0..050a5ff5dc96a7df58edff5faeb8c1ec6228b97d 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -214,13 +214,10 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_d
 	if (!id)
 		return NULL;
 
-	for (; id->protocol_id; id++)
-		if (id->protocol_id == scmi_dev->protocol_id) {
-			if (!id->name)
-				return id;
-			else if (!strcmp(id->name, scmi_dev->name))
-				return id;
-		}
+	for (; id->protocol_id && id->name; id++)
+		if (id->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id->name, scmi_dev->name))
+			return id;
 
 	return NULL;
 }

-- 
2.34.1



From sudeep.holla at arm.com  Mon Mar 17 03:31:23 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:23 +0000
Subject: [PATCH v2 3/5] firmware: arm_scmi: Refactor error logging from
 SCMI device creation to single helper
In-Reply-To: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
References: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-3-f4be99bd9864@arm.com>

Refactors the error logging related to SCMI device creation. The goal
is to remove duplicated error-handling code and centralize it into a
single helper function: _scmi_device_create().

By doing so, any code redundancy around error logging is avoided, as
error logging during device creation will now be handled by a unified
helper function.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c    | 29 +++++++++++++++++++----------
 drivers/firmware/arm_scmi/driver.c |  8 +-------
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index a30fd8e05e423e226a63833f309d8d30c400fabd..493e2c63b107fd9063f11034b71d65f567bb0778 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -411,6 +411,20 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 	return NULL;
 }
 
+static struct scmi_device *
+_scmi_device_create(struct device_node *np, struct device *parent,
+		    int protocol, const char *name)
+{
+	struct scmi_device *sdev;
+
+	sdev = __scmi_device_create(np, parent, protocol, name);
+	if (!sdev)
+		pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
+		       of_node_full_name(parent->of_node), protocol, name);
+
+	return sdev;
+}
+
 /**
  * scmi_device_create  - A method to create one or more SCMI devices
  *
@@ -443,7 +457,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	struct scmi_device *scmi_dev = NULL;
 
 	if (name)
-		return __scmi_device_create(np, parent, protocol, name);
+		return _scmi_device_create(np, parent, protocol, name);
 
 	mutex_lock(&scmi_requested_devices_mtx);
 	phead = idr_find(&scmi_requested_devices, protocol);
@@ -457,18 +471,13 @@ struct scmi_device *scmi_device_create(struct device_node *np,
 	list_for_each_entry(rdev, phead, node) {
 		struct scmi_device *sdev;
 
-		sdev = __scmi_device_create(np, parent,
-					    rdev->id_table->protocol_id,
-					    rdev->id_table->name);
-		/* Report errors and carry on... */
+		sdev = _scmi_device_create(np, parent,
+					   rdev->id_table->protocol_id,
+					   rdev->id_table->name);
 		if (sdev)
 			scmi_dev = sdev;
-		else
-			pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
-			       of_node_full_name(parent->of_node),
-			       rdev->id_table->protocol_id,
-			       rdev->id_table->name);
 	}
+
 	mutex_unlock(&scmi_requested_devices_mtx);
 
 	return scmi_dev;
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 60050da54bf24c0245290e846f91aea62392855b..b80c574cb3bb2f12b2980fc844ea3da10abdc9f1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -439,14 +439,8 @@ static void scmi_create_protocol_devices(struct device_node *np,
 					 struct scmi_info *info,
 					 int prot_id, const char *name)
 {
-	struct scmi_device *sdev;
-
 	mutex_lock(&info->devreq_mtx);
-	sdev = scmi_device_create(np, info->dev, prot_id, name);
-	if (name && !sdev)
-		dev_err(info->dev,
-			"failed to create device for protocol 0x%X (%s)\n",
-			prot_id, name);
+	scmi_device_create(np, info->dev, prot_id, name);
 	mutex_unlock(&info->devreq_mtx);
 }
 

-- 
2.34.1



From sudeep.holla at arm.com  Mon Mar 17 03:31:22 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:22 +0000
Subject: [PATCH v2 2/5] firmware: arm_scmi: Refactor device matching logic
 to eliminate duplication
In-Reply-To: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
References: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-2-f4be99bd9864@arm.com>

Currently, the device matching logic is duplicated in two functions:
  - scmi_dev_match() used by the scmi_bus to match scmi_devices with
    scmi_drivers.
  - scmi_child_dev_find() used to check for the presence of a device
    with the same name and protocol_id to avoid adding duplicates to
    the bus.

Refactor the code to eliminate the redundant matching logic and
consolidates the functionality for better maintainability and efficiency.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c | 43 +++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 050a5ff5dc96a7df58edff5faeb8c1ec6228b97d..a30fd8e05e423e226a63833f309d8d30c400fabd 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -206,52 +206,49 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
 		scmi_protocol_device_unrequest(entry);
 }
 
-static const struct scmi_device_id *
-scmi_dev_match_id(struct scmi_device *scmi_dev, const struct scmi_driver *scmi_drv)
+static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
+				      const struct scmi_device_id *id_table)
 {
-	const struct scmi_device_id *id = scmi_drv->id_table;
+	if (!id_table || !id_table->name)
+		return 0;
 
-	if (!id)
-		return NULL;
-
-	for (; id->protocol_id && id->name; id++)
-		if (id->protocol_id == scmi_dev->protocol_id &&
-		    !strcmp(id->name, scmi_dev->name))
-			return id;
+	for (; id_table->protocol_id && id_table->name; id_table++)
+		if (id_table->protocol_id == scmi_dev->protocol_id &&
+		    !strcmp(id_table->name, scmi_dev->name))
+			return 1;
+	return 0;
+}
 
-	return NULL;
+static int scmi_dev_match_id(struct scmi_device *scmi_dev,
+			     const struct scmi_driver *scmi_drv)
+{
+	return scmi_dev_match_by_id_table(scmi_dev, scmi_drv->id_table);
 }
 
 static int scmi_dev_match(struct device *dev, const struct device_driver *drv)
 {
 	const struct scmi_driver *scmi_drv = to_scmi_driver(drv);
 	struct scmi_device *scmi_dev = to_scmi_dev(dev);
-	const struct scmi_device_id *id;
-
-	id = scmi_dev_match_id(scmi_dev, scmi_drv);
-	if (id)
-		return 1;
 
-	return 0;
+	return scmi_dev_match_id(scmi_dev, scmi_drv);
 }
 
 static int scmi_match_by_id_table(struct device *dev, const void *data)
 {
-	struct scmi_device *sdev = to_scmi_dev(dev);
+	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 	const struct scmi_device_id *id_table = data;
 
-	return sdev->protocol_id == id_table->protocol_id &&
-		(id_table->name && !strcmp(sdev->name, id_table->name));
+	return scmi_dev_match_by_id_table(scmi_dev, id_table);
 }
 
 static struct scmi_device *scmi_child_dev_find(struct device *parent,
 					       int prot_id, const char *name)
 {
-	struct scmi_device_id id_table;
+	struct scmi_device_id id_table[2] = { 0 };
 	struct device *dev;
 
-	id_table.protocol_id = prot_id;
-	id_table.name = name;
+	id_table[0].protocol_id = prot_id;
+	id_table[0].name = name;
 
 	dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
 	if (!dev)

-- 
2.34.1



From sudeep.holla at arm.com  Mon Mar 17 03:31:24 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:24 +0000
Subject: [PATCH v2 4/5] firmware: arm_scmi: Assign correct parent to
 arm-scmi platform device
In-Reply-To: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
References: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-4-f4be99bd9864@arm.com>

With the decoupling of transport drivers from the SCMI core, the
"arm-scmi" platform device is now created dynamically from the probed
transport driver.

Currently, this "arm-scmi" platform device is added to the root of
the platform bus since no parent is assigned. However, the transport
platform device, created from the "firmware:scmi" node in the device
tree, should be considered its parent.

Ensure that the parent device is correctly set for the "arm-scmi"
platform device, aligning it with the correct transport hierarchy.
This will be more useful on systems with multiple transport and/or
SCMI firmware instances as the hierarchy is maintained correctly.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/common.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 10ea7962323e43e03e7c5636c56d707803d4ea55..dab758c5fdea3aa34188ef7d424ba8a43ada46d8 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -475,6 +475,7 @@ static int __tag##_probe(struct platform_device *pdev)			       \
 	if (ret)							       \
 		goto err;						       \
 									       \
+	spdev->dev.parent = dev;					       \
 	ret = platform_device_add(spdev);				       \
 	if (ret)							       \
 		goto err;						       \

-- 
2.34.1



From sudeep.holla at arm.com  Mon Mar 17 03:31:25 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 17 Mar 2025 10:31:25 +0000
Subject: [PATCH v2 5/5] firmware: arm_scmi: Exclude transport devices from
 bus matching
In-Reply-To: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
References: <20250317-b4-scmi_minor_cleanup-v2-0-f4be99bd9864@arm.com>
Message-ID: <20250317-b4-scmi_minor_cleanup-v2-5-f4be99bd9864@arm.com>

Transport devices are currently being unintentionally matched to
drivers with the same name, allowing their probe function to be
invoked. However, the bus notifier prevents them from setting up
handles, rendering them unable to utilize SCMI core functionality.

Instead of relying on the bus notifier which can't prevent bus matching
even if it returns early or error, move the check into the bus matching
logic itself. This change ensures that transport devices are entirely
excluded from driver matching, preventing any unintended probe attempts.

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_scmi/bus.c    | 2 ++
 drivers/firmware/arm_scmi/driver.c | 5 ++---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 493e2c63b107fd9063f11034b71d65f567bb0778..17b0e6e2cb0a65d88079346b3da319ce6356b42b 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -212,8 +212,10 @@ static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
 	if (!id_table || !id_table->name)
 		return 0;
 
+	/* Always skip transport devices from matching */
 	for (; id_table->protocol_id && id_table->name; id_table++)
 		if (id_table->protocol_id == scmi_dev->protocol_id &&
+		    strncmp(scmi_dev->name, "__scmi_transport_device", 23) &&
 		    !strcmp(id_table->name, scmi_dev->name))
 			return 1;
 	return 0;
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index b80c574cb3bb2f12b2980fc844ea3da10abdc9f1..2b567f29c83493487b8b0998886dcf75827017ef 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -2829,9 +2829,8 @@ static int scmi_bus_notifier(struct notifier_block *nb,
 	struct scmi_info *info = bus_nb_to_scmi_info(nb);
 	struct scmi_device *sdev = to_scmi_dev(data);
 
-	/* Skip transport devices and devices of different SCMI instances */
-	if (!strncmp(sdev->name, "__scmi_transport_device", 23) ||
-	    sdev->dev.parent != info->dev)
+	/* Skip devices of different SCMI instances */
+	if (sdev->dev.parent != info->dev)
 		return NOTIFY_DONE;
 
 	switch (action) {

-- 
2.34.1



From krzk at kernel.org  Mon Mar 17 03:34:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 11:34:48 +0100
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
 <20250314210652.GA2300828-robh@kernel.org>
 <PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>
Message-ID: <20250317-massive-calm-bat-43ff61@krzk-bin>

On Sat, Mar 15, 2025 at 07:32:28AM +0000, Maud Spierings | GOcontroll wrote:
> >> +required:
> >> +  - compatible
> >> +  - reg
> >> +  - reset-gpios
> >> +  - interrupts
> >> +  - sync-gpios
> >> +  - i2c-bus
> >> +  - slot-number
> >> +
> >> +additionalProperties: false
> >> +
> >> +examples:
> >> +  - |
> >> +    #include <dt-bindings/gpio/gpio.h>
> >> +    #include <dt-bindings/interrupt-controller/irq.h>
> >> +
> >> +    spi {
> >> +        #address-cells = <1>;
> >> +        #size-cells = <0>;
> >> +
> >> +        connector at 0 {
> >
> >I find this being a SPI device a bit strange. Is there a defined SPI
> >device that every slot is going to have? Or the connector has SPI
> >interface and *anything* could be attached on it?
> 
> So a module slot is like a pcie slot, it can be occupied or not, and when

But which buses...

Best regards,
Krzysztof



From maudspierings at gocontroll.com  Mon Mar 17 03:42:14 2025
From: maudspierings at gocontroll.com (Maud Spierings | GOcontroll)
Date: Mon, 17 Mar 2025 10:42:14 +0000
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <20250317-massive-calm-bat-43ff61@krzk-bin>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
 <20250314210652.GA2300828-robh@kernel.org>
 <PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>
 <20250317-massive-calm-bat-43ff61@krzk-bin>
Message-ID: <PA4PR04MB7630DA5DF63C18530B86AB59C5DF2@PA4PR04MB7630.eurprd04.prod.outlook.com>

From:?Krzysztof Kozlowski <krzk at kernel.org>
Sent:?Monday, March 17, 2025 11:34 AM
?
>On Sat, Mar 15, 2025 at 07:32:28AM +0000, Maud Spierings | GOcontroll wrote:
>> >> +required:
>> >> +? - compatible
>> >> +? - reg
>> >> +? - reset-gpios
>> >> +? - interrupts
>> >> +? - sync-gpios
>> >> +? - i2c-bus
>> >> +? - slot-number
>> >> +
>> >> +additionalProperties: false
>> >> +
>> >> +examples:
>> >> +? - |
>> >> +??? #include <dt-bindings/gpio/gpio.h>
>> >> +??? #include <dt-bindings/interrupt-controller/irq.h>
>> >> +
>> >> +??? spi {
>> >> +??????? #address-cells = <1>;
>> >> +??????? #size-cells = <0>;
>> >> +
>> >> +??????? connector at 0 {
>> >
>> >I find this being a SPI device a bit strange. Is there a defined SPI
>> >device that every slot is going to have? Or the connector has SPI
>> >interface and *anything* could be attached on it?
>>
>> So a module slot is like a pcie slot, it can be occupied or not, and when
>
>But which buses...

I don't think I am fully understanding what you are asking of me. The
module will always be an spi device, that is the main communication bus.

Kind regards,
Maud

From jic23 at kernel.org  Mon Mar 17 03:45:37 2025
From: jic23 at kernel.org (Jonathan Cameron)
Date: Mon, 17 Mar 2025 10:45:37 +0000
Subject: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <Z9frCUqRTD0i1Faq@smile.fi.intel.com>
References: <cover.1741849323.git.mazziesaccount@gmail.com>
	<df0b2b53affbef5ccb7219328cc15db3ba843737.1741849323.git.mazziesaccount@gmail.com>
	<Z9LQ0O34EUM8WZku@smile.fi.intel.com>
	<20250316094112.6731bd01@jic23-huawei>
	<50b126c5-248e-4694-9782-4f28d6db5fce@gmail.com>
	<Z9fUmo5wp3EcNWzm@smile.fi.intel.com>
	<0db2a42f-d393-4e75-afbf-cf30c0e06cce@gmail.com>
	<Z9frCUqRTD0i1Faq@smile.fi.intel.com>
Message-ID: <20250317104537.3a8819e5@jic23-huawei>

On Mon, 17 Mar 2025 11:27:37 +0200
Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:

> On Mon, Mar 17, 2025 at 10:42:07AM +0200, Matti Vaittinen wrote:
> > On 17/03/2025 09:51, Andy Shevchenko wrote:  
> > > On Mon, Mar 17, 2025 at 09:11:08AM +0200, Matti Vaittinen wrote:  
> > > > On 16/03/2025 11:41, Jonathan Cameron wrote:  
> > > > > On Thu, 13 Mar 2025 14:34:24 +0200
> > > > > Andy Shevchenko <andriy.shevchenko at linux.intel.com> wrote:  
> > > > > > On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:  
> 
> ...
> 
> > > > > > > +	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
> > > > > > > +				&sun20i_gpadc_chan_template, -1, &channels);
> > > > > > > +	if (num_channels < 0)
> > > > > > > +		return num_channels;
> > > > > > > +
> > > > > > >    	if (num_channels == 0)
> > > > > > >    		return dev_err_probe(dev, -ENODEV, "no channel children\n");  
> > > > > > 
> > > > > > Note, this what I would expected in your helper to see, i.e. separated cases
> > > > > > for < 0 (error code) and == 0, no channels.
> > > > > > 
> > > > > > Also, are all users going to have this check? Usually in other similar APIs
> > > > > > we return -ENOENT. And user won't need to have an additional check in case of
> > > > > > 0 being considered as an error case too.  
> > > > > In a few cases we'll need to do the dance the other way in the caller.
> > > > > So specifically check for -ENOENT and not treat it as an error.
> > > > > 
> > > > > That stems from channel nodes being optionally added to drivers after
> > > > > they have been around a while (usually to add more specific configuration)
> > > > > and needing to maintain old behaviour of presenting all channels with default
> > > > > settings.
> > > > > 
> > > > > I agree that returning -ENOENT is a reasonable way to handle this.  
> > > > 
> > > > I agree - but I'm going to use -ENODEV instead of -ENOENT because that's
> > > > what the current callers return if they find no channels. That way the
> > > > drivers can return the value directly without converting -ENOENT to -ENODEV.  
> > > 
> > > ENODEV can be easily clashed with other irrelevant cases,  
> > 
> > Can you please explain what cases?  
> 
> When it's a code path that returns the same error code for something different.
> 
> > > ENOENT is the correct
> > > error code.  
> > 
> > I kind of agree if we look this from the fwnode perspective. But, when we
> > look this from the intended user's perspective, I can very well understand
> > the -ENODEV. Returning -ENODEV from ADC driver's probe which can't find any
> > of the channels feels correct to me.  
> 
> Okay, it seems we have got yet another disagreement as I think this has to
> be ENOENT. Because this is related to the firmware description and not real
> hardware discovery path. If it is the latter, I may fully agree on ENODEV
> choice. But AFAICS it's not the case here.

I'd not rule so strongly but -ENOENT is fine and there should be no fall out from
standardizing around that.

> 
> > > If drivers return this instead of another error code, nothing bad
> > > happen, it's not an ABI path, correct?  
> > 
> > I don't know if failure returned from a probe is an ABI. I still feel
> > -ENODEV is correct value,  
> 
> And I have the opposite opinion. I think ENODEV is _incorrect_ choice
> in this case.
> 
> > and I don't want to change it for existing users -
> > and I think also new ADC drivers should use -ENODEV if they find no channels
> > at all.  
> 
> Again, the problem is that you are trying to apply the error code for HW to the
> information that comes from FW.
> 
> > Besides that I think -ENODEV to be right, changing it to -ENOENT for
> > existing callers requires a buy-in from Jonathan (and/or) the driver
> > maintainers.  
> 
> Yeah, will wait for Jonathan to judge, but I think you can find rationale above.

The distinction between hardware not there (-ENODEV) and missing stuff in 
FW (-ENOENT) seems reasonable to make. If anyone is relying on capturing
a specific error code and doing anything much with it beyond logging
for debug then they are very optimistic as this stuff is often
not particularly stable over kernel versions. That sort of error code specific
handling only makes sense very locally, not in probe() return values.

Hence my preference here is switch to -ENOENT and we'll go with that for
new code in general that hits this sort of problem.   I'd not consider
older code returning -ENODEV buggy as such, just slightly less than
ideal. So any changes for now probably belong in series touching the code
for other reasons rather than a mass cleanup.

Jonathan


From tudor.ambarus at linaro.org  Mon Mar 17 03:48:45 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 17 Mar 2025 10:48:45 +0000
Subject: [PATCH 2/3] firmware: exynos-acpm: silence EPROBE_DEFER error on
 boot
In-Reply-To: <638cf070-9fd1-416e-8172-75f189ab0dfe@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
 <20250314-acpm-fixes-v1-2-ab03ca8e723f@linaro.org>
 <638cf070-9fd1-416e-8172-75f189ab0dfe@linaro.org>
Message-ID: <d2e162cd-b12b-47e2-9190-2ecce3489b9c@linaro.org>



On 3/17/25 10:26 AM, Tudor Ambarus wrote:
> 
> 
> On 3/14/25 4:40 PM, Andr? Draszik wrote:
>> This driver emits error messages when client drivers are trying to get
>> an interface handle to this driver here before this driver has
>> completed _probe().
>>
>> Given this driver returns -EPROBE_DEFER in that case, this is not an
>> error and shouldn't be emitted to the log, so just remove them.
>>
>> Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
>> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> 
> Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>

I see you kept the error message though for of_find_device_by_node()
failure. You either get rid of that too, or maybe transform all to dev_dbg?


From krzk at kernel.org  Mon Mar 17 03:49:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 11:49:24 +0100
Subject: =?utf-8?B?5Zue5aSN?= =?utf-8?Q?=3A?= [PATCH 5/5] dt-bindings:
 pmic: mediatek: Add pmic documents
In-Reply-To: <SEZPR03MB6891E21CD04880AB1AC91BFC80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
References: <20250314073307.25092-1-Lu.Tang@mediatek.com>
 <20250314073307.25092-6-Lu.Tang@mediatek.com>
 <SEZPR03MB6891E21CD04880AB1AC91BFC80D22@SEZPR03MB6891.apcprd03.prod.outlook.com>
Message-ID: <20250317-mighty-dolphin-of-downpour-e7a9f5@krzk-bin>

On Fri, Mar 14, 2025 at 09:01:11AM +0000, Lu Tang (??) wrote:
> Update email
> 
> -----????-----
> ???: Lu.Tang <Lu.Tang at mediatek.com> 
> ????: 2025?3?14? 15:33
> ???: Jonathan Cameron <jic23 at kernel.org>; Lars-Peter Clausen <lars at metafoo.de>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Dmitry Torokhov <dmitry.torokhov at gmail.com>; Lee Jones <lee at kernel.org>; Matthias Brugger <matthias.bgg at gmail.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>; Sean Wang <sean.wang at kernel.org>; Linus Walleij <linus.walleij at linaro.org>; Liam Girdwood <lgirdwood at gmail.com>; Mark Brown <broonie at kernel.org>; Stephen Boyd <sboyd at kernel.org>; Chen Zhong (??) <Chen.Zhong at mediatek.com>; Sen Chu <shen.chu at mediatek.com>
> ??: linux-iio at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-input at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-mediatek at lists.infradead.org; linux-gpio at vger.kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group at mediatek.com>; Lu Tang (??) <Lu.Tang at mediatek.com>
> ??: [PATCH 5/5] dt-bindings: pmic: mediatek: Add pmic documents

The amount of errors shown by checkpatch on this is just shocking.

Best regards,
Krzysztof



From ulf.hansson at linaro.org  Mon Mar 17 03:51:20 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Mon, 17 Mar 2025 11:51:20 +0100
Subject: [PATCH v2] mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
In-Reply-To: <20250311165946.28190-1-kamal.dasu@broadcom.com>
References: <20250311165946.28190-1-kamal.dasu@broadcom.com>
Message-ID: <CAPDyKFoDh-9L49Yh+Xv10t9Dt_Vyvn7dGCb5dKV0RiNJi5aoZg@mail.gmail.com>

On Tue, 11 Mar 2025 at 17:59, Kamal Dasu <kamal.dasu at broadcom.com> wrote:
>
> cqhci timeouts observed on brcmstb platforms during suspend:
>   ...
>   [  164.832853] mmc0: cqhci: timeout for tag 18
>   ...
>
> Adding cqhci_suspend()/resume() calls to disable cqe
> in sdhci_brcmstb_suspend()/resume() respectively to fix
> CQE timeouts seen on PM suspend.
>
> Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)")
> Cc: stable at vger.kernel.org
> Signed-off-by: Kamal Dasu <kamal.dasu at broadcom.com>

Applied for fixes, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-brcmstb.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 0ef4d578ade8..48cdcba0f39c 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -503,8 +503,15 @@ static int sdhci_brcmstb_suspend(struct device *dev)
>         struct sdhci_host *host = dev_get_drvdata(dev);
>         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>         struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
> +       int ret;
>
>         clk_disable_unprepare(priv->base_clk);
> +       if (host->mmc->caps2 & MMC_CAP2_CQE) {
> +               ret = cqhci_suspend(host->mmc);
> +               if (ret)
> +                       return ret;
> +       }
> +
>         return sdhci_pltfm_suspend(dev);
>  }
>
> @@ -529,6 +536,9 @@ static int sdhci_brcmstb_resume(struct device *dev)
>                         ret = clk_set_rate(priv->base_clk, priv->base_freq_hz);
>         }
>
> +       if (host->mmc->caps2 & MMC_CAP2_CQE)
> +               ret = cqhci_resume(host->mmc);
> +
>         return ret;
>  }
>  #endif
> --
> 2.17.1
>


From krzysztof.kozlowski at linaro.org  Mon Mar 17 03:51:03 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 11:51:03 +0100
Subject: [PATCH 2/2] scsi: ufs: dt-bindings: exynos: add dma-coherent
 property for gs101
In-Reply-To: <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
 <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org>
Message-ID: <20250317-gorgeous-wrasse-of-aurora-82ee0c@krzk-bin>

On Fri, Mar 14, 2025 at 03:38:03PM +0000, Peter Griffin wrote:
> dma-coherent property is required for gs101 as ufs-exynos enables
> sharability.
> 
> Fixes: 438e23b61cd4 ("scsi: ufs: dt-bindings: exynos: Add gs101 compatible")
> Cc: stable at vger.kernel.org

This change is a noop and fixes nothing, which you can test by testing
your DTS without and with this patch.

Best regards,
Krzysztof



From ulf.hansson at linaro.org  Mon Mar 17 03:50:54 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Mon, 17 Mar 2025 11:50:54 +0100
Subject: [PATCH] pmdomain: arm: scmi_pm_domain: Remove redundant state verification
In-Reply-To: <20250314095851.443979-1-sudeep.holla@arm.com>
References: <20250314095851.443979-1-sudeep.holla@arm.com>
Message-ID: <CAPDyKFqhvJnth4ASfnfj5xTkM625m-rAidZ3zdy01CzkB7e1Ng@mail.gmail.com>

On Fri, 14 Mar 2025 at 10:58, Sudeep Holla <sudeep.holla at arm.com> wrote:
>
> Currently, scmi_pd_power() explicitly verifies whether the requested
> power state was applied by calling state_get(). While this check could
> detect failures where the state was not properly updated, ensuring
> correctness is the responsibility of the SCMI firmware.
>
> Removing this redundant state_get() call eliminates an unnecessary
> round-trip to the firmware, improving efficiency. Any mismatches
> between the requested and actual states should be handled by the SCMI
> firmware, which must return a failure if state_set() is unsuccessful.
>
> Additionally, in some cases, checking the state after powering off a
> domain may be unreliable or unsafe, depending on the firmware
> implementation.
>
> This patch removes the redundant verification, simplifying the function
> without compromising correctness.
>
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Ulf Hansson <ulf.hansson at linaro.org>
> Cc: Cristian Marussi <cristian.marussi at arm.com>
> Reported-and-tested-by: Ranjani Vaidyanathan <ranjani.vaidyanathan at nxp.com>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/pmdomain/arm/scmi_pm_domain.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
> index 86b531e15b85..2a213c218126 100644
> --- a/drivers/pmdomain/arm/scmi_pm_domain.c
> +++ b/drivers/pmdomain/arm/scmi_pm_domain.c
> @@ -24,8 +24,7 @@ struct scmi_pm_domain {
>
>  static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
>  {
> -       int ret;
> -       u32 state, ret_state;
> +       u32 state;
>         struct scmi_pm_domain *pd = to_scmi_pd(domain);
>
>         if (power_on)
> @@ -33,13 +32,7 @@ static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
>         else
>                 state = SCMI_POWER_STATE_GENERIC_OFF;
>
> -       ret = power_ops->state_set(pd->ph, pd->domain, state);
> -       if (!ret)
> -               ret = power_ops->state_get(pd->ph, pd->domain, &ret_state);
> -       if (!ret && state != ret_state)
> -               return -EIO;
> -
> -       return ret;
> +       return power_ops->state_set(pd->ph, pd->domain, state);
>  }
>
>  static int scmi_pd_power_on(struct generic_pm_domain *domain)
> --
> 2.34.1
>


From james.clark at linaro.org  Mon Mar 17 03:59:06 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 10:59:06 +0000
Subject: [PATCH v4] coresight: Add a KUnit test for
 coresight_find_default_sink()
In-Reply-To: <48b192c7-4250-4e11-8dcd-b147dd8c0a28@arm.com>
References: <20250312-james-cs-kunit-test-v4-1-ae3dd718a26a@linaro.org>
 <48b192c7-4250-4e11-8dcd-b147dd8c0a28@arm.com>
Message-ID: <919b1fa9-3b95-4be1-a966-9f0cfc166756@linaro.org>



On 14/03/2025 12:35 pm, Anshuman Khandual wrote:
> On 3/12/25 16:01, James Clark wrote:
>> Add a test to confirm that default sink selection skips over an ETF
>> and returns an ETR even if it's further away.
>>
>> This also makes it easier to add new unit tests in the future.
> 
> The test overall looks good but there are some comments below.
> 
>>
>> Reviewed-by: Leo Yan <leo.yan at arm.com>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>> Changes in v4:
>> - Rename etm to src now that it's not CORESIGHT_DEV_SUBTYPE_SOURCE_PROC
>> - Remove the now empty src_ops too
>> - Fix a rebase mistake in the Makefile that removed CTCU
>> - Link to v3: https://lore.kernel.org/r/20250312-james-cs-kunit-test-v3-1-dcfb69730161 at linaro.org
>>
>> Changes in v3:
>> - Use CORESIGHT_DEV_SUBTYPE_SOURCE_BUS type instead of the default
>>    (CORESIGHT_DEV_SUBTYPE_SOURCE_PROC) so that the test still works even
>>    when TRBE sinks are registered. This also removes the need for the
>>    fake CPU ID callback.
>> - Link to v2: https://lore.kernel.org/r/20250305-james-cs-kunit-test-v2-1-83ba682b976c at linaro.org
>>
>> Changes in v2:
>> - Let devm free everything rather than doing individual kfrees:
>>    "Like with managed drivers, KUnit-managed fake devices are
>>    automatically cleaned up when the test finishes, but can be manually
>>    cleaned up early with kunit_device_unregister()."
>> - Link to v1: https://lore.kernel.org/r/20250225164639.522741-1-james.clark at linaro.org
>> ---
>>   drivers/hwtracing/coresight/Kconfig                |  9 +++
>>   drivers/hwtracing/coresight/Makefile               |  1 +
>>   drivers/hwtracing/coresight/coresight-core.c       |  1 +
>>   .../hwtracing/coresight/coresight-kunit-tests.c    | 74 ++++++++++++++++++++++
>>   4 files changed, 85 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
>> index ecd7086a5b83..f064e3d172b3 100644
>> --- a/drivers/hwtracing/coresight/Kconfig
>> +++ b/drivers/hwtracing/coresight/Kconfig
>> @@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
>>   
>>   	  To compile this driver as a module, choose M here: the module will be
>>   	  called coresight-dummy.
>> +
>> +config CORESIGHT_KUNIT_TESTS
>> +	  tristate "Enable Coresight unit tests"
>> +	  depends on KUNIT
>> +	  default KUNIT_ALL_TESTS
>> +	  help
>> +	    Enable Coresight unit tests. Only useful for development and not
>> +	    intended for production.
> 
> The description sounds adequate given that more unit tests might be added later.
> 
>> +
>>   endif
>> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
>> index 8e62c3150aeb..4e6ea5b05b01 100644
>> --- a/drivers/hwtracing/coresight/Makefile
>> +++ b/drivers/hwtracing/coresight/Makefile
>> @@ -53,3 +53,4 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>>   obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
>>   coresight-ctcu-y := coresight-ctcu-core.o
>> +obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index fb43ef6a3b1f..47af75ba7a00 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -959,6 +959,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
>>   	}
>>   	return csdev->def_sink;
>>   }
>> +EXPORT_SYMBOL_GPL(coresight_find_default_sink);
> 
> This symbol needs exporting given that the kunit test here can also be built
> as a module.
> 
>>   
>>   static int coresight_remove_sink_ref(struct device *dev, void *data)
>>   {
>> diff --git a/drivers/hwtracing/coresight/coresight-kunit-tests.c b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> new file mode 100644
>> index 000000000000..c8f361767c45
>> --- /dev/null
>> +++ b/drivers/hwtracing/coresight/coresight-kunit-tests.c
>> @@ -0,0 +1,74 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#include <kunit/test.h>
>> +#include <kunit/device.h>
>> +#include <linux/coresight.h>
>> +
>> +#include "coresight-priv.h"
>> +
>> +static struct coresight_device *coresight_test_device(struct device *dev)
>> +{
>> +	struct coresight_device *csdev = devm_kcalloc(dev, 1,
>> +						     sizeof(struct coresight_device),
>> +						     GFP_KERNEL);
>> +	csdev->pdata = devm_kcalloc(dev, 1,
>> +				   sizeof(struct coresight_platform_data),
>> +				   GFP_KERNEL);
> 
> Guess both these memory allocations gets freed up here automatically
> via kunit_device's device framework when the test suit exits ?
> 

Yes, see the change log in the cover letter.

>> +	return csdev;
>> +}
>> +
>> +static void test_default_sink(struct kunit *test)
>> +{
>> +	/*
>> +	 * Source -> ETF -> ETR -> CATU
>> +	 *                   ^
>> +	 *                   | default
>> +	 */
> 
> Should some more random path combinations involving ETR and ETF along with
> other coresight devices also be tested where ETR gets selected as default ?
> 

Probably, but I only added what was required to test Steve's original 
bug report. We can add more tests for coresight_find_default_sink() if 
when it gets changed or refactored in the future. At the moment without 
any changes in sight there wouldn't be any benefit.

>> +	struct device *dev = kunit_device_register(test, "coresight_kunit");
>> +	struct coresight_device *src = coresight_test_device(dev),
>> +				*etf = coresight_test_device(dev),
>> +				*etr = coresight_test_device(dev),
>> +				*catu = coresight_test_device(dev);
>> +	struct coresight_connection conn = {};
>> +
>> +	src->type = CORESIGHT_DEV_TYPE_SOURCE;
>> +	/*
>> +	 * Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
>> +	 * a TRBE sink if one is registered.
> 
> Probably this should be tested as well i.e when TRBE sink is also available
> and it gets picked up as a default.
> 

This is quite simple logic so it's probably even less of a valuable 
test. I only added a test for the other sinks because the recursive 
search for them is not easy code to follow by eye.



From tudor.ambarus at linaro.org  Mon Mar 17 04:11:01 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 17 Mar 2025 11:11:01 +0000
Subject: [PATCH 3/3] firmware: exynos-acpm: convert to dev_err_probe() in
 client API
In-Reply-To: <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
 <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>
Message-ID: <75f49e65-5a8a-4a52-bed9-31be4a76d536@linaro.org>



On 3/14/25 4:40 PM, Andr? Draszik wrote:
> dev_err_probe() exists to simplify code and unify error messages by
> using its message template.
> 
> Convert the remaining dev_err() in acpm_get_by_phandle() to
> dev_err_probe().
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  drivers/firmware/samsung/exynos-acpm.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> index 48f1e3cacaa709ae703115169df138b659ddae44..03f907a95c6acd66d89cd8af2f52e7c6dadf492a 100644
> --- a/drivers/firmware/samsung/exynos-acpm.c
> +++ b/drivers/firmware/samsung/exynos-acpm.c
> @@ -701,12 +701,14 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
>  
>  	link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
>  	if (!link) {
> -		dev_err(&pdev->dev,
> -			"Failed to create device link to consumer %s.\n",
> -			dev_name(dev));
> +		int ret = -EINVAL;
> +
> +		dev_err_probe(&pdev->dev, ret,
> +			      "Failed to create device link to consumer %s.\n",
> +			      dev_name(dev));
>  		platform_device_put(pdev);
>  		module_put(pdev->dev.driver->owner);
> -		return ERR_PTR(-EINVAL);
> +		return ERR_PTR(ret);
>  	}
>  
>  	return &acpm->handle;
> 

The clients are indeed expected to call this method in their probe
method. Shall we make such assumption? I'm in the middle here, but I
don't mind if this gets queued:
Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>


From hejunhao3 at huawei.com  Mon Mar 17 04:16:01 2025
From: hejunhao3 at huawei.com (hejunhao)
Date: Mon, 17 Mar 2025 19:16:01 +0800
Subject: [PATCH] coresight: Fixes device's owner field for registered
 using coresight_init_driver()
In-Reply-To: <1a030491-5bc6-4122-baed-faf123f0f872@arm.com>
References: <20240918035327.9710-1-hejunhao3@huawei.com>
 <e2194d2a-0f51-4e59-a1ca-b4563b3389ec@arm.com>
 <c3744062-f7c1-82df-2fa1-591da3b2dc5e@huawei.com>
 <1a030491-5bc6-4122-baed-faf123f0f872@arm.com>
Message-ID: <2a681949-3053-8ae6-597b-49b16e1e87af@huawei.com>

Hi Suzuki,


On 2025/3/14 18:38, Suzuki K Poulose wrote:
> Hi
>
> On 14/03/2025 07:44, hejunhao wrote:
>> Hi Suzuki,
>>
>> Could you confirm if this patch was queued in coresight/next or 
>> upstream of the mainline?
>>
>> I couldn't find it in: kernel/git/coresight/linux.git or Kernel 
>> v6.14.0- rc4.
>>
>> Maybe am I missing some information?
>
> Apologies, I missed queueing this. That said, I have a minor comment 
> on the patch below.
>
>>
>> Best regards,
>> Junhao.
>>
>>
>> On 2024/9/18 16:29, Suzuki K Poulose wrote:
>>> On 18/09/2024 04:53, Junhao He wrote:
>>>> The coresight_init_driver() of the coresight-core module is called 
>>>> from
>>>> the sub coresgiht device (such as tmc/stm/funnle/...) module. It calls
>>>> amba_driver_register() and Platform_driver_register(), which are macro
>>>> functions that use the coresight-core's module to initialize the 
>>>> caller's
>>>> owner field.  Therefore, when the sub coresight device calls
>>>> coresight_init_driver(), an incorrect THIS_MODULE value is captured.
>>>>
>>>> The sub coesgiht modules can be removed while their callbacks are
>>>> running, resulting in a general protection failure.
>>>>
>>>> Add module parameter to coresight_init_driver() so can be called
>>>> with the module of the callback.
>>>>
>>>> Fixes: 075b7cd7ad7d ("coresight: Add helpers registering/removing 
>>>> both AMBA and platform drivers")
>>>> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
>>>
>>> Thanks for the fix, looks good to me. I will queue this for v6.13
>>>
>>> Suzuki
>>>
>>>> ---
>>>>   drivers/hwtracing/coresight/coresight-catu.c       | 2 +-
>>>>   drivers/hwtracing/coresight/coresight-core.c       | 6 +++---
>>>>   drivers/hwtracing/coresight/coresight-cpu-debug.c  | 3 ++-
>>>>   drivers/hwtracing/coresight/coresight-funnel.c     | 3 ++-
>>>>   drivers/hwtracing/coresight/coresight-replicator.c | 3 ++-
>>>>   drivers/hwtracing/coresight/coresight-stm.c        | 2 +-
>>>>   drivers/hwtracing/coresight/coresight-tmc-core.c   | 2 +-
>>>>   drivers/hwtracing/coresight/coresight-tpiu.c       | 2 +-
>>>>   include/linux/coresight.h                          | 2 +-
>>>>   9 files changed, 14 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/drivers/hwtracing/coresight/coresight-catu.c 
>>>> b/drivers/ hwtracing/coresight/coresight-catu.c
>>>> index bfea880d6dfb..337668f9cfd4 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-catu.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-catu.c
>>>> @@ -702,7 +702,7 @@ static int __init catu_init(void)
>>>>   {
>>>>       int ret;
>>>>   -    ret = coresight_init_driver("catu", &catu_driver, 
>>>> &catu_platform_driver);
>>>> +    ret = coresight_init_driver("catu", &catu_driver, 
>>>> &catu_platform_driver, THIS_MODULE);
>>>>       tmc_etr_set_catu_ops(&etr_catu_buf_ops);
>>>>       return ret;
>>>>   }
>>>> diff --git a/drivers/hwtracing/coresight/coresight-core.c 
>>>> b/drivers/ hwtracing/coresight/coresight-core.c
>>>> index 9fc6f6b863e0..c546a417836c 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-core.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>>>> @@ -1399,17 +1399,17 @@ module_init(coresight_init);
>>>>   module_exit(coresight_exit);
>>>>     int coresight_init_driver(const char *drv, struct amba_driver 
>>>> *amba_drv,
>>>> -              struct platform_driver *pdev_drv)
>>>> +              struct platform_driver *pdev_drv, struct module *owner)
>>>>   {
>>>>       int ret;
>>>>   -    ret = amba_driver_register(amba_drv);
>>>> +    ret = __amba_driver_register(amba_drv, owner);
>>>>       if (ret) {
>>>>           pr_err("%s: error registering AMBA driver\n", drv);
>>>>           return ret;
>>>>       }
>>>>   -    ret = platform_driver_register(pdev_drv);
>>>> +    ret = __platform_driver_register(pdev_drv, owner);
>>>>       if (!ret)
>>>>           return 0;
>>>>   diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/ 
>>>> drivers/hwtracing/coresight/coresight-cpu-debug.c
>>>> index 75962dae9aa1..cc599c5ef4b2 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
>>>> @@ -774,7 +774,8 @@ static struct platform_driver 
>>>> debug_platform_driver = {
>>>>     static int __init debug_init(void)
>>>>   {
>>>> -    return coresight_init_driver("debug", &debug_driver, 
>>>> &debug_platform_driver);
>>>> +    return coresight_init_driver("debug", &debug_driver, 
>>>> &debug_platform_driver,
>>>> +                     THIS_MODULE);
>
> minor nit:
>
> Could we make the coresight_init_driver() a static inline or even a
> macro to automatically add the THIS_MODULE param ?
>
> Something like:
>
> #define coresight_init_driver(name, amba_drv, pdev_drv)
>     coresight_init_driver_owner(name, amba_drv, pdev_drv, THIS_MODULE)
>
> I could respin this and queue the change.
>
>

Yes, thanks for the review.  Will fix in next version.



>
>
>>>>   }
>>>>     static void __exit debug_exit(void)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/ 
>>>> drivers/hwtracing/coresight/coresight-funnel.c
>>>> index 5a819c8970fb..8f451b051ddc 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-funnel.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
>>>> @@ -433,7 +433,8 @@ static struct amba_driver dynamic_funnel_driver 
>>>> = {
>>>>     static int __init funnel_init(void)
>>>>   {
>>>> -    return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>>>> &funnel_driver);
>>>> +    return coresight_init_driver("funnel", &dynamic_funnel_driver, 
>>>> &funnel_driver,
>>>> +                     THIS_MODULE);
>>>>   }
>>>>     static void __exit funnel_exit(void)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/ 
>>>> drivers/hwtracing/coresight/coresight-replicator.c
>>>> index 3e55be9c8418..f7607c72857c 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-replicator.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
>>>> @@ -438,7 +438,8 @@ static struct amba_driver 
>>>> dynamic_replicator_driver = {
>>>>     static int __init replicator_init(void)
>>>>   {
>>>> -    return coresight_init_driver("replicator", 
>>>> &dynamic_replicator_driver, &replicator_driver);
>>>> +    return coresight_init_driver("replicator", 
>>>> &dynamic_replicator_driver, &replicator_driver,
>>>> +                     THIS_MODULE);
>>>>   }
>>>>     static void __exit replicator_exit(void)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/ 
>>>> hwtracing/coresight/coresight-stm.c
>>>> index 117dbb484543..403eea8f95d4 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>>>> @@ -1046,7 +1046,7 @@ static struct platform_driver 
>>>> stm_platform_driver = {
>>>>     static int __init stm_init(void)
>>>>   {
>>>> -    return coresight_init_driver("stm", &stm_driver, 
>>>> &stm_platform_driver);
>>>> +    return coresight_init_driver("stm", &stm_driver, 
>>>> &stm_platform_driver, THIS_MODULE);
>>>>   }
>>>>     static void __exit stm_exit(void)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/ 
>>>> drivers/hwtracing/coresight/coresight-tmc-core.c
>>>> index b54562f392f3..e31e36635394 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
>>>> @@ -742,7 +742,7 @@ static struct platform_driver 
>>>> tmc_platform_driver = {
>>>>     static int __init tmc_init(void)
>>>>   {
>>>> -    return coresight_init_driver("tmc", &tmc_driver, 
>>>> &tmc_platform_driver);
>>>> +    return coresight_init_driver("tmc", &tmc_driver, 
>>>> &tmc_platform_driver, THIS_MODULE);
>>>>   }
>>>>     static void __exit tmc_exit(void)
>>>> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c 
>>>> b/drivers/ hwtracing/coresight/coresight-tpiu.c
>>>> index b048e146fbb1..f9ecd05cbe5c 100644
>>>> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
>>>> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
>>>> @@ -318,7 +318,7 @@ static struct platform_driver 
>>>> tpiu_platform_driver = {
>>>>     static int __init tpiu_init(void)
>>>>   {
>>>> -    return coresight_init_driver("tpiu", &tpiu_driver, 
>>>> &tpiu_platform_driver);
>>>> +    return coresight_init_driver("tpiu", &tpiu_driver, 
>>>> &tpiu_platform_driver, THIS_MODULE);
>>>>   }
>>>>     static void __exit tpiu_exit(void)
>>>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>>>> index f09ace92176e..e6c26952ddc2 100644
>>>> --- a/include/linux/coresight.h
>>>> +++ b/include/linux/coresight.h
>>>> @@ -660,7 +660,7 @@ coresight_find_output_type(struct 
>>>> coresight_platform_data *pdata,
>>>>                  union coresight_dev_subtype subtype);
>>>>     int coresight_init_driver(const char *drv, struct amba_driver 
>>>> *amba_drv,
>>>> -              struct platform_driver *pdev_drv);
>>>> +              struct platform_driver *pdev_drv, struct module 
>>>> *owner);
>>>>     void coresight_remove_driver(struct amba_driver *amba_drv,
>>>>                    struct platform_driver *pdev_drv);
>>>
>>>
>>> .
>>>
>>
>
>
> .
>



From krzysztof.kozlowski at linaro.org  Mon Mar 17 04:18:53 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 12:18:53 +0100
Subject: [PATCH] ARM: dts: nxp: Align NAND controller node name with bindings
Message-ID: <20250317111853.43708-1-krzysztof.kozlowski@linaro.org>

Bindings expect NAND controller device nodes to be named
"nand-controller".

Cc: Fabio Estevam <festevam at gmail.com>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 arch/arm/boot/dts/nxp/imx/imx25.dtsi | 2 +-
 arch/arm/boot/dts/nxp/imx/imx35.dtsi | 2 +-
 arch/arm/boot/dts/nxp/imx/imx51.dtsi | 2 +-
 arch/arm/boot/dts/nxp/imx/imx53.dtsi | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx25.dtsi b/arch/arm/boot/dts/nxp/imx/imx25.dtsi
index 9cfff2151b7e..82601a4b7b4b 100644
--- a/arch/arm/boot/dts/nxp/imx/imx25.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx25.dtsi
@@ -611,7 +611,7 @@ bus at 80000000 {
 			reg = <0x80000000 0x3b002000>;
 			ranges;
 
-			nfc: nand at bb000000 {
+			nfc: nand-controller at bb000000 {
 				#address-cells = <1>;
 				#size-cells = <1>;
 
diff --git a/arch/arm/boot/dts/nxp/imx/imx35.dtsi b/arch/arm/boot/dts/nxp/imx/imx35.dtsi
index 30beb39e0162..111d7c0331f5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx35.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx35.dtsi
@@ -363,7 +363,7 @@ emi at 80000000 { /* External Memory Interface */
 			reg = <0x80000000 0x40000000>;
 			ranges;
 
-			nfc: nand at bb000000 {
+			nfc: nand-controller at bb000000 {
 				#address-cells = <1>;
 				#size-cells = <1>;
 				compatible = "fsl,imx35-nand", "fsl,imx25-nand";
diff --git a/arch/arm/boot/dts/nxp/imx/imx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
index 8323e3a56a1f..f42903c9cf0d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
@@ -595,7 +595,7 @@ weim: memory-controller at 83fda000 {
 				status = "disabled";
 			};
 
-			nfc: nand at 83fdb000 {
+			nfc: nand-controller at 83fdb000 {
 				#address-cells = <1>;
 				#size-cells = <1>;
 				compatible = "fsl,imx51-nand";
diff --git a/arch/arm/boot/dts/nxp/imx/imx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
index faac7cc249d0..0c38c37dd142 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
@@ -775,7 +775,7 @@ audmux: audmux at 63fd0000 {
 				status = "disabled";
 			};
 
-			nfc: nand at 63fdb000 {
+			nfc: nand-controller at 63fdb000 {
 				compatible = "fsl,imx53-nand";
 				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
 				interrupts = <8>;
-- 
2.43.0



From krzk at kernel.org  Mon Mar 17 04:19:54 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 12:19:54 +0100
Subject: [PATCH] ARM: dts: imx31: Use nand-controller as node name
In-Reply-To: <20250220130345.2375204-1-festevam@gmail.com>
References: <20250220130345.2375204-1-festevam@gmail.com>
Message-ID: <a6e78d47-4961-4669-8149-4ed35f3a2c9c@kernel.org>

On 20/02/2025 14:03, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> According to mxc-nand.yaml, the correct node name must be
> 'nand-controller'.
> 
> Change it accordingly to fix the following dt-schema warning:
> 
> $nodename:0: 'nand at b8000000' does not match '^nand-controller(@.*)?'
> 
> Signed-off-by: Fabio Estevam <festevam at denx.de>
> ---
>  arch/arm/boot/dts/nxp/imx/imx31.dtsi | 2 +-

Sending one fix per each node name is quite a churn, so please fix all
files in given vendor at once.

Best regards,
Krzysztof


From parvathi at couthit.com  Mon Mar 17 04:19:30 2025
From: parvathi at couthit.com (Parvathi Pudi)
Date: Mon, 17 Mar 2025 16:49:30 +0530 (IST)
Subject: [PATCH v2 1/1] soc: ti: PRUSS OCP configuration
In-Reply-To: <20250307210517.5xjfc6wntcbj3s4k@precision>
References: <20250108125937.10604-1-basharath@couthit.com> <20250108125937.10604-2-basharath@couthit.com> <20250307210517.5xjfc6wntcbj3s4k@precision>
Message-ID: <1365068627.843903.1742210370862.JavaMail.zimbra@couthit.local>

Hi Nishanth,

> On 18:29-20250108, Basharath Hussain Khaja wrote:
>> From: Roger Quadros <rogerq at ti.com>
>> 
>> Updates OCP master port configuration to enable memory access outside
>> of the PRU-ICSS subsystem.
>> 
>> This set of changes configures PRUSS_SYSCFG.STANDBY_INIT bit either
>> to enable or disable the OCP master ports (applicable only on SoCs
>> using OCP interconnect like the OMAP family).
>> 
>> Signed-off-by: Roger Quadros <rogerq at ti.com>
>> Signed-off-by: Andrew F. Davis <afd at ti.com>
>> Signed-off-by: Parvathi Pudi <parvathi at couthit.com>
>> Signed-off-by: Basharath Hussain Khaja <basharath at couthit.com>
> 
> On the verge of applying this patch, looking deeper, I noticed
> drivers/bus/ti-sysc.c managing the sysc controls. infact, I wonder if
> b2745d92bb015cc4454d4195c4ce6e2852db397e ("bus: ti-sysc: Add support
> for PRUSS SYSC type") could be merged with this?
> 
> 
> Could you say why drivers/bus/ti-sysc.c would'nt be the right solution?
> 
> Ccying Kevin if he has any ideas about this.
> 

Thank you for the feedback.

We will analyze ti-sysc and revert back with an update shortly.


Thanks and Regards,
Parvathi.


From jjian.zhou at mediatek.com  Mon Mar 17 04:03:25 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 19:03:25 +0800
Subject: [PATCH RFC v3 3/3] dt-bindings: mailbox: mtk,mt8196-vcp-mbox: add mtk vcp-mbox document
In-Reply-To: <20250317110331.2776-1-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
Message-ID: <20250317110331.2776-4-jjian.zhou@mediatek.com>

This patch adds document for mediatek vcp mbox.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml

diff --git a/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
new file mode 100644
index 000000000000..bd1b024e22f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/mtk,mt8196-vcp-mbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Video Companion Processor (VCP) mailbox
+
+maintainers:
+  - Jjian Zhou <Jjian.Zhou at mediatek.com>
+
+description:
+  The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
+  messages through 64 32-bit wide registers. It has 32 interrupt vectors in
+  either direction for signalling purposes.
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8196-vcp-mbox
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  "#mbox-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - "#mbox-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    mailbox at 31b80000 {
+        compatible = "mediatek,mt8196-vcp-mbox";
+        reg = <0x31b80000 0x1000>;
+        interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
+        #mbox-cells = <0>;
+    };
-- 
2.45.2



From jjian.zhou at mediatek.com  Mon Mar 17 04:03:22 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 19:03:22 +0800
Subject: [PATCH RFC v3 0/3] add VCP mailbox and IPC driver
Message-ID: <20250317110331.2776-1-jjian.zhou@mediatek.com>

The VCP mailbox has 5 groups. Each group has corresponding interrupts,
registers, and 64 slots (each slot is 4 bytes). Since different features
share one of the mailbox groups, the VCP mailbox needs to establish a
send table and a receive table. The send table is used to record the
feature ID, mailbox ID, and the number of slots occupied. The receive table
is used to record the feature ID, mailbox ID, the number of slots occupied,
and the receive options. The API setup_mbox_table in mtk-vcp-ipc.c calculates
the slot offset and pin index for each feature ID based on the mailbox ID and
slot number in the send and receive tables (several slots form a pin, and
each pin can trigger an interrupt). These descriptions are written in the
mtk-vcp-ipc.c file -- we call it the IPC layer.

We have two questions:
How should we describe the mailbox and IPI?
Can the intermediate IPC layer be rewritten as a virtual mailbox layer?

Example of send and recve table:
Operation | mbox_id | ipi_id | msg_size | align_size | slot_ofs | pin_index |  notes
send          0          0       18          18           0          0
recv          0          1       18          18          18          9
send          1         15        8           8           0          0
send          1         16       18          18           8          4
send          1          9        2           2          26         13
recv          1         15        8           8          28         14       ack of send ipi_id=15
recv          1         17       18          18          36         18
recv          1         10        2           2          54         27       ack of send ipi_id=2
send          2         11       18          18           0          0
send          2          2        2           2          18          9
send          2          3        3           4          20         10
send          2         32        2           2          24         12
recv          2         12       18          18          26         13
recv          2          5        1           2          44         22
recv          2          2        1           2          46         23

Recv ipi_id=2 is the ack of send ipi_id=2(The ipi_id=15 is the same.)

Jjian Zhou (3):
  mailbox: mediatek: Add mtk-vcp-mailbox driver
  firmware: mediatek: Add vcp ipc protocol interface
  dt-bindings: mailbox: mtk,mt8196-vcp-mbox: add mtk vcp-mbox document

 .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml |  49 ++
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 drivers/mailbox/Kconfig                       |   9 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c             | 179 +++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 include/linux/mailbox/mtk-vcp-mailbox.h       |  34 ++
 9 files changed, 915 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

-- 
2.45.2



From jjian.zhou at mediatek.com  Mon Mar 17 04:03:23 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 19:03:23 +0800
Subject: [PATCH RFC v3 1/3] mailbox: mediatek: Add mtk-vcp-mailbox driver
In-Reply-To: <20250317110331.2776-1-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
Message-ID: <20250317110331.2776-2-jjian.zhou@mediatek.com>

Add mtk-vcp-mailbox driver to support the communication with
VCP remote microprocessor.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/mailbox/Kconfig                 |   9 ++
 drivers/mailbox/Makefile                |   2 +
 drivers/mailbox/mtk-vcp-mailbox.c       | 179 ++++++++++++++++++++++++
 include/linux/mailbox/mtk-vcp-mailbox.h |  34 +++++
 4 files changed, 224 insertions(+)
 create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
 create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ed52db272f4d..ffc4a5491462 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -275,6 +275,15 @@ config MTK_CMDQ_MBOX
 	  critical time limitation, such as updating display configuration
 	  during the vblank.
 
+config MTK_VCP_MBOX
+	tristate "MediaTek VCP Mailbox Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  Say yes here to add support for the MediaTek VCP mailbox driver.
+	  The mailbox implementation provides access from the application
+	  processor to the MediaTek Video Processing Unit.
+	  If unsure say N.
+
 config ZYNQMP_IPI_MBOX
 	tristate "Xilinx ZynqMP IPI Mailbox"
 	depends on ARCH_ZYNQMP && OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 9a1542b55539..75a200a9d2d2 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -59,6 +59,8 @@ obj-$(CONFIG_MTK_ADSP_MBOX)	+= mtk-adsp-mailbox.o
 
 obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o
 
+obj-$(CONFIG_MTK_VCP_MBOX)	+= mtk-vcp-mailbox.o
+
 obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o
 
 obj-$(CONFIG_SUN6I_MSGBOX)	+= sun6i-msgbox.o
diff --git a/drivers/mailbox/mtk-vcp-mailbox.c b/drivers/mailbox/mtk-vcp-mailbox.c
new file mode 100644
index 000000000000..fd7a123c71c8
--- /dev/null
+++ b/drivers/mailbox/mtk-vcp-mailbox.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Corporation. All rights reserved.
+ * Author: Jjian Zhou <jjian.zhou. at mediatek.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct mtk_vcp_mbox_priv {
+	void __iomem *base;
+	struct device *dev;
+	struct mbox_controller mbox;
+	const struct mtk_vcp_mbox_cfg *cfg;
+	struct mtk_ipi_info ipi_recv;
+};
+
+struct mtk_vcp_mbox_cfg {
+	u32 set_in;
+	u32 clr_out;
+};
+
+static inline struct mtk_vcp_mbox_priv *get_mtk_vcp_mbox_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct mtk_vcp_mbox_priv, mbox);
+}
+
+static irqreturn_t mtk_vcp_mbox_irq_thread(int irq, void *data)
+{
+	struct mbox_chan *chan = data;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+
+	/* get irq status */
+	priv->ipi_recv.irq_status = readl(priv->base + priv->cfg->clr_out);
+
+	__ioread32_copy(priv->ipi_recv.msg, priv->base, MAX_SLOT_NUM);
+
+	mbox_chan_received_data(chan, &priv->ipi_recv);
+
+	/* clear irq status */
+	writel(priv->ipi_recv.irq_status, priv->base + priv->cfg->clr_out);
+
+	return IRQ_HANDLED;
+}
+
+static struct mbox_chan *mtk_vcp_mbox_xlate(struct mbox_controller *mbox,
+					    const struct of_phandle_args *sp)
+{
+	if (sp->args_count)
+		return NULL;
+
+	return mbox->chans;
+}
+
+static int mtk_vcp_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	struct mtk_ipi_info *ipi_info = data;
+	u32 status;
+
+	if (!ipi_info->msg) {
+		dev_err(priv->dev, "msg buffer is NULL.\n");
+		return -ENOMEM;
+	}
+
+	status = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	if (status) {
+		dev_err(priv->dev, "mailbox IPI %d is busy.\n", ipi_info->id);
+		return -EBUSY;
+	}
+
+	if (ipi_info->slot_ofs + ipi_info->len > MBOX_SLOT_MAX_SIZE)
+		return -EINVAL;
+	__iowrite32_copy(priv->base + ipi_info->slot_ofs, ipi_info->msg,
+			 ipi_info->len);
+
+	writel(BIT(ipi_info->index), priv->base + priv->cfg->set_in);
+
+	return 0;
+}
+
+static bool mtk_vcp_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	struct mtk_ipi_info *ipi_info = chan->active_req;
+	struct mtk_vcp_mbox_priv *priv = get_mtk_vcp_mbox_priv(chan->mbox);
+	u32 op;
+
+	op = readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index);
+	return !op;
+}
+
+static const struct mbox_chan_ops mtk_vcp_mbox_chan_ops = {
+	.send_data	= mtk_vcp_mbox_send_data,
+	.last_tx_done	= mtk_vcp_mbox_last_tx_done,
+};
+
+static int mtk_vcp_mbox_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_mbox_priv *priv;
+	struct mbox_controller *mbox;
+	int ret, irq;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	mbox = &priv->mbox;
+	mbox->dev = dev;
+	mbox->ops = &mtk_vcp_mbox_chan_ops;
+	mbox->txdone_irq = false;
+	mbox->txdone_poll = true;
+	mbox->of_xlate = mtk_vcp_mbox_xlate;
+	mbox->num_chans = 1;
+	mbox->chans = devm_kzalloc(dev, sizeof(*mbox->chans), GFP_KERNEL);
+	if (!mbox->chans)
+		return -ENOMEM;
+
+	priv->ipi_recv.msg = devm_kzalloc(dev, sizeof(u8) * MBOX_SLOT_MAX_SIZE,
+					  GFP_KERNEL);
+	if (!priv->ipi_recv.msg)
+		return -ENOMEM;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->cfg = of_device_get_match_data(dev);
+	if (!priv->cfg)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_threaded_irq(dev, irq, NULL,
+					mtk_vcp_mbox_irq_thread, IRQF_ONESHOT,
+					dev_name(dev), mbox->chans);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);
+
+	dev_dbg(dev, "MTK VCP mailbox initialized\n");
+
+	return devm_mbox_controller_register(dev, &priv->mbox);
+}
+
+static const struct mtk_vcp_mbox_cfg mt8196_cfg = {
+	.set_in		= 0x100,
+	.clr_out	= 0x10C,
+};
+
+static const struct of_device_id mtk_vcp_mbox_of_match[] = {
+	{ .compatible = "mediatek,mt8196-vcp-mbox", .data = &mt8196_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_vcp_mbox_of_match);
+
+static struct platform_driver mtk_vcp_mbox_driver = {
+	.probe		= mtk_vcp_mbox_probe,
+	.driver = {
+		.name	= "mtk_vcp_mbox",
+		.of_match_table = mtk_vcp_mbox_of_match,
+	},
+};
+module_platform_driver(mtk_vcp_mbox_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MTK VCP Mailbox Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mailbox/mtk-vcp-mailbox.h b/include/linux/mailbox/mtk-vcp-mailbox.h
new file mode 100644
index 000000000000..953499b7cfeb
--- /dev/null
+++ b/include/linux/mailbox/mtk-vcp-mailbox.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_MAILBOX_H__
+#define __MTK_VCP_MAILBOX_H__
+
+#define MBOX_SLOT_MAX_SIZE	0x100 /* mbox max slot size */
+#define MAX_SLOT_NUM	64
+
+/**
+ * struct mtk_ipi_info - channel table that belong to mtk_ipi_device
+ * @msg: The share buffer between IPC and mailbox driver
+ * @len: Message length
+ * @id: IPI number
+ * @recv_opt: Recv option,  0:receive ,1: response
+ * @index: The pin groups number of the mailbox channel
+ * @slot_ofs: Slot offset of the mailbox channel
+ * @irq_status: Indicate which pin groups triggered the interrupt
+ *
+ * It is used between IPC with mailbox driver.
+ */
+struct mtk_ipi_info {
+	void *msg;
+	u32 len;
+	u32 id;
+	u32 recv_opt;
+	u32 index;
+	u32 slot_ofs;
+	u32 irq_status;
+};
+
+#endif
-- 
2.45.2



From jjian.zhou at mediatek.com  Mon Mar 17 04:03:24 2025
From: jjian.zhou at mediatek.com (Jjian Zhou)
Date: Mon, 17 Mar 2025 19:03:24 +0800
Subject: [PATCH RFC v3 2/3] firmware: mediatek: Add vcp ipc protocol interface
In-Reply-To: <20250317110331.2776-1-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
Message-ID: <20250317110331.2776-3-jjian.zhou@mediatek.com>

Some of mediatek processors contain the Risc-V coprocessor.

The communication between Host CPU and vcp firmware is
taking place using a shared memory area for message passing.

VCP IPC protocol offers (send/recv) interfaces using
mediatek-mailbox APIs.

Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
---
 drivers/firmware/Kconfig                      |   9 +
 drivers/firmware/Makefile                     |   1 +
 drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
 include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
 4 files changed, 642 insertions(+)
 create mode 100644 drivers/firmware/mtk-vcp-ipc.c
 create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 37e43f287e78..98c4ff667836 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -179,6 +179,15 @@ config MTK_ADSP_IPC
 	  ADSP exists on some mtk processors.
 	  Client might use shared memory to exchange information with ADSP.
 
+config MTK_VCP_IPC
+	tristate "MTK VCP IPC Protocol driver"
+	depends on MTK_VCP_MBOX
+	help
+	  Say yes here to add support for the MediaTek VCP IPC
+	  between host AP (Linux) and the firmware running on VCP.
+	  VCP exists on some mtk processors.
+	  Client might use shared memory to exchange information with VCP.
+
 config SYSFB
 	bool
 	select BOOT_VESA_SUPPORT
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 91efcc868a05..2b9894e5169a 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
 obj-$(CONFIG_MTK_ADSP_IPC)	+= mtk-adsp-ipc.o
+obj-$(CONFIG_MTK_VCP_IPC)	+= mtk-vcp-ipc.o
 obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
 obj-$(CONFIG_FW_CFG_SYSFS)	+= qemu_fw_cfg.o
 obj-$(CONFIG_SYSFB)		+= sysfb.o
diff --git a/drivers/firmware/mtk-vcp-ipc.c b/drivers/firmware/mtk-vcp-ipc.c
new file mode 100644
index 000000000000..744937c56b67
--- /dev/null
+++ b/drivers/firmware/mtk-vcp-ipc.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/firmware/mediatek/mtk-vcp-ipc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/sched/clock.h>
+#include <linux/time64.h>
+#include <linux/vmalloc.h>
+
+/**
+ * struct mtk_ipi_chan_table - channel table that belong to mtk_ipi_device
+ * @mbox: the mbox channel number
+ * @mbox_pin_cb: callback function
+ * @holder: keep 1 if there are ipi waiters (to wait the reply)
+ * @ipi_record: timestamp of each ipi transmission stage
+ * @pin_buf: buffer point
+ * @prdata: private data
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @notify: completion notify process
+ * @send_ofs: message offset in the slots of a mbox
+ * @send_index: bit offset in the mbox
+ * @msg_zie: slot size of the ipi message
+ *
+ * All of these data should be initialized by mtk_ipi_device_register()
+ */
+struct mtk_ipi_chan_table {
+	u32 mbox;
+	mbox_pin_cb_t mbox_pin_cb;
+	atomic_t holder;
+	void *pin_buf;
+	void *prdata;
+	u32 recv_opt;
+	struct completion notify;
+	/* define a mutex for remote response */
+	struct mutex mutex_send;
+	u32 send_ofs;
+	u32 send_index;
+	u32 msg_size;
+};
+
+/**
+ * mbox information
+ *
+ * @mbdev: mbox device
+ * @mbox_id: mbox id
+ * @slot: how many slots that mbox used
+ * @opt: option for tx mode, 0:mbox, 1:share memory 2:queue
+ * @base: mbox base address
+ * @mbox_client: mbox client
+ * @mbox_chan: mbox channel
+ */
+struct mtk_mbox_info {
+	struct mtk_vcp_ipc *vcp_ipc;
+	u32 mbox_id;
+	u32 slot;
+	u32 opt;
+	/* lock of mbox */
+	spinlock_t mbox_lock;
+	struct mbox_client cl;
+	struct mbox_chan *ch;
+	struct mtk_ipi_info ipi_info;
+};
+
+static const char * const mbox_names[VCP_MBOX_NUM] = {
+	"mbox0", "mbox1", "mbox2", "mbox3", "mbox4"
+};
+
+/**
+ * mtk_vcp_ipc_recv - recv callback used by MTK VCP mailbox
+ *
+ * @c: mbox client
+ * @msg: message received
+ *
+ * Users of VCP IPC will need to provide handle_reply and handle_request
+ * callbacks.
+ */
+static void mtk_vcp_ipc_recv(struct mbox_client *c, void *msg)
+{
+	struct mtk_mbox_info *minfo = container_of(c, struct mtk_mbox_info, cl);
+	struct mtk_vcp_ipc *vcp_ipc = minfo->vcp_ipc;
+	struct mtk_ipi_info *ipi_info = msg;
+	struct mtk_ipi_device *ipidev = vcp_ipc->ipi_priv;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_mbox_recv_table *mbox_recv;
+	u32 id;
+
+	/* execute all receive pin handler */
+	for (id = 0; id < vcp_ipc->mbdev->recv_count; id++) {
+		mbox_recv = &vcp_ipc->mbdev->recv_table[id];
+		if (mbox_recv->mbox_id != minfo->mbox_id)
+			continue;
+
+		if (!(BIT(mbox_recv->pin_index) & ipi_info->irq_status))
+			continue;
+
+		table = &ipidev->table[mbox_recv->ipi_id];
+		if (!table->pin_buf) {
+			dev_err(vcp_ipc->dev, "IPI%d buf is null.\n",
+				mbox_recv->ipi_id);
+			continue;
+		}
+
+		memcpy(table->pin_buf,
+		       ipi_info->msg + mbox_recv->offset * MBOX_SLOT_SIZE,
+		       mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		if (!mbox_recv->recv_opt && table->mbox_pin_cb)
+			table->mbox_pin_cb(mbox_recv->ipi_id,
+					   table->prdata,
+					   table->pin_buf,
+					   mbox_recv->msg_size * MBOX_SLOT_SIZE);
+
+		/* notify task */
+		if (table->recv_opt == MBOX_RECV_MESSAGE ||
+		    atomic_read(&table->holder))
+			complete(&table->notify);
+	}
+}
+
+/*
+ * mtk_vcp_ipc_send - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 id, void *data, u32 len)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	mutex_unlock(&table[id].mutex_send);
+	if (ret < 0) {
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send);
+
+/*
+ * mtk_vcp_ipc_send_compl - send ipc command to MTK VCP
+ *
+ * @ipidev: VCP struct mtk_ipi_device handle
+ * @id: id of the feature IPI
+ * @data: message address
+ * @len: message length
+ * @timeout_ms:
+ *
+ * Return: Zero for success from mbox_send_message
+ *         negative value for error
+ */
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 id,
+			   void *data, u32 len, u32 timeout_ms)
+{
+	struct device *dev;
+	struct mtk_mbox_info *minfo;
+	struct mtk_ipi_chan_table *table;
+	struct mtk_vcp_ipc *vcp_ipc;
+	int ret;
+
+	if (!ipidev || !ipidev->ipi_inited || !data)
+		return IPI_UNAVAILABLE;
+	vcp_ipc = ipidev->vcp_ipc;
+	if (!vcp_ipc)
+		return IPI_UNAVAILABLE;
+
+	table = ipidev->table;
+	dev = ipidev->vcp_ipc->dev;
+	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
+	if (!minfo) {
+		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
+		return IPI_UNAVAILABLE;
+	}
+
+	if (len > table[id].msg_size)
+		return IPI_MSG_TOO_BIG;
+	else if (!len)
+		len = table[id].msg_size;
+
+	mutex_lock(&table[id].mutex_send);
+
+	minfo->ipi_info.msg = data;
+	minfo->ipi_info.len = len;
+	minfo->ipi_info.id = id;
+	minfo->ipi_info.index = table[id].send_index;
+	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
+
+	atomic_inc(&table[id].holder);
+
+	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
+	if (ret < 0) {
+		atomic_set(&table[id].holder, 0);
+		mutex_unlock(&table[id].mutex_send);
+		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
+		return IPI_MBOX_ERR;
+	}
+
+	/* wait for completion */
+	ret = wait_for_completion_timeout(&table[id].notify,
+					  msecs_to_jiffies(timeout_ms));
+	atomic_set(&table[id].holder, 0);
+	if (ret > 0)
+		ret = IPI_ACTION_DONE;
+
+	mutex_unlock(&table[id].mutex_send);
+
+	return ret;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_send_compl);
+
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+	if (!msg)
+		return IPI_NO_MSGBUF;
+
+	if (ipidev->table[id].pin_buf)
+		return IPI_ALREADY_USED;
+	ipidev->table[id].mbox_pin_cb = cb;
+	ipidev->table[id].pin_buf = msg;
+	ipidev->table[id].prdata = prdata;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_register);
+
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int id)
+{
+	if (!ipidev || !ipidev->ipi_inited)
+		return IPI_DEV_ILLEGAL;
+
+	/* Drop the ipi and reset the record */
+	complete(&ipidev->table[id].notify);
+
+	ipidev->table[id].mbox_pin_cb = NULL;
+	ipidev->table[id].pin_buf = NULL;
+	ipidev->table[id].prdata = NULL;
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_mbox_ipc_unregister);
+
+static void mtk_fill_in_entry(struct mtk_ipi_chan_table *entry, const u32 ipi_id,
+			      const struct mtk_mbox_table *mbdev)
+{
+	const struct mtk_mbox_send_table *mbox_send = mbdev->send_table;
+	u32 index;
+
+	for (index = 0; index < mbdev->send_count; index++) {
+		if (ipi_id != mbox_send[index].ipi_id)
+			continue;
+
+		entry->send_ofs = mbox_send[index].offset;
+		entry->send_index = mbox_send[index].pin_index;
+		entry->msg_size = mbox_send[index].msg_size;
+		entry->mbox = mbox_send[index].mbox_id;
+		return;
+	}
+
+	entry->mbox = -ENOENT;
+}
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count, struct mtk_vcp_ipc *vcp_ipc)
+{
+	struct mtk_ipi_chan_table *ipi_chan_table;
+	struct mtk_mbox_table *mbdev;
+	u32 index;
+
+	if (!vcp_ipc || !ipidev)
+		return -EINVAL;
+
+	ipi_chan_table = kcalloc(ipi_chan_count,
+				 sizeof(struct mtk_ipi_chan_table), GFP_KERNEL);
+	if (!ipi_chan_table)
+		return -ENOMEM;
+
+	mbdev = vcp_ipc->mbdev;
+	vcp_ipc->ipi_priv = (void *)ipidev;
+	ipidev->table = ipi_chan_table;
+	ipidev->vcp_ipc = vcp_ipc;
+
+	for (index = 0; index < ipi_chan_count; index++) {
+		atomic_set(&ipi_chan_table[index].holder, 0);
+		mutex_init(&ipi_chan_table[index].mutex_send);
+		init_completion(&ipi_chan_table[index].notify);
+		mtk_fill_in_entry(&ipi_chan_table[index], index, mbdev);
+	}
+
+	ipidev->ipi_inited = 1;
+
+	dev_dbg(vcp_ipc->dev, "%s (with %d IPI) has registered.\n",
+		ipidev->name, ipi_chan_count);
+
+	return IPI_ACTION_DONE;
+}
+EXPORT_SYMBOL(mtk_vcp_ipc_device_register);
+
+static int setup_mbox_table(struct mtk_mbox_table *mbdev, u32 mbox)
+{
+	struct mtk_mbox_send_table *mbox_send = &mbdev->send_table[0];
+	struct mtk_mbox_recv_table *mbox_recv = &mbdev->recv_table[0];
+	u32 i, last_ofs = 0, last_idx = 0, last_slot = 0, last_sz = 0;
+
+	for (i = 0; i < mbdev->send_count; i++) {
+		if (mbox == mbox_send[i].mbox_id) {
+			mbox_send[i].offset = last_ofs + last_slot;
+			mbox_send[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_send[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_send[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_send[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	for (i = 0; i < mbdev->recv_count; i++) {
+		if (mbox == mbox_recv[i].mbox_id) {
+			mbox_recv[i].offset = last_ofs + last_slot;
+			mbox_recv[i].pin_index = last_idx + last_sz;
+			last_idx = mbox_recv[i].pin_index;
+			last_sz = DIV_ROUND_UP(mbox_recv[i].msg_size, MBOX_SLOT_ALIGN);
+			last_ofs = last_sz * MBOX_SLOT_ALIGN;
+			last_slot = last_idx * MBOX_SLOT_ALIGN;
+		} else if (mbox < mbox_recv[i].mbox_id) {
+			/* no need to search the rest id */
+			break;
+		}
+	}
+
+	if (last_idx > MBOX_MAX_PIN || (last_ofs + last_slot) > MAX_SLOT_NUM)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mtk_vcp_ipc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mbox_client *cl;
+	struct mtk_mbox_info *minfo;
+	int ret;
+	u32 mbox, i;
+	struct mtk_mbox_table *mbox_data = dev_get_platdata(dev);
+
+	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
+	vcp_ipc = devm_kzalloc(dev, sizeof(*vcp_ipc), GFP_KERNEL);
+	if (!vcp_ipc)
+		return -ENOMEM;
+
+	if (!mbox_data) {
+		dev_err(dev, "No platform data available\n");
+		return -EINVAL;
+	}
+	vcp_ipc->mbdev = mbox_data;
+
+	/* alloc and init mmup_mbox_info */
+	vcp_ipc->info_table = vzalloc(sizeof(*vcp_ipc->info_table) * VCP_MBOX_NUM);
+	if (!vcp_ipc->info_table)
+		return -ENOMEM;
+
+	/* create mbox dev */
+	for (mbox = 0; mbox < VCP_MBOX_NUM; mbox++) {
+		minfo = &vcp_ipc->info_table[mbox];
+		minfo->mbox_id = mbox;
+		minfo->vcp_ipc = vcp_ipc;
+		spin_lock_init(&minfo->mbox_lock);
+
+		ret = setup_mbox_table(vcp_ipc->mbdev, mbox);
+		if (ret)
+			return ret;
+
+		cl = &minfo->cl;
+		cl->dev = &pdev->dev;
+		cl->tx_block = false;
+		cl->knows_txdone = false;
+		cl->tx_prepare = NULL;
+		cl->rx_callback = mtk_vcp_ipc_recv;
+		minfo->ch = mbox_request_channel_byname(cl, mbox_names[mbox]);
+		if (IS_ERR(minfo->ch)) {
+			ret = PTR_ERR(minfo->ch);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to request mbox channel %s ret %d\n",
+					mbox_names[mbox], ret);
+
+			for (i = 0; i < mbox; i++) {
+				minfo = &vcp_ipc->info_table[i];
+				mbox_free_channel(minfo->ch);
+			}
+
+			vfree(vcp_ipc->info_table);
+			return ret;
+		}
+	}
+
+	vcp_ipc->dev = dev;
+	dev_set_drvdata(dev, vcp_ipc);
+	dev_dbg(dev, "MTK VCP IPC initialized\n");
+
+	return 0;
+}
+
+static void mtk_vcp_ipc_remove(struct platform_device *pdev)
+{
+	struct mtk_vcp_ipc *vcp_ipc = dev_get_drvdata(&pdev->dev);
+	struct mtk_mbox_info *minfo;
+	int i;
+
+	for (i = 0; i < VCP_MBOX_NUM; i++) {
+		minfo = &vcp_ipc->info_table[i];
+		mbox_free_channel(minfo->ch);
+	}
+
+	vfree(vcp_ipc->info_table);
+}
+
+static struct platform_driver mtk_vcp_ipc_driver = {
+	.probe = mtk_vcp_ipc_probe,
+	.remove = mtk_vcp_ipc_remove,
+	.driver = {
+		.name = "mtk-vcp-ipc",
+	},
+};
+builtin_platform_driver(mtk_vcp_ipc_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek VCP IPC Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/mediatek/mtk-vcp-ipc.h b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
new file mode 100644
index 000000000000..dc34b0ba9dd8
--- /dev/null
+++ b/include/linux/firmware/mediatek/mtk-vcp-ipc.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_IPC_H__
+#define __MTK_VCP_IPC_H__
+
+#include <linux/completion.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* IPI result definition */
+#define IPI_ACTION_DONE	  0
+#define IPI_DEV_ILLEGAL	 -1 /* ipi device is not initialized */
+#define IPI_ALREADY_USED	 -2 /* the ipi has be registered */
+#define IPI_UNAVAILABLE	 -3 /* the ipi can't be found */
+#define IPI_NO_MSGBUF		 -4 /* receiver doesn't have message buffer */
+#define IPI_MSG_TOO_BIG		 -5 /* message length is larger than defined */
+#define IPI_MBOX_ERR		-99 /* some error from rpmsg layer */
+
+/* mbox recv action definition */
+enum mtk_ipi_recv_opt {
+	MBOX_RECV_MESSAGE  = 0,
+	MBOX_RECV_ACK      = 1,
+};
+
+/* mbox table item number definition */
+#define send_item_num	3
+#define recv_item_num	4
+#define VCP_MBOX_NUM	5
+
+/* mbox slot size definition: 1 slot for 4 bytes */
+#define MBOX_SLOT_SIZE	0x4
+#define MBOX_MAX_PIN	32
+#define VCP_MBOX_NUM	5
+#define MBOX_SLOT_ALIGN	2
+
+struct mtk_vcp_ipc;
+struct mtk_ipi_chan_table;
+
+typedef int (*mbox_pin_cb_t)(u32 ipi_id, void *prdata, void *data, u32 len);
+
+/**
+ * mbox pin structure, this is for send definition,
+ * @offset: message offset in the slots of a mbox
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_send_table {
+	u32 offset;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * mbox pin structure, this is for receive definition,
+ * @offset: message offset in the slots of a mbox
+ * @recv_opt: recv option,  0:receive ,1: response
+ * @msg_size: message used slots in the mbox, 4 bytes alignment
+ * @pin_index: bit offset in the mbox
+ * @ipi_id: ipi enum number
+ * @mbox_id: mbox number id
+ */
+struct mtk_mbox_recv_table {
+	u32 offset;
+	u32 recv_opt;
+	u32 msg_size;
+	u32 pin_index;
+	u32 ipi_id;
+	u32 mbox_id;
+};
+
+/**
+ * struct mtk_ipi_device - device for represent the tinysys using mtk ipi
+ * @name: name of tinysys device
+ * @id: device id (used to match between rpmsg drivers and devices)
+ * @vcp_ipc: vcp ipc structure for tinysys device
+ * @table: channel table with endpoint & channel_info & mbox_pin info
+ * @prdata: private data for the callback use
+ * @ipi_inited: set when vcp_ipi_device_register() done
+ */
+struct mtk_ipi_device  {
+	const char *name;
+	struct mtk_vcp_ipc *vcp_ipc;
+	struct mtk_ipi_chan_table *table;
+	void *prdata;
+	int ipi_inited;
+};
+
+/**
+ * The mtk_mbox_table is a structure used to record the send
+ * table and recv table. The send table is used to record
+ * the feature ID and size of the sent data. The recv table
+ * is used to record the feature ID and size of the received
+ * data, and whether a callback needs to be invoked.
+ *
+ * Following are platform specific interfacer
+ * @recv_table: structure mtk_mbox_recv_table
+ * @send_table: structure mtk_mbox_send_table
+ * @recv_count: receive feature number in this channel
+ * @send_count: send feature number in this channel
+ */
+struct mtk_mbox_table {
+	struct mtk_mbox_recv_table recv_table[32];
+	struct mtk_mbox_send_table send_table[32];
+	u32 recv_count;
+	u32 send_count;
+};
+
+/**
+ * Mbox is a dedicate hardware of a tinysys consists of:
+ * 1) a share memory tightly coupled to the tinysys
+ * 2) several IRQs
+ *
+ * Following are platform specific interface
+ * @dev: vcp device
+ * @name: identity of the device
+ * @info_table: mbox info structure
+ * @ipi_priv: private data for synchronization layer
+ * @mbox_id: mbox number
+ * @mbdev: mtk_mbox_table structure
+ */
+struct mtk_vcp_ipc {
+	struct device *dev;
+	const char *name;
+	struct mtk_mbox_info *info_table;
+	void *ipi_priv;
+	void *mbox_id;
+	struct mtk_mbox_table *mbdev;
+};
+
+int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
+				u32 ipi_chan_count,
+				struct mtk_vcp_ipc *vcp_ipc);
+int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 ipi_id,
+		     void *data, u32 len);
+int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 ipi_id,
+			   void *data, u32 len, u32 timeout_ms);
+int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int ipi_id,
+			      mbox_pin_cb_t cb, void *prdata, void *msg);
+int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int ipi_id);
+
+#endif
-- 
2.45.2



From krzk at kernel.org  Mon Mar 17 04:08:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 12:08:48 +0100
Subject: [PATCH v2] ARM: dts: imx51-digi-connectcore-som: Fix MMA7455
 compatible
In-Reply-To: <20250315121054.1836483-1-festevam@gmail.com>
References: <20250315121054.1836483-1-festevam@gmail.com>
Message-ID: <e4e6eb2d-bac0-4e56-8926-00a3f51412dd@kernel.org>

On 15/03/2025 13:10, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> According to fsl,mma7455.yaml, the correct compatible string is
> "fsl,mma7455".

Not sure. This is a different device and you rename the compatible to be
pretend to be something else? Your commit msg should provide rather an
argument why binding is correct and not the DTS.

> 
> Change it accordingly to fix the following dt-schema warning:

Don't grow the simple commit msgs unnecessarily. This can easily part of
previous paragraph to save you two lines.

> 
> failed to match any schema with compatible: ['fsl,mma7455l']


Best regards,
Krzysztof


From linux at armlinux.org.uk  Mon Mar 17 04:09:14 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Mon, 17 Mar 2025 11:09:14 +0000
Subject: [net-next 4/4] net: ftgmac100: add RGMII delay for AST2600
In-Reply-To: <20250317095229.6f8754dd@fedora.home>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
 <20250317095229.6f8754dd@fedora.home>
Message-ID: <Z9gC2vz2w5dfZsum@shell.armlinux.org.uk>

On Mon, Mar 17, 2025 at 09:53:33AM +0100, Maxime Chevallier wrote:
> So this goes completely against the naming of the property. It has the
> -ps suffix, so you would expect to have picoseconds values passed, and
> not an arbiraty index.
> 
> Take a look at other drivers, you should accept picseconds values from
> these properties, then compute the relevant index in the driver. That
> index should be something internal to your driver.
> 
> An example here :
> 
> https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c#L51

Another example would be drivers/net/phy/adin.c::adin_get_reg_value()
and associated functions - these lookup a DT property and then look
that up in a table to convert it to a register value.

I suspect that's something which could become generic, as I suspect
most hardware isn't going to accept a picosecond value, but be a
choice of N different options.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From james.clark at linaro.org  Mon Mar 17 04:11:00 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 11:11:00 +0000
Subject: [PATCH v2 3/4] arm64/sysreg: Sort sysreg by encoding
In-Reply-To: <20250313215840.GC8101@willie-the-truck>
References: <20250115162600.2153226-1-james.clark@linaro.org>
 <20250115162600.2153226-4-james.clark@linaro.org>
 <20250313215840.GC8101@willie-the-truck>
Message-ID: <4cfcb9d8-3187-4ed7-8951-d54d781b4bd9@linaro.org>



On 13/03/2025 9:58 pm, Will Deacon wrote:
> On Wed, Jan 15, 2025 at 04:25:57PM +0000, James Clark wrote:
>> It's mostly been sorted by sysreg encoding, but not 100%. Sort it so
>> new entries can be added without wondering where to put them.
>>
>> The following python script was used to sort, keeping the top level
>> SysregFields and comments next to their current Sysreg entries by
>> splitting on "EndSysreg":
>>
>>    # cat arch/arm64/tools/sysreg | python3 sort.py > sorted-sysreg
>>    import sys, re
>>    def key(block):
>>            reg = r"\w+\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)"
>>            match = re.search(reg, block)
>>            sort_val = ''.join(f"{int(n):02d}" for n in match.groups())
>>            return (sort_val, block)
>>    sysreg = sys.stdin.read().split("\nEndSysreg\n")[:-1]
>>    sysreg = sorted(sysreg, key=key)
>>    print("\nEndSysreg\n".join(sysreg) + "\nEndSysreg")
>>
>> Tested by diffing sorted outputs:
>>
>>    $ diff <(sort arch/arm64/include/generated/asm/sysreg-defs.h)  \
>>           <(sort before-sysreg-defs.h) -s
>>
>>    Files /dev/fd/63 and /dev/fd/62 are identical
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>   arch/arm64/tools/sysreg | 1006 +++++++++++++++++++--------------------
>>   1 file changed, 503 insertions(+), 503 deletions(-)
> 
> This looks like unnecessary pain for backporting...
> 
> What do we gain from sorting this?
> 
> Will

It's from the discussion here [1]. But yeah backporting wasn't mentioned 
as a possible issue, it's something to think about.

The summary is:

  * I added one out of order because it wasn't obvious from the unsorted
    file that they were supposed to be in order
  * To avoid more of the same review comments and save time I wanted to
    put a "keep this file sorted" comment
  * But the comment wasn't ok because the file wasn't already sorted, so
    we ended up with sorting it

To be fair adding a "keep it sorted" comment is a bit awkward because 
there are sometimes multiple places you can insert something if it's not 
already fully sorted.

[1]: 
https://lore.kernel.org/all/996c7843-7f51-49a0-9122-e688e37f9902 at sirena.org.uk/



From krzk at kernel.org  Mon Mar 17 04:23:09 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 12:23:09 +0100
Subject: [PATCH v2 2/2] ARM: dts: apalis/colibri-imx6: Add support for
 v1.2
In-Reply-To: <20250307101758.27943-3-ernest.vanhoecke@toradex.com>
References: <20250307101758.27943-1-ernest.vanhoecke@toradex.com>
 <20250307101758.27943-3-ernest.vanhoecke@toradex.com>
Message-ID: <00667202-73e4-48ee-aa90-dee8c0dd5d43@kernel.org>

On 07/03/2025 11:17, ernestvanhoecke at gmail.com wrote:
> diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
> new file mode 100644
> index 000000000000..93fd0af53a3c
> --- /dev/null
> +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-v1.2-eval-v3.dts
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
> +/* Copyright (c) 2025 Toradex */
> +
> +/dts-v1/;
> +
> +#include "imx6dl-colibri-eval-v3.dts"
> +#include "imx6qdl-colibri-v1.2.dtsi"
> +
> +/ {
> +	model = "Toradex Colibri iMX6DL/S V1.2+ on Colibri Evaluation Board V3";
> +};


If devices are the same, you do not need new DTS. There is no benefit in
creating DTS per every revision.

Best regards,
Krzysztof


From yangyicong at huawei.com  Mon Mar 17 04:29:19 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Mon, 17 Mar 2025 19:29:19 +0800
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <2bd3aa0a-d700-46bf-81d1-a5fb0364d1e0@arm.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-3-yangyicong@huawei.com>
 <2bd3aa0a-d700-46bf-81d1-a5fb0364d1e0@arm.com>
Message-ID: <c88e5b78-37b7-3023-7842-56a93fe119d2@huawei.com>

On 2025/3/17 17:56, Dietmar Eggemann wrote:
> On 11/03/2025 08:51, Yicong Yang wrote:
>> From: Yicong Yang <yangyicong at hisilicon.com>
>>
>> On building the topology from the devicetree, we've already gotten the
>> SMT thread number of each core. Update the largest SMT thread number
>> and enable the SMT control by the end of topology parsing.
>>
>> The framework's SMT control provides two interface to the users [1]
>> through /sys/devices/system/cpu/smt/control:
>> 1) enable SMT by writing "on" and disable by "off"
>> 2) enable SMT by writing max_thread_number or disable by writing 1
>>
>> Both method support to completely disable/enable the SMT cores so both
>> work correctly for symmetric SMT platform and asymmetric platform with
>> non-SMT and one type SMT cores like:
>> core A: 1 thread
>> core B: X (X!=1) threads
>>
>> Note that for a theoretically possible multiple SMT-X (X>1) core
>> platform the SMT control is also supported as expected but only
>> by writing the "on/off" method.
> 
> Here we still have a little misunderstanding. IMHO, even on such a
> system 2) would work too.
> 


yes but only by writing the max_thread_number. e.g. a system with SMT number
of 1 (no SMT core), X, Y (Y > X), 1 works same as "off" and Y works same as
"on", as you shown below. write X will be blocked by the CPU framework:
estuary:/sys/devices/system/cpu/smt$ cat control
off
# emulated CPU 0-7,16-22 as SMT-2, CPU 8-11,24-27 as SMT-4
estuary:/sys/devices/system/cpu/smt$ cat ../online
0,2,4,6,8,12-16,18,20,22,24,28-31
estuary:/sys/devices/system/cpu/smt$ echo 2 > control
bash: echo: write error: Invalid argument
estuary:/sys/devices/system/cpu/smt$ echo 4 > control
estuary:/sys/devices/system/cpu/smt$ cat ../online
0-31

so method 1) will always match the expectation to fully enable/disable the
SMT on all cores, that's I mean here. But 2) won't work if user expected
to write 2 to enable SMT-2 (I think it'll will work if we support
CONFIG_SMT_NUM_THREADS_DYNAMIC on arm64 later).

Thanks.

> My qemu example with SMT-1, SMT-2 and SMT-4 in one system from your v11:
> 
> # cat /proc/schedstat | grep -v "^v\|^t" | awk '{print $1" "$2" "$3}'
> cpu0 0 0
> domain0 MC ff
> cpu1 0 0
> domain0 MC ff
> cpu2 0 0
> domain0 SMT 0c
> domain1 MC ff
> cpu3 0 0
> domain0 SMT 0c
> domain1 MC ff
> cpu4 0 0
> domain0 SMT f0
> domain1 MC ff
> cpu5 0 0
> domain0 SMT f0
> domain1 MC ff
> cpu6 0 0
> domain0 SMT f0
> domain1 MC ff
> cpu7 0 0
> domain0 SMT f0
> domain1 MC ff
> 
> # cat /proc/cpuinfo | grep ^processor
> processor	: 0
> processor	: 1
> processor	: 2
> processor	: 3
> processor	: 4
> processor	: 5
> processor	: 6
> processor	: 7
> 
> # echo 1 > /sys/devices/system/cpu/smt/control
> 
> # cat /proc/cpuinfo | grep ^processor
> processor	: 0
> processor	: 1
> processor	: 2
> processor	: 4
> 
> # echo 4 > /sys/devices/system/cpu/smt/control
> 
> # cat /proc/cpuinfo | grep ^processor
> processor	: 0
> processor	: 1
> processor	: 2
> processor	: 3
> processor	: 4
> processor	: 5
> processor	: 6
> processor	: 7
> 
> Whats doesn't work is to echoing a '2' but that's not
> 'max_thread_number' of the system.
> 
> [...]
> 
> .
> 


From mark.rutland at arm.com  Mon Mar 17 04:29:30 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 17 Mar 2025 11:29:30 +0000
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and
 use API for detecting hypervisor presence
In-Reply-To: <20250315001931.631210-2-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-2-romank@linux.microsoft.com>
Message-ID: <Z9gHmkNOsd29viHj@J2N7QTR9R3.cambridge.arm.com>

On Fri, Mar 14, 2025 at 05:19:21PM -0700, Roman Kisel wrote:
> The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is
> private, and it follows the SMCCC specification. Other existing and
> emerging hypervisor guest implementations can and should use that
> standard approach as well.
> 
> Factor out a common infrastructure that the guests can use, update KVM
> to employ the new API. The central notion of the SMCCC method is the
> UUID of the hypervisor, and the API follows that.
> 
> No functional changes. Validated with a KVM/arm64 guest.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Acked-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  arch/arm64/kvm/hypercalls.c        |  5 +--
>  drivers/firmware/smccc/kvm_guest.c | 10 ++----
>  drivers/firmware/smccc/smccc.c     | 19 +++++++++++
>  include/linux/arm-smccc.h          | 55 +++++++++++++++++++++++++++---
>  4 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
> index 27ce4cb44904..92b9bc1ea8e8 100644
> --- a/arch/arm64/kvm/hypercalls.c
> +++ b/arch/arm64/kvm/hypercalls.c
> @@ -353,10 +353,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
>  			val[0] = gpa;
>  		break;
>  	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
> -		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
> -		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
> -		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
> -		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
> +		UUID_TO_SMCCC_RES(ARM_SMCCC_VENDOR_HYP_UID_KVM, val);
>  		break;
>  	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
>  		val[0] = smccc_feat->vendor_hyp_bmap;
> diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
> index f3319be20b36..b5084b309ea0 100644
> --- a/drivers/firmware/smccc/kvm_guest.c
> +++ b/drivers/firmware/smccc/kvm_guest.c
> @@ -14,17 +14,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
>  
>  void __init kvm_init_hyp_services(void)
>  {
> +	uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
>  	struct arm_smccc_res res;
>  	u32 val[4];
>  
> -	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> -		return;
> -
> -	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> -	if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
> -	    res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
> -	    res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
> -	    res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
> +	if (!arm_smccc_hyp_present(&kvm_uuid))
>  		return;
>  
>  	memset(&res, 0, sizeof(res));
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index a74600d9f2d7..7399f27d58e5 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
> @@ -67,6 +67,25 @@ s32 arm_smccc_get_soc_id_revision(void)
>  }
>  EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
>  
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> +{
> +	struct arm_smccc_res res = {};
> +
> +	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> +		return false;
> +	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> +	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> +		return false;
> +
> +	return ({
> +		const uuid_t uuid = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
> +		const bool present = uuid_equal(&uuid, hyp_uuid);
> +
> +		present;
> +	});
> +}

This use of a statement expression is bizarre, and the function would be
clearer without it, e.g.

| bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
| {
| 	struct arm_smccc_res res = {};
| 	uuid_t uuid;
| 
| 	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
| 		return false;
| 
| 	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
| 	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
| 		return false;
| 	
| 	uuid_t = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
| 	return uuid_equal(&uuid, hyp_uuid);
| }

As noted below, I'd prefer if this were renamed to something like
arm_smccc_hypervisor_has_uuid(), to more clearly indicate what is being
checked.

[...]

> +/**
> + * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> + *
> + * Returns `true` if the hypervisor advertises its presence via SMCCC.
> + *
> + * When the function returns `false`, the caller shall not assume that
> + * there is no hypervisor running. Instead, the caller must fall back to
> + * other approaches if any are available.
> + */
> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);

I'd prefer if this were:

| /*
|  * Returns whether a specific hypervisor UUID is advertised for the
|  * Vendor Specific Hypervisor Service range.
|  */
| bool arm_smccc_hypervisor_has_uuid(const uuid_t *uuid);

> +#define SMCCC_RES_TO_UUID(r0, r1, r2, r3) \
> +	UUID_INIT( \
> +		cpu_to_le32(lower_32_bits(r0)), \
> +		cpu_to_le32(lower_32_bits(r1)) & 0xffff, \
> +		cpu_to_le32(lower_32_bits(r1)) >> 16, \
> +		cpu_to_le32(lower_32_bits(r2)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r2)) >> 24) & 0xff, \
> +		cpu_to_le32(lower_32_bits(r3)) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 8) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 16) & 0xff, \
> +		(cpu_to_le32(lower_32_bits(r3)) >> 24) & 0xff \
> +	)

I think this'd be clearer if we did something similar to what we did for
the SMCCC SOC_ID name:

  https://lore.kernel.org/linux-arm-kernel/20250219005932.3466-1-paul at os.amperecomputing.com/

... and pack/unpack the bytes explicitly, e.g.

| static inline uuid smccc_res_to_uuid(u32 r0, u32, r1, u32 r2, u32 r3)
| {
| 	uuid_t uuid = {
| 		.b = {
| 			[0]  = (r0 >> 0)  & 0xff,
| 			[1]  = (r0 >> 8)  & 0xff,
| 			[2]  = (r0 >> 16) & 0xff,
| 			[3]  = (r0 >> 24) & 0xff,
| 
| 			[4]  = (r1 >> 0)  & 0xff,
| 			[5]  = (r1 >> 8)  & 0xff,
| 			[6]  = (r1 >> 16) & 0xff,
| 			[7]  = (r1 >> 24) & 0xff,
| 
| 			[8]  = (r2 >> 0)  & 0xff,
| 			[9]  = (r2 >> 8)  & 0xff,
| 			[10] = (r2 >> 16) & 0xff,
| 			[11] = (r2 >> 24) & 0xff,
| 
| 			[12] = (r3 >> 0)  & 0xff,
| 			[13] = (r3 >> 8)  & 0xff,
| 			[14] = (r3 >> 16) & 0xff,
| 			[15] = (r3 >> 24) & 0xff,
| 		},
| 	};
| 
| 	return uuid;
| }

... which is a bit more verbose, but clearly aligns with what the SMCCC
spec says w.r.t. packing/unpacking, and should avoid warnings about
endianness conversions.

> +
> +#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
> +		const uuid_t uuid = uuid_init; \
> +		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
> +						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24)); \
> +		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
> +						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24)); \
> +		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
> +						((uuid.b[10]) << 16) | ((uuid.b[11]) << 24)); \
> +		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
> +						((uuid.b[14]) << 16) | ((uuid.b[15]) << 24)); \
> +	} while (0)
> +
> +#endif /* !__ASSEMBLER__ */

IMO it'd be clearer to initialise a uuid_t beforehand, and then allow
the helper to unpack the bytes, e.g.

static inline u32 smccc_uuid_to_reg(const uuid_t uuid, int reg)
{
	u32 val = 0;

	val |= (u32)(uuid.b[4 * reg + 0] << 0)
	val |= (u32)(uuid.b[4 * reg + 1] << 8)
	val |= (u32)(uuid.b[4 * reg + 2] << 16)
	val |= (u32)(uuid.b[4 * reg + 3] << 24)

	return val:
}

#define UUID_TO_SMCCC_RES(uuid, regs)		\
do {						\
	(regs)[0] = smccc_uuid_to_reg(uuid, 0); \
	(regs)[1] = smccc_uuid_to_reg(uuid, 1); \
	(regs)[2] = smccc_uuid_to_reg(uuid, 2); \
	(regs)[3] = smccc_uuid_to_reg(uuid, 3); \
} while (0)

... though arguably at that point you can get rid of the
UUID_TO_SMCCC_RES() macro and just expand that directly at the callsite.

Mark.


From mark.rutland at arm.com  Mon Mar 17 04:37:57 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 17 Mar 2025 11:37:57 +0000
Subject: [PATCH hyperv-next v6 02/11] arm64: hyperv: Use SMCCC to detect
 hypervisor presence
In-Reply-To: <20250315001931.631210-3-romank@linux.microsoft.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-3-romank@linux.microsoft.com>
Message-ID: <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>

On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote:
> The arm64 Hyper-V startup path relies on ACPI to detect
> running under a Hyper-V compatible hypervisor. That
> doesn't work on non-ACPI systems.
> 
> Hoist the ACPI detection logic into a separate function. Then
> use the vendor-specific hypervisor service call (implemented
> recently in Hyper-V) via SMCCC in the non-ACPI case.
> 
> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> ---
>  arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++-----
>  1 file changed, 38 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index 2265ea5ce5ad..c5b03d3af7c5 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
>  	return 0;
>  }
>  
> +static bool __init hyperv_detect_via_acpi(void)
> +{
> +	if (acpi_disabled)
> +		return false;
> +#if IS_ENABLED(CONFIG_ACPI)
> +	/*
> +	 * Hypervisor ID is only available in ACPI v6+, and the
> +	 * structure layout was extended in v6 to accommodate that
> +	 * new field.
> +	 *
> +	 * At the very minimum, this check makes sure not to read
> +	 * past the FADT structure.
> +	 *
> +	 * It is also needed to catch running in some unknown
> +	 * non-Hyper-V environment that has ACPI 5.x or less.
> +	 * In such a case, it can't be Hyper-V.
> +	 */
> +	if (acpi_gbl_FADT.header.revision < 6)
> +		return false;
> +	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
> +#else
> +	return false;
> +#endif
> +}
> +

The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use
prior to the ifdeffery looks misplaced.

Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED().
Otherwise, use a stub, e.g.

| #ifdef CONFIG_ACPI
| static bool __init hyperv_detect_via_acpi(void)
| {
| 	if (acpi_disabled)
| 		return false;
| 	
| 	if (acpi_gbl_FADT.header.revision < 6)
| 		return false;
| 	
| 	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
| }
| #else
| static inline bool hyperv_detect_via_acpi(void) { return false; }
| #endif

Mark.

> +static bool __init hyperv_detect_via_smccc(void)
> +{
> +	uuid_t hyperv_uuid = UUID_INIT(
> +		0x4d32ba58, 0x4764, 0xcd24,
> +		0x75, 0x6c, 0xef, 0x8e,
> +		0x24, 0x70, 0x59, 0x16);
> +
> +	return arm_smccc_hyp_present(&hyperv_uuid);
> +}
> +
>  static int __init hyperv_init(void)
>  {
>  	struct hv_get_vp_registers_output	result;
> @@ -35,13 +70,11 @@ static int __init hyperv_init(void)
>  
>  	/*
>  	 * Allow for a kernel built with CONFIG_HYPERV to be running in
> -	 * a non-Hyper-V environment, including on DT instead of ACPI.
> +	 * a non-Hyper-V environment.
> +	 *
>  	 * In such cases, do nothing and return success.
>  	 */
> -	if (acpi_disabled)
> -		return 0;
> -
> -	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
> +	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
>  		return 0;
>  
>  	/* Setup the guest ID */
> -- 
> 2.43.0
> 


From james.clark at linaro.org  Mon Mar 17 04:36:40 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 11:36:40 +0000
Subject: [PATCH 2/7] coresight: Convert disclaim functions to take a
 struct cs_access
In-Reply-To: <20250313145456.GR9682@e132581.arm.com>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-3-james.clark@linaro.org>
 <20250313145456.GR9682@e132581.arm.com>
Message-ID: <c6a86373-64be-4101-a08a-74aa302bf64c@linaro.org>



On 13/03/2025 2:54 pm, Leo Yan wrote:
> On Tue, Feb 11, 2025 at 10:39:38AM +0000, James Clark wrote:
> 
> [...]
> 
>>   static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>>   {
>> -       return coresight_read_claim_tags(csdev) != 0;
>> +       return coresight_read_claim_tags(&csdev->access) != 0;
>>   }
> 
> Likewise other claim functions, can coresight_is_claimed_any() change its
> argument type from struct coresight_device to struct csdev_access?
> 
> Thanks,
> Leo

I only wanted to change the ones that I had to. I think we should 
prioritize passing csdev as much as possible in the coresight framework 
to make everything consistent. Otherwise it's extra churn for no 
benefit, and if we need something from csdev here in the future we'll 
have to change this one back again.



From wei.fang at nxp.com  Mon Mar 17 04:39:49 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Mon, 17 Mar 2025 11:39:49 +0000
Subject: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver
 to support NTMP
In-Reply-To: <20250317100037.7o7r7gch433s5lq4@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-2-wei.fang@nxp.com>
 <20250313163526.pqwp2wsfvio7avs6@skbuf>
 <PAXPR04MB8510327277CFEAC750FE49F888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250314123715.fivq2cbczd4khxkk@skbuf>
 <PAXPR04MB851027E5F830F08F3395083888D22@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250317092808.jel2au3cgfwblaxk@skbuf>
 <PAXPR04MB85102185D0A4C30F0688AA5488DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250317100037.7o7r7gch433s5lq4@skbuf>
Message-ID: <PAXPR04MB8510C930C602101C4649791A88DF2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Mon, Mar 17, 2025 at 11:55:26AM +0200, Wei Fang wrote:
> > Actually I did this is the original version, I mean in downstream kernel 6.6
> > tree. I add a "ntmp_mfe" in ntmp.h like below
> >
> > struct ntmp_mfe {
> > 	u8 mac[ETH_ALEN];
> > 	u16 si_bitmap;
> > };
> >
> > And the conversion was done by the NTMP driver. But then I found that this
> was
> > very troublesome. We get data from kernel "struct A,B,C", then the enetc
> driver
> > converts them to "struct D", and finally the ntmp driver converts it to "struct
> E".
> > So I thought why don't we convert "struct A,B,C" to "struct E" from the
> beginning?
> > After all, these data structures are only used by enetc and netc switch drivers,
> so
> > in kernel 6.12, I changed it to the current way.
> 
> I understand. With pack_fields(), "struct E" (the packed representation
> of "struct D") doesn't explicitly exist, just an abstract type
> representing the u8 *buffer, and the struct packed_field_u8 array[]
> which is hidden inside the NTMP layer.

Yes, "struct E" will not exist, but we need to pack every member in
"struct D" to convert them to the hardware structure, so there are
still two conversions ("struct A,B,C" -> "struct "D" --> hardware
structure).



From jonas at kwiboo.se  Mon Mar 17 04:47:52 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 17 Mar 2025 12:47:52 +0100
Subject: [PATCH v3 3/6] thermal: rockchip: Support RK3576 SoC in the
 thermal driver
In-Reply-To: <4994384.31r3eYUQgx@workhorse>
References: <20250228-rk3576-tsadc-upstream-v3-0-4bfbb3b699b9@collabora.com>
 <20250228-rk3576-tsadc-upstream-v3-3-4bfbb3b699b9@collabora.com>
 <6c355664-50dd-4efd-94b7-9d93c02d3e80@kwiboo.se>
 <4994384.31r3eYUQgx@workhorse>
Message-ID: <ba057235-85d4-4635-87ad-741e369904f3@kwiboo.se>

Hi Nicolas,

On 2025-03-17 09:28, Nicolas Frattaroli wrote:
> On Saturday, 15 March 2025 09:20:07 Central European Standard Time Jonas 
> Karlman wrote:
>> Hi Nicolas,
> 
> Hi Jonas,
> 
>>
>> On 2025-02-28 21:06, Nicolas Frattaroli wrote:
>>> From: Ye Zhang <ye.zhang at rock-chips.com>
>>>
>>> The RK3576 SoC has six TS-ADC channels: TOP, BIG_CORE, LITTLE_CORE,
>>> DDR, NPU and GPU.
>>>
>>> Signed-off-by: Ye Zhang <ye.zhang at rock-chips.com>
>>> [ported to mainline, reworded commit message]
>>> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
>>> ---
>>>
>>>  drivers/thermal/rockchip_thermal.c | 42
>>>  ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
>>>
>>> diff --git a/drivers/thermal/rockchip_thermal.c
>>> b/drivers/thermal/rockchip_thermal.c index
>>> a8ad85feb68fbb7ec8d79602b16c47838ecb3c00..bec1930bebd87859a7e519cfc9f05e1
>>> 0b1c31e87 100644 --- a/drivers/thermal/rockchip_thermal.c
>>> +++ b/drivers/thermal/rockchip_thermal.c
>>> @@ -1061,6 +1061,22 @@ static void rk_tsadcv3_tshut_mode(int chn, void
>>> __iomem *regs,> 
>>>  	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
>>>  
>>>  }
>>>
>>> +static void rk_tsadcv4_tshut_mode(int chn, void __iomem *regs,
>>> +				  enum tshut_mode mode)
>>> +{
>>> +	u32 val_gpio, val_cru;
>>> +
>>> +	if (mode == TSHUT_MODE_GPIO) {
>>> +		val_gpio = TSADCV2_INT_SRC_EN(chn) | 
> TSADCV2_INT_SRC_EN_MASK(chn);
>>> +		val_cru = TSADCV2_INT_SRC_EN_MASK(chn);
>>> +	} else {
>>> +		val_cru = TSADCV2_INT_SRC_EN(chn) | 
> TSADCV2_INT_SRC_EN_MASK(chn);
>>> +		val_gpio = TSADCV2_INT_SRC_EN_MASK(chn);
>>> +	}
>>> +	writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN);
>>> +	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
>>> +}
>>
>> This function is identical to rk_tsadcv3_tshut_mode() in mainline.
>>
>> Should the v3 function be renamed to v4 in mainline to match vendor
>> kernel to avoid confusion?
> 
> Good catch. Yes, I'll add a patch to rename the function before introducing 
> new changes in v4, and get rid of the duplicate function.

Great.

> 
>>
>>> +
>>>
>>>  static const struct rockchip_tsadc_chip px30_tsadc_data = {
>>>  
>>>  	/* cpu, gpu */
>>>  	.chn_offset = 0,
>>>
>>> @@ -1284,6 +1300,28 @@ static const struct rockchip_tsadc_chip
>>> rk3568_tsadc_data = {> 
>>>  	},
>>>  
>>>  };
>>>
>>> +static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
>>> +	/* top, big_core, little_core, ddr, npu, gpu */
>>> +	.chn_offset = 0,
>>> +	.chn_num = 6, /* six channels for tsadc */
>>> +	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC 
> */
>>> +	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
>>> +	.tshut_temp = 95000,
>>
>> Here the default is GPIO and 95 deg, in DT node the default is override
>> to CRU and 120 deg.
>>
>> Any reason that is not the default here?
> 
> No reason, other than that this is what most Rockchip SoCs seem to do. RK3588 
> does the same thing. The hardware power-on-reset state is to not have any 
> tshut, so whatever the "default" should be is entirely made up by the driver 
> in either case.
> 
> For the sake of being consistent, I'll keep it the same in v4, as RK3588 does. 
> Otherwise, we'll have RK3576 and RK3588 do different things. If someone wants 
> to change the default, then ideally this would be done in a follow-up series 
> to make it consistent for all SoCs.
> 
> If that's alright with you, then I'll send out a v4.

Sounds good, I was mostly wondering because I am preparing patches for
RK3528 and it felt strange to define one default in driver and directly
override that default in DT to something different.

Also noticed that this driver log a warning when the DT props are
missing, something that probably should be downgraded as the props are
optional in DT schema. Something for another series.

Regards,
Jonas

> 
>>
>> Regards,
>> Jonas
>>
> 
> Regards,
> Nicolas Frattaroli
> 
>>> +	.initialize = rk_tsadcv8_initialize,
>>> +	.irq_ack = rk_tsadcv4_irq_ack,
>>> +	.control = rk_tsadcv4_control,
>>> +	.get_temp = rk_tsadcv4_get_temp,
>>> +	.set_alarm_temp = rk_tsadcv3_alarm_temp,
>>> +	.set_tshut_temp = rk_tsadcv3_tshut_temp,
>>> +	.set_tshut_mode = rk_tsadcv4_tshut_mode,
>>> +	.table = {
>>> +		.id = rk3588_code_table,
>>> +		.length = ARRAY_SIZE(rk3588_code_table),
>>> +		.data_mask = TSADCV4_DATA_MASK,
>>> +		.mode = ADC_INCREMENT,
>>> +	},
>>> +};
>>> +
>>>
>>>  static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
>>>  
>>>  	/* top, big_core0, big_core1, little_core, center, gpu, npu */
>>>  	.chn_offset = 0,
>>>
>>> @@ -1342,6 +1380,10 @@ static const struct of_device_id
>>> of_rockchip_thermal_match[] = {> 
>>>  		.compatible = "rockchip,rk3568-tsadc",
>>>  		.data = (void *)&rk3568_tsadc_data,
>>>  	
>>>  	},
>>>
>>> +	{
>>> +		.compatible = "rockchip,rk3576-tsadc",
>>> +		.data = (void *)&rk3576_tsadc_data,
>>> +	},
>>>
>>>  	{
>>>  	
>>>  		.compatible = "rockchip,rk3588-tsadc",
>>>  		.data = (void *)&rk3588_tsadc_data,
> 
> 
> 
> 



From quentin.schulz at cherry.de  Mon Mar 17 04:55:12 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Mon, 17 Mar 2025 12:55:12 +0100
Subject: [PATCH 0/3] Rockchip IOMMU fixes
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <7c620745-f218-4361-82c2-ea0efd3cbbe9@cherry.de>

Hi Robin,

On 3/13/25 6:31 PM, Robin Murphy wrote:
> Hi all,
> 
> I was expecting my DT probing change to flush out issues, and it seems
> some weaknesses in rockchip-iommu were the first to show. The first two
> patches here get things working again for me on my RK3399 NanoPC-T4
> (with a console on HDMI exercising the VOP MMU), the 3rd patch just
> finishes the cleanup since I was there and could test it.
> 
> Thanks,
> Robin.
> 
> Robin Murphy (3):
>    iommu/rockchip: Allocate per-device data sensibly
>    iommu/rockchip: Register in a sensible order
>    iommu/rockchip: Retire global dma_dev workaround
> 

Fixes the issue seen on next-20250314 on my RK3588 Tiger Haikou:

"""
[    2.007506] Unable to handle kernel NULL pointer dereference at 
virtual address 0000000000000298
[    2.017346] Mem abort info:
[    2.020465]   ESR = 0x0000000096000004
[    2.024654]   EC = 0x25: DABT (current EL), IL = 32 bits
[    2.030591]   SET = 0, FnV = 0
[    2.033999]   EA = 0, S1PTW = 0
[    2.037506]   FSC = 0x04: level 0 translation fault
[    2.042958] Data abort info:
[    2.046170]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[    2.052302]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[    2.057949]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[    2.063885] [0000000000000298] user address but active_mm is swapper
[    2.070989] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[    2.077994] Modules linked in:
[    2.081405] CPU: 7 UID: 0 PID: 1 Comm: swapper/0 Not tainted 
6.14.0-rc6-next-20250314-dirty #10
[    2.091132] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou 
devkit (DT)
[    2.099397] pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS 
BTYPE=--)
[    2.107179] pc : devm_kmalloc+0x28/0x100
[    2.111568] lr : rk_iommu_of_xlate+0x30/0x90
[    2.116341] sp : ffff800081d0b840
[    2.120040] x29: ffff800081d0b840 x28: 0000000000000000 x27: 
ffff8000815d3e20
[    2.128010] x26: 0000000000000001 x25: ffff8000815d4ed8 x24: 
ffff0001f08e1f60
[    2.135989] x23: 0000000000000000 x22: ffff8000811b3f58 x21: 
0000000000000000
[    2.143966] x20: 0000000000000010 x19: 0000000000000000 x18: 
00000000ffffffff
[    2.151944] x17: ffff0001f14acc00 x16: ffff0001f14aca00 x15: 
ffff0001f148b27c
[    2.159922] x14: ffff800081d0b820 x13: ffff0001f148ba1c x12: 
0101010101010101
[    2.167899] x11: 7f7f7f7f7f7f7f7f x10: 00000000000a2cc8 x9 : 
0000000000000003
[    2.175877] x8 : ffff0001f08e3540 x7 : 0000000000000000 x6 : 
1d150c11f5f38080
[    2.183855] x5 : ffff0001f0278000 x4 : 0000000000000000 x3 : 
ffff800081a77218
[    2.191832] x2 : 0000000000000dc0 x1 : 0000000000000010 x0 : 
0000000000000090
[    2.199812] Call trace:
[    2.202538]  devm_kmalloc+0x28/0x100 (P)
[    2.206924]  rk_iommu_of_xlate+0x30/0x90
[    2.211307]  of_iommu_xlate+0x94/0xc0
[    2.215400]  of_iommu_configure+0x1cc/0x250
[    2.220075]  of_dma_configure_id+0x144/0x24c
[    2.224848]  platform_dma_configure+0x8c/0xb4
[    2.229716]  __iommu_probe_device+0x2e4/0x4a0
[    2.234583]  probe_iommu_group+0x3c/0x68
[    2.238965]  bus_for_each_dev+0x7c/0xe0
[    2.243244]  iommu_device_register+0xd8/0x228
[    2.248111]  rk_iommu_probe+0x204/0x360
[    2.252397]  platform_probe+0x68/0xdc
[    2.256488]  really_probe+0xbc/0x2c0
[    2.260484]  __driver_probe_device+0x78/0x120
[    2.265355]  driver_probe_device+0x3c/0x154
[    2.270032]  __driver_attach+0x90/0x1a0
[    2.274315]  bus_for_each_dev+0x7c/0xe0
[    2.278602]  driver_attach+0x24/0x30
[    2.282599]  bus_add_driver+0xe4/0x208
[    2.286781]  driver_register+0x68/0x130
[    2.291065]  __platform_driver_register+0x24/0x30
[    2.296322]  rk_iommu_driver_init+0x1c/0x28
[    2.300997]  do_one_initcall+0x60/0x1d4
[    2.305283]  kernel_init_freeable+0x210/0x274
[    2.310153]  kernel_init+0x20/0x140
[    2.314051]  ret_from_fork+0x10/0x20
[    2.318048] Code: a90153f3 b1020020 f9001bf7 aa0103f4 (b9429ab7)
[    2.324857] ---[ end trace 0000000000000000 ]---
[    2.330029] Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x0000000b
[    2.338587] SMP: stopping secondary CPUs
[    2.342971] Kernel Offset: disabled
[    2.346862] CPU features: 0x0c00,000000e0,01202650,8200720b
[    2.353089] Memory Limit: none
[    2.356499] ---[ end Kernel panic - not syncing: Attempted to kill 
init! exitcode=0x0000000b ]---
"""

Therefore:

Tested-by: Quentin Schulz <quentin.schulz at cherry.de>

Thanks!
Quentin


From james.clark at linaro.org  Mon Mar 17 04:56:17 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 11:56:17 +0000
Subject: [PATCH 4/7] coresight: Add claim tag warnings and debug messages
In-Reply-To: <20250313144005.GQ9682@e132581.arm.com>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-5-james.clark@linaro.org>
 <20250313144005.GQ9682@e132581.arm.com>
Message-ID: <a4bce4f5-88c3-4755-9ac5-3ce6fb78dfbf@linaro.org>



On 13/03/2025 2:40 pm, Leo Yan wrote:
> On Tue, Feb 11, 2025 at 10:39:40AM +0000, James Clark wrote:
>>
>> Add a dev_dbg() message so that external debugger conflicts are more
>> visible. There are multiple reasons for -EBUSY so a message for this
>> particular one could be helpful. Add errors for and enumerate all the
>> other cases that are impossible.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>   drivers/hwtracing/coresight/coresight-core.c | 48 ++++++++++++--------
>>   drivers/hwtracing/coresight/coresight-priv.h |  5 +-
>>   2 files changed, 34 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index 7b53165c93af..7fe5d5d432c4 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -133,16 +133,6 @@ static inline u32 coresight_read_claim_tags(struct csdev_access *csa)
>>                           csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMCLR));
>>   }
>>
>> -static inline bool coresight_is_claimed_self_hosted(struct csdev_access *csa)
>> -{
>> -       return coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED;
>> -}
>> -
>> -static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>> -{
>> -       return coresight_read_claim_tags(&csdev->access) != 0;
>> -}
>> -
>>   static inline void coresight_set_self_claim_tag(struct csdev_access *csa)
>>   {
>>          csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>> @@ -169,18 +159,40 @@ static inline void coresight_clear_self_claim_tag(struct csdev_access *csa)
>>    */
>>   int coresight_claim_device_unlocked(struct coresight_device *csdev)
>>   {
>> +       int tag;
>> +       struct csdev_access *csa;
>> +
>>          if (WARN_ON(!csdev))
>>                  return -EINVAL;
>>
>> -       if (coresight_is_claimed_any(csdev))
>> +       csa = &csdev->access;
>> +       tag = coresight_read_claim_tags(csa);
>> +
>> +       switch (tag) {
>> +       case CORESIGHT_CLAIM_FREE:
>> +               coresight_set_self_claim_tag(csa);
>> +               if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED)
>> +                       return 0;
>> +
> 
> It would be a rare case if a failure happens here.  Seems to me, it
> would be valuable to print a log for this edge case.
> 
> Otherwise, looks good to me.
> 

Yeah I can add dev_dbg("Busy: Couldn't set self claim tag"). Just to 
distinguish this race case from the other busy case.




From robin.murphy at arm.com  Mon Mar 17 05:00:33 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 17 Mar 2025 12:00:33 +0000
Subject: [PATCH] perf/arm_cspmu: Fix missing io.h include
Message-ID: <657935ca177024ad08d5ec6f85e8faf75f82cf65.1742212833.git.robin.murphy@arm.com>

Adding the writel() calls needs io.h, which apparently gets
transiently included somewhere on arm64, but not elsewhere.

Fixes: 6de0298a3925 ("perf/arm_cspmu: Generalise event filtering")
Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503150649.Dol8RBSh-lkp at intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202503152245.cAG4FMfi-lkp at intel.com/
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/perf/arm_cspmu/nvidia_cspmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index 4d5c4912c68f..0a7e316fb999 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -6,6 +6,7 @@
 
 /* Support for NVIDIA specific attributes. */
 
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/topology.h>
 
-- 
2.39.2.101.g768bb238c484.dirty



From foss+kernel at 0leil.net  Mon Mar 17 05:07:25 2025
From: foss+kernel at 0leil.net (Quentin Schulz)
Date: Mon, 17 Mar 2025 13:07:25 +0100
Subject: [PATCH 0/2] arm64: dts: rockchip: enable HDMI audio on RK3588
 Jaguar and RK3588 Tiger Haikou
Message-ID: <20250317-tsd-rk3588-hdmi-audio-v1-0-0b8ceb9597a6@cherry.de>

Both have an HDMI TX port and can carry audio, therefore let's simply
enable the nodes required to get HDMI audio on that port.

This is based on next-20250314 and the following series needs to be
applied in order to reach userspace:
https://lore.kernel.org/linux-rockchip/cover.1741886382.git.robin.murphy at arm.com/

Signed-off-by: Quentin Schulz <quentin.schulz at cherry.de>
---
Quentin Schulz (2):
      arm64: dts: rockchip: Enable HDMI audio output for RK3588 Jaguar
      arm64: dts: rockchip: Enable HDMI audio output for RK3588 Tiger Haikou

 arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts       | 8 ++++++++
 arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts | 8 ++++++++
 2 files changed, 16 insertions(+)
---
base-commit: da920b7df701770e006928053672147075587fb2
change-id: 20250317-tsd-rk3588-hdmi-audio-c0ea0f1ab689

Best regards,
-- 
Quentin Schulz <quentin.schulz at cherry.de>



From foss+kernel at 0leil.net  Mon Mar 17 05:07:27 2025
From: foss+kernel at 0leil.net (Quentin Schulz)
Date: Mon, 17 Mar 2025 13:07:27 +0100
Subject: [PATCH 2/2] arm64: dts: rockchip: Enable HDMI audio output for
 RK3588 Tiger Haikou
In-Reply-To: <20250317-tsd-rk3588-hdmi-audio-v1-0-0b8ceb9597a6@cherry.de>
References: <20250317-tsd-rk3588-hdmi-audio-v1-0-0b8ceb9597a6@cherry.de>
Message-ID: <20250317-tsd-rk3588-hdmi-audio-v1-2-0b8ceb9597a6@cherry.de>

From: Quentin Schulz <quentin.schulz at cherry.de>

HDMI audio is available on the RK3588 Tiger Haikou HDMI TX port, so
let's enable it.

Signed-off-by: Quentin Schulz <quentin.schulz at cherry.de>
---
 arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
index a3d8ff647839a900ece2ca9113754c7b20605641..caa43d1abf179365d37a244ea374b0dae39b0433 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
@@ -189,6 +189,10 @@ hdmi0_out_con: endpoint {
 	};
 };
 
+&hdmi0_sound {
+	status = "okay";
+};
+
 &hdptxphy0 {
 	status = "okay";
 };
@@ -228,6 +232,10 @@ &i2s3_2ch {
 	status = "okay";
 };
 
+&i2s5_8ch {
+	status = "okay";
+};
+
 &pcie30phy {
 	status = "okay";
 };

-- 
2.48.1



From foss+kernel at 0leil.net  Mon Mar 17 05:07:26 2025
From: foss+kernel at 0leil.net (Quentin Schulz)
Date: Mon, 17 Mar 2025 13:07:26 +0100
Subject: [PATCH 1/2] arm64: dts: rockchip: Enable HDMI audio output for
 RK3588 Jaguar
In-Reply-To: <20250317-tsd-rk3588-hdmi-audio-v1-0-0b8ceb9597a6@cherry.de>
References: <20250317-tsd-rk3588-hdmi-audio-v1-0-0b8ceb9597a6@cherry.de>
Message-ID: <20250317-tsd-rk3588-hdmi-audio-v1-1-0b8ceb9597a6@cherry.de>

From: Quentin Schulz <quentin.schulz at cherry.de>

HDMI audio is available on the RK3588 Jaguar HDMI TX port, so let's
enable it.

Signed-off-by: Quentin Schulz <quentin.schulz at cherry.de>
---
 arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts b/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
index 9fceea6c1398e92114dcb735cf2babb7d05d67a5..ebe77cdd24e803b00fb848dc81258909472290f1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
@@ -303,6 +303,10 @@ hdmi0_out_con: endpoint {
 	};
 };
 
+&hdmi0_sound {
+	status = "okay";
+};
+
 &hdptxphy0 {
 	status = "okay";
 };
@@ -512,6 +516,10 @@ regulator-state-mem {
 	};
 };
 
+&i2s5_8ch {
+	status = "okay";
+};
+
 &mdio0 {
 	rgmii_phy: ethernet-phy at 6 {
 		/* KSZ9031 or KSZ9131 */

-- 
2.48.1



From festevam at gmail.com  Mon Mar 17 05:31:09 2025
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 17 Mar 2025 09:31:09 -0300
Subject: [PATCH v3] ARM: dts: imx51-digi-connectcore-som: Fix MMA7455 compatible
Message-ID: <20250317123109.2216509-1-festevam@gmail.com>

From: Fabio Estevam <festevam at denx.de>

The "fsl,mma7455l" compatible string is not documented anywhere.

MMA7455L is the exact same device as the MMA7455, with the exception that
it is lead-free. Use the documented compatible string.

Signed-off-by: Fabio Estevam <festevam at denx.de>
---
Changes since v2:
- Explain why it is safe to change the compatible string.

 arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
index dc72a2d14960..1980f751f161 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
@@ -165,7 +165,7 @@ &i2c2 {
 	mma7455l at 1d {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_mma7455l>;
-		compatible = "fsl,mma7455l";
+		compatible = "fsl,mma7455";
 		reg = <0x1d>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>, <6 IRQ_TYPE_LEVEL_HIGH>;
-- 
2.34.1



From ariel.dalessandro at collabora.com  Mon Mar 17 05:34:00 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:34:00 -0300
Subject: [PATCH v2 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250315094338.5f402426@collabora.com>
References: <20250314173858.212264-1-ariel.dalessandro@collabora.com>
 <20250314173858.212264-5-ariel.dalessandro@collabora.com>
 <20250315094338.5f402426@collabora.com>
Message-ID: <eabb2f2c-b193-4ddf-8a50-27952f37393d@collabora.com>

Boris,

On 3/15/25 5:43 AM, Boris Brezillon wrote:
> On Fri, 14 Mar 2025 14:38:56 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>> Address Extension", which in Linux we've called "mali_lpae".
>>
>> This commit adds support for conditionally enabling AARCH64_4K page
>> table format. To achieve that, a "GPU optional quirks" field was added
>> to `struct panfrost_features` with the related flag.
>>
>> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
>> the HW_FEATURE_AARCH64_MMU feature flag present.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> ---
>>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 136 +++++++++++++++++++--
>>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 ++++++
>>   3 files changed, 177 insertions(+), 9 deletions(-)
[snip]
>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> index 294f86b3c25e7..f24c23e1f67b8 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> @@ -26,6 +26,48 @@
>>   #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
>>   #define mmu_read(dev, reg) readl(dev->iomem + reg)
>>   
[snip]
>>   u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>>   {
>>   	int as;
>> @@ -618,6 +720,18 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>>   	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>>   	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
>>   	struct panfrost_mmu *mmu;
>> +	enum io_pgtable_fmt fmt;
>> +
>> +	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
>> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
>> +			dev_err_once(pfdev->dev,
>> +				     "AARCH64_4K page table not supported\n");
>> +			return ERR_PTR(-EINVAL);
>> +		}
>> +		fmt = ARM_64_LPAE_S1;
>> +	} else {
>> +		fmt = ARM_MALI_LPAE;
>> +	}
>>   
>>   	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>>   	if (!mmu)
>> @@ -642,16 +756,20 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>>   		.iommu_dev	= pfdev->dev,
>>   	};
>>   
>> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
>> -					      mmu);
>> -	if (!mmu->pgtbl_ops) {
>> -		kfree(mmu);
>> -		return ERR_PTR(-EINVAL);
>> -	}
>> +	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
>> +	if (!mmu->pgtbl_ops)
>> +		goto err_free_mmu;
>> +
>> +	if (panfrost_mmu_cfg_init(mmu, fmt))
>> +		goto err_free_mmu;
> 
> How about propagating the error returned by panfrost_mmu_cfg_init()
> instead of assuming it's always -EINVAL on failure? Oh, and you need to
> call free_io_pgtable_ops(), not just kfree().

Ah, totally, thanks for the heads up. Will fix in v3 right away.

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:44 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:44 -0300
Subject: [PATCH v3 6/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-7-ariel.dalessandro@collabora.com>

MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
Panfrost supports AARCH64_4K page table format, let's enable it on this
SoC.

Running glmark2-es2-drm [0] benchmark, reported the same performance
score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.

[0] https://github.com/glmark2/glmark2

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index e854f290858f9..ef30d314b2281 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -836,6 +836,7 @@ static const struct panfrost_compatible mediatek_mt8192_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains),
 	.pm_domain_names = mediatek_mt8192_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const struct of_device_id dt_match[] = {
-- 
2.47.2



From andrew at lunn.ch  Mon Mar 17 05:44:36 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 17 Mar 2025 13:44:36 +0100
Subject: [net-next 3/4] dt-bindings: net: ftgmac100: add rgmii delay
 properties
In-Reply-To: <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
Message-ID: <27927166-d73b-4837-90a9-ed15661b0a6e@lunn.ch>

> In Aspeed desgin, the RGMII delay is a number of ps as unit to
> set delay, do not use one ps as unit. The values are different
> from each MAC. So, here describes the property values
> as index to configure corresponding scu register.
> 
> Signed-off-by: Jacky Chou <jacky_chou at aspeedtech.com>
> ---
>  .../bindings/net/faraday,ftgmac100.yaml          | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
> index 55d6a8379025..c5904aa84e05 100644
> --- a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
> +++ b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
> @@ -66,6 +66,20 @@ properties:
>      type: boolean
>      deprecated: true
>  
> +  rx-internal-delay-ps:
> +    description:
> +       Setting this property to a non-zero number sets the RX internal delay
> +       for the MAC. Use this property value as a index not a ps unit to
> +       configure the corresponding delay register field. And the index range is
> +       0 to 63.

You have to use picoseconds here. As with all DT binding, you use SI
units, and the driver then converts them to whatever value you need to
poke into the register.
	
    Andrew

---
pw-bot: cr


From andrew at lunn.ch  Mon Mar 17 05:47:16 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 17 Mar 2025 13:47:16 +0100
Subject: [net-next 1/4] ARM: dts: aspeed-g6:add scu to mac for RGMII delay
In-Reply-To: <20250317025922.1526937-2-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-2-jacky_chou@aspeedtech.com>
Message-ID: <be284777-978d-470a-b38c-2f79a1d76134@lunn.ch>

On Mon, Mar 17, 2025 at 10:59:19AM +0800, Jacky Chou wrote:
> The RGMII delay of AST2600 MAC is configured in SCU
> register, so add scu regmap into mac node.

Don't you need to add the scu to the binding?

	Andrew


From hejunhao3 at huawei.com  Mon Mar 17 05:41:06 2025
From: hejunhao3 at huawei.com (Junhao He)
Date: Mon, 17 Mar 2025 20:41:06 +0800
Subject: [PATCH v2] coresight: Fixes device's owner field for registered using coresight_init_driver()
Message-ID: <20250317124106.271374-1-hejunhao3@huawei.com>

The coresight_init_driver() of the coresight-core module is called from
the sub coresgiht device (such as tmc/stm/funnle/...) module. It calls
amba_driver_register() and Platform_driver_register(), which are macro
functions that use the coresight-core's module to initialize the caller's
owner field.  Therefore, when the sub coresight device calls
coresight_init_driver(), an incorrect THIS_MODULE value is captured.

The sub coesgiht modules can be removed while their callbacks are
running, resulting in a general protection failure.

User a macro to automatically add the THIS_MODULE param to
coresight_init_driver() to fix this.

Fixes: 075b7cd7ad7d ("coresight: Add helpers registering/removing both AMBA and platform drivers")
Signed-off-by: Junhao He <hejunhao3 at huawei.com>
---
Changes in v2:
- even a macro to automatically add the THIS_MODULE param for coresight_init_driver();
- Link to v1: https://lore.kernel.org/lkml/c3744062-f7c1-82df-2fa1-591da3b2dc5e at huawei.com/T/
---
 drivers/hwtracing/coresight/coresight-core.c | 11 ++++++-----
 include/linux/coresight.h                    |  7 +++++--
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 0a9380350fb5..abf2e4fd4de0 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1486,18 +1486,19 @@ static void __exit coresight_exit(void)
 module_init(coresight_init);
 module_exit(coresight_exit);
 
-int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
-			  struct platform_driver *pdev_drv)
+int coresight_init_driver_owner(const char *drv, struct amba_driver *amba_drv,
+				struct platform_driver *pdev_drv,
+				struct module *owner)
 {
 	int ret;
 
-	ret = amba_driver_register(amba_drv);
+	ret = __amba_driver_register(amba_drv, owner);
 	if (ret) {
 		pr_err("%s: error registering AMBA driver\n", drv);
 		return ret;
 	}
 
-	ret = platform_driver_register(pdev_drv);
+	ret = __platform_driver_register(pdev_drv, owner);
 	if (!ret)
 		return 0;
 
@@ -1505,7 +1506,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
 	amba_driver_unregister(amba_drv);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(coresight_init_driver);
+EXPORT_SYMBOL_GPL(coresight_init_driver_owner);
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 17276965ff1d..b07455956f7a 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -689,8 +689,11 @@ coresight_find_output_type(struct coresight_platform_data *pdata,
 			   enum coresight_dev_type type,
 			   union coresight_dev_subtype subtype);
 
-int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
-			  struct platform_driver *pdev_drv);
+int coresight_init_driver_owner(const char *drv, struct amba_driver *amba_drv,
+				struct platform_driver *pdev_drv, struct module *owner);
+
+#define coresight_init_driver(name, amba_drv, pdev_drv)	\
+	coresight_init_driver_owner(name, amba_drv, pdev_drv, THIS_MODULE)
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv);
-- 
2.33.0



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:38 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:38 -0300
Subject: [PATCH v3 0/6] drm/panfrost: Add support for AARCH64_4K page table format
Message-ID: <20250317124044.16257-1-ariel.dalessandro@collabora.com>

Hi all,

This is a new iteration on Panfrost support for AARCH64_4K page table
format. The main reason behind this patchset is that MediaTek MT8188 SoC
(ARM Mali-G57 MC3 GPU) constantly faults due to the actual Panfrost cache
configuration.

Currently, Panfrost only supports MMU configuration in "LEGACY" (as Bifrost
calls it) mode, a (modified) version of LPAE "Large Physical Address
Extension", which in Linux we've called "mali_lpae".

This patchset adds support for conditionally enabling AARCH64_4K page table
format. To achieve that, a "GPU optional quirks" field was added to
`struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

The patchset only enables the new format on Mediatek MT8188 and MT8192,
which have been tested on a Mediatek Genio 700 EVK (MT8390) and Mediatek
Genio 1200 EVK (MT8395) boards respectively.

Thanks!

Changes in v3:
* Fixed error handling in panfrost_mmu_ctx_create().

Changes in v2:
* Dropped panfrost_mmu_enable/disable unification.
* Rename gpu_configs as gpu_quirks.
* Added error handling on page table not properly aligned.
* Enabled AARCH64_4K format on MediaTek MT8192 as well.
* Minor fixes.

Changes in v1:
* Added "Set IOMMU_CACHE flag" patch.
* Replaced `panfrost_mmu->enable()` function pointer by `cfg` struct
prepared during init time.
* Made mali_lpae/aarch64_4k name more clear.
* Added GPU_CONFIG_AARCH64_4K flag to enable AARCH64_4K page table
  format.
* Enabled AARCH64_4K mode only on mediatek-mt8188.

Ariel D'Alessandro (6):
  drm/panfrost: Set IOMMU_CACHE flag
  drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
  drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost
    models
  drm/panfrost: Add support for AARCH64_4K page table format
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192

 drivers/gpu/drm/panfrost/panfrost_device.h   |  16 ++
 drivers/gpu/drm/panfrost/panfrost_drv.c      |   2 +
 drivers/gpu/drm/panfrost/panfrost_features.h |   3 +
 drivers/gpu/drm/panfrost/panfrost_mmu.c      | 149 +++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h     |  36 +++++
 5 files changed, 195 insertions(+), 11 deletions(-)

-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:39 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:39 -0300
Subject: [PATCH v3 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-2-ariel.dalessandro@collabora.com>

Panfrost does not support uncached mappings, so flag them properly. Also
flag the pages that are mapped as response to a page fault as cached.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index b91019cd5acb1..9e6f198ef5c1b 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 	struct drm_gem_object *obj = &shmem->base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
-	int prot = IOMMU_READ | IOMMU_WRITE;
+	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
 
 	if (WARN_ON(mapping->active))
 		return 0;
@@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
 		goto err_map;
 
 	mmu_map_sg(pfdev, bomapping->mmu, addr,
-		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
 
 	bomapping->active = true;
 	bo->heap_rss_size += SZ_2M;
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:40 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:40 -0300
Subject: [PATCH v3 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-3-ariel.dalessandro@collabora.com>

As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
which makes code easier to read and reuse.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 9e6f198ef5c1b..294f86b3c25e7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
 
 struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
+	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
+	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 
 	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
 		.pgsize_bitmap	= SZ_4K | SZ_2M,
-		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
-		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
+		.ias		= va_bits,
+		.oas		= pa_bits,
 		.coherent_walk	= pfdev->coherent,
 		.tlb		= &mmu_tlb_ops,
 		.iommu_dev	= pfdev->dev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index c7bba476ab3f3..b5f279a19a084 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -16,6 +16,8 @@
 #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
 
 #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
+#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
+#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
 #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
 #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
 
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:41 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:41 -0300
Subject: [PATCH v3 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost models
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-4-ariel.dalessandro@collabora.com>

Set this feature flag on all Mali Bifrost platforms as the MMU supports
AARCH64 4K page table format.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_features.h
+++ b/drivers/gpu/drm/panfrost/panfrost_features.h
@@ -54,6 +54,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g72 (\
@@ -64,6 +65,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g51 hw_features_g72
@@ -77,6 +79,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
 	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g76 (\
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:42 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:42 -0300
Subject: [PATCH v3 4/6] drm/panfrost: Add support for AARCH64_4K page table format
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-5-ariel.dalessandro@collabora.com>

Currently, Panfrost only supports MMU configuration in "LEGACY" (as
Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called "mali_lpae".

This commit adds support for conditionally enabling AARCH64_4K page
table format. To achieve that, a "GPU optional quirks" field was added
to `struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
 drivers/gpu/drm/panfrost/panfrost_mmu.c    | 139 +++++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 +++++
 3 files changed, 182 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index cffcb0ac7c111..ad95f2ed31d9a 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
 	GPU_PM_VREG_OFF,
 };
 
+/**
+ * enum panfrost_gpu_quirks - GPU optional quirks
+ * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
+ */
+enum panfrost_gpu_quirks {
+	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
+};
+
 struct panfrost_features {
 	u16 id;
 	u16 revision;
@@ -95,6 +103,9 @@ struct panfrost_compatible {
 
 	/* Allowed PM features */
 	u8 pm_features;
+
+	/* GPU configuration quirks */
+	u8 gpu_quirks;
 };
 
 struct panfrost_device {
@@ -162,6 +173,11 @@ struct panfrost_mmu {
 	int as;
 	atomic_t as_count;
 	struct list_head list;
+	struct {
+		u64 transtab;
+		u64 memattr;
+		u64 transcfg;
+	} cfg;
 };
 
 struct panfrost_engine_usage {
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 294f86b3c25e7..e85bd482e7c56 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -26,6 +26,48 @@
 #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define mmu_read(dev, reg) readl(dev->iomem + reg)
 
+static u64 mair_to_memattr(u64 mair, bool coherent)
+{
+	u64 memattr = 0;
+	u32 i;
+
+	for (i = 0; i < 8; i++) {
+		u8 in_attr = mair >> (8 * i), out_attr;
+		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
+
+		/* For caching to be enabled, inner and outer caching policy
+		 * have to be both write-back, if one of them is write-through
+		 * or non-cacheable, we just choose non-cacheable. Device
+		 * memory is also translated to non-cacheable.
+		 */
+		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
+				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
+		} else {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
+			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
+			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
+			 * to Mali's internal-shareable mode. As per the Mali
+			 * Spec, inner and outer-shareable modes aren't allowed
+			 * for WB memory when coherency is disabled.
+			 * Use SH_CPU_INNER mode when coherency is enabled, so
+			 * that SH_IS actually maps to the standard definition of
+			 * inner-shareable.
+			 */
+			if (!coherent)
+				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
+			else
+				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
+		}
+
+		memattr |= (u64)out_attr << (8 * i);
+	}
+
+	return memattr;
+}
+
 static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
 {
 	int ret;
@@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
+	u64 transtab = mmu->cfg.transtab;
+	u64 memattr = mmu->cfg.memattr;
+	u64 transcfg = mmu->cfg.transcfg;
 
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
@@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
@@ -152,9 +197,66 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
+static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	/* TODO: The following fields are duplicated between the MMU and Page
+	 * Table config structs. Ideally, should be kept in one place.
+	 */
+	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
+	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
+	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
+
+	return 0;
+}
+
+static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
+				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
+		return -EINVAL;
+
+	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+
+	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
+					   pgtbl_cfg->coherent_walk);
+
+	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
+			    AS_TRANSCFG_PTW_RA |
+			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
+			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
+	if (pgtbl_cfg->coherent_walk)
+		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
+
+	return 0;
+}
+
+static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
+				  enum io_pgtable_fmt fmt)
+{
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		return mmu_cfg_init_aarch64_4k(mmu);
+	case ARM_MALI_LPAE:
+		return mmu_cfg_init_mali_lpae(mmu);
+	default:
+		/* This should never happen */
+		return drm_WARN_ON(pfdev->ddev, -EINVAL);
+	}
+}
+
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as;
@@ -618,6 +720,19 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
 	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
+	enum io_pgtable_fmt fmt;
+	int ret;
+
+	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
+		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
+			dev_err_once(pfdev->dev,
+				     "AARCH64_4K page table not supported\n");
+			return ERR_PTR(-EINVAL);
+		}
+		fmt = ARM_64_LPAE_S1;
+	} else {
+		fmt = ARM_MALI_LPAE;
+	}
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
 	if (!mmu)
@@ -642,16 +757,26 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 		.iommu_dev	= pfdev->dev,
 	};
 
-	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
-					      mmu);
+	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
 	if (!mmu->pgtbl_ops) {
-		kfree(mmu);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto err_free_mmu;
 	}
 
+	ret = panfrost_mmu_cfg_init(mmu, fmt);
+	if (ret)
+		goto err_free_io_pgtable;
+
 	kref_init(&mmu->refcount);
 
 	return mmu;
+
+err_free_io_pgtable:
+	free_io_pgtable_ops(mmu->pgtbl_ops);
+
+err_free_mmu:
+	kfree(mmu);
+	return ERR_PTR(ret);
 }
 
 static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index b5f279a19a084..2b8f1617b8369 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -301,6 +301,17 @@
 #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
 #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
+							 ((w) ? BIT(0) : 0) | \
+							 ((r) ? BIT(1) : 0))
+#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
+#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
+#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
 #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
 #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
 #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
@@ -311,6 +322,24 @@
 /* Additional Bifrost AS registers */
 #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
 #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
+#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
+#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
+#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
+#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
+#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
+#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
+#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
+#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
+#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
+#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
+#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
+#define   AS_TRANSCFG_PTW_RA				BIT(30)
+#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
+#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
+#define   AS_TRANSCFG_WXN				BIT(35)
+#define   AS_TRANSCFG_XREADABLE				BIT(36)
 #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
@@ -326,6 +355,11 @@
 #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
 #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
 
+/*
+ * Begin AARCH64_4K MMU TRANSTAB register values
+ */
+#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
+
 #define AS_STATUS_AS_ACTIVE			0x01
 
 #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 05:40:43 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 09:40:43 -0300
Subject: [PATCH v3 5/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
In-Reply-To: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317124044.16257-6-ariel.dalessandro@collabora.com>

MediaTek MT8188 SoC has an ARM Mali-G57 MC3 GPU (Valhall-JM), which
constantly faults with the current panfrost support.

For instance, running `glmark2-es2-drm` benchmark test:
```
[   79.617461] panfrost 13000000.gpu: js fault, js=1, status=JOB_BUS_FAULT, head=0xaadc380, tail=0xaadc380
[   80.119811] panfrost 13000000.gpu: gpu sched timeout, js=0, config=0x7300, status=0x58, head=0xaaca180, tail=0xaaca180, sched_job=000000002fd03ccc
[   80.129083] panfrost 13000000.gpu: Unhandled Page fault in AS0 at VA 0x0000000000000000
[   80.129083] Reason: TODO
[   80.129083] raw fault status: 0x1C2
[   80.129083] decoded fault status: SLAVE FAULT
[   80.129083] exception type 0xC2: TRANSLATION_FAULT_2
[   80.129083] access type 0x1: EXECUTE
[   80.129083] source id 0x0
```

Note that current panfrost mode (Mali LPAE - LEGACY) only allows to
specify write-cache or implementation-defined as the caching policy,
probably not matching the right configuration. As depicted in the source
code:

drivers/iommu/io-pgtable-arm.c:
```
* MEMATTR: Mali has no actual notion of a non-cacheable type, so the
* best we can do is mimic the out-of-tree driver and hope that the
* "implementation-defined caching policy" is good enough...
```

Now that Panfrost supports AARCH64_4K page table format, let's enable it
on Mediatek MT8188 and configure the cache/shareability policies
properly.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 0f3935556ac76..e854f290858f9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
 	.pm_domain_names = mediatek_mt8183_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
-- 
2.47.2



From andrew at lunn.ch  Mon Mar 17 05:52:39 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 17 Mar 2025 13:52:39 +0100
Subject: =?utf-8?B?5Zue6KaG?= =?utf-8?Q?=3A?= [net-next 4/4] net:
 ftgmac100: add RGMII delay for AST2600
In-Reply-To: <SEYPR06MB51347CD1AB5940641A77427D9DDF2@SEYPR06MB5134.apcprd06.prod.outlook.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
 <20250317095229.6f8754dd@fedora.home>
 <Z9gC2vz2w5dfZsum@shell.armlinux.org.uk>
 <SEYPR06MB51347CD1AB5940641A77427D9DDF2@SEYPR06MB5134.apcprd06.prod.outlook.com>
Message-ID: <c3c02498-24a3-4ced-8ba3-5ca62b243047@lunn.ch>

> The RGMII delay of AST2600 has a lot of steps can be configured.

Are they uniformly space? Then it should be a simple formula to
calculate? Or a lookup table?

	Andrew


From andrew at lunn.ch  Mon Mar 17 06:03:58 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 17 Mar 2025 14:03:58 +0100
Subject: [net-next 4/4] net: ftgmac100: add RGMII delay for AST2600
In-Reply-To: <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
Message-ID: <dc7296b2-e7aa-4cc3-9aa7-44e97ec50fc3@lunn.ch>

> +	u32 rgmii_tx_delay, rgmii_rx_delay;
> +	u32 dly_reg, tx_dly_mask, rx_dly_mask;
> +	int tx, rx;
> +
> +	netdev = platform_get_drvdata(pdev);
> +	priv = netdev_priv(netdev);
> +
> +	tx = of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay);
> +	rx = of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_rx_delay);

> +	if (!tx) {

The documentation for of_property_read_u32() says:

 * Return: 0 on success, -EINVAL if the property does not exist,
 * -ENODATA if property does not have a value, and -EOVERFLOW if the
 * property data isn't large enough.

You need to handle EINVAL different to the other errors, which are
real errors and should fail the probe.

The commit message, and probably the binding needs to document what
happens when the properties are not in the DT blob. This needs to be
part of the bigger picture of how you are going to sort out the mess
with existing .dts files listing 'rgmii' when in fact they should be
'rgmii-id'.

> +		/* Use tx-internal-delay-ps as index to configure tx delay
> +		 * into scu register.
> +		 */
> +		if (rgmii_tx_delay > 64)
> +			dev_warn(&pdev->dev, "Get invalid tx delay value");

Return EINVAL and fail the probe.

	Andrew


From lkp at intel.com  Mon Mar 17 06:02:47 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 17 Mar 2025 21:02:47 +0800
Subject: [PATCH v5 3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250315-pmc-v5-3-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-3-ecee87dab216@daynix.com>
Message-ID: <202503172023.fzyJ3TMB-lkp@intel.com>

Hi Akihiko,

kernel test robot noticed the following build errors:

[auto build test ERROR on 80e54e84911a923c40d7bee33a34c1b4be148d7a]

url:    https://github.com/intel-lab-lkp/linux/commits/Akihiko-Odaki/KVM-arm64-PMU-Set-raw-values-from-user-to-PM-C-I-NTEN-SET-CLR-PMOVS-SET-CLR/20250315-173731
base:   80e54e84911a923c40d7bee33a34c1b4be148d7a
patch link:    https://lore.kernel.org/r/20250315-pmc-v5-3-ecee87dab216%40daynix.com
patch subject: [PATCH v5 3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
config: arm64-randconfig-r122-20250317 (https://download.01.org/0day-ci/archive/20250317/202503172023.fzyJ3TMB-lkp at intel.com/config)
compiler: aarch64-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250317/202503172023.fzyJ3TMB-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503172023.fzyJ3TMB-lkp at intel.com/

All errors (new ones prefixed by >>):

   arch/arm64/kvm/sys_regs.c: In function 'set_pmu_evcntr':
>> arch/arm64/kvm/sys_regs.c:975:9: error: implicit declaration of function 'kvm_pmu_set_counter_value_user'; did you mean 'kvm_pmu_set_counter_value'? [-Wimplicit-function-declaration]
     975 |         kvm_pmu_set_counter_value_user(vcpu, idx, val);
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |         kvm_pmu_set_counter_value


vim +975 arch/arm64/kvm/sys_regs.c

   962	
   963	static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
   964				  u64 val)
   965	{
   966		u64 idx;
   967	
   968		if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
   969			/* PMCCNTR_EL0 */
   970			idx = ARMV8_PMU_CYCLE_IDX;
   971		else
   972			/* PMEVCNTRn_EL0 */
   973			idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
   974	
 > 975		kvm_pmu_set_counter_value_user(vcpu, idx, val);
   976		return 0;
   977	}
   978	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From iivanov at suse.de  Mon Mar 17 06:07:18 2025
From: iivanov at suse.de (Ivan T. Ivanov)
Date: Mon, 17 Mar 2025 15:07:18 +0200
Subject: [PATCH] [arm64/tlb] Fix mmu notifiers for range-based invalidates
In-Reply-To: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
References: <20250304085127.2238030-1-pjaroszynski@nvidia.com>
Message-ID: <20250317130718.a5wals252gymjlsk@localhost.localdomain>

Hi,

On 03-04 00:51, Piotr Jaroszynski wrote:
> 
> Update the __flush_tlb_range_op macro not to modify its parameters as
> these are unexepcted semantics. In practice, this fixes the call to
> mmu_notifier_arch_invalidate_secondary_tlbs() in
> __flush_tlb_range_nosync() to use the correct range instead of an empty
> range with start=end. The empty range was (un)lucky as it results in
> taking the invalidate-all path that doesn't cause correctness issues,
> but can certainly result in suboptimal perf.
> 
> This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
> invalidate_range() when invalidating TLBs") when the call to the
> notifiers was added to __flush_tlb_range(). It predates the addition of
> the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
> Refactor the core flush algorithm of __flush_tlb_range") that made the
> bug hard to spot.
> 
> Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

I think that strictly speaking this should be:

Fixes: 360839027a6e ("arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range")

Regards,
Ivan



From andrew at lunn.ch  Mon Mar 17 06:08:41 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 17 Mar 2025 14:08:41 +0100
Subject: [net-next 2/4] ARM: dts: ast2600-evb: add default RGMII delay
In-Reply-To: <20250317025922.1526937-3-jacky_chou@aspeedtech.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-3-jacky_chou@aspeedtech.com>
Message-ID: <5db47dea-7d90-45a1-85a1-1f4f5edd3567@lunn.ch>

> @@ -147,6 +153,9 @@ &mac2 {
>  	phy-mode = "rgmii";
>  	phy-handle = <&ethphy2>;
>  
> +	tx-internal-delay-ps = <8>;
> +	rx-internal-delay-ps = <4>;
> +

Ideally you want:

	phy-mode = "rgmii-id";
	tx-internal-delay-ps = <0>;
	rx-internal-delay-ps = <0>;

Since 'rgmii-id' correctly describes the hardware.

	Andrew


From krzk at kernel.org  Mon Mar 17 06:21:35 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 14:21:35 +0100
Subject: [net-next 3/4] dt-bindings: net: ftgmac100: add rgmii delay
 properties
In-Reply-To: <27927166-d73b-4837-90a9-ed15661b0a6e@lunn.ch>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-4-jacky_chou@aspeedtech.com>
 <27927166-d73b-4837-90a9-ed15661b0a6e@lunn.ch>
Message-ID: <6f862344-b6c1-4c9b-a6d6-bb0e6655d16e@kernel.org>

On 17/03/2025 13:44, Andrew Lunn wrote:
>> diff --git a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
>> index 55d6a8379025..c5904aa84e05 100644
>> --- a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
>> +++ b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml
>> @@ -66,6 +66,20 @@ properties:
>>      type: boolean
>>      deprecated: true
>>  
>> +  rx-internal-delay-ps:
>> +    description:
>> +       Setting this property to a non-zero number sets the RX internal delay
>> +       for the MAC. Use this property value as a index not a ps unit to
>> +       configure the corresponding delay register field. And the index range is
>> +       0 to 63.
> 
> You have to use picoseconds here. As with all DT binding, you use SI
> units, and the driver then converts them to whatever value you need to
> poke into the register.
Ykes, I did notice that when skimming through the patch. Such a sneaky
way to pretend you conform to the bindings but eh, not really, I will do
it my way.

I think reviewing Aspeed code takes a lot, a lot of our time. It's not
only about this patchset but several others.

Maybe it is time for Aspeed to perform intensive internal review, before
they post to the mailing lists? Several other companies do it, more or less.

Best regards,
Krzysztof


From florian.fainelli at broadcom.com  Mon Mar 17 06:29:22 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 17 Mar 2025 06:29:22 -0700
Subject: [PATCH v6 03/10] ARM: dts: Drop DTS for BCM59056 PMU
In-Reply-To: <20250304-bcm59054-v6-3-ae8302358443@gmail.com>
References: <20250304-bcm59054-v6-0-ae8302358443@gmail.com> <20250304-bcm59054-v6-3-ae8302358443@gmail.com>
Message-ID: <20250317132922.2698513-1-florian.fainelli@broadcom.com>

From: Florian Fainelli <f.fainelli at gmail.com>

On Tue, 04 Mar 2025 07:20:34 +0100, Artur Weber <aweber.kernel at gmail.com> wrote:
> The BCM59056 PMU has its own separate DTSI, meant to be included
> in a DTS file after defining the pmu node on some I2C bus.
> 
> This seems rather unintuitive; drop the DTS in favor of adding the
> BCM59056 PMU node directly into the device DTS files.
> 
> If the amount of subdevices supported by the BCM590xx grows, and
> a common device tree turns out to be beneficial, it can be reintroduced
> in the future.
> 
> Signed-off-by: Artur Weber <aweber.kernel at gmail.com>
> ---

Applied to https://github.com/Broadcom/stblinux/commits/devicetree/next, thanks!
--
Florian


From daniel.baluta at nxp.com  Mon Mar 17 06:33:05 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:05 +0200
Subject: [PATCH v5 4/5] arm64: dts: imx8mp: Add DSP clocks
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <20250317133306.2003909-5-daniel.baluta@nxp.com>

DSP core needs ocram, core and debug clocks.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index cbe8dfa3b3bc..5a43c10d07f6 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -2418,6 +2418,11 @@ usb_dwc3_1: usb at 38200000 {
 		dsp: dsp at 3b6e8000 {
 			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
+			clocks = <&audio_blk_ctrl  IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_OCRAMA_IPG>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSPDBG_ROOT>;
+			clock-names = "ipg", "ocram", "core", "debug";
 			power-domains = <&pgc_audio>;
 			mbox-names = "tx", "rx", "rxdb";
 			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
-- 
2.43.0



From daniel.baluta at nxp.com  Mon Mar 17 06:33:06 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:06 +0200
Subject: [PATCH v5 5/5] arm64: dts: Add dsp rproc related mem regions
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <20250317133306.2003909-6-daniel.baluta@nxp.com>

With imx8mp-evk board we are now configuring 'dsp' node for rproc usage,
so add rproc specific memory regions.

Also, enable dsp node because it is ready to be used.

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index c26954e5a605..cd7ab74de2b3 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -309,6 +309,16 @@ &aud2htx {
 	status = "okay";
 };
 
+&dsp_reserved {
+	status = "okay";
+};
+
+&dsp {
+	memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
+			<&dsp_vdev0vring1>, <&dsp_reserved>;
+	status = "okay";
+};
+
 &eqos {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_eqos>;
-- 
2.43.0



From daniel.baluta at gmail.com  Mon Mar 17 06:36:17 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:36:17 +0200
Subject: [PATCH] ARM: dts: nxp: Align NAND controller node name with bindings
In-Reply-To: <20250317111853.43708-1-krzysztof.kozlowski@linaro.org>
References: <20250317111853.43708-1-krzysztof.kozlowski@linaro.org>
Message-ID: <CAEnQRZBorgPS+P8Yt8irKm=CTpbY3hUdkSpOK5if5xaTpzikuQ@mail.gmail.com>

On Mon, Mar 17, 2025 at 1:19?PM Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
>
> Bindings expect NAND controller device nodes to be named
> "nand-controller".
>
> Cc: Fabio Estevam <festevam at gmail.com>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Daniel Baluta <daniel.baluta at nxp.com>


From daniel.baluta at nxp.com  Mon Mar 17 06:33:01 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:01 +0200
Subject: [PATCH v5 0/5] Configure imx8mp dsp node for rproc usage
Message-ID: <20250317133306.2003909-1-daniel.baluta@nxp.com>

DSP found in i.MX8MP SOC can be used by multiple frameworks in order to
enable various applications:
        - rproc/rpmsg framework, used to load for example Zephyr samples
        - Sound Open Firmware, used to enable various audio processing
          pipelines.

Current dsp node was configured with SOF in mind but it doesn't work
well with imx8mp-evk dts. SOF controls audio IPs from firmware side
while imx8mp-evk.dts preffers to control audio IPs from Linux side.

So, configure 'dsp' node to be used with rproc scenario and later will
add a separate dts or an overlay to configure the node for SOF.

This patch series configures and enables dsp node to be used with rproc.

Changes since v4:
(https://lore.kernel.org/linux-arm-kernel/Z6zGLn3B6SVXhTV1 at lizhi-Precision-Tower-5810/T/)
	- after comments received on v4, we implemented the run/stall
	  bits using reset controller API (changes merged ->
https://patchwork.kernel.org/project/linux-arm-kernel/cover/20250311085812.1296243-1-daniel.baluta at nxp.com/)
        - drop patches related to DSP run/stall/reset via syscon
	- picked up patch related to using run_stall via reset
	  controller API.

Daniel Baluta (5):
  arm64: dts: imx8mp: Use resets property
  arm64: dts: imx8mp: Add mu2 root clock
  arm64: dts: imx8mp: Configure dsp node for rproc usage
  arm64: dts: imx8mp: Add DSP clocks
  arm64: dts: Add dsp rproc related mem regions

 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 10 +++++++++
 arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 22 +++++++++++++-------
 2 files changed, 25 insertions(+), 7 deletions(-)

-- 
2.43.0



From daniel.baluta at nxp.com  Mon Mar 17 06:33:02 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:02 +0200
Subject: [PATCH v5 1/5] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <20250317133306.2003909-2-daniel.baluta@nxp.com>

Add resets property to dsp node in order to be able to control the dsp
run/stall bit from audio block control.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index ce6793b2d57e..3b725fe442d0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/imx8mp-clock.h>
 #include <dt-bindings/power/imx8mp-power.h>
 #include <dt-bindings/reset/imx8mp-reset.h>
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interconnect/fsl,imx8mp.h>
@@ -2422,6 +2423,8 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+			reset-names = "runstall";
 			status = "disabled";
 		};
 	};
-- 
2.43.0



From daniel.baluta at nxp.com  Mon Mar 17 06:33:03 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:03 +0200
Subject: [PATCH v5 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <20250317133306.2003909-3-daniel.baluta@nxp.com>

Enable MU2 node and add mu2 root clock.
MU2 is used to communicate with DSP core.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 3b725fe442d0..5b443fbeded8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -1253,7 +1253,7 @@ mu2: mailbox at 30e60000 {
 				reg = <0x30e60000 0x10000>;
 				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
 				#mbox-cells = <2>;
-				status = "disabled";
+				clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_MU2_ROOT>;
 			};
 
 			i2c5: i2c at 30ad0000 {
-- 
2.43.0



From daniel.baluta at nxp.com  Mon Mar 17 06:33:04 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 15:33:04 +0200
Subject: [PATCH v5 3/5] arm64: dts: imx8mp: Configure dsp node for rproc usage
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <20250317133306.2003909-4-daniel.baluta@nxp.com>

DSP can be used with various frameworks (e.g audio firmware, rproc).
Currently 'dsp' configuration is intended for audio firmware but it
doesn't work well with board level DTs (e.g imx8mp-evk) because
board level DT enables audio related IPs (e.g SAI) while audio firmware
needs this IPs disabled (because firmware will configure them).

So, configure 'dsp' node to be used with rproc. This way users will be
able to use board DT to use the DSP as long as they don't clash with
Audio IP configurations.

More comples usage of 'dsp' node (e.g by audio firmware) will need to
create a separate dts file (or an overlay).

This change follows the approach taken for other i.MX8 boards
in commit 391a319c81f6d7 ("arm64: dts: imx8-ss-audio: configure dsp node
for rproc usage")

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 5b443fbeded8..cbe8dfa3b3bc 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -281,7 +281,7 @@ reserved-memory {
 		ranges;
 
 		dsp_reserved: dsp at 92400000 {
-			reg = <0 0x92400000 0 0x2000000>;
+			reg = <0 0x92400000 0 0x1000000>;
 			no-map;
 			status = "disabled";
 		};
@@ -2416,12 +2416,12 @@ usb_dwc3_1: usb at 38200000 {
 		};
 
 		dsp: dsp at 3b6e8000 {
-			compatible = "fsl,imx8mp-dsp";
+			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
-			mbox-names = "txdb0", "txdb1",
-				"rxdb0", "rxdb1";
-			mboxes = <&mu2 2 0>, <&mu2 2 1>,
-				<&mu2 3 0>, <&mu2 3 1>;
+			power-domains = <&pgc_audio>;
+			mbox-names = "tx", "rx", "rxdb";
+			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
+			firmware-name = "imx/dsp/hifi4.bin";
 			memory-region = <&dsp_reserved>;
 			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
 			reset-names = "runstall";
-- 
2.43.0



From jgg at nvidia.com  Mon Mar 17 06:35:00 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 17 Mar 2025 10:35:00 -0300
Subject: [PATCH v3 20/23] iommu: Update various drivers to pass in lg2sz
 instead of order to iommu pages
In-Reply-To: <Z9GFFBvUFg7a9WEg@google.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <20-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <Z9GFFBvUFg7a9WEg@google.com>
Message-ID: <20250317133500.GC9311@nvidia.com>

On Wed, Mar 12, 2025 at 12:59:00PM +0000, Mostafa Saleh wrote:
> > --- a/drivers/iommu/io-pgtable-arm.c
> > +++ b/drivers/iommu/io-pgtable-arm.c
> > @@ -263,14 +263,13 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
> >  				    void *cookie)
> >  {
> >  	struct device *dev = cfg->iommu_dev;
> > -	int order = get_order(size);
> >  	dma_addr_t dma;
> >  	void *pages;
> >  
> >  	if (cfg->alloc)
> >  		pages = cfg->alloc(cookie, size, gfp);
> >  	else
> > -		pages = iommu_alloc_pages_node(dev_to_node(dev), gfp, order);
> > +		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp, size);
> 
> Although, the current implementation of iommu_alloc_pages_node_sz() would round
> the size to order, but this is not correct according to the API definition
> "The returned allocation is round_up_pow_two(size) big, and is physically aligned
> to its size."

Yes.. The current implementation is limited to full PAGE_SIZE only,
the documentation imagines a future where it is not. Drivers should
ideally not assume the PAGE_SIZE limit during this conversion.

> I'd say we can align the size or use min with 64 bytes before calling the
> function would be enough (or change the API to state that allocations
> are rounded to order)

OK, like this:

	if (cfg->alloc) {
		pages = cfg->alloc(cookie, size, gfp);
	} else {
		/*
		 * For very small starting-level translation tables the HW
		 * requires a minimum alignment of at least 64 to cover all
		 * cases.
		 */
		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp,
						  max(size, 64));
	}

Thanks,
Jason


From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:28 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:28 +0100
Subject: [PATCH v4 3/7] arm64: dts: rockchip: Add thermal nodes to RK3576
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-3-c5029ce55d74@collabora.com>

Add the TSADC node to the RK3576. Additionally, add everything the TSADC
needs to function, i.e. thermal zones, their trip points and maps, as
well as adjust the CPU cooling-cells property.

The polling-delay properties are set to 0 as we do have interrupts for
this TSADC on this particular SoC.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3576.dtsi | 164 ++++++++++++++++++++++++++++++-
 1 file changed, 162 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
index ebb5fc8bb8b1363127b9d3782801c4a79b678a92..250dca23ff4fc1ab3bd47366829c5dd1738057fe 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/power/rockchip,rk3576-power.h>
 #include <dt-bindings/reset/rockchip,rk3576-cru.h>
 #include <dt-bindings/soc/rockchip,boot-mode.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "rockchip,rk3576";
@@ -113,9 +114,9 @@ cpu_l0: cpu at 0 {
 			capacity-dmips-mhz = <485>;
 			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
-			#cooling-cells = <2>;
 			dynamic-power-coefficient = <120>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_l1: cpu at 1 {
@@ -127,6 +128,7 @@ cpu_l1: cpu at 1 {
 			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_l2: cpu at 2 {
@@ -138,6 +140,7 @@ cpu_l2: cpu at 2 {
 			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_l3: cpu at 3 {
@@ -149,6 +152,7 @@ cpu_l3: cpu at 3 {
 			clocks = <&scmi_clk SCMI_ARMCLK_L>;
 			operating-points-v2 = <&cluster0_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_b0: cpu at 100 {
@@ -159,9 +163,9 @@ cpu_b0: cpu at 100 {
 			capacity-dmips-mhz = <1024>;
 			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
-			#cooling-cells = <2>;
 			dynamic-power-coefficient = <320>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_b1: cpu at 101 {
@@ -173,6 +177,7 @@ cpu_b1: cpu at 101 {
 			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_b2: cpu at 102 {
@@ -184,6 +189,7 @@ cpu_b2: cpu at 102 {
 			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		cpu_b3: cpu at 103 {
@@ -195,6 +201,7 @@ cpu_b3: cpu at 103 {
 			clocks = <&scmi_clk SCMI_ARMCLK_B>;
 			operating-points-v2 = <&cluster1_opp_table>;
 			cpu-idle-states = <&CPU_SLEEP>;
+			#cooling-cells = <2>;
 		};
 
 		idle-states {
@@ -436,6 +443,143 @@ psci {
 		method = "smc";
 	};
 
+	thermal_zones: thermal-zones {
+		/* sensor near the center of the SoC */
+		package_thermal: package-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				package_crit: package-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+		};
+
+		/* sensor for cluster1 (big Cortex-A72 cores) */
+		bigcore_thermal: bigcore-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				bigcore_alert: bigcore-alert {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				bigcore_crit: bigcore-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&bigcore_alert>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		/* sensor for cluster0 (little Cortex-A53 cores) */
+		littlecore_thermal: littlecore-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 2>;
+
+			trips {
+				littlecore_alert: littlecore-alert {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				littlecore_crit: littlecore-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&littlecore_alert>;
+					cooling-device =
+						<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu_thermal: gpu-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 3>;
+
+			trips {
+				gpu_alert: gpu-alert {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				gpu_crit: gpu-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert>;
+					cooling-device =
+						<&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		npu_thermal: npu-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 4>;
+
+			trips {
+				npu_crit: npu-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+		};
+
+		ddr_thermal: ddr-thermal {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsadc 5>;
+
+			trips {
+				ddr_crit: ddr-crit {
+					temperature = <115000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
@@ -1853,6 +1997,22 @@ saradc: adc at 2ae00000 {
 			status = "disabled";
 		};
 
+		tsadc: tsadc at 2ae70000 {
+			compatible = "rockchip,rk3576-tsadc";
+			reg = <0x0 0x2ae70000 0x0 0x400>;
+			interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>;
+			clock-names = "tsadc", "apb_pclk";
+			assigned-clocks = <&cru CLK_TSADC>;
+			assigned-clock-rates = <2000000>;
+			resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>;
+			reset-names = "tsadc-apb", "tsadc";
+			#thermal-sensor-cells = <1>;
+			rockchip,hw-tshut-temp = <120000>;
+			rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
+			rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
+		};
+
 		i2c9: i2c at 2ae80000 {
 			compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
 			reg = <0x0 0x2ae80000 0x0 0x1000>;

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:29 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:29 +0100
Subject: [PATCH v4 4/7] thermal: rockchip: Support RK3576 SoC in the
 thermal driver
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-4-c5029ce55d74@collabora.com>

From: Ye Zhang <ye.zhang at rock-chips.com>

The RK3576 SoC has six TS-ADC channels: TOP, BIG_CORE, LITTLE_CORE,
DDR, NPU and GPU.

Signed-off-by: Ye Zhang <ye.zhang at rock-chips.com>
[ported to mainline, reworded commit message]
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 drivers/thermal/rockchip_thermal.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 40c7d234c3ef99f69dd8db4d8c47f9d493c0583d..89e3180667e2a8f0ef5542b0db4d9e19a21a24d3 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -1284,6 +1284,28 @@ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
 	},
 };
 
+static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
+	/* top, big_core, little_core, ddr, npu, gpu */
+	.chn_offset = 0,
+	.chn_num = 6, /* six channels for tsadc */
+	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
+	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
+	.tshut_temp = 95000,
+	.initialize = rk_tsadcv8_initialize,
+	.irq_ack = rk_tsadcv4_irq_ack,
+	.control = rk_tsadcv4_control,
+	.get_temp = rk_tsadcv4_get_temp,
+	.set_alarm_temp = rk_tsadcv3_alarm_temp,
+	.set_tshut_temp = rk_tsadcv3_tshut_temp,
+	.set_tshut_mode = rk_tsadcv4_tshut_mode,
+	.table = {
+		.id = rk3588_code_table,
+		.length = ARRAY_SIZE(rk3588_code_table),
+		.data_mask = TSADCV4_DATA_MASK,
+		.mode = ADC_INCREMENT,
+	},
+};
+
 static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
 	/* top, big_core0, big_core1, little_core, center, gpu, npu */
 	.chn_offset = 0,
@@ -1342,6 +1364,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
 		.compatible = "rockchip,rk3568-tsadc",
 		.data = (void *)&rk3568_tsadc_data,
 	},
+	{
+		.compatible = "rockchip,rk3576-tsadc",
+		.data = (void *)&rk3576_tsadc_data,
+	},
 	{
 		.compatible = "rockchip,rk3588-tsadc",
 		.data = (void *)&rk3588_tsadc_data,

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:30 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:30 +0100
Subject: [PATCH v4 5/7] dt-bindings: thermal: rockchip: document otp
 thermal trim
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-5-c5029ce55d74@collabora.com>

Several Rockchip SoCs, such as the RK3576, can store calibration trim
data for thermal sensors in OTP cells. This capability should be
documented.

Such a rockchip thermal sensor may reference cell handles that store
both a chip-wide trim for all the sensors, as well as cell handles
for each individual sensor channel pointing to that specific sensor's
trim value.

Additionally, the thermal sensor may optionally reference cells which
store the base in terms of degrees celsius and decicelsius that the trim
is relative to.

Each SoC that implements this appears to have a slightly different
combination of chip-wide trim, base, base fractional part and
per-channel trim, so which ones do which is documented in the bindings.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 .../bindings/thermal/rockchip-thermal.yaml         | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
index 49ceed68c92ce5a32ed8d4f39bd88fd052de0e80..573f447cc26ed7100638277598b0e745d436fd01 100644
--- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
@@ -40,6 +40,17 @@ properties:
       - const: tsadc
       - const: apb_pclk
 
+  nvmem-cells:
+    items:
+      - description: cell handle to where the trim's base temperature is stored
+      - description:
+          cell handle to where the trim's tenths of Celsius base value is stored
+
+  nvmem-cell-names:
+    items:
+      - const: trim_base
+      - const: trim_base_frac
+
   resets:
     minItems: 1
     maxItems: 3
@@ -51,6 +62,12 @@ properties:
       - const: tsadc
       - const: tsadc-phy
 
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
   "#thermal-sensor-cells":
     const: 1
 
@@ -72,6 +89,27 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum: [0, 1]
 
+patternProperties:
+  "@[0-9a-f]+$":
+    type: object
+    properties:
+      reg:
+        maxItems: 1
+        description: sensor ID, a.k.a. channel number
+
+      nvmem-cells:
+        items:
+          - description: handle of cell containing calibration data
+
+      nvmem-cell-names:
+        items:
+          - const: trim
+
+    required:
+      - reg
+
+    unevaluatedProperties: false
+
 required:
   - compatible
   - reg
@@ -80,6 +118,29 @@ required:
   - clock-names
   - resets
 
+allOf:
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              const: rockchip,rk3568-tsadc
+    then:
+      properties:
+        nvmem-cells: false
+        nvmem-cell-names: false
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - rockchip,rk3568-tsadc
+                - rockchip,rk3576-tsadc
+    then:
+      patternProperties:
+        "@[0-9a-f]+$": false
+
 unevaluatedProperties: false
 
 examples:

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:31 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:31 +0100
Subject: [PATCH v4 6/7] arm64: dts: rockchip: Add thermal trim OTP and
 tsadc nodes
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-6-c5029ce55d74@collabora.com>

Thanks to Heiko's work getting OTP working on the RK3576, we can specify
the thermal sensor trim values which are stored there now, and with my
driver addition to rockchip_thermal, we can make use of these.

Add them to the devicetree for the SoC.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3576.dtsi | 57 ++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
index 250dca23ff4fc1ab3bd47366829c5dd1738057fe..6adfa0bfbe9e7ee03f4f516ff91b5c67e5c8346d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -1600,6 +1600,30 @@ gpu_leakage: gpu-leakage at 21 {
 			log_leakage: log-leakage at 22 {
 				reg = <0x22 0x1>;
 			};
+			bigcore_tsadc_trim: bigcore-tsadc-trim at 24 {
+				reg = <0x24 0x2>;
+				bits = <0 10>;
+			};
+			litcore_tsadc_trim: litcore-tsadc-trim at 26 {
+				reg = <0x26 0x2>;
+				bits = <0 10>;
+			};
+			ddr_tsadc_trim: ddr-tsadc-trim at 28 {
+				reg = <0x28 0x2>;
+				bits = <0 10>;
+			};
+			npu_tsadc_trim: npu-tsadc-trim at 2a {
+				reg = <0x2a 0x2>;
+				bits = <0 10>;
+			};
+			gpu_tsadc_trim: gpu-tsadc-trim at 2c {
+				reg = <0x2c 0x2>;
+				bits = <0 10>;
+			};
+			soc_tsadc_trim: soc-tsadc-trim at 64 {
+				reg = <0x64 0x2>;
+				bits = <0 10>;
+			};
 		};
 
 		gic: interrupt-controller at 2a701000 {
@@ -2011,6 +2035,39 @@ tsadc: tsadc at 2ae70000 {
 			rockchip,hw-tshut-temp = <120000>;
 			rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
 			rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			sensor at 0 {
+				reg = <0>;
+				nvmem-cells = <&soc_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
+			sensor at 1 {
+				reg = <1>;
+				nvmem-cells = <&bigcore_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
+			sensor at 2 {
+				reg = <2>;
+				nvmem-cells = <&litcore_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
+			sensor at 3 {
+				reg = <3>;
+				nvmem-cells = <&ddr_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
+			sensor at 4 {
+				reg = <4>;
+				nvmem-cells = <&npu_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
+			sensor at 5 {
+				reg = <5>;
+				nvmem-cells = <&gpu_tsadc_trim>;
+				nvmem-cell-names = "trim";
+			};
 		};
 
 		i2c9: i2c at 2ae80000 {

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:32 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:32 +0100
Subject: [PATCH v4 7/7] thermal: rockchip: support reading trim values from
 OTP
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-7-c5029ce55d74@collabora.com>

Many of the Rockchip SoCs support storing trim values for the sensors in
factory programmable memory. These values specify a fixed offset from
the sensor's returned temperature to get a more accurate picture of what
temperature the silicon is actually at.

The way this is implemented is with various OTP cells, which may be
absent. There may both be whole-TSADC trim values, as well as per-sensor
trim values.

In the downstream driver, whole-chip trim values override the per-sensor
trim values. This rewrite of the functionality changes the semantics to
something I see as slightly more useful: allow the whole-chip trim
values to serve as a fallback for lacking per-sensor trim values,
instead of overriding already present sensor trim values.

Additionally, the chip may specify an offset (trim_base, trim_base_frac)
in degrees celsius and degrees decicelsius respectively which defines
what the basis is from which the trim, if any, should be calculated
from. By default, this is 30 degrees Celsius, but the chip can once
again specify a different value through OTP cells.

The implementation of these trim calculations have been tested
extensively on an RK3576, where it was confirmed to get rid of pesky 1.8
degree Celsius offsets between certain sensors.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 drivers/thermal/rockchip_thermal.c | 221 +++++++++++++++++++++++++++++++++----
 1 file changed, 202 insertions(+), 19 deletions(-)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 89e3180667e2a8f0ef5542b0db4d9e19a21a24d3..3beff9b6fac3abe8948b56132b618ff1bed57217 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -69,16 +70,18 @@ struct chip_tsadc_table {
  * struct rockchip_tsadc_chip - hold the private data of tsadc chip
  * @chn_offset: the channel offset of the first channel
  * @chn_num: the channel number of tsadc chip
- * @tshut_temp: the hardware-controlled shutdown temperature value
+ * @trim_slope: used to convert the trim code to a temperature in millicelsius
+ * @tshut_temp: the hardware-controlled shutdown temperature value, with no trim
  * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
  * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
  * @initialize: SoC special initialize tsadc controller method
  * @irq_ack: clear the interrupt
  * @control: enable/disable method for the tsadc controller
- * @get_temp: get the temperature
+ * @get_temp: get the raw temperature, unadjusted by trim
  * @set_alarm_temp: set the high temperature interrupt
  * @set_tshut_temp: set the hardware-controlled shutdown temperature
  * @set_tshut_mode: set the hardware-controlled shutdown mode
+ * @get_trim_code: convert a hardware temperature code to one adjusted for by trim
  * @table: the chip-specific conversion table
  */
 struct rockchip_tsadc_chip {
@@ -86,6 +89,9 @@ struct rockchip_tsadc_chip {
 	int chn_offset;
 	int chn_num;
 
+	/* Used to convert trim code to trim temp */
+	int trim_slope;
+
 	/* The hardware-controlled tshut property */
 	int tshut_temp;
 	enum tshut_mode tshut_mode;
@@ -105,6 +111,8 @@ struct rockchip_tsadc_chip {
 	int (*set_tshut_temp)(const struct chip_tsadc_table *table,
 			      int chn, void __iomem *reg, int temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
+	int (*get_trim_code)(const struct chip_tsadc_table *table,
+			     int code, int trim_base, int trim_base_frac);
 
 	/* Per-table methods */
 	struct chip_tsadc_table table;
@@ -114,12 +122,16 @@ struct rockchip_tsadc_chip {
  * struct rockchip_thermal_sensor - hold the information of thermal sensor
  * @thermal:  pointer to the platform/configuration data
  * @tzd: pointer to a thermal zone
+ * @of_node: pointer to the device_node representing this sensor, if any
  * @id: identifier of the thermal sensor
+ * @trim_temp: per-sensor trim temperature value
  */
 struct rockchip_thermal_sensor {
 	struct rockchip_thermal_data *thermal;
 	struct thermal_zone_device *tzd;
+	struct device_node *of_node;
 	int id;
+	int trim_temp;
 };
 
 /**
@@ -132,7 +144,11 @@ struct rockchip_thermal_sensor {
  * @pclk: the advanced peripherals bus clock
  * @grf: the general register file will be used to do static set by software
  * @regs: the base address of tsadc controller
- * @tshut_temp: the hardware-controlled shutdown temperature value
+ * @trim_base: major component of sensor trim value, in Celsius
+ * @trim_base_frac: minor component of sensor trim value, in Decicelsius
+ * @trim: fallback thermal trim value for each channel
+ * @tshut_temp: the hardware-controlled shutdown temperature value, with no trim
+ * @trim_temp: the fallback trim temperature for the whole sensor
  * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
  * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
  */
@@ -149,7 +165,12 @@ struct rockchip_thermal_data {
 	struct regmap *grf;
 	void __iomem *regs;
 
+	int trim_base;
+	int trim_base_frac;
+	int trim;
+
 	int tshut_temp;
+	int trim_temp;
 	enum tshut_mode tshut_mode;
 	enum tshut_polarity tshut_polarity;
 };
@@ -249,6 +270,9 @@ struct rockchip_thermal_data {
 
 #define GRF_CON_TSADC_CH_INV			(0x10001 << 1)
 
+
+#define RK_MAX_TEMP				(180000)
+
 /**
  * struct tsadc_table - code to temperature conversion table
  * @code: the value of adc channel
@@ -1061,6 +1085,15 @@ static void rk_tsadcv4_tshut_mode(int chn, void __iomem *regs,
 	writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
 }
 
+static int rk_tsadcv2_get_trim_code(const struct chip_tsadc_table *table,
+				    int code, int trim_base, int trim_base_frac)
+{
+	int temp = trim_base * 1000 + trim_base_frac * 100;
+	u32 base_code = rk_tsadcv2_temp_to_code(table, temp);
+
+	return code - base_code;
+}
+
 static const struct rockchip_tsadc_chip px30_tsadc_data = {
 	/* cpu, gpu */
 	.chn_offset = 0,
@@ -1298,6 +1331,8 @@ static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
 	.set_alarm_temp = rk_tsadcv3_alarm_temp,
 	.set_tshut_temp = rk_tsadcv3_tshut_temp,
 	.set_tshut_mode = rk_tsadcv4_tshut_mode,
+	.get_trim_code = rk_tsadcv2_get_trim_code,
+	.trim_slope = 923,
 	.table = {
 		.id = rk3588_code_table,
 		.length = ARRAY_SIZE(rk3588_code_table),
@@ -1413,7 +1448,7 @@ static int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, i
 		__func__, sensor->id, low, high);
 
 	return tsadc->set_alarm_temp(&tsadc->table,
-				     sensor->id, thermal->regs, high);
+				     sensor->id, thermal->regs, high + sensor->trim_temp);
 }
 
 static int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp)
@@ -1425,6 +1460,8 @@ static int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_te
 
 	retval = tsadc->get_temp(&tsadc->table,
 				 sensor->id, thermal->regs, out_temp);
+	*out_temp -= sensor->trim_temp;
+
 	return retval;
 }
 
@@ -1433,6 +1470,104 @@ static const struct thermal_zone_device_ops rockchip_of_thermal_ops = {
 	.set_trips = rockchip_thermal_set_trips,
 };
 
+/**
+ * rockchip_get_efuse_value - read an OTP cell from a device node
+ * @np: pointer to the device node with the nvmem-cells property
+ * @cell_name: name of cell that should be read
+ * @value: pointer to where the read value will be placed
+ *
+ * Return: Negative errno on failure, during which *value will not be touched,
+ * or 0 on success.
+ */
+static int rockchip_get_efuse_value(struct device_node *np, const char *cell_name,
+				    int *value)
+{
+	struct nvmem_cell *cell;
+	int ret = 0;
+	size_t len;
+	u8 *buf;
+	int i;
+
+	cell = of_nvmem_cell_get(np, cell_name);
+	if (IS_ERR(cell))
+		return PTR_ERR(cell);
+
+	buf = nvmem_cell_read(cell, &len);
+
+	nvmem_cell_put(cell);
+
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
+
+	if (len > sizeof(*value)) {
+		ret = -ERANGE;
+		goto exit;
+	}
+
+	/* Copy with implicit endian conversion */
+	*value = 0;
+	for (i = 0; i < len; i++)
+		*value |= (int) buf[i] << (8 * i);
+
+exit:
+	kfree(buf);
+	return ret;
+}
+
+static int rockchip_get_trim_configuration(struct device *dev, struct device_node *np,
+					   struct rockchip_thermal_data *thermal)
+{
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+	int trim_base = 0, trim_base_frac = 0, trim = 0;
+	int trim_code;
+	int ret;
+
+	thermal->trim_base = 0;
+	thermal->trim_base_frac = 0;
+	thermal->trim = 0;
+
+	if (!tsadc->get_trim_code)
+		return 0;
+
+	ret = rockchip_get_efuse_value(np, "trim_base", &trim_base);
+	if (ret < 0) {
+		if (ret == -ENOENT) {
+			trim_base = 30;
+			dev_dbg(dev, "trim_base is absent, defaulting to 30\n");
+		} else {
+			dev_err(dev, "failed reading nvmem value of trim_base: %pe\n",
+				ERR_PTR(ret));
+			return ret;
+		}
+	}
+	ret = rockchip_get_efuse_value(np, "trim_base_frac", &trim_base_frac);
+	if (ret < 0) {
+		if (ret == -ENOENT) {
+			dev_dbg(dev, "trim_base_frac is absent, defaulting to 0\n");
+		} else {
+			dev_err(dev, "failed reading nvmem value of trim_base_frac: %pe\n",
+				ERR_PTR(ret));
+			return ret;
+		}
+	}
+	thermal->trim_base = trim_base;
+	thermal->trim_base_frac = trim_base_frac;
+
+	/*
+	 * If the tsadc node contains the trim property, then it is used in the
+	 * absence of per-channel trim values
+	 */
+	if (!rockchip_get_efuse_value(np, "trim", &trim))
+		thermal->trim = trim;
+	if (trim) {
+		trim_code = tsadc->get_trim_code(&tsadc->table, trim,
+						 trim_base, trim_base_frac);
+		thermal->trim_temp = thermal->chip->trim_slope * trim_code;
+	}
+
+	return 0;
+}
+
 static int rockchip_configure_from_dt(struct device *dev,
 				      struct device_node *np,
 				      struct rockchip_thermal_data *thermal)
@@ -1493,6 +1628,8 @@ static int rockchip_configure_from_dt(struct device *dev,
 	if (IS_ERR(thermal->grf))
 		dev_warn(dev, "Missing rockchip,grf property\n");
 
+	rockchip_get_trim_configuration(dev, np, thermal);
+
 	return 0;
 }
 
@@ -1503,23 +1640,50 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
 				 int id)
 {
 	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+	struct device *dev = &pdev->dev;
+	int trim = thermal->trim;
+	int trim_code, tshut_temp;
+	int trim_temp = 0;
 	int error;
 
+	if (thermal->trim_temp)
+		trim_temp = thermal->trim_temp;
+
+	if (tsadc->get_trim_code && sensor->of_node) {
+		error = rockchip_get_efuse_value(sensor->of_node, "trim", &trim);
+		if (error < 0 && error != -ENOENT) {
+			dev_err(dev, "failed reading trim of sensor %d: %pe\n",
+				id, ERR_PTR(error));
+			return error;
+		}
+		if (trim) {
+			trim_code = tsadc->get_trim_code(&tsadc->table, trim,
+							 thermal->trim_base,
+							 thermal->trim_base_frac);
+			trim_temp = thermal->chip->trim_slope * trim_code;
+		}
+	}
+
+	sensor->trim_temp = trim_temp;
+
+	dev_dbg(dev, "trim of sensor %d is %d\n", id, sensor->trim_temp);
+
+	tshut_temp = min(thermal->tshut_temp + sensor->trim_temp, RK_MAX_TEMP);
+
 	tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
 
-	error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
-			      thermal->tshut_temp);
+	error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, tshut_temp);
 	if (error)
-		dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
-			__func__, thermal->tshut_temp, error);
+		dev_err(dev, "%s: invalid tshut=%d, error=%d\n",
+			__func__, tshut_temp, error);
 
 	sensor->thermal = thermal;
 	sensor->id = id;
-	sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, id, sensor,
+	sensor->tzd = devm_thermal_of_zone_register(dev, id, sensor,
 						    &rockchip_of_thermal_ops);
 	if (IS_ERR(sensor->tzd)) {
 		error = PTR_ERR(sensor->tzd);
-		dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
+		dev_err(dev, "failed to register sensor %d: %d\n",
 			id, error);
 		return error;
 	}
@@ -1542,9 +1706,11 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct rockchip_thermal_data *thermal;
+	struct device_node *child;
 	int irq;
 	int i;
 	int error;
+	u32 chn;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -1595,6 +1761,18 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
 	thermal->chip->initialize(thermal->grf, thermal->regs,
 				  thermal->tshut_polarity);
 
+	for_each_available_child_of_node(np, child) {
+		if (!of_property_read_u32(child, "reg", &chn)) {
+			if (chn < thermal->chip->chn_num)
+				thermal->sensors[chn].of_node = child;
+			else
+				dev_warn(&pdev->dev,
+					 "sensor address (%d) too large, ignoring its trim\n",
+					 chn);
+		}
+
+	}
+
 	for (i = 0; i < thermal->chip->chn_num; i++) {
 		error = rockchip_thermal_register_sensor(pdev, thermal,
 						&thermal->sensors[i],
@@ -1664,8 +1842,11 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
 static int __maybe_unused rockchip_thermal_resume(struct device *dev)
 {
 	struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
-	int i;
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+	struct rockchip_thermal_sensor *sensor;
+	int tshut_temp;
 	int error;
+	int i;
 
 	error = clk_enable(thermal->clk);
 	if (error)
@@ -1679,21 +1860,23 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
 
 	rockchip_thermal_reset_controller(thermal->reset);
 
-	thermal->chip->initialize(thermal->grf, thermal->regs,
-				  thermal->tshut_polarity);
+	tsadc->initialize(thermal->grf, thermal->regs, thermal->tshut_polarity);
 
 	for (i = 0; i < thermal->chip->chn_num; i++) {
-		int id = thermal->sensors[i].id;
+		sensor = &thermal->sensors[i];
+
+		tshut_temp = min(thermal->tshut_temp + sensor->trim_temp,
+				 RK_MAX_TEMP);
 
-		thermal->chip->set_tshut_mode(id, thermal->regs,
+		tsadc->set_tshut_mode(sensor->id, thermal->regs,
 					      thermal->tshut_mode);
 
-		error = thermal->chip->set_tshut_temp(&thermal->chip->table,
-					      id, thermal->regs,
-					      thermal->tshut_temp);
+		error = tsadc->set_tshut_temp(&thermal->chip->table,
+					      sensor->id, thermal->regs,
+					      tshut_temp);
 		if (error)
 			dev_err(dev, "%s: invalid tshut=%d, error=%d\n",
-				__func__, thermal->tshut_temp, error);
+				__func__, tshut_temp, error);
 	}
 
 	thermal->chip->control(thermal->regs, true);

-- 
2.48.1



From csokas.bence at prolan.hu  Mon Mar 17 06:53:38 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 17 Mar 2025 14:53:38 +0100
Subject: [PATCH v4 2/2] spi: atmel-quadspi: Use `devm_dma_request_chan()`
In-Reply-To: <20250317135340.382532-1-csokas.bence@prolan.hu>
References: <20250317135340.382532-1-csokas.bence@prolan.hu>
Message-ID: <20250317135340.382532-3-csokas.bence@prolan.hu>

Leave releasing of DMA channels up to the devm facilities. This way we can
eliminate the rest of the "goto ladder".

Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---
 drivers/spi/atmel-quadspi.c | 44 ++++++++++---------------------------
 1 file changed, 11 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index ddd12600a6f1..8a950a20b58a 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1288,18 +1288,20 @@ static int atmel_qspi_dma_init(struct spi_controller *ctrl)
 	struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
 	int ret;
 
-	aq->rx_chan = dma_request_chan(&aq->pdev->dev, "rx");
+	aq->rx_chan = devm_dma_request_chan(&aq->pdev->dev, "rx");
 	if (IS_ERR(aq->rx_chan)) {
 		aq->rx_chan = NULL;
 		return dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->rx_chan),
 				     "RX DMA channel is not available\n");
 	}
 
-	aq->tx_chan = dma_request_chan(&aq->pdev->dev, "tx");
+	aq->tx_chan = devm_dma_request_chan(&aq->pdev->dev, "tx");
 	if (IS_ERR(aq->tx_chan)) {
 		ret = dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->tx_chan),
 				    "TX DMA channel is not available\n");
-		goto release_rx_chan;
+		aq->rx_chan = NULL;
+		aq->tx_chan = NULL;
+		return ret;
 	}
 
 	ctrl->dma_rx = aq->rx_chan;
@@ -1310,20 +1312,6 @@ static int atmel_qspi_dma_init(struct spi_controller *ctrl)
 		 dma_chan_name(aq->tx_chan), dma_chan_name(aq->rx_chan));
 
 	return 0;
-
-release_rx_chan:
-	dma_release_channel(aq->rx_chan);
-	aq->rx_chan = NULL;
-	aq->tx_chan = NULL;
-	return ret;
-}
-
-static void atmel_qspi_dma_release(struct atmel_qspi *aq)
-{
-	if (aq->rx_chan)
-		dma_release_channel(aq->rx_chan);
-	if (aq->tx_chan)
-		dma_release_channel(aq->tx_chan);
 }
 
 static const struct atmel_qspi_ops atmel_qspi_ops = {
@@ -1428,14 +1416,13 @@ static int atmel_qspi_probe(struct platform_device *pdev)
 
 	/* Request the IRQ */
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		err = irq;
-		goto dma_release;
-	}
+	if (irq < 0)
+		return irq;
+
 	err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt,
 			       0, dev_name(&pdev->dev), aq);
 	if (err)
-		goto dma_release;
+		return err;
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
 	pm_runtime_use_autosuspend(&pdev->dev);
@@ -1445,22 +1432,16 @@ static int atmel_qspi_probe(struct platform_device *pdev)
 
 	err = atmel_qspi_init(aq);
 	if (err)
-		goto dma_release;
+		return err;
 
 	err = spi_register_controller(ctrl);
 	if (err)
-		goto dma_release;
+		return err;
 
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
 
 	return 0;
-
-dma_release:
-	if (aq->caps->has_dma)
-		atmel_qspi_dma_release(aq);
-
-	return err;
 }
 
 static int atmel_qspi_sama7g5_suspend(struct atmel_qspi *aq)
@@ -1510,9 +1491,6 @@ static void atmel_qspi_remove(struct platform_device *pdev)
 
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret >= 0) {
-		if (aq->caps->has_dma)
-			atmel_qspi_dma_release(aq);
-
 		if (aq->caps->has_gclk) {
 			ret = atmel_qspi_sama7g5_suspend(aq);
 			if (ret)
-- 
2.48.1




From nayabbasha.sayed at microchip.com  Mon Mar 17 06:31:08 2025
From: nayabbasha.sayed at microchip.com (Nayab Sayed)
Date: Mon, 17 Mar 2025 19:01:08 +0530
Subject: [PATCH RESEND] dt-bindings: mtd: atmel,dataflash: convert txt to
 yaml
Message-ID: <20250317-atmel-dataflash-v1-1-1a3247f40299@microchip.com>

Convert atmel-dataflash.txt into atmel,dataflash.yaml

Signed-off-by: Nayab Sayed <nayabbasha.sayed at microchip.com>
---
 .../devicetree/bindings/mtd/atmel,dataflash.yaml   | 55 ++++++++++++++++++++++
 .../devicetree/bindings/mtd/atmel-dataflash.txt    | 17 -------
 2 files changed, 55 insertions(+), 17 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/atmel,dataflash.yaml b/Documentation/devicetree/bindings/mtd/atmel,dataflash.yaml
new file mode 100644
index 000000000000..8c72fa346e36
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/atmel,dataflash.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/atmel,dataflash.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Atmel DataFlash
+
+maintainers:
+  - Nayab Sayed <nayabbasha.sayed at microchip.com>
+
+description:
+  The Atmel DataFlash is a low pin-count serial interface sequential access
+  Flash memory, compatible with SPI standard. The device tree may optionally
+  contain sub-nodes describing partitions of the address space.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - atmel,at45db321d
+              - atmel,at45db041e
+              - atmel,at45db642d
+              - atmel,at45db021d
+          - const: atmel,at45
+          - const: atmel,dataflash
+      - items:
+          - const: atmel,at45
+          - const: atmel,dataflash
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+allOf:
+  - $ref: mtd.yaml#
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        flash at 1 {
+            compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+            reg = <1>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt b/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
deleted file mode 100644
index 1889a4db5b7c..000000000000
--- a/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-* Atmel Data Flash
-
-Required properties:
-- compatible : "atmel,<model>", "atmel,<series>", "atmel,dataflash".
-
-The device tree may optionally contain sub-nodes describing partitions of the
-address space. See partition.txt for more detail.
-
-Example:
-
-flash at 1 {
-	#address-cells = <1>;
-	#size-cells = <1>;
-	compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
-	spi-max-frequency = <25000000>;
-	reg = <1>;
-};

---
base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
change-id: 20250317-atmel-dataflash-941cebc942ae

Best regards,
-- 
Nayab Sayed <nayabbasha.sayed at microchip.com>



From krzk at kernel.org  Mon Mar 17 06:41:55 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 14:41:55 +0100
Subject: [PATCH v3] ARM: dts: imx51-digi-connectcore-som: Fix MMA7455
 compatible
In-Reply-To: <20250317123109.2216509-1-festevam@gmail.com>
References: <20250317123109.2216509-1-festevam@gmail.com>
Message-ID: <2dc9de96-234c-4c5f-9f72-8e1d0e8a8c86@kernel.org>

On 17/03/2025 13:31, Fabio Estevam wrote:
> From: Fabio Estevam <festevam at denx.de>
> 
> The "fsl,mma7455l" compatible string is not documented anywhere.
> 
> MMA7455L is the exact same device as the MMA7455, with the exception that
> it is lead-free. Use the documented compatible string.
> 
> Signed-off-by: Fabio Estevam <festevam at denx.de>

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From boris.brezillon at collabora.com  Mon Mar 17 06:44:36 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 17 Mar 2025 14:44:36 +0100
Subject: [PATCH v3 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250317124044.16257-5-ariel.dalessandro@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
	<20250317124044.16257-5-ariel.dalessandro@collabora.com>
Message-ID: <20250317144436.2bcc17ed@collabora.com>

On Mon, 17 Mar 2025 09:40:42 -0300
Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:

> +static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
> +				  enum io_pgtable_fmt fmt)
> +{
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	switch (fmt) {
> +	case ARM_64_LPAE_S1:
> +		return mmu_cfg_init_aarch64_4k(mmu);
> +	case ARM_MALI_LPAE:
> +		return mmu_cfg_init_mali_lpae(mmu);
> +	default:
> +		/* This should never happen */
> +		return drm_WARN_ON(pfdev->ddev, -EINVAL);

This won't return -EINVAL, but !!(-EINVAL), AKA true. We should do

	default:
		drm_WARN(ptdev->ddev, "Invalid pgtable format");
		return -EINVAL;

instead.

> +	}
> +}


From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:26 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:26 +0100
Subject: [PATCH v4 1/7] thermal: rockchip: rename rk_tsadcv3_tshut_mode
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-1-c5029ce55d74@collabora.com>

The "v" version specifier here refers to the hardware IP revision.
Mainline deviated from downstream here by calling the v4 revision v3 as
it didn't support the v3 hardware revision at all.

This creates needless confusion, so rename it to rk_tsadcv4_tshut_mode
to be consistent with what the hardware wants to be called.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 drivers/thermal/rockchip_thermal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index a8ad85feb68fbb7ec8d79602b16c47838ecb3c00..40c7d234c3ef99f69dd8db4d8c47f9d493c0583d 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -1045,7 +1045,7 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
 	writel_relaxed(val, regs + TSADCV2_INT_EN);
 }
 
-static void rk_tsadcv3_tshut_mode(int chn, void __iomem *regs,
+static void rk_tsadcv4_tshut_mode(int chn, void __iomem *regs,
 				  enum tshut_mode mode)
 {
 	u32 val_gpio, val_cru;
@@ -1297,7 +1297,7 @@ static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
 	.get_temp = rk_tsadcv4_get_temp,
 	.set_alarm_temp = rk_tsadcv3_alarm_temp,
 	.set_tshut_temp = rk_tsadcv3_tshut_temp,
-	.set_tshut_mode = rk_tsadcv3_tshut_mode,
+	.set_tshut_mode = rk_tsadcv4_tshut_mode,
 	.table = {
 		.id = rk3588_code_table,
 		.length = ARRAY_SIZE(rk3588_code_table),

-- 
2.48.1



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:25 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:25 +0100
Subject: [PATCH v4 0/7] RK3576 thermal sensor support, including OTP trim
 adjustments
Message-ID: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>

This series adds support for the RK3576's thermal sensor.

The sensor has six channels, providing measurements for the package
temperature, the temperature of the big cores, the temperature of the
little cores, and the GPU, NPU and DDR controller.

In addition to adding support for the sensor itself, the series also
adds support for reading thermal trim values out of the device tree.
Most of this functionality is not specific to this SoC, but needed to be
implemented to make the sensors a little more accurate in order to
investigate whether the TRM swapped GPU and DDR or downstream swapped
GPU and DDR in terms of channel IDs, as downstream disagrees with what's
in the TRM, and the difference is so small and hard to pin down with
testing that the constant offset between the two sensors was a little
annoying for me to deal with.

I ended up going with the channel assignment the TRM lists, as I see the
DDR sensor get a larger deviation from baseline temperatures during memory
stress tests (stress-ng --memrate 8 --memrate-flush) than what the TRM
claims is the GPU sensor but downstream claims is the DDR sensor. Input
from Rockchip engineers on whether the TRM is right or wrong welcome.

The trim functionality is only used by RK3576 at the moment. Code to
handle other SoCs can rely on the shared otp reading and perhaps even
the IP revision specific function, but may need its own IP revision
specific functions added as well. Absent trim functionality in other
SoCs should not interfere with the modified common code paths.

Patch 1 is a cleanup patch for the rockchip thermal driver, where a
function was confusingly named.

Patch 2 adds the RK3576 compatible to the bindings.

Patch 3 adds the basic thermal nodes required to get temperature
readings and device throttling to the rk3576.dtsi device tree.

Patch 4 adds support for this SoC's thermal chip to the driver. It is a
port of the downstream commit adding support for this.

Patch 5 adds some documentation for imminent additional functionality to
the binding, namely the trim value stuff.

Patch 6 adds the requisite OTP cells and tsadc nodes to the SoC's device
tree, conforming with the bindings modified in Patch 5.

Patch 7 adds support for reading these OTP values in the
rockchip_thermal driver, and makes use of them. The code is mostly new
upstream code written by me, using downstream code as reference.

For the record, here's a listing of SoCs that implement the OTP trim
functionality in some variation, with a legend that is as follows:
- A = chip-wide trim value
- B = trim_base value
- C = trim_base_frac value
- D = per-channel trim value
- E = compatible is either in mainline or in this series

The list is as follows:
- RK3502 (A____)
- RK3528 (A____)
- RK3562 (ABC__)
- RK3566 (_BCDE)
- RK3568 (_BCDE)
- RK3576 (___DE) <- the only one we're adding OTP trim for here atm
- RV1126 (AB___)

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
Changes in v4:
- driver: added a patch to rename tsadcv3_tshut_mode to
  tsadcv4_tshut_mode, as per Jonas' suggestion, and drop the duplicated
  function from the RK3576 support patch.
- Link to v3: https://lore.kernel.org/r/20250228-rk3576-tsadc-upstream-v3-0-4bfbb3b699b9 at collabora.com

Changes in v3:
- Changed bindings back to using patternProperties, as per Rob's
  suggestions
- Adjusted dts changes to comply with the new schema
- Link to v2: https://lore.kernel.org/r/20250225-rk3576-tsadc-upstream-v2-0-6eb7b00de89c at collabora.com

Changes in v2:
- As per Rob's request, the bindings now only feature the new properties
  depending on the compatible. Since the combination is slightly
  different for each SoC anyway, this makes future work easier too.
- The different channels are now explicitly named, instead of giving
  them patternProperties names. This is once again per-compatible.
- As per Sebastian's suggestion, unified trim_l and trim_h into just one
  nvmem cell in the bindings, device tree and driver. I did this after
  verifying that downstream has no SoC where trim_l and trim_h are ever
  non-contiguous, including for SoCs upstream does not (yet) support.
- Rebased on top of next-20250225 and dropped Heiko's OTP patchset as a
  dependency as it was merged.
- Added a handy overview of which SoCs use which part of the OTP trim
  functionality in the cover letter
- Reintroduced an accidentally removed dev_dbg in the function 
  rockchip_thermal_set_trips
- Link to v1: https://lore.kernel.org/r/20250216-rk3576-tsadc-upstream-v1-0-6ec969322a14 at collabora.com

---
Nicolas Frattaroli (6):
      thermal: rockchip: rename rk_tsadcv3_tshut_mode
      dt-bindings: rockchip-thermal: Add RK3576 compatible
      arm64: dts: rockchip: Add thermal nodes to RK3576
      dt-bindings: thermal: rockchip: document otp thermal trim
      arm64: dts: rockchip: Add thermal trim OTP and tsadc nodes
      thermal: rockchip: support reading trim values from OTP

Ye Zhang (1):
      thermal: rockchip: Support RK3576 SoC in the thermal driver

 .../bindings/thermal/rockchip-thermal.yaml         |  62 +++++
 arch/arm64/boot/dts/rockchip/rk3576.dtsi           | 221 +++++++++++++++++-
 drivers/thermal/rockchip_thermal.c                 | 251 +++++++++++++++++++--
 3 files changed, 511 insertions(+), 23 deletions(-)
---
base-commit: 40a111d0a777f60b71369d835cfe46308a212235
change-id: 20250215-rk3576-tsadc-upstream-7e0c193f768a

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From nicolas.frattaroli at collabora.com  Mon Mar 17 06:49:27 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 14:49:27 +0100
Subject: [PATCH v4 2/7] dt-bindings: rockchip-thermal: Add RK3576
 compatible
In-Reply-To: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
References: <20250317-rk3576-tsadc-upstream-v4-0-c5029ce55d74@collabora.com>
Message-ID: <20250317-rk3576-tsadc-upstream-v4-2-c5029ce55d74@collabora.com>

Add a new compatible for the thermal sensor device on the RK3576 SoC.

Acked-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
index b717ea8261ca24ebaf709f410ec6372de1366b8a..49ceed68c92ce5a32ed8d4f39bd88fd052de0e80 100644
--- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
@@ -21,6 +21,7 @@ properties:
       - rockchip,rk3368-tsadc
       - rockchip,rk3399-tsadc
       - rockchip,rk3568-tsadc
+      - rockchip,rk3576-tsadc
       - rockchip,rk3588-tsadc
       - rockchip,rv1108-tsadc
 

-- 
2.48.1



From csokas.bence at prolan.hu  Mon Mar 17 06:53:36 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 17 Mar 2025 14:53:36 +0100
Subject: [PATCH v4 0/2] Add `devm_dma_request_chan()` to simplify probe path in atmel-quadspi.c
Message-ID: <20250317135340.382532-1-csokas.bence@prolan.hu>

The probe function of the atmel-quadspi driver got quite convoluted,
especially since the addition of SAMA7G5 support, that was forward-ported
from an older vendor kernel. To alleivate this - and similar problems in
the future - an effort was made to migrate as many functions as possible,
to their devm_ managed counterparts. Patch 1 adds the new
`devm_dma_request_chan()` function. Patch 2 then uses this APIs to
simplify the probe() function.

Change in v4:
* split PM imbalance fix [1] and DMA cleanup [this series]

This series is to be applied after the PM imbalance fix [1].

[1]
https://lore.kernel.org/linux-kernel/20250317093445.361821-1-csokas.bence at prolan.hu/

Links to previous versions:
pre-series:
https://lore.kernel.org/linux-kernel/20241222141427.819222-1-csokas.bence at prolan.hu/
https://lore.kernel.org/linux-kernel/20250114222851.1023194-1-csokas.bence at prolan.hu/
v1:
https://lore.kernel.org/linux-kernel/20250115160244.1102881-1-csokas.bence at prolan.hu/
v2:
https://lore.kernel.org/linux-kernel/20250124085221.766303-8-csokas.bence at prolan.hu/
v3:
https://lore.kernel.org/linux-kernel/20250207124802.165408-1-csokas.bence at prolan.hu/

Bence Cs?k?s (2):
  dma: Add devm_dma_request_chan()
  spi: atmel-quadspi: Use `devm_dma_request_chan()`

 drivers/dma/dmaengine.c     | 30 +++++++++++++++++++++++++
 drivers/spi/atmel-quadspi.c | 44 ++++++++++---------------------------
 include/linux/dmaengine.h   |  7 ++++++
 3 files changed, 48 insertions(+), 33 deletions(-)

-- 
2.48.1




From kabel at kernel.org  Mon Mar 17 07:08:16 2025
From: kabel at kernel.org (Marek =?utf-8?B?QmVow7pu?=)
Date: Mon, 17 Mar 2025 15:08:16 +0100
Subject: [PATCH v12 4/6] clk: qcom: Add NSS clock Controller driver for
 IPQ9574
In-Reply-To: <20250313110359.242491-5-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
 <20250313110359.242491-5-quic_mmanikan@quicinc.com>
Message-ID: <65gl7d6qd55xrdm3as3pnqevpmakin3k4jzyocehq7wq7565jj@x35t2inlykop>

On Thu, Mar 13, 2025 at 04:33:57PM +0530, Manikanta Mylavarapu wrote:

> +static struct clk_rcg2 nss_cc_clc_clk_src = {
> +	.cmd_rcgr = 0x28604,
> +	.mnd_width = 0,
> +	.hid_width = 5,
> +	.parent_map = nss_cc_parent_map_6,
> +	.freq_tbl = ftbl_nss_cc_clc_clk_src,
> +	.clkr.hw.init = &(const struct clk_init_data) {
> +		.name = "nss_cc_clc_clk_src",
> +		.parent_data = nss_cc_parent_data_6,
> +		.num_parents = ARRAY_SIZE(nss_cc_parent_data_6),
> +		.ops = &clk_rcg2_ops,
> +	},
> +};

This structure definition gets repeated many times in this driver,
with only slight changes. (This also happens in other qualcomm clock
drivers.)

Would it be possible to refactor it into a macro, to avoid the
insane code repetition?

Marek


From kevin.brodsky at arm.com  Mon Mar 17 07:16:55 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:55 +0000
Subject: [PATCH 06/11] mm: Skip ptlock_init() for kernel PMDs
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-7-kevin.brodsky@arm.com>

Split page table locks are not used for pgtables associated to
init_mm, at any level. pte_alloc_kernel() does not call
ptlock_init() as a result. There is however no separate alloc/free
functions for kernel PMDs, and pmd_ptlock_init() is called
unconditionally. When ALLOC_SPLIT_PTLOCKS is true (e.g. 32-bit
architectures or if CONFIG_PREEMPT_RT is selected), this results in
unnecessary dynamic memory allocation every time a kernel PMD is
allocated.

Now that pagetable_pmd_ctor() is passed the associated mm, we can
easily remove this overhead by skipping pmd_ptlock_init() if the
pgtable is associated to init_mm. No special-casing is needed on the
dtor path, as ptlock_free() is already called unconditionally for
all levels. (ptlock_free() is a no-op unless a ptlock was allocated
for the given PTP.)

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 include/linux/mm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index ee31ffd7ead2..4759da9cd633 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3125,7 +3125,7 @@ static inline spinlock_t *pmd_lock(struct mm_struct *mm, pmd_t *pmd)
 static inline bool pagetable_pmd_ctor(struct mm_struct *mm,
 				      struct ptdesc *ptdesc)
 {
-	if (!pmd_ptlock_init(ptdesc))
+	if (mm != &init_mm && !pmd_ptlock_init(ptdesc))
 		return false;
 	ptdesc_pmd_pts_init(ptdesc);
 	__pagetable_ctor(ptdesc);
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:56 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:56 +0000
Subject: [PATCH 07/11] arm64: mm: Use enum to identify pgtable level instead of *_SHIFT
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-8-kevin.brodsky@arm.com>

Commit 90292aca9854 ("arm64: mm: use appropriate ctors for page
tables") introduced pgtable ctor calls in pgd_pgtable_alloc(). To
identify the pgtable level and call the appropriate ctor, the
*_SHIFT value associated with the pgtable level is used. However,
those values do not unambiguously identify a level, because if a
given level is folded, the *_SHIFT value will be equal to that of
the upper level (e.g. PMD_SHIFT == PUD_SHIFT if PMD is folded).

As things stand, there is probably not much damaged done by calling
the ctor for a different level, and ARCH_ENABLE_SPLIT_PMD_PTLOCK is
only selected if PMD isn't folded (so we don't needlessly initialise
pmd_ptlock). Still, this is pretty confusing, and it would get even
more confusing when adding ctor calls for the remaining levels.

Let's simplify all this by using an enum to identify the pgtable
level instead; this way folding becomes irrelevant. This is inspired
by one of the m68k pgtable allocators
(arch/m68k/include/asm/motorola_pgalloc.h).

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm64/mm/mmu.c | 54 +++++++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 437d4977bcf5..a7292ce9d7b8 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -46,6 +46,13 @@
 #define NO_CONT_MAPPINGS	BIT(1)
 #define NO_EXEC_MAPPINGS	BIT(2)	/* assumes FEAT_HPDS is not used */
 
+enum pgtable_type {
+	TABLE_PTE,
+	TABLE_PMD,
+	TABLE_PUD,
+	TABLE_P4D,
+};
+
 u64 kimage_voffset __ro_after_init;
 EXPORT_SYMBOL(kimage_voffset);
 
@@ -107,7 +114,7 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 }
 EXPORT_SYMBOL(phys_mem_access_prot);
 
-static phys_addr_t __init early_pgtable_alloc(int shift)
+static phys_addr_t __init early_pgtable_alloc(enum pgtable_type pgtable_type)
 {
 	phys_addr_t phys;
 
@@ -192,7 +199,7 @@ static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
 static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 				unsigned long end, phys_addr_t phys,
 				pgprot_t prot,
-				phys_addr_t (*pgtable_alloc)(int),
+				phys_addr_t (*pgtable_alloc)(enum pgtable_type),
 				int flags)
 {
 	unsigned long next;
@@ -207,7 +214,7 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 		if (flags & NO_EXEC_MAPPINGS)
 			pmdval |= PMD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
-		pte_phys = pgtable_alloc(PAGE_SHIFT);
+		pte_phys = pgtable_alloc(TABLE_PTE);
 		ptep = pte_set_fixmap(pte_phys);
 		init_clear_pgtable(ptep);
 		ptep += pte_index(addr);
@@ -243,7 +250,7 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
 
 static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
 		     phys_addr_t phys, pgprot_t prot,
-		     phys_addr_t (*pgtable_alloc)(int), int flags)
+		     phys_addr_t (*pgtable_alloc)(enum pgtable_type), int flags)
 {
 	unsigned long next;
 
@@ -277,7 +284,8 @@ static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
 static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 				unsigned long end, phys_addr_t phys,
 				pgprot_t prot,
-				phys_addr_t (*pgtable_alloc)(int), int flags)
+				phys_addr_t (*pgtable_alloc)(enum pgtable_type),
+				int flags)
 {
 	unsigned long next;
 	pud_t pud = READ_ONCE(*pudp);
@@ -294,7 +302,7 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 		if (flags & NO_EXEC_MAPPINGS)
 			pudval |= PUD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
-		pmd_phys = pgtable_alloc(PMD_SHIFT);
+		pmd_phys = pgtable_alloc(TABLE_PMD);
 		pmdp = pmd_set_fixmap(pmd_phys);
 		init_clear_pgtable(pmdp);
 		pmdp += pmd_index(addr);
@@ -325,7 +333,7 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
 
 static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 			   phys_addr_t phys, pgprot_t prot,
-			   phys_addr_t (*pgtable_alloc)(int),
+			   phys_addr_t (*pgtable_alloc)(enum pgtable_type),
 			   int flags)
 {
 	unsigned long next;
@@ -339,7 +347,7 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 		if (flags & NO_EXEC_MAPPINGS)
 			p4dval |= P4D_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
-		pud_phys = pgtable_alloc(PUD_SHIFT);
+		pud_phys = pgtable_alloc(TABLE_PUD);
 		pudp = pud_set_fixmap(pud_phys);
 		init_clear_pgtable(pudp);
 		pudp += pud_index(addr);
@@ -383,7 +391,7 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
 
 static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 			   phys_addr_t phys, pgprot_t prot,
-			   phys_addr_t (*pgtable_alloc)(int),
+			   phys_addr_t (*pgtable_alloc)(enum pgtable_type),
 			   int flags)
 {
 	unsigned long next;
@@ -397,7 +405,7 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 		if (flags & NO_EXEC_MAPPINGS)
 			pgdval |= PGD_TABLE_PXN;
 		BUG_ON(!pgtable_alloc);
-		p4d_phys = pgtable_alloc(P4D_SHIFT);
+		p4d_phys = pgtable_alloc(TABLE_P4D);
 		p4dp = p4d_set_fixmap(p4d_phys);
 		init_clear_pgtable(p4dp);
 		p4dp += p4d_index(addr);
@@ -427,7 +435,7 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
 static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
 					unsigned long virt, phys_addr_t size,
 					pgprot_t prot,
-					phys_addr_t (*pgtable_alloc)(int),
+					phys_addr_t (*pgtable_alloc)(enum pgtable_type),
 					int flags)
 {
 	unsigned long addr, end, next;
@@ -455,7 +463,7 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
 static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
 				 unsigned long virt, phys_addr_t size,
 				 pgprot_t prot,
-				 phys_addr_t (*pgtable_alloc)(int),
+				 phys_addr_t (*pgtable_alloc)(enum pgtable_type),
 				 int flags)
 {
 	mutex_lock(&fixmap_lock);
@@ -468,10 +476,11 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
 extern __alias(__create_pgd_mapping_locked)
 void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
 			     phys_addr_t size, pgprot_t prot,
-			     phys_addr_t (*pgtable_alloc)(int), int flags);
+			     phys_addr_t (*pgtable_alloc)(enum pgtable_type),
+			     int flags);
 #endif
 
-static phys_addr_t __pgd_pgtable_alloc(int shift)
+static phys_addr_t __pgd_pgtable_alloc(enum pgtable_type pgtable_type)
 {
 	/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
 	void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL & ~__GFP_ZERO);
@@ -480,23 +489,26 @@ static phys_addr_t __pgd_pgtable_alloc(int shift)
 	return __pa(ptr);
 }
 
-static phys_addr_t pgd_pgtable_alloc(int shift)
+static phys_addr_t pgd_pgtable_alloc(enum pgtable_type pgtable_type)
 {
-	phys_addr_t pa = __pgd_pgtable_alloc(shift);
+	phys_addr_t pa = __pgd_pgtable_alloc(pgtable_type);
 	struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa));
 
 	/*
 	 * Call proper page table ctor in case later we need to
 	 * call core mm functions like apply_to_page_range() on
 	 * this pre-allocated page table.
-	 *
-	 * We don't select ARCH_ENABLE_SPLIT_PMD_PTLOCK if pmd is
-	 * folded, and if so pagetable_pte_ctor() becomes nop.
 	 */
-	if (shift == PAGE_SHIFT)
+	switch (pgtable_type) {
+	case TABLE_PTE:
 		BUG_ON(!pagetable_pte_ctor(NULL, ptdesc));
-	else if (shift == PMD_SHIFT)
+		break;
+	case TABLE_PMD:
 		BUG_ON(!pagetable_pmd_ctor(NULL, ptdesc));
+		break;
+	default:
+		break;
+	}
 
 	return pa;
 }
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:57 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:57 +0000
Subject: [PATCH 08/11] arm64: mm: Always call PTE/PMD ctor in __create_pgd_mapping()
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-9-kevin.brodsky@arm.com>

TL;DR: always call the PTE/PMD ctor, passing the appropriate mm to
skip ptlock_init() if unneeded.

__create_pgd_mapping() is used for creating different kinds of
mappings, and may allocate page table pages if passed an allocator
callback. There are currently three such cases:

1. create_pgd_mapping(), which is used to create the EFI mapping
2. arch_add_memory()
3. map_entry_trampoline()

1. uses pgd_pgtable_alloc() as allocator callback, which calls the
PTE/PMD ctor, while 2. and 3. use __pgd_pgtable_alloc(), which does
not. The rationale is most likely that pgtables associated with
init_mm do not make use of split page table locks, and it is
therefore unnecessary to initialise them by calling the ctor. 2.
operates on swapper_pg_dir so the allocated pgtables are clearly
associated with init_mm, this is arguably the case for 3. too (the
trampoline mapping is never modified so ptlocks are anyway
irrelevant). 1. corresponds to efi_mm so ptlocks need to be
initialised in that case.

We are now moving towards calling the ctor for all page tables, even
those associated with init_mm. pagetable_{pte,pmd}_ctor() have
become aware of the associated mm so that the ptlock initialisation
can be skipped for init_mm. This patch therefore amends the
allocator callbacks so that the PTE/PMD ctor are always called, with
an appropriate mm pointer to avoid unnecessary ptlock overhead.

Modifying the prototype of the allocator callbacks to take the mm
and propagating that pointer all the way down would be pretty
invasive. Instead:

* __pgd_pgtable_alloc() (cases 2. and 3. above) is replaced with
  pgd_pgtable_alloc_init_mm(), resulting in the ctors being called
  with &init_mm. This is the main functional change in this patch;
  the ptlock still isn't initialised, but other ctor actions (e.g.
  accounting-related) are now carried out for those allocated
  pgtables.

* pgd_pgtable_alloc() (case 1. above) is replaced with
  pgd_pgtable_alloc_special_mm(), resulting in the ctors being
  called with NULL as mm. No functional change here; NULL
  essentially means "not init_mm", and the ptlock is still
  initialised.

__pgd_pgtable_alloc() is now the common implementation of those two
helpers. While at it we switch it to using pagetable_alloc() like
standard pgtable allocator functions and remove the comment
regarding ctor calls (ctors are now always expected to be called).

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm64/mm/mmu.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a7292ce9d7b8..accb0a33c59f 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -480,31 +480,22 @@ void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
 			     int flags);
 #endif
 
-static phys_addr_t __pgd_pgtable_alloc(enum pgtable_type pgtable_type)
+static phys_addr_t __pgd_pgtable_alloc(struct mm_struct *mm,
+				       enum pgtable_type pgtable_type)
 {
 	/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
-	void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL & ~__GFP_ZERO);
+	struct ptdesc *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & ~__GFP_ZERO, 0);
+	phys_addr_t pa;
 
-	BUG_ON(!ptr);
-	return __pa(ptr);
-}
-
-static phys_addr_t pgd_pgtable_alloc(enum pgtable_type pgtable_type)
-{
-	phys_addr_t pa = __pgd_pgtable_alloc(pgtable_type);
-	struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa));
+	BUG_ON(!ptdesc);
+	pa = page_to_phys(ptdesc_page(ptdesc));
 
-	/*
-	 * Call proper page table ctor in case later we need to
-	 * call core mm functions like apply_to_page_range() on
-	 * this pre-allocated page table.
-	 */
 	switch (pgtable_type) {
 	case TABLE_PTE:
-		BUG_ON(!pagetable_pte_ctor(NULL, ptdesc));
+		BUG_ON(!pagetable_pte_ctor(mm, ptdesc));
 		break;
 	case TABLE_PMD:
-		BUG_ON(!pagetable_pmd_ctor(NULL, ptdesc));
+		BUG_ON(!pagetable_pmd_ctor(mm, ptdesc));
 		break;
 	default:
 		break;
@@ -513,6 +504,16 @@ static phys_addr_t pgd_pgtable_alloc(enum pgtable_type pgtable_type)
 	return pa;
 }
 
+static phys_addr_t pgd_pgtable_alloc_init_mm(enum pgtable_type pgtable_type)
+{
+	return __pgd_pgtable_alloc(&init_mm, pgtable_type);
+}
+
+static phys_addr_t pgd_pgtable_alloc_special_mm(enum pgtable_type pgtable_type)
+{
+	return __pgd_pgtable_alloc(NULL, pgtable_type);
+}
+
 /*
  * This function can only be used to modify existing table entries,
  * without allocating new levels of table. Note that this permits the
@@ -542,7 +543,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 		flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
 	__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
-			     pgd_pgtable_alloc, flags);
+			     pgd_pgtable_alloc_special_mm, flags);
 }
 
 static void update_mapping_prot(phys_addr_t phys, unsigned long virt,
@@ -756,7 +757,7 @@ static int __init map_entry_trampoline(void)
 	memset(tramp_pg_dir, 0, PGD_SIZE);
 	__create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS,
 			     entry_tramp_text_size(), prot,
-			     __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS);
+			     pgd_pgtable_alloc_init_mm, NO_BLOCK_MAPPINGS);
 
 	/* Map both the text and data into the kernel page table */
 	for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++)
@@ -1362,7 +1363,7 @@ int arch_add_memory(int nid, u64 start, u64 size,
 		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
 	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
-			     size, params->pgprot, __pgd_pgtable_alloc,
+			     size, params->pgprot, pgd_pgtable_alloc_init_mm,
 			     flags);
 
 	memblock_clear_nomap(start, size);
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:58 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:58 +0000
Subject: [PATCH 09/11] riscv: mm: Clarify ctor mm argument in alloc_{pte,pmd}_late
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-10-kevin.brodsky@arm.com>

pagetable_{pte,pmd}_ctor(mm, ptdesc) skip the ptlock initialisation
if mm is &init_mm. To avoid unnecessary overhead, it is therefore
preferable to pass the actual mm associated to the PTE/PMD.

Unfortunately, this proves challenging for alloc_{pte,pmd}_late() as
the associated mm is not available at the point where they are
called - in fact not even top-level functions like
create_pgd_mapping() are passed the mm. As a result they both call
the ctor with NULL as mm; this is safe but potentially wasteful.

This is not a new situation, but let's add a couple of comments to
clarify it.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/riscv/mm/init.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 703c3648cfa9..fb18940113f2 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -409,6 +409,11 @@ static phys_addr_t __meminit alloc_pte_late(uintptr_t va)
 {
 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
 
+	/*
+	 * We do not know which mm the PTE page is associated to at this point.
+	 * Passing NULL to the ctor is the safe option, though it may result
+	 * in unnecessary work (e.g. initialising the ptlock for init_mm).
+	 */
 	BUG_ON(!ptdesc || !pagetable_pte_ctor(NULL, ptdesc));
 	return __pa((pte_t *)ptdesc_address(ptdesc));
 }
@@ -489,6 +494,7 @@ static phys_addr_t __meminit alloc_pmd_late(uintptr_t va)
 {
 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
 
+	/* See comment in alloc_pte_late() regarding NULL passed the ctor */
 	BUG_ON(!ptdesc || !pagetable_pmd_ctor(NULL, ptdesc));
 	return __pa((pmd_t *)ptdesc_address(ptdesc));
 }
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:53 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:53 +0000
Subject: [PATCH 04/11] powerpc: mm: Call ctor/dtor for kernel PTEs
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-5-kevin.brodsky@arm.com>

The generic implementation of pte_{alloc_one,free}_kernel now calls
the [cd]tor, without initialising the ptlock needlessly as
pagetable_pte_ctor() skips it for init_mm.

On powerpc, all functions related to PTE allocation are implemented
by common helpers, which are passed a boolean to differentiate user
from kernel pgtables. This patch aligns the powerpc implementation
with the generic one by calling pagetable_pte_[cd]tor()
unconditionally in those helpers.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/powerpc/mm/pgtable-frag.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c
index 387e9b1fe12c..77e55eac16e4 100644
--- a/arch/powerpc/mm/pgtable-frag.c
+++ b/arch/powerpc/mm/pgtable-frag.c
@@ -56,19 +56,17 @@ static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel)
 {
 	void *ret = NULL;
 	struct ptdesc *ptdesc;
+	gfp_t gfp = PGALLOC_GFP;
 
-	if (!kernel) {
-		ptdesc = pagetable_alloc(PGALLOC_GFP | __GFP_ACCOUNT, 0);
-		if (!ptdesc)
-			return NULL;
-		if (!pagetable_pte_ctor(mm, ptdesc)) {
-			pagetable_free(ptdesc);
-			return NULL;
-		}
-	} else {
-		ptdesc = pagetable_alloc(PGALLOC_GFP, 0);
-		if (!ptdesc)
-			return NULL;
+	if (!kernel)
+		gfp |= __GFP_ACCOUNT;
+
+	ptdesc = pagetable_alloc(gfp, 0);
+	if (!ptdesc)
+		return NULL;
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
+		pagetable_free(ptdesc);
+		return NULL;
 	}
 
 	atomic_set(&ptdesc->pt_frag_refcount, 1);
@@ -124,12 +122,10 @@ void pte_fragment_free(unsigned long *table, int kernel)
 
 	BUG_ON(atomic_read(&ptdesc->pt_frag_refcount) <= 0);
 	if (atomic_dec_and_test(&ptdesc->pt_frag_refcount)) {
-		if (kernel)
-			pagetable_free(ptdesc);
-		else if (folio_test_clear_active(ptdesc_folio(ptdesc)))
-			call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
-		else
+		if (kernel || !folio_test_clear_active(ptdesc_folio(ptdesc)))
 			pte_free_now(&ptdesc->pt_rcu_head);
+		else
+			call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
 	}
 }
 
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:54 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:54 +0000
Subject: [PATCH 05/11] sparc64: mm: Call ctor/dtor for kernel PTEs
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-6-kevin.brodsky@arm.com>

The generic implementation of pte_{alloc_one,free}_kernel now calls
the [cd]tor, without initialising the ptlock needlessly as
pagetable_pte_ctor() skips it for init_mm.

Align sparc64 with the generic implementation by ensuring
pagetable_pte_[cd]tor() are called for kernel PTEs. As a result
the kernel and user alloc/free functions have the same
implementation, and since pgtable_t is defined as pte_t *, we can
have both call a common helper.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/sparc/mm/init_64.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index cd60a0a8ca0e..0a1b2b1adad4 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2882,18 +2882,7 @@ void __flush_tlb_all(void)
 			     : : "r" (pstate));
 }
 
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
-{
-	struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	pte_t *pte = NULL;
-
-	if (page)
-		pte = (pte_t *) page_address(page);
-
-	return pte;
-}
-
-pgtable_t pte_alloc_one(struct mm_struct *mm)
+static pte_t *__pte_alloc_one(struct mm_struct *mm)
 {
 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL | __GFP_ZERO, 0);
 
@@ -2906,9 +2895,14 @@ pgtable_t pte_alloc_one(struct mm_struct *mm)
 	return ptdesc_address(ptdesc);
 }
 
-void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 {
-	free_page((unsigned long)pte);
+	return __pte_alloc_one(mm);
+}
+
+pgtable_t pte_alloc_one(struct mm_struct *mm)
+{
+	return __pte_alloc_one(mm);
 }
 
 static void __pte_free(pgtable_t pte)
@@ -2919,6 +2913,11 @@ static void __pte_free(pgtable_t pte)
 	pagetable_free(ptdesc);
 }
 
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	__pte_free(pte);
+}
+
 void pte_free(struct mm_struct *mm, pgtable_t pte)
 {
 	__pte_free(pte);
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:59 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:59 +0000
Subject: [PATCH 10/11] arm64: mm: Call PUD/P4D ctor in __create_pgd_mapping()
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-11-kevin.brodsky@arm.com>

Constructors for PUD/P4D-level pgtables were recently introduced.
They should be called for all pgtables; make sure they are called
for special kernel mappings created by __create_pgd_mapping() too.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm64/mm/mmu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index accb0a33c59f..10bf39654e77 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -497,7 +497,11 @@ static phys_addr_t __pgd_pgtable_alloc(struct mm_struct *mm,
 	case TABLE_PMD:
 		BUG_ON(!pagetable_pmd_ctor(mm, ptdesc));
 		break;
-	default:
+	case TABLE_PUD:
+		pagetable_pud_ctor(ptdesc);
+		break;
+	case TABLE_P4D:
+		pagetable_p4d_ctor(ptdesc);
 		break;
 	}
 
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:17:00 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:17:00 +0000
Subject: [PATCH 11/11] riscv: mm: Call PUD/P4D ctor in special kernel pgtable alloc
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-12-kevin.brodsky@arm.com>

Constructors for PUD/P4D-level pgtables were recently introduced.
They should be called for all pgtables; make sure they are called
for special kernel mappings created by create_pgd_mapping() too.

While at it also switch to using pagetable_alloc() like
in alloc_{pte,pmd}_late().

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/riscv/mm/init.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index fb18940113f2..dc2715f3fd00 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -557,11 +557,11 @@ static phys_addr_t __init alloc_pud_fixmap(uintptr_t va)
 
 static phys_addr_t __meminit alloc_pud_late(uintptr_t va)
 {
-	unsigned long vaddr;
+	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
 
-	vaddr = __get_free_page(GFP_KERNEL);
-	BUG_ON(!vaddr);
-	return __pa(vaddr);
+	BUG_ON(!ptdesc);
+	pagetable_pud_ctor(ptdesc);
+	return __pa((pud_t *)ptdesc_address(ptdesc));
 }
 
 static p4d_t *__init get_p4d_virt_early(phys_addr_t pa)
@@ -595,11 +595,11 @@ static phys_addr_t __init alloc_p4d_fixmap(uintptr_t va)
 
 static phys_addr_t __meminit alloc_p4d_late(uintptr_t va)
 {
-	unsigned long vaddr;
+	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
 
-	vaddr = __get_free_page(GFP_KERNEL);
-	BUG_ON(!vaddr);
-	return __pa(vaddr);
+	BUG_ON(!ptdesc);
+	pagetable_p4d_ctor(ptdesc);
+	return __pa((p4d_t *)ptdesc_address(ptdesc));
 }
 
 static void __meminit create_pud_mapping(pud_t *pudp, uintptr_t va, phys_addr_t pa, phys_addr_t sz,
-- 
2.47.0



From krzk at kernel.org  Mon Mar 17 07:23:52 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 15:23:52 +0100
Subject: [PATCH 3/3] firmware: samsung: add ACPM debugfs support
In-Reply-To: <696494b8-14e9-4b9b-bf26-2a94a915b2ec@linaro.org>
References: <20250224-acpm-debugfs-v1-0-2418a3ea1b17@linaro.org>
 <20250224-acpm-debugfs-v1-3-2418a3ea1b17@linaro.org>
 <005424c2-7fb7-48db-b38c-c62f9f8b3897@kernel.org>
 <696494b8-14e9-4b9b-bf26-2a94a915b2ec@linaro.org>
Message-ID: <3a25e4f5-e017-4d30-92cc-62b9ebef1d5a@kernel.org>

On 12/03/2025 08:11, Tudor Ambarus wrote:
> 
>>> +		dev_info(acpm->dev, "[ACPM_FW] : %llu id:%u, %s, %x\n", time,
>>> +			 log_entry->plugin_id, (char *)&msg, log_entry->data);
>>
>>
>> I don't think these should be printed to dmesg - these are not system
>> logs. You either return the contents to the caller's read() on debugfs
>> entry or, if this is anyhow crashdump related, it goes to
>> pstore/minidump once triggered. Or to ramoops.
>>
>> Depends what these logs are (so please also explain what do you find
>> there in the commit msg).
>>
>> Maybe something like CHROMEOS_PSTORE?
>>
>> IOW, if enabled, this should go to ramoops/pstore unconditionally. For
>> runtime debugging this should be returned somehow to the userspace
>> reading the file. I think usually debugfs and sysfs is not expected to
>> provide more than PAGE_SIZE data, so this second part has to be
>> rethinked still.
>>
> 
> This is a logging feature, it's not oops/panic related. These logs are
> referred to as "block logs". A "block" is the start of a mailbox command
> to its end, so it logs every ACPM mailbox command issued to the
> firmware. After each end of a block, we see the state of all regulators,
> frequencies and devices up/down extracted from the block.
> 
> These are indeed system logs, and using the dmesg ring buffer seems fine
> as we typically care about the recent logs, we don't care if the ring
> starts all over again.

I claim these are not system logs, but firmware logs, thus dmesg ring
buffer is not suitable for them. Where do the other vendors log remoteprocs?


Best regards,
Krzysztof


From robh at kernel.org  Mon Mar 17 07:28:32 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 17 Mar 2025 09:28:32 -0500
Subject: [net-next PATCH v13 05/14] dt-bindings: mfd: Document support
 for Airoha AN8855 Switch SoC
In-Reply-To: <20250315154407.26304-6-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
 <20250315154407.26304-6-ansuelsmth@gmail.com>
Message-ID: <20250317142832.GA4116523-robh@kernel.org>

On Sat, Mar 15, 2025 at 04:43:45PM +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 Switch SoC. This SoC expose various
> peripherals like an Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> 
> It does also support i2c and timers but those are not currently
> supported/used.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/mfd/airoha,an8855.yaml           | 182 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 183 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> new file mode 100644
> index 000000000000..a59a23056b3a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
> @@ -0,0 +1,182 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/airoha,an8855.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Switch SoC
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  Airoha AN8855 Switch is a SoC that expose various peripherals like an
> +  Ethernet Switch, a NVMEM provider and Ethernet PHYs.
> +
> +  It does also support i2c and timers but those are not currently
> +  supported/used.
> +
> +properties:
> +  compatible:
> +    const: airoha,an8855
> +
> +  reg:
> +    maxItems: 1
> +
> +  reset-gpios: true
> +
> +  efuse:
> +    type: object
> +    $ref: /schemas/nvmem/airoha,an8855-efuse.yaml
> +    description:
> +      EFUSE exposed by the Airoha AN8855 Switch. This child node definition
> +      should follow the bindings specified in
> +      Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml

No need to list the schema twice. Drop the 2nd sentence.

> +
> +  ethernet-switch:
> +    type: object
> +    $ref: /schemas/net/dsa/airoha,an8855-switch.yaml
> +    description:
> +      Switch exposed by the Airoha AN8855 Switch. This child node definition
> +      should follow the bindings specified in
> +      Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml

ditto

> +
> +  mdio:
> +    type: object
> +    $ref: /schemas/net/airoha,an8855-mdio.yaml
> +    description:
> +      MDIO exposed by the Airoha AN8855 Switch. This child node definition
> +      should follow the bindings specified in
> +      Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml

ditto

> +
> +required:
> +  - compatible
> +  - reg

The child nodes are optional?

> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +
> +    mdio {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        soc at 1 {
> +            compatible = "airoha,an8855";
> +            reg = <1>;
> +
> +            reset-gpios = <&pio 39 0>;
> +
> +            efuse {
> +                compatible = "airoha,an8855-efuse";
> +
> +                #nvmem-cell-cells = <0>;
> +
> +                nvmem-layout {
> +                    compatible = "fixed-layout";
> +                    #address-cells = <1>;
> +                    #size-cells = <1>;
> +
> +                    shift_sel_port0_tx_a: shift-sel-port0-tx-a at c {
> +                       reg = <0xc 0x4>;
> +                    };
> +
> +                    shift_sel_port0_tx_b: shift-sel-port0-tx-b at 10 {
> +                        reg = <0x10 0x4>;
> +                    };
> +
> +                    shift_sel_port0_tx_c: shift-sel-port0-tx-c at 14 {
> +                        reg = <0x14 0x4>;
> +                    };
> +
> +                    shift_sel_port0_tx_d: shift-sel-port0-tx-d at 18 {
> +                       reg = <0x18 0x4>;
> +                    };
> +
> +                    shift_sel_port1_tx_a: shift-sel-port1-tx-a at 1c {
> +                        reg = <0x1c 0x4>;
> +                    };
> +
> +                    shift_sel_port1_tx_b: shift-sel-port1-tx-b at 20 {
> +                        reg = <0x20 0x4>;
> +                    };
> +
> +                    shift_sel_port1_tx_c: shift-sel-port1-tx-c at 24 {
> +                       reg = <0x24 0x4>;
> +                    };
> +
> +                    shift_sel_port1_tx_d: shift-sel-port1-tx-d at 28 {
> +                        reg = <0x28 0x4>;
> +                    };
> +                };
> +            };
> +
> +            ethernet-switch {
> +                compatible = "airoha,an8855-switch";
> +
> +                ports {
> +                    #address-cells = <1>;
> +                    #size-cells = <0>;
> +
> +                    port at 0 {
> +                        reg = <0>;
> +                        label = "lan1";
> +                        phy-mode = "internal";
> +                        phy-handle = <&internal_phy1>;
> +                    };
> +
> +                    port at 1 {
> +                        reg = <1>;
> +                        label = "lan2";
> +                        phy-mode = "internal";
> +                        phy-handle = <&internal_phy2>;
> +                    };
> +
> +                    port at 5 {
> +                        reg = <5>;
> +                        label = "cpu";
> +                        ethernet = <&gmac0>;
> +                        phy-mode = "2500base-x";
> +
> +                        fixed-link {
> +                            speed = <2500>;
> +                            full-duplex;
> +                            pause;
> +                        };
> +                    };
> +                };
> +            };
> +
> +            mdio {
> +                compatible = "airoha,an8855-mdio";
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                internal_phy1: phy at 1 {
> +                  compatible = "ethernet-phy-idc0ff.0410",
> +                               "ethernet-phy-ieee802.3-c45";
> +                  reg = <1>;
> +
> +                  nvmem-cells = <&shift_sel_port0_tx_a>,
> +                      <&shift_sel_port0_tx_b>,
> +                      <&shift_sel_port0_tx_c>,
> +                      <&shift_sel_port0_tx_d>;
> +                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
> +                };
> +
> +                internal_phy2: phy at 2 {
> +                  compatible = "ethernet-phy-idc0ff.0410",
> +                               "ethernet-phy-ieee802.3-c45";
> +                  reg = <2>;
> +
> +                  nvmem-cells = <&shift_sel_port1_tx_a>,
> +                      <&shift_sel_port1_tx_b>,
> +                      <&shift_sel_port1_tx_c>,
> +                      <&shift_sel_port1_tx_d>;
> +                  nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
> +                };
> +            };
> +        };
> +    };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 45f4bb8deb0d..65709e47adc7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -725,6 +725,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>  L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
>  L:	netdev at vger.kernel.org
>  S:	Maintained
> +F:	Documentation/devicetree/bindings/mfd/airoha,an8855.yaml
>  F:	Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
>  F:	Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
>  F:	Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> -- 
> 2.48.1
> 


From colin.i.king at gmail.com  Mon Mar 17 07:34:56 2025
From: colin.i.king at gmail.com (Colin Ian King)
Date: Mon, 17 Mar 2025 14:34:56 +0000
Subject: [PATCH][next] PCI: brcmstb: make const read-only arrays static
Message-ID: <20250317143456.477901-1-colin.i.king@gmail.com>

Don't populate the const read-only arrays data and regs on the stack at
run time, instead make them static.

Signed-off-by: Colin Ian King <colin.i.king at gmail.com>
---
 drivers/pci/controller/pcie-brcmstb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 8b2b099e81eb..d258b571f642 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -832,8 +832,8 @@ static int brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
 
 static int brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie)
 {
-	const u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
-	const u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
+	static const u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
+	static const u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
 	int ret, i;
 	u32 tmp;
 
-- 
2.47.2



From nicolas.frattaroli at collabora.com  Mon Mar 17 07:36:56 2025
From: nicolas.frattaroli at collabora.com (Nicolas Frattaroli)
Date: Mon, 17 Mar 2025 15:36:56 +0100
Subject: [PATCH] pmdomain: rockchip: keep PD_NVM on RK3576 always on
Message-ID: <20250317-rk3576-emmc-fix-v1-1-d534d49a41f5@collabora.com>

Due to what seemingly is a hardware bug, PD_NVM never comes up quite the
same after being turned off once. The result is that the sdhci
controller will lock up the entire SoC when it's accessing its CQHCI
registers.

The downstream kernel hacks around this by setting
GENPD_FLAG_RPM_ALWAYS_ON in the mmc host driver, which does not seem
like the right place for this.

Set GENPD_FLAG_ALWAYS_ON in the pmdomain driver for PD_NVM. I'm using
the non-RPM version of the flag here because I have my doubts a
suspend-resume cycle will fix it. Suspend-resume currently seems busted,
so I couldn't test this.

Fixes: cfee1b507758 ("pmdomain: rockchip: Add support for RK3576 SoC")
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli at collabora.com>
---
 drivers/pmdomain/rockchip/pm-domains.c | 48 ++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
index 03bcf79a461f5db14173b35c0d110541e6d3f760..2b220b7c77b3d292f49cbc60338d3925146fb211 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -48,6 +48,7 @@ struct rockchip_domain_info {
 	int ack_mask;
 	bool active_wakeup;
 	bool need_regulator;
+	bool always_on;
 	int pwr_w_mask;
 	int req_w_mask;
 	int clk_ungate_mask;
@@ -154,7 +155,7 @@ struct rockchip_pmu {
 	.need_regulator = regulator,			\
 }
 
-#define DOMAIN_M_O_R_G(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, g_mask, wakeup)	\
+#define DOMAIN_M_O_R_G(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, g_mask, wakeup, _always_on)	\
 {							\
 	.name = _name,					\
 	.pwr_offset = p_offset,				\
@@ -171,6 +172,7 @@ struct rockchip_pmu {
 	.clk_ungate_mask = (g_mask),			\
 	.ack_mask = (ack),				\
 	.active_wakeup = wakeup,			\
+	.always_on = _always_on,			\
 }
 
 #define DOMAIN_RK3036(_name, req, ack, idle, wakeup)		\
@@ -204,8 +206,8 @@ struct rockchip_pmu {
 #define DOMAIN_RK3568(name, pwr, req, wakeup)		\
 	DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
 
-#define DOMAIN_RK3576(name, p_offset, pwr, status, r_status, r_offset, req, idle, g_mask, wakeup)	\
-	DOMAIN_M_O_R_G(name, p_offset, pwr, status, 0, r_status, r_status, r_offset, req, idle, idle, g_mask, wakeup)
+#define DOMAIN_RK3576(name, p_offset, pwr, status, r_status, r_offset, req, idle, g_mask, wakeup, always_on)	\
+	DOMAIN_M_O_R_G(name, p_offset, pwr, status, 0, r_status, r_status, r_offset, req, idle, idle, g_mask, wakeup, always_on)
 
 /*
  * Dynamic Memory Controller may need to coordinate with us -- see
@@ -846,6 +848,8 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
 	pd->genpd.flags = GENPD_FLAG_PM_CLK;
 	if (pd_info->active_wakeup)
 		pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+	if (pd_info->always_on)
+		pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
 	pm_genpd_init(&pd->genpd, NULL,
 		      !rockchip_pmu_domain_is_on(pd) ||
 		      (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd)));
@@ -1210,25 +1214,25 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = {
 };
 
 static const struct rockchip_domain_info rk3576_pm_domains[] = {
-	[RK3576_PD_NPU]		= DOMAIN_RK3576("npu",    0x0, BIT(0),  BIT(0), 0,       0x0, 0,       0,       0,       false),
-	[RK3576_PD_NVM]		= DOMAIN_RK3576("nvm",    0x0, BIT(6),  0,      BIT(6),  0x4, BIT(2),  BIT(18), BIT(2),  false),
-	[RK3576_PD_SDGMAC]	= DOMAIN_RK3576("sdgmac", 0x0, BIT(7),  0,      BIT(7),  0x4, BIT(1),  BIT(17), 0x6,     false),
-	[RK3576_PD_AUDIO]	= DOMAIN_RK3576("audio",  0x0, BIT(8),  0,      BIT(8),  0x4, BIT(0),  BIT(16), BIT(0),  false),
-	[RK3576_PD_PHP]		= DOMAIN_RK3576("php",    0x0, BIT(9),  0,      BIT(9),  0x0, BIT(15), BIT(15), BIT(15), false),
-	[RK3576_PD_SUBPHP]	= DOMAIN_RK3576("subphp", 0x0, BIT(10), 0,      BIT(10), 0x0, 0,       0,       0,       false),
-	[RK3576_PD_VOP]		= DOMAIN_RK3576("vop",    0x0, BIT(11), 0,      BIT(11), 0x0, 0x6000,  0x6000,  0x6000,  false),
-	[RK3576_PD_VO1]		= DOMAIN_RK3576("vo1",    0x0, BIT(14), 0,      BIT(14), 0x0, BIT(12), BIT(12), 0x7000,  false),
-	[RK3576_PD_VO0]		= DOMAIN_RK3576("vo0",    0x0, BIT(15), 0,      BIT(15), 0x0, BIT(11), BIT(11), 0x6800,  false),
-	[RK3576_PD_USB]		= DOMAIN_RK3576("usb",    0x4, BIT(0),  0,      BIT(16), 0x0, BIT(10), BIT(10), 0x6400,  true),
-	[RK3576_PD_VI]		= DOMAIN_RK3576("vi",     0x4, BIT(1),  0,      BIT(17), 0x0, BIT(9),  BIT(9),  BIT(9),  false),
-	[RK3576_PD_VEPU0]	= DOMAIN_RK3576("vepu0",  0x4, BIT(2),  0,      BIT(18), 0x0, BIT(7),  BIT(7),  0x280,   false),
-	[RK3576_PD_VEPU1]	= DOMAIN_RK3576("vepu1",  0x4, BIT(3),  0,      BIT(19), 0x0, BIT(8),  BIT(8),  BIT(8),  false),
-	[RK3576_PD_VDEC]	= DOMAIN_RK3576("vdec",   0x4, BIT(4),  0,      BIT(20), 0x0, BIT(6),  BIT(6),  BIT(6),  false),
-	[RK3576_PD_VPU]		= DOMAIN_RK3576("vpu",    0x4, BIT(5),  0,      BIT(21), 0x0, BIT(5),  BIT(5),  BIT(5),  false),
-	[RK3576_PD_NPUTOP]	= DOMAIN_RK3576("nputop", 0x4, BIT(6),  0,      BIT(22), 0x0, 0x18,    0x18,    0x18,    false),
-	[RK3576_PD_NPU0]	= DOMAIN_RK3576("npu0",   0x4, BIT(7),  0,      BIT(23), 0x0, BIT(1),  BIT(1),  0x1a,    false),
-	[RK3576_PD_NPU1]	= DOMAIN_RK3576("npu1",   0x4, BIT(8),  0,      BIT(24), 0x0, BIT(2),  BIT(2),  0x1c,    false),
-	[RK3576_PD_GPU]		= DOMAIN_RK3576("gpu",    0x4, BIT(9),  0,      BIT(25), 0x0, BIT(0),  BIT(0),  BIT(0),  false),
+	[RK3576_PD_NPU]		= DOMAIN_RK3576("npu",    0x0, BIT(0),  BIT(0), 0,       0x0, 0,       0,       0,       false, false),
+	[RK3576_PD_NVM]		= DOMAIN_RK3576("nvm",    0x0, BIT(6),  0,      BIT(6),  0x4, BIT(2),  BIT(18), BIT(2),  false, true),
+	[RK3576_PD_SDGMAC]	= DOMAIN_RK3576("sdgmac", 0x0, BIT(7),  0,      BIT(7),  0x4, BIT(1),  BIT(17), 0x6,     false, false),
+	[RK3576_PD_AUDIO]	= DOMAIN_RK3576("audio",  0x0, BIT(8),  0,      BIT(8),  0x4, BIT(0),  BIT(16), BIT(0),  false, false),
+	[RK3576_PD_PHP]		= DOMAIN_RK3576("php",    0x0, BIT(9),  0,      BIT(9),  0x0, BIT(15), BIT(15), BIT(15), false, false),
+	[RK3576_PD_SUBPHP]	= DOMAIN_RK3576("subphp", 0x0, BIT(10), 0,      BIT(10), 0x0, 0,       0,       0,       false, false),
+	[RK3576_PD_VOP]		= DOMAIN_RK3576("vop",    0x0, BIT(11), 0,      BIT(11), 0x0, 0x6000,  0x6000,  0x6000,  false, false),
+	[RK3576_PD_VO1]		= DOMAIN_RK3576("vo1",    0x0, BIT(14), 0,      BIT(14), 0x0, BIT(12), BIT(12), 0x7000,  false, false),
+	[RK3576_PD_VO0]		= DOMAIN_RK3576("vo0",    0x0, BIT(15), 0,      BIT(15), 0x0, BIT(11), BIT(11), 0x6800,  false, false),
+	[RK3576_PD_USB]		= DOMAIN_RK3576("usb",    0x4, BIT(0),  0,      BIT(16), 0x0, BIT(10), BIT(10), 0x6400,  true,  false),
+	[RK3576_PD_VI]		= DOMAIN_RK3576("vi",     0x4, BIT(1),  0,      BIT(17), 0x0, BIT(9),  BIT(9),  BIT(9),  false, false),
+	[RK3576_PD_VEPU0]	= DOMAIN_RK3576("vepu0",  0x4, BIT(2),  0,      BIT(18), 0x0, BIT(7),  BIT(7),  0x280,   false, false),
+	[RK3576_PD_VEPU1]	= DOMAIN_RK3576("vepu1",  0x4, BIT(3),  0,      BIT(19), 0x0, BIT(8),  BIT(8),  BIT(8),  false, false),
+	[RK3576_PD_VDEC]	= DOMAIN_RK3576("vdec",   0x4, BIT(4),  0,      BIT(20), 0x0, BIT(6),  BIT(6),  BIT(6),  false, false),
+	[RK3576_PD_VPU]		= DOMAIN_RK3576("vpu",    0x4, BIT(5),  0,      BIT(21), 0x0, BIT(5),  BIT(5),  BIT(5),  false, false),
+	[RK3576_PD_NPUTOP]	= DOMAIN_RK3576("nputop", 0x4, BIT(6),  0,      BIT(22), 0x0, 0x18,    0x18,    0x18,    false, false),
+	[RK3576_PD_NPU0]	= DOMAIN_RK3576("npu0",   0x4, BIT(7),  0,      BIT(23), 0x0, BIT(1),  BIT(1),  0x1a,    false, false),
+	[RK3576_PD_NPU1]	= DOMAIN_RK3576("npu1",   0x4, BIT(8),  0,      BIT(24), 0x0, BIT(2),  BIT(2),  0x1c,    false, false),
+	[RK3576_PD_GPU]		= DOMAIN_RK3576("gpu",    0x4, BIT(9),  0,      BIT(25), 0x0, BIT(0),  BIT(0),  BIT(0),  false, false),
 };
 
 static const struct rockchip_domain_info rk3588_pm_domains[] = {

---
base-commit: b52e55576652f29ab7387e2da222123f624a7767
change-id: 20250317-rk3576-emmc-fix-7dc81a627422

Best regards,
-- 
Nicolas Frattaroli <nicolas.frattaroli at collabora.com>



From vladimir.oltean at nxp.com  Mon Mar 17 07:48:43 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 16:48:43 +0200
Subject: [PATCH v4 net-next 05/14] net: enetc: add debugfs interface to
 dump MAC filter
In-Reply-To: <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
Message-ID: <20250317144843.wp432pgodn4vjejf@skbuf>

On Tue, Mar 11, 2025 at 01:38:21PM +0800, Wei Fang wrote:
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> new file mode 100644
> index 000000000000..3a660c80344a
> --- /dev/null
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> @@ -0,0 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright 2025 NXP */
> +
> +#include <linux/device.h>
> +#include <linux/debugfs.h>
> +#include <linux/seq_file.h>
> +
> +#include "enetc_pf.h"
> +#include "enetc4_debugfs.h"
> +
> +#define is_en(x)	(x) ? "Enabled" : "Disabled"

str_enabled_disabled()

> +
> +static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
> +{
> +	struct enetc_si *si = s->private;
> +	struct enetc_hw *hw = &si->hw;
> +	u32 hash_h, hash_l;
> +
> +	hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
> +	hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
> +	seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
> +		   i, hash_h, hash_l);

Maybe the ":" separator between the high and low 32 bits is clearer than "x".

> +
> +	hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
> +	hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
> +	seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
> +		   i, hash_h, hash_l);
> +}
> +
> +static int enetc_mac_filter_show(struct seq_file *s, void *data)
> +{
> +	struct maft_entry_data maft_data;
> +	struct enetc_si *si = s->private;
> +	struct enetc_hw *hw = &si->hw;
> +	struct maft_keye_data *keye;
> +	struct enetc_pf *pf;
> +	int i, err, num_si;
> +	u32 val;
> +
> +	pf = enetc_si_priv(si);
> +	num_si = pf->caps.num_vsi + 1;
> +
> +	val = enetc_port_rd(hw, ENETC4_PSIPMMR);
> +	for (i = 0; i < num_si; i++) {
> +		seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
> +			   i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
> +		seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
> +			   i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
> +	}
> +
> +	/* MAC hash filter table */
> +	for (i = 0; i < num_si; i++)
> +		enetc_show_si_mac_hash_filter(s, i);
> +
> +	if (!pf->num_mfe)
> +		return 0;
> +
> +	/* MAC address filter table */
> +	seq_puts(s, "Show MAC address filter table\n");

The word "show" seems superfluous.

> +	for (i = 0; i < pf->num_mfe; i++) {
> +		memset(&maft_data, 0, sizeof(maft_data));
> +		err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
> +		if (err)
> +			return err;
> +
> +		keye = &maft_data.keye;
> +		seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
> +			   keye->mac_addr, le16_to_cpu(maft_data.cfge.si_bitmap));
> +	}
> +
> +	return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);


From vladimir.oltean at nxp.com  Mon Mar 17 07:18:07 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 16:18:07 +0200
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <20250311053830.1516523-5-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
Message-ID: <20250317141807.2zobsefxl5vnqdet@skbuf>

On Tue, Mar 11, 2025 at 01:38:20PM +0800, Wei Fang wrote:
> The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
> hash filter is implenented through a 64-bits hash table to match against

s/implenented/implemented/
s/64-bits/64-bit/

> the hashed addresses, PF and VFs each have two MAC hash tables, one is
> for unicast and the other one is for multicast. But MAC exact filter is
> shared between SIs (PF and VFs), each table entry contains a MAC address
> that may be unicast or multicast and the entry also contains an SI bitmap
> field that indicates for which SIs the entry is valid.
> 
> For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
> observation of the system default network configuration, the MAC filter
> will be configured with multiple multicast addresses, so MAC exact filter
> does not have enough entries to implement multicast filtering. Therefore,
> the current MAC exact filter is only used for unicast filtering. If the
> number of unicast addresses exceeds 4, then MAC hash filter is used.
> 
> Note that both MAC hash filter and MAC exact filter can only be accessed
> by PF, VFs can notify PF to set its corresponding MAC filter through the
> mailbox mechanism of ENETC. But currently MAC filter is only added for
> i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
> subsequent patches.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---
>  drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
>  .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
>  .../net/ethernet/freescale/enetc/enetc4_pf.c  | 422 +++++++++++++++++-
>  .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
>  .../net/ethernet/freescale/enetc/enetc_pf.h   |  11 +
>  5 files changed, 448 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
> index 9380d3e8ca01..4dba91408e3d 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> @@ -316,6 +316,8 @@ struct enetc_si {
>  	const struct enetc_si_ops *ops;
>  
>  	struct enetc_mac_filter mac_filter[MADDR_TYPE];
> +	struct workqueue_struct *workqueue;
> +	struct work_struct rx_mode_task;
>  };
>  
>  #define ENETC_SI_ALIGN	32
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
> index 695cb07c74bc..826359004850 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
> @@ -99,6 +99,14 @@
>  #define ENETC4_PSICFGR2(a)		((a) * 0x80 + 0x2018)
>  #define  PSICFGR2_NUM_MSIX		GENMASK(5, 0)
>  
> +/* Port station interface a unicast MAC hash filter register 0/1 */
> +#define ENETC4_PSIUMHFR0(a)		((a) * 0x80 + 0x2050)
> +#define ENETC4_PSIUMHFR1(a)		((a) * 0x80 + 0x2054)
> +
> +/* Port station interface a multicast MAC hash filter register 0/1 */
> +#define ENETC4_PSIMMHFR0(a)		((a) * 0x80 + 0x2058)
> +#define ENETC4_PSIMMHFR1(a)		((a) * 0x80 + 0x205c)
> +
>  #define ENETC4_PMCAPR			0x4004
>  #define  PMCAPR_HD			BIT(8)
>  #define  PMCAPR_FP			GENMASK(10, 9)
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> index 63001379f0a0..7d1c545f3f56 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> @@ -11,6 +11,15 @@
>  
>  #define ENETC_SI_MAX_RING_NUM	8
>  
> +#define ENETC_MAC_FILTER_TYPE_UC	BIT(0)
> +#define ENETC_MAC_FILTER_TYPE_MC	BIT(1)
> +#define ENETC_MAC_FILTER_TYPE_ALL	(ENETC_MAC_FILTER_TYPE_UC | \
> +					 ENETC_MAC_FILTER_TYPE_MC)
> +
> +struct enetc_mac_addr {
> +	u8 addr[ETH_ALEN];
> +};
> +
>  static void enetc4_get_port_caps(struct enetc_pf *pf)
>  {
>  	struct enetc_hw *hw = &pf->si->hw;
> @@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
>  
>  	val = enetc_port_rd(hw, ENETC4_PMCAPR);
>  	pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
> +
> +	val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
> +	pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
>  }
>  
>  static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
> @@ -56,6 +68,341 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
>  	put_unaligned_le16(lower, addr + 4);
>  }
>  
> +static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
> +					 int type, bool en)
> +{
> +	u32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);
> +
> +	if (type == UC) {
> +		if (en)
> +			val |= PSIPMMR_SI_MAC_UP(si);
> +		else
> +			val &= ~PSIPMMR_SI_MAC_UP(si);
> +	} else { /* Multicast promiscuous mode. */
> +		if (en)
> +			val |= PSIPMMR_SI_MAC_MP(si);
> +		else
> +			val &= ~PSIPMMR_SI_MAC_MP(si);
> +	}
> +
> +	enetc_port_wr(hw, ENETC4_PSIPMMR, val);
> +}
> +
> +static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
> +					     int type, u64 hash)
> +{
> +	if (type == UC) {
> +		enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
> +		enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
> +	} else { /* MC */
> +		enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
> +		enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
> +	}
> +}

Please split into separate functions for unicast and for multicast.
The implementations don't share any code, and the callers are not in
common code either.

> +
> +static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
> +{
> +	struct enetc_mac_list_entry *entry;
> +	struct hlist_node *tmp;
> +
> +	mutex_lock(&pf->mac_list_lock);

The mutex_lock() usage here should raise serious questions. This is
running right before mutex_destroy(). So if there were any concurrent
attempt to acquire this lock, that concurrent code would have been broken
any time it would have lost arbitration, by the fact that it would
attempt to acquire a destroyed mutex.

But there's no such concurrent thread, because we run after destroy_workqueue()
which flushes those concurrent calls and prevents new ones. So the mutex
usage here is not necessary.

[ same thing with mutex_init() immediately followed by mutex_lock().
  It is an incorrect pattern most of the time. ]

> +
> +	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
> +		hlist_del(&entry->node);
> +		kfree(entry);
> +	}
> +
> +	pf->num_mfe = 0;
> +
> +	mutex_unlock(&pf->mac_list_lock);
> +}
> +
> +static bool enetc_mac_filter_type_check(int type, const u8 *addr)
> +{
> +	if (type == ENETC_MAC_FILTER_TYPE_UC)
> +		return !is_multicast_ether_addr(addr);
> +	else if (type == ENETC_MAC_FILTER_TYPE_MC)
> +		return is_multicast_ether_addr(addr);
> +	else
> +		return true;
> +}
> +
> +static struct enetc_mac_list_entry *
> +enetc_mac_list_lookup_entry(struct enetc_pf *pf, const unsigned char *addr)
> +{
> +	struct enetc_mac_list_entry *entry;
> +
> +	hlist_for_each_entry(entry, &pf->mac_list, node)
> +		if (ether_addr_equal(entry->mac, addr))
> +			return entry;
> +
> +	return NULL;
> +}
> +
> +static void enetc_mac_list_add_entry(struct enetc_pf *pf,
> +				     struct enetc_mac_list_entry *entry)
> +{
> +	hlist_add_head(&entry->node, &pf->mac_list);
> +}
> +
> +static void enetc_mac_list_del_entry(struct enetc_mac_list_entry *entry)
> +{
> +	hlist_del(&entry->node);
> +	kfree(entry);
> +}
> +
> +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16 si_bit,
> +					       struct enetc_mac_addr *mac,
> +					       int mac_cnt)
> +{
> +	struct enetc_mac_list_entry *entry;
> +	int i;
> +
> +	for (i = 0; i < mac_cnt; i++) {
> +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> +		if (!entry)
> +			continue;
> +
> +		entry->si_bitmap &= ~si_bit;
> +		if (entry->si_bitmap)
> +			continue;
> +
> +		enetc_mac_list_del_entry(entry);
> +		pf->num_mfe--;
> +	}
> +}
> +
> +static bool enetc_mac_list_is_available(struct enetc_pf *pf,
> +					struct enetc_mac_addr *mac,
> +					int mac_cnt)
> +{
> +	int max_num_mfe = pf->caps.mac_filter_num;
> +	struct enetc_mac_list_entry *entry;
> +	int cur_num_mfe = pf->num_mfe;
> +	int i, new_mac_cnt = 0;
> +
> +	if (mac_cnt > max_num_mfe)
> +		return false;
> +
> +	/* Check MAC filter table whether has enough available entries */
> +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> +		for (i = 0; i < mac_cnt; i++) {
> +			if (ether_addr_equal(entry->mac, mac[i].addr))
> +				break;
> +		}
> +
> +		if (i == mac_cnt)
> +			new_mac_cnt++;
> +
> +		if ((cur_num_mfe + new_mac_cnt) > max_num_mfe)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
> +static int enetc4_pf_add_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
> +					     struct enetc_mac_addr *mac,
> +					     int mac_cnt)
> +{
> +	struct enetc_mac_list_entry *entry;
> +	struct maft_entry_data data = {0};

As I've also learned, what you actually want is an empty struct initializer "= {}" here:
https://lore.kernel.org/netdev/20210810091238.GB1343 at shell.armlinux.org.uk/

> +	struct enetc_si *si = pf->si;
> +	u16 si_bit = BIT(si_id);
> +	int i, num_mfe, err = 0;
> +
> +	mutex_lock(&pf->mac_list_lock);
> +
> +	if (!enetc_mac_list_is_available(pf, mac, mac_cnt)) {
> +		err = -ENOSPC;
> +		goto mac_list_unlock;
> +	}
> +
> +	num_mfe = pf->num_mfe;
> +	/* Update mac_list */
> +	for (i = 0; i < mac_cnt; i++) {
> +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> +		if (entry) {
> +			entry->si_bitmap |= si_bit;
> +			continue;
> +		}
> +
> +		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> +		if (unlikely(!entry)) {
> +			/* Restore MAC list to the state before the update
> +			 * if an error occurs.
> +			 */
> +			enetc_mac_list_del_matched_entries(pf, si_bit,
> +							   mac, i + 1);
> +			err = -ENOMEM;
> +			goto mac_list_unlock;
> +		}
> +
> +		ether_addr_copy(entry->mac, mac[i].addr);
> +		entry->si_bitmap = si_bit;
> +		enetc_mac_list_add_entry(pf, entry);
> +		pf->num_mfe++;
> +	}
> +
> +	/* Clear MAC filter table */
> +	for (i = 0; i < num_mfe; i++)
> +		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
> +
> +	i = 0;
> +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> +		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
> +		ether_addr_copy(data.keye.mac_addr, entry->mac);
> +		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);

Don't discard error code.

> +	}
> +
> +mac_list_unlock:
> +	mutex_unlock(&pf->mac_list_lock);
> +
> +	return err;
> +}
> +
> +static void enetc4_pf_flush_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
> +						int mac_type)
> +{
> +	struct enetc_mac_list_entry *entry;
> +	struct maft_entry_data data = {0};

s/{0}/{}/

> +	struct enetc_si *si = pf->si;
> +	u16 si_bit = BIT(si_id);
> +	struct hlist_node *tmp;
> +	int i, num_mfe;
> +
> +	mutex_lock(&pf->mac_list_lock);
> +
> +	num_mfe = pf->num_mfe;
> +	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
> +		if (enetc_mac_filter_type_check(mac_type, entry->mac) &&
> +		    entry->si_bitmap & si_bit) {
> +			entry->si_bitmap ^= si_bit;
> +			if (entry->si_bitmap)
> +				continue;
> +
> +			enetc_mac_list_del_entry(entry);
> +			pf->num_mfe--;
> +		}
> +	}
> +
> +	for (i = 0; i < num_mfe; i++)
> +		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
> +
> +	i = 0;
> +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> +		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
> +		ether_addr_copy(data.keye.mac_addr, entry->mac);
> +		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);

Don't discard error code.

Also, can't you edit MAFT entries in-place over NTMP? Deleting and
re-adding filters creates small time windows where you might have
RX packet loss, which is not ideal.

> +	}
> +
> +	mutex_unlock(&pf->mac_list_lock);
> +}
> +
> +static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
> +{
> +	int max_num_mfe = pf->caps.mac_filter_num;
> +	struct net_device *ndev = pf->si->ndev;
> +	struct enetc_mac_addr *mac_tbl;
> +	struct netdev_hw_addr *ha;
> +	u8 si_mac[ETH_ALEN];
> +	int mac_cnt = 0;
> +	int err;
> +
> +	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);

Can't you know ahead of time, based on netdev_uc_count(), whether you
will have space for exact match filters, and avoid unnecessary
allocations if not? enetc_mac_list_is_available() seems way too late.

> +	if (!mac_tbl)
> +		return -ENOMEM;
> +
> +	enetc_get_primary_mac_addr(&pf->si->hw, si_mac);
> +
> +	netif_addr_lock_bh(ndev);
> +	if (type & ENETC_MAC_FILTER_TYPE_UC) {
> +		netdev_for_each_uc_addr(ha, ndev) {
> +			if (!is_valid_ether_addr(ha->addr) ||
> +			    ether_addr_equal(ha->addr, si_mac))
> +				continue;
> +
> +			if (mac_cnt >= max_num_mfe)
> +				goto err_nospace_out;
> +
> +			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
> +		}
> +	}
> +
> +	if (type & ENETC_MAC_FILTER_TYPE_MC) {

Dead code, you never add multicast addresses as exact match filters.
Please remove.

> +		netdev_for_each_mc_addr(ha, ndev) {
> +			if (!is_multicast_ether_addr(ha->addr))
> +				continue;
> +
> +			if (mac_cnt >= max_num_mfe)
> +				goto err_nospace_out;
> +
> +			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
> +		}
> +	}
> +	netif_addr_unlock_bh(ndev);
> +
> +	err = enetc4_pf_add_si_mac_exact_filter(pf, 0, mac_tbl, mac_cnt);
> +	kfree(mac_tbl);
> +
> +	return err;
> +
> +err_nospace_out:
> +	netif_addr_unlock_bh(ndev);
> +	kfree(mac_tbl);
> +
> +	return -ENOSPC;
> +}
> +
> +static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)
> +{
> +	struct net_device *ndev = pf->si->ndev;
> +	struct enetc_mac_filter *mac_filter;
> +	struct enetc_hw *hw = &pf->si->hw;
> +	struct enetc_si *si = pf->si;
> +	struct netdev_hw_addr *ha;
> +
> +	netif_addr_lock_bh(ndev);
> +	if (type & ENETC_MAC_FILTER_TYPE_UC) {
> +		mac_filter = &si->mac_filter[UC];
> +		enetc_reset_mac_addr_filter(mac_filter);
> +		netdev_for_each_uc_addr(ha, ndev)
> +			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
> +
> +		enetc4_pf_set_si_mac_hash_filter(hw, 0, UC,
> +						 *mac_filter->mac_hash_table);
> +	}
> +
> +	if (type & ENETC_MAC_FILTER_TYPE_MC) {
> +		mac_filter = &si->mac_filter[MC];
> +		enetc_reset_mac_addr_filter(mac_filter);
> +		netdev_for_each_mc_addr(ha, ndev)
> +			enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
> +
> +		enetc4_pf_set_si_mac_hash_filter(hw, 0, MC,
> +						 *mac_filter->mac_hash_table);
> +	}
> +	netif_addr_unlock_bh(ndev);
> +}
> +
> +static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
> +{
> +	/* Currently, the MAC address filter table only has 4 entries, and the
> +	 * table is shared by PF and VFs. In the default network configuration,
> +	 * the MAC filter will be configured with multiple multicast addresses,
> +	 * so it is only suitable for unicast filtering. If the number of unicast
> +	 * addresses exceeds the table capacity, the MAC hash filter will be used.
> +	 */
> +	if (type & ENETC_MAC_FILTER_TYPE_UC) {
> +		if (enetc4_pf_set_mac_exact_filter(pf, ENETC_MAC_FILTER_TYPE_UC))
> +			/* Fall back to the MAC hash filter */
> +			enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);
> +	}
> +
> +	if (type & ENETC_MAC_FILTER_TYPE_MC)
> +		enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);
> +}
> +
>  static const struct enetc_pf_ops enetc4_pf_ops = {
>  	.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
>  	.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
> @@ -71,9 +418,18 @@ static int enetc4_pf_struct_init(struct enetc_si *si)
>  
>  	enetc4_get_port_caps(pf);
>  
> +	INIT_HLIST_HEAD(&pf->mac_list);
> +	mutex_init(&pf->mac_list_lock);
> +
>  	return 0;
>  }
>  
> +static void enetc4_pf_struct_free(struct enetc_pf *pf)
> +{
> +	enetc4_pf_destroy_mac_list(pf);
> +	mutex_destroy(&pf->mac_list_lock);
> +}
> +
>  static u32 enetc4_psicfgr0_val_construct(bool is_vf, u32 num_tx_bdr, u32 num_rx_bdr)
>  {
>  	u32 val;
> @@ -305,12 +661,53 @@ static void enetc4_pf_free(struct enetc_pf *pf)
>  	enetc4_free_ntmp_priv(pf->si);
>  }
>  
> +static void enetc4_pf_do_set_rx_mode(struct work_struct *work)
> +{
> +	struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
> +	struct enetc_pf *pf = enetc_si_priv(si);
> +	struct net_device *ndev = si->ndev;
> +	struct enetc_hw *hw = &si->hw;
> +	bool uc_promisc = false;
> +	bool mc_promisc = false;
> +	int type = 0;
> +
> +	if (ndev->flags & IFF_PROMISC) {
> +		uc_promisc = true;
> +		mc_promisc = true;
> +	} else if (ndev->flags & IFF_ALLMULTI) {
> +		mc_promisc = true;
> +		type = ENETC_MAC_FILTER_TYPE_UC;
> +	} else {
> +		type = ENETC_MAC_FILTER_TYPE_ALL;
> +	}
> +
> +	enetc4_pf_set_si_mac_promisc(hw, 0, UC, uc_promisc);
> +	enetc4_pf_set_si_mac_promisc(hw, 0, MC, mc_promisc);

Why don't you call the function just once and provide both uc_promisc
and mc_promisc arguments? You would avoid a useless read of the
ENETC4_PSIPMMR register.

> +
> +	/* Clear Old MAC filter */
> +	enetc4_pf_flush_si_mac_exact_filter(pf, 0, ENETC_MAC_FILTER_TYPE_ALL);
> +	enetc4_pf_set_si_mac_hash_filter(hw, 0, UC, 0);
> +	enetc4_pf_set_si_mac_hash_filter(hw, 0, MC, 0);
> +
> +	/* Set new MAC filter */
> +	enetc4_pf_set_mac_filter(pf, type);
> +}
> +
> +static void enetc4_pf_set_rx_mode(struct net_device *ndev)
> +{
> +	struct enetc_ndev_priv *priv = netdev_priv(ndev);
> +	struct enetc_si *si = priv->si;
> +
> +	queue_work(si->workqueue, &si->rx_mode_task);
> +}
> +
>  static const struct net_device_ops enetc4_ndev_ops = {
>  	.ndo_open		= enetc_open,
>  	.ndo_stop		= enetc_close,
>  	.ndo_start_xmit		= enetc_xmit,
>  	.ndo_get_stats		= enetc_get_stats,
>  	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
> +	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
>  };
>  
>  static struct phylink_pcs *
> @@ -721,6 +1118,19 @@ static const struct enetc_si_ops enetc4_psi_ops = {
>  	.teardown_cbdr = enetc4_teardown_cbdr,
>  };
>  
> +static int enetc4_pf_wq_task_init(struct enetc_si *si)
> +{
> +	char wq_name[24];
> +
> +	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
> +	snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
> +	si->workqueue = create_singlethread_workqueue(wq_name);
> +	if (!si->workqueue)
> +		return -ENOMEM;
> +
> +	return 0;
> +}

Naming scheme is inconsistent here: the function is called "pf" but
takes "si" as argument. Same for enetc4_pf_do_set_rx_mode() where the
rx_mode_task is part of the station interface structure.

> +
>  static int enetc4_pf_probe(struct pci_dev *pdev,
>  			   const struct pci_device_id *ent)
>  {
> @@ -756,9 +1166,13 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
>  		return err;
>  
>  	pf = enetc_si_priv(si);
> +	err = enetc4_pf_wq_task_init(si);
> +	if (err)
> +		goto err_wq_task_init;
> +
>  	err = enetc4_pf_init(pf);
>  	if (err)
> -		return err;
> +		goto err_pf_init;
>  
>  	enetc_get_si_caps(si);
>  
> @@ -770,6 +1184,10 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
>  
>  err_netdev_create:
>  	enetc4_pf_free(pf);
> +err_pf_init:
> +	destroy_workqueue(si->workqueue);
> +err_wq_task_init:
> +	enetc4_pf_struct_free(pf);
>  
>  	return err;
>  }
> @@ -781,6 +1199,8 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
>  
>  	enetc4_pf_netdev_destroy(si);
>  	enetc4_pf_free(pf);
> +	destroy_workqueue(si->workqueue);
> +	enetc4_pf_struct_free(pf);
>  }
>  
>  static const struct pci_device_id enetc4_pf_id_table[] = {
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> index 4098f01479bc..2e676212d230 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> @@ -712,6 +712,12 @@ static inline void enetc_load_primary_mac_addr(struct enetc_hw *hw,
>  	eth_hw_addr_set(ndev, addr);
>  }
>  
> +static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr)
> +{
> +	*(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0);
> +	*(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1);
> +}
> +
>  #define ENETC_SI_INT_IDX	0
>  /* base index for Rx/Tx interrupts */
>  #define ENETC_BDR_INT_BASE_IDX	1
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> index 2b9d0f625f01..3b0cb0d8bf48 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> @@ -22,6 +22,13 @@ struct enetc_port_caps {
>  	int num_msix;
>  	int num_rx_bdr;
>  	int num_tx_bdr;
> +	int mac_filter_num;
> +};
> +
> +struct enetc_mac_list_entry {
> +	u8 mac[ETH_ALEN];
> +	u16 si_bitmap;
> +	struct hlist_node node;
>  };
>  
>  struct enetc_pf;
> @@ -57,6 +64,10 @@ struct enetc_pf {
>  
>  	struct enetc_port_caps caps;
>  	const struct enetc_pf_ops *ops;
> +
> +	struct hlist_head mac_list; /* MAC address filter table */

One thing I don't understand is why, given this implementation and
final effect, you even bother to keep the mac_list persistently in
struct enetc_pf. You have:

enetc4_pf_do_set_rx_mode()
-> enetc4_pf_flush_si_mac_exact_filter(ENETC_MAC_FILTER_TYPE_ALL)
   -> hlist_for_each_entry_safe(&pf->mac_list)
      -> enetc_mac_list_del_entry()

which practically deletes all &pf->mac_list elements every time.
So why even store them persistently in the first place? Why not just
create an on-stack INIT_HLIST_HEAD() list?

> +	struct mutex mac_list_lock; /* mac_list lock */

Unsatisfactory explanation. If you try to explain why it is needed, you
will find it's not needed. That's the intention behind checkpatch
emitting warnings when locks don't have comments. Not to force you to
write blabla, but to force you to verbalize, and thus to think whether
the proposed locking scheme makes sense.

The si->rx_mode_task is an ordered workqueue, which, as per
include/linux/workqueue.h, "executes at most one work item at any given
time in the queued order". In other words, enetc4_pf_do_set_rx_mode()
doesn't race with itself.

Combined with the previous comment on enetc4_pf_destroy_mac_list(), I
suggest that there is no need for this lock.

> +	int num_mfe;	/* number of mac address filter table entries */
>  };
>  
>  #define phylink_to_enetc_pf(config) \
> -- 
> 2.34.1
>


From robh at kernel.org  Mon Mar 17 07:18:32 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 09:18:32 -0500
Subject: [PATCH v5 0/7] arm64 support for Milk-V Duo Module 01 EVB
In-Reply-To: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
References: <20250316185640.3750873-1-alexander.sverdlin@gmail.com>
Message-ID: <174221818050.3957183.18032992749339066585.robh@kernel.org>


On Sun, 16 Mar 2025 19:56:30 +0100, Alexander Sverdlin wrote:
> This series adds very basic support for Milk-V Duo Module 01 EVB [1] in
> arm64 mode. The SoC (SG2000) is dual-arch, RiscV and ARM64, the latter has
> been chosen because the upstream toolchain can be utilized.
> 
> Sophgo SG2000 seems to be a continuation of the Cvitek CV18xx series, same
> peripherals with an addition of ARM64 core. Therefore it would be
> beneficial not to copy-paste the peripherals' device-tree, but rather split
> the most suitable riscv DT into ARCH-specific and peripherals parts and
> just include the latter on the arm64 side.
> 
> This series adds the device-tree for Milk-V Duo Module 01 EVB, which
> in turn contains Milk-V Duo Module 01 (separate .dtsi) on it, which has
> SG2000 SoC inside (separate .dtsi).
> 
> This series has been tested with Sophgo-provided U-Boot binary [2]: it
> boots from SD card; pinctrl, serial, GPIO drivers are functional (same
> as for RiscV-based CV18xx SoCs).
> 
> Partial SoC documentation is available [3].
> 
> This series lacks the support of:
> - USB
> - Audio
> - Ethernet
> - WiFi
> - Bluetooth
> - eMMC
> - Video
> 
> Changelog:
> v5:
> - PSCI node in DT
> v4:
> - minimized patch 1/7 (cleanups dropped)
> - cv18xx-cpu-intc.dtsi instead of cv18xx-cpu.dtsi+cv18xx-intc.dtsi in
> patch 1/7
> v3:
> - &cpus node has been moved into cv18xx-cpu.dtsi, &plic and &clint nodes
> were moved into cv18xx-intc.dtsi to reduce code duplication;
> v2:
> - dropped all patches related to the new reboot driver and corresponding DT
> and bindings;
> - grouped DT-related and config-related patches together;
> - added patch moving sophgo.yaml from riscv into soc (to share it with
> ARM); added SG2000 SoC and Milk-V Duo Module 01 EVB into it;
> - other changes are documented in the corresponding patches;
> 
> [1] https://milkv.io/docs/duo/getting-started/duo-module-01
> [2] https://github.com/milkv-duo/duo-buildroot-sdk-v2/releases/
> [3] https://github.com/sophgo/sophgo-doc/releases/download/sg2000-trm-v1.01/sg2000_trm_en.pdf
> 
> Alexander Sverdlin (7):
>   riscv: dts: sophgo: cv18xx: Move RiscV-specific part into SoCs' .dtsi
>     files
>   dt-bindings: soc: sophgo: Move SoCs/boards from riscv into soc, add
>     SG2000
>   arm64: dts: sophgo: Add initial SG2000 SoC device tree
>   arm64: dts: sophgo: Add Duo Module 01
>   arm64: dts: sophgo: Add Duo Module 01 Evaluation Board
>   arm64: Add SOPHGO SOC family Kconfig support
>   arm64: defconfig: Enable rudimentary Sophgo SG2000 support
> 
>  .../{riscv => soc/sophgo}/sophgo.yaml         |  7 +-
>  arch/arm64/Kconfig.platforms                  |  6 ++
>  arch/arm64/boot/dts/Makefile                  |  1 +
>  arch/arm64/boot/dts/sophgo/Makefile           |  2 +
>  .../sophgo/sg2000-milkv-duo-module-01-evb.dts | 31 +++++++
>  .../sophgo/sg2000-milkv-duo-module-01.dtsi    | 85 +++++++++++++++++
>  arch/arm64/boot/dts/sophgo/sg2000.dtsi        | 81 +++++++++++++++++
>  arch/arm64/configs/defconfig                  |  4 +
>  arch/riscv/boot/dts/sophgo/cv1800b.dtsi       |  5 +
>  arch/riscv/boot/dts/sophgo/cv1812h.dtsi       |  5 +
>  arch/riscv/boot/dts/sophgo/cv181x.dtsi        |  2 +-
>  .../boot/dts/sophgo/cv18xx-cpu-intc.dtsi      | 54 +++++++++++
>  arch/riscv/boot/dts/sophgo/cv18xx.dtsi        | 91 +++++--------------
>  arch/riscv/boot/dts/sophgo/sg2002.dtsi        |  5 +
>  14 files changed, 309 insertions(+), 70 deletions(-)
>  rename Documentation/devicetree/bindings/{riscv => soc/sophgo}/sophgo.yaml (80%)
>  create mode 100644 arch/arm64/boot/dts/sophgo/Makefile
>  create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dts
>  create mode 100644 arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01.dtsi
>  create mode 100644 arch/arm64/boot/dts/sophgo/sg2000.dtsi
>  create mode 100644 arch/riscv/boot/dts/sophgo/cv18xx-cpu-intc.dtsi
> 
> --
> 2.48.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/sophgo/' for 20250316185640.3750873-1-alexander.sverdlin at gmail.com:

arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dtb: psci: 'cpu_off' is a required property
	from schema $id: http://devicetree.org/schemas/arm/psci.yaml#
arch/arm64/boot/dts/sophgo/sg2000-milkv-duo-module-01-evb.dtb: psci: 'cpu_on' is a required property
	from schema $id: http://devicetree.org/schemas/arm/psci.yaml#







From kevin.brodsky at arm.com  Mon Mar 17 07:16:49 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:49 +0000
Subject: [PATCH 00/11] Always call constructor for kernel page tables
Message-ID: <20250317141700.3701581-1-kevin.brodsky@arm.com>

There has been much confusion around exactly when page table
constructors/destructors (pagetable_*_[cd]tor) are supposed to be
called. They were initially introduced for user PTEs only (to support
split page table locks), then at the PMD level for the same purpose.
Accounting was added later on, starting at the PTE level and then moving
to higher levels (PMD, PUD). Finally, with my earlier series "Account
page tables at all levels" [1], the ctor/dtor is run for all levels, all
the way to PGD.

I thought this was the end of the story, and it hopefully is for user
pgtables, but I was wrong for what concerns kernel pgtables. The current
situation there makes very little sense:

* At the PTE level, the ctor/dtor is not called (at least in the generic
  implementation). Specific helpers are used for kernel pgtables at this
  level (pte_{alloc,free}_kernel()) and those have never called the
  ctor/dtor, most likely because they were initially irrelevant in the
  kernel case.

* At all other levels, the ctor/dtor is normally called. This is
  potentially wasteful at the PMD level (more on that later).

This series aims to ensure that the ctor/dtor is always called for kernel
pgtables, as it already is for user pgtables. Besides consistency, the
main motivation is to guarantee that ctor/dtor hooks are systematically
called; this makes it possible to insert hooks to protect page tables [2],
for instance. There is however an extra challenge: split locks are not
used for kernel pgtables, and it would therefore be wasteful to
initialise them (ptlock_init()).

It is worth clarifying exactly when split locks are used. They clearly
are for user pgtables, but as illustrated in commit 61444cde9170 ("ARM:
8591/1: mm: use fully constructed struct pages for EFI pgd
allocations"), they also are for special page tables like efi_mm. The
one case where split locks are definitely unused is pgtables owned by
init_mm; this is consistent with the behaviour of apply_to_pte_range().

The approach chosen in this series is therefore to pass the mm
associated to the pgtables being constructed to
pagetable_{pte,pmd}_ctor() (patch 1), and skip ptlock_init() if
mm == &init_mm (patch 2 and 6). This makes it possible to call the PTE
ctor/dtor from pte_{alloc,free}_kernel() without unintended consequences
(patch 2). As a result the accounting functions are now called at
all levels for kernel pgtables, and split locks are never initialised.

In configurations where ptlocks are dynamically allocated (32-bit,
PREEMPT_RT, etc.) and ARCH_ENABLE_SPLIT_PMD_PTLOCK is selected, this
series results in the removal of a kmem_cache allocation for every
kernel PMD. Additionally, for certain architectures that do not use
<asm-generic/pgalloc.h> such as s390, the same optimisation occurs at
the PTE level.

---

Things get more complicated when it comes to special pgtable allocators
(patch 7-11). All architectures need such allocators to create initial
kernel pgtables; we are not concerned with those as the ctor cannot be
called so early in the boot sequence. However, those allocators may also
be used later in the boot sequence or during normal operations. There
are two main use-cases:

1. Mapping EFI memory: efi_mm (arm, arm64, riscv)
2. arch_add_memory(): init_mm

The ctor is already explicitly run (at the PTE/PMD level) in the first
case, as required for pgtables that are not associated with init_mm.
However the same allocators may also be used for the second use-case (or
others), and this is where it gets messy. Patch 1 calls the ctor with
NULL as mm in those situations, as the actual mm isn't available.
Practically this means that ptlocks will be unconditionally initialised.
This is fine on arm - create_mapping_late() is only used for the EFI
mapping. On arm64, __create_pgd_mapping() is also used by
arch_add_memory(); patch 7/8/10 ensure that ctors are called at all
levels with the appropriate mm. The situation is similar on riscv, but
propagating the mm down to the ctor would require significant
refactoring. Since they are already called unconditionally, this series
leaves riscv no worse off - patch 9 adds comments to clarify the
situation.

>From a cursory look at other architectures implementing
arch_add_memory(), s390 and x86 may also need a similar treatment to add
constructor calls. This is to be taken care of in a future version or as
a follow-up.

---

The complications in those special pgtable allocators beg the question:
does it really make sense to treat efi_mm and init_mm differently in
e.g. apply_to_pte_range()? Maybe what we really need is a way to tell if
an mm corresponds to user memory or not, and never use split locks for
non-user mm's. Feedback and suggestions welcome!

- Kevin

[1] https://lore.kernel.org/linux-mm/20250103184415.2744423-1-kevin.brodsky at arm.com/
[2] https://lore.kernel.org/linux-hardening/20250203101839.1223008-1-kevin.brodsky at arm.com/
---
Cc: Albert Ou <aou at eecs.berkeley.edu>
Cc: Andreas Larsson <andreas at gaisler.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Dave Hansen <dave.hansen at linux.intel.com>
Cc: "David S. Miller" <davem at davemloft.net>
Cc: Geert Uytterhoeven <geert at linux-m68k.org>
Cc: Linus Walleij <linus.walleij at linaro.org>
Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Matthew Wilcox <willy at infradead.org>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: "Mike Rapoport (IBM)" <rppt at kernel.org>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Qi Zheng <zhengqi.arch at bytedance.com>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Yang Shi <yang at os.amperecomputing.com>
Cc: linux-arch at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-csky at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-m68k at lists.linux-m68k.org
Cc: linux-openrisc at vger.kernel.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-s390 at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: sparclinux at vger.kernel.org
---
Kevin Brodsky (11):
  mm: Pass mm down to pagetable_{pte,pmd}_ctor
  mm: Call ctor/dtor for kernel PTEs
  m68k: mm: Call ctor/dtor for kernel PTEs
  powerpc: mm: Call ctor/dtor for kernel PTEs
  sparc64: mm: Call ctor/dtor for kernel PTEs
  mm: Skip ptlock_init() for kernel PMDs
  arm64: mm: Use enum to identify pgtable level instead of *_SHIFT
  arm64: mm: Always call PTE/PMD ctor in __create_pgd_mapping()
  riscv: mm: Clarify ctor mm argument in alloc_{pte,pmd}_late
  arm64: mm: Call PUD/P4D ctor in __create_pgd_mapping()
  riscv: mm: Call PUD/P4D ctor in special kernel pgtable alloc

 arch/arm/mm/mmu.c                        |  2 +-
 arch/arm64/mm/mmu.c                      | 91 ++++++++++++++----------
 arch/csky/include/asm/pgalloc.h          |  2 +-
 arch/loongarch/include/asm/pgalloc.h     |  2 +-
 arch/m68k/include/asm/mcf_pgalloc.h      |  8 ++-
 arch/m68k/include/asm/motorola_pgalloc.h | 10 +--
 arch/m68k/mm/motorola.c                  |  6 +-
 arch/microblaze/mm/pgtable.c             |  2 +-
 arch/mips/include/asm/pgalloc.h          |  2 +-
 arch/openrisc/mm/ioremap.c               |  2 +-
 arch/parisc/include/asm/pgalloc.h        |  2 +-
 arch/powerpc/mm/book3s64/pgtable.c       |  2 +-
 arch/powerpc/mm/pgtable-frag.c           | 30 ++++----
 arch/riscv/mm/init.c                     | 26 ++++---
 arch/s390/include/asm/pgalloc.h          |  2 +-
 arch/s390/mm/pgalloc.c                   |  2 +-
 arch/sparc/mm/init_64.c                  | 29 ++++----
 arch/sparc/mm/srmmu.c                    |  2 +-
 arch/x86/mm/pgtable.c                    |  2 +-
 include/asm-generic/pgalloc.h            | 11 ++-
 include/linux/mm.h                       | 10 +--
 21 files changed, 137 insertions(+), 108 deletions(-)


base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:51 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:51 +0000
Subject: [PATCH 02/11] mm: Call ctor/dtor for kernel PTEs
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-3-kevin.brodsky@arm.com>

Since [1], constructors/destructors are expected to be called for
all page table pages, at all levels and for both user and kernel
pgtables. There is however one glaring exception: kernel PTEs are
managed via separate helpers (pte_alloc_kernel/pte_free_kernel),
which do not call the [cd]tor, at least not in the generic
implementation.

The most obvious reason for this anomaly is that init_mm is
special-cased not to use split page table locks. As a result calling
ptlock_init() for PTEs associated with init_mm would be wasteful,
potentially resulting in dynamic memory allocation. However, pgtable
[cd]tors perform other actions - currently related to
accounting/statistics, and potentially more functionally significant
in the future.

Now that pagetable_pte_ctor() is passed the associated mm, we can
make it skip the call to ptlock_init() for init_mm; this allows us
to call the ctor from pte_alloc_one_kernel() too. This is matched by
a call to the pgtable destructor in pte_free_kernel(); no
special-casing is needed on that path, as ptlock_free() is already
called unconditionally. (ptlock_free() is a no-op unless a ptlock
was allocated for the given PTP.)

This patch ensures that all architectures that rely on
<asm-generic/pgalloc.h> call the [cd]tor for kernel PTEs.
pte_free_kernel() cannot be overridden so changing the generic
implementation is sufficient. pte_alloc_one_kernel() can be
overridden using __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL, and a few
architectures implement it by calling the page allocator directly.
We amend those so that they call the generic
__pte_alloc_one_kernel() instead, if possible, ensuring that the
ctor is called.

A few architectures do not use <asm-generic/pgalloc.h>; those will
be taken care of separately.

[1] https://lore.kernel.org/linux-mm/20250103184415.2744423-1-kevin.brodsky at arm.com/

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/csky/include/asm/pgalloc.h | 2 +-
 arch/microblaze/mm/pgtable.c    | 2 +-
 arch/openrisc/mm/ioremap.c      | 2 +-
 include/asm-generic/pgalloc.h   | 7 ++++++-
 include/linux/mm.h              | 2 +-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/csky/include/asm/pgalloc.h b/arch/csky/include/asm/pgalloc.h
index bf8400c28b5a..288dca0d160a 100644
--- a/arch/csky/include/asm/pgalloc.h
+++ b/arch/csky/include/asm/pgalloc.h
@@ -29,7 +29,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 	pte_t *pte;
 	unsigned long i;
 
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
+	pte = __pte_alloc_one_kernel(mm);
 	if (!pte)
 		return NULL;
 
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c
index 9f73265aad4e..e96dd1b7aba4 100644
--- a/arch/microblaze/mm/pgtable.c
+++ b/arch/microblaze/mm/pgtable.c
@@ -245,7 +245,7 @@ unsigned long iopa(unsigned long addr)
 __ref pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 {
 	if (mem_init_done)
-		return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+		return __pte_alloc_one_kernel(mm);
 	else
 		return memblock_alloc_try_nid(PAGE_SIZE, PAGE_SIZE,
 					      MEMBLOCK_LOW_LIMIT,
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
index 8e63e86251ca..3b352f97fecb 100644
--- a/arch/openrisc/mm/ioremap.c
+++ b/arch/openrisc/mm/ioremap.c
@@ -36,7 +36,7 @@ pte_t __ref *pte_alloc_one_kernel(struct mm_struct *mm)
 	pte_t *pte;
 
 	if (likely(mem_init_done)) {
-		pte = (pte_t *)get_zeroed_page(GFP_KERNEL);
+		pte = __pte_alloc_one_kernel(mm);
 	} else {
 		pte = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
 	}
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index e164ca66f0f6..3c8ec3bfea44 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -23,6 +23,11 @@ static inline pte_t *__pte_alloc_one_kernel_noprof(struct mm_struct *mm)
 
 	if (!ptdesc)
 		return NULL;
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
+		pagetable_free(ptdesc);
+		return NULL;
+	}
+
 	return ptdesc_address(ptdesc);
 }
 #define __pte_alloc_one_kernel(...)	alloc_hooks(__pte_alloc_one_kernel_noprof(__VA_ARGS__))
@@ -48,7 +53,7 @@ static inline pte_t *pte_alloc_one_kernel_noprof(struct mm_struct *mm)
  */
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-	pagetable_free(virt_to_ptdesc(pte));
+	pagetable_dtor_free(virt_to_ptdesc(pte));
 }
 
 /**
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d92c16f6cfa2..ee31ffd7ead2 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3018,7 +3018,7 @@ static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
 static inline bool pagetable_pte_ctor(struct mm_struct *mm,
 				      struct ptdesc *ptdesc)
 {
-	if (!ptlock_init(ptdesc))
+	if (mm != &init_mm && !ptlock_init(ptdesc))
 		return false;
 	__pagetable_ctor(ptdesc);
 	return true;
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:50 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:50 +0000
Subject: [PATCH 01/11] mm: Pass mm down to pagetable_{pte,pmd}_ctor
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-2-kevin.brodsky@arm.com>

In preparation for calling constructors for all kernel page tables
while eliding unnecessary ptlock initialisation, let's pass down the
associated mm to the PTE/PMD level ctors. (These are the two levels
where ptlocks are used.)

In most cases the mm is already around at the point of calling the
ctor so we simply pass it down. This is however not the case for
special page table allocators:

* arch/arm/mm/mmu.c
* arch/arm64/mm/mmu.c
* arch/riscv/mm/init.c

In those cases, the page tables being allocated are either for
standard kernel memory (init_mm) or special page directories, which
may not be associated to any mm. For now let's pass NULL as mm; this
will be refined where possible in future patches.

No functional change in this patch.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm/mm/mmu.c                        |  2 +-
 arch/arm64/mm/mmu.c                      |  4 ++--
 arch/loongarch/include/asm/pgalloc.h     |  2 +-
 arch/m68k/include/asm/mcf_pgalloc.h      |  2 +-
 arch/m68k/include/asm/motorola_pgalloc.h | 10 +++++-----
 arch/m68k/mm/motorola.c                  |  6 +++---
 arch/mips/include/asm/pgalloc.h          |  2 +-
 arch/parisc/include/asm/pgalloc.h        |  2 +-
 arch/powerpc/mm/book3s64/pgtable.c       |  2 +-
 arch/powerpc/mm/pgtable-frag.c           |  2 +-
 arch/riscv/mm/init.c                     |  4 ++--
 arch/s390/include/asm/pgalloc.h          |  2 +-
 arch/s390/mm/pgalloc.c                   |  2 +-
 arch/sparc/mm/init_64.c                  |  2 +-
 arch/sparc/mm/srmmu.c                    |  2 +-
 arch/x86/mm/pgtable.c                    |  2 +-
 include/asm-generic/pgalloc.h            |  4 ++--
 include/linux/mm.h                       |  6 ++++--
 18 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index f02f872ea8a9..edb7f56b7c91 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -735,7 +735,7 @@ static void *__init late_alloc(unsigned long sz)
 	void *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & ~__GFP_HIGHMEM,
 			get_order(sz));
 
-	if (!ptdesc || !pagetable_pte_ctor(ptdesc))
+	if (!ptdesc || !pagetable_pte_ctor(NULL, ptdesc))
 		BUG();
 	return ptdesc_to_virt(ptdesc);
 }
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 1dfe1a8efdbe..437d4977bcf5 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -494,9 +494,9 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
 	 * folded, and if so pagetable_pte_ctor() becomes nop.
 	 */
 	if (shift == PAGE_SHIFT)
-		BUG_ON(!pagetable_pte_ctor(ptdesc));
+		BUG_ON(!pagetable_pte_ctor(NULL, ptdesc));
 	else if (shift == PMD_SHIFT)
-		BUG_ON(!pagetable_pmd_ctor(ptdesc));
+		BUG_ON(!pagetable_pmd_ctor(NULL, ptdesc));
 
 	return pa;
 }
diff --git a/arch/loongarch/include/asm/pgalloc.h b/arch/loongarch/include/asm/pgalloc.h
index 7211dff8c969..57b7dbcee259 100644
--- a/arch/loongarch/include/asm/pgalloc.h
+++ b/arch/loongarch/include/asm/pgalloc.h
@@ -72,7 +72,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 	if (!ptdesc)
 		return NULL;
 
-	if (!pagetable_pmd_ctor(ptdesc)) {
+	if (!pagetable_pmd_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h
index 4c648b51e7fd..465a71101b7d 100644
--- a/arch/m68k/include/asm/mcf_pgalloc.h
+++ b/arch/m68k/include/asm/mcf_pgalloc.h
@@ -48,7 +48,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
 
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pte_ctor(ptdesc)) {
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/m68k/include/asm/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
index 5abe7da8ac5a..1091fb0affbe 100644
--- a/arch/m68k/include/asm/motorola_pgalloc.h
+++ b/arch/m68k/include/asm/motorola_pgalloc.h
@@ -15,7 +15,7 @@ enum m68k_table_types {
 };
 
 extern void init_pointer_table(void *table, int type);
-extern void *get_pointer_table(int type);
+extern void *get_pointer_table(struct mm_struct *mm, int type);
 extern int free_pointer_table(void *table, int type);
 
 /*
@@ -26,7 +26,7 @@ extern int free_pointer_table(void *table, int type);
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 {
-	return get_pointer_table(TABLE_PTE);
+	return get_pointer_table(mm, TABLE_PTE);
 }
 
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
@@ -36,7 +36,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
 {
-	return get_pointer_table(TABLE_PTE);
+	return get_pointer_table(mm, TABLE_PTE);
 }
 
 static inline void pte_free(struct mm_struct *mm, pgtable_t pgtable)
@@ -53,7 +53,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pgtable,
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	return get_pointer_table(TABLE_PMD);
+	return get_pointer_table(mm, TABLE_PMD);
 }
 
 static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -75,7 +75,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-	return get_pointer_table(TABLE_PGD);
+	return get_pointer_table(mm, TABLE_PGD);
 }
 
 
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 73651e093c4d..6ab3ef39ba7a 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -139,7 +139,7 @@ void __init init_pointer_table(void *table, int type)
 	return;
 }
 
-void *get_pointer_table(int type)
+void *get_pointer_table(struct mm_struct *mm, int type)
 {
 	ptable_desc *dp = ptable_list[type].next;
 	unsigned int mask = list_empty(&ptable_list[type]) ? 0 : PD_MARKBITS(dp);
@@ -164,10 +164,10 @@ void *get_pointer_table(int type)
 			 * m68k doesn't have SPLIT_PTE_PTLOCKS for not having
 			 * SMP.
 			 */
-			pagetable_pte_ctor(virt_to_ptdesc(page));
+			pagetable_pte_ctor(mm, virt_to_ptdesc(page));
 			break;
 		case TABLE_PMD:
-			pagetable_pmd_ctor(virt_to_ptdesc(page));
+			pagetable_pmd_ctor(mm, virt_to_ptdesc(page));
 			break;
 		case TABLE_PGD:
 			pagetable_pgd_ctor(virt_to_ptdesc(page));
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index 26c7a6ede983..415237af4029 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -65,7 +65,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 	if (!ptdesc)
 		return NULL;
 
-	if (!pagetable_pmd_ctor(ptdesc)) {
+	if (!pagetable_pmd_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/parisc/include/asm/pgalloc.h b/arch/parisc/include/asm/pgalloc.h
index 2ca74a56415c..3b84ee93edaa 100644
--- a/arch/parisc/include/asm/pgalloc.h
+++ b/arch/parisc/include/asm/pgalloc.h
@@ -39,7 +39,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 	ptdesc = pagetable_alloc(gfp, PMD_TABLE_ORDER);
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pmd_ctor(ptdesc)) {
+	if (!pagetable_pmd_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index ce64abea9e3e..83afc4e72088 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -423,7 +423,7 @@ static pmd_t *__alloc_for_pmdcache(struct mm_struct *mm)
 	ptdesc = pagetable_alloc(gfp, 0);
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pmd_ctor(ptdesc)) {
+	if (!pagetable_pmd_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c
index 713268ccb1a0..387e9b1fe12c 100644
--- a/arch/powerpc/mm/pgtable-frag.c
+++ b/arch/powerpc/mm/pgtable-frag.c
@@ -61,7 +61,7 @@ static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel)
 		ptdesc = pagetable_alloc(PGALLOC_GFP | __GFP_ACCOUNT, 0);
 		if (!ptdesc)
 			return NULL;
-		if (!pagetable_pte_ctor(ptdesc)) {
+		if (!pagetable_pte_ctor(mm, ptdesc)) {
 			pagetable_free(ptdesc);
 			return NULL;
 		}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 15b2eda4c364..703c3648cfa9 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -409,7 +409,7 @@ static phys_addr_t __meminit alloc_pte_late(uintptr_t va)
 {
 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
 
-	BUG_ON(!ptdesc || !pagetable_pte_ctor(ptdesc));
+	BUG_ON(!ptdesc || !pagetable_pte_ctor(NULL, ptdesc));
 	return __pa((pte_t *)ptdesc_address(ptdesc));
 }
 
@@ -489,7 +489,7 @@ static phys_addr_t __meminit alloc_pmd_late(uintptr_t va)
 {
 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
 
-	BUG_ON(!ptdesc || !pagetable_pmd_ctor(ptdesc));
+	BUG_ON(!ptdesc || !pagetable_pmd_ctor(NULL, ptdesc));
 	return __pa((pmd_t *)ptdesc_address(ptdesc));
 }
 
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index b19b6ed2ab53..cd65b93d87e9 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -98,7 +98,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 	if (!table)
 		return NULL;
 	crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
-	if (!pagetable_pmd_ctor(virt_to_ptdesc(table))) {
+	if (!pagetable_pmd_ctor(mm, virt_to_ptdesc(table))) {
 		crst_table_free(mm, table);
 		return NULL;
 	}
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 30387a6e98ff..35b0ab6fab24 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -170,7 +170,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
 	ptdesc = pagetable_alloc(GFP_KERNEL, 0);
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pte_ctor(ptdesc)) {
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 05882bca5b73..cd60a0a8ca0e 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2899,7 +2899,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm)
 
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pte_ctor(ptdesc)) {
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index dd32711022f5..f8fb4911d360 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -350,7 +350,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm)
 	page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT);
 	spin_lock(&mm->page_table_lock);
 	if (page_ref_inc_return(page) == 2 &&
-			!pagetable_pte_ctor(page_ptdesc(page))) {
+			!pagetable_pte_ctor(mm, page_ptdesc(page))) {
 		page_ref_dec(page);
 		ptep = NULL;
 	}
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 1fef5ad32d5a..2d20f021c50b 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -249,7 +249,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[], int count)
 
 		if (!ptdesc)
 			failed = true;
-		if (ptdesc && !pagetable_pmd_ctor(ptdesc)) {
+		if (ptdesc && !pagetable_pmd_ctor(mm, ptdesc)) {
 			pagetable_free(ptdesc);
 			ptdesc = NULL;
 			failed = true;
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index 892ece4558a2..e164ca66f0f6 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -70,7 +70,7 @@ static inline pgtable_t __pte_alloc_one_noprof(struct mm_struct *mm, gfp_t gfp)
 	ptdesc = pagetable_alloc_noprof(gfp, 0);
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pte_ctor(ptdesc)) {
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
@@ -137,7 +137,7 @@ static inline pmd_t *pmd_alloc_one_noprof(struct mm_struct *mm, unsigned long ad
 	ptdesc = pagetable_alloc_noprof(gfp, 0);
 	if (!ptdesc)
 		return NULL;
-	if (!pagetable_pmd_ctor(ptdesc)) {
+	if (!pagetable_pmd_ctor(mm, ptdesc)) {
 		pagetable_free(ptdesc);
 		return NULL;
 	}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8483e09aeb2c..d92c16f6cfa2 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3015,7 +3015,8 @@ static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
 	pagetable_free(ptdesc);
 }
 
-static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
+static inline bool pagetable_pte_ctor(struct mm_struct *mm,
+				      struct ptdesc *ptdesc)
 {
 	if (!ptlock_init(ptdesc))
 		return false;
@@ -3121,7 +3122,8 @@ static inline spinlock_t *pmd_lock(struct mm_struct *mm, pmd_t *pmd)
 	return ptl;
 }
 
-static inline bool pagetable_pmd_ctor(struct ptdesc *ptdesc)
+static inline bool pagetable_pmd_ctor(struct mm_struct *mm,
+				      struct ptdesc *ptdesc)
 {
 	if (!pmd_ptlock_init(ptdesc))
 		return false;
-- 
2.47.0



From kevin.brodsky at arm.com  Mon Mar 17 07:16:52 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 17 Mar 2025 14:16:52 +0000
Subject: [PATCH 03/11] m68k: mm: Call ctor/dtor for kernel PTEs
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <20250317141700.3701581-4-kevin.brodsky@arm.com>

The generic implementation of pte_{alloc_one,free}_kernel now calls
the [cd]tor. Align the m68k/ColdFire implementation of those
functions by calling the [cd]tor explicitly.

Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/m68k/include/asm/mcf_pgalloc.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h
index 465a71101b7d..fc5454d37da3 100644
--- a/arch/m68k/include/asm/mcf_pgalloc.h
+++ b/arch/m68k/include/asm/mcf_pgalloc.h
@@ -7,7 +7,7 @@
 
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-	pagetable_free(virt_to_ptdesc(pte));
+	pagetable_dtor_free(virt_to_ptdesc(pte));
 }
 
 extern const char bad_pmd_string[];
@@ -19,6 +19,10 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 
 	if (!ptdesc)
 		return NULL;
+	if (!pagetable_pte_ctor(mm, ptdesc)) {
+		pagetable_free(ptdesc);
+		return NULL;
+	}
 
 	return ptdesc_address(ptdesc);
 }
-- 
2.47.0



From ariel.dalessandro at collabora.com  Mon Mar 17 07:30:59 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:30:59 -0300
Subject: [PATCH v3 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250317144436.2bcc17ed@collabora.com>
References: <20250317124044.16257-1-ariel.dalessandro@collabora.com>
 <20250317124044.16257-5-ariel.dalessandro@collabora.com>
 <20250317144436.2bcc17ed@collabora.com>
Message-ID: <992360e3-632c-4a0e-bb84-a72be7d7cd37@collabora.com>

Boris,

On 3/17/25 10:44 AM, Boris Brezillon wrote:
> On Mon, 17 Mar 2025 09:40:42 -0300
> Ariel D'Alessandro <ariel.dalessandro at collabora.com> wrote:
> 
>> +static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
>> +				  enum io_pgtable_fmt fmt)
>> +{
>> +	struct panfrost_device *pfdev = mmu->pfdev;
>> +
>> +	switch (fmt) {
>> +	case ARM_64_LPAE_S1:
>> +		return mmu_cfg_init_aarch64_4k(mmu);
>> +	case ARM_MALI_LPAE:
>> +		return mmu_cfg_init_mali_lpae(mmu);
>> +	default:
>> +		/* This should never happen */
>> +		return drm_WARN_ON(pfdev->ddev, -EINVAL);
> 
> This won't return -EINVAL, but !!(-EINVAL), AKA true. We should do
> 
> 	default:
> 		drm_WARN(ptdev->ddev, "Invalid pgtable format");
> 		return -EINVAL;
> 
> instead.

Ah, good catch. I missed that from the WARN_ON definition:

         int __ret_warn_on = !!(condition);

Thanks, will fix in v4.

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From maz at kernel.org  Mon Mar 17 07:49:24 2025
From: maz at kernel.org (Marc Zyngier)
Date: Mon, 17 Mar 2025 14:49:24 +0000
Subject: [PATCH v5 3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <202503172023.fzyJ3TMB-lkp@intel.com>
References: <20250315-pmc-v5-3-ecee87dab216@daynix.com>
	<202503172023.fzyJ3TMB-lkp@intel.com>
Message-ID: <86y0x3n24r.wl-maz@kernel.org>

On Mon, 17 Mar 2025 13:02:47 +0000,
kernel test robot <lkp at intel.com> wrote:
> 
> Hi Akihiko,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on 80e54e84911a923c40d7bee33a34c1b4be148d7a]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Akihiko-Odaki/KVM-arm64-PMU-Set-raw-values-from-user-to-PM-C-I-NTEN-SET-CLR-PMOVS-SET-CLR/20250315-173731
> base:   80e54e84911a923c40d7bee33a34c1b4be148d7a
> patch link:    https://lore.kernel.org/r/20250315-pmc-v5-3-ecee87dab216%40daynix.com
> patch subject: [PATCH v5 3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
> config: arm64-randconfig-r122-20250317 (https://download.01.org/0day-ci/archive/20250317/202503172023.fzyJ3TMB-lkp at intel.com/config)
> compiler: aarch64-linux-gcc (GCC) 14.2.0
> reproduce: (https://download.01.org/0day-ci/archive/20250317/202503172023.fzyJ3TMB-lkp at intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202503172023.fzyJ3TMB-lkp at intel.com/
> 
> All errors (new ones prefixed by >>):
> 
>    arch/arm64/kvm/sys_regs.c: In function 'set_pmu_evcntr':
> >> arch/arm64/kvm/sys_regs.c:975:9: error: implicit declaration of function 'kvm_pmu_set_counter_value_user'; did you mean 'kvm_pmu_set_counter_value'? [-Wimplicit-function-declaration]
>      975 |         kvm_pmu_set_counter_value_user(vcpu, idx, val);
>          |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>          |         kvm_pmu_set_counter_value
> 
> 
> vim +975 arch/arm64/kvm/sys_regs.c
> 
>    962	
>    963	static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
>    964				  u64 val)
>    965	{
>    966		u64 idx;
>    967	
>    968		if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
>    969			/* PMCCNTR_EL0 */
>    970			idx = ARMV8_PMU_CYCLE_IDX;
>    971		else
>    972			/* PMEVCNTRn_EL0 */
>    973			idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
>    974	
>  > 975		kvm_pmu_set_counter_value_user(vcpu, idx, val);
>    976		return 0;
>    977	}
>    978	
> 

Looks like a case of missing stub definitions when
CONFIG_HW_PERF_EVENTS isn't selected.

	M.

-- 
Without deviation from the norm, progress is not possible.


From luca.ceresoli at bootlin.com  Mon Mar 17 07:56:07 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Mon, 17 Mar 2025 15:56:07 +0100
Subject: [PATCH v7 00/11] drm/bridge: add devm_drm_bridge_alloc() with
 bridge refcount
In-Reply-To: <20250314-daft-woodoo-cheetah-e029c5@houat>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-daft-woodoo-cheetah-e029c5@houat>
Message-ID: <20250317155607.68cff522@booty>

Hello Maxime,

On Fri, 14 Mar 2025 19:21:01 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> Hi,
> 
> On Fri, Mar 14, 2025 at 11:31:13AM +0100, Luca Ceresoli wrote:
> > This series improves the way DRM bridges are allocated and
> > initialized and makes them reference-counted. The goal of reference
> > counting is to avoid use-after-free by drivers which got a pointer
> > to a bridge and keep it stored and used even after the bridge has
> > been deallocated.
> > 
> > The overall goal is supporting Linux devices with a DRM pipeline
> > whose final components can be hot-plugged and hot-unplugged,
> > including one or more bridges. For more details see the big picture
> > [0].
> > 
> > DRM bridge drivers will have to be adapted to the new API, which is
> > pretty simple for most cases. Refcounting will have to be adopted
> > on the two sides: all functions returning a bridge pointer and all
> > code obtaining such a pointer. This series has just an overview of
> > some of those conversions, because for now the main goal is to
> > agree on the API.
> > 
> > Series layout:
> > 
> >  1. Add the new API and refcounting:
> > 
> >     drm/bridge: add devm_drm_bridge_alloc()
> >     drm/bridge: add support for refcounting
> > 
> >  2. get/put the reference in basic operations in the bridge core:
> > 
> >     drm/bridge: get/put the bridge reference in
> > drm_bridge_add/remove() drm/bridge: get/put the bridge reference in
> > drm_bridge_attach/detach()
> > 
> >  3. as an example of changes for bridge consumers, get a reference
> > for the bridge returned by drm_bridge_chain_get_first_bridge(),
> > have it put by all callers (all users will be covered later on
> > separately):
> > 
> >     drm/bridge: add a cleanup action for scope-based
> > drm_bridge_put() invocation drm/bridge: get the bridge returned by
> > drm_bridge_chain_get_first_bridge() drm/mxsfb: put the bridge
> > returned by drm_bridge_chain_get_first_bridge() drm/atomic-helper:
> > put the bridge returned by drm_bridge_chain_get_first_bridge()
> > drm/probe-helper: put the bridge returned by
> > drm_bridge_chain_get_first_bridge()
> > 
> >  4. convert a few bridge drivers (bridge providers) to the new API:
> > 
> >     drm/bridge: ti-sn65dsi83: use dynamic lifetime management
> >     drm/bridge: samsung-dsim: use dynamic lifetime management
> > 
> > This work was formerly a part of my v6 DRM bridge hotplug
> > series[0], now split as a standalone series with many improvements,
> > hence the "v7" version number.  
> 
> Except for one patch where I had comments, I think the series is in
> excellent shape. We're still missing a couple of things to close this
> topic though:
> 
>   - Converting the other bridge iterators/accessors to take / put the
> references

I sent a couple in this series as you had asked, to show how conversion
looks like. But I have a large part of this conversion partially done
already, and it is the largest part of the refcounting work in terms of
touched files due to the large number of drivers using the iterators
and accessors. Here are the functions to convert:

 A) drm_bridge_chain_get_first_bridge
 B) drm_bridge_get_prev_bridge
 C) drm_bridge_get_next_bridge
 D) drm_for_each_bridge_in_chain
 E) drm_bridge_connector_init
 F) of_drm_find_bridge

A) is present in this series as an example but I don't think it should
be applied until all bridge drivers are converted to
drm_bridge_alloc(). Otherwise for not-yet-converted bridge drivers we'd
have drm_bridge_get/put() operating on an uninitialized kref, and
__drm_bridge_free() called on non-refcounted bridges, so I think we'd
see fireworks.

In the previous iteration I used drm_bridge_is_refcounted() in
drm_bridge_get/put() to allow a progressive migration, but if we want
to convert everything in a single run we need to first convert all
bridges to drm_bridge_alloc() and then convert all accessors.

The same reasoning applies to patches 3-4 which add get/put to
drm_bridge_add/remove() and _attach/detach().

B) to E) are ready in my work branch, about 20 patches in total.
Indeed item E) is a special case but it is handled there too.

Item F) is the beast, because of the reverse call graph of
of_drm_find_bridge() which includes drm_of_find_panel_or_bridge() and
then *_of_get_bridge(), each having a few dozen callers, and leading
to the panel_bridge topic. I have converted maybe half of the users of
accessors in F), it's 35 patches but it's the easy half and I still need
to tackle to hardest ones.

>   - Mass converting the drivers to devm_drm_bridge_alloc

Again I sent a couple in this series as you had asked, to show how
conversion looks like for the typical bridge driver. There are ~70
drivers to convert in total and I think most will be easy as the two
examples presented here.

I think this should be merged entirely before merging any accessor
changes, as explained above.

>   - Documenting somewhere (possibly in drm_bridge_init?) that it
> really shouldn't be used anymore

I'm afraid there is no drm_bridge_init(), bridge drivers just do
[devm_]kzalloc and set fields explicitly. So I don't think there is a
place to document this.

However I used to have a documentation patch until v6 [0], and I think
it should be revived and resent at some point, after removing the
"legacy mode" as we are converting all drivers at once. BTW I also have
a kunittest patch that should be revived. Do you still prefer me to
resend these two patches as a separate series, waiting after the API in
this series is applied?

Overall, I think this could be the path forward, let me know if
youthink it should be done differently:

 A. have patches 1 and 2 of this series applied
    (why not, even patches 10-11)
 B. after (A), send series to convert all bridge drivers to new API
    (includes patches 10-11 of this series if not applied already)
 C. after (A), send documentation and kunittest patches
 D. after (B), add get/put to drm_bridge_add/remove() + attach/detech()
    (patches 3-4 in this series)
 E. after (B), send series to convert accessors (including patches 5-9
    in this series which convert drm_bridge_chain_get_first_bridge()
    and its users)

[0] https://lore.kernel.org/lkml/20250206-hotplug-drm-bridge-v6-18-9d6f2c9c3058 at bootlin.com/

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From luca.ceresoli at bootlin.com  Mon Mar 17 07:56:30 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Mon, 17 Mar 2025 15:56:30 +0100
Subject: [PATCH v7 02/11] drm/bridge: add support for refcounting
In-Reply-To: <20250314-amorphous-congenial-woodlouse-f50bde@houat>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-drm-bridge-refcount-v7-2-152571f8c694@bootlin.com>
 <20250314-amorphous-congenial-woodlouse-f50bde@houat>
Message-ID: <20250317155630.020881e2@booty>

Hello Maxime,

thanks for the very prompt feedback!

On Fri, 14 Mar 2025 19:04:40 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> On Fri, Mar 14, 2025 at 11:31:15AM +0100, Luca Ceresoli wrote:
> > DRM bridges are currently considered as a fixed element of a DRM card, and
> > thus their lifetime is assumed to extend for as long as the card
> > exists. New use cases, such as hot-pluggable hardware with video bridges,
> > require DRM bridges to be added to and removed from a DRM card without
> > tearing the card down. This is possible for connectors already (used by DP
> > MST), it is now needed for DRM bridges as well.
> > 
> > As a first preliminary step, make bridges reference-counted to allow a
> > struct drm_bridge (along with the private driver structure embedding it) to
> > stay allocated even after the driver has been removed, until the last
> > reference is put.
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > 
> > ---
> > 
> > Changes in v7:
> >  - export drm_bridge_put_void
> >  - struct drm_bridge: use container pointer instead of container_offset
> >  - remove drm_bridge_is_refcounted()
> >  - remove all DRM_DEBUG()s
> >  - drm_bridge_get/put: accept NULL pointer and return the bridge pointer to
> >    allow pass-through calls
> >  - extract to separate patches:
> >     - the addition of drm_bridge_alloc
> >     - the addition of drm_bridge_get/put() to drm_bridge_add/remove()
> >     - the addition of drm_bridge_get/put() to drm_bridge_attach/detach()
> >  - fix a typo, slightly improve kerneldoc
> > 
> > Changes in v6:
> >  - use drm_warn, not WARN_ON (Jani Nikula)
> >  - Add devm_drm_bridge_alloc() to replace drm_bridge_init() (similar to
> >    drmm_encoder_alloc)
> >  - Remove .destroy func: deallocation is done via the struct offset
> >    computed by the devm_drm_bridge_alloc() macro
> >  - use fixed free callback, as the same callback is used in all cases
> >    anyway (remove free_cb, add bool is_refcounted)
> >  - add drm_bridge_get/put() to drm_bridge_attach/detach() (add the bridge
> >    to a list)
> >  - make some DRM_DEBUG() strings more informative
> > 
> > This patch was added in v5.
> > ---
> >  drivers/gpu/drm/drm_bridge.c | 33 +++++++++++++++-
> >  include/drm/drm_bridge.h     | 91 ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 123 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 96df717b2caeb41d45346ded576eaeb2806fd051..2ba0dac9bfc2dfd709d5e2457d69067c7324972c 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c
> > @@ -199,23 +199,54 @@
> >  static DEFINE_MUTEX(bridge_lock);
> >  static LIST_HEAD(bridge_list);
> >  
> > +void __drm_bridge_free(struct kref *kref)
> > +{
> > +	struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
> > +
> > +	kfree(bridge->container);
> > +}
> > +EXPORT_SYMBOL(__drm_bridge_free);
> > +
> > +/**
> > + * drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
> > + *
> > + * @data: pointer to @struct drm_bridge, cast to a void pointer
> > + *
> > + * Wrapper of drm_bridge_put() to be used when a function taking a void
> > + * pointer is needed, for example as a devm action.
> > + */
> > +void drm_bridge_put_void(void *data)
> > +{
> > +	struct drm_bridge *bridge = (struct drm_bridge *)data;
> > +
> > +	drm_bridge_put(bridge);
> > +}
> > +EXPORT_SYMBOL(drm_bridge_put_void);
> > +
> >  void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
> >  			      const struct drm_bridge_funcs *funcs)
> >  {
> >  	void *container;
> >  	struct drm_bridge *bridge;
> > +	int err;
> >  
> >  	if (!funcs) {
> >  		dev_warn(dev, "Missing funcs pointer\n");
> >  		return ERR_PTR(-EINVAL);
> >  	}
> >  
> > -	container = devm_kzalloc(dev, size, GFP_KERNEL);
> > +	container = kzalloc(size, GFP_KERNEL);
> >  	if (!container)
> >  		return ERR_PTR(-ENOMEM);
> >  
> >  	bridge = container + offset;
> > +	bridge->container = container;
> >  	bridge->funcs = funcs;
> > +	kref_init(&bridge->refcount);
> > +
> > +	err = devm_add_action_or_reset(dev, drm_bridge_put_void, bridge);
> > +	if (err)
> > +		return ERR_PTR(err);
> >  
> >  	return container;
> >  }
> > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> > index dae463b30542d586a595b67f7bdf5a5e898e9572..5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47 100644
> > --- a/include/drm/drm_bridge.h
> > +++ b/include/drm/drm_bridge.h
> > @@ -840,6 +840,17 @@ struct drm_bridge {
> >  	const struct drm_bridge_timings *timings;
> >  	/** @funcs: control functions */
> >  	const struct drm_bridge_funcs *funcs;
> > +
> > +	/**
> > +	 * @container: Pointer to the private driver struct embedding this
> > +	 * @struct drm_bridge.
> > +	 */
> > +	void *container;  
> 
> newline here
> 
> > +	/**
> > +	 * @refcount: reference count of users referencing this bridge.
> > +	 */
> > +	struct kref refcount;
> > +
> >  	/** @driver_private: pointer to the bridge driver's internal context */
> >  	void *driver_private;
> >  	/** @ops: bitmask of operations supported by the bridge */
> > @@ -941,6 +952,82 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
> >  	return container_of(priv, struct drm_bridge, base);
> >  }
> >  
> > +void __drm_bridge_free(struct kref *kref);
> > +
> > +/**
> > + * drm_bridge_get - Acquire a bridge reference
> > + * @bridge: DRM bridge
> > + *
> > + * This function increments the bridge's refcount.
> > + *
> > + * Returns:
> > + * Pointer to @bridge.
> > + */
> > +static inline struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge)
> > +{
> > +	if (!bridge)
> > +		return bridge;
> > +
> > +	kref_get(&bridge->refcount);
> > +
> > +	return bridge;
> > +}
> > +
> > +/**
> > + * drm_bridge_put - Release a bridge reference
> > + * @bridge: DRM bridge
> > + *
> > + * This function decrements the bridge's reference count and frees the
> > + * object if the reference count drops to zero.
> > + *
> > + * See also drm_bridge_put_and_clear() which is more handy in many cases.
> > + *
> > + * Returns:
> > + * Pointer to @bridge.
> > + */
> > +static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
> > +{
> > +	if (!bridge)
> > +		return bridge;
> > +
> > +	kref_put(&bridge->refcount, __drm_bridge_free);
> > +
> > +	return bridge;
> > +}  
> 
> I'm not sure we discussed it already, but why do you need to put both
> drm_bridge_get and drm_bridge_put into the header, and thus export
> __drm_bridge_free?
> 
> I'd expect both to be in drm_bridge.c?

I don't think we had discussed this before. There is no strong reason,
just a few small ones, and one is related to the DRM_DEBUG() calls that
I have removed from this series, so it's fine to move back
drm_bridge_get/put() in the .c file, and make __drm_bridge_free()
private again.

> > +/**
> > + * drm_bridge_put_and_clear - Given a bridge pointer, clear the pointer
> > + *                            then put the bridge
> > + *
> > + * @bridge_pp: pointer to pointer to a struct drm_bridge
> > + *
> > + * Helper to put a DRM bridge (whose pointer is passed), but only after
> > + * setting its pointer to NULL. Useful for drivers having struct drm_bridge
> > + * pointers they need to dispose of, without leaving a use-after-free
> > + * window where the pointed bridge might have been freed while still
> > + * holding a pointer to it.
> > + *
> > + * For example a driver having this private struct::
> > + *
> > + *     struct my_bridge {
> > + *         struct drm_bridge *remote_bridge;
> > + *         ...
> > + *     };
> > + *
> > + * can dispose of remote_bridge using::
> > + *
> > + *     drm_bridge_put_and_clear(&my_bridge->remote_bridge);
> > + */
> > +static inline void drm_bridge_put_and_clear(struct drm_bridge **bridge_pp)
> > +{
> > +	struct drm_bridge *bridge = *bridge_pp;
> > +
> > +	*bridge_pp = NULL;
> > +	drm_bridge_put(bridge);
> > +}  
> 
> I'm not convinced we need that one for now, and it doesn't look like
> there's a user for it in your series, so I'd rather introduce it once we
> actually need it.

Indeed, that's a leftover I missed when extracting this series for the
branch with the entire work. I'm definitely removing it in the next
iteration.

> >  void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
> >  			      const struct drm_bridge_funcs *funcs);
> >  
> > @@ -951,6 +1038,10 @@ void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
> >   * @member: the name of the &drm_bridge within @type
> >   * @funcs: callbacks for this bridge
> >   *
> > + * The returned refcount is initialized to 1.  
> 
> I'm confused, there's no returned refcount here? Or did you mean the
> returned bridge refcount?

Indeed, good catch!

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From luca.ceresoli at bootlin.com  Mon Mar 17 07:57:07 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Mon, 17 Mar 2025 15:57:07 +0100
Subject: [PATCH v7 05/11] drm/bridge: add a cleanup action for
 scope-based drm_bridge_put() invocation
In-Reply-To: <20250314-banana-toucanet-of-masquerade-8eeb4e@houat>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-drm-bridge-refcount-v7-5-152571f8c694@bootlin.com>
 <20250314-banana-toucanet-of-masquerade-8eeb4e@houat>
Message-ID: <20250317155707.6d1055f1@booty>

On Fri, 14 Mar 2025 19:08:22 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> On Fri, Mar 14, 2025 at 11:31:18AM +0100, Luca Ceresoli wrote:
> > Many functions get a drm_bridge pointer, only use it in the function body
> > (or a smaller scope such as a loop body), and don't store it. In these
> > cases they always need to drm_bridge_put() it before returning (or exiting
> > the scope).
> > 
> > Some of those functions have complex code paths with multiple return points
> > or loop break/continue. This makes adding drm_bridge_put() in the right
> > places tricky, ugly and error prone in case of future code changes.
> > 
> > Others use the bridge pointer in the return statement and would need to
> > split the return line to fit the drm_bridge_put, which is a bit annoying:
> > 
> >   -return some_thing(bridge);
> >   +ret = some_thing(bridge);
> >   +drm_bridge_put(bridge);
> >   +return ret;
> > 
> > To make it easier for all of them to put the bridge reference correctly
> > without complicating code, define a scope-based cleanup action to be used
> > with __free().
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> > 
> > ---
> > 
> > This patch was added in v7.
> > ---
> >  include/drm/drm_bridge.h | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> > index 5c1e2b9cafb12eb429d1f5d3ef312e6cf9b54f47..a5accd64c364ebb57903ae1e7459034ad9ebf4f3 100644
> > --- a/include/drm/drm_bridge.h
> > +++ b/include/drm/drm_bridge.h
> > @@ -23,6 +23,7 @@
> >  #ifndef __DRM_BRIDGE_H__
> >  #define __DRM_BRIDGE_H__
> >  
> > +#include <linux/cleanup.h>
> >  #include <linux/ctype.h>
> >  #include <linux/list.h>
> >  #include <linux/mutex.h>
> > @@ -995,6 +996,9 @@ static inline struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
> >  	return bridge;
> >  }
> >  
> > +/* Cleanup action for use with __free() */
> > +DEFINE_FREE(drm_bridge_put, struct drm_bridge *, if (_T) drm_bridge_put(_T))
> > +  
> 
> IIRC, drm_bridge_put already checks for the pointer being null before
> dereferencing it, right? Then we can probably simplify the macro here.

drm_bridge_put() does the NULL-check, yes. However I have kept the 'if'
here for consistency with all other DEFINE_FREE()s in the kernel which
also have an 'if' even when the called function does it as well.

Moreover, as per discussion after patch 2, in the next iteration I'm
moving drm_bridge_put() back to a an exported symbol instead of an
inline. So the 'if' here will save a useless function call on NULL.

For the two above reasons I'm rather inclined to keeping this line as
is.

> Either way,
> 
> Reviewed-by: Maxime Ripard <mripard at kernel.org>

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From luca.ceresoli at bootlin.com  Mon Mar 17 07:57:30 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Mon, 17 Mar 2025 15:57:30 +0100
Subject: [PATCH v7 06/11] drm/bridge: get the bridge returned by
 drm_bridge_chain_get_first_bridge()
In-Reply-To: <20250314-aspiring-myrtle-husky-a5f4ac@houat>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
	<20250314-drm-bridge-refcount-v7-6-152571f8c694@bootlin.com>
	<20250314-aspiring-myrtle-husky-a5f4ac@houat>
Message-ID: <20250317155730.4a328641@booty>

On Fri, 14 Mar 2025 19:10:41 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> On Fri, Mar 14, 2025 at 11:31:19AM +0100, Luca Ceresoli wrote:
> > drm_bridge_chain_get_first_bridge() returns a bridge pointer that the
> > caller could hold for a long time. Increment the refcount of the returned
> > bridge and document it must be put by the caller.
> > 
> > Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

...

> > @@ -1112,8 +1115,8 @@ drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
> >  static inline struct drm_bridge *
> >  drm_bridge_chain_get_first_bridge(struct drm_encoder *encoder)
> >  {
> > -	return list_first_entry_or_null(&encoder->bridge_chain,
> > -					struct drm_bridge, chain_node);
> > +	return drm_bridge_get(list_first_entry_or_null(&encoder->bridge_chain,
> > +						       struct drm_bridge, chain_node));
> >  }  
> 
> We'll need to modify drm_bridge_get_next_bridge, drm_bridge_get_prev_bridge, and
> drm_for_each_bridge_in_chain in a similar manner, but for this one

Sure. I'm discussing this in the cover letter.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From irogers at google.com  Mon Mar 17 08:01:55 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 08:01:55 -0700
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in the build
In-Reply-To: <Z9YHCzINiu4uBQ8B@google.com>
References: <20250308003209.234114-1-irogers@google.com> <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1> <Z9M9-YhDJg3NgiUy@x1> <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com> <Z9RjHpEJGWtj8PAM@x1> <Z9Rm0W6YLpxKIcI1@x1>
 <Z9SWDGsdgagMr8PV@x1> <Z9YHCzINiu4uBQ8B@google.com>
Message-ID: <CAP-5=fVoSVttcgFFxWrWAGXyXJm52LF8yaNR564HWcf0Jx4eUA@mail.gmail.com>

On Sat, Mar 15, 2025 at 4:02?PM Namhyung Kim <namhyung at kernel.org> wrote:
>
> On Fri, Mar 14, 2025 at 05:48:12PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Fri, Mar 14, 2025 at 02:26:41PM -0300, Arnaldo Carvalho de Melo wrote:
> > > it finds the pair, but then its sc->args has a bogus pointer... I'll see
> > > where this isn't being initialized...
> >
> > Breakpoint 4, trace__find_usable_bpf_prog_entry (trace=0x7fffffffa510, sc=0x1046f10) at builtin-trace.c:3874
> > 3874                  bool is_candidate = false;
> > (gdb) n
> > 3876                  if (pair == NULL || pair == sc ||
> > (gdb) p pair
> > $7 = (struct syscall *) 0x1083c50
> > (gdb) p pair->name
> > $8 = 0x81478e "accept4"
> > (gdb) n
> > 3877                      pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
> > (gdb) p i
> > $9 = 1
> > (gdb) n
> > 3876                  if (pair == NULL || pair == sc ||
> > (gdb) n
> > 3880                  printf("sc=%p\n", sc); fflush(stdout);
> > (gdb) n
> > sc=0x1046f10
> > 3881                  printf("sc->name=%p\n", sc->name); fflush(stdout);
> > (gdb) n
> > sc->name=0x6c66202c786c3830
> > 3882                  printf("sc->nr_args=%d, sc->args=%p\n", sc->nr_args, sc->args); fflush(stdout);
> > (gdb) p sc->nr_args
> > $10 = 1935635045
> > (gdb) p sc->args
> > $11 = (struct tep_format_field *) 0x257830203a6e656c
> > (gdb) p *sc
> > $12 = {e_machine = 540697702, id = 807761968, tp_format = 0x657075202c786c38, nr_args = 1935635045, args_size = 1634427759, bpf_prog = {sys_enter = 0x257830203a726464,
> >     sys_exit = 0x7075202c786c3830}, is_exit = 101, is_open = 101, nonexistent = 114, use_btf = 95, args = 0x257830203a6e656c,
> >   name = 0x6c66202c786c3830 <error: Cannot access memory at address 0x6c66202c786c3830>, fmt = 0x257830203a736761, arg_fmt = 0x786c3830}
> > (gdb)
> >
> > Ok, ran out of time, but if I simple avoid the second loop in:
> >
> > static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
> >
> >
> > I.e. the one that starts with:
> >
> >         /*
> >          * Now lets do a second pass looking for enabled syscalls without
> >          * an augmenter that have a signature that is a superset of another
> >          * syscall with an augmenter so that we can auto-reuse it.
> >
> > This:
> >
> > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> > index e0434f7dc67cb988..3664bb512c70cabf 100644
> > --- a/tools/perf/builtin-trace.c
> > +++ b/tools/perf/builtin-trace.c
> > @@ -3989,6 +3989,8 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
> >                         goto out;
> >         }
> >
> > +       return 0;
> > +
> >         /*
> >          * Now lets do a second pass looking for enabled syscalls without
> >          * an augmenter that have a signature that is a superset of another
> > ? [acme at toolbox perf-tools-next]$
> >
> >
> > Then all works, we don't reuse any BPF program, but then that is an
> > heuristic anyway, that is tried becuase landlock_add_rule has a pointer
> > argument:
> >
> > root at number:~# perf trace -e landlock_add_rule perf test -w landlock
> >      0.000 ( 0.003 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_PATH_BENEATH, rule_attr: 0x7fff6f2bb550, flags: 45) = -1 EINVAL (Invalid argument)
> >      0.004 ( 0.001 ms): perf/71034 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7fff6f2bb540, flags: 45) = -1 EINVAL (Invalid argument)
> > root at number:~# perf test enum
> > 105: perf trace enum augmentation tests                              : Ok
> > root at number:~#
> >
> > So its some sort of syncronization on the various new tables, sorted by
> > name, etc that then when iterating over the syscalls ends up using a sc
> > that is not initialized.
>
> Right, I've realized that calling trace__syscall_info() can invalidate
> the existing sc since it calls trace__find_syscall() which reallocates
> and resorts the syscall table.  That's why it was ok when no filter was
> used since it'd allocate the whole table in the first pass.  Otherwise
> it looks for a pair syscall while holding the original sc but calling
> the function would invalidate the sc.
>
> What about this (on top of my earlier fix)?

LGTM.
Reviewed-by: Ian Rogers <irogers at google.com>

Thanks,
Ian

> Thanks,
> Namhyung
>
>
> ---8<---
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 49199d753b7cafbf..da0ddc713e6b35da 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -2506,10 +2506,12 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
>         };
>         struct syscall *sc, *tmp;
>
> -       sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> -                    sizeof(struct syscall), syscall__cmp);
> -       if (sc)
> -               return sc;
> +       if (trace->syscalls.table) {
> +               sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> +                            sizeof(struct syscall), syscall__cmp);
> +               if (sc)
> +                       return sc;
> +       }
>
>         tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
>                            sizeof(struct syscall));
> @@ -3855,6 +3857,10 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, i
>
>  static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
>  {
> +       int orig_id = sc->id;
> +       const char *orig_name = sc->name;
> +       int e_machine = sc->e_machine;
> +       struct tep_format_field *args = sc->args;
>         struct tep_format_field *field, *candidate_field;
>         /*
>          * We're only interested in syscalls that have a pointer:
> @@ -3866,18 +3872,19 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
>
>         return NULL;
>
> +       /* calling trace__syscall_info() may invalidate 'sc' */
>  try_to_find_pair:
> -       for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
> -               int id = syscalltbl__id_at_idx(sc->e_machine, i);
> -               struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
> +       for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
> +               int id = syscalltbl__id_at_idx(e_machine, i);
> +               struct syscall *pair = trace__syscall_info(trace, NULL, e_machine, id);
>                 struct bpf_program *pair_prog;
>                 bool is_candidate = false;
>
> -               if (pair == NULL || pair == sc ||
> +               if (pair == NULL || pair->id == orig_id ||
>                     pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
>                         continue;
>
> -               for (field = sc->args, candidate_field = pair->args;
> +               for (field = args, candidate_field = pair->args;
>                      field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
>                         bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
>                              candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
> @@ -3944,7 +3951,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
>                                 goto next_candidate;
>                 }
>
> -               pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name);
> +               pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, orig_name);
>                 return pair_prog;
>         next_candidate:
>                 continue;
> @@ -4041,6 +4048,11 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
>                 if (pair_prog == NULL)
>                         continue;
>
> +               /*
> +                * Get syscall info again as find usable entry above might
> +                * modify the syscall table and shuffle it.
> +                */
> +               sc = trace__syscall_info(trace, NULL, e_machine, key);
>                 sc->bpf_prog.sys_enter = pair_prog;
>
>                 /*
>


From james.clark at linaro.org  Mon Mar 17 08:05:41 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 15:05:41 +0000
Subject: [PATCH 5/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250313160409.GS9682@e132581.arm.com>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-6-james.clark@linaro.org>
 <20250313160409.GS9682@e132581.arm.com>
Message-ID: <6be400e2-a464-4714-acf4-328dade883a9@linaro.org>



On 13/03/2025 4:04 pm, Leo Yan wrote:
> On Tue, Feb 11, 2025 at 10:39:41AM +0000, James Clark wrote:
>>
>> This can be left behind from a crashed kernel after a kexec so clear it
>> when probing each device. Similarly to
>> coresight_disclaim_device_unlocked(), only clear it if it's already set
>> to avoid races with an external debugger.
>>
>> We need a csdev_access struct in etm_init_arch_data() so just replace
>> the iomem pointer with a full csdev_access struct. This means all usages
>> need to be updated to go through csa->base.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>>   drivers/hwtracing/coresight/coresight-catu.c  |  1 +
>>   drivers/hwtracing/coresight/coresight-core.c  | 48 +++++++++++++++----
>>   .../hwtracing/coresight/coresight-cti-core.c  |  2 +
>>   drivers/hwtracing/coresight/coresight-etb10.c |  2 +
>>   drivers/hwtracing/coresight/coresight-etm.h   |  6 +--
>>   .../coresight/coresight-etm3x-core.c          | 28 +++++------
>>   .../coresight/coresight-etm3x-sysfs.c         |  8 ++--
>>   .../coresight/coresight-etm4x-core.c          |  2 +
>>   .../hwtracing/coresight/coresight-funnel.c    |  2 +
>>   .../coresight/coresight-replicator.c          |  1 +
>>   .../hwtracing/coresight/coresight-tmc-core.c  |  1 +
>>   include/linux/coresight.h                     |  3 ++
>>   12 files changed, 73 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
>> index d9259c0b6e64..575c2d247a90 100644
>> --- a/drivers/hwtracing/coresight/coresight-catu.c
>> +++ b/drivers/hwtracing/coresight/coresight-catu.c
>> @@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
>>          catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
>>          catu_desc.ops = &catu_ops;
>>
>> +       coresight_reset_claim(&catu_desc.access);
>>          drvdata->csdev = coresight_register(&catu_desc);
>>          if (IS_ERR(drvdata->csdev))
>>                  ret = PTR_ERR(drvdata->csdev);
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index 7fe5d5d432c4..97f33ffad05e 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -212,20 +212,48 @@ int coresight_claim_device(struct coresight_device *csdev)
>>   EXPORT_SYMBOL_GPL(coresight_claim_device);
>>
>>   /*
>> - * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
>> + * Clear the claim tag for the device.
>> + * Returns an error if the device wasn't already claimed.
>> + */
>> +int coresight_reset_claim(struct csdev_access *csa)
>> +{
>> +       int ret;
>> +
>> +       CS_UNLOCK(csa->base);
>> +       ret = coresight_reset_claim_unlocked(csa);
>> +       CS_LOCK(csa->base);
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(coresight_reset_claim);
> 
> Maybe my question is overlapping with Mike's comment.
> 
> Callers never check the return values from coresight_reset_claim(). I am

I can remove the return value if it's confusing. The thought process was 
probably that it could be useful somewhere in the future, and 
coresight_reset_claim_unlocked() returns something anyway so might as 
well pass it up.

> wandering if coresight_reset_claim() can directly call
> coresight_clear_self_claim_tag() for _trying_ to clear self-host tag in
> probe phase. Any self claim tag issues will be deferred to detect until
> enable the component.
> 

Maybe, the spec does a read before setting which I assumed should be 
done for clearing as well. As in to not touch anything if it's in use 
externally. It doesn't specifically describe any clearing sequence, but 
if we assume it's ok to blindly clear self hosted flag even when it's in 
use then yes we can directly call coresight_clear_self_claim_tag().

This doesn't change anything about deferring errors though, 
coresight_reset_claim() doesn't warn early either.

> For consistent, we might rename coresight_reset_claim() to
> coresight_reset_self_claim_tag(), which acquires CS lock and clear
> self claim tag.
> 
>> +/*
>> + * Clear the claim tag for the device. Called with CS_UNLOCKed for the component.
>> + * Returns an error if the device wasn't already claimed.
>> + */
>> +int coresight_reset_claim_unlocked(struct csdev_access *csa)
>> +{
>> +       if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED) {
>> +               coresight_clear_self_claim_tag(csa);
>> +               return 0;
>> +       }
>> +
>> +       return -EINVAL;
>> +}
>> +EXPORT_SYMBOL_GPL(coresight_reset_claim_unlocked);
>> +
>> +/*
>> + * coresight_disclaim_device_unlocked : Clear the claim tag for the device
>> + * and warn if the device wasn't already claimed.
>>    * Called with CS_UNLOCKed for the component.
>>    */
>>   void coresight_disclaim_device_unlocked(struct csdev_access *csa)
>>   {
>> -       if (coresight_read_claim_tags(csa) == CORESIGHT_CLAIM_SELF_HOSTED)
>> -               coresight_clear_self_claim_tag(csa);
>> -       else
>> -               /*
>> -                * The external agent may have not honoured our claim
>> -                * and has manipulated it. Or something else has seriously
>> -                * gone wrong in our driver.
>> -                */
>> -               WARN_ON_ONCE(1);
>> +       /*
>> +        * Warn if the external agent hasn't honoured our claim
>> +        * and has manipulated it. Or something else has seriously
>> +        * gone wrong in our driver.
>> +        */
>> +       WARN_ON_ONCE(coresight_reset_claim_unlocked(csa));
>>   }
>>   EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
>> index 073f67a41af9..389a72362f0c 100644
>> --- a/drivers/hwtracing/coresight/coresight-cti-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-cti-core.c
>> @@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>>          cti_desc.ops = &cti_ops;
>>          cti_desc.groups = drvdata->ctidev.con_groups;
>>          cti_desc.dev = dev;
>> +
>> +       coresight_reset_claim(&cti_desc.access);
>>          drvdata->csdev = coresight_register(&cti_desc);
>>          if (IS_ERR(drvdata->csdev)) {
>>                  ret = PTR_ERR(drvdata->csdev);
>> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
>> index d8bc3e776c88..b598b2c0c9bb 100644
>> --- a/drivers/hwtracing/coresight/coresight-etb10.c
>> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
>> @@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
>>          desc.pdata = pdata;
>>          desc.dev = dev;
>>          desc.groups = coresight_etb_groups;
>> +
>> +       coresight_reset_claim(&desc.access);
>>          drvdata->csdev = coresight_register(&desc);
>>          if (IS_ERR(drvdata->csdev))
>>                  return PTR_ERR(drvdata->csdev);
>> diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
>> index e02c3ea972c9..a89736309c27 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm.h
>> +++ b/drivers/hwtracing/coresight/coresight-etm.h
>> @@ -229,7 +229,7 @@ struct etm_config {
>>    * @config:    structure holding configuration parameters.
>>    */
>>   struct etm_drvdata {
>> -       void __iomem                    *base;
>> +       struct csdev_access             csa;
> 
> I would like to extract the change for using `csdev_access` in the
> ETMv3 driver into a new patch, which is irrelevant to reset self claim
> tags and would significantly reduce the complexity in this patch.
> 

Will do, good point.

> Thanks,
> Leo



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:39 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:39 -0300
Subject: [PATCH v4 0/6] drm/panfrost: Add support for AARCH64_4K page table format
Message-ID: <20250317145245.910566-1-ariel.dalessandro@collabora.com>

Hi all,

This is a new iteration on Panfrost support for AARCH64_4K page table
format. The main reason behind this patchset is that MediaTek MT8188 SoC
(ARM Mali-G57 MC3 GPU) constantly faults due to the actual Panfrost cache
configuration.

Currently, Panfrost only supports MMU configuration in "LEGACY" (as Bifrost
calls it) mode, a (modified) version of LPAE "Large Physical Address
Extension", which in Linux we've called "mali_lpae".

This patchset adds support for conditionally enabling AARCH64_4K page table
format. To achieve that, a "GPU optional quirks" field was added to
`struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

The patchset only enables the new format on Mediatek MT8188 and MT8192,
which have been tested on a Mediatek Genio 700 EVK (MT8390) and Mediatek
Genio 1200 EVK (MT8395) boards respectively.

Thanks!

Changes in v4:
* Fixed panfrost_mmu_cfg_init() return value on warning.

Changes in v3:
* Fixed error handling in panfrost_mmu_ctx_create().

Changes in v2:
* Dropped panfrost_mmu_enable/disable unification.
* Rename gpu_configs as gpu_quirks.
* Added error handling on page table not properly aligned.
* Enabled AARCH64_4K format on MediaTek MT8192 as well.
* Minor fixes.

Changes in v1:
* Added "Set IOMMU_CACHE flag" patch.
* Replaced `panfrost_mmu->enable()` function pointer by `cfg` struct
prepared during init time.
* Made mali_lpae/aarch64_4k name more clear.
* Added GPU_CONFIG_AARCH64_4K flag to enable AARCH64_4K page table
  format.
* Enabled AARCH64_4K mode only on mediatek-mt8188.

Ariel D'Alessandro (6):
  drm/panfrost: Set IOMMU_CACHE flag
  drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
  drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost
    models
  drm/panfrost: Add support for AARCH64_4K page table format
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192

 drivers/gpu/drm/panfrost/panfrost_device.h   |  16 ++
 drivers/gpu/drm/panfrost/panfrost_drv.c      |   2 +
 drivers/gpu/drm/panfrost/panfrost_features.h |   3 +
 drivers/gpu/drm/panfrost/panfrost_mmu.c      | 150 +++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h     |  36 +++++
 5 files changed, 196 insertions(+), 11 deletions(-)

-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:41 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:41 -0300
Subject: [PATCH v4 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-3-ariel.dalessandro@collabora.com>

As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
which makes code easier to read and reuse.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 9e6f198ef5c1b..294f86b3c25e7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
 
 struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
+	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
+	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 
 	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
 		.pgsize_bitmap	= SZ_4K | SZ_2M,
-		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
-		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
+		.ias		= va_bits,
+		.oas		= pa_bits,
 		.coherent_walk	= pfdev->coherent,
 		.tlb		= &mmu_tlb_ops,
 		.iommu_dev	= pfdev->dev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index c7bba476ab3f3..b5f279a19a084 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -16,6 +16,8 @@
 #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
 
 #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
+#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
+#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
 #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
 #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
 
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:42 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:42 -0300
Subject: [PATCH v4 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost models
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-4-ariel.dalessandro@collabora.com>

Set this feature flag on all Mali Bifrost platforms as the MMU supports
AARCH64 4K page table format.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_features.h
+++ b/drivers/gpu/drm/panfrost/panfrost_features.h
@@ -54,6 +54,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g72 (\
@@ -64,6 +65,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g51 hw_features_g72
@@ -77,6 +79,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
 	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g76 (\
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:40 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:40 -0300
Subject: [PATCH v4 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-2-ariel.dalessandro@collabora.com>

Panfrost does not support uncached mappings, so flag them properly. Also
flag the pages that are mapped as response to a page fault as cached.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index b91019cd5acb1..9e6f198ef5c1b 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 	struct drm_gem_object *obj = &shmem->base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
-	int prot = IOMMU_READ | IOMMU_WRITE;
+	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
 
 	if (WARN_ON(mapping->active))
 		return 0;
@@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
 		goto err_map;
 
 	mmu_map_sg(pfdev, bomapping->mmu, addr,
-		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
 
 	bomapping->active = true;
 	bo->heap_rss_size += SZ_2M;
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:43 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:43 -0300
Subject: [PATCH v4 4/6] drm/panfrost: Add support for AARCH64_4K page table format
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-5-ariel.dalessandro@collabora.com>

Currently, Panfrost only supports MMU configuration in "LEGACY" (as
Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called "mali_lpae".

This commit adds support for conditionally enabling AARCH64_4K page
table format. To achieve that, a "GPU optional quirks" field was added
to `struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
 drivers/gpu/drm/panfrost/panfrost_mmu.c    | 140 +++++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 +++++
 3 files changed, 183 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index cffcb0ac7c111..ad95f2ed31d9a 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
 	GPU_PM_VREG_OFF,
 };
 
+/**
+ * enum panfrost_gpu_quirks - GPU optional quirks
+ * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
+ */
+enum panfrost_gpu_quirks {
+	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
+};
+
 struct panfrost_features {
 	u16 id;
 	u16 revision;
@@ -95,6 +103,9 @@ struct panfrost_compatible {
 
 	/* Allowed PM features */
 	u8 pm_features;
+
+	/* GPU configuration quirks */
+	u8 gpu_quirks;
 };
 
 struct panfrost_device {
@@ -162,6 +173,11 @@ struct panfrost_mmu {
 	int as;
 	atomic_t as_count;
 	struct list_head list;
+	struct {
+		u64 transtab;
+		u64 memattr;
+		u64 transcfg;
+	} cfg;
 };
 
 struct panfrost_engine_usage {
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 294f86b3c25e7..506f42ccfd5fc 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -26,6 +26,48 @@
 #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define mmu_read(dev, reg) readl(dev->iomem + reg)
 
+static u64 mair_to_memattr(u64 mair, bool coherent)
+{
+	u64 memattr = 0;
+	u32 i;
+
+	for (i = 0; i < 8; i++) {
+		u8 in_attr = mair >> (8 * i), out_attr;
+		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
+
+		/* For caching to be enabled, inner and outer caching policy
+		 * have to be both write-back, if one of them is write-through
+		 * or non-cacheable, we just choose non-cacheable. Device
+		 * memory is also translated to non-cacheable.
+		 */
+		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
+				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
+		} else {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
+			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
+			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
+			 * to Mali's internal-shareable mode. As per the Mali
+			 * Spec, inner and outer-shareable modes aren't allowed
+			 * for WB memory when coherency is disabled.
+			 * Use SH_CPU_INNER mode when coherency is enabled, so
+			 * that SH_IS actually maps to the standard definition of
+			 * inner-shareable.
+			 */
+			if (!coherent)
+				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
+			else
+				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
+		}
+
+		memattr |= (u64)out_attr << (8 * i);
+	}
+
+	return memattr;
+}
+
 static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
 {
 	int ret;
@@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
+	u64 transtab = mmu->cfg.transtab;
+	u64 memattr = mmu->cfg.memattr;
+	u64 transcfg = mmu->cfg.transcfg;
 
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
@@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
@@ -152,9 +197,67 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
+static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	/* TODO: The following fields are duplicated between the MMU and Page
+	 * Table config structs. Ideally, should be kept in one place.
+	 */
+	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
+	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
+	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
+
+	return 0;
+}
+
+static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
+				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
+		return -EINVAL;
+
+	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+
+	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
+					   pgtbl_cfg->coherent_walk);
+
+	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
+			    AS_TRANSCFG_PTW_RA |
+			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
+			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
+	if (pgtbl_cfg->coherent_walk)
+		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
+
+	return 0;
+}
+
+static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
+				  enum io_pgtable_fmt fmt)
+{
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		return mmu_cfg_init_aarch64_4k(mmu);
+	case ARM_MALI_LPAE:
+		return mmu_cfg_init_mali_lpae(mmu);
+	default:
+		/* This should never happen */
+		drm_WARN(pfdev->ddev, "Invalid pgtable format");
+		return -EINVAL;
+	}
+}
+
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as;
@@ -618,6 +721,19 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
 	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
+	enum io_pgtable_fmt fmt;
+	int ret;
+
+	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
+		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
+			dev_err_once(pfdev->dev,
+				     "AARCH64_4K page table not supported\n");
+			return ERR_PTR(-EINVAL);
+		}
+		fmt = ARM_64_LPAE_S1;
+	} else {
+		fmt = ARM_MALI_LPAE;
+	}
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
 	if (!mmu)
@@ -642,16 +758,26 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 		.iommu_dev	= pfdev->dev,
 	};
 
-	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
-					      mmu);
+	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
 	if (!mmu->pgtbl_ops) {
-		kfree(mmu);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto err_free_mmu;
 	}
 
+	ret = panfrost_mmu_cfg_init(mmu, fmt);
+	if (ret)
+		goto err_free_io_pgtable;
+
 	kref_init(&mmu->refcount);
 
 	return mmu;
+
+err_free_io_pgtable:
+	free_io_pgtable_ops(mmu->pgtbl_ops);
+
+err_free_mmu:
+	kfree(mmu);
+	return ERR_PTR(ret);
 }
 
 static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index b5f279a19a084..2b8f1617b8369 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -301,6 +301,17 @@
 #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
 #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
+							 ((w) ? BIT(0) : 0) | \
+							 ((r) ? BIT(1) : 0))
+#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
+#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
+#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
 #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
 #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
 #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
@@ -311,6 +322,24 @@
 /* Additional Bifrost AS registers */
 #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
 #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
+#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
+#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
+#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
+#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
+#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
+#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
+#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
+#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
+#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
+#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
+#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
+#define   AS_TRANSCFG_PTW_RA				BIT(30)
+#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
+#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
+#define   AS_TRANSCFG_WXN				BIT(35)
+#define   AS_TRANSCFG_XREADABLE				BIT(36)
 #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
@@ -326,6 +355,11 @@
 #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
 #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
 
+/*
+ * Begin AARCH64_4K MMU TRANSTAB register values
+ */
+#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
+
 #define AS_STATUS_AS_ACTIVE			0x01
 
 #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:45 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:45 -0300
Subject: [PATCH v4 6/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-7-ariel.dalessandro@collabora.com>

MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
Panfrost supports AARCH64_4K page table format, let's enable it on this
SoC.

Running glmark2-es2-drm [0] benchmark, reported the same performance
score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.

[0] https://github.com/glmark2/glmark2

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index e854f290858f9..ef30d314b2281 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -836,6 +836,7 @@ static const struct panfrost_compatible mediatek_mt8192_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains),
 	.pm_domain_names = mediatek_mt8192_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const struct of_device_id dt_match[] = {
-- 
2.47.2



From ariel.dalessandro at collabora.com  Mon Mar 17 07:52:44 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 17 Mar 2025 11:52:44 -0300
Subject: [PATCH v4 5/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
In-Reply-To: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
Message-ID: <20250317145245.910566-6-ariel.dalessandro@collabora.com>

MediaTek MT8188 SoC has an ARM Mali-G57 MC3 GPU (Valhall-JM), which
constantly faults with the current panfrost support.

For instance, running `glmark2-es2-drm` benchmark test:
```
[   79.617461] panfrost 13000000.gpu: js fault, js=1, status=JOB_BUS_FAULT, head=0xaadc380, tail=0xaadc380
[   80.119811] panfrost 13000000.gpu: gpu sched timeout, js=0, config=0x7300, status=0x58, head=0xaaca180, tail=0xaaca180, sched_job=000000002fd03ccc
[   80.129083] panfrost 13000000.gpu: Unhandled Page fault in AS0 at VA 0x0000000000000000
[   80.129083] Reason: TODO
[   80.129083] raw fault status: 0x1C2
[   80.129083] decoded fault status: SLAVE FAULT
[   80.129083] exception type 0xC2: TRANSLATION_FAULT_2
[   80.129083] access type 0x1: EXECUTE
[   80.129083] source id 0x0
```

Note that current panfrost mode (Mali LPAE - LEGACY) only allows to
specify write-cache or implementation-defined as the caching policy,
probably not matching the right configuration. As depicted in the source
code:

drivers/iommu/io-pgtable-arm.c:
```
* MEMATTR: Mali has no actual notion of a non-cacheable type, so the
* best we can do is mimic the out-of-tree driver and hope that the
* "implementation-defined caching policy" is good enough...
```

Now that Panfrost supports AARCH64_4K page table format, let's enable it
on Mediatek MT8188 and configure the cache/shareability policies
properly.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 0f3935556ac76..e854f290858f9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
 	.pm_domain_names = mediatek_mt8183_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
-- 
2.47.2



From peter.griffin at linaro.org  Mon Mar 17 07:55:15 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Mon, 17 Mar 2025 14:55:15 +0000
Subject: [PATCH 2/2] scsi: ufs: dt-bindings: exynos: add dma-coherent
 property for gs101
In-Reply-To: <931e5e0b07d598912712b091d99a636b796fe19f.camel@linaro.org>
References: <20250314-ufs-dma-coherent-v1-0-bdf9f9be2919@linaro.org>
 <20250314-ufs-dma-coherent-v1-2-bdf9f9be2919@linaro.org> <931e5e0b07d598912712b091d99a636b796fe19f.camel@linaro.org>
Message-ID: <CADrjBPoESd7D4H80prCtFXTGaWOg-HV_ovNdwZ4G7Y8n-hFdsQ@mail.gmail.com>

Hi Andr?

On Fri, 14 Mar 2025 at 15:59, Andr? Draszik <andre.draszik at linaro.org> wrote:
>
> Hi Pete,
>
> On Fri, 2025-03-14 at 15:38 +0000, Peter Griffin wrote:
> > dma-coherent property is required for gs101 as ufs-exynos enables
> > sharability.
> >
> > Fixes: 438e23b61cd4 ("scsi: ufs: dt-bindings: exynos: Add gs101 compatible")
> > Cc: stable at vger.kernel.org
> > Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> > ---
> >  Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml b/Documentation/devicetree/bindings/ufs/samsung,exynos-
> > ufs.yaml
> > index 720879820f6616a30cae2db3d4d2d22e847666c4..5dbb7f6a8c354b82685c521e70655e106f702a8d 100644
> > --- a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
> > +++ b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml
> > @@ -96,6 +96,8 @@ allOf:
> >          clock-names:
> >            minItems: 6
> >
> > +        dma-coherent: true
> > +
>
> This is allowed globally already in this file. Did you meant to make it 'required'?

I hadn't noticed it was already handled further up in the yaml. In
which case this patch can be dropped entirely.

Thanks,

Peter


From will at kernel.org  Mon Mar 17 08:09:41 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 17 Mar 2025 15:09:41 +0000
Subject: [PATCH] perf/arm_cspmu: Fix missing io.h include
In-Reply-To: <657935ca177024ad08d5ec6f85e8faf75f82cf65.1742212833.git.robin.murphy@arm.com>
References: <657935ca177024ad08d5ec6f85e8faf75f82cf65.1742212833.git.robin.murphy@arm.com>
Message-ID: <174222318360.167046.12264124011753277546.b4-ty@kernel.org>

On Mon, 17 Mar 2025 12:00:33 +0000, Robin Murphy wrote:
> Adding the writel() calls needs io.h, which apparently gets
> transiently included somewhere on arm64, but not elsewhere.
> 
> 

Applied to will (for-next/perf), thanks!

[1/1] perf/arm_cspmu: Fix missing io.h include
      https://git.kernel.org/will/c/9651f7899cc5

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev


From sebastian.reichel at collabora.com  Mon Mar 17 08:21:04 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 17 Mar 2025 16:21:04 +0100
Subject: [PATCH] power: supply: mt6370: Remove redundant
 'flush_workqueue()' calls
In-Reply-To: <20250312073729.1430053-1-nichen@iscas.ac.cn>
References: <20250312073729.1430053-1-nichen@iscas.ac.cn>
Message-ID: <174222486427.175368.2927346420371391237.b4-ty@collabora.com>


On Wed, 12 Mar 2025 15:37:29 +0800, Chen Ni wrote:
> 'destroy_workqueue()' already drains the queue before destroying it, so
> there is no need to flush it explicitly.
> 
> Remove the redundant 'flush_workqueue()' calls.
> 
> This was generated with coccinelle:
> 
> [...]

Applied, thanks!

[1/1] power: supply: mt6370: Remove redundant 'flush_workqueue()' calls
      commit: 0b8d073f6c66d7110ac9fab1f13a09337e03f1b6

Best regards,
-- 
Sebastian Reichel <sebastian.reichel at collabora.com>



From james.clark at linaro.org  Mon Mar 17 08:26:42 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 17 Mar 2025 15:26:42 +0000
Subject: [PATCH 6/7] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250314095025.GW9682@e132581.arm.com>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-7-james.clark@linaro.org>
 <20250314095025.GW9682@e132581.arm.com>
Message-ID: <9d06b27a-c2ce-41b8-9657-151000c0b244@linaro.org>



On 14/03/2025 9:50 am, Leo Yan wrote:
> On Tue, Feb 11, 2025 at 10:39:42AM +0000, James Clark wrote:
>>
>> These are all static and in one compilation unit so the inline has no
>> effect on the binary.
> 
> I read the doc coding-style.rst, the section "15) The inline disease",
> my understanding is though the inline is not encouraged, I prefer we can
> follow up the rule:
> 
>    A reasonable rule of thumb is to not put inline at functions that have more
>    than 3 lines of code in them. An exception to this rule are the cases where
>    a parameter is known to be a compile time constant, and as a result of this
>    constantness you *know* the compiler will be able to optimize most of your
>    function away at compile time. For a good example of this later case, see
>    the kmalloc() inline function.
> 

Isn't this advice about whether to make an inline function in a header 
file or do definition + declaration? I only removed static ones local to 
.c files where 'inline' has no effect at all. We build with optimisation 
enabled so the compiler already auto inlines small functions and ignores 
the inline keyword for large re-used ones anyway.

>> Except if FTRACE is enabled, then some functions
>> which were already not inlined now get the nops added which allows them
>> to be traced.
> 
> I understand it is a side effect that we cannot use function tracer for
> inline functions.  This is not a big issue for me, as we still can use
> "perf probe" and trace_printk() for debugging.
> 
> Thanks,
> Leo
> 

I think it can be useful, I've used it a little bit. Might as well make 
it easier to use for someone if it exists.



From ryan.roberts at arm.com  Mon Mar 17 08:30:47 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Mon, 17 Mar 2025 15:30:47 +0000
Subject: [PATCH 00/11] Always call constructor for kernel page tables
In-Reply-To: <20250317141700.3701581-1-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
Message-ID: <70349335-84ee-4bca-a3d6-d7cf3c05b92b@arm.com>

On 17/03/2025 14:16, Kevin Brodsky wrote:
> The complications in those special pgtable allocators beg the question:
> does it really make sense to treat efi_mm and init_mm differently in
> e.g. apply_to_pte_range()? Maybe what we really need is a way to tell if
> an mm corresponds to user memory or not, and never use split locks for
> non-user mm's. Feedback and suggestions welcome!

The difference in treatment is whether or not the ptl is taken, right? So the
real question is when calling apply_to_pte_range() for efi_mm, is there already
a higher level serialization mechanism that prevents racy accesses? For init_mm,
I think this is handled implicitly because there is no way for user space to
cause apply_to_pte_range() for an arbitrary piece of kernel memory. Although I
can't even see where apply_to_page_range() is called for efi_mm.

FWIW, contpte.c has mm_is_user() which is used by arm64.

Thanks,
Ryan


From alexander.stein at ew.tq-group.com  Mon Mar 17 08:30:46 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 17 Mar 2025 16:30:46 +0100
Subject: [PATCH v5 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <20250317133306.2003909-3-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
 <20250317133306.2003909-3-daniel.baluta@nxp.com>
Message-ID: <5873285.DvuYhMxLoT@steina-w>

Am Montag, 17. M?rz 2025, 14:33:03 CET schrieb Daniel Baluta:
> Enable MU2 node and add mu2 root clock.
> MU2 is used to communicate with DSP core.
> 
> Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> index 3b725fe442d0..5b443fbeded8 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> @@ -1253,7 +1253,7 @@ mu2: mailbox at 30e60000 {
>  				reg = <0x30e60000 0x10000>;
>  				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
>  				#mbox-cells = <2>;
> -				status = "disabled";

There is no need to enable MU2 if the DSP is disabled by default, no?

Best regards
Alexander

> +				clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_MU2_ROOT>;
>  			};
>  
>  			i2c5: i2c at 30ad0000 {
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From jgg at nvidia.com  Mon Mar 17 08:44:23 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 17 Mar 2025 12:44:23 -0300
Subject: [PATCH v8 12/14] iommu/arm-smmu-v3: Introduce struct
 arm_smmu_vmaster
In-Reply-To: <Z9B2LMIi+88hlfza@Asurada-Nvidia>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
 <20250311155714.GC5138@willie-the-truck>
 <Z9B2LMIi+88hlfza@Asurada-Nvidia>
Message-ID: <20250317154423.GI9311@nvidia.com>

On Tue, Mar 11, 2025 at 10:43:08AM -0700, Nicolin Chen wrote:
> > > +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> > > +				    struct arm_smmu_nested_domain *nested_domain)
> > > +{
> > > +	struct arm_smmu_vmaster *vmaster;
> > > +	unsigned long vsid;
> > > +	int ret;
> > > +
> > > +	iommu_group_mutex_assert(state->master->dev);
> > > +
> > > +	/* Skip invalid vSTE */
> > > +	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> > > +		return 0;
> > 
> > Ok, and we don't need to set 'state->vmaster' in this case because we
> > only report stage-1 faults back to the vSMMU?
> 
> This is a good question that I didn't ask myself hard enough..
> 
> I think we should probably drop it. An invalid STE should trigger
> a C_BAD_STE event that is in the supported vEVENT list. I'll run
> some test before removing this line from v9.

It won't trigger C_BAD_STE, recall Robin was opposed to thatm so we have this:

static void arm_smmu_make_nested_domain_ste(
	struct arm_smmu_ste *target, struct arm_smmu_master *master,
	struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
{
	unsigned int cfg =
		FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(nested_domain->ste[0]));

	/*
	 * Userspace can request a non-valid STE through the nesting interface.
	 * We relay that into an abort physical STE with the intention that
	 * C_BAD_STE for this SID can be generated to userspace.
	 */
	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
		cfg = STRTAB_STE_0_CFG_ABORT;

So, in the case of a non-valid STE, and a device access, the HW will
generate one of the translation faults and that will be forwarded.

Some software component will have to transform those fault events into
C_BAD_STE for the VM.

I imagined userspace would do this, but it could be done in the kernel
too. Regardless, I think Will is right and the the viommu should be
set even in this case to capture the events.

Jason


From mazziesaccount at gmail.com  Mon Mar 17 08:51:38 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 17:51:38 +0200
Subject: [PATCH v8 07/10] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1742225817.git.mazziesaccount@gmail.com>
References: <cover.1742225817.git.mazziesaccount@gmail.com>
Message-ID: <a94e347b7a1dde5329bd20a34f2be99c598bf5f5.1742225817.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
v2 =>
 - No changes
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/1cc8be9d/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 17 08:50:49 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 17:50:49 +0200
Subject: [PATCH v8 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1742225817.git.mazziesaccount@gmail.com>
References: <cover.1742225817.git.mazziesaccount@gmail.com>
Message-ID: <e556f152a9cff2ff61e7b7a4b42feffb400cb1f9.1742225817.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
Revision history:
v7 => v8:
 devm_iio_adc_device_alloc_chaninfo_se():
 - Treat all negative values for the max ID as 'don't care'
 - Return -ENOENT instead of '0' if no channels were found.
v5 => v6:
 - Adapt to changed fwnode helper names
 - Fix spelling
v4 => v5:
 - Inline iio_adc_device_num_channels()
 - Fix Indenting function parameters
 - Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 82 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 114 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..b4057230e749
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use negative value if no
+ *			checking is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on success. Negative value to indicate
+ *		failure. Specifically, -ENOENT if no channel nodes were found.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 0)
+		return num_chan;
+
+	if (!num_chan)
+		return -ENOENT;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_named_child_node_scoped(dev, child, "channel") {
+		u32 ch;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id >= 0 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..56b092a2a4c4
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_named_child_node_count(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/2acec909/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 17 08:51:14 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 17 Mar 2025 17:51:14 +0200
Subject: [PATCH v8 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1742225817.git.mazziesaccount@gmail.com>
References: <cover.1742225817.git.mazziesaccount@gmail.com>
Message-ID: <78d33ea9a795abdb2c5a4c606d48593e827ca59e.1742225817.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
help drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-properties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>

---
NOTE: This change now drops a print "no channel children" which used to
be printed if no channel nodes were found. It also changes the return
value from -ENODEV to -ENOENT.

Revision history:
v7 => v8:
 - drop explicit "no channels check". It is now done inside the
   devm_iio_adc_device_alloc_chaninfo_se().
v6 => v7:
 - Fix function name in the commit message
v5 => v6:
 - Commit message typofix
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 39 +++++++++++-------------------
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..2428ea69d676 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,36 +150,23 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
-	if (num_channels == 0)
-		return dev_err_probe(dev, -ENODEV, "no channel children\n");
-
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
 
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
@@ -271,3 +259,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250317/6bb8c855/attachment.sig>

From vladimir.oltean at nxp.com  Mon Mar 17 08:55:01 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 17:55:01 +0200
Subject: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95
 ENETC PF
In-Reply-To: <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
Message-ID: <20250317155501.4haweyhlrfozg7zr@skbuf>

On Tue, Mar 11, 2025 at 01:38:24PM +0800, Wei Fang wrote:
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
> index a3ce324c716c..ecf79338cd79 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> @@ -543,6 +543,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
>  int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
>  int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
>  int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
> +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
> +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
>  
>  static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
>  					     struct enetc_cbd *cbd,
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> index f991e1aae85c..53dbd5d71859 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> @@ -693,6 +693,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
>  	queue_work(si->workqueue, &si->rx_mode_task);
>  }
>  
> +static int enetc4_pf_set_features(struct net_device *ndev,
> +				  netdev_features_t features)
> +{
> +	enetc_set_features(ndev, features);
> +
> +	return 0;
> +}
> +
>  static const struct net_device_ops enetc4_ndev_ops = {
>  	.ndo_open		= enetc_open,
>  	.ndo_stop		= enetc_close,
> @@ -700,6 +708,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
>  	.ndo_get_stats		= enetc_get_stats,
>  	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
>  	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
> +	.ndo_set_features	= enetc4_pf_set_features,
>  };
>  
>  static struct phylink_pcs *
> @@ -1108,6 +1117,8 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
>  static const struct enetc_si_ops enetc4_psi_ops = {
>  	.setup_cbdr = enetc4_setup_cbdr,
>  	.teardown_cbdr = enetc4_teardown_cbdr,
> +	.get_rss_table = enetc4_get_rss_table,
> +	.set_rss_table = enetc4_set_rss_table,
>  };
>  
>  static int enetc4_pf_wq_task_init(struct enetc_si *si)
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> index 4e5125331d7b..1a74b93f1fd3 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> @@ -299,3 +299,17 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count)
>  	return enetc_cmd_rss_table(si, (u32 *)table, count, false);
>  }
>  EXPORT_SYMBOL_GPL(enetc_set_rss_table);
> +
> +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
> +{
> +	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> +					       table, count, true);
> +}
> +EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
> +
> +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
> +{
> +	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> +					       (u32 *)table, count, false);
> +}
> +EXPORT_SYMBOL_GPL(enetc4_set_rss_table);

I don't understand the logic for placing enetc4_get_rss_table() and
enetc4_set_rss_table() in enetc_cbdr.c (built as part of fsl-enetc-core-y)?
It's not core code, it's used only by NETC v4.

> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> index 1a8fae3c406b..bc65135925b8 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> @@ -625,6 +625,24 @@ static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
>  	return 0;
>  }
>  
> +static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
> +			    u32 *rule_locs)
> +{
> +	struct enetc_ndev_priv *priv = netdev_priv(ndev);
> +
> +	switch (rxnfc->cmd) {
> +	case ETHTOOL_GRXRINGS:
> +		rxnfc->data = priv->num_rx_rings;
> +		break;
> +	case ETHTOOL_GRXFH:
> +		return enetc_get_rsshash(rxnfc);

These rxnfc commands seem implemented identically to the corresponding
subset from enetc_get_rxnfc(). Rather than duplicating those, could you
rather return -EOPNOTSUPP for the unsupported ones on NETC v4, and reuse
enetc_get_rxnfc()?

> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
>  static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)
>  {
>  	struct enetc_ndev_priv *priv = netdev_priv(ndev);
> @@ -685,22 +703,29 @@ static int enetc_get_rss_key_base(struct enetc_si *si)
>  	return ENETC4_PRSSKR(0);
>  }
>  
> +static void enetc_get_rss_key(struct enetc_si *si, const u8 *key)
> +{
> +	int base = enetc_get_rss_key_base(si);
> +	struct enetc_hw *hw = &si->hw;
> +	int i;
> +
> +	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> +		((u32 *)key)[i] = enetc_port_rd(hw, base + i * 4);
> +}

I would have expected that this refactoring of code into
enetc_get_rss_key() would be done as part of the previous change:
"net: enetc: make enetc_set_rss_key() reusable".

> +
>  static int enetc_get_rxfh(struct net_device *ndev,
>  			  struct ethtool_rxfh_param *rxfh)
>  {
>  	struct enetc_ndev_priv *priv = netdev_priv(ndev);
>  	struct enetc_si *si = priv->si;
> -	struct enetc_hw *hw = &si->hw;
> -	int err = 0, i;
> +	int err = 0;
>  
>  	/* return hash function */
>  	rxfh->hfunc = ETH_RSS_HASH_TOP;
>  
>  	/* return hash key */
> -	if (rxfh->key && hw->port)
> -		for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> -			((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
> -							      ENETC_PRSSK(i));
> +	if (rxfh->key && enetc_si_is_pf(si))
> +		enetc_get_rss_key(si, rxfh->key);
>  
>  	/* return RSS table */
>  	if (rxfh->indir)
> @@ -1249,6 +1274,11 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
>  	.set_wol = enetc_set_wol,
>  	.get_pauseparam = enetc_get_pauseparam,
>  	.set_pauseparam = enetc_set_pauseparam,
> +	.get_rxnfc = enetc4_get_rxnfc,
> +	.get_rxfh_key_size = enetc_get_rxfh_key_size,
> +	.get_rxfh_indir_size = enetc_get_rxfh_indir_size,
> +	.get_rxfh = enetc_get_rxfh,
> +	.set_rxfh = enetc_set_rxfh,
>  };
>  
>  void enetc_set_ethtool_ops(struct net_device *ndev)


From daniel.baluta at gmail.com  Mon Mar 17 08:58:07 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Mon, 17 Mar 2025 17:58:07 +0200
Subject: [PATCH v5 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <5873285.DvuYhMxLoT@steina-w>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
 <20250317133306.2003909-3-daniel.baluta@nxp.com> <5873285.DvuYhMxLoT@steina-w>
Message-ID: <CAEnQRZCsCYbQU8uxpFeyLmji65VRoO0rckRcoyc3frd2_B_KqQ@mail.gmail.com>

On Mon, Mar 17, 2025 at 5:30?PM Alexander Stein
<alexander.stein at ew.tq-group.com> wrote:
>
> Am Montag, 17. M?rz 2025, 14:33:03 CET schrieb Daniel Baluta:
> > Enable MU2 node and add mu2 root clock.
> > MU2 is used to communicate with DSP core.
> >
> > Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
> > Reviewed-by: Peng Fan <peng.fan at nxp.com>
> > Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> > ---
> >  arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> > index 3b725fe442d0..5b443fbeded8 100644
> > --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> > @@ -1253,7 +1253,7 @@ mu2: mailbox at 30e60000 {
> >                               reg = <0x30e60000 0x10000>;
> >                               interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
> >                               #mbox-cells = <2>;
> > -                             status = "disabled";
>
> There is no need to enable MU2 if the DSP is disabled by default, no?

True, I can enable it only when needed. Will fix in next version.


From andriy.shevchenko at linux.intel.com  Mon Mar 17 09:01:03 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 17 Mar 2025 18:01:03 +0200
Subject: [PATCH v8 03/10] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <e556f152a9cff2ff61e7b7a4b42feffb400cb1f9.1742225817.git.mazziesaccount@gmail.com>
References: <cover.1742225817.git.mazziesaccount@gmail.com>
 <e556f152a9cff2ff61e7b7a4b42feffb400cb1f9.1742225817.git.mazziesaccount@gmail.com>
Message-ID: <Z9hHP3vdCm0WFoyH@smile.fi.intel.com>

On Mon, Mar 17, 2025 at 05:50:49PM +0200, Matti Vaittinen wrote:
> There are ADC ICs which may have some of the AIN pins usable for other
> functions. These ICs may have some of the AIN pins wired so that they
> should not be used for ADC.
> 
> (Preferred?) way for marking pins which can be used as ADC inputs is to
> add corresponding channels at N nodes in the device tree as described in
> the ADC binding yaml.
> 
> Add couple of helper functions which can be used to retrieve the channel
> information from the device node.

LGTM now, thanks!
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko




From irogers at google.com  Mon Mar 17 09:02:47 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 09:02:47 -0700
Subject: [PATCH v2] perf libunwind: Fixup conversion perf_sample->user_regs
 to a pointer
In-Reply-To: <Z9TT3tGq4TJ76Tm9@google.com>
References: <20250313033121.758978-1-irogers@google.com> <Z9TT3tGq4TJ76Tm9@google.com>
Message-ID: <CAP-5=fVhd7=r+T6iL+ZgLi6YmDUzmDq-FEdZD1XHHYzm7KtBtw@mail.gmail.com>

On Fri, Mar 14, 2025 at 6:12?PM Namhyung Kim <namhyung at kernel.org> wrote:
>
> On Wed, Mar 12, 2025 at 08:31:21PM -0700, Ian Rogers wrote:
> > From: Arnaldo Carvalho de Melo <acme at redhat.com>
> >
> > The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
> > the changes to a file, resulting in this problem:
> >
> >   $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
> >   <SNIP>
> >     CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
> >     CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
> >   <SNIP>
> >   util/unwind-libunwind-local.c: In function ?access_mem?:
> >   util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
> >     582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
> >         |                                                        ^
> >         |                                                        ->
> >   util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
> >     587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
> >         |                                      ^~~~~~~~~~~~~~~~~~~~~~
> >         |                                      |
> >         |                                      struct regs_dump **
> > <SNIP>
> >   ? [acme at toolbox perf-tools-next]$ git bisect bad
> >   dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
> >   commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
> >   Author: Ian Rogers <irogers at google.com>
> >   Date:   Mon Jan 13 11:43:45 2025 -0800
> >
> >       perf sample: Make user_regs and intr_regs optional
> >
> > Detected using:
> >
> >   make -C tools/perf build-test
> >
> > Fixes: dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional")
> > Cc: Adrian Hunter <adrian.hunter at intel.com>
> > Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
> > Cc: Andi Kleen <ak at linux.intel.com>
> > Cc: Charlie Jenkins <charlie at rivosinc.com>
> > Cc: Ian Rogers <irogers at google.com>
> > Cc: Ingo Molnar <mingo at redhat.com>
> > Cc: James Clark <james.clark at linaro.org>
> > Cc: John Garry <john.g.garry at oracle.com>
> > Cc: Kan Liang <kan.liang at linux.intel.com>
> > Cc: Leo Yan <leo.yan at linux.dev>
> > Cc: Mark Rutland <mark.rutland at arm.com>
> > Cc: Michael Petlan <mpetlan at redhat.com>
> > Cc: Namhyung Kim <namhyung at kernel.org>
> > Cc: Peter Zijlstra <peterz at infradead.org>
> > Cc: Tavian Barnes <tavianator at tavianator.com>
> > Cc: Veronika Molnarova <vmolnaro at redhat.com>
> > Cc: coresight at lists.linaro.org
> > Cc: linux-arm-kernel at lists.infradead.org
> > Signed-off-by: Arnaldo Carvalho de Melo <acme at redhat.com>
> > Reviewed-by: Ian Rogers <irogers at google.com>
>
> I think you need to add your own Signed-off-by in this case.
> I'll change it for you, ok?

Sure.

Thanks,
Ian


From andriy.shevchenko at linux.intel.com  Mon Mar 17 09:03:01 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Mon, 17 Mar 2025 18:03:01 +0200
Subject: [PATCH v8 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <78d33ea9a795abdb2c5a4c606d48593e827ca59e.1742225817.git.mazziesaccount@gmail.com>
References: <cover.1742225817.git.mazziesaccount@gmail.com>
 <78d33ea9a795abdb2c5a4c606d48593e827ca59e.1742225817.git.mazziesaccount@gmail.com>
Message-ID: <Z9hHtTzUQ4CE8AB_@smile.fi.intel.com>

On Mon, Mar 17, 2025 at 05:51:14PM +0200, Matti Vaittinen wrote:
> The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
> help drivers avoid open-coding the for_each_node -loop for getting the
> channel IDs. The helper provides standard way to detect the ADC channel
> nodes (by the node name), and a standard way to convert the "reg"
> -properties to channel identification numbers, used in the struct
> iio_chan_spec. Furthermore, the helper can optionally check the found
> channel IDs are smaller than given maximum. This is useful for callers
> which later use the IDs for example for indexing a channel data array.
> 
> The original driver treated all found child nodes as channel nodes. The
> new helper requires channel nodes to be named channel[@N]. This should
> help avoid problems with devices which may contain also other but ADC
> child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
> string didn't reveal any in-tree .dts with channel nodes named
> otherwise. Also, same grep shows all the in-tree .dts seem to have
> channel IDs between 0..num of channels.
> 
> Use the new helper.

Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

-- 
With Best Regards,
Andy Shevchenko




From will at kernel.org  Mon Mar 17 09:00:35 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 17 Mar 2025 16:00:35 +0000
Subject: [GIT PULL] arm64 fixes for -rc7
In-Reply-To: <CAHk-=wgiX0q0WCL+SFwVCYtG7JR3=2Rshse-5J3AO2Y4AgT7Jw@mail.gmail.com>
References: <20250314160458.GA9438@willie-the-truck>
 <CAHk-=wgiX0q0WCL+SFwVCYtG7JR3=2Rshse-5J3AO2Y4AgT7Jw@mail.gmail.com>
Message-ID: <20250317160034.GA12267@willie-the-truck>

Hi Linus,

On Fri, Mar 14, 2025 at 10:34:57AM -1000, Linus Torvalds wrote:
> On Fri, 14 Mar 2025 at 06:05, Will Deacon <will at kernel.org> wrote:
> >
> > Summary in the tag, but the main one is a horrible macro fix for our
> > TLB flushing code which resulted in over-invalidation on the MMU
> > notifier path.
> 
> From a quick look, that macro is still quite broken. Maybe not in ways
> that matter, but still...
> 
> In particular, the 'stride' argument is used multiple times, and
> without parentheses.
> 
> The 'lpa' argument is also used multiple times, and the input to that
> is typically something like kvm_lpa2_is_enabled(), so I think it
> potentially generates lots of pointless duplicate code with that
> BUG_ON() in system_supports_lpa2() -> cpus_have_final_cap().
> 
> Maybe the compiler figures it out. But that macro is bad, bad, bad.
> When it looks like a function, it should act like a function, and not
> evaluate its arguments multiple times.
> 
> The most immediate bug may have been fixed, but not the actual real
> horror of that thing.

Yes, the minimal fix for -rc7 avoids explicitly mutating the macro
arguments but we still have the multiple-evaluation problem you point
out above.

Ideally, this function would be rewritten as a 'static inline' but it
was moved from C code into a macro as part of 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") because we need
to propagate the 'op' argument down to the low-level asm where it's
stringified as part of the instruction mnemonic.

I'll have a crack at reworking things to take a 'const char *' instead,
but it won't be for 6.14 as it'll be reasonably invasive.

Will


From krzysztof.kozlowski at linaro.org  Mon Mar 17 09:07:26 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 17:07:26 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
Message-ID: <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>

On 17/03/2025 09:47, Alberto Merciai wrote:
> While playing with linux-next and imx93-11x11-evk via NFS and TFTP
> I found that the dwmac-imx, nvmem-imx-ocotp-ele drivers by default are
> not builtin then the I was not able to reach userland. 
> 
> The following configs were needed to reach my goal:
> CONFIG_DWMAC_IMX8=y
> CONFIG_STMMAC_ETH=y
> CONFIG_NVMEM_IMX_OCOTP_ELE=y
> 
> is that something expected?

You mean they are disabled or you just did not put them inside your
initramfs?

Best regards,
Krzysztof


From neil.armstrong at linaro.org  Mon Mar 17 09:10:44 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 17:10:44 +0100
Subject: [GIT PULL] amlogic ARM DT updates for v6.15
Message-ID: <8632a8fa-7af6-4fb7-ba87-297df4f084f5@linaro.org>

Hi,

Here's a simple changeset for Amlogic ARM DT to switch to the new PWM controller bindings.

Thanks,
Neil

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

   https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git tags/amlogic-arm-dt-for-v6.15

for you to fetch changes up to dbf921861985c8d1db339bc8ad0652b9064f2f84:

   ARM: dts: amlogic: meson8b: switch to the new PWM controller binding (2025-02-28 09:16:23 +0100)

----------------------------------------------------------------
Amlogic ARM DT changes for v6.15:
- switch to the new PWM controller bindings

----------------------------------------------------------------
Martin Blumenstingl (2):
       ARM: dts: amlogic: meson8: switch to the new PWM controller binding
       ARM: dts: amlogic: meson8b: switch to the new PWM controller binding

  arch/arm/boot/dts/amlogic/meson8.dtsi          | 18 +++++++++++++++---
  arch/arm/boot/dts/amlogic/meson8b-ec100.dts    |  2 --
  arch/arm/boot/dts/amlogic/meson8b-mxq.dts      |  2 --
  arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts |  2 --
  arch/arm/boot/dts/amlogic/meson8b.dtsi         | 18 +++++++++++++++---
  5 files changed, 30 insertions(+), 12 deletions(-)


From neil.armstrong at linaro.org  Mon Mar 17 09:13:43 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 17:13:43 +0100
Subject: [GIT PULL] amlogic ARM64 DT updates for v6.15
Message-ID: <41ced8db-caeb-4deb-9193-9802fc603180@linaro.org>

Hi,

Here's a changeset for Amlogic ARM64 DT, also switching to the new PWM bindings,
adding pinctrl support for Amlogic A4 SoC with a brand new binding style then
finally gpio_intc node for Amlogic A4 & A5 SoCs.

Thanks,
Neil

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

   https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git tags/amlogic-arm64-dt-for-v6.15

for you to fetch changes up to 454e0353b226a47f3c3369b17c7a4893f74e29cd:

   arm64: dts: Add gpio_intc node for Amlogic A5 SoCs (2025-03-17 08:38:58 +0100)

----------------------------------------------------------------
Amlogic ARM64 DT changes for v6.15:
- Add pinctrl support for Amlogic A4 SoC with new bindings
- switch to the new PWM controller binding
- Add gpio_intc node for Amlogic A4 & A5 SoCs

----------------------------------------------------------------
Martin Blumenstingl (3):
       arm64: dts: amlogic: gx: switch to the new PWM controller binding
       arm64: dts: amlogic: axg: switch to the new PWM controller binding
       arm64: dts: amlogic: g12: switch to the new PWM controller binding

Neil Armstrong (1):
       Merge branch 'ib-amlogic-a4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl into HEAD

Xianwei Zhao (7):
       dt-bindings: pinctrl: Add support for Amlogic A4 SoC
       pinctrl: pinconf-generic: Add API for pinmux propertity in DTS file
       pinctrl: Add driver support for Amlogic SoCs
       MAINTAINERS: Add an entry for Amlogic pinctrl driver
       arm64: dts: amlogic: a4: add pinctrl node
       arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
       arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

  .../bindings/pinctrl/amlogic,pinctrl-a4.yaml       |  126 +++
  MAINTAINERS                                        |    8 +
  arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  139 +++
  arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |   12 +
  arch/arm64/boot/dts/amlogic/meson-axg.dtsi         |   24 +-
  arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi  |   33 +-
  arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts  |    4 -
  .../boot/dts/amlogic/meson-g12a-radxa-zero.dts     |    4 -
  arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts  |    4 -
  arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts    |    2 -
  arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts |    4 -
  .../dts/amlogic/meson-g12b-a311d-libretech-cc.dts  |    2 -
  .../boot/dts/amlogic/meson-g12b-bananapi-cm4.dtsi  |    4 -
  .../boot/dts/amlogic/meson-g12b-bananapi.dtsi      |    4 -
  .../boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi   |    4 -
  arch/arm64/boot/dts/amlogic/meson-g12b-odroid.dtsi |    4 -
  .../boot/dts/amlogic/meson-g12b-radxa-zero2.dts    |    8 -
  arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi   |    6 -
  .../boot/dts/amlogic/meson-gx-libretech-pc.dtsi    |    6 -
  .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |    2 -
  arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |    8 +-
  .../boot/dts/amlogic/meson-gxbb-nanopi-k2.dts      |    2 -
  .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    |    2 -
  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |    2 -
  .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |    2 -
  arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi  |    2 -
  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   25 +
  .../boot/dts/amlogic/meson-gxl-s805x-p241.dts      |    2 -
  .../amlogic/meson-gxl-s905w-jethome-jethub-j80.dts |    2 -
  .../dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts |    2 -
  .../dts/amlogic/meson-gxl-s905x-khadas-vim.dts     |    2 -
  .../dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts    |    2 -
  .../boot/dts/amlogic/meson-gxl-s905x-p212.dtsi     |    2 -
  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi         |   25 +
  .../boot/dts/amlogic/meson-gxm-khadas-vim2.dts     |    4 -
  arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts |    2 -
  .../dts/amlogic/meson-libretech-cottonwood.dtsi    |    6 -
  arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi   |    6 -
  .../arm64/boot/dts/amlogic/meson-sm1-bananapi.dtsi |    2 -
  .../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts    |    2 -
  arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi  |    2 -
  arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts   |    6 -
  drivers/pinctrl/meson/Kconfig                      |   11 +
  drivers/pinctrl/meson/Makefile                     |    1 +
  drivers/pinctrl/meson/pinctrl-amlogic-a4.c         | 1053 ++++++++++++++++++++
  drivers/pinctrl/pinconf-generic.c                  |  130 +++
  drivers/pinctrl/pinconf.h                          |    4 +
  include/dt-bindings/pinctrl/amlogic,pinctrl.h      |   46 +
  include/linux/pinctrl/pinconf-generic.h            |    4 +
  49 files changed, 1636 insertions(+), 123 deletions(-)
  create mode 100644 Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml
  create mode 100644 drivers/pinctrl/meson/pinctrl-amlogic-a4.c
  create mode 100644 include/dt-bindings/pinctrl/amlogic,pinctrl.h


From neil.armstrong at linaro.org  Mon Mar 17 09:16:08 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 17 Mar 2025 17:16:08 +0100
Subject: [GIT PULL] Amlogic drivers updates for v6.15
Message-ID: <eeaa8d3b-4fc3-4dae-92b8-0fc590e1a070@linaro.org>

Hi,

Here's the GPIO interrupt controller bindings & driver, acked by Thomas to be
merged via the Amlogic tree along the DT changes.

Thanks,
Neil

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

   https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git tags/amlogic-drivers-for-v6.15

for you to fetch changes up to bbd6fcc76b39502767e213ad24a349205cf75e96:

   irqchip: Add support for Amlogic A4 and A5 SoCs (2025-03-17 08:38:24 +0100)

----------------------------------------------------------------
Amlogic drivers changes for v6.15:
- GPIO interrupt controller support for Amlogic A4 and A5 SoCs

----------------------------------------------------------------
Xianwei Zhao (2):
       dt-bindings: interrupt-controller: Add support for Amlogic A4 and A5 SoCs
       irqchip: Add support for Amlogic A4 and A5 SoCs

  .../amlogic,meson-gpio-intc.yaml                   | 19 ++++++++-
  drivers/irqchip/irq-meson-gpio.c                   | 48 +++++++++++++++++-----
  2 files changed, 55 insertions(+), 12 deletions(-)


From dietmar.eggemann at arm.com  Mon Mar 17 09:18:49 2025
From: dietmar.eggemann at arm.com (Dietmar Eggemann)
Date: Mon, 17 Mar 2025 17:18:49 +0100
Subject: [PATCH v12 2/4] arch_topology: Support SMT control for OF based
 system
In-Reply-To: <c88e5b78-37b7-3023-7842-56a93fe119d2@huawei.com>
References: <20250311075143.61078-1-yangyicong@huawei.com>
 <20250311075143.61078-3-yangyicong@huawei.com>
 <2bd3aa0a-d700-46bf-81d1-a5fb0364d1e0@arm.com>
 <c88e5b78-37b7-3023-7842-56a93fe119d2@huawei.com>
Message-ID: <c357e638-d523-4cd2-a15f-ed3b0b41bd22@arm.com>

On 17/03/2025 12:29, Yicong Yang wrote:
> On 2025/3/17 17:56, Dietmar Eggemann wrote:
>> On 11/03/2025 08:51, Yicong Yang wrote:
>>> From: Yicong Yang <yangyicong at hisilicon.com>

[...]

>>> Both method support to completely disable/enable the SMT cores so both
>>> work correctly for symmetric SMT platform and asymmetric platform with
>>> non-SMT and one type SMT cores like:
>>> core A: 1 thread
>>> core B: X (X!=1) threads
>>>
>>> Note that for a theoretically possible multiple SMT-X (X>1) core
>>> platform the SMT control is also supported as expected but only
>>> by writing the "on/off" method.
>>
>> Here we still have a little misunderstanding. IMHO, even on such a
>> system 2) would work too.
>>
> 
> 
> yes but only by writing the max_thread_number. e.g. a system with SMT number
> of 1 (no SMT core), X, Y (Y > X), 1 works same as "off" and Y works same as
> "on", as you shown below. write X will be blocked by the CPU framework:
> estuary:/sys/devices/system/cpu/smt$ cat control
> off
> # emulated CPU 0-7,16-22 as SMT-2, CPU 8-11,24-27 as SMT-4
> estuary:/sys/devices/system/cpu/smt$ cat ../online
> 0,2,4,6,8,12-16,18,20,22,24,28-31
> estuary:/sys/devices/system/cpu/smt$ echo 2 > control
> bash: echo: write error: Invalid argument
> estuary:/sys/devices/system/cpu/smt$ echo 4 > control
> estuary:/sys/devices/system/cpu/smt$ cat ../online
> 0-31
> 
> so method 1) will always match the expectation to fully enable/disable the
> SMT on all cores, that's I mean here. But 2) won't work if user expected
> to write 2 to enable SMT-2 (I think it'll will work if we support
> CONFIG_SMT_NUM_THREADS_DYNAMIC on arm64 later).

OK, looks like you're aware of this then. Just saying that technically
'4' would be the max thread number of the system and not '2' so it still
looks OK from this perspective. But OK, we don't have those systems now
anyway.

[...]


From robh at kernel.org  Mon Mar 17 09:21:04 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:21:04 -0500
Subject: [net-next PATCH v13 03/14] dt-bindings: net: dsa: Document
 support for Airoha AN8855 DSA Switch
In-Reply-To: <20250315154407.26304-4-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
 <20250315154407.26304-4-ansuelsmth@gmail.com>
Message-ID: <174222846382.166778.10361750788975293677.robh@kernel.org>


On Sat, 15 Mar 2025 16:43:43 +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 5-port Gigabit Switch.
> 
> It does expose the 5 Internal PHYs on the MDIO bus and each port
> can access the Switch register space by configurting the PHY page.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../net/dsa/airoha,an8855-switch.yaml         | 86 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 87 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 17 09:22:13 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:22:13 -0500
Subject: [net-next PATCH v13 04/14] dt-bindings: net: Document support
 for AN8855 Switch Internal PHY
In-Reply-To: <20250315154407.26304-5-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
 <20250315154407.26304-5-ansuelsmth@gmail.com>
Message-ID: <174222853284.168151.15677522554772356388.robh@kernel.org>


On Sat, 15 Mar 2025 16:43:44 +0100, Christian Marangi wrote:
> Document support for AN8855 Switch Internal PHY.
> 
> Airoha AN8855 is a 5-port Gigabit Switch that expose the Internal
> PHYs on the MDIO bus.
> 
> Each PHY might need to be calibrated to correctly work with the
> use of the eFUSE provided by the Switch SoC. This can be enabled by
> defining in the PHY node the NVMEM cell properties.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/net/airoha,an8855-phy.yaml       | 83 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 84 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-phy.yaml
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 17 09:28:48 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:28:48 -0500
Subject: [PATCH 4/7] dt-bindings: serial: amlogic,meson-uart: Add
 compatible string for S6/S7/S7D
In-Reply-To: <20250317-s6-s7-basic-v1-4-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
 <20250317-s6-s7-basic-v1-4-d653384e41f3@amlogic.com>
Message-ID: <174222892762.176016.11358063656665993798.robh@kernel.org>


On Mon, 17 Mar 2025 15:16:55 +0800, Xianwei Zhao wrote:
> Amlogic S6/S7/7D SoCs uses the same UART controller as S4 SoCs and G12A.
> There is no need for an extra compatible line in the driver, but
> add S6/S7/S7D compatible line for documentation.
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From liujianfeng1994 at gmail.com  Mon Mar 17 09:32:21 2025
From: liujianfeng1994 at gmail.com (Jianfeng Liu)
Date: Tue, 18 Mar 2025 00:32:21 +0800
Subject: [PATCH] arm64: dts: rockchip: Enable HDMI ports on ArmSoM W3
Message-ID: <20250317163240.3083908-1-liujianfeng1994@gmail.com>

Enable the two HDMI ports on ArmSoM W3. And audio output of these two
ports are also enabled.

Signed-off-by: Jianfeng Liu <liujianfeng1994 at gmail.com>
---

 .../boot/dts/rockchip/rk3588-armsom-w3.dts    | 101 ++++++++++++++++++
 1 file changed, 101 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts
index 779cd1b1798c..6ad2759ddcca 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts
@@ -4,6 +4,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
 #include "rk3588-armsom-lm7.dtsi"
 
 / {
@@ -32,6 +33,28 @@ analog-sound {
 		pinctrl-0 = <&hp_detect>;
 	};
 
+	hdmi0-con {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi0_con_in: endpoint {
+				remote-endpoint = <&hdmi0_out_con>;
+			};
+		};
+	};
+
+	hdmi1-con {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi1_con_in: endpoint {
+				remote-endpoint = <&hdmi1_out_con>;
+			};
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -138,6 +161,54 @@ &combphy2_psu {
 	status = "okay";
 };
 
+&hdmi0 {
+	status = "okay";
+};
+
+&hdmi0_in {
+	hdmi0_in_vp0: endpoint {
+		remote-endpoint = <&vp0_out_hdmi0>;
+	};
+};
+
+&hdmi0_out {
+	hdmi0_out_con: endpoint {
+		remote-endpoint = <&hdmi0_con_in>;
+	};
+};
+
+&hdmi0_sound {
+	status = "okay";
+};
+
+&hdmi1 {
+	status = "okay";
+};
+
+&hdmi1_in {
+	hdmi1_in_vp1: endpoint {
+		remote-endpoint = <&vp1_out_hdmi1>;
+	};
+};
+
+&hdmi1_out {
+	hdmi1_out_con: endpoint {
+		remote-endpoint = <&hdmi1_con_in>;
+	};
+};
+
+&hdmi1_sound {
+	status = "okay";
+};
+
+&hdptxphy0 {
+	status = "okay";
+};
+
+&hdptxphy1 {
+	status = "okay";
+};
+
 &i2c6 {
 	status = "okay";
 
@@ -192,6 +263,14 @@ i2s0_8ch_p0_0: endpoint {
 	};
 };
 
+&i2s5_8ch {
+	status = "okay";
+};
+
+&i2s6_8ch {
+	status = "okay";
+};
+
 &package_thermal {
 	polling-delay = <1000>;
 
@@ -406,3 +485,25 @@ &usb_host1_xhci {
 &usb_host2_xhci {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0 {
+	vp0_out_hdmi0: endpoint at ROCKCHIP_VOP2_EP_HDMI0 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+		remote-endpoint = <&hdmi0_in_vp0>;
+	};
+};
+
+&vp1 {
+	vp1_out_hdmi1: endpoint at ROCKCHIP_VOP2_EP_HDMI1 {
+		reg = <ROCKCHIP_VOP2_EP_HDMI1>;
+		remote-endpoint = <&hdmi1_in_vp1>;
+	};
+};
-- 
2.43.0



From vladimir.oltean at nxp.com  Mon Mar 17 09:33:37 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 18:33:37 +0200
Subject: [PATCH v4 net-next 09/14] net: enetc: enable RSS feature by
 default
In-Reply-To: <20250311053830.1516523-10-wei.fang@nxp.com>
 <20250311053830.1516523-10-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-10-wei.fang@nxp.com>
 <20250311053830.1516523-10-wei.fang@nxp.com>
Message-ID: <20250317163337.4ii2bmourroiaryl@skbuf>

On Tue, Mar 11, 2025 at 01:38:25PM +0800, Wei Fang wrote:
> Receive side scaling (RSS) is a network driver technology that enables
> the efficient distribution of network receive processing across multiple
> CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
> default so that the CPU load can be balanced and network performance can
> be improved when then network is enabled.

s/then network/the network/

> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---
>  drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++++++++++---------
>  .../freescale/enetc/enetc_pf_common.c         |  4 ++-
>  .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
>  3 files changed, 25 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
> index 5b5e65ac8fab..8583ac9f7b9e 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
> @@ -2420,6 +2420,22 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
>  	enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
>  }
>  
> +static int enetc_set_rss(struct net_device *ndev, int en)

Can you please add a preliminary patch which converts this function's
prototype to:

static void enetc_set_rss(struct net_device *ndev, bool en)
?

After you do that please feel free to add my tag and keep it in future
patch submissions:

Acked-by: Vladimir Oltean <vladimir.oltean at nxp.com>

I don't see downsides to enabling RX hashing by default.


From vladimir.oltean at nxp.com  Mon Mar 17 09:26:17 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 18:26:17 +0200
Subject: [PATCH v4 net-next 07/14] net: enetc: make enetc_set_rss_key()
 reusable
In-Reply-To: <20250311053830.1516523-8-wei.fang@nxp.com>
 <20250311053830.1516523-8-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-8-wei.fang@nxp.com>
 <20250311053830.1516523-8-wei.fang@nxp.com>
Message-ID: <20250317162617.glikwbcey3s3isfn@skbuf>

On Tue, Mar 11, 2025 at 01:38:23PM +0800, Wei Fang wrote:
> Since the offset of the RSS key registers of i.MX95 ENETC is different
> from that of LS1028A, so add enetc_get_rss_key_base() to get the base
> offset for the different chips, so that enetc_set_rss_key() can be
> reused for this trivial.

for this trivial... ? task?

> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---
>  drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
>  .../net/ethernet/freescale/enetc/enetc4_pf.c  | 11 +----------
>  .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 ++++++++++++++-----
>  .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +-
>  4 files changed, 17 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> index a98ed059a83f..f991e1aae85c 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> @@ -583,22 +583,13 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
>  	enetc4_pf_reset_tc_msdu(&si->hw);
>  }
>  
> -static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
> -{
> -	int i;
> -
> -	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> -		enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
> -}
> -
>  static void enetc4_set_default_rss_key(struct enetc_pf *pf)
>  {
>  	u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
> -	struct enetc_hw *hw = &pf->si->hw;
>  
>  	/* set up hash key */
>  	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
> -	enetc4_set_rss_key(hw, hash_key);
> +	enetc_set_rss_key(pf->si, hash_key);
>  }

The entire enetc4_set_default_rss_key() seems reusable as
enetc_set_default_rss_key(). enetc_configure_port() has the same logic.

>  
>  static void enetc4_enable_trx(struct enetc_pf *pf)


From robh at kernel.org  Mon Mar 17 09:28:05 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:28:05 -0500
Subject: [PATCH 1/7] dt-bindings: arm: amlogic: add S6 support
In-Reply-To: <20250317-s6-s7-basic-v1-1-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
 <20250317-s6-s7-basic-v1-1-d653384e41f3@amlogic.com>
Message-ID: <174222888470.174842.6381740588460152313.robh@kernel.org>


On Mon, 17 Mar 2025 15:16:52 +0800, Xianwei Zhao wrote:
> Document the new S6 SoC/board device tree bindings.
> 
> Amlogic S6 is an advanced application processor designed for
> hybrid OTT/IP Set Top Box and high-end media box applications.
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 17 09:28:19 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:28:19 -0500
Subject: [PATCH 2/7] dt-bindings: arm: amlogic: add S7 support
In-Reply-To: <20250317-s6-s7-basic-v1-2-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
 <20250317-s6-s7-basic-v1-2-d653384e41f3@amlogic.com>
Message-ID: <174222889947.175239.6799516902581952337.robh@kernel.org>


On Mon, 17 Mar 2025 15:16:53 +0800, Xianwei Zhao wrote:
> Document the new S7 SoC/board device tree bindings.
> 
> Amlogic S7 is an advanced application processor designed for
> hybrid OTT/IP Set Top Box and high-end media box applications.
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 17 09:28:37 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:28:37 -0500
Subject: [PATCH 3/7] dt-bindings: arm: amlogic: add S7D support
In-Reply-To: <20250317-s6-s7-basic-v1-3-d653384e41f3@amlogic.com>
References: <20250317-s6-s7-basic-v1-0-d653384e41f3@amlogic.com>
 <20250317-s6-s7-basic-v1-3-d653384e41f3@amlogic.com>
Message-ID: <174222891679.175685.18314787347681123484.robh@kernel.org>


On Mon, 17 Mar 2025 15:16:54 +0800, Xianwei Zhao wrote:
> Document the new S7D SoC/board device tree bindings.
> 
> Amlogic S7D is an advanced application processor designed for
> hybrid OTT/IP Set Top Box and high-end media box applications.
> 
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  Documentation/devicetree/bindings/arm/amlogic.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 17 09:33:58 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 17 Mar 2025 11:33:58 -0500
Subject: [PATCH RFC v3 3/3] dt-bindings: mailbox: mtk,mt8196-vcp-mbox:
 add mtk vcp-mbox document
In-Reply-To: <20250317110331.2776-4-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
 <20250317110331.2776-4-jjian.zhou@mediatek.com>
Message-ID: <20250317163358.GA178378-robh@kernel.org>

On Mon, Mar 17, 2025 at 07:03:25PM +0800, Jjian Zhou wrote:
> This patch adds document for mediatek vcp mbox.
> 
> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> ---
>  .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49 +++++++++++++++++++
>  1 file changed, 49 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
> new file mode 100644
> index 000000000000..bd1b024e22f1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml

Still wrong...

> +  compatible:
> +    enum:
> +      - mediatek,mt8196-vcp-mbox

mediatek,mt8196-vcp-mbox != mtk,mt8196-vcp-mbox



From robh at kernel.org  Mon Mar 17 09:41:30 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 11:41:30 -0500
Subject: [PATCH RESEND] dt-bindings: mtd: atmel,dataflash: convert txt to
 yaml
In-Reply-To: <20250317-atmel-dataflash-v1-1-1a3247f40299@microchip.com>
References: <20250317-atmel-dataflash-v1-1-1a3247f40299@microchip.com>
Message-ID: <174222968999.190541.5419012872834930399.robh@kernel.org>


On Mon, 17 Mar 2025 19:01:08 +0530, Nayab Sayed wrote:
> Convert atmel-dataflash.txt into atmel,dataflash.yaml
> 
> Signed-off-by: Nayab Sayed <nayabbasha.sayed at microchip.com>
> ---
>  .../devicetree/bindings/mtd/atmel,dataflash.yaml   | 55 ++++++++++++++++++++++
>  .../devicetree/bindings/mtd/atmel-dataflash.txt    | 17 -------
>  2 files changed, 55 insertions(+), 17 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From vladimir.oltean at nxp.com  Mon Mar 17 09:42:05 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 18:42:05 +0200
Subject: [PATCH v4 net-next 06/14] net: enetc: add set/get_rss_table() to
 enetc_si_ops
In-Reply-To: <20250311053830.1516523-7-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-7-wei.fang@nxp.com>
Message-ID: <20250317164205.bp4vcqarggp3fnf4@skbuf>

On Tue, Mar 11, 2025 at 01:38:22PM +0800, Wei Fang wrote:
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> index d7d9a720069b..072e5b40a199 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> @@ -165,6 +165,8 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
>  static const struct enetc_si_ops enetc_vsi_ops = {
>  	.setup_cbdr = enetc_setup_cbdr,
>  	.teardown_cbdr = enetc_teardown_cbdr,
> +	.get_rss_table = enetc_get_rss_table,
> +	.set_rss_table = enetc_set_rss_table,
>  };

Are the CBDR-based enetc_get_rss_table() and enetc_set_rss_table()
the correct implementations for NETC v4 VSIs? (I guess not). Does
the driver/hardware fail in a civilized way, or does it crash?


From andersson at kernel.org  Mon Mar 17 10:04:13 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 17 Mar 2025 12:04:13 -0500
Subject: (subset) [PATCH v12 0/6] Add NSS clock controller support for IPQ9574
In-Reply-To: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
Message-ID: <174223105141.2000272.10352611755097062716.b4-ty@kernel.org>


On Thu, 13 Mar 2025 16:33:53 +0530, Manikanta Mylavarapu wrote:
> Add bindings, driver and devicetree node for networking sub system clock
> controller on IPQ9574. Also add support for gpll0_out_aux clock
> which serves as the parent for some nss clocks.
> 
> Changes in V12:
> 	- nsscc driver
> 		- Pick up R-b tag.
> 	- dtsi
> 		- Pick up R-b tag.
> 	- defconfig
> 		- Pick up R-b tag.
> 	- Rebased on linux-next tip.
> 
> [...]

Applied, thanks!

[6/6] arm64: defconfig: Build NSS Clock Controller driver for IPQ9574
      commit: 95204a95fd9657ffbd3f3c4a726e458833e4213d

Best regards,
-- 
Bjorn Andersson <andersson at kernel.org>


From vladimir.oltean at nxp.com  Mon Mar 17 10:05:11 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 19:05:11 +0200
Subject: [PATCH v4 net-next 10/14] net: enetc: move generic VLAN filter
 interfaces to enetc-core
In-Reply-To: <20250311053830.1516523-11-wei.fang@nxp.com>
 <20250311053830.1516523-11-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-11-wei.fang@nxp.com>
 <20250311053830.1516523-11-wei.fang@nxp.com>
Message-ID: <20250317170511.u7kfzmqafznovpoy@skbuf>

On Tue, Mar 11, 2025 at 01:38:26PM +0800, Wei Fang wrote:
> For ENETC, each SI has a corresponding VLAN hash table. That is to say,
> both PF and VFs can support VLAN filter. However, currently only ENETC v1
> PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
> VF drivers also support VLAN filter, some related macros are moved from
> enetc_pf.h to enetc.h, and the related structure variables are moved from
> enetc_pf to enetc_si.
> 
> Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
> Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
> so that it can be shared by PF and VF drivers. This will make it easier
> to add VLAN filter support for i.MX95 ENETC later.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---

In this and the next patch, can you please separate the code movement
from the logical changes? It makes review much more difficult. With the
similar observation that, as in the case of MAC filtering, VSIs don't
yet support VLAN filtering, so the movement of the hash table structures
from per-PF to per-SI is currently premature. So I expect to see that
part removed from the next revision.


From vladimir.oltean at nxp.com  Mon Mar 17 10:06:50 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Mon, 17 Mar 2025 19:06:50 +0200
Subject: [PATCH v4 net-next 14/14] MAINTAINERS: add new file ntmp.h to
 ENETC driver
In-Reply-To: <20250311053830.1516523-15-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-15-wei.fang@nxp.com>
Message-ID: <20250317170650.4oux6kxh2ng4z725@skbuf>

On Tue, Mar 11, 2025 at 01:38:30PM +0800, Wei Fang wrote:
> Add new file ntmp.h. to ENETC driver.
> 
> Signed-off-by: Wei Fang <wei.fang at nxp.com>
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7078199fcebf..e259b659eadb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9174,6 +9174,7 @@ F:	Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
>  F:	drivers/net/ethernet/freescale/enetc/
>  F:	include/linux/fsl/enetc_mdio.h
>  F:	include/linux/fsl/netc_global.h
> +F:	include/linux/fsl/ntmp.h
>  
>  FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
>  M:	Claudiu Manoil <claudiu.manoil at nxp.com>
> -- 
> 2.34.1
>

This should be squashed with the patch that adds the initial NTMP support.
We don't split out patches to the MAINTAINERS file.


From romank at linux.microsoft.com  Mon Mar 17 10:07:02 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 17 Mar 2025 10:07:02 -0700
Subject: [PATCH hyperv-next v6 11/11] PCI: hv: Get vPCI MSI IRQ domain
 from DeviceTree
In-Reply-To: <20250315184903.GA848938@bhelgaas>
References: <20250315184903.GA848938@bhelgaas>
Message-ID: <9c3f2492-823e-4548-8ad3-6aeb9c86d528@linux.microsoft.com>



On 3/15/2025 11:49 AM, Bjorn Helgaas wrote:
> On Fri, Mar 14, 2025 at 05:19:31PM -0700, Roman Kisel wrote:
>> The hyperv-pci driver uses ACPI for MSI IRQ domain configuration on
>> arm64. It won't be able to do that in the VTL mode where only DeviceTree
>> can be used.
>>
>> Update the hyperv-pci driver to get vPCI MSI IRQ domain in the DeviceTree
>> case, too.
>>
>> Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> 
> Acked-by: Bjorn Helgaas <bhelgaas at google.com>
> 
> Looks good to me; trivial whitespace comment below.
> 

Thanks a bunch!! I'll fix that the whitespace (and remove the unused
variable the robot noticed).

>> ---
>>   drivers/pci/controller/pci-hyperv.c | 73 ++++++++++++++++++++++++++---
>>   1 file changed, 67 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
>> index 6084b38bdda1..cbff19e8a07c 100644
>> --- a/drivers/pci/controller/pci-hyperv.c
>> +++ b/drivers/pci/controller/pci-hyperv.c
>> @@ -50,6 +50,7 @@
>>   #include <linux/irqdomain.h>
>>   #include <linux/acpi.h>
>>   #include <linux/sizes.h>
>> +#include <linux/of_irq.h>
>>   #include <asm/mshyperv.h>
>>   
>>   /*
>> @@ -817,9 +818,17 @@ static int hv_pci_vec_irq_gic_domain_alloc(struct irq_domain *domain,
>>   	int ret;
>>   
>>   	fwspec.fwnode = domain->parent->fwnode;
>> -	fwspec.param_count = 2;
>> -	fwspec.param[0] = hwirq;
>> -	fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
>> +	if (is_of_node(fwspec.fwnode)) {
>> +		/* SPI lines for OF translations start at offset 32 */
>> +		fwspec.param_count = 3;
>> +		fwspec.param[0] = 0;
>> +		fwspec.param[1] = hwirq - 32;
>> +		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
>> +	} else {
>> +		fwspec.param_count = 2;
>> +		fwspec.param[0] = hwirq;
>> +		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
>> +	}
>>   
>>   	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
>>   	if (ret)
>> @@ -887,10 +896,47 @@ static const struct irq_domain_ops hv_pci_domain_ops = {
>>   	.activate = hv_pci_vec_irq_domain_activate,
>>   };
>>   
>> +#ifdef CONFIG_OF
>> +
>> +static struct irq_domain *hv_pci_of_irq_domain_parent(void)
>> +{
>> +	struct device_node *parent;
>> +	struct irq_domain *domain;
>> +
>> +	parent = of_irq_find_parent(hv_get_vmbus_root_device()->of_node);
>> +	if (!parent)
>> +		return NULL;
>> +	domain = irq_find_host(parent);
>> +	of_node_put(parent);
>> +
>> +	return domain;
>> +}
>> +
>> +#endif
>> +
>> +#ifdef CONFIG_ACPI
>> +
>> +static struct irq_domain *hv_pci_acpi_irq_domain_parent(void)
>> +{
>> +	struct irq_domain *domain;
>> +	acpi_gsi_domain_disp_fn gsi_domain_disp_fn;
>> +
>> +	if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
>> +		return NULL;
>> +	gsi_domain_disp_fn = acpi_get_gsi_dispatcher();
>> +	if (!gsi_domain_disp_fn)
>> +		return NULL;
>> +	return irq_find_matching_fwnode(gsi_domain_disp_fn(0),
>> +				     DOMAIN_BUS_ANY);
>> +}
>> +
>> +#endif
>> +
>>   static int hv_pci_irqchip_init(void)
>>   {
>>   	static struct hv_pci_chip_data *chip_data;
>>   	struct fwnode_handle *fn = NULL;
>> +	struct irq_domain *irq_domain_parent = NULL;
>>   	int ret = -ENOMEM;
>>   
>>   	chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
>> @@ -907,9 +953,24 @@ static int hv_pci_irqchip_init(void)
>>   	 * way to ensure that all the corresponding devices are also gone and
>>   	 * no interrupts will be generated.
>>   	 */
>> -	hv_msi_gic_irq_domain = acpi_irq_create_hierarchy(0, HV_PCI_MSI_SPI_NR,
>> -							  fn, &hv_pci_domain_ops,
>> -							  chip_data);
>> +#ifdef CONFIG_ACPI
>> +	if (!acpi_disabled)
>> +		irq_domain_parent = hv_pci_acpi_irq_domain_parent();
>> +#endif
>> +#if defined(CONFIG_OF)
>> +	if (!irq_domain_parent)
>> +		irq_domain_parent = hv_pci_of_irq_domain_parent();
>> +#endif
>> +	if (!irq_domain_parent) {
>> +		WARN_ONCE(1, "Invalid firmware configuration for VMBus interrupts\n");
>> +		ret = -EINVAL;
>> +		goto free_chip;
>> +	}
>> +
>> +	hv_msi_gic_irq_domain = irq_domain_create_hierarchy(
>> +		irq_domain_parent, 0, HV_PCI_MSI_SPI_NR,
>> +		fn, &hv_pci_domain_ops,
>> +		chip_data);
> 
> This is a different style of indenting the parameters than other
> similar cases in this file, which line up parameters on subsequent
> lines under the open parenthesis.
> 
>>   	if (!hv_msi_gic_irq_domain) {
>>   		pr_err("Failed to create Hyper-V arm64 vPCI MSI IRQ domain\n");
>> -- 
>> 2.43.0
>>

-- 
Thank you,
Roman



From romank at linux.microsoft.com  Mon Mar 17 10:07:41 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 17 Mar 2025 10:07:41 -0700
Subject: [PATCH hyperv-next v6 07/11] dt-bindings: microsoft,vmbus: Add
 interrupt and DMA coherence properties
In-Reply-To: <20250316-versed-trogon-of-serendipity-bf7ea7@krzk-bin>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-8-romank@linux.microsoft.com>
 <20250316-versed-trogon-of-serendipity-bf7ea7@krzk-bin>
Message-ID: <091001a7-7398-4f5f-b9b6-d220a5a226cb@linux.microsoft.com>



On 3/16/2025 10:36 AM, Krzysztof Kozlowski wrote:
> On Fri, Mar 14, 2025 at 05:19:27PM -0700, Roman Kisel wrote:
>>   
>> +  dma-coherent: true
>> +
>> +  interrupts:
> 
>> +    maxItems: 1
>> +    description: |
>> +      This interrupt is used to report a message from the host.
> 
> These could be just two lines:
> 
> items:
>    - description: Interrupt used to report a message from the host.
> 
> (and note that just like we do not use "This" in commit msg, there is
> really no benefit of using it in hardware descruption for simple
> statements)
> 

Appreciate your help very much!! Will fix the formatting.

> Regardless:
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> 
> Best regards,
> Krzysztof
> 

-- 
Thank you,
Roman



From krzk at kernel.org  Mon Mar 17 10:08:40 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 18:08:40 +0100
Subject: [PATCH RFC v2 3/3] dt-bindings: mailbox: mtk,vcp-mbox: add mtk
 vcp-mbox document
In-Reply-To: <df592920-cdf3-40fe-8357-2fbdfc0afd78@kernel.org>
References: <20250317083822.891-1-jjian.zhou@mediatek.com>
 <20250317083822.891-4-jjian.zhou@mediatek.com>
 <df592920-cdf3-40fe-8357-2fbdfc0afd78@kernel.org>
Message-ID: <e5d2f827-9edb-4d0b-952d-24eadf8dfeb7@kernel.org>

On 17/03/2025 10:00, Krzysztof Kozlowski wrote:
> On 17/03/2025 09:38, Jjian Zhou wrote:
>> This patch adds document for mediatek vcp mbox.
>>
>> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
>> ---
>>  .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49 +++++++++++++++++++
> 
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
> 
>>  1 file changed, 49 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
> 
> Filename based on compatible. You already got this comment. Copy paste
> your filename here:
> 
> <here goes filename>
> 
> and here your compatible:
> 
> <here goes compatible>
> 
> Are the the same?

Can you do this exercise here, instead of sending next versions?

Best regards,
Krzysztof


From romank at linux.microsoft.com  Mon Mar 17 10:11:32 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 17 Mar 2025 10:11:32 -0700
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and use
 API for detecting hypervisor presence
In-Reply-To: <Z9gHmkNOsd29viHj@J2N7QTR9R3.cambridge.arm.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-2-romank@linux.microsoft.com>
 <Z9gHmkNOsd29viHj@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <d168a483-b425-4c18-ad71-eb39a0aba06c@linux.microsoft.com>



On 3/17/2025 4:29 AM, Mark Rutland wrote:
> On Fri, Mar 14, 2025 at 05:19:21PM -0700, Roman Kisel wrote:

[...]

>> +}
> 
> This use of a statement expression is bizarre, and the function would be
> clearer without it, e.g.

I'll change that to what you're suggesting, thanks for your help!

> 
> | bool arm_smccc_hyp_present(const uuid_t *hyp_uuid)
> | {
> | 	struct arm_smccc_res res = {};
> | 	uuid_t uuid;
> |
> | 	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
> | 		return false;
> |
> | 	arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
> | 	if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> | 		return false;
> | 	
> | 	uuid_t = SMCCC_RES_TO_UUID(res.a0, res.a1, res.a2, res.a3);
> | 	return uuid_equal(&uuid, hyp_uuid);
> | }
> 
> As noted below, I'd prefer if this were renamed to something like
> arm_smccc_hypervisor_has_uuid(), to more clearly indicate what is being
> checked.
> 
> [...]

Will update, thanks for your help!

> 
>> +/**
>> + * arm_smccc_hyp_present(const uuid_t *hyp_uuid)
>> + *
>> + * Returns `true` if the hypervisor advertises its presence via SMCCC.
>> + *
>> + * When the function returns `false`, the caller shall not assume that
>> + * there is no hypervisor running. Instead, the caller must fall back to
>> + * other approaches if any are available.
>> + */
>> +bool arm_smccc_hyp_present(const uuid_t *hyp_uuid);
> 
> I'd prefer if this were:
> 
> | /*
> |  * Returns whether a specific hypervisor UUID is advertised for the
> |  * Vendor Specific Hypervisor Service range.
> |  */
> | bool arm_smccc_hypervisor_has_uuid(const uuid_t *uuid);
> 
[...]



> 
> I think this'd be clearer if we did something similar to what we did for
> the SMCCC SOC_ID name:
> 
>    https://lore.kernel.org/linux-arm-kernel/20250219005932.3466-1-paul at os.amperecomputing.com/
> 
> ... and pack/unpack the bytes explicitly, e.g.

That looks great, thanks for the suggestion!

> 
> | static inline uuid smccc_res_to_uuid(u32 r0, u32, r1, u32 r2, u32 r3)
> | {
> | 	uuid_t uuid = {
> | 		.b = {
> | 			[0]  = (r0 >> 0)  & 0xff,
> | 			[1]  = (r0 >> 8)  & 0xff,
> | 			[2]  = (r0 >> 16) & 0xff,
> | 			[3]  = (r0 >> 24) & 0xff,
> |
> | 			[4]  = (r1 >> 0)  & 0xff,
> | 			[5]  = (r1 >> 8)  & 0xff,
> | 			[6]  = (r1 >> 16) & 0xff,
> | 			[7]  = (r1 >> 24) & 0xff,
> |
> | 			[8]  = (r2 >> 0)  & 0xff,
> | 			[9]  = (r2 >> 8)  & 0xff,
> | 			[10] = (r2 >> 16) & 0xff,
> | 			[11] = (r2 >> 24) & 0xff,
> |
> | 			[12] = (r3 >> 0)  & 0xff,
> | 			[13] = (r3 >> 8)  & 0xff,
> | 			[14] = (r3 >> 16) & 0xff,
> | 			[15] = (r3 >> 24) & 0xff,
> | 		},
> | 	};
> |
> | 	return uuid;
> | }
> 
> ... which is a bit more verbose, but clearly aligns with what the SMCCC
> spec says w.r.t. packing/unpacking, and should avoid warnings about
> endianness conversions.
> 

I believe what you're proposing hits a better trade-off, thanks again!

>> +
>> +#define UUID_TO_SMCCC_RES(uuid_init, regs) do { \
>> +		const uuid_t uuid = uuid_init; \
>> +		(regs)[0] = le32_to_cpu((u32)uuid.b[0] | (uuid.b[1] << 8) | \
>> +						((uuid.b[2]) << 16) | ((uuid.b[3]) << 24)); \
>> +		(regs)[1] = le32_to_cpu((u32)uuid.b[4] | (uuid.b[5] << 8) | \
>> +						((uuid.b[6]) << 16) | ((uuid.b[7]) << 24)); \
>> +		(regs)[2] = le32_to_cpu((u32)uuid.b[8] | (uuid.b[9] << 8) | \
>> +						((uuid.b[10]) << 16) | ((uuid.b[11]) << 24)); \
>> +		(regs)[3] = le32_to_cpu((u32)uuid.b[12] | (uuid.b[13] << 8) | \
>> +						((uuid.b[14]) << 16) | ((uuid.b[15]) << 24)); \
>> +	} while (0)
>> +
>> +#endif /* !__ASSEMBLER__ */
> 
> IMO it'd be clearer to initialise a uuid_t beforehand, and then allow
> the helper to unpack the bytes, e.g.
> 
> static inline u32 smccc_uuid_to_reg(const uuid_t uuid, int reg)
> {
> 	u32 val = 0;
> 
> 	val |= (u32)(uuid.b[4 * reg + 0] << 0)
> 	val |= (u32)(uuid.b[4 * reg + 1] << 8)
> 	val |= (u32)(uuid.b[4 * reg + 2] << 16)
> 	val |= (u32)(uuid.b[4 * reg + 3] << 24)
> 
> 	return val:
> }
> 
> #define UUID_TO_SMCCC_RES(uuid, regs)		\
> do {						\
> 	(regs)[0] = smccc_uuid_to_reg(uuid, 0); \
> 	(regs)[1] = smccc_uuid_to_reg(uuid, 1); \
> 	(regs)[2] = smccc_uuid_to_reg(uuid, 2); \
> 	(regs)[3] = smccc_uuid_to_reg(uuid, 3); \
> } while (0)
> 
> ... though arguably at that point you can get rid of the
> UUID_TO_SMCCC_RES() macro and just expand that directly at the callsite.
> 

I'll work on that, thanks!!

> Mark.

-- 
Thank you,
Roman



From romank at linux.microsoft.com  Mon Mar 17 10:12:53 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 17 Mar 2025 10:12:53 -0700
Subject: [PATCH hyperv-next v6 02/11] arm64: hyperv: Use SMCCC to detect
 hypervisor presence
In-Reply-To: <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-3-romank@linux.microsoft.com>
 <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <c0f51574-d31f-47e0-a4c0-6e6d0fbe1804@linux.microsoft.com>



On 3/17/2025 4:37 AM, Mark Rutland wrote:
> On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote:

[...]

> The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use
> prior to the ifdeffery looks misplaced.
> 
> Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED().
> Otherwise, use a stub, e.g.
> 

That looks much better, thanks for the review! Will implement in
the next version.

> | #ifdef CONFIG_ACPI
> | static bool __init hyperv_detect_via_acpi(void)
> | {
> | 	if (acpi_disabled)
> | 		return false;
> | 	
> | 	if (acpi_gbl_FADT.header.revision < 6)
> | 		return false;
> | 	
> | 	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
> | }
> | #else
> | static inline bool hyperv_detect_via_acpi(void) { return false; }
> | #endif
> 
> Mark.
> 
>> +static bool __init hyperv_detect_via_smccc(void)
>> +{
>> +	uuid_t hyperv_uuid = UUID_INIT(
>> +		0x4d32ba58, 0x4764, 0xcd24,
>> +		0x75, 0x6c, 0xef, 0x8e,
>> +		0x24, 0x70, 0x59, 0x16);
>> +
>> +	return arm_smccc_hyp_present(&hyperv_uuid);
>> +}
>> +
>>   static int __init hyperv_init(void)
>>   {
>>   	struct hv_get_vp_registers_output	result;
>> @@ -35,13 +70,11 @@ static int __init hyperv_init(void)
>>   
>>   	/*
>>   	 * Allow for a kernel built with CONFIG_HYPERV to be running in
>> -	 * a non-Hyper-V environment, including on DT instead of ACPI.
>> +	 * a non-Hyper-V environment.
>> +	 *
>>   	 * In such cases, do nothing and return success.
>>   	 */
>> -	if (acpi_disabled)
>> -		return 0;
>> -
>> -	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
>> +	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
>>   		return 0;
>>   
>>   	/* Setup the guest ID */
>> -- 
>> 2.43.0
>>

-- 
Thank you,
Roman



From krzk at kernel.org  Mon Mar 17 10:15:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 18:15:37 +0100
Subject: [PATCH RFC v3 1/3] mailbox: mediatek: Add mtk-vcp-mailbox driver
In-Reply-To: <20250317110331.2776-2-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
 <20250317110331.2776-2-jjian.zhou@mediatek.com>
Message-ID: <ade7ab48-c4f1-4ac0-ab1b-997e95b9c689@kernel.org>

On 17/03/2025 12:03, Jjian Zhou wrote:
> +
> +	ret = devm_request_threaded_irq(dev, irq, NULL,
> +					mtk_vcp_mbox_irq_thread, IRQF_ONESHOT,
> +					dev_name(dev), mbox->chans);
> +	if (ret < 0)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	dev_dbg(dev, "MTK VCP mailbox initialized\n");

Drop



Best regards,
Krzysztof


From krzk at kernel.org  Mon Mar 17 10:16:09 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 18:16:09 +0100
Subject: [PATCH RFC v3 2/3] firmware: mediatek: Add vcp ipc protocol
 interface
In-Reply-To: <20250317110331.2776-3-jjian.zhou@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
 <20250317110331.2776-3-jjian.zhou@mediatek.com>
Message-ID: <d3f8fbe3-c061-4d34-a5a3-09cbf676bc4c@kernel.org>

On 17/03/2025 12:03, Jjian Zhou wrote:
> Some of mediatek processors contain the Risc-V coprocessor.
> 
> The communication between Host CPU and vcp firmware is
> taking place using a shared memory area for message passing.
> 
> VCP IPC protocol offers (send/recv) interfaces using
> mediatek-mailbox APIs.
> 
> Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> ---
>  drivers/firmware/Kconfig                      |   9 +
>  drivers/firmware/Makefile                     |   1 +
>  drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
>  include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
>  4 files changed, 642 insertions(+)
>  create mode 100644 drivers/firmware/mtk-vcp-ipc.c
>  create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h

Do not send new versions while previous discussion is still going.

You still did not respond to previous feedback and you already sent two
versions repeating the same mistake.

> 
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index 37e43f287e78..98c4ff667836 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -179,6 +179,15 @@ config MTK_ADSP_IPC
>  	  ADSP exists on some mtk processors.
>  	  Client might use shared memory to exchange information with ADSP.
>  

..

> +
> +/*
> + * mtk_vcp_ipc_send - send ipc command to MTK VCP
> + *
> + * @ipidev: VCP struct mtk_ipi_device handle
> + * @id: id of the feature IPI
> + * @data: message address
> + * @len: message length
> + *
> + * Return: Zero for success from mbox_send_message
> + *         negative value for error
> + */
> +int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 id, void *data, u32 len)
> +{
> +	struct device *dev;
> +	struct mtk_mbox_info *minfo;
> +	struct mtk_ipi_chan_table *table;
> +	struct mtk_vcp_ipc *vcp_ipc;
> +	int ret;
> +
> +	if (!ipidev || !ipidev->ipi_inited || !data)
> +		return IPI_UNAVAILABLE;
> +	vcp_ipc = ipidev->vcp_ipc;
> +	if (!vcp_ipc)
> +		return IPI_UNAVAILABLE;
> +
> +	table = ipidev->table;
> +	dev = ipidev->vcp_ipc->dev;
> +	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
> +	if (!minfo) {
> +		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
> +		return IPI_UNAVAILABLE;
> +	}
> +
> +	if (len > table[id].msg_size)
> +		return IPI_MSG_TOO_BIG;
> +	else if (!len)
> +		len = table[id].msg_size;
> +
> +	mutex_lock(&table[id].mutex_send);
> +
> +	minfo->ipi_info.msg = data;
> +	minfo->ipi_info.len = len;
> +	minfo->ipi_info.id = id;
> +	minfo->ipi_info.index = table[id].send_index;
> +	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
> +
> +	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
> +	mutex_unlock(&table[id].mutex_send);
> +	if (ret < 0) {
> +		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
> +		return IPI_MBOX_ERR;
> +	}
> +
> +	return IPI_ACTION_DONE;
> +}
> +EXPORT_SYMBOL(mtk_vcp_ipc_send);

Drop export - no users

Anyway, every export must be GPL.

> +
> +/*
> + * mtk_vcp_ipc_send_compl - send ipc command to MTK VCP
> + *
> + * @ipidev: VCP struct mtk_ipi_device handle
> + * @id: id of the feature IPI
> + * @data: message address
> + * @len: message length
> + * @timeout_ms:
> + *
> + * Return: Zero for success from mbox_send_message
> + *         negative value for error
> + */
> +int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 id,
> +			   void *data, u32 len, u32 timeout_ms)
> +{
> +	struct device *dev;
> +	struct mtk_mbox_info *minfo;
> +	struct mtk_ipi_chan_table *table;
> +	struct mtk_vcp_ipc *vcp_ipc;
> +	int ret;
> +
> +	if (!ipidev || !ipidev->ipi_inited || !data)
> +		return IPI_UNAVAILABLE;
> +	vcp_ipc = ipidev->vcp_ipc;
> +	if (!vcp_ipc)
> +		return IPI_UNAVAILABLE;
> +
> +	table = ipidev->table;
> +	dev = ipidev->vcp_ipc->dev;
> +	minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
> +	if (!minfo) {
> +		dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev->name, id);
> +		return IPI_UNAVAILABLE;
> +	}
> +
> +	if (len > table[id].msg_size)
> +		return IPI_MSG_TOO_BIG;
> +	else if (!len)
> +		len = table[id].msg_size;
> +
> +	mutex_lock(&table[id].mutex_send);
> +
> +	minfo->ipi_info.msg = data;
> +	minfo->ipi_info.len = len;
> +	minfo->ipi_info.id = id;
> +	minfo->ipi_info.index = table[id].send_index;
> +	minfo->ipi_info.slot_ofs = table[id].send_ofs * MBOX_SLOT_SIZE;
> +
> +	atomic_inc(&table[id].holder);
> +
> +	ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
> +	if (ret < 0) {
> +		atomic_set(&table[id].holder, 0);
> +		mutex_unlock(&table[id].mutex_send);
> +		dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, id);
> +		return IPI_MBOX_ERR;
> +	}
> +
> +	/* wait for completion */
> +	ret = wait_for_completion_timeout(&table[id].notify,
> +					  msecs_to_jiffies(timeout_ms));
> +	atomic_set(&table[id].holder, 0);
> +	if (ret > 0)
> +		ret = IPI_ACTION_DONE;
> +
> +	mutex_unlock(&table[id].mutex_send);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(mtk_vcp_ipc_send_compl);

NAK, no users.

> +
> +int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int id,
> +			      mbox_pin_cb_t cb, void *prdata, void *msg)
> +{
> +	if (!ipidev || !ipidev->ipi_inited)
> +		return IPI_DEV_ILLEGAL;
> +	if (!msg)
> +		return IPI_NO_MSGBUF;
> +
> +	if (ipidev->table[id].pin_buf)
> +		return IPI_ALREADY_USED;
> +	ipidev->table[id].mbox_pin_cb = cb;
> +	ipidev->table[id].pin_buf = msg;
> +	ipidev->table[id].prdata = prdata;
> +
> +	return IPI_ACTION_DONE;
> +}
> +EXPORT_SYMBOL(mtk_vcp_mbox_ipc_register);

NAK, no users.


> +
> +int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int id)
> +{
> +	if (!ipidev || !ipidev->ipi_inited)
> +		return IPI_DEV_ILLEGAL;
> +
> +	/* Drop the ipi and reset the record */
> +	complete(&ipidev->table[id].notify);
> +
> +	ipidev->table[id].mbox_pin_cb = NULL;
> +	ipidev->table[id].pin_buf = NULL;
> +	ipidev->table[id].prdata = NULL;
> +
> +	return IPI_ACTION_DONE;
> +}
> +EXPORT_SYMBOL(mtk_vcp_mbox_ipc_unregister);

NAK, no users.


> +
> +static void mtk_fill_in_entry(struct mtk_ipi_chan_table *entry, const u32 ipi_id,
> +			      const struct mtk_mbox_table *mbdev)
> +{
> +	const struct mtk_mbox_send_table *mbox_send = mbdev->send_table;
> +	u32 index;
> +
> +	for (index = 0; index < mbdev->send_count; index++) {
> +		if (ipi_id != mbox_send[index].ipi_id)
> +			continue;
> +
> +		entry->send_ofs = mbox_send[index].offset;
> +		entry->send_index = mbox_send[index].pin_index;
> +		entry->msg_size = mbox_send[index].msg_size;
> +		entry->mbox = mbox_send[index].mbox_id;
> +		return;
> +	}
> +
> +	entry->mbox = -ENOENT;
> +}
> +
> +int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
> +				u32 ipi_chan_count, struct mtk_vcp_ipc *vcp_ipc)
> +{
> +	struct mtk_ipi_chan_table *ipi_chan_table;
> +	struct mtk_mbox_table *mbdev;
> +	u32 index;
> +
> +	if (!vcp_ipc || !ipidev)
> +		return -EINVAL;
> +
> +	ipi_chan_table = kcalloc(ipi_chan_count,
> +				 sizeof(struct mtk_ipi_chan_table), GFP_KERNEL);
> +	if (!ipi_chan_table)
> +		return -ENOMEM;
> +
> +	mbdev = vcp_ipc->mbdev;
> +	vcp_ipc->ipi_priv = (void *)ipidev;
> +	ipidev->table = ipi_chan_table;
> +	ipidev->vcp_ipc = vcp_ipc;
> +
> +	for (index = 0; index < ipi_chan_count; index++) {
> +		atomic_set(&ipi_chan_table[index].holder, 0);
> +		mutex_init(&ipi_chan_table[index].mutex_send);
> +		init_completion(&ipi_chan_table[index].notify);
> +		mtk_fill_in_entry(&ipi_chan_table[index], index, mbdev);
> +	}
> +
> +	ipidev->ipi_inited = 1;
> +
> +	dev_dbg(vcp_ipc->dev, "%s (with %d IPI) has registered.\n",
> +		ipidev->name, ipi_chan_count);
> +
> +	return IPI_ACTION_DONE;
> +}
> +EXPORT_SYMBOL(mtk_vcp_ipc_device_register);

NAK, no users.


> +
> +static int setup_mbox_table(struct mtk_mbox_table *mbdev, u32 mbox)
> +{
> +	struct mtk_mbox_send_table *mbox_send = &mbdev->send_table[0];
> +	struct mtk_mbox_recv_table *mbox_recv = &mbdev->recv_table[0];
> +	u32 i, last_ofs = 0, last_idx = 0, last_slot = 0, last_sz = 0;
> +
> +	for (i = 0; i < mbdev->send_count; i++) {
> +		if (mbox == mbox_send[i].mbox_id) {
> +			mbox_send[i].offset = last_ofs + last_slot;
> +			mbox_send[i].pin_index = last_idx + last_sz;
> +			last_idx = mbox_send[i].pin_index;
> +			last_sz = DIV_ROUND_UP(mbox_send[i].msg_size, MBOX_SLOT_ALIGN);
> +			last_ofs = last_sz * MBOX_SLOT_ALIGN;
> +			last_slot = last_idx * MBOX_SLOT_ALIGN;
> +		} else if (mbox < mbox_send[i].mbox_id) {
> +			/* no need to search the rest id */
> +			break;
> +		}
> +	}
> +
> +	for (i = 0; i < mbdev->recv_count; i++) {
> +		if (mbox == mbox_recv[i].mbox_id) {
> +			mbox_recv[i].offset = last_ofs + last_slot;
> +			mbox_recv[i].pin_index = last_idx + last_sz;
> +			last_idx = mbox_recv[i].pin_index;
> +			last_sz = DIV_ROUND_UP(mbox_recv[i].msg_size, MBOX_SLOT_ALIGN);
> +			last_ofs = last_sz * MBOX_SLOT_ALIGN;
> +			last_slot = last_idx * MBOX_SLOT_ALIGN;
> +		} else if (mbox < mbox_recv[i].mbox_id) {
> +			/* no need to search the rest id */
> +			break;
> +		}
> +	}
> +
> +	if (last_idx > MBOX_MAX_PIN || (last_ofs + last_slot) > MAX_SLOT_NUM)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int mtk_vcp_ipc_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_vcp_ipc *vcp_ipc;
> +	struct mbox_client *cl;
> +	struct mtk_mbox_info *minfo;
> +	int ret;
> +	u32 mbox, i;
> +	struct mtk_mbox_table *mbox_data = dev_get_platdata(dev);
> +
> +	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
> +
> +	vcp_ipc = devm_kzalloc(dev, sizeof(*vcp_ipc), GFP_KERNEL);
> +	if (!vcp_ipc)
> +		return -ENOMEM;
> +
> +	if (!mbox_data) {

Check goes immediately after declaration. I doubt it is useful in the
first place as this cannot even happen...


> +		dev_err(dev, "No platform data available\n");

No, drop. Cannot happen or fix your drivers. Who provides the platdata here?

> +		return -EINVAL;
> +	}
> +	vcp_ipc->mbdev = mbox_data;
> +
> +	/* alloc and init mmup_mbox_info */
> +	vcp_ipc->info_table = vzalloc(sizeof(*vcp_ipc->info_table) * VCP_MBOX_NUM);
> +	if (!vcp_ipc->info_table)
> +		return -ENOMEM;
> +
> +	/* create mbox dev */
> +	for (mbox = 0; mbox < VCP_MBOX_NUM; mbox++) {
> +		minfo = &vcp_ipc->info_table[mbox];
> +		minfo->mbox_id = mbox;
> +		minfo->vcp_ipc = vcp_ipc;
> +		spin_lock_init(&minfo->mbox_lock);
> +
> +		ret = setup_mbox_table(vcp_ipc->mbdev, mbox);
> +		if (ret)
> +			return ret;
> +
> +		cl = &minfo->cl;
> +		cl->dev = &pdev->dev;
> +		cl->tx_block = false;
> +		cl->knows_txdone = false;
> +		cl->tx_prepare = NULL;
> +		cl->rx_callback = mtk_vcp_ipc_recv;
> +		minfo->ch = mbox_request_channel_byname(cl, mbox_names[mbox]);
> +		if (IS_ERR(minfo->ch)) {
> +			ret = PTR_ERR(minfo->ch);
> +			if (ret != -EPROBE_DEFER)
> +				dev_err(dev, "Failed to request mbox channel %s ret %d\n",
> +					mbox_names[mbox], ret);

Do not open code dev_err_probe.

> +
> +			for (i = 0; i < mbox; i++) {
> +				minfo = &vcp_ipc->info_table[i];
> +				mbox_free_channel(minfo->ch);
> +			}
> +
> +			vfree(vcp_ipc->info_table);
> +			return ret;
> +		}
> +	}
> +
> +	vcp_ipc->dev = dev;
> +	dev_set_drvdata(dev, vcp_ipc);
> +	dev_dbg(dev, "MTK VCP IPC initialized\n");

No, drop


Best regards,
Krzysztof


From horms at kernel.org  Mon Mar 17 10:25:09 2025
From: horms at kernel.org (Simon Horman)
Date: Mon, 17 Mar 2025 17:25:09 +0000
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for
 return value in intel_tsn_lane_is_available()
In-Reply-To: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
References: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
Message-ID: <20250317172509.GH688833@kernel.org>

On Mon, Mar 10, 2025 at 01:08:35PM +0800, Choong Yong Liang wrote:
> Fix the warning "warn: missing error code? 'ret'" in the
> intel_tsn_lane_is_available() function.
> 
> The function now returns 0 to indicate that a TSN lane was found and
> returns -EINVAL when it is not found.
> 
> Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the interface mode")
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>

Reviewed-by: Simon Horman <horms at kernel.org>



From romank at linux.microsoft.com  Mon Mar 17 10:28:38 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Mon, 17 Mar 2025 10:28:38 -0700
Subject: [PATCH hyperv-next v6 01/11] arm64: kvm, smccc: Introduce and use
 API for detecting hypervisor presence
In-Reply-To: <50ec2615-97cf-423d-bfe6-f65092a14348@app.fastmail.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-2-romank@linux.microsoft.com>
 <96bc4caf-b79a-4111-bafa-a7662260f4be@linux.microsoft.com>
 <50ec2615-97cf-423d-bfe6-f65092a14348@app.fastmail.com>
Message-ID: <238beef1-16d3-4c72-ac7f-7d578ab8fc3d@linux.microsoft.com>



On 3/15/2025 6:12 AM, Arnd Bergmann wrote:
> On Sat, Mar 15, 2025, at 01:27, Roman Kisel wrote:
>> On 3/14/2025 5:19 PM, Roman Kisel wrote:
>>
>> While the change is Acked, here is the caveat maybe.
>>
>> This patch produces warnings wtih sparse and CHECK_ENDING.
>> That said, the kernel build produces a whole lot more other warnings
>> from building with sparse by itself and/or with CHECK_ENDING.
>>
>> I am not sure how to proceed with that, thinking I should
>> not add warnings yet at the same time there are many others.
>> Not certain if folks take these signals as fyi or blockers.
> 
> It would be best not to add warnigns. There is slow progress on
> fixing all the endianess warnings and I hope this can eventually
> complete, so even if there are many existing ones please try to
> keep new code clean.
> 

Will fix the warnings, appreciate providing the guidance!

>       Arnd

-- 
Thank you,
Roman



From helgaas at kernel.org  Mon Mar 17 10:30:08 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 17 Mar 2025 12:30:08 -0500
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250313060521.kjue4la47xd7g4te@thinkpad>
Message-ID: <20250317173008.GA933389@bhelgaas>

On Thu, Mar 13, 2025 at 11:35:21AM +0530, Manivannan Sadhasivam wrote:
> On Wed, Mar 05, 2025 at 11:20:21AM -0500, Frank Li wrote:
> > This patches basic on
> > https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/
> > 
> > I have not hardware to test.
> > 
> > Look for driver owner, who help test this and start move forward to remove
> > cpu_addr_fixup() work.
> 
> If you remove cpu_addr_fixup() callback, it will break backwards
> compatibility with old DTs.

Do you have any pointers to DTs that will be broken?  Or to commits
where they were fixed?

> You should fix the existing DTs and continue carrying the callback
> for a while.

Any insight into where these existing DTs are used and how long
they're likely to live?

Bjorn


From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:37 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:37 +0200
Subject: [PATCH 2/9] dt-bindings: display/msm: describe SFPB device
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-2-655c52e2ad97@oss.qualcomm.com>

Add DT schema for the MultiMedia SubSystem System FPB device, which
provides several registers to control interface between multimedia
devices (primarily display) and system busses.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 .../devicetree/bindings/display/msm/qcom,sfpb.yaml | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7ca105c97edd2f305527c58ae89b9b0cf22d3c8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sfpb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MultiMedia SubSystem System FPB
+
+maintainers:
+  - Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
+  - Rob Clark <robdclark at gmail.com>
+
+description:
+  The SFPB provides several registers controlling the multimedia attachment to
+  the system busses.
+
+properties:
+  compatible:
+    items:
+      - const: qcom,apq8064-mmss-sfpb
+      - const: syscon
+
+  reg:
+    items:
+      - description: SFPB register block
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    syscon at 5700000 {
+        compatible = "qcom,apq8064-mmss-sfpb", "syscon";
+        reg = <0x5700000 0x70>;
+    };
+...

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:36 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:36 +0200
Subject: [PATCH 1/9] dt-bindings: soc: qcom,rpm: add missing
 clock-controller node
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-1-655c52e2ad97@oss.qualcomm.com>

On Qualcomm platforms in addition to regulators the RPM also provides
clocks via the child clock-controller node. Describe it properly in the
schema.

Fixes: 6b42133d2189 ("dt-bindings: soc: qcom: convert non-smd RPM bindings to dt-schema")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
index b00be9e01206d1c61802dee9f9ec777c4b946b7b..10956240df0856a4241d6032d3aff7d447af9ce6 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
@@ -46,6 +46,14 @@ properties:
     description:
       Three entries specifying the outgoing ipc bit used for signaling the RPM.
 
+  clock-controller:
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        contains:
+          const: qcom,rpmcc
+
 patternProperties:
   "^regulators(-[01])?$":
     type: object

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:38 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:38 +0200
Subject: [PATCH 3/9] dt-bindings: soc: qcom: add Smart Peripheral System
 Interrupt Controller
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-3-655c52e2ad97@oss.qualcomm.com>

Add schema to properly describe the SPS SIC block present on APQ8064 and
several similar platforms.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 .../devicetree/bindings/soc/qcom/qcom,sps-sic.yaml | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,sps-sic.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,sps-sic.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ccacf6f45955177dd9302107e09897bfa2f1fd78
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,sps-sic.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/qcom/qcom,sps-sic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Smart Peripheral System Interrupt Controller
+
+maintainers:
+  - Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
+  - Bjorn Andersson <andersson at kernel.org>
+
+description:
+  Smart Peripheral System (SPS) Interrupt Controller (SIC)
+
+properties:
+  compatible:
+    items:
+      - const: qcom,apq8064-sps-sic
+      - const: syscon
+
+  reg:
+    items:
+      - description: SPS SIC register block
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    interrupt-controller at 12100000 {
+        compatible = "qcom,apq8064-sps-sic", "syscon";
+        reg = <0x12100000 0x10000>;
+    };
+...

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:39 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:39 +0200
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>

As most other CoreSight devices the replicator can use either of the
optional clocks (or both). Document those optional clocks in the schema.

Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
--- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
@@ -30,6 +30,16 @@ properties:
   power-domains:
     maxItems: 1
 
+  clocks:
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    minItems: 1
+    enum:
+      - apb_pclk
+      - atclk
+
   in-ports:
     $ref: /schemas/graph.yaml#/properties/ports
     additionalProperties: false

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:40 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:40 +0200
Subject: [PATCH 5/9] ARM: dts: qcom-apq8064: add missing clocks to the
 timer node
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-5-655c52e2ad97@oss.qualcomm.com>

In order to fix DT schema warning and describe hardware properly, add
missing sleep clock to the timer node.

Fixes: f335b8af4fd5 ("ARM: dts: qcom: Add initial APQ8064 SoC and IFC6410 board device trees")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 5f1a6b4b764492486df1a2610979f56c0a37b64a..ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -326,6 +326,8 @@ timer at 200a000 {
 				     <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 			reg = <0x0200a000 0x100>;
 			clock-frequency = <27000000>;
+			clocks = <&sleep_clk>;
+			clock-names = "sleep";
 			cpu-offset = <0x80000>;
 		};
 

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:41 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:41 +0200
Subject: [PATCH 6/9] ARM: dts: qcom: apq8064 merge hw splinlock into
 corresponding syscon device
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-6-655c52e2ad97@oss.qualcomm.com>

Follow up the expected way of describing the SFPB hwspinlock and merge
hwspinlock node into corresponding syscon node, fixing several dt-schema
warnings.

Fixes: 24a9baf933dc ("ARM: dts: qcom: apq8064: Add hwmutex and SMEM nodes")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e..3728875a5506397b36a4c0d6a5ad12c067bbdd8c 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -213,12 +213,6 @@ sleep_clk: sleep_clk {
 		};
 	};
 
-	sfpb_mutex: hwmutex {
-		compatible = "qcom,sfpb-mutex";
-		syscon = <&sfpb_wrapper_mutex 0x604 0x4>;
-		#hwlock-cells = <1>;
-	};
-
 	smem {
 		compatible = "qcom,smem";
 		memory-region = <&smem_region>;
@@ -305,9 +299,10 @@ tlmm_pinmux: pinctrl at 800000 {
 			pinctrl-0 = <&ps_hold_default_state>;
 		};
 
-		sfpb_wrapper_mutex: syscon at 1200000 {
-			compatible = "syscon";
+		sfpb_mutex: hwmutex at 1200000 {
+			compatible = "qcom,sfpb-mutex";
 			reg = <0x01200000 0x8000>;
+			#hwlock-cells = <1>;
 		};
 
 		intc: interrupt-controller at 2000000 {

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:42 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:42 +0200
Subject: [PATCH 7/9] ARM: dts: qcom: apq8064: use new compatible for SFPB
 device
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-7-655c52e2ad97@oss.qualcomm.com>

Use new SoC-specific compatible for the SFPB device node in addition to
the "syscon" compatible.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 3728875a5506397b36a4c0d6a5ad12c067bbdd8c..522387700fc8ce854c0995636998d2d4237e33df 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -1086,7 +1086,7 @@ opp-27000000 {
 		};
 
 		mmss_sfpb: syscon at 5700000 {
-			compatible = "syscon";
+			compatible = "qcom,apq8064-mmss-sfpb", "syscon";
 			reg = <0x5700000 0x70>;
 		};
 

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:43 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:43 +0200
Subject: [PATCH 8/9] ARM: dts: qcom: apq8064: use new compatible for SPS
 SIC device
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-8-655c52e2ad97@oss.qualcomm.com>

Use new SoC-specific compatible to the SPS SIC in addition to the
"syscon" compatible and rename the node to follow the purpose of it.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 522387700fc8ce854c0995636998d2d4237e33df..a106f9f984fcb51dea1fff1515e6f290b36ccf99 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -402,8 +402,8 @@ saw3_vreg: regulator {
 			};
 		};
 
-		sps_sic_non_secure: sps-sic-non-secure at 12100000 {
-			compatible = "syscon";
+		sps_sic_non_secure: interrupt-controller at 12100000 {
+			compatible = "qcom,apq8064-sps-sic", "syscon";
 			reg = <0x12100000 0x10000>;
 		};
 

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:44 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:44 +0200
Subject: [PATCH 9/9] ARM: dts: qcom: apq8064: move replicator out of soc
 node
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250317-fix-nexus-4-v1-9-655c52e2ad97@oss.qualcomm.com>

The CoreSight replicator device isn't a part of the system MMIO bus, as
such it should not be a part of the soc node. Follow the example of
other platforms and move it out of the soc bus to the top-level.

Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 66 ++++++++++++++++----------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index a106f9f984fcb51dea1fff1515e6f290b36ccf99..acd94f3ba0350c5dcdd8f80885ee643d8cbddac7 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -278,6 +278,39 @@ scm {
 		};
 	};
 
+	replicator {
+		compatible = "arm,coresight-static-replicator";
+
+		clocks = <&rpmcc RPM_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		out-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port at 0 {
+				reg = <0>;
+				replicator_out0: endpoint {
+					remote-endpoint = <&etb_in>;
+				};
+			};
+			port at 1 {
+				reg = <1>;
+				replicator_out1: endpoint {
+					remote-endpoint = <&tpiu_in>;
+				};
+			};
+		};
+
+		in-ports {
+			port {
+				replicator_in: endpoint {
+					remote-endpoint = <&funnel_out>;
+				};
+			};
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1529,39 +1562,6 @@ tpiu_in: endpoint {
 			};
 		};
 
-		replicator {
-			compatible = "arm,coresight-static-replicator";
-
-			clocks = <&rpmcc RPM_QDSS_CLK>;
-			clock-names = "apb_pclk";
-
-			out-ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				port at 0 {
-					reg = <0>;
-					replicator_out0: endpoint {
-						remote-endpoint = <&etb_in>;
-					};
-				};
-				port at 1 {
-					reg = <1>;
-					replicator_out1: endpoint {
-						remote-endpoint = <&tpiu_in>;
-					};
-				};
-			};
-
-			in-ports {
-				port {
-					replicator_in: endpoint {
-						remote-endpoint = <&funnel_out>;
-					};
-				};
-			};
-		};
-
 		funnel at 1a04000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x1a04000 0x1000>;

-- 
2.39.5



From leo.yan at arm.com  Mon Mar 17 10:45:18 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 17 Mar 2025 17:45:18 +0000
Subject: [PATCH 6/7] coresight: Remove inlines from static function
 definitions
In-Reply-To: <9d06b27a-c2ce-41b8-9657-151000c0b244@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-7-james.clark@linaro.org>
 <20250314095025.GW9682@e132581.arm.com>
 <9d06b27a-c2ce-41b8-9657-151000c0b244@linaro.org>
Message-ID: <20250317174518.GJ2487211@e132581.arm.com>

On Mon, Mar 17, 2025 at 03:26:42PM +0000, James Clark wrote:
> On 14/03/2025 9:50 am, Leo Yan wrote:
> > On Tue, Feb 11, 2025 at 10:39:42AM +0000, James Clark wrote:
> > > 
> > > These are all static and in one compilation unit so the inline has no
> > > effect on the binary.
> > 
> > I read the doc coding-style.rst, the section "15) The inline disease",
> > my understanding is though the inline is not encouraged, I prefer we can
> > follow up the rule:
> > 
> >    A reasonable rule of thumb is to not put inline at functions that have more
> >    than 3 lines of code in them. An exception to this rule are the cases where
> >    a parameter is known to be a compile time constant, and as a result of this
> >    constantness you *know* the compiler will be able to optimize most of your
> >    function away at compile time. For a good example of this later case, see
> >    the kmalloc() inline function.
> > 
> 
> Isn't this advice about whether to make an inline function in a header file
> or do definition + declaration?

Maybe it is not about where defines inline functions.  It is about
how these inline functions are invoked.  E.g., in a single C file, a
inline function can be invoked in multiple places, and it is possible
the incline function can optimized by compiler case by case.

To be honest, I don't really understand how compiler works :)

[...]

> I think it can be useful, I've used it a little bit. Might as well make it
> easier to use for someone if it exists.

Sure.  This patch is fine for me.  I verified this patch with default
kernel configuration (-O2, -g), it does works as expected (no code and
data section's size change between with and without this patch).

Thanks,
Leo


From yang at os.amperecomputing.com  Mon Mar 17 10:50:22 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Mon, 17 Mar 2025 10:50:22 -0700
Subject: [v3 PATCH 2/6] arm64: cpufeature: add AmpereOne to BBML2 allow
 list
In-Reply-To: <36c70203-5203-44a1-bc08-479334b730c7@arm.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-3-yang@os.amperecomputing.com>
 <36c70203-5203-44a1-bc08-479334b730c7@arm.com>
Message-ID: <242e70de-869f-4d00-ad5a-a8fe6721be1f@os.amperecomputing.com>



On 3/14/25 3:58 AM, Ryan Roberts wrote:
> On 04/03/2025 22:19, Yang Shi wrote:
>> AmpereOne supports BBML2 without conflict abort, add to the allow list.
>>
>> Signed-off-by: Yang Shi<yang at os.amperecomputing.com>
>> ---
>>   arch/arm64/kernel/cpufeature.c | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 7934c6dd493e..bf3df8407ca3 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -2192,6 +2192,8 @@ static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>>   	static const struct midr_range supports_bbml2_noabort_list[] = {
>>   		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
>>   		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
>> +		MIDR_ALL_VERSIONS(MIDR_AMPERE1),
>> +		MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
>>   		{}
>>   	};
>>   
> Miko's series will move back to additionally checking MMFR2.BBM, so you will
> need to add an erratum workaround for these CPUs to set MMFR2.BBM=2 in the
> per-cpu "sanitised" feature register. See:
>
> https://lore.kernel.org/linux-arm-kernel/86ecyzorb7.wl-maz at kernel.org/

Thank you. I will talk to our architect to see how we should handle 
this. This should not block the page table split work.

Yang

> Thanks,
> Ryan
>



From yang at os.amperecomputing.com  Mon Mar 17 10:53:09 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Mon, 17 Mar 2025 10:53:09 -0700
Subject: [v3 PATCH 3/6] arm64: mm: make __create_pgd_mapping() and helpers
 non-void
In-Reply-To: <172bf7a8-4533-4627-83d2-552e4681c360@arm.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-4-yang@os.amperecomputing.com>
 <172bf7a8-4533-4627-83d2-552e4681c360@arm.com>
Message-ID: <2b715836-b566-4a9e-b344-9401fa4c0feb@os.amperecomputing.com>



On 3/14/25 4:51 AM, Ryan Roberts wrote:
> On 04/03/2025 22:19, Yang Shi wrote:
>> The later patch will enhance __create_pgd_mapping() and related helpers
>> to split kernel linear mapping, it requires have return value.  So make
>> __create_pgd_mapping() and helpers non-void functions.
>>
>> And move the BUG_ON() out of page table alloc helper since failing
>> splitting kernel linear mapping is not fatal and can be handled by the
>> callers in the later patch.  Have BUG_ON() after
>> __create_pgd_mapping_locked() returns to keep the current callers behavior
>> intact.
>>
>> Suggested-by: Ryan Roberts<ryan.roberts at arm.com>
>> Signed-off-by: Yang Shi<yang at os.amperecomputing.com>
>> ---
>>   arch/arm64/mm/mmu.c | 127 ++++++++++++++++++++++++++++++--------------
>>   1 file changed, 86 insertions(+), 41 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index b4df5bc5b1b8..dccf0877285b 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -189,11 +189,11 @@ static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
>>   	} while (ptep++, addr += PAGE_SIZE, addr != end);
>>   }
>>   
>> -static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>> -				unsigned long end, phys_addr_t phys,
>> -				pgprot_t prot,
>> -				phys_addr_t (*pgtable_alloc)(int),
>> -				int flags)
>> +static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>> +			       unsigned long end, phys_addr_t phys,
>> +			       pgprot_t prot,
>> +			       phys_addr_t (*pgtable_alloc)(int),
>> +			       int flags)
>>   {
>>   	unsigned long next;
>>   	pmd_t pmd = READ_ONCE(*pmdp);
>> @@ -208,6 +208,8 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>>   			pmdval |= PMD_TABLE_PXN;
>>   		BUG_ON(!pgtable_alloc);
>>   		pte_phys = pgtable_alloc(PAGE_SHIFT);
>> +		if (!pte_phys)
>> +			return -ENOMEM;
> nit: personally I'd prefer to see a "goto out" and funnel all to a single return
> statement. You do that in some functions (via loop break), but would be cleaner
> if consistent.
>
> If pgtable_alloc() is modified to return int (see my comment at the bottom),
> this becomes:
>
> ret = pgtable_alloc(PAGE_SHIFT, &pte_phys);
> if (ret)
> 	goto out;

OK

>>   		ptep = pte_set_fixmap(pte_phys);
>>   		init_clear_pgtable(ptep);
>>   		ptep += pte_index(addr);
>> @@ -239,13 +241,16 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
>>   	 * walker.
>>   	 */
>>   	pte_clear_fixmap();
>> +
>> +	return 0;
>>   }
>>   
>> -static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>> -		     phys_addr_t phys, pgprot_t prot,
>> -		     phys_addr_t (*pgtable_alloc)(int), int flags)
>> +static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>> +		    phys_addr_t phys, pgprot_t prot,
>> +		    phys_addr_t (*pgtable_alloc)(int), int flags)
>>   {
>>   	unsigned long next;
>> +	int ret = 0;
>>   
>>   	do {
>>   		pmd_t old_pmd = READ_ONCE(*pmdp);
>> @@ -264,22 +269,27 @@ static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>>   			BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd),
>>   						      READ_ONCE(pmd_val(*pmdp))));
>>   		} else {
>> -			alloc_init_cont_pte(pmdp, addr, next, phys, prot,
>> +			ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot,
>>   					    pgtable_alloc, flags);
>> +			if (ret)
>> +				break;
>>   
>>   			BUG_ON(pmd_val(old_pmd) != 0 &&
>>   			       pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp)));
>>   		}
>>   		phys += next - addr;
>>   	} while (pmdp++, addr = next, addr != end);
>> +
>> +	return ret;
>>   }
>>   
>> -static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>> -				unsigned long end, phys_addr_t phys,
>> -				pgprot_t prot,
>> -				phys_addr_t (*pgtable_alloc)(int), int flags)
>> +static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>> +			       unsigned long end, phys_addr_t phys,
>> +			       pgprot_t prot,
>> +			       phys_addr_t (*pgtable_alloc)(int), int flags)
>>   {
>>   	unsigned long next;
>> +	int ret = 0;
>>   	pud_t pud = READ_ONCE(*pudp);
>>   	pmd_t *pmdp;
>>   
>> @@ -295,6 +305,8 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>>   			pudval |= PUD_TABLE_PXN;
>>   		BUG_ON(!pgtable_alloc);
>>   		pmd_phys = pgtable_alloc(PMD_SHIFT);
>> +		if (!pmd_phys)
>> +			return -ENOMEM;
>>   		pmdp = pmd_set_fixmap(pmd_phys);
>>   		init_clear_pgtable(pmdp);
>>   		pmdp += pmd_index(addr);
>> @@ -314,21 +326,26 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>>   		    (flags & NO_CONT_MAPPINGS) == 0)
>>   			__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>>   
>> -		init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
>> +		ret = init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags);
>> +		if (ret)
>> +			break;
>>   
>>   		pmdp += pmd_index(next) - pmd_index(addr);
>>   		phys += next - addr;
>>   	} while (addr = next, addr != end);
>>   
>>   	pmd_clear_fixmap();
>> +
>> +	return ret;
>>   }
>>   
>> -static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>> -			   phys_addr_t phys, pgprot_t prot,
>> -			   phys_addr_t (*pgtable_alloc)(int),
>> -			   int flags)
>> +static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>> +			  phys_addr_t phys, pgprot_t prot,
>> +			  phys_addr_t (*pgtable_alloc)(int),
>> +			  int flags)
>>   {
>>   	unsigned long next;
>> +	int ret = 0;
>>   	p4d_t p4d = READ_ONCE(*p4dp);
>>   	pud_t *pudp;
>>   
>> @@ -340,6 +357,8 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   			p4dval |= P4D_TABLE_PXN;
>>   		BUG_ON(!pgtable_alloc);
>>   		pud_phys = pgtable_alloc(PUD_SHIFT);
>> +		if (!pud_phys)
>> +			return -ENOMEM;
>>   		pudp = pud_set_fixmap(pud_phys);
>>   		init_clear_pgtable(pudp);
>>   		pudp += pud_index(addr);
>> @@ -369,8 +388,10 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   			BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
>>   						      READ_ONCE(pud_val(*pudp))));
>>   		} else {
>> -			alloc_init_cont_pmd(pudp, addr, next, phys, prot,
>> +			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
>>   					    pgtable_alloc, flags);
>> +			if (ret)
>> +				break;
>>   
>>   			BUG_ON(pud_val(old_pud) != 0 &&
>>   			       pud_val(old_pud) != READ_ONCE(pud_val(*pudp)));
>> @@ -379,14 +400,17 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   	} while (pudp++, addr = next, addr != end);
>>   
>>   	pud_clear_fixmap();
>> +
>> +	return ret;
>>   }
>>   
>> -static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>> -			   phys_addr_t phys, pgprot_t prot,
>> -			   phys_addr_t (*pgtable_alloc)(int),
>> -			   int flags)
>> +static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>> +			  phys_addr_t phys, pgprot_t prot,
>> +			  phys_addr_t (*pgtable_alloc)(int),
>> +			  int flags)
>>   {
>>   	unsigned long next;
>> +	int ret = 0;
>>   	pgd_t pgd = READ_ONCE(*pgdp);
>>   	p4d_t *p4dp;
>>   
>> @@ -398,6 +422,8 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   			pgdval |= PGD_TABLE_PXN;
>>   		BUG_ON(!pgtable_alloc);
>>   		p4d_phys = pgtable_alloc(P4D_SHIFT);
>> +		if (!p4d_phys)
>> +			return -ENOMEM;
>>   		p4dp = p4d_set_fixmap(p4d_phys);
>>   		init_clear_pgtable(p4dp);
>>   		p4dp += p4d_index(addr);
>> @@ -412,8 +438,10 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   
>>   		next = p4d_addr_end(addr, end);
>>   
>> -		alloc_init_pud(p4dp, addr, next, phys, prot,
>> +		ret = alloc_init_pud(p4dp, addr, next, phys, prot,
>>   			       pgtable_alloc, flags);
>> +		if (ret)
>> +			break;
>>   
>>   		BUG_ON(p4d_val(old_p4d) != 0 &&
>>   		       p4d_val(old_p4d) != READ_ONCE(p4d_val(*p4dp)));
>> @@ -422,23 +450,26 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   	} while (p4dp++, addr = next, addr != end);
>>   
>>   	p4d_clear_fixmap();
>> +
>> +	return ret;
>>   }
>>   
>> -static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
>> -					unsigned long virt, phys_addr_t size,
>> -					pgprot_t prot,
>> -					phys_addr_t (*pgtable_alloc)(int),
>> -					int flags)
>> +static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
>> +				       unsigned long virt, phys_addr_t size,
>> +				       pgprot_t prot,
>> +				       phys_addr_t (*pgtable_alloc)(int),
>> +				       int flags)
>>   {
>>   	unsigned long addr, end, next;
>>   	pgd_t *pgdp = pgd_offset_pgd(pgdir, virt);
>> +	int ret = 0;
>>   
>>   	/*
>>   	 * If the virtual and physical address don't have the same offset
>>   	 * within a page, we cannot map the region as the caller expects.
>>   	 */
>>   	if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
>> -		return;
>> +		return -EINVAL;
>>   
>>   	phys &= PAGE_MASK;
>>   	addr = virt & PAGE_MASK;
>> @@ -446,29 +477,38 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
>>   
>>   	do {
>>   		next = pgd_addr_end(addr, end);
>> -		alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
>> +		ret = alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc,
>>   			       flags);
>> +		if (ret)
>> +			break;
>>   		phys += next - addr;
>>   	} while (pgdp++, addr = next, addr != end);
>> +
>> +	return ret;
>>   }
>>   
>> -static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
>> -				 unsigned long virt, phys_addr_t size,
>> -				 pgprot_t prot,
>> -				 phys_addr_t (*pgtable_alloc)(int),
>> -				 int flags)
>> +static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
>> +				unsigned long virt, phys_addr_t size,
>> +				pgprot_t prot,
>> +				phys_addr_t (*pgtable_alloc)(int),
>> +				int flags)
>>   {
>> +	int ret;
>> +
>>   	mutex_lock(&fixmap_lock);
>> -	__create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
>> +	ret = __create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
>>   				    pgtable_alloc, flags);
>> +	BUG_ON(ret);
> This function now returns an error, but also BUGs on ret!=0. For this patch, I'd
> suggest keeping this function as void.

You mean __create_pgd_mapping(), right?

> But I believe there is a pre-existing bug in arch_add_memory(). That's called at
> runtime so if __create_pgd_mapping() fails and BUGs, it will take down a running
> system.

Yes, it is the current behavior.

> With this foundational patch, we can fix that with an additional patch to pass
> along the error code instead of BUGing in that case. arch_add_memory() would
> need to unwind whatever __create_pgd_mapping() managed to do before the memory
> allocation failure (presumably unmapping and freeing any allocated tables). I'm
> happy to do this as a follow up patch.

Yes, the allocated page tables need to be freed. Thank you for taking it.

>>   	mutex_unlock(&fixmap_lock);
>> +
>> +	return ret;
>>   }
>>   
>>   #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
>>   extern __alias(__create_pgd_mapping_locked)
>> -void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
>> -			     phys_addr_t size, pgprot_t prot,
>> -			     phys_addr_t (*pgtable_alloc)(int), int flags);
>> +int create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
>> +			    phys_addr_t size, pgprot_t prot,
>> +			    phys_addr_t (*pgtable_alloc)(int), int flags);
> create_kpti_ng_temp_pgd() now returns error instead of BUGing on allocation
> failure, but I don't see a change to handle that error. You'll want to update
> __kpti_install_ng_mappings() to BUG on error.

Yes, I missed that. It should BUG on error.

>>   #endif
>>   
>>   static phys_addr_t __pgd_pgtable_alloc(int shift)
>> @@ -476,13 +516,17 @@ static phys_addr_t __pgd_pgtable_alloc(int shift)
>>   	/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
>>   	void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL & ~__GFP_ZERO);
>>   
>> -	BUG_ON(!ptr);
>> +	if (!ptr)
>> +		return 0;
> 0 is a valid (though unlikely) physical address. I guess you could technically
> encode like ERR_PTR(), but since you are returning phys_addr_t and not a
> pointer, then perhaps it will be clearer to make this return int and accept a
> pointer to a phys_addr_t, which it will populate on success?

Actually I did something similar in the first place, but just returned 
the virt address. Then did something if it returns NULL. That made the 
code a little more messy since we need convert the virt address to phys 
address because __create_pgd_mapping() and the helpers require phys 
address, and changed the functions definition.

But I noticed 0 should be not a valid phys address if I remember 
correctly. I also noticed early_pgtable_alloc() calls 
memblock_phys_alloc_range(), it returns 0 on failure. If 0 is valid phys 
address, then it should not do that, right? And I also noticed the 
memblock range 0 - memstart_addr is actually removed from memblock (see 
arm64_memblock_init()), so IIUC 0 should be not valid phys address. So 
the patch ended up being as is.

If this assumption doesn't stand, I think your suggestion makes sense.

>> +
>>   	return __pa(ptr);
>>   }
>>   
>>   static phys_addr_t pgd_pgtable_alloc(int shift)
>>   {
>>   	phys_addr_t pa = __pgd_pgtable_alloc(shift);
>> +	if (!pa)
>> +		goto out;
> This would obviously need to be fixed up as per above.
>
>>   	struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa));
>>   
>>   	/*
>> @@ -498,6 +542,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
>>   	else if (shift == PMD_SHIFT)
>>   		BUG_ON(!pagetable_pmd_ctor(ptdesc));
>>   
>> +out:
>>   	return pa;
>>   }
>>   
> You have left early_pgtable_alloc() to panic() on allocation failure. Given we
> can now unwind the stack with error code, I think it would be more consistent to
> also allow early_pgtable_alloc() to return error.

The early_pgtable_alloc() is just used for painting linear mapping at 
early boot stage, if it fails I don't think unwinding the stack is 
feasible and worth it. Did I miss something?

Thanks,
Yang

> Thanks,
> Ryan
>



From yang at os.amperecomputing.com  Mon Mar 17 10:57:04 2025
From: yang at os.amperecomputing.com (Yang Shi)
Date: Mon, 17 Mar 2025 10:57:04 -0700
Subject: [v3 PATCH 4/6] arm64: mm: support large block mapping when
 rodata=full
In-Reply-To: <f745ab79-55e7-406a-a3cb-9f85fa461444@arm.com>
References: <20250304222018.615808-1-yang@os.amperecomputing.com>
 <20250304222018.615808-5-yang@os.amperecomputing.com>
 <f745ab79-55e7-406a-a3cb-9f85fa461444@arm.com>
Message-ID: <2745296a-9d39-4f77-8eb4-735920d35375@os.amperecomputing.com>



On 3/14/25 6:29 AM, Ryan Roberts wrote:
> On 04/03/2025 22:19, Yang Shi wrote:
>> When rodata=full is specified, kernel linear mapping has to be mapped at
>> PTE level since large page table can't be split due to break-before-make
>> rule on ARM64.
>>
>> This resulted in a couple of problems:
>>    - performance degradation
>>    - more TLB pressure
>>    - memory waste for kernel page table
>>
>> With FEAT_BBM level 2 support, splitting large block page table to
>> smaller ones doesn't need to make the page table entry invalid anymore.
>> This allows kernel split large block mapping on the fly.
>>
>> Add kernel page table split support and use large block mapping by
>> default when FEAT_BBM level 2 is supported for rodata=full.  When
>> changing permissions for kernel linear mapping, the page table will be
>> split to PTE level.
>>
>> The machine without FEAT_BBM level 2 will fallback to have kernel linear
>> mapping PTE-mapped when rodata=full.
>>
>> With this we saw significant performance boost with some benchmarks and
>> much less memory consumption on my AmpereOne machine (192 cores, 1P) with
>> 256GB memory.
>>
>> * Memory use after boot
>> Before:
>> MemTotal:       258988984 kB
>> MemFree:        254821700 kB
>>
>> After:
>> MemTotal:       259505132 kB
>> MemFree:        255410264 kB
>>
>> Around 500MB more memory are free to use.  The larger the machine, the
>> more memory saved.
>>
>> * Memcached
>> We saw performance degradation when running Memcached benchmark with
>> rodata=full vs rodata=on.  Our profiling pointed to kernel TLB pressure.
>> With this patchset we saw ops/sec is increased by around 3.5%, P99
>> latency is reduced by around 9.6%.
>> The gain mainly came from reduced kernel TLB misses.  The kernel TLB
>> MPKI is reduced by 28.5%.
>>
>> The benchmark data is now on par with rodata=on too.
>>
>> * Disk encryption (dm-crypt) benchmark
>> Ran fio benchmark with the below command on a 128G ramdisk (ext4) with disk
>> encryption (by dm-crypt).
>> fio --directory=/data --random_generator=lfsr --norandommap --randrepeat 1 \
>>      --status-interval=999 --rw=write --bs=4k --loops=1 --ioengine=sync \
>>      --iodepth=1 --numjobs=1 --fsync_on_close=1 --group_reporting --thread \
>>      --name=iops-test-job --eta-newline=1 --size 100G
>>
>> The IOPS is increased by 90% - 150% (the variance is high, but the worst
>> number of good case is around 90% more than the best number of bad case).
>> The bandwidth is increased and the avg clat is reduced proportionally.
>>
>> * Sequential file read
>> Read 100G file sequentially on XFS (xfs_io read with page cache populated).
>> The bandwidth is increased by 150%.
>>
>> Signed-off-by: Yang Shi<yang at os.amperecomputing.com>
>> ---
>>   arch/arm64/include/asm/cpufeature.h |  10 ++
>>   arch/arm64/include/asm/mmu.h        |   1 +
>>   arch/arm64/include/asm/pgtable.h    |   7 +-
>>   arch/arm64/kernel/cpufeature.c      |   2 +-
>>   arch/arm64/mm/mmu.c                 | 169 +++++++++++++++++++++++++++-
>>   arch/arm64/mm/pageattr.c            |  35 +++++-
>>   6 files changed, 211 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index 108ef3fbbc00..e24edc32b0bd 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -871,6 +871,16 @@ static inline bool system_supports_bbml2_noabort(void)
>>   	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
>>   }
>>   
>> +bool cpu_has_bbml2_noabort(unsigned int cpu_midr);
>> +/*
>> + * Called at early boot stage on boot CPU before cpu info and cpu feature
>> + * are ready.
>> + */
>> +static inline bool bbml2_noabort_available(void)
>> +{
>> +	return cpu_has_bbml2_noabort(read_cpuid_id());
> You'll want to incorporate the IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT) and
> arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2) checks from
> Miko's new series to avoid block mappings when BBML2 is disabled. (that second
> check will change a bit based on Maz's feedback against Miko's v3).

Sure

> Hopefully we can factor out into a common helper that is used by Miko's stuff too?

I think checking the kernel config and 
arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOBBML2) can be 
consolidated into a helper?

>> +}
>> +
>>   int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>>   bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>>   
>> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
>> index 662471cfc536..d658a33df266 100644
>> --- a/arch/arm64/include/asm/mmu.h
>> +++ b/arch/arm64/include/asm/mmu.h
>> @@ -71,6 +71,7 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
>>   			       pgprot_t prot, bool page_mappings_only);
>>   extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
>>   extern void mark_linear_text_alias_ro(void);
>> +extern int split_linear_mapping(unsigned long start, unsigned long end);
>>   
>>   /*
>>    * This check is triggered during the early boot before the cpufeature
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index 0b2a2ad1b9e8..ed2fc1dcf7ae 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -749,7 +749,7 @@ static inline bool in_swapper_pgdir(void *addr)
>>   	        ((unsigned long)swapper_pg_dir & PAGE_MASK);
>>   }
>>   
>> -static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
>> +static inline void __set_pmd_nosync(pmd_t *pmdp, pmd_t pmd)
>>   {
>>   #ifdef __PAGETABLE_PMD_FOLDED
>>   	if (in_swapper_pgdir(pmdp)) {
>> @@ -759,6 +759,11 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
>>   #endif /* __PAGETABLE_PMD_FOLDED */
>>   
>>   	WRITE_ONCE(*pmdp, pmd);
>> +}
>> +
>> +static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
>> +{
>> +	__set_pmd_nosync(pmdp, pmd);
>>   
>>   	if (pmd_valid(pmd)) {
>>   		dsb(ishst);
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index bf3df8407ca3..d39637d5aeab 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -2176,7 +2176,7 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>>   	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>>   }
>>   
>> -static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>> +bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>>   {
>>   	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
>>   	 * as possible. This list is therefore an allow-list of known-good
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index dccf0877285b..ad0f1cc55e3a 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -45,6 +45,7 @@
>>   #define NO_BLOCK_MAPPINGS	BIT(0)
>>   #define NO_CONT_MAPPINGS	BIT(1)
>>   #define NO_EXEC_MAPPINGS	BIT(2)	/* assumes FEAT_HPDS is not used */
>> +#define SPLIT_MAPPINGS		BIT(3)
>>   
>>   u64 kimage_voffset __ro_after_init;
>>   EXPORT_SYMBOL(kimage_voffset);
>> @@ -166,6 +167,73 @@ static void init_clear_pgtable(void *table)
>>   	dsb(ishst);
>>   }
>>   
>> +static int split_pmd(pmd_t *pmdp, pmd_t pmdval,
>> +		     phys_addr_t (*pgtable_alloc)(int))
>> +{
>> +	unsigned long pfn;
>> +	pgprot_t prot;
>> +	phys_addr_t pte_phys;
>> +	pte_t *ptep;
>> +
>> +	if (!pmd_leaf(pmdval))
>> +		return 0;
>> +
>> +	pfn = pmd_pfn(pmdval);
>> +	prot = pmd_pgprot(pmdval);
>> +
>> +	pte_phys = pgtable_alloc(PAGE_SHIFT);
>> +	if (!pte_phys)
>> +		return -ENOMEM;
>> +
>> +	ptep = (pte_t *)phys_to_virt(pte_phys);
>> +	init_clear_pgtable(ptep);
> No need for this, you're about to fill the table with ptes so clearing it is a
> waste of time.

OK

>> +	prot = __pgprot(pgprot_val(prot) | PTE_TYPE_PAGE);
> This happen to work for D64 pgtables because of the way the bits are arranged.
> But it won't work for D128 (when we get there). We are in the process of
> cleaning up the code base to make it D128 ready. So let's fix this now:
>
> 	prot = __pgprot(pgprot_val(prot) & ~PMD_TYPE_MASK) | PTE_TYPE_PAGE);
>
> nit: I'd move this up, next to the "prot = pmd_pgprot(pmdval);" line.

OK

>> +	for (int i = 0; i < PTRS_PER_PTE; i++, ptep++)
>> +		__set_pte_nosync(ptep, pfn_pte(pfn + i, prot));
> nit: you're incrementing ptep but adding i to pfn. Why not just increment pfn too?

Sure, pfn++ works too.

>> +
>> +	dsb(ishst);
>> +
>> +	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(pte_phys),
>> +		__pgprot(PMD_TYPE_TABLE)));
> You're missing some required pgprot flags and it would be better to follow what
> alloc_init_cont_pte() does in general. Something like:
>
> 	pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
> 	if (flags & NO_EXEC_MAPPINGS)
> 		pmdval |= PMD_TABLE_PXN;
> 	__pmd_populate(pmdp, pte_phys, pmdval);

Sure

>> +
>> +	return 0;
>> +}
>> +
>> +static int split_pud(pud_t *pudp, pud_t pudval,
>> +		     phys_addr_t (*pgtable_alloc)(int))
> All the same comments for split_pmd() apply here too.
>
>> +{
>> +	unsigned long pfn;
>> +	pgprot_t prot;
>> +	pmd_t *pmdp;
>> +	phys_addr_t pmd_phys;
>> +	unsigned int step;
>> +
>> +	if (!pud_leaf(pudval))
>> +		return 0;
>> +
>> +	pfn = pud_pfn(pudval);
>> +	prot = pud_pgprot(pudval);
>> +	step = PMD_SIZE >> PAGE_SHIFT;
>> +
>> +	pmd_phys = pgtable_alloc(PMD_SHIFT);
>> +	if (!pmd_phys)
>> +		return -ENOMEM;
>> +
>> +	pmdp = (pmd_t *)phys_to_virt(pmd_phys);
>> +	init_clear_pgtable(pmdp);
>> +	for (int i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
>> +		__set_pmd_nosync(pmdp, pfn_pmd(pfn, prot));
>> +		pfn += step;
>> +	}
>> +
>> +	dsb(ishst);
>> +
>> +	set_pud(pudp, pfn_pud(__phys_to_pfn(pmd_phys),
>> +		__pgprot(PUD_TYPE_TABLE)));
>> +
>> +	return 0;
>> +}
>> +
>>   static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
>>   		     phys_addr_t phys, pgprot_t prot)
>>   {
>> @@ -251,12 +319,21 @@ static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
>>   {
>>   	unsigned long next;
>>   	int ret = 0;
>> +	bool split = flags & SPLIT_MAPPINGS;
>>   
>>   	do {
>>   		pmd_t old_pmd = READ_ONCE(*pmdp);
>>   
>>   		next = pmd_addr_end(addr, end);
>>   
>> +		if (split) {
> I think this should be:
>
> 		if (flags & SPLIT_MAPPINGS &&
> 		    pmd_leaf(old_pmd) &&
> 		    next < addr + PMD_SIZE) {
>
> So we only attempt a split if its a leaf and the leaf is not fully contained by
> the range. Your current code is always splitting even if the block mapping is
> fully contained which seems a waste. And if the pmd is not a leaf (either not
> present or a table) split_pmd will currently do nothing and return 0, so there
> is no opportunity to install mappings or visit the ptes.

Yes, it splits the PMD even though the block mapping is fully contained. 
It is because the current user (change_memory_common()) just manipulates 
the page permission on PAGE_SIZE granularity IIRC. But I agree with you 
not splitting when it is fully contained is better and more flexible. We 
don't have to change the code if change_memory_common() is enhanced to 
handle contiguous pages. However the related code would be untested due 
to no usecase at the moment.

If the PMD is non-leaf it will do nothing because this patch doesn't 
handle CONT_PTE, if the PMD is table it means it already points to a PTE 
so we don't need do anything. The later patch handles CONT_PTE.

>> +			ret = split_pmd(pmdp, old_pmd, pgtable_alloc);
> But... do we need the special split_pmd() and split_pud() functions at all?
> Can't we just allocate a new table here, then let the existing code populate it,
> then replace the block mapping with the table mapping? Same goes for huge puds.
> If you take this approach, I think a lot of the code below will significantly
> simplify.

Actually I thought about this. The existing code populates page table in 
the range of size at addr, if the size is, for example, pud size, the 
existing code can populate the page table as you suggested. But as I 
mentioned above change_memory_common() is called on PAGE_SIZE 
granularity, If we just allocate a page table then let the existing code 
populate it, we will end up populating just one PMD and PTE entry for 
the specified address. For example, we a module is loaded, its text 
segment may just use one page, so kernel just need change the permission 
for that page.

So we still need populate other PMD entries and PTE entries other than 
the specified address. That would need the most code in split_pud() and 
split_pmd().

To make your suggestion work I think we can set addr and end used by the 
walker to the start boundary and end boundary of PUD (P4D doesn't 
support block mapping yet) respectively. For example:

@@ -441,8 +441,14 @@ static void __create_pgd_mapping_locked(pgd_t 
*pgdir, phys_addr_t phys,
 ??????????????? return;

 ??????? phys &= PAGE_MASK;
-?????? addr = virt & PAGE_MASK;
-?????? end = PAGE_ALIGN(virt + size);
+?????? if (split) {
+?????????????? addr = virt & PAGE_MASK;
+?????????????? end = PAGE_ALIGN(virt + size);
+?????? else {
+?????????????? addr = start_pud_boundary;
+?????????????? end = end_pud_boundary;
+?????????????? phys = __pa(start_boundary);
+?????? }

 ??????? do {
 ??????????????? next = pgd_addr_end(addr, end);

But we may need to add a dedicated parameter for the start boundary of 
page table if we want to do split and permission change in one pass as 
you suggested below since we need to know which PTE permission need to 
be changed. However this may make detecting fully contained range 
harder, the range passed in from caller needs to be preserved so that we 
can know what PUD or PMD permission need to be changed. CONT mappings 
will make it more complicated.

So it sounds like we need much more parameters. We may need put all the 
parameters into a struct, for example, something like below off the top 
of my head:

struct walk_param {
 ??? unsigned long start;
 ??? unsigned long end;
 ??? unsigned long addr;
 ??? unsigned long orig_start;
 ??? unsigned long orig_end;
 ??? pgprot_t clear_prot;
 ??? pgprot_t set_prot;
 ??? pgprot_t prot;
}

So I'm not sure whether the code can be significantly simplified or not.

>> +			if (ret)
>> +				break;
>> +
>> +			continue;
>> +		}
>> +
>>   		/* try section mapping first */
>>   		if (((addr | next | phys) & ~PMD_MASK) == 0 &&
>>   		    (flags & NO_BLOCK_MAPPINGS) == 0) {
> You'll want to modify this last bit to avoid setting up a block mapping if we
> are trying to split?
>
> 		    (flags & (NO_BLOCK_MAPPINGS | SPLIT_MAPPINGS) == 0) {

The specified address can't have block mapping, but the surrounding 
address can have. For example, when splitting a PUD, the PMD containing 
the specified address will be table, but all other 511 PMDs still can be 
block mappings.

> Or perhaps it's an error to call this without NO_BLOCK_MAPPINGS if
> SPLIT_MAPPINGS is specified? Or perhaps we don't even need SPLIT_MAPPINGS, and
> NO_BLOCK_MAPPINGS means we will split if we find any block mappings? (similarly
> for NO_CONT_MAPPINGS)?

As I said above we still can have block mappings, so using 
NO_BLOCK_MAPPINGS may cause some confusion?

>> @@ -292,11 +369,19 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>>   	int ret = 0;
>>   	pud_t pud = READ_ONCE(*pudp);
>>   	pmd_t *pmdp;
>> +	bool split = flags & SPLIT_MAPPINGS;
>>   
>>   	/*
>>   	 * Check for initial section mappings in the pgd/pud.
>>   	 */
>>   	BUG_ON(pud_sect(pud));
>> +
>> +	if (split) {
>> +		BUG_ON(pud_none(pud));
>> +		pmdp = pmd_offset(pudp, addr);
>> +		goto split_pgtable;
>> +	}
>> +
>>   	if (pud_none(pud)) {
>>   		pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
>>   		phys_addr_t pmd_phys;
>> @@ -316,6 +401,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>>   		pmdp = pmd_set_fixmap_offset(pudp, addr);
>>   	}
>>   
>> +split_pgtable:
>>   	do {
>>   		pgprot_t __prot = prot;
>>   
>> @@ -334,7 +420,8 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
>>   		phys += next - addr;
>>   	} while (addr = next, addr != end);
>>   
>> -	pmd_clear_fixmap();
>> +	if (!split)
>> +		pmd_clear_fixmap();
>>   
>>   	return ret;
>>   }
>> @@ -348,6 +435,13 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   	int ret = 0;
>>   	p4d_t p4d = READ_ONCE(*p4dp);
>>   	pud_t *pudp;
>> +	bool split = flags & SPLIT_MAPPINGS;
>> +
>> +	if (split) {
>> +		BUG_ON(p4d_none(p4d));
>> +		pudp = pud_offset(p4dp, addr);
>> +		goto split_pgtable;
>> +	}
>>   
>>   	if (p4d_none(p4d)) {
>>   		p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
>> @@ -368,11 +462,25 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   		pudp = pud_set_fixmap_offset(p4dp, addr);
>>   	}
>>   
>> +split_pgtable:
>>   	do {
>>   		pud_t old_pud = READ_ONCE(*pudp);
>>   
>>   		next = pud_addr_end(addr, end);
>>   
>> +		if (split) {
>> +			ret = split_pud(pudp, old_pud, pgtable_alloc);
>> +			if (ret)
>> +				break;
>> +
>> +			ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot,
>> +						  pgtable_alloc, flags);
>> +			if (ret)
>> +				break;
>> +
>> +			continue;
>> +		}
>> +
>>   		/*
>>   		 * For 4K granule only, attempt to put down a 1GB block
>>   		 */
>> @@ -399,7 +507,8 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
>>   		phys += next - addr;
>>   	} while (pudp++, addr = next, addr != end);
>>   
>> -	pud_clear_fixmap();
>> +	if (!split)
>> +		pud_clear_fixmap();
>>   
>>   	return ret;
>>   }
>> @@ -413,6 +522,13 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   	int ret = 0;
>>   	pgd_t pgd = READ_ONCE(*pgdp);
>>   	p4d_t *p4dp;
>> +	bool split = flags & SPLIT_MAPPINGS;
>> +
>> +	if (split) {
>> +		BUG_ON(pgd_none(pgd));
>> +		p4dp = p4d_offset(pgdp, addr);
>> +		goto split_pgtable;
>> +	}
>>   
>>   	if (pgd_none(pgd)) {
>>   		pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF;
>> @@ -433,6 +549,7 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   		p4dp = p4d_set_fixmap_offset(pgdp, addr);
>>   	}
>>   
>> +split_pgtable:
>>   	do {
>>   		p4d_t old_p4d = READ_ONCE(*p4dp);
>>   
>> @@ -449,7 +566,8 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
>>   		phys += next - addr;
>>   	} while (p4dp++, addr = next, addr != end);
>>   
>> -	p4d_clear_fixmap();
>> +	if (!split)
>> +		p4d_clear_fixmap();
>>   
>>   	return ret;
>>   }
>> @@ -546,6 +664,23 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
>>   	return pa;
>>   }
>>   
>> +int split_linear_mapping(unsigned long start, unsigned long end)
>> +{
>> +	int ret = 0;
>> +
>> +	if (!system_supports_bbml2_noabort())
>> +		return 0;
>> +
>> +	mmap_write_lock(&init_mm);
>> +	ret = __create_pgd_mapping_locked(init_mm.pgd, virt_to_phys((void *)start),
>> +					  start, (end - start), __pgprot(0),
>> +					  __pgd_pgtable_alloc, SPLIT_MAPPINGS);
>> +	mmap_write_unlock(&init_mm);
>> +	flush_tlb_kernel_range(start, end);
>> +
>> +	return ret;
>> +}
>> +
>>   /*
>>    * This function can only be used to modify existing table entries,
>>    * without allocating new levels of table. Note that this permits the
>> @@ -665,6 +800,24 @@ static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) {
>>   
>>   #endif /* CONFIG_KFENCE */
>>   
>> +static inline bool force_pte_mapping(void)
>> +{
>> +	/*
>> +	 * Can't use cpufeature API to determine whether BBML2 supported
>> +	 * or not since cpufeature have not been finalized yet.
>> +	 *
>> +	 * Checking the boot CPU only for now.  If the boot CPU has
>> +	 * BBML2, paint linear mapping with block mapping.  If it turns
>> +	 * out the secondary CPUs don't support BBML2 once cpufeature is
>> +	 * fininalized, the linear mapping will be repainted with PTE
>> +	 * mapping.
>> +	 */
>> +	return (rodata_full && !bbml2_noabort_available()) ||
>> +		debug_pagealloc_enabled() ||
>> +		arm64_kfence_can_set_direct_map() ||
>> +		is_realm_world();
>> +}
>> +
>>   static void __init map_mem(pgd_t *pgdp)
>>   {
>>   	static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN);
>> @@ -690,9 +843,12 @@ static void __init map_mem(pgd_t *pgdp)
>>   
>>   	early_kfence_pool = arm64_kfence_alloc_pool();
>>   
>> -	if (can_set_direct_map())
>> +	if (force_pte_mapping())
>>   		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>>   
>> +	if (rodata_full)
>> +		flags |= NO_CONT_MAPPINGS;
>> +
>>   	/*
>>   	 * Take care not to create a writable alias for the
>>   	 * read-only text and rodata sections of the kernel image.
>> @@ -1388,9 +1544,12 @@ int arch_add_memory(int nid, u64 start, u64 size,
>>   
>>   	VM_BUG_ON(!mhp_range_allowed(start, size, true));
>>   
>> -	if (can_set_direct_map())
>> +	if (force_pte_mapping())
>>   		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>>   
>> +	if (rodata_full)
>> +		flags |= NO_CONT_MAPPINGS;
>> +
>>   	__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
>>   			     size, params->pgprot, __pgd_pgtable_alloc,
>>   			     flags);
>> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
>> index 39fd1f7ff02a..5d42d87ea7e1 100644
>> --- a/arch/arm64/mm/pageattr.c
>> +++ b/arch/arm64/mm/pageattr.c
>> @@ -10,6 +10,7 @@
>>   #include <linux/vmalloc.h>
>>   
>>   #include <asm/cacheflush.h>
>> +#include <asm/mmu.h>
>>   #include <asm/pgtable-prot.h>
>>   #include <asm/set_memory.h>
>>   #include <asm/tlbflush.h>
>> @@ -80,8 +81,9 @@ static int change_memory_common(unsigned long addr, int numpages,
>>   	unsigned long start = addr;
>>   	unsigned long size = PAGE_SIZE * numpages;
>>   	unsigned long end = start + size;
>> +	unsigned long l_start;
>>   	struct vm_struct *area;
>> -	int i;
>> +	int i, ret;
>>   
>>   	if (!PAGE_ALIGNED(addr)) {
>>   		start &= PAGE_MASK;
>> @@ -118,7 +120,12 @@ static int change_memory_common(unsigned long addr, int numpages,
>>   	if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
>>   			    pgprot_val(clear_mask) == PTE_RDONLY)) {
>>   		for (i = 0; i < area->nr_pages; i++) {
>> -			__change_memory_common((u64)page_address(area->pages[i]),
>> +			l_start = (u64)page_address(area->pages[i]);
>> +			ret = split_linear_mapping(l_start, l_start + PAGE_SIZE);
> This isn't quite aligned with how I was thinking about it. You still have 2
> passes here; one to split the range to base pages, then another to modify the
> permissions.
>
> I was thinking we could use the table walker in mmu.c to achieve 2 benefits:
>
>    - Do both operations in a single pass (a bit like how calling
> update_mapping_prot() will update the protections on an existing mapping, and
> the table walker will split when it comes across a huge page)
>
>    - Only split when needed; if the whole huge page is contained within the
> range, then there is no need to split in the first place.
>
> We could then split vmalloc regions for free using this infrastructure too.
>
> Although there is a wrinkle that the mmu.c table walker only accepts a pgprot
> and can't currently handle a set_mask/clear_mask. I guess that could be added,
> but it starts to get a bit busy. I think this generic infra would be useful
> though. What do you think?

Yes, we need to add another pgprot parameter (maybe more) to tell the 
walker what is going to be set and what is going to be cleared. I agree 
the generic infra is useful. Would you prefer implement it in this 
patchset or in a separate following patchset?

Thanks,
Yang

> [...]
>
> Thanks,
> Ryan
>



From arnd at arndb.de  Mon Mar 17 10:57:57 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 17 Mar 2025 18:57:57 +0100
Subject: [GIT PULL] soc: fixes for 6.14, part 2
Message-ID: <860b2eaa-1aea-45e0-8bf5-3645b3840966@app.fastmail.com>

The following changes since commit 7eb172143d5508b4da468ed59ee857c6e5e01da6:

  Linux 6.14-rc5 (2025-03-02 11:48:20 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-fixes-6.14-2

for you to fetch changes up to 45d5fe1c53baaed1fb3043f45d1e15ebb4bbe86a:

  ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX (2025-03-14 18:24:05 +0100)

----------------------------------------------------------------
soc: fixes for 6.14, part 2

The majority of the last fixes are for devicetree files. This address two
important regressions for the Qualcomm SMMU and the Raspberry Pi 4 USB
controller, as well as a larger number of patches fixing minor mistakes
in board specific files for Rockchips, i.MX, starfive and broadcom.

The non-DT changes are

 - A fix for an old boot regression on Renesas shmobile chips

 - Another boot time regression for for the Qualcomm PDR SoC driver,
   among a few other Qualcomm firmware driver fixes for efivars
   and tzmem.

 - Minor Kconfig fixes for davinci and OMAP1

 - Minor code fixes for sparx5 reset controllers, OMAP memory controller,
   i.MX SCU, cpufreq and SoC drivers and a Hisilicon SoC driver.

 - One more update to the Asahi maintainers, adding Neal Gompa as a
   reviewer

----------------------------------------------------------------
Alexander Stein (1):
      arm64: dts: freescale: tqma8mpql: Fix vqmmc-supply

Arnd Bergmann (12):
      Merge tag 'arm-soc/for-6.14/devicetree-fixes' of https://github.com/Broadcom/stblinux into arm/fixes
      Merge tag 'arm-soc/for-6.14/devicetree-arm64-fixes' of https://github.com/Broadcom/stblinux into arm/fixes
      Merge tag 'imx-fixes-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/fixes
      Merge tag 'riscv-dt-fixes-for-v6.14-rc6' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux into arm/fixes
      ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP
      Merge tag 'arm-soc/for-6.14/devicetree-fixes-part2' of https://github.com/Broadcom/stblinux into arm/fixes
      Merge tag 'v6.14-rockchip-dtsfixes2' of https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into arm/fixes
      Merge tag 'asahi-soc-maintainers-6.14-fixes' of https://github.com/AsahiLinux/linux into arm/fixes
      Merge tag 'qcom-arm64-fixes-for-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes
      Merge tag 'qcom-drivers-fixes-for-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes
      Merge tag 'renesas-fixes-for-v6.14-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into arm/fixes
      Merge tag 'reset-fixes-for-v6.14' of git://git.pengutronix.de/pza/linux into arm/fixes

Chester A. Unal (2):
      ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC5300
      ARM: dts: BCM5301X: Fix switch port labels of ASUS RT-AC3200

Dan Carpenter (1):
      firmware: qcom: scm: Fix error code in probe()

David Lechner (1):
      ARM: davinci: da850: fix selecting ARCH_DAVINCI_DA8XX

Dragan Simic (2):
      arm64: dts: rockchip: Add avdd HDMI supplies to RockPro64 board dtsi
      arm64: dts: rockchip: Add missing PCIe supplies to RockPro64 board dtsi

E Shattow (1):
      riscv: dts: starfive: Fix a typo in StarFive JH7110 pin function definitions

Geert Uytterhoeven (1):
      ARM: shmobile: smp: Enforce shmobile_smp_* alignment

Hector Martin (1):
      MAINTAINERS: Add apple-spi driver & binding files

Heiko Stuebner (2):
      arm64: dts: rockchip: remove supports-cqe from rk3588 jaguar
      arm64: dts: rockchip: remove supports-cqe from rk3588 tiger

Horatiu Vultur (1):
      reset: mchp: sparx5: Fix for lan966x

Huisong Li (1):
      soc: hisilicon: kunpeng_hccs: Fix incorrect string assembly

Jianfeng Liu (1):
      arm64: dts: rockchip: slow down emmc freq for rock 5 itx

Joe Hattori (1):
      firmware: imx-scu: fix OF node leak in .probe()

Johan Hovold (1):
      firmware: qcom: uefisecapp: fix efivars registration race

Justin Klaassen (1):
      arm64: dts: rockchip: fix u2phy1_host status for NanoPi R4S

Konrad Dybcio (1):
      Revert "arm64: dts: qcom: sdm845: Affirm IDR0.CCTW on apps_smmu"

Krzysztof Kozlowski (1):
      soc: qcom: pmic_glink: Drop redundant pg assignment before taking lock

Neal Gompa (1):
      MAINTAINERS: Add myself (Neal Gompa) as a reviewer for ARM Apple support

Peng Fan (1):
      soc: imx8m: Unregister cpufreq and soc dev in cleanup path

Phil Elwell (3):
      ARM: dts: bcm2711: PL011 UARTs are actually r1p5
      arm64: dts: bcm2712: PL011 UARTs are actually r1p5
      ARM: dts: bcm2711: Don't mark timer regs unconfigured

Quentin Schulz (2):
      arm64: dts: rockchip: fix pinmux of UART0 for PX30 Ringneck on Haikou
      arm64: dts: rockchip: fix pinmux of UART5 for PX30 Ringneck on Haikou

Roger Quadros (1):
      memory: omap-gpmc: drop no compatible check

Saranya R (1):
      soc: qcom: pdr: Fix the potential deadlock

Stefan Eichenberger (3):
      ARM: dts: imx6qdl-apalis: Fix poweroff on Apalis iMX6
      arm64: dts: freescale: imx8mp-verdin-dahlia: add Microphone Jack to sound card
      arm64: dts: freescale: imx8mm-verdin-dahlia: add Microphone Jack to sound card

Stefan Wahren (1):
      ARM: dts: bcm2711: Fix xHCI power-domain

Yao Zi (1):
      arm64: dts: rockchip: Remove undocumented sdmmc property from lubancat-1

 MAINTAINERS                                        |  3 +++
 arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi        |  5 -----
 arch/arm/boot/dts/broadcom/bcm2711.dtsi            | 12 +++++-----
 .../boot/dts/broadcom/bcm4709-asus-rt-ac3200.dts   |  8 +++----
 .../boot/dts/broadcom/bcm47094-asus-rt-ac5300.dts  |  8 +++----
 arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi      | 10 ++++-----
 arch/arm/mach-davinci/Kconfig                      |  1 +
 arch/arm/mach-omap1/Kconfig                        |  1 +
 arch/arm/mach-shmobile/headsmp.S                   |  1 +
 arch/arm64/boot/dts/broadcom/bcm2712.dtsi          |  2 +-
 .../boot/dts/freescale/imx8mm-verdin-dahlia.dtsi   |  6 ++---
 .../arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi | 16 ++++---------
 .../boot/dts/freescale/imx8mp-verdin-dahlia.dtsi   |  6 ++---
 arch/arm64/boot/dts/qcom/sdm845.dtsi               |  1 -
 .../boot/dts/rockchip/px30-ringneck-haikou.dts     | 12 ++++++++++
 .../arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi |  2 +-
 arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 14 ++++++++++++
 arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts |  1 -
 arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts     |  1 -
 arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts |  3 +--
 arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi     |  1 -
 arch/riscv/boot/dts/starfive/jh7110-pinfunc.h      |  2 +-
 drivers/firmware/imx/imx-scu.c                     |  1 +
 drivers/firmware/qcom/qcom_qseecom_uefisecapp.c    | 18 +++++++--------
 drivers/firmware/qcom/qcom_scm.c                   |  4 ++--
 drivers/memory/omap-gpmc.c                         | 20 -----------------
 drivers/reset/reset-microchip-sparx5.c             | 19 +++++++++++-----
 drivers/soc/hisilicon/kunpeng_hccs.c               |  4 ++--
 drivers/soc/imx/soc-imx8m.c                        | 26 ++++++++++++++++++++--
 drivers/soc/qcom/pdr_interface.c                   |  8 +------
 drivers/soc/qcom/pmic_glink.c                      |  2 +-
 31 files changed, 119 insertions(+), 99 deletions(-)


From alb3rt0.m3rciai at gmail.com  Mon Mar 17 11:03:58 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Mon, 17 Mar 2025 19:03:58 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
 <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
Message-ID: <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>

On Mon, Mar 17, 2025 at 05:07:26PM +0100, Krzysztof Kozlowski wrote:
> On 17/03/2025 09:47, Alberto Merciai wrote:
> > While playing with linux-next and imx93-11x11-evk via NFS and TFTP
> > I found that the dwmac-imx, nvmem-imx-ocotp-ele drivers by default are
> > not builtin then the I was not able to reach userland. 
> > 
> > The following configs were needed to reach my goal:
> > CONFIG_DWMAC_IMX8=y
> > CONFIG_STMMAC_ETH=y
> > CONFIG_NVMEM_IMX_OCOTP_ELE=y
> > 
> > is that something expected?
> 
> You mean they are disabled or you just did not put them inside your
> initramfs?
> 
> Best regards,
> Krzysztof

Hello,

By default they are enabled as external modules, then until we don't
reach userland they are not loaded thus eth and all the mechanism behind
that are out.

I'm not using initramfs just tftp and NFS as follows:
setenv loaddtb "tftp 0x80400000 imx93-11x11-evk.dtb"
setenv loadkernel "tftp 0x83000000 Image"
setenv netargs "setenv bootargs console=ttyLP0,115200 root=/dev/nfs ip=dhcp nfsroot=192.168.1.3:/tftp/root,v3,tcp"
setenv bootcmd "run loaddtb; run loadkernel; run netargs; booti 0x83000000 - 0x80400000;"

Do you think that initramfs can solve that?

To be honest I was expecting to have a builtin driver for eth by
default, so that NFS and TFTP can be turned on without caring about the rest.
But for sure I'm missing something  there :)

Thanks,
Alberto


From leo.yan at arm.com  Mon Mar 17 11:09:45 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 17 Mar 2025 18:09:45 +0000
Subject: [PATCH 5/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <6be400e2-a464-4714-acf4-328dade883a9@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-6-james.clark@linaro.org>
 <20250313160409.GS9682@e132581.arm.com>
 <6be400e2-a464-4714-acf4-328dade883a9@linaro.org>
Message-ID: <20250317180945.GK2487211@e132581.arm.com>

On Mon, Mar 17, 2025 at 03:05:41PM +0000, James Clark wrote:

[...]

> > >   /*
> > > - * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
> > > + * Clear the claim tag for the device.
> > > + * Returns an error if the device wasn't already claimed.
> > > + */
> > > +int coresight_reset_claim(struct csdev_access *csa)
> > > +{
> > > +       int ret;
> > > +
> > > +       CS_UNLOCK(csa->base);
> > > +       ret = coresight_reset_claim_unlocked(csa);
> > > +       CS_LOCK(csa->base);
> > > +       return ret;
> > > +}
> > > +EXPORT_SYMBOL_GPL(coresight_reset_claim);
> > 
> > Maybe my question is overlapping with Mike's comment.
> > 
> > Callers never check the return values from coresight_reset_claim(). I am
> 
> I can remove the return value if it's confusing. The thought process was
> probably that it could be useful somewhere in the future, and
> coresight_reset_claim_unlocked() returns something anyway so might as well
> pass it up.
> 
> > wandering if coresight_reset_claim() can directly call
> > coresight_clear_self_claim_tag() for _trying_ to clear self-host tag in
> > probe phase. Any self claim tag issues will be deferred to detect until
> > enable the component.
> > 
> 
> Maybe, the spec does a read before setting which I assumed should be done
> for clearing as well.

If you mean PSCI doc, the flow for claiming tag is a handshake between
self-host software and external debugger, this is why a read is
required.

For a cleaning up, it is not about syncing with external debugger.  And
writing bit 0 to TRCCLAIMCLR will not impact external debugger.  So I
don't think a read prior to cleaning self claim tag is needed.

> As in to not touch anything if it's in use externally.
> It doesn't specifically describe any clearing sequence, but if we assume
> it's ok to blindly clear self hosted flag even when it's in use then yes we
> can directly call coresight_clear_self_claim_tag().

As a result, directly calling coresight_clear_self_claim_tag() works
for me.

Thanks,
Leo


From dmitry.baryshkov at oss.qualcomm.com  Mon Mar 17 10:44:35 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Mon, 17 Mar 2025 19:44:35 +0200
Subject: [PATCH 0/9] ARM: qcom: fix APQ8064 schema warnings
Message-ID: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>

Rob's bot has reported [1] several warnings for Nexus 4 submisson,
however none of those warnings are specific to that device. Fix all
those warnings for all APQ8064 platforms by extending existing schemas,
adding missing schemas and making APQ8064 DT follow all the schema
files.

[1]: https://lore.kernel.org/linux-arm-msm/174221818190.3957236.3364090534153729086.robh at kernel.org/

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
Dmitry Baryshkov (9):
      dt-bindings: soc: qcom,rpm: add missing clock-controller node
      dt-bindings: display/msm: describe SFPB device
      dt-bindings: soc: qcom: add Smart Peripheral System Interrupt Controller
      dt-bindings: arm: qcom,coresight-static-replicator: add optional clocks
      ARM: dts: qcom-apq8064: add missing clocks to the timer node
      ARM: dts: qcom: apq8064 merge hw splinlock into corresponding syscon device
      ARM: dts: qcom: apq8064: use new compatible for SFPB device
      ARM: dts: qcom: apq8064: use new compatible for SPS SIC device
      ARM: dts: qcom: apq8064: move replicator out of soc node

 .../arm/arm,coresight-static-replicator.yaml       | 10 +++
 .../devicetree/bindings/display/msm/qcom,sfpb.yaml | 39 ++++++++++
 .../devicetree/bindings/soc/qcom/qcom,rpm.yaml     |  8 ++
 .../devicetree/bindings/soc/qcom/qcom,sps-sic.yaml | 38 ++++++++++
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi           | 85 +++++++++++-----------
 5 files changed, 136 insertions(+), 44 deletions(-)
---
base-commit: 2bb3cf7805af73af62ebfcbb55e350549b6a0912
change-id: 20250317-fix-nexus-4-dd0fe3bca987

Best regards,
-- 
Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>



From krzysztof.kozlowski at linaro.org  Mon Mar 17 11:12:55 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 19:12:55 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
 <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
 <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>
Message-ID: <ef163f08-35f9-4d1d-8082-c826c6cd0aa0@linaro.org>

On 17/03/2025 19:03, Alberto Merciai wrote:
> On Mon, Mar 17, 2025 at 05:07:26PM +0100, Krzysztof Kozlowski wrote:
>> On 17/03/2025 09:47, Alberto Merciai wrote:
>>> While playing with linux-next and imx93-11x11-evk via NFS and TFTP
>>> I found that the dwmac-imx, nvmem-imx-ocotp-ele drivers by default are
>>> not builtin then the I was not able to reach userland. 
>>>
>>> The following configs were needed to reach my goal:
>>> CONFIG_DWMAC_IMX8=y
>>> CONFIG_STMMAC_ETH=y
>>> CONFIG_NVMEM_IMX_OCOTP_ELE=y
>>>
>>> is that something expected?
>>
>> You mean they are disabled or you just did not put them inside your
>> initramfs?
>>
>> Best regards,
>> Krzysztof
> 
> Hello,
> 
> By default they are enabled as external modules, then until we don't

So everything is as expected...

> reach userland they are not loaded thus eth and all the mechanism behind
> that are out.
> 
> I'm not using initramfs just tftp and NFS as follows:

All arm64 platforms are supposed to use initramfs on defconfig with
necessary modules.

> setenv loaddtb "tftp 0x80400000 imx93-11x11-evk.dtb"
> setenv loadkernel "tftp 0x83000000 Image"
> setenv netargs "setenv bootargs console=ttyLP0,115200 root=/dev/nfs ip=dhcp nfsroot=192.168.1.3:/tftp/root,v3,tcp"
> setenv bootcmd "run loaddtb; run loadkernel; run netargs; booti 0x83000000 - 0x80400000;"
> 
> Do you think that initramfs can solve that?

Yes, that's the entire point of initramfs.

> 
> To be honest I was expecting to have a builtin driver for eth by

No, why? We built as much as possible as modules in defconfig. Otherwise
it would be impossible to actually boot that image because several arm64
platforms have limitations of boot partition size.

Best regards,
Krzysztof


From robin.murphy at arm.com  Mon Mar 17 11:22:32 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 17 Mar 2025 18:22:32 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <cdc333e4-25bb-4171-9f6e-01f1de947db3@samsung.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
 <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
 <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
 <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
 <016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
 <b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>
 <cdc333e4-25bb-4171-9f6e-01f1de947db3@samsung.com>
Message-ID: <d6cd5e64-e2c0-4c6e-9c89-ce8b3e0a4a5b@arm.com>

On 17/03/2025 7:37 am, Marek Szyprowski wrote:
> On 13.03.2025 15:12, Robin Murphy wrote:
>> On 2025-03-13 1:06 pm, Robin Murphy wrote:
>>> On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
>>>> On 13.03.2025 12:01, Robin Murphy wrote:
>>>>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>>>>> [...]
>>>>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>>>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my
>>>>>> tests I
>>>>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>>>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>>>>> relevant kernel log:
>>>>>
>>>>> ...and the bug-flushing-out begins!
>>>>>
>>>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>>>> 00000000000003e8
>>>>>> Mem abort info:
>>>>>>  ?? ? ESR = 0x0000000096000004
>>>>>>  ?? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>>>>  ?? ? SET = 0, FnV = 0
>>>>>>  ?? ? EA = 0, S1PTW = 0
>>>>>>  ?? ? FSC = 0x04: level 0 translation fault
>>>>>> Data abort info:
>>>>>>  ?? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>>>>  ?? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>>>>  ?? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>>>> [00000000000003e8] user address but active_mm is swapper
>>>>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>>>>> Modules linked in:
>>>>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>>>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>>>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>>> pc : devm_kmalloc+0x2c/0x114
>>>>>> lr : rk_iommu_of_xlate+0x30/0x90
>>>>>> ...
>>>>>> Call trace:
>>>>>>  ?? ?devm_kmalloc+0x2c/0x114 (P)
>>>>>>  ?? ?rk_iommu_of_xlate+0x30/0x90
>>>>>
>>>>> Yeah, looks like this is doing something a bit questionable which
>>>>> can't
>>>>> work properly. TBH the whole dma_dev thing could probably be
>>>>> cleaned up
>>>>> now that we have proper instances, but for now does this work?
>>>>
>>>> Yes, this patch fixes the problem I've observed.
>>>>
>>>> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>
>>>> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver
>>>> and
>>>> I doubt it can be cleaned up.
>>>
>>> On the contrary I suspect they both can - it all dates back to when
>>> we had the single global platform bus iommu_ops and the SoC drivers
>>> were forced to bodge their own notion of multiple instances, but with
>>> the modern core code, ops are always called via a valid IOMMU
>>> instance or domain, so in principle it should always be possible to
>>> get at an appropriate IOMMU device now. IIRC it was mostly about
>>> allocating and DMA-mapping the pagetables in domain_alloc, where the
>>> private notion of instances didn't have enough information, but
>>> domain_alloc_paging solves that.
>>
>> Bah, in fact I think I am going to have to do that now, since although
>> it doesn't crash, rk_domain_alloc_paging() will also be failing for
>> the same reason. Time to find a PSU for the RK3399 board, I guess...
>>
>> (Or maybe just move the dma_dev assignment earlier to match Exynos?)
> 
> Well I just found that Exynos IOMMU is also broken on some on my test
> boards. It looks that the runtime pm links are somehow not correctly
> established. I will try to analyze this later in the afternoon.

Hmm, I tried to get an Odroid-XU3 up and running, but it seems unable to 
boot my original 6.14-rc3-based branch - even with the IOMMU driver 
disabled, it's consistently dying somewhere near (or just after) init 
with what looks like some catastrophic memory corruption issue - very 
occasionally it's managed to print the first line of various different 
panics.

Before that point though, with the IOMMU driver enabled it does appear 
to show signs of working OK:

[    0.649703] exynos-sysmmu 14650000.sysmmu: hardware version: 3.3
[    0.654220] platform 14450000.mixer: Adding to iommu group 1
...
[    2.680920] exynos-mixer 14450000.mixer: exynos_iommu_attach_device: 
Attached IOMMU with pgtable 0x42924000
...
[    5.196674] exynos-mixer 14450000.mixer: 
exynos_iommu_identity_attach: Restored IOMMU to IDENTITY from pgtable 
0x42924000
[    5.207091] exynos-mixer 14450000.mixer: exynos_iommu_attach_device: 
Attached IOMMU with pgtable 0x42884000


The multi-instance stuff in probe/release does look a bit suspect, 
however - seems like the second instance probe would overwrite the first 
instance's links, and then there would be a double-del() if the device 
were ever actually released again? I may have made that much more likely 
to happen, but I suspect it was already possible with async driver probe...

Thanks,
Robin.


From khilman at baylibre.com  Mon Mar 17 11:25:14 2025
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 17 Mar 2025 11:25:14 -0700
Subject: [GIT PULL] ARM: dts: misc. OMAP updates for v6.15
Message-ID: <7hiko7qzud.fsf@baylibre.com>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap.git tags/omap-for-v6.15/dt-signed

for you to fetch changes up to ea07a4775df03852c353514b5b7646a17bd425be:

  ARM: dts: omap4-panda-a4: Add missing model and compatible properties (2025-02-05 16:26:34 -0800)

----------------------------------------------------------------
ARM: dts: misc. OMAP updates for v6.15

----------------------------------------------------------------
Andreas Kemnade (1):
      ARM: dts: ti/omap: omap4-serial: fix interrupts syntax

Krzysztof Kozlowski (1):
      ARM: dts: ti: omap: Align GPIO hog name with bindings

Tom Rini (2):
      dt-bindings: omap: Add TI Pandaboard A4 variant
      ARM: dts: omap4-panda-a4: Add missing model and compatible properties

 Documentation/devicetree/bindings/arm/ti/omap.yaml        | 7 +++++++
 arch/arm/boot/dts/ti/omap/omap3-evm-processor-common.dtsi | 2 +-
 arch/arm/boot/dts/ti/omap/omap4-l4.dtsi                   | 8 ++++----
 arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts              | 5 +++++
 4 files changed, 17 insertions(+), 5 deletions(-)


From khilman at baylibre.com  Mon Mar 17 11:26:01 2025
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 17 Mar 2025 11:26:01 -0700
Subject: [GIT PULL] ARM: OMAP1: defconfig updates for v6.15
Message-ID: <7hcyefqzt2.fsf@baylibre.com>

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap.git tags/omap-for-v6.15/soc-signed

for you to fetch changes up to c2a5f8c4f28ffea8c93d10e509c5a6e61172cdca:

  ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP (2025-02-05 16:31:37 -0800)

----------------------------------------------------------------
ARM: OMAP1: defconfig updates for v6.15

----------------------------------------------------------------
Arnd Bergmann (1):
      ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP

 arch/arm/mach-omap1/Kconfig | 1 +
 1 file changed, 1 insertion(+)


From leo.yan at arm.com  Mon Mar 17 11:29:57 2025
From: leo.yan at arm.com (Leo Yan)
Date: Mon, 17 Mar 2025 18:29:57 +0000
Subject: [PATCH 2/7] coresight: Convert disclaim functions to take a
 struct cs_access
In-Reply-To: <c6a86373-64be-4101-a08a-74aa302bf64c@linaro.org>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-3-james.clark@linaro.org>
 <20250313145456.GR9682@e132581.arm.com>
 <c6a86373-64be-4101-a08a-74aa302bf64c@linaro.org>
Message-ID: <20250317182957.GL2487211@e132581.arm.com>

On Mon, Mar 17, 2025 at 11:36:40AM +0000, James Clark wrote:
> 
> 
> On 13/03/2025 2:54 pm, Leo Yan wrote:
> > On Tue, Feb 11, 2025 at 10:39:38AM +0000, James Clark wrote:
> > 
> > [...]
> > 
> > >   static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
> > >   {
> > > -       return coresight_read_claim_tags(csdev) != 0;
> > > +       return coresight_read_claim_tags(&csdev->access) != 0;
> > >   }
> > 
> > Likewise other claim functions, can coresight_is_claimed_any() change its
> > argument type from struct coresight_device to struct csdev_access?
> 
> I only wanted to change the ones that I had to. I think we should prioritize
> passing csdev as much as possible in the coresight framework to make
> everything consistent. Otherwise it's extra churn for no benefit, and if we
> need something from csdev here in the future we'll have to change this one
> back again.

The function coresight_is_claimed_any() has been deleted in a later
patch.  So this is fine for me.

In theory, claim tags are low level operations and don't need a
CoreSight device context, I prefer we can keep them as simple as
possible.

With this series, we can see coresight_claim_device() and
coresight_disclaim_device() are inconsistent for their parameters:
one is using "struct coresight_device *" and another is
"struct csdev_access *".  Maybe we just proceed to use csdev_access
for all claim tag functions?

If later we need to use a CoreSight device context when operating
claim tags, it means we might have different scenarios and we can
handle that separately.

Thanks,
Leo


From khilman at baylibre.com  Mon Mar 17 11:37:15 2025
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 17 Mar 2025 11:37:15 -0700
Subject: [GIT PULL] arm/omap: drivers: updates for v6.14
In-Reply-To: <7hcygyb3yi.fsf@baylibre.com>
References: <7hcygyb3yi.fsf@baylibre.com>
Message-ID: <CAOi56cVkwwsRQo-KQbME-Nmc2HemjmFEDn4_oaGcg9Te_MU_hg@mail.gmail.com>

Hi Arnd,

On Tue, Jan 7, 2025 at 3:26?PM Kevin Hilman <khilman at baylibre.com> wrote:
>
> The following changes since commit 40384c840ea1944d7c5a392e8975ed088ecf0b37:
>
>   Linux 6.13-rc1 (2024-12-01 14:28:56 -0800)
>
> are available in the Git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap.git tags/omap-for-v6.14/drivers-signed
>
> for you to fetch changes up to 6ef4ea3c944b9fc5d78317d1172cdcd10f9724f1:
>
>   Input: tsc2007 - accept standard properties (2024-12-10 16:17:30 -0800)
>
> ----------------------------------------------------------------
> arm/omap: drivers: updates for v6.14
>
> ----------------------------------------------------------------
> Andreas Kemnade (1):
>       Input: tsc2007 - accept standard properties
>
>  drivers/input/touchscreen/tsc2007.h      | 2 ++
>  drivers/input/touchscreen/tsc2007_core.c | 5 ++---
>  2 files changed, 4 insertions(+), 3 deletions(-)

It seems this PR was missed for v6.14.  Could you still take this one
for the v6.15 window?

Thanks,

Kevin


From manivannan.sadhasivam at linaro.org  Mon Mar 17 11:44:27 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 18 Mar 2025 00:14:27 +0530
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250317173008.GA933389@bhelgaas>
References: <20250313060521.kjue4la47xd7g4te@thinkpad>
 <20250317173008.GA933389@bhelgaas>
Message-ID: <20250317184427.7wkcr7jwu53r5jog@thinkpad>

On Mon, Mar 17, 2025 at 12:30:08PM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 11:35:21AM +0530, Manivannan Sadhasivam wrote:
> > On Wed, Mar 05, 2025 at 11:20:21AM -0500, Frank Li wrote:
> > > This patches basic on
> > > https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/
> > > 
> > > I have not hardware to test.
> > > 
> > > Look for driver owner, who help test this and start move forward to remove
> > > cpu_addr_fixup() work.
> > 
> > If you remove cpu_addr_fixup() callback, it will break backwards
> > compatibility with old DTs.
> 
> Do you have any pointers to DTs that will be broken?  Or to commits
> where they were fixed?
> 

Any patch that fixes issues in DT and then makes the required changes in the
driver without accounting for the old DTs will break backwards compatibility.

> > You should fix the existing DTs and continue carrying the callback
> > for a while.
> 
> Any insight into where these existing DTs are used and how long
> they're likely to live?
> 

There is no fixed rule in this afaik. Just like we continue to support old
hardwares, we need to continue supporting old DTs for some time. The best we can
do is provide some warning so that users can update their DTBs. Then we can get
rid of the old DT support in the driver after some time.

That's why I asked Frank to add the warning previously.

- Mani

-- 
????????? ????????


From nicolinc at nvidia.com  Mon Mar 17 11:49:14 2025
From: nicolinc at nvidia.com (Nicolin Chen)
Date: Mon, 17 Mar 2025 11:49:14 -0700
Subject: [PATCH v8 12/14] iommu/arm-smmu-v3: Introduce struct
 arm_smmu_vmaster
In-Reply-To: <20250317154423.GI9311@nvidia.com>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
 <20250311155714.GC5138@willie-the-truck>
 <Z9B2LMIi+88hlfza@Asurada-Nvidia>
 <20250317154423.GI9311@nvidia.com>
Message-ID: <Z9huquCf7YuzIjqx@Asurada-Nvidia>

On Mon, Mar 17, 2025 at 12:44:23PM -0300, Jason Gunthorpe wrote:
> On Tue, Mar 11, 2025 at 10:43:08AM -0700, Nicolin Chen wrote:
> > > > +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> > > > +				    struct arm_smmu_nested_domain *nested_domain)
> > > > +{
> > > > +	struct arm_smmu_vmaster *vmaster;
> > > > +	unsigned long vsid;
> > > > +	int ret;
> > > > +
> > > > +	iommu_group_mutex_assert(state->master->dev);
> > > > +
> > > > +	/* Skip invalid vSTE */
> > > > +	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> > > > +		return 0;
> > > 
> > > Ok, and we don't need to set 'state->vmaster' in this case because we
> > > only report stage-1 faults back to the vSMMU?
> > 
> > This is a good question that I didn't ask myself hard enough..
> > 
> > I think we should probably drop it. An invalid STE should trigger
> > a C_BAD_STE event that is in the supported vEVENT list. I'll run
> > some test before removing this line from v9.
> 
> It won't trigger C_BAD_STE, recall Robin was opposed to thatm so we have this:
> 
> static void arm_smmu_make_nested_domain_ste(
> 	struct arm_smmu_ste *target, struct arm_smmu_master *master,
> 	struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
> {
> 	unsigned int cfg =
> 		FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(nested_domain->ste[0]));
> 
> 	/*
> 	 * Userspace can request a non-valid STE through the nesting interface.
> 	 * We relay that into an abort physical STE with the intention that
> 	 * C_BAD_STE for this SID can be generated to userspace.
> 	 */
> 	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> 		cfg = STRTAB_STE_0_CFG_ABORT;
> 
> So, in the case of a non-valid STE, and a device access, the HW will
> generate one of the translation faults and that will be forwarded.
> 
> Some software component will have to transform those fault events into
> C_BAD_STE for the VM.

Hmm, double checked the spec. It does say that C_BAD_STE would be
triggered:

" V, bit [0] STE Valid.
  [...]
  Device transactions that select an STE with this field configured
  to 0 are terminated with an abort reported back to the device and
  a C_BAD_STE event is recorded."

I also did a hack test unsetting the V bit in the kernel. Then, the
HW did report C_BAD_STE (0x4) back to the VM (via vEVENTQ).

Thanks
Nicolin


From broonie at kernel.org  Mon Mar 17 11:46:58 2025
From: broonie at kernel.org (Mark Brown)
Date: Mon, 17 Mar 2025 18:46:58 +0000
Subject: [PATCH 0/3] Allow retrieving accessory detection reference on
 MT8188
In-Reply-To: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
References: <20250214-mt8188-accdet-v1-0-6bbd5483855b@collabora.com>
Message-ID: <174223721831.287878.9212541577191425735.b4-ty@kernel.org>

On Fri, 14 Feb 2025 12:14:28 -0300, N?colas F. R. A. Prado wrote:
> This series enables the MT8188-MT6359 sound driver to retrieve the
> MT6359 ACCDET sound component from a mediatek,accdet DT property, which
> allows detecting jack insertion/removal.
> 
> Patch 1 describes the new property in the binding. Patch 2 implements
> the sound component retrieval in the common MTK soundcard driver. Patch
> 3 updates the MT8188-MT6359 sound driver to register the audio jack and
> initialize the ACCDET driver for detection, if the property is present.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/3] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet
      commit: 3fec903f2cb18805b1ef22a0e310498020c1f15e
[2/3] ASoC: mediatek: common: Handle mediatek,accdet property
      commit: cf536e2622e2b0a60c99e799995b6e9acf539c17
[3/3] ASoC: mediatek: mt8188-mt6359: Add headset jack detect support
      (no commit info)

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From broonie at kernel.org  Mon Mar 17 11:47:01 2025
From: broonie at kernel.org (Mark Brown)
Date: Mon, 17 Mar 2025 18:47:01 +0000
Subject: [PATCH v3 0/4] Allow retrieving accessory detection reference
 on MT8188
In-Reply-To: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
References: <20250306-mt8188-accdet-v3-0-7828e835ff4b@collabora.com>
Message-ID: <174223722189.287878.14772373895585128225.b4-ty@kernel.org>

On Thu, 06 Mar 2025 16:52:14 -0300, N?colas F. R. A. Prado wrote:
> This series enables the MT8188-MT6359 sound driver to retrieve the
> MT6359 ACCDET sound component from a mediatek,accdet DT property, which
> allows detecting jack insertion/removal.
> 
> Patch 1 describes the new property in the binding. Patch 2 implements
> the sound component retrieval in the common MTK soundcard driver. Patch
> 4 updates the MT8188-MT6359 sound driver to register the audio jack and
> initialize the ACCDET driver for detection, if the property is present.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/4] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet
      commit: 3fec903f2cb18805b1ef22a0e310498020c1f15e
[2/4] ASoC: mediatek: common: Handle mediatek,accdet property
      commit: cf536e2622e2b0a60c99e799995b6e9acf539c17
[3/4] ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect
      commit: 0116a7d84b32537a10d9bea1fd1bfc06577ef527
[4/4] ASoC: mediatek: mt8188-mt6359: Add accdet headset jack detect support
      commit: f35d834d67adbbf121ee4397376d9eac21d99a85

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From jgg at nvidia.com  Mon Mar 17 11:49:30 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 17 Mar 2025 15:49:30 -0300
Subject: [PATCH v9 00/14] iommufd: Add vIOMMU infrastructure (Part-3:
 vEVENTQ)
In-Reply-To: <cover.1741719725.git.nicolinc@nvidia.com>
References: <cover.1741719725.git.nicolinc@nvidia.com>
Message-ID: <20250317184930.GQ9311@nvidia.com>

On Tue, Mar 11, 2025 at 12:44:18PM -0700, Nicolin Chen wrote:
> As the vIOMMU infrastructure series part-3, this introduces a new vEVENTQ
> object. The existing FAULT object provides a nice notification pathway to
> the user space with a queue already, so let vEVENTQ reuse that.
> 
> Mimicing the HWPT structure, add a common EVENTQ structure to support its
> derivatives: IOMMUFD_OBJ_FAULT (existing) and IOMMUFD_OBJ_VEVENTQ (new).
> 
> An IOMMUFD_CMD_VEVENTQ_ALLOC is introduced to allocate vEVENTQ object for
> vIOMMUs. One vIOMMU can have multiple vEVENTQs in different types but can
> not support multiple vEVENTQs in the same type.
> 
> The forwarding part is fairly simple but might need to replace a physical
> device ID with a virtual device ID in a driver-level event data structure.
> So, this also adds some helpers for drivers to use.
> 
> As usual, this series comes with the selftest coverage for this new ioctl
> and with a real world use case in the ARM SMMUv3 driver.

> Nicolin Chen (14):
>   iommufd/fault: Move two fault functions out of the header
>   iommufd/fault: Add an iommufd_fault_init() helper
>   iommufd: Abstract an iommufd_eventq from iommufd_fault
>   iommufd: Rename fault.c to eventq.c
>   iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC
>   iommufd/viommu: Add iommufd_viommu_get_vdev_id helper
>   iommufd/viommu: Add iommufd_viommu_report_event helper
>   iommufd/selftest: Require vdev_id when attaching to a nested domain
>   iommufd/selftest: Add IOMMU_TEST_OP_TRIGGER_VEVENT for vEVENTQ
>     coverage
>   iommufd/selftest: Add IOMMU_VEVENTQ_ALLOC test coverage
>   Documentation: userspace-api: iommufd: Update FAULT and VEVENTQ
>   iommu/arm-smmu-v3: Introduce struct arm_smmu_vmaster
>   iommu/arm-smmu-v3: Report events that belong to devices attached to
>     vIOMMU
>   iommu/arm-smmu-v3: Set MEV bit in nested STE for DoS mitigations

Applied, thanks

Jason


From florian.fainelli at broadcom.com  Mon Mar 17 11:50:31 2025
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 17 Mar 2025 11:50:31 -0700
Subject: [PATCH][next] PCI: brcmstb: make const read-only arrays static
In-Reply-To: <20250317143456.477901-1-colin.i.king@gmail.com>
References: <20250317143456.477901-1-colin.i.king@gmail.com>
Message-ID: <60ee6fd4-1cc6-4d77-8359-9215e1d604c3@broadcom.com>

On 3/17/25 07:34, Colin Ian King wrote:
> Don't populate the const read-only arrays data and regs on the stack at
> run time, instead make them static.
> 
> Signed-off-by: Colin Ian King <colin.i.king at gmail.com>

Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
-- 
Florian



From alb3rt0.m3rciai at gmail.com  Mon Mar 17 11:59:54 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Mon, 17 Mar 2025 19:59:54 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <ef163f08-35f9-4d1d-8082-c826c6cd0aa0@linaro.org>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
 <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
 <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>
 <ef163f08-35f9-4d1d-8082-c826c6cd0aa0@linaro.org>
Message-ID: <Z9hxKlrrqW4QyzdJ@alb3rt0-ThinkPad-P15-Gen-1>

On Mon, Mar 17, 2025 at 07:12:55PM +0100, Krzysztof Kozlowski wrote:
> On 17/03/2025 19:03, Alberto Merciai wrote:
> > On Mon, Mar 17, 2025 at 05:07:26PM +0100, Krzysztof Kozlowski wrote:
> >> On 17/03/2025 09:47, Alberto Merciai wrote:
> >>> While playing with linux-next and imx93-11x11-evk via NFS and TFTP
> >>> I found that the dwmac-imx, nvmem-imx-ocotp-ele drivers by default are
> >>> not builtin then the I was not able to reach userland. 
> >>>
> >>> The following configs were needed to reach my goal:
> >>> CONFIG_DWMAC_IMX8=y
> >>> CONFIG_STMMAC_ETH=y
> >>> CONFIG_NVMEM_IMX_OCOTP_ELE=y
> >>>
> >>> is that something expected?
> >>
> >> You mean they are disabled or you just did not put them inside your
> >> initramfs?
> >>
> >> Best regards,
> >> Krzysztof
> > 
> > Hello,
> > 
> > By default they are enabled as external modules, then until we don't
> 
> So everything is as expected...
> 
> > reach userland they are not loaded thus eth and all the mechanism behind
> > that are out.
> > 
> > I'm not using initramfs just tftp and NFS as follows:
> 
> All arm64 platforms are supposed to use initramfs on defconfig with
> necessary modules.
Thanks a lot, I was not aware of that.
Do you have any reference?

> > setenv loaddtb "tftp 0x80400000 imx93-11x11-evk.dtb"
> > setenv loadkernel "tftp 0x83000000 Image"
> > setenv netargs "setenv bootargs console=ttyLP0,115200 root=/dev/nfs ip=dhcp nfsroot=192.168.1.3:/tftp/root,v3,tcp"
> > setenv bootcmd "run loaddtb; run loadkernel; run netargs; booti 0x83000000 - 0x80400000;"
> > 
> > Do you think that initramfs can solve that?
> 
> Yes, that's the entire point of initramfs.
Let's proceed in that way :)

> > 
> > To be honest I was expecting to have a builtin driver for eth by
> 
> No, why? We built as much as possible as modules in defconfig. Otherwise
> it would be impossible to actually boot that image because several arm64
> platforms have limitations of boot partition size.
Cool! Now is clear.

> Best regards,
> Krzysztof

Thanks,
Alberto



From krzysztof.kozlowski at linaro.org  Mon Mar 17 12:14:30 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 17 Mar 2025 20:14:30 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <Z9hxKlrrqW4QyzdJ@alb3rt0-ThinkPad-P15-Gen-1>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
 <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
 <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>
 <ef163f08-35f9-4d1d-8082-c826c6cd0aa0@linaro.org>
 <Z9hxKlrrqW4QyzdJ@alb3rt0-ThinkPad-P15-Gen-1>
Message-ID: <88c66c98-7ea3-4172-9c99-405fe449cc5b@linaro.org>

On 17/03/2025 19:59, Alberto Merciai wrote:
>>>
>>> By default they are enabled as external modules, then until we don't
>>
>> So everything is as expected...
>>
>>> reach userland they are not loaded thus eth and all the mechanism behind
>>> that are out.
>>>
>>> I'm not using initramfs just tftp and NFS as follows:
>>
>> All arm64 platforms are supposed to use initramfs on defconfig with
>> necessary modules.
> Thanks a lot, I was not aware of that.
> Do you have any reference?
Reference for what? initramfs?

I am using meta-qcom initramfs:
https://github.com/krzk/yocto-qcom
with copy_modules argument:

https://github.com/krzk/tools/blob/7c0d1cacad06aa0cae8c2983ae26889471a9aaa6/linux/build.sh#L543

And here is how I append stuff, but simple `cat` one cpio archive to
another cpio archive would work as well, just be sure some paths are not
symlinks (/bin /usr/bin) because then `cat` has issues:

https://github.com/krzk/tools/blob/7c0d1cacad06aa0cae8c2983ae26889471a9aaa6/linux/build.sh#L504

Best regards,
Krzysztof


From jgg at nvidia.com  Mon Mar 17 12:27:13 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 17 Mar 2025 16:27:13 -0300
Subject: [PATCH v8 12/14] iommu/arm-smmu-v3: Introduce struct
 arm_smmu_vmaster
In-Reply-To: <Z9huquCf7YuzIjqx@Asurada-Nvidia>
References: <cover.1740504232.git.nicolinc@nvidia.com>
 <f205a4e2f5971cd4b1033d7cac41683e10ebabfb.1740504232.git.nicolinc@nvidia.com>
 <20250311155714.GC5138@willie-the-truck>
 <Z9B2LMIi+88hlfza@Asurada-Nvidia>
 <20250317154423.GI9311@nvidia.com>
 <Z9huquCf7YuzIjqx@Asurada-Nvidia>
Message-ID: <20250317192713.GS9311@nvidia.com>

On Mon, Mar 17, 2025 at 11:49:14AM -0700, Nicolin Chen wrote:
> On Mon, Mar 17, 2025 at 12:44:23PM -0300, Jason Gunthorpe wrote:
> > On Tue, Mar 11, 2025 at 10:43:08AM -0700, Nicolin Chen wrote:
> > > > > +int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
> > > > > +				    struct arm_smmu_nested_domain *nested_domain)
> > > > > +{
> > > > > +	struct arm_smmu_vmaster *vmaster;
> > > > > +	unsigned long vsid;
> > > > > +	int ret;
> > > > > +
> > > > > +	iommu_group_mutex_assert(state->master->dev);
> > > > > +
> > > > > +	/* Skip invalid vSTE */
> > > > > +	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> > > > > +		return 0;
> > > > 
> > > > Ok, and we don't need to set 'state->vmaster' in this case because we
> > > > only report stage-1 faults back to the vSMMU?
> > > 
> > > This is a good question that I didn't ask myself hard enough..
> > > 
> > > I think we should probably drop it. An invalid STE should trigger
> > > a C_BAD_STE event that is in the supported vEVENT list. I'll run
> > > some test before removing this line from v9.
> > 
> > It won't trigger C_BAD_STE, recall Robin was opposed to thatm so we have this:
> > 
> > static void arm_smmu_make_nested_domain_ste(
> > 	struct arm_smmu_ste *target, struct arm_smmu_master *master,
> > 	struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
> > {
> > 	unsigned int cfg =
> > 		FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(nested_domain->ste[0]));
> > 
> > 	/*
> > 	 * Userspace can request a non-valid STE through the nesting interface.
> > 	 * We relay that into an abort physical STE with the intention that
> > 	 * C_BAD_STE for this SID can be generated to userspace.
> > 	 */
> > 	if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
> > 		cfg = STRTAB_STE_0_CFG_ABORT;
> > 
> > So, in the case of a non-valid STE, and a device access, the HW will
> > generate one of the translation faults and that will be forwarded.
> > 
> > Some software component will have to transform those fault events into
> > C_BAD_STE for the VM.
> 
> Hmm, double checked the spec. It does say that C_BAD_STE would be
> triggered:
> 
> " V, bit [0] STE Valid.
>   [...]
>   Device transactions that select an STE with this field configured
>   to 0 are terminated with an abort reported back to the device and
>   a C_BAD_STE event is recorded."
> 
> I also did a hack test unsetting the V bit in the kernel. Then, the
> HW did report C_BAD_STE (0x4) back to the VM (via vEVENTQ).

Yes, I expect that C_BAD_STE will forward just fine.

But, as above, it should never be generated by HW because the
hypervisor kernel will never install a bad STE, we detect that and
convert it to abort.

Jason


From kauschluss at disroot.org  Mon Mar 17 12:31:42 2025
From: kauschluss at disroot.org (Kaustabh Chakraborty)
Date: Tue, 18 Mar 2025 01:01:42 +0530
Subject: [PATCH RESEND v2 2/3] dt-bindings: phy: samsung,usb3-drd-phy: add
 exynos7870-usbdrd-phy compatible
In-Reply-To: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
References: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
Message-ID: <20250318-exynos7870-usbphy-v2-2-551433b1b27c@disroot.org>

Add the compatible string "samsung,exynos7870-usbdrd-phy" to the
documentation. The devicetree node requires two clocks, named "phy" and
"ref" (same as clocks required by Exynos5).

Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
index 27295acbba7674f6cdc402f18ff4c505bd8760f6..fdddddc7d611364ce17870b5b8963b5a0c0c9668 100644
--- a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
@@ -30,6 +30,7 @@ properties:
       - samsung,exynos5420-usbdrd-phy
       - samsung,exynos5433-usbdrd-phy
       - samsung,exynos7-usbdrd-phy
+      - samsung,exynos7870-usbdrd-phy
       - samsung,exynos850-usbdrd-phy
 
   clocks:
@@ -184,6 +185,7 @@ allOf:
             enum:
               - samsung,exynos5250-usbdrd-phy
               - samsung,exynos5420-usbdrd-phy
+              - samsung,exynos7870-usbdrd-phy
               - samsung,exynos850-usbdrd-phy
     then:
       properties:

-- 
2.48.1



From kauschluss at disroot.org  Mon Mar 17 12:31:41 2025
From: kauschluss at disroot.org (Kaustabh Chakraborty)
Date: Tue, 18 Mar 2025 01:01:41 +0530
Subject: [PATCH RESEND v2 1/3] phy: exynos5-usbdrd: use GENMASK and
 FIELD_PREP for Exynos5 PHY registers
In-Reply-To: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
References: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
Message-ID: <20250318-exynos7870-usbphy-v2-1-551433b1b27c@disroot.org>

Most Exynos850 and Exynos9 (GS101) DRD PHY registers use GENMASK for masks
and FIELD_PREP for writing values to registers.

Rewrite the register definitions which don't follow this approach to follow
it as much as possible. This patch doesn't introduce any fixes or
functional changes, it's merely an attempt to introduce some uniformity and
consistency in the driver code.

The CRPORT SuperSpeed control registers have been exempted from this
change. Since the writing of register values do not require any masking
operations, implementing it would unnecessarily complicate things.

Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
---
 drivers/phy/samsung/phy-exynos5-usbdrd.c | 147 ++++++++++++++++---------------
 1 file changed, 75 insertions(+), 72 deletions(-)

diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 817fddee03927c943c3705ec38aba81b9b6a0975..534ccea9379539a1250e192660d169e47a5b193e 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -39,8 +39,7 @@
 /* Exynos5: USB 3.0 DRD PHY registers */
 #define EXYNOS5_DRD_LINKSYSTEM			0x04
 #define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)
-#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
-#define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
+#define LINKSYSTEM_FLADJ			GENMASK(6, 1)
 
 #define EXYNOS5_DRD_PHYUTMI			0x08
 #define PHYUTMI_OTGDISABLE			BIT(6)
@@ -51,30 +50,27 @@
 
 #define EXYNOS5_DRD_PHYCLKRST			0x10
 #define PHYCLKRST_EN_UTMISUSPEND		BIT(31)
-#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
-#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
-#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
-#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
+#define PHYCLKRST_SSC_REFCLKSEL			GENMASK(30, 23)
+#define PHYCLKRST_SSC_RANGE			GENMASK(22, 21)
 #define PHYCLKRST_SSC_EN			BIT(20)
 #define PHYCLKRST_REF_SSP_EN			BIT(19)
 #define PHYCLKRST_REF_CLKDIV2			BIT(18)
-#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x32 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
-#define PHYCLKRST_FSEL_PIPE_MASK		(0x7 << 8)
-#define PHYCLKRST_FSEL_UTMI_MASK		(0x7 << 5)
-#define PHYCLKRST_FSEL(_x)			((_x) << 5)
-#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
-#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
-#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
-#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
+#define PHYCLKRST_MPLL_MULTIPLIER		GENMASK(17, 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	0x19
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	0x32
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	0x68
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	0x7d
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	0x02
+#define PHYCLKRST_FSEL_PIPE			GENMASK(10, 8)
+#define PHYCLKRST_FSEL_UTMI			GENMASK(7, 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ		0x27
+#define PHYCLKRST_FSEL_PAD_24MHZ		0x2a
+#define PHYCLKRST_FSEL_PAD_20MHZ		0x31
+#define PHYCLKRST_FSEL_PAD_19_2MHZ		0x38
 #define PHYCLKRST_RETENABLEN			BIT(4)
-#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
-#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
-#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
+#define PHYCLKRST_REFCLKSEL			GENMASK(3, 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		0x2
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		0x3
 #define PHYCLKRST_PORTRESET			BIT(1)
 #define PHYCLKRST_COMMONONN			BIT(0)
 
@@ -83,22 +79,22 @@
 #define PHYREG0_SSC_RANGE			BIT(20)
 #define PHYREG0_CR_WRITE			BIT(19)
 #define PHYREG0_CR_READ				BIT(18)
-#define PHYREG0_CR_DATA_IN(_x)			((_x) << 2)
+#define PHYREG0_CR_DATA_IN			GENMASK(17, 2)
 #define PHYREG0_CR_CAP_DATA			BIT(1)
 #define PHYREG0_CR_CAP_ADDR			BIT(0)
 
 #define EXYNOS5_DRD_PHYREG1			0x18
-#define PHYREG1_CR_DATA_OUT(_x)			((_x) << 1)
+#define PHYREG0_CR_DATA_OUT			GENMASK(16, 1)
 #define PHYREG1_CR_ACK				BIT(0)
 
 #define EXYNOS5_DRD_PHYPARAM0			0x1c
 #define PHYPARAM0_REF_USE_PAD			BIT(31)
-#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
-#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
+#define PHYPARAM0_REF_LOSLEVEL			GENMASK(30, 26)
+#define PHYPARAM0_REF_LOSLEVEL_VAL		0x9
 
 #define EXYNOS5_DRD_PHYPARAM1			0x20
-#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
-#define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
+#define PHYPARAM1_PCS_TXDEEMPH			GENMASK(4, 0)
+#define PHYPARAM1_PCS_TXDEEMPH_VAL		0x1c
 
 #define EXYNOS5_DRD_PHYTERM			0x24
 
@@ -140,7 +136,7 @@
 #define LINKCTRL_FORCE_PHYSTATUS		BIT(17)
 #define LINKCTRL_FORCE_PIPE_EN			BIT(16)
 #define LINKCTRL_FORCE_QACT			BIT(8)
-#define LINKCTRL_BUS_FILTER_BYPASS(_x)		((_x) << 4)
+#define LINKCTRL_BUS_FILTER_BYPASS		GENMASK(7, 4)
 
 #define EXYNOS850_DRD_LINKPORT			0x08
 #define LINKPORT_HOST_NUM_U3			GENMASK(19, 16)
@@ -497,29 +493,34 @@ exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
 
 	/* Use EXTREFCLK as ref clock */
-	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
-	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+	reg &= ~PHYCLKRST_REFCLKSEL;
+	reg |=	FIELD_PREP_CONST(PHYCLKRST_REFCLKSEL,
+				 PHYCLKRST_REFCLKSEL_EXT_REFCLK);
 
 	/* FSEL settings corresponding to reference clock */
-	reg &= ~(PHYCLKRST_FSEL_PIPE_MASK |
-		 PHYCLKRST_MPLL_MULTIPLIER_MASK |
-		 PHYCLKRST_SSC_REFCLKSEL_MASK);
+	reg &= ~(PHYCLKRST_FSEL_PIPE |
+		 PHYCLKRST_MPLL_MULTIPLIER |
+		 PHYCLKRST_SSC_REFCLKSEL);
 	switch (phy_drd->extrefclk) {
 	case EXYNOS5_FSEL_50MHZ:
-		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
-			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		reg |= (FIELD_PREP_CONST(PHYCLKRST_SSC_REFCLKSEL, 0x00) |
+			FIELD_PREP_CONST(PHYCLKRST_MPLL_MULTIPLIER,
+					 PHYCLKRST_MPLL_MULTIPLIER_50M_REF));
 		break;
 	case EXYNOS5_FSEL_24MHZ:
-		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
-			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		reg |= (FIELD_PREP_CONST(PHYCLKRST_SSC_REFCLKSEL, 0x88) |
+			FIELD_PREP_CONST(PHYCLKRST_MPLL_MULTIPLIER,
+					 PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF));
 		break;
 	case EXYNOS5_FSEL_20MHZ:
-		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
-			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		reg |= (FIELD_PREP_CONST(PHYCLKRST_SSC_REFCLKSEL, 0x00) |
+			FIELD_PREP_CONST(PHYCLKRST_MPLL_MULTIPLIER,
+					 PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF));
 		break;
 	case EXYNOS5_FSEL_19MHZ2:
-		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
-			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		reg |= (FIELD_PREP_CONST(PHYCLKRST_SSC_REFCLKSEL, 0x88) |
+			FIELD_PREP_CONST(PHYCLKRST_MPLL_MULTIPLIER,
+					 PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF));
 		break;
 	default:
 		dev_dbg(phy_drd->dev, "unsupported ref clk\n");
@@ -542,13 +543,14 @@ exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
 	/* restore any previous reference clock settings */
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
 
-	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
-	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+	reg &= ~PHYCLKRST_REFCLKSEL;
+	reg |=	FIELD_PREP_CONST(PHYCLKRST_REFCLKSEL,
+				 PHYCLKRST_REFCLKSEL_EXT_REFCLK);
 
-	reg &= ~(PHYCLKRST_FSEL_UTMI_MASK |
-		 PHYCLKRST_MPLL_MULTIPLIER_MASK |
-		 PHYCLKRST_SSC_REFCLKSEL_MASK);
-	reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
+	reg &= ~(PHYCLKRST_FSEL_UTMI |
+		 PHYCLKRST_MPLL_MULTIPLIER |
+		 PHYCLKRST_SSC_REFCLKSEL);
+	reg |= FIELD_PREP(PHYCLKRST_FSEL_UTMI, phy_drd->extrefclk);
 
 	return reg;
 }
@@ -598,8 +600,9 @@ static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
 
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
 	/* Set Tx De-Emphasis level */
-	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
-	reg |=	PHYPARAM1_PCS_TXDEEMPH;
+	reg &= ~PHYPARAM1_PCS_TXDEEMPH;
+	reg |=	FIELD_PREP_CONST(PHYPARAM1_PCS_TXDEEMPH,
+				 PHYPARAM1_PCS_TXDEEMPH_VAL);
 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
 
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
@@ -620,7 +623,7 @@ exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(struct exynos5_usbdrd_phy *phy_drd)
 
 	reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
 	reg &= ~SECPMACTL_PMA_REF_FREQ_SEL;
-	reg |= FIELD_PREP(SECPMACTL_PMA_REF_FREQ_SEL, 1);
+	reg |= FIELD_PREP_CONST(SECPMACTL_PMA_REF_FREQ_SEL, 1);
 	/* SFR reset */
 	reg |= (SECPMACTL_PMA_LOW_PWR | SECPMACTL_PMA_APB_SW_RST);
 	reg &= ~(SECPMACTL_PMA_ROPLL_REF_CLK_SEL |
@@ -749,14 +752,16 @@ static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
 
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
 	/* Set Loss-of-Signal Detector sensitivity */
-	reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
-	reg |=	PHYPARAM0_REF_LOSLEVEL;
+	reg &= ~PHYPARAM0_REF_LOSLEVEL;
+	reg |=	FIELD_PREP_CONST(PHYPARAM0_REF_LOSLEVEL,
+				 PHYPARAM0_REF_LOSLEVEL_VAL);
 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
 
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
 	/* Set Tx De-Emphasis level */
-	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
-	reg |=	PHYPARAM1_PCS_TXDEEMPH;
+	reg &= ~PHYPARAM1_PCS_TXDEEMPH;
+	reg |=	FIELD_PREP_CONST(PHYPARAM1_PCS_TXDEEMPH,
+				 PHYPARAM1_PCS_TXDEEMPH_VAL);
 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
 
 	/* UTMI Power Control */
@@ -787,7 +792,7 @@ static int exynos5_usbdrd_phy_init(struct phy *phy)
 	 * See xHCI 1.0 spec, 5.2.4
 	 */
 	reg =	LINKSYSTEM_XHCI_VERSION_CONTROL |
-		LINKSYSTEM_FLADJ(0x20);
+		FIELD_PREP_CONST(LINKSYSTEM_FLADJ, 0x20);
 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
 
 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
@@ -946,26 +951,24 @@ static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
 static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
 			     u32 addr, u32 data)
 {
+	u32 val;
 	int ret;
 
 	/* Write Address */
-	writel(PHYREG0_CR_DATA_IN(addr),
-	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
-	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
-			       PHYREG0_CR_CAP_ADDR);
+	val = FIELD_PREP(PHYREG0_CR_DATA_IN, addr);
+	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+	ret = crport_handshake(phy_drd, val, PHYREG0_CR_CAP_ADDR);
 	if (ret)
 		return ret;
 
 	/* Write Data */
-	writel(PHYREG0_CR_DATA_IN(data),
-	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
-	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
-			       PHYREG0_CR_CAP_DATA);
+	val = FIELD_PREP(PHYREG0_CR_DATA_IN, data);
+	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+	ret = crport_handshake(phy_drd, val, PHYREG0_CR_CAP_DATA);
 	if (ret)
 		return ret;
 
-	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
-			       PHYREG0_CR_WRITE);
+	ret = crport_handshake(phy_drd, val, PHYREG0_CR_WRITE);
 
 	return ret;
 }
@@ -1134,7 +1137,7 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
 
 	/* Set VBUS Valid and D+ pull-up control by VBUS pad usage */
 	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);
-	reg |= LINKCTRL_BUS_FILTER_BYPASS(0xf);
+	reg |= FIELD_PREP_CONST(LINKCTRL_BUS_FILTER_BYPASS, 0xf);
 	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
 
 	if (!phy_drd->sw) {
@@ -1151,19 +1154,19 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
 	reg &= ~SSPPLLCTL_FSEL;
 	switch (phy_drd->extrefclk) {
 	case EXYNOS5_FSEL_50MHZ:
-		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 7);
+		reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 7);
 		break;
 	case EXYNOS5_FSEL_26MHZ:
-		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 6);
+		reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 6);
 		break;
 	case EXYNOS5_FSEL_24MHZ:
-		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 2);
+		reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 2);
 		break;
 	case EXYNOS5_FSEL_20MHZ:
-		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 1);
+		reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 1);
 		break;
 	case EXYNOS5_FSEL_19MHZ2:
-		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 0);
+		reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 0);
 		break;
 	default:
 		dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n",

-- 
2.48.1



From kauschluss at disroot.org  Mon Mar 17 12:31:40 2025
From: kauschluss at disroot.org (Kaustabh Chakraborty)
Date: Tue, 18 Mar 2025 01:01:40 +0530
Subject: [PATCH RESEND v2 0/3] Introduce USBDRD-PHY support for Exynos7870
 SoC
Message-ID: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>

Apart from introducing driver support and documentation, this patch series
also introduces a masking fix and non-functional changes.

This patch series is a part of Exynos7870 upstreaming.

Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
---
Changes in v2:
- Do away with [PATCH 1/4] from v1 as it was sent separately.
- Take over ownership of patches by the co-author, upon their request.
- Link to v1: https://lore.kernel.org/r/20250204-exynos7870-usbphy-v1-0-f30a9857efeb at disroot.org

---
Kaustabh Chakraborty (3):
      phy: exynos5-usbdrd: use GENMASK and FIELD_PREP for Exynos5 PHY registers
      dt-bindings: phy: samsung,usb3-drd-phy: add exynos7870-usbdrd-phy compatible
      phy: exynos5-usbdrd: add exynos7870 USBDRD support

 .../bindings/phy/samsung,usb3-drd-phy.yaml         |   2 +
 drivers/phy/samsung/phy-exynos5-usbdrd.c           | 407 +++++++++++++++++----
 include/linux/soc/samsung/exynos-regs-pmu.h        |   2 +
 3 files changed, 339 insertions(+), 72 deletions(-)
---
base-commit: e5d3fd687aac5eceb1721fa92b9f49afcf4c3717
change-id: 20250203-exynos7870-usbphy-6b98936f441d

Best regards,
-- 
Kaustabh Chakraborty <kauschluss at disroot.org>



From kauschluss at disroot.org  Mon Mar 17 12:31:43 2025
From: kauschluss at disroot.org (Kaustabh Chakraborty)
Date: Tue, 18 Mar 2025 01:01:43 +0530
Subject: [PATCH RESEND v2 3/3] phy: exynos5-usbdrd: add exynos7870 USBDRD
 support
In-Reply-To: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
References: <20250318-exynos7870-usbphy-v2-0-551433b1b27c@disroot.org>
Message-ID: <20250318-exynos7870-usbphy-v2-3-551433b1b27c@disroot.org>

Implement support for Exynos7870 USB DRD on top of the existing
exynos5-usbdrd driver.

Exynos7870 has a single USB 2.0 DRD PHY controller and no 3.0 PHYs. Thus,
it only supports the UTMI interface.

Moreover, the PMU register offset for enabling the PHY controller is
different for SoCs such as Exynos7870, where BIT(0) is for the 3.0 PHY and
BIT(1) is for the 2.0 PHY. The phy_isol function for Exynos7870 uses the
appropriate register offsets.

Signed-off-by: Kaustabh Chakraborty <kauschluss at disroot.org>
---
 drivers/phy/samsung/phy-exynos5-usbdrd.c    | 260 ++++++++++++++++++++++++++++
 include/linux/soc/samsung/exynos-regs-pmu.h |   2 +
 2 files changed, 262 insertions(+)

diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 534ccea9379539a1250e192660d169e47a5b193e..634c4310c660a50e5d0869645506ab1b64fffd4b 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -39,10 +39,22 @@
 /* Exynos5: USB 3.0 DRD PHY registers */
 #define EXYNOS5_DRD_LINKSYSTEM			0x04
 #define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)
+#define LINKSYSTEM_FORCE_VBUSVALID		BIT(8)
+#define LINKSYSTEM_FORCE_BVALID			BIT(7)
 #define LINKSYSTEM_FLADJ			GENMASK(6, 1)
 
 #define EXYNOS5_DRD_PHYUTMI			0x08
+#define PHYUTMI_UTMI_SUSPEND_COM_N		BIT(12)
+#define PHYUTMI_UTMI_L1_SUSPEND_COM_N		BIT(11)
+#define PHYUTMI_VBUSVLDEXTSEL			BIT(10)
+#define PHYUTMI_VBUSVLDEXT			BIT(9)
+#define PHYUTMI_TXBITSTUFFENH			BIT(8)
+#define PHYUTMI_TXBITSTUFFEN			BIT(7)
 #define PHYUTMI_OTGDISABLE			BIT(6)
+#define PHYUTMI_IDPULLUP			BIT(5)
+#define PHYUTMI_DRVVBUS				BIT(4)
+#define PHYUTMI_DPPULLDOWN			BIT(3)
+#define PHYUTMI_DMPULLDOWN			BIT(2)
 #define PHYUTMI_FORCESUSPEND			BIT(1)
 #define PHYUTMI_FORCESLEEP			BIT(0)
 
@@ -91,6 +103,16 @@
 #define PHYPARAM0_REF_USE_PAD			BIT(31)
 #define PHYPARAM0_REF_LOSLEVEL			GENMASK(30, 26)
 #define PHYPARAM0_REF_LOSLEVEL_VAL		0x9
+#define PHYPARAM0_TXVREFTUNE			GENMASK(25, 22)
+#define PHYPARAM0_TXRISETUNE			GENMASK(21, 20)
+#define PHYPARAM0_TXRESTUNE			GENMASK(19, 18)
+#define PHYPARAM0_TXPREEMPPULSETUNE		BIT(17)
+#define PHYPARAM0_TXPREEMPAMPTUNE		GENMASK(16, 15)
+#define PHYPARAM0_TXHSXVTUNE			GENMASK(14, 13)
+#define PHYPARAM0_TXFSLSTUNE			GENMASK(12, 9)
+#define PHYPARAM0_SQRXTUNE			GENMASK(8, 6)
+#define PHYPARAM0_OTGTUNE			GENMASK(5, 3)
+#define PHYPARAM0_COMPDISTUNE			GENMASK(2, 0)
 
 #define EXYNOS5_DRD_PHYPARAM1			0x20
 #define PHYPARAM1_PCS_TXDEEMPH			GENMASK(4, 0)
@@ -110,6 +132,12 @@
 #define EXYNOS5_DRD_PHYRESUME			0x34
 
 #define EXYNOS5_DRD_LINKPORT			0x44
+#define LINKPORT_HOST_U3_PORT_DISABLE		BIT(8)
+#define LINKPORT_HOST_U2_PORT_DISABLE		BIT(7)
+#define LINKPORT_HOST_PORT_OVCR_U3		BIT(5)
+#define LINKPORT_HOST_PORT_OVCR_U2		BIT(4)
+#define LINKPORT_HOST_PORT_OVCR_U3_SEL		BIT(3)
+#define LINKPORT_HOST_PORT_OVCR_U2_SEL		BIT(2)
 
 /* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
 #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)
@@ -130,6 +158,24 @@
 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)
 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)
 
+/* Exynos7870: USB DRD PHY registers */
+#define EXYNOS7870_DRD_PHYPCSVAL		0x3C
+#define PHYPCSVAL_PCS_RX_LOS_MASK		GENMASK(9, 0)
+
+#define EXYNOS7870_DRD_PHYPARAM2		0x50
+#define PHYPARAM2_TX_VBOOST_LVL		        GENMASK(6, 4)
+#define PHYPARAM2_LOS_BIAS			GENMASK(2, 0)
+
+#define EXYNOS7870_DRD_HSPHYCTRL		0x54
+#define HSPHYCTRL_PHYSWRSTALL			BIT(31)
+#define HSPHYCTRL_SIDDQ				BIT(6)
+#define HSPHYCTRL_PHYSWRST			BIT(0)
+
+#define EXYNOS7870_DRD_HSPHYPLLTUNE		0x70
+#define HSPHYPLLTUNE_PLL_B_TUNE			BIT(6)
+#define HSPHYPLLTUNE_PLL_I_TUNE			GENMASK(5, 4)
+#define HSPHYPLLTUNE_PLL_P_TUNE			GENMASK(3, 0)
+
 /* Exynos850: USB DRD PHY registers */
 #define EXYNOS850_DRD_LINKCTRL			0x04
 #define LINKCTRL_FORCE_RXELECIDLE		BIT(18)
@@ -1078,6 +1124,172 @@ static const struct phy_ops exynos5_usbdrd_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static void exynos7870_usbdrd_phy_isol(struct phy_usb_instance *inst,
+				       bool isolate)
+{
+	unsigned int val;
+
+	if (!inst->reg_pmu)
+		return;
+
+	val = isolate ? 0 : EXYNOS7870_USB2PHY_ENABLE;
+
+	regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
+			   EXYNOS7870_USB2PHY_ENABLE, val);
+}
+
+static void exynos7870_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+	u32 reg;
+
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+	/* Use PADREFCLK as ref clock */
+	reg &= ~PHYCLKRST_REFCLKSEL;
+	reg |= FIELD_PREP_CONST(PHYCLKRST_REFCLKSEL,
+				PHYCLKRST_REFCLKSEL_PAD_REFCLK);
+	/* Select ref clock rate */
+	reg &= ~PHYCLKRST_FSEL_UTMI;
+	reg &= ~PHYCLKRST_FSEL_PIPE;
+	reg |= FIELD_PREP(PHYCLKRST_FSEL_UTMI, phy_drd->extrefclk);
+	/* Enable suspend and reset the port */
+	reg |= PHYCLKRST_EN_UTMISUSPEND;
+	reg |= PHYCLKRST_COMMONONN;
+	reg |= PHYCLKRST_PORTRESET;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+	udelay(10);
+
+	/* Clear the port reset bit */
+	reg &= ~PHYCLKRST_PORTRESET;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+	/* Change PHY PLL tune value */
+	reg = readl(phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYPLLTUNE);
+	if (phy_drd->extrefclk == EXYNOS5_FSEL_24MHZ)
+		reg |= HSPHYPLLTUNE_PLL_B_TUNE;
+	else
+		reg &= ~HSPHYPLLTUNE_PLL_B_TUNE;
+	reg &= ~HSPHYPLLTUNE_PLL_P_TUNE;
+	reg |= FIELD_PREP_CONST(HSPHYPLLTUNE_PLL_P_TUNE, 14);
+	writel(reg, phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYPLLTUNE);
+
+	/* High-Speed PHY control */
+	reg = readl(phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	reg &= ~HSPHYCTRL_SIDDQ;
+	reg &= ~HSPHYCTRL_PHYSWRST;
+	reg &= ~HSPHYCTRL_PHYSWRSTALL;
+	writel(reg, phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	udelay(500);
+
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+	/*
+	 * Setting the Frame length Adj value[6:1] to default 0x20
+	 * See xHCI 1.0 spec, 5.2.4
+	 */
+	reg |= LINKSYSTEM_XHCI_VERSION_CONTROL;
+	reg |= FIELD_PREP_CONST(LINKSYSTEM_FLADJ, 0x20);
+	/* Set VBUSVALID signal as the VBUS pad is not used */
+	reg |= LINKSYSTEM_FORCE_BVALID;
+	reg |= LINKSYSTEM_FORCE_VBUSVALID;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+	/* Release force_sleep & force_suspend */
+	reg &= ~PHYUTMI_FORCESLEEP;
+	reg &= ~PHYUTMI_FORCESUSPEND;
+	/* DP/DM pull down control */
+	reg &= ~PHYUTMI_DMPULLDOWN;
+	reg &= ~PHYUTMI_DPPULLDOWN;
+	reg &= ~PHYUTMI_DRVVBUS;
+	/* Set DP-pull up as the VBUS pad is not used */
+	reg |= PHYUTMI_VBUSVLDEXTSEL;
+	reg |= PHYUTMI_VBUSVLDEXT;
+	/* Disable OTG block and VBUS valid comparator */
+	reg |= PHYUTMI_OTGDISABLE;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+	/* Configure OVC IO usage */
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_LINKPORT);
+	reg |= LINKPORT_HOST_PORT_OVCR_U3_SEL | LINKPORT_HOST_PORT_OVCR_U2_SEL;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKPORT);
+
+	/* High-Speed PHY swrst */
+	reg = readl(phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	reg |= HSPHYCTRL_PHYSWRST;
+	writel(reg, phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	udelay(20);
+
+	/* Clear the PHY swrst bit */
+	reg = readl(phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	reg &= ~HSPHYCTRL_PHYSWRST;
+	writel(reg, phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+
+	if (phy_drd->drv_data->phy_tunes)
+		exynos5_usbdrd_apply_phy_tunes(phy_drd,
+					       PTS_UTMI_POSTINIT);
+}
+
+static int exynos7870_usbdrd_phy_init(struct phy *phy)
+{
+	struct phy_usb_instance *inst = phy_get_drvdata(phy);
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+	int ret;
+
+	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
+	if (ret)
+		return ret;
+
+	/* UTMI or PIPE3 specific init */
+	inst->phy_cfg->phy_init(phy_drd);
+
+	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
+
+	return 0;
+}
+
+static int exynos7870_usbdrd_phy_exit(struct phy *phy)
+{
+	int ret;
+	u32 reg;
+	struct phy_usb_instance *inst = phy_get_drvdata(phy);
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
+	if (ret)
+		return ret;
+
+	/*
+	 * Disable the VBUS signal and the ID pull-up resistor.
+	 * Enable force-suspend and force-sleep modes.
+	 */
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+	reg &= ~(PHYUTMI_DRVVBUS | PHYUTMI_VBUSVLDEXT | PHYUTMI_VBUSVLDEXTSEL);
+	reg &= ~PHYUTMI_IDPULLUP;
+	reg |= PHYUTMI_FORCESUSPEND | PHYUTMI_FORCESLEEP;
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+	/* Power down PHY analog blocks */
+	reg = readl(phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+	reg |= HSPHYCTRL_SIDDQ;
+	writel(reg, phy_drd->reg_phy + EXYNOS7870_DRD_HSPHYCTRL);
+
+	/* Clear VBUSVALID signal as the VBUS pad is not used */
+	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+	reg &= ~(LINKSYSTEM_FORCE_BVALID | LINKSYSTEM_FORCE_VBUSVALID);
+	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+
+	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
+
+	return 0;
+}
+
+static const struct phy_ops exynos7870_usbdrd_phy_ops = {
+	.init		= exynos7870_usbdrd_phy_init,
+	.exit		= exynos7870_usbdrd_phy_exit,
+	.power_on	= exynos5_usbdrd_phy_power_on,
+	.power_off	= exynos5_usbdrd_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
 static void
 exynos5_usbdrd_usb_v3p1_pipe_override(struct exynos5_usbdrd_phy *phy_drd)
 {
@@ -1504,6 +1716,14 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	},
 };
 
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos7870[] = {
+	{
+		.id		= EXYNOS5_DRDPHY_UTMI,
+		.phy_isol	= exynos7870_usbdrd_phy_isol,
+		.phy_init	= exynos7870_usbdrd_utmi_init,
+	},
+};
+
 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos850[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
@@ -1512,6 +1732,30 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos850[] = {
 	},
 };
 
+static
+const struct exynos5_usbdrd_phy_tuning exynos7870_tunes_utmi_postinit[] = {
+	PHY_TUNING_ENTRY_PHY(EXYNOS5_DRD_PHYPARAM0,
+			     (PHYPARAM0_TXVREFTUNE | PHYPARAM0_TXRISETUNE |
+			      PHYPARAM0_TXRESTUNE | PHYPARAM0_TXPREEMPPULSETUNE |
+			      PHYPARAM0_TXPREEMPAMPTUNE | PHYPARAM0_TXHSXVTUNE |
+			      PHYPARAM0_TXFSLSTUNE | PHYPARAM0_SQRXTUNE |
+			      PHYPARAM0_OTGTUNE | PHYPARAM0_COMPDISTUNE),
+			     (FIELD_PREP_CONST(PHYPARAM0_TXVREFTUNE, 14) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXRISETUNE, 1) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXRESTUNE, 3) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXPREEMPAMPTUNE, 0) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXHSXVTUNE, 0) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXFSLSTUNE, 3) |
+			      FIELD_PREP_CONST(PHYPARAM0_SQRXTUNE, 6) |
+			      FIELD_PREP_CONST(PHYPARAM0_OTGTUNE, 2) |
+			      FIELD_PREP_CONST(PHYPARAM0_COMPDISTUNE, 3))),
+	PHY_TUNING_ENTRY_LAST
+};
+
+static const struct exynos5_usbdrd_phy_tuning *exynos7870_tunes[PTS_MAX] = {
+	[PTS_UTMI_POSTINIT] = exynos7870_tunes_utmi_postinit,
+};
+
 static const char * const exynos5_clk_names[] = {
 	"phy",
 };
@@ -1578,6 +1822,19 @@ static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
 	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),
 };
 
+static const struct exynos5_usbdrd_phy_drvdata exynos7870_usbdrd_phy = {
+	.phy_cfg		= phy_cfg_exynos7870,
+	.phy_tunes		= exynos7870_tunes,
+	.phy_ops		= &exynos7870_usbdrd_phy_ops,
+	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
+	.clk_names		= exynos5_clk_names,
+	.n_clks			= ARRAY_SIZE(exynos5_clk_names),
+	.core_clk_names		= exynos5_core_clk_names,
+	.n_core_clks		= ARRAY_SIZE(exynos5_core_clk_names),
+	.regulator_names	= exynos5_regulator_names,
+	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),
+};
+
 static const struct exynos5_usbdrd_phy_drvdata exynos850_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos850,
 	.phy_ops		= &exynos850_usbdrd_phy_ops,
@@ -1784,6 +2041,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
 	}, {
 		.compatible = "samsung,exynos7-usbdrd-phy",
 		.data = &exynos7_usbdrd_phy
+	}, {
+		.compatible = "samsung,exynos7870-usbdrd-phy",
+		.data = &exynos7870_usbdrd_phy
 	}, {
 		.compatible = "samsung,exynos850-usbdrd-phy",
 		.data = &exynos850_usbdrd_phy
diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h
index ce1a3790d6fb0400021f5cc22394afedfb742152..cde299a85384a70d04dae49ee9a4e2daa88fbbf6 100644
--- a/include/linux/soc/samsung/exynos-regs-pmu.h
+++ b/include/linux/soc/samsung/exynos-regs-pmu.h
@@ -55,6 +55,8 @@
 #define EXYNOS4_MIPI_PHY_SRESETN		(1 << 1)
 #define EXYNOS4_MIPI_PHY_MRESETN		(1 << 2)
 #define EXYNOS4_MIPI_PHY_RESET_MASK		(3 << 1)
+/* USB PHY enable bit, valid for Exynos7870 */
+#define EXYNOS7870_USB2PHY_ENABLE		(1 << 1)
 
 #define S5P_INFORM0				0x0800
 #define S5P_INFORM1				0x0804

-- 
2.48.1



From robh at kernel.org  Mon Mar 17 12:44:43 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 14:44:43 -0500
Subject: [PATCH 4/9] dt-bindings: arm:
 qcom,coresight-static-replicator: add optional clocks
In-Reply-To: <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
Message-ID: <174224068328.474126.11922746474259386307.robh@kernel.org>


On Mon, 17 Mar 2025 19:44:39 +0200, Dmitry Baryshkov wrote:
> As most other CoreSight devices the replicator can use either of the
> optional clocks (or both). Document those optional clocks in the schema.
> 
> Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml: properties:clock-names: 'enum' should not be valid under {'enum': ['const', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'minimum', 'maximum', 'multipleOf', 'pattern']}
	hint: Scalar and array keywords cannot be mixed
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250317-fix-nexus-4-v1-4-655c52e2ad97 at oss.qualcomm.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From horms at kernel.org  Mon Mar 17 12:43:09 2025
From: horms at kernel.org (Simon Horman)
Date: Mon, 17 Mar 2025 19:43:09 +0000
Subject: [PATCH v2 0/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <20250309232622.1498084-1-jonas@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
Message-ID: <20250317194309.GL688833@kernel.org>

On Sun, Mar 09, 2025 at 11:26:10PM +0000, Jonas Karlman wrote:
> The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
> used with the integrated PHY and a second 1000/100/10 MAC to be used
> with an external Ethernet PHY.
> 
> This series add initial support for the Ethernet controllers found in
> RK3528 and initial support to power up/down the integrated PHY.
> 
> This series depends on v2 of the "net: stmmac: dwmac-rk: Validate GRF
> and peripheral GRF during probe" [1] cleanup series.
> 
> 
> Changes in v2:
> - Restrict the minItems: 4 change to rockchip,rk3528-gmac
> - Add initial support to power up/down the integrated PHY in RK3528
> - Split device tree changes into a separate series
> 
> [1] https://lore.kernel.org/r/20250308213720.2517944-1-jonas at kwiboo.se/

Hi Jonas,

This patchset looks reasonable to me. However it will need
to be reposted once it's dependencies ([1]) are present in net-next.

And on the topic of process:

* As this is a patch-set for net-next it would be best to
  target it accordingly:

  Subject: [PATCH net-next] ...

* Please post patches for net/net-next which have dependencies as RFCs.

For more information on Netdev processes please take a look at
https://docs.kernel.org/process/maintainer-netdev.html

-- 
pw-bot: deferred


From helgaas at kernel.org  Mon Mar 17 12:45:39 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 17 Mar 2025 14:45:39 -0500
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250317184427.7wkcr7jwu53r5jog@thinkpad>
Message-ID: <20250317194539.GA969005@bhelgaas>

On Tue, Mar 18, 2025 at 12:14:27AM +0530, Manivannan Sadhasivam wrote:
> On Mon, Mar 17, 2025 at 12:30:08PM -0500, Bjorn Helgaas wrote:
> > On Thu, Mar 13, 2025 at 11:35:21AM +0530, Manivannan Sadhasivam wrote:
> > > On Wed, Mar 05, 2025 at 11:20:21AM -0500, Frank Li wrote:
> > > > This patches basic on
> > > > https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/
> > > > 
> > > > I have not hardware to test.
> > > > 
> > > > Look for driver owner, who help test this and start move
> > > > forward to remove cpu_addr_fixup() work.
> > > 
> > > If you remove cpu_addr_fixup() callback, it will break backwards
> > > compatibility with old DTs.
> > 
> > Do you have any pointers to DTs that will be broken?  Or to
> > commits where they were fixed?
> 
> Any patch that fixes issues in DT and then makes the required
> changes in the driver without accounting for the old DTs will break
> backwards compatibility.

Right, I guess the rule is that if we have patches that fix DT issues,
we should apply them as soon as possible.

And later if we ever have confidence that unfixed DTs no longer exist
(or if we can identify and work around them in the kernel), we can
remove the .cpu_addr_fixup().

Bjorn


From jonas at kwiboo.se  Mon Mar 17 12:50:34 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Mon, 17 Mar 2025 20:50:34 +0100
Subject: [PATCH v2 0/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <20250317194309.GL688833@kernel.org>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
 <20250317194309.GL688833@kernel.org>
Message-ID: <db3bf1cb-3385-4676-8ba4-41fea0212bf2@kwiboo.se>

Hi Simon,

On 2025-03-17 20:43, Simon Horman wrote:
> On Sun, Mar 09, 2025 at 11:26:10PM +0000, Jonas Karlman wrote:
>> The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
>> used with the integrated PHY and a second 1000/100/10 MAC to be used
>> with an external Ethernet PHY.
>>
>> This series add initial support for the Ethernet controllers found in
>> RK3528 and initial support to power up/down the integrated PHY.
>>
>> This series depends on v2 of the "net: stmmac: dwmac-rk: Validate GRF
>> and peripheral GRF during probe" [1] cleanup series.
>>
>>
>> Changes in v2:
>> - Restrict the minItems: 4 change to rockchip,rk3528-gmac
>> - Add initial support to power up/down the integrated PHY in RK3528
>> - Split device tree changes into a separate series
>>
>> [1] https://lore.kernel.org/r/20250308213720.2517944-1-jonas at kwiboo.se/
> 
> Hi Jonas,
> 
> This patchset looks reasonable to me. However it will need
> to be reposted once it's dependencies ([1]) are present in net-next.

The dependent series ([1]) has already been merged into net-next [2].

Do I still need to repost this series?

[2] https://lore.kernel.org/r/174186063226.1446759.12026198009173732573.git-patchwork-notify at kernel.org/

> 
> And on the topic of process:
> 
> * As this is a patch-set for net-next it would be best to
>   target it accordingly:
> 
>   Subject: [PATCH net-next] ...
> 
> * Please post patches for net/net-next which have dependencies as RFCs.
> 
> For more information on Netdev processes please take a look at
> https://docs.kernel.org/process/maintainer-netdev.html
> 

Thanks, I see, netdev seem to use a slight different process than what
I am familiar with compared to other Linux subsystems and U-Boot :-)

Regards,
Jonas



From catalin.marinas at arm.com  Mon Mar 17 12:54:25 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 17 Mar 2025 19:54:25 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <8634fcnh0n.wl-maz@kernel.org>
References: <20250310103008.3471-1-ankita@nvidia.com>
 <20250310103008.3471-2-ankita@nvidia.com>
 <861pv5p0c3.wl-maz@kernel.org>
 <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
Message-ID: <Z9h98RhunemcFhhz@arm.com>

On Mon, Mar 17, 2025 at 09:27:52AM +0000, Marc Zyngier wrote:
> On Mon, 17 Mar 2025 05:55:55 +0000,
> Ankit Agrawal <ankita at nvidia.com> wrote:
> > 
> > >> For my education, what is an accepted way to communicate this? Please let
> > >> me know if there are any relevant examples that you may be aware of.
> > >
> > > A KVM capability is what is usually needed.
> > 
> > I see. If IIUC, this would involve a corresponding Qemu (usermode) change
> > to fetch the new KVM cap. Then it could fail in case the FWB is not
> > supported with some additional conditions (so that the currently supported
> > configs with !FWB won't break on usermode). 
> > 
> > The proposed code change is to map in S2 as NORMAL when vma flags
> > has VM_PFNMAP. However, Qemu cannot know that driver is mapping
> > with PFNMAP or not. So how may Qemu decide whether it is okay to
> > fail for !FWB or not?
> 
> This is not about FWB as far as userspace is concerned. This is about
> PFNMAP as non-device memory. If the host doesn't have FWB, then the
> "PFNMAP as non-device memory" capability doesn't exist, and userspace
> fails early.
> 
> Userspace must also have some knowledge of what device it obtains the
> mapping from, and whether that device requires some extra host
> capability to be assigned to the guest.
> 
> You can then check whether the VMA associated with the memslot is
> PFNMAP or not, if the memslot has been enabled for PFNMAP mappings
> (either globally or on a per-memslot basis, I don't really care).

Trying to page this back in, I think there are three stages:

1. A KVM cap that the VMM can use to check for non-device PFNMAP (or
   rather cacheable PFNMAP since we already support Normal NC).

2. Memslot registration - we need a way for the VMM to require such
   cacheable PFNMAP and for KVM to check. Current patch relies on (a)
   the stage 1 vma attributes which I'm not a fan of. An alternative I
   suggested was (b) a VM_FORCE_CACHEABLE vma flag, on the assumption
   that the vfio driver knows if it supports cacheable (it's a bit of a
   stretch trying to make this generic). Yet another option is (c) a
   KVM_MEM_CACHEABLE flag that the VMM passes at memslot registration.

3. user_mem_abort() - follows the above logic (whatever we decide),
   maybe with some extra check and WARN in case we got the logic wrong.

The problems in (2) are that we need to know that the device supports
cacheable mappings and we don't introduce additional issues or end up
with FWB on a PFNMAP that does not support cacheable. Without any vma
flag like the current VM_ALLOW_ANY_UNCACHED, the next best thing is
relying on the stage 1 attributes. But we don't know them at the memslot
registration, only later in step (3) after a GUP on the VMM address
space.

So in (2), when !FWB, we only want to reject VM_PFNMAP slots if we know
they are going to be mapped as cacheable. So we need this information
somehow, either from the vma->vm_flags or slot->flags.

-- 
Catalin


From oliver.upton at linux.dev  Mon Mar 17 13:01:07 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Mon, 17 Mar 2025 13:01:07 -0700
Subject: [PATCH v5 0/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
In-Reply-To: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
References: <20250315-pmc-v5-0-ecee87dab216@daynix.com>
Message-ID: <174224155547.1588441.3490436622132208645.b4-ty@linux.dev>

On Sat, 15 Mar 2025 18:12:09 +0900, Akihiko Odaki wrote:
> Prepare vPMC registers for user-initiated changes after first run. This
> is important specifically for debugging Windows on QEMU with GDB; QEMU
> tries to write back all visible registers when resuming the VM execution
> with GDB, corrupting the PMU state. Windows always uses the PMU so this
> can cause adverse effects on that particular OS.
> 
> This series also contains patch "KVM: arm64: PMU: Set raw values from
> user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}", which reverts semantic
> changes made for the mentioned registers in the past. It is necessary
> to migrate the PMU state properly on Firecracker, QEMU, and crosvm.
> 
> [...]

Squashed in a fix for CONFIG_HW_PERF_EVENTS=n build.

Applied to next, thanks!

[1/5] KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
      https://git.kernel.org/kvmarm/kvmarm/c/f2aeb7bbd574
[2/5] KVM: arm64: PMU: Assume PMU presence in pmu-emul.c
      https://git.kernel.org/kvmarm/kvmarm/c/be5ccac3f15e
[3/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
      https://git.kernel.org/kvmarm/kvmarm/c/64074ca8ca92
[4/5] KVM: arm64: PMU: Reload when user modifies registers
      https://git.kernel.org/kvmarm/kvmarm/c/1db4aaa05589
[5/5] KVM: arm64: PMU: Reload when resetting
      https://git.kernel.org/kvmarm/kvmarm/c/fe53538069bb

--
Best,
Oliver


From patchwork-bot+netdevbpf at kernel.org  Mon Mar 17 13:20:48 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 17 Mar 2025 20:20:48 +0000
Subject: [PATCH net-next v1 1/1] stmmac: intel: Fix warning message for return
 value in intel_tsn_lane_is_available()
In-Reply-To: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
References: <20250310050835.808870-1-yong.liang.choong@linux.intel.com>
Message-ID: <174224284849.3901460.9366636522852386074.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Mon, 10 Mar 2025 13:08:35 +0800 you wrote:
> Fix the warning "warn: missing error code? 'ret'" in the
> intel_tsn_lane_is_available() function.
> 
> The function now returns 0 to indicate that a TSN lane was found and
> returns -EINVAL when it is not found.
> 
> Fixes: a42f6b3f1cc1 ("net: stmmac: configure SerDes according to the interface mode")
> Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
> 
> [...]

Here is the summary with links:
  - [net-next,v1,1/1] stmmac: intel: Fix warning message for return value in intel_tsn_lane_is_available()
    https://git.kernel.org/netdev/net-next/c/38f13bf80130

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From robh at kernel.org  Mon Mar 17 13:37:40 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 15:37:40 -0500
Subject: [PATCH v5 0/5] Configure imx8mp dsp node for rproc usage
In-Reply-To: <20250317133306.2003909-1-daniel.baluta@nxp.com>
References: <20250317133306.2003909-1-daniel.baluta@nxp.com>
Message-ID: <174224352689.683565.9145622703259276578.robh@kernel.org>


On Mon, 17 Mar 2025 15:33:01 +0200, Daniel Baluta wrote:
> DSP found in i.MX8MP SOC can be used by multiple frameworks in order to
> enable various applications:
>         - rproc/rpmsg framework, used to load for example Zephyr samples
>         - Sound Open Firmware, used to enable various audio processing
>           pipelines.
> 
> Current dsp node was configured with SOF in mind but it doesn't work
> well with imx8mp-evk dts. SOF controls audio IPs from firmware side
> while imx8mp-evk.dts preffers to control audio IPs from Linux side.
> 
> So, configure 'dsp' node to be used with rproc scenario and later will
> add a separate dts or an overlay to configure the node for SOF.
> 
> This patch series configures and enables dsp node to be used with rproc.
> 
> Changes since v4:
> (https://lore.kernel.org/linux-arm-kernel/Z6zGLn3B6SVXhTV1 at lizhi-Precision-Tower-5810/T/)
> 	- after comments received on v4, we implemented the run/stall
> 	  bits using reset controller API (changes merged ->
> https://patchwork.kernel.org/project/linux-arm-kernel/cover/20250311085812.1296243-1-daniel.baluta at nxp.com/)
>         - drop patches related to DSP run/stall/reset via syscon
> 	- picked up patch related to using run_stall via reset
> 	  controller API.
> 
> Daniel Baluta (5):
>   arm64: dts: imx8mp: Use resets property
>   arm64: dts: imx8mp: Add mu2 root clock
>   arm64: dts: imx8mp: Configure dsp node for rproc usage
>   arm64: dts: imx8mp: Add DSP clocks
>   arm64: dts: Add dsp rproc related mem regions
> 
>  arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 10 +++++++++
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 22 +++++++++++++-------
>  2 files changed, 25 insertions(+), 7 deletions(-)
> 
> --
> 2.43.0
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/freescale/' for 20250317133306.2003909-1-daniel.baluta at nxp.com:

arch/arm64/boot/dts/freescale/imx8mp-aristainetos3-proton2s.dtb: dsp at 3b6e8000: memory-region: [[142]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-var-som-symphony.dtb: dsp at 3b6e8000: memory-region: [[105]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dtb: dsp at 3b6e8000: memory-region: [[156]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx-2x.dtb: dsp at 3b6e8000: memory-region: [[127]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-dahlia.dtb: dsp at 3b6e8000: memory-region: [[164]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dtb: dsp at 3b6e8000: memory-region: [[102]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx-2x.dtb: dsp at 3b6e8000: memory-region: [[129]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-revb-lt6.dtb: dsp at 3b6e8000: memory-region: [[132]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dtb: dsp at 3b6e8000: memory-region: [[118]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-dev.dtb: dsp at 3b6e8000: memory-region: [[165]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-universal-board.dtb: dsp at 3b6e8000: memory-region: [[105]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dtb: dsp at 3b6e8000: memory-region: [[140]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-aristainetos3-adpismarc.dtb: dsp at 3b6e8000: memory-region: [[142]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-ivy.dtb: dsp at 3b6e8000: memory-region: [[162]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx-2x.dtb: dsp at 3b6e8000: memory-region: [[120]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-yavia.dtb: dsp at 3b6e8000: memory-region: [[163]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc-eval-carrier.dtb: dsp at 3b6e8000: memory-region: [[155]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-mallow.dtb: dsp at 3b6e8000: memory-region: [[164]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dtb: dsp at 3b6e8000: memory-region: [[119]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-yavia.dtb: dsp at 3b6e8000: memory-region: [[158]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dtb: dsp at 3b6e8000: memory-region: [[131]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-navqp.dtb: dsp at 3b6e8000: memory-region: [[111]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-revb-hdmi.dtb: dsp at 3b6e8000: memory-region: [[134]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dtb: dsp at 3b6e8000: memory-region: [[130]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dtb: dsp at 3b6e8000: memory-region: [[152]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-revc-bd500.dtb: dsp at 3b6e8000: memory-region: [[130]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dtb: dsp at 3b6e8000: memory-region: [[148]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dtb: dsp at 3b6e8000: memory-region: [[136]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-aristainetos3-helios.dtb: dsp at 3b6e8000: memory-region: [[142]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-dahlia.dtb: dsp at 3b6e8000: memory-region: [[169]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dtb: dsp at 3b6e8000: memory-region: [[156]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-dhcom-drc02.dtb: dsp at 3b6e8000: memory-region: [[160]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-ivy.dtb: dsp at 3b6e8000: memory-region: [[157]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-mallow.dtb: dsp at 3b6e8000: memory-region: [[159]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dtb: dsp at 3b6e8000: memory-region: [[153]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-kontron-bl-osm-s.dtb: dsp at 3b6e8000: memory-region: [[150]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx-2x.dtb: dsp at 3b6e8000: memory-region: [[132]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx-2x.dtb: dsp at 3b6e8000: memory-region: [[123]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dtb: dsp at 3b6e8000: memory-region: [[144]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-dev.dtb: dsp at 3b6e8000: memory-region: [[160]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-revc-tian-g07017.dtb: dsp at 3b6e8000: memory-region: [[131]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-iota2-lumpy.dtb: dsp at 3b6e8000: memory-region: [[107]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-dhcom-picoitx.dtb: dsp at 3b6e8000: memory-region: [[158]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
arch/arm64/boot/dts/freescale/imx8mp-skov-basic.dtb: dsp at 3b6e8000: memory-region: [[129]] is too short
	from schema $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#







From robh at kernel.org  Mon Mar 17 13:37:41 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 15:37:41 -0500
Subject: [PATCH 0/9] ARM: qcom: fix APQ8064 schema warnings
In-Reply-To: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
Message-ID: <174224352766.683604.12560729798577306237.robh@kernel.org>


On Mon, 17 Mar 2025 19:44:35 +0200, Dmitry Baryshkov wrote:
> Rob's bot has reported [1] several warnings for Nexus 4 submisson,
> however none of those warnings are specific to that device. Fix all
> those warnings for all APQ8064 platforms by extending existing schemas,
> adding missing schemas and making APQ8064 DT follow all the schema
> files.
> 
> [1]: https://lore.kernel.org/linux-arm-msm/174221818190.3957236.3364090534153729086.robh at kernel.org/
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
> Dmitry Baryshkov (9):
>       dt-bindings: soc: qcom,rpm: add missing clock-controller node
>       dt-bindings: display/msm: describe SFPB device
>       dt-bindings: soc: qcom: add Smart Peripheral System Interrupt Controller
>       dt-bindings: arm: qcom,coresight-static-replicator: add optional clocks
>       ARM: dts: qcom-apq8064: add missing clocks to the timer node
>       ARM: dts: qcom: apq8064 merge hw splinlock into corresponding syscon device
>       ARM: dts: qcom: apq8064: use new compatible for SFPB device
>       ARM: dts: qcom: apq8064: use new compatible for SPS SIC device
>       ARM: dts: qcom: apq8064: move replicator out of soc node
> 
>  .../arm/arm,coresight-static-replicator.yaml       | 10 +++
>  .../devicetree/bindings/display/msm/qcom,sfpb.yaml | 39 ++++++++++
>  .../devicetree/bindings/soc/qcom/qcom,rpm.yaml     |  8 ++
>  .../devicetree/bindings/soc/qcom/qcom,sps-sic.yaml | 38 ++++++++++
>  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi           | 85 +++++++++++-----------
>  5 files changed, 136 insertions(+), 44 deletions(-)
> ---
> base-commit: 2bb3cf7805af73af62ebfcbb55e350549b6a0912
> change-id: 20250317-fix-nexus-4-dd0fe3bca987
> 
> Best regards,
> --
> Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/qcom/' for 20250317-fix-nexus-4-v1-0-655c52e2ad97 at oss.qualcomm.com:

arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dtb: rpm at 108000: 'clock-names', 'clocks' do not match any of the regexes: '^regulators(-[01])?$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/qcom/qcom,rpm.yaml#
arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dtb: rpm at 108000: 'clock-names', 'clocks' do not match any of the regexes: '^regulators(-[01])?$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/qcom/qcom,rpm.yaml#
arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dtb: rpm at 104000: 'clock-names', 'clocks' do not match any of the regexes: '^regulators(-[01])?$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/qcom/qcom,rpm.yaml#
arch/arm/boot/dts/qcom/qcom-msm8660-surf.dtb: rpm at 104000: 'clock-names', 'clocks' do not match any of the regexes: '^regulators(-[01])?$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/soc/qcom/qcom,rpm.yaml#







From pabeni at redhat.com  Mon Mar 17 13:34:27 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Mon, 17 Mar 2025 21:34:27 +0100
Subject: [PATCH net-next 0/2] net: stmmac: avoid unnecessary work in
 stmmac_release()/stmmac_dvr_remove()
In-Reply-To: <Z9KTixM7_vc_GFe-@shell.armlinux.org.uk>
References: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
 <Z9KTixM7_vc_GFe-@shell.armlinux.org.uk>
Message-ID: <8176af6a-07b0-4f57-848e-6d161fe58746@redhat.com>

On 3/13/25 9:12 AM, Russell King (Oracle) wrote:
> On Mon, Mar 10, 2025 at 12:31:32PM +0000, Russell King (Oracle) wrote:
>> Hi,
>>
>> This small series is a subset of a RFC I sent earlier. These two
>> patches remove code that is unnecessary and/or wrong in these paths.
>> Details in each commit.
>>
>>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 -----
>>  1 file changed, 5 deletions(-)
> 
> Hi Jakub,
> 
> Why is this series showing in patchwork, but not being subjected to
> any nipabot tests?
> 
> There's also "net: phylink: expand on .pcs_config() method
> documentation" which isn't being subjected to nipabot tests.

We had an outage in the nipa infra that caused no test running for a
while. At least it entered later CI runs.

Cheers,

Paolo



From acme at kernel.org  Mon Mar 17 13:48:07 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Mon, 17 Mar 2025 17:48:07 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9RjHpEJGWtj8PAM@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
 <Z9RjHpEJGWtj8PAM@x1>
Message-ID: <Z9iKhwoj1GXvH4c9@x1>

On Fri, Mar 14, 2025 at 02:10:54PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Mar 13, 2025 at 10:45:49PM -0700, Namhyung Kim wrote:
> > On Thu, Mar 13, 2025 at 05:47:27PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > Still building, but noticed this on x86_64:
> > > > 
> > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > 106: perf trace BTF general tests                                    : FAILED!
> > > > 107: perf trace exit race                                            : Ok
> > > > 108: perf trace record and replay                                    : FAILED!
> > > > 
> > > > 
> > > > The first doesn?t help that much with verbose mode, haven't checked if
> > > > before this series it was failing :-\
> > > > 
> > > > root at x1:~# perf test -vvv 105
> > > > 105: perf trace enum augmentation tests:
> > > > --- start ---
> > > > test child forked, pid 19411
> > > > Checking if vmlinux exists
> > > > Tracing syscall landlock_add_rule
> > > > ---- end(-1) ----
> > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > root at x1:~#

This one is now ok:

     0.004 ( 0.000 ms): perf/200342 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffd649bd0d0, flags: 45) = -1 EINVAL (Invalid argument)
root at number:~# perf test enum
105: perf trace enum augmentation tests                              : Ok
root at number:~#

now looking at:

root at number:~# perf test -vvvvvvvvv 106
106: perf trace BTF general tests:
--- start ---
test child forked, pid 200467
Checking if vmlinux BTF exists
Testing perf trace's string augmentation
String augmentation test failed
---- end(-1) ----
106: perf trace BTF general tests                                    : FAILED!
root at number:~#

No clue from the test, reading its source code now to see where it is
failing to try and reproduce the problem.

- Arnaldo


From patchwork-bot+netdevbpf at kernel.org  Mon Mar 17 13:50:43 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 17 Mar 2025 20:50:43 +0000
Subject: [PATCH net-next] net: stmmac: remove unnecessary stmmac_mac_set() in
 stmmac_release()
In-Reply-To: <E1tt9Mq-006xIG-IC@rmk-PC.armlinux.org.uk>
References: <E1tt9Mq-006xIG-IC@rmk-PC.armlinux.org.uk>
Message-ID: <174224464324.3909531.15170592686789310939.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri, 14 Mar 2025 18:02:44 +0000 you wrote:
> stmmac_release() calls phylink_stop() and then goes on to call
> stmmac_mac_set(, false). However, phylink_stop() will call
> stmmac_mac_link_down() before returning, which will do this work.
> Remove this unnecessary call.
> 
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Tested-by: Furong Xu <0x1207 at gmail.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> 
> [...]

Here is the summary with links:
  - [net-next] net: stmmac: remove unnecessary stmmac_mac_set() in stmmac_release()
    https://git.kernel.org/netdev/net-next/c/39b0a10d80d6

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Mon Mar 17 13:50:41 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 17 Mar 2025 20:50:41 +0000
Subject: [PATCH net-next 0/2] net: stmmac: avoid unnecessary work in
 stmmac_release()/stmmac_dvr_remove()
In-Reply-To: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
References: <Z87bpDd7QYYVU0ML@shell.armlinux.org.uk>
Message-ID: <174224464199.3909531.2901969920115907730.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Mon, 10 Mar 2025 12:31:32 +0000 you wrote:
> Hi,
> 
> This small series is a subset of a RFC I sent earlier. These two
> patches remove code that is unnecessary and/or wrong in these paths.
> Details in each commit.
> 
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 -----
>  1 file changed, 5 deletions(-)

Here is the summary with links:
  - [net-next,1/2] net: stmmac: remove redundant racy tear-down in stmmac_dvr_remove()
    https://git.kernel.org/netdev/net-next/c/180fa8d0a2cb
  - [net-next,2/2] net: stmmac: remove unnecessary stmmac_mac_set() in stmmac_release()
    https://git.kernel.org/netdev/net-next/c/39b0a10d80d6

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From patchwork-bot+netdevbpf at kernel.org  Mon Mar 17 13:50:44 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 17 Mar 2025 20:50:44 +0000
Subject: [PATCH net-next] net: stmmac: remove redundant racy tear-down in
 stmmac_dvr_remove()
In-Reply-To: <E1tt9Ml-006xIA-EF@rmk-PC.armlinux.org.uk>
References: <E1tt9Ml-006xIA-EF@rmk-PC.armlinux.org.uk>
Message-ID: <174224464449.3909531.16032949444811656672.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri, 14 Mar 2025 18:02:39 +0000 you wrote:
> While the network device is registered, it is published to userspace,
> and thus userspace can change its state. This means calling
> functions such as stmmac_stop_all_dma() and stmmac_mac_set() are
> racy.
> 
> Moreover, unregister_netdev() will unpublish the network device, and
> then if appropriate call the .ndo_stop() method, which is
> stmmac_release(). This will first call phylink_stop() which will
> synchronously take the link down, resulting in stmmac_mac_link_down()
> and stmmac_mac_set(, false) being called.
> 
> [...]

Here is the summary with links:
  - [net-next] net: stmmac: remove redundant racy tear-down in stmmac_dvr_remove()
    https://git.kernel.org/netdev/net-next/c/180fa8d0a2cb

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From andersson at kernel.org  Mon Mar 17 14:01:57 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 17 Mar 2025 16:01:57 -0500
Subject: [GIT PULL] Qualcomm driver updates for v6.15
Message-ID: <20250317210158.2025380-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-drivers-for-6.15

for you to fetch changes up to 2e14c17a2e3d697bef6b5bf49b253d6e52f3d186:

  soc: qcom: Do not expose internal servreg_location_entry_ei array (2025-02-14 11:37:30 -0600)

----------------------------------------------------------------
Qualcomm driver updates for v6.15

Improve the client interface for the Qualcomm ICE driver to avoid
leaking references, including fixing the client drivers to call the new
function.

Adopt str_on_off() helper in AOSS driver and mark non-global servreg QMI
element info array in the PDR driver static.

----------------------------------------------------------------
Jishnu Prakash (1):
      dt-bindings: soc: qcom: qcom,pmic-glink: Document SM8750 compatible

Krzysztof Kozlowski (2):
      soc: qcom: Use str_enable_disable-like helpers
      soc: qcom: Do not expose internal servreg_location_entry_ei array

Tudor Ambarus (4):
      soc: qcom: ice: introduce devm_of_qcom_ice_get
      mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get
      scsi: ufs: qcom: fix dev reference leaked through of_qcom_ice_get
      soc: qcom: ice: make of_qcom_ice_get() static

 .../bindings/soc/qcom/qcom,pmic-glink.yaml         |  1 +
 drivers/mmc/host/sdhci-msm.c                       |  2 +-
 drivers/soc/qcom/ice.c                             | 51 +++++++++++++++++++++-
 drivers/soc/qcom/pdr_internal.h                    |  1 -
 drivers/soc/qcom/qcom_aoss.c                       |  3 +-
 drivers/soc/qcom/qcom_pdr_msg.c                    |  3 +-
 drivers/ufs/host/ufs-qcom.c                        |  2 +-
 include/soc/qcom/ice.h                             |  3 +-
 8 files changed, 57 insertions(+), 9 deletions(-)


From acme at kernel.org  Mon Mar 17 14:19:50 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Mon, 17 Mar 2025 18:19:50 -0300
Subject: [PATCH v5 00/11] perf: Support multiple system call tables in
 the build
In-Reply-To: <Z9iKhwoj1GXvH4c9@x1>
References: <20250308003209.234114-1-irogers@google.com>
 <Z9KFLGpenwOP32q3@google.com>
 <Z9M24AJzui9lFbGo@x1>
 <Z9M9-YhDJg3NgiUy@x1>
 <Z9NEX3j_1RUvaFI0@x1>
 <Z9PCjQ8PhOadVGQ8@google.com>
 <Z9RjHpEJGWtj8PAM@x1>
 <Z9iKhwoj1GXvH4c9@x1>
Message-ID: <Z9iR9iocSKg0SPph@x1>

On Mon, Mar 17, 2025 at 05:48:10PM -0300, Arnaldo Carvalho de Melo wrote:
> On Fri, Mar 14, 2025 at 02:10:54PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, Mar 13, 2025 at 10:45:49PM -0700, Namhyung Kim wrote:
> > > On Thu, Mar 13, 2025 at 05:47:27PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > On Thu, Mar 13, 2025 at 05:20:09PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > > Still building, but noticed this on x86_64:
> > > > > 
> > > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > > 106: perf trace BTF general tests                                    : FAILED!
> > > > > 107: perf trace exit race                                            : Ok
> > > > > 108: perf trace record and replay                                    : FAILED!
> > > > > 
> > > > > 
> > > > > The first doesn?t help that much with verbose mode, haven't checked if
> > > > > before this series it was failing :-\
> > > > > 
> > > > > root at x1:~# perf test -vvv 105
> > > > > 105: perf trace enum augmentation tests:
> > > > > --- start ---
> > > > > test child forked, pid 19411
> > > > > Checking if vmlinux exists
> > > > > Tracing syscall landlock_add_rule
> > > > > ---- end(-1) ----
> > > > > 105: perf trace enum augmentation tests                              : FAILED!
> > > > > root at x1:~#
 
> This one is now ok:
 
>      0.004 ( 0.000 ms): perf/200342 landlock_add_rule(ruleset_fd: 11, rule_type: LANDLOCK_RULE_NET_PORT, rule_attr: 0x7ffd649bd0d0, flags: 45) = -1 EINVAL (Invalid argument)
> root at number:~# perf test enum
> 105: perf trace enum augmentation tests                              : Ok
> root at number:~#
 
> now looking at:
 
> root at number:~# perf test -vvvvvvvvv 106
> 106: perf trace BTF general tests:
> --- start ---
> test child forked, pid 200467
> Checking if vmlinux BTF exists
> Testing perf trace's string augmentation
> String augmentation test failed
> ---- end(-1) ----
> 106: perf trace BTF general tests                                    : FAILED!
> root at number:~#
 
> No clue from the test, reading its source code now to see where it is
> failing to try and reproduce the problem.

root at number:~# rm -f /tmp/1234567 ; touch /tmp/1234567 ; perf trace -e renameat* --max-events=1 -- mv /tmp/1234567 /tmp/abcdefg
         ? (         ): mv/200698  ... [continued]: renameat2())                                        = -1 EEXIST (File exists)
root at number:~# 

At this point it works:

? [acme at toolbox perf-tools-next]$ git log -1
commit 58f4f294b358861adaee68dfd19da1060058ec27 (HEAD)
Author: James Clark <james.clark at linaro.org>
Date:   Mon Jan 6 16:42:58 2025 +0000

    perf test trace_btf_general: Fix shellcheck warning


root at number:~# rm -f /tmp/1234567 ; touch /tmp/1234567 ; perf trace -e renameat* --max-events=1 -- mv /tmp/1234567 /tmp/abcdefg
     0.000 ( 0.006 ms): mv/218282 renameat2(olddfd: CWD, oldname: "/tmp/1234567", newdfd: CWD, newname: "/tmp/abcdefg", flags: NOREPLACE) = -1 EEXIST (File exists)
root at number:~#

Seems like some transient problem on this test machine, didn't manage to
bisect and now everything seems to work:

Well, not always :-\

root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : Ok
106: perf trace BTF general tests                                    : Ok
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : Ok
106: perf trace BTF general tests                                    : Ok
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test 105 106 107 108 
105: perf trace enum augmentation tests                              : Ok
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# for test in 105 106 107 108 ; do perf test $test ; done
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# for test in 105 106 107 108 ; do perf test $test ; done
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : FAILED!
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~#

So, overall, I think this should land and we should continue trying to
figure out how to find out about the above failure cases, probably the
perf trace cases, since they do set up BPF programs, etc should be done
serially?

Doesn't seem to be the case:

root at number:~# for test in 105 106 107 108 ; do perf test --sequential $test ; done
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : Ok
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# for test in 105 106 107 108 ; do perf test --sequential $test ; done
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : Ok
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# perf test --sequential 105 106 107 108
105: perf trace enum augmentation tests                              : FAILED!
106: perf trace BTF general tests                                    : Ok
107: perf trace exit race                                            : Ok
108: perf trace record and replay                                    : Ok
root at number:~# 

But then if that is the case it needs some love and care to deal with
other BPF users in the system, being more graceful in the face of
errors.

- Arnaldo


From will at kernel.org  Mon Mar 17 14:26:12 2025
From: will at kernel.org (Will Deacon)
Date: Mon, 17 Mar 2025 21:26:12 +0000
Subject: [PATCH 0/4] arm64: mitigate CVE-2024-7881 in the absence of
 firmware mitigation
In-Reply-To: <174197730164.734861.6726211221092480832.b4-ty@arm.com>
References: <20250128155428.210645-1-mark.rutland@arm.com>
 <174197730164.734861.6726211221092480832.b4-ty@arm.com>
Message-ID: <20250317212611.GA12724@willie-the-truck>

On Fri, Mar 14, 2025 at 06:37:25PM +0000, Catalin Marinas wrote:
> On Tue, 28 Jan 2025 15:54:24 +0000, Mark Rutland wrote:
> > On some CPUs from Arm Ltd, it is possible for unprivileged code to cause
> > a hardware prefetcher to form an address using the contents of a memory
> > location which is accessible by privileged accesses in the active
> > translation regime, potentially leaking the contents of this memory
> > location via a side channel. This has been assigned CVE-2024-7881:
> > 
> >   https://developer.arm.com/Arm%20Security%20Center/Arm%20CPU%20Vulnerability%20CVE-2024-7881
> > 
> > [...]
> 
> Applied to arm64 (for-next/leaky-prefetcher), thanks!
> 
> There hasn't been much review (thanks Oliver for looking at the KVM
> bits) and there's some implied work that can go on top of this series.
> But the patches looked fine to me, so I queued them. Mark or others,
> please shout if you'd like them dropped, they are on a branch.

I'm really not comfortable with this series and would prefer to see it
dropped while we continue the discussion, especially as it's causing
minor conflicts with the KVM/arm64 tree in -next.

The series is pitched a bit like an erratum workaround, but the overall
problem that a memory-dependent prefetcher can bypass permission checks
is fairly general and, even if nobody else gets this wrong, I doubt that
it's the last time Arm will mess it up. So, while the EL3 mitigation may
be Arm-specific, I don't think the rest of it really is. That's
especially true given the sorry state of spectre mitigations on
third-party derivatives of Arm designs, such as the Qualcomm Kryo parts,
and the fact that we provide userspace with a mechanism today for
querying the state of those mitigations via sysfs.

The immediate question, then, is whether this broken behaviour is
prohibited by CSV3. The text in the latest Arm ARM just refers to
"Data loaded under speculation", so it's not entirely clear whether that
applies to a prefetcher. If it *does*, then I can see the argument for
treating this like an erratum, but then we should zap CSV3 and treat
these parts as being affected by meltdown. On the other hand, if CSV3
is not intended to cover these prefetchers, then we probably need to
add a new "CVE-2024-7881" entry to /sys/devices/system/cpu/vulnerabilities.

As it stands with this patch series, userspace has no way to know about
the problem. kpti gets silently enabled in dmesg:

  | CPU features: detected: Kernel page table isolation (KPTI)

but the contents of the vulnerabilities directory is pretty misleading:

  gather_data_sampling: Not affected
  ghostwrite: Not affected
  itlb_multihit: Not affected
  l1tf: Not affected
  mds: Not affected
  meltdown: Not affected
  mmio_stale_data: Not affected
  reg_file_data_sampling: Not affected
  retbleed: Not affected
  spec_rstack_overflow: Not affected
  spec_store_bypass: Mitigation: Speculative Store Bypass disabled via prctl
  spectre_v1: Mitigation: __user pointer sanitization
  spectre_v2: Mitigation: CSV2, BHB
  srbds: Not affected
  tsx_async_abort: Not affected

The meltdown entry doesn't even mention that KPTI has been enabled.

If we decide to go with a new entry for this, then we also need to
change the default behaviour along the lines of Doug's Spectre-BHB
changes queued on for-next/spectre-bhb-assume-vulnerable so that we
assume vulnerable if we don't know better. To do otherwise will result
in false assurances to userspace on derivative and third-party
implementations.

To be clear: I'm not at all against mitigating this problem and
advertising the status of that mitigation. I *am* against quietly
handling it like a CPU erratum whilst simultaneously telling userspace
that meltdown is not a problem regardless of the mitigation state.

Will


From wei.liu at kernel.org  Mon Mar 17 14:27:20 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Mon, 17 Mar 2025 21:27:20 +0000
Subject: [PATCH v6 00/10] Introduce /dev/mshv root partition driver
In-Reply-To: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <Z9iTuJRSnKAD5t15@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Fri, Mar 14, 2025 at 12:28:46PM -0700, Nuno Das Neves wrote:
> This series introduces support for creating and running guest virtual
> machines while running on the Microsoft Hypervisor[0] as root partition.
> This is done via an IOCTL interface accessed through /dev/mshv, similar to
> /dev/kvm. Another series introducing this support was previously posted in
> 2021[1], and versions 1-4 of this series were posted in 2023[2].
> 
> Patches 1-4 are small refactors and additions to Hyper-V code.
> Patches 5-6 just export some definitions needed by /dev/mshv.
> Patches 7-9 introduce some functionality and definitions in common code, that
> are specific to the driver.
> Patch 10 contains the driver code.
> 
> -----------------
> [0] "Hyper-V" is more well-known, but it really refers to the whole stack
>     including the hypervisor and other components that run in Windows
>     kernel and userspace.
> [1] Previous /dev/mshv patch series (2021) and discussion:
> https://lore.kernel.org/linux-hyperv/1632853875-20261-1-git-send-email-nunodasneves at linux.microsoft.com/
> [2] v4 (2023):
> https://lore.kernel.org/linux-hyperv/1696010501-24584-1-git-send-email-nunodasneves at linux.microsoft.com/
> 
> -----------------
> Changes since v5:
> * Rework patch 1:
>  1. Introduce hv_status_printk() logging macros which print the raw HV_STATUS_
>     code along with string [Roman Kisel]
>  2. Iterate over an array of data items to get the string and errno for the
>     hv_result_to_*() functions. [Michael Kelley]
>  3. Use hv_status_printk() to log errors in hyperv/irqdomain.c and
>     hyperv-iommu.c [Easwar Hariharan]
> * Minor cleanup, improvements, and commit wording changes in patches 2, 3, 4, 6
>   [Roman Kisel, Easwar Hariharan, Michael Kelley]
> * Fix issues with declaration and lifecycle of hv_synic_eventring_tail in patch
>   7 [Michael Kelley]
> * Improve detail and clarity of commit message in patch 8 [Michael Kelley]
> * Minor cleanups in patch 9 - uapi types -> kernel types, #ifdef CONFIG_X86_64
>   -> CONFIG_X86 for consistency, fix HVCALL_* ordering, remove redundant
>   __packed, use explicit enum value [Stanislav Kinsburskii, Easwar Hariharan,
>   Michael Kelley, Tianyu Lan]
> * Minor fixes and cleanup in patch 10 [Michael Kelley]
> * Add MODULE_DESCRIPTION() to patch 10 [Jeff Johnson]
> 
> Changes since v4:
> * Slim down the IOCTL interface significantly, via several means:
>   1. Use generic "passthrough" call MSHV_ROOT_HVCALL to replace many ioctls.
>   2. Use MSHV_* versions of some of the HV_* definitions.
>   3. Move hv headers out of uapi altogether, into include/hyperv/, see:
> https://lore.kernel.org/linux-hyperv/1732577084-2122-1-git-send-email-nunodasneves at linux.microsoft.com/
> * Remove mshv_vtl module altogther, it will be posted in followup series
>   * Also remove the parent "mshv" module which didn't serve much purpose
> * Update and refactor parts of the driver code for clarity, extensibility
> 
> Changes since v3 (summarized):
> * Clean up the error and debug logging:
>   1. Add a set of macros vp_*() and partition_*() which call the equivalent
>      dev_*(), passing the device from the partition struct
>      * The new macros also print the partition and vp ids to aid debugging
> 	   and reduce repeated code
>   2. Use dev_*() (mostly via the new macros) instead of pr_*() *almost*
>   everywhere - in interrupt context we can't always get the device struct
>   3. Remove pr_*() logging from hv_call.c and mshv_root_hv_call.c
> 
> Changes since v2 (summarized):
> * Fix many checkpatch.pl --strict style issues
> * Initialize status in get/set registers hypercall helpers
> * Add missing return on error in get_vp_signaled_count
> 
> Changes since v1 (summarized):
> * Clean up formatting, commit messages
> 
> Nuno Das Neves (9):
>   hyperv: Log hypercall status codes as strings
>   arm64/hyperv: Add some missing functions to arm64
>   hyperv: Introduce hv_recommend_using_aeoi()
>   acpi: numa: Export node_to_pxm()
>   Drivers: hv: Export some functions for use by root partition module
>   Drivers: hv: Introduce per-cpu event ring tail
>   x86: hyperv: Add mshv_handler() irq handler and setup function
>   hyperv: Add definitions for root partition driver to hv headers
>   Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
> 
> Stanislav Kinsburskii (1):
>   x86/mshyperv: Add support for extended Hyper-V features

Series applied to hyperv-next. Thanks.

I had to fix one minor compilation issue in patch 10, but nothing major.

I also folded the following patch to a previous patch that introduced
MSHV_ROOT (not in this series).


diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 794e88e9dc6b..3118d5472fab 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -57,7 +57,7 @@ config HYPERV_BALLOON
 
 config MSHV_ROOT
 	tristate "Microsoft Hyper-V root partition support"
-	depends on HYPERV
+	depends on HYPERV && (X86_64 || ARM64)
 	depends on !HYPERV_VTL_MODE
 	# The hypervisor interface operates on 4k pages. Enforcing it here
 	# simplifies many assumptions in the root partition code.

Wei.


From andersson at kernel.org  Mon Mar 17 14:36:30 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 17 Mar 2025 16:36:30 -0500
Subject: [GIT PULL] Qualcomm Arm32 DeviceTree updates for v6.15
Message-ID: <20250317213630.2029212-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm32-for-6.15

for you to fetch changes up to adbbdcf4b2d6556721b580385ba387baca5c26ee:

  ARM: dts: qcom: ipq4018: Switch to undeprecated qcom,calibration-variant (2025-03-03 22:36:52 -0600)

----------------------------------------------------------------
Qualcomm Arm32 DeviceTree updates for v6.15

Cleanup indentation issues and a deprecated WiFi property.

----------------------------------------------------------------
Krzysztof Kozlowski (1):
      ARM: dts: qcom: ipq4018: Switch to undeprecated qcom,calibration-variant

Sanjay Chitroda (1):
      ARM: dts: qcom: Fix indentation errors

 arch/arm/boot/dts/qcom/qcom-apq8074-dragonboard.dts | 4 ++--
 arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi  | 2 +-
 arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts    | 4 ++--
 arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi  | 2 +-
 arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi            | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)


From robh at kernel.org  Mon Mar 17 14:46:20 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 16:46:20 -0500
Subject: [PATCH] media: dt-bindings: mediatek,vcodec-encoder: Drop assigned-clock properties
Message-ID: <20250317214621.794674-1-robh@kernel.org>

The assigned-clock properties are always allowed on nodes with
'clocks' and generally not required. Additionally the mt8183 doesn't
define them, so they must not be required in that case.

Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../devicetree/bindings/media/mediatek,vcodec-encoder.yaml  | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
index 110e8f5f1f9e..ebc615584f92 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
@@ -41,10 +41,6 @@ properties:
     minItems: 1
     maxItems: 5
 
-  assigned-clocks: true
-
-  assigned-clock-parents: true
-
   iommus:
     minItems: 1
     maxItems: 32
@@ -78,8 +74,6 @@ required:
   - clocks
   - clock-names
   - iommus
-  - assigned-clocks
-  - assigned-clock-parents
 
 allOf:
   - if:
-- 
2.47.2



From andersson at kernel.org  Mon Mar 17 14:59:19 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Mon, 17 Mar 2025 16:59:19 -0500
Subject: [GIT PULL] Qualcomm Arm64 DeviceTree updates for v6.15
Message-ID: <20250317215921.2031880-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm64-for-6.15

for you to fetch changes up to d09ab685a8f51ba412d37305ea62628a01cbea57:

  arm64: dts: qcom: x1e80100-qcp: Add WiFi/BT pwrseq (2025-03-03 22:54:17 -0600)

----------------------------------------------------------------
Qualcomm Arm64 DeviceTree updates for v6.15

The Snapdragon X Plus platform and the reference device is introduced.

Tsens and thermal zones are added for IPQ5332 and IPQ5424. IPQ6018 gains
1.2GHz and 1.5GHz CPU frequencies.

Display and GPU are enabled in the QCM6490-based Fairphone FP5. On QCS6490
Rb3Gen2 ADC channels for thermal profiling are added and Bluetooth is
enabled.

QCS615 platform gains command DB definition.

The QCS8300 platform gains description of more QUP instances and the
SPMI controller.

On SDM630 missing resets are added for SDCC. Then on Fairphone FP3 modem
is enabled, and firmware-path are defined on ADSP and WCNSS.

The SDM845 RB3/DragonBoard845c and the QRB5165 RB5 has the sensors DSP
enabled, and the vision mezzanine on both gets their CMA configuration
cleaned up.

On the SM7325 Nothing Phone (1) camera EEPROMs are described.

For SM8550 OPP tables are described for PCIe and QUP. SM8750 gains RPMh
sleep stats.

SM8650 gians OSM L3 scaling and variety of OPP tables and missing
interconnect definitions. The thermal trip points for CPU cores and GPU
are raised in reliance on hardware throttling.

A few more temp-alarm instances are added for the SC8280XP PMICs.

On the X Elite platform GPU cooling and watchdog is introduced, together
with a number of smaller fixes. Dell XPS13 gains support for USB Type-C
display, the QCP gains WiFi/BT power sequence, and a few devices learns
about HBR3.

----------------------------------------------------------------
Aleksandrs Vinarskis (4):
      arm64: dts: qcom: x1e80100-dell-xps13-9345: Enable external DP support
      arm64: dts: qcom: x1e001de-devkit: Enable HBR3 on external DPs
      arm64: dts: qcom: x1e80100-hp-x14: Enable HBR3 on external DPs
      arm64: dts: qcom: x1e80100-qcp: Enable HBR3 on external DPs

Alexey Minnekhanov (2):
      dt-bindings: clock: gcc-sdm660: Add missing SDCC resets
      arm64: dts: qcom: sdm630: Add missing resets to mmc blocks

Bjorn Andersson (1):
      Merge branch '20250203063427.358327-2-alexeymin at postmarketos.org' into arm64-for-6.15

Cheng Jiang (1):
      arm64: dts: qcom: sa8775p-ride: Add firmware-name in BT node

Chukun Pan (5):
      arm64: dts: qcom: ipq6018: add 1.2GHz CPU Frequency
      arm64: dts: qcom: ipq6018: add 1.5GHz CPU Frequency
      arm64: dts: qcom: ipq6018: move mp5496 regulator out of soc dtsi
      arm64: dts: qcom: ipq6018: rename labels of mp5496 regulator
      arm64: dts: qcom: ipq6018: add LDOA2 regulator

Danila Tikhonov (2):
      arm64: dts: qcom: sm7325-nothing-spacewar: Add CAM fixed-regulators
      arm64: dts: qcom: sm7325-nothing-spacewar: Enable camera EEPROMs

Dmitry Baryshkov (2):
      arm64: dts: qcom: sdm845-db845c: enable sensors DSP
      arm64: dts: qcom: qrb5165-rb5: enable sensors DSP

Janaki Ramaiah Thota (1):
      arm64: dts: qcom: qcs6490-rb3gen2: add and enable BT node

Konrad Dybcio (5):
      arm64: dts: qcom: x1e80100: Set CPU interconnect paths as ACTIVE_ONLY
      arm64: dts: qcom: x1e80100: Wire up PCIe PHY NOCSR resets
      arm64: dts: qcom: Commonize X1 CRD DTSI
      arm64: dts: qcom: Add X1P42100 SoC and CRD
      arm64: dts: qcom: qcm6490-fairphone-fp5: Enable the GPU

Krzysztof Kozlowski (17):
      arm64: dts: qcom: sa8775p: Partially revert "arm64: dts: qcom: sa8775p: add QCrypto nodes"
      arm64: dts: qcom: qcs8300: Partially revert "arm64: dts: qcom: qcs8300: add QCrypto nodes"
      arm64: dts: qcom: x1e80100-slim7x: Drop incorrect qcom,ath12k-calibration-variant
      arm64: dts: qcom: msm8998: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: qrb2210-rb1: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: qrb4210-rb2: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sc7180: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sdm845: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sda660-ifc6560: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sm6115: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sm8150-hdk: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: qcm6490: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sa8775p-ride: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sc8280xp: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sm8250-elish: Switch to undeprecated qcom,calibration-variant
      arm64: dts: qcom: sm8750: Change labels to lower-case
      arm64: dts: qcom: Correct white-space style

Lijuan Gao (1):
      arm64: dts: qcom: qcs615: Add Command DB support

Luca Weiss (5):
      arm64: dts: qcom: qcm6490-fairphone-fp5: Enable display
      arm64: dts: qcom: sdm632-fairphone-fp3: Move status properties last
      arm64: dts: qcom: sdm632-fairphone-fp3: Add newlines between regulator nodes
      arm64: dts: qcom: sdm632-fairphone-fp3: Add firmware-name for adsp & wcnss
      arm64: dts: qcom: sdm632-fairphone-fp3: Enable modem

Manikanta Mylavarapu (2):
      arm64: dts: qcom: ipq5424: Add tsens node
      arm64: dts: qcom: ipq5424: Add thermal zone nodes

Mark Kettenis (1):
      arm64: dts: qcom: x1e80100: Mark usb_2 as dma-coherent

Maulik Shah (1):
      arm64: dts: qcom: sm8750: Add RPMh sleep stats

Neil Armstrong (19):
      arm64: dts: qcom: sm8650: add OSM L3 node
      arm64: dts: qcom: sm8650: add cpu interconnect nodes
      arm64: dts: qcom: sm8650: add cpu OPP table with DDR, LLCC & L3 bandwidths
      arm64: dts: qcom: sm8650: drop cpu thermal passive trip points
      arm64: dts: qcom: sm8650: setup gpu thermal with higher temperatures
      arm64: dts: qcom: sm8650: harmonize all unregulated thermal trip points
      arm64: dts: qcom: sm8650: drop remaining polling-delay-passive properties
      arm64: dts: qcom: sm8550: use ICC tag for all interconnect phandles
      arm64: dts: qcom: sm8550: set CPU interconnect paths as ACTIVE_ONLY
      arm64: dts: qcom: sm8550: add OPP table support to PCIe
      arm64: dts: qcom: sm8550: add QUP serial engines OPP tables
      arm64: dts: qcom: sm8650: use ICC tag for IPA interconnect phandles
      arm64: dts: qcom: sm8650: set CPU interconnect paths as ACTIVE_ONLY
      arm64: dts: qcom: sm8650: add USB interconnect paths
      arm64: dts: qcom: sm8650: add OPP table support to PCIe
      arm64: dts: qcom: sm8650: add QUP serial engines OPP tables
      arm64: dts: qcom: sm8650: add UFS OPP table instead of freq-table-hz property
      arm64: dts: qcom: sm8550: add missing cpu-cfg interconnect path in the mdss node
      arm64: dts: qcom: sm8650: add missing cpu-cfg interconnect path in the mdss node

Nikita Travkin (2):
      arm64: dts: qcom: qrb5165-rb5-vision-mezzanine: Drop CMA heap
      arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Drop CMA heap

Pengyu Luo (3):
      arm64: dts: qcom: sc8280xp-pmics: Fix slave ID in interrupts configuration
      arm64: dts: qcom: sc8280xp-pmics: Add more temp-alarm devices
      arm64: dts: qcom: sc8280xp: Fix clock for spi0 to spi7

Praveenkumar I (2):
      arm64: dts: qcom: ipq5332: Add tsens node
      arm64: dts: qcom: ipq5332: Add thermal zone nodes

Rajendra Nayak (1):
      arm64: dts: qcom: x1e80100: Add the watchdog device

Rakesh Kota (1):
      arm64: dts: qcom: qcs6490-rb3gen2: Add vadc and adc-tm channels

Stephan Gerhold (5):
      arm64: dts: qcom: x1e80100: Fix video thermal zone
      arm64: dts: qcom: x1e80100: Apply consistent critical thermal shutdown
      arm64: dts: qcom: x1e80100: Add GPU cooling
      arm64: dts: qcom: x1e80100: Drop unused passive thermal trip points for CPU
      arm64: dts: qcom: x1e80100-qcp: Add WiFi/BT pwrseq

Tingguo Cheng (2):
      arm64: dts: qcom: qcs8300: Adds SPMI support
      arm64: dts: qcom: qcs8300-ride: Enable PMIC peripherals

Viken Dadhaniya (1):
      arm64: dts: qcom: qcs8300: Add QUPv3 configuration

Wojciech Slenska (1):
      arm64: dts: qcom: qcm2290: Add uart3 node

 arch/arm64/boot/dts/qcom/Makefile                  |    1 +
 arch/arm64/boot/dts/qcom/ipq5332.dtsi              |  135 ++
 arch/arm64/boot/dts/qcom/ipq5424.dtsi              |  201 ++
 arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts       |    2 +-
 arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi       |   44 +
 arch/arm64/boot/dts/qcom/ipq6018.dtsi              |   28 +-
 arch/arm64/boot/dts/qcom/ipq9574.dtsi              |   40 +-
 arch/arm64/boot/dts/qcom/msm8917-xiaomi-riva.dts   |    2 +-
 arch/arm64/boot/dts/qcom/msm8917.dtsi              |    2 +-
 .../boot/dts/qcom/msm8998-lenovo-miix-630.dts      |    2 +-
 arch/arm64/boot/dts/qcom/qcm2290.dtsi              |   24 +
 arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts |  104 +-
 arch/arm64/boot/dts/qcom/qcm6490-idp.dts           |    2 +-
 arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts   |    2 +-
 arch/arm64/boot/dts/qcom/qcs615.dtsi               |   22 +-
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts       |  281 ++-
 arch/arm64/boot/dts/qcom/qcs8300-pmics.dtsi        |   51 +
 arch/arm64/boot/dts/qcom/qcs8300-ride.dts          |    1 +
 arch/arm64/boot/dts/qcom/qcs8300.dtsi              | 2126 +++++++++++++++++--
 arch/arm64/boot/dts/qcom/qrb2210-rb1.dts           |    2 +-
 arch/arm64/boot/dts/qcom/qrb4210-rb2.dts           |    2 +-
 .../dts/qcom/qrb5165-rb5-vision-mezzanine.dtso     |   11 -
 arch/arm64/boot/dts/qcom/qrb5165-rb5.dts           |    6 +
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi         |    3 +-
 arch/arm64/boot/dts/qcom/sa8775p.dtsi              |   11 -
 .../boot/dts/qcom/sc7180-trogdor-homestar.dtsi     |    2 +-
 .../boot/dts/qcom/sc7180-trogdor-kingoftown.dts    |    2 +-
 arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi |    2 +-
 .../boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi   |    2 +-
 .../arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi |    2 +-
 .../boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi  |    2 +-
 arch/arm64/boot/dts/qcom/sc8280xp-crd.dts          |    2 +-
 .../dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts     |    2 +-
 .../boot/dts/qcom/sc8280xp-microsoft-arcata.dts    |    2 +-
 .../boot/dts/qcom/sc8280xp-microsoft-blackrock.dts |    2 +-
 arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi       |   58 +-
 arch/arm64/boot/dts/qcom/sc8280xp.dtsi             |   16 +-
 .../arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts |    2 +-
 arch/arm64/boot/dts/qcom/sdm630.dtsi               |    3 +
 arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts  |   46 +-
 .../qcom/sdm845-db845c-navigation-mezzanine.dtso   |   11 -
 arch/arm64/boot/dts/qcom/sdm845-db845c.dts         |    8 +-
 arch/arm64/boot/dts/qcom/sdm845-mtp.dts            |    2 +-
 .../boot/dts/qcom/sdm850-lenovo-yoga-c630.dts      |    2 +-
 arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts    |    2 +-
 arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts  |    2 +-
 .../boot/dts/qcom/sm7325-nothing-spacewar.dts      |  157 +-
 arch/arm64/boot/dts/qcom/sm8150-hdk.dts            |    2 +-
 .../boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi  |    2 +-
 arch/arm64/boot/dts/qcom/sm8550.dtsi               |  602 ++++--
 arch/arm64/boot/dts/qcom/sm8650.dtsi               | 2152 +++++++++++++++-----
 arch/arm64/boot/dts/qcom/sm8750.dtsi               |   13 +-
 arch/arm64/boot/dts/qcom/x1-crd.dtsi               | 1275 ++++++++++++
 arch/arm64/boot/dts/qcom/x1e001de-devkit.dts       |    3 +
 arch/arm64/boot/dts/qcom/x1e80100-crd.dts          | 1270 +-----------
 .../boot/dts/qcom/x1e80100-dell-xps13-9345.dts     |   18 +
 .../boot/dts/qcom/x1e80100-hp-omnibook-x14.dts     |    2 +
 .../boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts  |    2 -
 arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi       |    2 +-
 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts          |  147 ++
 arch/arm64/boot/dts/qcom/x1e80100.dtsi             |  968 +++------
 arch/arm64/boot/dts/qcom/x1p42100-crd.dts          |   17 +
 arch/arm64/boot/dts/qcom/x1p42100.dtsi             |   81 +
 include/dt-bindings/clock/qcom,gcc-sdm660.h        |    2 +
 64 files changed, 7152 insertions(+), 2840 deletions(-)
 create mode 100644 arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
 create mode 100644 arch/arm64/boot/dts/qcom/qcs8300-pmics.dtsi
 create mode 100644 arch/arm64/boot/dts/qcom/x1-crd.dtsi
 create mode 100644 arch/arm64/boot/dts/qcom/x1p42100-crd.dts
 create mode 100644 arch/arm64/boot/dts/qcom/x1p42100.dtsi


From helgaas at kernel.org  Mon Mar 17 15:12:00 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 17 Mar 2025 17:12:00 -0500
Subject: [PATCH v12 00/13] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <20250317221200.GA975949@bhelgaas>

On Sat, Mar 15, 2025 at 03:15:35PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
> 
> This is a v12 based on Frank's v11 series.
> 
> v11 https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-0-01d2313502ab at nxp.com
>     
> Changes from v11:
>   - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init(), before
>     any devicetree-related code
>   - Call devm_pci_epc_create() early in dw_pcie_ep_init(), before any
>     devicetree-related code
>   - Consolidate devicetree-related code in dw_pcie_host_get_resources() and
>     dw_pcie_ep_get_resources()
>   - Integrate dw_pcie_cfg0_setup() into dw_pcie_host_get_resources()
>   - Convert dw_pcie_init_parent_bus_offset() to dw_pcie_parent_bus_offset()
>     which returns the offset rather than setting it internally
>   - Split the debug comparison of devicetree info with .cpu_addr_fixup() to
>     separate patch so we can easily revert it later
>   - Drop "cpu_addr_fixup() usage detected" warning since we always warn
>     about something in that case anyway
> 
> Any comments welcome.
> 
> 
> Bjorn Helgaas (3):
>   PCI: dwc: Consolidate devicetree handling in
>     dw_pcie_host_get_resources()
>   PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init()
>   PCI: dwc: ep: Consolidate devicetree handling in
>     dw_pcie_ep_get_resources()
> 
> Frank Li (10):
>   PCI: dwc: Use resource start as iomap() input in
>     dw_pcie_pme_turn_off()
>   PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
>   PCI: dwc: Call devm_pci_alloc_host_bridge() early in
>     dw_pcie_host_init()
>   PCI: dwc: Add dw_pcie_parent_bus_offset()
>   PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug
>   PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr
>     offset
>   PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU
>     addr offset
>   PCI: dwc: ep: Ensure proper iteration over outbound map windows
>   PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup()
>   PCI: imx6: Remove cpu_addr_fixup()
> 
>  drivers/pci/controller/dwc/pci-imx6.c         | 18 +---
>  .../pci/controller/dwc/pcie-designware-ep.c   | 74 +++++++++++------
>  .../pci/controller/dwc/pcie-designware-host.c | 57 ++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.c  | 82 ++++++++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.h  | 24 +++++-
>  5 files changed, 171 insertions(+), 84 deletions(-)

Applied to pci/controller/dwc-cpu-addr-fixup for v6.15.

Thank you very much, Frank, for all your hard work on driving this
series!  I think this is a major improvement.


From oliver.upton at linux.dev  Mon Mar 17 15:38:34 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Mon, 17 Mar 2025 15:38:34 -0700
Subject: [PATCH 0/4] arm64: mitigate CVE-2024-7881 in the absence of
 firmware mitigation
In-Reply-To: <20250317212611.GA12724@willie-the-truck>
References: <20250128155428.210645-1-mark.rutland@arm.com>
 <174197730164.734861.6726211221092480832.b4-ty@arm.com>
 <20250317212611.GA12724@willie-the-truck>
Message-ID: <Z9ikak5AOtDJNVgE@linux.dev>

On Mon, Mar 17, 2025 at 09:26:12PM +0000, Will Deacon wrote:
> On Fri, Mar 14, 2025 at 06:37:25PM +0000, Catalin Marinas wrote:
> > On Tue, 28 Jan 2025 15:54:24 +0000, Mark Rutland wrote:
> > > On some CPUs from Arm Ltd, it is possible for unprivileged code to cause
> > > a hardware prefetcher to form an address using the contents of a memory
> > > location which is accessible by privileged accesses in the active
> > > translation regime, potentially leaking the contents of this memory
> > > location via a side channel. This has been assigned CVE-2024-7881:
> > > 
> > >   https://developer.arm.com/Arm%20Security%20Center/Arm%20CPU%20Vulnerability%20CVE-2024-7881
> > > 
> > > [...]
> > 
> > Applied to arm64 (for-next/leaky-prefetcher), thanks!
> > 
> > There hasn't been much review (thanks Oliver for looking at the KVM
> > bits) and there's some implied work that can go on top of this series.
> > But the patches looked fine to me, so I queued them. Mark or others,
> > please shout if you'd like them dropped, they are on a branch.
> 
> I'm really not comfortable with this series and would prefer to see it
> dropped while we continue the discussion, especially as it's causing
> minor conflicts with the KVM/arm64 tree in -next.

Catalin, unless you say otherwise, I'm going to assume this will be
dropped in the interim.

> The series is pitched a bit like an erratum workaround, but the overall
> problem that a memory-dependent prefetcher can bypass permission checks
> is fairly general and, even if nobody else gets this wrong, I doubt that
> it's the last time Arm will mess it up. So, while the EL3 mitigation may
> be Arm-specific, I don't think the rest of it really is. That's
> especially true given the sorry state of spectre mitigations on
> third-party derivatives of Arm designs, such as the Qualcomm Kryo parts,
> and the fact that we provide userspace with a mechanism today for
> querying the state of those mitigations via sysfs.
> 
> The immediate question, then, is whether this broken behaviour is
> prohibited by CSV3. The text in the latest Arm ARM just refers to
> "Data loaded under speculation", so it's not entirely clear whether that
> applies to a prefetcher.

Hmm, good point. I think prefetchers fall under the ARM ARM glossary
definition of speculation, which includes:

 - Operations generated by the hardware that are not directly generated
   by any instructions appearing in the Execution stream.

> If we decide to go with a new entry for this, then we also need to
> change the default behaviour along the lines of Doug's Spectre-BHB
> changes queued on for-next/spectre-bhb-assume-vulnerable so that we
> assume vulnerable if we don't know better. To do otherwise will result
> in false assurances to userspace on derivative and third-party
> implementations.

Is the idea here that we'd assume any part with FEAT_CSV3 is vulnerable
to CVE-2024-7881 unless told otherwise by firmware / known good list of
implementations?

ARCH_WORKAROUND_4 assumes software has already detected an affected
implementation and doesn't distinguish between "not affected" and "not
mitigated". So I'd be concerned that we're gonna turn on KPTI for a load
of unrelated parts for something that hasn't (yet) been defined as a new
ecosystem bug.

> To be clear: I'm not at all against mitigating this problem and
> advertising the status of that mitigation. I *am* against quietly
> handling it like a CPU erratum whilst simultaneously telling userspace
> that meltdown is not a problem regardless of the mitigation state.

I like your idea of treating this as a broken CSV3 implementation
instead of an entirely new CPU bug, if only to avoid the 'assume the
worst' problem.

Either way KVM will need to implement the SMCCC call to the letter, even
if we wind up nuking CSV3.

Thanks,
Oliver


From heiko at sntech.de  Mon Mar 17 16:07:05 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 18 Mar 2025 00:07:05 +0100
Subject: [PATCH] Revert "dt-bindings: mfd: syscon: Add rk3528 QoS register compatible"
Message-ID: <20250317230705.932808-1-heiko@sntech.de>

This reverts commit 19a634195c1abe498798b564cd6b81e6dd4533f7.

The dt-binding addition adds the compatible to a syscon (a mfd) and should
go through the mfd tree. And it did, and is part of the mfd tree for 6.15
as commit 7f3e3e7228bb ("dt-bindings: mfd: syscon: Add rk3528 QoS register
compatible"), with all the correct Signed-off-by lines.

But of course having a commit present in two trees creates new problems.

So to prevent issues during the merge-window, revert the variant I
accidentially applied.

Fixes: 19a634195c1a ("dt-bindings: mfd: syscon: Add rk3528 QoS register compatible")
Closes: https://lore.kernel.org/lkml/20250317144507.0938757b at canb.auug.org.au/
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
This removes the change from the Rockchip tree, so that only the one in the
mfd tree remains.

 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 2836e4793afc9..4d67ff26d4450 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -103,7 +103,6 @@ select:
           - rockchip,rk3288-qos
           - rockchip,rk3368-qos
           - rockchip,rk3399-qos
-          - rockchip,rk3528-qos
           - rockchip,rk3562-qos
           - rockchip,rk3568-qos
           - rockchip,rk3576-qos
@@ -203,7 +202,6 @@ properties:
           - rockchip,rk3288-qos
           - rockchip,rk3368-qos
           - rockchip,rk3399-qos
-          - rockchip,rk3528-qos
           - rockchip,rk3562-qos
           - rockchip,rk3568-qos
           - rockchip,rk3576-qos
-- 
2.47.2



From robh at kernel.org  Mon Mar 17 16:24:22 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 18:24:22 -0500
Subject: [PATCH 2/3] of: Simplify of_dma_set_restricted_buffer() to use of_for_each_phandle()
In-Reply-To: <20250317232426.952188-1-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
Message-ID: <20250317232426.952188-3-robh@kernel.org>

Simplify of_dma_set_restricted_buffer() by using of_property_present()
and of_for_each_phandle() iterator.

Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
---
 drivers/of/device.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index edf3be197265..bb4a47d58249 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -35,44 +35,36 @@ EXPORT_SYMBOL(of_match_device);
 static void
 of_dma_set_restricted_buffer(struct device *dev, struct device_node *np)
 {
-	struct device_node *node, *of_node = dev->of_node;
-	int count, i;
+	struct device_node *of_node = dev->of_node;
+	struct of_phandle_iterator it;
+	int rc, i = 0;
 
 	if (!IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL))
 		return;
 
-	count = of_property_count_elems_of_size(of_node, "memory-region",
-						sizeof(u32));
 	/*
 	 * If dev->of_node doesn't exist or doesn't contain memory-region, try
 	 * the OF node having DMA configuration.
 	 */
-	if (count <= 0) {
+	if (!of_property_present(of_node, "memory-region"))
 		of_node = np;
-		count = of_property_count_elems_of_size(
-			of_node, "memory-region", sizeof(u32));
-	}
 
-	for (i = 0; i < count; i++) {
-		node = of_parse_phandle(of_node, "memory-region", i);
+	of_for_each_phandle(&it, rc, of_node, "memory-region", NULL, 0) {
 		/*
 		 * There might be multiple memory regions, but only one
 		 * restricted-dma-pool region is allowed.
 		 */
-		if (of_device_is_compatible(node, "restricted-dma-pool") &&
-		    of_device_is_available(node)) {
-			of_node_put(node);
-			break;
+		if (of_device_is_compatible(it.node, "restricted-dma-pool") &&
+		    of_device_is_available(it.node)) {
+			if (!of_reserved_mem_device_init_by_idx(dev, of_node, i)) {
+				of_node_put(it.node);
+				return;
+			}
 		}
-		of_node_put(node);
+		i++;
 	}
 
-	/*
-	 * Attempt to initialize a restricted-dma-pool region if one was found.
-	 * Note that count can hold a negative error code.
-	 */
-	if (i < count && of_reserved_mem_device_init_by_idx(dev, of_node, i))
-		dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n");
+	dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n");
 }
 
 /**
-- 
2.47.2



From robh at kernel.org  Mon Mar 17 16:24:20 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 18:24:20 -0500
Subject: [PATCH 0/3] of: Common "memory-region" parsing
Message-ID: <20250317232426.952188-1-robh@kernel.org>

While there's a common function to parse "memory-region" properties for
DMA pool regions, there's not anything for driver private regions. As a
result, drivers have resorted to parsing "memory-region" properties
themselves repeating the same pattern over and over. To fix this, this
series adds 2 functions to handle those cases:
of_reserved_mem_region_to_resource() and of_reserved_mem_region_count().

I've converted the whole tree, but just including remoteproc here as
it has the most cases. I intend to apply the first 2 patches for 6.15
so the driver conversions can be applied for 6.16.

A git tree with all the drivers converted is here[1].

[1] git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git dt/memory-region

Rob Herring (Arm) (3):
  of: reserved_mem: Add functions to parse "memory-region"
  of: Simplify of_dma_set_restricted_buffer() to use
    of_for_each_phandle()
  remoteproc: Use of_reserved_mem_region_* functions for "memory-region"

 drivers/of/device.c                       | 34 ++++------
 drivers/of/of_reserved_mem.c              | 77 +++++++++++++++++++++++
 drivers/remoteproc/imx_dsp_rproc.c        | 44 +++++--------
 drivers/remoteproc/imx_rproc.c            | 65 ++++++++-----------
 drivers/remoteproc/qcom_q6v5_adsp.c       | 24 +++----
 drivers/remoteproc/qcom_q6v5_mss.c        | 60 ++++++------------
 drivers/remoteproc/qcom_q6v5_pas.c        | 69 ++++++++------------
 drivers/remoteproc/qcom_q6v5_wcss.c       | 25 +++-----
 drivers/remoteproc/qcom_wcnss.c           | 23 +++----
 drivers/remoteproc/rcar_rproc.c           | 36 +++++------
 drivers/remoteproc/st_remoteproc.c        | 39 +++++-------
 drivers/remoteproc/stm32_rproc.c          | 42 ++++++-------
 drivers/remoteproc/ti_k3_dsp_remoteproc.c | 28 ++++-----
 drivers/remoteproc/ti_k3_m4_remoteproc.c  | 28 ++++-----
 drivers/remoteproc/ti_k3_r5_remoteproc.c  | 28 ++++-----
 drivers/remoteproc/xlnx_r5_remoteproc.c   | 49 +++++----------
 include/linux/of_reserved_mem.h           | 26 ++++++++
 17 files changed, 329 insertions(+), 368 deletions(-)

--
2.47.2



From robh at kernel.org  Mon Mar 17 16:24:21 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 18:24:21 -0500
Subject: [PATCH 1/3] of: reserved_mem: Add functions to parse "memory-region"
In-Reply-To: <20250317232426.952188-1-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
Message-ID: <20250317232426.952188-2-robh@kernel.org>

Drivers with "memory-region" properties currently have to do their own
parsing of "memory-region" properties. The result is all the drivers
have similar patterns of a call to parse "memory-region" and then get
the region's address and size. As this is a standard property, it should
have common functions for drivers to use. Add new functions to count the
number of regions and retrieve the region's address as a resource.

Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
---
 drivers/of/of_reserved_mem.c    | 77 +++++++++++++++++++++++++++++++++
 include/linux/of_reserved_mem.h | 26 +++++++++++
 2 files changed, 103 insertions(+)

diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 75e819f66a56..fd50038dff76 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -12,6 +12,7 @@
 #define pr_fmt(fmt)	"OF: reserved mem: " fmt
 
 #include <linux/err.h>
+#include <linux/ioport.h>
 #include <linux/libfdt.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
@@ -740,3 +741,79 @@ struct reserved_mem *of_reserved_mem_lookup(struct device_node *np)
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(of_reserved_mem_lookup);
+
+/**
+ * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource
+ * @np:		node containing 'memory-region' property
+ * @idx:	index of 'memory-region' property to lookup
+ * @res:	Pointer to a struct resource to fill in with reserved region
+ *
+ * This function allows drivers to lookup a node's 'memory-region' property
+ * entries by index and return a struct resource for the entry.
+ *
+ * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region'
+ * is missing or unavailable, -EINVAL for any other error.
+ */
+int of_reserved_mem_region_to_resource(const struct device_node *np, unsigned int idx, struct resource *res)
+{
+	struct reserved_mem *rmem;
+
+	if (!np)
+		return -EINVAL;
+
+	struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx);
+	if (!target || !of_device_is_available(target))
+		return -ENODEV;
+
+	rmem = of_reserved_mem_lookup(target);
+	if (!rmem)
+		return -EINVAL;
+
+	resource_set_range(res, rmem->base, rmem->size);
+	res->name = rmem->name;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource);
+
+/**
+ * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource
+ * @np:		node containing 'memory-region' property
+ * @name:	name of 'memory-region' property entry to lookup
+ * @res:	Pointer to a struct resource to fill in with reserved region
+ *
+ * This function allows drivers to lookup a node's 'memory-region' property
+ * entries by name and return a struct resource for the entry.
+ *
+ * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region'
+ * is missing or unavailable, -EINVAL for any other error.
+ */
+int of_reserved_mem_region_to_resource_byname(const struct device_node *np, const char *name, struct resource *res)
+{
+	int idx;
+
+	if (!name)
+		return -EINVAL;
+
+	idx = of_property_match_string(np, "memory-region-names", name);
+	if (idx < 0)
+		return idx;
+
+	return of_reserved_mem_region_to_resource(np, idx, res);
+}
+EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname);
+
+/**
+ * of_reserved_mem_region_count() - Return the number of 'memory-region' entries
+ * @np:		node containing 'memory-region' property
+ *
+ * This function allows drivers to retrieve the number of entries for a node's
+ * 'memory-region' property.
+ *
+ * Returns the number of entries on success, or negative error code on a
+ * malformed property.
+ */
+int of_reserved_mem_region_count(const struct device_node *np)
+{
+	return of_count_phandle_with_args(np, "memory-region", NULL);
+}
+EXPORT_SYMBOL_GPL(of_reserved_mem_region_count);
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index e338282da652..f573423359f4 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -7,6 +7,7 @@
 
 struct of_phandle_args;
 struct reserved_mem_ops;
+struct resource;
 
 struct reserved_mem {
 	const char			*name;
@@ -39,6 +40,12 @@ int of_reserved_mem_device_init_by_name(struct device *dev,
 void of_reserved_mem_device_release(struct device *dev);
 
 struct reserved_mem *of_reserved_mem_lookup(struct device_node *np);
+int of_reserved_mem_region_to_resource(const struct device_node *np,
+				       unsigned int idx, struct resource *res);
+int of_reserved_mem_region_to_resource_byname(const struct device_node *np,
+					      const char *name, struct resource *res);
+int of_reserved_mem_region_count(const struct device_node *np);
+
 #else
 
 #define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
@@ -63,6 +70,25 @@ static inline struct reserved_mem *of_reserved_mem_lookup(struct device_node *np
 {
 	return NULL;
 }
+
+static inline int of_reserved_mem_region_to_resource(const struct device_node *np,
+						     unsigned int idx,
+						     struct resource *res)
+{
+	return -ENOSYS;
+}
+
+static inline int of_reserved_mem_region_to_resource_byname(const struct device_node *np,
+							    const char *name,
+							    struct resource *res)
+{
+	return -ENOSYS;
+}
+
+static inline int of_reserved_mem_region_count(const struct device_node *np)
+{
+	return 0;
+}
 #endif
 
 /**
-- 
2.47.2



From robh at kernel.org  Mon Mar 17 16:24:23 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 17 Mar 2025 18:24:23 -0500
Subject: [PATCH 3/3] remoteproc: Use of_reserved_mem_region_* functions for "memory-region"
In-Reply-To: <20250317232426.952188-1-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
Message-ID: <20250317232426.952188-4-robh@kernel.org>

Use the newly added of_reserved_mem_region_to_resource() and
of_reserved_mem_region_count() functions to handle "memory-region"
properties.

The error handling is a bit different in some cases. Often
"memory-region" is optional, so failed lookup is not an error. But then
an error in of_reserved_mem_lookup() is treated as an error. However,
that distinction is not really important. Either the region is available
and usable or it is not. So now, it is just
of_reserved_mem_region_to_resource() which is checked for an error.

Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
---
For v6.16

 drivers/remoteproc/imx_dsp_rproc.c        | 44 ++++++---------
 drivers/remoteproc/imx_rproc.c            | 65 ++++++++-------------
 drivers/remoteproc/qcom_q6v5_adsp.c       | 24 +++-----
 drivers/remoteproc/qcom_q6v5_mss.c        | 60 +++++++-------------
 drivers/remoteproc/qcom_q6v5_pas.c        | 69 ++++++++---------------
 drivers/remoteproc/qcom_q6v5_wcss.c       | 25 ++++----
 drivers/remoteproc/qcom_wcnss.c           | 23 +++-----
 drivers/remoteproc/rcar_rproc.c           | 36 +++++-------
 drivers/remoteproc/st_remoteproc.c        | 39 ++++++-------
 drivers/remoteproc/stm32_rproc.c          | 42 ++++++--------
 drivers/remoteproc/ti_k3_dsp_remoteproc.c | 28 ++++-----
 drivers/remoteproc/ti_k3_m4_remoteproc.c  | 28 ++++-----
 drivers/remoteproc/ti_k3_r5_remoteproc.c  | 28 ++++-----
 drivers/remoteproc/xlnx_r5_remoteproc.c   | 49 ++++++----------
 14 files changed, 213 insertions(+), 347 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index ea5024919c2f..f3f341f4a262 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -595,11 +595,9 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
 	struct rproc *rproc = priv->rproc;
 	struct device *dev = rproc->dev.parent;
 	struct device_node *np = dev->of_node;
-	struct of_phandle_iterator it;
 	struct rproc_mem_entry *mem;
-	struct reserved_mem *rmem;
 	void __iomem *cpu_addr;
-	int a;
+	int a, i = 0;
 	u64 da;

 	/* Remap required addresses */
@@ -630,45 +628,37 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
 		rproc_add_carveout(rproc, mem);
 	}

-	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
-	while (of_phandle_iterator_next(&it) == 0) {
+	while (1) {
+		int err;
+		struct resource res;
+
+		err = of_reserved_mem_region_to_resource(np, i++, &res);
+		if (err)
+			return 0;
+
 		/*
 		 * Ignore the first memory region which will be used vdev buffer.
 		 * No need to do extra handlings, rproc_add_virtio_dev will handle it.
 		 */
-		if (!strcmp(it.node->name, "vdev0buffer"))
+		if (!strcmp(res.name, "vdev0buffer"))
 			continue;

-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(dev, "unable to acquire memory-region\n");
+		if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da))
 			return -EINVAL;
-		}

-		if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) {
-			of_node_put(it.node);
-			return -EINVAL;
-		}
-
-		cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
+		cpu_addr = devm_ioremap_resource_wc(dev, &res);
 		if (!cpu_addr) {
-			of_node_put(it.node);
-			dev_err(dev, "failed to map memory %p\n", &rmem->base);
+			dev_err(dev, "failed to map memory %pR\n", &res);
 			return -ENOMEM;
 		}

 		/* Register memory region */
-		mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base,
-					   rmem->size, da, NULL, NULL, it.node->name);
-
-		if (mem) {
-			rproc_coredump_add_segment(rproc, da, rmem->size);
-		} else {
-			of_node_put(it.node);
+		mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)res.start,
+					   resource_size(&res), da, NULL, NULL, res.name);
+		if (!mem)
 			return -ENOMEM;
-		}

+		rproc_coredump_add_segment(rproc, da, resource_size(&res));
 		rproc_add_carveout(rproc, mem);
 	}

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 74299af1d7f1..fba95507b6cf 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -549,46 +549,41 @@ static int imx_rproc_prepare(struct rproc *rproc)
 {
 	struct imx_rproc *priv = rproc->priv;
 	struct device_node *np = priv->dev->of_node;
-	struct of_phandle_iterator it;
 	struct rproc_mem_entry *mem;
-	struct reserved_mem *rmem;
+	int i = 0;
 	u32 da;

 	/* Register associated reserved memory regions */
-	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
-	while (of_phandle_iterator_next(&it) == 0) {
+	while (1) {
+		int err;
+		struct resource res;
+
+		err = of_reserved_mem_region_to_resource(np, i++, &res);
+		if (err)
+			return 0;
+
 		/*
 		 * Ignore the first memory region which will be used vdev buffer.
 		 * No need to do extra handlings, rproc_add_virtio_dev will handle it.
 		 */
-		if (!strcmp(it.node->name, "vdev0buffer"))
+		if (!strcmp(res.name, "vdev0buffer"))
 			continue;

-		if (!strcmp(it.node->name, "rsc-table"))
+		if (!strcmp(res.name, "rsc-table"))
 			continue;

-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(priv->dev, "unable to acquire memory-region\n");
-			return -EINVAL;
-		}
-
 		/* No need to translate pa to da, i.MX use same map */
-		da = rmem->base;
+		da = res.start;

 		/* Register memory region */
-		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da,
+		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start, resource_size(&res), da,
 					   imx_rproc_mem_alloc, imx_rproc_mem_release,
-					   it.node->name);
+					   res.name);

-		if (mem) {
-			rproc_coredump_add_segment(rproc, da, rmem->size);
-		} else {
-			of_node_put(it.node);
+		if (!mem)
 			return -ENOMEM;
-		}

+		rproc_coredump_add_segment(rproc, da, resource_size(&res));
 		rproc_add_carveout(rproc, mem);
 	}

@@ -723,47 +718,37 @@ static int imx_rproc_addr_init(struct imx_rproc *priv,
 	}

 	/* memory-region is optional property */
-	nph = of_count_phandle_with_args(np, "memory-region", NULL);
+	nph = of_reserved_mem_region_count(np);
 	if (nph <= 0)
 		return 0;

 	/* remap optional addresses */
 	for (a = 0; a < nph; a++) {
-		struct device_node *node;
 		struct resource res;

-		node = of_parse_phandle(np, "memory-region", a);
-		if (!node)
-			continue;
-		/* Not map vdevbuffer, vdevring region */
-		if (!strncmp(node->name, "vdev", strlen("vdev"))) {
-			of_node_put(node);
-			continue;
-		}
-		err = of_address_to_resource(node, 0, &res);
+		err = of_reserved_mem_region_to_resource(np, a, &res);
 		if (err) {
 			dev_err(dev, "unable to resolve memory region\n");
-			of_node_put(node);
 			return err;
 		}

-		if (b >= IMX_RPROC_MEM_MAX) {
-			of_node_put(node);
+		/* Not map vdevbuffer, vdevring region */
+		if (!strncmp(res.name, "vdev", strlen("vdev")))
+			continue;
+
+		if (b >= IMX_RPROC_MEM_MAX)
 			break;
-		}

 		/* Not use resource version, because we might share region */
-		priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res));
+		priv->mem[b].cpu_addr = devm_ioremap_resource_wc(&pdev->dev, &res);
 		if (!priv->mem[b].cpu_addr) {
 			dev_err(dev, "failed to remap %pr\n", &res);
-			of_node_put(node);
 			return -ENOMEM;
 		}
 		priv->mem[b].sys_addr = res.start;
 		priv->mem[b].size = resource_size(&res);
-		if (!strcmp(node->name, "rsc-table"))
+		if (!strcmp(res.name, "rsc-table"))
 			priv->rsc_table = priv->mem[b].cpu_addr;
-		of_node_put(node);
 		b++;
 	}

diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index 94af77baa7a1..a5b7cbb8fe07 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -625,26 +625,20 @@ static int adsp_init_mmio(struct qcom_adsp *adsp,

 static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
 {
-	struct reserved_mem *rmem = NULL;
-	struct device_node *node;
-
-	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
-	if (node)
-		rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
+	int ret;
+	struct resource res;

-	if (!rmem) {
+	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 0, &res);
+	if (!ret) {
 		dev_err(adsp->dev, "unable to resolve memory-region\n");
-		return -EINVAL;
+		return ret;
 	}

-	adsp->mem_phys = adsp->mem_reloc = rmem->base;
-	adsp->mem_size = rmem->size;
-	adsp->mem_region = devm_ioremap_wc(adsp->dev,
-				adsp->mem_phys, adsp->mem_size);
+	adsp->mem_phys = adsp->mem_reloc = res.start;
+	adsp->mem_size = resource_size(&res);
+	adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
 	if (!adsp->mem_region) {
-		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
-			&rmem->base, adsp->mem_size);
+		dev_err(adsp->dev, "unable to map memory region: %pR\n", &res);
 		return -EBUSY;
 	}

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index e78bd986dc3f..905a142bd65d 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1881,8 +1881,8 @@ static int q6v5_init_reset(struct q6v5 *qproc)
 static int q6v5_alloc_memory_region(struct q6v5 *qproc)
 {
 	struct device_node *child;
-	struct reserved_mem *rmem;
-	struct device_node *node;
+	struct resource res;
+	int ret;

 	/*
 	 * In the absence of mba/mpss sub-child, extract the mba and mpss
@@ -1890,71 +1890,49 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc)
 	 */
 	child = of_get_child_by_name(qproc->dev->of_node, "mba");
 	if (!child) {
-		node = of_parse_phandle(qproc->dev->of_node,
-					"memory-region", 0);
+		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 0, &res);
 	} else {
-		node = of_parse_phandle(child, "memory-region", 0);
+		ret = of_reserved_mem_region_to_resource(child, 0, &res);
 		of_node_put(child);
 	}

-	if (!node) {
-		dev_err(qproc->dev, "no mba memory-region specified\n");
-		return -EINVAL;
-	}
-
-	rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
-	if (!rmem) {
+	if (ret) {
 		dev_err(qproc->dev, "unable to resolve mba region\n");
-		return -EINVAL;
+		return ret;
 	}

-	qproc->mba_phys = rmem->base;
-	qproc->mba_size = rmem->size;
+	qproc->mba_phys = res.start;
+	qproc->mba_size = resource_size(&res);

 	if (!child) {
-		node = of_parse_phandle(qproc->dev->of_node,
-					"memory-region", 1);
+		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 1, &res);
 	} else {
 		child = of_get_child_by_name(qproc->dev->of_node, "mpss");
-		node = of_parse_phandle(child, "memory-region", 0);
+		ret = of_reserved_mem_region_to_resource(child, 0, &res);
 		of_node_put(child);
 	}

-	if (!node) {
-		dev_err(qproc->dev, "no mpss memory-region specified\n");
-		return -EINVAL;
-	}
-
-	rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
-	if (!rmem) {
+	if (ret) {
 		dev_err(qproc->dev, "unable to resolve mpss region\n");
-		return -EINVAL;
+		return ret;
 	}

-	qproc->mpss_phys = qproc->mpss_reloc = rmem->base;
-	qproc->mpss_size = rmem->size;
+	qproc->mpss_phys = qproc->mpss_reloc = res.start;
+	qproc->mpss_size = resource_size(&res);

 	if (!child) {
-		node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2);
+		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 2, &res);
 	} else {
 		child = of_get_child_by_name(qproc->dev->of_node, "metadata");
-		node = of_parse_phandle(child, "memory-region", 0);
+		ret = of_reserved_mem_region_to_resource(child, 0, &res);
 		of_node_put(child);
 	}

-	if (!node)
+	if (ret)
 		return 0;

-	rmem = of_reserved_mem_lookup(node);
-	if (!rmem) {
-		dev_err(qproc->dev, "unable to resolve metadata region\n");
-		return -EINVAL;
-	}
-
-	qproc->mdata_phys = rmem->base;
-	qproc->mdata_size = rmem->size;
+	qproc->mdata_phys = res.start;
+	qproc->mdata_size = resource_size(&res);

 	return 0;
 }
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 97c4bdd9222a..0ebd2ce0477b 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -546,53 +546,37 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,

 static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
 {
-	struct reserved_mem *rmem;
-	struct device_node *node;
-
-	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
-	if (!node) {
-		dev_err(adsp->dev, "no memory-region specified\n");
-		return -EINVAL;
-	}
+	struct resource res;
+	int ret;

-	rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
-	if (!rmem) {
+	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 0, &res);
+	if (ret) {
 		dev_err(adsp->dev, "unable to resolve memory-region\n");
-		return -EINVAL;
+		return ret;
 	}

-	adsp->mem_phys = adsp->mem_reloc = rmem->base;
-	adsp->mem_size = rmem->size;
-	adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
+	adsp->mem_phys = adsp->mem_reloc = res.start;
+	adsp->mem_size = resource_size(&res);
+	adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
 	if (!adsp->mem_region) {
-		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
-			&rmem->base, adsp->mem_size);
+		dev_err(adsp->dev, "unable to map memory region: %pR\n", &res);
 		return -EBUSY;
 	}

 	if (!adsp->dtb_pas_id)
 		return 0;

-	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1);
-	if (!node) {
-		dev_err(adsp->dev, "no dtb memory-region specified\n");
-		return -EINVAL;
-	}
-
-	rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
-	if (!rmem) {
+	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 1, &res);
+	if (ret) {
 		dev_err(adsp->dev, "unable to resolve dtb memory-region\n");
-		return -EINVAL;
+		return ret;
 	}

-	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base;
-	adsp->dtb_mem_size = rmem->size;
-	adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size);
+	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = res.start;
+	adsp->dtb_mem_size = resource_size(&res);
+	adsp->dtb_mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
 	if (!adsp->dtb_mem_region) {
-		dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n",
-			&rmem->base, adsp->dtb_mem_size);
+		dev_err(adsp->dev, "unable to map dtb memory region: %pR\n", &res);
 		return -EBUSY;
 	}

@@ -602,7 +586,6 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
 static int adsp_assign_memory_region(struct qcom_adsp *adsp)
 {
 	struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT];
-	struct device_node *node;
 	unsigned int perm_size;
 	int offset;
 	int ret;
@@ -611,17 +594,15 @@ static int adsp_assign_memory_region(struct qcom_adsp *adsp)
 		return 0;

 	for (offset = 0; offset < adsp->region_assign_count; ++offset) {
-		struct reserved_mem *rmem = NULL;
-
-		node = of_parse_phandle(adsp->dev->of_node, "memory-region",
-					adsp->region_assign_idx + offset);
-		if (node)
-			rmem = of_reserved_mem_lookup(node);
-		of_node_put(node);
-		if (!rmem) {
+		struct resource res;
+
+		ret = of_reserved_mem_region_to_resource(adsp->dev->of_node,
+							 adsp->region_assign_idx + offset,
+							 &res);
+		if (ret) {
 			dev_err(adsp->dev, "unable to resolve shareable memory-region index %d\n",
 				offset);
-			return -EINVAL;
+			return ret;
 		}

 		if (adsp->region_assign_shared)  {
@@ -636,8 +617,8 @@ static int adsp_assign_memory_region(struct qcom_adsp *adsp)
 			perm_size = 1;
 		}

-		adsp->region_assign_phys[offset] = rmem->base;
-		adsp->region_assign_size[offset] = rmem->size;
+		adsp->region_assign_phys[offset] = res.start;
+		adsp->region_assign_size[offset] = resource_size(&res);
 		adsp->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS);

 		ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset],
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index 93648734a2f2..4a3235ee0963 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -873,27 +873,22 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,

 static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
 {
-	struct reserved_mem *rmem = NULL;
-	struct device_node *node;
 	struct device *dev = wcss->dev;
+	struct resource res;
+	int ret;

-	node = of_parse_phandle(dev->of_node, "memory-region", 0);
-	if (node)
-		rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
-
-	if (!rmem) {
+	ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
+	if (ret) {
 		dev_err(dev, "unable to acquire memory-region\n");
-		return -EINVAL;
+		return ret;
 	}

-	wcss->mem_phys = rmem->base;
-	wcss->mem_reloc = rmem->base;
-	wcss->mem_size = rmem->size;
-	wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
+	wcss->mem_phys = res.start;
+	wcss->mem_reloc = res.start;
+	wcss->mem_size = resource_size(&res);
+	wcss->mem_region = devm_ioremap_resource_wc(dev, &res);
 	if (!wcss->mem_region) {
-		dev_err(dev, "unable to map memory region: %pa+%pa\n",
-			&rmem->base, &rmem->size);
+		dev_err(dev, "unable to map memory region: %pR\n", &res);
 		return -EBUSY;
 	}

diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index 5b5664603eed..d99a324bd532 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -506,25 +506,20 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss,

 static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
 {
-	struct reserved_mem *rmem = NULL;
-	struct device_node *node;
-
-	node = of_parse_phandle(wcnss->dev->of_node, "memory-region", 0);
-	if (node)
-		rmem = of_reserved_mem_lookup(node);
-	of_node_put(node);
+	struct resource res;
+	int ret;

-	if (!rmem) {
+	ret = of_reserved_mem_region_to_resource(wcnss->dev->of_node, 0, &res);
+	if (ret) {
 		dev_err(wcnss->dev, "unable to resolve memory-region\n");
-		return -EINVAL;
+		return ret;
 	}

-	wcnss->mem_phys = wcnss->mem_reloc = rmem->base;
-	wcnss->mem_size = rmem->size;
-	wcnss->mem_region = devm_ioremap_wc(wcnss->dev, wcnss->mem_phys, wcnss->mem_size);
+	wcnss->mem_phys = wcnss->mem_reloc = res.start;
+	wcnss->mem_size = resource_size(&res);
+	wcnss->mem_region = devm_ioremap_resource_wc(wcnss->dev, &res);
 	if (!wcnss->mem_region) {
-		dev_err(wcnss->dev, "unable to map memory region: %pa+%zx\n",
-			&rmem->base, wcnss->mem_size);
+		dev_err(wcnss->dev, "unable to map memory region: %pR\n", &res);
 		return -EBUSY;
 	}

diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c
index 921d853594f4..0be1a4073a94 100644
--- a/drivers/remoteproc/rcar_rproc.c
+++ b/drivers/remoteproc/rcar_rproc.c
@@ -52,41 +52,33 @@ static int rcar_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
 	struct device_node *np = dev->of_node;
-	struct of_phandle_iterator it;
 	struct rproc_mem_entry *mem;
-	struct reserved_mem *rmem;
+	int i = 0;
 	u32 da;

 	/* Register associated reserved memory regions */
-	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
-	while (of_phandle_iterator_next(&it) == 0) {
-
-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(&rproc->dev,
-				"unable to acquire memory-region\n");
-			return -EINVAL;
-		}
+	while (1) {
+		struct resource res;
+		int ret;
+
+		ret = of_reserved_mem_region_to_resource(np, i++, &res);
+		if (ret)
+			return 0;

-		if (rmem->base > U32_MAX) {
-			of_node_put(it.node);
+		if (res.start > U32_MAX)
 			return -EINVAL;
-		}

 		/* No need to translate pa to da, R-Car use same map */
-		da = rmem->base;
+		da = res.start;
 		mem = rproc_mem_entry_init(dev, NULL,
-					   rmem->base,
-					   rmem->size, da,
+					   res.start,
+					   resource_size(&res), da,
 					   rcar_rproc_mem_alloc,
 					   rcar_rproc_mem_release,
-					   it.node->name);
+					   res.name);

-		if (!mem) {
-			of_node_put(it.node);
+		if (!mem)
 			return -ENOMEM;
-		}

 		rproc_add_carveout(rproc, mem);
 	}
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index e6566a9839dc..901b90de4953 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -120,40 +120,35 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
 	struct device *dev = rproc->dev.parent;
 	struct device_node *np = dev->of_node;
 	struct rproc_mem_entry *mem;
-	struct reserved_mem *rmem;
-	struct of_phandle_iterator it;
-	int index = 0;
-
-	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
-	while (of_phandle_iterator_next(&it) == 0) {
-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(dev, "unable to acquire memory-region\n");
-			return -EINVAL;
-		}
+	int index = 0, mr = 0;
+
+	while (1) {
+		struct resource res;
+		int ret;
+
+		ret = of_reserved_mem_region_to_resource(np, mr++, &res);
+		if (ret)
+			return 0;

 		/*  No need to map vdev buffer */
-		if (strcmp(it.node->name, "vdev0buffer")) {
+		if (strcmp(res.name, "vdev0buffer")) {
 			/* Register memory region */
 			mem = rproc_mem_entry_init(dev, NULL,
-						   (dma_addr_t)rmem->base,
-						   rmem->size, rmem->base,
+						   (dma_addr_t)res.start,
+						   resource_size(&res), res.start,
 						   st_rproc_mem_alloc,
 						   st_rproc_mem_release,
-						   it.node->name);
+						   res.name);
 		} else {
 			/* Register reserved memory for vdev buffer allocation */
 			mem = rproc_of_resm_mem_entry_init(dev, index,
-							   rmem->size,
-							   rmem->base,
-							   it.node->name);
+							   resource_size(&res),
+							   res.start,
+							   res.name);
 		}

-		if (!mem) {
-			of_node_put(it.node);
+		if (!mem)
 			return -ENOMEM;
-		}

 		rproc_add_carveout(rproc, mem);
 		index++;
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index b02b36a3f515..9d2bd8904c49 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
 	struct device_node *np = dev->of_node;
-	struct of_phandle_iterator it;
 	struct rproc_mem_entry *mem;
-	struct reserved_mem *rmem;
 	u64 da;
-	int index = 0;
+	int index = 0, mr = 0;

 	/* Register associated reserved memory regions */
-	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
-	while (of_phandle_iterator_next(&it) == 0) {
-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(dev, "unable to acquire memory-region\n");
-			return -EINVAL;
-		}
+	while (1) {
+		struct resource res;
+		int ret;
+
+		ret = of_reserved_mem_region_to_resource(np, mr++, &res);
+		if (ret)
+			return 0;

-		if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
-			of_node_put(it.node);
-			dev_err(dev, "memory region not valid %pa\n",
-				&rmem->base);
+		if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
+			dev_err(dev, "memory region not valid %pR\n", &res);
 			return -EINVAL;
 		}

 		/*  No need to map vdev buffer */
-		if (strcmp(it.node->name, "vdev0buffer")) {
+		if (strcmp(res.name, "vdev0buffer")) {
 			/* Register memory region */
 			mem = rproc_mem_entry_init(dev, NULL,
-						   (dma_addr_t)rmem->base,
-						   rmem->size, da,
+						   (dma_addr_t)res.start,
+						   resource_size(&res), da,
 						   stm32_rproc_mem_alloc,
 						   stm32_rproc_mem_release,
-						   it.node->name);
+						   res.name);

 			if (mem)
 				rproc_coredump_add_segment(rproc, da,
-							   rmem->size);
+							   resource_size(&res));
 		} else {
 			/* Register reserved memory for vdev buffer alloc */
 			mem = rproc_of_resm_mem_entry_init(dev, index,
-							   rmem->size,
-							   rmem->base,
-							   it.node->name);
+							   resource_size(&res),
+							   res.start,
+							   res.name);
 		}

 		if (!mem) {
-			of_node_put(it.node);
 			return -ENOMEM;
 		}

diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
index a695890254ff..f02c835535bc 100644
--- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
@@ -535,13 +535,10 @@ static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)
 {
 	struct device *dev = kproc->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *rmem_np;
-	struct reserved_mem *rmem;
 	int num_rmems;
 	int ret, i;

-	num_rmems = of_property_count_elems_of_size(np, "memory-region",
-						    sizeof(phandle));
+	num_rmems = of_reserved_mem_region_count(np);
 	if (num_rmems < 0) {
 		dev_err(dev, "device does not reserved memory regions (%pe)\n",
 			ERR_PTR(num_rmems));
@@ -571,23 +568,20 @@ static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)

 	/* use remaining reserved memory regions for static carveouts */
 	for (i = 0; i < num_rmems; i++) {
-		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
-		if (!rmem_np)
-			return -EINVAL;
+		struct resource res;

-		rmem = of_reserved_mem_lookup(rmem_np);
-		of_node_put(rmem_np);
-		if (!rmem)
-			return -EINVAL;
+		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
+		if (ret)
+			return ret;

-		kproc->rmem[i].bus_addr = rmem->base;
+		kproc->rmem[i].bus_addr = res.start;
 		/* 64-bit address regions currently not supported */
-		kproc->rmem[i].dev_addr = (u32)rmem->base;
-		kproc->rmem[i].size = rmem->size;
-		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
+		kproc->rmem[i].dev_addr = (u32)res.start;
+		kproc->rmem[i].size = resource_size(&res);
+		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
 		if (!kproc->rmem[i].cpu_addr) {
-			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
-				i + 1, &rmem->base, &rmem->size);
+			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
+				i + 1, &res);
 			return -ENOMEM;
 		}

diff --git a/drivers/remoteproc/ti_k3_m4_remoteproc.c b/drivers/remoteproc/ti_k3_m4_remoteproc.c
index a16fb165fced..8c7772cd6baf 100644
--- a/drivers/remoteproc/ti_k3_m4_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_m4_remoteproc.c
@@ -393,13 +393,10 @@ static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)
 {
 	struct device *dev = kproc->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *rmem_np;
-	struct reserved_mem *rmem;
 	int num_rmems;
 	int ret, i;

-	num_rmems = of_property_count_elems_of_size(np, "memory-region",
-						    sizeof(phandle));
+	num_rmems = of_reserved_mem_region_count(np);
 	if (num_rmems < 0) {
 		dev_err(dev, "device does not reserved memory regions (%d)\n",
 			num_rmems);
@@ -428,23 +425,20 @@ static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)

 	/* use remaining reserved memory regions for static carveouts */
 	for (i = 0; i < num_rmems; i++) {
-		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
-		if (!rmem_np)
-			return -EINVAL;
+		struct resource res;

-		rmem = of_reserved_mem_lookup(rmem_np);
-		of_node_put(rmem_np);
-		if (!rmem)
-			return -EINVAL;
+		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
+		if (ret)
+			return ret;

-		kproc->rmem[i].bus_addr = rmem->base;
+		kproc->rmem[i].bus_addr = res.start;
 		/* 64-bit address regions currently not supported */
-		kproc->rmem[i].dev_addr = (u32)rmem->base;
-		kproc->rmem[i].size = rmem->size;
-		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
+		kproc->rmem[i].dev_addr = (u32)res.start;
+		kproc->rmem[i].size = resource_size(&res);
+		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
 		if (!kproc->rmem[i].cpu_addr) {
-			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
-				i + 1, &rmem->base, &rmem->size);
+			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
+				i + 1, &res);
 			return -ENOMEM;
 		}

diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
index dbc513c5569c..9a7a61e0ecb8 100644
--- a/drivers/remoteproc/ti_k3_r5_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c
@@ -966,13 +966,10 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
 {
 	struct device *dev = kproc->dev;
 	struct device_node *np = dev_of_node(dev);
-	struct device_node *rmem_np;
-	struct reserved_mem *rmem;
 	int num_rmems;
 	int ret, i;

-	num_rmems = of_property_count_elems_of_size(np, "memory-region",
-						    sizeof(phandle));
+	num_rmems = of_reserved_mem_region_count(np);
 	if (num_rmems <= 0) {
 		dev_err(dev, "device does not have reserved memory regions, ret = %d\n",
 			num_rmems);
@@ -1003,16 +1000,13 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)

 	/* use remaining reserved memory regions for static carveouts */
 	for (i = 0; i < num_rmems; i++) {
-		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
-		if (!rmem_np)
-			return -EINVAL;
+		struct resource res;

-		rmem = of_reserved_mem_lookup(rmem_np);
-		of_node_put(rmem_np);
-		if (!rmem)
-			return -EINVAL;
+		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
+		if (ret)
+			return ret;

-		kproc->rmem[i].bus_addr = rmem->base;
+		kproc->rmem[i].bus_addr = res.start;
 		/*
 		 * R5Fs do not have an MMU, but have a Region Address Translator
 		 * (RAT) module that provides a fixed entry translation between
@@ -1023,12 +1017,12 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
 		 * addresses/supported memory regions are restricted to 32-bit
 		 * bus addresses, and are identical
 		 */
-		kproc->rmem[i].dev_addr = (u32)rmem->base;
-		kproc->rmem[i].size = rmem->size;
-		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
+		kproc->rmem[i].dev_addr = (u32)res.start;
+		kproc->rmem[i].size = resource_size(&res);
+		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
 		if (!kproc->rmem[i].cpu_addr) {
-			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
-				i + 1, &rmem->base, &rmem->size);
+			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
+				i + 1, &res);
 			return -ENOMEM;
 		}

diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 5aeedeaf3c41..000eeadd5a01 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -460,49 +460,42 @@ static int add_mem_regions_carveout(struct rproc *rproc)
 {
 	struct rproc_mem_entry *rproc_mem;
 	struct zynqmp_r5_core *r5_core;
-	struct of_phandle_iterator it;
-	struct reserved_mem *rmem;
 	int i = 0;

 	r5_core = rproc->priv;

 	/* Register associated reserved memory regions */
-	of_phandle_iterator_init(&it, r5_core->np, "memory-region", NULL, 0);
+	while (1) {
+		int err;
+		struct resource res;

-	while (of_phandle_iterator_next(&it) == 0) {
-		rmem = of_reserved_mem_lookup(it.node);
-		if (!rmem) {
-			of_node_put(it.node);
-			dev_err(&rproc->dev, "unable to acquire memory-region\n");
-			return -EINVAL;
-		}
+		err = of_reserved_mem_region_to_resource(r5_core->np, i++, &res);
+		if (err)
+			return 0;

-		if (!strcmp(it.node->name, "vdev0buffer")) {
+		if (!strcmp(res.name, "vdev0buffer")) {
 			/* Init reserved memory for vdev buffer */
 			rproc_mem = rproc_of_resm_mem_entry_init(&rproc->dev, i,
-								 rmem->size,
-								 rmem->base,
-								 it.node->name);
+								 resource_size(&res),
+								 res.start,
+								 res.name);
 		} else {
 			/* Register associated reserved memory regions */
 			rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL,
-							 (dma_addr_t)rmem->base,
-							 rmem->size, rmem->base,
+							 (dma_addr_t)res.start,
+							 resource_size(&res), res.start,
 							 zynqmp_r5_mem_region_map,
 							 zynqmp_r5_mem_region_unmap,
-							 it.node->name);
+							 res.name);
 		}

-		if (!rproc_mem) {
-			of_node_put(it.node);
+		if (!rproc_mem)
 			return -ENOMEM;
-		}

 		rproc_add_carveout(rproc, rproc_mem);
-		rproc_coredump_add_segment(rproc, rmem->base, rmem->size);
+		rproc_coredump_add_segment(rproc, res.start, resource_size(&res));

-		dev_dbg(&rproc->dev, "reserved mem carveout %s addr=%llx, size=0x%llx",
-			it.node->name, rmem->base, rmem->size);
+		dev_dbg(&rproc->dev, "reserved mem carveout %pR\n", &res);
 		i++;
 	}

@@ -776,7 +769,6 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core)
 	struct device *dev = r5_core->dev;
 	struct rsc_tbl_data *rsc_data_va;
 	struct resource res_mem;
-	struct device_node *np;
 	int ret;

 	/*
@@ -786,14 +778,7 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core)
 	 * contains that data structure which holds resource table address, size
 	 * and some magic number to validate correct resource table entry.
 	 */
-	np = of_parse_phandle(r5_core->np, "memory-region", 0);
-	if (!np) {
-		dev_err(dev, "failed to get memory region dev node\n");
-		return -EINVAL;
-	}
-
-	ret = of_address_to_resource(np, 0, &res_mem);
-	of_node_put(np);
+	ret = of_reserved_mem_region_to_resource(r5_core->np, 0, &res_mem);
 	if (ret) {
 		dev_err(dev, "failed to get memory-region resource addr\n");
 		return -EINVAL;
--
2.47.2



From mhklinux at outlook.com  Mon Mar 17 16:51:52 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Mon, 17 Mar 2025 23:51:52 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 

This is part 2 of my review of this large patch.

[snipping what I already reviewed or decided to skip in part 1 of my review ]

> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> new file mode 100644
> index 000000000000..fed19aa80049
> --- /dev/null
> +++ b/drivers/hv/mshv_root_main.c
> @@ -0,0 +1,2329 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024, Microsoft Corporation.
> + *
> + * The main part of the mshv_root module, providing APIs to create
> + * and manage guest partitions.
> + *
> + * Authors: Microsoft Linux virtualization team
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/slab.h>
> +#include <linux/file.h>
> +#include <linux/anon_inodes.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/cpuhotplug.h>
> +#include <linux/random.h>
> +#include <asm/mshyperv.h>
> +#include <linux/hyperv.h>
> +#include <linux/notifier.h>
> +#include <linux/reboot.h>
> +#include <linux/kexec.h>
> +#include <linux/page-flags.h>
> +#include <linux/crash_dump.h>
> +#include <linux/panic_notifier.h>
> +#include <linux/vmalloc.h>
> +
> +#include "mshv_eventfd.h"
> +#include "mshv.h"
> +#include "mshv_root.h"
> +
> +/* TODO move this to mshyperv.h when needed outside driver */
> +static inline bool hv_parent_partition(void)
> +{
> +	return hv_root_partition();
> +}
> +
> +/* TODO move this to another file when debugfs code is added */
> +enum hv_stats_vp_counters {			/* HV_THREAD_COUNTER */
> +#if defined(CONFIG_X86)
> +	VpRootDispatchThreadBlocked			= 201,
> +#elif defined(CONFIG_ARM64)
> +	VpRootDispatchThreadBlocked			= 94,
> +#endif
> +	VpStatsMaxCounter
> +};

Where do these "magic" numbers come from?  Are they matching something
in the Hyper-V host?

> +
> +struct hv_stats_page {
> +	union {
> +		u64 vp_cntrs[VpStatsMaxCounter];		/* VP counters */
> +		u8 data[HV_HYP_PAGE_SIZE];
> +	};
> +} __packed;
> +
> +struct mshv_root mshv_root = {};

Initializer is unnecessary for global variables. They are already set to zero.

> +
> +enum hv_scheduler_type hv_scheduler_type;
> +
> +/* Once we implement the fast extended hypercall ABI they can go away. */
> +static void __percpu **root_scheduler_input;
> +static void __percpu **root_scheduler_output;

The __percpu is probably in the wrong place like mentioned in earlier
patches in this series.

> +
> +static long mshv_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
> +static int mshv_dev_open(struct inode *inode, struct file *filp);
> +static int mshv_dev_release(struct inode *inode, struct file *filp);
> +static int mshv_vp_release(struct inode *inode, struct file *filp);
> +static long mshv_vp_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
> +static int mshv_partition_release(struct inode *inode, struct file *filp);
> +static long mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
> +static int mshv_vp_mmap(struct file *file, struct vm_area_struct *vma);
> +static vm_fault_t mshv_vp_fault(struct vm_fault *vmf);
> +static int mshv_init_async_handler(struct mshv_partition *partition);
> +static void mshv_async_hvcall_handler(void *data, u64 *status);
> +
> +static const struct vm_operations_struct mshv_vp_vm_ops = {
> +	.fault = mshv_vp_fault,
> +};
> +
> +static const struct file_operations mshv_vp_fops = {
> +	.owner = THIS_MODULE,
> +	.release = mshv_vp_release,
> +	.unlocked_ioctl = mshv_vp_ioctl,
> +	.llseek = noop_llseek,
> +	.mmap = mshv_vp_mmap,
> +};
> +
> +static const struct file_operations mshv_partition_fops = {
> +	.owner = THIS_MODULE,
> +	.release = mshv_partition_release,
> +	.unlocked_ioctl = mshv_partition_ioctl,
> +	.llseek = noop_llseek,
> +};
> +
> +static const struct file_operations mshv_dev_fops = {
> +	.owner = THIS_MODULE,
> +	.open = mshv_dev_open,
> +	.release = mshv_dev_release,
> +	.unlocked_ioctl = mshv_dev_ioctl,
> +	.llseek = noop_llseek,
> +};
> +
> +static struct miscdevice mshv_dev = {
> +	.minor = MISC_DYNAMIC_MINOR,
> +	.name = "mshv",
> +	.fops = &mshv_dev_fops,
> +	.mode = 0600,
> +};
> +
> +/*
> + * Only allow hypercalls that have a u64 partition id as the first member of
> + * the input structure.
> + * These are sorted by value.
> + */
> +static u16 mshv_passthru_hvcalls[] = {
> +	HVCALL_GET_PARTITION_PROPERTY,
> +	HVCALL_SET_PARTITION_PROPERTY,
> +	HVCALL_INSTALL_INTERCEPT,
> +	HVCALL_GET_VP_REGISTERS,
> +	HVCALL_SET_VP_REGISTERS,
> +	HVCALL_TRANSLATE_VIRTUAL_ADDRESS,
> +	HVCALL_CLEAR_VIRTUAL_INTERRUPT,
> +	HVCALL_REGISTER_INTERCEPT_RESULT,
> +	HVCALL_ASSERT_VIRTUAL_INTERRUPT,
> +	HVCALL_GET_GPA_PAGES_ACCESS_STATES,
> +	HVCALL_SIGNAL_EVENT_DIRECT,
> +	HVCALL_POST_MESSAGE_DIRECT,
> +	HVCALL_GET_VP_CPUID_VALUES,
> +};
> +
> +static bool mshv_hvcall_is_async(u16 code)
> +{
> +	switch (code) {
> +	case HVCALL_SET_PARTITION_PROPERTY:
> +		return true;
> +	default:
> +		break;
> +	}
> +	return false;
> +}
> +
> +static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition,
> +				      bool partition_locked,
> +				      void __user *user_args)
> +{
> +	u64 status;
> +	int ret, i;

'ret' should be initialized to 0. There's a path through this function that
never sets 'ret' and the return value would be stack garbage.

> +	bool is_async;
> +	struct mshv_root_hvcall args;
> +	struct page *page;
> +	unsigned int pages_order;
> +	void *input_pg = NULL;
> +	void *output_pg = NULL;
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	if (args.status || !args.in_ptr || args.in_sz < sizeof(u64) ||
> +	    mshv_field_nonzero(args, rsvd) || args.in_sz > HV_HYP_PAGE_SIZE)
> +		return -EINVAL;
> +
> +	if (args.out_ptr && (!args.out_sz || args.out_sz > HV_HYP_PAGE_SIZE))
> +		return -EINVAL;
> +
> +	for (i = 0; i < ARRAY_SIZE(mshv_passthru_hvcalls); ++i)
> +		if (args.code == mshv_passthru_hvcalls[i])
> +			break;
> +
> +	if (i >= ARRAY_SIZE(mshv_passthru_hvcalls))
> +		return -EINVAL;
> +
> +	is_async = mshv_hvcall_is_async(args.code);
> +	if (is_async) {
> +		/* async hypercalls can only be called from partition fd */
> +		if (!partition_locked)
> +			return -EINVAL;
> +		ret = mshv_init_async_handler(partition);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	pages_order = args.out_ptr ? 1 : 0;
> +	page = alloc_pages(GFP_KERNEL, pages_order);
> +	if (!page)
> +		return -ENOMEM;
> +	input_pg = page_address(page);
> +
> +	if (args.out_ptr)
> +		output_pg = (char *)input_pg + PAGE_SIZE;
> +	else
> +		output_pg = NULL;
> +
> +	if (copy_from_user(input_pg, (void __user *)args.in_ptr,
> +			   args.in_sz)) {
> +		ret = -EFAULT;
> +		goto free_pages_out;
> +	}
> +
> +	/*
> +	 * NOTE: This only works because all the allowed hypercalls' input
> +	 * structs begin with a u64 partition_id field.
> +	 */
> +	*(u64 *)input_pg = partition->pt_id;
> +
> +	if (args.reps)
> +		status = hv_do_rep_hypercall(args.code, args.reps, 0,
> +					     input_pg, output_pg);
> +	else
> +		status = hv_do_hypercall(args.code, input_pg, output_pg);
> +
> +	if (hv_result(status) == HV_STATUS_CALL_PENDING) {
> +		if (is_async) {
> +			mshv_async_hvcall_handler(partition, &status);
> +		} else { /* Paranoia check. This shouldn't happen! */
> +			ret = -EBADFD;
> +			goto free_pages_out;
> +		}
> +	}
> +
> +	if (hv_result(status) == HV_STATUS_INSUFFICIENT_MEMORY) {
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE, partition->pt_id, 1);
> +		if (!ret)
> +			ret = -EAGAIN;
> +	} else if (!hv_result_success(status)) {
> +		ret = hv_result_to_errno(status);
> +	}
> +
> +	/*
> +	 * Always return the status and output data regardless of result.
> +	 * The VMM may need it to determine how to proceed. E.g. the status may
> +	 * contain the number of reps completed if a rep hypercall partially
> +	 * succeeded.
> +	 */
> +	args.status = hv_result(status);
> +	args.reps = args.reps ? hv_repcomp(status) : 0;
> +	if (copy_to_user(user_args, &args, sizeof(args)))
> +		ret = -EFAULT;
> +
> +	if (output_pg &&
> +	    copy_to_user((void __user *)args.out_ptr, output_pg, args.out_sz))
> +		ret = -EFAULT;
> +
> +free_pages_out:
> +	free_pages((unsigned long)input_pg, pages_order);
> +
> +	return ret;
> +}
> +
> +static inline bool is_ghcb_mapping_available(void)
> +{
> +#if IS_ENABLED(CONFIG_X86_64)
> +	return ms_hyperv.ext_features & HV_VP_GHCB_ROOT_MAPPING_AVAILABLE;
> +#else
> +	return 0;
> +#endif
> +}
> +
> +static int mshv_get_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +				 struct hv_register_assoc *registers)
> +{
> +	union hv_input_vtl input_vtl;
> +
> +	input_vtl.as_uint8 = 0;
> +	return hv_call_get_vp_registers(vp_index, partition_id,
> +					count, input_vtl, registers);
> +}
> +
> +static int mshv_set_vp_registers(u32 vp_index, u64 partition_id, u16 count,
> +				 struct hv_register_assoc *registers)
> +{
> +	union hv_input_vtl input_vtl;
> +
> +	input_vtl.as_uint8 = 0;
> +	return hv_call_set_vp_registers(vp_index, partition_id,
> +					count, input_vtl, registers);
> +}
> +
> +/*
> + * Explicit guest vCPU suspend is asynchronous by nature (as it is requested by
> + * dom0 vCPU for guest vCPU) and thus it can race with "intercept" suspend,
> + * done by the hypervisor.
> + * "Intercept" suspend leads to asynchronous message delivery to dom0 which
> + * should be awaited to keep the VP loop consistent (i.e. no message pending
> + * upon VP resume).
> + * VP intercept suspend can't be done when the VP is explicitly suspended
> + * already, and thus can be only two possible race scenarios:
> + *   1. implicit suspend bit set -> explicit suspend bit set -> message sent
> + *   2. implicit suspend bit set -> message sent -> explicit suspend bit set
> + * Checking for implicit suspend bit set after explicit suspend request has
> + * succeeded in either case allows us to reliably identify, if there is a
> + * message to receive and deliver to VMM.
> + */
> +static long

For this function, why is the return type "long" instead of "int"?  Same
question for several other functions below.  "long" works, but it's another
case of being gratuitously atypical -- unless there's a reason.

> +mshv_suspend_vp(const struct mshv_vp *vp, bool *message_in_flight)
> +{
> +	struct hv_register_assoc explicit_suspend = {
> +		.name = HV_REGISTER_EXPLICIT_SUSPEND
> +	};
> +	struct hv_register_assoc intercept_suspend = {
> +		.name = HV_REGISTER_INTERCEPT_SUSPEND
> +	};
> +	union hv_explicit_suspend_register *es =
> +		&explicit_suspend.value.explicit_suspend;
> +	union hv_intercept_suspend_register *is =
> +		&intercept_suspend.value.intercept_suspend;
> +	int ret;
> +
> +	es->suspended = 1;
> +
> +	ret = mshv_set_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    1, &explicit_suspend);
> +	if (ret) {
> +		vp_err(vp, "Failed to explicitly suspend vCPU\n");
> +		return ret;
> +	}
> +
> +	ret = mshv_get_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    1, &intercept_suspend);
> +	if (ret) {
> +		vp_err(vp, "Failed to get intercept suspend state\n");
> +		return ret;
> +	}
> +
> +	*message_in_flight = is->suspended;
> +
> +	return 0;
> +}
> +
> +/*
> + * This function is used when VPs are scheduled by the hypervisor's
> + * scheduler.
> + *
> + * Caller has to make sure the registers contain cleared
> + * HV_REGISTER_INTERCEPT_SUSPEND and HV_REGISTER_EXPLICIT_SUSPEND registers
> + * exactly in this order (the hypervisor clears them sequentially) to avoid
> + * potential invalid clearing a newly arrived HV_REGISTER_INTERCEPT_SUSPEND
> + * after VP is released from HV_REGISTER_EXPLICIT_SUSPEND in case of the
> + * opposite order.
> + */
> +static long mshv_run_vp_with_hyp_scheduler(struct mshv_vp *vp)
> +{
> +	long ret;
> +	struct hv_register_assoc suspend_regs[2] = {
> +			{ .name = HV_REGISTER_INTERCEPT_SUSPEND },
> +			{ .name = HV_REGISTER_EXPLICIT_SUSPEND }
> +	};
> +	size_t count = ARRAY_SIZE(suspend_regs);
> +
> +	/* Resume VP execution */
> +	ret = mshv_set_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    count, suspend_regs);
> +	if (ret) {
> +		vp_err(vp, "Failed to resume vp execution. %lx\n", ret);
> +		return ret;
> +	}
> +
> +	ret = wait_event_interruptible(vp->run.vp_suspend_queue,
> +				       vp->run.kicked_by_hv == 1);
> +	if (ret) {
> +		bool message_in_flight;
> +
> +		/*
> +		 * Otherwise the waiting was interrupted by a signal: suspend
> +		 * the vCPU explicitly and copy message in flight (if any).
> +		 */
> +		ret = mshv_suspend_vp(vp, &message_in_flight);
> +		if (ret)
> +			return ret;
> +
> +		/* Return if no message in flight */
> +		if (!message_in_flight)
> +			return -EINTR;
> +
> +		/* Wait for the message in flight. */
> +		wait_event(vp->run.vp_suspend_queue, vp->run.kicked_by_hv == 1);
> +	}
> +
> +	/*
> +	 * Reset the flag to make the wait_event call above work
> +	 * next time.
> +	 */
> +	vp->run.kicked_by_hv = 0;
> +
> +	return 0;
> +}
> +
> +static int
> +mshv_vp_dispatch(struct mshv_vp *vp, u32 flags,
> +		 struct hv_output_dispatch_vp *res)
> +{
> +	struct hv_input_dispatch_vp *input;
> +	struct hv_output_dispatch_vp *output;
> +	u64 status;
> +
> +	preempt_disable();
> +	input = *this_cpu_ptr(root_scheduler_input);
> +	output = *this_cpu_ptr(root_scheduler_output);
> +
> +	memset(input, 0, sizeof(*input));
> +	memset(output, 0, sizeof(*output));
> +
> +	input->partition_id = vp->vp_partition->pt_id;
> +	input->vp_index = vp->vp_index;
> +	input->time_slice = 0; /* Run forever until something happens */
> +	input->spec_ctrl = 0; /* TODO: set sensible flags */
> +	input->flags = flags;
> +
> +	vp->run.flags.root_sched_dispatched = 1;
> +	status = hv_do_hypercall(HVCALL_DISPATCH_VP, input, output);
> +	vp->run.flags.root_sched_dispatched = 0;
> +
> +	*res = *output;
> +	preempt_enable();
> +
> +	if (!hv_result_success(status))
> +		vp_err(vp, "%s: status %s\n", __func__,
> +		       hv_result_to_string(status));
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +static int
> +mshv_vp_clear_explicit_suspend(struct mshv_vp *vp)
> +{
> +	struct hv_register_assoc explicit_suspend = {
> +		.name = HV_REGISTER_EXPLICIT_SUSPEND,
> +		.value.explicit_suspend.suspended = 0,
> +	};
> +	int ret;
> +
> +	ret = mshv_set_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    1, &explicit_suspend);
> +
> +	if (ret)
> +		vp_err(vp, "Failed to unsuspend\n");
> +
> +	return ret;
> +}
> +
> +#if IS_ENABLED(CONFIG_X86_64)
> +static u64 mshv_vp_interrupt_pending(struct mshv_vp *vp)
> +{
> +	if (!vp->vp_register_page)
> +		return 0;
> +	return vp->vp_register_page->interrupt_vectors.as_uint64;
> +}
> +#else
> +static u64 mshv_vp_interrupt_pending(struct mshv_vp *vp)
> +{
> +	return 0;
> +}
> +#endif
> +
> +static bool mshv_vp_dispatch_thread_blocked(struct mshv_vp *vp)
> +{
> +	struct hv_stats_page **stats = vp->vp_stats_pages;
> +	u64 *self_vp_cntrs = stats[HV_STATS_AREA_SELF]->vp_cntrs;
> +	u64 *parent_vp_cntrs = stats[HV_STATS_AREA_PARENT]->vp_cntrs;
> +
> +	if (self_vp_cntrs[VpRootDispatchThreadBlocked])
> +		return self_vp_cntrs[VpRootDispatchThreadBlocked];
> +	return parent_vp_cntrs[VpRootDispatchThreadBlocked];
> +}
> +
> +static int
> +mshv_vp_wait_for_hv_kick(struct mshv_vp *vp)
> +{
> +	int ret;
> +
> +	ret = wait_event_interruptible(vp->run.vp_suspend_queue,
> +				       (vp->run.kicked_by_hv == 1 &&
> +					!mshv_vp_dispatch_thread_blocked(vp)) ||
> +				       mshv_vp_interrupt_pending(vp));
> +	if (ret)
> +		return -EINTR;
> +
> +	vp->run.flags.root_sched_blocked = 0;
> +	vp->run.kicked_by_hv = 0;
> +
> +	return 0;
> +}
> +
> +static int mshv_pre_guest_mode_work(struct mshv_vp *vp)
> +{
> +	const ulong work_flags = _TIF_NOTIFY_SIGNAL | _TIF_SIGPENDING |
> +				 _TIF_NEED_RESCHED  | _TIF_NOTIFY_RESUME;
> +	ulong th_flags;
> +
> +	th_flags = read_thread_flags();
> +	while (th_flags & work_flags) {
> +		int ret;
> +
> +		/* nb: following will call schedule */
> +		ret = mshv_do_pre_guest_mode_work(th_flags);
> +
> +		if (ret)
> +			return ret;
> +
> +		th_flags = read_thread_flags();
> +	}
> +
> +	return 0;
> +}
> +
> +/* Must be called with interrupts enabled */
> +static long mshv_run_vp_with_root_scheduler(struct mshv_vp *vp)
> +{
> +	long ret;
> +
> +	if (vp->run.flags.root_sched_blocked) {
> +		/*
> +		 * Dispatch state of this VP is blocked. Need to wait
> +		 * for the hypervisor to clear the blocked state before
> +		 * dispatching it.
> +		 */
> +		ret = mshv_vp_wait_for_hv_kick(vp);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	do {
> +		u32 flags = 0;
> +		struct hv_output_dispatch_vp output;
> +
> +		ret = mshv_pre_guest_mode_work(vp);
> +		if (ret)
> +			break;
> +
> +		if (vp->run.flags.intercept_suspend)
> +			flags |= HV_DISPATCH_VP_FLAG_CLEAR_INTERCEPT_SUSPEND;
> +
> +		if (mshv_vp_interrupt_pending(vp))
> +			flags |= HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION;
> +
> +		ret = mshv_vp_dispatch(vp, flags, &output);
> +		if (ret)
> +			break;
> +
> +		vp->run.flags.intercept_suspend = 0;
> +
> +		if (output.dispatch_state == HV_VP_DISPATCH_STATE_BLOCKED) {
> +			if (output.dispatch_event ==
> +						HV_VP_DISPATCH_EVENT_SUSPEND) {
> +				/*
> +				 * TODO: remove the warning once VP canceling
> +				 *	 is supported
> +				 */
> +				WARN_ONCE(atomic64_read(&vp->run.vp_signaled_count),
> +					  "%s: vp#%d: unexpected explicit suspend\n",
> +					  __func__, vp->vp_index);
> +				/*
> +				 * Need to clear explicit suspend before
> +				 * dispatching.
> +				 * Explicit suspend is either:
> +				 * - set right after the first VP dispatch or
> +				 * - set explicitly via hypercall
> +				 * Since the latter case is not yet supported,
> +				 * simply clear it here.
> +				 */
> +				ret = mshv_vp_clear_explicit_suspend(vp);
> +				if (ret)
> +					break;
> +
> +				ret = mshv_vp_wait_for_hv_kick(vp);
> +				if (ret)
> +					break;
> +			} else {
> +				vp->run.flags.root_sched_blocked = 1;
> +				ret = mshv_vp_wait_for_hv_kick(vp);
> +				if (ret)
> +					break;
> +			}
> +		} else {
> +			/* HV_VP_DISPATCH_STATE_READY */
> +			if (output.dispatch_event ==
> +						HV_VP_DISPATCH_EVENT_INTERCEPT)
> +				vp->run.flags.intercept_suspend = 1;
> +		}
> +	} while (!vp->run.flags.intercept_suspend);
> +
> +	return ret;
> +}
> +
> +static_assert(sizeof(struct hv_message) <= MSHV_RUN_VP_BUF_SZ,
> +	      "sizeof(struct hv_message) must not exceed MSHV_RUN_VP_BUF_SZ");
> +
> +static long mshv_vp_ioctl_run_vp(struct mshv_vp *vp, void __user *ret_msg)
> +{
> +	long rc;
> +	char *schednm;
> +
> +	schednm = hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT ? "root" : "hv";
> +
> +	if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT)
> +		rc = mshv_run_vp_with_root_scheduler(vp);
> +	else
> +		rc = mshv_run_vp_with_hyp_scheduler(vp);
> +
> +	if (rc)
> +		return rc;
> +
> +	if (copy_to_user(ret_msg, vp->vp_intercept_msg_page,
> +			 sizeof(struct hv_message)))
> +		rc = -EFAULT;
> +
> +	return rc;
> +}
> +
> +static int
> +mshv_vp_ioctl_get_set_state_pfn(struct mshv_vp *vp,
> +				struct hv_vp_state_data state_data,
> +				unsigned long user_pfn, size_t page_count,
> +				bool is_set)
> +{
> +	int completed, ret = 0;
> +	unsigned long check;
> +	struct page **pages;
> +
> +	if (page_count > INT_MAX)
> +		return -EINVAL;
> +	/*
> +	 * Check the arithmetic for wraparound/overflow.
> +	 * The last page address in the buffer is:
> +	 * (user_pfn + (page_count - 1)) * PAGE_SIZE
> +	 */
> +	if (check_add_overflow(user_pfn, (page_count - 1), &check))
> +		return -EOVERFLOW;
> +	if (check_mul_overflow(check, PAGE_SIZE, &check))
> +		return -EOVERFLOW;
> +
> +	/* Pin user pages so hypervisor can copy directly to them */
> +	pages = kcalloc(page_count, sizeof(struct page *), GFP_KERNEL);
> +	if (!pages)
> +		return -ENOMEM;
> +
> +	for (completed = 0; completed < page_count; completed += ret) {
> +		unsigned long user_addr = (user_pfn + completed) * PAGE_SIZE;
> +		int remaining = page_count - completed;
> +
> +		ret = pin_user_pages_fast(user_addr, remaining, FOLL_WRITE,
> +					  &pages[completed]);
> +		if (ret < 0) {
> +			vp_err(vp, "%s: Failed to pin user pages error %i\n",
> +			       __func__, ret);
> +			goto unpin_pages;
> +		}
> +	}
> +
> +	if (is_set)
> +		ret = hv_call_set_vp_state(vp->vp_index,
> +					   vp->vp_partition->pt_id,
> +					   state_data, page_count, pages,
> +					   0, NULL);
> +	else
> +		ret = hv_call_get_vp_state(vp->vp_index,
> +					   vp->vp_partition->pt_id,
> +					   state_data, page_count, pages,
> +					   NULL);
> +
> +unpin_pages:
> +	unpin_user_pages(pages, completed);
> +	kfree(pages);
> +	return ret;
> +}
> +
> +static long
> +mshv_vp_ioctl_get_set_state(struct mshv_vp *vp,
> +			    struct mshv_get_set_vp_state __user *user_args,
> +			    bool is_set)
> +{
> +	struct mshv_get_set_vp_state args;
> +	long ret = 0;
> +	union hv_output_get_vp_state vp_state;
> +	u32 data_sz;
> +	struct hv_vp_state_data state_data = {};
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	if (args.type >= MSHV_VP_STATE_COUNT || mshv_field_nonzero(args, rsvd) ||
> +	    !args.buf_sz || !PAGE_ALIGNED(args.buf_sz) ||
> +	    !PAGE_ALIGNED(args.buf_ptr))
> +		return -EINVAL;
> +
> +	if (!access_ok((void __user *)args.buf_ptr, args.buf_sz))
> +		return -EFAULT;
> +
> +	switch (args.type) {
> +	case MSHV_VP_STATE_LAPIC:
> +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
> +		data_sz = HV_HYP_PAGE_SIZE;
> +		break;
> +	case MSHV_VP_STATE_XSAVE:

Just FYI, you can put a semicolon after the colon on the above line, which
adds a null statement, and then the C compiler will accept the definition
of local variable data_sz_64 without needing the odd-looking braces. 

See https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement/19830820

I learn something new every day! :-)

> +	{
> +		u64 data_sz_64;
> +
> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
> +						     HV_PARTITION_PROPERTY_XSAVE_STATES,
> +						     &state_data.xsave.states.as_uint64);
> +		if (ret)
> +			return ret;
> +
> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
> +						     HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE,
> +						     &data_sz_64);
> +		if (ret)
> +			return ret;
> +
> +		data_sz = (u32)data_sz_64;
> +		state_data.xsave.flags = 0;
> +		/* Always request legacy states */
> +		state_data.xsave.states.legacy_x87 = 1;
> +		state_data.xsave.states.legacy_sse = 1;
> +		state_data.type = HV_GET_SET_VP_STATE_XSAVE;
> +		break;
> +	}
> +	case MSHV_VP_STATE_SIMP:
> +		state_data.type = HV_GET_SET_VP_STATE_SIM_PAGE;
> +		data_sz = HV_HYP_PAGE_SIZE;
> +		break;
> +	case MSHV_VP_STATE_SIEFP:
> +		state_data.type = HV_GET_SET_VP_STATE_SIEF_PAGE;
> +		data_sz = HV_HYP_PAGE_SIZE;
> +		break;
> +	case MSHV_VP_STATE_SYNTHETIC_TIMERS:
> +		state_data.type = HV_GET_SET_VP_STATE_SYNTHETIC_TIMERS;
> +		data_sz = sizeof(vp_state.synthetic_timers_state);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (copy_to_user(&user_args->buf_sz, &data_sz, sizeof(user_args->buf_sz)))
> +		return -EFAULT;
> +
> +	if (data_sz > args.buf_sz)
> +		return -EINVAL;
> +
> +	/* If the data is transmitted via pfns, delegate to helper */
> +	if (state_data.type & HV_GET_SET_VP_STATE_TYPE_PFN) {
> +		unsigned long user_pfn = PFN_DOWN(args.buf_ptr);
> +		size_t page_count = PFN_DOWN(args.buf_sz);
> +
> +		return mshv_vp_ioctl_get_set_state_pfn(vp, state_data, user_pfn,
> +						       page_count, is_set);
> +	}
> +
> +	/* Paranoia check - this shouldn't happen! */
> +	if (data_sz > sizeof(vp_state)) {
> +		vp_err(vp, "Invalid vp state data size!\n");
> +		return -EINVAL;
> +	}

I don't understand the above check.  sizeof(vp_state) is relatively small since
it is effectively sizeof(hv_synthetic_timers_state), which is 200 bytes if I've
done the arithmetic correctly. But data_sz could be a full page (4096 bytes)
for the LAPIC, SIMP, and SIEFP cases, and the check would cause an error to
be returned.

> +
> +	if (is_set) {
> +		if (copy_from_user(&vp_state, (__user void *)args.buf_ptr, data_sz))
> +			return -EFAULT;
> +
> +		return hv_call_set_vp_state(vp->vp_index,
> +					    vp->vp_partition->pt_id,
> +					    state_data, 0, NULL,
> +					    sizeof(vp_state), (u8 *)&vp_state);

This is one of the cases where data from user space gets passed directly to
the hypercall. So user space is responsible for ensuring that reserved fields
are zero'ed and for otherwise ensuring a proper hypercall input. I just
wonder if user space really does this correctly.

> +	}
> +
> +	ret = hv_call_get_vp_state(vp->vp_index, vp->vp_partition->pt_id,
> +				   state_data, 0, NULL, &vp_state);
> +	if (ret)
> +		return ret;
> +
> +	if (copy_to_user((void __user *)args.buf_ptr, &vp_state, data_sz))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static long
> +mshv_vp_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> +{
> +	struct mshv_vp *vp = filp->private_data;
> +	long r = -ENOTTY;
> +
> +	if (mutex_lock_killable(&vp->vp_mutex))
> +		return -EINTR;
> +
> +	switch (ioctl) {
> +	case MSHV_RUN_VP:
> +		r = mshv_vp_ioctl_run_vp(vp, (void __user *)arg);
> +		break;
> +	case MSHV_GET_VP_STATE:
> +		r = mshv_vp_ioctl_get_set_state(vp, (void __user *)arg, false);
> +		break;
> +	case MSHV_SET_VP_STATE:
> +		r = mshv_vp_ioctl_get_set_state(vp, (void __user *)arg, true);
> +		break;
> +	case MSHV_ROOT_HVCALL:
> +		r = mshv_ioctl_passthru_hvcall(vp->vp_partition, false,
> +					       (void __user *)arg);
> +		break;
> +	default:
> +		vp_warn(vp, "Invalid ioctl: %#x\n", ioctl);
> +		break;
> +	}
> +	mutex_unlock(&vp->vp_mutex);
> +
> +	return r;
> +}
> +
> +static vm_fault_t mshv_vp_fault(struct vm_fault *vmf)
> +{
> +	struct mshv_vp *vp = vmf->vma->vm_file->private_data;
> +
> +	switch (vmf->vma->vm_pgoff) {
> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
> +		vmf->page = virt_to_page(vp->vp_register_page);
> +		break;
> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
> +		vmf->page = virt_to_page(vp->vp_intercept_msg_page);
> +		break;
> +	case MSHV_VP_MMAP_OFFSET_GHCB:
> +		if (is_ghcb_mapping_available())
> +			vmf->page = virt_to_page(vp->vp_ghcb_page);
> +		break;

If there's no GHCB mapping available, execution just continues with
vmf->page not set. Won't the later get_page() call fail? Perhaps this
should fail if there's no GHCB mapping available. Or maybe there's
more about how this works that I'm ignorant of. :-)

> +	default:
> +		return -EINVAL;
> +	}
> +
> +	get_page(vmf->page);
> +
> +	return 0;
> +}
> +
> +static int mshv_vp_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct mshv_vp *vp = file->private_data;
> +
> +	switch (vma->vm_pgoff) {
> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
> +		if (!vp->vp_register_page)
> +			return -ENODEV;
> +		break;
> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
> +		if (!vp->vp_intercept_msg_page)
> +			return -ENODEV;
> +		break;
> +	case MSHV_VP_MMAP_OFFSET_GHCB:
> +		if (is_ghcb_mapping_available() && !vp->vp_ghcb_page)
> +			return -ENODEV;
> +		break;

Again, if no GHCB mapping is available, should this return success?

> +	default:
> +		return -EINVAL;
> +	}
> +
> +	vma->vm_ops = &mshv_vp_vm_ops;
> +	return 0;
> +}
> +
> +static int
> +mshv_vp_release(struct inode *inode, struct file *filp)
> +{
> +	struct mshv_vp *vp = filp->private_data;
> +
> +	/* Rest of VP cleanup happens in destroy_partition() */
> +	mshv_partition_put(vp->vp_partition);
> +	return 0;
> +}
> +
> +static void mshv_vp_stats_unmap(u64 partition_id, u32 vp_index)
> +{
> +	union hv_stats_object_identity identity = {
> +		.vp.partition_id = partition_id,
> +		.vp.vp_index = vp_index,
> +	};
> +
> +	identity.vp.stats_area_type = HV_STATS_AREA_SELF;
> +	hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity);
> +
> +	identity.vp.stats_area_type = HV_STATS_AREA_PARENT;
> +	hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity);
> +}
> +
> +static int mshv_vp_stats_map(u64 partition_id, u32 vp_index,
> +			     void *stats_pages[])
> +{
> +	union hv_stats_object_identity identity = {
> +		.vp.partition_id = partition_id,
> +		.vp.vp_index = vp_index,
> +	};
> +	int err;
> +
> +	identity.vp.stats_area_type = HV_STATS_AREA_SELF;
> +	err = hv_call_map_stat_page(HV_STATS_OBJECT_VP, &identity,
> +				    &stats_pages[HV_STATS_AREA_SELF]);
> +	if (err)
> +		return err;
> +
> +	identity.vp.stats_area_type = HV_STATS_AREA_PARENT;
> +	err = hv_call_map_stat_page(HV_STATS_OBJECT_VP, &identity,
> +				    &stats_pages[HV_STATS_AREA_PARENT]);
> +	if (err)
> +		goto unmap_self;
> +
> +	return 0;
> +
> +unmap_self:
> +	identity.vp.stats_area_type = HV_STATS_AREA_SELF;
> +	hv_call_unmap_stat_page(HV_STATS_OBJECT_VP, &identity);
> +	return err;
> +}
> +
> +static long
> +mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
> +			       void __user *arg)
> +{
> +	struct mshv_create_vp args;
> +	struct mshv_vp *vp;
> +	struct page *intercept_message_page, *register_page, *ghcb_page;
> +	void *stats_pages[2];
> +	long ret;
> +	union hv_input_vtl input_vtl;
> +
> +	if (copy_from_user(&args, arg, sizeof(args)))
> +		return -EFAULT;
> +
> +	if (args.vp_index >= MSHV_MAX_VPS)
> +		return -EINVAL;
> +
> +	if (partition->pt_vp_array[args.vp_index])
> +		return -EEXIST;
> +
> +	ret = hv_call_create_vp(NUMA_NO_NODE, partition->pt_id, args.vp_index,
> +				0 /* Only valid for root partition VPs */);
> +	if (ret)
> +		return ret;
> +
> +	input_vtl.as_uint8 = 0;

I see eight occurrences in this source code file where the above statement
occurs and there is no further modification. Perhaps declare a static
variable that is initialized properly, and use it as the input parameter to the
various functions.  A second static variable could have the use_target_vtl = 1
setting that is needed in three places.

> +	ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> +					HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> +					input_vtl,
> +					&intercept_message_page);
> +	if (ret)
> +		goto destroy_vp;
> +
> +	if (!mshv_partition_encrypted(partition)) {
> +		input_vtl.as_uint8 = 0;
> +		ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> +						HV_VP_STATE_PAGE_REGISTERS,
> +						input_vtl,
> +						&register_page);
> +		if (ret)
> +			goto unmap_intercept_message_page;
> +	}
> +
> +	if (mshv_partition_encrypted(partition) &&
> +	    is_ghcb_mapping_available()) {
> +		input_vtl.as_uint8 = 0;
> +		input_vtl.use_target_vtl = 1;
> +		input_vtl.target_vtl = HV_NORMAL_VTL;
> +		ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> +						HV_VP_STATE_PAGE_GHCB,
> +						input_vtl,
> +						&ghcb_page);
> +		if (ret)
> +			goto unmap_register_page;
> +	}
> +
> +	if (hv_parent_partition()) {
> +		ret = mshv_vp_stats_map(partition->pt_id, args.vp_index,
> +					stats_pages);
> +		if (ret)
> +			goto unmap_ghcb_page;
> +	}
> +
> +	vp = kzalloc(sizeof(*vp), GFP_KERNEL);
> +	if (!vp)
> +		goto unmap_stats_pages;
> +
> +	vp->vp_partition = mshv_partition_get(partition);
> +	if (!vp->vp_partition) {
> +		ret = -EBADF;
> +		goto free_vp;
> +	}
> +
> +	mutex_init(&vp->vp_mutex);
> +	init_waitqueue_head(&vp->run.vp_suspend_queue);
> +	atomic64_set(&vp->run.vp_signaled_count, 0);
> +
> +	vp->vp_index = args.vp_index;
> +	vp->vp_intercept_msg_page = page_to_virt(intercept_message_page);
> +	if (!mshv_partition_encrypted(partition))
> +		vp->vp_register_page = page_to_virt(register_page);
> +
> +	if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available())
> +		vp->vp_ghcb_page = page_to_virt(ghcb_page);
> +
> +	if (hv_parent_partition())
> +		memcpy(vp->vp_stats_pages, stats_pages, sizeof(stats_pages));
> +
> +	/*
> +	 * Keep anon_inode_getfd last: it installs fd in the file struct and
> +	 * thus makes the state accessible in user space.
> +	 */
> +	ret = anon_inode_getfd("mshv_vp", &mshv_vp_fops, vp,
> +			       O_RDWR | O_CLOEXEC);
> +	if (ret < 0)
> +		goto put_partition;
> +
> +	/* already exclusive with the partition mutex for all ioctls */
> +	partition->pt_vp_count++;
> +	partition->pt_vp_array[args.vp_index] = vp;
> +
> +	return ret;
> +
> +put_partition:
> +	mshv_partition_put(partition);
> +free_vp:
> +	kfree(vp);
> +unmap_stats_pages:
> +	if (hv_parent_partition())
> +		mshv_vp_stats_unmap(partition->pt_id, args.vp_index);
> +unmap_ghcb_page:
> +	if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) {
> +		input_vtl.as_uint8 = 0;
> +		input_vtl.use_target_vtl = 1;
> +		input_vtl.target_vtl = HV_NORMAL_VTL;
> +
> +		hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> +					    HV_VP_STATE_PAGE_GHCB, input_vtl);
> +	}
> +unmap_register_page:
> +	if (!mshv_partition_encrypted(partition)) {
> +		input_vtl.as_uint8 = 0;
> +
> +		hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> +					    HV_VP_STATE_PAGE_REGISTERS,
> +					    input_vtl);
> +	}
> +unmap_intercept_message_page:
> +	input_vtl.as_uint8 = 0;
> +	hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> +				    HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> +				    input_vtl);
> +destroy_vp:
> +	hv_call_delete_vp(partition->pt_id, args.vp_index);
> +	return ret;
> +}
> +
> +static int mshv_init_async_handler(struct mshv_partition *partition)
> +{
> +	if (completion_done(&partition->async_hypercall)) {
> +		pt_err(partition,
> +		       "Cannot issue another async hypercall, while another one in progress!\n");

Two uses of word "another" in the error message is redundant.  Perhaps

	"Cannot issue async hypercall while another one is in progress!"

> +		return -EPERM;
> +	}
> +
> +	reinit_completion(&partition->async_hypercall);
> +	return 0;
> +}
> +
> +static void mshv_async_hvcall_handler(void *data, u64 *status)
> +{
> +	struct mshv_partition *partition = data;
> +
> +	wait_for_completion(&partition->async_hypercall);
> +	pt_dbg(partition, "Async hypercall completed!\n");
> +
> +	*status = partition->async_hypercall_status;
> +}
> +
> +static int
> +mshv_partition_region_share(struct mshv_mem_region *region)
> +{
> +	u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED;
> +
> +	if (region->flags.large_pages)
> +		flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE;
> +
> +	return hv_call_modify_spa_host_access(region->partition->pt_id,
> +			region->pages, region->nr_pages,
> +			HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE,
> +			flags, true);
> +}
> +
> +static int
> +mshv_partition_region_unshare(struct mshv_mem_region *region)
> +{
> +	u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE;
> +
> +	if (region->flags.large_pages)
> +		flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE;
> +
> +	return hv_call_modify_spa_host_access(region->partition->pt_id,
> +			region->pages, region->nr_pages,
> +			0,
> +			flags, false);
> +}
> +
> +static int
> +mshv_region_remap_pages(struct mshv_mem_region *region, u32 map_flags,
> +			u64 page_offset, u64 page_count)
> +{
> +	if (page_offset + page_count > region->nr_pages)
> +		return -EINVAL;
> +
> +	if (region->flags.large_pages)
> +		map_flags |= HV_MAP_GPA_LARGE_PAGE;
> +
> +	/* ask the hypervisor to map guest ram */
> +	return hv_call_map_gpa_pages(region->partition->pt_id,
> +				     region->start_gfn + page_offset,
> +				     page_count, map_flags,
> +				     region->pages + page_offset);
> +}
> +
> +static int
> +mshv_region_map(struct mshv_mem_region *region)
> +{
> +	u32 map_flags = region->hv_map_flags;
> +
> +	return mshv_region_remap_pages(region, map_flags,
> +				       0, region->nr_pages);
> +}
> +
> +static void
> +mshv_region_evict_pages(struct mshv_mem_region *region,
> +			u64 page_offset, u64 page_count)
> +{
> +	if (region->flags.range_pinned)
> +		unpin_user_pages(region->pages + page_offset, page_count);
> +
> +	memset(region->pages + page_offset, 0,
> +	       page_count * sizeof(struct page *));
> +}
> +
> +static void
> +mshv_region_evict(struct mshv_mem_region *region)
> +{
> +	mshv_region_evict_pages(region, 0, region->nr_pages);
> +}
> +
> +static int
> +mshv_region_populate_pages(struct mshv_mem_region *region,
> +			   u64 page_offset, u64 page_count)
> +{
> +	u64 done_count, nr_pages;
> +	struct page **pages;
> +	__u64 userspace_addr;
> +	int ret;
> +
> +	if (page_offset + page_count > region->nr_pages)
> +		return -EINVAL;
> +
> +	for (done_count = 0; done_count < page_count; done_count += ret) {
> +		pages = region->pages + page_offset + done_count;
> +		userspace_addr = region->start_uaddr +
> +				(page_offset + done_count) *
> +				HV_HYP_PAGE_SIZE;
> +		nr_pages = min(page_count - done_count,
> +			       MSHV_PIN_PAGES_BATCH_SIZE);
> +
> +		/*
> +		 * Pinning assuming 4k pages works for large pages too.
> +		 * All page structs within the large page are returned.
> +		 *
> +		 * Pin requests are batched because pin_user_pages_fast
> +		 * with the FOLL_LONGTERM flag does a large temporary
> +		 * allocation of contiguous memory.
> +		 */
> +		if (region->flags.range_pinned)
> +			ret = pin_user_pages_fast(userspace_addr,
> +						  nr_pages,
> +						  FOLL_WRITE | FOLL_LONGTERM,
> +						  pages);
> +		else
> +			ret = -EOPNOTSUPP;
> +
> +		if (ret < 0)
> +			goto release_pages;
> +	}
> +
> +	if (PageHuge(region->pages[page_offset]))
> +		region->flags.large_pages = true;
> +
> +	return 0;
> +
> +release_pages:
> +	mshv_region_evict_pages(region, page_offset, done_count);
> +	return ret;
> +}
> +
> +static int
> +mshv_region_populate(struct mshv_mem_region *region)
> +{
> +	return mshv_region_populate_pages(region, 0, region->nr_pages);
> +}
> +
> +static struct mshv_mem_region *
> +mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn)
> +{
> +	struct mshv_mem_region *region;
> +
> +	hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) {
> +		if (gfn >= region->start_gfn &&
> +		    gfn < region->start_gfn + region->nr_pages)
> +			return region;
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct mshv_mem_region *
> +mshv_partition_region_by_uaddr(struct mshv_partition *partition, u64 uaddr)
> +{
> +	struct mshv_mem_region *region;
> +
> +	hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) {
> +		if (uaddr >= region->start_uaddr &&
> +		    uaddr < region->start_uaddr +
> +			    (region->nr_pages << HV_HYP_PAGE_SHIFT))
> +			return region;
> +	}
> +
> +	return NULL;
> +}
> +
> +/*
> + * NB: caller checks and makes sure mem->size is page aligned
> + * Returns: 0 with regionpp updated on success, or -errno
> + */
> +static int mshv_partition_create_region(struct mshv_partition *partition,
> +					struct mshv_user_mem_region *mem,
> +					struct mshv_mem_region **regionpp,
> +					bool is_mmio)
> +{
> +	struct mshv_mem_region *region;
> +	u64 nr_pages = HVPFN_DOWN(mem->size);
> +
> +	/* Reject overlapping regions */
> +	if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) ||
> +	    mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) ||
> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr) ||
> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1))
> +		return -EEXIST;

Having to fully walk the partition region list four times for the above checks
isn't the most efficient approach, but I'm guessing that creating a region isn't
really a hot path so it doesn't matter. And I don't know how long the region list
typically is.

> +
> +	region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages);
> +	if (!region)
> +		return -ENOMEM;
> +
> +	region->nr_pages = nr_pages;
> +	region->start_gfn = mem->guest_pfn;
> +	region->start_uaddr = mem->userspace_addr;
> +	region->hv_map_flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_ADJUSTABLE;
> +	if (mem->flags & BIT(MSHV_SET_MEM_BIT_WRITABLE))
> +		region->hv_map_flags |= HV_MAP_GPA_WRITABLE;
> +	if (mem->flags & BIT(MSHV_SET_MEM_BIT_EXECUTABLE))
> +		region->hv_map_flags |= HV_MAP_GPA_EXECUTABLE;
> +
> +	/* Note: large_pages flag populated when we pin the pages */
> +	if (!is_mmio)
> +		region->flags.range_pinned = true;
> +
> +	region->partition = partition;
> +
> +	*regionpp = region;
> +
> +	return 0;
> +}
> +
> +/*
> + * Map guest ram. if snp, make sure to release that from the host first
> + * Side Effects: In case of failure, pages are unpinned when feasible.
> + */
> +static int
> +mshv_partition_mem_region_map(struct mshv_mem_region *region)
> +{
> +	struct mshv_partition *partition = region->partition;
> +	int ret;
> +
> +	ret = mshv_region_populate(region);
> +	if (ret) {
> +		pt_err(partition, "Failed to populate memory region: %d\n",
> +		       ret);
> +		goto err_out;
> +	}
> +
> +	/*
> +	 * For an SNP partition it is a requirement that for every memory region
> +	 * that we are going to map for this partition we should make sure that
> +	 * host access to that region is released. This is ensured by doing an
> +	 * additional hypercall which will update the SLAT to release host
> +	 * access to guest memory regions.
> +	 */
> +	if (mshv_partition_encrypted(partition)) {
> +		ret = mshv_partition_region_unshare(region);
> +		if (ret) {
> +			pt_err(partition,
> +			       "Failed to unshare memory region (guest_pfn: %llu): %d\n",
> +			       region->start_gfn, ret);
> +			goto evict_region;
> +		}
> +	}
> +
> +	ret = mshv_region_map(region);
> +	if (ret && mshv_partition_encrypted(partition)) {
> +		int shrc;
> +
> +		shrc = mshv_partition_region_share(region);
> +		if (!shrc)
> +			goto evict_region;
> +
> +		pt_err(partition,
> +		       "Failed to share memory region (guest_pfn: %llu): %d\n",
> +		       region->start_gfn, shrc);
> +		/*
> +		 * Don't unpin if marking shared failed because pages are no
> +		 * longer mapped in the host, ie root, anymore.
> +		 */
> +		goto err_out;
> +	}
> +
> +	return 0;
> +
> +evict_region:
> +	mshv_region_evict(region);
> +err_out:
> +	return ret;
> +}
> +
> +/*
> + * This maps two things: guest RAM and for pci passthru mmio space.
> + *
> + * mmio:
> + *  - vfio overloads vm_pgoff to store the mmio start pfn/spa.
> + *  - Two things need to happen for mapping mmio range:
> + *	1. mapped in the uaddr so VMM can access it.
> + *	2. mapped in the hwpt (gfn <-> mmio phys addr) so guest can access it.
> + *
> + *   This function takes care of the second. The first one is managed by vfio,
> + *   and hence is taken care of via vfio_pci_mmap_fault().
> + */
> +static long
> +mshv_map_user_memory(struct mshv_partition *partition,
> +		     struct mshv_user_mem_region mem)
> +{
> +	struct mshv_mem_region *region;
> +	struct vm_area_struct *vma;
> +	bool is_mmio;
> +	ulong mmio_pfn;
> +	long ret;
> +
> +	if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP) ||
> +	    !access_ok((const void *)mem.userspace_addr, mem.size))
> +		return -EINVAL;
> +
> +	mmap_read_lock(current->mm);
> +	vma = vma_lookup(current->mm, mem.userspace_addr);
> +	is_mmio = vma ? !!(vma->vm_flags & (VM_IO | VM_PFNMAP)) : 0;
> +	mmio_pfn = is_mmio ? vma->vm_pgoff : 0;
> +	mmap_read_unlock(current->mm);
> +
> +	if (!vma)
> +		return -EINVAL;
> +
> +	ret = mshv_partition_create_region(partition, &mem, &region,
> +					   is_mmio);
> +	if (ret)
> +		return ret;
> +
> +	if (is_mmio)
> +		ret = hv_call_map_mmio_pages(partition->pt_id, mem.guest_pfn,
> +					     mmio_pfn, HVPFN_DOWN(mem.size));
> +	else
> +		ret = mshv_partition_mem_region_map(region);
> +
> +	if (ret)
> +		goto errout;
> +
> +	/* Install the new region */
> +	hlist_add_head(&region->hnode, &partition->pt_mem_regions);
> +
> +	return 0;
> +
> +errout:
> +	vfree(region);
> +	return ret;
> +}
> +
> +/* Called for unmapping both the guest ram and the mmio space */
> +static long
> +mshv_unmap_user_memory(struct mshv_partition *partition,
> +		       struct mshv_user_mem_region mem)
> +{
> +	struct mshv_mem_region *region;
> +	u32 unmap_flags = 0;
> +
> +	if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
> +		return -EINVAL;
> +
> +	if (hlist_empty(&partition->pt_mem_regions))
> +		return -EINVAL;

Isn't the above check redundant, given the lookup by gfn that is
done immediately below?

> +
> +	region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
> +	if (!region)
> +		return -EINVAL;
> +
> +	/* Paranoia check */
> +	if (region->start_uaddr != mem.userspace_addr ||
> +	    region->start_gfn != mem.guest_pfn ||
> +	    region->nr_pages != HVPFN_DOWN(mem.size))
> +		return -EINVAL;
> +
> +	hlist_del(&region->hnode);
> +
> +	if (region->flags.large_pages)
> +		unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
> +
> +	/* ignore unmap failures and continue as process may be exiting */
> +	hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn,
> +				region->nr_pages, unmap_flags);
> +
> +	mshv_region_evict(region);
> +
> +	vfree(region);
> +	return 0;
> +}
> +
> +static long
> +mshv_partition_ioctl_set_memory(struct mshv_partition *partition,
> +				struct mshv_user_mem_region __user *user_mem)
> +{
> +	struct mshv_user_mem_region mem;
> +
> +	if (copy_from_user(&mem, user_mem, sizeof(mem)))
> +		return -EFAULT;
> +
> +	if (!mem.size ||
> +	    !PAGE_ALIGNED(mem.size) ||
> +	    !PAGE_ALIGNED(mem.userspace_addr) ||
> +	    (mem.flags & ~MSHV_SET_MEM_FLAGS_MASK) ||
> +	    mshv_field_nonzero(mem, rsvd))
> +		return -EINVAL;
> +
> +	if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP))
> +		return mshv_unmap_user_memory(partition, mem);
> +
> +	return mshv_map_user_memory(partition, mem);
> +}
> +
> +static long
> +mshv_partition_ioctl_ioeventfd(struct mshv_partition *partition,
> +			       void __user *user_args)
> +{
> +	struct mshv_user_ioeventfd args;
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	return mshv_set_unset_ioeventfd(partition, &args);
> +}
> +
> +static long
> +mshv_partition_ioctl_irqfd(struct mshv_partition *partition,
> +			   void __user *user_args)
> +{
> +	struct mshv_user_irqfd args;
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	return mshv_set_unset_irqfd(partition, &args);
> +}
> +
> +static long
> +mshv_partition_ioctl_get_gpap_access_bitmap(struct mshv_partition *partition,
> +					    void __user *user_args)
> +{
> +	struct mshv_gpap_access_bitmap args;
> +	union hv_gpa_page_access_state *states;
> +	long ret, i;
> +	union hv_gpa_page_access_state_flags hv_flags = {};
> +	u8 hv_type_mask;
> +	ulong bitmap_buf_sz, states_buf_sz;
> +	int written = 0;
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	if (args.access_type >= MSHV_GPAP_ACCESS_TYPE_COUNT ||
> +	    args.access_op >= MSHV_GPAP_ACCESS_OP_COUNT ||
> +	    mshv_field_nonzero(args, rsvd) || !args.page_count ||
> +	    !args.bitmap_ptr)
> +		return -EINVAL;
> +
> +	if (check_mul_overflow(args.page_count, sizeof(*states), &states_buf_sz))
> +		return -E2BIG;
> +
> +	/* Num bytes needed to store bitmap; one bit per page rounded up */
> +	bitmap_buf_sz = DIV_ROUND_UP(args.page_count, 8);
> +
> +	/* Sanity check */
> +	if (bitmap_buf_sz > states_buf_sz)
> +		return -EBADFD;
> +
> +	switch (args.access_type) {
> +	case MSHV_GPAP_ACCESS_TYPE_ACCESSED:
> +		hv_type_mask = 1;
> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> +			hv_flags.clear_accessed = 1;
> +			/* not accessed implies not dirty */
> +			hv_flags.clear_dirty = 1;
> +		} else { // MSHV_GPAP_ACCESS_OP_SET

Avoid C++ style comments.

> +			hv_flags.set_accessed = 1;
> +		}
> +		break;
> +	case MSHV_GPAP_ACCESS_TYPE_DIRTY:
> +		hv_type_mask = 2;
> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> +			hv_flags.clear_dirty = 1;
> +		} else { // MSHV_GPAP_ACCESS_OP_SET

Same here.

> +			hv_flags.set_dirty = 1;
> +			/* dirty implies accessed */
> +			hv_flags.set_accessed = 1;
> +		}
> +		break;
> +	}
> +
> +	states = vzalloc(states_buf_sz);
> +	if (!states)
> +		return -ENOMEM;
> +
> +	ret = hv_call_get_gpa_access_states(partition->pt_id, args.page_count,
> +					    args.gpap_base, hv_flags, &written,
> +					    states);
> +	if (ret)
> +		goto free_return;
> +
> +	/*
> +	 * Overwrite states buffer with bitmap - the bits in hv_type_mask
> +	 * correspond to bitfields in hv_gpa_page_access_state
> +	 */
> +	for (i = 0; i < written; ++i)
> +		assign_bit(i, (ulong *)states,

Why the cast to ulong *?  I think this argument to assign_bit() is void *, in
which case the cast wouldn't be needed.

Also, assign_bit() does atomic bit operations. Doing such in a loop like
here will really hammer the hardware memory bus with atomic 
read-modify-write cycles. Use __assign_bit() instead, which does
non-atomic operations. You don't need atomic here as no other
threads are modifying the bit array.

> +			   states[i].as_uint8 & hv_type_mask);

OK, so the starting contents of "states" is an array of bytes. The ending
contents is an array of bits. This works because every bit in the ending
bit array is set to either 0 or 1. Overlap occurs on the first iteration
where the code reads the 0th byte, and writes the 0th bit, which is part of
the 0th byte. The second iteration reads the 1st byte, and writes the 1st bit,
which doesn't overlap, and there's no overlap from then on.

Suppose "written" is not a multiple of 8. The last byte of "states" as an
array of bits will have some bits that have not been set to either 0 or 1 and
might be leftover garbage from when "states" was an array of bytes. That
garbage will get copied to user space. Is that OK? Even if user space knows
enough to ignore those bits, it seems a little dubious to be copying even
a few bits of garbage to user space.

Some comments might help here.

> +
> +	args.page_count = written;
> +
> +	if (copy_to_user(user_args, &args, sizeof(args))) {
> +		ret = -EFAULT;
> +		goto free_return;
> +	}
> +	if (copy_to_user((void __user *)args.bitmap_ptr, states, bitmap_buf_sz))
> +		ret = -EFAULT;
> +
> +free_return:
> +	vfree(states);
> +	return ret;
> +}
> +
> +static long
> +mshv_partition_ioctl_set_msi_routing(struct mshv_partition *partition,
> +				     void __user *user_args)
> +{
> +	struct mshv_user_irq_entry *entries = NULL;
> +	struct mshv_user_irq_table args;
> +	long ret;
> +
> +	if (copy_from_user(&args, user_args, sizeof(args)))
> +		return -EFAULT;
> +
> +	if (args.nr > MSHV_MAX_GUEST_IRQS ||
> +	    mshv_field_nonzero(args, rsvd))
> +		return -EINVAL;
> +
> +	if (args.nr) {
> +		struct mshv_user_irq_table __user *urouting = user_args;
> +
> +		entries = vmemdup_user(urouting->entries,
> +				       array_size(sizeof(*entries),
> +						  args.nr));
> +		if (IS_ERR(entries))
> +			return PTR_ERR(entries);
> +	}
> +	ret = mshv_update_routing_table(partition, entries, args.nr);
> +	kvfree(entries);
> +
> +	return ret;
> +}
> +
> +static long
> +mshv_partition_ioctl_initialize(struct mshv_partition *partition)
> +{
> +	long ret;
> +
> +	if (partition->pt_initialized)
> +		return 0;
> +
> +	ret = hv_call_initialize_partition(partition->pt_id);
> +	if (ret)
> +		goto withdraw_mem;
> +
> +	partition->pt_initialized = true;
> +
> +	return 0;
> +
> +withdraw_mem:
> +	hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id);
> +
> +	return ret;
> +}
> +
> +static long
> +mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> +{
> +	struct mshv_partition *partition = filp->private_data;
> +	long ret;
> +	void __user *uarg = (void __user *)arg;
> +
> +	if (mutex_lock_killable(&partition->pt_mutex))
> +		return -EINTR;
> +
> +	switch (ioctl) {
> +	case MSHV_INITIALIZE_PARTITION:
> +		ret = mshv_partition_ioctl_initialize(partition);
> +		break;
> +	case MSHV_SET_GUEST_MEMORY:
> +		ret = mshv_partition_ioctl_set_memory(partition, uarg);
> +		break;
> +	case MSHV_CREATE_VP:
> +		ret = mshv_partition_ioctl_create_vp(partition, uarg);
> +		break;
> +	case MSHV_IRQFD:
> +		ret = mshv_partition_ioctl_irqfd(partition, uarg);
> +		break;
> +	case MSHV_IOEVENTFD:
> +		ret = mshv_partition_ioctl_ioeventfd(partition, uarg);
> +		break;
> +	case MSHV_SET_MSI_ROUTING:
> +		ret = mshv_partition_ioctl_set_msi_routing(partition, uarg);
> +		break;
> +	case MSHV_GET_GPAP_ACCESS_BITMAP:
> +		ret = mshv_partition_ioctl_get_gpap_access_bitmap(partition,
> +								  uarg);
> +		break;
> +	case MSHV_ROOT_HVCALL:
> +		ret = mshv_ioctl_passthru_hvcall(partition, true, uarg);
> +		break;
> +	default:
> +		ret = -ENOTTY;
> +	}
> +
> +	mutex_unlock(&partition->pt_mutex);
> +	return ret;
> +}
> +
> +static int
> +disable_vp_dispatch(struct mshv_vp *vp)
> +{
> +	int ret;
> +	struct hv_register_assoc dispatch_suspend = {
> +		.name = HV_REGISTER_DISPATCH_SUSPEND,
> +		.value.dispatch_suspend.suspended = 1,
> +	};
> +
> +	ret = mshv_set_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    1, &dispatch_suspend);
> +	if (ret)
> +		vp_err(vp, "failed to suspend\n");
> +
> +	return ret;
> +}
> +
> +static int
> +get_vp_signaled_count(struct mshv_vp *vp, u64 *count)
> +{
> +	int ret;
> +	struct hv_register_assoc root_signal_count = {
> +		.name = HV_REGISTER_VP_ROOT_SIGNAL_COUNT,
> +	};
> +
> +	ret = mshv_get_vp_registers(vp->vp_index, vp->vp_partition->pt_id,
> +				    1, &root_signal_count);
> +
> +	if (ret) {
> +		vp_err(vp, "Failed to get root signal count");
> +		*count = 0;
> +		return ret;
> +	}
> +
> +	*count = root_signal_count.value.reg64;
> +
> +	return ret;
> +}
> +
> +static void
> +drain_vp_signals(struct mshv_vp *vp)
> +{
> +	u64 hv_signal_count;
> +	u64 vp_signal_count;
> +
> +	get_vp_signaled_count(vp, &hv_signal_count);
> +
> +	vp_signal_count = atomic64_read(&vp->run.vp_signaled_count);
> +
> +	/*
> +	 * There should be at most 1 outstanding notification, but be extra
> +	 * careful anyway.
> +	 */
> +	while (hv_signal_count != vp_signal_count) {
> +		WARN_ON(hv_signal_count - vp_signal_count != 1);
> +
> +		if (wait_event_interruptible(vp->run.vp_suspend_queue,
> +					     vp->run.kicked_by_hv == 1))
> +			break;
> +		vp->run.kicked_by_hv = 0;
> +		vp_signal_count = atomic64_read(&vp->run.vp_signaled_count);
> +	}
> +}
> +
> +static void drain_all_vps(const struct mshv_partition *partition)
> +{
> +	int i;
> +	struct mshv_vp *vp;
> +
> +	/*
> +	 * VPs are reachable from ISR. It is safe to not take the partition
> +	 * lock because nobody else can enter this function and drop the
> +	 * partition from the list.
> +	 */
> +	for (i = 0; i < MSHV_MAX_VPS; i++) {
> +		vp = partition->pt_vp_array[i];
> +		if (!vp)
> +			continue;
> +		/*
> +		 * Disable dispatching of the VP in the hypervisor. After this
> +		 * the hypervisor guarantees it won't generate any signals for
> +		 * the VP and the hypervisor's VP signal count won't change.
> +		 */
> +		disable_vp_dispatch(vp);
> +		drain_vp_signals(vp);
> +	}
> +}
> +
> +static void
> +remove_partition(struct mshv_partition *partition)
> +{
> +	spin_lock(&mshv_root.pt_ht_lock);
> +	hlist_del_rcu(&partition->pt_hnode);
> +	spin_unlock(&mshv_root.pt_ht_lock);
> +
> +	synchronize_rcu();
> +}
> +
> +/*
> + * Tear down a partition and remove it from the list.
> + * Partition's refcount must be 0
> + */
> +static void destroy_partition(struct mshv_partition *partition)
> +{
> +	struct mshv_vp *vp;
> +	struct mshv_mem_region *region;
> +	int i, ret;
> +	struct hlist_node *n;
> +	union hv_input_vtl input_vtl;
> +
> +	if (refcount_read(&partition->pt_ref_count)) {
> +		pt_err(partition,
> +		       "Attempt to destroy partition but refcount > 0\n");
> +		return;
> +	}
> +
> +	if (partition->pt_initialized) {
> +		/*
> +		 * We only need to drain signals for root scheduler. This should be
> +		 * done before removing the partition from the partition list.
> +		 */
> +		if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT)
> +			drain_all_vps(partition);
> +
> +		/* Remove vps */
> +		for (i = 0; i < MSHV_MAX_VPS; ++i) {
> +			vp = partition->pt_vp_array[i];
> +			if (!vp)
> +				continue;
> +
> +			if (hv_parent_partition())
> +				mshv_vp_stats_unmap(partition->pt_id, vp->vp_index);
> +
> +			if (vp->vp_register_page) {
> +				input_vtl.as_uint8 = 0;
> +				(void)hv_call_unmap_vp_state_page(partition->pt_id,
> +								  vp->vp_index,
> +								  HV_VP_STATE_PAGE_REGISTERS,
> +								  input_vtl);
> +				vp->vp_register_page = NULL;
> +			}
> +
> +			input_vtl.as_uint8 = 0;
> +			(void)hv_call_unmap_vp_state_page(partition->pt_id,
> +							  vp->vp_index,
> +							  HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> +							  input_vtl);
> +			vp->vp_intercept_msg_page = NULL;
> +
> +			if (vp->vp_ghcb_page) {
> +				input_vtl.use_target_vtl = 1;
> +				input_vtl.target_vtl = HV_NORMAL_VTL;
> +				(void)hv_call_unmap_vp_state_page(partition->pt_id,
> +								  vp->vp_index,
> +								  HV_VP_STATE_PAGE_GHCB,
> +								  input_vtl);
> +				vp->vp_ghcb_page = NULL;
> +			}
> +
> +			kfree(vp);
> +
> +			partition->pt_vp_array[i] = NULL;
> +		}
> +
> +		/* Deallocates and unmaps everything including vcpus, GPA mappings etc */
> +		hv_call_finalize_partition(partition->pt_id);
> +
> +		partition->pt_initialized = false;
> +	}
> +
> +	remove_partition(partition);
> +
> +	/* Remove regions, regain access to the memory and unpin the pages */
> +	hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions,
> +				  hnode) {
> +		hlist_del(&region->hnode);
> +
> +		if (mshv_partition_encrypted(partition)) {
> +			ret = mshv_partition_region_share(region);
> +			if (ret) {
> +				pt_err(partition,
> +				       "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n",
> +				      ret);
> +				return;
> +			}
> +		}
> +
> +		mshv_region_evict(region);
> +
> +		vfree(region);
> +	}
> +
> +	/* Withdraw and free all pages we deposited */
> +	hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id);
> +	hv_call_delete_partition(partition->pt_id);
> +
> +	mshv_free_routing_table(partition);
> +	kfree(partition);
> +}
> +
> +struct
> +mshv_partition *mshv_partition_get(struct mshv_partition *partition)
> +{
> +	if (refcount_inc_not_zero(&partition->pt_ref_count))
> +		return partition;
> +	return NULL;
> +}
> +
> +struct
> +mshv_partition *mshv_partition_find(u64 partition_id)
> +	__must_hold(RCU)
> +{
> +	struct mshv_partition *p;
> +
> +	hash_for_each_possible_rcu(mshv_root.pt_htable, p, pt_hnode,
> +				   partition_id)
> +		if (p->pt_id == partition_id)
> +			return p;
> +
> +	return NULL;
> +}
> +
> +void
> +mshv_partition_put(struct mshv_partition *partition)
> +{
> +	if (refcount_dec_and_test(&partition->pt_ref_count))
> +		destroy_partition(partition);
> +}
> +
> +static int
> +mshv_partition_release(struct inode *inode, struct file *filp)
> +{
> +	struct mshv_partition *partition = filp->private_data;
> +
> +	mshv_eventfd_release(partition);
> +
> +	cleanup_srcu_struct(&partition->pt_irq_srcu);
> +
> +	mshv_partition_put(partition);
> +
> +	return 0;
> +}
> +
> +static int
> +add_partition(struct mshv_partition *partition)
> +{
> +	spin_lock(&mshv_root.pt_ht_lock);
> +
> +	hash_add_rcu(mshv_root.pt_htable, &partition->pt_hnode,
> +		     partition->pt_id);
> +
> +	spin_unlock(&mshv_root.pt_ht_lock);
> +
> +	return 0;
> +}
> +
> +static long
> +mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev)
> +{
> +	struct mshv_create_partition args;
> +	u64 creation_flags;
> +	struct hv_partition_creation_properties creation_properties = {};
> +	union hv_partition_isolation_properties isolation_properties = {};
> +	struct mshv_partition *partition;
> +	struct file *file;
> +	int fd;
> +	long ret;
> +
> +	if (copy_from_user(&args, user_arg, sizeof(args)))
> +		return -EFAULT;
> +
> +	if ((args.pt_flags & ~MSHV_PT_FLAGS_MASK) ||
> +	    args.pt_isolation >= MSHV_PT_ISOLATION_COUNT)
> +		return -EINVAL;
> +
> +	/* Only support EXO partitions */
> +	creation_flags = HV_PARTITION_CREATION_FLAG_EXO_PARTITION |
> +			HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED;
> +
> +	if (args.pt_flags & BIT(MSHV_PT_BIT_LAPIC))
> +		creation_flags |= HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED;
> +	if (args.pt_flags & BIT(MSHV_PT_BIT_X2APIC))
> +		creation_flags |= HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE;
> +	if (args.pt_flags & BIT(MSHV_PT_BIT_GPA_SUPER_PAGES))
> +		creation_flags |= HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED;
> +
> +	switch (args.pt_isolation) {
> +	case MSHV_PT_ISOLATION_NONE:
> +		isolation_properties.isolation_type =
> +			HV_PARTITION_ISOLATION_TYPE_NONE;
> +		break;
> +	}
> +
> +	partition = kzalloc(sizeof(*partition), GFP_KERNEL);
> +	if (!partition)
> +		return -ENOMEM;
> +
> +	partition->pt_module_dev = module_dev;
> +	partition->isolation_type = isolation_properties.isolation_type;
> +
> +	refcount_set(&partition->pt_ref_count, 1);
> +
> +	mutex_init(&partition->pt_mutex);
> +
> +	mutex_init(&partition->pt_irq_lock);
> +
> +	init_completion(&partition->async_hypercall);
> +
> +	INIT_HLIST_HEAD(&partition->irq_ack_notifier_list);
> +
> +	INIT_HLIST_HEAD(&partition->pt_devices);
> +
> +	INIT_HLIST_HEAD(&partition->pt_mem_regions);
> +
> +	mshv_eventfd_init(partition);
> +
> +	ret = init_srcu_struct(&partition->pt_irq_srcu);
> +	if (ret)
> +		goto free_partition;
> +
> +	ret = hv_call_create_partition(creation_flags,
> +				       creation_properties,
> +				       isolation_properties,
> +				       &partition->pt_id);
> +	if (ret)
> +		goto cleanup_irq_srcu;
> +
> +	ret = add_partition(partition);
> +	if (ret)
> +		goto delete_partition;
> +
> +	ret = mshv_init_async_handler(partition);
> +	if (ret)
> +		goto remove_partition;
> +
> +	fd = get_unused_fd_flags(O_CLOEXEC);
> +	if (fd < 0) {
> +		ret = fd;
> +		goto remove_partition;
> +	}
> +
> +	file = anon_inode_getfile("mshv_partition", &mshv_partition_fops,
> +				  partition, O_RDWR);
> +	if (IS_ERR(file)) {
> +		ret = PTR_ERR(file);
> +		goto put_fd;
> +	}
> +
> +	fd_install(fd, file);
> +
> +	return fd;
> +
> +put_fd:
> +	put_unused_fd(fd);
> +remove_partition:
> +	remove_partition(partition);
> +delete_partition:
> +	hv_call_delete_partition(partition->pt_id);
> +cleanup_irq_srcu:
> +	cleanup_srcu_struct(&partition->pt_irq_srcu);
> +free_partition:
> +	kfree(partition);
> +
> +	return ret;
> +}
> +
> +static long mshv_dev_ioctl(struct file *filp, unsigned int ioctl,
> +			   unsigned long arg)
> +{
> +	struct miscdevice *misc = filp->private_data;
> +
> +	switch (ioctl) {
> +	case MSHV_CREATE_PARTITION:
> +		return mshv_ioctl_create_partition((void __user *)arg,
> +						misc->this_device);
> +	}
> +
> +	return -ENOTTY;
> +}
> +
> +static int
> +mshv_dev_open(struct inode *inode, struct file *filp)
> +{
> +	return 0;
> +}
> +
> +static int
> +mshv_dev_release(struct inode *inode, struct file *filp)
> +{
> +	return 0;
> +}
> +
> +static int mshv_cpuhp_online;
> +static int mshv_root_sched_online;
> +
> +static const char *scheduler_type_to_string(enum hv_scheduler_type type)
> +{
> +	switch (type) {
> +	case HV_SCHEDULER_TYPE_LP:
> +		return "classic scheduler without SMT";
> +	case HV_SCHEDULER_TYPE_LP_SMT:
> +		return "classic scheduler with SMT";
> +	case HV_SCHEDULER_TYPE_CORE_SMT:
> +		return "core scheduler";
> +	case HV_SCHEDULER_TYPE_ROOT:
> +		return "root scheduler";
> +	default:
> +		return "unknown scheduler";
> +	};
> +}
> +
> +/* TODO move this to hv_common.c when needed outside */
> +static int __init hv_retrieve_scheduler_type(enum hv_scheduler_type *out)
> +{
> +	struct hv_input_get_system_property *input;
> +	struct hv_output_get_system_property *output;
> +	unsigned long flags;
> +	u64 status;
> +
> +	local_irq_save(flags);
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +	memset(input, 0, sizeof(*input));
> +	memset(output, 0, sizeof(*output));
> +	input->property_id = HV_SYSTEM_PROPERTY_SCHEDULER_TYPE;
> +
> +	status = hv_do_hypercall(HVCALL_GET_SYSTEM_PROPERTY, input, output);
> +	if (!hv_result_success(status)) {
> +		local_irq_restore(flags);
> +		pr_err("%s: %s\n", __func__, hv_result_to_string(status));
> +		return hv_result_to_errno(status);
> +	}
> +
> +	*out = output->scheduler_type;
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +/* Retrieve and stash the supported scheduler type */
> +static int __init mshv_retrieve_scheduler_type(struct device *dev)
> +{
> +	int ret;
> +
> +	ret = hv_retrieve_scheduler_type(&hv_scheduler_type);
> +	if (ret)
> +		return ret;
> +
> +	dev_info(dev, "Hypervisor using %s\n",
> +		 scheduler_type_to_string(hv_scheduler_type));
> +
> +	switch (hv_scheduler_type) {
> +	case HV_SCHEDULER_TYPE_CORE_SMT:
> +	case HV_SCHEDULER_TYPE_LP_SMT:
> +	case HV_SCHEDULER_TYPE_ROOT:
> +	case HV_SCHEDULER_TYPE_LP:
> +		/* Supported scheduler, nothing to do */
> +		break;
> +	default:
> +		dev_err(dev, "unsupported scheduler 0x%x, bailing.\n",
> +			hv_scheduler_type);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mshv_root_scheduler_init(unsigned int cpu)
> +{
> +	void **inputarg, **outputarg, *p;
> +
> +	inputarg = (void **)this_cpu_ptr(root_scheduler_input);
> +	outputarg = (void **)this_cpu_ptr(root_scheduler_output);
> +
> +	/* Allocate two consecutive pages. One for input, one for output. */
> +	p = kmalloc(2 * HV_HYP_PAGE_SIZE, GFP_KERNEL);
> +	if (!p)
> +		return -ENOMEM;
> +
> +	*inputarg = p;
> +	*outputarg = (char *)p + HV_HYP_PAGE_SIZE;
> +
> +	return 0;
> +}
> +
> +static int mshv_root_scheduler_cleanup(unsigned int cpu)
> +{
> +	void *p, **inputarg, **outputarg;
> +
> +	inputarg = (void **)this_cpu_ptr(root_scheduler_input);
> +	outputarg = (void **)this_cpu_ptr(root_scheduler_output);
> +
> +	p = *inputarg;
> +
> +	*inputarg = NULL;
> +	*outputarg = NULL;
> +
> +	kfree(p);
> +
> +	return 0;
> +}
> +
> +/* Must be called after retrieving the scheduler type */
> +static int
> +root_scheduler_init(struct device *dev)
> +{
> +	int ret;
> +
> +	if (hv_scheduler_type != HV_SCHEDULER_TYPE_ROOT)
> +		return 0;
> +
> +	root_scheduler_input = alloc_percpu(void *);
> +	root_scheduler_output = alloc_percpu(void *);
> +
> +	if (!root_scheduler_input || !root_scheduler_output) {
> +		dev_err(dev, "Failed to allocate root scheduler buffers\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_root_sched",
> +				mshv_root_scheduler_init,
> +				mshv_root_scheduler_cleanup);
> +
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to setup root scheduler state: %i\n", ret);
> +		goto out;
> +	}
> +
> +	mshv_root_sched_online = ret;
> +
> +	return 0;
> +
> +out:
> +	free_percpu(root_scheduler_input);
> +	free_percpu(root_scheduler_output);
> +	return ret;
> +}
> +
> +static void
> +root_scheduler_deinit(void)
> +{
> +	if (hv_scheduler_type != HV_SCHEDULER_TYPE_ROOT)
> +		return;
> +
> +	cpuhp_remove_state(mshv_root_sched_online);
> +	free_percpu(root_scheduler_input);
> +	free_percpu(root_scheduler_output);
> +}
> +
> +static int mshv_reboot_notify(struct notifier_block *nb,
> +			      unsigned long code, void *unused)
> +{
> +	cpuhp_remove_state(mshv_cpuhp_online);
> +	return 0;
> +}
> +
> +struct notifier_block mshv_reboot_nb = {
> +	.notifier_call = mshv_reboot_notify,
> +};
> +
> +static void mshv_root_partition_exit(void)
> +{
> +	unregister_reboot_notifier(&mshv_reboot_nb);
> +	root_scheduler_deinit();
> +}
> +
> +static int __init mshv_root_partition_init(struct device *dev)
> +{
> +	int err;
> +
> +	if (mshv_retrieve_scheduler_type(dev))
> +		return -ENODEV;
> +
> +	err = root_scheduler_init(dev);
> +	if (err)
> +		return err;
> +
> +	err = register_reboot_notifier(&mshv_reboot_nb);
> +	if (err)
> +		goto root_sched_deinit;
> +
> +	return 0;
> +
> +root_sched_deinit:
> +	root_scheduler_deinit();
> +	return err;
> +}
> +
> +static int __init mshv_parent_partition_init(void)
> +{
> +	int ret;
> +	struct device *dev;
> +	union hv_hypervisor_version_info version_info;
> +
> +	if (!hv_root_partition() || is_kdump_kernel())
> +		return -ENODEV;
> +
> +	if (hv_get_hypervisor_version(&version_info))
> +		return -ENODEV;
> +
> +	ret = misc_register(&mshv_dev);
> +	if (ret)
> +		return ret;
> +
> +	dev = mshv_dev.this_device;
> +
> +	if (version_info.build_number < MSHV_HV_MIN_VERSION ||
> +	    version_info.build_number > MSHV_HV_MAX_VERSION) {
> +		dev_err(dev, "Running on unvalidated Hyper-V version\n");
> +		dev_err(dev, "Versions: current: %u  min: %u  max: %u\n",
> +			version_info.build_number, MSHV_HV_MIN_VERSION,
> +			MSHV_HV_MAX_VERSION);
> +	}
> +
> +	mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages);
> +	if (!mshv_root.synic_pages) {
> +		dev_err(dev, "Failed to allocate percpu synic page\n");
> +		ret = -ENOMEM;
> +		goto device_deregister;
> +	}
> +
> +	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic",
> +				mshv_synic_init,
> +				mshv_synic_cleanup);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret);
> +		goto free_synic_pages;
> +	}
> +
> +	mshv_cpuhp_online = ret;
> +
> +	ret = mshv_root_partition_init(dev);
> +	if (ret)
> +		goto remove_cpu_state;
> +
> +	ret = mshv_irqfd_wq_init();
> +	if (ret)
> +		goto exit_partition;
> +
> +	spin_lock_init(&mshv_root.pt_ht_lock);
> +	hash_init(mshv_root.pt_htable);
> +
> +	hv_setup_mshv_handler(mshv_isr);
> +
> +	return 0;
> +
> +exit_partition:
> +	if (hv_root_partition())
> +		mshv_root_partition_exit();
> +remove_cpu_state:
> +	cpuhp_remove_state(mshv_cpuhp_online);
> +free_synic_pages:
> +	free_percpu(mshv_root.synic_pages);
> +device_deregister:
> +	misc_deregister(&mshv_dev);
> +	return ret;
> +}
> +
> +static void __exit mshv_parent_partition_exit(void)
> +{
> +	hv_setup_mshv_handler(NULL);
> +	mshv_port_table_fini();
> +	misc_deregister(&mshv_dev);
> +	mshv_irqfd_wq_cleanup();
> +	if (hv_root_partition())
> +		mshv_root_partition_exit();
> +	cpuhp_remove_state(mshv_cpuhp_online);
> +	free_percpu(mshv_root.synic_pages);
> +}
> +
> +module_init(mshv_parent_partition_init);
> +module_exit(mshv_parent_partition_exit);
> diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
> new file mode 100644
> index 000000000000..e7782f92e339
> --- /dev/null
> +++ b/drivers/hv/mshv_synic.c
> @@ -0,0 +1,665 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023, Microsoft Corporation.
> + *
> + * mshv_root module's main interrupt handler and associated functionality.
> + *
> + * Authors:
> + *   Nuno Das Neves <nunodasneves at linux.microsoft.com>
> + *   Lillian Grassin-Drake <ligrassi at microsoft.com>
> + *   Vineeth Remanan Pillai <viremana at linux.microsoft.com>
> + *   Wei Liu <wei.liu at kernel.org>
> + *   Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/random.h>
> +#include <asm/mshyperv.h>
> +
> +#include "mshv_eventfd.h"
> +#include "mshv.h"
> +
> +static u32 synic_event_ring_get_queued_port(u32 sint_index)
> +{
> +	struct hv_synic_event_ring_page **event_ring_page;
> +	volatile struct hv_synic_event_ring *ring;
> +	struct hv_synic_pages *spages;
> +	u8 **synic_eventring_tail;
> +	u32 message;
> +	u8 tail;
> +
> +	spages = this_cpu_ptr(mshv_root.synic_pages);
> +	event_ring_page = &spages->synic_event_ring_page;
> +	synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
> +	tail = (*synic_eventring_tail)[sint_index];
> +
> +	if (unlikely(!(*event_ring_page))) {
> +		pr_debug("Missing synic event ring page!\n");
> +		return 0;
> +	}
> +
> +	ring = &(*event_ring_page)->sint_event_ring[sint_index];
> +
> +	/*
> +	 * Get the message.
> +	 */
> +	message = ring->data[tail];
> +
> +	if (!message) {
> +		if (ring->ring_full) {
> +			/*
> +			 * Ring is marked full, but we would have consumed all
> +			 * the messages. Notify the hypervisor that ring is now
> +			 * empty and check again.
> +			 */
> +			ring->ring_full = 0;
> +			hv_call_notify_port_ring_empty(sint_index);
> +			message = ring->data[tail];
> +		}
> +
> +		if (!message) {
> +			ring->signal_masked = 0;
> +			/*
> +			 * Unmask the signal and sync with hypervisor
> +			 * before one last check for any message.
> +			 */
> +			mb();
> +			message = ring->data[tail];
> +
> +			/*
> +			 * Ok, lets bail out.
> +			 */
> +			if (!message)
> +				return 0;
> +		}
> +
> +		ring->signal_masked = 1;
> +	}
> +
> +	/*
> +	 * Clear the message in the ring buffer.
> +	 */
> +	ring->data[tail] = 0;
> +
> +	if (++tail == HV_SYNIC_EVENT_RING_MESSAGE_COUNT)
> +		tail = 0;
> +
> +	(*synic_eventring_tail)[sint_index] = tail;
> +
> +	return message;
> +}
> +
> +static bool
> +mshv_doorbell_isr(struct hv_message *msg)
> +{
> +	struct hv_notification_message_payload *notification;
> +	u32 port;
> +
> +	if (msg->header.message_type != HVMSG_SYNIC_SINT_INTERCEPT)
> +		return false;
> +
> +	notification = (struct hv_notification_message_payload *)msg->u.payload;
> +	if (notification->sint_index != HV_SYNIC_DOORBELL_SINT_INDEX)
> +		return false;
> +
> +	while ((port = synic_event_ring_get_queued_port(HV_SYNIC_DOORBELL_SINT_INDEX))) {
> +		struct port_table_info ptinfo = { 0 };
> +
> +		if (mshv_portid_lookup(port, &ptinfo)) {
> +			pr_debug("Failed to get port info from port_table!\n");
> +			continue;
> +		}
> +
> +		if (ptinfo.hv_port_type != HV_PORT_TYPE_DOORBELL) {
> +			pr_debug("Not a doorbell port!, port: %d, port_type: %d\n",
> +				 port, ptinfo.hv_port_type);
> +			continue;
> +		}
> +
> +		/* Invoke the callback */
> +		ptinfo.hv_port_doorbell.doorbell_cb(port,
> +						 ptinfo.hv_port_doorbell.data);
> +	}
> +
> +	return true;
> +}
> +
> +static bool mshv_async_call_completion_isr(struct hv_message *msg)
> +{
> +	bool handled = false;
> +	struct hv_async_completion_message_payload *async_msg;
> +	struct mshv_partition *partition;
> +	u64 partition_id;
> +
> +	if (msg->header.message_type != HVMSG_ASYNC_CALL_COMPLETION)
> +		goto out;
> +
> +	async_msg =
> +		(struct hv_async_completion_message_payload *)msg->u.payload;
> +
> +	partition_id = async_msg->partition_id;
> +
> +	/*
> +	 * Hold this lock for the rest of the isr, because the partition could
> +	 * be released anytime.
> +	 * e.g. the MSHV_RUN_VP thread could wake on another cpu; it could
> +	 * release the partition unless we hold this!
> +	 */
> +	rcu_read_lock();
> +
> +	partition = mshv_partition_find(partition_id);
> +	partition->async_hypercall_status = async_msg->status;
> +
> +	if (unlikely(!partition)) {
> +		pr_debug("failed to find partition %llu\n", partition_id);
> +		goto unlock_out;
> +	}
> +
> +	complete(&partition->async_hypercall);
> +
> +	handled = true;
> +
> +unlock_out:
> +	rcu_read_unlock();
> +out:
> +	return handled;
> +}
> +
> +static void kick_vp(struct mshv_vp *vp)
> +{
> +	atomic64_inc(&vp->run.vp_signaled_count);
> +	vp->run.kicked_by_hv = 1;
> +	wake_up(&vp->run.vp_suspend_queue);
> +}
> +
> +static void
> +handle_bitset_message(const struct hv_vp_signal_bitset_scheduler_message *msg)
> +{
> +	int bank_idx, vps_signaled = 0, bank_mask_size;
> +	struct mshv_partition *partition;
> +	const struct hv_vpset *vpset;
> +	const u64 *bank_contents;
> +	u64 partition_id = msg->partition_id;
> +
> +	if (msg->vp_bitset.bitset.format != HV_GENERIC_SET_SPARSE_4K) {
> +		pr_debug("scheduler message format is not HV_GENERIC_SET_SPARSE_4K");
> +		return;
> +	}
> +
> +	if (msg->vp_count == 0) {
> +		pr_debug("scheduler message with no VP specified");
> +		return;
> +	}
> +
> +	rcu_read_lock();
> +
> +	partition = mshv_partition_find(partition_id);
> +	if (unlikely(!partition)) {
> +		pr_debug("failed to find partition %llu\n", partition_id);
> +		goto unlock_out;
> +	}
> +
> +	vpset = &msg->vp_bitset.bitset;
> +
> +	bank_idx = -1;
> +	bank_contents = vpset->bank_contents;
> +	bank_mask_size = sizeof(vpset->valid_bank_mask) * BITS_PER_BYTE;
> +
> +	while (true) {
> +		int vp_bank_idx = -1;
> +		int vp_bank_size = sizeof(*bank_contents) * BITS_PER_BYTE;
> +		int vp_index;
> +
> +		bank_idx = find_next_bit((unsigned long *)&vpset->valid_bank_mask,
> +					 bank_mask_size, bank_idx + 1);
> +		if (bank_idx == bank_mask_size)
> +			break;
> +
> +		while (true) {
> +			struct mshv_vp *vp;
> +
> +			vp_bank_idx = find_next_bit((unsigned long *)bank_contents,
> +						    vp_bank_size, vp_bank_idx + 1);
> +			if (vp_bank_idx == vp_bank_size)
> +				break;
> +
> +			vp_index = (bank_idx << HV_GENERIC_SET_SHIFT) + vp_bank_idx;

This would be clearer if just multiplied by bank_mask_size instead of shifting.
Since the compiler knows the constant value of bank_mask_size, it should generate
the same code as the shift.

> +
> +			/* This shouldn't happen, but just in case. */
> +			if (unlikely(vp_index >= MSHV_MAX_VPS)) {
> +				pr_debug("VP index %u out of bounds\n",
> +					 vp_index);
> +				goto unlock_out;
> +			}
> +
> +			vp = partition->pt_vp_array[vp_index];
> +			if (unlikely(!vp)) {
> +				pr_debug("failed to find VP %u\n", vp_index);
> +				goto unlock_out;
> +			}
> +
> +			kick_vp(vp);
> +			vps_signaled++;
> +		}
> +
> +		bank_contents++;
> +	}
> +
> +unlock_out:
> +	rcu_read_unlock();
> +
> +	if (vps_signaled != msg->vp_count)
> +		pr_debug("asked to signal %u VPs but only did %u\n",
> +			 msg->vp_count, vps_signaled);
> +}
> +
> +static void
> +handle_pair_message(const struct hv_vp_signal_pair_scheduler_message *msg)
> +{
> +	struct mshv_partition *partition = NULL;
> +	struct mshv_vp *vp;
> +	int idx;
> +
> +	rcu_read_lock();
> +
> +	for (idx = 0; idx < msg->vp_count; idx++) {
> +		u64 partition_id = msg->partition_ids[idx];
> +		u32 vp_index = msg->vp_indexes[idx];
> +
> +		if (idx == 0 || partition->pt_id != partition_id) {
> +			partition = mshv_partition_find(partition_id);
> +			if (unlikely(!partition)) {
> +				pr_debug("failed to find partition %llu\n",
> +					 partition_id);
> +				break;
> +			}
> +		}
> +
> +		/* This shouldn't happen, but just in case. */
> +		if (unlikely(vp_index >= MSHV_MAX_VPS)) {
> +			pr_debug("VP index %u out of bounds\n", vp_index);
> +			break;
> +		}
> +
> +		vp = partition->pt_vp_array[vp_index];
> +		if (!vp) {
> +			pr_debug("failed to find VP %u\n", vp_index);
> +			break;
> +		}
> +
> +		kick_vp(vp);
> +	}
> +
> +	rcu_read_unlock();
> +}
> +
> +static bool
> +mshv_scheduler_isr(struct hv_message *msg)
> +{
> +	if (msg->header.message_type != HVMSG_SCHEDULER_VP_SIGNAL_BITSET &&
> +	    msg->header.message_type != HVMSG_SCHEDULER_VP_SIGNAL_PAIR)
> +		return false;
> +
> +	if (msg->header.message_type == HVMSG_SCHEDULER_VP_SIGNAL_BITSET)
> +		handle_bitset_message((struct hv_vp_signal_bitset_scheduler_message *)
> +				      msg->u.payload);
> +	else
> +		handle_pair_message((struct hv_vp_signal_pair_scheduler_message *)
> +				    msg->u.payload);
> +
> +	return true;
> +}
> +
> +static bool
> +mshv_intercept_isr(struct hv_message *msg)
> +{
> +	struct mshv_partition *partition;
> +	bool handled = false;
> +	struct mshv_vp *vp;
> +	u64 partition_id;
> +	u32 vp_index;
> +
> +	partition_id = msg->header.sender;
> +
> +	rcu_read_lock();
> +
> +	partition = mshv_partition_find(partition_id);
> +	if (unlikely(!partition)) {
> +		pr_debug("failed to find partition %llu\n",
> +			 partition_id);
> +		goto unlock_out;
> +	}
> +
> +	if (msg->header.message_type == HVMSG_X64_APIC_EOI) {
> +		/*
> +		 * Check if this gsi is registered in the
> +		 * ack_notifier list and invoke the callback
> +		 * if registered.
> +		 */
> +
> +		/*
> +		 * If there is a notifier, the ack callback is supposed
> +		 * to handle the VMEXIT. So we need not pass this message
> +		 * to vcpu thread.
> +		 */
> +		struct hv_x64_apic_eoi_message *eoi_msg =
> +			(struct hv_x64_apic_eoi_message *)&msg->u.payload[0];
> +
> +		if (mshv_notify_acked_gsi(partition, eoi_msg->interrupt_vector)) {
> +			handled = true;
> +			goto unlock_out;
> +		}
> +	}
> +
> +	/*
> +	 * We should get an opaque intercept message here for all intercept
> +	 * messages, since we're using the mapped VP intercept message page.
> +	 *
> +	 * The intercept message will have been placed in intercept message
> +	 * page at this point.
> +	 *
> +	 * Make sure the message type matches our expectation.
> +	 */
> +	if (msg->header.message_type != HVMSG_OPAQUE_INTERCEPT) {
> +		pr_debug("wrong message type %d", msg->header.message_type);
> +		goto unlock_out;
> +	}
> +
> +	/*
> +	 * Since we directly index the vp, and it has to exist for us to be here
> +	 * (because the vp is only deleted when the partition is), no additional
> +	 * locking is needed here
> +	 */
> +	vp_index =
> +	       ((struct hv_opaque_intercept_message *)msg->u.payload)->vp_index;
> +	vp = partition->pt_vp_array[vp_index];
> +	if (unlikely(!vp)) {
> +		pr_debug("failed to find VP %u\n", vp_index);
> +		goto unlock_out;
> +	}
> +
> +	kick_vp(vp);
> +
> +	handled = true;
> +
> +unlock_out:
> +	rcu_read_unlock();
> +
> +	return handled;
> +}
> +
> +void mshv_isr(void)
> +{
> +	struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
> +	struct hv_message_page **msg_page = &spages->synic_message_page;
> +	struct hv_message *msg;
> +	bool handled;
> +
> +	if (unlikely(!(*msg_page))) {
> +		pr_debug("Missing synic page!\n");
> +		return;
> +	}
> +
> +	msg = &((*msg_page)->sint_message[HV_SYNIC_INTERCEPTION_SINT_INDEX]);
> +
> +	/*
> +	 * If the type isn't set, there isn't really a message;
> +	 * it may be some other hyperv interrupt
> +	 */
> +	if (msg->header.message_type == HVMSG_NONE)
> +		return;
> +
> +	handled = mshv_doorbell_isr(msg);
> +
> +	if (!handled)
> +		handled = mshv_scheduler_isr(msg);
> +
> +	if (!handled)
> +		handled = mshv_async_call_completion_isr(msg);
> +
> +	if (!handled)
> +		handled = mshv_intercept_isr(msg);
> +
> +	if (handled) {
> +		/*
> +		 * Acknowledge message with hypervisor if another message is
> +		 * pending.
> +		 */
> +		msg->header.message_type = HVMSG_NONE;
> +		/*
> +		 * Ensure the write is complete so the hypervisor will deliver
> +		 * the next message if available.
> +		 */
> +		mb();
> +		if (msg->header.message_flags.msg_pending)
> +			hv_set_non_nested_msr(HV_MSR_EOM, 0);
> +
> +#ifdef HYPERVISOR_CALLBACK_VECTOR
> +		add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR);
> +#endif
> +	} else {
> +		pr_warn_once("%s: unknown message type 0x%x\n", __func__,
> +			     msg->header.message_type);
> +	}
> +}
> +
> +int mshv_synic_init(unsigned int cpu)
> +{
> +	union hv_synic_simp simp;
> +	union hv_synic_siefp siefp;
> +	union hv_synic_sirbp sirbp;
> +#ifdef HYPERVISOR_CALLBACK_VECTOR
> +	union hv_synic_sint sint;
> +#endif
> +	union hv_synic_scontrol sctrl;
> +	struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
> +	struct hv_message_page **msg_page = &spages->synic_message_page;
> +	struct hv_synic_event_flags_page **event_flags_page =
> +			&spages->synic_event_flags_page;
> +	struct hv_synic_event_ring_page **event_ring_page =
> +			&spages->synic_event_ring_page;
> +
> +	/* Setup the Synic's message page */
> +	simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
> +	simp.simp_enabled = true;
> +	*msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
> +			     HV_HYP_PAGE_SIZE,
> +			     MEMREMAP_WB);
> +
> +	if (!(*msg_page))
> +		return -EFAULT;
> +
> +	hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
> +
> +	/* Setup the Synic's event flags page */
> +	siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
> +	siefp.siefp_enabled = true;
> +	*event_flags_page = memremap(siefp.base_siefp_gpa << PAGE_SHIFT,
> +				     PAGE_SIZE, MEMREMAP_WB);
> +
> +	if (!(*event_flags_page))
> +		goto cleanup;
> +
> +	hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
> +
> +	/* Setup the Synic's event ring page */
> +	sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
> +	sirbp.sirbp_enabled = true;
> +	*event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
> +				    PAGE_SIZE, MEMREMAP_WB);
> +
> +	if (!(*event_ring_page))
> +		goto cleanup;
> +
> +	hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> +
> +#ifdef HYPERVISOR_CALLBACK_VECTOR
> +	/* Enable intercepts */
> +	sint.as_uint64 = 0;
> +	sint.vector = HYPERVISOR_CALLBACK_VECTOR;
> +	sint.masked = false;
> +	sint.auto_eoi = hv_recommend_using_aeoi();
> +	hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
> +			      sint.as_uint64);
> +
> +	/* Doorbell SINT */
> +	sint.as_uint64 = 0;
> +	sint.vector = HYPERVISOR_CALLBACK_VECTOR;
> +	sint.masked = false;
> +	sint.as_intercept = 1;
> +	sint.auto_eoi = hv_recommend_using_aeoi();
> +	hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
> +			      sint.as_uint64);
> +#endif
> +
> +	/* Enable global synic bit */
> +	sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
> +	sctrl.enable = 1;
> +	hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
> +
> +	return 0;
> +
> +cleanup:
> +	if (*event_ring_page) {
> +		sirbp.sirbp_enabled = false;
> +		hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> +		memunmap(*event_ring_page);
> +	}
> +	if (*event_flags_page) {
> +		siefp.siefp_enabled = false;
> +		hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
> +		memunmap(*event_flags_page);
> +	}
> +	if (*msg_page) {
> +		simp.simp_enabled = false;
> +		hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
> +		memunmap(*msg_page);
> +	}
> +
> +	return -EFAULT;
> +}
> +
> +int mshv_synic_cleanup(unsigned int cpu)
> +{
> +	union hv_synic_sint sint;
> +	union hv_synic_simp simp;
> +	union hv_synic_siefp siefp;
> +	union hv_synic_sirbp sirbp;
> +	union hv_synic_scontrol sctrl;
> +	struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
> +	struct hv_message_page **msg_page = &spages->synic_message_page;
> +	struct hv_synic_event_flags_page **event_flags_page =
> +		&spages->synic_event_flags_page;
> +	struct hv_synic_event_ring_page **event_ring_page =
> +		&spages->synic_event_ring_page;
> +
> +	/* Disable the interrupt */
> +	sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX);
> +	sint.masked = true;
> +	hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
> +			      sint.as_uint64);
> +
> +	/* Disable Doorbell SINT */
> +	sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX);
> +	sint.masked = true;
> +	hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
> +			      sint.as_uint64);
> +
> +	/* Disable Synic's event ring page */
> +	sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
> +	sirbp.sirbp_enabled = false;
> +	hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> +	memunmap(*event_ring_page);
> +
> +	/* Disable Synic's event flags page */
> +	siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
> +	siefp.siefp_enabled = false;
> +	hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
> +	memunmap(*event_flags_page);
> +
> +	/* Disable Synic's message page */
> +	simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
> +	simp.simp_enabled = false;
> +	hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
> +	memunmap(*msg_page);
> +
> +	/* Disable global synic bit */
> +	sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
> +	sctrl.enable = 0;
> +	hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
> +
> +	return 0;
> +}
> +
> +int
> +mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, void *data,
> +		       u64 gpa, u64 val, u64 flags)
> +{
> +	struct hv_connection_info connection_info = { 0 };
> +	union hv_connection_id connection_id = { 0 };
> +	struct port_table_info *port_table_info;
> +	struct hv_port_info port_info = { 0 };
> +	union hv_port_id port_id = { 0 };
> +	int ret;
> +
> +	port_table_info = kmalloc(sizeof(*port_table_info), GFP_KERNEL);
> +	if (!port_table_info)
> +		return -ENOMEM;
> +
> +	port_table_info->hv_port_type = HV_PORT_TYPE_DOORBELL;
> +	port_table_info->hv_port_doorbell.doorbell_cb = doorbell_cb;
> +	port_table_info->hv_port_doorbell.data = data;
> +	ret = mshv_portid_alloc(port_table_info);
> +	if (ret < 0) {
> +		kfree(port_table_info);
> +		return ret;
> +	}
> +
> +	port_id.u.id = ret;
> +	port_info.port_type = HV_PORT_TYPE_DOORBELL;
> +	port_info.doorbell_port_info.target_sint = HV_SYNIC_DOORBELL_SINT_INDEX;
> +	port_info.doorbell_port_info.target_vp = HV_ANY_VP;
> +	ret = hv_call_create_port(hv_current_partition_id, port_id, partition_id,
> +				  &port_info,
> +				  0, 0, NUMA_NO_NODE);
> +
> +	if (ret < 0) {
> +		mshv_portid_free(port_id.u.id);
> +		return ret;
> +	}
> +
> +	connection_id.u.id = port_id.u.id;
> +	connection_info.port_type = HV_PORT_TYPE_DOORBELL;
> +	connection_info.doorbell_connection_info.gpa = gpa;
> +	connection_info.doorbell_connection_info.trigger_value = val;
> +	connection_info.doorbell_connection_info.flags = flags;
> +
> +	ret = hv_call_connect_port(hv_current_partition_id, port_id, partition_id,
> +				   connection_id, &connection_info, 0, NUMA_NO_NODE);
> +	if (ret < 0) {
> +		hv_call_delete_port(hv_current_partition_id, port_id);
> +		mshv_portid_free(port_id.u.id);
> +		return ret;
> +	}
> +
> +	// lets use the port_id as the doorbell_id
> +	return port_id.u.id;
> +}
> +
> +void
> +mshv_unregister_doorbell(u64 partition_id, int doorbell_portid)
> +{
> +	union hv_port_id port_id = { 0 };
> +	union hv_connection_id connection_id = { 0 };
> +
> +	connection_id.u.id = doorbell_portid;
> +	hv_call_disconnect_port(partition_id, connection_id);
> +
> +	port_id.u.id = doorbell_portid;
> +	hv_call_delete_port(hv_current_partition_id, port_id);
> +
> +	mshv_portid_free(doorbell_portid);
> +}
> diff --git a/include/uapi/linux/mshv.h b/include/uapi/linux/mshv.h
> new file mode 100644
> index 000000000000..9468f66c5658
> --- /dev/null
> +++ b/include/uapi/linux/mshv.h
> @@ -0,0 +1,287 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Userspace interfaces for /dev/mshv* devices and derived fds
> + *
> + * This file is divided into sections containing data structures and IOCTLs for
> + * a particular set of related devices or derived file descriptors.
> + *
> + * The IOCTL definitions are at the end of each section. They are grouped by
> + * device/fd, so that new IOCTLs can easily be added with a monotonically
> + * increasing number.
> + */
> +#ifndef _UAPI_LINUX_MSHV_H
> +#define _UAPI_LINUX_MSHV_H
> +
> +#include <linux/types.h>
> +
> +#define MSHV_IOCTL	0xB8
> +
> +/*
> + *******************************************
> + * Entry point to main VMM APIs: /dev/mshv *
> + *******************************************
> + */
> +
> +enum {
> +	MSHV_PT_BIT_LAPIC,
> +	MSHV_PT_BIT_X2APIC,
> +	MSHV_PT_BIT_GPA_SUPER_PAGES,
> +	MSHV_PT_BIT_COUNT,
> +};
> +
> +#define MSHV_PT_FLAGS_MASK ((1 << MSHV_PT_BIT_COUNT) - 1)
> +
> +enum {
> +	MSHV_PT_ISOLATION_NONE,
> +	MSHV_PT_ISOLATION_COUNT,
> +};
> +
> +/**
> + * struct mshv_create_partition - arguments for MSHV_CREATE_PARTITION
> + * @pt_flags: Bitmask of 1 << MSHV_PT_BIT_*
> + * @pt_isolation: MSHV_PT_ISOLATION_*
> + *
> + * Returns a file descriptor to act as a handle to a guest partition.
> + * At this point the partition is not yet initialized in the hypervisor.
> + * Some operations must be done with the partition in this state, e.g. setting
> + * so-called "early" partition properties. The partition can then be
> + * initialized with MSHV_INITIALIZE_PARTITION.
> + */
> +struct mshv_create_partition {
> +	__u64 pt_flags;
> +	__u64 pt_isolation;
> +};
> +
> +/* /dev/mshv */
> +#define MSHV_CREATE_PARTITION	_IOW(MSHV_IOCTL, 0x00, struct mshv_create_partition)
> +
> +/*
> + ************************
> + * Child partition APIs *
> + ************************
> + */
> +
> +struct mshv_create_vp {
> +	__u32 vp_index;
> +};
> +
> +enum {
> +	MSHV_SET_MEM_BIT_WRITABLE,
> +	MSHV_SET_MEM_BIT_EXECUTABLE,
> +	MSHV_SET_MEM_BIT_UNMAP,
> +	MSHV_SET_MEM_BIT_COUNT
> +};
> +
> +#define MSHV_SET_MEM_FLAGS_MASK ((1 << MSHV_SET_MEM_BIT_COUNT) - 1)
> +
> +/**
> + * struct mshv_user_mem_region - arguments for MSHV_SET_GUEST_MEMORY
> + * @size: Size of the memory region (bytes). Must be aligned to PAGE_SIZE
> + * @guest_pfn: Base guest page number to map
> + * @userspace_addr: Base address of userspace memory. Must be aligned to
> + *                  PAGE_SIZE
> + * @flags: Bitmask of 1 << MSHV_SET_MEM_BIT_*. If (1 << MSHV_SET_MEM_BIT_UNMAP)
> + *         is set, ignore other bits.
> + * @rsvd: MBZ
> + *
> + * Map or unmap a region of userspace memory to Guest Physical Addresses (GPA).
> + * Mappings can't overlap in GPA space or userspace.
> + * To unmap, these fields must match an existing mapping.
> + */
> +struct mshv_user_mem_region {
> +	__u64 size;
> +	__u64 guest_pfn;
> +	__u64 userspace_addr;
> +	__u8 flags;
> +	__u8 rsvd[7];
> +};
> +
> +enum {
> +	MSHV_IRQFD_BIT_DEASSIGN,
> +	MSHV_IRQFD_BIT_RESAMPLE,
> +	MSHV_IRQFD_BIT_COUNT,
> +};
> +
> +#define MSHV_IRQFD_FLAGS_MASK	((1 << MSHV_IRQFD_BIT_COUNT) - 1)
> +
> +struct mshv_user_irqfd {
> +	__s32 fd;
> +	__s32 resamplefd;
> +	__u32 gsi;
> +	__u32 flags;
> +};
> +
> +enum {
> +	MSHV_IOEVENTFD_BIT_DATAMATCH,
> +	MSHV_IOEVENTFD_BIT_PIO,
> +	MSHV_IOEVENTFD_BIT_DEASSIGN,
> +	MSHV_IOEVENTFD_BIT_COUNT,
> +};
> +
> +#define MSHV_IOEVENTFD_FLAGS_MASK	((1 << MSHV_IOEVENTFD_BIT_COUNT) - 1)
> +
> +struct mshv_user_ioeventfd {
> +	__u64 datamatch;
> +	__u64 addr;	   /* legal pio/mmio address */
> +	__u32 len;	   /* 1, 2, 4, or 8 bytes    */
> +	__s32 fd;
> +	__u32 flags;
> +	__u8  rsvd[4];
> +};
> +
> +struct mshv_user_irq_entry {
> +	__u32 gsi;
> +	__u32 address_lo;
> +	__u32 address_hi;
> +	__u32 data;
> +};
> +
> +struct mshv_user_irq_table {
> +	__u32 nr;
> +	__u32 rsvd; /* MBZ */
> +	struct mshv_user_irq_entry entries[];
> +};
> +
> +enum {
> +	MSHV_GPAP_ACCESS_TYPE_ACCESSED = 0,
> +	MSHV_GPAP_ACCESS_TYPE_DIRTY,
> +	MSHV_GPAP_ACCESS_TYPE_COUNT		/* Count of enum members */
> +};
> +
> +enum {
> +	MSHV_GPAP_ACCESS_OP_NOOP = 0,
> +	MSHV_GPAP_ACCESS_OP_CLEAR,
> +	MSHV_GPAP_ACCESS_OP_SET,
> +	MSHV_GPAP_ACCESS_OP_COUNT		/* Count of enum members */
> +};

Any reason these two enums explicitly set the first value to 0, while
earlier enums do not?  This is another case of there being a difference,
and me wondering if it's just gratuitous or if there's a specific reason.
Consistency is a good thing!

> +
> +/**
> + * struct mshv_gpap_access_bitmap - arguments for MSHV_GET_GPAP_ACCESS_BITMAP
> + * @access_type: MSHV_GPAP_ACCESS_TYPE_* - The type of access to record in the
> + *               bitmap
> + * @access_op: MSHV_GPAP_ACCESS_OP_* - Allows an optional clear or set of all
> + *             the access states in the range, after retrieving the current
> + *             states.
> + * @rsvd: MBZ
> + * @page_count: in: number of pages
> + *              out: on error, number of states successfully written to bitmap
> + * @gpap_base: Base gpa page number
> + * @bitmap_ptr: Output buffer for bitmap, at least (page_count + 7) / 8 bytes
> + *
> + * Retrieve a bitmap of either ACCESSED or DIRTY bits for a given range of guest
> + * memory, and optionally clear or set the bits.
> + */
> +struct mshv_gpap_access_bitmap {
> +	__u8 access_type;
> +	__u8 access_op;
> +	__u8 rsvd[6];
> +	__u64 page_count;
> +	__u64 gpap_base;
> +	__u64 bitmap_ptr;
> +};
> +
> +/**
> + * struct mshv_root_hvcall - arguments for MSHV_ROOT_HVCALL
> + * @code: Hypercall code (HVCALL_*)
> + * @reps: in: Rep count ('repcount')
> + *	  out: Reps completed ('repcomp'). MBZ unless rep hvcall
> + * @in_sz: Size of input incl rep data. <= HV_HYP_PAGE_SIZE
> + * @out_sz: Size of output buffer. <= HV_HYP_PAGE_SIZE. MBZ if out_ptr is 0
> + * @status: in: MBZ
> + *	    out: HV_STATUS_* from hypercall
> + * @rsvd: MBZ
> + * @in_ptr: Input data buffer (struct hv_input_*). If used with partition or
> + *	    vp fd, partition id field is populated by kernel.
> + * @out_ptr: Output data buffer (optional)
> + */
> +struct mshv_root_hvcall {
> +	__u16 code;
> +	__u16 reps;
> +	__u16 in_sz;
> +	__u16 out_sz;
> +	__u16 status;
> +	__u8 rsvd[6];
> +	__u64 in_ptr;
> +	__u64 out_ptr;
> +};
> +
> +/* Partition fds created with MSHV_CREATE_PARTITION */
> +#define MSHV_INITIALIZE_PARTITION	_IO(MSHV_IOCTL, 0x00)
> +#define MSHV_CREATE_VP			_IOW(MSHV_IOCTL, 0x01, struct mshv_create_vp)
> +#define MSHV_SET_GUEST_MEMORY		_IOW(MSHV_IOCTL, 0x02, struct mshv_user_mem_region)
> +#define MSHV_IRQFD			_IOW(MSHV_IOCTL, 0x03, struct mshv_user_irqfd)
> +#define MSHV_IOEVENTFD			_IOW(MSHV_IOCTL, 0x04, struct mshv_user_ioeventfd)
> +#define MSHV_SET_MSI_ROUTING		_IOW(MSHV_IOCTL, 0x05, struct mshv_user_irq_table)
> +#define MSHV_GET_GPAP_ACCESS_BITMAP	_IOWR(MSHV_IOCTL, 0x06, struct mshv_gpap_access_bitmap)
> +/* Generic hypercall */
> +#define MSHV_ROOT_HVCALL		_IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall)

I really don't like having the ioctl numbers here overlap with the /dev/mshv ioctls.
There's just no need to overlap. But I realize changing it now is a big hassle.

> +
> +/*
> + ********************************
> + * VP APIs for child partitions *
> + ********************************
> + */
> +
> +#define MSHV_RUN_VP_BUF_SZ 256
> +
> +/*
> + * Map various VP state pages to userspace.
> + * Multiply the offset by PAGE_SIZE before being passed as the 'offset'
> + * argument to mmap().
> + * e.g.
> + * void *reg_page = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
> + *                       MAP_SHARED, vp_fd,
> + *                       MSHV_VP_MMAP_OFFSET_REGISTERS * PAGE_SIZE);
> + */

This is interesting.  I would not have thought PAGE_SIZE is available
in the UAPI.  You must use something like the getpagesize() call. I know
the root partition can only run with a 4K page size, but the symbol
"PAGE_SIZE" is probably kernel code only.

> +enum {
> +	MSHV_VP_MMAP_OFFSET_REGISTERS,
> +	MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE,
> +	MSHV_VP_MMAP_OFFSET_GHCB,
> +	MSHV_VP_MMAP_OFFSET_COUNT
> +};
> +
> +/**
> + * struct mshv_run_vp - argument for MSHV_RUN_VP
> + * @msg_buf: On success, the intercept message is copied here. It can be
> + *           interpreted using the relevant hypervisor definitions.
> + */
> +struct mshv_run_vp {
> +	__u8 msg_buf[MSHV_RUN_VP_BUF_SZ];
> +};
> +
> +enum {
> +	MSHV_VP_STATE_LAPIC,		/* Local interrupt controller state (either arch) */
> +	MSHV_VP_STATE_XSAVE,		/* XSAVE data in compacted form (x86_64) */
> +	MSHV_VP_STATE_SIMP,
> +	MSHV_VP_STATE_SIEFP,
> +	MSHV_VP_STATE_SYNTHETIC_TIMERS,
> +	MSHV_VP_STATE_COUNT,
> +};
> +
> +/**
> + * struct mshv_get_set_vp_hvcall - arguments for MSHV_[GET,SET]_VP_STATE

s/hvcall/state/

> + * @type: MSHV_VP_STATE_*
> + * @rsvd: MBZ
> + * @buf_sz: in: 4k page-aligned size of buffer
> + *          out: Actual size of data (on EINVAL, check this to see if buffer
> + *               was too small)
> + * @buf_ptr: 4k page-aligned data buffer
> + */
> +struct mshv_get_set_vp_state {
> +	__u8 type;
> +	__u8 rsvd[3];
> +	__u32 buf_sz;
> +	__u64 buf_ptr;
> +};
> +
> +/* VP fds created with MSHV_CREATE_VP */
> +#define MSHV_RUN_VP			_IOR(MSHV_IOCTL, 0x00, struct mshv_run_vp)
> +#define MSHV_GET_VP_STATE		_IOWR(MSHV_IOCTL, 0x01, struct mshv_get_set_vp_state)
> +#define MSHV_SET_VP_STATE		_IOWR(MSHV_IOCTL, 0x02, struct mshv_get_set_vp_state)
> +/*
> + * Generic hypercall
> + * Defined above in partition IOCTLs, avoid redefining it here
> + * #define MSHV_ROOT_HVCALL			_IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall)
> + */
> +
> +#endif
> --
> 2.34.1



From bhe at redhat.com  Mon Mar 17 16:52:00 2025
From: bhe at redhat.com (Baoquan He)
Date: Tue, 18 Mar 2025 07:52:00 +0800
Subject: [PATCH v3 1/5] arch/x86: Drop own definition of pgd,p4d_leaf
In-Reply-To: <c81566e5df160587de50f9095d0ec377114fdba8.1720854135.git.christophe.leroy@csgroup.eu>
References: <c81566e5df160587de50f9095d0ec377114fdba8.1720854135.git.christophe.leroy@csgroup.eu>
Message-ID: <Z9i1oGaAR9c2MPbN@MiWiFi-R3L-srv>

On 07/13/24 at 09:08am, Christophe Leroy wrote:
> From: Oscar Salvador <osalvador at suse.de>
> 
> We provide generic definitions of pXd_leaf in pgtable.h when the arch
> do not define their own, where the generic pXd_leaf always return false.
> 
> Although x86 defines {pgd,p4d}_leaf, they end up being a no-op, so drop them
> and make them fallback to the generic one.
> 
> Signed-off-by: Oscar Salvador <osalvador at suse.de>
> Signed-off-by: Christophe Leroy <christophe.leroy at csgroup.eu>
> Reviewed-by: Peter Xu <peterx at redhat.com>
> ---
>  arch/x86/include/asm/pgtable.h | 10 ----------
>  1 file changed, 10 deletions(-)

Seems this series is missed. It does do a great clean up.

> 
> diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
> index 65b8e5bb902c..772f778bac06 100644
> --- a/arch/x86/include/asm/pgtable.h
> +++ b/arch/x86/include/asm/pgtable.h
> @@ -252,13 +252,6 @@ static inline unsigned long pgd_pfn(pgd_t pgd)
>  	return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT;
>  }
>  
> -#define p4d_leaf p4d_leaf
> -static inline bool p4d_leaf(p4d_t p4d)
> -{
> -	/* No 512 GiB pages yet */
> -	return 0;
> -}
> -
>  #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
>  
>  #define pmd_leaf pmd_leaf
> @@ -1396,9 +1389,6 @@ static inline bool pgdp_maps_userspace(void *__ptr)
>  	return (((ptr & ~PAGE_MASK) / sizeof(pgd_t)) < PGD_KERNEL_START);
>  }
>  
> -#define pgd_leaf	pgd_leaf
> -static inline bool pgd_leaf(pgd_t pgd) { return false; }
> -
>  #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION
>  /*
>   * All top-level MITIGATION_PAGE_TABLE_ISOLATION page tables are order-1 pages
> -- 
> 2.44.0
> 
> 



From Thinh.Nguyen at synopsys.com  Mon Mar 17 17:12:16 2025
From: Thinh.Nguyen at synopsys.com (Thinh Nguyen)
Date: Tue, 18 Mar 2025 00:12:16 +0000
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
 <20250314211411.l5taj5nysvcalfyz@synopsys.com>
 <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>
Message-ID: <20250318001211.tnjwfckt5j4fbvjf@synopsys.com>

On Mon, Mar 17, 2025, Mike Looijmans wrote:
> On 14-03-2025 22:14, Thinh Nguyen wrote:
> > On Fri, Mar 14, 2025, Mike Looijmans wrote:
> > > Set the gpio to "high" on acquisition, instead of acquiring it in low
> > > state and then immediately setting it high again. This prevents a
> > > short "spike" on the reset signal.
> > How does this affect the current programming flow beside preventing a
> > spike to the reset signal?
> 
> I don't understand your question. What "programming flow" are you referring
> to?

It's not obvious to me if this is an error in Xilinx documentation, the
driver issue, or whether this is found through experiment. Since I don't
have the info of this platform, it would help to know where the source
of error is so we can document this in the code or change-log.

> 
> The reset sequence was just plain wrong, the issue is almost the same as the

Do we need a fix tag and add to stable then?

> one described in this commit:
> e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"
> 
> Note that I see this high-low-high-low double reset toggle in many Xilinx
> software drivers, they seem to teach that at the Xilinx academy or so.
> 
> 
> > > Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> > > ---
> > > 
> > >   drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
> > >   1 file changed, 1 insertion(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> > > index a33a42ba0249..a159a511483b 100644
> > > --- a/drivers/usb/dwc3/dwc3-xilinx.c
> > > +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> > > @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
> > >   skip_usb3_phy:
> > >   	/* ulpi reset via gpio-modepin or gpio-framework driver */
> > > -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> > >   	if (IS_ERR(reset_gpio)) {
> > >   		return dev_err_probe(dev, PTR_ERR(reset_gpio),
> > >   				     "Failed to request reset GPIO\n");
> > > @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
> > >   	if (reset_gpio) {
> > >   		/* Toggle ulpi to reset the phy. */
> > Does the comment above still apply?
> Now you mention it, the comment never made any sense anyway.
> 

Then can we remove it?

> 
> > > -		gpiod_set_value_cansleep(reset_gpio, 1);
> > >   		usleep_range(5000, 10000);
> > Do we still need this usleep_range here?
> 
> Yes, this is the "reset active" time.
> 

But why do we need 2 calls to usleep_range? From just looking at this
here, it appears that the first was intended for the removed
gpiod_set_value_cansleep(reset_gpio, 1). If this "reset active" time is
needed irrespective of the existent reset_gpio, then shouldn't it be set
outside of this if statement?

BR,
Thinh

> 
> 
> > 
> > BR,
> > Thinh
> > 
> > >   		gpiod_set_value_cansleep(reset_gpio, 0);
> > >   		usleep_range(5000, 10000);
> > > -- 
> > > 2.43.0
> > > 
> > > 
> > > Met vriendelijke groet / kind regards,
> > > 
> > > Mike Looijmans
> > > 
> > > 
> 
> -- 
> Mike Looijmans
> System Expert
> 
> TOPIC Embedded Products B.V.
> Materiaalweg 4, 5681 RJ Best
> The Netherlands
> 
> T: +31 (0) 499 33 69 69
> E: mike.looijmans at topic.nl
> W: https://urldefense.com/v3/__http://www.topic.nl__;!!A4F2R9G_pg!e45B0wD5dvB4NV8gz5JjIWaRTQrX9M2uE0ouoBVX4TQC8sKqtYRL8rJY3y2bb061gzSoGL0FOPJv-3-adkP1b3ldzRZnxdY$
> 
> 
> 

From andrew at codeconstruct.com.au  Mon Mar 17 17:30:21 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:00:21 +1030
Subject: [PATCH] watchdog: aspeed: fix 64-bit division
In-Reply-To: <20250314160248.502324-1-arnd@kernel.org>
References: <20250314160248.502324-1-arnd@kernel.org>
Message-ID: <3c16b98f113fa8918c879a16580811556b0c35c1.camel@codeconstruct.com.au>

On Fri, 2025-03-14 at 17:02 +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> On 32-bit architectures, the new calculation causes a build failure:
> 
> ld.lld-21: error: undefined symbol: __aeabi_uldivmod
> 
> Since neither value is ever larger than a register, cast both
> sides into a uintptr_t.
> 
> Fixes: 5c03f9f4d362 ("watchdog: aspeed: Update bootstatus handling")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>

Thanks,

Andrew



From andrew at codeconstruct.com.au  Mon Mar 17 17:42:09 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:12:09 +1030
Subject: [PATCH v4 3/3] soc: aspeed: lpc-pcc: Add PCC controller support
In-Reply-To: <20250314112113.953238-4-kevin_chen@aspeedtech.com>
References: <20250314112113.953238-1-kevin_chen@aspeedtech.com>
	 <20250314112113.953238-4-kevin_chen@aspeedtech.com>
Message-ID: <3270a7ea55fa28253b435da0b0bbce3adfdc00eb.camel@codeconstruct.com.au>

On Fri, 2025-03-14 at 19:21 +0800, Kevin Chen wrote:
> +???????pcc->mdev.parent = dev;
> +???????pcc->mdev.minor = MISC_DYNAMIC_MINOR;
> +???????pcc->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
> DEVICE_NAME,
> +???????????????????????????????????????pcc->mdev_id);
> +???????pcc->mdev.fops = &pcc_fops;
> +???????rc = misc_register(&pcc->mdev);
> +???????if (rc) {
> +???????????????dev_err(dev, "Couldn't register misc device\n");
> +???????????????goto err_free_ida;
> +???????}

Just a note that this still isn't accounting for discussion on the
previous posting of the series putting the driver under
drivers/soc/aspeed:

https://lore.kernel.org/all/f7369d6205e05c7aac3f3de7cbd08c3b08960d75.camel at codeconstruct.com.au/

If we're not going to try make a common userspace behaviour over the
Aspeed snoop and PCC functions and the Nuvoton BPC function then I
think the behaviour of the chardev should at least be documented. But I
would rather that it were common to avoid headaches in userspace.

Andrew

From sw617.shin at samsung.com  Mon Mar 17 17:44:12 2025
From: sw617.shin at samsung.com (Sangwook Shin)
Date: Tue, 18 Mar 2025 09:44:12 +0900
Subject: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
 ExynosAutoV920 SoC
In-Reply-To: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
References: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
	<CGME20250318005143epcas2p40ebb1954bed8890aaf8d0a641f710423@epcas2p4.samsung.com>
Message-ID: <20250318004411.695786-1-sw617.shin@samsung.com>

From: Kyunghwan Seo <khwan.seo at samsung.com>

Fix the PMU register bits for the ExynosAutoV920 SoC.
This SoC has different bit information compared to its previous
version, ExynosAutoV9, and we have made the necessary adjustments.

rst_stat_bit:
    - ExynosAutoV920 cl0 : 0
    - ExynosAutoV920 cl1 : 1

cnt_en_bit:
    - ExynosAutoV920 cl0 : 8
    - ExynosAutoV920 cl1 : 8

Signed-off-by: Kyunghwan Seo <khwan.seo at samsung.com>
Reviewed-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Alim Akhtar <alim.akhtar at samsung.com>
Signed-off-by: Sangwook Shin <sw617.shin at samsung.com>
---
v1 -> v2: Restore previous email history and tags.

 drivers/watchdog/s3c2410_wdt.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 30450e99e5e9..bdd81d8074b2 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -72,6 +72,8 @@
 #define EXYNOS850_CLUSTER1_WDTRESET_BIT		23
 #define EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT	25
 #define EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT	24
+#define EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT	0
+#define EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT	1
 
 #define GS_CLUSTER0_NONCPU_OUT			0x1220
 #define GS_CLUSTER1_NONCPU_OUT			0x1420
@@ -312,9 +314,9 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl0 = {
 	.mask_bit = 2,
 	.mask_reset_inv = true,
 	.rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
-	.rst_stat_bit = EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT,
+	.rst_stat_bit = EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT,
 	.cnt_en_reg = EXYNOSAUTOV920_CLUSTER0_NONCPU_OUT,
-	.cnt_en_bit = 7,
+	.cnt_en_bit = 8,
 	.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
 		  QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
 		  QUIRK_HAS_DBGACK_BIT,
@@ -325,9 +327,9 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
 	.mask_bit = 2,
 	.mask_reset_inv = true,
 	.rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
-	.rst_stat_bit = EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT,
+	.rst_stat_bit = EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT,
 	.cnt_en_reg = EXYNOSAUTOV920_CLUSTER1_NONCPU_OUT,
-	.cnt_en_bit = 7,
+	.cnt_en_bit = 8,
 	.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
 		  QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
 		  QUIRK_HAS_DBGACK_BIT,
-- 
2.40.1



From sfr at canb.auug.org.au  Mon Mar 17 17:54:19 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Tue, 18 Mar 2025 11:54:19 +1100
Subject: linux-next: duplicate patch in the omap tree
Message-ID: <20250318115419.53442fce@canb.auug.org.au>

Hi all,

The following commit is also in the arm-soc-fixes tree as a different
commit (but the same patch):

  c2a5f8c4f28f ("ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP")

This is commit

  98f3ab18a0a5 ("ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP")

in the arm-soc fixes tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250318/3f3d0833/attachment.sig>

From andrew at codeconstruct.com.au  Mon Mar 17 17:58:28 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:28:28 +1030
Subject: [PATCH 03/18] rtc: aspeed: drop needless struct
 aspeed_rtc::rtc_dev member
In-Reply-To: <20250228-rtc-cleanups-v1-3-b44cec078481@linaro.org>
References: <20250228-rtc-cleanups-v1-0-b44cec078481@linaro.org>
	 <20250228-rtc-cleanups-v1-3-b44cec078481@linaro.org>
Message-ID: <3e6a356cf1e6f293a2218e1c006f0222c9e01fa6.camel@codeconstruct.com.au>

On Fri, 2025-02-28 at 14:07 +0000, Andr? Draszik wrote:
> The memory pointed to by the ::rtc_dev member is managed via devres,
> and no code in this driver uses it past _probe().
> 
> We can drop it from the structure and just use a local temporary
> variable, reducing runtime memory consumption by a few bytes.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From andrew at codeconstruct.com.au  Mon Mar 17 18:24:10 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:54:10 +1030
Subject: [PATCH 12/15] gpio: aspeed: use lock guards
In-Reply-To: <20250303-gpiochip-set-conversion-v1-12-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
	 <20250303-gpiochip-set-conversion-v1-12-1d5cceeebf8b@linaro.org>
Message-ID: <2cf6056212d0eaae0946fd374edce1947afed93f.camel@codeconstruct.com.au>

On Mon, 2025-03-03 at 14:18 +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> Reduce the code complexity by using automatic lock guards with the raw
> spinlock.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Nice!

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From andrew at codeconstruct.com.au  Mon Mar 17 18:25:06 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:55:06 +1030
Subject: [PATCH 13/15] gpio: aspeed: use new line value setter callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-13-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
	 <20250303-gpiochip-set-conversion-v1-13-1d5cceeebf8b@linaro.org>
Message-ID: <bbc06c8cfd3ccd1847ec309f0fe4af80649720d4.camel@codeconstruct.com.au>

On Mon, 2025-03-03 at 14:18 +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> struct gpio_chip now has callbacks for setting line values that return
> an integer, allowing to indicate failures. Convert the driver to using
> them.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From namhyung at kernel.org  Mon Mar 17 18:25:50 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 18:25:50 -0700
Subject: [PATCH 0/7] Add data type profiling support for arm64
In-Reply-To: <20250314162137.528204-1-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
Message-ID: <Z9jLngEKQpkZdqXQ@google.com>

Hello,

On Sat, Mar 15, 2025 at 12:21:30AM +0800, Li Huafei wrote:
> Hi,
> 
> This patchset supports arm64 perf data type profiling. Data type
> profiling was introduced by Namhyung [1], which associates PMU sampling
> (here referring to memory access-related event sampling) with the
> referenced data types, providing developers with an effective tool for
> analyzing the impact of memory usage and layout. For more detailed
> background, please refer to [2].

Thanks a lot for working on this!  I'm glad to see it running on more
architectures!  I'll review and leave comments on each patch.

Thanks,
Namhyung

> 
> Namhyung initially supported this feature only on x86, and later Athira
> added support for it on powerpc [3]. Unlike the x86 implementation, the
> powerpc implementation parses operands directly from raw instruction
> code instead of using the results from assembler disassembly. As Athira
> mentioned, this is mainly because not all memory access instructions on
> powerpc have explicit memory reference assembler notations '()' in their
> assembly code. On arm64, all memory access instructions have the
> notation '[]', so my implementation is similar to x86, using the
> disassembly results from objdump, llvm, or libcapstone, and parsing
> based on strings. I believe this has the advantage of reusing the
> complex instruction parsing logic of the assembler, but it may not
> perform as well as raw instruction parsing in terms of efficiency.
> 
> Below is a brief description of this patchset:
>  - Patch 1 first identifies load and store instructions and provides a
>    parsing function.
>  - Patches 2-3 are refactoring patches. They primarily move the code for
>    extracting registers and offsets to specific architecture
>    implementations. Additionally, a new callback function
>    'extract_reg_offset' is introduced to avoid having too many
>    architecture-specific implementations in the function
>    'annotate_get_insn_location()'.
>  - Patch 4 implements the extract_reg_offset callback for arm64.
>    Currently, it does not support parsing instructions with register
>    pairs or register offsets in operands. Register pairs often appear in
>    stack push/pop instructions, and register offsets are common when
>    accessing per-CPU variables, both of which require special handling.
>  - Patch 5 adds support for instruction tracing on arm64, primarily
>    addressing the issue where DWARF does not generate information for
>    intermediate pointers in pointer chains.
>  - Patches 6-7 further enhance instruction tracing. Patch 6 supports
>    parsing accesses to global variables, while Patch 7 focuses on
>    resolving accesses to the kernel's current pointer.
> 
> There are still areas for improvement in the current implementation:
>  - Support more types of memory access instructions, such as those
>    involving register pairs and register offsets.
>  - Handle all data processing instructions (e.g., mov, add), as these
>    instructions can change the state of registers and may affect the
>    accuracy of instruction tracking.
>  - Supporting parsing of special memory access scenarios like per-CPU
>    variables and arrays.
> 
> The patch set is based on 6.14-rc6 (commit 80e54e84911a). After applying
> this patch set, the date type profiling results on arm64 are as follows
> (SPE support is required):
> 
>  # perf mem record -a -K -- sleep 1
>  # perf annotate --data-type --type-stat --stdio
>  Only instruction-based sampling period is currently supported by Arm SPE.
>  Annotate data type stats:
>  total 556, ok 357 (64.2%), bad 199 (35.8%)
>  -----------------------------------------------------------
>          10 : no_sym
>          36 : no_insn_ops
>          65 : no_var
>          70 : no_typeinfo
>          18 : bad_offset
>          59 : insn_track
>  
>  Annotate type: 'struct rq' in [kernel.kallsyms] (29 samples):
>  ============================================================================
>   Percent     offset       size  field
>    100.00          0      0xe80  struct rq        {
>      0.00          0        0x4      raw_spinlock_t      __lock {
>      0.00          0        0x4          arch_spinlock_t raw_lock {
>      0.00          0        0x4              union        {
>      0.00          0        0x4                  atomic_t        val {
>      0.00          0        0x4                      int counter;
>                                                  };
>      0.00          0        0x2                  struct   {
>      0.00          0        0x1                      u8  locked;
>      0.00        0x1        0x1                      u8  pending;
>                                                  };
>      0.00          0        0x4                  struct   {
>      0.00          0        0x2                      u16 locked_pending;
>      0.00        0x2        0x2                      u16 tail;
>                                                  };
>                                              };
>                                          };
>                                      };
>     13.79        0x4        0x4      unsigned int        nr_running;
>     13.79        0x8        0x4      unsigned int        nr_numa_running;
>      0.00        0xc        0x4      unsigned int        nr_preferred_running;
>      0.00       0x10        0x4      unsigned int        numa_migrate_on;
>      0.00       0x18        0x8      long unsigned int   last_blocked_load_update_tick;
>      0.00       0x20        0x4      unsigned int        has_blocked_load;
>      0.00       0x40       0x20      call_single_data_t  nohz_csd {
>      0.00       0x40       0x10          struct __call_single_node       node {
>      0.00       0x40        0x8              struct llist_node   llist {
>      0.00       0x40        0x8                  struct llist_node*      next;
>                                              };
>      0.00       0x48        0x4              union        {
>      0.00       0x48        0x4                  unsigned int    u_flags;
>      0.00       0x48        0x4                  atomic_t        a_flags {
>      0.00       0x48        0x4                      int counter;
>                                                  };
>                                              };
>      ...
> 
> Thanks,
> Huafei
> 
> [1] https://lore.kernel.org/lkml/20231213001323.718046-1-namhyung at kernel.org/
> [2] https://lwn.net/Articles/955709/
> [3] https://lore.kernel.org/all/20240718084358.72242-1-atrajeev at linux.vnet.ibm.com/#r
> 
> Li Huafei (7):
>   perf annotate: Handle arm64 load and store instructions
>   perf annotate: Advance the mem_ref check to mov__parse()
>   perf annotate: Add 'extract_reg_offset' callback function to extract
>     register number and access offset
>   perf annotate: Support for the 'extract_reg_offset' callback function
>     in arm64
>   perf annotate-data: Support instruction tracking for arm64
>   perf annotate-data: Handle arm64 global variable access
>   perf annotate-data: Handle the access to the 'current' pointer on
>     arm64
> 
>  tools/perf/arch/arm64/annotate/instructions.c | 302 +++++++++++++++++-
>  .../perf/arch/powerpc/annotate/instructions.c |  10 +
>  tools/perf/arch/x86/annotate/instructions.c   |  99 ++++++
>  tools/perf/util/Build                         |   1 +
>  tools/perf/util/annotate-data.c               |  23 +-
>  tools/perf/util/annotate-data.h               |   4 +-
>  tools/perf/util/annotate.c                    | 112 +------
>  tools/perf/util/disasm.c                      |  14 +
>  tools/perf/util/disasm.h                      |   4 +
>  tools/perf/util/dwarf-regs-arm64.c            |  25 ++
>  tools/perf/util/include/dwarf-regs.h          |   7 +
>  11 files changed, 490 insertions(+), 111 deletions(-)
>  create mode 100644 tools/perf/util/dwarf-regs-arm64.c
> 
> -- 
> 2.25.1
> 


From andrew at codeconstruct.com.au  Mon Mar 17 18:26:37 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:56:37 +1030
Subject: [PATCH 14/15] gpio: aspeed-sgpio: use lock guards
In-Reply-To: <20250303-gpiochip-set-conversion-v1-14-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
	 <20250303-gpiochip-set-conversion-v1-14-1d5cceeebf8b@linaro.org>
Message-ID: <ace3d4bfa8bf4d59e1578a5f8b7c9aa92a25d85b.camel@codeconstruct.com.au>

On Mon, 2025-03-03 at 14:18 +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> Reduce the code complexity by using automatic lock guards with the raw
> spinlock.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From andrew at codeconstruct.com.au  Mon Mar 17 18:27:33 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 11:57:33 +1030
Subject: [PATCH 15/15] gpio: aspeed-sgpio: use new line value setter
 callbacks
In-Reply-To: <20250303-gpiochip-set-conversion-v1-15-1d5cceeebf8b@linaro.org>
References: <20250303-gpiochip-set-conversion-v1-0-1d5cceeebf8b@linaro.org>
	 <20250303-gpiochip-set-conversion-v1-15-1d5cceeebf8b@linaro.org>
Message-ID: <91090eae4f8f4843139ba0a0baf9215965cd44d6.camel@codeconstruct.com.au>

On Mon, 2025-03-03 at 14:18 +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>
> 
> struct gpio_chip now has callbacks for setting line values that return
> an integer, allowing to indicate failures. Convert the driver to using
> them.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From namhyung at kernel.org  Mon Mar 17 18:32:42 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 18:32:42 -0700
Subject: [PATCH 1/7] perf annotate: Handle arm64 load and store
 instructions
In-Reply-To: <20250314162137.528204-2-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-2-lihuafei1@huawei.com>
Message-ID: <Z9jNOgbZj_ZCx-9-@google.com>

On Sat, Mar 15, 2025 at 12:21:31AM +0800, Li Huafei wrote:
> Add ldst_ops to handle load and store instructions in order to parse
> the data types and offsets associated with PMU events for memory access
> instructions. There are many variants of load and store instructions in
> ARM64, making it difficult to match all of these instruction names
> completely. Therefore, only the instruction prefixes are matched. The
> prefix 'ld|st' covers most of the memory access instructions, 'cas|swp'
> matches atomic instructions, and 'prf' matches memory prefetch
> instructions.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 67 ++++++++++++++++++-
>  1 file changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index d465d093e7eb..c212eb7341bd 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -6,7 +6,8 @@
>  
>  struct arm64_annotate {
>  	regex_t call_insn,
> -		jump_insn;
> +		jump_insn,
> +		ldst_insn; /* load and store instruction */
>  };
>  
>  static int arm64_mov__parse(struct arch *arch __maybe_unused,
> @@ -67,6 +68,57 @@ static struct ins_ops arm64_mov_ops = {
>  	.scnprintf = mov__scnprintf,
>  };
>  
> +static int arm64_ldst__parse(struct arch *arch __maybe_unused,
> +			     struct ins_operands *ops,
> +			     struct map_symbol *ms __maybe_unused,
> +			     struct disasm_line *dl __maybe_unused)
> +{
> +	char *s, *target;
> +
> +	/*
> +	 * The part starting from the memory access annotation '[' is parsed
> +	 * as 'target', while the part before it is parsed as 'source'.
> +	 */
> +	target = s = strchr(ops->raw, '[');
> +	if (!s)
> +		return -1;
> +
> +	while (s > ops->raw && *s != ',')
> +		--s;
> +
> +	if (s == ops->raw)
> +		return -1;
> +
> +	*s = '\0';
> +	ops->source.raw = strdup(ops->raw);
> +
> +	*s = ',';
> +	if (!ops->source.raw)
> +		return -1;
> +
> +	ops->target.raw = strdup(target);
> +	if (!ops->target.raw) {
> +		zfree(ops->source.raw);

I think you need 'zfree(&ops->source.raw)' instead.


> +		return -1;
> +	}
> +	ops->target.mem_ref = true;
> +
> +	return 0;
> +}
> +
> +static int ldst__scnprintf(struct ins *ins, char *bf, size_t size,
> +			   struct ins_operands *ops, int max_ins_name)
> +{
> +	return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
> +			 ops->source.name ?: ops->source.raw,
> +			 ops->target.name ?: ops->target.raw);
> +}
> +
> +static struct ins_ops arm64_ldst_ops = {
> +	.parse	   = arm64_ldst__parse,
> +	.scnprintf = ldst__scnprintf,
> +};
> +
>  static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
>  {
>  	struct arm64_annotate *arm = arch->priv;
> @@ -77,6 +129,8 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
>  		ops = &jump_ops;
>  	else if (!regexec(&arm->call_insn, name, 2, match, 0))
>  		ops = &call_ops;
> +	else if (!regexec(&arm->ldst_insn, name, 2, match, 0))
> +		ops = &arm64_ldst_ops;
>  	else if (!strcmp(name, "ret"))
>  		ops = &ret_ops;
>  	else
> @@ -107,6 +161,15 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
>  		      REG_EXTENDED);
>  	if (err)
>  		goto out_free_call;
> +	/*
> +	 * The ARM64 architecture has many variants of load/store instructions.
> +	 * It is quite challenging to match all of them completely. Here, we
> +	 * only match the prefixes of these instructions.
> +	 */
> +	err = regcomp(&arm->ldst_insn, "^(ld|st|cas|prf|swp)",
> +		      REG_EXTENDED);
> +	if (err)
> +		goto out_free_jump;
>  
>  	arch->initialized = true;
>  	arch->priv	  = arm;
> @@ -117,6 +180,8 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
>  	arch->e_flags = 0;
>  	return 0;
>  
> +out_free_jump:
> +	regfree(&arm->jump_insn);
>  out_free_call:
>  	regfree(&arm->call_insn);

It seems we leak these on the success path.  Probably we need arch
annotate_exit() to free the resources.

Thanks,
Namhyung


>  out_free_arm:
> -- 
> 2.25.1
> 


From andrew at codeconstruct.com.au  Mon Mar 17 18:33:51 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 18 Mar 2025 12:03:51 +1030
Subject: [PATCH] usb: gadget: aspeed: Add NULL pointer check in
 ast_vhub_init_dev()
In-Reply-To: <20250311012705.1233829-1-chenyuan0y@gmail.com>
References: <20250311012705.1233829-1-chenyuan0y@gmail.com>
Message-ID: <57f42b7d08b816bc1a2e25d7f5932c3b2166c074.camel@codeconstruct.com.au>

On Mon, 2025-03-10 at 20:27 -0500, Chenyuan Yang wrote:
> The variable d->name, returned by devm_kasprintf(), could be NULL.
> A pointer check is added to prevent potential NULL pointer
> dereference.
> This is similar to the fix in commit 3027e7b15b02
> ("ice: Fix some null pointer dereference issues in ice_ptp.c").
> 
> This issue is found by our static analysis tool

Which tool is this? Can it be run by others (me)?

> 
> Signed-off-by: Chenyuan Yang <chenyuan0y at gmail.com>

Reviewed-by: Andrew Jeffery <andrew at codeconstruct.com.au>


From namhyung at kernel.org  Mon Mar 17 18:45:42 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 18:45:42 -0700
Subject: [PATCH 4/7] perf annotate: Support for the 'extract_reg_offset'
 callback function in arm64
In-Reply-To: <20250314162137.528204-5-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-5-lihuafei1@huawei.com>
Message-ID: <Z9jQRl9mMpBhfc4q@google.com>

On Sat, Mar 15, 2025 at 12:21:34AM +0800, Li Huafei wrote:
> At present, only the following two addressing modes are supported:
> 
>  1. Base register only (no offset): [base{, #0}]
>  2. Base plus offset (immediate): [base{, #imm}]
> 
> For addressing modes where the offset needs to be calculated from the
> register value, it is difficult to know the specific value of the offset
> register, making it impossible to calculate the offset.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 62 +++++++++++++++++++
>  tools/perf/util/Build                         |  1 +
>  tools/perf/util/disasm.c                      |  1 +
>  tools/perf/util/dwarf-regs-arm64.c            | 25 ++++++++
>  tools/perf/util/include/dwarf-regs.h          |  7 +++
>  5 files changed, 96 insertions(+)
>  create mode 100644 tools/perf/util/dwarf-regs-arm64.c
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index c212eb7341bd..54497b72a5c5 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -188,3 +188,65 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
>  	free(arm);
>  	return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
>  }
> +
> +
> +/*
> + * Get the base register number and access offset in load/store instructions.
> + * At present, only the following two addressing modes are supported:
> + *
> + *  1. Base register only (no offset): [base{, #0}]
> + *  2. Base plus offset (immediate): [base{, #imm}]
> + *
> + * For addressing modes where the offset needs to be calculated from the
> + * register value, it is difficult to know the specific value of the offset
> + * register, making it impossible to calculate the offset.
> + *
> + * Fills @reg and @offset when return 0.
> + */
> +static int
> +extract_reg_offset_arm64(struct arch *arch __maybe_unused,
> +			 struct disasm_line *dl __maybe_unused,
> +			 const char *insn_str, int insn_ops __maybe_unused,
> +			 struct annotated_op_loc *op_loc)
> +{
> +	char *str;
> +	regmatch_t match[4];
> +	static regex_t reg_off_regex;
> +	static bool regex_compiled;
> +
> +	if (!regex_compiled) {
> +		regcomp(&reg_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
> +			REG_EXTENDED);
> +		regex_compiled = true;

Probably better to put it in the arch specific data and free it when you
add arch__annotate_exit().


> +	}
> +
> +	if (!op_loc->mem_ref)
> +		return 0;
> +
> +	if (regexec(&reg_off_regex, insn_str, 4, match, 0))
> +		return -1;
> +
> +	str = strdup(insn_str);
> +	if (!str)
> +		return -1;
> +
> +	/* Get the base register number. */
> +	str[match[1].rm_eo] = '\0';
> +	op_loc->reg1 = get_arm64_regnum(str + match[1].rm_so);
> +
> +	/*
> +	 * If there is an immediate offset, match[2] records the start and end
> +	 * positions of "#imm".
> +	 */
> +	if (match[2].rm_so == -1) {
> +		free(str);
> +		return 0;
> +	}
> +
> +	/* Get the immediate offset. */
> +	str[match[3].rm_eo] = '\0';
> +	op_loc->offset = strtol(str + match[3].rm_so, NULL, 0);

Can you please clarify what match 1,2,3 mean - hopefully with an
example?

Thanks,
Namhyung

> +
> +	free(str);
> +	return 0;
> +}
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 5ec97e8d6b6d..d408cbe94fdd 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -210,6 +210,7 @@ perf-util-$(CONFIG_LIBDW) += dwarf-regs.o
>  perf-util-$(CONFIG_LIBDW) += dwarf-regs-csky.o
>  perf-util-$(CONFIG_LIBDW) += dwarf-regs-powerpc.o
>  perf-util-$(CONFIG_LIBDW) += dwarf-regs-x86.o
> +perf-util-$(CONFIG_LIBDW) += dwarf-regs-arm64.o
>  perf-util-$(CONFIG_LIBDW) += debuginfo.o
>  perf-util-$(CONFIG_LIBDW) += annotate-data.o
>  
> diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
> index 905eceb824a4..1035c60a8545 100644
> --- a/tools/perf/util/disasm.c
> +++ b/tools/perf/util/disasm.c
> @@ -128,6 +128,7 @@ static struct arch architectures[] = {
>  	{
>  		.name = "arm64",
>  		.init = arm64__annotate_init,
> +		.extract_reg_offset = extract_reg_offset_arm64,
>  	},
>  	{
>  		.name = "csky",
> diff --git a/tools/perf/util/dwarf-regs-arm64.c b/tools/perf/util/dwarf-regs-arm64.c
> new file mode 100644
> index 000000000000..edf41c059967
> --- /dev/null
> +++ b/tools/perf/util/dwarf-regs-arm64.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Mapping of DWARF debug register numbers into register names.
> + *
> + * Copyright (c) 2025  Huawei Inc, Li Huafei <lihuafei1 at huawei.com>
> + */
> +#include <errno.h>
> +#include <string.h>
> +#include <dwarf-regs.h>
> +
> +int get_arm64_regnum(const char *name)
> +{
> +	int reg;
> +
> +	if (!strcmp(name, "sp"))
> +		return 31;
> +
> +	if (*name != 'x' && *name != 'w')
> +		return -EINVAL;
> +
> +	name++;
> +	reg = strtol(name, NULL, 0);
> +
> +	return reg >= 0 && reg <= 30 ? reg : -EINVAL;
> +}
> diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
> index 6f1b9f6b2466..81cc5f69a391 100644
> --- a/tools/perf/util/include/dwarf-regs.h
> +++ b/tools/perf/util/include/dwarf-regs.h
> @@ -101,6 +101,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine, unsigned int
>  
>  int get_x86_regnum(const char *name);
>  
> +int get_arm64_regnum(const char *name);
> +
>  #if !defined(__x86_64__) && !defined(__i386__)
>  int get_arch_regnum(const char *name);
>  #endif
> @@ -128,6 +130,11 @@ static inline void get_powerpc_regs(u32 raw_insn __maybe_unused, int is_source _
>  {
>  	return;
>  }
> +
> +static inline int get_arm64_regnum(const char *name __maybe_unused)
> +{
> +	return -1;
> +}
>  #endif
>  
>  #endif
> -- 
> 2.25.1
> 


From namhyung at kernel.org  Mon Mar 17 18:51:48 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 18:51:48 -0700
Subject: [PATCH 5/7] perf annotate-data: Support instruction tracking for
 arm64
In-Reply-To: <20250314162137.528204-6-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-6-lihuafei1@huawei.com>
Message-ID: <Z9jRtDJY-RjiyFer@google.com>

On Sat, Mar 15, 2025 at 12:21:35AM +0800, Li Huafei wrote:
> Support for arm64 instruction tracing. This patch addresses the scenario
> where type information cannot be found during multi-level pointer
> references. For example, consider the vfs_ioctl() function:
> 
>  long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  {
>      int error = -ENOTTY;
> 
>      if (!filp->f_op->unlocked_ioctl)
>          goto out;
> 
>      error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
>      if (error == -ENOIOCTLCMD)
>          error = -ENOTTY;
>  out:
>      return error;
>  }
> 
> The 'SYSCALL_DEFINE3(ioctl)' inlines vfs_ioctl, and the assembly
> instructions for 'if (!filp->f_op->unlocked_ioctl)' are as follows:
> 
>  ldr     x0, [x21, #16]
>  ldr     x3, [x0, #80]
>  cbz     x3, ffff80008048e9a4
> 
> The first instruction loads the 'filp->f_op' pointer, and the second
> instruction loads the 'filp->f_op->unlocked_ioctl' pointer. DWARF
> generates type information for x21, but not for x0. Therefore, if
> PMU sampling occurs on the second instruction, the corresponding data
> type cannot be obtained. However, by using the type information and
> offset from x21 in the first ldr instruction, we can infer the type
> of x0 and, combined with the offset, resolve the accessed data member.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 44 ++++++++++++++++++-
>  tools/perf/util/annotate-data.c               |  3 +-
>  tools/perf/util/annotate-data.h               |  2 +-
>  tools/perf/util/disasm.c                      |  3 ++
>  4 files changed, 49 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index 54497b72a5c5..f70d93001fe7 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -215,7 +215,8 @@ extract_reg_offset_arm64(struct arch *arch __maybe_unused,
>  	static bool regex_compiled;
>  
>  	if (!regex_compiled) {
> -		regcomp(&reg_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
> +		regcomp(&reg_off_regex,
> +			"^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",

Does it have any real changes?  If not I'd rather leave it or move the
change to the original commit.


>  			REG_EXTENDED);
>  		regex_compiled = true;
>  	}
> @@ -250,3 +251,44 @@ extract_reg_offset_arm64(struct arch *arch __maybe_unused,
>  	free(str);
>  	return 0;
>  }
> +
> +#ifdef HAVE_LIBDW_SUPPORT
> +static void
> +update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
> +			Dwarf_Die * cu_die __maybe_unused, struct disasm_line *dl)
> +{
> +	struct annotated_insn_loc loc;
> +	struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
> +	struct type_state_reg *tsr;
> +	Dwarf_Die type_die;
> +	int sreg, dreg;
> +
> +	if (strncmp(dl->ins.name, "ld", 2))
> +		return;
> +
> +	if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
> +		return;
> +
> +	sreg = get_arm64_regnum(dl->ops.source.raw);
> +	if (sreg < 0)
> +		return;
> +	if (!has_reg_type(state, sreg))
> +		return;

It'd be better to invalidate state of the target register even if it
failed to get the information of source register and its state.  The
destination would be updated anyway and keeping the stale state would
result in an invalid report at the end.

Thanks,
Namhyung

> +
> +	dreg = dst->reg1;
> +	if (has_reg_type(state, dreg) && state->regs[dreg].ok &&
> +	    state->regs[dreg].kind == TSR_KIND_TYPE &&
> +	    dwarf_tag(&state->regs[dreg].type) == DW_TAG_pointer_type &&
> +	    die_deref_ptr_type(&state->regs[dreg].type,
> +			       dst->offset, &type_die)) {
> +		tsr = &state->regs[sreg];
> +		tsr->type = type_die;
> +		tsr->kind = TSR_KIND_TYPE;
> +		tsr->ok = true;
> +
> +		pr_debug_dtp("load [%x] %#x(reg%d) -> reg%d",
> +			     (u32)dl->al.offset, dst->offset, dreg, sreg);
> +		pr_debug_type_name(&tsr->type, tsr->kind);
> +	}
> +}
> +#endif
> diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
> index 976abedca09e..2bc8d646eedc 100644
> --- a/tools/perf/util/annotate-data.c
> +++ b/tools/perf/util/annotate-data.c
> @@ -1293,7 +1293,8 @@ static enum type_match_result find_data_type_insn(struct data_loc_info *dloc,
>  
>  static int arch_supports_insn_tracking(struct data_loc_info *dloc)
>  {
> -	if ((arch__is(dloc->arch, "x86")) || (arch__is(dloc->arch, "powerpc")))
> +	if ((arch__is(dloc->arch, "x86")) || (arch__is(dloc->arch, "powerpc")) ||
> +	    (arch__is(dloc->arch, "arm64")))
>  		return 1;
>  	return 0;
>  }
> diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
> index 98c80b2268dd..717f394eb8f1 100644
> --- a/tools/perf/util/annotate-data.h
> +++ b/tools/perf/util/annotate-data.h
> @@ -190,7 +190,7 @@ struct type_state_stack {
>  };
>  
>  /* FIXME: This should be arch-dependent */
> -#ifdef __powerpc__
> +#if defined(__powerpc__) || defined(__aarch64__)
>  #define TYPE_STATE_MAX_REGS  32
>  #else
>  #define TYPE_STATE_MAX_REGS  16
> diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
> index 1035c60a8545..540981c155f9 100644
> --- a/tools/perf/util/disasm.c
> +++ b/tools/perf/util/disasm.c
> @@ -129,6 +129,9 @@ static struct arch architectures[] = {
>  		.name = "arm64",
>  		.init = arm64__annotate_init,
>  		.extract_reg_offset = extract_reg_offset_arm64,
> +#ifdef HAVE_LIBDW_SUPPORT
> +		.update_insn_state = update_insn_state_arm64,
> +#endif
>  	},
>  	{
>  		.name = "csky",
> -- 
> 2.25.1
> 


From namhyung at kernel.org  Mon Mar 17 19:01:01 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 19:01:01 -0700
Subject: [PATCH 6/7] perf annotate-data: Handle arm64 global variable
 access
In-Reply-To: <20250314162137.528204-7-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-7-lihuafei1@huawei.com>
Message-ID: <Z9jT3e2j8HDMLcYh@google.com>

On Sat, Mar 15, 2025 at 12:21:36AM +0800, Li Huafei wrote:
> Arm64 uses the 'adrp' and 'add' instructions to load the address of a
> global variable. For example:
> 
>  adrp    x19, ffff8000819c3000
>  add     x19, x19, #0x3e8
>  <<after some sequence>>
>  ldr     x22, [x19, #8]

You can try perf annotate --stdio --code-with-type and see if it finds a
correct type.  It'd be nice if you include the result in the commit log.

> 
> Here, 'adrp' retrieves the base address of the page where the global
> variable is located, and 'add' adds the offset within the page. If PMU
> sampling occurs at the instruction 'ldr x22, [x19, #8]', we need to
> trace the preceding 'adrp' and 'add' instructions to obtain the status
> information of x19.
> 
> A new register status type 'TSR_KIND_GLOBAL_ADDR' is introduced,
> indicating that the register holds the address of a global variable, and
> this address is also stored in the 'type_state_reg' structure. After
> obtaining the status information of x19, we use
> get_global_var_type() to search for a matching global variable and
> verify whether the returned offset is equal to 8. If it is, then we have
> identified the data type and offset of the accessed global variable.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 90 ++++++++++++++++++-
>  tools/perf/util/annotate-data.c               | 20 +++++
>  tools/perf/util/annotate-data.h               |  2 +
>  3 files changed, 111 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index f70d93001fe7..f2053e7f60a8 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -262,6 +262,94 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
>  	struct type_state_reg *tsr;
>  	Dwarf_Die type_die;
>  	int sreg, dreg;
> +	u32 insn_offset = dl->al.offset;
> +
> +	/* Access global variables via PC relative addressing, for example:
> +	 *
> +	 *  adrp    x19, ffff800082074000
> +	 *  add     x19, x19, #0x380
> +	 *
> +	 * The adrp instruction locates the page base address, and the add
> +	 * instruction adds the offset within the page.
> +	 */
> +	if (!strncmp(dl->ins.name, "adrp", 4)) {
> +		sreg = get_arm64_regnum(dl->ops.source.raw);
> +		if (sreg < 0 || !has_reg_type(state, sreg))
> +			return;
> +
> +		tsr = &state->regs[sreg];
> +		tsr->ok = true;
> +		tsr->kind = TSR_KIND_GLOBAL_ADDR;
> +		/*
> +		 * The default arm64_mov_ops has already parsed the adrp
> +		 * instruction and saved the target address.
> +		 */
> +		tsr->addr = dl->ops.target.addr;
> +
> +		pr_debug_dtp("adrp [%x] global addr=%#"PRIx64" -> reg%d\n",
> +			     insn_offset, tsr->addr, sreg);
> +		return;
> +	}
> +
> +	/* Add the offset within the page. */
> +	if (!strncmp(dl->ins.name, "add", 3)) {
> +		regmatch_t match[4];
> +		char *ops = strdup(dl->ops.raw);
> +		u64 offset;
> +		static regex_t add_regex;
> +		static bool regex_compiled;
> +
> +		/*
> +		 * Matching the operand assembly syntax of the add instruction:
> +		 *
> +		 *  <Xd|SP>, <Xn|SP>, #<imm>
> +		 */
> +		if (!regex_compiled) {
> +			regcomp(&add_regex,
> +				"^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
> +				REG_EXTENDED);
> +			regex_compiled = true;

Similarly you could put it in the arch and free later.

Thanks.
Namhyung


> +		}
> +
> +		if (!ops)
> +			return;
> +
> +		if (regexec(&add_regex, dl->ops.raw, 4, match, 0))
> +			return;
> +
> +		/*
> +		 * Parse the source register first. If it is not of the type
> +		 * TSR_KIND_GLOBAL_ADDR, further parsing is not required.
> +		 */
> +		ops[match[2].rm_eo] = '\0';
> +		sreg = get_arm64_regnum(ops + match[2].rm_so);
> +		if (sreg < 0 || !has_reg_type(state, sreg) ||
> +		    state->regs[sreg].kind != TSR_KIND_GLOBAL_ADDR) {
> +			free(ops);
> +			return;
> +		}
> +
> +		ops[match[1].rm_eo] = '\0';
> +		dreg = get_arm64_regnum(ops + match[1].rm_so);
> +		if (dreg < 0 || !has_reg_type(state, dreg)) {
> +			free(ops);
> +			return;
> +		}
> +
> +		ops[match[3].rm_eo] = '\0';
> +		offset = strtoul(ops + match[3].rm_so, NULL, 16);
> +
> +		tsr = &state->regs[dreg];
> +		tsr->ok = true;
> +		tsr->kind = TSR_KIND_GLOBAL_ADDR;
> +		tsr->addr = state->regs[sreg].addr + offset;
> +
> +		pr_debug_dtp("add [%x] global addr=%#"PRIx64"(reg%d) -> reg%d\n",
> +			     insn_offset, tsr->addr, sreg, dreg);
> +
> +		free(ops);
> +		return;
> +	}
>  
>  	if (strncmp(dl->ins.name, "ld", 2))
>  		return;
> @@ -287,7 +375,7 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
>  		tsr->ok = true;
>  
>  		pr_debug_dtp("load [%x] %#x(reg%d) -> reg%d",
> -			     (u32)dl->al.offset, dst->offset, dreg, sreg);
> +			     insn_offset, dst->offset, dreg, sreg);
>  		pr_debug_type_name(&tsr->type, tsr->kind);
>  	}
>  }
> diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
> index 2bc8d646eedc..aaca08bb9097 100644
> --- a/tools/perf/util/annotate-data.c
> +++ b/tools/perf/util/annotate-data.c
> @@ -65,6 +65,9 @@ void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind)
>  	case TSR_KIND_CANARY:
>  		pr_info(" stack canary\n");
>  		return;
> +	case TSR_KIND_GLOBAL_ADDR:
> +		pr_info(" global address\n");
> +		return;
>  	case TSR_KIND_TYPE:
>  	default:
>  		break;
> @@ -1087,6 +1090,23 @@ static enum type_match_result check_matching_type(struct type_state *state,
>  		return PERF_TMR_OK;
>  	}
>  
> +	if (state->regs[reg].kind == TSR_KIND_GLOBAL_ADDR) {
> +		int var_offset;
> +		u64 var_addr;
> +
> +		pr_debug_dtp("global var by address");
> +
> +		var_addr = state->regs[reg].addr + dloc->op->offset;
> +
> +		if (get_global_var_type(cu_die, dloc, dloc->ip, var_addr,
> +					&var_offset, type_die)) {
> +			dloc->type_offset = var_offset;
> +			return PERF_TMR_OK;
> +		}
> +
> +		return PERF_TMR_BAIL_OUT;
> +	}
> +
>  	if (state->regs[reg].kind == TSR_KIND_CANARY) {
>  		pr_debug_dtp("stack canary");
>  
> diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
> index 717f394eb8f1..e3e877313207 100644
> --- a/tools/perf/util/annotate-data.h
> +++ b/tools/perf/util/annotate-data.h
> @@ -36,6 +36,7 @@ enum type_state_kind {
>  	TSR_KIND_CONST,
>  	TSR_KIND_POINTER,
>  	TSR_KIND_CANARY,
> +	TSR_KIND_GLOBAL_ADDR,
>  };
>  
>  /**
> @@ -177,6 +178,7 @@ struct type_state_reg {
>  	bool caller_saved;
>  	u8 kind;
>  	u8 copied_from;
> +	u64 addr;
>  };
>  
>  /* Type information in a stack location, dynamically allocated */
> -- 
> 2.25.1
> 


From namhyung at kernel.org  Mon Mar 17 19:06:00 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Mon, 17 Mar 2025 19:06:00 -0700
Subject: [PATCH 7/7] perf annotate-data: Handle the access to the
 'current' pointer on arm64
In-Reply-To: <20250314162137.528204-8-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-8-lihuafei1@huawei.com>
Message-ID: <Z9jVCFwf7Gbs6u22@google.com>

On Sat, Mar 15, 2025 at 12:21:37AM +0800, Li Huafei wrote:
> According to the implementation of the 'current' macro on ARM64, the
> sp_el0 register stores the pointer to the current task's task_struct.
> For example:
> 
>  mrs x1, sp_el0
>  ldr x2, [x1, #1896]

Same here.  It'd be great if you could share a real example where it
found the current for x1 in the second instruction.

> 
> We can infer that the ldr instruction is accessing a member of the
> task_struct structure at an offset of 1896. The key is to construct the
> data type for x1. The instruction 'mrs x1, sp_el0' belongs to the inline
> function get_current(). By finding the DIE of the inline function
> through its instruction address, and then obtaining the DIE for its
> return type, which should be 'struct task_struct *'. Then, we update the
> register state of x1 with this type information.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 71 +++++++++++++++----
>  1 file changed, 57 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index f2053e7f60a8..c5a0a6381547 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -263,6 +263,20 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
>  	Dwarf_Die type_die;
>  	int sreg, dreg;
>  	u32 insn_offset = dl->al.offset;
> +	static regex_t add_regex, mrs_regex;
> +	static bool regex_compiled;
> +
> +	if (!regex_compiled) {
> +		/*
> +		 * Matching the operand assembly syntax of the add instruction:
> +		 *
> +		 *  <Xd|SP>, <Xn|SP>, #<imm>
> +		 */
> +		regcomp(&add_regex, "^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
> +			REG_EXTENDED);
> +		regcomp(&mrs_regex, "^(x[0-9]{1,2}), sp_el0", REG_EXTENDED);
> +		regex_compiled = true;
> +	}
>  
>  	/* Access global variables via PC relative addressing, for example:
>  	 *
> @@ -296,20 +310,6 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
>  		regmatch_t match[4];
>  		char *ops = strdup(dl->ops.raw);
>  		u64 offset;
> -		static regex_t add_regex;
> -		static bool regex_compiled;
> -
> -		/*
> -		 * Matching the operand assembly syntax of the add instruction:
> -		 *
> -		 *  <Xd|SP>, <Xn|SP>, #<imm>
> -		 */
> -		if (!regex_compiled) {
> -			regcomp(&add_regex,
> -				"^([xw][0-9]{1,2}|sp), ([xw][0-9]{1,2}|sp), #(0x[0-9a-f]+)",
> -				REG_EXTENDED);
> -			regex_compiled = true;
> -		}
>  
>  		if (!ops)
>  			return;
> @@ -351,6 +351,49 @@ update_insn_state_arm64(struct type_state *state, struct data_loc_info *dloc,
>  		return;
>  	}
>  
> +	if (!strncmp(dl->ins.name, "mrs", 3)) {

It should be kernel specific, you may want to add a check for it like
__map__is_kernel(dloc->ms->map).

Thanks,
Namhyung


> +		regmatch_t match[2];
> +		char *ops = strdup(dl->ops.raw);
> +		Dwarf_Die func_die;
> +		Dwarf_Attribute attr;
> +		u64 ip = dloc->ms->sym->start + dl->al.offset;
> +		u64 pc = map__rip_2objdump(dloc->ms->map, ip);
> +
> +		if (!ops)
> +			return;
> +
> +		if (regexec(&mrs_regex, dl->ops.raw, 2, match, 0))
> +			return;
> +
> +		ops[match[1].rm_eo] = '\0';
> +		sreg = get_arm64_regnum(ops + match[1].rm_so);
> +		if (sreg < 0 || !has_reg_type(state, sreg)) {
> +			free(ops);
> +			return;
> +		}
> +
> +		/*
> +		 * Find the inline function 'get_current()' Dwarf_Die and
> +		 * obtain its return value data type, which should be
> +		 * 'struct task_struct *'.
> +		 */
> +		if (!die_find_inlinefunc(cu_die, pc, &func_die) ||
> +		    !dwarf_attr_integrate(&func_die, DW_AT_type, &attr) ||
> +		    !dwarf_formref_die(&attr, &type_die)) {
> +			free(ops);
> +			return;
> +		}
> +
> +		tsr = &state->regs[sreg];
> +		tsr->type = type_die;
> +		tsr->kind = TSR_KIND_TYPE;
> +		tsr->ok = true;
> +
> +		pr_debug_dtp("mrs sp_el0 [%x] -> reg%d", insn_offset, sreg);
> +		free(ops);
> +		return;
> +	}
> +
>  	if (strncmp(dl->ins.name, "ld", 2))
>  		return;
>  
> -- 
> 2.25.1
> 


From leiyang at redhat.com  Mon Mar 17 19:04:07 2025
From: leiyang at redhat.com (Lei Yang)
Date: Tue, 18 Mar 2025 10:04:07 +0800
Subject: [PATCH v6 0/4] Add virtio_rtc module
In-Reply-To: <20250313173707.1492-1-quic_philber@quicinc.com>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
Message-ID: <CAPpAL=we6VkyBXBO2cBiszpGUP5f7QSioQbp6x3YoCqa9qUPRQ@mail.gmail.com>

QE tested this series of patches v6 with virtio-net regression tests,
everything works fine.

Tested-by: Lei Yang <leiyang at redhat.com>

On Fri, Mar 14, 2025 at 1:38?AM Peter Hilber <quic_philber at quicinc.com> wrote:
>
> This series implements a driver for a virtio-rtc device conforming to spec
> proposal v8 [1]. It includes a PTP clock driver and an RTC class driver
> with alarm.
>
> v6 updates
> ==========
>
> v6 fixes the PTP clock name length, and a few style issues, some of which
> resulted in warnings.
>
> Overview
> ========
>
> This patch series adds the virtio_rtc module, and related bugfixes. The
> virtio_rtc module implements a driver compatible with the proposed Virtio
> RTC device specification [1]. The Virtio RTC (Real Time Clock) device
> provides information about current time. The device can provide different
> clocks, e.g. for the UTC or TAI time standards, or for physical time
> elapsed since some past epoch. The driver can read the clocks with simple
> or more accurate methods. Optionally, the driver can set an alarm.
>
> For the Virtio RTC device, there is currently a proprietary implementation,
> which has been used for testing.
>
> PTP clock interface
> ===================
>
> virtio_rtc exposes clocks as PTP clocks to userspace, similar to ptp_kvm.
> If both the Virtio RTC device and this driver have special support for the
> current clocksource, time synchronization programs can use
> cross-timestamping using ioctl PTP_SYS_OFFSET_PRECISE2 aka
> PTP_SYS_OFFSET_PRECISE. Similar to ptp_kvm, system time synchronization
> with single-digit ns precision is possible with a quiescent reference clock
> (from the Virtio RTC device). This works even when the Virtio device
> response is slow compared to ptp_kvm hypercalls.
>
> The following illustrates a test using PTP_SYS_OFFSET_PRECISE, with
> interspersed strace log and chrony [2] refclocks log, on arm64. In the
> example, chrony tracks a virtio_rtc PTP clock ("PHCV", /dev/ptp0). The raw
> offset between the virtio_rtc clock and CLOCK_REALTIME is 0 to 1 ns. At the
> device side, the Virtio RTC device artificially delays both the clock read
> request, and the response, by 50 ms. Cross-timestamp interpolation still
> works with this delay. chrony also monitors a ptp_kvm clock ("PHCK",
> /dev/ptp3) for comparison, which yields a similar offset.
>
>         ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000329>
>         ===============================================================================
>            Date (UTC) Time         Refid  DP L P  Raw offset   Cooked offset      Disp.
>         ===============================================================================
>         2023-06-29 18:49:55.595742 PHCK    0 N 0  1.000000e-09  8.717931e-10  5.500e-08
>         2023-06-29 18:49:55.595742 PHCK    - N -       -        8.717931e-10  5.500e-08
>         ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101545>
>         2023-06-29 18:49:56.147766 PHCV    0 N 0  1.000000e-09  8.801870e-10  5.500e-08
>         2023-06-29 18:49:56.147766 PHCV    - N -       -        8.801870e-10  5.500e-08
>         ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000195>
>         2023-06-29 18:49:56.202446 PHCK    0 N 0  1.000000e-09  7.364180e-10  5.500e-08
>         2023-06-29 18:49:56.202446 PHCK    - N -       -        7.364180e-10  5.500e-08
>         ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101484>
>         2023-06-29 18:49:56.754641 PHCV    0 N 0  0.000000e+00 -2.617368e-10  5.500e-08
>         2023-06-29 18:49:56.754641 PHCV    - N -       -       -2.617368e-10  5.500e-08
>         ioctl(5</dev/ptp3>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.000270>
>         2023-06-29 18:49:56.809282 PHCK    0 N 0  1.000000e-09  7.779321e-10  5.500e-08
>         2023-06-29 18:49:56.809282 PHCK    - N -       -        7.779321e-10  5.500e-08
>         ioctl(6</dev/ptp0>, PTP_SYS_OFFSET_PRECISE, 0xffffe86691c8) = 0 <0.101510>
>         2023-06-29 18:49:57.361376 PHCV    0 N 0  0.000000e+00 -2.198794e-10  5.500e-08
>         2023-06-29 18:49:57.361376 PHCV    - N -       -       -2.198794e-10  5.500e-08
>
> This patch series only adds special support for the Arm Generic Timer
> clocksource. At the driver side, it should be easy to support more
> clocksources.
>
> Fallback PTP clock interface
> ----------------------------
>
> Without special support for the current clocksource, time synchronization
> programs can still use ioctl PTP_SYS_OFFSET_EXTENDED2 aka
> PTP_SYS_OFFSET_EXTENDED. In this case, precision will generally be worse
> and will depend on the Virtio device response characteristics.
>
> The following illustrates a test using PTP_SYS_OFFSET_EXTENDED, with
> interspersed strace log and chrony refclocks log, on x86-64 (with `ts'
> values omitted):
>
>         ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
>         ===============================================================================
>            Date (UTC) Time         Refid  DP L P  Raw offset   Cooked offset      Disp.
>         ===============================================================================
>         2023-06-28 14:11:26.697782 PHCV    0 N 0  3.318200e-05  3.450891e-05  4.611e-06
>         2023-06-28 14:11:26.697782 PHCV    - N -       -        3.450891e-05  4.611e-06
>         ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
>         2023-06-28 14:11:27.208763 PHCV    0 N 0 -3.792800e-05 -4.023965e-05  4.611e-06
>         2023-06-28 14:11:27.208763 PHCV    - N -       -       -4.023965e-05  4.611e-06
>         ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
>         2023-06-28 14:11:27.722818 PHCV    0 N 0 -3.328600e-05 -3.134404e-05  4.611e-06
>         2023-06-28 14:11:27.722818 PHCV    - N -       -       -3.134404e-05  4.611e-06
>         ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
>         2023-06-28 14:11:28.233572 PHCV    0 N 0 -4.966900e-05 -4.584331e-05  4.611e-06
>         2023-06-28 14:11:28.233572 PHCV    - N -       -       -4.584331e-05  4.611e-06
>         ioctl(5, PTP_SYS_OFFSET_EXTENDED, {n_samples=10, ts=OMITTED}) = 0
>         2023-06-28 14:11:28.742737 PHCV    0 N 0  4.902700e-05  5.361388e-05  4.611e-06
>         2023-06-28 14:11:28.742737 PHCV    - N -       -        5.361388e-05  4.611e-06
>
> PTP clock setup
> ---------------
>
> The following udev rule can be used to get a symlink /dev/ptp_virtio to the
> UTC clock:
>
>         SUBSYSTEM=="ptp", ATTR{clock_name}=="Virtio PTP type 0/variant 0", SYMLINK += "ptp_virtio"
>
> The following chrony configuration directive can then be added in
> /etc/chrony/chrony.conf to synchronize to the Virtio UTC clock:
>
>         refclock PHC /dev/ptp_virtio refid PHCV poll -1 dpoll -1
>
> RTC interface
> =============
>
> This patch series adds virtio_rtc as a generic Virtio driver, including
> both a PTP clock driver and an RTC class driver.
>
> Feedback is greatly appreciated.
>
> [1] https://lore.kernel.org/virtio-comment/20250306095112.1293-1-quic_philber at quicinc.com/
> [2] https://chrony.tuxfamily.org/
>
> Changelog
> =========
>
> v6:
>
> - Shorten PTP clock names to always fit into 32 bytes.
>
> - Fix sparse warning about endianness mismatch (Simon Horman).
>
> - Do not mark comments missing parameter documentation as kernel doc (Simon
>   Horman).
>
> - Improve error status computation readability.
>
> - Avoid conditional locking within a block.
>
> v5:
>
> - Update to virtio-rtc spec v7, essentially removing definitions.
>
> - Fix multiple bugs after readying device during probe and restore.
>
> - Actually initialize Virtio clock id for RTC class device.
>
> - Add freeze/restore ops already in first patch.
>
> - Minor changes:
>
>   - Use new APIs devm_device_init_wakeup(), secs_to_jiffies().
>
>   - Fix style issues.
>
>   - Improve logging types and clarity.
>
>   - Drop unnecessary memory barrier pair.
>
>   - Return error status from device, whenever available.
>
> v4:
>
> - Update Virtio interface to spec v6.
>
> - Distinguish UTC-like clocks by handling of leap seconds (spec v6).
>
> - Do not create RTC class device for clocks which may step on leap seconds
>   (Alexandre Belloni).
>
> - Clear RTC class feature bit instead of defining reduced ops
>   (Alexandre Belloni).
>
> - For PTP clock name, always use numeric clock type, and numeric variant.
>
> - Use macros for 64-bit divisions.
>
> - Remove unnecessary memory barriers.
>
> - Cosmetic improvements.
>
> - Drop upstreamed timekeeping bugfixes from series.
>
> v3:
>
> - Update to conform to virtio spec RFC v3 (no significant behavioral
>   changes).
>
> - Add RTC class driver with alarm according to virtio spec RFC v3.
>
> - For cross-timestamp corner case fix, switch back to v1 style closed
>   interval test (Thomas Gleixner).
>
> v2:
>
> - Depend on patch series "treewide: Use clocksource id for
>   get_device_system_crosststamp()" to avoid requiring a clocksource pointer
>   with get_device_system_crosststamp().
>
> - Assume Arm Generic Timer will use CP15 virtual counter. Drop
>   arm_arch_timer helper functions (Marc Zyngier).
>
> - Improve cross-timestamp fixes problem description and implementation
>   (John Stultz).
>
>
> Peter Hilber (4):
>   virtio_rtc: Add module and driver core
>   virtio_rtc: Add PTP clocks
>   virtio_rtc: Add Arm Generic Timer cross-timestamping
>   virtio_rtc: Add RTC class driver
>
>  MAINTAINERS                          |    7 +
>  drivers/virtio/Kconfig               |   64 ++
>  drivers/virtio/Makefile              |    5 +
>  drivers/virtio/virtio_rtc_arm.c      |   23 +
>  drivers/virtio/virtio_rtc_class.c    |  262 +++++
>  drivers/virtio/virtio_rtc_driver.c   | 1407 ++++++++++++++++++++++++++
>  drivers/virtio/virtio_rtc_internal.h |  122 +++
>  drivers/virtio/virtio_rtc_ptp.c      |  347 +++++++
>  include/uapi/linux/virtio_rtc.h      |  237 +++++
>  9 files changed, 2474 insertions(+)
>  create mode 100644 drivers/virtio/virtio_rtc_arm.c
>  create mode 100644 drivers/virtio/virtio_rtc_class.c
>  create mode 100644 drivers/virtio/virtio_rtc_driver.c
>  create mode 100644 drivers/virtio/virtio_rtc_internal.h
>  create mode 100644 drivers/virtio/virtio_rtc_ptp.c
>  create mode 100644 include/uapi/linux/virtio_rtc.h
>
>
> base-commit: 9d8960672d63db4b3b04542f5622748b345c637a
> --
> 2.43.0
>
>



From pr-tracker-bot at kernel.org  Mon Mar 17 19:42:41 2025
From: pr-tracker-bot at kernel.org (pr-tracker-bot at kernel.org)
Date: Tue, 18 Mar 2025 02:42:41 +0000
Subject: [GIT PULL] soc: fixes for 6.14, part 2
In-Reply-To: <860b2eaa-1aea-45e0-8bf5-3645b3840966@app.fastmail.com>
References: <860b2eaa-1aea-45e0-8bf5-3645b3840966@app.fastmail.com>
Message-ID: <174226576175.3993121.4904814038298026258.pr-tracker-bot@kernel.org>

The pull request you sent on Mon, 17 Mar 2025 18:57:57 +0100:

> https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-fixes-6.14-2

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/fc444ada131001812c5d10b380837238c9cf7c8c

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:29 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:29 -0400
Subject: [PATCH iwl-next v10 01/14] net: stmmac: move frag_size handling out of spin_lock
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-2-faizal.abdul.rahim@linux.intel.com>

The upcoming patch will extract verification logic into a new module,
MMSV (MAC Merge Software Verification). MMSV will handle most FPE fields,
except frag_size. It introduces its own lock (mmsv->lock), replacing
fpe_cfg->lock.

Since frag_size handling remains in the driver, the existing rtnl_lock()
is sufficient. Move frag_size handling out of spin_lock_irq_save() to keep
the upcoming patch a pure refactoring without behavior changes.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Reviewed-by: Furong Xu <0x1207 at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 918a32f8fda8..cfe5aea24549 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1216,6 +1216,10 @@ static int stmmac_get_mm(struct net_device *ndev,
 	if (!stmmac_fpe_supported(priv))
 		return -EOPNOTSUPP;
 
+	state->rx_min_frag_size = ETH_ZLEN;
+	frag_size = stmmac_fpe_get_add_frag_size(priv);
+	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
+
 	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
 
 	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
@@ -1224,7 +1228,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	state->verify_time = priv->fpe_cfg.verify_time;
 	state->tx_enabled = priv->fpe_cfg.tx_enabled;
 	state->verify_status = priv->fpe_cfg.status;
-	state->rx_min_frag_size = ETH_ZLEN;
 
 	/* FPE active if common tx_enabled and
 	 * (verification success or disabled(forced))
@@ -1236,9 +1239,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 	else
 		state->tx_active = false;
 
-	frag_size = stmmac_fpe_get_add_frag_size(priv);
-	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
-
 	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
 
 	return 0;
@@ -1258,6 +1258,8 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (err)
 		return err;
 
+	stmmac_fpe_set_add_frag_size(priv, frag_size);
+
 	/* Wait for the verification that's currently in progress to finish */
 	timer_shutdown_sync(&fpe_cfg->verify_timer);
 
@@ -1271,7 +1273,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 	if (!cfg->verify_enabled)
 		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
 
-	stmmac_fpe_set_add_frag_size(priv, frag_size);
 	stmmac_fpe_apply(priv);
 
 	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:30 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:30 -0400
Subject: [PATCH iwl-next v10 02/14] net: ethtool: mm: extract stmmac verification logic into common library
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-3-faizal.abdul.rahim@linux.intel.com>

From: Vladimir Oltean <vladimir.oltean at nxp.com>

It appears that stmmac is not the only hardware which requires a
software-driven verification state machine for the MAC Merge layer.

While on the one hand it's good to encourage hardware implementations,
on the other hand it's quite difficult to tolerate multiple drivers
implementing independently fairly non-trivial logic.

Extract the hardware-independent logic from stmmac into library code and
put it in ethtool. Name the state structure "mmsv" for MAC Merge
Software Verification. Let this expose an operations structure for
executing the hardware stuff: sync hardware with the tx_active boolean
(result of verification process), enable/disable the pMAC, send mPackets,
notify library of external events (reception of mPackets), as well as
link state changes.

Note that it is assumed that the external events are received in hardirq
context. If they are not, it is probably a good idea to disable hardirqs
when calling ethtool_mmsv_event_handle(), because the library does not
do so.

Also, the MM software verification process has no business with the
tx_min_frag_size, that is all the driver's to handle.

Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Tested-by: Furong Xu <0x1207 at gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |   1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  42 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 275 +++++++++++++++++-
 8 files changed, 392 insertions(+), 202 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 3c820ef56775..59c742a8b3ad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -3,6 +3,7 @@ config STMMAC_ETH
 	tristate "STMicroelectronics Multi-Gigabit Ethernet driver"
 	depends on HAS_IOMEM && HAS_DMA
 	depends on PTP_1588_CLOCK_OPTIONAL
+	depends on ETHTOOL_NETLINK
 	select MII
 	select PCS_XPCS
 	select PAGE_POOL
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index d87275c1cf23..7d7f0a7ad8b7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -149,21 +149,9 @@ struct stmmac_channel {
 };
 
 struct stmmac_fpe_cfg {
-	/* Serialize access to MAC Merge state between ethtool requests
-	 * and link state updates.
-	 */
-	spinlock_t lock;
-
+	struct ethtool_mmsv mmsv;
 	const struct stmmac_fpe_reg *reg;
-	u32 fpe_csr;				/* MAC_FPE_CTRL_STS reg cache */
-
-	enum ethtool_mm_verify_status status;
-	struct timer_list verify_timer;
-	bool verify_enabled;
-	int verify_retries;
-	bool pmac_enabled;
-	u32 verify_time;
-	bool tx_enabled;
+	u32 fpe_csr;	/* MAC_FPE_CTRL_STS reg cache */
 };
 
 struct stmmac_tc_entry {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index cfe5aea24549..44ee73569cb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1210,7 +1210,6 @@ static int stmmac_get_mm(struct net_device *ndev,
 			 struct ethtool_mm_state *state)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long flags;
 	u32 frag_size;
 
 	if (!stmmac_fpe_supported(priv))
@@ -1220,26 +1219,7 @@ static int stmmac_get_mm(struct net_device *ndev,
 	frag_size = stmmac_fpe_get_add_frag_size(priv);
 	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
 
-	spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
-
-	state->max_verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	state->verify_enabled = priv->fpe_cfg.verify_enabled;
-	state->pmac_enabled = priv->fpe_cfg.pmac_enabled;
-	state->verify_time = priv->fpe_cfg.verify_time;
-	state->tx_enabled = priv->fpe_cfg.tx_enabled;
-	state->verify_status = priv->fpe_cfg.status;
-
-	/* FPE active if common tx_enabled and
-	 * (verification success or disabled(forced))
-	 */
-	if (state->tx_enabled &&
-	    (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
-	     state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED))
-		state->tx_active = true;
-	else
-		state->tx_active = false;
-
-	spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
+	ethtool_mmsv_get_mm(&priv->fpe_cfg.mmsv, state);
 
 	return 0;
 }
@@ -1248,8 +1228,6 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 			 struct netlink_ext_ack *extack)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
 	u32 frag_size;
 	int err;
 
@@ -1259,23 +1237,7 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 		return err;
 
 	stmmac_fpe_set_add_frag_size(priv, frag_size);
-
-	/* Wait for the verification that's currently in progress to finish */
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	fpe_cfg->verify_enabled = cfg->verify_enabled;
-	fpe_cfg->pmac_enabled = cfg->pmac_enabled;
-	fpe_cfg->verify_time = cfg->verify_time;
-	fpe_cfg->tx_enabled = cfg->tx_enabled;
-
-	if (!cfg->verify_enabled)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-
-	stmmac_fpe_apply(priv);
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+	ethtool_mmsv_set_mm(&priv->fpe_cfg.mmsv, cfg);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index 3a4bee029c7f..75b470ee621a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -27,12 +27,6 @@
 #define STMMAC_MAC_FPE_CTRL_STS_SVER	BIT(1)
 #define STMMAC_MAC_FPE_CTRL_STS_EFPE	BIT(0)
 
-/* FPE link-partner hand-shaking mPacket type */
-enum stmmac_mpacket_type {
-	MPACKET_VERIFY = 0,
-	MPACKET_RESPONSE = 1,
-};
-
 struct stmmac_fpe_reg {
 	const u32 mac_fpe_reg;		/* offset of MAC_FPE_CTRL_STS */
 	const u32 mtl_fpe_reg;		/* offset of MTL_FPE_CTRL_STS */
@@ -48,10 +42,10 @@ bool stmmac_fpe_supported(struct stmmac_priv *priv)
 		priv->hw->mac->fpe_map_preemption_class;
 }
 
-static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
-				 bool pmac_enable)
+static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
 {
-	struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
 	const struct stmmac_fpe_reg *reg = cfg->reg;
 	u32 num_rxq = priv->plat->rx_queues_to_use;
 	void __iomem *ioaddr = priv->ioaddr;
@@ -68,6 +62,15 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 		cfg->fpe_csr = 0;
 	}
 	writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
+}
+
+static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
+{
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
+	void __iomem *ioaddr = priv->ioaddr;
+	u32 value;
 
 	value = readl(ioaddr + reg->int_en_reg);
 
@@ -85,47 +88,45 @@ static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
 	writel(value, ioaddr + reg->int_en_reg);
 }
 
-static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
-				    enum stmmac_mpacket_type type)
+static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				    enum ethtool_mpacket type)
 {
-	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
+	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
+	const struct stmmac_fpe_reg *reg = cfg->reg;
 	void __iomem *ioaddr = priv->ioaddr;
-	u32 value = priv->fpe_cfg.fpe_csr;
+	u32 value = cfg->fpe_csr;
 
-	if (type == MPACKET_VERIFY)
+	if (type == ETHTOOL_MPACKET_VERIFY)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
-	else if (type == MPACKET_RESPONSE)
+	else if (type == ETHTOOL_MPACKET_RESPONSE)
 		value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
 
 	writel(value, ioaddr + reg->mac_fpe_reg);
 }
 
+static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
+	.configure_tx = stmmac_fpe_configure_tx,
+	.configure_pmac = stmmac_fpe_configure_pmac,
+	.send_mpacket = stmmac_fpe_send_mpacket,
+};
+
 static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
 {
 	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+	struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv;
 
-	/* This is interrupt context, just spin_lock() */
-	spin_lock(&fpe_cfg->lock);
-
-	if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
-		goto unlock_out;
+	if (status == FPE_EVENT_UNKNOWN)
+		return;
 
-	/* LP has sent verify mPacket */
 	if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
-		stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET);
 
-	/* Local has sent verify mPacket */
-	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+	if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
 
-	/* LP has sent response mPacket */
-	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
-	    fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
-
-unlock_out:
-	spin_unlock(&fpe_cfg->lock);
+	if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP)
+		ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET);
 }
 
 void stmmac_fpe_irq_status(struct stmmac_priv *priv)
@@ -164,119 +165,16 @@ void stmmac_fpe_irq_status(struct stmmac_priv *priv)
 	stmmac_fpe_event_status(priv, status);
 }
 
-/**
- * stmmac_fpe_verify_timer - Timer for MAC Merge verification
- * @t:  timer_list struct containing private info
- *
- * Verify the MAC Merge capability in the local TX direction, by
- * transmitting Verify mPackets up to 3 times. Wait until link
- * partner responds with a Response mPacket, otherwise fail.
- */
-static void stmmac_fpe_verify_timer(struct timer_list *t)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
-	struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
-						fpe_cfg);
-	unsigned long flags;
-	bool rearm = false;
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	switch (fpe_cfg->status) {
-	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
-	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
-		if (fpe_cfg->verify_retries != 0) {
-			stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
-			rearm = true;
-		} else {
-			fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
-		}
-
-		fpe_cfg->verify_retries--;
-		break;
-
-	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
-		stmmac_fpe_configure(priv, true, true);
-		break;
-
-	default:
-		break;
-	}
-
-	if (rearm) {
-		mod_timer(&fpe_cfg->verify_timer,
-			  jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
-static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
-{
-	if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
-	    fpe_cfg->verify_enabled &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
-	    fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
-		timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
-		mod_timer(&fpe_cfg->verify_timer, jiffies);
-	}
-}
-
 void stmmac_fpe_init(struct stmmac_priv *priv)
 {
-	priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-	priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
-	priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
-	timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
-	spin_lock_init(&priv->fpe_cfg.lock);
+	ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev,
+			  &stmmac_mmsv_ops);
 
 	if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
 	    priv->dma_cap.fpesel)
 		dev_info(priv->device, "FPE is not supported by driver.\n");
 }
 
-void stmmac_fpe_apply(struct stmmac_priv *priv)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
-	/* If verification is disabled, configure FPE right away.
-	 * Otherwise let the timer code do it.
-	 */
-	if (!fpe_cfg->verify_enabled) {
-		stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
-				     fpe_cfg->pmac_enabled);
-	} else {
-		fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
-		fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-
-		if (netif_running(priv->dev))
-			stmmac_fpe_verify_timer_arm(fpe_cfg);
-	}
-}
-
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
-{
-	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-	unsigned long flags;
-
-	timer_shutdown_sync(&fpe_cfg->verify_timer);
-
-	spin_lock_irqsave(&fpe_cfg->lock, flags);
-
-	if (is_up && fpe_cfg->pmac_enabled) {
-		/* VERIFY process requires pmac enabled when NIC comes up */
-		stmmac_fpe_configure(priv, false, true);
-
-		/* New link => maybe new partner => new verification process */
-		stmmac_fpe_apply(priv);
-	} else {
-		/* No link => turn off EFPE */
-		stmmac_fpe_configure(priv, false, false);
-	}
-
-	spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
 {
 	const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
index b884eac7142d..3fc46acf7001 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
@@ -9,15 +9,10 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 
-#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES	3
-#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS	128
-
 struct stmmac_priv;
 
-void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
 bool stmmac_fpe_supported(struct stmmac_priv *priv);
 void stmmac_fpe_init(struct stmmac_priv *priv);
-void stmmac_fpe_apply(struct stmmac_priv *priv);
 void stmmac_fpe_irq_status(struct stmmac_priv *priv);
 int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
 void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fa1d7d3a2f43..5a803b7bee7f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -947,7 +947,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, false);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, false);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, false);
 }
 
 static void stmmac_mac_link_up(struct phylink_config *config,
@@ -1065,7 +1065,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 		stmmac_set_eee_pls(priv, priv->hw, true);
 
 	if (stmmac_fpe_supported(priv))
-		stmmac_fpe_link_state_handle(priv, true);
+		ethtool_mmsv_link_state_handle(&priv->fpe_cfg.mmsv, true);
 
 	if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
 		stmmac_hwtstamp_correct_latency(priv, priv);
@@ -4139,7 +4139,7 @@ static int stmmac_release(struct net_device *dev)
 	stmmac_release_ptp(priv);
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	pm_runtime_put(priv->device);
 
@@ -7848,7 +7848,7 @@ int stmmac_suspend(struct device *dev)
 	rtnl_unlock();
 
 	if (stmmac_fpe_supported(priv))
-		timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
+		ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
 
 	return 0;
 }
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 7f222dccc7d1..624e49c9fbf7 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -17,9 +17,13 @@
 #include <linux/compat.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
+#include <linux/timer_types.h>
 #include <uapi/linux/ethtool.h>
 #include <uapi/linux/net_tstamp.h>
 
+#define ETHTOOL_MM_MAX_VERIFY_TIME_MS		128
+#define ETHTOOL_MM_MAX_VERIFY_RETRIES		3
+
 struct compat_ethtool_rx_flow_spec {
 	u32		flow_type;
 	union ethtool_flow_union h_u;
@@ -710,6 +714,75 @@ struct ethtool_mm_stats {
 	u64 MACMergeHoldCount;
 };
 
+enum ethtool_mmsv_event {
+	ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET,
+	ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET,
+};
+
+/* MAC Merge verification mPacket type */
+enum ethtool_mpacket {
+	ETHTOOL_MPACKET_VERIFY,
+	ETHTOOL_MPACKET_RESPONSE,
+};
+
+struct ethtool_mmsv;
+
+/**
+ * struct ethtool_mmsv_ops - Operations for MAC Merge Software Verification
+ * @configure_tx: Driver callback for the event where the preemptible TX
+ *		  becomes active or inactive. Preemptible traffic
+ *		  classes must be committed to hardware only while
+ *		  preemptible TX is active.
+ * @configure_pmac: Driver callback for the event where the pMAC state
+ *		    changes as result of an administrative setting
+ *		    (ethtool) or a call to ethtool_mmsv_link_state_handle().
+ * @send_mpacket: Driver-provided method for sending a Verify or a Response
+ *		  mPacket.
+ */
+struct ethtool_mmsv_ops {
+	void (*configure_tx)(struct ethtool_mmsv *mmsv, bool tx_active);
+	void (*configure_pmac)(struct ethtool_mmsv *mmsv, bool pmac_enabled);
+	void (*send_mpacket)(struct ethtool_mmsv *mmsv, enum ethtool_mpacket mpacket);
+};
+
+/**
+ * struct ethtool_mmsv - MAC Merge Software Verification
+ * @ops: operations for MAC Merge Software Verification
+ * @dev: pointer to net_device structure
+ * @lock: serialize access to MAC Merge state between
+ *	  ethtool requests and link state updates.
+ * @status: current verification FSM state
+ * @verify_timer: timer for verification in local TX direction
+ * @verify_enabled: indicates if verification is enabled
+ * @verify_retries: number of retries for verification
+ * @pmac_enabled: indicates if the preemptible MAC is enabled
+ * @verify_time: time for verification in milliseconds
+ * @tx_enabled: indicates if transmission is enabled
+ */
+struct ethtool_mmsv {
+	const struct ethtool_mmsv_ops *ops;
+	struct net_device *dev;
+	spinlock_t lock;
+	enum ethtool_mm_verify_status status;
+	struct timer_list verify_timer;
+	bool verify_enabled;
+	int verify_retries;
+	bool pmac_enabled;
+	u32 verify_time;
+	bool tx_enabled;
+};
+
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv);
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up);
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event);
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state);
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg);
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops);
+
 /**
  * struct ethtool_rxfh_param - RXFH (RSS) parameters
  * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index 2816bb23c3ad..bfd988464d7d 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright 2022-2023 NXP
+ * Copyright 2022-2025 NXP
+ * Copyright 2024 Furong Xu <0x1207 at gmail.com>
  */
 #include "common.h"
 #include "netlink.h"
@@ -282,3 +283,275 @@ bool ethtool_dev_mm_supported(struct net_device *dev)
 	return supported;
 }
 EXPORT_SYMBOL_GPL(ethtool_dev_mm_supported);
+
+static void ethtool_mmsv_configure_tx(struct ethtool_mmsv *mmsv,
+				      bool tx_active)
+{
+	if (mmsv->ops->configure_tx)
+		mmsv->ops->configure_tx(mmsv, tx_active);
+}
+
+static void ethtool_mmsv_configure_pmac(struct ethtool_mmsv *mmsv,
+					bool pmac_enabled)
+{
+	if (mmsv->ops->configure_pmac)
+		mmsv->ops->configure_pmac(mmsv, pmac_enabled);
+}
+
+static void ethtool_mmsv_send_mpacket(struct ethtool_mmsv *mmsv,
+				      enum ethtool_mpacket mpacket)
+{
+	if (mmsv->ops->send_mpacket)
+		mmsv->ops->send_mpacket(mmsv, mpacket);
+}
+
+/**
+ * ethtool_mmsv_verify_timer - Timer for MAC Merge verification
+ * @t: timer_list struct containing private info
+ *
+ * Verify the MAC Merge capability in the local TX direction, by
+ * transmitting Verify mPackets up to 3 times. Wait until link
+ * partner responds with a Response mPacket, otherwise fail.
+ */
+static void ethtool_mmsv_verify_timer(struct timer_list *t)
+{
+	struct ethtool_mmsv *mmsv = from_timer(mmsv, t, verify_timer);
+	unsigned long flags;
+	bool rearm = false;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	switch (mmsv->status) {
+	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+		if (mmsv->verify_retries != 0) {
+			ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_VERIFY);
+			rearm = true;
+		} else {
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+		}
+
+		mmsv->verify_retries--;
+		break;
+
+	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+		ethtool_mmsv_configure_tx(mmsv, true);
+		break;
+
+	default:
+		break;
+	}
+
+	if (rearm) {
+		mod_timer(&mmsv->verify_timer,
+			  jiffies + msecs_to_jiffies(mmsv->verify_time));
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+
+static void ethtool_mmsv_verify_timer_arm(struct ethtool_mmsv *mmsv)
+{
+	if (mmsv->pmac_enabled && mmsv->tx_enabled && mmsv->verify_enabled &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
+	    mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
+		timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+		mod_timer(&mmsv->verify_timer, jiffies);
+	}
+}
+
+static void ethtool_mmsv_apply(struct ethtool_mmsv *mmsv)
+{
+	/* If verification is disabled, configure FPE right away.
+	 * Otherwise let the timer code do it.
+	 */
+	if (!mmsv->verify_enabled) {
+		ethtool_mmsv_configure_pmac(mmsv, mmsv->pmac_enabled);
+		ethtool_mmsv_configure_tx(mmsv, mmsv->tx_enabled);
+	} else {
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+
+		if (netif_running(mmsv->dev))
+			ethtool_mmsv_verify_timer_arm(mmsv);
+	}
+}
+
+/**
+ * ethtool_mmsv_stop() - Stop MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ *
+ * Drivers should call this method in a state where the hardware is
+ * about to lose state, like ndo_stop() or suspend(), and turning off
+ * MAC Merge features would be superfluous. Otherwise, prefer
+ * ethtool_mmsv_link_state_handle() with up=false.
+ */
+void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv)
+{
+	timer_shutdown_sync(&mmsv->verify_timer);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_stop);
+
+/**
+ * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification
+ *				      of link state changes
+ * @mmsv: MAC Merge Software Verification state
+ * @up: True if device carrier is up and able to pass verification packets
+ *
+ * Calling context is expected to be from a task, interrupts enabled.
+ */
+void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
+{
+	unsigned long flags;
+
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	if (up && mmsv->pmac_enabled) {
+		/* VERIFY process requires pMAC enabled when NIC comes up */
+		ethtool_mmsv_configure_pmac(mmsv, true);
+
+		/* New link => maybe new partner => new verification process */
+		ethtool_mmsv_apply(mmsv);
+	} else {
+		/* No link or pMAC not enabled */
+		ethtool_mmsv_configure_pmac(mmsv, false);
+		ethtool_mmsv_configure_tx(mmsv, false);
+	}
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle);
+
+/**
+ * ethtool_mmsv_event_handle() - Inform MAC Merge Software Verification
+ *				 of interrupt-based events
+ * @mmsv: MAC Merge Software Verification state
+ * @event: Event which took place (packet transmission or reception)
+ *
+ * Calling context expects to have interrupts disabled.
+ */
+void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv,
+			       enum ethtool_mmsv_event event)
+{
+	/* This is interrupt context, just spin_lock() */
+	spin_lock(&mmsv->lock);
+
+	if (!mmsv->pmac_enabled)
+		goto unlock;
+
+	switch (event) {
+	case ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET:
+		/* Link partner has sent verify mPacket */
+		ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_RESPONSE);
+		break;
+	case ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET:
+		/* Local device has sent verify mPacket */
+		if (mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+		break;
+	case ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET:
+		/* Link partner has sent response mPacket */
+		if (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+		break;
+	}
+
+unlock:
+	spin_unlock(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_event_handle);
+
+static bool ethtool_mmsv_is_tx_active(struct ethtool_mmsv *mmsv)
+{
+	/* TX is active if administratively enabled, and verification either
+	 * succeeded, or was administratively disabled.
+	 */
+	return mmsv->tx_enabled &&
+	       (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
+	       mmsv->status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
+}
+
+/**
+ * ethtool_mmsv_get_mm() - get_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @state: see struct ethtool_mm_state
+ *
+ * Drivers are expected to call this from their ethtool_ops :: get_mm()
+ * method.
+ */
+void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv,
+			 struct ethtool_mm_state *state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	state->verify_enabled = mmsv->verify_enabled;
+	state->pmac_enabled = mmsv->pmac_enabled;
+	state->verify_time = mmsv->verify_time;
+	state->tx_enabled = mmsv->tx_enabled;
+	state->verify_status = mmsv->status;
+	state->tx_active = ethtool_mmsv_is_tx_active(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_get_mm);
+
+/**
+ * ethtool_mmsv_set_mm() - set_mm() hook for MAC Merge Software Verification
+ * @mmsv: MAC Merge Software Verification state
+ * @cfg: see struct ethtool_mm_cfg
+ *
+ * Drivers are expected to call this from their ethtool_ops :: set_mm()
+ * method.
+ */
+void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg)
+{
+	unsigned long flags;
+
+	/* Wait for the verification that's currently in progress to finish */
+	ethtool_mmsv_stop(mmsv);
+
+	spin_lock_irqsave(&mmsv->lock, flags);
+
+	mmsv->verify_enabled = cfg->verify_enabled;
+	mmsv->pmac_enabled = cfg->pmac_enabled;
+	mmsv->verify_time = cfg->verify_time;
+	mmsv->tx_enabled = cfg->tx_enabled;
+
+	if (!cfg->verify_enabled)
+		mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+
+	ethtool_mmsv_apply(mmsv);
+
+	spin_unlock_irqrestore(&mmsv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_set_mm);
+
+/**
+ * ethtool_mmsv_init() - Initialize MAC Merge Software Verification state
+ * @mmsv: MAC Merge Software Verification state
+ * @dev: Pointer to network interface
+ * @ops: Methods for implementing the generic functionality
+ *
+ * The MAC Merge Software Verification is a timer- and event-based state
+ * machine intended for network interfaces which lack a hardware-based
+ * TX verification process (as per IEEE 802.3 clause 99.4.3). The timer
+ * is managed by the core code, whereas events are supplied by the
+ * driver explicitly calling one of the other API functions.
+ */
+void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev,
+		       const struct ethtool_mmsv_ops *ops)
+{
+	mmsv->ops = ops;
+	mmsv->dev = dev;
+	mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES;
+	mmsv->verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+	mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+	timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0);
+	spin_lock_init(&mmsv->lock);
+}
+EXPORT_SYMBOL_GPL(ethtool_mmsv_init);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:31 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:31 -0400
Subject: [PATCH iwl-next v10 03/14] net: ethtool: mm: reset verification status when link is down
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-4-faizal.abdul.rahim@linux.intel.com>

When the link partner goes down, "ethtool --show-mm" still displays
"Verification status: SUCCEEDED," reflecting a previous state that is
no longer valid.

Reset the verification status to ensure it reflects the current state.

Reviewed-by: Furong Xu <0x1207 at gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 net/ethtool/mm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/ethtool/mm.c b/net/ethtool/mm.c
index bfd988464d7d..ad9b40034003 100644
--- a/net/ethtool/mm.c
+++ b/net/ethtool/mm.c
@@ -415,6 +415,10 @@ void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up)
 		/* New link => maybe new partner => new verification process */
 		ethtool_mmsv_apply(mmsv);
 	} else {
+		/* Reset the reported verification state while the link is down */
+		if (mmsv->verify_enabled)
+			mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+
 		/* No link or pMAC not enabled */
 		ethtool_mmsv_configure_pmac(mmsv, false);
 		ethtool_mmsv_configure_tx(mmsv, false);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:32 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:32 -0400
Subject: [PATCH iwl-next v10 04/14] igc: rename xdp_get_tx_ring() for non-xdp usage
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-5-faizal.abdul.rahim@linux.intel.com>

Renamed xdp_get_tx_ring() function to a more generic name for use in
upcoming frame preemption patches.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h      | 2 +-
 drivers/net/ethernet/intel/igc/igc_main.c | 9 ++++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index cd1d7b6c1782..ba7c55d2dc85 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -737,7 +737,7 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
-
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 472f009630c9..99123eef610b 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2464,8 +2464,7 @@ static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
 	return -ENOMEM;
 }
 
-static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
-					    int cpu)
+struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu)
 {
 	int index = cpu;
 
@@ -2489,7 +2488,7 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
 	if (unlikely(!xdpf))
 		return -EFAULT;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
@@ -2566,7 +2565,7 @@ static void igc_finalize_xdp(struct igc_adapter *adapter, int status)
 	struct igc_ring *ring;
 
 	if (status & IGC_XDP_TX) {
-		ring = igc_xdp_get_tx_ring(adapter, cpu);
+		ring = igc_get_tx_ring(adapter, cpu);
 		nq = txring_txq(ring);
 
 		__netif_tx_lock(nq, cpu);
@@ -6779,7 +6778,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
 	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
 		return -EINVAL;
 
-	ring = igc_xdp_get_tx_ring(adapter, cpu);
+	ring = igc_get_tx_ring(adapter, cpu);
 	nq = txring_txq(ring);
 
 	__netif_tx_lock(nq, cpu);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:33 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:33 -0400
Subject: [PATCH iwl-next v10 05/14] igc: rename I225_RXPBSIZE_DEFAULT and I225_TXPBSIZE_DEFAULT
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-6-faizal.abdul.rahim@linux.intel.com>

Rename RX and TX packet buffer size macros in preparation for an
upcoming patch that will refactor buffer size handling using FIELD_PREP
and GENMASK.

Changes:
- Rename I225_RXPBSIZE_DEFAULT to IGC_RXPBSIZE_EXP_BMC_DEFAULT.
  The EXP_BMC suffix explicitly indicates Express and BMC buffer
  default values, improving readability and reusability for the
  upcoming changes, while also better reflecting the current buffer
  allocations.
- Rename I225_TXPBSIZE_DEFAULT to IGC_TXPBSIZE_DEFAULT.

These registers apply to both i225 and i226, so using the IGC prefix
aligns with existing macro naming conventions.

Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 7 ++++---
 drivers/net/ethernet/intel/igc/igc_main.c    | 4 ++--
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 8e449904aa7d..b6744ece64f0 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -396,9 +396,10 @@
 #define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
 #define IGC_RCTL_SECRC		0x04000000 /* Strip Ethernet CRC */
 
-#define I225_RXPBSIZE_DEFAULT	0x000000A2 /* RXPBSIZE default */
-#define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
-#define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */
+/* RXPBSIZE default value for Express and BMC buffer */
+#define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
+#define IGC_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
+#define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
 
 #define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
 
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 99123eef610b..6f0110e3ac22 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -7156,8 +7156,8 @@ static int igc_probe(struct pci_dev *pdev,
 	}
 
 	/* configure RXPBSIZE and TXPBSIZE */
-	wr32(IGC_RXPBS, I225_RXPBSIZE_DEFAULT);
-	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
+	wr32(IGC_RXPBS, IGC_RXPBSIZE_EXP_BMC_DEFAULT);
+	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 
 	timer_setup(&adapter->watchdog_timer, igc_watchdog, 0);
 	timer_setup(&adapter->phy_info_timer, igc_update_phy_info, 0);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 1e44374ca1ff..498741d83ca6 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -136,7 +136,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	int i;
 
 	wr32(IGC_GTXOFFSET, 0);
-	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
+	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
 	if (igc_is_device_id_i226(hw))
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:34 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:34 -0400
Subject: [PATCH iwl-next v10 06/14] igc: use FIELD_PREP and GENMASK for existing TX packet buffer size
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-7-faizal.abdul.rahim@linux.intel.com>

In preparation for an upcoming patch that will modify the TX buffer size
in  TSN mode, replace IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT
implementation with new macros that utilizes FIELD_PREP and GENMASK for
clarity.

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

I've tested IGC_TXPBSIZE_TSN and IGC_TXPBSIZE_DEFAULT before and after the
refactoring, and their values remain unchanged.

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 23 ++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b6744ece64f0..b180e1497cc5 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -398,10 +398,29 @@
 
 /* RXPBSIZE default value for Express and BMC buffer */
 #define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
-#define IGC_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
 #define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
 
-#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
+/* Mask for TX packet buffer size */
+#define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
+#define IGC_TXPB1SIZE_MASK		GENMASK(11, 6)
+#define IGC_TXPB2SIZE_MASK		GENMASK(17, 12)
+#define IGC_TXPB3SIZE_MASK		GENMASK(23, 18)
+/* Mask for OS to BMC packet buffer size */
+#define IGC_OS2BMCPBSIZE_MASK		GENMASK(29, 24)
+/* TX Packet buffer size in KB */
+#define IGC_TXPB0SIZE(x)		FIELD_PREP(IGC_TXPB0SIZE_MASK, (x))
+#define IGC_TXPB1SIZE(x)		FIELD_PREP(IGC_TXPB1SIZE_MASK, (x))
+#define IGC_TXPB2SIZE(x)		FIELD_PREP(IGC_TXPB2SIZE_MASK, (x))
+#define IGC_TXPB3SIZE(x)		FIELD_PREP(IGC_TXPB3SIZE_MASK, (x))
+/* OS to BMC packet buffer size in KB */
+#define IGC_OS2BMCPBSIZE(x)		FIELD_PREP(IGC_OS2BMCPBSIZE_MASK, (x))
+/* Default value following I225/I226 SW User Manual Section 8.3.2 */
+#define IGC_TXPBSIZE_DEFAULT ( \
+	IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
+	IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
+#define IGC_TXPBSIZE_TSN ( \
+	IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \
+	IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4))
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:35 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:35 -0400
Subject: [PATCH iwl-next v10 07/14] igc: optimize TX packet buffer utilization for TSN mode
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-8-faizal.abdul.rahim@linux.intel.com>

In preparation for upcoming frame preemption patches, optimize the TX
packet buffer size. The total packet buffer size (RX + TX) is 64KB, with
a maximum of 34KB for either RX or TX. Split the buffer evenly,
allocating 32KB to each.

For TX, assign 7KB to each of the four TX packet buffers (total 28KB)
and reserve 4KB for BMC.

References:
I225/I226 SW User Manual Section 4.7.9, Section 8.3.2

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index b180e1497cc5..db937931c646 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -419,8 +419,8 @@
 	IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
 	IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
 #define IGC_TXPBSIZE_TSN ( \
-	IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \
-	IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4))
+	IGC_TXPB0SIZE(7) | IGC_TXPB1SIZE(7) | IGC_TXPB2SIZE(7) | \
+	IGC_TXPB3SIZE(7) | IGC_OS2BMCPBSIZE(4))
 
 #define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
 #define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:36 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:36 -0400
Subject: [PATCH iwl-next v10 08/14] igc: use FIELD_PREP and GENMASK for existing RX packet buffer size
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-9-faizal.abdul.rahim@linux.intel.com>

Prepare for an upcoming patch that modifies the RX buffer size in TSN mode.
Refactor IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN using
FIELD_PREP and GENMASK to improve clarity and maintainability. Refactor
both macros for consistency, even though the upcoming patch only use
IGC_RXPBSIZE_EXP_BMC_DEFAULT.

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

I've tested IGC_RXPBSIZE_EXP_BMC_DEFAULT and IGC_RXPBS_CFG_TS_EN before
and after the refactoring, and their values remain unchanged.

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index db937931c646..3564d15df57b 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -396,9 +396,20 @@
 #define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
 #define IGC_RCTL_SECRC		0x04000000 /* Strip Ethernet CRC */
 
-/* RXPBSIZE default value for Express and BMC buffer */
-#define IGC_RXPBSIZE_EXP_BMC_DEFAULT	0x000000A2
-#define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
+/* Mask for RX packet buffer size */
+#define IGC_RXPBSIZE_EXP_MASK		GENMASK(5, 0)
+#define IGC_BMC2OSPBSIZE_MASK		GENMASK(11, 6)
+/* Mask for timestamp in RX buffer */
+#define IGC_RXPBS_CFG_TS_EN_MASK	GENMASK(31, 31)
+/* High-priority RX packet buffer size (KB). Used for Express traffic when preemption is enabled */
+#define IGC_RXPBSIZE_EXP(x)		FIELD_PREP(IGC_RXPBSIZE_EXP_MASK, (x))
+/* BMC to OS packet buffer size in KB */
+#define IGC_BMC2OSPBSIZE(x)		FIELD_PREP(IGC_BMC2OSPBSIZE_MASK, (x))
+/* Enable RX packet buffer for timestamp descriptor, saving 16 bytes per packet if set */
+#define IGC_RXPBS_CFG_TS_EN		FIELD_PREP(IGC_RXPBS_CFG_TS_EN_MASK, 1)
+/* Default value following I225/I226 SW User Manual Section 8.3.1 */
+#define IGC_RXPBSIZE_EXP_BMC_DEFAULT ( \
+	IGC_RXPBSIZE_EXP(34) | IGC_BMC2OSPBSIZE(2))
 
 /* Mask for TX packet buffer size */
 #define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:37 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:37 -0400
Subject: [PATCH iwl-next v10 09/14] igc: set the RX packet buffer size for TSN mode
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-10-faizal.abdul.rahim@linux.intel.com>

In preparation for supporting frame preemption, when entering TSN mode,
set the receive packet buffer to 15KB for the Express MAC, 15KB for
the Preemptible MAC and 2KB for the BMC.

References:
I225/I226 SW User Manual, Section 4.7.9, Section 7.1.3.2, Section 8.3.1

The newly introduced macros follow the naming from the i226 SW User Manual
for easy reference.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_defines.h |  5 ++++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 25 ++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 3564d15df57b..d753a8ec36ae 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -399,17 +399,22 @@
 /* Mask for RX packet buffer size */
 #define IGC_RXPBSIZE_EXP_MASK		GENMASK(5, 0)
 #define IGC_BMC2OSPBSIZE_MASK		GENMASK(11, 6)
+#define IGC_RXPBSIZE_BE_MASK		GENMASK(17, 12)
 /* Mask for timestamp in RX buffer */
 #define IGC_RXPBS_CFG_TS_EN_MASK	GENMASK(31, 31)
 /* High-priority RX packet buffer size (KB). Used for Express traffic when preemption is enabled */
 #define IGC_RXPBSIZE_EXP(x)		FIELD_PREP(IGC_RXPBSIZE_EXP_MASK, (x))
 /* BMC to OS packet buffer size in KB */
 #define IGC_BMC2OSPBSIZE(x)		FIELD_PREP(IGC_BMC2OSPBSIZE_MASK, (x))
+/* Low-priority RX packet buffer size (KB). Used for BE traffic when preemption is enabled */
+#define IGC_RXPBSIZE_BE(x)		FIELD_PREP(IGC_RXPBSIZE_BE_MASK, (x))
 /* Enable RX packet buffer for timestamp descriptor, saving 16 bytes per packet if set */
 #define IGC_RXPBS_CFG_TS_EN		FIELD_PREP(IGC_RXPBS_CFG_TS_EN_MASK, 1)
 /* Default value following I225/I226 SW User Manual Section 8.3.1 */
 #define IGC_RXPBSIZE_EXP_BMC_DEFAULT ( \
 	IGC_RXPBSIZE_EXP(34) | IGC_BMC2OSPBSIZE(2))
+#define IGC_RXPBSIZE_EXP_BMC_BE_TSN ( \
+	IGC_RXPBSIZE_EXP(15) | IGC_BMC2OSPBSIZE(2) | IGC_RXPBSIZE_BE(15))
 
 /* Mask for TX packet buffer size */
 #define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 498741d83ca6..5b3b1bc0b64a 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -125,6 +125,27 @@ static void igc_tsn_tx_arb(struct igc_adapter *adapter, u16 *queue_per_tc)
 	wr32(IGC_TXARB, txarb);
 }
 
+/**
+ * igc_tsn_set_rxpbsize - Set the receive packet buffer size
+ * @adapter: Pointer to the igc_adapter structure
+ * @rxpbs_exp_bmc_be: Value to set the receive packet buffer size, including
+ *                    express buffer, BMC buffer, and Best Effort buffer
+ *
+ * The IGC_RXPBS register value may include allocations for the Express buffer,
+ * BMC buffer, Best Effort buffer, and the timestamp descriptor buffer (IGC_RXPBS_CFG_TS_EN).
+ */
+static void igc_tsn_set_rxpbsize(struct igc_adapter *adapter, u32 rxpbs_exp_bmc_be)
+{
+	struct igc_hw *hw = &adapter->hw;
+	u32 rxpbs = rd32(IGC_RXPBS);
+
+	rxpbs &= ~(IGC_RXPBSIZE_EXP_MASK | IGC_BMC2OSPBSIZE_MASK |
+		   IGC_RXPBSIZE_BE_MASK);
+	rxpbs |= rxpbs_exp_bmc_be;
+
+	wr32(IGC_RXPBS, rxpbs);
+}
+
 /* Returns the TSN specific registers to their default values after
  * the adapter is reset.
  */
@@ -139,6 +160,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
 
+	igc_tsn_set_rxpbsize(adapter, IGC_RXPBSIZE_EXP_BMC_DEFAULT);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_restore_retx_default(adapter);
 
@@ -202,6 +225,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
 	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
 
+	igc_tsn_set_rxpbsize(adapter, IGC_RXPBSIZE_EXP_BMC_BE_TSN);
+
 	if (igc_is_device_id_i226(hw))
 		igc_tsn_set_retx_qbvfullthreshold(adapter);
 
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:38 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:38 -0400
Subject: [PATCH iwl-next v10 10/14] igc: add support for frame preemption verification
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-11-faizal.abdul.rahim@linux.intel.com>

This patch implements the "ethtool --set-mm" callback to trigger the
frame preemption verification handshake.

Uses the MAC Merge Software Verification (mmsv) mechanism in ethtool
to perform the verification handshake for igc.
The structure fpe.mmsv is set by mmsv in ethtool and should remain
read-only for the driver.

Other mmsv callbacks:
a) configure_tx() -> not used yet at this point
   - igc lacks registers to configure FPE in the transmit direction, so
     this API is not utilized for now. When igc supports preemptible queue,
     driver will use this API to manage its configuration.

b) configure_pmac() -> not used
   - this callback dynamically controls pmac_enabled at runtime. For
     example, mmsv calls configure_pmac() and disables pmac_enabled when
     the link partner goes down, even if the user previously enabled it.
     The intention is to save power but it is not feasible in igc
     because it causes an endless adapter reset loop:

   1) Board A and Board B complete the verification handshake. Tx mode
      register for both boards are in TSN mode.
   2) Board B link goes down.

   On Board A:
   3) mmsv calls configure_pmac() with pmac_enabled = false.
   4) configure_pmac() in igc updates a new field based on pmac_enabled.
      Driver uses this field in igc_tsn_new_flags() to indicate that the
      user enabled/disabled FPE.
   5) configure_pmac() in igc calls igc_tsn_offload_apply() to check
      whether an adapter reset is needed. Calls existing logic in
      igc_tsn_will_tx_mode_change() and igc_tsn_new_flags().
   6) Since pmac_enabled is now disabled and no other TSN feature is
      active, igc_tsn_will_tx_mode_change() evaluates to true because Tx
      mode will switch from TSN to Legacy.
   7) Driver resets the adapter.
   8) Registers are set, and Tx mode switches to Legacy.
   9) When link partner is up, steps 3?8 repeat, but this time with
      pmac_enabled = true, reactivating TSN.
      igc_tsn_will_tx_mode_change() evaluates to true again, since Tx
      mode will switch from Legacy to TSN.
  10) Driver resets the adapter.
  11) Adapter reset completes, registers are set, and Tx mode switches to
      TSN.

  On Board B:
  12) Adapter reset on Board A at step 10 causes it to detect its link
      partner as down.
  13) Repeats steps 3?8.
  14) Once reset adapter on Board A is completed at step 11, it detects
      its link partner as up.
  15) Repeats steps 9?11.

   - this cycle repeats indefinitely. To avoid this issue, igc only uses
     mmsv.pmac_enabled to track whether FPE is enabled or disabled.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/Kconfig           |   1 +
 drivers/net/ethernet/intel/igc/igc.h         |  12 +-
 drivers/net/ethernet/intel/igc/igc_base.h    |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |   8 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  21 +++
 drivers/net/ethernet/intel/igc/igc_main.c    |  52 ++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 146 ++++++++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  50 +++++++
 8 files changed, 286 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 1640d2f27833..906e0daaa2b0 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -367,6 +367,7 @@ config IGC
 	default n
 	depends on PCI
 	depends on PTP_1588_CLOCK_OPTIONAL
+	depends on ETHTOOL_NETLINK
 	help
 	  This driver supports Intel(R) Ethernet Controller I225-LM/I225-V
 	  family of adapters.
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index ba7c55d2dc85..d970968f3233 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -40,6 +40,10 @@ void igc_ethtool_set_ops(struct net_device *);
 
 #define IGC_MAX_TX_TSTAMP_REGS		4
 
+struct igc_fpe_t {
+	struct ethtool_mmsv mmsv;
+};
+
 enum igc_mac_filter_type {
 	IGC_MAC_FILTER_TYPE_DST = 0,
 	IGC_MAC_FILTER_TYPE_SRC
@@ -332,6 +336,8 @@ struct igc_adapter {
 		struct timespec64 period;
 	} perout[IGC_N_PEROUT];
 
+	struct igc_fpe_t fpe;
+
 	/* LEDs */
 	struct mutex led_mutex;
 	struct igc_led_classdev *leds;
@@ -389,10 +395,11 @@ extern char igc_driver_name[];
 #define IGC_FLAG_TSN_QBV_ENABLED	BIT(17)
 #define IGC_FLAG_TSN_QAV_ENABLED	BIT(18)
 #define IGC_FLAG_TSN_LEGACY_ENABLED	BIT(19)
+#define IGC_FLAG_TSN_PREEMPT_ENABLED	BIT(20)
 
 #define IGC_FLAG_TSN_ANY_ENABLED				\
 	(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED |	\
-	 IGC_FLAG_TSN_LEGACY_ENABLED)
+	 IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)
 
 #define IGC_FLAG_RSS_FIELD_IPV4_UDP	BIT(6)
 #define IGC_FLAG_RSS_FIELD_IPV6_UDP	BIT(7)
@@ -737,7 +744,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
 				      u32 location);
 int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
 void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter);
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter);
 struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
+void igc_flush_tx_descriptors(struct igc_ring *ring);
 void igc_ptp_init(struct igc_adapter *adapter);
 void igc_ptp_reset(struct igc_adapter *adapter);
 void igc_ptp_suspend(struct igc_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h
index bf8cdfbba9ff..6320eabb72fe 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.h
+++ b/drivers/net/ethernet/intel/igc/igc_base.h
@@ -49,6 +49,7 @@ struct igc_adv_tx_context_desc {
 #define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
 #define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
 #define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
+#define IGC_ADVTXD_PAYLEN_MASK	0XFFFFC000 /* Adv desc PAYLEN mask */
 #define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */
 
 #define IGC_RAR_ENTRIES		16
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index d753a8ec36ae..542c7c8802a0 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -308,6 +308,8 @@
 #define IGC_TXD_DTYP_C		0x00000000 /* Context Descriptor */
 #define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
 #define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
+#define IGC_TXD_POPTS_SMD_MASK	0x3000     /* Indicates whether it's SMD-V or SMD-R */
+
 #define IGC_TXD_CMD_EOP		0x01000000 /* End of Packet */
 #define IGC_TXD_CMD_IC		0x04000000 /* Insert Checksum */
 #define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
@@ -363,6 +365,8 @@
 #define IGC_SRRCTL_TIMER0SEL(timer)	(((timer) & 0x3) << 17)
 
 /* Receive Descriptor bit definitions */
+#define IGC_RXD_STAT_SMD_TYPE_V	0x01	/* SMD-V Packet */
+#define IGC_RXD_STAT_SMD_TYPE_R	0x02	/* SMD-R Packet */
 #define IGC_RXD_STAT_EOP	0x02	/* End of Packet */
 #define IGC_RXD_STAT_IXSM	0x04	/* Ignore checksum */
 #define IGC_RXD_STAT_UDPCS	0x10	/* UDP xsum calculated */
@@ -372,7 +376,8 @@
 #define IGC_RXDEXT_STATERR_LB	0x00040000
 
 /* Advanced Receive Descriptor bit definitions */
-#define IGC_RXDADV_STAT_TSIP	0x08000 /* timestamp in packet */
+#define IGC_RXDADV_STAT_SMD_TYPE_MASK	0x06000
+#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */
 
 #define IGC_RXDEXT_STATERR_L4E		0x20000000
 #define IGC_RXDEXT_STATERR_IPE		0x40000000
@@ -575,6 +580,7 @@
 
 /* Transmit Scheduling */
 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
+#define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
 
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 817838677817..b64d5c6c1d20 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -8,6 +8,7 @@
 
 #include "igc.h"
 #include "igc_diag.h"
+#include "igc_tsn.h"
 
 /* forward declaration */
 struct igc_stats {
@@ -1781,6 +1782,25 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_set_mm(struct net_device *netdev,
+			      struct ethtool_mm_cfg *cmd,
+			      struct netlink_ext_ack *extack)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
+		if (cmd->pmac_enabled)
+			static_branch_inc(&igc_fpe_enabled);
+		else
+			static_branch_dec(&igc_fpe_enabled);
+	}
+
+	ethtool_mmsv_set_mm(&fpe->mmsv, cmd);
+
+	return igc_tsn_offload_apply(adapter);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2076,6 +2096,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.set_mm			= igc_ethtool_set_mm,
 };
 
 void igc_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 6f0110e3ac22..71c377cb7a88 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2548,7 +2548,7 @@ static int igc_xdp_run_prog(struct igc_adapter *adapter, struct xdp_buff *xdp)
 }
 
 /* This function assumes __netif_tx_lock is held by the caller. */
-static void igc_flush_tx_descriptors(struct igc_ring *ring)
+void igc_flush_tx_descriptors(struct igc_ring *ring)
 {
 	/* Once tail pointer is updated, hardware can fetch the descriptors
 	 * any time so we issue a write membar here to ensure all memory
@@ -2637,6 +2637,14 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
 			size -= IGC_TS_HDR_LEN;
 		}
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf)) {
+			/* Advance the ring next-to-clean */
+			igc_is_non_eop(rx_ring, rx_desc);
+			cleaned_count++;
+			continue;
+		}
+
 		if (!skb) {
 			xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
 			xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
@@ -3144,6 +3152,11 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
 		if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD)))
 			break;
 
+		if (igc_fpe_is_pmac_enabled(adapter) &&
+		    igc_fpe_transmitted_smd_v(tx_desc))
+			ethtool_mmsv_event_handle(&adapter->fpe.mmsv,
+						  ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
+
 		/* Hold the completions while there's a pending tx hardware
 		 * timestamp request from XDP Tx metadata.
 		 */
@@ -4035,6 +4048,30 @@ static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr)
 	return 0;
 }
 
+/**
+ * igc_enable_empty_addr_recv - Enable Rx of packets with all-zeroes MAC address
+ * @adapter: Pointer to the igc_adapter structure.
+ *
+ * Frame preemption verification requires that packets with the all-zeroes
+ * MAC address are allowed to be received by the driver. This function adds the
+ * all-zeroes destination address to the list of acceptable addresses.
+ *
+ * Return: 0 on success, negative value otherwise.
+ */
+int igc_enable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty, -1);
+}
+
+void igc_disable_empty_addr_recv(struct igc_adapter *adapter)
+{
+	u8 empty[ETH_ALEN] = {};
+
+	igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, empty);
+}
+
 /**
  * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
  * @netdev: network interface device structure
@@ -5310,6 +5347,9 @@ void igc_down(struct igc_adapter *adapter)
 	igc_disable_all_tx_rings_hw(adapter);
 	igc_clean_all_tx_rings(adapter);
 	igc_clean_all_rx_rings(adapter);
+
+	if (adapter->fpe.mmsv.pmac_enabled)
+		ethtool_mmsv_stop(&adapter->fpe.mmsv);
 }
 
 void igc_reinit_locked(struct igc_adapter *adapter)
@@ -5834,6 +5874,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			 */
 			igc_tsn_adjust_txtime_offset(adapter);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       true);
+
 			if (adapter->link_speed != SPEED_1000)
 				goto no_wait;
 
@@ -5869,6 +5913,10 @@ static void igc_watchdog_task(struct work_struct *work)
 			netdev_info(netdev, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 
+			if (adapter->fpe.mmsv.pmac_enabled)
+				ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv,
+							       false);
+
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGC_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
@@ -7189,6 +7237,8 @@ static int igc_probe(struct pci_dev *pdev,
 
 	igc_tsn_clear_schedule(adapter);
 
+	igc_fpe_init(adapter);
+
 	/* reset the hardware with the new settings */
 	igc_reset(adapter);
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 5b3b1bc0b64a..8a1725688381 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -2,9 +2,135 @@
 /* Copyright (c)  2019 Intel Corporation */
 
 #include "igc.h"
+#include "igc_base.h"
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+static int igc_fpe_init_smd_frame(struct igc_ring *ring,
+				  struct igc_tx_buffer *buffer,
+				  struct sk_buff *skb)
+{
+	dma_addr_t dma = dma_map_single(ring->dev, skb->data, skb->len,
+					DMA_TO_DEVICE);
+
+	if (dma_mapping_error(ring->dev, dma)) {
+		netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
+		return -ENOMEM;
+	}
+
+	buffer->skb = skb;
+	buffer->protocol = 0;
+	buffer->bytecount = skb->len;
+	buffer->gso_segs = 1;
+	buffer->time_stamp = jiffies;
+	dma_unmap_len_set(buffer, len, skb->len);
+	dma_unmap_addr_set(buffer, dma, dma);
+
+	return 0;
+}
+
+static int igc_fpe_init_tx_descriptor(struct igc_ring *ring,
+				      struct sk_buff *skb,
+				      enum igc_txd_popts_type type)
+{
+	u32 cmd_type, olinfo_status = 0;
+	struct igc_tx_buffer *buffer;
+	union igc_adv_tx_desc *desc;
+	int err;
+
+	if (!igc_desc_unused(ring))
+		return -EBUSY;
+
+	buffer = &ring->tx_buffer_info[ring->next_to_use];
+	err = igc_fpe_init_smd_frame(ring, buffer, skb);
+	if (err)
+		return err;
+
+	cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
+		   IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
+		   buffer->bytecount;
+
+	olinfo_status |= FIELD_PREP(IGC_ADVTXD_PAYLEN_MASK, buffer->bytecount);
+
+	switch (type) {
+	case SMD_V:
+	case SMD_R:
+		olinfo_status |= FIELD_PREP(IGC_TXD_POPTS_SMD_MASK, type);
+		break;
+	}
+
+	desc = IGC_TX_DESC(ring, ring->next_to_use);
+	desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+	desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+	desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
+
+	netdev_tx_sent_queue(txring_txq(ring), skb->len);
+
+	buffer->next_to_watch = desc;
+	ring->next_to_use = (ring->next_to_use + 1) % ring->count;
+
+	return 0;
+}
+
+static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
+				  enum igc_txd_popts_type type)
+{
+	int cpu = smp_processor_id();
+	struct netdev_queue *nq;
+	struct igc_ring *ring;
+	struct sk_buff *skb;
+	int err;
+
+	ring = igc_get_tx_ring(adapter, cpu);
+	nq = txring_txq(ring);
+
+	skb = alloc_skb(SMD_FRAME_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put_zero(skb, SMD_FRAME_SIZE);
+
+	__netif_tx_lock(nq, cpu);
+
+	err = igc_fpe_init_tx_descriptor(ring, skb, type);
+	igc_flush_tx_descriptors(ring);
+
+	__netif_tx_unlock(nq);
+
+	return err;
+}
+
+static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+				 enum ethtool_mpacket type)
+{
+	struct igc_fpe_t *fpe = container_of(mmsv, struct igc_fpe_t, mmsv);
+	struct igc_adapter *adapter;
+	int err;
+
+	adapter = container_of(fpe, struct igc_adapter, fpe);
+
+	if (type == ETHTOOL_MPACKET_VERIFY) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_V);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-V\n");
+	} else if (type == ETHTOOL_MPACKET_RESPONSE) {
+		err = igc_fpe_xmit_smd_frame(adapter, SMD_R);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error sending SMD-R frame\n");
+	}
+}
+
+static const struct ethtool_mmsv_ops igc_mmsv_ops = {
+	.send_mpacket = igc_fpe_send_mpacket,
+};
+
+void igc_fpe_init(struct igc_adapter *adapter)
+{
+	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
+}
+
 static bool is_any_launchtime(struct igc_adapter *adapter)
 {
 	int i;
@@ -49,6 +175,9 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
 	if (adapter->strict_priority_enable)
 		new_flags |= IGC_FLAG_TSN_LEGACY_ENABLED;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		new_flags |= IGC_FLAG_TSN_PREEMPT_ENABLED;
+
 	return new_flags;
 }
 
@@ -167,7 +296,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
-		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
+		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
+		      IGC_TQAVCTRL_PREEMPT_ENA);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -386,10 +516,14 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 		wr32(IGC_TXQCTL(i), txqctl);
 	}
 
-	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
+	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
+		   IGC_TQAVCTRL_PREEMPT_ENA);
 
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
+	if (adapter->fpe.mmsv.pmac_enabled)
+		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
@@ -450,6 +584,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)
 	unsigned int new_flags;
 	int err = 0;
 
+	if (adapter->fpe.mmsv.pmac_enabled) {
+		err = igc_enable_empty_addr_recv(adapter);
+		if (err && net_ratelimit())
+			netdev_err(adapter->netdev, "Error adding empty address to MAC filter\n");
+	} else {
+		igc_disable_empty_addr_recv(adapter);
+	}
+
 	new_flags = igc_tsn_new_flags(adapter);
 
 	if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 98ec845a86bf..bb30d15cec76 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,9 +4,59 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define SMD_FRAME_SIZE			60
+
+enum igc_txd_popts_type {
+	SMD_V = 0x01,
+	SMD_R = 0x02,
+};
+
+DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
+
+void igc_fpe_init(struct igc_adapter *adapter);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
 bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter);
 
+static inline bool igc_fpe_is_pmac_enabled(struct igc_adapter *adapter)
+{
+	return static_branch_unlikely(&igc_fpe_enabled) &&
+	       adapter->fpe.mmsv.pmac_enabled;
+}
+
+static inline bool igc_fpe_handle_mpacket(struct igc_adapter *adapter,
+					  union igc_adv_rx_desc *rx_desc,
+					  unsigned int size, void *pktbuf)
+{
+	u32 status_error = le32_to_cpu(rx_desc->wb.upper.status_error);
+	int smd;
+
+	smd = FIELD_GET(IGC_RXDADV_STAT_SMD_TYPE_MASK, status_error);
+	if (smd != IGC_RXD_STAT_SMD_TYPE_V && smd != IGC_RXD_STAT_SMD_TYPE_R)
+		return false;
+
+	if (size == SMD_FRAME_SIZE && mem_is_zero(pktbuf, SMD_FRAME_SIZE)) {
+		struct ethtool_mmsv *mmsv = &adapter->fpe.mmsv;
+		enum ethtool_mmsv_event event;
+
+		if (smd == IGC_RXD_STAT_SMD_TYPE_V)
+			event = ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET;
+		else
+			event = ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET;
+
+		ethtool_mmsv_event_handle(mmsv, event);
+	}
+
+	return true;
+}
+
+static inline bool igc_fpe_transmitted_smd_v(union igc_adv_tx_desc *tx_desc)
+{
+	u32 olinfo_status = le32_to_cpu(tx_desc->read.olinfo_status);
+	u8 smd = FIELD_GET(IGC_TXD_POPTS_SMD_MASK, olinfo_status);
+
+	return smd == SMD_V;
+}
+
 #endif /* _IGC_BASE_H */
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:39 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:39 -0400
Subject: [PATCH iwl-next v10 11/14] igc: add support to set tx-min-frag-size
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-12-faizal.abdul.rahim@linux.intel.com>

Add support for setting tx-min-frag-size via the set_mm callback in igc.
If the requested value is unsupported, round it up to the smallest
supported i226 size (64, 128, 192, 256) and send a netlink message to
inform the user.

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc.h         |  1 +
 drivers/net/ethernet/intel/igc/igc_defines.h |  1 +
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  5 +++
 drivers/net/ethernet/intel/igc/igc_tsn.c     | 38 ++++++++++++++++++--
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 5 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index d970968f3233..d61e2915ccb4 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -42,6 +42,7 @@ void igc_ethtool_set_ops(struct net_device *);
 
 struct igc_fpe_t {
 	struct ethtool_mmsv mmsv;
+	u32 tx_min_frag_size;
 };
 
 enum igc_mac_filter_type {
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 542c7c8802a0..80e0b5ed8b1a 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -583,6 +583,7 @@
 #define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
 #define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
 #define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
+#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000
 
 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
 #define IGC_TXQCTL_STRICT_CYCLE		0x00000002
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index b64d5c6c1d20..529654ccd83f 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1789,6 +1789,11 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_fpe_t *fpe = &adapter->fpe;
 
+	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
+	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");
+
 	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
 		if (cmd->pmac_enabled)
 			static_branch_inc(&igc_fpe_enabled);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 8a1725688381..215bf8e38328 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -6,6 +6,12 @@
 #include "igc_hw.h"
 #include "igc_tsn.h"
 
+#define MIN_MULTPLIER_TX_MIN_FRAG	0
+#define MAX_MULTPLIER_TX_MIN_FRAG	3
+/* Frag size is based on the Section 8.12.2 of the SW User Manual */
+#define TX_MIN_FRAG_SIZE		64
+#define TX_MAX_FRAG_SIZE	(TX_MIN_FRAG_SIZE * (MAX_MULTPLIER_TX_MIN_FRAG + 1))
+
 DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 static int igc_fpe_init_smd_frame(struct igc_ring *ring,
@@ -128,6 +134,7 @@ static const struct ethtool_mmsv_ops igc_mmsv_ops = {
 
 void igc_fpe_init(struct igc_adapter *adapter)
 {
+	adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
 	ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
 }
 
@@ -297,7 +304,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 	tqavctrl = rd32(IGC_TQAVCTRL);
 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
 		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS |
-		      IGC_TQAVCTRL_PREEMPT_ENA);
+		      IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 
 	wr32(IGC_TQAVCTRL, tqavctrl);
 
@@ -343,12 +350,35 @@ static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
 	wr32(IGC_RETX_CTL, retxctl);
 }
 
+static u8 igc_fpe_get_frag_size_mult(const struct igc_fpe_t *fpe)
+{
+	u8 mult = (fpe->tx_min_frag_size / TX_MIN_FRAG_SIZE) - 1;
+
+	return clamp_t(u8, mult, MIN_MULTPLIER_TX_MIN_FRAG,
+		       MAX_MULTPLIER_TX_MIN_FRAG);
+}
+
+u32 igc_fpe_get_supported_frag_size(u32 frag_size)
+{
+	const u32 supported_sizes[] = {64, 128, 192, 256};
+
+	/* Find the smallest supported size that is >= frag_size */
+	for (int i = 0; i < ARRAY_SIZE(supported_sizes); i++) {
+		if (frag_size <= supported_sizes[i])
+			return supported_sizes[i];
+	}
+
+	/* Should not happen */
+	return TX_MAX_FRAG_SIZE;
+}
+
 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
 	struct igc_hw *hw = &adapter->hw;
 	u32 tqavctrl, baset_l, baset_h;
 	u32 sec, nsec, cycle;
 	ktime_t base_time, systim;
+	u32 frag_size_mult;
 	int i;
 
 	wr32(IGC_TSAUXC, 0);
@@ -517,13 +547,15 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 	}
 
 	tqavctrl = rd32(IGC_TQAVCTRL) & ~(IGC_TQAVCTRL_FUTSCDDIS |
-		   IGC_TQAVCTRL_PREEMPT_ENA);
-
+		   IGC_TQAVCTRL_PREEMPT_ENA | IGC_TQAVCTRL_MIN_FRAG_MASK);
 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
 	if (adapter->fpe.mmsv.pmac_enabled)
 		tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;
 
+	frag_size_mult = igc_fpe_get_frag_size_mult(&adapter->fpe);
+	tqavctrl |= FIELD_PREP(IGC_TQAVCTRL_MIN_FRAG_MASK, frag_size_mult);
+
 	adapter->qbv_count++;
 
 	cycle = adapter->cycle_time;
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index bb30d15cec76..58fe5f0773d7 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -14,6 +14,7 @@ enum igc_txd_popts_type {
 DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
 
 void igc_fpe_init(struct igc_adapter *adapter);
+u32 igc_fpe_get_supported_frag_size(u32 frag_size);
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:40 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:40 -0400
Subject: [PATCH iwl-next v10 12/14] igc: block setting preemptible traffic class in taprio
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-13-faizal.abdul.rahim@linux.intel.com>

Since preemptible tc implementation is not ready yet, block it from being
set in taprio. The existing code already blocks it in mqprio.

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 71c377cb7a88..fc945c5b7c70 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6486,6 +6486,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 	if (!validate_schedule(adapter, qopt))
 		return -EINVAL;
 
+	/* preemptible isn't supported yet */
+	if (qopt->mqprio.preemptible_tcs)
+		return -EOPNOTSUPP;
+
 	igc_ptp_read(adapter, &now);
 
 	if (igc_tsn_is_taprio_activated_by_user(adapter) &&
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:41 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:41 -0400
Subject: [PATCH iwl-next v10 13/14] igc: add support to get MAC Merge data via ethtool
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-14-faizal.abdul.rahim@linux.intel.com>

Implement "ethtool --show-mm" callback for IGC.

Tested with command:
$ ethtool --show-mm enp1s0.
  MAC Merge layer state for enp1s0:
  pMAC enabled: on
  TX enabled: on
  TX active: on
  TX minimum fragment size: 64
  RX minimum fragment size: 60
  Verify enabled: on
  Verify time: 128
  Max verify time: 128
  Verification status: SUCCEEDED

Verified that the fields value are retrieved correctly.

Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 14 ++++++++++++++
 drivers/net/ethernet/intel/igc/igc_tsn.h     |  1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 529654ccd83f..fd4b4b332309 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1782,6 +1782,19 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
 	return 0;
 }
 
+static int igc_ethtool_get_mm(struct net_device *netdev,
+			      struct ethtool_mm_state *cmd)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	struct igc_fpe_t *fpe = &adapter->fpe;
+
+	ethtool_mmsv_get_mm(&fpe->mmsv, cmd);
+	cmd->tx_min_frag_size = fpe->tx_min_frag_size;
+	cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE;
+
+	return 0;
+}
+
 static int igc_ethtool_set_mm(struct net_device *netdev,
 			      struct ethtool_mm_cfg *cmd,
 			      struct netlink_ext_ack *extack)
@@ -2101,6 +2114,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
+	.get_mm			= igc_ethtool_get_mm,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h
index 58fe5f0773d7..c2a77229207b 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
@@ -4,6 +4,7 @@
 #ifndef _IGC_TSN_H_
 #define _IGC_TSN_H_
 
+#define IGC_RX_MIN_FRAG_SIZE		60
 #define SMD_FRAME_SIZE			60
 
 enum igc_txd_popts_type {
-- 
2.34.1



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:42 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:42 -0400
Subject: [PATCH iwl-next v10 14/14] igc: add support to get frame preemption statistics via ethtool
In-Reply-To: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
References: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>
Message-ID: <20250318030742.2567080-15-faizal.abdul.rahim@linux.intel.com>

Implemented "ethtool --include-statistics --show-mm" callback for IGC.

Tested preemption scenario to check preemption statistics:
1) Trigger verification handshake on both boards:
    $ sudo ethtool --set-mm enp1s0 pmac-enabled on
    $ sudo ethtool --set-mm enp1s0 tx-enabled on
    $ sudo ethtool --set-mm enp1s0 verify-enabled on
2) Set preemptible or express queue in taprio for tx board:
    $ sudo tc qdisc replace dev enp1s0 parent root handle 100 taprio \
      num_tc 4 map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
      queues 1 at 0 1 at 1 1 at 2 1 at 3 base-time 0 sched-entry S F 100000 \
      fp E E P P
3) Send large size packets on preemptible queue
4) Send small size packets on express queue to preempt packets in
   preemptible queue
5) Show preemption statistics on the receiving board:
   $ ethtool --include-statistics --show-mm enp1s0
     MAC Merge layer state for enp1s0:
     pMAC enabled: on
     TX enabled: on
     TX active: on
     TX minimum fragment size: 64
     RX minimum fragment size: 60
     Verify enabled: on
     Verify time: 128
     Max verify time: 128
     Verification status: SUCCEEDED
     Statistics:
      MACMergeFrameAssErrorCount: 0
      MACMergeFrameSmdErrorCount: 0
      MACMergeFrameAssOkCount: 511
      MACMergeFragCountRx: 764
      MACMergeFragCountTx: 0
      MACMergeHoldCount: 0

Co-developed-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
Co-developed-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.choong at intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean at nxp.com>
Signed-off-by: Faizal Rahim <faizal.abdul.rahim at linux.intel.com>
---
 drivers/net/ethernet/intel/igc/igc_ethtool.c | 40 ++++++++++++++++++++
 drivers/net/ethernet/intel/igc/igc_regs.h    | 16 ++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index fd4b4b332309..324a27a5bef9 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1819,6 +1819,45 @@ static int igc_ethtool_set_mm(struct net_device *netdev,
 	return igc_tsn_offload_apply(adapter);
 }
 
+/**
+ * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
+ * @reg_value: Register value for IGC_PRMEXCPRCNT
+ * Return: The count of frame assembly errors.
+ */
+static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
+{
+	/* Out of order statistics */
+	u32 ooo_frame_cnt, ooo_frag_cnt;
+	u32 miss_frame_frag_cnt;
+
+	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
+	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
+	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT, reg_value);
+
+	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
+}
+
+static u64 igc_ethtool_get_frame_smd_error(u32 reg_value)
+{
+	return FIELD_GET(IGC_PRMEXCPRCNT_OOO_SMDC, reg_value);
+}
+
+static void igc_ethtool_get_mm_stats(struct net_device *dev,
+				     struct ethtool_mm_stats *stats)
+{
+	struct igc_adapter *adapter = netdev_priv(dev);
+	struct igc_hw *hw = &adapter->hw;
+	u32 reg_value;
+
+	reg_value = rd32(IGC_PRMEXCPRCNT);
+
+	stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(reg_value);
+	stats->MACMergeFrameSmdErrorCount = igc_ethtool_get_frame_smd_error(reg_value);
+	stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT);
+	stats->MACMergeFragCountRx = rd32(IGC_PRMEVNTRCNT);
+	stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT);
+}
+
 static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
 					  struct ethtool_link_ksettings *cmd)
 {
@@ -2115,6 +2154,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
 	.self_test		= igc_ethtool_diag_test,
 	.get_mm			= igc_ethtool_get_mm,
+	.get_mm_stats		= igc_ethtool_get_mm_stats,
 	.set_mm			= igc_ethtool_set_mm,
 };
 
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index 12ddc5793651..f343c6bfc6be 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -222,6 +222,22 @@
 
 #define IGC_FTQF(_n)	(0x059E0 + (4 * (_n)))  /* 5-tuple Queue Fltr */
 
+/* Time sync registers - preemption statistics */
+#define IGC_PRMPTDRCNT		0x04284	/* Good RX Preempted Packets */
+#define IGC_PRMEVNTTCNT		0x04298	/* TX Preemption event counter */
+#define IGC_PRMEVNTRCNT		0x0429C	/* RX Preemption event counter */
+
+ /* Preemption Exception Counter */
+ #define IGC_PRMEXCPRCNT				0x42A0
+/* Received out of order packets with SMD-C */
+#define IGC_PRMEXCPRCNT_OOO_SMDC			0x000000FF
+/* Received out of order packets with SMD-C and wrong Frame CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAME_CNT			0x0000FF00
+/* Received out of order packets with SMD-C and wrong Frag CNT */
+#define IGC_PRMEXCPRCNT_OOO_FRAG_CNT			0x00FF0000
+/* Received packets with SMD-S and wrong Frag CNT and Frame CNT */
+#define IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT		0xFF000000
+
 /* Transmit Scheduling Registers */
 #define IGC_TQAVCTRL		0x3570
 #define IGC_TXQCTL(_n)		(0x3344 + 0x4 * (_n))
-- 
2.34.1



From Sunny.Shen at mediatek.com  Mon Mar 17 20:14:07 2025
From: Sunny.Shen at mediatek.com (=?utf-8?B?U3VubnkgU2hlbiAo5rKI5aeN5aeNKQ==?=)
Date: Tue, 18 Mar 2025 03:14:07 +0000
Subject: [PATCH 1/5] dt-bindings: display: mediatek: mdp-rsz: Add rules
 for MT8196
In-Reply-To: <20250224-dreamland-tactile-bdb58daf6060@spud>
References: <20250211025317.399534-1-sunny.shen@mediatek.com>
	 <20250211025317.399534-2-sunny.shen@mediatek.com>
	 <20250211-feed-shed-4b32f146cc54@spud>
	 <029f9fd7ab898769a7ae627b160e1dce446ccc9e.camel@mediatek.com>
	 <20250224-dreamland-tactile-bdb58daf6060@spud>
Message-ID: <76a6fc25a09dfddb55fdaf0a9d7dcf9a6129b00f.camel@mediatek.com>

On Mon, 2025-02-24 at 19:01 +0000, Conor Dooley wrote:
> On Sun, Feb 23, 2025 at 05:49:45PM +0000, Sunny Shen (???) wrote:
> > On Tue, 2025-02-11 at 17:54 +0000, Conor Dooley wrote:
> > > On Tue, Feb 11, 2025 at 10:52:50AM +0800, Sunny Shen wrote:
> > > > Add MDP-RSZ hardware description for MediaTek MT8196 SoC
> 
> > > > +examples:
> > > > +? - |
> > > > +??? soc {
> > > > +??????? #address-cells = <2>;
> > > > +??????? #size-cells = <2>;
> > > > +
> > > > +??????? disp_mdp_rsz0: disp-mdp-rsz0 at 321a0000 {
> > > 
> > > And "disp-mdp-rsz0" isn't anything close to a generic node name.
> > 
> > Will modify "disp-mdp-rsz0 at 321a0000" to "mdp-rsz at 321a0000"
> 
> I don't think that's an improvement. Hint: full words would be a good
> place to start

?
Hi Conor,

About full words,?
Do you mean words like this??
multimedia-display-path-resizer?
or mdp-resizer?

We found that "mdp-rsz" this kind of word is used at
https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/mediatek/mt8183.dtsi

I'm not sure what will be better.
Can you provide more detailed suggestion about this naming?

Thank you


BR,
Sunny Shen


From wei.fang at nxp.com  Mon Mar 17 20:19:51 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 03:19:51 +0000
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <20250317141807.2zobsefxl5vnqdet@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
 <20250317141807.2zobsefxl5vnqdet@skbuf>
Message-ID: <PAXPR04MB8510EECE1FDDA893811EC28B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> > +
> > +static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
> > +					     int type, u64 hash)
> > +{
> > +	if (type == UC) {
> > +		enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
> > +		enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
> > +	} else { /* MC */
> > +		enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
> > +		enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
> > +	}
> > +}
> 
> Please split into separate functions for unicast and for multicast.
> The implementations don't share any code, and the callers are not in
> common code either.
> 

Just copied from enetc_set_mac_ht_flt (), I can split into two separate
functions.

> > +
> > +static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	struct hlist_node *tmp;
> > +
> > +	mutex_lock(&pf->mac_list_lock);
> 
> The mutex_lock() usage here should raise serious questions. This is
> running right before mutex_destroy(). So if there were any concurrent
> attempt to acquire this lock, that concurrent code would have been broken
> any time it would have lost arbitration, by the fact that it would
> attempt to acquire a destroyed mutex.
> 
> But there's no such concurrent thread, because we run after
> destroy_workqueue()
> which flushes those concurrent calls and prevents new ones. So the mutex
> usage here is not necessary.
> 

You are right, but I'm afraid of the Coverity will report an issue, because the
pf->mac_list and pf->num_mfe are protected by the mac_list_lock in other
functions. And enetc4_pf_destroy_mac_list() will be called in other function
in the subsequent patches. I don't think it is unnecessary.

> [ same thing with mutex_init() immediately followed by mutex_lock().
>   It is an incorrect pattern most of the time. ]
> 
> > +
> > +	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
> > +		hlist_del(&entry->node);
> > +		kfree(entry);
> > +	}
> > +
> > +	pf->num_mfe = 0;
> > +
> > +	mutex_unlock(&pf->mac_list_lock);
> > +}
> > +
> > +static bool enetc_mac_filter_type_check(int type, const u8 *addr)
> > +{
> > +	if (type == ENETC_MAC_FILTER_TYPE_UC)
> > +		return !is_multicast_ether_addr(addr);
> > +	else if (type == ENETC_MAC_FILTER_TYPE_MC)
> > +		return is_multicast_ether_addr(addr);
> > +	else
> > +		return true;
> > +}
> > +
> > +static struct enetc_mac_list_entry *
> > +enetc_mac_list_lookup_entry(struct enetc_pf *pf, const unsigned char
> *addr)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +
> > +	hlist_for_each_entry(entry, &pf->mac_list, node)
> > +		if (ether_addr_equal(entry->mac, addr))
> > +			return entry;
> > +
> > +	return NULL;
> > +}
> > +
> > +static void enetc_mac_list_add_entry(struct enetc_pf *pf,
> > +				     struct enetc_mac_list_entry *entry)
> > +{
> > +	hlist_add_head(&entry->node, &pf->mac_list);
> > +}
> > +
> > +static void enetc_mac_list_del_entry(struct enetc_mac_list_entry *entry)
> > +{
> > +	hlist_del(&entry->node);
> > +	kfree(entry);
> > +}
> > +
> > +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16
> si_bit,
> > +					       struct enetc_mac_addr *mac,
> > +					       int mac_cnt)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	int i;
> > +
> > +	for (i = 0; i < mac_cnt; i++) {
> > +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> > +		if (!entry)
> > +			continue;
> > +
> > +		entry->si_bitmap &= ~si_bit;
> > +		if (entry->si_bitmap)
> > +			continue;
> > +
> > +		enetc_mac_list_del_entry(entry);
> > +		pf->num_mfe--;
> > +	}
> > +}
> > +
> > +static bool enetc_mac_list_is_available(struct enetc_pf *pf,
> > +					struct enetc_mac_addr *mac,
> > +					int mac_cnt)
> > +{
> > +	int max_num_mfe = pf->caps.mac_filter_num;
> > +	struct enetc_mac_list_entry *entry;
> > +	int cur_num_mfe = pf->num_mfe;
> > +	int i, new_mac_cnt = 0;
> > +
> > +	if (mac_cnt > max_num_mfe)
> > +		return false;
> > +
> > +	/* Check MAC filter table whether has enough available entries */
> > +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> > +		for (i = 0; i < mac_cnt; i++) {
> > +			if (ether_addr_equal(entry->mac, mac[i].addr))
> > +				break;
> > +		}
> > +
> > +		if (i == mac_cnt)
> > +			new_mac_cnt++;
> > +
> > +		if ((cur_num_mfe + new_mac_cnt) > max_num_mfe)
> > +			return false;
> > +	}
> > +
> > +	return true;
> > +}
> > +
> > +static int enetc4_pf_add_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
> > +					     struct enetc_mac_addr *mac,
> > +					     int mac_cnt)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	struct maft_entry_data data = {0};
> 
> As I've also learned, what you actually want is an empty struct initializer "= {}"
> here:
> https://lore.kernel.org/netdev/20210810091238.GB1343 at shell.armlinux.org.u
> k/
> 

Thanks for the info, I will improve all of this in the patch set.

> > +	struct enetc_si *si = pf->si;
> > +	u16 si_bit = BIT(si_id);
> > +	int i, num_mfe, err = 0;
> > +
> > +	mutex_lock(&pf->mac_list_lock);
> > +
> > +	if (!enetc_mac_list_is_available(pf, mac, mac_cnt)) {
> > +		err = -ENOSPC;
> > +		goto mac_list_unlock;
> > +	}
> > +
> > +	num_mfe = pf->num_mfe;
> > +	/* Update mac_list */
> > +	for (i = 0; i < mac_cnt; i++) {
> > +		entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> > +		if (entry) {
> > +			entry->si_bitmap |= si_bit;
> > +			continue;
> > +		}
> > +
> > +		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> > +		if (unlikely(!entry)) {
> > +			/* Restore MAC list to the state before the update
> > +			 * if an error occurs.
> > +			 */
> > +			enetc_mac_list_del_matched_entries(pf, si_bit,
> > +							   mac, i + 1);
> > +			err = -ENOMEM;
> > +			goto mac_list_unlock;
> > +		}
> > +
> > +		ether_addr_copy(entry->mac, mac[i].addr);
> > +		entry->si_bitmap = si_bit;
> > +		enetc_mac_list_add_entry(pf, entry);
> > +		pf->num_mfe++;
> > +	}
> > +
> > +	/* Clear MAC filter table */
> > +	for (i = 0; i < num_mfe; i++)
> > +		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
> > +
> > +	i = 0;
> > +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> > +		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
> > +		ether_addr_copy(data.keye.mac_addr, entry->mac);
> > +		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
> 
> Don't discard error code.

Okay, I will add error check.
> 
> > +	}
> > +
> > +mac_list_unlock:
> > +	mutex_unlock(&pf->mac_list_lock);
> > +
> > +	return err;
> > +}
> > +
> > +static void enetc4_pf_flush_si_mac_exact_filter(struct enetc_pf *pf, int si_id,
> > +						int mac_type)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	struct maft_entry_data data = {0};
> 
> s/{0}/{}/
> 
> > +	struct enetc_si *si = pf->si;
> > +	u16 si_bit = BIT(si_id);
> > +	struct hlist_node *tmp;
> > +	int i, num_mfe;
> > +
> > +	mutex_lock(&pf->mac_list_lock);
> > +
> > +	num_mfe = pf->num_mfe;
> > +	hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
> > +		if (enetc_mac_filter_type_check(mac_type, entry->mac) &&
> > +		    entry->si_bitmap & si_bit) {
> > +			entry->si_bitmap ^= si_bit;
> > +			if (entry->si_bitmap)
> > +				continue;
> > +
> > +			enetc_mac_list_del_entry(entry);
> > +			pf->num_mfe--;
> > +		}
> > +	}
> > +
> > +	for (i = 0; i < num_mfe; i++)
> > +		ntmp_maft_delete_entry(&si->ntmp.cbdrs, i);
> > +
> > +	i = 0;
> > +	hlist_for_each_entry(entry, &pf->mac_list, node) {
> > +		data.cfge.si_bitmap = cpu_to_le16(entry->si_bitmap);
> > +		ether_addr_copy(data.keye.mac_addr, entry->mac);
> > +		ntmp_maft_add_entry(&si->ntmp.cbdrs, i++, &data);
> 
> Don't discard error code.
> 
> Also, can't you edit MAFT entries in-place over NTMP? Deleting and
> re-adding filters creates small time windows where you might have
> RX packet loss, which is not ideal.

Actually MAFT does not support update action, if a MAC address has
been used by a SI, then another SI also wants to filter the same MAC
address, we only can delete the old entry and then add a new entry.
So there will be Rx packet loss as you said.

Second, the MAFT does not support key match, so we only access the
table through entry id. If we don't want to delete and re-add these
existing entries, then the driver needs to record the entry id of each
entry, this will make adding and removing entries more complicated.

So for your question about Rx packet loss, although it is a very corner
case, the solution I can think of is that we can use temporary MAC hash
filters before deleting MAFT entries and delete them after adding the
MAFT entries. Can you accept this proposal?

> 
> > +	}
> > +
> > +	mutex_unlock(&pf->mac_list_lock);
> > +}
> > +
> > +static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
> > +{
> > +	int max_num_mfe = pf->caps.mac_filter_num;
> > +	struct net_device *ndev = pf->si->ndev;
> > +	struct enetc_mac_addr *mac_tbl;
> > +	struct netdev_hw_addr *ha;
> > +	u8 si_mac[ETH_ALEN];
> > +	int mac_cnt = 0;
> > +	int err;
> > +
> > +	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
> 
> Can't you know ahead of time, based on netdev_uc_count(), whether you
> will have space for exact match filters, and avoid unnecessary
> allocations if not? enetc_mac_list_is_available() seems way too late.
> 

I can add a check before alloc mac_tbl, but enetc_mac_list_is_available()
is still needed, because enetc4_pf_add_si_mac_exact_filter() is a common
function for all Sis, not only for PSI.

> > +	if (!mac_tbl)
> > +		return -ENOMEM;
> > +
> > +	enetc_get_primary_mac_addr(&pf->si->hw, si_mac);
> > +
> > +	netif_addr_lock_bh(ndev);
> > +	if (type & ENETC_MAC_FILTER_TYPE_UC) {
> > +		netdev_for_each_uc_addr(ha, ndev) {
> > +			if (!is_valid_ether_addr(ha->addr) ||
> > +			    ether_addr_equal(ha->addr, si_mac))
> > +				continue;
> > +
> > +			if (mac_cnt >= max_num_mfe)
> > +				goto err_nospace_out;
> > +
> > +			ether_addr_copy(mac_tbl[mac_cnt++].addr, ha->addr);
> > +		}
> > +	}
> > +
> > +	if (type & ENETC_MAC_FILTER_TYPE_MC) {
> 
> Dead code, you never add multicast addresses as exact match filters.
> Please remove.

Okay, I thought that we could support multicast exact filter for later
SoCs in the future with slight modification.

> 
> > +static void enetc4_pf_do_set_rx_mode(struct work_struct *work)
> > +{
> > +	struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
> > +	struct enetc_pf *pf = enetc_si_priv(si);
> > +	struct net_device *ndev = si->ndev;
> > +	struct enetc_hw *hw = &si->hw;
> > +	bool uc_promisc = false;
> > +	bool mc_promisc = false;
> > +	int type = 0;
> > +
> > +	if (ndev->flags & IFF_PROMISC) {
> > +		uc_promisc = true;
> > +		mc_promisc = true;
> > +	} else if (ndev->flags & IFF_ALLMULTI) {
> > +		mc_promisc = true;
> > +		type = ENETC_MAC_FILTER_TYPE_UC;
> > +	} else {
> > +		type = ENETC_MAC_FILTER_TYPE_ALL;
> > +	}
> > +
> > +	enetc4_pf_set_si_mac_promisc(hw, 0, UC, uc_promisc);
> > +	enetc4_pf_set_si_mac_promisc(hw, 0, MC, mc_promisc);
> 
> Why don't you call the function just once and provide both uc_promisc
> and mc_promisc arguments? You would avoid a useless read of the
> ENETC4_PSIPMMR register.
> 
Okay, I will refine the enetc4_pf_set_si_mac_promisc().

> > +static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > +{
> > +	char wq_name[24];
> > +
> > +	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
> > +	snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
> > +	si->workqueue = create_singlethread_workqueue(wq_name);
> > +	if (!si->workqueue)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> 
> Naming scheme is inconsistent here: the function is called "pf" but
> takes "si" as argument. Same for enetc4_pf_do_set_rx_mode() where the
> rx_mode_task is part of the station interface structure.
> 

So change 'pf' to 'psi'?

> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> > index 2b9d0f625f01..3b0cb0d8bf48 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> > @@ -22,6 +22,13 @@ struct enetc_port_caps {
> >  	int num_msix;
> >  	int num_rx_bdr;
> >  	int num_tx_bdr;
> > +	int mac_filter_num;
> > +};
> > +
> > +struct enetc_mac_list_entry {
> > +	u8 mac[ETH_ALEN];
> > +	u16 si_bitmap;
> > +	struct hlist_node node;
> >  };
> >
> >  struct enetc_pf;
> > @@ -57,6 +64,10 @@ struct enetc_pf {
> >
> >  	struct enetc_port_caps caps;
> >  	const struct enetc_pf_ops *ops;
> > +
> > +	struct hlist_head mac_list; /* MAC address filter table */
> 
> One thing I don't understand is why, given this implementation and
> final effect, you even bother to keep the mac_list persistently in
> struct enetc_pf. You have:
> 
> enetc4_pf_do_set_rx_mode()
> -> enetc4_pf_flush_si_mac_exact_filter(ENETC_MAC_FILTER_TYPE_ALL)
>    -> hlist_for_each_entry_safe(&pf->mac_list)
>       -> enetc_mac_list_del_entry()
> 
> which practically deletes all &pf->mac_list elements every time.
> So why even store them persistently in the first place? Why not just
> create an on-stack INIT_HLIST_HEAD() list?

The enetc4_pf_add_si_mac_exact_filter() and
enetc4_pf_add_si_mac_exact_filter() are used for all Sis, but only
PF can access MAFT, and PSI and VSIs may share the same MAFT
entry, so we need to store them in struct enetc_pf. Although we
have not added VFs support yet, for such shared functions, we
should design its implementation from the beginning, rather than
modifying them when we add the VFs support.

> 
> > +	struct mutex mac_list_lock; /* mac_list lock */
> 
> Unsatisfactory explanation. If you try to explain why it is needed, you
> will find it's not needed. That's the intention behind checkpatch
> emitting warnings when locks don't have comments. Not to force you to
> write blabla, but to force you to verbalize, and thus to think whether
> the proposed locking scheme makes sense.
> 
> The si->rx_mode_task is an ordered workqueue, which, as per
> include/linux/workqueue.h, "executes at most one work item at any given
> time in the queued order". In other words, enetc4_pf_do_set_rx_mode()
> doesn't race with itself.
> 
> Combined with the previous comment on enetc4_pf_destroy_mac_list(), I
> suggest that there is no need for this lock.
> 

I thought we could lay some foundation for VF's MAC filter support, so that
it would be easier to support VF later. However, judging from the current patch,
what you said is not unreasonable, we should pay more attention to whether
the current implementation is consistent with the current functions to be
supported. I will remove some parts related to VF, thank you.

> > +	int num_mfe;	/* number of mac address filter table entries */
> >  };
> >
> >  #define phylink_to_enetc_pf(config) \
> > --
> > 2.34.1
> >


From dqfext at gmail.com  Mon Mar 17 20:24:23 2025
From: dqfext at gmail.com (Qingfang Deng)
Date: Tue, 18 Mar 2025 11:24:23 +0800
Subject: [PATCH net v2] net: stmmac: Fix accessing freed irq affinity_hint
Message-ID: <20250318032424.112067-1-dqfext@gmail.com>

The cpumask should not be a local variable, since its pointer is saved
to irq_desc and may be accessed from procfs.
To fix it, use the persistent mask cpumask_of(cpu#).

Cc: stable at vger.kernel.org
Fixes: 8deec94c6040 ("net: stmmac: set IRQ affinity hint for multi MSI vectors")
Signed-off-by: Qingfang Deng <dqfext at gmail.com>
---
v2: use cpumask_of()

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b22417167cac..ec63452187d0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3667,7 +3667,6 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	enum request_irq_err irq_err;
-	cpumask_t cpu_mask;
 	int irq_idx = 0;
 	char *int_name;
 	int ret;
@@ -3796,9 +3795,8 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 			irq_idx = i;
 			goto irq_error;
 		}
-		cpumask_clear(&cpu_mask);
-		cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
-		irq_set_affinity_hint(priv->rx_irq[i], &cpu_mask);
+		irq_set_affinity_hint(priv->rx_irq[i],
+				      cpumask_of(i % num_online_cpus()));
 	}
 
 	/* Request Tx MSI irq */
@@ -3821,9 +3819,8 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 			irq_idx = i;
 			goto irq_error;
 		}
-		cpumask_clear(&cpu_mask);
-		cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
-		irq_set_affinity_hint(priv->tx_irq[i], &cpu_mask);
+		irq_set_affinity_hint(priv->tx_irq[i],
+				      cpumask_of(i % num_online_cpus()));
 	}
 
 	return 0;
-- 
2.43.0



From wei.fang at nxp.com  Mon Mar 17 20:28:56 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 03:28:56 +0000
Subject: [PATCH v4 net-next 05/14] net: enetc: add debugfs interface to
 dump MAC filter
In-Reply-To: <20250317144843.wp432pgodn4vjejf@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250317144843.wp432pgodn4vjejf@skbuf>
Message-ID: <PAXPR04MB8510F67EFC80DFCC7B9F13B588DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:21PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > new file mode 100644
> > index 000000000000..3a660c80344a
> > --- /dev/null
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > @@ -0,0 +1,93 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/* Copyright 2025 NXP */
> > +
> > +#include <linux/device.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/seq_file.h>
> > +
> > +#include "enetc_pf.h"
> > +#include "enetc4_debugfs.h"
> > +
> > +#define is_en(x)	(x) ? "Enabled" : "Disabled"
> 
> str_enabled_disabled()

Oh, good, I wondered if there was a general implementation in
the kernel, but I did not find one due to my limited knowledge.
Thanks!

> 
> > +
> > +static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
> > +{
> > +	struct enetc_si *si = s->private;
> > +	struct enetc_hw *hw = &si->hw;
> > +	u32 hash_h, hash_l;
> > +
> > +	hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
> > +	hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
> > +	seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
> > +		   i, hash_h, hash_l);
> 
> Maybe the ":" separator between the high and low 32 bits is clearer than "x".

I want it to be presented as a full 64-bit entry. If it is in the format
of "%08x:%08x", it may be difficult to understand which is the high
32-bit and which is the low 32-bit.

> 
> > +
> > +	hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
> > +	hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
> > +	seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
> > +		   i, hash_h, hash_l);
> > +}
> > +
> > +static int enetc_mac_filter_show(struct seq_file *s, void *data) {
> > +	struct maft_entry_data maft_data;
> > +	struct enetc_si *si = s->private;
> > +	struct enetc_hw *hw = &si->hw;
> > +	struct maft_keye_data *keye;
> > +	struct enetc_pf *pf;
> > +	int i, err, num_si;
> > +	u32 val;
> > +
> > +	pf = enetc_si_priv(si);
> > +	num_si = pf->caps.num_vsi + 1;
> > +
> > +	val = enetc_port_rd(hw, ENETC4_PSIPMMR);
> > +	for (i = 0; i < num_si; i++) {
> > +		seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
> > +			   i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
> > +		seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
> > +			   i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
> > +	}
> > +
> > +	/* MAC hash filter table */
> > +	for (i = 0; i < num_si; i++)
> > +		enetc_show_si_mac_hash_filter(s, i);
> > +
> > +	if (!pf->num_mfe)
> > +		return 0;
> > +
> > +	/* MAC address filter table */
> > +	seq_puts(s, "Show MAC address filter table\n");
> 
> The word "show" seems superfluous.

Okay, will remove it.

> 
> > +	for (i = 0; i < pf->num_mfe; i++) {
> > +		memset(&maft_data, 0, sizeof(maft_data));
> > +		err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
> > +		if (err)
> > +			return err;
> > +
> > +		keye = &maft_data.keye;
> > +		seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
> > +			   keye->mac_addr, le16_to_cpu(maft_data.cfge.si_bitmap));
> > +	}
> > +
> > +	return 0;
> > +}
> > +DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);


From irogers at google.com  Mon Mar 17 20:31:47 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:47 -0700
Subject: [PATCH v6 10/13] perf build: Remove Makefile.syscalls
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-11-irogers@google.com>

Now a single beauty file is generated and used by all architectures,
remove the per-architecture Makefiles, Kbuild files and previous
generator script.

Note: there was conversation with Charlie Jenkins
<charlie at rivosinc.com> and they'd written an alternate approach to
support multiple architectures:
https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
It would have been better to have helped Charlie fix their series (my
apologies) but they agreed that the approach taken here was likely
best for longer term maintainability:
https://lore.kernel.org/lkml/Z6Jk_UN9i69QGqUj at ghost/

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf                      |  1 -
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |  2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/arc/entry/syscalls/Kbuild     |  2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |  3 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |  4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |  2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |  3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |  6 --
 tools/perf/arch/csky/entry/syscalls/Kbuild    |  2 -
 .../csky/entry/syscalls/Makefile.syscalls     |  3 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |  2 -
 .../entry/syscalls/Makefile.syscalls          |  3 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |  2 -
 .../mips/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |  3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |  6 --
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |  3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |  6 --
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |  2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |  4 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |  2 -
 .../s390/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/sh/entry/syscalls/Kbuild      |  2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |  4 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |  3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/x86/entry/syscalls/Kbuild     |  3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |  6 --
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |  2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |  4 -
 tools/perf/scripts/Makefile.syscalls          | 61 ---------------
 tools/perf/scripts/syscalltbl.sh              | 76 -------------------
 33 files changed, 242 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index f949ec72f3d2..f3cd8de15d1a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -339,7 +339,6 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
 FEATURE_TESTS := all
 endif
 endif
-include $(srctree)/tools/perf/scripts/Makefile.syscalls
 include Makefile.config
 endif
 
diff --git a/tools/perf/arch/alpha/entry/syscalls/Kbuild b/tools/perf/arch/alpha/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls b/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 690168aac34d..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/alpha/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arc/entry/syscalls/Kbuild b/tools/perf/arch/arc/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 391d30ab7a83..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += arc time32 renameat stat64 rlimit
diff --git a/tools/perf/arch/arm/entry/syscalls/Kbuild b/tools/perf/arch/arm/entry/syscalls/Kbuild
deleted file mode 100644
index 9d777540f089..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += oabi
-syscalltbl = $(srctree)/tools/perf/arch/arm/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Kbuild b/tools/perf/arch/arm64/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e7e78c2d1c02..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/arm64/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/csky/entry/syscalls/Kbuild b/tools/perf/arch/csky/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls b/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ea2dd10d0571..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += csky time32 stat64 rlimit
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Kbuild b/tools/perf/arch/loongarch/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls b/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 47d32da2aed8..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 +=
diff --git a/tools/perf/arch/mips/entry/syscalls/Kbuild b/tools/perf/arch/mips/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls b/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9ee914bdfb05..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += n64
-
-syscalltbl = $(srctree)/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
diff --git a/tools/perf/arch/parisc/entry/syscalls/Kbuild b/tools/perf/arch/parisc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ae326fecb83b..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/parisc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Kbuild b/tools/perf/arch/powerpc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e35afbc57c79..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += nospu
-syscall_abis_64 += nospu
-
-syscalltbl = $(srctree)/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/riscv/entry/syscalls/Kbuild b/tools/perf/arch/riscv/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls b/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9668fd1faf60..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += riscv memfd_secret
-syscall_abis_64 += riscv rlimit memfd_secret
diff --git a/tools/perf/arch/s390/entry/syscalls/Kbuild b/tools/perf/arch/s390/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls b/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9762d7abf17c..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/s390/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sh/entry/syscalls/Kbuild b/tools/perf/arch/sh/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 25080390e4ed..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscalltbl = $(srctree)/tools/perf/arch/sh/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sparc/entry/syscalls/Kbuild b/tools/perf/arch/sparc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 212c1800b644..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-syscalltbl = $(srctree)/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/x86/entry/syscalls/Kbuild b/tools/perf/arch/x86/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls b/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index db3d5d6d4e56..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += i386
-syscall_abis_64 +=
-
-syscalltbl = $(srctree)/tools/perf/arch/x86/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Kbuild b/tools/perf/arch/xtensa/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls b/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index d4aa2358460c..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscalltbl = $(srctree)/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
diff --git a/tools/perf/scripts/Makefile.syscalls b/tools/perf/scripts/Makefile.syscalls
deleted file mode 100644
index 8bf55333262e..000000000000
--- a/tools/perf/scripts/Makefile.syscalls
+++ /dev/null
@@ -1,61 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# This Makefile generates headers in
-# tools/perf/arch/$(SRCARCH)/include/generated/asm from the architecture's
-# syscall table. This will either be from the generic syscall table, or from a
-# table that is specific to that architecture.
-
-PHONY := all
-all:
-
-obj := $(OUTPUT)arch/$(SRCARCH)/include/generated/asm
-
-syscall_abis_32  := common,32
-syscall_abis_64  := common,64
-syscalltbl := $(srctree)/tools/scripts/syscall.tbl
-
-# let architectures override $(syscall_abis_%) and $(syscalltbl)
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Makefile.syscalls
-include $(srctree)/tools/build/Build.include
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Kbuild
-
-systbl := $(srctree)/tools/perf/scripts/syscalltbl.sh
-
-syscall-y   := $(addprefix $(obj)/, $(syscall-y))
-
-# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
-unwanted    := $(filter-out $(syscall-y),$(old-headers))
-
-quiet_cmd_remove = REMOVE  $(unwanted)
-      cmd_remove = rm -f $(unwanted)
-
-quiet_cmd_systbl = SYSTBL  $@
-      cmd_systbl = $(CONFIG_SHELL) $(systbl) \
-		   $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \
-		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
-		   $< $@
-
-all: $(syscall-y)
-	$(if $(unwanted),$(call cmd,remove))
-	@:
-
-$(obj)/syscalls_%.h: $(syscalltbl) $(systbl) FORCE
-	$(call if_changed,systbl)
-
-targets := $(syscall-y)
-
-# Create output directory. Skip it if at least one old header exists
-# since we know the output directory already exists.
-ifeq ($(old-headers),)
-$(shell mkdir -p $(obj))
-endif
-
-PHONY += FORCE
-
-FORCE:
-
-existing-targets := $(wildcard $(sort $(targets)))
-
--include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-
-.PHONY: $(PHONY)
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
deleted file mode 100755
index a39b3013b103..000000000000
--- a/tools/perf/scripts/syscalltbl.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Generate a syscall table header.
-#
-# Each line of the syscall table should have the following format:
-#
-# NR ABI NAME [NATIVE] [COMPAT]
-#
-# NR       syscall number
-# ABI      ABI name
-# NAME     syscall name
-# NATIVE   native entry point (optional)
-# COMPAT   compat entry point (optional)
-
-set -e
-
-usage() {
-	echo >&2 "usage: $0 [--abis ABIS] INFILE OUTFILE" >&2
-	echo >&2
-	echo >&2 "  INFILE    input syscall table"
-	echo >&2 "  OUTFILE   output header file"
-	echo >&2
-	echo >&2 "options:"
-	echo >&2 "  --abis ABIS        ABI(s) to handle (By default, all lines are handled)"
-	exit 1
-}
-
-# default unless specified by options
-abis=
-
-while [ $# -gt 0 ]
-do
-	case $1 in
-	--abis)
-		abis=$(echo "($2)" | tr ',' '|')
-		shift 2;;
-	-*)
-		echo "$1: unknown option" >&2
-		usage;;
-	*)
-		break;;
-	esac
-done
-
-if [ $# -ne 2 ]; then
-	usage
-fi
-
-infile="$1"
-outfile="$2"
-
-sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
-
-echo "static const char *const syscall_num_to_name[] = {" > $outfile
-# the params are: nr abi name entry compat
-# use _ for intentionally unused variables according to SC2034
-while read nr _ name _ _; do
-	echo "	[$nr] = \"$name\"," >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
-
-# When sorting by name, add a suffix of 0s upto 20 characters so that system
-# calls that differ with a numerical suffix don't sort before those
-# without. This default behavior of sort differs from that of strcmp used at
-# runtime. Use sed to strip the trailing 0s suffix afterwards.
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
-while read name nr; do
-	echo "	$nr,	/* $name */" >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-rm -f $sorted_table
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:48 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:48 -0700
Subject: [PATCH v6 11/13] perf syscalltbl: Mask off ABI type for MIPS system calls
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-12-irogers@google.com>

Arnd Bergmann described that MIPS system calls don't necessarily start
from 0 as an ABI prefix is applied:
https://lore.kernel.org/lkml/8ed7dfb2-1e4d-4aa4-a04b-0397a89365d1 at app.fastmail.com/
When decoding the "id" (aka system call number) for MIPS ignore values
greater-than 1000.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/syscalltbl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 4e6018e2e0b3..67a8ec10e9e4 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -46,6 +46,14 @@ const char *syscalltbl__name(int e_machine, int id)
 {
 	const struct syscalltbl *table = find_table(e_machine);
 
+	if (e_machine == EM_MIPS && id > 1000) {
+		/*
+		 * MIPS may encode the N32/64/O32 type in the high part of
+		 * syscall number. Mask this off if present. See the values of
+		 * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux.
+		 */
+		id = id % 1000;
+	}
 	if (table && id >= 0 && id < table->num_to_name_len)
 		return table->num_to_name[id];
 	return NULL;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:49 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:49 -0700
Subject: [PATCH v6 12/13] perf trace: Make syscall table stable
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-13-irogers@google.com>

Namhyung fixed the syscall table being reallocated and moving by
reloading the system call pointer after a move:
https://lore.kernel.org/lkml/Z9YHCzINiu4uBQ8B at google.com/
This could be brittle so this patch changes the syscall table to be an
array of pointers of "struct syscall" that don't move. Remove
unnecessary copies and searches with this change.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 87 +++++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1c080d95c1e2..a5f31472980b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -151,7 +151,7 @@ struct trace {
 	struct perf_tool	tool;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
-		struct syscall  *table;
+		struct syscall  **table;
 		/** Size of table. */
 		size_t		table_size;
 		struct {
@@ -2473,24 +2473,41 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
-static void syscall__init(struct syscall *sc, int e_machine, int id)
+static struct syscall *syscall__new(int e_machine, int id)
 {
-	memset(sc, 0, sizeof(*sc));
+	struct syscall *sc = zalloc(sizeof(*sc));
+
+	if (!sc)
+		return NULL;
+
 	sc->e_machine = e_machine;
 	sc->id = id;
+	return sc;
 }
 
-static void syscall__exit(struct syscall *sc)
+static void syscall__delete(struct syscall *sc)
 {
 	if (!sc)
 		return;
 
-	zfree(&sc->arg_fmt);
+	free(sc->arg_fmt);
+	free(sc);
+}
+
+static int syscall__bsearch_cmp(const void *key, const void *entry)
+{
+	const struct syscall *a = key, *b = *((const struct syscall **)entry);
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
 }
 
 static int syscall__cmp(const void *va, const void *vb)
 {
-	const struct syscall *a = va, *b = vb;
+	const struct syscall *a = *((const struct syscall **)va);
+	const struct syscall *b = *((const struct syscall **)vb);
 
 	if (a->e_machine != b->e_machine)
 		return a->e_machine - b->e_machine;
@@ -2504,27 +2521,33 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
 		.e_machine = e_machine,
 		.id = id,
 	};
-	struct syscall *sc, *tmp;
+	struct syscall *sc, **tmp;
 
 	if (trace->syscalls.table) {
-		sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
-			     sizeof(struct syscall), syscall__cmp);
-		if (sc)
-			return sc;
+		struct syscall **sc_entry = bsearch(&key, trace->syscalls.table,
+						    trace->syscalls.table_size,
+						    sizeof(trace->syscalls.table[0]),
+						    syscall__bsearch_cmp);
+
+		if (sc_entry)
+			return *sc_entry;
 	}
 
+	sc = syscall__new(e_machine, id);
+	if (!sc)
+		return NULL;
+
 	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
-			   sizeof(struct syscall));
-	if (!tmp)
+			   sizeof(trace->syscalls.table[0]));
+	if (!tmp) {
+		syscall__delete(sc);
 		return NULL;
+	}
 
 	trace->syscalls.table = tmp;
-	sc = &trace->syscalls.table[trace->syscalls.table_size++];
-	syscall__init(sc, e_machine, id);
-	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	trace->syscalls.table[trace->syscalls.table_size++] = sc;
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(trace->syscalls.table[0]),
 	      syscall__cmp);
-	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
-		     sizeof(struct syscall), syscall__cmp);
 	return sc;
 }
 
@@ -3855,14 +3878,14 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, i
 	return -1;
 }
 
-static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *_sc)
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace,
+							     struct syscall *sc)
 {
-	struct syscall sc = *_sc; /* Copy as trace__syscall_info may invalidate pointer. */
 	struct tep_format_field *field, *candidate_field;
 	/*
 	 * We're only interested in syscalls that have a pointer:
 	 */
-	for (field = sc.args; field; field = field->next) {
+	for (field = sc->args; field; field = field->next) {
 		if (field->flags & TEP_FIELD_IS_POINTER)
 			goto try_to_find_pair;
 	}
@@ -3870,18 +3893,17 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0, num_idx = syscalltbl__num_idx(sc.e_machine); i < num_idx; ++i) {
-		int id = syscalltbl__id_at_idx(sc.e_machine, i);
-		/* calling trace__syscall_info() may invalidate '_sc' */
-		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc->e_machine, i);
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
-		if (pair == NULL || pair->id == sc.id ||
+		if (pair == NULL || pair->id == sc->id ||
 		    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
 			continue;
 
-		for (field = sc.args, candidate_field = pair->args;
+		for (field = sc->args, candidate_field = pair->args;
 		     field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
 			bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
 			     candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3948,7 +3970,8 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 				goto next_candidate;
 		}
 
-		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc.name);
+		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name,
+			 sc->name);
 		return pair_prog;
 	next_candidate:
 		continue;
@@ -4044,11 +4067,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
 		pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
 		if (pair_prog == NULL)
 			continue;
-		/*
-		 * Get syscall info again as find usable entry above might
-		 * modify the syscall table and shuffle it.
-		 */
-		sc = trace__syscall_info(trace, NULL, e_machine, key);
+
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -5316,7 +5335,7 @@ static void trace__exit(struct trace *trace)
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
 		for (size_t i = 0; i < trace->syscalls.table_size; i++)
-			syscall__exit(&trace->syscalls.table[i]);
+			syscall__delete(trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
 	zfree(&trace->perfconfig_events);
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:50 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:50 -0700
Subject: [PATCH v6 13/13] perf trace: Fix BTF memory leak
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-14-irogers@google.com>

Add missing btf__free in trace__exit.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a5f31472980b..d4bbb6a1e817 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -5339,6 +5339,12 @@ static void trace__exit(struct trace *trace)
 		zfree(&trace->syscalls.table);
 	}
 	zfree(&trace->perfconfig_events);
+#ifdef HAVE_LIBBPF_SUPPORT
+	if (trace->btf != NULL) {
+		btf__free(trace->btf);
+		trace->btf = NULL;
+	}
+#endif
 }
 
 #ifdef HAVE_BPF_SKEL
-- 
2.49.0.rc1.451.g8f38331e32-goog



From vulab at iscas.ac.cn  Mon Mar 17 20:07:17 2025
From: vulab at iscas.ac.cn (Wentao Liang)
Date: Tue, 18 Mar 2025 11:07:17 +0800
Subject: [PATCH] pinctrl: at91: Add error handling for pinctrl_utils_add_map_mux()
Message-ID: <20250318030717.781-1-vulab@iscas.ac.cn>

In atmel_pctl_dt_subnode_to_map(), the return value of
pinctrl_utils_add_map_mux() needs to be checked, for the function
will fail to associate group when the group map is full. Add error
handling for pinctrl_utils_add_map_mux() to return immediately and
propagate the error code to caller function when the function fails.

Signed-off-by: Wentao Liang <vulab at iscas.ac.cn>
---
 drivers/pinctrl/pinctrl-at91-pio4.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 8b01d312305a..4dcaebc20d99 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -609,8 +609,10 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
 		if (ret)
 			goto exit;
 
-		pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps,
+		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps,
 					  group, func);
+		if (ret)
+			goto exit;
 
 		if (num_configs) {
 			ret = pinctrl_utils_add_map_configs(pctldev, map,
-- 
2.42.0.windows.2



From faizal.abdul.rahim at linux.intel.com  Mon Mar 17 20:07:28 2025
From: faizal.abdul.rahim at linux.intel.com (Faizal Rahim)
Date: Mon, 17 Mar 2025 23:07:28 -0400
Subject: [PATCH iwl-next v10 00/14] igc: Add support for Frame Preemption feature in IGC
Message-ID: <20250318030742.2567080-1-faizal.abdul.rahim@linux.intel.com>

Introduces support for the FPE feature in the IGC driver.

The patches aligns with the upstream FPE API:
https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.oltean at nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.oltean at nxp.com/

It builds upon earlier work:
https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.1098888-1-vinicius.gomes at intel.com/

The patch series adds the following functionalities to the IGC driver:
a) Configure FPE using `ethtool --set-mm`.
b) Display FPE settings via `ethtool --show-mm`.
c) View FPE statistics using `ethtool --include-statistics --show-mm'.
e) Block setting preemptible tc in taprio since it is not supported yet.
   Existing code already blocks it in mqprio.

Tested:
Enabled CONFIG_PROVE_LOCKING, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_DMA_API_DEBUG, and CONFIG_KASAN
1) selftests
2) netdev down/up cycles
3) suspend/resume cycles
4) fpe verification

No bugs or unusual dmesg logs were observed.
Ran 1), 2) and 3) with and without the patch series, compared dmesg and selftest logs ? no differences found.

Change Log:
v10:
- Add  Vladimir Reviewed-by for patch 2, 3, 6, 8, 10-14
- Add Fu Rong Reviewed-by for patch 3
- Fix compilation error in intel lkp-test, snippet of error:
  "aarch64-linux-ld: drivers/net/ethernet/intel/igc/igc_main.o: in function `igc_clean_tx_irq':
  drivers/net/ethernet/intel/igc/igc_main.c:3157:(.text+0xec44): undefined reference to `ethtool_mmsv_event_handle"
  which randomize .config options (CONFIG_IGC=y, disable CONFIG_ETHTOOL_NETLINK).
  config -> https://download.01.org/0day-ci/archive/20250314/202503141646.6yybVfAe-lkp at intel.com/config
  Fix at patch 2 and 10 by adding "depends on ETHTOOL_NETLINK" in stmmac and igc Kconfig.

v8 -> v9:
- Add Vladimir and Fu Rong Reviewed-by, patch 1
- Remove Faizal Co-developed-by for patch 2
- Remove code that reset verification state when link is down, patch 2 (Vladimir)
- Refactor TX buffer and RX buffer magic constants with macro for each field. patch 5-9 (Vladimir)
- s/Rest adapter/Adapter reset/ in commit description, patch 10 (Vladimir)
- Replace igc_fpe_is_verify_or_response() and igc_fpe_lp_event_status() with igc_fpe_handle_mpacket(), patch 10 (Vladimir)
- Comments on separate lines from code in igc_fpe_get_supported_frag_size(), patch 11 (Vladimir)
- Remove mistakenly added igc_fpe_get_supported_frag_size(), patch 10 (Vladimir)
- Remove max limit 256 of tx-min-size changes, patch 11 (Vladimir)

v7 -> v8:
- Reject SMD-V and SMD-R if the payload contains non-zero values (Vladimir, Chwee Lin)
- Move resetting verification state when link is down to a new patch 3/11 (Vladimir)
- Move frag_size related handling outside of spin_lock_irq_save(), patch 1/11 (Vladimir)
- Renamed IGC_PRMEXPRCNT to IGC_PRMEXCPRCNT, to align with i226 SW User Manual, patch 11/11 (Chwee Lin)
- Use IGC_PRMEXPRCNT_OOO_SMDC for frame smd errors instead of frame assembly errors, 11/11 (Chwee Lin)

v6 -> v7:
- Squash the cpu param to the prev line (Przemek Kitszel)
- Use igc_ prefix for fpe_t (Przemek Kitszel)
- Move new ops to different line in igc_ethtool_ops (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): rx -> Rx (Przemek Kitszel)
- Documentation for igc_enable_empty_addr_recv (): s/IGC/the driver/ (Przemek Kitszel)
- Change preferred style of init, from { }, to {} (Przemek Kitszel)
- Remove inclusion of umbrella header <linux/kernel.h> in igc_tsn.c (Przemek Kitszel)
- End enum with "," in igc_txd_popts_type (Przemek Kitszel)
- Remove unnecessary braces in igc_fpe_is_verify_or_response() (Przemek Kitszel)

v5 -> v6:
- Added Tested-by: Furong Xu for patch 1/9 (Vladimir, Furong Xu)
- Updated logic in ethtool_mmsv_link_state_handle() (Vladimir, Furong Xu)
- Swap sequence of function call in stmmac_set_mm() (Furong Xu)
- Log an error if igc_enable_empty_addr_recv() fails (Vladimir)
- Move the patch ".. Block setting preemptible traffic .." before ".. Add support to get MAC Merge data .." (Vladimir)
- Move mmsv function kernel-doc from .h to .c file (Vladimir)

v4 -> v5:
- Remove "igc: Add support for preemptible traffic class in taprio" patch (Vladimir)
- Add a new patch "igc: Block setting preemptible traffic classes in taprio" (Vladimir)
- Add kernel-doc for mmsv api (Vladimir)
- olininfo_status to use host byte order (Simon)
- status_error should host byte type (Simon)
- Some code was misplaced in the wrong patch (Vladimir)
- Mix of tabs and spaces in patch description (Vladimir)
- Created igc_is_pmac_enabled() to reduce code repetition (Vladimir)

v3 -> v4:
- Fix compilation warnings introduced by this patch series

v2 -> v3:
- Implement configure_tx() mmsv callback (Vladimir)
- Use static_branch_inc() and static_branch_dec() (Vladimir)
- Add adapter->fpe.mmsv.pmac_enabled as extra check (Vladimir)
- Remove unnecessary error check in igc_fpe_init_tx_descriptor() (Vladimir)
- Additional places to use FIELD_PREP() instead of manual bit manipulation (Vladimir)
- IGC_TXD_POPTS_SMD_V and IGC_TXD_POPTS_SMD_R type change to enum (Vladimir)
- Remove unnecessary netif_running() check in igc_fpe_xmit_frame (Vladimir)
- Rate limit print in igc_fpe_send_mpacket (Vladimir)

v1 -> v2:
- Extract the stmmac verification logic into a common library (Vladimir)
- igc to use common library for verification (Vladimir)
- Fix syntax for kernel-doc to use "Return:" (Vladimir)
- Use FIELD_GET instead of manual bit masking (Vladimir)
- Don't assign 0 to statistics counter in igc_ethtool_get_mm_stats() (Vladimir)
- Use pmac-enabled as a condition to allow MAC address value 0 (Vladimir)
- Define macro register value in increasing value order (Vladimir)
- Fix tx-min-frag-size handling for igc (Vladimir)
- Handle link state changes with verification in igc (Vladimir)
- Add static key for fast path code (Vladimir)
- rx_min_frag_size get from constant (Vladimir)

v1: https://patchwork.kernel.org/project/netdevbpf/cover/20241216064720.931522-1-faizal.abdul.rahim at linux.intel.com/
v2: https://patchwork.kernel.org/project/netdevbpf/cover/20250205100524.1138523-1-faizal.abdul.rahim at linux.intel.com/
v3: https://patchwork.kernel.org/project/netdevbpf/cover/20250207165649.2245320-1-faizal.abdul.rahim at linux.intel.com/
v4: https://patchwork.kernel.org/project/netdevbpf/cover/20250210070207.2615418-1-faizal.abdul.rahim at linux.intel.com/
v5: https://patchwork.kernel.org/project/netdevbpf/cover/20250220025349.3007793-1-faizal.abdul.rahim at linux.intel.com/
v6: https://patchwork.kernel.org/project/netdevbpf/cover/20250227140158.2129988-1-faizal.abdul.rahim at linux.intel.com/
v7: https://patchwork.kernel.org/project/netdevbpf/cover/20250303102658.3580232-1-faizal.abdul.rahim at linux.intel.com/
v8: https://patchwork.kernel.org/project/netdevbpf/cover/20250305130026.642219-1-faizal.abdul.rahim at linux.intel.com/
v9: https://patchwork.kernel.org/project/netdevbpf/cover/20250309104648.3895551-1-faizal.abdul.rahim at linux.intel.com/

Faizal Rahim (13):
  net: stmmac: move frag_size handling out of spin_lock
  net: ethtool: mm: reset verification status when link is down
  igc: rename xdp_get_tx_ring() for non-xdp usage
  igc: rename I225_RXPBSIZE_DEFAULT and I225_TXPBSIZE_DEFAULT
  igc: use FIELD_PREP and GENMASK for existing TX packet buffer size
  igc: optimize TX packet buffer utilization for TSN mode
  igc: use FIELD_PREP and GENMASK for existing RX packet buffer size
  igc: set the RX packet buffer size for TSN mode
  igc: add support for frame preemption verification
  igc: add support to set tx-min-frag-size
  igc: block setting preemptible traffic class in taprio
  igc: add support to get MAC Merge data via ethtool
  igc: add support to get frame preemption statistics via ethtool

Vladimir Oltean (1):
  net: ethtool: mm: extract stmmac verification logic into common
    library

 drivers/net/ethernet/intel/Kconfig            |   1 +
 drivers/net/ethernet/intel/igc/igc.h          |  15 +-
 drivers/net/ethernet/intel/igc/igc_base.h     |   1 +
 drivers/net/ethernet/intel/igc/igc_defines.h  |  55 +++-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |  80 +++++
 drivers/net/ethernet/intel/igc/igc_main.c     |  69 ++++-
 drivers/net/ethernet/intel/igc/igc_regs.h     |  16 +
 drivers/net/ethernet/intel/igc/igc_tsn.c      | 207 ++++++++++++-
 drivers/net/ethernet/intel/igc/igc_tsn.h      |  52 ++++
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |   1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  16 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  41 +--
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.c  | 174 +++--------
 .../net/ethernet/stmicro/stmmac/stmmac_fpe.h  |   5 -
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   8 +-
 include/linux/ethtool.h                       |  73 +++++
 net/ethtool/mm.c                              | 279 +++++++++++++++++-
 17 files changed, 872 insertions(+), 221 deletions(-)

--
2.34.1



From irogers at google.com  Mon Mar 17 20:31:37 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:37 -0700
Subject: [PATCH v6 00/13] perf: Support multiple system call tables in the build
Message-ID: <20250318033150.119174-1-irogers@google.com>

This work builds on the clean up of system call tables and removal of
libaudit by Charlie Jenkins <charlie at rivosinc.com>.

The system call table in perf trace is used to map system call numbers
to names and vice versa. Prior to these changes, a single table
matching the perf binary's build was present. The table would be
incorrect if tracing say a 32-bit binary from a 64-bit version of
perf, the names and numbers wouldn't match.

Change the build so that a single system call file is built and the
potentially multiple tables are identifiable from the ELF machine type
of the process being examined. To determine the ELF machine type, the
executable's maps are searched and the associated DSOs ELF headers are
read. When this fails and when live, /proc/pid/exe's ELF header is
read. Fallback to using the perf's binary type when unknown.

Remove some runtime types used by the system call tables and make
equivalents generated at build time.

v6: Incorporate Namhyung's fixes:
    https://lore.kernel.org/lkml/Z9PCjQ8PhOadVGQ8 at google.com/
    https://lore.kernel.org/lkml/Z9YHCzINiu4uBQ8B at google.com/
    Which highlighted an issue with syscall pointers becoming
    stale. Add a patch 12 to make the syscall table a table of
    pointers that don't move so that struct syscalls don't move. Add a
    patch 13 fixing a BTF memory leak.

v5: Add byte swap to dso__e_machine and fix comment as suggested by
    Namhyung.

v4: Add reading the e_machine from the thread's maps dsos, only read
    from /proc/pid/exe on failure and when live as requested by
    Namhyung. Add patches to add dso comments and remove unused
    dso_data variables that are unused without libunwind.

v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
    Bergmann <arnd at arndb.de> on additional optional column and MIPS
    system call numbering. Rebase past Namhyung's global system call
    statistics and add comments that they don't yet support an
    e_machine other than EM_HOST.

v2: Change the 1 element cache for the last table as suggested by
    Howard Chu, add Howard's reviewed-by tags.
    Add a comment and apology to Charlie for not doing better in
    guiding:
    https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
    After discussion on v1 and he agreed this patch series would be
    the better direction.

Ian Rogers (13):
  perf dso: Move libunwind dso_data variables into ifdef
  perf dso: kernel-doc for enum dso_binary_type
  perf syscalltbl: Remove syscall_table.h
  perf trace: Reorganize syscalls
  perf syscalltbl: Remove struct syscalltbl
  perf dso: Add support for reading the e_machine type for a dso
  perf thread: Add support for reading the e_machine type for a thread
  perf trace beauty: Add syscalltbl.sh generating all system call tables
  perf syscalltbl: Use lookup table containing multiple architectures
  perf build: Remove Makefile.syscalls
  perf syscalltbl: Mask off ABI type for MIPS system calls
  perf trace: Make syscall table stable
  perf trace: Fix BTF memory leak

 tools/perf/Makefile.perf                      |  10 +-
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/alpha/include/syscall_table.h |   2 -
 tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
 tools/perf/arch/arc/include/syscall_table.h   |   2 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
 tools/perf/arch/arm/include/syscall_table.h   |   2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
 tools/perf/arch/arm64/include/syscall_table.h |   8 -
 tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
 .../csky/entry/syscalls/Makefile.syscalls     |   3 -
 tools/perf/arch/csky/include/syscall_table.h  |   2 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
 .../entry/syscalls/Makefile.syscalls          |   3 -
 .../arch/loongarch/include/syscall_table.h    |   2 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
 .../mips/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/mips/include/syscall_table.h  |   2 -
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
 .../perf/arch/parisc/include/syscall_table.h  |   8 -
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
 .../perf/arch/powerpc/include/syscall_table.h |   8 -
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
 tools/perf/arch/riscv/include/syscall_table.h |   8 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
 .../s390/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/s390/include/syscall_table.h  |   2 -
 tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
 tools/perf/arch/sh/include/syscall_table.h    |   2 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/sparc/include/syscall_table.h |   8 -
 tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
 tools/perf/arch/x86/include/syscall_table.h   |   8 -
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
 .../perf/arch/xtensa/include/syscall_table.h  |   2 -
 tools/perf/builtin-trace.c                    | 333 ++++++++++++------
 tools/perf/scripts/Makefile.syscalls          |  61 ----
 tools/perf/scripts/syscalltbl.sh              |  86 -----
 tools/perf/trace/beauty/syscalltbl.sh         | 274 ++++++++++++++
 tools/perf/util/dso.c                         |  89 +++++
 tools/perf/util/dso.h                         |  62 ++++
 tools/perf/util/symbol-elf.c                  |  27 --
 tools/perf/util/syscalltbl.c                  | 148 ++++----
 tools/perf/util/syscalltbl.h                  |  22 +-
 tools/perf/util/thread.c                      |  80 +++++
 tools/perf/util/thread.h                      |  14 +-
 57 files changed, 835 insertions(+), 541 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:38 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:38 -0700
Subject: [PATCH v6 01/13] perf dso: Move libunwind dso_data variables into ifdef
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-2-irogers@google.com>

The variables elf_base_addr, debug_frame_offset, eh_frame_hdr_addr and
eh_frame_hdr_offset are only accessed in unwind-libunwind-local.c
which is conditionally built on having libunwind support. Make the
variables conditional on libunwind support too.

Reviewed-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 84d5aac666aa..14e4ac21a1d3 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -155,10 +155,12 @@ struct dso_data {
 	int		 status;
 	u32		 status_seen;
 	u64		 file_size;
+#ifdef HAVE_LIBUNWIND_SUPPORT
 	u64		 elf_base_addr;
 	u64		 debug_frame_offset;
 	u64		 eh_frame_hdr_addr;
 	u64		 eh_frame_hdr_offset;
+#endif
 };
 
 struct dso_bpf_prog {
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:39 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:39 -0700
Subject: [PATCH v6 02/13] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-3-irogers@google.com>

There are many and non-obvious meanings to the dso_binary_type enum
values. Add kernel-doc to speed interpretting their meanings.

Acked-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 57 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 14e4ac21a1d3..fcb2898e0f49 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -20,31 +20,88 @@ struct perf_env;
 #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
 #define DSO__NAME_KCORE		"[kernel.kcore]"
 
+/**
+ * enum dso_binary_type - The kind of DSO generally associated with a memory
+ *                        region (struct map).
+ */
 enum dso_binary_type {
+	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
 	DSO_BINARY_TYPE__KALLSYMS = 0,
+	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
 	DSO_BINARY_TYPE__GUEST_KALLSYMS,
+	/** @DSO_BINARY_TYPE__VMLINUX: Path to kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__VMLINUX,
+	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to guest kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__GUEST_VMLINUX,
+	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
 	DSO_BINARY_TYPE__JAVA_JIT,
+	/**
+	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
+	 * in the .gnu_debuglink ELF section of the dso.
+	 */
 	DSO_BINARY_TYPE__DEBUGLINK,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
+	 * the buildid cache with an elf filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
+	 * located in the buildid cache with a debug filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
+	 * with .debug suffix.
+	 */
 	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
 	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
+	 * file in /usr/lib/debug/lib rather than the expected
+	 * /usr/lib/debug/usr/lib.
+	 */
 	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
+	 * in /usr/lib/debug/.build-id/.
+	 */
 	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__GNU_DEBUGDATA: MiniDebuginfo where a compressed
+	 * ELF file is placed in a .gnu_debugdata section.
+	 */
 	DSO_BINARY_TYPE__GNU_DEBUGDATA,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
 	DSO_BINARY_TYPE__KCORE,
+	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
 	DSO_BINARY_TYPE__GUEST_KCORE,
+	/**
+	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
+	 * package debug info.
+	 */
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
 	DSO_BINARY_TYPE__BPF_PROG_INFO,
+	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
 	DSO_BINARY_TYPE__BPF_IMAGE,
+	/**
+	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
+	 * instructions or optimized kprobes or ftrace trampolines.
+	 */
 	DSO_BINARY_TYPE__OOL,
+	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:40 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:40 -0700
Subject: [PATCH v6 03/13] perf syscalltbl: Remove syscall_table.h
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-4-irogers@google.com>

The definition of "static const char *const syscalltbl[] = {" is done
in a generated syscalls_32.h or syscalls_64.h that is architecture
dependent. In order to include the appropriate file a syscall_table.h
is found via the perf include path and it includes the syscalls_32.h
or syscalls_64.h as appropriate.

To support having multiple syscall tables, one for 32-bit and one for
64-bit, or for different architectures, an include path cannot be
used. Remove syscall_table.h because of this and inline what it does
into syscalltbl.c.

For architectures without a syscall_table.h this will cause a failure
to include either syscalls_32.h or syscalls_64.h rather than a failure
to include syscall_table.h. For architectures that only included one
or other, the behavior matches BITS_PER_LONG as previously done on
architectures supporting both syscalls_32.h and syscalls_64.h.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/arch/alpha/include/syscall_table.h     | 2 --
 tools/perf/arch/arc/include/syscall_table.h       | 2 --
 tools/perf/arch/arm/include/syscall_table.h       | 2 --
 tools/perf/arch/arm64/include/syscall_table.h     | 8 --------
 tools/perf/arch/csky/include/syscall_table.h      | 2 --
 tools/perf/arch/loongarch/include/syscall_table.h | 2 --
 tools/perf/arch/mips/include/syscall_table.h      | 2 --
 tools/perf/arch/parisc/include/syscall_table.h    | 8 --------
 tools/perf/arch/powerpc/include/syscall_table.h   | 8 --------
 tools/perf/arch/riscv/include/syscall_table.h     | 8 --------
 tools/perf/arch/s390/include/syscall_table.h      | 2 --
 tools/perf/arch/sh/include/syscall_table.h        | 2 --
 tools/perf/arch/sparc/include/syscall_table.h     | 8 --------
 tools/perf/arch/x86/include/syscall_table.h       | 8 --------
 tools/perf/arch/xtensa/include/syscall_table.h    | 2 --
 tools/perf/util/syscalltbl.c                      | 8 +++++++-
 16 files changed, 7 insertions(+), 67 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h

diff --git a/tools/perf/arch/alpha/include/syscall_table.h b/tools/perf/arch/alpha/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/alpha/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/arc/include/syscall_table.h b/tools/perf/arch/arc/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arc/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm/include/syscall_table.h b/tools/perf/arch/arm/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arm/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm64/include/syscall_table.h b/tools/perf/arch/arm64/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/arm64/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/csky/include/syscall_table.h b/tools/perf/arch/csky/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/csky/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/loongarch/include/syscall_table.h b/tools/perf/arch/loongarch/include/syscall_table.h
deleted file mode 100644
index 9d0646d3455c..000000000000
--- a/tools/perf/arch/loongarch/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscall_table_64.h>
diff --git a/tools/perf/arch/mips/include/syscall_table.h b/tools/perf/arch/mips/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/mips/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/parisc/include/syscall_table.h b/tools/perf/arch/parisc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/parisc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/powerpc/include/syscall_table.h b/tools/perf/arch/powerpc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/powerpc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/riscv/include/syscall_table.h b/tools/perf/arch/riscv/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/riscv/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/s390/include/syscall_table.h b/tools/perf/arch/s390/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/s390/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/sh/include/syscall_table.h b/tools/perf/arch/sh/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/sh/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/sparc/include/syscall_table.h b/tools/perf/arch/sparc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/sparc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/x86/include/syscall_table.h b/tools/perf/arch/x86/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/x86/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/xtensa/include/syscall_table.h b/tools/perf/arch/xtensa/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/xtensa/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 928aca4cd6e9..2f76241494c8 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -7,13 +7,19 @@
 
 #include "syscalltbl.h"
 #include <stdlib.h>
+#include <asm/bitsperlong.h>
 #include <linux/compiler.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
 #include "string2.h"
 
-#include <syscall_table.h>
+#if __BITS_PER_LONG == 64
+  #include <asm/syscalls_64.h>
+#else
+  #include <asm/syscalls_32.h>
+#endif
+
 const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
 static const char *const *syscalltbl_native = syscalltbl;
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:41 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:41 -0700
Subject: [PATCH v6 04/13] perf trace: Reorganize syscalls
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-5-irogers@google.com>

Identify struct syscall information in the syscalls table by a machine
type and syscall number, not just system call number. Having the
machine type means that 32-bit system calls can be differentiated from
64-bit ones on a machine capable of both. Having a table for all
machine types and all system call numbers would be too large, so
maintain a sorted array of system calls as they are encountered.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c | 197 +++++++++++++++++++++++++------------
 1 file changed, 132 insertions(+), 65 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 092c5f6404ba..bdfd3d5128b7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -66,6 +66,7 @@
 #include "syscalltbl.h"
 #include "../perf.h"
 #include "trace_augment.h"
+#include "dwarf-regs.h"
 
 #include <errno.h>
 #include <inttypes.h>
@@ -86,6 +87,7 @@
 
 #include <linux/ctype.h>
 #include <perf/mmap.h>
+#include <tools/libc_compat.h>
 
 #ifdef HAVE_LIBTRACEEVENT
 #include <event-parse.h>
@@ -149,7 +151,10 @@ struct trace {
 	struct perf_tool	tool;
 	struct syscalltbl	*sctbl;
 	struct {
+		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
+		/** Size of table. */
+		size_t		table_size;
 		struct {
 			struct evsel *sys_enter,
 				*sys_exit,
@@ -1454,22 +1459,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
 	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
 }
 
-/*
- * is_exit: is this "exit" or "exit_group"?
- * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
- * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
- * nonexistent: Just a hole in the syscall table, syscall id not allocated
+/**
+ * struct syscall
  */
 struct syscall {
+	/** @e_machine: The ELF machine associated with the entry. */
+	int e_machine;
+	/** @id: id value from the tracepoint, the system call number. */
+	int id;
 	struct tep_event    *tp_format;
 	int		    nr_args;
+	/**
+	 * @args_size: sum of the sizes of the syscall arguments, anything
+	 * after that is augmented stuff: pathname for openat, etc.
+	 */
+
 	int		    args_size;
 	struct {
 		struct bpf_program *sys_enter,
 				   *sys_exit;
 	}		    bpf_prog;
+	/** @is_exit: is this "exit" or "exit_group"? */
 	bool		    is_exit;
+	/**
+	 * @is_open: is this "open" or "openat"? To associate the fd returned in
+	 * sys_exit with the pathname in sys_enter.
+	 */
 	bool		    is_open;
+	/**
+	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
+	 * syscall id not allocated.
+	 */
 	bool		    nonexistent;
 	bool		    use_btf;
 	struct tep_format_field *args;
@@ -2107,22 +2127,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
 	return 0;
 }
 
-static int trace__read_syscall_info(struct trace *trace, int id)
+static int syscall__read_info(struct syscall *sc, struct trace *trace)
 {
 	char tp_name[128];
-	struct syscall *sc;
-	const char *name = syscalltbl__name(trace->sctbl, id);
+	const char *name;
 	int err;
 
-	if (trace->syscalls.table == NULL) {
-		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
-		if (trace->syscalls.table == NULL)
-			return -ENOMEM;
-	}
-	sc = trace->syscalls.table + id;
 	if (sc->nonexistent)
 		return -EEXIST;
 
+	if (sc->name) {
+		/* Info already read. */
+		return 0;
+	}
+
+	name = syscalltbl__name(trace->sctbl, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2145,15 +2164,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 	 */
 	if (IS_ERR(sc->tp_format)) {
 		sc->nonexistent = true;
-		return PTR_ERR(sc->tp_format);
+		err = PTR_ERR(sc->tp_format);
+		sc->tp_format = NULL;
+		return err;
 	}
 
 	/*
 	 * The tracepoint format contains __syscall_nr field, so it's one more
 	 * than the actual number of syscall arguments.
 	 */
-	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
-					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
+	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
 		return -ENOMEM;
 
 	sc->args = sc->tp_format->format.fields;
@@ -2442,13 +2462,69 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
+static void syscall__init(struct syscall *sc, int e_machine, int id)
+{
+	memset(sc, 0, sizeof(*sc));
+	sc->e_machine = e_machine;
+	sc->id = id;
+}
+
+static void syscall__exit(struct syscall *sc)
+{
+	if (!sc)
+		return;
+
+	zfree(&sc->arg_fmt);
+}
+
+static int syscall__cmp(const void *va, const void *vb)
+{
+	const struct syscall *a = va, *b = vb;
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
+}
+
+static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
+{
+	struct syscall key = {
+		.e_machine = e_machine,
+		.id = id,
+	};
+	struct syscall *sc, *tmp;
+
+	if (trace->syscalls.table) {
+		sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+			     sizeof(struct syscall), syscall__cmp);
+		if (sc)
+			return sc;
+	}
+
+	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
+			   sizeof(struct syscall));
+	if (!tmp)
+		return NULL;
+
+	trace->syscalls.table = tmp;
+	sc = &trace->syscalls.table[trace->syscalls.table_size++];
+	syscall__init(sc, e_machine, id);
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	      syscall__cmp);
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	return sc;
+}
+
 typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
 				  union perf_event *event,
 				  struct perf_sample *sample);
 
-static struct syscall *trace__syscall_info(struct trace *trace,
-					   struct evsel *evsel, int id)
+static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
+					   int e_machine, int id)
 {
+	struct syscall *sc;
 	int err = 0;
 
 	if (id < 0) {
@@ -2473,28 +2549,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
 
 	err = -EINVAL;
 
-	if (id > trace->sctbl->syscalls.max_id) {
-		goto out_cant_read;
-	}
-
-	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
-	    (err = trace__read_syscall_info(trace, id)) != 0)
-		goto out_cant_read;
-
-	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
-		goto out_cant_read;
+	sc = trace__find_syscall(trace, e_machine, id);
+	if (sc)
+		err = syscall__read_info(sc, trace);
 
-	return &trace->syscalls.table[id];
-
-out_cant_read:
-	if (verbose > 0) {
+	if (err && verbose > 0) {
 		char sbuf[STRERR_BUFSIZE];
-		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
-		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
-			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
+
+		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
+			str_error_r(-err, sbuf, sizeof(sbuf)));
+		if (sc && sc->name)
+			fprintf(trace->output, "(%s)", sc->name);
 		fputs(" information\n", trace->output);
 	}
-	return NULL;
+	return err ? NULL : sc;
 }
 
 struct syscall_stats {
@@ -2643,14 +2711,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
 	return NULL;
 }
 
-static void syscall__exit(struct syscall *sc)
-{
-	if (!sc)
-		return;
-
-	zfree(&sc->arg_fmt);
-}
-
 static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 			    union perf_event *event __maybe_unused,
 			    struct perf_sample *sample)
@@ -2662,7 +2722,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -2736,7 +2796,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
 	int augmented_args_size;
@@ -2811,7 +2871,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -3164,7 +3224,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		struct syscall *sc = trace__syscall_info(trace, evsel, id);
+		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -3673,7 +3733,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 
 static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 
 	if (sc == NULL)
 		return;
@@ -3684,20 +3744,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 
 static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3779,13 +3839,14 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigne
 	return -1;
 }
 
-static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *_sc)
 {
+	struct syscall sc = *_sc; /* Copy as trace__syscall_info may invalidate pointer. */
 	struct tep_format_field *field, *candidate_field;
 	/*
 	 * We're only interested in syscalls that have a pointer:
 	 */
-	for (field = sc->args; field; field = field->next) {
+	for (field = sc.args; field; field = field->next) {
 		if (field->flags & TEP_FIELD_IS_POINTER)
 			goto try_to_find_pair;
 	}
@@ -3795,15 +3856,16 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 try_to_find_pair:
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, id);
+		/* calling trace__syscall_info() may invalidate '_sc' */
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
-		if (pair == NULL || pair == sc ||
+		if (pair == NULL || pair->id == sc.id ||
 		    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
 			continue;
 
-		for (field = sc->args, candidate_field = pair->args;
+		for (field = sc.args, candidate_field = pair->args;
 		     field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
 			bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
 			     candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3870,7 +3932,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 				goto next_candidate;
 		}
 
-		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name);
+		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc.name);
 		return pair_prog;
 	next_candidate:
 		continue;
@@ -3945,7 +4007,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 */
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, key);
+		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -3966,7 +4028,11 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 		pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
 		if (pair_prog == NULL)
 			continue;
-
+		/*
+		 * Get syscall info again as find usable entry above might
+		 * modify the syscall table and shuffle it.
+		 */
+		sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -4761,7 +4827,10 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = &trace->syscalls.table[entry->syscall];
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			if (!sc)
+				continue;
+
 			printed += fprintf(fp, "   %-15s", sc->name);
 			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
 					   n, stats->nr_failures, entry->msecs, min, avg);
@@ -5218,12 +5287,10 @@ static int trace__config(const char *var, const char *value, void *arg)
 
 static void trace__exit(struct trace *trace)
 {
-	int i;
-
 	strlist__delete(trace->ev_qualifier);
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
-		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
+		for (size_t i = 0; i < trace->syscalls.table_size; i++)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:42 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:42 -0700
Subject: [PATCH v6 05/13] perf syscalltbl: Remove struct syscalltbl
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-6-irogers@google.com>

The syscalltbl held entries of system call name and number pairs,
generated from a native syscalltbl at start up. As there are gaps in
the system call number there is a notion of index into the
table. Going forward we want the system call table to be identifiable
by a machine type, for example, i386 vs x86-64. Change the interface
to the syscalltbl so (1) a (currently unused machine type of EM_HOST)
is passed (2) the index to syscall number and system call name mapping
is computed at build time.

Two tables are used for this, an array of system call number to name,
an array of system call numbers sorted by the system call name. The
sorted array doesn't store strings in part to save memory and
relocations. The index notion is carried forward and is an index into
the sorted array of system call numbers, the data structures are
opaque (held only in syscalltbl.c), and so the number of indices for a
machine type is exposed as a new API.

The arrays are computed in the syscalltbl.sh script and so no start-up
time computation and storage is necessary.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c       | 106 +++++++++++++++++------------
 tools/perf/scripts/syscalltbl.sh |  36 ++++------
 tools/perf/util/syscalltbl.c     | 113 ++++++++++---------------------
 tools/perf/util/syscalltbl.h     |  22 ++----
 4 files changed, 117 insertions(+), 160 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index bdfd3d5128b7..3017291242cf 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -149,7 +149,6 @@ enum summary_mode {
 
 struct trace {
 	struct perf_tool	tool;
-	struct syscalltbl	*sctbl;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
@@ -188,6 +187,14 @@ struct trace {
 		pid_t		*entries;
 		struct bpf_map  *map;
 	}			filter_pids;
+	/*
+	 * TODO: The map is from an ID (aka system call number) to struct
+	 * syscall_stats. If there is >1 e_machine, such as i386 and x86-64
+	 * processes, then the stats here will gather wrong the statistics for
+	 * the non EM_HOST system calls. A fix would be to add the e_machine
+	 * into the key, but this would make the code inconsistent with the
+	 * per-thread version.
+	 */
 	struct hashmap		*syscall_stats;
 	double			duration_filter;
 	double			runtime_ms;
@@ -2141,7 +2148,7 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace)
 		return 0;
 	}
 
-	name = syscalltbl__name(trace->sctbl, sc->id);
+	name = syscalltbl__name(sc->e_machine, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2241,10 +2248,14 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 
 	strlist__for_each_entry(pos, trace->ev_qualifier) {
 		const char *sc = pos->s;
-		int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
+		/*
+		 * TODO: Assume more than the validation/warnings are all for
+		 * the same binary type as perf.
+		 */
+		int id = syscalltbl__id(EM_HOST, sc), match_next = -1;
 
 		if (id < 0) {
-			id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_first(EM_HOST, sc, &match_next);
 			if (id >= 0)
 				goto matches;
 
@@ -2264,7 +2275,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 			continue;
 
 		while (1) {
-			id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_next(EM_HOST, sc, &match_next);
 			if (id < 0)
 				break;
 			if (nr_allocated == nr_used) {
@@ -2722,6 +2733,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -2796,6 +2808,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
@@ -2871,6 +2884,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -3224,6 +3238,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+		/* TODO: get e_machine from thread. */
 		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
@@ -3731,9 +3746,9 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 	return trace->skel->progs.syscall_unaugmented;
 }
 
-static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
+static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 
 	if (sc == NULL)
 		return;
@@ -3742,22 +3757,22 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 	sc->bpf_prog.sys_exit  = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit  : NULL,  "exit");
 }
 
-static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
+static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3854,8 +3869,8 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int id = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc.e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc.e_machine, i);
 		/* calling trace__syscall_info() may invalidate '_sc' */
 		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
 		struct bpf_program *pair_prog;
@@ -3941,7 +3956,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 }
 
-static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
 {
 	int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
 	int map_exit_fd  = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
@@ -3949,27 +3964,27 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	int err = 0;
 	unsigned int beauty_array[6];
 
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int prog_fd, key = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int prog_fd, key = syscalltbl__id_at_idx(e_machine, i);
 
 		if (!trace__syscall_enabled(trace, key))
 			continue;
 
-		trace__init_syscall_bpf_progs(trace, key);
+		trace__init_syscall_bpf_progs(trace, e_machine, key);
 
 		// It'll get at least the "!raw_syscalls:unaugmented"
-		prog_fd = trace__bpf_prog_sys_enter_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_enter_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
-		prog_fd = trace__bpf_prog_sys_exit_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_exit_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
 
 		/* use beauty_map to tell BPF how many bytes to collect, set beauty_map's value here */
 		memset(beauty_array, 0, sizeof(beauty_array));
-		err = trace__bpf_sys_enter_beauty_map(trace, key, (unsigned int *)beauty_array);
+		err = trace__bpf_sys_enter_beauty_map(trace, e_machine, key, (unsigned int *)beauty_array);
 		if (err)
 			continue;
 		err = bpf_map_update_elem(beauty_map_fd, &key, beauty_array, BPF_ANY);
@@ -4005,9 +4020,9 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 * first and second arg (this one on the raw_syscalls:sys_exit prog
 	 * array tail call, then that one will be used.
 	 */
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int key = syscalltbl__id_at_idx(e_machine, i);
+		struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4032,7 +4047,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 		 * Get syscall info again as find usable entry above might
 		 * modify the syscall table and shuffle it.
 		 */
-		sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+		sc = trace__syscall_info(trace, NULL, e_machine, key);
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -4457,8 +4472,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 		goto out_error_mem;
 
 #ifdef HAVE_BPF_SKEL
-	if (trace->skel && trace->skel->progs.sys_enter)
-		trace__init_syscalls_bpf_prog_array_maps(trace);
+	if (trace->skel && trace->skel->progs.sys_enter) {
+		/*
+		 * TODO: Initialize for all host binary machine types, not just
+		 * those matching the perf binary.
+		 */
+		trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
+	}
 #endif
 
 	if (trace->ev_qualifier_ids.nr > 0) {
@@ -4483,7 +4503,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	 *  So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is
 	 *  not in use.
 	 */
-	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close"));
+	/* TODO: support for more than just perf binary machine type close. */
+	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(EM_HOST, "close"));
 
 	err = trace__expand_filters(trace, &evsel);
 	if (err)
@@ -4796,7 +4817,7 @@ static struct syscall_entry *syscall__sort_stats(struct hashmap *syscall_stats)
 	return entry;
 }
 
-static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
+static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
 				  struct hashmap *syscall_stats)
 {
 	size_t printed = 0;
@@ -4827,7 +4848,7 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, e_machine, entry->syscall);
 			if (!sc)
 				continue;
 
@@ -4854,14 +4875,14 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 }
 
 static size_t thread__dump_stats(struct thread_trace *ttrace,
-				 struct trace *trace, FILE *fp)
+				 struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, ttrace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, ttrace->syscall_stats);
 }
 
-static size_t system__dump_stats(struct trace *trace, FILE *fp)
+static size_t system__dump_stats(struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, trace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, trace->syscall_stats);
 }
 
 static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
@@ -4887,7 +4908,8 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += thread__dump_stats(ttrace, trace, fp);
+	/* TODO: get e_machine from thread. */
+	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -4948,7 +4970,8 @@ static size_t trace__fprintf_total_summary(struct trace *trace, FILE *fp)
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += system__dump_stats(trace, fp);
+	/* TODO: get all system e_machines. */
+	printed += system__dump_stats(trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -5140,8 +5163,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
 			*sep = '\0';
 
 		list = 0;
-		if (syscalltbl__id(trace->sctbl, s) >= 0 ||
-		    syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
+		/* TODO: support for more than just perf binary machine type syscalls. */
+		if (syscalltbl__id(EM_HOST, s) >= 0 ||
+		    syscalltbl__strglobmatch_first(EM_HOST, s, &idx) >= 0) {
 			list = 1;
 			goto do_concat;
 		}
@@ -5294,7 +5318,6 @@ static void trace__exit(struct trace *trace)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-	syscalltbl__delete(trace->sctbl);
 	zfree(&trace->perfconfig_events);
 }
 
@@ -5443,9 +5466,8 @@ int cmd_trace(int argc, const char **argv)
 	sigaction(SIGCHLD, &sigchld_act, NULL);
 
 	trace.evlist = evlist__new();
-	trace.sctbl = syscalltbl__new();
 
-	if (trace.evlist == NULL || trace.sctbl == NULL) {
+	if (trace.evlist == NULL) {
 		pr_err("Not enough memory to run!\n");
 		err = -ENOMEM;
 		goto out;
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
index 1ce0d5aa8b50..a39b3013b103 100755
--- a/tools/perf/scripts/syscalltbl.sh
+++ b/tools/perf/scripts/syscalltbl.sh
@@ -50,37 +50,27 @@ fi
 infile="$1"
 outfile="$2"
 
-nxt=0
-
-syscall_macro() {
-    nr="$1"
-    name="$2"
-
-    echo "	[$nr] = \"$name\","
-}
-
-emit() {
-    nr="$1"
-    entry="$2"
-
-    syscall_macro "$nr" "$entry"
-}
-
-echo "static const char *const syscalltbl[] = {" > $outfile
-
 sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
 grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
 
-max_nr=0
+echo "static const char *const syscall_num_to_name[] = {" > $outfile
 # the params are: nr abi name entry compat
 # use _ for intentionally unused variables according to SC2034
 while read nr _ name _ _; do
-    emit "$nr" "$name" >> $outfile
-    max_nr=$nr
+	echo "	[$nr] = \"$name\"," >> $outfile
 done < $sorted_table
+echo "};" >> $outfile
 
-rm -f $sorted_table
+echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
 
+# When sorting by name, add a suffix of 0s upto 20 characters so that system
+# calls that differ with a numerical suffix don't sort before those
+# without. This default behavior of sort differs from that of strcmp used at
+# runtime. Use sed to strip the trailing 0s suffix afterwards.
+grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
+while read name nr; do
+	echo "	$nr,	/* $name */" >> $outfile
+done < $sorted_table
 echo "};" >> $outfile
 
-echo "#define SYSCALLTBL_MAX_ID ${max_nr}" >> $outfile
+rm -f $sorted_table
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 2f76241494c8..760ac4d0869f 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <asm/bitsperlong.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
@@ -20,112 +21,66 @@
   #include <asm/syscalls_32.h>
 #endif
 
-const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
-static const char *const *syscalltbl_native = syscalltbl;
+const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+{
+	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
+		return syscall_num_to_name[id];
+	return NULL;
+}
 
-struct syscall {
-	int id;
+struct syscall_cmp_key {
 	const char *name;
+	const char *const *tbl;
 };
 
 static int syscallcmpname(const void *vkey, const void *ventry)
 {
-	const char *key = vkey;
-	const struct syscall *entry = ventry;
+	const struct syscall_cmp_key *key = vkey;
+	const uint16_t *entry = ventry;
 
-	return strcmp(key, entry->name);
+	return strcmp(key->name, key->tbl[*entry]);
 }
 
-static int syscallcmp(const void *va, const void *vb)
+int syscalltbl__id(int e_machine __maybe_unused, const char *name)
 {
-	const struct syscall *a = va, *b = vb;
-
-	return strcmp(a->name, b->name);
+	struct syscall_cmp_key key = {
+		.name = name,
+		.tbl = syscall_num_to_name,
+	};
+	const int *id = bsearch(&key, syscall_sorted_names,
+				ARRAY_SIZE(syscall_sorted_names),
+				sizeof(syscall_sorted_names[0]),
+				syscallcmpname);
+
+	return id ? *id : -1;
 }
 
-static int syscalltbl__init_native(struct syscalltbl *tbl)
+int syscalltbl__num_idx(int e_machine __maybe_unused)
 {
-	int nr_entries = 0, i, j;
-	struct syscall *entries;
-
-	for (i = 0; i <= syscalltbl_native_max_id; ++i)
-		if (syscalltbl_native[i])
-			++nr_entries;
-
-	entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
-	if (tbl->syscalls.entries == NULL)
-		return -1;
-
-	for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
-		if (syscalltbl_native[i]) {
-			entries[j].name = syscalltbl_native[i];
-			entries[j].id = i;
-			++j;
-		}
-	}
-
-	qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
-	tbl->syscalls.nr_entries = nr_entries;
-	tbl->syscalls.max_id	 = syscalltbl_native_max_id;
-	return 0;
+	return ARRAY_SIZE(syscall_sorted_names);
 }
 
-struct syscalltbl *syscalltbl__new(void)
+int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
 {
-	struct syscalltbl *tbl = malloc(sizeof(*tbl));
-	if (tbl) {
-		if (syscalltbl__init_native(tbl)) {
-			free(tbl);
-			return NULL;
-		}
-	}
-	return tbl;
-}
-
-void syscalltbl__delete(struct syscalltbl *tbl)
-{
-	zfree(&tbl->syscalls.entries);
-	free(tbl);
-}
-
-const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
-{
-	return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
-}
-
-int syscalltbl__id(struct syscalltbl *tbl, const char *name)
-{
-	struct syscall *sc = bsearch(name, tbl->syscalls.entries,
-				     tbl->syscalls.nr_entries, sizeof(*sc),
-				     syscallcmpname);
-
-	return sc ? sc->id : -1;
-}
-
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx)
-{
-	struct syscall *syscalls = tbl->syscalls.entries;
-
-	return idx < tbl->syscalls.nr_entries ? syscalls[idx].id : -1;
+	return syscall_sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
 {
-	int i;
-	struct syscall *syscalls = tbl->syscalls.entries;
+	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
+		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
 
-	for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
-		if (strglobmatch(syscalls[i].name, syscall_glob)) {
+		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscalls[i].id;
+			return syscall_sorted_names[i];
 		}
 	}
 
 	return -1;
 }
 
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx)
 {
 	*idx = -1;
-	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+	return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx);
 }
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index 362411a6d849..2bb628eff367 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -2,22 +2,12 @@
 #ifndef __PERF_SYSCALLTBL_H
 #define __PERF_SYSCALLTBL_H
 
-struct syscalltbl {
-	struct {
-		int max_id;
-		int nr_entries;
-		void *entries;
-	} syscalls;
-};
+const char *syscalltbl__name(int e_machine, int id);
+int syscalltbl__id(int e_machine, const char *name);
+int syscalltbl__num_idx(int e_machine);
+int syscalltbl__id_at_idx(int e_machine, int idx);
 
-struct syscalltbl *syscalltbl__new(void);
-void syscalltbl__delete(struct syscalltbl *tbl);
-
-const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
-int syscalltbl__id(struct syscalltbl *tbl, const char *name);
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx);
-
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx);
 
 #endif /* __PERF_SYSCALLTBL_H */
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:43 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:43 -0700
Subject: [PATCH v6 06/13] perf dso: Add support for reading the e_machine type
 for a dso
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-7-irogers@google.com>

For ELF file dsos read the e_machine from the ELF header. For kernel
types assume the e_machine matches the perf tool. In other cases
return EM_NONE.

When reading from the ELF header use DSO__SWAP that may need
dso->needs_swap initializing. Factor out dso__swap_init to allow this.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.c        | 89 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/dso.h        |  3 ++
 tools/perf/util/symbol-elf.c | 27 -----------
 3 files changed, 92 insertions(+), 27 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 7576e8e24838..45da63d7315b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1173,6 +1173,68 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 	return data_read_write_offset(dso, machine, offset, data, size, true);
 }
 
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
+{
+	uint16_t e_machine = EM_NONE;
+	int fd;
+
+	switch (dso__binary_type(dso)) {
+	case DSO_BINARY_TYPE__KALLSYMS:
+	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
+	case DSO_BINARY_TYPE__VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_KMODULE:
+	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
+	case DSO_BINARY_TYPE__KCORE:
+	case DSO_BINARY_TYPE__GUEST_KCORE:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
+	case DSO_BINARY_TYPE__BPF_IMAGE:
+	case DSO_BINARY_TYPE__OOL:
+	case DSO_BINARY_TYPE__JAVA_JIT:
+		return EM_HOST;
+	case DSO_BINARY_TYPE__DEBUGLINK:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
+	case DSO_BINARY_TYPE__GNU_DEBUGDATA:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
+	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
+	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+		break;
+	case DSO_BINARY_TYPE__NOT_FOUND:
+	default:
+		return EM_NONE;
+	}
+
+	pthread_mutex_lock(&dso__data_open_lock);
+
+	/*
+	 * dso__data(dso)->fd might be closed if other thread opened another
+	 * file (dso) due to open file limit (RLIMIT_NOFILE).
+	 */
+	try_to_open_dso(dso, machine);
+	fd = dso__data(dso)->fd;
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
+			unsigned char eidata;
+
+			if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
+				dso__swap_init(dso, eidata);
+		}
+		if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
+		    pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
+			e_machine = DSO__SWAP(dso, uint16_t, e_machine);
+	}
+	pthread_mutex_unlock(&dso__data_open_lock);
+	return e_machine;
+}
+
 /**
  * dso__data_read_addr - Read data from dso address
  * @dso: dso object
@@ -1528,6 +1590,33 @@ void dso__put(struct dso *dso)
 		RC_CHK_PUT(dso);
 }
 
+int dso__swap_init(struct dso *dso, unsigned char eidata)
+{
+	static unsigned int const endian = 1;
+
+	dso__set_needs_swap(dso, DSO_SWAP__NO);
+
+	switch (eidata) {
+	case ELFDATA2LSB:
+		/* We are big endian, DSO is little endian. */
+		if (*(unsigned char const *)&endian != 1)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	case ELFDATA2MSB:
+		/* We are little endian, DSO is big endian. */
+		if (*(unsigned char const *)&endian != 0)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	default:
+		pr_err("unrecognized DSO data encoding %d\n", eidata);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid)
 {
 	RC_CHK_ACCESS(dso)->bid = *bid;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index fcb2898e0f49..0459d4e41b14 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -735,6 +735,8 @@ bool dso__sorted_by_name(const struct dso *dso);
 void dso__set_sorted_by_name(struct dso *dso);
 void dso__sort_by_name(struct dso *dso);
 
+int dso__swap_init(struct dso *dso, unsigned char eidata);
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid);
 bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
 void dso__read_running_kernel_build_id(struct dso *dso,
@@ -823,6 +825,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
 off_t dso__data_size(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 			      u64 offset, u8 *data, ssize_t size);
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
 			    struct machine *machine, u64 addr,
 			    u8 *data, ssize_t size);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 3fa92697c457..fbf6d0f73af9 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1174,33 +1174,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
 
 #endif
 
-static int dso__swap_init(struct dso *dso, unsigned char eidata)
-{
-	static unsigned int const endian = 1;
-
-	dso__set_needs_swap(dso, DSO_SWAP__NO);
-
-	switch (eidata) {
-	case ELFDATA2LSB:
-		/* We are big endian, DSO is little endian. */
-		if (*(unsigned char const *)&endian != 1)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	case ELFDATA2MSB:
-		/* We are little endian, DSO is big endian. */
-		if (*(unsigned char const *)&endian != 0)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	default:
-		pr_err("unrecognized DSO data encoding %d\n", eidata);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 bool symsrc__possibly_runtime(struct symsrc *ss)
 {
 	return ss->dynsym || ss->opdsec;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:44 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:44 -0700
Subject: [PATCH v6 07/13] perf thread: Add support for reading the e_machine
 type for a thread
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-8-irogers@google.com>

First try to read the e_machine from the dsos associated with the
thread's maps. If live use the executable from /proc/pid/exe and read
the e_machine from the ELF header. On failure use EM_HOST. Change
builtin-trace syscall functions to pass e_machine from the thread
rather than EM_HOST, so that in later patches when syscalltbl can use
the e_machine the system calls are specific to the architecture.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 43 ++++++++++----------
 tools/perf/util/thread.c   | 80 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/thread.h   | 14 ++++++-
 3 files changed, 115 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 3017291242cf..1c080d95c1e2 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2731,16 +2731,16 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int printed = 0;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	int augmented_args_size = 0;
+	int augmented_args_size = 0, e_machine;
 	void *augmented_args = NULL;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -2808,17 +2808,18 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	char msg[1024];
 	void *args, *augmented_args = NULL;
-	int augmented_args_size;
+	int augmented_args_size, e_machine;
 	size_t printed = 0;
 
-	if (sc == NULL)
-		return -1;
 
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		return -1;
 	ttrace = thread__trace(thread, trace);
 	/*
 	 * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
@@ -2883,15 +2884,15 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	bool duration_calculated = false;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
-	int alignment = trace->args_alignment;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	int alignment = trace->args_alignment, e_machine;
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -3238,8 +3239,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		/* TODO: get e_machine from thread. */
-		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+		int e_machine = thread ? thread__e_machine(thread, trace->host) : EM_HOST;
+		struct syscall *sc = trace__syscall_info(trace, evsel, e_machine, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -4889,6 +4890,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 {
 	size_t printed = 0;
 	struct thread_trace *ttrace = thread__priv(thread);
+	int e_machine = thread__e_machine(thread, trace->host);
 	double ratio;
 
 	if (ttrace == NULL)
@@ -4908,8 +4910,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	/* TODO: get e_machine from thread. */
-	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
+	printed += thread__dump_stats(ttrace, trace, e_machine, fp);
 
 	return printed;
 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0ffdd52d86d7..89585f53c1d5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <elf.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,6 +18,7 @@
 #include "symbol.h"
 #include "unwind.h"
 #include "callchain.h"
+#include "dwarf-regs.h"
 
 #include <api/fs/fs.h>
 
@@ -51,6 +54,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		thread__set_ppid(thread, -1);
 		thread__set_cpu(thread, -1);
 		thread__set_guest_cpu(thread, -1);
+		thread__set_e_machine(thread, EM_NONE);
 		thread__set_lbr_stitch_enable(thread, false);
 		INIT_LIST_HEAD(thread__namespaces_list(thread));
 		INIT_LIST_HEAD(thread__comm_list(thread));
@@ -423,6 +427,82 @@ void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
 	}
 }
 
+static uint16_t read_proc_e_machine_for_pid(pid_t pid)
+{
+	char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */];
+	int fd;
+	uint16_t e_machine = EM_NONE;
+
+	snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+	fd = open(path, O_RDONLY);
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
+			e_machine = EM_NONE;
+		close(fd);
+	}
+	return e_machine;
+}
+
+static int thread__e_machine_callback(struct map *map, void *machine)
+{
+	struct dso *dso = map__dso(map);
+
+	_Static_assert(0 == EM_NONE, "Unexpected EM_NONE");
+	if (!dso)
+		return EM_NONE;
+
+	return dso__e_machine(dso, machine);
+}
+
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine)
+{
+	pid_t tid, pid;
+	uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine;
+
+	if (e_machine != EM_NONE)
+		return e_machine;
+
+	tid = thread__tid(thread);
+	pid = thread__pid(thread);
+	if (pid != tid) {
+		struct thread *parent = machine__findnew_thread(machine, pid, pid);
+
+		if (parent) {
+			e_machine = thread__e_machine(parent, machine);
+			thread__set_e_machine(thread, e_machine);
+			return e_machine;
+		}
+		/* Something went wrong, fallback. */
+	}
+	/* Reading on the PID thread. First try to find from the maps. */
+	e_machine = maps__for_each_map(thread__maps(thread),
+				       thread__e_machine_callback,
+				       machine);
+	if (e_machine == EM_NONE) {
+		/* Maps failed, perhaps we're live with map events disabled. */
+		bool is_live = machine->machines == NULL;
+
+		if (!is_live) {
+			/* Check if the session has a data file. */
+			struct perf_session *session = container_of(machine->machines,
+								    struct perf_session,
+								    machines);
+
+			is_live = !!session->data;
+		}
+		/* Read from /proc/pid/exe if live. */
+		if (is_live)
+			e_machine = read_proc_e_machine_for_pid(pid);
+	}
+	if (e_machine != EM_NONE)
+		thread__set_e_machine(thread, e_machine);
+	else
+		e_machine = EM_HOST;
+	return e_machine;
+}
+
 struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
 {
 	if (thread__pid(thread) == thread__tid(thread))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 6cbf6eb2812e..cd574a896418 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -60,7 +60,11 @@ DECLARE_RC_STRUCT(thread) {
 	struct srccode_state	srccode_state;
 	bool			filter;
 	int			filter_entry_depth;
-
+	/**
+	 * @e_machine: The ELF EM_* associated with the thread. EM_NONE if not
+	 * computed.
+	 */
+	uint16_t		e_machine;
 	/* LBR call stack stitch */
 	bool			lbr_stitch_enable;
 	struct lbr_stitch	*lbr_stitch;
@@ -302,6 +306,14 @@ static inline void thread__set_filter_entry_depth(struct thread *thread, int dep
 	RC_CHK_ACCESS(thread)->filter_entry_depth = depth;
 }
 
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine);
+
+static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine)
+{
+	RC_CHK_ACCESS(thread)->e_machine = e_machine;
+}
+
+
 static inline bool thread__lbr_stitch_enable(const struct thread *thread)
 {
 	return RC_CHK_ACCESS(thread)->lbr_stitch_enable;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:45 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:45 -0700
Subject: [PATCH v6 08/13] perf trace beauty: Add syscalltbl.sh generating all
 system call tables
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-9-irogers@google.com>

Rather than generating individual syscall header files generate a
single trace/beauty/generated/syscalltbl.c. In a syscalltbls array
have references to each architectures tables along with the
corresponding e_machine. When the 32-bit or 64-bit table is ambiguous,
match the perf binary's type. For ARM32 don't use the arm64 32-bit
table which is smaller. EM_NONE is present for is no machine matches.

Conditionally compile the tables, only having the appropriate 32 and
64-bit table. If ALL_SYSCALLTBL is defined all tables can be
compiled.

Add comment for noreturn column suggested by Arnd Bergmann:
https://lore.kernel.org/lkml/d47c35dd-9c52-48e7-a00d-135572f11fbb at app.fastmail.com/
and added in commit 9142be9e6443 ("x86/syscall: Mark exit[_group]
syscall handlers __noreturn").

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf              |   9 +
 tools/perf/trace/beauty/syscalltbl.sh | 274 ++++++++++++++++++++++++++
 2 files changed, 283 insertions(+)
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d0b50ccc9d7b..f949ec72f3d2 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -559,6 +559,14 @@ beauty_ioctl_outdir := $(beauty_outdir)/ioctl
 # Create output directory if not already present
 $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
 
+syscall_array := $(beauty_outdir)/syscalltbl.c
+syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh
+syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \
+	$(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl)
+
+$(syscall_array): $(syscall_tbl) $(syscall_tbl_data)
+	$(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@
+
 fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c
 fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh
 
@@ -878,6 +886,7 @@ build-dir   = $(or $(__build-dir),.)
 
 prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders \
 	arm64-sysreg-defs \
+	$(syscall_array) \
 	$(fs_at_flags_array) \
 	$(clone_flags_array) \
 	$(drm_ioctl_array) \
diff --git a/tools/perf/trace/beauty/syscalltbl.sh b/tools/perf/trace/beauty/syscalltbl.sh
new file mode 100755
index 000000000000..1199618dc178
--- /dev/null
+++ b/tools/perf/trace/beauty/syscalltbl.sh
@@ -0,0 +1,274 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate all syscall tables.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT [noreturn]]
+#
+# NR       syscall number
+# ABI      ABI name
+# NAME     syscall name
+# NATIVE   native entry point (optional)
+# COMPAT   compat entry point (optional)
+# noreturn system call doesn't return (optional)
+set -e
+
+usage() {
+       cat >&2 <<EOF
+usage: $0 <TOOLS DIRECTORY> <OUTFILE>
+
+  <TOOLS DIRECTORY>    path to kernel tools directory
+  <OUTFILE>            output header file
+EOF
+       exit 1
+}
+
+if [ $# -ne 2 ]; then
+       usage
+fi
+tools_dir=$1
+outfile=$2
+
+build_tables() {
+	infile="$1"
+	outfile="$2"
+	abis=$(echo "($3)" | tr ',' '|')
+	e_machine="$4"
+
+	if [ ! -f "$infile" ]
+	then
+		echo "Missing file $infile"
+		exit 1
+	fi
+	sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > "$sorted_table"
+
+	echo "static const char *const syscall_num_to_name_${e_machine}[] = {" >> "$outfile"
+	# the params are: nr abi name entry compat
+	# use _ for intentionally unused variables according to SC2034
+	while read -r nr _ name _ _; do
+		echo "	[$nr] = \"$name\"," >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	echo "static const uint16_t syscall_sorted_names_${e_machine}[] = {" >> "$outfile"
+
+	# When sorting by name, add a suffix of 0s upto 20 characters so that
+	# system calls that differ with a numerical suffix don't sort before
+	# those without. This default behavior of sort differs from that of
+	# strcmp used at runtime. Use sed to strip the trailing 0s suffix
+	# afterwards.
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > "$sorted_table"
+	while read -r name nr; do
+		echo "	$nr,	/* $name */" >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	rm -f "$sorted_table"
+}
+
+rm -f "$outfile"
+cat >> "$outfile" <<EOF
+#include <elf.h>
+#include <stdint.h>
+#include <asm/bitsperlong.h>
+#include <linux/kernel.h>
+
+struct syscalltbl {
+       const char *const *num_to_name;
+       const uint16_t *sorted_names;
+       uint16_t e_machine;
+       uint16_t num_to_name_len;
+       uint16_t sorted_names_len;
+};
+
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_tables "$tools_dir/perf/arch/alpha/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_ALPHA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_tables "$tools_dir/perf/arch/arm/entry/syscalls/syscall.tbl" "$outfile" common,32,oabi EM_ARM
+build_tables "$tools_dir/perf/arch/arm64/entry/syscalls/syscall_64.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_AARCH64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,csky,time32,stat64,rlimit EM_CSKY
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_tables "$tools_dir/perf/arch/mips/entry/syscalls/syscall_n64.tbl" "$outfile" common,64,n64 EM_MIPS
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_PARISC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_PARISC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,32,nospu EM_PPC
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,64,nospu EM_PPC64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,riscv,memfd_secret EM_RISCV
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64,riscv,rlimit,memfd_secret EM_RISCV
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_tables "$tools_dir/perf/arch/s390/entry/syscalls/syscall.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_S390
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_tables "$tools_dir/perf/arch/sh/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SH
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SPARC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_SPARC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_32.tbl" "$outfile" common,32,i386 EM_386
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_64.tbl" "$outfile" common,64 EM_X86_64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_tables "$tools_dir/perf/arch/xtensa/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_XTENSA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32 EM_NONE
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64 EM_NONE
+echo "#endif //__BITS_PER_LONG != 64" >> "$outfile"
+
+build_outer_table() {
+       e_machine=$1
+       outfile="$2"
+       cat >> "$outfile" <<EOF
+       {
+	      .num_to_name = syscall_num_to_name_$e_machine,
+	      .sorted_names = syscall_sorted_names_$e_machine,
+	      .e_machine = $e_machine,
+	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_$e_machine),
+	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_$e_machine),
+       },
+EOF
+}
+
+cat >> "$outfile" <<EOF
+static const struct syscalltbl syscalltbls[] = {
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_outer_table EM_ALPHA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_outer_table EM_ARM "$outfile"
+build_outer_table EM_AARCH64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_outer_table EM_CSKY "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_outer_table EM_MIPS "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+EOF
+build_outer_table EM_PARISC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_outer_table EM_PPC "$outfile"
+build_outer_table EM_PPC64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+EOF
+build_outer_table EM_RISCV "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_outer_table EM_S390 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_outer_table EM_SH "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+EOF
+build_outer_table EM_SPARC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_outer_table EM_386 "$outfile"
+build_outer_table EM_X86_64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_XTENSA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_NONE "$outfile"
+cat >> "$outfile" <<EOF
+};
+EOF
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Mon Mar 17 20:31:46 2025
From: irogers at google.com (Ian Rogers)
Date: Mon, 17 Mar 2025 20:31:46 -0700
Subject: [PATCH v6 09/13] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <20250318033150.119174-1-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
Message-ID: <20250318033150.119174-10-irogers@google.com>

Switch to use the lookup table containing all architectures rather
than tables matching the perf binary.

This fixes perf trace when executed on a 32-bit i386 binary on an
x86-64 machine. Note in the following the system call names of the
32-bit i386 binary as seen by an x86-64 perf.

Before:
```
         ? (         ): a.out/447296  ... [continued]: munmap())                                           = 0
     0.024 ( 0.001 ms): a.out/447296 recvfrom(ubuf: 0x2, size: 4160585708, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|NOSIGNAL|WAITFORONE|BATCH|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f80000, addr: 0xe30, addr_len: 0xffce438c) = 1475198976
     0.042 ( 0.003 ms): a.out/447296 lgetxattr(name: "", value: 0x3, size: 34)                             = 4160344064
     0.054 ( 0.003 ms): a.out/447296 dup2(oldfd: -134422744, newfd: 4)                                     = -1 ENOENT (No such file or directory)
     0.060 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x2e646c2f6374652f,.iov_len = (__kernel_size_t)7307199665335594867,}, vlen: 557056, pos_h: 4160585708) = 3
     0.074 ( 0.004 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2)                              = 4160237568
     0.080 ( 0.001 ms): a.out/447296 lstat(filename: "", statbuf: 0x193f6)                                 = 0
     0.089 ( 0.007 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x3833692f62696c2f,.iov_len = (__kernel_size_t)3276497845987585334,}, vlen: 557056, pos_h: 4160585708) = 3
     0.097 ( 0.002 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 512
     0.103 ( 0.002 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2050)                           = 4157935616
     0.107 ( 0.007 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x5, size: 2066)             = 4158078976
     0.116 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x1, size: 2066)             = 4159639552
     0.121 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 2066)             = 4160184320
     0.129 ( 0.002 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 50)               = 4160196608
     0.138 ( 0.001 ms): a.out/447296 lstat(filename: "")                                                   = 0
     0.145 ( 0.002 ms): a.out/447296 mq_timedreceive(mqdes: 4291706800, u_msg_ptr: 0xf7f9ea48, msg_len: 134616640, u_msg_prio: 0xf7fd7fec, u_abs_timeout: (struct __kernel_timespec){.tv_sec = (__kernel_time64_t)-578174027777317696,.tv_nsec = (long long int)4160349376,}) = 0
     0.148 ( 0.001 ms): a.out/447296 mkdirat(dfd: -134617816, pathname: " ??? ???????????", mode: IFREG|ISUID|IRUSR|IWGRP|0xf7fd0000) = 447296
     0.150 ( 0.001 ms): a.out/447296 process_vm_writev(pid: -134617812, lvec: (struct iovec){.iov_base = (void *)0xf7f9e9c8f7f9e4c0,.iov_len = (__kernel_size_t)4160349376,}, liovcnt: 4160588048, rvec: (struct iovec){}, riovcnt: 4160585708, flags: 4291707352) = 0
     0.197 ( 0.004 ms): a.out/447296 capget(header: 4160184320, dataptr: 8192)                             = 0
     0.202 ( 0.002 ms): a.out/447296 capget(header: 1448669184, dataptr: 4096)                             = 0
     0.208 ( 0.002 ms): a.out/447296 capget(header: 4160577536, dataptr: 8192)                             = 0
     0.220 ( 0.001 ms): a.out/447296 getxattr(pathname: "", name: "c??????", value: 0xf7f77e34, size: 1)  = 0
     0.228 ( 0.005 ms): a.out/447296 fchmod(fd: -134729728, mode: IRUGO|IWUGO|IFREG|IFIFO|ISVTX|IXUSR|0x10000) = 0
     0.240 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: 0x5658e008, pos_h: 4160192052)            = 3
     0.250 ( 0.008 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 1436
     0.260 ( 0.018 ms): a.out/447296 stat(filename: "", statbuf: 0xffce32ac)                               = 1436
     0.288 (1000.213 ms): a.out/447296 readlinkat(buf: 0xffce31d4, bufsiz: 4291703244)                       = 0
```

After:
```
         ? (         ): a.out/442930  ... [continued]: execve())                                           = 0
     0.023 ( 0.002 ms): a.out/442930 brk()                                                                 = 0x57760000
     0.052 ( 0.003 ms): a.out/442930 access(filename: 0xf7f5af28, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.059 ( 0.009 ms): a.out/442930 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.078 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.087 ( 0.007 ms): a.out/442930 openat(dfd: CWD, filename: "/lib/i386-linux-", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.095 ( 0.002 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdbb70, count: 512)         = 512
     0.135 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.148 ( 0.001 ms): a.out/442930 set_tid_address(tidptr: 0xf7f2b528)                                   = 442930 (a.out)
     0.150 ( 0.001 ms): a.out/442930 set_robust_list(head: 0xf7f2b52c, len: 12)                            =
     0.196 ( 0.004 ms): a.out/442930 mprotect(start: 0xf7f03000, len: 8192, prot: READ)                    = 0
     0.202 ( 0.002 ms): a.out/442930 mprotect(start: 0x5658e000, len: 4096, prot: READ)                    = 0
     0.207 ( 0.002 ms): a.out/442930 mprotect(start: 0xf7f63000, len: 8192, prot: READ)                    = 0
     0.230 ( 0.005 ms): a.out/442930 munmap(addr: 0xf7f10000, len: 103414)                                 = 0
     0.244 ( 0.010 ms): a.out/442930 openat(dfd: CWD, filename: 0x5658d008)                                = 3
     0.255 ( 0.007 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdb67c, count: 4096)        = 1436
     0.264 ( 0.018 ms): a.out/442930 write(fd: 1</dev/pts/4>, buf: , count: 1436)                          = 1436
     0.292 (1000.173 ms): a.out/442930 clock_nanosleep(rqtp: { .tv_sec: 17866546940376776704, .tv_nsec: 4159878336 }, rmtp: 0xffbdb59c) = 0
  1000.478 (         ): a.out/442930 exit_group()                                                          = ?
```

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/util/syscalltbl.c | 89 ++++++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 760ac4d0869f..4e6018e2e0b3 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,16 +15,39 @@
 #include <string.h>
 #include "string2.h"
 
-#if __BITS_PER_LONG == 64
-  #include <asm/syscalls_64.h>
-#else
-  #include <asm/syscalls_32.h>
-#endif
+#include "trace/beauty/generated/syscalltbl.c"
 
-const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+static const struct syscalltbl *find_table(int e_machine)
 {
-	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
-		return syscall_num_to_name[id];
+	static const struct syscalltbl *last_table;
+	static int last_table_machine = EM_NONE;
+
+	/* Tables only exist for EM_SPARC. */
+	if (e_machine == EM_SPARCV9)
+		e_machine = EM_SPARC;
+
+	if (last_table_machine == e_machine && last_table != NULL)
+		return last_table;
+
+	for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) {
+		const struct syscalltbl *entry = &syscalltbls[i];
+
+		if (entry->e_machine != e_machine && entry->e_machine != EM_NONE)
+			continue;
+
+		last_table = entry;
+		last_table_machine = e_machine;
+		return entry;
+	}
+	return NULL;
+}
+
+const char *syscalltbl__name(int e_machine, int id)
+{
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (table && id >= 0 && id < table->num_to_name_len)
+		return table->num_to_name[id];
 	return NULL;
 }
 
@@ -41,38 +64,54 @@ static int syscallcmpname(const void *vkey, const void *ventry)
 	return strcmp(key->name, key->tbl[*entry]);
 }
 
-int syscalltbl__id(int e_machine __maybe_unused, const char *name)
+int syscalltbl__id(int e_machine, const char *name)
 {
-	struct syscall_cmp_key key = {
-		.name = name,
-		.tbl = syscall_num_to_name,
-	};
-	const int *id = bsearch(&key, syscall_sorted_names,
-				ARRAY_SIZE(syscall_sorted_names),
-				sizeof(syscall_sorted_names[0]),
-				syscallcmpname);
+	const struct syscalltbl *table = find_table(e_machine);
+	struct syscall_cmp_key key;
+	const uint16_t *id;
+
+	if (!table)
+		return -1;
+
+	key.name = name;
+	key.tbl = table->num_to_name;
+	id = bsearch(&key, table->sorted_names, table->sorted_names_len,
+		     sizeof(table->sorted_names[0]), syscallcmpname);
 
 	return id ? *id : -1;
 }
 
-int syscalltbl__num_idx(int e_machine __maybe_unused)
+int syscalltbl__num_idx(int e_machine)
 {
-	return ARRAY_SIZE(syscall_sorted_names);
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return 0;
+
+	return table->sorted_names_len;
 }
 
-int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
+int syscalltbl__id_at_idx(int e_machine, int idx)
 {
-	return syscall_sorted_names[idx];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return -1;
+
+	assert(idx >= 0 && idx < table->sorted_names_len);
+	return table->sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx)
 {
-	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
-		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) {
+		const char *name = table->num_to_name[table->sorted_names[i]];
 
 		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscall_sorted_names[i];
+			return table->sorted_names[i];
 		}
 	}
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From Rajaganesh.Rathinasabapathi at amd.com  Mon Mar 17 21:12:23 2025
From: Rajaganesh.Rathinasabapathi at amd.com (Rajaganesh Rathinasabapathi)
Date: Mon, 17 Mar 2025 23:12:23 -0500
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC compatible
Message-ID: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>

Document new AMD Onyx BMC board compatibles

Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 01333ac111fb..98f92c16e342 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -74,6 +74,7 @@ properties:
       - description: AST2600 based boards
         items:
           - enum:
+              - amd,onyx-bmc
               - ampere,mtjefferson-bmc
               - ampere,mtmitchell-bmc
               - aspeed,ast2600-evb
-- 
2.34.1



From Rajaganesh.Rathinasabapathi at amd.com  Mon Mar 17 21:12:24 2025
From: Rajaganesh.Rathinasabapathi at amd.com (Rajaganesh Rathinasabapathi)
Date: Mon, 17 Mar 2025 23:12:24 -0500
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx Platform
In-Reply-To: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>

Add initial device tree and makefile updates for
AMD Onyx platform.

AMD Onyx platform is an AMD customer reference board with an Aspeed
ast2600 BMC manufactured by AMD.
It describes I2C devices, UARTs, MAC, FMC, etc.
present on AMD Onyx platform.

Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
---
Changes since v1:
* Incorporate review comments
* Update commit message
* Remove vmalloc and earlyprintk

Changes since v2:
* Address review comments
* Fix checkpatch warnings
* Remove bootargs
---
 arch/arm/boot/dts/aspeed/Makefile             |   1 +
 .../boot/dts/aspeed/aspeed-bmc-amd-onyx.dts   | 102 ++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..1e6a130377b8 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-ast2600-evb.dtb \
 	aspeed-bmc-amd-daytonax.dtb \
 	aspeed-bmc-amd-ethanolx.dtb \
+	aspeed-bmc-amd-onyx.dtb \
 	aspeed-bmc-ampere-mtjade.dtb \
 	aspeed-bmc-ampere-mtjefferson.dtb \
 	aspeed-bmc-ampere-mtmitchell.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
new file mode 100644
index 000000000000..6f3334995398
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2021 - 2024 AMD Inc.
+// Author: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
+
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+	model = "AMD Onyx BMC";
+	compatible = "amd,onyx-bmc", "aspeed,ast2600";
+
+	aliases {
+		serial0 = &uart1;
+		serial4 = &uart5;
+	};
+
+	chosen {
+		stdout-path = serial4:115200n8;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+};
+
+&mdio0 {
+	status = "okay";
+	ethphy0: ethernet-phy at 0 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+};
+
+&mac3 {
+	status = "okay";
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rgmii4_default>;
+};
+
+&fmc {
+	status = "okay";
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		status = "okay";
+		#include "openbmc-flash-layout-128.dtsi"
+	};
+};
+
+//Host Console
+&uart1 {
+	status = "okay";
+};
+
+//BMC Console
+&uart5 {
+	status = "okay";
+};
+
+&gpio0 {
+gpio-line-names =
+	/*A0-A7*/	"","","","","","","","",
+	/*B0-B7*/	"","","","","MON_POST_COMPLETE","P0_PRESENT_L","","",
+	/*C0-C7*/	"","","","","","","","",
+	/*D0-D7*/	"","","","","","","","",
+	/*E0-E7*/	"","","","","","","","",
+	/*F0-F7*/	"","","","","","","","",
+	/*G0-G7*/	"","","","","","","","",
+	/*H0-H7*/	"","ASSERT_WARM_RST_BTN_L","ASSERT_SOC_RST_BTN_L","","","","","",
+	/*I0-I7*/	"","","","","","","","P0_I3C_APML_ALERT_L",
+	/*J0-J7*/	"","","","","","","","",
+	/*K0-K7*/	"","","","","","","","",
+	/*L0-L7*/	"","","","","","","","",
+	/*M0-M7*/	"","","","","","","","",
+	/*N0-N7*/	"","","","","","","PSP_SOFT_FUSE_NOTIFY","ASSERT_BMC_READY",
+	/*O0-O7*/	"","","HDT_SEL","HDT_XTRIG5","HDT_XTRIG6","JTAG_TRST_N","","",
+	/*P0-P7*/	"MON_RST_BTN_L","ASSERT_RST_BTN_L","MON_PWR_BTN_L","ASSERT_PWR_BTN_L",
+					"HPM_FPGA_LOCKOUT","ASSERT_NMI_BTN_L","MON_PWR_GOOD","",
+	/*Q0-Q7*/	"","","HDT_DBREQ_L","","BIOS_SPD_MUX_CTRL_RELEASED_L","","","",
+	/*R0-R7*/	"","","","","","","","",
+	/*S0-S7*/	"","","","","","","P0_DIMM_AF_ERROR","P0_DIMM_GL_ERROR",
+	/*T0-T7*/	"","","","","","","","",
+	/*U0-U7*/	"","","","","","","","",
+	/*V0-V7*/	"","","","","","","","",
+	/*W0-W7*/	"","","","","","","","",
+	/*X0-X7*/	"","","","","","","","",
+	/*Y0-Y7*/	"","","","","","","","",
+	/*Z0-Z7*/	"","","","","","","","";
+};
+
+&i2c7 {
+	status = "okay";
+	mbeeprom at 50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+	};
+};
-- 
2.34.1



From anshuman.khandual at arm.com  Mon Mar 17 21:37:56 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 18 Mar 2025 10:07:56 +0530
Subject: [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t
In-Reply-To: <16c12c3f-f2c2-45fa-9db6-4dfaeb002059@arm.com>
References: <20250317061818.16244-1-anshuman.khandual@arm.com>
 <20250317061818.16244-3-anshuman.khandual@arm.com>
 <16c12c3f-f2c2-45fa-9db6-4dfaeb002059@arm.com>
Message-ID: <392723e2-da82-4bdb-bebe-ed1c982d0d5f@arm.com>



On 3/17/25 14:58, Ryan Roberts wrote:
> On 17/03/2025 06:18, Anshuman Khandual wrote:
>> Page table entry's value, mask and protection are represented with pteval_t
>> data type format not u64 that has been assumed while dumping the page table
>> entries. Replace all such u64 instances with pteval_t instead as required.
>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Marc Zyngier <maz at kernel.org>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>>  arch/arm64/include/asm/ptdump.h | 8 ++++----
>>  arch/arm64/mm/ptdump.c          | 2 +-
>>  2 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
>> index e5da9ce8a515..476a870489b9 100644
>> --- a/arch/arm64/include/asm/ptdump.h
>> +++ b/arch/arm64/include/asm/ptdump.h
>> @@ -24,8 +24,8 @@ struct ptdump_info {
>>  };
>>  
>>  struct ptdump_prot_bits {
>> -	u64		mask;
>> -	u64		val;
>> +	pteval_t	mask;
>> +	pteval_t	val;
> 
> Given Ard's suggestion of using "ptdesc" as a generic term for PTDESC_SHIFT (or
> PTDESC_ORDER, or whatever we ended up calling it), I wonder if it would be
> cleaner to do the same with the types? We could have a ptdesc_t, which is
> typedef'ed as u64 (or u128), then pteval_t, pmdval_t, ..., could all be
> typedef'ed as ptdesc_t. Then for code that just wants a generic pgtable
> descriptor value, we can use that type to indicate that it can be at any level.

Something like the following ? Will cross check again if this might have
missed something which could be converted as ptdesc_t as well.

diff --git a/arch/arm64/include/asm/pgtable-types.h b/arch/arm64/include/asm/pgtable-types.h
index 6d6d4065b0cb..686541e986e3 100644
--- a/arch/arm64/include/asm/pgtable-types.h
+++ b/arch/arm64/include/asm/pgtable-types.h
@@ -11,11 +11,13 @@
 
 #include <asm/types.h>
 
-typedef u64 pteval_t;
-typedef u64 pmdval_t;
-typedef u64 pudval_t;
-typedef u64 p4dval_t;
-typedef u64 pgdval_t;
+typedef u64 ptdesc_t;
+
+typedef ptdesc_t pteval_t;
+typedef ptdesc_t pmdval_t;
+typedef ptdesc_t pudval_t;
+typedef ptdesc_t p4dval_t;
+typedef ptdesc_t pgdval_t;
 
 /*
  * These are used to make use of C type-checking..
@@ -46,7 +48,7 @@ typedef struct { pgdval_t pgd; } pgd_t;
 #define pgd_val(x)	((x).pgd)
 #define __pgd(x)	((pgd_t) { (x) } )
 
-typedef struct { pteval_t pgprot; } pgprot_t;
+typedef struct { ptdesc_t pgprot; } pgprot_t;
 #define pgprot_val(x)	((x).pgprot)
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index e5da9ce8a515..9548813bc877 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -24,8 +24,8 @@ struct ptdump_info {
 };
 
 struct ptdump_prot_bits {
-	u64		mask;
-	u64		val;
+	ptdesc_t	mask;
+	ptdesc_t	val;
 	const char	*set;
 	const char	*clear;
 };
@@ -34,7 +34,7 @@ struct ptdump_pg_level {
 	const struct ptdump_prot_bits *bits;
 	char name[4];
 	int num;
-	u64 mask;
+	ptdesc_t mask;
 };
 
 /*
@@ -51,7 +51,7 @@ struct ptdump_pg_state {
 	const struct mm_struct *mm;
 	unsigned long start_address;
 	int level;
-	u64 current_prot;
+	ptdesc_t current_prot;
 	bool check_wx;
 	unsigned long wx_pages;
 	unsigned long uxn_pages;
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 1d25d8899dbf..42e281c07c2f 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -29,7 +29,7 @@ static bool region_is_misaligned(const efi_memory_desc_t *md)
  * executable, everything else can be mapped with the XN bits
  * set. Also take the new (optional) RO/XP bits into account.
  */
-static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
+static __init ptdesc_t create_mapping_protection(efi_memory_desc_t *md)
 {
 	u64 attr = md->attribute;
 	u32 type = md->type;
@@ -83,7 +83,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
 
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
-	pteval_t prot_val = create_mapping_protection(md);
+	ptdesc_t prot_val = create_mapping_protection(md);
 	bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE ||
 				   md->type == EFI_RUNTIME_SERVICES_DATA);
 
diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index e57b043f324b..a00f57c73d81 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -159,7 +159,7 @@ static void noinline __section(".idmap.text") set_ttbr0_for_lpa2(u64 ttbr)
 static void __init remap_idmap_for_lpa2(void)
 {
 	/* clear the bits that change meaning once LPA2 is turned on */
-	pteval_t mask = PTE_SHARED;
+	ptdesc_t mask = PTE_SHARED;
 
 	/*
 	 * We have to clear bits [9:8] in all block or page descriptors in the
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 2b69e3beeef8..30c6bc50844f 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -30,7 +30,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 		      int level, pte_t *tbl, bool may_use_cont, u64 va_offset)
 {
 	u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
-	pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
+	ptdesc_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
 	int lshift = (3 - level) * (PAGE_SHIFT - 3);
 	u64 lmask = (PAGE_SIZE << lshift) - 1;
 
@@ -87,7 +87,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
 	}
 }
 
-asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, pteval_t clrmask)
+asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, ptdesc_t clrmask)
 {
 	u64 ptep = (u64)pg_dir + PAGE_SIZE;
 	pgprot_t text_prot = PAGE_KERNEL_ROX;
diff --git a/arch/arm64/kernel/pi/pi.h b/arch/arm64/kernel/pi/pi.h
index c91e5e965cd3..91dcb5b6bbd1 100644
--- a/arch/arm64/kernel/pi/pi.h
+++ b/arch/arm64/kernel/pi/pi.h
@@ -33,4 +33,4 @@ void map_range(u64 *pgd, u64 start, u64 end, u64 pa, pgprot_t prot,
 
 asmlinkage void early_map_kernel(u64 boot_status, void *fdt);
 
-asmlinkage u64 create_init_idmap(pgd_t *pgd, pteval_t clrmask);
+asmlinkage u64 create_init_idmap(pgd_t *pgd, ptdesc_t clrmask);
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 07aeab8a7606..c86c348857c4 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -83,7 +83,7 @@ arch_initcall(adjust_protection_map);
 
 pgprot_t vm_get_page_prot(unsigned long vm_flags)
 {
-	pteval_t prot;
+	ptdesc_t prot;
 
 	/* Short circuit GCS to avoid bloating the table. */
 	if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) {
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index fd1610b4fd15..280e850f1688 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
 	struct ptdump_pg_level *pg_level = st->pg_level;
 	static const char units[] = "KMGTPE";
-	u64 prot = 0;
+	ptdesc_t prot = 0;
 
 	/* check if the current level has been folded dynamically */
 	if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) ||
-- 
2.25.1

> 
> Thanks,
> Ryan
> 
>>  	const char	*set;
>>  	const char	*clear;
>>  };
>> @@ -34,7 +34,7 @@ struct ptdump_pg_level {
>>  	const struct ptdump_prot_bits *bits;
>>  	char name[4];
>>  	int num;
>> -	u64 mask;
>> +	pteval_t mask;
>>  };
>>  
>>  /*
>> @@ -51,7 +51,7 @@ struct ptdump_pg_state {
>>  	const struct mm_struct *mm;
>>  	unsigned long start_address;
>>  	int level;
>> -	u64 current_prot;
>> +	pteval_t current_prot;
>>  	bool check_wx;
>>  	unsigned long wx_pages;
>>  	unsigned long uxn_pages;
>> diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
>> index fd1610b4fd15..a5651be95868 100644
>> --- a/arch/arm64/mm/ptdump.c
>> +++ b/arch/arm64/mm/ptdump.c
>> @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
>>  	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
>>  	struct ptdump_pg_level *pg_level = st->pg_level;
>>  	static const char units[] = "KMGTPE";
>> -	u64 prot = 0;
>> +	pteval_t prot = 0;
>>  
>>  	/* check if the current level has been folded dynamically */
>>  	if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) ||
> 


From wei.fang at nxp.com  Mon Mar 17 21:47:11 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 04:47:11 +0000
Subject: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95
 ENETC PF
In-Reply-To: <20250317155501.4haweyhlrfozg7zr@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250317155501.4haweyhlrfozg7zr@skbuf>
Message-ID: <PAXPR04MB8510DE829523749E9FB5E20B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:24PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h
> b/drivers/net/ethernet/freescale/enetc/enetc.h
> > index a3ce324c716c..ecf79338cd79 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> > @@ -543,6 +543,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8
> *bytes);
> >  int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
> >  int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
> >  int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
> > +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
> > +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
> >
> >  static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
> >  					     struct enetc_cbd *cbd,
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > index f991e1aae85c..53dbd5d71859 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > @@ -693,6 +693,14 @@ static void enetc4_pf_set_rx_mode(struct
> net_device *ndev)
> >  	queue_work(si->workqueue, &si->rx_mode_task);
> >  }
> >
> > +static int enetc4_pf_set_features(struct net_device *ndev,
> > +				  netdev_features_t features)
> > +{
> > +	enetc_set_features(ndev, features);
> > +
> > +	return 0;
> > +}
> > +
> >  static const struct net_device_ops enetc4_ndev_ops = {
> >  	.ndo_open		= enetc_open,
> >  	.ndo_stop		= enetc_close,
> > @@ -700,6 +708,7 @@ static const struct net_device_ops enetc4_ndev_ops
> = {
> >  	.ndo_get_stats		= enetc_get_stats,
> >  	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
> >  	.ndo_set_rx_mode	= enetc4_pf_set_rx_mode,
> > +	.ndo_set_features	= enetc4_pf_set_features,
> >  };
> >
> >  static struct phylink_pcs *
> > @@ -1108,6 +1117,8 @@ static void enetc4_pf_netdev_destroy(struct
> enetc_si *si)
> >  static const struct enetc_si_ops enetc4_psi_ops = {
> >  	.setup_cbdr = enetc4_setup_cbdr,
> >  	.teardown_cbdr = enetc4_teardown_cbdr,
> > +	.get_rss_table = enetc4_get_rss_table,
> > +	.set_rss_table = enetc4_set_rss_table,
> >  };
> >
> >  static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > index 4e5125331d7b..1a74b93f1fd3 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > @@ -299,3 +299,17 @@ int enetc_set_rss_table(struct enetc_si *si, const
> u32 *table, int count)
> >  	return enetc_cmd_rss_table(si, (u32 *)table, count, false);
> >  }
> >  EXPORT_SYMBOL_GPL(enetc_set_rss_table);
> > +
> > +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
> > +{
> > +	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> > +					       table, count, true);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
> > +
> > +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
> > +{
> > +	return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> > +					       (u32 *)table, count, false);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_set_rss_table);
> 
> I don't understand the logic for placing enetc4_get_rss_table() and
> enetc4_set_rss_table() in enetc_cbdr.c (built as part of fsl-enetc-core-y)?
> It's not core code, it's used only by NETC v4.

The ENETC v4 VF will reuse the driver of ENETC v1, and it also supports
RSS, so I think these functions are fine to be placed in enetc-core.

> 
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > index 1a8fae3c406b..bc65135925b8 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > @@ -625,6 +625,24 @@ static int enetc_get_rxnfc(struct net_device *ndev,
> struct ethtool_rxnfc *rxnfc,
> >  	return 0;
> >  }
> >
> > +static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc
> *rxnfc,
> > +			    u32 *rule_locs)
> > +{
> > +	struct enetc_ndev_priv *priv = netdev_priv(ndev);
> > +
> > +	switch (rxnfc->cmd) {
> > +	case ETHTOOL_GRXRINGS:
> > +		rxnfc->data = priv->num_rx_rings;
> > +		break;
> > +	case ETHTOOL_GRXFH:
> > +		return enetc_get_rsshash(rxnfc);
> 
> These rxnfc commands seem implemented identically to the corresponding
> subset from enetc_get_rxnfc(). Rather than duplicating those, could you
> rather return -EOPNOTSUPP for the unsupported ones on NETC v4, and reuse
> enetc_get_rxnfc()?
> 

I have explained it to Jakub in v2:
https://lore.kernel.org/imx/PAXPR04MB8510B52B7D27640C557680B4881A2 at PAXPR04MB8510.eurprd04.prod.outlook.com/

So I don't want to reuse it for ENETC v4 PF.

> > +	default:
> > +		return -EOPNOTSUPP;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc
> *rxnfc)
> >  {
> >  	struct enetc_ndev_priv *priv = netdev_priv(ndev);
> > @@ -685,22 +703,29 @@ static int enetc_get_rss_key_base(struct enetc_si
> *si)
> >  	return ENETC4_PRSSKR(0);
> >  }
> >
> > +static void enetc_get_rss_key(struct enetc_si *si, const u8 *key)
> > +{
> > +	int base = enetc_get_rss_key_base(si);
> > +	struct enetc_hw *hw = &si->hw;
> > +	int i;
> > +
> > +	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> > +		((u32 *)key)[i] = enetc_port_rd(hw, base + i * 4);
> > +}
> 
> I would have expected that this refactoring of code into
> enetc_get_rss_key() would be done as part of the previous change:
> "net: enetc: make enetc_set_rss_key() reusable".
> 

I think this goes against the theme.



From wei.fang at nxp.com  Mon Mar 17 21:54:42 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 04:54:42 +0000
Subject: [PATCH v4 net-next 07/14] net: enetc: make enetc_set_rss_key()
 reusable
In-Reply-To: <20250317162617.glikwbcey3s3isfn@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-8-wei.fang@nxp.com>
 <20250311053830.1516523-8-wei.fang@nxp.com>
 <20250317162617.glikwbcey3s3isfn@skbuf>
Message-ID: <PAXPR04MB85100C7CDC7F0A915BF35AC188DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:23PM +0800, Wei Fang wrote:
> > Since the offset of the RSS key registers of i.MX95 ENETC is different
> > from that of LS1028A, so add enetc_get_rss_key_base() to get the base
> > offset for the different chips, so that enetc_set_rss_key() can be
> > reused for this trivial.
> 
> for this trivial... ? task?

Sorry, it should be trivial thing.
> 
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
> > .../net/ethernet/freescale/enetc/enetc4_pf.c  | 11 +----------
> > .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 ++++++++++++++-----
> >  .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +-
> >  4 files changed, 17 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > index a98ed059a83f..f991e1aae85c 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > @@ -583,22 +583,13 @@ static void enetc4_set_trx_frame_size(struct
> enetc_pf *pf)
> >  	enetc4_pf_reset_tc_msdu(&si->hw);
> >  }
> >
> > -static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
> > -{
> > -	int i;
> > -
> > -	for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> > -		enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
> > -}
> > -
> >  static void enetc4_set_default_rss_key(struct enetc_pf *pf)  {
> >  	u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
> > -	struct enetc_hw *hw = &pf->si->hw;
> >
> >  	/* set up hash key */
> >  	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
> > -	enetc4_set_rss_key(hw, hash_key);
> > +	enetc_set_rss_key(pf->si, hash_key);
> >  }
> 
> The entire enetc4_set_default_rss_key() seems reusable as
> enetc_set_default_rss_key(). enetc_configure_port() has the same logic.
> 

Yes, I can add enetc_set_default_rss_key() to enetc_pf_common.c

> >
> >  static void enetc4_enable_trx(struct enetc_pf *pf)


From peng.fan at oss.nxp.com  Mon Mar 17 21:55:49 2025
From: peng.fan at oss.nxp.com (Peng Fan (OSS))
Date: Tue, 18 Mar 2025 12:55:49 +0800
Subject: [PATCH] spi: stm32-ospi: Include "gpio/consumer.h"
Message-ID: <20250318045549.1711502-1-peng.fan@oss.nxp.com>

From: Peng Fan <peng.fan at nxp.com>

of_gpio.h should be deprecated, use "gpio/consumer.h".

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/spi/spi-stm32-ospi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index d4f413c8c3ce..668022098b1e 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -10,6 +10,7 @@
 #include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
@@ -19,7 +20,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
-- 
2.37.1



From wei.fang at nxp.com  Mon Mar 17 22:00:03 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 05:00:03 +0000
Subject: [PATCH v4 net-next 09/14] net: enetc: enable RSS feature by
 default
In-Reply-To: <20250317163337.4ii2bmourroiaryl@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-10-wei.fang@nxp.com>
 <20250311053830.1516523-10-wei.fang@nxp.com>
 <20250317163337.4ii2bmourroiaryl@skbuf>
Message-ID: <PAXPR04MB851013FE0ED69502EEB2175988DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:25PM +0800, Wei Fang wrote:
> > Receive side scaling (RSS) is a network driver technology that enables
> > the efficient distribution of network receive processing across
> > multiple CPUs in multiprocessor systems. Therefore, it is better to
> > enable RSS by default so that the CPU load can be balanced and network
> > performance can be improved when then network is enabled.
> 
> s/then network/the network/
> 
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++++++++++---------
> >  .../freescale/enetc/enetc_pf_common.c         |  4 ++-
> >  .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
> >  3 files changed, 25 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c
> > b/drivers/net/ethernet/freescale/enetc/enetc.c
> > index 5b5e65ac8fab..8583ac9f7b9e 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
> > @@ -2420,6 +2420,22 @@ static void enetc_set_lso_flags_mask(struct
> enetc_hw *hw)
> >  	enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
> >  }
> >
> > +static int enetc_set_rss(struct net_device *ndev, int en)
> 
> Can you please add a preliminary patch which converts this function's prototype
> to:

Okay, I can add such a patch in this patch set.
> 
> static void enetc_set_rss(struct net_device *ndev, bool en) ?
> 
> After you do that please feel free to add my tag and keep it in future patch
> submissions:
> 
> Acked-by: Vladimir Oltean <vladimir.oltean at nxp.com>
> 
> I don't see downsides to enabling RX hashing by default.


From wei.fang at nxp.com  Mon Mar 17 22:06:22 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 05:06:22 +0000
Subject: [PATCH v4 net-next 06/14] net: enetc: add set/get_rss_table() to
 enetc_si_ops
In-Reply-To: <20250317164205.bp4vcqarggp3fnf4@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-7-wei.fang@nxp.com>
 <20250317164205.bp4vcqarggp3fnf4@skbuf>
Message-ID: <PAXPR04MB851032D673522F8548855B7188DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:22PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > index d7d9a720069b..072e5b40a199 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > @@ -165,6 +165,8 @@ static void enetc_vf_netdev_setup(struct enetc_si *si,
> struct net_device *ndev,
> >  static const struct enetc_si_ops enetc_vsi_ops = {
> >  	.setup_cbdr = enetc_setup_cbdr,
> >  	.teardown_cbdr = enetc_teardown_cbdr,
> > +	.get_rss_table = enetc_get_rss_table,
> > +	.set_rss_table = enetc_set_rss_table,
> >  };
> 
> Are the CBDR-based enetc_get_rss_table() and enetc_set_rss_table()
> the correct implementations for NETC v4 VSIs? (I guess not). Does
> the driver/hardware fail in a civilized way, or does it crash?

We have not added ENETC v4 VSI support yet, the current VSI driver
is only applicable to v1. I will add enetc4_vsi_ops when supporting
v4 VSI.



From wei.fang at nxp.com  Mon Mar 17 22:12:25 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 05:12:25 +0000
Subject: [PATCH v4 net-next 10/14] net: enetc: move generic VLAN filter
 interfaces to enetc-core
In-Reply-To: <20250317170511.u7kfzmqafznovpoy@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-11-wei.fang@nxp.com>
 <20250311053830.1516523-11-wei.fang@nxp.com>
 <20250317170511.u7kfzmqafznovpoy@skbuf>
Message-ID: <PAXPR04MB851056BB4772F971F87C70CF88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:26PM +0800, Wei Fang wrote:
> > For ENETC, each SI has a corresponding VLAN hash table. That is to say,
> > both PF and VFs can support VLAN filter. However, currently only ENETC v1
> > PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
> > VF drivers also support VLAN filter, some related macros are moved from
> > enetc_pf.h to enetc.h, and the related structure variables are moved from
> > enetc_pf to enetc_si.
> >
> > Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
> > Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
> > so that it can be shared by PF and VF drivers. This will make it easier
> > to add VLAN filter support for i.MX95 ENETC later.
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> 
> In this and the next patch, can you please separate the code movement
> from the logical changes? It makes review much more difficult. With the
> similar observation that, as in the case of MAC filtering, VSIs don't
> yet support VLAN filtering, so the movement of the hash table structures
> from per-PF to per-SI is currently premature. So I expect to see that
> part removed from the next revision.

Okay, I will keep vlan_ht_filter in struct enetc_pf, and move common
interfaces to enetc_pf_common.c.



From wei.fang at nxp.com  Mon Mar 17 22:13:55 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 05:13:55 +0000
Subject: [PATCH v4 net-next 14/14] MAINTAINERS: add new file ntmp.h to
 ENETC driver
In-Reply-To: <20250317170650.4oux6kxh2ng4z725@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-15-wei.fang@nxp.com>
 <20250317170650.4oux6kxh2ng4z725@skbuf>
Message-ID: <PAXPR04MB85100C9846EF8AFC2622166288DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:30PM +0800, Wei Fang wrote:
> > Add new file ntmp.h. to ENETC driver.
> >
> > Signed-off-by: Wei Fang <wei.fang at nxp.com>
> > ---
> >  MAINTAINERS | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 7078199fcebf..e259b659eadb 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9174,6 +9174,7 @@ F:
> 	Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
> >  F:	drivers/net/ethernet/freescale/enetc/
> >  F:	include/linux/fsl/enetc_mdio.h
> >  F:	include/linux/fsl/netc_global.h
> > +F:	include/linux/fsl/ntmp.h
> >
> >  FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
> >  M:	Claudiu Manoil <claudiu.manoil at nxp.com>
> > --
> > 2.34.1
> >
> 
> This should be squashed with the patch that adds the initial NTMP support.
> We don't split out patches to the MAINTAINERS file.

Okay, I will squashed it to the NTMP patch.



From maddy at linux.ibm.com  Mon Mar 17 22:38:45 2025
From: maddy at linux.ibm.com (Madhavan Srinivasan)
Date: Tue, 18 Mar 2025 11:08:45 +0530
Subject: [PATCH v13 00/11] Support page table check on PowerPC
In-Reply-To: <20250211161404.850215-1-ajd@linux.ibm.com>
References: <20250211161404.850215-1-ajd@linux.ibm.com>
Message-ID: <67bff00d-eca7-41bd-ad9c-7ee6d5dac040@linux.ibm.com>



On 2/11/25 9:43 PM, Andrew Donnellan wrote:
> Support page table check on all PowerPC platforms. This works by
> serialising assignments, reassignments and clears of page table
> entries at each level in order to ensure that anonymous mappings
> have at most one writable consumer, and likewise that file-backed
> mappings are not simultaneously also anonymous mappings.
> 
> In order to support this infrastructure, a number of stubs must be
> defined for all powerpc platforms. Additionally, seperate set_pte_at()
> and set_pte_at_unchecked(), to allow for internal, uninstrumented mappings.
> 
> (This series was written by Rohan McLure, who has left IBM and is no longer
> working on powerpc - I've taken far too long to pick this up and finally
> send it.)
> 

For powerpc changes
Acked-by: Madhavan Srinivasan <maddy at linux.ibm.com>

> v13:
>  * Rebase on mainline
>  * Don't use set_pte_at_unchecked() for early boot purposes (Pasha)
> 
> v12:
>  * Rename commits that revert changes to instead reflect that we are
>    reinstating old behaviour due to it providing more flexibility
>  * Add return line to pud_pfn() stub
>  * Instrument ptep_get_and_clear() for nohash
> Link: https://lore.kernel.org/linuxppc-dev/20240402051154.476244-1-rmclure at linux.ibm.com/
> 
> v11:
>  * The pud_pfn() stub, which previously had no legitimate users on any
>    powerpc platform, now has users in Book3s64 with transparent pages.
>    Include a stub of the same name for each platform that does not
>    define their own.
>  * Drop patch that standardised use of p*d_leaf(), as already included
>    upstream in v6.9.
>  * Provide fallback definitions of p{m,u}d_user_accessible_page() that
>    do not reference p*d_leaf(), p*d_pte(), as they are defined after
>    powerpc/mm headers by linux/mm headers.
>  * Ensure that set_pte_at_unchecked() has the same checks as
>    set_pte_at().
> Link: https://lore.kernel.org/linuxppc-dev/20240328045535.194800-14-rmclure at linux.ibm.com/ 
> 
> v10:
>  * Revert patches that removed address and mm parameters from page table
>    check routines, including consuming code from arm64, x86_64 and
>    riscv.
>  * Implement *_user_accessible_page() routines in terms of pte_user()
>    where available (64-bit, book3s) but otherwise by checking the
>    address (on platforms where the pte does not imply whether the
>    mapping is for user or kernel)
>  * Internal set_pte_at() calls replaced with set_pte_at_unchecked(), which
>    is identical, but prevents double instrumentation.
> Link: https://lore.kernel.org/linuxppc-dev/20240313042118.230397-9-rmclure at linux.ibm.com/T/
> 
> v9:
>  * Adapt to using the set_ptes() API, using __set_pte_at() where we need
>    must avoid instrumentation.
>  * Use the logic of *_access_permitted() for implementing
>    *_user_accessible_page(), which are required routines for page table
>    check.
>  * Even though we no longer need p{m,u,4}d_leaf(), still default
>    implement these to assist in refactoring out extant
>    p{m,u,4}_is_leaf().
>  * Add p{m,u}_pte() stubs where asm-generic does not provide them, as
>    page table check wants all *user_accessible_page() variants, and we
>    would like to default implement the variants in terms of
>    pte_user_accessible_page().
>  * Avoid the ugly pmdp_collapse_flush() macro nonsense! Just instrument
>    its constituent calls instead for radix and hash.
> Link: https://lore.kernel.org/linuxppc-dev/20231130025404.37179-2-rmclure at linux.ibm.com/
> 
> v8:
>  * Fix linux/page_table_check.h include in asm/pgtable.h breaking
>    32-bit.
> Link: https://lore.kernel.org/linuxppc-dev/20230215231153.2147454-1-rmclure at linux.ibm.com/
> 
> v7:
>  * Remove use of extern in set_pte prototypes
>  * Clean up pmdp_collapse_flush macro
>  * Replace set_pte_at with static inline function
>  * Fix commit message for patch 7
> Link: https://lore.kernel.org/linuxppc-dev/20230215020155.1969194-1-rmclure at linux.ibm.com/
> 
> v6:
>  * Support huge pages and p{m,u}d accounting.
>  * Remove instrumentation from set_pte from kernel internal pages.
>  * 64s: Implement pmdp_collapse_flush in terms of __pmdp_collapse_flush
>    as access to the mm_struct * is required.
> Link: https://lore.kernel.org/linuxppc-dev/20230214015939.1853438-1-rmclure at linux.ibm.com/
> 
> v5:
> Link: https://lore.kernel.org/linuxppc-dev/20221118002146.25979-1-rmclure at linux.ibm.com/
> 
> Rohan McLure (11):
>   mm/page_table_check: Reinstate address parameter in
>     [__]page_table_check_pud_set()
>   mm/page_table_check: Reinstate address parameter in
>     [__]page_table_check_pmd_set()
>   mm/page_table_check: Provide addr parameter to
>     page_table_check_pte_set()
>   mm/page_table_check: Reinstate address parameter in
>     [__]page_table_check_pud_clear()
>   mm/page_table_check: Reinstate address parameter in
>     [__]page_table_check_pmd_clear()
>   mm/page_table_check: Reinstate address parameter in
>     [__]page_table_check_pte_clear()
>   mm: Provide address parameter to p{te,md,ud}_user_accessible_page()
>   powerpc: mm: Add pud_pfn() stub
>   powerpc: mm: Implement *_user_accessible_page() for ptes
>   powerpc: mm: Use set_pte_at_unchecked() for internal usages
>   powerpc: mm: Support page table check
> 
>  arch/arm64/include/asm/pgtable.h             | 18 +++---
>  arch/powerpc/Kconfig                         |  1 +
>  arch/powerpc/include/asm/book3s/32/pgtable.h | 12 +++-
>  arch/powerpc/include/asm/book3s/64/pgtable.h | 62 +++++++++++++++---
>  arch/powerpc/include/asm/nohash/pgtable.h    | 13 +++-
>  arch/powerpc/include/asm/pgtable.h           | 19 ++++++
>  arch/powerpc/mm/book3s64/hash_pgtable.c      |  4 ++
>  arch/powerpc/mm/book3s64/pgtable.c           | 17 +++--
>  arch/powerpc/mm/book3s64/radix_pgtable.c     |  9 ++-
>  arch/powerpc/mm/pgtable.c                    | 12 ++++
>  arch/riscv/include/asm/pgtable.h             | 18 +++---
>  arch/x86/include/asm/pgtable.h               | 20 +++---
>  include/linux/page_table_check.h             | 67 ++++++++++++--------
>  include/linux/pgtable.h                      | 10 +--
>  mm/page_table_check.c                        | 39 +++++++-----
>  15 files changed, 225 insertions(+), 96 deletions(-)
> 



From anshuman.khandual at arm.com  Mon Mar 17 22:54:45 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Tue, 18 Mar 2025 11:24:45 +0530
Subject: [PATCH 0/2] arm64/mm/hotplug: Drop some redundant WARN_ON()
In-Reply-To: <20250221094449.1188427-1-anshuman.khandual@arm.com>
References: <20250221094449.1188427-1-anshuman.khandual@arm.com>
Message-ID: <9abeecc3-2b19-43ba-8619-ea286d54db8e@arm.com>

On 2/21/25 15:14, Anshuman Khandual wrote:
> This series drops some redundant WARN_ON() tests which are not required any
> more while unmapping and freeing up kernel page table pages during a memory
> hot remove operation.
> 
> This series applies on v6.14-rc3
> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> 
> Anshuman Khandual (2):
>   arm64/mm/hotplug: Drop redundant [pgd|p4d]_present()
>   arm64/mm/hotplug: Replace pxx_present() with pxx_valid()
> 
>  arch/arm64/mm/mmu.c | 14 +++++---------
>  1 file changed, 5 insertions(+), 9 deletions(-)
> 

Gentle ping, any updates on this series ? This simplifies WARN_ON()
checks during memory hotplug operation, after subsequent changes to
page table helpers such as pxd_present() etc.


From Jjian.Zhou at mediatek.com  Mon Mar 17 22:54:59 2025
From: Jjian.Zhou at mediatek.com (=?utf-8?B?SmppYW4gWmhvdSAo5ZGo5bu6KQ==?=)
Date: Tue, 18 Mar 2025 05:54:59 +0000
Subject: [PATCH RFC v3 3/3] dt-bindings: mailbox: mtk,mt8196-vcp-mbox: add
 mtk vcp-mbox document
In-Reply-To: <20250317163358.GA178378-robh@kernel.org>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
	 <20250317110331.2776-4-jjian.zhou@mediatek.com>
	 <20250317163358.GA178378-robh@kernel.org>
Message-ID: <9d930e1b8245e3e8f00f79a661cf7b9adf273986.camel@mediatek.com>

On Mon, 2025-03-17 at 11:33 -0500, Rob Herring wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Mon, Mar 17, 2025 at 07:03:25PM +0800, Jjian Zhou wrote:
> > This patch adds document for mediatek vcp mbox.
> > 
> > Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> > ---
> >  .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml | 49
> > +++++++++++++++++++
> >  1 file changed, 49 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/mailbox/mtk,mt8196-
> > vcp-mbox.yaml
> > b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-
> > mbox.yaml
> > new file mode 100644
> > index 000000000000..bd1b024e22f1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-
> > mbox.yaml
> 
> Still wrong...
> 
> > +  compatible:
> > +    enum:
> > +      - mediatek,mt8196-vcp-mbox
> 
> mediatek,mt8196-vcp-mbox != mtk,mt8196-vcp-mbox
> 
Hi Rob,

I'm sorry for my mistake.
I will change the file name to mediatek,mt8196-vcp-mbox.yaml.

From andyshrk at 163.com  Mon Mar 17 23:20:17 2025
From: andyshrk at 163.com (Andy Yan)
Date: Tue, 18 Mar 2025 14:20:17 +0800
Subject: [PATCH] drm/rockchip: vop2: Make overlay layer select register configuration take effect by vsync
Message-ID: <20250318062024.4555-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Because the layer/window enable/disable is take effect by vsync, if the
overlay configuration of these layers does not follow vsync and
takes effect immediately instead, when multiple layers are dynamically
enable/disable, inconsistent display contents may be seen on the screen.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 1 +
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
index 680bedbb770e..fc3ecb9fcd95 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -710,6 +710,7 @@ enum dst_factor_mode {
 
 #define VOP2_COLOR_KEY_MASK				BIT(31)
 
+#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL		GENMASK(31, 30)
 #define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD		BIT(28)
 #define RK3568_OVL_CTRL__YUV_MODE(vp)			BIT(vp)
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 0a2840cbe8e2..32c4ed685739 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -2070,7 +2070,10 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
 
 	ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL);
-	ovl_ctrl |= RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD;
+	ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD;
+	ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL;
+	ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id);
+
 	if (vcstate->yuv_overlay)
 		ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id);
 	else
-- 
2.43.0



From mike.looijmans at topic.nl  Mon Mar 17 23:21:28 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Tue, 18 Mar 2025 07:21:28 +0100
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <20250318001211.tnjwfckt5j4fbvjf@synopsys.com>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
 <20250314211411.l5taj5nysvcalfyz@synopsys.com>
 <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>
 <20250318001211.tnjwfckt5j4fbvjf@synopsys.com>
Message-ID: <a9812897-2c79-4a1c-9431-c6f184233a57@topic.nl>

On 18-03-2025 01:12, Thinh Nguyen wrote:
> On Mon, Mar 17, 2025, Mike Looijmans wrote:
>> On 14-03-2025 22:14, Thinh Nguyen wrote:
>>> On Fri, Mar 14, 2025, Mike Looijmans wrote:
>>>> Set the gpio to "high" on acquisition, instead of acquiring it in low
>>>> state and then immediately setting it high again. This prevents a
>>>> short "spike" on the reset signal.
>>> How does this affect the current programming flow beside preventing a
>>> spike to the reset signal?
>> I don't understand your question. What "programming flow" are you referring
>> to?
> It's not obvious to me if this is an error in Xilinx documentation, the
> driver issue, or whether this is found through experiment. Since I don't
> have the info of this platform, it would help to know where the source
> of error is so we can document this in the code or change-log.

It's a bug in the driver, found through code inspection.

The reset GPIO here is to control the reset signal to an external, 
usually ULPI PHY, chip. This external chip is not part of the Xilinx 
hardware.

>> The reset sequence was just plain wrong, the issue is almost the same as the
> Do we need a fix tag and add to stable then?

That would be appropriate I think.


>
>> one described in this commit:
>> e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"
>>
>> Note that I see this high-low-high-low double reset toggle in many Xilinx
>> software drivers, they seem to teach that at the Xilinx academy or so.
>>
>>
>>>> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
>>>> ---
>>>>
>>>>    drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
>>>>    1 file changed, 1 insertion(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
>>>> index a33a42ba0249..a159a511483b 100644
>>>> --- a/drivers/usb/dwc3/dwc3-xilinx.c
>>>> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
>>>> @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>>>>    skip_usb3_phy:
>>>>    	/* ulpi reset via gpio-modepin or gpio-framework driver */
>>>> -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>>>> +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>>>>    	if (IS_ERR(reset_gpio)) {
>>>>    		return dev_err_probe(dev, PTR_ERR(reset_gpio),
>>>>    				     "Failed to request reset GPIO\n");
>>>> @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>>>>    	if (reset_gpio) {
>>>>    		/* Toggle ulpi to reset the phy. */
>>> Does the comment above still apply?
>> Now you mention it, the comment never made any sense anyway.
>>
> Then can we remove it?

Removing would be better, yes. I'll make a v2 patch.


>>>> -		gpiod_set_value_cansleep(reset_gpio, 1);
>>>>    		usleep_range(5000, 10000);
>>> Do we still need this usleep_range here?
>> Yes, this is the "reset active" time.
>>
> But why do we need 2 calls to usleep_range? From just looking at this
> here, it appears that the first was intended for the removed
> gpiod_set_value_cansleep(reset_gpio, 1). If this "reset active" time is
> needed irrespective of the existent reset_gpio, then shouldn't it be set
> outside of this if statement?

It helps to see the whole thing instead of just the patch.

If I omit error handling and comments then the original code reads:

 ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 ??????? if (reset_gpio) {
 ??????????????? gpiod_set_value_cansleep(reset_gpio, 1);
 ??????????????? usleep_range(5000, 10000);
 ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
 ??????????????? usleep_range(5000, 10000);
 ??????? }

So the gpio is acquired in a LOW state and then, without delay, is set 
to a high state again. This causes the "spike" I'm mentioning here. The 
correct procedure is to acquire it in the HIGH state immediately, so the 
sequence becomes:

 ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 ??????? if (reset_gpio) {
 ??????????????? usleep_range(5000, 10000);
 ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
 ??????????????? usleep_range(5000, 10000);
 ??????? }

This patch does exactly that.


> BR,
> Thinh
>
>>
>>> BR,
>>> Thinh
>>>
>>>>    		gpiod_set_value_cansleep(reset_gpio, 0);
>>>>    		usleep_range(5000, 10000);
>>>> -- 
>>>> 2.43.0
>>>>
>>>>
>>>> Met vriendelijke groet / kind regards,
>>>>
>>>> Mike Looijmans
>>>>
>>>>
>> -- 
>> Mike Looijmans
>> System Expert
>>
>> TOPIC Embedded Products B.V.
>> Materiaalweg 4, 5681 RJ Best
>> The Netherlands
>>
>> T: +31 (0) 499 33 69 69
>> E: mike.looijmans at topic.nl
>> W: https://urldefense.com/v3/__http://www.topic.nl__;!!A4F2R9G_pg!e45B0wD5dvB4NV8gz5JjIWaRTQrX9M2uE0ouoBVX4TQC8sKqtYRL8rJY3y2bb061gzSoGL0FOPJv-3-adkP1b3ldzRZnxdY$
>>
>>

-- 
Mike Looijmans
System Expert

TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl





From shayne.chen at mediatek.com  Mon Mar 17 23:28:57 2025
From: shayne.chen at mediatek.com (Shayne Chen)
Date: Tue, 18 Mar 2025 14:28:57 +0800
Subject: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to
 support MLO
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-20-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
	 <20250312-b4-mt7996-mlo-p2-v1-20-015b3d6fd928@kernel.org>
Message-ID: <38ab11261debaf7e0884080031412808396eea5b.camel@mediatek.com>

Hi Lorenzo,

On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Active/de-active TX/RX BA sessssion for each active links running
> mt7996_ampdu_action routine.
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
> ---
> ?drivers/net/wireless/mediatek/mt76/mt7996/main.c?? | 89
> ++++++++++++++--------
> ?drivers/net/wireless/mediatek/mt76/mt7996/mcu.c??? | 16 ++--
> ?drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |? 5 +-
> ?3 files changed, 64 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index
> 8bcb4b8e3ef58c23294c16c10d38384bfba87e30..adeb267b2801894590f90d02e90
> 2ebec602de98a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -1259,12 +1259,13 @@ mt7996_ampdu_action(struct ieee80211_hw *hw,
> struct ieee80211_vif *vif,
> ??????? enum ieee80211_ampdu_mlme_action action = params->action;
> ??????? struct mt7996_dev *dev = mt7996_hw_dev(hw);
> ??????? struct ieee80211_sta *sta = params->sta;
> -?????? struct ieee80211_txq *txq = sta->txq[params->tid];
> ??????? struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
> -?????? struct mt7996_sta_link *msta_link = &msta->deflink;
> +?????? struct ieee80211_txq *txq = sta->txq[params->tid];
> +?????? struct ieee80211_link_sta *link_sta;
> ??????? u16 tid = params->tid;
> ??????? u16 ssn = params->ssn;
> ??????? struct mt76_txq *mtxq;
> +?????? unsigned int link_id;
> ??????? int ret = 0;
> 
> ??????? if (!txq)
> @@ -1274,38 +1275,60 @@ mt7996_ampdu_action(struct ieee80211_hw *hw,
> struct ieee80211_vif *vif,
> 
> ??????? mutex_lock(&dev->mt76.mutex);
> 
> -?????? switch (action) {
> -?????? case IEEE80211_AMPDU_RX_START:
> -?????????????? mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid,
> ssn,
> -????????????????????????????????? params->buf_size);
> -?????????????? ret = mt7996_mcu_add_rx_ba(dev, params, true);
> -?????????????? break;
> -?????? case IEEE80211_AMPDU_RX_STOP:
> -?????????????? mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
> -?????????????? ret = mt7996_mcu_add_rx_ba(dev, params, false);
> -?????????????? break;
> -?????? case IEEE80211_AMPDU_TX_OPERATIONAL:
> -?????????????? mtxq->aggr = true;
> -?????????????? mtxq->send_bar = false;
> -?????????????? ret = mt7996_mcu_add_tx_ba(dev, params, true);
> -?????????????? break;
> -?????? case IEEE80211_AMPDU_TX_STOP_FLUSH:
> -?????? case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> -?????????????? mtxq->aggr = false;
> -?????????????? clear_bit(tid, &msta_link->wcid.ampdu_state);
> -?????????????? ret = mt7996_mcu_add_tx_ba(dev, params, false);
> -?????????????? break;
> -?????? case IEEE80211_AMPDU_TX_START:
> -?????????????? set_bit(tid, &msta_link->wcid.ampdu_state);
> -?????????????? ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
> -?????????????? break;
> -?????? case IEEE80211_AMPDU_TX_STOP_CONT:
> -?????????????? mtxq->aggr = false;
> -?????????????? clear_bit(tid, &msta_link->wcid.ampdu_state);
> -?????????????? ret = mt7996_mcu_add_tx_ba(dev, params, false);
> -?????????????? ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> -?????????????? break;
> +?????? for_each_sta_active_link(vif, sta, link_sta, link_id) {
> +?????????????? struct mt7996_sta_link *msta_link;
> +?????????????? struct mt7996_vif_link *link;
> +
> +?????????????? msta_link = mt76_dereference(msta->link[link_id],
> &dev->mt76);
> +?????????????? if (!msta_link)
> +?????????????????????? continue;
> +
> +?????????????? link = mt7996_vif_link(dev, vif, link_id);
> +?????????????? if (!link)
> +?????????????????????? continue;
> +
> +?????????????? switch (action) {
> +?????????????? case IEEE80211_AMPDU_RX_START:
> +?????????????????????? mt76_rx_aggr_start(&dev->mt76, &msta_link-
> >wcid, tid,
> +????????????????????????????????????????? ssn, params->buf_size);
> +?????????????????????? ret = mt7996_mcu_add_rx_ba(dev, params, link,
> true);
> +?????????????????????? break;
> +?????????????? case IEEE80211_AMPDU_RX_STOP:
> +?????????????????????? mt76_rx_aggr_stop(&dev->mt76, &msta_link-
> >wcid, tid);
> +?????????????????????? ret = mt7996_mcu_add_rx_ba(dev, params, link,
> false);
> +?????????????????????? break;
> +?????????????? case IEEE80211_AMPDU_TX_OPERATIONAL:
> +?????????????????????? mtxq->aggr = true;
> +?????????????????????? mtxq->send_bar = false;
> +?????????????????????? ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +????????????????????????????????????????????????? msta_link, true);
> +?????????????????????? break;
> +?????????????? case IEEE80211_AMPDU_TX_STOP_FLUSH:
> +?????????????? case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> +?????????????????????? mtxq->aggr = false;
> +?????????????????????? clear_bit(tid, &msta_link->wcid.ampdu_state);
> +?????????????????????? ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +????????????????????????????????????????????????? msta_link, false);
> +?????????????????????? break;
> +?????????????? case IEEE80211_AMPDU_TX_START:
> +?????????????????????? set_bit(tid, &msta_link->wcid.ampdu_state);
> +?????????????????????? ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
> +?????????????????????? break;
> +?????????????? case IEEE80211_AMPDU_TX_STOP_CONT:
> +?????????????????????? mtxq->aggr = false;
> +?????????????????????? clear_bit(tid, &msta_link->wcid.ampdu_state);
> +?????????????????????? ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +????????????????????????????????????????????????? msta_link, false);
> +?????????????????????? break;
> +?????????????? }
> +
> +?????????????? if (ret)
> +?????????????????????? break;
> ??????? }
> +
> +?????? if (action == IEEE80211_AMPDU_TX_STOP_CONT)
> +?????????????? ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> +
> ??????? mutex_unlock(&dev->mt76.mutex);
> 
> ??????? return ret;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index
> 85602a8594e0c9ab3a0055e04cf1ca836d62b6b9..89e4f0e8858322b636650a27d9a
> b0872987b7011 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -1160,26 +1160,20 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev,
> struct mt76_vif_link *mvif,
> ?/** starec & wtbl **/
> ?int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
> ???????????????????????? struct ieee80211_ampdu_params *params,
> -??????????????????????? bool enable)
> +??????????????????????? struct mt7996_vif_link *link,
> +??????????????????????? struct mt7996_sta_link *msta_link, bool
> enable)
> ?{
> -?????? struct mt7996_sta *msta = (struct mt7996_sta *)params->sta-
> >drv_priv;
> -?????? struct mt7996_sta_link *msta_link = &msta->deflink;
> -?????? struct mt7996_vif *mvif = msta->vif;
> -
> ??????? if (enable && !params->amsdu)
> ??????????????? msta_link->wcid.amsdu = false;
> 
> -?????? return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params,
> enable, true);
> +?????? return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable,
> true);

Per-link-bss setting is now ready for mt7996_mcu_sta_ba(), while for
per-link-sta, the wcid is still retrieved from deflink through the
following line:

struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv

We may also need to pass msta_link->wcid to mt7996_mcu_sta_ba().
> ?}
> 
> ?int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
> ???????????????????????? struct ieee80211_ampdu_params *params,
> -??????????????????????? bool enable)
> +??????????????????????? struct mt7996_vif_link *link, bool enable)
> ?{
> -?????? struct mt7996_sta *msta = (struct mt7996_sta *)params->sta-
> >drv_priv;
> -?????? struct mt7996_vif *mvif = msta->vif;
> -
> -?????? return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params,
> enable, false);
> +?????? return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable,
> false);

Same here.
> ?}
> 
> ?static void
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> index
> 815a3c68b8723469e32e74b85979eaf75c1b176a..43e646ed6094cb7fb78d201fc3e
> e8446ad2a16a1 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> @@ -584,10 +584,11 @@ int mt7996_mcu_teardown_mld_sta(struct
> mt7996_dev *dev,
> ??????????????????????????????? struct mt7996_sta_link *msta_link);
> ?int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
> ???????????????????????? struct ieee80211_ampdu_params *params,
> -??????????????????????? bool add);
> +??????????????????????? struct mt7996_vif_link *link,
> +??????????????????????? struct mt7996_sta_link *msta_link, bool
> enable);
> ?int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
> ???????????????????????? struct ieee80211_ampdu_params *params,
> -??????????????????????? bool add);
> +??????????????????????? struct mt7996_vif_link *link, bool enable);
> ?int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
> ??????????????????????????????? struct mt76_vif_link *mlink,
> ??????????????????????????????? struct cfg80211_he_bss_color
> *he_bss_color);
> 
> --
> 2.48.1
> 

Regards,
Shayne

From mike.looijmans at topic.nl  Mon Mar 17 23:44:52 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Tue, 18 Mar 2025 07:44:52 +0100
Subject: [PATCH v2] usb: dwc3: xilinx: Prevent spike in reset signal
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.92a20336-7677-4cd7-9893-b0e0da853ba9@emailsignatures365.codetwo.com>
Message-ID: <20250318064518.9320-1-mike.looijmans@topic.nl>

The "reset" GPIO controls the RESET signal to an external, usually
ULPI PHY, chip. The original code path acquires the signal in LOW
state, and then immediately asserts it HIGH again, if the reset
signal defaulted to asserted, there'd be a short "spike" before the
reset.

Here is what happens depending on the pre-existing state of the reset
signal:
Reset (previously asserted):   ~~~|_|~~~~|_______
Reset (previously deasserted): _____|~~~~|_______
                                  ^ ^    ^
                                  A B    C

At point A, the low going transition is because the reset line is
requested using GPIOD_OUT_LOW. If the line is successfully requested,
the first thing we do is set it high _without_ any delay. This is
point B. So, a glitch occurs between A and B.

Requesting the line using GPIOD_OUT_HIGH eliminates the A and B
transitions. Instead we get:

Reset (previously asserted)  : ~~~~~~~~~~|______
Reset (previously deasserted): ____|~~~~~|______
                                   ^     ^
                                   A     C

Where A and C are the points described above in the code. Point B
has been eliminated.

The issue was found during code inspection.

Also remove the cryptic "toggle ulpi .." comment.

Fixes: ca05b38252d7 ("usb: dwc3: xilinx: Add gpio-reset support")
Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

Changes in v2:
Add "Fixes" tag
Remove "toggle ulpi" comment
Extend comment to explain what is happening in detail

 drivers/usb/dwc3/dwc3-xilinx.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index a33a42ba0249..4ca7f6240d07 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -207,15 +207,13 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
 
 skip_usb3_phy:
 	/* ulpi reset via gpio-modepin or gpio-framework driver */
-	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(reset_gpio)) {
 		return dev_err_probe(dev, PTR_ERR(reset_gpio),
 				     "Failed to request reset GPIO\n");
 	}
 
 	if (reset_gpio) {
-		/* Toggle ulpi to reset the phy. */
-		gpiod_set_value_cansleep(reset_gpio, 1);
 		usleep_range(5000, 10000);
 		gpiod_set_value_cansleep(reset_gpio, 0);
 		usleep_range(5000, 10000);
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From alb3rt0.m3rciai at gmail.com  Mon Mar 17 23:56:15 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Tue, 18 Mar 2025 07:56:15 +0100
Subject: OCOTP and DWMAC builtin modules are needed for imx93-11x11-evk
 kernel dev via TFTP and NFS
In-Reply-To: <88c66c98-7ea3-4172-9c99-405fe449cc5b@linaro.org>
References: <Z9fhuVltKwqgHdLp@alb3rt0-ThinkPad-P15-Gen-1>
 <935028c6-ce56-46e0-96ff-46fa91c8f66a@linaro.org>
 <Z9hkDqcKG1xOmIB5@alb3rt0-ThinkPad-P15-Gen-1>
 <ef163f08-35f9-4d1d-8082-c826c6cd0aa0@linaro.org>
 <Z9hxKlrrqW4QyzdJ@alb3rt0-ThinkPad-P15-Gen-1>
 <88c66c98-7ea3-4172-9c99-405fe449cc5b@linaro.org>
Message-ID: <Z9kZD0vEsrrIftk5@alb3rt0-ThinkPad-P15-Gen-1>

On Mon, Mar 17, 2025 at 08:14:30PM +0100, Krzysztof Kozlowski wrote:
> On 17/03/2025 19:59, Alberto Merciai wrote:
> >>>
> >>> By default they are enabled as external modules, then until we don't
> >>
> >> So everything is as expected...
> >>
> >>> reach userland they are not loaded thus eth and all the mechanism behind
> >>> that are out.
> >>>
> >>> I'm not using initramfs just tftp and NFS as follows:
> >>
> >> All arm64 platforms are supposed to use initramfs on defconfig with
> >> necessary modules.
> > Thanks a lot, I was not aware of that.
> > Do you have any reference?
> Reference for what? initramfs?
> 
> I am using meta-qcom initramfs:
> https://github.com/krzk/yocto-qcom
> with copy_modules argument:
> 
> https://github.com/krzk/tools/blob/7c0d1cacad06aa0cae8c2983ae26889471a9aaa6/linux/build.sh#L543
> 
> And here is how I append stuff, but simple `cat` one cpio archive to
> another cpio archive would work as well, just be sure some paths are not
> symlinks (/bin /usr/bin) because then `cat` has issues:
> 
> https://github.com/krzk/tools/blob/7c0d1cacad06aa0cae8c2983ae26889471a9aaa6/linux/build.sh#L504
> 
> Best regards,
> Krzysztof
Really appreciate, Thanks a lot!


From krzk at kernel.org  Tue Mar 18 00:16:11 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 08:16:11 +0100
Subject: [PATCH v1 1/2] media: dt-bindings: Add qcom,qcs8300-camss
In-Reply-To: <66c35bce-c657-4c12-ad02-58c995ae385a@quicinc.com>
References: <20250214094747.2483058-1-quic_vikramsa@quicinc.com>
 <20250214094747.2483058-2-quic_vikramsa@quicinc.com>
 <20250223-observant-auspicious-basilisk-d78ba9@krzk-bin>
 <66c35bce-c657-4c12-ad02-58c995ae385a@quicinc.com>
Message-ID: <f2899540-f9ac-4013-a703-25800429f97d@kernel.org>

On 18/03/2025 06:52, Vikram Sharma wrote:
> 
> On 2/23/2025 5:03 PM, Krzysztof Kozlowski wrote:
>> On Fri, Feb 14, 2025 at 03:17:46PM +0530, Vikram Sharma wrote:
>>> +properties:
>>> +  compatible:
>>> +    const: qcom,qcs8300-camss
>>> +
>>> +  reg:
>>> +    maxItems: 21
>>> +
>>> +  reg-names:
>>> +    items:
>>> +      - const: csid_wrapper
>> Why different order of entries than sm8550?
> 
> Hi Krzysztof,
> 
> Thanks for your review.
> I did this change to address a comment from Bryan on another series.
> https://lore.kernel.org/linux-arm-msm/e152ff78-caa5-493a-88da-96a6670eb2a2 at linaro.org/
> 
> Please suggest if I should keep the order same as sm8550?
If you chosen the same order as x1e80100 then it is fine, but that file
is not merged so it is your responsibility to track any differences and
be sure whatever you send is always in sync with x1e.

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 18 00:19:39 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 08:19:39 +0100
Subject: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
 ExynosAutoV920 SoC
In-Reply-To: <20250318004411.695786-1-sw617.shin@samsung.com>
References: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
 <CGME20250318005143epcas2p40ebb1954bed8890aaf8d0a641f710423@epcas2p4.samsung.com>
 <20250318004411.695786-1-sw617.shin@samsung.com>
Message-ID: <658c00e2-e8ef-4997-bb91-9620e97bafae@kernel.org>

On 18/03/2025 01:44, Sangwook Shin wrote:
> From: Kyunghwan Seo <khwan.seo at samsung.com>
> 
> Fix the PMU register bits for the ExynosAutoV920 SoC.
> This SoC has different bit information compared to its previous
> version, ExynosAutoV9, and we have made the necessary adjustments.
> 
> rst_stat_bit:
>     - ExynosAutoV920 cl0 : 0
>     - ExynosAutoV920 cl1 : 1
> 
> cnt_en_bit:
>     - ExynosAutoV920 cl0 : 8
>     - ExynosAutoV920 cl1 : 8
> 
> Signed-off-by: Kyunghwan Seo <khwan.seo at samsung.com>
> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
> Reviewed-by: Alim Akhtar <alim.akhtar at samsung.com>
> Signed-off-by: Sangwook Shin <sw617.shin at samsung.com>
> ---
> v1 -> v2: Restore previous email history and tags.
> 

Why do you send patches which were applied?

Best regards,
Krzysztof


From peng.fan at oss.nxp.com  Tue Mar 18 01:28:04 2025
From: peng.fan at oss.nxp.com (Peng Fan)
Date: Tue, 18 Mar 2025 16:28:04 +0800
Subject: [PATCH v3 0/7] firmware: scmi/imx: Add i.MX95 LMM/CPU Protocol
In-Reply-To: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
Message-ID: <20250318082804.GA1326@nxa18884-linux>

Hi Sudeep, Cristian

On Mon, Mar 03, 2025 at 10:53:21AM +0800, Peng Fan (OSS) wrote:
>i.MX95 System Manager(SM) implements Logical Machine Management(LMM) and
>CPU protocol to manage Logical Machine(LM) and CPUs(eg, M7).

Any comments?
I am thinking to address comments and post v4 after 6.15 merge window close.

Thanks,
Peng

>
>To manage M7 in a separate LM or in same LM as Linux itself. LMM APIs
>and CPU APIs are needed.
>
>When M7 is in LM 'lm-m7', and this LM is managable by 'linux-lm',
>linux could use LMM_BOOT, LMM_SHUTDOWN and etc to manage 'lm-m7'.
>
>If in same LM, use CPU_START, CPU_STOP, CPU_RESET_VECTOR_SET and etc to
>manage M7.
>
>Both LMM/CPU APIs will be used by remoteproc driver. The remoteproc
>patchset will be posted out after this patchset gets reviewed or in
>good shape per Maitainer's view.
>
>Build pass with COMPILE_TEST
>Tested with remoteproc on i.MX95
>
>Signed-off-by: Peng Fan <peng.fan at nxp.com>
>---
>Changes in v3:
>Patch 1: Correct LMM_ATTRIBUTE return values
>        Update the return status of LM_BOOT/RESET/SHUTDOWN/WAKE
>        clarify sync/async in the Introduction chapter of LMM
>        Update the Origin entry in LMM_RESET_REASON
>        Clarify CPU run/sleep mode
>        Add note for CPU protocol to indicate AP using PSCI, non-AP use OS.
>        Specify mandatory for each command in LMM/CPU per firmware owner.
>        For BBM/MISC which have optional command, I will update doc in separate patch later
>Patch 2: Add description in binding doc
>Patch 3: Unify scmi_imx_lmm_[boot,power_on], Use le32_get_bits
>Patch 4: Unify scmi_imx_cpu_[start,stop], Use le32_encode_bits
>	 Add pointer check in scmi_imx_cpu_started
>	 correct nr_cpus calculation
>Patch 5: Unify lmm shutdown,boot/power_on, update kconfig to avoid build bot issue
>         Add R-b
>Patch 6: Unity cpu start/stop, update Kconfig to avoid build bot issue.
>         Add R-b
>
>Ran smatch as below, no issue found.
>~/smatch/smatch_scripts/kchecker drivers/firmware/arm_scmi/vendors/imx/
>~/smatch/smatch_scripts/kchecker drivers/firmware/imx/
>
>- Link to v2: https://lore.kernel.org/r/20250212-imx-lmm-cpu-v2-0-3aee005968c1 at nxp.com
>
>Changes in v2:
>- Add dt-bindings patch 2
>- Add a maintainer entry with patch 7
>- Update doc to address various questions and make it clear
>- Use strscpy to use scmi server returned string
>- Drop extra blank line
>- Shrink scmi_imx_cpu_attributes_get function args.
>- Typo fixes
>- Add LMM_RESET_VECTOR_SET
>- Link to v1: https://lore.kernel.org/r/20250121-imx-lmm-cpu-v1-0-0eab7e073e4e at nxp.com
>
>---
>Peng Fan (7):
>      firmware: arm_scmi: imx: Add LMM and CPU documentation
>      dt-bindings: firmware: Add i.MX95 SCMI LMM and CPU protocol
>      firmware: arm_scmi: imx: Add i.MX95 LMM protocol
>      firmware: arm_scmi: imx: Add i.MX95 CPU Protocol
>      firmware: imx: Add i.MX95 SCMI LMM driver
>      firmware: imx: Add i.MX95 SCMI CPU driver
>      MAINTAINERS: add entry for i.MX SCMI extensions
>
> .../bindings/firmware/nxp,imx95-scmi.yaml          |  23 +
> MAINTAINERS                                        |   9 +
> drivers/firmware/arm_scmi/vendors/imx/Kconfig      |  24 +
> drivers/firmware/arm_scmi/vendors/imx/Makefile     |   2 +
> drivers/firmware/arm_scmi/vendors/imx/imx-sm-cpu.c | 276 +++++++
> drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c | 257 +++++++
> drivers/firmware/arm_scmi/vendors/imx/imx95.rst    | 801 +++++++++++++++++++++
> drivers/firmware/imx/Kconfig                       |  22 +
> drivers/firmware/imx/Makefile                      |   2 +
> drivers/firmware/imx/sm-cpu.c                      |  85 +++
> drivers/firmware/imx/sm-lmm.c                      |  91 +++
> include/linux/firmware/imx/sm.h                    |  19 +
> include/linux/scmi_imx_protocol.h                  |  42 ++
> 13 files changed, 1653 insertions(+)
>---
>base-commit: fb2b3e3bd74b8a3f742eaade06f6565323cf4bdf
>change-id: 20250120-imx-lmm-cpu-418daaa257e2
>
>Best regards,
>-- 
>Peng Fan <peng.fan at nxp.com>
>


From michal.simek at amd.com  Tue Mar 18 00:36:22 2025
From: michal.simek at amd.com (Michal Simek)
Date: Tue, 18 Mar 2025 08:36:22 +0100
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <a9812897-2c79-4a1c-9431-c6f184233a57@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
 <20250314211411.l5taj5nysvcalfyz@synopsys.com>
 <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>
 <20250318001211.tnjwfckt5j4fbvjf@synopsys.com>
 <a9812897-2c79-4a1c-9431-c6f184233a57@topic.nl>
Message-ID: <a8be82ee-b6c8-4308-bf3a-d18050dd043a@amd.com>

+Radhey

On 3/18/25 07:21, Mike Looijmans wrote:
> On 18-03-2025 01:12, Thinh Nguyen wrote:
>> On Mon, Mar 17, 2025, Mike Looijmans wrote:
>>> On 14-03-2025 22:14, Thinh Nguyen wrote:
>>>> On Fri, Mar 14, 2025, Mike Looijmans wrote:
>>>>> Set the gpio to "high" on acquisition, instead of acquiring it in low
>>>>> state and then immediately setting it high again. This prevents a
>>>>> short "spike" on the reset signal.
>>>> How does this affect the current programming flow beside preventing a
>>>> spike to the reset signal?
>>> I don't understand your question. What "programming flow" are you referring
>>> to?
>> It's not obvious to me if this is an error in Xilinx documentation, the
>> driver issue, or whether this is found through experiment. Since I don't
>> have the info of this platform, it would help to know where the source
>> of error is so we can document this in the code or change-log.
> 
> It's a bug in the driver, found through code inspection.
> 
> The reset GPIO here is to control the reset signal to an external, usually ULPI 
> PHY, chip. This external chip is not part of the Xilinx hardware.
> 
>>> The reset sequence was just plain wrong, the issue is almost the same as the
>> Do we need a fix tag and add to stable then?
> 
> That would be appropriate I think.
> 
> 
>>
>>> one described in this commit:
>>> e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"
>>>
>>> Note that I see this high-low-high-low double reset toggle in many Xilinx
>>> software drivers, they seem to teach that at the Xilinx academy or so.
>>>
>>>
>>>>> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
>>>>> ---
>>>>>
>>>>> ?? drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
>>>>> ?? 1 file changed, 1 insertion(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
>>>>> index a33a42ba0249..a159a511483b 100644
>>>>> --- a/drivers/usb/dwc3/dwc3-xilinx.c
>>>>> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
>>>>> @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx 
>>>>> *priv_data)
>>>>> ?? skip_usb3_phy:
>>>>> ?????? /* ulpi reset via gpio-modepin or gpio-framework driver */
>>>>> -??? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>>>>> +??? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>>>>> ?????? if (IS_ERR(reset_gpio)) {
>>>>> ?????????? return dev_err_probe(dev, PTR_ERR(reset_gpio),
>>>>> ??????????????????????? "Failed to request reset GPIO\n");
>>>>> @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx 
>>>>> *priv_data)
>>>>> ?????? if (reset_gpio) {
>>>>> ?????????? /* Toggle ulpi to reset the phy. */
>>>> Does the comment above still apply?
>>> Now you mention it, the comment never made any sense anyway.
>>>
>> Then can we remove it?
> 
> Removing would be better, yes. I'll make a v2 patch.
> 
> 
>>>>> -??????? gpiod_set_value_cansleep(reset_gpio, 1);
>>>>> ?????????? usleep_range(5000, 10000);
>>>> Do we still need this usleep_range here?
>>> Yes, this is the "reset active" time.
>>>
>> But why do we need 2 calls to usleep_range? From just looking at this
>> here, it appears that the first was intended for the removed
>> gpiod_set_value_cansleep(reset_gpio, 1). If this "reset active" time is
>> needed irrespective of the existent reset_gpio, then shouldn't it be set
>> outside of this if statement?
> 
> It helps to see the whole thing instead of just the patch.
> 
> If I omit error handling and comments then the original code reads:
> 
>  ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>  ??????? if (reset_gpio) {
>  ??????????????? gpiod_set_value_cansleep(reset_gpio, 1);
>  ??????????????? usleep_range(5000, 10000);
>  ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
>  ??????????????? usleep_range(5000, 10000);
>  ??????? }
> 
> So the gpio is acquired in a LOW state and then, without delay, is set to a high 
> state again. This causes the "spike" I'm mentioning here. The correct procedure 
> is to acquire it in the HIGH state immediately, so the sequence becomes:
> 
>  ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>  ??????? if (reset_gpio) {
>  ??????????????? usleep_range(5000, 10000);
>  ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
>  ??????????????? usleep_range(5000, 10000);
>  ??????? }
> 
> This patch does exactly that.

Please keep Radhey in loop. He will take a look at it from our side.

Thanks,
Michal


From michal.simek at amd.com  Tue Mar 18 00:36:49 2025
From: michal.simek at amd.com (Michal Simek)
Date: Tue, 18 Mar 2025 08:36:49 +0100
Subject: [PATCH v2] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <20250318064518.9320-1-mike.looijmans@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.92a20336-7677-4cd7-9893-b0e0da853ba9@emailsignatures365.codetwo.com>
 <20250318064518.9320-1-mike.looijmans@topic.nl>
Message-ID: <b106b46b-f00f-40bc-aafc-f57a879fe090@amd.com>

+Radhey

On 3/18/25 07:44, Mike Looijmans wrote:
> The "reset" GPIO controls the RESET signal to an external, usually
> ULPI PHY, chip. The original code path acquires the signal in LOW
> state, and then immediately asserts it HIGH again, if the reset
> signal defaulted to asserted, there'd be a short "spike" before the
> reset.
> 
> Here is what happens depending on the pre-existing state of the reset
> signal:
> Reset (previously asserted):   ~~~|_|~~~~|_______
> Reset (previously deasserted): _____|~~~~|_______
>                                    ^ ^    ^
>                                    A B    C
> 
> At point A, the low going transition is because the reset line is
> requested using GPIOD_OUT_LOW. If the line is successfully requested,
> the first thing we do is set it high _without_ any delay. This is
> point B. So, a glitch occurs between A and B.
> 
> Requesting the line using GPIOD_OUT_HIGH eliminates the A and B
> transitions. Instead we get:
> 
> Reset (previously asserted)  : ~~~~~~~~~~|______
> Reset (previously deasserted): ____|~~~~~|______
>                                     ^     ^
>                                     A     C
> 
> Where A and C are the points described above in the code. Point B
> has been eliminated.
> 
> The issue was found during code inspection.
> 
> Also remove the cryptic "toggle ulpi .." comment.
> 
> Fixes: ca05b38252d7 ("usb: dwc3: xilinx: Add gpio-reset support")
> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> ---
> 
> Changes in v2:
> Add "Fixes" tag
> Remove "toggle ulpi" comment
> Extend comment to explain what is happening in detail
> 
>   drivers/usb/dwc3/dwc3-xilinx.c | 4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> index a33a42ba0249..4ca7f6240d07 100644
> --- a/drivers/usb/dwc3/dwc3-xilinx.c
> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> @@ -207,15 +207,13 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>   
>   skip_usb3_phy:
>   	/* ulpi reset via gpio-modepin or gpio-framework driver */
> -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>   	if (IS_ERR(reset_gpio)) {
>   		return dev_err_probe(dev, PTR_ERR(reset_gpio),
>   				     "Failed to request reset GPIO\n");
>   	}
>   
>   	if (reset_gpio) {
> -		/* Toggle ulpi to reset the phy. */
> -		gpiod_set_value_cansleep(reset_gpio, 1);
>   		usleep_range(5000, 10000);
>   		gpiod_set_value_cansleep(reset_gpio, 0);
>   		usleep_range(5000, 10000);



From wenst at chromium.org  Tue Mar 18 00:44:00 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Tue, 18 Mar 2025 15:44:00 +0800
Subject: [PATCH RFC v2 0/3] add VCP mailbox and IPC driver
In-Reply-To: <375d5281-41f5-49e8-ac20-d58931c0c1f9@collabora.com>
References: <20250317083822.891-1-jjian.zhou@mediatek.com> <375d5281-41f5-49e8-ac20-d58931c0c1f9@collabora.com>
Message-ID: <CAGXv+5G4KRbv=qcKurn5u300XPp4KNovmUD9OBfX7mKk57tucg@mail.gmail.com>

On Mon, Mar 17, 2025 at 6:07?PM AngeloGioacchino Del Regno
<angelogioacchino.delregno at collabora.com> wrote:
>
> Il 17/03/25 09:38, Jjian Zhou ha scritto:
> > The VCP mailbox has 5 groups. Each group has corresponding interrupts,
> > registers, and 64 slots (each slot is 4 bytes). Since different features
> > share one of the mailbox groups, the VCP mailbox needs to establish a
> > send table and a receive table. The send table is used to record the
> > feature ID, mailbox ID, and the number of slots occupied. The receive table
> > is used to record the feature ID, mailbox ID, the number of slots occupied,
> > and the receive options. The API setup_mbox_table in mtk-vcp-ipc.c calculates
> > the slot offset and pin index for each feature ID based on the mailbox ID and
> > slot number in the send and receive tables (several slots form a pin, and
> > each pin can trigger an interrupt). These descriptions are written in the
> > mtk-vcp-ipc.c file -- we call it the IPC layer.
> >
> > We have two questions:
> > How should we describe the mailbox and IPI?
> > Can the intermediate IPC layer be rewritten as a virtual mailbox layer?
> >
>
> So, for this remote processor messaging system you have:
>   - Dynamic channel allocation
>     - Each channel has its own endpoint

The rpmsg model has:

- device -> the remote processor
- channel
- endpoint

However here for the VCP and possibly all the coprocessors using the
tinysys model, channel and endpoint are basically the same. If we
consider the "channel" to be the storage plus the interrupt vector,
and the "endpoint" to be the function running on the remote processor
servicing a given IPI ID, then it's always one endpoint per channel.

IMHO rpmsg gives too much latitude to make things confusing here.

rpmsg also requires the remote processor to support name service
announcements, which really doesn't exist. The endpoints and how
they map to the various hardware mailbox interrupt vectors and
storage is statically allocated, and thus needs to be described
in the driver.

>     - Each channel has its own interrupt
>   - Data send operation
>     - Both with and without ACK indication from the remote processor
>     - To channel -> endpoint
>   - Data receive operation
>     - From channel <- endpoint
>     - When interrupt fires
>     - Could use polling to avoid blocking in a few cases
>   - A custom message structure not adhering to any standard
>
> Check drivers/rpmsg/ :-)

While discussing this internally, I felt like that wasn't a really
correct model. IIUC rpmsg was first created to allow userspace to
pass messages to the remote processor. Then somehow devices were
being created on top of those channels.

Also, the existing mtk_rpmsg driver seemed a bit weird, like requiring
a DT node for each rpmsg endpoint.

That's why I thought mailboxes made more sense, as the terminology mapped
better. As a result I never brought up rpmsg in the discussion.

Perhaps that could be improved with better documentation for the MediaTek
specific implementation.

> On MediaTek platforms, there are many IPI to handle in many subsystems for
> all of the remote processors that are integrated in the SoC and, at this
> point, you might as well just aggregate all of the inter processor communication
> stuff in one place, having an API that is made just exactly for that, instead
> of keeping to duplicate the IPI stuff over and over (and yes I know that for each
> remote processor the TX/RX is slightly different).
>
> If you aggregate the IPI messaging in one place, maintenance is going to be easier,
> and we stop getting duplication... more or less like it was done with the mtk_scp
> IPI and mtk-vcodec .. and that's also something that is partially handled as RPMSG
> because, well, it is a remote processor messaging driver.
>
> Just to make people understand *how heavily* MediaTek SoCs rely on IPI, there's
> a *partial* list of SoC IPs that use IPI communcation:
>
> thermal, ccu, ccd, tinysys, vcp, atsp, sspm, slbc, mcupm, npu, mvpu, aps, mdla,
> qos, audio, cm_mgr.... and... again, it's a partial list!

Indeed, the newest chip has become quite complicated.

> That said... any other opinion from anyone else?

I tried to describe why I thought a virtual mailbox was better.


Thanks
ChenYu

> Cheers,
> Angelo
>
> > Example of send and recve table:
> > Operation | mbox_id | ipi_id | msg_size | align_size | slot_ofs | pin_index |  notes
> > send          0          0       18          18           0          0
> > recv          0          1       18          18          18          9
> > send          1         15        8           8           0          0
> > send          1         16       18          18           8          4
> > send          1          9        2           2          26         13
> > recv          1         15        8           8          28         14       ack of send ipi_id=15
> > recv          1         17       18          18          36         18
> > recv          1         10        2           2          54         27       ack of send ipi_id=2
> > send          2         11       18          18           0          0
> > send          2          2        2           2          18          9
> > send          2          3        3           4          20         10
> > send          2         32        2           2          24         12
> > recv          2         12       18          18          26         13
> > recv          2          5        1           2          44         22
> > recv          2          2        1           2          46         23
> >
> > Recv ipi_id=2 is the ack of send ipi_id=2(The ipi_id=15 is the same.)
> >
> > Jjian Zhou (3):
> >    mailbox: mediatek: Add mtk-vcp-mailbox driver
> >    firmware: mediatek: Add vcp ipc protocol interface
> >    dt-bindings: mailbox: mtk,vcp-mbox: add mtk vcp-mbox document
> >
> >   .../bindings/mailbox/mtk,mt8196-vcp-mbox.yaml |  49 ++
> >   drivers/firmware/Kconfig                      |   9 +
> >   drivers/firmware/Makefile                     |   1 +
> >   drivers/firmware/mtk-vcp-ipc.c                | 481 ++++++++++++++++++
> >   drivers/mailbox/Kconfig                       |   9 +
> >   drivers/mailbox/Makefile                      |   2 +
> >   drivers/mailbox/mtk-vcp-mailbox.c             | 179 +++++++
> >   include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
> >   include/linux/mailbox/mtk-vcp-mailbox.h       |  34 ++
> >   9 files changed, 915 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/mailbox/mtk,mt8196-vcp-mbox.yaml
> >   create mode 100644 drivers/firmware/mtk-vcp-ipc.c
> >   create mode 100644 drivers/mailbox/mtk-vcp-mailbox.c
> >   create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
> >   create mode 100644 include/linux/mailbox/mtk-vcp-mailbox.h
> >
>
>
>


From oliver.upton at linux.dev  Tue Mar 18 00:47:36 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Tue, 18 Mar 2025 00:47:36 -0700
Subject: [PATCH] KVM: arm64: Tear down vGIC on failed vCPU creation
In-Reply-To: <20250314133409.9123-1-will@kernel.org>
References: <20250314133409.9123-1-will@kernel.org>
Message-ID: <174228404857.1652170.4192050516109561246.b4-ty@linux.dev>

On Fri, 14 Mar 2025 13:34:09 +0000, Will Deacon wrote:
> If kvm_arch_vcpu_create() fails to share the vCPU page with the
> hypervisor, we propagate the error back to the ioctl but leave the
> vGIC vCPU data initialised. Note only does this leak the corresponding
> memory when the vCPU is destroyed but it can also lead to use-after-free
> if the redistributor device handling tries to walk into the vCPU.
> 
> Add the missing cleanup to kvm_arch_vcpu_create(), ensuring that the
> vGIC vCPU structures are destroyed on error.
> 
> [...]

Applied to next, thanks!

[1/1] KVM: arm64: Tear down vGIC on failed vCPU creation
      https://git.kernel.org/kvmarm/kvmarm/c/250f25367b58

--
Best,
Oliver


From manivannan.sadhasivam at linaro.org  Tue Mar 18 00:46:18 2025
From: manivannan.sadhasivam at linaro.org (manivannan.sadhasivam at linaro.org)
Date: Tue, 18 Mar 2025 13:16:18 +0530
Subject: [PATCH v1 2/2] PCI: imx6: Use domain number replace the hardcodes
In-Reply-To: <20250313160648.GA736867@bhelgaas>
References: <b425a7c7a7d6508daf23fe7046864a498029a7ac.camel@pengutronix.de>
 <20250313160648.GA736867@bhelgaas>
Message-ID: <20250318074618.tqbnr7nv665fk25n@thinkpad>

On Thu, Mar 13, 2025 at 11:06:48AM -0500, Bjorn Helgaas wrote:
> On Thu, Mar 13, 2025 at 09:54:25AM +0100, Lucas Stach wrote:
> > Am Mittwoch, dem 12.03.2025 um 10:22 -0400 schrieb Frank Li:
> > > On Wed, Mar 12, 2025 at 09:28:02AM +0100, Lucas Stach wrote:
> > > > Am Mittwoch, dem 12.03.2025 um 04:05 +0000 schrieb Hongxing Zhu:
> > > > > > -----Original Message-----
> > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > Sent: 2025?3?11? 23:55
> > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org; bhelgaas at google.com;
> > > > > > s.hauer at pengutronix.de; festevam at gmail.com; devicetree at vger.kernel.org;
> > > > > > linux-pci at vger.kernel.org; imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > hardcodes
> > > > > > 
> > > > > > On Tue, Mar 11, 2025 at 01:11:04AM +0000, Hongxing Zhu wrote:
> > > > > > > > -----Original Message-----
> > > > > > > > From: Bjorn Helgaas <helgaas at kernel.org>
> > > > > > > > Sent: 2025?3?10? 23:11
> > > > > > > > To: Hongxing Zhu <hongxing.zhu at nxp.com>
> > > > > > > > Cc: robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> > > > > > > > shawnguo at kernel.org; l.stach at pengutronix.de; lpieralisi at kernel.org;
> > > > > > > > kw at linux.com; manivannan.sadhasivam at linaro.org;
> > > > > > bhelgaas at google.com;
> > > > > > > > s.hauer at pengutronix.de; festevam at gmail.com;
> > > > > > > > devicetree at vger.kernel.org; linux-pci at vger.kernel.org;
> > > > > > > > imx at lists.linux.dev; kernel at pengutronix.de;
> > > > > > > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > > > > > > Subject: Re: [PATCH v1 2/2] PCI: imx6: Use domain number replace the
> > > > > > > > hardcodes
> > > > > > > > 
> > > > > > > > On Wed, Feb 26, 2025 at 10:42:56AM +0800, Richard Zhu wrote:
> > > > > > > > > Use the domain number replace the hardcodes to uniquely identify
> > > > > > > > > different controller on i.MX8MQ platforms. No function changes.
> > > > > > > > > 
> > > > > > > > > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > > > > > > > > ---
> > > > > > > > > ?drivers/pci/controller/dwc/pci-imx6.c | 14 ++++++--------
> > > > > > > > > ?1 file changed, 6 insertions(+), 8 deletions(-)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > index 90ace941090f..ab9ebb783593 100644
> > > > > > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > > > > > > @@ -41,7 +41,6 @@
> > > > > > > > > ?#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE	BIT(11)
> > > > > > > > > ?#define IMX8MQ_GPR_PCIE_VREG_BYPASS		BIT(12)
> > > > > > > > > ?#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE	GENMASK(11,
> > > > > > 8)
> > > > > > > > > -#define IMX8MQ_PCIE2_BASE_ADDR			0x33c00000
> > > > > > > > > 
> > > > > > > > > ?#define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > > > > > > > > ?#define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > > > > > > > > @@ -1474,7 +1473,6 @@ static int imx_pcie_probe(struct
> > > > > > > > > platform_device
> > > > > > > > *pdev)
> > > > > > > > > ?	struct dw_pcie *pci;
> > > > > > > > > ?	struct imx_pcie *imx_pcie;
> > > > > > > > > ?	struct device_node *np;
> > > > > > > > > -	struct resource *dbi_base;
> > > > > > > > > ?	struct device_node *node = dev->of_node;
> > > > > > > > > ?	int i, ret, req_cnt;
> > > > > > > > > ?	u16 val;
> > > > > > > > > @@ -1515,10 +1513,6 @@ static int imx_pcie_probe(struct
> > > > > > > > platform_device *pdev)
> > > > > > > > > ?			return PTR_ERR(imx_pcie->phy_base);
> > > > > > > > > ?	}
> > > > > > > > > 
> > > > > > > > > -	pci->dbi_base = devm_platform_get_and_ioremap_resource(pdev,
> > > > > > 0,
> > > > > > > > &dbi_base);
> > > > > > > > > -	if (IS_ERR(pci->dbi_base))
> > > > > > > > > -		return PTR_ERR(pci->dbi_base);
> > > > > > > > 
> > > > > > > > This makes me wonder.
> > > > > > > > 
> > > > > > > > IIUC this means that previously we set controller_id to
> > > > > > > > 1 if the first item in devicetree "reg" was 0x33c00000,
> > > > > > > > and now we will set controller_id to 1 if the devicetree
> > > > > > > > "linux,pci-domain" property is 1.  This is good, but I
> > > > > > > > think this new dependency on the correct
> > > > > > > > "linux,pci-domain" in devicetree should be mentioned in
> > > > > > > > the commit log.
> > > > > > > > 
> > > > > > > > My bigger worry is that we no longer set pci->dbi_base
> > > > > > > > at all.  I see that the only use of pci->dbi_base in
> > > > > > > > pci-imx6.c was to determine the controller_id, but this
> > > > > > > > is a DWC-based driver, and the DWC core certainly uses
> > > > > > > > pci->dbi_base.  Are we sure that none of those DWC core
> > > > > > > > paths are important to pci-imx6.c?
> > > > > > >
> > > > > > > Thanks for your concerns.  Don't worry about the
> > > > > > > assignment of pci->dbi_base.  If pci-imx6.c driver doesn't
> > > > > > > set it. DWC core driver would set it when
> > > > > > > ?dw_pcie_get_resources() is invoked.
> > > > > > 
> > > > > > Great, thanks!  Maybe we can amend the commit log to mention
> > > > > > that and the new "linux,pci-domain" dependency.
> > > > >
> > > > > How about the following updates of the commit log?
> > > > > 
> > > > > Use the domain number replace the hardcodes to uniquely
> > > > > identify different controller on i.MX8MQ platforms. No
> > > > > function changes.  Please make sure the " linux,pci-domain" is
> > > > > set for i.MX8MQ correctly, since ?the controller id is relied
> > > > > on it totally.
> > > > > 
> > > > This breaks running a new kernel on an old DT without the
> > > > linux,pci-domain property, which I'm absolutely no fan of. We
> > > > tried really hard to keep this way around working in the i.MX
> > > > world.
> > > 
> > > 8MQ already add linux,pci-domain since Jan, 2021
> > > 
> > > commit c0b70f05c87f3b09b391027c6f056d0facf331ef
> > > Author: Peng Fan <peng.fan at nxp.com>
> > > Date:   Fri Jan 15 11:26:57 2021 +0800
> > > 
> > > Only missed is pcie-ep side, which have not been used at all boards dts
> > > file in upstream.
> > 
> > I wasn't aware of this. 2021 is quite a while ago, so I suspect that
> > nobody is going to run a new kernel with a DT this old. I retract my
> > objection.
> 
> Sounds good, thanks, Lucas.  We really do want to avoid breaking old
> DTs, so I appreciate your highlighting of it.  Even if we believe none
> of them will break, I think it's worth mentioning the
> 'linux,pci-domain' dependency and the commit that added it to the
> .dtsi in the commit log.
> 

If there is a dependency, then it should be added to the binding. Only that will
ensure that the DTs will have the dependent property present.

- Mani

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Tue Mar 18 00:49:17 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 18 Mar 2025 13:19:17 +0530
Subject: [PATCH 1/4] PCI: cadence: Add support to build pcie-cadence
 library as a kernel module
In-Reply-To: <20250314065444.fmvhyqmuefnm4mcq@uda0492258>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-2-s-vadapalli@ti.com>
 <20250313174416.n3c4srf6hb2l3bvg@thinkpad>
 <20250314065444.fmvhyqmuefnm4mcq@uda0492258>
Message-ID: <20250318074917.inhspuuypxmaioqe@thinkpad>

On Fri, Mar 14, 2025 at 12:24:44PM +0530, Siddharth Vadapalli wrote:
> On Thu, Mar 13, 2025 at 11:14:16PM +0530, Manivannan Sadhasivam wrote:
> 
> Hello Mani,
> 
> > On Fri, Mar 07, 2025 at 04:01:25PM +0530, Siddharth Vadapalli wrote:
> > > From: Kishon Vijay Abraham I <kishon at ti.com>
> > > 
> > > Currently, the Cadence PCIe controller driver can be built as a built-in
> > > module only. Since PCIe functionality is not a necessity for booting, add
> > > support to build the Cadence PCIe driver as a loadable module as well.
> > > 
> > > Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > 
> > Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> > 
> > > ---
> > >  drivers/pci/controller/cadence/Kconfig             |  6 +++---
> > >  drivers/pci/controller/cadence/pcie-cadence-ep.c   |  6 ++++++
> > >  drivers/pci/controller/cadence/pcie-cadence-host.c |  9 +++++++++
> > >  drivers/pci/controller/cadence/pcie-cadence.c      | 12 ++++++++++++
> > >  drivers/pci/controller/cadence/pcie-cadence.h      |  4 ++--
> > >  5 files changed, 32 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
> > > index 8a0044bb3989..82b58096eea0 100644
> > > --- a/drivers/pci/controller/cadence/Kconfig
> > > +++ b/drivers/pci/controller/cadence/Kconfig
> > > @@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
> > >  	depends on PCI
> > >  
> > >  config PCIE_CADENCE
> > > -	bool
> > > +	tristate
> > >  
> > >  config PCIE_CADENCE_HOST
> > > -	bool
> > > +	tristate
> > >  	depends on OF
> > >  	select IRQ_DOMAIN
> > 
> > Even though this was added earlier, looks like not needed.
> 
> Thank you for reviewing this patch.
> 
> drivers/pci/controller/cadence/Kconfig has the following:
> ...
> 	config PCIE_CADENCE_HOST
> 		bool
> 		depends on OF
> 		select IRQ_DOMAIN
> 		select PCIE_CADENCE
> ...
> 	config PCI_J721E_HOST
> 		bool "TI J721E PCIe controller (host mode)"
> 		depends on ARCH_K3 || COMPILE_TEST
> 		depends on OF
> 		select PCIE_CADENCE_HOST
> 		select PCI_J721E
> ...
> So PCI_J721E_HOST selects PCIE_CADENCE_HOST which in turn selects
> PCIE_CADENCE. As of now, none of these configs are enabled in
> arm64-defconfig, and they also will not be accepted as built-in modules
> as it will bloat the Linux Image for everyone. For that reason, they are
> all being converted to loadable modules, and their configs will eventually
> be enabled in arm64-defconfig as loadable modules.
> 
> Please let me know if I misunderstood your comment regarding the quoted
> change not being required.
> 

Yes, you misunderstood indeed :) My earlier comment was about IRQ_DOMAIN symbol
which looked like not needed at all.

- Mani

-- 
????????? ????????


From krzysztof.kozlowski at linaro.org  Tue Mar 18 01:07:38 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 09:07:38 +0100
Subject: [PATCH] drm/exynos: exynos7_drm_decon: Consstify struct decon_data
Message-ID: <20250318080738.29292-1-krzysztof.kozlowski@linaro.org>

static 'struct decon_data' is only read, so it can be const for code
safety.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/gpu/drm/exynos/exynos7_drm_decon.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 5170f72b0830..f91daefa9d2b 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -43,13 +43,13 @@ struct decon_data {
 	unsigned int wincon_burstlen_shift;
 };
 
-static struct decon_data exynos7_decon_data = {
+static const struct decon_data exynos7_decon_data = {
 	.vidw_buf_start_base = 0x80,
 	.shadowcon_win_protect_shift = 10,
 	.wincon_burstlen_shift = 11,
 };
 
-static struct decon_data exynos7870_decon_data = {
+static const struct decon_data exynos7870_decon_data = {
 	.vidw_buf_start_base = 0x880,
 	.shadowcon_win_protect_shift = 8,
 	.wincon_burstlen_shift = 10,
-- 
2.43.0



From claudiu.manoil at nxp.com  Tue Mar 18 01:08:24 2025
From: claudiu.manoil at nxp.com (Claudiu Manoil)
Date: Tue, 18 Mar 2025 08:08:24 +0000
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <20250317141807.2zobsefxl5vnqdet@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
 <20250317141807.2zobsefxl5vnqdet@skbuf>
Message-ID: <AS8PR04MB8849FBA73A50F0D553F1AF1B96DE2@AS8PR04MB8849.eurprd04.prod.outlook.com>


> -----Original Message-----
> From: Vladimir Oltean <vladimir.oltean at nxp.com>
> Sent: Monday, March 17, 2025 4:18 PM
[...]
> Subject: Re: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
> ENETC PF
> 
> On Tue, Mar 11, 2025 at 01:38:20PM +0800, Wei Fang wrote:
[...]
> > +static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
> > +{
> > +	struct enetc_mac_list_entry *entry;
> > +	struct hlist_node *tmp;
> > +
> > +	mutex_lock(&pf->mac_list_lock);
> 
> The mutex_lock() usage here should raise serious questions. This is
> running right before mutex_destroy(). So if there were any concurrent
> attempt to acquire this lock, that concurrent code would have been broken
> any time it would have lost arbitration, by the fact that it would
> attempt to acquire a destroyed mutex.
> 
> But there's no such concurrent thread, because we run after destroy_workqueue()
> which flushes those concurrent calls and prevents new ones. So the mutex
> usage here is not necessary.
> 
> [ same thing with mutex_init() immediately followed by mutex_lock().
>   It is an incorrect pattern most of the time. ]
> 

This is not as bad as it seems. In the final version of the code, mutex 'mac_list_lock'
serializes the access btw the thread programming the filter for the PF instance,
and the threads programming the filter on behalf of underlying VFs (triggered by async
request from VF). But since VF support is not included in this patch set (as Wei
already mentioned) the lock can/should be added later, with the VF patches.


From patchwork-bot+netdevbpf at kernel.org  Tue Mar 18 01:10:35 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 18 Mar 2025 08:10:35 +0000
Subject: [PATCH net-next v5 00/13] net: phy: Rework linkmodes handling in a
 dedicated file
In-Reply-To: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
References: <20250307173611.129125-1-maxime.chevallier@bootlin.com>
Message-ID: <174228543527.4071400.14783355936899188267.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri,  7 Mar 2025 18:35:57 +0100 you wrote:
> Hello everyone,
> 
> This is V5 of the phy_caps series. In a nutshell, this series reworks the way
> we maintain the list of speed/duplex capablities for each linkmode so that we
> no longer have multiple definition of these associations.
> 
> That will help making sure that when people add new linkmodes in
> include/uapi/linux/ethtool.h, they don't have to update phylib and phylink as
> well, making the process more straightforward and less error-prone.
> 
> [...]

Here is the summary with links:
  - [net-next,v5,01/13] net: ethtool: Export the link_mode_params definitions
    https://git.kernel.org/netdev/net-next/c/79f88a584e35
  - [net-next,v5,02/13] net: phy: Use an internal, searchable storage for the linkmodes
    https://git.kernel.org/netdev/net-next/c/d8c838a57ce2
  - [net-next,v5,03/13] net: phy: phy_caps: Move phy_speeds to phy_caps
    https://git.kernel.org/netdev/net-next/c/8c8c4a87933d
  - [net-next,v5,04/13] net: phy: phy_caps: Move __set_linkmode_max_speed to phy_caps
    https://git.kernel.org/netdev/net-next/c/4823ed060919
  - [net-next,v5,05/13] net: phy: phy_caps: Introduce phy_caps_valid
    https://git.kernel.org/netdev/net-next/c/87b22ce31235
  - [net-next,v5,06/13] net: phy: phy_caps: Implement link_capabilities lookup by linkmode
    https://git.kernel.org/netdev/net-next/c/dbcd85b05c5b
  - [net-next,v5,07/13] net: phy: phy_caps: Allow looking-up link caps based on speed and duplex
    https://git.kernel.org/netdev/net-next/c/fc81e257d19f
  - [net-next,v5,08/13] net: phy: phy_device: Use link_capabilities lookup for PHY aneg config
    https://git.kernel.org/netdev/net-next/c/c7ae89c6b4d5
  - [net-next,v5,09/13] net: phylink: Use phy_caps_lookup for fixed-link configuration
    https://git.kernel.org/netdev/net-next/c/de7d3f87be3c
  - [net-next,v5,10/13] net: phy: drop phy_settings and the associated lookup helpers
    https://git.kernel.org/netdev/net-next/c/ce60fef7fecc
  - [net-next,v5,11/13] net: phylink: Add a mapping between MAC_CAPS and LINK_CAPS
    https://git.kernel.org/netdev/net-next/c/3bea75002a05
  - [net-next,v5,12/13] net: phylink: Convert capabilities to linkmodes using phy_caps
    https://git.kernel.org/netdev/net-next/c/4ca5b8a258b6
  - [net-next,v5,13/13] net: phylink: Use phy_caps to get an interface's capabilities and modes
    https://git.kernel.org/netdev/net-next/c/3bd87f3b4405

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From krzk at kernel.org  Tue Mar 18 00:55:01 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 08:55:01 +0100
Subject: [PATCH 1/9] dt-bindings: soc: qcom,rpm: add missing
 clock-controller node
In-Reply-To: <20250317-fix-nexus-4-v1-1-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-1-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250318-hungry-nimble-marten-dfb4db@krzk-bin>

On Mon, Mar 17, 2025 at 07:44:36PM +0200, Dmitry Baryshkov wrote:
> On Qualcomm platforms in addition to regulators the RPM also provides
> clocks via the child clock-controller node. Describe it properly in the
> schema.
> 
> Fixes: 6b42133d2189 ("dt-bindings: soc: qcom: convert non-smd RPM bindings to dt-schema")

Fixes should rather point to original binding, because the conversion
did not miss them. They were not there in the first place. Coversion
should add them, to match existing DTS, but still the mistake is in the
TXT binding.


> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml | 8 ++++++++
>  1 file changed, 8 insertions(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From s-vadapalli at ti.com  Tue Mar 18 00:55:30 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 18 Mar 2025 13:25:30 +0530
Subject: [PATCH 1/4] PCI: cadence: Add support to build pcie-cadence
 library as a kernel module
In-Reply-To: <20250318074917.inhspuuypxmaioqe@thinkpad>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-2-s-vadapalli@ti.com>
 <20250313174416.n3c4srf6hb2l3bvg@thinkpad>
 <20250314065444.fmvhyqmuefnm4mcq@uda0492258>
 <20250318074917.inhspuuypxmaioqe@thinkpad>
Message-ID: <20250318075530.ca663uwlj7uqf2tr@uda0492258>

On Tue, Mar 18, 2025 at 01:19:17PM +0530, Manivannan Sadhasivam wrote:
> On Fri, Mar 14, 2025 at 12:24:44PM +0530, Siddharth Vadapalli wrote:
> > On Thu, Mar 13, 2025 at 11:14:16PM +0530, Manivannan Sadhasivam wrote:
> > 
> > Hello Mani,
> > 
> > > On Fri, Mar 07, 2025 at 04:01:25PM +0530, Siddharth Vadapalli wrote:
> > > > From: Kishon Vijay Abraham I <kishon at ti.com>
> > > > 
> > > > Currently, the Cadence PCIe controller driver can be built as a built-in
> > > > module only. Since PCIe functionality is not a necessity for booting, add
> > > > support to build the Cadence PCIe driver as a loadable module as well.
> > > > 
> > > > Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> > > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > > 
> > > Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
> > > 
> > > > ---
> > > >  drivers/pci/controller/cadence/Kconfig             |  6 +++---
> > > >  drivers/pci/controller/cadence/pcie-cadence-ep.c   |  6 ++++++
> > > >  drivers/pci/controller/cadence/pcie-cadence-host.c |  9 +++++++++
> > > >  drivers/pci/controller/cadence/pcie-cadence.c      | 12 ++++++++++++
> > > >  drivers/pci/controller/cadence/pcie-cadence.h      |  4 ++--
> > > >  5 files changed, 32 insertions(+), 5 deletions(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
> > > > index 8a0044bb3989..82b58096eea0 100644
> > > > --- a/drivers/pci/controller/cadence/Kconfig
> > > > +++ b/drivers/pci/controller/cadence/Kconfig
> > > > @@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
> > > >  	depends on PCI
> > > >  
> > > >  config PCIE_CADENCE
> > > > -	bool
> > > > +	tristate
> > > >  
> > > >  config PCIE_CADENCE_HOST
> > > > -	bool
> > > > +	tristate
> > > >  	depends on OF
> > > >  	select IRQ_DOMAIN
> > > 
> > > Even though this was added earlier, looks like not needed.
> > 
> > Thank you for reviewing this patch.
> > 
> > drivers/pci/controller/cadence/Kconfig has the following:
> > ...
> > 	config PCIE_CADENCE_HOST
> > 		bool
> > 		depends on OF
> > 		select IRQ_DOMAIN
> > 		select PCIE_CADENCE
> > ...
> > 	config PCI_J721E_HOST
> > 		bool "TI J721E PCIe controller (host mode)"
> > 		depends on ARCH_K3 || COMPILE_TEST
> > 		depends on OF
> > 		select PCIE_CADENCE_HOST
> > 		select PCI_J721E
> > ...
> > So PCI_J721E_HOST selects PCIE_CADENCE_HOST which in turn selects
> > PCIE_CADENCE. As of now, none of these configs are enabled in
> > arm64-defconfig, and they also will not be accepted as built-in modules
> > as it will bloat the Linux Image for everyone. For that reason, they are
> > all being converted to loadable modules, and their configs will eventually
> > be enabled in arm64-defconfig as loadable modules.
> > 
> > Please let me know if I misunderstood your comment regarding the quoted
> > change not being required.
> > 
> 
> Yes, you misunderstood indeed :) My earlier comment was about IRQ_DOMAIN symbol
> which looked like not needed at all.

Thank you for clarifying. I (mis)interpret your comment in the context of
the entire "config PCIE_CADENCE_HOST" block and the change made in it :)

Regards,
Siddharth.


From manivannan.sadhasivam at linaro.org  Tue Mar 18 00:55:47 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 18 Mar 2025 13:25:47 +0530
Subject: [PATCH 2/4] PCI: cadence-host: Introduce cdns_pcie_host_disable
 helper for cleanup
In-Reply-To: <20250307103128.3287497-3-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-3-s-vadapalli@ti.com>
Message-ID: <20250318075547.wyijae6pumogkl4e@thinkpad>

On Fri, Mar 07, 2025 at 04:01:26PM +0530, Siddharth Vadapalli wrote:
> Introduce the helper function cdns_pcie_host_disable() which will undo
> the configuration performed by cdns_pcie_host_setup(). Also, export it
> for use by existing callers of cdns_pcie_host_setup(), thereby allowing
> them to cleanup on their exit path.
> 
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> ---
>  .../controller/cadence/pcie-cadence-host.c    | 104 ++++++++++++++++++
>  drivers/pci/controller/cadence/pcie-cadence.h |   5 +
>  2 files changed, 109 insertions(+)
> 
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
> index 96055edeb099..741508738f88 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-host.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
> @@ -152,6 +152,14 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie)
>  	return ret;
>  }
>  
> +static void cdns_pcie_host_disable_ptm_response(struct cdns_pcie *pcie)
> +{
> +	u32 val;
> +
> +	val = cdns_pcie_readl(pcie, CDNS_PCIE_LM_PTM_CTRL);
> +	cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val & ~CDNS_PCIE_LM_TPM_CTRL_PTMRSEN);
> +}
> +
>  static void cdns_pcie_host_enable_ptm_response(struct cdns_pcie *pcie)
>  {
>  	u32 val;
> @@ -177,6 +185,26 @@ static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
>  	return ret;
>  }
>  
> +static void cdns_pcie_host_deinit_root_port(struct cdns_pcie_rc *rc)
> +{
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	u32 value, ctrl;
> +
> +	cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, 0xffff);
> +	cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0xff);
> +	cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0xff);
> +	cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, 0xffffffff);
> +	cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, 0xffff);
> +	ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
> +	value = ~(CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
> +		CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
> +		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
> +		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
> +		CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
> +		CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS);
> +	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
> +}
> +
>  static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
>  {
>  	struct cdns_pcie *pcie = &rc->pcie;
> @@ -393,6 +421,32 @@ static int cdns_pcie_host_dma_ranges_cmp(void *priv, const struct list_head *a,
>          return resource_size(entry2->res) - resource_size(entry1->res);
>  }
>  
> +static void cdns_pcie_host_unmap_dma_ranges(struct cdns_pcie_rc *rc)
> +{
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	enum cdns_pcie_rp_bar bar;
> +	u32 value;
> +
> +	/* Reset inbound configuration for all BARs which were being used */
> +	for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
> +		if (rc->avail_ib_bar[bar])
> +			continue;
> +
> +		cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), 0);
> +		cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), 0);
> +
> +		if (bar == RP_NO_BAR)
> +			continue;
> +
> +		value = ~(LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar) |
> +			  LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar) |
> +			  LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar) |
> +			  LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar) |
> +			  LM_RC_BAR_CFG_APERTURE(bar, bar_aperture_mask[bar] + 2));
> +		cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
> +	}
> +}
> +
>  static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
>  {
>  	struct cdns_pcie *pcie = &rc->pcie;
> @@ -430,6 +484,29 @@ static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
>  	return 0;
>  }
>  
> +static void cdns_pcie_host_deinit_address_translation(struct cdns_pcie_rc *rc)
> +{
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
> +	struct resource_entry *entry;
> +	int r;
> +
> +	cdns_pcie_host_unmap_dma_ranges(rc);
> +
> +	/*
> +	 * Reset outbound region 0 which was reserved for configuration space
> +	 * accesses.
> +	 */
> +	cdns_pcie_reset_outbound_region(pcie, 0);
> +
> +	/* Reset rest of the outbound regions */
> +	r = 1;
> +	resource_list_for_each_entry(entry, &bridge->windows) {
> +		cdns_pcie_reset_outbound_region(pcie, r);
> +		r++;
> +	}
> +}
> +
>  static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
>  {
>  	struct cdns_pcie *pcie = &rc->pcie;
> @@ -487,6 +564,12 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
>  	return cdns_pcie_host_map_dma_ranges(rc);
>  }
>  
> +static void cdns_pcie_host_deinit(struct cdns_pcie_rc *rc)
> +{
> +	cdns_pcie_host_deinit_address_translation(rc);
> +	cdns_pcie_host_deinit_root_port(rc);
> +}
> +
>  int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
>  {
>  	int err;
> @@ -499,6 +582,14 @@ int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
>  }
>  EXPORT_SYMBOL_GPL(cdns_pcie_host_init);
>  
> +static void cdns_pcie_host_link_disable(struct cdns_pcie_rc *rc)
> +{
> +	struct cdns_pcie *pcie = &rc->pcie;
> +
> +	cdns_pcie_stop_link(pcie);
> +	cdns_pcie_host_disable_ptm_response(pcie);
> +}
> +
>  int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
>  {
>  	struct cdns_pcie *pcie = &rc->pcie;
> @@ -524,6 +615,19 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
>  }
>  EXPORT_SYMBOL_GPL(cdns_pcie_host_link_setup);
>  
> +void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
> +{
> +	struct pci_host_bridge *bridge;
> +
> +	bridge = pci_host_bridge_from_priv(rc);
> +	pci_stop_root_bus(bridge->bus);
> +	pci_remove_root_bus(bridge->bus);
> +
> +	cdns_pcie_host_deinit(rc);
> +	cdns_pcie_host_link_disable(rc);
> +}
> +EXPORT_SYMBOL_GPL(cdns_pcie_host_disable);
> +
>  int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>  {
>  	struct device *dev = rc->pcie.dev;
> diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
> index c671e25a481b..9068f140596a 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence.h
> +++ b/drivers/pci/controller/cadence/pcie-cadence.h
> @@ -523,6 +523,7 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
>  int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc);
>  int cdns_pcie_host_init(struct cdns_pcie_rc *rc);
>  int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
> +void cdns_pcie_host_disable(struct cdns_pcie_rc *rc);
>  void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
>  			       int where);
>  #else
> @@ -541,6 +542,10 @@ static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>  	return 0;
>  }
>  
> +static inline void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
> +{
> +}
> +
>  static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
>  					     int where)
>  {
> -- 
> 2.34.1
> 

-- 
????????? ????????


From krzk at kernel.org  Tue Mar 18 00:55:59 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 08:55:59 +0100
Subject: [PATCH 2/9] dt-bindings: display/msm: describe SFPB device
In-Reply-To: <20250317-fix-nexus-4-v1-2-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-2-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250318-adventurous-cherubic-coua-eecbbc@krzk-bin>

On Mon, Mar 17, 2025 at 07:44:37PM +0200, Dmitry Baryshkov wrote:
> Add DT schema for the MultiMedia SubSystem System FPB device, which
> provides several registers to control interface between multimedia
> devices (primarily display) and system busses.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  .../devicetree/bindings/display/msm/qcom,sfpb.yaml | 39 ++++++++++++++++++++++

Filename: qcom,apq8064-mmss-sfpb.yaml

>  1 file changed, 39 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..7ca105c97edd2f305527c58ae89b9b0cf22d3c8c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
> @@ -0,0 +1,39 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/msm/qcom,sfpb.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm MultiMedia SubSystem System FPB
> +
> +maintainers:
> +  - Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> +  - Rob Clark <robdclark at gmail.com>
> +
> +description:
> +  The SFPB provides several registers controlling the multimedia attachment to
> +  the system busses.
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: qcom,apq8064-mmss-sfpb
> +      - const: syscon

Why this cannot be part of standard syscon bindings file? Looks simple
enough.

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar 18 00:56:46 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 08:56:46 +0100
Subject: [PATCH 3/9] dt-bindings: soc: qcom: add Smart Peripheral System
 Interrupt Controller
In-Reply-To: <20250317-fix-nexus-4-v1-3-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-3-655c52e2ad97@oss.qualcomm.com>
Message-ID: <20250318-dandelion-aardwolf-of-radiance-695fd9@krzk-bin>

On Mon, Mar 17, 2025 at 07:44:38PM +0200, Dmitry Baryshkov wrote:
> +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,sps-sic.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/qcom/qcom,sps-sic.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Smart Peripheral System Interrupt Controller

Interrupt controller should have interrupt-cells. Or this is not
interrupt controller...

Anyway same comments as for previous patch.

Best regards,
Krzysztof



From faraz.ata at samsung.com  Tue Mar 18 00:56:35 2025
From: faraz.ata at samsung.com (Faraz Ata)
Date: Tue, 18 Mar 2025 13:26:35 +0530
Subject: [PATCH v2] arm64: dts: exynos: Add DT node for all UART ports
References: <CGME20250318074801epcas5p3de68627a3e64ebc2a95ed33a3f485e80@epcas5p3.samsung.com>
Message-ID: <20250318075635.3372599-1-faraz.ata@samsung.com>

Universal Serial Interface (USI) supports three serial protocol
like uart, i2c and spi. ExynosAutov920 has 18 instances of USI.
Add all the USI DT node and subsequent uart nodes for all the instances.

Signed-off-by: Faraz Ata <faraz.ata at samsung.com>
---
Changes in v2:
- Fixed review comments from Krzysztof
- Link to v1: https://patchwork.kernel.org/project/linux-samsung-soc/patch/20250312061932.1797993-2-faraz.ata at samsung.com/
---
 .../arm64/boot/dts/exynos/exynosautov920.dtsi | 493 ++++++++++++++++++
 1 file changed, 493 insertions(+)

diff --git a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
index eb446cdc4ab6..9e2887fa51a7 100644
--- a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
@@ -330,6 +330,499 @@ serial_0: serial at 10880000 {
 			};
 		};
 
+		usi_1: usi at 108a00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108a00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1008>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI01_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_1: serial at 108a0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x108a0000 0xc0>;
+				interrupts = <GIC_SPI 766 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart1_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI01_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <256>;
+				status = "disabled";
+			};
+		};
+
+		usi_2: usi at 108c00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108c00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1010>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI02_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_2: serial at 108c0000 {
+			compatible = "samsung,exynosautov920-uart",
+				     "samsung,exynos850-uart";
+				reg = <0x108c0000 0xc0>;
+				interrupts = <GIC_SPI 768 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart2_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI02_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_3: usi at 108e00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x108e00c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1018>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI03_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_3: serial at 108e0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x108e0000 0xc0>;
+				interrupts = <GIC_SPI 770 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart3_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI03_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_4: usi at 109000c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109000c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1020>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI04_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_4: serial at 10900000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10900000 0xc0>;
+				interrupts = <GIC_SPI 772 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart4_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI04_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_5: usi at 109200c0 {
+				compatible = "samsung,exynosautov920-usi",
+					     "samsung,exynos850-usi";
+				reg = <0x109200c0 0x20>;
+				samsung,sysreg = <&syscon_peric0 0x1028>;
+				samsung,mode = <USI_V2_UART>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI05_USI>;
+				clock-names = "pclk", "ipclk";
+				status = "disabled";
+
+			serial_5: serial at 10920000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10920000 0xc0>;
+				interrupts = <GIC_SPI 774 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart5_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI05_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_6: usi at 109400c0 {
+				compatible = "samsung,exynosautov920-usi",
+					     "samsung,exynos850-usi";
+			reg = <0x109400c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1030>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI06_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_6: serial at 10940000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10940000 0xc0>;
+				interrupts = <GIC_SPI 776 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart6_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI06_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_7: usi at 109600c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109600c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1038>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI07_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_7: serial at 10960000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10960000 0xc0>;
+				interrupts = <GIC_SPI 778 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart7_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI07_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_8: usi at 109800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x109800c0 0x20>;
+			samsung,sysreg = <&syscon_peric0 0x1040>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+				 <&cmu_peric0 CLK_DOUT_PERIC0_USI08_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_8: serial at 10980000 {
+			compatible = "samsung,exynosautov920-uart",
+				     "samsung,exynos850-uart";
+				reg = <0x10980000 0xc0>;
+				interrupts = <GIC_SPI 780 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart8_bus>;
+				clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>,
+					 <&cmu_peric0 CLK_DOUT_PERIC0_USI08_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_9: usi at 10c800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10c800c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1000>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI09_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_9: serial at 10c8000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10c80000 0xc0>;
+				interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart9_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI09_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <256>;
+				status = "disabled";
+			};
+		};
+
+		usi_10: usi at 10ca00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10ca00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1008>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI10_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_10: serial at 10ca0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10ca0000 0xc0>;
+				interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart10_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI10_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_11: usi at 10cc00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10cc00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1010>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI11_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_11: serial at 10cc0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10cc0000 0xc0>;
+				interrupts = <GIC_SPI 791 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart11_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI11_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_12: usi at 10ce00c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10ce00c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1018>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI12_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_12: serial at 10ce0000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10ce0000 0xc0>;
+				interrupts = <GIC_SPI 793 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart12_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI12_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_13: usi at 10d000c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d000c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1020>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI13_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_13: serial at 10d00000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d00000 0xc0>;
+				interrupts = <GIC_SPI 795 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart13_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI13_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_14: usi at 10d200c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d200c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1028>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI14_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_14: serial at 10d20000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d20000 0xc0>;
+				interrupts = <GIC_SPI 797 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart14_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI14_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_15: usi at 10d400c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d400c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1030>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI15_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_15: serial at 10d40000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d40000 0xc0>;
+				interrupts = <GIC_SPI 799 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart15_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI15_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_16: usi at 10d600c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d600c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1038>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI16_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_16: serial at 10d60000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d60000 0xc0>;
+				interrupts = <GIC_SPI 801 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart16_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI16_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
+		usi_17: usi at 10d800c0 {
+			compatible = "samsung,exynosautov920-usi",
+				     "samsung,exynos850-usi";
+			reg = <0x10d800c0 0x20>;
+			samsung,sysreg = <&syscon_peric1 0x1040>;
+			samsung,mode = <USI_V2_UART>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+				 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
+			clock-names = "pclk", "ipclk";
+			status = "disabled";
+
+			serial_17: serial at 10d80000 {
+				compatible = "samsung,exynosautov920-uart",
+					     "samsung,exynos850-uart";
+				reg = <0x10d80000 0xc0>;
+				interrupts = <GIC_SPI 803 IRQ_TYPE_LEVEL_HIGH>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart17_bus>;
+				clocks = <&cmu_peric1 CLK_MOUT_PERIC1_NOC_USER>,
+					 <&cmu_peric1 CLK_DOUT_PERIC1_USI17_USI>;
+				clock-names = "uart", "clk_uart_baud0";
+				samsung,uart-fifosize = <64>;
+				status = "disabled";
+			};
+		};
+
 		pwm: pwm at 109b0000 {
 			compatible = "samsung,exynosautov920-pwm",
 				     "samsung,exynos4210-pwm";
-- 
2.34.1



From luis.gerhorst at fau.de  Tue Mar 18 00:59:24 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Tue, 18 Mar 2025 08:59:24 +0100
Subject: [PATCH bpf-next 09/11] bpf: Return PTR_ERR from push_stack()
In-Reply-To: <9083b52fd4a2d7a5a0473e858042c277c883f8b0.camel@gmail.com>
	(Eduard Zingerman's message of "Mon, 17 Mar 2025 02:19:08 -0700")
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	<20250313174149.1113165-1-luis.gerhorst@fau.de>
	<20250313174149.1113165-4-luis.gerhorst@fau.de>
	<9083b52fd4a2d7a5a0473e858042c277c883f8b0.camel@gmail.com>
Message-ID: <87r02uu5ur.fsf@fau.de>

Eduard Zingerman <eddyz87 at gmail.com> writes:

> Could you please point me to a location, where exact error code
> returned by updated push_stack() matters?
> I checked push_stack() callgraph (in the attachment), but can't find
> anything.

Only with the final patch 11 ("bpf: Fall back to nospec for spec path
verification") applied, the error code should matter. Then, the error
code either matches `state->speculative &&
error_recoverable_with_nospec(err)` in do_check() if it was EINVAL (in
this case we heuristically avoided nested speculative path verification
but have to add a nospec), or we continue to raise the error (e.g.,
ENOMEM) from do_check().

Or is your question on this part from the commit message of patch 9?

  This changes the sanitization-case to returning -ENOMEM. However, this
  is more fitting as -EFAULT would indicate a verifier-internal bug.

This was referring to the sanitize_speculative_path() calls in
check_cond_jmp_op(). For that case, the error should also only be used
in do_check() with patch 11 applied. However, regarding this, EFAULT and
ENOMEM are treated the same (they both don't satisfy
error_recoverable_with_nospec()), therefore this change is primarily
made to not complicate the code.

I just became aware that there is some special handling of EFAULT as
discussed in c7a897843224 ("bpf: don't leave partial mangled prog in
jit_subprogs error path"). I will have look into this in detail to make
sure changing push_stack() from EFAULT to ENOMEM is OK.

Hope this answers your question.

Adding some of these details to v2 won't hurt I guess.


From manivannan.sadhasivam at linaro.org  Tue Mar 18 01:03:04 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Tue, 18 Mar 2025 13:33:04 +0530
Subject: [PATCH 3/4] PCI: cadence-ep: Introduce cdns_pcie_ep_disable
 helper for cleanup
In-Reply-To: <20250307103128.3287497-4-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-4-s-vadapalli@ti.com>
Message-ID: <20250318080304.jsmrxqil6pn74nzh@thinkpad>

On Fri, Mar 07, 2025 at 04:01:27PM +0530, Siddharth Vadapalli wrote:
> Introduce the helper function cdns_pcie_ep_disable() which will undo the
> configuration performed by cdns_pcie_ep_setup(). Also, export it for use
> by the existing callers of cdns_pcie_ep_setup(), thereby allowing them
> to cleanup on their exit path.
> 
> Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> ---
>  drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++++++
>  drivers/pci/controller/cadence/pcie-cadence.h    |  5 +++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> index eeb2afdd223e..85bec57fa5d9 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> @@ -646,6 +646,16 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
>  	.get_features	= cdns_pcie_ep_get_features,
>  };
>  
> +void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
> +{
> +	struct device *dev = ep->pcie.dev;
> +	struct pci_epc *epc = to_pci_epc(dev);
> +

pci_epc_deinit_notify()

- Mani

-- 
????????? ????????


From s-vadapalli at ti.com  Tue Mar 18 01:12:39 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Tue, 18 Mar 2025 13:42:39 +0530
Subject: [PATCH 3/4] PCI: cadence-ep: Introduce cdns_pcie_ep_disable
 helper for cleanup
In-Reply-To: <20250318080304.jsmrxqil6pn74nzh@thinkpad>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-4-s-vadapalli@ti.com>
 <20250318080304.jsmrxqil6pn74nzh@thinkpad>
Message-ID: <20250318081239.rvbk3rqud7wcj5pj@uda0492258>

On Tue, Mar 18, 2025 at 01:33:04PM +0530, Manivannan Sadhasivam wrote:

Hello Mani,

> On Fri, Mar 07, 2025 at 04:01:27PM +0530, Siddharth Vadapalli wrote:
> > Introduce the helper function cdns_pcie_ep_disable() which will undo the
> > configuration performed by cdns_pcie_ep_setup(). Also, export it for use
> > by the existing callers of cdns_pcie_ep_setup(), thereby allowing them
> > to cleanup on their exit path.
> > 
> > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > ---
> >  drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++++++
> >  drivers/pci/controller/cadence/pcie-cadence.h    |  5 +++++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > index eeb2afdd223e..85bec57fa5d9 100644
> > --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > @@ -646,6 +646,16 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
> >  	.get_features	= cdns_pcie_ep_get_features,
> >  };
> >  
> > +void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
> > +{
> > +	struct device *dev = ep->pcie.dev;
> > +	struct pci_epc *epc = to_pci_epc(dev);
> > +
> 
> pci_epc_deinit_notify()

I had initially planned to add this, but I noticed that it is not
invoked by dw_pcie_ep_deinit() within
drivers/pci/controller/dwc/pcie-designware-ep.c
Since cdns_pcie_ep_disable() is similar to dw_pcie_ep_deinit(), I
decided to drop it. Current callers of pci_epc_deinit_notify() are:
drivers/pci/controller/dwc/pcie-qcom-ep.c
drivers/pci/controller/dwc/pcie-tegra194.c
while there are many more users of dw_pcie_ep_deinit() that don't invoke
pci_epc_deinit_notify().

While I don't intend to justify dropping pci_epc_deinit_notify() in the
cleanup path, I wanted to check if this should be added to
dw_pcie_ep_deinit() as well. Or is it the case that dw_pcie_ep_deinit()
is different from cdns_pcie_ep_disable()? Please let me know.

Regards,
Siddharth.


From johan at kernel.org  Tue Mar 18 01:16:36 2025
From: johan at kernel.org (Johan Hovold)
Date: Tue, 18 Mar 2025 09:16:36 +0100
Subject: [RFC V6 2/2] firmware: arm_scmi: Add quirk to bypass SCP fw bug
In-Reply-To: <Z8WKQJcPTQDIXaKD@hovoldconsulting.com>
References: <20250226024338.3994701-1-quic_sibis@quicinc.com>
 <20250226024338.3994701-3-quic_sibis@quicinc.com>
 <Z77M5iXHQsdMptWm@hovoldconsulting.com>
 <Z77W-fKBUqAALZKJ@hovoldconsulting.com>
 <759226e1-05aa-4ca2-b2f5-7f1a84dc427f@stanley.mountain>
 <Z77l1NflYXTnRyg0@hovoldconsulting.com>
 <Z8AjhHsVT9ZQTtZX@pluto>
 <Z8WKQJcPTQDIXaKD@hovoldconsulting.com>
Message-ID: <Z9kr5ABbqO27_BM-@hovoldconsulting.com>

Hi Cristian,

On Mon, Mar 03, 2025 at 11:53:52AM +0100, Johan Hovold wrote:
> On Thu, Feb 27, 2025 at 08:34:44AM +0000, Cristian Marussi wrote:
> > On Wed, Feb 26, 2025 at 10:58:44AM +0100, Johan Hovold wrote:
> 
> > > Something like that, yes. :) I didn't try to implement it, but it seems
> > > like it should be possible implement this is a way that keeps the quirk
> > > handling isolated.
> > 
> > I hope next week to have a better look at this, in tne meantime just a
> > few considerations....
> > 
> > Sooner or later we should have introduced some sort of quirk framework
> > in SCMI to deal systematically with potentially out-of-spec FW, but as
> > in the name, it should be some sort of framework where you have a table of
> > quirks, related activation conditions and a few very well isolated points
> > where the quirks are placed and take action if enabled...this does not
> > seem the case here where instead an ad-hoc param is added to the function
> > that needs to be quirked...this does not scale and will make the codebase
> > a mess IMHO...
> 
> Sounds good. At least we have a good understanding now of how this
> particular firmware is broken so it would be great if you could use
> this as a test case for the implementation.
> 
> In summary, we need to force the use of a fast channel for
> PERF_LEVEL_GET on these machines, or possibly fall back to the current
> behaviour of only using the domain attribute to determine whether the
> fast channels should be initialised.
> 
> The latter may allow for a less intrusive implementation even if we'd
> still see:
> 
> 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:0] - ret:-95. Using regular messaging.
> 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:1] - ret:-95. Using regular messaging.
> 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:2] - ret:-95. Using regular messaging.
> 
> when not supported for all messages (e.g. with the current firmware).

> > Anyway, after all of this babbling, I know, talk is cheap :D...so now I will shut
> > up and see if I can prototype something generic to deal with quirks, possibly
> > next week...

Have you made any progress on the quirk framework prototyping?

Do you need any input from Sibi on the protocol versioning for that?

We'd really like to enable cpufreq on this platform and ideally in 6.15.
I think that should be possible given that we now understand in what
ways the firmware is broken and what is needed to handle it even if we
still need to decide on how best to implement this.

Johan


From shayne.chen at mediatek.com  Tue Mar 18 01:30:51 2025
From: shayne.chen at mediatek.com (Shayne Chen)
Date: Tue, 18 Mar 2025 16:30:51 +0800
Subject: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to
 support MLO
In-Reply-To: <38ab11261debaf7e0884080031412808396eea5b.camel@mediatek.com>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
	 <20250312-b4-mt7996-mlo-p2-v1-20-015b3d6fd928@kernel.org>
	 <38ab11261debaf7e0884080031412808396eea5b.camel@mediatek.com>
Message-ID: <d584cae48470cf08b1029e0fef1383f92444970b.camel@mediatek.com>

Hi Lorenzo,

Sorry, please ignore the previous mail.
I just aware that the deflink is now used as the primary/assoc link, so
it should work.

Regards,
Shayne

On Tue, 2025-03-18 at 14:28 +0800, Shayne Chen wrote:
> Hi Lorenzo,
> 
> On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> > 
> 
> Regards,
> Shayne



From Jjian.Zhou at mediatek.com  Tue Mar 18 01:32:15 2025
From: Jjian.Zhou at mediatek.com (=?utf-8?B?SmppYW4gWmhvdSAo5ZGo5bu6KQ==?=)
Date: Tue, 18 Mar 2025 08:32:15 +0000
Subject: [PATCH RFC v3 2/3] firmware: mediatek: Add vcp ipc protocol
 interface
In-Reply-To: <d3f8fbe3-c061-4d34-a5a3-09cbf676bc4c@kernel.org>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
	 <20250317110331.2776-3-jjian.zhou@mediatek.com>
	 <d3f8fbe3-c061-4d34-a5a3-09cbf676bc4c@kernel.org>
Message-ID: <f3b6a690f73e8f5a5370a587d0b1671e96e8b5b2.camel@mediatek.com>

On Mon, 2025-03-17 at 18:16 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 17/03/2025 12:03, Jjian Zhou wrote:
> > Some of mediatek processors contain the Risc-V coprocessor.
> > 
> > The communication between Host CPU and vcp firmware is
> > taking place using a shared memory area for message passing.
> > 
> > VCP IPC protocol offers (send/recv) interfaces using
> > mediatek-mailbox APIs.
> > 
> > Signed-off-by: Jjian Zhou <jjian.zhou at mediatek.com>
> > ---
> >  drivers/firmware/Kconfig                      |   9 +
> >  drivers/firmware/Makefile                     |   1 +
> >  drivers/firmware/mtk-vcp-ipc.c                | 481
> > ++++++++++++++++++
> >  include/linux/firmware/mediatek/mtk-vcp-ipc.h | 151 ++++++
> >  4 files changed, 642 insertions(+)
> >  create mode 100644 drivers/firmware/mtk-vcp-ipc.c
> >  create mode 100644 include/linux/firmware/mediatek/mtk-vcp-ipc.h
> 
> Do not send new versions while previous discussion is still going.
> 
> You still did not respond to previous feedback and you already sent
> two
> versions repeating the same mistake.
> 

I'm sorry for my mistake. 
After we have discussed it, I will fix it in the next version.


> > 
> > diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> > index 37e43f287e78..98c4ff667836 100644
> > --- a/drivers/firmware/Kconfig
> > +++ b/drivers/firmware/Kconfig
> > @@ -179,6 +179,15 @@ config MTK_ADSP_IPC
> >         ADSP exists on some mtk processors.
> >         Client might use shared memory to exchange information with
> > ADSP.
> > 
> 
> ..
> 
> > +
> > +/*
> > + * mtk_vcp_ipc_send - send ipc command to MTK VCP
> > + *
> > + * @ipidev: VCP struct mtk_ipi_device handle
> > + * @id: id of the feature IPI
> > + * @data: message address
> > + * @len: message length
> > + *
> > + * Return: Zero for success from mbox_send_message
> > + *         negative value for error
> > + */
> > +int mtk_vcp_ipc_send(struct mtk_ipi_device *ipidev, u32 id, void
> > *data, u32 len)
> > +{
> > +     struct device *dev;
> > +     struct mtk_mbox_info *minfo;
> > +     struct mtk_ipi_chan_table *table;
> > +     struct mtk_vcp_ipc *vcp_ipc;
> > +     int ret;
> > +
> > +     if (!ipidev || !ipidev->ipi_inited || !data)
> > +             return IPI_UNAVAILABLE;
> > +     vcp_ipc = ipidev->vcp_ipc;
> > +     if (!vcp_ipc)
> > +             return IPI_UNAVAILABLE;
> > +
> > +     table = ipidev->table;
> > +     dev = ipidev->vcp_ipc->dev;
> > +     minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
> > +     if (!minfo) {
> > +             dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev-
> > >name, id);
> > +             return IPI_UNAVAILABLE;
> > +     }
> > +
> > +     if (len > table[id].msg_size)
> > +             return IPI_MSG_TOO_BIG;
> > +     else if (!len)
> > +             len = table[id].msg_size;
> > +
> > +     mutex_lock(&table[id].mutex_send);
> > +
> > +     minfo->ipi_info.msg = data;
> > +     minfo->ipi_info.len = len;
> > +     minfo->ipi_info.id = id;
> > +     minfo->ipi_info.index = table[id].send_index;
> > +     minfo->ipi_info.slot_ofs = table[id].send_ofs *
> > MBOX_SLOT_SIZE;
> > +
> > +     ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
> > +     mutex_unlock(&table[id].mutex_send);
> > +     if (ret < 0) {
> > +             dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, 
> > id);
> > +             return IPI_MBOX_ERR;
> > +     }
> > +
> > +     return IPI_ACTION_DONE;
> > +}
> > +EXPORT_SYMBOL(mtk_vcp_ipc_send);
> 
> Drop export - no users
> 
> Anyway, every export must be GPL.

The Video Companion Processor (VCP) driver (currently being prepared
for submission to the community) will call it.

> 
> > +
> > +/*
> > + * mtk_vcp_ipc_send_compl - send ipc command to MTK VCP
> > + *
> > + * @ipidev: VCP struct mtk_ipi_device handle
> > + * @id: id of the feature IPI
> > + * @data: message address
> > + * @len: message length
> > + * @timeout_ms:
> > + *
> > + * Return: Zero for success from mbox_send_message
> > + *         negative value for error
> > + */
> > +int mtk_vcp_ipc_send_compl(struct mtk_ipi_device *ipidev, u32 id,
> > +                        void *data, u32 len, u32 timeout_ms)
> > +{
> > +     struct device *dev;
> > +     struct mtk_mbox_info *minfo;
> > +     struct mtk_ipi_chan_table *table;
> > +     struct mtk_vcp_ipc *vcp_ipc;
> > +     int ret;
> > +
> > +     if (!ipidev || !ipidev->ipi_inited || !data)
> > +             return IPI_UNAVAILABLE;
> > +     vcp_ipc = ipidev->vcp_ipc;
> > +     if (!vcp_ipc)
> > +             return IPI_UNAVAILABLE;
> > +
> > +     table = ipidev->table;
> > +     dev = ipidev->vcp_ipc->dev;
> > +     minfo = &ipidev->vcp_ipc->info_table[table[id].mbox];
> > +     if (!minfo) {
> > +             dev_err(dev, "%s IPI%d minfo is invalid.\n", ipidev-
> > >name, id);
> > +             return IPI_UNAVAILABLE;
> > +     }
> > +
> > +     if (len > table[id].msg_size)
> > +             return IPI_MSG_TOO_BIG;
> > +     else if (!len)
> > +             len = table[id].msg_size;
> > +
> > +     mutex_lock(&table[id].mutex_send);
> > +
> > +     minfo->ipi_info.msg = data;
> > +     minfo->ipi_info.len = len;
> > +     minfo->ipi_info.id = id;
> > +     minfo->ipi_info.index = table[id].send_index;
> > +     minfo->ipi_info.slot_ofs = table[id].send_ofs *
> > MBOX_SLOT_SIZE;
> > +
> > +     atomic_inc(&table[id].holder);
> > +
> > +     ret = mbox_send_message(minfo->ch, &minfo->ipi_info);
> > +     if (ret < 0) {
> > +             atomic_set(&table[id].holder, 0);
> > +             mutex_unlock(&table[id].mutex_send);
> > +             dev_err(dev, "%s IPI%d send failed.\n", ipidev->name, 
> > id);
> > +             return IPI_MBOX_ERR;
> > +     }
> > +
> > +     /* wait for completion */
> > +     ret = wait_for_completion_timeout(&table[id].notify,
> > +                                       msecs_to_jiffies(timeout_ms
> > ));
> > +     atomic_set(&table[id].holder, 0);
> > +     if (ret > 0)
> > +             ret = IPI_ACTION_DONE;
> > +
> > +     mutex_unlock(&table[id].mutex_send);
> > +
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL(mtk_vcp_ipc_send_compl);
> 
> NAK, no users.
> 

The VCP driver will call it.

> > +
> > +int mtk_vcp_mbox_ipc_register(struct mtk_ipi_device *ipidev, int
> > id,
> > +                           mbox_pin_cb_t cb, void *prdata, void
> > *msg)
> > +{
> > +     if (!ipidev || !ipidev->ipi_inited)
> > +             return IPI_DEV_ILLEGAL;
> > +     if (!msg)
> > +             return IPI_NO_MSGBUF;
> > +
> > +     if (ipidev->table[id].pin_buf)
> > +             return IPI_ALREADY_USED;
> > +     ipidev->table[id].mbox_pin_cb = cb;
> > +     ipidev->table[id].pin_buf = msg;
> > +     ipidev->table[id].prdata = prdata;
> > +
> > +     return IPI_ACTION_DONE;
> > +}
> > +EXPORT_SYMBOL(mtk_vcp_mbox_ipc_register);
> 
> NAK, no users.
> 

The VCP driver will call it.

> 
> > +
> > +int mtk_vcp_mbox_ipc_unregister(struct mtk_ipi_device *ipidev, int
> > id)
> > +{
> > +     if (!ipidev || !ipidev->ipi_inited)
> > +             return IPI_DEV_ILLEGAL;
> > +
> > +     /* Drop the ipi and reset the record */
> > +     complete(&ipidev->table[id].notify);
> > +
> > +     ipidev->table[id].mbox_pin_cb = NULL;
> > +     ipidev->table[id].pin_buf = NULL;
> > +     ipidev->table[id].prdata = NULL;
> > +
> > +     return IPI_ACTION_DONE;
> > +}
> > +EXPORT_SYMBOL(mtk_vcp_mbox_ipc_unregister);
> 
> NAK, no users.
> 

The VCP driver will call it.

> 
> > +
> > +static void mtk_fill_in_entry(struct mtk_ipi_chan_table *entry,
> > const u32 ipi_id,
> > +                           const struct mtk_mbox_table *mbdev)
> > +{
> > +     const struct mtk_mbox_send_table *mbox_send = mbdev-
> > >send_table;
> > +     u32 index;
> > +
> > +     for (index = 0; index < mbdev->send_count; index++) {
> > +             if (ipi_id != mbox_send[index].ipi_id)
> > +                     continue;
> > +
> > +             entry->send_ofs = mbox_send[index].offset;
> > +             entry->send_index = mbox_send[index].pin_index;
> > +             entry->msg_size = mbox_send[index].msg_size;
> > +             entry->mbox = mbox_send[index].mbox_id;
> > +             return;
> > +     }
> > +
> > +     entry->mbox = -ENOENT;
> > +}
> > +
> > +int mtk_vcp_ipc_device_register(struct mtk_ipi_device *ipidev,
> > +                             u32 ipi_chan_count, struct
> > mtk_vcp_ipc *vcp_ipc)
> > +{
> > +     struct mtk_ipi_chan_table *ipi_chan_table;
> > +     struct mtk_mbox_table *mbdev;
> > +     u32 index;
> > +
> > +     if (!vcp_ipc || !ipidev)
> > +             return -EINVAL;
> > +
> > +     ipi_chan_table = kcalloc(ipi_chan_count,
> > +                              sizeof(struct mtk_ipi_chan_table),
> > GFP_KERNEL);
> > +     if (!ipi_chan_table)
> > +             return -ENOMEM;
> > +
> > +     mbdev = vcp_ipc->mbdev;
> > +     vcp_ipc->ipi_priv = (void *)ipidev;
> > +     ipidev->table = ipi_chan_table;
> > +     ipidev->vcp_ipc = vcp_ipc;
> > +
> > +     for (index = 0; index < ipi_chan_count; index++) {
> > +             atomic_set(&ipi_chan_table[index].holder, 0);
> > +             mutex_init(&ipi_chan_table[index].mutex_send);
> > +             init_completion(&ipi_chan_table[index].notify);
> > +             mtk_fill_in_entry(&ipi_chan_table[index], index,
> > mbdev);
> > +     }
> > +
> > +     ipidev->ipi_inited = 1;
> > +
> > +     dev_dbg(vcp_ipc->dev, "%s (with %d IPI) has registered.\n",
> > +             ipidev->name, ipi_chan_count);
> > +
> > +     return IPI_ACTION_DONE;
> > +}
> > +EXPORT_SYMBOL(mtk_vcp_ipc_device_register);
> 
> NAK, no users.
> 

The VCP driver will call it.

> 
> > +
> > +static int setup_mbox_table(struct mtk_mbox_table *mbdev, u32
> > mbox)
> > +{
> > +     struct mtk_mbox_send_table *mbox_send = &mbdev-
> > >send_table[0];
> > +     struct mtk_mbox_recv_table *mbox_recv = &mbdev-
> > >recv_table[0];
> > +     u32 i, last_ofs = 0, last_idx = 0, last_slot = 0, last_sz =
> > 0;
> > +
> > +     for (i = 0; i < mbdev->send_count; i++) {
> > +             if (mbox == mbox_send[i].mbox_id) {
> > +                     mbox_send[i].offset = last_ofs + last_slot;
> > +                     mbox_send[i].pin_index = last_idx + last_sz;
> > +                     last_idx = mbox_send[i].pin_index;
> > +                     last_sz = DIV_ROUND_UP(mbox_send[i].msg_size,
> > MBOX_SLOT_ALIGN);
> > +                     last_ofs = last_sz * MBOX_SLOT_ALIGN;
> > +                     last_slot = last_idx * MBOX_SLOT_ALIGN;
> > +             } else if (mbox < mbox_send[i].mbox_id) {
> > +                     /* no need to search the rest id */
> > +                     break;
> > +             }
> > +     }
> > +
> > +     for (i = 0; i < mbdev->recv_count; i++) {
> > +             if (mbox == mbox_recv[i].mbox_id) {
> > +                     mbox_recv[i].offset = last_ofs + last_slot;
> > +                     mbox_recv[i].pin_index = last_idx + last_sz;
> > +                     last_idx = mbox_recv[i].pin_index;
> > +                     last_sz = DIV_ROUND_UP(mbox_recv[i].msg_size,
> > MBOX_SLOT_ALIGN);
> > +                     last_ofs = last_sz * MBOX_SLOT_ALIGN;
> > +                     last_slot = last_idx * MBOX_SLOT_ALIGN;
> > +             } else if (mbox < mbox_recv[i].mbox_id) {
> > +                     /* no need to search the rest id */
> > +                     break;
> > +             }
> > +     }
> > +
> > +     if (last_idx > MBOX_MAX_PIN || (last_ofs + last_slot) >
> > MAX_SLOT_NUM)
> > +             return -EINVAL;
> > +
> > +     return 0;
> > +}
> > +
> > +static int mtk_vcp_ipc_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct mtk_vcp_ipc *vcp_ipc;
> > +     struct mbox_client *cl;
> > +     struct mtk_mbox_info *minfo;
> > +     int ret;
> > +     u32 mbox, i;
> > +     struct mtk_mbox_table *mbox_data = dev_get_platdata(dev);
> > +
> > +     device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
> > +
> > +     vcp_ipc = devm_kzalloc(dev, sizeof(*vcp_ipc), GFP_KERNEL);
> > +     if (!vcp_ipc)
> > +             return -ENOMEM;
> > +
> > +     if (!mbox_data) {
> 
> Check goes immediately after declaration. I doubt it is useful in the
> first place as this cannot even happen...
> 
> 
> > +             dev_err(dev, "No platform data available\n");
> 
> No, drop. Cannot happen or fix your drivers. Who provides the
> platdata here?

The VCP driver will call platform_device_register_data to register the
structure data. mtk_vcp_ipc_probe will be triggered by vcp_probe. This
structure data is the structure we described in the cover letter.

> 
> > +             return -EINVAL;
> > +     }
> > +     vcp_ipc->mbdev = mbox_data;
> > +
> > +     /* alloc and init mmup_mbox_info */
> > +     vcp_ipc->info_table = vzalloc(sizeof(*vcp_ipc->info_table) *
> > VCP_MBOX_NUM);
> > +     if (!vcp_ipc->info_table)
> > +             return -ENOMEM;
> > +
> > +     /* create mbox dev */
> > +     for (mbox = 0; mbox < VCP_MBOX_NUM; mbox++) {
> > +             minfo = &vcp_ipc->info_table[mbox];
> > +             minfo->mbox_id = mbox;
> > +             minfo->vcp_ipc = vcp_ipc;
> > +             spin_lock_init(&minfo->mbox_lock);
> > +
> > +             ret = setup_mbox_table(vcp_ipc->mbdev, mbox);
> > +             if (ret)
> > +                     return ret;
> > +
> > +             cl = &minfo->cl;
> > +             cl->dev = &pdev->dev;
> > +             cl->tx_block = false;
> > +             cl->knows_txdone = false;
> > +             cl->tx_prepare = NULL;
> > +             cl->rx_callback = mtk_vcp_ipc_recv;
> > +             minfo->ch = mbox_request_channel_byname(cl,
> > mbox_names[mbox]);
> > +             if (IS_ERR(minfo->ch)) {
> > +                     ret = PTR_ERR(minfo->ch);
> > +                     if (ret != -EPROBE_DEFER)
> > +                             dev_err(dev, "Failed to request mbox
> > channel %s ret %d\n",
> > +                                     mbox_names[mbox], ret);
> 
> Do not open code dev_err_probe.

OK, I modify it as below:
    dev_err_probe(dev, PTR_ERR(minfo->ch),
                  "Failed to request mbox channel %s \n",
                   mbox_names[mbox])

> 
> > +
> > +                     for (i = 0; i < mbox; i++) {
> > +                             minfo = &vcp_ipc->info_table[i];
> > +                             mbox_free_channel(minfo->ch);
> > +                     }
> > +
> > +                     vfree(vcp_ipc->info_table);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     vcp_ipc->dev = dev;
> > +     dev_set_drvdata(dev, vcp_ipc);
> > +     dev_dbg(dev, "MTK VCP IPC initialized\n");
> 
> No, drop

OK. I will remove this debug log.

> 
> 
> Best regards,
> Krzysztof

From sw617.shin at samsung.com  Tue Mar 18 01:37:13 2025
From: sw617.shin at samsung.com (sw617.shin at samsung.com)
Date: Tue, 18 Mar 2025 17:37:13 +0900
Subject: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
 ExynosAutoV920 SoC
In-Reply-To: <658c00e2-e8ef-4997-bb91-9620e97bafae@kernel.org>
References: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
	<CGME20250318005143epcas2p40ebb1954bed8890aaf8d0a641f710423@epcas2p4.samsung.com>
	<20250318004411.695786-1-sw617.shin@samsung.com>
	<658c00e2-e8ef-4997-bb91-9620e97bafae@kernel.org>
Message-ID: <000001db97e0$f2ef9e60$d8cedb20$@samsung.com>

Hello, Krzysztof

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Tuesday, March 18, 2025 4:20 PM
> To: Sangwook Shin <sw617.shin at samsung.com>; alim.akhtar at samsung.com;
> wim at linux-watchdog.org; linux at roeck-us.net
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; linux-watchdog at vger.kernel.org; linux-
> kernel at vger.kernel.org; Kyunghwan Seo <khwan.seo at samsung.com>
> Subject: Re: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
> ExynosAutoV920 SoC
> 
> On 18/03/2025 01:44, Sangwook Shin wrote:
> > From: Kyunghwan Seo <khwan.seo at samsung.com>
> >
> > Fix the PMU register bits for the ExynosAutoV920 SoC.
> > This SoC has different bit information compared to its previous
> > version, ExynosAutoV9, and we have made the necessary adjustments.
> >
> > rst_stat_bit:
> >     - ExynosAutoV920 cl0 : 0
> >     - ExynosAutoV920 cl1 : 1
> >
> > cnt_en_bit:
> >     - ExynosAutoV920 cl0 : 8
> >     - ExynosAutoV920 cl1 : 8
> >
> > Signed-off-by: Kyunghwan Seo <khwan.seo at samsung.com>
> > Reviewed-by: Guenter Roeck <linux at roeck-us.net>
> > Reviewed-by: Alim Akhtar <alim.akhtar at samsung.com>
> > Signed-off-by: Sangwook Shin <sw617.shin at samsung.com>
> > ---
> > v1 -> v2: Restore previous email history and tags.
> >
> 
> Why do you send patches which were applied?
> 
> Best regards,
> Krzysztof

I can't see this patch in -next yet.
Could you please advise me where it is? Then, I will check again.
If there are any missing parts that I need to handle on my end,
please let me know.



From daniel.baluta at gmail.com  Tue Mar 18 01:57:11 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Tue, 18 Mar 2025 10:57:11 +0200
Subject: [PATCH 3/3] remoteproc: Use of_reserved_mem_region_* functions
 for "memory-region"
In-Reply-To: <20250317232426.952188-4-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org> <20250317232426.952188-4-robh@kernel.org>
Message-ID: <CAEnQRZA7jEA0V4T1JSam-vV-GcBAbynP0PCfQsyejScwdgd3pg@mail.gmail.com>

On Tue, Mar 18, 2025 at 1:25?AM Rob Herring (Arm) <robh at kernel.org> wrote:
>
> Use the newly added of_reserved_mem_region_to_resource() and
> of_reserved_mem_region_count() functions to handle "memory-region"
> properties.
>
> The error handling is a bit different in some cases. Often
> "memory-region" is optional, so failed lookup is not an error. But then
> an error in of_reserved_mem_lookup() is treated as an error. However,
> that distinction is not really important. Either the region is available
> and usable or it is not. So now, it is just
> of_reserved_mem_region_to_resource() which is checked for an error.
>
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>

For IMX part:

Reviewed-by: Daniel Baluta <daniel.baluta at nxp.com>


From krzk at kernel.org  Tue Mar 18 01:44:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 09:44:34 +0100
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <20250318-rapid-coot-of-tact-d779ad@krzk-bin>

On Mon, Mar 17, 2025 at 11:12:23PM -0500, Rajaganesh Rathinasabapathi wrote:
> Document new AMD Onyx BMC board compatibles
> 
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---

Where is the changelog? What happened with this patch between v1 and v3?

Best regards,
Krzysztof



From krzk at kernel.org  Tue Mar 18 01:45:22 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 09:45:22 +0100
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <20250318-imaginary-peccary-of-argument-ab6b39@krzk-bin>

On Mon, Mar 17, 2025 at 11:12:24PM -0500, Rajaganesh Rathinasabapathi wrote:
> +/ {
> +	model = "AMD Onyx BMC";
> +	compatible = "amd,onyx-bmc", "aspeed,ast2600";
> +
> +	aliases {
> +		serial0 = &uart1;
> +		serial4 = &uart5;
> +	};
> +
> +	chosen {
> +		stdout-path = serial4:115200n8;
> +	};
> +
> +	memory at 80000000 {
> +		device_type = "memory";
> +		reg = <0x80000000 0x80000000>;
> +	};
> +
> +};

<form letter>
This is a friendly reminder during the review process.

It seems my or other reviewer's previous comments were not fully
addressed. Maybe the feedback got lost between the quotes, maybe you
just forgot to apply it. Please go back to the previous discussion and
either implement all requested changes or keep discussing them.

Thank you.
</form letter>

Best regards,
Krzysztof



From vladimir.oltean at nxp.com  Tue Mar 18 01:47:37 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 10:47:37 +0200
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <AS8PR04MB8849FBA73A50F0D553F1AF1B96DE2@AS8PR04MB8849.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
 <20250317141807.2zobsefxl5vnqdet@skbuf>
 <AS8PR04MB8849FBA73A50F0D553F1AF1B96DE2@AS8PR04MB8849.eurprd04.prod.outlook.com>
Message-ID: <20250318084737.e27y6x4mrky47ih4@skbuf>

Hi Claudiu,

On Tue, Mar 18, 2025 at 10:08:24AM +0200, Claudiu Manoil wrote:
> 
> > -----Original Message-----
> > From: Vladimir Oltean <vladimir.oltean at nxp.com>
> > Sent: Monday, March 17, 2025 4:18 PM
> [...]
> > Subject: Re: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
> > ENETC PF
> > 
> > On Tue, Mar 11, 2025 at 01:38:20PM +0800, Wei Fang wrote:
> [...]
> > > +static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
> > > +{
> > > +	struct enetc_mac_list_entry *entry;
> > > +	struct hlist_node *tmp;
> > > +
> > > +	mutex_lock(&pf->mac_list_lock);
> > 
> > The mutex_lock() usage here should raise serious questions. This is
> > running right before mutex_destroy(). So if there were any concurrent
> > attempt to acquire this lock, that concurrent code would have been broken
> > any time it would have lost arbitration, by the fact that it would
> > attempt to acquire a destroyed mutex.
> > 
> > But there's no such concurrent thread, because we run after destroy_workqueue()
> > which flushes those concurrent calls and prevents new ones. So the mutex
> > usage here is not necessary.
> > 
> > [ same thing with mutex_init() immediately followed by mutex_lock().
> >   It is an incorrect pattern most of the time. ]
> > 
> 
> This is not as bad as it seems. In the final version of the code, mutex 'mac_list_lock'
> serializes the access btw the thread programming the filter for the PF instance,
> and the threads programming the filter on behalf of underlying VFs (triggered by async
> request from VF). But since VF support is not included in this patch set (as Wei
> already mentioned) the lock can/should be added later, with the VF patches.

We all agree that the lock is unnecessary as far as the logic presented
in this patch set is concerned, and thus should not be added.

When Wei will present new code that will make explicit serialization
necessary, we can comment more. But, I don't see how any extra logic
can change the basic fact I was pointing out in the portion that you've
quoted. Before you destroy the mutex, you need to do something that
ensures concurrent threads can no longer execute. Then, there's no point
in locking in enetc4_pf_destroy_mac_list(). I expect not to see such
locking there in future patch sets.


From florin.leotescu at oss.nxp.com  Tue Mar 18 01:54:41 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue, 18 Mar 2025 10:54:41 +0200
Subject: [PATCH v5 0/3] Add OF support for Microchip emc2305 fan controller
Message-ID: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

This patch series add initial OF support for Microchip emc2305 fan controller.

Changes since v4:
- Corrected quotes to have a consistent definition.
- Corrected DTS coding style as recommended by Krzysztof Kozlowski.
- Updated pwms phandle to include pwm frequency, pwm polarity and pwm output,
  as recommended by Guenter Roeck and skipped the pwm channel as recommended by Krzysztof Kozlowski.
- Documented the pwms args in #pwm-cells description.
- Updated pwms phandle in dt-binding example to include pwm frequency and 
  use PWM_POLARITY_INVERTED macro to inverse the PWM polarity. 

Changes since v3:
- Removed thermal_cooling_device_register_fail label since is no longer needed
  and replaced goto with imediate return, as recommended by Guenter Roeck. 
- Redefined compatible property in dt-binding, as recommended by Frank Li.
- Updated driver of compatible list.
- Renamed node name in the dt-binding example, as recommended by Connor Dooley.
- Corrected dt-binding commit subject.
- Added dt-binding fan descriptions and $ref to fan schema, 
  as Connor Dooley & Krzysztof Kozlowski recommended.
  Used similar as on maxim,max6639 and nuvoton,nct7363. 
- Updated dt-binding example.

Changes since v2:
- Removed the introduction of new properties for now and we only 
  enable basic OF support.
- Link to previous version: 
  https://lore.kernel.org/linux-arm-kernel/20250219133221.2641041-3-florin.leotescu at oss.nxp.com/T/

Florin Leotescu (3):
  dt-bindings: hwmon: Add Microchip emc2305 support
  hwmon: emc2305: Add OF support
  hwmon: emc2305: Use devm_thermal_of_cooling_device_register

 .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
 drivers/hwmon/emc2305.c                       |  38 ++----
 2 files changed, 123 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar 18 01:54:42 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue, 18 Mar 2025 10:54:42 +0200
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce yaml schema for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
 1 file changed, 113 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
new file mode 100644
index 000000000000..e61ef97e63af
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip EMC2305 SMBus compliant PWM fan controller
+
+maintainers:
+  - Michael Shych <michaelsh at nvidia.com>
+
+description:
+  Microchip EMC2301/2/3/5 pwm controller which supports
+  up to five programmable fan control circuits.
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - microchip,emc2305
+      - items:
+          - enum:
+              - microchip,emc2303
+              - microchip,emc2302
+              - microchip,emc2301
+          - const: microchip,emc2305
+
+  reg:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  '#pwm-cells':
+    const: 3
+    description: |
+      Number of cells in a PWM specifier.
+      - cell 0: The PWM frequency
+      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
+      - cell 2: The PWM output config:
+           - 0 (Open-Drain)
+           - 1 (Push-Pull)
+
+
+patternProperties:
+  '^fan@[0-4]$':
+    $ref: fan-common.yaml#
+    unevaluatedProperties: false
+    properties:
+      reg:
+        description:
+          The fan number used to determine the associated PWM channel.
+
+    required:
+      - reg
+      - pwms
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/pwm/pwm.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        fan_controller: fan-controller at 2f {
+            compatible = "microchip,emc2305";
+            reg = <0x2f>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            #pwm-cells = <3>;
+
+            fan at 0 {
+                reg = <0x0>;
+                pwms = <&fan_controller 26000 PWM_POLARITY_INVERTED 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 1 {
+                reg = <0x1>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 2 {
+                reg = <0x2>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 3 {
+                reg = <0x3>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 4 {
+                reg = <0x4>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+        };
+    };
+...
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar 18 01:54:43 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue, 18 Mar 2025 10:54:43 +0200
Subject: [PATCH v5 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250318085444.3459380-3-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce OF support for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/hwmon/emc2305.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 4d39fbd83769..f8a4c76fcadd 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -607,9 +607,16 @@ static void emc2305_remove(struct i2c_client *client)
 		emc2305_unset_tz(dev);
 }
 
+static const struct of_device_id of_emc2305_match_table[] = {
+	{ .compatible = "microchip,emc2305", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
+
 static struct i2c_driver emc2305_driver = {
 	.driver = {
 		.name = "emc2305",
+		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
 	.remove	  = emc2305_remove,
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Tue Mar 18 01:54:44 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Tue, 18 Mar 2025 10:54:44 +0200
Subject: [PATCH v5 3/3] hwmon: emc2305: Use devm_thermal_of_cooling_device_register
In-Reply-To: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250318085444.3459380-4-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Prepare the emc2305 driver to use configuration from Device Tree nodes.
Switch to devm_thermal_of_cooling_device_register to simplify the
cleanup procedure, allowing the removal of emc2305_unset_tz and
emc2305_remove, which are no longer needed.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/hwmon/emc2305.c | 33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index f8a4c76fcadd..234c54956a4b 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
 	"emc2305_fan5",
 };
 
-static void emc2305_unset_tz(struct device *dev);
-
 static int emc2305_get_max_channel(const struct emc2305_data *data)
 {
 	return data->pwm_num;
@@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
 	pwm = data->pwm_min[cdev_idx];
 
 	data->cdev_data[cdev_idx].cdev =
-		thermal_cooling_device_register(emc2305_fan_name[idx], data,
-						&emc2305_cooling_ops);
+		devm_thermal_of_cooling_device_register(dev, dev->of_node,
+							emc2305_fan_name[idx], data,
+							&emc2305_cooling_ops);
 
 	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
 		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
@@ -332,24 +331,9 @@ static int emc2305_set_tz(struct device *dev)
 	for (i = 0; i < data->pwm_num; i++) {
 		ret = emc2305_set_single_tz(dev, i + 1);
 		if (ret)
-			goto thermal_cooling_device_register_fail;
+			return ret;
 	}
 	return 0;
-
-thermal_cooling_device_register_fail:
-	emc2305_unset_tz(dev);
-	return ret;
-}
-
-static void emc2305_unset_tz(struct device *dev)
-{
-	struct emc2305_data *data = dev_get_drvdata(dev);
-	int i;
-
-	/* Unregister cooling device. */
-	for (i = 0; i < EMC2305_PWM_MAX; i++)
-		if (data->cdev_data[i].cdev)
-			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
 }
 
 static umode_t
@@ -599,14 +583,6 @@ static int emc2305_probe(struct i2c_client *client)
 	return 0;
 }
 
-static void emc2305_remove(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-
-	if (IS_REACHABLE(CONFIG_THERMAL))
-		emc2305_unset_tz(dev);
-}
-
 static const struct of_device_id of_emc2305_match_table[] = {
 	{ .compatible = "microchip,emc2305", },
 	{},
@@ -619,7 +595,6 @@ static struct i2c_driver emc2305_driver = {
 		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
-	.remove	  = emc2305_remove,
 	.id_table = emc2305_ids,
 };
 
-- 
2.34.1



From krzk at kernel.org  Tue Mar 18 01:50:01 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 09:50:01 +0100
Subject: [PATCH] media: dt-bindings: mediatek,vcodec-encoder: Drop
 assigned-clock properties
In-Reply-To: <20250317214621.794674-1-robh@kernel.org>
References: <20250317214621.794674-1-robh@kernel.org>
Message-ID: <20250318-rebel-voracious-tuna-3a9f53@krzk-bin>

On Mon, Mar 17, 2025 at 04:46:20PM -0500, Rob Herring (Arm) wrote:
> The assigned-clock properties are always allowed on nodes with
> 'clocks' and generally not required. Additionally the mt8183 doesn't
> define them, so they must not be required in that case.
> 
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From Shayne.Chen at mediatek.com  Tue Mar 18 01:51:23 2025
From: Shayne.Chen at mediatek.com (=?utf-8?B?U2hheW5lIENoZW4gKOmZs+i7kuS4nik=?=)
Date: Tue, 18 Mar 2025 08:51:23 +0000
Subject: [PATCH 02/21] wifi: mt76: mt7996: Add
 mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
In-Reply-To: <20250312-b4-mt7996-mlo-p2-v1-2-015b3d6fd928@kernel.org>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
	 <20250312-b4-mt7996-mlo-p2-v1-2-015b3d6fd928@kernel.org>
Message-ID: <9efb42f0948b23cc127dc5c5d9e31791f80219ef.camel@mediatek.com>

On Wed, 2025-03-12 at 12:13 +0100, Lorenzo Bianconi wrote:
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index
> 0cc822a8a6799a4552fa537cab2f13d6537bb1a8..ac01eb880e2a6f6ef3a81591bca
> cd2b90c48986a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -2197,6 +2197,80 @@ mt7996_mcu_add_group(struct mt7996_dev *dev,
> struct ieee80211_vif *vif,
> ???????????????????????????????? sizeof(req), true);
> ?}
> 
> +static void
> +mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff
> *skb,
> +??????????????????????????? struct ieee80211_sta *sta)
> +{
> +?????? struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
> +?????? unsigned long links = sta->valid_links;
> +?????? unsigned int nlinks = hweight16(links);
> +?????? struct mld_setup_link *mld_setup_link;
> +?????? struct sta_rec_mld_setup *mld_setup;
> +?????? struct mt7996_sta_link *msta_link;
> +?????? struct ieee80211_vif *vif;
> +?????? unsigned int link_id;
> +?????? struct tlv *tlv;
> +
> +?????? msta_link = mt76_dereference(msta->link[msta->deflink_id],
> &dev->mt76);
> +?????? if (!msta_link)
> +?????????????? return;
> +
> +?????? tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD,
> +???????????????????????????????????? sizeof(struct
> sta_rec_mld_setup) +
> +???????????????????????????????????? sizeof(struct mld_setup_link) *
> nlinks);
> +
> +?????? mld_setup = (struct sta_rec_mld_setup *)tlv;
> +?????? memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN);
> +?????? mld_setup->setup_wcid = cpu_to_le16(msta_link->wcid.idx);
> +?????? mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
> +
> +?????? if (nlinks > 1) {
> +?????????????? link_id = __ffs(links & ~BIT(msta->deflink_id));
> +?????????????? msta_link = mt76_dereference(msta->link[msta-
> >deflink_id],
> +??????????????????????????????????????????? &dev->mt76);
> +?????????????? if (!msta_link)
> +?????????????????????? return;
> +?????? }
> +?????? mld_setup->seconed_id = cpu_to_le16(msta_link->wcid.idx);
> +?????? mld_setup->link_num = nlinks;
> +
> +?????? vif = container_of((void *)msta->vif, struct ieee80211_vif,
> drv_priv);
> +?????? mld_setup_link = (struct mld_setup_link *)mld_setup-
> >link_info;
> +?????? for_each_set_bit(link_id, &links,
> IEEE80211_MLD_MAX_NUM_LINKS) {
> +?????????????? struct mt7996_vif_link *link;
> +
> +?????????????? msta_link = mt76_dereference(msta->link[link_id],
> &dev->mt76);
> +?????????????? if (!msta_link)
> +?????????????????????? continue;
> +
> +?????????????? link = mt7996_vif_link(dev, vif, link_id);
> +?????????????? if (!link)
> +?????????????????????? continue;
> +
> +?????????????? if (!msta_link)
> +?????????????????????? continue;
> +
> +?????????????? mld_setup_link->wcid = cpu_to_le16(msta_link-
> >wcid.idx);
> +?????????????? mld_setup_link->bss_idx = link->mt76.idx;
> +?????????????? mld_setup_link++;
> +?????? }
> +}
> +
> +static void
> +mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff
> *skb,
> +????????????????????????? struct ieee80211_sta *sta)
> +{
> +?????? struct sta_rec_eht_mld *eht_mld;
> +?????? struct tlv *tlv;
> +?????? int i;
> +
> +?????? tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD,
> sizeof(*eht_mld));
> +?????? eht_mld = (struct sta_rec_eht_mld *)tlv;
> +
> +?????? for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++)
> +?????????????? eht_mld->str_cap[i] = 0x7;
> +}
> +
> ?int mt7996_mcu_add_sta(struct mt7996_dev *dev,
> ?????????????????????? struct ieee80211_bss_conf *link_conf,
> ?????????????????????? struct ieee80211_link_sta *link_sta,
> @@ -2255,6 +2329,11 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
> ??????????????? mt7996_mcu_sta_eht_tlv(skb, link_sta);
> ??????????????? /* starec muru */
> ??????????????? mt7996_mcu_sta_muru_tlv(dev, skb, link_conf,
> link_sta);
> +
> +?????????????? if (sta->mlo && conn_state != CONN_STATE_DISCONNECT)

The latter check seems already to be handled by:
if (conn_state == CONN_STATE_DISCONNECT)
    goto out;

> {
> +?????????????????????? mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
> +?????????????????????? mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
> +?????????????? }
> ??????? }
> 
> ??????? ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
> 


From daniel.baluta at gmail.com  Tue Mar 18 01:54:07 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Tue, 18 Mar 2025 10:54:07 +0200
Subject: [PATCH 1/3] of: reserved_mem: Add functions to parse "memory-region"
In-Reply-To: <20250317232426.952188-2-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org> <20250317232426.952188-2-robh@kernel.org>
Message-ID: <CAEnQRZAwd-e=j2bfHimx9xjQU-2=Anr7fJ_w98t3TAweZY4J8w@mail.gmail.com>

On Tue, Mar 18, 2025 at 1:24?AM Rob Herring (Arm) <robh at kernel.org> wrote:
>
> Drivers with "memory-region" properties currently have to do their own
> parsing of "memory-region" properties. The result is all the drivers
> have similar patterns of a call to parse "memory-region" and then get
> the region's address and size. As this is a standard property, it should
> have common functions for drivers to use. Add new functions to count the
> number of regions and retrieve the region's address as a resource.
>
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>

Reviewed-by: Daniel Baluta <daniel.baluta at nxp.com>


From krzk at kernel.org  Tue Mar 18 01:57:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 09:57:26 +0100
Subject: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
 ExynosAutoV920 SoC
In-Reply-To: <000001db97e0$f2ef9e60$d8cedb20$@samsung.com>
References: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
 <CGME20250318005143epcas2p40ebb1954bed8890aaf8d0a641f710423@epcas2p4.samsung.com>
 <20250318004411.695786-1-sw617.shin@samsung.com>
 <658c00e2-e8ef-4997-bb91-9620e97bafae@kernel.org>
 <000001db97e0$f2ef9e60$d8cedb20$@samsung.com>
Message-ID: <81ce5a24-70b4-4dc7-af1c-3a193c5033e8@kernel.org>

On 18/03/2025 09:37, sw617.shin at samsung.com wrote:
>> Why do you send patches which were applied?
>>
>> Best regards,
>> Krzysztof
> 
> I can't see this patch in -next yet.
> Could you please advise me where it is? Then, I will check again.
> If there are any missing parts that I need to handle on my end,
> please let me know.
I don't think you tried enough.

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 18 02:00:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 10:00:07 +0100
Subject: [PATCH RFC v3 2/3] firmware: mediatek: Add vcp ipc protocol
 interface
In-Reply-To: <f3b6a690f73e8f5a5370a587d0b1671e96e8b5b2.camel@mediatek.com>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
 <20250317110331.2776-3-jjian.zhou@mediatek.com>
 <d3f8fbe3-c061-4d34-a5a3-09cbf676bc4c@kernel.org>
 <f3b6a690f73e8f5a5370a587d0b1671e96e8b5b2.camel@mediatek.com>
Message-ID: <12f5049d-02e1-4c80-9289-b2dfb1e136a8@kernel.org>

On 18/03/2025 09:32, Jjian Zhou (??) wrote:
>>> +
>>> +     return IPI_ACTION_DONE;
>>> +}
>>> +EXPORT_SYMBOL(mtk_vcp_ipc_send);
>>
>> Drop export - no users
>>
>> Anyway, every export must be GPL.
> 
> The Video Companion Processor (VCP) driver (currently being prepared
> for submission to the community) will call it.
> 

It does not work like that. You must post the users NOW.

NAK


...

>> Check goes immediately after declaration. I doubt it is useful in the
>> first place as this cannot even happen...
>>
>>
>>> +             dev_err(dev, "No platform data available\n");
>>
>> No, drop. Cannot happen or fix your drivers. Who provides the
>> platdata here?
> 
> The VCP driver will call platform_device_register_data to register the
> structure data. mtk_vcp_ipc_probe will be triggered by vcp_probe. This
> structure data is the structure we described in the cover letter.


Comment is still valid.

Best regards,
Krzysztof


From heiko at sntech.de  Tue Mar 18 02:15:21 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 18 Mar 2025 10:15:21 +0100
Subject: (subset) [PATCH RESEND v2 0/6] RK3576 OTP support
In-Reply-To: <173978599692.25901.15315285566342669137.b4-ty@linaro.org>
References: <20250210224510.1194963-1-heiko@sntech.de>
 <173978599692.25901.15315285566342669137.b4-ty@linaro.org>
Message-ID: <2364081.ElGaqSPkdT@diego>

Hi,

Am Montag, 17. Februar 2025, 10:53:16 MEZ schrieb Srinivas Kandagatla:
> 
> On Mon, 10 Feb 2025 23:45:04 +0100, Heiko Stuebner wrote:
> > This enables OTP support in the nvmem driver for rk3576.
> > 
> > I expect to pick the clock patch (patch1) and the arm64-dts patch (patch6)
> > myself, after the nvmem-driver and -binding patches have been applied
> > (patches 2-5).
> > 
> > But kept them together for people wanting to try this series.
> > 
> > [...]
> 
> Applied, thanks!
> 
> [1/6] clk: rockchip: rk3576: define clk_otp_phy_g
>       commit: 3e081aa132bbefe31ac95dd6dfc8d787ffa83d0b

the applied message says you picked the clock patch, but it's not in your
tree - probably because you realized that it's a clock patch? :-)

So just to make sure it doesn't land in two trees, I should probably pick
up the patch for the Rockchip clock driver, right?


Thanks a lot
Heiko


> [2/6] nvmem: rockchip-otp: Move read-offset into variant-data
>       commit: 024e21343f3cbcde0343473fcaf094d2c19cc7bf
> [3/6] dt-bindings: nvmem: rockchip,otp: add missing limits for clock-names
>       commit: a1bf00100d06ad69286154a63e548ae6f6ce8539
> [4/6] dt-bindings: nvmem: rockchip,otp: Add compatible for RK3576
>       commit: 8c94337ebbfb840944574f82df0cbe35930d8df8
> [5/6] nvmem: rockchip-otp: add rk3576 variant data
>       commit: c5ebefe4e20d9fd99ae49cbfd1c18632cf338fa5
> 
> Best regards,
> 






From sw617.shin at samsung.com  Tue Mar 18 02:25:34 2025
From: sw617.shin at samsung.com (sw617.shin at samsung.com)
Date: Tue, 18 Mar 2025 18:25:34 +0900
Subject: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
 ExynosAutoV920 SoC
In-Reply-To: <81ce5a24-70b4-4dc7-af1c-3a193c5033e8@kernel.org>
References: <9c94a771-b3e6-4ba4-9b7f-dcd93b53f924@kernel.org>
	<CGME20250318005143epcas2p40ebb1954bed8890aaf8d0a641f710423@epcas2p4.samsung.com>
	<20250318004411.695786-1-sw617.shin@samsung.com>
	<658c00e2-e8ef-4997-bb91-9620e97bafae@kernel.org>
	<000001db97e0$f2ef9e60$d8cedb20$@samsung.com>
	<81ce5a24-70b4-4dc7-af1c-3a193c5033e8@kernel.org>
Message-ID: <001e01db97e7$b3780b30$1a682190$@samsung.com>

Hello Krzysztof

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Tuesday, March 18, 2025 5:57 PM
> To: sw617.shin at samsung.com; alim.akhtar at samsung.com; wim at linux-
> watchdog.org; linux at roeck-us.net
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; linux-watchdog at vger.kernel.org; linux-
> kernel at vger.kernel.org; 'Kyunghwan Seo' <khwan.seo at samsung.com>
> Subject: Re: [PATCH v2] watchdog: s3c2410_wdt: Fix PMU register bits for
> ExynosAutoV920 SoC
> 
> On 18/03/2025 09:37, sw617.shin at samsung.com wrote:
> >> Why do you send patches which were applied?
> >>
> >> Best regards,
> >> Krzysztof
> >
> > I can't see this patch in -next yet.
> > Could you please advise me where it is? Then, I will check again.
> > If there are any missing parts that I need to handle on my end, please
> > let me know.
> I don't think you tried enough.
> 
> Best regards,
> Krzysztof

You're definitely right.
I found it with my colleague's help.
I was monitoring wrong ones.
Thanks for notice and sorry for making you uncomfortable.
Thank you.



From james.clark at linaro.org  Tue Mar 18 02:27:10 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 09:27:10 +0000
Subject: [PATCH 2/7] coresight: Convert disclaim functions to take a
 struct cs_access
In-Reply-To: <20250317182957.GL2487211@e132581.arm.com>
References: <20250211103945.967495-1-james.clark@linaro.org>
 <20250211103945.967495-3-james.clark@linaro.org>
 <20250313145456.GR9682@e132581.arm.com>
 <c6a86373-64be-4101-a08a-74aa302bf64c@linaro.org>
 <20250317182957.GL2487211@e132581.arm.com>
Message-ID: <b6c2622a-5c54-4951-be23-7f05599fc10d@linaro.org>



On 17/03/2025 6:29 pm, Leo Yan wrote:
> On Mon, Mar 17, 2025 at 11:36:40AM +0000, James Clark wrote:
>>
>>
>> On 13/03/2025 2:54 pm, Leo Yan wrote:
>>> On Tue, Feb 11, 2025 at 10:39:38AM +0000, James Clark wrote:
>>>
>>> [...]
>>>
>>>>    static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>>>>    {
>>>> -       return coresight_read_claim_tags(csdev) != 0;
>>>> +       return coresight_read_claim_tags(&csdev->access) != 0;
>>>>    }
>>>
>>> Likewise other claim functions, can coresight_is_claimed_any() change its
>>> argument type from struct coresight_device to struct csdev_access?
>>
>> I only wanted to change the ones that I had to. I think we should prioritize
>> passing csdev as much as possible in the coresight framework to make
>> everything consistent. Otherwise it's extra churn for no benefit, and if we
>> need something from csdev here in the future we'll have to change this one
>> back again.
> 
> The function coresight_is_claimed_any() has been deleted in a later
> patch.  So this is fine for me.
> 
> In theory, claim tags are low level operations and don't need a
> CoreSight device context, I prefer we can keep them as simple as
> possible.
> 
> With this series, we can see coresight_claim_device() and
> coresight_disclaim_device() are inconsistent for their parameters:
> one is using "struct coresight_device *" and another is
> "struct csdev_access *".  Maybe we just proceed to use csdev_access
> for all claim tag functions?
> 

That's because coresight_claim_device() has logging which requires the 
device name to make it useful. If anything, coresight_disclaim_device() 
should actually take a csdev and then print a better log message. I 
don't think there's a way to make it consistent when there are different 
requirements for each level of operations. The ones with logging need a 
csdev and the lower level ones used on probe need to work with only csa.

> If later we need to use a CoreSight device context when operating
> claim tags, it means we might have different scenarios and we can
> handle that separately.
> 
> Thanks,
> Leo




From vladimir.oltean at nxp.com  Tue Mar 18 02:29:28 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 11:29:28 +0200
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <PAXPR04MB8510EECE1FDDA893811EC28B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
 <20250317141807.2zobsefxl5vnqdet@skbuf>
 <PAXPR04MB8510EECE1FDDA893811EC28B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250318092928.6e2tspaf4rfyn32c@skbuf>

On Tue, Mar 18, 2025 at 05:19:51AM +0200, Wei Fang wrote:
> You are right, but I'm afraid of the Coverity will report an issue, because the
> pf->mac_list and pf->num_mfe are protected by the mac_list_lock in other
> functions. And enetc4_pf_destroy_mac_list() will be called in other function
> in the subsequent patches. I don't think it is unnecessary.

Sorry, but I can only take the presented code at face value. If the
Coverity tool signals an issue, you can still triage it and explain why
it is a false positive. Or, if it is a real issue, you can add locking
and provide a good justification for it. But the justification is
missing now.

> So for your question about Rx packet loss, although it is a very corner
> case, the solution I can think of is that we can use temporary MAC hash
> filters before deleting MAFT entries and delete them after adding the
> MAFT entries. Can you accept this proposal?

That sounds good. I'm thinking, for each MAC address filter, maybe you
need an information whether it is programmed to hardware as an exact
match filter or a hash filter, and make use of that functionality here:
temporarily make all filters be hash-based ones, and then see how many
you can convert to exact matches. With something like this, it should
also be easier to maximize the use of the exact match table. Currently,
AFAIU, if you have 5 MAC address filters, they will all be stored as hash
filters, even if 4 of them could have been exact matches. Maybe that can
also be improved with such extra information.

> > > +static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
> > > +{
> > > +	int max_num_mfe = pf->caps.mac_filter_num;
> > > +	struct net_device *ndev = pf->si->ndev;
> > > +	struct enetc_mac_addr *mac_tbl;
> > > +	struct netdev_hw_addr *ha;
> > > +	u8 si_mac[ETH_ALEN];
> > > +	int mac_cnt = 0;
> > > +	int err;
> > > +
> > > +	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
> > 
> > Can't you know ahead of time, based on netdev_uc_count(), whether you
> > will have space for exact match filters, and avoid unnecessary
> > allocations if not? enetc_mac_list_is_available() seems way too late.
> 
> I can add a check before alloc mac_tbl, but enetc_mac_list_is_available()
> is still needed, because enetc4_pf_add_si_mac_exact_filter() is a common
> function for all Sis, not only for PSI.

>From the way in which the discussion is progressing in the replies
above, it sounds to me like maybe this logic will change a bit more.

> > > +static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > > +{
> > > +	char wq_name[24];
> > > +
> > > +	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
> > > +	snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
> > > +	si->workqueue = create_singlethread_workqueue(wq_name);
> > > +	if (!si->workqueue)
> > > +		return -ENOMEM;
> > > +
> > > +	return 0;
> > > +}
> > 
> > Naming scheme is inconsistent here: the function is called "pf" but
> > takes "si" as argument. Same for enetc4_pf_do_set_rx_mode() where the
> > rx_mode_task is part of the station interface structure.
> 
> So change 'pf' to 'psi'?

Sounds better.

> > > +	struct hlist_head mac_list; /* MAC address filter table */
> > 
> > One thing I don't understand is why, given this implementation and
> > final effect, you even bother to keep the mac_list persistently in
> > struct enetc_pf. You have:
> > 
> > enetc4_pf_do_set_rx_mode()
> > -> enetc4_pf_flush_si_mac_exact_filter(ENETC_MAC_FILTER_TYPE_ALL)
> >    -> hlist_for_each_entry_safe(&pf->mac_list)
> >       -> enetc_mac_list_del_entry()
> > 
> > which practically deletes all &pf->mac_list elements every time.
> > So why even store them persistently in the first place? Why not just
> > create an on-stack INIT_HLIST_HEAD() list?
> 
> The enetc4_pf_add_si_mac_exact_filter() and
> enetc4_pf_add_si_mac_exact_filter() are used for all Sis, but only
> PF can access MAFT, and PSI and VSIs may share the same MAFT
> entry, so we need to store them in struct enetc_pf. Although we
> have not added VFs support yet, for such shared functions, we
> should design its implementation from the beginning, rather than
> modifying them when we add the VFs support.

Ok. We need to find a way in which the code also makes sense today
(who knows how much time will pass until VSIs are also supported in the
mainline kernel - we all hope "as soon as possible" but have to plan for
the worst). I don't disagree with the existence of &pf->mac_list,
but it seems slightly inconsistent with the fact that you rebuild it
(for now, completely, but I understand that it the future it will be
just partially) each time ndo_set_rx_mode() is called.

Are you aware of __dev_uc_sync() / __dev_mc_sync()? They are helpers
with explicit sync/unsync callbacks per address, so you don't have to
manually walk using netdev_for_each_uc_addr() / netdev_for_each_mc_addr()
each time, and instead act only on the delta. I haven't thought this
suggestion through, but with you mentioning future VSI mailbox support
for MAC filtering, maybe it is helpful if the PSI's MAC filters are also
structured in this way.


From maz at kernel.org  Tue Mar 18 02:39:30 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 18 Mar 2025 09:39:30 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using VMA flags
In-Reply-To: <Z9h98RhunemcFhhz@arm.com>
References: <20250310103008.3471-1-ankita@nvidia.com>
	<20250310103008.3471-2-ankita@nvidia.com>
	<861pv5p0c3.wl-maz@kernel.org>
	<SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<86r033olwv.wl-maz@kernel.org>
	<SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
	<87tt7y7j6r.wl-maz@kernel.org>
	<SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
	<8634fcnh0n.wl-maz@kernel.org>
	<Z9h98RhunemcFhhz@arm.com>
Message-ID: <86wmcmn0dp.wl-maz@kernel.org>

On Mon, 17 Mar 2025 19:54:25 +0000,
Catalin Marinas <catalin.marinas at arm.com> wrote:
> 
> On Mon, Mar 17, 2025 at 09:27:52AM +0000, Marc Zyngier wrote:
> > On Mon, 17 Mar 2025 05:55:55 +0000,
> > Ankit Agrawal <ankita at nvidia.com> wrote:
> > > 
> > > >> For my education, what is an accepted way to communicate this? Please let
> > > >> me know if there are any relevant examples that you may be aware of.
> > > >
> > > > A KVM capability is what is usually needed.
> > > 
> > > I see. If IIUC, this would involve a corresponding Qemu (usermode) change
> > > to fetch the new KVM cap. Then it could fail in case the FWB is not
> > > supported with some additional conditions (so that the currently supported
> > > configs with !FWB won't break on usermode). 
> > > 
> > > The proposed code change is to map in S2 as NORMAL when vma flags
> > > has VM_PFNMAP. However, Qemu cannot know that driver is mapping
> > > with PFNMAP or not. So how may Qemu decide whether it is okay to
> > > fail for !FWB or not?
> > 
> > This is not about FWB as far as userspace is concerned. This is about
> > PFNMAP as non-device memory. If the host doesn't have FWB, then the
> > "PFNMAP as non-device memory" capability doesn't exist, and userspace
> > fails early.
> > 
> > Userspace must also have some knowledge of what device it obtains the
> > mapping from, and whether that device requires some extra host
> > capability to be assigned to the guest.
> > 
> > You can then check whether the VMA associated with the memslot is
> > PFNMAP or not, if the memslot has been enabled for PFNMAP mappings
> > (either globally or on a per-memslot basis, I don't really care).
> 
> Trying to page this back in, I think there are three stages:
> 
> 1. A KVM cap that the VMM can use to check for non-device PFNMAP (or
>    rather cacheable PFNMAP since we already support Normal NC).
> 
> 2. Memslot registration - we need a way for the VMM to require such
>    cacheable PFNMAP and for KVM to check. Current patch relies on (a)
>    the stage 1 vma attributes which I'm not a fan of. An alternative I
>    suggested was (b) a VM_FORCE_CACHEABLE vma flag, on the assumption
>    that the vfio driver knows if it supports cacheable (it's a bit of a
>    stretch trying to make this generic). Yet another option is (c) a
>    KVM_MEM_CACHEABLE flag that the VMM passes at memslot registration.
> 
> 3. user_mem_abort() - follows the above logic (whatever we decide),
>    maybe with some extra check and WARN in case we got the logic wrong.
> 
> The problems in (2) are that we need to know that the device supports
> cacheable mappings and we don't introduce additional issues or end up
> with FWB on a PFNMAP that does not support cacheable. Without any vma
> flag like the current VM_ALLOW_ANY_UNCACHED, the next best thing is
> relying on the stage 1 attributes. But we don't know them at the memslot
> registration, only later in step (3) after a GUP on the VMM address
> space.
> 
> So in (2), when !FWB, we only want to reject VM_PFNMAP slots if we know
> they are going to be mapped as cacheable. So we need this information
> somehow, either from the vma->vm_flags or slot->flags.

Yup, that's mostly how I think of it.

Obtaining a mapping from the xPU driver must result in VM_PFNMAP being
set in the VMA. I don't think that's particularly controversial.

The memslot must also be created with a new flag ((2c) in the taxonomy
above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
flag is only allowed if (1) is valid.

This results in the following behaviours:

- If the VMM creates the memslot with the cacheable attribute without
  (1) being advertised, we fail.

- If the VMM creates the memslot without the cacheable attribute, we
  map as NC, as it is today.

What this doesn't do is *automatically* decide for the VMM what
attributes to use. The VMM must know what it is doing, and only
provide the memslot flag when appropriate. Doing otherwise may eat
your data and/or take the machine down (cacheable mapping on a device
can be great fun). If you want to address this, then "someone" needs
to pass some additional VMA flag that KVM can check.

Of course, all of this only caters for well behaved userspace, and we
need to gracefully handle (3) when the VMM sneaks in a new VMA that
has conflicting attributes.

For that, we need a reasonable fault reporting interface that allows
userspace to correctly handle it. I don't think this is unique to this
case, but also covers things like MTE and other funky stuff that
relies on the backing memory having some particular "attributes".

An alternative could be to require the VMA to be sealed, which would
prevent any overlapping mapping. But I only have looked at that for 2
minutes...

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From andrea.porta at suse.com  Tue Mar 18 02:46:07 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Tue, 18 Mar 2025 10:46:07 +0100
Subject: [PATCH v7 08/11] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <20250314083730.GC234496@rocinante>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <d1362766e3e966f78591129de918046a4b892c18.1738963156.git.andrea.porta@suse.com>
 <20250314083730.GC234496@rocinante>
Message-ID: <Z9lA31gBjpIRHm6y@apocalypse>

Hi Krzysztof,

On 17:37 Fri 14 Mar     , Krzysztof Wilczynski wrote:
> Hello,
> 
> Even though this is not for the PCI sub-system directly, I had a very brief
> look over the code.  I hope you don't mind.

Highly appreciated, thanks!

> 
> As such, a few nit picks, nothing blocking.
> 
> > +# RaspberryPi RP1 misc device
> 
> Would this be better if it matched the "tristate" description below?

Ack.

> 
> > +config MISC_RP1
> > +	tristate "RaspberryPi RP1 PCIe support"
> > +	depends on OF_IRQ && OF_OVERLAY && PCI_MSI && PCI_QUIRKS
> > +	select PCI_DYNAMIC_OF_NODES
> > +	help
> > +	  Support the RP1 peripheral chip found on Raspberry Pi 5 board.
> > +
> > +	  This device supports several sub-devices including e.g. Ethernet
> > +	  controller, USB controller, I2C, SPI and UART.
> > +
> > +	  The driver is responsible for enabling the DT node once the PCIe
> > +	  endpoint has been configured, and handling interrupts.
> > +
> > +	  This driver uses an overlay to load other drivers to support for
> > +	  RP1 internal sub-devices.
> 
> > +/* the dts overlay is included from the dts directory so
> 
>   /*
>    * The dts overlay is included from the dts directory so
> 
> To make the code comment match rest of the style.

Ack.

> 
> > +/*
> > + * Copyright (c) 2018-24 Raspberry Pi Ltd.
> > + * All rights reserved.
> 
>   Copyright (c) 2018-2025 Raspberry Pi Ltd.
> 
> To spell the current year fully, plus update it to 2025 already.
> 
> I would also add an extra newline here to split the two apart a bit.

Ack.

> 
> > +	if (pci_resource_len(pdev, 1) <= 0x10000) {
> > +		dev_err(&pdev->dev,
> > +			"Not initialised - is the firmware running?\n");
> > +		return -EINVAL;
> > +	}
> 
> The American spelling in the above might be better.  But I don't have
> strong opinions here.  It seems more popular in error messages.

I agree.

> 
> > +	err = pci_alloc_irq_vectors(pdev, RP1_INT_END, RP1_INT_END,
> > +				    PCI_IRQ_MSIX);
> > +	if (err < 0) {
> > +		return dev_err_probe(&pdev->dev, err,
> > +				     "pci_alloc_irq_vectors failed");
> 
> Missing a new line at the end, but also...
> 
>   return dev_err_probe(&pdev->dev, err,
> 		       "Failed to allocate MSI-X vectors\n");

Ack.

> 
> Or, something like this over this the function name.  Perhaps exposing
> error code could be useful to the end user? If so then something like this:
> 
>   return dev_err_probe(&pdev->dev, err,
> 		       "Failed to allocate MSI-X vectors, err=%d\n", err);

dev_err_probe() should already print the err code, no need to add it.

> 
> Here and other errors where appropriate.

I've changed dev_err() to dev_err_probe() in cases where the error code
is not evident (i.e. hardcoded) from the source.

> 
> > +	for (i = 0; i < RP1_INT_END; i++) {
> > +		unsigned int irq = irq_create_mapping(rp1->domain, i);
> > +
> > +		if (!irq) {
> > +			dev_err(&pdev->dev, "failed to create irq mapping\n");
> 
>   dev_err(&pdev->dev, "Failed to create IRQ mapping\n");
> 
> To make the error message capitalisation consistent.

Ack.

> 
> > +static const struct pci_device_id dev_id_table[] = {
> > +	{ PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), },
> > +	{ 0, }
> 
>   { }
> 
> Would probably be sufficient.

Ack.

> 
> > +MODULE_AUTHOR("Phil Elwell <phil at raspberrypi.com>");
> > +MODULE_AUTHOR("Andrea della Porta <andrea.porta at suse.com>");
> > +MODULE_DESCRIPTION("RP1 wrapper");
> 
>   RaspberryPi RP1 misc device
> 
> To match the Kconfig comment in the above description or the one from the
> "tristate" also in Kconfig.

Ack.

> 
> Thank you for all the work here!

Thank you so much for your review!

Andrea

> 
> 	Krzysztof


From wei.fang at nxp.com  Tue Mar 18 02:48:57 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 09:48:57 +0000
Subject: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95
 ENETC PF
In-Reply-To: <20250318092928.6e2tspaf4rfyn32c@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-5-wei.fang@nxp.com>
 <20250317141807.2zobsefxl5vnqdet@skbuf>
 <PAXPR04MB8510EECE1FDDA893811EC28B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250318092928.6e2tspaf4rfyn32c@skbuf>
Message-ID: <PAXPR04MB85109D85826511330E80EC4E88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 18, 2025 at 05:19:51AM +0200, Wei Fang wrote:
> > You are right, but I'm afraid of the Coverity will report an issue, because the
> > pf->mac_list and pf->num_mfe are protected by the mac_list_lock in other
> > functions. And enetc4_pf_destroy_mac_list() will be called in other function
> > in the subsequent patches. I don't think it is unnecessary.
> 
> Sorry, but I can only take the presented code at face value. If the
> Coverity tool signals an issue, you can still triage it and explain why
> it is a false positive. Or, if it is a real issue, you can add locking
> and provide a good justification for it. But the justification is
> missing now.
> 
> > So for your question about Rx packet loss, although it is a very corner
> > case, the solution I can think of is that we can use temporary MAC hash
> > filters before deleting MAFT entries and delete them after adding the
> > MAFT entries. Can you accept this proposal?
> 
> That sounds good. I'm thinking, for each MAC address filter, maybe you
> need an information whether it is programmed to hardware as an exact
> match filter or a hash filter, and make use of that functionality here:
> temporarily make all filters be hash-based ones, and then see how many
> you can convert to exact matches. With something like this, it should
> also be easier to maximize the use of the exact match table. Currently,
> AFAIU, if you have 5 MAC address filters, they will all be stored as hash
> filters, even if 4 of them could have been exact matches. Maybe that can
> also be improved with such extra information.
> 

Currently, I don't want to make the driver too complicated, I think if the number
of MACs exceeds the MAFT's capability, we just use hash filter. Otherwise, we
use MAFT.

> > > > +static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int type)
> > > > +{
> > > > +	int max_num_mfe = pf->caps.mac_filter_num;
> > > > +	struct net_device *ndev = pf->si->ndev;
> > > > +	struct enetc_mac_addr *mac_tbl;
> > > > +	struct netdev_hw_addr *ha;
> > > > +	u8 si_mac[ETH_ALEN];
> > > > +	int mac_cnt = 0;
> > > > +	int err;
> > > > +
> > > > +	mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
> > >
> > > Can't you know ahead of time, based on netdev_uc_count(), whether you
> > > will have space for exact match filters, and avoid unnecessary
> > > allocations if not? enetc_mac_list_is_available() seems way too late.
> >
> > I can add a check before alloc mac_tbl, but enetc_mac_list_is_available()
> > is still needed, because enetc4_pf_add_si_mac_exact_filter() is a common
> > function for all Sis, not only for PSI.
> 
> From the way in which the discussion is progressing in the replies
> above, it sounds to me like maybe this logic will change a bit more.
> 
> > > > +static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > > > +{
> > > > +	char wq_name[24];
> > > > +
> > > > +	INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
> > > > +	snprintf(wq_name, sizeof(wq_name), "enetc-%s",
> pci_name(si->pdev));
> > > > +	si->workqueue = create_singlethread_workqueue(wq_name);
> > > > +	if (!si->workqueue)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	return 0;
> > > > +}
> > >
> > > Naming scheme is inconsistent here: the function is called "pf" but
> > > takes "si" as argument. Same for enetc4_pf_do_set_rx_mode() where the
> > > rx_mode_task is part of the station interface structure.
> >
> > So change 'pf' to 'psi'?
> 
> Sounds better.
> 
> > > > +	struct hlist_head mac_list; /* MAC address filter table */
> > >
> > > One thing I don't understand is why, given this implementation and
> > > final effect, you even bother to keep the mac_list persistently in
> > > struct enetc_pf. You have:
> > >
> > > enetc4_pf_do_set_rx_mode()
> > > -> enetc4_pf_flush_si_mac_exact_filter(ENETC_MAC_FILTER_TYPE_ALL)
> > >    -> hlist_for_each_entry_safe(&pf->mac_list)
> > >       -> enetc_mac_list_del_entry()
> > >
> > > which practically deletes all &pf->mac_list elements every time.
> > > So why even store them persistently in the first place? Why not just
> > > create an on-stack INIT_HLIST_HEAD() list?
> >
> > The enetc4_pf_add_si_mac_exact_filter() and
> > enetc4_pf_add_si_mac_exact_filter() are used for all Sis, but only
> > PF can access MAFT, and PSI and VSIs may share the same MAFT
> > entry, so we need to store them in struct enetc_pf. Although we
> > have not added VFs support yet, for such shared functions, we
> > should design its implementation from the beginning, rather than
> > modifying them when we add the VFs support.
> 
> Ok. We need to find a way in which the code also makes sense today
> (who knows how much time will pass until VSIs are also supported in the
> mainline kernel - we all hope "as soon as possible" but have to plan for
> the worst). I don't disagree with the existence of &pf->mac_list,
> but it seems slightly inconsistent with the fact that you rebuild it
> (for now, completely, but I understand that it the future it will be
> just partially) each time ndo_set_rx_mode() is called.
> 
> Are you aware of __dev_uc_sync() / __dev_mc_sync()? They are helpers

All I can say that I have been saw them in kernel, but I did not spend time
to study them.

> with explicit sync/unsync callbacks per address, so you don't have to
> manually walk using netdev_for_each_uc_addr() / netdev_for_each_mc_addr()
> each time, and instead act only on the delta. I haven't thought this
> suggestion through, but with you mentioning future VSI mailbox support
> for MAC filtering, maybe it is helpful if the PSI's MAC filters are also
> structured in this way.


From amadeus at jmu.edu.cn  Tue Mar 18 03:00:08 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 18:00:08 +0800
Subject: [PATCH 1/3] arm64: dts: rockchip: Add missing uart3 interrupt for RK3528
In-Reply-To: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
References: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
Message-ID: <20250318100010.2253408-2-amadeus@jmu.edu.cn>

The interrupt of uart3 node on rk3528 is missing, fix it.

Fixes: 7983e6c379a9 ("arm64: dts: rockchip: Add base DT for rk3528 SoC")
Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 26c3559d6a6d..7f1ffd6003f5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -404,9 +404,10 @@ uart2: serial at ffa00000 {
 
 		uart3: serial at ffa08000 {
 			compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+			reg = <0x0 0xffa08000 0x0 0x100>;
 			clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
 			clock-names = "baudclk", "apb_pclk";
-			reg = <0x0 0xffa08000 0x0 0x100>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
-- 
2.25.1



From amadeus at jmu.edu.cn  Tue Mar 18 03:00:09 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 18:00:09 +0800
Subject: [PATCH 2/3] arm64: dts: rockchip: Add DMA controller for RK3528
In-Reply-To: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
References: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
Message-ID: <20250318100010.2253408-3-amadeus@jmu.edu.cn>

Add DMA controller dt node for RK3528 SoC.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 7f1ffd6003f5..ad77e0ef70f2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -493,6 +493,24 @@ sdhci: mmc at ffbf0000 {
 			status = "disabled";
 		};
 
+		dmac: dma-controller at ffd60000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xffd60000 0x0 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			arm,pl330-periph-burst;
+			clocks = <&cru ACLK_DMAC>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+		};
+
 		pinctrl: pinctrl {
 			compatible = "rockchip,rk3528-pinctrl";
 			rockchip,grf = <&ioc_grf>;
-- 
2.25.1



From amadeus at jmu.edu.cn  Tue Mar 18 03:00:07 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 18:00:07 +0800
Subject: [PATCH 0/3] arm64: dts: rockchip: Add DMA controller for RK3528
Message-ID: <20250318100010.2253408-1-amadeus@jmu.edu.cn>

First commit adds missing uart3 interrupt for uart3 node.
The next commit adds the DMA controller that can be used
for spi and uart. And add DMA description for uart nodes.

~# dmesg | grep dma
[    0.103466] dma-pl330 ffd60000.dma-controller: Loaded driver for PL330 DMAC-241330
[    0.104212] dma-pl330 ffd60000.dma-controller:       DBUFF-128x8bytes Num_Chans-8 Num_Peri-32 Num_Events-16

Chukun Pan (3):
  arm64: dts: rockchip: Add missing uart3 interrupt for RK3528
  arm64: dts: rockchip: Add DMA controller for RK3528
  arm64: dts: rockchip: Add UART DMA support for RK3528

 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 29 +++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

-- 
2.25.1



From amadeus at jmu.edu.cn  Tue Mar 18 03:00:10 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 18:00:10 +0800
Subject: [PATCH 3/3] arm64: dts: rockchip: Add UART DMA support for RK3528
In-Reply-To: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
References: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
Message-ID: <20250318100010.2253408-4-amadeus@jmu.edu.cn>

The UART ports on RK3528 have DMA capability, describe it.
Flow control is optional, so dma-names are not added.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index ad77e0ef70f2..1af0d036cf32 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -375,6 +375,7 @@ uart0: serial at ff9f0000 {
 			clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 8>, <&dmac 9>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -386,6 +387,7 @@ uart1: serial at ff9f8000 {
 			clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 10>, <&dmac 11>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -397,6 +399,7 @@ uart2: serial at ffa00000 {
 			clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 12>, <&dmac 13>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -408,6 +411,7 @@ uart3: serial at ffa08000 {
 			clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 14>, <&dmac 15>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -419,6 +423,7 @@ uart4: serial at ffa10000 {
 			clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 16>, <&dmac 17>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -430,6 +435,7 @@ uart5: serial at ffa18000 {
 			clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 18>, <&dmac 19>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -441,6 +447,7 @@ uart6: serial at ffa20000 {
 			clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 20>, <&dmac 21>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
@@ -452,6 +459,7 @@ uart7: serial at ffa28000 {
 			clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>;
 			clock-names = "baudclk", "apb_pclk";
 			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dmac 22>, <&dmac 23>;
 			reg-io-width = <4>;
 			reg-shift = <2>;
 			status = "disabled";
-- 
2.25.1



From linus.walleij at linaro.org  Tue Mar 18 03:10:57 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 18 Mar 2025 11:10:57 +0100
Subject: [GIT PULL] pinctrl: samsung: drivers for v6.15
In-Reply-To: <20250316143108.17045-1-krzysztof.kozlowski@linaro.org>
References: <20250316143108.17045-1-krzysztof.kozlowski@linaro.org>
Message-ID: <CACRpkdac0zZtB=85Y+Fu=TYwf9qTjNog90-P4SBjQ-oB7X5Vag@mail.gmail.com>

On Sun, Mar 16, 2025 at 3:31?PM Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:

> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
>
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
>
> are available in the Git repository at:
>
>   https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git tags/samsung-pinctrl-6.15
>
> for you to fetch changes up to 701d0e910955627734917c3587258aa7e73068bb:
>
>   pinctrl: samsung: add support for eint_fltcon_offset (2025-03-11 20:37:29 +0100)

Pulled in, thanks for taking care of the Samsung drivers!

Yours,
Linus Walleij


From pabeni at redhat.com  Tue Mar 18 03:13:20 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Tue, 18 Mar 2025 11:13:20 +0100
Subject: [PATCH net-next 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
In-Reply-To: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
Message-ID: <6259af5f-f518-4f88-ada9-31c3425ce6ed@redhat.com>

On 3/11/25 1:18 PM, Lorenzo Bianconi wrote:
> Introduce missing metadata support for some xdp drivers setting metadata
> size building the skb from xdp_buff.
> Please note most of the drivers are just compile tested.

I'm sorry, but you should at very least report explicitly on per patch
basis which ones have been compile tested.

Even better, please additionally document in each patch why/how the
current headroom is large enough.

Thanks,

Paolo



From quic_philber at quicinc.com  Tue Mar 18 03:13:22 2025
From: quic_philber at quicinc.com (Peter Hilber)
Date: Tue, 18 Mar 2025 11:13:22 +0100
Subject: [PATCH v6 0/4] Add virtio_rtc module
In-Reply-To: <CAPpAL=we6VkyBXBO2cBiszpGUP5f7QSioQbp6x3YoCqa9qUPRQ@mail.gmail.com>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
 <CAPpAL=we6VkyBXBO2cBiszpGUP5f7QSioQbp6x3YoCqa9qUPRQ@mail.gmail.com>
Message-ID: <xogief67mb2wonb7angoypj4ddvvecyrcsnncqitggpij6ssim@fo3psnqqhovp>

On Tue, Mar 18, 2025 at 10:04:07AM +0800, Lei Yang wrote:
> QE tested this series of patches v6 with virtio-net regression tests,
> everything works fine.
> 
> Tested-by: Lei Yang <leiyang at redhat.com>
> 

Hi Lei,

thanks for the reply! However, I am not sure which virtio-net regression
tests you are referring to, and how these tests would be relevant to
virtio_rtc. The virtio_rtc driver does not have any relation to
virtio-net ATM. Reusing virtio_rtc within virtio-net has been discussed
in the past, but not done yet.

Best regards,

Peter


From vladimir.oltean at nxp.com  Tue Mar 18 03:21:21 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 12:21:21 +0200
Subject: [PATCH v4 net-next 11/14] net: enetc: move generic VLAN hash
 filter functions to enetc_pf_common.c
In-Reply-To: <20250311053830.1516523-12-wei.fang@nxp.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-12-wei.fang@nxp.com>
Message-ID: <20250318102121.5vmv4x6qs32x2y5s@skbuf>

On Tue, Mar 11, 2025 at 01:38:27PM +0800, Wei Fang wrote:
> Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
> only difference is the offset of the VLAN hash filter registers. So, the
> .set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
> the registers of the corresponding platform.

For the RSS hash key register, you added a function which retrieves the
register base. For the VLAN hash filter, you add ops. Same problem,
different solutions?


From laura.nao at collabora.com  Tue Mar 18 03:22:57 2025
From: laura.nao at collabora.com (Laura Nao)
Date: Tue, 18 Mar 2025 11:22:57 +0100
Subject: [PATCH 0/2] Use ChromeOS DT hardware prober with MT8192 Spherion trackpads
Message-ID: <20250318102259.189289-1-laura.nao@collabora.com>

This series marks the trackpads for the Google Spherion variants as
"fail-needs-probe" and makes them compatibile with the ChromeOS DT hardware
prober.

Laura Nao (2):
  platform/chrome: Add support for Google Spherion in HW prober
  arm64: dts: mediatek: mt8192-asurada-spherion: Mark trackpads as
    fail-needs-probe

 .../arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts | 7 +++++++
 arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi           | 6 ++++--
 drivers/platform/chrome/chromeos_of_hw_prober.c            | 4 ++++
 3 files changed, 15 insertions(+), 2 deletions(-)

-- 
2.39.5



From laura.nao at collabora.com  Tue Mar 18 03:22:59 2025
From: laura.nao at collabora.com (Laura Nao)
Date: Tue, 18 Mar 2025 11:22:59 +0100
Subject: [PATCH 2/2] arm64: dts: mediatek: mt8192-asurada-spherion: Mark trackpads as fail-needs-probe
In-Reply-To: <20250318102259.189289-1-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
Message-ID: <20250318102259.189289-3-laura.nao@collabora.com>

Different Spherion variants use different trackpads on the same I2C2
bus. Instead of enabling all of them by default, mark them as
"fail-needs-probe" and let the implementation determine which one is
actually present.

Additionally, move the trackpad pinctrl entry back to the individual
trackpad nodes.

Signed-off-by: Laura Nao <laura.nao at collabora.com>
---
 .../arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts | 7 +++++++
 arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi           | 6 ++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
index 8c485c3ced2c..163960f58db5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
@@ -85,8 +85,15 @@ &i2c2 {
 	trackpad at 2c {
 		compatible = "hid-over-i2c";
 		reg = <0x2c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pins>;
 		hid-descr-addr = <0x20>;
 		interrupts-extended = <&pio 15 IRQ_TYPE_LEVEL_LOW>;
 		wakeup-source;
+		status = "fail-needs-probe";
 	};
 };
+
+&trackpad {
+	status = "fail-needs-probe";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index dd0d07fbe61a..b11b32a63bbc 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -335,11 +335,13 @@ &i2c2 {
 	clock-frequency = <400000>;
 	clock-stretch-ns = <12600>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&i2c2_pins>, <&trackpad_pins>;
+	pinctrl-0 = <&i2c2_pins>;
 
-	trackpad at 15 {
+	trackpad: trackpad at 15 {
 		compatible = "elan,ekth3000";
 		reg = <0x15>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_pins>;
 		interrupts-extended = <&pio 15 IRQ_TYPE_LEVEL_LOW>;
 		vcc-supply = <&pp3300_u>;
 		wakeup-source;
-- 
2.39.5



From laura.nao at collabora.com  Tue Mar 18 03:22:58 2025
From: laura.nao at collabora.com (Laura Nao)
Date: Tue, 18 Mar 2025 11:22:58 +0100
Subject: [PATCH 1/2] platform/chrome: Add support for Google Spherion in HW prober
In-Reply-To: <20250318102259.189289-1-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
Message-ID: <20250318102259.189289-2-laura.nao@collabora.com>

Add a new compatible entry for "google,spherion" to the hardware prober
platform list, using the same I2C component prober and trackpad data as
"google,hana".

Signed-off-by: Laura Nao <laura.nao at collabora.com>
---
 drivers/platform/chrome/chromeos_of_hw_prober.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
index c6992f5cdc76..019578bc7ad0 100644
--- a/drivers/platform/chrome/chromeos_of_hw_prober.c
+++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
@@ -84,6 +84,10 @@ static const struct hw_prober_entry hw_prober_platforms[] = {
 		.compatible = "google,hana",
 		.prober = chromeos_i2c_component_prober,
 		.data = &chromeos_i2c_probe_hana_trackpad,
+	}, {
+		.compatible = "google,spherion",
+		.prober = chromeos_i2c_component_prober,
+		.data = &chromeos_i2c_probe_hana_trackpad,
 	},
 };
 
-- 
2.39.5



From leiyang at redhat.com  Tue Mar 18 03:22:49 2025
From: leiyang at redhat.com (Lei Yang)
Date: Tue, 18 Mar 2025 18:22:49 +0800
Subject: [PATCH v6 0/4] Add virtio_rtc module
In-Reply-To: <xogief67mb2wonb7angoypj4ddvvecyrcsnncqitggpij6ssim@fo3psnqqhovp>
References: <20250313173707.1492-1-quic_philber@quicinc.com>
 <CAPpAL=we6VkyBXBO2cBiszpGUP5f7QSioQbp6x3YoCqa9qUPRQ@mail.gmail.com> <xogief67mb2wonb7angoypj4ddvvecyrcsnncqitggpij6ssim@fo3psnqqhovp>
Message-ID: <CAPpAL=xiQ0x7Vk55of1=-Hm0ijsVQkeLixv65WJc-J0sL9Fnww@mail.gmail.com>

On Tue, Mar 18, 2025 at 6:14?PM Peter Hilber <quic_philber at quicinc.com> wrote:
>
> On Tue, Mar 18, 2025 at 10:04:07AM +0800, Lei Yang wrote:
> > QE tested this series of patches v6 with virtio-net regression tests,
> > everything works fine.
> >
> > Tested-by: Lei Yang <leiyang at redhat.com>
> >
>
> Hi Lei,
>
Hi Peter

> thanks for the reply! However, I am not sure which virtio-net regression
> tests you are referring to, and how these tests would be relevant to
> virtio_rtc. The virtio_rtc driver does not have any relation to
> virtio-net ATM. Reusing virtio_rtc within virtio-net has been discussed
> in the past, but not done yet.

First let me introduce the virtio-net tests which include
ping,hotplug/unplug nic device, live migration under stress etc
scenarios. This test was triggered because some of the monitoring
conditions of the CI tool are general. I will change the code later to
avoid similar things happening in the future. Please ignore the last
comment from my side, and sorry for bothering everyone.

Best Regards
Lei
>
> Best regards,
>
> Peter
>



From neil.armstrong at linaro.org  Tue Mar 18 03:24:03 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 18 Mar 2025 11:24:03 +0100
Subject: [PATCH v2 2/2] arm64: dts: amlogic: Add Ugoos AM3
In-Reply-To: <20250314-ugoos-am3-v2-2-422104b0cec5@posteo.net>
References: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net>
 <20250314-ugoos-am3-v2-2-422104b0cec5@posteo.net>
Message-ID: <61a0eb6c-aa15-4316-9e4b-929c3cad13c9@linaro.org>

On 14/03/2025 00:11, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC,
> with a board design that is very close to the Q20x development boards.
> The MMC max-frequency properties are copied from the downstream device
> tree.
> 
>    https://ugoos.com/ugoos-am3-16g
> 
> The following functionality has been tested and is known to work:
>   - debug serial port
>   - "update" button inside the case
>   - USB host mode, on all three ports
>   - HDMI video/audio output
>   - eMMC, MicroSD, and SDIO WLAN
>   - S/PDIF audio output
>   - Ethernet
>   - Infrared remote control input
> 
> The following functionality doesn't seem to work:
>   - USB role switching and device mode on the "OTG" port
>   - case LED
> 
> Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
> ---
> 
> V2:
> - Fix vendor name in patch subject
> - Remove incorrect override of SDIO pwrseq reset line
> ---
>   arch/arm64/boot/dts/amlogic/Makefile               |  1 +
>   .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 +-
>   .../arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts | 91 ++++++++++++++++++++++
>   3 files changed, 93 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
> index 2fbda8419c65a3056410ac45ca3ddaceb69ea4f5..bf2bc14528bfa27e8d6ae2730085fc356d6c6dd8 100644
> --- a/arch/arm64/boot/dts/amlogic/Makefile
> +++ b/arch/arm64/boot/dts/amlogic/Makefile
> @@ -76,6 +76,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-libretech-pc.dtb
> +dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
> index 45ccddd1aaf0546632c81a52c8917a923beae883..4223b26f7d0f3aa47e42e9434d24f73b20441981 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
> @@ -97,7 +97,7 @@ sdio_pwrseq: sdio-pwrseq {
>   		clock-names = "ext_clock";
>   	};
>   
> -	cvbs-connector {
> +	cvbs_connector: cvbs-connector {
>   		compatible = "composite-video-connector";
>   
>   		port {
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
> new file mode 100644
> index 0000000000000000000000000000000000000000..ba871f3f53bb99b47b325bae228b59b722c5123b
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-ugoos-am3.dts
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025 J. Neusch?fer <j.ne at posteo.net>
> + *
> + * Debug UART (3.3V, 115200 baud) at the corner of the board:
> + *   (4) (3) (2) [1]
> + *   Vcc RXD TXD GND
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/input/input.h>
> +#include <dt-bindings/interrupt-controller/amlogic,meson-g12a-gpio-intc.h>
> +
> +#include "meson-gxm.dtsi"
> +#include "meson-gx-p23x-q20x.dtsi"
> +
> +/ {
> +	compatible = "ugoos,am3", "amlogic,s912", "amlogic,meson-gxm";
> +	model = "Ugoos AM3";
> +
> +	adc-keys {
> +		compatible = "adc-keys";
> +		io-channels = <&saradc 0>;
> +		io-channel-names = "buttons";
> +		keyup-threshold-microvolt = <1710000>;
> +
> +		button-function {
> +			label = "Update";
> +			linux,code = <KEY_VENDOR>;
> +			press-threshold-microvolt = <10000>;
> +		};
> +	};
> +};
> +
> +&cvbs_connector {
> +	/* Not used on this board */
> +	status = "disabled";
> +};
> +
> +&ethmac {
> +	pinctrl-0 = <&eth_pins>;
> +	pinctrl-names = "default";
> +
> +	/* Select external PHY by default */
> +	phy-handle = <&external_phy>;
> +
> +	amlogic,tx-delay-ns = <2>;
> +
> +	/* External PHY is in RGMII */
> +	phy-mode = "rgmii";
> +
> +	status = "okay";
> +};
> +
> +&external_mdio {
> +	external_phy: ethernet-phy at 0 {
> +		/* Realtek RTL8211F (0x001cc916) */
> +		reg = <0>;
> +
> +		reset-assert-us = <10000>;
> +		reset-deassert-us = <80000>;
> +		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
> +
> +		interrupt-parent = <&gpio_intc>;
> +		/* MAC_INTR on GPIOZ_15 */
> +		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
> +	};
> +};
> +
> +&i2c_B {
> +	status = "okay";
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&i2c_b_pins>;
> +
> +	rtc: rtc at 51 {
> +		compatible = "haoyu,hym8563";
> +		reg = <0x51>;
> +		#clock-cells = <0>;
> +	};
> +};
> +
> +/* WLAN: Atheros 10k (QCA9377) */
> +&sd_emmc_a {
> +	max-frequency = <200000000>;
> +};
> +
> +/* eMMC */
> +&sd_emmc_c {
> +	max-frequency = <100000000>;
> +};
> 

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 03:28:12 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 11:28:12 +0100
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
Message-ID: <f1848598-c8d7-4c17-8a40-3a6828c32dbe@oss.qualcomm.com>

On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> As most other CoreSight devices the replicator can use either of the
> optional clocks (or both). Document those optional clocks in the schema.
> 
> Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
> --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> @@ -30,6 +30,16 @@ properties:
>    power-domains:
>      maxItems: 1
>  
> +  clocks:
> +    minItems: 1
> +    maxItems: 2
> +
> +  clock-names:
> +    minItems: 1
> +    enum:

I believe this should either be items: if 0/1/2 is allowed, or
minItems should be dropped if 0/1 is allowed, but the former seems
to be the intention

Konrad

> +      - apb_pclk
> +      - atclk
> +
>    in-ports:
>      $ref: /schemas/graph.yaml#/properties/ports
>      additionalProperties: false
> 


From patchwork-bot+netdevbpf at kernel.org  Tue Mar 18 03:30:33 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 18 Mar 2025 10:30:33 +0000
Subject: [PATCH net v3] net: ethernet: ti: am65-cpsw: Fix NAPI registration
 sequence
In-Reply-To: <20250311154259.102865-1-s-vadapalli@ti.com>
References: <20250311154259.102865-1-s-vadapalli@ti.com>
Message-ID: <174229383352.4118139.13974344587777019051.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Tue, 11 Mar 2025 21:12:59 +0530 you wrote:
> From: Vignesh Raghavendra <vigneshr at ti.com>
> 
> Registering the interrupts for TX or RX DMA Channels prior to registering
> their respective NAPI callbacks can result in a NULL pointer dereference.
> This is seen in practice as a random occurrence since it depends on the
> randomness associated with the generation of traffic by Linux and the
> reception of traffic from the wire.
> 
> [...]

Here is the summary with links:
  - [net,v3] net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
    https://git.kernel.org/netdev/net/c/5f079290e591

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From suzuki.poulose at arm.com  Tue Mar 18 03:38:17 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 18 Mar 2025 10:38:17 +0000
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
Message-ID: <7b0af57c-a38c-4c30-9bb7-efe511d6bd1d@arm.com>

On 17/03/2025 17:44, Dmitry Baryshkov wrote:

nit: Subject:

s/qcom,coresight-static-replicator/arm,coresight-static-replicator

> As most other CoreSight devices the replicator can use either of the
> optional clocks (or both). Document those optional clocks in the schema.
> 
> Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>   .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
> --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> @@ -30,6 +30,16 @@ properties:
>     power-domains:
>       maxItems: 1
>   
> +  clocks:
> +    minItems: 1
> +    maxItems: 2
> +

For the static replicator, you don't have an APB clock, as they can't be 
programmed. It may have an ATB clock. So minItems 0, maxItems: 1

Suzuki



> +  clock-names:
> +    minItems: 1
> +    enum:
> +      - apb_pclk
> +      - atclk
> +
>     in-ports:
>       $ref: /schemas/graph.yaml#/properties/ports
>       additionalProperties: false
> 



From james.clark at linaro.org  Tue Mar 18 03:47:02 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 10:47:02 +0000
Subject: [PATCH 2/2] perf vendor events arm64 AmpereOneX: Fix
 frontend_bound calculation
In-Reply-To: <20250313201559.11332-3-ilkka@os.amperecomputing.com>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
 <20250313201559.11332-3-ilkka@os.amperecomputing.com>
Message-ID: <880bebc4-5a59-451e-beb2-60cee9a3efd5@linaro.org>



On 13/03/2025 8:15 pm, Ilkka Koskinen wrote:
> frontend_bound metrics was miscalculated due to different scaling in
> a couple of metrics it depends on. Change the scaling to match with
> AmpereOne.
> 
> Fixes: 16438b652b46 ("perf vendor events arm64 AmpereOneX: Add core PMU events and metrics")
> Signed-off-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>
> ---
>   .../arch/arm64/ampere/ampereonex/metrics.json          | 10 +++++-----
>   1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
> index c5d1d22bd034..5228f94a793f 100644
> --- a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
> +++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json
> @@ -229,19 +229,19 @@
>       },
>       {
>           "MetricName": "slots_lost_misspeculation_fraction",
> -        "MetricExpr": "(OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)",
> +        "MetricExpr": "100 * (OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)",
>           "BriefDescription": "Fraction of slots lost due to misspeculation",
>           "DefaultMetricgroupName": "TopdownL1",
>           "MetricGroup": "Default;TopdownL1",
> -        "ScaleUnit": "100percent of slots"
> +        "ScaleUnit": "1percent of slots"
>       },
>       {
>           "MetricName": "retired_fraction",
> -        "MetricExpr": "OP_RETIRED / (CPU_CYCLES * #slots)",
> +        "MetricExpr": "100 * OP_RETIRED / (CPU_CYCLES * #slots)",
>           "BriefDescription": "Fraction of slots retiring, useful work",
>           "DefaultMetricgroupName": "TopdownL1",
>           "MetricGroup": "Default;TopdownL1",
> -        "ScaleUnit": "100percent of slots"
> +        "ScaleUnit": "1percent of slots"

I never considered that ScaleUnit could be an issue when the metric was 
included in other metrics with different scales. Seems like an easy trap.

Reviewed-by: James Clark <james.clark at linaro.org>



From neil.armstrong at linaro.org  Tue Mar 18 03:48:01 2025
From: neil.armstrong at linaro.org (neil.armstrong at linaro.org)
Date: Tue, 18 Mar 2025 11:48:01 +0100
Subject: [PATCH 3/3] remoteproc: Use of_reserved_mem_region_* functions
 for "memory-region"
In-Reply-To: <20250317232426.952188-4-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
 <20250317232426.952188-4-robh@kernel.org>
Message-ID: <a2ecebf5-9d37-49ad-9422-f984d1da8c57@linaro.org>

Hi,

On 18/03/2025 00:24, Rob Herring (Arm) wrote:
> Use the newly added of_reserved_mem_region_to_resource() and
> of_reserved_mem_region_count() functions to handle "memory-region"
> properties.
> 
> The error handling is a bit different in some cases. Often
> "memory-region" is optional, so failed lookup is not an error. But then
> an error in of_reserved_mem_lookup() is treated as an error. However,
> that distinction is not really important. Either the region is available
> and usable or it is not. So now, it is just
> of_reserved_mem_region_to_resource() which is checked for an error.
> 
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> ---
> For v6.16
> 
>   drivers/remoteproc/imx_dsp_rproc.c        | 44 ++++++---------
>   drivers/remoteproc/imx_rproc.c            | 65 ++++++++-------------
>   drivers/remoteproc/qcom_q6v5_adsp.c       | 24 +++-----
>   drivers/remoteproc/qcom_q6v5_mss.c        | 60 +++++++-------------
>   drivers/remoteproc/qcom_q6v5_pas.c        | 69 ++++++++---------------
>   drivers/remoteproc/qcom_q6v5_wcss.c       | 25 ++++----
>   drivers/remoteproc/qcom_wcnss.c           | 23 +++-----
>   drivers/remoteproc/rcar_rproc.c           | 36 +++++-------
>   drivers/remoteproc/st_remoteproc.c        | 39 ++++++-------
>   drivers/remoteproc/stm32_rproc.c          | 42 ++++++--------
>   drivers/remoteproc/ti_k3_dsp_remoteproc.c | 28 ++++-----
>   drivers/remoteproc/ti_k3_m4_remoteproc.c  | 28 ++++-----
>   drivers/remoteproc/ti_k3_r5_remoteproc.c  | 28 ++++-----
>   drivers/remoteproc/xlnx_r5_remoteproc.c   | 49 ++++++----------
>   14 files changed, 213 insertions(+), 347 deletions(-)
> 
<snip>

I get:
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/qcom_q6v5_adsp.ko] undefined!
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/qcom_q6v5_pas.ko] undefined!
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/qcom_wcnss_pil.ko] undefined!
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/ti_k3_dsp_remoteproc.ko] undefined!
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/ti_k3_m4_remoteproc.ko] undefined!
ERROR: modpost: "devm_ioremap_resource_wc" [drivers/remoteproc/ti_k3_r5_remoteproc.ko] undefined!

when building with arm64 defconfig. I guess a proper:
EXPORT_SYMBOL(devm_ioremap_resource_wc)
is missing.

Neil



From suzuki.poulose at arm.com  Tue Mar 18 03:48:16 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 18 Mar 2025 10:48:16 +0000
Subject: [PATCH] arm: coresight: Finish removal of Coresight support in
 arch/arm/kernel
In-Reply-To: <20250210112927.623872-1-james.clark@linaro.org>
References: <20250210112927.623872-1-james.clark@linaro.org>
Message-ID: <15720521-7ee3-4945-a0bd-2b166682d4c9@arm.com>

On 10/02/2025 11:29, James Clark wrote:
> Commit 184901a06a36 ("ARM: removing support for etb/etm in
> "arch/arm/kernel/"") removed asm/hardware/coresight.h which is included
> by this file. Therefore this is dead code so delete it.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Acked-by: Suzuki K Poulose <suzuki.poulose at arm.com>

> ---
>   arch/arm/include/asm/cti.h | 160 -------------------------------------
>   1 file changed, 160 deletions(-)
>   delete mode 100644 arch/arm/include/asm/cti.h
> 
> diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h
> deleted file mode 100644
> index f8500e5d6ea8..000000000000
> --- a/arch/arm/include/asm/cti.h
> +++ /dev/null
> @@ -1,160 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -#ifndef __ASMARM_CTI_H
> -#define __ASMARM_CTI_H
> -
> -#include	<asm/io.h>
> -#include	<asm/hardware/coresight.h>
> -
> -/* The registers' definition is from section 3.2 of
> - * Embedded Cross Trigger Revision: r0p0
> - */
> -#define		CTICONTROL		0x000
> -#define		CTISTATUS		0x004
> -#define		CTILOCK			0x008
> -#define		CTIPROTECTION		0x00C
> -#define		CTIINTACK		0x010
> -#define		CTIAPPSET		0x014
> -#define		CTIAPPCLEAR		0x018
> -#define		CTIAPPPULSE		0x01c
> -#define		CTIINEN			0x020
> -#define		CTIOUTEN		0x0A0
> -#define		CTITRIGINSTATUS		0x130
> -#define		CTITRIGOUTSTATUS	0x134
> -#define		CTICHINSTATUS		0x138
> -#define		CTICHOUTSTATUS		0x13c
> -#define		CTIPERIPHID0		0xFE0
> -#define		CTIPERIPHID1		0xFE4
> -#define		CTIPERIPHID2		0xFE8
> -#define		CTIPERIPHID3		0xFEC
> -#define		CTIPCELLID0		0xFF0
> -#define		CTIPCELLID1		0xFF4
> -#define		CTIPCELLID2		0xFF8
> -#define		CTIPCELLID3		0xFFC
> -
> -/* The below are from section 3.6.4 of
> - * CoreSight v1.0 Architecture Specification
> - */
> -#define		LOCKACCESS		0xFB0
> -#define		LOCKSTATUS		0xFB4
> -
> -/**
> - * struct cti - cross trigger interface struct
> - * @base: mapped virtual address for the cti base
> - * @irq: irq number for the cti
> - * @trig_out_for_irq: triger out number which will cause
> - *	the @irq happen
> - *
> - * cti struct used to operate cti registers.
> - */
> -struct cti {
> -	void __iomem *base;
> -	int irq;
> -	int trig_out_for_irq;
> -};
> -
> -/**
> - * cti_init - initialize the cti instance
> - * @cti: cti instance
> - * @base: mapped virtual address for the cti base
> - * @irq: irq number for the cti
> - * @trig_out: triger out number which will cause
> - *	the @irq happen
> - *
> - * called by machine code to pass the board dependent
> - * @base, @irq and @trig_out to cti.
> - */
> -static inline void cti_init(struct cti *cti,
> -	void __iomem *base, int irq, int trig_out)
> -{
> -	cti->base = base;
> -	cti->irq  = irq;
> -	cti->trig_out_for_irq = trig_out;
> -}
> -
> -/**
> - * cti_map_trigger - use the @chan to map @trig_in to @trig_out
> - * @cti: cti instance
> - * @trig_in: trigger in number
> - * @trig_out: trigger out number
> - * @channel: channel number
> - *
> - * This function maps one trigger in of @trig_in to one trigger
> - * out of @trig_out using the channel @chan.
> - */
> -static inline void cti_map_trigger(struct cti *cti,
> -	int trig_in, int trig_out, int chan)
> -{
> -	void __iomem *base = cti->base;
> -	unsigned long val;
> -
> -	val = __raw_readl(base + CTIINEN + trig_in * 4);
> -	val |= BIT(chan);
> -	__raw_writel(val, base + CTIINEN + trig_in * 4);
> -
> -	val = __raw_readl(base + CTIOUTEN + trig_out * 4);
> -	val |= BIT(chan);
> -	__raw_writel(val, base + CTIOUTEN + trig_out * 4);
> -}
> -
> -/**
> - * cti_enable - enable the cti module
> - * @cti: cti instance
> - *
> - * enable the cti module
> - */
> -static inline void cti_enable(struct cti *cti)
> -{
> -	__raw_writel(0x1, cti->base + CTICONTROL);
> -}
> -
> -/**
> - * cti_disable - disable the cti module
> - * @cti: cti instance
> - *
> - * enable the cti module
> - */
> -static inline void cti_disable(struct cti *cti)
> -{
> -	__raw_writel(0, cti->base + CTICONTROL);
> -}
> -
> -/**
> - * cti_irq_ack - clear the cti irq
> - * @cti: cti instance
> - *
> - * clear the cti irq
> - */
> -static inline void cti_irq_ack(struct cti *cti)
> -{
> -	void __iomem *base = cti->base;
> -	unsigned long val;
> -
> -	val = __raw_readl(base + CTIINTACK);
> -	val |= BIT(cti->trig_out_for_irq);
> -	__raw_writel(val, base + CTIINTACK);
> -}
> -
> -/**
> - * cti_unlock - unlock cti module
> - * @cti: cti instance
> - *
> - * unlock the cti module, or else any writes to the cti
> - * module is not allowed.
> - */
> -static inline void cti_unlock(struct cti *cti)
> -{
> -	__raw_writel(CS_LAR_KEY, cti->base + LOCKACCESS);
> -}
> -
> -/**
> - * cti_lock - lock cti module
> - * @cti: cti instance
> - *
> - * lock the cti module, so any writes to the cti
> - * module will be not allowed.
> - */
> -static inline void cti_lock(struct cti *cti)
> -{
> -	__raw_writel(~CS_LAR_KEY, cti->base + LOCKACCESS);
> -}
> -#endif



From james.clark at linaro.org  Tue Mar 18 03:48:49 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 10:48:49 +0000
Subject: [PATCH 1/2] perf vendor events arm64: AmpereOne/AmpereOneX: Mark
 LD_RETIRED impacted by errata
In-Reply-To: <20250313201559.11332-2-ilkka@os.amperecomputing.com>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
 <20250313201559.11332-2-ilkka@os.amperecomputing.com>
Message-ID: <9fe071f9-27bb-4694-ace5-f23eb0d0e50d@linaro.org>



On 13/03/2025 8:15 pm, Ilkka Koskinen wrote:
> Atomic instructions are both memory-reading and memory-writing
> instructions and so should be counted by both LD_RETIRED and ST_RETIRED
> performance monitoring events. However LD_RETIRED does not count atomic
> instructions.
> 
> Signed-off-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>
> ---
>   tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json | 4 +++-
>   .../perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json  | 4 +++-
>   2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
> index 0711782bfa6b..13382d29b25f 100644
> --- a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
> +++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
> @@ -1,6 +1,8 @@
>   [
>       {
> -        "ArchStdEvent": "LD_RETIRED"
> +        "ArchStdEvent": "LD_RETIRED",
> +        "Errata": "Errata AC03_CPU_52",
> +        "BriefDescription": "Instruction architecturally executed, condition code check pass, load. Impacted by errata -"

I think this could also have a 'Fixes:' tag, either way:

Reviewed-by: James Clark <james.clark at linaro.org>



From smostafa at google.com  Tue Mar 18 03:46:18 2025
From: smostafa at google.com (Mostafa Saleh)
Date: Tue, 18 Mar 2025 10:46:18 +0000
Subject: [PATCH v3 20/23] iommu: Update various drivers to pass in lg2sz
 instead of order to iommu pages
In-Reply-To: <20250317133500.GC9311@nvidia.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <20-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <Z9GFFBvUFg7a9WEg@google.com>
 <20250317133500.GC9311@nvidia.com>
Message-ID: <Z9lO-viudk9YGakl@google.com>

On Mon, Mar 17, 2025 at 10:35:00AM -0300, Jason Gunthorpe wrote:
> On Wed, Mar 12, 2025 at 12:59:00PM +0000, Mostafa Saleh wrote:
> > > --- a/drivers/iommu/io-pgtable-arm.c
> > > +++ b/drivers/iommu/io-pgtable-arm.c
> > > @@ -263,14 +263,13 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
> > >  				    void *cookie)
> > >  {
> > >  	struct device *dev = cfg->iommu_dev;
> > > -	int order = get_order(size);
> > >  	dma_addr_t dma;
> > >  	void *pages;
> > >  
> > >  	if (cfg->alloc)
> > >  		pages = cfg->alloc(cookie, size, gfp);
> > >  	else
> > > -		pages = iommu_alloc_pages_node(dev_to_node(dev), gfp, order);
> > > +		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp, size);
> > 
> > Although, the current implementation of iommu_alloc_pages_node_sz() would round
> > the size to order, but this is not correct according to the API definition
> > "The returned allocation is round_up_pow_two(size) big, and is physically aligned
> > to its size."
> 
> Yes.. The current implementation is limited to full PAGE_SIZE only,
> the documentation imagines a future where it is not. Drivers should
> ideally not assume the PAGE_SIZE limit during this conversion.
> 
> > I'd say we can align the size or use min with 64 bytes before calling the
> > function would be enough (or change the API to state that allocations
> > are rounded to order)
> 
> OK, like this:
> 
> 	if (cfg->alloc) {
> 		pages = cfg->alloc(cookie, size, gfp);
> 	} else {
> 		/*
> 		 * For very small starting-level translation tables the HW
> 		 * requires a minimum alignment of at least 64 to cover all
> 		 * cases.
> 		 */
> 		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp,
> 						  max(size, 64));
> 	}

Yes, that looks good.

Thanks,
Mostafa

> 
> Thanks,
> Jason


From alim.akhtar at samsung.com  Tue Mar 18 03:49:48 2025
From: alim.akhtar at samsung.com (Alim Akhtar)
Date: Tue, 18 Mar 2025 16:19:48 +0530
Subject: [PATCH] drm/exynos: exynos7_drm_decon: Consstify struct
 decon_data
In-Reply-To: <20250318080738.29292-1-krzysztof.kozlowski@linaro.org>
References: <CGME20250318080746epcas5p476317bb7bae69a8a85b5ad870bb3d0a5@epcas5p4.samsung.com>
	<20250318080738.29292-1-krzysztof.kozlowski@linaro.org>
Message-ID: <000c01db97f3$7976af70$6c640e50$@samsung.com>

Hello Krzysztof

> -----Original Message-----
> From: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Sent: Tuesday, March 18, 2025 1:38 PM
> To: Inki Dae <inki.dae at samsung.com>; Seung-Woo Kim
> <sw0312.kim at samsung.com>; Kyungmin Park
> <kyungmin.park at samsung.com>; David Airlie <airlied at gmail.com>; Simona
> Vetter <simona at ffwll.ch>; Krzysztof Kozlowski <krzk at kernel.org>; Alim
> Akhtar <alim.akhtar at samsung.com>; dri-devel at lists.freedesktop.org; linux-
> arm-kernel at lists.infradead.org; linux-samsung-soc at vger.kernel.org; linux-
> kernel at vger.kernel.org
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Subject: [PATCH] drm/exynos: exynos7_drm_decon: Consstify struct
> decon_data
> 
> static 'struct decon_data' is only read, so it can be const for code
safety.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---

Reviewed-by: Alim Akhtar <alim.akhtar at samsung.com>





From robin.murphy at arm.com  Tue Mar 18 03:57:47 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 10:57:47 +0000
Subject: [PATCH v3 20/23] iommu: Update various drivers to pass in lg2sz
 instead of order to iommu pages
In-Reply-To: <Z9lO-viudk9YGakl@google.com>
References: <0-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <20-v3-e797f4dc6918+93057-iommu_pages_jgg@nvidia.com>
 <Z9GFFBvUFg7a9WEg@google.com> <20250317133500.GC9311@nvidia.com>
 <Z9lO-viudk9YGakl@google.com>
Message-ID: <b956d9d0-d169-4deb-9b7e-cbec95363214@arm.com>

On 2025-03-18 10:46 am, Mostafa Saleh wrote:
> On Mon, Mar 17, 2025 at 10:35:00AM -0300, Jason Gunthorpe wrote:
>> On Wed, Mar 12, 2025 at 12:59:00PM +0000, Mostafa Saleh wrote:
>>>> --- a/drivers/iommu/io-pgtable-arm.c
>>>> +++ b/drivers/iommu/io-pgtable-arm.c
>>>> @@ -263,14 +263,13 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
>>>>   				    void *cookie)
>>>>   {
>>>>   	struct device *dev = cfg->iommu_dev;
>>>> -	int order = get_order(size);
>>>>   	dma_addr_t dma;
>>>>   	void *pages;
>>>>   
>>>>   	if (cfg->alloc)
>>>>   		pages = cfg->alloc(cookie, size, gfp);
>>>>   	else
>>>> -		pages = iommu_alloc_pages_node(dev_to_node(dev), gfp, order);
>>>> +		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp, size);
>>>
>>> Although, the current implementation of iommu_alloc_pages_node_sz() would round
>>> the size to order, but this is not correct according to the API definition
>>> "The returned allocation is round_up_pow_two(size) big, and is physically aligned
>>> to its size."
>>
>> Yes.. The current implementation is limited to full PAGE_SIZE only,
>> the documentation imagines a future where it is not. Drivers should
>> ideally not assume the PAGE_SIZE limit during this conversion.
>>
>>> I'd say we can align the size or use min with 64 bytes before calling the
>>> function would be enough (or change the API to state that allocations
>>> are rounded to order)
>>
>> OK, like this:
>>
>> 	if (cfg->alloc) {
>> 		pages = cfg->alloc(cookie, size, gfp);
>> 	} else {
>> 		/*
>> 		 * For very small starting-level translation tables the HW
>> 		 * requires a minimum alignment of at least 64 to cover all
>> 		 * cases.
>> 		 */
>> 		pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp,
>> 						  max(size, 64));
>> 	}
> 
> Yes, that looks good.

Although for completeness it really wants to cover both paths, so an 
unconditional "size = max(size, 64);" further up would be even better.

Thanks,
Robin.


From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:14 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:14 +0200
Subject: [PATCH v2 1/5] pinctrl: npcm8xx: Fix incorrect struct npcm8xx_pincfg assignment
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <20250318105932.2090926-2-andriy.shevchenko@linux.intel.com>

Sparse is not happy about implementation of the NPCM8XX_PINCFG()

 pinctrl-npcm8xx.c:1314:9: warning: obsolete array initializer, use C99 syntax
 pinctrl-npcm8xx.c:1315:9: warning: obsolete array initializer, use C99 syntax
 ...
 pinctrl-npcm8xx.c:1412:9: warning: obsolete array initializer, use C99 syntax
 pinctrl-npcm8xx.c:1413:9: warning: too many warnings

which uses index-based assignment in a wrong way, i.e. it missed
the equal sign and hence the index is simply ignored, while the
entries are indexed naturally. This is not a problem as the pin
numbering repeats the natural order, but it might be in case of
shuffling the entries. Fix this by adding missed equal sign and
reformat a bit for better readability.

Fixes: acf4884a5717 ("pinctrl: nuvoton: add NPCM8XX pinctrl and GPIO driver")
Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 17825bbe1421..f6a1e684a386 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -1290,12 +1290,14 @@ static struct npcm8xx_func npcm8xx_funcs[] = {
 };
 
 #define NPCM8XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
-	[a] { .fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \
+	[a] = {								  \
+			.flag = q,					  \
+			.fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \
 			.fn1 = fn_ ## e, .reg1 = NPCM8XX_GCR_ ## f, .bit1 = g, \
 			.fn2 = fn_ ## h, .reg2 = NPCM8XX_GCR_ ## i, .bit2 = j, \
 			.fn3 = fn_ ## k, .reg3 = NPCM8XX_GCR_ ## l, .bit3 = m, \
 			.fn4 = fn_ ## n, .reg4 = NPCM8XX_GCR_ ## o, .bit4 = p, \
-			.flag = q }
+	}
 
 /* Drive strength controlled by NPCM8XX_GP_N_ODSC */
 #define DRIVE_STRENGTH_LO_SHIFT		8
-- 
2.47.2



From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:13 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:13 +0200
Subject: [PATCH v2 0/5] pinctrl: nuvoton: A few cleanups and a fix
Message-ID: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>

Convert Nuvoton drivers to use pin control provided data types
and more of device property APIs.

While doing that, fix one non-critical issue that sparse complains about.

Compile tested only.

In v2:
- fixed compilation errors and warnings (LKP)
- collected tags (Jonathan)

Andy Shevchenko (5):
  pinctrl: npcm8xx: Fix incorrect struct npcm8xx_pincfg assignment
  pinctrl: nuvoton: Convert to use struct pingroup and
    PINCTRL_PINGROUP()
  pinctrl: nuvoton: Make use of struct pinfunction and
    PINCTRL_PINFUNCTION()
  pinctrl: nuvoton: Convert to use struct group_desc
  pinctrl: nuvoton: Reduce use of OF-specific APIs

 drivers/pinctrl/nuvoton/pinctrl-ma35.c    | 120 ++++++++++------------
 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c  |   1 -
 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c |  44 ++------
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c |  35 ++-----
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c |  11 +-
 5 files changed, 77 insertions(+), 134 deletions(-)

-- 
2.47.2



From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:18 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:18 +0200
Subject: [PATCH v2 5/5] pinctrl: nuvoton: Reduce use of OF-specific APIs
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <20250318105932.2090926-6-andriy.shevchenko@linux.intel.com>

From: Andy Shevchenko <andy.shevchenko at gmail.com>

Some drivers are using device property APIs along with OF-specific ones.
At the same time few of the latter can be converted to device property
calls. Reduce use of OF-specific APIs in order to bring a bit more consistency
into the drivers.

Signed-off-by: Andy Shevchenko <andy.shevchenko at gmail.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/pinctrl/nuvoton/pinctrl-ma35.c    | 35 +++++++++++------------
 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c  |  1 -
 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 17 ++---------
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c |  2 +-
 4 files changed, 21 insertions(+), 34 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
index da3c8d8e3eb3..06ae1fe8b8c5 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
@@ -519,7 +519,6 @@ static int ma35_gpiolib_register(struct platform_device *pdev, struct ma35_pinct
 		bank->irqtype = 0;
 		bank->irqinten = 0;
 		bank->chip.label = bank->name;
-		bank->chip.of_gpio_n_cells = 2;
 		bank->chip.parent = &pdev->dev;
 		bank->chip.request = ma35_gpio_core_to_request;
 		bank->chip.direction_input = ma35_gpio_core_direction_in;
@@ -976,9 +975,10 @@ static const struct pinconf_ops ma35_pinconf_ops = {
 	.is_generic = true,
 };
 
-static int ma35_pinctrl_parse_groups(struct device_node *np, struct group_desc *grp,
+static int ma35_pinctrl_parse_groups(struct fwnode_handle *fwnode, struct group_desc *grp,
 				     struct ma35_pinctrl *npctl, u32 index)
 {
+	struct device_node *np = to_of_node(fwnode);
 	struct ma35_pin_setting *pin;
 	unsigned long *configs;
 	unsigned int nconfigs;
@@ -990,7 +990,7 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct group_desc *
 	if (ret)
 		return ret;
 
-	count = of_property_count_elems_of_size(np, "nuvoton,pins", sizeof(u32));
+	count = fwnode_property_count_u32(fwnode, "nuvoton,pins");
 	if (!count || count % 3)
 		return -EINVAL;
 
@@ -1000,7 +1000,7 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct group_desc *
 
 	grp->grp.name = np->name;
 
-	ret = of_property_read_u32_array(np, "nuvoton,pins", elems, count);
+	ret = fwnode_property_read_u32_array(fwnode, "nuvoton,pins", elems, count);
 	if (ret)
 		return -EINVAL;
 	grp->grp.npins = count / 3;
@@ -1027,10 +1027,11 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct group_desc *
 	return 0;
 }
 
-static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinctrl *npctl,
+static int ma35_pinctrl_parse_functions(struct fwnode_handle *fwnode, struct ma35_pinctrl *npctl,
 					u32 index)
 {
-	struct device_node *child;
+	struct device_node *np = to_of_node(fwnode);
+	struct fwnode_handle *child;
 	struct pinfunction *func;
 	struct group_desc *grp;
 	static u32 grp_index;
@@ -1050,12 +1051,14 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 	if (!groups)
 		return -ENOMEM;
 
-	for_each_child_of_node(np, child) {
-		groups[i] = child->name;
+	fwnode_for_each_child_node(fwnode, child) {
+		struct device_node *node = to_of_node(child);
+
+		groups[i] = node->name;
 		grp = &npctl->groups[grp_index++];
 		ret = ma35_pinctrl_parse_groups(child, grp, npctl, i++);
 		if (ret) {
-			of_node_put(child);
+			fwnode_handle_put(child);
 			return ret;
 		}
 	}
@@ -1066,13 +1069,12 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 
 static int ma35_pinctrl_probe_dt(struct platform_device *pdev, struct ma35_pinctrl *npctl)
 {
+	struct device *dev = &pdev->dev;
 	struct fwnode_handle *child;
 	u32 idx = 0;
 	int ret;
 
-	device_for_each_child_node(&pdev->dev, child) {
-		if (fwnode_property_present(child, "gpio-controller"))
-			continue;
+	for_each_gpiochip_node(dev, child) {
 		npctl->nfunctions++;
 		npctl->ngroups += of_get_child_count(to_of_node(child));
 	}
@@ -1090,11 +1092,8 @@ static int ma35_pinctrl_probe_dt(struct platform_device *pdev, struct ma35_pinct
 	if (!npctl->groups)
 		return -ENOMEM;
 
-	device_for_each_child_node(&pdev->dev, child) {
-		if (fwnode_property_present(child, "gpio-controller"))
-			continue;
-
-		ret = ma35_pinctrl_parse_functions(to_of_node(child), npctl, idx++);
+	for_each_gpiochip_node(dev, child) {
+		ret = ma35_pinctrl_parse_functions(child, npctl, idx++);
 		if (ret) {
 			fwnode_handle_put(child);
 			dev_err(&pdev->dev, "failed to parse function\n");
@@ -1139,7 +1138,7 @@ int ma35_pinctrl_probe(struct platform_device *pdev, const struct ma35_pinctrl_s
 	npctl->info = info;
 	npctl->dev = &pdev->dev;
 
-	npctl->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "nuvoton,sys");
+	npctl->regmap = syscon_regmap_lookup_by_phandle(dev_of_node(dev), "nuvoton,sys");
 	if (IS_ERR(npctl->regmap))
 		return dev_err_probe(&pdev->dev, PTR_ERR(npctl->regmap),
 				     "No syscfg phandle specified\n");
diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c b/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c
index 8bb9a5a35954..eafa06ca0879 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c
@@ -9,7 +9,6 @@
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index c6b11a198c76..dfd32feb3428 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -7,10 +7,8 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
@@ -1832,22 +1830,13 @@ static struct pinctrl_desc npcm7xx_pinctrl_desc = {
 static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
 {
 	int ret = -ENXIO;
-	struct resource res;
 	struct device *dev = pctrl->dev;
 	struct fwnode_reference_args args;
 	struct fwnode_handle *child;
 	int id = 0;
 
 	for_each_gpiochip_node(dev, child) {
-		struct device_node *np = to_of_node(child);
-
-		ret = of_address_to_resource(np, 0, &res);
-		if (ret < 0) {
-			dev_err(dev, "Resource fail for GPIO bank %u\n", id);
-			return ret;
-		}
-
-		pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res));
+		pctrl->gpio_bank[id].base = fwnode_iomap(child, 0);
 		if (!pctrl->gpio_bank[id].base)
 			return -EINVAL;
 
@@ -1869,7 +1858,7 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
 			return ret;
 		}
 
-		ret = irq_of_parse_and_map(np, 0);
+		ret = fwnode_irq_get(child, 0);
 		if (!ret) {
 			dev_err(dev, "No IRQ for GPIO bank %u\n", id);
 			return -EINVAL;
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 62347a82282d..be3db8ab406c 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -2424,7 +2424,7 @@ static int npcm8xx_pinctrl_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, pctrl);
 
 	pctrl->gcr_regmap =
-		syscon_regmap_lookup_by_phandle(dev->of_node, "nuvoton,sysgcr");
+		syscon_regmap_lookup_by_phandle(dev_of_node(dev), "nuvoton,sysgcr");
 	if (IS_ERR(pctrl->gcr_regmap))
 		return dev_err_probe(dev, PTR_ERR(pctrl->gcr_regmap),
 				      "Failed to find nuvoton,sysgcr property\n");
-- 
2.47.2



From andrea.porta at suse.com  Tue Mar 18 04:05:12 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Tue, 18 Mar 2025 12:05:12 +0100
Subject: [PATCH v7 08/11] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <Z7dnnW4npJmfOVE0@apocalypse>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <d1362766e3e966f78591129de918046a4b892c18.1738963156.git.andrea.porta@suse.com>
 <87525350-b432-40b3-927c-60cd74228ea4@gmx.net>
 <Z7dnnW4npJmfOVE0@apocalypse>
Message-ID: <Z9lTaKsbLND4i3Ir@apocalypse>

Hi Stefan,

On 18:34 Thu 20 Feb     , Andrea della Porta wrote:
> Hi Stefan,
> 
> On 15:21 Sat 08 Feb     , Stefan Wahren wrote:
> > Hi Andrea,
> > 
> > Am 07.02.25 um 22:31 schrieb Andrea della Porta:
> > > +		msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
> > > +		rp1->level_triggered_irq[hwirq] = true;
> > > +	break;
> > > +	case IRQ_TYPE_EDGE_RISING:
> > > +		msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
> > > +		rp1->level_triggered_irq[hwirq] = false;
> > > +		break;
> > > +	default:
> > > +		return -EINVAL;
> > It would be nice to document why only IRQ_TYPE_LEVEL_HIGH and
> > IRQ_TYPE_EDGE_RISING are supported. In case it's a software limitation,
> > this function would be a good place. In case this is a hardware
> > limitation this should be in the binding.
> 
> All ints are level-triggered. I guess I should add a short comment in
> the bindings.
> 

Quick errata: s/level-triggered/active high/

Thanks,
Andrea


From lorenzo at kernel.org  Tue Mar 18 04:06:01 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:06:01 +0100
Subject: [PATCH net-next 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
In-Reply-To: <6259af5f-f518-4f88-ada9-31c3425ce6ed@redhat.com>
References: <20250311-mvneta-xdp-meta-v1-0-36cf1c99790e@kernel.org>
 <6259af5f-f518-4f88-ada9-31c3425ce6ed@redhat.com>
Message-ID: <Z9lTmfyUsY3lqr1m@lore-desk>

> On 3/11/25 1:18 PM, Lorenzo Bianconi wrote:
> > Introduce missing metadata support for some xdp drivers setting metadata
> > size building the skb from xdp_buff.
> > Please note most of the drivers are just compile tested.
> 
> I'm sorry, but you should at very least report explicitly on per patch
> basis which ones have been compile tested.
> 
> Even better, please additionally document in each patch why/how the
> current headroom is large enough.

ack, I will do in v2.

Regards,
Lorenzo

> 
> Thanks,
> 
> Paolo
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250318/af47a387/attachment.sig>

From linmq006 at gmail.com  Tue Mar 18 04:05:53 2025
From: linmq006 at gmail.com (Miaoqian Lin)
Date: Tue, 18 Mar 2025 19:05:53 +0800
Subject: [PATCH] media: mtk-vcodec: Fix reference count leak in mtk_vcodec_fw_scp_init
Message-ID: <20250318110556.903-1-linmq006@gmail.com>

scp_get() returns a reference that needs to be released with scp_put().
Add missing scp_put() before returning error in mtk_vcodec_fw_scp_init().

Fixes: 53dbe0850444 ("media: mtk-vcodec: potential null pointer deference in SCP")
Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
---
 .../platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c      | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
index ff23b225db70..11ab3bc60217 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
@@ -71,7 +71,6 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void *priv, enum mtk_vcodec_fw_use
 		pr_err("Invalid fw_use %d (use a reasonable fw id here)\n", fw_use);
 		return ERR_PTR(-EINVAL);
 	}
-
 	scp = scp_get(plat_dev);
 	if (!scp) {
 		dev_err(&plat_dev->dev, "could not get vdec scp handle");
@@ -79,8 +78,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void *priv, enum mtk_vcodec_fw_use
 	}
 
 	fw = devm_kzalloc(&plat_dev->dev, sizeof(*fw), GFP_KERNEL);
-	if (!fw)
+	if (!fw) {
+		scp_put(scp);
 		return ERR_PTR(-ENOMEM);
+	}
 	fw->type = SCP;
 	fw->ops = &mtk_vcodec_rproc_msg;
 	fw->scp = scp;
-- 
2.39.5 (Apple Git-154)



From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:17 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:17 +0200
Subject: [PATCH v2 4/5] pinctrl: nuvoton: Convert to use struct group_desc
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <20250318105932.2090926-5-andriy.shevchenko@linux.intel.com>

The pin control core header provides struct group_desc.
Utilize it instead of open coded variants in the driver.

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/pinctrl/nuvoton/pinctrl-ma35.c | 70 ++++++++++++--------------
 1 file changed, 33 insertions(+), 37 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
index ad4f9ca414c8..da3c8d8e3eb3 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
@@ -106,13 +106,6 @@ struct ma35_pin_setting {
 	unsigned int		nconfigs;
 };
 
-struct ma35_pin_group {
-	const char		*name;
-	unsigned int		npins;
-	unsigned int		*pins;
-	struct ma35_pin_setting	*settings;
-};
-
 struct ma35_pin_bank {
 	void __iomem		*reg_base;
 	struct clk		*clk;
@@ -141,7 +134,7 @@ struct ma35_pinctrl {
 	struct pinctrl_dev	*pctl;
 	const struct ma35_pinctrl_soc_info *info;
 	struct regmap		*regmap;
-	struct ma35_pin_group	*groups;
+	struct group_desc	*groups;
 	unsigned int		ngroups;
 	struct pinfunction	*functions;
 	unsigned int		nfunctions;
@@ -160,7 +153,7 @@ static const char *ma35_get_group_name(struct pinctrl_dev *pctldev, unsigned int
 {
 	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
 
-	return npctl->groups[selector].name;
+	return npctl->groups[selector].grp.name;
 }
 
 static int ma35_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
@@ -171,19 +164,19 @@ static int ma35_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selecto
 	if (selector >= npctl->ngroups)
 		return -EINVAL;
 
-	*pins = npctl->groups[selector].pins;
-	*npins = npctl->groups[selector].npins;
+	*pins = npctl->groups[selector].grp.pins;
+	*npins = npctl->groups[selector].grp.npins;
 
 	return 0;
 }
 
-static struct ma35_pin_group *ma35_pinctrl_find_group_by_name(
-			      const struct ma35_pinctrl *npctl, const char *name)
+static struct group_desc *
+ma35_pinctrl_find_group_by_name(const struct ma35_pinctrl *npctl, const char *name)
 {
 	int i;
 
 	for (i = 0; i < npctl->ngroups; i++) {
-		if (!strcmp(npctl->groups[i].name, name))
+		if (!strcmp(npctl->groups[i].grp.name, name))
 			return &npctl->groups[i];
 	}
 	return NULL;
@@ -195,9 +188,10 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
 					    unsigned int *num_maps)
 {
 	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
-	struct ma35_pin_group *grp;
+	struct ma35_pin_setting *setting;
 	struct pinctrl_map *new_map;
 	struct device_node *parent;
+	struct group_desc *grp;
 	int map_num = 1;
 	int i;
 
@@ -211,7 +205,7 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 	}
 
-	map_num += grp->npins;
+	map_num += grp->grp.npins;
 	new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);
 	if (!new_map)
 		return -ENOMEM;
@@ -223,17 +217,19 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
 	if (!parent)
 		return -EINVAL;
 
+	setting = grp->data;
+
 	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
 	new_map[0].data.mux.function = parent->name;
 	new_map[0].data.mux.group = np->name;
 	of_node_put(parent);
 
 	new_map++;
-	for (i = 0; i < grp->npins; i++) {
+	for (i = 0; i < grp->grp.npins; i++) {
 		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
-		new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, grp->pins[i]);
-		new_map[i].data.configs.configs = grp->settings[i].configs;
-		new_map[i].data.configs.num_configs = grp->settings[i].nconfigs;
+		new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, grp->grp.pins[i]);
+		new_map[i].data.configs.configs = setting[i].configs;
+		new_map[i].data.configs.num_configs = setting[i].nconfigs;
 	}
 	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
 		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
@@ -281,14 +277,14 @@ static int ma35_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selecto
 			       unsigned int group)
 {
 	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
-	struct ma35_pin_group *grp = &npctl->groups[group];
-	struct ma35_pin_setting *setting = grp->settings;
+	struct group_desc *grp = &npctl->groups[group];
+	struct ma35_pin_setting *setting = grp->data;
 	u32 i, regval;
 
 	dev_dbg(npctl->dev, "enable function %s group %s\n",
-		npctl->functions[selector].name, npctl->groups[group].name);
+		npctl->functions[selector].name, grp->grp.name);
 
-	for (i = 0; i < grp->npins; i++) {
+	for (i = 0; i < grp->grp.npins; i++) {
 		regmap_read(npctl->regmap, setting->offset, &regval);
 		regval &= ~GENMASK(setting->shift + MA35_MFP_BITS_PER_PORT - 1,
 				   setting->shift);
@@ -980,17 +976,16 @@ static const struct pinconf_ops ma35_pinconf_ops = {
 	.is_generic = true,
 };
 
-static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_group *grp,
+static int ma35_pinctrl_parse_groups(struct device_node *np, struct group_desc *grp,
 				     struct ma35_pinctrl *npctl, u32 index)
 {
 	struct ma35_pin_setting *pin;
 	unsigned long *configs;
 	unsigned int nconfigs;
+	unsigned int *pins;
 	int i, j, count, ret;
 	u32 *elems;
 
-	grp->name = np->name;
-
 	ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &nconfigs);
 	if (ret)
 		return ret;
@@ -1003,21 +998,22 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_gro
 	if (!elems)
 		return -ENOMEM;
 
+	grp->grp.name = np->name;
+
 	ret = of_property_read_u32_array(np, "nuvoton,pins", elems, count);
 	if (ret)
 		return -EINVAL;
+	grp->grp.npins = count / 3;
 
-	grp->npins = count / 3;
-
-	grp->pins = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->pins), GFP_KERNEL);
-	if (!grp->pins)
+	pins = devm_kcalloc(npctl->dev, grp->grp.npins, sizeof(*pins), GFP_KERNEL);
+	if (!pins)
 		return -ENOMEM;
+	grp->grp.pins = pins;
 
-	grp->settings = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->settings), GFP_KERNEL);
-	if (!grp->settings)
+	pin = devm_kcalloc(npctl->dev, grp->grp.npins, sizeof(*pin), GFP_KERNEL);
+	if (!pin)
 		return -ENOMEM;
-
-	pin = grp->settings;
+	grp->data = pin;
 
 	for (i = 0, j = 0; i < count; i += 3, j++) {
 		pin->offset = elems[i] * MA35_MFP_REG_SZ_PER_BANK + MA35_MFP_REG_BASE;
@@ -1025,7 +1021,7 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_gro
 		pin->muxval = elems[i + 2];
 		pin->configs = configs;
 		pin->nconfigs = nconfigs;
-		grp->pins[j] = npctl->info->get_pin_num(pin->offset, pin->shift);
+		pins[j] = npctl->info->get_pin_num(pin->offset, pin->shift);
 		pin++;
 	}
 	return 0;
@@ -1036,7 +1032,7 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 {
 	struct device_node *child;
 	struct pinfunction *func;
-	struct ma35_pin_group *grp;
+	struct group_desc *grp;
 	static u32 grp_index;
 	const char **groups;
 	u32 ret, i = 0;
-- 
2.47.2



From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:15 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:15 +0200
Subject: [PATCH v2 2/5] pinctrl: nuvoton: Convert to use struct pingroup and PINCTRL_PINGROUP()
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <20250318105932.2090926-3-andriy.shevchenko@linux.intel.com>

The pin control header provides struct pingroup and PINCTRL_PINGROUP() macro.
Utilize them instead of open coded variants in the driver.

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 16 ++--------------
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 16 ++--------------
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 62a46d824b46..2601aacfb976 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -504,17 +504,6 @@ static const int lkgpo2_pins[] = { 9 };
 
 static const int nprd_smi_pins[] = { 190 };
 
-/*
- * pin:	     name, number
- * group:    name, npins,   pins
- * function: name, ngroups, groups
- */
-struct npcm7xx_group {
-	const char *name;
-	const unsigned int *pins;
-	int npins;
-};
-
 #define NPCM7XX_GRPS \
 	NPCM7XX_GRP(smb0), \
 	NPCM7XX_GRP(smb0b), \
@@ -642,9 +631,8 @@ enum {
 #undef NPCM7XX_GRP
 };
 
-static struct npcm7xx_group npcm7xx_groups[] = {
-#define NPCM7XX_GRP(x) { .name = #x, .pins = x ## _pins, \
-			.npins = ARRAY_SIZE(x ## _pins) }
+static struct pingroup npcm7xx_groups[] = {
+#define NPCM7XX_GRP(x) PINCTRL_PINGROUP(#x, x ## _pins, ARRAY_SIZE(x ## _pins))
 	NPCM7XX_GRPS
 #undef NPCM7XX_GRP
 };
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index f6a1e684a386..eac43315a360 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -587,17 +587,6 @@ static const int hgpio5_pins[] = { 25 };
 static const int hgpio6_pins[] = { 59 };
 static const int hgpio7_pins[] = { 60 };
 
-/*
- * pin:	     name, number
- * group:    name, npins,   pins
- * function: name, ngroups, groups
- */
-struct npcm8xx_pingroup {
-	const char *name;
-	const unsigned int *pins;
-	int npins;
-};
-
 #define NPCM8XX_GRPS \
 	NPCM8XX_GRP(gpi36), \
 	NPCM8XX_GRP(gpi35), \
@@ -829,9 +818,8 @@ enum {
 #undef NPCM8XX_GRP
 };
 
-static struct npcm8xx_pingroup npcm8xx_pingroups[] = {
-#define NPCM8XX_GRP(x) { .name = #x, .pins = x ## _pins, \
-			.npins = ARRAY_SIZE(x ## _pins) }
+static struct pingroup npcm8xx_pingroups[] = {
+#define NPCM8XX_GRP(x) PINCTRL_PINGROUP(#x, x ## _pins, ARRAY_SIZE(x ## _pins))
 	NPCM8XX_GRPS
 #undef NPCM8XX_GRP
 };
-- 
2.47.2



From Jonathan.Cameron at huawei.com  Tue Mar 18 04:12:42 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Tue, 18 Mar 2025 11:12:42 +0000
Subject: [PATCH 1/3] of: reserved_mem: Add functions to parse
 "memory-region"
In-Reply-To: <20250317232426.952188-2-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
	<20250317232426.952188-2-robh@kernel.org>
Message-ID: <20250318111242.00007457@huawei.com>

On Mon, 17 Mar 2025 18:24:21 -0500
"Rob Herring (Arm)" <robh at kernel.org> wrote:

> Drivers with "memory-region" properties currently have to do their own
> parsing of "memory-region" properties. The result is all the drivers
> have similar patterns of a call to parse "memory-region" and then get
> the region's address and size. As this is a standard property, it should
> have common functions for drivers to use. Add new functions to count the
> number of regions and retrieve the region's address as a resource.
> 
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> ---
>  drivers/of/of_reserved_mem.c    | 77 +++++++++++++++++++++++++++++++++
>  include/linux/of_reserved_mem.h | 26 +++++++++++
>  2 files changed, 103 insertions(+)
> 
> diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
> index 75e819f66a56..fd50038dff76 100644
> --- a/drivers/of/of_reserved_mem.c
> +++ b/drivers/of/of_reserved_mem.c
> @@ -12,6 +12,7 @@
>  #define pr_fmt(fmt)	"OF: reserved mem: " fmt
>  
>  #include <linux/err.h>
> +#include <linux/ioport.h>
>  #include <linux/libfdt.h>
>  #include <linux/of.h>
>  #include <linux/of_fdt.h>
> @@ -740,3 +741,79 @@ struct reserved_mem *of_reserved_mem_lookup(struct device_node *np)
>  	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(of_reserved_mem_lookup);
> +
> +/**
> + * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource
> + * @np:		node containing 'memory-region' property
> + * @idx:	index of 'memory-region' property to lookup
> + * @res:	Pointer to a struct resource to fill in with reserved region
> + *
> + * This function allows drivers to lookup a node's 'memory-region' property
> + * entries by index and return a struct resource for the entry.
> + *
> + * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region'
> + * is missing or unavailable, -EINVAL for any other error.
> + */
> +int of_reserved_mem_region_to_resource(const struct device_node *np, unsigned int idx, struct resource *res)

Maybe wrap?
 
> +{



From andriy.shevchenko at linux.intel.com  Tue Mar 18 03:57:16 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 18 Mar 2025 12:57:16 +0200
Subject: [PATCH v2 3/5] pinctrl: nuvoton: Make use of struct pinfunction and PINCTRL_PINFUNCTION()
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <20250318105932.2090926-4-andriy.shevchenko@linux.intel.com>

Since pin control provides a generic data type and a macro for
the pin function definition, use them in the driver.

Reviewed-by: Jonathan Neusch?fer <j.neuschaefer at gmx.net>
Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/pinctrl/nuvoton/pinctrl-ma35.c    | 19 ++++++++-----------
 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 11 +++--------
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 11 +++--------
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c | 11 +++--------
 4 files changed, 17 insertions(+), 35 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
index 59c4e7c6cdde..ad4f9ca414c8 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
@@ -98,12 +98,6 @@ static const u32 ds_3300mv_tbl[] = {
 	17100, 25600, 34100, 42800, 48000, 56000, 77000, 82000,
 };
 
-struct ma35_pin_func {
-	const char		*name;
-	const char		**groups;
-	u32			ngroups;
-};
-
 struct ma35_pin_setting {
 	u32			offset;
 	u32			shift;
@@ -149,7 +143,7 @@ struct ma35_pinctrl {
 	struct regmap		*regmap;
 	struct ma35_pin_group	*groups;
 	unsigned int		ngroups;
-	struct ma35_pin_func	*functions;
+	struct pinfunction	*functions;
 	unsigned int		nfunctions;
 };
 
@@ -1041,9 +1035,10 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 					u32 index)
 {
 	struct device_node *child;
-	struct ma35_pin_func *func;
+	struct pinfunction *func;
 	struct ma35_pin_group *grp;
 	static u32 grp_index;
+	const char **groups;
 	u32 ret, i = 0;
 
 	dev_dbg(npctl->dev, "parse function(%d): %s\n", index, np->name);
@@ -1055,12 +1050,12 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 	if (func->ngroups <= 0)
 		return 0;
 
-	func->groups = devm_kcalloc(npctl->dev, func->ngroups, sizeof(char *), GFP_KERNEL);
-	if (!func->groups)
+	groups = devm_kcalloc(npctl->dev, func->ngroups, sizeof(*groups), GFP_KERNEL);
+	if (!groups)
 		return -ENOMEM;
 
 	for_each_child_of_node(np, child) {
-		func->groups[i] = child->name;
+		groups[i] = child->name;
 		grp = &npctl->groups[grp_index++];
 		ret = ma35_pinctrl_parse_groups(child, grp, npctl, i++);
 		if (ret) {
@@ -1068,6 +1063,8 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
 			return ret;
 		}
 	}
+
+	func->groups = groups;
 	return 0;
 }
 
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 2601aacfb976..c6b11a198c76 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -639,13 +639,6 @@ static struct pingroup npcm7xx_groups[] = {
 
 #define NPCM7XX_SFUNC(a) NPCM7XX_FUNC(a, #a)
 #define NPCM7XX_FUNC(a, b...) static const char *a ## _grp[] = { b }
-#define NPCM7XX_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
-			.groups = nm ## _grp }
-struct npcm7xx_func {
-	const char *name;
-	const unsigned int ngroups;
-	const char *const *groups;
-};
 
 NPCM7XX_SFUNC(smb0);
 NPCM7XX_SFUNC(smb0b);
@@ -764,7 +757,8 @@ NPCM7XX_SFUNC(lkgpo2);
 NPCM7XX_SFUNC(nprd_smi);
 
 /* Function names */
-static struct npcm7xx_func npcm7xx_funcs[] = {
+static struct pinfunction npcm7xx_funcs[] = {
+#define NPCM7XX_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
 	NPCM7XX_MKFUNC(smb0),
 	NPCM7XX_MKFUNC(smb0b),
 	NPCM7XX_MKFUNC(smb0c),
@@ -880,6 +874,7 @@ static struct npcm7xx_func npcm7xx_funcs[] = {
 	NPCM7XX_MKFUNC(lkgpo1),
 	NPCM7XX_MKFUNC(lkgpo2),
 	NPCM7XX_MKFUNC(nprd_smi),
+#undef NPCM7XX_MKFUNC
 };
 
 #define NPCM7XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k) \
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index eac43315a360..62347a82282d 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -826,13 +826,6 @@ static struct pingroup npcm8xx_pingroups[] = {
 
 #define NPCM8XX_SFUNC(a) NPCM8XX_FUNC(a, #a)
 #define NPCM8XX_FUNC(a, b...) static const char *a ## _grp[] = { b }
-#define NPCM8XX_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
-			.groups = nm ## _grp }
-struct npcm8xx_func {
-	const char *name;
-	const unsigned int ngroups;
-	const char *const *groups;
-};
 
 NPCM8XX_SFUNC(gpi36);
 NPCM8XX_SFUNC(gpi35);
@@ -1055,7 +1048,8 @@ NPCM8XX_SFUNC(hgpio6);
 NPCM8XX_SFUNC(hgpio7);
 
 /* Function names */
-static struct npcm8xx_func npcm8xx_funcs[] = {
+static struct pinfunction npcm8xx_funcs[] = {
+#define NPCM8XX_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
 	NPCM8XX_MKFUNC(gpi36),
 	NPCM8XX_MKFUNC(gpi35),
 	NPCM8XX_MKFUNC(tp_jtag3),
@@ -1275,6 +1269,7 @@ static struct npcm8xx_func npcm8xx_funcs[] = {
 	NPCM8XX_MKFUNC(hgpio5),
 	NPCM8XX_MKFUNC(hgpio6),
 	NPCM8XX_MKFUNC(hgpio7),
+#undef NPCM8XX_MKFUNC
 };
 
 #define NPCM8XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
diff --git a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
index 2f97accef837..4264ca749175 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
@@ -482,13 +482,6 @@ static const struct pingroup wpcm450_groups[] = {
 
 #define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
 #define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
-#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
-			.groups = nm ## _grp }
-struct wpcm450_func {
-	const char *name;
-	const unsigned int ngroups;
-	const char *const *groups;
-};
 
 WPCM450_SFUNC(smb3);
 WPCM450_SFUNC(smb4);
@@ -555,7 +548,8 @@ WPCM450_FUNC(gpio, WPCM450_GRPS);
 #undef WPCM450_GRP
 
 /* Function names */
-static struct wpcm450_func wpcm450_funcs[] = {
+static struct pinfunction wpcm450_funcs[] = {
+#define WPCM450_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
 	WPCM450_MKFUNC(smb3),
 	WPCM450_MKFUNC(smb4),
 	WPCM450_MKFUNC(smb5),
@@ -616,6 +610,7 @@ static struct wpcm450_func wpcm450_funcs[] = {
 	WPCM450_MKFUNC(hg6),
 	WPCM450_MKFUNC(hg7),
 	WPCM450_MKFUNC(gpio),
+#undef WPCM450_MKFUNC
 };
 
 #define WPCM450_PINCFG(a, b, c, d, e, f, g) \
-- 
2.47.2



From mark.rutland at arm.com  Tue Mar 18 04:16:54 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 18 Mar 2025 11:16:54 +0000
Subject: [PATCH 1/2] arm64/mm/hotplug: Drop redundant [pgd|p4d]_present()
In-Reply-To: <20250221094449.1188427-2-anshuman.khandual@arm.com>
References: <20250221094449.1188427-1-anshuman.khandual@arm.com>
 <20250221094449.1188427-2-anshuman.khandual@arm.com>
Message-ID: <Z9lWJsA2hg2UKZ0T@J2N7QTR9R3>

On Fri, Feb 21, 2025 at 03:14:48PM +0530, Anshuman Khandual wrote:
> [pgd|p4d]_present() are inverse to their corresponding [pgd|p4d]_none().

Maybe their implementations happen to be inverse today, but the semantic
of pXX_present() is not the inverse of the semantic of pXX_none(). In
general, !pXX_none() does not imply pXX_present().

> So [pgd|p4d]_present() test right after corresponding [pgd|p4d]_none()
> inverse test does not make sense. Hence just drop these redundant
> checks.

I think the checks make sense in abstract, even if they're redundant
today

Is there any reason to remove these specific case?

Surely the compiler optimizes these out when they're redundant?

Mark.

> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ard Biesheuvel <ardb at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
>  arch/arm64/mm/mmu.c | 4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b4df5bc5b1b8..66906c45c7f6 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -952,7 +952,6 @@ static void unmap_hotplug_p4d_range(pgd_t *pgdp, unsigned long addr,
>  		if (p4d_none(p4d))
>  			continue;
>  
> -		WARN_ON(!p4d_present(p4d));
>  		unmap_hotplug_pud_range(p4dp, addr, next, free_mapped, altmap);
>  	} while (addr = next, addr < end);
>  }
> @@ -978,7 +977,6 @@ static void unmap_hotplug_range(unsigned long addr, unsigned long end,
>  		if (pgd_none(pgd))
>  			continue;
>  
> -		WARN_ON(!pgd_present(pgd));
>  		unmap_hotplug_p4d_range(pgdp, addr, next, free_mapped, altmap);
>  	} while (addr = next, addr < end);
>  }
> @@ -1114,7 +1112,6 @@ static void free_empty_p4d_table(pgd_t *pgdp, unsigned long addr,
>  		if (p4d_none(p4d))
>  			continue;
>  
> -		WARN_ON(!p4d_present(p4d));
>  		free_empty_pud_table(p4dp, addr, next, floor, ceiling);
>  	} while (addr = next, addr < end);
>  
> @@ -1153,7 +1150,6 @@ static void free_empty_tables(unsigned long addr, unsigned long end,
>  		if (pgd_none(pgd))
>  			continue;
>  
> -		WARN_ON(!pgd_present(pgd));
>  		free_empty_p4d_table(pgdp, addr, next, floor, ceiling);
>  	} while (addr = next, addr < end);
>  }
> -- 
> 2.30.2
> 


From catalin.marinas at arm.com  Tue Mar 18 04:24:10 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 18 Mar 2025 11:24:10 +0000
Subject: [PATCH 0/4] arm64: mitigate CVE-2024-7881 in the absence of
 firmware mitigation
In-Reply-To: <Z9ikak5AOtDJNVgE@linux.dev>
References: <20250128155428.210645-1-mark.rutland@arm.com>
 <174197730164.734861.6726211221092480832.b4-ty@arm.com>
 <20250317212611.GA12724@willie-the-truck>
 <Z9ikak5AOtDJNVgE@linux.dev>
Message-ID: <Z9lX2juZYCq_cnZs@arm.com>

On Mon, Mar 17, 2025 at 03:38:34PM -0700, Oliver Upton wrote:
> On Mon, Mar 17, 2025 at 09:26:12PM +0000, Will Deacon wrote:
> > On Fri, Mar 14, 2025 at 06:37:25PM +0000, Catalin Marinas wrote:
> > > On Tue, 28 Jan 2025 15:54:24 +0000, Mark Rutland wrote:
> > > > On some CPUs from Arm Ltd, it is possible for unprivileged code to cause
> > > > a hardware prefetcher to form an address using the contents of a memory
> > > > location which is accessible by privileged accesses in the active
> > > > translation regime, potentially leaking the contents of this memory
> > > > location via a side channel. This has been assigned CVE-2024-7881:
> > > > 
> > > >   https://developer.arm.com/Arm%20Security%20Center/Arm%20CPU%20Vulnerability%20CVE-2024-7881
> > > > 
> > > > [...]
> > > 
> > > Applied to arm64 (for-next/leaky-prefetcher), thanks!
> > > 
> > > There hasn't been much review (thanks Oliver for looking at the KVM
> > > bits) and there's some implied work that can go on top of this series.
> > > But the patches looked fine to me, so I queued them. Mark or others,
> > > please shout if you'd like them dropped, they are on a branch.
> > 
> > I'm really not comfortable with this series and would prefer to see it
> > dropped while we continue the discussion, especially as it's causing
> > minor conflicts with the KVM/arm64 tree in -next.
> 
> Catalin, unless you say otherwise, I'm going to assume this will be
> dropped in the interim.

Yes, I just dropped it.

-- 
Catalin


From ansuelsmth at gmail.com  Tue Mar 18 04:31:00 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Tue, 18 Mar 2025 12:31:00 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <4a9ac302-dfbe-4d76-a634-a445957c313c@kernel.org>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-10-ansuelsmth@gmail.com>
 <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>
 <67d0862f.df0a0220.375bd.6b15@mx.google.com>
 <4a9ac302-dfbe-4d76-a634-a445957c313c@kernel.org>
Message-ID: <67d95979.050a0220.166852.25e6@mx.google.com>

On Sun, Mar 16, 2025 at 06:01:02PM +0100, Krzysztof Kozlowski wrote:
> On 11/03/2025 19:51, Christian Marangi wrote:
> >>
> >>> +    $ref: /schemas/types.yaml#/definitions/uint32
> >>> +    enum: [0, 1]
> >>
> >> I don't understand why do you need index property here (which are
> >> usually not allowed).
> >>
> > 
> > Eh... As said in the description this is really to differentiate the 2
> > different physical port...
> > 
> > Each port have a dedicated oscillator for calibration and these
> > calibration are identified by an offset (all placed one after another in
> > a separate register space).
> 
> So different oscillators? Then describe the oscillator and its differences.
> 
> Different programing model? Different compatible.
> 
> Other difference? Depending what is the difference.
> 
> But there is no such thing as "different port ID" based on your
> description above. You just claimed that they are different, but you do
> not put that difference to hardware description. Instead you encode that
> difference in the drivers and it should be opposite. The DTS, so the
> hardware description, should tell you the difference. And I am sorry,
> but in 99% of cases "I am the first phy" and "I am the second" is not
> the actual difference we are interested in.
>

Ok to make it as clear as possible. (hope I don't contraddict with the
previous statement) (actually yes the "separate register space statement
was wrong and sorry for the confusion")

- 2 USB port
- USB 2.0 needs to be calibrated with an oscillator
- Each USB port have his own dedicated oscillator somewhere in the HW
- Each USB port have at the same offset a register to SELECT the
  oscillator. This register refer to the same oscillator selection in
  the HW.
  
  Example:
  reg 0x1fac0100 MASK 27:26 can be set to source out of oscillator 0,1,2
  reg 0x1fae0100 MASK 27:26 can be set to source out of oscillator 0,1,2

  Both register refer to the same oscillators in hardware (hence each
  port should select the correct one)
  Selecting oscillator 0 for both USB port is problematic.

With this in mind is it ok if I describe this with something like

airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL0>;

and some dt-bindings include

#define AIROHA_USB2_MONCLK_SEL0 0
#define AIROHA_USB2_MONCLK_SEL1 1
#define AIROHA_USB2_MONCLK_SEL2 2
#define AIROHA_USB2_MONCLK_SEL3 3

Or an enum of string like "osc0", "osc1", "osc2"...?

> > 
> > Oscillator 0 for physical port 0
> > Oscillator 1 for physcial port 1
> > 
> > And model this is a bit problematic without an additional property, any
> > hint for this?
> > 
> Best regards,
> Krzysztof

-- 
	Ansuel


From chenhuacai at kernel.org  Tue Mar 18 04:57:44 2025
From: chenhuacai at kernel.org (Huacai Chen)
Date: Tue, 18 Mar 2025 19:57:44 +0800
Subject: [PATCH v4 4/4] arm: defconfig: drop RT_GROUP_SCHED=y from bcm2835/tegra/omap2plus
In-Reply-To: <t2dustbykx2qd24wazjeiw5hch5nwr6z2ewmaf4srg6r2grwrf@rdw47chzkef2>
References: <20250115-fix-riscv-rt_group_sched-v4-0-607606fe73a5@coelacanthus.name>
 <20250115-fix-riscv-rt_group_sched-v4-4-607606fe73a5@coelacanthus.name> <t2dustbykx2qd24wazjeiw5hch5nwr6z2ewmaf4srg6r2grwrf@rdw47chzkef2>
Message-ID: <CAAhV-H4fTGs-7EXE0EcR=P6GqHF2fokRE-kEte+cDmhjy=FYsA@mail.gmail.com>

On Fri, Mar 7, 2025 at 3:19?AM Thierry Reding <thierry.reding at gmail.com> wrote:
>
> On Wed, Jan 15, 2025 at 04:41:23AM +0800, Celeste Liu wrote:
> > Commit 673ce00c5d6c ("ARM: omap2plus_defconfig: Add support for distros
> > with systemd") said it's because of recommendation from systemd. But
> > systemd changed their recommendation later.[1]
> >
> > For cgroup v1, if turned on, and there's any cgroup in the "cpu" hierarchy it
> > needs an RT budget assigned, otherwise the processes in it will not be able to
> > get RT at all. The problem with RT group scheduling is that it requires the
> > budget assigned but there's no way we could assign a default budget, since the
> > values to assign are both upper and lower time limits, are absolute, and need to
> > be sum up to < 1 for each individal cgroup. That means we cannot really come up
> > with values that would work by default in the general case.[2]
> >
> > For cgroup v2, it's almost unusable as well. If it turned on, the cpu controller
> > can only be enabled when all RT processes are in the root cgroup. But it will
> > lose the benefits of cgroup v2 if all RT process were placed in the same cgroup.
> >
> > Red Hat, Gentoo, Arch Linux and Debian all disable it. systemd also doesn't
> > support it.
> >
> > [1]: https://github.com/systemd/systemd/commit/f4e74be1856b3ac058acbf1be321c31d5299f69f
> > [2]: https://bugzilla.redhat.com/show_bug.cgi?id=1229700
> >
> > Tested-by: Stefan Wahren <wahrenst at gmx.net>
> > Acked-by: Kevin Hilman <khilman at baylibre.com>
> > Acked-by: Thierry Reding <treding at nvidia.com>
> > Signed-off-by: Celeste Liu <uwu at coelacanthus.name>
> > ---
> >  arch/arm/configs/bcm2835_defconfig   | 1 -
> >  arch/arm/configs/omap2plus_defconfig | 1 -
> >  arch/arm/configs/tegra_defconfig     | 1 -
> >  3 files changed, 3 deletions(-)
>
> Hi Arnd,
>
> is this something that you could pick up? I think so far only the RISC-V
> patch was picked up, but nobody seems to feel responsible for the ARM
> patch here.
I will take the LoongArch patch, but may be squashed to another one
about config file update.

Huacai

>
> Thierry


From amadeus at jmu.edu.cn  Tue Mar 18 05:00:03 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 20:00:03 +0800
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Enable regulators for Radxa E20C
In-Reply-To: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
Message-ID: <20250318120003.2340652-3-amadeus@jmu.edu.cn>

Enable pwm and fixed regulators for Radxa E20C. The pwm regulator is
used to power the CPU and GPU. Note that the LPDDR4 voltage is 1.1V.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 72 +++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
index 57a446b5cbd6..159b55aa970d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -100,6 +100,16 @@ vcc_3v3: regulator-3v3-vcc {
 		vin-supply = <&vcc5v0_sys>;
 	};
 
+	vcc_ddr: regulator-vcc-ddr {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_ddr";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
 	vcc5v0_sys: regulator-5v0-vcc-sys {
 		compatible = "regulator-fixed";
 		regulator-name = "vcc5v0_sys";
@@ -108,6 +118,56 @@ vcc5v0_sys: regulator-5v0-vcc-sys {
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
 	};
+
+	vdd_0v9: regulator-0v9-vdd {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_0v9";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <900000>;
+		regulator-max-microvolt = <900000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vdd_arm: regulator-vdd-arm {
+		compatible = "pwm-regulator";
+		pwms = <&pwm1 0 5000 1>;
+		pwm-supply = <&vcc5v0_sys>;
+		regulator-name = "vdd_arm";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <746000>;
+		regulator-max-microvolt = <1201000>;
+		regulator-settling-time-up-us = <250>;
+	};
+
+	vdd_logic: regulator-vdd-logic {
+		compatible = "pwm-regulator";
+		pwms = <&pwm2 0 5000 1>;
+		pwm-supply = <&vcc5v0_sys>;
+		regulator-name = "vdd_logic";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <705000>;
+		regulator-max-microvolt = <1006000>;
+		regulator-settling-time-up-us = <250>;
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+	cpu-supply = <&vdd_arm>;
 };
 
 &pinctrl {
@@ -132,6 +192,18 @@ wan_led_g: wan-led-g {
 	};
 };
 
+&pwm1 {
+	pinctrl-0 = <&pwm1m0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-0 = <&pwm2m0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
 &saradc {
 	vref-supply = <&vcc_1v8>;
 	status = "okay";
-- 
2.25.1



From amadeus at jmu.edu.cn  Tue Mar 18 05:00:01 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 20:00:01 +0800
Subject: [PATCH v2 0/2] arm64: dts: rockchip: Add pwm nodes for RK3528
Message-ID: <20250318120003.2340652-1-amadeus@jmu.edu.cn>

Add pwm nodes for RK3528. Most rk3528 boards use pwm-regulator to
supply to CPU, add node to enable them. The PWM core on RK3528 is
the same as RK3328, but the driver doesn't support interrupts yet.

Note that pwm regulator needs to be initialized in U-Boot:
```
&vdd_arm {
	regulator-init-microvolt = <953000>;
};

&vdd_logic {
	regulator-init-microvolt = <900000>;
};
```

Changes in v2:
  Remove merged bindings patch
  Remove pwm pinctrl in rk3528.dtsi
  Enable pwm regulator for Radxa E20C

Chukun Pan (2):
  arm64: dts: rockchip: Add pwm nodes for RK3528
  arm64: dts: rockchip: Enable regulators for Radxa E20C

 .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 72 +++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3528.dtsi      | 80 +++++++++++++++++++
 2 files changed, 152 insertions(+)

-- 
2.25.1



From vladimir.oltean at nxp.com  Tue Mar 18 04:43:16 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 13:43:16 +0200
Subject: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95
 ENETC PF
In-Reply-To: <PAXPR04MB8510DE829523749E9FB5E20B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250317155501.4haweyhlrfozg7zr@skbuf>
 <PAXPR04MB8510DE829523749E9FB5E20B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250318114316.2st2ylxuu7srloqc@skbuf>

On Tue, Mar 18, 2025 at 06:47:11AM +0200, Wei Fang wrote:
> > These rxnfc commands seem implemented identically to the corresponding
> > subset from enetc_get_rxnfc(). Rather than duplicating those, could you
> > rather return -EOPNOTSUPP for the unsupported ones on NETC v4, and reuse
> > enetc_get_rxnfc()?
> > 
> 
> I have explained it to Jakub in v2:
> https://lore.kernel.org/imx/PAXPR04MB8510B52B7D27640C557680B4881A2 at PAXPR04MB8510.eurprd04.prod.outlook.com/
> 
> So I don't want to reuse it for ENETC v4 PF.

A detail of the review process, written in Documentation/process/6.Followthrough.rst,
is that "Andrew Morton has suggested that every review comment which does
not result in a code change should result in an additional code comment
instead; that can help future reviewers avoid the questions which came
up the first time around."

[ personal mention: it doesn't have to be a code comment but can also be
  a sentence in the commit message ]

I believe that it would be good if you could apply that suggestion for
future submissions (not only for this particular comment).


From will at kernel.org  Tue Mar 18 04:43:24 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 11:43:24 +0000
Subject: [GIT PULL] arm64 fixes for -rc7
In-Reply-To: <20250317160034.GA12267@willie-the-truck>
References: <20250314160458.GA9438@willie-the-truck>
 <CAHk-=wgiX0q0WCL+SFwVCYtG7JR3=2Rshse-5J3AO2Y4AgT7Jw@mail.gmail.com>
 <20250317160034.GA12267@willie-the-truck>
Message-ID: <20250318114323.GA13641@willie-the-truck>

On Mon, Mar 17, 2025 at 04:00:35PM +0000, Will Deacon wrote:
> I'll have a crack at reworking things to take a 'const char *' instead,
> but it won't be for 6.14 as it'll be reasonably invasive.

Bah, that doesn't work at all because we need a string literal for the
asm and I can't spot any constraints that allow you to pass in a string.

So a different flavour of surgery is required...

Will


From lorenzo at kernel.org  Tue Mar 18 04:46:04 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:04 +0100
Subject: [PATCH net-next v2 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
Message-ID: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>

Introduce missing metadata support for some xdp drivers setting metadata
size building the skb from xdp_buff.
Please note most of the drivers are just compile tested.

---
Changes in v2:
- Improve commit logs for each patch specifying xdp headroom size for
  each modified driver.
- Link to v1: https://lore.kernel.org/r/20250311-mvneta-xdp-meta-v1-0-36cf1c99790e at kernel.org

---
Lorenzo Bianconi (7):
      net: mvneta: Add metadata support for xdp mode
      net: mvpp2: Add metadata support for xdp mode
      net: netsec: Add metadata support for xdp mode
      net: octeontx2: Add metadata support for xdp mode
      net: ethernet: mediatek: Add metadata support for xdp mode
      net: mana: Add metadata support for xdp mode
      net: ti: cpsw: Add metadata support for xdp mode

 drivers/net/ethernet/marvell/mvneta.c                  |  5 ++++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c        |  8 ++++++--
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 13 +++++++++----
 drivers/net/ethernet/mediatek/mtk_eth_soc.c            |  7 +++++--
 drivers/net/ethernet/microsoft/mana/mana_bpf.c         |  2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c          |  4 ++++
 drivers/net/ethernet/socionext/netsec.c                |  7 +++++--
 drivers/net/ethernet/ti/cpsw.c                         |  6 +++++-
 drivers/net/ethernet/ti/cpsw_new.c                     |  6 +++++-
 9 files changed, 44 insertions(+), 14 deletions(-)
---
base-commit: aedfbe251e1c56034cb6ffd87eabe5895b31ae5d
change-id: 20250310-mvneta-xdp-meta-3e0da8ef4498

Best regards,
-- 
Lorenzo Bianconi <lorenzo at kernel.org>



From lorenzo at kernel.org  Tue Mar 18 04:46:05 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:05 +0100
Subject: [PATCH net-next v2 1/7] net: mvneta: Add metadata support for xdp
 mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-1-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in mvneta driver
mvneta sets xdp headroom to:

MVNETA_MH_SIZE + MVNETA_SKB_HEADROOM

where

MVNETA_MH_SIZE 2
MVNETA_SKB_HEADROOM max(NET_SKB_PAD, XDP_PACKET_HEADROOM)

so the headroom is large enough to contain xdp_frame and xdp metadata.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/mvneta.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 44b18c57390927e37eac267632cace656bb5526e..147571fdada378e430fd96f2fb4a7e7870b784a2 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2342,7 +2342,7 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,
 	prefetch(data);
 	xdp_buff_clear_frags_flag(xdp);
 	xdp_prepare_buff(xdp, data, pp->rx_offset_correction + MVNETA_MH_SIZE,
-			 data_len, false);
+			 data_len, true);
 }
 
 static void
@@ -2396,6 +2396,7 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
 		      struct xdp_buff *xdp, u32 desc_status)
 {
 	struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
+	u32 metasize = xdp->data - xdp->data_meta;
 	struct sk_buff *skb;
 	u8 num_frags;
 
@@ -2410,6 +2411,8 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
 
 	skb_reserve(skb, xdp->data - xdp->data_hard_start);
 	skb_put(skb, xdp->data_end - xdp->data);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->ip_summed = mvneta_rx_csum(pp, desc_status);
 
 	if (unlikely(xdp_buff_has_frags(xdp)))

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:06 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:06 +0100
Subject: [PATCH net-next v2 2/7] net: mvpp2: Add metadata support for xdp
 mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-2-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in mvpp2 driver
mvpp2 driver sets xdp headroom to:

MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM

where

MVPP2_MH_SIZE 2
MVPP2_SKB_HEADROOM min(max(XDP_PACKET_HEADROOM, NET_SKB_PAD), 224)

so the headroom is large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index f166dc4e650372d66e248601a5c948819e1dcd79..54a235366a01bdba526a1956f27836bcdee210ae 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3915,13 +3915,13 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 
 	while (rx_done < rx_todo) {
 		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+		u32 rx_status, timestamp, metasize = 0;
 		struct mvpp2_bm_pool *bm_pool;
 		struct page_pool *pp = NULL;
 		struct sk_buff *skb;
 		unsigned int frag_size;
 		dma_addr_t dma_addr;
 		phys_addr_t phys_addr;
-		u32 rx_status, timestamp;
 		int pool, rx_bytes, err, ret;
 		struct page *page;
 		void *data;
@@ -3983,7 +3983,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 			xdp_init_buff(&xdp, PAGE_SIZE, xdp_rxq);
 			xdp_prepare_buff(&xdp, data,
 					 MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM,
-					 rx_bytes, false);
+					 rx_bytes, true);
 
 			ret = mvpp2_run_xdp(port, xdp_prog, &xdp, pp, &ps);
 
@@ -3999,6 +3999,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 				ps.rx_bytes += rx_bytes;
 				continue;
 			}
+
+			metasize = xdp.data - xdp.data_meta;
 		}
 
 		if (frag_size)
@@ -4038,6 +4040,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 
 		skb_reserve(skb, MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM);
 		skb_put(skb, rx_bytes);
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		skb->ip_summed = mvpp2_rx_csum(port, rx_status);
 		skb->protocol = eth_type_trans(skb, dev);
 

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:07 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:07 +0100
Subject: [PATCH net-next v2 3/7] net: netsec: Add metadata support for xdp
 mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-3-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in netsec driver.
netsec driver sets xdp headroom to NETSEC_RXBUF_HEADROOM:

NETSEC_RXBUF_HEADROOM max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN

so the headroom is large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/socionext/netsec.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index dc99821c6226fbaece65c8ade23899f610b44a9a..ee890de69ffe795dbdcc5331e36be86769f0d9a6 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -970,7 +970,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
 		struct netsec_desc *desc = &dring->desc[idx];
 		struct page *page = virt_to_page(desc->addr);
-		u32 xdp_result = NETSEC_XDP_PASS;
+		u32 metasize, xdp_result = NETSEC_XDP_PASS;
 		struct sk_buff *skb = NULL;
 		u16 pkt_len, desc_len;
 		dma_addr_t dma_handle;
@@ -1019,7 +1019,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		prefetch(desc->addr);
 
 		xdp_prepare_buff(&xdp, desc->addr, NETSEC_RXBUF_HEADROOM,
-				 pkt_len, false);
+				 pkt_len, true);
 
 		if (xdp_prog) {
 			xdp_result = netsec_run_xdp(priv, xdp_prog, &xdp);
@@ -1048,6 +1048,9 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 
 		skb_reserve(skb, xdp.data - xdp.data_hard_start);
 		skb_put(skb, xdp.data_end - xdp.data);
+		metasize = xdp.data - xdp.data_meta;
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		skb->protocol = eth_type_trans(skb, priv->ndev);
 
 		if (priv->rx_cksum_offload_flag &&

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:08 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:08 +0100
Subject: [PATCH net-next v2 4/7] net: octeontx2: Add metadata support for
 xdp mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-4-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in octeontx2 driver.
octeontx2 driver sets xdp headroom to OTX2_HEAD_ROOM

OTX2_HEAD_ROOM	OTX2_ALIGN
OTX2_ALIGN	128

so the headroom is large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 6bc5ce5a9f61cc2830975e7cc5219344760b0e51..af8cabe828d05c8832085d24d183312f24d00330 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -41,7 +41,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 				     struct bpf_prog *prog,
 				     struct nix_cqe_rx_s *cqe,
 				     struct otx2_cq_queue *cq,
-				     bool *need_xdp_flush);
+				     u32 *metasize, bool *need_xdp_flush);
 
 static void otx2_sq_set_sqe_base(struct otx2_snd_queue *sq,
 				 struct sk_buff *skb)
@@ -336,6 +336,7 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	struct nix_rx_sg_s *sg = &cqe->sg;
 	struct sk_buff *skb = NULL;
 	void *end, *start;
+	u32 metasize = 0;
 	u64 *seg_addr;
 	u16 *seg_size;
 	int seg;
@@ -346,7 +347,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	}
 
 	if (pfvf->xdp_prog)
-		if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq, need_xdp_flush))
+		if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq,
+					     &metasize, need_xdp_flush))
 			return;
 
 	skb = napi_get_frags(napi);
@@ -378,6 +380,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 		skb->mark = parse->match_id;
 
 	skb_mark_for_recycle(skb);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 
 	napi_gro_frags(napi);
 }
@@ -1482,7 +1486,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 				     struct bpf_prog *prog,
 				     struct nix_cqe_rx_s *cqe,
 				     struct otx2_cq_queue *cq,
-				     bool *need_xdp_flush)
+				     u32 *metasize, bool *need_xdp_flush)
 {
 	struct xdp_buff xdp, *xsk_buff = NULL;
 	unsigned char *hard_start;
@@ -1514,13 +1518,14 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 
 	hard_start = (unsigned char *)phys_to_virt(pa);
 	xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM,
-			 cqe->sg.seg_size, false);
+			 cqe->sg.seg_size, true);
 
 	act = bpf_prog_run_xdp(prog, &xdp);
 
 handle_xdp_verdict:
 	switch (act) {
 	case XDP_PASS:
+		*metasize = xdp.data - xdp.data_meta;
 		break;
 	case XDP_TX:
 		qidx += pfvf->hw.tx_queues;

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:09 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:09 +0100
Subject: [PATCH net-next v2 5/7] net: ethernet: mediatek: Add metadata
 support for xdp mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-5-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in mediatek driver.
mtk_eth_soc driver sets xdp headroom to XDP_PACKET_HEADROOM so the
headroom is large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 922330b3f4d70421276ecd3f4ab175b3ae263f71..43197b28b3e745319e974c6022a6a51b6953f60a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2122,7 +2122,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 		if (ring->page_pool) {
 			struct page *page = virt_to_head_page(data);
 			struct xdp_buff xdp;
-			u32 ret;
+			u32 ret, metasize;
 
 			new_data = mtk_page_pool_get_buff(ring->page_pool,
 							  &dma_addr,
@@ -2138,7 +2138,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
 			xdp_init_buff(&xdp, PAGE_SIZE, &ring->xdp_q);
 			xdp_prepare_buff(&xdp, data, MTK_PP_HEADROOM, pktlen,
-					 false);
+					 true);
 			xdp_buff_clear_frags_flag(&xdp);
 
 			ret = mtk_xdp_run(eth, ring, &xdp, netdev);
@@ -2158,6 +2158,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
 			skb_reserve(skb, xdp.data - xdp.data_hard_start);
 			skb_put(skb, xdp.data_end - xdp.data);
+			metasize = xdp.data - xdp.data_meta;
+			if (metasize)
+				skb_metadata_set(skb, metasize);
 			skb_mark_for_recycle(skb);
 		} else {
 			if (ring->frag_size <= PAGE_SIZE)

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:10 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:10 +0100
Subject: [PATCH net-next v2 6/7] net: mana: Add metadata support for xdp
 mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-6-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in mana driver.
mana driver sets xdp headroom to XDP_PACKET_HEADROOM so the headroom is
large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/microsoft/mana/mana_bpf.c | 2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c  | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
index 23b1521c0df96e7fd595daad8b49fa9be935090c..d30721d4516fc60cf8883f2b35cc561559082ccc 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
@@ -91,7 +91,7 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
 		goto out;
 
 	xdp_init_buff(xdp, PAGE_SIZE, &rxq->xdp_rxq);
-	xdp_prepare_buff(xdp, buf_va, XDP_PACKET_HEADROOM, pkt_len, false);
+	xdp_prepare_buff(xdp, buf_va, XDP_PACKET_HEADROOM, pkt_len, true);
 
 	act = bpf_prog_run_xdp(prog, xdp);
 
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 9a8171f099b63c6a1a6415f12718d46d5d835f97..e190d5ee51544090a703c14c76abdc23797f864a 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1559,8 +1559,12 @@ static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va,
 		return NULL;
 
 	if (xdp->data_hard_start) {
+		u32 metasize = xdp->data - xdp->data_meta;
+
 		skb_reserve(skb, xdp->data - xdp->data_hard_start);
 		skb_put(skb, xdp->data_end - xdp->data);
+		if (metasize)
+			skb_metadata_set(skb, metasize);
 		return skb;
 	}
 

-- 
2.48.1



From lorenzo at kernel.org  Tue Mar 18 04:46:11 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 12:46:11 +0100
Subject: [PATCH net-next v2 7/7] net: ti: cpsw: Add metadata support for
 xdp mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <20250318-mvneta-xdp-meta-v2-7-b6075778f61f@kernel.org>

Set metadata size building the skb from xdp_buff in cpsw/cpsw_new
drivers. ti cpsw and cpsw_new drivers set xdp headroom at least to
CPSW_HEADROOM_NA:

CPSW_HEADROOM_NA max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN

so the headroom is large enough to contain xdp_frame and xdp metadata.
Please note this patch is just compiled tested.

Reviewed-by: Michal Kubiak <michal.kubiak at intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
 drivers/net/ethernet/ti/cpsw.c     | 6 +++++-
 drivers/net/ethernet/ti/cpsw_new.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 0cb6fa6e5b7d4fb9703633f0d67a7e95e6e7d8aa..a984b7d84e5e5917b83547c862924ccd30d83601 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -351,6 +351,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	int			ret = 0, port, ch = xmeta->ch;
 	int			headroom = CPSW_HEADROOM_NA;
 	struct net_device	*ndev = xmeta->ndev;
+	u32			metasize = 0;
 	struct cpsw_priv	*priv;
 	struct page_pool	*pool;
 	struct sk_buff		*skb;
@@ -400,7 +401,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			size -= CPSW_RX_VLAN_ENCAP_HDR_SIZE;
 		}
 
-		xdp_prepare_buff(&xdp, pa, headroom, size, false);
+		xdp_prepare_buff(&xdp, pa, headroom, size, true);
 
 		port = priv->emac_port + cpsw->data.dual_emac;
 		ret = cpsw_run_xdp(priv, ch, &xdp, page, port, &len);
@@ -408,6 +409,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			goto requeue;
 
 		headroom = xdp.data - xdp.data_hard_start;
+		metasize = xdp.data - xdp.data_meta;
 
 		/* XDP prog can modify vlan tag, so can't use encap header */
 		status &= ~CPDMA_RX_VLAN_ENCAP;
@@ -423,6 +425,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
 
 	skb_reserve(skb, headroom);
 	skb_put(skb, len);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->dev = ndev;
 	if (status & CPDMA_RX_VLAN_ENCAP)
 		cpsw_rx_vlan_encap(skb);
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 3da1c131335df1ff79b32ce0e3ea5200a2e53f4b..5b5b52e4e7a757a14965fe6df41935aed547111f 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -293,6 +293,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	struct page_pool *pool;
 	struct sk_buff *skb;
 	struct xdp_buff xdp;
+	u32 metasize = 0;
 	int ret = 0;
 	dma_addr_t dma;
 
@@ -345,13 +346,14 @@ static void cpsw_rx_handler(void *token, int len, int status)
 			size -= CPSW_RX_VLAN_ENCAP_HDR_SIZE;
 		}
 
-		xdp_prepare_buff(&xdp, pa, headroom, size, false);
+		xdp_prepare_buff(&xdp, pa, headroom, size, true);
 
 		ret = cpsw_run_xdp(priv, ch, &xdp, page, priv->emac_port, &len);
 		if (ret != CPSW_XDP_PASS)
 			goto requeue;
 
 		headroom = xdp.data - xdp.data_hard_start;
+		metasize = xdp.data - xdp.data_meta;
 
 		/* XDP prog can modify vlan tag, so can't use encap header */
 		status &= ~CPDMA_RX_VLAN_ENCAP;
@@ -368,6 +370,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
 	skb->offload_fwd_mark = priv->offload_fwd_mark;
 	skb_reserve(skb, headroom);
 	skb_put(skb, len);
+	if (metasize)
+		skb_metadata_set(skb, metasize);
 	skb->dev = ndev;
 	if (status & CPDMA_RX_VLAN_ENCAP)
 		cpsw_rx_vlan_encap(skb);

-- 
2.48.1



From maz at kernel.org  Tue Mar 18 04:46:31 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 18 Mar 2025 11:46:31 +0000
Subject: [GIT PULL] arm64 fixes for -rc7
In-Reply-To: <20250317160034.GA12267@willie-the-truck>
References: <20250314160458.GA9438@willie-the-truck>
	<CAHk-=wgiX0q0WCL+SFwVCYtG7JR3=2Rshse-5J3AO2Y4AgT7Jw@mail.gmail.com>
	<20250317160034.GA12267@willie-the-truck>
Message-ID: <86tt7qmui0.wl-maz@kernel.org>

On Mon, 17 Mar 2025 16:00:35 +0000,
Will Deacon <will at kernel.org> wrote:
> 
> Hi Linus,
> 
> On Fri, Mar 14, 2025 at 10:34:57AM -1000, Linus Torvalds wrote:
> > On Fri, 14 Mar 2025 at 06:05, Will Deacon <will at kernel.org> wrote:
> > >
> > > Summary in the tag, but the main one is a horrible macro fix for our
> > > TLB flushing code which resulted in over-invalidation on the MMU
> > > notifier path.
> > 
> > From a quick look, that macro is still quite broken. Maybe not in ways
> > that matter, but still...
> > 
> > In particular, the 'stride' argument is used multiple times, and
> > without parentheses.
> > 
> > The 'lpa' argument is also used multiple times, and the input to that
> > is typically something like kvm_lpa2_is_enabled(), so I think it
> > potentially generates lots of pointless duplicate code with that
> > BUG_ON() in system_supports_lpa2() -> cpus_have_final_cap().
> > 
> > Maybe the compiler figures it out. But that macro is bad, bad, bad.
> > When it looks like a function, it should act like a function, and not
> > evaluate its arguments multiple times.
> > 
> > The most immediate bug may have been fixed, but not the actual real
> > horror of that thing.
> 
> Yes, the minimal fix for -rc7 avoids explicitly mutating the macro
> arguments but we still have the multiple-evaluation problem you point
> out above.
> 
> Ideally, this function would be rewritten as a 'static inline' but it
> was moved from C code into a macro as part of 360839027a6e ("arm64: tlb:
> Refactor the core flush algorithm of __flush_tlb_range") because we need
> to propagate the 'op' argument down to the low-level asm where it's
> stringified as part of the instruction mnemonic.
> 
> I'll have a crack at reworking things to take a 'const char *' instead,
> but it won't be for 6.14 as it'll be reasonably invasive.

I had a go at the 'const char *' approach, but couldn't make it work
reliably without making it very invasive.

I ended up with a slightly bigger hammer (see below) that survived
booting on a test box and running a couple of VMs. I wouldn't trust it
with anything more important than that though.

	M.

diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 8104aee4f9a08..0ff635cf8abf5 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -393,45 +393,93 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
  *    operations can only span an even number of pages. We save this for last to
  *    ensure 64KB start alignment is maintained for the LPA2 case.
  */
+typedef void (*tlbi_level_fn_t)(u64, int);
+typedef void (*tlbi_fn_t)(u64);
+
+#define __TLBI_LEVEL_FN(t, s)						\
+static inline void tlbi_level_##t##s(u64 addr, int level)		\
+{									\
+	__tlbi_level(t##s, addr, level);				\
+}									\
+static inline void tlbi_user_level_##t##s(u64 addr, int level)		\
+{									\
+	__tlbi_user_level(t##s, addr, level);				\
+}
+
+#define __TLBI_FN(t, s)							\
+static inline void tlbi_##t##s(u64 addr)				\
+{									\
+	__tlbi(t##s, addr);						\
+}									\
+static inline void tlbi_user_##t##s(u64 addr)				\
+{									\
+	__tlbi_user(t##s, addr);					\
+}
+
+#define TLBI_FNS(t)					\
+	__TLBI_FN(t, )					\
+	__TLBI_FN(t, is)				\
+	__TLBI_FN(r##t, )				\
+	__TLBI_FN(r##t, is)				\
+	__TLBI_LEVEL_FN(t, )				\
+	__TLBI_LEVEL_FN(t, is)				\
+	__TLBI_LEVEL_FN(r##t, )				\
+	__TLBI_LEVEL_FN(r##t, is)
+
+/* These are the TLBI instructions we allow for range operation */
+TLBI_FNS(ipas2e1)
+TLBI_FNS(vae1)
+TLBI_FNS(vale1)
+TLBI_FNS(vaale1)
+
+static __always_inline
+void __flush_tlb_range_by_op(tlbi_level_fn_t il, tlbi_level_fn_t iul,
+			     tlbi_fn_t ri, tlbi_fn_t riu,
+			     u64 start, u64 pages, int stride,
+			     u16 asid, int tlb_level,
+			     bool tlbi_user, bool lpa2)
+{
+	int num = 0;
+	int scale = 3;
+	int shift = lpa2 ? 16 : PAGE_SHIFT;
+	unsigned long addr;
+
+	while (pages > 0) {
+		if (!system_supports_tlb_range() ||
+		    pages == 1 ||
+		    (lpa2 && start != ALIGN(start, SZ_64K))) {
+			addr = __TLBI_VADDR(start, asid);
+			il(addr, tlb_level);
+			if (tlbi_user)
+				iul(addr, tlb_level);
+			start += stride;
+			pages -= stride >> PAGE_SHIFT;
+			continue;
+		}
+
+		num = __TLBI_RANGE_NUM(pages, scale);
+		if (num >= 0) {
+			addr = __TLBI_VADDR_RANGE(start >> shift, asid,
+						scale, num, tlb_level);
+			ri(addr);
+			if (tlbi_user)
+				riu(addr);
+			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT;
+			pages -= __TLBI_RANGE_PAGES(num, scale);
+		}
+		scale--;
+	}
+}
+
 #define __flush_tlb_range_op(op, start, pages, stride,			\
-				asid, tlb_level, tlbi_user, lpa2)	\
-do {									\
-	typeof(start) __flush_start = start;				\
-	typeof(pages) __flush_pages = pages;				\
-	int num = 0;							\
-	int scale = 3;							\
-	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
-	unsigned long addr;						\
-									\
-	while (__flush_pages > 0) {					\
-		if (!system_supports_tlb_range() ||			\
-		    __flush_pages == 1 ||				\
-		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
-			addr = __TLBI_VADDR(__flush_start, asid);	\
-			__tlbi_level(op, addr, tlb_level);		\
-			if (tlbi_user)					\
-				__tlbi_user_level(op, addr, tlb_level);	\
-			__flush_start += stride;			\
-			__flush_pages -= stride >> PAGE_SHIFT;		\
-			continue;					\
-		}							\
-									\
-		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
-		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
-						scale, num, tlb_level);	\
-			__tlbi(r##op, addr);				\
-			if (tlbi_user)					\
-				__tlbi_user(r##op, addr);		\
-			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
-		}							\
-		scale--;						\
-	}								\
-} while (0)
+			     asid, tlb_level, tlbi_user, lpa2)		\
+	__flush_tlb_range_by_op(tlbi_level_##op, tlbi_user_level_##op,	\
+				tlbi_r##op, tlbi_user_r##op,		\
+				start, pages, stride, asid,		\
+				tlb_level, tlbi_user, lpa2)
 
 #define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \
-	__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false, kvm_lpa2_is_enabled());
+	__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false, kvm_lpa2_is_enabled())
 
 static inline bool __flush_tlb_range_limit_excess(unsigned long start,
 		unsigned long end, unsigned long pages, unsigned long stride)

-- 
Without deviation from the norm, progress is not possible.


From amadeus at jmu.edu.cn  Tue Mar 18 05:00:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Tue, 18 Mar 2025 20:00:02 +0800
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
Message-ID: <20250318120003.2340652-2-amadeus@jmu.edu.cn>

Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
RK3328, but the driver does not support interrupts yet.

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 1af0d036cf32..621fc19ac0b3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -465,6 +465,86 @@ uart7: serial at ffa28000 {
 			status = "disabled";
 		};
 
+		pwm0: pwm at ffa90000 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90000 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm1: pwm at ffa90010 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90010 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm2: pwm at ffa90020 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90020 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm3: pwm at ffa90030 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa90030 0x0 0x10>;
+			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm4: pwm at ffa98000 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98000 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm5: pwm at ffa98010 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98010 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm6: pwm at ffa98020 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98020 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm7: pwm at ffa98030 {
+			compatible = "rockchip,rk3528-pwm",
+				     "rockchip,rk3328-pwm";
+			reg = <0x0 0xffa98030 0x0 0x10>;
+			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+			clock-names = "pwm", "pclk";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		saradc: adc at ffae0000 {
 			compatible = "rockchip,rk3528-saradc";
 			reg = <0x0 0xffae0000 0x0 0x10000>;
-- 
2.25.1



From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 05:08:00 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 13:08:00 +0100
Subject: [PATCH 6/9] ARM: dts: qcom: apq8064 merge hw splinlock into
 corresponding syscon device
In-Reply-To: <20250317-fix-nexus-4-v1-6-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-6-655c52e2ad97@oss.qualcomm.com>
Message-ID: <579cd909-8a0f-4998-88a6-47073ecc0eae@oss.qualcomm.com>

On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> Follow up the expected way of describing the SFPB hwspinlock and merge
> hwspinlock node into corresponding syscon node, fixing several dt-schema
> warnings.
> 
> Fixes: 24a9baf933dc ("ARM: dts: qcom: apq8064: Add hwmutex and SMEM nodes")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> index ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e..3728875a5506397b36a4c0d6a5ad12c067bbdd8c 100644
> --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> @@ -213,12 +213,6 @@ sleep_clk: sleep_clk {
>  		};
>  	};
>  
> -	sfpb_mutex: hwmutex {
> -		compatible = "qcom,sfpb-mutex";
> -		syscon = <&sfpb_wrapper_mutex 0x604 0x4>;
> -		#hwlock-cells = <1>;
> -	};
> -
>  	smem {
>  		compatible = "qcom,smem";
>  		memory-region = <&smem_region>;
> @@ -305,9 +299,10 @@ tlmm_pinmux: pinctrl at 800000 {
>  			pinctrl-0 = <&ps_hold_default_state>;
>  		};
>  
> -		sfpb_wrapper_mutex: syscon at 1200000 {
> -			compatible = "syscon";
> +		sfpb_mutex: hwmutex at 1200000 {
> +			compatible = "qcom,sfpb-mutex";
>  			reg = <0x01200000 0x8000>;

The mutex is at +0x600

Konrad


From ulf.hansson at linaro.org  Tue Mar 18 05:25:48 2025
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 18 Mar 2025 13:25:48 +0100
Subject: [GIT PULL] pmdomain fixes for v6.14-rc8
Message-ID: <20250318122548.1328552-1-ulf.hansson@linaro.org>

Hi Linus,

Here's a PR with a pmdomain fixe intended for v6.14-rc8. Details about the
highlights are as usual found in the signed tag.

Please pull this in!

Kind regards
Ulf Hansson


The following changes since commit d082ecbc71e9e0bf49883ee4afd435a77a5101b6:

  Linux 6.14-rc4 (2025-02-23 12:32:57 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git tags/pmdomain-v6.14-rc4

for you to fetch changes up to ef17b519088ee0c167cf507820609732ec8bad1a:

  pmdomain: amlogic: fix T7 ISP secpower (2025-03-05 15:51:04 +0100)

----------------------------------------------------------------
pmdomain providers:
 - amlogic: Fix T7 ISP secpower

----------------------------------------------------------------
Xianwei Zhao (1):
      pmdomain: amlogic: fix T7 ISP secpower

 drivers/pmdomain/amlogic/meson-secure-pwrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:26:46 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:26:46 +0200
Subject: [PATCH 8/9] ARM: dts: qcom: apq8064: use new compatible for SPS
 SIC device
In-Reply-To: <e26284b1-217b-4afe-af40-ae65cb7ee646@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-8-655c52e2ad97@oss.qualcomm.com>
 <e26284b1-217b-4afe-af40-ae65cb7ee646@oss.qualcomm.com>
Message-ID: <p4hda4puovabvqnf3unge2rifzu37hgim2k4fnvdpbekhojzq5@cx7j4hrspzdy>

On Tue, Mar 18, 2025 at 01:13:23PM +0100, Konrad Dybcio wrote:
> On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> > Use new SoC-specific compatible to the SPS SIC in addition to the
> > "syscon" compatible and rename the node to follow the purpose of it.
> > 
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > ---
> >  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > index 522387700fc8ce854c0995636998d2d4237e33df..a106f9f984fcb51dea1fff1515e6f290b36ccf99 100644
> > --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > @@ -402,8 +402,8 @@ saw3_vreg: regulator {
> >  			};
> >  		};
> >  
> > -		sps_sic_non_secure: sps-sic-non-secure at 12100000 {
> > -			compatible = "syscon";
> > +		sps_sic_non_secure: interrupt-controller at 12100000 {
> 
> The register that the consumer of this points to doesn't seem to exist..

It does, although it is marked as reserved. And this matches msm-3.4:

                .smsm_int.out_bit_pos =  1,
                .smsm_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
                .smsm_int.out_offset = 0x4094,

#define MSM_SIC_NON_SECURE_BASE IOMEM(0xFA600000)
#define MSM_SIC_NON_SECURE_PHYS 0x12100000
#define MSM_SIC_NON_SECURE_SIZE SZ_64K

I don't think anybody tried bringing up dsps on APQ8064 though.

-- 
With best wishes
Dmitry


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:27:23 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:27:23 +0200
Subject: [PATCH 9/9] ARM: dts: qcom: apq8064: move replicator out of soc
 node
In-Reply-To: <d0c03e76-8b61-4cc6-8839-448fbb64d4e9@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-9-655c52e2ad97@oss.qualcomm.com>
 <d0c03e76-8b61-4cc6-8839-448fbb64d4e9@oss.qualcomm.com>
Message-ID: <nr5xdpt5sm6xwghcjwmwv4higr2saddewaifwdi7ysztyvh56i@26omyq26f4cy>

On Tue, Mar 18, 2025 at 01:15:16PM +0100, Konrad Dybcio wrote:
> On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> > The CoreSight replicator device isn't a part of the system MMIO bus, as
> 
> the static kind, anyway - the dynamic ones are
> 
> > such it should not be a part of the soc node. Follow the example of
> > other platforms and move it out of the soc bus to the top-level.
> > 
> > Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components")
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > ---
> >  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 66 ++++++++++++++++----------------
> >  1 file changed, 33 insertions(+), 33 deletions(-)
> > 
> > diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > index a106f9f984fcb51dea1fff1515e6f290b36ccf99..acd94f3ba0350c5dcdd8f80885ee643d8cbddac7 100644
> > --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > @@ -278,6 +278,39 @@ scm {
> >  		};
> >  	};
> >  
> > +	replicator {
> > +		compatible = "arm,coresight-static-replicator";
> > +
> > +		clocks = <&rpmcc RPM_QDSS_CLK>;
> > +		clock-names = "apb_pclk";
> > +
> > +		out-ports {
> > +			#address-cells = <1>;
> > +			#size-cells = <0>;
> > +
> > +			port at 0 {
> > +				reg = <0>;
> > +				replicator_out0: endpoint {
> 
> Please take the artistic liberty to add a newline before subnodes and re-sort
> the in/out-ports to make them alphabetical

Ack

-- 
With best wishes
Dmitry


From ziyao at disroot.org  Tue Mar 18 05:12:33 2025
From: ziyao at disroot.org (Yao Zi)
Date: Tue, 18 Mar 2025 12:12:33 +0000
Subject: [PATCH 1/3] arm64: dts: rockchip: Add missing uart3 interrupt
 for RK3528
In-Reply-To: <20250318100010.2253408-2-amadeus@jmu.edu.cn>
References: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
 <20250318100010.2253408-2-amadeus@jmu.edu.cn>
Message-ID: <Z9ljMc96QoCNzzq3@pie>

On Tue, Mar 18, 2025 at 06:00:08PM +0800, Chukun Pan wrote:
> The interrupt of uart3 node on rk3528 is missing, fix it.
> 
> Fixes: 7983e6c379a9 ("arm64: dts: rockchip: Add base DT for rk3528 SoC")
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>

Reviewed-by: Yao Zi <ziyao at disroot.org>

Thanks for catching this, seems I messed uart3 up when cleaning the
devicetree.

> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 26c3559d6a6d..7f1ffd6003f5 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -404,9 +404,10 @@ uart2: serial at ffa00000 {
>  
>  		uart3: serial at ffa08000 {
>  			compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
> +			reg = <0x0 0xffa08000 0x0 0x100>;
>  			clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
>  			clock-names = "baudclk", "apb_pclk";
> -			reg = <0x0 0xffa08000 0x0 0x100>;
> +			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
>  			reg-io-width = <4>;
>  			reg-shift = <2>;
>  			status = "disabled";
> -- 
> 2.25.1
> 


From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 05:13:23 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 13:13:23 +0100
Subject: [PATCH 8/9] ARM: dts: qcom: apq8064: use new compatible for SPS
 SIC device
In-Reply-To: <20250317-fix-nexus-4-v1-8-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-8-655c52e2ad97@oss.qualcomm.com>
Message-ID: <e26284b1-217b-4afe-af40-ae65cb7ee646@oss.qualcomm.com>

On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> Use new SoC-specific compatible to the SPS SIC in addition to the
> "syscon" compatible and rename the node to follow the purpose of it.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> index 522387700fc8ce854c0995636998d2d4237e33df..a106f9f984fcb51dea1fff1515e6f290b36ccf99 100644
> --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> @@ -402,8 +402,8 @@ saw3_vreg: regulator {
>  			};
>  		};
>  
> -		sps_sic_non_secure: sps-sic-non-secure at 12100000 {
> -			compatible = "syscon";
> +		sps_sic_non_secure: interrupt-controller at 12100000 {

The register that the consumer of this points to doesn't seem to exist..

Konrad


From kevin.brodsky at arm.com  Tue Mar 18 05:14:18 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Tue, 18 Mar 2025 13:14:18 +0100
Subject: [PATCH 00/11] Always call constructor for kernel page tables
In-Reply-To: <70349335-84ee-4bca-a3d6-d7cf3c05b92b@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
 <70349335-84ee-4bca-a3d6-d7cf3c05b92b@arm.com>
Message-ID: <e79f9aa9-ce1b-4d42-8a61-aebaae1744fc@arm.com>

On 17/03/2025 16:30, Ryan Roberts wrote:
> On 17/03/2025 14:16, Kevin Brodsky wrote:
>> The complications in those special pgtable allocators beg the question:
>> does it really make sense to treat efi_mm and init_mm differently in
>> e.g. apply_to_pte_range()? Maybe what we really need is a way to tell if
>> an mm corresponds to user memory or not, and never use split locks for
>> non-user mm's. Feedback and suggestions welcome!
> The difference in treatment is whether or not the ptl is taken, right? So the
> real question is when calling apply_to_pte_range() for efi_mm, is there already
> a higher level serialization mechanism that prevents racy accesses? For init_mm,
> I think this is handled implicitly because there is no way for user space to
> cause apply_to_pte_range() for an arbitrary piece of kernel memory. Although I
> can't even see where apply_to_page_range() is called for efi_mm.

The commit I mentioned above, 61444cde9170 ("ARM: 8591/1: mm: use fully
constructed struct pages for EFI pgd allocations"), shows that
apply_to_page_range() is called from efi_set_mapping_permissions(), and
this indeed hasn't changed. It is itself called from efi_virtmap_init().
I would expect that no locking at all is necessary here, since the
mapping has just been created and surely isn't used yet. Now the
question is where exactly init_mm is special-cased in this manner. I can
see that walk_page_range() does something similar, there may be more
cases. And the other question is whether those functions are ever used
on special mm's, aside from efi_set_mapping_permissions().
> FWIW, contpte.c has mm_is_user() which is used by arm64.

Interesting! But not pretty, that's basically checking that the mm is
not &init_mm or &efi_mm... which wouldn't work for a generic
implementation. It feels like adding some attribute to mm_struct
wouldn't hurt. It looks like we've run out of MMF_* flags though :/

- Kevin


From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 05:15:16 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 13:15:16 +0100
Subject: [PATCH 9/9] ARM: dts: qcom: apq8064: move replicator out of soc
 node
In-Reply-To: <20250317-fix-nexus-4-v1-9-655c52e2ad97@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-9-655c52e2ad97@oss.qualcomm.com>
Message-ID: <d0c03e76-8b61-4cc6-8839-448fbb64d4e9@oss.qualcomm.com>

On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> The CoreSight replicator device isn't a part of the system MMIO bus, as

the static kind, anyway - the dynamic ones are

> such it should not be a part of the soc node. Follow the example of
> other platforms and move it out of the soc bus to the top-level.
> 
> Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 66 ++++++++++++++++----------------
>  1 file changed, 33 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> index a106f9f984fcb51dea1fff1515e6f290b36ccf99..acd94f3ba0350c5dcdd8f80885ee643d8cbddac7 100644
> --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> @@ -278,6 +278,39 @@ scm {
>  		};
>  	};
>  
> +	replicator {
> +		compatible = "arm,coresight-static-replicator";
> +
> +		clocks = <&rpmcc RPM_QDSS_CLK>;
> +		clock-names = "apb_pclk";
> +
> +		out-ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			port at 0 {
> +				reg = <0>;
> +				replicator_out0: endpoint {

Please take the artistic liberty to add a newline before subnodes and re-sort
the in/out-ports to make them alphabetical

Konrad


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:16:46 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:16:46 +0200
Subject: [PATCH 2/9] dt-bindings: display/msm: describe SFPB device
In-Reply-To: <20250318-adventurous-cherubic-coua-eecbbc@krzk-bin>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-2-655c52e2ad97@oss.qualcomm.com>
 <20250318-adventurous-cherubic-coua-eecbbc@krzk-bin>
Message-ID: <t37wdbwkbuyb5xn2lsdynp7on2oujvojmjkba24t4lqxuu64vl@htfidrpftxx7>

On Tue, Mar 18, 2025 at 08:55:59AM +0100, Krzysztof Kozlowski wrote:
> On Mon, Mar 17, 2025 at 07:44:37PM +0200, Dmitry Baryshkov wrote:
> > Add DT schema for the MultiMedia SubSystem System FPB device, which
> > provides several registers to control interface between multimedia
> > devices (primarily display) and system busses.
> > 
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > ---
> >  .../devicetree/bindings/display/msm/qcom,sfpb.yaml | 39 ++++++++++++++++++++++
> 
> Filename: qcom,apq8064-mmss-sfpb.yaml
> 
> >  1 file changed, 39 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..7ca105c97edd2f305527c58ae89b9b0cf22d3c8c
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/msm/qcom,sfpb.yaml
> > @@ -0,0 +1,39 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/msm/qcom,sfpb.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Qualcomm MultiMedia SubSystem System FPB
> > +
> > +maintainers:
> > +  - Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > +  - Rob Clark <robdclark at gmail.com>
> > +
> > +description:
> > +  The SFPB provides several registers controlling the multimedia attachment to
> > +  the system busses.
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - const: qcom,apq8064-mmss-sfpb
> > +      - const: syscon
> 
> Why this cannot be part of standard syscon bindings file? Looks simple
> enough.

Ack

-- 
With best wishes
Dmitry


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:17:46 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:17:46 +0200
Subject: [PATCH 3/9] dt-bindings: soc: qcom: add Smart Peripheral System
 Interrupt Controller
In-Reply-To: <20250318-dandelion-aardwolf-of-radiance-695fd9@krzk-bin>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-3-655c52e2ad97@oss.qualcomm.com>
 <20250318-dandelion-aardwolf-of-radiance-695fd9@krzk-bin>
Message-ID: <fr2s2ndjzyd2z7m6bsztudyb74a7rdvunehb6qfu6ar3s3i7hf@x7fap3clhlbe>

On Tue, Mar 18, 2025 at 08:56:46AM +0100, Krzysztof Kozlowski wrote:
> On Mon, Mar 17, 2025 at 07:44:38PM +0200, Dmitry Baryshkov wrote:
> > +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,sps-sic.yaml
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/soc/qcom/qcom,sps-sic.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Qualcomm Smart Peripheral System Interrupt Controller
> 
> Interrupt controller should have interrupt-cells. Or this is not
> interrupt controller...

Well, it is an interrupt controller, per the name of the block.

> 
> Anyway same comments as for previous patch.

Ack


-- 
With best wishes
Dmitry


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:19:04 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:19:04 +0200
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <7b0af57c-a38c-4c30-9bb7-efe511d6bd1d@arm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
 <7b0af57c-a38c-4c30-9bb7-efe511d6bd1d@arm.com>
Message-ID: <klcggfxrhjqty4rktx24xmnosqnwzsbyfzgv5ea6okqbffyswn@5yei6276hlla>

On Tue, Mar 18, 2025 at 10:38:17AM +0000, Suzuki K Poulose wrote:
> On 17/03/2025 17:44, Dmitry Baryshkov wrote:
> 
> nit: Subject:
> 
> s/qcom,coresight-static-replicator/arm,coresight-static-replicator
> 
> > As most other CoreSight devices the replicator can use either of the
> > optional clocks (or both). Document those optional clocks in the schema.
> > 
> > Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > ---
> >   .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
> >   1 file changed, 10 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
> > --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > @@ -30,6 +30,16 @@ properties:
> >     power-domains:
> >       maxItems: 1
> > +  clocks:
> > +    minItems: 1
> > +    maxItems: 2
> > +
> 
> For the static replicator, you don't have an APB clock, as they can't be
> programmed. It may have an ATB clock. So minItems 0, maxItems: 1

It can, see qcom-apq8064.dtsi

Also minItems:0 doesn't make sense to me. I'd rather keep this as an
optional property rather than requiring an empty set.

> 
> Suzuki
> 
> 
> 
> > +  clock-names:
> > +    minItems: 1
> > +    enum:
> > +      - apb_pclk
> > +      - atclk
> > +
> >     in-ports:
> >       $ref: /schemas/graph.yaml#/properties/ports
> >       additionalProperties: false
> > 
> 

-- 
With best wishes
Dmitry


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 05:24:14 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 14:24:14 +0200
Subject: [PATCH 6/9] ARM: dts: qcom: apq8064 merge hw splinlock into
 corresponding syscon device
In-Reply-To: <579cd909-8a0f-4998-88a6-47073ecc0eae@oss.qualcomm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-6-655c52e2ad97@oss.qualcomm.com>
 <579cd909-8a0f-4998-88a6-47073ecc0eae@oss.qualcomm.com>
Message-ID: <5g5ni3xoeliy4xs7wlhjjeust32qerutt4tdkkdvgeisdvbc6d@shlkxbzsw3vw>

On Tue, Mar 18, 2025 at 01:08:00PM +0100, Konrad Dybcio wrote:
> On 3/17/25 6:44 PM, Dmitry Baryshkov wrote:
> > Follow up the expected way of describing the SFPB hwspinlock and merge
> > hwspinlock node into corresponding syscon node, fixing several dt-schema
> > warnings.
> > 
> > Fixes: 24a9baf933dc ("ARM: dts: qcom: apq8064: Add hwmutex and SMEM nodes")
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > ---
> >  arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 11 +++--------
> >  1 file changed, 3 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > index ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e..3728875a5506397b36a4c0d6a5ad12c067bbdd8c 100644
> > --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
> > @@ -213,12 +213,6 @@ sleep_clk: sleep_clk {
> >  		};
> >  	};
> >  
> > -	sfpb_mutex: hwmutex {
> > -		compatible = "qcom,sfpb-mutex";
> > -		syscon = <&sfpb_wrapper_mutex 0x604 0x4>;
> > -		#hwlock-cells = <1>;
> > -	};
> > -
> >  	smem {
> >  		compatible = "qcom,smem";
> >  		memory-region = <&smem_region>;
> > @@ -305,9 +299,10 @@ tlmm_pinmux: pinctrl at 800000 {
> >  			pinctrl-0 = <&ps_hold_default_state>;
> >  		};
> >  
> > -		sfpb_wrapper_mutex: syscon at 1200000 {
> > -			compatible = "syscon";
> > +		sfpb_mutex: hwmutex at 1200000 {
> > +			compatible = "qcom,sfpb-mutex";
> >  			reg = <0x01200000 0x8000>;
> 
> The mutex is at +0x600

Indeed...

-- 
With best wishes
Dmitry


From xuwei5 at hisilicon.com  Tue Mar 18 05:30:21 2025
From: xuwei5 at hisilicon.com (Wei Xu)
Date: Tue, 18 Mar 2025 20:30:21 +0800
Subject: [PATCH] arm64: dts: hi3660: Add property for fixing CPUIdle
In-Reply-To: <20250310093708.9332-1-leo.yan@arm.com>
References: <20250310093708.9332-1-leo.yan@arm.com>
Message-ID: <67D9675D.6030001@hisilicon.com>

Hi Leo,

On 2025/3/10 17:37, Leo Yan wrote:
> During CPU low power modes, ETM components will lose their context.  Add
> the "arm,coresight-loses-context-with-cpu" property to ETM nodes to save
> and restore ETM context for CPU idle states.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---

Applied to the HiSilicon arm64 dt tree.
Thanks!

Best Regards,
Wei

>  arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> index 79a55a0fa2f1..4c6a075908d1 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi
> @@ -17,6 +17,7 @@ etm at ecc40000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu0>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -34,6 +35,7 @@ etm at ecd40000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu1>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -51,6 +53,7 @@ etm at ece40000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu2>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -68,6 +71,7 @@ etm at ecf40000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu3>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -160,6 +164,7 @@ etm at ed440000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu4>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -177,6 +182,7 @@ etm at ed540000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu5>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -194,6 +200,7 @@ etm at ed640000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu6>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> @@ -211,6 +218,7 @@ etm at ed740000 {
>  			clocks = <&crg_ctrl HI3660_PCLK>;
>  			clock-names = "apb_pclk";
>  			cpu = <&cpu7>;
> +			arm,coresight-loses-context-with-cpu;
>  
>  			out-ports {
>  				port {
> 


From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:38 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:38 +0200
Subject: [PATCH v6 04/14] phy: rockchip: samsung-hdptx: Do no set
 rk_hdptx_phy->rate in case of errors
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-4-8cb1678e7663@collabora.com>

Ensure rk_hdptx_ropll_tmds_cmn_config() updates hdptx->rate only after
all the other operations have been successful.

Fixes: c4b09c562086 ("phy: phy-rockchip-samsung-hdptx: Add clock provider support")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 34a7ef20936422b540b699f1acba44ca465501b7..d0989dc5a0173af4de4521e690c3f7b6cc343402 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1006,9 +1006,7 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 {
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
-	int i;
-
-	hdptx->rate = rate * 100;
+	int ret, i;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
 		if (rate == ropll_tmds_cfg[i].bit_rate) {
@@ -1063,7 +1061,11 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
-	return rk_hdptx_post_enable_pll(hdptx);
+	ret = rk_hdptx_post_enable_pll(hdptx);
+	if (!ret)
+		hdptx->rate = rate * 100;
+
+	return ret;
 }
 
 static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:39 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:39 +0200
Subject: [PATCH v6 05/14] phy: rockchip: samsung-hdptx: Drop unused struct
 lcpll_config
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-5-8cb1678e7663@collabora.com>

This is just a leftover from downstream support for HDMI 2.1.
Remove the unused struct for now.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -----------------------
 1 file changed, 31 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index d0989dc5a0173af4de4521e690c3f7b6cc343402..70621687b5eb3581a81af20b23d0be53263003bb 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -329,37 +329,6 @@ enum dp_link_rate {
 	DP_BW_HBR2,
 };
 
-struct lcpll_config {
-	u32 bit_rate;
-	u8 lcvco_mode_en;
-	u8 pi_en;
-	u8 clk_en_100m;
-	u8 pms_mdiv;
-	u8 pms_mdiv_afc;
-	u8 pms_pdiv;
-	u8 pms_refdiv;
-	u8 pms_sdiv;
-	u8 pi_cdiv_rstn;
-	u8 pi_cdiv_sel;
-	u8 sdm_en;
-	u8 sdm_rstn;
-	u8 sdc_frac_en;
-	u8 sdc_rstn;
-	u8 sdm_deno;
-	u8 sdm_num_sign;
-	u8 sdm_num;
-	u8 sdc_n;
-	u8 sdc_n2;
-	u8 sdc_num;
-	u8 sdc_deno;
-	u8 sdc_ndiv_rstn;
-	u8 ssc_en;
-	u8 ssc_fm_dev;
-	u8 ssc_fm_freq;
-	u8 ssc_clk_div_sel;
-	u8 cd_tx_ser_rate_sel;
-};
-
 struct ropll_config {
 	u32 bit_rate;
 	u8 pms_mdiv;

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:40 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:40 +0200
Subject: [PATCH v6 06/14] phy: rockchip: samsung-hdptx: Drop unused phy_cfg
 driver data
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-6-8cb1678e7663@collabora.com>

There is no usage of phy_cfg in the upstream driver data, nor in the
downstream one, hence remove it.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 70621687b5eb3581a81af20b23d0be53263003bb..c9f79c4e698cef405dd2b6a8c1071e296464c36e 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -397,7 +397,6 @@ struct rk_hdptx_phy {
 	int phy_id;
 
 	struct phy *phy;
-	struct phy_config *phy_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:41 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:41 +0200
Subject: [PATCH v6 07/14] phy: rockchip: samsung-hdptx: Drop superfluous
 cfgs driver data
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-7-8cb1678e7663@collabora.com>

The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
but it is only used during probe() in order to setup ->phy_id.

Use a probe() local variable to store device match data and remove the
now unnecessary member from struct rk_hdptx_phy.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index c9f79c4e698cef405dd2b6a8c1071e296464c36e..2c0ae2442842fe84a86eba6815125be9d31cc41e 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -392,10 +392,7 @@ struct rk_hdptx_phy {
 	struct regmap *regmap;
 	struct regmap *grf;
 
-	/* PHY const config */
-	const struct rk_hdptx_phy_cfg *cfgs;
 	int phy_id;
-
 	struct phy *phy;
 	struct clk_bulk_data *clks;
 	int nr_clks;
@@ -1894,6 +1891,7 @@ static int rk_hdptx_phy_runtime_resume(struct device *dev)
 
 static int rk_hdptx_phy_probe(struct platform_device *pdev)
 {
+	const struct rk_hdptx_phy_cfg *cfgs;
 	struct phy_provider *phy_provider;
 	struct device *dev = &pdev->dev;
 	struct rk_hdptx_phy *hdptx;
@@ -1912,14 +1910,14 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(regs),
 				     "Failed to ioremap resource\n");
 
-	hdptx->cfgs = device_get_match_data(dev);
-	if (!hdptx->cfgs)
+	cfgs = device_get_match_data(dev);
+	if (!cfgs)
 		return dev_err_probe(dev, -EINVAL, "missing match data\n");
 
 	/* find the phy-id from the io address */
 	hdptx->phy_id = -ENODEV;
-	for (id = 0; id < hdptx->cfgs->num_phys; id++) {
-		if (res->start == hdptx->cfgs->phy_ids[id]) {
+	for (id = 0; id < cfgs->num_phys; id++) {
+		if (res->start == cfgs->phy_ids[id]) {
 			hdptx->phy_id = id;
 			break;
 		}

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:42 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:42 +0200
Subject: [PATCH v6 08/14] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit
 conversion overhead
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-8-8cb1678e7663@collabora.com>

The ropll_tmds_cfg table used to identify the configuration params for
the supported rates expects the search key, i.e. bit_rate member of
struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
Hz).  This requires multiple conversions between these units being
performed at runtime.

Improve implementation clarity and efficiency by consistently using the
Hz unit throughout driver's internal data structures and functions.
Also rename the rather misleading struct member.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
 1 file changed, 39 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 2c0ae2442842fe84a86eba6815125be9d31cc41e..e4f6b1d6d999ae01eb7a9a35ea1748b8a2da339c 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -330,7 +330,7 @@ enum dp_link_rate {
 };
 
 struct ropll_config {
-	u32 bit_rate;
+	unsigned long long rate;
 	u8 pms_mdiv;
 	u8 pms_mdiv_afc;
 	u8 pms_pdiv;
@@ -410,45 +410,45 @@ struct rk_hdptx_phy {
 };
 
 static const struct ropll_config ropll_tmds_cfg[] = {
-	{ 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 594000000ULL, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 371250000ULL, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 297000000ULL, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
+	{ 162000000ULL, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 185625000ULL, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
+	{ 154000000ULL, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
+	{ 148500000ULL, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
 	  0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
+	{ 146250000ULL, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
+	{ 119000000ULL, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
+	{ 106500000ULL, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 108000000ULL, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
+	{ 85500000ULL, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
+	{ 83500000ULL, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 92812500ULL, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+	{ 74250000ULL, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
+	{ 65000000ULL, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
 	  1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
+	{ 33750000ULL, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
 	  1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 40000000ULL, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+	{ 27000000ULL, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
 	  0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
-	{ 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
+	{ 25175000ULL, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
 	  1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
 };
 
@@ -894,10 +894,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
 	regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
 }
 
-static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
+static bool rk_hdptx_phy_clk_pll_calc(unsigned long long rate,
 				      struct ropll_config *cfg)
 {
-	const unsigned int fout = data_rate / 2, fref = 24000;
+	const unsigned int fout = div_u64(rate, 200), fref = 24000;
 	unsigned long k = 0, lc, k_sub, lc_sub;
 	unsigned int fvco, sdc;
 	u32 mdiv, sdiv, n = 8;
@@ -967,14 +967,14 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
 }
 
 static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
-					  unsigned int rate)
+					  unsigned long long rate)
 {
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
 	int ret, i;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].bit_rate) {
+		if (rate == ropll_tmds_cfg[i].rate) {
 			cfg = &ropll_tmds_cfg[i];
 			break;
 		}
@@ -988,8 +988,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 		}
 	}
 
-	dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
-		cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
+	dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
+		__func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
 		cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
 
 	rk_hdptx_pre_power_up(hdptx);
@@ -1028,19 +1028,19 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 
 	ret = rk_hdptx_post_enable_pll(hdptx);
 	if (!ret)
-		hdptx->rate = rate * 100;
+		hdptx->rate = rate;
 
 	return ret;
 }
 
 static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
-					   unsigned int rate)
+					   unsigned long long rate)
 {
 	rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate > HDMI14_MAX_RATE / 100) {
+	if (rate > HDMI14_MAX_RATE) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {
@@ -1093,7 +1093,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
 }
 
 static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
-				     unsigned int rate)
+				     unsigned long long rate)
 {
 	enum phy_mode mode = phy_get_mode(hdptx->phy);
 	u32 status;
@@ -1411,8 +1411,8 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
 static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
-	int bus_width = phy_get_bus_width(hdptx->phy);
 	enum phy_mode mode = phy_get_mode(phy);
+	unsigned long long rate;
 	int ret, lane;
 
 	/*
@@ -1420,10 +1420,10 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 	 * from the HDMI bridge driver until phy_configure_opts_hdmi
 	 * becomes available in the PHY API.
 	 */
-	unsigned int rate = bus_width & 0xfffffff;
+	rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+	rate *= 100;
 
-	dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
-		__func__, bus_width, rate);
+	dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, rate);
 
 	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
 	if (ret)
@@ -1785,7 +1785,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
+	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1806,18 +1806,17 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate)
 {
-	u32 bit_rate = rate / 100;
 	int i;
 
 	if (rate > HDMI20_MAX_RATE)
 		return rate;
 
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+		if (rate == ropll_tmds_cfg[i].rate)
 			break;
 
 	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+	    !rk_hdptx_phy_clk_pll_calc(rate, NULL))
 		return -EINVAL;
 
 	return rate;
@@ -1828,7 +1827,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
 }
 
 static const struct clk_ops hdptx_phy_clk_ops = {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:43 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:43 +0200
Subject: [PATCH v6 09/14] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-9-8cb1678e7663@collabora.com>

The current workaround to setup the TMDS character rate relies on the
unconventional usage of phy_set_bus_width().

Make use of the recently introduced HDMI PHY configuration API to
properly handle the setup.  The workaround will be dropped as soon as
the switch has been completed on both ends.

Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
HDMI parameters during phy_configure().

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 +++++++++++++++++------
 1 file changed, 47 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index e4f6b1d6d999ae01eb7a9a35ea1748b8a2da339c..62de40515338730a56a83972ad57a7e71c3ca5cb 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -394,6 +394,7 @@ struct rk_hdptx_phy {
 
 	int phy_id;
 	struct phy *phy;
+	struct phy_configure_opts_hdmi hdmi_cfg;
 	struct clk_bulk_data *clks;
 	int nr_clks;
 	struct reset_control_bulk_data rsts[RST_MAX];
@@ -1412,20 +1413,24 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 {
 	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
 	enum phy_mode mode = phy_get_mode(phy);
-	unsigned long long rate;
 	int ret, lane;
 
-	/*
-	 * FIXME: Temporary workaround to pass pixel_clk_rate
-	 * from the HDMI bridge driver until phy_configure_opts_hdmi
-	 * becomes available in the PHY API.
-	 */
-	rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
-	rate *= 100;
+	if (mode != PHY_MODE_DP) {
+		if (!hdptx->hdmi_cfg.tmds_char_rate) {
+			/*
+			 * FIXME: Temporary workaround to setup TMDS char rate
+			 * from the RK DW HDMI QP bridge driver.
+			 * Will be removed as soon the switch to the HDMI PHY
+			 * configuration API has been completed on both ends.
+			 */
+			hdptx->hdmi_cfg.tmds_char_rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+			hdptx->hdmi_cfg.tmds_char_rate *= 100;
+		}
 
-	dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, rate);
+		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+	}
 
-	ret = rk_hdptx_phy_consumer_get(hdptx, rate);
+	ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
 	if (ret)
 		return ret;
 
@@ -1456,7 +1461,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		regmap_write(hdptx->grf, GRF_HDPTX_CON0,
 			     HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
 
-		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
 		if (ret)
 			rk_hdptx_phy_consumer_put(hdptx, true);
 	}
@@ -1471,8 +1476,27 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
 	return rk_hdptx_phy_consumer_put(hdptx, false);
 }
 
-static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
-				      struct phy_configure_opts_dp *dp)
+static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
+					   struct phy_configure_opts_hdmi *hdmi)
+{
+	int i;
+
+	if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+		if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
+			break;
+
+	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
+	    !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rk_hdptx_phy_verify_dp_config(struct rk_hdptx_phy *hdptx,
+					 struct phy_configure_opts_dp *dp)
 {
 	int i;
 
@@ -1732,12 +1756,18 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	enum phy_mode mode = phy_get_mode(phy);
 	int ret;
 
-	if (mode != PHY_MODE_DP)
-		return 0;
+	if (mode != PHY_MODE_DP) {
+		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+		if (ret)
+			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
+		else
+			hdptx->hdmi_cfg = opts->hdmi;
+		return ret;
+	}
 
-	ret = rk_hdptx_phy_verify_config(hdptx, &opts->dp);
+	ret = rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
 	if (ret) {
-		dev_err(hdptx->dev, "invalid params for phy configure\n");
+		dev_err(hdptx->dev, "invalid dp params for phy configure\n");
 		return ret;
 	}
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:44 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:44 +0200
Subject: [PATCH v6 10/14] phy: rockchip: samsung-hdptx: Provide config
 params validation support
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-10-8cb1678e7663@collabora.com>

Implement the phy_ops.validate() callback to allow checking the PHY
configuration parameters without actually applying them.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 62de40515338730a56a83972ad57a7e71c3ca5cb..80dd896861bcac6ef9dbde410327b893f8039627 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1799,10 +1799,22 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 	return 0;
 }
 
+static int rk_hdptx_phy_validate(struct phy *phy, enum phy_mode mode,
+				 int submode, union phy_configure_opts *opts)
+{
+	struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+
+	if (mode != PHY_MODE_DP)
+		return rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+
+	return rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
+}
+
 static const struct phy_ops rk_hdptx_phy_ops = {
 	.power_on  = rk_hdptx_phy_power_on,
 	.power_off = rk_hdptx_phy_power_off,
 	.configure = rk_hdptx_phy_configure,
+	.validate  = rk_hdptx_phy_validate,
 	.owner	   = THIS_MODULE,
 };
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:34 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:34 +0200
Subject: [PATCH v6 00/14] phy: rockchip: samsung-hdptx: Support high color
 depth management
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>

This series relies on the new HDMI PHY configuration options [1] (patch
included here for convenience) to provide high color depth management
for rockchip-samsung-hdptx, and to introduce a proper solution to setup
the TMDS character rate on this PHY.

[1] https://lore.kernel.org/lkml/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com/

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
Changes in v6:
- Collected R-b tags from Dmitry
- Updated commit description for "phy: rockchip: samsung-hdptx: Fix
  clock ratio setup"
- Added new patch "phy: rockchip: samsung-hdptx: Do no set
  rk_hdptx_phy->rate in case of errors"
- Replaced some "unsigned long" and "u32" types with "unsigned long
  long" in "phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit conversion
  overhead" to match the tmds_char_rate type (Dmitry)
- Added new patch "phy: rockchip: samsung-hdptx: Rename ambiguous
  rk_hdptx_phy->rate", originally part of "phy: rockchip: samsung-hdptx:
  Optimize internal rate handling" (Dmitry)
- Rebased series onto next-20250317
- Link to v5: https://lore.kernel.org/r/20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1 at collabora.com

Changes in v5:
- Moved the patch eliminating the unnecessary and rather confusing
  Hz<->hHz unit conversion before all the others adding new content
- Moved the patch adding high color depth management to the last
  position, so that it follows the internal rate handling optimization
- Amended description for a few patches to improve clarity
- Performed some trivial refactoring in some cases while dealing with
  rebase conflicts
- Link to v4: https://lore.kernel.org/r/20250304-phy-sam-hdptx-bpc-v4-0-8657847c13f7 at collabora.com

Changes in v4:
- Added patches to drop unnecessary phy_cfg & cfgs driver data
- Embedded struct phy_configure_opts_hdmi in driver data (Dmitry)
- Added new patch to provide config params validation support
- Provided a patch to restrict altering TMDS char rate via CCF (Dmitry)
- Made a bunch of small tweaks here and there
- Link to v3: https://lore.kernel.org/r/20250223-phy-sam-hdptx-bpc-v3-0-66a5c8e68327 at collabora.com

Changes in v3:
- Rebased series onto next-20250221 and fixed several conflicts due to
  the recently introduced eDP support
- Link to v2: https://lore.kernel.org/r/20241212-phy-sam-hdptx-bpc-v2-0-57e672c7c7c4 at collabora.com

Changes in v2:
- Added new patches providing a bug fix and several driver cleanups and
  improvements
- Link to v1: https://lore.kernel.org/r/20241207-phy-sam-hdptx-bpc-v1-0-03c2e4d6d797 at collabora.com

---
Cristian Ciocaltea (13):
      phy: hdmi: Add color depth configuration
      phy: rockchip: samsung-hdptx: Fix clock ratio setup
      phy: rockchip: samsung-hdptx: Do no set rk_hdptx_phy->rate in case of errors
      phy: rockchip: samsung-hdptx: Drop unused struct lcpll_config
      phy: rockchip: samsung-hdptx: Drop unused phy_cfg driver data
      phy: rockchip: samsung-hdptx: Drop superfluous cfgs driver data
      phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit conversion overhead
      phy: rockchip: samsung-hdptx: Setup TMDS char rate via phy_configure_opts_hdmi
      phy: rockchip: samsung-hdptx: Provide config params validation support
      phy: rockchip: samsung-hdptx: Restrict altering TMDS char rate via CCF
      phy: rockchip: samsung-hdptx: Rename ambiguous rk_hdptx_phy->rate
      phy: rockchip: samsung-hdptx: Optimize internal rate handling
      phy: rockchip: samsung-hdptx: Add high color depth management

Sandor Yu (1):
      phy: Add HDMI configuration options

 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 292 +++++++++++++---------
 include/linux/phy/phy-hdmi.h                      |  21 ++
 include/linux/phy/phy.h                           |   7 +-
 3 files changed, 202 insertions(+), 118 deletions(-)
---
base-commit: e94bd4ec45ac156616da285a0bf03056cd7430fc
change-id: 20241206-phy-sam-hdptx-bpc-3b05c6276fd7



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:35 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:35 +0200
Subject: [PATCH v6 01/14] phy: Add HDMI configuration options
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-1-8cb1678e7663@collabora.com>

From: Sandor Yu <Sandor.yu at nxp.com>

Allow HDMI PHYs to be configured through the generic
functions through a custom structure added to the generic union.

The parameters added here are based on HDMI PHY
implementation practices.  The current set of parameters
should cover the potential users.

Signed-off-by: Sandor Yu <Sandor.yu at nxp.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Maxime Ripard <mripard at kernel.org>
Acked-by: Vinod Koul <vkoul at kernel.org>
Link: https://lore.kernel.org/r/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu at nxp.com
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 19 +++++++++++++++++++
 include/linux/phy/phy.h      |  7 ++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a696922bc7f29af63d88646701b2c0fcee5c885
--- /dev/null
+++ b/include/linux/phy/phy-hdmi.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2022,2024 NXP
+ */
+
+#ifndef __PHY_HDMI_H_
+#define __PHY_HDMI_H_
+
+/**
+ * struct phy_configure_opts_hdmi - HDMI configuration set
+ * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ *
+ * This structure is used to represent the configuration state of a HDMI phy.
+ */
+struct phy_configure_opts_hdmi {
+	unsigned long long tmds_char_rate;
+};
+
+#endif /* __PHY_HDMI_H_ */
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index e63e6e70e860421539179c8178cbe742410cc546..437769e061b7030105c9ea4e9b0da9d32b6fa158 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <linux/phy/phy-dp.h>
+#include <linux/phy/phy-hdmi.h>
 #include <linux/phy/phy-lvds.h>
 #include <linux/phy/phy-mipi-dphy.h>
 
@@ -42,7 +43,8 @@ enum phy_mode {
 	PHY_MODE_MIPI_DPHY,
 	PHY_MODE_SATA,
 	PHY_MODE_LVDS,
-	PHY_MODE_DP
+	PHY_MODE_DP,
+	PHY_MODE_HDMI,
 };
 
 enum phy_media {
@@ -60,11 +62,14 @@ enum phy_media {
  *		the DisplayPort protocol.
  * @lvds:	Configuration set applicable for phys supporting
  *		the LVDS phy mode.
+ * @hdmi:	Configuration set applicable for phys supporting
+ *		the HDMI phy mode.
  */
 union phy_configure_opts {
 	struct phy_configure_opts_mipi_dphy	mipi_dphy;
 	struct phy_configure_opts_dp		dp;
 	struct phy_configure_opts_lvds		lvds;
+	struct phy_configure_opts_hdmi		hdmi;
 };
 
 /**

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:36 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:36 +0200
Subject: [PATCH v6 02/14] phy: hdmi: Add color depth configuration
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-2-8cb1678e7663@collabora.com>

Extend the HDMI configuration options to allow managing bits per color
channel.  This is required by some PHY drivers such as
rockchip-samsung-hdptx.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 include/linux/phy/phy-hdmi.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h
index 6a696922bc7f29af63d88646701b2c0fcee5c885..f0ec963c6e84f1b7728acafc824dff191c6b873d 100644
--- a/include/linux/phy/phy-hdmi.h
+++ b/include/linux/phy/phy-hdmi.h
@@ -9,11 +9,13 @@
 /**
  * struct phy_configure_opts_hdmi - HDMI configuration set
  * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ * @bpc: Bits per color channel.
  *
  * This structure is used to represent the configuration state of a HDMI phy.
  */
 struct phy_configure_opts_hdmi {
 	unsigned long long tmds_char_rate;
+	unsigned int bpc;
 };
 
 #endif /* __PHY_HDMI_H_ */

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:37 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:37 +0200
Subject: [PATCH v6 03/14] phy: rockchip: samsung-hdptx: Fix clock ratio
 setup
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-3-8cb1678e7663@collabora.com>

The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
and not before.

Therefore, use the correct comparison operator '>' instead of '>=' when
checking the max rate.  While at it, introduce a define for this rate
limit constant.

Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index fe7c057483563686b8076cf2ce562440cfa6fe55..34a7ef20936422b540b699f1acba44ca465501b7 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -320,6 +320,7 @@
 #define LN3_TX_SER_RATE_SEL_HBR2_MASK	BIT(3)
 #define LN3_TX_SER_RATE_SEL_HBR3_MASK	BIT(2)
 
+#define HDMI14_MAX_RATE			340000000
 #define HDMI20_MAX_RATE			600000000
 
 enum dp_link_rate {
@@ -1072,7 +1073,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate >= 3400000) {
+	if (rate > HDMI14_MAX_RATE / 100) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:45 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:45 +0200
Subject: [PATCH v6 11/14] phy: rockchip: samsung-hdptx: Restrict altering
 TMDS char rate via CCF
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-11-8cb1678e7663@collabora.com>

Although, in theory, the clock provider functionality could be enabled
as a standalone driver feature, in practice it is unlikely that it would
be ever needed separately from the common PHY related features, i.e.
making use of the PHY PLL as an alternative and more accurate clock
source for display modes handling.  Which means the PLL will be always
programmed according to the TMDS char rate set via the HDMI PHY
configuration API.

Currently it's possible to freely adjust the rate via the clock API as
well, that is through clk_set_rate().  Making the clock read-only is not
feasible since we need to ensure any rate update done via the PHY
configuration API has been actually programmed into the hardware before
CCF accesses it.  This would be normally done during phy_ops.power_on()
or clk_ops.prepare() callbacks, but it might happen that the former gets
fired too late and the latter only once, hence we need to keep handle it
via clk_ops.set_rate() as a fallback approach.

Prevent changing the TMDS character rate via CCF by letting
rk_hdptx_phy_clk_round_rate() always return the value set via
phy_configure().  To avoid breaking existing users, i.e. RK DW HDMI QP
bridge driver, until the switch to the HDMI PHY config based approach is
completed, introduce a temporary exception to the rule, toggled via the
new ->restrict_rate_change flag, which indicates whether phy_configure()
has been called or not.

Additionally, revert any unlikely rate change that might have occurred
between the calls to ->round_rate() and ->set_rate().

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 52 +++++++++++++++++------
 1 file changed, 40 insertions(+), 12 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 80dd896861bcac6ef9dbde410327b893f8039627..2feb46f6d4e5bd2f43140e465cc25d2b0c363df4 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -402,6 +402,7 @@ struct rk_hdptx_phy {
 	/* clk provider */
 	struct clk_hw hw;
 	unsigned long rate;
+	bool restrict_rate_change;
 
 	atomic_t usage_count;
 
@@ -1758,10 +1759,12 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 
 	if (mode != PHY_MODE_DP) {
 		ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
-		if (ret)
+		if (ret) {
 			dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
-		else
+		} else {
 			hdptx->hdmi_cfg = opts->hdmi;
+			hdptx->restrict_rate_change = true;
+		}
 		return ret;
 	}
 
@@ -1848,20 +1851,31 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate)
 {
-	int i;
+	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	if (rate > HDMI20_MAX_RATE)
-		return rate;
+	/*
+	 * FIXME: Temporarily allow altering TMDS char rate via CCF.
+	 * To be dropped as soon as the RK DW HDMI QP bridge driver
+	 * switches to make use of phy_configure().
+	 */
+	if (!hdptx->restrict_rate_change && rate != hdptx->hdmi_cfg.tmds_char_rate) {
+		struct phy_configure_opts_hdmi hdmi = {
+			.tmds_char_rate = rate,
+		};
+		int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi);
 
-	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].rate)
-			break;
+		if (ret)
+			return ret;
 
-	if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
-	    !rk_hdptx_phy_clk_pll_calc(rate, NULL))
-		return -EINVAL;
+		hdptx->hdmi_cfg = hdmi;
+	}
 
-	return rate;
+	/*
+	 * The TMDS char rate shall be adjusted via phy_configure() only,
+	 * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
+	 * a different rate argument.
+	 */
+	return hdptx->hdmi_cfg.tmds_char_rate;
 }
 
 static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1869,6 +1883,20 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
+	/* Revert any unlikely TMDS char rate change since round_rate() */
+	if (hdptx->hdmi_cfg.tmds_char_rate != rate) {
+		dev_warn(hdptx->dev, "Reverting unexpected rate change from %lu to %llu\n",
+			 rate, hdptx->hdmi_cfg.tmds_char_rate);
+		hdptx->hdmi_cfg.tmds_char_rate = rate;
+	}
+
+	/*
+	 * The TMDS char rate would be normally programmed in HW during
+	 * phy_ops.power_on() or clk_ops.prepare() callbacks, but it might
+	 * happen that the former gets fired too late, i.e. after this call,
+	 * while the latter being executed only once, i.e. when clock remains
+	 * in the prepared state during rate changes.
+	 */
 	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
 }
 

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:46 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:46 +0200
Subject: [PATCH v6 12/14] phy: rockchip: samsung-hdptx: Rename ambiguous
 rk_hdptx_phy->rate
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-12-8cb1678e7663@collabora.com>

The main purpose of the ->rate member of struct rk_hdptx_phy is to
implement rk_hdptx_phy_clk_recalc_rate() by providing the actual rate
programmed in hardware.  Hence the current naming is too generic and
rather ambiguous.

Improve clarity by renaming ->rate to ->hw_rate.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 2feb46f6d4e5bd2f43140e465cc25d2b0c363df4..a19a89233d808e2b38f6e7e58a1dc38ddd7cadd3 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -401,7 +401,7 @@ struct rk_hdptx_phy {
 
 	/* clk provider */
 	struct clk_hw hw;
-	unsigned long rate;
+	unsigned long hw_rate;
 	bool restrict_rate_change;
 
 	atomic_t usage_count;
@@ -1030,7 +1030,7 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 
 	ret = rk_hdptx_post_enable_pll(hdptx);
 	if (!ret)
-		hdptx->rate = rate;
+		hdptx->hw_rate = rate;
 
 	return ret;
 }
@@ -1830,7 +1830,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
+	return rk_hdptx_phy_consumer_get(hdptx, hdptx->hw_rate);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1845,7 +1845,7 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return hdptx->rate;
+	return hdptx->hw_rate;
 }
 
 static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:47 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:47 +0200
Subject: [PATCH v6 13/14] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-13-8cb1678e7663@collabora.com>

Drop the rate parameter from a bunch of internal helpers and, instead,
make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
data.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 47 +++++++++++------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index a19a89233d808e2b38f6e7e58a1dc38ddd7cadd3..d09e1f7b25ec131d3c40fb52564cad27dce3b2d4 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -968,31 +968,34 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned long long rate,
 	return true;
 }
 
-static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
-					  unsigned long long rate)
+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 {
 	const struct ropll_config *cfg = NULL;
 	struct ropll_config rc = {0};
 	int ret, i;
 
+	if (!hdptx->hdmi_cfg.tmds_char_rate)
+		return 0;
+
 	for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
-		if (rate == ropll_tmds_cfg[i].rate) {
+		if (hdptx->hdmi_cfg.tmds_char_rate == ropll_tmds_cfg[i].rate) {
 			cfg = &ropll_tmds_cfg[i];
 			break;
 		}
 
 	if (!cfg) {
-		if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
-			cfg = &rc;
-		} else {
-			dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+		if (!rk_hdptx_phy_clk_pll_calc(hdptx->hdmi_cfg.tmds_char_rate, &rc)) {
+			dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%llu\n",
+				__func__, hdptx->hdmi_cfg.tmds_char_rate);
 			return -EINVAL;
 		}
+
+		cfg = &rc;
 	}
 
 	dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
-		__func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
-		cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
+		__func__, hdptx->hdmi_cfg.tmds_char_rate, cfg->pms_mdiv, cfg->pms_sdiv + 1,
+		cfg->sdm_en, cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
 
 	rk_hdptx_pre_power_up(hdptx);
 
@@ -1030,19 +1033,18 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
 
 	ret = rk_hdptx_post_enable_pll(hdptx);
 	if (!ret)
-		hdptx->hw_rate = rate;
+		hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate;
 
 	return ret;
 }
 
-static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
-					   unsigned long long rate)
+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx)
 {
 	rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
 
 	regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
 
-	if (rate > HDMI14_MAX_RATE) {
+	if (hdptx->hdmi_cfg.tmds_char_rate > HDMI14_MAX_RATE) {
 		/* For 1/40 bitrate clk */
 		rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
 	} else {
@@ -1094,8 +1096,7 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
 		     HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
 }
 
-static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
-				     unsigned long long rate)
+static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
 {
 	enum phy_mode mode = phy_get_mode(hdptx->phy);
 	u32 status;
@@ -1114,11 +1115,9 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
 	if (mode == PHY_MODE_DP) {
 		rk_hdptx_dp_reset(hdptx);
 	} else {
-		if (rate) {
-			ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
-			if (ret)
-				goto dec_usage;
-		}
+		ret = rk_hdptx_ropll_tmds_cmn_config(hdptx);
+		if (ret)
+			goto dec_usage;
 	}
 
 	return 0;
@@ -1431,7 +1430,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
 	}
 
-	ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+	ret = rk_hdptx_phy_consumer_get(hdptx);
 	if (ret)
 		return ret;
 
@@ -1462,7 +1461,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 		regmap_write(hdptx->grf, GRF_HDPTX_CON0,
 			     HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
 
-		ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+		ret = rk_hdptx_ropll_tmds_mode_config(hdptx);
 		if (ret)
 			rk_hdptx_phy_consumer_put(hdptx, true);
 	}
@@ -1830,7 +1829,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
 {
 	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
 
-	return rk_hdptx_phy_consumer_get(hdptx, hdptx->hw_rate);
+	return rk_hdptx_phy_consumer_get(hdptx);
 }
 
 static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1897,7 +1896,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	 * while the latter being executed only once, i.e. when clock remains
 	 * in the prepared state during rate changes.
 	 */
-	return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
+	return rk_hdptx_ropll_tmds_cmn_config(hdptx);
 }
 
 static const struct clk_ops hdptx_phy_clk_ops = {

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:35:48 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:35:48 +0200
Subject: [PATCH v6 14/14] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
Message-ID: <20250318-phy-sam-hdptx-bpc-v6-14-8cb1678e7663@collabora.com>

Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index d09e1f7b25ec131d3c40fb52564cad27dce3b2d4..fc289ed8d915d84916870329101655cd956898e3 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1028,6 +1028,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
 			   FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
 
+	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+			   FIELD_PREP(PLL_PCG_CLK_SEL_MASK, (hdptx->hdmi_cfg.bpc - 8) >> 1));
+
 	regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
 			   FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
 
@@ -1427,7 +1430,8 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
 			hdptx->hdmi_cfg.tmds_char_rate *= 100;
 		}
 
-		dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+		dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 	}
 
 	ret = rk_hdptx_phy_consumer_get(hdptx);
@@ -1492,6 +1496,19 @@ static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
 	    !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
 		return -EINVAL;
 
+	if (!hdmi->bpc)
+		hdmi->bpc = 8;
+
+	switch (hdmi->bpc) {
+	case 8:
+	case 10:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	};
+
 	return 0;
 }
 
@@ -1764,6 +1781,9 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
 			hdptx->hdmi_cfg = opts->hdmi;
 			hdptx->restrict_rate_change = true;
 		}
+
+		dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+			hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
 		return ret;
 	}
 
@@ -1972,6 +1992,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hdptx->dev = dev;
+	hdptx->hdmi_cfg.bpc = 8;
 
 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(regs))

-- 
2.48.1



From cristian.ciocaltea at collabora.com  Tue Mar 18 05:48:08 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:48:08 +0200
Subject: [PATCH v5 08/12] phy: rockchip: samsung-hdptx: Setup TMDS char
 rate via phy_configure_opts_hdmi
In-Reply-To: <6caefe9f-1b15-41c1-94f2-9a2a92aeec67@collabora.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-8-35087287f9d1@collabora.com>
 <CAA8EJpoGu4Tq-wt09Jj+b+=eJ3dNXhPWVOg4DyCQxrJbFNFfYw@mail.gmail.com>
 <6caefe9f-1b15-41c1-94f2-9a2a92aeec67@collabora.com>
Message-ID: <5e9516bc-66ac-4583-b949-5714e89d73ee@collabora.com>

On 3/9/25 12:15 PM, Cristian Ciocaltea wrote:
> On 3/9/25 11:26 AM, Dmitry Baryshkov wrote:
>> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
>> <cristian.ciocaltea at collabora.com> wrote:
>>>
>>> The current workaround to setup the TMDS character rate relies on the
>>> unconventional usage of phy_set_bus_width().
>>>
>>> Make use of the recently introduced HDMI PHY configuration API to
>>> properly handle the setup.  The workaround will be dropped as soon as
>>> the switch has been completed on both ends.
>>>
>>> Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
>>> and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
>>> HDMI parameters during phy_configure().
>>>
>>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>>> ---
>>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 +++++++++++++++++------
>>>  1 file changed, 47 insertions(+), 17 deletions(-)
>>>
>>
>>> @@ -1469,8 +1474,27 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
>>>         return rk_hdptx_phy_consumer_put(hdptx, false);
>>>  }
>>>
>>> -static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
>>> -                                     struct phy_configure_opts_dp *dp)
>>> +static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
>>> +                                          struct phy_configure_opts_hdmi *hdmi)
>>> +{
>>> +       int i;
>>> +
>>> +       if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
>>> +               return -EINVAL;
>>> +
>>> +       for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
>>> +               if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
>>> +                       break;
>>
>> return 0;
>>
>>> +
>>> +       if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
>>
>> Then you can drop the first clause in the if
> 
> Sure, will do!

I actually ended up submitting v6 [1] without these changes, since the last
patch "phy: rockchip: samsung-hdptx: Add high color depth management" would
need to revert them, i.e. it extends the verification and cannot really do
"return 0;" early.

[1] https://lore.kernel.org/lkml/20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663 at collabora.com/


From jgg at nvidia.com  Tue Mar 18 05:55:27 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Tue, 18 Mar 2025 09:55:27 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <86wmcmn0dp.wl-maz@kernel.org>
References: <20250310103008.3471-2-ankita@nvidia.com>
 <861pv5p0c3.wl-maz@kernel.org>
 <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
Message-ID: <20250318125527.GP9311@nvidia.com>

On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:

> The memslot must also be created with a new flag ((2c) in the taxonomy
> above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
> flag is only allowed if (1) is valid.
> 
> This results in the following behaviours:
> 
> - If the VMM creates the memslot with the cacheable attribute without
>   (1) being advertised, we fail.
> 
> - If the VMM creates the memslot without the cacheable attribute, we
>   map as NC, as it is today.

Is that OK though?

Now we have the MM page tables mapping this memory as cachable but KVM
and the guest is accessing it as non-cached.

I thought ARM tried hard to avoid creating such mismatches? This is
why the pgprot flags were used to drive this, not an opt-in flag. To
prevent userspace from forcing a mismatch.

> What this doesn't do is *automatically* decide for the VMM what
> attributes to use. The VMM must know what it is doing, and only
> provide the memslot flag when appropriate. Doing otherwise may eat
> your data and/or take the machine down (cacheable mapping on a device
> can be great fun).

Again, this is why we followed the VMA flags. The thing creating the
VMA already made this safety determination when it set pgprot
cachable. We should not allow KVM to randomly make any PGPROT
cachable!

> If you want to address this, then "someone" needs
> to pass some additional VMA flag that KVM can check.

pgprot does this already, we don't need a new flag to determine if the
VMA is cachably mapped.

Jason


From cristian.ciocaltea at collabora.com  Tue Mar 18 05:56:02 2025
From: cristian.ciocaltea at collabora.com (Cristian Ciocaltea)
Date: Tue, 18 Mar 2025 14:56:02 +0200
Subject: [PATCH v5 12/12] phy: rockchip: samsung-hdptx: Add high color
 depth management
In-Reply-To: <CAA8EJppo29p+8a5VUbr6dwaE9ywgS+-VcuUH_sF+NdA0xGU1Zw@mail.gmail.com>
References: <20250308-phy-sam-hdptx-bpc-v5-0-35087287f9d1@collabora.com>
 <20250308-phy-sam-hdptx-bpc-v5-12-35087287f9d1@collabora.com>
 <CAA8EJppo29p+8a5VUbr6dwaE9ywgS+-VcuUH_sF+NdA0xGU1Zw@mail.gmail.com>
Message-ID: <eafe83e6-c18a-4d1d-841d-8d2472a670e7@collabora.com>

On 3/9/25 12:18 PM, Dmitry Baryshkov wrote:
> On Sat, 8 Mar 2025 at 14:21, Cristian Ciocaltea
> <cristian.ciocaltea at collabora.com> wrote:
>>
>> Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.
>>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
>> ---
>>  drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 ++++++++++++++++++++++-
>>  1 file changed, 22 insertions(+), 1 deletion(-)
>>
> 
> Reviewed-by: Dmitry Baryshkov <dmtiry.baryshkov at linaro.org>

There's a typo in the email address, I've corrected it in v6.
 



From xuwei5 at hisilicon.com  Tue Mar 18 05:35:53 2025
From: xuwei5 at hisilicon.com (Wei Xu)
Date: Tue, 18 Mar 2025 20:35:53 +0800
Subject: [GIT,PULL] arm64: dts: hisilicon dts updates for v6.15
Message-ID: <67D968A9.7080504@hisilicon.com>

Hi ARM SoC maintainers,

Please consider to pull the following changes.
Thanks!

Best Regards,
Wei

---

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://github.com/hisilicon/linux-hisi.git tags/hisi-arm64-dt-for-6.15

for you to fetch changes up to 8095a17b0ace09a280a5954096701b883dcaa135:

  arm64: dts: hi3660: Add property for fixing CPUIdle (2025-03-18 11:46:55 +0000)

----------------------------------------------------------------
ARM64: DT: HiSilicon ARM64 DT updates for v6.15

- Add property to the ETM nodes for fixing CPU idle states

----------------------------------------------------------------
Leo Yan (1):
      arm64: dts: hi3660: Add property for fixing CPUIdle

 arch/arm64/boot/dts/hisilicon/hi3660-coresight.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)


From jgg at nvidia.com  Tue Mar 18 05:57:51 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Tue, 18 Mar 2025 09:57:51 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <861pv5p0c3.wl-maz@kernel.org>
References: <20250310103008.3471-1-ankita@nvidia.com>
 <20250310103008.3471-2-ankita@nvidia.com>
 <861pv5p0c3.wl-maz@kernel.org>
Message-ID: <20250318125751.GQ9311@nvidia.com>

On Mon, Mar 10, 2025 at 11:54:52AM +0000, Marc Zyngier wrote:

> Which brings me to the next point: FWB is not discoverable from
> userspace. How do you expect a VMM to know what it can or cannot do?

If you add a check at memslot creation time then simply fail the
memslot.

There is nothing the VMM can do except completely fail. There is no
alternative path here where a cachable VMA can be safely made
non-cachable for the guest?

Jason


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:56 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:56 +0200
Subject: [PATCH v2 03/10] dt-bindings: arm:
 arm,coresight-static-replicator: add optional clocks
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-3-bcedd1406790@oss.qualcomm.com>

As most other CoreSight devices the replicator can use either of the
optional clocks. Document those optional clocks in the schema.
Additionally document the one-off case of Zynq-7000 platforms which uses
apb_pclk and two additional debug clocks.

Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 .../bindings/arm/arm,coresight-static-replicator.yaml       | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..0c1017affbad2f03892b250ad864d9a5dc8d02f1 100644
--- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
@@ -30,6 +30,19 @@ properties:
   power-domains:
     maxItems: 1
 
+  clocks:
+    minItems: 1
+    maxItems: 3
+
+  clock-names:
+    oneOf:
+      - items:
+          - enum: [apb_pclk, atclk]
+      - items: # Zynq-700
+          - const: apb_pclk
+          - const: dbg_trc
+          - const: dbg_apb
+
   in-ports:
     $ref: /schemas/graph.yaml#/properties/ports
     additionalProperties: false

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:57 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:57 +0200
Subject: [PATCH v2 04/10] dt-bindings: mfd: syscon: add
 qcom,apq8064-sps-sic
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-4-bcedd1406790@oss.qualcomm.com>

Add compat for Smart Peripheral System (SPS) Interrupt Controller (SIC)
present on Qualcomm APQ8064 SoC.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 2836e4793afc918067d3ef93baf5bc7096f72f12..0d2530bd05b8c114232926e3ba8b0fed99e276f9 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -95,6 +95,7 @@ select:
           - mstar,msc313-pmsleep
           - nuvoton,ma35d1-sys
           - nuvoton,wpcm450-shm
+          - qcom,apq8064-sps-sic
           - rockchip,px30-qos
           - rockchip,rk3036-qos
           - rockchip,rk3066-qos
@@ -195,6 +196,7 @@ properties:
           - mstar,msc313-pmsleep
           - nuvoton,ma35d1-sys
           - nuvoton,wpcm450-shm
+          - qcom,apq8064-sps-sic
           - rockchip,px30-qos
           - rockchip,rk3036-qos
           - rockchip,rk3066-qos

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:58 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:58 +0200
Subject: [PATCH v2 05/10] dt-bindings: mfd: syscon: add
 qcom,apq8064-mmss-sfpb
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-5-bcedd1406790@oss.qualcomm.com>

Add compat string for Qualcomm MultiMedia SubSystem System FPB.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 0d2530bd05b8c114232926e3ba8b0fed99e276f9..60f153cb57d56b00813cf65070fc4636141c5b52 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -95,6 +95,7 @@ select:
           - mstar,msc313-pmsleep
           - nuvoton,ma35d1-sys
           - nuvoton,wpcm450-shm
+          - qcom,apq8064-mmss-sfpb
           - qcom,apq8064-sps-sic
           - rockchip,px30-qos
           - rockchip,rk3036-qos
@@ -196,6 +197,7 @@ properties:
           - mstar,msc313-pmsleep
           - nuvoton,ma35d1-sys
           - nuvoton,wpcm450-shm
+          - qcom,apq8064-mmss-sfpb
           - qcom,apq8064-sps-sic
           - rockchip,px30-qos
           - rockchip,rk3036-qos

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:59 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:59 +0200
Subject: [PATCH v2 06/10] ARM: dts: qcom: apq8064: add missing clocks to
 the timer node
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-6-bcedd1406790@oss.qualcomm.com>

In order to fix DT schema warning and describe hardware properly, add
missing sleep clock to the timer node.

Fixes: f335b8af4fd5 ("ARM: dts: qcom: Add initial APQ8064 SoC and IFC6410 board device trees")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 5f1a6b4b764492486df1a2610979f56c0a37b64a..ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -326,6 +326,8 @@ timer at 200a000 {
 				     <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 			reg = <0x0200a000 0x100>;
 			clock-frequency = <27000000>;
+			clocks = <&sleep_clk>;
+			clock-names = "sleep";
 			cpu-offset = <0x80000>;
 		};
 

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:53 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:53 +0200
Subject: [PATCH v2 00/10] ARM: qcom: fix APQ8064 schema warnings
Message-ID: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>

Rob's bot has reported [1] several warnings for Nexus 4 submisson,
however none of those warnings are specific to that device. Fix all
those warnings for all APQ8064 platforms by extending existing schemas,
adding missing schemas and making APQ8064 DT follow all the schema
files.

[1]: https://lore.kernel.org/linux-arm-msm/174221818190.3957236.3364090534153729086.robh at kernel.org/

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
Changes in v2:
- Corrected Fixes tag for the clock-controller patch to point to the
  commit which introduced qcom,rpmcc schema for APQ8064 (Krzysztof)
- Switched to syscon.yaml (Krzysztof)
- Reordered ports in the static replicator node (Konrad)
- Fixed hwmutex node address (Konrad)
- Fixed clocks in arm,coresight-static-replicator.yaml (Rob)
- Documented clocks /clock-names in qcom,rpm node (Rob)
- Link to v1: https://lore.kernel.org/r/20250317-fix-nexus-4-v1-0-655c52e2ad97 at oss.qualcomm.com

---
Dmitry Baryshkov (10):
      dt-bindings: soc: qcom,rpm: add missing clock-controller node
      dt-bindings: soc: qcom: qcom,rpm: add missing clock/-names properties
      dt-bindings: arm: arm,coresight-static-replicator: add optional clocks
      dt-bindings: mfd: syscon: add qcom,apq8064-sps-sic
      dt-bindings: mfd: syscon: add qcom,apq8064-mmss-sfpb
      ARM: dts: qcom: apq8064: add missing clocks to the timer node
      ARM: dts: qcom: apq8064 merge hw splinlock into corresponding syscon device
      ARM: dts: qcom: apq8064: use new compatible for SFPB device
      ARM: dts: qcom: apq8064: use new compatible for SPS SIC device
      ARM: dts: qcom: apq8064: move replicator out of soc node

 .../arm/arm,coresight-static-replicator.yaml       | 13 ++++
 Documentation/devicetree/bindings/mfd/syscon.yaml  |  4 +
 .../devicetree/bindings/soc/qcom/qcom,rpm.yaml     | 15 ++++
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi           | 88 +++++++++++-----------
 4 files changed, 75 insertions(+), 45 deletions(-)
---
base-commit: 9f789dc174dc1a40754507a962a4e9e7c593e2d8
change-id: 20250317-fix-nexus-4-dd0fe3bca987

Best regards,
-- 
Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:54 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:54 +0200
Subject: [PATCH v2 01/10] dt-bindings: soc: qcom,rpm: add missing
 clock-controller node
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-1-bcedd1406790@oss.qualcomm.com>

On Qualcomm platforms in addition to regulators the RPM also provides
clocks via the child clock-controller node. Describe it properly in the
schema.

Fixes: 872f91b5ea72 ("clk: qcom: Add support for RPM Clocks")
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
index b00be9e01206d1c61802dee9f9ec777c4b946b7b..10956240df0856a4241d6032d3aff7d447af9ce6 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
@@ -46,6 +46,14 @@ properties:
     description:
       Three entries specifying the outgoing ipc bit used for signaling the RPM.
 
+  clock-controller:
+    type: object
+    additionalProperties: true
+    properties:
+      compatible:
+        contains:
+          const: qcom,rpmcc
+
 patternProperties:
   "^regulators(-[01])?$":
     type: object

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:21:55 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:21:55 +0200
Subject: [PATCH v2 02/10] dt-bindings: soc: qcom: qcom,rpm: add missing
 clock/-names properties
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-2-bcedd1406790@oss.qualcomm.com>

Qualcomm MSM8660 and IPQ0864 platforms use additional clock for the RPM
device. Document it in the schema.

Fixes: aa0c4b815045 ("mfd: devicetree: bindings: Add Qualcomm RPM DT binding")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
index 10956240df0856a4241d6032d3aff7d447af9ce6..3e8d99cb4dc368ab6b31e3e60eb5f7e082cd312d 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml
@@ -36,6 +36,13 @@ properties:
       - const: err
       - const: wakeup
 
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: ram
+
   qcom,ipc:
     $ref: /schemas/types.yaml#/definitions/phandle-array
     items:

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:22:00 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:22:00 +0200
Subject: [PATCH v2 07/10] ARM: dts: qcom: apq8064 merge hw splinlock into
 corresponding syscon device
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-7-bcedd1406790@oss.qualcomm.com>

Follow up the expected way of describing the SFPB hwspinlock and merge
hwspinlock node into corresponding syscon node, fixing several dt-schema
warnings.

Fixes: 24a9baf933dc ("ARM: dts: qcom: apq8064: Add hwmutex and SMEM nodes")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index ba99e794dcd2236f65f2f3d8c49213cfdaee5f6e..41f8dcde20819b3134c38dcb3e45b9e5cc24920f 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -213,12 +213,6 @@ sleep_clk: sleep_clk {
 		};
 	};
 
-	sfpb_mutex: hwmutex {
-		compatible = "qcom,sfpb-mutex";
-		syscon = <&sfpb_wrapper_mutex 0x604 0x4>;
-		#hwlock-cells = <1>;
-	};
-
 	smem {
 		compatible = "qcom,smem";
 		memory-region = <&smem_region>;
@@ -305,9 +299,10 @@ tlmm_pinmux: pinctrl at 800000 {
 			pinctrl-0 = <&ps_hold_default_state>;
 		};
 
-		sfpb_wrapper_mutex: syscon at 1200000 {
-			compatible = "syscon";
-			reg = <0x01200000 0x8000>;
+		sfpb_mutex: hwmutex at 1200600 {
+			compatible = "qcom,sfpb-mutex";
+			reg = <0x01200600 0x100>;
+			#hwlock-cells = <1>;
 		};
 
 		intc: interrupt-controller at 2000000 {

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:22:02 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:22:02 +0200
Subject: [PATCH v2 09/10] ARM: dts: qcom: apq8064: use new compatible for
 SPS SIC device
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-9-bcedd1406790@oss.qualcomm.com>

Use new SoC-specific compatible to the SPS SIC in addition to the
"syscon" compatible and rename the node to follow the purpose of it.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index a5aad4f145dd368aabed44cf520ffc037018b37e..b6533630e347c8fc5e3f0791778cd05760b3f3c8 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -402,8 +402,8 @@ saw3_vreg: regulator {
 			};
 		};
 
-		sps_sic_non_secure: sps-sic-non-secure at 12100000 {
-			compatible = "syscon";
+		sps_sic_non_secure: interrupt-controller at 12100000 {
+			compatible = "qcom,apq8064-sps-sic", "syscon";
 			reg = <0x12100000 0x10000>;
 		};
 

-- 
2.39.5



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:22:01 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:22:01 +0200
Subject: [PATCH v2 08/10] ARM: dts: qcom: apq8064: use new compatible for
 SFPB device
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-8-bcedd1406790@oss.qualcomm.com>

Use new SoC-specific compatible for the SFPB device node in addition to
the "syscon" compatible.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 41f8dcde20819b3134c38dcb3e45b9e5cc24920f..a5aad4f145dd368aabed44cf520ffc037018b37e 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -1086,7 +1086,7 @@ opp-27000000 {
 		};
 
 		mmss_sfpb: syscon at 5700000 {
-			compatible = "syscon";
+			compatible = "qcom,apq8064-mmss-sfpb", "syscon";
 			reg = <0x5700000 0x70>;
 		};
 

-- 
2.39.5



From ardb+git at google.com  Tue Mar 18 06:24:22 2025
From: ardb+git at google.com (Ard Biesheuvel)
Date: Tue, 18 Mar 2025 14:24:22 +0100
Subject: [PATCH] arm64/fpsimd: Avoid unnecessary per-CPU buffers for EFI
 runtime calls
Message-ID: <20250318132421.3155799-2-ardb+git@google.com>

From: Ard Biesheuvel <ardb at kernel.org>

The EFI specification has some elaborate rules about which runtime
services may be called while another runtime service call is already in
progress. In Linux, however, for simplicity, all EFI runtime service
invocations are serialized via the efi_runtime_lock semaphore.

This implies that calls to the helper pair arch_efi_call_virt_setup()
and arch_efi_call_virt_teardown() are serialized too, and are guaranteed
not to nest.  Furthermore, the arm64 arch code has its own spinlock to
serialize use of the EFI runtime stack, of which only a single instance
exists.

This all means that the FP/SIMD and SVE state preserve/restore logic in
__efi_fpsimd_begin() and __efi_fpsimd_end() are also serialized, and
only a single instance of the associated per-CPU variables can ever be
in use at the same time. There is therefore no need at all for per-CPU
variables here, and they can all be replaced with singleton instances.
This saves a non-trivial amount of memory on systems with many CPUs.

To be more robust against potential future changes in the core EFI code
that may invalidate the reasoning above, move the invocations of
__efi_fpsimd_begin() and __efi_fpsimd_end() into the critical section
covered by the efi_rt_lock spinlock.

Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm64/kernel/efi.c    |  4 +--
 arch/arm64/kernel/fpsimd.c | 54 ++++++++++++++++++--------------------
 2 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 1d25d8899dbf..250e9d7c08a7 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -169,14 +169,14 @@ static DEFINE_RAW_SPINLOCK(efi_rt_lock);
 void arch_efi_call_virt_setup(void)
 {
 	efi_virtmap_load();
-	__efi_fpsimd_begin();
 	raw_spin_lock(&efi_rt_lock);
+	__efi_fpsimd_begin();
 }
 
 void arch_efi_call_virt_teardown(void)
 {
-	raw_spin_unlock(&efi_rt_lock);
 	__efi_fpsimd_end();
+	raw_spin_unlock(&efi_rt_lock);
 	efi_virtmap_unload();
 }
 
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 2b601d88762d..788cc3ad6101 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -180,12 +180,12 @@ static inline void set_sve_default_vl(int val)
 	set_default_vl(ARM64_VEC_SVE, val);
 }
 
-static void __percpu *efi_sve_state;
+static u8 *efi_sve_state;
 
 #else /* ! CONFIG_ARM64_SVE */
 
 /* Dummy declaration for code that will be optimised out: */
-extern void __percpu *efi_sve_state;
+extern u8 *efi_sve_state;
 
 #endif /* ! CONFIG_ARM64_SVE */
 
@@ -1131,15 +1131,15 @@ static void __init sve_efi_setup(void)
 	if (!sve_vl_valid(max_vl))
 		goto fail;
 
-	efi_sve_state = __alloc_percpu(
-		SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)), SVE_VQ_BYTES);
+	efi_sve_state = kmalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)),
+				GFP_KERNEL);
 	if (!efi_sve_state)
 		goto fail;
 
 	return;
 
 fail:
-	panic("Cannot allocate percpu memory for EFI SVE save/restore");
+	panic("Cannot allocate memory for EFI SVE save/restore");
 }
 
 void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
@@ -1973,10 +1973,10 @@ EXPORT_SYMBOL_GPL(kernel_neon_end);
 
 #ifdef CONFIG_EFI
 
-static DEFINE_PER_CPU(struct user_fpsimd_state, efi_fpsimd_state);
-static DEFINE_PER_CPU(bool, efi_fpsimd_state_used);
-static DEFINE_PER_CPU(bool, efi_sve_state_used);
-static DEFINE_PER_CPU(bool, efi_sm_state);
+static struct user_fpsimd_state efi_fpsimd_state;
+static bool efi_fpsimd_state_used;
+static bool efi_sve_state_used;
+static bool efi_sm_state;
 
 /*
  * EFI runtime services support functions
@@ -2009,18 +2009,16 @@ void __efi_fpsimd_begin(void)
 		 * If !efi_sve_state, SVE can't be in use yet and doesn't need
 		 * preserving:
 		 */
-		if (system_supports_sve() && likely(efi_sve_state)) {
-			char *sve_state = this_cpu_ptr(efi_sve_state);
+		if (system_supports_sve() && efi_sve_state != NULL) {
 			bool ffr = true;
 			u64 svcr;
 
-			__this_cpu_write(efi_sve_state_used, true);
+			efi_sve_state_used = true;
 
 			if (system_supports_sme()) {
 				svcr = read_sysreg_s(SYS_SVCR);
 
-				__this_cpu_write(efi_sm_state,
-						 svcr & SVCR_SM_MASK);
+				efi_sm_state = svcr & SVCR_SM_MASK;
 
 				/*
 				 * Unless we have FA64 FFR does not
@@ -2030,19 +2028,18 @@ void __efi_fpsimd_begin(void)
 					ffr = !(svcr & SVCR_SM_MASK);
 			}
 
-			sve_save_state(sve_state + sve_ffr_offset(sve_max_vl()),
-				       &this_cpu_ptr(&efi_fpsimd_state)->fpsr,
-				       ffr);
+			sve_save_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
+				       &efi_fpsimd_state.fpsr, ffr);
 
 			if (system_supports_sme())
 				sysreg_clear_set_s(SYS_SVCR,
 						   SVCR_SM_MASK, 0);
 
 		} else {
-			fpsimd_save_state(this_cpu_ptr(&efi_fpsimd_state));
+			fpsimd_save_state(&efi_fpsimd_state);
 		}
 
-		__this_cpu_write(efi_fpsimd_state_used, true);
+		efi_fpsimd_state_used = true;
 	}
 }
 
@@ -2054,12 +2051,10 @@ void __efi_fpsimd_end(void)
 	if (!system_supports_fpsimd())
 		return;
 
-	if (!__this_cpu_xchg(efi_fpsimd_state_used, false)) {
+	if (!efi_fpsimd_state_used) {
 		kernel_neon_end();
 	} else {
-		if (system_supports_sve() &&
-		    likely(__this_cpu_read(efi_sve_state_used))) {
-			char const *sve_state = this_cpu_ptr(efi_sve_state);
+		if (system_supports_sve() && efi_sve_state_used) {
 			bool ffr = true;
 
 			/*
@@ -2068,7 +2063,7 @@ void __efi_fpsimd_end(void)
 			 * streaming mode.
 			 */
 			if (system_supports_sme()) {
-				if (__this_cpu_read(efi_sm_state)) {
+				if (efi_sm_state) {
 					sysreg_clear_set_s(SYS_SVCR,
 							   0,
 							   SVCR_SM_MASK);
@@ -2082,14 +2077,15 @@ void __efi_fpsimd_end(void)
 				}
 			}
 
-			sve_load_state(sve_state + sve_ffr_offset(sve_max_vl()),
-				       &this_cpu_ptr(&efi_fpsimd_state)->fpsr,
-				       ffr);
+			sve_load_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
+				       &efi_fpsimd_state.fpsr, ffr);
 
-			__this_cpu_write(efi_sve_state_used, false);
+			efi_sve_state_used = false;
 		} else {
-			fpsimd_load_state(this_cpu_ptr(&efi_fpsimd_state));
+			fpsimd_load_state(&efi_fpsimd_state);
 		}
+
+		efi_fpsimd_state_used = false;
 	}
 }
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 06:22:03 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 15:22:03 +0200
Subject: [PATCH v2 10/10] ARM: dts: qcom: apq8064: move replicator out of
 soc node
In-Reply-To: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
Message-ID: <20250318-fix-nexus-4-v2-10-bcedd1406790@oss.qualcomm.com>

The CoreSight static replicator device isn't a part of the system MMIO
bus, as such it should not be a part of the soc node. Follow the example
of other platforms and move it out of the soc bus to the top-level (and
reoder ports to follow alphabetic order).

Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-apq8064.dtsi | 67 ++++++++++++++++----------------
 1 file changed, 34 insertions(+), 33 deletions(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index b6533630e347c8fc5e3f0791778cd05760b3f3c8..b02e6739ccb20a287095d8c3e212040e4ac50fdd 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -278,6 +278,40 @@ scm {
 		};
 	};
 
+	replicator {
+		compatible = "arm,coresight-static-replicator";
+
+		clocks = <&rpmcc RPM_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		in-ports {
+			port {
+				replicator_in: endpoint {
+					remote-endpoint = <&funnel_out>;
+				};
+			};
+		};
+
+		out-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port at 0 {
+				reg = <0>;
+				replicator_out0: endpoint {
+					remote-endpoint = <&etb_in>;
+				};
+			};
+
+			port at 1 {
+				reg = <1>;
+				replicator_out1: endpoint {
+					remote-endpoint = <&tpiu_in>;
+				};
+			};
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1529,39 +1563,6 @@ tpiu_in: endpoint {
 			};
 		};
 
-		replicator {
-			compatible = "arm,coresight-static-replicator";
-
-			clocks = <&rpmcc RPM_QDSS_CLK>;
-			clock-names = "apb_pclk";
-
-			out-ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				port at 0 {
-					reg = <0>;
-					replicator_out0: endpoint {
-						remote-endpoint = <&etb_in>;
-					};
-				};
-				port at 1 {
-					reg = <1>;
-					replicator_out1: endpoint {
-						remote-endpoint = <&tpiu_in>;
-					};
-				};
-			};
-
-			in-ports {
-				port {
-					replicator_in: endpoint {
-						remote-endpoint = <&funnel_out>;
-					};
-				};
-			};
-		};
-
 		funnel at 1a04000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x1a04000 0x1000>;

-- 
2.39.5



From cristian.marussi at arm.com  Tue Mar 18 06:29:19 2025
From: cristian.marussi at arm.com (Cristian Marussi)
Date: Tue, 18 Mar 2025 13:29:19 +0000
Subject: [RFC V6 2/2] firmware: arm_scmi: Add quirk to bypass SCP fw bug
In-Reply-To: <Z9kr5ABbqO27_BM-@hovoldconsulting.com>
References: <20250226024338.3994701-1-quic_sibis@quicinc.com>
 <20250226024338.3994701-3-quic_sibis@quicinc.com>
 <Z77M5iXHQsdMptWm@hovoldconsulting.com>
 <Z77W-fKBUqAALZKJ@hovoldconsulting.com>
 <759226e1-05aa-4ca2-b2f5-7f1a84dc427f@stanley.mountain>
 <Z77l1NflYXTnRyg0@hovoldconsulting.com>
 <Z8AjhHsVT9ZQTtZX@pluto>
 <Z8WKQJcPTQDIXaKD@hovoldconsulting.com>
 <Z9kr5ABbqO27_BM-@hovoldconsulting.com>
Message-ID: <Z9l1L1WICMYXSoIu@pluto>

On Tue, Mar 18, 2025 at 09:16:36AM +0100, Johan Hovold wrote:
> Hi Cristian,

Hi Johan,

> 
> On Mon, Mar 03, 2025 at 11:53:52AM +0100, Johan Hovold wrote:
> > On Thu, Feb 27, 2025 at 08:34:44AM +0000, Cristian Marussi wrote:
> > > On Wed, Feb 26, 2025 at 10:58:44AM +0100, Johan Hovold wrote:
> > 
> > > > Something like that, yes. :) I didn't try to implement it, but it seems
> > > > like it should be possible implement this is a way that keeps the quirk
> > > > handling isolated.
> > > 
> > > I hope next week to have a better look at this, in tne meantime just a
> > > few considerations....
> > > 
> > > Sooner or later we should have introduced some sort of quirk framework
> > > in SCMI to deal systematically with potentially out-of-spec FW, but as
> > > in the name, it should be some sort of framework where you have a table of
> > > quirks, related activation conditions and a few very well isolated points
> > > where the quirks are placed and take action if enabled...this does not
> > > seem the case here where instead an ad-hoc param is added to the function
> > > that needs to be quirked...this does not scale and will make the codebase
> > > a mess IMHO...
> > 
> > Sounds good. At least we have a good understanding now of how this
> > particular firmware is broken so it would be great if you could use
> > this as a test case for the implementation.
> > 
> > In summary, we need to force the use of a fast channel for
> > PERF_LEVEL_GET on these machines, or possibly fall back to the current
> > behaviour of only using the domain attribute to determine whether the
> > fast channels should be initialised.
> > 
> > The latter may allow for a less intrusive implementation even if we'd
> > still see:
> > 
> > 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:0] - ret:-95. Using regular messaging.
> > 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:1] - ret:-95. Using regular messaging.
> > 	arm-scmi arm-scmi.0.auto: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:2] - ret:-95. Using regular messaging.
> > 
> > when not supported for all messages (e.g. with the current firmware).
> 
> > > Anyway, after all of this babbling, I know, talk is cheap :D...so now I will shut
> > > up and see if I can prototype something generic to deal with quirks, possibly
> > > next week...
> 
> Have you made any progress on the quirk framework prototyping?
> 

I have not forgot, tried a few things, but nothing really to post as of
now...dont wnat to rush either .... I was hoping to push something out at
the end of this next merge window...

> Do you need any input from Sibi on the protocol versioning for that?
>

No I am fine, I am planning anyway for something generic enough to be
easy then to plug your own quirks separately...

> We'd really like to enable cpufreq on this platform and ideally in 6.15.
> I think that should be possible given that we now understand in what
> ways the firmware is broken and what is needed to handle it even if we
> still need to decide on how best to implement this.
> 

v6.15 seems hard/impossible even using the original Sibi patch 
given the usual upstreaming-timeline of the SCMI stack where everything has
to be usually reviewed and accepted by rc4/rc5.....so both Sibi initial
patch and my own babbling were alreaady sort of late.

Thanks,
Cristian


From lorenzo at kernel.org  Tue Mar 18 06:53:56 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Tue, 18 Mar 2025 14:53:56 +0100
Subject: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to
 support MLO
In-Reply-To: <d584cae48470cf08b1029e0fef1383f92444970b.camel@mediatek.com>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
 <20250312-b4-mt7996-mlo-p2-v1-20-015b3d6fd928@kernel.org>
 <38ab11261debaf7e0884080031412808396eea5b.camel@mediatek.com>
 <d584cae48470cf08b1029e0fef1383f92444970b.camel@mediatek.com>
Message-ID: <Z9l69EeSm3ZemucG@lore-desk>

> Hi Lorenzo,
> 
> Sorry, please ignore the previous mail.
> I just aware that the deflink is now used as the primary/assoc link, so
> it should work.
> 
> Regards,
> Shayne
> 
> On Tue, 2025-03-18 at 14:28 +0800, Shayne Chen wrote:
> > Hi Lorenzo,
> > 
> > On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> > > 
> > 
> > Regards,
> > Shayne
> 

ack, no worries.

Regards,
Lorenzo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250318/47c033d0/attachment.sig>

From alb3rt0.m3rciai at gmail.com  Tue Mar 18 06:54:05 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Tue, 18 Mar 2025 14:54:05 +0100
Subject: [PATCH v13 3/5] arm64: dts: imx8ulp-evk: add nxp secure enclave
 firmware
In-Reply-To: <20250311-imx-se-if-v13-3-9cc6d8fd6d1c@nxp.com>
References: <20250311-imx-se-if-v13-0-9cc6d8fd6d1c@nxp.com>
 <20250311-imx-se-if-v13-3-9cc6d8fd6d1c@nxp.com>
Message-ID: <Z9l6/WKTmBvzjEfn@alb3rt0-ThinkPad-P15-Gen-1>

On Tue, Mar 11, 2025 at 09:09:34PM +0530, Pankaj Gupta wrote:
> Add support for NXP secure enclave called EdgeLock Enclave
> firmware (se-fw) for imx8ulp-evk.
> 
> EdgeLock Enclave has a hardware limitation of restricted access to DDR
> address: 0x80000000 to 0xAFFFFFFF, so reserve 1MB of DDR memory region
> from 0x80000000.
> 
> Signed-off-by: Pankaj Gupta <pankaj.gupta at nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8ulp-evk.dts | 17 ++++++++++++++++-
>  arch/arm64/boot/dts/freescale/imx8ulp.dtsi    | 13 +++++++++++--
>  2 files changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> index 290a49bea2f7..a25d71bf2c26 100644
> --- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>  /*
> - * Copyright 2021 NXP
> + * Copyright 2021, 2025 NXP
>   */
>  
>  /dts-v1/;
> @@ -24,6 +24,17 @@ memory at 80000000 {
>  		device_type = "memory";
>  		reg = <0x0 0x80000000 0 0x80000000>;
>  	};
> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		ele_reserved: ele-reserved at 90000000 {
> +			compatible = "shared-dma-pool";
> +			reg = <0 0x90000000 0 0x100000>;
> +			no-map;
> +		};
> +	};
>  
>  	reserved-memory {
>  		#address-cells = <2>;
> @@ -259,6 +270,10 @@ &usdhc0 {
>  	status = "okay";
>  };
>  
> +&hsm0 {
> +	memory-region = <&ele_reserved>;
> +};
> +
>  &fec {
>  	pinctrl-names = "default", "sleep";
>  	pinctrl-0 = <&pinctrl_enet>;
> diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> index 2562a35286c2..c79a5de227b3 100644
> --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>  /*
> - * Copyright 2021 NXP
> + * Copyright 2021, 2025 NXP
>   */
>  
>  #include <dt-bindings/clock/imx8ulp-clock.h>
> @@ -154,7 +154,7 @@ sosc: clock-sosc {
>  		#clock-cells = <0>;
>  	};
>  
> -	sram at 2201f000 {
> +	sram0: sram at 2201f000 {
>  		compatible = "mmio-sram";
>  		reg = <0x0 0x2201f000 0x0 0x1000>;
>  
> @@ -169,6 +169,8 @@ scmi_buf: scmi-sram-section at 0 {
>  	};
>  
>  	firmware {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		scmi {
>  			compatible = "arm,scmi-smc";
>  			arm,smc-id = <0xc20000fe>;
> @@ -186,6 +188,13 @@ scmi_sensor: protocol at 15 {
>  				#thermal-sensor-cells = <1>;
>  			};
>  		};
> +
> +		hsm0: secure-enclave {
> +			 compatible = "fsl,imx8ulp-se-ele-hsm";
> +			 mbox-names = "tx", "rx";
> +			 mboxes = <&s4muap 0 0>, <&s4muap 1 0>;
> +			 sram = <&sram0>;
> +		 };
>  	};
>  
>  	cm33: remoteproc-cm33 {
> 
> -- 
> 2.43.0
> 
> 
Hello,

I'm trying to test that solution with imx93-evk-11x11.

Driver is loaded fine:
[    2.098390] fsl-se firmware:ele-if at 0: i.MX secure-enclave: hsm0 interface to firmware, configured.
and I was able to expose /dev/hsm0_ch0 to userland.

Can you share me tests that I can run against that device?

Thanks,
Alberto


From wei.fang at nxp.com  Tue Mar 18 06:57:54 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 13:57:54 +0000
Subject: [PATCH v4 net-next 11/14] net: enetc: move generic VLAN hash
 filter functions to enetc_pf_common.c
In-Reply-To: <20250318102121.5vmv4x6qs32x2y5s@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-12-wei.fang@nxp.com>
 <20250318102121.5vmv4x6qs32x2y5s@skbuf>
Message-ID: <PAXPR04MB8510E831836A28A00C5CC76988DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 11, 2025 at 01:38:27PM +0800, Wei Fang wrote:
> > Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
> > only difference is the offset of the VLAN hash filter registers. So, the
> > .set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
> > the registers of the corresponding platform.
> 
> For the RSS hash key register, you added a function which retrieves the
> register base. For the VLAN hash filter, you add ops. Same problem,
> different solutions?

I thought it was a bit different, because we have a 'si' parameter, anyway,
I think it is fine to remove this ops and use the same way as RSS.



From wei.fang at nxp.com  Tue Mar 18 07:00:09 2025
From: wei.fang at nxp.com (Wei Fang)
Date: Tue, 18 Mar 2025 14:00:09 +0000
Subject: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95
 ENETC PF
In-Reply-To: <20250318114316.2st2ylxuu7srloqc@skbuf>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250311053830.1516523-9-wei.fang@nxp.com>
 <20250317155501.4haweyhlrfozg7zr@skbuf>
 <PAXPR04MB8510DE829523749E9FB5E20B88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
 <20250318114316.2st2ylxuu7srloqc@skbuf>
Message-ID: <PAXPR04MB851099502FD17128BDC13A2A88DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>

> On Tue, Mar 18, 2025 at 06:47:11AM +0200, Wei Fang wrote:
> > > These rxnfc commands seem implemented identically to the corresponding
> > > subset from enetc_get_rxnfc(). Rather than duplicating those, could you
> > > rather return -EOPNOTSUPP for the unsupported ones on NETC v4, and
> reuse
> > > enetc_get_rxnfc()?
> > >
> >
> > I have explained it to Jakub in v2:
> >
> https://lore.kernel.org/imx/PAXPR04MB8510B52B7D27640C557680B4881A2
> @PAXPR04MB8510.eurprd04.prod.outlook.com/
> >
> > So I don't want to reuse it for ENETC v4 PF.
> 
> A detail of the review process, written in
> Documentation/process/6.Followthrough.rst,
> is that "Andrew Morton has suggested that every review comment which does
> not result in a code change should result in an additional code comment
> instead; that can help future reviewers avoid the questions which came
> up the first time around."
> 
> [ personal mention: it doesn't have to be a code comment but can also be
>   a sentence in the commit message ]
> 
> I believe that it would be good if you could apply that suggestion for
> future submissions (not only for this particular comment).

Okay, good to know this info, I will add a comments here.



From liankun.yang at mediatek.com  Tue Mar 18 07:02:20 2025
From: liankun.yang at mediatek.com (Liankun Yang)
Date: Tue, 18 Mar 2025 22:02:20 +0800
Subject: [PATCH v3 0/1] *** SUBJECT HERE ***
Message-ID: <20250318140236.13650-1-liankun.yang@mediatek.com>

*** BLURB HERE ***

Liankun Yang (1):
  drm/mediatek: Adjust bandwidth limit for DP

Applied to mediatek-drm-fixes [1]
  drm/mediatek: Fix mode valid issue for dp.
  drm/mediatek: Fix YCbCr422 color format issue for DP.

 drivers/gpu/drm/mediatek/mtk_dp.c | 39 ++++++++++++++++---------------
 1 file changed, 20 insertions(+), 19 deletions(-)

-- 
2.45.2



From robin.murphy at arm.com  Tue Mar 18 06:36:55 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 13:36:55 +0000
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <CACu1E7Hm=DWDC2aFdBRkT8f=8gKXJPpif_uEOA9iFZcyT-uCfQ@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
 <20250311181151.GD5216@willie-the-truck>
 <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>
 <20250312124907.GB6181@willie-the-truck>
 <CACu1E7Hm=DWDC2aFdBRkT8f=8gKXJPpif_uEOA9iFZcyT-uCfQ@mail.gmail.com>
Message-ID: <394571e1-f86d-472c-91dc-4377d512bfbe@arm.com>

On 12/03/2025 1:30 pm, Connor Abbott wrote:
> On Wed, Mar 12, 2025 at 8:49?AM Will Deacon <will at kernel.org> wrote:
>>
>> On Tue, Mar 11, 2025 at 04:01:00PM -0400, Connor Abbott wrote:
>>> On Tue, Mar 11, 2025 at 2:11?PM Will Deacon <will at kernel.org> wrote:
>>>>
>>>> On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
>>>>> Up until now we have only called the set_stall callback during
>>>>> initialization when the device is off. But we will soon start calling it
>>>>> to temporarily disable stall-on-fault when the device is on, so handle
>>>>> that by checking if the device is on and writing SCTLR.
>>>>>
>>>>> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
>>>>> ---
>>>>>   drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 +++++++++++++++++++++++++++---
>>>>>   1 file changed, 27 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
>>>>> index a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2 100644
>>>>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
>>>>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
>>>>> @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
>>>>>   {
>>>>>        struct arm_smmu_domain *smmu_domain = (void *)cookie;
>>>>>        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
>>>>> -     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
>>>>> +     struct arm_smmu_device *smmu = smmu_domain->smmu;
>>>>> +     struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
>>>>> +     u32 mask = BIT(cfg->cbndx);
>>>>> +     bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
>>>>> +     unsigned long flags;
>>>>>
>>>>>        if (enabled)
>>>>> -             qsmmu->stall_enabled |= BIT(cfg->cbndx);
>>>>> +             qsmmu->stall_enabled |= mask;
>>>>>        else
>>>>> -             qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
>>>>> +             qsmmu->stall_enabled &= ~mask;
>>>>> +
>>>>> +     /*
>>>>> +      * If the device is on and we changed the setting, update the register.
>>>>> +      */
>>>>> +     if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
>>>>> +             spin_lock_irqsave(&smmu_domain->cb_lock, flags);
>>>>> +
>>>>> +             u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
>>>>> +
>>>>> +             if (enabled)
>>>>> +                     reg |= ARM_SMMU_SCTLR_CFCFG;
>>>>> +             else
>>>>> +                     reg &= ~ARM_SMMU_SCTLR_CFCFG;
>>>>> +
>>>>> +             arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
>>>>
>>>> Are you sure you don't need TLB invalidation for this to take effect? I
>>>> think some fields in the SCTLR can be cached in the TLB but you'll need
>>>> to check whether or not that applies to CFCFG.
>>>>
>>>
>>> I think it should be fine because CFCFG only controls behavior when
>>> there's a context fault and there can't be TLB entries for entries
>>> that cause a context fault: "The architecture permits the caching of
>>> any translation table entry that has been returned from memory without
>>> a fault and that does not, as a result of that entry, cause a
>>> Translation Fault or an Access Flag fault."
>>
>> Ok, but what about other types of fault? For example, a permission fault
>> or an address size fault?
>>
>> Will
> 
> I'm not sure, but the pseudocode for context faults mentions
> resampling CFCFG after a fault happens ("We have a fault and must
> resample FSR, CFCFG and HUPCF") so I don't think it would be legal to
> cache it. Also in practice this does seem to work. Does that answer
> it?

FWIW I checked with the former MMU-500 design lead, and although he 
doesn't remember the exact details he's pretty confident that they 
wouldn't have cached anything fault-related, so at least from our side 
I'd consider this OK.

Thanks,
Robin.


From suzuki.poulose at arm.com  Tue Mar 18 06:37:23 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 18 Mar 2025 13:37:23 +0000
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <klcggfxrhjqty4rktx24xmnosqnwzsbyfzgv5ea6okqbffyswn@5yei6276hlla>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
 <7b0af57c-a38c-4c30-9bb7-efe511d6bd1d@arm.com>
 <klcggfxrhjqty4rktx24xmnosqnwzsbyfzgv5ea6okqbffyswn@5yei6276hlla>
Message-ID: <eeff769a-ff81-4017-9738-98ad130980a9@arm.com>

On 18/03/2025 12:19, Dmitry Baryshkov wrote:
> On Tue, Mar 18, 2025 at 10:38:17AM +0000, Suzuki K Poulose wrote:
>> On 17/03/2025 17:44, Dmitry Baryshkov wrote:
>>
>> nit: Subject:
>>
>> s/qcom,coresight-static-replicator/arm,coresight-static-replicator
>>
>>> As most other CoreSight devices the replicator can use either of the
>>> optional clocks (or both). Document those optional clocks in the schema.
>>>
>>> Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
>>> ---
>>>    .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
>>>    1 file changed, 10 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
>>> index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
>>> --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
>>> +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
>>> @@ -30,6 +30,16 @@ properties:
>>>      power-domains:
>>>        maxItems: 1
>>> +  clocks:
>>> +    minItems: 1
>>> +    maxItems: 2
>>> +
>>
>> For the static replicator, you don't have an APB clock, as they can't be
>> programmed. It may have an ATB clock. So minItems 0, maxItems: 1
> 
> It can, see qcom-apq8064.dtsi
> 
> Also minItems:0 doesn't make sense to me. I'd rather keep this as an
> optional property rather than requiring an empty set.

Interesting, that must be atclk in fact. Because a static replicator
only manages ATB transactions. It doesn't have an APB interface.

I am not an expert in DTB schema. But the point is the clocks are optional.

Suzuki


> 
>>
>> Suzuki
>>
>>
>>
>>> +  clock-names:
>>> +    minItems: 1
>>> +    enum:
>>> +      - apb_pclk
>>> +      - atclk
>>> +
>>>      in-ports:
>>>        $ref: /schemas/graph.yaml#/properties/ports
>>>        additionalProperties: false
>>>
>>
> 



From patrice.chotard at foss.st.com  Tue Mar 18 06:40:42 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Tue, 18 Mar 2025 14:40:42 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <ac119dba-6e73-496c-97e1-d59ac0fe4a27@kernel.org>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
 <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>
 <ac119dba-6e73-496c-97e1-d59ac0fe4a27@kernel.org>
Message-ID: <06244bfb-1bd0-4a07-a928-3d2e68a89259@foss.st.com>



On 3/13/25 08:33, Krzysztof Kozlowski wrote:
> On 12/03/2025 15:23, Patrice CHOTARD wrote:
>>>> +static int stm32_omm_disable_child(struct device *dev)
>>>> +{
>>>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>>>> +	struct reset_control *reset;
>>>> +	int ret;
>>>> +	u8 i;
>>>> +
>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>> +		ret = clk_prepare_enable(omm->child[i].clk);
>>>> +		if (ret) {
>>>> +			dev_err(dev, "Can not enable clock\n");
>>>> +			return ret;
>>>> +		}
>>>> +
>>>> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
>>>> +		if (IS_ERR(reset)) {
>>>> +			dev_err(dev, "Can't get child reset\n");
>>>
>>> Why do you get reset of child? Parent is not suppposed to poke there.
>>> You might not have the reset there in the first place and it would not
>>> be an error.
>>
>> By ressetting child (OSPI), we ensure they are disabled and in a known state.
>> See the comment below.
>>
>>>
>>>
>>>> +			return PTR_ERR(reset);
>>>> +		};
>>>> +
>>>> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
>>>> +		reset_control_assert(reset);
>>>> +		udelay(2);
>>>> +		reset_control_deassert(reset);
>>>
>>> No, the child should handle this, not parent.
>>
>> Octo Memory Manager can only be configured if both child are disabled.
>> That's why here, parent handles this.
> 
> So if device by any chance started and is doing some useful work, then
> you cancel that work and reset it?

stm32_omm_configure() is only called if we get access granted on both children.
That means we are authorized to use these devices, so we can reset them.

> 
> And what if child does not have reset line? Your binding allows that, so
> how is it supposed to work then?

Ah yes, you are right, the OSPI bindings need to be updated
by requiring reset lines and the driver spi-stm32-ospi.c as well.
I will send a fix for that.

Thanks for pointing this.

> 
> This also leads me to questions about bindings - if you need to assert
> some reset, doesn't it mean that these resets are also coming through
> this device so they are part of this device node?

As we are able to retrieve children's reset from their respective node,
if you don't mind, OMM bindings can be kept as it's currently.

And another information, on some MP2 SoCs family, there is only one 
OSPI instance. So for these SoCs, there is no Octo Memory Manager.

> 
>>
>>>
>>>> +
>>>> +		reset_control_put(reset);
>>>> +		clk_disable_unprepare(omm->child[i].clk);
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int stm32_omm_probe(struct platform_device *pdev)
>>>> +{
>>>> +	struct platform_device *vdev;
>>>> +	struct device *dev = &pdev->dev;
>>>> +	struct stm32_omm *omm;
>>>> +	struct clk *clk;
>>>> +	int ret;
>>>> +	u8 child_access_granted = 0;
>>>
>>> Keep inits/assignments together
>>
>> ok
>>
>>>
>>>> +	u8 i, j;
>>>> +	bool child_access[OMM_CHILD_NB];
>>>> +
>>>> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
>>>> +	if (!omm)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
>>>> +	if (IS_ERR(omm->io_base))
>>>> +		return PTR_ERR(omm->io_base);
>>>> +
>>>> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
>>>> +	if (IS_ERR(omm->mm_res))
>>>> +		return PTR_ERR(omm->mm_res);
>>>> +
>>>> +	/* check child's access */
>>>> +	for_each_child_of_node_scoped(dev->of_node, child) {
>>>> +		if (omm->nb_child >= OMM_CHILD_NB) {
>>>> +			dev_err(dev, "Bad DT, found too much children\n");
>>>> +			ret = -E2BIG;
>>>> +			goto err_clk_release;
>>>> +		}
>>>> +
>>>> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
>>>> +			ret = -EINVAL;
>>>> +			goto err_clk_release;
>>>> +		}
>>>> +
>>>> +		ret = stm32_omm_check_access(dev, child);
>>>> +		if (ret < 0 && ret != -EACCES)
>>>> +			goto err_clk_release;
>>>> +
>>>> +		child_access[omm->nb_child] = false;
>>>> +		if (!ret) {
>>>> +			child_access_granted++;
>>>> +			child_access[omm->nb_child] = true;
>>>> +		}
>>>> +
>>>> +		omm->child[omm->nb_child].node = child;
>>>> +
>>>> +		clk = of_clk_get(child, 0);
>>>
>>> Why are you taking children clock? And why with this API, not clk_get?
>>
>> I need children's clock to reset them.
> 
> 
> The device driver should reset its device. It is not a discoverable bus,
> that would explain power sequencing from the parent.
> 
>> Why of_clk_get() usage is a problem here ? i can't get your point ?
> 
> Because it is not the API which device drivers should use. You should
> use clk_get or devm_clk_get.


ok, i will update this part using clk_get().

> 
> 
>>
>>> This looks like mixing clock provider in the clock consumer.
>>>
>>>> +		if (IS_ERR(clk)) {
>>>> +			dev_err(dev, "Can't get child clock\n");
>>>
>>> Syntax is always return dev_err_probe (or ret = dev_err_probe).
>>
>> ok
>>
>>>
>>>> +			ret = PTR_ERR(clk);
>>>> +			goto err_clk_release;
>>>> +		};
>>>> +
>>>> +		omm->child[omm->nb_child].clk = clk;
>>>> +		omm->nb_child++;
>>>> +	}
>>>> +
>>>> +	if (omm->nb_child != OMM_CHILD_NB) {
>>>> +		ret = -EINVAL;
>>>> +		goto err_clk_release;
>>>> +	}
>>>> +
>>>> +	platform_set_drvdata(pdev, omm);
>>>> +
>>>> +	pm_runtime_enable(dev);
>>>> +
>>>> +	/* check if OMM's resource access is granted */
>>>> +	ret = stm32_omm_check_access(dev, dev->of_node);
>>>> +	if (ret < 0 && ret != -EACCES)
>>>> +		goto err_clk_release;
>>>> +
>>>> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
>>>> +		/* Ensure both OSPI instance are disabled before configuring OMM */
>>>> +		ret = stm32_omm_disable_child(dev);
>>>> +		if (ret)
>>>> +			goto err_clk_release;
>>>> +
>>>> +		ret = stm32_omm_configure(dev);
>>>> +		if (ret)
>>>> +			goto err_clk_release;
>>>> +	} else {
>>>> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
>>>> +		/*
>>>> +		 * AMCR can't be set, so check if current value is coherent
>>>> +		 * with memory-map areas defined in DT
>>>> +		 */
>>>> +		ret = stm32_omm_set_amcr(dev, false);
>>>> +		if (ret)
>>>> +			goto err_clk_release;
>>>> +	}
>>>> +
>>>> +	/* for each child, if resource access is granted and status "okay", probe it */
>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
>>>
>>> If you have a device available, why do you create one more platform device?
>>>
>>>> +			continue;
>>>> +
>>>> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
>>>
>>> Why you cannot just populate the children?
>>
>> I can't use of_platform_populate(), by default it will populate all OMM's child.
>> Whereas here, we want to probe only the OMM's child which match our criteria.  
> 
> 
> Why wouldn't you populate everyone? The task of bus driver is not to
> filter out DT. If you got such DT - with all device nodes - you are
> expected to populate all of them. Otherwise, if you do not want all of
> them, it is expected that firmware or bootloader will give you DT
> without these nodes.

We don't want to populate every child by default because we can get 
cases where one child is shared between Cortex A and Cortex M.
That's why we must check if access is granted which ensure that 
firewall semaphore is available (RIFSC semaphore in our case).

Patrice

> 
> Best regards,
> Krzysztof


From andrew at lunn.ch  Tue Mar 18 06:44:36 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 14:44:36 +0100
Subject: =?utf-8?B?5Zue6KaG?= =?utf-8?Q?=3A?= [net-next 4/4] net:
 ftgmac100: add RGMII delay for AST2600
In-Reply-To: <SEYPR06MB513471FBFDEAFAA3308000699DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
 <dc7296b2-e7aa-4cc3-9aa7-44e97ec50fc3@lunn.ch>
 <SEYPR06MB513471FBFDEAFAA3308000699DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
Message-ID: <1a2dab82-ddb1-4c38-a576-abd1edd8d5e1@lunn.ch>

On Tue, Mar 18, 2025 at 10:46:58AM +0000, Jacky Chou wrote:
> Hi Andrew,
> 
> Thank you for your reply.
> 
> > > +	u32 rgmii_tx_delay, rgmii_rx_delay;
> > > +	u32 dly_reg, tx_dly_mask, rx_dly_mask;
> > > +	int tx, rx;
> > > +
> > > +	netdev = platform_get_drvdata(pdev);
> > > +	priv = netdev_priv(netdev);
> > > +
> > > +	tx = of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay);
> > > +	rx = of_property_read_u32(np, "rx-internal-delay-ps",
> > > +&rgmii_rx_delay);
> > 
> > > +	if (!tx) {
> > 
> > The documentation for of_property_read_u32() says:
> > 
> >  * Return: 0 on success, -EINVAL if the property does not exist,
> >  * -ENODATA if property does not have a value, and -EOVERFLOW if the
> >  * property data isn't large enough.
> > 
> > You need to handle EINVAL different to the other errors, which are real errors
> > and should fail the probe.
> > 
> > The commit message, and probably the binding needs to document what
> > happens when the properties are not in the DT blob. This needs to be part of
> > the bigger picture of how you are going to sort out the mess with existing .dts
> > files listing 'rgmii' when in fact they should be 'rgmii-id'.
> 
> Why can't the MAC add internal delay to RGMII? Is it necessary to add on PHY side?

The MAC could, but that is not the point. You need to explain how you
are going to solve the mess you have in DT, why all aspeed boards have
the wrong phy-mode. You need to fix that, and i will continue to NACK
new boards until the correct rgmii-id value can be used to indicate
there do not have extra long clock lines on the PCB.

> > > +		/* Use tx-internal-delay-ps as index to configure tx delay
> > > +		 * into scu register.
> > > +		 */
> > > +		if (rgmii_tx_delay > 64)
> > > +			dev_warn(&pdev->dev, "Get invalid tx delay value");
> > 
> > Return EINVAL and fail the probe.
> 
> Agreed.
> I just show warning here, because sometimes the RGMII delay value will configure at bootloader.

That is a different issue. If there is a value in DT, it must be
valid, fail the probe otherwise.

	Andrew


From ardb+git at google.com  Tue Mar 18 06:49:50 2025
From: ardb+git at google.com (Ard Biesheuvel)
Date: Tue, 18 Mar 2025 14:49:50 +0100
Subject: [RFC PATCH] arm64/mm: Remove randomization of the linear map
Message-ID: <20250318134949.3194334-2-ardb+git@google.com>

From: Ard Biesheuvel <ardb at kernel.org>

Since commit

  97d6786e0669 ("arm64: mm: account for hotplug memory when randomizing the linear region")

the decision whether or not to randomize the placement of the system's
DRAM inside the linear map is based on the capabilities of the CPU
rather than how much memory is present at boot time. This change was
necessary because memory hotplug may result in DRAM appearing in places
that are not covered by the linear region at all (and therefore
unusable) if the decision is solely based on the memory map at boot.

In the Android GKI kernel, which requires support for memory hotplug,
and is built with a reduced virtual address space of only 39 bits wide,
randomization of the linear map never happens in practice as a result.
And even on arm64 kernels built with support for 48 bit virtual
addressing, the wider PArange of recent CPUs means that linear map
randomization is slowly becoming a feature that only works on systems
that will soon be obsolete.

So let's just remove this feature. We can always bring it back in an
improved form if there is a real need for it.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Ryan Roberts <ryan.roberts at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Anshuman Khandual <anshuman.khandual at arm.com>
Cc: Kees Cook <kees at kernel.org>
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm64/kernel/image-vars.h     |  1 -
 arch/arm64/kernel/kaslr.c          |  2 --
 arch/arm64/kernel/pi/kaslr_early.c |  4 ----
 arch/arm64/mm/init.c               | 20 --------------------
 4 files changed, 27 deletions(-)

diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index ef3a69cc398e..80e0fd6e7651 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -51,7 +51,6 @@ PROVIDE(__pi_arm64_use_ng_mappings	= arm64_use_ng_mappings);
 PROVIDE(__pi_cavium_erratum_27456_cpus	= cavium_erratum_27456_cpus);
 #endif
 PROVIDE(__pi__ctype			= _ctype);
-PROVIDE(__pi_memstart_offset_seed	= memstart_offset_seed);
 
 PROVIDE(__pi_init_idmap_pg_dir		= init_idmap_pg_dir);
 PROVIDE(__pi_init_idmap_pg_end		= init_idmap_pg_end);
diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 1da3e25f9d9e..c9503ed45a6c 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -10,8 +10,6 @@
 #include <asm/cpufeature.h>
 #include <asm/memory.h>
 
-u16 __initdata memstart_offset_seed;
-
 bool __ro_after_init __kaslr_is_enabled = false;
 
 void __init kaslr_init(void)
diff --git a/arch/arm64/kernel/pi/kaslr_early.c b/arch/arm64/kernel/pi/kaslr_early.c
index 0257b43819db..e0e018046a46 100644
--- a/arch/arm64/kernel/pi/kaslr_early.c
+++ b/arch/arm64/kernel/pi/kaslr_early.c
@@ -18,8 +18,6 @@
 
 #include "pi.h"
 
-extern u16 memstart_offset_seed;
-
 static u64 __init get_kaslr_seed(void *fdt, int node)
 {
 	static char const seed_str[] __initconst = "kaslr-seed";
@@ -53,8 +51,6 @@ u64 __init kaslr_early_init(void *fdt, int chosen)
 			return 0;
 	}
 
-	memstart_offset_seed = seed & U16_MAX;
-
 	/*
 	 * OK, so we are proceeding with KASLR enabled. Calculate a suitable
 	 * kernel image offset from the seed. Let's place the kernel in the
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index ccdef53872a0..b3add829d681 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -277,26 +277,6 @@ void __init arm64_memblock_init(void)
 		}
 	}
 
-	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-		extern u16 memstart_offset_seed;
-		u64 mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
-		int parange = cpuid_feature_extract_unsigned_field(
-					mmfr0, ID_AA64MMFR0_EL1_PARANGE_SHIFT);
-		s64 range = linear_region_size -
-			    BIT(id_aa64mmfr0_parange_to_phys_shift(parange));
-
-		/*
-		 * If the size of the linear region exceeds, by a sufficient
-		 * margin, the size of the region that the physical memory can
-		 * span, randomize the linear region as well.
-		 */
-		if (memstart_offset_seed > 0 && range >= (s64)ARM64_MEMSTART_ALIGN) {
-			range /= ARM64_MEMSTART_ALIGN;
-			memstart_addr -= ARM64_MEMSTART_ALIGN *
-					 ((range * memstart_offset_seed) >> 16);
-		}
-	}
-
 	/*
 	 * Register the kernel text, kernel data, initrd, and initial
 	 * pagetables with memblock.
-- 
2.49.0.rc1.451.g8f38331e32-goog



From andrew at lunn.ch  Tue Mar 18 06:51:52 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 14:51:52 +0100
Subject: =?utf-8?B?5Zue6KaGOiDlm57opoY=?= =?utf-8?Q?=3A?= [net-next 4/4]
 net: ftgmac100: add RGMII delay for AST2600
In-Reply-To: <SEYPR06MB5134C8128FCF57D37F38CEFF9DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
 <20250317095229.6f8754dd@fedora.home>
 <Z9gC2vz2w5dfZsum@shell.armlinux.org.uk>
 <SEYPR06MB51347CD1AB5940641A77427D9DDF2@SEYPR06MB5134.apcprd06.prod.outlook.com>
 <c3c02498-24a3-4ced-8ba3-5ca62b243047@lunn.ch>
 <SEYPR06MB5134C8128FCF57D37F38CEFF9DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
Message-ID: <5b448c6b-a37d-4028-a56d-2953fc0e743a@lunn.ch>

On Tue, Mar 18, 2025 at 05:34:08AM +0000, Jacky Chou wrote:
> Hi Andrew,
> 
> Thank you for your reply.
> 
> > > The RGMII delay of AST2600 has a lot of steps can be configured.
> > 
> > Are they uniformly space? Then it should be a simple formula to calculate? Or
> > a lookup table?
> 
> There are fixed delay values by step. I list below.
> AST2600 MAC0/1 one step delay = 45 ps
> AST2600 MAC2/3 one step delay = 250 ps

That is messy.

> I calculate all step and emulate them.
> The dt-binding will be like below.
> rx-internal-delay-ps:
>     description:
>       Setting this property to a non-zero number sets the RX internal delay
>       for the MAC. ... skip ...
>     enum:
>       [45, 90, 135, 180, 225, 250, 270, 315, 360, 405, 450, 495, 500, 540, 585, 630, 675, 
>        720, 750, 765, 810, 855, 900, 945, 990, 1000, 1035, 1080, 1125, 1170, 1215, 1250, 
>        1260, 1305, 1350, 1395, 1440, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 
>        3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 
>        7250, 7500, 7750, 8000]

Can the hardware do 0 ps?

So this list is a superset of both 45ps and 250ps steps?

Lets see what the DT Maintainers say, but it could be you need two
different compatibles for mac0/1 to mac2/3 because they are not
actually compatible! You can then have a list per compatible.

	Andrew


From lorenzo at kernel.org  Tue Mar 18 06:53:06 2025
From: lorenzo at kernel.org (lorenzo at kernel.org)
Date: Tue, 18 Mar 2025 14:53:06 +0100
Subject: [PATCH 02/21] wifi: mt76: mt7996: Add
 mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
In-Reply-To: <9efb42f0948b23cc127dc5c5d9e31791f80219ef.camel@mediatek.com>
References: <20250312-b4-mt7996-mlo-p2-v1-0-015b3d6fd928@kernel.org>
 <20250312-b4-mt7996-mlo-p2-v1-2-015b3d6fd928@kernel.org>
 <9efb42f0948b23cc127dc5c5d9e31791f80219ef.camel@mediatek.com>
Message-ID: <Z9l6woY4TYKe2olT@lore-desk>

[...]
> > link_sta);
> > +
> > +?????????????? if (sta->mlo && conn_state != CONN_STATE_DISCONNECT)
> 
> The latter check seems already to be handled by:
> if (conn_state == CONN_STATE_DISCONNECT)
>     goto out;

ack, I will fix it.

Regards,
Lorenzo

> 
> > {
> > +?????????????????????? mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
> > +?????????????????????? mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
> > +?????????????? }
> > ??????? }
> > 
> > ??????? ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
> > 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250318/b50758ef/attachment.sig>

From andrew at lunn.ch  Tue Mar 18 07:03:03 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 15:03:03 +0100
Subject: =?utf-8?B?5Zue6KaGOiBbbmV0LW5leA==?= =?utf-8?Q?t?= 2/4] ARM:
 dts: ast2600-evb: add default RGMII delay
In-Reply-To: <SEYPR06MB5134A69692C6C474BDE9A6A99DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-3-jacky_chou@aspeedtech.com>
 <5db47dea-7d90-45a1-85a1-1f4f5edd3567@lunn.ch>
 <SEYPR06MB5134A69692C6C474BDE9A6A99DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
Message-ID: <8c0195dd-50b3-4f30-a021-c5b77d39d895@lunn.ch>

On Tue, Mar 18, 2025 at 11:00:27AM +0000, Jacky Chou wrote:
> Hi Andrew,
> 
> Thank you for your reply.
> 
> > >  	phy-mode = "rgmii";
> > >  	phy-handle = <&ethphy2>;
> > >
> > > +	tx-internal-delay-ps = <8>;
> > > +	rx-internal-delay-ps = <4>;
> > > +
> > 
> > Ideally you want:
> > 
> > 	phy-mode = "rgmii-id";
> > 	tx-internal-delay-ps = <0>;
> > 	rx-internal-delay-ps = <0>;
> > 
> > Since 'rgmii-id' correctly describes the hardware.
> 
> I still confuse about ethernet-controller.yaml.
> It lists 'rgmi', 'rgmii-rxid', 'rgmii-txid' and 'rgmii-id'.

DT describes the board. Does the board add the 2ns delay via extra
long clock lines? If yes, use rgmii. If the MAC/PHY pair need to add
the 2ns delay, use rgmii-id.

If the MAC/PHY pair is adding the delay, the DT says nothing about how
they add the delay.

The general rule is the PHY adds the delay. If you look at
drivers/net/phy/*.c, every PHY that implements RGMII support both
PHY_INTERFACE_MODE_RGMII_ID and PHY_INTERFACE_MODE_RGMII. There is no
reason not to follow ever other MAC/PHY pair and have the PHY add the
delay. The MAC can then do fine tuning if needed, adding small delays.

	Andrew


From andrew at lunn.ch  Tue Mar 18 07:08:24 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 15:08:24 +0100
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <fdd969cb-aa2d-4d55-949e-e2631757221e@lunn.ch>

> +&mac3 {
> +	status = "okay";
> +	phy-mode = "rgmii";

Does the PCB have extra long clock lines to insert the 2ns RGMII
delay? Or are you another victim of aspeeds broken MAC/SCU driver?

       Andrew


From liankun.yang at mediatek.com  Tue Mar 18 07:02:21 2025
From: liankun.yang at mediatek.com (Liankun Yang)
Date: Tue, 18 Mar 2025 22:02:21 +0800
Subject: [PATCH v3 1/1] drm/mediatek: Adjust bandwidth limit for DP
In-Reply-To: <20250318140236.13650-1-liankun.yang@mediatek.com>
References: <20250318140236.13650-1-liankun.yang@mediatek.com>
Message-ID: <20250318140236.13650-2-liankun.yang@mediatek.com>

By adjusting the order of link training and relocating it to HPD,
link training can identify the usability of each lane in the current link.

It also supports handling signal instability and weakness due to
environmental issues, enabling the acquisition of a stable bandwidth
for the current link. Subsequently, DP work can proceed based on
the actual maximum bandwidth.

It should training in the hpd event thread.
Check the mode with lane count and link rate of training.

Signed-off-by: Liankun Yang <liankun.yang at mediatek.com>
---
Change in V3:
- Remove 'mtk_dp->enabled = false" in atomic disable.
- Remove 'mtk_dp->enabled = true" in atomic enable.
Per suggestion from the previous thread:
https://patchwork.kernel.org/project/linux-mediatek/patch/20241025083036.8829-4-liankun.yang at mediatek.com/

Change in V2:
- Adjust DP training timing.
- Adjust parse capabilities timing.
- Add power on/off for connect/disconnect.
Per suggestion from the previous thread:
https://patchwork.kernel.org/project/linux-mediatek/patch/20240315015233.2023-1-liankun.yang at mediatek.com/
---
 drivers/gpu/drm/mediatek/mtk_dp.c | 39 ++++++++++++++++---------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index 3d4648d2e15f..fb76fc1bf497 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -1976,6 +1976,7 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
 	struct mtk_dp *mtk_dp = dev;
 	unsigned long flags;
 	u32 status;
+	int ret;
 
 	if (mtk_dp->need_debounce && mtk_dp->train_info.cable_plugged_in)
 		msleep(100);
@@ -1994,9 +1995,28 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
 			memset(&mtk_dp->info.audio_cur_cfg, 0,
 			       sizeof(mtk_dp->info.audio_cur_cfg));
 
+			mtk_dp->enabled = false;
+			/* power off aux */
+			mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
+			       DP_PWR_STATE_BANDGAP_TPLL,
+			       DP_PWR_STATE_MASK);
+
 			mtk_dp->need_debounce = false;
 			mod_timer(&mtk_dp->debounce_timer,
 				  jiffies + msecs_to_jiffies(100) - 1);
+		} else {
+			mtk_dp_aux_panel_poweron(mtk_dp, true);
+
+			ret = mtk_dp_parse_capabilities(mtk_dp);
+			if (ret)
+				drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
+
+			/* Training */
+			ret = mtk_dp_training(mtk_dp);
+			if (ret)
+				drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret);
+
+			mtk_dp->enabled = true;
 		}
 	}
 
@@ -2162,16 +2182,6 @@ static const struct drm_edid *mtk_dp_edid_read(struct drm_bridge *bridge,
 
 	drm_edid = drm_edid_read_ddc(connector, &mtk_dp->aux.ddc);
 
-	/*
-	 * Parse capability here to let atomic_get_input_bus_fmts and
-	 * mode_valid use the capability to calculate sink bitrates.
-	 */
-	if (mtk_dp_parse_capabilities(mtk_dp)) {
-		drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
-		drm_edid_free(drm_edid);
-		drm_edid = NULL;
-	}
-
 	if (drm_edid) {
 		/*
 		 * FIXME: get rid of drm_edid_raw()
@@ -2365,13 +2375,6 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
 
 	mtk_dp_aux_panel_poweron(mtk_dp, true);
 
-	/* Training */
-	ret = mtk_dp_training(mtk_dp);
-	if (ret) {
-		drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret);
-		goto power_off_aux;
-	}
-
 	ret = mtk_dp_video_config(mtk_dp);
 	if (ret)
 		goto power_off_aux;
@@ -2389,7 +2392,6 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
 		       sizeof(mtk_dp->info.audio_cur_cfg));
 	}
 
-	mtk_dp->enabled = true;
 	mtk_dp_update_plugged_status(mtk_dp);
 
 	return;
@@ -2404,7 +2406,6 @@ static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge,
 {
 	struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
 
-	mtk_dp->enabled = false;
 	mtk_dp_update_plugged_status(mtk_dp);
 	mtk_dp_video_enable(mtk_dp, false);
 	mtk_dp_audio_mute(mtk_dp, true);
-- 
2.45.2



From angelogioacchino.delregno at collabora.com  Tue Mar 18 07:21:20 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 18 Mar 2025 15:21:20 +0100
Subject: [PATCH 2/2] arm64: dts: mediatek: mt8192-asurada-spherion: Mark
 trackpads as fail-needs-probe
In-Reply-To: <20250318102259.189289-3-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
 <20250318102259.189289-3-laura.nao@collabora.com>
Message-ID: <79fc072f-9fea-4810-bd9d-3539ebb70ca3@collabora.com>

Il 18/03/25 11:22, Laura Nao ha scritto:
> Different Spherion variants use different trackpads on the same I2C2
> bus. Instead of enabling all of them by default, mark them as
> "fail-needs-probe" and let the implementation determine which one is
> actually present.
> 
> Additionally, move the trackpad pinctrl entry back to the individual
> trackpad nodes.
> 
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From broonie at kernel.org  Tue Mar 18 07:21:13 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 18 Mar 2025 14:21:13 +0000
Subject: [PATCH] arm64/fpsimd: Avoid unnecessary per-CPU buffers for EFI
 runtime calls
In-Reply-To: <20250318132421.3155799-2-ardb+git@google.com>
References: <20250318132421.3155799-2-ardb+git@google.com>
Message-ID: <5c025dd9-8a4a-4ebb-a2ae-ef55538cd39a@sirena.org.uk>

On Tue, Mar 18, 2025 at 02:24:22PM +0100, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb at kernel.org>
> 
> The EFI specification has some elaborate rules about which runtime
> services may be called while another runtime service call is already in
> progress. In Linux, however, for simplicity, all EFI runtime service
> invocations are serialized via the efi_runtime_lock semaphore.

> This implies that calls to the helper pair arch_efi_call_virt_setup()
> and arch_efi_call_virt_teardown() are serialized too, and are guaranteed
> not to nest.  Furthermore, the arm64 arch code has its own spinlock to
> serialize use of the EFI runtime stack, of which only a single instance
> exists.

> This all means that the FP/SIMD and SVE state preserve/restore logic in
> __efi_fpsimd_begin() and __efi_fpsimd_end() are also serialized, and
> only a single instance of the associated per-CPU variables can ever be
> in use at the same time. There is therefore no need at all for per-CPU
> variables here, and they can all be replaced with singleton instances.
> This saves a non-trivial amount of memory on systems with many CPUs.

That makes life a lot easier all round, and like you say the memory
savings are nice.

Reviewed-by: Mark Brown <broonie at kernel.org>

> -		if (system_supports_sve() && likely(efi_sve_state)) {
> -			char *sve_state = this_cpu_ptr(efi_sve_state);
> +		if (system_supports_sve() && efi_sve_state != NULL) {

The change does remove a bunch of these likely() annotations, though the
chances that they were ever having an impact seem minimal.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250318/9341ead7/attachment.sig>

From angelogioacchino.delregno at collabora.com  Tue Mar 18 07:21:21 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 18 Mar 2025 15:21:21 +0100
Subject: [PATCH 1/2] platform/chrome: Add support for Google Spherion in
 HW prober
In-Reply-To: <20250318102259.189289-2-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
 <20250318102259.189289-2-laura.nao@collabora.com>
Message-ID: <2b666683-47f9-44b5-bae9-109764e60690@collabora.com>

Il 18/03/25 11:22, Laura Nao ha scritto:
> Add a new compatible entry for "google,spherion" to the hardware prober
> platform list, using the same I2C component prober and trackpad data as
> "google,hana".
> 
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From robin.murphy at arm.com  Tue Mar 18 07:32:10 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 14:32:10 +0000
Subject: [PATCH Resend] perf/arm-cmn: Remove CMN-600 DTC domain special case
Message-ID: <67985e39f53b56385d79a4f1264cf7f9cacedb58.1742308248.git.robin.murphy@arm.com>

The special case for trying to infer the DTC domain for DTC-adjacent
nodes on CMN-600 is fragile and buggy - currently resulting in subtly
messed up DTC counter allocation - and the theoretical benefit it
offers to a tiny minority of use-cases arguably doesn't outweigh the
inconsistency it offers to others anyway. Just get rid of it.

Fixes: ab33c66fd8f1 ("perf/arm-cmn: Enable per-DTC counter allocation")
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/perf/arm-cmn.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index ef959e66db7c..582f0c0e1783 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -2166,13 +2166,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
 
 	cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
 
-	if (cmn->part == PART_CMN600 && cmn->num_dtcs > 1) {
-		/* We do at least know that a DTC's XP must be in that DTC's domain */
-		dn = arm_cmn_node(cmn, CMN_TYPE_DTC);
-		for (int i = 0; i < cmn->num_dtcs; i++)
-			arm_cmn_node_to_xp(cmn, dn + i)->dtc = i;
-	}
-
 	for (dn = cmn->dns; dn->type; dn++) {
 		if (dn->type == CMN_TYPE_XP)
 			continue;
-- 
2.39.2.101.g768bb238c484.dirty



From linmq006 at gmail.com  Tue Mar 18 07:33:40 2025
From: linmq006 at gmail.com (Miaoqian Lin)
Date: Tue, 18 Mar 2025 22:33:40 +0800
Subject: [PATCH] phy: rockchip-usb: Fix refcount leak in rockchip_init_usb_uart
Message-ID: <20250318143340.25162-1-linmq006@gmail.com>

Fix a reference counter leak in rockchip_init_usb_uart() where
of_node_put(np) was missing after of_find_matching_node_and_match().

Fixes: 605df8af33a7 ("phy: rockchip-usb: add handler for usb-uart functionality")
Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-usb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-usb.c b/drivers/phy/rockchip/phy-rockchip-usb.c
index 666a896c8f0a..de7d879bb460 100644
--- a/drivers/phy/rockchip/phy-rockchip-usb.c
+++ b/drivers/phy/rockchip/phy-rockchip-usb.c
@@ -539,6 +539,7 @@ static int __init rockchip_init_usb_uart(void)
 	if (!data->init_usb_uart) {
 		pr_err("%s: usb-uart not available on %s\n",
 		       __func__, match->compatible);
+		of_node_put(np);
 		return -ENOTSUPP;
 	}
 
@@ -547,6 +548,7 @@ static int __init rockchip_init_usb_uart(void)
 		grf = syscon_node_to_regmap(np->parent);
 	if (IS_ERR(grf))
 		grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	of_node_put(np);
 	if (IS_ERR(grf)) {
 		pr_err("%s: Missing rockchip,grf property, %lu\n",
 		       __func__, PTR_ERR(grf));
-- 
2.39.5 (Apple Git-154)



From broonie at kernel.org  Tue Mar 18 07:37:34 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 18 Mar 2025 14:37:34 +0000
Subject: [PATCH] spi: stm32-ospi: Include "gpio/consumer.h"
In-Reply-To: <20250318045549.1711502-1-peng.fan@oss.nxp.com>
References: <20250318045549.1711502-1-peng.fan@oss.nxp.com>
Message-ID: <174230865462.108912.8267700120820923591.b4-ty@kernel.org>

On Tue, 18 Mar 2025 12:55:49 +0800, Peng Fan (OSS) wrote:
> of_gpio.h should be deprecated, use "gpio/consumer.h".
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: stm32-ospi: Include "gpio/consumer.h"
      commit: cc1273dfac2697545adc9418c890ac194f18f523

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 07:37:31 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 15:37:31 +0100
Subject: [PATCH v2 07/10] ARM: dts: qcom: apq8064 merge hw splinlock into
 corresponding syscon device
In-Reply-To: <20250318-fix-nexus-4-v2-7-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-7-bcedd1406790@oss.qualcomm.com>
Message-ID: <61ed7f53-e7af-43ab-bd92-15317b94b617@oss.qualcomm.com>

On 3/18/25 2:22 PM, Dmitry Baryshkov wrote:
> Follow up the expected way of describing the SFPB hwspinlock and merge
> hwspinlock node into corresponding syscon node, fixing several dt-schema
> warnings.
> 
> Fixes: 24a9baf933dc ("ARM: dts: qcom: apq8064: Add hwmutex and SMEM nodes")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>

Konrad


From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 07:37:53 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 15:37:53 +0100
Subject: [PATCH v2 10/10] ARM: dts: qcom: apq8064: move replicator out of
 soc node
In-Reply-To: <20250318-fix-nexus-4-v2-10-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-10-bcedd1406790@oss.qualcomm.com>
Message-ID: <08d0a3ba-9141-4877-84ef-3b16b074b31d@oss.qualcomm.com>

On 3/18/25 2:22 PM, Dmitry Baryshkov wrote:
> The CoreSight static replicator device isn't a part of the system MMIO
> bus, as such it should not be a part of the soc node. Follow the example
> of other platforms and move it out of the soc bus to the top-level (and
> reoder ports to follow alphabetic order).
> 
> Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>

Konrad


From nfraprado at collabora.com  Tue Mar 18 07:39:14 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Tue, 18 Mar 2025 11:39:14 -0300
Subject: [PATCH 2/2] arm64: dts: mediatek: mt8192-asurada-spherion: Mark
 trackpads as fail-needs-probe
In-Reply-To: <20250318102259.189289-3-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
 <20250318102259.189289-3-laura.nao@collabora.com>
Message-ID: <f80dfa43-74f4-431b-934c-e103b8204276@notapiano>

On Tue, Mar 18, 2025 at 11:22:59AM +0100, Laura Nao wrote:
> Different Spherion variants use different trackpads on the same I2C2
> bus. Instead of enabling all of them by default, mark them as
> "fail-needs-probe" and let the implementation determine which one is
> actually present.
> 
> Additionally, move the trackpad pinctrl entry back to the individual
> trackpad nodes.
> 
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
Tested-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

With these patches only the right trackpad is enabled on my Spherion and it
works as expected.

Thanks,
N?colas


From nfraprado at collabora.com  Tue Mar 18 07:36:18 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Tue, 18 Mar 2025 11:36:18 -0300
Subject: [PATCH 1/2] platform/chrome: Add support for Google Spherion in
 HW prober
In-Reply-To: <20250318102259.189289-2-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com>
 <20250318102259.189289-2-laura.nao@collabora.com>
Message-ID: <f74001b3-ea40-4acc-b8a1-635532a5f205@notapiano>

On Tue, Mar 18, 2025 at 11:22:58AM +0100, Laura Nao wrote:
> Add a new compatible entry for "google,spherion" to the hardware prober
> platform list, using the same I2C component prober and trackpad data as
> "google,hana".
> 
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
Tested-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Thanks,
N?colas


From konrad.dybcio at oss.qualcomm.com  Tue Mar 18 07:36:49 2025
From: konrad.dybcio at oss.qualcomm.com (Konrad Dybcio)
Date: Tue, 18 Mar 2025 15:36:49 +0100
Subject: [PATCH v2 06/10] ARM: dts: qcom: apq8064: add missing clocks to
 the timer node
In-Reply-To: <20250318-fix-nexus-4-v2-6-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-6-bcedd1406790@oss.qualcomm.com>
Message-ID: <c8b872ed-62fa-4c56-97ac-d01c400d621c@oss.qualcomm.com>

On 3/18/25 2:21 PM, Dmitry Baryshkov wrote:
> In order to fix DT schema warning and describe hardware properly, add
> missing sleep clock to the timer node.
> 
> Fixes: f335b8af4fd5 ("ARM: dts: qcom: Add initial APQ8064 SoC and IFC6410 board device trees")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---

This is not strictly related to this patch, but this node/binding:

* clock-frequency seems unused
* "qcom,msm-timer" seems to have never been present in drivers/watchdog,
  arch/arm/mach-qcom or arch/arm/mach-msm

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>

Konrad


From alb3rt0.m3rciai at gmail.com  Tue Mar 18 07:41:59 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Tue, 18 Mar 2025 15:41:59 +0100
Subject: [PATCH resend v3 1/1] arm64: dts: imx93: add ddr edac support
In-Reply-To: <Z8+mcZw9yjOr3m/y@dragon>
References: <20250225192159.2907320-1-Frank.Li@nxp.com>
 <Z8+mcZw9yjOr3m/y@dragon>
Message-ID: <Z9mGNxfcquaYW0P0@alb3rt0-ThinkPad-P15-Gen-1>

On Tue, Mar 11, 2025 at 10:56:49AM +0800, Shawn Guo wrote:
> On Tue, Feb 25, 2025 at 02:21:58PM -0500, Frank Li wrote:
> > Add ddr edac support for imx93.
> > 
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> 
> Applied, thanks!
> 
> 
Reviewed-by: Alberto Merciai <alb3rt0.m3rciai at gmail.com>
Tested-by: Alberto Merciai <alb3rt0.m3rciai at gmail.com>

Thanks,
Alberto


From vladimir.oltean at nxp.com  Tue Mar 18 07:54:38 2025
From: vladimir.oltean at nxp.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 16:54:38 +0200
Subject: [PATCH v4 net-next 05/14] net: enetc: add debugfs interface to
 dump MAC filter
In-Reply-To: <PAXPR04MB8510F67EFC80DFCC7B9F13B588DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
References: <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-1-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250311053830.1516523-6-wei.fang@nxp.com>
 <20250317144843.wp432pgodn4vjejf@skbuf>
 <PAXPR04MB8510F67EFC80DFCC7B9F13B588DE2@PAXPR04MB8510.eurprd04.prod.outlook.com>
Message-ID: <20250318145438.h5bowwyopppnryw6@skbuf>

On Tue, Mar 18, 2025 at 05:28:56AM +0200, Wei Fang wrote:
> > On Tue, Mar 11, 2025 at 01:38:21PM +0800, Wei Fang wrote:
> > > +static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
> > > +{
> > > +	struct enetc_si *si = s->private;
> > > +	struct enetc_hw *hw = &si->hw;
> > > +	u32 hash_h, hash_l;
> > > +
> > > +	hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
> > > +	hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
> > > +	seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
> > > +		   i, hash_h, hash_l);
> > 
> > Maybe the ":" separator between the high and low 32 bits is clearer than "x".
> 
> I want it to be presented as a full 64-bit entry. If it is in the format
> of "%08x:%08x", it may be difficult to understand which is the high
> 32-bit and which is the low 32-bit.

Ah :-/ sorry, I made a mistake. I believed you're printing a literal "x"
as a separator between the high and the low word, which made no sense
(hence my comment). But the "x" was in fact the printf format specifier
for "hexadecimal" (sorry!). What I was saying is that ":" is a clearer
separator than "x", which of course makes no sense now.

Anyway, I made a second mistake, which is that I didn't mean to suggest
":" as a separator, but ",". I had misremembered...

The reason I had made that suggestion is prior experience with phylink,
which prints link mode masks with "%*pb" (the implementation is in the
"pointer()" function in lib/vsprintf.c). This is an error message which
many users may have seen before:

[   61.800079] mv88e6085 d0032004.mdio-mii:12 sfp: validation with support 00,00000000,00000000,00000000 failed: -EINVAL

I think the semantics are also widely accepted for this format, and it's
a little bit easier on the eye. I have searched many times in the past
through enum ethtool_link_mode_bit_indices based on the bits set in this
bitmap, and others may have done that too. It's known that bit zero is
the right-most bit.

But overall, printing the 64-bit number with no separator at all is not
unacceptable, either.


From patchwork-bot+netdevbpf at kernel.org  Tue Mar 18 08:00:34 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 18 Mar 2025 15:00:34 +0000
Subject: [PATCH net-next v2 0/9] net: stmmac: remove unnecessary
 of_get_phy_mode() calls
In-Reply-To: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
References: <Z9FQjQZb0IMaQJ9H@shell.armlinux.org.uk>
Message-ID: <174231003400.344268.9977818669398853411.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Wed, 12 Mar 2025 09:14:53 +0000 you wrote:
> Hi,
> 
> This series removes unnecessary of_get_phy_mode() calls from the stmmac
> glue drivers. stmmac_probe_config_dt() / devm_stmmac_probe_config_dt()
> already gets the interface mode using device_get_phy_mode() and stores
> it in plat_dat->phy_interface.
> 
> [...]

Here is the summary with links:
  - [net-next,v2,1/9] net: stmmac: qcom-ethqos: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/8ee1c926f31e
  - [net-next,v2,2/9] net: stmmac: mediatek: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/46f84d700cb8
  - [net-next,v2,3/9] net: stmmac: anarion: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/e3ef12172a83
  - [net-next,v2,4/9] net: stmmac: ipq806x: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/f07cb4b4b481
  - [net-next,v2,5/9] net: stmmac: meson8b: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/3e5833060efb
  - [net-next,v2,6/9] net: stmmac: rk: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/9886718ad1c5
  - [net-next,v2,7/9] net: stmmac: sti: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/3e2858bb3f59
  - [net-next,v2,8/9] net: stmmac: sun8i: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/3d9e9dfce04c
  - [net-next,v2,9/9] net: stmmac: sunxi: remove of_get_phy_mode()
    https://git.kernel.org/netdev/net-next/c/00d2c3c07124

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From olteanv at gmail.com  Tue Mar 18 08:15:40 2025
From: olteanv at gmail.com (Vladimir Oltean)
Date: Tue, 18 Mar 2025 17:15:40 +0200
Subject: [net-next PATCH v13 13/14] net: dsa: Add Airoha AN8855 5-Port
 Gigabit DSA Switch driver
In-Reply-To: <20250315154407.26304-14-ansuelsmth@gmail.com>
References: <20250315154407.26304-1-ansuelsmth@gmail.com>
 <20250315154407.26304-14-ansuelsmth@gmail.com>
Message-ID: <20250318151540.4rmw6jj5hh2rp4b4@skbuf>

On Sat, Mar 15, 2025 at 04:43:53PM +0100, Christian Marangi wrote:
> +/* Similar to MT7530 also trap link local frame and special frame to CPU */
> +static int an8855_trap_special_frames(struct an8855_priv *priv)
> +{
> +	int ret;
> +
> +	/* Trap BPDUs to the CPU port(s) and egress them
> +	 * VLAN-untagged.
> +	 */
> +	ret = regmap_update_bits(priv->regmap, AN8855_BPC,
> +				 AN8855_BPDU_BPDU_FR | AN8855_BPDU_EG_TAG |
> +				 AN8855_BPDU_PORT_FW,
> +				 AN8855_BPDU_BPDU_FR |
> +				 FIELD_PREP(AN8855_BPDU_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				 FIELD_PREP(AN8855_BPDU_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +	if (ret)
> +		return ret;
> +
> +	/* Trap 802.1X PAE frames to the CPU port(s) and egress them
> +	 * VLAN-untagged.
> +	 */
> +	ret = regmap_update_bits(priv->regmap, AN8855_PAC,
> +				 AN8855_PAE_BPDU_FR | AN8855_PAE_EG_TAG |
> +				 AN8855_PAE_PORT_FW,
> +				 AN8855_PAE_BPDU_FR |
> +				 FIELD_PREP(AN8855_PAE_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				 FIELD_PREP(AN8855_PAE_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +	if (ret)
> +		return ret;
> +
> +	/* Trap frames with :01 MAC DAs to the CPU port(s) and egress
> +	 * them VLAN-untagged.
> +	 */
> +	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
> +				 AN8855_R01_BPDU_FR | AN8855_R01_EG_TAG |
> +				 AN8855_R01_PORT_FW,
> +				 AN8855_R01_BPDU_FR |
> +				 FIELD_PREP(AN8855_R01_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				 FIELD_PREP(AN8855_R01_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +	if (ret)
> +		return ret;
> +
> +	/* Trap frames with :02 MAC DAs to the CPU port(s) and egress
> +	 * them VLAN-untagged.
> +	 */
> +	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
> +				 AN8855_R02_BPDU_FR | AN8855_R02_EG_TAG |
> +				 AN8855_R02_PORT_FW,
> +				 AN8855_R02_BPDU_FR |
> +				 FIELD_PREP(AN8855_R02_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				 FIELD_PREP(AN8855_R02_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +	if (ret)
> +		return ret;
> +
> +	/* Trap frames with :03 MAC DAs to the CPU port(s) and egress
> +	 * them VLAN-untagged.
> +	 */
> +	ret = regmap_update_bits(priv->regmap, AN8855_RGAC1,
> +				 AN8855_R03_BPDU_FR | AN8855_R03_EG_TAG |
> +				 AN8855_R03_PORT_FW,
> +				 AN8855_R03_BPDU_FR |
> +				 FIELD_PREP(AN8855_R03_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				 FIELD_PREP(AN8855_R03_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +	if (ret)
> +		return ret;
> +
> +	/* Trap frames with :0E MAC DAs to the CPU port(s) and egress
> +	 * them VLAN-untagged.
> +	 */
> +	return regmap_update_bits(priv->regmap, AN8855_RGAC1,
> +				  AN8855_R0E_BPDU_FR | AN8855_R0E_EG_TAG |
> +				  AN8855_R0E_PORT_FW,
> +				  AN8855_R0E_BPDU_FR |
> +				  FIELD_PREP(AN8855_R0E_EG_TAG, AN8855_VLAN_EG_UNTAGGED) |
> +				  FIELD_PREP(AN8855_R0E_PORT_FW, AN8855_BPDU_CPU_ONLY));
> +}

Is there a way in which you could group the registers a bit more?
The function occupies 2 screens :-/

There are 4 read-modify-write operations in succession to the RGAC1
register. Maybe you can converge them into a single regmap_update_bits()
call.

Also, for packets which reach the CPU via a trap, we shouldn't set
skb->offload_fwd_mark = 1. In other words, if the bridge layer wants to
forward them in software (including to other an8855 ports), let it do so.
The common example given in commit 515853ccecc6 ("bridge: allow
forwarding some link local frames") is 802.1X PAE (01-80-C2-00-00-03).

I notice mtk_tag_rcv() calls dsa_default_offload_fwd_mark() with no
pre-condition. Do you know whether there exists any bit in the RX tag
which signifies whether the packet was received because of a trap
(or if it was autonomously forwarded by the switch to the other bridge
ports as well)? The offload_fwd_mark bit should be set based on
something like that.


From linmq006 at gmail.com  Tue Mar 18 08:17:12 2025
From: linmq006 at gmail.com (Miaoqian Lin)
Date: Tue, 18 Mar 2025 23:17:12 +0800
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
Message-ID: <20250318151712.28763-1-linmq006@gmail.com>

Fix a reference counter leak in psci_dt_init() where of_node_put(np) was
missing after of_find_matching_node_and_match() when np is unavailable.

Fixes: bff60792f994 ("arm64: psci: factor invocation code to drivers")
Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
---
 drivers/firmware/psci/psci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index a1ebbe9b73b1..38ca190d4a22 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -804,8 +804,10 @@ int __init psci_dt_init(void)
 
 	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
 
-	if (!np || !of_device_is_available(np))
+	if (!np || !of_device_is_available(np)) {
+		of_node_put(np);
 		return -ENODEV;
+	}
 
 	init_fn = (psci_initcall_t)matched_np->data;
 	ret = init_fn(np);
-- 
2.39.5 (Apple Git-154)



From detlev.casanova at collabora.com  Tue Mar 18 08:20:49 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Tue, 18 Mar 2025 11:20:49 -0400
Subject: [PATCH] iommu/rockchip: Add flush_iotlb_all ops
Message-ID: <20250318152049.14781-1-detlev.casanova@collabora.com>

From: Jonas Karlman <jonas at kwiboo.se>

On some Rockchip cores (like the vdpu34x video decoder), the IOMMU device
is inside the the device that uses it.

The IOMMU device can still be driven by the iommu driver, but when an
error occurs in the main device (e.g. a decoding error that resets the
decoder), the IOMMU device will also be reseted.
In such situation, the IOMMU driver and the hardware are out of sync and
IOMMU errors will start popping up.

To avoid that, add a flush_iotlb_all function that will let the main drivers
(e.g. rkvdec) tell the IOMMU driver to write all its cached mappings into
the IOMMU hardware when such an error occured.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
Signed-off-by: Detlev Casanova <detlev.casanova at collabora.com>
---
 drivers/iommu/rockchip-iommu.c | 45 ++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 323cc665c357..7086716cb8fc 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -899,6 +899,40 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
 	return unmap_size;
 }
 
+static void rk_iommu_flush_iotlb_all(struct iommu_domain *domain)
+{
+	struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
+	struct list_head *pos;
+	unsigned long flags;
+	int i, ret;
+
+	spin_lock_irqsave(&rk_domain->iommus_lock, flags);
+	list_for_each(pos, &rk_domain->iommus) {
+		struct rk_iommu *iommu = list_entry(pos, struct rk_iommu, node);
+
+		ret = pm_runtime_get_if_in_use(iommu->dev);
+		if (!ret || WARN_ON_ONCE(ret < 0))
+			continue;
+
+		if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
+			continue;
+
+		rk_iommu_enable_stall(iommu);
+		for (i = 0; i < iommu->num_mmu; i++) {
+			rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
+				rk_ops->mk_dtentries(rk_domain->dt_dma));
+			rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
+			rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
+		}
+		rk_iommu_enable_paging(iommu);
+		rk_iommu_disable_stall(iommu);
+
+		clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+		pm_runtime_put(iommu->dev);
+	}
+	spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
+}
+
 static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
 {
 	struct rk_iommudata *data = dev_iommu_priv_get(dev);
@@ -1172,11 +1206,12 @@ static const struct iommu_ops rk_iommu_ops = {
 	.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
 	.of_xlate = rk_iommu_of_xlate,
 	.default_domain_ops = &(const struct iommu_domain_ops) {
-		.attach_dev	= rk_iommu_attach_device,
-		.map_pages	= rk_iommu_map,
-		.unmap_pages	= rk_iommu_unmap,
-		.iova_to_phys	= rk_iommu_iova_to_phys,
-		.free		= rk_iommu_domain_free,
+		.attach_dev		= rk_iommu_attach_device,
+		.map_pages		= rk_iommu_map,
+		.unmap_pages		= rk_iommu_unmap,
+		.flush_iotlb_all	= rk_iommu_flush_iotlb_all,
+		.iova_to_phys		= rk_iommu_iova_to_phys,
+		.free			= rk_iommu_domain_free,
 	}
 };
 
-- 
2.49.0



From linux at roeck-us.net  Tue Mar 18 08:22:34 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 18 Mar 2025 08:22:34 -0700
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
Message-ID: <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>

On 3/18/25 01:54, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> ---
>   .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
>   1 file changed, 113 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..e61ef97e63af
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,113 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +
> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>
> +
> +description:
> +  Microchip EMC2301/2/3/5 pwm controller which supports
> +  up to five programmable fan control circuits.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - microchip,emc2305
> +      - items:
> +          - enum:
> +              - microchip,emc2303
> +              - microchip,emc2302
> +              - microchip,emc2301
> +          - const: microchip,emc2305
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  '#pwm-cells':
> +    const: 3
> +    description: |
> +      Number of cells in a PWM specifier.
> +      - cell 0: The PWM frequency
> +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
> +      - cell 2: The PWM output config:
> +           - 0 (Open-Drain)
> +           - 1 (Push-Pull)
> +
> +
> +patternProperties:
> +  '^fan@[0-4]$':
> +    $ref: fan-common.yaml#
> +    unevaluatedProperties: false
> +    properties:
> +      reg:
> +        description:
> +          The fan number used to determine the associated PWM channel.
> +
> +    required:
> +      - reg
> +      - pwms

Is it necessary to make 'pwms' mandatory ? The current code works
just fine with defaults.

Thanks,
Guenter



From khilman at baylibre.com  Tue Mar 18 08:27:46 2025
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 18 Mar 2025 08:27:46 -0700
Subject: [GIT PULL] ARM: OMAP1: defconfig updates for v6.15
In-Reply-To: <7hcyefqzt2.fsf@baylibre.com>
References: <7hcyefqzt2.fsf@baylibre.com>
Message-ID: <7h4izqqryl.fsf@baylibre.com>

Hi Arnd,

Kevin Hilman <khilman at baylibre.com> writes:

> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
>
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
>
> are available in the Git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap.git tags/omap-for-v6.15/soc-signed
>
> for you to fetch changes up to c2a5f8c4f28ffea8c93d10e509c5a6e61172cdca:
>
>   ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP (2025-02-05 16:31:37 -0800)
>
> ----------------------------------------------------------------
> ARM: OMAP1: defconfig updates for v6.15
>
> ----------------------------------------------------------------
> Arnd Bergmann (1):
>       ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP

I see now this one was already included in the arm/fixes branch of the
soc tree, so you can igore this PR.

Kevin


From horms at kernel.org  Tue Mar 18 08:30:43 2025
From: horms at kernel.org (Simon Horman)
Date: Tue, 18 Mar 2025 15:30:43 +0000
Subject: [PATCH v2 0/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <db3bf1cb-3385-4676-8ba4-41fea0212bf2@kwiboo.se>
References: <20250309232622.1498084-1-jonas@kwiboo.se>
 <20250317194309.GL688833@kernel.org>
 <db3bf1cb-3385-4676-8ba4-41fea0212bf2@kwiboo.se>
Message-ID: <20250318153043.GE688833@kernel.org>

On Mon, Mar 17, 2025 at 08:50:34PM +0100, Jonas Karlman wrote:
> Hi Simon,
> 
> On 2025-03-17 20:43, Simon Horman wrote:
> > On Sun, Mar 09, 2025 at 11:26:10PM +0000, Jonas Karlman wrote:
> >> The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
> >> used with the integrated PHY and a second 1000/100/10 MAC to be used
> >> with an external Ethernet PHY.
> >>
> >> This series add initial support for the Ethernet controllers found in
> >> RK3528 and initial support to power up/down the integrated PHY.
> >>
> >> This series depends on v2 of the "net: stmmac: dwmac-rk: Validate GRF
> >> and peripheral GRF during probe" [1] cleanup series.
> >>
> >>
> >> Changes in v2:
> >> - Restrict the minItems: 4 change to rockchip,rk3528-gmac
> >> - Add initial support to power up/down the integrated PHY in RK3528
> >> - Split device tree changes into a separate series
> >>
> >> [1] https://lore.kernel.org/r/20250308213720.2517944-1-jonas at kwiboo.se/
> > 
> > Hi Jonas,
> > 
> > This patchset looks reasonable to me. However it will need
> > to be reposted once it's dependencies ([1]) are present in net-next.
> 
> The dependent series ([1]) has already been merged into net-next [2].

Thanks, and sorry for not noticing that.

> Do I still need to repost this series?

Yes, I think that would be best so there is a CI run over the series
(the CI doesn't understand dependencies).

> [2] https://lore.kernel.org/r/174186063226.1446759.12026198009173732573.git-patchwork-notify at kernel.org/
> 
> > 
> > And on the topic of process:
> > 
> > * As this is a patch-set for net-next it would be best to
> >   target it accordingly:
> > 
> >   Subject: [PATCH net-next] ...
> > 
> > * Please post patches for net/net-next which have dependencies as RFCs.
> > 
> > For more information on Netdev processes please take a look at
> > https://docs.kernel.org/process/maintainer-netdev.html
> > 
> 
> Thanks, I see, netdev seem to use a slight different process than what
> I am familiar with compared to other Linux subsystems and U-Boot :-)
> 
> Regards,
> Jonas
> 


From daniel.baluta at gmail.com  Tue Mar 18 08:33:12 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Tue, 18 Mar 2025 17:33:12 +0200
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com> <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>
Message-ID: <CAEnQRZBmYdLh29ha1FKz8=CbxjFBFFTgDkjrEmwTxW2WcxodfA@mail.gmail.com>

On Tue, Mar 18, 2025 at 5:22?PM Guenter Roeck <linux at roeck-us.net> wrote:
>
> On 3/18/25 01:54, florin.leotescu at oss.nxp.com wrote:
> > From: Florin Leotescu <florin.leotescu at nxp.com>
> >
> > Introduce yaml schema for Microchip emc2305 pwm fan controller.
> >
> > Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> > Reviewed-by: Frank Li <Frank.Li at nxp.com>
> > ---
> >   .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
> >   1 file changed, 113 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > new file mode 100644
> > index 000000000000..e61ef97e63af
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > @@ -0,0 +1,113 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +
> > +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Microchip EMC2305 SMBus compliant PWM fan controller
> > +
> > +maintainers:
> > +  - Michael Shych <michaelsh at nvidia.com>
> > +
> > +description:
> > +  Microchip EMC2301/2/3/5 pwm controller which supports
> > +  up to five programmable fan control circuits.
> > +
> > +properties:
> > +  compatible:
> > +    oneOf:
> > +      - enum:
> > +          - microchip,emc2305
> > +      - items:
> > +          - enum:
> > +              - microchip,emc2303
> > +              - microchip,emc2302
> > +              - microchip,emc2301
> > +          - const: microchip,emc2305
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  '#address-cells':
> > +    const: 1
> > +
> > +  '#size-cells':
> > +    const: 0
> > +
> > +  '#pwm-cells':
> > +    const: 3
> > +    description: |
> > +      Number of cells in a PWM specifier.
> > +      - cell 0: The PWM frequency
> > +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
> > +      - cell 2: The PWM output config:
> > +           - 0 (Open-Drain)
> > +           - 1 (Push-Pull)
> > +
> > +
> > +patternProperties:
> > +  '^fan@[0-4]$':
> > +    $ref: fan-common.yaml#
> > +    unevaluatedProperties: false
> > +    properties:
> > +      reg:
> > +        description:
> > +          The fan number used to determine the associated PWM channel.
> > +
> > +    required:
> > +      - reg
> > +      - pwms
>
> Is it necessary to make 'pwms' mandatory ? The current code works
> just fine with defaults.

The code adding OF support is added just in the next patch, so the
current code isn't event
probed when trying to use dts.

Or am I missing something?

+static const struct of_device_id of_emc2305_match_table[] = {
+       { .compatible = "microchip,emc2305", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_emc2305_match_table);

I have no strong opinion on this we could make pwms optional.


From robh at kernel.org  Tue Mar 18 08:37:17 2025
From: robh at kernel.org (Rob Herring)
Date: Tue, 18 Mar 2025 10:37:17 -0500
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <PA4PR04MB7630DA5DF63C18530B86AB59C5DF2@PA4PR04MB7630.eurprd04.prod.outlook.com>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
 <20250314210652.GA2300828-robh@kernel.org> <PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>
 <20250317-massive-calm-bat-43ff61@krzk-bin> <PA4PR04MB7630DA5DF63C18530B86AB59C5DF2@PA4PR04MB7630.eurprd04.prod.outlook.com>
Message-ID: <CAL_JsqKiWyMMqZwdvbZp8pebqDYrA7MwoD3AGAST6iixXzU0LQ@mail.gmail.com>

On Mon, Mar 17, 2025 at 5:42?AM Maud Spierings | GOcontroll
<maudspierings at gocontroll.com> wrote:
>
> From: Krzysztof Kozlowski <krzk at kernel.org>
> Sent: Monday, March 17, 2025 11:34 AM
>
> >On Sat, Mar 15, 2025 at 07:32:28AM +0000, Maud Spierings | GOcontroll wrote:
> >> >> +required:
> >> >> +  - compatible
> >> >> +  - reg
> >> >> +  - reset-gpios
> >> >> +  - interrupts
> >> >> +  - sync-gpios
> >> >> +  - i2c-bus
> >> >> +  - slot-number
> >> >> +
> >> >> +additionalProperties: false
> >> >> +
> >> >> +examples:
> >> >> +  - |
> >> >> +    #include <dt-bindings/gpio/gpio.h>
> >> >> +    #include <dt-bindings/interrupt-controller/irq.h>
> >> >> +
> >> >> +    spi {
> >> >> +        #address-cells = <1>;
> >> >> +        #size-cells = <0>;
> >> >> +
> >> >> +        connector at 0 {
> >> >
> >> >I find this being a SPI device a bit strange. Is there a defined SPI
> >> >device that every slot is going to have? Or the connector has SPI
> >> >interface and *anything* could be attached on it?
> >>
> >> So a module slot is like a pcie slot, it can be occupied or not, and when
> >
> >But which buses...
>
> I don't think I am fully understanding what you are asking of me. The
> module will always be an spi device, that is the main communication bus.

Okay, that clears up whether it should be a SPI device or not, and I
think it should as SPI is always used. The 2nd question is what does
"gocontroll,moduline-module-slot" mean exactly. Normally, the
compatible implies how you interact with the device (or what is the
programming model). For SPI, that's what do the SPI transactions look
like to begin with. Does the slot spec define that such that every
module is the same? Then when it comes to different module types, are
those discoverable (e.g. PCI has vendor and device ID) or will you
need "compatible" to make that distinction?

Rob


From helgaas at kernel.org  Tue Mar 18 08:38:20 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 18 Mar 2025 10:38:20 -0500
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <20250315201548.858189-7-helgaas@kernel.org>
Message-ID: <20250318153820.GA1001146@bhelgaas>

On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
> 
> dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> is a hard-coded way to get the parent bus address corresponding to a CPU
> physical address.
> 
> Add debug code to compare the address from .cpu_addr_fixup() with the
> address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> redundant and should be removed; if they differ, warn that something is
> wrong with the devicetree.
> 
> If .cpu_addr_fixup() is not implemented, the parent bus address should be
> identical to the CPU physical address because we previously ignored the
> parent bus address from devicetree.  If the devicetree has a different
> parent bus address, warn about it being broken.

> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>  	struct device *dev = pci->dev;
>  	struct device_node *np = dev->of_node;
>  	int index;
> -	u64 reg_addr;
> +	u64 reg_addr, fixup_addr;
> +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
>  
>  	/* Look up reg_name address on parent bus */
>  	index = of_property_match_string(np, "reg-names", reg_name);
> @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>  
>  	of_property_read_reg(np, index, &reg_addr, NULL);
>  
> +	fixup = pci->ops->cpu_addr_fixup;
> +	if (fixup) {
> +		fixup_addr = fixup(pci, cpu_phy_addr);
> +		if (reg_addr == fixup_addr) {
> +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",

On second thought, I think this one should be a dev_info(), not a
dev_warn().  We know the *current* devicetree describes the offset
correctly, but there may be other devicetrees that do not describe it,
and we need to keep .cpu_addr_fixup() for those other devicetrees.

So there's nothing the current user can or should do about this.

> +				 cpu_phy_addr, reg_name, index,
> +				 fixup_addr, fixup);
> +		} else {
> +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> +				 cpu_phy_addr, reg_name,
> +				 index, fixup_addr);
> +			reg_addr = fixup_addr;
> +		}
> +	} else if (!pci->use_parent_dt_ranges) {
> +		if (reg_addr != cpu_phy_addr) {
> +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> +				 cpu_phy_addr, reg_addr);
> +			return 0;
> +		}
> +	}
> +
> +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> +		 reg_name, cpu_phy_addr - reg_addr);
>  	return cpu_phy_addr - reg_addr;
>  }


From johan at kernel.org  Tue Mar 18 08:40:58 2025
From: johan at kernel.org (Johan Hovold)
Date: Tue, 18 Mar 2025 16:40:58 +0100
Subject: [RFC V6 2/2] firmware: arm_scmi: Add quirk to bypass SCP fw bug
In-Reply-To: <Z9l1L1WICMYXSoIu@pluto>
References: <20250226024338.3994701-1-quic_sibis@quicinc.com>
 <20250226024338.3994701-3-quic_sibis@quicinc.com>
 <Z77M5iXHQsdMptWm@hovoldconsulting.com>
 <Z77W-fKBUqAALZKJ@hovoldconsulting.com>
 <759226e1-05aa-4ca2-b2f5-7f1a84dc427f@stanley.mountain>
 <Z77l1NflYXTnRyg0@hovoldconsulting.com>
 <Z8AjhHsVT9ZQTtZX@pluto>
 <Z8WKQJcPTQDIXaKD@hovoldconsulting.com>
 <Z9kr5ABbqO27_BM-@hovoldconsulting.com>
 <Z9l1L1WICMYXSoIu@pluto>
Message-ID: <Z9mUCmQW7L3yx7qt@hovoldconsulting.com>

On Tue, Mar 18, 2025 at 01:29:19PM +0000, Cristian Marussi wrote:
> On Tue, Mar 18, 2025 at 09:16:36AM +0100, Johan Hovold wrote:

> > Have you made any progress on the quirk framework prototyping?
> 
> I have not forgot, tried a few things, but nothing really to post as of
> now...dont wnat to rush either .... I was hoping to push something out at
> the end of this next merge window...
> 
> > Do you need any input from Sibi on the protocol versioning for that?
> 
> No I am fine, I am planning anyway for something generic enough to be
> easy then to plug your own quirks separately...

Sounds good, thanks.

> > We'd really like to enable cpufreq on this platform and ideally in 6.15.
> > I think that should be possible given that we now understand in what
> > ways the firmware is broken and what is needed to handle it even if we
> > still need to decide on how best to implement this.
> 
> v6.15 seems hard/impossible even using the original Sibi patch 
> given the usual upstreaming-timeline of the SCMI stack where everything has
> to be usually reviewed and accepted by rc4/rc5.....so both Sibi initial
> patch and my own babbling were alreaady sort of late.

Yes, sorry, I wasn't referring to Sibi's SCMI patches, but the
devicetree changes needed to enable cpufreq on these platforms (that
will go through the qcom tree).

It may be a little late for that too, but with an understanding of the
problem and a quirk implementation around the corner, we could enable
cpufreq as long as we make sure that Sibi's per-channel FC fix (that
addresses the FC warnings) is not merged without the quirk in place (to
avoid the crashes).

Johan


From will at kernel.org  Tue Mar 18 08:46:22 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 15:46:22 +0000
Subject: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <CAF6AEGvhixYvXghvD+itnSDjr7bO4i3Ls0Y-kXC-ohFN=CS0PQ@mail.gmail.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-1-be14be37f4c3@gmail.com>
 <20250311180553.GB5216@willie-the-truck>
 <CACu1E7GzCiO2b7AFJSDC+pN2VD9VaD2aYz_GGymM3-xAUqd__A@mail.gmail.com>
 <20250312130525.GC6181@willie-the-truck>
 <CAF6AEGvqYithLFAKpfdkw35DEsUZ8rBt25-oWz3r=kaLt+RbQw@mail.gmail.com>
 <20250312164735.GA6561@willie-the-truck>
 <CAF6AEGskyoemQDrTXh=ewf61e-hVzWMjmqe=nX2J-65W5-M6Zw@mail.gmail.com>
 <2d47815d-6bee-4d1f-8b60-854763794bf6@arm.com>
 <CAF6AEGvhixYvXghvD+itnSDjr7bO4i3Ls0Y-kXC-ohFN=CS0PQ@mail.gmail.com>
Message-ID: <20250318154622.GA13829@willie-the-truck>

On Wed, Mar 12, 2025 at 01:20:45PM -0700, Rob Clark wrote:
> On Wed, Mar 12, 2025 at 11:01?AM Robin Murphy <robin.murphy at arm.com> wrote:
> >
> > On 12/03/2025 5:23 pm, Rob Clark wrote:
> > > On Wed, Mar 12, 2025 at 9:47?AM Will Deacon <will at kernel.org> wrote:
> > >>
> > >> On Wed, Mar 12, 2025 at 07:59:52AM -0700, Rob Clark wrote:
> > >>> On Wed, Mar 12, 2025 at 6:05?AM Will Deacon <will at kernel.org> wrote:
> > >>>> On Tue, Mar 11, 2025 at 06:36:38PM -0400, Connor Abbott wrote:
> > >>>>> On Tue, Mar 11, 2025 at 2:06?PM Will Deacon <will at kernel.org> wrote:
> > >>>>>> On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > >>>>>>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > >>>>>>> index ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de 100644
> > >>>>>>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > >>>>>>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > >>>>>>> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
> > >>>>>>>                                      struct arm_smmu_context_fault_info *cfi)
> > >>>>>>>   {
> > >>>>>>>        cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > >>>>>>> +     cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> > >>>>>>>        cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > >>>>>>> -     cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > >>>>>>> +     cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > >>>>>>> +     cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
> > >>>>>>
> > >>>>>> We already have an implementation hook (->get_fault_info()) which the
> > >>>>>> qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> > >>>>>> That thing dumps these registers already so if we're moving that into
> > >>>>>> the core SMMU driver, let's get rid of the hook and move everybody over
> > >>>>>> rather than having it done in both places.
> > >>>>>
> > >>>>> As you probably saw, the next commit moves over
> > >>>>> qcom_adreno_smmu_get_fault_info() to use this. The current back door
> > >>>>> used by drm/msm to access these functions is specific to adreno_smmu
> > >>>>> and there isn't an equivalent interface to allow it to call a generic
> > >>>>> SMMU function so it isn't possible to move it entirely to the core. At
> > >>>>> least not without a bigger refactoring that isn't justified for this
> > >>>>> series that is just trying to fix things.
> > >>>>
> > >>>> Ok :(
> > >>>>
> > >>>>>>>        cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > >>>>>>> +     cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
> > >>>>>>
> > >>>>>> I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> > >>>>>> it for stage-2 domains.
> > >>>>>>
> > >>>>> Does it matter if we read the register though, as long as users are
> > >>>>> aware of this and don't use its value for anything?
> > >>>>
> > >>>> I think the contents are "UNKNOWN", so it could be hugely confusing even
> > >>>> if they just got logged someplace. Why is it difficult to avoid touching
> > >>>> it for stage-2?
> > >>>>
> > >>> Fwiw, we are only ever using stage-1
> > >>
> > >> Sure, but this is in arm-smmu.c which is used by other people and supports
> > >> both stages.
> > >
> > > Sure, but no one else is using this field in the fault-info.  So maybe
> > > the addition of a comment in the struct would be enough if it isn't
> > > going to cause an SError/etc to read it for S2 cb?
> >
> > Any worthwhile comment isn't going to be significantly shorter or
> > clearer than 1 extra line of "if (smmu_domain->stage ==
> > ARM_SMMU_DOMAIN_S1)"...
> 
> Just that smmu_domain isn't passed to
> arm_smmu_read_context_fault_info(), so it would add some extra churn
> on top of that one extra line

Churn is what we do best in this driver :)

Will


From will at kernel.org  Tue Mar 18 08:47:47 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 15:47:47 +0000
Subject: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <394571e1-f86d-472c-91dc-4377d512bfbe@arm.com>
References: <20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3@gmail.com>
 <20250304-msm-gpu-fault-fixes-next-v4-4-be14be37f4c3@gmail.com>
 <20250311181151.GD5216@willie-the-truck>
 <CACu1E7Gg3WpQASADAdediRzFz2wEXAnfD7tg05XkiXZQp=X8fQ@mail.gmail.com>
 <20250312124907.GB6181@willie-the-truck>
 <CACu1E7Hm=DWDC2aFdBRkT8f=8gKXJPpif_uEOA9iFZcyT-uCfQ@mail.gmail.com>
 <394571e1-f86d-472c-91dc-4377d512bfbe@arm.com>
Message-ID: <20250318154746.GB13829@willie-the-truck>

On Tue, Mar 18, 2025 at 01:36:55PM +0000, Robin Murphy wrote:
> On 12/03/2025 1:30 pm, Connor Abbott wrote:
> > On Wed, Mar 12, 2025 at 8:49?AM Will Deacon <will at kernel.org> wrote:
> > > On Tue, Mar 11, 2025 at 04:01:00PM -0400, Connor Abbott wrote:
> > > > On Tue, Mar 11, 2025 at 2:11?PM Will Deacon <will at kernel.org> wrote:
> > > > > On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> > > > > > +     /*
> > > > > > +      * If the device is on and we changed the setting, update the register.
> > > > > > +      */
> > > > > > +     if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> > > > > > +             spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> > > > > > +
> > > > > > +             u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> > > > > > +
> > > > > > +             if (enabled)
> > > > > > +                     reg |= ARM_SMMU_SCTLR_CFCFG;
> > > > > > +             else
> > > > > > +                     reg &= ~ARM_SMMU_SCTLR_CFCFG;
> > > > > > +
> > > > > > +             arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
> > > > > 
> > > > > Are you sure you don't need TLB invalidation for this to take effect? I
> > > > > think some fields in the SCTLR can be cached in the TLB but you'll need
> > > > > to check whether or not that applies to CFCFG.
> > > > > 
> > > > 
> > > > I think it should be fine because CFCFG only controls behavior when
> > > > there's a context fault and there can't be TLB entries for entries
> > > > that cause a context fault: "The architecture permits the caching of
> > > > any translation table entry that has been returned from memory without
> > > > a fault and that does not, as a result of that entry, cause a
> > > > Translation Fault or an Access Flag fault."
> > > 
> > > Ok, but what about other types of fault? For example, a permission fault
> > > or an address size fault?
> > > 
> > I'm not sure, but the pseudocode for context faults mentions
> > resampling CFCFG after a fault happens ("We have a fault and must
> > resample FSR, CFCFG and HUPCF") so I don't think it would be legal to
> > cache it. Also in practice this does seem to work. Does that answer
> > it?
> 
> FWIW I checked with the former MMU-500 design lead, and although he doesn't
> remember the exact details he's pretty confident that they wouldn't have
> cached anything fault-related, so at least from our side I'd consider this
> OK.

Thanks for checking, Robin.

Connor -- please can you stick some of the above in a comment prior
to the CFCFG munging so I don't "rediscover" the problem in the future?

Will


From alb3rt0.m3rciai at gmail.com  Tue Mar 18 08:49:23 2025
From: alb3rt0.m3rciai at gmail.com (Alberto Merciai)
Date: Tue, 18 Mar 2025 16:49:23 +0100
Subject: [PATCH] arm64: dtsi: imx93: add alias id for bbnsm_rtc
In-Reply-To: <116096172.nniJfEyVGO@steina-w>
References: <20250306193014.490091-1-Frank.Li@nxp.com>
 <116096172.nniJfEyVGO@steina-w>
Message-ID: <Z9mWA5ldMDqZcVf5@alb3rt0-ThinkPad-P15-Gen-1>

On Fri, Mar 07, 2025 at 11:19:13AM +0100, Alexander Stein wrote:
> Hi,
> 
> Am Donnerstag, 6. M?rz 2025, 20:30:14 CET schrieb Frank Li:
> > From: Joy Zou <joy.zou at nxp.com>
> > 
> > Add rtc0 alias to set bbnsm_rtc as the default rtc.
> > 
> > Signed-off-by: Joy Zou <joy.zou at nxp.com>
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > ---
> >  arch/arm64/boot/dts/freescale/imx93.dtsi | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
> > index 56766fdb0b1e5..7d9aa15ebf5d0 100644
> > --- a/arch/arm64/boot/dts/freescale/imx93.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
> > @@ -34,6 +34,7 @@ aliases {
> >  		mmc0 = &usdhc1;
> >  		mmc1 = &usdhc2;
> >  		mmc2 = &usdhc3;
> > +		rtc0 = &bbnsm_rtc;
> 
> IMHO this is a board property, not SoC property.
> 
> Best regards
> Alexander
> 
> >  		serial0 = &lpuart1;
> >  		serial1 = &lpuart2;
> >  		serial2 = &lpuart3;
> > 
> 
> 
> -- 
> TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
> Amtsgericht M?nchen, HRB 105018
> Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
> http://www.tq-group.com/
> 
> 
> 
I agree with Alexander, furthermore if we look to others dtsi we don't
create this relationship at soc level even if we have rtc there, is not?

for example:
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi

Regards,
Alberto


From will at kernel.org  Tue Mar 18 08:59:47 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 15:59:47 +0000
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
 <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
Message-ID: <20250318155946.GC13829@willie-the-truck>

On Thu, Mar 13, 2025 at 05:40:59PM +0100, Alessandro Carminati wrote:
> On Thu, Mar 13, 2025 at 1:25?PM Will Deacon <will at kernel.org> wrote:
> >
> > On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
> > > diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
> > > index 28be048db3f6..044c5e24a17d 100644
> > > --- a/arch/arm64/include/asm/bug.h
> > > +++ b/arch/arm64/include/asm/bug.h
> > > @@ -11,8 +11,14 @@
> > >
> > >  #include <asm/asm-bug.h>
> > >
> > > +#ifdef HAVE_BUG_FUNCTION
> > > +# define __BUG_FUNC  __func__
> > > +#else
> > > +# define __BUG_FUNC  NULL
> > > +#endif
> > > +
> > >  #define __BUG_FLAGS(flags)                           \
> > > -     asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
> > > +     asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
> >
> > Why is 'i' the right asm constraint to use here? It seems a bit odd to
> > use that for a pointer.
> 
> I received this code as legacy from a previous version.
> In my review, I considered the case when HAVE_BUG_FUNCTION is defined:
> Here, __BUG_FUNC is defined as __func__, which is the name of the
> current function as a string literal.
> Using the constraint "i" seems appropriate to me in this case.
> 
> However, when HAVE_BUG_FUNCTION is not defined:
> __BUG_FUNC is defined as NULL. Initially, I considered it literal 0,
> but after investigating your concern, I found:
> 
> ```
> $ echo -E "#include <stdio.h>\n#include <stddef.h>\nint main()
> {\nreturn 0;\n}" | aarch64-linux-gnu-gcc -E -dM - | grep NULL
> #define NULL ((void *)0)
> ```
> 
> I realized that NULL is actually a pointer that is not a link time
> symbol, and using the "i" constraint with NULL may result in undefined
> behavior.
> 
> Would the following alternative definition for __BUG_FUNC be more convincing?
> 
> ```
> #ifdef HAVE_BUG_FUNCTION
>     #define __BUG_FUNC __func__
> #else
>     #define __BUG_FUNC (uintptr_t)0
> #endif
> ```
> Let me know your thoughts.

Thanks for the analysis; I hadn't noticed this specific issue, it just
smelled a bit fishy. Anyway, the diff above looks better, thanks.

Will


From cki-project at redhat.com  Tue Mar 18 09:02:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Tue, 18 Mar 2025 16:02:05 -0000
Subject: =?utf-8?b?4p2M?= FAIL: Test report for for-kernelci (6.14.0-rc7,
 upstream-arm-next, b5737d35)
Message-ID: <05723.125031812020701353@us-mta-49.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: FAILED
             Merge: OK
           Compile: FAILED


Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1722678593

One or more kernel builds failed:
    Unrecognized or new issues:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1722678593-aarch64-kernel


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From maudspierings at gocontroll.com  Tue Mar 18 09:03:40 2025
From: maudspierings at gocontroll.com (Maud Spierings | GOcontroll)
Date: Tue, 18 Mar 2025 16:03:40 +0000
Subject: [PATCH v2 03/12] dt-bindings: connector: Add the GOcontroll
 Moduline module slot bindings
In-Reply-To: <CAL_JsqKiWyMMqZwdvbZp8pebqDYrA7MwoD3AGAST6iixXzU0LQ@mail.gmail.com>
References: <20250226-initial_display-v2-0-23fafa130817@gocontroll.com>
 <20250226-initial_display-v2-3-23fafa130817@gocontroll.com>
 <20250314210652.GA2300828-robh@kernel.org>
 <PA4PR04MB7630094413C8E1F3D715EE23C5DD2@PA4PR04MB7630.eurprd04.prod.outlook.com>
 <20250317-massive-calm-bat-43ff61@krzk-bin>
 <PA4PR04MB7630DA5DF63C18530B86AB59C5DF2@PA4PR04MB7630.eurprd04.prod.outlook.com>
 <CAL_JsqKiWyMMqZwdvbZp8pebqDYrA7MwoD3AGAST6iixXzU0LQ@mail.gmail.com>
Message-ID: <PA4PR04MB76301A4A8097CC399109AA98C5DE2@PA4PR04MB7630.eurprd04.prod.outlook.com>

From:?Rob Herring <robh at kernel.org>
Sent:?Tuesday, March 18, 2025 4:37 PM
?
>On Mon, Mar 17, 2025 at 5:42?AM Maud Spierings | GOcontroll
><maudspierings at gocontroll.com> wrote:
>>
>> From: Krzysztof Kozlowski <krzk at kernel.org>
>> Sent: Monday, March 17, 2025 11:34 AM
>>
>> >On Sat, Mar 15, 2025 at 07:32:28AM +0000, Maud Spierings | GOcontroll wrote:
>> >> >> +required:
>> >> >> +? - compatible
>> >> >> +? - reg
>> >> >> +? - reset-gpios
>> >> >> +? - interrupts
>> >> >> +? - sync-gpios
>> >> >> +? - i2c-bus
>> >> >> +? - slot-number
>> >> >> +
>> >> >> +additionalProperties: false
>> >> >> +
>> >> >> +examples:
>> >> >> +? - |
>> >> >> +??? #include <dt-bindings/gpio/gpio.h>
>> >> >> +??? #include <dt-bindings/interrupt-controller/irq.h>
>> >> >> +
>> >> >> +??? spi {
>> >> >> +??????? #address-cells = <1>;
>> >> >> +??????? #size-cells = <0>;
>> >> >> +
>> >> >> +??????? connector at 0 {
>> >> >
>> >> >I find this being a SPI device a bit strange. Is there a defined SPI
>> >> >device that every slot is going to have? Or the connector has SPI
>> >> >interface and *anything* could be attached on it?
>> >>
>> >> So a module slot is like a pcie slot, it can be occupied or not, and when
>> >
>> >But which buses...
>>
>> I don't think I am fully understanding what you are asking of me. The
>> module will always be an spi device, that is the main communication bus.
>
>Okay, that clears up whether it should be a SPI device or not, and I
>think it should as SPI is always used. The 2nd question is what does
>"gocontroll,moduline-module-slot" mean exactly. Normally, the
>compatible implies how you interact with the device (or what is the
>programming model). For SPI, that's what do the SPI transactions look
>like to begin with. Does the slot spec define that such that every
>module is the same? Then when it comes to different module types, are
>those discoverable (e.g. PCI has vendor and device ID) or will you
>need "compatible" to make that distinction?

The slot spec defines the physical interface, what pins etc and the
interaction with the bootloader. From the module bootloader it can
retrieve the module hardware identifier. This is a group of 4 bytes:
1. The standard version (currently and for the foreseable future 20)
2. Category currently these exist:
    10: Input
    20: Output
    30: Communication
    40: Multi function
3. A specific module identifier in this category
4. The module hw version

So a common module is 20-10-1-6, which is the 6 Channel Input module
version 6. It was the first input module type so it is number 1.

After this follow 3 bytes for the firmware revision which is a standard
semantic scheme of major.feature.fix.

The actual communication with the firmware is not standardized. Each
module has its own needs when it comes to that. This will be handled in a
userspace program. Our communication library is open source and can be
adapted to any shape a user wishes.

So there is no seperate compatible needed for each module, this would make
swapping modules dramatically more involved and hurt our ease of use.

I am not quite sure yet if the firmware update part will be moved into the
kernel driver as that is a stable part that can easily be there.

So the "slot" will mostly just interact with the module bootloader and set
the module up for userspace use.

kind regards,
Maud

From will at kernel.org  Tue Mar 18 09:11:11 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 16:11:11 +0000
Subject: [PATCH] arm64: mm: Don't use %pK through printk
In-Reply-To: <20250224150920-87b1bf56-9520-4cd1-ab51-93da2eece162@linutronix.de>
References: <20250217-restricted-pointers-arm64-v1-1-14bb1f516b01@linutronix.de>
 <20250221145513.GA20567@willie-the-truck>
 <20250224150920-87b1bf56-9520-4cd1-ab51-93da2eece162@linutronix.de>
Message-ID: <20250318161109.GA13981@willie-the-truck>

On Mon, Feb 24, 2025 at 03:12:54PM +0100, Thomas Wei?schuh wrote:
> On Fri, Feb 21, 2025 at 02:55:14PM +0000, Will Deacon wrote:
> > On Mon, Feb 17, 2025 at 08:39:06AM +0100, Thomas Wei?schuh wrote:
> > > Restricted pointers ("%pK") are not meant to be used through printk().
> > > It can unintentionally expose security sensitive, raw pointer values.
> > > 
> > > Use regular pointer formatting instead.
> > > 
> > > Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023 at linutronix.de/
> > > Signed-off-by: Thomas Wei?schuh <thomas.weissschuh at linutronix.de>
> > > ---
> > >  arch/arm64/mm/physaddr.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/arch/arm64/mm/physaddr.c b/arch/arm64/mm/physaddr.c
> > > index cde44c13dda1bc0924d2d50369ad87f544a0a802..7d94e09b01b35094e883875a46b979666549095c 100644
> > > --- a/arch/arm64/mm/physaddr.c
> > > +++ b/arch/arm64/mm/physaddr.c
> > > @@ -10,7 +10,7 @@
> > >  phys_addr_t __virt_to_phys(unsigned long x)
> > >  {
> > >  	WARN(!__is_lm_address(__tag_reset(x)),
> > > -	     "virt_to_phys used for non-linear address: %pK (%pS)\n",
> > > +	     "virt_to_phys used for non-linear address: %p (%pS)\n",
> > >  	      (void *)x,
> > >  	      (void *)x);
> > 
> > This is part of a WARN() and knowing the actual address may well be
> > useful in debugging. I suspect it also ends up being dumped as part of
> > the register dump _anyway_.
> 
> That makes sense, especially the value being part of the register dump.
> OTOH in the default kernel configuration (kptr_restrict==0), %pK is an alias to
> %p and also hashing the pointers. And so far nobody seems to have cared.
> 
> If you prefer I can also change it to %px, to specifically show the value.
> My main goal is to remove %pK, as it's prone to misuse.

Probably best to ignore me, then, and keep the existing behaviour with
your change (as your patch is doing).

Thanks,

Will


From will at kernel.org  Tue Mar 18 09:17:46 2025
From: will at kernel.org (Will Deacon)
Date: Tue, 18 Mar 2025 16:17:46 +0000
Subject: [PATCH Resend] perf/arm-cmn: Remove CMN-600 DTC domain special
 case
In-Reply-To: <67985e39f53b56385d79a4f1264cf7f9cacedb58.1742308248.git.robin.murphy@arm.com>
References: <67985e39f53b56385d79a4f1264cf7f9cacedb58.1742308248.git.robin.murphy@arm.com>
Message-ID: <20250318161744.GB13981@willie-the-truck>

Hi Robin,

On Tue, Mar 18, 2025 at 02:32:10PM +0000, Robin Murphy wrote:
> The special case for trying to infer the DTC domain for DTC-adjacent
> nodes on CMN-600 is fragile and buggy - currently resulting in subtly
> messed up DTC counter allocation - and the theoretical benefit it
> offers to a tiny minority of use-cases arguably doesn't outweigh the
> inconsistency it offers to others anyway. Just get rid of it.
> 
> Fixes: ab33c66fd8f1 ("perf/arm-cmn: Enable per-DTC counter allocation")
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/perf/arm-cmn.c | 7 -------
>  1 file changed, 7 deletions(-)

You've got "Resend" in the subject, but I can't seem to find the original
posting :/

Please can you point me at it? I just want to make sure that I'm not
missing patches, as you're unlikely to be the only person affected if
that is the case.

Cheers,

Will


From miquel.raynal at bootlin.com  Tue Mar 18 09:19:24 2025
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Tue, 18 Mar 2025 17:19:24 +0100
Subject: [PATCH RESEND] dt-bindings: mtd: atmel,dataflash: convert txt
 to yaml
In-Reply-To: <20250317-atmel-dataflash-v1-1-1a3247f40299@microchip.com>
References: <20250317-atmel-dataflash-v1-1-1a3247f40299@microchip.com>
Message-ID: <174231476490.980483.3190469118057006004.b4-ty@bootlin.com>

On Mon, 17 Mar 2025 19:01:08 +0530, Nayab Sayed wrote:
> Convert atmel-dataflash.txt into atmel,dataflash.yaml
> 
> 

Applied to mtd/next, thanks!

[1/1] dt-bindings: mtd: atmel,dataflash: convert txt to yaml
      commit: 48a29721c967da1af657279fa696d6c386bdd5ca

Patche(s) should be available on mtd/linux.git and will be
part of the next PR (provided that no robot complains by then).

Kind regards,
Miqu?l



From krzk at kernel.org  Tue Mar 18 09:43:58 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 17:43:58 +0100
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <bc27b658-5c62-4187-acdc-df8dc22161a8@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318-rapid-coot-of-tact-d779ad@krzk-bin>
 <bc27b658-5c62-4187-acdc-df8dc22161a8@amd.com>
Message-ID: <5b32c913-7ae5-44b9-b9c3-84713d2f055c@kernel.org>

On 18/03/2025 17:42, Rajaganesh Rathinasabapathi wrote:
>>
>> Where is the changelog? What happened with this patch between v1 and v3?
>>
>> Best regards,
>> Krzysztof
>>
> Earlier patches did not add dt-binding patch. Added compatibles now in v3.
> It was a review comment on earlier dts submission.


Then your changelog says this is a new patch in the series.

Best regards,
Krzysztof


From rrathina at amd.com  Tue Mar 18 09:44:29 2025
From: rrathina at amd.com (Rajaganesh Rathinasabapathi)
Date: Tue, 18 Mar 2025 22:14:29 +0530
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <20250318-imaginary-peccary-of-argument-ab6b39@krzk-bin>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318-imaginary-peccary-of-argument-ab6b39@krzk-bin>
Message-ID: <cfdbfe7e-5cf4-47a7-af5f-b220cad6f7e4@amd.com>

On 3/18/25 14:15, Krzysztof Kozlowski wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> On Mon, Mar 17, 2025 at 11:12:24PM -0500, Rajaganesh Rathinasabapathi wrote:
>> +/ {
>> +     model = "AMD Onyx BMC";
>> +     compatible = "amd,onyx-bmc", "aspeed,ast2600";
>> +
>> +     aliases {
>> +             serial0 = &uart1;
>> +             serial4 = &uart5;
>> +     };
>> +
>> +     chosen {
>> +             stdout-path = serial4:115200n8;
>> +     };
>> +
>> +     memory at 80000000 {
>> +             device_type = "memory";
>> +             reg = <0x80000000 0x80000000>;
>> +     };
>> +
>> +};
> 
> <form letter>
> This is a friendly reminder during the review process.
> 
> It seems my or other reviewer's previous comments were not fully
> addressed. Maybe the feedback got lost between the quotes, maybe you
> just forgot to apply it. Please go back to the previous discussion and
> either implement all requested changes or keep discussing them.
> 
> Thank you.
> </form letter>
> 
> Best regards,
> Krzysztof
> 

There were two comments. One was to remove bootargs, this is addressed in v3.
Another comment was to add compatibles for amd,onyx-bmc, it part of earlier commit (patch v3 1/2).

Thanks,
Raja


From james.clark at linaro.org  Tue Mar 18 09:21:54 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:54 +0000
Subject: [PATCH v2 0/8] coresight: Clear self hosted claim tag on probe
Message-ID: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>

I've gotten stuck a few times with unusable Coresight after a warm boot
due to lingering claim tags, especially when testing the Coresight
panic patchsets.

This change does some tidy ups, adds some debug messages and clears the
self hosted claim tag on probe. The last two commits are unrelated
tidyups but they touch some of the same functions so to avoid extra
conflicts I'm including them here.

This gets as far as fixing the claim tag issue, but there is some other
state not being cleared on probe that results in the following error.
This can be fixed up as a later change:

  coresight tmc_etf0: timeout while waiting for TMC to be Ready
  coresight tmc_etf0: Failed to enable : TMC is not ready

Changes in v2:
 * Revert most of the interface changes, just call
   coresight_clear_self_claim_tag() directly. This is possible because
   we're not doing the read first, so it has fewer knock on effects.
 * Split out the change to add struct cs_access to etm3x
 * Add another warning for racing with external debugger

--
2.34.1

---
James Clark (8):
      coresight: Rename coresight_{set,clear}_claim_tags()
      coresight: Convert tag clear function to take a struct cs_access
      coresight: Only check bottom two claim bits
      coresight: Add claim tag warnings and debug messages
      coresight: etm3x: Convert raw base pointer to struct coresight access
      coresight: Clear self hosted claim tag on probe
      coresight: Remove inlines from static function definitions
      coresight: Remove extern from function declarations

 drivers/hwtracing/coresight/coresight-catu.c       | 12 +--
 drivers/hwtracing/coresight/coresight-core.c       | 85 ++++++++++++++--------
 drivers/hwtracing/coresight/coresight-cti-core.c   |  2 +
 drivers/hwtracing/coresight/coresight-etb10.c      |  4 +-
 drivers/hwtracing/coresight/coresight-etm.h        |  6 +-
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 28 +++----
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++-
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 +-
 drivers/hwtracing/coresight/coresight-funnel.c     |  1 +
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++----
 drivers/hwtracing/coresight/coresight-priv.h       | 20 ++---
 drivers/hwtracing/coresight/coresight-replicator.c |  3 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 +-
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  9 ++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++--
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 ++---
 include/linux/coresight.h                          | 40 +++++-----
 19 files changed, 166 insertions(+), 134 deletions(-)
---
base-commit: 5442d22da7dbff3ba8c6720fc6f23ea4934d402d
change-id: 20250317-james-coresight-claim-tags-ae1461f1f5e0

Best regards,
-- 
James Clark <james.clark at linaro.org>



From james.clark at linaro.org  Tue Mar 18 09:21:55 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:55 +0000
Subject: [PATCH v2 1/8] coresight: Rename
 coresight_{set,clear}_claim_tags()
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-1-e9c8a9cde84e@linaro.org>

These look like they set the whole tags register as one value, but they
only set and clear the self hosted bit using a SET/CLR bits mechanism.
Rename the functions to reflect this better.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index fb43ef6a3b1f..3f1c996d668a 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -144,14 +144,14 @@ static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
 	return coresight_read_claim_tags(csdev) != 0;
 }
 
-static inline void coresight_set_claim_tags(struct coresight_device *csdev)
+static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
 	isb();
 }
 
-static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
+static inline void coresight_clear_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMCLR);
@@ -176,11 +176,11 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
 	if (coresight_is_claimed_any(csdev))
 		return -EBUSY;
 
-	coresight_set_claim_tags(csdev);
+	coresight_set_self_claim_tag(csdev);
 	if (coresight_is_claimed_self_hosted(csdev))
 		return 0;
-	/* There was a race setting the tags, clean up and fail */
-	coresight_clear_claim_tags(csdev);
+	/* There was a race setting the tag, clean up and fail */
+	coresight_clear_self_claim_tag(csdev);
 	return -EBUSY;
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
@@ -201,7 +201,7 @@ int coresight_claim_device(struct coresight_device *csdev)
 EXPORT_SYMBOL_GPL(coresight_claim_device);
 
 /*
- * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
+ * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
  * Called with CS_UNLOCKed for the component.
  */
 void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
@@ -211,7 +211,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		return;
 
 	if (coresight_is_claimed_self_hosted(csdev))
-		coresight_clear_claim_tags(csdev);
+		coresight_clear_self_claim_tag(csdev);
 	else
 		/*
 		 * The external agent may have not honoured our claim

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:21:56 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:56 +0000
Subject: [PATCH v2 2/8] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>

The self hosted claim tag will be reset on device probe in a later
commit. We'll want to do this before coresight_register() is called so
won't have a coresight_device and have to use cs_access instead.

Also make them public and create locked and unlocked versions for
later use.

Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 17 +++++++++++++----
 include/linux/coresight.h                    |  3 ++-
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 3f1c996d668a..9ff601e2415a 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -151,12 +151,21 @@ static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
 	isb();
 }
 
-static inline void coresight_clear_self_claim_tag(struct coresight_device *csdev)
+void coresight_clear_self_claim_tag(struct csdev_access *csa)
 {
-	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
+	CS_UNLOCK(csa->base);
+	coresight_clear_self_claim_tag_unlocked(csa);
+	CS_LOCK(csa->base);
+}
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
+
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
+{
+	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMCLR);
 	isb();
 }
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
 
 /*
  * coresight_claim_device_unlocked : Claim the device for self-hosted usage
@@ -180,7 +189,7 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
 	if (coresight_is_claimed_self_hosted(csdev))
 		return 0;
 	/* There was a race setting the tag, clean up and fail */
-	coresight_clear_self_claim_tag(csdev);
+	coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	return -EBUSY;
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
@@ -211,7 +220,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		return;
 
 	if (coresight_is_claimed_self_hosted(csdev))
-		coresight_clear_self_claim_tag(csdev);
+		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
 		 * The external agent may have not honoured our claim
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d79a242b271d..00134a80d358 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
 
 extern int coresight_claim_device(struct coresight_device *csdev);
 extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
-
+void coresight_clear_self_claim_tag(struct csdev_access *csa);
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
 extern void coresight_disclaim_device(struct coresight_device *csdev);
 extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
 extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:21:57 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:57 +0000
Subject: [PATCH v2 3/8] coresight: Only check bottom two claim bits
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-3-e9c8a9cde84e@linaro.org>

The use of the whole register and == could break the claim mechanism if
any of the other bits are used in the future. The referenced doc "PSCI -
ARM DEN 0022D" also says to only read and clear the bottom two bits.

Use FIELD_GET() to extract only the relevant part.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 3 ++-
 drivers/hwtracing/coresight/coresight-priv.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 9ff601e2415a..e39043a9551f 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -131,7 +131,8 @@ coresight_find_out_connection(struct coresight_device *csdev,
 
 static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
 {
-	return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
+	return FIELD_GET(CORESIGHT_CLAIM_MASK,
+			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
 static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 82644aff8d2b..38bb4e8b50ef 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -35,6 +35,7 @@ extern const struct device_type coresight_dev_type[];
  * Coresight device CLAIM protocol.
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
+#define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
 #define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
 
 #define TIMEOUT_US		100

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:21:58 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:58 +0000
Subject: [PATCH v2 4/8] coresight: Add claim tag warnings and debug
 messages
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-4-e9c8a9cde84e@linaro.org>

Add a dev_dbg() message so that external debugger conflicts are more
visible. There are multiple reasons for -EBUSY so a message for this
particular one could be helpful. Add errors for and enumerate all the
other cases that are impossible.

Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 51 +++++++++++++++++-----------
 drivers/hwtracing/coresight/coresight-priv.h |  5 ++-
 2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index e39043a9551f..5f08845faf0d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -135,16 +135,6 @@ static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
-}
-
-static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags(csdev) != 0;
-}
-
 static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
@@ -180,18 +170,41 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
  */
 int coresight_claim_device_unlocked(struct coresight_device *csdev)
 {
+	int tag;
+	struct csdev_access *csa;
+
 	if (WARN_ON(!csdev))
 		return -EINVAL;
 
-	if (coresight_is_claimed_any(csdev))
+	csa = &csdev->access;
+	tag = coresight_read_claim_tags(csdev);
+
+	switch (tag) {
+	case CORESIGHT_CLAIM_FREE:
+		coresight_set_self_claim_tag(csdev);
+		if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
+			return 0;
+
+		/* There was a race setting the tag, clean up and fail */
+		coresight_clear_self_claim_tag_unlocked(csa);
+		dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
 		return -EBUSY;
 
-	coresight_set_self_claim_tag(csdev);
-	if (coresight_is_claimed_self_hosted(csdev))
-		return 0;
-	/* There was a race setting the tag, clean up and fail */
-	coresight_clear_self_claim_tag_unlocked(&csdev->access);
-	return -EBUSY;
+	case CORESIGHT_CLAIM_EXTERNAL:
+		/* External debug is an expected state, so log and report BUSY */
+		dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
+		return -EBUSY;
+
+	default:
+	case CORESIGHT_CLAIM_SELF_HOSTED:
+	case CORESIGHT_CLAIM_INVALID:
+		/*
+		 * Warn here because we clear a lingering self hosted tag
+		 * on probe, so other tag combinations are impossible.
+		 */
+		dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
+		return -EBUSY;
+	}
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
 
@@ -220,7 +233,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 	if (WARN_ON(!csdev))
 		return;
 
-	if (coresight_is_claimed_self_hosted(csdev))
+	if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
 		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
@@ -228,7 +241,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		 * and has manipulated it. Or something else has seriously
 		 * gone wrong in our driver.
 		 */
-		WARN_ON_ONCE(1);
+		dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
 }
 EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
 
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 38bb4e8b50ef..6e8cf55aee0a 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -36,7 +36,10 @@ extern const struct device_type coresight_dev_type[];
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
 #define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
-#define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
+#define CORESIGHT_CLAIM_FREE		0
+#define CORESIGHT_CLAIM_EXTERNAL	1
+#define CORESIGHT_CLAIM_SELF_HOSTED	2
+#define CORESIGHT_CLAIM_INVALID		3
 
 #define TIMEOUT_US		100
 #define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:21:59 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:21:59 +0000
Subject: [PATCH v2 5/8] coresight: etm3x: Convert raw base pointer to
 struct coresight access
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-5-e9c8a9cde84e@linaro.org>

This is so that etm3x can use the new claim tag functions which take a
csa pointer in a later commit.

Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm.h        |  6 ++---
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 27 +++++++++++-----------
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +++----
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index 171f1384f7c0..1d753cca2943 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -229,7 +229,7 @@ struct etm_config {
  * @config:	structure holding configuration parameters.
  */
 struct etm_drvdata {
-	void __iomem			*base;
+	struct csdev_access		csa;
 	struct clk			*atclk;
 	struct coresight_device		*csdev;
 	spinlock_t			spinlock;
@@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		writel_relaxed(val, drvdata->base + off);
+		writel_relaxed(val, drvdata->csa.base + off);
 	}
 }
 
@@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		val = readl_relaxed(drvdata->base + off);
+		val = readl_relaxed(drvdata->csa.base + off);
 	}
 
 	return val;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index 8927bfaf3af2..cfd463ac715c 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
 {
 	u32 etmpdcr;
 
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr |= ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 	/* Ensure pwrup completes before subsequent cp14 accesses */
 	mb();
 	isb();
@@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
 	/* Ensure pending cp14 accesses complete before clearing pwrup */
 	mb();
 	isb();
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr &= ~ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 }
 
 /**
@@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	rc = coresight_claim_device_unlocked(csdev);
 	if (rc)
@@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	etm_clr_prog(drvdata);
 
 done:
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
 		drvdata->cpu, rc);
@@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	etm_set_prog(drvdata);
 
 	/* Read back sequencer and counters for post trace analysis */
@@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev,
 		"cpu: %d disable smp call done\n", drvdata->cpu);
@@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* Setting the prog bit disables tracing immediately */
 	etm_set_prog(drvdata);
@@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	/*
 	 * perf will release trace ids when _free_aux()
@@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
 	/* Make sure all registers are accessible */
 	etm_os_unlock(drvdata);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* First dummy read */
 	(void)etm_readl(drvdata, ETMPDSR);
@@ -766,7 +766,7 @@ static void etm_init_arch_data(void *info)
 
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 }
 
 static int __init etm_hp_setup(void)
@@ -827,8 +827,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	drvdata->base = base;
-	desc.access = CSDEV_ACCESS_IOMEM(base);
+	desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
 
 	spin_lock_init(&drvdata->spinlock);
 
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
index b9006451f515..762109307b86 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
@@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
 
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	val = etm_readl(drvdata, ETMSR);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);
 
@@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:22:00 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:22:00 +0000
Subject: [PATCH v2 6/8] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-6-e9c8a9cde84e@linaro.org>

This can be left behind from a crashed kernel after a kexec so clear it
when probing each device. Clearing the self hosted bit even when claimed
externally is harmless, so do it unconditionally.

Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 1 +
 drivers/hwtracing/coresight/coresight-cti-core.c   | 2 ++
 drivers/hwtracing/coresight/coresight-etb10.c      | 2 ++
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 1 +
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 ++
 drivers/hwtracing/coresight/coresight-funnel.c     | 1 +
 drivers/hwtracing/coresight/coresight-replicator.c | 1 +
 drivers/hwtracing/coresight/coresight-tmc-core.c   | 1 +
 8 files changed, 11 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index fa170c966bc3..deaacfd875af 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
 	catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
 	catu_desc.ops = &catu_ops;
 
+	coresight_clear_self_claim_tag(&catu_desc.access);
 	drvdata->csdev = coresight_register(&catu_desc);
 	if (IS_ERR(drvdata->csdev))
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 80f6265e3740..8fb30dd73fd2 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	cti_desc.ops = &cti_ops;
 	cti_desc.groups = drvdata->ctidev.con_groups;
 	cti_desc.dev = dev;
+
+	coresight_clear_self_claim_tag(&cti_desc.access);
 	drvdata->csdev = coresight_register(&cti_desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 7948597d483d..2bfcb669aa84 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.pdata = pdata;
 	desc.dev = dev;
 	desc.groups = coresight_etb_groups;
+
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev))
 		return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index cfd463ac715c..1c6204e14422 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -764,6 +764,7 @@ static void etm_init_arch_data(void *info)
 	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
+	coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
 	CS_LOCK(drvdata->csa.base);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e5972f16abff..52c9aa56e8b9 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1372,6 +1372,8 @@ static void etm4_init_arch_data(void *info)
 	drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
 	/* NUMCNTR, bits[30:28] number of counters available for tracing */
 	drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
+
+	coresight_clear_self_claim_tag_unlocked(csa);
 	etm4_cs_lock(drvdata, csa);
 	cpu_detect_trace_filtering(drvdata);
 }
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 0541712b2bcb..7249cc356ccb 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
 		drvdata->base = base;
 		desc.groups = coresight_funnel_groups;
 		desc.access = CSDEV_ACCESS_IOMEM(base);
+		coresight_clear_self_claim_tag(&desc.access);
 	}
 
 	dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index ee7ee79f6cf7..b2acd4535c74 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -284,6 +284,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
 	desc.pdata = dev->platform_data;
 	desc.dev = dev;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index a7814e8e657b..a09579eff3fd 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -869,6 +869,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
 	dev->platform_data = pdata;
 	desc.pdata = pdata;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:22:01 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:22:01 +0000
Subject: [PATCH v2 7/8] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-7-e9c8a9cde84e@linaro.org>

These are all static and in one compilation unit so the inline has no
effect on the binary. Except if FTRACE is enabled, then some functions
which were already not inlined now get the nops added which allows them
to be traced.

Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 11 +++++----
 drivers/hwtracing/coresight/coresight-core.c       | 14 ++++++------
 drivers/hwtracing/coresight/coresight-etb10.c      |  2 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c |  8 +++----
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 ++--
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++++++++++-----------
 drivers/hwtracing/coresight/coresight-replicator.c |  2 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 ++---
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  8 +++----
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++++++-------
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 +++++++--------
 12 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index deaacfd875af..6f411db24a54 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -113,9 +113,8 @@ typedef u64 cate_t;
  * containing the data page pointer for @offset. If @daddrp is not NULL,
  * @daddrp points the DMA address of the beginning of the table.
  */
-static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
-				     unsigned long offset,
-				     dma_addr_t *daddrp)
+static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
+			      dma_addr_t *daddrp)
 {
 	unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
 	unsigned int table_nr, pg_idx, pg_offset;
@@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
 }
 
 #else
-static inline void catu_dump_table(struct tmc_sg_table *catu_table)
+static void catu_dump_table(struct tmc_sg_table *catu_table)
 {
 }
 #endif
 
-static inline cate_t catu_make_entry(dma_addr_t addr)
+static cate_t catu_make_entry(dma_addr_t addr)
 {
 	return addr ? CATU_VALID_ENTRY(addr) : 0;
 }
@@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
 };
 
 
-static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
+static int catu_wait_for_ready(struct catu_drvdata *drvdata)
 {
 	struct csdev_access *csa = &drvdata->csdev->access;
 
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 5f08845faf0d..69388e2dd386 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -129,13 +129,13 @@ coresight_find_out_connection(struct coresight_device *csdev,
 	return ERR_PTR(-ENODEV);
 }
 
-static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
+static u32 coresight_read_claim_tags(struct coresight_device *csdev)
 {
 	return FIELD_GET(CORESIGHT_CLAIM_MASK,
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
+static void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
@@ -602,7 +602,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
  * Return true in successful case and power up the device.
  * Return false when failed to get reference of module.
  */
-static inline bool coresight_get_ref(struct coresight_device *csdev)
+static bool coresight_get_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -621,7 +621,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
  *
  * @csdev: The coresight device to decrement a reference from.
  */
-static inline void coresight_put_ref(struct coresight_device *csdev)
+static void coresight_put_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -844,7 +844,7 @@ void coresight_release_path(struct coresight_path *path)
 }
 
 /* return true if the device is a suitable type for a default sink */
-static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
+static bool coresight_is_def_sink_type(struct coresight_device *csdev)
 {
 	/* sink & correct subtype */
 	if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
@@ -1408,8 +1408,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
  *
  * Returns the index of the entry, when found. Otherwise, -ENOENT.
  */
-static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
-					      struct fwnode_handle *fwnode)
+static int coresight_search_device_idx(struct coresight_dev_list *dict,
+				       struct fwnode_handle *fwnode)
 {
 	int i;
 
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 2bfcb669aa84..d5efb085b30d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -95,7 +95,7 @@ struct etb_drvdata {
 static int etb_set_buffer(struct coresight_device *csdev,
 			  struct perf_output_handle *handle);
 
-static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
+static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
 {
 	return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
 }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 52c9aa56e8b9..2ca35ef35f77 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
  *		TRCIDR4.NUMPC > 0b0000 .
  *		TRCSSCSR<n>.PC == 0b1
  */
-static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
+static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
 {
 	return (n < drvdata->nr_ss_cmp) &&
 	       drvdata->nr_pe &&
@@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
 	isb();
 }
 
-static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
+static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
 				      struct csdev_access *csa)
 {
 	WARN_ON(drvdata->cpu != smp_processor_id());
@@ -1070,7 +1070,7 @@ static const struct coresight_ops etm4_cs_ops = {
 	.source_ops	= &etm4_source_ops,
 };
 
-static inline bool cpu_supports_sysreg_trace(void)
+static bool cpu_supports_sysreg_trace(void)
 {
 	u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
 
@@ -1378,7 +1378,7 @@ static void etm4_init_arch_data(void *info)
 	cpu_detect_trace_filtering(drvdata);
 }
 
-static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
+static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
 {
 	return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
 }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index fdd0956fecb3..49d5fb87a74b 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
 	return reg.data;
 }
 
-static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
+static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
 {
 	struct dev_ext_attribute *eattr;
 
@@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
 	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
 }
 
-static inline bool
+static bool
 etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
 {
 	switch (offset) {
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index 8192ba3279f0..0db64c5f4995 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
 EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
 
 #ifdef CONFIG_OF
-static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
+static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
 {
 	return of_property_read_bool(ep, "slave-mode");
 }
@@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
 	return parent;
 }
 
-static inline struct device_node *
+static struct device_node *
 of_coresight_get_output_ports_node(const struct device_node *node)
 {
 	return of_get_child_by_name(node, "out-ports");
@@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
 	return 0;
 }
 #else
-static inline int
+static int
 of_get_coresight_platform_data(struct device *dev,
 			       struct coresight_platform_data *pdata)
 {
 	return -ENOENT;
 }
 
-static inline int of_coresight_get_cpu(struct device *dev)
+static int of_coresight_get_cpu(struct device *dev)
 {
 	return -ENODEV;
 }
@@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
 #define ACPI_CORESIGHT_LINK_SLAVE	0
 #define ACPI_CORESIGHT_LINK_MASTER	1
 
-static inline bool is_acpi_guid(const union acpi_object *obj)
+static bool is_acpi_guid(const union acpi_object *obj)
 {
 	return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
 }
@@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
  * acpi_guid_matches	- Checks if the given object is a GUID object and
  * that it matches the supplied the GUID.
  */
-static inline bool acpi_guid_matches(const union acpi_object *obj,
+static bool acpi_guid_matches(const union acpi_object *obj,
 				   const guid_t *guid)
 {
 	return is_acpi_guid(obj) &&
 	       guid_equal((guid_t *)obj->buffer.pointer, guid);
 }
 
-static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
+static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
 {
 	return acpi_guid_matches(obj, &acpi_graph_uuid);
 }
 
-static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
+static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
 {
 	return acpi_guid_matches(obj, &coresight_graph_uuid);
 }
 
-static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
+static bool is_acpi_coresight_graph(const union acpi_object *obj)
 {
 	const union acpi_object *graphid, *guid, *links;
 
@@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
  *	}, // End of ACPI Graph Property
  *  })
  */
-static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
+static bool acpi_validate_dsd_graph(const union acpi_object *graph)
 {
 	int i, n;
 	const union acpi_object *rev, *nr_graphs;
@@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
 	return NULL;
 }
 
-static inline bool
+static bool
 acpi_validate_coresight_graph(const union acpi_object *cs_graph)
 {
 	int nlinks;
@@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
 
 #else
 
-static inline int
+static int
 acpi_get_coresight_platform_data(struct device *dev,
 				 struct coresight_platform_data *pdata)
 {
 	return -ENOENT;
 }
 
-static inline int acpi_coresight_get_cpu(struct device *dev)
+static int acpi_coresight_get_cpu(struct device *dev)
 {
 	return -ENODEV;
 }
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index b2acd4535c74..52beb2fc4094 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
 /*
  * replicator_reset : Reset the replicator configuration to sane values.
  */
-static inline void replicator_reset(struct replicator_drvdata *drvdata)
+static void replicator_reset(struct replicator_drvdata *drvdata)
 {
 	if (drvdata->base)
 		dynamic_replicator_reset(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 26f9339f38b9..8c0741583a2c 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -301,7 +301,7 @@ static const struct coresight_ops stm_cs_ops = {
 	.source_ops	= &stm_source_ops,
 };
 
-static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
+static bool stm_addr_unaligned(const void *addr, u8 write_bytes)
 {
 	return ((unsigned long)addr & (write_bytes - 1));
 }
@@ -685,7 +685,7 @@ static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)
 	return of_address_to_resource(np, index, res);
 }
 #else
-static inline int of_stm_get_stimulus_area(struct device *dev,
+static int of_stm_get_stimulus_area(struct device *dev,
 					   struct resource *res)
 {
 	return -ENOENT;
@@ -729,7 +729,7 @@ static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)
 	return rc;
 }
 #else
-static inline int acpi_stm_get_stimulus_area(struct device *dev,
+static int acpi_stm_get_stimulus_area(struct device *dev,
 					     struct resource *res)
 {
 	return -ENOENT;
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
index 213b4159b062..2b40e556be87 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -10,7 +10,7 @@
 #include "coresight-syscfg-configfs.h"
 
 /* create a default ci_type. */
-static inline struct config_item_type *cscfg_create_ci_type(void)
+static struct config_item_type *cscfg_create_ci_type(void)
 {
 	struct config_item_type *ci_type;
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index a09579eff3fd..6f6d51c13454 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -287,8 +287,8 @@ static int tmc_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
-					  loff_t pos, size_t len, char **bufpp)
+static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len,
+				   char **bufpp)
 {
 	switch (drvdata->config_type) {
 	case TMC_CONFIG_TYPE_ETB:
@@ -591,7 +591,7 @@ static const struct attribute_group *coresight_etr_groups[] = {
 	NULL,
 };
 
-static inline bool tmc_etr_can_use_sg(struct device *dev)
+static bool tmc_etr_can_use_sg(struct device *dev)
 {
 	int ret;
 	u8 val_u8;
@@ -621,7 +621,7 @@ static inline bool tmc_etr_can_use_sg(struct device *dev)
 	return false;
 }
 
-static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
+static bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
 {
 	u32 auth = readl_relaxed(drvdata->base + TMC_AUTHSTATUS);
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 76a8cb29b68a..3f31ad2ae65d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -125,7 +125,7 @@ struct etr_sg_table {
  * If we spill over to a new page for mapping 1 entry, we could as
  * well replace the link entry of the previous page with the last entry.
  */
-static inline unsigned long __attribute_const__
+static unsigned long __attribute_const__
 tmc_etr_sg_table_entries(int nr_pages)
 {
 	unsigned long nr_sgpages = nr_pages * ETR_SG_PAGES_PER_SYSPAGE;
@@ -239,13 +239,13 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
 	return -ENOMEM;
 }
 
-static inline long
+static long
 tmc_sg_get_data_page_offset(struct tmc_sg_table *sg_table, dma_addr_t addr)
 {
 	return tmc_pages_get_offset(&sg_table->data_pages, addr);
 }
 
-static inline void tmc_free_table_pages(struct tmc_sg_table *sg_table)
+static void tmc_free_table_pages(struct tmc_sg_table *sg_table)
 {
 	if (sg_table->table_vaddr)
 		vunmap(sg_table->table_vaddr);
@@ -481,7 +481,7 @@ static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table)
 	dev_dbg(sg_table->dev, "******* End of Table *****\n");
 }
 #else
-static inline void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
+static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
 #endif
 
 /*
@@ -886,10 +886,8 @@ void tmc_etr_remove_catu_ops(void)
 }
 EXPORT_SYMBOL_GPL(tmc_etr_remove_catu_ops);
 
-static inline int tmc_etr_mode_alloc_buf(int mode,
-					 struct tmc_drvdata *drvdata,
-					 struct etr_buf *etr_buf, int node,
-					 void **pages)
+static int tmc_etr_mode_alloc_buf(int mode, struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
+				  int node, void **pages)
 {
 	int rc = -EINVAL;
 
@@ -1009,7 +1007,7 @@ static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
 	return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
 }
 
-static inline s64
+static s64
 tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
 {
 	ssize_t len;
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index fff67aac8418..8267dd1a2130 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -160,22 +160,22 @@ static void trbe_check_errata(struct trbe_cpudata *cpudata)
 	}
 }
 
-static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
+static bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
 {
 	return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata);
 }
 
-static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
+static bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE);
 }
 
-static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
+static bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE);
 }
 
-static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
+static bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
 {
 	/*
 	 * Errata affected TRBE implementation will need TSB CSYNC and
@@ -185,7 +185,7 @@ static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
 	return trbe_has_erratum(cpudata, TRBE_NEEDS_DRAIN_AFTER_DISABLE);
 }
 
-static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
+static bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
 {
 	/*
 	 * Errata affected TRBE implementation will need an additional
@@ -196,7 +196,7 @@ static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudat
 	return trbe_has_erratum(cpudata, TRBE_NEEDS_CTXT_SYNC_AFTER_ENABLE);
 }
 
-static inline bool trbe_is_broken(struct trbe_cpudata *cpudata)
+static bool trbe_is_broken(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_IS_BROKEN);
 }
@@ -208,13 +208,13 @@ static int trbe_alloc_node(struct perf_event *event)
 	return cpu_to_node(event->cpu);
 }
 
-static inline void trbe_drain_buffer(void)
+static void trbe_drain_buffer(void)
 {
 	tsb_csync();
 	dsb(nsh);
 }
 
-static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
+static void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
 {
 	/*
 	 * Enable the TRBE without clearing LIMITPTR which
@@ -231,7 +231,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
 		isb();
 }
 
-static inline void set_trbe_disabled(struct trbe_cpudata *cpudata)
+static void set_trbe_disabled(struct trbe_cpudata *cpudata)
 {
 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
 

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 18 09:22:02 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 18 Mar 2025 16:22:02 +0000
Subject: [PATCH v2 8/8] coresight: Remove extern from function declarations
In-Reply-To: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
Message-ID: <20250318-james-coresight-claim-tags-v2-8-e9c8a9cde84e@linaro.org>

Function declarations are extern by default so remove the extra noise
and inconsistency.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-priv.h | 14 +++++------
 include/linux/coresight.h                    | 35 ++++++++++++++--------------
 2 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 6e8cf55aee0a..ce91e0fbb497 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -60,10 +60,8 @@ struct cs_off_attribute {
 	u32 off;
 };
 
-extern ssize_t coresight_simple_show32(struct device *_dev,
-				     struct device_attribute *attr, char *buf);
-extern ssize_t coresight_simple_show_pair(struct device *_dev,
-				     struct device_attribute *attr, char *buf);
+ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
+ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf);
 
 #define coresight_simple_reg32(name, offset)				\
 	(&((struct cs_off_attribute[]) {				\
@@ -160,8 +158,8 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
 				   enum cs_mode mode);
 
 #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
-extern int etm_readl_cp14(u32 off, unsigned int *val);
-extern int etm_writel_cp14(u32 off, u32 val);
+int etm_readl_cp14(u32 off, unsigned int *val);
+int etm_writel_cp14(u32 off, u32 val);
 #else
 static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
 static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
@@ -172,8 +170,8 @@ struct cti_assoc_op {
 	void (*remove)(struct coresight_device *csdev);
 };
 
-extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
-extern void coresight_remove_cti_ops(void);
+void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
+void coresight_remove_cti_ops(void);
 
 /*
  * Macros and inline functions to handle CoreSight UCI data and driver
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 00134a80d358..8cb07c132b01 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -671,28 +671,27 @@ static inline void coresight_set_mode(struct coresight_device *csdev,
 	local_set(&csdev->mode, new_mode);
 }
 
-extern struct coresight_device *
-coresight_register(struct coresight_desc *desc);
-extern void coresight_unregister(struct coresight_device *csdev);
-extern int coresight_enable_sysfs(struct coresight_device *csdev);
-extern void coresight_disable_sysfs(struct coresight_device *csdev);
-extern int coresight_timeout(struct csdev_access *csa, u32 offset,
-			     int position, int value);
+struct coresight_device *coresight_register(struct coresight_desc *desc);
+void coresight_unregister(struct coresight_device *csdev);
+int coresight_enable_sysfs(struct coresight_device *csdev);
+void coresight_disable_sysfs(struct coresight_device *csdev);
+int coresight_timeout(struct csdev_access *csa, u32 offset, int position, int value);
 typedef void (*coresight_timeout_cb_t) (struct csdev_access *, u32, int, int);
-extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
-					int position, int value,
-					coresight_timeout_cb_t cb);
+int coresight_timeout_action(struct csdev_access *csa, u32 offset, int position, int value,
+			     coresight_timeout_cb_t cb);
+int coresight_claim_device(struct coresight_device *csdev);
+int coresight_claim_device_unlocked(struct coresight_device *csdev);
 
-extern int coresight_claim_device(struct coresight_device *csdev);
-extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
+int coresight_claim_device(struct coresight_device *csdev);
+int coresight_claim_device_unlocked(struct coresight_device *csdev);
 void coresight_clear_self_claim_tag(struct csdev_access *csa);
 void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
-extern void coresight_disclaim_device(struct coresight_device *csdev);
-extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
-extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
+void coresight_disclaim_device(struct coresight_device *csdev);
+void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
+char *coresight_alloc_device_name(struct coresight_dev_list *devs,
 					 struct device *dev);
 
-extern bool coresight_loses_context_with_cpu(struct device *dev);
+bool coresight_loses_context_with_cpu(struct device *dev);
 
 u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset);
 u32 coresight_read32(struct coresight_device *csdev, u32 offset);
@@ -705,8 +704,8 @@ void coresight_relaxed_write64(struct coresight_device *csdev,
 			       u64 val, u32 offset);
 void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset);
 
-extern int coresight_get_cpu(struct device *dev);
-extern int coresight_get_static_trace_id(struct device *dev, u32 *id);
+int coresight_get_cpu(struct device *dev);
+int coresight_get_static_trace_id(struct device *dev, u32 *id);
 
 struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
 struct coresight_connection *

-- 
2.34.1



From sebastianene at google.com  Tue Mar 18 09:25:07 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 18 Mar 2025 16:25:07 +0000
Subject: [PATCH v3 0/3] KVM: arm64: Separate the hyp FF-A buffers init from
 the host
Message-ID: <20250318162510.3280359-1-sebastianene@google.com>

Hello,

This moves the initialization of the hypervisor FF-A buffers
away from the host FF-A map calling path. If the hypervisor
cannot map the buffers with Trustzone, it rejects any FF-A call
when it runs under protected mode. 
Other than that it moves the definitions of the ffa_to_linux_err
map from the arm_ffa driver to the ffa header so that the hyp code
can make use of it.

*** Changelog ***

v2 -> this version:

- dropped the "Map the hypervisor FF-A buffers on ffa init" patch
- added ack & reviewed-by tags
- don't release the ownership of the RX buffer if the flag from
 FFA_GET_PARTITION is (1)

v1 -> v2:

Split the patch that maps the ff-a buffers of ffa init and introduce
"Move the ffa_to_linux definition to the ffa header".

Thanks,


Sebastian Ene (3):
  KVM: arm64: Use the static initializer for the version lock
  firmware: arm_ffa: Move the ffa_to_linux definition to the ffa header
  KVM: arm64: Release the ownership of the hyp rx buffer to Trustzone

 arch/arm64/kvm/hyp/nvhe/ffa.c     | 12 +++++++-----
 drivers/firmware/arm_ffa/driver.c | 24 ------------------------
 include/linux/arm_ffa.h           | 27 +++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 29 deletions(-)

-- 
2.49.0.rc1.451.g8f38331e32-goog



From sebastianene at google.com  Tue Mar 18 09:25:08 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 18 Mar 2025 16:25:08 +0000
Subject: [PATCH v3 1/3] KVM: arm64: Use the static initializer for the version lock
In-Reply-To: <20250318162510.3280359-1-sebastianene@google.com>
References: <20250318162510.3280359-1-sebastianene@google.com>
Message-ID: <20250318162510.3280359-2-sebastianene@google.com>

Replace the definition of the hypervisor version lock
with a static initializer.

Signed-off-by: Sebastian Ene <sebastianene at google.com>
Acked-by: Will Deacon <will at kernel.org>
---
 arch/arm64/kvm/hyp/nvhe/ffa.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index e433dfab882a..6df6131f1107 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -69,7 +69,7 @@ static struct kvm_ffa_buffers hyp_buffers;
 static struct kvm_ffa_buffers host_buffers;
 static u32 hyp_ffa_version;
 static bool has_version_negotiated;
-static hyp_spinlock_t version_lock;
+static DEFINE_HYP_SPINLOCK(version_lock);
 
 static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
 {
@@ -911,6 +911,5 @@ int hyp_ffa_init(void *pages)
 		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
 	};
 
-	version_lock = __HYP_SPIN_LOCK_UNLOCKED;
 	return 0;
 }
-- 
2.49.0.rc1.451.g8f38331e32-goog



From sebastianene at google.com  Tue Mar 18 09:25:09 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 18 Mar 2025 16:25:09 +0000
Subject: [PATCH v3 2/3] firmware: arm_ffa: Move the ffa_to_linux definition to
 the ffa header
In-Reply-To: <20250318162510.3280359-1-sebastianene@google.com>
References: <20250318162510.3280359-1-sebastianene@google.com>
Message-ID: <20250318162510.3280359-3-sebastianene@google.com>

Keep the ffa_to_linux error map in the header and move it away
from the arm ffa driver to make it accessible for other components.

Signed-off-by: Sebastian Ene <sebastianene at google.com>
Reviewed-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_ffa/driver.c | 24 ------------------------
 include/linux/arm_ffa.h           | 24 ++++++++++++++++++++++++
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2c2ec3c35f15..b02b80f3dfe8 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -61,30 +61,6 @@
 
 static ffa_fn *invoke_ffa_fn;
 
-static const int ffa_linux_errmap[] = {
-	/* better than switch case as long as return value is continuous */
-	0,		/* FFA_RET_SUCCESS */
-	-EOPNOTSUPP,	/* FFA_RET_NOT_SUPPORTED */
-	-EINVAL,	/* FFA_RET_INVALID_PARAMETERS */
-	-ENOMEM,	/* FFA_RET_NO_MEMORY */
-	-EBUSY,		/* FFA_RET_BUSY */
-	-EINTR,		/* FFA_RET_INTERRUPTED */
-	-EACCES,	/* FFA_RET_DENIED */
-	-EAGAIN,	/* FFA_RET_RETRY */
-	-ECANCELED,	/* FFA_RET_ABORTED */
-	-ENODATA,	/* FFA_RET_NO_DATA */
-	-EAGAIN,	/* FFA_RET_NOT_READY */
-};
-
-static inline int ffa_to_linux_errno(int errno)
-{
-	int err_idx = -errno;
-
-	if (err_idx >= 0 && err_idx < ARRAY_SIZE(ffa_linux_errmap))
-		return ffa_linux_errmap[err_idx];
-	return -EINVAL;
-}
-
 struct ffa_pcpu_irq {
 	struct ffa_drv_info *info;
 };
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 74169dd0f659..850577edadbc 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -475,4 +475,28 @@ struct ffa_ops {
 	const struct ffa_notifier_ops *notifier_ops;
 };
 
+static const int ffa_linux_errmap[] = {
+	/* better than switch case as long as return value is continuous */
+	0,		/* FFA_RET_SUCCESS */
+	-EOPNOTSUPP,	/* FFA_RET_NOT_SUPPORTED */
+	-EINVAL,	/* FFA_RET_INVALID_PARAMETERS */
+	-ENOMEM,	/* FFA_RET_NO_MEMORY */
+	-EBUSY,		/* FFA_RET_BUSY */
+	-EINTR,		/* FFA_RET_INTERRUPTED */
+	-EACCES,	/* FFA_RET_DENIED */
+	-EAGAIN,	/* FFA_RET_RETRY */
+	-ECANCELED,	/* FFA_RET_ABORTED */
+	-ENODATA,	/* FFA_RET_NO_DATA */
+	-EAGAIN,	/* FFA_RET_NOT_READY */
+};
+
+static inline int ffa_to_linux_errno(int errno)
+{
+	int err_idx = -errno;
+
+	if (err_idx >= 0 && err_idx < ARRAY_SIZE(ffa_linux_errmap))
+		return ffa_linux_errmap[err_idx];
+	return -EINVAL;
+}
+
 #endif /* _LINUX_ARM_FFA_H */
-- 
2.49.0.rc1.451.g8f38331e32-goog



From sebastianene at google.com  Tue Mar 18 09:25:10 2025
From: sebastianene at google.com (Sebastian Ene)
Date: Tue, 18 Mar 2025 16:25:10 +0000
Subject: [PATCH v3 3/3] KVM: arm64: Release the ownership of the hyp rx buffer
 to Trustzone
In-Reply-To: <20250318162510.3280359-1-sebastianene@google.com>
References: <20250318162510.3280359-1-sebastianene@google.com>
Message-ID: <20250318162510.3280359-4-sebastianene@google.com>

Introduce the release FF-A call to notify Trustzone that the hypervisor
has finished copying the data from the buffer shared with Trustzone to
the non-secure partition.

Reported-by: Andrei Homescu <ahomescu at google.com>
Signed-off-by: Sebastian Ene <sebastianene at google.com>
---
 arch/arm64/kvm/hyp/nvhe/ffa.c | 9 ++++++---
 include/linux/arm_ffa.h       | 3 +++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 6df6131f1107..ac898ea6274a 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -749,6 +749,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
 	DECLARE_REG(u32, uuid3, ctxt, 4);
 	DECLARE_REG(u32, flags, ctxt, 5);
 	u32 count, partition_sz, copy_sz;
+	struct arm_smccc_res _res;
 
 	hyp_spin_lock(&host_buffers.lock);
 	if (!host_buffers.rx) {
@@ -765,11 +766,11 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
 
 	count = res->a2;
 	if (!count)
-		goto out_unlock;
+		goto release_rx;
 
 	if (hyp_ffa_version > FFA_VERSION_1_0) {
 		/* Get the number of partitions deployed in the system */
-		if (flags & 0x1)
+		if (flags & PARTITION_INFO_GET_RETURN_COUNT_ONLY)
 			goto out_unlock;
 
 		partition_sz  = res->a3;
@@ -781,10 +782,12 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
 	copy_sz = partition_sz * count;
 	if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
 		ffa_to_smccc_res(res, FFA_RET_ABORTED);
-		goto out_unlock;
+		goto release_rx;
 	}
 
 	memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
+release_rx:
+	ffa_rx_release(&_res);
 out_unlock:
 	hyp_spin_unlock(&host_buffers.lock);
 }
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 850577edadbc..32e235a2bedf 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -223,6 +223,9 @@ extern const struct bus_type ffa_bus_type;
 /* The FF-A 1.0 partition structure lacks the uuid[4] */
 #define FFA_1_0_PARTITON_INFO_SZ	(8)
 
+/* Return the count of partitions deployed in the system */
+#define PARTITION_INFO_GET_RETURN_COUNT_ONLY	(1)
+
 /* FFA transport related */
 struct ffa_partition_info {
 	u16 id;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From broonie at kernel.org  Tue Mar 18 09:29:02 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 18 Mar 2025 16:29:02 +0000
Subject: (subset) [PATCH v5 0/3] add sof support on imx95
In-Reply-To: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
References: <20250311163255.2664-1-laurentiumihalcea111@gmail.com>
Message-ID: <174231534280.179247.7213620173027724495.b4-ty@kernel.org>

On Tue, 11 Mar 2025 12:32:52 -0400, Laurentiu Mihalcea wrote:
> Add sof support on imx95. This series also includes some changes to
> the audio-graph-card2 binding required for the support.
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/3] ASoC: dt-bindings: support imx95's CM7 core
      commit: 811944a790451169876947a89338d2b86ff9fe5b
[2/3] ASoC: dt-bindings: audio-graph-card2: add widgets and hp-det-gpios support
      commit: ed92f40eccc801bd0e5dfd78b1058072638471f1

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From geert at linux-m68k.org  Tue Mar 18 09:37:06 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 18 Mar 2025 17:37:06 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe path
In-Reply-To: <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com> <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
Message-ID: <CAMuHMdWPFnHTFeeWL2-BU8tKOL-E5K2ROOz=LLBLTJJLCK9NgA@mail.gmail.com>

Hi Robin,

On Fri, 28 Feb 2025 at 16:51, Robin Murphy <robin.murphy at arm.com> wrote:
> In hindsight, there were some crucial subtleties overlooked when moving
> {of,acpi}_dma_configure() to driver probe time to allow waiting for
> IOMMU drivers with -EPROBE_DEFER, and these have become an
> ever-increasing source of problems. The IOMMU API has some fundamental
> assumptions that iommu_probe_device() is called for every device added
> to the system, in the order in which they are added. Calling it in a
> random order or not at all dependent on driver binding leads to
> malformed groups, a potential lack of isolation for devices with no
> driver, and all manner of unexpected concurrency and race conditions.
> We've attempted to mitigate the latter with point-fix bodges like
> iommu_probe_device_lock, but it's a losing battle and the time has come
> to bite the bullet and address the true source of the problem instead.
>
> The crux of the matter is that the firmware parsing actually serves two
> distinct purposes; one is identifying the IOMMU instance associated with
> a device so we can check its availability, the second is actually
> telling that instance about the relevant firmware-provided data for the
> device. However the latter also depends on the former, and at the time
> there was no good place to defer and retry that separately from the
> availability check we also wanted for client driver probe.
>
> Nowadays, though, we have a proper notion of multiple IOMMU instances in
> the core API itself, and each one gets a chance to probe its own devices
> upon registration, so we can finally make that work as intended for
> DT/IORT/VIOT platforms too. All we need is for iommu_probe_device() to
> be able to run the iommu_fwspec machinery currently buried deep in the
> wrong end of {of,acpi}_dma_configure(). Luckily it turns out to be
> surprisingly straightforward to bootstrap this transformation by pretty
> much just calling the same path twice. At client driver probe time,
> dev->driver is obviously set; conversely at device_add(), or a
> subsequent bus_iommu_probe(), any device waiting for an IOMMU really
> should *not* have a driver already, so we can use that as a condition to
> disambiguate the two cases, and avoid recursing back into the IOMMU core
> at the wrong times.
>
> Obviously this isn't the nicest thing, but for now it gives us a
> functional baseline to then unpick the layers in between without many
> more awkward cross-subsystem patches. There are some minor side-effects
> like dma_range_map potentially being created earlier, and some debug
> prints being repeated, but these aren't significantly detrimental. Let's
> make things work first, then deal with making them nice.
>
> With the basic flow finally in the right order again, the next step is
> probably turning the bus->dma_configure paths inside-out, since all we
> really need from bus code is its notion of which device and input ID(s)
> to parse the common firmware properties with...
>
> Acked-by: Bjorn Helgaas <bhelgaas at google.com> # pci-driver.c
> Acked-by: Rob Herring (Arm) <robh at kernel.org> # of/device.c
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>

Thanks for your patch, which is now commit bcb81ac6ae3c2ef9 ("iommu:
Get DT/ACPI parsing into the proper probe path") in iommu/next.

This patch triggers two issues on R-Car Gen3 platforms:

1. I am seeing a warning on Renesas Salvator-XS with R-Car M3N
(but not on the similar board with R-Car H3), and only for SATA[1].
Unfortunately commit 73d2f10957f517e5 ("iommu: Don't warn prematurely
about dodgy probes") does not help:

    ------------[ cut here ]------------
    sata_rcar ee300000.sata: late IOMMU probe at driver bind,
something fishy here!
    WARNING: CPU: 1 PID: 13 at drivers/iommu/iommu.c:571
__iommu_probe_device+0x208/0x38c
    Modules linked in:
    CPU: 1 UID: 0 PID: 13 Comm: kworker/u8:1 Not tainted
6.14.0-rc3-rcar3-00020-g73d2f10957f5-dirty #315
    Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
    Workqueue: events_unbound deferred_probe_work_func
    pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : __iommu_probe_device+0x208/0x38c
    lr : __iommu_probe_device+0x208/0x38c
    sp : ffffffc086da39a0
    x29: ffffffc086da39b0 x28: 0000000000000000 x27: 0000000000000000
    x26: 0000000000000001 x25: ffffffc080e0e0ae x24: ffffffc080e0e0bb
    x23: 0000000000000000 x22: ffffff800bd3d090 x21: ffffffc080acf680
    x20: ffffff8008e8f780 x19: ffffff800aca8810 x18: 00000000e9f55e4c
    x17: 6874656d6f73202c x16: 646e696220726576 x15: 0720072007200720
    x14: 0720072007200720 x13: 0720072007200720 x12: 0720072007200720
    x11: 00000000000001ac x10: ffffffc086da3700 x9 : ffffffc083edb140
    x8 : ffffffc086da3698 x7 : ffffffc086da36a0 x6 : 00000000fff7ffff
    x5 : c0000000fff7ffff x4 : 0000000000000000 x3 : 0000000000000001
    x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffffff80083d5380
    Call trace:
     __iommu_probe_device+0x208/0x38c (P)
     iommu_probe_device+0x34/0x74
     of_iommu_configure+0x128/0x200
     of_dma_configure_id+0xdc/0x1d4
     platform_dma_configure+0x48/0x6c
     really_probe+0xf0/0x260
     __driver_probe_device+0xec/0x104
     driver_probe_device+0x3c/0xc0
     __device_attach_driver+0x58/0xcc
     bus_for_each_drv+0xb8/0xe0
     __device_attach+0xdc/0x138
     device_initial_probe+0x10/0x18
     bus_probe_device+0x38/0xa0
     deferred_probe_work_func+0xb4/0xcc
     process_scheduled_works+0x2e4/0x4a8
     worker_thread+0x144/0x1cc
     kthread+0x188/0x198
     ret_from_fork+0x10/0x20
    irq event stamp: 49052
    hardirqs last  enabled at (49051): [<ffffffc0800fb6a8>]
__up_console_sem+0x50/0x74
    hardirqs last disabled at (49052): [<ffffffc0809eb65c>] el1_dbg+0x20/0x6c
    softirqs last  enabled at (49046): [<ffffffc080096c50>]
handle_softirqs+0x1b0/0x3b4
    softirqs last disabled at (48839): [<ffffffc080010168>]
__do_softirq+0x10/0x18
    ---[ end trace 0000000000000000 ]---

I added debug prints to sata_rcar_probe(), and verified SATA is
probed at about the same time on R-Car H3 and M3N, and the probe is
never deferred.

Do you have a clue?


2. The IOMMU driver's iommu_ops.of_xlate() callback is called about
three times as much as before:

    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform fea27000.fcp: ipmmu_of_xlate
    +platform fea2f000.fcp: ipmmu_of_xlate
    +platform ec700000.dma-controller: ipmmu_of_xlate
    +platform ec720000.dma-controller: ipmmu_of_xlate
    +platform fe950000.fcp: ipmmu_of_xlate
    +platform fe96f000.fcp: ipmmu_of_xlate
    +platform fea27000.fcp: ipmmu_of_xlate
    +platform fea2f000.fcp: ipmmu_of_xlate
    +platform fe9af000.fcp: ipmmu_of_xlate
     rcar-fcp fe950000.fcp: ipmmu_of_xlate
     rcar-fcp fe96f000.fcp: ipmmu_of_xlate
     rcar-fcp fea27000.fcp: ipmmu_of_xlate
     rcar-fcp fea2f000.fcp: ipmmu_of_xlate
     rcar-fcp fe9af000.fcp: ipmmu_of_xlate
     rcar-dmac ec700000.dma-controller: ipmmu_of_xlate
     rcar-dmac ec720000.dma-controller: ipmmu_of_xlate
    +platform e6700000.dma-controller: ipmmu_of_xlate
    +platform e6800000.ethernet: ipmmu_of_xlate
    +platform e6700000.dma-controller: ipmmu_of_xlate
    +platform e7300000.dma-controller: ipmmu_of_xlate
    +platform e7310000.dma-controller: ipmmu_of_xlate
    +platform e6800000.ethernet: ipmmu_of_xlate
    +platform ee100000.mmc: ipmmu_of_xlate
    +platform ee140000.mmc: ipmmu_of_xlate
    +platform ee160000.mmc: ipmmu_of_xlate
    +platform e6700000.dma-controller: ipmmu_of_xlate
    +platform e7300000.dma-controller: ipmmu_of_xlate
    +platform e7310000.dma-controller: ipmmu_of_xlate
    +platform e6800000.ethernet: ipmmu_of_xlate
    +platform ee100000.mmc: ipmmu_of_xlate
    +platform ee140000.mmc: ipmmu_of_xlate
    +platform ee160000.mmc: ipmmu_of_xlate
    +platform ee300000.sata: ipmmu_of_xlate
     sata_rcar ee300000.sata: ipmmu_of_xlate
     ravb e6800000.ethernet: ipmmu_of_xlate
    -renesas_sdhi_internal_dmac ee100000.mmc: ipmmu_of_xlate
    -renesas_sdhi_internal_dmac ee140000.mmc: ipmmu_of_xlate
    -renesas_sdhi_internal_dmac ee160000.mmc: ipmmu_of_xlate
     rcar-dmac e6700000.dma-controller: ipmmu_of_xlate
     rcar-dmac e7300000.dma-controller: ipmmu_of_xlate
     rcar-dmac e7310000.dma-controller: ipmmu_of_xlate

For some devices, it can be called up to 6 times. All of the duplicates
happen before the device is bound (cfr. "platform" instead of the
actual driver name):

      6 platform ec720000.dma-controller: ipmmu_of_xlate
      6 platform ec700000.dma-controller: ipmmu_of_xlate
      3 platform e6800000.ethernet: ipmmu_of_xlate
      3 platform e6700000.dma-controller: ipmmu_of_xlate
      2 platform fea2f000.fcp: ipmmu_of_xlate
      2 platform fea27000.fcp: ipmmu_of_xlate
      2 platform ee160000.mmc: ipmmu_of_xlate
      2 platform ee140000.mmc: ipmmu_of_xlate
      2 platform ee100000.mmc: ipmmu_of_xlate
      2 platform e7310000.dma-controller: ipmmu_of_xlate
      2 platform e7300000.dma-controller: ipmmu_of_xlate
      1 platform fe9af000.fcp: ipmmu_of_xlate
      1 platform fe96f000.fcp: ipmmu_of_xlate
      1 platform fe950000.fcp: ipmmu_of_xlate
      1 platform ee300000.sata: ipmmu_of_xlate
      1 sata_rcar ee300000.sata: ipmmu_of_xlate
      1 rcar-fcp fea2f000.fcp: ipmmu_of_xlate
      1 rcar-fcp fea27000.fcp: ipmmu_of_xlate
      1 rcar-fcp fe9af000.fcp: ipmmu_of_xlate
      1 rcar-fcp fe96f000.fcp: ipmmu_of_xlate
      1 rcar-fcp fe950000.fcp: ipmmu_of_xlate
      1 rcar-dmac ec720000.dma-controller: ipmmu_of_xlate
      1 rcar-dmac ec700000.dma-controller: ipmmu_of_xlate
      1 rcar-dmac e7310000.dma-controller: ipmmu_of_xlate
      1 rcar-dmac e7300000.dma-controller: ipmmu_of_xlate
      1 rcar-dmac e6700000.dma-controller: ipmmu_of_xlate
      1 ravb e6800000.ethernet: ipmmu_of_xlate

Before, the callback was called just once for each DMA slave device.

Is this intentional?

Thanks!

[1] SATA IOMMU on R-Car Gen3 needs an out-of-tree patch to add it to
    drivers/iommu/ipmmu-vmsa.c:devices_allowlist[].

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From linux at roeck-us.net  Tue Mar 18 09:37:29 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 18 Mar 2025 09:37:29 -0700
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <CAEnQRZBmYdLh29ha1FKz8=CbxjFBFFTgDkjrEmwTxW2WcxodfA@mail.gmail.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
 <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>
 <CAEnQRZBmYdLh29ha1FKz8=CbxjFBFFTgDkjrEmwTxW2WcxodfA@mail.gmail.com>
Message-ID: <ca734f66-593f-4e7c-bc76-e343a7eb88d7@roeck-us.net>

On 3/18/25 08:33, Daniel Baluta wrote:
> On Tue, Mar 18, 2025 at 5:22?PM Guenter Roeck <linux at roeck-us.net> wrote:
>>
>> On 3/18/25 01:54, florin.leotescu at oss.nxp.com wrote:
>>> From: Florin Leotescu <florin.leotescu at nxp.com>
>>>
>>> Introduce yaml schema for Microchip emc2305 pwm fan controller.
>>>
>>> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
>>> Reviewed-by: Frank Li <Frank.Li at nxp.com>
>>> ---
>>>    .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
>>>    1 file changed, 113 insertions(+)
>>>    create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>>> new file mode 100644
>>> index 000000000000..e61ef97e63af
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>>> @@ -0,0 +1,113 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +
>>> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Microchip EMC2305 SMBus compliant PWM fan controller
>>> +
>>> +maintainers:
>>> +  - Michael Shych <michaelsh at nvidia.com>
>>> +
>>> +description:
>>> +  Microchip EMC2301/2/3/5 pwm controller which supports
>>> +  up to five programmable fan control circuits.
>>> +
>>> +properties:
>>> +  compatible:
>>> +    oneOf:
>>> +      - enum:
>>> +          - microchip,emc2305
>>> +      - items:
>>> +          - enum:
>>> +              - microchip,emc2303
>>> +              - microchip,emc2302
>>> +              - microchip,emc2301
>>> +          - const: microchip,emc2305
>>> +
>>> +  reg:
>>> +    maxItems: 1
>>> +
>>> +  '#address-cells':
>>> +    const: 1
>>> +
>>> +  '#size-cells':
>>> +    const: 0
>>> +
>>> +  '#pwm-cells':
>>> +    const: 3
>>> +    description: |
>>> +      Number of cells in a PWM specifier.
>>> +      - cell 0: The PWM frequency
>>> +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
>>> +      - cell 2: The PWM output config:
>>> +           - 0 (Open-Drain)
>>> +           - 1 (Push-Pull)
>>> +
>>> +
>>> +patternProperties:
>>> +  '^fan@[0-4]$':
>>> +    $ref: fan-common.yaml#
>>> +    unevaluatedProperties: false
>>> +    properties:
>>> +      reg:
>>> +        description:
>>> +          The fan number used to determine the associated PWM channel.
>>> +
>>> +    required:
>>> +      - reg
>>> +      - pwms
>>
>> Is it necessary to make 'pwms' mandatory ? The current code works
>> just fine with defaults.
> 
> The code adding OF support is added just in the next patch, so the
> current code isn't event
> probed when trying to use dts.
> 
> Or am I missing something?
> 

The patch introducing devicetree support to the driver doesn't evaluate
the pwm property. That makes it quite obvious that, from driver perspective,
it isn't needed. I don't immediately see why it would add value to _force_
users to provide pwm frequency, polarity, and the output configuration
if the defaults work just fine.

Guenter



From krzk at kernel.org  Tue Mar 18 09:38:35 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 17:38:35 +0100
Subject: =?UTF-8?B?UmU6IOWbnuimhjog5Zue6KaGOiBbbmV0LW5leHQgNC80XSBuZXQ6IGZ0?=
 =?UTF-8?Q?gmac100=3A_add_RGMII_delay_for_AST2600?=
In-Reply-To: <5b448c6b-a37d-4028-a56d-2953fc0e743a@lunn.ch>
References: <20250317025922.1526937-1-jacky_chou@aspeedtech.com>
 <20250317025922.1526937-5-jacky_chou@aspeedtech.com>
 <20250317095229.6f8754dd@fedora.home>
 <Z9gC2vz2w5dfZsum@shell.armlinux.org.uk>
 <SEYPR06MB51347CD1AB5940641A77427D9DDF2@SEYPR06MB5134.apcprd06.prod.outlook.com>
 <c3c02498-24a3-4ced-8ba3-5ca62b243047@lunn.ch>
 <SEYPR06MB5134C8128FCF57D37F38CEFF9DDE2@SEYPR06MB5134.apcprd06.prod.outlook.com>
 <5b448c6b-a37d-4028-a56d-2953fc0e743a@lunn.ch>
Message-ID: <8762dea1-3a0d-4bc8-aacd-fc8a2b5e2714@kernel.org>

On 18/03/2025 14:51, Andrew Lunn wrote:
> On Tue, Mar 18, 2025 at 05:34:08AM +0000, Jacky Chou wrote:
>> Hi Andrew,
>>
>> Thank you for your reply.
>>
>>>> The RGMII delay of AST2600 has a lot of steps can be configured.
>>>
>>> Are they uniformly space? Then it should be a simple formula to calculate? Or
>>> a lookup table?
>>
>> There are fixed delay values by step. I list below.
>> AST2600 MAC0/1 one step delay = 45 ps
>> AST2600 MAC2/3 one step delay = 250 ps
> 
> That is messy.
> 
>> I calculate all step and emulate them.
>> The dt-binding will be like below.
>> rx-internal-delay-ps:
>>     description:
>>       Setting this property to a non-zero number sets the RX internal delay
>>       for the MAC. ... skip ...
>>     enum:
>>       [45, 90, 135, 180, 225, 250, 270, 315, 360, 405, 450, 495, 500, 540, 585, 630, 675, 
>>        720, 750, 765, 810, 855, 900, 945, 990, 1000, 1035, 1080, 1125, 1170, 1215, 1250, 
>>        1260, 1305, 1350, 1395, 1440, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 
>>        3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 
>>        7250, 7500, 7750, 8000]
> 
> Can the hardware do 0 ps?
> 
> So this list is a superset of both 45ps and 250ps steps?

git grep multipleOf:

e.g.
oneOf:
 - minimum: 45
   maximum: ...
   multipleOf: 45
 - minimum: 1500
   maximum: ...
   multipleOf: 250

> 
> Lets see what the DT Maintainers say, but it could be you need two
> different compatibles for mac0/1 to mac2/3 because they are not
> actually compatible! You can then have a list per compatible.
If this is the only, *only* difference, then just go with vendor
property matching register value... but oh, wait, how person reading and
writing the DTS would understand if "0x2" means 90 ps or 1750 ps? I
don't see how the original binding was helping here in total. Just
moving the burden from driver developer to DTS developer. :/

If different instances are not the same, means the devices are not the
same, so two compatibles seem reasonable.

Best regards,
Krzysztof


From linux at roeck-us.net  Tue Mar 18 09:39:35 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 18 Mar 2025 09:39:35 -0700
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <20250318155946.GC13829@willie-the-truck>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
 <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
 <20250318155946.GC13829@willie-the-truck>
Message-ID: <17a383b4-2add-4e74-b7ca-d7ef2baac4f9@roeck-us.net>

On 3/18/25 08:59, Will Deacon wrote:
> On Thu, Mar 13, 2025 at 05:40:59PM +0100, Alessandro Carminati wrote:
>> On Thu, Mar 13, 2025 at 1:25?PM Will Deacon <will at kernel.org> wrote:
>>>
>>> On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
>>>> diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
>>>> index 28be048db3f6..044c5e24a17d 100644
>>>> --- a/arch/arm64/include/asm/bug.h
>>>> +++ b/arch/arm64/include/asm/bug.h
>>>> @@ -11,8 +11,14 @@
>>>>
>>>>   #include <asm/asm-bug.h>
>>>>
>>>> +#ifdef HAVE_BUG_FUNCTION
>>>> +# define __BUG_FUNC  __func__
>>>> +#else
>>>> +# define __BUG_FUNC  NULL
>>>> +#endif
>>>> +
>>>>   #define __BUG_FLAGS(flags)                           \
>>>> -     asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
>>>> +     asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
>>>
>>> Why is 'i' the right asm constraint to use here? It seems a bit odd to
>>> use that for a pointer.
>>
>> I received this code as legacy from a previous version.
>> In my review, I considered the case when HAVE_BUG_FUNCTION is defined:
>> Here, __BUG_FUNC is defined as __func__, which is the name of the
>> current function as a string literal.
>> Using the constraint "i" seems appropriate to me in this case.
>>
>> However, when HAVE_BUG_FUNCTION is not defined:
>> __BUG_FUNC is defined as NULL. Initially, I considered it literal 0,
>> but after investigating your concern, I found:
>>
>> ```
>> $ echo -E "#include <stdio.h>\n#include <stddef.h>\nint main()
>> {\nreturn 0;\n}" | aarch64-linux-gnu-gcc -E -dM - | grep NULL
>> #define NULL ((void *)0)
>> ```
>>
>> I realized that NULL is actually a pointer that is not a link time
>> symbol, and using the "i" constraint with NULL may result in undefined
>> behavior.
>>
>> Would the following alternative definition for __BUG_FUNC be more convincing?
>>
>> ```
>> #ifdef HAVE_BUG_FUNCTION
>>      #define __BUG_FUNC __func__
>> #else
>>      #define __BUG_FUNC (uintptr_t)0
>> #endif
>> ```
>> Let me know your thoughts.
> 
> Thanks for the analysis; I hadn't noticed this specific issue, it just
> smelled a bit fishy. Anyway, the diff above looks better, thanks.
> 

It has been a long time, but I seem to recall that I ran into trouble when
trying to use a different constraint.

Guenter



From robin.murphy at arm.com  Tue Mar 18 09:40:26 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 16:40:26 +0000
Subject: [PATCH Resend] perf/arm-cmn: Remove CMN-600 DTC domain special
 case
In-Reply-To: <20250318161744.GB13981@willie-the-truck>
References: <67985e39f53b56385d79a4f1264cf7f9cacedb58.1742308248.git.robin.murphy@arm.com>
 <20250318161744.GB13981@willie-the-truck>
Message-ID: <e1d7aee0-06e4-4aa3-be37-98b0e9b165fe@arm.com>

On 18/03/2025 4:17 pm, Will Deacon wrote:
> Hi Robin,
> 
> On Tue, Mar 18, 2025 at 02:32:10PM +0000, Robin Murphy wrote:
>> The special case for trying to infer the DTC domain for DTC-adjacent
>> nodes on CMN-600 is fragile and buggy - currently resulting in subtly
>> messed up DTC counter allocation - and the theoretical benefit it
>> offers to a tiny minority of use-cases arguably doesn't outweigh the
>> inconsistency it offers to others anyway. Just get rid of it.
>>
>> Fixes: ab33c66fd8f1 ("perf/arm-cmn: Enable per-DTC counter allocation")
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>   drivers/perf/arm-cmn.c | 7 -------
>>   1 file changed, 7 deletions(-)
> 
> You've got "Resend" in the subject, but I can't seem to find the original
> posting :/
> 
> Please can you point me at it? I just want to make sure that I'm not
> missing patches, as you're unlikely to be the only person affected if
> that is the case.

Sorry, forgot to explain below the cut - this is a resend from my end 
because I fat-fingered my LAKML alias the first time around, so I wasn't 
entirely sure whether you'd get it twice. I guess the error I got was 
actually from the SMTP server before it delivered anything, phew!

Thanks,
Robin.


From rrathina at amd.com  Tue Mar 18 09:42:18 2025
From: rrathina at amd.com (Rajaganesh Rathinasabapathi)
Date: Tue, 18 Mar 2025 22:12:18 +0530
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318-rapid-coot-of-tact-d779ad@krzk-bin>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318-rapid-coot-of-tact-d779ad@krzk-bin>
Message-ID: <bc27b658-5c62-4187-acdc-df8dc22161a8@amd.com>

On 3/18/25 14:14, Krzysztof Kozlowski wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> On Mon, Mar 17, 2025 at 11:12:23PM -0500, Rajaganesh Rathinasabapathi wrote:
>> Document new AMD Onyx BMC board compatibles
>>
>> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
>> ---
> 
> Where is the changelog? What happened with this patch between v1 and v3?
> 
> Best regards,
> Krzysztof
> 
Earlier patches did not add dt-binding patch. Added compatibles now in v3.
It was a review comment on earlier dts submission.


From krzk at kernel.org  Tue Mar 18 09:43:41 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 17:43:41 +0100
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <1142f61a-63d8-4a3c-8f89-a7b3bbd6cdc9@kernel.org>

On 18/03/2025 05:12, Rajaganesh Rathinasabapathi wrote:
> Document new AMD Onyx BMC board compatibles
> 
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---
>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From rrathina at amd.com  Tue Mar 18 09:48:46 2025
From: rrathina at amd.com (Rajaganesh Rathinasabapathi)
Date: Tue, 18 Mar 2025 22:18:46 +0530
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <fdd969cb-aa2d-4d55-949e-e2631757221e@lunn.ch>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
 <fdd969cb-aa2d-4d55-949e-e2631757221e@lunn.ch>
Message-ID: <ab74593d-a3be-4283-ad83-3525cb6d7dd1@amd.com>

On 3/18/25 19:38, Andrew Lunn wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
>> +&mac3 {
>> +     status = "okay";
>> +     phy-mode = "rgmii";
> 
> Does the PCB have extra long clock lines to insert the 2ns RGMII
> delay? Or are you another victim of aspeeds broken MAC/SCU driver?
> 
>        Andrew
We're following Aspeed SDK and referred other dts based on ast2600.
I assume Aspeed has moved clock delays to u-boot.
Link: https://lore.kernel.org/lkml/SG2PR06MB23150B3673E58737ABB08D51E6139 at SG2PR06MB2315.apcprd06.prod.outlook.com/



From andrew at lunn.ch  Tue Mar 18 09:54:06 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 17:54:06 +0100
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <ab74593d-a3be-4283-ad83-3525cb6d7dd1@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
 <fdd969cb-aa2d-4d55-949e-e2631757221e@lunn.ch>
 <ab74593d-a3be-4283-ad83-3525cb6d7dd1@amd.com>
Message-ID: <6ca63f35-05c4-472d-a412-74e5c7ffeefb@lunn.ch>

On Tue, Mar 18, 2025 at 10:18:46PM +0530, Rajaganesh Rathinasabapathi wrote:
> On 3/18/25 19:38, Andrew Lunn wrote:
> > Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> > 
> > 
> >> +&mac3 {
> >> +     status = "okay";
> >> +     phy-mode = "rgmii";
> > 
> > Does the PCB have extra long clock lines to insert the 2ns RGMII
> > delay? Or are you another victim of aspeeds broken MAC/SCU driver?
> > 
> >        Andrew
> We're following Aspeed SDK and referred other dts based on ast2600.

Which are all broken.

At the moment, you are joining NVIDIA and IBM waiting for Aspeed to
sort out this mess. Maybe you can apply some pressure...

     Andrew


From krzk at kernel.org  Tue Mar 18 09:58:50 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 17:58:50 +0100
Subject: [PATCH v3 2/2] ARM:dts:aspeed: Initial device tree for AMD Onyx
 Platform
In-Reply-To: <cfdbfe7e-5cf4-47a7-af5f-b220cad6f7e4@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318041224.1693323-2-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318-imaginary-peccary-of-argument-ab6b39@krzk-bin>
 <cfdbfe7e-5cf4-47a7-af5f-b220cad6f7e4@amd.com>
Message-ID: <4277e7d2-2449-4b82-8743-ba7f4581b02f@kernel.org>

On 18/03/2025 17:44, Rajaganesh Rathinasabapathi wrote:
>>
>> <form letter>
>> This is a friendly reminder during the review process.
>>
>> It seems my or other reviewer's previous comments were not fully
>> addressed. Maybe the feedback got lost between the quotes, maybe you
>> just forgot to apply it. Please go back to the previous discussion and
>> either implement all requested changes or keep discussing them.
>>
>> Thank you.
>> </form letter>
>>
>> Best regards,
>> Krzysztof
>>
> 
> There were two comments. One was to remove bootargs, this is addressed in v3.
> Another comment was to add compatibles for amd,onyx-bmc, it part of earlier commit (patch v3 1/2).
No, there were more.

Best regards,
Krzysztof


From robh at kernel.org  Tue Mar 18 10:07:51 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 12:07:51 -0500
Subject: [PATCH v3 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318041224.1693323-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <174231753965.3228114.9624277631612711787.robh@kernel.org>


On Mon, 17 Mar 2025 23:12:23 -0500, Rajaganesh Rathinasabapathi wrote:
> Document new AMD Onyx BMC board compatibles
> 
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---
>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250318041224.1693323-1-Rajaganesh.Rathinasabapathi at amd.com:

Error: arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts:20.25-31 syntax error
FATAL ERROR: Unable to parse input tree
make[3]: *** [scripts/Makefile.dtbs:131: arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb] Error 1
make[2]: *** [scripts/Makefile.build:461: arch/arm/boot/dts/aspeed] Error 2
make[2]: Target 'arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb' not remade because of errors.
make[1]: *** [/home/rob/proj/linux-dt-testing/Makefile:1475: aspeed/aspeed-bmc-amd-onyx.dtb] Error 2
arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-spc621d8hm3.dtb: /ahb/apb at 1e780000/pwm-tacho-controller at 1e786000: failed to match any schema with compatible: ['aspeed,ast2500-pwm-tacho']
make: *** [Makefile:248: __sub-make] Error 2
make: Target 'aspeed/aspeed-bmc-microsoft-olympus.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-delta-ahe50dc.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-palmetto.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-ast2500-evb.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-quanta-s6q.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-romulus.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-sbp1.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-inspur-fp5280g2.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-minipack.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-mowgli.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-witherspoon.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-vegman-sx20.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-tacoma.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-lanyang.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-vegman-rx20.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-fuji.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-everest.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-bytedance-g220a.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-cmm.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-blueridge-4u.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asrock-e3c246d4i.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-ast2600-evb-a1.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-amd-onyx.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-supermicro-x11spi.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-vegman-n110.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-vesnin.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-bletchley.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-ast2600-evb.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-inventec-transformers.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-rainier.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-tyan-s8036.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ampere-mtjade.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asrock-x570d4u.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-yosemite4.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-blueridge.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asrock-spc621d8hm3.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-inventec-starscream.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-rainier-1s4u.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-yamp.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-rainier-4u.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-catalina.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-amd-ethanolx.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-bonnell.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-inspur-on5263m5.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ampere-mtjefferson.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asus-x4tf.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-nicole.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-intel-s2600wf.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-wedge40.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-lenovo-hr855xg2.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asrock-e3c256d4i.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-lenovo-hr630.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-asrock-romed8hm3.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-quanta-q71l.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-tyan-s7106.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-yosemitev2.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-wedge100.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-elbert.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-amd-daytonax.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-qcom-dc-scm-v1.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ufispace-ncplite.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-opp-zaius.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-portwell-neptune.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ampere-mtmitchell.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-fuji.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-minerva.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-galaxy100.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-harma.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-inspur-nf5280m6.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-wedge400.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-arm-stardragon4800-rep2.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-ibm-system1.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-greatlakes.dtb' not remade because of errors.
make: Target 'aspeed/aspeed-bmc-facebook-tiogapass.dtb' not remade because of errors.







From leo.yan at arm.com  Tue Mar 18 10:15:57 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 18 Mar 2025 17:15:57 +0000
Subject: [PATCH 1/7] perf annotate: Handle arm64 load and store
 instructions
In-Reply-To: <20250314162137.528204-2-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-2-lihuafei1@huawei.com>
Message-ID: <20250318171557.GA2860028@e132581.arm.com>

Hi Huafei,

On Sat, Mar 15, 2025 at 12:21:31AM +0800, Li Huafei wrote:
> Add ldst_ops to handle load and store instructions in order to parse
> the data types and offsets associated with PMU events for memory access
> instructions. There are many variants of load and store instructions in
> ARM64, making it difficult to match all of these instruction names
> completely. Therefore, only the instruction prefixes are matched. The
> prefix 'ld|st' covers most of the memory access instructions, 'cas|swp'
> matches atomic instructions, and 'prf' matches memory prefetch
> instructions.

Thanks a lot for working on this!

> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/arch/arm64/annotate/instructions.c | 67 ++++++++++++++++++-
>  1 file changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
> index d465d093e7eb..c212eb7341bd 100644
> --- a/tools/perf/arch/arm64/annotate/instructions.c
> +++ b/tools/perf/arch/arm64/annotate/instructions.c
> @@ -6,7 +6,8 @@
>  
>  struct arm64_annotate {
>  	regex_t call_insn,
> -		jump_insn;
> +		jump_insn,
> +		ldst_insn; /* load and store instruction */
>
>  };
>  
>  static int arm64_mov__parse(struct arch *arch __maybe_unused,
> @@ -67,6 +68,57 @@ static struct ins_ops arm64_mov_ops = {
>  	.scnprintf = mov__scnprintf,
>  };
>  
> +static int arm64_ldst__parse(struct arch *arch __maybe_unused,
> +			     struct ins_operands *ops,
> +			     struct map_symbol *ms __maybe_unused,
> +			     struct disasm_line *dl __maybe_unused)
> +{
> +	char *s, *target;
> +
> +	/*
> +	 * The part starting from the memory access annotation '[' is parsed
> +	 * as 'target', while the part before it is parsed as 'source'.
> +	 */
> +	target = s = strchr(ops->raw, '[');
> +	if (!s)
> +		return -1;

I am wandering if this is sufficient for handling different load /
store instructions.

A simple case is an instruction "ldr x1, [x2]", the handling above
should can work well.  How about instructions below with offsets:

    ldr     x2, [x0, #968]
    ldr     w3, [x25], #4

Could you also confirm if the parsing can fit the pattern for
load/store pair instructions?

    ldp     x29, x30, [sp], #16

The instruction loads paired 64-bit data into two registers.

> +	while (s > ops->raw && *s != ',')
> +		--s;
> +
> +	if (s == ops->raw)
> +		return -1;
> +
> +	*s = '\0';
> +	ops->source.raw = strdup(ops->raw);
>
> +
> +	*s = ',';
> +	if (!ops->source.raw)
> +		return -1;
> +
> +	ops->target.raw = strdup(target);
> +	if (!ops->target.raw) {
> +		zfree(ops->source.raw);
> +		return -1;
> +	}
> +	ops->target.mem_ref = true;
> +
> +	return 0;
> +}
> +
> +static int ldst__scnprintf(struct ins *ins, char *bf, size_t size,
> +			   struct ins_operands *ops, int max_ins_name)
> +{
> +	return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
> +			 ops->source.name ?: ops->source.raw,
> +			 ops->target.name ?: ops->target.raw);
> +}
> +
> +static struct ins_ops arm64_ldst_ops = {
> +	.parse	   = arm64_ldst__parse,
> +	.scnprintf = ldst__scnprintf,
> +};
> +
>  static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
>  {
>  	struct arm64_annotate *arm = arch->priv;
> @@ -77,6 +129,8 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
>  		ops = &jump_ops;
>  	else if (!regexec(&arm->call_insn, name, 2, match, 0))
>  		ops = &call_ops;
> +	else if (!regexec(&arm->ldst_insn, name, 2, match, 0))
> +		ops = &arm64_ldst_ops;
>  	else if (!strcmp(name, "ret"))
>  		ops = &ret_ops;
>  	else
> @@ -107,6 +161,15 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
>  		      REG_EXTENDED);
>  	if (err)
>  		goto out_free_call;
> +	/*
> +	 * The ARM64 architecture has many variants of load/store instructions.
> +	 * It is quite challenging to match all of them completely. Here, we
> +	 * only match the prefixes of these instructions.
> +	 */
> +	err = regcomp(&arm->ldst_insn, "^(ld|st|cas|prf|swp)",
> +		      REG_EXTENDED);

As a first step, it is fine for me to support these memory types.

After I review the whole series, I might go back to check if we can
support other memory instructions (e.g. SVE, Memory Copy and
Memory Set instructions, etc).  At least, we need to avoid any
barriers for extending these instructions.

Thanks,
Leo

> +	if (err)
> +		goto out_free_jump;
>  
>  	arch->initialized = true;
>  	arch->priv	  = arm;
> @@ -117,6 +180,8 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
>  	arch->e_flags = 0;
>  	return 0;
>  
> +out_free_jump:
> +	regfree(&arm->jump_insn);
>  out_free_call:
>  	regfree(&arm->call_insn);
>  out_free_arm:
> 
> -- 
> 2.25.1
> 


From pr-tracker-bot at kernel.org  Tue Mar 18 10:19:39 2025
From: pr-tracker-bot at kernel.org (pr-tracker-bot at kernel.org)
Date: Tue, 18 Mar 2025 17:19:39 +0000
Subject: [GIT PULL] pmdomain fixes for v6.14-rc8
In-Reply-To: <20250318122548.1328552-1-ulf.hansson@linaro.org>
References: <20250318122548.1328552-1-ulf.hansson@linaro.org>
Message-ID: <174231837963.393299.6404503405685975618.pr-tracker-bot@kernel.org>

The pull request you sent on Tue, 18 Mar 2025 13:25:48 +0100:

> git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git tags/pmdomain-v6.14-rc4

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/81e4f8d68c66da301bb881862735bd74c6241a19

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


From irogers at google.com  Tue Mar 18 10:19:14 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 10:19:14 -0700
Subject: [PATCH v1] perf cpumap: Increment reference count for online cpumap
Message-ID: <20250318171914.145616-1-irogers@google.com>

Thomas Richter <tmricht at linux.ibm.com> reported a double put on the
cpumap for the placeholder core PMU:
https://lore.kernel.org/lkml/20250318095132.1502654-3-tmricht at linux.ibm.com/
Requiring the caller to get the cpumap is not how these things are
usually done, switch cpu_map__online to do the get and then fix up any
use cases where a put is needed.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/arch/arm/util/pmu.c | 5 +++--
 tools/perf/util/cpumap.c       | 2 +-
 tools/perf/util/evlist.c       | 5 +++--
 tools/perf/util/mem-events.c   | 5 ++++-
 tools/perf/util/mmap.c         | 4 ++--
 tools/perf/util/pmu.c          | 2 +-
 tools/perf/util/tool_pmu.c     | 1 +
 7 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
index 57dc94a6e38c..f70075c89aa0 100644
--- a/tools/perf/arch/arm/util/pmu.c
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -18,7 +18,7 @@
 
 void perf_pmu__arch_init(struct perf_pmu *pmu)
 {
-	struct perf_cpu_map *intersect;
+	struct perf_cpu_map *intersect, *online = cpu_map__online();
 
 #ifdef HAVE_AUXTRACE_SUPPORT
 	if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
@@ -41,7 +41,8 @@ void perf_pmu__arch_init(struct perf_pmu *pmu)
 	}
 #endif
 	/* Workaround some ARM PMU's failing to correctly set CPU maps for online processors. */
-	intersect = perf_cpu_map__intersect(cpu_map__online(), pmu->cpus);
+	intersect = perf_cpu_map__intersect(online, pmu->cpus);
+	perf_cpu_map__put(online);
 	perf_cpu_map__put(pmu->cpus);
 	pmu->cpus = intersect;
 }
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 9bc5e0370234..89570397a4b3 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -722,7 +722,7 @@ struct perf_cpu_map *cpu_map__online(void) /* thread unsafe */
 	if (!online)
 		online = perf_cpu_map__new_online_cpus(); /* from /sys/devices/system/cpu/online */
 
-	return online;
+	return perf_cpu_map__get(online);
 }
 
 bool aggr_cpu_id__equal(const struct aggr_cpu_id *a, const struct aggr_cpu_id *b)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 49e10d6981ad..c1a04141aed0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -2534,10 +2534,10 @@ void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_lis
 		return;
 
 	evlist__for_each_entry(evlist, pos) {
-		struct perf_cpu_map *intersect, *to_test;
+		struct perf_cpu_map *intersect, *to_test, *online = cpu_map__online();
 		const struct perf_pmu *pmu = evsel__find_pmu(pos);
 
-		to_test = pmu && pmu->is_core ? pmu->cpus : cpu_map__online();
+		to_test = pmu && pmu->is_core ? pmu->cpus : online;
 		intersect = perf_cpu_map__intersect(to_test, user_requested_cpus);
 		if (!perf_cpu_map__equal(intersect, user_requested_cpus)) {
 			char buf[128];
@@ -2547,6 +2547,7 @@ void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_lis
 				cpu_list, pmu ? pmu->name : "cpu", buf, evsel__name(pos));
 		}
 		perf_cpu_map__put(intersect);
+		perf_cpu_map__put(online);
 	}
 	perf_cpu_map__put(user_requested_cpus);
 }
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 9011784b950d..884d9aebce91 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -303,12 +303,15 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, char **eve
 	}
 
 	if (cpu_map) {
-		if (!perf_cpu_map__equal(cpu_map, cpu_map__online())) {
+		struct perf_cpu_map *online = cpu_map__online();
+
+		if (!perf_cpu_map__equal(cpu_map, online)) {
 			char buf[200];
 
 			cpu_map__snprint(cpu_map, buf, sizeof(buf));
 			pr_warning("Memory events are enabled on a subset of CPUs: %s\n", buf);
 		}
+		perf_cpu_map__put(online);
 		perf_cpu_map__put(cpu_map);
 	}
 
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index a7ef4d8d57d8..a34726219af3 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -244,9 +244,8 @@ static void build_node_mask(int node, struct mmap_cpu_mask *mask)
 {
 	int idx, nr_cpus;
 	struct perf_cpu cpu;
-	const struct perf_cpu_map *cpu_map = NULL;
+	struct perf_cpu_map *cpu_map = cpu_map__online();
 
-	cpu_map = cpu_map__online();
 	if (!cpu_map)
 		return;
 
@@ -256,6 +255,7 @@ static void build_node_mask(int node, struct mmap_cpu_mask *mask)
 		if (cpu__get_node(cpu) == node)
 			__set_bit(cpu.cpu, mask->bits);
 	}
+	perf_cpu_map__put(cpu_map);
 }
 
 static int perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp)
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57450c73fb63..b7ebac5ab1d1 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -779,7 +779,7 @@ static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *pmu_name, bool is
 	}
 
 	/* Nothing found, for core PMUs assume this means all CPUs. */
-	return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL;
+	return is_core ? cpu_map__online() : NULL;
 }
 
 static bool pmu_is_uncore(int dirfd, const char *name)
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index 9156745ea180..b60ac390d52d 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -355,6 +355,7 @@ bool tool_pmu__read_event(enum tool_pmu_event ev, u64 *result)
 
 		if (online) {
 			*result = perf_cpu_map__nr(online);
+			perf_cpu_map__put(online);
 			return true;
 		}
 		return false;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From wei.liu at kernel.org  Tue Mar 18 10:24:44 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Tue, 18 Mar 2025 17:24:44 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <Z9msXAClr-vGn3GR@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Mon, Mar 17, 2025 at 11:51:52PM +0000, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
[...]
> > +static long
> > +mshv_vp_ioctl_get_set_state(struct mshv_vp *vp,
> > +			    struct mshv_get_set_vp_state __user *user_args,
> > +			    bool is_set)
> > +{
> > +	struct mshv_get_set_vp_state args;
> > +	long ret = 0;
> > +	union hv_output_get_vp_state vp_state;
> > +	u32 data_sz;
> > +	struct hv_vp_state_data state_data = {};
> > +
> > +	if (copy_from_user(&args, user_args, sizeof(args)))
> > +		return -EFAULT;
> > +
> > +	if (args.type >= MSHV_VP_STATE_COUNT || mshv_field_nonzero(args, rsvd) ||
> > +	    !args.buf_sz || !PAGE_ALIGNED(args.buf_sz) ||
> > +	    !PAGE_ALIGNED(args.buf_ptr))
> > +		return -EINVAL;
> > +
> > +	if (!access_ok((void __user *)args.buf_ptr, args.buf_sz))
> > +		return -EFAULT;
> > +
> > +	switch (args.type) {
> > +	case MSHV_VP_STATE_LAPIC:
> > +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
> > +		data_sz = HV_HYP_PAGE_SIZE;
> > +		break;
> > +	case MSHV_VP_STATE_XSAVE:
> 
> Just FYI, you can put a semicolon after the colon on the above line, which
> adds a null statement, and then the C compiler will accept the definition
> of local variable data_sz_64 without needing the odd-looking braces. 
> 
> See https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement/19830820
> 

This is a rarely seen pattern in the kernel, so I would prefer to keep
the braces for clarity.

 $ git grep -A5 -P 'case\s+\w+:;$'

This shows a few places are using this pattern. But they are not
declaring variables afterwards.

> I learn something new every day! :-)
> 

Yep, me too.

Thanks for reviewing the code. Nuno will address the comments. I can fix
them up.

Thanks,
Wei.


From robin.murphy at arm.com  Tue Mar 18 10:24:51 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 17:24:51 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <CAMuHMdWPFnHTFeeWL2-BU8tKOL-E5K2ROOz=LLBLTJJLCK9NgA@mail.gmail.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CAMuHMdWPFnHTFeeWL2-BU8tKOL-E5K2ROOz=LLBLTJJLCK9NgA@mail.gmail.com>
Message-ID: <25bd5477-a388-405f-a976-6b1a59860ef8@arm.com>

Hi Geert,

On 18/03/2025 4:37 pm, Geert Uytterhoeven wrote:
[...]
> Thanks for your patch, which is now commit bcb81ac6ae3c2ef9 ("iommu:
> Get DT/ACPI parsing into the proper probe path") in iommu/next.
> 
> This patch triggers two issues on R-Car Gen3 platforms:
> 
> 1. I am seeing a warning on Renesas Salvator-XS with R-Car M3N
> (but not on the similar board with R-Car H3), and only for SATA[1].
> Unfortunately commit 73d2f10957f517e5 ("iommu: Don't warn prematurely
> about dodgy probes") does not help:
[...]
>      Call trace:
>       __iommu_probe_device+0x208/0x38c (P)
>       iommu_probe_device+0x34/0x74
>       of_iommu_configure+0x128/0x200
>       of_dma_configure_id+0xdc/0x1d4
>       platform_dma_configure+0x48/0x6c
>       really_probe+0xf0/0x260
>       __driver_probe_device+0xec/0x104
>       driver_probe_device+0x3c/0xc0

Hurrah, this is the warning doing the correct job - something *is* off
if we're now getting here without the IOMMU configuration being done
already (for a normal device with no other funny business going on).

> 2. The IOMMU driver's iommu_ops.of_xlate() callback is called about
> three times as much as before:

That would suggest that the fwspec gets set up OK, then something later
in the __iommu_probe_device() path fails and tears it down again, so the
next attempt starts from scratch. Do you see the "Cannot attach to
IPMMU" message firing? And similarly to the Rockchip case, does the
below help?

Thanks,
Robin.

----->8-----
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 074daf1aac4e..5d416262ae5f 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -1081,6 +1081,7 @@ static int ipmmu_probe(struct platform_device *pdev)
  		}
  	}
  
+	platform_set_drvdata(pdev, mmu);
  	/*
  	 * Register the IPMMU to the IOMMU subsystem in the following cases:
  	 * - R-Car Gen2 IPMMU (all devices registered)
@@ -1103,7 +1104,6 @@ static int ipmmu_probe(struct platform_device *pdev)
  	 * ipmmu_init() after the probe function returns.
  	 */
  
-	platform_set_drvdata(pdev, mmu);
  
  	return 0;
  }


From ryan.wanner at microchip.com  Tue Mar 18 10:33:39 2025
From: ryan.wanner at microchip.com (Ryan Wanner)
Date: Tue, 18 Mar 2025 10:33:39 -0700
Subject: [PATCH 0/2] AT91 Clock Adjustments
In-Reply-To: <b76108c1-3282-4b98-a210-b350e8ec0ec2@microchip.com>
References: <cover.1738864727.git.Ryan.Wanner@microchip.com>
 <7dd5a0a2-4f56-48b4-8861-c7d75754faab@tuxon.dev>
 <b76108c1-3282-4b98-a210-b350e8ec0ec2@microchip.com>
Message-ID: <7512d7fb-30dd-41f6-8936-45ff0d949876@microchip.com>

On 2/26/25 08:36, Ryan wrote:
> On 2/26/25 02:06, Claudiu Beznea wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>
>> On 06.02.2025 20:14, Ryan.Wanner at microchip.com wrote:
>>> From: Ryan Wanner <Ryan.Wanner at microchip.com>
>>>
>>> This set has clock system adjustments for the AT91 clock system.
>>>
>>> The first is to adjust the slow clock driver to account for the updated
>>> DT node-naming for clocks and xtals and ensuring the driver is still
>>> backwards compatible.
>>>
>>> The second is a adding a missing clk_hw struct that is not added into
>>> parent_data struct causing a incorrect parent for main_osc.
>>>
>>> Ryan Wanner (2):
>>>   clk: at91: sckc: Fix parent_data struct for slow osc
>>>   clk: at91: sama7d65: Add missing clk_hw to parent_data
>>>
>>>  drivers/clk/at91/sama7d65.c |  1 +
>>>  drivers/clk/at91/sckc.c     | 12 ++++++------
>>>  2 files changed, 7 insertions(+), 6 deletions(-)
>>>
>>
>> There are boot failures on sama7g5 with this series on top of at91-next and
>> the following diff on sama7g5 dts to mimic the sama7d65 use case:
>>
>> diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>> b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>> index 0f5e6ad438dd..1bce9f999431 100644
>> --- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>> +++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>> @@ -35,16 +35,6 @@ aliases {
>>                 i2c2 = &i2c9;
>>         };
>>
>> -       clocks {
>> -               slow_xtal {
>> -                       clock-frequency = <32768>;
>> -               };
>> -
>> -               main_xtal {
>> -                       clock-frequency = <24000000>;
>> -               };
>> -       };
>> -
>>         gpio-keys {
>>                 compatible = "gpio-keys";
>>
>> @@ -132,6 +122,15 @@ spdif_out: spdif-out {
>>         };
>>  };
>>
>> +&slow_xtal {
>> +       clock-frequency = <32768>;
>> +};
>> +
>> +&main_xtal {
>> +       clock-frequency = <24000000>;
>> +};
>> +
>> +
>>  &adc {
>>         vddana-supply = <&vddout25>;
>>         vref-supply = <&vddout25>;
>> diff --git a/arch/arm/boot/dts/microchip/sama7g5.dtsi
>> b/arch/arm/boot/dts/microchip/sama7g5.dtsi
>> index 17bcdcf0cf4a..3158c2f0b4c0 100644
>> --- a/arch/arm/boot/dts/microchip/sama7g5.dtsi
>> +++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi
>> @@ -117,12 +117,12 @@ map1 {
>>         };
>>
>>         clocks {
>> -               slow_xtal: slow_xtal {
>> +               slow_xtal: clk-slowxtal {
>>                         compatible = "fixed-clock";
>>                         #clock-cells = <0>;
>>                 };
>>
>> -               main_xtal: main_xtal {
>> +               main_xtal: clk-mainxtal {
>>                         compatible = "fixed-clock";
>>                         #clock-cells = <0>;
>>                 };
>>
>> I've identified the following:
>>
>>
>> cpu cpu0: _opp_config_clk_single: failed to set clock rate: -22
>> cpufreq: __target_index: Failed to change cpu frequency: -22
>> ------------[ cut here ]------------
>> kernel BUG at drivers/cpufreq/cpufreq.c:1523!
>> Internal error: Oops - BUG: 0 [#1] ARM
>> Modules linked in:
>> CPU: 0 UID: 0 PID: 1 Comm: swapper Not tainted 6.14.0-rc1+ #11
>> Hardware name: Microchip SAMA7
>> PC is at cpufreq_online+0x8d8/0xa30
>> LR is at __wake_up+0x20/0x30
>> pc : [<c063cca0>]    lr : [<c0151254>]    psr: a0000013
>> sp : e0821d30  ip : 00000000  fp : c0e50508
>> r10: c434830c  r9 : c4348204  r8 : c0e97230
>> r7 : c4348264  r6 : 00000000  r5 : 000ca511  r4 : c4348200
>> r3 : 047e0d67  r2 : 047e0d67  r1 : 00000003  r0 : ffffffea
>> Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>> Control: 10c53c7d  Table: 60004059  DAC: 00000051
>> Register r0 information: non-paged memory
>> Register r1 information: non-paged memory
>> Register r2 information: non-paged memory
>> Register r3 information: non-paged memory
>> Register r4 information: slab kmalloc-512 start c4348200 pointer offset 0
>> size 512
>> Register r5 information: non-paged memory
>> Register r6 information: NULL pointer
>> Register r7 information: slab kmalloc-512 start c4348200 pointer offset 100
>> size 512
>> Register r8 information: non-slab/vmalloc memory
>> Register r9 information: slab kmalloc-512 start c4348200 pointer offset 4
>> size 512
>> Register r10 information: slab kmalloc-512 start c4348200 pointer offset
>> 268 size 512
>> Register r11 information: non-slab/vmalloc memory
>> Register r12 information: NULL pointer
>> Process swapper (pid: 1, stack limit = 0x08d7ca6b)
>> Stack: (0xe0821d30 to 0xe0822000)
>> 1d20:                                     00000000 e0821d98 c4348208 c0c00250
>> 1d40: 00000001 00000000 e0821d98 c0e50508 c4048000 00000000 c406f480 c4048000
>> 1d60: c4341ec0 c0e50508 c4341ec8 c063ce8c c0e593a8 c4048000 c406f4bc c406f480
>> 1d80: c4048000 c04c8bb0 c406f4cc c40704b0 00000000 047e0d67 3b9aca03 c0e5986c
>> 1da0: c0e5931c c0e97230 00000000 c063a618 00000000 c4048000 c0e59858 c40d0a10
>> 1dc0: c0e597f0 c063f80c c0d31830 00000000 00000000 00000000 00000000 00000000
>> 1de0: 00000000 00000000 e0821df4 00000000 00000000 c0ba32fc 00000000 047e0d67
>> 1e00: c40d75d8 00000000 c40d0a10 c0e59804 00000000 00000000 c0d31830 c0c2b5a0
>> 1e20: c0c776b0 c04cc8dc c40d0a10 00000000 c0e59804 c04ca1f4 c40d0a10 c0e59804
>> 1e40: c40d0a10 00000000 00000000 c04ca47c 00000000 c0be8598 c0e94b28 c0e59804
>> 1e60: c40d0a10 00000000 00000000 c04ca658 c40d0a10 c0e59804 c40d0a54 c4048000
>> 1e80: 00000000 c04ca8c4 c0e59804 c04ca834 c406f3c0 c04c8494 c4048000 c406f40c
>> 1ea0: c4070d30 047e0d67 c0e59804 c4341e00 00000000 c406f3c0 c4341e34 c04c959c
>> 1ec0: c0c00c14 c0e6c000 c0e59804 c0d2113c c4070800 00000000 c0e6c000 c04cb598
>> 1ee0: c4048000 c0d2113c c4070800 c010d21c 000003c0 00000000 c407084e c4070800
>> 1f00: c407084d c013e9e0 c0bee764 000000c0 00000000 00000000 c0d004d0 c4048000
>> 1f20: 00000006 00000006 373126cc c407086a 00000000 047e0d67 00000012 047e0d67
>> 1f40: 00000007 c0d42bd8 00000007 c4070800 000000c0 c0d31850 c0d31830 c0d011f4
>> 1f60: 00000006 00000006 00000000 c0d004d0 e0821f6c c0d004d0 00000000 c0e03380
>> 1f80: c0905828 00000000 00000000 00000000 00000000 00000000 00000000 c0905844
>> 1fa0: 00000000 c0905828 00000000 c010014c 00000000 00000000 00000000 00000000
>> 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>> 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
>> Call trace:
>>  cpufreq_online from cpufreq_add_dev+0x84/0x94
>>  cpufreq_add_dev from subsys_interface_register+0xf0/0x108
>>  subsys_interface_register from cpufreq_register_driver+0x13c/0x2e4
>>  cpufreq_register_driver from dt_cpufreq_probe+0xb4/0x380
>>  dt_cpufreq_probe from platform_probe+0x5c/0xb8
>>  platform_probe from really_probe+0xc8/0x2c8
>>  really_probe from __driver_probe_device+0x88/0x19c
>>  __driver_probe_device from driver_probe_device+0x30/0x104
>>  driver_probe_device from __driver_attach+0x90/0x178
>>  __driver_attach from bus_for_each_dev+0x6c/0xb4
>>  bus_for_each_dev from bus_add_driver+0xcc/0x1ec
>>  bus_add_driver from driver_register+0x7c/0x114
>>  driver_register from do_one_initcall+0x40/0x21c
>>  do_one_initcall from kernel_init_freeable+0x194/0x1f8
>>  kernel_init_freeable from kernel_init+0x1c/0x128
>>  kernel_init from ret_from_fork+0x14/0x28
>> Exception stack(0xe0821fb0 to 0xe0821ff8)
>> 1fa0:                                     00000000 00000000 00000000 00000000
>> 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>> 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
>> Code: e3a02000 ebfff87e e3500000 0a000043 (e7f001f2)
>> ---[ end trace 0000000000000000 ]---
>> note: swapper[1] exited with irqs disabled
>> Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
>> ---[ end Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b ]---
>>
>>
>> And this one:
>>
>> Starting kernel ...
>>
>> Booting Linux on physical CPU 0x0
>> Linux version 6.14.0-rc1+ (claudiu at claudiu-X670E-Pro-RS)
>> (arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture
>> 10.3-2021.07 (arm-10.29)) 10.3.1 20210621, GNU ld (GNU Toolchain for the
>> A-profile Architecture 10.3-2021.07 (arm-10.29)) 2.36.1.20210621) #11 Wed
>> Feb 26 11:01:10 EET 2025
>> CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c53c7d
>> CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
>> OF: fdt: Machine model: Microchip SAMA7G5-EK
>> printk: legacy bootconsole [earlycon0] enabled
>> Memory policy: Data cache writeback
>> cma: Reserved 192 MiB at 0x70000000 on node -1
>> Zone ranges:
>>   Normal   [mem 0x0000000060000000-0x000000007fffffff]
>> Movable zone start for each node
>> Early memory node ranges
>>   node   0: [mem 0x0000000060000000-0x000000007fffffff]
>> Initmem setup node 0 [mem 0x0000000060000000-0x000000007fffffff]
>> OF: reserved mem: Reserved memory: No reserved-memory node in the DT
>> CPU: All CPU(s) started in SVC mode.
>> Kernel command line: console=ttyS0,115200 root=/dev/mmcblk1p2
>> rootfstype=ext4 rw rootwait cma=192m atmel.pm_modes=standby,ulp0 earlyprintk
>> printk: log buffer data + meta data: 65536 + 204800 = 270336 bytes
>> Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
>> Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
>> Built 1 zonelists, mobility grouping on.  Total pages: 131072
>> mem auto-init: stack:off, heap alloc:off, heap free:off
>> SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
>> NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
>> Main crystal frequency not set, using approximate value
>> timer_probe: no matching timers found
>> Console: colour dummy device 80x30
>> sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every
>> 21474836475000000ns
>>
>>
>> I suspect parent_data in sama7g5_pmc_setup() need to be initialized with zero.
> 
> With this series I did not see any boot issues with the sama7g54. But
> when doing the DTS and DTSI changes that you made above I did see boot
> issues with the sama7g54.
> 
> It seems that the 2/2 patch also needs to have a similar patch for the
> sama7g54 clock driver.

Would it be better to have this change to all the SoCs and their clock
drivers to match the correct naming? Since this set is mainly to adjust
for sama7d65 and a separate change to sama7g5.c clock driver would be
needed to fix the error that you are seeing above.
> 
> Best,
> Ryan
>>
>> Thank you,
>> Claudiu
>>
>>
>>
> 



From mhklinux at outlook.com  Tue Mar 18 10:45:46 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Tue, 18 Mar 2025 17:45:46 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <Z9msXAClr-vGn3GR@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <Z9msXAClr-vGn3GR@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
Message-ID: <SN6PR02MB415725C0B70BBBE541D6F87DD4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Wei Liu <wei.liu at kernel.org> Sent: Tuesday, March 18, 2025 10:25 AM
> 
> On Mon, Mar 17, 2025 at 11:51:52PM +0000, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday,
> February 26, 2025 3:08 PM
> [...]
> > > +static long
> > > +mshv_vp_ioctl_get_set_state(struct mshv_vp *vp,
> > > +			    struct mshv_get_set_vp_state __user *user_args,
> > > +			    bool is_set)
> > > +{
> > > +	struct mshv_get_set_vp_state args;
> > > +	long ret = 0;
> > > +	union hv_output_get_vp_state vp_state;
> > > +	u32 data_sz;
> > > +	struct hv_vp_state_data state_data = {};
> > > +
> > > +	if (copy_from_user(&args, user_args, sizeof(args)))
> > > +		return -EFAULT;
> > > +
> > > +	if (args.type >= MSHV_VP_STATE_COUNT || mshv_field_nonzero(args, rsvd) ||
> > > +	    !args.buf_sz || !PAGE_ALIGNED(args.buf_sz) ||
> > > +	    !PAGE_ALIGNED(args.buf_ptr))
> > > +		return -EINVAL;
> > > +
> > > +	if (!access_ok((void __user *)args.buf_ptr, args.buf_sz))
> > > +		return -EFAULT;
> > > +
> > > +	switch (args.type) {
> > > +	case MSHV_VP_STATE_LAPIC:
> > > +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
> > > +		data_sz = HV_HYP_PAGE_SIZE;
> > > +		break;
> > > +	case MSHV_VP_STATE_XSAVE:
> >
> > Just FYI, you can put a semicolon after the colon on the above line, which
> > adds a null statement, and then the C compiler will accept the definition
> > of local variable data_sz_64 without needing the odd-looking braces.
> >
> > See https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement/19830820
> >
> 
> This is a rarely seen pattern in the kernel, so I would prefer to keep
> the braces for clarity.
> 
>  $ git grep -A5 -P 'case\s+\w+:;$'
> 
> This shows a few places are using this pattern. But they are not
> declaring variables afterwards.
> 

The braces just looked a little odd, particularly the way they are indented. Another
alternative is to move the variable to function scope, and avoid the issue altogether.
But I'm fine regardless of which approach you take, including keeping it like it is.

> > I learn something new every day! :-)
> >
> 
> Yep, me too.
> 
> Thanks for reviewing the code. Nuno will address the comments. I can fix
> them up.

FYI, I may submit a few more comments on the v6 version of the patches.
If there are changes you want to make based on my comments, I don't care
if you fix up the existing patches, or take them later as follow up patches.
And of course, you may choose to not make changes.

Michael


From Rajaganesh.Rathinasabapathi at amd.com  Tue Mar 18 10:47:29 2025
From: Rajaganesh.Rathinasabapathi at amd.com (Rajaganesh Rathinasabapathi)
Date: Tue, 18 Mar 2025 12:47:29 -0500
Subject: [PATCH v4 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC compatible
Message-ID: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>

Document new AMD Onyx BMC board compatibles

Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 01333ac111fb..98f92c16e342 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -74,6 +74,7 @@ properties:
       - description: AST2600 based boards
         items:
           - enum:
+              - amd,onyx-bmc
               - ampere,mtjefferson-bmc
               - ampere,mtmitchell-bmc
               - aspeed,ast2600-evb
-- 
2.34.1



From Rajaganesh.Rathinasabapathi at amd.com  Tue Mar 18 10:47:30 2025
From: Rajaganesh.Rathinasabapathi at amd.com (Rajaganesh Rathinasabapathi)
Date: Tue, 18 Mar 2025 12:47:30 -0500
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD Onyx Platform
In-Reply-To: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>

Add initial device tree and makefile updates for
AMD Onyx platform.

AMD Onyx platform is an AMD customer reference board with an Aspeed
ast2600 BMC manufactured by AMD.
It describes I2C devices, UARTs, MAC, FMC, etc.
present on AMD Onyx platform.

Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
---
Changes since v1:
* Incorporate review comments
* Update commit message
* Remove vmalloc and earlyprintk

Changes since v2:
* Address review comments
* Fix checkpatch warnings
* Remove bootargs

Changes since v3:
* Fix stdout-path
* Change commit summary
---
 arch/arm/boot/dts/aspeed/Makefile             |   1 +
 .../boot/dts/aspeed/aspeed-bmc-amd-onyx.dts   | 102 ++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..1e6a130377b8 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-ast2600-evb.dtb \
 	aspeed-bmc-amd-daytonax.dtb \
 	aspeed-bmc-amd-ethanolx.dtb \
+	aspeed-bmc-amd-onyx.dtb \
 	aspeed-bmc-ampere-mtjade.dtb \
 	aspeed-bmc-ampere-mtjefferson.dtb \
 	aspeed-bmc-ampere-mtmitchell.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
new file mode 100644
index 000000000000..32509a651183
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2021 - 2024 AMD Inc.
+// Author: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
+
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+	model = "AMD Onyx BMC";
+	compatible = "amd,onyx-bmc", "aspeed,ast2600";
+
+	aliases {
+		serial0 = &uart1;
+		serial4 = &uart5;
+	};
+
+	chosen {
+		stdout-path = "serial4:115200n8";
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+};
+
+&mdio0 {
+	status = "okay";
+	ethphy0: ethernet-phy at 0 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+};
+
+&mac3 {
+	status = "okay";
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rgmii4_default>;
+};
+
+&fmc {
+	status = "okay";
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		status = "okay";
+		#include "openbmc-flash-layout-128.dtsi"
+	};
+};
+
+//Host Console
+&uart1 {
+	status = "okay";
+};
+
+//BMC Console
+&uart5 {
+	status = "okay";
+};
+
+&gpio0 {
+gpio-line-names =
+	/*A0-A7*/	"","","","","","","","",
+	/*B0-B7*/	"","","","","MON_POST_COMPLETE","P0_PRESENT_L","","",
+	/*C0-C7*/	"","","","","","","","",
+	/*D0-D7*/	"","","","","","","","",
+	/*E0-E7*/	"","","","","","","","",
+	/*F0-F7*/	"","","","","","","","",
+	/*G0-G7*/	"","","","","","","","",
+	/*H0-H7*/	"","ASSERT_WARM_RST_BTN_L","ASSERT_SOC_RST_BTN_L","","","","","",
+	/*I0-I7*/	"","","","","","","","P0_I3C_APML_ALERT_L",
+	/*J0-J7*/	"","","","","","","","",
+	/*K0-K7*/	"","","","","","","","",
+	/*L0-L7*/	"","","","","","","","",
+	/*M0-M7*/	"","","","","","","","",
+	/*N0-N7*/	"","","","","","","PSP_SOFT_FUSE_NOTIFY","ASSERT_BMC_READY",
+	/*O0-O7*/	"","","HDT_SEL","HDT_XTRIG5","HDT_XTRIG6","JTAG_TRST_N","","",
+	/*P0-P7*/	"MON_RST_BTN_L","ASSERT_RST_BTN_L","MON_PWR_BTN_L","ASSERT_PWR_BTN_L",
+					"HPM_FPGA_LOCKOUT","ASSERT_NMI_BTN_L","MON_PWR_GOOD","",
+	/*Q0-Q7*/	"","","HDT_DBREQ_L","","BIOS_SPD_MUX_CTRL_RELEASED_L","","","",
+	/*R0-R7*/	"","","","","","","","",
+	/*S0-S7*/	"","","","","","","P0_DIMM_AF_ERROR","P0_DIMM_GL_ERROR",
+	/*T0-T7*/	"","","","","","","","",
+	/*U0-U7*/	"","","","","","","","",
+	/*V0-V7*/	"","","","","","","","",
+	/*W0-W7*/	"","","","","","","","",
+	/*X0-X7*/	"","","","","","","","",
+	/*Y0-Y7*/	"","","","","","","","",
+	/*Z0-Z7*/	"","","","","","","","";
+};
+
+&i2c7 {
+	status = "okay";
+	mbeeprom at 50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+	};
+};
-- 
2.34.1



From robh at kernel.org  Tue Mar 18 10:40:00 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 12:40:00 -0500
Subject: [PATCH v2 02/10] dt-bindings: soc: qcom: qcom,rpm: add missing
 clock/-names properties
In-Reply-To: <20250318-fix-nexus-4-v2-2-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-2-bcedd1406790@oss.qualcomm.com>
Message-ID: <174231959987.3278245.15510321850308863529.robh@kernel.org>


On Tue, 18 Mar 2025 15:21:55 +0200, Dmitry Baryshkov wrote:
> Qualcomm MSM8660 and IPQ0864 platforms use additional clock for the RPM
> device. Document it in the schema.
> 
> Fixes: aa0c4b815045 ("mfd: devicetree: bindings: Add Qualcomm RPM DT binding")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/soc/qcom/qcom,rpm.yaml | 7 +++++++
>  1 file changed, 7 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 18 10:40:30 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 12:40:30 -0500
Subject: [PATCH v2 03/10] dt-bindings: arm:
 arm,coresight-static-replicator: add optional clocks
In-Reply-To: <20250318-fix-nexus-4-v2-3-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-3-bcedd1406790@oss.qualcomm.com>
Message-ID: <174231962960.3279035.17499878913808619235.robh@kernel.org>


On Tue, 18 Mar 2025 15:21:56 +0200, Dmitry Baryshkov wrote:
> As most other CoreSight devices the replicator can use either of the
> optional clocks. Document those optional clocks in the schema.
> Additionally document the one-off case of Zynq-7000 platforms which uses
> apb_pclk and two additional debug clocks.
> 
> Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  .../bindings/arm/arm,coresight-static-replicator.yaml       | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 18 10:42:04 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 12:42:04 -0500
Subject: [PATCH v2 04/10] dt-bindings: mfd: syscon: add
 qcom,apq8064-sps-sic
In-Reply-To: <20250318-fix-nexus-4-v2-4-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-4-bcedd1406790@oss.qualcomm.com>
Message-ID: <174231972363.3281332.10722530407269396405.robh@kernel.org>


On Tue, 18 Mar 2025 15:21:57 +0200, Dmitry Baryshkov wrote:
> Add compat for Smart Peripheral System (SPS) Interrupt Controller (SIC)
> present on Qualcomm APQ8064 SoC.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Tue Mar 18 10:42:16 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 12:42:16 -0500
Subject: [PATCH v2 05/10] dt-bindings: mfd: syscon: add
 qcom,apq8064-mmss-sfpb
In-Reply-To: <20250318-fix-nexus-4-v2-5-bcedd1406790@oss.qualcomm.com>
References: <20250318-fix-nexus-4-v2-0-bcedd1406790@oss.qualcomm.com>
 <20250318-fix-nexus-4-v2-5-bcedd1406790@oss.qualcomm.com>
Message-ID: <174231973562.3281729.13844213824981860585.robh@kernel.org>


On Tue, 18 Mar 2025 15:21:58 +0200, Dmitry Baryshkov wrote:
> Add compat string for Qualcomm MultiMedia SubSystem System FPB.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From horms at kernel.org  Tue Mar 18 10:50:31 2025
From: horms at kernel.org (Simon Horman)
Date: Tue, 18 Mar 2025 17:50:31 +0000
Subject: [PATCH net-next 0/3] Clean up deprecated PCI calls
In-Reply-To: <20250313161422.97174-2-phasta@kernel.org>
References: <20250313161422.97174-2-phasta@kernel.org>
Message-ID: <20250318175031.GT688833@kernel.org>

On Thu, Mar 13, 2025 at 05:14:20PM +0100, Philipp Stanner wrote:
> Spiritual successor of this older series, of which one patch has already
> been merged [1]
> 
> P.
> 
> [1] https://lore.kernel.org/netdev/20250226085208.97891-1-phasta at kernel.org/
> 
> Philipp Stanner (3):
>   stmmac: loongson: Remove surplus loop
>   stmmac: Remove pcim_* functions for driver detach
>   stmmac: Replace deprecated PCI functions

Hi Philipp,

Unfortunately this series did not apply cleanly to net-next when the CI ran.
Please rebase and repost, including Jacob's tags.

-- 
pw-bot: changes-requested


From namhyung at kernel.org  Tue Mar 18 11:02:16 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Tue, 18 Mar 2025 11:02:16 -0700
Subject: [PATCH v2] perf libunwind: Fixup conversion
 perf_sample->user_regs to a pointer
In-Reply-To: <20250313033121.758978-1-irogers@google.com>
References: <20250313033121.758978-1-irogers@google.com>
Message-ID: <174232093676.2542685.15670125863336766245.b4-ty@kernel.org>

On Wed, 12 Mar 2025 20:31:21 -0700, Ian Rogers wrote:
> The dc6d2bc2d893a878 ("perf sample: Make user_regs and intr_regs optional") misses
> the changes to a file, resulting in this problem:
> 
>   $ make LIBUNWIND=1 -C tools/perf O=/tmp/build/perf-tools-next install-bin
>   <SNIP>
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind-local.o
>     CC      /tmp/build/perf-tools-next/util/unwind-libunwind.o
>   <SNIP>
>   util/unwind-libunwind-local.c: In function ?access_mem?:
>   util/unwind-libunwind-local.c:582:56: error: ?ui->sample->user_regs? is a pointer; did you mean to use ?->??
>     582 |         if (__write || !stack || !ui->sample->user_regs.regs) {
>         |                                                        ^
>         |                                                        ->
>   util/unwind-libunwind-local.c:587:38: error: passing argument 2 of ?perf_reg_value? from incompatible pointer type [-Wincompatible-pointer-types]
>     587 |         ret = perf_reg_value(&start, &ui->sample->user_regs,
>         |                                      ^~~~~~~~~~~~~~~~~~~~~~
>         |                                      |
>         |                                      struct regs_dump **
> <SNIP>
>   ? [acme at toolbox perf-tools-next]$ git bisect bad
>   dc6d2bc2d893a878e7b58578ff01b4738708deb4 is the first bad commit
>   commit dc6d2bc2d893a878e7b58578ff01b4738708deb4 (HEAD)
>   Author: Ian Rogers <irogers at google.com>
>   Date:   Mon Jan 13 11:43:45 2025 -0800
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From mhklinux at outlook.com  Tue Mar 18 11:01:36 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Tue, 18 Mar 2025 18:01:36 +0000
Subject: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
In-Reply-To: <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157E630EC520DC487139372D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
> 
> Introduce hv_status_printk() macros as a convenience to log hypercall
> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
> value and also as a string, which saves some time while debugging.
> 
> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
> use it for hv_result_to_string() and hv_result_to_errno().
> 
> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
> irqdomain.c hypercalls to aid debugging in the root partition.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> ---
>  arch/x86/hyperv/irqdomain.c    |   6 +-
>  drivers/hv/hv_common.c         | 129 ++++++++++++++++++++++++---------
>  drivers/hv/hv_proc.c           |  10 +--
>  drivers/iommu/hyperv-iommu.c   |   4 +-
>  include/asm-generic/mshyperv.h |  13 ++++
>  5 files changed, 118 insertions(+), 44 deletions(-)
>

[snip]
 
> +
> +struct hv_status_info {
> +	char *string;
> +	int errno;
> +	u16 code;
> +};
> +
> +/*
> + * Note on the errno mappings:
> + * A failed hypercall is usually only recoverable (or loggable) near
> + * the call site where the HV_STATUS_* code is known. So the errno
> + * it gets converted to is not too useful further up the stack.
> + * Provide a few mappings that could be useful, and revert to -EIO
> + * as a fallback.
> + */
> +static const struct hv_status_info hv_status_infos[] = {
> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> +	_STATUS_INFO(HV_STATUS_SUCCESS,				0),
> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARAMETER,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_ACCESS_DENIED,			-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_OPERATION_DENIED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY,		-EIO),
> +	_STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE,	-EIO),
> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY,		-ENOMEM),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_VP_INDEX,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_NOT_FOUND,			-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PORT_ID,			-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS,		-EIO),
> +	_STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_VP_STATE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_NO_RESOURCES,			-EIO),
> +	_STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED,	-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_OPERATION_FAILED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_TIME_OUT,			-EIO),
> +	_STATUS_INFO(HV_STATUS_CALL_PENDING,			-EIO),
> +	_STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,		-EIO),
> +#undef _STATUS_INFO
> +};
> +
> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> +{
> +	int i;
> +	u16 code = hv_result(hv_status);
> +
> +	for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> +		const struct hv_status_info *info = &hv_status_infos[i];
> +
> +		if (info->code == code)
> +			return info;
> +	}
> +
> +	return NULL;
> +}
> +
> +/* Convert a hypercall result into a linux-friendly error code. */
> +int hv_result_to_errno(u64 status)
> +{
> +	const struct hv_status_info *info;
> +
> +	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> +	if (unlikely(status == U64_MAX))
> +		return -EOPNOTSUPP;
> +
> +	info = find_hv_status_info(status);
> +	if (info)
> +		return info->errno;
> +
> +	return -EIO;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> +
> +const char *hv_result_to_string(u64 status)
> +{
> +	const struct hv_status_info *info;
> +
> +	if (unlikely(status == U64_MAX))
> +		return "Hypercall page missing!";
> +
> +	info = find_hv_status_info(status);
> +	if (info)
> +		return info->string;
> +
> +	return "Unknown";
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_string);

I think the table-driven approach worked out pretty well. But here's a version that
is even more compact, and avoids the duplicate testing for U64_MAX and having
to special case both U64_MAX and not finding a match:

+
+struct hv_status_info {
+	char *string;
+	int errno;
+	int code;
+};
+
+/*
+ * Note on the errno mappings:
+ * A failed hypercall is usually only recoverable (or loggable) near
+ * the call site where the HV_STATUS_* code is known. So the errno
+ * it gets converted to is not too useful further up the stack.
+ * Provide a few mappings that could be useful, and revert to -EIO
+ * as a fallback.
+ */
+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
+	_STATUS_INFO(HV_STATUS_SUCCESS,				0),
+	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PARAMETER,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_ACCESS_DENIED,			-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE,		-EIO),
+	_STATUS_INFO(HV_STATUS_OPERATION_DENIED,		-EIO),
+	_STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY,		-EIO),
+	_STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE,	-EIO),
+	_STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY,		-ENOMEM),
+	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_VP_INDEX,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_NOT_FOUND,			-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_PORT_ID,			-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS,		-EIO),
+	_STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_VP_STATE,		-EIO),
+	_STATUS_INFO(HV_STATUS_NO_RESOURCES,			-EIO),
+	_STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED,	-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EINVAL),
+	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EIO),
+	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EIO),
+	_STATUS_INFO(HV_STATUS_OPERATION_FAILED,		-EIO),
+	_STATUS_INFO(HV_STATUS_TIME_OUT,			-EIO),
+	_STATUS_INFO(HV_STATUS_CALL_PENDING,			-EIO),
+	_STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,		-EIO),
+	{"Hypercall page missing!", -EOPNOTSUPP, -1}, /* code -1 is "no hypercall page" */
+	{"Unknown", -EIO, -2},  /* code -2 is "Not found" entry; must be last */
+#undef _STATUS_INFO
+};
+
+static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
+{
+	int i, code;
+	const struct hv_status_info *info;
+
+	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
+	if (unlikely(hv_status == U64_MAX))
+		code = -1;
+	else
+		code = hv_result(hv_status);
+
+	for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+		info = &hv_status_infos[i];
+		if (info->code == code || info->code == -2)
+			break;
+	}
+
+	return info;
+}
+
+/* Convert a hypercall result into a linux-friendly error code. */
+int hv_result_to_errno(u64 status)
+{
+	return find_hv_status_info(status)->errno;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_errno);
+
+const char *hv_result_to_string(u64 status)
+{
+	return find_hv_status_info(status)->string;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_string);

It could be even more compact by exporting find_hv_status_info() and
letting  hv_result_to_errno() and hv_result_to_string() be #defines to
find_hv_status_info()->errno and find_hv_status_info()->string,
respectively.

Note that in struct hv_status_info, the "code" field is defined as "int"
instead of "u16" so that it can contain sentinel values -1 and -2 that
won't overlap with HV_STATUS_* values.

Anyway, just a suggestion. The current code works from what I can
see.

Michael


From leo.yan at arm.com  Tue Mar 18 11:02:40 2025
From: leo.yan at arm.com (Leo Yan)
Date: Tue, 18 Mar 2025 18:02:40 +0000
Subject: [PATCH 2/7] perf annotate: Advance the mem_ref check to
 mov__parse()
In-Reply-To: <20250314162137.528204-3-lihuafei1@huawei.com>
References: <20250314162137.528204-1-lihuafei1@huawei.com>
 <20250314162137.528204-3-lihuafei1@huawei.com>
Message-ID: <20250318180240.GB2860028@e132581.arm.com>

On Sat, Mar 15, 2025 at 12:21:32AM +0800, Li Huafei wrote:
> Advance the mem_ref check on x86 to mov__parse(), along with the
> multi_reg check, to make annotate_get_insn_location() more concise.
> 
> Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
> ---
>  tools/perf/util/annotate.c | 9 ++++-----
>  tools/perf/util/disasm.c   | 8 ++++++++
>  2 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index 31bb326b07a6..860ea6c72411 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -2442,18 +2442,17 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
>  				continue;
>  		}
>  
> +		op_loc->mem_ref = mem_ref;
> +		op_loc->multi_regs = multi_regs;
> +
>  		/*
>  		 * For powerpc, call get_powerpc_regs function which extracts the
>  		 * required fields for op_loc, ie reg1, reg2, offset from the
>  		 * raw instruction.
>  		 */
>  		if (arch__is(arch, "powerpc")) {
> -			op_loc->mem_ref = mem_ref;
> -			op_loc->multi_regs = multi_regs;
>  			get_powerpc_regs(dl->raw.raw_insn, !i, op_loc);
> -		} else if (strchr(insn_str, arch->objdump.memory_ref_char)) {
> -			op_loc->mem_ref = true;
> -			op_loc->multi_regs = multi_regs;
> +		} else if (mem_ref) {
>  			extract_reg_offset(arch, insn_str, op_loc);
>  		} else {
>  			char *s, *p = NULL;
> diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
> index 50c5c206b70e..d91526cff9df 100644
> --- a/tools/perf/util/disasm.c
> +++ b/tools/perf/util/disasm.c
> @@ -607,6 +607,12 @@ static bool check_multi_regs(struct arch *arch, const char *op)
>  	return count > 1;
>  }
>  
> +/* Check whether the operand accesses memory. */
> +static bool check_memory_ref(struct arch *arch, const char *op)
> +{
> +	return strchr(op, arch->objdump.memory_ref_char) != NULL;
> +}

This patch looks fine for me.

However, I did not find the 'memory_ref_char' field is set for Arm64.
Later patches even remove the condition checking for mem_ref() and
unconditionally invoke extract_reg_offset().

This is a logic change for me.  Shouldn't the register offset be
extracted only for memory access instructions?


>  static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,
>  		struct disasm_line *dl __maybe_unused)
>  {
> @@ -635,6 +641,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy
>  	if (ops->source.raw == NULL)
>  		return -1;
>  
> +	ops->source.mem_ref = check_memory_ref(arch, ops->source.raw);
>  	ops->source.multi_regs = check_multi_regs(arch, ops->source.raw);
>  
>  	target = skip_spaces(++s);
> @@ -657,6 +664,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy
>  	if (ops->target.raw == NULL)
>  		goto out_free_source;
>  
> +	ops->target.mem_ref = check_memory_ref(arch, ops->target.raw);
>  	ops->target.multi_regs = check_multi_regs(arch, ops->target.raw);
>  
>  	if (comment == NULL)
> 
> -- 
> 2.25.1
> 


From krzk at kernel.org  Tue Mar 18 11:10:58 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 19:10:58 +0100
Subject: [PATCH v4 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <cebf6611-4a9f-48fa-9226-e4a559e75ab9@kernel.org>

On 18/03/2025 18:47, Rajaganesh Rathinasabapathi wrote:
> Document new AMD Onyx BMC board compatibles
> 
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---
>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>  1 file changed, 1 insertion(+)

Can you slow down and read submitting patches before posting or at least
get someone experienced in AMD to help you?

<form letter>
This is a friendly reminder during the review process.

It looks like you received a tag and forgot to add it.

If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions
of patchset, under or above your Signed-off-by tag, unless patch changed
significantly (e.g. new properties added to the DT bindings). Tag is
"received", when provided in a message replied to you on the mailing
list. Tools like b4 can help here. However, there's no need to repost
patches *only* to add the tags. The upstream maintainer will do that for
tags received on the version they apply.

Please read:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577

If a tag was not added on purpose, please state why and what changed.
</form letter>

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 18 11:14:35 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 19:14:35 +0100
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD
 Onyx Platform
In-Reply-To: <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <af75c352-0010-4c58-b8bc-ac0d02337d1a@kernel.org>

On 18/03/2025 18:47, Rajaganesh Rathinasabapathi wrote:
> Add initial device tree and makefile updates for
> AMD Onyx platform.
> 
> AMD Onyx platform is an AMD customer reference board with an Aspeed
> ast2600 BMC manufactured by AMD.
> It describes I2C devices, UARTs, MAC, FMC, etc.
> present on AMD Onyx platform.
> 
> Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---
> Changes since v1:
> * Incorporate review comments

Which ones? I do not see my comments addressed and if you do not list
them, I treat it as a clear sign you do not care.

> * Update commit message
> * Remove vmalloc and earlyprintk
> 
> Changes since v2:
> * Address review comments

Which ones? This has to be specific

> * Fix checkpatch warnings
> * Remove bootargs
> 
> Changes since v3:
> * Fix stdout-path
> * Change commit summary
> ---
>  arch/arm/boot/dts/aspeed/Makefile             |   1 +
>  .../boot/dts/aspeed/aspeed-bmc-amd-onyx.dts   | 102 ++++++++++++++++++
>  2 files changed, 103 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
> 
> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
> index 2e5f4833a073..1e6a130377b8 100644
> --- a/arch/arm/boot/dts/aspeed/Makefile
> +++ b/arch/arm/boot/dts/aspeed/Makefile
> @@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>  	aspeed-ast2600-evb.dtb \
>  	aspeed-bmc-amd-daytonax.dtb \
>  	aspeed-bmc-amd-ethanolx.dtb \
> +	aspeed-bmc-amd-onyx.dtb \
>  	aspeed-bmc-ampere-mtjade.dtb \
>  	aspeed-bmc-ampere-mtjefferson.dtb \
>  	aspeed-bmc-ampere-mtmitchell.dtb \
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
> new file mode 100644
> index 000000000000..32509a651183
> --- /dev/null
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
> @@ -0,0 +1,102 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright (c) 2021 - 2024 AMD Inc.
> +// Author: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
> +
> +/dts-v1/;
> +
> +#include "aspeed-g6.dtsi"
> +#include <dt-bindings/gpio/aspeed-gpio.h>
> +
> +/ {
> +	model = "AMD Onyx BMC";
> +	compatible = "amd,onyx-bmc", "aspeed,ast2600";
> +
> +	aliases {
> +		serial0 = &uart1;
> +		serial4 = &uart5;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial4:115200n8";
> +	};
> +
> +	memory at 80000000 {
> +		device_type = "memory";
> +		reg = <0x80000000 0x80000000>;
> +	};
> +
> +};
How did you address comment here from v1 which was responded with "ACK"?

What else what exactly fixed and what not?

Best regards,
Krzysztof


From anarsoul at gmail.com  Tue Mar 18 11:18:51 2025
From: anarsoul at gmail.com (Vasily Khoruzhick)
Date: Tue, 18 Mar 2025 11:18:51 -0700
Subject: [PATCH] clk: rockchip: rk3568: Add PLL rate for 33.3MHz
Message-ID: <20250318181930.1178256-1-anarsoul@gmail.com>

Add PLL rate for 33.3 MHz to allow BTT HDMI5 screen to run at its native
mode of 800x480

Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
---
 drivers/clk/rockchip/clk-rk3568.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
index 53d10b1c627b..1c73e18a9862 100644
--- a/drivers/clk/rockchip/clk-rk3568.c
+++ b/drivers/clk/rockchip/clk-rk3568.c
@@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
 	RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0),
 	RK3036_PLL_RATE(78750000, 4, 315, 6, 4, 1, 0),
 	RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0),
+	RK3036_PLL_RATE(33300000, 4, 111, 5, 4, 1, 0),
 	{ /* sentinel */ },
 };
 
-- 
2.49.0



From andrew at lunn.ch  Tue Mar 18 11:33:09 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 18 Mar 2025 19:33:09 +0100
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD
 Onyx Platform
In-Reply-To: <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <472a4f78-24f4-4bfd-bf99-8b1194bfe8f0@lunn.ch>

> +&mac3 {
> +	status = "okay";
> +	phy-mode = "rgmii";

Still broken. And it appears you are just ignoring my comments.

Sorry, but:

NACK

There is a discussion here:

https://lore.kernel.org/lkml/20250317025922.1526937-1-jacky_chou at aspeedtech.com/

There is also IBM in a similar situation to you:

https://lore.kernel.org/linux-arm-kernel/20250108163640.1374680-6-ninad at linux.ibm.com/

and NVIDIA

https://lore.kernel.org/lkml/20250312045802.4115029-1-wthai at nvidia.com/

Could i suggest you, IBM and NVIDIA work together to get Aspeed to fix
this.

	Andrew


From nicolas at ndufresne.ca  Tue Mar 18 11:38:02 2025
From: nicolas at ndufresne.ca (Nicolas Dufresne)
Date: Tue, 18 Mar 2025 14:38:02 -0400
Subject: [PATCH v4 0/6] TEE subsystem for restricted dma-buf allocations
In-Reply-To: <Z8avsigZJ4vqmiA4@sumit-X1>
References: <CAHUa44G9hw-z6wzxg=HkVAxPKEW1yES5JTEqRWMvJUJAtcUDkQ@mail.gmail.com>
	 <CAPj87rPHnME5Osgnf5-FSAu22mDpLj=dzvhi_NqEcOwr1ThgGw@mail.gmail.com>
	 <CAHUa44Gs0D1fBD0=+EDgcQUMeDv4knci9trUkYEc1J98qFV7HQ@mail.gmail.com>
	 <CAFA6WYOuTwRPEh3L7+hMyARB_E73xmp+OwhKyS-r4+ryS7=9sw@mail.gmail.com>
	 <20250214164856.0d2ead8a@collabora.com>
	 <CAFA6WYPc6EHQwcPuMZRm4C1P6SoDrCzEPUmju_meupB6NXQ1sg@mail.gmail.com>
	 <CAPj87rN-OYTzh5=Gdv619UQD5=x=U6Yt=uV4N1kCs4Zao4RVAg@mail.gmail.com>
	 <CAFA6WYMLLLSuz3y5J+DuRFAGrmwpZoWax5sasfAUhXoQXmrNNA@mail.gmail.com>
	 <CAPj87rN7J6u9NsviAdw8=OenEYc8t719Lds6u6-BhFKrtkLZ-A@mail.gmail.com>
	 <CAHUa44FkG1NAWpoW8UVBywv44XW_mjAJa32PcC9mcmiOLdiRqw@mail.gmail.com>
	 <Z8avsigZJ4vqmiA4@sumit-X1>
Message-ID: <32c29526416c07c37819aedabcbf1e562ee98bf2.camel@ndufresne.ca>

Le mardi 04 mars 2025 ? 13:15 +0530, Sumit Garg a ?crit?:
> On Tue, Mar 04, 2025 at 08:17:23AM +0100, Jens Wiklander wrote:
> > Hi Daniel,
> > 
> > On Fri, Feb 21, 2025 at 3:12?PM Daniel Stone <daniel at fooishbar.org> wrote:
> > > 
> > > Hi Sumit,
> > > 
> > > On Fri, 21 Feb 2025 at 11:24, Sumit Garg <sumit.garg at linaro.org> wrote:
> > > > On Tue, 18 Feb 2025 at 21:52, Daniel Stone <daniel at fooishbar.org> wrote:
> > > > > dma-heaps was created to solve the problem of having too many
> > > > > 'allocate $n bytes from $specialplace' uAPIs. The proliferation was
> > > > > painful and making it difficult for userspace to do what it needed to
> > > > > do. Userspace doesn't _yet_ make full use of it, but the solution is
> > > > > to make userspace make full use of it, not to go create entirely
> > > > > separate allocation paths for unclear reasons.
> > > > > 
> > > > > Besides, I'm writing this from a platform that implements SVP not via
> > > > > TEE. I've worked on platforms which implement SVP without any TEE,
> > > > > where the TEE implementation would be at best a no-op stub, and at
> > > > > worst flat-out impossible.
> > > > 
> > > > Can you elaborate the non-TEE use-case for Secure Video Path (SVP) a
> > > > bit more? As to how the protected/encrypted media content pipeline
> > > > works? Which architecture support does your use-case require? Is there
> > > > any higher privileged level firmware interaction required to perform
> > > > media content decryption into restricted memory? Do you plan to
> > > > upstream corresponding support in near future?
> > > 
> > > You can see the MTK SVP patches on list which use the MTK SMC to mediate it.
> > > 
> > > There are TI Jacinto platforms which implement a 'secure' area
> > > configured statically by (IIRC) BL2, with static permissions defined
> > > for each AXI endpoint, e.g. CPU write + codec RW + dispc read. I've
> > > heard of another SoC vendor doing the same, but I don't think I can
> > > share those details. There is no TEE interaction.
> > > 
> > > I'm writing this message from an AMD laptop which implements
> > > restricted content paths outside of TEE. I don't have the full picture
> > > of how SVP is implemented on AMD systems, but I do know that I don't
> > > have any TEE devices exposed.
> > > 
> > > > Let me try to elaborate on the Secure Video Path (SVP) flow requiring
> > > > a TEE implementation (in general terms a higher privileged firmware
> > > > managing the pipeline as the kernel/user-space has no access
> > > > permissions to the plain text media content):
> > > > 
> > > > - [...]
> > > 
> > > Yeah, I totally understand the TEE usecase. I think that TEE is a good
> > > design to implement this. I think that TEE should be used for SVP
> > > where it makes sense.
> > > 
> > > Please understand that I am _not_ arguing that no-one should use TEE for SVP!
> > > 
> > > > > So, again, let's
> > > > > please turn this around: _why_ TEE? Who benefits from exposing this as
> > > > > completely separate to the more generic uAPI that we specifically
> > > > > designed to handle things like this?
> > > > 
> > > > The bridging between DMA heaps and TEE would still require user-space
> > > > to perform an IOCTL into TEE to register the DMA-bufs as you can see
> > > > here [1]. Then it will rather be two handles for user-space to manage.
> > > 
> > > Yes, the decoder would need to do this. That's common though: if you
> > > want to share a buffer between V4L2 and DRM, you have three handles:
> > > the V4L2 buffer handle, the DRM GEM handle, and the dmabuf you use to
> > > bridge the two.
> > > 
> > > > Similarly during restricted memory allocation/free we need another
> > > > glue layer under DMA heaps to TEE subsystem.
> > > 
> > > Yep.
> > > 
> > > > The reason is simply which has been iterated over many times in the
> > > > past threads that:
> > > > 
> > > > ??? "If user-space has to interact with a TEE device for SVP use-case
> > > > then why it's not better to ask TEE to allocate restricted DMA-bufs
> > > > too"
> > > 
> > > The first word in your proposition is load-bearing.
> > > 
> > > Build out the usecase a little more here. You have a DRMed video
> > > stream coming in, which you need to decode (involving TEE for this
> > > usecase). You get a dmabuf handle to the decoded frame. You need to
> > > pass the dmabuf across to the Wayland compositor. The compositor needs
> > > to pass it to EGL/Vulkan to import and do composition, which in turn
> > > passes it to the GPU DRM driver. The output of the composition is in
> > > turn shared between the GPU DRM driver and the separate KMS DRM
> > > driver, with the involvement of GBM.
> > > 
> > > For the platforms I'm interested in, the GPU DRM driver needs to
> > > switch into protected mode, which has no involvement at all with TEE -
> > > it's architecturally impossible to have TEE involved without moving
> > > most of the GPU driver into TEE and destroying performance. The
> > > display hardware also needs to engage protected mode, which again has
> > > no involvement with TEE and again would need to have half the driver
> > > moved into TEE for no benefit in order to do so. The Wayland
> > > compositor also has no interest in TEE: it tells the GPU DRM driver
> > > about the protected status of its buffers, and that's it.
> > > 
> > > What these components _are_ opinionated about, is the way buffers are
> > > allocated and managed. We built out dmabuf modifiers for this usecase,
> > > and we have a good negotiation protocol around that. We also really
> > > care about buffer placement in some usecases - e.g. some display/codec
> > > hardware requires buffers to be sourced from contiguous memory, other
> > > hardware needs to know that when it shares buffers with another
> > > device, it needs to place the buffers outside of inaccessible/slow
> > > local RAM. So we built out dma-heaps, so every part of the component
> > > in the stack can communicate their buffer-placement needs in the same
> > > way as we do modifiers, and negotiate an acceptable allocation.
> > > 
> > > That's my starting point for this discussion. We have a mechanism to
> > > deal with the fact that buffers need to be shared between different IP
> > > blocks which have their own constraints on buffer placement, avoiding
> > > the current problem of having every subsystem reinvent their own
> > > allocation uAPI which was burying us in impedance mismatch and
> > > confusion. That mechanism is dma-heaps. It seems like your starting
> > > point from this discussion is that you've implemented a TEE-centric
> > > design for SVP, and so all of userspace should bypass our existing
> > > cross-subsystem special-purpose allocation mechanism, and write
> > > specifically to one implementation. I believe that is a massive step
> > > backwards and an immediate introduction of technical debt.
> > > 
> > > Again, having an implementation of SVP via TEE makes a huge amount of
> > > sense. Having _most_ SVP implementations via TEE still makes a lot of
> > > sense. Having _all_ SVP implementations eventually be via TEE would
> > > still make sense. But even if we were at that point - which we aren't
> > > - it still doesn't justify telling userspace 'use the generic dma-heap
> > > uAPI for every device-specific allocation constraint, apart from SVP
> > > which has a completely different way to allocate some bytes'.
> > 
> > I must admit that I don't see how this makes a significant difference,
> > but then I haven't hacked much in the stacks you're talking about, so
> > I'm going to take your word for it.
> > 
> > I've experimented with providing a dma-heap replacing the TEE API. The
> > implementation is more complex than I first anticipated, adding about
> > 400 lines to the patch set.
> 
> I did anticipated this but let's give it a try and see if DMA heaps
> really adds any value from user-space point of view. If it does then it
> will be worth the maintenence overhead.
> 
> > From user space, it looks like another
> > dma-heap. I'm using the names you gave earlier,
> > protected,secure-video, protected,trusted-ui, and
> > protected,secure-video-record. However, I wonder if we shouldn't use
> > "restricted" instead of "protected" since we had agreed to call it
> > restricted memory earlier.
> 
> Let's stick with "restricted" memory buffer references only.

Until now, we didn't have a standard to balance our naming choice, we
simply wanted to move away from "secure" which didn't mean much, and
restricted met our needs. I think the discussion is worth having again,
now that there is a standard that decided toward "protected". Matchcing
the Khronos standard means reducing a lot of confusion.

https://docs.vulkan.org/guide/latest/protected.html

regards,
Nicolas


From robin.murphy at arm.com  Tue Mar 18 11:40:20 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 18 Mar 2025 18:40:20 +0000
Subject: [PATCH] iommu/rockchip: Add flush_iotlb_all ops
In-Reply-To: <20250318152049.14781-1-detlev.casanova@collabora.com>
References: <20250318152049.14781-1-detlev.casanova@collabora.com>
Message-ID: <9bd56bd6-ce7d-495f-9bb3-ce7f07975f62@arm.com>

On 18/03/2025 3:20 pm, Detlev Casanova wrote:
> From: Jonas Karlman <jonas at kwiboo.se>
> 
> On some Rockchip cores (like the vdpu34x video decoder), the IOMMU device
> is inside the the device that uses it.
> 
> The IOMMU device can still be driven by the iommu driver, but when an
> error occurs in the main device (e.g. a decoding error that resets the
> decoder), the IOMMU device will also be reseted.
> In such situation, the IOMMU driver and the hardware are out of sync and
> IOMMU errors will start popping up.
> 
> To avoid that, add a flush_iotlb_all function that will let the main drivers
> (e.g. rkvdec) tell the IOMMU driver to write all its cached mappings into
> the IOMMU hardware when such an error occured.

Eww, this is the exact opposite of what flush_iotlb_all represents, and 
I really don't like the idea of the public IOMMU API being abused for 
inter-driver communication. Please have some kind of proper reset 
notifier mechanism - in fact with runtime PM could you not already 
invoke a suspend/resume cycle via the device links? AFAICS it would also 
work to attach to a different domain then switch back again. Or at worst 
just export a public interface for the other driver to invoke 
rk_iommu_resume() directly. Just don't hide it in something completely 
inappropriate - I mean, consider if someone wants to implement 
IOMMU_CAP_DEFERRED_FLUSH support here in future...

Thanks,
Robin.

> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> Signed-off-by: Detlev Casanova <detlev.casanova at collabora.com>
> ---
>   drivers/iommu/rockchip-iommu.c | 45 ++++++++++++++++++++++++++++++----
>   1 file changed, 40 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
> index 323cc665c357..7086716cb8fc 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -899,6 +899,40 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
>   	return unmap_size;
>   }
>   
> +static void rk_iommu_flush_iotlb_all(struct iommu_domain *domain)
> +{
> +	struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
> +	struct list_head *pos;
> +	unsigned long flags;
> +	int i, ret;
> +
> +	spin_lock_irqsave(&rk_domain->iommus_lock, flags);
> +	list_for_each(pos, &rk_domain->iommus) {
> +		struct rk_iommu *iommu = list_entry(pos, struct rk_iommu, node);
> +
> +		ret = pm_runtime_get_if_in_use(iommu->dev);
> +		if (!ret || WARN_ON_ONCE(ret < 0))
> +			continue;
> +
> +		if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
> +			continue;
> +
> +		rk_iommu_enable_stall(iommu);
> +		for (i = 0; i < iommu->num_mmu; i++) {
> +			rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
> +				rk_ops->mk_dtentries(rk_domain->dt_dma));
> +			rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
> +			rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
> +		}
> +		rk_iommu_enable_paging(iommu);
> +		rk_iommu_disable_stall(iommu);
> +
> +		clk_bulk_disable(iommu->num_clocks, iommu->clocks);
> +		pm_runtime_put(iommu->dev);
> +	}
> +	spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
> +}
> +
>   static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
>   {
>   	struct rk_iommudata *data = dev_iommu_priv_get(dev);
> @@ -1172,11 +1206,12 @@ static const struct iommu_ops rk_iommu_ops = {
>   	.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
>   	.of_xlate = rk_iommu_of_xlate,
>   	.default_domain_ops = &(const struct iommu_domain_ops) {
> -		.attach_dev	= rk_iommu_attach_device,
> -		.map_pages	= rk_iommu_map,
> -		.unmap_pages	= rk_iommu_unmap,
> -		.iova_to_phys	= rk_iommu_iova_to_phys,
> -		.free		= rk_iommu_domain_free,
> +		.attach_dev		= rk_iommu_attach_device,
> +		.map_pages		= rk_iommu_map,
> +		.unmap_pages		= rk_iommu_unmap,
> +		.flush_iotlb_all	= rk_iommu_flush_iotlb_all,
> +		.iova_to_phys		= rk_iommu_iova_to_phys,
> +		.free			= rk_iommu_domain_free,
>   	}
>   };
>   


From jpoimboe at kernel.org  Tue Mar 18 11:45:40 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Tue, 18 Mar 2025 11:45:40 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250308012742.3208215-2-song@kernel.org>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-2-song@kernel.org>
Message-ID: <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>

On Fri, Mar 07, 2025 at 05:27:41PM -0800, Song Liu wrote:
> With proper exception boundary detection, it is possible to implment
> arch_stack_walk_reliable without sframe.
> 
> Note that, arch_stack_walk_reliable does not guarantee getting reliable
> stack in all scenarios. Instead, it can reliably detect when the stack
> trace is not reliable, which is enough to provide reliable livepatching.
> 
> This version has been inspired by Weinan Liu's patch [1].
> 
> [1] https://lore.kernel.org/live-patching/20250127213310.2496133-7-wnliu at google.com/
> Signed-off-by: Song Liu <song at kernel.org>

This looks incomplete.  The reliable unwinder needs to be extra
paranoid.  There are several already-checked-for errors in the unwinder
that don't actually set the unreliable bit.

There are likely other failure modes it should also be checking for.
For example I don't see where it confirms that the unwind completed to
the end of the stack (which is typically at a certain offset).

See for example all the error conditions in the x86 version of
arch_stack_walk_reliable() and in arch/x86/kernel/unwind_frame.c.

-- 
Josh


From uwe at kleine-koenig.org  Tue Mar 18 11:45:49 2025
From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 18 Mar 2025 19:45:49 +0100
Subject: [PATCH] arm64: dts: rockchip: Improve gmac phy setup for QNAP-TS433
Message-ID: <20250318184550.47642-2-uwe@kleine-koenig.org>

Instead of relying on the MDIO broadcast address (0) talk to the phy on
its configured address. Also add the phy reset gpio which was found by
Heiko inspecting the U-Boot vendor source code. He is still trying to
recover.

Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
---
 .../arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
index 7bd32d230ad2..411f8ac7994b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
@@ -481,9 +481,14 @@ eeprom at 56 {
 };
 
 &mdio0 {
-	rgmii_phy0: ethernet-phy at 0 {
+	rgmii_phy0: ethernet-phy at 3 {
+		/* Motorcomm YT8521 phy */
 		compatible = "ethernet-phy-ieee802.3-c22";
-		reg = <0x0>;
+		reg = <0x3>;
+		pinctrl-0 = <&eth_phy0_reset_pin>;
+		pinctrl-names = "default";
+		reset-assert-us = <10000>;
+		reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>;
 	};
 };
 
@@ -556,6 +561,12 @@ &pcie3x2 {
 };
 
 &pinctrl {
+	gmac0 {
+		eth_phy0_reset_pin: eth-phy0-reset-pin {
+			rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
 	keys {
 		copy_button_pin: copy-button-pin {
 			rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>;

base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
-- 
2.47.1



From acme at kernel.org  Tue Mar 18 12:04:20 2025
From: acme at kernel.org (Arnaldo Carvalho de Melo)
Date: Tue, 18 Mar 2025 16:04:20 -0300
Subject: [PATCH v6 13/13] perf trace: Fix BTF memory leak
In-Reply-To: <20250318033150.119174-14-irogers@google.com>
References: <20250318033150.119174-1-irogers@google.com>
 <20250318033150.119174-14-irogers@google.com>
Message-ID: <Z9nDtMyoARGiHAGg@x1>

On Mon, Mar 17, 2025 at 08:31:50PM -0700, Ian Rogers wrote:
> Add missing btf__free in trace__exit.
> 
> Signed-off-by: Ian Rogers <irogers at google.com>
> ---
>  tools/perf/builtin-trace.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index a5f31472980b..d4bbb6a1e817 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -5339,6 +5339,12 @@ static void trace__exit(struct trace *trace)
>  		zfree(&trace->syscalls.table);
>  	}
>  	zfree(&trace->perfconfig_events);
> +#ifdef HAVE_LIBBPF_SUPPORT
> +	if (trace->btf != NULL) {

No need for the check, btf__free() does:

void btf__free(struct btf *btf)
{
        if (IS_ERR_OR_NULL(btf))
                return;

Up to Namhyung to turn this into the simpler:

	btf__free(trace->btf);
	trace->btf = NULL;

> +		btf__free(trace->btf);
> +		trace->btf = NULL;
> +	}
> +#endif
>  }
>  
>  #ifdef HAVE_BPF_SKEL
> -- 
> 2.49.0.rc1.451.g8f38331e32-goog


From wthai at nvidia.com  Tue Mar 18 12:14:24 2025
From: wthai at nvidia.com (Willie Thai)
Date: Tue, 18 Mar 2025 19:14:24 +0000
Subject: [PATCH v3] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <9ccc845b-9392-4a37-8bca-4f54997126ce@lunn.ch>
References: <9ccc845b-9392-4a37-8bca-4f54997126ce@lunn.ch>
Message-ID: <20250318191424.4161850-1-wthai@nvidia.com>

>> +&mac0 {
>> +     status = "okay";
>> +     pinctrl-names = "default";
>> +     phy-mode = "rgmii";
>> +     phy-handle = <&ethphy3>;
>> +     pinctrl-0 = <&pinctrl_rgmii1_default>; };

> Please read the discussion again. "rgmii" is probably equally wrong as "rgmii-rxid" you had in v1.

> Please talk with Aspeed and ask them the clean up the mess they made with RGMII delays. Until that happens, adding this node should wait.

Thanks for your feedback !
Talked with Aspeed SOC vendor, will skip this node in the next patch version till the delay issue get resolved.


From krzk at kernel.org  Tue Mar 18 12:23:44 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 20:23:44 +0100
Subject: [PATCH 3/3] firmware: exynos-acpm: convert to dev_err_probe() in
 client API
In-Reply-To: <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
 <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>
Message-ID: <801a9754-cd57-42c6-9569-16d9a99bfed9@kernel.org>

On 14/03/2025 17:40, Andr? Draszik wrote:
> dev_err_probe() exists to simplify code and unify error messages by
> using its message template.
> 
> Convert the remaining dev_err() in acpm_get_by_phandle() to
> dev_err_probe().
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  drivers/firmware/samsung/exynos-acpm.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> index 48f1e3cacaa709ae703115169df138b659ddae44..03f907a95c6acd66d89cd8af2f52e7c6dadf492a 100644
> --- a/drivers/firmware/samsung/exynos-acpm.c
> +++ b/drivers/firmware/samsung/exynos-acpm.c
> @@ -701,12 +701,14 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
>  
>  	link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
>  	if (!link) {
> -		dev_err(&pdev->dev,
> -			"Failed to create device link to consumer %s.\n",
> -			dev_name(dev));
> +		int ret = -EINVAL;
> +
> +		dev_err_probe(&pdev->dev, ret,
> +			      "Failed to create device link to consumer %s.\n",
> +			      dev_name(dev));

I do not see how it is simpler. Three lines (statement) is now 5 lines
with two statements.

What's more important, dev_err_probe is supposed to be used only in
probe context, while this could be called in other contexts.

Best regards,
Krzysztof


From catalin.marinas at arm.com  Tue Mar 18 12:27:27 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 18 Mar 2025 19:27:27 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250318125527.GP9311@nvidia.com>
References: <861pv5p0c3.wl-maz@kernel.org>
 <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
Message-ID: <Z9nJH38Em9XEx3U7@arm.com>

On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
> On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
> > The memslot must also be created with a new flag ((2c) in the taxonomy
> > above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
> > flag is only allowed if (1) is valid.
> > 
> > This results in the following behaviours:
> > 
> > - If the VMM creates the memslot with the cacheable attribute without
> >   (1) being advertised, we fail.
> > 
> > - If the VMM creates the memslot without the cacheable attribute, we
> >   map as NC, as it is today.
> 
> Is that OK though?
> 
> Now we have the MM page tables mapping this memory as cachable but KVM
> and the guest is accessing it as non-cached.

I don't think we should allow this.

> I thought ARM tried hard to avoid creating such mismatches? This is
> why the pgprot flags were used to drive this, not an opt-in flag. To
> prevent userspace from forcing a mismatch.

We have the vma->vm_page_prot when the memslot is added, so we could use
this instead of additional KVM flags. If it's Normal Cacheable and the
platform does not support FWB, reject it. If the prot bits say
cacheable, it means that the driver was ok with such mapping. Some extra
checks for !MTE or MTE_PERM.

As additional safety, we could check this again in user_mem_abort() in
case the driver played with the vm_page_prot field in the meantime (e.g.
in the .fault() callback).

I'm not particularly keen on using the vm_page_prot but we probably need
to do this anyway to avoid aliases as we can't fully trust the VMM. The
alternative is a VM_* flag that says "cacheable everywhere" and we avoid
the low-level attributes checking.

> > What this doesn't do is *automatically* decide for the VMM what
> > attributes to use. The VMM must know what it is doing, and only
> > provide the memslot flag when appropriate. Doing otherwise may eat
> > your data and/or take the machine down (cacheable mapping on a device
> > can be great fun).
> 
> Again, this is why we followed the VMA flags. The thing creating the
> VMA already made this safety determination when it set pgprot
> cachable. We should not allow KVM to randomly make any PGPROT
> cachable!

Can this be moved to kvm_arch_prepare_memory_region() and maybe an
additional check in user_mem_abort()?

Thinking some more about a KVM capability that the VMM can check, I'm
not sure what it can do with this. The VMM simply maps something from a
device and cannot probe the cacheability - that's a property of the
device that's not usually exposed to user by the driver. The VMM just
passes this vma to KVM. As with the Normal NC, we tried to avoid
building device knowledge into the VMM (and ended up with
VM_ALLOW_ANY_UNCACHED since the VFIO driver did not allow such user
mapping and probably wasn't entirely safe either).

I assume with the cacheable pfn mapping, the whole range covered by the
vma is entirely safe to be mapped as such in user space.

-- 
Catalin


From krzk at kernel.org  Tue Mar 18 12:28:25 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 20:28:25 +0100
Subject: [PATCH v5 1/5] pinctrl: samsung: add support for
 eint_fltcon_offset
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-1-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
 <20250312-pinctrl-fltcon-suspend-v5-1-d98d5b271242@linaro.org>
Message-ID: <40eb446b-6531-4a73-b47b-55e609fb4d64@kernel.org>

On 12/03/2025 22:58, Peter Griffin wrote:
> On gs101 SoC the fltcon0 (filter configuration 0) offset
> isn't at a fixed offset like previous SoCs as the fltcon1
> register only exists when there are more than 4 pins in the
> bank.
> 
> Add a eint_fltcon_offset and new GS101_PIN_BANK_EINT*
> macros that take an additional fltcon_offs variable.
> 
> This can then be used in suspend/resume callbacks to
> save and restore the fltcon0 and fltcon1 registers.
> 
> Fixes: 4a8be01a1a7a ("pinctrl: samsung: Add gs101 SoC pinctrl configuration")
> Cc: stable at vger.kernel.org
> Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---

Please rebase on next and send incremental patch fixing previous, if needed.

Best regards,
Krzysztof


From oliver.upton at linux.dev  Tue Mar 18 12:30:43 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Tue, 18 Mar 2025 12:30:43 -0700
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250318125527.GP9311@nvidia.com>
References: <861pv5p0c3.wl-maz@kernel.org>
 <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
Message-ID: <Z9nJ42PllG8a7AY7@linux.dev>

On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
> On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
> 
> > The memslot must also be created with a new flag ((2c) in the taxonomy
> > above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
> > flag is only allowed if (1) is valid.
> > 
> > This results in the following behaviours:
> > 
> > - If the VMM creates the memslot with the cacheable attribute without
> >   (1) being advertised, we fail.
> > 
> > - If the VMM creates the memslot without the cacheable attribute, we
> >   map as NC, as it is today.
> 
> Is that OK though?
> 
> Now we have the MM page tables mapping this memory as cachable but KVM
> and the guest is accessing it as non-cached.
> 
> I thought ARM tried hard to avoid creating such mismatches? This is
> why the pgprot flags were used to drive this, not an opt-in flag. To
> prevent userspace from forcing a mismatch.

It's far more problematic the other way around, e.g. the host knows that
something needs a Device-* attribute and the VM has done something
cacheable. The endpoint for that PA could, for example, fall over when
lines pulled in by the guest are written back, which of course can't
always be traced back to the offending VM.

OTOH, if the host knows that a PA is cacheable and the guest does
something non-cacheable, you 'just' have to deal with the usual
mismatched attributes problem as laid out in the ARM ARM.

> > What this doesn't do is *automatically* decide for the VMM what
> > attributes to use. The VMM must know what it is doing, and only
> > provide the memslot flag when appropriate. Doing otherwise may eat
> > your data and/or take the machine down (cacheable mapping on a device
> > can be great fun).
> 
> Again, this is why we followed the VMA flags. The thing creating the
> VMA already made this safety determination when it set pgprot
> cachable. We should not allow KVM to randomly make any PGPROT
> cachable!

That doesn't seem to be the suggestion.

Userspace should be stating intentions on the memslot with the sort of
mapping that it wants to create, and a memslot flag to say "I allow
cacheable mappings" seems to fit the bill.

Then we have:

 - Memslot creation fails for any PFNMAP slot with the flag set &&
   !FEAT_FWB

 - Stage-2 faults fail (exit to userspace) if the above conditions are
   not met

 - Stage-2 faults serviced w/ a cacheable mapping if the precondition is
   satisfied and pgprot on the VMA is cacheable

 - Stage-2 faults serviced w/ a non-cacheable mapping if flag is not
   set

Seems workable + would prevent KVM from being excessively permissive?

Thanks,
Oliver


From calvin at wbinvd.org  Tue Mar 18 12:31:12 2025
From: calvin at wbinvd.org (Calvin Owens)
Date: Tue, 18 Mar 2025 12:31:12 -0700
Subject: [PATCH][QUESTION] bluetooth: Remove duplicated h4_recv_buf() in header
Message-ID: <2b612e2c1f4fa697b47b5dd9b72f1949d7c206f5.1742324401.git.calvin@wbinvd.org>

Hello all,

In the course of other debugging, I've discovered that h4_recv_buf() is
almost completely duplicated in an inline header definiton, and I don't
understand why.

I'd like to clean this up: see the patch below for an explanation.

Does anybody who was around at the time remember any more details about
this? Or failing that, perhaps somebody with access to the bpa10x
hardware can test it with the core function?

Thanks,
Calvin

---8<---
From: Calvin Owens <calvin at wbinvd.org>
Subject: [PATCH] bluetooth: Remove duplicated h4_recv_buf() in header

The "h4_recv.h" header contains a duplicate h4_recv_buf() that is nearly
but not quite identical to the h4_recv_buf() in hci_h4.c.

This duplicated header was added in commit 07eb96a5a7b0 ("Bluetooth:
bpa10x: Use separate h4_recv_buf helper"). Unfortunately, there was no
discussion about it on the list at the time:

    https://lore.kernel.org/all/20180320181855.37297-1-marcel at holtmann.org/
    https://lore.kernel.org/all/20180324091954.73229-2-marcel at holtmann.org/

This is the diff between the two implementations as they exist today:

    --- /home/calvinow/orig.c	2025-03-10 14:43:18.383882623 -0700
    +++ /home/calvinow/copy.c	2025-03-10 14:42:57.109953576 -0700
    @@ -1,117 +1,100 @@
     {
    -	struct hci_uart *hu = hci_get_drvdata(hdev);
    -	u8 alignment = hu->alignment ? hu->alignment : 1;
    -
     	/* Check for error from previous call */
     	if (IS_ERR(skb))
     		skb = NULL;

     	while (count) {
     		int i, len;

    -		/* remove padding bytes from buffer */
    -		for (; hu->padding && count > 0; hu->padding--) {
    -			count--;
    -			buffer++;
    -		}
    -		if (!count)
    -			break;
    -
     		if (!skb) {
     			for (i = 0; i < pkts_count; i++) {
     				if (buffer[0] != (&pkts[i])->type)
     					continue;

     				skb = bt_skb_alloc((&pkts[i])->maxlen,
     						   GFP_ATOMIC);
     				if (!skb)
     					return ERR_PTR(-ENOMEM);

     				hci_skb_pkt_type(skb) = (&pkts[i])->type;
     				hci_skb_expect(skb) = (&pkts[i])->hlen;
     				break;
     			}

     			/* Check for invalid packet type */
     			if (!skb)
     				return ERR_PTR(-EILSEQ);

     			count -= 1;
     			buffer += 1;
     		}

     		len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
     		skb_put_data(skb, buffer, len);

     		count -= len;
     		buffer += len;

     		/* Check for partial packet */
     		if (skb->len < hci_skb_expect(skb))
     			continue;

     		for (i = 0; i < pkts_count; i++) {
     			if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
     				break;
     		}

     		if (i >= pkts_count) {
     			kfree_skb(skb);
     			return ERR_PTR(-EILSEQ);
     		}

     		if (skb->len == (&pkts[i])->hlen) {
     			u16 dlen;

     			switch ((&pkts[i])->lsize) {
     			case 0:
     				/* No variable data length */
     				dlen = 0;
     				break;
     			case 1:
     				/* Single octet variable length */
     				dlen = skb->data[(&pkts[i])->loff];
     				hci_skb_expect(skb) += dlen;

     				if (skb_tailroom(skb) < dlen) {
     					kfree_skb(skb);
     					return ERR_PTR(-EMSGSIZE);
     				}
     				break;
     			case 2:
     				/* Double octet variable length */
     				dlen = get_unaligned_le16(skb->data +
     							  (&pkts[i])->loff);
     				hci_skb_expect(skb) += dlen;

     				if (skb_tailroom(skb) < dlen) {
     					kfree_skb(skb);
     					return ERR_PTR(-EMSGSIZE);
     				}
     				break;
     			default:
     				/* Unsupported variable length */
     				kfree_skb(skb);
     				return ERR_PTR(-EILSEQ);
     			}

     			if (!dlen) {
    -				hu->padding = (skb->len + 1) % alignment;
    -				hu->padding = (alignment - hu->padding) % alignment;
    -
     				/* No more data, complete frame */
     				(&pkts[i])->recv(hdev, skb);
     				skb = NULL;
     			}
     		} else {
    -			hu->padding = (skb->len + 1) % alignment;
    -			hu->padding = (alignment - hu->padding) % alignment;
    -
     			/* Complete frame */
     			(&pkts[i])->recv(hdev, skb);
     			skb = NULL;
     		}
     	}

     	return skb;
     }

It seems fairly obvious from the above that, if alignment is one,
hu->padding is always zero, and in that case the two functions behave
strictly identically.

Since that is the case for every driver except hci_nokia, clean this up
and let them use the core function. I've done some light testing on
btnxpuart, so far everything seems to work.

I would love to eliminate the duplicate function entirely, but I don't
have access to hardware for bpa10x. Since bpa10x breaking was the
original justification for the change, I've left it there for now. I'm
hoping somebody else can shed more light on this.

Cc: Marcel Holtmann <marcel at holtmann.org>
Signed-off-by: Calvin Owens <calvin at wbinvd.org>
---
 drivers/bluetooth/btmtksdio.c | 2 +-
 drivers/bluetooth/btmtkuart.c | 2 +-
 drivers/bluetooth/btnxpuart.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index bd5464bde174..47d1073fb4a4 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -29,7 +29,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#include "h4_recv.h"
+#include "hci_uart.h"
 #include "btmtk.h"
 
 #define VERSION "0.1"
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index c97e260fcb0c..aeb111a0f242 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -27,7 +27,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#include "h4_recv.h"
+#include "hci_uart.h"
 #include "btmtk.h"
 
 #define VERSION "0.2"
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index aa5ec1d444a9..e6db563088cb 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -21,7 +21,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#include "h4_recv.h"
+#include "hci_uart.h"
 
 #define MANUFACTURER_NXP		37
 
-- 
2.47.2



From david at redhat.com  Tue Mar 18 12:35:38 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 18 Mar 2025 20:35:38 +0100
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9nJH38Em9XEx3U7@arm.com>
References: <861pv5p0c3.wl-maz@kernel.org>
 <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org> <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org> <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com>
Message-ID: <ed25f5a6-dad6-4b5e-b42b-58e6ced6c7a2@redhat.com>

On 18.03.25 20:27, Catalin Marinas wrote:
> On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
>> On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
>>> The memslot must also be created with a new flag ((2c) in the taxonomy
>>> above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
>>> flag is only allowed if (1) is valid.
>>>
>>> This results in the following behaviours:
>>>
>>> - If the VMM creates the memslot with the cacheable attribute without
>>>    (1) being advertised, we fail.
>>>
>>> - If the VMM creates the memslot without the cacheable attribute, we
>>>    map as NC, as it is today.
>>
>> Is that OK though?
>>
>> Now we have the MM page tables mapping this memory as cachable but KVM
>> and the guest is accessing it as non-cached.
> 
> I don't think we should allow this.
> 
>> I thought ARM tried hard to avoid creating such mismatches? This is
>> why the pgprot flags were used to drive this, not an opt-in flag. To
>> prevent userspace from forcing a mismatch.
> 
> We have the vma->vm_page_prot when the memslot is added, so we could use
> this instead of additional KVM flags.

I thought we try to avoid messing with the VMA when adding memslots; 
because KVM_CAP_SYNC_MMU allows user space for changing the VMAs 
afterwards without changing the memslot?

include/uapi/linux/kvm.h:#define KVM_CAP_SYNC_MMU 16  /* Changes to host 
mmap are reflected in guest */

-- 
Cheers,

David / dhildenb



From heiko at sntech.de  Tue Mar 18 12:40:23 2025
From: heiko at sntech.de (Heiko =?UTF-8?B?U3TDvGJuZXI=?=)
Date: Tue, 18 Mar 2025 20:40:23 +0100
Subject: [PATCH] arm64: dts: rockchip: Improve gmac phy setup for QNAP-TS433
In-Reply-To: <20250318184550.47642-2-uwe@kleine-koenig.org>
References: <20250318184550.47642-2-uwe@kleine-koenig.org>
Message-ID: <2984786.e9J7NaK4W3@diego>

Hey Uwe,

Am Dienstag, 18. M?rz 2025, 19:45:49 MEZ schrieb Uwe Kleine-K?nig:
> Instead of relying on the MDIO broadcast address (0) talk to the phy on
> its configured address. Also add the phy reset gpio which was found by
> Heiko inspecting the U-Boot vendor source code. He is still trying to
> recover.

I believe these want to be two separate changes ... as indicated by
the "Also ..." in the commit message:
- reset-gpio addition 
- mdio address change

and I guess both could possibly have a

Fixes: 9da1c0327d58 ("arm64: dts: rockchip: Add basic support for QNAP TS-433")


Heiko

> Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
> ---
>  .../arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> index 7bd32d230ad2..411f8ac7994b 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> @@ -481,9 +481,14 @@ eeprom at 56 {
>  };
>  
>  &mdio0 {
> -	rgmii_phy0: ethernet-phy at 0 {
> +	rgmii_phy0: ethernet-phy at 3 {
> +		/* Motorcomm YT8521 phy */
>  		compatible = "ethernet-phy-ieee802.3-c22";
> -		reg = <0x0>;
> +		reg = <0x3>;
> +		pinctrl-0 = <&eth_phy0_reset_pin>;
> +		pinctrl-names = "default";
> +		reset-assert-us = <10000>;
> +		reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>;
>  	};
>  };
>  
> @@ -556,6 +561,12 @@ &pcie3x2 {
>  };
>  
>  &pinctrl {
> +	gmac0 {
> +		eth_phy0_reset_pin: eth-phy0-reset-pin {
> +			rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
> +		};
> +	};
> +
>  	keys {
>  		copy_button_pin: copy-button-pin {
>  			rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>;
> 
> base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
> 






From oliver.upton at linux.dev  Tue Mar 18 12:40:13 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Tue, 18 Mar 2025 12:40:13 -0700
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <ed25f5a6-dad6-4b5e-b42b-58e6ced6c7a2@redhat.com>
References: <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com>
 <ed25f5a6-dad6-4b5e-b42b-58e6ced6c7a2@redhat.com>
Message-ID: <Z9nMHW-OqTLEqDRs@linux.dev>

On Tue, Mar 18, 2025 at 08:35:38PM +0100, David Hildenbrand wrote:
> On 18.03.25 20:27, Catalin Marinas wrote:
> > On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
> > > On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
> > > > The memslot must also be created with a new flag ((2c) in the taxonomy
> > > > above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
> > > > flag is only allowed if (1) is valid.
> > > > 
> > > > This results in the following behaviours:
> > > > 
> > > > - If the VMM creates the memslot with the cacheable attribute without
> > > >    (1) being advertised, we fail.
> > > > 
> > > > - If the VMM creates the memslot without the cacheable attribute, we
> > > >    map as NC, as it is today.
> > > 
> > > Is that OK though?
> > > 
> > > Now we have the MM page tables mapping this memory as cachable but KVM
> > > and the guest is accessing it as non-cached.
> > 
> > I don't think we should allow this.
> > 
> > > I thought ARM tried hard to avoid creating such mismatches? This is
> > > why the pgprot flags were used to drive this, not an opt-in flag. To
> > > prevent userspace from forcing a mismatch.
> > 
> > We have the vma->vm_page_prot when the memslot is added, so we could use
> > this instead of additional KVM flags.
> 
> I thought we try to avoid messing with the VMA when adding memslots; because
> KVM_CAP_SYNC_MMU allows user space for changing the VMAs afterwards without
> changing the memslot?

Any checks on the VMA at memslot creation is done out of courtesy to
userspace so it 'fails fast'. We repeat checks on the VMA at the time of
fault to handle userspace twiddling VMAs behind our back.

VM_MTE_ALLOWED is an example of this.

Thanks,
Oliver


From krzk at kernel.org  Tue Mar 18 12:47:47 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 18 Mar 2025 20:47:47 +0100
Subject: [PATCH v5 2/5] pinctrl: samsung: refactor drvdata suspend &
 resume callbacks
In-Reply-To: <20250312-pinctrl-fltcon-suspend-v5-2-d98d5b271242@linaro.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
 <20250312-pinctrl-fltcon-suspend-v5-2-d98d5b271242@linaro.org>
Message-ID: <5ff8d26d-65bd-4b99-90b1-ae01f0ee9eb7@kernel.org>

On 12/03/2025 22:58, Peter Griffin wrote:
> Move the call of drvdata->suspend()/resume into the loop which is
> iterating drvdata for each bank.


Side effect is that now each drvdata->suspend will be called before
saving registers. Please mention it here and this lead me to one more
comment.

> This allows the clk_enable() and clk_disable() logic to be removed


For suspend path - yes. For resume path - nothing changed, because
drvdata->resume(drvdata) was called with clock enabled.

> from each callback, and also avoids iterating the same loop again
> in the next function.

...

> diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> index 963060920301ec90affb2ee6d758d3d602ffb4a9..375634d8cc79d6533603e3eed562452181e2ee25 100644
> --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> @@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
>  		const u8 *widths = bank->type->fld_width;
>  		enum pincfg_type type;
>  
> +		if (drvdata->suspend)
> +			drvdata->suspend(bank);

Here suspend() is called before saving common register state (was
*after*)...

> +
>  		/* Registers without a powerdown config aren't lost */
>  		if (!widths[PINCFG_TYPE_CON_PDN])
>  			continue;
> @@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
>  
>  	clk_disable(drvdata->pclk);
>  
> -	if (drvdata->suspend)
> -		drvdata->suspend(drvdata);
>  	if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
>  		drvdata->retention_ctrl->enable(drvdata);
>  
> @@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
>  		return ret;
>  	}
>  
> -	if (drvdata->resume)
> -		drvdata->resume(drvdata);
> -
>  	for (i = 0; i < drvdata->nr_banks; i++) {
>  		struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
>  		void __iomem *reg = bank->pctl_base + bank->pctl_offset;
> @@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
>  		const u8 *widths = bank->type->fld_width;
>  		enum pincfg_type type;
>  
> +		if (drvdata->resume)
> +			drvdata->resume(bank);

But this is not symmetrically reversed now - resume() is before
restoring from saved state.

Maybe this change is intentional, but then it should be expressed in
commit msg and in commit why this was chosen.

I guess you decided to do that way only because of code:
	if (!widths[PINCFG_TYPE_CON_PDN])

This code should be symmetrically reversed, otherwise it just raises
questions. For saving register state, it does not really matter, but in
general if we assume driver-specific suspend callback is run the last,
then driver-specific resume callback should be first, no?


Best regards,
Krzysztof


From mhklinux at outlook.com  Tue Mar 18 12:54:49 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Tue, 18 Mar 2025 19:54:49 +0000
Subject: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <SN6PR02MB4157261B9C4AA8CF89A30317D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
>
> Provide a set of IOCTLs for creating and managing child partitions when
> running as root partition on Hyper-V. The new driver is enabled via
> CONFIG_MSHV_ROOT.
> 

[snip]
 
> +
> +int
> +hv_call_clear_virtual_interrupt(u64 partition_id)
> +{
> +	unsigned long flags;

This local variable is now unused and will generate a compile warning.

> +	int status;
> +
> +	status = hv_do_fast_hypercall8(HVCALL_CLEAR_VIRTUAL_INTERRUPT,
> +				       partition_id);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,
> +		    u64 connection_partition_id,
> +		    struct hv_port_info *port_info,
> +		    u8 port_vtl, u8 min_connection_vtl, int node)
> +{
> +	struct hv_input_create_port *input;
> +	unsigned long flags;
> +	int ret = 0;
> +	int status;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		memset(input, 0, sizeof(*input));
> +
> +		input->port_partition_id = port_partition_id;
> +		input->port_id = port_id;
> +		input->connection_partition_id = connection_partition_id;
> +		input->port_info = *port_info;
> +		input->port_vtl = port_vtl;
> +		input->min_connection_vtl = min_connection_vtl;
> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> +		status = hv_do_hypercall(HVCALL_CREATE_PORT, input, NULL);
> +		local_irq_restore(flags);
> +		if (hv_result_success(status))
> +			break;
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE, port_partition_id, 1);
> +
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int
> +hv_call_delete_port(u64 port_partition_id, union hv_port_id port_id)
> +{
> +	union hv_input_delete_port input = { 0 };
> +	unsigned long flags;

Unused local variable.

> +	int status;
> +
> +	input.port_partition_id = port_partition_id;
> +	input.port_id = port_id;
> +	status = hv_do_fast_hypercall16(HVCALL_DELETE_PORT,
> +					input.as_uint64[0],
> +					input.as_uint64[1]);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id,
> +		     u64 connection_partition_id,
> +		     union hv_connection_id connection_id,
> +		     struct hv_connection_info *connection_info,
> +		     u8 connection_vtl, int node)
> +{
> +	struct hv_input_connect_port *input;
> +	unsigned long flags;
> +	int ret = 0, status;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		memset(input, 0, sizeof(*input));
> +		input->port_partition_id = port_partition_id;
> +		input->port_id = port_id;
> +		input->connection_partition_id = connection_partition_id;
> +		input->connection_id = connection_id;
> +		input->connection_info = *connection_info;
> +		input->connection_vtl = connection_vtl;
> +		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> +		status = hv_do_hypercall(HVCALL_CONNECT_PORT, input, NULL);
> +
> +		local_irq_restore(flags);
> +		if (hv_result_success(status))
> +			break;
> +
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			ret = hv_result_to_errno(status);
> +			break;
> +		}
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    connection_partition_id, 1);
> +	} while (!ret);
> +
> +	return ret;
> +}
> +
> +int
> +hv_call_disconnect_port(u64 connection_partition_id,
> +			union hv_connection_id connection_id)
> +{
> +	union hv_input_disconnect_port input = { 0 };
> +	unsigned long flags;

Unused local variable.

> +	int status;
> +
> +	input.connection_partition_id = connection_partition_id;
> +	input.connection_id = connection_id;
> +	input.is_doorbell = 1;
> +	status = hv_do_fast_hypercall16(HVCALL_DISCONNECT_PORT,
> +					input.as_uint64[0],
> +					input.as_uint64[1]);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_notify_port_ring_empty(u32 sint_index)
> +{
> +	union hv_input_notify_port_ring_empty input = { 0 };
> +	unsigned long flags;

Unused.

> +	int status;
> +
> +	input.sint_index = sint_index;
> +	status = hv_do_fast_hypercall8(HVCALL_NOTIFY_PORT_RING_EMPTY,
> +				       input.as_uint64);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_map_stat_page(enum hv_stats_object_type type,
> +			  const union hv_stats_object_identity *identity,
> +			  void **addr)
> +{
> +	unsigned long flags;
> +	struct hv_input_map_stats_page *input;
> +	struct hv_output_map_stats_page *output;
> +	u64 status, pfn;
> +	int ret;
> +
> +	do {
> +		local_irq_save(flags);
> +		input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +		output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> +		memset(input, 0, sizeof(*input));
> +		input->type = type;
> +		input->identity = *identity;
> +
> +		status = hv_do_hypercall(HVCALL_MAP_STATS_PAGE, input, output);
> +		pfn = output->map_location;
> +
> +		local_irq_restore(flags);
> +		if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> +			if (hv_result_success(status))
> +				break;

If this "break" is taken, "ret" may be uninitialized and the return value is
stack garbage. This bug was also in v5 and I didn't notice it in my
previous review.

> +			return hv_result_to_errno(status);
> +		}
> +
> +		ret = hv_call_deposit_pages(NUMA_NO_NODE,
> +					    hv_current_partition_id, 1);
> +		if (ret)
> +			return ret;
> +	} while (!ret);
> +
> +	*addr = page_address(pfn_to_page(pfn));
> +
> +	return ret;
> +}
> +
> +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> +			    const union hv_stats_object_identity *identity)
> +{
> +	unsigned long flags;
> +	struct hv_input_unmap_stats_page *input;
> +	u64 status;
> +
> +	local_irq_save(flags);
> +	input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +	memset(input, 0, sizeof(*input));
> +	input->type = type;
> +	input->identity = *identity;
> +
> +	status = hv_do_hypercall(HVCALL_UNMAP_STATS_PAGE, input, NULL);
> +	local_irq_restore(flags);
> +
> +	return hv_result_to_errno(status);
> +}
> +
> +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> +				   u64 page_struct_count, u32 host_access,
> +				   u32 flags, u8 acquire)
> +{
> +	struct hv_input_modify_sparse_spa_page_host_access *input_page;
> +	u64 status;
> +	int done = 0;
> +	unsigned long irq_flags, large_shift = 0;
> +	u64 page_count = page_struct_count;
> +	u16 code = acquire ? HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS :
> +			     HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS;
> +
> +	if (page_count == 0)
> +		return -EINVAL;
> +
> +	if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE) {
> +		if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> +			return -EINVAL;
> +		large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> +		page_count >>= large_shift;
> +	}
> +
> +	while (done < page_count) {
> +		ulong i, completed, remain = page_count - done;
> +		int rep_count = min(remain,
> +				HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT);
> +
> +		local_irq_save(irq_flags);
> +		input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +		memset(input_page, 0, sizeof(*input_page));
> +		/* Only set the partition id if you are making the pages
> +		 * exclusive
> +		 */
> +		if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE)
> +			input_page->partition_id = partition_id;
> +		input_page->flags = flags;
> +		input_page->host_access = host_access;
> +
> +		for (i = 0; i < rep_count; i++) {
> +			u64 index = (done + i) << large_shift;
> +
> +			if (index >= page_struct_count)
> +				return -EINVAL;
> +
> +			input_page->spa_page_list[i] =
> +						page_to_pfn(pages[index]);
> +		}
> +
> +		status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
> +					     NULL);
> +		local_irq_restore(irq_flags);
> +
> +		completed = hv_repcomp(status);
> +
> +		if (!hv_result_success(status))
> +			return hv_result_to_errno(status);
> +
> +		done += completed;
> +	}
> +
> +	return 0;
> +}

Stopping here because that's where I stopped in Part 1 of my v5 review
of this patch.

Michael


From wei.liu at kernel.org  Tue Mar 18 13:00:04 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Tue, 18 Mar 2025 20:00:04 +0000
Subject: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB4157261B9C4AA8CF89A30317D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157261B9C4AA8CF89A30317D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <Z9nQxOD1N2HZIyaF@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Tue, Mar 18, 2025 at 07:54:49PM +0000, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
> >
> > Provide a set of IOCTLs for creating and managing child partitions when
> > running as root partition on Hyper-V. The new driver is enabled via
> > CONFIG_MSHV_ROOT.
> > 
> 
> [snip]
>  
> > +
> > +int
> > +hv_call_clear_virtual_interrupt(u64 partition_id)
> > +{
> > +	unsigned long flags;
> 
> This local variable is now unused and will generate a compile warning.

FWIW I noticed the same thing too and fixed them all while I committed
the patch.

Thanks,
Wei.


From wei.liu at kernel.org  Tue Mar 18 13:07:06 2025
From: wei.liu at kernel.org (Wei Liu)
Date: Tue, 18 Mar 2025 20:07:06 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB415725C0B70BBBE541D6F87DD4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <Z9msXAClr-vGn3GR@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
 <SN6PR02MB415725C0B70BBBE541D6F87DD4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <Z9nSav5QX-Vf0Eae@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>

On Tue, Mar 18, 2025 at 05:45:46PM +0000, Michael Kelley wrote:
> From: Wei Liu <wei.liu at kernel.org> Sent: Tuesday, March 18, 2025 10:25 AM
> > 
> > On Mon, Mar 17, 2025 at 11:51:52PM +0000, Michael Kelley wrote:
> > > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday,
> > February 26, 2025 3:08 PM
> > [...]
> > > > +static long
> > > > +mshv_vp_ioctl_get_set_state(struct mshv_vp *vp,
> > > > +			    struct mshv_get_set_vp_state __user *user_args,
> > > > +			    bool is_set)
> > > > +{
> > > > +	struct mshv_get_set_vp_state args;
> > > > +	long ret = 0;
> > > > +	union hv_output_get_vp_state vp_state;
> > > > +	u32 data_sz;
> > > > +	struct hv_vp_state_data state_data = {};
> > > > +
> > > > +	if (copy_from_user(&args, user_args, sizeof(args)))
> > > > +		return -EFAULT;
> > > > +
> > > > +	if (args.type >= MSHV_VP_STATE_COUNT || mshv_field_nonzero(args, rsvd) ||
> > > > +	    !args.buf_sz || !PAGE_ALIGNED(args.buf_sz) ||
> > > > +	    !PAGE_ALIGNED(args.buf_ptr))
> > > > +		return -EINVAL;
> > > > +
> > > > +	if (!access_ok((void __user *)args.buf_ptr, args.buf_sz))
> > > > +		return -EFAULT;
> > > > +
> > > > +	switch (args.type) {
> > > > +	case MSHV_VP_STATE_LAPIC:
> > > > +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
> > > > +		data_sz = HV_HYP_PAGE_SIZE;
> > > > +		break;
> > > > +	case MSHV_VP_STATE_XSAVE:
> > >
> > > Just FYI, you can put a semicolon after the colon on the above line, which
> > > adds a null statement, and then the C compiler will accept the definition
> > > of local variable data_sz_64 without needing the odd-looking braces.
> > >
> > > See https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement/19830820
> > >
> > 
> > This is a rarely seen pattern in the kernel, so I would prefer to keep
> > the braces for clarity.
> > 
> >  $ git grep -A5 -P 'case\s+\w+:;$'
> > 
> > This shows a few places are using this pattern. But they are not
> > declaring variables afterwards.
> > 
> 
> The braces just looked a little odd, particularly the way they are indented. Another
> alternative is to move the variable to function scope, and avoid the issue altogether.
> But I'm fine regardless of which approach you take, including keeping it like it is.
> 
> > > I learn something new every day! :-)
> > >
> > 
> > Yep, me too.
> > 
> > Thanks for reviewing the code. Nuno will address the comments. I can fix
> > them up.
> 
> FYI, I may submit a few more comments on the v6 version of the patches.
> If there are changes you want to make based on my comments, I don't care
> if you fix up the existing patches, or take them later as follow up patches.
> And of course, you may choose to not make changes.

We will aim to  address as many comments as possible in the first
submission to reduce the number of follow-up patches. This driver will
be backported to replace the one running internally in Microsoft, so the
fewer patches we need to backport the better.

Wei.

> 
> Michael


From song at kernel.org  Tue Mar 18 13:14:40 2025
From: song at kernel.org (Song Liu)
Date: Tue, 18 Mar 2025 13:14:40 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
References: <20250308012742.3208215-1-song@kernel.org> <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
Message-ID: <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>

Hi Josh,

Thanks for the review!

On Tue, Mar 18, 2025 at 11:45?AM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
>
> On Fri, Mar 07, 2025 at 05:27:41PM -0800, Song Liu wrote:
> > With proper exception boundary detection, it is possible to implment
> > arch_stack_walk_reliable without sframe.
> >
> > Note that, arch_stack_walk_reliable does not guarantee getting reliable
> > stack in all scenarios. Instead, it can reliably detect when the stack
> > trace is not reliable, which is enough to provide reliable livepatching.
> >
> > This version has been inspired by Weinan Liu's patch [1].
> >
> > [1] https://lore.kernel.org/live-patching/20250127213310.2496133-7-wnliu at google.com/
> > Signed-off-by: Song Liu <song at kernel.org>
>
> This looks incomplete.  The reliable unwinder needs to be extra
> paranoid.  There are several already-checked-for errors in the unwinder
> that don't actually set the unreliable bit.
>
> There are likely other failure modes it should also be checking for.
> For example I don't see where it confirms that the unwind completed to
> the end of the stack (which is typically at a certain offset).

If I understand the comment correctly, this should be handled by the
meta data type FRAME_META_TYPE_FINAL.

>
> See for example all the error conditions in the x86 version of
> arch_stack_walk_reliable() and in arch/x86/kernel/unwind_frame.c.

I guess I missed this part:

diff --git i/arch/arm64/kernel/stacktrace.c w/arch/arm64/kernel/stacktrace.c
index 69d0567a0c38..3bb8e3ea4c4b 100644
--- i/arch/arm64/kernel/stacktrace.c
+++ w/arch/arm64/kernel/stacktrace.c
@@ -268,6 +268,8 @@ kunwind_next(struct kunwind_state *state)
        case KUNWIND_SOURCE_TASK:
        case KUNWIND_SOURCE_REGS_PC:
                err = kunwind_next_frame_record(state);
+               if (err && err != -ENOENT)
+                       state->common.unreliable = true;
                break;
        default:
                err = -EINVAL;


With this part, we should cover all these cases? Did I miss something
else?

Thanks,
Song


From mhklinux at outlook.com  Tue Mar 18 13:23:19 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Tue, 18 Mar 2025 20:23:19 +0000
Subject: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <Z9nQxOD1N2HZIyaF@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157261B9C4AA8CF89A30317D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <Z9nQxOD1N2HZIyaF@liuwe-devbox-ubuntu-v2.lamzopl0uupeniq2etz1fddiyg.xx.internal.cloudapp.net>
Message-ID: <SN6PR02MB41578462FA9CE129979F604DD4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Wei Liu <wei.liu at kernel.org> Sent: Tuesday, March 18, 2025 1:00 PM
> 
> On Tue, Mar 18, 2025 at 07:54:49PM +0000, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 14,
> 2025 12:29 PM
> > >
> > > Provide a set of IOCTLs for creating and managing child partitions when
> > > running as root partition on Hyper-V. The new driver is enabled via
> > > CONFIG_MSHV_ROOT.
> > >
> >
> > [snip]
> >
> > > +
> > > +int
> > > +hv_call_clear_virtual_interrupt(u64 partition_id)
> > > +{
> > > +	unsigned long flags;
> >
> > This local variable is now unused and will generate a compile warning.
> 
> FWIW I noticed the same thing too and fixed them all while I committed
> the patch.
> 

Ah, good. That just leaves the uninitialized "ret" in hv_call_map_stat_page().

Michael


From alexei.starovoitov at gmail.com  Tue Mar 18 13:32:02 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Tue, 18 Mar 2025 13:32:02 -0700
Subject: [PATCH bpf-next v4 00/25] Resilient Queued Spin Lock
In-Reply-To: <20250316040541.108729-1-memxor@gmail.com>
References: <20250316040541.108729-1-memxor@gmail.com>
Message-ID: <CAADnVQ+Q+meSfHmang0QYjsbBJsNG5rJXifUxrRXC0GNQKUcnQ@mail.gmail.com>

On Sat, Mar 15, 2025 at 9:05?PM Kumar Kartikeya Dwivedi
<memxor at gmail.com> wrote:
>
> Changelog:
> ----------
> v3 -> v4
> v4: https://lore.kernel.org/bpf/20250303152305.3195648-1-memxor at gmail.com
>
>  * Fix bisectability problem by reordering locktorture commit before
>    Makefile commit.
>  * Add EXPORT_SYMBOL_GPL to all used symbols and variables by consumers.
>  * Skip BPF selftest when nrprocs < 2.
>  * Fix kdoc to describe return value for res_spin_lock, slowpath.
>  * Move kernel/locking/rqspinlock.{c,h} to kernel/bpf/rqspinlock.{c,h}.

Applied to bpf-next/res_spin_lock and /for-next branches.

bpf queue_stack, ringbuf, and various local storage-s need to
be converted to res_spin_lock in follow ups.


From andre.draszik at linaro.org  Tue Mar 18 13:37:04 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Tue, 18 Mar 2025 20:37:04 +0000
Subject: [PATCH 3/3] firmware: exynos-acpm: convert to dev_err_probe()
 in client API
In-Reply-To: <801a9754-cd57-42c6-9569-16d9a99bfed9@kernel.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
	 <20250314-acpm-fixes-v1-3-ab03ca8e723f@linaro.org>
	 <801a9754-cd57-42c6-9569-16d9a99bfed9@kernel.org>
Message-ID: <2d38d2f242bbcce452f6c29f4ee79aa9c5703b7d.camel@linaro.org>

Hi Krzysztof,

On Tue, 2025-03-18 at 20:23 +0100, Krzysztof Kozlowski wrote:
> On 14/03/2025 17:40, Andr? Draszik wrote:
> > dev_err_probe() exists to simplify code and unify error messages by
> > using its message template.
> > 
> > Convert the remaining dev_err() in acpm_get_by_phandle() to
> > dev_err_probe().
> > 
> > Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> > ---
> > ?drivers/firmware/samsung/exynos-acpm.c | 10 ++++++----
> > ?1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> > index 48f1e3cacaa709ae703115169df138b659ddae44..03f907a95c6acd66d89cd8af2f52e7c6dadf492a 100644
> > --- a/drivers/firmware/samsung/exynos-acpm.c
> > +++ b/drivers/firmware/samsung/exynos-acpm.c
> > @@ -701,12 +701,14 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
> > ?
> > ?	link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
> > ?	if (!link) {
> > -		dev_err(&pdev->dev,
> > -			"Failed to create device link to consumer %s.\n",
> > -			dev_name(dev));
> > +		int ret = -EINVAL;
> > +
> > +		dev_err_probe(&pdev->dev, ret,
> > +			????? "Failed to create device link to consumer %s.\n",
> > +			????? dev_name(dev));
> 
> I do not see how it is simpler. Three lines (statement) is now 5 lines
> with two statements.

This was part of some patches converting to scoped cleanup, and
there it was shorter. Shouldn't have taken this change out of
that context...

> What's more important, dev_err_probe is supposed to be used only in
> probe context, while this could be called in other contexts.

True. dev_err_probe is nice though in that it gives us unified
error messages.

Happy to drop for now.

Cheers,
A.



From jeremy.linton at arm.com  Tue Mar 18 13:48:40 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:40 -0500
Subject: [PATCH 6/7] uprobes: Allow the use of uprobe_warn() in arch code
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-7-jeremy.linton@arm.com>

The uprobe_warn function is limited to the uprobe core,
but the functionality is useful to report arch specific errors.

Drop the static so it can be used in those code paths.

Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/kernel/probes/simulate-insn.c | 8 ++++++--
 arch/arm64/kernel/probes/uprobes.c       | 4 ++++
 include/linux/uprobes.h                  | 1 +
 kernel/events/uprobes.c                  | 2 +-
 4 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index 1fc9bb69b1eb..fe637fec8f36 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -56,8 +56,10 @@ static inline void update_lr(struct pt_regs *regs, long addr)
 
 	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
 		push_user_gcs(addr + 4,	 &err);
-		if (err)
+		if (err) {
+			uprobe_warn(current, "GCS stack push failure");
 			force_sig(SIGSEGV);
+		}
 	}
 	procedure_link_pointer_set(regs, addr + 4);
 }
@@ -160,8 +162,10 @@ simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
 
 	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
 		ret_addr = pop_user_gcs(&err);
-		if (err || ret_addr != procedure_link_pointer(regs))
+		if (err || ret_addr != procedure_link_pointer(regs)) {
+			uprobe_warn(current, "GCS RET address mismatch");
 			force_sig(SIGSEGV);
+		}
 	}
 
 }
diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
index 5e72409a255a..9349d521316c 100644
--- a/arch/arm64/kernel/probes/uprobes.c
+++ b/arch/arm64/kernel/probes/uprobes.c
@@ -54,6 +54,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 	switch (arm_probe_decode_insn(insn, &auprobe->api)) {
 	case INSN_REJECTED:
+		uprobe_warn(current, "Unsupported instruction at probe location");
 		return -EINVAL;
 
 	case INSN_GOOD_NO_SLOT:
@@ -169,6 +170,7 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
 		gcspr = read_sysreg_s(SYS_GCSPR_EL0);
 		gcs_ret_vaddr = load_user_gcs((unsigned long __user *)gcspr, &err);
 		if (err) {
+			uprobe_warn(current, "GCS stack not available for retprobe");
 			force_sig(SIGSEGV);
 			goto out;
 		}
@@ -180,11 +182,13 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
 		 * a GCS exception.
 		 */
 		if (gcs_ret_vaddr != orig_ret_vaddr)	{
+			uprobe_warn(current, "LR/GCS mismatch, likely due to incorrectly placed retprobe");
 			orig_ret_vaddr = -1;
 			goto out;
 		}
 		put_user_gcs(trampoline_vaddr, (unsigned long __user *) gcspr, &err);
 		if (err) {
+			uprobe_warn(current, "GCS stack update failure during retprobe");
 			force_sig(SIGSEGV);
 			goto out;
 		}
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index b1df7d792fa1..9578ef1ea5a3 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -185,6 +185,7 @@ struct uprobes_state {
 };
 
 extern void __init uprobes_init(void);
+extern void uprobe_warn(struct task_struct *t, const char *msg);
 extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern bool is_swbp_insn(uprobe_opcode_t *insn);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index b4ca8898fe17..613c1c76f227 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -118,7 +118,7 @@ struct xol_area {
 	unsigned long 			vaddr;		/* Page(s) of instruction slots */
 };
 
-static void uprobe_warn(struct task_struct *t, const char *msg)
+void uprobe_warn(struct task_struct *t, const char *msg)
 {
 	pr_warn("uprobe: %s:%d failed to %s\n", current->comm, current->pid, msg);
 }
-- 
2.48.1



From andre.draszik at linaro.org  Tue Mar 18 13:48:11 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Tue, 18 Mar 2025 20:48:11 +0000
Subject: [PATCH 2/3] firmware: exynos-acpm: silence EPROBE_DEFER error
 on boot
In-Reply-To: <d2e162cd-b12b-47e2-9190-2ecce3489b9c@linaro.org>
References: <20250314-acpm-fixes-v1-0-ab03ca8e723f@linaro.org>
	 <20250314-acpm-fixes-v1-2-ab03ca8e723f@linaro.org>
	 <638cf070-9fd1-416e-8172-75f189ab0dfe@linaro.org>
	 <d2e162cd-b12b-47e2-9190-2ecce3489b9c@linaro.org>
Message-ID: <632522cbc66e456f3b12e884c6c140b38e101aa6.camel@linaro.org>

On Mon, 2025-03-17 at 10:48 +0000, Tudor Ambarus wrote:
> 
> 
> On 3/17/25 10:26 AM, Tudor Ambarus wrote:
> > 
> > 
> > On 3/14/25 4:40 PM, Andr? Draszik wrote:
> > > This driver emits error messages when client drivers are trying to get
> > > an interface handle to this driver here before this driver has
> > > completed _probe().
> > > 
> > > Given this driver returns -EPROBE_DEFER in that case, this is not an
> > > error and shouldn't be emitted to the log, so just remove them.
> > > 
> > > Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
> > > Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> > 
> > Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> 
> I see you kept the error message though for of_find_device_by_node()
> failure. You either get rid of that too, or maybe transform all to dev_dbg?

Thanks Tudor. Seems I missed that, I'll remove it, too.


Cheers,
A.


From jeremy.linton at arm.com  Tue Mar 18 13:48:34 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:34 -0500
Subject: [PATCH 0/7] arm64: Enable UPROBES with GCS
Message-ID: <20250318204841.373116-1-jeremy.linton@arm.com>

Currently uprobes and the Arm Guarded Control Stack (GCS) feature are
exclusive of each other. This restriction needs to be lifted in order
to utilize GCS for generic Linux distro images where the expectation
is that core debugging features like uprobes work.

This series adds some user accessors to read/push/pop the userspace
shadow stack. It then utilizes those functions in the uprobe paths
as needed to synchronize GCS with the changes in control flow at
probe locations. 

Along the way we fix a bug in the core gcs task handling and export
some uprobe quality of life functionality for use in arch specific code.

The KCONFIG restriction is then dropped.

Jeremy Linton (7):
  arm64/gcs: task_gcs_el0_enable() should use passed task
  arm64: probes: Break ret out from bl/blr
  arm64: uaccess: Add additional userspace GCS accessors
  arm64: probes: Add GCS support to bl/blr/ret
  arm64: uprobes: Add GCS support to uretprobes
  uprobes: Allow the use of uprobe_warn() in arch code
  arm64: Kconfig: Remove GCS restrictions on UPROBES

 arch/arm64/Kconfig                       |  1 -
 arch/arm64/include/asm/gcs.h             |  2 +-
 arch/arm64/include/asm/uaccess.h         | 42 ++++++++++++++++++++++++
 arch/arm64/kernel/probes/decode-insn.c   |  7 ++--
 arch/arm64/kernel/probes/simulate-insn.c | 42 +++++++++++++++++++++---
 arch/arm64/kernel/probes/simulate-insn.h |  3 +-
 arch/arm64/kernel/probes/uprobes.c       | 34 +++++++++++++++++++
 include/linux/uprobes.h                  |  1 +
 kernel/events/uprobes.c                  |  2 +-
 9 files changed, 122 insertions(+), 12 deletions(-)

-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:35 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:35 -0500
Subject: [PATCH 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-2-jeremy.linton@arm.com>

Mark Rutland noticed that the task parameter is ignored and
'current' is being used instead. Since this is usually
what its passed, it hasn't yet been causing problems but likely
will as the code gets more testing.

Fixes: fc84bc5378a8 ("arm64/gcs: Context switch GCS state for EL0")
Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/include/asm/gcs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h
index f50660603ecf..5bc432234d3a 100644
--- a/arch/arm64/include/asm/gcs.h
+++ b/arch/arm64/include/asm/gcs.h
@@ -58,7 +58,7 @@ static inline u64 gcsss2(void)
 
 static inline bool task_gcs_el0_enabled(struct task_struct *task)
 {
-	return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
+	return task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
 }
 
 void gcs_set_el0_mode(struct task_struct *task);
-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:37 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:37 -0500
Subject: [PATCH 3/7] arm64: uaccess: Add additional userspace GCS accessors
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-4-jeremy.linton@arm.com>

Uprobes need more advanced read, push, and pop userspace
GCS functionality. Implement those features using the
existing gcsstr() and copy_from_user().

Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/include/asm/uaccess.h | 42 ++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 5b91803201ef..c77ab09a01c2 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -20,6 +20,7 @@
 
 #include <asm/asm-extable.h>
 #include <asm/cpufeature.h>
+#include <asm/gcs.h>
 #include <asm/mmu.h>
 #include <asm/mte.h>
 #include <asm/ptrace.h>
@@ -539,6 +540,47 @@ static inline void put_user_gcs(unsigned long val, unsigned long __user *addr,
 	uaccess_ttbr0_disable();
 }
 
+static __always_inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n);
+
+static inline u64 load_user_gcs(unsigned long __user *addr, int *err)
+{
+	unsigned long ret;
+	u64 load;
+
+	if (!access_ok((char __user *)addr, sizeof(load))) {
+		*err = -EFAULT;
+		return 0;
+	}
+
+	gcsb_dsync();
+	ret = copy_from_user(&load, addr, sizeof(load));
+	if (ret != 0)
+		*err = ret;
+	return load;
+}
+
+static inline void push_user_gcs(unsigned long val, int *err)
+{
+	u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+
+	gcspr -= sizeof(u64);
+	put_user_gcs(val, (unsigned long __user *)gcspr, err);
+	if (!*err)
+		write_sysreg_s(gcspr, SYS_GCSPR_EL0);
+}
+
+static inline u64 pop_user_gcs(int *err)
+{
+	u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+	u64 read_val;
+
+	read_val = load_user_gcs((unsigned long __user *)gcspr, err);
+	if (!*err)
+		write_sysreg_s(gcspr + sizeof(u64), SYS_GCSPR_EL0);
+
+	return read_val;
+}
 
 #endif /* CONFIG_ARM64_GCS */
 
-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:36 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:36 -0500
Subject: [PATCH 2/7] arm64: probes: Break ret out from bl/blr
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-3-jeremy.linton@arm.com>

Prepare for GCS by breaking RET out into its own function, where
it makes more sense to encapsulate the new behavior independent
from the branch instructions.

Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/kernel/probes/decode-insn.c   |  7 ++++---
 arch/arm64/kernel/probes/simulate-insn.c | 10 +++++++++-
 arch/arm64/kernel/probes/simulate-insn.h |  3 ++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c
index 6438bf62e753..4137cc5ef031 100644
--- a/arch/arm64/kernel/probes/decode-insn.c
+++ b/arch/arm64/kernel/probes/decode-insn.c
@@ -108,9 +108,10 @@ arm_probe_decode_insn(u32 insn, struct arch_probe_insn *api)
 	    aarch64_insn_is_bl(insn)) {
 		api->handler = simulate_b_bl;
 	} else if (aarch64_insn_is_br(insn) ||
-	    aarch64_insn_is_blr(insn) ||
-	    aarch64_insn_is_ret(insn)) {
-		api->handler = simulate_br_blr_ret;
+		aarch64_insn_is_blr(insn)) {
+		api->handler = simulate_br_blr;
+	} else if (aarch64_insn_is_ret(insn)) {
+		api->handler = simulate_ret;
 	} else {
 		/*
 		 * Instruction cannot be stepped out-of-line and we don't
diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index 4c6d2d712fbd..09a0b36122d0 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -126,7 +126,7 @@ simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs)
 }
 
 void __kprobes
-simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs)
+simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
 {
 	int xn = (opcode >> 5) & 0x1f;
 
@@ -138,6 +138,14 @@ simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs)
 		set_x_reg(regs, 30, addr + 4);
 }
 
+void __kprobes
+simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
+{
+	int xn = (opcode >> 5) & 0x1f;
+
+	instruction_pointer_set(regs, get_x_reg(regs, xn));
+}
+
 void __kprobes
 simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs)
 {
diff --git a/arch/arm64/kernel/probes/simulate-insn.h b/arch/arm64/kernel/probes/simulate-insn.h
index efb2803ec943..9e772a292d56 100644
--- a/arch/arm64/kernel/probes/simulate-insn.h
+++ b/arch/arm64/kernel/probes/simulate-insn.h
@@ -11,7 +11,8 @@
 void simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs);
-void simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs);
+void simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs);
+void simulate_ret(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs);
-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:38 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:38 -0500
Subject: [PATCH 4/7] arm64: probes: Add GCS support to bl/blr/ret
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-5-jeremy.linton@arm.com>

The arm64 probe simulation doesn't currently have logic in place
to deal with GCS and this results in core dumps if probes are inserted
at control flow locations. Fix-up bl, blr and ret to manipulate the
shadow stack as needed.

Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/kernel/probes/simulate-insn.c | 28 ++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index 09a0b36122d0..1fc9bb69b1eb 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -13,6 +13,7 @@
 #include <asm/traps.h>
 
 #include "simulate-insn.h"
+#include "asm/gcs.h"
 
 #define bbl_displacement(insn)		\
 	sign_extend32(((insn) & 0x3ffffff) << 2, 27)
@@ -49,6 +50,18 @@ static inline u32 get_w_reg(struct pt_regs *regs, int reg)
 	return lower_32_bits(pt_regs_read_reg(regs, reg));
 }
 
+static inline void update_lr(struct pt_regs *regs, long addr)
+{
+	int err = 0;
+
+	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
+		push_user_gcs(addr + 4,	 &err);
+		if (err)
+			force_sig(SIGSEGV);
+	}
+	procedure_link_pointer_set(regs, addr + 4);
+}
+
 static bool __kprobes check_cbz(u32 opcode, struct pt_regs *regs)
 {
 	int xn = opcode & 0x1f;
@@ -107,9 +120,8 @@ simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs)
 {
 	int disp = bbl_displacement(opcode);
 
-	/* Link register is x30 */
 	if (opcode & (1 << 31))
-		set_x_reg(regs, 30, addr + 4);
+		update_lr(regs, addr);
 
 	instruction_pointer_set(regs, addr + disp);
 }
@@ -133,17 +145,25 @@ simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
 	/* update pc first in case we're doing a "blr lr" */
 	instruction_pointer_set(regs, get_x_reg(regs, xn));
 
-	/* Link register is x30 */
 	if (((opcode >> 21) & 0x3) == 1)
-		set_x_reg(regs, 30, addr + 4);
+		update_lr(regs, addr);
 }
 
 void __kprobes
 simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
 {
+	u64 ret_addr;
+	int err = 0;
 	int xn = (opcode >> 5) & 0x1f;
 
 	instruction_pointer_set(regs, get_x_reg(regs, xn));
+
+	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
+		ret_addr = pop_user_gcs(&err);
+		if (err || ret_addr != procedure_link_pointer(regs))
+			force_sig(SIGSEGV);
+	}
+
 }
 
 void __kprobes
-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:39 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:39 -0500
Subject: [PATCH 5/7] arm64: uprobes: Add GCS support to uretprobes
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-6-jeremy.linton@arm.com>

Ret probes work by changing the value in the link register at
the probe location to return to the probe rather than the calling
routine. Thus the GCS needs to be updated with this address as well.

Since its possible to insert probes at locations where the
current value of the LR doesn't match the GCS state this needs
to be detected and handled in order to maintain the existing
no-fault behavior.

Co-developed-by: Steve Capper <steve.capper at arm.com>
Signed-off-by: Steve Capper <steve.capper at arm.com>
(updated to use new gcs accessors, and handle LR/GCS mismatches)
Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/kernel/probes/uprobes.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
index cb3d05af36e3..5e72409a255a 100644
--- a/arch/arm64/kernel/probes/uprobes.c
+++ b/arch/arm64/kernel/probes/uprobes.c
@@ -159,11 +159,41 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
 				  struct pt_regs *regs)
 {
 	unsigned long orig_ret_vaddr;
+	unsigned long gcs_ret_vaddr;
+	int err = 0;
+	u64 gcspr;
 
 	orig_ret_vaddr = procedure_link_pointer(regs);
+
+	if (task_gcs_el0_enabled(current)) {
+		gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+		gcs_ret_vaddr = load_user_gcs((unsigned long __user *)gcspr, &err);
+		if (err) {
+			force_sig(SIGSEGV);
+			goto out;
+		}
+		/*
+		 * If the LR and GCS entry don't match, then some kind of PAC/control
+		 * flow happened. Likely because the user is attempting to retprobe
+		 * on something that isn't a function boundary or inside a leaf
+		 * function. Explicitly abort this retprobe because it will generate
+		 * a GCS exception.
+		 */
+		if (gcs_ret_vaddr != orig_ret_vaddr)	{
+			orig_ret_vaddr = -1;
+			goto out;
+		}
+		put_user_gcs(trampoline_vaddr, (unsigned long __user *) gcspr, &err);
+		if (err) {
+			force_sig(SIGSEGV);
+			goto out;
+		}
+	}
+
 	/* Replace the return addr with trampoline addr */
 	procedure_link_pointer_set(regs, trampoline_vaddr);
 
+out:
 	return orig_ret_vaddr;
 }
 
-- 
2.48.1



From jeremy.linton at arm.com  Tue Mar 18 13:48:41 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Tue, 18 Mar 2025 15:48:41 -0500
Subject: [PATCH 7/7] arm64: Kconfig: Remove GCS restrictions on UPROBES
In-Reply-To: <20250318204841.373116-1-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
Message-ID: <20250318204841.373116-8-jeremy.linton@arm.com>

Now that the uprobe paths have been made GCS compatible
drop the Kconfig restriction.

Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
---
 arch/arm64/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..8e6fe551f5fb 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2223,7 +2223,6 @@ config ARM64_GCS
 	default y
 	select ARCH_HAS_USER_SHADOW_STACK
 	select ARCH_USES_HIGH_VMA_FLAGS
-	depends on !UPROBES
 	help
 	  Guarded Control Stack (GCS) provides support for a separate
 	  stack with restricted access which contains only return
-- 
2.48.1



From uwe at kleine-koenig.org  Tue Mar 18 14:08:44 2025
From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 18 Mar 2025 22:08:44 +0100
Subject: [PATCH v2 0/2] arm64: dts: rockchip: Improve gmac phy setup for QNAP-TS433
Message-ID: <cover.1742331667.git.ukleinek@kernel.org>

Hello,

as suggested by Heiko I split the patch to improve the phy setup of the
gmac ethernet into two patches. The initial patch can be found at
https://lore.kernel.org/linux-arm-kernel/20250318184550.47642-2-uwe at kleine-koenig.org/ .

Heiko also suggested to add Fixes tags. I'm unsure these are justified
because while these patches are an improvement the old devicetree is
working fine. I suggest Heiko to add the tags if he feels strongly
enough about these.

Best regards
Uwe

Uwe Kleine-K?nig (2):
  arm64: dts: rockchip: Correct gmac phy address
  arm64: dts: rockchip: Add gmac phy reset GPIO

 .../arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
-- 
2.47.1



From uwe at kleine-koenig.org  Tue Mar 18 14:08:46 2025
From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 18 Mar 2025 22:08:46 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add gmac phy reset GPIO
In-Reply-To: <cover.1742331667.git.ukleinek@kernel.org>
References: <cover.1742331667.git.ukleinek@kernel.org>
Message-ID: <49f66206fccc714a8745b9ac35247615ad5cc369.1742331667.git.ukleinek@kernel.org>

While looking through the vendor U-Boot code Heiko spotted that a SoC
GPIO is connected to the ethernet phy's reset pin. Add the respective
reset-gpios property with pinmuxing for the GPIO to the phy node.

Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
---
 arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
index 70e88769e21c..411f8ac7994b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
@@ -485,6 +485,10 @@ rgmii_phy0: ethernet-phy at 3 {
 		/* Motorcomm YT8521 phy */
 		compatible = "ethernet-phy-ieee802.3-c22";
 		reg = <0x3>;
+		pinctrl-0 = <&eth_phy0_reset_pin>;
+		pinctrl-names = "default";
+		reset-assert-us = <10000>;
+		reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>;
 	};
 };
 
@@ -557,6 +561,12 @@ &pcie3x2 {
 };
 
 &pinctrl {
+	gmac0 {
+		eth_phy0_reset_pin: eth-phy0-reset-pin {
+			rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
 	keys {
 		copy_button_pin: copy-button-pin {
 			rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>;
-- 
2.47.1



From uwe at kleine-koenig.org  Tue Mar 18 14:08:45 2025
From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 18 Mar 2025 22:08:45 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Correct gmac phy address
In-Reply-To: <cover.1742331667.git.ukleinek@kernel.org>
References: <cover.1742331667.git.ukleinek@kernel.org>
Message-ID: <6b8ef7e37e646f4cd399ceb2f46017644d76da9d.1742331667.git.ukleinek@kernel.org>

The Motorcomm Phy can be talked to on mdio broadcast address 0, but the
actuall address is 3. Adapt the reg property and node name accordingly.

Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
---
 arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
index 7bd32d230ad2..70e88769e21c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
@@ -481,9 +481,10 @@ eeprom at 56 {
 };
 
 &mdio0 {
-	rgmii_phy0: ethernet-phy at 0 {
+	rgmii_phy0: ethernet-phy at 3 {
+		/* Motorcomm YT8521 phy */
 		compatible = "ethernet-phy-ieee802.3-c22";
-		reg = <0x0>;
+		reg = <0x3>;
 	};
 };
 
-- 
2.47.1



From pcc at google.com  Tue Mar 18 14:40:32 2025
From: pcc at google.com (Peter Collingbourne)
Date: Tue, 18 Mar 2025 14:40:32 -0700
Subject: [PATCH v2 1/2] string: Add load_unaligned_zeropad() code path to sized_strscpy()
In-Reply-To: <20250318214035.481950-1-pcc@google.com>
References: <20250318214035.481950-1-pcc@google.com>
Message-ID: <20250318214035.481950-2-pcc@google.com>

The call to read_word_at_a_time() in sized_strscpy() is problematic
with MTE because it may trigger a tag check fault when reading
across a tag granule (16 bytes) boundary. To make this code
MTE compatible, let's start using load_unaligned_zeropad()
on architectures where it is available (i.e. architectures that
define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad()
takes care of page boundaries as well as tag granule boundaries,
also disable the code preventing crossing page boundaries when using
load_unaligned_zeropad().

Signed-off-by: Peter Collingbourne <pcc at google.com>
Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
Cc: stable at vger.kernel.org
---
v2:
- new approach

 lib/string.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/string.c b/lib/string.c
index eb4486ed40d25..b632c71df1a50 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -119,6 +119,7 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
 		return -E2BIG;
 
+#ifndef CONFIG_DCACHE_WORD_ACCESS
 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 	/*
 	 * If src is unaligned, don't cross a page boundary,
@@ -133,12 +134,14 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	/* If src or dest is unaligned, don't do word-at-a-time. */
 	if (((long) dest | (long) src) & (sizeof(long) - 1))
 		max = 0;
+#endif
 #endif
 
 	/*
-	 * read_word_at_a_time() below may read uninitialized bytes after the
-	 * trailing zero and use them in comparisons. Disable this optimization
-	 * under KMSAN to prevent false positive reports.
+	 * load_unaligned_zeropad() or read_word_at_a_time() below may read
+	 * uninitialized bytes after the trailing zero and use them in
+	 * comparisons. Disable this optimization under KMSAN to prevent
+	 * false positive reports.
 	 */
 	if (IS_ENABLED(CONFIG_KMSAN))
 		max = 0;
@@ -146,7 +149,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	while (max >= sizeof(unsigned long)) {
 		unsigned long c, data;
 
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+		c = load_unaligned_zeropad(src+res);
+#else
 		c = read_word_at_a_time(src+res);
+#endif
 		if (has_zero(c, &data, &constants)) {
 			data = prep_zero_mask(c, data, &constants);
 			data = create_zero_mask(data);
-- 
2.49.0.395.g12beb8f557-goog



From pcc at google.com  Tue Mar 18 14:40:33 2025
From: pcc at google.com (Peter Collingbourne)
Date: Tue, 18 Mar 2025 14:40:33 -0700
Subject: [PATCH v2 2/2] kasan: Add strscpy() test to trigger tag fault on arm64
In-Reply-To: <20250318214035.481950-1-pcc@google.com>
References: <20250318214035.481950-1-pcc@google.com>
Message-ID: <20250318214035.481950-3-pcc@google.com>

From: Vincenzo Frascino <vincenzo.frascino at arm.com>

When we invoke strscpy() with a maximum size of N bytes, it assumes
that:
- It can always read N bytes from the source.
- It always write N bytes (zero-padded) to the destination.

On aarch64 with Memory Tagging Extension enabled if we pass an N that is
bigger then the source buffer, it triggers an MTE fault.

Implement a KASAN KUnit test that triggers the issue with the current
implementation of read_word_at_a_time() on aarch64 with MTE enabled.

Cc: Will Deacon <will at kernel.org>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
Co-developed-by: Peter Collingbourne <pcc at google.com>
Signed-off-by: Peter Collingbourne <pcc at google.com>
Link: https://linux-review.googlesource.com/id/If88e396b9e7c058c1a4b5a252274120e77b1898a
---
v2:
- rebased
- fixed test failure

 mm/kasan/kasan_test_c.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
index 59d673400085f..c4bb3ee497b54 100644
--- a/mm/kasan/kasan_test_c.c
+++ b/mm/kasan/kasan_test_c.c
@@ -1570,7 +1570,9 @@ static void kasan_memcmp(struct kunit *test)
 static void kasan_strings(struct kunit *test)
 {
 	char *ptr;
-	size_t size = 24;
+	char *src, *src2;
+	u8 tag;
+	size_t size = 2 * KASAN_GRANULE_SIZE;
 
 	/*
 	 * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT.
@@ -1581,6 +1583,33 @@ static void kasan_strings(struct kunit *test)
 	ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
 
+	src = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
+	strscpy(src, "f0cacc1a00000000f0cacc1a00000000", size);
+
+	tag = get_tag(src);
+
+	src2 = src + KASAN_GRANULE_SIZE;
+
+	/*
+	 * Shorten string and poison the granule after it so that the unaligned
+	 * read in strscpy() triggers a tag mismatch.
+	 */
+	src[KASAN_GRANULE_SIZE - 1] = '\0';
+	kasan_poison(src2, KASAN_GRANULE_SIZE, tag + 1, false);
+
+	/*
+	 * The expected size does not include the terminator '\0'
+	 * so it is (KASAN_GRANULE_SIZE - 2) ==
+	 * KASAN_GRANULE_SIZE - ("initial removed character" + "\0").
+	 */
+	KUNIT_EXPECT_EQ(test, KASAN_GRANULE_SIZE - 2,
+			strscpy(ptr, src + 1, size));
+
+	/* Undo operations above. */
+	src[KASAN_GRANULE_SIZE - 1] = '0';
+	kasan_poison(src2, KASAN_GRANULE_SIZE, tag, false);
+
+	kfree(src);
 	kfree(ptr);
 
 	/*
-- 
2.49.0.395.g12beb8f557-goog



From pcc at google.com  Tue Mar 18 14:41:39 2025
From: pcc at google.com (Peter Collingbourne)
Date: Tue, 18 Mar 2025 14:41:39 -0700
Subject: [PATCH] string: Disable read_word_at_a_time() optimizations if
 kernel MTE is enabled
In-Reply-To: <Z88jbhobIz2yWBbJ@arm.com>
References: <20250308023314.3981455-1-pcc@google.com> <202503071927.1A795821A@keescook>
 <Z88jbhobIz2yWBbJ@arm.com>
Message-ID: <CAMn1gO6Zy1W0M_JsHcX6pcOp8cb7=uWUScf3WGxKTRm=AjXKKA@mail.gmail.com>

On Mon, Mar 10, 2025 at 10:37?AM Catalin Marinas
<catalin.marinas at arm.com> wrote:
>
> On Fri, Mar 07, 2025 at 07:36:31PM -0800, Kees Cook wrote:
> > On Fri, Mar 07, 2025 at 06:33:13PM -0800, Peter Collingbourne wrote:
> > > The optimized strscpy() and dentry_string_cmp() routines will read 8
> > > unaligned bytes at a time via the function read_word_at_a_time(), but
> > > this is incompatible with MTE which will fault on a partially invalid
> > > read. The attributes on read_word_at_a_time() that disable KASAN are
> > > invisible to the CPU so they have no effect on MTE. Let's fix the
> > > bug for now by disabling the optimizations if the kernel is built
> > > with HW tag-based KASAN and consider improvements for followup changes.
> >
> > Why is faulting on a partially invalid read a problem? It's still
> > invalid, so ... it should fault, yes? What am I missing?
>
> read_word_at_a_time() is used to read 8 bytes, potentially unaligned and
> beyond the end of string. The has_zero() function is then used to check
> where the string ends. For this uses, I think we can go with
> load_unaligned_zeropad() which handles a potential fault and pads the
> rest with zeroes.

Agreed, strscpy() should be using load_unaligned_zeropad() if
available. We can also disable the code that checks for page
boundaries if load_unaligned_zeropad() is available.

The only other use of read_word_at_a_time() is the one in
dentry_string_cmp(). At the time that I sent the patch I hadn't
noticed the comment in dentry_string_cmp() stating that its argument
to read_word_at_a_time() is aligned. Since calling
read_word_at_a_time() is fine if the pointer is aligned but partially
invalid (not possible with MTE but it is possible with SW KASAN which
uses a 1:1 shadow mapping), I left this user as-is. In other words, I
didn't make read_word_at_a_time() arch-specific as in Vincenzo's
series.

I sent a v2 with my patch to switch strscpy() over to using
load_unaligned_zeropad() if available, as well as the patch adding
tests from Vincenzo's series (which had some issues that I fixed).

Peter

> > > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > > Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> > > Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> > > Cc: stable at vger.kernel.org
> > > ---
> > >  fs/dcache.c  | 2 +-
> > >  lib/string.c | 3 ++-
> > >  2 files changed, 3 insertions(+), 2 deletions(-)
> >
> > Why are DCACHE_WORD_ACCESS and HAVE_EFFICIENT_UNALIGNED_ACCESS separate
> > things? I can see at least one place where it's directly tied:
> >
> > arch/arm/Kconfig:58:    select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
>
> DCACHE_WORD_ACCESS requires load_unaligned_zeropad() which handles the
> faults. For some reason, read_word_at_a_time() doesn't expect to fault
> and it is only used with HAVE_EFFICIENT_UNALIGNED_ACCESS. I guess arm32
> only enabled load_unaligned_zeropad() on hardware that supports
> efficient unaligned accesses (v6 onwards), hence the dependency.
>
> > Would it make sense to sort this out so that KASAN_HW_TAGS can be taken
> > into account at the Kconfig level instead?
>
> I don't think we should play with config options but rather sort out the
> fault path (load_unaligned_zeropad) or disable MTE temporarily. I'd go
> with the former as long as read_word_at_a_time() is only used for
> strings in conjunction with has_zero(). I haven't checked.
>
> --
> Catalin


From dmitry.baryshkov at oss.qualcomm.com  Tue Mar 18 14:44:23 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Tue, 18 Mar 2025 23:44:23 +0200
Subject: [PATCH 4/9] dt-bindings: arm: qcom,coresight-static-replicator:
 add optional clocks
In-Reply-To: <eeff769a-ff81-4017-9738-98ad130980a9@arm.com>
References: <20250317-fix-nexus-4-v1-0-655c52e2ad97@oss.qualcomm.com>
 <20250317-fix-nexus-4-v1-4-655c52e2ad97@oss.qualcomm.com>
 <7b0af57c-a38c-4c30-9bb7-efe511d6bd1d@arm.com>
 <klcggfxrhjqty4rktx24xmnosqnwzsbyfzgv5ea6okqbffyswn@5yei6276hlla>
 <eeff769a-ff81-4017-9738-98ad130980a9@arm.com>
Message-ID: <3ibbttdnygwsikfm2anusyrg6zoghhlj5sfom2f4ujc434dg22@xa6x5igbrbmf>

On Tue, Mar 18, 2025 at 01:37:23PM +0000, Suzuki K Poulose wrote:
> On 18/03/2025 12:19, Dmitry Baryshkov wrote:
> > On Tue, Mar 18, 2025 at 10:38:17AM +0000, Suzuki K Poulose wrote:
> > > On 17/03/2025 17:44, Dmitry Baryshkov wrote:
> > > 
> > > nit: Subject:
> > > 
> > > s/qcom,coresight-static-replicator/arm,coresight-static-replicator
> > > 
> > > > As most other CoreSight devices the replicator can use either of the
> > > > optional clocks (or both). Document those optional clocks in the schema.
> > > > 
> > > > Fixes: 3c15fddf3121 ("dt-bindings: arm: Convert CoreSight bindings to DT schema")
> > > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> > > > ---
> > > >    .../bindings/arm/arm,coresight-static-replicator.yaml          | 10 ++++++++++
> > > >    1 file changed, 10 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > > > index a6f793ea03b6c193fc0ff72a45e0249a63a2ba3c..56e64067ed3d63c5e293a0840858f13428bacb45 100644
> > > > --- a/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > > > +++ b/Documentation/devicetree/bindings/arm/arm,coresight-static-replicator.yaml
> > > > @@ -30,6 +30,16 @@ properties:
> > > >      power-domains:
> > > >        maxItems: 1
> > > > +  clocks:
> > > > +    minItems: 1
> > > > +    maxItems: 2
> > > > +
> > > 
> > > For the static replicator, you don't have an APB clock, as they can't be
> > > programmed. It may have an ATB clock. So minItems 0, maxItems: 1
> > 
> > It can, see qcom-apq8064.dtsi
> > 
> > Also minItems:0 doesn't make sense to me. I'd rather keep this as an
> > optional property rather than requiring an empty set.
> 
> Interesting, that must be atclk in fact. Because a static replicator
> only manages ATB transactions. It doesn't have an APB interface.

Ack. Unfortunately there are platforms (and grepping revealed more than
just APQ8064) that list the apb_pclk. We have to support those DTs :-(

> 
> I am not an expert in DTB schema. But the point is the clocks are optional.

This is handled by not listing the 'clocks' / 'clock-names' under the
'required' list.

> 
> Suzuki
> 
> 
> > 
> > > 
> > > Suzuki
> > > 
> > > 
> > > 
> > > > +  clock-names:
> > > > +    minItems: 1
> > > > +    enum:
> > > > +      - apb_pclk
> > > > +      - atclk
> > > > +
> > > >      in-ports:
> > > >        $ref: /schemas/graph.yaml#/properties/ports
> > > >        additionalProperties: false
> > > > 
> > > 
> > 
> 

-- 
With best wishes
Dmitry


From bryan.odonoghue at linaro.org  Tue Mar 18 14:48:40 2025
From: bryan.odonoghue at linaro.org (Bryan O'Donoghue)
Date: Tue, 18 Mar 2025 21:48:40 +0000
Subject: [PATCH v1 1/2] media: dt-bindings: Add qcom,qcs8300-camss
In-Reply-To: <f2899540-f9ac-4013-a703-25800429f97d@kernel.org>
References: <20250214094747.2483058-1-quic_vikramsa@quicinc.com>
 <20250214094747.2483058-2-quic_vikramsa@quicinc.com>
 <20250223-observant-auspicious-basilisk-d78ba9@krzk-bin>
 <66c35bce-c657-4c12-ad02-58c995ae385a@quicinc.com>
 <f2899540-f9ac-4013-a703-25800429f97d@kernel.org>
Message-ID: <b1ea0500-595f-48d6-9358-649c25fd4ee9@linaro.org>

On 18/03/2025 07:16, Krzysztof Kozlowski wrote:
> On 18/03/2025 06:52, Vikram Sharma wrote:
>>
>> On 2/23/2025 5:03 PM, Krzysztof Kozlowski wrote:
>>> On Fri, Feb 14, 2025 at 03:17:46PM +0530, Vikram Sharma wrote:
>>>> +properties:
>>>> +  compatible:
>>>> +    const: qcom,qcs8300-camss
>>>> +
>>>> +  reg:
>>>> +    maxItems: 21
>>>> +
>>>> +  reg-names:
>>>> +    items:
>>>> +      - const: csid_wrapper
>>> Why different order of entries than sm8550?
>>
>> Hi Krzysztof,
>>
>> Thanks for your review.
>> I did this change to address a comment from Bryan on another series.
>> https://lore.kernel.org/linux-arm-msm/e152ff78-caa5-493a-88da-96a6670eb2a2 at linaro.org/
>>
>> Please suggest if I should keep the order same as sm8550?
> If you chosen the same order as x1e80100 then it is fine, but that file
> is not merged so it is your responsibility to track any differences and
> be sure whatever you send is always in sync with x1e.
> 
> Best regards,
> Krzysztof

My mistake, I hadn't realised/remembered what we merged for 8550.

Vikram, please follow latest committed example @ 8550.

---
bod


From pcc at google.com  Tue Mar 18 14:40:31 2025
From: pcc at google.com (Peter Collingbourne)
Date: Tue, 18 Mar 2025 14:40:31 -0700
Subject: [PATCH v2 0/2] string: Add load_unaligned_zeropad() code path to sized_strscpy()
Message-ID: <20250318214035.481950-1-pcc@google.com>

This series fixes an issue where strscpy() would sometimes trigger
a false positive KASAN report with MTE.

Peter Collingbourne (1):
  string: Add load_unaligned_zeropad() code path to sized_strscpy()

Vincenzo Frascino (1):
  kasan: Add strscpy() test to trigger tag fault on arm64

 lib/string.c            | 13 ++++++++++---
 mm/kasan/kasan_test_c.c | 31 ++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 4 deletions(-)

-- 
2.49.0.395.g12beb8f557-goog



From iuliana.prodan at oss.nxp.com  Tue Mar 18 14:50:07 2025
From: iuliana.prodan at oss.nxp.com (Iuliana Prodan (OSS))
Date: Tue, 18 Mar 2025 23:50:07 +0200
Subject: [PATCH v2] remoteproc: imx_dsp_rproc: Add support for DSP-specific features
Message-ID: <20250318215007.2109726-1-iuliana.prodan@oss.nxp.com>

From: Iuliana Prodan <iuliana.prodan at nxp.com>

Some DSP firmware requires a FW_READY signal before proceeding, while
others do not.
Therefore, add support to handle i.MX DSP-specific features.

Implement handle_rsc callback to handle resource table parsing and to
process DSP-specific resource, to determine if waiting is needed.

Update imx_dsp_rproc_start() to handle this condition accordingly.

Signed-off-by: Iuliana Prodan <iuliana.prodan at nxp.com>
---
Changes in v2:
- Reviews from Mathieu Poirier:
  - Use vendor-specific resource table entry.
  - Implement resource handler specific to the i.MX DSP.
- Revise commit message to include recent updates.
- Link to v1: https://lore.kernel.org/all/20250305123923.514386-1-iuliana.prodan at oss.nxp.com/

 drivers/remoteproc/imx_dsp_rproc.c | 59 +++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index b9bb15970966..1729bfbc602e 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -35,9 +35,17 @@ module_param_named(no_mailboxes, no_mailboxes, int, 0644);
 MODULE_PARM_DESC(no_mailboxes,
 		 "There is no mailbox between cores, so ignore remote proc reply after start, default is 0 (off).");
 
+/* Flag indicating that the remote is up and running */
 #define REMOTE_IS_READY				BIT(0)
+/* Flag indicating that the host should wait for a firmware-ready response */
+#define HOST_WAIT_FW_READY			BIT(1)
 #define REMOTE_READY_WAIT_MAX_RETRIES		500
 
+/* This flag is set in the DSP resource table's features field to indicate
+ * that the firmware requires the host to wait for a FW_READY response.
+ */
+#define WAIT_FW_READY				BIT(0)
+
 /* att flags */
 /* DSP own area */
 #define ATT_OWN					BIT(31)
@@ -136,6 +144,19 @@ struct imx_dsp_rproc_dcfg {
 	int (*reset)(struct imx_dsp_rproc *priv);
 };
 
+/**
+ * struct fw_rsc_imx_dsp - i.MX DSP specific info
+ * @len: length of the resource entry
+ * @features: feature flags supported by the i.MX DSP firmware
+ *
+ * This represents a DSP-specific resource in the firmware's
+ * resource table, providing information on supported features.
+ */
+struct fw_rsc_imx_dsp {
+	uint32_t len;
+	uint32_t features;
+};
+
 static const struct imx_rproc_att imx_dsp_rproc_att_imx8qm[] = {
 	/* dev addr , sys addr  , size	    , flags */
 	{ 0x596e8000, 0x556e8000, 0x00008000, ATT_OWN },
@@ -300,6 +321,39 @@ static int imx_dsp_rproc_ready(struct rproc *rproc)
 	return -ETIMEDOUT;
 }
 
+/**
+ * imx_dsp_rproc_handle_rsc() - Handle DSP-specific resource table entries
+ * @rproc: remote processor instance
+ * @rsc_type: resource type identifier
+ * @rsc: pointer to the resource entry
+ * @offset: offset of the resource entry
+ * @avail: available space in the resource table
+ *
+ * Parse the DSP-specific resource entry and update flags accordingly.
+ * If the WAIT_FW_READY feature is set, the host must wait for the firmware
+ * to signal readiness before proceeding with execution.
+ *
+ * Return: RSC_HANDLED if processed successfully, RSC_IGNORED otherwise.
+ */
+static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type,
+				    void *rsc, int offset, int avail)
+{
+	struct imx_dsp_rproc *priv = rproc->priv;
+	struct fw_rsc_imx_dsp *imx_dsp_rsc = rsc;
+
+	if (!imx_dsp_rsc || imx_dsp_rsc->len != sizeof(imx_dsp_rsc->features)) {
+		priv->flags |= HOST_WAIT_FW_READY;
+		return RSC_IGNORED;
+	}
+
+	if (imx_dsp_rsc->features & WAIT_FW_READY)
+		priv->flags |= HOST_WAIT_FW_READY;
+	else
+		priv->flags &= ~HOST_WAIT_FW_READY;
+
+	return RSC_HANDLED;
+}
+
 /*
  * Start function for rproc_ops
  *
@@ -335,8 +389,8 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
 
 	if (ret)
 		dev_err(dev, "Failed to enable remote core!\n");
-	else
-		ret = imx_dsp_rproc_ready(rproc);
+	else if (priv->flags & HOST_WAIT_FW_READY)
+		return imx_dsp_rproc_ready(rproc);
 
 	return ret;
 }
@@ -936,6 +990,7 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
 	.kick		= imx_dsp_rproc_kick,
 	.load		= imx_dsp_rproc_elf_load_segments,
 	.parse_fw	= imx_dsp_rproc_parse_fw,
+	.handle_rsc	= imx_dsp_rproc_handle_rsc,
 	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
 	.sanity_check	= rproc_elf_sanity_check,
 	.get_boot_addr	= rproc_elf_get_boot_addr,
-- 
2.25.1



From david at redhat.com  Tue Mar 18 15:14:54 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 18 Mar 2025 23:14:54 +0100
Subject: [PATCH v2 0/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
Message-ID: <20250318221457.3055598-1-david@redhat.com>

Based on mm/unstable.

Currently, uprobe_write_opcode() implements COW-breaking manually, which is
really far from ideal. Further, there is interest in supporting uprobes on
hugetlb pages [1], and leaving at least the COW-breaking to the core will
make this much easier.

Also, I think the current code doesn't really handle some things
properly (see patch #3) when replacing/zapping pages.

Let's rewrite it, to leave COW-breaking to the fault handler, and handle
registration/unregistration by temporarily unmapping the anonymous page,
modifying it, and mapping it again. We still have to implement
zapping of anonymous pages ourselves, unfortunately.

We could look into not performing the temporary unmapping if we can
perform the write atomically, which would likely also make adding hugetlb
support a lot easier. But, limited (e.g., only PMD/PUD) hugetlb support
could be added on top of this with some tweaking.

Note that we now won't have to allocate another anonymous folio when
unregistering (which will be beneficial for hugetlb as well), we can simply
modify the already-mapped one from the registration (if any). When
registering a uprobe, we'll first trigger a ptrace-like write fault to
break COW, to then modify the already-mapped page.

Briefly sanity tested with perf probes and with the bpf uprobes
selftest.

v1 -> v2:
* "kernel/events/uprobes: uprobe_write_opcode() rewrite"
 -> hold GUP reference longer so we can see if the page is still
    mapped when performing the folio_walk
 -> Move anon-folio check
 -> Reshuffle / cleanup some related things

RFC -> v1:
* Use folio_walk and simplify the logic

Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Andrii Nakryiko <andrii.nakryiko at gmail.com>
Cc: Matthew Wilcox <willy at infradead.org>
Cc: Russell King <linux at armlinux.org.uk>
Cc: Masami Hiramatsu <mhiramat at kernel.org>
Cc: Oleg Nesterov <oleg at redhat.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Arnaldo Carvalho de Melo <acme at kernel.org>
Cc: Namhyung Kim <namhyung at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
Cc: Jiri Olsa <jolsa at kernel.org>
Cc: Ian Rogers <irogers at google.com>
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: "Liang, Kan" <kan.liang at linux.intel.com>
Cc: Tong Tiangen <tongtiangen at huawei.com>

[1] https://lkml.kernel.org/r/ZiK50qob9yl5e0Xz at bender.morinfr.org

David Hildenbrand (3):
  kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
  kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and
    uprobe_write_opcode()
  kernel/events/uprobes: uprobe_write_opcode() rewrite

 arch/arm/probes/uprobes/core.c |   4 +-
 include/linux/uprobes.h        |   6 +-
 kernel/events/uprobes.c        | 356 +++++++++++++++++----------------
 3 files changed, 186 insertions(+), 180 deletions(-)


base-commit: 40caf747267c18b6206e26a37d6ea6b695236c11
-- 
2.48.1



From david at redhat.com  Tue Mar 18 15:14:55 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 18 Mar 2025 23:14:55 +0100
Subject: [PATCH v2 1/3] kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
In-Reply-To: <20250318221457.3055598-1-david@redhat.com>
References: <20250318221457.3055598-1-david@redhat.com>
Message-ID: <20250318221457.3055598-2-david@redhat.com>

... and remove the "MM" argument from install_breakpoint(), because it
can easily be derived from the VMA.

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 5d6f3d9d29f44..259038d099819 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1134,10 +1134,10 @@ static bool filter_chain(struct uprobe *uprobe, struct mm_struct *mm)
 	return ret;
 }
 
-static int
-install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
-			struct vm_area_struct *vma, unsigned long vaddr)
+static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	bool first_uprobe;
 	int ret;
 
@@ -1162,9 +1162,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
-static int
-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
+static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
+
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
 	return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
@@ -1296,10 +1298,10 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 		if (is_register) {
 			/* consult only the "caller", new consumer. */
 			if (consumer_filter(new, mm))
-				err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+				err = install_breakpoint(uprobe, vma, info->vaddr);
 		} else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
 			if (!filter_chain(uprobe, mm))
-				err |= remove_breakpoint(uprobe, mm, info->vaddr);
+				err |= remove_breakpoint(uprobe, vma, info->vaddr);
 		}
 
  unlock:
@@ -1472,7 +1474,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
 			continue;
 
 		vaddr = offset_to_vaddr(vma, uprobe->offset);
-		err |= remove_breakpoint(uprobe, mm, vaddr);
+		err |= remove_breakpoint(uprobe, vma, vaddr);
 	}
 	mmap_read_unlock(mm);
 
@@ -1610,7 +1612,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 		if (!fatal_signal_pending(current) &&
 		    filter_chain(uprobe, vma->vm_mm)) {
 			unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
-			install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
+			install_breakpoint(uprobe, vma, vaddr);
 		}
 		put_uprobe(uprobe);
 	}
-- 
2.48.1



From david at redhat.com  Tue Mar 18 15:14:56 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 18 Mar 2025 23:14:56 +0100
Subject: [PATCH v2 2/3] kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and uprobe_write_opcode()
In-Reply-To: <20250318221457.3055598-1-david@redhat.com>
References: <20250318221457.3055598-1-david@redhat.com>
Message-ID: <20250318221457.3055598-3-david@redhat.com>

We already have the VMA, no need to look it up using
get_user_page_vma_remote(). We can now switch to
get_user_pages_remote().

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 arch/arm/probes/uprobes/core.c |  4 ++--
 include/linux/uprobes.h        |  6 +++---
 kernel/events/uprobes.c        | 33 +++++++++++++++++----------------
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c
index f5f790c6e5f89..885e0c5e8c20d 100644
--- a/arch/arm/probes/uprobes/core.c
+++ b/arch/arm/probes/uprobes/core.c
@@ -26,10 +26,10 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
 		(UPROBE_SWBP_ARM_INSN & 0x0fffffff);
 }
 
-int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+int set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
 	     unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 		   __opcode_to_mem_arm(auprobe->bpinsn));
 }
 
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index b1df7d792fa16..288a42cc40baa 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -185,13 +185,13 @@ struct uprobes_state {
 };
 
 extern void __init uprobes_init(void);
-extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
-extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+extern int set_swbp(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
+extern int set_orig_insn(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
 extern bool is_swbp_insn(uprobe_opcode_t *insn);
 extern bool is_trap_insn(uprobe_opcode_t *insn);
 extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
 extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
-extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
+extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t);
 extern struct uprobe *uprobe_register(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister_nosync(struct uprobe *uprobe, struct uprobe_consumer *uc);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 259038d099819..ac17c16f65d63 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -474,19 +474,19 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  *
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
-int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-			unsigned long vaddr, uprobe_opcode_t opcode)
+int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr, uprobe_opcode_t opcode)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
 	struct page *old_page, *new_page;
-	struct vm_area_struct *vma;
 	int ret, is_register, ref_ctr_updated = 0;
 	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
@@ -498,9 +498,9 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 	if (is_register)
 		gup_flags |= FOLL_SPLIT_PMD;
 	/* Read the page with vaddr into memory */
-	old_page = get_user_page_vma_remote(mm, vaddr, gup_flags, &vma);
-	if (IS_ERR(old_page))
-		return PTR_ERR(old_page);
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
+	if (ret != 1)
+		return ret;
 
 	ret = verify_opcode(old_page, vaddr, &opcode);
 	if (ret <= 0)
@@ -590,30 +590,31 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, store the breakpoint instruction at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+	return uprobe_write_opcode(auprobe, vma, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
  * set_orig_insn - Restore the original instruction.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @auprobe: arch specific probepoint information.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, restore the original opcode (opcode) at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak
-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_orig_insn(struct arch_uprobe *auprobe,
+		struct vm_area_struct *vma, unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 			*(uprobe_opcode_t *)&auprobe->insn);
 }
 
@@ -1153,7 +1154,7 @@ static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	if (first_uprobe)
 		set_bit(MMF_HAS_UPROBES, &mm->flags);
 
-	ret = set_swbp(&uprobe->arch, mm, vaddr);
+	ret = set_swbp(&uprobe->arch, vma, vaddr);
 	if (!ret)
 		clear_bit(MMF_RECALC_UPROBES, &mm->flags);
 	else if (first_uprobe)
@@ -1168,7 +1169,7 @@ static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
-	return set_orig_insn(&uprobe->arch, mm, vaddr);
+	return set_orig_insn(&uprobe->arch, vma, vaddr);
 }
 
 struct map_info {
-- 
2.48.1



From david at redhat.com  Tue Mar 18 15:14:57 2025
From: david at redhat.com (David Hildenbrand)
Date: Tue, 18 Mar 2025 23:14:57 +0100
Subject: [PATCH v2 3/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
In-Reply-To: <20250318221457.3055598-1-david@redhat.com>
References: <20250318221457.3055598-1-david@redhat.com>
Message-ID: <20250318221457.3055598-4-david@redhat.com>

uprobe_write_opcode() does some pretty low-level things that really, it
shouldn't be doing: for example, manually breaking COW by allocating
anonymous folios and replacing mapped pages.

Further, it does seem to do some shaky things: for example, writing to
possible COW-shared anonymous pages or zapping anonymous pages that might
be pinned. We're also not taking care of uffd, uffd-wp, softdirty ...
although rather corner cases here. Let's just get it right like ordinary
ptrace writes would.

Let's rewrite the code, leaving COW-breaking to core-MM, triggered by
FOLL_FORCE|FOLL_WRITE (note that the code was already using FOLL_FORCE).

We'll use GUP to lookup/faultin the page and break COW if required. Then,
we'll walk the page tables using a folio_walk to perform our page
modification atomically by temporarily unmap the PTE + flushing the TLB.

Likely, we could avoid the temporary unmap in case we can just
atomically write the instruction, but that will be a separate project.

Unfortunately, we still have to implement the zapping logic manually,
because we only want to zap in specific circumstances (e.g., page
content identical).

Note that we can now handle large folios (compound pages) and the shared
zeropage just fine, so drop these checks.

Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 311 ++++++++++++++++++++--------------------
 1 file changed, 157 insertions(+), 154 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ac17c16f65d63..671b8b6ad4e1b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -29,6 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/srcu.h>
 #include <linux/oom.h>          /* check_stable_address_space */
+#include <linux/pagewalk.h>
 
 #include <linux/uprobes.h>
 
@@ -151,91 +152,6 @@ static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
 	return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
 }
 
-/**
- * __replace_page - replace page in vma by new page.
- * based on replace_page in mm/ksm.c
- *
- * @vma:      vma that holds the pte pointing to page
- * @addr:     address the old @page is mapped at
- * @old_page: the page we are replacing by new_page
- * @new_page: the modified page we replace page by
- *
- * If @new_page is NULL, only unmap @old_page.
- *
- * Returns 0 on success, negative error code otherwise.
- */
-static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
-				struct page *old_page, struct page *new_page)
-{
-	struct folio *old_folio = page_folio(old_page);
-	struct folio *new_folio;
-	struct mm_struct *mm = vma->vm_mm;
-	DEFINE_FOLIO_VMA_WALK(pvmw, old_folio, vma, addr, 0);
-	int err;
-	struct mmu_notifier_range range;
-	pte_t pte;
-
-	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, addr,
-				addr + PAGE_SIZE);
-
-	if (new_page) {
-		new_folio = page_folio(new_page);
-		err = mem_cgroup_charge(new_folio, vma->vm_mm, GFP_KERNEL);
-		if (err)
-			return err;
-	}
-
-	/* For folio_free_swap() below */
-	folio_lock(old_folio);
-
-	mmu_notifier_invalidate_range_start(&range);
-	err = -EAGAIN;
-	if (!page_vma_mapped_walk(&pvmw))
-		goto unlock;
-	VM_BUG_ON_PAGE(addr != pvmw.address, old_page);
-	pte = ptep_get(pvmw.pte);
-
-	/*
-	 * Handle PFN swap PTES, such as device-exclusive ones, that actually
-	 * map pages: simply trigger GUP again to fix it up.
-	 */
-	if (unlikely(!pte_present(pte))) {
-		page_vma_mapped_walk_done(&pvmw);
-		goto unlock;
-	}
-
-	if (new_page) {
-		folio_get(new_folio);
-		folio_add_new_anon_rmap(new_folio, vma, addr, RMAP_EXCLUSIVE);
-		folio_add_lru_vma(new_folio, vma);
-	} else
-		/* no new page, just dec_mm_counter for old_page */
-		dec_mm_counter(mm, MM_ANONPAGES);
-
-	if (!folio_test_anon(old_folio)) {
-		dec_mm_counter(mm, mm_counter_file(old_folio));
-		inc_mm_counter(mm, MM_ANONPAGES);
-	}
-
-	flush_cache_page(vma, addr, pte_pfn(pte));
-	ptep_clear_flush(vma, addr, pvmw.pte);
-	if (new_page)
-		set_pte_at(mm, addr, pvmw.pte,
-			   mk_pte(new_page, vma->vm_page_prot));
-
-	folio_remove_rmap_pte(old_folio, old_page, vma);
-	if (!folio_mapped(old_folio))
-		folio_free_swap(old_folio);
-	page_vma_mapped_walk_done(&pvmw);
-	folio_put(old_folio);
-
-	err = 0;
- unlock:
-	mmu_notifier_invalidate_range_end(&range);
-	folio_unlock(old_folio);
-	return err;
-}
-
 /**
  * is_swbp_insn - check if instruction is breakpoint instruction.
  * @insn: instruction to be checked.
@@ -463,6 +379,95 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
+static bool orig_page_is_identical(struct vm_area_struct *vma,
+		unsigned long vaddr, struct page *page, bool *pmd_mappable)
+{
+	const pgoff_t index = vaddr_to_offset(vma, vaddr) >> PAGE_SHIFT;
+	struct folio *orig_folio = filemap_get_folio(vma->vm_file->f_mapping,
+						    index);
+	struct page *orig_page;
+	bool identical;
+
+	if (IS_ERR(orig_folio))
+		return false;
+	orig_page = folio_file_page(orig_folio, index);
+
+	*pmd_mappable = folio_test_pmd_mappable(orig_folio);
+	identical = folio_test_uptodate(orig_folio) &&
+		    pages_identical(page, orig_page);
+	folio_put(orig_folio);
+	return identical;
+}
+
+static int __uprobe_write_opcode(struct vm_area_struct *vma,
+		struct folio_walk *fw, struct folio *folio,
+		unsigned long opcode_vaddr, uprobe_opcode_t opcode)
+{
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
+	const bool is_register = !!is_swbp_insn(&opcode);
+	bool pmd_mappable;
+
+	/* For now, we'll only handle PTE-mapped folios. */
+	if (fw->level != FW_LEVEL_PTE)
+		return -EFAULT;
+
+	/*
+	 * See can_follow_write_pte(): we'd actually prefer a writable PTE here,
+	 * but the VMA might not be writable.
+	 */
+	if (!pte_write(fw->pte)) {
+		if (!PageAnonExclusive(fw->page))
+			return -EFAULT;
+		if (unlikely(userfaultfd_pte_wp(vma, fw->pte)))
+			return -EFAULT;
+		/* SOFTDIRTY is handled via pte_mkdirty() below. */
+	}
+
+	/*
+	 * We'll temporarily unmap the page and flush the TLB, such that we can
+	 * modify the page atomically.
+	 */
+	flush_cache_page(vma, vaddr, pte_pfn(fw->pte));
+	fw->pte = ptep_clear_flush(vma, vaddr, fw->ptep);
+	copy_to_page(fw->page, opcode_vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+
+	/*
+	 * When unregistering, we may only zap a PTE if uffd is disabled and
+	 * there are no unexpected folio references ...
+	 */
+	if (is_register || userfaultfd_missing(vma) ||
+	    (folio_ref_count(folio) != folio_mapcount(folio) + 1 +
+	     folio_test_swapcache(folio) * folio_nr_pages(folio)))
+		goto remap;
+
+	/*
+	 * ... and the mapped page is identical to the original page that
+	 * would get faulted in on next access.
+	 */
+	if (!orig_page_is_identical(vma, vaddr, fw->page, &pmd_mappable))
+		goto remap;
+
+	dec_mm_counter(vma->vm_mm, MM_ANONPAGES);
+	folio_remove_rmap_pte(folio, fw->page, vma);
+	if (!folio_mapped(folio) && folio_test_swapcache(folio) &&
+	     folio_trylock(folio)) {
+		folio_free_swap(folio);
+		folio_unlock(folio);
+	}
+	folio_put(folio);
+
+	return pmd_mappable;
+remap:
+	/*
+	 * Make sure that our copy_to_page() changes become visible before the
+	 * set_pte_at() write.
+	 */
+	smp_wmb();
+	/* We modified the page. Make sure to mark the PTE dirty. */
+	set_pte_at(vma->vm_mm, vaddr, fw->ptep, pte_mkdirty(fw->pte));
+	return 0;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
@@ -475,116 +480,114 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
  * @vma: the probed virtual memory area.
- * @vaddr: the virtual address to store the opcode.
- * @opcode: opcode to be written at @vaddr.
+ * @opcode_vaddr: the virtual address to store the opcode.
+ * @opcode: opcode to be written at @opcode_vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
 int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
-		unsigned long vaddr, uprobe_opcode_t opcode)
+		const unsigned long opcode_vaddr, uprobe_opcode_t opcode)
 {
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
 	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
-	struct page *old_page, *new_page;
 	int ret, is_register, ref_ctr_updated = 0;
-	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
+	struct mmu_notifier_range range;
+	struct folio_walk fw;
+	struct folio *folio;
+	struct page *page;
 
 	is_register = is_swbp_insn(&opcode);
 	uprobe = container_of(auprobe, struct uprobe, arch);
 
-retry:
+	if (WARN_ON_ONCE(!is_cow_mapping(vma->vm_flags)))
+		return -EINVAL;
+
+	/*
+	 * When registering, we have to break COW to get an exclusive anonymous
+	 * page that we can safely modify. Use FOLL_WRITE to trigger a write
+	 * fault if required. When unregistering, we might be lucky and the
+	 * anon page is already gone. So defer write faults until really
+	 * required. Use FOLL_SPLIT_PMD, because __uprobe_write_opcode()
+	 * cannot deal with PMDs yet.
+	 */
 	if (is_register)
-		gup_flags |= FOLL_SPLIT_PMD;
-	/* Read the page with vaddr into memory */
-	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
-	if (ret != 1)
-		return ret;
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
 
-	ret = verify_opcode(old_page, vaddr, &opcode);
+retry:
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &page, NULL);
 	if (ret <= 0)
-		goto put_old;
-
-	if (is_zero_page(old_page)) {
-		ret = -EINVAL;
-		goto put_old;
-	}
+		goto out;
+	folio = page_folio(page);
 
-	if (WARN(!is_register && PageCompound(old_page),
-		 "uprobe unregister should never work on compound page\n")) {
-		ret = -EINVAL;
-		goto put_old;
+	ret = verify_opcode(page, opcode_vaddr, &opcode);
+	if (ret <= 0) {
+		folio_put(folio);
+		goto out;
 	}
 
 	/* We are going to replace instruction, update ref_ctr. */
 	if (!ref_ctr_updated && uprobe->ref_ctr_offset) {
 		ret = update_ref_ctr(uprobe, mm, is_register ? 1 : -1);
-		if (ret)
-			goto put_old;
+		if (ret) {
+			folio_put(folio);
+			goto out;
+		}
 
 		ref_ctr_updated = 1;
 	}
 
 	ret = 0;
-	if (!is_register && !PageAnon(old_page))
-		goto put_old;
-
-	ret = anon_vma_prepare(vma);
-	if (ret)
-		goto put_old;
-
-	ret = -ENOMEM;
-	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
-	if (!new_page)
-		goto put_old;
-
-	__SetPageUptodate(new_page);
-	copy_highpage(new_page, old_page);
-	copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+	if (unlikely(!folio_test_anon(folio))) {
+		VM_WARN_ON_ONCE(is_register);
+		goto out;
+	}
 
 	if (!is_register) {
-		struct page *orig_page;
-		pgoff_t index;
-
-		VM_BUG_ON_PAGE(!PageAnon(old_page), old_page);
-
-		index = vaddr_to_offset(vma, vaddr & PAGE_MASK) >> PAGE_SHIFT;
-		orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
-					  index);
-
-		if (orig_page) {
-			if (PageUptodate(orig_page) &&
-			    pages_identical(new_page, orig_page)) {
-				/* let go new_page */
-				put_page(new_page);
-				new_page = NULL;
-
-				if (PageCompound(orig_page))
-					orig_page_huge = true;
-			}
-			put_page(orig_page);
-		}
+		/*
+		 * In the common case, we'll be able to zap the page when
+		 * unregistering. So trigger MMU notifiers now, as we won't
+		 * be able to do it under PTL.
+		 */
+		mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
+					vaddr, vaddr + PAGE_SIZE);
+		mmu_notifier_invalidate_range_start(&range);
+	}
+
+	ret = -EAGAIN;
+	/* Walk the page tables again, to perform the actual update. */
+	if (folio_walk_start(&fw, vma, vaddr, 0)) {
+		if (fw.page == page)
+			ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr, opcode);
+		folio_walk_end(&fw, vma);
 	}
 
-	ret = __replace_page(vma, vaddr & PAGE_MASK, old_page, new_page);
-	if (new_page)
-		put_page(new_page);
-put_old:
-	put_page(old_page);
+	if (!is_register)
+		mmu_notifier_invalidate_range_end(&range);
 
-	if (unlikely(ret == -EAGAIN))
+	folio_put(folio);
+	switch (ret) {
+	case -EFAULT:
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
+		fallthrough;
+	case -EAGAIN:
 		goto retry;
+	default:
+		break;
+	}
 
+out:
 	/* Revert back reference counter if instruction update failed. */
-	if (ret && is_register && ref_ctr_updated)
+	if (ret < 0 && is_register && ref_ctr_updated)
 		update_ref_ctr(uprobe, mm, -1);
 
 	/* try collapse pmd for compound page */
-	if (!ret && orig_page_huge)
+	if (ret > 0)
 		collapse_pte_mapped_thp(mm, vaddr, false);
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 /**
-- 
2.48.1



From nfraprado at collabora.com  Tue Mar 18 15:22:16 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 18 Mar 2025 18:22:16 -0400
Subject: [PATCH 2/4] dt-bindings: remoteproc: mediatek: Remove l1tcm for
 dual-core MT8188 SCP
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
Message-ID: <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>

The SCP present on MT8188 does not have an L1TCM memory region, but the
binding incorrectly requires one for the dual-core description of the
MT8188 SCP. Remove that requirement. Also update the minimum number of
reg and reg-names to 1, since as this is a multi-core SCP with no
L1TCM memory, only the CFG memory region is present in the parent node.

Fixes: 91e0d560b9fd ("dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP")
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 .../devicetree/bindings/remoteproc/mtk,scp.yaml       | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
index ee33c233e44f3d51f0851b35697a24208c87f68a..04348cfcb0424dc78ff1ddd77665285a052925e9 100644
--- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
@@ -28,11 +28,11 @@ properties:
     description:
       Should contain the address ranges for memory regions SRAM, CFG, and,
       on some platforms, L1TCM.
-    minItems: 2
+    minItems: 1
     maxItems: 3
 
   reg-names:
-    minItems: 2
+    minItems: 1
     maxItems: 3
 
   clocks:
@@ -171,6 +171,7 @@ allOf:
     then:
       properties:
         reg:
+          minItems: 2
           maxItems: 2
         reg-names:
           items:
@@ -196,16 +197,28 @@ allOf:
       properties:
         compatible:
           enum:
-            - mediatek,mt8188-scp-dual
             - mediatek,mt8195-scp-dual
     then:
       properties:
         reg:
+          minItems: 2
           maxItems: 2
         reg-names:
           items:
             - const: cfg
             - const: l1tcm
+  - if:
+      properties:
+        compatible:
+          enum:
+            - mediatek,mt8188-scp-dual
+    then:
+      properties:
+        reg:
+          maxItems: 1
+        reg-names:
+          items:
+            - const: cfg
 
 additionalProperties: false
 

-- 
2.49.0



From nfraprado at collabora.com  Tue Mar 18 15:22:17 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 18 Mar 2025 18:22:17 -0400
Subject: [PATCH 3/4] arm64: dts: mediatek: mt8188: Describe SCP as a
 cluster with two cores
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
Message-ID: <20250318-scp-dual-core-mt8390-v1-3-8733e192cc73@collabora.com>

The SCP is currently described in the Devicetree as a single-core
processor, but really it is a cluster with two cores. Describe the full
cluster but enable only core0 on the current mt8188 platforms since
that's the only one usable with the upstream firmware.

Co-developed-by: Tinghan Shen <tinghan.shen at mediatek.com>
Signed-off-by: Tinghan Shen <tinghan.shen at mediatek.com>
Co-developed-by: Jason Chen <jason-ch.chen at mediatek.corp-partner.google.com>
Signed-off-by: Jason Chen <jason-ch.chen at mediatek.corp-partner.google.com>
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/boot/dts/mediatek/mt8188-evb.dts        |  6 +++-
 arch/arm64/boot/dts/mediatek/mt8188.dtsi           | 36 ++++++++++++++++------
 .../boot/dts/mediatek/mt8390-genio-common.dtsi     |  6 +++-
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8188-evb.dts b/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
index f89835ac36f36f86e2054ae0c332172be97b049a..f4c207d65b877e1eefaa26540446c3c06369ca21 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
@@ -331,7 +331,11 @@ &pmic {
 	interrupts-extended = <&pio 222 IRQ_TYPE_LEVEL_HIGH>;
 };
 
-&scp {
+&scp_cluster {
+	status = "okay";
+};
+
+&scp_c0 {
 	memory-region = <&scp_mem_reserved>;
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
index 4437b1820f2685281c3a373bf626f72b53503e62..bea3cee9b8e8f0dc656edd85e63f4f6f6645607f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
@@ -1382,12 +1382,30 @@ gce1: mailbox at 10330000 {
 			clocks = <&infracfg_ao CLK_INFRA_AO_GCE2>;
 		};
 
-		scp: scp at 10500000 {
-			compatible = "mediatek,mt8188-scp";
-			reg = <0 0x10500000 0 0x100000>,
-			      <0 0x10720000 0 0xe0000>;
-			reg-names = "sram", "cfg";
-			interrupts = <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH 0>;
+		scp_cluster: scp at 10720000 {
+			compatible = "mediatek,mt8188-scp-dual";
+			reg = <0 0x10720000 0 0xe0000>;
+			reg-names = "cfg";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0 0x10500000 0x100000>;
+			status = "disabled";
+
+			scp_c0: scp at 0 {
+				compatible = "mediatek,scp-core";
+				reg = <0x0 0xd0000>;
+				reg-names = "sram";
+				interrupts = <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH 0>;
+				status = "disabled";
+			};
+
+			scp_c1: scp at d0000 {
+				compatible = "mediatek,scp-core";
+				reg = <0xd0000 0x2f000>;
+				reg-names = "sram";
+				interrupts = <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH 0>;
+				status = "disabled";
+			};
 		};
 
 		afe: audio-controller at 10b10000 {
@@ -2249,7 +2267,7 @@ dma-controller at 14001000 {
 			mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0x1000 0x1000>;
 			mediatek,gce-events = <CMDQ_EVENT_VPP0_MDP_RDMA_SOF>,
 					      <CMDQ_EVENT_VPP0_MDP_RDMA_FRAME_DONE>;
-			mediatek,scp = <&scp>;
+			mediatek,scp = <&scp_c0>;
 		};
 
 		display at 14002000 {
@@ -2704,7 +2722,7 @@ video_decoder: video-decoder at 18000000 {
 			iommus = <&vpp_iommu M4U_PORT_L23_HW_VDEC_UFO_ENC_EXT>;
 			#address-cells = <2>;
 			#size-cells = <2>;
-			mediatek,scp = <&scp>;
+			mediatek,scp = <&scp_c0>;
 
 			video-codec at 10000 {
 				compatible = "mediatek,mtk-vcodec-lat";
@@ -2828,7 +2846,7 @@ video_encoder: video-encoder at 1a020000 {
 				 <&vdo_iommu M4U_PORT_L19_VENC_SUB_W_LUMA>,
 				 <&vdo_iommu M4U_PORT_L19_VENC_SUB_R_LUMA>;
 			power-domains = <&spm MT8188_POWER_DOMAIN_VENC>;
-			mediatek,scp = <&scp>;
+			mediatek,scp = <&scp_c0>;
 		};
 
 		jpeg_encoder: jpeg-encoder at 1a030000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
index 60139e6dffd8e0e326690d922f3360d829ed026b..65952bcf5d03e3b22984dd3e997e7107e74dac72 100644
--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
@@ -1055,7 +1055,11 @@ power-key {
 	};
 };
 
-&scp {
+&scp_cluster {
+	status = "okay";
+};
+
+&scp_c0 {
 	memory-region = <&scp_mem>;
 	status = "okay";
 };

-- 
2.49.0



From nfraprado at collabora.com  Tue Mar 18 15:22:18 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 18 Mar 2025 18:22:18 -0400
Subject: [PATCH 4/4] arm64: dts: mediatek: mt8390-genio-common: Add
 firmware-name for scp0
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
Message-ID: <20250318-scp-dual-core-mt8390-v1-4-8733e192cc73@collabora.com>

Add the firmware-name property for SCP core0 so the firmware can be
loaded from its canonical location in the linux-firmware repository.

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
index 65952bcf5d03e3b22984dd3e997e7107e74dac72..53951817df468ee27d20db1f1028c21a1832b880 100644
--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi
@@ -1060,6 +1060,7 @@ &scp_cluster {
 };
 
 &scp_c0 {
+	firmware-name = "mediatek/mt8188/scp.img";
 	memory-region = <&scp_mem>;
 	status = "okay";
 };

-- 
2.49.0



From nfraprado at collabora.com  Tue Mar 18 15:22:14 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 18 Mar 2025 18:22:14 -0400
Subject: [PATCH 0/4] Describe MT8188's SCP as dual-core
Message-ID: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>

This series updates the MT8188 SCP description to dual-core and prepares
its usage. Patch 3 updates the MT8188 DT to describe the SCP as a dual
core cluster and patch 4 adds the firmware-name property so the firmware
can be loaded. Patches 1 and 2 are dt-binding fixes for the SCP.

Depends on the "MediaTek MT8188 MDP3 Enablement" series [1].

[1] https://lore.kernel.org/all/20241218105320.38980-1-angelogioacchino.delregno at collabora.com

Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
N?colas F. R. A. Prado (4):
      dt-bindings: remoteproc: mediatek: Add missing minItems for 8192/8195
      dt-bindings: remoteproc: mediatek: Remove l1tcm for dual-core MT8188 SCP
      arm64: dts: mediatek: mt8188: Describe SCP as a cluster with two cores
      arm64: dts: mediatek: mt8390-genio-common: Add firmware-name for scp0

 .../devicetree/bindings/remoteproc/mtk,scp.yaml    | 20 ++++++++++--
 arch/arm64/boot/dts/mediatek/mt8188-evb.dts        |  6 +++-
 arch/arm64/boot/dts/mediatek/mt8188.dtsi           | 36 ++++++++++++++++------
 .../boot/dts/mediatek/mt8390-genio-common.dtsi     |  7 ++++-
 4 files changed, 55 insertions(+), 14 deletions(-)
---
base-commit: 04b0d54949f9660384ceefc6f707e40daba6bf3e
change-id: 20250318-scp-dual-core-mt8390-8ef1b02f2d92

Best regards,
-- 
N?colas F. R. A. Prado <nfraprado at collabora.com>



From nfraprado at collabora.com  Tue Mar 18 15:22:15 2025
From: nfraprado at collabora.com (=?utf-8?q?N=C3=ADcolas_F=2E_R=2E_A=2E_Prado?=)
Date: Tue, 18 Mar 2025 18:22:15 -0400
Subject: [PATCH 1/4] dt-bindings: remoteproc: mediatek: Add missing
 minItems for 8192/8195
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
Message-ID: <20250318-scp-dual-core-mt8390-v1-1-8733e192cc73@collabora.com>

Both MT8192 and MT8195 have an L1TCM memory, so it should be described
in reg, and therefore reg's minItems should be 3, as is already implicit
by reg-names. Override minItems to 3 for MT8192 and MT8195.

Fixes: 6b55b1e2fd7f ("dt-bindings: remoteproc: mediatek: Support MT8195 dual-core SCP")
Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
---
 Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
index adc6b3f36fde49eb3fa7ed3f08b0fa9e7f331162..ee33c233e44f3d51f0851b35697a24208c87f68a 100644
--- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
@@ -185,6 +185,7 @@ allOf:
     then:
       properties:
         reg:
+          minItems: 3
           maxItems: 3
         reg-names:
           items:

-- 
2.49.0



From robh at kernel.org  Tue Mar 18 15:26:00 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Tue, 18 Mar 2025 17:26:00 -0500
Subject: [PATCH v4 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
Message-ID: <174233663954.4094319.18412685456723022993.robh@kernel.org>


On Tue, 18 Mar 2025 12:47:29 -0500, Rajaganesh Rathinasabapathi wrote:
> Document new AMD Onyx BMC board compatibles
> 
> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> ---
>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250318174730.1921983-1-Rajaganesh.Rathinasabapathi at amd.com:

arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e6e0000/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e780000/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e780000/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e780000/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: mbeeprom at 50: $nodename:0: 'mbeeprom at 50' does not match '^eeprom@[0-9a-f]{1,2}$'
	from schema $id: http://devicetree.org/schemas/eeprom/at24.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: mbeeprom at 50: Unevaluated properties are not allowed ('$nodename' was unexpected)
	from schema $id: http://devicetree.org/schemas/eeprom/at24.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e790000/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e790000/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: /ahb/apb at 1e790000/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']
arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-nf5280m6.dtb: /ahb/apb at 1e6e0000/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2500-gfx', 'syscon']







From sboyd at kernel.org  Tue Mar 18 15:50:31 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Tue, 18 Mar 2025 15:50:31 -0700
Subject: [PATCH v12 4/6] clk: qcom: Add NSS clock Controller driver for IPQ9574
In-Reply-To: <65gl7d6qd55xrdm3as3pnqevpmakin3k4jzyocehq7wq7565jj@x35t2inlykop>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com> <20250313110359.242491-5-quic_mmanikan@quicinc.com> <65gl7d6qd55xrdm3as3pnqevpmakin3k4jzyocehq7wq7565jj@x35t2inlykop>
Message-ID: <ef86ccad056bc03af7f01d5696787766.sboyd@kernel.org>

Quoting Marek Beh?n (2025-03-17 07:08:16)
> On Thu, Mar 13, 2025 at 04:33:57PM +0530, Manikanta Mylavarapu wrote:
> 
> > +static struct clk_rcg2 nss_cc_clc_clk_src = {
> > +     .cmd_rcgr = 0x28604,
> > +     .mnd_width = 0,
> > +     .hid_width = 5,
> > +     .parent_map = nss_cc_parent_map_6,
> > +     .freq_tbl = ftbl_nss_cc_clc_clk_src,
> > +     .clkr.hw.init = &(const struct clk_init_data) {
> > +             .name = "nss_cc_clc_clk_src",
> > +             .parent_data = nss_cc_parent_data_6,
> > +             .num_parents = ARRAY_SIZE(nss_cc_parent_data_6),
> > +             .ops = &clk_rcg2_ops,
> > +     },
> > +};
> 
> This structure definition gets repeated many times in this driver,
> with only slight changes. (This also happens in other qualcomm clock
> drivers.)
> 
> Would it be possible to refactor it into a macro, to avoid the
> insane code repetition?
> 

We have this discussion every couple years or so. The short answer is
no. The long answer is that it makes it harder to read because we don't
know what argument to the macro corresponds to the struct members.

It could probably use the CLK_HW_INIT_PARENTS_DATA macro though.

static struct clk_rcg2 nss_cc_clc_clk_src = {
     .cmd_rcgr = 0x28604,
     .mnd_width = 0,
     .hid_width = 5,
     .parent_map = nss_cc_parent_map_6,
     .freq_tbl = ftbl_nss_cc_clc_clk_src,
     .clkr.hw.init = CLK_HW_INIT_PARENTS_DATA("nss_cc_clc_clk_src",
                                              nss_cc_parent_data_6,
					      &clk_rcg2_ops, 0),
     },
};

but then we lose the const. Oh well.

The whole qcom clk driver probably needs an overhaul to just have
descriptors that populate a bunch of clks that are allocated at probe
time so that the memory footprint is smaller if you have multiple clk
drivers loaded and so that we can probe the driver again without
unloading the whole kernel module.


From lkp at intel.com  Tue Mar 18 15:56:22 2025
From: lkp at intel.com (kernel test robot)
Date: Wed, 19 Mar 2025 06:56:22 +0800
Subject: [PATCH v6 2/4] virtio_rtc: Add PTP clocks
In-Reply-To: <20250313173707.1492-3-quic_philber@quicinc.com>
References: <20250313173707.1492-3-quic_philber@quicinc.com>
Message-ID: <202503190602.IElWB74j-lkp@intel.com>

Hi Peter,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 9d8960672d63db4b3b04542f5622748b345c637a]

url:    https://github.com/intel-lab-lkp/linux/commits/Peter-Hilber/virtio_rtc-Add-module-and-driver-core/20250314-014130
base:   9d8960672d63db4b3b04542f5622748b345c637a
patch link:    https://lore.kernel.org/r/20250313173707.1492-3-quic_philber%40quicinc.com
patch subject: [PATCH v6 2/4] virtio_rtc: Add PTP clocks
config: sparc-allyesconfig (https://download.01.org/0day-ci/archive/20250319/202503190602.IElWB74j-lkp at intel.com/config)
compiler: sparc64-linux-gcc (GCC) 7.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250319/202503190602.IElWB74j-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503190602.IElWB74j-lkp at intel.com/

All warnings (new ones prefixed by >>):

   drivers/virtio/virtio_rtc_driver.c: In function 'viortc_probe':
>> drivers/virtio/virtio_rtc_driver.c:665:23: warning: '/variant ' directive output may be truncated writing 9 bytes into a region of size between 6 and 15 [-Wformat-truncation=]
       "Virtio PTP type %d/variant %d", clock_type,
                          ^~~~~~~~~
   drivers/virtio/virtio_rtc_driver.c:665:4: note: directive argument in the range [0, 2147483647]
       "Virtio PTP type %d/variant %d", clock_type,
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/virtio/virtio_rtc_driver.c:664:2: note: 'snprintf' output between 28 and 46 bytes into a destination of size 32
     snprintf(ptp_clock_name, PTP_CLOCK_NAME_LEN,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       "Virtio PTP type %d/variant %d", clock_type,
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       leap_second_smearing);
       ~~~~~~~~~~~~~~~~~~~~~


vim +665 drivers/virtio/virtio_rtc_driver.c

   641	
   642	/*
   643	 * init, deinit
   644	 */
   645	
   646	/**
   647	 * viortc_init_ptp_clock() - init and register PTP clock
   648	 * @viortc: device data
   649	 * @vio_clk_id: virtio_rtc clock id
   650	 * @clock_type: virtio_rtc clock type
   651	 * @leap_second_smearing: virtio_rtc leap second smearing
   652	 *
   653	 * Context: Process context.
   654	 * Return: Positive if registered, zero if not supported by configuration,
   655	 *         negative error code otherwise.
   656	 */
   657	static int viortc_init_ptp_clock(struct viortc_dev *viortc, u16 vio_clk_id,
   658					 u8 clock_type, u8 leap_second_smearing)
   659	{
   660		struct device *dev = &viortc->vdev->dev;
   661		char ptp_clock_name[PTP_CLOCK_NAME_LEN];
   662		struct viortc_ptp_clock *vio_ptp;
   663	
   664		snprintf(ptp_clock_name, PTP_CLOCK_NAME_LEN,
 > 665			 "Virtio PTP type %d/variant %d", clock_type,
   666			 leap_second_smearing);
   667	
   668		vio_ptp = viortc_ptp_register(viortc, dev, vio_clk_id, ptp_clock_name);
   669		if (IS_ERR(vio_ptp)) {
   670			dev_err(dev, "failed to register PTP clock '%s'\n",
   671				ptp_clock_name);
   672			return PTR_ERR(vio_ptp);
   673		}
   674	
   675		viortc->clocks_to_unregister[vio_clk_id] = vio_ptp;
   676	
   677		return !!vio_ptp;
   678	}
   679	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From sbellary at baylibre.com  Tue Mar 18 16:00:42 2025
From: sbellary at baylibre.com (Sukrut Bellary)
Date: Tue, 18 Mar 2025 16:00:42 -0700
Subject: [PATCH 4/4] ARM: multi_v7_defconfig: Enable am335x PM configs
In-Reply-To: <20250318230042.3138542-1-sbellary@baylibre.com>
References: <20250318230042.3138542-1-sbellary@baylibre.com>
Message-ID: <20250318230042.3138542-5-sbellary@baylibre.com>

Enable Power management related defconfigs for TI AM335x[1].

[1] AM335x TRM - https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf

Signed-off-by: Sukrut Bellary <sbellary at baylibre.com>
---
 arch/arm/configs/multi_v7_defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 37e3baa33b67..1d2600b5f975 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -985,6 +985,7 @@ CONFIG_EDAC=y
 CONFIG_EDAC_LAYERSCAPE=y
 CONFIG_EDAC_HIGHBANK_MC=y
 CONFIG_EDAC_HIGHBANK_L2=y
+CONFIG_RTC_DRV_OMAP=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AC100=y
 CONFIG_RTC_DRV_AS3722=y
@@ -1095,6 +1096,7 @@ CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_EXYNOS_IOMMU=y
 CONFIG_QCOM_IOMMU=y
 CONFIG_REMOTEPROC=y
+CONFIG_WKUP_M3_RPROC=m
 CONFIG_OMAP_REMOTEPROC=m
 CONFIG_OMAP_REMOTEPROC_WATCHDOG=y
 CONFIG_KEYSTONE_REMOTEPROC=m
@@ -1146,6 +1148,8 @@ CONFIG_ARCH_TEGRA_3x_SOC=y
 CONFIG_ARCH_TEGRA_114_SOC=y
 CONFIG_ARCH_TEGRA_124_SOC=y
 CONFIG_SOC_TI=y
+CONFIG_AMX3_PM=m
+CONFIG_WKUP_M3_IPC=m
 CONFIG_KEYSTONE_NAVIGATOR_QMSS=y
 CONFIG_KEYSTONE_NAVIGATOR_DMA=y
 CONFIG_RASPBERRYPI_POWER=y
@@ -1162,6 +1166,7 @@ CONFIG_EXTCON_MAX77693=m
 CONFIG_EXTCON_MAX8997=m
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_TI_AEMIF=y
+CONFIG_TI_EMIF_SRAM=m
 CONFIG_STM32_FMC2_EBI=y
 CONFIG_EXYNOS5422_DMC=m
 CONFIG_IIO=y
-- 
2.34.1



From jacob.e.keller at intel.com  Tue Mar 18 16:08:06 2025
From: jacob.e.keller at intel.com (Keller, Jacob E)
Date: Tue, 18 Mar 2025 23:08:06 +0000
Subject: [PATCH net v2] net: stmmac: Fix accessing freed irq affinity_hint
In-Reply-To: <20250318032424.112067-1-dqfext@gmail.com>
References: <20250318032424.112067-1-dqfext@gmail.com>
Message-ID: <CO1PR11MB50891366B8997C225707C519D6DE2@CO1PR11MB5089.namprd11.prod.outlook.com>



> -----Original Message-----
> From: Qingfang Deng <dqfext at gmail.com>
> Sent: Monday, March 17, 2025 8:24 PM
> To: Andrew Lunn <andrew+netdev at lunn.ch>; David S. Miller
> <davem at davemloft.net>; Dumazet, Eric <edumazet at google.com>; Jakub Kicinski
> <kuba at kernel.org>; Paolo Abeni <pabeni at redhat.com>; Maxime Coquelin
> <mcoquelin.stm32 at gmail.com>; Alexandre Torgue
> <alexandre.torgue at foss.st.com>; Ong, Boon Leong
> <boon.leong.ong at intel.com>; netdev at vger.kernel.org; linux-stm32 at st-md-
> mailman.stormreply.com; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org
> Cc: stable at vger.kernel.org
> Subject: [PATCH net v2] net: stmmac: Fix accessing freed irq affinity_hint
> 
> The cpumask should not be a local variable, since its pointer is saved
> to irq_desc and may be accessed from procfs.
> To fix it, use the persistent mask cpumask_of(cpu#).
> 
> Cc: stable at vger.kernel.org
> Fixes: 8deec94c6040 ("net: stmmac: set IRQ affinity hint for multi MSI vectors")
> Signed-off-by: Qingfang Deng <dqfext at gmail.com>
> ---
> v2: use cpumask_of()
> 

Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>


From jpoimboe at kernel.org  Tue Mar 18 16:00:32 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Tue, 18 Mar 2025 16:00:32 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
 <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>
Message-ID: <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>

On Tue, Mar 18, 2025 at 01:14:40PM -0700, Song Liu wrote:
> >
> > See for example all the error conditions in the x86 version of
> > arch_stack_walk_reliable() and in arch/x86/kernel/unwind_frame.c.
> 
> I guess I missed this part:
> 
> diff --git i/arch/arm64/kernel/stacktrace.c w/arch/arm64/kernel/stacktrace.c
> index 69d0567a0c38..3bb8e3ea4c4b 100644
> --- i/arch/arm64/kernel/stacktrace.c
> +++ w/arch/arm64/kernel/stacktrace.c
> @@ -268,6 +268,8 @@ kunwind_next(struct kunwind_state *state)
>         case KUNWIND_SOURCE_TASK:
>         case KUNWIND_SOURCE_REGS_PC:
>                 err = kunwind_next_frame_record(state);
> +               if (err && err != -ENOENT)
> +                       state->common.unreliable = true;
>                 break;
>         default:
>                 err = -EINVAL;

I still see some issues:

  - do_kunwind() -> kunwind_recover_return_address() can fail

  - do_kunwind() -> consume_state() can fail

  - even in the -ENOENT case the unreliable bit has already been set
    right before the call to kunwind_next_frame_record_meta().

-- 
Josh


From sbellary at baylibre.com  Tue Mar 18 16:00:38 2025
From: sbellary at baylibre.com (Sukrut Bellary)
Date: Tue, 18 Mar 2025 16:00:38 -0700
Subject: [PATCH 0/4] PM: TI: AM335x: PM STANDBY fixes
Message-ID: <20250318230042.3138542-1-sbellary@baylibre.com>

This patch series fixes the Power management issues on TI's am335x soc.

on AM335x, the wakeup doesn't work in the case of STANDBY.

1. Since CM3 PM FW [1](ti-v4.1.y) doesn't enable l4ls clockdomain upon
wakeup, it fails to wakeup the MPU.
To fix this, don't turn off the l4ls clk domain in the STANDBY transition
in MPU.

2. Also Per AM335x TRM [2](section 8.1.4.3 Power mode), in case of STANDBY,
PER domain should be ON. So fix PER power domain handling for 
standby. l4ls is a part of the PER domain.

Since we are not turning off the l4ls clockdomain on STANDBY in MPU,
PER power domain would remain ON. But still, explicitly handle this
to be in sync with the STANDBY requirement.

3. On am335x evm[1], UART0 - (UART1-HW) has a wakeup capability.
Set the wakeup-source property in DT for AM335x.

4. Enable PM configs for AM335x.

[1] https://git.ti.com/cgit/processor-firmware/ti-amx3-cm3-pm-firmware/
[2] https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf
[3] https://www.ti.com/tool/TMDXEVM3358

Test log:
https://gist.github.com/sukrutb/bdbfd1220fe8578a9decf87d0bac6796

Sukrut Bellary (4):
  ARM: OMAP2+: Fix l4ls clk domain handling in STANDBY
  pmdomain: ti: Fix STANDBY handling of PER power domain
  ARM: dts: am335x: Set wakeup-source for UART0
  ARM: multi_v7_defconfig: Enable am335x PM configs

 arch/arm/boot/dts/ti/omap/am335x-evm.dts    |  2 +-
 arch/arm/configs/multi_v7_defconfig         |  5 +++++
 arch/arm/mach-omap2/clockdomain.h           |  1 +
 arch/arm/mach-omap2/clockdomains33xx_data.c |  2 +-
 arch/arm/mach-omap2/cm33xx.c                | 14 +++++++++++++-
 drivers/pmdomain/ti/omap_prm.c              |  8 ++++++--
 6 files changed, 27 insertions(+), 5 deletions(-)

-- 
2.34.1



From sbellary at baylibre.com  Tue Mar 18 16:00:39 2025
From: sbellary at baylibre.com (Sukrut Bellary)
Date: Tue, 18 Mar 2025 16:00:39 -0700
Subject: [PATCH 1/4] ARM: OMAP2+: Fix l4ls clk domain handling in STANDBY
In-Reply-To: <20250318230042.3138542-1-sbellary@baylibre.com>
References: <20250318230042.3138542-1-sbellary@baylibre.com>
Message-ID: <20250318230042.3138542-2-sbellary@baylibre.com>

Don't put the l4ls clk domain to sleep in case of standby.
Since CM3 PM FW[1](ti-v4.1.y) doesn't wake-up/enable the l4ls clk domain
upon wake-up, CM3 PM FW fails to wake-up the MPU.

[1] https://git.ti.com/cgit/processor-firmware/ti-amx3-cm3-pm-firmware/

Signed-off-by: Sukrut Bellary <sbellary at baylibre.com>
---
 arch/arm/mach-omap2/clockdomain.h           |  1 +
 arch/arm/mach-omap2/clockdomains33xx_data.c |  2 +-
 arch/arm/mach-omap2/cm33xx.c                | 14 +++++++++++++-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index c36fb2721261..86a2f9e5d0ef 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -48,6 +48,7 @@
 #define CLKDM_NO_AUTODEPS			(1 << 4)
 #define CLKDM_ACTIVE_WITH_MPU			(1 << 5)
 #define CLKDM_MISSING_IDLE_REPORTING		(1 << 6)
+#define CLKDM_STANDBY_FORCE_WAKEUP		BIT(7)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
diff --git a/arch/arm/mach-omap2/clockdomains33xx_data.c b/arch/arm/mach-omap2/clockdomains33xx_data.c
index 87f4e927eb18..c05a3c07d448 100644
--- a/arch/arm/mach-omap2/clockdomains33xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains33xx_data.c
@@ -19,7 +19,7 @@ static struct clockdomain l4ls_am33xx_clkdm = {
 	.pwrdm		= { .name = "per_pwrdm" },
 	.cm_inst	= AM33XX_CM_PER_MOD,
 	.clkdm_offs	= AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET,
-	.flags		= CLKDM_CAN_SWSUP,
+	.flags		= CLKDM_CAN_SWSUP | CLKDM_STANDBY_FORCE_WAKEUP,
 };
 
 static struct clockdomain l3s_am33xx_clkdm = {
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index acdf72a541c0..a4dd42abda89 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -20,6 +20,9 @@
 #include "cm-regbits-34xx.h"
 #include "cm-regbits-33xx.h"
 #include "prm33xx.h"
+#if IS_ENABLED(CONFIG_SUSPEND)
+#include <linux/suspend.h>
+#endif
 
 /*
  * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
@@ -328,8 +331,17 @@ static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
 {
 	bool hwsup = false;
 
+#if IS_ENABLED(CONFIG_SUSPEND)
+	/*
+	 * In case of standby, Don't put the l4ls clk domain to sleep.
+	 * Since CM3 PM FW doesn't wake-up/enable the l4ls clk domain
+	 * upon wake-up, CM3 PM FW fails to wake-up th MPU.
+	 */
+	if (pm_suspend_target_state == PM_SUSPEND_STANDBY &&
+	    (clkdm->flags & CLKDM_STANDBY_FORCE_WAKEUP))
+		return 0;
+#endif
 	hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
-
 	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
 		am33xx_clkdm_sleep(clkdm);
 
-- 
2.34.1



From sbellary at baylibre.com  Tue Mar 18 16:00:40 2025
From: sbellary at baylibre.com (Sukrut Bellary)
Date: Tue, 18 Mar 2025 16:00:40 -0700
Subject: [PATCH 2/4] pmdomain: ti: Fix STANDBY handling of PER power domain
In-Reply-To: <20250318230042.3138542-1-sbellary@baylibre.com>
References: <20250318230042.3138542-1-sbellary@baylibre.com>
Message-ID: <20250318230042.3138542-3-sbellary@baylibre.com>

Per AM335x TRM[1](section 8.1.4.3 Power mode), in case of STANDBY,
PER domain should be ON. So, fix the PER power domain handling on standby.

[1] https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf

Signed-off-by: Sukrut Bellary <sbellary at baylibre.com>
---
 drivers/pmdomain/ti/omap_prm.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/pmdomain/ti/omap_prm.c b/drivers/pmdomain/ti/omap_prm.c
index b8ceb3c2b81c..7e36e675a8c6 100644
--- a/drivers/pmdomain/ti/omap_prm.c
+++ b/drivers/pmdomain/ti/omap_prm.c
@@ -18,7 +18,9 @@
 #include <linux/pm_domain.h>
 #include <linux/reset-controller.h>
 #include <linux/delay.h>
-
+#if IS_ENABLED(CONFIG_SUSPEND)
+#include <linux/suspend.h>
+#endif
 #include <linux/platform_data/ti-prm.h>
 
 enum omap_prm_domain_mode {
@@ -88,6 +90,7 @@ struct omap_reset_data {
 #define OMAP_PRM_HAS_RSTST	BIT(1)
 #define OMAP_PRM_HAS_NO_CLKDM	BIT(2)
 #define OMAP_PRM_RET_WHEN_IDLE	BIT(3)
+#define OMAP_PRM_ON_WHEN_STANDBY	BIT(4)
 
 #define OMAP_PRM_HAS_RESETS	(OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
 
@@ -404,7 +407,8 @@ static const struct omap_prm_data am3_prm_data[] = {
 		.name = "per", .base = 0x44e00c00,
 		.pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact,
 		.rstctrl = 0x0, .rstmap = am3_per_rst_map,
-		.flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp"
+		.flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_ON_WHEN_STANDBY,
+		.clkdm_name = "pruss_ocp",
 	},
 	{
 		.name = "wkup", .base = 0x44e00d00,
-- 
2.34.1



From sbellary at baylibre.com  Tue Mar 18 16:00:41 2025
From: sbellary at baylibre.com (Sukrut Bellary)
Date: Tue, 18 Mar 2025 16:00:41 -0700
Subject: [PATCH 3/4] ARM: dts: am335x: Set wakeup-source for UART0
In-Reply-To: <20250318230042.3138542-1-sbellary@baylibre.com>
References: <20250318230042.3138542-1-sbellary@baylibre.com>
Message-ID: <20250318230042.3138542-4-sbellary@baylibre.com>

On am335x evm[1], UART0(UART1-HW) has a wakeup capability.
Set wakeup-source, which will be used in the omap serial driver to enable
the device wakeup capability.

[1] https://www.ti.com/tool/TMDXEVM3358
[2] AM335x TRM - https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf

Signed-off-by: Sukrut Bellary <sbellary at baylibre.com>
---
 arch/arm/boot/dts/ti/omap/am335x-evm.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/ti/omap/am335x-evm.dts b/arch/arm/boot/dts/ti/omap/am335x-evm.dts
index 61bf8bcd4c4e..20222f82f21b 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-evm.dts
@@ -388,7 +388,7 @@ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE2) /* uart0_rt
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins>;
-
+	wakeup-source;
 	status = "okay";
 };
 
-- 
2.34.1



From jgg at nvidia.com  Tue Mar 18 16:09:09 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Tue, 18 Mar 2025 20:09:09 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9nJ42PllG8a7AY7@linux.dev>
References: <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
Message-ID: <20250318230909.GD9311@nvidia.com>

On Tue, Mar 18, 2025 at 12:30:43PM -0700, Oliver Upton wrote:
> On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
> > On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
> > 
> > > The memslot must also be created with a new flag ((2c) in the taxonomy
> > > above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
> > > flag is only allowed if (1) is valid.
> > > 
> > > This results in the following behaviours:
> > > 
> > > - If the VMM creates the memslot with the cacheable attribute without
> > >   (1) being advertised, we fail.
> > > 
> > > - If the VMM creates the memslot without the cacheable attribute, we
> > >   map as NC, as it is today.
> > 
> > Is that OK though?
> > 
> > Now we have the MM page tables mapping this memory as cachable but KVM
> > and the guest is accessing it as non-cached.
> > 
> > I thought ARM tried hard to avoid creating such mismatches? This is
> > why the pgprot flags were used to drive this, not an opt-in flag. To
> > prevent userspace from forcing a mismatch.
> 
> It's far more problematic the other way around, e.g. the host knows that
> something needs a Device-* attribute and the VM has done something
> cacheable. The endpoint for that PA could, for example, fall over when
> lines pulled in by the guest are written back, which of course can't
> always be traced back to the offending VM.
> 
> OTOH, if the host knows that a PA is cacheable and the guest does
> something non-cacheable, you 'just' have to deal with the usual
> mismatched attributes problem as laid out in the ARM ARM.

I think the issue is that KVM doesn't do that usual stuff (ie cache
flushing) for memory that doesn't have a struct page backing.

So nothing in the hypervisor does any cache flushing and I belive you
end up with a situation where the VMM could have zero'd this cachable
memory using cachable stores to sanitize it across VMs and then KVM
can put that memory into the VM as uncached and the VM could then
access stale non-zeroed data from a prior VM. Yes? This is a security
problem.

As I understand things KVM must either do the cache flushing, or must
not allow mismatched attributes, as a matter of security.

This is why FWB comes into the picture because KVM cannot do the cache
flushing of PFNMAP VMAs. So we force the MM and KVM S2 to be cachable
and use S2 FWB to prevent the guest from ever making it
uncachable. Thus the cache flushes are not required and everything is
security safe.

So I think the logic we want here in the fault handler is to:
  Get the mm's PTE
  If it is cachable:
    Check if it has a struct page:
       Yes - KVM flushes it and can use a non-FWB path
       No - KVM either fails to install it, or installs it using FWB
           to force cachability. KVM never allows degrading cachable
	   to non-cachable when it can't do flushing.
  Not cachable:
    Install it with Normal-NC as was previously discussed and merged

> Userspace should be stating intentions on the memslot with the sort of
> mapping that it wants to create, and a memslot flag to say "I allow
> cacheable mappings" seems to fit the bill.

I'm not sure about this, I don't see that the userspace has any
choice. As above, KVM has to follow whatever is in the PTEs, the
userspace can't ask for something different here. At best you could
make non-struct page cachable memory always fail unless the flag is
given - but why?

It seems sufficient for fast fail to check if the VMA has PFNMAP and
pgprot cachable then !FEAT_FWB fails the memslot. There is no real
recovery from this, the VMM is doing something that cannot be
supported.

>  - Stage-2 faults serviced w/ a non-cacheable mapping if flag is not
>    set

As above, I think this creates a bug :\

Jason


From jgg at nvidia.com  Tue Mar 18 16:17:36 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Tue, 18 Mar 2025 20:17:36 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9nJH38Em9XEx3U7@arm.com>
References: <SA1PR12MB7199DD985C45943A663E7003B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com>
Message-ID: <20250318231736.GE9311@nvidia.com>

On Tue, Mar 18, 2025 at 07:27:27PM +0000, Catalin Marinas wrote:

> Thinking some more about a KVM capability that the VMM can check, I'm
> not sure what it can do with this. The VMM simply maps something from a
> device and cannot probe the cacheability 

KVM is mirroring the MM's PTEs to the S2's PTEs.

You can think about this differently - KVM currently has a little bug
where the MM's PTE's can say cachable but KVM will mirror it to a S2
PTE that is forced non-cachable. KVM will not do any cache flushing to
make this safe.

Fundamentally that discrepancy is what is being addressed
here. Cachable PTEs in the MM should be mirrored to cachable PTEs in
the S2.

That the issue only arises with non-struct page memory is just part of
the triggering condition..

> I assume with the cacheable pfn mapping, the whole range covered by the
> vma is entirely safe to be mapped as such in user space.

Yes

Jason


From heiko at sntech.de  Tue Mar 18 16:24:42 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 19 Mar 2025 00:24:42 +0100
Subject: [PATCH] arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0
In-Reply-To: <20250314-rk3576-sige5-eth-clk-begone-v1-1-2858338fc555@collabora.com>
References: <20250314-rk3576-sige5-eth-clk-begone-v1-1-2858338fc555@collabora.com>
Message-ID: <174234022086.1144821.10038416716073358190.b4-ty@sntech.de>


On Fri, 14 Mar 2025 16:35:50 +0100, Nicolas Frattaroli wrote:
> The GPIO3 A4 pin on the ArmSoM Sige5 is routed to the 40-pin GPIO
> header. This pin can serve a variety of functions, including ones of
> questionable use to us on a GPIO header such as the 25MHz clock of the
> ethernet controller.
> 
> Unfortunately, this is the precise function that it is being claimed for
> by the gmac0 node in the Sige5 board dts, meaning it can't be used for
> anything else despite serving no useful function in this role. Since it
> goes through a RS0108 bidirectional voltage level translator with a
> maximum data rate of 24Mbit/s in push-pull mode and 2Mbit/s data rate in
> open-drain mode, it's doubtful as to whether the 25MHz clock signal
> would even survive to the actual user-accessible pin it terminates in.
> 
> [...]

Applied, thanks!

[1/1] arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0
      commit: 73d246b4402c3356f6b3d13665de3a51eea7b555

Actually applied this some days ago, but b4 is of the opinion,
I didn't sent out an applied-message yet, so doing that now :-) .


Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From heiko at sntech.de  Tue Mar 18 16:24:41 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 19 Mar 2025 00:24:41 +0100
Subject: [PATCH] Revert "dt-bindings: mfd: syscon: Add rk3528 QoS register compatible"
In-Reply-To: <20250317230705.932808-1-heiko@sntech.de>
References: <20250317230705.932808-1-heiko@sntech.de>
Message-ID: <174234022088.1144821.1552001262318084726.b4-ty@sntech.de>


On Tue, 18 Mar 2025 00:07:05 +0100, Heiko Stuebner wrote:
> This reverts commit 19a634195c1abe498798b564cd6b81e6dd4533f7.
> 
> The dt-binding addition adds the compatible to a syscon (a mfd) and should
> go through the mfd tree. And it did, and is part of the mfd tree for 6.15
> as commit 7f3e3e7228bb ("dt-bindings: mfd: syscon: Add rk3528 QoS register
> compatible"), with all the correct Signed-off-by lines.
> 
> [...]

Applied, thanks!

[1/1] Revert "dt-bindings: mfd: syscon: Add rk3528 QoS register compatible"
      commit: cee24bc73d4f3f47344a1a54100a69c72f1db061

Best regards,
-- 
Heiko Stuebner <heiko at sntech.de>


From andi.shyti at kernel.org  Tue Mar 18 16:34:53 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Wed, 19 Mar 2025 00:34:53 +0100
Subject: [PATCH v5 1/1] i2c: mediatek: add runtime PM operations and bus
 regulator control
In-Reply-To: <20250314145407.2900190-1-zoie.lin@mediatek.com>
References: <20250314145407.2900190-1-zoie.lin@mediatek.com>
Message-ID: <fqicrglyug7gmkmysok7hilhmkyhxmnkztzv4iffgry6xce6t3@2i6b2ihfu4rb>

Hi Zoie,

On Fri, Mar 14, 2025 at 10:53:43PM +0800, Zoie Lin wrote:
> Introduce support for runtime PM operations in
> the I2C driver, enabling runtime suspend and resume functionality.
> 
> Although in most platforms, the bus power of i2c is always
> on, some platforms disable the i2c bus power in order to meet
> low power request.
> 
> This implementation includes bus regulator control to facilitate
> proper handling of the bus power based on platform requirements.
> 
> Signed-off-by: Zoie Lin <zoie.lin at mediatek.com>

merged to i2c/i2c-host.

Thanks,
Andi


From song at kernel.org  Tue Mar 18 16:38:20 2025
From: song at kernel.org (Song Liu)
Date: Tue, 18 Mar 2025 16:38:20 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>
References: <20250308012742.3208215-1-song@kernel.org> <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
 <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com> <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>
Message-ID: <CAPhsuW4BEDU=ZJavnofZtygGcQ9AJ5F2jJiuV6-nsnbZD+Gg-Q@mail.gmail.com>

On Tue, Mar 18, 2025 at 4:00?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
>
> On Tue, Mar 18, 2025 at 01:14:40PM -0700, Song Liu wrote:
> > >
> > > See for example all the error conditions in the x86 version of
> > > arch_stack_walk_reliable() and in arch/x86/kernel/unwind_frame.c.
> >
> > I guess I missed this part:
> >
> > diff --git i/arch/arm64/kernel/stacktrace.c w/arch/arm64/kernel/stacktrace.c
> > index 69d0567a0c38..3bb8e3ea4c4b 100644
> > --- i/arch/arm64/kernel/stacktrace.c
> > +++ w/arch/arm64/kernel/stacktrace.c
> > @@ -268,6 +268,8 @@ kunwind_next(struct kunwind_state *state)
> >         case KUNWIND_SOURCE_TASK:
> >         case KUNWIND_SOURCE_REGS_PC:
> >                 err = kunwind_next_frame_record(state);
> > +               if (err && err != -ENOENT)
> > +                       state->common.unreliable = true;
> >                 break;
> >         default:
> >                 err = -EINVAL;
>
> I still see some issues:
>
>   - do_kunwind() -> kunwind_recover_return_address() can fail
>
>   - do_kunwind() -> consume_state() can fail

Great points! I have got the following:

diff --git i/arch/arm64/kernel/stacktrace.c w/arch/arm64/kernel/stacktrace.c
index 69d0567a0c38..852e4b322209 100644
--- i/arch/arm64/kernel/stacktrace.c
+++ w/arch/arm64/kernel/stacktrace.c
@@ -139,6 +139,7 @@ kunwind_recover_return_address(struct kunwind_state *state)
                                                (void *)state->common.fp);
                if (state->common.pc == orig_pc) {
                        WARN_ON_ONCE(state->task == current);
+                       state->common.unreliable = true;
                        return -EINVAL;
                }
                state->common.pc = orig_pc;
@@ -268,6 +269,8 @@ kunwind_next(struct kunwind_state *state)
        case KUNWIND_SOURCE_TASK:
        case KUNWIND_SOURCE_REGS_PC:
                err = kunwind_next_frame_record(state);
+               if (err && err != -ENOENT)
+                       state->common.unreliable = true;
                break;
        default:
                err = -EINVAL;
@@ -404,12 +407,16 @@ static __always_inline bool
 arch_kunwind_reliable_consume_entry(const struct kunwind_state
*state, void *cookie)
 {
        struct kunwind_reliable_consume_entry_data *data = cookie;
+       bool ret;

        if (state->common.unreliable) {
                data->unreliable = true;
                return false;
        }
-       return data->consume_entry(data->cookie, state->common.pc);
+       ret = data->consume_entry(data->cookie, state->common.pc);
+       if (!ret)
+               data->unreliable = true;
+       return ret;
 }

 noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn
consume_entry,


>   - even in the -ENOENT case the unreliable bit has already been set
>     right before the call to kunwind_next_frame_record_meta().

For this one, do you mean we set state->common.unreliable, but
failed to propagate it to data.unreliable?

Thanks,
Song


From gshan at redhat.com  Tue Mar 18 17:26:14 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 19 Mar 2025 10:26:14 +1000
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
Message-ID: <019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>

Hi Mark,

On 3/14/25 10:35 AM, Mark Brown wrote:
> From: Mark Rutland <mark.rutland at arm.com>
> 
> [ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]
> 
> In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
> CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:
> 
> * For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
>    by the guest hypervisor, which may be less than or equal to that
>    guest's maximum VL.
> 
>    Note: in this case the value of ZCR_EL1 is immaterial due to E2H.
> 
> * For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
>    which may be less than or greater than the guest's maximum VL.
> 
>    Note: in this case hyp code traps host SVE usage and lazily restores
>    ZCR_EL2 to the host's maximum VL, which may be greater than the
>    guest's maximum VL.
> 
> This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
> If a softirq is taken during this period and the softirq handler tries
> to use kernel-mode NEON, then the kernel will fail to save the guest's
> FPSIMD/SVE state, and will pend a SIGKILL for the current thread.
> 
> This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
> FPSIMD/SVE state with the guest's maximum SVE VL, and
> fpsimd_save_user_state() verifies that the live SVE VL is as expected
> before attempting to save the register state:
> 
> | if (WARN_ON(sve_get_vl() != vl)) {
> |         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
> |         return;
> | }
> 
> Fix this and make this a bit easier to reason about by always eagerly
> switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
> happening, there's no need to trap host SVE usage, and the nVHE/nVHE
> __deactivate_cptr_traps() logic can be simplified to enable host access
> to all present FPSIMD/SVE/SME features.
> 
> In protected nVHE/hVHE modes, the host's state is always saved/restored
> by hyp, and the guest's state is saved prior to exit to the host, so
> from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
> the host's ZCR_EL1 is never clobbered by hyp.
> 
> Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
> Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Reviewed-by: Mark Brown <broonie at kernel.org>
> Tested-by: Mark Brown <broonie at kernel.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Fuad Tabba <tabba at google.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Cc: Will Deacon <will at kernel.org>
> Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
> Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
>   arch/arm64/kvm/fpsimd.c                 | 30 -----------------
>   arch/arm64/kvm/hyp/entry.S              |  5 +++
>   arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
>   arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 13 ++++----
>   arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
>   arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
>   6 files changed, 103 insertions(+), 41 deletions(-)
> 

[...]

> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 4e757a77322c9efc59cdff501745f7c80d452358..1c8e2ad32e8c396fc4b11d5fec2e86728f2829d9 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -5,6 +5,7 @@
>    */
>   
>   #include <hyp/adjust_pc.h>
> +#include <hyp/switch.h>
>   
>   #include <asm/pgtable-types.h>
>   #include <asm/kvm_asm.h>
> @@ -176,8 +177,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
>   		sync_hyp_vcpu(hyp_vcpu);
>   		pkvm_put_hyp_vcpu(hyp_vcpu);
>   	} else {
> +		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
> +
>   		/* The host is fully trusted, run its vCPU directly. */
> -		ret = __kvm_vcpu_run(host_vcpu);
> +		fpsimd_lazy_switch_to_guest(vcpu);
> +		ret = __kvm_vcpu_run(vcpu);
> +		fpsimd_lazy_switch_to_host(vcpu);
>   	}
>   

@host_vcpu should have been hypervisor's linear mapping address in v6.12. It looks
incorrect to assume it's a kernel's linear mapping address and convert it (@host_vcpu)
to the hypervisor's linear address agin, if I don't miss anything.

https://web.git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/kvm/hyp/nvhe/hyp-main.c?h=linux-6.12.y

Thanks,
Gavin

>   out:
> @@ -486,12 +491,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
>   	case ESR_ELx_EC_SMC64:
>   		handle_host_smc(host_ctxt);
>   		break;
> -	case ESR_ELx_EC_SVE:
> -		cpacr_clear_set(0, CPACR_ELx_ZEN);
> -		isb();
> -		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
> -				       SYS_ZCR_EL2);
> -		break;
>   	case ESR_ELx_EC_IABT_LOW:
>   	case ESR_ELx_EC_DABT_LOW:
>   		handle_host_mem_abort(host_ctxt);
> diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
> index ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494..a1245fa838319544f3770a05a58eeed5233f0324 100644
> --- a/arch/arm64/kvm/hyp/nvhe/switch.c
> +++ b/arch/arm64/kvm/hyp/nvhe/switch.c
> @@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
>   {
>   	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
>   
> +	if (!guest_owns_fp_regs())
> +		__activate_traps_fpsimd32(vcpu);
> +
>   	if (has_hvhe()) {
>   		val |= CPACR_ELx_TTA;
>   
> @@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
>   			if (vcpu_has_sve(vcpu))
>   				val |= CPACR_ELx_ZEN;
>   		}
> +
> +		write_sysreg(val, cpacr_el1);
>   	} else {
>   		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
>   
> @@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
>   
>   		if (!guest_owns_fp_regs())
>   			val |= CPTR_EL2_TFP;
> +
> +		write_sysreg(val, cptr_el2);
>   	}
> +}
>   
> -	if (!guest_owns_fp_regs())
> -		__activate_traps_fpsimd32(vcpu);
> +static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
> +{
> +	if (has_hvhe()) {
> +		u64 val = CPACR_ELx_FPEN;
> +
> +		if (cpus_have_final_cap(ARM64_SVE))
> +			val |= CPACR_ELx_ZEN;
> +		if (cpus_have_final_cap(ARM64_SME))
> +			val |= CPACR_ELx_SMEN;
> +
> +		write_sysreg(val, cpacr_el1);
> +	} else {
> +		u64 val = CPTR_NVHE_EL2_RES1;
> +
> +		if (!cpus_have_final_cap(ARM64_SVE))
> +			val |= CPTR_EL2_TZ;
> +		if (!cpus_have_final_cap(ARM64_SME))
> +			val |= CPTR_EL2_TSM;
>   
> -	kvm_write_cptr_el2(val);
> +		write_sysreg(val, cptr_el2);
> +	}
>   }
>   
>   static void __activate_traps(struct kvm_vcpu *vcpu)
> @@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
>   
>   	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
>   
> -	kvm_reset_cptr_el2(vcpu);
> +	__deactivate_cptr_traps(vcpu);
>   	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
>   }
>   
> diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
> index 46c1f5caf007331cdbbc806a184e9b4721042fc0..496abfd3646b9858e95e06a79edec11eee3a5893 100644
> --- a/arch/arm64/kvm/hyp/vhe/switch.c
> +++ b/arch/arm64/kvm/hyp/vhe/switch.c
> @@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
>   
>   	sysreg_save_host_state_vhe(host_ctxt);
>   
> +	fpsimd_lazy_switch_to_guest(vcpu);
> +
>   	/*
>   	 * Note that ARM erratum 1165522 requires us to configure both stage 1
>   	 * and stage 2 translation for the guest context before we clear
> @@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
>   
>   	__deactivate_traps(vcpu);
>   
> +	fpsimd_lazy_switch_to_host(vcpu);
> +
>   	sysreg_restore_host_state_vhe(host_ctxt);
>   
>   	if (guest_owns_fp_regs())
> 



From nunodasneves at linux.microsoft.com  Tue Mar 18 17:34:16 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Tue, 18 Mar 2025 17:34:16 -0700
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <afd87eba-742f-4b67-9171-fd8486416b7b@linux.microsoft.com>

On 3/17/2025 4:51 PM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
<snip>
>> +
>> +/* TODO move this to another file when debugfs code is added */
>> +enum hv_stats_vp_counters {			/* HV_THREAD_COUNTER */
>> +#if defined(CONFIG_X86)
>> +	VpRootDispatchThreadBlocked			= 201,
>> +#elif defined(CONFIG_ARM64)
>> +	VpRootDispatchThreadBlocked			= 94,
>> +#endif
>> +	VpStatsMaxCounter
>> +};
> 
> Where do these "magic" numbers come from?  Are they matching something
> in the Hyper-V host?
> 
They are part of the hypervisor ABI and really belong in hvhdk.h. These enums
have many members which we use in another part of the code but which are omitted
here.

For this patchset I put them here to avoid putting PascalCase definitions in the
global namespace. I was undecided if we want to keep them like this (maybe keeping
them out of hvhdk.h), or change them to linux style in a followup.

>> +
>> +struct hv_stats_page {
>> +	union {
>> +		u64 vp_cntrs[VpStatsMaxCounter];		/* VP counters */
>> +		u8 data[HV_HYP_PAGE_SIZE];
>> +	};
>> +} __packed;
>> +
>> +struct mshv_root mshv_root = {};
> 
> Initializer is unnecessary for global variables. They are already set to zero.
> 
Yep, I'll remove it.

>> +
>> +enum hv_scheduler_type hv_scheduler_type;
>> +
>> +/* Once we implement the fast extended hypercall ABI they can go away. */
>> +static void __percpu **root_scheduler_input;
>> +static void __percpu **root_scheduler_output;
> 
> The __percpu is probably in the wrong place like mentioned in earlier
> patches in this series.
> 
Ack, will fix.

<snip>
>> +
>> +static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition,
>> +				      bool partition_locked,
>> +				      void __user *user_args)
>> +{
>> +	u64 status;
>> +	int ret, i;
> 
> 'ret' should be initialized to 0. There's a path through this function that
> never sets 'ret' and the return value would be stack garbage.
> 
Thanks, will fix.

<snip>
>> +
>> +/*
>> + * Explicit guest vCPU suspend is asynchronous by nature (as it is requested by
>> + * dom0 vCPU for guest vCPU) and thus it can race with "intercept" suspend,
>> + * done by the hypervisor.
>> + * "Intercept" suspend leads to asynchronous message delivery to dom0 which
>> + * should be awaited to keep the VP loop consistent (i.e. no message pending
>> + * upon VP resume).
>> + * VP intercept suspend can't be done when the VP is explicitly suspended
>> + * already, and thus can be only two possible race scenarios:
>> + *   1. implicit suspend bit set -> explicit suspend bit set -> message sent
>> + *   2. implicit suspend bit set -> message sent -> explicit suspend bit set
>> + * Checking for implicit suspend bit set after explicit suspend request has
>> + * succeeded in either case allows us to reliably identify, if there is a
>> + * message to receive and deliver to VMM.
>> + */
>> +static long
> 
> For this function, why is the return type "long" instead of "int"?  Same
> question for several other functions below.  "long" works, but it's another
> case of being gratuitously atypical -- unless there's a reason.
> 
No good reason. It should just be an int.

<snip>
>> +
>> +	switch (args.type) {
>> +	case MSHV_VP_STATE_LAPIC:
>> +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
>> +		data_sz = HV_HYP_PAGE_SIZE;
>> +		break;
>> +	case MSHV_VP_STATE_XSAVE:
> 
> Just FYI, you can put a semicolon after the colon on the above line, which
> adds a null statement, and then the C compiler will accept the definition
> of local variable data_sz_64 without needing the odd-looking braces. 
> 
> See https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement/19830820
> 
> I learn something new every day! :-)
> 
I didn't know that! But actually I prefer the braces because they clearly
denote a new block scope for that case.

>> +	{
>> +		u64 data_sz_64;
>> +
>> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
>> +						     HV_PARTITION_PROPERTY_XSAVE_STATES,
>> +						     &state_data.xsave.states.as_uint64);
>> +		if (ret)
>> +			return ret;
>> +
>> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
>> +						     HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE,
>> +						     &data_sz_64);
>> +		if (ret)
>> +			return ret;
>> +
>> +		data_sz = (u32)data_sz_64;
>> +		state_data.xsave.flags = 0;
>> +		/* Always request legacy states */
>> +		state_data.xsave.states.legacy_x87 = 1;
>> +		state_data.xsave.states.legacy_sse = 1;
>> +		state_data.type = HV_GET_SET_VP_STATE_XSAVE;
>> +		break;
>> +	}
>> +	case MSHV_VP_STATE_SIMP:
>> +		state_data.type = HV_GET_SET_VP_STATE_SIM_PAGE;
>> +		data_sz = HV_HYP_PAGE_SIZE;
>> +		break;
>> +	case MSHV_VP_STATE_SIEFP:
>> +		state_data.type = HV_GET_SET_VP_STATE_SIEF_PAGE;
>> +		data_sz = HV_HYP_PAGE_SIZE;
>> +		break;
>> +	case MSHV_VP_STATE_SYNTHETIC_TIMERS:
>> +		state_data.type = HV_GET_SET_VP_STATE_SYNTHETIC_TIMERS;
>> +		data_sz = sizeof(vp_state.synthetic_timers_state);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (copy_to_user(&user_args->buf_sz, &data_sz, sizeof(user_args->buf_sz)))
>> +		return -EFAULT;
>> +
>> +	if (data_sz > args.buf_sz)
>> +		return -EINVAL;
>> +
>> +	/* If the data is transmitted via pfns, delegate to helper */
>> +	if (state_data.type & HV_GET_SET_VP_STATE_TYPE_PFN) {
>> +		unsigned long user_pfn = PFN_DOWN(args.buf_ptr);
>> +		size_t page_count = PFN_DOWN(args.buf_sz);
>> +
>> +		return mshv_vp_ioctl_get_set_state_pfn(vp, state_data, user_pfn,
>> +						       page_count, is_set);
>> +	}
>> +
>> +	/* Paranoia check - this shouldn't happen! */
>> +	if (data_sz > sizeof(vp_state)) {
>> +		vp_err(vp, "Invalid vp state data size!\n");
>> +		return -EINVAL;
>> +	}
> 
> I don't understand the above check.  sizeof(vp_state) is relatively small since
> it is effectively sizeof(hv_synthetic_timers_state), which is 200 bytes if I've
> done the arithmetic correctly. But data_sz could be a full page (4096 bytes)
> for the LAPIC, SIMP, and SIEFP cases, and the check would cause an error to
> be returned.
> 
data_sz > sizeof(vp_state) is true if and only if the HV_GET_SET_VP_STATE_TYPE_PFN
bit is set in state_data.type. This check ensures that invariant holds.

See just above where we delegate to mshv_vp_ioctl_get_set_state_pfn() in that case.

>> +
>> +	if (is_set) {
>> +		if (copy_from_user(&vp_state, (__user void *)args.buf_ptr, data_sz))
>> +			return -EFAULT;
>> +
>> +		return hv_call_set_vp_state(vp->vp_index,
>> +					    vp->vp_partition->pt_id,
>> +					    state_data, 0, NULL,
>> +					    sizeof(vp_state), (u8 *)&vp_state);
> 
> This is one of the cases where data from user space gets passed directly to
> the hypercall. So user space is responsible for ensuring that reserved fields
> are zero'ed and for otherwise ensuring a proper hypercall input. I just
> wonder if user space really does this correctly.
> 
The interfaces that are 'passthrough' like this remove quite a bit of
complexity from the kernel code and delegates it to userspace and the hypervisor.

It is on userspace to ensure the parameters are valid, and it's on the
hypervisor to check the fields and error if they are used improperly.

Note the hypervisor still needs to check everything regardless of if it comes
from the kernel or directly from userspace.

>> +
>> +static vm_fault_t mshv_vp_fault(struct vm_fault *vmf)
>> +{
>> +	struct mshv_vp *vp = vmf->vma->vm_file->private_data;
>> +
>> +	switch (vmf->vma->vm_pgoff) {
>> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
>> +		vmf->page = virt_to_page(vp->vp_register_page);
>> +		break;
>> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
>> +		vmf->page = virt_to_page(vp->vp_intercept_msg_page);
>> +		break;
>> +	case MSHV_VP_MMAP_OFFSET_GHCB:
>> +		if (is_ghcb_mapping_available())
>> +			vmf->page = virt_to_page(vp->vp_ghcb_page);
>> +		break;
> 
> If there's no GHCB mapping available, execution just continues with
> vmf->page not set. Won't the later get_page() call fail? Perhaps this
> should fail if there's no GHCB mapping available. Or maybe there's
> more about how this works that I'm ignorant of. :-)
> 
Hmm, maybe this check should just be removed. If we got here it means
the vmf->vma->vm_pgoff was already set in mmap(), so the page should be
valid in that case.

>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	get_page(vmf->page);
>> +
>> +	return 0;
>> +}
>> +
>> +static int mshv_vp_mmap(struct file *file, struct vm_area_struct *vma)
>> +{
>> +	struct mshv_vp *vp = file->private_data;
>> +
>> +	switch (vma->vm_pgoff) {
>> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
>> +		if (!vp->vp_register_page)
>> +			return -ENODEV;
>> +		break;
>> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
>> +		if (!vp->vp_intercept_msg_page)
>> +			return -ENODEV;
>> +		break;
>> +	case MSHV_VP_MMAP_OFFSET_GHCB:
>> +		if (is_ghcb_mapping_available() && !vp->vp_ghcb_page)
>> +			return -ENODEV;
>> +		break;
> 
> Again, if no GHCB mapping is available, should this return success?
> 
I think this should just check the vp->vp_ghcb_page is not NULL, like
the other cases. is_ghcb_mapping_available() is already checked to
decide whether to map the page in the first place. I'll change it.

>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	vma->vm_ops = &mshv_vp_vm_ops;
>> +	return 0;
>> +}
<snip>
>> +
>> +	input_vtl.as_uint8 = 0;
> 
> I see eight occurrences in this source code file where the above statement
> occurs and there is no further modification. Perhaps declare a static
> variable that is initialized properly, and use it as the input parameter to the
> various functions.  A second static variable could have the use_target_vtl = 1
> setting that is needed in three places.
> 
I was a bit doubtful, but I tried this and it removes quite a few lines without
much tradeoff in readability. Thanks!

>> +	ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
>> +					HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
>> +					input_vtl,
>> +					&intercept_message_page);
<snip>>> +static int mshv_init_async_handler(struct mshv_partition *partition)
>> +{
>> +	if (completion_done(&partition->async_hypercall)) {
>> +		pt_err(partition,
>> +		       "Cannot issue another async hypercall, while another one in progress!\n");
> 
> Two uses of word "another" in the error message is redundant.  Perhaps
> 
> 	"Cannot issue async hypercall while another one is in progress!"
> 
Thanks, I'll change it.

<snip>>> +
>> +	/* Reject overlapping regions */
>> +	if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) ||
>> +	    mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) ||
>> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr) ||
>> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1))
>> +		return -EEXIST;
> 
> Having to fully walk the partition region list four times for the above checks
> isn't the most efficient approach, but I'm guessing that creating a region isn't
> really a hot path so it doesn't matter. And I don't know how long the region list
> typically is.
> 
Indeed, it seems wasteful at first but the list is usually only a few entries long,
and regions are rarely added or removed (usually just at boot).

<snip>>> +/* Called for unmapping both the guest ram and the mmio space */
>> +static long
>> +mshv_unmap_user_memory(struct mshv_partition *partition,
>> +		       struct mshv_user_mem_region mem)
>> +{
>> +	struct mshv_mem_region *region;
>> +	u32 unmap_flags = 0;
>> +
>> +	if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
>> +		return -EINVAL;
>> +
>> +	if (hlist_empty(&partition->pt_mem_regions))
>> +		return -EINVAL;
> 
> Isn't the above check redundant, given the lookup by gfn that is
> done immediately below?
> 
Yes, I'll remove it.

>> +
>> +	region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
>> +	if (!region)
>> +		return -EINVAL;
<snip>>> +	case MSHV_GPAP_ACCESS_TYPE_ACCESSED:
>> +		hv_type_mask = 1;
>> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
>> +			hv_flags.clear_accessed = 1;
>> +			/* not accessed implies not dirty */
>> +			hv_flags.clear_dirty = 1;
>> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> 
> Avoid C++ style comments.
> 
Ack

>> +			hv_flags.set_accessed = 1;
>> +		}
>> +		break;
>> +	case MSHV_GPAP_ACCESS_TYPE_DIRTY:
>> +		hv_type_mask = 2;
>> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
>> +			hv_flags.clear_dirty = 1;
>> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> 
> Same here.
> 
Ack

>> +			hv_flags.set_dirty = 1;
>> +			/* dirty implies accessed */
>> +			hv_flags.set_accessed = 1;
>> +		}
>> +		break;
>> +	}
>> +
>> +	states = vzalloc(states_buf_sz);
>> +	if (!states)
>> +		return -ENOMEM;
>> +
>> +	ret = hv_call_get_gpa_access_states(partition->pt_id, args.page_count,
>> +					    args.gpap_base, hv_flags, &written,
>> +					    states);
>> +	if (ret)
>> +		goto free_return;
>> +
>> +	/*
>> +	 * Overwrite states buffer with bitmap - the bits in hv_type_mask
>> +	 * correspond to bitfields in hv_gpa_page_access_state
>> +	 */
>> +	for (i = 0; i < written; ++i)
>> +		assign_bit(i, (ulong *)states,
> 
> Why the cast to ulong *?  I think this argument to assign_bit() is void *, in
> which case the cast wouldn't be needed.
> 
It looks like assign_bit() and friends resolve to a set of functions which do
take an unsigned long pointer, e.g.:

__set_bit() -> generic___set_bit(unsigned long nr, volatile unsigned long *addr)
set_bit() -> arch_set_bit(unsigned int nr, volatile unsigned long *p)
etc...

So a cast is necessary.

> Also, assign_bit() does atomic bit operations. Doing such in a loop like
> here will really hammer the hardware memory bus with atomic 
> read-modify-write cycles. Use __assign_bit() instead, which does
> non-atomic operations. You don't need atomic here as no other
> threads are modifying the bit array.
> 
I didn't realize it was atomic. I'll change it to __assign_bit().

>> +			   states[i].as_uint8 & hv_type_mask);
> 
> OK, so the starting contents of "states" is an array of bytes. The ending
> contents is an array of bits. This works because every bit in the ending
> bit array is set to either 0 or 1. Overlap occurs on the first iteration
> where the code reads the 0th byte, and writes the 0th bit, which is part of
> the 0th byte. The second iteration reads the 1st byte, and writes the 1st bit,
> which doesn't overlap, and there's no overlap from then on.
> 
> Suppose "written" is not a multiple of 8. The last byte of "states" as an
> array of bits will have some bits that have not been set to either 0 or 1 and
> might be leftover garbage from when "states" was an array of bytes. That
> garbage will get copied to user space. Is that OK? Even if user space knows
> enough to ignore those bits, it seems a little dubious to be copying even
> a few bits of garbage to user space.
> 
> Some comments might help here.
> 
This is a good point. The expectation is indeed that userspace knows which
bits are valid from the returned "written" value, but I agree it's a bit
odd to have some garbage bits in the last byte. How does this look (to be
inserted here directly after the loop):

+       /* zero the unused bits in the last byte of the returned bitmap */
+       if (written > 0) {
+               u8 last_bits_mask;
+               int last_byte_idx;
+               int bits_rem = written % 8;
+
+               /* bits_rem == 0 when all bits in the last byte were assigned */
+               if (bits_rem > 0) {
+                       /* written > 0 ensures last_byte_idx >= 0 */
+                       last_byte_idx = ((written + 7) / 8) - 1;
+                       /* bits_rem > 0 ensures this masks 1 to 7 bits */
+                       last_bits_mask = (1 << bits_rem) - 1;
+                       states[last_byte_idx].as_uint8 &= last_bits_mask;
+               }
+       }

The remaining bytes could be memset() to zero but I think it's fine to leave
them.

>> +
>> +	args.page_count = written;
>> +
>> +	if (copy_to_user(user_args, &args, sizeof(args))) {
>> +		ret = -EFAULT;
>> +		goto free_return;
>> +	}
>> +	if (copy_to_user((void __user *)args.bitmap_ptr, states, bitmap_buf_sz))
>> +		ret = -EFAULT;
>> +
>> +free_return:
>> +	vfree(states);
>> +	return ret;
>> +}
<snip>
>> +static void
>> +handle_bitset_message(const struct hv_vp_signal_bitset_scheduler_message *msg)
>> +{
>> +	int bank_idx, vps_signaled = 0, bank_mask_size;
>> +	struct mshv_partition *partition;
>> +	const struct hv_vpset *vpset;
>> +	const u64 *bank_contents;
>> +	u64 partition_id = msg->partition_id;
>> +
>> +	if (msg->vp_bitset.bitset.format != HV_GENERIC_SET_SPARSE_4K) {
>> +		pr_debug("scheduler message format is not HV_GENERIC_SET_SPARSE_4K");
>> +		return;
>> +	}
>> +
>> +	if (msg->vp_count == 0) {
>> +		pr_debug("scheduler message with no VP specified");
>> +		return;
>> +	}
>> +
>> +	rcu_read_lock();
>> +
>> +	partition = mshv_partition_find(partition_id);
>> +	if (unlikely(!partition)) {
>> +		pr_debug("failed to find partition %llu\n", partition_id);
>> +		goto unlock_out;
>> +	}
>> +
>> +	vpset = &msg->vp_bitset.bitset;
>> +
>> +	bank_idx = -1;
>> +	bank_contents = vpset->bank_contents;
>> +	bank_mask_size = sizeof(vpset->valid_bank_mask) * BITS_PER_BYTE;
>> +
>> +	while (true) {
>> +		int vp_bank_idx = -1;
>> +		int vp_bank_size = sizeof(*bank_contents) * BITS_PER_BYTE;
>> +		int vp_index;
>> +
>> +		bank_idx = find_next_bit((unsigned long *)&vpset->valid_bank_mask,
>> +					 bank_mask_size, bank_idx + 1);
>> +		if (bank_idx == bank_mask_size)
>> +			break;
>> +
>> +		while (true) {
>> +			struct mshv_vp *vp;
>> +
>> +			vp_bank_idx = find_next_bit((unsigned long *)bank_contents,
>> +						    vp_bank_size, vp_bank_idx + 1);
>> +			if (vp_bank_idx == vp_bank_size)
>> +				break;
>> +
>> +			vp_index = (bank_idx << HV_GENERIC_SET_SHIFT) + vp_bank_idx;
> 
> This would be clearer if just multiplied by bank_mask_size instead of shifting.
> Since the compiler knows the constant value of bank_mask_size, it should generate
> the same code as the shift.
> 
I agree, but it should be multiplied by vp_bank_size as that's the size of a bank
in bits, as opposed bank_mask_size which is the size of the valid banks mask in bits.

(They're both the same value though, 64).

<snip>>> +
>> +enum {
>> +	MSHV_GPAP_ACCESS_TYPE_ACCESSED = 0,
>> +	MSHV_GPAP_ACCESS_TYPE_DIRTY,
>> +	MSHV_GPAP_ACCESS_TYPE_COUNT		/* Count of enum members */
>> +};
>> +
>> +enum {
>> +	MSHV_GPAP_ACCESS_OP_NOOP = 0,
>> +	MSHV_GPAP_ACCESS_OP_CLEAR,
>> +	MSHV_GPAP_ACCESS_OP_SET,
>> +	MSHV_GPAP_ACCESS_OP_COUNT		/* Count of enum members */
>> +};
> 
> Any reason these two enums explicitly set the first value to 0, while
> earlier enums do not?  This is another case of there being a difference,
> and me wondering if it's just gratuitous or if there's a specific reason.
> Consistency is a good thing!
> 
No reason, I'll remove these assignments.

<snip>>> +/* Partition fds created with MSHV_CREATE_PARTITION */
>> +#define MSHV_INITIALIZE_PARTITION	_IO(MSHV_IOCTL, 0x00)
>> +#define MSHV_CREATE_VP			_IOW(MSHV_IOCTL, 0x01, struct mshv_create_vp)
>> +#define MSHV_SET_GUEST_MEMORY		_IOW(MSHV_IOCTL, 0x02, struct mshv_user_mem_region)
>> +#define MSHV_IRQFD			_IOW(MSHV_IOCTL, 0x03, struct mshv_user_irqfd)
>> +#define MSHV_IOEVENTFD			_IOW(MSHV_IOCTL, 0x04, struct mshv_user_ioeventfd)
>> +#define MSHV_SET_MSI_ROUTING		_IOW(MSHV_IOCTL, 0x05, struct mshv_user_irq_table)
>> +#define MSHV_GET_GPAP_ACCESS_BITMAP	_IOWR(MSHV_IOCTL, 0x06, struct mshv_gpap_access_bitmap)
>> +/* Generic hypercall */
>> +#define MSHV_ROOT_HVCALL		_IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall)
> 
> I really don't like having the ioctl numbers here overlap with the /dev/mshv ioctls.
> There's just no need to overlap. But I realize changing it now is a big hassle.
> 
Fair enough, there isn't a real need for overlap between the different device IOCTLs.
But, yes, I am going to leave them alone unless there's a really good reason.

>> +
>> +/*
>> + ********************************
>> + * VP APIs for child partitions *
>> + ********************************
>> + */
>> +
>> +#define MSHV_RUN_VP_BUF_SZ 256
>> +
>> +/*
>> + * Map various VP state pages to userspace.
>> + * Multiply the offset by PAGE_SIZE before being passed as the 'offset'
>> + * argument to mmap().
>> + * e.g.
>> + * void *reg_page = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
>> + *                       MAP_SHARED, vp_fd,
>> + *                       MSHV_VP_MMAP_OFFSET_REGISTERS * PAGE_SIZE);
>> + */
> 
> This is interesting.  I would not have thought PAGE_SIZE is available
> in the UAPI.  You must use something like the getpagesize() call. I know
> the root partition can only run with a 4K page size, but the symbol
> "PAGE_SIZE" is probably kernel code only.
> 
PAGE_SIZE here is meant to imply using whatever the system page size is,
but I think it's probably better to be explicit in the example. I will
change it to sysconf(_SC_PAGE_SIZE) as that seems to be the recommended way.

While at it I realized there were some more references to PAGE_SIZE and
HV_HYP_PAGE_SIZE in this file, but neither are defined in uapi.
I'm going to add a new #define MSHV_HV_PAGE_SIZE which matches the
hypervisor native page size of 0x1000 for these cases.

This mmap() call is the only time where the system page size is needed
instead of the Hyper-V page size.

>> +enum {
>> +	MSHV_VP_MMAP_OFFSET_REGISTERS,
>> +	MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE,
>> +	MSHV_VP_MMAP_OFFSET_GHCB,
>> +	MSHV_VP_MMAP_OFFSET_COUNT
>> +};
>> +
>> +/**
>> + * struct mshv_run_vp - argument for MSHV_RUN_VP
>> + * @msg_buf: On success, the intercept message is copied here. It can be
>> + *           interpreted using the relevant hypervisor definitions.
>> + */
>> +struct mshv_run_vp {
>> +	__u8 msg_buf[MSHV_RUN_VP_BUF_SZ];
>> +};
>> +
>> +enum {
>> +	MSHV_VP_STATE_LAPIC,		/* Local interrupt controller state (either arch) */
>> +	MSHV_VP_STATE_XSAVE,		/* XSAVE data in compacted form (x86_64) */
>> +	MSHV_VP_STATE_SIMP,
>> +	MSHV_VP_STATE_SIEFP,
>> +	MSHV_VP_STATE_SYNTHETIC_TIMERS,
>> +	MSHV_VP_STATE_COUNT,
>> +};
>> +
>> +/**
>> + * struct mshv_get_set_vp_hvcall - arguments for MSHV_[GET,SET]_VP_STATE
> 
> s/hvcall/state/
> 
Ack

<snip>
Thanks for the comments
Nuno


From jpoimboe at kernel.org  Tue Mar 18 18:03:13 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Tue, 18 Mar 2025 18:03:13 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <CAPhsuW4BEDU=ZJavnofZtygGcQ9AJ5F2jJiuV6-nsnbZD+Gg-Q@mail.gmail.com>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
 <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>
 <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>
 <CAPhsuW4BEDU=ZJavnofZtygGcQ9AJ5F2jJiuV6-nsnbZD+Gg-Q@mail.gmail.com>
Message-ID: <pym6gfbapfy6qlmduszjk6tf2oc2fv4rtxgwjgex7bwlgpfwvs@bkt7qfmf7rc4>

On Tue, Mar 18, 2025 at 04:38:20PM -0700, Song Liu wrote:
> On Tue, Mar 18, 2025 at 4:00?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
> >   - even in the -ENOENT case the unreliable bit has already been set
> >     right before the call to kunwind_next_frame_record_meta().
> 
> For this one, do you mean we set state->common.unreliable, but
> failed to propagate it to data.unreliable?

Hm, I hadn't noticed that.  That code is quite the maze.

It's unfortunate there are two separate 'unreliable' variables.  It
looks like consume_state() is the only way they get synced?

How does that work if kunwind_next() returns an error and skips
consume_state()?  Or if kunwind_recover_return_address() returns an
error to kunwind_next()?

What I actually meant was the following:

  do_kunwind()
    kunwind_next()
      kunwind_next_frame_record()
        state->common.unreliable = true;
	kunwind_next_frame_record_meta()
	  return -ENOENT;

Notice that in the success case (-ENOENT), unreliable has already been
set.

Actually I think it would be much simpler to just propagate -ENOENT down
the call chain.  Then no 'unreliable' bits needed.

Like so (instead of original patch):

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c9fe3e7566a6..5713fad567c5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -276,6 +276,7 @@ config ARM64
 	select HAVE_SOFTIRQ_ON_OWN_STACK
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
+	select HAVE_RELIABLE_STACKTRACE
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2509,4 +2510,3 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
-
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 1d9d51d7627f..e227da842bc3 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -277,22 +277,28 @@ kunwind_next(struct kunwind_state *state)
 
 typedef bool (*kunwind_consume_fn)(const struct kunwind_state *state, void *cookie);
 
-static __always_inline void
+static __always_inline int
 do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 	   void *cookie)
 {
-	if (kunwind_recover_return_address(state))
-		return;
+	int ret;
+
+	ret = kunwind_recover_return_address(state);
+	if (ret)
+		return ret;
 
 	while (1) {
 		int ret;
 
 		if (!consume_state(state, cookie))
-			break;
+			return -EINVAL;
+
 		ret = kunwind_next(state);
-		if (ret < 0)
-			break;
+		if (ret)
+			return ret;
 	}
+
+	return -EINVAL;
 }
 
 /*
@@ -324,7 +330,7 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 			: stackinfo_get_unknown();		\
 	})
 
-static __always_inline void
+static __always_inline int
 kunwind_stack_walk(kunwind_consume_fn consume_state,
 		   void *cookie, struct task_struct *task,
 		   struct pt_regs *regs)
@@ -352,7 +358,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 
 	if (regs) {
 		if (task != current)
-			return;
+			return -EINVAL;
 		kunwind_init_from_regs(&state, regs);
 	} else if (task == current) {
 		kunwind_init_from_caller(&state);
@@ -360,7 +366,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 		kunwind_init_from_task(&state, task);
 	}
 
-	do_kunwind(&state, consume_state, cookie);
+	return do_kunwind(&state, consume_state, cookie);
 }
 
 struct kunwind_consume_entry_data {
@@ -387,6 +393,25 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
 }
 
+noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
+			void *cookie, struct task_struct *task)
+{
+	int ret;
+	struct kunwind_consume_entry_data data = {
+		.consume_entry = consume_entry,
+		.cookie = cookie,
+	};
+
+	ret = kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL);
+	if (ret) {
+		if (ret == -ENOENT)
+			return 0;
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
 struct bpf_unwind_consume_entry_data {
 	bool (*consume_entry)(void *cookie, u64 ip, u64 sp, u64 fp);
 	void *cookie;


From yury.norov at gmail.com  Tue Mar 18 18:46:58 2025
From: yury.norov at gmail.com (Yury Norov)
Date: Tue, 18 Mar 2025 21:46:58 -0400
Subject: [PATCH v4 3/8] bits: introduce fixed-type genmasks
In-Reply-To: <Z8hsRJvpjYoqh9RG@thinkpad>
References: <20250305-fixed-type-genmasks-v4-0-1873dcdf6723@wanadoo.fr>
 <20250305-fixed-type-genmasks-v4-3-1873dcdf6723@wanadoo.fr>
 <Z8hsRJvpjYoqh9RG@thinkpad>
Message-ID: <Z9oiEkQEcHhA0a80@thinkpad>

+ Catalin Marinas, ARM maillist

Hi Catalin and everyone,

Anshuman Khandual asked me to merge GENMASK_U128() saying it's
important for ARM to stabilize API. While it's a dead code, I
accepted his patch as he promised to add users shortly.

Now it's more than half a year since that. There's no users,
and no feedback from Anshuman.

Can you please tell if you still need the macro? I don't want to
undercut your development, but if you don't need 128-bit genmasks
there's no reason to have a dead code in the uapi.

Thanks,
Yury

On Wed, Mar 05, 2025 at 10:22:47AM -0500, Yury Norov wrote:
> + Anshuman Khandual <anshuman.khandual at arm.com>
> 
> Anshuman,
> 
> I merged your GENMASK_U128() because you said it's important for your
> projects, and that it will get used in the kernel soon.
> 
> Now it's in the kernel for more than 6 month, but no users were added.
> Can you clarify if you still need it, and if so why it's not used?
> 
> As you see, people add another fixed-types GENMASK() macros, and their
> implementation differ from GENMASK_U128().
> 
> My second concern is that __GENMASK_U128() is declared in uapi, while
> the general understanding for other fixed-type genmasks is that they
> are not exported to users. Do you need this macro to be exported to
> userspace? Can you show how and where it is used there?
> 
> Thanks,
> Yury
> 
> 
> On Wed, Mar 05, 2025 at 10:00:15PM +0900, Vincent Mailhol via B4 Relay wrote:
> > From: Yury Norov <yury.norov at gmail.com>
> > 
> > Add __GENMASK_t() which generalizes __GENMASK() to support different
> > types, and implement fixed-types versions of GENMASK() based on it.
> > The fixed-type version allows more strict checks to the min/max values
> > accepted, which is useful for defining registers like implemented by
> > i915 and xe drivers with their REG_GENMASK*() macros.
> > 
> > The strict checks rely on shift-count-overflow compiler check to fail
> > the build if a number outside of the range allowed is passed.
> > Example:
> > 
> > 	#define FOO_MASK GENMASK_U32(33, 4)
> > 
> > will generate a warning like:
> > 
> > 	../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
> > 	   41 |          (((t)~0ULL - ((t)(1) << (l)) + 1) & \
> > 	      |                               ^~
> > 
> > Signed-off-by: Yury Norov <yury.norov at gmail.com>
> > Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
> > Acked-by: Jani Nikula <jani.nikula at intel.com>
> > Signed-off-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
> > ---
> > Changelog:
> > 
> >   v3 -> v4:
> > 
> >     - The v3 is one year old. Meanwhile people started using
> >       __GENMASK() directly. So instead of generalizing __GENMASK() to
> >       support different types, add a new GENMASK_t().
> > 
> >     - replace ~0ULL by ~_ULL(0). Otherwise, __GENMASK_t() would fail
> >       in asm code.
> > 
> >     - Make GENMASK_U8() and GENMASK_U16() return an unsigned int. In
> >       v3, due to the integer promotion rules, these were returning a
> >       signed integer. By casting these to unsigned int, at least the
> >       signedness is kept.
> > ---
> >  include/linux/bitops.h |  1 -
> >  include/linux/bits.h   | 33 +++++++++++++++++++++++++++++----
> >  2 files changed, 29 insertions(+), 5 deletions(-)
> > 
> > diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> > index c1cb53cf2f0f8662ed3e324578f74330e63f935d..9be2d50da09a417966b3d11c84092bb2f4cd0bef 100644
> > --- a/include/linux/bitops.h
> > +++ b/include/linux/bitops.h
> > @@ -8,7 +8,6 @@
> >  
> >  #include <uapi/linux/kernel.h>
> >  
> > -#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
> >  #define BITS_TO_LONGS(nr)	__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
> >  #define BITS_TO_U64(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
> >  #define BITS_TO_U32(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
> > diff --git a/include/linux/bits.h b/include/linux/bits.h
> > index 5f68980a1b98d771426872c74d7b5c0f79e5e802..f202e46d2f4b7899c16d975120f3fa3ae41556ae 100644
> > --- a/include/linux/bits.h
> > +++ b/include/linux/bits.h
> > @@ -12,6 +12,7 @@
> >  #define BIT_ULL_MASK(nr)	(ULL(1) << ((nr) % BITS_PER_LONG_LONG))
> >  #define BIT_ULL_WORD(nr)	((nr) / BITS_PER_LONG_LONG)
> >  #define BITS_PER_BYTE		8
> > +#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
> >  
> >  /*
> >   * Create a contiguous bitmask starting at bit position @l and ending at
> > @@ -25,14 +26,38 @@
> >  
> >  #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h)))
> >  
> > -#define GENMASK(h, l) \
> > -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
> > -#define GENMASK_ULL(h, l) \
> > -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> > +/*
> > + * Generate a mask for the specified type @t. Additional checks are made to
> > + * guarantee the value returned fits in that type, relying on
> > + * shift-count-overflow compiler check to detect incompatible arguments.
> > + * For example, all these create build errors or warnings:
> > + *
> > + * - GENMASK(15, 20): wrong argument order
> > + * - GENMASK(72, 15): doesn't fit unsigned long
> > + * - GENMASK_U32(33, 15): doesn't fit in a u32
> > + */
> > +#define GENMASK_t(t, h, l)				\
> > +	(GENMASK_INPUT_CHECK(h, l) +			\
> > +	 (((t)~ULL(0) - ((t)1 << (l)) + 1) &		\
> > +	  ((t)~ULL(0) >> (BITS_PER_TYPE(t) - 1 - (h)))))
> > +
> > +#define GENMASK(h, l) GENMASK_t(unsigned long,  h, l)
> > +#define GENMASK_ULL(h, l) GENMASK_t(unsigned long long, h, l)
> >  
> >  /*
> >   * Missing asm support
> >   *
> > + * __GENMASK_U*() depends on BITS_PER_TYPE() which would not work in the asm
> > + * code as BITS_PER_TYPE() relies on sizeof(), something not available in
> > + * asm. Nethertheless, the concept of fixed width integers is a C thing which
> > + * does not apply to assembly code.
> > + */
> > +#define GENMASK_U8(h, l) ((unsigned int)GENMASK_t(u8,  h, l))
> > +#define GENMASK_U16(h, l) ((unsigned int)GENMASK_t(u16, h, l))
> > +#define GENMASK_U32(h, l) GENMASK_t(u32, h, l)
> > +#define GENMASK_U64(h, l) GENMASK_t(u64, h, l)
> > +
> > +/*
> >   * __GENMASK_U128() depends on _BIT128() which would not work
> >   * in the asm code, as it shifts an 'unsigned __int128' data
> >   * type instead of direct representation of 128 bit constants
> > 
> > -- 
> > 2.45.3
> > 


From mhklinux at outlook.com  Tue Mar 18 19:10:17 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Wed, 19 Mar 2025 02:10:17 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <afd87eba-742f-4b67-9171-fd8486416b7b@linux.microsoft.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <afd87eba-742f-4b67-9171-fd8486416b7b@linux.microsoft.com>
Message-ID: <SN6PR02MB41574DE5535222985147134CD4D92@SN6PR02MB4157.namprd02.prod.outlook.com>

From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Tuesday, March 18, 2025 5:34 PM
> 
> On 3/17/2025 4:51 PM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday,
> February 26, 2025 3:08 PM
> <snip>
> >> +
> >> +/* TODO move this to another file when debugfs code is added */
> >> +enum hv_stats_vp_counters {			/* HV_THREAD_COUNTER */
> >> +#if defined(CONFIG_X86)
> >> +	VpRootDispatchThreadBlocked			= 201,
> >> +#elif defined(CONFIG_ARM64)
> >> +	VpRootDispatchThreadBlocked			= 94,
> >> +#endif
> >> +	VpStatsMaxCounter
> >> +};
> >
> > Where do these "magic" numbers come from?  Are they matching something
> > in the Hyper-V host?
> >
> They are part of the hypervisor ABI and really belong in hvhdk.h. These enums
> have many members which we use in another part of the code but which are omitted
> here.
> 
> For this patchset I put them here to avoid putting PascalCase definitions in the
> global namespace. I was undecided if we want to keep them like this (maybe keeping
> them out of hvhdk.h), or change them to linux style in a followup.

OK.  I don't object to them staying like this pending a future decision.

> <snip>
> >> +
> >> +	switch (args.type) {
> >> +	case MSHV_VP_STATE_LAPIC:
> >> +		state_data.type = HV_GET_SET_VP_STATE_LAPIC_STATE;
> >> +		data_sz = HV_HYP_PAGE_SIZE;
> >> +		break;
> >> +	case MSHV_VP_STATE_XSAVE:
> >
> > Just FYI, you can put a semicolon after the colon on the above line, which
> > adds a null statement, and then the C compiler will accept the definition
> > of local variable data_sz_64 without needing the odd-looking braces.
> >
> > I learn something new every day! :-)
> >
> I didn't know that! But actually I prefer the braces because they clearly
> denote a new block scope for that case.

That's fine.

> >> +	{
> >> +		u64 data_sz_64;
> >> +
> >> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
> >> +						     HV_PARTITION_PROPERTY_XSAVE_STATES,
> >> +						     &state_data.xsave.states.as_uint64);
> >> +		if (ret)
> >> +			return ret;
> >> +
> >> +		ret = hv_call_get_partition_property(vp->vp_partition->pt_id,
> >> +						     HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE,
> >> +						     &data_sz_64);
> >> +		if (ret)
> >> +			return ret;
> >> +
> >> +		data_sz = (u32)data_sz_64;
> >> +		state_data.xsave.flags = 0;
> >> +		/* Always request legacy states */
> >> +		state_data.xsave.states.legacy_x87 = 1;
> >> +		state_data.xsave.states.legacy_sse = 1;
> >> +		state_data.type = HV_GET_SET_VP_STATE_XSAVE;
> >> +		break;
> >> +	}
> >> +	case MSHV_VP_STATE_SIMP:
> >> +		state_data.type = HV_GET_SET_VP_STATE_SIM_PAGE;
> >> +		data_sz = HV_HYP_PAGE_SIZE;
> >> +		break;
> >> +	case MSHV_VP_STATE_SIEFP:
> >> +		state_data.type = HV_GET_SET_VP_STATE_SIEF_PAGE;
> >> +		data_sz = HV_HYP_PAGE_SIZE;
> >> +		break;
> >> +	case MSHV_VP_STATE_SYNTHETIC_TIMERS:
> >> +		state_data.type = HV_GET_SET_VP_STATE_SYNTHETIC_TIMERS;
> >> +		data_sz = sizeof(vp_state.synthetic_timers_state);
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	if (copy_to_user(&user_args->buf_sz, &data_sz, sizeof(user_args->buf_sz)))
> >> +		return -EFAULT;
> >> +
> >> +	if (data_sz > args.buf_sz)
> >> +		return -EINVAL;
> >> +
> >> +	/* If the data is transmitted via pfns, delegate to helper */
> >> +	if (state_data.type & HV_GET_SET_VP_STATE_TYPE_PFN) {
> >> +		unsigned long user_pfn = PFN_DOWN(args.buf_ptr);
> >> +		size_t page_count = PFN_DOWN(args.buf_sz);
> >> +
> >> +		return mshv_vp_ioctl_get_set_state_pfn(vp, state_data, user_pfn,
> >> +						       page_count, is_set);
> >> +	}
> >> +
> >> +	/* Paranoia check - this shouldn't happen! */
> >> +	if (data_sz > sizeof(vp_state)) {
> >> +		vp_err(vp, "Invalid vp state data size!\n");
> >> +		return -EINVAL;
> >> +	}
> >
> > I don't understand the above check.  sizeof(vp_state) is relatively small since
> > it is effectively sizeof(hv_synthetic_timers_state), which is 200 bytes if I've
> > done the arithmetic correctly. But data_sz could be a full page (4096 bytes)
> > for the LAPIC, SIMP, and SIEFP cases, and the check would cause an error to
> > be returned.
> >
> data_sz > sizeof(vp_state) is true if and only if the HV_GET_SET_VP_STATE_TYPE_PFN
> bit is set in state_data.type. This check ensures that invariant holds.
> 
> See just above where we delegate to mshv_vp_ioctl_get_set_state_pfn() in that case.

OK. Got it now.  

> 
> >> +
> >> +	if (is_set) {
> >> +		if (copy_from_user(&vp_state, (__user void *)args.buf_ptr, data_sz))
> >> +			return -EFAULT;
> >> +
> >> +		return hv_call_set_vp_state(vp->vp_index,
> >> +					    vp->vp_partition->pt_id,
> >> +					    state_data, 0, NULL,
> >> +					    sizeof(vp_state), (u8 *)&vp_state);
> >
> > This is one of the cases where data from user space gets passed directly to
> > the hypercall. So user space is responsible for ensuring that reserved fields
> > are zero'ed and for otherwise ensuring a proper hypercall input. I just
> > wonder if user space really does this correctly.
> >
> The interfaces that are 'passthrough' like this remove quite a bit of
> complexity from the kernel code and delegates it to userspace and the hypervisor.
> 
> It is on userspace to ensure the parameters are valid, and it's on the
> hypervisor to check the fields and error if they are used improperly.
> 
> Note the hypervisor still needs to check everything regardless of if it comes
> from the kernel or directly from userspace.
> 
> >> +
> >> +static vm_fault_t mshv_vp_fault(struct vm_fault *vmf)
> >> +{
> >> +	struct mshv_vp *vp = vmf->vma->vm_file->private_data;
> >> +
> >> +	switch (vmf->vma->vm_pgoff) {
> >> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
> >> +		vmf->page = virt_to_page(vp->vp_register_page);
> >> +		break;
> >> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
> >> +		vmf->page = virt_to_page(vp->vp_intercept_msg_page);
> >> +		break;
> >> +	case MSHV_VP_MMAP_OFFSET_GHCB:
> >> +		if (is_ghcb_mapping_available())
> >> +			vmf->page = virt_to_page(vp->vp_ghcb_page);
> >> +		break;
> >
> > If there's no GHCB mapping available, execution just continues with
> > vmf->page not set. Won't the later get_page() call fail? Perhaps this
> > should fail if there's no GHCB mapping available. Or maybe there's
> > more about how this works that I'm ignorant of. :-)
> >
> Hmm, maybe this check should just be removed. If we got here it means
> the vmf->vma->vm_pgoff was already set in mmap(), so the page should be
> valid in that case.
> 
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	get_page(vmf->page);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int mshv_vp_mmap(struct file *file, struct vm_area_struct *vma)
> >> +{
> >> +	struct mshv_vp *vp = file->private_data;
> >> +
> >> +	switch (vma->vm_pgoff) {
> >> +	case MSHV_VP_MMAP_OFFSET_REGISTERS:
> >> +		if (!vp->vp_register_page)
> >> +			return -ENODEV;
> >> +		break;
> >> +	case MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE:
> >> +		if (!vp->vp_intercept_msg_page)
> >> +			return -ENODEV;
> >> +		break;
> >> +	case MSHV_VP_MMAP_OFFSET_GHCB:
> >> +		if (is_ghcb_mapping_available() && !vp->vp_ghcb_page)
> >> +			return -ENODEV;
> >> +		break;
> >
> > Again, if no GHCB mapping is available, should this return success?
> >
> I think this should just check the vp->vp_ghcb_page is not NULL, like
> the other cases. is_ghcb_mapping_available() is already checked to
> decide whether to map the page in the first place. I'll change it.
> 
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	vma->vm_ops = &mshv_vp_vm_ops;
> >> +	return 0;
> >> +}
> <snip>
> >> +
> >> +	input_vtl.as_uint8 = 0;
> >
> > I see eight occurrences in this source code file where the above statement
> > occurs and there is no further modification. Perhaps declare a static
> > variable that is initialized properly, and use it as the input parameter to the
> > various functions.  A second static variable could have the use_target_vtl = 1
> > setting that is needed in three places.
> >
> I was a bit doubtful, but I tried this and it removes quite a few lines without
> much tradeoff in readability. Thanks!
> 
> >> +	ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> >> +					HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> >> +					input_vtl,
> >> +					&intercept_message_page);
> <snip>
>> +static int mshv_init_async_handler(struct mshv_partition *partition)
> >> +{
> >> +	if (completion_done(&partition->async_hypercall)) {
> >> +		pt_err(partition,
> >> +		       "Cannot issue another async hypercall, while another one in progress!\n");
> >
> > Two uses of word "another" in the error message is redundant.  Perhaps
> >
> > 	"Cannot issue async hypercall while another one is in progress!"
> >
> Thanks, I'll change it.
> 
> <snip>
>> +
> >> +	/* Reject overlapping regions */
> >> +	if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) ||
> >> +	    mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) ||
> >> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr) ||
> >> +	    mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem- size - 1))
> >> +		return -EEXIST;
> >
> > Having to fully walk the partition region list four times for the above checks
> > isn't the most efficient approach, but I'm guessing that creating a region isn't
> > really a hot path so it doesn't matter. And I don't know how long the region list
> > typically is.
> >
> Indeed, it seems wasteful at first but the list is usually only a few entries long,
> and regions are rarely added or removed (usually just at boot).

OK, not a problem then.

> 
> <snip>
>> +/* Called for unmapping both the guest ram and the mmio space */
> >> +static long
> >> +mshv_unmap_user_memory(struct mshv_partition *partition,
> >> +		       struct mshv_user_mem_region mem)
> >> +{
> >> +	struct mshv_mem_region *region;
> >> +	u32 unmap_flags = 0;
> >> +
> >> +	if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
> >> +		return -EINVAL;
> >> +
> >> +	if (hlist_empty(&partition->pt_mem_regions))
> >> +		return -EINVAL;
> >
> > Isn't the above check redundant, given the lookup by gfn that is
> > done immediately below?
> >
> Yes, I'll remove it.
> 
> >> +
> >> +	region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
> >> +	if (!region)
> >> +		return -EINVAL;
> <snip>
>> +	case MSHV_GPAP_ACCESS_TYPE_ACCESSED:
> >> +		hv_type_mask = 1;
> >> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> >> +			hv_flags.clear_accessed = 1;
> >> +			/* not accessed implies not dirty */
> >> +			hv_flags.clear_dirty = 1;
> >> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> >
> > Avoid C++ style comments.
> >
> Ack
> 
> >> +			hv_flags.set_accessed = 1;
> >> +		}
> >> +		break;
> >> +	case MSHV_GPAP_ACCESS_TYPE_DIRTY:
> >> +		hv_type_mask = 2;
> >> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> >> +			hv_flags.clear_dirty = 1;
> >> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> >
> > Same here.
> >
> Ack
> 
> >> +			hv_flags.set_dirty = 1;
> >> +			/* dirty implies accessed */
> >> +			hv_flags.set_accessed = 1;
> >> +		}
> >> +		break;
> >> +	}
> >> +
> >> +	states = vzalloc(states_buf_sz);
> >> +	if (!states)
> >> +		return -ENOMEM;
> >> +
> >> +	ret = hv_call_get_gpa_access_states(partition->pt_id, args.page_count,
> >> +					    args.gpap_base, hv_flags, &written,
> >> +					    states);
> >> +	if (ret)
> >> +		goto free_return;
> >> +
> >> +	/*
> >> +	 * Overwrite states buffer with bitmap - the bits in hv_type_mask
> >> +	 * correspond to bitfields in hv_gpa_page_access_state
> >> +	 */
> >> +	for (i = 0; i < written; ++i)
> >> +		assign_bit(i, (ulong *)states,
> >
> > Why the cast to ulong *?  I think this argument to assign_bit() is void *, in
> > which case the cast wouldn't be needed.
> >
> It looks like assign_bit() and friends resolve to a set of functions which do
> take an unsigned long pointer, e.g.:
> 
> __set_bit() -> generic___set_bit(unsigned long nr, volatile unsigned long *addr)
> set_bit() -> arch_set_bit(unsigned int nr, volatile unsigned long *p)
> etc...
> 
> So a cast is necessary.

Indeed, you are right.  Seems like set_bit() and friends should take a void *.
But that's a different kettle of fish.

> 
> > Also, assign_bit() does atomic bit operations. Doing such in a loop like
> > here will really hammer the hardware memory bus with atomic
> > read-modify-write cycles. Use __assign_bit() instead, which does
> > non-atomic operations. You don't need atomic here as no other
> > threads are modifying the bit array.
> >
> I didn't realize it was atomic. I'll change it to __assign_bit().
> 
> >> +			   states[i].as_uint8 & hv_type_mask);
> >
> > OK, so the starting contents of "states" is an array of bytes. The ending
> > contents is an array of bits. This works because every bit in the ending
> > bit array is set to either 0 or 1. Overlap occurs on the first iteration
> > where the code reads the 0th byte, and writes the 0th bit, which is part of
> > the 0th byte. The second iteration reads the 1st byte, and writes the 1st bit,
> > which doesn't overlap, and there's no overlap from then on.
> >
> > Suppose "written" is not a multiple of 8. The last byte of "states" as an
> > array of bits will have some bits that have not been set to either 0 or 1 and
> > might be leftover garbage from when "states" was an array of bytes. That
> > garbage will get copied to user space. Is that OK? Even if user space knows
> > enough to ignore those bits, it seems a little dubious to be copying even
> > a few bits of garbage to user space.
> >
> > Some comments might help here.
> >
> This is a good point. The expectation is indeed that userspace knows which
> bits are valid from the returned "written" value, but I agree it's a bit
> odd to have some garbage bits in the last byte. How does this look (to be
> inserted here directly after the loop):
> 
> +       /* zero the unused bits in the last byte of the returned bitmap */
> +       if (written > 0) {
> +               u8 last_bits_mask;
> +               int last_byte_idx;
> +               int bits_rem = written % 8;
> +
> +               /* bits_rem == 0 when all bits in the last byte were assigned */
> +               if (bits_rem > 0) {
> +                       /* written > 0 ensures last_byte_idx >= 0 */
> +                       last_byte_idx = ((written + 7) / 8) - 1;
> +                       /* bits_rem > 0 ensures this masks 1 to 7 bits */
> +                       last_bits_mask = (1 << bits_rem) - 1;
> +                       states[last_byte_idx].as_uint8 &= last_bits_mask;
> +               }
> +       }

A simpler approach is to "continue" the previous loop.  And if "written"
is zero, this additional loop won't do anything either: 

	for (i = written; i < ALIGN(written, 8); ++i)
		__clear_bit(i, (ulong *)states);

> 
> The remaining bytes could be memset() to zero but I think it's fine to leave
> them.

I agree.  The remaining bytes aren't written back to user space anyway
since the copy_to_user() uses bitmap_buf_sz.

> 
> >> +
> >> +	args.page_count = written;
> >> +
> >> +	if (copy_to_user(user_args, &args, sizeof(args))) {
> >> +		ret = -EFAULT;
> >> +		goto free_return;
> >> +	}
> >> +	if (copy_to_user((void __user *)args.bitmap_ptr, states, bitmap_buf_sz))
> >> +		ret = -EFAULT;
> >> +
> >> +free_return:
> >> +	vfree(states);
> >> +	return ret;
> >> +}
> <snip>
> >> +static void
> >> +handle_bitset_message(const struct hv_vp_signal_bitset_scheduler_message *msg)
> >> +{
> >> +	int bank_idx, vps_signaled = 0, bank_mask_size;
> >> +	struct mshv_partition *partition;
> >> +	const struct hv_vpset *vpset;
> >> +	const u64 *bank_contents;
> >> +	u64 partition_id = msg->partition_id;
> >> +
> >> +	if (msg->vp_bitset.bitset.format != HV_GENERIC_SET_SPARSE_4K) {
> >> +		pr_debug("scheduler message format is not HV_GENERIC_SET_SPARSE_4K");
> >> +		return;
> >> +	}
> >> +
> >> +	if (msg->vp_count == 0) {
> >> +		pr_debug("scheduler message with no VP specified");
> >> +		return;
> >> +	}
> >> +
> >> +	rcu_read_lock();
> >> +
> >> +	partition = mshv_partition_find(partition_id);
> >> +	if (unlikely(!partition)) {
> >> +		pr_debug("failed to find partition %llu\n", partition_id);
> >> +		goto unlock_out;
> >> +	}
> >> +
> >> +	vpset = &msg->vp_bitset.bitset;
> >> +
> >> +	bank_idx = -1;
> >> +	bank_contents = vpset->bank_contents;
> >> +	bank_mask_size = sizeof(vpset->valid_bank_mask) * BITS_PER_BYTE;
> >> +
> >> +	while (true) {
> >> +		int vp_bank_idx = -1;
> >> +		int vp_bank_size = sizeof(*bank_contents) * BITS_PER_BYTE;
> >> +		int vp_index;
> >> +
> >> +		bank_idx = find_next_bit((unsigned long *)&vpset->valid_bank_mask,
> >> +					 bank_mask_size, bank_idx + 1);
> >> +		if (bank_idx == bank_mask_size)
> >> +			break;
> >> +
> >> +		while (true) {
> >> +			struct mshv_vp *vp;
> >> +
> >> +			vp_bank_idx = find_next_bit((unsigned long *)bank_contents,
> >> +						    vp_bank_size, vp_bank_idx + 1);
> >> +			if (vp_bank_idx == vp_bank_size)
> >> +				break;
> >> +
> >> +			vp_index = (bank_idx << HV_GENERIC_SET_SHIFT) + vp_bank_idx;
> >
> > This would be clearer if just multiplied by bank_mask_size instead of shifting.
> > Since the compiler knows the constant value of bank_mask_size, it should generate
> > the same code as the shift.
> >
> I agree, but it should be multiplied by vp_bank_size as that's the size of a bank
> in bits, as opposed bank_mask_size which is the size of the valid banks mask in bits.

Yep, you are right.

> 
> (They're both the same value though, 64).
> 
> <snip>>> +
> >> +/*
> >> + * Map various VP state pages to userspace.
> >> + * Multiply the offset by PAGE_SIZE before being passed as the 'offset'
> >> + * argument to mmap().
> >> + * e.g.
> >> + * void *reg_page = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
> >> + *                       MAP_SHARED, vp_fd,
> >> + *                       MSHV_VP_MMAP_OFFSET_REGISTERS * PAGE_SIZE);
> >> + */
> >
> > This is interesting.  I would not have thought PAGE_SIZE is available
> > in the UAPI.  You must use something like the getpagesize() call. I know
> > the root partition can only run with a 4K page size, but the symbol
> > "PAGE_SIZE" is probably kernel code only.
> >
> PAGE_SIZE here is meant to imply using whatever the system page size is,
> but I think it's probably better to be explicit in the example. I will
> change it to sysconf(_SC_PAGE_SIZE) as that seems to be the recommended way.
> 
> While at it I realized there were some more references to PAGE_SIZE and
> HV_HYP_PAGE_SIZE in this file, but neither are defined in uapi.
> I'm going to add a new #define MSHV_HV_PAGE_SIZE which matches the
> hypervisor native page size of 0x1000 for these cases.

OK.

> 
> This mmap() call is the only time where the system page size is needed
> instead of the Hyper-V page size.
> 

Michael


From alexei.starovoitov at gmail.com  Tue Mar 18 19:40:44 2025
From: alexei.starovoitov at gmail.com (Alexei Starovoitov)
Date: Tue, 18 Mar 2025 19:40:44 -0700
Subject: [PATCH bpf-next 11/11] bpf: Fall back to nospec for spec path verification
In-Reply-To: <20250313175312.1120183-2-luis.gerhorst@fau.de>
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
 <20250313175312.1120183-1-luis.gerhorst@fau.de> <20250313175312.1120183-2-luis.gerhorst@fau.de>
Message-ID: <CAADnVQKL-NwxigMWM+U=n5ZXPG+xHYzSTEv0Rq8Y91m45eRJDw@mail.gmail.com>

On Thu, Mar 13, 2025 at 10:57?AM Luis Gerhorst <luis.gerhorst at fau.de> wrote:
>
> This trades verification complexity for runtime overheads due to the
> nospec inserted because of the EINVAL.
>
> With increased limits this allows applying mitigations to large BPF
> progs such as the Parca Continuous Profiler's prog. However, this
> requires a jump-seq limit of 256k. In any case, the same principle
> should apply to smaller programs therefore include it even if the limit
> stays at 8k for now. Most programs in [1] only require a limit of 32k.

Do you mean that without this change the verifier needs 256k
jmp limit to load Parca's prog as unpriv due to speculative
path exploration with push_stack ?

And this change uses 4k as a trade-off between prog runtime
and verification time ?

But tracing progs use bpf_probe_read_kernel(), so they're never going
to be unpriv.

> @@ -2010,6 +2011,19 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
>         struct bpf_verifier_stack_elem *elem;
>         int err;
>
> +       if (!env->bypass_spec_v1 &&
> +           cur->speculative &&

Should this be
(cur->speculative || speculative)
?

In general I'm not convinced that the approach is safe.

This recoverable EINVAL means that exploration under speculation
stops early, but there could be more branches and they won't be
sanitized with extra lfence.
So speculative execution can still happen at later insns.

Similar concern in patch 7:
+ if (state->speculative && cur_aux(env)->nospec)
+   goto process_bpf_exit;

One lfence at this insn doesn't stop speculation until the program end.
Only at this insn. The rest of the code is free to speculate.

The refactoring in patches 1-3 is nice.
Patches 4-5 are tricky and somewhat questionable, but make sense.
Patch 7 without early goto process_bpf_exit looks correct too,
Patch 8 is borderline. Feels like it's opening the door for
new vulnerabilities and space to explore for security researchers.
We disabled unpriv bpf by default and have no intentions to enable it.
Even if we land the whole thing the unpriv will stay disabled.
So trade offs don't appear favorable.


From Jjian.Zhou at mediatek.com  Tue Mar 18 19:45:40 2025
From: Jjian.Zhou at mediatek.com (=?utf-8?B?SmppYW4gWmhvdSAo5ZGo5bu6KQ==?=)
Date: Wed, 19 Mar 2025 02:45:40 +0000
Subject: [PATCH RFC v3 2/3] firmware: mediatek: Add vcp ipc protocol
 interface
In-Reply-To: <12f5049d-02e1-4c80-9289-b2dfb1e136a8@kernel.org>
References: <20250317110331.2776-1-jjian.zhou@mediatek.com>
	 <20250317110331.2776-3-jjian.zhou@mediatek.com>
	 <d3f8fbe3-c061-4d34-a5a3-09cbf676bc4c@kernel.org>
	 <f3b6a690f73e8f5a5370a587d0b1671e96e8b5b2.camel@mediatek.com>
	 <12f5049d-02e1-4c80-9289-b2dfb1e136a8@kernel.org>
Message-ID: <d55bcde48451f403172833ecf48fbc9066915e57.camel@mediatek.com>

On Tue, 2025-03-18 at 10:00 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 18/03/2025 09:32, Jjian Zhou (??) wrote:
> > > > +
> > > > +     return IPI_ACTION_DONE;
> > > > +}
> > > > +EXPORT_SYMBOL(mtk_vcp_ipc_send);
> > > 
> > > Drop export - no users
> > > 
> > > Anyway, every export must be GPL.
> > 
> > The Video Companion Processor (VCP) driver (currently being
> > prepared
> > for submission to the community) will call it.
> > 
> 
> It does not work like that. You must post the users NOW.
> 
> NAK
> 

Let's review this patch together after the VCP driver is ready. Patch 1
and Patch 3 will be combined into v4 for review. How do you think?

> 
> ...
> 
> > > Check goes immediately after declaration. I doubt it is useful in
> > > the
> > > first place as this cannot even happen...
> > > 
> > > 
> > > > +             dev_err(dev, "No platform data available\n");
> > > 
> > > No, drop. Cannot happen or fix your drivers. Who provides the
> > > platdata here?
> > 
> > The VCP driver will call platform_device_register_data to register
> > the
> > structure data. mtk_vcp_ipc_probe will be triggered by vcp_probe.
> > This
> > structure data is the structure we described in the cover letter.
> 
> 
> Comment is still valid.

Let's review this patch together after the VCP driver is ready. Patch 1
and Patch 3 will be combined into v4 for review. How do you think?

> 
> Best regards,
> Krzysztof

From xueshuai at linux.alibaba.com  Tue Mar 18 19:59:57 2025
From: xueshuai at linux.alibaba.com (Shuai Xue)
Date: Wed, 19 Mar 2025 10:59:57 +0800
Subject: [PATCH] selftests/pidfd: align stack to fix SP alignment
 exception
In-Reply-To: <20250312061557.28532-1-xueshuai@linux.alibaba.com>
References: <20250312061557.28532-1-xueshuai@linux.alibaba.com>
Message-ID: <0a70f4ab-cd83-434d-8dd2-486d58e5599a@linux.alibaba.com>

+ ARM maintainers for review.

? 2025/3/12 14:15, Shuai Xue ??:
> The pidfd_test fails on the ARM64 platform with the following error:
> 
>      Bail out! pidfd_poll check for premature notification on child thread exec test: Failed
> 
> When exception-trace is enabled, the kernel logs the details:
> 
>      #echo 1 > /proc/sys/debug/exception-trace
>      #dmesg | tail -n 20
>      [48628.713023] pidfd_test[1082142]: unhandled exception: SP Alignment, ESR 0x000000009a000000, SP/PC alignment exception in pidfd_test[400000+4000]
>      [48628.713049] CPU: 21 PID: 1082142 Comm: pidfd_test Kdump: loaded Tainted: G        W   E      6.6.71-3_rc1.al8.aarch64 #1
>      [48628.713051] Hardware name: AlibabaCloud AliServer-Xuanwu2.0AM-1UC1P-5B/AS1111MG1, BIOS 1.2.M1.AL.P.157.00 07/29/2023
>      [48628.713053] pstate: 60001800 (nZCv daif -PAN -UAO -TCO -DIT +SSBS BTYPE=-c)
>      [48628.713055] pc : 0000000000402100
>      [48628.713056] lr : 0000ffff98288f9c
>      [48628.713056] sp : 0000ffffde49daa8
>      [48628.713057] x29: 0000000000000000 x28: 0000000000000000 x27: 0000000000000000
>      [48628.713060] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
>      [48628.713062] x23: 0000000000000000 x22: 0000000000000000 x21: 0000000000400e80
>      [48628.713065] x20: 0000000000000000 x19: 0000000000402650 x18: 0000000000000000
>      [48628.713067] x17: 00000000004200d8 x16: 0000ffff98288f40 x15: 0000ffffde49b92c
>      [48628.713070] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
>      [48628.713072] x11: 0000000000001011 x10: 0000000000402100 x9 : 0000000000000010
>      [48628.713074] x8 : 00000000000000dc x7 : 3861616239346564 x6 : 000000000000000a
>      [48628.713077] x5 : 0000ffffde49daa8 x4 : 000000000000000a x3 : 0000ffffde49daa8
>      [48628.713079] x2 : 0000ffffde49dadc x1 : 0000ffffde49daa8 x0 : 0000000000000000
> 
> According to ARM ARM D1.3.10.2 SP alignment checking:
> 
>> When the SP is used as the base address of a calculation, regardless of
>> any offset applied by the instruction, if bits [3:0] of the SP are not
>> 0b0000, there is a misaligned SP.
> 
> To fix it, align the stack with 16 bytes.
> 
> Signed-off-by: Shuai Xue <xueshuai at linux.alibaba.com>
> ---
>   tools/testing/selftests/pidfd/pidfd_test.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c
> index c081ae91313a..ec161a7c3ff9 100644
> --- a/tools/testing/selftests/pidfd/pidfd_test.c
> +++ b/tools/testing/selftests/pidfd/pidfd_test.c
> @@ -33,7 +33,7 @@ static bool have_pidfd_send_signal;
>   static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
>   {
>   	size_t stack_size = 1024;
> -	char *stack[1024] = { 0 };
> +	char *stack[1024] __attribute__((aligned(16))) = {0};
>   
>   #ifdef __ia64__
>   	return __clone2(fn, stack, stack_size, flags | SIGCHLD, NULL, pidfd);



From kees at kernel.org  Tue Mar 18 20:06:28 2025
From: kees at kernel.org (Kees Cook)
Date: Tue, 18 Mar 2025 20:06:28 -0700
Subject: [PATCH v2 1/2] string: Add load_unaligned_zeropad() code path to
 sized_strscpy()
In-Reply-To: <20250318214035.481950-2-pcc@google.com>
References: <20250318214035.481950-1-pcc@google.com>
 <20250318214035.481950-2-pcc@google.com>
Message-ID: <202503181957.55A0E0A@keescook>

On Tue, Mar 18, 2025 at 02:40:32PM -0700, Peter Collingbourne wrote:
> The call to read_word_at_a_time() in sized_strscpy() is problematic
> with MTE because it may trigger a tag check fault when reading
> across a tag granule (16 bytes) boundary. To make this code
> MTE compatible, let's start using load_unaligned_zeropad()
> on architectures where it is available (i.e. architectures that
> define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad()
> takes care of page boundaries as well as tag granule boundaries,
> also disable the code preventing crossing page boundaries when using
> load_unaligned_zeropad().
> 
> Signed-off-by: Peter Collingbourne <pcc at google.com>
> Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> Cc: stable at vger.kernel.org
> ---
> v2:
> - new approach
> 
>  lib/string.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/string.c b/lib/string.c
> index eb4486ed40d25..b632c71df1a50 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -119,6 +119,7 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
>  		return -E2BIG;
>  
> +#ifndef CONFIG_DCACHE_WORD_ACCESS
>  #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS

I would prefer this were written as:

#if !defined(CONFIG_DCACHE_WORD_ACCESS) && \
    defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)

Having 2 #ifs makes me think there is some reason for having them
separable. But the logic here is for a single check.

>  	/*
>  	 * If src is unaligned, don't cross a page boundary,
> @@ -133,12 +134,14 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	/* If src or dest is unaligned, don't do word-at-a-time. */
>  	if (((long) dest | (long) src) & (sizeof(long) - 1))
>  		max = 0;
> +#endif
>  #endif

(Then no second #endif needed)

>  
>  	/*
> -	 * read_word_at_a_time() below may read uninitialized bytes after the
> -	 * trailing zero and use them in comparisons. Disable this optimization
> -	 * under KMSAN to prevent false positive reports.
> +	 * load_unaligned_zeropad() or read_word_at_a_time() below may read
> +	 * uninitialized bytes after the trailing zero and use them in
> +	 * comparisons. Disable this optimization under KMSAN to prevent
> +	 * false positive reports.
>  	 */
>  	if (IS_ENABLED(CONFIG_KMSAN))
>  		max = 0;
> @@ -146,7 +149,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	while (max >= sizeof(unsigned long)) {
>  		unsigned long c, data;
>  
> +#ifdef CONFIG_DCACHE_WORD_ACCESS
> +		c = load_unaligned_zeropad(src+res);
> +#else
>  		c = read_word_at_a_time(src+res);
> +#endif
>  		if (has_zero(c, &data, &constants)) {
>  			data = prep_zero_mask(c, data, &constants);
>  			data = create_zero_mask(data);

The rest seems good. Though I do wonder: what happens on a page boundary
for read_word_at_a_time(), then? We get back zero-filled remainder? Will
that hide a missing NUL terminator? As in, it's not actually there
because of the end of the page/granule, but a zero was put in, so now
it looks like it's been terminated and the exception got eaten? And
doesn't this hide MTE faults since we can't differentiate "overran MTE
tag" from "overran granule while over-reading"?

-- 
Kees Cook


From Friday.Yang at mediatek.com  Tue Mar 18 20:06:50 2025
From: Friday.Yang at mediatek.com (=?utf-8?B?RnJpZGF5IFlhbmcgKOadqOmYsyk=?=)
Date: Wed, 19 Mar 2025 03:06:50 +0000
Subject: [PATCH v5 2/2] memory: mtk-smi: mt8188: Add SMI reset and clamp
 for MT8188
In-Reply-To: <6008832c-e175-4b02-90a6-f790dacd1d09@kernel.org>
References: <20250311122327.20685-1-friday.yang@mediatek.com>
	 <20250311122327.20685-3-friday.yang@mediatek.com>
	 <6008832c-e175-4b02-90a6-f790dacd1d09@kernel.org>
Message-ID: <18146544c3563868e84621708d53825f31849079.camel@mediatek.com>

On Wed, 2025-03-12 at 13:02 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 11/03/2025 13:23, Friday Yang wrote:
> >  static int mtk_smi_device_link_common(struct device *dev, struct
> > device **com_dev)
> >  {
> >       struct platform_device *smi_com_pdev;
> > @@ -528,6 +598,53 @@ static int mtk_smi_dts_clk_init(struct device
> > *dev, struct mtk_smi *smi,
> >       return ret;
> >  }
> > 
> > +static int mtk_smi_larb_parse_clamp_optional(struct mtk_smi_larb
> > *larb)
> > +{
> > +     struct device *dev = larb->dev;
> > +     const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
> > +     u32 larb_id;
> > +     int ret;
> > +
> > +     /**
> 
> Not a kerneldoc
> 

OK, I will fix it like this:
/*
 * Only SMI LARBs ...
 */

> > +      * Only SMI LARBs in camera, image and IPE subsys need to
> > +      * apply clamp and reset operations, others can be skipped.
> > +      */
> > +     ret = of_property_read_u32(dev->of_node, "mediatek,larb-id",
> > &larb_id);
> 
> 
> ...
> 
> 
> >  static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
> >       .type     = MTK_SMI_GEN2,
> >       .has_gals = true,
> > @@ -729,6 +862,7 @@ static const struct of_device_id
> > mtk_smi_common_of_ids[] = {
> >       {.compatible = "mediatek,mt8186-smi-common", .data =
> > &mtk_smi_common_mt8186},
> >       {.compatible = "mediatek,mt8188-smi-common-vdo", .data =
> > &mtk_smi_common_mt8188_vdo},
> >       {.compatible = "mediatek,mt8188-smi-common-vpp", .data =
> > &mtk_smi_common_mt8188_vpp},
> > +     {.compatible = "mediatek,mt8188-smi-sub-common", .data =
> > &mtk_smi_sub_common_mt8188},
> >       {.compatible = "mediatek,mt8192-smi-common", .data =
> > &mtk_smi_common_mt8192},
> >       {.compatible = "mediatek,mt8195-smi-common-vdo", .data =
> > &mtk_smi_common_mt8195_vdo},
> >       {.compatible = "mediatek,mt8195-smi-common-vpp", .data =
> > &mtk_smi_common_mt8195_vpp},
> > @@ -787,7 +921,10 @@ static int mtk_smi_common_probe(struct
> > platform_device *pdev)
> >                       return ret;
> >       }
> > 
> > -     pm_runtime_enable(dev);
> > +     ret = devm_pm_runtime_enable(dev);
> > +     if (ret)
> > +             return ret;
> > +
> >       platform_set_drvdata(pdev, common);
> >       return 0;
> >  }
> > @@ -798,7 +935,6 @@ static void mtk_smi_common_remove(struct
> > platform_device *pdev)
> > 
> >       if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
> >               device_link_remove(&pdev->dev, common-
> > >smi_common_dev);
> > -     pm_runtime_disable(&pdev->dev);
> 
> Does not look related to this patch. Is it some sort of cleanup to
> devm?

This 'devm' modification aims to remove 'pm_runtime_disable' and
'err_pm_disable', which would make the code more efficient. 
If I insist on using 'pm_runtime_enable', I would need to add another
'goto err_pm_disable', which is not an ideal solution. Just as below,

	ret = mtk_smi_larb_parse_clamp_optional(larb);
	if (ret)
		goto err_link_remove;

	ret = mtk_smi_larb_parse_reset_optional(larb);
	if (ret)
		goto err_link_remove;

	pm_runtime_enable(dev);
	platform_set_drvdata(pdev, larb);
	ret = component_add(dev, &mtk_smi_larb_component_ops);
	if (ret)
		goto err_pm_disable;

	return 0;

err_pm_disable:
	pm_runtime_disable(dev);
err_link_remove:
	device_link_remove(dev, larb->smi_common_dev);
	return ret;

Therefore, I prefer to use 'devm_pm_runtime_enable' here. Please let me
know if you have any concerns, thanks!

> 
> Best regards,
> Krzysztof

From devnull+bjorn.andersson.oss.qualcomm.com at kernel.org  Tue Mar 18 20:11:37 2025
From: devnull+bjorn.andersson.oss.qualcomm.com at kernel.org (Bjorn Andersson via B4 Relay)
Date: Tue, 18 Mar 2025 22:11:37 -0500
Subject: [PATCH] arm64: defconfig: Enable USB retimer and redriver
Message-ID: <20250318-xelite-retimer-redriver-v1-1-b3e85a37d294@oss.qualcomm.com>

From: Bjorn Andersson <bjorn.andersson at oss.qualcomm.com>

Several boards based on the Qualcomm X Elite platform uses the NXP
PTN3222 USB redriver and the Parade PS883x USB Type-C retimer. Without
these USB, and in some cases display, doesn't probe successfully, so
enable them.

Signed-off-by: Bjorn Andersson <bjorn.andersson at oss.qualcomm.com>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index e8dfbe22db68d9aa24df5af0786a2eeb8f33bf3c..5bb8f09422a22116781169611482179b10798c14 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1153,6 +1153,7 @@ CONFIG_TYPEC_HD3SS3220=m
 CONFIG_TYPEC_MUX_FSA4480=m
 CONFIG_TYPEC_MUX_GPIO_SBU=m
 CONFIG_TYPEC_MUX_NB7VPQ904M=m
+CONFIG_TYPEC_MUX_PS883X=m
 CONFIG_TYPEC_MUX_WCD939X_USBSS=m
 CONFIG_TYPEC_DP_ALTMODE=m
 CONFIG_MMC=y
@@ -1573,6 +1574,7 @@ CONFIG_RESET_RZG2L_USBPHY_CTRL=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_PHY_XGENE=y
 CONFIG_PHY_CAN_TRANSCEIVER=m
+CONFIG_PHY_NXP_PTN3222=m
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_CADENCE_TORRENT=m
 CONFIG_PHY_CADENCE_DPHY_RX=m

---
base-commit: c4d4884b67802c41fd67399747165d65c770621a
change-id: 20250318-xelite-retimer-redriver-72b46318d962

Best regards,
-- 
Bjorn Andersson <bjorn.andersson at oss.qualcomm.com>




From inki.dae at samsung.com  Tue Mar 18 20:30:36 2025
From: inki.dae at samsung.com (=?utf-8?B?64yA7J246riwL1RpemVuIFBsYXRmb3JtIExhYihTUikv7IK87ISx7KCE7J6Q?=)
Date: Wed, 19 Mar 2025 12:30:36 +0900
Subject: [PATCH] drm/exynos/vidi: Remove redundant error handling in
 vidi_get_modes()
In-Reply-To: <20250306042720.2296-1-vulab@iscas.ac.cn>
References: <CGME20250306042753epcas1p3983510872a862109f7f72aff5d074ea3@epcas1p3.samsung.com>
	<20250306042720.2296-1-vulab@iscas.ac.cn>
Message-ID: <000001db987f$479ece60$d6dc6b20$@samsung.com>

Hi,

> -----Original Message-----
> From: Wentao Liang <vulab at iscas.ac.cn>
> Sent: Thursday, March 6, 2025 1:27 PM
> To: jani.nikula at linux.intel.com; inki.dae at samsung.com;
> sw0312.kim at samsung.com; kyungmin.park at samsung.com; airlied at gmail.com;
> simona at ffwll.ch; krzk at kernel.org; alim.akhtar at samsung.com
> Cc: dri-devel at lists.freedesktop.org; linux-arm-kernel at lists.infradead.org;
> linux-samsung-soc at vger.kernel.org; linux-kernel at vger.kernel.org; Wentao
> Liang <vulab at iscas.ac.cn>
> Subject: [PATCH] drm/exynos/vidi: Remove redundant error handling in
> vidi_get_modes()
> 
> In the vidi_get_modes() function, if either drm_edid_dup() or
> drm_edid_alloc() fails, the function will immediately return 0,
> indicating that no display modes can be retrieved. However, in
> the event of failure in these two functions, it is still necessary
> to call the subsequent drm_edid_connector_update() function with
> a NULL drm_edid as an argument. This ensures that operations such
> as connector settings are performed in its callee function,
> _drm_edid_connector_property_update. To maintain the integrity of
> the operation, redundant error handling needs to be removed.

You are right. Merged.

Thanks,
Inki Dae

> 
> Signed-off-by: Wentao Liang <vulab at iscas.ac.cn>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index fd388b1dbe68..a956cdb2f33a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -312,9 +312,6 @@ static int vidi_get_modes(struct drm_connector
> *connector)
>  	else
>  		drm_edid = drm_edid_alloc(fake_edid_info,
> sizeof(fake_edid_info));
> 
> -	if (!drm_edid)
> -		return 0;
> -
>  	drm_edid_connector_update(connector, drm_edid);
> 
>  	count = drm_edid_connector_add_modes(connector);
> --
> 2.42.0.windows.2




From anshuman.khandual at arm.com  Tue Mar 18 20:34:08 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Wed, 19 Mar 2025 09:04:08 +0530
Subject: [PATCH v4 3/8] bits: introduce fixed-type genmasks
In-Reply-To: <Z9oiEkQEcHhA0a80@thinkpad>
References: <20250305-fixed-type-genmasks-v4-0-1873dcdf6723@wanadoo.fr>
 <20250305-fixed-type-genmasks-v4-3-1873dcdf6723@wanadoo.fr>
 <Z8hsRJvpjYoqh9RG@thinkpad> <Z9oiEkQEcHhA0a80@thinkpad>
Message-ID: <5cbaefa8-e51f-415f-a9b3-4841e69bb3fa@arm.com>

On 3/19/25 07:16, Yury Norov wrote:
> + Catalin Marinas, ARM maillist
> 
> Hi Catalin and everyone,

Hello Yury,

> 
> Anshuman Khandual asked me to merge GENMASK_U128() saying it's
> important for ARM to stabilize API. While it's a dead code, I
> accepted his patch as he promised to add users shortly.
> 
> Now it's more than half a year since that. There's no users,
> and no feedback from Anshuman.

My apologies to have missed your email earlier. Please find response
for the earlier email below as well.

> 
> Can you please tell if you still need the macro? I don't want to
> undercut your development, but if you don't need 128-bit genmasks
> there's no reason to have a dead code in the uapi.

The code base specifically using GENMASK_U128() has not been posted
upstream (probably in next couple of months or so) till now, except
the following patch which has been not been merged and still under
review and development.

https://lore.kernel.org/lkml/20240801054436.612024-1-anshuman.khandual at arm.com/

> 
> Thanks,
> Yury
> 
> On Wed, Mar 05, 2025 at 10:22:47AM -0500, Yury Norov wrote:
>> + Anshuman Khandual <anshuman.khandual at arm.com>
>>
>> Anshuman,
>>
>> I merged your GENMASK_U128() because you said it's important for your
>> projects, and that it will get used in the kernel soon.
>>
>> Now it's in the kernel for more than 6 month, but no users were added.
>> Can you clarify if you still need it, and if so why it's not used?

We would need it but although the code using GENMASK_U128() has not been
posted upstream.

>>
>> As you see, people add another fixed-types GENMASK() macros, and their
>> implementation differ from GENMASK_U128().

I will take a look. Is GENMASK_U128() being problematic for the this new
scheme ?

>>
>> My second concern is that __GENMASK_U128() is declared in uapi, while
>> the general understanding for other fixed-type genmasks is that they
>> are not exported to users. Do you need this macro to be exported to
>> userspace? Can you show how and where it is used there?

No, not atleast right now.

These were moved into uapi subsequently via the following commit.

21a3a3d015aee ("tools headers: Synchronize {uapi/}linux/bits.h with the kernel sources")

But in general GENMASK_U128() is needed for generating 128 bit page table
entries, related flags and masks whether in kernel or in user space for
writing kernel test cases etc.

>>
>> Thanks,
>> Yury
>>
>>
>> On Wed, Mar 05, 2025 at 10:00:15PM +0900, Vincent Mailhol via B4 Relay wrote:
>>> From: Yury Norov <yury.norov at gmail.com>
>>>
>>> Add __GENMASK_t() which generalizes __GENMASK() to support different
>>> types, and implement fixed-types versions of GENMASK() based on it.
>>> The fixed-type version allows more strict checks to the min/max values
>>> accepted, which is useful for defining registers like implemented by
>>> i915 and xe drivers with their REG_GENMASK*() macros.
>>>
>>> The strict checks rely on shift-count-overflow compiler check to fail
>>> the build if a number outside of the range allowed is passed.
>>> Example:
>>>
>>> 	#define FOO_MASK GENMASK_U32(33, 4)
>>>
>>> will generate a warning like:
>>>
>>> 	../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
>>> 	   41 |          (((t)~0ULL - ((t)(1) << (l)) + 1) & \
>>> 	      |                               ^~
>>>
>>> Signed-off-by: Yury Norov <yury.norov at gmail.com>
>>> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
>>> Acked-by: Jani Nikula <jani.nikula at intel.com>
>>> Signed-off-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
>>> ---
>>> Changelog:
>>>
>>>   v3 -> v4:
>>>
>>>     - The v3 is one year old. Meanwhile people started using
>>>       __GENMASK() directly. So instead of generalizing __GENMASK() to
>>>       support different types, add a new GENMASK_t().
>>>
>>>     - replace ~0ULL by ~_ULL(0). Otherwise, __GENMASK_t() would fail
>>>       in asm code.
>>>
>>>     - Make GENMASK_U8() and GENMASK_U16() return an unsigned int. In
>>>       v3, due to the integer promotion rules, these were returning a
>>>       signed integer. By casting these to unsigned int, at least the
>>>       signedness is kept.
>>> ---
>>>  include/linux/bitops.h |  1 -
>>>  include/linux/bits.h   | 33 +++++++++++++++++++++++++++++----
>>>  2 files changed, 29 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
>>> index c1cb53cf2f0f8662ed3e324578f74330e63f935d..9be2d50da09a417966b3d11c84092bb2f4cd0bef 100644
>>> --- a/include/linux/bitops.h
>>> +++ b/include/linux/bitops.h
>>> @@ -8,7 +8,6 @@
>>>  
>>>  #include <uapi/linux/kernel.h>
>>>  
>>> -#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
>>>  #define BITS_TO_LONGS(nr)	__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
>>>  #define BITS_TO_U64(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
>>>  #define BITS_TO_U32(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
>>> diff --git a/include/linux/bits.h b/include/linux/bits.h
>>> index 5f68980a1b98d771426872c74d7b5c0f79e5e802..f202e46d2f4b7899c16d975120f3fa3ae41556ae 100644
>>> --- a/include/linux/bits.h
>>> +++ b/include/linux/bits.h
>>> @@ -12,6 +12,7 @@
>>>  #define BIT_ULL_MASK(nr)	(ULL(1) << ((nr) % BITS_PER_LONG_LONG))
>>>  #define BIT_ULL_WORD(nr)	((nr) / BITS_PER_LONG_LONG)
>>>  #define BITS_PER_BYTE		8
>>> +#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
>>>  
>>>  /*
>>>   * Create a contiguous bitmask starting at bit position @l and ending at
>>> @@ -25,14 +26,38 @@
>>>  
>>>  #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h)))
>>>  
>>> -#define GENMASK(h, l) \
>>> -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
>>> -#define GENMASK_ULL(h, l) \
>>> -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
>>> +/*
>>> + * Generate a mask for the specified type @t. Additional checks are made to
>>> + * guarantee the value returned fits in that type, relying on
>>> + * shift-count-overflow compiler check to detect incompatible arguments.
>>> + * For example, all these create build errors or warnings:
>>> + *
>>> + * - GENMASK(15, 20): wrong argument order
>>> + * - GENMASK(72, 15): doesn't fit unsigned long
>>> + * - GENMASK_U32(33, 15): doesn't fit in a u32
>>> + */
>>> +#define GENMASK_t(t, h, l)				\
>>> +	(GENMASK_INPUT_CHECK(h, l) +			\
>>> +	 (((t)~ULL(0) - ((t)1 << (l)) + 1) &		\
>>> +	  ((t)~ULL(0) >> (BITS_PER_TYPE(t) - 1 - (h)))))
>>> +
>>> +#define GENMASK(h, l) GENMASK_t(unsigned long,  h, l)
>>> +#define GENMASK_ULL(h, l) GENMASK_t(unsigned long long, h, l)
>>>  
>>>  /*
>>>   * Missing asm support
>>>   *
>>> + * __GENMASK_U*() depends on BITS_PER_TYPE() which would not work in the asm
>>> + * code as BITS_PER_TYPE() relies on sizeof(), something not available in
>>> + * asm. Nethertheless, the concept of fixed width integers is a C thing which
>>> + * does not apply to assembly code.
>>> + */
>>> +#define GENMASK_U8(h, l) ((unsigned int)GENMASK_t(u8,  h, l))
>>> +#define GENMASK_U16(h, l) ((unsigned int)GENMASK_t(u16, h, l))
>>> +#define GENMASK_U32(h, l) GENMASK_t(u32, h, l)
>>> +#define GENMASK_U64(h, l) GENMASK_t(u64, h, l)
>>> +
>>> +/*
>>>   * __GENMASK_U128() depends on _BIT128() which would not work
>>>   * in the asm code, as it shifts an 'unsigned __int128' data
>>>   * type instead of direct representation of 128 bit constants
>>>
>>> -- 
>>> 2.45.3
>>>


From pcc at google.com  Tue Mar 18 20:35:19 2025
From: pcc at google.com (Peter Collingbourne)
Date: Tue, 18 Mar 2025 20:35:19 -0700
Subject: [PATCH v2 1/2] string: Add load_unaligned_zeropad() code path to sized_strscpy()
In-Reply-To: <202503181957.55A0E0A@keescook>
References: <20250318214035.481950-1-pcc@google.com> <20250318214035.481950-2-pcc@google.com>
 <202503181957.55A0E0A@keescook>
Message-ID: <CAMn1gO7TG0xXMFNFXTm9W8n4hdit9Yr40m4jvFCjdv9fGiU5iw@mail.gmail.com>

On Tue, Mar 18, 2025 at 8:06?PM Kees Cook <kees at kernel.org> wrote:
>
> On Tue, Mar 18, 2025 at 02:40:32PM -0700, Peter Collingbourne wrote:
> > The call to read_word_at_a_time() in sized_strscpy() is problematic
> > with MTE because it may trigger a tag check fault when reading
> > across a tag granule (16 bytes) boundary. To make this code
> > MTE compatible, let's start using load_unaligned_zeropad()
> > on architectures where it is available (i.e. architectures that
> > define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad()
> > takes care of page boundaries as well as tag granule boundaries,
> > also disable the code preventing crossing page boundaries when using
> > load_unaligned_zeropad().
> >
> > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
> > Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
> > Cc: stable at vger.kernel.org
> > ---
> > v2:
> > - new approach
> >
> >  lib/string.c | 13 ++++++++++---
> >  1 file changed, 10 insertions(+), 3 deletions(-)
> >
> > diff --git a/lib/string.c b/lib/string.c
> > index eb4486ed40d25..b632c71df1a50 100644
> > --- a/lib/string.c
> > +++ b/lib/string.c
> > @@ -119,6 +119,7 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
> >       if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
> >               return -E2BIG;
> >
> > +#ifndef CONFIG_DCACHE_WORD_ACCESS
> >  #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
>
> I would prefer this were written as:
>
> #if !defined(CONFIG_DCACHE_WORD_ACCESS) && \
>     defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
>
> Having 2 #ifs makes me think there is some reason for having them
> separable. But the logic here is for a single check.

There is indeed a reason for having two: there's an #else in the
middle (which pertains to CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
only).

>
> >       /*
> >        * If src is unaligned, don't cross a page boundary,
> > @@ -133,12 +134,14 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
> >       /* If src or dest is unaligned, don't do word-at-a-time. */
> >       if (((long) dest | (long) src) & (sizeof(long) - 1))
> >               max = 0;
> > +#endif
> >  #endif
>
> (Then no second #endif needed)
>
> >
> >       /*
> > -      * read_word_at_a_time() below may read uninitialized bytes after the
> > -      * trailing zero and use them in comparisons. Disable this optimization
> > -      * under KMSAN to prevent false positive reports.
> > +      * load_unaligned_zeropad() or read_word_at_a_time() below may read
> > +      * uninitialized bytes after the trailing zero and use them in
> > +      * comparisons. Disable this optimization under KMSAN to prevent
> > +      * false positive reports.
> >        */
> >       if (IS_ENABLED(CONFIG_KMSAN))
> >               max = 0;
> > @@ -146,7 +149,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
> >       while (max >= sizeof(unsigned long)) {
> >               unsigned long c, data;
> >
> > +#ifdef CONFIG_DCACHE_WORD_ACCESS
> > +             c = load_unaligned_zeropad(src+res);
> > +#else
> >               c = read_word_at_a_time(src+res);
> > +#endif
> >               if (has_zero(c, &data, &constants)) {
> >                       data = prep_zero_mask(c, data, &constants);
> >                       data = create_zero_mask(data);
>
> The rest seems good. Though I do wonder: what happens on a page boundary
> for read_word_at_a_time(), then? We get back zero-filled remainder? Will
> that hide a missing NUL terminator? As in, it's not actually there
> because of the end of the page/granule, but a zero was put in, so now
> it looks like it's been terminated and the exception got eaten? And
> doesn't this hide MTE faults since we can't differentiate "overran MTE
> tag" from "overran granule while over-reading"?

Correct. The behavior I implemented seems good enough for now IMO (and
at least good enough for backports). If we did want to detect this
case, we would need an alternative to "load_unaligned_zeropad" that
would do something other than fill the unreadable bytes with zeros in
the fault handler. For example, it could fill them with all-ones. That
would prevent the loop from being terminated by the tag check fault,
and we would proceed to the next granule, take another tag check fault
which would recur in the fault handler and cause the bug to be
detected.

Peter


From song at kernel.org  Tue Mar 18 20:58:52 2025
From: song at kernel.org (Song Liu)
Date: Tue, 18 Mar 2025 20:58:52 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <pym6gfbapfy6qlmduszjk6tf2oc2fv4rtxgwjgex7bwlgpfwvs@bkt7qfmf7rc4>
References: <20250308012742.3208215-1-song@kernel.org> <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
 <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>
 <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>
 <CAPhsuW4BEDU=ZJavnofZtygGcQ9AJ5F2jJiuV6-nsnbZD+Gg-Q@mail.gmail.com> <pym6gfbapfy6qlmduszjk6tf2oc2fv4rtxgwjgex7bwlgpfwvs@bkt7qfmf7rc4>
Message-ID: <CAPhsuW6_ZA+V_5JK+xy4v3pyQ-kaZzUooxO=4L+c95fHaW38ig@mail.gmail.com>

On Tue, Mar 18, 2025 at 6:03?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
>
> On Tue, Mar 18, 2025 at 04:38:20PM -0700, Song Liu wrote:
> > On Tue, Mar 18, 2025 at 4:00?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
> > >   - even in the -ENOENT case the unreliable bit has already been set
> > >     right before the call to kunwind_next_frame_record_meta().
> >
> > For this one, do you mean we set state->common.unreliable, but
> > failed to propagate it to data.unreliable?
>
> Hm, I hadn't noticed that.  That code is quite the maze.
>
> It's unfortunate there are two separate 'unreliable' variables.  It
> looks like consume_state() is the only way they get synced?
>
> How does that work if kunwind_next() returns an error and skips
> consume_state()?  Or if kunwind_recover_return_address() returns an
> error to kunwind_next()?
>
> What I actually meant was the following:
>
>   do_kunwind()
>     kunwind_next()
>       kunwind_next_frame_record()
>         state->common.unreliable = true;
>         kunwind_next_frame_record_meta()
>           return -ENOENT;
>
> Notice that in the success case (-ENOENT), unreliable has already been
> set.
>
> Actually I think it would be much simpler to just propagate -ENOENT down
> the call chain.  Then no 'unreliable' bits needed.

Yeah, I was thinking about something like this. This is actually quite
similar to my original RFC version.

On a closer look, I think we also need some logic in unwind_find_stack()
so that we can see when the unwinder hits the exception boundary. For
this reason, we may still need unwind_state.unreliable. I will look into
fixing this and send v2.

Thanks,
Song

>
> Like so (instead of original patch):
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index c9fe3e7566a6..5713fad567c5 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -276,6 +276,7 @@ config ARM64
>         select HAVE_SOFTIRQ_ON_OWN_STACK
>         select USER_STACKTRACE_SUPPORT
>         select VDSO_GETRANDOM
> +       select HAVE_RELIABLE_STACKTRACE
>         help
>           ARM 64-bit (AArch64) Linux support.
>
> @@ -2509,4 +2510,3 @@ endmenu # "CPU Power Management"
>  source "drivers/acpi/Kconfig"
>
>  source "arch/arm64/kvm/Kconfig"
> -
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 1d9d51d7627f..e227da842bc3 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -277,22 +277,28 @@ kunwind_next(struct kunwind_state *state)
>
>  typedef bool (*kunwind_consume_fn)(const struct kunwind_state *state, void *cookie);
>
> -static __always_inline void
> +static __always_inline int
>  do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
>            void *cookie)
>  {
> -       if (kunwind_recover_return_address(state))
> -               return;
> +       int ret;
> +
> +       ret = kunwind_recover_return_address(state);
> +       if (ret)
> +               return ret;
>
>         while (1) {
>                 int ret;
>
>                 if (!consume_state(state, cookie))
> -                       break;
> +                       return -EINVAL;
> +
>                 ret = kunwind_next(state);
> -               if (ret < 0)
> -                       break;
> +               if (ret)
> +                       return ret;
>         }
> +
> +       return -EINVAL;
>  }
>
>  /*
> @@ -324,7 +330,7 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
>                         : stackinfo_get_unknown();              \
>         })
>
> -static __always_inline void
> +static __always_inline int
>  kunwind_stack_walk(kunwind_consume_fn consume_state,
>                    void *cookie, struct task_struct *task,
>                    struct pt_regs *regs)
> @@ -352,7 +358,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
>
>         if (regs) {
>                 if (task != current)
> -                       return;
> +                       return -EINVAL;
>                 kunwind_init_from_regs(&state, regs);
>         } else if (task == current) {
>                 kunwind_init_from_caller(&state);
> @@ -360,7 +366,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
>                 kunwind_init_from_task(&state, task);
>         }
>
> -       do_kunwind(&state, consume_state, cookie);
> +       return do_kunwind(&state, consume_state, cookie);
>  }
>
>  struct kunwind_consume_entry_data {
> @@ -387,6 +393,25 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
>         kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
>  }
>
> +noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
> +                       void *cookie, struct task_struct *task)
> +{
> +       int ret;
> +       struct kunwind_consume_entry_data data = {
> +               .consume_entry = consume_entry,
> +               .cookie = cookie,
> +       };
> +
> +       ret = kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL);
> +       if (ret) {
> +               if (ret == -ENOENT)
> +                       return 0;
> +               return ret;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  struct bpf_unwind_consume_entry_data {
>         bool (*consume_entry)(void *cookie, u64 ip, u64 sp, u64 fp);
>         void *cookie;


From eahariha at linux.microsoft.com  Tue Mar 18 21:04:51 2025
From: eahariha at linux.microsoft.com (Easwar Hariharan)
Date: Tue, 18 Mar 2025 21:04:51 -0700
Subject: [PATCH v6 09/10] hyperv: Add definitions for root partition
 driver to hv headers
In-Reply-To: <1741980536-3865-10-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-10-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <d1da11e5-519c-4b8c-bff8-c266d984a950@linux.microsoft.com>

On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> A few additional definitions are required for the mshv driver code
> (to follow). Introduce those here and clean up a little bit while
> at it.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Reviewed-by: Tianyu Lan <tiala at microsoft.com>
> ---
>  include/hyperv/hvgdk_mini.h |  72 ++++++++++++++++++--
>  include/hyperv/hvhdk.h      | 132 ++++++++++++++++++++++++++++++++++--
>  include/hyperv/hvhdk_mini.h |  91 +++++++++++++++++++++++++
>  3 files changed, 284 insertions(+), 11 deletions(-)

Looks good to me.

Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>


From eahariha at linux.microsoft.com  Tue Mar 18 21:08:16 2025
From: eahariha at linux.microsoft.com (Easwar Hariharan)
Date: Tue, 18 Mar 2025 21:08:16 -0700
Subject: [PATCH v6 03/10] arm64/hyperv: Add some missing functions to
 arm64
In-Reply-To: <1741980536-3865-4-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-4-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <1a60c4f3-b93b-4bc2-9ded-07a1acd9d754@linux.microsoft.com>

On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> These non-nested msr and fast hypercall functions are present in x86,
> but they must be available in both architectures for the root partition
> driver code.
> 
> While at it, remove the redundant 'extern' keywords from the
> hv_do_hypercall() variants in asm-generic/mshyperv.h.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> Reviewed-by: Roman Kisel <romank at linux.microsoft.com>
> ---
>  arch/arm64/hyperv/hv_core.c       | 17 +++++++++++++++++
>  arch/arm64/include/asm/mshyperv.h | 13 +++++++++++++
>  include/asm-generic/mshyperv.h    |  6 ++++--
>  3 files changed, 34 insertions(+), 2 deletions(-)
> 

Looks good to me.

Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>


From anshuman.khandual at arm.com  Tue Mar 18 21:13:06 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Wed, 19 Mar 2025 09:43:06 +0530
Subject: [PATCH v4 3/8] bits: introduce fixed-type genmasks
In-Reply-To: <5cbaefa8-e51f-415f-a9b3-4841e69bb3fa@arm.com>
References: <20250305-fixed-type-genmasks-v4-0-1873dcdf6723@wanadoo.fr>
 <20250305-fixed-type-genmasks-v4-3-1873dcdf6723@wanadoo.fr>
 <Z8hsRJvpjYoqh9RG@thinkpad> <Z9oiEkQEcHhA0a80@thinkpad>
 <5cbaefa8-e51f-415f-a9b3-4841e69bb3fa@arm.com>
Message-ID: <1aba17f1-0cd2-429c-8338-28387ec16314@arm.com>



On 3/19/25 09:04, Anshuman Khandual wrote:
> On 3/19/25 07:16, Yury Norov wrote:
>> + Catalin Marinas, ARM maillist
>>
>> Hi Catalin and everyone,
> 
> Hello Yury,
> 
>>
>> Anshuman Khandual asked me to merge GENMASK_U128() saying it's
>> important for ARM to stabilize API. While it's a dead code, I
>> accepted his patch as he promised to add users shortly.
>>
>> Now it's more than half a year since that. There's no users,
>> and no feedback from Anshuman.
> 
> My apologies to have missed your email earlier. Please find response
> for the earlier email below as well.
> 
>>
>> Can you please tell if you still need the macro? I don't want to
>> undercut your development, but if you don't need 128-bit genmasks
>> there's no reason to have a dead code in the uapi.
> 
> The code base specifically using GENMASK_U128() has not been posted
> upstream (probably in next couple of months or so) till now, except
> the following patch which has been not been merged and still under
> review and development.
> 
> https://lore.kernel.org/lkml/20240801054436.612024-1-anshuman.khandual at arm.com/
> 
>>
>> Thanks,
>> Yury
>>
>> On Wed, Mar 05, 2025 at 10:22:47AM -0500, Yury Norov wrote:
>>> + Anshuman Khandual <anshuman.khandual at arm.com>
>>>
>>> Anshuman,
>>>
>>> I merged your GENMASK_U128() because you said it's important for your
>>> projects, and that it will get used in the kernel soon.
>>>
>>> Now it's in the kernel for more than 6 month, but no users were added.
>>> Can you clarify if you still need it, and if so why it's not used?
> 
> We would need it but although the code using GENMASK_U128() has not been
> posted upstream.
> 
>>>
>>> As you see, people add another fixed-types GENMASK() macros, and their
>>> implementation differ from GENMASK_U128().
> 
> I will take a look. Is GENMASK_U128() being problematic for the this new
> scheme ?
> 
>>>
>>> My second concern is that __GENMASK_U128() is declared in uapi, while
>>> the general understanding for other fixed-type genmasks is that they
>>> are not exported to users. Do you need this macro to be exported to
>>> userspace? Can you show how and where it is used there?
> 
> No, not atleast right now.
> 
> These were moved into uapi subsequently via the following commit.
> 
> 21a3a3d015aee ("tools headers: Synchronize {uapi/}linux/bits.h with the kernel sources")
> 
> But in general GENMASK_U128() is needed for generating 128 bit page table
> entries, related flags and masks whether in kernel or in user space for
> writing kernel test cases etc.

In the commit 947697c6f0f7 ("uapi: Define GENMASK_U128"), GENMASK_U128() gets defined
using __GENMASK_U128() which in turn calls __BIT128() - both of which are defined in
UAPI headers inside (include/uapi/linux/). 

Just wondering - are you suggesting to move these helpers from include/uapi/linux/ to
include/linux/bits.h instead ?

> 
>>>
>>> Thanks,
>>> Yury
>>>
>>>
>>> On Wed, Mar 05, 2025 at 10:00:15PM +0900, Vincent Mailhol via B4 Relay wrote:
>>>> From: Yury Norov <yury.norov at gmail.com>
>>>>
>>>> Add __GENMASK_t() which generalizes __GENMASK() to support different
>>>> types, and implement fixed-types versions of GENMASK() based on it.
>>>> The fixed-type version allows more strict checks to the min/max values
>>>> accepted, which is useful for defining registers like implemented by
>>>> i915 and xe drivers with their REG_GENMASK*() macros.
>>>>
>>>> The strict checks rely on shift-count-overflow compiler check to fail
>>>> the build if a number outside of the range allowed is passed.
>>>> Example:
>>>>
>>>> 	#define FOO_MASK GENMASK_U32(33, 4)
>>>>
>>>> will generate a warning like:
>>>>
>>>> 	../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
>>>> 	   41 |          (((t)~0ULL - ((t)(1) << (l)) + 1) & \
>>>> 	      |                               ^~
>>>>
>>>> Signed-off-by: Yury Norov <yury.norov at gmail.com>
>>>> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
>>>> Acked-by: Jani Nikula <jani.nikula at intel.com>
>>>> Signed-off-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
>>>> ---
>>>> Changelog:
>>>>
>>>>   v3 -> v4:
>>>>
>>>>     - The v3 is one year old. Meanwhile people started using
>>>>       __GENMASK() directly. So instead of generalizing __GENMASK() to
>>>>       support different types, add a new GENMASK_t().
>>>>
>>>>     - replace ~0ULL by ~_ULL(0). Otherwise, __GENMASK_t() would fail
>>>>       in asm code.
>>>>
>>>>     - Make GENMASK_U8() and GENMASK_U16() return an unsigned int. In
>>>>       v3, due to the integer promotion rules, these were returning a
>>>>       signed integer. By casting these to unsigned int, at least the
>>>>       signedness is kept.
>>>> ---
>>>>  include/linux/bitops.h |  1 -
>>>>  include/linux/bits.h   | 33 +++++++++++++++++++++++++++++----
>>>>  2 files changed, 29 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
>>>> index c1cb53cf2f0f8662ed3e324578f74330e63f935d..9be2d50da09a417966b3d11c84092bb2f4cd0bef 100644
>>>> --- a/include/linux/bitops.h
>>>> +++ b/include/linux/bitops.h
>>>> @@ -8,7 +8,6 @@
>>>>  
>>>>  #include <uapi/linux/kernel.h>
>>>>  
>>>> -#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
>>>>  #define BITS_TO_LONGS(nr)	__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
>>>>  #define BITS_TO_U64(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
>>>>  #define BITS_TO_U32(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
>>>> diff --git a/include/linux/bits.h b/include/linux/bits.h
>>>> index 5f68980a1b98d771426872c74d7b5c0f79e5e802..f202e46d2f4b7899c16d975120f3fa3ae41556ae 100644
>>>> --- a/include/linux/bits.h
>>>> +++ b/include/linux/bits.h
>>>> @@ -12,6 +12,7 @@
>>>>  #define BIT_ULL_MASK(nr)	(ULL(1) << ((nr) % BITS_PER_LONG_LONG))
>>>>  #define BIT_ULL_WORD(nr)	((nr) / BITS_PER_LONG_LONG)
>>>>  #define BITS_PER_BYTE		8
>>>> +#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
>>>>  
>>>>  /*
>>>>   * Create a contiguous bitmask starting at bit position @l and ending at
>>>> @@ -25,14 +26,38 @@
>>>>  
>>>>  #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h)))
>>>>  
>>>> -#define GENMASK(h, l) \
>>>> -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
>>>> -#define GENMASK_ULL(h, l) \
>>>> -	(GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
>>>> +/*
>>>> + * Generate a mask for the specified type @t. Additional checks are made to
>>>> + * guarantee the value returned fits in that type, relying on
>>>> + * shift-count-overflow compiler check to detect incompatible arguments.
>>>> + * For example, all these create build errors or warnings:
>>>> + *
>>>> + * - GENMASK(15, 20): wrong argument order
>>>> + * - GENMASK(72, 15): doesn't fit unsigned long
>>>> + * - GENMASK_U32(33, 15): doesn't fit in a u32
>>>> + */
>>>> +#define GENMASK_t(t, h, l)				\
>>>> +	(GENMASK_INPUT_CHECK(h, l) +			\
>>>> +	 (((t)~ULL(0) - ((t)1 << (l)) + 1) &		\
>>>> +	  ((t)~ULL(0) >> (BITS_PER_TYPE(t) - 1 - (h)))))
>>>> +
>>>> +#define GENMASK(h, l) GENMASK_t(unsigned long,  h, l)
>>>> +#define GENMASK_ULL(h, l) GENMASK_t(unsigned long long, h, l)
>>>>  
>>>>  /*
>>>>   * Missing asm support
>>>>   *
>>>> + * __GENMASK_U*() depends on BITS_PER_TYPE() which would not work in the asm
>>>> + * code as BITS_PER_TYPE() relies on sizeof(), something not available in
>>>> + * asm. Nethertheless, the concept of fixed width integers is a C thing which
>>>> + * does not apply to assembly code.
>>>> + */
>>>> +#define GENMASK_U8(h, l) ((unsigned int)GENMASK_t(u8,  h, l))
>>>> +#define GENMASK_U16(h, l) ((unsigned int)GENMASK_t(u16, h, l))
>>>> +#define GENMASK_U32(h, l) GENMASK_t(u32, h, l)
>>>> +#define GENMASK_U64(h, l) GENMASK_t(u64, h, l)
>>>> +
>>>> +/*
>>>>   * __GENMASK_U128() depends on _BIT128() which would not work
>>>>   * in the asm code, as it shifts an 'unsigned __int128' data
>>>>   * type instead of direct representation of 128 bit constants
>>>>
>>>> -- 
>>>> 2.45.3
>>>>
> 


From eahariha at linux.microsoft.com  Tue Mar 18 21:17:52 2025
From: eahariha at linux.microsoft.com (Easwar Hariharan)
Date: Tue, 18 Mar 2025 21:17:52 -0700
Subject: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
In-Reply-To: <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>
Message-ID: <06d2ad24-7554-4e7c-86f7-9e22828cb725@linux.microsoft.com>

On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> Introduce hv_status_printk() macros as a convenience to log hypercall
> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
> value and also as a string, which saves some time while debugging.
> 
> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
> use it for hv_result_to_string() and hv_result_to_errno().
> 
> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
> irqdomain.c hypercalls to aid debugging in the root partition.
> 
> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
> ---
>  arch/x86/hyperv/irqdomain.c    |   6 +-
>  drivers/hv/hv_common.c         | 129 ++++++++++++++++++++++++---------
>  drivers/hv/hv_proc.c           |  10 +--
>  drivers/iommu/hyperv-iommu.c   |   4 +-
>  include/asm-generic/mshyperv.h |  13 ++++
>  5 files changed, 118 insertions(+), 44 deletions(-)
> 

Looks good to me.

Reviewed-by: Easwar Hariharan <eahariha at linux.microsoft.com>


From wenst at chromium.org  Tue Mar 18 21:23:27 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 19 Mar 2025 12:23:27 +0800
Subject: [PATCH 1/2] platform/chrome: Add support for Google Spherion in
 HW prober
In-Reply-To: <20250318102259.189289-2-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com> <20250318102259.189289-2-laura.nao@collabora.com>
Message-ID: <CAGXv+5HZBS-L=BSPcy+QJAwJE--wB1AvG-xnxu+sf1FttYtV=g@mail.gmail.com>

On Tue, Mar 18, 2025 at 6:28?PM Laura Nao <laura.nao at collabora.com> wrote:
>
> Add a new compatible entry for "google,spherion" to the hardware prober
> platform list, using the same I2C component prober and trackpad data as
> "google,hana".
>
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: Chen-Yu Tsai <wenst at chromium.org>

> ---
>  drivers/platform/chrome/chromeos_of_hw_prober.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
> index c6992f5cdc76..019578bc7ad0 100644
> --- a/drivers/platform/chrome/chromeos_of_hw_prober.c
> +++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
> @@ -84,6 +84,10 @@ static const struct hw_prober_entry hw_prober_platforms[] = {
>                 .compatible = "google,hana",
>                 .prober = chromeos_i2c_component_prober,
>                 .data = &chromeos_i2c_probe_hana_trackpad,
> +       }, {
> +               .compatible = "google,spherion",
> +               .prober = chromeos_i2c_component_prober,
> +               .data = &chromeos_i2c_probe_hana_trackpad,
>         },
>  };
>
> --
> 2.39.5
>
>


From wenst at chromium.org  Tue Mar 18 21:23:55 2025
From: wenst at chromium.org (Chen-Yu Tsai)
Date: Wed, 19 Mar 2025 12:23:55 +0800
Subject: [PATCH 2/2] arm64: dts: mediatek: mt8192-asurada-spherion: Mark
 trackpads as fail-needs-probe
In-Reply-To: <20250318102259.189289-3-laura.nao@collabora.com>
References: <20250318102259.189289-1-laura.nao@collabora.com> <20250318102259.189289-3-laura.nao@collabora.com>
Message-ID: <CAGXv+5E-G0BY5q_EsxOkEEJvqXaX5=Y9PWqNbwysLEFfU-UmAg@mail.gmail.com>

On Tue, Mar 18, 2025 at 6:26?PM Laura Nao <laura.nao at collabora.com> wrote:
>
> Different Spherion variants use different trackpads on the same I2C2
> bus. Instead of enabling all of them by default, mark them as
> "fail-needs-probe" and let the implementation determine which one is
> actually present.
>
> Additionally, move the trackpad pinctrl entry back to the individual
> trackpad nodes.
>
> Signed-off-by: Laura Nao <laura.nao at collabora.com>

Reviewed-by: Chen-Yu Tsai <wenst at chromium.org>


From irogers at google.com  Tue Mar 18 22:07:27 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:27 -0700
Subject: [PATCH v7 00/14] perf: Support multiple system call tables in the build
Message-ID: <20250319050741.269828-1-irogers@google.com>

This work builds on the clean up of system call tables and removal of
libaudit by Charlie Jenkins <charlie at rivosinc.com>.

The system call table in perf trace is used to map system call numbers
to names and vice versa. Prior to these changes, a single table
matching the perf binary's build was present. The table would be
incorrect if tracing say a 32-bit binary from a 64-bit version of
perf, the names and numbers wouldn't match.

Change the build so that a single system call file is built and the
potentially multiple tables are identifiable from the ELF machine type
of the process being examined. To determine the ELF machine type, the
executable's maps are searched and the associated DSOs ELF headers are
read. When this fails and when live, /proc/pid/exe's ELF header is
read. Fallback to using the perf's binary type when unknown.

Remove some runtime types used by the system call tables and make
equivalents generated at build time.

v7: Rebase for dso data locking changes. Don't NULL check before
    btf__free (Arnaldo). Add patch to clean up perf trace's evlist to
    make leak sanitizer happier.

v6: Incorporate Namhyung's fixes:
    https://lore.kernel.org/lkml/Z9PCjQ8PhOadVGQ8 at google.com/
    https://lore.kernel.org/lkml/Z9YHCzINiu4uBQ8B at google.com/
    Which highlighted an issue with syscall pointers becoming
    stale. Add a patch 12 to make the syscall table a table of
    pointers that don't move so that struct syscalls don't move. Add a
    patch 13 fixing a BTF memory leak.

v5: Add byte swap to dso__e_machine and fix comment as suggested by
    Namhyung.

v4: Add reading the e_machine from the thread's maps dsos, only read
    from /proc/pid/exe on failure and when live as requested by
    Namhyung. Add patches to add dso comments and remove unused
    dso_data variables that are unused without libunwind.

v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
    Bergmann <arnd at arndb.de> on additional optional column and MIPS
    system call numbering. Rebase past Namhyung's global system call
    statistics and add comments that they don't yet support an
    e_machine other than EM_HOST.

v2: Change the 1 element cache for the last table as suggested by
    Howard Chu, add Howard's reviewed-by tags.
    Add a comment and apology to Charlie for not doing better in
    guiding:
    https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
    After discussion on v1 and he agreed this patch series would be
    the better direction.

Ian Rogers (14):
  perf dso: Move libunwind dso_data variables into ifdef
  perf dso: kernel-doc for enum dso_binary_type
  perf syscalltbl: Remove syscall_table.h
  perf trace: Reorganize syscalls
  perf syscalltbl: Remove struct syscalltbl
  perf dso: Add support for reading the e_machine type for a dso
  perf thread: Add support for reading the e_machine type for a thread
  perf trace beauty: Add syscalltbl.sh generating all system call tables
  perf syscalltbl: Use lookup table containing multiple architectures
  perf build: Remove Makefile.syscalls
  perf syscalltbl: Mask off ABI type for MIPS system calls
  perf trace: Make syscall table stable
  perf trace: Fix BTF memory leak
  perf trace: Fix evlist memory leak

 tools/perf/Makefile.perf                      |  10 +-
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/alpha/include/syscall_table.h |   2 -
 tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
 tools/perf/arch/arc/include/syscall_table.h   |   2 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
 tools/perf/arch/arm/include/syscall_table.h   |   2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
 tools/perf/arch/arm64/include/syscall_table.h |   8 -
 tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
 .../csky/entry/syscalls/Makefile.syscalls     |   3 -
 tools/perf/arch/csky/include/syscall_table.h  |   2 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
 .../entry/syscalls/Makefile.syscalls          |   3 -
 .../arch/loongarch/include/syscall_table.h    |   2 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
 .../mips/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/mips/include/syscall_table.h  |   2 -
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
 .../perf/arch/parisc/include/syscall_table.h  |   8 -
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
 .../perf/arch/powerpc/include/syscall_table.h |   8 -
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
 tools/perf/arch/riscv/include/syscall_table.h |   8 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
 .../s390/entry/syscalls/Makefile.syscalls     |   5 -
 tools/perf/arch/s390/include/syscall_table.h  |   2 -
 tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
 tools/perf/arch/sh/include/syscall_table.h    |   2 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
 tools/perf/arch/sparc/include/syscall_table.h |   8 -
 tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
 tools/perf/arch/x86/include/syscall_table.h   |   8 -
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
 .../perf/arch/xtensa/include/syscall_table.h  |   2 -
 tools/perf/builtin-trace.c                    | 339 ++++++++++++------
 tools/perf/scripts/Makefile.syscalls          |  61 ----
 tools/perf/scripts/syscalltbl.sh              |  86 -----
 tools/perf/trace/beauty/syscalltbl.sh         | 274 ++++++++++++++
 tools/perf/util/dso.c                         |  89 +++++
 tools/perf/util/dso.h                         |  62 ++++
 tools/perf/util/symbol-elf.c                  |  27 --
 tools/perf/util/syscalltbl.c                  | 148 ++++----
 tools/perf/util/syscalltbl.h                  |  22 +-
 tools/perf/util/thread.c                      |  80 +++++
 tools/perf/util/thread.h                      |  14 +-
 57 files changed, 839 insertions(+), 543 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:28 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:28 -0700
Subject: [PATCH v7 01/14] perf dso: Move libunwind dso_data variables into ifdef
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-2-irogers@google.com>

The variables elf_base_addr, debug_frame_offset, eh_frame_hdr_addr and
eh_frame_hdr_offset are only accessed in unwind-libunwind-local.c
which is conditionally built on having libunwind support. Make the
variables conditional on libunwind support too.

Reviewed-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 846b74510038..2cc1f6593f9e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -155,10 +155,12 @@ struct dso_data {
 	int		 status;
 	u32		 status_seen;
 	u64		 file_size;
+#ifdef HAVE_LIBUNWIND_SUPPORT
 	u64		 elf_base_addr;
 	u64		 debug_frame_offset;
 	u64		 eh_frame_hdr_addr;
 	u64		 eh_frame_hdr_offset;
+#endif
 };
 
 struct dso_bpf_prog {
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:29 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:29 -0700
Subject: [PATCH v7 02/14] perf dso: kernel-doc for enum dso_binary_type
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-3-irogers@google.com>

There are many and non-obvious meanings to the dso_binary_type enum
values. Add kernel-doc to speed interpretting their meanings.

Acked-by: Arnaldo Carvalho de Melo <acme at redhat.com>
Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.h | 57 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 2cc1f6593f9e..53e3b9b337e5 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -20,31 +20,88 @@ struct perf_env;
 #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
 #define DSO__NAME_KCORE		"[kernel.kcore]"
 
+/**
+ * enum dso_binary_type - The kind of DSO generally associated with a memory
+ *                        region (struct map).
+ */
 enum dso_binary_type {
+	/** @DSO_BINARY_TYPE__KALLSYMS: Symbols from /proc/kallsyms file. */
 	DSO_BINARY_TYPE__KALLSYMS = 0,
+	/** @DSO_BINARY_TYPE__GUEST_KALLSYMS: Guest /proc/kallsyms file. */
 	DSO_BINARY_TYPE__GUEST_KALLSYMS,
+	/** @DSO_BINARY_TYPE__VMLINUX: Path to kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__VMLINUX,
+	/** @DSO_BINARY_TYPE__GUEST_VMLINUX: Path to guest kernel /boot/vmlinux file. */
 	DSO_BINARY_TYPE__GUEST_VMLINUX,
+	/** @DSO_BINARY_TYPE__JAVA_JIT: Symbols from /tmp/perf.map file. */
 	DSO_BINARY_TYPE__JAVA_JIT,
+	/**
+	 * @DSO_BINARY_TYPE__DEBUGLINK: Debug file readable from the file path
+	 * in the .gnu_debuglink ELF section of the dso.
+	 */
 	DSO_BINARY_TYPE__DEBUGLINK,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE: File named after buildid located in
+	 * the buildid cache with an elf filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE,
+	/**
+	 * @DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: File named after buildid
+	 * located in the buildid cache with a debug filename.
+	 */
 	DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__FEDORA_DEBUGINFO: Debug file in /usr/lib/debug
+	 * with .debug suffix.
+	 */
 	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: Debug file in /usr/lib/debug. */
 	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: dso__long_name debuginfo
+	 * file in /usr/lib/debug/lib rather than the expected
+	 * /usr/lib/debug/usr/lib.
+	 */
 	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__BUILDID_DEBUGINFO: File named after buildid located
+	 * in /usr/lib/debug/.build-id/.
+	 */
 	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
+	/**
+	 * @DSO_BINARY_TYPE__GNU_DEBUGDATA: MiniDebuginfo where a compressed
+	 * ELF file is placed in a .gnu_debugdata section.
+	 */
 	DSO_BINARY_TYPE__GNU_DEBUGDATA,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_DSO: A regular executable/shared-object file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE: Guest kernel module .ko file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE,
+	/** @DSO_BINARY_TYPE__GUEST_KMODULE_COMP: Guest kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: Kernel module .ko file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+	/** @DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: Kernel module .ko.gz file. */
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
+	/** @DSO_BINARY_TYPE__KCORE: /proc/kcore file. */
 	DSO_BINARY_TYPE__KCORE,
+	/** @DSO_BINARY_TYPE__GUEST_KCORE: Guest /proc/kcore file. */
 	DSO_BINARY_TYPE__GUEST_KCORE,
+	/**
+	 * @DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: Openembedded/Yocto -dbg
+	 * package debug info.
+	 */
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	/** @DSO_BINARY_TYPE__BPF_PROG_INFO: jitted BPF code. */
 	DSO_BINARY_TYPE__BPF_PROG_INFO,
+	/** @DSO_BINARY_TYPE__BPF_IMAGE: jitted BPF trampoline or dispatcher code. */
 	DSO_BINARY_TYPE__BPF_IMAGE,
+	/**
+	 * @DSO_BINARY_TYPE__OOL: out of line code such as kprobe-replaced
+	 * instructions or optimized kprobes or ftrace trampolines.
+	 */
 	DSO_BINARY_TYPE__OOL,
+	/** @DSO_BINARY_TYPE__NOT_FOUND: Unknown DSO kind. */
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:30 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:30 -0700
Subject: [PATCH v7 03/14] perf syscalltbl: Remove syscall_table.h
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-4-irogers@google.com>

The definition of "static const char *const syscalltbl[] = {" is done
in a generated syscalls_32.h or syscalls_64.h that is architecture
dependent. In order to include the appropriate file a syscall_table.h
is found via the perf include path and it includes the syscalls_32.h
or syscalls_64.h as appropriate.

To support having multiple syscall tables, one for 32-bit and one for
64-bit, or for different architectures, an include path cannot be
used. Remove syscall_table.h because of this and inline what it does
into syscalltbl.c.

For architectures without a syscall_table.h this will cause a failure
to include either syscalls_32.h or syscalls_64.h rather than a failure
to include syscall_table.h. For architectures that only included one
or other, the behavior matches BITS_PER_LONG as previously done on
architectures supporting both syscalls_32.h and syscalls_64.h.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/arch/alpha/include/syscall_table.h     | 2 --
 tools/perf/arch/arc/include/syscall_table.h       | 2 --
 tools/perf/arch/arm/include/syscall_table.h       | 2 --
 tools/perf/arch/arm64/include/syscall_table.h     | 8 --------
 tools/perf/arch/csky/include/syscall_table.h      | 2 --
 tools/perf/arch/loongarch/include/syscall_table.h | 2 --
 tools/perf/arch/mips/include/syscall_table.h      | 2 --
 tools/perf/arch/parisc/include/syscall_table.h    | 8 --------
 tools/perf/arch/powerpc/include/syscall_table.h   | 8 --------
 tools/perf/arch/riscv/include/syscall_table.h     | 8 --------
 tools/perf/arch/s390/include/syscall_table.h      | 2 --
 tools/perf/arch/sh/include/syscall_table.h        | 2 --
 tools/perf/arch/sparc/include/syscall_table.h     | 8 --------
 tools/perf/arch/x86/include/syscall_table.h       | 8 --------
 tools/perf/arch/xtensa/include/syscall_table.h    | 2 --
 tools/perf/util/syscalltbl.c                      | 8 +++++++-
 16 files changed, 7 insertions(+), 67 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
 delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
 delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
 delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
 delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
 delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
 delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
 delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
 delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
 delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h

diff --git a/tools/perf/arch/alpha/include/syscall_table.h b/tools/perf/arch/alpha/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/alpha/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/arc/include/syscall_table.h b/tools/perf/arch/arc/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arc/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm/include/syscall_table.h b/tools/perf/arch/arm/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/arm/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/arm64/include/syscall_table.h b/tools/perf/arch/arm64/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/arm64/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/csky/include/syscall_table.h b/tools/perf/arch/csky/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/csky/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/loongarch/include/syscall_table.h b/tools/perf/arch/loongarch/include/syscall_table.h
deleted file mode 100644
index 9d0646d3455c..000000000000
--- a/tools/perf/arch/loongarch/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscall_table_64.h>
diff --git a/tools/perf/arch/mips/include/syscall_table.h b/tools/perf/arch/mips/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/mips/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/parisc/include/syscall_table.h b/tools/perf/arch/parisc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/parisc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/powerpc/include/syscall_table.h b/tools/perf/arch/powerpc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/powerpc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/riscv/include/syscall_table.h b/tools/perf/arch/riscv/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/riscv/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/s390/include/syscall_table.h b/tools/perf/arch/s390/include/syscall_table.h
deleted file mode 100644
index b53e31c15805..000000000000
--- a/tools/perf/arch/s390/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_64.h>
diff --git a/tools/perf/arch/sh/include/syscall_table.h b/tools/perf/arch/sh/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/sh/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/arch/sparc/include/syscall_table.h b/tools/perf/arch/sparc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/sparc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/x86/include/syscall_table.h b/tools/perf/arch/x86/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/x86/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/xtensa/include/syscall_table.h b/tools/perf/arch/xtensa/include/syscall_table.h
deleted file mode 100644
index 4c942821662d..000000000000
--- a/tools/perf/arch/xtensa/include/syscall_table.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/syscalls_32.h>
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 928aca4cd6e9..2f76241494c8 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -7,13 +7,19 @@
 
 #include "syscalltbl.h"
 #include <stdlib.h>
+#include <asm/bitsperlong.h>
 #include <linux/compiler.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
 #include "string2.h"
 
-#include <syscall_table.h>
+#if __BITS_PER_LONG == 64
+  #include <asm/syscalls_64.h>
+#else
+  #include <asm/syscalls_32.h>
+#endif
+
 const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
 static const char *const *syscalltbl_native = syscalltbl;
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:32 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:32 -0700
Subject: [PATCH v7 05/14] perf syscalltbl: Remove struct syscalltbl
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-6-irogers@google.com>

The syscalltbl held entries of system call name and number pairs,
generated from a native syscalltbl at start up. As there are gaps in
the system call number there is a notion of index into the
table. Going forward we want the system call table to be identifiable
by a machine type, for example, i386 vs x86-64. Change the interface
to the syscalltbl so (1) a (currently unused machine type of EM_HOST)
is passed (2) the index to syscall number and system call name mapping
is computed at build time.

Two tables are used for this, an array of system call number to name,
an array of system call numbers sorted by the system call name. The
sorted array doesn't store strings in part to save memory and
relocations. The index notion is carried forward and is an index into
the sorted array of system call numbers, the data structures are
opaque (held only in syscalltbl.c), and so the number of indices for a
machine type is exposed as a new API.

The arrays are computed in the syscalltbl.sh script and so no start-up
time computation and storage is necessary.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c       | 106 +++++++++++++++++------------
 tools/perf/scripts/syscalltbl.sh |  36 ++++------
 tools/perf/util/syscalltbl.c     | 113 ++++++++++---------------------
 tools/perf/util/syscalltbl.h     |  22 ++----
 4 files changed, 117 insertions(+), 160 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index bdfd3d5128b7..3017291242cf 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -149,7 +149,6 @@ enum summary_mode {
 
 struct trace {
 	struct perf_tool	tool;
-	struct syscalltbl	*sctbl;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
@@ -188,6 +187,14 @@ struct trace {
 		pid_t		*entries;
 		struct bpf_map  *map;
 	}			filter_pids;
+	/*
+	 * TODO: The map is from an ID (aka system call number) to struct
+	 * syscall_stats. If there is >1 e_machine, such as i386 and x86-64
+	 * processes, then the stats here will gather wrong the statistics for
+	 * the non EM_HOST system calls. A fix would be to add the e_machine
+	 * into the key, but this would make the code inconsistent with the
+	 * per-thread version.
+	 */
 	struct hashmap		*syscall_stats;
 	double			duration_filter;
 	double			runtime_ms;
@@ -2141,7 +2148,7 @@ static int syscall__read_info(struct syscall *sc, struct trace *trace)
 		return 0;
 	}
 
-	name = syscalltbl__name(trace->sctbl, sc->id);
+	name = syscalltbl__name(sc->e_machine, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2241,10 +2248,14 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 
 	strlist__for_each_entry(pos, trace->ev_qualifier) {
 		const char *sc = pos->s;
-		int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
+		/*
+		 * TODO: Assume more than the validation/warnings are all for
+		 * the same binary type as perf.
+		 */
+		int id = syscalltbl__id(EM_HOST, sc), match_next = -1;
 
 		if (id < 0) {
-			id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_first(EM_HOST, sc, &match_next);
 			if (id >= 0)
 				goto matches;
 
@@ -2264,7 +2275,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
 			continue;
 
 		while (1) {
-			id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
+			id = syscalltbl__strglobmatch_next(EM_HOST, sc, &match_next);
 			if (id < 0)
 				break;
 			if (nr_allocated == nr_used) {
@@ -2722,6 +2733,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -2796,6 +2808,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
@@ -2871,6 +2884,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
+	/* TODO: get e_machine from thread. */
 	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
@@ -3224,6 +3238,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+		/* TODO: get e_machine from thread. */
 		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
@@ -3731,9 +3746,9 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 	return trace->skel->progs.syscall_unaugmented;
 }
 
-static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
+static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 
 	if (sc == NULL)
 		return;
@@ -3742,22 +3757,22 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 	sc->bpf_prog.sys_exit  = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit  : NULL,  "exit");
 }
 
-static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
+static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int e_machine, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
-static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
+static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3854,8 +3869,8 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int id = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc.e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc.e_machine, i);
 		/* calling trace__syscall_info() may invalidate '_sc' */
 		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
 		struct bpf_program *pair_prog;
@@ -3941,7 +3956,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 }
 
-static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
 {
 	int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
 	int map_exit_fd  = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
@@ -3949,27 +3964,27 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	int err = 0;
 	unsigned int beauty_array[6];
 
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int prog_fd, key = syscalltbl__id_at_idx(trace->sctbl, i);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int prog_fd, key = syscalltbl__id_at_idx(e_machine, i);
 
 		if (!trace__syscall_enabled(trace, key))
 			continue;
 
-		trace__init_syscall_bpf_progs(trace, key);
+		trace__init_syscall_bpf_progs(trace, e_machine, key);
 
 		// It'll get at least the "!raw_syscalls:unaugmented"
-		prog_fd = trace__bpf_prog_sys_enter_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_enter_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
-		prog_fd = trace__bpf_prog_sys_exit_fd(trace, key);
+		prog_fd = trace__bpf_prog_sys_exit_fd(trace, e_machine, key);
 		err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
 		if (err)
 			break;
 
 		/* use beauty_map to tell BPF how many bytes to collect, set beauty_map's value here */
 		memset(beauty_array, 0, sizeof(beauty_array));
-		err = trace__bpf_sys_enter_beauty_map(trace, key, (unsigned int *)beauty_array);
+		err = trace__bpf_sys_enter_beauty_map(trace, e_machine, key, (unsigned int *)beauty_array);
 		if (err)
 			continue;
 		err = bpf_map_update_elem(beauty_map_fd, &key, beauty_array, BPF_ANY);
@@ -4005,9 +4020,9 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 * first and second arg (this one on the raw_syscalls:sys_exit prog
 	 * array tail call, then that one will be used.
 	 */
-	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
-		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+	for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
+		int key = syscalltbl__id_at_idx(e_machine, i);
+		struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -4032,7 +4047,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 		 * Get syscall info again as find usable entry above might
 		 * modify the syscall table and shuffle it.
 		 */
-		sc = trace__syscall_info(trace, NULL, EM_HOST, key);
+		sc = trace__syscall_info(trace, NULL, e_machine, key);
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -4457,8 +4472,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 		goto out_error_mem;
 
 #ifdef HAVE_BPF_SKEL
-	if (trace->skel && trace->skel->progs.sys_enter)
-		trace__init_syscalls_bpf_prog_array_maps(trace);
+	if (trace->skel && trace->skel->progs.sys_enter) {
+		/*
+		 * TODO: Initialize for all host binary machine types, not just
+		 * those matching the perf binary.
+		 */
+		trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
+	}
 #endif
 
 	if (trace->ev_qualifier_ids.nr > 0) {
@@ -4483,7 +4503,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	 *  So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is
 	 *  not in use.
 	 */
-	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close"));
+	/* TODO: support for more than just perf binary machine type close. */
+	trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(EM_HOST, "close"));
 
 	err = trace__expand_filters(trace, &evsel);
 	if (err)
@@ -4796,7 +4817,7 @@ static struct syscall_entry *syscall__sort_stats(struct hashmap *syscall_stats)
 	return entry;
 }
 
-static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
+static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
 				  struct hashmap *syscall_stats)
 {
 	size_t printed = 0;
@@ -4827,7 +4848,7 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, e_machine, entry->syscall);
 			if (!sc)
 				continue;
 
@@ -4854,14 +4875,14 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 }
 
 static size_t thread__dump_stats(struct thread_trace *ttrace,
-				 struct trace *trace, FILE *fp)
+				 struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, ttrace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, ttrace->syscall_stats);
 }
 
-static size_t system__dump_stats(struct trace *trace, FILE *fp)
+static size_t system__dump_stats(struct trace *trace, int e_machine, FILE *fp)
 {
-	return syscall__dump_stats(trace, fp, trace->syscall_stats);
+	return syscall__dump_stats(trace, e_machine, fp, trace->syscall_stats);
 }
 
 static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
@@ -4887,7 +4908,8 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += thread__dump_stats(ttrace, trace, fp);
+	/* TODO: get e_machine from thread. */
+	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -4948,7 +4970,8 @@ static size_t trace__fprintf_total_summary(struct trace *trace, FILE *fp)
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	printed += system__dump_stats(trace, fp);
+	/* TODO: get all system e_machines. */
+	printed += system__dump_stats(trace, EM_HOST, fp);
 
 	return printed;
 }
@@ -5140,8 +5163,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
 			*sep = '\0';
 
 		list = 0;
-		if (syscalltbl__id(trace->sctbl, s) >= 0 ||
-		    syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
+		/* TODO: support for more than just perf binary machine type syscalls. */
+		if (syscalltbl__id(EM_HOST, s) >= 0 ||
+		    syscalltbl__strglobmatch_first(EM_HOST, s, &idx) >= 0) {
 			list = 1;
 			goto do_concat;
 		}
@@ -5294,7 +5318,6 @@ static void trace__exit(struct trace *trace)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-	syscalltbl__delete(trace->sctbl);
 	zfree(&trace->perfconfig_events);
 }
 
@@ -5443,9 +5466,8 @@ int cmd_trace(int argc, const char **argv)
 	sigaction(SIGCHLD, &sigchld_act, NULL);
 
 	trace.evlist = evlist__new();
-	trace.sctbl = syscalltbl__new();
 
-	if (trace.evlist == NULL || trace.sctbl == NULL) {
+	if (trace.evlist == NULL) {
 		pr_err("Not enough memory to run!\n");
 		err = -ENOMEM;
 		goto out;
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
index 1ce0d5aa8b50..a39b3013b103 100755
--- a/tools/perf/scripts/syscalltbl.sh
+++ b/tools/perf/scripts/syscalltbl.sh
@@ -50,37 +50,27 @@ fi
 infile="$1"
 outfile="$2"
 
-nxt=0
-
-syscall_macro() {
-    nr="$1"
-    name="$2"
-
-    echo "	[$nr] = \"$name\","
-}
-
-emit() {
-    nr="$1"
-    entry="$2"
-
-    syscall_macro "$nr" "$entry"
-}
-
-echo "static const char *const syscalltbl[] = {" > $outfile
-
 sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
 grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
 
-max_nr=0
+echo "static const char *const syscall_num_to_name[] = {" > $outfile
 # the params are: nr abi name entry compat
 # use _ for intentionally unused variables according to SC2034
 while read nr _ name _ _; do
-    emit "$nr" "$name" >> $outfile
-    max_nr=$nr
+	echo "	[$nr] = \"$name\"," >> $outfile
 done < $sorted_table
+echo "};" >> $outfile
 
-rm -f $sorted_table
+echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
 
+# When sorting by name, add a suffix of 0s upto 20 characters so that system
+# calls that differ with a numerical suffix don't sort before those
+# without. This default behavior of sort differs from that of strcmp used at
+# runtime. Use sed to strip the trailing 0s suffix afterwards.
+grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
+while read name nr; do
+	echo "	$nr,	/* $name */" >> $outfile
+done < $sorted_table
 echo "};" >> $outfile
 
-echo "#define SYSCALLTBL_MAX_ID ${max_nr}" >> $outfile
+rm -f $sorted_table
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 2f76241494c8..760ac4d0869f 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <asm/bitsperlong.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/zalloc.h>
 
 #include <string.h>
@@ -20,112 +21,66 @@
   #include <asm/syscalls_32.h>
 #endif
 
-const int syscalltbl_native_max_id = SYSCALLTBL_MAX_ID;
-static const char *const *syscalltbl_native = syscalltbl;
+const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+{
+	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
+		return syscall_num_to_name[id];
+	return NULL;
+}
 
-struct syscall {
-	int id;
+struct syscall_cmp_key {
 	const char *name;
+	const char *const *tbl;
 };
 
 static int syscallcmpname(const void *vkey, const void *ventry)
 {
-	const char *key = vkey;
-	const struct syscall *entry = ventry;
+	const struct syscall_cmp_key *key = vkey;
+	const uint16_t *entry = ventry;
 
-	return strcmp(key, entry->name);
+	return strcmp(key->name, key->tbl[*entry]);
 }
 
-static int syscallcmp(const void *va, const void *vb)
+int syscalltbl__id(int e_machine __maybe_unused, const char *name)
 {
-	const struct syscall *a = va, *b = vb;
-
-	return strcmp(a->name, b->name);
+	struct syscall_cmp_key key = {
+		.name = name,
+		.tbl = syscall_num_to_name,
+	};
+	const int *id = bsearch(&key, syscall_sorted_names,
+				ARRAY_SIZE(syscall_sorted_names),
+				sizeof(syscall_sorted_names[0]),
+				syscallcmpname);
+
+	return id ? *id : -1;
 }
 
-static int syscalltbl__init_native(struct syscalltbl *tbl)
+int syscalltbl__num_idx(int e_machine __maybe_unused)
 {
-	int nr_entries = 0, i, j;
-	struct syscall *entries;
-
-	for (i = 0; i <= syscalltbl_native_max_id; ++i)
-		if (syscalltbl_native[i])
-			++nr_entries;
-
-	entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
-	if (tbl->syscalls.entries == NULL)
-		return -1;
-
-	for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
-		if (syscalltbl_native[i]) {
-			entries[j].name = syscalltbl_native[i];
-			entries[j].id = i;
-			++j;
-		}
-	}
-
-	qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
-	tbl->syscalls.nr_entries = nr_entries;
-	tbl->syscalls.max_id	 = syscalltbl_native_max_id;
-	return 0;
+	return ARRAY_SIZE(syscall_sorted_names);
 }
 
-struct syscalltbl *syscalltbl__new(void)
+int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
 {
-	struct syscalltbl *tbl = malloc(sizeof(*tbl));
-	if (tbl) {
-		if (syscalltbl__init_native(tbl)) {
-			free(tbl);
-			return NULL;
-		}
-	}
-	return tbl;
-}
-
-void syscalltbl__delete(struct syscalltbl *tbl)
-{
-	zfree(&tbl->syscalls.entries);
-	free(tbl);
-}
-
-const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
-{
-	return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
-}
-
-int syscalltbl__id(struct syscalltbl *tbl, const char *name)
-{
-	struct syscall *sc = bsearch(name, tbl->syscalls.entries,
-				     tbl->syscalls.nr_entries, sizeof(*sc),
-				     syscallcmpname);
-
-	return sc ? sc->id : -1;
-}
-
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx)
-{
-	struct syscall *syscalls = tbl->syscalls.entries;
-
-	return idx < tbl->syscalls.nr_entries ? syscalls[idx].id : -1;
+	return syscall_sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
 {
-	int i;
-	struct syscall *syscalls = tbl->syscalls.entries;
+	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
+		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
 
-	for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
-		if (strglobmatch(syscalls[i].name, syscall_glob)) {
+		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscalls[i].id;
+			return syscall_sorted_names[i];
 		}
 	}
 
 	return -1;
 }
 
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx)
 {
 	*idx = -1;
-	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
+	return syscalltbl__strglobmatch_next(e_machine, syscall_glob, idx);
 }
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index 362411a6d849..2bb628eff367 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -2,22 +2,12 @@
 #ifndef __PERF_SYSCALLTBL_H
 #define __PERF_SYSCALLTBL_H
 
-struct syscalltbl {
-	struct {
-		int max_id;
-		int nr_entries;
-		void *entries;
-	} syscalls;
-};
+const char *syscalltbl__name(int e_machine, int id);
+int syscalltbl__id(int e_machine, const char *name);
+int syscalltbl__num_idx(int e_machine);
+int syscalltbl__id_at_idx(int e_machine, int idx);
 
-struct syscalltbl *syscalltbl__new(void);
-void syscalltbl__delete(struct syscalltbl *tbl);
-
-const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
-int syscalltbl__id(struct syscalltbl *tbl, const char *name);
-int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx);
-
-int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
-int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_first(int e_machine, const char *syscall_glob, int *idx);
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx);
 
 #endif /* __PERF_SYSCALLTBL_H */
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:31 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:31 -0700
Subject: [PATCH v7 04/14] perf trace: Reorganize syscalls
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-5-irogers@google.com>

Identify struct syscall information in the syscalls table by a machine
type and syscall number, not just system call number. Having the
machine type means that 32-bit system calls can be differentiated from
64-bit ones on a machine capable of both. Having a table for all
machine types and all system call numbers would be too large, so
maintain a sorted array of system calls as they are encountered.

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/builtin-trace.c | 197 +++++++++++++++++++++++++------------
 1 file changed, 132 insertions(+), 65 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 092c5f6404ba..bdfd3d5128b7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -66,6 +66,7 @@
 #include "syscalltbl.h"
 #include "../perf.h"
 #include "trace_augment.h"
+#include "dwarf-regs.h"
 
 #include <errno.h>
 #include <inttypes.h>
@@ -86,6 +87,7 @@
 
 #include <linux/ctype.h>
 #include <perf/mmap.h>
+#include <tools/libc_compat.h>
 
 #ifdef HAVE_LIBTRACEEVENT
 #include <event-parse.h>
@@ -149,7 +151,10 @@ struct trace {
 	struct perf_tool	tool;
 	struct syscalltbl	*sctbl;
 	struct {
+		/** Sorted sycall numbers used by the trace. */
 		struct syscall  *table;
+		/** Size of table. */
+		size_t		table_size;
 		struct {
 			struct evsel *sys_enter,
 				*sys_exit,
@@ -1454,22 +1459,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
 	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
 }
 
-/*
- * is_exit: is this "exit" or "exit_group"?
- * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
- * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
- * nonexistent: Just a hole in the syscall table, syscall id not allocated
+/**
+ * struct syscall
  */
 struct syscall {
+	/** @e_machine: The ELF machine associated with the entry. */
+	int e_machine;
+	/** @id: id value from the tracepoint, the system call number. */
+	int id;
 	struct tep_event    *tp_format;
 	int		    nr_args;
+	/**
+	 * @args_size: sum of the sizes of the syscall arguments, anything
+	 * after that is augmented stuff: pathname for openat, etc.
+	 */
+
 	int		    args_size;
 	struct {
 		struct bpf_program *sys_enter,
 				   *sys_exit;
 	}		    bpf_prog;
+	/** @is_exit: is this "exit" or "exit_group"? */
 	bool		    is_exit;
+	/**
+	 * @is_open: is this "open" or "openat"? To associate the fd returned in
+	 * sys_exit with the pathname in sys_enter.
+	 */
 	bool		    is_open;
+	/**
+	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
+	 * syscall id not allocated.
+	 */
 	bool		    nonexistent;
 	bool		    use_btf;
 	struct tep_format_field *args;
@@ -2107,22 +2127,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
 	return 0;
 }
 
-static int trace__read_syscall_info(struct trace *trace, int id)
+static int syscall__read_info(struct syscall *sc, struct trace *trace)
 {
 	char tp_name[128];
-	struct syscall *sc;
-	const char *name = syscalltbl__name(trace->sctbl, id);
+	const char *name;
 	int err;
 
-	if (trace->syscalls.table == NULL) {
-		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
-		if (trace->syscalls.table == NULL)
-			return -ENOMEM;
-	}
-	sc = trace->syscalls.table + id;
 	if (sc->nonexistent)
 		return -EEXIST;
 
+	if (sc->name) {
+		/* Info already read. */
+		return 0;
+	}
+
+	name = syscalltbl__name(trace->sctbl, sc->id);
 	if (name == NULL) {
 		sc->nonexistent = true;
 		return -EEXIST;
@@ -2145,15 +2164,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 	 */
 	if (IS_ERR(sc->tp_format)) {
 		sc->nonexistent = true;
-		return PTR_ERR(sc->tp_format);
+		err = PTR_ERR(sc->tp_format);
+		sc->tp_format = NULL;
+		return err;
 	}
 
 	/*
 	 * The tracepoint format contains __syscall_nr field, so it's one more
 	 * than the actual number of syscall arguments.
 	 */
-	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
-					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
+	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
 		return -ENOMEM;
 
 	sc->args = sc->tp_format->format.fields;
@@ -2442,13 +2462,69 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
+static void syscall__init(struct syscall *sc, int e_machine, int id)
+{
+	memset(sc, 0, sizeof(*sc));
+	sc->e_machine = e_machine;
+	sc->id = id;
+}
+
+static void syscall__exit(struct syscall *sc)
+{
+	if (!sc)
+		return;
+
+	zfree(&sc->arg_fmt);
+}
+
+static int syscall__cmp(const void *va, const void *vb)
+{
+	const struct syscall *a = va, *b = vb;
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
+}
+
+static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
+{
+	struct syscall key = {
+		.e_machine = e_machine,
+		.id = id,
+	};
+	struct syscall *sc, *tmp;
+
+	if (trace->syscalls.table) {
+		sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+			     sizeof(struct syscall), syscall__cmp);
+		if (sc)
+			return sc;
+	}
+
+	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
+			   sizeof(struct syscall));
+	if (!tmp)
+		return NULL;
+
+	trace->syscalls.table = tmp;
+	sc = &trace->syscalls.table[trace->syscalls.table_size++];
+	syscall__init(sc, e_machine, id);
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	      syscall__cmp);
+	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
+		     sizeof(struct syscall), syscall__cmp);
+	return sc;
+}
+
 typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
 				  union perf_event *event,
 				  struct perf_sample *sample);
 
-static struct syscall *trace__syscall_info(struct trace *trace,
-					   struct evsel *evsel, int id)
+static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
+					   int e_machine, int id)
 {
+	struct syscall *sc;
 	int err = 0;
 
 	if (id < 0) {
@@ -2473,28 +2549,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
 
 	err = -EINVAL;
 
-	if (id > trace->sctbl->syscalls.max_id) {
-		goto out_cant_read;
-	}
-
-	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
-	    (err = trace__read_syscall_info(trace, id)) != 0)
-		goto out_cant_read;
-
-	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
-		goto out_cant_read;
+	sc = trace__find_syscall(trace, e_machine, id);
+	if (sc)
+		err = syscall__read_info(sc, trace);
 
-	return &trace->syscalls.table[id];
-
-out_cant_read:
-	if (verbose > 0) {
+	if (err && verbose > 0) {
 		char sbuf[STRERR_BUFSIZE];
-		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
-		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
-			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
+
+		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
+			str_error_r(-err, sbuf, sizeof(sbuf)));
+		if (sc && sc->name)
+			fprintf(trace->output, "(%s)", sc->name);
 		fputs(" information\n", trace->output);
 	}
-	return NULL;
+	return err ? NULL : sc;
 }
 
 struct syscall_stats {
@@ -2643,14 +2711,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
 	return NULL;
 }
 
-static void syscall__exit(struct syscall *sc)
-{
-	if (!sc)
-		return;
-
-	zfree(&sc->arg_fmt);
-}
-
 static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 			    union perf_event *event __maybe_unused,
 			    struct perf_sample *sample)
@@ -2662,7 +2722,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	int augmented_args_size = 0;
 	void *augmented_args = NULL;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -2736,7 +2796,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	char msg[1024];
 	void *args, *augmented_args = NULL;
 	int augmented_args_size;
@@ -2811,7 +2871,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
 	int alignment = trace->args_alignment;
-	struct syscall *sc = trace__syscall_info(trace, evsel, id);
+	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -3164,7 +3224,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		struct syscall *sc = trace__syscall_info(trace, evsel, id);
+		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -3673,7 +3733,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
 
 static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 
 	if (sc == NULL)
 		return;
@@ -3684,20 +3744,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
 
 static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
 {
-	struct syscall *sc = trace__syscall_info(trace, NULL, id);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
 	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
 }
 
 static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
 {
 	struct tep_format_field *field;
-	struct syscall *sc = trace__syscall_info(trace, NULL, key);
+	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 	const struct btf_type *bt;
 	char *struct_offset, *tmp, name[32];
 	bool can_augment = false;
@@ -3779,13 +3839,14 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigne
 	return -1;
 }
 
-static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *_sc)
 {
+	struct syscall sc = *_sc; /* Copy as trace__syscall_info may invalidate pointer. */
 	struct tep_format_field *field, *candidate_field;
 	/*
 	 * We're only interested in syscalls that have a pointer:
 	 */
-	for (field = sc->args; field; field = field->next) {
+	for (field = sc.args; field; field = field->next) {
 		if (field->flags & TEP_FIELD_IS_POINTER)
 			goto try_to_find_pair;
 	}
@@ -3795,15 +3856,16 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 try_to_find_pair:
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int id = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *pair = trace__syscall_info(trace, NULL, id);
+		/* calling trace__syscall_info() may invalidate '_sc' */
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
-		if (pair == NULL || pair == sc ||
+		if (pair == NULL || pair->id == sc.id ||
 		    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
 			continue;
 
-		for (field = sc->args, candidate_field = pair->args;
+		for (field = sc.args, candidate_field = pair->args;
 		     field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
 			bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
 			     candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3870,7 +3932,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 				goto next_candidate;
 		}
 
-		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name);
+		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc.name);
 		return pair_prog;
 	next_candidate:
 		continue;
@@ -3945,7 +4007,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 	 */
 	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
 		int key = syscalltbl__id_at_idx(trace->sctbl, i);
-		struct syscall *sc = trace__syscall_info(trace, NULL, key);
+		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		struct bpf_program *pair_prog;
 		int prog_fd;
 
@@ -3966,7 +4028,11 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
 		pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
 		if (pair_prog == NULL)
 			continue;
-
+		/*
+		 * Get syscall info again as find usable entry above might
+		 * modify the syscall table and shuffle it.
+		 */
+		sc = trace__syscall_info(trace, NULL, EM_HOST, key);
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -4761,7 +4827,10 @@ static size_t syscall__dump_stats(struct trace *trace, FILE *fp,
 			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
 			avg /= NSEC_PER_MSEC;
 
-			sc = &trace->syscalls.table[entry->syscall];
+			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST, entry->syscall);
+			if (!sc)
+				continue;
+
 			printed += fprintf(fp, "   %-15s", sc->name);
 			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
 					   n, stats->nr_failures, entry->msecs, min, avg);
@@ -5218,12 +5287,10 @@ static int trace__config(const char *var, const char *value, void *arg)
 
 static void trace__exit(struct trace *trace)
 {
-	int i;
-
 	strlist__delete(trace->ev_qualifier);
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
-		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
+		for (size_t i = 0; i < trace->syscalls.table_size; i++)
 			syscall__exit(&trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:33 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:33 -0700
Subject: [PATCH v7 06/14] perf dso: Add support for reading the e_machine type
 for a dso
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-7-irogers@google.com>

For ELF file dsos read the e_machine from the ELF header. For kernel
types assume the e_machine matches the perf tool. In other cases
return EM_NONE.

When reading from the ELF header use DSO__SWAP that may need
dso->needs_swap initializing. Factor out dso__swap_init to allow this.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/dso.c        | 89 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/dso.h        |  3 ++
 tools/perf/util/symbol-elf.c | 27 -----------
 3 files changed, 92 insertions(+), 27 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e0111049f6b0..8619b6eea62d 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1194,6 +1194,68 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 	return data_read_write_offset(dso, machine, offset, data, size, true);
 }
 
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
+{
+	uint16_t e_machine = EM_NONE;
+	int fd;
+
+	switch (dso__binary_type(dso)) {
+	case DSO_BINARY_TYPE__KALLSYMS:
+	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
+	case DSO_BINARY_TYPE__VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_VMLINUX:
+	case DSO_BINARY_TYPE__GUEST_KMODULE:
+	case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
+	case DSO_BINARY_TYPE__KCORE:
+	case DSO_BINARY_TYPE__GUEST_KCORE:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
+	case DSO_BINARY_TYPE__BPF_IMAGE:
+	case DSO_BINARY_TYPE__OOL:
+	case DSO_BINARY_TYPE__JAVA_JIT:
+		return EM_HOST;
+	case DSO_BINARY_TYPE__DEBUGLINK:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
+	case DSO_BINARY_TYPE__GNU_DEBUGDATA:
+	case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
+	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+	case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
+	case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
+	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+		break;
+	case DSO_BINARY_TYPE__NOT_FOUND:
+	default:
+		return EM_NONE;
+	}
+
+	mutex_lock(dso__data_open_lock());
+
+	/*
+	 * dso__data(dso)->fd might be closed if other thread opened another
+	 * file (dso) due to open file limit (RLIMIT_NOFILE).
+	 */
+	try_to_open_dso(dso, machine);
+	fd = dso__data(dso)->fd;
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
+			unsigned char eidata;
+
+			if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
+				dso__swap_init(dso, eidata);
+		}
+		if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
+		    pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
+			e_machine = DSO__SWAP(dso, uint16_t, e_machine);
+	}
+	mutex_unlock(dso__data_open_lock());
+	return e_machine;
+}
+
 /**
  * dso__data_read_addr - Read data from dso address
  * @dso: dso object
@@ -1549,6 +1611,33 @@ void dso__put(struct dso *dso)
 		RC_CHK_PUT(dso);
 }
 
+int dso__swap_init(struct dso *dso, unsigned char eidata)
+{
+	static unsigned int const endian = 1;
+
+	dso__set_needs_swap(dso, DSO_SWAP__NO);
+
+	switch (eidata) {
+	case ELFDATA2LSB:
+		/* We are big endian, DSO is little endian. */
+		if (*(unsigned char const *)&endian != 1)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	case ELFDATA2MSB:
+		/* We are little endian, DSO is big endian. */
+		if (*(unsigned char const *)&endian != 0)
+			dso__set_needs_swap(dso, DSO_SWAP__YES);
+		break;
+
+	default:
+		pr_err("unrecognized DSO data encoding %d\n", eidata);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid)
 {
 	RC_CHK_ACCESS(dso)->bid = *bid;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 53e3b9b337e5..8c1e7cdbaefd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -737,6 +737,8 @@ bool dso__sorted_by_name(const struct dso *dso);
 void dso__set_sorted_by_name(struct dso *dso);
 void dso__sort_by_name(struct dso *dso);
 
+int dso__swap_init(struct dso *dso, unsigned char eidata);
+
 void dso__set_build_id(struct dso *dso, struct build_id *bid);
 bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
 void dso__read_running_kernel_build_id(struct dso *dso,
@@ -826,6 +828,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
 off_t dso__data_size(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 			      u64 offset, u8 *data, ssize_t size);
+uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
 			    struct machine *machine, u64 addr,
 			    u8 *data, ssize_t size);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 3fa92697c457..fbf6d0f73af9 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1174,33 +1174,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
 
 #endif
 
-static int dso__swap_init(struct dso *dso, unsigned char eidata)
-{
-	static unsigned int const endian = 1;
-
-	dso__set_needs_swap(dso, DSO_SWAP__NO);
-
-	switch (eidata) {
-	case ELFDATA2LSB:
-		/* We are big endian, DSO is little endian. */
-		if (*(unsigned char const *)&endian != 1)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	case ELFDATA2MSB:
-		/* We are little endian, DSO is big endian. */
-		if (*(unsigned char const *)&endian != 0)
-			dso__set_needs_swap(dso, DSO_SWAP__YES);
-		break;
-
-	default:
-		pr_err("unrecognized DSO data encoding %d\n", eidata);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 bool symsrc__possibly_runtime(struct symsrc *ss)
 {
 	return ss->dynsym || ss->opdsec;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:34 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:34 -0700
Subject: [PATCH v7 07/14] perf thread: Add support for reading the e_machine
 type for a thread
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-8-irogers@google.com>

First try to read the e_machine from the dsos associated with the
thread's maps. If live use the executable from /proc/pid/exe and read
the e_machine from the ELF header. On failure use EM_HOST. Change
builtin-trace syscall functions to pass e_machine from the thread
rather than EM_HOST, so that in later patches when syscalltbl can use
the e_machine the system calls are specific to the architecture.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 43 ++++++++++----------
 tools/perf/util/thread.c   | 80 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/thread.h   | 14 ++++++-
 3 files changed, 115 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 3017291242cf..1c080d95c1e2 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2731,16 +2731,16 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
 	int printed = 0;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	int augmented_args_size = 0;
+	int augmented_args_size = 0, e_machine;
 	void *augmented_args = NULL;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -2808,17 +2808,18 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
 	struct thread_trace *ttrace;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	struct syscall *sc;
 	char msg[1024];
 	void *args, *augmented_args = NULL;
-	int augmented_args_size;
+	int augmented_args_size, e_machine;
 	size_t printed = 0;
 
-	if (sc == NULL)
-		return -1;
 
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		return -1;
 	ttrace = thread__trace(thread, trace);
 	/*
 	 * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
@@ -2883,15 +2884,15 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
 	bool duration_calculated = false;
 	struct thread *thread;
 	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
-	int alignment = trace->args_alignment;
-	/* TODO: get e_machine from thread. */
-	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+	int alignment = trace->args_alignment, e_machine;
+	struct syscall *sc;
 	struct thread_trace *ttrace;
 
-	if (sc == NULL)
-		return -1;
-
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+	e_machine = thread__e_machine(thread, trace->host);
+	sc = trace__syscall_info(trace, evsel, e_machine, id);
+	if (sc == NULL)
+		goto out_put;
 	ttrace = thread__trace(thread, trace);
 	if (ttrace == NULL)
 		goto out_put;
@@ -3238,8 +3239,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
 
 	if (evsel == trace->syscalls.events.bpf_output) {
 		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
-		/* TODO: get e_machine from thread. */
-		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
+		int e_machine = thread ? thread__e_machine(thread, trace->host) : EM_HOST;
+		struct syscall *sc = trace__syscall_info(trace, evsel, e_machine, id);
 
 		if (sc) {
 			fprintf(trace->output, "%s(", sc->name);
@@ -4889,6 +4890,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 {
 	size_t printed = 0;
 	struct thread_trace *ttrace = thread__priv(thread);
+	int e_machine = thread__e_machine(thread, trace->host);
 	double ratio;
 
 	if (ttrace == NULL)
@@ -4908,8 +4910,7 @@ static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trac
 	else if (fputc('\n', fp) != EOF)
 		++printed;
 
-	/* TODO: get e_machine from thread. */
-	printed += thread__dump_stats(ttrace, trace, EM_HOST, fp);
+	printed += thread__dump_stats(ttrace, trace, e_machine, fp);
 
 	return printed;
 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0ffdd52d86d7..89585f53c1d5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <elf.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,6 +18,7 @@
 #include "symbol.h"
 #include "unwind.h"
 #include "callchain.h"
+#include "dwarf-regs.h"
 
 #include <api/fs/fs.h>
 
@@ -51,6 +54,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		thread__set_ppid(thread, -1);
 		thread__set_cpu(thread, -1);
 		thread__set_guest_cpu(thread, -1);
+		thread__set_e_machine(thread, EM_NONE);
 		thread__set_lbr_stitch_enable(thread, false);
 		INIT_LIST_HEAD(thread__namespaces_list(thread));
 		INIT_LIST_HEAD(thread__comm_list(thread));
@@ -423,6 +427,82 @@ void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
 	}
 }
 
+static uint16_t read_proc_e_machine_for_pid(pid_t pid)
+{
+	char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */];
+	int fd;
+	uint16_t e_machine = EM_NONE;
+
+	snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+	fd = open(path, O_RDONLY);
+	if (fd >= 0) {
+		_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
+		_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
+		if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine))
+			e_machine = EM_NONE;
+		close(fd);
+	}
+	return e_machine;
+}
+
+static int thread__e_machine_callback(struct map *map, void *machine)
+{
+	struct dso *dso = map__dso(map);
+
+	_Static_assert(0 == EM_NONE, "Unexpected EM_NONE");
+	if (!dso)
+		return EM_NONE;
+
+	return dso__e_machine(dso, machine);
+}
+
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine)
+{
+	pid_t tid, pid;
+	uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine;
+
+	if (e_machine != EM_NONE)
+		return e_machine;
+
+	tid = thread__tid(thread);
+	pid = thread__pid(thread);
+	if (pid != tid) {
+		struct thread *parent = machine__findnew_thread(machine, pid, pid);
+
+		if (parent) {
+			e_machine = thread__e_machine(parent, machine);
+			thread__set_e_machine(thread, e_machine);
+			return e_machine;
+		}
+		/* Something went wrong, fallback. */
+	}
+	/* Reading on the PID thread. First try to find from the maps. */
+	e_machine = maps__for_each_map(thread__maps(thread),
+				       thread__e_machine_callback,
+				       machine);
+	if (e_machine == EM_NONE) {
+		/* Maps failed, perhaps we're live with map events disabled. */
+		bool is_live = machine->machines == NULL;
+
+		if (!is_live) {
+			/* Check if the session has a data file. */
+			struct perf_session *session = container_of(machine->machines,
+								    struct perf_session,
+								    machines);
+
+			is_live = !!session->data;
+		}
+		/* Read from /proc/pid/exe if live. */
+		if (is_live)
+			e_machine = read_proc_e_machine_for_pid(pid);
+	}
+	if (e_machine != EM_NONE)
+		thread__set_e_machine(thread, e_machine);
+	else
+		e_machine = EM_HOST;
+	return e_machine;
+}
+
 struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
 {
 	if (thread__pid(thread) == thread__tid(thread))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 6cbf6eb2812e..cd574a896418 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -60,7 +60,11 @@ DECLARE_RC_STRUCT(thread) {
 	struct srccode_state	srccode_state;
 	bool			filter;
 	int			filter_entry_depth;
-
+	/**
+	 * @e_machine: The ELF EM_* associated with the thread. EM_NONE if not
+	 * computed.
+	 */
+	uint16_t		e_machine;
 	/* LBR call stack stitch */
 	bool			lbr_stitch_enable;
 	struct lbr_stitch	*lbr_stitch;
@@ -302,6 +306,14 @@ static inline void thread__set_filter_entry_depth(struct thread *thread, int dep
 	RC_CHK_ACCESS(thread)->filter_entry_depth = depth;
 }
 
+uint16_t thread__e_machine(struct thread *thread, struct machine *machine);
+
+static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine)
+{
+	RC_CHK_ACCESS(thread)->e_machine = e_machine;
+}
+
+
 static inline bool thread__lbr_stitch_enable(const struct thread *thread)
 {
 	return RC_CHK_ACCESS(thread)->lbr_stitch_enable;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:35 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:35 -0700
Subject: [PATCH v7 08/14] perf trace beauty: Add syscalltbl.sh generating all
 system call tables
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-9-irogers@google.com>

Rather than generating individual syscall header files generate a
single trace/beauty/generated/syscalltbl.c. In a syscalltbls array
have references to each architectures tables along with the
corresponding e_machine. When the 32-bit or 64-bit table is ambiguous,
match the perf binary's type. For ARM32 don't use the arm64 32-bit
table which is smaller. EM_NONE is present for is no machine matches.

Conditionally compile the tables, only having the appropriate 32 and
64-bit table. If ALL_SYSCALLTBL is defined all tables can be
compiled.

Add comment for noreturn column suggested by Arnd Bergmann:
https://lore.kernel.org/lkml/d47c35dd-9c52-48e7-a00d-135572f11fbb at app.fastmail.com/
and added in commit 9142be9e6443 ("x86/syscall: Mark exit[_group]
syscall handlers __noreturn").

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf              |   9 +
 tools/perf/trace/beauty/syscalltbl.sh | 274 ++++++++++++++++++++++++++
 2 files changed, 283 insertions(+)
 create mode 100755 tools/perf/trace/beauty/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d0b50ccc9d7b..f949ec72f3d2 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -559,6 +559,14 @@ beauty_ioctl_outdir := $(beauty_outdir)/ioctl
 # Create output directory if not already present
 $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
 
+syscall_array := $(beauty_outdir)/syscalltbl.c
+syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh
+syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \
+	$(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl)
+
+$(syscall_array): $(syscall_tbl) $(syscall_tbl_data)
+	$(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@
+
 fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c
 fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh
 
@@ -878,6 +886,7 @@ build-dir   = $(or $(__build-dir),.)
 
 prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders \
 	arm64-sysreg-defs \
+	$(syscall_array) \
 	$(fs_at_flags_array) \
 	$(clone_flags_array) \
 	$(drm_ioctl_array) \
diff --git a/tools/perf/trace/beauty/syscalltbl.sh b/tools/perf/trace/beauty/syscalltbl.sh
new file mode 100755
index 000000000000..1199618dc178
--- /dev/null
+++ b/tools/perf/trace/beauty/syscalltbl.sh
@@ -0,0 +1,274 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate all syscall tables.
+#
+# Each line of the syscall table should have the following format:
+#
+# NR ABI NAME [NATIVE] [COMPAT [noreturn]]
+#
+# NR       syscall number
+# ABI      ABI name
+# NAME     syscall name
+# NATIVE   native entry point (optional)
+# COMPAT   compat entry point (optional)
+# noreturn system call doesn't return (optional)
+set -e
+
+usage() {
+       cat >&2 <<EOF
+usage: $0 <TOOLS DIRECTORY> <OUTFILE>
+
+  <TOOLS DIRECTORY>    path to kernel tools directory
+  <OUTFILE>            output header file
+EOF
+       exit 1
+}
+
+if [ $# -ne 2 ]; then
+       usage
+fi
+tools_dir=$1
+outfile=$2
+
+build_tables() {
+	infile="$1"
+	outfile="$2"
+	abis=$(echo "($3)" | tr ',' '|')
+	e_machine="$4"
+
+	if [ ! -f "$infile" ]
+	then
+		echo "Missing file $infile"
+		exit 1
+	fi
+	sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > "$sorted_table"
+
+	echo "static const char *const syscall_num_to_name_${e_machine}[] = {" >> "$outfile"
+	# the params are: nr abi name entry compat
+	# use _ for intentionally unused variables according to SC2034
+	while read -r nr _ name _ _; do
+		echo "	[$nr] = \"$name\"," >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	echo "static const uint16_t syscall_sorted_names_${e_machine}[] = {" >> "$outfile"
+
+	# When sorting by name, add a suffix of 0s upto 20 characters so that
+	# system calls that differ with a numerical suffix don't sort before
+	# those without. This default behavior of sort differs from that of
+	# strcmp used at runtime. Use sed to strip the trailing 0s suffix
+	# afterwards.
+	grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > "$sorted_table"
+	while read -r name nr; do
+		echo "	$nr,	/* $name */" >> "$outfile"
+	done < "$sorted_table"
+	echo "};" >> "$outfile"
+
+	rm -f "$sorted_table"
+}
+
+rm -f "$outfile"
+cat >> "$outfile" <<EOF
+#include <elf.h>
+#include <stdint.h>
+#include <asm/bitsperlong.h>
+#include <linux/kernel.h>
+
+struct syscalltbl {
+       const char *const *num_to_name;
+       const uint16_t *sorted_names;
+       uint16_t e_machine;
+       uint16_t num_to_name_len;
+       uint16_t sorted_names_len;
+};
+
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_tables "$tools_dir/perf/arch/alpha/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_ALPHA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_tables "$tools_dir/perf/arch/arm/entry/syscalls/syscall.tbl" "$outfile" common,32,oabi EM_ARM
+build_tables "$tools_dir/perf/arch/arm64/entry/syscalls/syscall_64.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_AARCH64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,csky,time32,stat64,rlimit EM_CSKY
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_tables "$tools_dir/perf/arch/mips/entry/syscalls/syscall_n64.tbl" "$outfile" common,64,n64 EM_MIPS
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_PARISC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/parisc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_PARISC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,32,nospu EM_PPC
+build_tables "$tools_dir/perf/arch/powerpc/entry/syscalls/syscall.tbl" "$outfile" common,64,nospu EM_PPC64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32,riscv,memfd_secret EM_RISCV
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64,riscv,rlimit,memfd_secret EM_RISCV
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_tables "$tools_dir/perf/arch/s390/entry/syscalls/syscall.tbl" "$outfile" common,64,renameat,rlimit,memfd_secret EM_S390
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_tables "$tools_dir/perf/arch/sh/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SH
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_SPARC
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/perf/arch/sparc/entry/syscalls/syscall.tbl" "$outfile" common,64 EM_SPARC
+cat >> "$outfile" <<EOF
+#endif //__BITS_PER_LONG != 64
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_32.tbl" "$outfile" common,32,i386 EM_386
+build_tables "$tools_dir/perf/arch/x86/entry/syscalls/syscall_64.tbl" "$outfile" common,64 EM_X86_64
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_tables "$tools_dir/perf/arch/xtensa/entry/syscalls/syscall.tbl" "$outfile" common,32 EM_XTENSA
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+
+#if __BITS_PER_LONG != 64
+EOF
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,32 EM_NONE
+echo "#else" >> "$outfile"
+build_tables "$tools_dir/scripts/syscall.tbl" "$outfile" common,64 EM_NONE
+echo "#endif //__BITS_PER_LONG != 64" >> "$outfile"
+
+build_outer_table() {
+       e_machine=$1
+       outfile="$2"
+       cat >> "$outfile" <<EOF
+       {
+	      .num_to_name = syscall_num_to_name_$e_machine,
+	      .sorted_names = syscall_sorted_names_$e_machine,
+	      .e_machine = $e_machine,
+	      .num_to_name_len = ARRAY_SIZE(syscall_num_to_name_$e_machine),
+	      .sorted_names_len = ARRAY_SIZE(syscall_sorted_names_$e_machine),
+       },
+EOF
+}
+
+cat >> "$outfile" <<EOF
+static const struct syscalltbl syscalltbls[] = {
+#if defined(ALL_SYSCALLTBL) || defined(__alpha__)
+EOF
+build_outer_table EM_ALPHA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__alpha__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+EOF
+build_outer_table EM_ARM "$outfile"
+build_outer_table EM_AARCH64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__arm__) || defined(__aarch64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__csky__)
+EOF
+build_outer_table EM_CSKY "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__csky__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__mips__)
+EOF
+build_outer_table EM_MIPS "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__mips__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__hppa__)
+EOF
+build_outer_table EM_PARISC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__hppa__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+EOF
+build_outer_table EM_PPC "$outfile"
+build_outer_table EM_PPC64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__powerpc__) || defined(__powerpc64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__riscv)
+EOF
+build_outer_table EM_RISCV "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__riscv)
+
+#if defined(ALL_SYSCALLTBL) || defined(__s390x__)
+EOF
+build_outer_table EM_S390 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__s390x__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sh__)
+EOF
+build_outer_table EM_SH "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sh__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+EOF
+build_outer_table EM_SPARC "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__sparc64__) || defined(__sparc__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+EOF
+build_outer_table EM_386 "$outfile"
+build_outer_table EM_X86_64 "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__i386__) || defined(__x86_64__)
+
+#if defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_XTENSA "$outfile"
+cat >> "$outfile" <<EOF
+#endif // defined(ALL_SYSCALLTBL) || defined(__xtensa__)
+EOF
+build_outer_table EM_NONE "$outfile"
+cat >> "$outfile" <<EOF
+};
+EOF
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:37 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:37 -0700
Subject: [PATCH v7 10/14] perf build: Remove Makefile.syscalls
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-11-irogers@google.com>

Now a single beauty file is generated and used by all architectures,
remove the per-architecture Makefiles, Kbuild files and previous
generator script.

Note: there was conversation with Charlie Jenkins
<charlie at rivosinc.com> and they'd written an alternate approach to
support multiple architectures:
https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
It would have been better to have helped Charlie fix their series (my
apologies) but they agreed that the approach taken here was likely
best for longer term maintainability:
https://lore.kernel.org/lkml/Z6Jk_UN9i69QGqUj at ghost/

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/Makefile.perf                      |  1 -
 tools/perf/arch/alpha/entry/syscalls/Kbuild   |  2 -
 .../alpha/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/arc/entry/syscalls/Kbuild     |  2 -
 .../arch/arc/entry/syscalls/Makefile.syscalls |  3 -
 tools/perf/arch/arm/entry/syscalls/Kbuild     |  4 -
 .../arch/arm/entry/syscalls/Makefile.syscalls |  2 -
 tools/perf/arch/arm64/entry/syscalls/Kbuild   |  3 -
 .../arm64/entry/syscalls/Makefile.syscalls    |  6 --
 tools/perf/arch/csky/entry/syscalls/Kbuild    |  2 -
 .../csky/entry/syscalls/Makefile.syscalls     |  3 -
 .../perf/arch/loongarch/entry/syscalls/Kbuild |  2 -
 .../entry/syscalls/Makefile.syscalls          |  3 -
 tools/perf/arch/mips/entry/syscalls/Kbuild    |  2 -
 .../mips/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/parisc/entry/syscalls/Kbuild  |  3 -
 .../parisc/entry/syscalls/Makefile.syscalls   |  6 --
 tools/perf/arch/powerpc/entry/syscalls/Kbuild |  3 -
 .../powerpc/entry/syscalls/Makefile.syscalls  |  6 --
 tools/perf/arch/riscv/entry/syscalls/Kbuild   |  2 -
 .../riscv/entry/syscalls/Makefile.syscalls    |  4 -
 tools/perf/arch/s390/entry/syscalls/Kbuild    |  2 -
 .../s390/entry/syscalls/Makefile.syscalls     |  5 --
 tools/perf/arch/sh/entry/syscalls/Kbuild      |  2 -
 .../arch/sh/entry/syscalls/Makefile.syscalls  |  4 -
 tools/perf/arch/sparc/entry/syscalls/Kbuild   |  3 -
 .../sparc/entry/syscalls/Makefile.syscalls    |  5 --
 tools/perf/arch/x86/entry/syscalls/Kbuild     |  3 -
 .../arch/x86/entry/syscalls/Makefile.syscalls |  6 --
 tools/perf/arch/xtensa/entry/syscalls/Kbuild  |  2 -
 .../xtensa/entry/syscalls/Makefile.syscalls   |  4 -
 tools/perf/scripts/Makefile.syscalls          | 61 ---------------
 tools/perf/scripts/syscalltbl.sh              | 76 -------------------
 33 files changed, 242 deletions(-)
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
 delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
 delete mode 100644 tools/perf/scripts/Makefile.syscalls
 delete mode 100755 tools/perf/scripts/syscalltbl.sh

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index f949ec72f3d2..f3cd8de15d1a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -339,7 +339,6 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
 FEATURE_TESTS := all
 endif
 endif
-include $(srctree)/tools/perf/scripts/Makefile.syscalls
 include Makefile.config
 endif
 
diff --git a/tools/perf/arch/alpha/entry/syscalls/Kbuild b/tools/perf/arch/alpha/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls b/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 690168aac34d..000000000000
--- a/tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/alpha/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arc/entry/syscalls/Kbuild b/tools/perf/arch/arc/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 391d30ab7a83..000000000000
--- a/tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += arc time32 renameat stat64 rlimit
diff --git a/tools/perf/arch/arm/entry/syscalls/Kbuild b/tools/perf/arch/arm/entry/syscalls/Kbuild
deleted file mode 100644
index 9d777540f089..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += oabi
-syscalltbl = $(srctree)/tools/perf/arch/arm/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Kbuild b/tools/perf/arch/arm64/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls b/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e7e78c2d1c02..000000000000
--- a/tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/arm64/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/csky/entry/syscalls/Kbuild b/tools/perf/arch/csky/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls b/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ea2dd10d0571..000000000000
--- a/tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += csky time32 stat64 rlimit
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Kbuild b/tools/perf/arch/loongarch/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls b/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 47d32da2aed8..000000000000
--- a/tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 +=
diff --git a/tools/perf/arch/mips/entry/syscalls/Kbuild b/tools/perf/arch/mips/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls b/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9ee914bdfb05..000000000000
--- a/tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += n64
-
-syscalltbl = $(srctree)/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
diff --git a/tools/perf/arch/parisc/entry/syscalls/Kbuild b/tools/perf/arch/parisc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index ae326fecb83b..000000000000
--- a/tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-
-syscalltbl = $(srctree)/tools/perf/arch/parisc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Kbuild b/tools/perf/arch/powerpc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e35afbc57c79..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += nospu
-syscall_abis_64 += nospu
-
-syscalltbl = $(srctree)/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/riscv/entry/syscalls/Kbuild b/tools/perf/arch/riscv/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls b/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9668fd1faf60..000000000000
--- a/tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += riscv memfd_secret
-syscall_abis_64 += riscv rlimit memfd_secret
diff --git a/tools/perf/arch/s390/entry/syscalls/Kbuild b/tools/perf/arch/s390/entry/syscalls/Kbuild
deleted file mode 100644
index 9a41e3572c3a..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls b/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 9762d7abf17c..000000000000
--- a/tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_64 += renameat rlimit memfd_secret
-
-syscalltbl = $(srctree)/tools/perf/arch/s390/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sh/entry/syscalls/Kbuild b/tools/perf/arch/sh/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 25080390e4ed..000000000000
--- a/tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 +=
-syscalltbl = $(srctree)/tools/perf/arch/sh/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/sparc/entry/syscalls/Kbuild b/tools/perf/arch/sparc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index 212c1800b644..000000000000
--- a/tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscall_abis_64  +=
-syscalltbl = $(srctree)/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/x86/entry/syscalls/Kbuild b/tools/perf/arch/x86/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls b/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index db3d5d6d4e56..000000000000
--- a/tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += i386
-syscall_abis_64 +=
-
-syscalltbl = $(srctree)/tools/perf/arch/x86/entry/syscalls/syscall_%.tbl
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Kbuild b/tools/perf/arch/xtensa/entry/syscalls/Kbuild
deleted file mode 100644
index 11707c481a24..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
diff --git a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls b/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index d4aa2358460c..000000000000
--- a/tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32  +=
-syscalltbl = $(srctree)/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
diff --git a/tools/perf/scripts/Makefile.syscalls b/tools/perf/scripts/Makefile.syscalls
deleted file mode 100644
index 8bf55333262e..000000000000
--- a/tools/perf/scripts/Makefile.syscalls
+++ /dev/null
@@ -1,61 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# This Makefile generates headers in
-# tools/perf/arch/$(SRCARCH)/include/generated/asm from the architecture's
-# syscall table. This will either be from the generic syscall table, or from a
-# table that is specific to that architecture.
-
-PHONY := all
-all:
-
-obj := $(OUTPUT)arch/$(SRCARCH)/include/generated/asm
-
-syscall_abis_32  := common,32
-syscall_abis_64  := common,64
-syscalltbl := $(srctree)/tools/scripts/syscall.tbl
-
-# let architectures override $(syscall_abis_%) and $(syscalltbl)
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Makefile.syscalls
-include $(srctree)/tools/build/Build.include
--include $(srctree)/tools/perf/arch/$(SRCARCH)/entry/syscalls/Kbuild
-
-systbl := $(srctree)/tools/perf/scripts/syscalltbl.sh
-
-syscall-y   := $(addprefix $(obj)/, $(syscall-y))
-
-# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
-unwanted    := $(filter-out $(syscall-y),$(old-headers))
-
-quiet_cmd_remove = REMOVE  $(unwanted)
-      cmd_remove = rm -f $(unwanted)
-
-quiet_cmd_systbl = SYSTBL  $@
-      cmd_systbl = $(CONFIG_SHELL) $(systbl) \
-		   $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \
-		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
-		   $< $@
-
-all: $(syscall-y)
-	$(if $(unwanted),$(call cmd,remove))
-	@:
-
-$(obj)/syscalls_%.h: $(syscalltbl) $(systbl) FORCE
-	$(call if_changed,systbl)
-
-targets := $(syscall-y)
-
-# Create output directory. Skip it if at least one old header exists
-# since we know the output directory already exists.
-ifeq ($(old-headers),)
-$(shell mkdir -p $(obj))
-endif
-
-PHONY += FORCE
-
-FORCE:
-
-existing-targets := $(wildcard $(sort $(targets)))
-
--include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
-
-.PHONY: $(PHONY)
diff --git a/tools/perf/scripts/syscalltbl.sh b/tools/perf/scripts/syscalltbl.sh
deleted file mode 100755
index a39b3013b103..000000000000
--- a/tools/perf/scripts/syscalltbl.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Generate a syscall table header.
-#
-# Each line of the syscall table should have the following format:
-#
-# NR ABI NAME [NATIVE] [COMPAT]
-#
-# NR       syscall number
-# ABI      ABI name
-# NAME     syscall name
-# NATIVE   native entry point (optional)
-# COMPAT   compat entry point (optional)
-
-set -e
-
-usage() {
-	echo >&2 "usage: $0 [--abis ABIS] INFILE OUTFILE" >&2
-	echo >&2
-	echo >&2 "  INFILE    input syscall table"
-	echo >&2 "  OUTFILE   output header file"
-	echo >&2
-	echo >&2 "options:"
-	echo >&2 "  --abis ABIS        ABI(s) to handle (By default, all lines are handled)"
-	exit 1
-}
-
-# default unless specified by options
-abis=
-
-while [ $# -gt 0 ]
-do
-	case $1 in
-	--abis)
-		abis=$(echo "($2)" | tr ',' '|')
-		shift 2;;
-	-*)
-		echo "$1: unknown option" >&2
-		usage;;
-	*)
-		break;;
-	esac
-done
-
-if [ $# -ne 2 ]; then
-	usage
-fi
-
-infile="$1"
-outfile="$2"
-
-sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | sort -n > $sorted_table
-
-echo "static const char *const syscall_num_to_name[] = {" > $outfile
-# the params are: nr abi name entry compat
-# use _ for intentionally unused variables according to SC2034
-while read nr _ name _ _; do
-	echo "	[$nr] = \"$name\"," >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-echo "static const uint16_t syscall_sorted_names[] = {" >> $outfile
-
-# When sorting by name, add a suffix of 0s upto 20 characters so that system
-# calls that differ with a numerical suffix don't sort before those
-# without. This default behavior of sort differs from that of strcmp used at
-# runtime. Use sed to strip the trailing 0s suffix afterwards.
-grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | awk '{printf $3; for (i = length($3); i < 20; i++) { printf "0"; }; print " " $1}'| sort | sed 's/\([a-zA-Z1-9]\+\)0\+ \([0-9]\+\)/\1 \2/' > $sorted_table
-while read name nr; do
-	echo "	$nr,	/* $name */" >> $outfile
-done < $sorted_table
-echo "};" >> $outfile
-
-rm -f $sorted_table
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:38 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:38 -0700
Subject: [PATCH v7 11/14] perf syscalltbl: Mask off ABI type for MIPS system calls
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-12-irogers@google.com>

Arnd Bergmann described that MIPS system calls don't necessarily start
from 0 as an ABI prefix is applied:
https://lore.kernel.org/lkml/8ed7dfb2-1e4d-4aa4-a04b-0397a89365d1 at app.fastmail.com/
When decoding the "id" (aka system call number) for MIPS ignore values
greater-than 1000.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/util/syscalltbl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 4e6018e2e0b3..67a8ec10e9e4 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -46,6 +46,14 @@ const char *syscalltbl__name(int e_machine, int id)
 {
 	const struct syscalltbl *table = find_table(e_machine);
 
+	if (e_machine == EM_MIPS && id > 1000) {
+		/*
+		 * MIPS may encode the N32/64/O32 type in the high part of
+		 * syscall number. Mask this off if present. See the values of
+		 * __NR_N32_Linux, __NR_64_Linux, __NR_O32_Linux and __NR_Linux.
+		 */
+		id = id % 1000;
+	}
 	if (table && id >= 0 && id < table->num_to_name_len)
 		return table->num_to_name[id];
 	return NULL;
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:40 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:40 -0700
Subject: [PATCH v7 13/14] perf trace: Fix BTF memory leak
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-14-irogers@google.com>

Add missing btf__free in trace__exit.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a5f31472980b..1d4ad5d19b10 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -5339,6 +5339,10 @@ static void trace__exit(struct trace *trace)
 		zfree(&trace->syscalls.table);
 	}
 	zfree(&trace->perfconfig_events);
+#ifdef HAVE_LIBBPF_SUPPORT
+	btf__free(trace->btf);
+	trace->btf = NULL;
+#endif
 }
 
 #ifdef HAVE_BPF_SKEL
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:39 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:39 -0700
Subject: [PATCH v7 12/14] perf trace: Make syscall table stable
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-13-irogers@google.com>

Namhyung fixed the syscall table being reallocated and moving by
reloading the system call pointer after a move:
https://lore.kernel.org/lkml/Z9YHCzINiu4uBQ8B at google.com/
This could be brittle so this patch changes the syscall table to be an
array of pointers of "struct syscall" that don't move. Remove
unnecessary copies and searches with this change.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 87 +++++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1c080d95c1e2..a5f31472980b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -151,7 +151,7 @@ struct trace {
 	struct perf_tool	tool;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
-		struct syscall  *table;
+		struct syscall  **table;
 		/** Size of table. */
 		size_t		table_size;
 		struct {
@@ -2473,24 +2473,41 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
 	return printed;
 }
 
-static void syscall__init(struct syscall *sc, int e_machine, int id)
+static struct syscall *syscall__new(int e_machine, int id)
 {
-	memset(sc, 0, sizeof(*sc));
+	struct syscall *sc = zalloc(sizeof(*sc));
+
+	if (!sc)
+		return NULL;
+
 	sc->e_machine = e_machine;
 	sc->id = id;
+	return sc;
 }
 
-static void syscall__exit(struct syscall *sc)
+static void syscall__delete(struct syscall *sc)
 {
 	if (!sc)
 		return;
 
-	zfree(&sc->arg_fmt);
+	free(sc->arg_fmt);
+	free(sc);
+}
+
+static int syscall__bsearch_cmp(const void *key, const void *entry)
+{
+	const struct syscall *a = key, *b = *((const struct syscall **)entry);
+
+	if (a->e_machine != b->e_machine)
+		return a->e_machine - b->e_machine;
+
+	return a->id - b->id;
 }
 
 static int syscall__cmp(const void *va, const void *vb)
 {
-	const struct syscall *a = va, *b = vb;
+	const struct syscall *a = *((const struct syscall **)va);
+	const struct syscall *b = *((const struct syscall **)vb);
 
 	if (a->e_machine != b->e_machine)
 		return a->e_machine - b->e_machine;
@@ -2504,27 +2521,33 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
 		.e_machine = e_machine,
 		.id = id,
 	};
-	struct syscall *sc, *tmp;
+	struct syscall *sc, **tmp;
 
 	if (trace->syscalls.table) {
-		sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
-			     sizeof(struct syscall), syscall__cmp);
-		if (sc)
-			return sc;
+		struct syscall **sc_entry = bsearch(&key, trace->syscalls.table,
+						    trace->syscalls.table_size,
+						    sizeof(trace->syscalls.table[0]),
+						    syscall__bsearch_cmp);
+
+		if (sc_entry)
+			return *sc_entry;
 	}
 
+	sc = syscall__new(e_machine, id);
+	if (!sc)
+		return NULL;
+
 	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
-			   sizeof(struct syscall));
-	if (!tmp)
+			   sizeof(trace->syscalls.table[0]));
+	if (!tmp) {
+		syscall__delete(sc);
 		return NULL;
+	}
 
 	trace->syscalls.table = tmp;
-	sc = &trace->syscalls.table[trace->syscalls.table_size++];
-	syscall__init(sc, e_machine, id);
-	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+	trace->syscalls.table[trace->syscalls.table_size++] = sc;
+	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(trace->syscalls.table[0]),
 	      syscall__cmp);
-	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
-		     sizeof(struct syscall), syscall__cmp);
 	return sc;
 }
 
@@ -3855,14 +3878,14 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, i
 	return -1;
 }
 
-static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *_sc)
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace,
+							     struct syscall *sc)
 {
-	struct syscall sc = *_sc; /* Copy as trace__syscall_info may invalidate pointer. */
 	struct tep_format_field *field, *candidate_field;
 	/*
 	 * We're only interested in syscalls that have a pointer:
 	 */
-	for (field = sc.args; field; field = field->next) {
+	for (field = sc->args; field; field = field->next) {
 		if (field->flags & TEP_FIELD_IS_POINTER)
 			goto try_to_find_pair;
 	}
@@ -3870,18 +3893,17 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 	return NULL;
 
 try_to_find_pair:
-	for (int i = 0, num_idx = syscalltbl__num_idx(sc.e_machine); i < num_idx; ++i) {
-		int id = syscalltbl__id_at_idx(sc.e_machine, i);
-		/* calling trace__syscall_info() may invalidate '_sc' */
-		struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
+	for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
+		int id = syscalltbl__id_at_idx(sc->e_machine, i);
+		struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
 		struct bpf_program *pair_prog;
 		bool is_candidate = false;
 
-		if (pair == NULL || pair->id == sc.id ||
+		if (pair == NULL || pair->id == sc->id ||
 		    pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
 			continue;
 
-		for (field = sc.args, candidate_field = pair->args;
+		for (field = sc->args, candidate_field = pair->args;
 		     field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
 			bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
 			     candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3948,7 +3970,8 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
 				goto next_candidate;
 		}
 
-		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc.name);
+		pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name,
+			 sc->name);
 		return pair_prog;
 	next_candidate:
 		continue;
@@ -4044,11 +4067,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
 		pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
 		if (pair_prog == NULL)
 			continue;
-		/*
-		 * Get syscall info again as find usable entry above might
-		 * modify the syscall table and shuffle it.
-		 */
-		sc = trace__syscall_info(trace, NULL, e_machine, key);
+
 		sc->bpf_prog.sys_enter = pair_prog;
 
 		/*
@@ -5316,7 +5335,7 @@ static void trace__exit(struct trace *trace)
 	zfree(&trace->ev_qualifier_ids.entries);
 	if (trace->syscalls.table) {
 		for (size_t i = 0; i < trace->syscalls.table_size; i++)
-			syscall__exit(&trace->syscalls.table[i]);
+			syscall__delete(trace->syscalls.table[i]);
 		zfree(&trace->syscalls.table);
 	}
 	zfree(&trace->perfconfig_events);
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:41 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:41 -0700
Subject: [PATCH v7 14/14] perf trace: Fix evlist memory leak
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-15-irogers@google.com>

Leak sanitizer was reporting a memory leak in the "perf record and
replay" test. Add evlist__delete to trace__exit, also ensure
trace__exit is called after trace__record.

Signed-off-by: Ian Rogers <irogers at google.com>
---
 tools/perf/builtin-trace.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1d4ad5d19b10..a102748bd0c9 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -5339,6 +5339,8 @@ static void trace__exit(struct trace *trace)
 		zfree(&trace->syscalls.table);
 	}
 	zfree(&trace->perfconfig_events);
+	evlist__delete(trace->evlist);
+	trace->evlist = NULL;
 #ifdef HAVE_LIBBPF_SUPPORT
 	btf__free(trace->btf);
 	trace->btf = NULL;
@@ -5719,8 +5721,10 @@ int cmd_trace(int argc, const char **argv)
 		}
 	}
 
-	if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
-		return trace__record(&trace, argc-1, &argv[1]);
+	if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) {
+		err = trace__record(&trace, argc-1, &argv[1]);
+		goto out;
+	}
 
 	/* Using just --errno-summary will trigger --summary */
 	if (trace.errno_summary && !trace.summary && !trace.summary_only)
-- 
2.49.0.rc1.451.g8f38331e32-goog



From irogers at google.com  Tue Mar 18 22:07:36 2025
From: irogers at google.com (Ian Rogers)
Date: Tue, 18 Mar 2025 22:07:36 -0700
Subject: [PATCH v7 09/14] perf syscalltbl: Use lookup table containing
 multiple architectures
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <20250319050741.269828-10-irogers@google.com>

Switch to use the lookup table containing all architectures rather
than tables matching the perf binary.

This fixes perf trace when executed on a 32-bit i386 binary on an
x86-64 machine. Note in the following the system call names of the
32-bit i386 binary as seen by an x86-64 perf.

Before:
```
         ? (         ): a.out/447296  ... [continued]: munmap())                                           = 0
     0.024 ( 0.001 ms): a.out/447296 recvfrom(ubuf: 0x2, size: 4160585708, flags: DONTROUTE|CTRUNC|TRUNC|DONTWAIT|EOR|WAITALL|FIN|SYN|CONFIRM|RST|ERRQUEUE|NOSIGNAL|WAITFORONE|BATCH|SOCK_DEVMEM|ZEROCOPY|FASTOPEN|CMSG_CLOEXEC|0x91f80000, addr: 0xe30, addr_len: 0xffce438c) = 1475198976
     0.042 ( 0.003 ms): a.out/447296 lgetxattr(name: "", value: 0x3, size: 34)                             = 4160344064
     0.054 ( 0.003 ms): a.out/447296 dup2(oldfd: -134422744, newfd: 4)                                     = -1 ENOENT (No such file or directory)
     0.060 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x2e646c2f6374652f,.iov_len = (__kernel_size_t)7307199665335594867,}, vlen: 557056, pos_h: 4160585708) = 3
     0.074 ( 0.004 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2)                              = 4160237568
     0.080 ( 0.001 ms): a.out/447296 lstat(filename: "", statbuf: 0x193f6)                                 = 0
     0.089 ( 0.007 ms): a.out/447296 preadv(fd: 4294967196, vec: (struct iovec){.iov_base = (void *)0x3833692f62696c2f,.iov_len = (__kernel_size_t)3276497845987585334,}, vlen: 557056, pos_h: 4160585708) = 3
     0.097 ( 0.002 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 512
     0.103 ( 0.002 ms): a.out/447296 lgetxattr(name: "", value: 0x1, size: 2050)                           = 4157935616
     0.107 ( 0.007 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x5, size: 2066)             = 4158078976
     0.116 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x1, size: 2066)             = 4159639552
     0.121 ( 0.003 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 2066)             = 4160184320
     0.129 ( 0.002 ms): a.out/447296 lgetxattr(pathname: "", name: "", value: 0x3, size: 50)               = 4160196608
     0.138 ( 0.001 ms): a.out/447296 lstat(filename: "")                                                   = 0
     0.145 ( 0.002 ms): a.out/447296 mq_timedreceive(mqdes: 4291706800, u_msg_ptr: 0xf7f9ea48, msg_len: 134616640, u_msg_prio: 0xf7fd7fec, u_abs_timeout: (struct __kernel_timespec){.tv_sec = (__kernel_time64_t)-578174027777317696,.tv_nsec = (long long int)4160349376,}) = 0
     0.148 ( 0.001 ms): a.out/447296 mkdirat(dfd: -134617816, pathname: " ??? ???????????", mode: IFREG|ISUID|IRUSR|IWGRP|0xf7fd0000) = 447296
     0.150 ( 0.001 ms): a.out/447296 process_vm_writev(pid: -134617812, lvec: (struct iovec){.iov_base = (void *)0xf7f9e9c8f7f9e4c0,.iov_len = (__kernel_size_t)4160349376,}, liovcnt: 4160588048, rvec: (struct iovec){}, riovcnt: 4160585708, flags: 4291707352) = 0
     0.197 ( 0.004 ms): a.out/447296 capget(header: 4160184320, dataptr: 8192)                             = 0
     0.202 ( 0.002 ms): a.out/447296 capget(header: 1448669184, dataptr: 4096)                             = 0
     0.208 ( 0.002 ms): a.out/447296 capget(header: 4160577536, dataptr: 8192)                             = 0
     0.220 ( 0.001 ms): a.out/447296 getxattr(pathname: "", name: "c??????", value: 0xf7f77e34, size: 1)  = 0
     0.228 ( 0.005 ms): a.out/447296 fchmod(fd: -134729728, mode: IRUGO|IWUGO|IFREG|IFIFO|ISVTX|IXUSR|0x10000) = 0
     0.240 ( 0.009 ms): a.out/447296 preadv(fd: 4294967196, vec: 0x5658e008, pos_h: 4160192052)            = 3
     0.250 ( 0.008 ms): a.out/447296 close(fd: 3</proc/447296/status>)                                     = 1436
     0.260 ( 0.018 ms): a.out/447296 stat(filename: "", statbuf: 0xffce32ac)                               = 1436
     0.288 (1000.213 ms): a.out/447296 readlinkat(buf: 0xffce31d4, bufsiz: 4291703244)                       = 0
```

After:
```
         ? (         ): a.out/442930  ... [continued]: execve())                                           = 0
     0.023 ( 0.002 ms): a.out/442930 brk()                                                                 = 0x57760000
     0.052 ( 0.003 ms): a.out/442930 access(filename: 0xf7f5af28, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.059 ( 0.009 ms): a.out/442930 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.078 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.087 ( 0.007 ms): a.out/442930 openat(dfd: CWD, filename: "/lib/i386-linux-", flags: RDONLY|CLOEXEC|LARGEFILE) = 3
     0.095 ( 0.002 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdbb70, count: 512)         = 512
     0.135 ( 0.001 ms): a.out/442930 close(fd: 3</proc/442930/status>)                                     = 0
     0.148 ( 0.001 ms): a.out/442930 set_tid_address(tidptr: 0xf7f2b528)                                   = 442930 (a.out)
     0.150 ( 0.001 ms): a.out/442930 set_robust_list(head: 0xf7f2b52c, len: 12)                            =
     0.196 ( 0.004 ms): a.out/442930 mprotect(start: 0xf7f03000, len: 8192, prot: READ)                    = 0
     0.202 ( 0.002 ms): a.out/442930 mprotect(start: 0x5658e000, len: 4096, prot: READ)                    = 0
     0.207 ( 0.002 ms): a.out/442930 mprotect(start: 0xf7f63000, len: 8192, prot: READ)                    = 0
     0.230 ( 0.005 ms): a.out/442930 munmap(addr: 0xf7f10000, len: 103414)                                 = 0
     0.244 ( 0.010 ms): a.out/442930 openat(dfd: CWD, filename: 0x5658d008)                                = 3
     0.255 ( 0.007 ms): a.out/442930 read(fd: 3</proc/442930/status>, buf: 0xffbdb67c, count: 4096)        = 1436
     0.264 ( 0.018 ms): a.out/442930 write(fd: 1</dev/pts/4>, buf: , count: 1436)                          = 1436
     0.292 (1000.173 ms): a.out/442930 clock_nanosleep(rqtp: { .tv_sec: 17866546940376776704, .tv_nsec: 4159878336 }, rmtp: 0xffbdb59c) = 0
  1000.478 (         ): a.out/442930 exit_group()                                                          = ?
```

Signed-off-by: Ian Rogers <irogers at google.com>
Reviewed-by: Howard Chu <howardchu95 at gmail.com>
Reviewed-by: Charlie Jenkins <charlie at rivosinc.com>
---
 tools/perf/util/syscalltbl.c | 89 ++++++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 760ac4d0869f..4e6018e2e0b3 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,16 +15,39 @@
 #include <string.h>
 #include "string2.h"
 
-#if __BITS_PER_LONG == 64
-  #include <asm/syscalls_64.h>
-#else
-  #include <asm/syscalls_32.h>
-#endif
+#include "trace/beauty/generated/syscalltbl.c"
 
-const char *syscalltbl__name(int e_machine __maybe_unused, int id)
+static const struct syscalltbl *find_table(int e_machine)
 {
-	if (id >= 0 && id <= (int)ARRAY_SIZE(syscall_num_to_name))
-		return syscall_num_to_name[id];
+	static const struct syscalltbl *last_table;
+	static int last_table_machine = EM_NONE;
+
+	/* Tables only exist for EM_SPARC. */
+	if (e_machine == EM_SPARCV9)
+		e_machine = EM_SPARC;
+
+	if (last_table_machine == e_machine && last_table != NULL)
+		return last_table;
+
+	for (size_t i = 0; i < ARRAY_SIZE(syscalltbls); i++) {
+		const struct syscalltbl *entry = &syscalltbls[i];
+
+		if (entry->e_machine != e_machine && entry->e_machine != EM_NONE)
+			continue;
+
+		last_table = entry;
+		last_table_machine = e_machine;
+		return entry;
+	}
+	return NULL;
+}
+
+const char *syscalltbl__name(int e_machine, int id)
+{
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (table && id >= 0 && id < table->num_to_name_len)
+		return table->num_to_name[id];
 	return NULL;
 }
 
@@ -41,38 +64,54 @@ static int syscallcmpname(const void *vkey, const void *ventry)
 	return strcmp(key->name, key->tbl[*entry]);
 }
 
-int syscalltbl__id(int e_machine __maybe_unused, const char *name)
+int syscalltbl__id(int e_machine, const char *name)
 {
-	struct syscall_cmp_key key = {
-		.name = name,
-		.tbl = syscall_num_to_name,
-	};
-	const int *id = bsearch(&key, syscall_sorted_names,
-				ARRAY_SIZE(syscall_sorted_names),
-				sizeof(syscall_sorted_names[0]),
-				syscallcmpname);
+	const struct syscalltbl *table = find_table(e_machine);
+	struct syscall_cmp_key key;
+	const uint16_t *id;
+
+	if (!table)
+		return -1;
+
+	key.name = name;
+	key.tbl = table->num_to_name;
+	id = bsearch(&key, table->sorted_names, table->sorted_names_len,
+		     sizeof(table->sorted_names[0]), syscallcmpname);
 
 	return id ? *id : -1;
 }
 
-int syscalltbl__num_idx(int e_machine __maybe_unused)
+int syscalltbl__num_idx(int e_machine)
 {
-	return ARRAY_SIZE(syscall_sorted_names);
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return 0;
+
+	return table->sorted_names_len;
 }
 
-int syscalltbl__id_at_idx(int e_machine __maybe_unused, int idx)
+int syscalltbl__id_at_idx(int e_machine, int idx)
 {
-	return syscall_sorted_names[idx];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	if (!table)
+		return -1;
+
+	assert(idx >= 0 && idx < table->sorted_names_len);
+	return table->sorted_names[idx];
 }
 
-int syscalltbl__strglobmatch_next(int e_machine __maybe_unused, const char *syscall_glob, int *idx)
+int syscalltbl__strglobmatch_next(int e_machine, const char *syscall_glob, int *idx)
 {
-	for (int i = *idx + 1; i < (int)ARRAY_SIZE(syscall_sorted_names); ++i) {
-		const char *name = syscall_num_to_name[syscall_sorted_names[i]];
+	const struct syscalltbl *table = find_table(e_machine);
+
+	for (int i = *idx + 1; table && i < table->sorted_names_len; ++i) {
+		const char *name = table->num_to_name[table->sorted_names[i]];
 
 		if (strglobmatch(name, syscall_glob)) {
 			*idx = i;
-			return syscall_sorted_names[i];
+			return table->sorted_names[i];
 		}
 	}
 
-- 
2.49.0.rc1.451.g8f38331e32-goog



From andre.draszik at linaro.org  Tue Mar 18 22:38:24 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Wed, 19 Mar 2025 05:38:24 +0000
Subject: [PATCH v2 2/2] firmware: exynos-acpm: silence EPROBE_DEFER error
 on boot
In-Reply-To: <20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org>
References: <20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org>
Message-ID: <20250319-acpm-fixes-v2-2-ac2c1bcf322b@linaro.org>

This driver emits error messages when client drivers are trying to get
an interface handle to this driver here before this driver has
completed _probe().

Given this driver returns -EPROBE_DEFER in that case, this is not an
error and shouldn't be emitted to the log, similar to how
dev_err_probe() behaves, so just remove them.

This change also allows us to simplify the logic around releasing of
the acpm_np handle.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
issue is in linux-next only afaics at this stage, as driver is not
merged into Linus' tree yet
---
 drivers/firmware/samsung/exynos-acpm.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..04c73692383b17ace33e95ce9534101bc68f089e 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -680,24 +680,17 @@ static const struct acpm_handle *acpm_get_by_phandle(struct device *dev,
 		return ERR_PTR(-ENODEV);
 
 	pdev = of_find_device_by_node(acpm_np);
-	if (!pdev) {
-		dev_err(dev, "Cannot find device node %s\n", acpm_np->name);
-		of_node_put(acpm_np);
-		return ERR_PTR(-EPROBE_DEFER);
-	}
-
 	of_node_put(acpm_np);
+	if (!pdev)
+		return ERR_PTR(-EPROBE_DEFER);
 
 	acpm = platform_get_drvdata(pdev);
 	if (!acpm) {
-		dev_err(dev, "Cannot get drvdata from %s\n",
-			dev_name(&pdev->dev));
 		platform_device_put(pdev);
 		return ERR_PTR(-EPROBE_DEFER);
 	}
 
 	if (!try_module_get(pdev->dev.driver->owner)) {
-		dev_err(dev, "Cannot get module reference.\n");
 		platform_device_put(pdev);
 		return ERR_PTR(-EPROBE_DEFER);
 	}

-- 
2.49.0.rc1.451.g8f38331e32-goog



From andre.draszik at linaro.org  Tue Mar 18 22:38:22 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Wed, 19 Mar 2025 05:38:22 +0000
Subject: [PATCH v2 0/2] firmware: exynos-acpm: read fix & reduce log
 verbosity
Message-ID: <20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org>

While trying to use the ACPM driver, I stubmbled across two issues:

    * acpm_pmic_bulk_read() doesn't return the correct register values
    * superfluous log messages during boot

The patches attached are the result and hopefully self-explanatory.

This driver only exists in linux-next at the moment.

Cheers,
Andre'

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Changes in v2:
- collect Rb tag for 1st patch in series
- also drop message from of_find_device_by_node() and simplify related
  of_node_put() (Tudor)
- drop patch 3 from original series, as not useful at this stage
  (Krzysztof)
- Link to v1: https://lore.kernel.org/r/20250314-acpm-fixes-v1-0-ab03ca8e723f at linaro.org

---
Andr? Draszik (2):
      firmware: exynos-acpm: fix reading longer results
      firmware: exynos-acpm: silence EPROBE_DEFER error on boot

 drivers/firmware/samsung/exynos-acpm-pmic.c | 16 ++++++++--------
 drivers/firmware/samsung/exynos-acpm.c      | 11 ++---------
 2 files changed, 10 insertions(+), 17 deletions(-)
---
base-commit: c4d4884b67802c41fd67399747165d65c770621a
change-id: 20250314-acpm-fixes-348c058476a7

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Tue Mar 18 22:38:23 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Wed, 19 Mar 2025 05:38:23 +0000
Subject: [PATCH v2 1/2] firmware: exynos-acpm: fix reading longer results
In-Reply-To: <20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org>
References: <20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org>
Message-ID: <20250319-acpm-fixes-v2-1-ac2c1bcf322b@linaro.org>

ACPM commands that return more than 8 bytes currently don't work
correctly, as this driver ignores any such returned bytes.

This is evident in at least acpm_pmic_bulk_read(), where up to 8
registers can be read back and those 8 register values are placed
starting at &xfer->rxd[8].

The reason is that xfter->rxlen is initialized with the size of a
pointer (8 bytes), rather than the size of the byte array that pointer
points to (16 bytes)

Update the code such that we set the number of bytes expected to be the
size of the rx buffer.

Note1: While different commands have different lengths rx buffers, we
have to specify the same length for all rx buffers since acpm_get_rx()
assumes they're all the same length.

Note2: The different commands also have different lengths tx buffers,
but before switching the code to use the minimum possible length, some
more testing would have to be done to ensure this works correctly in
all situations. It seems wiser to just apply this fix here without
additional logic changes for now.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
issue is in linux-next only afaics at this stage, as driver is not
merged into Linus' tree yet
---
 drivers/firmware/samsung/exynos-acpm-pmic.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm-pmic.c b/drivers/firmware/samsung/exynos-acpm-pmic.c
index 85e90d236da21ed76f7adba59caec165138ad313..39b33a356ebd240506b6390163229a70a2d1fe68 100644
--- a/drivers/firmware/samsung/exynos-acpm-pmic.c
+++ b/drivers/firmware/samsung/exynos-acpm-pmic.c
@@ -43,13 +43,13 @@ static inline u32 acpm_pmic_get_bulk(u32 data, unsigned int i)
 	return (data >> (ACPM_PMIC_BULK_SHIFT * i)) & ACPM_PMIC_BULK_MASK;
 }
 
-static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd,
+static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
 			       unsigned int acpm_chan_id)
 {
 	xfer->txd = cmd;
 	xfer->rxd = cmd;
-	xfer->txlen = sizeof(cmd);
-	xfer->rxlen = sizeof(cmd);
+	xfer->txlen = cmdlen;
+	xfer->rxlen = cmdlen;
 	xfer->acpm_chan_id = acpm_chan_id;
 }
 
@@ -71,7 +71,7 @@ int acpm_pmic_read_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_read_cmd(cmd, type, reg, chan);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -104,7 +104,7 @@ int acpm_pmic_bulk_read(const struct acpm_handle *handle,
 		return -EINVAL;
 
 	acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -144,7 +144,7 @@ int acpm_pmic_write_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_write_cmd(cmd, type, reg, chan, value);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -184,7 +184,7 @@ int acpm_pmic_bulk_write(const struct acpm_handle *handle,
 		return -EINVAL;
 
 	acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)
@@ -214,7 +214,7 @@ int acpm_pmic_update_reg(const struct acpm_handle *handle,
 	int ret;
 
 	acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask);
-	acpm_pmic_set_xfer(&xfer, cmd, acpm_chan_id);
+	acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
 
 	ret = acpm_do_xfer(handle, &xfer);
 	if (ret)

-- 
2.49.0.rc1.451.g8f38331e32-goog



From jpoimboe at kernel.org  Tue Mar 18 22:39:54 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Tue, 18 Mar 2025 22:39:54 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <CAPhsuW6_ZA+V_5JK+xy4v3pyQ-kaZzUooxO=4L+c95fHaW38ig@mail.gmail.com>
References: <20250308012742.3208215-1-song@kernel.org>
 <20250308012742.3208215-2-song@kernel.org>
 <iajk7zuxy7fun7f7sv52ydhq7siqub3ec2lmguomdd3fhdw4s2@cwyfihj3gvpn>
 <CAPhsuW4A73c0AjpUwSRJ4o-4E6wpA9c5L0xWaxvHkJ3m+BLGVA@mail.gmail.com>
 <ox4c6flgu7mzkvyontbz2budummiu7e6icke7xl3msmuj2q2ii@xb5mvqcst2vg>
 <CAPhsuW4BEDU=ZJavnofZtygGcQ9AJ5F2jJiuV6-nsnbZD+Gg-Q@mail.gmail.com>
 <pym6gfbapfy6qlmduszjk6tf2oc2fv4rtxgwjgex7bwlgpfwvs@bkt7qfmf7rc4>
 <CAPhsuW6_ZA+V_5JK+xy4v3pyQ-kaZzUooxO=4L+c95fHaW38ig@mail.gmail.com>
Message-ID: <ifqn5txrr25ffky7lxtnjtb4b2gekq5jy4fmbiwtwfvofb4wgw@py7v7xpzaqxa>

On Tue, Mar 18, 2025 at 08:58:52PM -0700, Song Liu wrote:
> On a closer look, I think we also need some logic in unwind_find_stack()
> so that we can see when the unwinder hits the exception boundary. For
> this reason, we may still need unwind_state.unreliable. I will look into
> fixing this and send v2.

Isn't that what FRAME_META_TYPE_PT_REGS is for?

Maybe it can just tell kunwind_stack_walk() to set a bit in
kunwind_state which tells kunwind_next_frame_record_meta() to quit the
unwind early for the FRAME_META_TYPE_PT_REGS case.  That also has the
benefit of stopping the unwind as soon as the exception is encounterd.

-- 
Josh


From anshuman.khandual at arm.com  Tue Mar 18 23:02:25 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Wed, 19 Mar 2025 11:32:25 +0530
Subject: [PATCH 1/2] arm64/mm/hotplug: Drop redundant [pgd|p4d]_present()
In-Reply-To: <Z9lWJsA2hg2UKZ0T@J2N7QTR9R3>
References: <20250221094449.1188427-1-anshuman.khandual@arm.com>
 <20250221094449.1188427-2-anshuman.khandual@arm.com>
 <Z9lWJsA2hg2UKZ0T@J2N7QTR9R3>
Message-ID: <1c35a8c5-324b-4c60-9bf1-a5414481e5ad@arm.com>

On 3/18/25 16:46, Mark Rutland wrote:
> On Fri, Feb 21, 2025 at 03:14:48PM +0530, Anshuman Khandual wrote:
>> [pgd|p4d]_present() are inverse to their corresponding [pgd|p4d]_none().
> 
> Maybe their implementations happen to be inverse today, but the semantic
> of pXX_present() is not the inverse of the semantic of pXX_none(). In
> general, !pXX_none() does not imply pXX_present().

Agreed.

> 
>> So [pgd|p4d]_present() test right after corresponding [pgd|p4d]_none()
>> inverse test does not make sense. Hence just drop these redundant
>> checks.
> 
> I think the checks make sense in abstract, even if they're redundant
> today

Okay.

> 
> Is there any reason to remove these specific case?

Just for optimization.

> 
> Surely the compiler optimizes these out when they're redundant?

Agreed. Although wondering if p4d_present() is the right thing to test.
Should it be replaced with a p4d_bad() check instead because subsequent
calls into either unmap_hotplug_pud_range() or free_empty_pud_table() 
requires given entry to be a table to proceed further successfully.

> 
> Mark.
> 
>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>>  arch/arm64/mm/mmu.c | 4 ----
>>  1 file changed, 4 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index b4df5bc5b1b8..66906c45c7f6 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -952,7 +952,6 @@ static void unmap_hotplug_p4d_range(pgd_t *pgdp, unsigned long addr,
>>  		if (p4d_none(p4d))
>>  			continue;
>>  
>> -		WARN_ON(!p4d_present(p4d));
>>  		unmap_hotplug_pud_range(p4dp, addr, next, free_mapped, altmap);
>>  	} while (addr = next, addr < end);
>>  }
>> @@ -978,7 +977,6 @@ static void unmap_hotplug_range(unsigned long addr, unsigned long end,
>>  		if (pgd_none(pgd))
>>  			continue;
>>  
>> -		WARN_ON(!pgd_present(pgd));
>>  		unmap_hotplug_p4d_range(pgdp, addr, next, free_mapped, altmap);
>>  	} while (addr = next, addr < end);
>>  }
>> @@ -1114,7 +1112,6 @@ static void free_empty_p4d_table(pgd_t *pgdp, unsigned long addr,
>>  		if (p4d_none(p4d))
>>  			continue;
>>  
>> -		WARN_ON(!p4d_present(p4d));
>>  		free_empty_pud_table(p4dp, addr, next, floor, ceiling);
>>  	} while (addr = next, addr < end);
>>  
>> @@ -1153,7 +1150,6 @@ static void free_empty_tables(unsigned long addr, unsigned long end,
>>  		if (pgd_none(pgd))
>>  			continue;
>>  
>> -		WARN_ON(!pgd_present(pgd));
>>  		free_empty_p4d_table(pgdp, addr, next, floor, ceiling);
>>  	} while (addr = next, addr < end);
>>  }
>> -- 
>> 2.30.2
>>


From peter.chen at cixtech.com  Tue Mar 18 23:09:03 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed, 19 Mar 2025 14:09:03 +0800
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <20250307103128.3287497-1-s-vadapalli@ti.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
Message-ID: <Z9pffxeXHVOsoi4O@nchen-desktop>

On 25-03-07 16:01:24, Siddharth Vadapalli wrote:
> EXTERNAL EMAIL
> 
> Hello,
> 
> This series enables support to build the PCIe Cadence Controller drivers
> and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
> Modules. The motivation for this series is that PCIe is not a necessity
> for booting the SoC, due to which it doesn't have to be a built-in
> module. Additionally, the defconfig doesn't enable the PCIe Cadence
> Controller drivers and the PCI J721E driver, due to which PCIe is not
> supported by default. Enabling the configs as of now (i.e. without this
> series) will result in built-in drivers i.e. a bloated Linux Image for
> everyone who doesn't have the PCIe Controller.

If the user doesn't enable PCIe controller device through DTS/ACPI,
that's doesn't matter.

> @@ -209,6 +209,12 @@ CONFIG_NFC=m
>  CONFIG_NFC_NCI=m
>  CONFIG_NFC_S3FWRN5_I2C=m
>  CONFIG_PCI=y
> +CONFIG_PCI_J721E=m
> +CONFIG_PCI_J721E_HOST=m
> +CONFIG_PCI_J721E_EP=m
> +CONFIG_PCIE_CADENCE=m
> +CONFIG_PCIE_CADENCE_HOST=m
> +CONFIG_PCIE_CADENCE_EP=m

The common Cadence configuration will be select if the glue layer's
configuration is select according to Kconfig.

Please do not set common configuration as module, some user may need
it as build-in like dw's. Considering the situation, the rootfs is at
NVMe.

Peter

>  CONFIG_PCIEPORTBUS=y
>  CONFIG_PCIEAER=y
>  CONFIG_PCI_IOV=y
> 
> Regards,
> Siddharth.
> 
> Kishon Vijay Abraham I (1):
>   PCI: cadence: Add support to build pcie-cadence library as a kernel
>     module
> 
> Siddharth Vadapalli (3):
>   PCI: cadence-host: Introduce cdns_pcie_host_disable helper for cleanup
>   PCI: cadence-ep: Introduce cdns_pcie_ep_disable helper for cleanup
>   PCI: j721e: Add support to build as a loadable module
> 
>  drivers/pci/controller/cadence/Kconfig        |  12 +-
>  drivers/pci/controller/cadence/pci-j721e.c    |  37 +++++-
>  .../pci/controller/cadence/pcie-cadence-ep.c  |  16 +++
>  .../controller/cadence/pcie-cadence-host.c    | 113 ++++++++++++++++++
>  drivers/pci/controller/cadence/pcie-cadence.c |  12 ++
>  drivers/pci/controller/cadence/pcie-cadence.h |  14 ++-
>  6 files changed, 194 insertions(+), 10 deletions(-)
> 
> --
> 2.34.1
> 
> 

-- 

Best regards,
Peter


From quic_vikramsa at quicinc.com  Tue Mar 18 23:24:16 2025
From: quic_vikramsa at quicinc.com (Vikram Sharma)
Date: Wed, 19 Mar 2025 11:54:16 +0530
Subject: [PATCH v1 1/2] media: dt-bindings: Add qcom,qcs8300-camss
In-Reply-To: <b1ea0500-595f-48d6-9358-649c25fd4ee9@linaro.org>
References: <20250214094747.2483058-1-quic_vikramsa@quicinc.com>
 <20250214094747.2483058-2-quic_vikramsa@quicinc.com>
 <20250223-observant-auspicious-basilisk-d78ba9@krzk-bin>
 <66c35bce-c657-4c12-ad02-58c995ae385a@quicinc.com>
 <f2899540-f9ac-4013-a703-25800429f97d@kernel.org>
 <b1ea0500-595f-48d6-9358-649c25fd4ee9@linaro.org>
Message-ID: <a734ed32-00ed-43ca-a42f-5ac88e2a70c1@quicinc.com>


On 3/19/2025 3:18 AM, Bryan O'Donoghue wrote:
> On 18/03/2025 07:16, Krzysztof Kozlowski wrote:
>> On 18/03/2025 06:52, Vikram Sharma wrote:
>>>
>>> On 2/23/2025 5:03 PM, Krzysztof Kozlowski wrote:
>>>> On Fri, Feb 14, 2025 at 03:17:46PM +0530, Vikram Sharma wrote:
>>>>> +properties:
>>>>> +? compatible:
>>>>> +??? const: qcom,qcs8300-camss
>>>>> +
>>>>> +? reg:
>>>>> +??? maxItems: 21
>>>>> +
>>>>> +? reg-names:
>>>>> +??? items:
>>>>> +????? - const: csid_wrapper
>>>> Why different order of entries than sm8550?
>>>
>>> Hi Krzysztof,
>>>
>>> Thanks for your review.
>>> I did this change to address a comment from Bryan on another series.
>>> https://lore.kernel.org/linux-arm-msm/e152ff78-caa5-493a-88da-96a6670eb2a2 at linaro.org/ 
>>>
>>>
>>> Please suggest if I should keep the order same as sm8550?
>> If you chosen the same order as x1e80100 then it is fine, but that file
>> is not merged so it is your responsibility to track any differences and
>> be sure whatever you send is always in sync with x1e.
>>
>> Best regards,
>> Krzysztof
>
> My mistake, I hadn't realised/remembered what we merged for 8550.
>
> Vikram, please follow latest committed example @ 8550.

Thanks Bryan for conclusion on this. Will keep reference dts as 8550.

>
> ---
> bod
>
Best regards,
Vikram


From s-vadapalli at ti.com  Tue Mar 18 23:25:34 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Wed, 19 Mar 2025 11:55:34 +0530
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <Z9pffxeXHVOsoi4O@nchen-desktop>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <Z9pffxeXHVOsoi4O@nchen-desktop>
Message-ID: <20250319062534.ollh3s5t7znf5zqs@uda0492258>

On Wed, Mar 19, 2025 at 02:09:03PM +0800, Peter Chen wrote:

Hello Peter,

> On 25-03-07 16:01:24, Siddharth Vadapalli wrote:
> > EXTERNAL EMAIL
> >
> > Hello,
> >
> > This series enables support to build the PCIe Cadence Controller drivers
> > and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
> > Modules. The motivation for this series is that PCIe is not a necessity
> > for booting the SoC, due to which it doesn't have to be a built-in
> > module. Additionally, the defconfig doesn't enable the PCIe Cadence
> > Controller drivers and the PCI J721E driver, due to which PCIe is not
> > supported by default. Enabling the configs as of now (i.e. without this
> > series) will result in built-in drivers i.e. a bloated Linux Image for
> > everyone who doesn't have the PCIe Controller.
> 
> If the user doesn't enable PCIe controller device through DTS/ACPI,
> that's doesn't matter.

The Linux Image for arm64 systems built using:
arch/arm64/configs/defconfig
will not have support for the Cadence PCIe Controller and the PCIe J721e
driver, because these configs aren't enabled.

> 
> > @@ -209,6 +209,12 @@ CONFIG_NFC=m
> >  CONFIG_NFC_NCI=m
> >  CONFIG_NFC_S3FWRN5_I2C=m
> >  CONFIG_PCI=y
> > +CONFIG_PCI_J721E=m
> > +CONFIG_PCI_J721E_HOST=m
> > +CONFIG_PCI_J721E_EP=m
> > +CONFIG_PCIE_CADENCE=m
> > +CONFIG_PCIE_CADENCE_HOST=m
> > +CONFIG_PCIE_CADENCE_EP=m
> 
> The common Cadence configuration will be select if the glue layer's
> configuration is select according to Kconfig.
> 
> Please do not set common configuration as module, some user may need
> it as build-in like dw's. Considering the situation, the rootfs is at
> NVMe.

The common configuration at the moment is "DISABLED" i.e. no support for
the Cadence Controller at all. Which "user" are you referring to? This
series was introduced since having the drivers built-in was pushed back at:
https://lore.kernel.org/linux-arm-kernel/20250122145822.4ewsmkk6ztbeejzf at slashing/

Regards,
Siddharth.


From akihiko.odaki at daynix.com  Tue Mar 18 23:33:46 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 15:33:46 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
Message-ID: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>

Problem
-------

arch/arm64/kvm/pmu-emul.c used to have a comment saying the follows:
> The observant among you will notice that the supported_cpus
> mask does not get updated for the default PMU even though it
> is quite possible the selected instance supports only a
> subset of cores in the system. This is intentional, and
> upholds the preexisting behavior on heterogeneous systems
> where vCPUs can be scheduled on any core but the guest
> counters could stop working.

Despite the reference manual says counters may not continuously
incrementing, Windows is not robust enough to handle stopped PMCCNTR_EL0
and crashes with a division-by-zero error and it also crashes when the
PMU is not present.

To avoid such a problem, the userspace should pin the vCPU threads to
pCPUs supported by one host PMU when initializing the vCPUs or specify
the host PMU to use with KVM_ARM_VCPU_PMU_V3_SET_PMU after the
initialization. However, QEMU/libvirt can pin vCPU threads only after the
vCPUs are initialized. It also limits the pCPUs the guest can use even
for VMMs that support proper pinning.

Solution
--------

Ideally, Windows should fix the division-by-zero error and QEMU/libvirt
should support pinning better, but neither of them are going to happen
anytime soon.

To allow running Windows on QEMU/libvirt or with heterogeneous cores,
combine all host PMUs necessary to cover the cores vCPUs can run and
keep PMCCNTR_EL0 working.

This approach is already adopted by the perf program. VMMs that support
pinning can pin vCPUs to pCPUs supported by different host PMUs to get
more cores and accurate measurements with the emulated PMU. Even VMMs
without pinning can get approximate metrics and run Windows without
crashes.

A system that has only one PMU or a VMM that supports pinning better
should have no visible changes.

Limitations
-----------

Below are limitations of the current implementation; they are not
fundamental and can be resolved by additional code.

Counter overflows with multiple host PMUs are not handled and left for
future work.

KVM still advertises the feature set of the host PMU captured when
initializing the first vCPU and that feature set may not be covered by
all the host PMUs in use.

The emulated PMU still stops counting if the affinity of the vCPU thread
expands after the perf events are created. Creating a perf event on
demand is complicated as perf events cannot be created while the
preemption is disabled. It is not a practical limitation as there is no
real reason to expand the vCPU thread affinity.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
This patch depends on:
https://lore.kernel.org/r/20250315-pmc-v5-0-ecee87dab216 at daynix.com
("[PATCH v5 0/5] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs")
---
 arch/arm64/kvm/arm.c      |   2 -
 arch/arm64/kvm/pmu-emul.c | 351 ++++++++++++++++++++++++++--------------------
 include/kvm/arm_pmu.h     |   7 +-
 3 files changed, 205 insertions(+), 155 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index caa1357fa367..06292a4ccdc8 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -449,8 +449,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 	/* Set up the timer */
 	kvm_timer_vcpu_init(vcpu);
 
-	kvm_pmu_vcpu_init(vcpu);
-
 	kvm_arm_pvtime_vcpu_init(&vcpu->arch);
 
 	vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index aae5713d8993..631752f5327f 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -22,16 +22,16 @@ DEFINE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
 static LIST_HEAD(arm_pmus);
 static DEFINE_MUTEX(arm_pmus_lock);
 
-static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc);
-static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc);
-static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc);
+static void kvm_pmu_create_pmc(struct kvm_vcpu *vcpu, u8 idx);
+static void kvm_pmu_release_pmc(struct kvm_vcpu *vcpu, u8 idx);
+static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u8 idx);
 
-static struct kvm_vcpu *kvm_pmc_to_vcpu(const struct kvm_pmc *pmc)
+static struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc * const *pmc)
 {
-	return container_of(pmc, struct kvm_vcpu, arch.pmu.pmc[pmc->idx]);
+	return container_of(pmc, struct kvm_vcpu, arch.pmu.pmc[(*pmc)->idx]);
 }
 
-static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx)
+static struct kvm_pmc **kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx)
 {
 	return &vcpu->arch.pmu.pmc[cnt_idx];
 }
@@ -80,30 +80,27 @@ u64 kvm_pmu_evtyper_mask(struct kvm *kvm)
  * kvm_pmc_is_64bit - determine if counter is 64bit
  * @pmc: counter context
  */
-static bool kvm_pmc_is_64bit(struct kvm_pmc *pmc)
+static bool kvm_pmc_is_64bit(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
-
-	return (pmc->idx == ARMV8_PMU_CYCLE_IDX ||
+	return (idx == ARMV8_PMU_CYCLE_IDX ||
 		kvm_has_feat(vcpu->kvm, ID_AA64DFR0_EL1, PMUVer, V3P5));
 }
 
-static bool kvm_pmc_has_64bit_overflow(struct kvm_pmc *pmc)
+static bool kvm_pmc_has_64bit_overflow(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	u64 val = kvm_vcpu_read_pmcr(vcpu);
 
-	if (kvm_pmu_counter_is_hyp(vcpu, pmc->idx))
+	if (kvm_pmu_counter_is_hyp(vcpu, idx))
 		return __vcpu_sys_reg(vcpu, MDCR_EL2) & MDCR_EL2_HLP;
 
-	return (pmc->idx < ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LP)) ||
-	       (pmc->idx == ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LC));
+	return (idx < ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LP)) ||
+	       (idx == ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LC));
 }
 
-static bool kvm_pmu_counter_can_chain(struct kvm_pmc *pmc)
+static bool kvm_pmu_counter_can_chain(struct kvm_vcpu *vcpu, u8 idx)
 {
-	return (!(pmc->idx & 1) && (pmc->idx + 1) < ARMV8_PMU_CYCLE_IDX &&
-		!kvm_pmc_has_64bit_overflow(pmc));
+	return (!(idx & 1) && (idx + 1) < ARMV8_PMU_CYCLE_IDX &&
+		!kvm_pmc_has_64bit_overflow(vcpu, idx));
 }
 
 static u32 counter_index_to_reg(u64 idx)
@@ -116,28 +113,30 @@ static u32 counter_index_to_evtreg(u64 idx)
 	return (idx == ARMV8_PMU_CYCLE_IDX) ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + idx;
 }
 
-static u64 kvm_pmc_read_evtreg(const struct kvm_pmc *pmc)
+static u64 kvm_pmc_read_evtreg(const struct kvm_vcpu *vcpu, u8 idx)
 {
-	return __vcpu_sys_reg(kvm_pmc_to_vcpu(pmc), counter_index_to_evtreg(pmc->idx));
+	return __vcpu_sys_reg(vcpu, counter_index_to_evtreg(idx));
 }
 
-static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
+static u64 kvm_pmu_get_pmc_value(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+	struct kvm_pmc *pmc = *kvm_vcpu_idx_to_pmc(vcpu, idx);
 	u64 counter, reg, enabled, running;
+	unsigned int i;
 
-	reg = counter_index_to_reg(pmc->idx);
+	reg = counter_index_to_reg(idx);
 	counter = __vcpu_sys_reg(vcpu, reg);
 
 	/*
 	 * The real counter value is equal to the value of counter register plus
 	 * the value perf event counts.
 	 */
-	if (pmc->perf_event)
-		counter += perf_event_read_value(pmc->perf_event, &enabled,
-						 &running);
+	if (pmc)
+		for (i = 0; i < pmc->nr_perf_events; i++)
+			counter += perf_event_read_value(pmc->perf_events[i],
+							 &enabled, &running);
 
-	if (!kvm_pmc_is_64bit(pmc))
+	if (!kvm_pmc_is_64bit(vcpu, idx))
 		counter = lower_32_bits(counter);
 
 	return counter;
@@ -150,20 +149,18 @@ static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
  */
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
 {
-	return kvm_pmu_get_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	return kvm_pmu_get_pmc_value(vcpu, select_idx);
 }
 
-static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
+static void kvm_pmu_set_pmc_value(struct kvm_vcpu *vcpu, u8 idx, u64 val, bool force)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	u64 reg;
 
-	kvm_pmu_release_perf_event(pmc);
+	kvm_pmu_release_pmc(vcpu, idx);
 
-	reg = counter_index_to_reg(pmc->idx);
+	reg = counter_index_to_reg(idx);
 
-	if (vcpu_mode_is_32bit(vcpu) && pmc->idx != ARMV8_PMU_CYCLE_IDX &&
-	    !force) {
+	if (vcpu_mode_is_32bit(vcpu) && idx != ARMV8_PMU_CYCLE_IDX && !force) {
 		/*
 		 * Even with PMUv3p5, AArch32 cannot write to the top
 		 * 32bit of the counters. The only possible course of
@@ -176,8 +173,8 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
 
 	__vcpu_sys_reg(vcpu, reg) = val;
 
-	/* Recreate the perf event to reflect the updated sample_period */
-	kvm_pmu_create_perf_event(pmc);
+	/* Recreate the pmc to reflect the updated sample_period */
+	kvm_pmu_create_pmc(vcpu, idx);
 }
 
 /**
@@ -188,7 +185,7 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
  */
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 {
-	kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
+	kvm_pmu_set_pmc_value(vcpu, select_idx, val, false);
 }
 
 /**
@@ -199,21 +196,28 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
  */
 void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
 {
-	kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
+	kvm_pmu_release_pmc(vcpu, select_idx);
 	__vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
 	kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
 }
 
 /**
- * kvm_pmu_release_perf_event - remove the perf event
+ * kvm_pmu_release_pmc - remove the pmc
  * @pmc: The PMU counter pointer
  */
-static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc)
+static void kvm_pmu_release_pmc(struct kvm_vcpu *vcpu, u8 idx)
 {
-	if (pmc->perf_event) {
-		perf_event_disable(pmc->perf_event);
-		perf_event_release_kernel(pmc->perf_event);
-		pmc->perf_event = NULL;
+	struct kvm_pmc **pmc = kvm_vcpu_idx_to_pmc(vcpu, idx);
+	unsigned int i;
+
+	if (*pmc) {
+		for (i = 0; i < (*pmc)->nr_perf_events; i++) {
+			perf_event_disable((*pmc)->perf_events[i]);
+			perf_event_release_kernel((*pmc)->perf_events[i]);
+		}
+
+		kfree(*pmc);
+		*pmc = NULL;
 	}
 }
 
@@ -223,35 +227,17 @@ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc)
  *
  * If this counter has been configured to monitor some event, release it here.
  */
-static void kvm_pmu_stop_counter(struct kvm_pmc *pmc)
+static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	u64 reg, val;
 
-	if (!pmc->perf_event)
-		return;
-
-	val = kvm_pmu_get_pmc_value(pmc);
+	val = kvm_pmu_get_pmc_value(vcpu, idx);
 
-	reg = counter_index_to_reg(pmc->idx);
+	reg = counter_index_to_reg(idx);
 
 	__vcpu_sys_reg(vcpu, reg) = val;
 
-	kvm_pmu_release_perf_event(pmc);
-}
-
-/**
- * kvm_pmu_vcpu_init - assign pmu counter idx for cpu
- * @vcpu: The vcpu pointer
- *
- */
-void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
-{
-	int i;
-	struct kvm_pmu *pmu = &vcpu->arch.pmu;
-
-	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++)
-		pmu->pmc[i].idx = i;
+	kvm_pmu_release_pmc(vcpu, idx);
 }
 
 /**
@@ -264,7 +250,7 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
 	int i;
 
 	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++)
-		kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, i));
+		kvm_pmu_release_pmc(vcpu, i);
 	irq_work_sync(&vcpu->arch.pmu.overflow_work);
 }
 
@@ -321,22 +307,31 @@ u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu)
 		return GENMASK(val - 1, 0) | BIT(ARMV8_PMU_CYCLE_IDX);
 }
 
-static void kvm_pmc_enable_perf_event(struct kvm_pmc *pmc)
+static void kvm_pmc_enable_perf_event(struct kvm_vcpu *vcpu, u8 idx)
 {
-	if (!pmc->perf_event) {
-		kvm_pmu_create_perf_event(pmc);
+	struct kvm_pmc *pmc = *kvm_vcpu_idx_to_pmc(vcpu, idx);
+	unsigned int i;
+
+	if (!pmc) {
+		kvm_pmu_create_pmc(vcpu, idx);
 		return;
 	}
 
-	perf_event_enable(pmc->perf_event);
-	if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE)
-		kvm_debug("fail to enable perf event\n");
+	for (i = 0; i < pmc->nr_perf_events; i++) {
+		perf_event_enable(pmc->perf_events[i]);
+		if (pmc->perf_events[i]->state != PERF_EVENT_STATE_ACTIVE)
+			kvm_debug("fail to enable perf event\n");
+	}
 }
 
-static void kvm_pmc_disable_perf_event(struct kvm_pmc *pmc)
+static void kvm_pmc_disable_perf_event(struct kvm_vcpu *vcpu, u8 idx)
 {
-	if (pmc->perf_event)
-		perf_event_disable(pmc->perf_event);
+	struct kvm_pmc *pmc = *kvm_vcpu_idx_to_pmc(vcpu, idx);
+	unsigned int i;
+
+	if (pmc)
+		for (i = 0; i < pmc->nr_perf_events; i++)
+			perf_event_disable(pmc->perf_events[i]);
 }
 
 void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val)
@@ -347,15 +342,13 @@ void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val)
 		return;
 
 	for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) {
-		struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
-
 		if (!(val & BIT(i)))
 			continue;
 
-		if (kvm_pmu_counter_is_enabled(pmc))
-			kvm_pmc_enable_perf_event(pmc);
+		if (kvm_pmu_counter_is_enabled(vcpu, i))
+			kvm_pmc_enable_perf_event(vcpu, i);
 		else
-			kvm_pmc_disable_perf_event(pmc);
+			kvm_pmc_disable_perf_event(vcpu, i);
 	}
 
 	kvm_vcpu_pmu_restore_guest(vcpu);
@@ -486,7 +479,6 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu,
 	mask &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
 
 	for_each_set_bit(i, &mask, ARMV8_PMU_CYCLE_IDX) {
-		struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
 		u64 type, reg;
 
 		/* Filter on event type */
@@ -497,29 +489,30 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu,
 
 		/* Increment this counter */
 		reg = __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) + 1;
-		if (!kvm_pmc_is_64bit(pmc))
+		if (!kvm_pmc_is_64bit(vcpu, i))
 			reg = lower_32_bits(reg);
 		__vcpu_sys_reg(vcpu, counter_index_to_reg(i)) = reg;
 
 		/* No overflow? move on */
-		if (kvm_pmc_has_64bit_overflow(pmc) ? reg : lower_32_bits(reg))
+		if (kvm_pmc_has_64bit_overflow(vcpu, i) ? reg : lower_32_bits(reg))
 			continue;
 
 		/* Mark overflow */
 		__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
 
-		if (kvm_pmu_counter_can_chain(pmc))
+		if (kvm_pmu_counter_can_chain(vcpu, i))
 			kvm_pmu_counter_increment(vcpu, BIT(i + 1),
 						  ARMV8_PMUV3_PERFCTR_CHAIN);
 	}
 }
 
 /* Compute the sample period for a given counter value */
-static u64 compute_period(struct kvm_pmc *pmc, u64 counter)
+static u64 compute_period(struct kvm_pmc **pmc, u64 counter)
 {
+	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	u64 val;
 
-	if (kvm_pmc_is_64bit(pmc) && kvm_pmc_has_64bit_overflow(pmc))
+	if (kvm_pmc_is_64bit(vcpu, (*pmc)->idx) && kvm_pmc_has_64bit_overflow(vcpu, (*pmc)->idx))
 		val = (-counter) & GENMASK(63, 0);
 	else
 		val = (-counter) & GENMASK(31, 0);
@@ -534,10 +527,10 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
 				  struct perf_sample_data *data,
 				  struct pt_regs *regs)
 {
-	struct kvm_pmc *pmc = perf_event->overflow_handler_context;
+	struct kvm_pmc **pmc = perf_event->overflow_handler_context;
 	struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu);
 	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
-	int idx = pmc->idx;
+	int idx = (*pmc)->idx;
 	u64 period;
 
 	cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE);
@@ -554,7 +547,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
 
 	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
 
-	if (kvm_pmu_counter_can_chain(pmc))
+	if (kvm_pmu_counter_can_chain(vcpu, idx))
 		kvm_pmu_counter_increment(vcpu, BIT(idx + 1),
 					  ARMV8_PMUV3_PERFCTR_CHAIN);
 
@@ -613,95 +606,74 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
 				     ~BIT(ARMV8_PMU_CYCLE_IDX);
 
 		for_each_set_bit(i, &mask, 32)
-			kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, i), 0, true);
+			kvm_pmu_set_pmc_value(vcpu, i, 0, true);
 	}
 }
 
-static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc)
+static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	unsigned int mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
 
-	if (!(__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(pmc->idx)))
+	if (!(__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(idx)))
 		return false;
 
-	if (kvm_pmu_counter_is_hyp(vcpu, pmc->idx))
+	if (kvm_pmu_counter_is_hyp(vcpu, idx))
 		return mdcr & MDCR_EL2_HPME;
 
 	return kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E;
 }
 
-static bool kvm_pmc_counts_at_el0(struct kvm_pmc *pmc)
+static bool kvm_pmc_counts_at_el0(struct kvm_vcpu *vcpu, u8 idx)
 {
-	u64 evtreg = kvm_pmc_read_evtreg(pmc);
+	u64 evtreg = kvm_pmc_read_evtreg(vcpu, idx);
 	bool nsu = evtreg & ARMV8_PMU_EXCLUDE_NS_EL0;
 	bool u = evtreg & ARMV8_PMU_EXCLUDE_EL0;
 
 	return u == nsu;
 }
 
-static bool kvm_pmc_counts_at_el1(struct kvm_pmc *pmc)
+static bool kvm_pmc_counts_at_el1(struct kvm_vcpu *vcpu, u8 idx)
 {
-	u64 evtreg = kvm_pmc_read_evtreg(pmc);
+	u64 evtreg = kvm_pmc_read_evtreg(vcpu, idx);
 	bool nsk = evtreg & ARMV8_PMU_EXCLUDE_NS_EL1;
 	bool p = evtreg & ARMV8_PMU_EXCLUDE_EL1;
 
 	return p == nsk;
 }
 
-static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
+static bool kvm_pmc_counts_at_el2(struct kvm_vcpu *vcpu, u8 idx)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
 	u64 mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
 
-	if (!kvm_pmu_counter_is_hyp(vcpu, pmc->idx) && (mdcr & MDCR_EL2_HPMD))
+	if (!kvm_pmu_counter_is_hyp(vcpu, idx) && (mdcr & MDCR_EL2_HPMD))
 		return false;
 
-	return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
+	return kvm_pmc_read_evtreg(vcpu, idx) & ARMV8_PMU_INCLUDE_EL2;
 }
 
-/**
- * kvm_pmu_create_perf_event - create a perf event for a counter
- * @pmc: Counter context
- */
-static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
+static struct kvm_pmc *kvm_pmu_alloc_pmc(u8 idx, unsigned int capacity)
 {
-	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
-	struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
-	struct perf_event *event;
-	struct perf_event_attr attr;
-	u64 eventsel, evtreg;
+	struct kvm_pmc *pmc = kzalloc(struct_size(pmc, perf_events, capacity), GFP_KERNEL_ACCOUNT);
 
-	evtreg = kvm_pmc_read_evtreg(pmc);
-
-	kvm_pmu_stop_counter(pmc);
-	if (pmc->idx == ARMV8_PMU_CYCLE_IDX)
-		eventsel = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
-	else
-		eventsel = evtreg & kvm_pmu_event_mask(vcpu->kvm);
+	if (pmc)
+		pmc->idx = idx;
 
-	/*
-	 * Neither SW increment nor chained events need to be backed
-	 * by a perf event.
-	 */
-	if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR ||
-	    eventsel == ARMV8_PMUV3_PERFCTR_CHAIN)
-		return;
+	return pmc;
+}
 
-	/*
-	 * If we have a filter in place and that the event isn't allowed, do
-	 * not install a perf event either.
-	 */
-	if (vcpu->kvm->arch.pmu_filter &&
-	    !test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
-		return;
+static void kvm_pmu_create_perf_event(struct kvm_pmc **pmc,
+				      struct arm_pmu *arm_pmu, u64 eventsel)
+{
+	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+	struct perf_event *event;
+	struct perf_event_attr attr;
 
 	memset(&attr, 0, sizeof(struct perf_event_attr));
 	attr.type = arm_pmu->pmu.type;
 	attr.size = sizeof(attr);
 	attr.pinned = 1;
-	attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
-	attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
+	attr.disabled = !kvm_pmu_counter_is_enabled(vcpu, (*pmc)->idx);
+	attr.exclude_user = !kvm_pmc_counts_at_el0(vcpu, (*pmc)->idx);
 	attr.exclude_hv = 1; /* Don't count EL2 events */
 	attr.exclude_host = 1; /* Don't count host events */
 	attr.config = eventsel;
@@ -711,19 +683,19 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 	 * guest's EL2 filter.
 	 */
 	if (unlikely(is_hyp_ctxt(vcpu)))
-		attr.exclude_kernel = !kvm_pmc_counts_at_el2(pmc);
+		attr.exclude_kernel = !kvm_pmc_counts_at_el2(vcpu, (*pmc)->idx);
 	else
-		attr.exclude_kernel = !kvm_pmc_counts_at_el1(pmc);
+		attr.exclude_kernel = !kvm_pmc_counts_at_el1(vcpu, (*pmc)->idx);
 
 	/*
 	 * If counting with a 64bit counter, advertise it to the perf
 	 * code, carefully dealing with the initial sample period
 	 * which also depends on the overflow.
 	 */
-	if (kvm_pmc_is_64bit(pmc))
+	if (kvm_pmc_is_64bit(vcpu, (*pmc)->idx))
 		attr.config1 |= PERF_ATTR_CFG1_COUNTER_64BIT;
 
-	attr.sample_period = compute_period(pmc, kvm_pmu_get_pmc_value(pmc));
+	attr.sample_period = compute_period(pmc, kvm_pmu_get_pmc_value(vcpu, (*pmc)->idx));
 
 	event = perf_event_create_kernel_counter(&attr, -1, current,
 						 kvm_pmu_perf_overflow, pmc);
@@ -731,10 +703,93 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 	if (IS_ERR(event)) {
 		pr_err_once("kvm: pmu event creation failed %ld\n",
 			    PTR_ERR(event));
+	}
+
+	(*pmc)->perf_events[(*pmc)->nr_perf_events] = event;
+	(*pmc)->nr_perf_events++;
+}
+
+/**
+ * kvm_pmu_create_pmc - create a pmc
+ * @pmc: Counter context
+ */
+static void kvm_pmu_create_pmc(struct kvm_vcpu *vcpu, u8 idx)
+{
+	struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
+	struct arm_pmu_entry *entry;
+	struct kvm_pmc **pmc = kvm_vcpu_idx_to_pmc(vcpu, idx);
+	u64 eventsel, evtreg;
+	cpumask_t cpus;
+	size_t n;
+
+
+	evtreg = kvm_pmc_read_evtreg(vcpu, idx);
+
+	kvm_pmu_stop_counter(vcpu, idx);
+	if (idx == ARMV8_PMU_CYCLE_IDX)
+		eventsel = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
+	else
+		eventsel = evtreg & kvm_pmu_event_mask(vcpu->kvm);
+
+	/*
+	 * Neither SW increment nor chained events need to be backed
+	 * by a perf event.
+	 */
+	if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR ||
+	    eventsel == ARMV8_PMUV3_PERFCTR_CHAIN)
 		return;
+
+	/*
+	 * If we have a filter in place and that the event isn't allowed, do
+	 * not install a perf event either.
+	 */
+	if (vcpu->kvm->arch.pmu_filter &&
+	    !test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
+		return;
+
+	if (cpumask_subset(current->cpus_ptr, &arm_pmu->supported_cpus)) {
+		*pmc = kvm_pmu_alloc_pmc(idx, 1);
+		if (!*pmc)
+			goto err;
+
+		kvm_pmu_create_perf_event(pmc, arm_pmu, eventsel);
+	} else {
+		guard(mutex)(&arm_pmus_lock);
+
+		n = 0;
+		cpumask_clear(&cpus);
+		list_for_each_entry(entry, &arm_pmus, entry) {
+			arm_pmu = entry->arm_pmu;
+
+			if (!cpumask_intersects(current->cpus_ptr, &arm_pmu->supported_cpus) ||
+			    cpumask_intersects(&cpus, &arm_pmu->supported_cpus))
+				continue;
+
+			cpumask_or(&cpus, &cpus, &arm_pmu->supported_cpus);
+			n++;
+		}
+
+		*pmc = kvm_pmu_alloc_pmc(idx, n);
+		if (!*pmc)
+			goto err;
+
+		cpumask_clear(&cpus);
+		list_for_each_entry(entry, &arm_pmus, entry) {
+			arm_pmu = entry->arm_pmu;
+
+			if (!cpumask_intersects(current->cpus_ptr, &arm_pmu->supported_cpus) ||
+			    cpumask_intersects(&cpus, &arm_pmu->supported_cpus))
+				continue;
+
+			cpumask_or(&cpus, &cpus, &arm_pmu->supported_cpus);
+			kvm_pmu_create_perf_event(pmc, arm_pmu, eventsel);
+		}
 	}
 
-	pmc->perf_event = event;
+	return;
+
+err:
+	pr_err_once("kvm: pmc allocation failed\n");
 }
 
 /**
@@ -750,13 +805,12 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
 				    u64 select_idx)
 {
-	struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, select_idx);
 	u64 reg;
 
-	reg = counter_index_to_evtreg(pmc->idx);
+	reg = counter_index_to_evtreg(select_idx);
 	__vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm);
 
-	kvm_pmu_create_perf_event(pmc);
+	kvm_pmu_create_pmc(vcpu, select_idx);
 }
 
 void kvm_host_pmu_init(struct arm_pmu *pmu)
@@ -994,7 +1048,8 @@ static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
  * subset of cores in the system. This is intentional, and
  * upholds the preexisting behavior on heterogeneous systems
  * where vCPUs can be scheduled on any core but the guest
- * counters could stop working.
+ * may see features not supported on some cores being advertised
+ * via PMCR_EL0, PMCEID0_EL0, and PMCEID1_EL0.
  */
 int kvm_arm_set_default_pmu(struct kvm *kvm)
 {
@@ -1208,17 +1263,15 @@ void kvm_pmu_nested_transition(struct kvm_vcpu *vcpu)
 
 	mask = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
 	for_each_set_bit(i, &mask, 32) {
-		struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
-
 		/*
 		 * We only need to reconfigure events where the filter is
 		 * different at EL1 vs. EL2, as we're multiplexing the true EL1
 		 * event filter bit for nested.
 		 */
-		if (kvm_pmc_counts_at_el1(pmc) == kvm_pmc_counts_at_el2(pmc))
+		if (kvm_pmc_counts_at_el1(vcpu, i) == kvm_pmc_counts_at_el2(vcpu, i))
 			continue;
 
-		kvm_pmu_create_perf_event(pmc);
+		kvm_pmu_create_pmc(vcpu, i);
 		reprogrammed = true;
 	}
 
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index d6ad13925978..79ab5ff203eb 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -15,7 +15,8 @@
 #if IS_ENABLED(CONFIG_HW_PERF_EVENTS) && IS_ENABLED(CONFIG_KVM)
 struct kvm_pmc {
 	u8 idx;	/* index into the pmu->pmc array */
-	struct perf_event *perf_event;
+	unsigned int nr_perf_events;
+	struct perf_event *perf_events[] __counted_by(nr_perf_events);
 };
 
 struct kvm_pmu_events {
@@ -26,7 +27,7 @@ struct kvm_pmu_events {
 struct kvm_pmu {
 	struct irq_work overflow_work;
 	struct kvm_pmu_events events;
-	struct kvm_pmc pmc[KVM_ARMV8_PMU_MAX_COUNTERS];
+	struct kvm_pmc *pmc[KVM_ARMV8_PMU_MAX_COUNTERS];
 	int irq_num;
 	bool created;
 	bool irq_level;
@@ -52,7 +53,6 @@ u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
 u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
-void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val);
 void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu);
@@ -124,7 +124,6 @@ static inline u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu)
 {
 	return 0;
 }
-static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_reprogram_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
 static inline void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) {}

---
base-commit: 8098cf067a7aae92a4f293df03964bf8474faca1
change-id: 20250224-hybrid-01d5ff47edd2
prerequisite-change-id: 20250302-pmc-b90a86af945c:v5
prerequisite-patch-id: 3ad91b60da556a3e1d599882a12288f397c6b4e7
prerequisite-patch-id: 1be00eb7a63e8546dbb159beae3ca464e29e3e96
prerequisite-patch-id: 63d32a008656195057c7bd215423656b1e206d3c
prerequisite-patch-id: 8b7aab52cb84c781012ab8adf468bbb5c4ccfd7d
prerequisite-patch-id: a9aa801b5624bcd5ebd80ec9ab5d727ddf6b1242
prerequisite-patch-id: e65d864dbb379dc01882e74e2608b1fad51b50e7
prerequisite-patch-id: 4fecf0e86792a8e5101a173bfa6f3c9bf7473e41
prerequisite-patch-id: 4d6787214a8d3e13eda61cf8f43fdf3e4e6f2b33
prerequisite-patch-id: c2df211b631f9c0d56ec778446ab4b37088c137a
prerequisite-patch-id: 9d9092dcb5669787179c98b4d026ca6fcddf43b9
prerequisite-patch-id: 817bded5bedc86b2659c9446cde2450b85d46624
prerequisite-patch-id: 1c54041ec06ed3cbb7b7d5b1eda64af615f1a94d
prerequisite-patch-id: 9c528724ae0e1291087992b1cef2448584c03f1b
prerequisite-patch-id: 02fffd6814bd121c8ce0af75b7bc32b0dd8260d2
prerequisite-patch-id: 7a86d80c7918f0ba88a509dce30831adff7562a7
prerequisite-patch-id: eafdea1a57ccd213bb7dbc58a3eacb0ff75b9d87
prerequisite-patch-id: b40661f81df728ae9fbd2ef97414bdf101fcd4b2
prerequisite-patch-id: be4b96bead5212147b2c841fa4aca2e39d48e34d
prerequisite-patch-id: 48f1725c6e7794b180de0e2d1c7fd061d37089fe
prerequisite-patch-id: 87b62eb9889d885ed179e53efbba8e4e31c9de4c
prerequisite-patch-id: 4604f02e892cb8a9c4704520b6372cd4fcadb0a2
prerequisite-patch-id: d377c33ec6bb4dd756ddb5a7e550a387513d65f0
prerequisite-patch-id: 2d4d416cf592845c85f320ac98d6ac25931ff057
prerequisite-patch-id: 88a998d505fef1f541e29bbfab4b7ac24be18fc2
prerequisite-patch-id: a9f9f4adfe152df7edd5ed11906d69eaacdc8c67
prerequisite-patch-id: baab1efc93f5d60a369bd21f60cb34f1831615ae
prerequisite-patch-id: 3cfcf5bd6b6a4ac67463951846b566b3b75c0a99
prerequisite-patch-id: 59a0d40227f4cf85d4946ab173a7d4870e07c78d
prerequisite-patch-id: 113bdd109be34ee9da663d194e8b4aedf02180c5
prerequisite-patch-id: 0f75bac966d96f4f7273152267a84ad33701ca06
prerequisite-patch-id: 0947ba9625edd95b88f1117f7ac71596089815cd
prerequisite-patch-id: a929dcbd57229a02012454f55e6f197d6535e15e
prerequisite-patch-id: 9923900be884b6b66bde9db818697311618c7e96
prerequisite-patch-id: fcaba98777b403c2c762f0e402339b173ef50598
prerequisite-patch-id: cbab40b40cddfbac5a03187f742a1c86855b6c44
prerequisite-patch-id: 6e52a0bbf0d8ab82675e531e35701570ca69b487
prerequisite-patch-id: afd676b03ef9f08b9b1e6cdd550682af6ed97846
prerequisite-patch-id: 3082c60677ac286c4b7c0eb9379075dffb8b4b17
prerequisite-patch-id: 90fd1af7585680c9278bb306af9142b07f954a67
prerequisite-patch-id: 9027f2d4b6fea899090915a3f05e36a96809deb9
prerequisite-patch-id: e387ecd2afb85036aef864e68c5b48889228f4bf
prerequisite-patch-id: cbe3ea4b6588b26230e54cc491757bdd8f7b2a93
prerequisite-patch-id: a7e5d1a4e223f5b3d6b62819b5f9e137ad099844
prerequisite-patch-id: d91500215e3ac9d42674ac8535d6c250a8ab9773
prerequisite-patch-id: 820352aad0f9a1e7be48e33cd0926f52c0b496c8
prerequisite-patch-id: 7ecf99a1889f92b76421c779c8ad654aaee10375
prerequisite-patch-id: 826a5c996141385dc3c2807d1177d9704de6051b
prerequisite-patch-id: e684a92d65eda3bfbb050fad182bd5238f8b9427
prerequisite-patch-id: 1723969d360d0bdcc50d60f6dd8827a5696b65a1
prerequisite-patch-id: 4cfc11997e7a2e3eb5c97d6cccbe4c48bd61348d
prerequisite-patch-id: 0653690229352095ec92eb2e6e47d3f06ccccd7b
prerequisite-patch-id: 864cc661749846cc237e9496f06948fde567c335
prerequisite-patch-id: 0afa3791265ba660562266c1d410121a1acfcce7
prerequisite-patch-id: b4eb9e4cb8ed286bd30e57863384bad1f560e937
prerequisite-patch-id: 3c2b301c5c479174a09f71397579b32283a83979
prerequisite-patch-id: ccaee0a5dee13d875b268378c357e62bd42084bd
prerequisite-patch-id: 4e0f2b2ffdffaa099257ead992b819bb4d809351
prerequisite-patch-id: f5722ae339169e127b1e99852b931fbbe1efd748
prerequisite-patch-id: 9853d4ceca03be817a8dd09f966b94e78097827f
prerequisite-patch-id: 32ba9afcad03f7daec660e73b370a436a8214076
prerequisite-patch-id: 991d2a7eebbd01d1bd081a904dbf0f333da33928
prerequisite-patch-id: e2e9634e2bf36bffa9a88abdccc5801d71c43a61
prerequisite-patch-id: 6f0a9c4198f0df422a579f876b2f7fecdabbceab
prerequisite-patch-id: 76d52907dcce2c5c590e0f832ca7ced7a885feb8
prerequisite-patch-id: 414578ffe40ff395bc35b49e3eebf236a988a602
prerequisite-patch-id: 73d0b87fe9deb70428998ceef0efbc5bbbfc6b44
prerequisite-patch-id: 237625c1544c921925aaae0508b170ca3a7ab4cb
prerequisite-patch-id: 77738ec0c4dc3148ada391f1c70420ed0ebd257a
prerequisite-patch-id: 68a94a1d9a2d0e78c60e845193917a59a81391bc
prerequisite-patch-id: 9c5202a6319aeead827551a014adc46a535e3939
prerequisite-patch-id: 687455d69ebcd60af5be3b6a6e7a3def362e8d21
prerequisite-patch-id: 9d01feac1577e0a680295ce0e447226dd566a599
prerequisite-patch-id: 582613278901f1846e87104fe61f8aa823d73fbe
prerequisite-patch-id: ef9e51f54a813ed7fb24d9959dacafd471957813
prerequisite-patch-id: 528391ed13c7d8c3d7b071df716461b90e351393
prerequisite-patch-id: 427380cc73731a17fed4e366e1c1d9c9912b4d56
prerequisite-patch-id: 0738e1561a723be0d148c3fbe70dcc71791b760b
prerequisite-patch-id: 67d4137f71f254a3b3d92046de2b3eea846108c1
prerequisite-patch-id: 1cc6dbf313bff99bad69b7647dd6306f6ae96863
prerequisite-patch-id: 508501eb00942f9c6652880703289bd85be9fed4
prerequisite-patch-id: e2757ae3a94b3bc64f6ae9e1a98dbbbd23abb127
prerequisite-patch-id: 5921298136d3669b3ca0f3036f24b3843a696e15
prerequisite-patch-id: 1ccaccf6215b4363c111ef0e06ca0ecab552df29
prerequisite-patch-id: 1f1a8e68685abc50b1b4d445d9b08356f16dc28c
prerequisite-patch-id: 2b6ca0f577975f7c04d5606e36b53e014c7c3877
prerequisite-patch-id: 0f0234e2bea5e3345bf65330884f9958c7a89e18
prerequisite-patch-id: b02cacfb40f350d1c6d00850d1cb1f3f079bcc05
prerequisite-patch-id: 992620c80608c0c85afa0f2889d8c2f9a1e8c96e
prerequisite-patch-id: f2b7064182e99cf35aef728a4256ed4559f2c1e3
prerequisite-patch-id: 243e74119ab19928c6c8ee0a6b81162ef8c22228
prerequisite-patch-id: 84a3ddfcc8c8204bc4458f94af0c516e372d5172
prerequisite-patch-id: 4812137266da6e3426cd7e2d3b414de49e9095ee
prerequisite-patch-id: ac17ad31222d4c02271670d5eb192cc25ef665d7
prerequisite-patch-id: 2c91820315e60dd49f363bb797b9cef53822f31f
prerequisite-patch-id: 6ace5a1604e1ec77419af8d95e833cd282689fa8
prerequisite-patch-id: 7d56e47edcc30e479d76d5ffad02c6275e346413
prerequisite-patch-id: 160e82e0a149ab44bedd3c8c9b96a95dd1baa96f
prerequisite-patch-id: a7cf66c22b099e1c9c75c0700c6ca0df102b4c52
prerequisite-patch-id: 3f776dc69cbfa252d5fef9522978a358a1c82531
prerequisite-patch-id: 8c0a03030212fe4bbf5f1207fc744c5f85f55a46
prerequisite-patch-id: 014852e77de3411df1cb10fa3d71b4b579d2514b
prerequisite-patch-id: 0790043a1ff0c64837d7fec887521006ae8552d7
prerequisite-patch-id: ac91783d5fdac90aa068eab1310ed6d462589b71
prerequisite-patch-id: baf8b4b761a5dfcf1db25cefbc253bf901413fa2
prerequisite-patch-id: 9f635f9e0901a8a4d2a98db2455e2255782a1df9
prerequisite-patch-id: 4e91c279f98bf5627c1405847c9d2ee16ad3cdaa
prerequisite-patch-id: fd52cc146ca09cece69e897b697971ba2609a31a
prerequisite-patch-id: b9b438ed2a39e4e21874ddb9653c1026d5ad84ff
prerequisite-patch-id: 84aee72393d42cef7fa33f7787d7efc0973c1c14
prerequisite-patch-id: c685a1bba21ec01978c4c8a4d3e3f6cf56e68d3e
prerequisite-patch-id: a09e204e5b5c32b4a7cb605c086a285d3ab69283
prerequisite-patch-id: e8361b0ab5d0917f1cd780c1e94b9be7a17004ee
prerequisite-patch-id: 36dae7626f3657d5e083948b8ed7bda2d89ed0a7
prerequisite-patch-id: ea1c797acd9653c538d05b23c309c2a822d1cdb3
prerequisite-patch-id: 57fd583a033873db42af45e5965e13100330d68f
prerequisite-patch-id: 09fb5cac310e0a4b0718932daa043a8ec776919d
prerequisite-patch-id: d81fb77386a4ea1711ddccc4c79818dc809dd7fa
prerequisite-patch-id: c1bd6d04019af14a039ddf783948eafffe930118
prerequisite-patch-id: 49394ffa8d826cfb81fc08ed88f9cf77b685c0fa
prerequisite-patch-id: f23c099774651da18b44aa299127f6d07a8e6c9d
prerequisite-patch-id: fc52c27adb7a008167780de6cbb9511bea653d31
prerequisite-patch-id: 1cc63161557c851485ebf55105e1af9b626bcfcd
prerequisite-patch-id: bc00834d08adf70ded280ed004fa13274c1a7167
prerequisite-patch-id: 3a16138a8260da2853282e94f070d2e220e9311d
prerequisite-patch-id: e8284ff3059502d875a95fcef7403249f5070fc5
prerequisite-patch-id: bb14b4b351f98e2c249a87f65bd4674e129c56a9
prerequisite-patch-id: 267e7ec1b5cf09a7259e280f098a2a6ddf10258a
prerequisite-patch-id: fb4e533971866f36552fb264b90700396e527198
prerequisite-patch-id: 9d13b8a5269805338984ba442a2211912c7b1e10
prerequisite-patch-id: c186df04042662fbd3ec3acc3c3a80c71b66e533
prerequisite-patch-id: 63707bf52e1ee91a3cffb34c4fc7726417ae18d3
prerequisite-patch-id: e08588c06386deb67d100fc161502fc3d5976bf4
prerequisite-patch-id: 002b44529b32ff81a68829d59467b7b4ea426dc8
prerequisite-patch-id: fd2c055ab4965c0dfdf3ff23d2a1d66beacfed8e
prerequisite-patch-id: 73b66c84c9fdc0b9acc8a66105fc62ca41c313a9
prerequisite-patch-id: 474c6c3437682d50da1cef36e2b90609622f02f0
prerequisite-patch-id: 16595ddb9b99419c2470e6db313cb380bd5167b7
prerequisite-patch-id: b7a95879bbec84b503fc0a0ab71e9dfecc5be3f2
prerequisite-patch-id: fa878a3a218889b6ed248224cc10ab03cd43d11e
prerequisite-patch-id: c4790779fae92911fcbfad95d3fe93720bc25842
prerequisite-patch-id: c44f8670e0d4f72603b3561e55078fa0fb3e1977
prerequisite-patch-id: f3aaa5e4e73029b6b680a7f7d317dc08a8175cf7
prerequisite-patch-id: 12fc867df0c684ca3d91e6171a2b5100cb93b81a
prerequisite-patch-id: e0254c4842bded3be11957f1dff564254f28d8e9
prerequisite-patch-id: dedc5951f52bf6b57ac56c969f08b5d52107d0bf
prerequisite-patch-id: 0e60bb1e67ee3217df2997d32b9ced1da1833239
prerequisite-patch-id: 8c6ddc2a1d2d561bb1e2b1cc2396a47f551f610f
prerequisite-patch-id: 1b14360ef13ec6d1d91c488d1aba36d4da007935
prerequisite-patch-id: 336fab68fe736e8083144cc858b634d195eb3b3a
prerequisite-patch-id: 94fa7d6f1cc7510f501d3aa3d47e5cc89a9188b9
prerequisite-patch-id: 9f653ab8c436c1ca641d6288a33d49cc04281027
prerequisite-patch-id: 5573f2b3705d46f54223440a674b67cad482f807
prerequisite-patch-id: 1d1422970df81399872490ea9c1ebc1c643635c0
prerequisite-patch-id: fc925d9235ed000ba17b903871a9525f933b912f
prerequisite-patch-id: 0ba6835463ff611d6945231a0c83c2ab02e9785d
prerequisite-patch-id: b95ccd72b69e2cf329d4342e918510c5edf8d701
prerequisite-patch-id: 9c3c59b4af2fdd549029cc870750a81c1b794659
prerequisite-patch-id: ac630b4826b80e0c49618f9b3399a6a3d1c0c77c
prerequisite-patch-id: c72ec2e0a4256288f9d4e291060c28c9716b18ea
prerequisite-patch-id: 786b50179d8543f7c9ba2defce6f9eaff11a35bd
prerequisite-patch-id: 3b6895ac656902427500b75d280775cf28be335c
prerequisite-patch-id: 5e6819a641f7dce4feb201445e024e9a10d56949
prerequisite-patch-id: 9a99286b6feedc4a62d314eff229a397837ad9b9
prerequisite-patch-id: 3477b52acf854cdf964608a4f23e840301378b6f
prerequisite-patch-id: dc40c0cdaad940ba04da12f23c599dfa0e8d4ce5
prerequisite-patch-id: 3b4c8e0628e2917ac2a6d12fc341bb59d9acc3e6
prerequisite-patch-id: aaf8c0f1c9c6876e4fbcf583717f8019253054bc
prerequisite-patch-id: ad87ec2fc754f44e54641d073b258018fa4e88c2
prerequisite-patch-id: 585bc34ead1177a97544cf5d6561491c61df253e
prerequisite-patch-id: 75c518f0d2042195c937a5816bcf54ad77e62b99
prerequisite-patch-id: 0ceb4baf4e6a918b118cb698393b40545a363ae4
prerequisite-patch-id: 624b07e44a85cc4125ddbb4a6f22733be8a412bf
prerequisite-patch-id: 762c9bfa8ad9e8055b4b409a56ed1475803c9a9a
prerequisite-patch-id: 7d73294d78e58a31ac5d61bab6ba29e8e241f34d
prerequisite-patch-id: 0198a123807ad6092869bc9b526fd4d7ab973e01
prerequisite-patch-id: 2002985a8160e98c5f2cf41923c2c978b6ba7fbf
prerequisite-patch-id: 9b8082332c625eec6795903bfe021ac7255e51d1
prerequisite-patch-id: 5e4fe280f36543e66ffd0d8092693ac86fd6dfb0
prerequisite-patch-id: 1fcd6c7add50710303de26540ec3a4c81a46b34d
prerequisite-patch-id: 6f3a9165a8410d6ee933a921538da36abeaa7d1d
prerequisite-patch-id: f57009e493c574d328503f69cdffb2f59d95e776
prerequisite-patch-id: 26125efe660fff28296bf1bdf64b88fb7ecd3fcd
prerequisite-patch-id: 895db4d227b1574b372a409a6e88d1136b0f8c3e
prerequisite-patch-id: fcd1b5cfb668f72f8a3bda919c90e96a35fa4c9e
prerequisite-patch-id: 4417778bf942905f6c06f2e65c82cfb4c3b530de
prerequisite-patch-id: 306768fbb26ddd866575c6247e41cefd2883d3ad
prerequisite-patch-id: ab56a6d75aca9b24479ee6004284b7d5bb386468
prerequisite-patch-id: 2c726747bce5b0bb50a6a7cdddda27e086a6314b
prerequisite-patch-id: 41e90f1a4a57c82d79291367e691de5dda426401
prerequisite-patch-id: 7682ad57a1b8d284f919cc1c1c582f97cfdb87f9
prerequisite-patch-id: 38fc889b0635d25cdf563d98d6177a8998b9cb24
prerequisite-patch-id: 7bfa210214eeceada83339821e8da795dca755fc
prerequisite-patch-id: 2761d2ea11f1469de7bcd7fb34146903b29ae57c
prerequisite-patch-id: 16d29bce080ae9f8150dd47aab67e156dc20fafb
prerequisite-patch-id: 6e3b583db810aeac9afa80b40027d1ca4b1fcf78
prerequisite-patch-id: 5b47f85b2f7e51137e3c3f0eb822f9d5adaef20a
prerequisite-patch-id: 15f8ead5b84787039a24de8a580bf460bf02cf5d
prerequisite-patch-id: a8291c4f5e3118165362aeb3d436ae1a0e2bc0b5
prerequisite-patch-id: f2a67cf7c7010e96f228cccb72ab6ab7171a4562
prerequisite-patch-id: 2bdcf4269674da080c837102f0f1baf5e5699e30
prerequisite-patch-id: 2963d5634caca58815f5954f3ac38862c0761925
prerequisite-patch-id: b649de93b5cf069305cf1ec541a8b140caa97992
prerequisite-patch-id: 72e5eda7d15935f15a67569dacef1c3d397d7600
prerequisite-patch-id: 8634951bb66ef258834c0ecdb2739a3ac155858e
prerequisite-patch-id: adea1618a1432b8902a73b0a706033d6ecd006b9
prerequisite-patch-id: 2a83ce1d0f5fa300c524d43f9a2f0b2376a9b686
prerequisite-patch-id: e1522fda4d999087becef78cc2d275f4c96676b7
prerequisite-patch-id: 0d1e4ac438db54dc324cbca2486fcb1094b22e84
prerequisite-patch-id: 44212f9d04e563364da143b7e777c9e5478b6c8b
prerequisite-patch-id: 04fa11f69c36914825165ec6bc4d67c059033a3c
prerequisite-patch-id: 15497d23098170f60b18d4f4c7c19bd711359e12
prerequisite-patch-id: 8f7a0f1d5ec7c8b71beedf9313051f5d1d06a1bf
prerequisite-patch-id: 5d071c175bae7b68f4ec76c1b03e8e3e949056b1
prerequisite-patch-id: feb6d749f6e3b9f4fd113b6ec66f8b67cb63ebdb
prerequisite-patch-id: 6f953005e51f7dac874104d13bdbfb1252469afc
prerequisite-patch-id: 3677a9e5472f14522d0095829bba22366dae9198
prerequisite-patch-id: 973f1f3244f7e4f0aab190a03beae20be6346fe6
prerequisite-patch-id: 040d656240f4472341051a3d8c73322a5495f651
prerequisite-patch-id: a5ce40e4ba24af6ba0ff16a0942123f88365bb0f
prerequisite-patch-id: ca2ce900eac784330551b6329256905aaeceb439
prerequisite-patch-id: ca9369e0079264c05fa5733a8ceae59aff0c9b62
prerequisite-patch-id: 033295484ca32b2f54a913d7ac2b74b9c1c3322d
prerequisite-patch-id: e1c0a14a0dcc6527e420dcdaacc2bfb358a34f8b
prerequisite-patch-id: 1d3d22321c13c2646da09638e4869f8672600a23
prerequisite-patch-id: 8f80091e3c883de876d06ba6e1b331eb99b90cb3
prerequisite-patch-id: 8d35d40bbfe34ae825d1cc5cce189d3aa82de156
prerequisite-patch-id: 3b8c0f636f008f7c06713cc2c7bbfd23e7f8b5e7
prerequisite-patch-id: a295bc38b7e96cad655d04421fa6f73976697e8e
prerequisite-patch-id: 7ade259d372ac7e087e5a4531d6518642d1e779d
prerequisite-patch-id: d1f57fb0b89c64544a323ab0d6eaac361c740416
prerequisite-patch-id: c10a45af9d47e1e4ea26148c12f7a046f7054a18
prerequisite-patch-id: fddb719312d6852d0d48ee45a6d0a5f9250efc82
prerequisite-patch-id: cecd63b709fd46ae6c422edd1cc5401864c87891
prerequisite-patch-id: 150ae8720a847604bc2c39a46b7b2df727e2876a
prerequisite-patch-id: fac9518e1d60dcf3da2faf56aae3ae384ca3bc95
prerequisite-patch-id: 832691297497cde3cc85c5959b8de1f4049f0d1e
prerequisite-patch-id: f21e249e583c4c893584b84e97a88a77e477b445
prerequisite-patch-id: dc216c6e832b6fe089d98f855e9bde1933b7fcc9
prerequisite-patch-id: 63985942576401f33379841a7a479c0d0785e0c9
prerequisite-patch-id: 9e6444c4e9e70d6b5e3a6d184adb27c98e9363b4
prerequisite-patch-id: 53fc16017b20e668b99c5681cef030b009534ffd
prerequisite-patch-id: 3182587fd4a1515111c020f92a17647a89e4bf50
prerequisite-patch-id: f47272efe246fa988e58c9476d3ccbc1f5a64234
prerequisite-patch-id: 0926d980333fdc5d7d5d5535f0f92645df691fb2
prerequisite-patch-id: 8117cb7135de3527a76a618299a7883002517597
prerequisite-patch-id: 1119bba4ef5fde04dd0e485527c72e168b045c22
prerequisite-patch-id: 45003166fd8698deda34d9ed23a200f4519d1788
prerequisite-patch-id: cb8bd0d492978e59094a4677024fbf0676c42347
prerequisite-patch-id: 6213d7c2cd350213a6a51fac1b952469c5e39ee3
prerequisite-patch-id: 47856ba76b9ba33ebbb6c9a1210961bfce23cc6d
prerequisite-patch-id: 04dfc436f75f4d258c7851c93d95e2363ca26843
prerequisite-patch-id: b75a63e5c59c004458258bb944f9be21c2543a60
prerequisite-patch-id: fa2e54b5306ff45896fbdeb47996627f7501f882
prerequisite-patch-id: 3a8ef7b24a87288483226357bf4149d1ecc80550
prerequisite-patch-id: b68d0d2fee3d84d24eb033a04025c9846b569b51
prerequisite-patch-id: a579bd78fb5c4e841456d0faf026dd6151d22fc7
prerequisite-patch-id: 45e3135deff29990d6048334b230861c707f3a20
prerequisite-patch-id: 5926f2e475baa63315dc3ba306ecbbdca95a98fb
prerequisite-patch-id: 4694455e7823dde9ea38d4f1686abc9756c5f7f6
prerequisite-patch-id: 7d8d8973f796e68fd80a7f62f3bcc52e1c30396d
prerequisite-patch-id: 54314baf3f2b3b16d4983e1de4e3b52d69883529
prerequisite-patch-id: 33847c2db7509a594706eea93c4c42732e6b9549
prerequisite-patch-id: 5b3aed3de30030b299a85b1e0e88cf1d344b211c
prerequisite-patch-id: 045ddb683740bbe9786ce716d58320f1e5767dfd
prerequisite-patch-id: e0352391bb506af334f14dce49dd68416af98917
prerequisite-patch-id: 857ac927e95b128e57e99dfb28ad6a3a4c4c6fb0
prerequisite-patch-id: cca60390b03d02c521ae6f63f068a7c99cda24be
prerequisite-patch-id: f576a42d00dc084991882cea6d06fa44706ad178
prerequisite-patch-id: edb411ce9d031e942a5e543b04a0a42edbfd0d02
prerequisite-patch-id: 61b1a2f483f14ff0bdf3886d287c89b0ef42a086
prerequisite-patch-id: 8d57b599fc2b2ed3681b5b3b7efb8b9b0417f51d
prerequisite-patch-id: 64ed7fa64272c2866d3b81142f9cd321cb76a37c
prerequisite-patch-id: a0bc3b82b2c90c72ddbd8dd115a56e16d4cac469
prerequisite-patch-id: c2d0fcd7bca2ab18ebc7fb54db120889ae6d08fb
prerequisite-patch-id: 65164d9d8833fe61620695eb3d45785598494a9a
prerequisite-patch-id: 9fd1db7ba39d66c92592c7f22eb33604df018004
prerequisite-patch-id: 3e8babc53751c8b34a09809aa8617fcc55648b01
prerequisite-patch-id: 92ff008efdcf7cbd39e8dccfc0517c6f6c5b6a25
prerequisite-patch-id: 9c70e32d6c9918e59fab34b791990a2a666535ca
prerequisite-patch-id: b892f4f194714d502572d2cf28b0157f8610f6d7
prerequisite-patch-id: 7101d7c3a2aab470ecfedeb300c85b6477b62552
prerequisite-patch-id: 8fa7a2384ae82b8ccef76ce37f7cbce163bac309
prerequisite-patch-id: 8fedce4d136f8b6cea6077946b1822908445a39e
prerequisite-patch-id: b8920c0abfc72783f4ef218b55ddbe9222a15319
prerequisite-patch-id: 61282bd2766fb4935f851c9fd630d8d0f2891cfe
prerequisite-patch-id: 1deca844492c24736188d94468206fd10054c371
prerequisite-patch-id: 022e4390afb3b31f890bb7d6bb1492dea5d76179
prerequisite-patch-id: 2055614272e6a7a8cf67a78c6c63f73e35390d67
prerequisite-patch-id: f09d0fac16db52162f7fbbab82c1a7f405aec957
prerequisite-patch-id: 7c70f31ef28696c9875931cb316a7343368f9527
prerequisite-patch-id: 48b124c9ca64a263e15a4ec6786261d7e34794e4
prerequisite-patch-id: 044a3c3bd7ca396e71896ee31f55f3b15931f205
prerequisite-patch-id: bd9d532b932cbe4ad5e68ba2027c02f81138ff2a
prerequisite-patch-id: 7948521e7678662ef69ae9806d4bafa99c3bfb83
prerequisite-patch-id: 15a43b5ae46c7e0fd885c461d2ed30d160a2c169
prerequisite-patch-id: 659e687545aa6498ce31ca973d1721429a195060
prerequisite-patch-id: a2afe906f9eeea4d1d1623cbb6459426dd20a0d4
prerequisite-patch-id: c18762364783b89aef76098f1b2b74d3a2ef079b
prerequisite-patch-id: 9393946e363ada6f14e5aca292515a9598e37112
prerequisite-patch-id: f78efee71866139b424e27b803bee565742f8a59
prerequisite-patch-id: 6d8555d8f2e9a7d0700979d69e0e037c69585c01
prerequisite-patch-id: 263895d259db042587f00ca6963ca82416804373
prerequisite-patch-id: 35124c953047b8e47ebb8d027a3d0179adaff347
prerequisite-patch-id: 815011e65f95944ec317ad0e95586cadbe8e7314
prerequisite-patch-id: 7448bd5669e9b78c2a745bff2ae8a0d27527c720
prerequisite-patch-id: b30e011017f9ff9c0d1411089a77eedff7003573
prerequisite-patch-id: b30bf656b167e20776076dcedbae348cfdb11b45
prerequisite-patch-id: 47052688b79ff10339fbc4a36684e094f5b7e501
prerequisite-patch-id: 70ebc770d9d0c3d36f945d77d07b90383246d6d5
prerequisite-patch-id: 40b847f228570992cfbbba8f23b15172df9ab52e
prerequisite-patch-id: d14125a8ff6fe93d428de62eb10fe0d357ba5621
prerequisite-patch-id: 7f16342e34e51875b16706b5f44909bcb7fed8e1
prerequisite-patch-id: d6cb4e69f7f34c39cd831a27115d9555624cff3a
prerequisite-patch-id: cda7b586a4ddbbe74bb4c4fc009d8abad8d4d8c8
prerequisite-patch-id: a6160f3a56107ab8f60a909a56c107b3d415a2b2
prerequisite-patch-id: 226b3f5969ad48e261d8c4b6b2290b615e4248c0
prerequisite-patch-id: 4a80e82bd4d0fa45f99e7ef64f27fb4372f7098d
prerequisite-patch-id: 343ec305fe3cfc25f838bc2403c0cbee4ef231d4
prerequisite-patch-id: 0cf6e92e4b54da57c182b7b1c75c2885b80d3625
prerequisite-patch-id: 563204fa63c2f3817813833a8225aefee4830b89
prerequisite-patch-id: e06389031f40b9281347af3c333392c5771cf8dd
prerequisite-patch-id: a2f066e544fad08fd4eacf418d0e0ddb8a5824bc
prerequisite-patch-id: 89f5877a59242b0aa6639a56a76786d81a31fd12
prerequisite-patch-id: eb0082470384181e2130572801c0603e482659e5
prerequisite-patch-id: a0f166d8fa37fcecb6a5715fe5a9251f264b6138
prerequisite-patch-id: ac6b204146bc1bd9adbd17d4b4b6b94086efc94d
prerequisite-patch-id: 4b7e016967819dec90211a45b7c8108cb5183c8c
prerequisite-patch-id: d4668537fbec4151431559896709edc89a568d66
prerequisite-patch-id: 1ab4069259ba9b2b7268c1adacf01b3d279072cc
prerequisite-patch-id: 353d9ef33d3578d7bce5bebd6e75f90fd34bf074
prerequisite-patch-id: cf0459efd975d369395303af0cf32fa11928fc12
prerequisite-patch-id: 80ae4bee6e8845b78abb8aafd2c7e1ebc9b65a2a
prerequisite-patch-id: 215cf62d492b20ead116832c777225475016bd56
prerequisite-patch-id: bb603532ef61c78b8da48d4b01d2e33638823792
prerequisite-patch-id: 1d3947887302f62bec2290bcff455d64d2f9cd2b
prerequisite-patch-id: 80221c8bbebdd43d405d0dd74f0f0ce908ad0a64
prerequisite-patch-id: 45195dda6f397648bde6326a214d38b24fc62260
prerequisite-patch-id: c316914e8322c2158abc8314448c8606455be3d3
prerequisite-patch-id: 78ab02a24bda5817aa2bd350ca7addc05cc1b9e5
prerequisite-patch-id: dc651cfeafa388b64e813ed167844f545bedfe67
prerequisite-patch-id: 84654c84cf34c228bbe0298d2646a014a0c86d5c
prerequisite-patch-id: e4883cbf3decded286b35b73d5875d38f53d92b4
prerequisite-patch-id: 42522e48cb9678e40037f93573569ca741852e32
prerequisite-patch-id: 289e0cb785aec51623d2e477824f7b0610af3247
prerequisite-patch-id: beaf589f2fad05f33763d485e60bbc9c657023d6
prerequisite-patch-id: 91320847959a6c77f36b226468906884a77d8ce4
prerequisite-patch-id: b645be536e6a1bf764c33de98fa7f125d1658f6c
prerequisite-patch-id: bc6dce8e2dc3f982daa58995b57b21c5d2a9b062
prerequisite-patch-id: 64f2941c1c07082db0b22296cd82249b1f80e20a
prerequisite-patch-id: 4a0305a86a7de3a10617d91281bf01a958deba36
prerequisite-patch-id: 8560eb6bb8a3ecf9879a2af5319dac884fec247d
prerequisite-patch-id: c6b1a4dd8857cae512e864ba5c4250965edc3081
prerequisite-patch-id: f023cea0776dc6410a46fa378ee177989af49ba7
prerequisite-patch-id: a09825b59eda893ea4e300bd489329072cf7fb3f
prerequisite-patch-id: d65a308395cc0e696bad627110f97d0799c1a7a6
prerequisite-patch-id: 1f0803cf6816970449745cc5bcfe175ec7399e12
prerequisite-patch-id: 744097e56bdbb907dab4291f6c7b19979a7a4306
prerequisite-patch-id: 0f8f9a6daa1917ddb2145a754a8476db263ce529
prerequisite-patch-id: 110cd5ef402e87b87fc21ace4863b58ff8724ac6
prerequisite-patch-id: 2b8373bbca5155acbd78fdc82d251b650398a55b
prerequisite-patch-id: 3e52220aecf6f7125a5e46502fe3c541161ad8ef
prerequisite-patch-id: f755e8d6302012e03c5707ca50905a652a1e7c5c
prerequisite-patch-id: c98250c473ce2a36cfeee9d6e5174c335d8d2556
prerequisite-patch-id: 5f5514a96a0f8d93a1aaea6a9675d307859f0613
prerequisite-patch-id: 6a97495f22f994aa12c1f04c27969c6feefe1f17
prerequisite-patch-id: d8066c801b7e329526cd8acee6d26bededcc76c9
prerequisite-patch-id: ee4959731689961bcbd9bca63c71287e26e87827
prerequisite-patch-id: 52da141be6ca6bd5c80979392e7f0100ee977ce0
prerequisite-patch-id: 7b5047edfd7cd3123e619c2d4d4f181f540fae2f
prerequisite-patch-id: c6a55394d3c375e9bc3c4292369b5895ddc59f86
prerequisite-patch-id: f10c2b2ba00790b03b529dc1d53827cbadfed00c
prerequisite-patch-id: 95b127cc1d511ea8294833987364af2cee7a7bb6
prerequisite-patch-id: 4e6881cb545c0651e1cefac099222008c5968a1c
prerequisite-patch-id: 3629d181497765e133a9937e3bf9ab2115b29d7f
prerequisite-patch-id: 808efdf345e2c2e9348825056792b9ebd7df569b
prerequisite-patch-id: 5c083492e95d31876d4fd37fb9bc71e9ab476678
prerequisite-patch-id: 52880749a3f50f34e375e6c85edb47214a2db507
prerequisite-patch-id: 70da7ee7d8053f6e276b32539e1bed798cb32c16
prerequisite-patch-id: 4257e6500bb74574b175dab9e1d0747c22f496a1
prerequisite-patch-id: 2ce90fb9c9463ae0c8431ef9d716d2b0209f4ba9
prerequisite-patch-id: 56ad46fdd2d74bb17f5a3e26738c1037a0a1670f
prerequisite-patch-id: c44191d1a65ca26ef376969e02b17f63d0d9c323
prerequisite-patch-id: da304def18e67d3c76f313320c1a0ee26dce7dc6
prerequisite-patch-id: 258c64e7b8a816b8514703fa3e6f5cc0d654fe9d
prerequisite-patch-id: 54cc0917cb997057bfc5647265b40eb44b336d0a
prerequisite-patch-id: 0207eb3c22a80599325494e61af83ca645b0fc29
prerequisite-patch-id: ece560be87bc959ec4ca3a1885ee055e49901a10
prerequisite-patch-id: 26c616d39e2e374d28a603c40167c4b0752c8143
prerequisite-patch-id: 3626efcb60b67ee70bb82a6500a4639700b6b04d
prerequisite-patch-id: e26dcbc1ccb8d5c03f501de53a85a484f882f949
prerequisite-patch-id: 7d5d296bb61199e940f0252ae60abbb3abbcd95b
prerequisite-patch-id: 5f04cf5823a647065cfc98bb222576db5b11bb47
prerequisite-patch-id: 1a9306b73086a8ea746cb48fc859bc8079dbd5da
prerequisite-patch-id: 186eacd51ca3d33a64844085fe9d1b5790d0a1e2
prerequisite-patch-id: 0e5078d7d65f800bebad5dd1ba8aa160d1d1d430
prerequisite-patch-id: 6ef0875cbb97bcdcf14249b7c15f96510c965242
prerequisite-patch-id: 49a4b72da2824e22105e741e48da8b430a7c04c0
prerequisite-patch-id: dfe5e1a51be03628b1620f9fb1807100c251f949
prerequisite-patch-id: dbd16a808427a8fd8f6f554ea3a3cfdbe148eb7e
prerequisite-patch-id: 06a40ba9a71f7625b5427ab12acbf55ca5321e49
prerequisite-patch-id: c7579c5eabbfcfe6d087ab77c408cf7e38046d1c
prerequisite-patch-id: eb5c09d47a2c1fea64808cb7eaf8e1cbb799c609
prerequisite-patch-id: 7bcf806c61bd1341f44dc856c2ed2d95e8ccaaa8
prerequisite-patch-id: 38873a4b0dc0f6fad4a32abc7715ab89350bda24
prerequisite-patch-id: d1be1acfe075d4dedb792f271e50cc18f27224c6
prerequisite-patch-id: 33e7bfe8838bca1f7c890f6fd81318ffa024a776
prerequisite-patch-id: b7c60c9e566e2283c497c67e39dc2419ec607bb0
prerequisite-patch-id: d0e11ca1dcb7b011d327163a50bd8e0a960e6b0d
prerequisite-patch-id: 231d20732e5d04d8c8f3a1157bd78e504afae44d
prerequisite-patch-id: fe1b4f13f8c16018e08d79d958c573367bed84ce
prerequisite-patch-id: 37be15216ed829861a0cea31db2ba860d3f55083
prerequisite-patch-id: 8e896e22f3b16d02064364c40f786c0bf6977871
prerequisite-patch-id: f99eab853b8dc14491d90afafc7a3c3652c50a9a
prerequisite-patch-id: 9c9c0822330e6b437b201c0c549fdc7d966dfaa3
prerequisite-patch-id: 3eb43015756b6396004c533c4d802c188ee65520
prerequisite-patch-id: 1bd961fa9b86de4ac0cde21975e7faa2ce8073f9
prerequisite-patch-id: c15578279e6f2e2b54b6798be1c22c16d34ab634
prerequisite-patch-id: dfc8f401c28e95e955d57e0e94f4a7b379830c6e
prerequisite-patch-id: bc8bb4a341771e0446a5c2bdfc005907b83c65c6
prerequisite-patch-id: 4a39e2f925bd9f2a6b7fbb0e6ff8c5fb58543fca
prerequisite-patch-id: 635feb3938bf23e9c4de5fd91478019cc1222600
prerequisite-patch-id: 1988e49e1b74a0cd3c66ff2e34243c1a9e62de61
prerequisite-patch-id: da3d59e7e3c482e921e5b907c1b955d1d44852ab
prerequisite-patch-id: 4bb69ddb5fe9bc833e1353d91f6adcf28c3e238d
prerequisite-patch-id: 6ad8a6be52c1db0522db94c470aae3c8f8b8e4aa
prerequisite-patch-id: 967f03199eb21ff4c6c088d2c6d39a9925f87c81
prerequisite-patch-id: 82bc77e9415e8fdaf2333c2b56df82286702414e
prerequisite-patch-id: c86342d002dc1076359e81b6aedd90ec5a9e378a
prerequisite-patch-id: 0ae51fab4abff566ea3f3ba6f33b1923030fb08b
prerequisite-patch-id: 5a587ab40f8b4d3e31f38f9795f639dccc9dd31e
prerequisite-patch-id: 34e270872fb90cd6db2b8e6d60d8e9e7bcfd42e9
prerequisite-patch-id: db18756ab2a6fd5838469154495b7a8b7f5edfbe
prerequisite-patch-id: 94990f61fa42211116247d2e109d75eaababaf6f
prerequisite-patch-id: 48d6b255c072b11293d7793b7f27cef52bf98ae7
prerequisite-patch-id: 772b565df0fd413a8d8c3b14eaf4a5103dee61f8
prerequisite-patch-id: 69ec86be151a329e261e57def85374a692ac7f10
prerequisite-patch-id: e4fc22921228ceaad3854c6e21a9451113c781ad
prerequisite-patch-id: 2a73f1aa2e8af14900a114795328079f49b050d8
prerequisite-patch-id: 068f5960eccfbf57c016d512e644a5417d3de61d
prerequisite-patch-id: b9a49884113095b234a5e2a2e4c07afe40ad705b
prerequisite-patch-id: 1a71fe2ee32005fcc7e558b0fa0e385f89f15da9
prerequisite-patch-id: 368da9d5593dc4400a1e1c706c33bb02d142f964
prerequisite-patch-id: dc1470cd9745de64ce0bda1cbbb53e713bab699d
prerequisite-patch-id: 456c92b9c32317114c4182fab04426993a8b6d76
prerequisite-patch-id: 64d00e62fa6c6a3991020b3f7448ce3c17799bc8
prerequisite-patch-id: 256fe9a91ac7436449e451d7c6ebb0743e9fcdd5
prerequisite-patch-id: 908715555dcaed256b51998e61e72ad003271016
prerequisite-patch-id: a18bfa1916549a7c8572315cb46924bdf911913d
prerequisite-patch-id: 4c59688d574e6661689f9574f717b70f43770311
prerequisite-patch-id: 0d9d1406095ba144da2dd41bbb5c3eed9233bf03
prerequisite-patch-id: 79c22da5a20d67cab349486549c096147e7b3b2f
prerequisite-patch-id: 3716d2b4fd58e4db672690e47659ab5cc5e03150
prerequisite-patch-id: 64e808f6a830534c54f9ca143c91198c6c7c0066
prerequisite-patch-id: 0f145e51c806a5a6ca12ce8f2b107829d0657a64
prerequisite-patch-id: d0185272ffecf89bb3f455b8656cde91616aa262
prerequisite-patch-id: fd49afde7ff732254e826f7c2080a5536f213fe1
prerequisite-patch-id: f61c3e289fb57efdba6e3ded6d3d52c012653fbe
prerequisite-patch-id: 5c93ae8186de5d285fb20e30578e37875cebd8e4
prerequisite-patch-id: e1e70da2210edb0f442df55b849559349de783e5
prerequisite-patch-id: c9c016ad03a0833c36c3e97b62d946b636d20566
prerequisite-patch-id: 54b7455b92cce0ec81c080b64729273c3ee37c6c
prerequisite-patch-id: 61cdbd1b73934576f870728c4de2168fbf2f070d
prerequisite-patch-id: 1264eef4586a975ee437ca7e18eebebee3e76181
prerequisite-patch-id: 39bf5f221647ca7fb5f650b82bdda9936672e7d3
prerequisite-patch-id: 4ac11d1dd1c13ddcdab054d76ba998ddd19bf3ba
prerequisite-patch-id: 5e53924569be95445dfb6e08fa37b75194515194
prerequisite-patch-id: 2b4edf6acd351d77502ddc6c3d2b2f577bb3ff80
prerequisite-patch-id: 1f142e4a92fd1215b7aa3e9332ac94e62c83023c
prerequisite-patch-id: 02dd17b5e79f217c98e7c285c0d317f336b950cf
prerequisite-patch-id: d5cfbca6c735c1624d217358e18ef0daec68d878
prerequisite-patch-id: 1a1f575066e1d4e8952601fe8713c5cc5f3a55fe
prerequisite-patch-id: 47ccd4c5b5e48b58883151c11fccb8d306f48981
prerequisite-patch-id: 272cc1b6a3955978c0ff0105e65bedefb8f32969
prerequisite-patch-id: 2d2cadc5c4bf6c9024be505f0e86138ee53768ff
prerequisite-patch-id: 3ac36395b22c57406ea22ee79d63e520c754dc5f
prerequisite-patch-id: abf1b936b8b8424152aa7584c437529aa0cc1fb9
prerequisite-patch-id: 75272b5661f28bdcd43a0bc5f47814db8dffee16
prerequisite-patch-id: f9de331dc4eb1fbea6107bf09acca296b074f076
prerequisite-patch-id: 52e159b7690931f4fa559c009a3d46f53f4970ed
prerequisite-patch-id: dc6f0271ec6b456a83b41ae0fb8f2def404a71cc
prerequisite-patch-id: 94cf00b99d77885f67c7a0ff09cd8340c58eb93d
prerequisite-patch-id: 0bfcc47b69dff593739f568fb1e4faea29bb3c65
prerequisite-patch-id: cc1bdccfea7ef6c0c824b6d638483f6388d00103
prerequisite-patch-id: ef29ed952f1794c72ad83214c4500948a28d8d4a
prerequisite-patch-id: 7f48d05a818e6e27b7265da0b6506bbfd4dcbcf7
prerequisite-patch-id: 046797094a5160fce717052283837866498de197
prerequisite-patch-id: f398f0da4cb15469a41f8e2e4ceb00e2bc84dfa8
prerequisite-patch-id: 369df977dcf9bd21deac2b3cb5e3e39ced9fd67c
prerequisite-patch-id: e5204558f65384cf5d8d5d8bdfc03c2044b55da7
prerequisite-patch-id: 1564b62bd189c64e49d817a498dd8bb4d12108e3
prerequisite-patch-id: d4350b0342f878e0d64e63adb056096bb13a8a99
prerequisite-patch-id: 7e4b10af07b60ea5c15e2680484f4bf215929564
prerequisite-patch-id: 3f6e689898d0ed1a3ead4d39d38dfc9c69b753fb
prerequisite-patch-id: 0fdd7f3ae396245781d4ae78c69ff52391aaa4ee
prerequisite-patch-id: 3b9e408672861b275f6a8648b308e1cfeb034758
prerequisite-patch-id: 3cec868e45b1041dff11a8e900694160627f2419
prerequisite-patch-id: e4ecc3221475fa2e0c8c286aefa22f6c3d39ff3d
prerequisite-patch-id: 249cae2ba018c0234d5366626e37d212dfac1293
prerequisite-patch-id: feeffbc048facb2cd81081ad99230c98a8521e58
prerequisite-patch-id: 2a307e1353ae67d1ecf55d7d70da10304bc28506
prerequisite-patch-id: 53d9c0283ecbe385ded6dd1e3dd4c7a2425a6550
prerequisite-patch-id: 29df8ce1d251b78e248b36aee536494e35c59e1c
prerequisite-patch-id: 5a654be46f1bf63e927d5638479adcd504db4fb0
prerequisite-patch-id: e80f97b5e12287341abf3b3dc8cdbda6c4d74605
prerequisite-patch-id: c86c568c9400699a3836b2c41cc621a54eeed9ef
prerequisite-patch-id: e29570d9e33d3487510b345a74b073123f5da3b2
prerequisite-patch-id: 5a20e3fcd8b7744ab65925b3a41adb46f44280ca
prerequisite-patch-id: 677e94f583c68be11e7ee02cca38dacc4e63f38c
prerequisite-patch-id: 89670164d58c60374c2198922636f8e56daa55dd
prerequisite-patch-id: 156e248b41ceca167a9144d55f0c004848cac472
prerequisite-patch-id: 3bea24f60b9ae48b0e006adc2fdc6f20e9eeed50
prerequisite-patch-id: 7104afe86fa6f723fb0926373a43fe87d6231d96
prerequisite-patch-id: 5d100d83277dda72b9fa838b70c287c9483e106c
prerequisite-patch-id: d87f9672212fefae5ee62a08e96c0f0cc6a234f5
prerequisite-patch-id: 389f89091b9a4b72af227f1cfa48deb3702130bc
prerequisite-patch-id: a792cc4ddd9ed2ddce25e54cd00b456fa550ec40
prerequisite-patch-id: 6c3425158924ba27dc4bf5f1cc2232a6ccbfcbb7
prerequisite-patch-id: 2a2c63e9ee6e3f4050517891727ad8b37d87d1bd
prerequisite-patch-id: f50aca0aac66b918885cabf1cac0a068a5f378e0
prerequisite-patch-id: c4a882be24d173f87d2adf5997803dae9f523acf
prerequisite-patch-id: fd852e79b93c5cc8722ba7738775d2380355fbdb
prerequisite-patch-id: 7ccf4291026b9a829a1169a1aec97884b9552d89
prerequisite-patch-id: be7555fdca1c0e86a4f8f3c764c4c7a017f7abb4
prerequisite-patch-id: f14ac614f8fb47e0ab48d8d12ae27c2c7b1e59ac
prerequisite-patch-id: 674f2207a2bc68eddd45d1a53f09bf233f02d67e
prerequisite-patch-id: c2b6682870606e6bd85c0f9abee5142927c52646
prerequisite-patch-id: 82495a86f23714f33a028387d216e6392af1540d
prerequisite-patch-id: 9d93195954be79a1a20509de864a5b073eb3ce41
prerequisite-patch-id: c8bd4da6601c2bca416c0e4ed3486792ab4498a0
prerequisite-patch-id: f3df35aedc3f9f10844d785a48313c77816433a2
prerequisite-patch-id: 97d37f851724f13de4406210ffe3785a5123ce6f
prerequisite-patch-id: b064d96e661fb886cc1e75dc793cadc34dca1c29
prerequisite-patch-id: 823ae0d18c59a737a2733bfcea3d3c5c6f99e366
prerequisite-patch-id: dc790a2cfbf8d6ece082b5bf5a971ef4f1bfc49c
prerequisite-patch-id: cb36edf11e41b7987824cd7b546560bf1f3e877b
prerequisite-patch-id: cb55cf16a8baa3799403348fb9260f55809040d6
prerequisite-patch-id: 7a6dd6e747d49f67cfd1475f28253d8b253c8fd1
prerequisite-patch-id: a827e3c63d7082e11352cfa44d98c407a0ad3460
prerequisite-patch-id: d9661ace72394feff069245920a1b290d7343b8f
prerequisite-patch-id: b4fd66a12ed592ee574de4b2b47165b7c0f8c7f0
prerequisite-patch-id: 3e4fd2d54c2b2d192eecaaa7dd8a124b6cb1b150
prerequisite-patch-id: 7c9631df4f1fee4c8a19dcd71ad080ef918c29a2
prerequisite-patch-id: b3654f5d17ee0611fd0afb204cf4d1385fcaac8b
prerequisite-patch-id: 7dee8d17b5bc7703ac94ec12e7b8f75df2bea495
prerequisite-patch-id: 0f227d3ee83bc1a7ac23d08339163d5d413e79da
prerequisite-patch-id: 93804e22d88027afd9e56f68b064a544804fceed
prerequisite-patch-id: 283adb283c287a4cfa091972d483bbeac3a1de4b
prerequisite-patch-id: f2774f45e32d951fd98aa02e63594f0061eaca66
prerequisite-patch-id: 67243001e8876ccce16fc95ff4b23cbdb44f5e2e
prerequisite-patch-id: ace6a1955c436888e634014b2334d5ac30d7aede
prerequisite-patch-id: 3287035808a4e27393769f437b1dbaf6df9d046a
prerequisite-patch-id: 1a2d6fddc1abab2643d86689a31d8812a749299e
prerequisite-patch-id: 167505944834139cf3f7091679dd0663d20357bf
prerequisite-patch-id: a6027fa23f4ed0641e79739220ed843d732abca0
prerequisite-patch-id: 89de1ddbb692fe0e6664800cb43ed20af8d2c918
prerequisite-patch-id: 903fa4f4a223a548cc6cc33b1817e39501d70bca
prerequisite-patch-id: 0fe2cdd29953fc364031e2e0b3cd872ea9145571
prerequisite-patch-id: d1c03c3deaf3f31cb1d60b0d1bbed6069fafb156
prerequisite-patch-id: 4d873375ee04d825b4d94d7e01667f7c96e84e50
prerequisite-patch-id: 628d854e3414c0e7082cae9f6d0008d290df87b3

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From oliver.upton at linux.dev  Wed Mar 19 00:01:29 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 19 Mar 2025 00:01:29 -0700
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250318230909.GD9311@nvidia.com>
References: <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
 <20250318230909.GD9311@nvidia.com>
Message-ID: <Z9pryQwy2iwa2bpJ@linux.dev>

On Tue, Mar 18, 2025 at 08:09:09PM -0300, Jason Gunthorpe wrote:
> > It's far more problematic the other way around, e.g. the host knows that
> > something needs a Device-* attribute and the VM has done something
> > cacheable. The endpoint for that PA could, for example, fall over when
> > lines pulled in by the guest are written back, which of course can't
> > always be traced back to the offending VM.
> > 
> > OTOH, if the host knows that a PA is cacheable and the guest does
> > something non-cacheable, you 'just' have to deal with the usual
> > mismatched attributes problem as laid out in the ARM ARM.
> 
> I think the issue is that KVM doesn't do that usual stuff (ie cache
> flushing) for memory that doesn't have a struct page backing.

Indeed, I clearly paged that out. What I said is how we arrived at the
Device-* v. Normal-NC distinction.

> So nothing in the hypervisor does any cache flushing and I belive you
> end up with a situation where the VMM could have zero'd this cachable
> memory using cachable stores to sanitize it across VMs and then KVM
> can put that memory into the VM as uncached and the VM could then
> access stale non-zeroed data from a prior VM. Yes? This is a security
> problem.

Pedantic, but KVM only cares about cache maintenance in response to the
primary MM, not the VMM. After a stage-2 mapping has been established
userspace cannot expect KVM to do cache maintenance on its behalf.

You have a very good point that KVM is broken for cacheable PFNMAP'd
crap since we demote to something non-cacheable, and maybe that
deserves fixing first. Hopefully nobody notices that we've taken away
the toys...

> So I think the logic we want here in the fault handler is to:
>   Get the mm's PTE
>   If it is cachable:
>     Check if it has a struct page:
>        Yes - KVM flushes it and can use a non-FWB path
>        No - KVM either fails to install it, or installs it using FWB
>            to force cachability. KVM never allows degrading cachable
> 	   to non-cachable when it can't do flushing.
>   Not cachable:
>     Install it with Normal-NC as was previously discussed and merged

We still need to test the VMA flag here to select Normal-NC v. Device.

> > Userspace should be stating intentions on the memslot with the sort of
> > mapping that it wants to create, and a memslot flag to say "I allow
> > cacheable mappings" seems to fit the bill.
> 
> I'm not sure about this, I don't see that the userspace has any
> choice. As above, KVM has to follow whatever is in the PTEs, the
> userspace can't ask for something different here. At best you could
> make non-struct page cachable memory always fail unless the flag is
> given - but why?
> 
> It seems sufficient for fast fail to check if the VMA has PFNMAP and
> pgprot cachable then !FEAT_FWB fails the memslot. There is no real
> recovery from this, the VMM is doing something that cannot be
> supported.

I'm less worried about recovery and more focused on userspace being
able to understand what happened. Otherwise we may get folks complaining
about the ioctl failing "randomly" on certain machines.

But we might need to just expose the FWB-ness of the MMU to userspace
since it can already encounter mismatched attributes when poking struct
page-backed guest memory.

Thanks,
Oliver


From daniel.baluta at gmail.com  Wed Mar 19 00:06:17 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 09:06:17 +0200
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <ca734f66-593f-4e7c-bc76-e343a7eb88d7@roeck-us.net>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com> <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>
 <CAEnQRZBmYdLh29ha1FKz8=CbxjFBFFTgDkjrEmwTxW2WcxodfA@mail.gmail.com> <ca734f66-593f-4e7c-bc76-e343a7eb88d7@roeck-us.net>
Message-ID: <CAEnQRZDf_ko2p50EwR6q=dfkwdqE=c7fZe0jO2JdSmbaDa=j3Q@mail.gmail.com>

> >> Is it necessary to make 'pwms' mandatory ? The current code works
> >> just fine with defaults.
> >
> > The code adding OF support is added just in the next patch, so the
> > current code isn't event
> > probed when trying to use dts.
> >
> > Or am I missing something?
> >
>
> The patch introducing devicetree support to the driver doesn't evaluate
> the pwm property. That makes it quite obvious that, from driver perspective,
> it isn't needed. I don't immediately see why it would add value to _force_
> users to provide pwm frequency, polarity, and the output configuration
> if the defaults work just fine.
>


Got your point now! Thanks.


From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:45 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:45 +0800
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

Add clock IDs for the mclk pads found on s4 SoCs

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/dt-bindings/clock/axg-audio-clkc.h b/include/dt-bindings/clock/axg-audio-clkc.h
index 607f23b83fa7287fe0403682ebf827e2df26a1ce..75dde05343d1fa74304ee21c9ec0541a8f51b15e 100644
--- a/include/dt-bindings/clock/axg-audio-clkc.h
+++ b/include/dt-bindings/clock/axg-audio-clkc.h
@@ -162,5 +162,16 @@
 #define AUD_CLKID_EARCRX_DMAC_SEL	182
 #define AUD_CLKID_EARCRX_DMAC_DIV	183
 #define AUD_CLKID_EARCRX_DMAC		184
+#define AUD_CLKID_TDM_MCLK_PAD0_SEL     185
+#define AUD_CLKID_TDM_MCLK_PAD1_SEL     186
+#define AUD_CLKID_TDM_MCLK_PAD0_DIV     187
+#define AUD_CLKID_TDM_MCLK_PAD1_DIV     188
+#define AUD_CLKID_TDM_MCLK_PAD2         189
+#define AUD_CLKID_TDM_MCLK_PAD2_SEL     190
+#define AUD_CLKID_TDM_MCLK_PAD2_DIV     191
+#define AUD_CLKID_TDM_SCLK_PAD3		192
+#define AUD_CLKID_TDM_SCLK_PAD4		193
+#define AUD_CLKID_TDM_LRCLK_PAD3	194
+#define AUD_CLKID_TDM_LRCLK_PAD4	195
 
 #endif /* __AXG_AUDIO_CLKC_BINDINGS_H */

-- 
2.43.0




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:44 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:44 +0800
Subject: [PATCH v4 1/6] dt-bindings: clock: meson: Add audio power domain
 for s4 soc
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-1-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

Audio power domain found on S4 device.it need to enable before audio work.

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 .../bindings/clock/amlogic,axg-audio-clkc.yaml       | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
index fd7982dd4ceab82389167079c2258a9acff51a76..50a5cbb6eb64873dd5aa55f6f1a63e9e97542760 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
+++ b/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml
@@ -21,6 +21,7 @@ properties:
       - amlogic,axg-audio-clkc
       - amlogic,g12a-audio-clkc
       - amlogic,sm1-audio-clkc
+      - amlogic,s4-audio-clkc
 
   '#clock-cells':
     const: 1
@@ -29,7 +30,7 @@ properties:
     const: 1
 
   reg:
-    maxItems: 1
+    maxItems: 2
 
   clocks:
     minItems: 1
@@ -100,6 +101,9 @@ properties:
   resets:
     description: internal reset line
 
+  power-domains:
+      maxItems: 1
+
 required:
   - compatible
   - '#clock-cells'
@@ -116,12 +120,26 @@ allOf:
             enum:
               - amlogic,g12a-audio-clkc
               - amlogic,sm1-audio-clkc
+              - amlogic,s4-audio-clkc
     then:
       required:
         - '#reset-cells'
     else:
       properties:
         '#reset-cells': false
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,s4-audio-clkc
+    then:
+      required:
+        - power-domains
+
+    else:
+      properties:
+        power-domains: false
 
 additionalProperties: false
 

-- 
2.43.0




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:48 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:48 +0800
Subject: [PATCH v4 5/6] clk: meson: axg-audio: Add the mclk pad div for s4
 chip
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-5-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

Add mclk pad div support, Increased the number of lrclk
and sclk pads to five

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 drivers/clk/meson/axg-audio.c | 441 +++++++++++++++++++++++++++++++++++++++++-
 drivers/clk/meson/axg-audio.h |   6 +
 2 files changed, 445 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 9df627b142f89788966ede0262aaaf39e13f0b49..50e7c78ddb98ee08121690633c8113489503bc04 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -323,6 +323,16 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
 	AUD_MUX(_name, _reg, 0x7, _shift, 0, _parents,		\
 		CLK_SET_RATE_NO_REPARENT)
 
+#define AUD_MCLK_PAD_MUX(_name, _reg, _shift)					\
+	AUD_MUX(_name##_sel, _reg, 0x7, _shift, CLK_MUX_ROUND_CLOSEST,			\
+		mclk_pad_ctrl_parent_data, 0)
+#define AUD_MCLK_PAD_DIV(_name, _reg, _shift)					\
+	AUD_DIV(_name##_div, _reg, _shift, 8, CLK_DIVIDER_ROUND_CLOSEST,			\
+		aud_##_name##_sel, CLK_SET_RATE_PARENT)
+#define AUD_MCLK_PAD_GATE(_name, _reg, _shift)					\
+	AUD_GATE(_name, _reg, _shift, aud_##_name##_div,			\
+		 CLK_SET_RATE_PARENT)
+
 /* Common Clocks */
 static struct clk_regmap ddr_arb =
 	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
@@ -826,6 +836,49 @@ static struct clk_regmap sm1_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
 static struct clk_regmap sm1_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
 	tdm_sclk_pad_2, AUDIO_SM1_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
 
+static struct clk_regmap s4_tdm_mclk_pad0_sel =
+	AUD_MCLK_PAD_MUX(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 8);
+static struct clk_regmap s4_tdm_mclk_pad1_sel =
+	AUD_MCLK_PAD_MUX(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 24);
+static struct clk_regmap s4_tdm_mclk_pad2_sel =
+	AUD_MCLK_PAD_MUX(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 8);
+
+static struct clk_regmap s4_tdm_mclk_pad0_div =
+	AUD_MCLK_PAD_DIV(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 0);
+static struct clk_regmap s4_tdm_mclk_pad1_div =
+	AUD_MCLK_PAD_DIV(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 16);
+static struct clk_regmap s4_tdm_mclk_pad2_div =
+	AUD_MCLK_PAD_DIV(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 0);
+
+static struct clk_regmap s4_tdm_mclk_pad_0 =
+	AUD_MCLK_PAD_GATE(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 15);
+static struct clk_regmap s4_tdm_mclk_pad_1 =
+	AUD_MCLK_PAD_GATE(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 31);
+static struct clk_regmap s4_tdm_mclk_pad_2 =
+	AUD_MCLK_PAD_GATE(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 15);
+
+static struct clk_regmap s4_tdm_sclk_pad_0 =
+	AUD_TDM_PAD_CTRL(tdm_sclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL0, 0, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_sclk_pad_1 =
+	AUD_TDM_PAD_CTRL(tdm_sclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL0, 4, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_sclk_pad_2 =
+	AUD_TDM_PAD_CTRL(tdm_sclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL0, 8, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_sclk_pad_3 =
+	AUD_TDM_PAD_CTRL(tdm_sclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL0, 16, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_sclk_pad_4 =
+	AUD_TDM_PAD_CTRL(tdm_sclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL0, 20, lrclk_pad_ctrl_parent_data);
+
+static struct clk_regmap s4_tdm_lrclk_pad_0 =
+	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL1, 0, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_lrclk_pad_1 =
+	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL1, 4, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_lrclk_pad_2 =
+	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL1, 8, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_lrclk_pad_3 =
+	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL1, 16, lrclk_pad_ctrl_parent_data);
+static struct clk_regmap s4_tdm_lrclk_pad_4 =
+	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL1, 20, lrclk_pad_ctrl_parent_data);
+
 /*
  * Array of all clocks provided by this provider
  * The input clocks of the controller will be populated at runtime
@@ -1257,6 +1310,177 @@ static struct clk_hw *sm1_audio_hw_clks[] = {
 	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
 };
 
+/*
+ * Array of all S4 clocks provided by this provider
+ * The input clocks of the controller will be populated at runtime
+ */
+static struct clk_hw *s4_audio_hw_clks[] = {
+	[AUD_CLKID_DDR_ARB]		= &ddr_arb.hw,
+	[AUD_CLKID_PDM]			= &pdm.hw,
+	[AUD_CLKID_TDMIN_A]		= &tdmin_a.hw,
+	[AUD_CLKID_TDMIN_B]		= &tdmin_b.hw,
+	[AUD_CLKID_TDMIN_C]		= &tdmin_c.hw,
+	[AUD_CLKID_TDMIN_LB]		= &tdmin_lb.hw,
+	[AUD_CLKID_TDMOUT_A]		= &tdmout_a.hw,
+	[AUD_CLKID_TDMOUT_B]		= &tdmout_b.hw,
+	[AUD_CLKID_TDMOUT_C]		= &tdmout_c.hw,
+	[AUD_CLKID_FRDDR_A]		= &frddr_a.hw,
+	[AUD_CLKID_FRDDR_B]		= &frddr_b.hw,
+	[AUD_CLKID_FRDDR_C]		= &frddr_c.hw,
+	[AUD_CLKID_TODDR_A]		= &toddr_a.hw,
+	[AUD_CLKID_TODDR_B]		= &toddr_b.hw,
+	[AUD_CLKID_TODDR_C]		= &toddr_c.hw,
+	[AUD_CLKID_LOOPBACK]		= &loopback.hw,
+	[AUD_CLKID_SPDIFIN]		= &spdifin.hw,
+	[AUD_CLKID_SPDIFOUT]		= &spdifout.hw,
+	[AUD_CLKID_RESAMPLE]		= &resample.hw,
+	[AUD_CLKID_SPDIFOUT_B]		= &spdifout_b.hw,
+	[AUD_CLKID_MST_A_MCLK_SEL]	= &sm1_mst_a_mclk_sel.hw,
+	[AUD_CLKID_MST_B_MCLK_SEL]	= &sm1_mst_b_mclk_sel.hw,
+	[AUD_CLKID_MST_C_MCLK_SEL]	= &sm1_mst_c_mclk_sel.hw,
+	[AUD_CLKID_MST_D_MCLK_SEL]	= &sm1_mst_d_mclk_sel.hw,
+	[AUD_CLKID_MST_E_MCLK_SEL]	= &sm1_mst_e_mclk_sel.hw,
+	[AUD_CLKID_MST_F_MCLK_SEL]	= &sm1_mst_f_mclk_sel.hw,
+	[AUD_CLKID_MST_A_MCLK_DIV]	= &sm1_mst_a_mclk_div.hw,
+	[AUD_CLKID_MST_B_MCLK_DIV]	= &sm1_mst_b_mclk_div.hw,
+	[AUD_CLKID_MST_C_MCLK_DIV]	= &sm1_mst_c_mclk_div.hw,
+	[AUD_CLKID_MST_D_MCLK_DIV]	= &sm1_mst_d_mclk_div.hw,
+	[AUD_CLKID_MST_E_MCLK_DIV]	= &sm1_mst_e_mclk_div.hw,
+	[AUD_CLKID_MST_F_MCLK_DIV]	= &sm1_mst_f_mclk_div.hw,
+	[AUD_CLKID_MST_A_MCLK]		= &sm1_mst_a_mclk.hw,
+	[AUD_CLKID_MST_B_MCLK]		= &sm1_mst_b_mclk.hw,
+	[AUD_CLKID_MST_C_MCLK]		= &sm1_mst_c_mclk.hw,
+	[AUD_CLKID_MST_D_MCLK]		= &sm1_mst_d_mclk.hw,
+	[AUD_CLKID_MST_E_MCLK]		= &sm1_mst_e_mclk.hw,
+	[AUD_CLKID_MST_F_MCLK]		= &sm1_mst_f_mclk.hw,
+	[AUD_CLKID_SPDIFOUT_CLK_SEL]	= &spdifout_clk_sel.hw,
+	[AUD_CLKID_SPDIFOUT_CLK_DIV]	= &spdifout_clk_div.hw,
+	[AUD_CLKID_SPDIFOUT_CLK]	= &spdifout_clk.hw,
+	[AUD_CLKID_SPDIFOUT_B_CLK_SEL]	= &spdifout_b_clk_sel.hw,
+	[AUD_CLKID_SPDIFOUT_B_CLK_DIV]	= &spdifout_b_clk_div.hw,
+	[AUD_CLKID_SPDIFOUT_B_CLK]	= &spdifout_b_clk.hw,
+	[AUD_CLKID_SPDIFIN_CLK_SEL]	= &spdifin_clk_sel.hw,
+	[AUD_CLKID_SPDIFIN_CLK_DIV]	= &spdifin_clk_div.hw,
+	[AUD_CLKID_SPDIFIN_CLK]		= &spdifin_clk.hw,
+	[AUD_CLKID_PDM_DCLK_SEL]	= &pdm_dclk_sel.hw,
+	[AUD_CLKID_PDM_DCLK_DIV]	= &pdm_dclk_div.hw,
+	[AUD_CLKID_PDM_DCLK]		= &pdm_dclk.hw,
+	[AUD_CLKID_PDM_SYSCLK_SEL]	= &pdm_sysclk_sel.hw,
+	[AUD_CLKID_PDM_SYSCLK_DIV]	= &pdm_sysclk_div.hw,
+	[AUD_CLKID_PDM_SYSCLK]		= &pdm_sysclk.hw,
+	[AUD_CLKID_MST_A_SCLK_PRE_EN]	= &mst_a_sclk_pre_en.hw,
+	[AUD_CLKID_MST_B_SCLK_PRE_EN]	= &mst_b_sclk_pre_en.hw,
+	[AUD_CLKID_MST_C_SCLK_PRE_EN]	= &mst_c_sclk_pre_en.hw,
+	[AUD_CLKID_MST_D_SCLK_PRE_EN]	= &mst_d_sclk_pre_en.hw,
+	[AUD_CLKID_MST_E_SCLK_PRE_EN]	= &mst_e_sclk_pre_en.hw,
+	[AUD_CLKID_MST_F_SCLK_PRE_EN]	= &mst_f_sclk_pre_en.hw,
+	[AUD_CLKID_MST_A_SCLK_DIV]	= &mst_a_sclk_div.hw,
+	[AUD_CLKID_MST_B_SCLK_DIV]	= &mst_b_sclk_div.hw,
+	[AUD_CLKID_MST_C_SCLK_DIV]	= &mst_c_sclk_div.hw,
+	[AUD_CLKID_MST_D_SCLK_DIV]	= &mst_d_sclk_div.hw,
+	[AUD_CLKID_MST_E_SCLK_DIV]	= &mst_e_sclk_div.hw,
+	[AUD_CLKID_MST_F_SCLK_DIV]	= &mst_f_sclk_div.hw,
+	[AUD_CLKID_MST_A_SCLK_POST_EN]	= &mst_a_sclk_post_en.hw,
+	[AUD_CLKID_MST_B_SCLK_POST_EN]	= &mst_b_sclk_post_en.hw,
+	[AUD_CLKID_MST_C_SCLK_POST_EN]	= &mst_c_sclk_post_en.hw,
+	[AUD_CLKID_MST_D_SCLK_POST_EN]	= &mst_d_sclk_post_en.hw,
+	[AUD_CLKID_MST_E_SCLK_POST_EN]	= &mst_e_sclk_post_en.hw,
+	[AUD_CLKID_MST_F_SCLK_POST_EN]	= &mst_f_sclk_post_en.hw,
+	[AUD_CLKID_MST_A_SCLK]		= &mst_a_sclk.hw,
+	[AUD_CLKID_MST_B_SCLK]		= &mst_b_sclk.hw,
+	[AUD_CLKID_MST_C_SCLK]		= &mst_c_sclk.hw,
+	[AUD_CLKID_MST_D_SCLK]		= &mst_d_sclk.hw,
+	[AUD_CLKID_MST_E_SCLK]		= &mst_e_sclk.hw,
+	[AUD_CLKID_MST_F_SCLK]		= &mst_f_sclk.hw,
+	[AUD_CLKID_MST_A_LRCLK_DIV]	= &mst_a_lrclk_div.hw,
+	[AUD_CLKID_MST_B_LRCLK_DIV]	= &mst_b_lrclk_div.hw,
+	[AUD_CLKID_MST_C_LRCLK_DIV]	= &mst_c_lrclk_div.hw,
+	[AUD_CLKID_MST_D_LRCLK_DIV]	= &mst_d_lrclk_div.hw,
+	[AUD_CLKID_MST_E_LRCLK_DIV]	= &mst_e_lrclk_div.hw,
+	[AUD_CLKID_MST_F_LRCLK_DIV]	= &mst_f_lrclk_div.hw,
+	[AUD_CLKID_MST_A_LRCLK]		= &mst_a_lrclk.hw,
+	[AUD_CLKID_MST_B_LRCLK]		= &mst_b_lrclk.hw,
+	[AUD_CLKID_MST_C_LRCLK]		= &mst_c_lrclk.hw,
+	[AUD_CLKID_MST_D_LRCLK]		= &mst_d_lrclk.hw,
+	[AUD_CLKID_MST_E_LRCLK]		= &mst_e_lrclk.hw,
+	[AUD_CLKID_MST_F_LRCLK]		= &mst_f_lrclk.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_SEL]	= &tdmin_a_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_SEL]	= &tdmin_b_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_C_SCLK_SEL]	= &tdmin_c_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_SEL]	= &tdmin_lb_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_SEL]	= &tdmout_a_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_SEL]	= &tdmout_b_sclk_sel.hw,
+	[AUD_CLKID_TDMOUT_C_SCLK_SEL]	= &tdmout_c_sclk_sel.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_PRE_EN]	= &tdmin_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_PRE_EN]	= &tdmin_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_C_SCLK_PRE_EN]	= &tdmin_c_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &tdmin_lb_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &tdmout_a_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &tdmout_b_sclk_pre_en.hw,
+	[AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &tdmout_c_sclk_pre_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &tdmin_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &tdmin_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &tdmin_c_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &tdmin_lb_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &tdmout_a_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &tdmout_b_sclk_post_en.hw,
+	[AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &tdmout_c_sclk_post_en.hw,
+	[AUD_CLKID_TDMIN_A_SCLK]	= &tdmin_a_sclk.hw,
+	[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
+	[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
+	[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
+	[AUD_CLKID_TDMOUT_A_SCLK]	= &g12a_tdmout_a_sclk.hw,
+	[AUD_CLKID_TDMOUT_B_SCLK]	= &g12a_tdmout_b_sclk.hw,
+	[AUD_CLKID_TDMOUT_C_SCLK]	= &g12a_tdmout_c_sclk.hw,
+	[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
+	[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
+	[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
+	[AUD_CLKID_TDMIN_LB_LRCLK]	= &tdmin_lb_lrclk.hw,
+	[AUD_CLKID_TDMOUT_A_LRCLK]	= &tdmout_a_lrclk.hw,
+	[AUD_CLKID_TDMOUT_B_LRCLK]	= &tdmout_b_lrclk.hw,
+	[AUD_CLKID_TDMOUT_C_LRCLK]	= &tdmout_c_lrclk.hw,
+	[AUD_CLKID_TDM_MCLK_PAD0]	= &s4_tdm_mclk_pad_0.hw,
+	[AUD_CLKID_TDM_MCLK_PAD1]	= &s4_tdm_mclk_pad_1.hw,
+	[AUD_CLKID_TDM_LRCLK_PAD0]	= &s4_tdm_lrclk_pad_0.hw,
+	[AUD_CLKID_TDM_LRCLK_PAD1]	= &s4_tdm_lrclk_pad_1.hw,
+	[AUD_CLKID_TDM_LRCLK_PAD2]	= &s4_tdm_lrclk_pad_2.hw,
+	[AUD_CLKID_TDM_SCLK_PAD0]	= &s4_tdm_sclk_pad_0.hw,
+	[AUD_CLKID_TDM_SCLK_PAD1]	= &s4_tdm_sclk_pad_1.hw,
+	[AUD_CLKID_TDM_SCLK_PAD2]	= &s4_tdm_sclk_pad_2.hw,
+	[AUD_CLKID_TOP]			= &sm1_aud_top.hw,
+	[AUD_CLKID_TORAM]		= &toram.hw,
+	[AUD_CLKID_EQDRC]		= &eqdrc.hw,
+	[AUD_CLKID_RESAMPLE_B]		= &resample_b.hw,
+	[AUD_CLKID_TOVAD]		= &tovad.hw,
+	[AUD_CLKID_LOCKER]		= &locker.hw,
+	[AUD_CLKID_SPDIFIN_LB]		= &spdifin_lb.hw,
+	[AUD_CLKID_FRDDR_D]		= &frddr_d.hw,
+	[AUD_CLKID_TODDR_D]		= &toddr_d.hw,
+	[AUD_CLKID_LOOPBACK_B]		= &loopback_b.hw,
+	[AUD_CLKID_CLK81_EN]		= &sm1_clk81_en.hw,
+	[AUD_CLKID_SYSCLK_A_DIV]	= &sm1_sysclk_a_div.hw,
+	[AUD_CLKID_SYSCLK_A_EN]		= &sm1_sysclk_a_en.hw,
+	[AUD_CLKID_SYSCLK_B_DIV]	= &sm1_sysclk_b_div.hw,
+	[AUD_CLKID_SYSCLK_B_EN]		= &sm1_sysclk_b_en.hw,
+	[AUD_CLKID_EARCRX]		= &earcrx.hw,
+	[AUD_CLKID_EARCRX_CMDC_SEL]	= &sm1_earcrx_cmdc_clk_sel.hw,
+	[AUD_CLKID_EARCRX_CMDC_DIV]	= &sm1_earcrx_cmdc_clk_div.hw,
+	[AUD_CLKID_EARCRX_CMDC]		= &sm1_earcrx_cmdc_clk.hw,
+	[AUD_CLKID_EARCRX_DMAC_SEL]	= &sm1_earcrx_dmac_clk_sel.hw,
+	[AUD_CLKID_EARCRX_DMAC_DIV]	= &sm1_earcrx_dmac_clk_div.hw,
+	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
+	[AUD_CLKID_TDM_MCLK_PAD0_SEL]		= &s4_tdm_mclk_pad0_sel.hw,
+	[AUD_CLKID_TDM_MCLK_PAD1_SEL]       = &s4_tdm_mclk_pad1_sel.hw,
+	[AUD_CLKID_TDM_MCLK_PAD0_DIV]		= &s4_tdm_mclk_pad0_div.hw,
+	[AUD_CLKID_TDM_MCLK_PAD1_DIV]       = &s4_tdm_mclk_pad1_div.hw,
+	[AUD_CLKID_TDM_MCLK_PAD2]	        = &s4_tdm_mclk_pad_2.hw,
+	[AUD_CLKID_TDM_MCLK_PAD2_SEL]		= &s4_tdm_mclk_pad2_sel.hw,
+	[AUD_CLKID_TDM_MCLK_PAD2_DIV]       = &s4_tdm_mclk_pad2_div.hw,
+	[AUD_CLKID_TDM_SCLK_PAD3]	= &s4_tdm_sclk_pad_3.hw,
+	[AUD_CLKID_TDM_SCLK_PAD4]	= &s4_tdm_sclk_pad_4.hw,
+	[AUD_CLKID_TDM_LRCLK_PAD3]	= &s4_tdm_lrclk_pad_3.hw,
+	[AUD_CLKID_TDM_LRCLK_PAD4]	= &s4_tdm_lrclk_pad_4.hw,
+};
 
 /* Convenience table to populate regmap in .probe(). */
 static struct clk_regmap *const axg_clk_regmaps[] = {
@@ -1678,6 +1902,177 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
 	&sm1_earcrx_dmac_clk,
 };
 
+static struct clk_regmap *const s4_clk_regmaps[] = {
+	&ddr_arb,
+	&pdm,
+	&tdmin_a,
+	&tdmin_b,
+	&tdmin_c,
+	&tdmin_lb,
+	&tdmout_a,
+	&tdmout_b,
+	&tdmout_c,
+	&frddr_a,
+	&frddr_b,
+	&frddr_c,
+	&toddr_a,
+	&toddr_b,
+	&toddr_c,
+	&loopback,
+	&spdifin,
+	&spdifout,
+	&resample,
+	&spdifout_b,
+	&sm1_mst_a_mclk_sel,
+	&sm1_mst_b_mclk_sel,
+	&sm1_mst_c_mclk_sel,
+	&sm1_mst_d_mclk_sel,
+	&sm1_mst_e_mclk_sel,
+	&sm1_mst_f_mclk_sel,
+	&sm1_mst_a_mclk_div,
+	&sm1_mst_b_mclk_div,
+	&sm1_mst_c_mclk_div,
+	&sm1_mst_d_mclk_div,
+	&sm1_mst_e_mclk_div,
+	&sm1_mst_f_mclk_div,
+	&sm1_mst_a_mclk,
+	&sm1_mst_b_mclk,
+	&sm1_mst_c_mclk,
+	&sm1_mst_d_mclk,
+	&sm1_mst_e_mclk,
+	&sm1_mst_f_mclk,
+	&spdifout_clk_sel,
+	&spdifout_clk_div,
+	&spdifout_clk,
+	&spdifin_clk_sel,
+	&spdifin_clk_div,
+	&spdifin_clk,
+	&pdm_dclk_sel,
+	&pdm_dclk_div,
+	&pdm_dclk,
+	&pdm_sysclk_sel,
+	&pdm_sysclk_div,
+	&pdm_sysclk,
+	&mst_a_sclk_pre_en,
+	&mst_b_sclk_pre_en,
+	&mst_c_sclk_pre_en,
+	&mst_d_sclk_pre_en,
+	&mst_e_sclk_pre_en,
+	&mst_f_sclk_pre_en,
+	&mst_a_sclk_div,
+	&mst_b_sclk_div,
+	&mst_c_sclk_div,
+	&mst_d_sclk_div,
+	&mst_e_sclk_div,
+	&mst_f_sclk_div,
+	&mst_a_sclk_post_en,
+	&mst_b_sclk_post_en,
+	&mst_c_sclk_post_en,
+	&mst_d_sclk_post_en,
+	&mst_e_sclk_post_en,
+	&mst_f_sclk_post_en,
+	&mst_a_sclk,
+	&mst_b_sclk,
+	&mst_c_sclk,
+	&mst_d_sclk,
+	&mst_e_sclk,
+	&mst_f_sclk,
+	&mst_a_lrclk_div,
+	&mst_b_lrclk_div,
+	&mst_c_lrclk_div,
+	&mst_d_lrclk_div,
+	&mst_e_lrclk_div,
+	&mst_f_lrclk_div,
+	&mst_a_lrclk,
+	&mst_b_lrclk,
+	&mst_c_lrclk,
+	&mst_d_lrclk,
+	&mst_e_lrclk,
+	&mst_f_lrclk,
+	&tdmin_a_sclk_sel,
+	&tdmin_b_sclk_sel,
+	&tdmin_c_sclk_sel,
+	&tdmin_lb_sclk_sel,
+	&tdmout_a_sclk_sel,
+	&tdmout_b_sclk_sel,
+	&tdmout_c_sclk_sel,
+	&tdmin_a_sclk_pre_en,
+	&tdmin_b_sclk_pre_en,
+	&tdmin_c_sclk_pre_en,
+	&tdmin_lb_sclk_pre_en,
+	&tdmout_a_sclk_pre_en,
+	&tdmout_b_sclk_pre_en,
+	&tdmout_c_sclk_pre_en,
+	&tdmin_a_sclk_post_en,
+	&tdmin_b_sclk_post_en,
+	&tdmin_c_sclk_post_en,
+	&tdmin_lb_sclk_post_en,
+	&tdmout_a_sclk_post_en,
+	&tdmout_b_sclk_post_en,
+	&tdmout_c_sclk_post_en,
+	&tdmin_a_sclk,
+	&tdmin_b_sclk,
+	&tdmin_c_sclk,
+	&tdmin_lb_sclk,
+	&g12a_tdmout_a_sclk,
+	&g12a_tdmout_b_sclk,
+	&g12a_tdmout_c_sclk,
+	&tdmin_a_lrclk,
+	&tdmin_b_lrclk,
+	&tdmin_c_lrclk,
+	&tdmin_lb_lrclk,
+	&tdmout_a_lrclk,
+	&tdmout_b_lrclk,
+	&tdmout_c_lrclk,
+	&spdifout_b_clk_sel,
+	&spdifout_b_clk_div,
+	&spdifout_b_clk,
+	&sm1_aud_top,
+	&toram,
+	&eqdrc,
+	&resample_b,
+	&tovad,
+	&locker,
+	&spdifin_lb,
+	&frddr_d,
+	&toddr_d,
+	&loopback_b,
+	&sm1_clk81_en,
+	&sm1_sysclk_a_div,
+	&sm1_sysclk_a_en,
+	&sm1_sysclk_b_div,
+	&sm1_sysclk_b_en,
+	&earcrx,
+	&sm1_earcrx_cmdc_clk_sel,
+	&sm1_earcrx_cmdc_clk_div,
+	&sm1_earcrx_cmdc_clk,
+	&sm1_earcrx_dmac_clk_sel,
+	&sm1_earcrx_dmac_clk_div,
+	&sm1_earcrx_dmac_clk,
+};
+
+static struct clk_regmap *const s4_clk_pad_regmaps[] = {
+	&s4_tdm_mclk_pad_0,
+	&s4_tdm_mclk_pad_1,
+	&s4_tdm_mclk_pad_2,
+	&s4_tdm_lrclk_pad_0,
+	&s4_tdm_lrclk_pad_1,
+	&s4_tdm_lrclk_pad_2,
+	&s4_tdm_lrclk_pad_3,
+	&s4_tdm_lrclk_pad_4,
+	&s4_tdm_sclk_pad_0,
+	&s4_tdm_sclk_pad_1,
+	&s4_tdm_sclk_pad_2,
+	&s4_tdm_sclk_pad_3,
+	&s4_tdm_sclk_pad_4,
+	&s4_tdm_mclk_pad0_sel,
+	&s4_tdm_mclk_pad1_sel,
+	&s4_tdm_mclk_pad0_div,
+	&s4_tdm_mclk_pad1_div,
+	&s4_tdm_mclk_pad2_sel,
+	&s4_tdm_mclk_pad2_div,
+};
+
 struct axg_audio_reset_data {
 	struct reset_controller_dev rstc;
 	struct regmap *map;
@@ -1764,13 +2159,20 @@ static struct regmap_config axg_audio_regmap_cfg = {
 
 struct audioclk_data {
 	struct clk_regmap *const *regmap_clks;
+	struct clk_regmap *const *regmap_clks_pads;
 	unsigned int regmap_clk_num;
+	unsigned int regmap_clk_pads_num;
 	struct meson_clk_hw_data hw_clks;
 	unsigned int reset_offset;
 	unsigned int reset_num;
 	unsigned int max_register;
 };
 
+static int audio_clock_pad_is_new_regmap(struct device_node *np)
+{
+	return of_device_is_compatible(np, "amlogic,s4-audio-clkc");
+}
+
 static int axg_audio_clkc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1812,6 +2214,25 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
 	for (i = 0; i < data->regmap_clk_num; i++)
 		data->regmap_clks[i]->map = map;
 
+	/* some amlogic chip clock pad reg domian is different */
+	if (audio_clock_pad_is_new_regmap(dev->of_node)) {
+		struct resource *res;
+		static const struct regmap_config aud_regmap_config = {
+			.reg_bits = 32,
+			.val_bits = 32,
+			.reg_stride = 4,
+		};
+		regs = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
+		if (IS_ERR(regs))
+			return PTR_ERR(regs);
+		aud_regmap_config.max_register = resource_size(res) - 4;
+		aud_regmap_config.name =
+			devm_kasprintf(dev, GFP_KERNEL, "%s-%s", dev->of_node->name, "pads");
+		map = devm_regmap_init_mmio(dev, regs, &aud_regmap_config);
+		/* Populate clk pad regmap for the regmap backed clocks */
+		for (i = 0; i < data->regmap_clk_pads_num; i++)
+			data->regmap_clks_pads[i]->map = map;
+	}
 	/* Take care to skip the registered input clocks */
 	for (i = AUD_CLKID_DDR_ARB; i < data->hw_clks.num; i++) {
 		const char *name;
@@ -1822,7 +2243,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
 			continue;
 
 		name = hw->init->name;
-
 		ret = devm_clk_hw_register(dev, hw);
 		if (ret) {
 			dev_err(dev, "failed to register clock %s\n", name);
@@ -1886,6 +2306,20 @@ static const struct audioclk_data sm1_audioclk_data = {
 	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
 };
 
+static const struct audioclk_data s4_audioclk_data = {
+	.regmap_clks = s4_clk_regmaps,
+	.regmap_clk_num = ARRAY_SIZE(s4_clk_regmaps),
+	.regmap_clks_pads = s4_clk_pad_regmaps,
+	.regmap_clk_pads_num = ARRAY_SIZE(s4_clk_pad_regmaps),
+	.hw_clks = {
+		.hws = s4_audio_hw_clks,
+		.num = ARRAY_SIZE(s4_audio_hw_clks),
+	},
+	.reset_offset = AUDIO_SM1_SW_RESET0,
+	.reset_num = 39,
+	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
+};
+
 static const struct of_device_id clkc_match_table[] = {
 	{
 		.compatible = "amlogic,axg-audio-clkc",
@@ -1896,7 +2330,10 @@ static const struct of_device_id clkc_match_table[] = {
 	}, {
 		.compatible = "amlogic,sm1-audio-clkc",
 		.data = &sm1_audioclk_data
-	}, {}
+	}, {
+		.compatible = "amlogic,s4-audio-clkc",
+		.data = &s4_audioclk_data
+	}, { }
 };
 MODULE_DEVICE_TABLE(of, clkc_match_table);
 
diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
index 9e7765b630c96a8029140539ffda789b7db5277a..24233c40171034eba86c699db0200f07555926af 100644
--- a/drivers/clk/meson/axg-audio.h
+++ b/drivers/clk/meson/axg-audio.h
@@ -67,4 +67,10 @@
 #define AUDIO_EARCRX_CMDC_CLK_CTRL	0x0D0
 #define AUDIO_EARCRX_DMAC_CLK_CTRL	0x0D4
 
+/* s4 clock pads use new reg base */
+#define AUDIO_S4_MCLK_PAD_CTRL0 0x0
+#define AUDIO_S4_MCLK_PAD_CTRL1 0x4
+#define AUDIO_S4_SCLK_PAD_CTRL0 0x8
+#define AUDIO_S4_SCLK_PAD_CTRL1 0xC
+
 #endif /*__AXG_AUDIO_CLKC_H */

-- 
2.43.0




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:46 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:46 +0800
Subject: [PATCH v4 3/6] dt-bindings: Asoc: axg-audio: Add s4 audio tocodec
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-3-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

Add the s4 tocodec compatible

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
index 23f82bb89750898d20c866015bc2e1a4b0554846..ea669f4359bc81b0f45bc2105c832fc2b11d8441 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
@@ -26,6 +26,7 @@ properties:
       - items:
           - enum:
               - amlogic,sm1-toacodec
+              - amlogic,s4-toacodec
           - const: amlogic,g12a-toacodec
 
   reg:

-- 
2.43.0




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:43 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:43 +0800
Subject: [PATCH v4 0/6] Add support for S4 audio
Message-ID: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>

Add s4 audio base driver. 

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
Changes in v4:
- fix dtb check warning 
- add maxItems of power domain for dt-bindings
- fixed audio clock pads regmap base and reg offset 
- use dapm widget to control tocodec bclk and mclk enable
- Link to v3: https://lore.kernel.org/r/20250228-audio_drvier-v3-0-dbfd30507e4c at amlogic.com

Changes in v3:
- remove g12a tocodec switch event
- Modify the incorrect title for dt-bindings
- Link to v2: https://lore.kernel.org/r/20250214-audio_drvier-v2-0-37881fa37c9e at amlogic.com

Changes in v2:
- remove tdm pad control and change tocodec base on g12a
- change hifipll rate to support 24bit
- add s4 audio clock
- Link to v1: https://lore.kernel.org/r/20250113-audio_drvier-v1-0-8c14770f38a0 at amlogic.com

---
jiebing chen (6):
      dt-bindings: clock: meson: Add audio power domain for s4 soc
      dt-bindings: clock: axg-audio: Add mclk and sclk pad clock ids
      dt-bindings: Asoc: axg-audio: Add s4 audio tocodec
      ASoC: meson: g12a-toacodec: Add s4 tocodec driver
      clk: meson: axg-audio: Add the mclk pad div for s4 chip
      arm64: dts: amlogic: Add Amlogic S4 Audio

 .../bindings/clock/amlogic,axg-audio-clkc.yaml     |  20 +-
 .../bindings/sound/amlogic,g12a-toacodec.yaml      |   1 +
 .../boot/dts/amlogic/meson-s4-s805x2-aq222.dts     | 219 ++++++++++
 arch/arm64/boot/dts/amlogic/meson-s4.dtsi          | 372 ++++++++++++++++-
 drivers/clk/meson/axg-audio.c                      | 441 ++++++++++++++++++++-
 drivers/clk/meson/axg-audio.h                      |   6 +
 include/dt-bindings/clock/axg-audio-clkc.h         |  11 +
 sound/soc/meson/g12a-toacodec.c                    |  46 +++
 8 files changed, 1111 insertions(+), 5 deletions(-)
---
base-commit: 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
change-id: 20250110-audio_drvier-07a5381c494b

Best regards,
-- 
jiebing chen <jiebing.chen at amlogic.com>




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:47 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:47 +0800
Subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

S4 tocodec support 8 lane to input, It need to enable
bclk and mclk control bit when work

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 sound/soc/meson/g12a-toacodec.c | 46 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
index 531bb8707a3ec4c47814d6a0676d5c62c705da75..88f9adabb3b5d7d8881fa110f1d0d51e9ac9c60e 100644
--- a/sound/soc/meson/g12a-toacodec.c
+++ b/sound/soc/meson/g12a-toacodec.c
@@ -41,6 +41,9 @@
 #define  CTRL0_BCLK_SEL_LSB		4
 #define  CTRL0_MCLK_SEL			GENMASK(2, 0)
 
+#define CTRL0_BCLK_ENABLE_SHIFT		30
+#define CTRL0_MCLK_ENABLE_SHIFT		29
+
 #define TOACODEC_OUT_CHMAX		2
 
 struct g12a_toacodec {
@@ -129,6 +132,10 @@ static const struct snd_kcontrol_new g12a_toacodec_out_enable =
 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
 				    CTRL0_ENABLE_SHIFT, 1, 0);
 
+static const struct snd_kcontrol_new s4_toacodec_clk_enable =
+	SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
+			CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
+
 static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
 	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
 			 &g12a_toacodec_mux),
@@ -143,6 +150,19 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
 			    &g12a_toacodec_out_enable),
 };
 
+/*
+ * FIXME:
+ * On this soc, tocodec need enable mclk and bclk control
+ * just enable it when dapm power widget power on.
+ */
+
+static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
+	SND_SOC_DAPM_MUX("SRC", TOACODEC_CTRL0, CTRL0_BCLK_ENABLE_SHIFT, 0,
+			 &sm1_toacodec_mux),
+	SND_SOC_DAPM_SWITCH("OUT EN", TOACODEC_CTRL0, CTRL0_MCLK_ENABLE_SHIFT, 0,
+			    &g12a_toacodec_out_enable),
+};
+
 static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
 					 struct snd_pcm_hw_params *params,
 					 struct snd_soc_dai *dai)
@@ -236,6 +256,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
 	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
 };
 
+static const struct snd_kcontrol_new s4_toacodec_controls[] = {
+	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 7, 0),
+};
+
 static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
 	.probe			= g12a_toacodec_component_probe,
 	.controls		= g12a_toacodec_controls,
@@ -258,6 +282,17 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
 	.endianness		= 1,
 };
 
+static const struct snd_soc_component_driver s4_toacodec_component_drv = {
+	.probe			= sm1_toacodec_component_probe,
+	.controls		= s4_toacodec_controls,
+	.num_controls		= ARRAY_SIZE(s4_toacodec_controls),
+	.dapm_widgets		= s4_toacodec_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(s4_toacodec_widgets),
+	.dapm_routes		= g12a_toacodec_routes,
+	.num_dapm_routes	= ARRAY_SIZE(g12a_toacodec_routes),
+	.endianness		= 1,
+};
+
 static const struct regmap_config g12a_toacodec_regmap_cfg = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -278,6 +313,13 @@ static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
 	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
 };
 
+static const struct g12a_toacodec_match_data s4_toacodec_match_data = {
+	.component_drv	= &s4_toacodec_component_drv,
+	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 19, 20),
+	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
+	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
+};
+
 static const struct of_device_id g12a_toacodec_of_match[] = {
 	{
 		.compatible = "amlogic,g12a-toacodec",
@@ -287,6 +329,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
 		.compatible = "amlogic,sm1-toacodec",
 		.data = &sm1_toacodec_match_data,
 	},
+	{
+		.compatible = "amlogic,s4-toacodec",
+		.data = &s4_toacodec_match_data,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);

-- 
2.43.0




From devnull+jiebing.chen.amlogic.com at kernel.org  Wed Mar 19 00:04:49 2025
From: devnull+jiebing.chen.amlogic.com at kernel.org (jiebing chen via B4 Relay)
Date: Wed, 19 Mar 2025 15:04:49 +0800
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>

From: jiebing chen <jiebing.chen at amlogic.com>

Add basic audio driver support for the Amlogic S4 based
Amlogic AQ222 board. use hifipll pll (1179648000) to
support 768k sample rate and 24 bit (s24_le), 24bit sclk
is 48fs, use mpll0 (270950400) to support 705.6k sample
rate and 32bit, use mpll1 (338688000) to support 705.6k
and 24bit.

Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
---
 .../boot/dts/amlogic/meson-s4-s805x2-aq222.dts     | 219 ++++++++++++
 arch/arm64/boot/dts/amlogic/meson-s4.dtsi          | 372 ++++++++++++++++++++-
 2 files changed, 589 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
index 6730c44642d2910d42ec0c4adf49fefc3514dbec..6fccaeb0e151e959af1cbe04d9dca50d70f0b7fc 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
@@ -75,6 +75,19 @@ vddio_ao1v8: regulator-vddio-ao1v8 {
 	       regulator-always-on;
 	};
 
+	vcc5v_reg: regulator-vcc-5v {
+		compatible = "regulator-fixed";
+		vin-supply = <&main_12v>;
+		regulator-name = "VCC5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <7000>;
+		enable-active-high;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	/* SY8120B1ABC DC/DC Regulator. */
 	vddcpu: regulator-vddcpu {
 		compatible = "pwm-regulator";
@@ -129,6 +142,212 @@ vddcpu: regulator-vddcpu {
 				<699000 98>,
 				<689000 100>;
 	};
+	dmics: audio-codec-1 {
+		compatible = "dmic-codec";
+		#sound-dai-cells = <0>;
+		num-channels = <2>;
+		wakeup-delay-ms = <50>;
+		sound-name-prefix = "MIC";
+	};
+
+	dioo2133: audio-amplifier-0 {
+		compatible = "simple-audio-amplifier";
+		enable-gpios = <&gpio GPIOH_8 GPIO_ACTIVE_HIGH>;
+		VCC-supply = <&vcc5v_reg>;
+		sound-name-prefix = "10U2";
+	};
+
+	spdif_dir: audio-spdif-in {
+		compatible = "linux,spdif-dir";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "DIR";
+	};
+
+	spdif_dit: audio-spdif-out {
+		compatible = "linux,spdif-dit";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "DIT";
+	};
+
+	sound {
+		compatible = "amlogic,axg-sound-card";
+		model = "aq222";
+		audio-widgets = "Line", "Lineout";
+		audio-aux-devs = <&tdmout_a>, <&tdmout_b>, <&tdmout_c>,
+				 <&tdmin_a>, <&tdmin_b>, <&tdmin_c>,
+				 <&tdmin_lb>, <&dioo2133>;
+		audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+				"TDMOUT_A IN 1", "FRDDR_B OUT 0",
+				"TDMOUT_A IN 2", "FRDDR_C OUT 0",
+				"TDM_A Playback", "TDMOUT_A OUT",
+				"TDMOUT_B IN 0", "FRDDR_A OUT 1",
+				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
+				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
+				"TDM_B Playback", "TDMOUT_B OUT",
+				"TDMOUT_C IN 0", "FRDDR_A OUT 2",
+				"TDMOUT_C IN 1", "FRDDR_B OUT 2",
+				"TDMOUT_C IN 2", "FRDDR_C OUT 2",
+				"TDM_C Playback", "TDMOUT_C OUT",
+				"SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+				"SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+				"SPDIFOUT_A IN 2", "FRDDR_C OUT 3",
+				"SPDIFOUT_B IN 0", "FRDDR_A OUT 4",
+				"SPDIFOUT_B IN 1", "FRDDR_B OUT 4",
+				"SPDIFOUT_B IN 2", "FRDDR_C OUT 4",
+				"TDMIN_A IN 0", "TDM_A Capture",
+				"TDMIN_A IN 1", "TDM_B Capture",
+				"TDMIN_A IN 2", "TDM_C Capture",
+				"TDMIN_A IN 3", "TDM_A Loopback",
+				"TDMIN_A IN 4", "TDM_B Loopback",
+				"TDMIN_A IN 5", "TDM_C Loopback",
+				"TDMIN_B IN 0", "TDM_A Capture",
+				"TDMIN_B IN 1", "TDM_B Capture",
+				"TDMIN_B IN 2", "TDM_C Capture",
+				"TDMIN_B IN 3", "TDM_A Loopback",
+				"TDMIN_B IN 4", "TDM_B Loopback",
+				"TDMIN_B IN 5", "TDM_C Loopback",
+				"TDMIN_C IN 0", "TDM_A Capture",
+				"TDMIN_C IN 1", "TDM_B Capture",
+				"TDMIN_C IN 2", "TDM_C Capture",
+				"TDMIN_C IN 3", "TDM_A Loopback",
+				"TDMIN_C IN 4", "TDM_B Loopback",
+				"TDMIN_C IN 5", "TDM_C Loopback",
+				"TDMIN_LB IN 3", "TDM_A Capture",
+				"TDMIN_LB IN 4", "TDM_B Capture",
+				"TDMIN_LB IN 5", "TDM_C Capture",
+				"TDMIN_LB IN 0", "TDM_A Loopback",
+				"TDMIN_LB IN 1", "TDM_B Loopback",
+				"TDMIN_LB IN 2", "TDM_C Loopback",
+				"TODDR_A IN 0", "TDMIN_A OUT",
+				"TODDR_B IN 0", "TDMIN_A OUT",
+				"TODDR_C IN 0", "TDMIN_A OUT",
+				"TODDR_A IN 1", "TDMIN_B OUT",
+				"TODDR_B IN 1", "TDMIN_B OUT",
+				"TODDR_C IN 1", "TDMIN_B OUT",
+				"TODDR_A IN 2", "TDMIN_C OUT",
+				"TODDR_B IN 2", "TDMIN_C OUT",
+				"TODDR_C IN 2", "TDMIN_C OUT",
+				"TODDR_A IN 3", "SPDIFIN Capture",
+				"TODDR_B IN 3", "SPDIFIN Capture",
+				"TODDR_C IN 3", "SPDIFIN Capture",
+				"TODDR_A IN 6", "TDMIN_LB OUT",
+				"TODDR_B IN 6", "TDMIN_LB OUT",
+				"TODDR_C IN 6", "TDMIN_LB OUT",
+				"10U2 INL", "ACODEC LOLP",
+				"10U2 INR", "ACODEC LORP",
+				"Lineout", "10U2 OUTL",
+				"Lineout", "10U2 OUTR";
+		assigned-clocks = <&clkc_pll CLKID_HIFI_PLL>,
+				  <&clkc_pll CLKID_MPLL0>,
+				  <&clkc_pll CLKID_MPLL1>;
+		assigned-clock-rates = <1179648000>,
+				       <270950400>,
+				       <338688000>;
+
+		dai-link-0 {
+			sound-dai = <&frddr_a>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&frddr_b>;
+		};
+
+		dai-link-2 {
+			sound-dai = <&frddr_c>;
+		};
+
+		dai-link-3 {
+			sound-dai = <&toddr_a>;
+		};
+
+		dai-link-4 {
+			sound-dai = <&toddr_b>;
+		};
+
+		dai-link-5 {
+			sound-dai = <&toddr_c>;
+		};
+
+		dai-link-6 {
+			sound-dai = <&tdmif_a>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			mclk-fs = <256>;
+			codec-0 {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>;
+			};
+			codec-1 {
+				sound-dai = <&toacodec TOACODEC_IN_A>;
+			};
+		};
+
+		dai-link-7 {
+			sound-dai = <&tdmif_b>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			mclk-fs = <256>;
+			codec-0 {
+				sound-dai = <&toacodec TOACODEC_IN_B>;
+			};
+			codec-1 {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+			};
+		};
+
+		/* 8ch HDMI interface */
+		dai-link-8 {
+			sound-dai = <&tdmif_c>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			dai-tdm-slot-tx-mask-1 = <1 1>;
+			dai-tdm-slot-tx-mask-2 = <1 1>;
+			dai-tdm-slot-tx-mask-3 = <1 1>;
+			mclk-fs = <256>;
+			codec-0 {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
+			};
+		};
+
+		/* spdif hdmi and coax output */
+		dai-link-9 {
+			sound-dai = <&spdifout_a>;
+
+			codec-0 {
+				sound-dai = <&spdif_dit>;
+			};
+
+			codec-1 {
+				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>;
+			};
+		};
+
+		/* spdif hdmi interface */
+		dai-link-10 {
+			sound-dai = <&spdifout_b>;
+
+			codec {
+				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>;
+			};
+		};
+
+		/* spdif coax input */
+		dai-link-11 {
+			sound-dai = <&spdifin>;
+
+			codec {
+				sound-dai = <&spdif_dir>;
+			};
+		};
+
+		dai-link-12 {
+			sound-dai = <&toacodec TOACODEC_OUT>;
+
+			codec {
+				sound-dai = <&acodec>;
+			};
+		};
+	};
+
 };
 
 &pwm_ef {
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
@@ -11,7 +11,11 @@
 #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
 #include <dt-bindings/power/meson-s4-power.h>
 #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
-
+#include <dt-bindings/clock/axg-audio-clkc.h>
+#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
+#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
 / {
 	cpus {
 		#address-cells = <2>;
@@ -46,6 +50,36 @@ cpu3: cpu at 3 {
 		};
 	};
 
+	tdmif_a: audio-controller-0 {
+		compatible = "amlogic,axg-tdm-iface";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "TDM_A";
+		clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+			 <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
+			 <&clkc_audio AUD_CLKID_MST_A_MCLK>;
+		clock-names = "sclk", "lrclk","mclk";
+	};
+
+	tdmif_b: audio-controller-1 {
+		compatible = "amlogic,axg-tdm-iface";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "TDM_B";
+		clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+			 <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
+			 <&clkc_audio AUD_CLKID_MST_B_MCLK>;
+		clock-names = "sclk", "lrclk","mclk";
+	};
+
+	tdmif_c: audio-controller-2 {
+		compatible = "amlogic,axg-tdm-iface";
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "TDM_C";
+		clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
+			 <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
+			 <&clkc_audio AUD_CLKID_MST_C_MCLK>;
+		clock-names = "sclk", "lrclk","mclk";
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -101,7 +135,6 @@ apb4: bus at fe000000 {
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
-
 			clkc_periphs: clock-controller at 0 {
 				compatible = "amlogic,s4-peripherals-clkc";
 				reg = <0x0 0x0 0x0 0x49c>;
@@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
 				#clock-cells = <1>;
 			};
 
+			acodec: audio-controller at 1a000 {
+				compatible = "amlogic,t9015";
+				reg = <0x0 0x1A000 0x0 0x14>;
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "ACODEC";
+				clocks = <&clkc_periphs CLKID_ACODEC>;
+				clock-names = "pclk";
+				resets = <&reset RESET_ACODEC>;
+				AVDD-supply = <&vddio_ao1v8>;
+			};
+
 			watchdog at 2100 {
 				compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
 				reg = <0x0 0x2100 0x0 0x10>;
@@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
 		};
 	};
 };
+
+&apb4 {
+	audio: bus at 330000 {
+		compatible = "simple-bus";
+		reg = <0x0 0x330000 0x0 0x1000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x0 0x0 0x0 0x330000 0x0 0x1000>;
+
+		clkc_audio: clock-controller at 0 {
+			compatible = "amlogic,s4-audio-clkc";
+			reg = <0x0 0x0 0x0 0xd8>,
+			      <0x0 0xE80 0x0 0x10>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			power-domains = <&pwrc PWRC_S4_AUDIO_ID>;
+			clocks = <&clkc_periphs CLKID_AUDIO>,
+				 <&clkc_pll CLKID_MPLL0>,
+				 <&clkc_pll CLKID_MPLL1>,
+				 <&clkc_pll CLKID_MPLL2>,
+				 <&clkc_pll CLKID_MPLL3>,
+				 <&clkc_pll CLKID_HIFI_PLL>,
+				 <&clkc_pll CLKID_FCLK_DIV3>,
+				 <&clkc_pll CLKID_FCLK_DIV4>,
+				 <&clkc_pll CLKID_FCLK_DIV5>;
+			clock-names = "pclk",
+				      "mst_in0",
+				      "mst_in1",
+				      "mst_in2",
+				      "mst_in3",
+				      "mst_in4",
+				      "mst_in5",
+				      "mst_in6",
+				      "mst_in7";
+
+			resets = <&reset RESET_AUDIO>;
+		};
+
+		toddr_a: audio-controller at 100 {
+			compatible = "amlogic,sm1-toddr",
+				     "amlogic,axg-toddr";
+			reg = <0x0 0x100 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "TODDR_A";
+			interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_TODDR_A>;
+			resets = <&arb AXG_ARB_TODDR_A>,
+				 <&clkc_audio AUD_RESET_TODDR_A>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <8192>;
+		};
+
+		toddr_b: audio-controller at 140 {
+			compatible = "amlogic,sm1-toddr",
+				     "amlogic,axg-toddr";
+			reg = <0x0 0x140 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "TODDR_B";
+			interrupts = <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_TODDR_B>;
+			resets = <&arb AXG_ARB_TODDR_B>,
+				 <&clkc_audio AUD_RESET_TODDR_B>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+
+		toddr_c: audio-controller at 180 {
+			compatible = "amlogic,sm1-toddr",
+				     "amlogic,axg-toddr";
+			reg = <0x0 0x180 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "TODDR_C";
+			interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_TODDR_C>;
+			resets = <&arb AXG_ARB_TODDR_C>,
+				 <&clkc_audio AUD_RESET_TODDR_C>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+
+		frddr_a: audio-controller at 1c0 {
+			compatible = "amlogic,sm1-frddr",
+				     "amlogic,axg-frddr";
+			reg = <0x0 0x1c0 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "FRDDR_A";
+			interrupts = <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
+			resets = <&arb AXG_ARB_FRDDR_A>,
+				 <&clkc_audio AUD_RESET_FRDDR_A>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <512>;
+		};
+
+		frddr_b: audio-controller at 200 {
+			compatible = "amlogic,sm1-frddr",
+				     "amlogic,axg-frddr";
+			reg = <0x0 0x200 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "FRDDR_B";
+			interrupts = <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_FRDDR_B>;
+			resets = <&arb AXG_ARB_FRDDR_B>,
+				 <&clkc_audio AUD_RESET_FRDDR_B>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+
+		frddr_c: audio-controller at 240 {
+			compatible = "amlogic,sm1-frddr",
+				     "amlogic,axg-frddr";
+			reg = <0x0 0x240 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "FRDDR_C";
+			interrupts = <GIC_SPI 38 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_FRDDR_C>;
+			resets = <&arb AXG_ARB_FRDDR_C>,
+				 <&clkc_audio AUD_RESET_FRDDR_C>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+
+		arb: reset-controller at 280 {
+			compatible = "amlogic,meson-sm1-audio-arb";
+			reg = <0x0 0x280 0x0 0x4>;
+			#reset-cells = <1>;
+			clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
+		};
+
+		tdmin_a: audio-controller at 300 {
+			compatible = "amlogic,sm1-tdmin";
+			reg = <0x0 0x300 0x0 0x40>;
+			sound-name-prefix = "TDMIN_A";
+			resets = <&clkc_audio AUD_RESET_TDMIN_A>;
+			clocks = <&clkc_audio AUD_CLKID_TDMIN_A>,
+				 <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		tdmin_b: audio-controller at 340 {
+			compatible = "amlogic,sm1-tdmin";
+			reg = <0x0 0x340 0x0 0x40>;
+			sound-name-prefix = "TDMIN_B";
+			resets = <&clkc_audio AUD_RESET_TDMIN_B>;
+			clocks = <&clkc_audio AUD_CLKID_TDMIN_B>,
+				 <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		tdmin_c: audio-controller at 380 {
+			compatible = "amlogic,sm1-tdmin";
+			reg = <0x0 0x380 0x0 0x40>;
+			sound-name-prefix = "TDMIN_C";
+			resets = <&clkc_audio AUD_RESET_TDMIN_C>;
+			clocks = <&clkc_audio AUD_CLKID_TDMIN_C>,
+				 <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		tdmin_lb: audio-controller at 3c0 {
+			compatible = "amlogic,sm1-tdmin";
+			reg = <0x0 0x3c0 0x0 0x40>;
+			sound-name-prefix = "TDMIN_LB";
+			resets = <&clkc_audio AUD_RESET_TDMIN_LB>;
+			clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>,
+				 <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		spdifin: audio-controller at 400 {
+			compatible = "amlogic,g12a-spdifin",
+				     "amlogic,axg-spdifin";
+			reg = <0x0 0x400 0x0 0x30>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SPDIFIN";
+			interrupts = <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_SPDIFIN>,
+			<&clkc_audio AUD_CLKID_SPDIFIN_CLK>;
+			clock-names = "pclk", "refclk";
+			resets = <&clkc_audio AUD_RESET_SPDIFIN>;
+		};
+
+		spdifout_a: audio-controller at 480 {
+			compatible = "amlogic,g12a-spdifout",
+				     "amlogic,axg-spdifout";
+			reg = <0x0 0x480 0x0 0x50>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SPDIFOUT_A";
+			clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
+			<&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
+			clock-names = "pclk", "mclk";
+			resets = <&clkc_audio AUD_RESET_SPDIFOUT>;
+		};
+
+		tdmout_a: audio-controller at 500 {
+			compatible = "amlogic,sm1-tdmout";
+			reg = <0x0 0x500 0x0 0x40>;
+			sound-name-prefix = "TDMOUT_A";
+			resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
+			clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		tdmout_b: audio-controller at 540 {
+			compatible = "amlogic,sm1-tdmout";
+			reg = <0x0 0x540 0x0 0x40>;
+			sound-name-prefix = "TDMOUT_B";
+			resets = <&clkc_audio AUD_RESET_TDMOUT_B>;
+			clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		tdmout_c: audio-controller at 580 {
+			compatible = "amlogic,sm1-tdmout";
+			reg = <0x0 0x580 0x0 0x40>;
+			sound-name-prefix = "TDMOUT_C";
+			resets = <&clkc_audio AUD_RESET_TDMOUT_C>;
+			clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>,
+				 <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>;
+			clock-names = "pclk", "sclk", "sclk_sel",
+				      "lrclk", "lrclk_sel";
+		};
+
+		spdifout_b: audio-controller at 680 {
+			compatible = "amlogic,g12a-spdifout",
+				     "amlogic,axg-spdifout";
+			reg = <0x0 0x680 0x0 0x50>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "SPDIFOUT_B";
+			clocks = <&clkc_audio AUD_CLKID_SPDIFOUT_B>,
+				 <&clkc_audio AUD_CLKID_SPDIFOUT_B_CLK>;
+			clock-names = "pclk", "mclk";
+			resets = <&clkc_audio AUD_RESET_SPDIFOUT_B>;
+		};
+
+		toacodec: audio-controller at 740 {
+			compatible = "amlogic,s4-toacodec",
+				     "amlogic,g12a-toacodec";
+			reg = <0x0 0x740 0x0 0x4>;
+			sound-name-prefix = "TOACODEC";
+			#sound-dai-cells = <1>;
+			resets = <&clkc_audio AUD_RESET_TOACODEC>;
+		};
+
+		tohdmitx: audio-controller at 744 {
+			compatible = "amlogic,sm1-tohdmitx",
+				     "amlogic,g12a-tohdmitx";
+			reg = <0x0 0x744 0x0 0x4>;
+			#sound-dai-cells = <1>;
+			sound-name-prefix = "TOHDMITX";
+			resets = <&clkc_audio AUD_RESET_TOHDMITX>;
+		};
+
+		toddr_d: audio-controller at 840 {
+			compatible = "amlogic,sm1-toddr",
+				     "amlogic,axg-toddr";
+			reg = <0x0 0x840 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "TODDR_D";
+			interrupts = <GIC_SPI 45 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_TODDR_D>;
+			resets = <&arb AXG_ARB_TODDR_D>,
+				 <&clkc_audio AUD_RESET_TODDR_D>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+
+		frddr_d: audio-controller at 880 {
+			 compatible = "amlogic,sm1-frddr",
+				      "amlogic,axg-frddr";
+			reg = <0x0 0x880 0x0 0x2c>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "FRDDR_D";
+			interrupts = <GIC_SPI 46 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkc_audio AUD_CLKID_FRDDR_D>;
+			resets = <&arb AXG_ARB_FRDDR_D>,
+				 <&clkc_audio AUD_RESET_FRDDR_D>;
+			reset-names = "arb", "rst";
+			amlogic,fifo-depth = <256>;
+		};
+	};
+
+	pdm: audio-controller at 331000 {
+		compatible = "amlogic,sm1-pdm",
+			     "amlogic,axg-pdm";
+		reg = <0x0 0x331000 0x0 0x34>;
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "PDM";
+		clocks = <&clkc_audio AUD_CLKID_PDM>,
+			 <&clkc_audio AUD_CLKID_PDM_DCLK>,
+			 <&clkc_audio AUD_CLKID_PDM_SYSCLK>;
+		clock-names = "pclk", "dclk", "sysclk";
+		resets = <&clkc_audio AUD_RESET_PDM>;
+	};
+};

-- 
2.43.0




From krzysztof.kozlowski at linaro.org  Wed Mar 19 00:18:19 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:18:19 +0100
Subject: [PATCH 2/4] dt-bindings: remoteproc: mediatek: Remove l1tcm for
 dual-core MT8188 SCP
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
Message-ID: <3f147dbd-c4a7-4cf5-911c-1d9263f5067c@linaro.org>

On 18/03/2025 23:22, N?colas F. R. A. Prado wrote:
> The SCP present on MT8188 does not have an L1TCM memory region, but the
> binding incorrectly requires one for the dual-core description of the
> MT8188 SCP. Remove that requirement. Also update the minimum number of
> reg and reg-names to 1, since as this is a multi-core SCP with no
> L1TCM memory, only the CFG memory region is present in the parent node.
> 
> Fixes: 91e0d560b9fd ("dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP")
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From krzysztof.kozlowski at linaro.org  Wed Mar 19 00:16:37 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:16:37 +0100
Subject: [PATCH 1/4] dt-bindings: remoteproc: mediatek: Add missing
 minItems for 8192/8195
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-1-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-1-8733e192cc73@collabora.com>
Message-ID: <3fa1573d-e3b4-434c-867d-38fa69ad3a8e@linaro.org>

On 18/03/2025 23:22, N?colas F. R. A. Prado wrote:
> Both MT8192 and MT8195 have an L1TCM memory, so it should be described
> in reg, and therefore reg's minItems should be 3, as is already implicit
> by reg-names. Override minItems to 3 for MT8192 and MT8195.

I think that was the original intention already, because reg-names are
expecting min 3 items. Basically you just correct the missing lower
constraint.

> 
> Fixes: 6b55b1e2fd7f ("dt-bindings: remoteproc: mediatek: Support MT8195 dual-core SCP")
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> ---
>  Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> index adc6b3f36fde49eb3fa7ed3f08b0fa9e7f331162..ee33c233e44f3d51f0851b35697a24208c87f68a 100644
> --- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> @@ -185,6 +185,7 @@ allOf:
>      then:
>        properties:
>          reg:
> +          minItems: 3
>            maxItems: 3

maxItems can be dropped.


Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 00:23:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:23:32 +0100
Subject: [PATCH] arm64: defconfig: Enable USB retimer and redriver
In-Reply-To: <20250318-xelite-retimer-redriver-v1-1-b3e85a37d294@oss.qualcomm.com>
References: <20250318-xelite-retimer-redriver-v1-1-b3e85a37d294@oss.qualcomm.com>
Message-ID: <0c44592f-0189-4876-8587-d2706774232b@kernel.org>

On 19/03/2025 04:11, Bjorn Andersson via B4 Relay wrote:
> From: Bjorn Andersson <bjorn.andersson at oss.qualcomm.com>
> 
> Several boards based on the Qualcomm X Elite platform uses the NXP
> PTN3222 USB redriver and the Parade PS883x USB Type-C retimer. Without
> these USB, and in some cases display, doesn't probe successfully, so
> enable them.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson at oss.qualcomm.com>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From quic_nguyenb at quicinc.com  Wed Mar 19 00:29:30 2025
From: quic_nguyenb at quicinc.com (Bao D. Nguyen)
Date: Wed, 19 Mar 2025 00:29:30 -0700
Subject: [PATCH v3 1/1] scsi: ufs: core: add device level exception support
Message-ID: <6109425449ac4d18249ce7254e4fa1252138a94a.1742369183.git.quic_nguyenb@quicinc.com>

The ufs device JEDEC specification version 4.1 adds support for the
device level exception events. To support this new device level
exception feature, expose two new sysfs nodes below to provide
the user space access to the device level exception information.
/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id

The device_lvl_exception_count sysfs node reports the number of
device level exceptions that have occurred since the last time
this variable is reset. Writing a value of 0 will reset it.
The device_lvl_exception_id reports the exception ID which is the
qDeviceLevelExceptionID attribute of the device JEDEC specifications
version 4.1 and later. The user space application can query these
sysfs nodes to get more information about the device level exception.

Signed-off-by: Bao D. Nguyen <quic_nguyenb at quicinc.com>
Reviewed-by: Peter Wang <peter.wang at mediatek.com>
---
Changes in v3:
1. Add protection for hba->dev_lvl_exception_count accesses in different
contexts (Bart's comment).

Changes in v2:
1. Addressed Mani's comments:
   - Update the documentation of dev_lvl_exception_count to read/write.
   - Rephrase the description of the Documentation and commit text.
   - Remove the export of ufshcd_read_device_lvl_exception_id().
2. Addressed Bart's comments:
   - Rename dev_lvl_exception sysfs node to dev_lvl_exception_count.
   - Update the documentation of the sysfs nodes.
   - Skip comment about sysfs_notify() being used in interrupt
     context because Avri already addressed it.
---
 Documentation/ABI/testing/sysfs-driver-ufs | 27 +++++++++++++
 drivers/ufs/core/ufs-sysfs.c               | 57 +++++++++++++++++++++++++++
 drivers/ufs/core/ufshcd-priv.h             |  1 +
 drivers/ufs/core/ufshcd.c                  | 63 ++++++++++++++++++++++++++++++
 include/uapi/scsi/scsi_bsg_ufs.h           |  9 +++++
 include/ufs/ufs.h                          |  5 ++-
 include/ufs/ufshcd.h                       |  5 +++
 7 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index ae01912..6a6c35a 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -1604,3 +1604,30 @@ Description:
 		prevent the UFS from frequently performing clock gating/ungating.
 
 		The attribute is read/write.
+
+What:		/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
+What:		/sys/bus/platform/devices/*.ufs/device_lvl_exception_count
+Date:		March 2025
+Contact:	Bao D. Nguyen <quic_nguyenb at quicinc.com>
+Description:
+		This attribute is applicable to ufs devices compliant to the JEDEC
+		specifications version 4.1 or later. The device_lvl_exception_count
+		is a counter indicating the number of times the device level exceptions
+		have occurred since the last time this variable is reset.
+		Writing a 0 value to this attribute will reset the device_lvl_exception_count.
+		If the device_lvl_exception_count reads a positive value, the user
+		application should read the device_lvl_exception_id attribute to know more
+		information about the exception.
+		This attribute is read/write.
+
+What:		/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id
+What:		/sys/bus/platform/devices/*.ufs/device_lvl_exception_id
+Date:		March 2025
+Contact:	Bao D. Nguyen <quic_nguyenb at quicinc.com>
+Description:
+		Reading the device_lvl_exception_id returns the qDeviceLevelExceptionID
+		attribute of the ufs device JEDEC specification version 4.1. The definition
+		of the qDeviceLevelExceptionID is the ufs device vendor specific implementation.
+		Refer to the device manufacturer datasheet for more information
+		on the meaning of the qDeviceLevelExceptionID attribute value.
+		The attribute is read only.
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 90b5ab6..4cd2e0b 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -466,6 +466,59 @@ static ssize_t critical_health_show(struct device *dev,
 	return sysfs_emit(buf, "%d\n", hba->critical_health_count);
 }
 
+static ssize_t device_lvl_exception_count_show(struct device *dev,
+					       struct device_attribute *attr,
+					       char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return -EOPNOTSUPP;
+
+	return sysfs_emit(buf, "%u\n", hba->dev_lvl_exception_count);
+}
+
+static ssize_t device_lvl_exception_count_store(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	unsigned long flags;
+	unsigned int value;
+
+	if (kstrtouint(buf, 0, &value))
+		return -EINVAL;
+
+	/* the only supported usecase is to reset the dev_lvl_exception_count */
+	if (value)
+		return -EINVAL;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->dev_lvl_exception_count = 0;
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	return count;
+}
+
+static ssize_t device_lvl_exception_id_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	u64 exception_id;
+	int err;
+
+	ufshcd_rpm_get_sync(hba);
+	err = ufshcd_read_device_lvl_exception_id(hba, &exception_id);
+	ufshcd_rpm_put_sync(hba);
+
+	if (err)
+		return err;
+
+	hba->dev_lvl_exception_id = exception_id;
+	return sysfs_emit(buf, "%llu\n", exception_id);
+}
+
 static DEVICE_ATTR_RW(rpm_lvl);
 static DEVICE_ATTR_RO(rpm_target_dev_state);
 static DEVICE_ATTR_RO(rpm_target_link_state);
@@ -479,6 +532,8 @@ static DEVICE_ATTR_RW(wb_flush_threshold);
 static DEVICE_ATTR_RW(rtc_update_ms);
 static DEVICE_ATTR_RW(pm_qos_enable);
 static DEVICE_ATTR_RO(critical_health);
+static DEVICE_ATTR_RW(device_lvl_exception_count);
+static DEVICE_ATTR_RO(device_lvl_exception_id);
 
 static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
 	&dev_attr_rpm_lvl.attr,
@@ -494,6 +549,8 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
 	&dev_attr_rtc_update_ms.attr,
 	&dev_attr_pm_qos_enable.attr,
 	&dev_attr_critical_health.attr,
+	&dev_attr_device_lvl_exception_count.attr,
+	&dev_attr_device_lvl_exception_id.attr,
 	NULL
 };
 
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 10b4a19..d0a2c96 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -94,6 +94,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 			     enum query_opcode desc_op);
 
 int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
+int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id);
 
 /* Wrapper functions for safely calling variant operations */
 static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 4e1e214..5674f4a 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -6013,6 +6013,43 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
 				__func__, err);
 }
 
+int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id)
+{
+	struct utp_upiu_query_response_v4_0 *upiu_resp;
+	struct ufs_query_req *request = NULL;
+	struct ufs_query_res *response = NULL;
+	int err;
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return -EOPNOTSUPP;
+
+	ufshcd_hold(hba);
+	mutex_lock(&hba->dev_cmd.lock);
+
+	ufshcd_init_query(hba, &request, &response,
+			  UPIU_QUERY_OPCODE_READ_ATTR,
+			  QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID, 0, 0);
+
+	request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
+
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+	if (err) {
+		dev_err(hba->dev, "%s: failed to read device level exception %d\n",
+			__func__, err);
+		goto out;
+	}
+
+	upiu_resp = (struct utp_upiu_query_response_v4_0 *)response;
+	*exception_id = get_unaligned_be64(&upiu_resp->value);
+
+out:
+	mutex_unlock(&hba->dev_cmd.lock);
+	ufshcd_release(hba);
+
+	return err;
+}
+
 static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn)
 {
 	u8 index;
@@ -6215,6 +6252,7 @@ static void ufshcd_rpm_dev_flush_recheck_work(struct work_struct *work)
  */
 static void ufshcd_exception_event_handler(struct work_struct *work)
 {
+	unsigned long flags;
 	struct ufs_hba *hba;
 	int err;
 	u32 status = 0;
@@ -6240,6 +6278,13 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
 		sysfs_notify(&hba->dev->kobj, NULL, "critical_health");
 	}
 
+	if (status & hba->ee_drv_mask & MASK_EE_DEV_LVL_EXCEPTION) {
+		spin_lock_irqsave(hba->host->host_lock, flags);
+		hba->dev_lvl_exception_count++;
+		spin_unlock_irqrestore(hba->host->host_lock, flags);
+		sysfs_notify(&hba->dev->kobj, NULL, "device_lvl_exception_count");
+	}
+
 	ufs_debugfs_exception_event(hba, status);
 }
 
@@ -8139,6 +8184,22 @@ static void ufshcd_temp_notif_probe(struct ufs_hba *hba, const u8 *desc_buf)
 	}
 }
 
+static void ufshcd_device_lvl_exception_probe(struct ufs_hba *hba, u8 *desc_buf)
+{
+	u32 ext_ufs_feature;
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return;
+
+	ext_ufs_feature = get_unaligned_be32(desc_buf +
+				DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+	if (!(ext_ufs_feature & UFS_DEV_LVL_EXCEPTION_SUP))
+		return;
+
+	hba->dev_lvl_exception_count = 0;
+	ufshcd_enable_ee(hba, MASK_EE_DEV_LVL_EXCEPTION);
+}
+
 static void ufshcd_set_rtt(struct ufs_hba *hba)
 {
 	struct ufs_dev_info *dev_info = &hba->dev_info;
@@ -8339,6 +8400,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
 
 	ufs_init_rtc(hba, desc_buf);
 
+	ufshcd_device_lvl_exception_probe(hba, desc_buf);
+
 	/*
 	 * ufshcd_read_string_desc returns size of the string
 	 * reset the error value
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 8c29e49..8b61dff 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -143,6 +143,15 @@ struct utp_upiu_query_v4_0 {
 	__be32 reserved;
 };
 
+struct utp_upiu_query_response_v4_0 {
+	__u8 opcode;
+	__u8 idn;
+	__u8 index;
+	__u8 selector;
+	__be64 value;
+	__be32 reserved;
+} __attribute__((__packed__));
+
 /**
  * struct utp_upiu_cmd - Command UPIU structure
  * @exp_data_transfer_len: Data Transfer Length DW-3
diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h
index 8a24ed5..1c47136 100644
--- a/include/ufs/ufs.h
+++ b/include/ufs/ufs.h
@@ -180,7 +180,8 @@ enum attr_idn {
 	QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE       = 0x1D,
 	QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST    = 0x1E,
 	QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE        = 0x1F,
-	QUERY_ATTR_IDN_TIMESTAMP		= 0x30
+	QUERY_ATTR_IDN_TIMESTAMP		= 0x30,
+	QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID     = 0x34,
 };
 
 /* Descriptor idn for Query requests */
@@ -390,6 +391,7 @@ enum {
 	UFS_DEV_EXT_TEMP_NOTIF		= BIT(6),
 	UFS_DEV_HPB_SUPPORT		= BIT(7),
 	UFS_DEV_WRITE_BOOSTER_SUP	= BIT(8),
+	UFS_DEV_LVL_EXCEPTION_SUP       = BIT(12),
 };
 #define UFS_DEV_HPB_SUPPORT_VERSION		0x310
 
@@ -419,6 +421,7 @@ enum {
 	MASK_EE_TOO_LOW_TEMP		= BIT(4),
 	MASK_EE_WRITEBOOSTER_EVENT	= BIT(5),
 	MASK_EE_PERFORMANCE_THROTTLING	= BIT(6),
+	MASK_EE_DEV_LVL_EXCEPTION       = BIT(7),
 	MASK_EE_HEALTH_CRITICAL		= BIT(9),
 };
 #define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index e3909cc..ad90a43 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -968,6 +968,9 @@ enum ufshcd_mcq_opr {
  * @pm_qos_req: PM QoS request handle
  * @pm_qos_enabled: flag to check if pm qos is enabled
  * @critical_health_count: count of critical health exceptions
+ * @dev_lvl_exception_count: count of device level exceptions since last reset
+ * @dev_lvl_exception_id: vendor specific information about the
+ * device level exception event.
  */
 struct ufs_hba {
 	void __iomem *mmio_base;
@@ -1138,6 +1141,8 @@ struct ufs_hba {
 	bool pm_qos_enabled;
 
 	int critical_health_count;
+	u32 dev_lvl_exception_count;
+	u64 dev_lvl_exception_id;
 };
 
 /**
-- 
2.7.4



From oliver.upton at linux.dev  Wed Mar 19 00:34:19 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 19 Mar 2025 00:34:19 -0700
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
Message-ID: <Z9pze3J2_zrTk_yC@linux.dev>

Hi Akihiko,

On Wed, Mar 19, 2025 at 03:33:46PM +0900, Akihiko Odaki wrote:
> Problem
> -------
> 
> arch/arm64/kvm/pmu-emul.c used to have a comment saying the follows:
> > The observant among you will notice that the supported_cpus
> > mask does not get updated for the default PMU even though it
> > is quite possible the selected instance supports only a
> > subset of cores in the system. This is intentional, and
> > upholds the preexisting behavior on heterogeneous systems
> > where vCPUs can be scheduled on any core but the guest
> > counters could stop working.
> 
> Despite the reference manual says counters may not continuously
> incrementing, Windows is not robust enough to handle stopped PMCCNTR_EL0
> and crashes with a division-by-zero error and it also crashes when the
> PMU is not present.
> 
> To avoid such a problem, the userspace should pin the vCPU threads to
> pCPUs supported by one host PMU when initializing the vCPUs or specify
> the host PMU to use with KVM_ARM_VCPU_PMU_V3_SET_PMU after the
> initialization. However, QEMU/libvirt can pin vCPU threads only after the
> vCPUs are initialized. It also limits the pCPUs the guest can use even
> for VMMs that support proper pinning.
> 
> Solution
> --------
> 
> Ideally, Windows should fix the division-by-zero error and QEMU/libvirt
> should support pinning better, but neither of them are going to happen
> anytime soon.
> 
> To allow running Windows on QEMU/libvirt or with heterogeneous cores,
> combine all host PMUs necessary to cover the cores vCPUs can run and
> keep PMCCNTR_EL0 working.

I'm extremely uneasy about making this a generalized solution. PMUs are
deeply tied to the microarchitecture of a particular implementation, and
that isn't something we can abstract away from the guest in KVM.

For example, you could have an event ID that counts on only a subset of
cores, or better yet an event that counts something completely different
depending on where a vCPU lands.

I do appreciate the issue that you're trying to solve.

The good news though is that the fixed PMU cycle counter is the only
thing guaranteed to be present in any PMUv3 implementation. Since
that's the only counter Windows actually needs, perhaps we could
special-case this in KVM.

I have the following (completely untested) patch, do you want to give it
a try? There's still going to be observable differences between PMUs
(e.g. CPU frequency) but at least it should get things booting.

Thanks,
Oliver

---
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index a1bc10d7116a..913a7bab50b5 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -724,14 +724,21 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
 		return;
 
 	memset(&attr, 0, sizeof(struct perf_event_attr));
-	attr.type = arm_pmu->pmu.type;
+
+	if (pmc->idx == ARMV8_PMU_CYCLE_IDX) {
+		attr.type = PERF_TYPE_HARDWARE;
+		attr.config = PERF_COUNT_HW_CPU_CYCLES;
+	} else {
+		attr.type = arm_pmu->pmu.type;
+		attr.config = eventsel;
+	}
+
 	attr.size = sizeof(attr);
 	attr.pinned = 1;
 	attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
 	attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
 	attr.exclude_hv = 1; /* Don't count EL2 events */
 	attr.exclude_host = 1; /* Don't count host events */
-	attr.config = eventsel;
 
 	/*
 	 * Filter events at EL1 (i.e. vEL2) when in a hyp context based on the


From krzk at kernel.org  Wed Mar 19 00:37:12 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:37:12 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <06244bfb-1bd0-4a07-a928-3d2e68a89259@foss.st.com>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
 <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>
 <ac119dba-6e73-496c-97e1-d59ac0fe4a27@kernel.org>
 <06244bfb-1bd0-4a07-a928-3d2e68a89259@foss.st.com>
Message-ID: <f508b96e-81c8-41bd-baca-ebd1b4419904@kernel.org>

On 18/03/2025 14:40, Patrice CHOTARD wrote:
> 
> 
> On 3/13/25 08:33, Krzysztof Kozlowski wrote:
>> On 12/03/2025 15:23, Patrice CHOTARD wrote:
>>>>> +static int stm32_omm_disable_child(struct device *dev)
>>>>> +{
>>>>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>>>>> +	struct reset_control *reset;
>>>>> +	int ret;
>>>>> +	u8 i;
>>>>> +
>>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>>> +		ret = clk_prepare_enable(omm->child[i].clk);
>>>>> +		if (ret) {
>>>>> +			dev_err(dev, "Can not enable clock\n");
>>>>> +			return ret;
>>>>> +		}
>>>>> +
>>>>> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
>>>>> +		if (IS_ERR(reset)) {
>>>>> +			dev_err(dev, "Can't get child reset\n");
>>>>
>>>> Why do you get reset of child? Parent is not suppposed to poke there.
>>>> You might not have the reset there in the first place and it would not
>>>> be an error.
>>>
>>> By ressetting child (OSPI), we ensure they are disabled and in a known state.
>>> See the comment below.
>>>
>>>>
>>>>
>>>>> +			return PTR_ERR(reset);
>>>>> +		};
>>>>> +
>>>>> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
>>>>> +		reset_control_assert(reset);
>>>>> +		udelay(2);
>>>>> +		reset_control_deassert(reset);
>>>>
>>>> No, the child should handle this, not parent.
>>>
>>> Octo Memory Manager can only be configured if both child are disabled.
>>> That's why here, parent handles this.
>>
>> So if device by any chance started and is doing some useful work, then
>> you cancel that work and reset it?
> 
> stm32_omm_configure() is only called if we get access granted on both children.
> That means we are authorized to use these devices, so we can reset them.
> 
>>
>> And what if child does not have reset line? Your binding allows that, so
>> how is it supposed to work then?
> 
> Ah yes, you are right, the OSPI bindings need to be updated
> by requiring reset lines and the driver spi-stm32-ospi.c as well.
> I will send a fix for that.
> 
> Thanks for pointing this.
> 
>>
>> This also leads me to questions about bindings - if you need to assert
>> some reset, doesn't it mean that these resets are also coming through
>> this device so they are part of this device node?
> 
> As we are able to retrieve children's reset from their respective node,
> if you don't mind, OMM bindings can be kept as it's currently.

But that is what the entire discussion is about - I do mind. I said it
already - you are not supposed to poke into child's node.

If you need to toggle child's resources, then I claim these are your
resources as well.

> 
> And another information, on some MP2 SoCs family, there is only one 
> OSPI instance. So for these SoCs, there is no Octo Memory Manager.
> 
>>
>>>
>>>>
>>>>> +
>>>>> +		reset_control_put(reset);
>>>>> +		clk_disable_unprepare(omm->child[i].clk);
>>>>> +	}
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>> +static int stm32_omm_probe(struct platform_device *pdev)
>>>>> +{
>>>>> +	struct platform_device *vdev;
>>>>> +	struct device *dev = &pdev->dev;
>>>>> +	struct stm32_omm *omm;
>>>>> +	struct clk *clk;
>>>>> +	int ret;
>>>>> +	u8 child_access_granted = 0;
>>>>
>>>> Keep inits/assignments together
>>>
>>> ok
>>>
>>>>
>>>>> +	u8 i, j;
>>>>> +	bool child_access[OMM_CHILD_NB];
>>>>> +
>>>>> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
>>>>> +	if (!omm)
>>>>> +		return -ENOMEM;
>>>>> +
>>>>> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
>>>>> +	if (IS_ERR(omm->io_base))
>>>>> +		return PTR_ERR(omm->io_base);
>>>>> +
>>>>> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
>>>>> +	if (IS_ERR(omm->mm_res))
>>>>> +		return PTR_ERR(omm->mm_res);
>>>>> +
>>>>> +	/* check child's access */
>>>>> +	for_each_child_of_node_scoped(dev->of_node, child) {
>>>>> +		if (omm->nb_child >= OMM_CHILD_NB) {
>>>>> +			dev_err(dev, "Bad DT, found too much children\n");
>>>>> +			ret = -E2BIG;
>>>>> +			goto err_clk_release;
>>>>> +		}
>>>>> +
>>>>> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
>>>>> +			ret = -EINVAL;
>>>>> +			goto err_clk_release;
>>>>> +		}
>>>>> +
>>>>> +		ret = stm32_omm_check_access(dev, child);
>>>>> +		if (ret < 0 && ret != -EACCES)
>>>>> +			goto err_clk_release;
>>>>> +
>>>>> +		child_access[omm->nb_child] = false;
>>>>> +		if (!ret) {
>>>>> +			child_access_granted++;
>>>>> +			child_access[omm->nb_child] = true;
>>>>> +		}
>>>>> +
>>>>> +		omm->child[omm->nb_child].node = child;
>>>>> +
>>>>> +		clk = of_clk_get(child, 0);
>>>>
>>>> Why are you taking children clock? And why with this API, not clk_get?
>>>
>>> I need children's clock to reset them.
>>
>>
>> The device driver should reset its device. It is not a discoverable bus,
>> that would explain power sequencing from the parent.
>>
>>> Why of_clk_get() usage is a problem here ? i can't get your point ?
>>
>> Because it is not the API which device drivers should use. You should
>> use clk_get or devm_clk_get.
> 
> 
> ok, i will update this part using clk_get().
> 
>>
>>
>>>
>>>> This looks like mixing clock provider in the clock consumer.
>>>>
>>>>> +		if (IS_ERR(clk)) {
>>>>> +			dev_err(dev, "Can't get child clock\n");
>>>>
>>>> Syntax is always return dev_err_probe (or ret = dev_err_probe).
>>>
>>> ok
>>>
>>>>
>>>>> +			ret = PTR_ERR(clk);
>>>>> +			goto err_clk_release;
>>>>> +		};
>>>>> +
>>>>> +		omm->child[omm->nb_child].clk = clk;
>>>>> +		omm->nb_child++;
>>>>> +	}
>>>>> +
>>>>> +	if (omm->nb_child != OMM_CHILD_NB) {
>>>>> +		ret = -EINVAL;
>>>>> +		goto err_clk_release;
>>>>> +	}
>>>>> +
>>>>> +	platform_set_drvdata(pdev, omm);
>>>>> +
>>>>> +	pm_runtime_enable(dev);
>>>>> +
>>>>> +	/* check if OMM's resource access is granted */
>>>>> +	ret = stm32_omm_check_access(dev, dev->of_node);
>>>>> +	if (ret < 0 && ret != -EACCES)
>>>>> +		goto err_clk_release;
>>>>> +
>>>>> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
>>>>> +		/* Ensure both OSPI instance are disabled before configuring OMM */
>>>>> +		ret = stm32_omm_disable_child(dev);
>>>>> +		if (ret)
>>>>> +			goto err_clk_release;
>>>>> +
>>>>> +		ret = stm32_omm_configure(dev);
>>>>> +		if (ret)
>>>>> +			goto err_clk_release;
>>>>> +	} else {
>>>>> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
>>>>> +		/*
>>>>> +		 * AMCR can't be set, so check if current value is coherent
>>>>> +		 * with memory-map areas defined in DT
>>>>> +		 */
>>>>> +		ret = stm32_omm_set_amcr(dev, false);
>>>>> +		if (ret)
>>>>> +			goto err_clk_release;
>>>>> +	}
>>>>> +
>>>>> +	/* for each child, if resource access is granted and status "okay", probe it */
>>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>>> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
>>>>
>>>> If you have a device available, why do you create one more platform device?
>>>>
>>>>> +			continue;
>>>>> +
>>>>> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
>>>>
>>>> Why you cannot just populate the children?
>>>
>>> I can't use of_platform_populate(), by default it will populate all OMM's child.
>>> Whereas here, we want to probe only the OMM's child which match our criteria.  
>>
>>
>> Why wouldn't you populate everyone? The task of bus driver is not to
>> filter out DT. If you got such DT - with all device nodes - you are
>> expected to populate all of them. Otherwise, if you do not want all of
>> them, it is expected that firmware or bootloader will give you DT
>> without these nodes.
> 
> We don't want to populate every child by default because we can get 
> cases where one child is shared between Cortex A and Cortex M.

But in such case DTB would not have that child enabled.

> That's why we must check if access is granted which ensure that 
> firewall semaphore is available (RIFSC semaphore in our case).

If you do not have access, means child is assigned to other processor,
right? In that case that child would not have been enabled in your DTB.

Fix your DTB instead of creating another layer of handling children
inside drivers.


Best regards,
Krzysztof


From jens.wiklander at linaro.org  Wed Mar 19 00:37:38 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Wed, 19 Mar 2025 08:37:38 +0100
Subject: [PATCH v4 0/6] TEE subsystem for restricted dma-buf allocations
In-Reply-To: <32c29526416c07c37819aedabcbf1e562ee98bf2.camel@ndufresne.ca>
References: <CAHUa44G9hw-z6wzxg=HkVAxPKEW1yES5JTEqRWMvJUJAtcUDkQ@mail.gmail.com>
 <CAPj87rPHnME5Osgnf5-FSAu22mDpLj=dzvhi_NqEcOwr1ThgGw@mail.gmail.com>
 <CAHUa44Gs0D1fBD0=+EDgcQUMeDv4knci9trUkYEc1J98qFV7HQ@mail.gmail.com>
 <CAFA6WYOuTwRPEh3L7+hMyARB_E73xmp+OwhKyS-r4+ryS7=9sw@mail.gmail.com>
 <20250214164856.0d2ead8a@collabora.com> <CAFA6WYPc6EHQwcPuMZRm4C1P6SoDrCzEPUmju_meupB6NXQ1sg@mail.gmail.com>
 <CAPj87rN-OYTzh5=Gdv619UQD5=x=U6Yt=uV4N1kCs4Zao4RVAg@mail.gmail.com>
 <CAFA6WYMLLLSuz3y5J+DuRFAGrmwpZoWax5sasfAUhXoQXmrNNA@mail.gmail.com>
 <CAPj87rN7J6u9NsviAdw8=OenEYc8t719Lds6u6-BhFKrtkLZ-A@mail.gmail.com>
 <CAHUa44FkG1NAWpoW8UVBywv44XW_mjAJa32PcC9mcmiOLdiRqw@mail.gmail.com>
 <Z8avsigZJ4vqmiA4@sumit-X1> <32c29526416c07c37819aedabcbf1e562ee98bf2.camel@ndufresne.ca>
Message-ID: <CAHUa44E11jYFrAFrZmNVTpLJ-XDs45QyTr-_DbeWBOQ0DjHPkQ@mail.gmail.com>

Hi,

On Tue, Mar 18, 2025 at 7:38?PM Nicolas Dufresne <nicolas at ndufresne.ca> wrote:
>
> Le mardi 04 mars 2025 ? 13:15 +0530, Sumit Garg a ?crit :
> > On Tue, Mar 04, 2025 at 08:17:23AM +0100, Jens Wiklander wrote:
> > > Hi Daniel,
> > >
> > > On Fri, Feb 21, 2025 at 3:12?PM Daniel Stone <daniel at fooishbar.org> wrote:
> > > >
> > > > Hi Sumit,
> > > >
> > > > On Fri, 21 Feb 2025 at 11:24, Sumit Garg <sumit.garg at linaro.org> wrote:
> > > > > On Tue, 18 Feb 2025 at 21:52, Daniel Stone <daniel at fooishbar.org> wrote:
> > > > > > dma-heaps was created to solve the problem of having too many
> > > > > > 'allocate $n bytes from $specialplace' uAPIs. The proliferation was
> > > > > > painful and making it difficult for userspace to do what it needed to
> > > > > > do. Userspace doesn't _yet_ make full use of it, but the solution is
> > > > > > to make userspace make full use of it, not to go create entirely
> > > > > > separate allocation paths for unclear reasons.
> > > > > >
> > > > > > Besides, I'm writing this from a platform that implements SVP not via
> > > > > > TEE. I've worked on platforms which implement SVP without any TEE,
> > > > > > where the TEE implementation would be at best a no-op stub, and at
> > > > > > worst flat-out impossible.
> > > > >
> > > > > Can you elaborate the non-TEE use-case for Secure Video Path (SVP) a
> > > > > bit more? As to how the protected/encrypted media content pipeline
> > > > > works? Which architecture support does your use-case require? Is there
> > > > > any higher privileged level firmware interaction required to perform
> > > > > media content decryption into restricted memory? Do you plan to
> > > > > upstream corresponding support in near future?
> > > >
> > > > You can see the MTK SVP patches on list which use the MTK SMC to mediate it.
> > > >
> > > > There are TI Jacinto platforms which implement a 'secure' area
> > > > configured statically by (IIRC) BL2, with static permissions defined
> > > > for each AXI endpoint, e.g. CPU write + codec RW + dispc read. I've
> > > > heard of another SoC vendor doing the same, but I don't think I can
> > > > share those details. There is no TEE interaction.
> > > >
> > > > I'm writing this message from an AMD laptop which implements
> > > > restricted content paths outside of TEE. I don't have the full picture
> > > > of how SVP is implemented on AMD systems, but I do know that I don't
> > > > have any TEE devices exposed.
> > > >
> > > > > Let me try to elaborate on the Secure Video Path (SVP) flow requiring
> > > > > a TEE implementation (in general terms a higher privileged firmware
> > > > > managing the pipeline as the kernel/user-space has no access
> > > > > permissions to the plain text media content):
> > > > >
> > > > > - [...]
> > > >
> > > > Yeah, I totally understand the TEE usecase. I think that TEE is a good
> > > > design to implement this. I think that TEE should be used for SVP
> > > > where it makes sense.
> > > >
> > > > Please understand that I am _not_ arguing that no-one should use TEE for SVP!
> > > >
> > > > > > So, again, let's
> > > > > > please turn this around: _why_ TEE? Who benefits from exposing this as
> > > > > > completely separate to the more generic uAPI that we specifically
> > > > > > designed to handle things like this?
> > > > >
> > > > > The bridging between DMA heaps and TEE would still require user-space
> > > > > to perform an IOCTL into TEE to register the DMA-bufs as you can see
> > > > > here [1]. Then it will rather be two handles for user-space to manage.
> > > >
> > > > Yes, the decoder would need to do this. That's common though: if you
> > > > want to share a buffer between V4L2 and DRM, you have three handles:
> > > > the V4L2 buffer handle, the DRM GEM handle, and the dmabuf you use to
> > > > bridge the two.
> > > >
> > > > > Similarly during restricted memory allocation/free we need another
> > > > > glue layer under DMA heaps to TEE subsystem.
> > > >
> > > > Yep.
> > > >
> > > > > The reason is simply which has been iterated over many times in the
> > > > > past threads that:
> > > > >
> > > > >     "If user-space has to interact with a TEE device for SVP use-case
> > > > > then why it's not better to ask TEE to allocate restricted DMA-bufs
> > > > > too"
> > > >
> > > > The first word in your proposition is load-bearing.
> > > >
> > > > Build out the usecase a little more here. You have a DRMed video
> > > > stream coming in, which you need to decode (involving TEE for this
> > > > usecase). You get a dmabuf handle to the decoded frame. You need to
> > > > pass the dmabuf across to the Wayland compositor. The compositor needs
> > > > to pass it to EGL/Vulkan to import and do composition, which in turn
> > > > passes it to the GPU DRM driver. The output of the composition is in
> > > > turn shared between the GPU DRM driver and the separate KMS DRM
> > > > driver, with the involvement of GBM.
> > > >
> > > > For the platforms I'm interested in, the GPU DRM driver needs to
> > > > switch into protected mode, which has no involvement at all with TEE -
> > > > it's architecturally impossible to have TEE involved without moving
> > > > most of the GPU driver into TEE and destroying performance. The
> > > > display hardware also needs to engage protected mode, which again has
> > > > no involvement with TEE and again would need to have half the driver
> > > > moved into TEE for no benefit in order to do so. The Wayland
> > > > compositor also has no interest in TEE: it tells the GPU DRM driver
> > > > about the protected status of its buffers, and that's it.
> > > >
> > > > What these components _are_ opinionated about, is the way buffers are
> > > > allocated and managed. We built out dmabuf modifiers for this usecase,
> > > > and we have a good negotiation protocol around that. We also really
> > > > care about buffer placement in some usecases - e.g. some display/codec
> > > > hardware requires buffers to be sourced from contiguous memory, other
> > > > hardware needs to know that when it shares buffers with another
> > > > device, it needs to place the buffers outside of inaccessible/slow
> > > > local RAM. So we built out dma-heaps, so every part of the component
> > > > in the stack can communicate their buffer-placement needs in the same
> > > > way as we do modifiers, and negotiate an acceptable allocation.
> > > >
> > > > That's my starting point for this discussion. We have a mechanism to
> > > > deal with the fact that buffers need to be shared between different IP
> > > > blocks which have their own constraints on buffer placement, avoiding
> > > > the current problem of having every subsystem reinvent their own
> > > > allocation uAPI which was burying us in impedance mismatch and
> > > > confusion. That mechanism is dma-heaps. It seems like your starting
> > > > point from this discussion is that you've implemented a TEE-centric
> > > > design for SVP, and so all of userspace should bypass our existing
> > > > cross-subsystem special-purpose allocation mechanism, and write
> > > > specifically to one implementation. I believe that is a massive step
> > > > backwards and an immediate introduction of technical debt.
> > > >
> > > > Again, having an implementation of SVP via TEE makes a huge amount of
> > > > sense. Having _most_ SVP implementations via TEE still makes a lot of
> > > > sense. Having _all_ SVP implementations eventually be via TEE would
> > > > still make sense. But even if we were at that point - which we aren't
> > > > - it still doesn't justify telling userspace 'use the generic dma-heap
> > > > uAPI for every device-specific allocation constraint, apart from SVP
> > > > which has a completely different way to allocate some bytes'.
> > >
> > > I must admit that I don't see how this makes a significant difference,
> > > but then I haven't hacked much in the stacks you're talking about, so
> > > I'm going to take your word for it.
> > >
> > > I've experimented with providing a dma-heap replacing the TEE API. The
> > > implementation is more complex than I first anticipated, adding about
> > > 400 lines to the patch set.
> >
> > I did anticipated this but let's give it a try and see if DMA heaps
> > really adds any value from user-space point of view. If it does then it
> > will be worth the maintenence overhead.
> >
> > > From user space, it looks like another
> > > dma-heap. I'm using the names you gave earlier,
> > > protected,secure-video, protected,trusted-ui, and
> > > protected,secure-video-record. However, I wonder if we shouldn't use
> > > "restricted" instead of "protected" since we had agreed to call it
> > > restricted memory earlier.
> >
> > Let's stick with "restricted" memory buffer references only.
>
> Until now, we didn't have a standard to balance our naming choice, we
> simply wanted to move away from "secure" which didn't mean much, and
> restricted met our needs. I think the discussion is worth having again,
> now that there is a standard that decided toward "protected". Matchcing
> the Khronos standard means reducing a lot of confusion.
>
> https://docs.vulkan.org/guide/latest/protected.html

Yeah, that's fine with me. I don't mind changing the name again as
long as we progress. The latest version of the patchset is here [1].
I've published a demo and changed the patchset to provide a heap
interface instead of a special interface in the TEE subsystem for
memory allocations as requested. I'm interested in feedback on the
patches in general, but in particular, on how the heap interface is
provided.

[1] https://lore.kernel.org/lkml/20250305130634.1850178-1-jens.wiklander at linaro.org/

Cheers,
Jens


From krzk at kernel.org  Wed Mar 19 00:39:52 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:39:52 +0100
Subject: [PATCH 09/13] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <67d95979.050a0220.166852.25e6@mx.google.com>
References: <20250309132959.19045-1-ansuelsmth@gmail.com>
 <20250309132959.19045-10-ansuelsmth@gmail.com>
 <4f16d239-f540-45d5-b67a-767b09f1c70c@kernel.org>
 <67d0862f.df0a0220.375bd.6b15@mx.google.com>
 <4a9ac302-dfbe-4d76-a634-a445957c313c@kernel.org>
 <67d95979.050a0220.166852.25e6@mx.google.com>
Message-ID: <cd445f29-ea01-4e57-b1b7-4e9c3bfbcc8f@kernel.org>

On 18/03/2025 12:31, Christian Marangi wrote:
> On Sun, Mar 16, 2025 at 06:01:02PM +0100, Krzysztof Kozlowski wrote:
>> On 11/03/2025 19:51, Christian Marangi wrote:
>>>>
>>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>>> +    enum: [0, 1]
>>>>
>>>> I don't understand why do you need index property here (which are
>>>> usually not allowed).
>>>>
>>>
>>> Eh... As said in the description this is really to differentiate the 2
>>> different physical port...
>>>
>>> Each port have a dedicated oscillator for calibration and these
>>> calibration are identified by an offset (all placed one after another in
>>> a separate register space).
>>
>> So different oscillators? Then describe the oscillator and its differences.
>>
>> Different programing model? Different compatible.
>>
>> Other difference? Depending what is the difference.
>>
>> But there is no such thing as "different port ID" based on your
>> description above. You just claimed that they are different, but you do
>> not put that difference to hardware description. Instead you encode that
>> difference in the drivers and it should be opposite. The DTS, so the
>> hardware description, should tell you the difference. And I am sorry,
>> but in 99% of cases "I am the first phy" and "I am the second" is not
>> the actual difference we are interested in.
>>
> 
> Ok to make it as clear as possible. (hope I don't contraddict with the
> previous statement) (actually yes the "separate register space statement
> was wrong and sorry for the confusion")
> 
> - 2 USB port
> - USB 2.0 needs to be calibrated with an oscillator
> - Each USB port have his own dedicated oscillator somewhere in the HW
> - Each USB port have at the same offset a register to SELECT the
>   oscillator. This register refer to the same oscillator selection in
>   the HW.
>   
>   Example:
>   reg 0x1fac0100 MASK 27:26 can be set to source out of oscillator 0,1,2
>   reg 0x1fae0100 MASK 27:26 can be set to source out of oscillator 0,1,2

So that's your difference between devices - you choose the oscillator.

> 
>   Both register refer to the same oscillators in hardware (hence each
>   port should select the correct one)
>   Selecting oscillator 0 for both USB port is problematic.
> 
> With this in mind is it ok if I describe this with something like
> 
> airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL0>;
> 
> and some dt-bindings include
> 
> #define AIROHA_USB2_MONCLK_SEL0 0
> #define AIROHA_USB2_MONCLK_SEL1 1
> #define AIROHA_USB2_MONCLK_SEL2 2
> #define AIROHA_USB2_MONCLK_SEL3 3
> 
> Or an enum of string like "osc0", "osc1", "osc2"...?

Both are fine.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 00:44:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:44:32 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
Message-ID: <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>

On 17/03/2025 10:21, Ryan Chen wrote:
>> Neither this.
>>
>> So it seems you describe already existing and documented I2C, but for some
>> reason you want second compatible. The problem is that you do not provide
>> reason from the point of view of bindings.
>>
>> To summarize: what your users want - don't care. Start properly describing
>> hardware and your SoC.
> 
> OK, for ast2600 i2c controller have two register mode setting.
> One, I call it is old register setting, that is right now i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus",
> And there have a global register that can set i2c controller as new mode register set. 
> That I am going to drive. That I post is all register in new an old register list.
> 
> For example, 
> Global register [2] = 0 => i2c present as old register set
> Global register [2] = 1 => i2c present as new register set
It's the same device though, so the same compatible.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 00:46:36 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 08:46:36 +0100
Subject: [PATCH 1/2] dt-bindings: misc: bist: Add BIST dt-binding for TI
 K3 devices
In-Reply-To: <8e58b093-1c64-45b9-a9d3-9835a3bbc4fd@ti.com>
References: <20241128140825.263216-1-n-francis@ti.com>
 <20241128140825.263216-2-n-francis@ti.com>
 <ho7ktcnbtl7mvamfthqho23co2fc4z7bgjha7pu4wivxm6ndhu@tfbpveonhckz>
 <837d329b-bcdd-4c3b-b508-e916b110ce25@ti.com>
 <e57dfc3e-b702-4803-b776-20c6dbd98fef@kernel.org>
 <8e58b093-1c64-45b9-a9d3-9835a3bbc4fd@ti.com>
Message-ID: <1da4e402-62f3-4bad-9129-1f5a08148987@kernel.org>

On 13/03/2025 12:14, Neha Malcom Francis wrote:
> Hi Krzysztof
> 
> On 29/11/24 14:45, Krzysztof Kozlowski wrote:
>> On 29/11/2024 08:43, Neha Malcom Francis wrote:
>>>>> +
>>>>> +  power-domains:
>>>>> +    maxItems: 1
>>>>> +
>>>>> +  ti,bist-instance:
>>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>>> +    description:
>>>>> +      the BIST instance in the SoC represented as an integer
>>>>
>>>> No instance indices are allowed. Drop.
>>>>
>>>
>>> Question on this, this is not a property that is driven by software but rather 
>>> indicates which register sequences have to be picked up for triggering this test 
>>> from this instance. So I don't see how I can workaround this without getting 
>>> this number. Or maybe call it ID rather than instance?
>>
>> I don't understand how the device operates, so what is exactly behind
>> some sequences of registers for triggering this test. You described
>> property as index or ID of one instance of the block. That's not what we
>> want in the binding. That's said maybe other, different hardware
>> characteristic is behind, who knows. Or maybe it's about callers... or
>> maybe that's not hardware property at all, but runtime OS, who knows.
>>
> 
> Sorry for such a late reply, but I was hoping to get more details on
> this "ID" and never got back to the thread...
> 
> The best way I can describe is this device (BIST) runs a safety
> diagnostic test on a bunch of processors/blocks (let's call them
> targets). There's a mapping between the instance of this device and the
> targets it will run the test. This ID was essentially letting the BIST
> driver know which are these targets.


So you want to configure some target? Then this is your property. If you
want to configure 'foo' difference in DT, you do not write 'bar'...

Anyway, no clue, original emails are long time not in my inbox. Context
disappeared also long time ago.


Best regards,
Krzysztof


From frieder.schrempf at kontron.de  Wed Mar 19 00:52:39 2025
From: frieder.schrempf at kontron.de (Frieder Schrempf)
Date: Wed, 19 Mar 2025 08:52:39 +0100
Subject: imx8mp: HDMI display blank/black problems
In-Reply-To: <CAGETcx-LGZ1k-seh4LkvCobsxUk67QK40swiQvH6Wrzs0Log0A@mail.gmail.com>
References: <20240203165307.7806-1-aford173@gmail.com>
 <20241025080544.136280-1-mailinglist1@johanneskirchmair.de>
 <6d039ecf-0e48-415a-afd8-6bfce60081ae@kontron.de>
 <CAHCN7xKevGWipBSch6gKVeJRT9Zb8QTchhxg3c=96XhnAvnjZw@mail.gmail.com>
 <CAGETcx-LGZ1k-seh4LkvCobsxUk67QK40swiQvH6Wrzs0Log0A@mail.gmail.com>
Message-ID: <15acbb84-efa1-4ca6-bbfd-a4c3f17a7d19@kontron.de>

Am 30.10.24 um 9:20 PM schrieb Saravana Kannan:
> On Wed, Oct 30, 2024 at 10:28?AM Adam Ford <aford173 at gmail.com> wrote:
>>
>> On Wed, Oct 30, 2024 at 4:01?AM Frieder Schrempf
>> <frieder.schrempf at kontron.de> wrote:
>>>
>>> Hi Johannes,
>>>
>>> On 25.10.24 10:05 AM, mailinglist1 at johanneskirchmair.de wrote:
>>>> [Sie erhalten nicht h?ufig E-Mails von mailinglist1 at johanneskirchmair.de. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
>>>>
>>>> Hey,
>>>> We had some problems with the hdmi on the imx8mp and wanted to leave, what we found out about it, somewhere for others to find it.
>>>>
>>>> The problem was that our hdmi display sometimes stayed blank after hot plugging and sometimes at startup. On older kernel versions 6.6 we did not have the problem with the not mainlined hdmi patches.
>>>> We tracked the commit down that introduced the problem for us. It was the following ?driver core: Enable fw_devlink=rpm by default?  https://lore.kernel.org/lkml/20231113220948.80089-1-saravanak at google.com/
>>>> So we switched back to FW_DEVLINK_FLAGS_ON via kernel parameter. Don?t really understand what the problem with RPM is.
>>>>
>>>> So, this information is just for reference. Maybe someone has an idea what is going on here. And how to fix the problem in a more proper way.
>>>
>>> Thanks for investigating and sharing your results!
>>>
>>> I'm seeing the same symptoms and previously found out that this is
>>> related to LCDIF underrun errors. See [1] for more information.
>>>
>>> Adam has also started this thread: [2].
>>>
>>> Anyway, knowing that this is related to fw_devlink=rpm is really
>>> helpful. I just tried with fw_devlink=on and wasn't able to see any
>>> issues anymore. So this confirms your findings.
>>
>> I was off in the weeds thinking there was something wrong in timing
>> and/or a race condition around the PLL or something.  This is good
>> news.
>> Please forgive my ignorance, what does fw_devlink do?  Is there
>> something we can do in the driver itself to force its behavior?
> 
> fw_devlink figures out supplier/consumer dependencies between devices
> and creates device links between them. This ensures proper
> probe/suspend/resume/shutdown/runtime PM ordering.
> 
> fw_devlink=rpm vs on means "enforce all of these" vs "enforce all of
> these except runtime PM".
> 
>> adam
>>>
>>> I hope that some of the driver framework and runtime PM experts can help
>>> to find out what is actually wrong and how the correct fix might look like.
>>>
>>> I'm also CC-ing Saravana who authored the change from fw_devlink=on to
>>> fw_devlink=rpm to see if they have anything to add.
> 
> When fw_devlink=rpm, you'll have device links created between
> consumers and suppliers with the DL_FLAG_PM_RUNTIME flag set. So
> before your device is runtime resumed, it'll make sure all your
> suppliers are resumed first.
> 
> My guess is that there is some issue in the runtime PM handling in
> these drivers. I don't have enough context to provide further insight.

I bet you are right. I tried to have a closer look but unfortunately I
didn't make any progress.

The drivers involved are lcdif_drv.c, imx8mp-hdmi-tx.c and
phy-fsl-samsung-hdmi.c.

As we see a "LCDIF Underrun Error" with fw_devlink=rpm my first guess
would be that the suppliers of LCDIF are maybe turned on in the wrong order.

Lucas, Marek: As the main authors of these drivers, do you think you
could help a little with further debugging? Any ideas?

Thanks!


From peter.wang at mediatek.com  Wed Mar 19 00:56:31 2025
From: peter.wang at mediatek.com (=?utf-8?B?UGV0ZXIgV2FuZyAo546L5L+h5Y+LKQ==?=)
Date: Wed, 19 Mar 2025 07:56:31 +0000
Subject: [PATCH v3 1/1] scsi: ufs: core: add device level exception
 support
In-Reply-To: <6109425449ac4d18249ce7254e4fa1252138a94a.1742369183.git.quic_nguyenb@quicinc.com>
References: <6109425449ac4d18249ce7254e4fa1252138a94a.1742369183.git.quic_nguyenb@quicinc.com>
Message-ID: <61570104d58cef22716fefe459c0c45670108aad.camel@mediatek.com>

On Wed, 2025-03-19 at 00:29 -0700, Bao D. Nguyen wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> The ufs device JEDEC specification version 4.1 adds support for the
> device level exception events. To support this new device level
> exception feature, expose two new sysfs nodes below to provide
> the user space access to the device level exception information.
> /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
> /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id
> 
> The device_lvl_exception_count sysfs node reports the number of
> device level exceptions that have occurred since the last time
> this variable is reset. Writing a value of 0 will reset it.
> The device_lvl_exception_id reports the exception ID which is the
> qDeviceLevelExceptionID attribute of the device JEDEC specifications
> version 4.1 and later. The user space application can query these
> sysfs nodes to get more information about the device level exception.
> 
> Signed-off-by: Bao D. Nguyen <quic_nguyenb at quicinc.com>
> Reviewed-by: Peter Wang <peter.wang at mediatek.com>
> ---
> Changes in v3:
> 1. Add protection for hba->dev_lvl_exception_count accesses in
> different
> contexts (Bart's comment).

Hi Bao,

Could use atomic_t for counter protect?

Thanks.
Peter


From christophe.leroy at csgroup.eu  Wed Mar 19 01:05:27 2025
From: christophe.leroy at csgroup.eu (Christophe Leroy)
Date: Wed, 19 Mar 2025 09:05:27 +0100
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <20250318155946.GC13829@willie-the-truck>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
 <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
 <20250318155946.GC13829@willie-the-truck>
Message-ID: <a64bf821-ea90-4fd9-92ec-13bf7b7a3067@csgroup.eu>



Le 18/03/2025 ? 16:59, Will Deacon a ?crit?:
> On Thu, Mar 13, 2025 at 05:40:59PM +0100, Alessandro Carminati wrote:
>> On Thu, Mar 13, 2025 at 1:25?PM Will Deacon <will at kernel.org> wrote:
>>>
>>> On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
>>>> diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
>>>> index 28be048db3f6..044c5e24a17d 100644
>>>> --- a/arch/arm64/include/asm/bug.h
>>>> +++ b/arch/arm64/include/asm/bug.h
>>>> @@ -11,8 +11,14 @@
>>>>
>>>>   #include <asm/asm-bug.h>
>>>>
>>>> +#ifdef HAVE_BUG_FUNCTION
>>>> +# define __BUG_FUNC  __func__
>>>> +#else
>>>> +# define __BUG_FUNC  NULL
>>>> +#endif
>>>> +
>>>>   #define __BUG_FLAGS(flags)                           \
>>>> -     asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
>>>> +     asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
>>>
>>> Why is 'i' the right asm constraint to use here? It seems a bit odd to
>>> use that for a pointer.
>>
>> I received this code as legacy from a previous version.
>> In my review, I considered the case when HAVE_BUG_FUNCTION is defined:
>> Here, __BUG_FUNC is defined as __func__, which is the name of the
>> current function as a string literal.
>> Using the constraint "i" seems appropriate to me in this case.
>>
>> However, when HAVE_BUG_FUNCTION is not defined:
>> __BUG_FUNC is defined as NULL. Initially, I considered it literal 0,
>> but after investigating your concern, I found:
>>
>> ```
>> $ echo -E "#include <stdio.h>\n#include <stddef.h>\nint main()
>> {\nreturn 0;\n}" | aarch64-linux-gnu-gcc -E -dM - | grep NULL
>> #define NULL ((void *)0)
>> ```
>>
>> I realized that NULL is actually a pointer that is not a link time
>> symbol, and using the "i" constraint with NULL may result in undefined
>> behavior.
>>
>> Would the following alternative definition for __BUG_FUNC be more convincing?
>>
>> ```
>> #ifdef HAVE_BUG_FUNCTION
>>      #define __BUG_FUNC __func__
>> #else
>>      #define __BUG_FUNC (uintptr_t)0
>> #endif
>> ```
>> Let me know your thoughts.
> 
> Thanks for the analysis; I hadn't noticed this specific issue, it just
> smelled a bit fishy. Anyway, the diff above looks better, thanks.

That propably deserves a comment.

Doesn't sparse and/or checkpatch complain about 0 being used in lieu of 
NULL ?

By the way I had similar problem in the past with GCC not seeing NULL as 
a __builtin_constant_p(), refer commit 1d8f739b07bd ("powerpc/kuap: Fix 
set direction in allow/prevent_user_access()")

Christophe


From krzk at kernel.org  Wed Mar 19 01:23:02 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:23:02 +0100
Subject: [PATCH v4 3/6] dt-bindings: Asoc: axg-audio: Add s4 audio tocodec
In-Reply-To: <20250319-audio_drvier-v4-3-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-3-686867fad719@amlogic.com>
Message-ID: <20250319-panda-of-unknown-wonder-236812@krzk-bin>

On Wed, Mar 19, 2025 at 03:04:46PM +0800, jiebing chen wrote:
> Add the s4 tocodec compatible
> 
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---

So you just ignored everything you received?

Best regards,
Krzysztof



From leo.yan at arm.com  Wed Mar 19 01:24:23 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 19 Mar 2025 08:24:23 +0000
Subject: [PATCH v2 2/8] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>
Message-ID: <20250319082423.GC2860028@e132581.arm.com>

On Tue, Mar 18, 2025 at 04:21:56PM +0000, James Clark wrote:
> The self hosted claim tag will be reset on device probe in a later
> commit. We'll want to do this before coresight_register() is called so
> won't have a coresight_device and have to use cs_access instead.
> 
> Also make them public and create locked and unlocked versions for
> later use.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-core.c | 17 +++++++++++++----
>  include/linux/coresight.h                    |  3 ++-
>  2 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 3f1c996d668a..9ff601e2415a 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -151,12 +151,21 @@ static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
>  	isb();
>  }
>  
> -static inline void coresight_clear_self_claim_tag(struct coresight_device *csdev)
> +void coresight_clear_self_claim_tag(struct csdev_access *csa)
>  {
> -	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> +	CS_UNLOCK(csa->base);
> +	coresight_clear_self_claim_tag_unlocked(csa);
> +	CS_LOCK(csa->base);
> +}
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
> +
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
> +{
> +	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>  				     CORESIGHT_CLAIMCLR);
>  	isb();
>  }
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
>  
>  /*
>   * coresight_claim_device_unlocked : Claim the device for self-hosted usage
> @@ -180,7 +189,7 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
>  	if (coresight_is_claimed_self_hosted(csdev))
>  		return 0;
>  	/* There was a race setting the tag, clean up and fail */
> -	coresight_clear_self_claim_tag(csdev);
> +	coresight_clear_self_claim_tag_unlocked(&csdev->access);
>  	return -EBUSY;
>  }
>  EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
> @@ -211,7 +220,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>  		return;
>  
>  	if (coresight_is_claimed_self_hosted(csdev))
> -		coresight_clear_self_claim_tag(csdev);
> +		coresight_clear_self_claim_tag_unlocked(&csdev->access);
>  	else
>  		/*
>  		 * The external agent may have not honoured our claim
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index d79a242b271d..00134a80d358 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
>  
>  extern int coresight_claim_device(struct coresight_device *csdev);
>  extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
> -
> +void coresight_clear_self_claim_tag(struct csdev_access *csa);
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
>  extern void coresight_disclaim_device(struct coresight_device *csdev);
>  extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
>  extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
> 
> -- 
> 2.34.1
> 


From krzk at kernel.org  Wed Mar 19 01:26:31 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:26:31 +0100
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
Message-ID: <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>

On Wed, Mar 19, 2025 at 03:04:49PM +0800, jiebing chen wrote:
> Add basic audio driver support for the Amlogic S4 based
> Amlogic AQ222 board. use hifipll pll (1179648000) to
> support 768k sample rate and 24 bit (s24_le), 24bit sclk
> is 48fs, use mpll0 (270950400) to support 705.6k sample
> rate and 32bit, use mpll1 (338688000) to support 705.6k
> and 24bit.

Please wrap commit message according to Linux coding style / submission
process (neither too early nor over the limit):
https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597

> 
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>

...

> +
> +		dai-link-12 {
> +			sound-dai = <&toacodec TOACODEC_OUT>;
> +
> +			codec {
> +				sound-dai = <&acodec>;
> +			};
> +		};
> +	};
> +

Do not add stray blank lines.

>  };
>  
>  &pwm_ef {
> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
> index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
> @@ -11,7 +11,11 @@
>  #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
>  #include <dt-bindings/power/meson-s4-power.h>
>  #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
> -

Why?

> +#include <dt-bindings/clock/axg-audio-clkc.h>
> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
> +#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
> +#include <dt-bindings/sound/meson-g12a-toacodec.h>
> +#include <dt-bindings/sound/meson-g12a-tohdmitx.h>

Old style was correct.

>  / {
>  	cpus {
>  		#address-cells = <2>;
> @@ -46,6 +50,36 @@ cpu3: cpu at 3 {
>  		};
>  	};
>  
> +	tdmif_a: audio-controller-0 {
> +		compatible = "amlogic,axg-tdm-iface";
> +		#sound-dai-cells = <0>;
> +		sound-name-prefix = "TDM_A";
> +		clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_A_MCLK>;
> +		clock-names = "sclk", "lrclk","mclk";
> +	};
> +
> +	tdmif_b: audio-controller-1 {
> +		compatible = "amlogic,axg-tdm-iface";
> +		#sound-dai-cells = <0>;
> +		sound-name-prefix = "TDM_B";
> +		clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_B_MCLK>;
> +		clock-names = "sclk", "lrclk","mclk";
> +	};
> +
> +	tdmif_c: audio-controller-2 {
> +		compatible = "amlogic,axg-tdm-iface";
> +		#sound-dai-cells = <0>;
> +		sound-name-prefix = "TDM_C";
> +		clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
> +			 <&clkc_audio AUD_CLKID_MST_C_MCLK>;
> +		clock-names = "sclk", "lrclk","mclk";
> +	};
> +
>  	timer {
>  		compatible = "arm,armv8-timer";
>  		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>  			#address-cells = <2>;
>  			#size-cells = <2>;
>  			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
> -

Why? What is happening in this patch - why are you changing so many
other pieces?

>  			clkc_periphs: clock-controller at 0 {
>  				compatible = "amlogic,s4-peripherals-clkc";
>  				reg = <0x0 0x0 0x0 0x49c>;
> @@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
>  				#clock-cells = <1>;
>  			};
>  
> +			acodec: audio-controller at 1a000 {
> +				compatible = "amlogic,t9015";
> +				reg = <0x0 0x1A000 0x0 0x14>;
> +				#sound-dai-cells = <0>;
> +				sound-name-prefix = "ACODEC";
> +				clocks = <&clkc_periphs CLKID_ACODEC>;
> +				clock-names = "pclk";
> +				resets = <&reset RESET_ACODEC>;
> +				AVDD-supply = <&vddio_ao1v8>;
> +			};
> +
>  			watchdog at 2100 {
>  				compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
>  				reg = <0x0 0x2100 0x0 0x10>;
> @@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
>  		};
>  	};
>  };
> +
> +&apb4 {
> +	audio: bus at 330000 {
> +		compatible = "simple-bus";
> +		reg = <0x0 0x330000 0x0 0x1000>;

That's not a simple bus in such case.

NAK


Best regards,
Krzysztof



From krzk at kernel.org  Wed Mar 19 01:22:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:22:13 +0100
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
Message-ID: <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>

On Wed, Mar 19, 2025 at 03:04:45PM +0800, jiebing chen wrote:
> Add clock IDs for the mclk pads found on s4 SoCs
> 
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++

This belongs to the binding patch, usually.

Anyway - do not ask us to do the work twice.

<form letter>
This is a friendly reminder during the review process.

It looks like you received a tag and forgot to add it.

If you do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new
versions of patchset, under or above your Signed-off-by tag, unless
patch changed significantly (e.g. new properties added to the DT
bindings). Tag is "received", when provided in a message replied to you
on the mailing list. Tools like b4 can help here. However, there's no
need to repost patches *only* to add the tags. The upstream maintainer
will do that for tags received on the version they apply.

Please read:
https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577

If a tag was not added on purpose, please state why and what changed.
</form letter>

Best regards,
Krzysztof



From leo.yan at arm.com  Wed Mar 19 01:27:15 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 19 Mar 2025 08:27:15 +0000
Subject: [PATCH v2 4/8] coresight: Add claim tag warnings and debug
 messages
In-Reply-To: <20250318-james-coresight-claim-tags-v2-4-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-4-e9c8a9cde84e@linaro.org>
Message-ID: <20250319082715.GD2860028@e132581.arm.com>

On Tue, Mar 18, 2025 at 04:21:58PM +0000, James Clark wrote:
> Add a dev_dbg() message so that external debugger conflicts are more
> visible. There are multiple reasons for -EBUSY so a message for this
> particular one could be helpful. Add errors for and enumerate all the
> other cases that are impossible.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-core.c | 51 +++++++++++++++++-----------
>  drivers/hwtracing/coresight/coresight-priv.h |  5 ++-
>  2 files changed, 36 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index e39043a9551f..5f08845faf0d 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -135,16 +135,6 @@ static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
>  			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
>  }
>  
> -static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
> -{
> -	return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
> -}
> -
> -static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
> -{
> -	return coresight_read_claim_tags(csdev) != 0;
> -}
> -
>  static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
>  {
>  	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> @@ -180,18 +170,41 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
>   */
>  int coresight_claim_device_unlocked(struct coresight_device *csdev)
>  {
> +	int tag;
> +	struct csdev_access *csa;
> +
>  	if (WARN_ON(!csdev))
>  		return -EINVAL;
>  
> -	if (coresight_is_claimed_any(csdev))
> +	csa = &csdev->access;
> +	tag = coresight_read_claim_tags(csdev);
> +
> +	switch (tag) {
> +	case CORESIGHT_CLAIM_FREE:
> +		coresight_set_self_claim_tag(csdev);
> +		if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
> +			return 0;
> +
> +		/* There was a race setting the tag, clean up and fail */
> +		coresight_clear_self_claim_tag_unlocked(csa);
> +		dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
>  		return -EBUSY;
>  
> -	coresight_set_self_claim_tag(csdev);
> -	if (coresight_is_claimed_self_hosted(csdev))
> -		return 0;
> -	/* There was a race setting the tag, clean up and fail */
> -	coresight_clear_self_claim_tag_unlocked(&csdev->access);
> -	return -EBUSY;
> +	case CORESIGHT_CLAIM_EXTERNAL:
> +		/* External debug is an expected state, so log and report BUSY */
> +		dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
> +		return -EBUSY;
> +
> +	default:
> +	case CORESIGHT_CLAIM_SELF_HOSTED:
> +	case CORESIGHT_CLAIM_INVALID:
> +		/*
> +		 * Warn here because we clear a lingering self hosted tag
> +		 * on probe, so other tag combinations are impossible.
> +		 */
> +		dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
> +		return -EBUSY;
> +	}
>  }
>  EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
>  
> @@ -220,7 +233,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>  	if (WARN_ON(!csdev))
>  		return;
>  
> -	if (coresight_is_claimed_self_hosted(csdev))
> +	if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
>  		coresight_clear_self_claim_tag_unlocked(&csdev->access);
>  	else
>  		/*
> @@ -228,7 +241,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>  		 * and has manipulated it. Or something else has seriously
>  		 * gone wrong in our driver.
>  		 */
> -		WARN_ON_ONCE(1);
> +		dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
>  }
>  EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
>  
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 38bb4e8b50ef..6e8cf55aee0a 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -36,7 +36,10 @@ extern const struct device_type coresight_dev_type[];
>   * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
>   */
>  #define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
> -#define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
> +#define CORESIGHT_CLAIM_FREE		0
> +#define CORESIGHT_CLAIM_EXTERNAL	1
> +#define CORESIGHT_CLAIM_SELF_HOSTED	2
> +#define CORESIGHT_CLAIM_INVALID		3
>  
>  #define TIMEOUT_US		100
>  #define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)
> 
> -- 
> 2.34.1
> 


From leo.yan at arm.com  Wed Mar 19 01:30:53 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 19 Mar 2025 08:30:53 +0000
Subject: [PATCH v2 5/8] coresight: etm3x: Convert raw base pointer to
 struct coresight access
In-Reply-To: <20250318-james-coresight-claim-tags-v2-5-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-5-e9c8a9cde84e@linaro.org>
Message-ID: <20250319083053.GE2860028@e132581.arm.com>

On Tue, Mar 18, 2025 at 04:21:59PM +0000, James Clark wrote:
> This is so that etm3x can use the new claim tag functions which take a
> csa pointer in a later commit.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

LGTM:

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-etm.h        |  6 ++---
>  drivers/hwtracing/coresight/coresight-etm3x-core.c | 27 +++++++++++-----------
>  .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +++----
>  3 files changed, 20 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
> index 171f1384f7c0..1d753cca2943 100644
> --- a/drivers/hwtracing/coresight/coresight-etm.h
> +++ b/drivers/hwtracing/coresight/coresight-etm.h
> @@ -229,7 +229,7 @@ struct etm_config {
>   * @config:	structure holding configuration parameters.
>   */
>  struct etm_drvdata {
> -	void __iomem			*base;
> +	struct csdev_access		csa;
>  	struct clk			*atclk;
>  	struct coresight_device		*csdev;
>  	spinlock_t			spinlock;
> @@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
>  				"invalid CP14 access to ETM reg: %#x", off);
>  		}
>  	} else {
> -		writel_relaxed(val, drvdata->base + off);
> +		writel_relaxed(val, drvdata->csa.base + off);
>  	}
>  }
>  
> @@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
>  				"invalid CP14 access to ETM reg: %#x", off);
>  		}
>  	} else {
> -		val = readl_relaxed(drvdata->base + off);
> +		val = readl_relaxed(drvdata->csa.base + off);
>  	}
>  
>  	return val;
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> index 8927bfaf3af2..cfd463ac715c 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> @@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
>  {
>  	u32 etmpdcr;
>  
> -	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
> +	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
>  	etmpdcr |= ETMPDCR_PWD_UP;
> -	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
> +	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
>  	/* Ensure pwrup completes before subsequent cp14 accesses */
>  	mb();
>  	isb();
> @@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
>  	/* Ensure pending cp14 accesses complete before clearing pwrup */
>  	mb();
>  	isb();
> -	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
> +	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
>  	etmpdcr &= ~ETMPDCR_PWD_UP;
> -	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
> +	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
>  }
>  
>  /**
> @@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
>  	struct etm_config *config = &drvdata->config;
>  	struct coresight_device *csdev = drvdata->csdev;
>  
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  
>  	rc = coresight_claim_device_unlocked(csdev);
>  	if (rc)
> @@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
>  	etm_clr_prog(drvdata);
>  
>  done:
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  
>  	dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
>  		drvdata->cpu, rc);
> @@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
>  	struct etm_config *config = &drvdata->config;
>  	struct coresight_device *csdev = drvdata->csdev;
>  
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  	etm_set_prog(drvdata);
>  
>  	/* Read back sequencer and counters for post trace analysis */
> @@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
>  	etm_set_pwrdwn(drvdata);
>  	coresight_disclaim_device_unlocked(csdev);
>  
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  
>  	dev_dbg(&drvdata->csdev->dev,
>  		"cpu: %d disable smp call done\n", drvdata->cpu);
> @@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
>  	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
>  		return;
>  
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  
>  	/* Setting the prog bit disables tracing immediately */
>  	etm_set_prog(drvdata);
> @@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
>  	etm_set_pwrdwn(drvdata);
>  	coresight_disclaim_device_unlocked(csdev);
>  
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  
>  	/*
>  	 * perf will release trace ids when _free_aux()
> @@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
>  	/* Make sure all registers are accessible */
>  	etm_os_unlock(drvdata);
>  
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  
>  	/* First dummy read */
>  	(void)etm_readl(drvdata, ETMPDSR);
> @@ -766,7 +766,7 @@ static void etm_init_arch_data(void *info)
>  
>  	etm_set_pwrdwn(drvdata);
>  	etm_clr_pwrup(drvdata);
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  }
>  
>  static int __init etm_hp_setup(void)
> @@ -827,8 +827,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
>  	if (IS_ERR(base))
>  		return PTR_ERR(base);
>  
> -	drvdata->base = base;
> -	desc.access = CSDEV_ACCESS_IOMEM(base);
> +	desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
>  
>  	spin_lock_init(&drvdata->spinlock);
>  
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> index b9006451f515..762109307b86 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> @@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
>  
>  	pm_runtime_get_sync(dev->parent);
>  	spin_lock_irqsave(&drvdata->spinlock, flags);
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  
>  	val = etm_readl(drvdata, ETMSR);
>  
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  	spin_unlock_irqrestore(&drvdata->spinlock, flags);
>  	pm_runtime_put(dev->parent);
>  
> @@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
>  	pm_runtime_get_sync(dev->parent);
>  	spin_lock_irqsave(&drvdata->spinlock, flags);
>  
> -	CS_UNLOCK(drvdata->base);
> +	CS_UNLOCK(drvdata->csa.base);
>  	val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
> -	CS_LOCK(drvdata->base);
> +	CS_LOCK(drvdata->csa.base);
>  
>  	spin_unlock_irqrestore(&drvdata->spinlock, flags);
>  	pm_runtime_put(dev->parent);
> 
> -- 
> 2.34.1
> 


From krzk at kernel.org  Wed Mar 19 01:31:35 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:31:35 +0100
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
Message-ID: <20250319-optimistic-positive-peacock-cc26b1@krzk-bin>

On Tue, Mar 18, 2025 at 10:54:42AM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
>  1 file changed, 113 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..e61ef97e63af
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,113 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +

No blank line here. Use existing code as template. If you find such
code, share so we can fix it.

> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>
> +
> +description:
> +  Microchip EMC2301/2/3/5 pwm controller which supports
> +  up to five programmable fan control circuits.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - microchip,emc2305
> +      - items:
> +          - enum:
> +              - microchip,emc2303
> +              - microchip,emc2302
> +              - microchip,emc2301
> +          - const: microchip,emc2305
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  '#pwm-cells':
> +    const: 3
> +    description: |
> +      Number of cells in a PWM specifier.
> +      - cell 0: The PWM frequency
> +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
> +      - cell 2: The PWM output config:
> +           - 0 (Open-Drain)
> +           - 1 (Push-Pull)
> +
> +

Just one blank line

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From krzk at kernel.org  Wed Mar 19 01:33:59 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:33:59 +0100
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <ca734f66-593f-4e7c-bc76-e343a7eb88d7@roeck-us.net>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
 <7afcd224-1154-4e2f-b383-10f6a89fdae0@roeck-us.net>
 <CAEnQRZBmYdLh29ha1FKz8=CbxjFBFFTgDkjrEmwTxW2WcxodfA@mail.gmail.com>
 <ca734f66-593f-4e7c-bc76-e343a7eb88d7@roeck-us.net>
Message-ID: <20250319-auspicious-sparkling-dachshund-ef0eed@krzk-bin>

On Tue, Mar 18, 2025 at 09:37:29AM -0700, Guenter Roeck wrote:
> > > > +patternProperties:
> > > > +  '^fan@[0-4]$':
> > > > +    $ref: fan-common.yaml#
> > > > +    unevaluatedProperties: false
> > > > +    properties:
> > > > +      reg:
> > > > +        description:
> > > > +          The fan number used to determine the associated PWM channel.
> > > > +
> > > > +    required:
> > > > +      - reg
> > > > +      - pwms
> > > 
> > > Is it necessary to make 'pwms' mandatory ? The current code works
> > > just fine with defaults.
> > 
> > The code adding OF support is added just in the next patch, so the
> > current code isn't event
> > probed when trying to use dts.
> > 
> > Or am I missing something?
> > 
> 
> The patch introducing devicetree support to the driver doesn't evaluate
> the pwm property. That makes it quite obvious that, from driver perspective,
> it isn't needed. I don't immediately see why it would add value to _force_
> users to provide pwm frequency, polarity, and the output configuration
> if the defaults work just fine.

Indeed. PWM source is actually fixed and rest of pwm argument could be fine
with defaults.

Both options are fine with me, so keep my tag.

Best regards,
Krzysztof



From leo.yan at arm.com  Wed Mar 19 01:36:38 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 19 Mar 2025 08:36:38 +0000
Subject: [PATCH v2 7/8] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250318-james-coresight-claim-tags-v2-7-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-7-e9c8a9cde84e@linaro.org>
Message-ID: <20250319083638.GF2860028@e132581.arm.com>

On Tue, Mar 18, 2025 at 04:22:01PM +0000, James Clark wrote:
> These are all static and in one compilation unit so the inline has no
> effect on the binary. Except if FTRACE is enabled, then some functions
> which were already not inlined now get the nops added which allows them
> to be traced.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

LGTM:

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-catu.c       | 11 +++++----
>  drivers/hwtracing/coresight/coresight-core.c       | 14 ++++++------
>  drivers/hwtracing/coresight/coresight-etb10.c      |  2 +-
>  drivers/hwtracing/coresight/coresight-etm4x-core.c |  8 +++----
>  .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 ++--
>  drivers/hwtracing/coresight/coresight-platform.c   | 26 +++++++++++-----------
>  drivers/hwtracing/coresight/coresight-replicator.c |  2 +-
>  drivers/hwtracing/coresight/coresight-stm.c        |  6 ++---
>  .../coresight/coresight-syscfg-configfs.c          |  2 +-
>  drivers/hwtracing/coresight/coresight-tmc-core.c   |  8 +++----
>  drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++++++-------
>  drivers/hwtracing/coresight/coresight-trbe.c       | 18 +++++++--------
>  12 files changed, 57 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index deaacfd875af..6f411db24a54 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -113,9 +113,8 @@ typedef u64 cate_t;
>   * containing the data page pointer for @offset. If @daddrp is not NULL,
>   * @daddrp points the DMA address of the beginning of the table.
>   */
> -static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
> -				     unsigned long offset,
> -				     dma_addr_t *daddrp)
> +static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
> +			      dma_addr_t *daddrp)
>  {
>  	unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
>  	unsigned int table_nr, pg_idx, pg_offset;
> @@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
>  }
>  
>  #else
> -static inline void catu_dump_table(struct tmc_sg_table *catu_table)
> +static void catu_dump_table(struct tmc_sg_table *catu_table)
>  {
>  }
>  #endif
>  
> -static inline cate_t catu_make_entry(dma_addr_t addr)
> +static cate_t catu_make_entry(dma_addr_t addr)
>  {
>  	return addr ? CATU_VALID_ENTRY(addr) : 0;
>  }
> @@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
>  };
>  
>  
> -static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
> +static int catu_wait_for_ready(struct catu_drvdata *drvdata)
>  {
>  	struct csdev_access *csa = &drvdata->csdev->access;
>  
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 5f08845faf0d..69388e2dd386 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -129,13 +129,13 @@ coresight_find_out_connection(struct coresight_device *csdev,
>  	return ERR_PTR(-ENODEV);
>  }
>  
> -static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
> +static u32 coresight_read_claim_tags(struct coresight_device *csdev)
>  {
>  	return FIELD_GET(CORESIGHT_CLAIM_MASK,
>  			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
>  }
>  
> -static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
> +static void coresight_set_self_claim_tag(struct coresight_device *csdev)
>  {
>  	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>  				     CORESIGHT_CLAIMSET);
> @@ -602,7 +602,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
>   * Return true in successful case and power up the device.
>   * Return false when failed to get reference of module.
>   */
> -static inline bool coresight_get_ref(struct coresight_device *csdev)
> +static bool coresight_get_ref(struct coresight_device *csdev)
>  {
>  	struct device *dev = csdev->dev.parent;
>  
> @@ -621,7 +621,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
>   *
>   * @csdev: The coresight device to decrement a reference from.
>   */
> -static inline void coresight_put_ref(struct coresight_device *csdev)
> +static void coresight_put_ref(struct coresight_device *csdev)
>  {
>  	struct device *dev = csdev->dev.parent;
>  
> @@ -844,7 +844,7 @@ void coresight_release_path(struct coresight_path *path)
>  }
>  
>  /* return true if the device is a suitable type for a default sink */
> -static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
> +static bool coresight_is_def_sink_type(struct coresight_device *csdev)
>  {
>  	/* sink & correct subtype */
>  	if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
> @@ -1408,8 +1408,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
>   *
>   * Returns the index of the entry, when found. Otherwise, -ENOENT.
>   */
> -static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
> -					      struct fwnode_handle *fwnode)
> +static int coresight_search_device_idx(struct coresight_dev_list *dict,
> +				       struct fwnode_handle *fwnode)
>  {
>  	int i;
>  
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index 2bfcb669aa84..d5efb085b30d 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -95,7 +95,7 @@ struct etb_drvdata {
>  static int etb_set_buffer(struct coresight_device *csdev,
>  			  struct perf_output_handle *handle);
>  
> -static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
> +static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
>  {
>  	return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 52c9aa56e8b9..2ca35ef35f77 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
>   *		TRCIDR4.NUMPC > 0b0000 .
>   *		TRCSSCSR<n>.PC == 0b1
>   */
> -static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> +static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
>  {
>  	return (n < drvdata->nr_ss_cmp) &&
>  	       drvdata->nr_pe &&
> @@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
>  	isb();
>  }
>  
> -static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
> +static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
>  				      struct csdev_access *csa)
>  {
>  	WARN_ON(drvdata->cpu != smp_processor_id());
> @@ -1070,7 +1070,7 @@ static const struct coresight_ops etm4_cs_ops = {
>  	.source_ops	= &etm4_source_ops,
>  };
>  
> -static inline bool cpu_supports_sysreg_trace(void)
> +static bool cpu_supports_sysreg_trace(void)
>  {
>  	u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
>  
> @@ -1378,7 +1378,7 @@ static void etm4_init_arch_data(void *info)
>  	cpu_detect_trace_filtering(drvdata);
>  }
>  
> -static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
> +static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
>  {
>  	return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index fdd0956fecb3..49d5fb87a74b 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
>  	return reg.data;
>  }
>  
> -static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
> +static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
>  {
>  	struct dev_ext_attribute *eattr;
>  
> @@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
>  	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
>  }
>  
> -static inline bool
> +static bool
>  etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
>  {
>  	switch (offset) {
> diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> index 8192ba3279f0..0db64c5f4995 100644
> --- a/drivers/hwtracing/coresight/coresight-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-platform.c
> @@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
>  EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
>  
>  #ifdef CONFIG_OF
> -static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
> +static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
>  {
>  	return of_property_read_bool(ep, "slave-mode");
>  }
> @@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
>  	return parent;
>  }
>  
> -static inline struct device_node *
> +static struct device_node *
>  of_coresight_get_output_ports_node(const struct device_node *node)
>  {
>  	return of_get_child_by_name(node, "out-ports");
> @@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
>  	return 0;
>  }
>  #else
> -static inline int
> +static int
>  of_get_coresight_platform_data(struct device *dev,
>  			       struct coresight_platform_data *pdata)
>  {
>  	return -ENOENT;
>  }
>  
> -static inline int of_coresight_get_cpu(struct device *dev)
> +static int of_coresight_get_cpu(struct device *dev)
>  {
>  	return -ENODEV;
>  }
> @@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
>  #define ACPI_CORESIGHT_LINK_SLAVE	0
>  #define ACPI_CORESIGHT_LINK_MASTER	1
>  
> -static inline bool is_acpi_guid(const union acpi_object *obj)
> +static bool is_acpi_guid(const union acpi_object *obj)
>  {
>  	return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
>  }
> @@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
>   * acpi_guid_matches	- Checks if the given object is a GUID object and
>   * that it matches the supplied the GUID.
>   */
> -static inline bool acpi_guid_matches(const union acpi_object *obj,
> +static bool acpi_guid_matches(const union acpi_object *obj,
>  				   const guid_t *guid)
>  {
>  	return is_acpi_guid(obj) &&
>  	       guid_equal((guid_t *)obj->buffer.pointer, guid);
>  }
>  
> -static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
> +static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
>  {
>  	return acpi_guid_matches(obj, &acpi_graph_uuid);
>  }
>  
> -static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
> +static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
>  {
>  	return acpi_guid_matches(obj, &coresight_graph_uuid);
>  }
>  
> -static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
> +static bool is_acpi_coresight_graph(const union acpi_object *obj)
>  {
>  	const union acpi_object *graphid, *guid, *links;
>  
> @@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
>   *	}, // End of ACPI Graph Property
>   *  })
>   */
> -static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
> +static bool acpi_validate_dsd_graph(const union acpi_object *graph)
>  {
>  	int i, n;
>  	const union acpi_object *rev, *nr_graphs;
> @@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
>  	return NULL;
>  }
>  
> -static inline bool
> +static bool
>  acpi_validate_coresight_graph(const union acpi_object *cs_graph)
>  {
>  	int nlinks;
> @@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
>  
>  #else
>  
> -static inline int
> +static int
>  acpi_get_coresight_platform_data(struct device *dev,
>  				 struct coresight_platform_data *pdata)
>  {
>  	return -ENOENT;
>  }
>  
> -static inline int acpi_coresight_get_cpu(struct device *dev)
> +static int acpi_coresight_get_cpu(struct device *dev)
>  {
>  	return -ENODEV;
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
> index b2acd4535c74..52beb2fc4094 100644
> --- a/drivers/hwtracing/coresight/coresight-replicator.c
> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
> @@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
>  /*
>   * replicator_reset : Reset the replicator configuration to sane values.
>   */
> -static inline void replicator_reset(struct replicator_drvdata *drvdata)
> +static void replicator_reset(struct replicator_drvdata *drvdata)
>  {
>  	if (drvdata->base)
>  		dynamic_replicator_reset(drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> index 26f9339f38b9..8c0741583a2c 100644
> --- a/drivers/hwtracing/coresight/coresight-stm.c
> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> @@ -301,7 +301,7 @@ static const struct coresight_ops stm_cs_ops = {
>  	.source_ops	= &stm_source_ops,
>  };
>  
> -static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
> +static bool stm_addr_unaligned(const void *addr, u8 write_bytes)
>  {
>  	return ((unsigned long)addr & (write_bytes - 1));
>  }
> @@ -685,7 +685,7 @@ static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)
>  	return of_address_to_resource(np, index, res);
>  }
>  #else
> -static inline int of_stm_get_stimulus_area(struct device *dev,
> +static int of_stm_get_stimulus_area(struct device *dev,
>  					   struct resource *res)
>  {
>  	return -ENOENT;
> @@ -729,7 +729,7 @@ static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)
>  	return rc;
>  }
>  #else
> -static inline int acpi_stm_get_stimulus_area(struct device *dev,
> +static int acpi_stm_get_stimulus_area(struct device *dev,
>  					     struct resource *res)
>  {
>  	return -ENOENT;
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> index 213b4159b062..2b40e556be87 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> @@ -10,7 +10,7 @@
>  #include "coresight-syscfg-configfs.h"
>  
>  /* create a default ci_type. */
> -static inline struct config_item_type *cscfg_create_ci_type(void)
> +static struct config_item_type *cscfg_create_ci_type(void)
>  {
>  	struct config_item_type *ci_type;
>  
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index a09579eff3fd..6f6d51c13454 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -287,8 +287,8 @@ static int tmc_open(struct inode *inode, struct file *file)
>  	return 0;
>  }
>  
> -static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
> -					  loff_t pos, size_t len, char **bufpp)
> +static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len,
> +				   char **bufpp)
>  {
>  	switch (drvdata->config_type) {
>  	case TMC_CONFIG_TYPE_ETB:
> @@ -591,7 +591,7 @@ static const struct attribute_group *coresight_etr_groups[] = {
>  	NULL,
>  };
>  
> -static inline bool tmc_etr_can_use_sg(struct device *dev)
> +static bool tmc_etr_can_use_sg(struct device *dev)
>  {
>  	int ret;
>  	u8 val_u8;
> @@ -621,7 +621,7 @@ static inline bool tmc_etr_can_use_sg(struct device *dev)
>  	return false;
>  }
>  
> -static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
> +static bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
>  {
>  	u32 auth = readl_relaxed(drvdata->base + TMC_AUTHSTATUS);
>  
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 76a8cb29b68a..3f31ad2ae65d 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -125,7 +125,7 @@ struct etr_sg_table {
>   * If we spill over to a new page for mapping 1 entry, we could as
>   * well replace the link entry of the previous page with the last entry.
>   */
> -static inline unsigned long __attribute_const__
> +static unsigned long __attribute_const__
>  tmc_etr_sg_table_entries(int nr_pages)
>  {
>  	unsigned long nr_sgpages = nr_pages * ETR_SG_PAGES_PER_SYSPAGE;
> @@ -239,13 +239,13 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
>  	return -ENOMEM;
>  }
>  
> -static inline long
> +static long
>  tmc_sg_get_data_page_offset(struct tmc_sg_table *sg_table, dma_addr_t addr)
>  {
>  	return tmc_pages_get_offset(&sg_table->data_pages, addr);
>  }
>  
> -static inline void tmc_free_table_pages(struct tmc_sg_table *sg_table)
> +static void tmc_free_table_pages(struct tmc_sg_table *sg_table)
>  {
>  	if (sg_table->table_vaddr)
>  		vunmap(sg_table->table_vaddr);
> @@ -481,7 +481,7 @@ static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table)
>  	dev_dbg(sg_table->dev, "******* End of Table *****\n");
>  }
>  #else
> -static inline void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
> +static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
>  #endif
>  
>  /*
> @@ -886,10 +886,8 @@ void tmc_etr_remove_catu_ops(void)
>  }
>  EXPORT_SYMBOL_GPL(tmc_etr_remove_catu_ops);
>  
> -static inline int tmc_etr_mode_alloc_buf(int mode,
> -					 struct tmc_drvdata *drvdata,
> -					 struct etr_buf *etr_buf, int node,
> -					 void **pages)
> +static int tmc_etr_mode_alloc_buf(int mode, struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
> +				  int node, void **pages)
>  {
>  	int rc = -EINVAL;
>  
> @@ -1009,7 +1007,7 @@ static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
>  	return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
>  }
>  
> -static inline s64
> +static s64
>  tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
>  {
>  	ssize_t len;
> diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
> index fff67aac8418..8267dd1a2130 100644
> --- a/drivers/hwtracing/coresight/coresight-trbe.c
> +++ b/drivers/hwtracing/coresight/coresight-trbe.c
> @@ -160,22 +160,22 @@ static void trbe_check_errata(struct trbe_cpudata *cpudata)
>  	}
>  }
>  
> -static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
> +static bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
>  {
>  	return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata);
>  }
>  
> -static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
> +static bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
>  {
>  	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE);
>  }
>  
> -static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
> +static bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
>  {
>  	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE);
>  }
>  
> -static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
> +static bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
>  {
>  	/*
>  	 * Errata affected TRBE implementation will need TSB CSYNC and
> @@ -185,7 +185,7 @@ static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
>  	return trbe_has_erratum(cpudata, TRBE_NEEDS_DRAIN_AFTER_DISABLE);
>  }
>  
> -static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
> +static bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
>  {
>  	/*
>  	 * Errata affected TRBE implementation will need an additional
> @@ -196,7 +196,7 @@ static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudat
>  	return trbe_has_erratum(cpudata, TRBE_NEEDS_CTXT_SYNC_AFTER_ENABLE);
>  }
>  
> -static inline bool trbe_is_broken(struct trbe_cpudata *cpudata)
> +static bool trbe_is_broken(struct trbe_cpudata *cpudata)
>  {
>  	return trbe_has_erratum(cpudata, TRBE_IS_BROKEN);
>  }
> @@ -208,13 +208,13 @@ static int trbe_alloc_node(struct perf_event *event)
>  	return cpu_to_node(event->cpu);
>  }
>  
> -static inline void trbe_drain_buffer(void)
> +static void trbe_drain_buffer(void)
>  {
>  	tsb_csync();
>  	dsb(nsh);
>  }
>  
> -static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
> +static void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
>  {
>  	/*
>  	 * Enable the TRBE without clearing LIMITPTR which
> @@ -231,7 +231,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
>  		isb();
>  }
>  
> -static inline void set_trbe_disabled(struct trbe_cpudata *cpudata)
> +static void set_trbe_disabled(struct trbe_cpudata *cpudata)
>  {
>  	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
>  
> 
> -- 
> 2.34.1
> 


From akihiko.odaki at daynix.com  Wed Mar 19 01:37:29 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 17:37:29 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <Z9pze3J2_zrTk_yC@linux.dev>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
Message-ID: <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>

On 2025/03/19 16:34, Oliver Upton wrote:
> Hi Akihiko,
> 
> On Wed, Mar 19, 2025 at 03:33:46PM +0900, Akihiko Odaki wrote:
>> Problem
>> -------
>>
>> arch/arm64/kvm/pmu-emul.c used to have a comment saying the follows:
>>> The observant among you will notice that the supported_cpus
>>> mask does not get updated for the default PMU even though it
>>> is quite possible the selected instance supports only a
>>> subset of cores in the system. This is intentional, and
>>> upholds the preexisting behavior on heterogeneous systems
>>> where vCPUs can be scheduled on any core but the guest
>>> counters could stop working.
>>
>> Despite the reference manual says counters may not continuously
>> incrementing, Windows is not robust enough to handle stopped PMCCNTR_EL0
>> and crashes with a division-by-zero error and it also crashes when the
>> PMU is not present.
>>
>> To avoid such a problem, the userspace should pin the vCPU threads to
>> pCPUs supported by one host PMU when initializing the vCPUs or specify
>> the host PMU to use with KVM_ARM_VCPU_PMU_V3_SET_PMU after the
>> initialization. However, QEMU/libvirt can pin vCPU threads only after the
>> vCPUs are initialized. It also limits the pCPUs the guest can use even
>> for VMMs that support proper pinning.
>>
>> Solution
>> --------
>>
>> Ideally, Windows should fix the division-by-zero error and QEMU/libvirt
>> should support pinning better, but neither of them are going to happen
>> anytime soon.
>>
>> To allow running Windows on QEMU/libvirt or with heterogeneous cores,
>> combine all host PMUs necessary to cover the cores vCPUs can run and
>> keep PMCCNTR_EL0 working.
 > > I'm extremely uneasy about making this a generalized solution. PMUs are
> deeply tied to the microarchitecture of a particular implementation, and
> that isn't something we can abstract away from the guest in KVM.
> 
> For example, you could have an event ID that counts on only a subset of
> cores, or better yet an event that counts something completely different
> depending on where a vCPU lands.> > I do appreciate the issue that you're trying to solve.
> 
> The good news though is that the fixed PMU cycle counter is the only
> thing guaranteed to be present in any PMUv3 implementation. Since
> that's the only counter Windows actually needs, perhaps we could
> special-case this in KVM.
> 
> I have the following (completely untested) patch, do you want to give it
> a try? There's still going to be observable differences between PMUs
> (e.g. CPU frequency) but at least it should get things booting.

I don't think it will work, unfortunately. perf_init_event() binds a 
perf event to a particular PMU so the event will stop working when the 
thread migrates away.

It should also be the reason why the perf program creates an event for 
each PMU. tools/perf/Documentation/intel-hybrid.txt has more descriptions.

Allowing to enable more than one counter and/or an event type other than 
the cycle counter is not the goal. Enabling another event type may 
result in a garbage value, but I don't think it's worse than the current 
situation where the count stays zero; please tell me if I miss something.

There is still room for improvement. Returning a garbage value may not 
be worse than returning zero, but counters and event types not supported 
by some cores shouldn't be advertised as available in the first place. 
More concretely:

- The vCPU should be limited to run only on cores covered by PMUs when 
KVM_ARM_VCPU_PMU_V3 is set.
- PMCR_EL0.N advertised to the guest should be the minimum of ones of 
host PMUs.
- PMCEID0_EL0 and PMCEID1_EL0 advertised to the guest should be the 
result of the AND operations of ones of host PMUs.

Special-casing the cycle counter may make sense if we are going to fix 
the advertised values of PMCR_EL0.N, PMCEID0_EL0, and PMCEID1_EL0. 
PMCR_EL0.N as we can simply return zero for these registers. We can also 
prevent enabling a counter that returns zero or a garbage value.

Do you think it's worth fixing these registers? If so, I'll do that by 
special-casing the cycle counter.

Regards,
Akihiko Odaki

> 
> Thanks,
> Oliver
> 
> ---
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index a1bc10d7116a..913a7bab50b5 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -724,14 +724,21 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
>   		return;
>   
>   	memset(&attr, 0, sizeof(struct perf_event_attr));
> -	attr.type = arm_pmu->pmu.type;
> +
> +	if (pmc->idx == ARMV8_PMU_CYCLE_IDX) {
> +		attr.type = PERF_TYPE_HARDWARE;
> +		attr.config = PERF_COUNT_HW_CPU_CYCLES;
> +	} else {
> +		attr.type = arm_pmu->pmu.type;
> +		attr.config = eventsel;
> +	}
> +
>   	attr.size = sizeof(attr);
>   	attr.pinned = 1;
>   	attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
>   	attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
>   	attr.exclude_hv = 1; /* Don't count EL2 events */
>   	attr.exclude_host = 1; /* Don't count host events */
> -	attr.config = eventsel;
>   
>   	/*
>   	 * Filter events at EL1 (i.e. vEL2) when in a hyp context based on the



From robh at kernel.org  Wed Mar 19 01:38:28 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 19 Mar 2025 03:38:28 -0500
Subject: [PATCH v4 1/6] dt-bindings: clock: meson: Add audio power
 domain for s4 soc
In-Reply-To: <20250319-audio_drvier-v4-1-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-1-686867fad719@amlogic.com>
Message-ID: <174237350819.971004.1098115771430334211.robh@kernel.org>


On Wed, 19 Mar 2025 15:04:44 +0800, jiebing chen wrote:
> Audio power domain found on S4 device.it need to enable before audio work.
> 
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  .../bindings/clock/amlogic,axg-audio-clkc.yaml       | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml:105:7: [warning] wrong indentation: expected 4 but found 6 (indentation)

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.example.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250319-audio_drvier-v4-1-686867fad719 at amlogic.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From jiebing.chen at amlogic.com  Wed Mar 19 01:46:53 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Wed, 19 Mar 2025 16:46:53 +0800
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
 <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
Message-ID: <6c1ca29e-37e4-488c-b3a3-f61aad7f8dcf@amlogic.com>


? 2025/3/19 16:26, Krzysztof Kozlowski ??:
> [You don't often get email fromkrzk at kernel.org. Learn why this is important athttps://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On Wed, Mar 19, 2025 at 03:04:49PM +0800, jiebing chen wrote:
>> Add basic audio driver support for the Amlogic S4 based
>> Amlogic AQ222 board. use hifipll pll (1179648000) to
>> support 768k sample rate and 24 bit (s24_le), 24bit sclk
>> is 48fs, use mpll0 (270950400) to support 705.6k sample
>> rate and 32bit, use mpll1 (338688000) to support 705.6k
>> and 24bit.
> Please wrap commit message according to Linux coding style / submission
> process (neither too early nor over the limit):
> https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
>
>> Signed-off-by: jiebing chen<jiebing.chen at amlogic.com>
> ...
>
>> +
>> +             dai-link-12 {
>> +                     sound-dai = <&toacodec TOACODEC_OUT>;
>> +
>> +                     codec {
>> +                             sound-dai = <&acodec>;
>> +                     };
>> +             };
>> +     };
>> +
> Do not add stray blank lines.
>
>>   };
>>
>>   &pwm_ef {
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> @@ -11,7 +11,11 @@
>>   #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
>>   #include <dt-bindings/power/meson-s4-power.h>
>>   #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
>> -
> Why?
>
>> +#include <dt-bindings/clock/axg-audio-clkc.h>
>> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
>> +#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
>> +#include <dt-bindings/sound/meson-g12a-toacodec.h>
>> +#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
> Old style was correct.
>
>>   / {
>>        cpus {
>>                #address-cells = <2>;
>> @@ -46,6 +50,36 @@ cpu3: cpu at 3 {
>>                };
>>        };
>>
>> +     tdmif_a: audio-controller-0 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_A";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_A_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>> +     tdmif_b: audio-controller-1 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_B";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_B_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>> +     tdmif_c: audio-controller-2 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_C";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_C_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>>        timer {
>>                compatible = "arm,armv8-timer";
>>                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
>> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>>                        #address-cells = <2>;
>>                        #size-cells = <2>;
>>                        ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>> -
> Why? What is happening in this patch - why are you changing so many
> other pieces?

Hi, Krzysztof

for last versions ,it it not match the amlogic,axg-tdm-iface.yaml

so we must be change the order, otherwise a warning will be thrown?we 
copy the dts config from merged dts

the old order not meet the dt-binding rule, Another change, we only add 
the audio clock reg

+ compatible = "amlogic,s4-audio-clkc"; + reg = <0x0 0x0 0x0 0xd8>,

add <0x0 0xE80 0x0 0x10>;

We have not made any changes to the rest


arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dtb: audio-controller-0: clock-names:0: 'sclk' was expected
         from schema $id:http://devicetree.org/schemas/sound/amlogic,axg-tdm-iface.yaml#
arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dtb: audio-controller-0: clock-names:1: 'lrclk' was expected
         from schema $id:http://devicetree.org/schemas/sound/amlogic,axg-tdm-iface.yaml#
arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dtb: audio-controller-0: clock-names:2: 'mclk' was expected


>>                        clkc_periphs: clock-controller at 0 {
>>                                compatible = "amlogic,s4-peripherals-clkc";
>>                                reg = <0x0 0x0 0x0 0x49c>;
>> @@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
>>                                #clock-cells = <1>;
>>                        };
>>
>> +                     acodec: audio-controller at 1a000 {
>> +                             compatible = "amlogic,t9015";
>> +                             reg = <0x0 0x1A000 0x0 0x14>;
>> +                             #sound-dai-cells = <0>;
>> +                             sound-name-prefix = "ACODEC";
>> +                             clocks = <&clkc_periphs CLKID_ACODEC>;
>> +                             clock-names = "pclk";
>> +                             resets = <&reset RESET_ACODEC>;
>> +                             AVDD-supply = <&vddio_ao1v8>;
>> +                     };
>> +
>>                        watchdog at 2100 {
>>                                compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
>>                                reg = <0x0 0x2100 0x0 0x10>;
>> @@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
>>                };
>>        };
>>   };
>> +
>> +&apb4 {
>> +     audio: bus at 330000 {
>> +             compatible = "simple-bus";
>> +             reg = <0x0 0x330000 0x0 0x1000>;
> That's not a simple bus in such case.
>
> NAK
>
>
> Best regards,
> Krzysztof
>


From krzk at kernel.org  Wed Mar 19 01:49:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 09:49:06 +0100
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <6c1ca29e-37e4-488c-b3a3-f61aad7f8dcf@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
 <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
 <6c1ca29e-37e4-488c-b3a3-f61aad7f8dcf@amlogic.com>
Message-ID: <7bb26735-bd68-426a-ab0e-ec8379b39bdf@kernel.org>

On 19/03/2025 09:46, Jiebing Chen wrote:
>>> +     tdmif_b: audio-controller-1 {
>>> +             compatible = "amlogic,axg-tdm-iface";
>>> +             #sound-dai-cells = <0>;
>>> +             sound-name-prefix = "TDM_B";
>>> +             clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
>>> +                      <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
>>> +                      <&clkc_audio AUD_CLKID_MST_B_MCLK>;
>>> +             clock-names = "sclk", "lrclk","mclk";
>>> +     };
>>> +
>>> +     tdmif_c: audio-controller-2 {
>>> +             compatible = "amlogic,axg-tdm-iface";
>>> +             #sound-dai-cells = <0>;
>>> +             sound-name-prefix = "TDM_C";
>>> +             clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
>>> +                      <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
>>> +                      <&clkc_audio AUD_CLKID_MST_C_MCLK>;
>>> +             clock-names = "sclk", "lrclk","mclk";
>>> +     };
>>> +
>>>        timer {
>>>                compatible = "arm,armv8-timer";
>>>                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
>>> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>>>                        #address-cells = <2>;
>>>                        #size-cells = <2>;
>>>                        ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>>> -
>> Why? What is happening in this patch - why are you changing so many
>> other pieces?
> 
> Hi, Krzysztof
> 
> for last versions ,it it not match the amlogic,axg-tdm-iface.yaml

It is not what is happening here. Read replies and patches again.

> 
> so we must be change the order, otherwise a warning will be thrown?we 
> copy the dts config from merged dts
> 
> the old order not meet the dt-binding rule, Another change, we only add 
> the audio clock reg
> 
> + compatible = "amlogic,s4-audio-clkc"; + reg = <0x0 0x0 0x0 0xd8>,
> 
> add <0x0 0xE80 0x0 0x10>;
> 
> We have not made any changes to the rest

How is this even remotely related to my comment?

It's still a NAK for reasons stated later which you decided to ignore.


Best regards,
Krzysztof


From quic_nguyenb at quicinc.com  Wed Mar 19 02:01:07 2025
From: quic_nguyenb at quicinc.com (Bao D. Nguyen)
Date: Wed, 19 Mar 2025 02:01:07 -0700
Subject: [PATCH v3 1/1] scsi: ufs: core: add device level exception
 support
In-Reply-To: <61570104d58cef22716fefe459c0c45670108aad.camel@mediatek.com>
References: <6109425449ac4d18249ce7254e4fa1252138a94a.1742369183.git.quic_nguyenb@quicinc.com>
 <61570104d58cef22716fefe459c0c45670108aad.camel@mediatek.com>
Message-ID: <9cf88cda-cf9c-9dbd-d586-5463ce2a0cfc@quicinc.com>

On 3/19/2025 12:56 AM, Peter Wang (???) wrote:
> Hi Bao,
> 
> Could use atomic_t for counter protect?
Hi Peter,
Are you suggesting to convert the dev_lvl_exception_count type from u32 
to atomic_t type? Because the value of dev_lvl_exception_count is 
returned to the user space via the device_lvl_exception_count_show() 
using the sysfs_emit() function, keeping the dev_lvl_exception_count as 
u32 data type probably works better in terms of the format.

Thanks, Bao


From n-francis at ti.com  Wed Mar 19 02:02:10 2025
From: n-francis at ti.com (Neha Malcom Francis)
Date: Wed, 19 Mar 2025 14:32:10 +0530
Subject: [PATCH 1/2] dt-bindings: misc: bist: Add BIST dt-binding for TI
 K3 devices
In-Reply-To: <1da4e402-62f3-4bad-9129-1f5a08148987@kernel.org>
References: <20241128140825.263216-1-n-francis@ti.com>
 <20241128140825.263216-2-n-francis@ti.com>
 <ho7ktcnbtl7mvamfthqho23co2fc4z7bgjha7pu4wivxm6ndhu@tfbpveonhckz>
 <837d329b-bcdd-4c3b-b508-e916b110ce25@ti.com>
 <e57dfc3e-b702-4803-b776-20c6dbd98fef@kernel.org>
 <8e58b093-1c64-45b9-a9d3-9835a3bbc4fd@ti.com>
 <1da4e402-62f3-4bad-9129-1f5a08148987@kernel.org>
Message-ID: <f39d80fc-3600-4c2c-b09c-980288f86fa2@ti.com>

Hi Krzysztof,

On 19/03/25 13:16, Krzysztof Kozlowski wrote:
> On 13/03/2025 12:14, Neha Malcom Francis wrote:
>> Hi Krzysztof
>>
>> On 29/11/24 14:45, Krzysztof Kozlowski wrote:
>>> On 29/11/2024 08:43, Neha Malcom Francis wrote:
>>>>>> +
>>>>>> +  power-domains:
>>>>>> +    maxItems: 1
>>>>>> +
>>>>>> +  ti,bist-instance:
>>>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>>>> +    description:
>>>>>> +      the BIST instance in the SoC represented as an integer
>>>>>
>>>>> No instance indices are allowed. Drop.
>>>>>
>>>>
>>>> Question on this, this is not a property that is driven by software but rather 
>>>> indicates which register sequences have to be picked up for triggering this test 
>>>> from this instance. So I don't see how I can workaround this without getting 
>>>> this number. Or maybe call it ID rather than instance?
>>>
>>> I don't understand how the device operates, so what is exactly behind
>>> some sequences of registers for triggering this test. You described
>>> property as index or ID of one instance of the block. That's not what we
>>> want in the binding. That's said maybe other, different hardware
>>> characteristic is behind, who knows. Or maybe it's about callers... or
>>> maybe that's not hardware property at all, but runtime OS, who knows.
>>>
>>
>> Sorry for such a late reply, but I was hoping to get more details on
>> this "ID" and never got back to the thread...
>>
>> The best way I can describe is this device (BIST) runs a safety
>> diagnostic test on a bunch of processors/blocks (let's call them
>> targets). There's a mapping between the instance of this device and the
>> targets it will run the test. This ID was essentially letting the BIST
>> driver know which are these targets.
> 
> 
> So you want to configure some target? Then this is your property. If you
> want to configure 'foo' difference in DT, you do not write 'bar'...
> 

So the difficulty in doing this is, what I mentioned in the earlier
email just copying it over again:

"Yet another way would be the BIST points out the targets it controls via
their phandles in its node... but this approach would trigger the probe
of these targets before the test runs on them. And in hardware, the test
must run only one before the device is used, else we see indefinite
behavior."

Property that has a list of strings (targets) instead of phandles maybe?
Would that be acceptable?

> Anyway, no clue, original emails are long time not in my inbox. Context
> disappeared also long time ago.
> 

Completely understand, delay from my end, sorry!

> 
> Best regards,
> Krzysztof

-- 
Thanking You
Neha Malcom Francis


From tmricht at linux.ibm.com  Wed Mar 19 02:05:05 2025
From: tmricht at linux.ibm.com (Thomas Richter)
Date: Wed, 19 Mar 2025 10:05:05 +0100
Subject: [PATCH v1] perf cpumap: Increment reference count for online
 cpumap
In-Reply-To: <20250318171914.145616-1-irogers@google.com>
References: <20250318171914.145616-1-irogers@google.com>
Message-ID: <a27a9066-b0e3-4d8f-bbb3-2dfd080800ef@linux.ibm.com>

On 3/18/25 18:19, Ian Rogers wrote:
> Thomas Richter <tmricht at linux.ibm.com> reported a double put on the
> cpumap for the placeholder core PMU:
> https://lore.kernel.org/lkml/20250318095132.1502654-3-tmricht at linux.ibm.com/
> Requiring the caller to get the cpumap is not how these things are
> usually done, switch cpu_map__online to do the get and then fix up any
> use cases where a put is needed.
> 
> Signed-off-by: Ian Rogers <irogers at google.com>

Ian,

thanks for fixing this. Here are the results on s390 z/VM:

# ./perf bench internals pmu-scan
# Running 'internals/pmu-scan' benchmark:
Computing performance of sysfs PMU event scan for 100 times
  Average core PMU scanning took: 6.340 usec (+- 0.050 usec)
  Average PMU scanning took: 93.785 usec (+- 6.210 usec)
# 

Tested-by: Thomas Richter <tmricht at linux.ibm.com>

-- 
Thomas Richter, Dept 3303, IBM s390 Linux Development, Boeblingen, Germany
--
IBM Deutschland Research & Development GmbH

Vorsitzender des Aufsichtsrats: Wolfgang Wendt

Gesch?ftsf?hrung: David Faller

Sitz der Gesellschaft: B?blingen / Registergericht: Amtsgericht Stuttgart, HRB 243294


From luis.gerhorst at fau.de  Wed Mar 19 02:06:27 2025
From: luis.gerhorst at fau.de (Luis Gerhorst)
Date: Wed, 19 Mar 2025 10:06:27 +0100
Subject: [PATCH bpf-next 11/11] bpf: Fall back to nospec for spec path
 verification
In-Reply-To: <CAADnVQKL-NwxigMWM+U=n5ZXPG+xHYzSTEv0Rq8Y91m45eRJDw@mail.gmail.com>
	(Alexei Starovoitov's message of "Tue, 18 Mar 2025 19:40:44 -0700")
References: <20250313172127.1098195-1-luis.gerhorst@fau.de>
	<20250313175312.1120183-1-luis.gerhorst@fau.de>
	<20250313175312.1120183-2-luis.gerhorst@fau.de>
	<CAADnVQKL-NwxigMWM+U=n5ZXPG+xHYzSTEv0Rq8Y91m45eRJDw@mail.gmail.com>
Message-ID: <87cyedie3w.fsf@fau.de>

Alexei Starovoitov <alexei.starovoitov at gmail.com> writes:

> On Thu, Mar 13, 2025 at 10:57?AM Luis Gerhorst <luis.gerhorst at fau.de> wrote:
>> With increased limits this allows applying mitigations to large BPF
>> progs such as the Parca Continuous Profiler's prog. However, this
>> requires a jump-seq limit of 256k. In any case, the same principle
>> should apply to smaller programs therefore include it even if the limit
>> stays at 8k for now. Most programs in [1] only require a limit of 32k.
>
> Do you mean that without this change the verifier needs 256k
> jmp limit to load Parca's prog as unpriv due to speculative
> path exploration with push_stack ?
>

Only with this change Parca is loadable when manually enabling Spectre
defenses for privileged programs and setting the following limits:
- BPF_COMPLEXITY_LIMIT_JMP_SEQ=256k
- BPF_COMPLEXITY_LIMIT_SPEC_V1_VERIFICATION=128k
- BPF_COMPLEXITY_LIMIT_INSNS=32M

>
> And this change uses 4k as a trade-off between prog runtime
> and verification time ?
>

Yes, this change uses 4k to limited nested speculative path exploration.
At the top-level (i.e., on architectural paths), spawned speculative
paths are still explored.

>
> But tracing progs use bpf_probe_read_kernel(), so they're never going
> to be unpriv.
>

I'm sorry this was not clear. Parca is only used as an example here
to test whether this improves expressiveness in general.

If you do not see this as a favorable tradeoff (because of the code
complexity), I think it would be acceptable to drop the last patch for
now. The biggest improvements is already achieved with the other patches
as evident from the selftests. I can do a more exhaustive analysis on
patch 11 later.

>
>> @@ -2010,6 +2011,19 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
>>         struct bpf_verifier_stack_elem *elem;
>>         int err;
>>
>> +       if (!env->bypass_spec_v1 &&
>> +           cur->speculative &&
>
> Should this be
> (cur->speculative || speculative)
> ?

No, I think it will be unsafe to add `|| speculative` here. If we were
to return -EINVAL from push_stack() when pushing a speculative path from
a non-speculative path (e.g., in check_cond_jmp_op() through
sanitize_speculative_path()), this will cause do_check() to add an
lfence before the jump-op.

Here's a minimal example program:

	A = true
	B = true
	if A goto e
	f()
	if B goto e
	unsafe()
e:	exit

There are the following speculative and non-speculative paths
(`cur->speculative` and `speculative` referring to the value of the
push_stack() parameters):

- A = true
- B = true
- if A goto e
  - A && !cur->speculative && !speculative
    - exit
  - !A && !cur->speculative && speculative
    - f()
    - if B goto e
      - B && cur->speculative && !speculative
        - exit
      - !B && cur->speculative && speculative
        - unsafe()

`|| speculative` might cause us to only add an lfence before `if A goto
e`, which would not be sufficient. Intel recommends adding the lfence
after the jump [1].

>
> In general I'm not convinced that the approach is safe.
>
> This recoverable EINVAL means that exploration under speculation
> stops early, but there could be more branches and they won't be
> sanitized with extra lfence.
> So speculative execution can still happen at later insns.
>

`goto process_bpf_exit` only causes us to stop analyzing this particular
path, not the rest of the program.

This is based on the assumption, that the lfence stops the CPU from ever
reaching those branches (if they are not reachable through other means).

>
> Similar concern in patch 7:
> + if (state->speculative && cur_aux(env)->nospec)
> +   goto process_bpf_exit;
>
> One lfence at this insn doesn't stop speculation until the program end.
> Only at this insn. The rest of the code is free to speculate.
>

Taking the program above as an example, this allows us to stop before
f() if an lfence was inserted there.

Fully patched program would be:

	A = true
	B = true
	if A goto e
	lfence
	f()
	if B goto e
	unsafe()
e:	exit

In this example, all instructions after the lfence are dead code (and
with the lfence they are also dead code speculatively).

I believe this is in line with Intel's guidance [1]:

	An LFENCE instruction or a serializing instruction will ensure that
	no later instructions execute, even speculatively, until all prior
	instructions complete locally. Developers might prefer LFENCE over a
	serializing instruction because LFENCE may have lower latency.
	Inserting an LFENCE instruction after a bounds check prevents later
	operations from executing before the bound check completes.

With regards to the example, this implies that `if B goto e` will not
execute before `if A goto e` completes. Once `if A goto e` completes,
the CPU should find that the speculation was wrong and continue with
`exit`.

If there is any other path that leads to `if B goto e` (and therefore
`unsafe()`) without going through `if A goto e`, then an lfence might of
course still be needed there. However, I assume this other path will be
explored separately and therefore be discovered by the verifier even if
the exploration discussed here stops at the lfence. If this assumption
is wrong, please let me know.

>
> The refactoring in patches 1-3 is nice.
> Patches 4-5 are tricky and somewhat questionable, but make sense.
> Patch 7 without early goto process_bpf_exit looks correct too,
> Patch 8 is borderline. Feels like it's opening the door for
> new vulnerabilities and space to explore for security researchers.
> We disabled unpriv bpf by default and have no intentions to enable it.
> Even if we land the whole thing the unpriv will stay disabled.
> So trade offs don't appear favorable.
>

Thank you very much for having a look. Let me know whether the above
resolves your concern.

In any case, should I separate patches 1-3 into another series?

[1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/runtime-speculative-side-channel-mitigations.html
    ("Managed Runtime Speculative Execution Side Channel Mitigations")


From kabel at kernel.org  Wed Mar 19 02:10:26 2025
From: kabel at kernel.org (Marek =?utf-8?B?QmVow7pu?=)
Date: Wed, 19 Mar 2025 10:10:26 +0100
Subject: [PATCH v12 4/6] clk: qcom: Add NSS clock Controller driver for
 IPQ9574
In-Reply-To: <ef86ccad056bc03af7f01d5696787766.sboyd@kernel.org>
References: <20250313110359.242491-1-quic_mmanikan@quicinc.com>
 <20250313110359.242491-5-quic_mmanikan@quicinc.com>
 <65gl7d6qd55xrdm3as3pnqevpmakin3k4jzyocehq7wq7565jj@x35t2inlykop>
 <ef86ccad056bc03af7f01d5696787766.sboyd@kernel.org>
Message-ID: <qf36kofpouii3m5bdihy5fizmsnnd7pzxltuhorynql57ivvey@uxplo7joejsd>

On Tue, Mar 18, 2025 at 03:50:31PM -0700, Stephen Boyd wrote:
> Quoting Marek Beh?n (2025-03-17 07:08:16)
> > On Thu, Mar 13, 2025 at 04:33:57PM +0530, Manikanta Mylavarapu wrote:
> > 
> > > +static struct clk_rcg2 nss_cc_clc_clk_src = {
> > > +     .cmd_rcgr = 0x28604,
> > > +     .mnd_width = 0,
> > > +     .hid_width = 5,
> > > +     .parent_map = nss_cc_parent_map_6,
> > > +     .freq_tbl = ftbl_nss_cc_clc_clk_src,
> > > +     .clkr.hw.init = &(const struct clk_init_data) {
> > > +             .name = "nss_cc_clc_clk_src",
> > > +             .parent_data = nss_cc_parent_data_6,
> > > +             .num_parents = ARRAY_SIZE(nss_cc_parent_data_6),
> > > +             .ops = &clk_rcg2_ops,
> > > +     },
> > > +};
> > 
> > This structure definition gets repeated many times in this driver,
> > with only slight changes. (This also happens in other qualcomm clock
> > drivers.)
> > 
> > Would it be possible to refactor it into a macro, to avoid the
> > insane code repetition?
> > 
> 
> We have this discussion every couple years or so. The short answer is
> no. The long answer is that it makes it harder to read because we don't
> know what argument to the macro corresponds to the struct members.
> 
> It could probably use the CLK_HW_INIT_PARENTS_DATA macro though.
> 
> static struct clk_rcg2 nss_cc_clc_clk_src = {
>      .cmd_rcgr = 0x28604,
>      .mnd_width = 0,
>      .hid_width = 5,
>      .parent_map = nss_cc_parent_map_6,
>      .freq_tbl = ftbl_nss_cc_clc_clk_src,
>      .clkr.hw.init = CLK_HW_INIT_PARENTS_DATA("nss_cc_clc_clk_src",
>                                               nss_cc_parent_data_6,
> 					      &clk_rcg2_ops, 0),
>      },
> };
> 
> but then we lose the const. Oh well.
> 
> The whole qcom clk driver probably needs an overhaul to just have
> descriptors that populate a bunch of clks that are allocated at probe
> time so that the memory footprint is smaller if you have multiple clk
> drivers loaded and so that we can probe the driver again without
> unloading the whole kernel module.

Okay then, in that case just ignore me :)


From daniel.baluta at gmail.com  Wed Mar 19 02:13:22 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:13:22 +0200
Subject: [PATCH v2] remoteproc: imx_dsp_rproc: Add support for
 DSP-specific features
In-Reply-To: <20250318215007.2109726-1-iuliana.prodan@oss.nxp.com>
References: <20250318215007.2109726-1-iuliana.prodan@oss.nxp.com>
Message-ID: <CAEnQRZCk042G01vfypi6SY3mR53kchHLYpHs_cg=sZ9vVyZFdQ@mail.gmail.com>

On Tue, Mar 18, 2025 at 11:50?PM Iuliana Prodan (OSS)
<iuliana.prodan at oss.nxp.com> wrote:
>
> From: Iuliana Prodan <iuliana.prodan at nxp.com>
>
> Some DSP firmware requires a FW_READY signal before proceeding, while
> others do not.
> Therefore, add support to handle i.MX DSP-specific features.
>
> Implement handle_rsc callback to handle resource table parsing and to
> process DSP-specific resource, to determine if waiting is needed.
>
> Update imx_dsp_rproc_start() to handle this condition accordingly.
>
> Signed-off-by: Iuliana Prodan <iuliana.prodan at nxp.com>

Reviewed-by: Daniel Baluta <daniel.baluta at nxp.com>


From leo.yan at arm.com  Wed Mar 19 02:13:33 2025
From: leo.yan at arm.com (Leo Yan)
Date: Wed, 19 Mar 2025 09:13:33 +0000
Subject: [PATCH v2 6/8] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250318-james-coresight-claim-tags-v2-6-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-6-e9c8a9cde84e@linaro.org>
Message-ID: <20250319091333.GG2860028@e132581.arm.com>

On Tue, Mar 18, 2025 at 04:22:00PM +0000, James Clark wrote:
> This can be left behind from a crashed kernel after a kexec so clear it
> when probing each device. Clearing the self hosted bit even when claimed
> externally is harmless, so do it unconditionally.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

Just a note from me.

I'd expect it would be a rare case that users enable a Arm CoreSight
trace in a dump-capture kernel, as the second kernel is for dumping
CoreSight trace data but it is not necessarily to enable CoreSight
components.

This patch is not only helpful for crash kernel case, it can dismiss
quirks caused by insane hardware reset cases.

Reviewed-by: Leo Yan <leo.yan at arm.com>

> ---
>  drivers/hwtracing/coresight/coresight-catu.c       | 1 +
>  drivers/hwtracing/coresight/coresight-cti-core.c   | 2 ++
>  drivers/hwtracing/coresight/coresight-etb10.c      | 2 ++
>  drivers/hwtracing/coresight/coresight-etm3x-core.c | 1 +
>  drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 ++
>  drivers/hwtracing/coresight/coresight-funnel.c     | 1 +
>  drivers/hwtracing/coresight/coresight-replicator.c | 1 +
>  drivers/hwtracing/coresight/coresight-tmc-core.c   | 1 +
>  8 files changed, 11 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index fa170c966bc3..deaacfd875af 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
>  	catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
>  	catu_desc.ops = &catu_ops;
>  
> +	coresight_clear_self_claim_tag(&catu_desc.access);
>  	drvdata->csdev = coresight_register(&catu_desc);
>  	if (IS_ERR(drvdata->csdev))
>  		ret = PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
> index 80f6265e3740..8fb30dd73fd2 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-core.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-core.c
> @@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>  	cti_desc.ops = &cti_ops;
>  	cti_desc.groups = drvdata->ctidev.con_groups;
>  	cti_desc.dev = dev;
> +
> +	coresight_clear_self_claim_tag(&cti_desc.access);
>  	drvdata->csdev = coresight_register(&cti_desc);
>  	if (IS_ERR(drvdata->csdev)) {
>  		ret = PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index 7948597d483d..2bfcb669aa84 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
>  	desc.pdata = pdata;
>  	desc.dev = dev;
>  	desc.groups = coresight_etb_groups;
> +
> +	coresight_clear_self_claim_tag(&desc.access);
>  	drvdata->csdev = coresight_register(&desc);
>  	if (IS_ERR(drvdata->csdev))
>  		return PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> index cfd463ac715c..1c6204e14422 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> @@ -764,6 +764,7 @@ static void etm_init_arch_data(void *info)
>  	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
>  	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
>  
> +	coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
>  	etm_set_pwrdwn(drvdata);
>  	etm_clr_pwrup(drvdata);
>  	CS_LOCK(drvdata->csa.base);
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index e5972f16abff..52c9aa56e8b9 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -1372,6 +1372,8 @@ static void etm4_init_arch_data(void *info)
>  	drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
>  	/* NUMCNTR, bits[30:28] number of counters available for tracing */
>  	drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
> +
> +	coresight_clear_self_claim_tag_unlocked(csa);
>  	etm4_cs_lock(drvdata, csa);
>  	cpu_detect_trace_filtering(drvdata);
>  }
> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
> index 0541712b2bcb..7249cc356ccb 100644
> --- a/drivers/hwtracing/coresight/coresight-funnel.c
> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
> @@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
>  		drvdata->base = base;
>  		desc.groups = coresight_funnel_groups;
>  		desc.access = CSDEV_ACCESS_IOMEM(base);
> +		coresight_clear_self_claim_tag(&desc.access);
>  	}
>  
>  	dev_set_drvdata(dev, drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
> index ee7ee79f6cf7..b2acd4535c74 100644
> --- a/drivers/hwtracing/coresight/coresight-replicator.c
> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
> @@ -284,6 +284,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
>  	desc.pdata = dev->platform_data;
>  	desc.dev = dev;
>  
> +	coresight_clear_self_claim_tag(&desc.access);
>  	drvdata->csdev = coresight_register(&desc);
>  	if (IS_ERR(drvdata->csdev)) {
>  		ret = PTR_ERR(drvdata->csdev);
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index a7814e8e657b..a09579eff3fd 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -869,6 +869,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
>  	dev->platform_data = pdata;
>  	desc.pdata = pdata;
>  
> +	coresight_clear_self_claim_tag(&desc.access);
>  	drvdata->csdev = coresight_register(&desc);
>  	if (IS_ERR(drvdata->csdev)) {
>  		ret = PTR_ERR(drvdata->csdev);
> 
> -- 
> 2.34.1
> 


From maz at kernel.org  Wed Mar 19 02:15:54 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 19 Mar 2025 09:15:54 +0000
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
	<20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
	<019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>
Message-ID: <86r02tmldh.wl-maz@kernel.org>

On Wed, 19 Mar 2025 00:26:14 +0000,
Gavin Shan <gshan at redhat.com> wrote:
> 
> Hi Mark,
> 
> On 3/14/25 10:35 AM, Mark Brown wrote:
> > From: Mark Rutland <mark.rutland at arm.com>
> > 
> > [ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]
> > 
> > In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
> > CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:
> > 
> > * For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
> >    by the guest hypervisor, which may be less than or equal to that
> >    guest's maximum VL.
> > 
> >    Note: in this case the value of ZCR_EL1 is immaterial due to E2H.
> > 
> > * For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
> >    which may be less than or greater than the guest's maximum VL.
> > 
> >    Note: in this case hyp code traps host SVE usage and lazily restores
> >    ZCR_EL2 to the host's maximum VL, which may be greater than the
> >    guest's maximum VL.
> > 
> > This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
> > If a softirq is taken during this period and the softirq handler tries
> > to use kernel-mode NEON, then the kernel will fail to save the guest's
> > FPSIMD/SVE state, and will pend a SIGKILL for the current thread.
> > 
> > This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
> > FPSIMD/SVE state with the guest's maximum SVE VL, and
> > fpsimd_save_user_state() verifies that the live SVE VL is as expected
> > before attempting to save the register state:
> > 
> > | if (WARN_ON(sve_get_vl() != vl)) {
> > |         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
> > |         return;
> > | }
> > 
> > Fix this and make this a bit easier to reason about by always eagerly
> > switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
> > happening, there's no need to trap host SVE usage, and the nVHE/nVHE
> > __deactivate_cptr_traps() logic can be simplified to enable host access
> > to all present FPSIMD/SVE/SME features.
> > 
> > In protected nVHE/hVHE modes, the host's state is always saved/restored
> > by hyp, and the guest's state is saved prior to exit to the host, so
> > from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
> > the host's ZCR_EL1 is never clobbered by hyp.
> > 
> > Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
> > Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
> > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> > Reviewed-by: Mark Brown <broonie at kernel.org>
> > Tested-by: Mark Brown <broonie at kernel.org>
> > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > Cc: Fuad Tabba <tabba at google.com>
> > Cc: Marc Zyngier <maz at kernel.org>
> > Cc: Oliver Upton <oliver.upton at linux.dev>
> > Cc: Will Deacon <will at kernel.org>
> > Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
> > Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > Signed-off-by: Mark Brown <broonie at kernel.org>
> > ---
> >   arch/arm64/kvm/fpsimd.c                 | 30 -----------------
> >   arch/arm64/kvm/hyp/entry.S              |  5 +++
> >   arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
> >   arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 13 ++++----
> >   arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
> >   arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
> >   6 files changed, 103 insertions(+), 41 deletions(-)
> > 
> 
> [...]
> 
> > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > index 4e757a77322c9efc59cdff501745f7c80d452358..1c8e2ad32e8c396fc4b11d5fec2e86728f2829d9 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > @@ -5,6 +5,7 @@
> >    */
> >     #include <hyp/adjust_pc.h>
> > +#include <hyp/switch.h>
> >     #include <asm/pgtable-types.h>
> >   #include <asm/kvm_asm.h>
> > @@ -176,8 +177,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
> >   		sync_hyp_vcpu(hyp_vcpu);
> >   		pkvm_put_hyp_vcpu(hyp_vcpu);
> >   	} else {
> > +		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
> > +
> >   		/* The host is fully trusted, run its vCPU directly. */
> > -		ret = __kvm_vcpu_run(host_vcpu);
> > +		fpsimd_lazy_switch_to_guest(vcpu);
> > +		ret = __kvm_vcpu_run(vcpu);
> > +		fpsimd_lazy_switch_to_host(vcpu);
> >   	}
> >   
> 
> @host_vcpu should have been hypervisor's linear mapping address in v6.12. It looks
> incorrect to assume it's a kernel's linear mapping address and convert it (@host_vcpu)
> to the hypervisor's linear address agin, if I don't miss anything.

host_vcpu is passed as a parameter to the hypercall, and is definitely
a kernel address.

However, at this stage, we have *already* converted it to a HYP VA:

https://web.git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/kvm/hyp/nvhe/hyp-main.c?h=linux-6.12.y#n147

The result is that this change is turning a perfectly valid HYP VA
into... something. Odds are that the masking/patching will not mess up
the address, but this is completely buggy anyway. In general,
kern_hyp_va() is not an idempotent operation.

Thanks for noticing that something was wrong.

Broonie, can you please look into this?

Greg, it may be more prudent to unstage this series from 6.12-stable
until we know for sure this is the only problem.

	M.

-- 
Without deviation from the norm, progress is not possible.


From jirislaby at kernel.org  Wed Mar 19 02:28:59 2025
From: jirislaby at kernel.org (Jiri Slaby (SUSE))
Date: Wed, 19 Mar 2025 10:28:59 +0100
Subject: [PATCH v2 06/57] irqdomain: irqchip: Switch to of_fwnode_handle()
In-Reply-To: <20250319092951.37667-1-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
Message-ID: <20250319092951.37667-7-jirislaby@kernel.org>

of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
defined of_fwnode_handle(). The former is in the process of being
removed, so use the latter instead.

Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
Cc: Antoine Tenart <atenart at kernel.org>
Cc: Sven Peter <sven at svenpeter.dev>
Cc: Janne Grunau <j at jannau.net>
Cc: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Gregory Clement <gregory.clement at bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Linus Walleij <linusw at kernel.org>
Cc: Imre Kaloz <kaloz at openwrt.org>
Cc: Herve Codina <herve.codina at bootlin.com>
Cc: Huacai Chen <chenhuacai at kernel.org>
Cc: WANG Xuerui <kernel at xen0n.name>
Cc: Jiaxun Yang <jiaxun.yang at flygoat.com>
Cc: Neil Armstrong <neil.armstrong at linaro.org>
Cc: Kevin Hilman <khilman at baylibre.com>
Cc: Jerome Brunet <jbrunet at baylibre.com>
Cc: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Cc: Anup Patel <anup at brainfault.org>
Cc: Paul Walmsley <paul.walmsley at sifive.com>
Cc: Palmer Dabbelt <palmer at dabbelt.com>
Cc: Albert Ou <aou at eecs.berkeley.edu>
Cc: Alexandre Ghiti <alex at ghiti.fr>
Cc: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
Cc: Alexandre Torgue <alexandre.torgue at foss.st.com>
Cc: Nishanth Menon <nm at ti.com>
Cc: Tero Kristo <kristo at kernel.org>
Cc: Santosh Shilimkar <ssantosh at kernel.org>
Cc: Kunihiko Hayashi <hayashi.kunihiko at socionext.com>
Cc: Masami Hiramatsu <mhiramat at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Cc: asahi at lists.linux.dev
Cc: loongarch at lists.linux.dev
Cc: linux-mips at vger.kernel.org
Cc: linux-amlogic at lists.infradead.org
Cc: linux-riscv at lists.infradead.org
Cc: linux-stm32 at st-md-mailman.stormreply.com
---
 drivers/irqchip/irq-alpine-msi.c            | 2 +-
 drivers/irqchip/irq-apple-aic.c             | 4 ++--
 drivers/irqchip/irq-armada-370-xp.c         | 4 ++--
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 2 +-
 drivers/irqchip/irq-gic-v3.c                | 4 ++--
 drivers/irqchip/irq-ixp4xx.c                | 2 +-
 drivers/irqchip/irq-lan966x-oic.c           | 2 +-
 drivers/irqchip/irq-loongarch-cpu.c         | 2 +-
 drivers/irqchip/irq-loongson-eiointc.c      | 2 +-
 drivers/irqchip/irq-loongson-htvec.c        | 2 +-
 drivers/irqchip/irq-loongson-liointc.c      | 2 +-
 drivers/irqchip/irq-loongson-pch-msi.c      | 2 +-
 drivers/irqchip/irq-loongson-pch-pic.c      | 2 +-
 drivers/irqchip/irq-ls-scfg-msi.c           | 2 +-
 drivers/irqchip/irq-meson-gpio.c            | 2 +-
 drivers/irqchip/irq-mvebu-gicp.c            | 2 +-
 drivers/irqchip/irq-mvebu-odmi.c            | 2 +-
 drivers/irqchip/irq-mvebu-sei.c             | 6 +++---
 drivers/irqchip/irq-qcom-mpm.c              | 2 +-
 drivers/irqchip/irq-riscv-intc.c            | 2 +-
 drivers/irqchip/irq-sni-exiu.c              | 2 +-
 drivers/irqchip/irq-stm32mp-exti.c          | 2 +-
 drivers/irqchip/irq-ti-sci-inta.c           | 4 ++--
 drivers/irqchip/irq-ti-sci-intr.c           | 2 +-
 drivers/irqchip/irq-uniphier-aidet.c        | 2 +-
 25 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c
index a1430ab60a8a..0207d35135da 100644
--- a/drivers/irqchip/irq-alpine-msi.c
+++ b/drivers/irqchip/irq-alpine-msi.c
@@ -213,7 +213,7 @@ static int alpine_msix_init_domains(struct alpine_msix_data *priv,
 		return -ENOMEM;
 	}
 
-	msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+	msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node),
 					       &alpine_msix_domain_info,
 					       middle_domain);
 	if (!msi_domain) {
diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c
index 974dc088c853..032d66dceb8e 100644
--- a/drivers/irqchip/irq-apple-aic.c
+++ b/drivers/irqchip/irq-apple-aic.c
@@ -1014,7 +1014,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
 
 	irqc->info.die_stride = off - start_off;
 
-	irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node),
+	irqc->hw_domain = irq_domain_create_tree(of_fwnode_handle(node),
 						 &aic_irq_domain_ops, irqc);
 	if (WARN_ON(!irqc->hw_domain))
 		goto err_unmap;
@@ -1067,7 +1067,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
 
 	if (is_kernel_in_hyp_mode()) {
 		struct irq_fwspec mi = {
-			.fwnode		= of_node_to_fwnode(node),
+			.fwnode		= of_fwnode_handle(node),
 			.param_count	= 3,
 			.param		= {
 				[0]	= AIC_FIQ, /* This is a lie */
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 2aa6a51e05d0..de98d16c1718 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -353,7 +353,7 @@ static int __init mpic_msi_init(struct mpic *mpic, struct device_node *node,
 	if (!mpic->msi_inner_domain)
 		return -ENOMEM;
 
-	mpic->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), &mpic_msi_domain_info,
+	mpic->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node), &mpic_msi_domain_info,
 						     mpic->msi_inner_domain);
 	if (!mpic->msi_domain) {
 		irq_domain_remove(mpic->msi_inner_domain);
@@ -492,7 +492,7 @@ static int __init mpic_ipi_init(struct mpic *mpic, struct device_node *node)
 {
 	int base_ipi;
 
-	mpic->ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
+	mpic->ipi_domain = irq_domain_create_linear(of_fwnode_handle(node), IPI_DOORBELL_NR,
 						    &mpic_ipi_domain_ops, mpic);
 	if (WARN_ON(!mpic->ipi_domain))
 		return -ENOMEM;
diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
index 8e87fc35f8aa..11549d85f23b 100644
--- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
@@ -152,7 +152,7 @@ static void __init its_fsl_mc_of_msi_init(void)
 		if (!of_property_read_bool(np, "msi-controller"))
 			continue;
 
-		its_fsl_mc_msi_init_one(of_node_to_fwnode(np),
+		its_fsl_mc_msi_init_one(of_fwnode_handle(np),
 					np->full_name);
 	}
 }
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 270d7a4d85a6..efc791c43d44 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1826,7 +1826,7 @@ static int partition_domain_translate(struct irq_domain *d,
 
 	ppi_idx = __gic_get_ppi_index(ppi_intid);
 	ret = partition_translate_id(gic_data.ppi_descs[ppi_idx],
-				     of_node_to_fwnode(np));
+				     of_fwnode_handle(np));
 	if (ret < 0)
 		return ret;
 
@@ -2192,7 +2192,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 
 		part = &parts[part_idx];
 
-		part->partition_id = of_node_to_fwnode(child_part);
+		part->partition_id = of_fwnode_handle(child_part);
 
 		pr_info("GIC: PPI partition %pOFn[%d] { ",
 			child_part, part_idx);
diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
index f23b02f62a5c..a9a5a52b818a 100644
--- a/drivers/irqchip/irq-ixp4xx.c
+++ b/drivers/irqchip/irq-ixp4xx.c
@@ -261,7 +261,7 @@ static int __init ixp4xx_of_init_irq(struct device_node *np,
 		pr_crit("IXP4XX: could not ioremap interrupt controller\n");
 		return -ENODEV;
 	}
-	fwnode = of_node_to_fwnode(np);
+	fwnode = of_fwnode_handle(np);
 
 	/* These chip variants have 64 interrupts */
 	is_356 = of_device_is_compatible(np, "intel,ixp43x-interrupt") ||
diff --git a/drivers/irqchip/irq-lan966x-oic.c b/drivers/irqchip/irq-lan966x-oic.c
index 41ac880e3b87..9445c3a6b1b0 100644
--- a/drivers/irqchip/irq-lan966x-oic.c
+++ b/drivers/irqchip/irq-lan966x-oic.c
@@ -224,7 +224,7 @@ static int lan966x_oic_probe(struct platform_device *pdev)
 		.exit		= lan966x_oic_chip_exit,
 	};
 	struct irq_domain_info d_info = {
-		.fwnode		= of_node_to_fwnode(pdev->dev.of_node),
+		.fwnode		= of_fwnode_handle(pdev->dev.of_node),
 		.domain_flags	= IRQ_DOMAIN_FLAG_DESTROY_GC,
 		.size		= LAN966X_OIC_NR_IRQ,
 		.hwirq_max	= LAN966X_OIC_NR_IRQ,
diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
index e62dab4c97fc..950bc087e388 100644
--- a/drivers/irqchip/irq-loongarch-cpu.c
+++ b/drivers/irqchip/irq-loongarch-cpu.c
@@ -100,7 +100,7 @@ static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
 static int __init cpuintc_of_init(struct device_node *of_node,
 				struct device_node *parent)
 {
-	cpuintc_handle = of_node_to_fwnode(of_node);
+	cpuintc_handle = of_fwnode_handle(of_node);
 
 	irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM,
 				&loongarch_cpu_intc_irq_domain_ops, NULL);
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
index bb79e19dfb59..b2860eb2d32c 100644
--- a/drivers/irqchip/irq-loongson-eiointc.c
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -554,7 +554,7 @@ static int __init eiointc_of_init(struct device_node *of_node,
 		priv->vec_count = VEC_COUNT;
 
 	priv->node = 0;
-	priv->domain_handle = of_node_to_fwnode(of_node);
+	priv->domain_handle = of_fwnode_handle(of_node);
 
 	ret = eiointc_init(priv, parent_irq, 0);
 	if (ret < 0)
diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c
index 5da02c7ad0b3..d8558eb35044 100644
--- a/drivers/irqchip/irq-loongson-htvec.c
+++ b/drivers/irqchip/irq-loongson-htvec.c
@@ -248,7 +248,7 @@ static int htvec_of_init(struct device_node *node,
 	}
 
 	err = htvec_init(res.start, resource_size(&res),
-			num_parents, parent_irq, of_node_to_fwnode(node));
+			num_parents, parent_irq, of_fwnode_handle(node));
 	if (err < 0)
 		return err;
 
diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 2b1bd4a96665..95cade56e0be 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -363,7 +363,7 @@ static int __init liointc_of_init(struct device_node *node,
 	}
 
 	err = liointc_init(res.start, resource_size(&res),
-			revision, of_node_to_fwnode(node), node);
+			revision, of_fwnode_handle(node), node);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
index 9c62108b3ad5..c07876ae7b49 100644
--- a/drivers/irqchip/irq-loongson-pch-msi.c
+++ b/drivers/irqchip/irq-loongson-pch-msi.c
@@ -243,7 +243,7 @@ static int pch_msi_of_init(struct device_node *node, struct device_node *parent)
 		return -EINVAL;
 	}
 
-	err = pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_node_to_fwnode(node));
+	err = pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_fwnode_handle(node));
 	if (err < 0)
 		return err;
 
diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
index 69efda35a8e7..62e6bf3a0611 100644
--- a/drivers/irqchip/irq-loongson-pch-pic.c
+++ b/drivers/irqchip/irq-loongson-pch-pic.c
@@ -392,7 +392,7 @@ static int pch_pic_of_init(struct device_node *node,
 	}
 
 	err = pch_pic_init(res.start, resource_size(&res), vec_base,
-				parent_domain, of_node_to_fwnode(node), 0);
+				parent_domain, of_fwnode_handle(node), 0);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 3cb80796cc7c..cbe11a8afe4f 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -225,7 +225,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
 	}
 
 	msi_data->msi_domain = pci_msi_create_irq_domain(
-				of_node_to_fwnode(msi_data->pdev->dev.of_node),
+				of_fwnode_handle(msi_data->pdev->dev.of_node),
 				&ls_scfg_msi_domain_info,
 				msi_data->parent);
 	if (!msi_data->msi_domain) {
diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index 0a25536a5d07..7d177626d64b 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -607,7 +607,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
 
 	domain = irq_domain_create_hierarchy(parent_domain, 0,
 					     ctl->params->nr_hwirq,
-					     of_node_to_fwnode(node),
+					     of_fwnode_handle(node),
 					     &meson_gpio_irq_domain_ops,
 					     ctl);
 	if (!domain) {
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
index d67f93f6d750..521cc265c05e 100644
--- a/drivers/irqchip/irq-mvebu-gicp.c
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -232,7 +232,7 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
 
 	inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
 						   gicp->spi_cnt,
-						   of_node_to_fwnode(node),
+						   of_fwnode_handle(node),
 						   &gicp_domain_ops, gicp);
 	if (!inner_domain)
 		return -ENOMEM;
diff --git a/drivers/irqchip/irq-mvebu-odmi.c b/drivers/irqchip/irq-mvebu-odmi.c
index 28f7e81df94f..c1fcd4525e3b 100644
--- a/drivers/irqchip/irq-mvebu-odmi.c
+++ b/drivers/irqchip/irq-mvebu-odmi.c
@@ -207,7 +207,7 @@ static int __init mvebu_odmi_init(struct device_node *node,
 
 	inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
 						   odmis_count * NODMIS_PER_FRAME,
-						   of_node_to_fwnode(node),
+						   of_fwnode_handle(node),
 						   &odmi_domain_ops, NULL);
 	if (!inner_domain) {
 		ret = -ENOMEM;
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
index ebd4a9014e8d..5030fcecdcc3 100644
--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -402,7 +402,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
 	}
 
 	/* Create the root SEI domain */
-	sei->sei_domain = irq_domain_create_linear(of_node_to_fwnode(node),
+	sei->sei_domain = irq_domain_create_linear(of_fwnode_handle(node),
 						   (sei->caps->ap_range.size +
 						    sei->caps->cp_range.size),
 						   &mvebu_sei_domain_ops,
@@ -418,7 +418,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
 	/* Create the 'wired' domain */
 	sei->ap_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
 						     sei->caps->ap_range.size,
-						     of_node_to_fwnode(node),
+						     of_fwnode_handle(node),
 						     &mvebu_sei_ap_domain_ops,
 						     sei);
 	if (!sei->ap_domain) {
@@ -432,7 +432,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
 	/* Create the 'MSI' domain */
 	sei->cp_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
 						     sei->caps->cp_range.size,
-						     of_node_to_fwnode(node),
+						     of_fwnode_handle(node),
 						     &mvebu_sei_cp_domain_ops,
 						     sei);
 	if (!sei->cp_domain) {
diff --git a/drivers/irqchip/irq-qcom-mpm.c b/drivers/irqchip/irq-qcom-mpm.c
index 7942d8eb3d00..00c770e367d0 100644
--- a/drivers/irqchip/irq-qcom-mpm.c
+++ b/drivers/irqchip/irq-qcom-mpm.c
@@ -447,7 +447,7 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
 
 	priv->domain = irq_domain_create_hierarchy(parent_domain,
 				IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP, pin_cnt,
-				of_node_to_fwnode(np), &qcom_mpm_ops, priv);
+				of_fwnode_handle(np), &qcom_mpm_ops, priv);
 	if (!priv->domain) {
 		dev_err(dev, "failed to create MPM domain\n");
 		ret = -ENOMEM;
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index f653c13de62b..e5805885394e 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -242,7 +242,7 @@ static int __init riscv_intc_init(struct device_node *node,
 		chip = &andes_intc_chip;
 	}
 
-	return riscv_intc_init_common(of_node_to_fwnode(node), chip);
+	return riscv_intc_init_common(of_fwnode_handle(node), chip);
 }
 
 IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
index c7db617e1a2f..7d10bf6e5824 100644
--- a/drivers/irqchip/irq-sni-exiu.c
+++ b/drivers/irqchip/irq-sni-exiu.c
@@ -249,7 +249,7 @@ static int __init exiu_dt_init(struct device_node *node,
 		return -ENXIO;
 	}
 
-	data = exiu_init(of_node_to_fwnode(node), &res);
+	data = exiu_init(of_fwnode_handle(node), &res);
 	if (IS_ERR(data))
 		return PTR_ERR(data);
 
diff --git a/drivers/irqchip/irq-stm32mp-exti.c b/drivers/irqchip/irq-stm32mp-exti.c
index cb83d6cc6113..649b84f12efc 100644
--- a/drivers/irqchip/irq-stm32mp-exti.c
+++ b/drivers/irqchip/irq-stm32mp-exti.c
@@ -531,7 +531,7 @@ static int stm32mp_exti_domain_alloc(struct irq_domain *dm,
 		if (ret)
 			return ret;
 		/* we only support one parent, so far */
-		if (of_node_to_fwnode(out_irq.np) != dm->parent->fwnode)
+		if (of_fwnode_handle(out_irq.np) != dm->parent->fwnode)
 			return -EINVAL;
 
 		of_phandle_args_to_fwspec(out_irq.np, out_irq.args,
diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c
index a887efba262c..38dfc1f9a56b 100644
--- a/drivers/irqchip/irq-ti-sci-inta.c
+++ b/drivers/irqchip/irq-ti-sci-inta.c
@@ -233,7 +233,7 @@ static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_dom
 	INIT_LIST_HEAD(&vint_desc->list);
 
 	parent_node = of_irq_find_parent(dev_of_node(&inta->pdev->dev));
-	parent_fwspec.fwnode = of_node_to_fwnode(parent_node);
+	parent_fwspec.fwnode = of_fwnode_handle(parent_node);
 
 	if (of_device_is_compatible(parent_node, "arm,gic-v3")) {
 		/* Parent is GIC */
@@ -709,7 +709,7 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node),
+	msi_domain = ti_sci_inta_msi_create_irq_domain(of_fwnode_handle(node),
 						&ti_sci_inta_msi_domain_info,
 						domain);
 	if (!msi_domain) {
diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c
index b49a73106c69..686a8f69fd9c 100644
--- a/drivers/irqchip/irq-ti-sci-intr.c
+++ b/drivers/irqchip/irq-ti-sci-intr.c
@@ -149,7 +149,7 @@ static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain,
 		goto err_irqs;
 
 	parent_node = of_irq_find_parent(dev_of_node(intr->dev));
-	fwspec.fwnode = of_node_to_fwnode(parent_node);
+	fwspec.fwnode = of_fwnode_handle(parent_node);
 
 	if (of_device_is_compatible(parent_node, "arm,gic-v3")) {
 		/* Parent is GIC */
diff --git a/drivers/irqchip/irq-uniphier-aidet.c b/drivers/irqchip/irq-uniphier-aidet.c
index 601f9343d5b3..6005c2d28dd9 100644
--- a/drivers/irqchip/irq-uniphier-aidet.c
+++ b/drivers/irqchip/irq-uniphier-aidet.c
@@ -188,7 +188,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
 	priv->domain = irq_domain_create_hierarchy(
 					parent_domain, 0,
 					UNIPHIER_AIDET_NR_IRQS,
-					of_node_to_fwnode(dev->of_node),
+					of_fwnode_handle(dev->of_node),
 					&uniphier_aidet_domain_ops, priv);
 	if (!priv->domain)
 		return -ENOMEM;
-- 
2.49.0



From jirislaby at kernel.org  Wed Mar 19 02:29:00 2025
From: jirislaby at kernel.org (Jiri Slaby (SUSE))
Date: Wed, 19 Mar 2025 10:29:00 +0100
Subject: [PATCH v2 07/57] irqdomain: pci: Switch to of_fwnode_handle()
In-Reply-To: <20250319092951.37667-1-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
Message-ID: <20250319092951.37667-8-jirislaby@kernel.org>

of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
defined of_fwnode_handle(). The former is in the process of being
removed, so use the latter instead.

Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
Cc: Jingoo Han <jingoohan1 at gmail.com>
Cc: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
Cc: Lorenzo Pieralisi <lpieralisi at kernel.org>
Cc: "Krzysztof Wilczy?ski" <kw at linux.com>
Cc: Rob Herring <robh at kernel.org>
Cc: Bjorn Helgaas <bhelgaas at google.com>
Cc: Karthikeyan Mitran <m.karthikeyan at mobiveil.co.in>
Cc: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
Cc: Toan Le <toan at os.amperecomputing.com>
Cc: Joyce Ooi <joyce.ooi at intel.com>
Cc: Jim Quinlan <jim2101024 at gmail.com>
Cc: Nicolas Saenz Julienne <nsaenz at kernel.org>
Cc: Florian Fainelli <florian.fainelli at broadcom.com>
Cc: Broadcom internal kernel review list <bcm-kernel-feedback-list at broadcom.com>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Scott Branden <sbranden at broadcom.com>
Cc: Ryder Lee <ryder.lee at mediatek.com>
Cc: Jianjun Wang <jianjun.wang at mediatek.com>
Cc: Michal Simek <michal.simek at amd.com>
Cc: Daire McNamara <daire.mcnamara at microchip.com>
Cc: linux-pci at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-mediatek at lists.infradead.org
---
 drivers/pci/controller/dwc/pcie-designware-host.c    | 2 +-
 drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 2 +-
 drivers/pci/controller/pci-xgene-msi.c               | 2 +-
 drivers/pci/controller/pcie-altera-msi.c             | 2 +-
 drivers/pci/controller/pcie-brcmstb.c                | 2 +-
 drivers/pci/controller/pcie-iproc-msi.c              | 2 +-
 drivers/pci/controller/pcie-mediatek.c               | 2 +-
 drivers/pci/controller/pcie-xilinx-dma-pl.c          | 2 +-
 drivers/pci/controller/pcie-xilinx-nwl.c             | 2 +-
 drivers/pci/controller/plda/pcie-plda-host.c         | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ecc33f6789e3..d1cd48efad43 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -227,7 +227,7 @@ static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
 int dw_pcie_allocate_domains(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-	struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(pci->dev->of_node);
 
 	pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,
 					       &dw_pcie_msi_domain_ops, pp);
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
index 0e088e74155d..6628eed9d26e 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -435,7 +435,7 @@ static const struct irq_domain_ops msi_domain_ops = {
 static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie)
 {
 	struct device *dev = &pcie->pdev->dev;
-	struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node);
 	struct mobiveil_msi *msi = &pcie->rp.msi;
 
 	mutex_init(&msi->lock);
diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c
index 7bce327897c9..69a9c0a87639 100644
--- a/drivers/pci/controller/pci-xgene-msi.c
+++ b/drivers/pci/controller/pci-xgene-msi.c
@@ -247,7 +247,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
 	if (!msi->inner_domain)
 		return -ENOMEM;
 
-	msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
+	msi->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(msi->node),
 						    &xgene_msi_domain_info,
 						    msi->inner_domain);
 
diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c
index e1cee3c0575f..5fb3a2e0017e 100644
--- a/drivers/pci/controller/pcie-altera-msi.c
+++ b/drivers/pci/controller/pcie-altera-msi.c
@@ -164,7 +164,7 @@ static const struct irq_domain_ops msi_domain_ops = {
 
 static int altera_allocate_domains(struct altera_msi *msi)
 {
-	struct fwnode_handle *fwnode = of_node_to_fwnode(msi->pdev->dev.of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(msi->pdev->dev.of_node);
 
 	msi->inner_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
 					     &msi_domain_ops, msi);
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 8b2b099e81eb..1f356fca07a2 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -581,7 +581,7 @@ static const struct irq_domain_ops msi_domain_ops = {
 
 static int brcm_allocate_domains(struct brcm_msi *msi)
 {
-	struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
+	struct fwnode_handle *fwnode = of_fwnode_handle(msi->np);
 	struct device *dev = msi->dev;
 
 	msi->inner_domain = irq_domain_add_linear(NULL, msi->nr, &msi_domain_ops, msi);
diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c
index 649fcb449f34..804b3a5787c5 100644
--- a/drivers/pci/controller/pcie-iproc-msi.c
+++ b/drivers/pci/controller/pcie-iproc-msi.c
@@ -451,7 +451,7 @@ static int iproc_msi_alloc_domains(struct device_node *node,
 	if (!msi->inner_domain)
 		return -ENOMEM;
 
-	msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+	msi->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node),
 						    &iproc_msi_domain_info,
 						    msi->inner_domain);
 	if (!msi->msi_domain) {
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 811a8b4acd50..efcc4a7c17be 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -485,7 +485,7 @@ static struct msi_domain_info mtk_msi_domain_info = {
 
 static int mtk_pcie_allocate_msi_domains(struct mtk_pcie_port *port)
 {
-	struct fwnode_handle *fwnode = of_node_to_fwnode(port->pcie->dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(port->pcie->dev->of_node);
 
 	mutex_init(&port->lock);
 
diff --git a/drivers/pci/controller/pcie-xilinx-dma-pl.c b/drivers/pci/controller/pcie-xilinx-dma-pl.c
index dd117f07fc95..71cf13ae51c7 100644
--- a/drivers/pci/controller/pcie-xilinx-dma-pl.c
+++ b/drivers/pci/controller/pcie-xilinx-dma-pl.c
@@ -470,7 +470,7 @@ static int xilinx_pl_dma_pcie_init_msi_irq_domain(struct pl_dma_pcie *port)
 	struct device *dev = port->dev;
 	struct xilinx_msi *msi = &port->msi;
 	int size = BITS_TO_LONGS(XILINX_NUM_MSI_IRQS) * sizeof(long);
-	struct fwnode_handle *fwnode = of_node_to_fwnode(port->dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(port->dev->of_node);
 
 	msi->dev_domain = irq_domain_add_linear(NULL, XILINX_NUM_MSI_IRQS,
 						&dev_msi_domain_ops, port);
diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index 8d6e2a89b067..9cf8a96f7bc4 100644
--- a/drivers/pci/controller/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
@@ -495,7 +495,7 @@ static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie)
 {
 #ifdef CONFIG_PCI_MSI
 	struct device *dev = pcie->dev;
-	struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node);
 	struct nwl_msi *msi = &pcie->msi;
 
 	msi->dev_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR,
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index 4153214ca410..4c7a9fa311e3 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -150,7 +150,7 @@ static struct msi_domain_info plda_msi_domain_info = {
 static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
 {
 	struct device *dev = port->dev;
-	struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
+	struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node);
 	struct plda_msi *msi = &port->msi;
 
 	mutex_init(&port->msi.lock);
-- 
2.49.0



From jirislaby at kernel.org  Wed Mar 19 02:29:41 2025
From: jirislaby at kernel.org (Jiri Slaby (SUSE))
Date: Wed, 19 Mar 2025 10:29:41 +0100
Subject: [PATCH v2 48/57] irqdomain: soc: Switch to irq_find_mapping()
In-Reply-To: <20250319092951.37667-1-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
Message-ID: <20250319092951.37667-49-jirislaby@kernel.org>

irq_linear_revmap() is deprecated, so remove all its uses and supersede
them by an identical call to irq_find_mapping().

Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
Cc: Qiang Zhao <qiang.zhao at nxp.com>
Cc: Christophe Leroy <christophe.leroy at csgroup.eu>
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 drivers/soc/fsl/qe/qe_ic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c
index e5831c298ad6..e4b6ff2cc76b 100644
--- a/drivers/soc/fsl/qe/qe_ic.c
+++ b/drivers/soc/fsl/qe/qe_ic.c
@@ -344,7 +344,7 @@ static unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
 	if (irq == 0)
 		return 0;
 
-	return irq_linear_revmap(qe_ic->irqhost, irq);
+	return irq_find_mapping(qe_ic->irqhost, irq);
 }
 
 /* Return an interrupt vector or 0 if no interrupt is pending. */
@@ -360,7 +360,7 @@ static unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
 	if (irq == 0)
 		return 0;
 
-	return irq_linear_revmap(qe_ic->irqhost, irq);
+	return irq_find_mapping(qe_ic->irqhost, irq);
 }
 
 static void qe_ic_cascade_low(struct irq_desc *desc)
-- 
2.49.0



From angelogioacchino.delregno at collabora.com  Wed Mar 19 02:34:46 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 19 Mar 2025 10:34:46 +0100
Subject: [PATCH 2/4] dt-bindings: remoteproc: mediatek: Remove l1tcm for
 dual-core MT8188 SCP
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
Message-ID: <70c10764-121b-43f5-931e-84ffd666c594@collabora.com>

Il 18/03/25 23:22, N?colas F. R. A. Prado ha scritto:
> The SCP present on MT8188 does not have an L1TCM memory region, but the
> binding incorrectly requires one for the dual-core description of the
> MT8188 SCP. Remove that requirement. Also update the minimum number of
> reg and reg-names to 1, since as this is a multi-core SCP with no
> L1TCM memory, only the CFG memory region is present in the parent node.
> 
> Fixes: 91e0d560b9fd ("dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP")
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

As far as I know, the L1TCM is present on MT8188, and it's at 0x1070000 len 0x8000
exactly like MT8195.

Moudy, are you able to please confirm or deny that?

Cheers,
Angelo




From peter.chen at cixtech.com  Wed Mar 19 02:31:01 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Wed, 19 Mar 2025 17:31:01 +0800
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <20250319062534.ollh3s5t7znf5zqs@uda0492258>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <Z9pffxeXHVOsoi4O@nchen-desktop>
 <20250319062534.ollh3s5t7znf5zqs@uda0492258>
Message-ID: <Z9qO1f5MgNcwO5A4@nchen-desktop>

On 25-03-19 14:25:34, Siddharth Vadapalli wrote:
> > >
> > > Hello,
> > >
> > > This series enables support to build the PCIe Cadence Controller drivers
> > > and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
> > > Modules. The motivation for this series is that PCIe is not a necessity
> > > for booting the SoC, due to which it doesn't have to be a built-in
> > > module. Additionally, the defconfig doesn't enable the PCIe Cadence
> > > Controller drivers and the PCI J721E driver, due to which PCIe is not
> > > supported by default. Enabling the configs as of now (i.e. without this
> > > series) will result in built-in drivers i.e. a bloated Linux Image for
> > > everyone who doesn't have the PCIe Controller.
> >
> > If the user doesn't enable PCIe controller device through DTS/ACPI,
> > that's doesn't matter.
> 
> The Linux Image for arm64 systems built using:
> arch/arm64/configs/defconfig
> will not have support for the Cadence PCIe Controller and the PCIe J721e
> driver, because these configs aren't enabled.
> 
> >
> > > @@ -209,6 +209,12 @@ CONFIG_NFC=m
> > >  CONFIG_NFC_NCI=m
> > >  CONFIG_NFC_S3FWRN5_I2C=m
> > >  CONFIG_PCI=y
> > > +CONFIG_PCI_J721E=m
> > > +CONFIG_PCI_J721E_HOST=m
> > > +CONFIG_PCI_J721E_EP=m
> > > +CONFIG_PCIE_CADENCE=m
> > > +CONFIG_PCIE_CADENCE_HOST=m
> > > +CONFIG_PCIE_CADENCE_EP=m
> >
> > The common Cadence configuration will be select if the glue layer's
> > configuration is select according to Kconfig.
> >
> > Please do not set common configuration as module, some user may need
> > it as build-in like dw's. Considering the situation, the rootfs is at
> > NVMe.
> 
> The common configuration at the moment is "DISABLED" i.e. no support for
> the Cadence Controller at all. Which "user" are you referring to? This
> series was introduced since having the drivers built-in was pushed back at:

We are using Cadence controller, and prepare upstream radxa-o6 board
whose rootfs is at PCIe NVMe.

You could build driver as module for TI glue layer, but don't force
other vendors using module as well, see dwc as an example please.

-- 

Best regards,
Peter


From jirislaby at kernel.org  Wed Mar 19 02:29:07 2025
From: jirislaby at kernel.org (Jiri Slaby (SUSE))
Date: Wed, 19 Mar 2025 10:29:07 +0100
Subject: [PATCH v2 14/57] irqdomain: arm: Switch to irq_domain_create_*()
In-Reply-To: <20250319092951.37667-1-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
Message-ID: <20250319092951.37667-15-jirislaby@kernel.org>

irq_domain_add_*() interfaces are going away as being obsolete now.
Switch to the preferred irq_domain_create_*() ones. Those differ in the
node parameter: They take more generic struct fwnode_handle instead of
struct device_node. Therefore, of_fwnode_handle() is added around the
original parameter.

Note some of the users can likely use dev->fwnode directly instead of
indirect of_fwnode_handle(dev->of_node). But dev->fwnode is not
guaranteed to be set for all, so this has to be investigated on case to
case basis (by people who can actually test with the HW).

Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
Cc: Russell King <linux at armlinux.org.uk>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Alim Akhtar <alim.akhtar at samsung.com>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Aaro Koskinen <aaro.koskinen at iki.fi>
Cc: Janusz Krzysztofik <jmkrzyszt at gmail.com>
Cc: Tony Lindgren <tony at atomide.com>
Cc: Andreas Kemnade <andreas at kemnade.info>
Cc: Kevin Hilman <khilman at baylibre.com>
Cc: Roger Quadros <rogerq at kernel.org>
Cc: Daniel Mack <daniel at zonque.org>
Cc: Haojian Zhuang <haojian.zhuang at gmail.com>
Cc: Robert Jarzmik <robert.jarzmik at free.fr>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
Cc: Gregory Clement <gregory.clement at bootlin.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm/common/sa1111.c             |  6 +++---
 arch/arm/mach-exynos/suspend.c       |  5 ++---
 arch/arm/mach-imx/avic.c             |  4 ++--
 arch/arm/mach-imx/gpc.c              |  5 ++---
 arch/arm/mach-imx/tzic.c             |  4 ++--
 arch/arm/mach-omap1/irq.c            |  3 +--
 arch/arm/mach-omap2/omap-wakeupgen.c |  5 ++---
 arch/arm/mach-pxa/irq.c              |  5 ++---
 arch/arm/plat-orion/gpio.c           | 12 ++++++------
 9 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 9846f30990f7..02eda44a6faa 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -416,9 +416,9 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
 	writel_relaxed(~0, irqbase + SA1111_INTSTATCLR0);
 	writel_relaxed(~0, irqbase + SA1111_INTSTATCLR1);
 
-	sachip->irqdomain = irq_domain_add_linear(NULL, SA1111_IRQ_NR,
-						  &sa1111_irqdomain_ops,
-						  sachip);
+	sachip->irqdomain = irq_domain_create_linear(NULL, SA1111_IRQ_NR,
+						     &sa1111_irqdomain_ops,
+						     sachip);
 	if (!sachip->irqdomain) {
 		irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
 		return -ENOMEM;
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index cac4e82f6c82..150a1e56dcae 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -209,9 +209,8 @@ static int __init exynos_pmu_irq_init(struct device_node *node,
 		return -ENOMEM;
 	}
 
-	domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
-					  node, &exynos_pmu_domain_ops,
-					  NULL);
+	domain = irq_domain_create_hierarchy(parent_domain, 0, 0, of_fwnode_handle(node),
+					     &exynos_pmu_domain_ops, NULL);
 	if (!domain) {
 		iounmap(pmu_base_addr);
 		pmu_base_addr = NULL;
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c
index cf6546ddc7a3..3067c06b4b8e 100644
--- a/arch/arm/mach-imx/avic.c
+++ b/arch/arm/mach-imx/avic.c
@@ -201,8 +201,8 @@ static void __init mxc_init_irq(void __iomem *irqbase)
 	WARN_ON(irq_base < 0);
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,avic");
-	domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
+	domain = irq_domain_create_legacy(of_fwnode_handle(np), AVIC_NUM_IRQS, irq_base, 0,
+					  &irq_domain_simple_ops, NULL);
 	WARN_ON(!domain);
 
 	for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 5909088d5482..2e633569d2f8 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -245,9 +245,8 @@ static int __init imx_gpc_init(struct device_node *node,
 	if (WARN_ON(!gpc_base))
 	        return -ENOMEM;
 
-	domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
-					  node, &imx_gpc_domain_ops,
-					  NULL);
+	domain = irq_domain_create_hierarchy(parent_domain, 0, GPC_MAX_IRQS, of_fwnode_handle(node),
+					     &imx_gpc_domain_ops, NULL);
 	if (!domain) {
 		iounmap(gpc_base);
 		return -ENOMEM;
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c
index 8b3d98d288d9..50a5668e65d2 100644
--- a/arch/arm/mach-imx/tzic.c
+++ b/arch/arm/mach-imx/tzic.c
@@ -175,8 +175,8 @@ static int __init tzic_init_dt(struct device_node *np, struct device_node *p)
 	irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
 	WARN_ON(irq_base < 0);
 
-	domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
+	domain = irq_domain_create_legacy(of_fwnode_handle(np), TZIC_NUM_IRQS, irq_base, 0,
+					  &irq_domain_simple_ops, NULL);
 	WARN_ON(!domain);
 
 	for (i = 0; i < 4; i++, irq_base += 32)
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 9b587ecebb1c..bb1bc060ecd8 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -220,8 +220,7 @@ void __init omap1_init_irq(void)
 	omap_l2_irq = irq_base;
 	omap_l2_irq -= NR_IRQS_LEGACY;
 
-	domain = irq_domain_add_legacy(NULL, nr_irqs, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
+	domain = irq_domain_create_legacy(NULL, nr_irqs, irq_base, 0, &irq_domain_simple_ops, NULL);
 
 	pr_info("Total of %lu interrupts in %i interrupt banks\n",
 		nr_irqs, irq_bank_count);
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 6f0d6120c174..a66b1dc61571 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -585,9 +585,8 @@ static int __init wakeupgen_init(struct device_node *node,
 		wakeupgen_ops = &am43xx_wakeupgen_ops;
 	}
 
-	domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
-					  node, &wakeupgen_domain_ops,
-					  NULL);
+	domain = irq_domain_create_hierarchy(parent_domain, 0, max_irqs, of_fwnode_handle(node),
+					     &wakeupgen_domain_ops, NULL);
 	if (!domain) {
 		iounmap(wakeupgen_base);
 		return -ENOMEM;
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index d9cadd97748a..5bfce8aa4102 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -147,9 +147,8 @@ pxa_init_irq_common(struct device_node *node, int irq_nr,
 	int n;
 
 	pxa_internal_irq_nr = irq_nr;
-	pxa_irq_domain = irq_domain_add_legacy(node, irq_nr,
-					       PXA_IRQ(0), 0,
-					       &pxa_irq_ops, NULL);
+	pxa_irq_domain = irq_domain_create_legacy(of_fwnode_handle(node), irq_nr, PXA_IRQ(0), 0,
+						  &pxa_irq_ops, NULL);
 	if (!pxa_irq_domain)
 		panic("Unable to add PXA IRQ domain\n");
 	irq_set_default_domain(pxa_irq_domain);
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index 595e9cb33c1d..a15f47450084 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -602,12 +602,12 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
 			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
 	/* Setup irq domain on top of the generic chip. */
-	ochip->domain = irq_domain_add_legacy(NULL,
-					      ochip->chip.ngpio,
-					      ochip->secondary_irq_base,
-					      ochip->secondary_irq_base,
-					      &irq_domain_simple_ops,
-					      ochip);
+	ochip->domain = irq_domain_create_legacy(NULL,
+						 ochip->chip.ngpio,
+						 ochip->secondary_irq_base,
+						 ochip->secondary_irq_base,
+						 &irq_domain_simple_ops,
+						 ochip);
 	if (!ochip->domain)
 		panic("%s: couldn't allocate irq domain (DT).\n",
 		      ochip->chip.label);
-- 
2.49.0



From jirislaby at kernel.org  Wed Mar 19 02:29:39 2025
From: jirislaby at kernel.org (Jiri Slaby (SUSE))
Date: Wed, 19 Mar 2025 10:29:39 +0100
Subject: [PATCH v2 46/57] irqdomain: irqchip: Switch to irq_find_mapping()
In-Reply-To: <20250319092951.37667-1-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
Message-ID: <20250319092951.37667-47-jirislaby@kernel.org>

irq_linear_revmap() is deprecated, so remove all its uses and supersede
them by an identical call to irq_find_mapping().

Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Gregory Clement <gregory.clement at bootlin.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: linux-arm-kernel at lists.infradead.org
---
 drivers/irqchip/irq-armada-370-xp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index e51612992735..67b672a78862 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -546,7 +546,7 @@ static void mpic_reenable_percpu(struct mpic *mpic)
 {
 	/* Re-enable per-CPU interrupts that were enabled before suspend */
 	for (irq_hw_number_t i = 0; i < MPIC_PER_CPU_IRQS_NR; i++) {
-		unsigned int virq = irq_linear_revmap(mpic->domain, i);
+		unsigned int virq = irq_find_mapping(mpic->domain, i);
 		struct irq_data *d;
 
 		if (!virq || !irq_percpu_is_enabled(virq))
@@ -740,7 +740,7 @@ static void mpic_resume(void)
 
 	/* Re-enable interrupts */
 	for (irq_hw_number_t i = 0; i < mpic->domain->hwirq_max; i++) {
-		unsigned int virq = irq_linear_revmap(mpic->domain, i);
+		unsigned int virq = irq_find_mapping(mpic->domain, i);
 		struct irq_data *d;
 
 		if (!virq)
-- 
2.49.0



From angelogioacchino.delregno at collabora.com  Wed Mar 19 02:34:56 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 19 Mar 2025 10:34:56 +0100
Subject: [PATCH 4/4] arm64: dts: mediatek: mt8390-genio-common: Add
 firmware-name for scp0
In-Reply-To: <20250318-scp-dual-core-mt8390-v1-4-8733e192cc73@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-4-8733e192cc73@collabora.com>
Message-ID: <5bbf7b0d-245b-4f1d-a712-1d81709e35d2@collabora.com>

Il 18/03/25 23:22, N?colas F. R. A. Prado ha scritto:
> Add the firmware-name property for SCP core0 so the firmware can be
> loaded from its canonical location in the linux-firmware repository.
> 
> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From daniel.baluta at nxp.com  Wed Mar 19 02:46:16 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:16 +0200
Subject: [PATCH v6 0/5] Configure imx8mp dsp node for rproc usage
Message-ID: <20250319094621.2353442-1-daniel.baluta@nxp.com>

DSP found in i.MX8MP SOC can be used by multiple frameworks in order to
enable various applications:
        - rproc/rpmsg framework, used to load for example Zephyr samples
        - Sound Open Firmware, used to enable various audio processing
          pipelines.

Current dsp node was configured with SOF in mind but it doesn't work
well with imx8mp-evk dts. SOF controls audio IPs from firmware side
while imx8mp-evk.dts preffers to control audio IPs from Linux side.

So, configure 'dsp' node to be used with rproc scenario and later will
add a separate dts or an overlay to configure the node for SOF.

This patch series configures and enables dsp node to be used with rproc.

Changes since v5:
       - do not enable mu2 node by default
       - fix dt_bindings errors

Changes since v4:
(https://lore.kernel.org/linux-arm-kernel/Z6zGLn3B6SVXhTV1 at lizhi-Precision-Tower-5810/T/)                                                                                               
       - after comments received on v4, we implemented the run/stall
         bits using reset controller API (changes merged ->
https://patchwork.kernel.org/project/linux-arm-kernel/cover/20250311085812.1296243-1-daniel.baluta at nxp.com/)
        - drop patches related to DSP run/stall/reset via syscon
       - picked up patch related to using run_stall via reset
         controller API.

Daniel Baluta (5):
  arm64: dts: imx8mp: Use resets property
  arm64: dts: imx8mp: Add mu2 root clock
  arm64: dts: imx8mp: Configure dsp node for rproc usage
  arm64: dts: imx8mp: Add DSP clocks
  arm64: dts: Add dsp rproc related mem regions

 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 14 +++++++++++++
 arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 22 +++++++++++++-------
 2 files changed, 29 insertions(+), 7 deletions(-)

-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar 19 02:46:17 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:17 +0200
Subject: [PATCH v6 1/5] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250319094621.2353442-1-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
Message-ID: <20250319094621.2353442-2-daniel.baluta@nxp.com>

Add resets property to dsp node in order to be able to control the dsp
run/stall bit from audio block control.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index ce6793b2d57e..3b725fe442d0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/imx8mp-clock.h>
 #include <dt-bindings/power/imx8mp-power.h>
 #include <dt-bindings/reset/imx8mp-reset.h>
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interconnect/fsl,imx8mp.h>
@@ -2422,6 +2423,8 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+			reset-names = "runstall";
 			status = "disabled";
 		};
 	};
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar 19 02:46:18 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:18 +0200
Subject: [PATCH v6 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <20250319094621.2353442-1-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
Message-ID: <20250319094621.2353442-3-daniel.baluta@nxp.com>

Enable MU2 node and add mu2 root clock.
MU2 is used to communicate with DSP core.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 4 ++++
 arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 1 +
 2 files changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index c26954e5a605..d2fdb420f2d3 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -690,6 +690,10 @@ dsi_out: endpoint {
 	};
 };
 
+&mu2 {
+	status = "okay";
+};
+
 &pcie_phy {
 	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
 	clocks = <&pcie0_refclk>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 3b725fe442d0..deb98f03180a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -1254,6 +1254,7 @@ mu2: mailbox at 30e60000 {
 				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
 				#mbox-cells = <2>;
 				status = "disabled";
+				clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_MU2_ROOT>;
 			};
 
 			i2c5: i2c at 30ad0000 {
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar 19 02:46:19 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:19 +0200
Subject: [PATCH v6 3/5] arm64: dts: imx8mp: Configure dsp node for rproc usage
In-Reply-To: <20250319094621.2353442-1-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
Message-ID: <20250319094621.2353442-4-daniel.baluta@nxp.com>

DSP can be used with various frameworks (e.g audio firmware, rproc).
Currently 'dsp' configuration is intended for audio firmware but it
doesn't work well with board level DTs (e.g imx8mp-evk) because
board level DT enables audio related IPs (e.g SAI) while audio firmware
needs this IPs disabled (because firmware will configure them).

So, configure 'dsp' node to be used with rproc. This way users will be
able to use board DT to use the DSP as long as they don't clash with
Audio IP configurations.

More comples usage of 'dsp' node (e.g by audio firmware) will need to
create a separate dts file (or an overlay).

This change follows the approach taken for other i.MX8 boards
in commit 391a319c81f6d7 ("arm64: dts: imx8-ss-audio: configure dsp node
for rproc usage")

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index deb98f03180a..5f9421316ecc 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -281,7 +281,7 @@ reserved-memory {
 		ranges;
 
 		dsp_reserved: dsp at 92400000 {
-			reg = <0 0x92400000 0 0x2000000>;
+			reg = <0 0x92400000 0 0x1000000>;
 			no-map;
 			status = "disabled";
 		};
@@ -2417,13 +2417,12 @@ usb_dwc3_1: usb at 38200000 {
 		};
 
 		dsp: dsp at 3b6e8000 {
-			compatible = "fsl,imx8mp-dsp";
+			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
-			mbox-names = "txdb0", "txdb1",
-				"rxdb0", "rxdb1";
-			mboxes = <&mu2 2 0>, <&mu2 2 1>,
-				<&mu2 3 0>, <&mu2 3 1>;
-			memory-region = <&dsp_reserved>;
+			power-domains = <&pgc_audio>;
+			mbox-names = "tx", "rx", "rxdb";
+			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
+			firmware-name = "imx/dsp/hifi4.bin";
 			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
 			reset-names = "runstall";
 			status = "disabled";
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar 19 02:46:20 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:20 +0200
Subject: [PATCH v6 4/5] arm64: dts: imx8mp: Add DSP clocks
In-Reply-To: <20250319094621.2353442-1-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
Message-ID: <20250319094621.2353442-5-daniel.baluta@nxp.com>

DSP core needs ocram, core and debug clocks.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 5f9421316ecc..5e5cbad9a98a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -2419,6 +2419,11 @@ usb_dwc3_1: usb at 38200000 {
 		dsp: dsp at 3b6e8000 {
 			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
+			clocks = <&audio_blk_ctrl  IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_OCRAMA_IPG>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSPDBG_ROOT>;
+			clock-names = "ipg", "ocram", "core", "debug";
 			power-domains = <&pgc_audio>;
 			mbox-names = "tx", "rx", "rxdb";
 			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
-- 
2.43.0



From daniel.baluta at nxp.com  Wed Mar 19 02:46:21 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Wed, 19 Mar 2025 11:46:21 +0200
Subject: [PATCH v6 5/5] arm64: dts: Add dsp rproc related mem regions
In-Reply-To: <20250319094621.2353442-1-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
Message-ID: <20250319094621.2353442-6-daniel.baluta@nxp.com>

With imx8mp-evk board we are now configuring 'dsp' node for rproc usage,
so add rproc specific memory regions.

Also, enable dsp node because it is ready to be used.

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index d2fdb420f2d3..9ab3ee93a35b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -309,6 +309,16 @@ &aud2htx {
 	status = "okay";
 };
 
+&dsp_reserved {
+	status = "okay";
+};
+
+&dsp {
+	memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
+			<&dsp_vdev0vring1>, <&dsp_reserved>;
+	status = "okay";
+};
+
 &eqos {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_eqos>;
-- 
2.43.0



From maz at kernel.org  Wed Mar 19 02:47:42 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 19 Mar 2025 09:47:42 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
Message-ID: <86plidmjwh.wl-maz@kernel.org>

On Wed, 19 Mar 2025 08:37:29 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/19 16:34, Oliver Upton wrote:
> > Hi Akihiko,
> > 
> > On Wed, Mar 19, 2025 at 03:33:46PM +0900, Akihiko Odaki wrote:
> >> Problem
> >> -------
> >> 
> >> arch/arm64/kvm/pmu-emul.c used to have a comment saying the follows:
> >>> The observant among you will notice that the supported_cpus
> >>> mask does not get updated for the default PMU even though it
> >>> is quite possible the selected instance supports only a
> >>> subset of cores in the system. This is intentional, and
> >>> upholds the preexisting behavior on heterogeneous systems
> >>> where vCPUs can be scheduled on any core but the guest
> >>> counters could stop working.
> >> 
> >> Despite the reference manual says counters may not continuously
> >> incrementing, Windows is not robust enough to handle stopped PMCCNTR_EL0
> >> and crashes with a division-by-zero error and it also crashes when the
> >> PMU is not present.
> >> 
> >> To avoid such a problem, the userspace should pin the vCPU threads to
> >> pCPUs supported by one host PMU when initializing the vCPUs or specify
> >> the host PMU to use with KVM_ARM_VCPU_PMU_V3_SET_PMU after the
> >> initialization. However, QEMU/libvirt can pin vCPU threads only after the
> >> vCPUs are initialized. It also limits the pCPUs the guest can use even
> >> for VMMs that support proper pinning.
> >> 
> >> Solution
> >> --------
> >> 
> >> Ideally, Windows should fix the division-by-zero error and QEMU/libvirt
> >> should support pinning better, but neither of them are going to happen
> >> anytime soon.
> >> 
> >> To allow running Windows on QEMU/libvirt or with heterogeneous cores,
> >> combine all host PMUs necessary to cover the cores vCPUs can run and
> >> keep PMCCNTR_EL0 working.
> > > I'm extremely uneasy about making this a generalized solution. PMUs are
> > deeply tied to the microarchitecture of a particular implementation, and
> > that isn't something we can abstract away from the guest in KVM.
> > 
> > For example, you could have an event ID that counts on only a subset of
> > cores, or better yet an event that counts something completely different
> > depending on where a vCPU lands.> > I do appreciate the issue that you're trying to solve.
> > 
> > The good news though is that the fixed PMU cycle counter is the only
> > thing guaranteed to be present in any PMUv3 implementation. Since
> > that's the only counter Windows actually needs, perhaps we could
> > special-case this in KVM.
> > 
> > I have the following (completely untested) patch, do you want to give it
> > a try? There's still going to be observable differences between PMUs
> > (e.g. CPU frequency) but at least it should get things booting.
> 
> I don't think it will work, unfortunately. perf_init_event() binds a
> perf event to a particular PMU so the event will stop working when the
> thread migrates away.
> 
> It should also be the reason why the perf program creates an event for
> each PMU. tools/perf/Documentation/intel-hybrid.txt has more
> descriptions.

But perf on non-Intel behaves pretty differently. ARM PMUs behaves
pretty differently, because there is no guarantee of homogeneous
events.

> 
> Allowing to enable more than one counter and/or an event type other
> than the cycle counter is not the goal. Enabling another event type
> may result in a garbage value, but I don't think it's worse than the
> current situation where the count stays zero; please tell me if I miss
> something.
> 
> There is still room for improvement. Returning a garbage value may not
> be worse than returning zero, but counters and event types not
> supported by some cores shouldn't be advertised as available in the
> first place. More concretely:
> 
> - The vCPU should be limited to run only on cores covered by PMUs when
> KVM_ARM_VCPU_PMU_V3 is set.

That's userspace's job. Bind to the desired PMU, and run. KVM will
actively prevent you from running on the wrong CPU.

> - PMCR_EL0.N advertised to the guest should be the minimum of ones of
> host PMUs.

How do you find out? CPUs can be hot-plugged on long after a VM has
started, bringing in a new PMU, with a different number of counters.

> - PMCEID0_EL0 and PMCEID1_EL0 advertised to the guest should be the
> result of the AND operations of ones of host PMUs.

Same problem.

> 
> Special-casing the cycle counter may make sense if we are going to fix
> the advertised values of PMCR_EL0.N, PMCEID0_EL0, and
> PMCEID1_EL0. PMCR_EL0.N as we can simply return zero for these
> registers. We can also prevent enabling a counter that returns zero or
> a garbage value.
>
> Do you think it's worth fixing these registers? If so, I'll do that by
> special-casing the cycle counter.

I think this is really going in the wrong direction.

The whole design of the PMU emulation is that we expose a single,
architecturally correct PMU implementation. This is clearly
documented.

Furthermore, userspace is being given all the relevant information to
place vcpus on the correct physical CPUs. Why should we add this sort
of hack in the kernel, creating a new userspace ABI that we will have
to support forever, when usespace can do the correct thing right now?

Worse case, this is just a 'taskset' away, and everything will work.

Frankly, I'm not prepared to add more hacks to KVM for the sake of the
combination of broken userspace and broken guest.

	M.

-- 
Without deviation from the norm, progress is not possible.


From khalasa at piap.pl  Wed Mar 19 02:51:45 2025
From: khalasa at piap.pl (=?utf-8?Q?Krzysztof_Ha=C5=82asa?=)
Date: Wed, 19 Mar 2025 10:51:45 +0100
Subject: ARM64 GICv3 IRQ handling on i.MX8MP
Message-ID: <m3y0x1e4b2.fsf@t19.piap.pl>

Hi,

I'm looking at the i.MX8MP I2C transfers to an image sensor (Sony IMX290
and 462) and I find the following interesting. I wonder about the time
spent before the IRQ handler is called. This is mostly mainline v6.13
kernel (not any of the NXP branches).

The i.MX8MP uses drivers/i2c/busses/i2c-imx.c driver:

request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx);

As I can see, this means i2c_imx_isr() will be called by el1h_64_irq()
(constructed with the entry_handler macro). el1h_64_irq() is the
ultimate hardware interrupt:

Call trace:
 i2c_imx_isr
 __handle_irq_event_percpu
 handle_irq_event
 handle_fasteoi_irq
 generic_handle_domain_irq
 gic_handle_irq
 call_on_irq_stack
 do_interrupt_handler
 el1_interrupt
 el1h_64_irq_handler
 el1h_64_irq
 cpuidle_enter_state

Now I put some debugging GPIO outputs (very short) in both i2c_imx_isr()
and el1h_64_irq_handler() and this is what I'm getting:

- the CPU gets from el1h_64_irq_handler() to i2c_imx_isr() in less than
  20 us (sometimes < 3 us).

- but, it usually takes like 350 us to get from the end of I2C byte
  transfer to the actual el1h_64_irq_handler(). This is the case when
  the CPU is only slightly loaded.

- sometimes el1h_64_irq_handler() is called within 2 us after the
  end of transfer. This appears to be much more frequent when I put
  4 busy shell loops on the CPU.

- especially with the busy loops, the I2C IRQs appear to work in some
  sort of polled mode as well - the el1h_64_irq_handler() isn't called
  before i2c_imx_isr(). This is fast, though - ca. 1 us after the end
  of transfer.

Why do the times between the hardware event and the actual call of
el1h_64_irq_handler() vary so much? Is this some sort of power saving
issue? Maybe I can prevent it when e.g. the I2C xfer is ongoing?

BTW it appears the I2C transfer times are much better now (in comparison
with the old 5.15.71 Freescale/NXP branch), most probably thanks to a
recent patch by Stefan Eichenberger (5f5c2d4579ca683 "i2c: imx: prevent
rescheduling in non dma mode"). Still, I2C is (in this case) 400 kHz (or
so) and the IRQ delays make it much slower.

Could that be caused by the ATF/TEE?

Obviously, the "polled" mode isn't a problem - only the 350 us delay is.
-- 
Krzysztof "Chris" Ha?asa

Sie? Badawcza ?ukasiewicz
Przemys?owy Instytut Automatyki i Pomiar?w PIAP
Al. Jerozolimskie 202, 02-486 Warszawa


From sudeep.holla at arm.com  Wed Mar 19 02:54:12 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 19 Mar 2025 09:54:12 +0000
Subject: [PATCH v3 0/7] firmware: scmi/imx: Add i.MX95 LMM/CPU Protocol
In-Reply-To: <20250318082804.GA1326@nxa18884-linux>
References: <20250303-imx-lmm-cpu-v3-0-7695f6f61cfc@nxp.com>
 <20250318082804.GA1326@nxa18884-linux>
Message-ID: <Z9qURBnqtvbNoZ7K@bogus>

On Tue, Mar 18, 2025 at 04:28:04PM +0800, Peng Fan wrote:
> Hi Sudeep, Cristian
> 
> On Mon, Mar 03, 2025 at 10:53:21AM +0800, Peng Fan (OSS) wrote:
> >i.MX95 System Manager(SM) implements Logical Machine Management(LMM) and
> >CPU protocol to manage Logical Machine(LM) and CPUs(eg, M7).
> 
> Any comments?
> I am thinking to address comments and post v4 after 6.15 merge window close.
> 

Sure I will take a look later this week or next week.

-- 
Regards,
Sudeep


From manivannan.sadhasivam at linaro.org  Wed Mar 19 02:55:11 2025
From: manivannan.sadhasivam at linaro.org (manivannan.sadhasivam at linaro.org)
Date: Wed, 19 Mar 2025 15:25:11 +0530
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <Z9qO1f5MgNcwO5A4@nchen-desktop>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <Z9pffxeXHVOsoi4O@nchen-desktop>
 <20250319062534.ollh3s5t7znf5zqs@uda0492258>
 <Z9qO1f5MgNcwO5A4@nchen-desktop>
Message-ID: <20250319095511.hf3y2c6vbbnm3ien@thinkpad>

On Wed, Mar 19, 2025 at 05:31:01PM +0800, Peter Chen wrote:
> On 25-03-19 14:25:34, Siddharth Vadapalli wrote:
> > > >
> > > > Hello,
> > > >
> > > > This series enables support to build the PCIe Cadence Controller drivers
> > > > and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
> > > > Modules. The motivation for this series is that PCIe is not a necessity
> > > > for booting the SoC, due to which it doesn't have to be a built-in
> > > > module. Additionally, the defconfig doesn't enable the PCIe Cadence
> > > > Controller drivers and the PCI J721E driver, due to which PCIe is not
> > > > supported by default. Enabling the configs as of now (i.e. without this
> > > > series) will result in built-in drivers i.e. a bloated Linux Image for
> > > > everyone who doesn't have the PCIe Controller.
> > >
> > > If the user doesn't enable PCIe controller device through DTS/ACPI,
> > > that's doesn't matter.
> > 
> > The Linux Image for arm64 systems built using:
> > arch/arm64/configs/defconfig
> > will not have support for the Cadence PCIe Controller and the PCIe J721e
> > driver, because these configs aren't enabled.
> > 
> > >
> > > > @@ -209,6 +209,12 @@ CONFIG_NFC=m
> > > >  CONFIG_NFC_NCI=m
> > > >  CONFIG_NFC_S3FWRN5_I2C=m
> > > >  CONFIG_PCI=y
> > > > +CONFIG_PCI_J721E=m
> > > > +CONFIG_PCI_J721E_HOST=m
> > > > +CONFIG_PCI_J721E_EP=m
> > > > +CONFIG_PCIE_CADENCE=m
> > > > +CONFIG_PCIE_CADENCE_HOST=m
> > > > +CONFIG_PCIE_CADENCE_EP=m
> > >
> > > The common Cadence configuration will be select if the glue layer's
> > > configuration is select according to Kconfig.
> > >
> > > Please do not set common configuration as module, some user may need
> > > it as build-in like dw's. Considering the situation, the rootfs is at
> > > NVMe.
> > 
> > The common configuration at the moment is "DISABLED" i.e. no support for
> > the Cadence Controller at all. Which "user" are you referring to? This
> > series was introduced since having the drivers built-in was pushed back at:
> 
> We are using Cadence controller, and prepare upstream radxa-o6 board
> whose rootfs is at PCIe NVMe.
> 

It doesn't matter. Only criteria AFAIK to build the driver as built-in in
defconfig is that it should be a depedency for console. For some time, storage
was also a dependency, but for sure PCIe is not.

Moreover, CONFIG_BLK_DEV_NVME is built as a module in ARM64 defconfig. So it
doesn't matter if you build PCIe controller driver as a built-in or not. You
need to load the NVMe driver somehow.

So please use initramfs.

> You could build driver as module for TI glue layer, but don't force
> other vendors using module as well, see dwc as an example please.
> 

DWC is a bad example here. Only reason the DWC drivers are not loadable is due
to the in-built MSI controller implementation as irqchip. People tend to build
the irqchip controllers as always built-in for some known issues. Even then some
driver developers prefer to built them as loadable module but suppress unbind to
avoid rmmoding the module.

- Mani

-- 
????????? ????????


From alexander.stein at ew.tq-group.com  Wed Mar 19 02:59:28 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Wed, 19 Mar 2025 10:59:28 +0100
Subject: [PATCH v6 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <20250319094621.2353442-3-daniel.baluta@nxp.com>
References: <20250319094621.2353442-1-daniel.baluta@nxp.com>
 <20250319094621.2353442-3-daniel.baluta@nxp.com>
Message-ID: <4999695.31r3eYUQgx@steina-w>

Hi,

Am Mittwoch, 19. M?rz 2025, 10:46:18 CET schrieb Daniel Baluta:
> Enable MU2 node and add mu2 root clock.
> MU2 is used to communicate with DSP core.
> 
> Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 4 ++++
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 1 +
>  2 files changed, 5 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> index c26954e5a605..d2fdb420f2d3 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> @@ -690,6 +690,10 @@ dsi_out: endpoint {
>  	};
>  };
>  
> +&mu2 {
> +	status = "okay";
> +};
> +

I think this is supposed to be part of patch 5.

>  &pcie_phy {
>  	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
>  	clocks = <&pcie0_refclk>;
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> index 3b725fe442d0..deb98f03180a 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> @@ -1254,6 +1254,7 @@ mu2: mailbox at 30e60000 {
>  				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
>  				#mbox-cells = <2>;
>  				status = "disabled";
> +				clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_MU2_ROOT>;

Please keep status as the last property.

Best regards
Alexander

>  			};
>  
>  			i2c5: i2c at 30ad0000 {
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From khalasa at piap.pl  Wed Mar 19 03:06:30 2025
From: khalasa at piap.pl (=?utf-8?Q?Krzysztof_Ha=C5=82asa?=)
Date: Wed, 19 Mar 2025 11:06:30 +0100
Subject: ARM64 GICv3 IRQ handling on i.MX8MP
In-Reply-To: <m3y0x1e4b2.fsf@t19.piap.pl> ("Krzysztof =?utf-8?Q?Ha=C5=82as?=
 =?utf-8?Q?a=22's?= message of
	"Wed, 19 Mar 2025 10:51:45 +0100")
References: <m3y0x1e4b2.fsf@t19.piap.pl>
Message-ID: <m3tt7pe3mh.fsf@t19.piap.pl>

Me:

> - especially with the busy loops, the I2C IRQs appear to work in some
>   sort of polled mode as well - the el1h_64_irq_handler() isn't called
>   before i2c_imx_isr(). This is fast, though - ca. 1 us after the end
>   of transfer.

It seems this is actually called by el0t_64_irq(), not a polling.
-- 
Krzysztof "Chris" Ha?asa

Sie? Badawcza ?ukasiewicz
Przemys?owy Instytut Automatyki i Pomiar?w PIAP
Al. Jerozolimskie 202, 02-486 Warszawa


From jiebing.chen at amlogic.com  Wed Mar 19 03:09:04 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Wed, 19 Mar 2025 18:09:04 +0800
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
 <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>
Message-ID: <9ae73d75-9c59-4255-8924-b456c86cbc01@amlogic.com>


? 2025/3/19 16:22, Krzysztof Kozlowski ??:
> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On Wed, Mar 19, 2025 at 03:04:45PM +0800, jiebing chen wrote:
>> Add clock IDs for the mclk pads found on s4 SoCs
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++
> This belongs to the binding patch, usually.
>
> Anyway - do not ask us to do the work twice.
>
> <form letter>
> This is a friendly reminder during the review process.
>
> It looks like you received a tag and forgot to add it.
>
> If you do not know the process, here is a short explanation:
> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
> versions of patchset, under or above your Signed-off-by tag, unless
> patch changed significantly (e.g. new properties added to the DT
> bindings). Tag is "received", when provided in a message replied to you
> on the mailing list. Tools like b4 can help here. However, there's no
> need to repost patches *only* to add the tags. The upstream maintainer
> will do that for tags received on the version they apply.
>
> Please read:
> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
>
> If a tag was not added on purpose, please state why and what changed.
> </form letter>

thanks for your remind

> Best regards,
> Krzysztof
>


From dan.carpenter at linaro.org  Wed Mar 19 03:20:10 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Wed, 19 Mar 2025 13:20:10 +0300
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <a64bf821-ea90-4fd9-92ec-13bf7b7a3067@csgroup.eu>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
 <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
 <20250318155946.GC13829@willie-the-truck>
 <a64bf821-ea90-4fd9-92ec-13bf7b7a3067@csgroup.eu>
Message-ID: <fc197abf-e65a-439f-9d35-83f4665519f3@stanley.mountain>

On Wed, Mar 19, 2025 at 09:05:27AM +0100, Christophe Leroy wrote:
> 
> Doesn't sparse and/or checkpatch complain about 0 being used in lieu of NULL
> ?

Sparse does have a "Using plain integer as NULL pointer" warning, yes.

I can't apply this patchset and I haven't been following the conversation
closely (plus I'm pretty stupid as well) so I'm not sure if it will
trigger here...

regards,
dan carpenter



From mark.rutland at arm.com  Wed Mar 19 03:20:11 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 10:20:11 +0000
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <86r02tmldh.wl-maz@kernel.org>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
 <019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>
 <86r02tmldh.wl-maz@kernel.org>
Message-ID: <Z9qaW_H9UFqdc1bI@J2N7QTR9R3>

On Wed, Mar 19, 2025 at 09:15:54AM +0000, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 00:26:14 +0000,
> Gavin Shan <gshan at redhat.com> wrote:
> > On 3/14/25 10:35 AM, Mark Brown wrote:

> > > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > index 4e757a77322c9efc59cdff501745f7c80d452358..1c8e2ad32e8c396fc4b11d5fec2e86728f2829d9 100644
> > > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > @@ -5,6 +5,7 @@
> > >    */
> > >     #include <hyp/adjust_pc.h>
> > > +#include <hyp/switch.h>
> > >     #include <asm/pgtable-types.h>
> > >   #include <asm/kvm_asm.h>
> > > @@ -176,8 +177,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
> > >   		sync_hyp_vcpu(hyp_vcpu);
> > >   		pkvm_put_hyp_vcpu(hyp_vcpu);
> > >   	} else {
> > > +		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
> > > +
> > >   		/* The host is fully trusted, run its vCPU directly. */
> > > -		ret = __kvm_vcpu_run(host_vcpu);
> > > +		fpsimd_lazy_switch_to_guest(vcpu);
> > > +		ret = __kvm_vcpu_run(vcpu);
> > > +		fpsimd_lazy_switch_to_host(vcpu);
> > >   	}
> > >   
> > 
> > @host_vcpu should have been hypervisor's linear mapping address in v6.12. It looks
> > incorrect to assume it's a kernel's linear mapping address and convert it (@host_vcpu)
> > to the hypervisor's linear address agin, if I don't miss anything.
> 
> host_vcpu is passed as a parameter to the hypercall, and is definitely
> a kernel address.
> 
> However, at this stage, we have *already* converted it to a HYP VA:
> 
> https://web.git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/kvm/hyp/nvhe/hyp-main.c?h=linux-6.12.y#n147

That's also the case in v6.13; the earlier conversion was removed in
v6.14-rc1 in commit:

  f7d03fcbf1f48206 ("KVM: arm64: Introduce __pkvm_vcpu_{load,put}()")

... where the code in the 'else' block changed from:

|	ret = __kvm_vcpu_run(host_vcpu);

... to:

	ret = __kvm_vcpu_run(kern_hyp_va(host_vcpu));
|

In the upstream version of this patch, the code here changed from

|	/* The host is fully trusted, run its vCPU directly. */
|	ret = __kvm_vcpu_run(kern_hyp_va(host_vcpu));

... to:

|	struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
|
|	/* The host is fully trusted, run its vCPU directly. */
|	fpsimd_lazy_switch_to_guest(vcpu);
|	ret = __kvm_vcpu_run(vcpu);
|	fpsimd_lazy_switch_to_host(vcpu);

> The result is that this change is turning a perfectly valid HYP VA
> into... something. Odds are that the masking/patching will not mess up
> the address, but this is completely buggy anyway. In general,
> kern_hyp_va() is not an idempotent operation.

IIUC today it *happens* to be idempotent, but as you say that is not
guaranteed to remain the case, and this is definitely a logical bug.

> Thanks for noticing that something was wrong.
> 
> Broonie, can you please look into this?
> 
> Greg, it may be more prudent to unstage this series from 6.12-stable
> until we know for sure this is the only problem.

As above, likewise with the v6.13 version.

I'll go reply there linking to this thread.

Mark.


From akihiko.odaki at daynix.com  Wed Mar 19 03:26:57 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 19:26:57 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86plidmjwh.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
Message-ID: <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>

On 2025/03/19 18:47, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 08:37:29 +0000,
> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>
>> On 2025/03/19 16:34, Oliver Upton wrote:
>>> Hi Akihiko,
>>>
>>> On Wed, Mar 19, 2025 at 03:33:46PM +0900, Akihiko Odaki wrote:
>>>> Problem
>>>> -------
>>>>
>>>> arch/arm64/kvm/pmu-emul.c used to have a comment saying the follows:
>>>>> The observant among you will notice that the supported_cpus
>>>>> mask does not get updated for the default PMU even though it
>>>>> is quite possible the selected instance supports only a
>>>>> subset of cores in the system. This is intentional, and
>>>>> upholds the preexisting behavior on heterogeneous systems
>>>>> where vCPUs can be scheduled on any core but the guest
>>>>> counters could stop working.
>>>>
>>>> Despite the reference manual says counters may not continuously
>>>> incrementing, Windows is not robust enough to handle stopped PMCCNTR_EL0
>>>> and crashes with a division-by-zero error and it also crashes when the
>>>> PMU is not present.
>>>>
>>>> To avoid such a problem, the userspace should pin the vCPU threads to
>>>> pCPUs supported by one host PMU when initializing the vCPUs or specify
>>>> the host PMU to use with KVM_ARM_VCPU_PMU_V3_SET_PMU after the
>>>> initialization. However, QEMU/libvirt can pin vCPU threads only after the
>>>> vCPUs are initialized. It also limits the pCPUs the guest can use even
>>>> for VMMs that support proper pinning.
>>>>
>>>> Solution
>>>> --------
>>>>
>>>> Ideally, Windows should fix the division-by-zero error and QEMU/libvirt
>>>> should support pinning better, but neither of them are going to happen
>>>> anytime soon.
>>>>
>>>> To allow running Windows on QEMU/libvirt or with heterogeneous cores,
>>>> combine all host PMUs necessary to cover the cores vCPUs can run and
>>>> keep PMCCNTR_EL0 working.
>>>> I'm extremely uneasy about making this a generalized solution. PMUs are
>>> deeply tied to the microarchitecture of a particular implementation, and
>>> that isn't something we can abstract away from the guest in KVM.
>>>
>>> For example, you could have an event ID that counts on only a subset of
>>> cores, or better yet an event that counts something completely different
>>> depending on where a vCPU lands.> > I do appreciate the issue that you're trying to solve.
>>>
>>> The good news though is that the fixed PMU cycle counter is the only
>>> thing guaranteed to be present in any PMUv3 implementation. Since
>>> that's the only counter Windows actually needs, perhaps we could
>>> special-case this in KVM.
>>>
>>> I have the following (completely untested) patch, do you want to give it
>>> a try? There's still going to be observable differences between PMUs
>>> (e.g. CPU frequency) but at least it should get things booting.
>>
>> I don't think it will work, unfortunately. perf_init_event() binds a
>> perf event to a particular PMU so the event will stop working when the
>> thread migrates away.
>>
>> It should also be the reason why the perf program creates an event for
>> each PMU. tools/perf/Documentation/intel-hybrid.txt has more
>> descriptions.
> 
> But perf on non-Intel behaves pretty differently. ARM PMUs behaves
> pretty differently, because there is no guarantee of homogeneous
> events.

It works in the same manner in this particular aspect (i.e., "perf stat 
-e cycles -a" creates events for all PMUs).

> 
>>
>> Allowing to enable more than one counter and/or an event type other
>> than the cycle counter is not the goal. Enabling another event type
>> may result in a garbage value, but I don't think it's worse than the
>> current situation where the count stays zero; please tell me if I miss
>> something.
>>
>> There is still room for improvement. Returning a garbage value may not
>> be worse than returning zero, but counters and event types not
>> supported by some cores shouldn't be advertised as available in the
>> first place. More concretely:
>>
>> - The vCPU should be limited to run only on cores covered by PMUs when
>> KVM_ARM_VCPU_PMU_V3 is set.
> 
> That's userspace's job. Bind to the desired PMU, and run. KVM will
> actively prevent you from running on the wrong CPU.
> 
>> - PMCR_EL0.N advertised to the guest should be the minimum of ones of
>> host PMUs.
> 
> How do you find out? CPUs can be hot-plugged on long after a VM has
> started, bringing in a new PMU, with a different number of counters.
> 
>> - PMCEID0_EL0 and PMCEID1_EL0 advertised to the guest should be the
>> result of the AND operations of ones of host PMUs.
> 
> Same problem.

I guess special-casing the cycle counter is the only option if the 
kernel is going to deal with this.

> 
>>
>> Special-casing the cycle counter may make sense if we are going to fix
>> the advertised values of PMCR_EL0.N, PMCEID0_EL0, and
>> PMCEID1_EL0. PMCR_EL0.N as we can simply return zero for these
>> registers. We can also prevent enabling a counter that returns zero or
>> a garbage value.
>>
>> Do you think it's worth fixing these registers? If so, I'll do that by
>> special-casing the cycle counter.
> 
> I think this is really going in the wrong direction.
> 
> The whole design of the PMU emulation is that we expose a single,
> architecturally correct PMU implementation. This is clearly
> documented.
> 
> Furthermore, userspace is being given all the relevant information to
> place vcpus on the correct physical CPUs. Why should we add this sort
> of hack in the kernel, creating a new userspace ABI that we will have
> to support forever, when usespace can do the correct thing right now?
> 
> Worse case, this is just a 'taskset' away, and everything will work.

It's surprisingly difficult to do that with libvirt; of course it is a 
userspace problem though.

> 
> Frankly, I'm not prepared to add more hacks to KVM for the sake of the
> combination of broken userspace and broken guest.

The only counter argument I have in this regard is that some change is 
also needed to expose all CPUs to Windows guest even when the userspace 
does its best. It may result in odd scheduling, but still gives the best 
throughput.

Regards,
Akihiko Odaki

> 
> 	M.
> 



From gshan at redhat.com  Wed Mar 19 03:28:38 2025
From: gshan at redhat.com (Gavin Shan)
Date: Wed, 19 Mar 2025 20:28:38 +1000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <20250318151712.28763-1-linmq006@gmail.com>
References: <20250318151712.28763-1-linmq006@gmail.com>
Message-ID: <28cb8360-7fb0-46f0-b05f-5114f1974cf3@redhat.com>

Hi Miaoqian,

On 3/19/25 1:17 AM, Miaoqian Lin wrote:
> Fix a reference counter leak in psci_dt_init() where of_node_put(np) was
> missing after of_find_matching_node_and_match() when np is unavailable.
> 
> Fixes: bff60792f994 ("arm64: psci: factor invocation code to drivers")
> Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
> ---
>   drivers/firmware/psci/psci.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 

I'm wandering if the fix tag is correct enough because !of_device_is_available(np)
wasn't added by bff60792f994.

> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index a1ebbe9b73b1..38ca190d4a22 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
> @@ -804,8 +804,10 @@ int __init psci_dt_init(void)
>   
>   	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
>   
> -	if (!np || !of_device_is_available(np))
> +	if (!np || !of_device_is_available(np)) {
> +		of_node_put(np);
>   		return -ENODEV;
> +	}

The fix looks good to me. The duplicated of_node_put() can be avoided with
a 'out' tag added, something like below.

	if (!np || !of_device_is_available(np)) {
		ret = -ENODEV;
		goto out;
	}

	:

out:
	of_node_put(np);
	return ret;

>   
>   	init_fn = (psci_initcall_t)matched_np->data;
>   	ret = init_fn(np);

Thanks,
Gavin



From mark.rutland at arm.com  Wed Mar 19 03:29:14 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 10:29:14 +0000
Subject: [PATCH 6.13 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250312-stable-sve-6-13-v1-8-c7ba07a6f4f7@kernel.org>
References: <20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7@kernel.org>
 <20250312-stable-sve-6-13-v1-8-c7ba07a6f4f7@kernel.org>
Message-ID: <Z9qcem7BVeuRd5XD@J2N7QTR9R3>

On Wed, Mar 12, 2025 at 11:49:16PM +0000, Mark Brown wrote:
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 7262983c75fbc18ab44f52753bff1dd9167a68d3..84326765c66087d992a517a19fea94b04c39c994 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -5,6 +5,7 @@
>   */
>  
>  #include <hyp/adjust_pc.h>
> +#include <hyp/switch.h>
>  
>  #include <asm/pgtable-types.h>
>  #include <asm/kvm_asm.h>
> @@ -178,8 +179,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
>  		sync_hyp_vcpu(hyp_vcpu);
>  		pkvm_put_hyp_vcpu(hyp_vcpu);
>  	} else {
> +		struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu);
> +
>  		/* The host is fully trusted, run its vCPU directly. */
> -		ret = __kvm_vcpu_run(host_vcpu);
> +		fpsimd_lazy_switch_to_guest(vcpu);
> +		ret = __kvm_vcpu_run(vcpu);
> +		fpsimd_lazy_switch_to_host(vcpu);
>  	}

As Gavin noted [1] for the v6.12 backport, the addition of kern_hyp_va()
is not correct, since 'host_vcpu' has already been converted to a hyp VA
at this point.

[1] https://lore.kernel.org/linux-arm-kernel/019afc2d-b047-4e33-971c-7debbbaec84d at redhat.com/#t

Mark.


From manivannan.sadhasivam at linaro.org  Wed Mar 19 03:32:17 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Wed, 19 Mar 2025 16:02:17 +0530
Subject: [PATCH 3/4] PCI: cadence-ep: Introduce cdns_pcie_ep_disable
 helper for cleanup
In-Reply-To: <20250318081239.rvbk3rqud7wcj5pj@uda0492258>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-4-s-vadapalli@ti.com>
 <20250318080304.jsmrxqil6pn74nzh@thinkpad>
 <20250318081239.rvbk3rqud7wcj5pj@uda0492258>
Message-ID: <20250319103217.aaoxpzk2baqna5vc@thinkpad>

On Tue, Mar 18, 2025 at 01:42:39PM +0530, Siddharth Vadapalli wrote:
> On Tue, Mar 18, 2025 at 01:33:04PM +0530, Manivannan Sadhasivam wrote:
> 
> Hello Mani,
> 
> > On Fri, Mar 07, 2025 at 04:01:27PM +0530, Siddharth Vadapalli wrote:
> > > Introduce the helper function cdns_pcie_ep_disable() which will undo the
> > > configuration performed by cdns_pcie_ep_setup(). Also, export it for use
> > > by the existing callers of cdns_pcie_ep_setup(), thereby allowing them
> > > to cleanup on their exit path.
> > > 
> > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > > ---
> > >  drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++++++
> > >  drivers/pci/controller/cadence/pcie-cadence.h    |  5 +++++
> > >  2 files changed, 15 insertions(+)
> > > 
> > > diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > index eeb2afdd223e..85bec57fa5d9 100644
> > > --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > @@ -646,6 +646,16 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
> > >  	.get_features	= cdns_pcie_ep_get_features,
> > >  };
> > >  
> > > +void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
> > > +{
> > > +	struct device *dev = ep->pcie.dev;
> > > +	struct pci_epc *epc = to_pci_epc(dev);
> > > +
> > 
> > pci_epc_deinit_notify()
> 
> I had initially planned to add this, but I noticed that it is not
> invoked by dw_pcie_ep_deinit() within
> drivers/pci/controller/dwc/pcie-designware-ep.c
> Since cdns_pcie_ep_disable() is similar to dw_pcie_ep_deinit(), I
> decided to drop it. Current callers of pci_epc_deinit_notify() are:
> drivers/pci/controller/dwc/pcie-qcom-ep.c
> drivers/pci/controller/dwc/pcie-tegra194.c
> while there are many more users of dw_pcie_ep_deinit() that don't invoke
> pci_epc_deinit_notify().
> 
> While I don't intend to justify dropping pci_epc_deinit_notify() in the
> cleanup path, I wanted to check if this should be added to
> dw_pcie_ep_deinit() as well. Or is it the case that dw_pcie_ep_deinit()
> is different from cdns_pcie_ep_disable()? Please let me know.
> 

Reason why it was not added to dw_pcie_ep_deinit() because, deinit_notify() is
supposed to be called while performing the resource cleanup with active refclk.

Some plaforms (Tegra, Qcom) depend on refclk from host. So if deinit_notify() is
called when there is no refclk, it will crash the endpoint SoC. But since
cadence endpoint platforms seem to generate their own refclk, you can call
deinit_notify() during deinit phase.

That said, I noticed some issues in the DWC cleanup path while checking the code
now. Will submit fixes for them.

- Mani

-- 
????????? ????????


From antonio.borneo at foss.st.com  Wed Mar 19 03:29:10 2025
From: antonio.borneo at foss.st.com (Antonio Borneo)
Date: Wed, 19 Mar 2025 11:29:10 +0100
Subject: [Linux-stm32] [PATCH v2 06/57] irqdomain: irqchip: Switch to
 of_fwnode_handle()
In-Reply-To: <20250319092951.37667-7-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
	 <20250319092951.37667-7-jirislaby@kernel.org>
Message-ID: <45d5baa5a93fec388a75e91653439f7678d000ee.camel@foss.st.com>

On Wed, 2025-03-19 at 10:28 +0100, Jiri Slaby (SUSE) wrote:
> of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
> defined of_fwnode_handle(). The former is in the process of being
> removed, so use the latter instead.
> 

... snip ...

> diff --git a/drivers/irqchip/irq-stm32mp-exti.c b/drivers/irqchip/irq-stm32mp-exti.c
> index cb83d6cc6113..649b84f12efc 100644
> --- a/drivers/irqchip/irq-stm32mp-exti.c
> +++ b/drivers/irqchip/irq-stm32mp-exti.c
> @@ -531,7 +531,7 @@ static int stm32mp_exti_domain_alloc(struct irq_domain *dm,
> ????????????????if (ret)
> ????????????????????????return ret;
> ????????????????/* we only support one parent, so far */
> -???????????????if (of_node_to_fwnode(out_irq.np) != dm->parent->fwnode)
> +???????????????if (of_fwnode_handle(out_irq.np) != dm->parent->fwnode)
> 

For drivers/irqchip/irq-stm32mp-exti.c
Reviewed-by: Antonio Borneo <antonio.borneo at foss.st.com>


From s-vadapalli at ti.com  Wed Mar 19 03:37:35 2025
From: s-vadapalli at ti.com (Siddharth Vadapalli)
Date: Wed, 19 Mar 2025 16:07:35 +0530
Subject: [PATCH 3/4] PCI: cadence-ep: Introduce cdns_pcie_ep_disable
 helper for cleanup
In-Reply-To: <20250319103217.aaoxpzk2baqna5vc@thinkpad>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <20250307103128.3287497-4-s-vadapalli@ti.com>
 <20250318080304.jsmrxqil6pn74nzh@thinkpad>
 <20250318081239.rvbk3rqud7wcj5pj@uda0492258>
 <20250319103217.aaoxpzk2baqna5vc@thinkpad>
Message-ID: <20250319103735.a45aa5trofo2c2fc@uda0492258>

On Wed, Mar 19, 2025 at 04:02:17PM +0530, Manivannan Sadhasivam wrote:
> On Tue, Mar 18, 2025 at 01:42:39PM +0530, Siddharth Vadapalli wrote:
> > On Tue, Mar 18, 2025 at 01:33:04PM +0530, Manivannan Sadhasivam wrote:
> > 
> > Hello Mani,
> > 
> > > On Fri, Mar 07, 2025 at 04:01:27PM +0530, Siddharth Vadapalli wrote:
> > > > Introduce the helper function cdns_pcie_ep_disable() which will undo the
> > > > configuration performed by cdns_pcie_ep_setup(). Also, export it for use
> > > > by the existing callers of cdns_pcie_ep_setup(), thereby allowing them
> > > > to cleanup on their exit path.
> > > > 
> > > > Signed-off-by: Siddharth Vadapalli <s-vadapalli at ti.com>
> > > > ---
> > > >  drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++++++
> > > >  drivers/pci/controller/cadence/pcie-cadence.h    |  5 +++++
> > > >  2 files changed, 15 insertions(+)
> > > > 
> > > > diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > > index eeb2afdd223e..85bec57fa5d9 100644
> > > > --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > > +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > > > @@ -646,6 +646,16 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
> > > >  	.get_features	= cdns_pcie_ep_get_features,
> > > >  };
> > > >  
> > > > +void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
> > > > +{
> > > > +	struct device *dev = ep->pcie.dev;
> > > > +	struct pci_epc *epc = to_pci_epc(dev);
> > > > +
> > > 
> > > pci_epc_deinit_notify()
> > 
> > I had initially planned to add this, but I noticed that it is not
> > invoked by dw_pcie_ep_deinit() within
> > drivers/pci/controller/dwc/pcie-designware-ep.c
> > Since cdns_pcie_ep_disable() is similar to dw_pcie_ep_deinit(), I
> > decided to drop it. Current callers of pci_epc_deinit_notify() are:
> > drivers/pci/controller/dwc/pcie-qcom-ep.c
> > drivers/pci/controller/dwc/pcie-tegra194.c
> > while there are many more users of dw_pcie_ep_deinit() that don't invoke
> > pci_epc_deinit_notify().
> > 
> > While I don't intend to justify dropping pci_epc_deinit_notify() in the
> > cleanup path, I wanted to check if this should be added to
> > dw_pcie_ep_deinit() as well. Or is it the case that dw_pcie_ep_deinit()
> > is different from cdns_pcie_ep_disable()? Please let me know.
> > 
> 
> Reason why it was not added to dw_pcie_ep_deinit() because, deinit_notify() is
> supposed to be called while performing the resource cleanup with active refclk.
> 
> Some plaforms (Tegra, Qcom) depend on refclk from host. So if deinit_notify() is
> called when there is no refclk, it will crash the endpoint SoC. But since
> cadence endpoint platforms seem to generate their own refclk, you can call
> deinit_notify() during deinit phase.

Thank you for the clarification. I will add pci_epc_deinit_notify() to
cdns_pcie_ep_disable() in the v2 series.

Regards,
Siddharth.


From jiebing.chen at amlogic.com  Wed Mar 19 03:38:44 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Wed, 19 Mar 2025 18:38:44 +0800
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
 <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
Message-ID: <9397d6d5-518d-4bd0-a34a-7a5f5e1201f1@amlogic.com>


? 2025/3/19 16:26, Krzysztof Kozlowski ??:
> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On Wed, Mar 19, 2025 at 03:04:49PM +0800, jiebing chen wrote:
>> Add basic audio driver support for the Amlogic S4 based
>> Amlogic AQ222 board. use hifipll pll (1179648000) to
>> support 768k sample rate and 24 bit (s24_le), 24bit sclk
>> is 48fs, use mpll0 (270950400) to support 705.6k sample
>> rate and 32bit, use mpll1 (338688000) to support 705.6k
>> and 24bit.
> Please wrap commit message according to Linux coding style / submission
> process (neither too early nor over the limit):
> https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
ok, thanaks
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ...
>
>> +
>> +             dai-link-12 {
>> +                     sound-dai = <&toacodec TOACODEC_OUT>;
>> +
>> +                     codec {
>> +                             sound-dai = <&acodec>;
>> +                     };
>> +             };
>> +     };
>> +
> Do not add stray blank lines.
>
>>   };
>>
>>   &pwm_ef {
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>> @@ -11,7 +11,11 @@
>>   #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
>>   #include <dt-bindings/power/meson-s4-power.h>
>>   #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
>> -
> Why?

The following files are included that the audio driver depends on

it is same as sm1 chip

>> +#include <dt-bindings/clock/axg-audio-clkc.h>
>> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
>> +#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
>> +#include <dt-bindings/sound/meson-g12a-toacodec.h>
>> +#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
> Old style was correct.

I didn't understand where you were referring to, I'm guessing that's 
what it was about

the following changes to tdmif_a

old:

clock-names = "mclk", "sclk", "lrclk";

new:
clock-names = "sclk", "lrclk","mclk";
it fix warning

it showhttp://devicetree.org/schemas/sound/amlogic,axg-tdm-iface.yaml#
examples:
   - |
     #include <dt-bindings/clock/axg-audio-clkc.h>

     audio-controller {
         compatible = "amlogic,axg-tdm-iface";
         #sound-dai-cells = <0>;
         clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
                  <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
                  <&clkc_audio AUD_CLKID_MST_A_MCLK>;
         clock-names = "sclk", "lrclk", "mclk";
     };

>
>>   / {
>>        cpus {
>>                #address-cells = <2>;
>> @@ -46,6 +50,36 @@ cpu3: cpu at 3 {
>>                };
>>        };
>>
>> +     tdmif_a: audio-controller-0 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_A";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_A_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>> +     tdmif_b: audio-controller-1 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_B";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_B_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>> +     tdmif_c: audio-controller-2 {
>> +             compatible = "amlogic,axg-tdm-iface";
>> +             #sound-dai-cells = <0>;
>> +             sound-name-prefix = "TDM_C";
>> +             clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
>> +                      <&clkc_audio AUD_CLKID_MST_C_MCLK>;
>> +             clock-names = "sclk", "lrclk","mclk";
>> +     };
>> +
>>        timer {
>>                compatible = "arm,armv8-timer";
>>                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
>> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>>                        #address-cells = <2>;
>>                        #size-cells = <2>;
>>                        ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>> -
> Why? What is happening in this patch - why are you changing so many
> other pieces?
>
>>                        clkc_periphs: clock-controller at 0 {
>>                                compatible = "amlogic,s4-peripherals-clkc";
>>                                reg = <0x0 0x0 0x0 0x49c>;
>> @@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
>>                                #clock-cells = <1>;
>>                        };
>>
>> +                     acodec: audio-controller at 1a000 {
>> +                             compatible = "amlogic,t9015";
>> +                             reg = <0x0 0x1A000 0x0 0x14>;
>> +                             #sound-dai-cells = <0>;
>> +                             sound-name-prefix = "ACODEC";
>> +                             clocks = <&clkc_periphs CLKID_ACODEC>;
>> +                             clock-names = "pclk";
>> +                             resets = <&reset RESET_ACODEC>;
>> +                             AVDD-supply = <&vddio_ao1v8>;
>> +                     };
>> +
>>                        watchdog at 2100 {
>>                                compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
>>                                reg = <0x0 0x2100 0x0 0x10>;
>> @@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
>>                };
>>        };
>>   };
>> +
>> +&apb4 {
>> +     audio: bus at 330000 {
>> +             compatible = "simple-bus";
>> +             reg = <0x0 0x330000 0x0 0x1000>;
> That's not a simple bus in such case.

these code base on old dts like sm1/g12a, we didn't easily change any of 
the relevant properties

To be consistent with the previous one

>
> NAK
>
>
> Best regards,
> Krzysztof
>


From matthias.schiffer at ew.tq-group.com  Wed Mar 19 03:45:51 2025
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Wed, 19 Mar 2025 11:45:51 +0100
Subject: [PATCH v2 5/5] arm64: dts: ti: Add TQ-Systems TQMa62xx SoM and
 MBa62xx carrier board Device Trees
In-Reply-To: <2953e10c-0a57-4d49-b831-3864a07eefd5@lunn.ch>
References: <cover.1733737487.git.matthias.schiffer@ew.tq-group.com>
	 <95ff66ca2c89f69d893c2ce9eed9a0c677633c7b.1733737487.git.matthias.schiffer@ew.tq-group.com>
	 <a9c5cfda-e3e3-436a-8d05-b2f096157cfe@lunn.ch>
	 <c902a56cf34838f60cee67624bb923e91d74e9e0.camel@ew.tq-group.com>
	 <d25b1447-c28b-4998-b238-92672434dc28@lunn.ch>
	 <e16076d16349e929af82fa987a658bff1d9804c4.camel@ew.tq-group.com>
	 <a2a2f201-73a4-4a99-baef-0d593a88c872@lunn.ch>
	 <309052f3f69950fe43390505cc7254aee8c8f5c6.camel@ew.tq-group.com>
	 <2953e10c-0a57-4d49-b831-3864a07eefd5@lunn.ch>
Message-ID: <e6ee878f655c31473bca54e4187d9006a19158b1.camel@ew.tq-group.com>

On Tue, 2024-12-10 at 20:54 +0100, Andrew Lunn wrote:
> 
> On Tue, Dec 10, 2024 at 10:56:41AM +0100, Matthias Schiffer wrote:
> > On Mon, 2024-12-09 at 17:14 +0100, Andrew Lunn wrote:
> > > 
> > > > Not our board, but the AM62 SoC. From the datasheet:
> > > > 
> > > > "TXC is delayed internally before being driven to the RGMII[x]_TXC pin. This
> > > > internal delay is always enabled." So enabling the TX delay on the PHY side
> > > > would result in a double delay.
> > > 
> > > phy-mode describes the board. If the board does not have extra long
> > > clock lines, phy-mode should be rgmii-id.
> > > 
> > > The fact the MAC is doing something which no other MAC does should be
> > > hidden away in the MAC driver, as much as possible.
> > 
> > Isn't it kind of a philosophical question whether a delay added by the SoC
> > integration is part of the MAC or not? One could also argue that the MAC IP core
> > is always the same, with some SoCs adding the delay and others not. (I don't
> > know if there are actually SoCs with the same IP core that don't add a delay;
> > I'm just not a big fan of hiding details in the driver that could easily be
> > described by the Device Tree, thus making the driver more generic)
> 
> It is more about, what does phy-mode = "rgmii"; mean? It means the
> board provides the delay via extra long clock lines. Except for when
> some random MAC driver has a completely different meaning, it is not
> documented it means something else, you have to read the sources and
> the mailing lists, to find out what this particularly MAC driver is
> doing for phy-mode = "rgmii".
> 
> Do we really want that. Or should we define that phy-mode = "rgmii"
> means the PCB provides the delay. End of story, no exceptions. And
> that "rgmii-id" means the MAC/PHY pair need to provide the delay? End
> of story, no exceptions.


Hi Andrew,

I've just thought about this issue again. As mentioned, a number of MAC
drivers(*) implement what is described here:

https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/ethernet-controller.yaml?h=v6.13#n77


That is, the delay is either added by the PHY or the MAC; having a delay on the
PCB is simply not supported. Fixing MAC drivers to interpret the values without
"id" to mean that there is a delay on the PCB will break existing Device Trees,
so that's no good.

As a first step, I'd update the docs to describe the intended behavior, but
mention that some drivers implement it wrong. The question is how to deal with
the wrong behavior going forward. I see the following options, but none spark
joy for me...

- Keep current driver behavior forever where fixing it would break existing
  Device Trees
- Deprecate all existing "rgmii*" values because of their inconsistent
  implementation, come up with new ones. Seems like a huge pain to add support
  for in all MAC drivers and other code that deals with PHY modes...
- Introduce an additional DTS flag next to phy-mode to express that the
  phy-mode is supposed to be interpreted correctly

Do you have any suggestions?

Best,
Matthias



(*) At a glance, at least the following MAC drivers appear to configure a delay,
making it impossible to support delays on the PCB with the current
implementation:
- renesas/ravb_main.c
- stmicro/stmmac/dwmac-* (some variants)
- ti/cpsw-phy-sel.c (incomplete; does not distinguish between RX and TX delays) 
- Some other MAC drivers check for specific PHY_INTERFACE_MODE_RGMII* values,
  which also doesn't seem completely correct



-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
https://www.tq-group.com/


From sudeep.holla at arm.com  Wed Mar 19 03:46:49 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 19 Mar 2025 10:46:49 +0000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <28cb8360-7fb0-46f0-b05f-5114f1974cf3@redhat.com>
References: <20250318151712.28763-1-linmq006@gmail.com>
 <28cb8360-7fb0-46f0-b05f-5114f1974cf3@redhat.com>
Message-ID: <Z9qgmTbeLh0cCULw@bogus>

On Wed, Mar 19, 2025 at 08:28:38PM +1000, Gavin Shan wrote:
> Hi Miaoqian,
> 
> On 3/19/25 1:17 AM, Miaoqian Lin wrote:
> > Fix a reference counter leak in psci_dt_init() where of_node_put(np) was
> > missing after of_find_matching_node_and_match() when np is unavailable.
> > 
> > Fixes: bff60792f994 ("arm64: psci: factor invocation code to drivers")
> > Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
> > ---
> >   drivers/firmware/psci/psci.c | 4 +++-
> >   1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> 
> I'm wandering if the fix tag is correct enough because !of_device_is_available(np)
> wasn't added by bff60792f994.
> 
> > diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> > index a1ebbe9b73b1..38ca190d4a22 100644
> > --- a/drivers/firmware/psci/psci.c
> > +++ b/drivers/firmware/psci/psci.c
> > @@ -804,8 +804,10 @@ int __init psci_dt_init(void)
> >   	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
> > -	if (!np || !of_device_is_available(np))
> > +	if (!np || !of_device_is_available(np)) {
> > +		of_node_put(np);
> >   		return -ENODEV;
> > +	}
> 
> The fix looks good to me. The duplicated of_node_put() can be avoided with
> a 'out' tag added, something like below.
> 
> 	if (!np || !of_device_is_available(np)) {
> 		ret = -ENODEV;
> 		goto out;
> 	}
> 
> 	:
> 
> out:
> 	of_node_put(np);
> 	return ret;
> 
> >   	init_fn = (psci_initcall_t)matched_np->data;
> >   	ret = init_fn(np);
> 

Any reason why we can't move to the new scoped usage like below?

-- 
Regards,
Sudeep

-->8

diff --git i/drivers/firmware/psci/psci.c w/drivers/firmware/psci/psci.c
index a1ebbe9b73b1..a4269078b2a2 100644
--- i/drivers/firmware/psci/psci.c
+++ w/drivers/firmware/psci/psci.c
@@ -797,12 +797,11 @@ static const struct of_device_id psci_of_match[] __initconst = {

 int __init psci_dt_init(void)
 {
-       struct device_node *np;
        const struct of_device_id *matched_np;
        psci_initcall_t init_fn;
        int ret;
-
-       np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
+       struct device_node *np __free(device_node) =
+               of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);

        if (!np || !of_device_is_available(np))
                return -ENODEV;
@@ -810,7 +809,6 @@ int __init psci_dt_init(void)
        init_fn = (psci_initcall_t)matched_np->data;
        ret = init_fn(np);

-       of_node_put(np);
        return ret;
 }



From maz at kernel.org  Wed Mar 19 04:07:04 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 19 Mar 2025 11:07:04 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
Message-ID: <86o6xxmg87.wl-maz@kernel.org>

On Wed, 19 Mar 2025 10:26:57 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> >> It should also be the reason why the perf program creates an event for
> >> each PMU. tools/perf/Documentation/intel-hybrid.txt has more
> >> descriptions.
> > 
> > But perf on non-Intel behaves pretty differently. ARM PMUs behaves
> > pretty differently, because there is no guarantee of homogeneous
> > events.
> 
> It works in the same manner in this particular aspect (i.e., "perf
> stat -e cycles -a" creates events for all PMUs).

But it then becomes a system-wide counter, and that's not what KVM
needs to do.

> >> Allowing to enable more than one counter and/or an event type other
> >> than the cycle counter is not the goal. Enabling another event type
> >> may result in a garbage value, but I don't think it's worse than the
> >> current situation where the count stays zero; please tell me if I miss
> >> something.
> >> 
> >> There is still room for improvement. Returning a garbage value may not
> >> be worse than returning zero, but counters and event types not
> >> supported by some cores shouldn't be advertised as available in the
> >> first place. More concretely:
> >> 
> >> - The vCPU should be limited to run only on cores covered by PMUs when
> >> KVM_ARM_VCPU_PMU_V3 is set.
> > 
> > That's userspace's job. Bind to the desired PMU, and run. KVM will
> > actively prevent you from running on the wrong CPU.
> > 
> >> - PMCR_EL0.N advertised to the guest should be the minimum of ones of
> >> host PMUs.
> > 
> > How do you find out? CPUs can be hot-plugged on long after a VM has
> > started, bringing in a new PMU, with a different number of counters.
> > 
> >> - PMCEID0_EL0 and PMCEID1_EL0 advertised to the guest should be the
> >> result of the AND operations of ones of host PMUs.
> > 
> > Same problem.
> 
> I guess special-casing the cycle counter is the only option if the
> kernel is going to deal with this.

Indeed. I think Oliver's idea is the least bad of them all, but man,
this is really ugly.

> >> Special-casing the cycle counter may make sense if we are going to fix
> >> the advertised values of PMCR_EL0.N, PMCEID0_EL0, and
> >> PMCEID1_EL0. PMCR_EL0.N as we can simply return zero for these
> >> registers. We can also prevent enabling a counter that returns zero or
> >> a garbage value.
> >> 
> >> Do you think it's worth fixing these registers? If so, I'll do that by
> >> special-casing the cycle counter.
> > 
> > I think this is really going in the wrong direction.
> > 
> > The whole design of the PMU emulation is that we expose a single,
> > architecturally correct PMU implementation. This is clearly
> > documented.
> > 
> > Furthermore, userspace is being given all the relevant information to
> > place vcpus on the correct physical CPUs. Why should we add this sort
> > of hack in the kernel, creating a new userspace ABI that we will have
> > to support forever, when usespace can do the correct thing right now?
> > 
> > Worse case, this is just a 'taskset' away, and everything will work.
> 
> It's surprisingly difficult to do that with libvirt; of course it is a
> userspace problem though.

Sorry, I must admit I'm completely ignorant of libvirt. I tried it
years ago, and concluded that 95% of what I needed was adequately done
with a shell script...

> > Frankly, I'm not prepared to add more hacks to KVM for the sake of the
> > combination of broken userspace and broken guest.
> 
> The only counter argument I have in this regard is that some change is
> also needed to expose all CPUs to Windows guest even when the
> userspace does its best. It may result in odd scheduling, but still
> gives the best throughput.

But that'd be a new ABI, which again would require buy-in from
userspace.  Maybe there is scope for an all CPUs, cycle-counter only
PMUv3 exposed to the guest, but that cannot be set automatically, as
we would otherwise regress existing setups.

At this stage, and given that you need to change userspace, I'm not
sure what the best course of action is.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From dmitry.baryshkov at oss.qualcomm.com  Wed Mar 19 04:08:40 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Wed, 19 Mar 2025 13:08:40 +0200
Subject: [PATCH v2 5/8] phy: phy-snps-eusb2: make repeater optional
In-Reply-To: <20250223122227.725233-6-ivo.ivanov.ivanov1@gmail.com>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-6-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <sxrae5pmykx6ul2y7uc24fss2kdeezkkom7ev7mavt3fbc6ckv@tghyp3whuxnu>

On Sun, Feb 23, 2025 at 02:22:24PM +0200, Ivaylo Ivanov wrote:
> Some platforms initialize their eUSB2 to USB repeater in the previous
> stage bootloader and leave it in a working state for linux. Make the
> repeater optional in order to allow for reusing that state until
> proper repeater drivers are introduced.

Generally "works as it is setup by the bootloader" is a very invalid
justification. Please don't do that. We should not be depending on the
way the bootlader sets up the devices, unless that _really_ makes sense.

> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  drivers/phy/phy-snps-eusb2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
> index 4e5914a76..dcc69c00a 100644
> --- a/drivers/phy/phy-snps-eusb2.c
> +++ b/drivers/phy/phy-snps-eusb2.c
> @@ -461,7 +461,7 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>  		return dev_err_probe(dev, ret,
>  				     "failed to get regulator supplies\n");
>  
> -	phy->repeater = devm_of_phy_get_by_index(dev, np, 0);
> +	phy->repeater = devm_of_phy_optional_get(dev, np, 0);
>  	if (IS_ERR(phy->repeater))
>  		return dev_err_probe(dev, PTR_ERR(phy->repeater),
>  				     "failed to get repeater\n");
> -- 
> 2.43.0
> 

-- 
With best wishes
Dmitry


From mark.rutland at arm.com  Wed Mar 19 04:12:02 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 11:12:02 +0000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <Z9qgmTbeLh0cCULw@bogus>
References: <20250318151712.28763-1-linmq006@gmail.com>
 <28cb8360-7fb0-46f0-b05f-5114f1974cf3@redhat.com>
 <Z9qgmTbeLh0cCULw@bogus>
Message-ID: <Z9qmglbXw0xILaet@J2N7QTR9R3>

On Wed, Mar 19, 2025 at 10:46:49AM +0000, Sudeep Holla wrote:
> On Wed, Mar 19, 2025 at 08:28:38PM +1000, Gavin Shan wrote:

> Any reason why we can't move to the new scoped usage like below?

> diff --git i/drivers/firmware/psci/psci.c w/drivers/firmware/psci/psci.c
> index a1ebbe9b73b1..a4269078b2a2 100644
> --- i/drivers/firmware/psci/psci.c
> +++ w/drivers/firmware/psci/psci.c
> @@ -797,12 +797,11 @@ static const struct of_device_id psci_of_match[] __initconst = {
> 
>  int __init psci_dt_init(void)
>  {
> -       struct device_node *np;
>         const struct of_device_id *matched_np;
>         psci_initcall_t init_fn;
>         int ret;
> -
> -       np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
> +       struct device_node *np __free(device_node) =
> +               of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
> 
>         if (!np || !of_device_is_available(np))
>                 return -ENODEV;
> @@ -810,7 +809,6 @@ int __init psci_dt_init(void)
>         init_fn = (psci_initcall_t)matched_np->data;
>         ret = init_fn(np);
> 
> -       of_node_put(np);
>         return ret;
>  }

IIUC the bug has existed since before the scoped helpers were
introduced, so for the sake of keeping the backport simple I reckon we
should take Miaoqian Lin's patch as-is, and we can consider moving to
the scoped helpers as a later cleanup.

Mark.


From ryan_chen at aspeedtech.com  Wed Mar 19 04:12:10 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Wed, 19 Mar 2025 11:12:10 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
Message-ID: <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 17/03/2025 10:21, Ryan Chen wrote:
> >> Neither this.
> >>
> >> So it seems you describe already existing and documented I2C, but for
> >> some reason you want second compatible. The problem is that you do
> >> not provide reason from the point of view of bindings.
> >>
> >> To summarize: what your users want - don't care. Start properly
> >> describing hardware and your SoC.
> >
> > OK, for ast2600 i2c controller have two register mode setting.
> > One, I call it is old register setting, that is right now i2c-aspeed.c
> > .compatible = "aspeed,ast2600-i2c-bus", And there have a global register
> that can set i2c controller as new mode register set.
> > That I am going to drive. That I post is all register in new an old register list.
> >
> > For example,
> > Global register [2] = 0 => i2c present as old register set Global
> > register [2] = 1 => i2c present as new register set
> It's the same device though, so the same compatible.

Sorry, it is different design, and it share the same register space.
So that the reason add new compatible "aspeed,ast2600-i2cv2" for this driver.
It is different register layout.


> 
> Best regards,
> Krzysztof

From mark.rutland at arm.com  Wed Mar 19 04:23:02 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 11:23:02 +0000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <20250318151712.28763-1-linmq006@gmail.com>
References: <20250318151712.28763-1-linmq006@gmail.com>
Message-ID: <Z9qpFlBJeLrGuEXq@J2N7QTR9R3>

On Tue, Mar 18, 2025 at 11:17:12PM +0800, Miaoqian Lin wrote:
> Fix a reference counter leak in psci_dt_init() where of_node_put(np) was
> missing after of_find_matching_node_and_match() when np is unavailable.
> 
> Fixes: bff60792f994 ("arm64: psci: factor invocation code to drivers")
> Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>

The fixes tag is wrong. As of commit bff60792f994 the code was:

|       np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
|
|       if (!np)
|               return -ENODEV;

... which was correct.

The bug was introduced later in commit:

  d09a0011ec0d511b ("drivers: psci: Allow PSCI node to be disabled")

... which added the of_device_is_available() check.

Other than that, this looks fine. With the fixes tag corrected:

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> ---
>  drivers/firmware/psci/psci.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index a1ebbe9b73b1..38ca190d4a22 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
> @@ -804,8 +804,10 @@ int __init psci_dt_init(void)
>  
>  	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
>  
> -	if (!np || !of_device_is_available(np))
> +	if (!np || !of_device_is_available(np)) {
> +		of_node_put(np);
>  		return -ENODEV;
> +	}
>  
>  	init_fn = (psci_initcall_t)matched_np->data;
>  	ret = init_fn(np);
> -- 
> 2.39.5 (Apple Git-154)
> 


From wthai at nvidia.com  Wed Mar 19 04:24:51 2025
From: wthai at nvidia.com (Willie Thai)
Date: Wed, 19 Mar 2025 11:24:51 +0000
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <93bb3092-7f49-4a7f-ac97-3cf1a62ac39d@kernel.org>
References: <93bb3092-7f49-4a7f-ac97-3cf1a62ac39d@kernel.org>
Message-ID: <20250319112451.4171471-1-wthai@nvidia.com>

>> The GB200NVL BMC is an Aspeed Ast2600 based BMC
>> for Nvidia Blackwell GB200NVL platform.
>> Reference to Ast2600 SOC [1].
>> Reference to Blackwell GB200NVL Platform [2].
> 
> Missing blank line
> 

Thanks Krzysztof for the comments !
Will fix in the v3.

>> Co-developed-by: Mars Yang <maryang at nvidia.com>
>> Signed-off-by: Mars Yang <maryang at nvidia.com>
>> Cc: Krzysztof Kozlowski <krzk at kernel.org>
>> Cc: Andrew Lunn <andrew at lunn.ch>
>> Cc: Paul Menzel <pmenzel at molgen.mpg.de>
>> Link: Reference to Ast2600 SOC: https://www.aspeedtech.com/server_ast2600/ [1]
>> Link: Reference to Blackwell GB200NVL Platform: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
> 
> Links do not have text, I think. Just link.
> 

Will fix in the v3.

>> Signed-off-by: Willie Thai <wthai at nvidia.com>
>> ---
>> Changes in v2:
>>   - Fix the SOB name [Krzysztof]
>>   - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
>>   - Fix DTS coding style [Krzysztof]
>>   - Move pinctrl override to the bottom [Krzysztof]
>>   - Drop bootargs [Krzysztof]
>>   - Follow DTS coding style and change naming for leds node [Krzysztof]
>>   - Change flash 0 status property [Krzysztof]
>>   - Change the phy-mode to rgmii [Andrew]
>>   - Remove the max-speed in mac0 [Andrew]
>> ---
>> ---
>>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>>  .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1229 +++++++++++++++++
>>  2 files changed, 1230 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> 
>> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
>> index 2e5f4833a073..20fd357a1ee9 100644
>> --- a/arch/arm/boot/dts/aspeed/Makefile
>> +++ b/arch/arm/boot/dts/aspeed/Makefile
>> @@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>>  	aspeed-bmc-lenovo-hr630.dtb \
>>  	aspeed-bmc-lenovo-hr855xg2.dtb \
>>  	aspeed-bmc-microsoft-olympus.dtb \
>> +	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
>>  	aspeed-bmc-opp-lanyang.dtb \
>>  	aspeed-bmc-opp-mowgli.dtb \
>>  	aspeed-bmc-opp-nicole.dtb \
>> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> new file mode 100644
>> index 000000000000..eeec3704a43b
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> @@ -0,0 +1,1229 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/dts-v1/;
>> +
>> +#include "aspeed-g6.dtsi"
>> +#include <dt-bindings/gpio/aspeed-gpio.h>
>> +#include <dt-bindings/leds/common.h>
>> +
>> +/ {
>> +	model = "AST2600 GB200NVL BMC";
>> +	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";
> 
> Missing bindings.
> 
> Please run scripts/checkpatch.pl and fix reported warnings. After that,
> run also `scripts/checkpatch.pl --strict` and (probably) fix more
> warnings. Some warnings can be ignored, especially from --strict run,
> but the code here looks like it needs a fix. Feel free to get in touch
> if the warning is not clear.
> 

Will add the binding to dt-bindings in patch v3.

> 
> ...
> 
>> +	leds {
>> +		compatible = "gpio-leds";
>> +		led-0{
> 
> Missing space befre {
> 
> This applies everywhere.
> 
>> +			label = "uid_led";
>> +			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
>> +		};
>> +		led-1{
>> +			label = "fault_led";
>> +			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
>> +		};
>> +		led-2{
>> +			label = "power_led";
>> +			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
>> +		};
>> +
>> +	};
>> +
>> +	buttons {
>> +		button-power {
>> +			label = "power-btn";
>> +			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
>> +		};
>> +		button-uid {
>> +			label = "uid-btn";
>> +			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
>> +		};
>> +	};
>> +
>> +};
>> +
>> +// Enable Primary flash on FMC for bring up activity
>> +&fmc {
>> +	status = "okay";
>> +	flash at 0 {
>> +		status = "okay";
> 
> Nothing improved.
> 
> Respond to comment instead of ignoring it.
> 

The property was disabled here: https://github.com/torvalds/linux/blob/master/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi#L172

> 
> 
> ...
> 
> 
>> +
>> +		imux33: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +			pca9555 at 21 {
> 
> Node names should be generic. See also an explanation and list of
> examples (not exhaustive) in DT specification:
> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
> 
> You already got this comment. You must apply such feedback to entire
> file instead of fixing only one issue and relying on us to find all
> instances. It's your task to find all of the instances.
> 

Sure, will modify node names to generic

Thanks !


From akihiko.odaki at daynix.com  Wed Mar 19 04:26:18 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 20:26:18 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86o6xxmg87.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
Message-ID: <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>

On 2025/03/19 20:07, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 10:26:57 +0000,
> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>
>>>> It should also be the reason why the perf program creates an event for
>>>> each PMU. tools/perf/Documentation/intel-hybrid.txt has more
>>>> descriptions.
>>>
>>> But perf on non-Intel behaves pretty differently. ARM PMUs behaves
>>> pretty differently, because there is no guarantee of homogeneous
>>> events.
>>
>> It works in the same manner in this particular aspect (i.e., "perf
>> stat -e cycles -a" creates events for all PMUs).
> 
> But it then becomes a system-wide counter, and that's not what KVM
> needs to do.

There is also an example of program profiling:
"perf stat -e cycles \-- taskset -c 16 ./triad_loop"

This also creates events for all PMUs.

> 
>>>> Allowing to enable more than one counter and/or an event type other
>>>> than the cycle counter is not the goal. Enabling another event type
>>>> may result in a garbage value, but I don't think it's worse than the
>>>> current situation where the count stays zero; please tell me if I miss
>>>> something.
>>>>
>>>> There is still room for improvement. Returning a garbage value may not
>>>> be worse than returning zero, but counters and event types not
>>>> supported by some cores shouldn't be advertised as available in the
>>>> first place. More concretely:
>>>>
>>>> - The vCPU should be limited to run only on cores covered by PMUs when
>>>> KVM_ARM_VCPU_PMU_V3 is set.
>>>
>>> That's userspace's job. Bind to the desired PMU, and run. KVM will
>>> actively prevent you from running on the wrong CPU.
>>>
>>>> - PMCR_EL0.N advertised to the guest should be the minimum of ones of
>>>> host PMUs.
>>>
>>> How do you find out? CPUs can be hot-plugged on long after a VM has
>>> started, bringing in a new PMU, with a different number of counters.
>>>
>>>> - PMCEID0_EL0 and PMCEID1_EL0 advertised to the guest should be the
>>>> result of the AND operations of ones of host PMUs.
>>>
>>> Same problem.
>>
>> I guess special-casing the cycle counter is the only option if the
>> kernel is going to deal with this.
> 
> Indeed. I think Oliver's idea is the least bad of them all, but man,
> this is really ugly.
> 
>>>> Special-casing the cycle counter may make sense if we are going to fix
>>>> the advertised values of PMCR_EL0.N, PMCEID0_EL0, and
>>>> PMCEID1_EL0. PMCR_EL0.N as we can simply return zero for these
>>>> registers. We can also prevent enabling a counter that returns zero or
>>>> a garbage value.
>>>>
>>>> Do you think it's worth fixing these registers? If so, I'll do that by
>>>> special-casing the cycle counter.
>>>
>>> I think this is really going in the wrong direction.
>>>
>>> The whole design of the PMU emulation is that we expose a single,
>>> architecturally correct PMU implementation. This is clearly
>>> documented.
>>>
>>> Furthermore, userspace is being given all the relevant information to
>>> place vcpus on the correct physical CPUs. Why should we add this sort
>>> of hack in the kernel, creating a new userspace ABI that we will have
>>> to support forever, when usespace can do the correct thing right now?
>>>
>>> Worse case, this is just a 'taskset' away, and everything will work.
>>
>> It's surprisingly difficult to do that with libvirt; of course it is a
>> userspace problem though.
> 
> Sorry, I must admit I'm completely ignorant of libvirt. I tried it
> years ago, and concluded that 95% of what I needed was adequately done
> with a shell script...
> 
>>> Frankly, I'm not prepared to add more hacks to KVM for the sake of the
>>> combination of broken userspace and broken guest.
>>
>> The only counter argument I have in this regard is that some change is
>> also needed to expose all CPUs to Windows guest even when the
>> userspace does its best. It may result in odd scheduling, but still
>> gives the best throughput.
> 
> But that'd be a new ABI, which again would require buy-in from
> userspace.  Maybe there is scope for an all CPUs, cycle-counter only
> PMUv3 exposed to the guest, but that cannot be set automatically, as
> we would otherwise regress existing setups.
> 
> At this stage, and given that you need to change userspace, I'm not
> sure what the best course of action is.

Having an explicit flag for the userspace is fine for QEMU, which I 
care. It can flip the flag if and only if threads are not pinned to one 
PMU and the machine is a new setup.

I also wonder what regression you think setting it automatically causes.

Regards,
Akihiko Odaki

> 
> Thanks,
> 
> 	M.
> 



From uwe at kleine-koenig.org  Wed Mar 19 04:31:38 2025
From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Wed, 19 Mar 2025 12:31:38 +0100
Subject: [PATCH] arm64: dts: rockchip: ts433: Add pinmuxing for eMMC
Message-ID: <20250319113138.125192-2-uwe@kleine-koenig.org>

With this added barebox is able to access the eMMC even when booted via
USB.

Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
---
Hello,

I tested that on top of v6.14-rc1 +
https://lore.kernel.org/linux-arm-kernel/cover.1742331667.git.ukleinek at kernel.org/
but I guess git can apply it just fine on a different tree.

Best regards
Uwe

 arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
index 411f8ac7994b..6ae4316761c4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
@@ -630,6 +630,8 @@ &sdhci {
 	bus-width = <8>;
 	max-frequency = <200000000>;
 	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
 	status = "okay";
 };
 

base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
prerequisite-patch-id: 827ca0888cffe7cc82a938969cbe145d33967157
prerequisite-patch-id: 7d29172f7269dcddc26b0c6f08c4f1361a1fe0b3
-- 
2.47.1


From akihiko.odaki at daynix.com  Wed Mar 19 04:38:56 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 20:38:56 +0900
Subject: [PATCH 2/2] KVM: arm64: Trace SMC in a way similar to HVC
In-Reply-To: <20250319-trace-v1-0-0fff03204efa@daynix.com>
References: <20250319-trace-v1-0-0fff03204efa@daynix.com>
Message-ID: <20250319-trace-v1-2-0fff03204efa@daynix.com>

KVM handles SMCCC calls from virtual EL2 that use the SMC instruction
since commit bd36b1a9eb5a ("KVM: arm64: nv: Handle SMCs taken from
virtual EL2"). Copy the tracepoint for HVC to the SMC handler to trace
SMCCC calls whether they come from either HVC or SMC.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/handle_exit.c       |  3 +++
 arch/arm64/kvm/trace_handle_exit.h | 20 ++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 512d152233ff..087880b645be 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -55,6 +55,9 @@ static int handle_hvc(struct kvm_vcpu *vcpu)
 
 static int handle_smc(struct kvm_vcpu *vcpu)
 {
+	trace_kvm_smc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
+			    kvm_vcpu_hvc_get_imm(vcpu));
+
 	/*
 	 * Forward this trapped smc instruction to the virtual EL2 if
 	 * the guest has asked for it.
diff --git a/arch/arm64/kvm/trace_handle_exit.h b/arch/arm64/kvm/trace_handle_exit.h
index b0308d95304d..a3a0e0a46c60 100644
--- a/arch/arm64/kvm/trace_handle_exit.h
+++ b/arch/arm64/kvm/trace_handle_exit.h
@@ -46,6 +46,26 @@ TRACE_EVENT(kvm_hvc_arm64,
 		  __entry->vcpu_pc, __entry->r0, __entry->imm)
 );
 
+TRACE_EVENT(kvm_smc_arm64,
+	TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
+	TP_ARGS(vcpu_pc, r0, imm),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, vcpu_pc)
+		__field(unsigned long, r0)
+		__field(unsigned long, imm)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu_pc = vcpu_pc;
+		__entry->r0 = r0;
+		__entry->imm = imm;
+	),
+
+	TP_printk("SMC at 0x%016lx (r0: 0x%016lx, imm: 0x%lx)",
+		  __entry->vcpu_pc, __entry->r0, __entry->imm)
+);
+
 /*
  * The dreg32 name is a leftover from a distant past. This will really
  * output a 64bit value...

-- 
2.48.1



From sudeep.holla at arm.com  Wed Mar 19 04:39:22 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 19 Mar 2025 11:39:22 +0000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <Z9qmglbXw0xILaet@J2N7QTR9R3>
References: <20250318151712.28763-1-linmq006@gmail.com>
 <28cb8360-7fb0-46f0-b05f-5114f1974cf3@redhat.com>
 <Z9qgmTbeLh0cCULw@bogus>
 <Z9qmglbXw0xILaet@J2N7QTR9R3>
Message-ID: <Z9qs6r_eaQ0qLx9B@bogus>

On Wed, Mar 19, 2025 at 11:12:02AM +0000, Mark Rutland wrote:
> On Wed, Mar 19, 2025 at 10:46:49AM +0000, Sudeep Holla wrote:
> > On Wed, Mar 19, 2025 at 08:28:38PM +1000, Gavin Shan wrote:
> 
> > Any reason why we can't move to the new scoped usage like below?
> 
> > diff --git i/drivers/firmware/psci/psci.c w/drivers/firmware/psci/psci.c
> > index a1ebbe9b73b1..a4269078b2a2 100644
> > --- i/drivers/firmware/psci/psci.c
> > +++ w/drivers/firmware/psci/psci.c
> > @@ -797,12 +797,11 @@ static const struct of_device_id psci_of_match[] __initconst = {
> > 
> >  int __init psci_dt_init(void)
> >  {
> > -       struct device_node *np;
> >         const struct of_device_id *matched_np;
> >         psci_initcall_t init_fn;
> >         int ret;
> > -
> > -       np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
> > +       struct device_node *np __free(device_node) =
> > +               of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
> > 
> >         if (!np || !of_device_is_available(np))
> >                 return -ENODEV;
> > @@ -810,7 +809,6 @@ int __init psci_dt_init(void)
> >         init_fn = (psci_initcall_t)matched_np->data;
> >         ret = init_fn(np);
> > 
> > -       of_node_put(np);
> >         return ret;
> >  }
> 
> IIUC the bug has existed since before the scoped helpers were
> introduced, so for the sake of keeping the backport simple I reckon we
> should take Miaoqian Lin's patch as-is, and we can consider moving to
> the scoped helpers as a later cleanup.
> 

Agreed.

-- 
Regards,
Sudeep


From akihiko.odaki at daynix.com  Wed Mar 19 04:38:54 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 20:38:54 +0900
Subject: [PATCH 0/2] KVM: arm64: A few trace additions
Message-ID: <20250319-trace-v1-0-0fff03204efa@daynix.com>

These are tracepoints I added during recent debugging. I hope they are
useful for others too.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
Akihiko Odaki (2):
      KVM: arm64: Trace values with kvm_sys_access
      KVM: arm64: Trace SMC in a way similar to HVC

 arch/arm64/kvm/handle_exit.c       |  3 +++
 arch/arm64/kvm/sys_regs.c          | 24 ++++++++++++++----------
 arch/arm64/kvm/trace_handle_exit.h | 26 ++++++++++++++++++++++++--
 3 files changed, 41 insertions(+), 12 deletions(-)
---
base-commit: 8098cf067a7aae92a4f293df03964bf8474faca1
change-id: 20250319-trace-80cb8d39de2e

Best regards,
-- 
Akihiko Odaki <akihiko.odaki at daynix.com>



From akihiko.odaki at daynix.com  Wed Mar 19 04:38:55 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 20:38:55 +0900
Subject: [PATCH 1/2] KVM: arm64: Trace values with kvm_sys_access
In-Reply-To: <20250319-trace-v1-0-0fff03204efa@daynix.com>
References: <20250319-trace-v1-0-0fff03204efa@daynix.com>
Message-ID: <20250319-trace-v1-1-0fff03204efa@daynix.com>

Tracing values written to or read from system registers.

Signed-off-by: Akihiko Odaki <akihiko.odaki at daynix.com>
---
 arch/arm64/kvm/sys_regs.c          | 24 ++++++++++++++----------
 arch/arm64/kvm/trace_handle_exit.h |  6 ++++--
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 14f66c7a4545..362e2758d101 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -3994,23 +3994,27 @@ static void perform_access(struct kvm_vcpu *vcpu,
 			   struct sys_reg_params *params,
 			   const struct sys_reg_desc *r)
 {
-	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
+	bool skip;
 
 	/* Check for regs disabled by runtime config */
 	if (sysreg_hidden(vcpu, r)) {
 		kvm_inject_undefined(vcpu);
-		return;
+		skip = false;
+	} else {
+		/*
+		 * Not having an accessor means that we have configured a trap
+		 * that we don't know how to handle. This certainly qualifies
+		 * as a gross bug that should be fixed right away.
+		 */
+		BUG_ON(!r->access);
+
+		/* Skip instruction if instructed so */
+		skip = r->access(vcpu, params, r);
 	}
 
-	/*
-	 * Not having an accessor means that we have configured a trap
-	 * that we don't know how to handle. This certainly qualifies
-	 * as a gross bug that should be fixed right away.
-	 */
-	BUG_ON(!r->access);
+	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
 
-	/* Skip instruction if instructed so */
-	if (likely(r->access(vcpu, params, r)))
+	if (likely(skip))
 		kvm_incr_pc(vcpu);
 }
 
diff --git a/arch/arm64/kvm/trace_handle_exit.h b/arch/arm64/kvm/trace_handle_exit.h
index f85415db7713..b0308d95304d 100644
--- a/arch/arm64/kvm/trace_handle_exit.h
+++ b/arch/arm64/kvm/trace_handle_exit.h
@@ -88,6 +88,7 @@ TRACE_EVENT(kvm_sys_access,
 
 	TP_STRUCT__entry(
 		__field(unsigned long,			vcpu_pc)
+		__field(u64,				regval)
 		__field(bool,				is_write)
 		__field(const char *,			name)
 		__field(u8,				Op0)
@@ -99,6 +100,7 @@ TRACE_EVENT(kvm_sys_access,
 
 	TP_fast_assign(
 		__entry->vcpu_pc = vcpu_pc;
+		__entry->regval = params->regval;
 		__entry->is_write = params->is_write;
 		__entry->name = reg->name;
 		__entry->Op0 = reg->Op0;
@@ -109,10 +111,10 @@ TRACE_EVENT(kvm_sys_access,
 		__entry->Op2 = reg->Op2;
 	),
 
-	TP_printk("PC: %lx %s (%d,%d,%d,%d,%d) %s",
+	TP_printk("PC: %lx %s (%d,%d,%d,%d,%d) %llx %s",
 		  __entry->vcpu_pc, __entry->name ?: "UNKN",
 		  __entry->Op0, __entry->Op1, __entry->CRn,
-		  __entry->CRm, __entry->Op2,
+		  __entry->CRm, __entry->Op2, __entry->regval,
 		  __entry->is_write ? "write" : "read")
 );
 

-- 
2.48.1



From ivo.ivanov.ivanov1 at gmail.com  Wed Mar 19 04:39:00 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Wed, 19 Mar 2025 13:39:00 +0200
Subject: [PATCH v2 5/8] phy: phy-snps-eusb2: make repeater optional
In-Reply-To: <sxrae5pmykx6ul2y7uc24fss2kdeezkkom7ev7mavt3fbc6ckv@tghyp3whuxnu>
References: <20250223122227.725233-1-ivo.ivanov.ivanov1@gmail.com>
 <20250223122227.725233-6-ivo.ivanov.ivanov1@gmail.com>
 <sxrae5pmykx6ul2y7uc24fss2kdeezkkom7ev7mavt3fbc6ckv@tghyp3whuxnu>
Message-ID: <8e8bbcde-8ed4-4239-ad96-6cffd8b9d65c@gmail.com>

On 3/19/25 13:08, Dmitry Baryshkov wrote:
> On Sun, Feb 23, 2025 at 02:22:24PM +0200, Ivaylo Ivanov wrote:
>> Some platforms initialize their eUSB2 to USB repeater in the previous
>> stage bootloader and leave it in a working state for linux. Make the
>> repeater optional in order to allow for reusing that state until
>> proper repeater drivers are introduced.
> Generally "works as it is setup by the bootloader" is a very invalid
> justification. Please don't do that. We should not be depending on the
> way the bootlader sets up the devices, unless that _really_ makes sense.

It does, doesn't it? We still don't even have i2c up on Exynos2200, so bringing up
the repeater before this patchset gets merged is a no-go. Either way, we should
follow what bindings say. I will change the commit description a bit.

Best regards,
Ivaylo

>
>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>> ---
>>  drivers/phy/phy-snps-eusb2.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
>> index 4e5914a76..dcc69c00a 100644
>> --- a/drivers/phy/phy-snps-eusb2.c
>> +++ b/drivers/phy/phy-snps-eusb2.c
>> @@ -461,7 +461,7 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>>  		return dev_err_probe(dev, ret,
>>  				     "failed to get regulator supplies\n");
>>  
>> -	phy->repeater = devm_of_phy_get_by_index(dev, np, 0);
>> +	phy->repeater = devm_of_phy_optional_get(dev, np, 0);
>>  	if (IS_ERR(phy->repeater))
>>  		return dev_err_probe(dev, PTR_ERR(phy->repeater),
>>  				     "failed to get repeater\n");
>> -- 
>> 2.43.0
>>



From maz at kernel.org  Wed Mar 19 04:41:27 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 19 Mar 2025 11:41:27 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
Message-ID: <86msdhmemw.wl-maz@kernel.org>

On Wed, 19 Mar 2025 11:26:18 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/19 20:07, Marc Zyngier wrote:
> > On Wed, 19 Mar 2025 10:26:57 +0000,
> >>
> > But that'd be a new ABI, which again would require buy-in from
> > userspace.  Maybe there is scope for an all CPUs, cycle-counter only
> > PMUv3 exposed to the guest, but that cannot be set automatically, as
> > we would otherwise regress existing setups.
> > 
> > At this stage, and given that you need to change userspace, I'm not
> > sure what the best course of action is.
> 
> Having an explicit flag for the userspace is fine for QEMU, which I
> care. It can flip the flag if and only if threads are not pinned to
> one PMU and the machine is a new setup.
> 
> I also wonder what regression you think setting it automatically causes.

The current behaviour is that if you don't specify anything other than
creating a PMUv3 (without KVM_ARM_VCPU_PMU_V3_SET_PMU), you get *some*
PMU, and userspace is responsible for running the vcpu on CPUs that
will implement that PMU. When if does, all the counters, all the
events are valid. If it doesn't, nothing counts, but the
counters/events are still valid.

If you now add this flag automatically, the guest doesn't see the full
PMU anymore. Only the cycle counter. That's the regression.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From akihiko.odaki at daynix.com  Wed Mar 19 04:51:21 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Wed, 19 Mar 2025 20:51:21 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86msdhmemw.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
Message-ID: <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>

On 2025/03/19 20:41, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 11:26:18 +0000,
> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>
>> On 2025/03/19 20:07, Marc Zyngier wrote:
>>> On Wed, 19 Mar 2025 10:26:57 +0000,
>>>>
>>> But that'd be a new ABI, which again would require buy-in from
>>> userspace.  Maybe there is scope for an all CPUs, cycle-counter only
>>> PMUv3 exposed to the guest, but that cannot be set automatically, as
>>> we would otherwise regress existing setups.
>>>
>>> At this stage, and given that you need to change userspace, I'm not
>>> sure what the best course of action is.
>>
>> Having an explicit flag for the userspace is fine for QEMU, which I
>> care. It can flip the flag if and only if threads are not pinned to
>> one PMU and the machine is a new setup.
>>
>> I also wonder what regression you think setting it automatically causes.
> 
> The current behaviour is that if you don't specify anything other than
> creating a PMUv3 (without KVM_ARM_VCPU_PMU_V3_SET_PMU), you get *some*
> PMU, and userspace is responsible for running the vcpu on CPUs that
> will implement that PMU. When if does, all the counters, all the
> events are valid. If it doesn't, nothing counts, but the
> counters/events are still valid.
> 
> If you now add this flag automatically, the guest doesn't see the full
> PMU anymore. Only the cycle counter. That's the regression.

What about setting the flag automatically when a user fails to pin vCPUs 
to CPUs that are covered by one PMU? There would be no change if a user 
correctly pins vCPUs as it is. Otherwise, they will see a correct 
feature set advertised to the guest and the cycle counter working.

Regards,
Akihiko Odaki

> 
> Thanks,
> 
> 	M.
> 



From florin.leotescu at oss.nxp.com  Wed Mar 19 04:54:57 2025
From: florin.leotescu at oss.nxp.com (Florin Leotescu (OSS))
Date: Wed, 19 Mar 2025 11:54:57 +0000
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250319-optimistic-positive-peacock-cc26b1@krzk-bin>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
 <20250319-optimistic-positive-peacock-cc26b1@krzk-bin>
Message-ID: <DU7PR04MB111631E2E5B074A306033D001FFD92@DU7PR04MB11163.eurprd04.prod.outlook.com>

>>On Tue, Mar 18, 2025 at 10:54:42AM +0200, florin.leotescu at oss.nxp.com wrote:
>> From: Florin Leotescu <florin.leotescu at nxp.com>
>> 
>> Introduce yaml schema for Microchip emc2305 pwm fan controller.
>> 
>> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
>> Reviewed-by: Frank Li <Frank.Li at nxp.com>
>> ---
>>  .../bindings/hwmon/microchip,emc2305.yaml     | 113 ++++++++++++++++++
>>  1 file changed, 113 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>> 
>> diff --git 
>> a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml 
>> b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>> new file mode 100644
>> index 000000000000..e61ef97e63af
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
>> @@ -0,0 +1,113 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
>> +---
>> +

> No blank line here. Use existing code as template. If you find such code, share so we can fix it.

Thanks!   I will remove it.

Identified similar blank line on the following dt-binding files:

1 adi,ad741x.yaml
2 adi,adm1275.yaml
3 adi,ltc2991.yaml
4 maxim,max20730.yaml
5 maxim,max6639.yaml
6 maxim,max6650.yaml
7 nuvoton,nct6775.yaml
8 nuvoton,nct7363.yaml
9 nuvoton,nct7802.yaml
10 ti,adc128d818.yaml
11 ti,ads7828.yaml
12 ti,ina2xx.yaml
13 ti,lm87.yaml
14 ti,tmp513.yaml
15 ti,tps23861.yaml
16 winbond,w83781d.yaml

>> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Microchip EMC2305 SMBus compliant PWM fan controller
>> +
>> +maintainers:
>> +  - Michael Shych <michaelsh at nvidia.com>
>> +
>> +description:
>> +  Microchip EMC2301/2/3/5 pwm controller which supports
>> +  up to five programmable fan control circuits.
>> +
>> +properties:
>> +  compatible:
>> +    oneOf:
>> +      - enum:
>> +          - microchip,emc2305
>> +      - items:
>> +          - enum:
>> +              - microchip,emc2303
>> +              - microchip,emc2302
>> +              - microchip,emc2301
>> +          - const: microchip,emc2305
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  '#address-cells':
>> +    const: 1
>> +
>> +  '#size-cells':
>> +    const: 0
>> +
>> +  '#pwm-cells':
>> +    const: 3
>> +    description: |
>> +      Number of cells in a PWM specifier.
>> +      - cell 0: The PWM frequency
>> +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
>> +      - cell 2: The PWM output config:
>> +           - 0 (Open-Drain)
>> +           - 1 (Push-Pull)
>> +
>> +

> Just one blank line

Ok, I'll remove it. Thank you!

> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Florin


From oleg at redhat.com  Wed Mar 19 05:00:29 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Wed, 19 Mar 2025 13:00:29 +0100
Subject: [PATCH v2 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250318221457.3055598-4-david@redhat.com>
References: <20250318221457.3055598-1-david@redhat.com>
 <20250318221457.3055598-4-david@redhat.com>
Message-ID: <20250319120028.GA26879@redhat.com>

On 03/18, David Hildenbrand wrote:
>
> +	if (unlikely(!folio_test_anon(folio))) {
> +		VM_WARN_ON_ONCE(is_register);
> +		goto out;
> +	}

Don't we need folio_put() before "goto out" ?

Other than that, for this series:

Acked-by: Oleg Nesterov <oleg at redhat.com>



From suzuki.poulose at arm.com  Wed Mar 19 05:00:05 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Wed, 19 Mar 2025 12:00:05 +0000
Subject: [PATCH v2 2/8] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>
Message-ID: <cc68d43f-4719-4f57-a38c-fb5afe8d29cc@arm.com>

On 18/03/2025 16:21, James Clark wrote:
> The self hosted claim tag will be reset on device probe in a later
> commit. We'll want to do this before coresight_register() is called so
> won't have a coresight_device and have to use cs_access instead.
> 
> Also make them public and create locked and unlocked versions for
> later use.
> 
> Signed-off-by: James Clark <james.clark at linaro.org>

minor nit:

The restructuring looks a bit confusing. Could we start with :

coresight_{set,clear}_self_claim_tag_unlocked in Patch 1. Rather
than rename what we renamed in patch 1 again here.


> ---
>   drivers/hwtracing/coresight/coresight-core.c | 17 +++++++++++++----
>   include/linux/coresight.h                    |  3 ++-
>   2 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 3f1c996d668a..9ff601e2415a 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -151,12 +151,21 @@ static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
>   	isb();
>   }
>   
> -static inline void coresight_clear_self_claim_tag(struct coresight_device *csdev)
> +void coresight_clear_self_claim_tag(struct csdev_access *csa)
>   {
> -	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> +	CS_UNLOCK(csa->base);

This looks to be hard coding MMIO based access ? Should we abstract it 
based on the csdev_access_** ?


Suzuki


> +	coresight_clear_self_claim_tag_unlocked(csa);
> +	CS_LOCK(csa->base);
> +}
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
> +
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
> +{
> +	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>   				     CORESIGHT_CLAIMCLR);
>   	isb();
>   }
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
>   
>   /*
>    * coresight_claim_device_unlocked : Claim the device for self-hosted usage
> @@ -180,7 +189,7 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
>   	if (coresight_is_claimed_self_hosted(csdev))
>   		return 0;
>   	/* There was a race setting the tag, clean up and fail */
> -	coresight_clear_self_claim_tag(csdev);
> +	coresight_clear_self_claim_tag_unlocked(&csdev->access);
>   	return -EBUSY;
>   }
>   EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
> @@ -211,7 +220,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>   		return;
>   
>   	if (coresight_is_claimed_self_hosted(csdev))
> -		coresight_clear_self_claim_tag(csdev);
> +		coresight_clear_self_claim_tag_unlocked(&csdev->access);
>   	else
>   		/*
>   		 * The external agent may have not honoured our claim
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index d79a242b271d..00134a80d358 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
>   
>   extern int coresight_claim_device(struct coresight_device *csdev);
>   extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
> -
> +void coresight_clear_self_claim_tag(struct csdev_access *csa);
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
>   extern void coresight_disclaim_device(struct coresight_device *csdev);
>   extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
>   extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
> 





From david at redhat.com  Wed Mar 19 05:02:50 2025
From: david at redhat.com (David Hildenbrand)
Date: Wed, 19 Mar 2025 13:02:50 +0100
Subject: [PATCH v2 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250319120028.GA26879@redhat.com>
References: <20250318221457.3055598-1-david@redhat.com>
 <20250318221457.3055598-4-david@redhat.com>
 <20250319120028.GA26879@redhat.com>
Message-ID: <d0f0cbb3-6284-4060-afdb-ea828b9e909d@redhat.com>

On 19.03.25 13:00, Oleg Nesterov wrote:
> On 03/18, David Hildenbrand wrote:
>>
>> +	if (unlikely(!folio_test_anon(folio))) {
>> +		VM_WARN_ON_ONCE(is_register);
>> +		goto out;
>> +	}
> 
> Don't we need folio_put() before "goto out" ?
> 

Yes, thanks! ... as always, the result of some last-minute reshuffling :)

> Other than that, for this series:
> 
> Acked-by: Oleg Nesterov <oleg at redhat.com>
> 


-- 
Cheers,

David / dhildenb



From swathi.ks at samsung.com  Tue Mar 18 03:52:09 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Tue, 18 Mar 2025 16:22:09 +0530
Subject: [PATCH v8 0/2] arm64: dts: fsd: Add Ethernet support for FSD
 SoC
In-Reply-To: <20250307044904.59077-1-swathi.ks@samsung.com>
References: <CGME20250307045516epcas5p3b4006a5e2005beda04170179dc92ad16@epcas5p3.samsung.com>
	<20250307044904.59077-1-swathi.ks@samsung.com>
Message-ID: <000401db97f3$d20f5970$762e0c50$@samsung.com>



> -----Original Message-----
> From: Swathi K S <swathi.ks at samsung.com>
> Sent: 07 March 2025 10:19
> To: krzk+dt at kernel.org; linux-fsd at tesla.com; robh at kernel.org;
> conor+dt at kernel.org; richardcochran at gmail.com;
> alim.akhtar at samsung.com
> Cc: jayati.sahu at samsung.com; swathi.ks at samsung.com; linux-arm-
> kernel at lists.infradead.org; linux-samsung-soc at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org;
> netdev at vger.kernel.org; pankaj.dubey at samsung.com;
> ravi.patel at samsung.com; gost.dev at samsung.com
> Subject: [PATCH v8 0/2] arm64: dts: fsd: Add Ethernet support for FSD SoC
> 
> FSD platform has two instances of EQoS IP, one is in FSYS0 block and another
> one is in PERIC block. This patch series add required DT file modifications for
> the same.
> 
> Changes since v1:
> 1. Addressed the format related corrections.
> 2. Addressed the MAC address correction.
> 
> Changes since v2:
> 1. Corrected intendation issues.
> 
> Changes since v3:
> 1. Removed alias names of ethernet nodes
> 
> Changes since v4:
> 1. Added more details to the commit message as per review comment.
> 
> Changes since v5:
> 1. Avoided inserting node in the end and inserted it in between as per
> address.
> 2. Changed the node label.
> 3. Separating DT patches from net patches and posting in different branches.
> 
> Changes since v6:
> 1. Addressed Andrew's review comment and removed phy-mode from .dtsi
> to .dts
> 
> Changes since v7:
> 1. Addressed Russell's review comment-Implemented clock tree setup in DT
> 

Hi, 
The DT binding and driver patches corresponding to this patch is now reflecting in linux-next
https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/diff/Documentation/devicetree/bindings/net/tesla,fsd-ethqos.yaml?id=f654ead4682a1d351d4d780b1b59ab02477b1185

Could you consider these DT file patches for review/merge or do I need to resend these?

-Swathi

> Swathi K S (2):
>   arm64: dts: fsd: Add Ethernet support for FSYS0 Block of FSD SoC
>   arm64: dts: fsd: Add Ethernet support for PERIC Block of FSD SoC
> 
>  arch/arm64/boot/dts/tesla/fsd-evb.dts      |  20 ++++
>  arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi | 112 +++++++++++++++++++++
>  arch/arm64/boot/dts/tesla/fsd.dtsi         |  50 +++++++++
>  3 files changed, 182 insertions(+)
> 
> --
> 2.17.1




From james.clark at linaro.org  Wed Mar 19 05:30:17 2025
From: james.clark at linaro.org (James Clark)
Date: Wed, 19 Mar 2025 12:30:17 +0000
Subject: [PATCH v2 2/8] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <cc68d43f-4719-4f57-a38c-fb5afe8d29cc@arm.com>
References: <20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e@linaro.org>
 <20250318-james-coresight-claim-tags-v2-2-e9c8a9cde84e@linaro.org>
 <cc68d43f-4719-4f57-a38c-fb5afe8d29cc@arm.com>
Message-ID: <2700171e-dbaa-4218-9b46-5d181f5afee7@linaro.org>



On 19/03/2025 12:00 pm, Suzuki K Poulose wrote:
> On 18/03/2025 16:21, James Clark wrote:
>> The self hosted claim tag will be reset on device probe in a later
>> commit. We'll want to do this before coresight_register() is called so
>> won't have a coresight_device and have to use cs_access instead.
>>
>> Also make them public and create locked and unlocked versions for
>> later use.
>>
>> Signed-off-by: James Clark <james.clark at linaro.org>
> 
> minor nit:
> 
> The restructuring looks a bit confusing. Could we start with :
> 
> coresight_{set,clear}_self_claim_tag_unlocked in Patch 1. Rather
> than rename what we renamed in patch 1 again here.
> 
> 

I considered collapsing these two actually, would you be ok with that?

>> ---
>> ? drivers/hwtracing/coresight/coresight-core.c | 17 +++++++++++++----
>> ? include/linux/coresight.h??????????????????? |? 3 ++-
>> ? 2 files changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index 3f1c996d668a..9ff601e2415a 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -151,12 +151,21 @@ static inline void 
>> coresight_set_self_claim_tag(struct coresight_device *csdev)
>> ????? isb();
>> ? }
>> -static inline void coresight_clear_self_claim_tag(struct 
>> coresight_device *csdev)
>> +void coresight_clear_self_claim_tag(struct csdev_access *csa)
>> ? {
>> -??? csdev_access_relaxed_write32(&csdev->access, 
>> CORESIGHT_CLAIM_SELF_HOSTED,
>> +??? CS_UNLOCK(csa->base);
> 
> This looks to be hard coding MMIO based access ? Should we abstract it 
> based on the csdev_access_** ?
> 
> 
> Suzuki
> 
> 

I did something similar earlier but it ended up being huge to do it 
properly and I wasn't sure of the benefits so I deleted it. By 
'properly' I mean change all of the CS_UNLOCK() calls to be abstracted 
and delete etm4_cs_unlock() because CS_UNLOCK() would handle both. It 
ends adding in an if and indirection for every lock/unlock for devices 
that are never sysreg access anyway.

Because there's already this:

static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
			   struct csdev_access *csa)
{
	if (csa->io_mem)
		CS_UNLOCK(csa->base);

But yeah I can add the if into coresight_clear_self_claim_tag(), 
although it technically doesn't do anything now because it's never 
called by any devices that aren't MMIO. And then it makes 
etm4_cs_unlock() stand out a bit because its not a core function when it 
could be. But that's probably fine.






From swathi.ks at samsung.com  Tue Mar 18 03:56:03 2025
From: swathi.ks at samsung.com (Swathi K S)
Date: Tue, 18 Mar 2025 16:26:03 +0530
Subject: [PATCH v8 2/2] net: stmmac: dwc-qos: Add FSD EQoS support
In-Reply-To: <Z9HK2de5Ba_Vbeo7@shell.armlinux.org.uk>
References: <20250305091246.106626-1-swathi.ks@samsung.com>
	<CGME20250305091856epcas5p4228c09989c7acfe45a99541eef01fbcd@epcas5p4.samsung.com>
	<20250305091246.106626-3-swathi.ks@samsung.com>
	<Z8hjKI1ZqU19nrTP@shell.armlinux.org.uk>
	<Z9HK2de5Ba_Vbeo7@shell.armlinux.org.uk>
Message-ID: <000501db97f4$5cf4e7d0$16deb770$@samsung.com>



> -----Original Message-----
> From: Russell King (Oracle) <linux at armlinux.org.uk>
> Sent: 12 March 2025 23:27
> To: Swathi K S <swathi.ks at samsung.com>
> Cc: krzk+dt at kernel.org; andrew+netdev at lunn.ch; davem at davemloft.net;
> edumazet at google.com; kuba at kernel.org; pabeni at redhat.com;
> robh at kernel.org; conor+dt at kernel.org; richardcochran at gmail.com;
> mcoquelin.stm32 at gmail.com; alexandre.torgue at foss.st.com;
> netdev at vger.kernel.org; devicetree at vger.kernel.org; linux-stm32 at st-md-
> mailman.stormreply.com; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; pankaj.dubey at samsung.com;
> ravi.patel at samsung.com; gost.dev at samsung.com
> Subject: Re: [PATCH v8 2/2] net: stmmac: dwc-qos: Add FSD EQoS support
> 
> On Wed, Mar 05, 2025 at 02:43:52PM +0000, Russell King (Oracle) wrote:
> > On Wed, Mar 05, 2025 at 02:42:46PM +0530, Swathi K S wrote:
> > > The FSD SoC contains two instance of the Synopsys DWC ethernet QOS IP
> core.
> > > The binding that it uses is slightly different from existing ones
> > > because of the integration (clocks, resets).
> > >
> > > Signed-off-by: Swathi K S <swathi.ks at samsung.com>
> >
> > This looks much better!
> >
> > Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> >
> > Thanks!
> 
> Hi Swathi,
> 
> Please can you test with my TX clock gating series applied (
> https://lore.kernel.org/r/Z9FVHEf3uUqtKzyt at shell.armlinux.org.uk ) with
> STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP set as per the attached diff.
> Please let me know whether this passes your testing, so I know whether
this
> platform supports it - please check that this results in a message in the
kernel
> log indicating "tx_clk_stop = 1". Thanks.

Hi Russell, 
Applied your patches and tested. 
It did not cause any functional issue, but at the same time, as EEE is not
enabled in our HW, we cannot really test that particular functionality.

Regards, 
Swathi

> 
> --
> RMK's Patch system: https://protect2.fireeye.com/v1/url?k=23e12f6a-
> 429cc5e9-23e0a425-74fe48600158-954ebfe080aed91e&q=1&e=40e60980-
> bcfe-49e0-a9c9-
> d9b87765f87c&u=https%3A%2F%2Fwww.armlinux.org.uk%2Fdeveloper%2F
> patches%2F
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!



From broonie at kernel.org  Wed Mar 19 06:02:30 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 19 Mar 2025 13:02:30 +0000
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <Z9qaW_H9UFqdc1bI@J2N7QTR9R3>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
 <019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>
 <86r02tmldh.wl-maz@kernel.org>
 <Z9qaW_H9UFqdc1bI@J2N7QTR9R3>
Message-ID: <83ba4e5b-7700-4527-8376-2c60507bd0d7@sirena.org.uk>

On Wed, Mar 19, 2025 at 10:20:11AM +0000, Mark Rutland wrote:
> On Wed, Mar 19, 2025 at 09:15:54AM +0000, Marc Zyngier wrote:

> > The result is that this change is turning a perfectly valid HYP VA
> > into... something. Odds are that the masking/patching will not mess up
> > the address, but this is completely buggy anyway. In general,
> > kern_hyp_va() is not an idempotent operation.

> IIUC today it *happens* to be idempotent, but as you say that is not
> guaranteed to remain the case, and this is definitely a logical bug.

I think so, yes.  I suspect the idempotency confused me.

> > Greg, it may be more prudent to unstage this series from 6.12-stable
> > until we know for sure this is the only problem.

> As above, likewise with the v6.13 version.

Yes, please unstage these.  I'll send out new versions.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/f13798f1/attachment.sig>

From linux at roeck-us.net  Wed Mar 19 06:11:28 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 19 Mar 2025 06:11:28 -0700
Subject: [PATCH v4 07/14] arm64: Add support for suppressing warning
 backtraces
In-Reply-To: <a64bf821-ea90-4fd9-92ec-13bf7b7a3067@csgroup.eu>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-8-acarmina@redhat.com>
 <20250313122503.GA7438@willie-the-truck>
 <CAGegRW5r3V2-_44-X353vS-GZwDYG=SVwc6MzSGE8GdFQuFoKA@mail.gmail.com>
 <20250318155946.GC13829@willie-the-truck>
 <a64bf821-ea90-4fd9-92ec-13bf7b7a3067@csgroup.eu>
Message-ID: <9030a298-fcb6-48ea-a941-ad6916bf9fa7@roeck-us.net>

On 3/19/25 01:05, Christophe Leroy wrote:
> 
> 
> Le 18/03/2025 ? 16:59, Will Deacon a ?crit?:
>> On Thu, Mar 13, 2025 at 05:40:59PM +0100, Alessandro Carminati wrote:
>>> On Thu, Mar 13, 2025 at 1:25?PM Will Deacon <will at kernel.org> wrote:
>>>>
>>>> On Thu, Mar 13, 2025 at 11:43:22AM +0000, Alessandro Carminati wrote:
>>>>> diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
>>>>> index 28be048db3f6..044c5e24a17d 100644
>>>>> --- a/arch/arm64/include/asm/bug.h
>>>>> +++ b/arch/arm64/include/asm/bug.h
>>>>> @@ -11,8 +11,14 @@
>>>>>
>>>>> ? #include <asm/asm-bug.h>
>>>>>
>>>>> +#ifdef HAVE_BUG_FUNCTION
>>>>> +# define __BUG_FUNC? __func__
>>>>> +#else
>>>>> +# define __BUG_FUNC? NULL
>>>>> +#endif
>>>>> +
>>>>> ? #define __BUG_FLAGS(flags)?????????????????????????? \
>>>>> -???? asm volatile (__stringify(ASM_BUG_FLAGS(flags)));
>>>>> +???? asm volatile (__stringify(ASM_BUG_FLAGS(flags, %c0)) : : "i" (__BUG_FUNC));
>>>>
>>>> Why is 'i' the right asm constraint to use here? It seems a bit odd to
>>>> use that for a pointer.
>>>
>>> I received this code as legacy from a previous version.
>>> In my review, I considered the case when HAVE_BUG_FUNCTION is defined:
>>> Here, __BUG_FUNC is defined as __func__, which is the name of the
>>> current function as a string literal.
>>> Using the constraint "i" seems appropriate to me in this case.
>>>
>>> However, when HAVE_BUG_FUNCTION is not defined:
>>> __BUG_FUNC is defined as NULL. Initially, I considered it literal 0,
>>> but after investigating your concern, I found:
>>>
>>> ```
>>> $ echo -E "#include <stdio.h>\n#include <stddef.h>\nint main()
>>> {\nreturn 0;\n}" | aarch64-linux-gnu-gcc -E -dM - | grep NULL
>>> #define NULL ((void *)0)
>>> ```
>>>
>>> I realized that NULL is actually a pointer that is not a link time
>>> symbol, and using the "i" constraint with NULL may result in undefined
>>> behavior.
>>>
>>> Would the following alternative definition for __BUG_FUNC be more convincing?
>>>
>>> ```
>>> #ifdef HAVE_BUG_FUNCTION
>>> ???? #define __BUG_FUNC __func__
>>> #else
>>> ???? #define __BUG_FUNC (uintptr_t)0
>>> #endif
>>> ```
>>> Let me know your thoughts.
>>
>> Thanks for the analysis; I hadn't noticed this specific issue, it just
>> smelled a bit fishy. Anyway, the diff above looks better, thanks.
> 
> That propably deserves a comment.
> 
> Doesn't sparse and/or checkpatch complain about 0 being used in lieu of NULL ?
> 

__BUG_FUNC is only used as parameter to asm code, not as pointer.

 From the diff:

-                    : : "i" (__FILE__), "i" (__LINE__),                \
+                    : : "i" (__FILE__), "i" (__BUG_FUNC), "i" (__LINE__),\

The use is quite similar to __FILE__ and __LINE__. It might even be possible
and appropriate to just define __BUG_FUNC as 0 if HAVE_BUG_FUNCTION is not defined.

Guenter



From broonie at kernel.org  Wed Mar 19 06:12:22 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 19 Mar 2025 13:12:22 +0000
Subject: [PATCH 1/7] arm64/gcs: task_gcs_el0_enable() should use passed
 task
In-Reply-To: <20250318204841.373116-2-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-2-jeremy.linton@arm.com>
Message-ID: <979bd797-6f92-4195-989c-9a004d0d018c@sirena.org.uk>

On Tue, Mar 18, 2025 at 03:48:35PM -0500, Jeremy Linton wrote:
> Mark Rutland noticed that the task parameter is ignored and
> 'current' is being used instead. Since this is usually
> what its passed, it hasn't yet been causing problems but likely
> will as the code gets more testing.

Reviewed-by: Mark Brown <broonie at kernel.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/bb8296ff/attachment.sig>

From Frank.li at nxp.com  Wed Mar 19 06:22:53 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 19 Mar 2025 09:22:53 -0400
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <20250318153820.GA1001146@bhelgaas>
References: <20250315201548.858189-7-helgaas@kernel.org>
 <20250318153820.GA1001146@bhelgaas>
Message-ID: <Z9rFLSf9bcGyJqiT@lizhi-Precision-Tower-5810>

On Tue, Mar 18, 2025 at 10:38:20AM -0500, Bjorn Helgaas wrote:
> On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> > From: Frank Li <Frank.Li at nxp.com>
> >
> > dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> > controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> > is a hard-coded way to get the parent bus address corresponding to a CPU
> > physical address.
> >
> > Add debug code to compare the address from .cpu_addr_fixup() with the
> > address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> > redundant and should be removed; if they differ, warn that something is
> > wrong with the devicetree.
> >
> > If .cpu_addr_fixup() is not implemented, the parent bus address should be
> > identical to the CPU physical address because we previously ignored the
> > parent bus address from devicetree.  If the devicetree has a different
> > parent bus address, warn about it being broken.
>
> > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >  	struct device *dev = pci->dev;
> >  	struct device_node *np = dev->of_node;
> >  	int index;
> > -	u64 reg_addr;
> > +	u64 reg_addr, fixup_addr;
> > +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
> >
> >  	/* Look up reg_name address on parent bus */
> >  	index = of_property_match_string(np, "reg-names", reg_name);
> > @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >
> >  	of_property_read_reg(np, index, &reg_addr, NULL);
> >
> > +	fixup = pci->ops->cpu_addr_fixup;
> > +	if (fixup) {
> > +		fixup_addr = fixup(pci, cpu_phy_addr);
> > +		if (reg_addr == fixup_addr) {
> > +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
>
> On second thought, I think this one should be a dev_info(), not a
> dev_warn().  We know the *current* devicetree describes the offset
> correctly, but there may be other devicetrees that do not describe it,
> and we need to keep .cpu_addr_fixup() for those other devicetrees.
>
> So there's nothing the current user can or should do about this.

Okay

Frank
>
> > +				 cpu_phy_addr, reg_name, index,
> > +				 fixup_addr, fixup);
> > +		} else {
> > +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> > +				 cpu_phy_addr, reg_name,
> > +				 index, fixup_addr);
> > +			reg_addr = fixup_addr;
> > +		}
> > +	} else if (!pci->use_parent_dt_ranges) {
> > +		if (reg_addr != cpu_phy_addr) {
> > +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> > +				 cpu_phy_addr, reg_addr);
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> > +		 reg_name, cpu_phy_addr - reg_addr);
> >  	return cpu_phy_addr - reg_addr;
> >  }


From broonie at kernel.org  Wed Mar 19 06:24:15 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 19 Mar 2025 13:24:15 +0000
Subject: [PATCH 3/7] arm64: uaccess: Add additional userspace GCS
 accessors
In-Reply-To: <20250318204841.373116-4-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-4-jeremy.linton@arm.com>
Message-ID: <50a0920d-3e3d-4e96-b68a-a7a0d78c3695@sirena.org.uk>

On Tue, Mar 18, 2025 at 03:48:37PM -0500, Jeremy Linton wrote:

> +static inline u64 load_user_gcs(unsigned long __user *addr, int *err)
> +{
> +	unsigned long ret;
> +	u64 load;
> +
> +	if (!access_ok((char __user *)addr, sizeof(load))) {
> +		*err = -EFAULT;
> +		return 0;
> +	}
> +
> +	gcsb_dsync();
> +	ret = copy_from_user(&load, addr, sizeof(load));
> +	if (ret != 0)
> +		*err = ret;
> +	return load;
> +}

A GCS load done by the hardware will verify that we are loading from GCS
memory (the accesses are marked as AccessType_GCS in the pseudocode
which is then validated in for example S1CheckPermissions()).  Sadly
there's no equivalent of GCSSTR so we'd need to do the permission check
ourselves to match this behaviour.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/64d8a4b9/attachment.sig>

From broonie at kernel.org  Wed Mar 19 06:32:46 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 19 Mar 2025 13:32:46 +0000
Subject: [PATCH 6/7] uprobes: Allow the use of uprobe_warn() in arch code
In-Reply-To: <20250318204841.373116-7-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-7-jeremy.linton@arm.com>
Message-ID: <07499f3e-b730-444e-bd52-75bfaefef84f@sirena.org.uk>

On Tue, Mar 18, 2025 at 03:48:40PM -0500, Jeremy Linton wrote:
> The uprobe_warn function is limited to the uprobe core,
> but the functionality is useful to report arch specific errors.
> 
> Drop the static so it can be used in those code paths.

...and also make use of it in the arm64 code.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/b41dd46f/attachment.sig>

From andrew at lunn.ch  Wed Mar 19 06:37:47 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 19 Mar 2025 14:37:47 +0100
Subject: [PATCH v2 5/5] arm64: dts: ti: Add TQ-Systems TQMa62xx SoM and
 MBa62xx carrier board Device Trees
In-Reply-To: <e6ee878f655c31473bca54e4187d9006a19158b1.camel@ew.tq-group.com>
References: <cover.1733737487.git.matthias.schiffer@ew.tq-group.com>
 <95ff66ca2c89f69d893c2ce9eed9a0c677633c7b.1733737487.git.matthias.schiffer@ew.tq-group.com>
 <a9c5cfda-e3e3-436a-8d05-b2f096157cfe@lunn.ch>
 <c902a56cf34838f60cee67624bb923e91d74e9e0.camel@ew.tq-group.com>
 <d25b1447-c28b-4998-b238-92672434dc28@lunn.ch>
 <e16076d16349e929af82fa987a658bff1d9804c4.camel@ew.tq-group.com>
 <a2a2f201-73a4-4a99-baef-0d593a88c872@lunn.ch>
 <309052f3f69950fe43390505cc7254aee8c8f5c6.camel@ew.tq-group.com>
 <2953e10c-0a57-4d49-b831-3864a07eefd5@lunn.ch>
 <e6ee878f655c31473bca54e4187d9006a19158b1.camel@ew.tq-group.com>
Message-ID: <262ff436-2334-43bb-a998-ab48f06ea0e3@lunn.ch>

> Hi Andrew,
> 
> I've just thought about this issue again. As mentioned, a number of MAC
> drivers(*) implement what is described here:
> 
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/ethernet-controller.yaml?h=v6.13#n77
> 
> 
> That is, the delay is either added by the PHY or the MAC; having a delay on the
> PCB is simply not supported.

Yes it is, you are reading it wrong. First off, as said a number of
times in the last couple of months, this description is from the
perspective of the PHY. It is not the board perspective. So:

      # RX and TX delays are added by the MAC when required
      - rgmii

>From the perspective of the PHY, "when required" the MAC adds the
delay. It might not be required, because the PCB adds the delay.

      # RGMII with internal RX and TX delays provided by the PHY,
      # the MAC should not add the RX or TX delays in this case
      - rgmii-id

The MAC should not add delays because the PHY does. But this implies
the PCB cannot also be adding delays because you would end up with two
sets of delays.

> Fixing MAC drivers to interpret the values without
> "id" to mean that there is a delay on the PCB will break existing Device Trees,
> so that's no good.

You need to look at it broken driver by broken driver. I _think_ the
Aspeed case can be fixed. Others we need to look at the details. Maybe
in some cases we do need to add a warning to the device tree binding
the driver is FUBAR and has special, broken meaning for 'rgmii'.

> As a first step, I'd update the docs to describe the intended behavior, but
> mention that some drivers implement it wrong.

Feel free to submit patches. However, please think about it. DT is OS
agnostic. DT describes the hardware, not configuration. Other OSes
might decide on a different policy about which of the MAC/PHY pair
implements the delay, since that is configuration, not a hardware
description.

> The question is how to deal with
> the wrong behavior going forward. I see the following options, but none spark
> joy for me...
> 
> - Keep current driver behavior forever where fixing it would break existing
>   Device Trees
> - Deprecate all existing "rgmii*" values because of their inconsistent
>   implementation, come up with new ones. Seems like a huge pain to add support
>   for in all MAC drivers and other code that deals with PHY modes...

Won't help anyway. If developers are getting it wrong now, why should
they suddenly start getting it right when all you are changing is the
name.

The real issue is that you can combine two bugs to get a working
system. It seems like few developers actually understand RGMII
delays. They don't spend time to understand it, they just try random
things until it works. As a result, they get systems where the MAC is
unknowingly adding delays, and 'rgmii' works, so job done. They don't
know or care it is wrong.

> - Introduce an additional DTS flag next to phy-mode to express that the
>   phy-mode is supposed to be interpreted correctly

If you are going to do add any sort of property, it should be a bool
indicating the opposite, 'phy-mode-is-fubar'. Something which
developers will think about before copying into their DT.

> Do you have any suggestions?

Add a checkpatch.pl check. Any patch which adds a phy-mode !=
'rgmii-id' needs to have a comment on the previous line containing the
word PCB. That should at least help stop more broken DT being added.

	Andrew


From gregkh at linuxfoundation.org  Wed Mar 19 06:55:54 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Wed, 19 Mar 2025 06:55:54 -0700
Subject: [PATCH 6.12 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <83ba4e5b-7700-4527-8376-2c60507bd0d7@sirena.org.uk>
References: <20250314-stable-sve-6-12-v1-0-ddc16609d9ba@kernel.org>
 <20250314-stable-sve-6-12-v1-8-ddc16609d9ba@kernel.org>
 <019afc2d-b047-4e33-971c-7debbbaec84d@redhat.com>
 <86r02tmldh.wl-maz@kernel.org>
 <Z9qaW_H9UFqdc1bI@J2N7QTR9R3>
 <83ba4e5b-7700-4527-8376-2c60507bd0d7@sirena.org.uk>
Message-ID: <2025031946-myself-underling-0f4d@gregkh>

On Wed, Mar 19, 2025 at 01:02:30PM +0000, Mark Brown wrote:
> On Wed, Mar 19, 2025 at 10:20:11AM +0000, Mark Rutland wrote:
> > On Wed, Mar 19, 2025 at 09:15:54AM +0000, Marc Zyngier wrote:
> 
> > > The result is that this change is turning a perfectly valid HYP VA
> > > into... something. Odds are that the masking/patching will not mess up
> > > the address, but this is completely buggy anyway. In general,
> > > kern_hyp_va() is not an idempotent operation.
> 
> > IIUC today it *happens* to be idempotent, but as you say that is not
> > guaranteed to remain the case, and this is definitely a logical bug.
> 
> I think so, yes.  I suspect the idempotency confused me.
> 
> > > Greg, it may be more prudent to unstage this series from 6.12-stable
> > > until we know for sure this is the only problem.
> 
> > As above, likewise with the v6.13 version.
> 
> Yes, please unstage these.  I'll send out new versions.

All now dropped from both queues, thanks.

greg k-h


From angelogioacchino.delregno at collabora.com  Wed Mar 19 07:07:13 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Wed, 19 Mar 2025 15:07:13 +0100
Subject: [PATCH v1 2/3] dt-bindings: media: mediatek: mdp3: Add
 compatibles for MT8188 MDP3
In-Reply-To: <5682afd1785f37d9a995bee1643174b669c48535.camel@ndufresne.ca>
References: <20241218105320.38980-1-angelogioacchino.delregno@collabora.com>
 <20241218105320.38980-3-angelogioacchino.delregno@collabora.com>
 <5682afd1785f37d9a995bee1643174b669c48535.camel@ndufresne.ca>
Message-ID: <a79697fa-9ac0-4829-a36f-4e9915ad6bff@collabora.com>

Il 19/02/25 16:38, Nicolas Dufresne ha scritto:
> Hi Angelo,
> 
> Le mercredi 18 d?cembre 2024 ? 11:53 +0100, AngeloGioacchino Del Regno
> a ?crit?:
>> Add compatible strings for the FG, HDR, RSZ, STITCH, TCC, TDSHP
>> and WROT hardware components found in MediaTek's MT8188 SoC.
> 
> The firmware for this is missing in linux-firmware. I will not ack or
> pickMTK-VCODEC/MDP3 patches until this issue has been resolved.
> 

Nicolas et al linux-media maintainers:

https://lore.kernel.org/all/CA+5PVA6a+g1rZOM+ZRsNr-e4C9DPagQrffRO36yO3Bt3UXJNfQ at mail.gmail.com/

We ran tests on the firmware that was pushed, and sent the results in
reply to the patch that adds the firmware:

https://lore.kernel.org/all/8049a2ec-b5fe-440d-9704-c3b0e2d610c7 at notapiano

The SCP firmware for VCODEC and MDP3 on the MT8188/MT8370/MT8390 SoCs has
been merged in linux-firmware.

Can you please ack this patch now? :-)

Cheers,
Angelo

> regards,
> Nicolas
> 
>>
>> This hardware is compatible with MT8195.
>>
>> Signed-off-by: AngeloGioacchino Del Regno
>> <angelogioacchino.delregno at collabora.com>
>> ---
>>  ?.../devicetree/bindings/media/mediatek,mdp3-fg.yaml?????? | 8
>> ++++++--
>>  ?.../devicetree/bindings/media/mediatek,mdp3-hdr.yaml????? | 8
>> ++++++--
>>  ?.../devicetree/bindings/media/mediatek,mdp3-rsz.yaml????? | 1 +
>>  ?.../devicetree/bindings/media/mediatek,mdp3-stitch.yaml?? | 8
>> ++++++--
>>  ?.../devicetree/bindings/media/mediatek,mdp3-tcc.yaml????? | 8
>> ++++++--
>>  ?.../devicetree/bindings/media/mediatek,mdp3-tdshp.yaml??? | 8
>> ++++++--
>>  ?.../devicetree/bindings/media/mediatek,mdp3-wrot.yaml???? | 1 +
>>  ?7 files changed, 32 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> fg.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> fg.yaml
>> index 03f31b009085..40fda59fa8a8 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-fg.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-fg.yaml
>> @@ -16,8 +16,12 @@ description:
>>   
>>  ?properties:
>>  ?? compatible:
>> -??? enum:
>> -????? - mediatek,mt8195-mdp3-fg
>> +??? oneOf:
>> +????? - enum:
>> +????????? - mediatek,mt8195-mdp3-fg
>> +????? - items:
>> +????????? - const: mediatek,mt8188-mdp3-fg
>> +????????? - const: mediatek,mt8195-mdp3-fg
>>   
>>  ?? reg:
>>  ???? maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> hdr.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> hdr.yaml
>> index d4609bba6578..d9f926c20220 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-hdr.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-hdr.yaml
>> @@ -16,8 +16,12 @@ description:
>>   
>>  ?properties:
>>  ?? compatible:
>> -??? enum:
>> -????? - mediatek,mt8195-mdp3-hdr
>> +??? oneOf:
>> +????? - enum:
>> +????????? - mediatek,mt8195-mdp3-hdr
>> +????? - items:
>> +????????? - const: mediatek,mt8188-mdp3-hdr
>> +????????? - const: mediatek,mt8195-mdp3-hdr
>>   
>>  ?? reg:
>>  ???? maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> rsz.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> rsz.yaml
>> index f5676bec4326..8124c39d73e9 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-rsz.yaml
>> @@ -20,6 +20,7 @@ properties:
>>  ?????????? - mediatek,mt8183-mdp3-rsz
>>  ?????? - items:
>>  ?????????? - enum:
>> +????????????? - mediatek,mt8188-mdp3-rsz
>>  ?????????????? - mediatek,mt8195-mdp3-rsz
>>  ?????????? - const: mediatek,mt8183-mdp3-rsz
>>   
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> stitch.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> stitch.yaml
>> index d815bea29154..1d8e7e202c42 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> stitch.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> stitch.yaml
>> @@ -16,8 +16,12 @@ description:
>>   
>>  ?properties:
>>  ?? compatible:
>> -??? enum:
>> -????? - mediatek,mt8195-mdp3-stitch
>> +??? oneOf:
>> +????? - enum:
>> +????????? - mediatek,mt8195-mdp3-stitch
>> +????? - items:
>> +????????? - const: mediatek,mt8188-mdp3-stitch
>> +????????? - const: mediatek,mt8195-mdp3-stitch
>>   
>>  ?? reg:
>>  ???? maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tcc.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tcc.yaml
>> index 14ea556d4f82..6cff7c073ce4 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-tcc.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-tcc.yaml
>> @@ -17,8 +17,12 @@ description:
>>   
>>  ?properties:
>>  ?? compatible:
>> -??? enum:
>> -????? - mediatek,mt8195-mdp3-tcc
>> +??? oneOf:
>> +????? - enum:
>> +????????? - mediatek,mt8195-mdp3-tcc
>> +????? - items:
>> +????????? - const: mediatek,mt8188-mdp3-tcc
>> +????????? - const: mediatek,mt8195-mdp3-tcc
>>   
>>  ?? reg:
>>  ???? maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tdshp.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tdshp.yaml
>> index 8ab7f2d8e148..cdfa27324738 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tdshp.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> tdshp.yaml
>> @@ -16,8 +16,12 @@ description:
>>   
>>  ?properties:
>>  ?? compatible:
>> -??? enum:
>> -????? - mediatek,mt8195-mdp3-tdshp
>> +??? oneOf:
>> +????? - enum:
>> +????????? - mediatek,mt8195-mdp3-tdshp
>> +????? - items:
>> +????????? - const: mediatek,mt8188-mdp3-tdshp
>> +????????? - const: mediatek,mt8195-mdp3-tdshp
>>   
>>  ?? reg:
>>  ???? maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> wrot.yaml b/Documentation/devicetree/bindings/media/mediatek,mdp3-
>> wrot.yaml
>> index 53a679338402..b6269f4f9fd6 100644
>> --- a/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml
>> +++ b/Documentation/devicetree/bindings/media/mediatek,mdp3-wrot.yaml
>> @@ -20,6 +20,7 @@ properties:
>>  ?????????? - mediatek,mt8183-mdp3-wrot
>>  ?????? - items:
>>  ?????????? - enum:
>> +????????????? - mediatek,mt8188-mdp3-wrot
>>  ?????????????? - mediatek,mt8195-mdp3-wrot
>>  ?????????? - const: mediatek,mt8183-mdp3-wrot
>>   
> 




From horms at kernel.org  Wed Mar 19 07:17:02 2025
From: horms at kernel.org (Simon Horman)
Date: Wed, 19 Mar 2025 14:17:02 +0000
Subject: [PATCH net] net: ti: icssg-prueth: Add lock to stats
In-Reply-To: <20250314102721.1394366-1-danishanwar@ti.com>
References: <20250314102721.1394366-1-danishanwar@ti.com>
Message-ID: <20250319141702.GF280585@kernel.org>

On Fri, Mar 14, 2025 at 03:57:21PM +0530, MD Danish Anwar wrote:
> Currently the API emac_update_hardware_stats() reads different ICSSG
> stats without any lock protection.
> 
> This API gets called by .ndo_get_stats64() which is only under RCU
> protection and nothing else. Add lock to this API so that the reading of
> statistics happens during lock.
> 
> Fixes: c1e10d5dc7a1 ("net: ti: icssg-prueth: Add ICSSG Stats")
> Signed-off-by: MD Danish Anwar <danishanwar at ti.com>
> ---
> NOTE: This was suggested by Jakub Kicinski <kuba at kernel.org> [1] to get
> this as bug fix in net during upstreaming of FW Stats for ICSSG driver
> This patch doesn't depend on [1] and can be applied cleanly on net/main
> 
> [1] https://lore.kernel.org/all/20250306165513.541ff46e at kernel.org/

Reviewed-by: Simon Horman <horms at kernel.org>



From andersson at kernel.org  Wed Mar 19 07:19:08 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Wed, 19 Mar 2025 09:19:08 -0500
Subject: [PATCH] arm64: defconfig: Enable USB retimer and redriver
In-Reply-To: <20250318-xelite-retimer-redriver-v1-1-b3e85a37d294@oss.qualcomm.com>
References: <20250318-xelite-retimer-redriver-v1-1-b3e85a37d294@oss.qualcomm.com>
Message-ID: <174239394606.2278051.11144638961266854595.b4-ty@kernel.org>


On Tue, 18 Mar 2025 22:11:37 -0500, Bjorn Andersson wrote:
> Several boards based on the Qualcomm X Elite platform uses the NXP
> PTN3222 USB redriver and the Parade PS883x USB Type-C retimer. Without
> these USB, and in some cases display, doesn't probe successfully, so
> enable them.
> 
> 

Applied, thanks!

[1/1] arm64: defconfig: Enable USB retimer and redriver
      commit: dd20903cc09ac40e71096370a9564e6523e87c22

Best regards,
-- 
Bjorn Andersson <andersson at kernel.org>


From mark.rutland at arm.com  Wed Mar 19 07:26:26 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 14:26:26 +0000
Subject: [PATCH 1/7] arm64/gcs: task_gcs_el0_enable() should use passed
 task
In-Reply-To: <20250318204841.373116-2-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-2-jeremy.linton@arm.com>
Message-ID: <Z9rUEtZtNXhVnarO@J2N7QTR9R3>

On Tue, Mar 18, 2025 at 03:48:35PM -0500, Jeremy Linton wrote:
> Mark Rutland noticed that the task parameter is ignored and
> 'current' is being used instead. Since this is usually
> what its passed, it hasn't yet been causing problems but likely
> will as the code gets more testing.

Are we sure nothing is relying upon the bug?

For example, in copy_thread_gcs():

copy_thread_gcs(p, ...) {
	...
	gcs = gcs_alloc_thread_stack(p, ...) {
		...
		if (!task_gcs_el0_enabled(p))
			return 0;
		...
		< actually allocate here >
	}
	...
	p->thread.gcs_el0_mode = current->thread.gcs_el0_mode;
	...
}

Either that later assignment is redundant, or copy_thread_gcs() was
accidentally relying upon task_gcs_el0_enabled() reading from 'current'
rather than 'p', and this change opens up another bug...

Mark.

> 
> Fixes: fc84bc5378a8 ("arm64/gcs: Context switch GCS state for EL0")
> Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
> ---
>  arch/arm64/include/asm/gcs.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h
> index f50660603ecf..5bc432234d3a 100644
> --- a/arch/arm64/include/asm/gcs.h
> +++ b/arch/arm64/include/asm/gcs.h
> @@ -58,7 +58,7 @@ static inline u64 gcsss2(void)
>  
>  static inline bool task_gcs_el0_enabled(struct task_struct *task)
>  {
> -	return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
> +	return task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
>  }
>  
>  void gcs_set_el0_mode(struct task_struct *task);
> -- 
> 2.48.1
> 


From andersson at kernel.org  Wed Mar 19 07:24:47 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Wed, 19 Mar 2025 09:24:47 -0500
Subject: [GIT PULL] More Qualcomm driver updates for v6.15
Message-ID: <20250319142448.2279164-1-andersson@kernel.org>


The following changes since commit 2e14c17a2e3d697bef6b5bf49b253d6e52f3d186:

  soc: qcom: Do not expose internal servreg_location_entry_ei array (2025-02-14 11:37:30 -0600)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-drivers-for-6.15-2

for you to fetch changes up to 65f330ade7daec740ed8dbdf33ccfbfcc5fbf5c8:

  dt-bindings: power: qcom,kpss-acc-v2: add qcom,msm8916-acc compatible (2025-03-13 17:50:04 -0500)

----------------------------------------------------------------
More Qualcomm driver updates for v6.15

Introduce Devicetree binding for providing board-specific firmware-name
for the GENI serial engine block. Add SDM630/636 support in pd-mapper.
Clean up and fix error handling in the SSC block bus driver.
Add missing msm8916-acc compatible to resolve a number of Devicetree
validation errors.

----------------------------------------------------------------
Alexey Minnekhanov (1):
      soc: qcom: pd-mapper: Add support for SDM630/636

Christophe JAILLET (2):
      bus: qcom-ssc-block-bus: Remove some duplicated iounmap() calls
      bus: qcom-ssc-block-bus: Fix the error handling path of qcom_ssc_block_bus_probe()

Rayyan Ansari (1):
      dt-bindings: power: qcom,kpss-acc-v2: add qcom,msm8916-acc compatible

Viken Dadhaniya (1):
      dt-bindings: qcom: geni-se: Add 'firmware-name' property for firmware loading

 .../bindings/power/qcom,kpss-acc-v2.yaml           |  4 ++-
 .../devicetree/bindings/soc/qcom/qcom,geni-se.yaml |  5 ++++
 drivers/bus/qcom-ssc-block-bus.c                   | 34 ++++++++++++----------
 drivers/soc/qcom/qcom_pd_mapper.c                  | 12 ++++++++
 4 files changed, 39 insertions(+), 16 deletions(-)


From nfraprado at collabora.com  Wed Mar 19 07:25:18 2025
From: nfraprado at collabora.com (=?utf-8?B?TsOtY29sYXMgRi4gUi4gQS4=?= Prado)
Date: Wed, 19 Mar 2025 11:25:18 -0300
Subject: [PATCH 1/4] dt-bindings: remoteproc: mediatek: Add missing
 minItems for 8192/8195
In-Reply-To: <3fa1573d-e3b4-434c-867d-38fa69ad3a8e@linaro.org>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-1-8733e192cc73@collabora.com>
 <3fa1573d-e3b4-434c-867d-38fa69ad3a8e@linaro.org>
Message-ID: <7ab084b8-e77a-4881-a6a6-057b89613fb4@notapiano>

On Wed, Mar 19, 2025 at 08:16:37AM +0100, Krzysztof Kozlowski wrote:
> On 18/03/2025 23:22, N?colas F. R. A. Prado wrote:
> > Both MT8192 and MT8195 have an L1TCM memory, so it should be described
> > in reg, and therefore reg's minItems should be 3, as is already implicit
> > by reg-names. Override minItems to 3 for MT8192 and MT8195.
> 
> I think that was the original intention already, because reg-names are
> expecting min 3 items. Basically you just correct the missing lower
> constraint.

Yes, exactly, that's what I meant by "is already implicit by reg-names".

> 
> > 
> > Fixes: 6b55b1e2fd7f ("dt-bindings: remoteproc: mediatek: Support MT8195 dual-core SCP")
> > Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> > ---
> >  Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> > index adc6b3f36fde49eb3fa7ed3f08b0fa9e7f331162..ee33c233e44f3d51f0851b35697a24208c87f68a 100644
> > --- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> > +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> > @@ -185,6 +185,7 @@ allOf:
> >      then:
> >        properties:
> >          reg:
> > +          minItems: 3
> >            maxItems: 3
> 
> maxItems can be dropped.

Sure, I can send a patch for that in the next version.

Thanks,
N?colas


From andersson at kernel.org  Wed Mar 19 07:28:34 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Wed, 19 Mar 2025 09:28:34 -0500
Subject: [GIT PULL] More Qualcomm Arm32 Devicetree updates for v6.15
Message-ID: <20250319142836.2279859-1-andersson@kernel.org>


The following changes since commit adbbdcf4b2d6556721b580385ba387baca5c26ee:

  ARM: dts: qcom: ipq4018: Switch to undeprecated qcom,calibration-variant (2025-03-03 22:36:52 -0600)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm32-for-6.15-2

for you to fetch changes up to f5b7564fedcfd32df68d56781b9d7698343f8fbf:

  ARM: dts: qcom: Initial dts for LG Nexus 4 (2025-03-16 21:51:58 -0500)

----------------------------------------------------------------
More Qualcomm Arm32 Devicetree updates for v6.15

Introduce DeviceTree for the LG Nexus 4. Describe the modem remoteproc
and related components on MSM8226 and enable the modem on Samsung Galaxy
Tab 4 10.1 and HTC One Mini 2.

----------------------------------------------------------------
Ivan Belokobylskiy (1):
      ARM: dts: qcom: Initial dts for LG Nexus 4

Luca Weiss (4):
      ARM: dts: qcom: msm8226: Add modem remoteproc node
      ARM: dts: qcom: msm8226: Add BAM DMUX Ethernet/IP device
      ARM: dts: qcom: Introduce dtsi for LTE-capable MSM8926
      ARM: dts: qcom: msm8926-htc-memul: Enable modem

Matti Lehtim?ki (3):
      ARM: dts: qcom: msm8226: Add node for TCSR halt regs
      ARM: dts: qcom: msm8226: Add smsm node
      ARM: dts: qcom: msm8226-samsung-matisse-common: Enable modem

Rudraksha Gupta (2):
      ARM: dts: qcom: msm8960: Add BAM
      ARM: dts: qcom: msm8960: Add thermal sensor (tsens)

 arch/arm/boot/dts/qcom/Makefile                    |   1 +
 arch/arm/boot/dts/qcom/msm8926.dtsi                |  11 +
 .../dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts |   1 +
 .../dts/qcom/qcom-apq8026-samsung-milletwifi.dts   |   2 +
 .../boot/dts/qcom/qcom-apq8064-lg-nexus4-mako.dts  | 341 +++++++++++++++++++++
 .../dts/qcom/qcom-msm8226-microsoft-common.dtsi    |   6 +-
 .../dts/qcom/qcom-msm8226-microsoft-dempsey.dts    |   1 +
 .../dts/qcom/qcom-msm8226-microsoft-makepeace.dts  |   1 +
 .../dts/qcom/qcom-msm8226-microsoft-moneypenny.dts |   1 +
 .../qcom/qcom-msm8226-samsung-matisse-common.dtsi  |  19 +-
 arch/arm/boot/dts/qcom/qcom-msm8226.dtsi           | 155 ++++++++++
 arch/arm/boot/dts/qcom/qcom-msm8926-htc-memul.dts  |  14 +-
 .../qcom/qcom-msm8926-microsoft-superman-lte.dts   |   1 +
 .../boot/dts/qcom/qcom-msm8926-microsoft-tesla.dts |   1 +
 .../dts/qcom/qcom-msm8926-motorola-peregrine.dts   |   2 +-
 .../dts/qcom/qcom-msm8926-samsung-matisselte.dts   |   5 +
 arch/arm/boot/dts/qcom/qcom-msm8960.dtsi           |  99 +++++-
 17 files changed, 652 insertions(+), 9 deletions(-)
 create mode 100644 arch/arm/boot/dts/qcom/msm8926.dtsi
 create mode 100644 arch/arm/boot/dts/qcom/qcom-apq8064-lg-nexus4-mako.dts


From mark.rutland at arm.com  Wed Mar 19 07:34:25 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 14:34:25 +0000
Subject: [PATCH 6/7] uprobes: Allow the use of uprobe_warn() in arch code
In-Reply-To: <20250318204841.373116-7-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-7-jeremy.linton@arm.com>
Message-ID: <Z9rV8YbThvW2r69-@J2N7QTR9R3>

On Tue, Mar 18, 2025 at 03:48:40PM -0500, Jeremy Linton wrote:
> The uprobe_warn function is limited to the uprobe core,
> but the functionality is useful to report arch specific errors.
> 
> Drop the static so it can be used in those code paths.
> 
> Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>

NAK to the arm64 additions.

There is no reason to print a warning message for something that does
not adversely affect the kernel, and where buggy or malicious userspace
can trigger the warning when the kernel is behaving correctly.

This isn't even ratelimited.

Mark.

> ---
>  arch/arm64/kernel/probes/simulate-insn.c | 8 ++++++--
>  arch/arm64/kernel/probes/uprobes.c       | 4 ++++
>  include/linux/uprobes.h                  | 1 +
>  kernel/events/uprobes.c                  | 2 +-
>  4 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
> index 1fc9bb69b1eb..fe637fec8f36 100644
> --- a/arch/arm64/kernel/probes/simulate-insn.c
> +++ b/arch/arm64/kernel/probes/simulate-insn.c
> @@ -56,8 +56,10 @@ static inline void update_lr(struct pt_regs *regs, long addr)
>  
>  	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
>  		push_user_gcs(addr + 4,	 &err);
> -		if (err)
> +		if (err) {
> +			uprobe_warn(current, "GCS stack push failure");
>  			force_sig(SIGSEGV);
> +		}
>  	}
>  	procedure_link_pointer_set(regs, addr + 4);
>  }
> @@ -160,8 +162,10 @@ simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
>  
>  	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
>  		ret_addr = pop_user_gcs(&err);
> -		if (err || ret_addr != procedure_link_pointer(regs))
> +		if (err || ret_addr != procedure_link_pointer(regs)) {
> +			uprobe_warn(current, "GCS RET address mismatch");
>  			force_sig(SIGSEGV);
> +		}
>  	}
>  
>  }
> diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
> index 5e72409a255a..9349d521316c 100644
> --- a/arch/arm64/kernel/probes/uprobes.c
> +++ b/arch/arm64/kernel/probes/uprobes.c
> @@ -54,6 +54,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
>  
>  	switch (arm_probe_decode_insn(insn, &auprobe->api)) {
>  	case INSN_REJECTED:
> +		uprobe_warn(current, "Unsupported instruction at probe location");
>  		return -EINVAL;
>  
>  	case INSN_GOOD_NO_SLOT:
> @@ -169,6 +170,7 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
>  		gcspr = read_sysreg_s(SYS_GCSPR_EL0);
>  		gcs_ret_vaddr = load_user_gcs((unsigned long __user *)gcspr, &err);
>  		if (err) {
> +			uprobe_warn(current, "GCS stack not available for retprobe");
>  			force_sig(SIGSEGV);
>  			goto out;
>  		}
> @@ -180,11 +182,13 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
>  		 * a GCS exception.
>  		 */
>  		if (gcs_ret_vaddr != orig_ret_vaddr)	{
> +			uprobe_warn(current, "LR/GCS mismatch, likely due to incorrectly placed retprobe");
>  			orig_ret_vaddr = -1;
>  			goto out;
>  		}
>  		put_user_gcs(trampoline_vaddr, (unsigned long __user *) gcspr, &err);
>  		if (err) {
> +			uprobe_warn(current, "GCS stack update failure during retprobe");
>  			force_sig(SIGSEGV);
>  			goto out;
>  		}
> diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
> index b1df7d792fa1..9578ef1ea5a3 100644
> --- a/include/linux/uprobes.h
> +++ b/include/linux/uprobes.h
> @@ -185,6 +185,7 @@ struct uprobes_state {
>  };
>  
>  extern void __init uprobes_init(void);
> +extern void uprobe_warn(struct task_struct *t, const char *msg);
>  extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>  extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>  extern bool is_swbp_insn(uprobe_opcode_t *insn);
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index b4ca8898fe17..613c1c76f227 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -118,7 +118,7 @@ struct xol_area {
>  	unsigned long 			vaddr;		/* Page(s) of instruction slots */
>  };
>  
> -static void uprobe_warn(struct task_struct *t, const char *msg)
> +void uprobe_warn(struct task_struct *t, const char *msg)
>  {
>  	pr_warn("uprobe: %s:%d failed to %s\n", current->comm, current->pid, msg);
>  }
> -- 
> 2.48.1
> 


From matthias.schiffer at ew.tq-group.com  Wed Mar 19 07:38:33 2025
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Wed, 19 Mar 2025 15:38:33 +0100
Subject: [PATCH v2 5/5] arm64: dts: ti: Add TQ-Systems TQMa62xx SoM and
 MBa62xx carrier board Device Trees
In-Reply-To: <262ff436-2334-43bb-a998-ab48f06ea0e3@lunn.ch>
References: <cover.1733737487.git.matthias.schiffer@ew.tq-group.com>
	 <95ff66ca2c89f69d893c2ce9eed9a0c677633c7b.1733737487.git.matthias.schiffer@ew.tq-group.com>
	 <a9c5cfda-e3e3-436a-8d05-b2f096157cfe@lunn.ch>
	 <c902a56cf34838f60cee67624bb923e91d74e9e0.camel@ew.tq-group.com>
	 <d25b1447-c28b-4998-b238-92672434dc28@lunn.ch>
	 <e16076d16349e929af82fa987a658bff1d9804c4.camel@ew.tq-group.com>
	 <a2a2f201-73a4-4a99-baef-0d593a88c872@lunn.ch>
	 <309052f3f69950fe43390505cc7254aee8c8f5c6.camel@ew.tq-group.com>
	 <2953e10c-0a57-4d49-b831-3864a07eefd5@lunn.ch>
	 <e6ee878f655c31473bca54e4187d9006a19158b1.camel@ew.tq-group.com>
	 <262ff436-2334-43bb-a998-ab48f06ea0e3@lunn.ch>
Message-ID: <570d9c2a25b437ab75f14104b354027210809028.camel@ew.tq-group.com>

On Wed, 2025-03-19 at 14:37 +0100, Andrew Lunn wrote:
> > Hi Andrew,
> > 
> > I've just thought about this issue again. As mentioned, a number of MAC
> > drivers(*) implement what is described here:
> > 
> > https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/ethernet-controller.yaml?h=v6.13#n77
> > 
> > 
> > That is, the delay is either added by the PHY or the MAC; having a delay on the
> > PCB is simply not supported.
> 
> Yes it is, you are reading it wrong. First off, as said a number of
> times in the last couple of months, this description is from the
> perspective of the PHY. It is not the board perspective. So:
> 
>       # RX and TX delays are added by the MAC when required
>       - rgmii
> 
> From the perspective of the PHY, "when required" the MAC adds the
> delay. It might not be required, because the PCB adds the delay.

I fail to see how the documentation could be interpreted that way. As you
explained, "rgmii" actually means that the delay is added by the PCB, so there
simply is no "when required" here - it can't be required if it's already in the
PCB. I stand by my opinion that this doc is plain wrong and not just worded
poorly, and needs to be fixed to express the intended meaning.

(I believe we agree on the point that this should be improved, I just don't
think it is appropriate to make statements like "few developers actually
understand RGMII delays" when the inaccuracy of the binding docs - supposedly an
authoritative resource on the meaning of DT properties - is the cause of the
misunderstanding)


> 
>       # RGMII with internal RX and TX delays provided by the PHY,
>       # the MAC should not add the RX or TX delays in this case
>       - rgmii-id
> 
> The MAC should not add delays because the PHY does. But this implies
> the PCB cannot also be adding delays because you would end up with two
> sets of delays.
> 
> > Fixing MAC drivers to interpret the values without
> > "id" to mean that there is a delay on the PCB will break existing Device Trees,
> > so that's no good.
> 
> You need to look at it broken driver by broken driver. I _think_ the
> Aspeed case can be fixed. Others we need to look at the details. Maybe
> in some cases we do need to add a warning to the device tree binding
> the driver is FUBAR and has special, broken meaning for 'rgmii'.

I don't know about Aspeed (maybe you're mixing something up, or I'm not aware of
something?) - in the case of the TI driver I'm dealing with, this is indeed
possible to fix up because the MAC always adds a delay, it is not configurable.

> 
> > As a first step, I'd update the docs to describe the intended behavior, but
> > mention that some drivers implement it wrong.
> 
> Feel free to submit patches. However, please think about it. DT is OS
> agnostic. DT describes the hardware, not configuration. Other OSes
> might decide on a different policy about which of the MAC/PHY pair
> implements the delay, since that is configuration, not a hardware
> description.
> 
> > The question is how to deal with
> > the wrong behavior going forward. I see the following options, but none spark
> > joy for me...
> > 
> > - Keep current driver behavior forever where fixing it would break existing
> >   Device Trees
> > - Deprecate all existing "rgmii*" values because of their inconsistent
> >   implementation, come up with new ones. Seems like a huge pain to add support
> >   for in all MAC drivers and other code that deals with PHY modes...
> 
> Won't help anyway. If developers are getting it wrong now, why should
> they suddenly start getting it right when all you are changing is the
> name.
> 
> The real issue is that you can combine two bugs to get a working
> system. It seems like few developers actually understand RGMII
> delays. They don't spend time to understand it, they just try random
> things until it works. As a result, they get systems where the MAC is
> unknowingly adding delays, and 'rgmii' works, so job done. They don't
> know or care it is wrong.
> 
> > - Introduce an additional DTS flag next to phy-mode to express that the
> >   phy-mode is supposed to be interpreted correctly
> 
> If you are going to do add any sort of property, it should be a bool
> indicating the opposite, 'phy-mode-is-fubar'. Something which
> developers will think about before copying into their DT.

The whole point of my suggestions is to allow fixing the drivers while staying
compatible with old, broken Device Trees. If we could add a property 'phy-mode-
is-fubar' to old Device Trees, we could just fix them instead - but we can only
fix in-tree DTS, and it will only have an effect on systems that update their
DTBs with their kernel, so I believe this simply isn't an option because of
backwards compat guarantees for Device Trees.


> 
> > Do you have any suggestions?
> 
> Add a checkpatch.pl check. Any patch which adds a phy-mode !=
> 'rgmii-id' needs to have a comment on the previous line containing the
> word PCB. That should at least help stop more broken DT being added.

Ah, I like that idea - I'll see if I can find time to look into it.

Best,
Matthias



> 
> 	Andrew

-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
https://www.tq-group.com/


From gregkh at linuxfoundation.org  Wed Mar 19 07:31:09 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Wed, 19 Mar 2025 07:31:09 -0700
Subject: [PATCH 6.13 199/241] Fix mmu notifiers for range-based invalidates
In-Reply-To: <20250319143027.685727358@linuxfoundation.org>
References: <20250319143027.685727358@linuxfoundation.org>
Message-ID: <20250319143032.645686776@linuxfoundation.org>

6.13-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Piotr Jaroszynski <pjaroszynski at nvidia.com>

commit f7edb07ad7c66eab3dce57384f33b9799d579133 upstream.

Update the __flush_tlb_range_op macro not to modify its parameters as
these are unexepcted semantics. In practice, this fixes the call to
mmu_notifier_arch_invalidate_secondary_tlbs() in
__flush_tlb_range_nosync() to use the correct range instead of an empty
range with start=end. The empty range was (un)lucky as it results in
taking the invalidate-all path that doesn't cause correctness issues,
but can certainly result in suboptimal perf.

This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
invalidate_range() when invalidating TLBs") when the call to the
notifiers was added to __flush_tlb_range(). It predates the addition of
the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") that made the
bug hard to spot.

Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Alistair Popple <apopple at nvidia.com>
Cc: Raghavendra Rao Ananta <rananta at google.com>
Cc: SeongJae Park <sj at kernel.org>
Cc: Jason Gunthorpe <jgg at nvidia.com>
Cc: John Hubbard <jhubbard at nvidia.com>
Cc: Nicolin Chen <nicolinc at nvidia.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: linux-mm at kvack.org
Cc: linux-kernel at vger.kernel.org
Cc: stable at vger.kernel.org
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Reviewed-by: Alistair Popple <apopple at nvidia.com>
Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski at nvidia.com
Signed-off-by: Will Deacon <will at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/tlbflush.h |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(s
 #define __flush_tlb_range_op(op, start, pages, stride,			\
 				asid, tlb_level, tlbi_user, lpa2)	\
 do {									\
+	typeof(start) __flush_start = start;				\
+	typeof(pages) __flush_pages = pages;				\
 	int num = 0;							\
 	int scale = 3;							\
 	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 	unsigned long addr;						\
 									\
-	while (pages > 0) {						\
+	while (__flush_pages > 0) {					\
 		if (!system_supports_tlb_range() ||			\
-		    pages == 1 ||					\
-		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
-			addr = __TLBI_VADDR(start, asid);		\
+		    __flush_pages == 1 ||				\
+		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
+			addr = __TLBI_VADDR(__flush_start, asid);	\
 			__tlbi_level(op, addr, tlb_level);		\
 			if (tlbi_user)					\
 				__tlbi_user_level(op, addr, tlb_level);	\
-			start += stride;				\
-			pages -= stride >> PAGE_SHIFT;			\
+			__flush_start += stride;			\
+			__flush_pages -= stride >> PAGE_SHIFT;		\
 			continue;					\
 		}							\
 									\
-		num = __TLBI_RANGE_NUM(pages, scale);			\
+		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
+			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 						scale, num, tlb_level);	\
 			__tlbi(r##op, addr);				\
 			if (tlbi_user)					\
 				__tlbi_user(r##op, addr);		\
-			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			pages -= __TLBI_RANGE_PAGES(num, scale);	\
+			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 		}							\
 		scale--;						\
 	}								\




From naresh.kamboju at linaro.org  Wed Mar 19 07:37:47 2025
From: naresh.kamboju at linaro.org (Naresh Kamboju)
Date: Wed, 19 Mar 2025 20:07:47 +0530
Subject: Fast model boot failure with Linux next-20250312
Message-ID: <CA+G9fYvPu+MQKhYyPZSSDpAn-zhRGmeHQ8hJksT_cdDdxfbB-g@mail.gmail.com>

Regressions on the arm64 Fast Model (FVP-AEMvA) caused boot failures starting
with Linux next-20250312 and persisting through next-20250319.

First seen on the next-20250312
 Good: next-20250311
 Bad:  next-20250312 .. next-20250319

Regressions found on FVP:
 - boot

Regression Analysis:
 - New regression? Yes
 - Reproducible? Yes

Boot regression: Fast model boot failure with Linux next-20250312
Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>

Anders bisected this to this commit id,

# first bad commit:
  [858c7bfcb35e1100b58bb63c9f562d86e09418d9]
  arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9

NOTE:
  LKFT is currently running FVP Fast Models version 11.24.
  Planned upgrade to the Fast Models version 11.28 in this sprint.

## Boot log
  <No crash log on the console>

## Source
* Kernel version: 6.14.0-rc7
* Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
* Git sha: ff7f9b199e3f4cc7d61df5a9a26a7cbb5c1492e6
* Git describe: next-20250319
* Project details:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319
* DUT: arm64 Fast Model (FVP-AEMvA)
* Toolchains: gcc-13 and clang-20

## Build
* Build log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/log
* Build history:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675685/suite/boot/test/gcc-13-lkftconfig/history/
* Build details:
https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/
* Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/
* Kernel config:
https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/config

--
Linaro LKFT
https://lkft.linaro.org


From gregkh at linuxfoundation.org  Wed Mar 19 07:31:25 2025
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Wed, 19 Mar 2025 07:31:25 -0700
Subject: [PATCH 6.12 192/231] Fix mmu notifiers for range-based invalidates
In-Reply-To: <20250319143026.865956961@linuxfoundation.org>
References: <20250319143026.865956961@linuxfoundation.org>
Message-ID: <20250319143031.585102708@linuxfoundation.org>

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Piotr Jaroszynski <pjaroszynski at nvidia.com>

commit f7edb07ad7c66eab3dce57384f33b9799d579133 upstream.

Update the __flush_tlb_range_op macro not to modify its parameters as
these are unexepcted semantics. In practice, this fixes the call to
mmu_notifier_arch_invalidate_secondary_tlbs() in
__flush_tlb_range_nosync() to use the correct range instead of an empty
range with start=end. The empty range was (un)lucky as it results in
taking the invalidate-all path that doesn't cause correctness issues,
but can certainly result in suboptimal perf.

This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call
invalidate_range() when invalidating TLBs") when the call to the
notifiers was added to __flush_tlb_range(). It predates the addition of
the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb:
Refactor the core flush algorithm of __flush_tlb_range") that made the
bug hard to spot.

Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs")

Signed-off-by: Piotr Jaroszynski <pjaroszynski at nvidia.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Alistair Popple <apopple at nvidia.com>
Cc: Raghavendra Rao Ananta <rananta at google.com>
Cc: SeongJae Park <sj at kernel.org>
Cc: Jason Gunthorpe <jgg at nvidia.com>
Cc: John Hubbard <jhubbard at nvidia.com>
Cc: Nicolin Chen <nicolinc at nvidia.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: iommu at lists.linux.dev
Cc: linux-mm at kvack.org
Cc: linux-kernel at vger.kernel.org
Cc: stable at vger.kernel.org
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Reviewed-by: Alistair Popple <apopple at nvidia.com>
Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski at nvidia.com
Signed-off-by: Will Deacon <will at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/tlbflush.h |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(s
 #define __flush_tlb_range_op(op, start, pages, stride,			\
 				asid, tlb_level, tlbi_user, lpa2)	\
 do {									\
+	typeof(start) __flush_start = start;				\
+	typeof(pages) __flush_pages = pages;				\
 	int num = 0;							\
 	int scale = 3;							\
 	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 	unsigned long addr;						\
 									\
-	while (pages > 0) {						\
+	while (__flush_pages > 0) {					\
 		if (!system_supports_tlb_range() ||			\
-		    pages == 1 ||					\
-		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
-			addr = __TLBI_VADDR(start, asid);		\
+		    __flush_pages == 1 ||				\
+		    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
+			addr = __TLBI_VADDR(__flush_start, asid);	\
 			__tlbi_level(op, addr, tlb_level);		\
 			if (tlbi_user)					\
 				__tlbi_user_level(op, addr, tlb_level);	\
-			start += stride;				\
-			pages -= stride >> PAGE_SHIFT;			\
+			__flush_start += stride;			\
+			__flush_pages -= stride >> PAGE_SHIFT;		\
 			continue;					\
 		}							\
 									\
-		num = __TLBI_RANGE_NUM(pages, scale);			\
+		num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 		if (num >= 0) {						\
-			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
+			addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 						scale, num, tlb_level);	\
 			__tlbi(r##op, addr);				\
 			if (tlbi_user)					\
 				__tlbi_user(r##op, addr);		\
-			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
-			pages -= __TLBI_RANGE_PAGES(num, scale);	\
+			__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+			__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 		}							\
 		scale--;						\
 	}								\




From cwabbott0 at gmail.com  Wed Mar 19 07:44:00 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:44:00 -0400
Subject: [PATCH v5 1/5] iommu/arm-smmu: Save additional information on
 context fault
In-Reply-To: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
References: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-1-97561209dd8c@gmail.com>

This will be used by drm/msm for GPU page faults, replacing the manual
register reading it does.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  6 ++--
 drivers/iommu/arm/arm-smmu/arm-smmu.c            | 35 ++++++++++++++----------
 drivers/iommu/arm/arm-smmu/arm-smmu.h            |  7 +++--
 3 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
index 548783f3f8e89fd978367afa65c473002f66e2e7..5bf1aa4aa941962710f1f14260e133d560aee86f 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
@@ -393,14 +393,14 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
 				      DEFAULT_RATELIMIT_INTERVAL,
 				      DEFAULT_RATELIMIT_BURST);
 
-	arm_smmu_read_context_fault_info(smmu, idx, &cfi);
+	arm_smmu_read_context_fault_info(smmu_domain, &cfi);
 
 	if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
 	if (list_empty(&tbu_list)) {
 		ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-					 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+					 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 		if (ret == -ENOSYS)
 			arm_smmu_print_context_fault_info(smmu, idx, &cfi);
@@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
 	phys_soft = ops->iova_to_phys(ops, cfi.iova);
 
 	tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-				 cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+				 cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 	if (!tmp || tmp == -EBUSY) {
 		ret = IRQ_HANDLED;
 		resume = ARM_SMMU_RESUME_TERMINATE;
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index ade4684c14c9b2724a71e2457288dbfaf7562c83..a02078eb968b81a35c1c086ed7007ea2a453ef94 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -405,13 +405,20 @@ static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = {
 };
 
 
-void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
+void arm_smmu_read_context_fault_info(struct arm_smmu_domain *smmu_domain,
 				      struct arm_smmu_context_fault_info *cfi)
 {
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	int idx = smmu_domain->cfg.cbndx;
+
 	cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
+	cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
 	cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
-	cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
+	cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
+	cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
 	cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
+	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1)
+		cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
 }
 
 void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
@@ -419,7 +426,7 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 {
 	dev_err(smmu->dev,
 		"Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cbfrsynra=0x%x, cb=%d\n",
-		cfi->fsr, cfi->iova, cfi->fsynr, cfi->cbfrsynra, idx);
+		cfi->fsr, cfi->iova, cfi->fsynr0, cfi->cbfrsynra, idx);
 
 	dev_err(smmu->dev, "FSR    = %08x [%s%sFormat=%u%s%s%s%s%s%s%s%s], SID=0x%x\n",
 		cfi->fsr,
@@ -437,15 +444,15 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 		cfi->cbfrsynra);
 
 	dev_err(smmu->dev, "FSYNR0 = %08x [S1CBNDX=%u%s%s%s%s%s%s PLVL=%u]\n",
-		cfi->fsynr,
-		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr),
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
-		(cfi->fsynr & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
-		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr));
+		cfi->fsynr0,
+		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_S1CBNDX, cfi->fsynr0),
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_AFR) ? " AFR" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PTWF) ? " PTWF" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_NSATTR) ? " NSATTR" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_IND) ? " IND" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_PNU) ? " PNU" : "",
+		(cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR) ? " WNR" : "",
+		(u32)FIELD_GET(ARM_SMMU_CB_FSYNR0_PLVL, cfi->fsynr0));
 }
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
@@ -458,13 +465,13 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 	int idx = smmu_domain->cfg.cbndx;
 	int ret;
 
-	arm_smmu_read_context_fault_info(smmu, idx, &cfi);
+	arm_smmu_read_context_fault_info(smmu_domain, &cfi);
 
 	if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
 	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-		cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+		cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
 		arm_smmu_print_context_fault_info(smmu, idx, &cfi);
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index e2aeb511ae903302e3c15d2cf5f22e2a26ac2346..ef6915a0d9f62b0a1734a3ee57ea422615036094 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -543,12 +543,15 @@ int arm_mmu500_reset(struct arm_smmu_device *smmu);
 
 struct arm_smmu_context_fault_info {
 	unsigned long iova;
+	u64 ttbr0;
 	u32 fsr;
-	u32 fsynr;
+	u32 fsynr0;
+	u32 fsynr1;
 	u32 cbfrsynra;
+	u32 contextidr;
 };
 
-void arm_smmu_read_context_fault_info(struct arm_smmu_device *smmu, int idx,
+void arm_smmu_read_context_fault_info(struct arm_smmu_domain *smmu_domain,
 				      struct arm_smmu_context_fault_info *cfi);
 
 void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,

-- 
2.47.1



From cwabbott0 at gmail.com  Wed Mar 19 07:44:01 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:44:01 -0400
Subject: [PATCH v5 2/5] iommu/arm-smmu-qcom: Don't read fault registers
 directly
In-Reply-To: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
References: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-2-97561209dd8c@gmail.com>

In some cases drm/msm has to resume a stalled transaction directly in
its fault handler. Experimentally this doesn't work on SMMU500 if the
fault hasn't already been acknowledged by clearing FSR. Rather than
trying to clear FSR in msm's fault handler and implementing a
tricky handshake to avoid accidentally clearing FSR twice, we want to
clear FSR before calling the fault handlers, but this means that the
contents of registers can change underneath us in the fault handler and
msm currently uses a private function to read the register contents for
its own purposes in its fault handler, such as using the
implementation-defined FSYNR1 to determine which block caused the fault.
Fix this by making msm use the register values already read by arm-smmu
itself before clearing FSR rather than messing around with reading
registers directly.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +++++++++----------
 drivers/iommu/arm/arm-smmu/arm-smmu.c      | 14 +++++++-------
 drivers/iommu/arm/arm-smmu/arm-smmu.h      | 21 +++++++++++----------
 3 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 6372f3e25c4bc24cb52f9233095170e8aa510a53..186d6ad4fd1c990398df4dec53f4d58ada9e658c 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -62,16 +62,15 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie,
 		struct adreno_smmu_fault_info *info)
 {
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
-	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-
-	info->fsr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSR);
-	info->fsynr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR0);
-	info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1);
-	info->far = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_FAR);
-	info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
-	info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0);
-	info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR);
+	struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
+
+	info->fsr = cfi->fsr;
+	info->fsynr0 = cfi->fsynr0;
+	info->fsynr1 = cfi->fsynr1;
+	info->far = cfi->iova;
+	info->cbfrsynra = cfi->cbfrsynra;
+	info->ttbr0 = cfi->ttbr0;
+	info->contextidr = cfi->contextidr;
 }
 
 static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index a02078eb968b81a35c1c086ed7007ea2a453ef94..c7b5d7c093e71050d29a834c8d33125e96b04d81 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -457,26 +457,26 @@ void arm_smmu_print_context_fault_info(struct arm_smmu_device *smmu, int idx,
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 {
-	struct arm_smmu_context_fault_info cfi;
 	struct arm_smmu_domain *smmu_domain = dev;
+	struct arm_smmu_context_fault_info *cfi = &smmu_domain->cfi;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
 				      DEFAULT_RATELIMIT_BURST);
 	int idx = smmu_domain->cfg.cbndx;
 	int ret;
 
-	arm_smmu_read_context_fault_info(smmu_domain, &cfi);
+	arm_smmu_read_context_fault_info(smmu_domain, cfi);
 
-	if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT))
+	if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
-	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
-		cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
+	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
+		cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
-		arm_smmu_print_context_fault_info(smmu, idx, &cfi);
+		arm_smmu_print_context_fault_info(smmu, idx, cfi);
 
-	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi.fsr);
+	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index ef6915a0d9f62b0a1734a3ee57ea422615036094..ff84ce3b8d8567d3402e945e8277ca2a87df9a4e 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
 	ARM_SMMU_DOMAIN_NESTED,
 };
 
+struct arm_smmu_context_fault_info {
+	unsigned long iova;
+	u64 ttbr0;
+	u32 fsr;
+	u32 fsynr0;
+	u32 fsynr1;
+	u32 cbfrsynra;
+	u32 contextidr;
+};
+
 struct arm_smmu_domain {
 	struct arm_smmu_device		*smmu;
 	struct io_pgtable_ops		*pgtbl_ops;
@@ -380,6 +390,7 @@ struct arm_smmu_domain {
 	const struct iommu_flush_ops	*flush_ops;
 	struct arm_smmu_cfg		cfg;
 	enum arm_smmu_domain_stage	stage;
+	struct arm_smmu_context_fault_info cfi;
 	struct mutex			init_mutex; /* Protects smmu pointer */
 	spinlock_t			cb_lock; /* Serialises ATS1* ops and TLB syncs */
 	struct iommu_domain		domain;
@@ -541,16 +552,6 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
 void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
 int arm_mmu500_reset(struct arm_smmu_device *smmu);
 
-struct arm_smmu_context_fault_info {
-	unsigned long iova;
-	u64 ttbr0;
-	u32 fsr;
-	u32 fsynr0;
-	u32 fsynr1;
-	u32 cbfrsynra;
-	u32 contextidr;
-};
-
 void arm_smmu_read_context_fault_info(struct arm_smmu_domain *smmu_domain,
 				      struct arm_smmu_context_fault_info *cfi);
 

-- 
2.47.1



From cwabbott0 at gmail.com  Wed Mar 19 07:44:02 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:44:02 -0400
Subject: [PATCH v5 3/5] iommu/arm-smmu: Fix spurious interrupts with
 stall-on-fault
In-Reply-To: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
References: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-3-97561209dd8c@gmail.com>

On some SMMUv2 implementations, including MMU-500, SMMU_CBn_FSR.SS
asserts an interrupt. The only way to clear that bit is to resume the
transaction by writing SMMU_CBn_RESUME, but typically resuming the
transaction requires complex operations (copying in pages, etc.) that
can't be done in IRQ context. drm/msm already has a problem, because
its fault handler sometimes schedules a job to dump the GPU state and
doesn't resume translation until this is complete.

Work around this by disabling context fault interrupts until after the
transaction is resumed. Because other context banks can share an IRQ
line, we may still get an interrupt intended for another context bank,
but in this case only SMMU_CBn_FSR.SS will be asserted and we can skip
it assuming that interrupts are disabled which is accomplished by
removing the bit from ARM_SMMU_CB_FSR_FAULT. SMMU_CBn_FSR.SS won't be
asserted unless an external user enabled stall-on-fault, and they are
expected to resume the translation and re-enable interrupts.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by Robin Murphy <robin.murphy at arm.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 15 ++++++++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.c      | 41 +++++++++++++++++++++++++++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.h      |  1 -
 3 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 186d6ad4fd1c990398df4dec53f4d58ada9e658c..a428e53add08d451fb2152e3ab80e0fba936e214 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -90,12 +90,25 @@ static void qcom_adreno_smmu_resume_translation(const void *cookie, bool termina
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
 	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	u32 reg = 0;
+	u32 reg = 0, sctlr;
+	unsigned long flags;
 
 	if (terminate)
 		reg |= ARM_SMMU_RESUME_TERMINATE;
 
+	spin_lock_irqsave(&smmu_domain->cb_lock, flags);
+
 	arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg);
+
+	/*
+	 * Re-enable interrupts after they were disabled by
+	 * arm_smmu_context_fault().
+	 */
+	sctlr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
+	sctlr |= ARM_SMMU_SCTLR_CFIE;
+	arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, sctlr);
+
+	spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
 }
 
 #define QCOM_ADRENO_SMMU_GPU_SID 0
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index c7b5d7c093e71050d29a834c8d33125e96b04d81..9927f3431a2eab913750e6079edc6393d1938c98 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -470,13 +470,52 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 	if (!(cfi->fsr & ARM_SMMU_CB_FSR_FAULT))
 		return IRQ_NONE;
 
+	/*
+	 * On some implementations FSR.SS asserts a context fault
+	 * interrupt. We do not want this behavior, because resolving the
+	 * original context fault typically requires operations that cannot be
+	 * performed in IRQ context but leaving the stall unacknowledged will
+	 * immediately lead to another spurious interrupt as FSR.SS is still
+	 * set. Work around this by disabling interrupts for this context bank.
+	 * It's expected that interrupts are re-enabled after resuming the
+	 * translation.
+	 *
+	 * We have to do this before report_iommu_fault() so that we don't
+	 * leave interrupts disabled in case the downstream user decides the
+	 * fault can be resolved inside its fault handler.
+	 *
+	 * There is a possible race if there are multiple context banks sharing
+	 * the same interrupt and both signal an interrupt in between writing
+	 * RESUME and SCTLR. We could disable interrupts here before we
+	 * re-enable them in the resume handler, leaving interrupts enabled.
+	 * Lock the write to serialize it with the resume handler.
+	 */
+	if (cfi->fsr & ARM_SMMU_CB_FSR_SS) {
+		u32 val;
+
+		spin_lock(&smmu_domain->cb_lock);
+		val = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_SCTLR);
+		val &= ~ARM_SMMU_SCTLR_CFIE;
+		arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, val);
+		spin_unlock(&smmu_domain->cb_lock);
+	}
+
+	/*
+	 * The SMMUv2 architecture specification says that if stall-on-fault is
+	 * enabled the correct sequence is to write to SMMU_CBn_FSR to clear
+	 * the fault and then write to SMMU_CBn_RESUME. Clear the interrupt
+	 * first before running the user's fault handler to make sure we follow
+	 * this sequence. It should be ok if there is another fault in the
+	 * meantime because we have already read the fault info.
+	 */
+	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
+
 	ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi->iova,
 		cfi->fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
 
 	if (ret == -ENOSYS && __ratelimit(&rs))
 		arm_smmu_print_context_fault_info(smmu, idx, cfi);
 
-	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, cfi->fsr);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index ff84ce3b8d8567d3402e945e8277ca2a87df9a4e..5fe8e482457f905529a08aea14ea5656d3e31328 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -214,7 +214,6 @@ enum arm_smmu_cbar_type {
 					 ARM_SMMU_CB_FSR_TLBLKF)
 
 #define ARM_SMMU_CB_FSR_FAULT		(ARM_SMMU_CB_FSR_MULTI |	\
-					 ARM_SMMU_CB_FSR_SS |		\
 					 ARM_SMMU_CB_FSR_UUT |		\
 					 ARM_SMMU_CB_FSR_EF |		\
 					 ARM_SMMU_CB_FSR_PF |		\

-- 
2.47.1



From cwabbott0 at gmail.com  Wed Mar 19 07:44:03 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:44:03 -0400
Subject: [PATCH v5 4/5] iommu/arm-smmu-qcom: Make set_stall work when the
 device is on
In-Reply-To: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
References: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-4-97561209dd8c@gmail.com>

Up until now we have only called the set_stall callback during
initialization when the device is off. But we will soon start calling it
to temporarily disable stall-on-fault when the device is on, so handle
that by checking if the device is on and writing SCTLR.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 33 +++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index a428e53add08d451fb2152e3ab80e0fba936e214..f6bb405573be0ed480a2587a5a780dd711b8d2aa 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -77,12 +77,39 @@ static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
 {
 	struct arm_smmu_domain *smmu_domain = (void *)cookie;
 	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
+	u32 mask = BIT(cfg->cbndx);
+	bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
+	unsigned long flags;
 
 	if (enabled)
-		qsmmu->stall_enabled |= BIT(cfg->cbndx);
+		qsmmu->stall_enabled |= mask;
 	else
-		qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
+		qsmmu->stall_enabled &= ~mask;
+
+	/*
+	 * If the device is on and we changed the setting, update the register.
+	 * The spec pseudocode says that CFCFG is resampled after a fault, and
+	 * we believe that no implementations cache it in the TLB, so it should
+	 * be safe to change it without a TLB invalidation.
+	 */
+	if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
+		spin_lock_irqsave(&smmu_domain->cb_lock, flags);
+
+		u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
+
+		if (enabled)
+			reg |= ARM_SMMU_SCTLR_CFCFG;
+		else
+			reg &= ~ARM_SMMU_SCTLR_CFCFG;
+
+		arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
+
+		spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
+
+		pm_runtime_put_autosuspend(smmu->dev);
+	}
 }
 
 static void qcom_adreno_smmu_resume_translation(const void *cookie, bool terminate)

-- 
2.47.1



From cwabbott0 at gmail.com  Wed Mar 19 07:44:04 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:44:04 -0400
Subject: [PATCH v5 5/5] drm/msm: Temporarily disable stall-on-fault after a
 page fault
In-Reply-To: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
References: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-5-97561209dd8c@gmail.com>

When things go wrong, the GPU is capable of quickly generating millions
of faulting translation requests per second. When that happens, in the
stall-on-fault model each access will stall until it wins the race to
signal the fault and then the RESUME register is written. This slows
processing page faults to a crawl as the GPU can generate faults much
faster than the CPU can acknowledge them. It also means that all
available resources in the SMMU are saturated waiting for the stalled
transactions, so that other transactions such as transactions generated
by the GMU, which shares translation resources with the GPU, cannot
proceed. This causes a GMU watchdog timeout, which leads to a failed
reset because GX cannot collapse when there is a transaction pending and
a permanently hung GPU.

On older platforms with qcom,smmu-v2, it seems that when one transaction
is stalled subsequent faulting transactions are terminated, which avoids
this problem, but the MMU-500 follows the spec here.

To work around these problems, disable stall-on-fault as soon as we get a
page fault until a cooldown period after pagefaults stop. This allows
the GMU some guaranteed time to continue working. We only use
stall-on-fault to halt the GPU while we collect a devcoredump and we
always terminate the transaction afterward, so it's fine to miss some
subsequent page faults. We also keep it disabled so long as the current
devcoredump hasn't been deleted, because in that case we likely won't
capture another one if there's a fault.

After this commit HFI messages still occasionally time out, because the
crashdump handler doesn't run fast enough to let the GMU resume, but the
driver seems to recover from it. This will probably go away after the
HFI timeout is increased.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  4 ++++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 42 ++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h | 26 ++++++++++++++++++++
 drivers/gpu/drm/msm/msm_iommu.c         |  9 +++++++
 drivers/gpu/drm/msm/msm_mmu.h           |  1 +
 6 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 71dca78cd7a5324e9ff5b14f173e2209fa42e196..670141531112c9d29cef8ef1fd51b74759fdd6d2 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
 		ring->cur_ctx_seqno = 0;
 		a5xx_submit_in_rb(gpu, submit);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 0ae29a7c8a4d3f74236a35cc919f69d5c0a384a0..5a34cd2109a2d74c92841448a61ccb0d4f34e264 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -212,6 +212,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	a6xx_set_pagetable(a6xx_gpu, ring, submit);
 
 	get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
@@ -335,6 +337,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	struct msm_ringbuffer *ring = submit->ring;
 	unsigned int i, ibs = 0;
 
+	adreno_check_and_reenable_stall(adreno_gpu);
+
 	/*
 	 * Toggle concurrent binning for pagetable switch and set the thread to
 	 * BR since only it can execute the pagetable switch packets.
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 1238f326597808eb28b4c6822cbd41a26e555eb9..bac586101dc0494f46b069a8440a45825dfe9b5e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -246,16 +246,53 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
 	return SZ_4G;
 }
 
+void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
+{
+	struct msm_gpu *gpu = &adreno_gpu->base;
+	unsigned long flags;
+
+	/*
+	 * Wait until the cooldown period has passed and we would actually
+	 * collect a crashdump to re-enable stall-on-fault.
+	 */
+	spin_lock_irqsave(&adreno_gpu->fault_stall_lock, flags);
+	if (!adreno_gpu->stall_enabled &&
+			ktime_after(ktime_get(), adreno_gpu->stall_reenable_time) &&
+			!READ_ONCE(gpu->crashstate)) {
+		adreno_gpu->stall_enabled = true;
+
+		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
+	}
+	spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, flags);
+}
+
 #define ARM_SMMU_FSR_TF                 BIT(1)
 #define ARM_SMMU_FSR_PF			BIT(3)
 #define ARM_SMMU_FSR_EF			BIT(4)
+#define ARM_SMMU_FSR_SS			BIT(30)
 
 int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
 			 struct adreno_smmu_fault_info *info, const char *block,
 			 u32 scratch[4])
 {
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
 	const char *type = "UNKNOWN";
-	bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
+	bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
+		!READ_ONCE(gpu->crashstate);
+	unsigned long irq_flags;
+
+	/*
+	 * In case there is a subsequent storm of pagefaults, disable
+	 * stall-on-fault for at least half a second.
+	 */
+	spin_lock_irqsave(&adreno_gpu->fault_stall_lock, irq_flags);
+	if (adreno_gpu->stall_enabled) {
+		adreno_gpu->stall_enabled = false;
+
+		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
+	}
+	adreno_gpu->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
+	spin_unlock_irqrestore(&adreno_gpu->fault_stall_lock, irq_flags);
 
 	/*
 	 * If we aren't going to be resuming later from fault_worker, then do
@@ -1143,6 +1180,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 		adreno_gpu->info->inactive_period);
 	pm_runtime_use_autosuspend(dev);
 
+	spin_lock_init(&adreno_gpu->fault_stall_lock);
+	adreno_gpu->stall_enabled = true;
+
 	return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
 			gpu_name, &adreno_gpu_config);
 }
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index dcf454629ce037b2a8274a6699674ad754ce1f07..868d22fde1396def35e2f46bc2b2f4eff611d8fd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -205,6 +205,30 @@ struct adreno_gpu {
 	/* firmware: */
 	const struct firmware *fw[ADRENO_FW_MAX];
 
+	/**
+	 * @fault_stall_lock:
+	 *
+	 * Serialize changes to stall-on-fault state.
+	 */
+	spinlock_t fault_stall_lock;
+
+	/**
+	 * @fault_stall_reenable_time:
+	 *
+	 * If stall_enabled is false, when to reenable stall-on-fault.
+	 * Protected by @fault_stall_lock.
+	 */
+	ktime_t stall_reenable_time;
+
+	/**
+	 * @stall_enabled:
+	 *
+	 * Whether stall-on-fault is currently enabled. Protected by
+	 * @fault_stall_lock.
+	 */
+	bool stall_enabled;
+
+
 	struct {
 		/**
 		 * @rgb565_predicator: Unknown, introduced with A650 family,
@@ -629,6 +653,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
 			 struct adreno_smmu_fault_info *info, const char *block,
 			 u32 scratch[4]);
 
+void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
+
 int adreno_read_speedbin(struct device *dev, u32 *speedbin);
 
 /*
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 2a94e82316f95c5f9dcc37ef0a4664a29e3492b2..8d5380e6dcc217c7c209b51527bf15748b3ada71 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -351,6 +351,14 @@ static void msm_iommu_resume_translation(struct msm_mmu *mmu)
 		adreno_smmu->resume_translation(adreno_smmu->cookie, true);
 }
 
+static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
+{
+	struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
+
+	if (adreno_smmu->set_stall)
+		adreno_smmu->set_stall(adreno_smmu->cookie, enable);
+}
+
 static void msm_iommu_detach(struct msm_mmu *mmu)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
@@ -399,6 +407,7 @@ static const struct msm_mmu_funcs funcs = {
 		.unmap = msm_iommu_unmap,
 		.destroy = msm_iommu_destroy,
 		.resume_translation = msm_iommu_resume_translation,
+		.set_stall = msm_iommu_set_stall,
 };
 
 struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 88af4f490881f2a6789ae2d03e1c02d10046331a..2694a356a17904e7572b767b16ed0cee806406cf 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -16,6 +16,7 @@ struct msm_mmu_funcs {
 	int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
 	void (*destroy)(struct msm_mmu *mmu);
 	void (*resume_translation)(struct msm_mmu *mmu);
+	void (*set_stall)(struct msm_mmu *mmu, bool enable);
 };
 
 enum msm_mmu_type {

-- 
2.47.1



From francesco at dolcini.it  Wed Mar 19 07:51:14 2025
From: francesco at dolcini.it (Francesco Dolcini)
Date: Wed, 19 Mar 2025 15:51:14 +0100
Subject: [PATCH v1] i2c: lpi2c: implement master_xfer_atomic callback
Message-ID: <20250319145114.50771-1-francesco@dolcini.it>

From: Emanuele Ghidoli <emanuele.ghidoli at toradex.com>

Rework the read and write code paths in the driver to support operation
in atomic contexts. To achieve this, the driver must not rely on IRQs
or perform any scheduling, e.g., via a sleep or schedule routine. Even
jiffies do not advance in atomic contexts, so timeouts based on them
are substituted with delays.

Implement atomic, sleep-free, and IRQ-less operation. This increases
complexity but is necessary for atomic I2C transfers required by some
hardware configurations, e.g., to trigger reboots on an external PMIC chip.

Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli at toradex.com>
Signed-off-by: Francesco Dolcini <francesco.dolcini at toradex.com>
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 258 +++++++++++++++++++----------
 1 file changed, 173 insertions(+), 85 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 0d4b3935e687..f34b6f07e9a4 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -187,36 +188,35 @@ struct lpi2c_imx_struct {
 	struct i2c_client	*target;
 };
 
+#define READL_POLL_TIMEOUT(atomic, addr, val, cond, delay_us, timeout_us) \
+	(atomic ? readl_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) : \
+		  readl_poll_timeout(addr, val, cond, delay_us, timeout_us))
+
 static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
 			      unsigned int enable)
 {
 	writel(enable, lpi2c_imx->base + LPI2C_MIER);
 }
 
-static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
+static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
 {
-	unsigned long orig_jiffies = jiffies;
 	unsigned int temp;
 
-	while (1) {
-		temp = readl(lpi2c_imx->base + LPI2C_MSR);
+	READL_POLL_TIMEOUT(atomic, lpi2c_imx->base + LPI2C_MSR, temp,
+			   temp & (MSR_ALF | MSR_BBF | MSR_MBF), 1, 500000);
 
-		/* check for arbitration lost, clear if set */
-		if (temp & MSR_ALF) {
-			writel(temp, lpi2c_imx->base + LPI2C_MSR);
-			return -EAGAIN;
-		}
-
-		if (temp & (MSR_BBF | MSR_MBF))
-			break;
+	/* check for arbitration lost, clear if set */
+	if (temp & MSR_ALF) {
+		writel(temp, lpi2c_imx->base + LPI2C_MSR);
+		return -EAGAIN;
+	}
 
-		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
-			dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
-			if (lpi2c_imx->adapter.bus_recovery_info)
-				i2c_recover_bus(&lpi2c_imx->adapter);
-			return -ETIMEDOUT;
-		}
-		schedule();
+	/* check for bus not busy */
+	if (!(temp & (MSR_BBF | MSR_MBF))) {
+		dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
+		if (lpi2c_imx->adapter.bus_recovery_info)
+			i2c_recover_bus(&lpi2c_imx->adapter);
+		return -ETIMEDOUT;
 	}
 
 	return 0;
@@ -242,7 +242,7 @@ static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx)
 }
 
 static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
-			   struct i2c_msg *msgs)
+			   struct i2c_msg *msgs, bool atomic)
 {
 	unsigned int temp;
 
@@ -254,30 +254,23 @@ static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
 	temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8);
 	writel(temp, lpi2c_imx->base + LPI2C_MTDR);
 
-	return lpi2c_imx_bus_busy(lpi2c_imx);
+	return lpi2c_imx_bus_busy(lpi2c_imx, atomic);
 }
 
-static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
+static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
 {
-	unsigned long orig_jiffies = jiffies;
 	unsigned int temp;
 
 	writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
 
-	do {
-		temp = readl(lpi2c_imx->base + LPI2C_MSR);
-		if (temp & MSR_SDF)
-			break;
-
-		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
-			dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
-			if (lpi2c_imx->adapter.bus_recovery_info)
-				i2c_recover_bus(&lpi2c_imx->adapter);
-			break;
-		}
-		schedule();
+	READL_POLL_TIMEOUT(atomic, lpi2c_imx->base + LPI2C_MSR, temp,
+			   temp & MSR_SDF, 1, 500000);
 
-	} while (1);
+	if (!(temp & MSR_SDF)) {
+		dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
+		if (lpi2c_imx->adapter.bus_recovery_info)
+			i2c_recover_bus(&lpi2c_imx->adapter);
+	}
 }
 
 /* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
@@ -391,28 +384,31 @@ static int lpi2c_imx_pio_msg_complete(struct lpi2c_imx_struct *lpi2c_imx)
 	return time_left ? 0 : -ETIMEDOUT;
 }
 
-static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
+static u32 txfifo_cnt(struct lpi2c_imx_struct *lpi2c_imx)
 {
-	unsigned long orig_jiffies = jiffies;
-	u32 txcnt;
+	return readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+}
 
-	do {
-		txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
+{
+	unsigned int temp;
+	int err;
 
-		if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) {
-			dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
-			return -EIO;
-		}
+	err = READL_POLL_TIMEOUT(atomic, lpi2c_imx->base + LPI2C_MSR, temp,
+				 (temp & MSR_NDF) || !txfifo_cnt(lpi2c_imx),
+				 1, 500000);
 
-		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
-			dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
-			if (lpi2c_imx->adapter.bus_recovery_info)
-				i2c_recover_bus(&lpi2c_imx->adapter);
-			return -ETIMEDOUT;
-		}
-		schedule();
+	if (temp & MSR_NDF) {
+		dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
+		return -EIO;
+	}
 
-	} while (txcnt);
+	if (err) {
+		dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
+		if (lpi2c_imx->adapter.bus_recovery_info)
+			i2c_recover_bus(&lpi2c_imx->adapter);
+		return -ETIMEDOUT;
+	}
 
 	return 0;
 }
@@ -436,7 +432,7 @@ static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct *lpi2c_imx)
 	writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR);
 }
 
-static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx)
+static bool lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
 {
 	unsigned int data, txcnt;
 
@@ -451,13 +447,19 @@ static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx)
 		txcnt++;
 	}
 
-	if (lpi2c_imx->delivered < lpi2c_imx->msglen)
-		lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE);
-	else
+	if (lpi2c_imx->delivered < lpi2c_imx->msglen) {
+		if (!atomic)
+			lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE);
+		return false;
+	}
+
+	if (!atomic)
 		complete(&lpi2c_imx->complete);
+
+	return true;
 }
 
-static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
+static bool lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
 {
 	unsigned int blocklen, remaining;
 	unsigned int temp, data;
@@ -482,8 +484,9 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
 	remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
 
 	if (!remaining) {
-		complete(&lpi2c_imx->complete);
-		return;
+		if (!atomic)
+			complete(&lpi2c_imx->complete);
+		return true;
 	}
 
 	/* not finished, still waiting for rx data */
@@ -501,7 +504,10 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
 		writel(temp, lpi2c_imx->base + LPI2C_MTDR);
 	}
 
-	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
+	if (!atomic)
+		lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
+
+	return false;
 }
 
 static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
@@ -509,11 +515,29 @@ static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
 {
 	lpi2c_imx->tx_buf = msgs->buf;
 	lpi2c_imx_set_tx_watermark(lpi2c_imx);
-	lpi2c_imx_write_txfifo(lpi2c_imx);
+	lpi2c_imx_write_txfifo(lpi2c_imx, false);
 }
 
-static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
-			   struct i2c_msg *msgs)
+static int lpi2c_imx_write_atomic(struct lpi2c_imx_struct *lpi2c_imx,
+				  struct i2c_msg *msgs)
+{
+	u32 temp;
+	int err;
+
+	lpi2c_imx->tx_buf = msgs->buf;
+
+	err = READL_POLL_TIMEOUT(true, lpi2c_imx->base + LPI2C_MSR, temp,
+				 (temp & MSR_NDF) || lpi2c_imx_write_txfifo(lpi2c_imx, true),
+				 5, 1000000);
+
+	if (temp & MSR_NDF)
+		return -EIO;
+
+	return err;
+}
+
+static void lpi2c_imx_read_init(struct lpi2c_imx_struct *lpi2c_imx,
+				struct i2c_msg *msgs)
 {
 	unsigned int temp;
 
@@ -524,8 +548,43 @@ static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
 	temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1;
 	temp |= (RECV_DATA << 8);
 	writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+}
+
+static bool lpi2c_imx_read_chunk_atomic(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	u32 rxcnt;
+
+	rxcnt = (readl(lpi2c_imx->base + LPI2C_MFSR) >> 16) & 0xFF;
+	if (!rxcnt)
+		return false;
+
+	if (!lpi2c_imx_read_rxfifo(lpi2c_imx, true))
+		return false;
 
-	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
+	return true;
+}
+
+static int lpi2c_imx_read_atomic(struct lpi2c_imx_struct *lpi2c_imx,
+				 struct i2c_msg *msgs)
+{
+	u32 temp;
+	int tmo_us;
+
+	tmo_us = 1000000;
+	do {
+		if (lpi2c_imx_read_chunk_atomic(lpi2c_imx))
+			return 0;
+
+		temp = readl(lpi2c_imx->base + LPI2C_MSR);
+
+		if (temp & MSR_NDF)
+			return -EIO;
+
+		udelay(100);
+		tmo_us -= 100;
+	} while (tmo_us > 0);
+
+	return -ETIMEDOUT;
 }
 
 static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct i2c_msg *msg)
@@ -545,14 +604,27 @@ static int lpi2c_imx_pio_xfer(struct lpi2c_imx_struct *lpi2c_imx,
 {
 	reinit_completion(&lpi2c_imx->complete);
 
-	if (msg->flags & I2C_M_RD)
-		lpi2c_imx_read(lpi2c_imx, msg);
-	else
+	if (msg->flags & I2C_M_RD) {
+		lpi2c_imx_read_init(lpi2c_imx, msg);
+		lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
+	} else {
 		lpi2c_imx_write(lpi2c_imx, msg);
+	}
 
 	return lpi2c_imx_pio_msg_complete(lpi2c_imx);
 }
 
+static int lpi2c_imx_pio_xfer_atomic(struct lpi2c_imx_struct *lpi2c_imx,
+				     struct i2c_msg *msg)
+{
+	if (msg->flags & I2C_M_RD) {
+		lpi2c_imx_read_init(lpi2c_imx, msg);
+		return lpi2c_imx_read_atomic(lpi2c_imx, msg);
+	}
+
+	return lpi2c_imx_write_atomic(lpi2c_imx, msg);
+}
+
 static int lpi2c_imx_dma_timeout_calculate(struct lpi2c_imx_struct *lpi2c_imx)
 {
 	unsigned long time = 0;
@@ -947,8 +1019,8 @@ static int lpi2c_imx_dma_xfer(struct lpi2c_imx_struct *lpi2c_imx,
 	return ret;
 }
 
-static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
-			  struct i2c_msg *msgs, int num)
+static int lpi2c_imx_xfer_common(struct i2c_adapter *adapter,
+				 struct i2c_msg *msgs, int num, bool atomic)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
 	unsigned int temp;
@@ -959,7 +1031,7 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 		return result;
 
 	for (i = 0; i < num; i++) {
-		result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
+		result = lpi2c_imx_start(lpi2c_imx, &msgs[i], atomic);
 		if (result)
 			goto disable;
 
@@ -971,28 +1043,33 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 		lpi2c_imx->tx_buf = NULL;
 		lpi2c_imx->delivered = 0;
 		lpi2c_imx->msglen = msgs[i].len;
-		init_completion(&lpi2c_imx->complete);
 
-		if (is_use_dma(lpi2c_imx, &msgs[i])) {
-			result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]);
-			if (result && lpi2c_imx->dma->using_pio_mode)
-				result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
+		if (atomic) {
+			result = lpi2c_imx_pio_xfer_atomic(lpi2c_imx, &msgs[i]);
 		} else {
-			result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
+			init_completion(&lpi2c_imx->complete);
+
+			if (is_use_dma(lpi2c_imx, &msgs[i])) {
+				result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]);
+				if (result && lpi2c_imx->dma->using_pio_mode)
+					result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
+			} else {
+				result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
+			}
 		}
 
 		if (result)
 			goto stop;
 
 		if (!(msgs[i].flags & I2C_M_RD)) {
-			result = lpi2c_imx_txfifo_empty(lpi2c_imx);
+			result = lpi2c_imx_txfifo_empty(lpi2c_imx, atomic);
 			if (result)
 				goto stop;
 		}
 	}
 
 stop:
-	lpi2c_imx_stop(lpi2c_imx);
+	lpi2c_imx_stop(lpi2c_imx, atomic);
 
 	temp = readl(lpi2c_imx->base + LPI2C_MSR);
 	if ((temp & MSR_NDF) && !result)
@@ -1008,6 +1085,16 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 	return (result < 0) ? result : num;
 }
 
+static int lpi2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+	return lpi2c_imx_xfer_common(adapter, msgs, num, false);
+}
+
+static int lpi2c_imx_xfer_atomic(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+	return lpi2c_imx_xfer_common(adapter, msgs, num, true);
+}
+
 static irqreturn_t lpi2c_imx_target_isr(struct lpi2c_imx_struct *lpi2c_imx,
 					u32 ssr, u32 sier_filter)
 {
@@ -1070,9 +1157,9 @@ static irqreturn_t lpi2c_imx_master_isr(struct lpi2c_imx_struct *lpi2c_imx)
 	if (temp & MSR_NDF)
 		complete(&lpi2c_imx->complete);
 	else if (temp & MSR_RDF)
-		lpi2c_imx_read_rxfifo(lpi2c_imx);
+		lpi2c_imx_read_rxfifo(lpi2c_imx, false);
 	else if (temp & MSR_TDF)
-		lpi2c_imx_write_txfifo(lpi2c_imx);
+		lpi2c_imx_write_txfifo(lpi2c_imx, false);
 
 	return IRQ_HANDLED;
 }
@@ -1268,10 +1355,11 @@ static u32 lpi2c_imx_func(struct i2c_adapter *adapter)
 }
 
 static const struct i2c_algorithm lpi2c_imx_algo = {
-	.master_xfer	= lpi2c_imx_xfer,
-	.functionality	= lpi2c_imx_func,
-	.reg_target	= lpi2c_imx_register_target,
-	.unreg_target	= lpi2c_imx_unregister_target,
+	.master_xfer		= lpi2c_imx_xfer,
+	.master_xfer_atomic	= lpi2c_imx_xfer_atomic,
+	.functionality		= lpi2c_imx_func,
+	.reg_target		= lpi2c_imx_register_target,
+	.unreg_target		= lpi2c_imx_unregister_target,
 };
 
 static const struct of_device_id lpi2c_imx_of_match[] = {
-- 
2.39.5



From oleg at redhat.com  Wed Mar 19 07:51:13 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Wed, 19 Mar 2025 15:51:13 +0100
Subject: [PATCH 6/7] uprobes: Allow the use of uprobe_warn() in arch code
In-Reply-To: <20250318204841.373116-7-jeremy.linton@arm.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-7-jeremy.linton@arm.com>
Message-ID: <20250319145057.GA10753@redhat.com>

On 03/18, Jeremy Linton wrote:
>
> --- a/include/linux/uprobes.h
> +++ b/include/linux/uprobes.h
> @@ -185,6 +185,7 @@ struct uprobes_state {
>  };
>  
>  extern void __init uprobes_init(void);
> +extern void uprobe_warn(struct task_struct *t, const char *msg);
>  extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>  extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>  extern bool is_swbp_insn(uprobe_opcode_t *insn);
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index b4ca8898fe17..613c1c76f227 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -118,7 +118,7 @@ struct xol_area {
>  	unsigned long 			vaddr;		/* Page(s) of instruction slots */
>  };
>  
> -static void uprobe_warn(struct task_struct *t, const char *msg)
> +void uprobe_warn(struct task_struct *t, const char *msg)
>  {
>  	pr_warn("uprobe: %s:%d failed to %s\n", current->comm, current->pid, msg);
>  }

Oh, no, please don't.

uprobe_warn() is ugly and needs changes. If nothing else it doesn't even use
its "t" argument.

Oleg.



From andersson at kernel.org  Wed Mar 19 07:43:53 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Wed, 19 Mar 2025 09:43:53 -0500
Subject: [GIT PULL] Qualcomm Arm64 defconfig updates for v6.15
Message-ID: <20250319144354.2281720-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm64-defconfig-for-6.15

for you to fetch changes up to dd20903cc09ac40e71096370a9564e6523e87c22:

  arm64: defconfig: Enable USB retimer and redriver (2025-03-19 08:46:36 -0500)

----------------------------------------------------------------
Qualcomm Arm64 defconfig updates for v6.15

Explicitly enable the DRM_DISPLAY_CONNECTOR module, as this is used by a
variety of boards.

Enable retimer and redriver drivers used in the USB configuration of a
variety of Qualcomm X Elite-based devices. Enable the NSS clock
controller driver for IPQ9574, the new Iris video encoder/decoder driver
and it's clock controller, as well as the QCM2290 GPU clocck ontroller.

----------------------------------------------------------------
Bjorn Andersson (1):
      arm64: defconfig: Enable USB retimer and redriver

Devi Priya (1):
      arm64: defconfig: Build NSS Clock Controller driver for IPQ9574

Dmitry Baryshkov (2):
      arm64: defconfig: Enable Qualcomm QCM2290 GPU clock controller
      arm64: defconfig: enable DRM_DISPLAY_CONNECTOR as a module

Neil Armstrong (1):
      arm64: defconfig: enable Qualcomm IRIS & VIDEOCC_8550 as module

 arch/arm64/configs/defconfig | 7 +++++++
 1 file changed, 7 insertions(+)


From cwabbott0 at gmail.com  Wed Mar 19 07:43:59 2025
From: cwabbott0 at gmail.com (Connor Abbott)
Date: Wed, 19 Mar 2025 10:43:59 -0400
Subject: [PATCH v5 0/5] iommu/arm-smmu, drm/msm: Fixes for stall-on-fault
Message-ID: <20250319-msm-gpu-fault-fixes-next-v5-0-97561209dd8c@gmail.com>

drm/msm uses the stall-on-fault model to record the GPU state on the
first GPU page fault to help debugging. On systems where the GPU is
paired with a MMU-500, there were two problems:

1. The MMU-500 doesn't de-assert its interrupt line until the fault is
   resumed, which led to a storm of interrupts until the fault handler
   was called. If we got unlucky and the fault handler was on the same
   CPU as the interrupt, there was a deadlock.
2. The GPU is capable of generating page faults much faster than we can
   resume them. GMU (GPU Management Unit) shares the same context bank
   as the GPU, so if there was a sudden spurt of page faults it would be
   effectively starved and would trigger a watchdog reset, made even
   worse because the GPU cannot be reset while there's a pending
   transaction leaving the GPU permanently wedged.

Patches 1-3 fixes the first problem and is independent of the rest of the
series. Patch 5 fixes the second problem and is dependent on patch 4, so
there will have to be some cross-tree coordination.

I've rebased this series on the latest linux-next to avoid rebase
troubles.

Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
---
Changes in v5:
- Don't read CONTEXTIDR for stage 2 domains.
- Clarify that we don't need TLB invalidation when changing
  SMMU_CBn_SCTLR.CFCFG.
- Link to v4: https://lore.kernel.org/r/20250304-msm-gpu-fault-fixes-next-v4-0-be14be37f4c3 at gmail.com

Changes in v4:
- Add patches 1-2, which fix reading registers in drm/msm when
  acknowledging the fault early. This was Robin's preferred solution
  compared to making drm/msm's fault handler tell arm-smmu to resume the
  fault.
- Link to v3: https://lore.kernel.org/r/20250122-msm-gpu-fault-fixes-next-v3-0-0afa00158521 at gmail.com

Changes in v3:
- Acknowledge the fault before resuming the transaction in patch 1.
- Add suggested extra context to commit messages.
- Link to v2: https://lore.kernel.org/r/20250120-msm-gpu-fault-fixes-next-v2-0-d636c4027042 at gmail.com

Changes in v2:
- Remove unnecessary _irqsave when locking in IRQ handler (Robin)
- Reuse existing spinlock for CFIE manipulation (Robin)
- Lock CFCFG manipulation against concurrent CFIE manipulation
- Don't use timer to re-enable stall-on-fault. (Rob)
- Use more descriptive name for the function that re-enables
  stall-on-fault if the cooldown period has ended. (Rob)
- Link to v1: https://lore.kernel.org/r/20250117-msm-gpu-fault-fixes-next-v1-0-bc9b332b5d0b at gmail.com

---
Connor Abbott (5):
      iommu/arm-smmu: Save additional information on context fault
      iommu/arm-smmu-qcom: Don't read fault registers directly
      iommu/arm-smmu: Fix spurious interrupts with stall-on-fault
      iommu/arm-smmu-qcom: Make set_stall work when the device is on
      drm/msm: Temporarily disable stall-on-fault after a page fault

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c            |  2 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c            |  4 ++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c          | 42 +++++++++++-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h          | 26 ++++++++
 drivers/gpu/drm/msm/msm_iommu.c                  |  9 +++
 drivers/gpu/drm/msm/msm_mmu.h                    |  1 +
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  6 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c       | 67 +++++++++++++++----
 drivers/iommu/arm/arm-smmu/arm-smmu.c            | 84 ++++++++++++++++++------
 drivers/iommu/arm/arm-smmu/arm-smmu.h            | 21 +++---
 10 files changed, 216 insertions(+), 46 deletions(-)
---
base-commit: 866e43b945bf98f8e807dfa45eca92f931f3a032
change-id: 20250117-msm-gpu-fault-fixes-next-96e3098023e1

Best regards,
-- 
Connor Abbott <cwabbott0 at gmail.com>



From mark.rutland at arm.com  Wed Mar 19 07:55:24 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 19 Mar 2025 14:55:24 +0000
Subject: Fast model boot failure with Linux next-20250312
In-Reply-To: <CA+G9fYvPu+MQKhYyPZSSDpAn-zhRGmeHQ8hJksT_cdDdxfbB-g@mail.gmail.com>
References: <CA+G9fYvPu+MQKhYyPZSSDpAn-zhRGmeHQ8hJksT_cdDdxfbB-g@mail.gmail.com>
Message-ID: <Z9ra3I2axii2HRVb@J2N7QTR9R3>

On Wed, Mar 19, 2025 at 08:07:47PM +0530, Naresh Kamboju wrote:
> Regressions on the arm64 Fast Model (FVP-AEMvA) caused boot failures starting
> with Linux next-20250312 and persisting through next-20250319.
> 
> First seen on the next-20250312
>  Good: next-20250311
>  Bad:  next-20250312 .. next-20250319
> 
> Regressions found on FVP:
>  - boot
> 
> Regression Analysis:
>  - New regression? Yes
>  - Reproducible? Yes
> 
> Boot regression: Fast model boot failure with Linux next-20250312
> Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>
> 
> Anders bisected this to this commit id,
> 
> # first bad commit:
>   [858c7bfcb35e1100b58bb63c9f562d86e09418d9]
>   arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
> 
> NOTE:
>   LKFT is currently running FVP Fast Models version 11.24.
>   Planned upgrade to the Fast Models version 11.28 in this sprint.

What firmware (and version therof) are you running within the model?

For example, if the EL3 firmware lacks support for FEAT_FGT2 or
FEAT_PMUv3p9, the kernel will trap to EL3 early during boot and die.

It would be really helpful if you could capture that in the report in
future.

Mark.

> 
> ## Boot log
>   <No crash log on the console>
> 
> ## Source
> * Kernel version: 6.14.0-rc7
> * Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
> * Git sha: ff7f9b199e3f4cc7d61df5a9a26a7cbb5c1492e6
> * Git describe: next-20250319
> * Project details:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319
> * DUT: arm64 Fast Model (FVP-AEMvA)
> * Toolchains: gcc-13 and clang-20
> 
> ## Build
> * Build log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/log
> * Build history:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675685/suite/boot/test/gcc-13-lkftconfig/history/
> * Build details:
> https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/
> * Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/
> * Kernel config:
> https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/config
> 
> --
> Linaro LKFT
> https://lkft.linaro.org
> 


From broonie at kernel.org  Wed Mar 19 08:03:06 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 19 Mar 2025 15:03:06 +0000
Subject: [PATCH 1/7] arm64/gcs: task_gcs_el0_enable() should use passed
 task
In-Reply-To: <Z9rUEtZtNXhVnarO@J2N7QTR9R3>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-2-jeremy.linton@arm.com>
 <Z9rUEtZtNXhVnarO@J2N7QTR9R3>
Message-ID: <ad1408f2-8a6d-4299-b986-0bacc58ad388@sirena.org.uk>

On Wed, Mar 19, 2025 at 02:26:26PM +0000, Mark Rutland wrote:
> On Tue, Mar 18, 2025 at 03:48:35PM -0500, Jeremy Linton wrote:

> 		if (!task_gcs_el0_enabled(p))
> 			return 0;

> 	p->thread.gcs_el0_mode = current->thread.gcs_el0_mode;

> Either that later assignment is redundant, or copy_thread_gcs() was
> accidentally relying upon task_gcs_el0_enabled() reading from 'current'
> rather than 'p', and this change opens up another bug...

copy_thread_gcs() looks buggy here - we should move the allocation of
the new stack to the bottom of the function after the assignments.  Like
you say it does currently work due to the check of the source thread.
The other users are the prctl and signal code which always work with
current and the check to see if we should do a GCSB DSYNC in
gcs_thread_switch() which currently misses a sync if switching from a
non-GCS to GCS task.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/25ea82b1/attachment.sig>

From miko.lenczewski at arm.com  Wed Mar 19 08:05:32 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Wed, 19 Mar 2025 15:05:32 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250319150533.37440-2-miko.lenczewski@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
Message-ID: <20250319150533.37440-3-miko.lenczewski@arm.com>

The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
and this commit adds a dedicated BBML2 cpufeature to test against
support for, as well as a kernel commandline parameter to optionally
disable BBML2 altogether.

This is a system feature as we might have a big.LITTLE architecture
where some cores support BBML2 and some don't, but we want all cores to
be available and BBM to default to level 0 (as opposed to having cores
without BBML2 not coming online).

To support BBML2 in as wide a range of contexts as we can, we want not
only the architectural guarantees that BBML2 makes, but additionally
want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
us having to prove that no recursive faults can be induced in any path
that uses BBML2, allowing its use for arbitrary kernel mappings.
Support detection of such CPUs.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 11 +++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  5 ++
 arch/arm64/kernel/cpufeature.c                | 68 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/tools/cpucaps                      |  1 +
 7 files changed, 92 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec8..3e4cc917a07e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -453,6 +453,9 @@
 	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
 			32 bit applications.
 
+	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
+			2 support
+
 	arm64.nobti	[ARM64] Unconditionally disable Branch Target
 			Identification support
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..49deda2b22ae 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
 	  The feature introduces new assembly instructions, and they were
 	  support when binutils >= 2.30.
 
+config ARM64_BBML2_NOABORT
+	bool "Enable support for Break-Before-Make Level 2 detection and usage"
+	default y
+	help
+	  FEAT_BBM provides detection of support levels for break-before-make
+	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
+	  can be relaxed to improve performance. We additonally require the
+	  property that the implementation cannot ever raise TLB Conflict Aborts.
+	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
+	  even if the system supports BBM level 2.
+
 endmenu # "ARMv8.4 architectural features"
 
 menu "ARMv8.5 architectural features"
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 0b5ca6e0eb09..2d6db33d4e45 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
 		return IS_ENABLED(CONFIG_ARM64_PAN);
 	case ARM64_HAS_EPAN:
 		return IS_ENABLED(CONFIG_ARM64_EPAN);
+	case ARM64_HAS_BBML2_NOABORT:
+		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
 	case ARM64_SVE:
 		return IS_ENABLED(CONFIG_ARM64_SVE);
 	case ARM64_SME:
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..108ef3fbbc00 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
 	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
 }
 
+static inline bool system_supports_bbml2_noabort(void)
+{
+	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d561cf3b8ac7..1a4adcda267b 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
 	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
 }
 
+static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
+{
+	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
+	 * as possible. This list is therefore an allow-list of known-good
+	 * implementations that both support bbml2 and additionally, fulfill the
+	 * extra constraint of never generating TLB conflict aborts when using
+	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
+	 * kernel contexts difficult to prove safe against recursive aborts).
+	 *
+	 * Note that implementations can only be considered "known-good" if their
+	 * implementors attest to the fact that the implementation never raises
+	 * TLBI conflict aborts for bbml2 mapping granularity changes.
+	 */
+	static const struct midr_range supports_bbml2_noabort_list[] = {
+		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
+		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
+		{}
+	};
+
+	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
+}
+
+static inline unsigned int cpu_read_midr(int cpu)
+{
+	WARN_ON_ONCE(!cpu_online(cpu));
+
+	return per_cpu(cpu_data, cpu).reg_midr;
+}
+
+static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
+		return false;
+
+	if (scope & SCOPE_SYSTEM) {
+		int cpu;
+
+		/* We are a boot CPU, and must verify that all enumerated boot
+		 * CPUs have MIDR values within our allowlist. Otherwise, we do
+		 * not allow the BBML2 feature to avoid potential faults when
+		 * the insufficient CPUs access memory regions using BBML2
+		 * semantics.
+		 */
+		for_each_online_cpu(cpu) {
+			if (!cpu_has_bbml2_noabort(cpu_read_midr(cpu)))
+				return false;
+		}
+	} else if (scope & SCOPE_LOCAL_CPU) {
+		/* We are a hot-plugged CPU, so must only check our MIDR.
+		 * If we have the correct MIDR, but the kernel booted on an
+		 * insufficient CPU, we will not use BBML2 (this is safe). If
+		 * we have an incorrect MIDR, but the kernel booted on a
+		 * sufficient CPU, we will not bring up this CPU.
+		 */
+		if (!cpu_has_bbml2_noabort(read_cpuid_id()))
+			return false;
+	}
+
+	return has_cpuid_feature(caps, scope);
+}
+
 #ifdef CONFIG_ARM64_PAN
 static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
@@ -2926,6 +2987,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.matches = has_cpuid_feature,
 		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
 	},
+	{
+		.desc = "BBM Level 2 without conflict abort",
+		.capability = ARM64_HAS_BBML2_NOABORT,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_bbml2_noabort,
+		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
+	},
 	{
 		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
 		.capability = ARM64_HAS_LPA2,
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index c6b185b885f7..803a0c99f7b4 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
 	.override	= &id_aa64mmfr2_override,
 	.fields		= {
 		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
+		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
 		{}
 	},
 };
@@ -246,6 +247,7 @@ static const struct {
 	{ "rodata=off",			"arm64_sw.rodataoff=1" },
 	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
 	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
+	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
 };
 
 static int __init parse_hexdigit(const char *p, u64 *v)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1e65f2fb45bd..b03a375e5507 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
 HAS_ADDRESS_AUTH_IMP_DEF
 HAS_AMU_EXTN
 HAS_ARMv8_4_TTL
+HAS_BBML2_NOABORT
 HAS_CACHE_DIC
 HAS_CACHE_IDC
 HAS_CNP
-- 
2.48.1



From miko.lenczewski at arm.com  Wed Mar 19 08:05:33 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Wed, 19 Mar 2025 15:05:33 +0000
Subject: [PATCH v4 2/3] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250319150533.37440-2-miko.lenczewski@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
Message-ID: <20250319150533.37440-4-miko.lenczewski@arm.com>

For supporting BBM Level 2 for userspace mappings, we want to ensure
that the smmu also supports its own version of BBM Level 2. Luckily, the
smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
0487K.a D8.16.2), so already guarantees that no aborts are raised when
BBM level 2 is claimed.

Add the feature and testing for it under arm_smmu_sva_supported().

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
Reviewed-by: Robin Murphy <robin.murphy at arm.com>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 9ba596430e7c..6ba182572788 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 		feat_mask |= ARM_SMMU_FEAT_VAX;
 	}
 
+	if (system_supports_bbml2_noabort())
+		feat_mask |= ARM_SMMU_FEAT_BBML2;
+
 	if ((smmu->features & feat_mask) != feat_mask)
 		return false;
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 358072b4e293..dcee0bdec924 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 	if (FIELD_GET(IDR3_RIL, reg))
 		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
 
+	if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
+		smmu->features |= ARM_SMMU_FEAT_BBML2;
+
 	/* IDR5 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index bd9d7c85576a..85eaf3ab88c2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -60,6 +60,9 @@ struct arm_smmu_device;
 #define ARM_SMMU_IDR3			0xc
 #define IDR3_FWB			(1 << 8)
 #define IDR3_RIL			(1 << 10)
+#define IDR3_BBML			GENMASK(12, 11)
+#define IDR3_BBML1			(1 << 11)
+#define IDR3_BBML2			(2 << 11)
 
 #define ARM_SMMU_IDR5			0x14
 #define IDR5_STALL_MAX			GENMASK(31, 16)
@@ -754,6 +757,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_HA		(1 << 21)
 #define ARM_SMMU_FEAT_HD		(1 << 22)
 #define ARM_SMMU_FEAT_S2FWB		(1 << 23)
+#define ARM_SMMU_FEAT_BBML2		(1 << 24)
 	u32				features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)
-- 
2.48.1



From miko.lenczewski at arm.com  Wed Mar 19 08:05:34 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Wed, 19 Mar 2025 15:05:34 +0000
Subject: [PATCH v4 3/3] arm64/mm: Elide tlbi in contpte_convert() under BBML2
In-Reply-To: <20250319150533.37440-2-miko.lenczewski@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
Message-ID: <20250319150533.37440-5-miko.lenczewski@arm.com>

When converting a region via contpte_convert() to use mTHP, we have two
different goals. We have to mark each entry as contiguous, and we would
like to smear the dirty and young (access) bits across all entries in
the contiguous block. Currently, we do this by first accumulating the
dirty and young bits in the block, using an atomic
__ptep_get_and_clear() and the relevant pte_{dirty,young}() calls,
performing a tlbi, and finally smearing the correct bits across the
block using __set_ptes().

This approach works fine for BBM level 0, but with support for BBM level
2 we are allowed to reorder the tlbi to after setting the pagetable
entries. We expect the time cost of a tlbi to be much greater than the
cost of clearing and resetting the PTEs. As such, this reordering of the
tlbi outside the window where our PTEs are invalid greatly reduces the
duration the PTE are visibly invalid for other threads. This reduces the
likelyhood of a concurrent page walk finding an invalid PTE, reducing
the likelyhood of a fault in other threads, and improving performance
(more so when there are more threads).

Because we support via allowlist only bbml2 implementations that never
raise conflict aborts and instead invalidate the tlb entries
automatically in hardware, we can avoid the final flush altogether.
Avoiding flushes is a win.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/mm/contpte.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
index 55107d27d3f8..77ed03b30b72 100644
--- a/arch/arm64/mm/contpte.c
+++ b/arch/arm64/mm/contpte.c
@@ -68,7 +68,8 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
 			pte = pte_mkyoung(pte);
 	}
 
-	__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
+	if (!system_supports_bbml2_noabort())
+		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
 
 	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
 }
-- 
2.48.1



From miko.lenczewski at arm.com  Wed Mar 19 08:05:31 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Wed, 19 Mar 2025 15:05:31 +0000
Subject: [PATCH v4 0/3] Initial BBML2 support for contpte_convert()
Message-ID: <20250319150533.37440-2-miko.lenczewski@arm.com>

Hi All,

This patch series adds initial support for eliding break-before-make
requirements on systems that support BBML2 and additionally guarantee
to never raise a conflict abort.

This support elides a TLB invalidation in contpte_convert(). This
leads to a 12% improvement when executing a microbenchmark designed
to force the pathological path where contpte_convert() gets called.
This represents an 80% reduction in the cost of calling
contpte_convert().

This series is based on v6.14-rc5 (7eb172143d55).

Notes
======

Patch 1 implements an allow-list of cpus that support BBML2, but with
the additional constraint of never causing TLB conflict aborts. We
settled on this constraint because we will use the feature for kernel
mappings in the future, for which we cannot handle conflict aborts
safely.

Yang Shi has a series at [1] that aims to use BBML2 to enable splitting
the linear map at runtime. This series partially overlaps with it to add
the cpu feature. We believe this series is fully compatible with Yang's
requirements and could go first.

Due to constraints with the current design of the cpufeature framework
and the fact that our has_bbml2_noabort() check relies on both a MIDR
allowlist and the exposed mmfr2 register value, if an implementation
supports our desired bbml2+noabort semantics but fails to declare
support for base bbml2 via the id_aa64mmfr2.bbm field, the check will
fail.

Not declaring base support for bbml2 when supporting bbml2+noabort
should be considered an erratum [2], and a workaround can be applied in
__cpuinfo_store_cpu() to patch in support for bbml2 for the sanitised
register view used by SCOPE_SYSTEM. However, SCOPE_LOCAL_CPU bypasses
this sanitised view and reads the MSRs directly by design, and so an
additional workaround can be applied in __read_sysreg_by_encoding()
for the MMFR2 case.

[1]:
  https://lore.kernel.org/linux-arm-kernel/20250304222018.615808-1-yang at os.amperecomputing.com/

[2]:
  https://lore.kernel.org/linux-arm-kernel/3bba7adb-392b-4024-984f-b6f0f0f88629 at arm.com/

Changelog
=========

v4:
  - rebase onto v6.14-rc5
  - switch from arm64 sw feature override to hw feature override
  - reintroduce has_cpuid_feature() check in addition to MIDR check

v3:
  - https://lore.kernel.org/all/20250313104111.24196-2-miko.lenczewski at arm.com/
  - rebase onto v6.14-rc4
  - add arm64.nobbml2 commandline override
  - squash "delay tlbi" and "elide tlbi" patches

v2:
  - https://lore.kernel.org/all/20250228182403.6269-2-miko.lenczewski at arm.com/
  - fix buggy MIDR check to properly account for all boot+late cpus
  - add smmu bbml2 feature check

v1:
  - https://lore.kernel.org/all/20250219143837.44277-3-miko.lenczewski at arm.com/
  - rebase onto v6.14-rc3
  - remove kvm bugfix patches from series
  - strip out conflict abort handler code
  - switch from blocklist to allowlist of bmml2+noabort implementations
  - remove has_cpuid_feature() in favour of MIDR check

rfc-v1:
  - https://lore.kernel.org/all/20241211154611.40395-1-miko.lenczewski at arm.com/
  - https://lore.kernel.org/all/20241211160218.41404-1-miko.lenczewski at arm.com/

Miko?aj Lenczewski (3):
  arm64: Add BBM Level 2 cpu feature
  iommu/arm: Add BBM Level 2 smmu feature
  arm64/mm: Elide tlbi in contpte_convert() under BBML2

 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 11 +++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  5 ++
 arch/arm64/kernel/cpufeature.c                | 68 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/mm/contpte.c                       |  3 +-
 arch/arm64/tools/cpucaps                      |  1 +
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  4 ++
 11 files changed, 104 insertions(+), 1 deletion(-)

-- 
2.48.1



From admin at hifiphile.com  Wed Mar 19 08:06:56 2025
From: admin at hifiphile.com (Zixun LI)
Date: Wed, 19 Mar 2025 16:06:56 +0100
Subject: [PATCH] crypto: atmel - add CRYPTO_ALG_KERN_DRIVER_ONLY flag to atmel-aes, atmel-sha, atmel-tdes drivers
Message-ID: <20250319150657.2698916-1-zli@ogga.fr>

From: Zixun LI <admin at hifiphile.com>

This patch introduces the CRYPTO_ALG_KERN_DRIVER_ONLY flag to the
atmel-aes, atmel-sha, and atmel-tdes drivers. This flag is set for
hardware accelerated ciphers accessible through a kernel driver only,
which is the case of these drivers.

Signed-off-by: Zixun LI <admin at hifiphile.com>
---
 drivers/crypto/atmel-aes.c  | 5 +++--
 drivers/crypto/atmel-sha.c  | 6 ++++--
 drivers/crypto/atmel-tdes.c | 3 ++-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 90dcae7049b7..8a6ee5ac9956 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -1948,7 +1948,8 @@ static struct skcipher_alg aes_xts_alg = {
 	.base.cra_driver_name	= "atmel-xts-aes",
 	.base.cra_blocksize	= AES_BLOCK_SIZE,
 	.base.cra_ctxsize	= sizeof(struct atmel_aes_xts_ctx),
-	.base.cra_flags		= CRYPTO_ALG_NEED_FALLBACK,
+	.base.cra_flags		= CRYPTO_ALG_NEED_FALLBACK |
+						  CRYPTO_ALG_KERN_DRIVER_ONLY,
 
 	.min_keysize		= 2 * AES_MIN_KEY_SIZE,
 	.max_keysize		= 2 * AES_MAX_KEY_SIZE,
@@ -2471,7 +2472,7 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 
 static void atmel_aes_crypto_alg_init(struct crypto_alg *alg)
 {
-	alg->cra_flags |= CRYPTO_ALG_ASYNC;
+	alg->cra_flags |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
 	alg->cra_alignmask = 0xf;
 	alg->cra_priority = ATMEL_AES_PRIORITY;
 	alg->cra_module = THIS_MODULE;
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 3622120add62..40f6ed5b20ee 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1254,7 +1254,8 @@ static int atmel_sha_cra_init(struct crypto_tfm *tfm)
 static void atmel_sha_alg_init(struct ahash_alg *alg)
 {
 	alg->halg.base.cra_priority = ATMEL_SHA_PRIORITY;
-	alg->halg.base.cra_flags = CRYPTO_ALG_ASYNC;
+	alg->halg.base.cra_flags = CRYPTO_ALG_ASYNC |
+							   CRYPTO_ALG_KERN_DRIVER_ONLY;
 	alg->halg.base.cra_ctxsize = sizeof(struct atmel_sha_ctx);
 	alg->halg.base.cra_module = THIS_MODULE;
 	alg->halg.base.cra_init = atmel_sha_cra_init;
@@ -2043,7 +2044,8 @@ static void atmel_sha_hmac_cra_exit(struct crypto_tfm *tfm)
 static void atmel_sha_hmac_alg_init(struct ahash_alg *alg)
 {
 	alg->halg.base.cra_priority = ATMEL_SHA_PRIORITY;
-	alg->halg.base.cra_flags = CRYPTO_ALG_ASYNC;
+	alg->halg.base.cra_flags = CRYPTO_ALG_ASYNC |
+							   CRYPTO_ALG_KERN_DRIVER_ONLY;
 	alg->halg.base.cra_ctxsize = sizeof(struct atmel_sha_hmac_ctx);
 	alg->halg.base.cra_module = THIS_MODULE;
 	alg->halg.base.cra_init	= atmel_sha_hmac_cra_init;
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index 099b32a10dd7..3a6a890172cd 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -898,7 +898,8 @@ static int atmel_tdes_init_tfm(struct crypto_skcipher *tfm)
 static void atmel_tdes_skcipher_alg_init(struct skcipher_alg *alg)
 {
 	alg->base.cra_priority = ATMEL_TDES_PRIORITY;
-	alg->base.cra_flags = CRYPTO_ALG_ASYNC;
+	alg->base.cra_flags = CRYPTO_ALG_ASYNC |
+						  CRYPTO_ALG_KERN_DRIVER_ONLY;
 	alg->base.cra_ctxsize = sizeof(struct atmel_tdes_ctx);
 	alg->base.cra_module = THIS_MODULE;
 
-- 
2.48.1



From mhklinux at outlook.com  Wed Mar 19 08:26:20 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Wed, 19 Mar 2025 15:26:20 +0000
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <SN6PR02MB41574DE5535222985147134CD4D92@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <afd87eba-742f-4b67-9171-fd8486416b7b@linux.microsoft.com>
 <SN6PR02MB41574DE5535222985147134CD4D92@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <BN7PR02MB4148D51FFF965676AD155A3ED4D92@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Michael Kelley <mhklinux at outlook.com> Sent: Tuesday, March 18, 2025 7:10 PM
> 
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Tuesday, March
> 18, 2025 5:34 PM
> >
> > On 3/17/2025 4:51 PM, Michael Kelley wrote:
> > > From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM

[snip]

> > >> +
> > >> +	region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
> > >> +	if (!region)
> > >> +		return -EINVAL;
> > <snip>
> >> +	case MSHV_GPAP_ACCESS_TYPE_ACCESSED:
> > >> +		hv_type_mask = 1;
> > >> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> > >> +			hv_flags.clear_accessed = 1;
> > >> +			/* not accessed implies not dirty */
> > >> +			hv_flags.clear_dirty = 1;
> > >> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> > >
> > > Avoid C++ style comments.
> > >
> > Ack
> >
> > >> +			hv_flags.set_accessed = 1;
> > >> +		}
> > >> +		break;
> > >> +	case MSHV_GPAP_ACCESS_TYPE_DIRTY:
> > >> +		hv_type_mask = 2;
> > >> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
> > >> +			hv_flags.clear_dirty = 1;
> > >> +		} else { // MSHV_GPAP_ACCESS_OP_SET
> > >
> > > Same here.
> > >
> > Ack
> >
> > >> +			hv_flags.set_dirty = 1;
> > >> +			/* dirty implies accessed */
> > >> +			hv_flags.set_accessed = 1;
> > >> +		}
> > >> +		break;
> > >> +	}
> > >> +
> > >> +	states = vzalloc(states_buf_sz);
> > >> +	if (!states)
> > >> +		return -ENOMEM;
> > >> +
> > >> +	ret = hv_call_get_gpa_access_states(partition->pt_id, args.page_count,
> > >> +					    args.gpap_base, hv_flags, &written,
> > >> +					    states);
> > >> +	if (ret)
> > >> +		goto free_return;
> > >> +
> > >> +	/*
> > >> +	 * Overwrite states buffer with bitmap - the bits in hv_type_mask
> > >> +	 * correspond to bitfields in hv_gpa_page_access_state
> > >> +	 */
> > >> +	for (i = 0; i < written; ++i)
> > >> +		assign_bit(i, (ulong *)states,
> > >
> > > Why the cast to ulong *?  I think this argument to assign_bit() is void *, in
> > > which case the cast wouldn't be needed.
> > >
> > It looks like assign_bit() and friends resolve to a set of functions which do
> > take an unsigned long pointer, e.g.:
> >
> > __set_bit() -> generic___set_bit(unsigned long nr, volatile unsigned long *addr)
> > set_bit() -> arch_set_bit(unsigned int nr, volatile unsigned long *p)
> > etc...
> >
> > So a cast is necessary.
> 
> Indeed, you are right.  Seems like set_bit() and friends should take a void *.
> But that's a different kettle of fish.
> 
> >
> > > Also, assign_bit() does atomic bit operations. Doing such in a loop like
> > > here will really hammer the hardware memory bus with atomic
> > > read-modify-write cycles. Use __assign_bit() instead, which does
> > > non-atomic operations. You don't need atomic here as no other
> > > threads are modifying the bit array.
> > >
> > I didn't realize it was atomic. I'll change it to __assign_bit().
> >
> > >> +			   states[i].as_uint8 & hv_type_mask);
> > >
> > > OK, so the starting contents of "states" is an array of bytes. The ending
> > > contents is an array of bits. This works because every bit in the ending
> > > bit array is set to either 0 or 1. Overlap occurs on the first iteration
> > > where the code reads the 0th byte, and writes the 0th bit, which is part of
> > > the 0th byte. The second iteration reads the 1st byte, and writes the 1st bit,
> > > which doesn't overlap, and there's no overlap from then on.
> > >
> > > Suppose "written" is not a multiple of 8. The last byte of "states" as an
> > > array of bits will have some bits that have not been set to either 0 or 1 and
> > > might be leftover garbage from when "states" was an array of bytes. That
> > > garbage will get copied to user space. Is that OK? Even if user space knows
> > > enough to ignore those bits, it seems a little dubious to be copying even
> > > a few bits of garbage to user space.
> > >
> > > Some comments might help here.
> > >
> > This is a good point. The expectation is indeed that userspace knows which
> > bits are valid from the returned "written" value, but I agree it's a bit
> > odd to have some garbage bits in the last byte. How does this look (to be
> > inserted here directly after the loop):
> >
> > +       /* zero the unused bits in the last byte of the returned bitmap */
> > +       if (written > 0) {
> > +               u8 last_bits_mask;
> > +               int last_byte_idx;
> > +               int bits_rem = written % 8;
> > +
> > +               /* bits_rem == 0 when all bits in the last byte were assigned */
> > +               if (bits_rem > 0) {
> > +                       /* written > 0 ensures last_byte_idx >= 0 */
> > +                       last_byte_idx = ((written + 7) / 8) - 1;
> > +                       /* bits_rem > 0 ensures this masks 1 to 7 bits */
> > +                       last_bits_mask = (1 << bits_rem) - 1;
> > +                       states[last_byte_idx].as_uint8 &= last_bits_mask;
> > +               }
> > +       }
> 
> A simpler approach is to "continue" the previous loop.  And if "written"
> is zero, this additional loop won't do anything either:
> 
> 	for (i = written; i < ALIGN(written, 8); ++i)
> 		__clear_bit(i, (ulong *)states);
> 

One further thought here: Could "written" be less than
args.page_count at this point? That would require
hv_call_get_gpa_access_states() to not fail, but still return
a value for written that is less than args.page_count. If that
could happen, then the above loop should be:

	for (i = written; i < bitmap_buf_sz * 8; ++i)
		__clear_bit(i, (ulong *)states);

so that all the uninitialized bits and bytes that will be written
back to user space are cleared.

> >
> > The remaining bytes could be memset() to zero but I think it's fine to leave
> > them.
> 
> I agree.  The remaining bytes aren't written back to user space anyway
> since the copy_to_user() uses bitmap_buf_sz.

Maybe I misunderstood what you meant by "remaining bytes".  I think
all bits and bytes that are written back to user space should have
valid data or zeros so that no garbage is written back.

Michael

> 
> >
> > >> +
> > >> +	args.page_count = written;
> > >> +
> > >> +	if (copy_to_user(user_args, &args, sizeof(args))) {
> > >> +		ret = -EFAULT;
> > >> +		goto free_return;
> > >> +	}
> > >> +	if (copy_to_user((void __user *)args.bitmap_ptr, states, bitmap_buf_sz))
> > >> +		ret = -EFAULT;
> > >> +
> > >> +free_return:
> > >> +	vfree(states);
> > >> +	return ret;
> > >> +}


From arnaud.pouliquen at foss.st.com  Wed Mar 19 08:23:54 2025
From: arnaud.pouliquen at foss.st.com (Arnaud POULIQUEN)
Date: Wed, 19 Mar 2025 16:23:54 +0100
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use
 of_reserved_mem_region_* functions for "memory-region"
In-Reply-To: <20250317232426.952188-4-robh@kernel.org>
References: <20250317232426.952188-1-robh@kernel.org>
 <20250317232426.952188-4-robh@kernel.org>
Message-ID: <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>

Hello Rob,

On 3/18/25 00:24, Rob Herring (Arm) wrote:
> Use the newly added of_reserved_mem_region_to_resource() and
> of_reserved_mem_region_count() functions to handle "memory-region"
> properties.
> 
> The error handling is a bit different in some cases. Often
> "memory-region" is optional, so failed lookup is not an error. But then
> an error in of_reserved_mem_lookup() is treated as an error. However,
> that distinction is not really important. Either the region is available
> and usable or it is not. So now, it is just
> of_reserved_mem_region_to_resource() which is checked for an error.
> 
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> ---
> For v6.16
> 
>  drivers/remoteproc/imx_dsp_rproc.c        | 44 ++++++---------
>  drivers/remoteproc/imx_rproc.c            | 65 ++++++++-------------
>  drivers/remoteproc/qcom_q6v5_adsp.c       | 24 +++-----
>  drivers/remoteproc/qcom_q6v5_mss.c        | 60 +++++++-------------
>  drivers/remoteproc/qcom_q6v5_pas.c        | 69 ++++++++---------------
>  drivers/remoteproc/qcom_q6v5_wcss.c       | 25 ++++----
>  drivers/remoteproc/qcom_wcnss.c           | 23 +++-----
>  drivers/remoteproc/rcar_rproc.c           | 36 +++++-------
>  drivers/remoteproc/st_remoteproc.c        | 39 ++++++-------
>  drivers/remoteproc/stm32_rproc.c          | 42 ++++++--------
>  drivers/remoteproc/ti_k3_dsp_remoteproc.c | 28 ++++-----
>  drivers/remoteproc/ti_k3_m4_remoteproc.c  | 28 ++++-----
>  drivers/remoteproc/ti_k3_r5_remoteproc.c  | 28 ++++-----
>  drivers/remoteproc/xlnx_r5_remoteproc.c   | 49 ++++++----------
>  14 files changed, 213 insertions(+), 347 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
> index ea5024919c2f..f3f341f4a262 100644
> --- a/drivers/remoteproc/imx_dsp_rproc.c
> +++ b/drivers/remoteproc/imx_dsp_rproc.c
> @@ -595,11 +595,9 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
>  	struct rproc *rproc = priv->rproc;
>  	struct device *dev = rproc->dev.parent;
>  	struct device_node *np = dev->of_node;
> -	struct of_phandle_iterator it;
>  	struct rproc_mem_entry *mem;
> -	struct reserved_mem *rmem;
>  	void __iomem *cpu_addr;
> -	int a;
> +	int a, i = 0;
>  	u64 da;
> 
>  	/* Remap required addresses */
> @@ -630,45 +628,37 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
>  		rproc_add_carveout(rproc, mem);
>  	}
> 
> -	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> -	while (of_phandle_iterator_next(&it) == 0) {
> +	while (1) {
> +		int err;
> +		struct resource res;
> +
> +		err = of_reserved_mem_region_to_resource(np, i++, &res);
> +		if (err)
> +			return 0;
> +
>  		/*
>  		 * Ignore the first memory region which will be used vdev buffer.
>  		 * No need to do extra handlings, rproc_add_virtio_dev will handle it.
>  		 */
> -		if (!strcmp(it.node->name, "vdev0buffer"))
> +		if (!strcmp(res.name, "vdev0buffer"))
>  			continue;
> 
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(dev, "unable to acquire memory-region\n");
> +		if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da))
>  			return -EINVAL;
> -		}
> 
> -		if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) {
> -			of_node_put(it.node);
> -			return -EINVAL;
> -		}
> -
> -		cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
> +		cpu_addr = devm_ioremap_resource_wc(dev, &res);
>  		if (!cpu_addr) {
> -			of_node_put(it.node);
> -			dev_err(dev, "failed to map memory %p\n", &rmem->base);
> +			dev_err(dev, "failed to map memory %pR\n", &res);
>  			return -ENOMEM;
>  		}
> 
>  		/* Register memory region */
> -		mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base,
> -					   rmem->size, da, NULL, NULL, it.node->name);
> -
> -		if (mem) {
> -			rproc_coredump_add_segment(rproc, da, rmem->size);
> -		} else {
> -			of_node_put(it.node);
> +		mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)res.start,
> +					   resource_size(&res), da, NULL, NULL, res.name);
> +		if (!mem)
>  			return -ENOMEM;
> -		}
> 
> +		rproc_coredump_add_segment(rproc, da, resource_size(&res));
>  		rproc_add_carveout(rproc, mem);
>  	}
> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 74299af1d7f1..fba95507b6cf 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -549,46 +549,41 @@ static int imx_rproc_prepare(struct rproc *rproc)
>  {
>  	struct imx_rproc *priv = rproc->priv;
>  	struct device_node *np = priv->dev->of_node;
> -	struct of_phandle_iterator it;
>  	struct rproc_mem_entry *mem;
> -	struct reserved_mem *rmem;
> +	int i = 0;
>  	u32 da;
> 
>  	/* Register associated reserved memory regions */
> -	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> -	while (of_phandle_iterator_next(&it) == 0) {
> +	while (1) {
> +		int err;
> +		struct resource res;
> +
> +		err = of_reserved_mem_region_to_resource(np, i++, &res);
> +		if (err)
> +			return 0;
> +
>  		/*
>  		 * Ignore the first memory region which will be used vdev buffer.
>  		 * No need to do extra handlings, rproc_add_virtio_dev will handle it.
>  		 */
> -		if (!strcmp(it.node->name, "vdev0buffer"))
> +		if (!strcmp(res.name, "vdev0buffer"))
>  			continue;
> 
> -		if (!strcmp(it.node->name, "rsc-table"))
> +		if (!strcmp(res.name, "rsc-table"))
>  			continue;
> 
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(priv->dev, "unable to acquire memory-region\n");
> -			return -EINVAL;
> -		}
> -
>  		/* No need to translate pa to da, i.MX use same map */
> -		da = rmem->base;
> +		da = res.start;
> 
>  		/* Register memory region */
> -		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da,
> +		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start, resource_size(&res), da,
>  					   imx_rproc_mem_alloc, imx_rproc_mem_release,
> -					   it.node->name);
> +					   res.name);
> 
> -		if (mem) {
> -			rproc_coredump_add_segment(rproc, da, rmem->size);
> -		} else {
> -			of_node_put(it.node);
> +		if (!mem)
>  			return -ENOMEM;
> -		}
> 
> +		rproc_coredump_add_segment(rproc, da, resource_size(&res));
>  		rproc_add_carveout(rproc, mem);
>  	}
> 
> @@ -723,47 +718,37 @@ static int imx_rproc_addr_init(struct imx_rproc *priv,
>  	}
> 
>  	/* memory-region is optional property */
> -	nph = of_count_phandle_with_args(np, "memory-region", NULL);
> +	nph = of_reserved_mem_region_count(np);
>  	if (nph <= 0)
>  		return 0;
> 
>  	/* remap optional addresses */
>  	for (a = 0; a < nph; a++) {
> -		struct device_node *node;
>  		struct resource res;
> 
> -		node = of_parse_phandle(np, "memory-region", a);
> -		if (!node)
> -			continue;
> -		/* Not map vdevbuffer, vdevring region */
> -		if (!strncmp(node->name, "vdev", strlen("vdev"))) {
> -			of_node_put(node);
> -			continue;
> -		}
> -		err = of_address_to_resource(node, 0, &res);
> +		err = of_reserved_mem_region_to_resource(np, a, &res);
>  		if (err) {
>  			dev_err(dev, "unable to resolve memory region\n");
> -			of_node_put(node);
>  			return err;
>  		}
> 
> -		if (b >= IMX_RPROC_MEM_MAX) {
> -			of_node_put(node);
> +		/* Not map vdevbuffer, vdevring region */
> +		if (!strncmp(res.name, "vdev", strlen("vdev")))
> +			continue;
> +
> +		if (b >= IMX_RPROC_MEM_MAX)
>  			break;
> -		}
> 
>  		/* Not use resource version, because we might share region */
> -		priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res));
> +		priv->mem[b].cpu_addr = devm_ioremap_resource_wc(&pdev->dev, &res);
>  		if (!priv->mem[b].cpu_addr) {
>  			dev_err(dev, "failed to remap %pr\n", &res);
> -			of_node_put(node);
>  			return -ENOMEM;
>  		}
>  		priv->mem[b].sys_addr = res.start;
>  		priv->mem[b].size = resource_size(&res);
> -		if (!strcmp(node->name, "rsc-table"))
> +		if (!strcmp(res.name, "rsc-table"))
>  			priv->rsc_table = priv->mem[b].cpu_addr;
> -		of_node_put(node);
>  		b++;
>  	}
> 
> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
> index 94af77baa7a1..a5b7cbb8fe07 100644
> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> @@ -625,26 +625,20 @@ static int adsp_init_mmio(struct qcom_adsp *adsp,
> 
>  static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
>  {
> -	struct reserved_mem *rmem = NULL;
> -	struct device_node *node;
> -
> -	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
> -	if (node)
> -		rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> +	int ret;
> +	struct resource res;
> 
> -	if (!rmem) {
> +	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 0, &res);
> +	if (!ret) {
>  		dev_err(adsp->dev, "unable to resolve memory-region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	adsp->mem_phys = adsp->mem_reloc = rmem->base;
> -	adsp->mem_size = rmem->size;
> -	adsp->mem_region = devm_ioremap_wc(adsp->dev,
> -				adsp->mem_phys, adsp->mem_size);
> +	adsp->mem_phys = adsp->mem_reloc = res.start;
> +	adsp->mem_size = resource_size(&res);
> +	adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
>  	if (!adsp->mem_region) {
> -		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
> -			&rmem->base, adsp->mem_size);
> +		dev_err(adsp->dev, "unable to map memory region: %pR\n", &res);
>  		return -EBUSY;
>  	}
> 
> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
> index e78bd986dc3f..905a142bd65d 100644
> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> @@ -1881,8 +1881,8 @@ static int q6v5_init_reset(struct q6v5 *qproc)
>  static int q6v5_alloc_memory_region(struct q6v5 *qproc)
>  {
>  	struct device_node *child;
> -	struct reserved_mem *rmem;
> -	struct device_node *node;
> +	struct resource res;
> +	int ret;
> 
>  	/*
>  	 * In the absence of mba/mpss sub-child, extract the mba and mpss
> @@ -1890,71 +1890,49 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc)
>  	 */
>  	child = of_get_child_by_name(qproc->dev->of_node, "mba");
>  	if (!child) {
> -		node = of_parse_phandle(qproc->dev->of_node,
> -					"memory-region", 0);
> +		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 0, &res);
>  	} else {
> -		node = of_parse_phandle(child, "memory-region", 0);
> +		ret = of_reserved_mem_region_to_resource(child, 0, &res);
>  		of_node_put(child);
>  	}
> 
> -	if (!node) {
> -		dev_err(qproc->dev, "no mba memory-region specified\n");
> -		return -EINVAL;
> -	}
> -
> -	rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> -	if (!rmem) {
> +	if (ret) {
>  		dev_err(qproc->dev, "unable to resolve mba region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	qproc->mba_phys = rmem->base;
> -	qproc->mba_size = rmem->size;
> +	qproc->mba_phys = res.start;
> +	qproc->mba_size = resource_size(&res);
> 
>  	if (!child) {
> -		node = of_parse_phandle(qproc->dev->of_node,
> -					"memory-region", 1);
> +		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 1, &res);
>  	} else {
>  		child = of_get_child_by_name(qproc->dev->of_node, "mpss");
> -		node = of_parse_phandle(child, "memory-region", 0);
> +		ret = of_reserved_mem_region_to_resource(child, 0, &res);
>  		of_node_put(child);
>  	}
> 
> -	if (!node) {
> -		dev_err(qproc->dev, "no mpss memory-region specified\n");
> -		return -EINVAL;
> -	}
> -
> -	rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> -	if (!rmem) {
> +	if (ret) {
>  		dev_err(qproc->dev, "unable to resolve mpss region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	qproc->mpss_phys = qproc->mpss_reloc = rmem->base;
> -	qproc->mpss_size = rmem->size;
> +	qproc->mpss_phys = qproc->mpss_reloc = res.start;
> +	qproc->mpss_size = resource_size(&res);
> 
>  	if (!child) {
> -		node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2);
> +		ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 2, &res);
>  	} else {
>  		child = of_get_child_by_name(qproc->dev->of_node, "metadata");
> -		node = of_parse_phandle(child, "memory-region", 0);
> +		ret = of_reserved_mem_region_to_resource(child, 0, &res);
>  		of_node_put(child);
>  	}
> 
> -	if (!node)
> +	if (ret)
>  		return 0;
> 
> -	rmem = of_reserved_mem_lookup(node);
> -	if (!rmem) {
> -		dev_err(qproc->dev, "unable to resolve metadata region\n");
> -		return -EINVAL;
> -	}
> -
> -	qproc->mdata_phys = rmem->base;
> -	qproc->mdata_size = rmem->size;
> +	qproc->mdata_phys = res.start;
> +	qproc->mdata_size = resource_size(&res);
> 
>  	return 0;
>  }
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 97c4bdd9222a..0ebd2ce0477b 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -546,53 +546,37 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
> 
>  static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
>  {
> -	struct reserved_mem *rmem;
> -	struct device_node *node;
> -
> -	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
> -	if (!node) {
> -		dev_err(adsp->dev, "no memory-region specified\n");
> -		return -EINVAL;
> -	}
> +	struct resource res;
> +	int ret;
> 
> -	rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> -	if (!rmem) {
> +	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 0, &res);
> +	if (ret) {
>  		dev_err(adsp->dev, "unable to resolve memory-region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	adsp->mem_phys = adsp->mem_reloc = rmem->base;
> -	adsp->mem_size = rmem->size;
> -	adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
> +	adsp->mem_phys = adsp->mem_reloc = res.start;
> +	adsp->mem_size = resource_size(&res);
> +	adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
>  	if (!adsp->mem_region) {
> -		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
> -			&rmem->base, adsp->mem_size);
> +		dev_err(adsp->dev, "unable to map memory region: %pR\n", &res);
>  		return -EBUSY;
>  	}
> 
>  	if (!adsp->dtb_pas_id)
>  		return 0;
> 
> -	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1);
> -	if (!node) {
> -		dev_err(adsp->dev, "no dtb memory-region specified\n");
> -		return -EINVAL;
> -	}
> -
> -	rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> -	if (!rmem) {
> +	ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 1, &res);
> +	if (ret) {
>  		dev_err(adsp->dev, "unable to resolve dtb memory-region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base;
> -	adsp->dtb_mem_size = rmem->size;
> -	adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size);
> +	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = res.start;
> +	adsp->dtb_mem_size = resource_size(&res);
> +	adsp->dtb_mem_region = devm_ioremap_resource_wc(adsp->dev, &res);
>  	if (!adsp->dtb_mem_region) {
> -		dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n",
> -			&rmem->base, adsp->dtb_mem_size);
> +		dev_err(adsp->dev, "unable to map dtb memory region: %pR\n", &res);
>  		return -EBUSY;
>  	}
> 
> @@ -602,7 +586,6 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
>  static int adsp_assign_memory_region(struct qcom_adsp *adsp)
>  {
>  	struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT];
> -	struct device_node *node;
>  	unsigned int perm_size;
>  	int offset;
>  	int ret;
> @@ -611,17 +594,15 @@ static int adsp_assign_memory_region(struct qcom_adsp *adsp)
>  		return 0;
> 
>  	for (offset = 0; offset < adsp->region_assign_count; ++offset) {
> -		struct reserved_mem *rmem = NULL;
> -
> -		node = of_parse_phandle(adsp->dev->of_node, "memory-region",
> -					adsp->region_assign_idx + offset);
> -		if (node)
> -			rmem = of_reserved_mem_lookup(node);
> -		of_node_put(node);
> -		if (!rmem) {
> +		struct resource res;
> +
> +		ret = of_reserved_mem_region_to_resource(adsp->dev->of_node,
> +							 adsp->region_assign_idx + offset,
> +							 &res);
> +		if (ret) {
>  			dev_err(adsp->dev, "unable to resolve shareable memory-region index %d\n",
>  				offset);
> -			return -EINVAL;
> +			return ret;
>  		}
> 
>  		if (adsp->region_assign_shared)  {
> @@ -636,8 +617,8 @@ static int adsp_assign_memory_region(struct qcom_adsp *adsp)
>  			perm_size = 1;
>  		}
> 
> -		adsp->region_assign_phys[offset] = rmem->base;
> -		adsp->region_assign_size[offset] = rmem->size;
> +		adsp->region_assign_phys[offset] = res.start;
> +		adsp->region_assign_size[offset] = resource_size(&res);
>  		adsp->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS);
> 
>  		ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset],
> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
> index 93648734a2f2..4a3235ee0963 100644
> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> @@ -873,27 +873,22 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,
> 
>  static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
>  {
> -	struct reserved_mem *rmem = NULL;
> -	struct device_node *node;
>  	struct device *dev = wcss->dev;
> +	struct resource res;
> +	int ret;
> 
> -	node = of_parse_phandle(dev->of_node, "memory-region", 0);
> -	if (node)
> -		rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> -
> -	if (!rmem) {
> +	ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
> +	if (ret) {
>  		dev_err(dev, "unable to acquire memory-region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	wcss->mem_phys = rmem->base;
> -	wcss->mem_reloc = rmem->base;
> -	wcss->mem_size = rmem->size;
> -	wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
> +	wcss->mem_phys = res.start;
> +	wcss->mem_reloc = res.start;
> +	wcss->mem_size = resource_size(&res);
> +	wcss->mem_region = devm_ioremap_resource_wc(dev, &res);
>  	if (!wcss->mem_region) {
> -		dev_err(dev, "unable to map memory region: %pa+%pa\n",
> -			&rmem->base, &rmem->size);
> +		dev_err(dev, "unable to map memory region: %pR\n", &res);
>  		return -EBUSY;
>  	}
> 
> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> index 5b5664603eed..d99a324bd532 100644
> --- a/drivers/remoteproc/qcom_wcnss.c
> +++ b/drivers/remoteproc/qcom_wcnss.c
> @@ -506,25 +506,20 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss,
> 
>  static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
>  {
> -	struct reserved_mem *rmem = NULL;
> -	struct device_node *node;
> -
> -	node = of_parse_phandle(wcnss->dev->of_node, "memory-region", 0);
> -	if (node)
> -		rmem = of_reserved_mem_lookup(node);
> -	of_node_put(node);
> +	struct resource res;
> +	int ret;
> 
> -	if (!rmem) {
> +	ret = of_reserved_mem_region_to_resource(wcnss->dev->of_node, 0, &res);
> +	if (ret) {
>  		dev_err(wcnss->dev, "unable to resolve memory-region\n");
> -		return -EINVAL;
> +		return ret;
>  	}
> 
> -	wcnss->mem_phys = wcnss->mem_reloc = rmem->base;
> -	wcnss->mem_size = rmem->size;
> -	wcnss->mem_region = devm_ioremap_wc(wcnss->dev, wcnss->mem_phys, wcnss->mem_size);
> +	wcnss->mem_phys = wcnss->mem_reloc = res.start;
> +	wcnss->mem_size = resource_size(&res);
> +	wcnss->mem_region = devm_ioremap_resource_wc(wcnss->dev, &res);
>  	if (!wcnss->mem_region) {
> -		dev_err(wcnss->dev, "unable to map memory region: %pa+%zx\n",
> -			&rmem->base, wcnss->mem_size);
> +		dev_err(wcnss->dev, "unable to map memory region: %pR\n", &res);
>  		return -EBUSY;
>  	}
> 
> diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c
> index 921d853594f4..0be1a4073a94 100644
> --- a/drivers/remoteproc/rcar_rproc.c
> +++ b/drivers/remoteproc/rcar_rproc.c
> @@ -52,41 +52,33 @@ static int rcar_rproc_prepare(struct rproc *rproc)
>  {
>  	struct device *dev = rproc->dev.parent;
>  	struct device_node *np = dev->of_node;
> -	struct of_phandle_iterator it;
>  	struct rproc_mem_entry *mem;
> -	struct reserved_mem *rmem;
> +	int i = 0;
>  	u32 da;
> 
>  	/* Register associated reserved memory regions */
> -	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> -	while (of_phandle_iterator_next(&it) == 0) {
> -
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(&rproc->dev,
> -				"unable to acquire memory-region\n");
> -			return -EINVAL;
> -		}
> +	while (1) {
> +		struct resource res;
> +		int ret;
> +
> +		ret = of_reserved_mem_region_to_resource(np, i++, &res);
> +		if (ret)
> +			return 0;
> 
> -		if (rmem->base > U32_MAX) {
> -			of_node_put(it.node);
> +		if (res.start > U32_MAX)
>  			return -EINVAL;
> -		}
> 
>  		/* No need to translate pa to da, R-Car use same map */
> -		da = rmem->base;
> +		da = res.start;
>  		mem = rproc_mem_entry_init(dev, NULL,
> -					   rmem->base,
> -					   rmem->size, da,
> +					   res.start,
> +					   resource_size(&res), da,
>  					   rcar_rproc_mem_alloc,
>  					   rcar_rproc_mem_release,
> -					   it.node->name);
> +					   res.name);
> 
> -		if (!mem) {
> -			of_node_put(it.node);
> +		if (!mem)
>  			return -ENOMEM;
> -		}
> 
>  		rproc_add_carveout(rproc, mem);
>  	}
> diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
> index e6566a9839dc..901b90de4953 100644
> --- a/drivers/remoteproc/st_remoteproc.c
> +++ b/drivers/remoteproc/st_remoteproc.c
> @@ -120,40 +120,35 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
>  	struct device *dev = rproc->dev.parent;
>  	struct device_node *np = dev->of_node;
>  	struct rproc_mem_entry *mem;
> -	struct reserved_mem *rmem;
> -	struct of_phandle_iterator it;
> -	int index = 0;
> -
> -	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> -	while (of_phandle_iterator_next(&it) == 0) {
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(dev, "unable to acquire memory-region\n");
> -			return -EINVAL;
> -		}
> +	int index = 0, mr = 0;
> +
> +	while (1) {
> +		struct resource res;
> +		int ret;
> +
> +		ret = of_reserved_mem_region_to_resource(np, mr++, &res);
> +		if (ret)
> +			return 0;
> 
>  		/*  No need to map vdev buffer */
> -		if (strcmp(it.node->name, "vdev0buffer")) {
> +		if (strcmp(res.name, "vdev0buffer")) {
>  			/* Register memory region */
>  			mem = rproc_mem_entry_init(dev, NULL,
> -						   (dma_addr_t)rmem->base,
> -						   rmem->size, rmem->base,
> +						   (dma_addr_t)res.start,
> +						   resource_size(&res), res.start,
>  						   st_rproc_mem_alloc,
>  						   st_rproc_mem_release,
> -						   it.node->name);
> +						   res.name);
>  		} else {
>  			/* Register reserved memory for vdev buffer allocation */
>  			mem = rproc_of_resm_mem_entry_init(dev, index,
> -							   rmem->size,
> -							   rmem->base,
> -							   it.node->name);
> +							   resource_size(&res),
> +							   res.start,
> +							   res.name);
>  		}
> 
> -		if (!mem) {
> -			of_node_put(it.node);
> +		if (!mem)
>  			return -ENOMEM;
> -		}
> 
>  		rproc_add_carveout(rproc, mem);
>  		index++;
> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> index b02b36a3f515..9d2bd8904c49 100644
> --- a/drivers/remoteproc/stm32_rproc.c
> +++ b/drivers/remoteproc/stm32_rproc.c
> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>  {
>  	struct device *dev = rproc->dev.parent;
>  	struct device_node *np = dev->of_node;
> -	struct of_phandle_iterator it;
>  	struct rproc_mem_entry *mem;
> -	struct reserved_mem *rmem;
>  	u64 da;
> -	int index = 0;
> +	int index = 0, mr = 0;
> 
>  	/* Register associated reserved memory regions */
> -	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> -	while (of_phandle_iterator_next(&it) == 0) {
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(dev, "unable to acquire memory-region\n");
> -			return -EINVAL;
> -		}
> +	while (1) {
> +		struct resource res;
> +		int ret;
> +
> +		ret = of_reserved_mem_region_to_resource(np, mr++, &res);
> +		if (ret)
> +			return 0;
> 
> -		if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
> -			of_node_put(it.node);
> -			dev_err(dev, "memory region not valid %pa\n",
> -				&rmem->base);
> +		if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
> +			dev_err(dev, "memory region not valid %pR\n", &res);
>  			return -EINVAL;
>  		}
> 
>  		/*  No need to map vdev buffer */
> -		if (strcmp(it.node->name, "vdev0buffer")) {
> +		if (strcmp(res.name, "vdev0buffer")) {

I tested your patches

The update introduces a regression here. The strcmp function never returns 0.
Indeed, it.node->name stores the memory region label "vdev0buffer," while
res.name stores the memory region name "vdev0buffer at 10042000."

Several remoteproc drivers may face the same issue as they embed similar code.

Regards,
Arnaud

>  			/* Register memory region */
>  			mem = rproc_mem_entry_init(dev, NULL,
> -						   (dma_addr_t)rmem->base,
> -						   rmem->size, da,
> +						   (dma_addr_t)res.start,
> +						   resource_size(&res), da,
>  						   stm32_rproc_mem_alloc,
>  						   stm32_rproc_mem_release,
> -						   it.node->name);
> +						   res.name);
> 
>  			if (mem)
>  				rproc_coredump_add_segment(rproc, da,
> -							   rmem->size);
> +							   resource_size(&res));
>  		} else {
>  			/* Register reserved memory for vdev buffer alloc */
>  			mem = rproc_of_resm_mem_entry_init(dev, index,
> -							   rmem->size,
> -							   rmem->base,
> -							   it.node->name);
> +							   resource_size(&res),
> +							   res.start,
> +							   res.name);
>  		}
> 
>  		if (!mem) {
> -			of_node_put(it.node);
>  			return -ENOMEM;
>  		}
> 
> diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> index a695890254ff..f02c835535bc 100644
> --- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> +++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> @@ -535,13 +535,10 @@ static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)
>  {
>  	struct device *dev = kproc->dev;
>  	struct device_node *np = dev->of_node;
> -	struct device_node *rmem_np;
> -	struct reserved_mem *rmem;
>  	int num_rmems;
>  	int ret, i;
> 
> -	num_rmems = of_property_count_elems_of_size(np, "memory-region",
> -						    sizeof(phandle));
> +	num_rmems = of_reserved_mem_region_count(np);
>  	if (num_rmems < 0) {
>  		dev_err(dev, "device does not reserved memory regions (%pe)\n",
>  			ERR_PTR(num_rmems));
> @@ -571,23 +568,20 @@ static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)
> 
>  	/* use remaining reserved memory regions for static carveouts */
>  	for (i = 0; i < num_rmems; i++) {
> -		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
> -		if (!rmem_np)
> -			return -EINVAL;
> +		struct resource res;
> 
> -		rmem = of_reserved_mem_lookup(rmem_np);
> -		of_node_put(rmem_np);
> -		if (!rmem)
> -			return -EINVAL;
> +		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
> +		if (ret)
> +			return ret;
> 
> -		kproc->rmem[i].bus_addr = rmem->base;
> +		kproc->rmem[i].bus_addr = res.start;
>  		/* 64-bit address regions currently not supported */
> -		kproc->rmem[i].dev_addr = (u32)rmem->base;
> -		kproc->rmem[i].size = rmem->size;
> -		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
> +		kproc->rmem[i].dev_addr = (u32)res.start;
> +		kproc->rmem[i].size = resource_size(&res);
> +		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
>  		if (!kproc->rmem[i].cpu_addr) {
> -			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
> -				i + 1, &rmem->base, &rmem->size);
> +			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
> +				i + 1, &res);
>  			return -ENOMEM;
>  		}
> 
> diff --git a/drivers/remoteproc/ti_k3_m4_remoteproc.c b/drivers/remoteproc/ti_k3_m4_remoteproc.c
> index a16fb165fced..8c7772cd6baf 100644
> --- a/drivers/remoteproc/ti_k3_m4_remoteproc.c
> +++ b/drivers/remoteproc/ti_k3_m4_remoteproc.c
> @@ -393,13 +393,10 @@ static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)
>  {
>  	struct device *dev = kproc->dev;
>  	struct device_node *np = dev->of_node;
> -	struct device_node *rmem_np;
> -	struct reserved_mem *rmem;
>  	int num_rmems;
>  	int ret, i;
> 
> -	num_rmems = of_property_count_elems_of_size(np, "memory-region",
> -						    sizeof(phandle));
> +	num_rmems = of_reserved_mem_region_count(np);
>  	if (num_rmems < 0) {
>  		dev_err(dev, "device does not reserved memory regions (%d)\n",
>  			num_rmems);
> @@ -428,23 +425,20 @@ static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)
> 
>  	/* use remaining reserved memory regions for static carveouts */
>  	for (i = 0; i < num_rmems; i++) {
> -		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
> -		if (!rmem_np)
> -			return -EINVAL;
> +		struct resource res;
> 
> -		rmem = of_reserved_mem_lookup(rmem_np);
> -		of_node_put(rmem_np);
> -		if (!rmem)
> -			return -EINVAL;
> +		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
> +		if (ret)
> +			return ret;
> 
> -		kproc->rmem[i].bus_addr = rmem->base;
> +		kproc->rmem[i].bus_addr = res.start;
>  		/* 64-bit address regions currently not supported */
> -		kproc->rmem[i].dev_addr = (u32)rmem->base;
> -		kproc->rmem[i].size = rmem->size;
> -		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
> +		kproc->rmem[i].dev_addr = (u32)res.start;
> +		kproc->rmem[i].size = resource_size(&res);
> +		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
>  		if (!kproc->rmem[i].cpu_addr) {
> -			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
> -				i + 1, &rmem->base, &rmem->size);
> +			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
> +				i + 1, &res);
>  			return -ENOMEM;
>  		}
> 
> diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
> index dbc513c5569c..9a7a61e0ecb8 100644
> --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c
> +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c
> @@ -966,13 +966,10 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
>  {
>  	struct device *dev = kproc->dev;
>  	struct device_node *np = dev_of_node(dev);
> -	struct device_node *rmem_np;
> -	struct reserved_mem *rmem;
>  	int num_rmems;
>  	int ret, i;
> 
> -	num_rmems = of_property_count_elems_of_size(np, "memory-region",
> -						    sizeof(phandle));
> +	num_rmems = of_reserved_mem_region_count(np);
>  	if (num_rmems <= 0) {
>  		dev_err(dev, "device does not have reserved memory regions, ret = %d\n",
>  			num_rmems);
> @@ -1003,16 +1000,13 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
> 
>  	/* use remaining reserved memory regions for static carveouts */
>  	for (i = 0; i < num_rmems; i++) {
> -		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
> -		if (!rmem_np)
> -			return -EINVAL;
> +		struct resource res;
> 
> -		rmem = of_reserved_mem_lookup(rmem_np);
> -		of_node_put(rmem_np);
> -		if (!rmem)
> -			return -EINVAL;
> +		ret = of_reserved_mem_region_to_resource(np, i + 1, &res);
> +		if (ret)
> +			return ret;
> 
> -		kproc->rmem[i].bus_addr = rmem->base;
> +		kproc->rmem[i].bus_addr = res.start;
>  		/*
>  		 * R5Fs do not have an MMU, but have a Region Address Translator
>  		 * (RAT) module that provides a fixed entry translation between
> @@ -1023,12 +1017,12 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
>  		 * addresses/supported memory regions are restricted to 32-bit
>  		 * bus addresses, and are identical
>  		 */
> -		kproc->rmem[i].dev_addr = (u32)rmem->base;
> -		kproc->rmem[i].size = rmem->size;
> -		kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
> +		kproc->rmem[i].dev_addr = (u32)res.start;
> +		kproc->rmem[i].size = resource_size(&res);
> +		kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res);
>  		if (!kproc->rmem[i].cpu_addr) {
> -			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
> -				i + 1, &rmem->base, &rmem->size);
> +			dev_err(dev, "failed to map reserved memory#%d at %pR\n",
> +				i + 1, &res);
>  			return -ENOMEM;
>  		}
> 
> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
> index 5aeedeaf3c41..000eeadd5a01 100644
> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
> @@ -460,49 +460,42 @@ static int add_mem_regions_carveout(struct rproc *rproc)
>  {
>  	struct rproc_mem_entry *rproc_mem;
>  	struct zynqmp_r5_core *r5_core;
> -	struct of_phandle_iterator it;
> -	struct reserved_mem *rmem;
>  	int i = 0;
> 
>  	r5_core = rproc->priv;
> 
>  	/* Register associated reserved memory regions */
> -	of_phandle_iterator_init(&it, r5_core->np, "memory-region", NULL, 0);
> +	while (1) {
> +		int err;
> +		struct resource res;
> 
> -	while (of_phandle_iterator_next(&it) == 0) {
> -		rmem = of_reserved_mem_lookup(it.node);
> -		if (!rmem) {
> -			of_node_put(it.node);
> -			dev_err(&rproc->dev, "unable to acquire memory-region\n");
> -			return -EINVAL;
> -		}
> +		err = of_reserved_mem_region_to_resource(r5_core->np, i++, &res);
> +		if (err)
> +			return 0;
> 
> -		if (!strcmp(it.node->name, "vdev0buffer")) {
> +		if (!strcmp(res.name, "vdev0buffer")) {
>  			/* Init reserved memory for vdev buffer */
>  			rproc_mem = rproc_of_resm_mem_entry_init(&rproc->dev, i,
> -								 rmem->size,
> -								 rmem->base,
> -								 it.node->name);
> +								 resource_size(&res),
> +								 res.start,
> +								 res.name);
>  		} else {
>  			/* Register associated reserved memory regions */
>  			rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL,
> -							 (dma_addr_t)rmem->base,
> -							 rmem->size, rmem->base,
> +							 (dma_addr_t)res.start,
> +							 resource_size(&res), res.start,
>  							 zynqmp_r5_mem_region_map,
>  							 zynqmp_r5_mem_region_unmap,
> -							 it.node->name);
> +							 res.name);
>  		}
> 
> -		if (!rproc_mem) {
> -			of_node_put(it.node);
> +		if (!rproc_mem)
>  			return -ENOMEM;
> -		}
> 
>  		rproc_add_carveout(rproc, rproc_mem);
> -		rproc_coredump_add_segment(rproc, rmem->base, rmem->size);
> +		rproc_coredump_add_segment(rproc, res.start, resource_size(&res));
> 
> -		dev_dbg(&rproc->dev, "reserved mem carveout %s addr=%llx, size=0x%llx",
> -			it.node->name, rmem->base, rmem->size);
> +		dev_dbg(&rproc->dev, "reserved mem carveout %pR\n", &res);
>  		i++;
>  	}
> 
> @@ -776,7 +769,6 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core)
>  	struct device *dev = r5_core->dev;
>  	struct rsc_tbl_data *rsc_data_va;
>  	struct resource res_mem;
> -	struct device_node *np;
>  	int ret;
> 
>  	/*
> @@ -786,14 +778,7 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core)
>  	 * contains that data structure which holds resource table address, size
>  	 * and some magic number to validate correct resource table entry.
>  	 */
> -	np = of_parse_phandle(r5_core->np, "memory-region", 0);
> -	if (!np) {
> -		dev_err(dev, "failed to get memory region dev node\n");
> -		return -EINVAL;
> -	}
> -
> -	ret = of_address_to_resource(np, 0, &res_mem);
> -	of_node_put(np);
> +	ret = of_reserved_mem_region_to_resource(r5_core->np, 0, &res_mem);
>  	if (ret) {
>  		dev_err(dev, "failed to get memory-region resource addr\n");
>  		return -EINVAL;
> --
> 2.47.2
> 
> _______________________________________________
> Linux-stm32 mailing list
> Linux-stm32 at st-md-mailman.stormreply.com
> https://st-md-mailman.stormreply.com/mailman/listinfo/linux-stm32


From peter.griffin at linaro.org  Wed Mar 19 08:30:24 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:24 +0000
Subject: [PATCH v2 7/7] scsi: ufs: exynos: gs101: put ufs device in reset
 on .suspend()
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-7-96722cc2ba1b@linaro.org>

GPIO_OUT[0] is connected to the reset pin of embedded UFS device.
Before powering off the phy assert the reset signal.

This is added as a gs101 specific suspend hook so as not to
have any unintended consequences for other SoCs supported by
this driver.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v1:
 * Add a gs101 specific suspend hook (Bart)
 * Drop asserting GPIO_OUT in .exit (Peter)
---
 drivers/ufs/host/ufs-exynos.c | 10 ++++++++++
 drivers/ufs/host/ufs-exynos.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 81a1f04411c0426d6fae931e75db5f4c8693daca..3e545af536e53e06b66c624ed0dc6dc7de13549f 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1701,6 +1701,12 @@ static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
 	}
 }
 
+static int gs101_ufs_suspend(struct exynos_ufs *ufs)
+{
+	hci_writel(ufs, 0 << 0, HCI_GPIO_OUT);
+	return 0;
+}
+
 static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
 	enum ufs_notify_change_status status)
 {
@@ -1709,6 +1715,9 @@ static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
 	if (status == PRE_CHANGE)
 		return 0;
 
+	if (ufs->drv_data->suspend)
+		ufs->drv_data->suspend(ufs);
+
 	if (!ufshcd_is_link_active(hba))
 		phy_power_off(ufs->phy);
 
@@ -2171,6 +2180,7 @@ static const struct exynos_ufs_drv_data gs101_ufs_drvs = {
 	.pre_link		= gs101_ufs_pre_link,
 	.post_link		= gs101_ufs_post_link,
 	.pre_pwr_change		= gs101_ufs_pre_pwr_change,
+	.suspend		= gs101_ufs_suspend,
 };
 
 static const struct of_device_id exynos_ufs_of_match[] = {
diff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h
index a345809af79dc528ad518d3572fe8be034341ee0..abe7e472759e94fef353e9a97bc9b55f6a0324c1 100644
--- a/drivers/ufs/host/ufs-exynos.h
+++ b/drivers/ufs/host/ufs-exynos.h
@@ -192,6 +192,7 @@ struct exynos_ufs_drv_data {
 			       const struct ufs_pa_layer_attr *pwr);
 	int (*pre_hce_enable)(struct exynos_ufs *ufs);
 	int (*post_hce_enable)(struct exynos_ufs *ufs);
+	int (*suspend)(struct exynos_ufs *ufs);
 };
 
 struct ufs_phy_time_cfg {

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:17 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:17 +0000
Subject: [PATCH v2 0/7] ufs-exynos stability fixes for gs101
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>

Hi folks,

This series fixes several stability issues with the upstream ufs-exynos
driver, specifically for the gs101 SoC found in Pixel 6.

The main fix is regarding the IO cache coherency setting and ensuring
that it is correctly applied depending on if the dma-coherent property
is specified in device tree. This fixes the UFS stability issues on gs101
and I would imagine will also fix issues on exynosauto platform that
seems to have similar iocc shareability bits.

Additionally the phy reference counting is fixed which allows module
load/unload to work reliably and keeps the phy state machine in sync
with the controller glue driver.

regards,

Peter

Changes since v1:
 * Added patch for correct handling of iocc depedent on dma-coherent property
 * Rebased onto next-20250319
 * Add a gs101 specific suspend hook (Bart)
 * Drop asserting GPIO_OUT in .exit() (Peter)
 * Remove superfluous blank line (Bart)
 * Update PRDT_PREFECT_EN to PRDT_PREFETCH_EN (Bart)
 * Update commit description for desctype type 3 (Eric)
 * https://lore.kernel.org/lkml/20250226220414.343659-1-peter.griffin at linaro.org/

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Peter Griffin (7):
      scsi: ufs: exynos: ensure pre_link() executes before exynos_ufs_phy_init()
      scsi: ufs: exynos: move ufs shareability value to drvdata
      scsi: ufs: exynos: disable iocc if dma-coherent property isn't set
      scsi: ufs: exynos: ensure consistent phy reference counts
      scsi: ufs: exynos: Enable PRDT pre-fetching with UFSHCD_CAP_CRYPTO
      scsi: ufs: exynos: Move phy calls to .exit() callback
      scsi: ufs: exynos: gs101: put ufs device in reset on .suspend()

 drivers/ufs/host/ufs-exynos.c | 85 ++++++++++++++++++++++++++++++++-----------
 drivers/ufs/host/ufs-exynos.h |  6 ++-
 2 files changed, 68 insertions(+), 23 deletions(-)
---
base-commit: 433ccb6f2e879866b8601fcb1de14e316cdb0d39
change-id: 20250319-exynos-ufs-stability-fixes-e8da9862e3dc

Best regards,
-- 
Peter Griffin <peter.griffin at linaro.org>



From peter.griffin at linaro.org  Wed Mar 19 08:30:18 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:18 +0000
Subject: [PATCH v2 1/7] scsi: ufs: exynos: ensure pre_link() executes
 before exynos_ufs_phy_init()
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-1-96722cc2ba1b@linaro.org>

Ensure clocks are enabled before configuring unipro. Additionally move the
pre_link() hook before the exynos_ufs_phy_init() calls. This means the
register write sequence  more closely resembles the ordering of the
downstream driver.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/ufs/host/ufs-exynos.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index d7539cda97da5023ec8a2852ff3f5191642ffd37..0c8c2e41e851cdbefc80a66d87273b7e8fcf9d4d 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1049,9 +1049,14 @@ static int exynos_ufs_pre_link(struct ufs_hba *hba)
 	exynos_ufs_config_intr(ufs, DFES_DEF_L4_ERRS, UNIPRO_L4);
 	exynos_ufs_set_unipro_pclk_div(ufs);
 
+	exynos_ufs_setup_clocks(hba, true, PRE_CHANGE);
+
 	/* unipro */
 	exynos_ufs_config_unipro(ufs);
 
+	if (ufs->drv_data->pre_link)
+		ufs->drv_data->pre_link(ufs);
+
 	/* m-phy */
 	exynos_ufs_phy_init(ufs);
 	if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR)) {
@@ -1059,11 +1064,6 @@ static int exynos_ufs_pre_link(struct ufs_hba *hba)
 		exynos_ufs_config_phy_cap_attr(ufs);
 	}
 
-	exynos_ufs_setup_clocks(hba, true, PRE_CHANGE);
-
-	if (ufs->drv_data->pre_link)
-		ufs->drv_data->pre_link(ufs);
-
 	return 0;
 }
 

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:19 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:19 +0000
Subject: [PATCH v2 2/7] scsi: ufs: exynos: move ufs shareability value to
 drvdata
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-2-96722cc2ba1b@linaro.org>

gs101 IO coherency shareability bits differ from exynosauto SoC. To
support both SoCs move this info the SoC drvdata.

Currently both the value and mask are the same for both gs101 and
exynosauto, thus we use the same value.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Fixes: d11e0a318df8 ("scsi: ufs: exynos: Add support for Tensor gs101 SoC")
Cc: stable at vger.kernel.org
---
 drivers/ufs/host/ufs-exynos.c | 20 ++++++++++++++------
 drivers/ufs/host/ufs-exynos.h |  2 ++
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 0c8c2e41e851cdbefc80a66d87273b7e8fcf9d4d..f393d42a659f821225e67e3e5d323478456ca3af 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -92,11 +92,16 @@
 				 UIC_TRANSPORT_NO_CONNECTION_RX |\
 				 UIC_TRANSPORT_BAD_TC)
 
-/* FSYS UFS Shareability */
-#define UFS_WR_SHARABLE		BIT(2)
-#define UFS_RD_SHARABLE		BIT(1)
-#define UFS_SHARABLE		(UFS_WR_SHARABLE | UFS_RD_SHARABLE)
-#define UFS_SHAREABILITY_OFFSET	0x710
+/* UFS Shareability */
+#define UFS_EXYNOSAUTO_WR_SHARABLE	BIT(2)
+#define UFS_EXYNOSAUTO_RD_SHARABLE	BIT(1)
+#define UFS_EXYNOSAUTO_SHARABLE		(UFS_EXYNOSAUTO_WR_SHARABLE | \
+					 UFS_EXYNOSAUTO_RD_SHARABLE)
+#define UFS_GS101_WR_SHARABLE		BIT(1)
+#define UFS_GS101_RD_SHARABLE		BIT(0)
+#define UFS_GS101_SHARABLE		(UFS_GS101_WR_SHARABLE | \
+					 UFS_GS101_RD_SHARABLE)
+#define UFS_SHAREABILITY_OFFSET		0x710
 
 /* Multi-host registers */
 #define MHCTRL			0xC4
@@ -210,7 +215,7 @@ static int exynos_ufs_shareability(struct exynos_ufs *ufs)
 	if (ufs->sysreg) {
 		return regmap_update_bits(ufs->sysreg,
 					  ufs->shareability_reg_offset,
-					  UFS_SHARABLE, UFS_SHARABLE);
+					  ufs->iocc_mask, ufs->iocc_mask);
 	}
 
 	return 0;
@@ -1174,6 +1179,7 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs)
 		}
 	}
 
+	ufs->iocc_mask = ufs->drv_data->iocc_mask;
 	ufs->pclk_avail_min = PCLK_AVAIL_MIN;
 	ufs->pclk_avail_max = PCLK_AVAIL_MAX;
 
@@ -2035,6 +2041,7 @@ static const struct exynos_ufs_drv_data exynosauto_ufs_drvs = {
 	.opts			= EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL |
 				  EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR |
 				  EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX,
+	.iocc_mask		= UFS_EXYNOSAUTO_SHARABLE,
 	.drv_init		= exynosauto_ufs_drv_init,
 	.post_hce_enable	= exynosauto_ufs_post_hce_enable,
 	.pre_link		= exynosauto_ufs_pre_link,
@@ -2136,6 +2143,7 @@ static const struct exynos_ufs_drv_data gs101_ufs_drvs = {
 	.opts			= EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR |
 				  EXYNOS_UFS_OPT_UFSPR_SECURE |
 				  EXYNOS_UFS_OPT_TIMER_TICK_SELECT,
+	.iocc_mask		= UFS_GS101_SHARABLE,
 	.drv_init		= gs101_ufs_drv_init,
 	.pre_link		= gs101_ufs_pre_link,
 	.post_link		= gs101_ufs_post_link,
diff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h
index aac5172761899a5dd8ad98f9ee34b1671dd27880..17696b3768debd641188b5089585b6d303de7451 100644
--- a/drivers/ufs/host/ufs-exynos.h
+++ b/drivers/ufs/host/ufs-exynos.h
@@ -181,6 +181,7 @@ struct exynos_ufs_drv_data {
 	struct exynos_ufs_uic_attr *uic_attr;
 	unsigned int quirks;
 	unsigned int opts;
+	u32 iocc_mask;
 	/* SoC's specific operations */
 	int (*drv_init)(struct exynos_ufs *ufs);
 	int (*pre_link)(struct exynos_ufs *ufs);
@@ -231,6 +232,7 @@ struct exynos_ufs {
 	const struct exynos_ufs_drv_data *drv_data;
 	struct regmap *sysreg;
 	u32 shareability_reg_offset;
+	u32 iocc_mask;
 
 	u32 opts;
 #define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL		BIT(0)

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:20 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:20 +0000
Subject: [PATCH v2 3/7] scsi: ufs: exynos: disable iocc if dma-coherent
 property isn't set
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-3-96722cc2ba1b@linaro.org>

If dma-coherent property isn't set then descriptors are non-cacheable
and the iocc shareability bits should be disabled. Without this UFS
can end up in an incompatible configuration and suffer from random
cache related stability issues.

Suggested-by: Bart Van Assche <bvanassche at acm.org>
Fixes: cc52e15397cc ("scsi: ufs: ufs-exynos: Support ExynosAuto v9 UFS")
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Cc: Chanho Park <chanho61.park at samsung.com>
Cc: stable at vger.kernel.org
---
 drivers/ufs/host/ufs-exynos.c | 17 +++++++++++++----
 drivers/ufs/host/ufs-exynos.h |  3 ++-
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index f393d42a659f821225e67e3e5d323478456ca3af..61b03e493cc1ddba17179a9f22e5b59ece02458b 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -214,8 +214,8 @@ static int exynos_ufs_shareability(struct exynos_ufs *ufs)
 	/* IO Coherency setting */
 	if (ufs->sysreg) {
 		return regmap_update_bits(ufs->sysreg,
-					  ufs->shareability_reg_offset,
-					  ufs->iocc_mask, ufs->iocc_mask);
+					  ufs->iocc_offset,
+					  ufs->iocc_mask, ufs->iocc_val);
 	}
 
 	return 0;
@@ -1173,13 +1173,22 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs)
 		ufs->sysreg = NULL;
 	else {
 		if (of_property_read_u32_index(np, "samsung,sysreg", 1,
-					       &ufs->shareability_reg_offset)) {
+					       &ufs->iocc_offset)) {
 			dev_warn(dev, "can't get an offset from sysreg. Set to default value\n");
-			ufs->shareability_reg_offset = UFS_SHAREABILITY_OFFSET;
+			ufs->iocc_offset = UFS_SHAREABILITY_OFFSET;
 		}
 	}
 
 	ufs->iocc_mask = ufs->drv_data->iocc_mask;
+	/*
+	 * no 'dma-coherent' property means the descriptors are
+	 * non-cacheable so iocc shareability should be disabled.
+	 */
+	if (of_dma_is_coherent(dev->of_node))
+		ufs->iocc_val = ufs->iocc_mask;
+	else
+		ufs->iocc_val = 0;
+
 	ufs->pclk_avail_min = PCLK_AVAIL_MIN;
 	ufs->pclk_avail_max = PCLK_AVAIL_MAX;
 
diff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h
index 17696b3768debd641188b5089585b6d303de7451..a345809af79dc528ad518d3572fe8be034341ee0 100644
--- a/drivers/ufs/host/ufs-exynos.h
+++ b/drivers/ufs/host/ufs-exynos.h
@@ -231,8 +231,9 @@ struct exynos_ufs {
 	ktime_t entry_hibern8_t;
 	const struct exynos_ufs_drv_data *drv_data;
 	struct regmap *sysreg;
-	u32 shareability_reg_offset;
+	u32 iocc_offset;
 	u32 iocc_mask;
+	u32 iocc_val;
 
 	u32 opts;
 #define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL		BIT(0)

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:21 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:21 +0000
Subject: [PATCH v2 4/7] scsi: ufs: exynos: ensure consistent phy reference
 counts
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-4-96722cc2ba1b@linaro.org>

ufshcd_link_startup() can call ufshcd_vops_link_startup_notify()
multiple times when retrying. This causes the phy reference count
to keep increasing and the phy to not properly re-initialize.

If the phy has already been previously powered on, first issue a
phy_power_off() and phy_exit(), before re-initializing and powering
on again.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Fixes: 3d73b200f989 ("scsi: ufs: ufs-exynos: Change ufs phy control sequence")
Cc: stable at vger.kernel.org
---
 drivers/ufs/host/ufs-exynos.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 61b03e493cc1ddba17179a9f22e5b59ece02458b..34e16e198830d086cbdb6cb0b027ca92687b2ae6 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -962,6 +962,12 @@ static int exynos_ufs_phy_init(struct exynos_ufs *ufs)
 	}
 
 	phy_set_bus_width(generic_phy, ufs->avail_ln_rx);
+
+	if (generic_phy->power_count) {
+		phy_power_off(generic_phy);
+		phy_exit(generic_phy);
+	}
+
 	ret = phy_init(generic_phy);
 	if (ret) {
 		dev_err(hba->dev, "%s: phy init failed, ret = %d\n",

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:22 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:22 +0000
Subject: [PATCH v2 5/7] scsi: ufs: exynos: Enable PRDT pre-fetching with
 UFSHCD_CAP_CRYPTO
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-5-96722cc2ba1b@linaro.org>

PRDT_PREFETCH_ENABLE[31] bit should be set when desctype field of
fmpsecurity0 register is type2 (double file encryption) or type3
(support for file and disk encryption). Setting this bit enables
PRDT pre-fetching on both TXPRDT and RXPRDT.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v1:
* Update PRDT_PREFECT_EN to PRDT_PREFETCH_EN (Bart)
* Update commit description for desctype type 3 (Eric)
---
 drivers/ufs/host/ufs-exynos.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 34e16e198830d086cbdb6cb0b027ca92687b2ae6..f6980f05bd5555b351070fe33d0afda469fe498c 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -34,7 +34,7 @@
  * Exynos's Vendor specific registers for UFSHCI
  */
 #define HCI_TXPRDT_ENTRY_SIZE	0x00
-#define PRDT_PREFECT_EN		BIT(31)
+#define PRDT_PREFETCH_EN	BIT(31)
 #define HCI_RXPRDT_ENTRY_SIZE	0x04
 #define HCI_1US_TO_CNT_VAL	0x0C
 #define CNT_VAL_1US_MASK	0x3FF
@@ -1098,12 +1098,17 @@ static int exynos_ufs_post_link(struct ufs_hba *hba)
 	struct exynos_ufs *ufs = ufshcd_get_variant(hba);
 	struct phy *generic_phy = ufs->phy;
 	struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+	u32 val = ilog2(DATA_UNIT_SIZE);
 
 	exynos_ufs_establish_connt(ufs);
 	exynos_ufs_fit_aggr_timeout(ufs);
 
 	hci_writel(ufs, 0xa, HCI_DATA_REORDER);
-	hci_writel(ufs, ilog2(DATA_UNIT_SIZE), HCI_TXPRDT_ENTRY_SIZE);
+
+	if (hba->caps & UFSHCD_CAP_CRYPTO)
+		val |= PRDT_PREFETCH_EN;
+	hci_writel(ufs, val, HCI_TXPRDT_ENTRY_SIZE);
+
 	hci_writel(ufs, ilog2(DATA_UNIT_SIZE), HCI_RXPRDT_ENTRY_SIZE);
 	hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE);
 	hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE);

-- 
2.49.0.rc1.451.g8f38331e32-goog



From peter.griffin at linaro.org  Wed Mar 19 08:30:23 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 19 Mar 2025 15:30:23 +0000
Subject: [PATCH v2 6/7] scsi: ufs: exynos: Move phy calls to .exit()
 callback
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <20250319-exynos-ufs-stability-fixes-v2-6-96722cc2ba1b@linaro.org>

ufshcd_pltfrm_remove() calls ufshcd_remove(hba) which in turn calls
ufshcd_hba_exit().

By moving the phy_power_off() and phy_exit() calls to the newly created
.exit callback they get called by ufshcd_variant_hba_exit() before
ufshcd_hba_exit() turns off the regulators. This is also similar flow
to the ufs-qcom driver.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
Changes since v1:
* Remove superfluous blank line (Bart)
---
 drivers/ufs/host/ufs-exynos.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index f6980f05bd5555b351070fe33d0afda469fe498c..81a1f04411c0426d6fae931e75db5f4c8693daca 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1523,6 +1523,14 @@ static int exynos_ufs_init(struct ufs_hba *hba)
 	return ret;
 }
 
+static void exynos_ufs_exit(struct ufs_hba *hba)
+{
+	struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+	phy_power_off(ufs->phy);
+	phy_exit(ufs->phy);
+}
+
 static int exynos_ufs_host_reset(struct ufs_hba *hba)
 {
 	struct exynos_ufs *ufs = ufshcd_get_variant(hba);
@@ -1978,6 +1986,7 @@ static int gs101_ufs_pre_pwr_change(struct exynos_ufs *ufs,
 static const struct ufs_hba_variant_ops ufs_hba_exynos_ops = {
 	.name				= "exynos_ufs",
 	.init				= exynos_ufs_init,
+	.exit				= exynos_ufs_exit,
 	.hce_enable_notify		= exynos_ufs_hce_enable_notify,
 	.link_startup_notify		= exynos_ufs_link_startup_notify,
 	.pwr_change_notify		= exynos_ufs_pwr_change_notify,
@@ -2016,13 +2025,7 @@ static int exynos_ufs_probe(struct platform_device *pdev)
 
 static void exynos_ufs_remove(struct platform_device *pdev)
 {
-	struct ufs_hba *hba =  platform_get_drvdata(pdev);
-	struct exynos_ufs *ufs = ufshcd_get_variant(hba);
-
 	ufshcd_pltfrm_remove(pdev);
-
-	phy_power_off(ufs->phy);
-	phy_exit(ufs->phy);
 }
 
 static struct exynos_ufs_uic_attr exynos7_uic_attr = {

-- 
2.49.0.rc1.451.g8f38331e32-goog



From andrew at lunn.ch  Wed Mar 19 08:39:57 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 19 Mar 2025 16:39:57 +0100
Subject: [PATCH v2 5/5] arm64: dts: ti: Add TQ-Systems TQMa62xx SoM and
 MBa62xx carrier board Device Trees
In-Reply-To: <570d9c2a25b437ab75f14104b354027210809028.camel@ew.tq-group.com>
References: <a9c5cfda-e3e3-436a-8d05-b2f096157cfe@lunn.ch>
 <c902a56cf34838f60cee67624bb923e91d74e9e0.camel@ew.tq-group.com>
 <d25b1447-c28b-4998-b238-92672434dc28@lunn.ch>
 <e16076d16349e929af82fa987a658bff1d9804c4.camel@ew.tq-group.com>
 <a2a2f201-73a4-4a99-baef-0d593a88c872@lunn.ch>
 <309052f3f69950fe43390505cc7254aee8c8f5c6.camel@ew.tq-group.com>
 <2953e10c-0a57-4d49-b831-3864a07eefd5@lunn.ch>
 <e6ee878f655c31473bca54e4187d9006a19158b1.camel@ew.tq-group.com>
 <262ff436-2334-43bb-a998-ab48f06ea0e3@lunn.ch>
 <570d9c2a25b437ab75f14104b354027210809028.camel@ew.tq-group.com>
Message-ID: <c277cc6b-6624-44df-94ff-45b341859b62@lunn.ch>

> > > Fixing MAC drivers to interpret the values without
> > > "id" to mean that there is a delay on the PCB will break existing Device Trees,
> > > so that's no good.
> > 
> > You need to look at it broken driver by broken driver. I _think_ the
> > Aspeed case can be fixed. Others we need to look at the details. Maybe
> > in some cases we do need to add a warning to the device tree binding
> > the driver is FUBAR and has special, broken meaning for 'rgmii'.
> 
> I don't know about Aspeed (maybe you're mixing something up, or I'm not aware of
> something?) - in the case of the TI driver I'm dealing with, this is indeed
> possible to fix up because the MAC always adds a delay, it is not configurable.

The Aspeed driver also gets RGMII delays wrong. And there is an
ongoing discussion about how to fix it. The discussions there probably
apply to most drivers which get RGMII delays wrong. Following the
discussions on how RGMII is broken in other places might help you fix
the TI driver.

> The whole point of my suggestions is to allow fixing the drivers while staying
> compatible with old, broken Device Trees. If we could add a property 'phy-mode-
> is-fubar' to old Device Trees, we could just fix them instead - but we can only
> fix in-tree DTS, and it will only have an effect on systems that update their
> DTBs with their kernel, so I believe this simply isn't an option because of
> backwards compat guarantees for Device Trees.

So you need the TI driver to accept the broken 'rgmii', and the
correct 'rgmii-id'. You say the MAC hardware always adds the delay. So

1) Patch the driver to test for 'rgmii', and issues a warning that the
   DT is wrong and needs updating.

2) Add the missing masking of the value passed to the PHY. Since the
   MAC driver is adding the delays, it needs to modify the
   phy_interface_t passed to phy_connect(), masking out the delays the
   MAC is adding. This is an established procedure for MACs which
   implement the delays, rather than ask the PHY to do it. It then
   becomes possible to use the correct 'rgmii-id' value.

3) Patch the TI .dts files to use the correct rgmii-id. That makes the
   warnings added in 1) go away.

This is a lot simpler than the Aspeed case, but the basic discussion
taking place with the Aspeed driver would give you useful background.

	Andrew


From mripard at kernel.org  Wed Mar 19 09:16:53 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Wed, 19 Mar 2025 17:16:53 +0100
Subject: [PATCH v7 00/11] drm/bridge: add devm_drm_bridge_alloc() with
 bridge refcount
In-Reply-To: <20250317155607.68cff522@booty>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
 <20250314-daft-woodoo-cheetah-e029c5@houat>
 <20250317155607.68cff522@booty>
Message-ID: <20250319-stylish-lime-mongoose-0a18ad@houat>

On Mon, Mar 17, 2025 at 03:56:07PM +0100, Luca Ceresoli wrote:
> Hello Maxime,
> 
> On Fri, 14 Mar 2025 19:21:01 +0100
> Maxime Ripard <mripard at kernel.org> wrote:
> 
> > Hi,
> > 
> > On Fri, Mar 14, 2025 at 11:31:13AM +0100, Luca Ceresoli wrote:
> > > This series improves the way DRM bridges are allocated and
> > > initialized and makes them reference-counted. The goal of reference
> > > counting is to avoid use-after-free by drivers which got a pointer
> > > to a bridge and keep it stored and used even after the bridge has
> > > been deallocated.
> > > 
> > > The overall goal is supporting Linux devices with a DRM pipeline
> > > whose final components can be hot-plugged and hot-unplugged,
> > > including one or more bridges. For more details see the big picture
> > > [0].
> > > 
> > > DRM bridge drivers will have to be adapted to the new API, which is
> > > pretty simple for most cases. Refcounting will have to be adopted
> > > on the two sides: all functions returning a bridge pointer and all
> > > code obtaining such a pointer. This series has just an overview of
> > > some of those conversions, because for now the main goal is to
> > > agree on the API.
> > > 
> > > Series layout:
> > > 
> > >  1. Add the new API and refcounting:
> > > 
> > >     drm/bridge: add devm_drm_bridge_alloc()
> > >     drm/bridge: add support for refcounting
> > > 
> > >  2. get/put the reference in basic operations in the bridge core:
> > > 
> > >     drm/bridge: get/put the bridge reference in
> > > drm_bridge_add/remove() drm/bridge: get/put the bridge reference in
> > > drm_bridge_attach/detach()
> > > 
> > >  3. as an example of changes for bridge consumers, get a reference
> > > for the bridge returned by drm_bridge_chain_get_first_bridge(),
> > > have it put by all callers (all users will be covered later on
> > > separately):
> > > 
> > >     drm/bridge: add a cleanup action for scope-based
> > > drm_bridge_put() invocation drm/bridge: get the bridge returned by
> > > drm_bridge_chain_get_first_bridge() drm/mxsfb: put the bridge
> > > returned by drm_bridge_chain_get_first_bridge() drm/atomic-helper:
> > > put the bridge returned by drm_bridge_chain_get_first_bridge()
> > > drm/probe-helper: put the bridge returned by
> > > drm_bridge_chain_get_first_bridge()
> > > 
> > >  4. convert a few bridge drivers (bridge providers) to the new API:
> > > 
> > >     drm/bridge: ti-sn65dsi83: use dynamic lifetime management
> > >     drm/bridge: samsung-dsim: use dynamic lifetime management
> > > 
> > > This work was formerly a part of my v6 DRM bridge hotplug
> > > series[0], now split as a standalone series with many improvements,
> > > hence the "v7" version number.  
> > 
> > Except for one patch where I had comments, I think the series is in
> > excellent shape. We're still missing a couple of things to close this
> > topic though:
> > 
> >   - Converting the other bridge iterators/accessors to take / put the
> > references
> 
> I sent a couple in this series as you had asked, to show how conversion
> looks like. But I have a large part of this conversion partially done
> already, and it is the largest part of the refcounting work in terms of
> touched files due to the large number of drivers using the iterators
> and accessors. Here are the functions to convert:
> 
>  A) drm_bridge_chain_get_first_bridge
>  B) drm_bridge_get_prev_bridge
>  C) drm_bridge_get_next_bridge
>  D) drm_for_each_bridge_in_chain
>  E) drm_bridge_connector_init
>  F) of_drm_find_bridge
> 
> A) is present in this series as an example but I don't think it should
> be applied until all bridge drivers are converted to
> drm_bridge_alloc(). Otherwise for not-yet-converted bridge drivers we'd
> have drm_bridge_get/put() operating on an uninitialized kref, and
> __drm_bridge_free() called on non-refcounted bridges, so I think we'd
> see fireworks.
> 
> In the previous iteration I used drm_bridge_is_refcounted() in
> drm_bridge_get/put() to allow a progressive migration, but if we want
> to convert everything in a single run we need to first convert all
> bridges to drm_bridge_alloc() and then convert all accessors.
> 
> The same reasoning applies to patches 3-4 which add get/put to
> drm_bridge_add/remove() and _attach/detach().

Agreed.

> B) to E) are ready in my work branch, about 20 patches in total.
> Indeed item E) is a special case but it is handled there too.
> 
> Item F) is the beast, because of the reverse call graph of
> of_drm_find_bridge() which includes drm_of_find_panel_or_bridge() and
> then *_of_get_bridge(), each having a few dozen callers, and leading
> to the panel_bridge topic. I have converted maybe half of the users of
> accessors in F), it's 35 patches but it's the easy half and I still need
> to tackle to hardest ones.

One thing to keep in mind is that, while it's not correct, if the bridge
has been allocated with devm_drm_bridge_alloc, it's not worse either. If
you're not getting a reference to your pointer, the point is buggy,
sure, but it's just as buggy as before, and in the same situations.

So we can make that gradually if it's more convenient.

One way to solve it would be that, for example, of_drm_find_bridge is
oddly named according to our convention and it would make more sense to
be called drm_of_find_bridge().

So maybe we can just create drm_of_find_bridge() that takes a reference,
make of_drm_find_bridge() deprecated in favour of drm_of_find_bridge(),
add a TODO, and call it a day. People will gradually switch to the new
API over time.

> >   - Mass converting the drivers to devm_drm_bridge_alloc
> 
> Again I sent a couple in this series as you had asked, to show how
> conversion looks like for the typical bridge driver. There are ~70
> drivers to convert in total and I think most will be easy as the two
> examples presented here.
> 
> I think this should be merged entirely before merging any accessor
> changes, as explained above.

Agreed.

> >   - Documenting somewhere (possibly in drm_bridge_init?) that it
> > really shouldn't be used anymore
> 
> I'm afraid there is no drm_bridge_init(), bridge drivers just do
> [devm_]kzalloc and set fields explicitly. So I don't think there is a
> place to document this.

Oh, right.

Then, drm_bridge_add() would be a good candidate too to mention that
bridges must be allocated using devm_drm_bridge_alloc().

> However I used to have a documentation patch until v6 [0], and I think
> it should be revived and resent at some point, after removing the
> "legacy mode" as we are converting all drivers at once. BTW I also have
> a kunittest patch that should be revived. Do you still prefer me to
> resend these two patches as a separate series, waiting after the API in
> this series is applied?

Both options work for me.

> Overall, I think this could be the path forward, let me know if
> youthink it should be done differently:
> 
>  A. have patches 1 and 2 of this series applied
>     (why not, even patches 10-11)

I had some comments on patch 2, but it's ok for me on principle.

>  B. after (A), send series to convert all bridge drivers to new API
>     (includes patches 10-11 of this series if not applied already)
>  C. after (A), send documentation and kunittest patches
>  D. after (B), add get/put to drm_bridge_add/remove() + attach/detech()
>     (patches 3-4 in this series)
>  E. after (B), send series to convert accessors (including patches 5-9
>     in this series which convert drm_bridge_chain_get_first_bridge()
>     and its users)

Sounds like a plan.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/5298c78a/attachment.sig>

From andersson at kernel.org  Wed Mar 19 09:25:16 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Wed, 19 Mar 2025 11:25:16 -0500
Subject: [GIT PULL] More Qualcomm Arm64 Devicetree updates for v6.15
Message-ID: <20250319162517.2292540-1-andersson@kernel.org>


The following changes since commit d09ab685a8f51ba412d37305ea62628a01cbea57:

  arm64: dts: qcom: x1e80100-qcp: Add WiFi/BT pwrseq (2025-03-03 22:54:17 -0600)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-arm64-for-6.15-2

for you to fetch changes up to 1a7646d784513dcf0e8b16c1d9124ef54b4ec5e0:

  arm64: dts: qcom: x1e001de-devkit: fix USB retimer reset polarity (2025-03-18 14:51:22 -0500)

----------------------------------------------------------------
More Qualcomm Arm64 Devicetree updates for v6.15

Devicetree for the Xiaomi Redmi Note 8 is added.

The IPQ5424 gains MMC, LEDs and buttons, while the IPQ9574 gains NSS
clock controller and SPI NAND support.

The LPG/PWM node is added to PM8937 and Xiaomi Redmi 5A gains display
backlight control.

The USB Type-C orientation GPIO is added on the QCS6490 Rb3Gen2 and the
vision mezzanine is described.
The Fairphone FP5 gains touchscreen support, and the QCM6490 IDP board
gains a required listed of protected clocks.

On SA8775P CTCU and ETR nodes are added, and the CPUfreq throttling
interrupts are added.

On SAR2130P PCIe EP device nodes are added.

The camera subsystem in SC7280 is described.

Samsung Galaxy S9 SM-G9600 gains a description of the MAX77705 used for
charging, fuel gauge, haptic, and LED, as well as the PMIC used for
display and touchscreen, which then is used to enable the touchscreen.

Display and GPU are enabled for the Nothing Phone (1).

On SM8450 the PCIe endpoint controller is described.

SM8650 is transitioned to per-CPU interrupt partitions, in order to
properly describe the PMU interrupts. Missing Coresight ETE instances
are added as well.

On SM8750 the cluster idle states are corrected, then audio and compute
DSPs are introduced, together with the crypto and rng blocks.

On the X Elite platform RTC is enabled. Regulators that are feeding
resources that should be always on is marked as such on a variety of
boards.

Support for external Display is introduced on the reference device and
the Lenovo Thinkpad T14s. The Asus Vivobook S 15 gains support for its
USB-A ports and uSD card reader. The reference device also gains support
for the volume keys found on the debug board.

The Lenovo Thinkpad T14s DeviceTree is split in two, in order to
describe the LCD and OLED variants.

Missing properties for the crypto BAM is introduced on a variety of
platforms, taking care of a long standing error message in the kernel
log during boot.

----------------------------------------------------------------
Abel Vesa (7):
      arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers
      arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support
      arm64: dts: qcom: x1e80100-t14s: Describe the Parade PS8830 retimers
      arm64: dts: qcom: x1e80100-t14s: Enable external DisplayPort support
      dt-bindings: arm: qcom: Document Lenovo ThinkPad T14s Gen 6 LCD and OLED
      arm64: dts: qcom: x1e78100-t14s: Add LCD variant with backlight support
      arm64: dts: qcom: x1e78100-t14s: Add OLED variant

Abhinaba Rakshit (1):
      arm64: dts: qcom: qcs615: add TRNG node

Alexey Klimov (1):
      arm64: dts: qcom: qrb5165-rb5: add compressed playback support

Barnab?s Cz?m?n (1):
      arm64: dts: qcom: msm8917-xiaomi-riva: Add display backlight

Bjorn Andersson (1):
      Merge branch '20250313110359.242491-1-quic_mmanikan at quicinc.com' into arm64-for-6.15

Daniil Titov (1):
      arm64: dts: qcom: pm8937: Add LPG PWM driver

Devi Priya (3):
      dt-bindings: clock: gcc-ipq9574: Add definition for GPLL0_OUT_AUX
      dt-bindings: clock: Add ipq9574 NSSCC clock and reset definitions
      arm64: dts: qcom: ipq9574: Add nsscc node

Dmitry Baryshkov (2):
      arm64: dts: qcom: sar2130p: add PCIe EP device nodes
      arm64: dts: qcom: sm8450: add PCIe EP device nodes

Dzmitry Sankouski (9):
      arm64: dts: qcom: sdm845: enable gmu
      arm64: dts: qcom: sdm845-starqltechn: remove wifi
      arm64: dts: qcom: sdm845-starqltechn: fix usb regulator mistake
      arm64: dts: qcom: sdm845-starqltechn: refactor node order
      arm64: dts: qcom: sdm845-starqltechn: remove excess reserved gpios
      arm64: dts: qcom: sdm845-starqltechn: add gpio keys
      arm64: dts: qcom: sdm845-starqltechn: add max77705 PMIC
      arm64: dts: qcom: sdm845-starqltechn: add display PMIC
      arm64: dts: qcom: sdm845-starqltechn: add touchscreen support

Eugene Lepshy (1):
      arm64: dts: qcom: sm7325-nothing-spacewar: Enable panel and GPU

Gabriel Gonzales (2):
      dt-bindings: arm: qcom: Add Xiaomi Redmi Note 8
      arm64: dts: qcom: sm6125: Initial support for xiaomi-ginkgo

Gaurav Kashyap (3):
      arm64: dts: qcom: sm8750: Add QCrypto nodes
      arm64: dts: qcom: sm8750: Add TRNG nodes
      arm64: dts: qcom: sm8750: Add ICE nodes

Jagadeesh Kona (1):
      arm64: dts: qcom: sa8775p: Add LMH interrupts for cpufreq_hw node

Jie Gan (1):
      arm64: dts: qcom: sa8775p: Add CTCU and ETR nodes

Johan Hovold (14):
      arm64: dts: qcom: x1e80100-crd: add support for volume-up key
      arm64: dts: qcom: x1e80100-crd: add gpio-keys label for lid switch
      arm64: dts: qcom: sc8280xp-crd: add support for volume-up key
      arm64: dts: qcom: x1e80100-crd: mark l12b and l15b always-on
      arm64: dts: qcom: x1e78100-t14s: mark l12b and l15b always-on
      arm64: dts: qcom: x1e001de-devkit: mark l12b and l15b always-on
      arm64: dts: qcom: x1e80100-dell-xps13-9345: mark l12b and l15b always-on
      arm64: dts: qcom: x1e80100-hp-x14: mark l12b and l15b always-on
      arm64: dts: qcom: x1e80100-yoga-slim7x: mark l12b and l15b always-on
      arm64: dts: qcom: x1e80100-qcp: mark l12b and l15b always-on
      arm64: dts: qcom: x1e78100-t14s: fix missing HID supplies
      arm64: dts: qcom: sc8280xp-x13s: switch to uefi rtc offset
      arm64: dts: qcom: x1e80100: enable rtc
      arm64: dts: qcom: x1e001de-devkit: fix USB retimer reset polarity

Jyothi Kumar Seerapu (1):
      arm64: dts: qcom: sm8750: Correct clocks property for uart14 node

Konrad Dybcio (8):
      arm64: dts: qcom: x1e80100-romulus: Keep L12B and L15B always on
      arm64: dts: qcom: sdx75: Fix up the USB interrupt description
      arm64: dts: qcom: sdx75: Rename AOSS_QMP to power-management
      arm64: dts: qcom: qcs615: Rename AOSS_QMP to power-management
      arm64: dts: qcom: sc8180x: Rename AOSS_QMP to power-management
      arm64: dts: qcom: x1e80100-dell-xps13-9345: Drop clock-names from PS8830
      arm64: dts: qcom: x1e80100-romulus: Drop clock-names from PS8830
      arm64: dts: qcom: x1e001de-devkit: Drop clock-names from PS8830

Krishna Kurapati (1):
      arm64: dts: qcom: qcs6490-rb3gen2: Add orientation gpio

Krzysztof Kozlowski (8):
      arm64: dts: qcom: Use recommended MBN firmware path
      arm64: dts: qcom: sm8750: Add IPCC, SMP2P, AOSS and ADSP
      arm64: dts: qcom: sm8750: Add LPASS macro codecs and pinctrl
      arm64: dts: qcom: sm8750-mtp: Enable ADSP
      arm64: dts: qcom: sm8750-qrd: Enable ADSP
      arm64: dts: qcom: sm8750: Add CDSP
      arm64: dts: qcom: sm8750-mtp: Enable CDSP
      arm64: dts: qcom: sm8750-qrd: Enable CDSP

Lad Prabhakar (1):
      arm64: dts: qcom: Drop `tx-sched-sp` property

Luca Weiss (3):
      arm64: dts: qcom: sm8350: Reenable crypto & cryptobam
      arm64: dts: qcom: qcm6490-fairphone-fp5: Add touchscreen node
      arm64: dts: qcom: sm8650: Fix domain-idle-state for CPU2

Manikanta Mylavarapu (3):
      arm64: dts: qcom: ipq9574: fix the msi interrupt numbers of pcie3
      arm64: dts: qcom: ipq5424: add reserved memory region for bootloader
      arm64: dts: qcom: ipq5424: enable GPIO based LEDs and Buttons

Manish Nagar (1):
      arm64: dts: qcom: qcs8300-ride: Enable second USB controller on QCS8300 Ride

Maud Spierings (2):
      arm64: dts: qcom: x1e80100-vivobook-s15: Enable USB-A ports
      arm64: dts: qcom: x1e80100-vivobook-s15: Enable micro-sd card reader

Maulik Shah (2):
      arm64: dts: qcom: sm8750: Fix cluster hierarchy for idle states
      arm64: dts: qcom: qcs8300: Add RPMh sleep stats

Md Sadre Alam (3):
      arm64: dts: qcom: ipq9574: Add SPI nand support
      arm64: dts: qcom: ipq9574: Enable SPI NAND for ipq9574
      arm64: dts: qcom: ipq9574: Remove eMMC node

Neil Armstrong (3):
      arm64: dts: qcom: sm8650: add all 8 coresight ETE nodes
      arm64: dts: qcom: sm8650: switch to interrupt-cells 4 to add PPI partitions
      arm64: dts: qcom: sm8650: add PPI interrupt partitions for the ARM PMUs

Pratyush Brahma (1):
      arm64: dts: qcom: qcs8300: Add device node for gfx_smmu

Stephan Gerhold (7):
      arm64: dts: qcom: sm8450: Add missing properties for cryptobam
      arm64: dts: qcom: sm8550: Add missing properties for cryptobam
      arm64: dts: qcom: sm8650: Add missing properties for cryptobam
      arm64: dts: qcom: sa8775p: Add missing properties for cryptobam
      arm64: dts: qcom: ipq9574: Add missing properties for cryptobam
      arm64: dts: qcom: sc8280xp-x13s: Drop duplicate DMIC supplies
      arm64: dts: qcom: x1e80100-crd: Drop duplicate DMIC supplies

Taniya Das (1):
      arm64: dts: qcom: qcm6490-idp: Update protected clocks list

Tingguo Cheng (1):
      arm64: dts: qcom: qcs615: remove disallowed property in spmi bus node

Varadarajan Narayanan (2):
      arm64: dts: qcom: ipq5424: Enable MMC
      arm64: dts: qcom: ipq9574: Fix USB vdd info

Vikash Garodia (1):
      arm64: dts: qcom: sc7280: drop video decoder and encoder nodes

Vikram Sharma (2):
      arm64: dts: qcom: sc7280: Add support for camss
      arm64: dts: qcom: qcs6490-rb3gen2-vision-mezzanine: Add vision mezzanine

Xilin Wu (1):
      arm64: dts: qcom: sm8250: Fix CPU7 opp table

 Documentation/devicetree/bindings/arm/qcom.yaml    |    5 +-
 .../bindings/clock/qcom,ipq9574-nsscc.yaml         |   98 ++
 arch/arm64/boot/dts/qcom/Makefile                  |    6 +
 arch/arm64/boot/dts/qcom/ipq5424-rdp466.dts        |   50 +
 arch/arm64/boot/dts/qcom/ipq5424.dtsi              |    7 +
 arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi   |   55 +-
 arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts        |   12 -
 arch/arm64/boot/dts/qcom/ipq9574.dtsi              |   74 +-
 arch/arm64/boot/dts/qcom/msm8917-xiaomi-riva.dts   |   25 +
 arch/arm64/boot/dts/qcom/pm8937.dtsi               |    8 +
 arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts |   12 +-
 arch/arm64/boot/dts/qcom/qcm6490-idp.dts           |   21 +
 arch/arm64/boot/dts/qcom/qcs615.dtsi               |    8 +-
 .../dts/qcom/qcs6490-rb3gen2-vision-mezzanine.dtso |   89 ++
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts       |    1 +
 arch/arm64/boot/dts/qcom/qcs8300-ride.dts          |   36 +-
 arch/arm64/boot/dts/qcom/qcs8300.dtsi              |   44 +
 arch/arm64/boot/dts/qcom/qrb5165-rb5.dts           |   17 +-
 arch/arm64/boot/dts/qcom/sa8155p-adp.dts           |    4 +-
 arch/arm64/boot/dts/qcom/sa8540p-ride.dts          |    2 -
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi         |    2 -
 arch/arm64/boot/dts/qcom/sa8775p.dtsi              |  159 +++
 arch/arm64/boot/dts/qcom/sar2130p.dtsi             |   61 +
 arch/arm64/boot/dts/qcom/sc7280.dtsi               |  186 ++-
 arch/arm64/boot/dts/qcom/sc8180x.dtsi              |    2 +-
 arch/arm64/boot/dts/qcom/sc8280xp-crd.dts          |   22 +
 .../dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts     |   14 -
 .../boot/dts/qcom/sdm630-sony-xperia-nile.dtsi     |    2 +-
 arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi         |    4 -
 arch/arm64/boot/dts/qcom/sdm845-db845c.dts         |    4 -
 arch/arm64/boot/dts/qcom/sdm845-mtp.dts            |    4 -
 .../arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi |    4 -
 .../boot/dts/qcom/sdm845-samsung-starqltechn.dts   |  271 +++-
 arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts  |    4 -
 .../boot/dts/qcom/sdm845-sony-xperia-tama.dtsi     |    4 -
 .../dts/qcom/sdm845-xiaomi-beryllium-common.dtsi   |    4 -
 arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts |    4 -
 arch/arm64/boot/dts/qcom/sdm845.dtsi               |    2 -
 .../boot/dts/qcom/sdm850-lenovo-yoga-c630.dts      |    4 -
 arch/arm64/boot/dts/qcom/sdx75.dtsi                |   16 +-
 arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo.dts  |  295 ++++
 .../boot/dts/qcom/sm7325-nothing-spacewar.dts      |   51 +-
 .../boot/dts/qcom/sm8150-microsoft-surface-duo.dts |    8 +-
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts            |    8 +-
 arch/arm64/boot/dts/qcom/sm8250.dtsi               |    2 +-
 arch/arm64/boot/dts/qcom/sm8350.dtsi               |    6 +-
 arch/arm64/boot/dts/qcom/sm8450.dtsi               |   64 +
 arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts    |   12 +-
 arch/arm64/boot/dts/qcom/sm8550.dtsi               |    2 +
 arch/arm64/boot/dts/qcom/sm8650.dtsi               |  723 ++++++----
 arch/arm64/boot/dts/qcom/sm8750-mtp.dts            |   14 +
 arch/arm64/boot/dts/qcom/sm8750-qrd.dts            |   14 +
 arch/arm64/boot/dts/qcom/sm8750.dtsi               |  605 +++++++-
 arch/arm64/boot/dts/qcom/x1-crd.dtsi               |  497 ++++++-
 arch/arm64/boot/dts/qcom/x1e001de-devkit.dts       |   11 +-
 .../qcom/x1e78100-lenovo-thinkpad-t14s-oled.dts    |   12 +
 .../dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts     | 1126 +--------------
 .../dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi    | 1487 ++++++++++++++++++++
 .../boot/dts/qcom/x1e80100-asus-vivobook-s15.dts   |  142 +-
 .../boot/dts/qcom/x1e80100-dell-xps13-9345.dts     |    4 +-
 .../boot/dts/qcom/x1e80100-hp-omnibook-x14.dts     |    2 +
 .../boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts  |    3 +-
 .../boot/dts/qcom/x1e80100-microsoft-romulus.dtsi  |    4 +-
 arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi       |    3 +-
 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts          |    2 +
 include/dt-bindings/clock/qcom,ipq9574-gcc.h       |    1 +
 include/dt-bindings/clock/qcom,ipq9574-nsscc.h     |  152 ++
 include/dt-bindings/reset/qcom,ipq9574-nsscc.h     |  134 ++
 68 files changed, 5189 insertions(+), 1542 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
 create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine.dtso
 create mode 100644 arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo.dts
 create mode 100644 arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s-oled.dts
 create mode 100644 arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
 create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h
 create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h


From jeremy.linton at arm.com  Wed Mar 19 09:40:35 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Wed, 19 Mar 2025 11:40:35 -0500
Subject: [PATCH 6/7] uprobes: Allow the use of uprobe_warn() in arch code
In-Reply-To: <20250319145057.GA10753@redhat.com>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-7-jeremy.linton@arm.com>
 <20250319145057.GA10753@redhat.com>
Message-ID: <83cf1b26-3a30-47fd-93e9-84903193bf07@arm.com>

Hi,

On 3/19/25 9:51 AM, Oleg Nesterov wrote:
> On 03/18, Jeremy Linton wrote:
>>
>> --- a/include/linux/uprobes.h
>> +++ b/include/linux/uprobes.h
>> @@ -185,6 +185,7 @@ struct uprobes_state {
>>   };
>>   
>>   extern void __init uprobes_init(void);
>> +extern void uprobe_warn(struct task_struct *t, const char *msg);
>>   extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>>   extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
>>   extern bool is_swbp_insn(uprobe_opcode_t *insn);
>> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
>> index b4ca8898fe17..613c1c76f227 100644
>> --- a/kernel/events/uprobes.c
>> +++ b/kernel/events/uprobes.c
>> @@ -118,7 +118,7 @@ struct xol_area {
>>   	unsigned long 			vaddr;		/* Page(s) of instruction slots */
>>   };
>>   
>> -static void uprobe_warn(struct task_struct *t, const char *msg)
>> +void uprobe_warn(struct task_struct *t, const char *msg)
>>   {
>>   	pr_warn("uprobe: %s:%d failed to %s\n", current->comm, current->pid, msg);
>>   }
> 
> Oh, no, please don't.
> 
> uprobe_warn() is ugly and needs changes. If nothing else it doesn't even use
> its "t" argument.

Ha, I didn't look that closely at it. That is basically the same bug 1/7 
here is fixing for the gcs task function!

This is in its own patch to allow it to be easily dropped, which is what 
will happen as I'm aware of previous variations of this discussion.

While Mark R's perspective is valid, it remains worthwhile to again 
point out that the uprobes subsystem (and a few like it) is a bit of a 
mystery box. Some of these error conditions are very opaque for a user 
who isn't also sufficiently familiar with uprobes to be able to both 
find the code as well as understand or instrument it when it tosses an 
error. Discoverability is made more difficult by the extensive use of 
inline/static. End users try to work around this. For example Brendan 
Gregg's perf-tools uprobe wrapper will dump the last two lines of the 
kernel log when it hits unexpected errors.



From rrathina at amd.com  Wed Mar 19 09:41:30 2025
From: rrathina at amd.com (Rajaganesh Rathinasabapathi)
Date: Wed, 19 Mar 2025 22:11:30 +0530
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD
 Onyx Platform
In-Reply-To: <af75c352-0010-4c58-b8bc-ac0d02337d1a@kernel.org>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
 <af75c352-0010-4c58-b8bc-ac0d02337d1a@kernel.org>
Message-ID: <8c7be61d-d5e4-4f7f-a995-06cf856a84ae@amd.com>

On 3/18/25 23:44, Krzysztof Kozlowski wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> On 18/03/2025 18:47, Rajaganesh Rathinasabapathi wrote:
>> Add initial device tree and makefile updates for
>> AMD Onyx platform.
>>
>> AMD Onyx platform is an AMD customer reference board with an Aspeed
>> ast2600 BMC manufactured by AMD.
>> It describes I2C devices, UARTs, MAC, FMC, etc.
>> present on AMD Onyx platform.
>>
>> Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
>> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
>> ---
>> Changes since v1:
>> * Incorporate review comments
> 
> Which ones? I do not see my comments addressed and if you do not list
> them, I treat it as a clear sign you do not care.
> 

Understood, will list them in next patch submission.
>> * Update commit message
>> * Remove vmalloc and earlyprintk
>>
>> Changes since v2:
>> * Address review comments
> 
> Which ones? This has to be specific
> 
Got it, will add details and fix in next patch.

>> * Fix checkpatch warnings
>> * Remove bootargs
>>
>> Changes since v3:
>> * Fix stdout-path
>> * Change commit summary
>> ---
>>  arch/arm/boot/dts/aspeed/Makefile             |   1 +
>>  .../boot/dts/aspeed/aspeed-bmc-amd-onyx.dts   | 102 ++++++++++++++++++
>>  2 files changed, 103 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>>
>> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
>> index 2e5f4833a073..1e6a130377b8 100644
>> --- a/arch/arm/boot/dts/aspeed/Makefile
>> +++ b/arch/arm/boot/dts/aspeed/Makefile
>> @@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>>       aspeed-ast2600-evb.dtb \
>>       aspeed-bmc-amd-daytonax.dtb \
>>       aspeed-bmc-amd-ethanolx.dtb \
>> +     aspeed-bmc-amd-onyx.dtb \
>>       aspeed-bmc-ampere-mtjade.dtb \
>>       aspeed-bmc-ampere-mtjefferson.dtb \
>>       aspeed-bmc-ampere-mtmitchell.dtb \
>> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>> new file mode 100644
>> index 000000000000..32509a651183
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>> @@ -0,0 +1,102 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +// Copyright (c) 2021 - 2024 AMD Inc.
>> +// Author: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
>> +
>> +/dts-v1/;
>> +
>> +#include "aspeed-g6.dtsi"
>> +#include <dt-bindings/gpio/aspeed-gpio.h>
>> +
>> +/ {
>> +     model = "AMD Onyx BMC";
>> +     compatible = "amd,onyx-bmc", "aspeed,ast2600";
>> +
>> +     aliases {
>> +             serial0 = &uart1;
>> +             serial4 = &uart5;
>> +     };
>> +
>> +     chosen {
>> +             stdout-path = "serial4:115200n8";
>> +     };
>> +
>> +     memory at 80000000 {
>> +             device_type = "memory";
>> +             reg = <0x80000000 0x80000000>;
>> +     };
>> +
>> +};
> How did you address comment here from v1 which was responded with "ACK"?
> 
> What else what exactly fixed and what not?
> 
> Best regards,
> Krzysztof

Thanks for the comments.
I will add 'Acked-by' and in next patch submission. 

Thanks,
Raja


From potin.lai.pt at gmail.com  Wed Mar 19 09:47:23 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:23 +0800
Subject: [PATCH v4 2/8] ARM: dts: aspeed: catalina: Add Front IO board
 remote thermal sensor
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-2-7c34b8139014@gmail.com>

Add a remote thermal sensor node for the Front IO board in the Catalina
platform device tree. This sensor enables monitoring of the inlet
temperature.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 75c3906d9654..b9a7654325f0 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -604,6 +604,12 @@ temperature-sensor at 4b {
 				compatible = "ti,tmp75";
 				reg = <0x4b>;
 			};
+
+			// FIO REMOTE TEMP SENSOR
+			temperature-sensor at 4f {
+				compatible = "ti,tmp75";
+				reg = <0x4f>;
+			};
 		};
 	};
 };

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:24 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:24 +0800
Subject: [PATCH v4 3/8] ARM: dts: aspeed: catalina: Add MP5990 power sensor
 node
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-3-7c34b8139014@gmail.com>

Add a device tree node for the MP5990 power sensor to enable monitoring of
the P12V supplying power to the fans.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index b9a7654325f0..db999408e397 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -488,6 +488,10 @@ i2c1mux0ch0: i2c at 0 {
 			#size-cells = <0>;
 			reg = <0x0>;
 
+			power-sensor at 22 {
+				compatible = "mps,mp5990";
+				reg = <0x22>;
+			};
 			power-sensor at 41 {
 				compatible = "ti,ina238";
 				reg = <0x41>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:25 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:25 +0800
Subject: [PATCH v4 4/8] ARM: dts: aspeed: catalina: Add fan controller
 support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-4-7c34b8139014@gmail.com>

Add device tree nodes for the MAX31790 fan controllers on the Power
Distribution Board (PDB). These nodes enable fan speed control and
monitoring, improving thermal management and system reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index db999408e397..0b513829f2de 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -526,6 +526,15 @@ i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x2>;
+
+			pwm at 21{
+				compatible = "maxim,max31790";
+				reg = <0x21>;
+			};
+			pwm at 27{
+				compatible = "maxim,max31790";
+				reg = <0x27>;
+			};
 		};
 		i2c1mux0ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:26 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:26 +0800
Subject: [PATCH v4 5/8] ARM: dts: aspeed: catalina: Add second source fan
 controller support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-5-7c34b8139014@gmail.com>

Add device tree nodes for the NCT7363 fan controllers on the second-source
Power Distribution Board (PDB).

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 0b513829f2de..e11be815a6af 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -527,6 +527,82 @@ i2c1mux0ch2: i2c at 2 {
 			#size-cells = <0>;
 			reg = <0x2>;
 
+			hwmon0: hwmon at 1 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x01>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&hwmon0 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&hwmon0 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&hwmon0 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&hwmon0 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&hwmon0 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&hwmon0 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&hwmon0 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&hwmon0 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
+			hwmon1: hwmon at 2 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x02>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&hwmon1 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&hwmon1 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&hwmon1 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&hwmon1 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&hwmon1 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&hwmon1 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&hwmon1 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&hwmon1 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
 			pwm at 21{
 				compatible = "maxim,max31790";
 				reg = <0x21>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:27 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:27 +0800
Subject: [PATCH v4 6/8] ARM: dts: aspeed: catalina: Add second source HSC
 node support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-6-7c34b8139014@gmail.com>

Add device tree nodes for the XDP710 Hot-Swap Controller (HSC) to support
the Power Distribution Board (PDB) with a second-source configuration.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index e11be815a6af..fb4b236d36c0 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -622,6 +622,14 @@ i2c1mux0ch4: i2c at 4 {
 			#size-cells = <0>;
 			reg = <0x4>;
 
+			power-monitor at 13 {
+				compatible = "infineon,xdp710";
+				reg = <0x13>;
+			};
+			power-monitor at 1c {
+				compatible = "infineon,xdp710";
+				reg = <0x1c>;
+			};
 			power-monitor at 42 {
 				compatible = "lltc,ltc4287";
 				reg = <0x42>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:28 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:28 +0800
Subject: [PATCH v4 7/8] ARM: dts: aspeed: catalina: Remove INA238 and
 INA230 nodes
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-7-7c34b8139014@gmail.com>

Remove INA238 and INA230 power sensor nodes from the device tree (DTS) due
to incompatibility with the second-source ISL28022, which shares the same
I2C address.

Move the driver probe to userspace to handle sensor dynamically.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 45 ----------------------
 1 file changed, 45 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index fb4b236d36c0..573701bb7fee 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -304,27 +304,6 @@ i2c30mux0ch7: i2c at 7 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <7>;
-
-					power-sensor at 40 {
-						compatible = "ti,ina230";
-						reg = <0x40>;
-						shunt-resistor = <2000>;
-					};
-					power-sensor at 41 {
-						compatible = "ti,ina230";
-						reg = <0x41>;
-						shunt-resistor = <2000>;
-					};
-					power-sensor at 44 {
-						compatible = "ti,ina230";
-						reg = <0x44>;
-						shunt-resistor = <2000>;
-					};
-					power-sensor at 45 {
-						compatible = "ti,ina230";
-						reg = <0x45>;
-						shunt-resistor = <2000>;
-					};
 				};
 			};
 		};
@@ -492,35 +471,11 @@ power-sensor at 22 {
 				compatible = "mps,mp5990";
 				reg = <0x22>;
 			};
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 42 {
-				compatible = "ti,ina238";
-				reg = <0x42>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 44 {
-				compatible = "ti,ina238";
-				reg = <0x44>;
-				shunt-resistor = <500>;
-			};
 		};
 		i2c1mux0ch1: i2c at 1 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x1>;
-
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-			};
-			power-sensor at 43 {
-				compatible = "ti,ina238";
-				reg = <0x43>;
-			};
 		};
 		i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:29 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:29 +0800
Subject: [PATCH v4 8/8] ARM: dts: aspeed: catalina: Enable multi-master on
 additional I2C buses
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-8-7c34b8139014@gmail.com>

Update the device tree to enable `multi-master` mode on I2C buses shared
between the host BMC and the NV module with HMC. This ensures proper bus
arbitration and coordination in multi-master environments, preventing
communication conflicts and improving reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 573701bb7fee..c11de5a61912 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -800,6 +800,7 @@ ssif-bmc at 10 {
 
 &i2c12 {
 	status = "okay";
+	multi-master;
 
 	// Module 1 FRU EEPROM
 	eeprom at 50 {
@@ -810,6 +811,7 @@ eeprom at 50 {
 
 &i2c13 {
 	status = "okay";
+	multi-master;
 
 	// Module 0 FRU EEPROM
 	eeprom at 50 {

-- 
2.31.1



From rrathina at amd.com  Wed Mar 19 09:47:58 2025
From: rrathina at amd.com (Rajaganesh Rathinasabapathi)
Date: Wed, 19 Mar 2025 22:17:58 +0530
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD
 Onyx Platform
In-Reply-To: <472a4f78-24f4-4bfd-bf99-8b1194bfe8f0@lunn.ch>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
 <472a4f78-24f4-4bfd-bf99-8b1194bfe8f0@lunn.ch>
Message-ID: <3780ab88-f6c5-4298-89c2-ae798592c5bd@amd.com>

On 3/19/25 00:03, Andrew Lunn wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
>> +&mac3 {
>> +     status = "okay";
>> +     phy-mode = "rgmii";
> 
> Still broken. And it appears you are just ignoring my comments.
> 
> Sorry, but:
> 
> NACK
> 
> There is a discussion here:
> 
> https://lore.kernel.org/lkml/20250317025922.1526937-1-jacky_chou at aspeedtech.com/
> 
> There is also IBM in a similar situation to you:
> 
> https://lore.kernel.org/linux-arm-kernel/20250108163640.1374680-6-ninad at linux.ibm.com/
> 
> and NVIDIA
> 
> https://lore.kernel.org/lkml/20250312045802.4115029-1-wthai at nvidia.com/
> 
> Could i suggest you, IBM and NVIDIA work together to get Aspeed to fix
> this.
> 
>         Andrew
Hi Andrew,

Thanks for the comments. Will follow up with Aspeed.
We will skip this node in next patch.



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:21 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:21 +0800
Subject: [PATCH v4 0/8] ARM: dts: aspeed: catalina: Update DTS to support
 Catalina PVT hardware
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>

Update the DTS file for the Catalina platform based on the PVT hardware
changes.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
Changes in v4:
- Split a single commit into multiple smaller commits to reduce complexity.
- Add `multi-master` into i2c12 & i2c13  
- Link to v3: https://lore.kernel.org/r/20250114-potin-catalina-dts-update-20250102-v3-1-14981744b2fe at gmail.com

Changes in v3:
- Remove delta_brick nodes due to compatible string not supported
- Link to v2: https://lore.kernel.org/r/20250113-potin-catalina-dts-update-20250102-v2-1-1725117fe7a9 at gmail.com

Changes in v2:
- Add delta_brick nodes to support PDB brick board
- Link to v1: https://lore.kernel.org/r/20250103-potin-catalina-dts-update-20250102-v1-1-b0b7a523c968 at gmail.com

---
Potin Lai (8):
      ARM: dts: aspeed: catalina: Add IO Mezz board thermal sensor nodes
      ARM: dts: aspeed: catalina: Add Front IO board remote thermal sensor
      ARM: dts: aspeed: catalina: Add MP5990 power sensor node
      ARM: dts: aspeed: catalina: Add fan controller support
      ARM: dts: aspeed: catalina: Add second source fan controller support
      ARM: dts: aspeed: catalina: Add second source HSC node support
      ARM: dts: aspeed: catalina: Remove INA238 and INA230 nodes
      ARM: dts: aspeed: catalina: Enable multi-master on additional I2C buses

 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 172 +++++++++++++++------
 1 file changed, 128 insertions(+), 44 deletions(-)
---
base-commit: becaccc292bfbd12df81148746043c5221e49da8
change-id: 20250102-potin-catalina-dts-update-20250102-914b06a4bdba

Best regards,
-- 
Potin Lai <potin.lai.pt at gmail.com>



From potin.lai.pt at gmail.com  Wed Mar 19 09:47:22 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 00:47:22 +0800
Subject: [PATCH v4 1/8] ARM: dts: aspeed: catalina: Add IO Mezz board
 thermal sensor nodes
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v4-1-7c34b8139014@gmail.com>

Add thermal sensor nodes for the IO Mezzanine (IO Mezz) board in the
Catalina platform device tree. These nodes enable temperature monitoring
for the backend NIC, improving thermal management and monitoring
capabilities.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 3822bb3c9243..75c3906d9654 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -190,6 +190,12 @@ i2c0mux0ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB0 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -200,6 +206,12 @@ i2c0mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB0 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch3: i2c at 3 {
 			#address-cells = <1>;
@@ -361,6 +373,12 @@ i2c0mux3ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB1 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -371,6 +389,12 @@ i2c0mux3ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB1 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From jgg at nvidia.com  Wed Mar 19 10:04:29 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 19 Mar 2025 14:04:29 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9pryQwy2iwa2bpJ@linux.dev>
References: <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
 <20250318230909.GD9311@nvidia.com>
 <Z9pryQwy2iwa2bpJ@linux.dev>
Message-ID: <20250319170429.GK9311@nvidia.com>

On Wed, Mar 19, 2025 at 12:01:29AM -0700, Oliver Upton wrote:

> You have a very good point that KVM is broken for cacheable PFNMAP'd
> crap since we demote to something non-cacheable, and maybe that
> deserves fixing first. Hopefully nobody notices that we've taken away
> the toys...

Fixing it is either faulting all access attempts or mapping it
cachable to the S2 (as this series is trying to do)..

> We still need to test the VMA flag here to select Normal-NC v. Device.

Yes

> I'm less worried about recovery and more focused on userspace being
> able to understand what happened. Otherwise we may get folks complaining
> about the ioctl failing "randomly" on certain machines.

Even today something like qemu doesn't know that VFIO has created a
cachable mmap, so it would need a bunch more work to feed everything
through as proposed here.

IMHO the semantic should be simple enough, when the memslot is created
determine if KVM can support it at all. non-struct page cacheable
memory requires FWB to support it today.

Maybe tomorrow KVM will learn how to cache flush non-struct page
memory and then everything can support it.

It just seems wrong to be making uAPI based around limitations of the
kernel implementation..

Jason


From ajones at ventanamicro.com  Wed Mar 19 10:08:43 2025
From: ajones at ventanamicro.com (Andrew Jones)
Date: Wed, 19 Mar 2025 18:08:43 +0100
Subject: [PATCH v3 2/4] riscv: add support for SBI Supervisor Software
 Events extension
In-Reply-To: <20241206163102.843505-3-cleger@rivosinc.com>
References: <20241206163102.843505-1-cleger@rivosinc.com>
 <20241206163102.843505-3-cleger@rivosinc.com>
Message-ID: <20250319-46b625cf8b771616d4c7c053@orel>

On Fri, Dec 06, 2024 at 05:30:58PM +0100, Cl?ment L?ger wrote:
...
> +int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cpu)
> +{
> +	void *stack;
> +
> +	arch_evt->evt_id = evt_id;
> +	stack = sse_stack_alloc(cpu, SSE_STACK_SIZE);
> +	if (!stack)
> +		return -ENOMEM;
> +
> +	arch_evt->stack = stack + SSE_STACK_SIZE;
> +
> +	if (sse_init_scs(cpu, arch_evt))
> +		goto free_stack;
> +
> +	if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
> +		arch_evt->interrupted_state_phys =
> +				per_cpu_ptr_to_phys(&arch_evt->interrupted);
> +	} else {
> +		arch_evt->interrupted_state_phys =
> +				virt_to_phys(&arch_evt->interrupted);
> +	}
> +
> +	return 0;

Hi Cl?ment,

Testing SSE support with tools/testing/selftests/kvm/riscv/sbi_pmu_test
led to an opensbi sbi_trap_error because the output_phys_lo address passed
to sbi_sse_read_attrs() wasn't a physical address. The reason is that
is_kernel_percpu_address() can only be used on static percpu addresses,
but local sse events get their percpu addresses with alloc_percpu(), so
is_kernel_percpu_address() was returning false even for local events. I
made the following changes to get things working.

Thanks,
drew

diff --git a/arch/riscv/kernel/sse.c b/arch/riscv/kernel/sse.c
index b48ae69dad8d..f46893946086 100644
--- a/arch/riscv/kernel/sse.c
+++ b/arch/riscv/kernel/sse.c
@@ -100,12 +100,12 @@ int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cp
        if (sse_init_scs(cpu, arch_evt))
                goto free_stack;

-       if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
+       if (sse_event_is_global(evt_id)) {
                arch_evt->interrupted_state_phys =
-                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
+                               virt_to_phys(&arch_evt->interrupted);
        } else {
                arch_evt->interrupted_state_phys =
-                               virt_to_phys(&arch_evt->interrupted);
+                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
        }

        return 0;
diff --git a/drivers/firmware/riscv/riscv_sse.c b/drivers/firmware/riscv/riscv_sse.c
index 511db9ad7a9e..fef375046f75 100644
--- a/drivers/firmware/riscv/riscv_sse.c
+++ b/drivers/firmware/riscv/riscv_sse.c
@@ -62,11 +62,6 @@ void sse_handle_event(struct sse_event_arch_data *arch_event,
                        ret);
 }

-static bool sse_event_is_global(u32 evt)
-{
-       return !!(evt & SBI_SSE_EVENT_GLOBAL);
-}
-
 static
 struct sse_event *sse_event_get(u32 evt)
 {
diff --git a/include/linux/riscv_sse.h b/include/linux/riscv_sse.h
index 16700677f1e8..06b757b036b0 100644
--- a/include/linux/riscv_sse.h
+++ b/include/linux/riscv_sse.h
@@ -8,6 +8,7 @@

 #include <linux/types.h>
 #include <linux/linkage.h>
+#include <asm/sbi.h>

 struct sse_event;
 struct pt_regs;
@@ -16,6 +17,11 @@ struct ghes;

 typedef int (sse_event_handler)(u32 event_num, void *arg, struct pt_regs *regs);

+static inline bool sse_event_is_global(u32 evt)
+{
+       return !!(evt & SBI_SSE_EVENT_GLOBAL);
+}
+
 #ifdef CONFIG_RISCV_SSE

 struct sse_event *sse_event_register(u32 event_num, u32 priority,


From luiz.dentz at gmail.com  Wed Mar 19 10:13:06 2025
From: luiz.dentz at gmail.com (Luiz Augusto von Dentz)
Date: Wed, 19 Mar 2025 13:13:06 -0400
Subject: [PATCH][QUESTION] bluetooth: Remove duplicated h4_recv_buf() in header
In-Reply-To: <2b612e2c1f4fa697b47b5dd9b72f1949d7c206f5.1742324401.git.calvin@wbinvd.org>
References: <2b612e2c1f4fa697b47b5dd9b72f1949d7c206f5.1742324401.git.calvin@wbinvd.org>
Message-ID: <CABBYNZ+ONkYtq2fR-8PtL3X-vetvJ0BdP4MTw9cNpjLDzG3HUQ@mail.gmail.com>

Hi Calvin,

On Tue, Mar 18, 2025 at 3:31?PM Calvin Owens <calvin at wbinvd.org> wrote:
>
> Hello all,
>
> In the course of other debugging, I've discovered that h4_recv_buf() is
> almost completely duplicated in an inline header definiton, and I don't
> understand why.
>
> I'd like to clean this up: see the patch below for an explanation.
>
> Does anybody who was around at the time remember any more details about
> this? Or failing that, perhaps somebody with access to the bpa10x
> hardware can test it with the core function?

Don't think Ive been involved with kernel internals for this long to
give you an answer, but I assume it was due to alignment differences
in the drivers, but it looks like you could only find bpa10x, which
seems to be a usb driver for a single model (Tektronix BPA 100/105
(Digianswer)) and a quick google seem to refer to a protocol analyzer
for Bluetooth 2.1, so it is not really a regular Bluetooth controller.

> Thanks,
> Calvin
>
> ---8<---
> From: Calvin Owens <calvin at wbinvd.org>
> Subject: [PATCH] bluetooth: Remove duplicated h4_recv_buf() in header
>
> The "h4_recv.h" header contains a duplicate h4_recv_buf() that is nearly
> but not quite identical to the h4_recv_buf() in hci_h4.c.
>
> This duplicated header was added in commit 07eb96a5a7b0 ("Bluetooth:
> bpa10x: Use separate h4_recv_buf helper"). Unfortunately, there was no
> discussion about it on the list at the time:
>
>     https://lore.kernel.org/all/20180320181855.37297-1-marcel at holtmann.org/
>     https://lore.kernel.org/all/20180324091954.73229-2-marcel at holtmann.org/
>
> This is the diff between the two implementations as they exist today:
>
>     --- /home/calvinow/orig.c   2025-03-10 14:43:18.383882623 -0700
>     +++ /home/calvinow/copy.c   2025-03-10 14:42:57.109953576 -0700
>     @@ -1,117 +1,100 @@
>      {
>     -   struct hci_uart *hu = hci_get_drvdata(hdev);
>     -   u8 alignment = hu->alignment ? hu->alignment : 1;
>     -
>         /* Check for error from previous call */
>         if (IS_ERR(skb))
>                 skb = NULL;
>
>         while (count) {
>                 int i, len;
>
>     -           /* remove padding bytes from buffer */
>     -           for (; hu->padding && count > 0; hu->padding--) {
>     -                   count--;
>     -                   buffer++;
>     -           }
>     -           if (!count)
>     -                   break;
>     -
>                 if (!skb) {
>                         for (i = 0; i < pkts_count; i++) {
>                                 if (buffer[0] != (&pkts[i])->type)
>                                         continue;
>
>                                 skb = bt_skb_alloc((&pkts[i])->maxlen,
>                                                    GFP_ATOMIC);
>                                 if (!skb)
>                                         return ERR_PTR(-ENOMEM);
>
>                                 hci_skb_pkt_type(skb) = (&pkts[i])->type;
>                                 hci_skb_expect(skb) = (&pkts[i])->hlen;
>                                 break;
>                         }
>
>                         /* Check for invalid packet type */
>                         if (!skb)
>                                 return ERR_PTR(-EILSEQ);
>
>                         count -= 1;
>                         buffer += 1;
>                 }
>
>                 len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
>                 skb_put_data(skb, buffer, len);
>
>                 count -= len;
>                 buffer += len;
>
>                 /* Check for partial packet */
>                 if (skb->len < hci_skb_expect(skb))
>                         continue;
>
>                 for (i = 0; i < pkts_count; i++) {
>                         if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
>                                 break;
>                 }
>
>                 if (i >= pkts_count) {
>                         kfree_skb(skb);
>                         return ERR_PTR(-EILSEQ);
>                 }
>
>                 if (skb->len == (&pkts[i])->hlen) {
>                         u16 dlen;
>
>                         switch ((&pkts[i])->lsize) {
>                         case 0:
>                                 /* No variable data length */
>                                 dlen = 0;
>                                 break;
>                         case 1:
>                                 /* Single octet variable length */
>                                 dlen = skb->data[(&pkts[i])->loff];
>                                 hci_skb_expect(skb) += dlen;
>
>                                 if (skb_tailroom(skb) < dlen) {
>                                         kfree_skb(skb);
>                                         return ERR_PTR(-EMSGSIZE);
>                                 }
>                                 break;
>                         case 2:
>                                 /* Double octet variable length */
>                                 dlen = get_unaligned_le16(skb->data +
>                                                           (&pkts[i])->loff);
>                                 hci_skb_expect(skb) += dlen;
>
>                                 if (skb_tailroom(skb) < dlen) {
>                                         kfree_skb(skb);
>                                         return ERR_PTR(-EMSGSIZE);
>                                 }
>                                 break;
>                         default:
>                                 /* Unsupported variable length */
>                                 kfree_skb(skb);
>                                 return ERR_PTR(-EILSEQ);
>                         }
>
>                         if (!dlen) {
>     -                           hu->padding = (skb->len + 1) % alignment;
>     -                           hu->padding = (alignment - hu->padding) % alignment;
>     -
>                                 /* No more data, complete frame */
>                                 (&pkts[i])->recv(hdev, skb);
>                                 skb = NULL;
>                         }
>                 } else {
>     -                   hu->padding = (skb->len + 1) % alignment;
>     -                   hu->padding = (alignment - hu->padding) % alignment;
>     -
>                         /* Complete frame */
>                         (&pkts[i])->recv(hdev, skb);
>                         skb = NULL;
>                 }
>         }
>
>         return skb;
>      }
>
> It seems fairly obvious from the above that, if alignment is one,
> hu->padding is always zero, and in that case the two functions behave
> strictly identically.
>
> Since that is the case for every driver except hci_nokia, clean this up
> and let them use the core function. I've done some light testing on
> btnxpuart, so far everything seems to work.
>
> I would love to eliminate the duplicate function entirely, but I don't
> have access to hardware for bpa10x. Since bpa10x breaking was the
> original justification for the change, I've left it there for now. I'm
> hoping somebody else can shed more light on this.
>
> Cc: Marcel Holtmann <marcel at holtmann.org>
> Signed-off-by: Calvin Owens <calvin at wbinvd.org>
> ---
>  drivers/bluetooth/btmtksdio.c | 2 +-
>  drivers/bluetooth/btmtkuart.c | 2 +-
>  drivers/bluetooth/btnxpuart.c | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
> index bd5464bde174..47d1073fb4a4 100644
> --- a/drivers/bluetooth/btmtksdio.c
> +++ b/drivers/bluetooth/btmtksdio.c
> @@ -29,7 +29,7 @@
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
>
> -#include "h4_recv.h"
> +#include "hci_uart.h"
>  #include "btmtk.h"
>
>  #define VERSION "0.1"
> diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
> index c97e260fcb0c..aeb111a0f242 100644
> --- a/drivers/bluetooth/btmtkuart.c
> +++ b/drivers/bluetooth/btmtkuart.c
> @@ -27,7 +27,7 @@
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
>
> -#include "h4_recv.h"
> +#include "hci_uart.h"
>  #include "btmtk.h"
>
>  #define VERSION "0.2"
> diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
> index aa5ec1d444a9..e6db563088cb 100644
> --- a/drivers/bluetooth/btnxpuart.c
> +++ b/drivers/bluetooth/btnxpuart.c
> @@ -21,7 +21,7 @@
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
>
> -#include "h4_recv.h"
> +#include "hci_uart.h"
>
>  #define MANUFACTURER_NXP               37
>
> --
> 2.47.2
>


-- 
Luiz Augusto von Dentz


From patchwork-bot+netdevbpf at kernel.org  Wed Mar 19 10:20:33 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Wed, 19 Mar 2025 17:20:33 +0000
Subject: [PATCH net-next v2 0/7] net: stmmac: deprecate
 "snps,en-tx-lpi-clockgating" property
In-Reply-To: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
References: <Z9FVHEf3uUqtKzyt@shell.armlinux.org.uk>
Message-ID: <174240483352.1121844.16892728893562053636.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Wed, 12 Mar 2025 09:34:20 +0000 you wrote:
> On Sun, Mar 09, 2025 at 03:01:45PM +0000, Russell King (Oracle) wrote:
> Hi,
> 
> This series deprecates the "snps,en-tx-lpi-clockgating" property for
> stmmac.
> 
> MII Transmit clock gating, where the MAC hardware supports gating this
> clock, is a function of the connected PHY capabilities, which it
> reports through its status register.
> 
> [...]

Here is the summary with links:
  - [net-next,v2,1/7] net: stmmac: allow platforms to use PHY tx clock stop capability
    https://git.kernel.org/netdev/net-next/c/0c1f1eb65425
  - [net-next,v2,2/7] net: stmmac: starfive: use PHY capability for TX clock stop
    https://git.kernel.org/netdev/net-next/c/5f250bd72a01
  - [net-next,v2,3/7] net: stmmac: stm32: use PHY capability for TX clock stop
    https://git.kernel.org/netdev/net-next/c/a5bc19e2abeb
  - [net-next,v2,4/7] riscv: dts: starfive: remove "snps,en-tx-lpi-clockgating" property
    https://git.kernel.org/netdev/net-next/c/637af286f9fc
  - [net-next,v2,5/7] ARM: dts: stm32: remove "snps,en-tx-lpi-clockgating" property
    https://git.kernel.org/netdev/net-next/c/50a84bbc7ec1
  - [net-next,v2,6/7] dt-bindings: deprecate "snps,en-tx-lpi-clockgating" property
    https://git.kernel.org/netdev/net-next/c/a62b7901d3a9
  - [net-next,v2,7/7] net: stmmac: deprecate "snps,en-tx-lpi-clockgating" property
    https://git.kernel.org/netdev/net-next/c/cf0a96de397e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:32:00 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:32:00 +0000
Subject: [RFC PATCH v3 3/5] iommu/arm-smmu-v3-iommufd: Pass in kvm pointer to viommu_alloc
In-Reply-To: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319173202.78988-4-shameerali.kolothum.thodi@huawei.com>

No functional changes.

This will be used in a later patch to add support to use
KVM VMID in ARM SMMUv3 s2 stage configuration.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 1 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h         | 1 +
 drivers/iommu/iommufd/viommu.c                      | 3 ++-
 include/linux/iommu.h                               | 4 +++-
 4 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 6f8be1164167..ee2fac5c899b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -370,6 +370,7 @@ static const struct iommufd_viommu_ops arm_vsmmu_ops = {
 };
 
 struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
+				       struct kvm *kvm,
 				       struct iommu_domain *parent,
 				       struct iommufd_ctx *ictx,
 				       unsigned int viommu_type)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 1f6696bc4f6c..9f49de52a700 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1060,6 +1060,7 @@ struct arm_vsmmu {
 #if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD)
 void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type);
 struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
+				       struct kvm *kvm,
 				       struct iommu_domain *parent,
 				       struct iommufd_ctx *ictx,
 				       unsigned int viommu_type);
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 69b88e8c7c26..e157d786f295 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -47,7 +47,8 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
 		goto out_put_hwpt;
 	}
 
-	viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain,
+	viommu = ops->viommu_alloc(idev->dev, idev->kvm,
+				   hwpt_paging->common.domain,
 				   ucmd->ictx, cmd->type);
 	if (IS_ERR(viommu)) {
 		rc = PTR_ERR(viommu);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index cb01fe49f5df..2f61e0178cfa 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -44,6 +44,7 @@ struct iommu_dma_cookie;
 struct iommu_fault_param;
 struct iommufd_ctx;
 struct iommufd_viommu;
+struct kvm;
 
 #define IOMMU_FAULT_PERM_READ	(1 << 0) /* read */
 #define IOMMU_FAULT_PERM_WRITE	(1 << 1) /* write */
@@ -646,7 +647,8 @@ struct iommu_ops {
 	int (*def_domain_type)(struct device *dev);
 
 	struct iommufd_viommu *(*viommu_alloc)(
-		struct device *dev, struct iommu_domain *parent_domain,
+		struct device *dev, struct kvm *kvm,
+		struct iommu_domain *parent_domain,
 		struct iommufd_ctx *ictx, unsigned int viommu_type);
 
 	const struct iommu_domain_ops *default_domain_ops;
-- 
2.47.0



From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:32:01 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:32:01 +0000
Subject: [RFC PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Use KVM VMID for s2 stage
In-Reply-To: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319173202.78988-5-shameerali.kolothum.thodi@huawei.com>

If kvm is available make use of kvm pinned VMID on BTM
enabled systems to set the s2 stage VMID for nested
domains.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
---
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 53 +++++++++++++++++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  1 +
 2 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index ee2fac5c899b..79fcb903741f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
  */
 
+#include <linux/kvm_host.h>
 #include <uapi/linux/iommufd.h>
 
 #include "arm-smmu-v3.h"
@@ -39,6 +40,48 @@ arm_smmu_get_msi_mapping_domain(struct iommu_domain *domain)
 	return &nested_domain->vsmmu->s2_parent->domain;
 }
 
+static int arm_vsmmu_alloc_vmid(struct arm_smmu_device *smmu, struct kvm *kvm,
+				bool *kvm_used)
+{
+#ifdef CONFIG_KVM
+	/*
+	 * There can only be one allocator for VMIDs active at once. If BTM is
+	 * turned on then KVM's allocator always supplies the VMID, and the
+	 * VMID is matched by CPU invalidation of the KVM S2. Right now there
+	 * is no API to get an unused VMID from KVM so this also means BTM systems
+	 * cannot support S2 without an associated KVM.
+	 */
+	if ((smmu->features & ARM_SMMU_FEAT_BTM)) {
+		int vmid;
+
+		if (!kvm || !kvm_get_kvm_safe(kvm))
+			return -EOPNOTSUPP;
+		vmid = kvm_arm_pinned_vmid_get(kvm);
+		if (vmid < 0)
+			kvm_put_kvm(kvm);
+		else
+			*kvm_used = true;
+		return vmid;
+	}
+#endif
+	return ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1,
+			       GFP_KERNEL);
+}
+
+static void arm_vsmmu_free_vmid(struct arm_smmu_device *smmu, u16 vmid,
+				struct kvm *kvm)
+{
+#ifdef CONFIG_KVM
+	if ((smmu->features & ARM_SMMU_FEAT_BTM)) {
+		if (kvm) {
+			kvm_arm_pinned_vmid_put(kvm);
+			return kvm_put_kvm(kvm);
+		}
+	}
+#endif
+	ida_free(&smmu->vmid_map, vmid);
+}
+
 static void arm_vsmmu_destroy(struct iommufd_viommu *viommu)
 {
 	struct arm_vsmmu *vsmmu = container_of(viommu, struct arm_vsmmu, core);
@@ -53,7 +96,7 @@ static void arm_vsmmu_destroy(struct iommufd_viommu *viommu)
 	list_del(&vsmmu->vsmmus_elm);
 	spin_unlock_irqrestore(&vsmmu->s2_parent->vsmmus.lock, flags);
 	arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
-	ida_free(&smmu->vmid_map, vsmmu->vmid);
+	arm_vsmmu_free_vmid(smmu, vsmmu->vmid, vsmmu->kvm);
 }
 
 static void arm_smmu_make_nested_cd_table_ste(
@@ -379,6 +422,7 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 		iommu_get_iommu_dev(dev, struct arm_smmu_device, iommu);
 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
 	struct arm_smmu_domain *s2_parent = to_smmu_domain(parent);
+	bool kvm_used = false;
 	struct arm_vsmmu *vsmmu;
 	unsigned long flags;
 	int vmid;
@@ -409,21 +453,22 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
 	    !(smmu->features & ARM_SMMU_FEAT_S2FWB))
 		return ERR_PTR(-EOPNOTSUPP);
 
-	vmid = ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1,
-			       GFP_KERNEL);
+	vmid = arm_vsmmu_alloc_vmid(smmu, kvm, &kvm_used);
 	if (vmid < 0)
 		return ERR_PTR(vmid);
 
 	vsmmu = iommufd_viommu_alloc(ictx, struct arm_vsmmu, core,
 				     &arm_vsmmu_ops);
 	if (IS_ERR(vsmmu)) {
-		ida_free(&smmu->vmid_map, vmid);
+		arm_vsmmu_free_vmid(smmu, vmid, kvm);
 		return ERR_CAST(vsmmu);
 	}
 
 	vsmmu->smmu = smmu;
 	vsmmu->vmid = (u16)vmid;
 	vsmmu->s2_parent = s2_parent;
+	if (kvm_used)
+		vsmmu->kvm = kvm;
 	spin_lock_irqsave(&s2_parent->vsmmus.lock, flags);
 	list_add_tail(&vsmmu->vsmmus_elm, &s2_parent->vsmmus.list);
 	spin_unlock_irqrestore(&s2_parent->vsmmus.lock, flags);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 9f49de52a700..5890c233f73b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1053,6 +1053,7 @@ struct arm_vsmmu {
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_domain *s2_parent;
 	u16 vmid;
+	struct kvm *kvm;
 
 	struct list_head vsmmus_elm; /* arm_smmu_domain::vsmmus::list */
 };
-- 
2.47.0



From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:31:57 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:31:57 +0000
Subject: [RFC PATCH v3 0/5] iommu/arm-smmu-v3: Use pinned KVM VMID for stage 2
Message-ID: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>

Hi All,

Changes from RFCv2[0]

-Based on feedback received, removed generic KVM APIs for pinned_vmid_
 {get,put}()?and are now implemented directly by KVM ARM.
-struct kvm * is now associated with struct iommufd_device and the association
?is established when idev is first allocated during iommufd_device_bind().
-This is now based on Nicolin's recent series[1], which decouples the vmid
?from S2 parent domains and is assigned during viommu/vSMMU alloc time.
-Added additional checks to make sure when BTM is enabled, kvm is mandatory.
-At the moment, kvm_get_kvm_safe()/kvm_put_kvm() is used inside the smmuv3
?driver and not in iommufd as iommufd is not a user of kvm and is just
 passed through.

ToDo:
-May be we need to check both KVM and SMMUv3 has the same number of VMID
bits supported. Not sure we have systems like that out there.

Why we require this(Thanks to Jean for the nice write-up below):

---
* When enabling BTM in the SMMU, all TLB invalidations to the
? inner-shareable domain issued by the CPU are taken into account by the
? SMMU. That includes for example the TLBI IPAS2E1IS from
? __kvm_tlb_flush_vmid_range().

* BTM is enabled globally in the SMMU CR2 register. If we enable BTM for
? host SVA, then it also affects KVM.

* Stage-1 TLB entries in the SMMU have a bit (ASET) saying "this entry
? is private and does not participate in BTM", which we set for private
? SMMU address spaces.

? Annoyingly, the stage-2 TLB entries do not have it. With BTM all VMIDs
? are shared between CPU and SMMU.

* So, if the SMMU driver allocates VMID privately and we enable BTM, then
? CPU invalidations will remove unrelated SMMU TLB entries. Instead, the
? SMMU driver needs to coordinate with KVM on VMID allocation.

* Private stage-2 address spaces in the SMMU would need to allocate VMIDs
? that aren't used by KVM, but that's not a use-case at the moment:

? - For assigning devices to a host process or to a VM, we use private
? ? stage-1 mappings. stage-2 will be used to enable nesting translation,
? ? and will typically mirror the KVM stage-2 since it pins the guest
? ? address space.

? - If the SMMU doesn't support stage-1, the driver falls back to stage-2
? ? for private address spaces. For such an implementation we disable BTM.
---

This is sanity tested on a HiSilicon platform and the complete branch is
available here[2].

Please take a look and let me know your feedback.

Thanks,
Shameer
[0] https://lore.kernel.org/kvmarm/20240208151837.35068-1-shameerali.kolothum.thodi at huawei.com/
[1] https://lore.kernel.org/linux-iommu/cover.1741150594.git.nicolinc at nvidia.com/
[2] https://github.com/hisilicon/kernel-dev/tree/smmuv3_vmid-v1-with-rmr-vmid-v3-ext

Jean-Philippe Brucker (1):
  iommu/arm-smmu-v3: Enable broadcast TLB maintenance

Shameer Kolothum (4):
  KVM: arm64: Introduce support to pin VMIDs
  iommufd/device: Associate a kvm pointer to iommufd_device
  iommu/arm-smmu-v3-iommufd: Pass in kvm pointer to viommu_alloc
  iommu/arm-smmu-v3-iommufd: Use KVM VMID for s2 stage

 arch/arm64/include/asm/kvm_host.h             |  3 +
 arch/arm64/kvm/vmid.c                         | 76 ++++++++++++++++++-
 .../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c     | 54 ++++++++++++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 24 +++++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  3 +
 drivers/iommu/iommufd/device.c                |  5 +-
 drivers/iommu/iommufd/iommufd_private.h       |  2 +
 drivers/iommu/iommufd/viommu.c                |  3 +-
 drivers/vfio/iommufd.c                        |  2 +-
 include/linux/iommu.h                         |  4 +-
 include/linux/iommufd.h                       |  4 +-
 11 files changed, 168 insertions(+), 12 deletions(-)

-- 
2.47.0



From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:31:58 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:31:58 +0000
Subject: [RFC PATCH v3 1/5] KVM: arm64: Introduce support to pin VMIDs
In-Reply-To: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319173202.78988-2-shameerali.kolothum.thodi@huawei.com>

Introduce kvm_arm_pinned_vmid_get() and kvm_arm_pinned_vmid_put(), to pin
a VMID associated with a KVM instance. This will guarantee that VMID
remains the same after a rollover.

This is in preparation of introducing support in the SMMUv3 driver to use
the KVM VMID for S2 stage configuration in nested mode.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
---
 arch/arm64/include/asm/kvm_host.h |  3 ++
 arch/arm64/kvm/vmid.c             | 76 ++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d919557af5e5..b6682f5d1b86 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -142,6 +142,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages);
 
 struct kvm_vmid {
 	atomic64_t id;
+	refcount_t pinned;
 };
 
 struct kvm_s2_mmu {
@@ -1261,6 +1262,8 @@ int __init kvm_arm_vmid_alloc_init(void);
 void __init kvm_arm_vmid_alloc_free(void);
 void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
 void kvm_arm_vmid_clear_active(void);
+int kvm_arm_pinned_vmid_get(struct kvm *kvm);
+void kvm_arm_pinned_vmid_put(struct kvm *kvm);
 
 static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
 {
diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c
index 7fe8ba1a2851..7bda189e927c 100644
--- a/arch/arm64/kvm/vmid.c
+++ b/arch/arm64/kvm/vmid.c
@@ -25,6 +25,10 @@ static unsigned long *vmid_map;
 static DEFINE_PER_CPU(atomic64_t, active_vmids);
 static DEFINE_PER_CPU(u64, reserved_vmids);
 
+static unsigned long max_pinned_vmids;
+static unsigned long nr_pinned_vmids;
+static unsigned long *pinned_vmid_map;
+
 #define VMID_MASK		(~GENMASK(kvm_arm_vmid_bits - 1, 0))
 #define VMID_FIRST_VERSION	(1UL << kvm_arm_vmid_bits)
 
@@ -47,7 +51,10 @@ static void flush_context(void)
 	int cpu;
 	u64 vmid;
 
-	bitmap_zero(vmid_map, NUM_USER_VMIDS);
+	if (pinned_vmid_map)
+		bitmap_copy(vmid_map, pinned_vmid_map, NUM_USER_VMIDS);
+	else
+		bitmap_zero(vmid_map, NUM_USER_VMIDS);
 
 	for_each_possible_cpu(cpu) {
 		vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0);
@@ -103,6 +110,14 @@ static u64 new_vmid(struct kvm_vmid *kvm_vmid)
 			return newvmid;
 		}
 
+		/*
+		 * If it is pinned, we can keep using it. Note that reserved
+		 * takes priority, because even if it is also pinned, we need to
+		 * update the generation into the reserved_vmids.
+		 */
+		if (refcount_read(&kvm_vmid->pinned))
+			return newvmid;
+
 		if (!__test_and_set_bit(vmid2idx(vmid), vmid_map)) {
 			atomic64_set(&kvm_vmid->id, newvmid);
 			return newvmid;
@@ -169,6 +184,55 @@ void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
 	raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags);
 }
 
+int kvm_arm_pinned_vmid_get(struct kvm *kvm)
+{
+	struct kvm_vmid *kvm_vmid;
+	u64 vmid;
+
+	if (!pinned_vmid_map || !kvm)
+		return -EINVAL;
+
+	kvm_vmid = &kvm->arch.mmu.vmid;
+
+	guard(raw_spinlock_irqsave)(&cpu_vmid_lock);
+	vmid = atomic64_read(&kvm_vmid->id);
+
+	if (refcount_inc_not_zero(&kvm_vmid->pinned))
+		return (vmid & ~VMID_MASK);
+
+	if (nr_pinned_vmids >= max_pinned_vmids)
+		return -EINVAL;
+
+	/*
+	 * If we went through one or more rollover since that VMID was
+	 * used, make sure it is still valid, or generate a new one.
+	 */
+	if (!vmid_gen_match(vmid))
+		vmid = new_vmid(kvm_vmid);
+
+	nr_pinned_vmids++;
+	__set_bit(vmid2idx(vmid), pinned_vmid_map);
+	refcount_set(&kvm_vmid->pinned, 1);
+	return (vmid & ~VMID_MASK);
+}
+
+void kvm_arm_pinned_vmid_put(struct kvm *kvm)
+{
+	struct kvm_vmid *kvm_vmid;
+	u64 vmid;
+
+	if (!pinned_vmid_map || !kvm)
+		return;
+
+	kvm_vmid = &kvm->arch.mmu.vmid;
+	vmid = atomic64_read(&kvm_vmid->id);
+	guard(raw_spinlock_irqsave)(&cpu_vmid_lock);
+	if (refcount_dec_and_test(&kvm_vmid->pinned)) {
+		__clear_bit(vmid2idx(vmid), pinned_vmid_map);
+		nr_pinned_vmids--;
+	}
+}
+
 /*
  * Initialize the VMID allocator
  */
@@ -186,10 +250,20 @@ int __init kvm_arm_vmid_alloc_init(void)
 	if (!vmid_map)
 		return -ENOMEM;
 
+	pinned_vmid_map = bitmap_zalloc(NUM_USER_VMIDS, GFP_KERNEL);
+	nr_pinned_vmids = 0;
+
+	/*
+	 * Ensure we have at least one emty slot available after rollover
+	 * and maximum number of VMIDs are pinned. VMID#0 is reserved.
+	 */
+	max_pinned_vmids = NUM_USER_VMIDS - num_possible_cpus() - 2;
+
 	return 0;
 }
 
 void __init kvm_arm_vmid_alloc_free(void)
 {
+	bitmap_free(pinned_vmid_map);
 	bitmap_free(vmid_map);
 }
-- 
2.47.0



From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:31:59 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:31:59 +0000
Subject: [RFC PATCH v3 2/5] iommufd/device: Associate a kvm pointer to iommufd_device
In-Reply-To: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319173202.78988-3-shameerali.kolothum.thodi@huawei.com>

Add a struct kvm * to iommufd_device_bind() fn and associate it
with idev if bind is successful.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
---
 drivers/iommu/iommufd/device.c          | 5 ++++-
 drivers/iommu/iommufd/iommufd_private.h | 2 ++
 drivers/vfio/iommufd.c                  | 2 +-
 include/linux/iommufd.h                 | 4 +++-
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index dfd0898fb6c1..0f3983b16d56 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -146,6 +146,7 @@ void iommufd_device_destroy(struct iommufd_object *obj)
  * iommufd_device_bind - Bind a physical device to an iommu fd
  * @ictx: iommufd file descriptor
  * @dev: Pointer to a physical device struct
+ * @kvm: Pointer to struct kvm if device belongs to a KVM VM
  * @id: Output ID number to return to userspace for this device
  *
  * A successful bind establishes an ownership over the device and returns
@@ -159,7 +160,8 @@ void iommufd_device_destroy(struct iommufd_object *obj)
  * The caller must undo this with iommufd_device_unbind()
  */
 struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
-					   struct device *dev, u32 *id)
+					   struct device *dev, struct kvm *kvm,
+					   u32 *id)
 {
 	struct iommufd_device *idev;
 	struct iommufd_group *igroup;
@@ -209,6 +211,7 @@ struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
 	if (!iommufd_selftest_is_mock_dev(dev))
 		iommufd_ctx_get(ictx);
 	idev->dev = dev;
+	idev->kvm = kvm;
 	idev->enforce_cache_coherency =
 		device_iommu_capable(dev, IOMMU_CAP_ENFORCE_CACHE_COHERENCY);
 	/* The calling driver is a user until iommufd_device_unbind() */
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 0b1bafc7fd99..73201ff2c40e 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -398,6 +398,8 @@ struct iommufd_device {
 	struct list_head group_item;
 	/* always the physical device */
 	struct device *dev;
+	/* ..and kvm if available */
+	struct kvm *kvm;
 	bool enforce_cache_coherency;
 	/* protect iopf_enabled counter */
 	struct mutex iopf_lock;
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 516294fd901b..664e3579ce0e 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -115,7 +115,7 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
 {
 	struct iommufd_device *idev;
 
-	idev = iommufd_device_bind(ictx, vdev->dev, out_device_id);
+	idev = iommufd_device_bind(ictx, vdev->dev, vdev->kvm, out_device_id);
 	if (IS_ERR(idev))
 		return PTR_ERR(idev);
 	vdev->iommufd_device = idev;
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 11110c749200..ac8cca0190f4 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -22,6 +22,7 @@ struct iommufd_ctx;
 struct iommufd_device;
 struct iommufd_viommu_ops;
 struct page;
+struct kvm;
 
 enum iommufd_object_type {
 	IOMMUFD_OBJ_NONE,
@@ -49,7 +50,8 @@ struct iommufd_object {
 };
 
 struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
-					   struct device *dev, u32 *id);
+					   struct device *dev, struct kvm *kvm,
+					   u32 *id);
 void iommufd_device_unbind(struct iommufd_device *idev);
 
 int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id);
-- 
2.47.0



From shameerali.kolothum.thodi at huawei.com  Wed Mar 19 10:32:02 2025
From: shameerali.kolothum.thodi at huawei.com (Shameer Kolothum)
Date: Wed, 19 Mar 2025 17:32:02 +0000
Subject: [RFC PATCH v3 5/5] iommu/arm-smmu-v3: Enable broadcast TLB maintenance
In-Reply-To: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319173202.78988-6-shameerali.kolothum.thodi@huawei.com>

From: Jean-Philippe Brucker <jean-philippe at linaro.org>

The SMMUv3 can handle invalidation targeted at TLB entries with shared
ASIDs. If the implementation supports broadcast TLB maintenance, enable it
and keep track of it in a feature bit. The SMMU will then be affected by
inner-shareable TLB invalidations from other agents.

In order to avoid over invalidation with stage-2 translation contexts,
enable BTM only when SMMUv3 supports eiher S1 or both S1 & S2 transaltion
contexts. In this way the default domain will use stage-1 and stage-2 will
be only used for NESTED Domain setup.

Signed-off-by: Jean-Philippe Brucker <jean-philippe at linaro.org>
[Shameer: Enable BTM only if S1 is supported]
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 +++++++++++++++++++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  1 +
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index addc6308742b..06a13d78286a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4119,11 +4119,14 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	writel_relaxed(reg, smmu->base + ARM_SMMU_CR1);
 
 	/* CR2 (random crap) */
-	reg = CR2_PTM | CR2_RECINVSID;
+	reg = CR2_RECINVSID;
 
 	if (smmu->features & ARM_SMMU_FEAT_E2H)
 		reg |= CR2_E2H;
 
+	if (!(smmu->features & ARM_SMMU_FEAT_BTM))
+		reg |= CR2_PTM;
+
 	writel_relaxed(reg, smmu->base + ARM_SMMU_CR2);
 
 	/* Stream table */
@@ -4289,6 +4292,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
 	u32 reg;
 	bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
+	bool vhe = cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN);
 
 	/* IDR0 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -4341,7 +4345,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 
 	if (reg & IDR0_HYP) {
 		smmu->features |= ARM_SMMU_FEAT_HYP;
-		if (cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN))
+		if (vhe)
 			smmu->features |= ARM_SMMU_FEAT_E2H;
 	}
 
@@ -4368,6 +4372,22 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 
 	if (reg & IDR0_S2P)
 		smmu->features |= ARM_SMMU_FEAT_TRANS_S2;
+	/*
+	 * If S1 is supported, verify that BTM can be enabled.  If S2 is available
+	 * and BTM is enabled, S2 will be used exclusively for nested domains,
+	 * ensuring a KVM VMID is obtained.
+	 * BTM is beneficial when the CPU shares page tables with SMMUv3 (e.g., vSVA).
+	 */
+	if (reg & IDR0_S1P) {
+		/*
+		 * If the CPU is using VHE, but the SMMU doesn't support it, the SMMU
+		 * will create TLB entries for NH-EL1 world and will miss the
+		 * broadcasted TLB invalidations that target EL2-E2H world. Don't enable
+		 * BTM in that case.
+		 */
+		if (reg & IDR0_BTM && (!vhe || reg & IDR0_HYP))
+			smmu->features |= ARM_SMMU_FEAT_BTM;
+	}
 
 	if (!(reg & (IDR0_S1P | IDR0_S2P))) {
 		dev_err(smmu->dev, "no translation support!\n");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 5890c233f73b..f554b6aa52c9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -39,6 +39,7 @@ struct arm_smmu_device;
 #define IDR0_HTTU			GENMASK(7, 6)
 #define IDR0_HTTU_ACCESS		1
 #define IDR0_HTTU_ACCESS_DIRTY		2
+#define IDR0_BTM			(1 << 5)
 #define IDR0_COHACC			(1 << 4)
 #define IDR0_TTF			GENMASK(3, 2)
 #define IDR0_TTF_AARCH64		2
-- 
2.47.0



From patchwork-bot+netdevbpf at kernel.org  Wed Mar 19 10:40:35 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Wed, 19 Mar 2025 17:40:35 +0000
Subject: [PATCH RESEND net-next v2] net: stmmac: dwmac-rk: Provide FIFO sizes
 for DWMAC 1000
In-Reply-To: <20250312163426.2178314-1-wens@kernel.org>
References: <20250312163426.2178314-1-wens@kernel.org>
Message-ID: <174240603529.1129938.15321664004147428078.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Thu, 13 Mar 2025 00:34:26 +0800 you wrote:
> From: Chen-Yu Tsai <wens at csie.org>
> 
> The DWMAC 1000 DMA capabilities register does not provide actual
> FIFO sizes, nor does the driver really care. If they are not
> provided via some other means, the driver will work fine, only
> disallowing changing the MTU setting.
> 
> [...]

Here is the summary with links:
  - [RESEND,net-next,v2] net: stmmac: dwmac-rk: Provide FIFO sizes for DWMAC 1000
    https://git.kernel.org/netdev/net-next/c/d3c58b656c97

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From bvanassche at acm.org  Wed Mar 19 10:45:20 2025
From: bvanassche at acm.org (Bart Van Assche)
Date: Wed, 19 Mar 2025 10:45:20 -0700
Subject: [PATCH v3 1/1] scsi: ufs: core: add device level exception
 support
In-Reply-To: <9cf88cda-cf9c-9dbd-d586-5463ce2a0cfc@quicinc.com>
References: <6109425449ac4d18249ce7254e4fa1252138a94a.1742369183.git.quic_nguyenb@quicinc.com>
 <61570104d58cef22716fefe459c0c45670108aad.camel@mediatek.com>
 <9cf88cda-cf9c-9dbd-d586-5463ce2a0cfc@quicinc.com>
Message-ID: <d82ce6c4-ae17-4ac6-9bb9-59759f8a185d@acm.org>

On 3/19/25 2:01 AM, Bao D. Nguyen wrote:
> On 3/19/2025 12:56 AM, Peter Wang (???) wrote:
>> Could use atomic_t for counter protect?
>
> Are you suggesting to convert the dev_lvl_exception_count type from u32 
> to atomic_t type? Because the value of dev_lvl_exception_count is 
> returned to the user space via the device_lvl_exception_count_show() 
> using the sysfs_emit() function, keeping the dev_lvl_exception_count as 
> u32 data type probably works better in terms of the format.

I like the suggestion to use atomic_t. atomic_read() can be used in the
sysfs show method.

Thanks,

Bart.


From claudiu.beznea at tuxon.dev  Wed Mar 19 10:50:09 2025
From: claudiu.beznea at tuxon.dev (Claudiu Beznea)
Date: Wed, 19 Mar 2025 19:50:09 +0200
Subject: [PATCH 0/2] AT91 Clock Adjustments
In-Reply-To: <7512d7fb-30dd-41f6-8936-45ff0d949876@microchip.com>
References: <cover.1738864727.git.Ryan.Wanner@microchip.com>
 <7dd5a0a2-4f56-48b4-8861-c7d75754faab@tuxon.dev>
 <b76108c1-3282-4b98-a210-b350e8ec0ec2@microchip.com>
 <7512d7fb-30dd-41f6-8936-45ff0d949876@microchip.com>
Message-ID: <3935c980-3802-48f0-8f02-7222db0f3fd5@tuxon.dev>



On 18.03.2025 19:33, Ryan Wanner wrote:
> On 2/26/25 08:36, Ryan wrote:
>> On 2/26/25 02:06, Claudiu Beznea wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> On 06.02.2025 20:14, Ryan.Wanner at microchip.com wrote:
>>>> From: Ryan Wanner <Ryan.Wanner at microchip.com>
>>>>
>>>> This set has clock system adjustments for the AT91 clock system.
>>>>
>>>> The first is to adjust the slow clock driver to account for the updated
>>>> DT node-naming for clocks and xtals and ensuring the driver is still
>>>> backwards compatible.
>>>>
>>>> The second is a adding a missing clk_hw struct that is not added into
>>>> parent_data struct causing a incorrect parent for main_osc.
>>>>
>>>> Ryan Wanner (2):
>>>>   clk: at91: sckc: Fix parent_data struct for slow osc
>>>>   clk: at91: sama7d65: Add missing clk_hw to parent_data
>>>>
>>>>  drivers/clk/at91/sama7d65.c |  1 +
>>>>  drivers/clk/at91/sckc.c     | 12 ++++++------
>>>>  2 files changed, 7 insertions(+), 6 deletions(-)
>>>>
>>>
>>> There are boot failures on sama7g5 with this series on top of at91-next and
>>> the following diff on sama7g5 dts to mimic the sama7d65 use case:
>>>
>>> diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>>> b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>>> index 0f5e6ad438dd..1bce9f999431 100644
>>> --- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>>> +++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
>>> @@ -35,16 +35,6 @@ aliases {
>>>                 i2c2 = &i2c9;
>>>         };
>>>
>>> -       clocks {
>>> -               slow_xtal {
>>> -                       clock-frequency = <32768>;
>>> -               };
>>> -
>>> -               main_xtal {
>>> -                       clock-frequency = <24000000>;
>>> -               };
>>> -       };
>>> -
>>>         gpio-keys {
>>>                 compatible = "gpio-keys";
>>>
>>> @@ -132,6 +122,15 @@ spdif_out: spdif-out {
>>>         };
>>>  };
>>>
>>> +&slow_xtal {
>>> +       clock-frequency = <32768>;
>>> +};
>>> +
>>> +&main_xtal {
>>> +       clock-frequency = <24000000>;
>>> +};
>>> +
>>> +
>>>  &adc {
>>>         vddana-supply = <&vddout25>;
>>>         vref-supply = <&vddout25>;
>>> diff --git a/arch/arm/boot/dts/microchip/sama7g5.dtsi
>>> b/arch/arm/boot/dts/microchip/sama7g5.dtsi
>>> index 17bcdcf0cf4a..3158c2f0b4c0 100644
>>> --- a/arch/arm/boot/dts/microchip/sama7g5.dtsi
>>> +++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi
>>> @@ -117,12 +117,12 @@ map1 {
>>>         };
>>>
>>>         clocks {
>>> -               slow_xtal: slow_xtal {
>>> +               slow_xtal: clk-slowxtal {
>>>                         compatible = "fixed-clock";
>>>                         #clock-cells = <0>;
>>>                 };
>>>
>>> -               main_xtal: main_xtal {
>>> +               main_xtal: clk-mainxtal {
>>>                         compatible = "fixed-clock";
>>>                         #clock-cells = <0>;
>>>                 };
>>>
>>> I've identified the following:
>>>
>>>
>>> cpu cpu0: _opp_config_clk_single: failed to set clock rate: -22
>>> cpufreq: __target_index: Failed to change cpu frequency: -22
>>> ------------[ cut here ]------------
>>> kernel BUG at drivers/cpufreq/cpufreq.c:1523!
>>> Internal error: Oops - BUG: 0 [#1] ARM
>>> Modules linked in:
>>> CPU: 0 UID: 0 PID: 1 Comm: swapper Not tainted 6.14.0-rc1+ #11
>>> Hardware name: Microchip SAMA7
>>> PC is at cpufreq_online+0x8d8/0xa30
>>> LR is at __wake_up+0x20/0x30
>>> pc : [<c063cca0>]    lr : [<c0151254>]    psr: a0000013
>>> sp : e0821d30  ip : 00000000  fp : c0e50508
>>> r10: c434830c  r9 : c4348204  r8 : c0e97230
>>> r7 : c4348264  r6 : 00000000  r5 : 000ca511  r4 : c4348200
>>> r3 : 047e0d67  r2 : 047e0d67  r1 : 00000003  r0 : ffffffea
>>> Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>>> Control: 10c53c7d  Table: 60004059  DAC: 00000051
>>> Register r0 information: non-paged memory
>>> Register r1 information: non-paged memory
>>> Register r2 information: non-paged memory
>>> Register r3 information: non-paged memory
>>> Register r4 information: slab kmalloc-512 start c4348200 pointer offset 0
>>> size 512
>>> Register r5 information: non-paged memory
>>> Register r6 information: NULL pointer
>>> Register r7 information: slab kmalloc-512 start c4348200 pointer offset 100
>>> size 512
>>> Register r8 information: non-slab/vmalloc memory
>>> Register r9 information: slab kmalloc-512 start c4348200 pointer offset 4
>>> size 512
>>> Register r10 information: slab kmalloc-512 start c4348200 pointer offset
>>> 268 size 512
>>> Register r11 information: non-slab/vmalloc memory
>>> Register r12 information: NULL pointer
>>> Process swapper (pid: 1, stack limit = 0x08d7ca6b)
>>> Stack: (0xe0821d30 to 0xe0822000)
>>> 1d20:                                     00000000 e0821d98 c4348208 c0c00250
>>> 1d40: 00000001 00000000 e0821d98 c0e50508 c4048000 00000000 c406f480 c4048000
>>> 1d60: c4341ec0 c0e50508 c4341ec8 c063ce8c c0e593a8 c4048000 c406f4bc c406f480
>>> 1d80: c4048000 c04c8bb0 c406f4cc c40704b0 00000000 047e0d67 3b9aca03 c0e5986c
>>> 1da0: c0e5931c c0e97230 00000000 c063a618 00000000 c4048000 c0e59858 c40d0a10
>>> 1dc0: c0e597f0 c063f80c c0d31830 00000000 00000000 00000000 00000000 00000000
>>> 1de0: 00000000 00000000 e0821df4 00000000 00000000 c0ba32fc 00000000 047e0d67
>>> 1e00: c40d75d8 00000000 c40d0a10 c0e59804 00000000 00000000 c0d31830 c0c2b5a0
>>> 1e20: c0c776b0 c04cc8dc c40d0a10 00000000 c0e59804 c04ca1f4 c40d0a10 c0e59804
>>> 1e40: c40d0a10 00000000 00000000 c04ca47c 00000000 c0be8598 c0e94b28 c0e59804
>>> 1e60: c40d0a10 00000000 00000000 c04ca658 c40d0a10 c0e59804 c40d0a54 c4048000
>>> 1e80: 00000000 c04ca8c4 c0e59804 c04ca834 c406f3c0 c04c8494 c4048000 c406f40c
>>> 1ea0: c4070d30 047e0d67 c0e59804 c4341e00 00000000 c406f3c0 c4341e34 c04c959c
>>> 1ec0: c0c00c14 c0e6c000 c0e59804 c0d2113c c4070800 00000000 c0e6c000 c04cb598
>>> 1ee0: c4048000 c0d2113c c4070800 c010d21c 000003c0 00000000 c407084e c4070800
>>> 1f00: c407084d c013e9e0 c0bee764 000000c0 00000000 00000000 c0d004d0 c4048000
>>> 1f20: 00000006 00000006 373126cc c407086a 00000000 047e0d67 00000012 047e0d67
>>> 1f40: 00000007 c0d42bd8 00000007 c4070800 000000c0 c0d31850 c0d31830 c0d011f4
>>> 1f60: 00000006 00000006 00000000 c0d004d0 e0821f6c c0d004d0 00000000 c0e03380
>>> 1f80: c0905828 00000000 00000000 00000000 00000000 00000000 00000000 c0905844
>>> 1fa0: 00000000 c0905828 00000000 c010014c 00000000 00000000 00000000 00000000
>>> 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>>> 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
>>> Call trace:
>>>  cpufreq_online from cpufreq_add_dev+0x84/0x94
>>>  cpufreq_add_dev from subsys_interface_register+0xf0/0x108
>>>  subsys_interface_register from cpufreq_register_driver+0x13c/0x2e4
>>>  cpufreq_register_driver from dt_cpufreq_probe+0xb4/0x380
>>>  dt_cpufreq_probe from platform_probe+0x5c/0xb8
>>>  platform_probe from really_probe+0xc8/0x2c8
>>>  really_probe from __driver_probe_device+0x88/0x19c
>>>  __driver_probe_device from driver_probe_device+0x30/0x104
>>>  driver_probe_device from __driver_attach+0x90/0x178
>>>  __driver_attach from bus_for_each_dev+0x6c/0xb4
>>>  bus_for_each_dev from bus_add_driver+0xcc/0x1ec
>>>  bus_add_driver from driver_register+0x7c/0x114
>>>  driver_register from do_one_initcall+0x40/0x21c
>>>  do_one_initcall from kernel_init_freeable+0x194/0x1f8
>>>  kernel_init_freeable from kernel_init+0x1c/0x128
>>>  kernel_init from ret_from_fork+0x14/0x28
>>> Exception stack(0xe0821fb0 to 0xe0821ff8)
>>> 1fa0:                                     00000000 00000000 00000000 00000000
>>> 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>>> 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
>>> Code: e3a02000 ebfff87e e3500000 0a000043 (e7f001f2)
>>> ---[ end trace 0000000000000000 ]---
>>> note: swapper[1] exited with irqs disabled
>>> Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
>>> ---[ end Kernel panic - not syncing: Attempted to kill init!
>>> exitcode=0x0000000b ]---
>>>
>>>
>>> And this one:
>>>
>>> Starting kernel ...
>>>
>>> Booting Linux on physical CPU 0x0
>>> Linux version 6.14.0-rc1+ (claudiu at claudiu-X670E-Pro-RS)
>>> (arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture
>>> 10.3-2021.07 (arm-10.29)) 10.3.1 20210621, GNU ld (GNU Toolchain for the
>>> A-profile Architecture 10.3-2021.07 (arm-10.29)) 2.36.1.20210621) #11 Wed
>>> Feb 26 11:01:10 EET 2025
>>> CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c53c7d
>>> CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
>>> OF: fdt: Machine model: Microchip SAMA7G5-EK
>>> printk: legacy bootconsole [earlycon0] enabled
>>> Memory policy: Data cache writeback
>>> cma: Reserved 192 MiB at 0x70000000 on node -1
>>> Zone ranges:
>>>   Normal   [mem 0x0000000060000000-0x000000007fffffff]
>>> Movable zone start for each node
>>> Early memory node ranges
>>>   node   0: [mem 0x0000000060000000-0x000000007fffffff]
>>> Initmem setup node 0 [mem 0x0000000060000000-0x000000007fffffff]
>>> OF: reserved mem: Reserved memory: No reserved-memory node in the DT
>>> CPU: All CPU(s) started in SVC mode.
>>> Kernel command line: console=ttyS0,115200 root=/dev/mmcblk1p2
>>> rootfstype=ext4 rw rootwait cma=192m atmel.pm_modes=standby,ulp0 earlyprintk
>>> printk: log buffer data + meta data: 65536 + 204800 = 270336 bytes
>>> Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
>>> Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
>>> Built 1 zonelists, mobility grouping on.  Total pages: 131072
>>> mem auto-init: stack:off, heap alloc:off, heap free:off
>>> SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
>>> NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
>>> Main crystal frequency not set, using approximate value
>>> timer_probe: no matching timers found
>>> Console: colour dummy device 80x30
>>> sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every
>>> 21474836475000000ns
>>>
>>>
>>> I suspect parent_data in sama7g5_pmc_setup() need to be initialized with zero.
>>
>> With this series I did not see any boot issues with the sama7g54. But
>> when doing the DTS and DTSI changes that you made above I did see boot
>> issues with the sama7g54.
>>
>> It seems that the 2/2 patch also needs to have a similar patch for the
>> sama7g54 clock driver.
> 
> Would it be better to have this change to all the SoCs and their clock
> drivers to match the correct naming? 

That would be good.

Thank you,
Claudiu

> Since this set is mainly to adjust
> for sama7d65 and a separate change to sama7g5.c clock driver would be
> needed to fix the error that you are seeing above.
>>
>> Best,
>> Ryan
>>>
>>> Thank you,
>>> Claudiu
>>>
>>>
>>>
>>
> 



From catalin.marinas at arm.com  Wed Mar 19 11:03:57 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 19 Mar 2025 18:03:57 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250318231736.GE9311@nvidia.com>
References: <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com>
 <20250318231736.GE9311@nvidia.com>
Message-ID: <Z9sHDbBgoMt7M-vc@arm.com>

On Tue, Mar 18, 2025 at 08:17:36PM -0300, Jason Gunthorpe wrote:
> On Tue, Mar 18, 2025 at 07:27:27PM +0000, Catalin Marinas wrote:
> > Thinking some more about a KVM capability that the VMM can check, I'm
> > not sure what it can do with this. The VMM simply maps something from a
> > device and cannot probe the cacheability 
> 
> KVM is mirroring the MM's PTEs to the S2's PTEs.
> 
> You can think about this differently - KVM currently has a little bug
> where the MM's PTE's can say cachable but KVM will mirror it to a S2
> PTE that is forced non-cachable. KVM will not do any cache flushing to
> make this safe.
> 
> Fundamentally that discrepancy is what is being addressed
> here. Cachable PTEs in the MM should be mirrored to cachable PTEs in
> the S2.

If we treat this as a bug (and I agree it's a potential problem if we
assign devices to the guest that have cacheable VMM mappings), the first
step would be to reject such memory slots, report some error to the VMM.
I don't think it's worth attempting to do any cache maintenance to sync
the aliases.

Subsequently, this can be allowed with on FWB-capable hardware. Whether
we want to expose such capability to the VMM, I guess it's harmless but
I doubt the VMM would do anything with it since it doesn't know the
device mapping attributes anyway.

-- 
Catalin


From nunodasneves at linux.microsoft.com  Wed Mar 19 11:04:22 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Wed, 19 Mar 2025 11:04:22 -0700
Subject: [PATCH v5 10/10] Drivers: hv: Introduce mshv_root module to
 expose /dev/mshv to VMMs
In-Reply-To: <BN7PR02MB4148D51FFF965676AD155A3ED4D92@BN7PR02MB4148.namprd02.prod.outlook.com>
References: <1740611284-27506-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1740611284-27506-11-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157BE8AF5A1CDD39CF31124D4DF2@SN6PR02MB4157.namprd02.prod.outlook.com>
 <afd87eba-742f-4b67-9171-fd8486416b7b@linux.microsoft.com>
 <SN6PR02MB41574DE5535222985147134CD4D92@SN6PR02MB4157.namprd02.prod.outlook.com>
 <BN7PR02MB4148D51FFF965676AD155A3ED4D92@BN7PR02MB4148.namprd02.prod.outlook.com>
Message-ID: <9791bc6b-d8ad-47ee-8c54-7230d044f8d5@linux.microsoft.com>

On 3/19/2025 8:26 AM, Michael Kelley wrote:
> From: Michael Kelley <mhklinux at outlook.com> Sent: Tuesday, March 18, 2025 7:10 PM
>>
>> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Tuesday, March
>> 18, 2025 5:34 PM
>>>
>>> On 3/17/2025 4:51 PM, Michael Kelley wrote:
>>>> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Wednesday, February 26, 2025 3:08 PM
> 
> [snip]
> 
>>>>> +
>>>>> +	region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
>>>>> +	if (!region)
>>>>> +		return -EINVAL;
>>> <snip>
>>>> +	case MSHV_GPAP_ACCESS_TYPE_ACCESSED:
>>>>> +		hv_type_mask = 1;
>>>>> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
>>>>> +			hv_flags.clear_accessed = 1;
>>>>> +			/* not accessed implies not dirty */
>>>>> +			hv_flags.clear_dirty = 1;
>>>>> +		} else { // MSHV_GPAP_ACCESS_OP_SET
>>>>
>>>> Avoid C++ style comments.
>>>>
>>> Ack
>>>
>>>>> +			hv_flags.set_accessed = 1;
>>>>> +		}
>>>>> +		break;
>>>>> +	case MSHV_GPAP_ACCESS_TYPE_DIRTY:
>>>>> +		hv_type_mask = 2;
>>>>> +		if (args.access_op == MSHV_GPAP_ACCESS_OP_CLEAR) {
>>>>> +			hv_flags.clear_dirty = 1;
>>>>> +		} else { // MSHV_GPAP_ACCESS_OP_SET
>>>>
>>>> Same here.
>>>>
>>> Ack
>>>
>>>>> +			hv_flags.set_dirty = 1;
>>>>> +			/* dirty implies accessed */
>>>>> +			hv_flags.set_accessed = 1;
>>>>> +		}
>>>>> +		break;
>>>>> +	}
>>>>> +
>>>>> +	states = vzalloc(states_buf_sz);
>>>>> +	if (!states)
>>>>> +		return -ENOMEM;
>>>>> +
>>>>> +	ret = hv_call_get_gpa_access_states(partition->pt_id, args.page_count,
>>>>> +					    args.gpap_base, hv_flags, &written,
>>>>> +					    states);
>>>>> +	if (ret)
>>>>> +		goto free_return;
>>>>> +
>>>>> +	/*
>>>>> +	 * Overwrite states buffer with bitmap - the bits in hv_type_mask
>>>>> +	 * correspond to bitfields in hv_gpa_page_access_state
>>>>> +	 */
>>>>> +	for (i = 0; i < written; ++i)
>>>>> +		assign_bit(i, (ulong *)states,
>>>>
>>>> Why the cast to ulong *?  I think this argument to assign_bit() is void *, in
>>>> which case the cast wouldn't be needed.
>>>>
>>> It looks like assign_bit() and friends resolve to a set of functions which do
>>> take an unsigned long pointer, e.g.:
>>>
>>> __set_bit() -> generic___set_bit(unsigned long nr, volatile unsigned long *addr)
>>> set_bit() -> arch_set_bit(unsigned int nr, volatile unsigned long *p)
>>> etc...
>>>
>>> So a cast is necessary.
>>
>> Indeed, you are right.  Seems like set_bit() and friends should take a void *.
>> But that's a different kettle of fish.
>>
>>>
>>>> Also, assign_bit() does atomic bit operations. Doing such in a loop like
>>>> here will really hammer the hardware memory bus with atomic
>>>> read-modify-write cycles. Use __assign_bit() instead, which does
>>>> non-atomic operations. You don't need atomic here as no other
>>>> threads are modifying the bit array.
>>>>
>>> I didn't realize it was atomic. I'll change it to __assign_bit().
>>>
>>>>> +			   states[i].as_uint8 & hv_type_mask);
>>>>
>>>> OK, so the starting contents of "states" is an array of bytes. The ending
>>>> contents is an array of bits. This works because every bit in the ending
>>>> bit array is set to either 0 or 1. Overlap occurs on the first iteration
>>>> where the code reads the 0th byte, and writes the 0th bit, which is part of
>>>> the 0th byte. The second iteration reads the 1st byte, and writes the 1st bit,
>>>> which doesn't overlap, and there's no overlap from then on.
>>>>
>>>> Suppose "written" is not a multiple of 8. The last byte of "states" as an
>>>> array of bits will have some bits that have not been set to either 0 or 1 and
>>>> might be leftover garbage from when "states" was an array of bytes. That
>>>> garbage will get copied to user space. Is that OK? Even if user space knows
>>>> enough to ignore those bits, it seems a little dubious to be copying even
>>>> a few bits of garbage to user space.
>>>>
>>>> Some comments might help here.
>>>>
>>> This is a good point. The expectation is indeed that userspace knows which
>>> bits are valid from the returned "written" value, but I agree it's a bit
>>> odd to have some garbage bits in the last byte. How does this look (to be
>>> inserted here directly after the loop):
>>>
>>> +       /* zero the unused bits in the last byte of the returned bitmap */
>>> +       if (written > 0) {
>>> +               u8 last_bits_mask;
>>> +               int last_byte_idx;
>>> +               int bits_rem = written % 8;
>>> +
>>> +               /* bits_rem == 0 when all bits in the last byte were assigned */
>>> +               if (bits_rem > 0) {
>>> +                       /* written > 0 ensures last_byte_idx >= 0 */
>>> +                       last_byte_idx = ((written + 7) / 8) - 1;
>>> +                       /* bits_rem > 0 ensures this masks 1 to 7 bits */
>>> +                       last_bits_mask = (1 << bits_rem) - 1;
>>> +                       states[last_byte_idx].as_uint8 &= last_bits_mask;
>>> +               }
>>> +       }
>>
>> A simpler approach is to "continue" the previous loop.  And if "written"
>> is zero, this additional loop won't do anything either:
>>
>> 	for (i = written; i < ALIGN(written, 8); ++i)
>> 		__clear_bit(i, (ulong *)states);
>>
> > One further thought here: Could "written" be less than
> args.page_count at this point? That would require
> hv_call_get_gpa_access_states() to not fail, but still return
> a value for written that is less than args.page_count. If that
> could happen, then the above loop should be:
> 
> 	for (i = written; i < bitmap_buf_sz * 8; ++i)
> 		__clear_bit(i, (ulong *)states);
> 
> so that all the uninitialized bits and bytes that will be written
> back to user space are cleared.
> Hmmm...now I'm not so sure where the need for "written" came from in
the first place - in practice "written" will always be equal to
args.page_count except on error, but in that case there's a goto
free_return anyway, so the number is never copied to userspace. And
I checked the userspace code - it doesn't expect a partial result
either.

So it seems to be redundant, but I don't really want to remove it just
now.

Your suggestion with bitmap_buf_sz * 8 should be fine, and will make it
straightforward to remove "written" in a future cleanup if that ends up
looking like a good idea.

>>>
>>> The remaining bytes could be memset() to zero but I think it's fine to leave
>>> them.
>>
>> I agree.  The remaining bytes aren't written back to user space anyway
>> since the copy_to_user() uses bitmap_buf_sz.
> 
> Maybe I misunderstood what you meant by "remaining bytes".  I think
> all bits and bytes that are written back to user space should have
> valid data or zeros so that no garbage is written back.
> 
Agreed.

Nuno

> Michael
> 
>>
>>>
>>>>> +
>>>>> +	args.page_count = written;
>>>>> +
>>>>> +	if (copy_to_user(user_args, &args, sizeof(args))) {
>>>>> +		ret = -EFAULT;
>>>>> +		goto free_return;
>>>>> +	}
>>>>> +	if (copy_to_user((void __user *)args.bitmap_ptr, states, bitmap_buf_sz))
>>>>> +		ret = -EFAULT;
>>>>> +
>>>>> +free_return:
>>>>> +	vfree(states);
>>>>> +	return ret;
>>>>> +}



From catalin.marinas at arm.com  Wed Mar 19 11:11:02 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 19 Mar 2025 18:11:02 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250319170429.GK9311@nvidia.com>
References: <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
 <20250318230909.GD9311@nvidia.com>
 <Z9pryQwy2iwa2bpJ@linux.dev>
 <20250319170429.GK9311@nvidia.com>
Message-ID: <Z9sItt8BIgvbBY8M@arm.com>

On Wed, Mar 19, 2025 at 02:04:29PM -0300, Jason Gunthorpe wrote:
> On Wed, Mar 19, 2025 at 12:01:29AM -0700, Oliver Upton wrote:
> > You have a very good point that KVM is broken for cacheable PFNMAP'd
> > crap since we demote to something non-cacheable, and maybe that
> > deserves fixing first. Hopefully nobody notices that we've taken away
> > the toys...
> 
> Fixing it is either faulting all access attempts or mapping it
> cachable to the S2 (as this series is trying to do)..

As I replied earlier, it might be worth doing both - fault on !FWB
hardware (or rather reject the memslot creation), cacheable S2
otherwise.

> > I'm less worried about recovery and more focused on userspace being
> > able to understand what happened. Otherwise we may get folks complaining
> > about the ioctl failing "randomly" on certain machines.
> 
> Even today something like qemu doesn't know that VFIO has created a
> cachable mmap, so it would need a bunch more work to feed everything
> through as proposed here.

I came to the same conclusion, qemu wouldn't be able to pass any
KVM_MEMORY_* flag to request cacheable since it doesn't know what
attributes it got from VFIO. You need a side-channel communication
between the host VFIO driver and KVM. With Ankit's proposal, that's the
Stage 1 MMU attributes for the qemu mapping.

-- 
Catalin


From patchwork-bot+netdevbpf at kernel.org  Wed Mar 19 11:20:30 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Wed, 19 Mar 2025 18:20:30 +0000
Subject: [PATCH net] net: stmmac: dwc-qos-eth: use devm_kzalloc() for AXI data
In-Reply-To: <E1tsRyv-0064nU-O9@rmk-PC.armlinux.org.uk>
References: <E1tsRyv-0064nU-O9@rmk-PC.armlinux.org.uk>
Message-ID: <174240843003.1143902.13702964341385385111.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Wed, 12 Mar 2025 19:43:09 +0000 you wrote:
> Everywhere else in the driver uses devm_kzalloc() when allocating the
> AXI data, so there is no kfree() of this structure. However,
> dwc-qos-eth uses kzalloc(), which leads to this memory being leaked.
> Switch to use devm_kzalloc().
> 
> Fixes: d8256121a91a ("stmmac: adding new glue driver dwmac-dwc-qos-eth")
> Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
> 
> [...]

Here is the summary with links:
  - [net] net: stmmac: dwc-qos-eth: use devm_kzalloc() for AXI data
    https://git.kernel.org/netdev/net/c/c9cb135bc604

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From wnliu at google.com  Wed Mar 19 11:37:56 2025
From: wnliu at google.com (Weinan Liu)
Date: Wed, 19 Mar 2025 18:37:56 +0000
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <ifqn5txrr25ffky7lxtnjtb4b2gekq5jy4fmbiwtwfvofb4wgw@py7v7xpzaqxa>
References: <ifqn5txrr25ffky7lxtnjtb4b2gekq5jy4fmbiwtwfvofb4wgw@py7v7xpzaqxa>
Message-ID: <20250319183757.404779-1-wnliu@google.com>

On Tue, Mar 18, 2025 at 10:39?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
>
> On Tue, Mar 18, 2025 at 08:58:52PM -0700, Song Liu wrote:
> > On a closer look, I think we also need some logic in unwind_find_stack()
> > so that we can see when the unwinder hits the exception boundary. For
> > this reason, we may still need unwind_state.unreliable. I will look into
> > fixing this and send v2.
>
> Isn't that what FRAME_META_TYPE_PT_REGS is for?
>
> Maybe it can just tell kunwind_stack_walk() to set a bit in
> kunwind_state which tells kunwind_next_frame_record_meta() to quit the
> unwind early for the FRAME_META_TYPE_PT_REGS case. ?That also has the
> benefit of stopping the unwind as soon as the exception is encounterd.
>

After reviewing the code flow, it seems like we should treat all -EINVALID
cases or `FRAME_META_TYPE_PT_REGS` cases as unreliable unwinds.

Would a simplification like the one below work?
Or we can return a special value for success cases in kunwind_next_regs_pc() 

```
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 69d0567a0c38..0eb69fa6161a 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -296,7 +296,8 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 		if (!consume_state(state, cookie))
 			break;
 		ret = kunwind_next(state);
-		if (ret < 0)
+		if (ret < 0 || state->source == KUNWIND_SOURCE_REGS_PC)
+			state->common.unreliable = true;
 			break;
 	}
 }
```

--
Weinan


From maz at kernel.org  Wed Mar 19 11:38:38 2025
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 19 Mar 2025 18:38:38 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
	<86msdhmemw.wl-maz@kernel.org>
	<cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
Message-ID: <86ldt0n9w1.wl-maz@kernel.org>

On Wed, 19 Mar 2025 11:51:21 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/19 20:41, Marc Zyngier wrote:
> > On Wed, 19 Mar 2025 11:26:18 +0000,
> > Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >> 
> >> On 2025/03/19 20:07, Marc Zyngier wrote:
> >>> On Wed, 19 Mar 2025 10:26:57 +0000,
> >>>> 
> >>> But that'd be a new ABI, which again would require buy-in from
> >>> userspace.  Maybe there is scope for an all CPUs, cycle-counter only
> >>> PMUv3 exposed to the guest, but that cannot be set automatically, as
> >>> we would otherwise regress existing setups.
> >>> 
> >>> At this stage, and given that you need to change userspace, I'm not
> >>> sure what the best course of action is.
> >> 
> >> Having an explicit flag for the userspace is fine for QEMU, which I
> >> care. It can flip the flag if and only if threads are not pinned to
> >> one PMU and the machine is a new setup.
> >> 
> >> I also wonder what regression you think setting it automatically causes.
> > 
> > The current behaviour is that if you don't specify anything other than
> > creating a PMUv3 (without KVM_ARM_VCPU_PMU_V3_SET_PMU), you get *some*
> > PMU, and userspace is responsible for running the vcpu on CPUs that
> > will implement that PMU. When if does, all the counters, all the
> > events are valid. If it doesn't, nothing counts, but the
> > counters/events are still valid.
> > 
> > If you now add this flag automatically, the guest doesn't see the full
> > PMU anymore. Only the cycle counter. That's the regression.
> 
> What about setting the flag automatically when a user fails to pin
> vCPUs to CPUs that are covered by one PMU? There would be no change if
> a user correctly pins vCPUs as it is. Otherwise, they will see a
> correct feature set advertised to the guest and the cycle counter
> working.

How do you know that the affinity is "correct"? VCPU affinity can be
changed at any time. I, for one, do not want my VMs to change
behaviour because I let the vcpus bounce around as the scheduler sees
fit.

Honestly, this is not a can of worm I want to open. We already have a
pretty terrible userspace API for the PMU, let's not add to the
confusion. *If* we are going down the road of presenting a dumbed-down
PMU to the guest, it has to be an explicit buy-in from userspace.

	M.

-- 
Without deviation from the norm, progress is not possible.


From Suraj.Gupta2 at amd.com  Wed Mar 19 11:41:46 2025
From: Suraj.Gupta2 at amd.com (Gupta, Suraj)
Date: Wed, 19 Mar 2025 18:41:46 +0000
Subject: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X
 only configuration.
In-Reply-To: <b2a65ad1-d4ca-4c0d-b59e-911b07f96554@lunn.ch>
References: <Z9GWokRDzEYwJmBz@shell.armlinux.org.uk>
 <BL3PR12MB6571795DA783FD05189AD74BC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <34ed11e7-b287-45c6-8ff4-4a5506b79d17@lunn.ch>
 <BL3PR12MB6571540090EE54AC9743E17EC9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <fd686050-e794-4b2f-bfb8-3a0769abb506@lunn.ch>
 <BL3PR12MB6571959081FC8DDC5D509560C9D02@BL3PR12MB6571.namprd12.prod.outlook.com>
 <Z9HjOAnpNkmZcoeo@shell.armlinux.org.uk>
 <186bf47a-04af-4bfb-a6d3-118b844c9ba8@lunn.ch>
 <BL3PR12MB6571E707DC09A31A553CB1BCC9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
 <BL3PR12MB6571DF7CBA49AF626ABDA382C9D32@BL3PR12MB6571.namprd12.prod.outlook.com>
 <b2a65ad1-d4ca-4c0d-b59e-911b07f96554@lunn.ch>
Message-ID: <DS0PR12MB658350DFEAFE603095D7E17BC9D92@DS0PR12MB6583.namprd12.prod.outlook.com>

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Andrew Lunn <andrew at lunn.ch>
> Sent: Thursday, March 13, 2025 6:17 PM
> To: Gupta, Suraj <Suraj.Gupta2 at amd.com>
> Cc: Russell King (Oracle) <linux at armlinux.org.uk>; Pandey, Radhey Shyam
> <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org; conor+dt at kernel.org;
> Simek, Michal <michal.simek at amd.com>; netdev at vger.kernel.org;
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> <harini.katakam at amd.com>
> Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for 2500base-X only
> configuration.
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Thu, Mar 13, 2025 at 07:34:55AM +0000, Gupta, Suraj wrote:
> > [AMD Official Use Only - AMD Internal Distribution Only]
> >
> > > -----Original Message-----
> > > From: Gupta, Suraj
> > > Sent: Thursday, March 13, 2025 9:01 AM
> > > To: Andrew Lunn <andrew at lunn.ch>; Russell King (Oracle)
> > > <linux at armlinux.org.uk>
> > > Cc: Pandey, Radhey Shyam <radhey.shyam.pandey at amd.com>;
> > > andrew+netdev at lunn.ch; davem at davemloft.net; edumazet at google.com;
> > > kuba at kernel.org; pabeni at redhat.com; robh at kernel.org;
> > > krzk+dt at kernel.org;
> > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > git (AMD-Xilinx) <git at amd.com>; Katakam, Harini
> > > <harini.katakam at amd.com>
> > > Subject: RE: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > 2500base-X only configuration.
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Andrew Lunn <andrew at lunn.ch>
> > > > Sent: Thursday, March 13, 2025 3:41 AM
> > > > To: Russell King (Oracle) <linux at armlinux.org.uk>
> > > > Cc: Gupta, Suraj <Suraj.Gupta2 at amd.com>; Pandey, Radhey Shyam
> > > > <radhey.shyam.pandey at amd.com>; andrew+netdev at lunn.ch;
> > > > davem at davemloft.net; edumazet at google.com; kuba at kernel.org;
> > > > pabeni at redhat.com; robh at kernel.org; krzk+dt at kernel.org;
> > > > conor+dt at kernel.org; Simek, Michal <michal.simek at amd.com>;
> > > > netdev at vger.kernel.org; devicetree at vger.kernel.org;
> > > > linux-kernel at vger.kernel.org; linux-arm-
> > > > kernel at lists.infradead.org; git (AMD-Xilinx) <git at amd.com>;
> > > > Katakam, Harini <harini.katakam at amd.com>
> > > > Subject: Re: [PATCH net-next V2 2/2] net: axienet: Add support for
> > > > 2500base-X only configuration.
> > > >
> > > > Caution: This message originated from an External Source. Use
> > > > proper caution when opening attachments, clicking links, or responding.
> > > >
> > > >
> > > > > This is not an approach that works with the Linux kernel, sorry.
> > > > >
> > > > > What we have today is a driver that works for people's hardware
> > > > > - and we don't know what the capabilities of that hardware is.
> > > > >
> > > > > If there's hardware out there today which has XAE_ABILITY_2_5G
> > > > > set, but defaults to <=1G mode, this will work with the current driver.
> > > > > However, with your patch applied, it stops working because
> > > > > instead of the driver indicating MAC_10FD | MAC_100FD |
> > > > > MAC_1000FD, it only indicates MAC_2500FD. If this happens, it
> > > > > will regress users setups, and that is something we try not to do.
> > > > >
> > > > > Saying "someone else needs to add the code for their FPGA logic"
> > > > > misses the point - there may not be "someone else" to do that,
> > > > > which means the only option is to revert your change if it were merged.
> > > > > That in itself can cause its own user regressions because
> > > > > obviously stuff that works with this patch stops working.
> > > > >
> > > > > This is why we're being cautious, and given your responses, it's
> > > > > not making Andrew or myself feel that there's a reasonable
> > > > > approach being taken here.
> > > > >
> > > > > >From everything you have said, I am getting the feeling that
> > > > > >using
> > > > > XAE_ABILITY_2_5G to decide which of (1) or (2) is supported is
> > > > > just wrong. Given that we're talking about an implementation
> > > > > that has been synthesized at 2.5G and can't operate slower,
> > > > > maybe there's some way that could be created to specify that in DT?
> > > > >
> > > > > e.g. (and I'm sure the DT folk aren't going to like it)...
> > > > >
> > > > >       xlnx,axi-ethernet-X.YY.Z-2.5G
> > > > >
> > > > > (where X.YY.Z is the version) for implementations that can
> > > > > _only_ do 2.5G, and leave all other implementations only doing 1G and
> below.
> > > > >
> > > > > Or maybe some DT property. Or something else.
> > > >
> > > > Given that AMD has been talking about an FPGA, not silicon, i
> > > > actually think it would be best to change the IP to explicitly
> > > > enumerate how it has been synthesised. Make use of some register
> > > > bits which currently read as 0. Current IP would then remain as
> > > > 1000BaseX/SGMII, independent of how they have been synthesised.
> > > > Newer versions of the IP will then set the bits if they have been
> > > > synthesised as 2) or 3), and the driver can then enable that
> > > > capability, without breaking current generation systems. Plus
> > > > there needs to be big fat warning for anybody upgrading to the
> > > > latest version of the IP for bug fixes to ensure they
> > > correctly set the synthesis options because it now actually matters.
> > > >
> > > >          Andrew
> > >
> > > Synthesis options I mentioned in comment might sound confusing, let me clear it
> up.
> > > Actual synthesis options (as seen from configuration UI) IP provides are (1) and
> (2).
> > > When a user selects (2), IP comes with default 2.5G but also
> > > contains 1G capabilities which can be enabled and work with by
> > > adding switching FPGA logic (that makes it (3)).
> > >
> > > So, in short  if a user selects (1): It's <=1G only.
> > > If it selects (2): It's 2.5G only but can be made (3) by FPGA logic
> > > changes. So whatever existing systems for (3) would be working at default (2).
> > >
> > > This is the reason we didn't described (3) in V1 series as that is
> > > not provided by IP but can be synthesized after FPGA changes.
> > > Hope I'm able to answer your questions.
> > >
> >
> > I understand your concerns that current solution might break if any existing system
> uses (3).
> >
> > Russel's suggestion to use DT compatible we can try to send as RFC and check if
> that is accepted by DT maintainers.
> > Andrew's suggestion is complete IP solution and will involve IP changes to correct
> ability register behaviour based on synthesis time selection in a new IP version. But
> this will need internal discussions and IP rework and might take few months.
> >
> > Please let me know your thoughts on it.
>
> Given your comment:
>
> > It's 2.5G only but can be made (3) by FPGA logic changes
>
> It sounds like the design is not ideal at the moment, and you will be making changes
> anyway to clean this up. Being fixed in 2.5G mode is not nice, you need a PHY
> doing rate adaptation in order to support the slower speeds.
>
> You should also be thinking forwards. If you add support for fixed 2.5G now, can you
> cleanly integrate switching between 1000BaseX/SGMII and 2500BaseX in the future
> without breaking existing systems? You probably at least need a paper design of
> how this will work, so you can say you have thought through all the user cases: New
> IP old driver, Old IP new driver, etc...
>
>         Andrew

Hi Andrew, Russell,

Thank you for your guidance.

Based on our internal discussions, pushing for IP changes would be difficult and time-taking. As an alternative, we propose the following driver modifications to support the current 2.5G-only design while considering existing functionality and potential future switching logic:

1) The driver will advertise speeds based on the Temac ability register-both 1G and 2.5G for the current 2.5G-only design.

2) In axienet_pcs_config(), based on the return type of phylink_mii_c22_pcs_config() (as switching between 1G and 2.5G involves an interface change), if a speed change fails, the driver will print a warning:
"Check for potential missing switching logic in the design if 1G ? 2.5G switching is attempted."

Expected Effects:
1) Existing 1G Design
        New Driver:
        (a) Advertises 1G
        (b)If an attempt to change the configuration fails, a warning is printed regarding missing switching logic.

2) 2.5G-Only Design
        Old Driver: Fails, as it attempts to advertise only 1G.
        New Driver:
        (a) Advertises both 1G and 2.5G
        (b)If a configuration change attempt fails, a warning is printed regarding missing switching logic.

3) Custom Design with Switching Logic
        (a) Users will need to implement speed/interface change logic.
        (b) If a configuration change attempt fails, a warning is printed regarding potential missing switching logic.

I understand this approach might generate false warnings if phylink_mii_c22_pcs_config() fails due to other reasons. However, we can explore maintaining current interface / speed in axienet_local structure and track 1G <-> 2.5G switching.

Please let me know your thoughts.

Regards,
Suraj


From yosry.ahmed at linux.dev  Wed Mar 19 11:47:31 2025
From: yosry.ahmed at linux.dev (Yosry Ahmed)
Date: Wed, 19 Mar 2025 18:47:31 +0000
Subject: [PATCH RFC v2 04/29] mm: asi: Add infrastructure for boot-time
 enablement
In-Reply-To: <20250319172935.GMZ9r-_zzXhyhHBLfj@fat_crate.local>
References: <20250110-asi-rfc-v2-v2-0-8419288bc805@google.com>
 <20250110-asi-rfc-v2-v2-4-8419288bc805@google.com>
 <20250319172935.GMZ9r-_zzXhyhHBLfj@fat_crate.local>
Message-ID: <Z9sRQ0cK0rupEiT-@google.com>

On Wed, Mar 19, 2025 at 06:29:35PM +0100, Borislav Petkov wrote:
> On Fri, Jan 10, 2025 at 06:40:30PM +0000, Brendan Jackman wrote:
> > Add a boot time parameter to control the newly added X86_FEATURE_ASI.
> > "asi=on" or "asi=off" can be used in the kernel command line to enable
> > or disable ASI at boot time. If not specified, ASI enablement depends
> > on CONFIG_ADDRESS_SPACE_ISOLATION_DEFAULT_ON, which is off by default.
> 
> I don't know yet why we need this default-on thing...

It's a convenience to avoid needing to set asi=on if you want ASI to be
on by default. It's similar to HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON
or ZSWAP_DEFAULT_ON.

[..]
> > @@ -175,7 +184,11 @@ static __always_inline bool asi_is_restricted(void)
> >  	return (bool)asi_get_current();
> >  }
> >  
> > -/* If we exit/have exited, can we stay that way until the next asi_enter? */
> > +/*
> > + * If we exit/have exited, can we stay that way until the next asi_enter?
> 
> What is that supposed to mean here?

asi_is_relaxed() checks if the thread is outside an ASI critical
section.

I say "the thread" because it will also return true if we are executing
an interrupt that arrived during the critical section, even though the
interrupt handler is not technically part of the critical section.

Now the reason it says "if we exit we stay that way" is probably
referring to the fact that an asi_exit() when interrupting a critical
section will be undone in the interrupt epilogue by re-entering ASI.

I agree the wording here is confusing. We should probably describe this
more explicitly and probably rename the function after the API
discussions you had in the previous patch.

> 
> > + *
> > + * When ASI is disabled, this returns true.
> > + */
> >  static __always_inline bool asi_is_relaxed(void)
> >  {
> >  	return !asi_get_target(current);
[..]
> > @@ -66,10 +73,36 @@ const char *asi_class_name(enum asi_class_id class_id)
> >  	return asi_class_names[class_id];
> >  }
> >  
> > +void __init asi_check_boottime_disable(void)
> > +{
> > +	bool enabled = IS_ENABLED(CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION_DEFAULT_ON);
> > +	char arg[4];
> > +	int ret;
> > +
> > +	ret = cmdline_find_option(boot_command_line, "asi", arg, sizeof(arg));
> > +	if (ret == 3 && !strncmp(arg, "off", 3)) {
> > +		enabled = false;
> > +		pr_info("ASI disabled through kernel command line.\n");
> > +	} else if (ret == 2 && !strncmp(arg, "on", 2)) {
> > +		enabled = true;
> > +		pr_info("Ignoring asi=on param while ASI implementation is incomplete.\n");
> > +	} else {
> > +		pr_info("ASI %s by default.\n",
> > +			enabled ? "enabled" : "disabled");
> > +	}
> > +
> > +	if (enabled)
> > +		pr_info("ASI enablement ignored due to incomplete implementation.\n");
> 
> Incomplete how?

This is referring to the fact that ASI is still not fully/correctly
functional, but it will be after the following patches.

I think it will be clearer if we just add the feature flag here so that
we have something to check for in the following patches, but add the
infrastructure for boot-time enablement at the end of the series when
the impelemntation is complete.

Basically start by a feature flag that has no way of being enabled, use
it in the implmentation, then add means of enabling it.

> 
> > +}
> > +
> >  static void __asi_destroy(struct asi *asi)
> >  {
> > -	lockdep_assert_held(&asi->mm->asi_init_lock);
> > +	WARN_ON_ONCE(asi->ref_count <= 0);
> > +	if (--(asi->ref_count) > 0)
> 
> Switch that to
> 
> include/linux/kref.h
> 
> It gives you a sanity-checking functionality too so you don't need the WARN...

I think we hve internal changes that completely get rid of this
ref_count and simplifies the lifetime handling that we can squash here.
We basically keep ASI objects around until the process is torn down,
which makes this simpler and avoids the need for complex synchronization
when we try to context switch or run userspace without exiting ASI
(spoiler alert :) ).

> 
> > +		return;
> >  
> > +	free_pages((ulong)asi->pgd, PGD_ALLOCATION_ORDER);
> > +	memset(asi, 0, sizeof(struct asi));
> 
> And then you can do:
> 
> 	if (kref_put())
> 		free_pages...
> 
> and so on.
> 
> Thx.
> 
> -- 
> Regards/Gruss,
>     Boris.
> 
> https://people.kernel.org/tglx/notes-about-netiquette
> 


From oliver.upton at linux.dev  Wed Mar 19 11:51:28 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Wed, 19 Mar 2025 11:51:28 -0700
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86ldt0n9w1.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
 <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
 <86ldt0n9w1.wl-maz@kernel.org>
Message-ID: <Z9sSMJAlf7cQ5viu@linux.dev>

On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> > What about setting the flag automatically when a user fails to pin
> > vCPUs to CPUs that are covered by one PMU? There would be no change if
> > a user correctly pins vCPUs as it is. Otherwise, they will see a
> > correct feature set advertised to the guest and the cycle counter
> > working.
> 
> How do you know that the affinity is "correct"? VCPU affinity can be
> changed at any time. I, for one, do not want my VMs to change
> behaviour because I let the vcpus bounce around as the scheduler sees
> fit.
> 
> Honestly, this is not a can of worm I want to open. We already have a
> pretty terrible userspace API for the PMU, let's not add to the
> confusion. *If* we are going down the road of presenting a dumbed-down
> PMU to the guest, it has to be an explicit buy-in from userspace.

I also have a very strong distaste for the crappy UAPI we have around a
'default' PMU. At the same time I do recognize this hurts practical
usecases since some VMMs can't be bothered to configure the vPMU / vCPU
pinning correctly.

I'm at least willing to plug my nose and do the following:

 1) When the VMM does not specify a vPMU type:

   - We continue to present the 'default' PMU (including event counters)
     to the VM

   - KVM ensures that the fixed CPU cycle counter works on any PMUv3
     implementation in the system, even if it is different from the
     default

   - Otherwise, event counters will only count on the default
     implementation and will not count on different PMUs

 2) Implement your suggestion of a UAPI where the VMM can select a PMU
    that only has the CPU cycle counter and works on any PMUv3
    implementation.

Either way KVM will need to have some special case handling of the fixed
CPU cycle counter. That'd allow users to actually run Windows *now* and
provide a clear mechanism for userspace to present a less-broken vPMU if
it cares.

Thanks,
Oliver


From lkp at intel.com  Wed Mar 19 12:02:22 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 20 Mar 2025 03:02:22 +0800
Subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
In-Reply-To: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
Message-ID: <202503200205.amGhOXua-lkp@intel.com>

Hi jiebing,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab]

url:    https://github.com/intel-lab-lkp/linux/commits/jiebing-chen-via-B4-Relay/dt-bindings-clock-meson-Add-audio-power-domain-for-s4-soc/20250319-151110
base:   6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
patch link:    https://lore.kernel.org/r/20250319-audio_drvier-v4-4-686867fad719%40amlogic.com
patch subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
config: i386-buildonly-randconfig-005-20250320 (https://download.01.org/0day-ci/archive/20250320/202503200205.amGhOXua-lkp at intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250320/202503200205.amGhOXua-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503200205.amGhOXua-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> sound/soc/meson/g12a-toacodec.c:135:38: warning: 's4_toacodec_clk_enable' defined but not used [-Wunused-const-variable=]
     135 | static const struct snd_kcontrol_new s4_toacodec_clk_enable =
         |                                      ^~~~~~~~~~~~~~~~~~~~~~


vim +/s4_toacodec_clk_enable +135 sound/soc/meson/g12a-toacodec.c

   112	
   113	static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0,
   114				    CTRL0_DAT_SEL_LSB,
   115				    g12a_toacodec_mux_texts);
   116	
   117	static SOC_ENUM_SINGLE_DECL(sm1_toacodec_mux_enum, TOACODEC_CTRL0,
   118				    CTRL0_DAT_SEL_SM1_LSB,
   119				    g12a_toacodec_mux_texts);
   120	
   121	static const struct snd_kcontrol_new g12a_toacodec_mux =
   122		SOC_DAPM_ENUM_EXT("Source", g12a_toacodec_mux_enum,
   123				  snd_soc_dapm_get_enum_double,
   124				  g12a_toacodec_mux_put_enum);
   125	
   126	static const struct snd_kcontrol_new sm1_toacodec_mux =
   127		SOC_DAPM_ENUM_EXT("Source", sm1_toacodec_mux_enum,
   128				  snd_soc_dapm_get_enum_double,
   129				  g12a_toacodec_mux_put_enum);
   130	
   131	static const struct snd_kcontrol_new g12a_toacodec_out_enable =
   132		SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
   133					    CTRL0_ENABLE_SHIFT, 1, 0);
   134	
 > 135	static const struct snd_kcontrol_new s4_toacodec_clk_enable =
   136		SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
   137				CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
   138	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From funderscore at postmarketos.org  Wed Mar 19 12:05:50 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Wed, 19 Mar 2025 19:05:50 +0000
Subject: [PATCH v5 0/2] Add support for Xiaomi Mi TV Stick
In-Reply-To: <20250319190150.31529-2-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
Message-ID: <D8KH7CDPMWDS.396O6X214BX59@postmarketos.org>

On Wed Mar 19, 2025 at 7:01 PM UTC, Ferass El Hafidi wrote:
<snip>
>
> More information is available on the postmarketOS wiki page [6].
>

Which would be https://wiki.postmarketos.org/wiki/Xiaomi_Mi_TV_Stick_(xiaomi-aquaman)

Sorry, forgot to put the link.

Regards.

> [1]: https://lore.kernel.org/all/20250203174346.13737-1-funderscore at postmarketos.org/
> [2]: https://lore.kernel.org/all/20250203091453.15751-1-funderscore at postmarketos.org/
> [3]: https://lore.kernel.org/all/20250201193044.28856-1-funderscore at postmarketos.org/
> [4]: https://lore.kernel.org/all/20250131200319.19996-1-funderscore at postmarketos.org/
> [5]: https://lore.kernel.org/linux-amlogic/20241227212514.1376682-1-martin.blumenstingl at googlemail.com/
>
>
> Ferass El Hafidi (2):
>   dt-bindings: arm: amlogic: add S805Y and Mi TV Stick
>   arm64: dts: amlogic: add support for xiaomi-aquaman/Mi TV Stick
>
>  .../devicetree/bindings/arm/amlogic.yaml      |   7 +
>  arch/arm64/boot/dts/amlogic/Makefile          |   1 +
>  .../meson-gxl-s805y-xiaomi-aquaman.dts        | 292 ++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxl-s805y.dtsi     |  10 +
>  4 files changed, 310 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi



From funderscore at postmarketos.org  Wed Mar 19 12:08:17 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Wed, 19 Mar 2025 19:08:17 +0000
Subject: [PATCH v4 0/2] Add support for Xiaomi Mi TV Stick
In-Reply-To: <20250203174346.13737-1-funderscore@postmarketos.org>
References: <20250203174346.13737-1-funderscore@postmarketos.org>
Message-ID: <D8KH97UKHPJW.300OTP897K3KO@postmarketos.org>

Hello,

Superseded by v5:
https://lore.kernel.org/all/20250319190150.31529-2-funderscore at postmarketos.org/

Thanks.


From funderscore at postmarketos.org  Wed Mar 19 12:01:49 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Wed, 19 Mar 2025 19:01:49 +0000
Subject: [PATCH v5 1/2] dt-bindings: arm: amlogic: add S805Y and Mi TV Stick
In-Reply-To: <20250319190150.31529-2-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
Message-ID: <20250319190150.31529-3-funderscore@postmarketos.org>

Add support for the Amlogic S805Y SoC and the Xiaomi Mi TV Stick (aka.
xiaomi-aquaman).  The S805Y is very similar to the S805X, with just a
few minor differences.

Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 0647851ae..3403362e0 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -73,6 +73,13 @@ properties:
           - const: amlogic,s805x
           - const: amlogic,meson-gxl
 
+      - description: Boards with the Amlogic Meson GXL S805Y SoC
+        items:
+          - enum:
+              - xiaomi,aquaman
+          - const: amlogic,s805y
+          - const: amlogic,meson-gxl
+
       - description: Boards with the Amlogic Meson GXL S905W SoC
         items:
           - enum:
-- 
2.47.1



From funderscore at postmarketos.org  Wed Mar 19 12:01:50 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Wed, 19 Mar 2025 19:01:50 +0000
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for xiaomi-aquaman/Mi TV Stick
In-Reply-To: <20250319190150.31529-2-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
Message-ID: <20250319190150.31529-4-funderscore@postmarketos.org>

Xiaomi Mi TV Stick is a small Amlogic-based Android TV stick released in
2020.  It is known as `xiaomi-aquaman` internally.  Specifications:
 * Amlogic S805Y SoC
 * Android TV 9, upgradable to Android TV 10
 * 8 GB eMMC
 * 1 GB of RAM
 * Wi-Fi + Bluetooth

The devicetree is based on p241's DT, with some changes to better match
the Mi TV Stick:
 * there is no Ethernet port, no IR, no CVBS connector on the stick
 * a white LED is present
 * adjust memory to have 1 GB of RAM available

Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
---
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../meson-gxl-s805y-xiaomi-aquaman.dts        | 292 ++++++++++++++++++
 .../boot/dts/amlogic/meson-gxl-s805y.dtsi     |  10 +
 3 files changed, 303 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 2fbda8419..0921707f1 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-hub.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-libretech-ac.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-p241.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805y-xiaomi-aquaman.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-libretech-pc.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-kii-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
new file mode 100644
index 000000000..42c692017
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Ferass El Hafidi <funderscore at postmarketos.org>
+ * Heavily based on meson-gxl-s805x-p241.dtb:
+ *  - Copyright (c) 2018 BayLibre, SAS.
+ *    Author: Neil Armstrong <narmstrong at baylibre.com>
+ *    Author: Jerome Brunet <jbrunet at baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/meson-aiu.h>
+
+#include "meson-gxl-s805y.dtsi"
+
+/ {
+	compatible = "xiaomi,aquaman", "amlogic,s805y", "amlogic,meson-gxl";
+	model = "Xiaomi Mi TV Stick (aquaman)";
+
+	aliases {
+		serial0 = &uart_AO;
+		serial1 = &uart_A;
+	};
+
+	au2: analog-amplifier {
+		compatible = "simple-audio-amplifier";
+		sound-name-prefix = "AU2";
+		VCC-supply = <&vcc_5v>;
+		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_tx_tmds_out>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-white {
+			color = <LED_COLOR_ID_WHITE>;
+			function = LED_FUNCTION_POWER;
+			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+			panic-indicator;
+		};
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	vddio_boot: regulator-vddio-boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vddio_ao18: regulator-vddio-ao18 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_AO18";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vcc_3v3: regulator-vcc-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_5v: regulator-vcc-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
+
+	sound {
+		compatible = "amlogic,gx-sound-card";
+		model = "XIAOMI-AQUAMAN";
+		audio-aux-devs = <&au2>;
+		audio-widgets = "Line", "Lineout";
+		audio-routing = "AU2 INL", "ACODEC LOLN",
+				"AU2 INR", "ACODEC LORN",
+				"Lineout", "AU2 OUTL",
+				"Lineout", "AU2 OUTR";
+		clocks = <&clkc CLKID_MPLL0>,
+			 <&clkc CLKID_MPLL1>,
+			 <&clkc CLKID_MPLL2>;
+
+		assigned-clocks = <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>,
+				  <&clkc CLKID_MPLL2>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+
+		dai-link-0 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+			dai-format = "i2s";
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+			};
+
+			codec-1 {
+				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
+			};
+		};
+
+		dai-link-2 {
+			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+
+		dai-link-3 {
+			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&acodec>;
+			};
+		};
+	};
+};
+
+&acodec {
+	AVDD-supply = <&vddio_ao18>;
+	status = "okay";
+};
+
+&aiu {
+	status = "okay";
+};
+
+&cec_AO {
+	status = "okay";
+	pinctrl-0 = <&ao_cec_pins>;
+	pinctrl-names = "default";
+	hdmi-phandle = <&hdmi_tx>;
+};
+
+&hdmi_tx {
+	status = "okay";
+	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+	pinctrl-names = "default";
+	hdmi-supply = <&vcc_5v>;
+};
+
+&hdmi_tx_tmds_port {
+	hdmi_tx_tmds_out: endpoint {
+		remote-endpoint = <&hdmi_connector_in>;
+	};
+};
+
+&saradc {
+	status = "okay";
+	vref-supply = <&vddio_ao18>;
+};
+
+/* Wireless SDIO Module (Amlogic W155S1 / Realtek RTL8821CS) */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-1 = <&sdio_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <50000000>;
+
+	non-removable;
+	disable-wp;
+
+	/* WiFi firmware requires power to be kept while in suspend */
+	keep-power-in-suspend;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+
+	sdio: wifi at 1 {
+		reg = <1>;
+	}
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+	pinctrl-1 = <&emmc_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+};
+
+/*
+ * This is connected to the Bluetooth module
+ * Note: There's no driver for the Bluetooth module of some variants yet.
+ */
+&uart_A {
+	status = "okay";
+	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+	pinctrl-names = "default";
+	uart-has-rtscts;
+};
+
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&usb {
+	status = "okay";
+	dr_mode = "otg";
+	vbus-supply = <&vcc_5v>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
new file mode 100644
index 000000000..49b29b71f
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Ferass El Hafidi <funderscore at postmarketos.org>
+ */
+
+#include "meson-gxl-s805x.dtsi"
+
+/ {
+	compatible = "amlogic,s805y", "amlogic,meson-gxl";
+};
-- 
2.47.1



From funderscore at postmarketos.org  Wed Mar 19 12:01:48 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Wed, 19 Mar 2025 19:01:48 +0000
Subject: [PATCH v5 0/2] Add support for Xiaomi Mi TV Stick
Message-ID: <20250319190150.31529-2-funderscore@postmarketos.org>

This patch series aims to add initial support for the Xiaomi Mi TV
Stick.

Xiaomi Mi TV Stick is a small Amlogic-based Android TV stick released in 
2020, and known as `xiaomi-aquaman` internally (in the downstream kernel,
u-boot, ...)
Its specifications are as follows:
 * Amlogic S805Y SoC (believed to be mostly identical to S805X)
 * 8 GB eMMC
 * 1 GB of RAM
 * Wi-Fi + Bluetooth
 * Android TV 9, upgradable to Android TV 10
 * Google-certified

There are multiple variants:
 * 1. Green PCB, manufactured in 2020, known UART pinout (helpfully 
   labeled on the board)
 * 2. Blue PCB, not much documentation about it, presumably manufactured
   between 2021 and 2023
 * 3. Green PCB, manufactured in 2023/2024, known UART pinout, some layout
   changes compared to the 2020 variant

Among these variants, there are many boards using multiple different
Wi-Fi chips.  Supporting all of them is out of scope for this patch
series.  However, there has been some work identifying Wi-Fi/Bluetooth 
since v4.  Some variants use a Realtek module while others use an
Amlogic module.

As of the time of writing this has only been tested on the 3rd variant.
It is believed that software-wise all three work mostly the same (if we 
don't count Wi-Fi/BT), but testing on the other variants would still be
appreciated.  Sadly, booting Mainline linux is slightly more
challenging on some versions of the original firmware.

The devicetree is based on the Amlogic P241 DTS.

Changes since v4 [1]:
 * add Acked-by from krzk
 * Wi-Fi on sd_emmc_b

Changes since v3 [2]:
 * typo fix (`vbus-supply` in `&usb`)

Changes since v2 [3]:
 * fix SoB/From mismatch

Changes since v1 [4]:
 * remove useless nodes: cvbs-connector, ethmac, internal_phy, ir
 * add `amlogic,s805y` DT binding section
 * add S805Y dtsi: meson-gxl-s805y.dtsi
 * adjust DT `model` to "Xiaomi Mi TV Stick (Aquaman)"
 * explain the changes being done a bit more in the commit message for
   the DT patch
 * drop `clocks` and `clock-names` from pwm_ef (background: [5])
 * change sound `model` to "XIAOMI-AQUAMAN"

More information is available on the postmarketOS wiki page [6].

[1]: https://lore.kernel.org/all/20250203174346.13737-1-funderscore at postmarketos.org/
[2]: https://lore.kernel.org/all/20250203091453.15751-1-funderscore at postmarketos.org/
[3]: https://lore.kernel.org/all/20250201193044.28856-1-funderscore at postmarketos.org/
[4]: https://lore.kernel.org/all/20250131200319.19996-1-funderscore at postmarketos.org/
[5]: https://lore.kernel.org/linux-amlogic/20241227212514.1376682-1-martin.blumenstingl at googlemail.com/


Ferass El Hafidi (2):
  dt-bindings: arm: amlogic: add S805Y and Mi TV Stick
  arm64: dts: amlogic: add support for xiaomi-aquaman/Mi TV Stick

 .../devicetree/bindings/arm/amlogic.yaml      |   7 +
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../meson-gxl-s805y-xiaomi-aquaman.dts        | 292 ++++++++++++++++++
 .../boot/dts/amlogic/meson-gxl-s805y.dtsi     |  10 +
 4 files changed, 310 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi

-- 
2.47.1



From quic_wcheng at quicinc.com  Wed Mar 19 12:03:00 2025
From: quic_wcheng at quicinc.com (Wesley Cheng)
Date: Wed, 19 Mar 2025 12:03:00 -0700
Subject: [PATCH v2 6/9] phy: qcom: Add M31 based eUSB2 PHY driver
In-Reply-To: <69fa7f33-e957-4dac-93dc-6fd40167873c@oss.qualcomm.com>
References: <20250304-sm8750_usb_master-v2-0-a698a2e68e06@quicinc.com>
 <20250304-sm8750_usb_master-v2-6-a698a2e68e06@quicinc.com>
 <69fa7f33-e957-4dac-93dc-6fd40167873c@oss.qualcomm.com>
Message-ID: <1956a94e-b231-4458-a1c1-6d9f158da669@quicinc.com>

Hi Konrad,

On 3/11/2025 4:19 AM, Konrad Dybcio wrote:
> On 3/4/25 10:56 PM, Melody Olvera wrote:
>> From: Wesley Cheng <quic_wcheng at quicinc.com>
>>
>> SM8750 utilizes an eUSB2 PHY from M31.  Add the initialization
>> sequences to bring it out of reset and into an operational state.  This
>> differs to the M31 USB driver, in that the M31 eUSB2 driver will
>> require a connection to an eUSB2 repeater.  This PHY driver will handle
>> the initialization of the associated eUSB2 repeater when required.
>>
>> Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
>> Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
>> ---
> 
> [...]
> 
>> +static int msm_m31_eusb2_write_readback(void __iomem *base, u32 offset,
>> +					const u32 mask, u32 val)
>> +{
>> +	u32 write_val;
>> +	u32 tmp;
>> +
>> +	tmp = readl_relaxed(base + offset);
>> +	tmp &= ~mask;
>> +	write_val = tmp | val;
>> +
>> +	writel_relaxed(write_val, base + offset);
>> +
>> +	tmp = readl_relaxed(base + offset);
>> +	tmp &= mask;
>> +
>> +	if (tmp != val) {
>> +		pr_err("write: %x to offset: %x FAILED\n", val, offset);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
> 
> Is there a reason we need to read back every write?
> 
> Does this have to do with some funny write buffering?
> 

Probably because its just a form of write synchronization, since we're
using the relaxed variants.  If desired I can switch to just using writel
and remove the readback.

Thanks
Wesley Cheng



From song at kernel.org  Wed Mar 19 12:09:17 2025
From: song at kernel.org (Song Liu)
Date: Wed, 19 Mar 2025 12:09:17 -0700
Subject: [PATCH 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250319183757.404779-1-wnliu@google.com>
References: <ifqn5txrr25ffky7lxtnjtb4b2gekq5jy4fmbiwtwfvofb4wgw@py7v7xpzaqxa> <20250319183757.404779-1-wnliu@google.com>
Message-ID: <CAPhsuW7Zz9EaW3+gtp2Ut-8DVB4F=Dacr2btJ8gL0OA4T6bQzA@mail.gmail.com>

On Wed, Mar 19, 2025 at 11:38?AM Weinan Liu <wnliu at google.com> wrote:
>
> On Tue, Mar 18, 2025 at 10:39?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
> >
> > On Tue, Mar 18, 2025 at 08:58:52PM -0700, Song Liu wrote:
> > > On a closer look, I think we also need some logic in unwind_find_stack()
> > > so that we can see when the unwinder hits the exception boundary. For
> > > this reason, we may still need unwind_state.unreliable. I will look into
> > > fixing this and send v2.
> >
> > Isn't that what FRAME_META_TYPE_PT_REGS is for?
> >
> > Maybe it can just tell kunwind_stack_walk() to set a bit in
> > kunwind_state which tells kunwind_next_frame_record_meta() to quit the
> > unwind early for the FRAME_META_TYPE_PT_REGS case.  That also has the
> > benefit of stopping the unwind as soon as the exception is encounterd.
> >
>
> After reviewing the code flow, it seems like we should treat all -EINVALID
> cases or `FRAME_META_TYPE_PT_REGS` cases as unreliable unwinds.

Agreed with this: all -EINVALID cases or `FRAME_META_TYPE_PT_REGS`
should be unreliable, IIUC.

>
> Would a simplification like the one below work?
> Or we can return a special value for success cases in kunwind_next_regs_pc()
>
> ```
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 69d0567a0c38..0eb69fa6161a 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -296,7 +296,8 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
>                 if (!consume_state(state, cookie))
>                         break;
>                 ret = kunwind_next(state);
> -               if (ret < 0)
> +               if (ret < 0 || state->source == KUNWIND_SOURCE_REGS_PC)
> +                       state->common.unreliable = true;

I am current leaning toward not using common.unreliable. It seems to add
unnecessary complexity here. But I may change my mind later on.

Thanks,
Song

>                         break;
>         }
>  }
> ```
>
> --
> Weinan


From jgg at nvidia.com  Wed Mar 19 12:22:46 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Wed, 19 Mar 2025 16:22:46 -0300
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9sItt8BIgvbBY8M@arm.com>
References: <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
 <20250318230909.GD9311@nvidia.com>
 <Z9pryQwy2iwa2bpJ@linux.dev>
 <20250319170429.GK9311@nvidia.com>
 <Z9sItt8BIgvbBY8M@arm.com>
Message-ID: <20250319192246.GQ9311@nvidia.com>

On Wed, Mar 19, 2025 at 06:11:02PM +0000, Catalin Marinas wrote:
> On Wed, Mar 19, 2025 at 02:04:29PM -0300, Jason Gunthorpe wrote:
> > On Wed, Mar 19, 2025 at 12:01:29AM -0700, Oliver Upton wrote:
> > > You have a very good point that KVM is broken for cacheable PFNMAP'd
> > > crap since we demote to something non-cacheable, and maybe that
> > > deserves fixing first. Hopefully nobody notices that we've taken away
> > > the toys...
> > 
> > Fixing it is either faulting all access attempts or mapping it
> > cachable to the S2 (as this series is trying to do)..
> 
> As I replied earlier, it might be worth doing both - fault on !FWB
> hardware (or rather reject the memslot creation), cacheable S2
> otherwise.

I have no objection, Ankit are you able to make a failure patch?

Jason


From krzk at kernel.org  Wed Mar 19 12:23:11 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 20:23:11 +0100
Subject: [PATCH v4 2/2] ARM: dts: aspeed: Add Initial device tree for AMD
 Onyx Platform
In-Reply-To: <8c7be61d-d5e4-4f7f-a995-06cf856a84ae@amd.com>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
 <20250318174730.1921983-2-Rajaganesh.Rathinasabapathi@amd.com>
 <af75c352-0010-4c58-b8bc-ac0d02337d1a@kernel.org>
 <8c7be61d-d5e4-4f7f-a995-06cf856a84ae@amd.com>
Message-ID: <b75a5c14-f399-45e2-80f3-923e7afe78ab@kernel.org>

On 19/03/2025 17:41, Rajaganesh Rathinasabapathi wrote:
> On 3/18/25 23:44, Krzysztof Kozlowski wrote:
>> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
>>
>>
>> On 18/03/2025 18:47, Rajaganesh Rathinasabapathi wrote:
>>> Add initial device tree and makefile updates for
>>> AMD Onyx platform.
>>>
>>> AMD Onyx platform is an AMD customer reference board with an Aspeed
>>> ast2600 BMC manufactured by AMD.
>>> It describes I2C devices, UARTs, MAC, FMC, etc.
>>> present on AMD Onyx platform.
>>>
>>> Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
>>> Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
>>> ---
>>> Changes since v1:
>>> * Incorporate review comments
>>
>> Which ones? I do not see my comments addressed and if you do not list
>> them, I treat it as a clear sign you do not care.
>>
> 
> Understood, will list them in next patch submission.
>>> * Update commit message
>>> * Remove vmalloc and earlyprintk
>>>
>>> Changes since v2:
>>> * Address review comments
>>
>> Which ones? This has to be specific
>>
> Got it, will add details and fix in next patch.
> 
>>> * Fix checkpatch warnings
>>> * Remove bootargs
>>>
>>> Changes since v3:
>>> * Fix stdout-path
>>> * Change commit summary
>>> ---
>>>  arch/arm/boot/dts/aspeed/Makefile             |   1 +
>>>  .../boot/dts/aspeed/aspeed-bmc-amd-onyx.dts   | 102 ++++++++++++++++++
>>>  2 files changed, 103 insertions(+)
>>>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>>>
>>> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
>>> index 2e5f4833a073..1e6a130377b8 100644
>>> --- a/arch/arm/boot/dts/aspeed/Makefile
>>> +++ b/arch/arm/boot/dts/aspeed/Makefile
>>> @@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>>>       aspeed-ast2600-evb.dtb \
>>>       aspeed-bmc-amd-daytonax.dtb \
>>>       aspeed-bmc-amd-ethanolx.dtb \
>>> +     aspeed-bmc-amd-onyx.dtb \
>>>       aspeed-bmc-ampere-mtjade.dtb \
>>>       aspeed-bmc-ampere-mtjefferson.dtb \
>>>       aspeed-bmc-ampere-mtmitchell.dtb \
>>> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>>> new file mode 100644
>>> index 000000000000..32509a651183
>>> --- /dev/null
>>> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dts
>>> @@ -0,0 +1,102 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +// Copyright (c) 2021 - 2024 AMD Inc.
>>> +// Author: Supreeth Venkatesh <supreeth.venkatesh at amd.com>
>>> +
>>> +/dts-v1/;
>>> +
>>> +#include "aspeed-g6.dtsi"
>>> +#include <dt-bindings/gpio/aspeed-gpio.h>
>>> +
>>> +/ {
>>> +     model = "AMD Onyx BMC";
>>> +     compatible = "amd,onyx-bmc", "aspeed,ast2600";
>>> +
>>> +     aliases {
>>> +             serial0 = &uart1;
>>> +             serial4 = &uart5;
>>> +     };
>>> +
>>> +     chosen {
>>> +             stdout-path = "serial4:115200n8";
>>> +     };
>>> +
>>> +     memory at 80000000 {
>>> +             device_type = "memory";
>>> +             reg = <0x80000000 0x80000000>;
>>> +     };
>>> +
>>> +};
>> How did you address comment here from v1 which was responded with "ACK"?
>>
>> What else what exactly fixed and what not?
>>
>> Best regards,
>> Krzysztof
> 
> Thanks for the comments.
> I will add 'Acked-by' and in next patch submission. 
> 


What? Where did you get it from? Are you sure you understand submitting
patches document regarding this section?

Read the comment given on v1 instead of some random actions.

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 12:28:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 20:28:56 +0100
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250319112451.4171471-1-wthai@nvidia.com>
References: <93bb3092-7f49-4a7f-ac97-3cf1a62ac39d@kernel.org>
 <20250319112451.4171471-1-wthai@nvidia.com>
Message-ID: <44f2387b-0a86-46cc-a5d2-950dd688b207@kernel.org>

On 19/03/2025 12:24, Willie Thai wrote:
>>> +
>>> +// Enable Primary flash on FMC for bring up activity
>>> +&fmc {
>>> +	status = "okay";
>>> +	flash at 0 {
>>> +		status = "okay";
>>
>> Nothing improved.
>>
>> Respond to comment instead of ignoring it.
>>
> 
> The property was disabled here: https://github.com/torvalds/linux/blob/master/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi#L172

I see, thanks.


Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 12:31:09 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 20:31:09 +0100
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <9397d6d5-518d-4bd0-a34a-7a5f5e1201f1@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
 <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
 <9397d6d5-518d-4bd0-a34a-7a5f5e1201f1@amlogic.com>
Message-ID: <37f65ad0-69fa-4031-86da-8b07828aff34@kernel.org>

On 19/03/2025 11:38, Jiebing Chen wrote:
>>>   };
>>>
>>>   &pwm_ef {
>>> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>> index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
>>> --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>> +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>> @@ -11,7 +11,11 @@
>>>   #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
>>>   #include <dt-bindings/power/meson-s4-power.h>
>>>   #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
>>> -
>> Why?
> 
> The following files are included that the audio driver depends on

Do you understand how emails work and patch review? I commented under
your change, not unrelated code being there already.

> 
> it is same as sm1 chip
> 
>>> +#include <dt-bindings/clock/axg-audio-clkc.h>
>>> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
>>> +#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
>>> +#include <dt-bindings/sound/meson-g12a-toacodec.h>
>>> +#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
>> Old style was correct.
> 
> I didn't understand where you were referring to, I'm guessing that's 
> what it was about

Read your patch.


> 
> the following changes to tdmif_a
> 
> old:
> 
> clock-names = "mclk", "sclk", "lrclk";
> 
> new:
> clock-names = "sclk", "lrclk","mclk";
> it fix warning

How is this related to the patch hunk?

Do you understand how patch format works?


...

>>>        timer {
>>>                compatible = "arm,armv8-timer";
>>>                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
>>> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>>>                        #address-cells = <2>;
>>>                        #size-cells = <2>;
>>>                        ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>>> -
>> Why? What is happening in this patch - why are you changing so many
>> other pieces?

You did not respond here, so I assume you will fix this and do intensive
review before posting next version.

>>
>>>                        clkc_periphs: clock-controller at 0 {
>>>                                compatible = "amlogic,s4-peripherals-clkc";
>>>                                reg = <0x0 0x0 0x0 0x49c>;
>>> @@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
>>>                                #clock-cells = <1>;
>>>                        };
>>>
>>> +                     acodec: audio-controller at 1a000 {
>>> +                             compatible = "amlogic,t9015";
>>> +                             reg = <0x0 0x1A000 0x0 0x14>;
>>> +                             #sound-dai-cells = <0>;
>>> +                             sound-name-prefix = "ACODEC";
>>> +                             clocks = <&clkc_periphs CLKID_ACODEC>;
>>> +                             clock-names = "pclk";
>>> +                             resets = <&reset RESET_ACODEC>;
>>> +                             AVDD-supply = <&vddio_ao1v8>;
>>> +                     };
>>> +
>>>                        watchdog at 2100 {
>>>                                compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
>>>                                reg = <0x0 0x2100 0x0 0x10>;
>>> @@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
>>>                };
>>>        };
>>>   };
>>> +
>>> +&apb4 {
>>> +     audio: bus at 330000 {
>>> +             compatible = "simple-bus";
>>> +             reg = <0x0 0x330000 0x0 0x1000>;
>> That's not a simple bus in such case.
> 
> these code base on old dts like sm1/g12a, we didn't easily change any of 
> the relevant properties
> 
> To be consistent with the previous one

Still NAK.

You cannot add bugs just to be consistent.


Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 19 12:31:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 19 Mar 2025 20:31:34 +0100
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <9ae73d75-9c59-4255-8924-b456c86cbc01@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
 <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>
 <9ae73d75-9c59-4255-8924-b456c86cbc01@amlogic.com>
Message-ID: <7084e271-8546-4a49-9eb8-ee3f647c529a@kernel.org>

On 19/03/2025 11:09, Jiebing Chen wrote:
> 
> ? 2025/3/19 16:22, Krzysztof Kozlowski ??:
>> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> [ EXTERNAL EMAIL ]
>>
>> On Wed, Mar 19, 2025 at 03:04:45PM +0800, jiebing chen wrote:
>>> Add clock IDs for the mclk pads found on s4 SoCs
>>>
>>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>>> ---
>>>   include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++
>> This belongs to the binding patch, usually.
>>
>> Anyway - do not ask us to do the work twice.
>>
>> <form letter>
>> This is a friendly reminder during the review process.
>>
>> It looks like you received a tag and forgot to add it.
>>
>> If you do not know the process, here is a short explanation:
>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
>> versions of patchset, under or above your Signed-off-by tag, unless
>> patch changed significantly (e.g. new properties added to the DT
>> bindings). Tag is "received", when provided in a message replied to you
>> on the mailing list. Tools like b4 can help here. However, there's no
>> need to repost patches *only* to add the tags. The upstream maintainer
>> will do that for tags received on the version they apply.
>>
>> Please read:
>> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
>>
>> If a tag was not added on purpose, please state why and what changed.
>> </form letter>
> 
> thanks for your remind

Are you going to do anything or you are going to ignore us?

Best regards,
Krzysztof


From conor at kernel.org  Wed Mar 19 13:00:19 2025
From: conor at kernel.org (Conor Dooley)
Date: Wed, 19 Mar 2025 20:00:19 +0000
Subject: [PATCH 1/5] dt-bindings: display: mediatek: mdp-rsz: Add rules
 for MT8196
In-Reply-To: <76a6fc25a09dfddb55fdaf0a9d7dcf9a6129b00f.camel@mediatek.com>
References: <20250211025317.399534-1-sunny.shen@mediatek.com>
 <20250211025317.399534-2-sunny.shen@mediatek.com>
 <20250211-feed-shed-4b32f146cc54@spud>
 <029f9fd7ab898769a7ae627b160e1dce446ccc9e.camel@mediatek.com>
 <20250224-dreamland-tactile-bdb58daf6060@spud>
 <76a6fc25a09dfddb55fdaf0a9d7dcf9a6129b00f.camel@mediatek.com>
Message-ID: <20250319-footnote-trusting-230e509bed07@spud>

On Tue, Mar 18, 2025 at 03:14:07AM +0000, Sunny Shen (???) wrote:
> On Mon, 2025-02-24 at 19:01 +0000, Conor Dooley wrote:
> > On Sun, Feb 23, 2025 at 05:49:45PM +0000, Sunny Shen (???) wrote:
> > > On Tue, 2025-02-11 at 17:54 +0000, Conor Dooley wrote:
> > > > On Tue, Feb 11, 2025 at 10:52:50AM +0800, Sunny Shen wrote:
> > > > > Add MDP-RSZ hardware description for MediaTek MT8196 SoC
> > 
> > > > > +examples:
> > > > > +? - |
> > > > > +??? soc {
> > > > > +??????? #address-cells = <2>;
> > > > > +??????? #size-cells = <2>;
> > > > > +
> > > > > +??????? disp_mdp_rsz0: disp-mdp-rsz0 at 321a0000 {
> > > > 
> > > > And "disp-mdp-rsz0" isn't anything close to a generic node name.
> > > 
> > > Will modify "disp-mdp-rsz0 at 321a0000" to "mdp-rsz at 321a0000"
> > 
> > I don't think that's an improvement. Hint: full words would be a good
> > place to start
> 
> ?
> Hi Conor,
> 
> About full words,?
> Do you mean words like this??
> multimedia-display-path-resizer?
> or mdp-resizer?

These are both improvements on what you've got right now.

> We found that "mdp-rsz" this kind of word is used at
> https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/mediatek/mt8183.dtsi
> 
> I'm not sure what will be better.
> Can you provide more detailed suggestion about this naming?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250319/ef0dff65/attachment.sig>

From arnd at arndb.de  Wed Mar 19 13:57:26 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 19 Mar 2025 21:57:26 +0100
Subject: [GIT PULL] amlogic ARM64 DT updates for v6.15
In-Reply-To: <41ced8db-caeb-4deb-9193-9802fc603180@linaro.org>
References: <41ced8db-caeb-4deb-9193-9802fc603180@linaro.org>
Message-ID: <47683e40-aa0e-4d86-9226-94f7d56f34ae@app.fastmail.com>

On Mon, Mar 17, 2025, at 17:13, Neil Armstrong wrote:
> Hi,
>
> Here's a changeset for Amlogic ARM64 DT, also switching to the new PWM bindings,
> adding pinctrl support for Amlogic A4 SoC with a brand new binding style then
> finally gpio_intc node for Amlogic A4 & A5 SoCs.

I'll skip this one for 6.15, seeing that the branch contains both
driver and devicetree changes, which messes up the way I send
the contents.

>From the description I also can't tell to what degree there is
backwards compatibility in the new binding, I assume the changed
PWM and pinctrl drivers continue to work find with the old dts
but not the other way round, which is why you sent them together?

     Arnd


From arnd at arndb.de  Wed Mar 19 14:10:31 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 19 Mar 2025 22:10:31 +0100
Subject: [GIT PULL] Qualcomm Arm64 DeviceTree updates for v6.15
In-Reply-To: <20250317215921.2031880-1-andersson@kernel.org>
References: <20250317215921.2031880-1-andersson@kernel.org>
Message-ID: <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>

On Mon, Mar 17, 2025, at 22:59, Bjorn Andersson wrote:
>
> Krzysztof Kozlowski (17):
>       arm64: dts: qcom: sa8775p: Partially revert "arm64: dts: qcom: 
> sa8775p: add QCrypto nodes"
>       arm64: dts: qcom: qcs8300: Partially revert "arm64: dts: qcom: 
> qcs8300: add QCrypto nodes"
>       arm64: dts: qcom: x1e80100-slim7x: Drop incorrect 
> qcom,ath12k-calibration-variant
>       arm64: dts: qcom: msm8998: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: qrb2210-rb1: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: qrb4210-rb2: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sc7180: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sdm845: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sda660-ifc6560: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sm6115: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sm8150-hdk: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: qcm6490: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sa8775p-ride: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sc8280xp: Switch to undeprecated 
> qcom,calibration-variant
>       arm64: dts: qcom: sm8250-elish: Switch to undeprecated 
> qcom,calibration-variant

This seeems to remove the properties that the drivers expect
even in 6.14-rc7, so the branch is currently broken and I'll
skip it for 6.15. Let's see how we should handle this properly
in the next cycle, since it's too late now to fix it.

      Arnd


From arnd at arndb.de  Wed Mar 19 14:11:36 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 19 Mar 2025 22:11:36 +0100
Subject: [GIT PULL] Qualcomm Arm32 DeviceTree updates for v6.15
In-Reply-To: <20250317213630.2029212-1-andersson@kernel.org>
References: <20250317213630.2029212-1-andersson@kernel.org>
Message-ID: <e817e828-7ffa-4114-b957-35552cb16cc3@app.fastmail.com>

On Mon, Mar 17, 2025, at 22:36, Bjorn Andersson wrote:
> ----------------------------------------------------------------
> Qualcomm Arm32 DeviceTree updates for v6.15
>
> Cleanup indentation issues and a deprecated WiFi property.
>
> ----------------------------------------------------------------
> Krzysztof Kozlowski (1):
>       ARM: dts: qcom: ipq4018: Switch to undeprecated qcom,calibration-variant

Same as for the arm64 changes, let's skip this one for 6.15 and
do it properly next time. The branch in its current form is
clearly broken as it removes the properties that the driver expects.

     Arnd


From song at kernel.org  Wed Mar 19 14:37:06 2025
From: song at kernel.org (Song Liu)
Date: Wed, 19 Mar 2025 14:37:06 -0700
Subject: [PATCH v2 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250319213707.1784775-1-song@kernel.org>
References: <20250319213707.1784775-1-song@kernel.org>
Message-ID: <20250319213707.1784775-2-song@kernel.org>

With proper exception boundary detection, it is possible to implment
arch_stack_walk_reliable without sframe.

Note that, arch_stack_walk_reliable does not guarantee getting reliable
stack in all scenarios. Instead, it can reliably detect when the stack
trace is not reliable, which is enough to provide reliable livepatching.

Signed-off-by: Song Liu <song at kernel.org>
---
 arch/arm64/Kconfig             |  2 +-
 arch/arm64/kernel/stacktrace.c | 70 ++++++++++++++++++++++++++--------
 2 files changed, 55 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..ed4f7bf4a879 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -275,6 +275,7 @@ config ARM64
 	select HAVE_SOFTIRQ_ON_OWN_STACK
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
+	select HAVE_RELIABLE_STACKTRACE
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2499,4 +2500,3 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
-
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 1d9d51d7627f..b0489aad5897 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -56,6 +56,7 @@ struct kunwind_state {
 	enum kunwind_source source;
 	union unwind_flags flags;
 	struct pt_regs *regs;
+	bool end_on_unreliable;
 };
 
 static __always_inline void
@@ -230,8 +231,26 @@ kunwind_next_frame_record(struct kunwind_state *state)
 	new_fp = READ_ONCE(record->fp);
 	new_pc = READ_ONCE(record->lr);
 
-	if (!new_fp && !new_pc)
-		return kunwind_next_frame_record_meta(state);
+	if (!new_fp && !new_pc) {
+		int ret;
+
+		ret = kunwind_next_frame_record_meta(state);
+		if (ret < 0) {
+			/*
+			 * This covers two different conditions:
+			 *  1. ret == -ENOENT, unwinding is done.
+			 *  2. ret == -EINVAL, unwinding hit error.
+			 */
+			return ret;
+		}
+		/*
+		 * Searching across exception boundaries. The stack is now
+		 * unreliable.
+		 */
+		if (state->end_on_unreliable)
+			return -EINVAL;
+		return 0;
+	}
 
 	unwind_consume_stack(&state->common, info, fp, sizeof(*record));
 
@@ -277,21 +296,24 @@ kunwind_next(struct kunwind_state *state)
 
 typedef bool (*kunwind_consume_fn)(const struct kunwind_state *state, void *cookie);
 
-static __always_inline void
+static __always_inline int
 do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 	   void *cookie)
 {
-	if (kunwind_recover_return_address(state))
-		return;
+	int ret;
 
-	while (1) {
-		int ret;
+	ret = kunwind_recover_return_address(state);
+	if (ret)
+		return ret;
 
+	while (1) {
 		if (!consume_state(state, cookie))
-			break;
+			return -EINVAL;
 		ret = kunwind_next(state);
+		if (ret == -ENOENT)
+			return 0;
 		if (ret < 0)
-			break;
+			return ret;
 	}
 }
 
@@ -324,10 +346,10 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 			: stackinfo_get_unknown();		\
 	})
 
-static __always_inline void
+static __always_inline int
 kunwind_stack_walk(kunwind_consume_fn consume_state,
 		   void *cookie, struct task_struct *task,
-		   struct pt_regs *regs)
+		   struct pt_regs *regs, bool end_on_unreliable)
 {
 	struct stack_info stacks[] = {
 		stackinfo_get_task(task),
@@ -348,11 +370,12 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 			.stacks = stacks,
 			.nr_stacks = ARRAY_SIZE(stacks),
 		},
+		.end_on_unreliable = end_on_unreliable,
 	};
 
 	if (regs) {
 		if (task != current)
-			return;
+			return -EINVAL;
 		kunwind_init_from_regs(&state, regs);
 	} else if (task == current) {
 		kunwind_init_from_caller(&state);
@@ -360,7 +383,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 		kunwind_init_from_task(&state, task);
 	}
 
-	do_kunwind(&state, consume_state, cookie);
+	return do_kunwind(&state, consume_state, cookie);
 }
 
 struct kunwind_consume_entry_data {
@@ -384,7 +407,22 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 		.cookie = cookie,
 	};
 
-	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
+	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs, false);
+}
+
+noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
+			void *cookie, struct task_struct *task)
+{
+	struct kunwind_consume_entry_data data = {
+		.consume_entry = consume_entry,
+		.cookie = cookie,
+	};
+	int ret;
+
+	ret = kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL, true);
+	if (ret == -ENOENT)
+		ret = 0;
+	return ret;
 }
 
 struct bpf_unwind_consume_entry_data {
@@ -409,7 +447,7 @@ noinline noinstr void arch_bpf_stack_walk(bool (*consume_entry)(void *cookie, u6
 		.cookie = cookie,
 	};
 
-	kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL);
+	kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL, false);
 }
 
 static const char *state_source_string(const struct kunwind_state *state)
@@ -456,7 +494,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
 		return;
 
 	printk("%sCall trace:\n", loglvl);
-	kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs);
+	kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs, false);
 
 	put_task_stack(tsk);
 }
-- 
2.47.1



From song at kernel.org  Wed Mar 19 14:37:05 2025
From: song at kernel.org (Song Liu)
Date: Wed, 19 Mar 2025 14:37:05 -0700
Subject: [PATCH v2 0/2] arm64: livepatch: Enable livepatch without sframe
Message-ID: <20250319213707.1784775-1-song@kernel.org>

There are recent efforts to enable livepatch for arm64, with sframe [1] or
without sframe [2]. This set tries to enable livepatch without sframe. Some
of the code, however, are from [1].

Although the sframe implementation is more promising in longer term, it
suffers from the following issues:

  1. sframe is not yet supported in llvm;
  2. There is still bug in binutil [3], so that we cannot yet use sframe
     with gcc;
  3. sframe unwinder hasn't been fully verified in the kernel.

On the other hand, arm64 processors have become more and more important in
the data center world. Therefore, it is getting critical to support
livepatching of arm64 kernels.

With recent change in arm64 unwinder [4], it is possible to reliably
livepatch arm64 kernels without sframe. This is because we do not need
arch_stack_walk_reliable() to get reliable stack trace in all scenarios.
Instead, we only need arch_stack_walk_reliable() to detect when the
stack trace is not reliable, then the livepatch logic can retry the patch
transition at a later time.

Given the increasing need of livepatching, and relatively long time before
sframe is fully ready (for both gcc and clang), we would like to enable
livepatch without sframe.

Thanks!

[1] https://lore.kernel.org/live-patching/20250127213310.2496133-1-wnliu at google.com/
[2] https://lore.kernel.org/live-patching/20250129232936.1795412-1-song at kernel.org/
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=32589
[4] https://lore.kernel.org/linux-arm-kernel/20241017092538.1859841-1-mark.rutland at arm.com/

Changes v1 => v2:

1. Rework arch_stack_walk_reliable().

v1: https://lore.kernel.org/live-patching/20250308012742.3208215-1-song at kernel.org/

Song Liu (2):
  arm64: Implement arch_stack_walk_reliable
  arm64: Implement HAVE_LIVEPATCH

 arch/arm64/Kconfig                   |  3 ++
 arch/arm64/include/asm/thread_info.h |  4 +-
 arch/arm64/kernel/entry-common.c     |  4 ++
 arch/arm64/kernel/stacktrace.c       | 70 +++++++++++++++++++++-------
 4 files changed, 64 insertions(+), 17 deletions(-)

--
2.47.1


From song at kernel.org  Wed Mar 19 14:37:07 2025
From: song at kernel.org (Song Liu)
Date: Wed, 19 Mar 2025 14:37:07 -0700
Subject: [PATCH v2 2/2] arm64: Implement HAVE_LIVEPATCH
In-Reply-To: <20250319213707.1784775-1-song@kernel.org>
References: <20250319213707.1784775-1-song@kernel.org>
Message-ID: <20250319213707.1784775-3-song@kernel.org>

This is largely based on [1] by Suraj Jitindar Singh.

Test coverage:

- Passed manual tests with samples/livepatch.
- Passed all but test-kprobe.sh in selftests/livepatch.
  test-kprobe.sh is expected to fail, because arm64 doesn't have
  KPROBES_ON_FTRACE.
- Passed tests with kpatch-build [2]. (This version includes commits that
  are not merged to upstream kpatch yet).

[1] https://lore.kernel.org/all/20210604235930.603-1-surajjs at amazon.com/
[2] https://github.com/liu-song-6/kpatch/tree/fb-6.13
Cc: Suraj Jitindar Singh <surajjs at amazon.com>
Cc: Torsten Duwe <duwe at suse.de>
Signed-off-by: Song Liu <song at kernel.org>
---
 arch/arm64/Kconfig                   | 3 +++
 arch/arm64/include/asm/thread_info.h | 4 +++-
 arch/arm64/kernel/entry-common.c     | 4 ++++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index ed4f7bf4a879..bc9edba6171a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -276,6 +276,7 @@ config ARM64
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
 	select HAVE_RELIABLE_STACKTRACE
+	select HAVE_LIVEPATCH
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2500,3 +2501,5 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
+
+source "kernel/livepatch/Kconfig"
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 1114c1c3300a..4ac42e13032b 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -64,6 +64,7 @@ void arch_setup_new_exec(void);
 #define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
 #define TIF_MTE_ASYNC_FAULT	5	/* MTE Asynchronous Tag Check Fault */
 #define TIF_NOTIFY_SIGNAL	6	/* signal notifications exist */
+#define TIF_PATCH_PENDING	7	/* pending live patching update */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing */
 #define TIF_SYSCALL_TRACEPOINT	10	/* syscall tracepoint for ftrace */
@@ -92,6 +93,7 @@ void arch_setup_new_exec(void);
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
+#define _TIF_PATCH_PENDING	(1 << TIF_PATCH_PENDING)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
@@ -103,7 +105,7 @@ void arch_setup_new_exec(void);
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
 				 _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
-				 _TIF_NOTIFY_SIGNAL)
+				 _TIF_NOTIFY_SIGNAL | _TIF_PATCH_PENDING)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index b260ddc4d3e9..b537af333b42 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -8,6 +8,7 @@
 #include <linux/context_tracking.h>
 #include <linux/kasan.h>
 #include <linux/linkage.h>
+#include <linux/livepatch.h>
 #include <linux/lockdep.h>
 #include <linux/ptrace.h>
 #include <linux/resume_user_mode.h>
@@ -144,6 +145,9 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 				       (void __user *)NULL, current);
 		}
 
+		if (thread_flags & _TIF_PATCH_PENDING)
+			klp_update_patch_state(current);
+
 		if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
 			do_signal(regs);
 
-- 
2.47.1



From andrea.porta at suse.com  Wed Mar 19 14:52:30 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:30 +0100
Subject: [PATCH v8 09/13] arm64: dts: Add board DTS for Rpi5 which includes RP1 node
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <c6498d8cf8dfade1980b566e99a9a91551fd8b53.1742418429.git.andrea.porta@suse.com>

Add the board 'monolithic' DTS for RaspberryPi 5 which includes
the RP1 node definition.  The inclusion treeis as follow (the
arrow points to the includer):

rp1-common.dtsi ----> rp1-nexus.dtsi ----> bcm2712-rpi-5-b-monolithic.dts
                                               ^
                                               |
                                           bcm2712-rpi-5-b.dts

This is designed to maximize the compatibility with downstream DT
while ensuring that a fully defined DT (one which includes the RP1
node as opposed to load it from overlay at runtime) is present
since early boot stage.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
---
Right now bcm2712-rpi-5-b.dts is the overlay-ready DT which will make
the RP1 driver to load the RP1 dtb overlay at runtime, while
bcm2712-rpi-5-b-monolithic.dts is the fully defined one (i.e. it
already contains RP1 node, so no overlay is loaded nor needed). 
Depending on which one we want to be considered the default, we can
swap the file names to align with downstream naming convention that
has only the fully defined DT called bcm2712-rpi-5-b.dts.
---
 arch/arm64/boot/dts/broadcom/Makefile                     | 1 +
 .../boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts      | 8 ++++++++
 2 files changed, 9 insertions(+)
 create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts

diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
index 3d0efb93b06d..4836c6da5bee 100644
--- a/arch/arm64/boot/dts/broadcom/Makefile
+++ b/arch/arm64/boot/dts/broadcom/Makefile
@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
 			      bcm2711-rpi-4-b.dtb \
 			      bcm2711-rpi-cm4-io.dtb \
 			      bcm2712-rpi-5-b.dtb \
+			      bcm2712-rpi-5-b-monolithic.dtb \
 			      bcm2712-d-rpi-5-b.dtb \
 			      bcm2837-rpi-3-a-plus.dtb \
 			      bcm2837-rpi-3-b.dtb \
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts
new file mode 100644
index 000000000000..3aeee678b0bc
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/dts-v1/;
+
+#include "bcm2712-rpi-5-b.dts"
+
+&pcie2 {
+	#include "rp1-nexus.dtsi"
+};
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:31 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:31 +0100
Subject: [PATCH v8 10/13] arm64: dts: Add overlay for RP1 device
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <ab9ab3536baf5fdf6016f2a01044f00034189291.1742418429.git.andrea.porta@suse.com>

Define the RP1 node in an overlay. The inclusion tree is
as follow (the arrow points to the includer):

                      rp1.dtso
                          ^
                          |
rp1-common.dtsi ----> rp1-nexus.dtsi

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
---
This patch can be considered optional, since it fills just the second
scenario as detailed in [1], which is the RP1 DT node loaded from a dtb
overlay by the FW at early boot stage.
This may be useful for debug purpose, but as such not strictly necessary.

[1] https://lore.kernel.org/all/CAMEGJJ0f4YUgdWBhxvQ_dquZHztve9KO7pvQjoDWJ3=zd3cgcg at mail.gmail.com/#t
---
 arch/arm64/boot/dts/broadcom/Makefile |  3 ++-
 arch/arm64/boot/dts/broadcom/rp1.dtso | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1.dtso

diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
index 4836c6da5bee..58293f9c16ab 100644
--- a/arch/arm64/boot/dts/broadcom/Makefile
+++ b/arch/arm64/boot/dts/broadcom/Makefile
@@ -13,7 +13,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
 			      bcm2837-rpi-3-b.dtb \
 			      bcm2837-rpi-3-b-plus.dtb \
 			      bcm2837-rpi-cm3-io3.dtb \
-			      bcm2837-rpi-zero-2-w.dtb
+			      bcm2837-rpi-zero-2-w.dtb \
+			      rp1.dtbo
 
 subdir-y	+= bcmbca
 subdir-y	+= northstar2
diff --git a/arch/arm64/boot/dts/broadcom/rp1.dtso b/arch/arm64/boot/dts/broadcom/rp1.dtso
new file mode 100644
index 000000000000..ab4f146d22c0
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/rp1.dtso
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/dts-v1/;
+/plugin/;
+
+&pcie2 {
+	#address-cells = <3>;
+	#size-cells = <2>;
+
+	#include "rp1-nexus.dtsi"
+};
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:32 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:32 +0100
Subject: [PATCH v8 11/13] arm64: dts: bcm2712: Add external clock for RP1 chipset on Rpi5
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <7c26a0b52e00a39930ba02f7552abdd1be4c828c.1742418429.git.andrea.porta@suse.com>

The RP1 found on Raspberry Pi 5 board needs an external crystal at 50MHz.
Add clk_rp1_xosc node to provide that.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
index fbc56309660f..1850a575e708 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
@@ -16,6 +16,13 @@ chosen: chosen {
 		stdout-path = "serial10:115200n8";
 	};
 
+	clk_rp1_xosc: clock-50000000 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "rp1-xosc";
+		clock-frequency = <50000000>;
+	};
+
 	/* Will be filled by the bootloader */
 	memory at 0 {
 		device_type = "memory";
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:33 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:33 +0100
Subject: [PATCH v8 12/13] arm64: defconfig: Enable RP1 misc/clock/gpio drivers
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <378f6ef859d7c23770b1532a370f4af97cc9a922.1742418429.git.andrea.porta@suse.com>

Select the RP1 drivers needed to operate the PCI endpoint containing
several peripherals such as Ethernet and USB Controller. This chip is
present on RaspberryPi 5.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Stefan Wahren <wahrenst at gmx.net>
---
 arch/arm64/configs/defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..cc70793e97ef 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -618,6 +618,7 @@ CONFIG_PINCTRL_QCS615=y
 CONFIG_PINCTRL_QCS8300=y
 CONFIG_PINCTRL_QDF2XXX=y
 CONFIG_PINCTRL_QDU1000=y
+CONFIG_PINCTRL_RP1=m
 CONFIG_PINCTRL_SA8775P=y
 CONFIG_PINCTRL_SC7180=y
 CONFIG_PINCTRL_SC7280=y
@@ -700,6 +701,7 @@ CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_SENSORS_SL28CPLD=m
 CONFIG_SENSORS_INA2XX=m
 CONFIG_SENSORS_INA3221=m
+CONFIG_MISC_RP1=m
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
 CONFIG_DEVFREQ_THERMAL=y
@@ -1289,6 +1291,7 @@ CONFIG_COMMON_CLK_CS2000_CP=y
 CONFIG_COMMON_CLK_FSL_SAI=y
 CONFIG_COMMON_CLK_S2MPS11=y
 CONFIG_COMMON_CLK_PWM=y
+CONFIG_COMMON_CLK_RP1=m
 CONFIG_COMMON_CLK_RS9_PCIE=y
 CONFIG_COMMON_CLK_VC3=y
 CONFIG_COMMON_CLK_VC5=y
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:34 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:34 +0100
Subject: [PATCH v8 13/13] arm64: defconfig: Enable OF_OVERLAY option
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <9d5b41bf6d1565f0de96c7c1680bd404cba40189.1742418429.git.andrea.porta@suse.com>

The RP1 driver uses the infrastructure enabled by OF_OVERLAY config
option. Enable that option in defconfig in order to produce a kernel
usable on RaspberryPi5 avoiding to enable it separately.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
---
The following metrics should help to decide whether this patch is
acceptable or not. The defconfig kernel with CONFIG_OF_OVERLAY=y
added (wrt to the defconfig one without that set) has:

- same uncompressed kernel image size (due to ELF section alignment I guess)

- ~7Kb bigger Image.gz

- 3 new modules (all related to RP1, i.e.: clk-rp1, pinctrl-rp1 and rp1-pci)

- 27 added symbols, of which 5 exported
 
hoping this is enough to gather a rough idea of the impact.
Please note that OF_OVERLAY has to be defined in a way or another,
otherwise the RP1 driver won't work correctly in case the dtb overlay
embedded into the driver is used.
Another way would be to add a phony target to the arm64 makefile which
just add that config option to the target.
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cc70793e97ef..ca492fbd2773 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1643,6 +1643,7 @@ CONFIG_FPGA_BRIDGE=m
 CONFIG_ALTERA_FREEZE_BRIDGE=m
 CONFIG_FPGA_REGION=m
 CONFIG_OF_FPGA_REGION=m
+CONFIG_OF_OVERLAY=y
 CONFIG_TEE=y
 CONFIG_OPTEE=y
 CONFIG_MUX_GPIO=m
-- 
2.35.3



From mbland at motorola.com  Wed Mar 19 14:54:01 2025
From: mbland at motorola.com (Maxwell Bland)
Date: Wed, 19 Mar 2025 16:54:01 -0500
Subject: [RFC PATCH v3 00/15] pkeys-based page table hardening
In-Reply-To: <802963a0-32bd-49e8-82b1-34443acdd5ae@arm.com>
References: <20250203101839.1223008-1-kevin.brodsky@arm.com>
 <a32cjyekuecoowzbitc2xykilvpu6l3jjtityp7x5hw7xbiysp@5l2lptwmqiug>
 <802963a0-32bd-49e8-82b1-34443acdd5ae@arm.com>
Message-ID: <epnxrdkidbrjyjzapms7dfsvjcc7ewewjue7khbuxhresy5x5n@hyhokacdi2yg>

On Thu, Mar 13, 2025 at 01:32:31PM +0100, Kevin Brodsky wrote:
> On 06/03/2025 17:23, Maxwell Bland wrote:
> > On Mon, Feb 03, 2025 at 10:18:24AM +0000, Kevin Brodsky wrote:
> > I wanted to know your thoughts on associating specific policies to
> > page table updates in cases where an adversary is able to corrupt
> > other state associated with parameters to the page table infrastructure
> > code, e.g.
> >
> > arch/arm64/net/bpf_jit_comp.c
> > 2417:		if (set_memory_rw(PAGE_MASK & ((uintptr_t)&plt->target),
> >
> > Is this something we would assume is handled via the security_* hook
> > infrastructure, a shadow stack CFI method, or changing the kernel code
> > to reverify the data non-modularly, some combination of the above?
> 
> This is a good question and the short answer is that I don't know what
> the best approach would be. As far as kpkeys are concerned, I'm not sure
> they can really help here - it seems to be about the integrity of a
> generated BPF program, and surely that program is already made read-only
> once generated?

Apologies for the slight (5ish) day delay in response here!

Regarding the above discussion of attacks on the context wrapping calls
to the PT infrastructure, I will share the approach I took below, though
it is not super fun, and I don't have all the code publicly available
(yet!).

Before that, another quick example to show it is not just BPF:

There are PT update calls inside EROFS, commonly used in mobile devices
to save on memory. One of the issues I've run into during pagetable
lockdown is

https://github.com/torvalds/linux/blob/81e4f8d68c66da301bb881862735bd74c6241a19/fs/erofs/internal.h#L414

MotoChopper-style attacks could be accomplished through corruption of
the z_erofs_pcluster allocated via SLAB, since erofs has that series of
pointers for compressed_bvecs, which is parsed out into the
compressed_pages used by the EROFS backend to map ram. 

Onto the solution. In a pure-immutability approach, I ended up creating
some definitions regarding what an "expected" virtual-to-physical
mapping of kernel memory or change in page permissions is (my solution
was to treat init_mm as a ground truth structure which is only RW under
a more refined set of constraints on mapping updates and permission set
updates), for example,

if (get_tag(cur_pte & EL1_PADDR_MASK) == SECCOMP_PAGE) {
// run BPF re-verifier to avoid the Qualys 2021 CVE PoC magic

or forcing PXN for everything always unless some other check says we
absolutely have to make this PX:

if (!cur_pte && new_pte) {
  if (!(new_pte & pxn_bit)) {
    new_pte |= pxn_bit; 

And then a bunch of additional infrastructure to define what a "safe
mapping of physical memory looks like", which introduces its own set of
problems for defining how/where vmalloc allocates from, physical address
layout randomization, ...

Such an explication of the expected possible modifications to PTEs may
be needed? I don't understand whether just adding guard() around set_pte
helps this case.

> Could you elaborate on this point? Are you referring to protecting
> arbitrary data structures with kpkeys, rather than what this series
> covers (i.e. pgtables)?

Correct.

> > Where overwriting f_op is a "classic" bypass of protection systems like
> > this one.
> 
> Indeed, this has been pointed out to me on a few occasions. On that note
> I should reference the follow-up series that aims at protecting struct
> cred [1].
> 
> Using kpkeys to ensure that the task->cred pointer itself is mostly
> read-only is not straightforward, because there is just too much
> existing code that directly writes to other fields in task_struct -
> meaning we can't simply make the whole task_struct mostly read-only.
> What could be done is to split out the cred fields in a separate
> kpkeys-protected page, and link that page from task_struct. There is a
> clear overhead associated with this approach though, and maybe more
> importantly we have just displaced the issue as the pointer to that
> protected page remains writeable... I'm not sure how much a page-based
> technique like pkeys can help here.

__randomize_layout accomplished some of what is necessary here, while
accommodating contemporary hardware limitations, albeit to a finer
granularity and lesser degree. I am also not sure how well it works on
production systems (yet! It is on my TODO list in the short term), or
how much protection it really implies for an adversary with a "read
gadget" that can determine where to write (either from associated asm or
from the struct itself).

But...

(1) After thinking about this for a few hours, __randomize_layout implies
something valuable: under circumstances where this is supported, because
we assume the struct's layout itself is modifable, it becomes possible
to introduce a canary value _not_ for the modifiable portions, but just
for the non-modifiable portions, store this canary value in a strictly
read-only region of memory that also tracks pointers to the structure,
and ensure uses of the non-modifiable fields must always leverage the
canary value stored in this secondary region.

Also...

(2) Maybe the supposition that we'd not be able to go through each of
the ~300 memcpy and all the other copy operations throughout the kernel
to add an additional step which prevents a stale reference to a pointer
to a modifable part is not totally crazy, just a little crazy.

> 
> [1]
> https://lore.kernel.org/linux-hardening/20250203102809.1223255-1-kevin.brodsky at arm.com/
> 
> > I think this problem may be totally solvable if POE was integrated into
> > something like CFI, since we can guarantee only the code that sets f_op
> > to "vmfile_fops" can unlock/relock the file's page.
> 
> I'm interested to hear more about this - I don't think I'm aware of the
> CFI instrumentation you're referring to.

It may be possible to write a plugin modification to

https://github.com/gcc-mirror/gcc/blob/12b2c414b6d0e0d1b3d328b58d654c19c30bee8c/gcc/config/arm/aarch-bti-insert.cc

To also inject the POE/register set instructions conditioned upon the an
expected privilege (kpkeys) level of the executing function.

Instead of adding code to set the privilege state via a specialized
callgate function, having this function's call explicitly tied into the
GCC CFI instrumentation pass. Determination of the specific "key level",
i.e. KPKEYS_LVL_PGTABLES, could likely be determined by the file
name/path via the compiler, or many other clever mechanisms, potentially
with support for exceptions via function attribute tags.

Note this implies still correctly accounting for the key level during
allocation, which could be retrieved from the POE level register.

> >>
> >> Any comment or feedback will be highly appreciated, be it on the
> >> high-level approach or implementation choices!
> > Last note, I'd not totallllyyy trust the compiler to inline the
> > functions.... I've met cases where functions on memory protections
> > I expected to be inlined were not. I think __forceinline *may* work
> > here, vs standard "static inline", but am not confident/sure.
> 
> That's a fair point, __always_inline could be used to make sure
> set_pkey/restore_pkey_reg (and the helpers they call) are actually
> inlined. I'll change that in v4. The guard object constructor/destructor
> are defined as regular inline functions in <linux/cleanup.h> though, so
> the inlining might not be complete.

Noticed as well, just now, the reliance on the static_key for branch
unlikely ... the following data structure (at the end of this email) may
be of interest as an FYI ... it can be used to track whether the kernel
self patching API is only being used to patch expected locations.

I use this right now with additional checks that the instruction being
written for the indirect branch matches the expected offset.

Cheers,
Maxwell


/* SPDX-License-Identifier: GPL-2.0 */
/**
 * Copyright (C) 2023 Motorola Mobility, Inc.
 *
 * Author: Maxwell Bland
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Bitwise trie data structure for storing jump label code addresses.
 * To perform a lookup, we iterate over the bits of the jump_label from MSB to
 * LSB, and use the bit as a tree traversal.
 *
 * Ideally we would just store this in the hypervisor, but we don't have enough
 * memory.  At the time of writing there are 56404 jump labels in the kernel,
 * and the hypervisor is restricted to a memory footprint of 32 KB.
 *
 * So instead what we do is allocate this data structure in the kernel module,
 * and then lock it down. Finally, we pass the pointer to the hypervisor, which
 * can then perform lookups whenever a DABT exception occurs.
 *
 * We choose not to use the kernel's radix tree for this because it is less
 * space efficient and much slower, and jump_label operations relate to
 * performance sensitive code (e.g. the networking stack).
 */

#ifndef JUMP_TABLE_LOOKUP_H
#define JUMP_TABLE_LOOKUP_H

#include <linux/of_address.h>

/* Used to determine the branch direction */
#define JUMP_TREE_BRANCH(x) ((x >> ((sizeof(x) * 8) - 1)) & 1)

union jump_tree_node {
	uint32_t je_index[2];
	uint64_t je_val;
};

static union jump_tree_node *jet; /* Start of jump table lookup */
static uint64_t jet_ind; /* Current index of jump table lookup */
static union jump_tree_node *jet_end; /* End of jump table lookup */

void init_jtn(union jump_tree_node *jtn)
{
	jtn->je_val = 0;
}

/**
 * jet_extend - extends the jump entry lookup table
 *
 * Scales up the size of the jump entry lookup table by 2 just in case our
 * initial estimate was too small. Ensures that the new size is a multiple of
 * PAGE_SIZE.
 */
void jet_extend(void)
{
	uint64_t jet_sz = jet_end - jet;
	uint64_t new_sz = jet_sz * 2;
	union jump_tree_node *new_jet;

	if (new_sz % PAGE_SIZE)
		new_sz += PAGE_SIZE - (new_sz % PAGE_SIZE);

	if (jet_ind + 1 >= jet_sz) {
		new_jet = kvmalloc(new_sz * sizeof(union jump_tree_node),
				   GFP_KERNEL);
		memcpy(new_jet, jet, jet_sz * sizeof(union jump_tree_node));
		jet_end = new_jet + new_sz;
		kvfree(jet);
		jet = new_jet;
	}

	init_jtn(jet + jet_ind);
}

/**
 * add_branch - adds a branch to the jump entry lookup tree
 *
 * Adds a branch to the current node corresponding to whether the LSB of the
 * cur_code_ptr is 1 or 0. The branch target is the index of the next node in
 * the tree or a leaf (jump entry)
 */
int add_branch(unsigned long *cur_code_ptr, union jump_tree_node *cur_node,
	       uint64_t branch_target)
{
	bool bit;

	if (!cur_code_ptr || !cur_node)
		return -EACCES;

	bit = JUMP_TREE_BRANCH(*cur_code_ptr);
	*cur_code_ptr <<= 1;

	if (bit)
		cur_node->je_index[0] = branch_target;
	else
		cur_node->je_index[1] = branch_target;

	return 0;
}

/**
 * add_trunk - adds a path of branches to the jump entry lookup tree
 *
 * Adds the series of branches to the jump entry lookup tree corresponding to
 * the bits in the cur_code_ptr value starting at LSB index i, and adds the leaf
 * node at the end.
 */
int add_trunk(union jump_tree_node *cur_node, struct jump_entry *je,
	      unsigned long cur_code_ptr, int i)
{
	if (!cur_node || !je)
		return -EACCES;

	for (; i < sizeof(cur_code_ptr) * 8; i++) {
		if (add_branch(&cur_code_ptr, cur_node, jet_ind))
			return -EACCES;
		jet_extend();
		cur_node = jet + jet_ind;
		jet_ind++;
	}

	/*
	 * GKI rips aarch64_insn_gen_branch_imm out for the illusion of security
	 * while leaving jump_labels as a whole intact, this is a partial
	 * duplicate of that function
	 */
	cur_node->je_val = (jump_entry_target(je) - jump_entry_code(je)) >> 2;

	return 0;
}

/**
 * jet_alloc - allocates a new jump entry tree for lookups
 * @jet_end_out: output parameter for the size of the jump entry tree (bytes)
 *
 * Allocates the jump entry tree with 2x the number of jump entries in the
 * kernel. This is because we need to store both the jump entry and, in the
 * worst case, a pointer to the next index in the tree. Ensures the total memory
 * allocated is a multiple of PAGE_SIZE, uses kvmalloc (the memory is
 * non-contiguous)
 *
 * Return: 0 on failure, or the pointer to the allocated jump entry tree
 */
uint64_t jet_alloc(struct jump_entry *je_start, struct jump_entry *je_end,
		   uint64_t *jet_size_out)
{
	union jump_tree_node *cur_node;
	unsigned long cur_code_ptr = -1;
	bool bit;
	int i = 0;

	if (!je_start || !je_end || !jet_size_out) {
		pr_err("%s fail: invalid parameters\n", __func__);
		return 0;
	}

	if (je_start >= je_end) {
		pr_err("%s fail: je_start >= je_end\n", __func__);
		return 0;
	}

	jet = kvmalloc(2 * (je_end - je_start) * sizeof(union jump_tree_node),
		       GFP_KERNEL);
	jet_ind = 1;
	jet_end = jet + 2 * (je_end - je_start);
	init_jtn(jet);
	init_jtn(jet + 1);

	while (je_start != je_end) {
		cur_code_ptr = __virt_to_phys(jump_entry_code(je_start));
		cur_node = jet;

		// iterate over the bits of the jump label
		for (i = 0; i < sizeof(cur_code_ptr) * 8; i++) {
			bit = JUMP_TREE_BRANCH(cur_code_ptr);

			if (bit) {
				if (cur_node->je_index[0]) {
					cur_node = jet + cur_node->je_index[0];
				} else {
					if (add_trunk(cur_node, je_start,
						      cur_code_ptr, i))
						return 0;
					break;
				}
			} else {
				if (cur_node->je_index[1]) {
					cur_node = jet + cur_node->je_index[1];
				} else {
					if (add_trunk(cur_node, je_start,
						      cur_code_ptr, i))
						return 0;
					break;
				}
			}

			cur_code_ptr <<= 1;
		}

		je_start++;
	}

	*jet_size_out = jet_end - jet;
	return (uint64_t)jet;
}

#endif


From mhklinux at outlook.com  Wed Mar 19 15:11:50 2025
From: mhklinux at outlook.com (Michael Kelley)
Date: Wed, 19 Mar 2025 22:11:50 +0000
Subject: [PATCH hyperv-next v6 02/11] arm64: hyperv: Use SMCCC to detect
 hypervisor presence
In-Reply-To: <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-3-romank@linux.microsoft.com>
 <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>
Message-ID: <BN7PR02MB414871F1A3D8EF3809391F2FD4D92@BN7PR02MB4148.namprd02.prod.outlook.com>

From: Mark Rutland <mark.rutland at arm.com> Sent: Monday, March 17, 2025 4:38 AM
> 
> On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote:
> > The arm64 Hyper-V startup path relies on ACPI to detect
> > running under a Hyper-V compatible hypervisor. That
> > doesn't work on non-ACPI systems.
> >
> > Hoist the ACPI detection logic into a separate function. Then
> > use the vendor-specific hypervisor service call (implemented
> > recently in Hyper-V) via SMCCC in the non-ACPI case.
> >
> > Signed-off-by: Roman Kisel <romank at linux.microsoft.com>
> > Reviewed-by: Michael Kelley <mhklinux at outlook.com>
> > ---
> >  arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++-----
> >  1 file changed, 38 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> > index 2265ea5ce5ad..c5b03d3af7c5 100644
> > --- a/arch/arm64/hyperv/mshyperv.c
> > +++ b/arch/arm64/hyperv/mshyperv.c
> > @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union
> hv_hypervisor_version_info *info)
> >  	return 0;
> >  }
> >
> > +static bool __init hyperv_detect_via_acpi(void)
> > +{
> > +	if (acpi_disabled)
> > +		return false;
> > +#if IS_ENABLED(CONFIG_ACPI)
> > +	/*
> > +	 * Hypervisor ID is only available in ACPI v6+, and the
> > +	 * structure layout was extended in v6 to accommodate that
> > +	 * new field.
> > +	 *
> > +	 * At the very minimum, this check makes sure not to read
> > +	 * past the FADT structure.
> > +	 *
> > +	 * It is also needed to catch running in some unknown
> > +	 * non-Hyper-V environment that has ACPI 5.x or less.
> > +	 * In such a case, it can't be Hyper-V.
> > +	 */
> > +	if (acpi_gbl_FADT.header.revision < 6)
> > +		return false;
> > +	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
> > +#else
> > +	return false;
> > +#endif
> > +}
> > +
> 
> The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use
> prior to the ifdeffery looks misplaced.

FWIW, include/linux/acpi.h has 

#define acpi_disabled 1

when !CONFIG_ACPI.  But I agree that using a stub is better.

Michael

> 
> Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED().
> Otherwise, use a stub, e.g.
> 
> | #ifdef CONFIG_ACPI
> | static bool __init hyperv_detect_via_acpi(void)
> | {
> | 	if (acpi_disabled)
> | 		return false;
> |
> | 	if (acpi_gbl_FADT.header.revision < 6)
> | 		return false;
> |
> | 	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
> | }
> | #else
> | static inline bool hyperv_detect_via_acpi(void) { return false; }
> | #endif
> 
> Mark.
> 
> > +static bool __init hyperv_detect_via_smccc(void)
> > +{
> > +	uuid_t hyperv_uuid = UUID_INIT(
> > +		0x4d32ba58, 0x4764, 0xcd24,
> > +		0x75, 0x6c, 0xef, 0x8e,
> > +		0x24, 0x70, 0x59, 0x16);
> > +
> > +	return arm_smccc_hyp_present(&hyperv_uuid);
> > +}
> > +
> >  static int __init hyperv_init(void)
> >  {
> >  	struct hv_get_vp_registers_output	result;
> > @@ -35,13 +70,11 @@ static int __init hyperv_init(void)
> >
> >  	/*
> >  	 * Allow for a kernel built with CONFIG_HYPERV to be running in
> > -	 * a non-Hyper-V environment, including on DT instead of ACPI.
> > +	 * a non-Hyper-V environment.
> > +	 *
> >  	 * In such cases, do nothing and return success.
> >  	 */
> > -	if (acpi_disabled)
> > -		return 0;
> > -
> > -	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
> > +	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
> >  		return 0;
> >
> >  	/* Setup the guest ID */
> > --
> > 2.43.0
> >



From kbusch at kernel.org  Wed Mar 19 15:22:04 2025
From: kbusch at kernel.org (Keith Busch)
Date: Wed, 19 Mar 2025 16:22:04 -0600
Subject: [PATCH v2 18/19] mm/arm64: Support large pfn mappings
In-Reply-To: <20240826204353.2228736-19-peterx@redhat.com>
References: <20240826204353.2228736-1-peterx@redhat.com>
 <20240826204353.2228736-19-peterx@redhat.com>
Message-ID: <Z9tDjOk-JdV_fCY4@kbusch-mbp.dhcp.thefacebook.com>

On Mon, Aug 26, 2024 at 04:43:52PM -0400, Peter Xu wrote:
> +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
> +#define pud_special(pte)	pte_special(pud_pte(pud))
> +#define pud_mkspecial(pte)	pte_pud(pte_mkspecial(pud_pte(pud)))
> +#endif

Sorry for such a late reply, but this looked a bit weird as I'm doing
some backporting. Not that I'm actually interested in this arch, so I
can't readily test this, but I believe the intention was to name the
macro argument "pud", not "pte".


From martin.blumenstingl at googlemail.com  Wed Mar 19 15:22:44 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 19 Mar 2025 23:22:44 +0100
Subject: [PATCH v2 1/2] dt-bindings: arm: amlogic: Add Ugoos AM3
In-Reply-To: <20250314-ugoos-am3-v2-1-422104b0cec5@posteo.net>
References: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net> <20250314-ugoos-am3-v2-1-422104b0cec5@posteo.net>
Message-ID: <CAFBinCA8Sk8rKt7zZBEgCdRh4J_fktapo56RtVJOC4myCJ1qeQ@mail.gmail.com>

On Fri, Mar 14, 2025 at 12:11?AM J. Neusch?fer via B4 Relay
<devnull+j.ne.posteo.net at kernel.org> wrote:
>
> From: "J. Neusch?fer" <j.ne at posteo.net>
>
> The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC.
>
>   https://ugoos.com/ugoos-am3-16g
>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


From jonas at kwiboo.se  Wed Mar 19 14:44:04 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:04 +0000
Subject: [PATCH net-next v3 0/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
Message-ID: <20250319214415.3086027-1-jonas@kwiboo.se>

The Rockchip RK3528 has two Ethernet controllers, one 100/10 MAC to be
used with the integrated PHY and a second 1000/100/10 MAC to be used
with an external Ethernet PHY.

This series add initial support for the Ethernet controllers found in
RK3528 and initial support to power up/down the integrated PHY.

Changes in v3:
- Rebase on latest net-next/main
- Collect r-b tag on dt-bindings patch
Link to v2: https://lore.kernel.org/r/20250309232622.1498084-1-jonas at kwiboo.se

Changes in v2:
- Restrict the minItems: 4 change to rockchip,rk3528-gmac
- Add initial support to power up/down the integrated PHY in RK3528
- Split device tree changes into a separate series
Link to v1: https://lore.kernel.org/r/20250306221402.1704196-1-jonas at kwiboo.se

David Wu (1):
  net: stmmac: dwmac-rk: Add GMAC support for RK3528

Jonas Karlman (4):
  dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
  net: stmmac: dwmac-rk: Move integrated_phy_powerup/down functions
  net: stmmac: dwmac-rk: Add integrated_phy_powerdown operation
  net: stmmac: dwmac-rk: Add initial support for RK3528 integrated PHY

 .../bindings/net/rockchip-dwmac.yaml          |  16 +-
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 277 ++++++++++++++----
 2 files changed, 242 insertions(+), 51 deletions(-)

-- 
2.49.0



From jonas at kwiboo.se  Wed Mar 19 14:44:05 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:05 +0000
Subject: [PATCH net-next v3 1/5] dt-bindings: net: rockchip-dwmac: Add compatible string for RK3528
In-Reply-To: <20250319214415.3086027-1-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
Message-ID: <20250319214415.3086027-2-jonas@kwiboo.se>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add compatible string for the RK3528 variant.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
Changes in v3:
- Rebase on latest net-next/main
- Collect r-b tag

Changes in v2:
- Restrict the minItems: 4 change to rockchip,rk3528-gmac

The enum will be extended in a future patch, Pending RK3562 and a future
RK3506 variant also only have 4 clocks.

Because snps,dwmac-4.20a is already listed in snps,dwmac.yaml adding the
rockchip,rk3528-gmac compatible did not seem necessary.
---
 .../devicetree/bindings/net/rockchip-dwmac.yaml  | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
index 63ee0cc7a8f8..0ac7c4b47d6b 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
@@ -24,6 +24,7 @@ select:
           - rockchip,rk3366-gmac
           - rockchip,rk3368-gmac
           - rockchip,rk3399-gmac
+          - rockchip,rk3528-gmac
           - rockchip,rk3568-gmac
           - rockchip,rk3576-gmac
           - rockchip,rk3588-gmac
@@ -49,6 +50,7 @@ properties:
               - rockchip,rv1108-gmac
       - items:
           - enum:
+              - rockchip,rk3528-gmac
               - rockchip,rk3568-gmac
               - rockchip,rk3576-gmac
               - rockchip,rk3588-gmac
@@ -66,7 +68,7 @@ properties:
       - const: eth_wake_irq
 
   clocks:
-    minItems: 5
+    minItems: 4
     maxItems: 8
 
   clock-names:
@@ -140,6 +142,18 @@ allOf:
       properties:
         rockchip,php-grf: false
 
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - rockchip,rk3528-gmac
+    then:
+      properties:
+        clocks:
+          minItems: 5
+
 unevaluatedProperties: false
 
 examples:
-- 
2.49.0



From jonas at kwiboo.se  Wed Mar 19 14:44:06 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:06 +0000
Subject: [PATCH net-next v3 2/5] net: stmmac: dwmac-rk: Add GMAC support for RK3528
In-Reply-To: <20250319214415.3086027-1-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
Message-ID: <20250319214415.3086027-3-jonas@kwiboo.se>

From: David Wu <david.wu at rock-chips.com>

Rockchip RK3528 has two Ethernet controllers based on Synopsys DWC
Ethernet QoS IP.

Add initial support for the RK3528 GMAC variant.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v3:
- No change
Changes in v2:
- No change

Power up/down of the integrated PHY is added in a separate patch.
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 132 ++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index c404017bc1da..dfb4668db4ee 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -828,6 +828,137 @@ static const struct rk_gmac_ops rk3399_ops = {
 	.set_rmii_speed = rk3399_set_rmii_speed,
 };
 
+#define RK3528_VO_GRF_GMAC_CON		0x0018
+#define RK3528_VO_GRF_MACPHY_CON0	0x001c
+#define RK3528_VO_GRF_MACPHY_CON1	0x0020
+#define RK3528_VPU_GRF_GMAC_CON5	0x0018
+#define RK3528_VPU_GRF_GMAC_CON6	0x001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII	GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII	GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII	GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELECT_CRU	GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELECT_IO	GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2	GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20	GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2	GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20	GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1	(GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5	(GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50	(GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE	GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE	GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE	GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE	GRF_CLR_BIT(9)
+
+static void rk3528_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
+{
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+		     DELAY_ENABLE(RK3528, tx_delay, rx_delay));
+
+	regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON6,
+		     RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+	if (bsp_priv->id == 1)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_PHY_INTF_SEL_RMII);
+	else
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON,
+			     RK3528_GMAC0_PHY_INTF_SEL_RMII |
+			     RK3528_GMAC0_CLK_RMII_DIV2);
+}
+
+static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (speed == 10)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV50);
+	else if (speed == 100)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV5);
+	else if (speed == 1000)
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+			     RK3528_GMAC1_CLK_RGMII_DIV1);
+	else
+		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+	unsigned int reg, val;
+
+	if (speed == 10)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 :
+					  RK3528_GMAC0_CLK_RMII_DIV20;
+	else if (speed == 100)
+		val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 :
+					  RK3528_GMAC0_CLK_RMII_DIV2;
+	else {
+		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+		return;
+	}
+
+	reg = bsp_priv->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 :
+				  RK3528_VO_GRF_GMAC_CON;
+
+	regmap_write(bsp_priv->grf, reg, val);
+}
+
+static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
+				       bool input, bool enable)
+{
+	unsigned int val;
+
+	if (bsp_priv->id == 1) {
+		val = input ? RK3528_GMAC1_CLK_SELECT_IO :
+			      RK3528_GMAC1_CLK_SELECT_CRU;
+		val |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+				RK3528_GMAC1_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+	} else {
+		val = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+			       RK3528_GMAC0_CLK_RMII_GATE;
+		regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON, val);
+	}
+}
+
+static const struct rk_gmac_ops rk3528_ops = {
+	.set_to_rgmii = rk3528_set_to_rgmii,
+	.set_to_rmii = rk3528_set_to_rmii,
+	.set_rgmii_speed = rk3528_set_rgmii_speed,
+	.set_rmii_speed = rk3528_set_rmii_speed,
+	.set_clock_selection = rk3528_set_clock_selection,
+	.regs_valid = true,
+	.regs = {
+		0xffbd0000, /* gmac0 */
+		0xffbe0000, /* gmac1 */
+		0x0, /* sentinel */
+	},
+};
+
 #define RK3568_GRF_GMAC0_CON0		0x0380
 #define RK3568_GRF_GMAC0_CON1		0x0384
 #define RK3568_GRF_GMAC1_CON0		0x0388
@@ -1819,6 +1950,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
 	{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
 	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
 	{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
+	{ .compatible = "rockchip,rk3528-gmac", .data = &rk3528_ops },
 	{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
 	{ .compatible = "rockchip,rk3576-gmac", .data = &rk3576_ops },
 	{ .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },
-- 
2.49.0



From jonas at kwiboo.se  Wed Mar 19 14:44:07 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:07 +0000
Subject: [PATCH net-next v3 3/5] net: stmmac: dwmac-rk: Move integrated_phy_powerup/down functions
In-Reply-To: <20250319214415.3086027-1-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
Message-ID: <20250319214415.3086027-4-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these SoCs.

Move the rk_gmac_integrated_phy_powerup/down functions to top of the
file to prepare for them to be called directly by a GMAC variant
specific powerup/down operation.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v3:
- No change
Changes in v2:
- New patch
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 88 +++++++++----------
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index dfb4668db4ee..0321befed0d3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -92,6 +92,50 @@ struct rk_priv_data {
 	(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
 	 ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
 
+#define RK_GRF_MACPHY_CON0		0xb00
+#define RK_GRF_MACPHY_CON1		0xb04
+#define RK_GRF_MACPHY_CON2		0xb08
+#define RK_GRF_MACPHY_CON3		0xb0c
+
+#define RK_MACPHY_ENABLE		GRF_BIT(0)
+#define RK_MACPHY_DISABLE		GRF_CLR_BIT(0)
+#define RK_MACPHY_CFG_CLK_50M		GRF_BIT(14)
+#define RK_GMAC2PHY_RMII_MODE		(GRF_BIT(6) | GRF_CLR_BIT(7))
+#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
+#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
+
+static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
+{
+	if (priv->ops->integrated_phy_powerup)
+		priv->ops->integrated_phy_powerup(priv);
+
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
+
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
+
+	if (priv->phy_reset) {
+		/* PHY needs to be disabled before trying to reset it */
+		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
+		if (priv->phy_reset)
+			reset_control_assert(priv->phy_reset);
+		usleep_range(10, 20);
+		if (priv->phy_reset)
+			reset_control_deassert(priv->phy_reset);
+		usleep_range(10, 20);
+		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
+		msleep(30);
+	}
+}
+
+static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
+{
+	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
+	if (priv->phy_reset)
+		reset_control_assert(priv->phy_reset);
+}
+
 #define PX30_GRF_GMAC_CON1		0x0904
 
 /* PX30_GRF_GMAC_CON1 */
@@ -1463,50 +1507,6 @@ static const struct rk_gmac_ops rv1126_ops = {
 	.set_rmii_speed = rv1126_set_rmii_speed,
 };
 
-#define RK_GRF_MACPHY_CON0		0xb00
-#define RK_GRF_MACPHY_CON1		0xb04
-#define RK_GRF_MACPHY_CON2		0xb08
-#define RK_GRF_MACPHY_CON3		0xb0c
-
-#define RK_MACPHY_ENABLE		GRF_BIT(0)
-#define RK_MACPHY_DISABLE		GRF_CLR_BIT(0)
-#define RK_MACPHY_CFG_CLK_50M		GRF_BIT(14)
-#define RK_GMAC2PHY_RMII_MODE		(GRF_BIT(6) | GRF_CLR_BIT(7))
-#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
-#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
-
-static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
-{
-	if (priv->ops->integrated_phy_powerup)
-		priv->ops->integrated_phy_powerup(priv);
-
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
-
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
-
-	if (priv->phy_reset) {
-		/* PHY needs to be disabled before trying to reset it */
-		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
-		if (priv->phy_reset)
-			reset_control_assert(priv->phy_reset);
-		usleep_range(10, 20);
-		if (priv->phy_reset)
-			reset_control_deassert(priv->phy_reset);
-		usleep_range(10, 20);
-		regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
-		msleep(30);
-	}
-}
-
-static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
-{
-	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
-	if (priv->phy_reset)
-		reset_control_assert(priv->phy_reset);
-}
-
 static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
 {
 	struct rk_priv_data *bsp_priv = plat->bsp_priv;
-- 
2.49.0



From jonas at kwiboo.se  Wed Mar 19 14:44:08 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:08 +0000
Subject: [PATCH net-next v3 4/5] net: stmmac: dwmac-rk: Add integrated_phy_powerdown operation
In-Reply-To: <20250319214415.3086027-1-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
Message-ID: <20250319214415.3086027-5-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these newer SoCs.

Add a new integrated_phy_powerdown operation and change the call chain
for integrated_phy_powerup to prepare support for the integrated PHY
found in these newer SoCs.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v3:
- No change
Changes in v2:
- New patch
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 26 +++++++++++--------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 0321befed0d3..3673abd65302 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,6 +33,7 @@ struct rk_gmac_ops {
 	void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
 				    bool enable);
 	void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
+	void (*integrated_phy_powerdown)(struct rk_priv_data *bsp_priv);
 	bool php_grf_required;
 	bool regs_valid;
 	u32 regs[];
@@ -104,11 +105,8 @@ struct rk_priv_data {
 #define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
 #define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
 
-static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
+static void rk_gmac_integrated_ephy_powerup(struct rk_priv_data *priv)
 {
-	if (priv->ops->integrated_phy_powerup)
-		priv->ops->integrated_phy_powerup(priv);
-
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
 
@@ -129,7 +127,7 @@ static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
 	}
 }
 
-static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
+static void rk_gmac_integrated_ephy_powerdown(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
 	if (priv->phy_reset)
@@ -368,6 +366,8 @@ static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK3228_GRF_CON_MUX,
 		     RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY);
+
+	rk_gmac_integrated_ephy_powerup(priv);
 }
 
 static const struct rk_gmac_ops rk3228_ops = {
@@ -375,7 +375,8 @@ static const struct rk_gmac_ops rk3228_ops = {
 	.set_to_rmii = rk3228_set_to_rmii,
 	.set_rgmii_speed = rk3228_set_rgmii_speed,
 	.set_rmii_speed = rk3228_set_rmii_speed,
-	.integrated_phy_powerup =  rk3228_integrated_phy_powerup,
+	.integrated_phy_powerup = rk3228_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown,
 };
 
 #define RK3288_GRF_SOC_CON1	0x0248
@@ -601,6 +602,8 @@ static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv)
 {
 	regmap_write(priv->grf, RK3328_GRF_MACPHY_CON1,
 		     RK3328_MACPHY_RMII_MODE);
+
+	rk_gmac_integrated_ephy_powerup(priv);
 }
 
 static const struct rk_gmac_ops rk3328_ops = {
@@ -608,7 +611,8 @@ static const struct rk_gmac_ops rk3328_ops = {
 	.set_to_rmii = rk3328_set_to_rmii,
 	.set_rgmii_speed = rk3328_set_rgmii_speed,
 	.set_rmii_speed = rk3328_set_rmii_speed,
-	.integrated_phy_powerup =  rk3328_integrated_phy_powerup,
+	.integrated_phy_powerup = rk3328_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown,
 };
 
 #define RK3366_GRF_SOC_CON6	0x0418
@@ -1802,16 +1806,16 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
 
 	pm_runtime_get_sync(dev);
 
-	if (bsp_priv->integrated_phy)
-		rk_gmac_integrated_phy_powerup(bsp_priv);
+	if (bsp_priv->integrated_phy && bsp_priv->ops->integrated_phy_powerup)
+		bsp_priv->ops->integrated_phy_powerup(bsp_priv);
 
 	return 0;
 }
 
 static void rk_gmac_powerdown(struct rk_priv_data *gmac)
 {
-	if (gmac->integrated_phy)
-		rk_gmac_integrated_phy_powerdown(gmac);
+	if (gmac->integrated_phy && gmac->ops->integrated_phy_powerdown)
+		gmac->ops->integrated_phy_powerdown(gmac);
 
 	pm_runtime_put_sync(&gmac->pdev->dev);
 
-- 
2.49.0



From jonas at kwiboo.se  Wed Mar 19 14:44:09 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Wed, 19 Mar 2025 21:44:09 +0000
Subject: [PATCH net-next v3 5/5] net: stmmac: dwmac-rk: Add initial support for RK3528 integrated PHY
In-Reply-To: <20250319214415.3086027-1-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
Message-ID: <20250319214415.3086027-6-jonas@kwiboo.se>

Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
the integrated PHY on RK3228/RK3328. Current powerup/down operation is
not compatible with the integrated PHY found in these newer SoCs.

Add operations to powerup/down the integrated PHY found in RK3528.
Use helpers that can be used by other GMAC variants in the future.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
Changes in v3:
- No change
Changes in v2:
- New patch

This is enough to power up the integrated PHY on RK3528 for MDIO/MII.
However, a PHY driver is still missing and I do not have any RK3528
board that make use of this MAC and PHY, so something that can be
improved upon in the future.
---
 .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 3673abd65302..700858ff6f7c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -134,6 +134,35 @@ static void rk_gmac_integrated_ephy_powerdown(struct rk_priv_data *priv)
 		reset_control_assert(priv->phy_reset);
 }
 
+#define RK_FEPHY_SHUTDOWN		GRF_BIT(1)
+#define RK_FEPHY_POWERUP		GRF_CLR_BIT(1)
+#define RK_FEPHY_INTERNAL_RMII_SEL	GRF_BIT(6)
+#define RK_FEPHY_24M_CLK_SEL		(GRF_BIT(8) | GRF_BIT(9))
+#define RK_FEPHY_PHY_ID			GRF_BIT(11)
+
+static void rk_gmac_integrated_fephy_powerup(struct rk_priv_data *priv,
+					     unsigned int reg)
+{
+	reset_control_assert(priv->phy_reset);
+	usleep_range(20, 30);
+
+	regmap_write(priv->grf, reg,
+		     RK_FEPHY_POWERUP |
+		     RK_FEPHY_INTERNAL_RMII_SEL |
+		     RK_FEPHY_24M_CLK_SEL |
+		     RK_FEPHY_PHY_ID);
+	usleep_range(10000, 12000);
+
+	reset_control_deassert(priv->phy_reset);
+	usleep_range(50000, 60000);
+}
+
+static void rk_gmac_integrated_fephy_powerdown(struct rk_priv_data *priv,
+					       unsigned int reg)
+{
+	regmap_write(priv->grf, reg, RK_FEPHY_SHUTDOWN);
+}
+
 #define PX30_GRF_GMAC_CON1		0x0904
 
 /* PX30_GRF_GMAC_CON1 */
@@ -993,12 +1022,24 @@ static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
 	}
 }
 
+static void rk3528_integrated_phy_powerup(struct rk_priv_data *bsp_priv)
+{
+	rk_gmac_integrated_fephy_powerup(bsp_priv, RK3528_VO_GRF_MACPHY_CON0);
+}
+
+static void rk3528_integrated_phy_powerdown(struct rk_priv_data *bsp_priv)
+{
+	rk_gmac_integrated_fephy_powerdown(bsp_priv, RK3528_VO_GRF_MACPHY_CON0);
+}
+
 static const struct rk_gmac_ops rk3528_ops = {
 	.set_to_rgmii = rk3528_set_to_rgmii,
 	.set_to_rmii = rk3528_set_to_rmii,
 	.set_rgmii_speed = rk3528_set_rgmii_speed,
 	.set_rmii_speed = rk3528_set_rmii_speed,
 	.set_clock_selection = rk3528_set_clock_selection,
+	.integrated_phy_powerup = rk3528_integrated_phy_powerup,
+	.integrated_phy_powerdown = rk3528_integrated_phy_powerdown,
 	.regs_valid = true,
 	.regs = {
 		0xffbd0000, /* gmac0 */
-- 
2.49.0



From arnd at arndb.de  Wed Mar 19 14:45:57 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 19 Mar 2025 22:45:57 +0100
Subject: [PATCH v2] firmware: config: ti-sci: Default set to ARCH_K3 for the ti sci
 driver
In-Reply-To: <20250220-ti-firmware-v2-1-ff26883c6ce9@baylibre.com>
References: <20250220-ti-firmware-v2-1-ff26883c6ce9@baylibre.com>
Message-ID: <c506a805-9221-4afe-8d98-af0ca97a1fd2@app.fastmail.com>

On Thu, Feb 20, 2025, at 14:31, Guillaume La Roque wrote:
> With ARCH_K3=y we cannot enable TI_SCI_PROTOCOL=m because
> ARCH_K3 selects TI_SCI_PROTOCOL.
>
> Modify the logic to enable TI_SCI_PROTOCOL by default when ARCH_K3=y
> allowing us to submit a future patch to remove select on ARCH_K3 without
> breaking existing users.
>
> Signed-off-by: Guillaume La Roque <glaroque at baylibre.com>
> ---
> Link to comment done on last serie [1] we come back on first version of
> series[2] to not use imply but set deps on ARCH_K3 in driver directly.
> An other patch will be sent to update Kconfig.platform when this patch
> is merged.

I just merged the patch and hadn't seen the earlier discussion,
just two small notes from me:

- thanks for doing it this way instead of the backwards 'imply'
- there is really no need to split it into two steps, since the
  change to the Kconfig.platforms file logically goes with this
  one and I would merge both through the SoC tree, having it
  as a single patch would make sense.

        Arnd


From catalin.marinas at arm.com  Wed Mar 19 14:48:31 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 19 Mar 2025 21:48:31 +0000
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <20250319192246.GQ9311@nvidia.com>
References: <8634fcnh0n.wl-maz@kernel.org>
 <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org>
 <20250318125527.GP9311@nvidia.com>
 <Z9nJ42PllG8a7AY7@linux.dev>
 <20250318230909.GD9311@nvidia.com>
 <Z9pryQwy2iwa2bpJ@linux.dev>
 <20250319170429.GK9311@nvidia.com>
 <Z9sItt8BIgvbBY8M@arm.com>
 <20250319192246.GQ9311@nvidia.com>
Message-ID: <Z9s7r2JocpoM_t-m@arm.com>

On Wed, Mar 19, 2025 at 04:22:46PM -0300, Jason Gunthorpe wrote:
> On Wed, Mar 19, 2025 at 06:11:02PM +0000, Catalin Marinas wrote:
> > On Wed, Mar 19, 2025 at 02:04:29PM -0300, Jason Gunthorpe wrote:
> > > On Wed, Mar 19, 2025 at 12:01:29AM -0700, Oliver Upton wrote:
> > > > You have a very good point that KVM is broken for cacheable PFNMAP'd
> > > > crap since we demote to something non-cacheable, and maybe that
> > > > deserves fixing first. Hopefully nobody notices that we've taken away
> > > > the toys...
> > > 
> > > Fixing it is either faulting all access attempts or mapping it
> > > cachable to the S2 (as this series is trying to do)..
> > 
> > As I replied earlier, it might be worth doing both - fault on !FWB
> > hardware (or rather reject the memslot creation), cacheable S2
> > otherwise.
> 
> I have no objection, Ankit are you able to make a failure patch?

I'd wait until the KVM maintainers have their say.

-- 
Catalin


From andrea.porta at suse.com  Wed Mar 19 14:52:21 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:21 +0100
Subject: [PATCH v8 00/13] Add support for RaspberryPi RP1 PCI device using a DT overlay
Message-ID: <cover.1742418429.git.andrea.porta@suse.com>

RP1 is an MFD chipset that acts as a south-bridge PCIe endpoint sporting
a pletora of subdevices (i.e.  Ethernet, USB host controller, I2C, PWM,
etc.) whose registers are all reachable starting from an offset from the
BAR address.  The main point here is that while the RP1 as an endpoint
itself is discoverable via usual PCI enumeraiton, the devices it contains
are not discoverable and must be declared e.g. via the devicetree.

This patchset is an attempt to provide a minimum infrastructure to allow
the RP1 chipset to be discovered and perpherals it contains to be added
from a devictree overlay loaded during RP1 PCI endpoint enumeration. To
ensure compatibility with downstream, a devicetree already comprising the
RP1 node is also provided, so it's not strictly necessary to use the
dynamically loaded overlay if the devicetree is already fully defined at
the origin.
To achieve this modularity, the RP1 node DT definitions are arranged by
file inclusion as per following schema (the arrow points to the includer,
see also [9]):
 
 rp1-pci.dtso         rp1.dtso
     ^                    ^
     |                    |
rp1-common.dtsi ----> rp1-nexus.dtsi ----> bcm2712-rpi-5-b-monolithic.dts
                                               ^
                                               |
                                           bcm2712-rpi-5-b.dts

Followup patches should add support for the several peripherals contained
in RP1.

This work is based upon dowstream drivers code and the proposal from RH
et al. (see [1] and [2]). A similar approach is also pursued in [3].

The patches are ordered as follows:

-PATCHES 1 to 4: add binding schemas for clock, gpio and RP1 peripherals.
 They are needed to support the other peripherals, e.g. the ethernet mac
 depends on a clock generated by RP1 and the phy is reset through the
 on-board gpio controller.

-PATCH 5 and 6: add clock and gpio device drivers.

-PATCH 7: the devicetree node describing the RP1 chipset. Please
 note that this patch should be taken by the same maintainer that will
 also take patch 8, since the definition it contains is possibly used
 by the dtso compiled in as binary blob and is closely coupled to the
 driver.

-PATCH 8: this is the main patch to support RP1 chipset. It can work
 either with a fully defined devicetree (i.e. one that already included
 the rp1 node since boot time) or with a runtime loaded dtb overlay
 which is linked as binary blob in the driver obj. This duality is
 useful to comply with both downstream and upstream needs (see [9]).
 The real dtso is in devicetree folder while the dtso in driver folder is
 just a placeholder to include the real dtso.
 In this way it is possible to check the dtso against dt-bindings.
 The reason why drivers/misc has been selected as containing folder
 for this driver can be seen in [6], [7] and [8].

-PATCH 9: the fully fledged devictree containing also the rp1 node.
 This devicetree is similar to the one downstream is using.

-PATCH 10 (OPTIONAL): this patch introduces a new scenario about how
 the rp1 node is specified and loaded in DT. On top of the base DT
 (without rp1 node), the fw loads this overlay and the end result is
 the same devicetree as in patch 9, which is then passed to the next
 stage (either the kernel or u-boot/bootloader).
 While this patch is not strictly necessary and can therefore be dropped
 (see [10]), it's not introducing much extra work and maybe can come
 in handy while debugging.
 
-PATCH 11: add the external clock node (used by RP1) to the main dts.

-PATCH 12: add the relevant kernel CONFIG_ options to defconfig.

-PATCH 13: enable CONFIG_OF_OVERLAY in order for 'make defconfig'
 to produce a configuration valid for the RP1 driver. Without this
 patch, the user has to explicitly enable it since the misc driver
 depends on OF_OVERLAY.

This patchset is also a first attempt to be more agnostic wrt hardware
description standards such as OF devicetree and ACPI, where 'agnostic'
means "using DT in coexistence with ACPI", as been already promoted
by e.g. AL (see [4]). Although there's currently no evidence it will also
run out of the box on purely ACPI system, it is a first step towards
that direction.

Many thanks,
Andrea della Porta

Links:
- [1]: https://lpc.events/event/17/contributions/1421/attachments/1337/2680/LPC2023%20Non-discoverable%20devices%20in%20PCI.pdf
- [2]: https://lore.kernel.org/lkml/20230419231155.GA899497-robh at kernel.org/t/
- [3]: https://lore.kernel.org/all/20240808154658.247873-1-herve.codina at bootlin.com/#t
- [4]: https://lore.kernel.org/all/73e05c77-6d53-4aae-95ac-415456ff0ae4 at lunn.ch/
- [5]: https://lore.kernel.org/all/20240626104544.14233-1-svarbanov at suse.de/
- [6]: https://lore.kernel.org/all/20240612140208.GC1504919 at google.com/
- [7]: https://lore.kernel.org/all/83f7fa09-d0e6-4f36-a27d-cee08979be2a at app.fastmail.com/
- [8]: https://lore.kernel.org/all/2024081356-mutable-everyday-6f9d at gregkh/
- [9]: https://lore.kernel.org/all/Z87wTfChRC5Ruwc0 at apocalypse/
- [10]: https://lore.kernel.org/all/CAMEGJJ0f4YUgdWBhxvQ_dquZHztve9KO7pvQjoDWJ3=zd3cgcg at mail.gmail.com/#t

CHANGES IN V8


PATCH RELATED -------------------------------------------------

- This cover letter and patch 8 commit messages now have
  more details explaining the new DT include files organization.

- Added two new patches numbered 9 and 10 respectively dealing
  with the new DT inclusion schema.


BINDINGS ------------------------------------------------------

- Modified maintainer first name for get_maintainer.pl to be able
  to retrieve the entire name correctly from the .yaml files. As
  a consequence, MAINTAINERS file does not need an entry for
  schemas anymore.

- pci1de4,1.yaml: Added a statement about the ints activation
  type for rp1 peripherals: only level high or rising edge
  are supported since they all are active high only.

RP1 PINCTRL DRIVER ---------------------------------

- Added GPIOCHIP_IRQ_RESOURCE_HELPERS.


RP1 CLOCK DRIVER ------------------------------------

- Added PLL_DIV_INVALID to denote invalid values in pll_sec_div_table[].

- Dropped some empty lines.

- Changed TODO comment to better reflect the intent

- Changed a WARN() into WARN_ONCE() to prevent flooding

- Fixed the hard limit condition "rate > 4000000000ll" in
  rp1_clock_set_rate_and_parent() to "rate > data->max_freq", in order
  to check against the limit specific for that clock.

- Style change: dropped an empty line


RP1 MISC DRIVER -----------------------------------

- rp1_pci.c: Added a suitable dev_err() warning in case
  of_platform_default_populate() fails.

- rp1_pci.c: Fixed the mismatching %d vs %u in dev_dbg().

- rp1_pci.c: Changed the error string printed on pci_alloc_irq_vectors()
  failure, plus minor cosmetic changes such as capitalization of error
  strings. 

- rp1_pci.c: Changed dev_err() to dev_err_probe() where appropriate.

- rp1_pci.c: Updated the year in the top header copyright notice,
  also added a newline between lines. Also, changed the error string
  'Not initialised' to 'Not initialized'.

- rp1_pci.c: Changed MODULE_DESCRIPTION() string to match the one
  in Kconfig.

- rp1-pci.dtso: Minor change to the top header comment to unify
  the multi-line comment style.

- Kconfig: Changed description in the header comment to match the
  description in the tristate option.


Andrea della Porta (13):
  dt-bindings: clock: Add RaspberryPi RP1 clock bindings
  dt-bindings: pinctrl: Add RaspberryPi RP1 gpio/pinctrl/pinmux bindings
  dt-bindings: pci: Add common schema for devices accessible through PCI
    BARs
  dt-bindings: misc: Add device specific bindings for RaspberryPi RP1
  clk: rp1: Add support for clocks provided by RP1
  pinctrl: rp1: Implement RaspberryPi RP1 gpio support
  arm64: dts: rp1: Add support for RaspberryPi's RP1 device
  misc: rp1: RaspberryPi RP1 misc driver
  arm64: dts: Add board DTS for Rpi5 which includes RP1 node
  arm64: dts: Add overlay for RP1 device
  arm64: dts: bcm2712: Add external clock for RP1 chipset on Rpi5
  arm64: defconfig: Enable RP1 misc/clock/gpio drivers
  arm64: defconfig: Enable OF_OVERLAY option

 .../clock/raspberrypi,rp1-clocks.yaml         |   58 +
 .../devicetree/bindings/misc/pci1de4,1.yaml   |  137 ++
 .../devicetree/bindings/pci/pci-ep-bus.yaml   |   58 +
 .../pinctrl/raspberrypi,rp1-gpio.yaml         |  198 +++
 MAINTAINERS                                   |    8 +
 arch/arm64/boot/dts/broadcom/Makefile         |    4 +-
 .../broadcom/bcm2712-rpi-5-b-monolithic.dts   |    8 +
 .../boot/dts/broadcom/bcm2712-rpi-5-b.dts     |    7 +
 arch/arm64/boot/dts/broadcom/rp1-common.dtsi  |   42 +
 arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi   |   14 +
 arch/arm64/boot/dts/broadcom/rp1.dtso         |   11 +
 arch/arm64/configs/defconfig                  |    4 +
 drivers/clk/Kconfig                           |    9 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/clk-rp1.c                         | 1512 +++++++++++++++++
 drivers/misc/Kconfig                          |    1 +
 drivers/misc/Makefile                         |    1 +
 drivers/misc/rp1/Kconfig                      |   20 +
 drivers/misc/rp1/Makefile                     |    3 +
 drivers/misc/rp1/rp1-pci.dtso                 |   25 +
 drivers/misc/rp1/rp1_pci.c                    |  333 ++++
 drivers/pci/quirks.c                          |    1 +
 drivers/pinctrl/Kconfig                       |   11 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/pinctrl-rp1.c                 |  790 +++++++++
 .../clock/raspberrypi,rp1-clocks.h            |   61 +
 include/linux/pci_ids.h                       |    3 +
 27 files changed, 3320 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
 create mode 100644 Documentation/devicetree/bindings/misc/pci1de4,1.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
 create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-monolithic.dts
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1-common.dtsi
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1.dtso
 create mode 100644 drivers/clk/clk-rp1.c
 create mode 100644 drivers/misc/rp1/Kconfig
 create mode 100644 drivers/misc/rp1/Makefile
 create mode 100644 drivers/misc/rp1/rp1-pci.dtso
 create mode 100644 drivers/misc/rp1/rp1_pci.c
 create mode 100644 drivers/pinctrl/pinctrl-rp1.c
 create mode 100644 include/dt-bindings/clock/raspberrypi,rp1-clocks.h

-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:23 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:23 +0100
Subject: [PATCH v8 02/13] dt-bindings: pinctrl: Add RaspberryPi RP1 gpio/pinctrl/pinmux bindings
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <699a42204afbb4772176051a83363d0ac7fd7c99.1742418429.git.andrea.porta@suse.com>

Add device tree bindings for the gpio/pin/mux controller that is part of
the RP1 multi function device, and relative entries in MAINTAINERS file.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 .../pinctrl/raspberrypi,rp1-gpio.yaml         | 198 ++++++++++++++++++
 1 file changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
new file mode 100644
index 000000000000..eec9a9b58542
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/raspberrypi,rp1-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RaspberryPi RP1 GPIO/Pinconf/Pinmux Controller submodule
+
+maintainers:
+  - A. della Porta <andrea.porta at suse.com>
+
+description:
+  The RP1 chipset is a Multi Function Device containing, among other
+  sub-peripherals, a gpio/pinconf/mux controller whose 54 pins are grouped
+  into 3 banks.
+  It works also as an interrupt controller for those gpios.
+
+properties:
+  compatible:
+    const: raspberrypi,rp1-gpio
+
+  reg:
+    maxItems: 3
+    description: One reg specifier for each one of the 3 pin banks.
+
+  '#gpio-cells':
+    description: The first cell is the pin number and the second cell is used
+      to specify the flags (see include/dt-bindings/gpio/gpio.h).
+    const: 2
+
+  gpio-controller: true
+
+  gpio-ranges:
+    maxItems: 1
+
+  gpio-line-names:
+    maxItems: 54
+
+  interrupts:
+    maxItems: 3
+    description: One interrupt specifier for each one of the 3 pin banks.
+
+  '#interrupt-cells':
+    description:
+      Specifies the Bank number [0, 1, 2] and Flags as defined in
+      include/dt-bindings/interrupt-controller/irq.h.
+    const: 2
+
+  interrupt-controller: true
+
+patternProperties:
+  '-state$':
+    oneOf:
+      - $ref: '#/$defs/raspberrypi-rp1-state'
+      - patternProperties:
+          '-pins$':
+            $ref: '#/$defs/raspberrypi-rp1-state'
+        additionalProperties: false
+
+$defs:
+  raspberrypi-rp1-state:
+    allOf:
+      - $ref: pincfg-node.yaml#
+      - $ref: pinmux-node.yaml#
+
+    description:
+      Pin controller client devices use pin configuration subnodes (children
+      and grandchildren) for desired pin configuration.
+      Client device subnodes use below standard properties.
+
+    properties:
+      pins:
+        description:
+          List of gpio pins affected by the properties specified in this
+          subnode.
+        items:
+          pattern: '^gpio([0-9]|[1-4][0-9]|5[0-3])$'
+
+      function:
+        enum: [ alt0, alt1, alt2, alt3, alt4, gpio, alt6, alt7, alt8, none,
+                aaud, dcd0, dpi, dsi0_te_ext, dsi1_te_ext, dsr0, dtr0, gpclk0,
+                gpclk1, gpclk2, gpclk3, gpclk4, gpclk5, i2c0, i2c1, i2c2, i2c3,
+                i2c4, i2c5, i2c6, i2s0, i2s1, i2s2, ir, mic, pcie_clkreq_n,
+                pio, proc_rio, pwm0, pwm1, ri0, sd0, sd1, spi0, spi1, spi2,
+                spi3, spi4, spi5, spi6, spi7, spi8, uart0, uart1, uart2, uart3,
+                uart4, uart5, vbus0, vbus1, vbus2, vbus3 ]
+
+        description:
+          Specify the alternative function to be configured for the specified
+          pins.
+
+      bias-disable: true
+      bias-pull-down: true
+      bias-pull-up: true
+      input-enable: true
+      input-schmitt-enable: true
+      output-enable: true
+      output-high: true
+      output-low: true
+      slew-rate:
+        description: 0 is slow slew rate, 1 is fast slew rate
+        enum: [ 0, 1 ]
+      drive-strength:
+        enum: [ 2, 4, 8, 12 ]
+
+    additionalProperties: false
+
+allOf:
+  - $ref: pinctrl.yaml#
+
+required:
+  - reg
+  - compatible
+  - '#gpio-cells'
+  - gpio-controller
+  - interrupts
+  - '#interrupt-cells'
+  - interrupt-controller
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    rp1 {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        rp1_gpio: pinctrl at c0400d0000 {
+            reg = <0xc0 0x400d0000  0x0 0xc000>,
+                  <0xc0 0x400e0000  0x0 0xc000>,
+                  <0xc0 0x400f0000  0x0 0xc000>;
+            compatible = "raspberrypi,rp1-gpio";
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+            interrupts = <0 IRQ_TYPE_LEVEL_HIGH>,
+                         <1 IRQ_TYPE_LEVEL_HIGH>,
+                         <2 IRQ_TYPE_LEVEL_HIGH>;
+            gpio-line-names =
+                   "ID_SDA", // GPIO0
+                   "ID_SCL", // GPIO1
+                   "GPIO2", "GPIO3", "GPIO4", "GPIO5", "GPIO6",
+                   "GPIO7", "GPIO8", "GPIO9", "GPIO10", "GPIO11",
+                   "GPIO12", "GPIO13", "GPIO14", "GPIO15", "GPIO16",
+                   "GPIO17", "GPIO18", "GPIO19", "GPIO20", "GPIO21",
+                   "GPIO22", "GPIO23", "GPIO24", "GPIO25", "GPIO26",
+                   "GPIO27",
+                   "PCIE_RP1_WAKE", // GPIO28
+                   "FAN_TACH", // GPIO29
+                   "HOST_SDA", // GPIO30
+                   "HOST_SCL", // GPIO31
+                   "ETH_RST_N", // GPIO32
+                   "", // GPIO33
+                   "CD0_IO0_MICCLK", // GPIO34
+                   "CD0_IO0_MICDAT0", // GPIO35
+                   "RP1_PCIE_CLKREQ_N", // GPIO36
+                   "", // GPIO37
+                   "CD0_SDA", // GPIO38
+                   "CD0_SCL", // GPIO39
+                   "CD1_SDA", // GPIO40
+                   "CD1_SCL", // GPIO41
+                   "USB_VBUS_EN", // GPIO42
+                   "USB_OC_N", // GPIO43
+                   "RP1_STAT_LED", // GPIO44
+                   "FAN_PWM", // GPIO45
+                   "CD1_IO0_MICCLK", // GPIO46
+                   "2712_WAKE", // GPIO47
+                   "CD1_IO1_MICDAT1", // GPIO48
+                   "EN_MAX_USB_CUR", // GPIO49
+                   "", // GPIO50
+                   "", // GPIO51
+                   "", // GPIO52
+                   ""; // GPIO53
+
+            rp1-i2s0-default-state {
+                function = "i2s0";
+                pins = "gpio18", "gpio19", "gpio20", "gpio21";
+                bias-disable;
+            };
+
+            rp1-uart0-default-state {
+                txd-pins {
+                    function = "uart0";
+                    pins = "gpio14";
+                    bias-disable;
+                };
+
+                rxd-pins {
+                    function = "uart0";
+                    pins = "gpio15";
+                    bias-pull-up;
+                };
+            };
+        };
+    };
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:25 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:25 +0100
Subject: [PATCH v8 04/13] dt-bindings: misc: Add device specific bindings for RaspberryPi RP1
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <e220e2ee4f64d99b44b739f1d10a5a4cb28132e8.1742418429.git.andrea.porta@suse.com>

The RP1 is a MFD that exposes its peripherals through PCI BARs. This
schema is intended as minimal support for the clock generator and
gpio controller peripherals which are accessible through BAR1.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 .../devicetree/bindings/misc/pci1de4,1.yaml   | 137 ++++++++++++++++++
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/pci1de4,1.yaml

diff --git a/Documentation/devicetree/bindings/misc/pci1de4,1.yaml b/Documentation/devicetree/bindings/misc/pci1de4,1.yaml
new file mode 100644
index 000000000000..2f9a7a554ed8
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/pci1de4,1.yaml
@@ -0,0 +1,137 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/pci1de4,1.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RaspberryPi RP1 MFD PCI device
+
+maintainers:
+  - A. della Porta <andrea.porta at suse.com>
+
+description:
+  The RaspberryPi RP1 is a PCI multi function device containing
+  peripherals ranging from Ethernet to USB controller, I2C, SPI
+  and others.
+  The peripherals are accessed by addressing the PCI BAR1 region.
+
+allOf:
+  - $ref: /schemas/pci/pci-ep-bus.yaml
+
+properties:
+  compatible:
+    additionalItems: true
+    maxItems: 3
+    items:
+      - const: pci1de4,1
+
+  '#interrupt-cells':
+    const: 2
+    description: |
+      Specifies respectively the interrupt number and flags as defined
+      in include/dt-bindings/interrupt-controller/irq.h.
+      Since all interrupts are active high, only IRQ_TYPE_LEVEL_HIGH
+      and IRQ_TYPE_EDGE_RISING can be specified as type flags.
+      The supported values for the interrupt number are:
+        - IO BANK0: 0
+        - IO BANK1: 1
+        - IO BANK2: 2
+        - AUDIO IN: 3
+        - AUDIO OUT: 4
+        - PWM0: 5
+        - ETH: 6
+        - I2C0: 7
+        - I2C1: 8
+        - I2C2: 9
+        - I2C3: 10
+        - I2C4: 11
+        - I2C5: 12
+        - I2C6: 13
+        - I2S0: 14
+        - I2S1: 15
+        - I2S2: 16
+        - SDIO0: 17
+        - SDIO1: 18
+        - SPI0: 19
+        - SPI1: 20
+        - SPI2: 21
+        - SPI3: 22
+        - SPI4: 23
+        - SPI5: 24
+        - UART0: 25
+        - TIMER0: 26
+        - TIMER1: 27
+        - TIMER2: 28
+        - TIMER3: 29
+        - USB HOST0: 30
+        - USB HOST0-0: 31
+        - USB HOST0-1: 32
+        - USB HOST0-2: 33
+        - USB HOST0-3: 34
+        - USB HOST1: 35
+        - USB HOST1-0: 36
+        - USB HOST1-1: 37
+        - USB HOST1-2: 38
+        - USB HOST1-3: 39
+        - DMA: 40
+        - PWM1: 41
+        - UART1: 42
+        - UART2: 43
+        - UART3: 44
+        - UART4: 45
+        - UART5: 46
+        - MIPI0: 47
+        - MIPI1: 48
+        - VIDEO OUT: 49
+        - PIO0: 50
+        - PIO1: 51
+        - ADC FIFO: 52
+        - PCIE OUT: 53
+        - SPI6: 54
+        - SPI7: 55
+        - SPI8: 56
+        - PROC MISC: 57
+        - SYSCFG: 58
+        - CLOCKS DEFAULT: 59
+        - VBUSCTRL: 60
+
+  interrupt-controller: true
+
+unevaluatedProperties: false
+
+required:
+  - compatible
+  - '#interrupt-cells'
+  - interrupt-controller
+  - pci-ep-bus at 1
+
+examples:
+  - |
+    pci {
+        #address-cells = <3>;
+        #size-cells = <2>;
+
+        rp1 at 0,0 {
+            compatible = "pci1de4,1";
+            ranges = <0x01 0x00 0x00000000  0x82010000 0x00 0x00  0x00 0x400000>;
+            #address-cells = <3>;
+            #size-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+
+            pci_ep_bus: pci-ep-bus at 1 {
+                compatible = "simple-bus";
+                ranges = <0x00 0x40000000  0x01 0x00 0x00000000  0x00 0x00400000>;
+                dma-ranges = <0x10 0x00000000  0x43000000 0x10 0x00000000  0x10 0x00000000>;
+                #address-cells = <2>;
+                #size-cells = <2>;
+
+                rp1_clocks: clocks at 40018000 {
+                    compatible = "raspberrypi,rp1-clocks";
+                    reg = <0x00 0x40018000 0x0 0x10038>;
+                    #clock-cells = <1>;
+                    clocks = <&clk_rp1_xosc>;
+                };
+            };
+        };
+    };
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:22 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:22 +0100
Subject: [PATCH v8 01/13] dt-bindings: clock: Add RaspberryPi RP1 clock bindings
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <342a5ba676f7af34827cdd9ba8f10ba295c93022.1742418429.git.andrea.porta@suse.com>

Add device tree bindings for the clock generator found in RP1 multi
function device, and relative entries in MAINTAINERS file.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 .../clock/raspberrypi,rp1-clocks.yaml         | 58 ++++++++++++++++++
 .../clock/raspberrypi,rp1-clocks.h            | 61 +++++++++++++++++++
 2 files changed, 119 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
 create mode 100644 include/dt-bindings/clock/raspberrypi,rp1-clocks.h

diff --git a/Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml b/Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
new file mode 100644
index 000000000000..cc4491f7ee5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/raspberrypi,rp1-clocks.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/raspberrypi,rp1-clocks.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RaspberryPi RP1 clock generator
+
+maintainers:
+  - A. della Porta <andrea.porta at suse.com>
+
+description: |
+  The RP1 contains a clock generator designed as three PLLs (CORE, AUDIO,
+  VIDEO), and each PLL output can be programmed through dividers to generate
+  the clocks to drive the sub-peripherals embedded inside the chipset.
+
+  Link to datasheet:
+  https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf
+
+properties:
+  compatible:
+    const: raspberrypi,rp1-clocks
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+    description:
+      The available clocks are defined in
+      include/dt-bindings/clock/raspberrypi,rp1-clocks.h.
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/raspberrypi,rp1-clocks.h>
+
+    rp1 {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        clocks at c040018000 {
+            compatible = "raspberrypi,rp1-clocks";
+            reg = <0xc0 0x40018000 0x0 0x10038>;
+            #clock-cells = <1>;
+            clocks = <&clk_rp1_xosc>;
+        };
+    };
diff --git a/include/dt-bindings/clock/raspberrypi,rp1-clocks.h b/include/dt-bindings/clock/raspberrypi,rp1-clocks.h
new file mode 100644
index 000000000000..248efb895f35
--- /dev/null
+++ b/include/dt-bindings/clock/raspberrypi,rp1-clocks.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2021 Raspberry Pi Ltd.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_RASPBERRYPI_RP1
+#define __DT_BINDINGS_CLOCK_RASPBERRYPI_RP1
+
+#define RP1_PLL_SYS_CORE		0
+#define RP1_PLL_AUDIO_CORE		1
+#define RP1_PLL_VIDEO_CORE		2
+
+#define RP1_PLL_SYS			3
+#define RP1_PLL_AUDIO			4
+#define RP1_PLL_VIDEO			5
+
+#define RP1_PLL_SYS_PRI_PH		6
+#define RP1_PLL_SYS_SEC_PH		7
+#define RP1_PLL_AUDIO_PRI_PH		8
+
+#define RP1_PLL_SYS_SEC			9
+#define RP1_PLL_AUDIO_SEC		10
+#define RP1_PLL_VIDEO_SEC		11
+
+#define RP1_CLK_SYS			12
+#define RP1_CLK_SLOW_SYS		13
+#define RP1_CLK_DMA			14
+#define RP1_CLK_UART			15
+#define RP1_CLK_ETH			16
+#define RP1_CLK_PWM0			17
+#define RP1_CLK_PWM1			18
+#define RP1_CLK_AUDIO_IN		19
+#define RP1_CLK_AUDIO_OUT		20
+#define RP1_CLK_I2S			21
+#define RP1_CLK_MIPI0_CFG		22
+#define RP1_CLK_MIPI1_CFG		23
+#define RP1_CLK_PCIE_AUX		24
+#define RP1_CLK_USBH0_MICROFRAME	25
+#define RP1_CLK_USBH1_MICROFRAME	26
+#define RP1_CLK_USBH0_SUSPEND		27
+#define RP1_CLK_USBH1_SUSPEND		28
+#define RP1_CLK_ETH_TSU			29
+#define RP1_CLK_ADC			30
+#define RP1_CLK_SDIO_TIMER		31
+#define RP1_CLK_SDIO_ALT_SRC		32
+#define RP1_CLK_GP0			33
+#define RP1_CLK_GP1			34
+#define RP1_CLK_GP2			35
+#define RP1_CLK_GP3			36
+#define RP1_CLK_GP4			37
+#define RP1_CLK_GP5			38
+#define RP1_CLK_VEC			39
+#define RP1_CLK_DPI			40
+#define RP1_CLK_MIPI0_DPI		41
+#define RP1_CLK_MIPI1_DPI		42
+
+/* Extra PLL output channels - RP1B0 only */
+#define RP1_PLL_VIDEO_PRI_PH		43
+#define RP1_PLL_AUDIO_TERN		44
+
+#endif
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:24 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:24 +0100
Subject: [PATCH v8 03/13] dt-bindings: pci: Add common schema for devices accessible through PCI BARs
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <096ab7addb39e498e28ac2526c07157cc9327c42.1742418429.git.andrea.porta@suse.com>

Common YAML schema for devices that exports internal peripherals through
PCI BARs. The BARs are exposed as simple-buses through which the
peripherals can be accessed.

This is not intended to be used as a standalone binding, but should be
included by device specific bindings.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 .../devicetree/bindings/pci/pci-ep-bus.yaml   | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/pci-ep-bus.yaml

diff --git a/Documentation/devicetree/bindings/pci/pci-ep-bus.yaml b/Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
new file mode 100644
index 000000000000..78129712da87
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/pci-ep-bus.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/pci-ep-bus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common Properties for PCI MFD EP with Peripherals Addressable from BARs
+
+maintainers:
+  - A. della Porta  <andrea.porta at suse.com>
+
+description:
+  Define a generic node representing a PCI endpoint which contains several sub-
+  peripherals. The peripherals can be accessed through one or more BARs.
+  This common schema is intended to be referenced from device tree bindings, and
+  does not represent a device tree binding by itself.
+
+properties:
+  '#address-cells':
+    const: 3
+
+  '#size-cells':
+    const: 2
+
+  ranges:
+    minItems: 1
+    maxItems: 6
+    items:
+      maxItems: 8
+      additionalItems: true
+      items:
+        - maximum: 5  # The BAR number
+        - const: 0
+        - const: 0
+
+patternProperties:
+  '^pci-ep-bus@[0-5]$':
+    type: object
+    description:
+      One node for each BAR used by peripherals contained in the PCI endpoint.
+      Each node represent a bus on which peripherals are connected.
+      This allows for some segmentation, e.g. one peripheral is accessible
+      through BAR0 and another through BAR1, and you don't want the two
+      peripherals to be able to act on the other BAR. Alternatively, when
+      different peripherals need to share BARs, you can define only one node
+      and use 'ranges' property to map all the used BARs.
+
+    additionalProperties: true
+
+    properties:
+      compatible:
+        const: simple-bus
+
+    required:
+      - compatible
+
+additionalProperties: true
+...
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:26 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:26 +0100
Subject: [PATCH v8 05/13] clk: rp1: Add support for clocks provided by RP1
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <370137263691f4fc14928e4b378b27f75bfd0826.1742418429.git.andrea.porta@suse.com>

RaspberryPi RP1 is an MFD providing, among other peripherals, several
clock generators and PLLs that drives the sub-peripherals.
Add the driver to support the clock providers.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
---
 MAINTAINERS           |    5 +
 drivers/clk/Kconfig   |    9 +
 drivers/clk/Makefile  |    1 +
 drivers/clk/clk-rp1.c | 1512 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1527 insertions(+)
 create mode 100644 drivers/clk/clk-rp1.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 896a307fa065..75263700370d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19748,6 +19748,11 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
 F:	drivers/media/platform/raspberrypi/rp1-cfe/
 
+RASPBERRY PI RP1 PCI DRIVER
+M:	Andrea della Porta <andrea.porta at suse.com>
+S:	Maintained
+F:	drivers/clk/clk-rp1.c
+
 RC-CORE / LIRC FRAMEWORK
 M:	Sean Young <sean at mess.org>
 L:	linux-media at vger.kernel.org
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 713573b6c86c..cff90de71409 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -88,6 +88,15 @@ config COMMON_CLK_RK808
 	  These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
 	  Clkout1 is always on, Clkout2 can off by control register.
 
+config COMMON_CLK_RP1
+	tristate "Raspberry Pi RP1-based clock support"
+	depends on MISC_RP1 || COMPILE_TEST
+	default MISC_RP1
+	help
+	  Enable common clock framework support for Raspberry Pi RP1.
+	  This multi-function device has 3 main PLLs and several clock
+	  generators to drive the internal sub-peripherals.
+
 config COMMON_CLK_HI655X
 	tristate "Clock driver for Hi655x" if EXPERT
 	depends on (MFD_HI655X_PMIC || COMPILE_TEST)
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bf4bd45adc3a..ff3993ed7e09 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_CLK_LS1028A_PLLDIG)	+= clk-plldig.o
 obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
+obj-$(CONFIG_COMMON_CLK_RP1)            += clk-rp1.o
 obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SCMI)           += clk-scmi.o
diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c
new file mode 100644
index 000000000000..72c74e344c1d
--- /dev/null
+++ b/drivers/clk/clk-rp1.c
@@ -0,0 +1,1512 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Raspberry Pi Ltd.
+ *
+ * Clock driver for RP1 PCIe multifunction chip.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/units.h>
+
+#include <dt-bindings/clock/raspberrypi,rp1-clocks.h>
+
+#define PLL_SYS_OFFSET			0x08000
+#define PLL_SYS_CS			(PLL_SYS_OFFSET + 0x00)
+#define PLL_SYS_PWR			(PLL_SYS_OFFSET + 0x04)
+#define PLL_SYS_FBDIV_INT		(PLL_SYS_OFFSET + 0x08)
+#define PLL_SYS_FBDIV_FRAC		(PLL_SYS_OFFSET + 0x0c)
+#define PLL_SYS_PRIM			(PLL_SYS_OFFSET + 0x10)
+#define PLL_SYS_SEC			(PLL_SYS_OFFSET + 0x14)
+
+#define PLL_AUDIO_OFFSET		0x0c000
+#define PLL_AUDIO_CS			(PLL_AUDIO_OFFSET + 0x00)
+#define PLL_AUDIO_PWR			(PLL_AUDIO_OFFSET + 0x04)
+#define PLL_AUDIO_FBDIV_INT		(PLL_AUDIO_OFFSET + 0x08)
+#define PLL_AUDIO_FBDIV_FRAC		(PLL_AUDIO_OFFSET + 0x0c)
+#define PLL_AUDIO_PRIM			(PLL_AUDIO_OFFSET + 0x10)
+#define PLL_AUDIO_SEC			(PLL_AUDIO_OFFSET + 0x14)
+#define PLL_AUDIO_TERN			(PLL_AUDIO_OFFSET + 0x18)
+
+#define PLL_VIDEO_OFFSET		0x10000
+#define PLL_VIDEO_CS			(PLL_VIDEO_OFFSET + 0x00)
+#define PLL_VIDEO_PWR			(PLL_VIDEO_OFFSET + 0x04)
+#define PLL_VIDEO_FBDIV_INT		(PLL_VIDEO_OFFSET + 0x08)
+#define PLL_VIDEO_FBDIV_FRAC		(PLL_VIDEO_OFFSET + 0x0c)
+#define PLL_VIDEO_PRIM			(PLL_VIDEO_OFFSET + 0x10)
+#define PLL_VIDEO_SEC			(PLL_VIDEO_OFFSET + 0x14)
+
+#define GPCLK_OE_CTRL			0x00000
+
+#define CLK_SYS_OFFSET			0x00014
+#define CLK_SYS_CTRL			(CLK_SYS_OFFSET + 0x00)
+#define CLK_SYS_DIV_INT			(CLK_SYS_OFFSET + 0x04)
+#define CLK_SYS_SEL			(CLK_SYS_OFFSET + 0x0c)
+
+#define CLK_SLOW_OFFSET			0x00024
+#define CLK_SLOW_SYS_CTRL		(CLK_SLOW_OFFSET + 0x00)
+#define CLK_SLOW_SYS_DIV_INT		(CLK_SLOW_OFFSET + 0x04)
+#define CLK_SLOW_SYS_SEL		(CLK_SLOW_OFFSET + 0x0c)
+
+#define CLK_DMA_OFFSET			0x00044
+#define CLK_DMA_CTRL			(CLK_DMA_OFFSET + 0x00)
+#define CLK_DMA_DIV_INT			(CLK_DMA_OFFSET + 0x04)
+#define CLK_DMA_SEL			(CLK_DMA_OFFSET + 0x0c)
+
+#define CLK_UART_OFFSET			0x00054
+#define CLK_UART_CTRL			(CLK_UART_OFFSET + 0x00)
+#define CLK_UART_DIV_INT		(CLK_UART_OFFSET + 0x04)
+#define CLK_UART_SEL			(CLK_UART_OFFSET + 0x0c)
+
+#define CLK_ETH_OFFSET			0x00064
+#define CLK_ETH_CTRL			(CLK_ETH_OFFSET + 0x00)
+#define CLK_ETH_DIV_INT			(CLK_ETH_OFFSET + 0x04)
+#define CLK_ETH_SEL			(CLK_ETH_OFFSET + 0x0c)
+
+#define CLK_PWM0_OFFSET			0x00074
+#define CLK_PWM0_CTRL			(CLK_PWM0_OFFSET + 0x00)
+#define CLK_PWM0_DIV_INT		(CLK_PWM0_OFFSET + 0x04)
+#define CLK_PWM0_DIV_FRAC		(CLK_PWM0_OFFSET + 0x08)
+#define CLK_PWM0_SEL			(CLK_PWM0_OFFSET + 0x0c)
+
+#define CLK_PWM1_OFFSET			0x00084
+#define CLK_PWM1_CTRL			(CLK_PWM1_OFFSET + 0x00)
+#define CLK_PWM1_DIV_INT		(CLK_PWM1_OFFSET + 0x04)
+#define CLK_PWM1_DIV_FRAC		(CLK_PWM1_OFFSET + 0x08)
+#define CLK_PWM1_SEL			(CLK_PWM1_OFFSET + 0x0c)
+
+#define CLK_AUDIO_IN_OFFSET		0x00094
+#define CLK_AUDIO_IN_CTRL		(CLK_AUDIO_IN_OFFSET + 0x00)
+#define CLK_AUDIO_IN_DIV_INT		(CLK_AUDIO_IN_OFFSET + 0x04)
+#define CLK_AUDIO_IN_SEL		(CLK_AUDIO_IN_OFFSET + 0x0c)
+
+#define CLK_AUDIO_OUT_OFFSET		0x000a4
+#define CLK_AUDIO_OUT_CTRL		(CLK_AUDIO_OUT_OFFSET + 0x00)
+#define CLK_AUDIO_OUT_DIV_INT		(CLK_AUDIO_OUT_OFFSET + 0x04)
+#define CLK_AUDIO_OUT_SEL		(CLK_AUDIO_OUT_OFFSET + 0x0c)
+
+#define CLK_I2S_OFFSET			0x000b4
+#define CLK_I2S_CTRL			(CLK_I2S_OFFSET + 0x00)
+#define CLK_I2S_DIV_INT			(CLK_I2S_OFFSET + 0x04)
+#define CLK_I2S_SEL			(CLK_I2S_OFFSET + 0x0c)
+
+#define CLK_MIPI0_CFG_OFFSET		0x000c4
+#define CLK_MIPI0_CFG_CTRL		(CLK_MIPI0_CFG_OFFSET + 0x00)
+#define CLK_MIPI0_CFG_DIV_INT		(CLK_MIPI0_CFG_OFFSET + 0x04)
+#define CLK_MIPI0_CFG_SEL		(CLK_MIPI0_CFG_OFFSET + 0x0c)
+
+#define CLK_MIPI1_CFG_OFFSET		0x000d4
+#define CLK_MIPI1_CFG_CTRL		(CLK_MIPI1_CFG_OFFSET + 0x00)
+#define CLK_MIPI1_CFG_DIV_INT		(CLK_MIPI1_CFG_OFFSET + 0x04)
+#define CLK_MIPI1_CFG_SEL		(CLK_MIPI1_CFG_OFFSET + 0x0c)
+
+#define CLK_PCIE_AUX_OFFSET		0x000e4
+#define CLK_PCIE_AUX_CTRL		(CLK_PCIE_AUX_OFFSET + 0x00)
+#define CLK_PCIE_AUX_DIV_INT		(CLK_PCIE_AUX_OFFSET + 0x04)
+#define CLK_PCIE_AUX_SEL		(CLK_PCIE_AUX_OFFSET + 0x0c)
+
+#define CLK_USBH0_MICROFRAME_OFFSET	0x000f4
+#define CLK_USBH0_MICROFRAME_CTRL	(CLK_USBH0_MICROFRAME_OFFSET + 0x00)
+#define CLK_USBH0_MICROFRAME_DIV_INT	(CLK_USBH0_MICROFRAME_OFFSET + 0x04)
+#define CLK_USBH0_MICROFRAME_SEL	(CLK_USBH0_MICROFRAME_OFFSET + 0x0c)
+
+#define CLK_USBH1_MICROFRAME_OFFSET	0x00104
+#define CLK_USBH1_MICROFRAME_CTRL	(CLK_USBH1_MICROFRAME_OFFSET + 0x00)
+#define CLK_USBH1_MICROFRAME_DIV_INT	(CLK_USBH1_MICROFRAME_OFFSET + 0x04)
+#define CLK_USBH1_MICROFRAME_SEL	(CLK_USBH1_MICROFRAME_OFFSET + 0x0c)
+
+#define CLK_USBH0_SUSPEND_OFFSET	0x00114
+#define CLK_USBH0_SUSPEND_CTRL		(CLK_USBH0_SUSPEND_OFFSET + 0x00)
+#define CLK_USBH0_SUSPEND_DIV_INT	(CLK_USBH0_SUSPEND_OFFSET + 0x04)
+#define CLK_USBH0_SUSPEND_SEL		(CLK_USBH0_SUSPEND_OFFSET + 0x0c)
+
+#define CLK_USBH1_SUSPEND_OFFSET	0x00124
+#define CLK_USBH1_SUSPEND_CTRL		(CLK_USBH1_SUSPEND_OFFSET + 0x00)
+#define CLK_USBH1_SUSPEND_DIV_INT	(CLK_USBH1_SUSPEND_OFFSET + 0x04)
+#define CLK_USBH1_SUSPEND_SEL		(CLK_USBH1_SUSPEND_OFFSET + 0x0c)
+
+#define CLK_ETH_TSU_OFFSET		0x00134
+#define CLK_ETH_TSU_CTRL		(CLK_ETH_TSU_OFFSET + 0x00)
+#define CLK_ETH_TSU_DIV_INT		(CLK_ETH_TSU_OFFSET + 0x04)
+#define CLK_ETH_TSU_SEL			(CLK_ETH_TSU_OFFSET + 0x0c)
+
+#define CLK_ADC_OFFSET			0x00144
+#define CLK_ADC_CTRL			(CLK_ADC_OFFSET + 0x00)
+#define CLK_ADC_DIV_INT			(CLK_ADC_OFFSET + 0x04)
+#define CLK_ADC_SEL			(CLK_ADC_OFFSET + 0x0c)
+
+#define CLK_SDIO_TIMER_OFFSET		0x00154
+#define CLK_SDIO_TIMER_CTRL		(CLK_SDIO_TIMER_OFFSET + 0x00)
+#define CLK_SDIO_TIMER_DIV_INT		(CLK_SDIO_TIMER_OFFSET + 0x04)
+#define CLK_SDIO_TIMER_SEL		(CLK_SDIO_TIMER_OFFSET + 0x0c)
+
+#define CLK_SDIO_ALT_SRC_OFFSET		0x00164
+#define CLK_SDIO_ALT_SRC_CTRL		(CLK_SDIO_ALT_SRC_OFFSET + 0x00)
+#define CLK_SDIO_ALT_SRC_DIV_INT	(CLK_SDIO_ALT_SRC_OFFSET + 0x04)
+#define CLK_SDIO_ALT_SRC_SEL		(CLK_SDIO_ALT_SRC_OFFSET + 0x0c)
+
+#define CLK_GP0_OFFSET			0x00174
+#define CLK_GP0_CTRL			(CLK_GP0_OFFSET + 0x00)
+#define CLK_GP0_DIV_INT			(CLK_GP0_OFFSET + 0x04)
+#define CLK_GP0_DIV_FRAC		(CLK_GP0_OFFSET + 0x08)
+#define CLK_GP0_SEL			(CLK_GP0_OFFSET + 0x0c)
+
+#define CLK_GP1_OFFSET			0x00184
+#define CLK_GP1_CTRL			(CLK_GP1_OFFSET + 0x00)
+#define CLK_GP1_DIV_INT			(CLK_GP1_OFFSET + 0x04)
+#define CLK_GP1_DIV_FRAC		(CLK_GP1_OFFSET + 0x08)
+#define CLK_GP1_SEL			(CLK_GP1_OFFSET + 0x0c)
+
+#define CLK_GP2_OFFSET			0x00194
+#define CLK_GP2_CTRL			(CLK_GP2_OFFSET + 0x00)
+#define CLK_GP2_DIV_INT			(CLK_GP2_OFFSET + 0x04)
+#define CLK_GP2_DIV_FRAC		(CLK_GP2_OFFSET + 0x08)
+#define CLK_GP2_SEL			(CLK_GP2_OFFSET + 0x0c)
+
+#define CLK_GP3_OFFSET			0x001a4
+#define CLK_GP3_CTRL			(CLK_GP3_OFFSET + 0x00)
+#define CLK_GP3_DIV_INT			(CLK_GP3_OFFSET + 0x04)
+#define CLK_GP3_DIV_FRAC		(CLK_GP3_OFFSET + 0x08)
+#define CLK_GP3_SEL			(CLK_GP3_OFFSET + 0x0c)
+
+#define CLK_GP4_OFFSET			0x001b4
+#define CLK_GP4_CTRL			(CLK_GP4_OFFSET + 0x00)
+#define CLK_GP4_DIV_INT			(CLK_GP4_OFFSET + 0x04)
+#define CLK_GP4_DIV_FRAC		(CLK_GP4_OFFSET + 0x08)
+#define CLK_GP4_SEL			(CLK_GP4_OFFSET + 0x0c)
+
+#define CLK_GP5_OFFSET			0x001c4
+#define CLK_GP5_CTRL			(CLK_GP5_OFFSET + 0x00)
+#define CLK_GP5_DIV_INT			(CLK_GP5_OFFSET + 0x04)
+#define CLK_GP5_DIV_FRAC		(CLK_GP5_OFFSET + 0x08)
+#define CLK_GP5_SEL			(CLK_GP5_OFFSET + 0x0c)
+
+#define CLK_SYS_RESUS_CTRL		0x0020c
+
+#define CLK_SLOW_SYS_RESUS_CTRL		0x00214
+
+#define FC0_OFFSET			0x0021c
+#define FC0_REF_KHZ			(FC0_OFFSET + 0x00)
+#define FC0_MIN_KHZ			(FC0_OFFSET + 0x04)
+#define FC0_MAX_KHZ			(FC0_OFFSET + 0x08)
+#define FC0_DELAY			(FC0_OFFSET + 0x0c)
+#define FC0_INTERVAL			(FC0_OFFSET + 0x10)
+#define FC0_SRC				(FC0_OFFSET + 0x14)
+#define FC0_STATUS			(FC0_OFFSET + 0x18)
+#define FC0_RESULT			(FC0_OFFSET + 0x1c)
+#define FC_SIZE				0x20
+#define FC_COUNT			8
+#define FC_NUM(idx, off)		((idx) * 32 + (off))
+
+#define AUX_SEL				1
+
+#define VIDEO_CLOCKS_OFFSET		0x4000
+#define VIDEO_CLK_VEC_CTRL		(VIDEO_CLOCKS_OFFSET + 0x0000)
+#define VIDEO_CLK_VEC_DIV_INT		(VIDEO_CLOCKS_OFFSET + 0x0004)
+#define VIDEO_CLK_VEC_SEL		(VIDEO_CLOCKS_OFFSET + 0x000c)
+#define VIDEO_CLK_DPI_CTRL		(VIDEO_CLOCKS_OFFSET + 0x0010)
+#define VIDEO_CLK_DPI_DIV_INT		(VIDEO_CLOCKS_OFFSET + 0x0014)
+#define VIDEO_CLK_DPI_SEL		(VIDEO_CLOCKS_OFFSET + 0x001c)
+#define VIDEO_CLK_MIPI0_DPI_CTRL	(VIDEO_CLOCKS_OFFSET + 0x0020)
+#define VIDEO_CLK_MIPI0_DPI_DIV_INT	(VIDEO_CLOCKS_OFFSET + 0x0024)
+#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC	(VIDEO_CLOCKS_OFFSET + 0x0028)
+#define VIDEO_CLK_MIPI0_DPI_SEL		(VIDEO_CLOCKS_OFFSET + 0x002c)
+#define VIDEO_CLK_MIPI1_DPI_CTRL	(VIDEO_CLOCKS_OFFSET + 0x0030)
+#define VIDEO_CLK_MIPI1_DPI_DIV_INT	(VIDEO_CLOCKS_OFFSET + 0x0034)
+#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC	(VIDEO_CLOCKS_OFFSET + 0x0038)
+#define VIDEO_CLK_MIPI1_DPI_SEL		(VIDEO_CLOCKS_OFFSET + 0x003c)
+
+#define DIV_INT_8BIT_MAX		GENMASK(7, 0)	/* max divide for most clocks */
+#define DIV_INT_16BIT_MAX		GENMASK(15, 0)	/* max divide for GPx, PWM */
+#define DIV_INT_24BIT_MAX               GENMASK(23, 0)	/* max divide for CLK_SYS */
+
+#define FC0_STATUS_DONE			BIT(4)
+#define FC0_STATUS_RUNNING		BIT(8)
+#define FC0_RESULT_FRAC_SHIFT		5
+
+#define PLL_PRIM_DIV1_MASK		GENMASK(18, 16)
+#define PLL_PRIM_DIV2_MASK		GENMASK(14, 12)
+
+#define PLL_SEC_DIV_MASK		GENMASK(12, 8)
+
+#define PLL_CS_LOCK			BIT(31)
+#define PLL_CS_REFDIV_MASK		BIT(1)
+
+#define PLL_PWR_PD			BIT(0)
+#define PLL_PWR_DACPD			BIT(1)
+#define PLL_PWR_DSMPD			BIT(2)
+#define PLL_PWR_POSTDIVPD		BIT(3)
+#define PLL_PWR_4PHASEPD		BIT(4)
+#define PLL_PWR_VCOPD			BIT(5)
+#define PLL_PWR_MASK			GENMASK(5, 0)
+
+#define PLL_SEC_RST			BIT(16)
+#define PLL_SEC_IMPL			BIT(31)
+
+/* PLL phase output for both PRI and SEC */
+#define PLL_PH_EN			BIT(4)
+#define PLL_PH_PHASE_SHIFT		0
+
+#define RP1_PLL_PHASE_0			0
+#define RP1_PLL_PHASE_90		1
+#define RP1_PLL_PHASE_180		2
+#define RP1_PLL_PHASE_270		3
+
+/* Clock fields for all clocks */
+#define CLK_CTRL_ENABLE			BIT(11)
+#define CLK_CTRL_AUXSRC_MASK		GENMASK(9, 5)
+#define CLK_CTRL_SRC_SHIFT		0
+#define CLK_DIV_FRAC_BITS		16
+
+#define LOCK_TIMEOUT_US			100000
+#define LOCK_POLL_DELAY_US		5
+
+#define MAX_CLK_PARENTS			16
+
+#define PLL_DIV_INVALID			19
+/*
+ * Secondary PLL channel output divider table.
+ * Divider values range from 8 to 19, where
+ * 19 means invalid.
+ */
+static const struct clk_div_table pll_sec_div_table[] = {
+	{ 0x00, PLL_DIV_INVALID },
+	{ 0x01, PLL_DIV_INVALID },
+	{ 0x02, PLL_DIV_INVALID },
+	{ 0x03, PLL_DIV_INVALID },
+	{ 0x04, PLL_DIV_INVALID },
+	{ 0x05, PLL_DIV_INVALID },
+	{ 0x06, PLL_DIV_INVALID },
+	{ 0x07, PLL_DIV_INVALID },
+	{ 0x08,  8 },
+	{ 0x09,  9 },
+	{ 0x0a, 10 },
+	{ 0x0b, 11 },
+	{ 0x0c, 12 },
+	{ 0x0d, 13 },
+	{ 0x0e, 14 },
+	{ 0x0f, 15 },
+	{ 0x10, 16 },
+	{ 0x11, 17 },
+	{ 0x12, 18 },
+	{ 0x13, PLL_DIV_INVALID },
+	{ 0x14, PLL_DIV_INVALID },
+	{ 0x15, PLL_DIV_INVALID },
+	{ 0x16, PLL_DIV_INVALID },
+	{ 0x17, PLL_DIV_INVALID },
+	{ 0x18, PLL_DIV_INVALID },
+	{ 0x19, PLL_DIV_INVALID },
+	{ 0x1a, PLL_DIV_INVALID },
+	{ 0x1b, PLL_DIV_INVALID },
+	{ 0x1c, PLL_DIV_INVALID },
+	{ 0x1d, PLL_DIV_INVALID },
+	{ 0x1e, PLL_DIV_INVALID },
+	{ 0x1f, PLL_DIV_INVALID },
+	{ 0 }
+};
+
+struct rp1_clockman {
+	struct device *dev;
+	void __iomem *regs;
+	struct regmap *regmap;
+	spinlock_t regs_lock; /* spinlock for all clocks */
+
+	/* Must be last */
+	struct clk_hw_onecell_data onecell;
+};
+
+struct rp1_pll_core_data {
+	u32 cs_reg;
+	u32 pwr_reg;
+	u32 fbdiv_int_reg;
+	u32 fbdiv_frac_reg;
+	u32 fc0_src;
+};
+
+struct rp1_pll_data {
+	u32 ctrl_reg;
+	u32 fc0_src;
+};
+
+struct rp1_pll_ph_data {
+	unsigned int phase;
+	unsigned int fixed_divider;
+	u32 ph_reg;
+	u32 fc0_src;
+};
+
+struct rp1_pll_divider_data {
+	u32 sec_reg;
+	u32 fc0_src;
+};
+
+struct rp1_clock_data {
+	int num_std_parents;
+	int num_aux_parents;
+	u32 oe_mask;
+	u32 clk_src_mask;
+	u32 ctrl_reg;
+	u32 div_int_reg;
+	u32 div_frac_reg;
+	u32 sel_reg;
+	u32 div_int_max;
+	unsigned long max_freq;
+	u32 fc0_src;
+};
+
+struct rp1_clk_desc {
+	struct clk_hw *(*clk_register)(struct rp1_clockman *clockman,
+				       struct rp1_clk_desc *desc);
+	const void *data;
+	struct clk_hw hw;
+	struct rp1_clockman *clockman;
+	unsigned long cached_rate;
+	struct clk_divider div;
+};
+
+static inline
+void clockman_write(struct rp1_clockman *clockman, u32 reg, u32 val)
+{
+	regmap_write(clockman->regmap, reg, val);
+}
+
+static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg)
+{
+	u32 val;
+
+	regmap_read(clockman->regmap, reg, &val);
+
+	return val;
+}
+
+static int rp1_pll_core_is_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_core->clockman;
+	const struct rp1_pll_core_data *data = pll_core->data;
+	u32 pwr = clockman_read(clockman, data->pwr_reg);
+
+	return (pwr & PLL_PWR_PD) || (pwr & PLL_PWR_POSTDIVPD);
+}
+
+static int rp1_pll_core_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_core->clockman;
+	const struct rp1_pll_core_data *data = pll_core->data;
+	u32 fbdiv_frac, val;
+	int ret;
+
+	spin_lock(&clockman->regs_lock);
+
+	if (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) {
+		/* Reset to a known state. */
+		clockman_write(clockman, data->pwr_reg, PLL_PWR_MASK);
+		clockman_write(clockman, data->fbdiv_int_reg, 20);
+		clockman_write(clockman, data->fbdiv_frac_reg, 0);
+		clockman_write(clockman, data->cs_reg, PLL_CS_REFDIV_MASK);
+	}
+
+	/* Come out of reset. */
+	fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg);
+	clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD);
+	spin_unlock(&clockman->regs_lock);
+
+	/* Wait for the PLL to lock. */
+	ret = regmap_read_poll_timeout(clockman->regmap, data->cs_reg, val,
+				       val & PLL_CS_LOCK,
+				       LOCK_POLL_DELAY_US, LOCK_TIMEOUT_US);
+	if (ret)
+		dev_err(clockman->dev, "%s: can't lock PLL\n",
+			clk_hw_get_name(hw));
+
+	return ret;
+}
+
+static void rp1_pll_core_off(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_core->clockman;
+	const struct rp1_pll_core_data *data = pll_core->data;
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->pwr_reg, 0);
+	spin_unlock(&clockman->regs_lock);
+}
+
+static inline unsigned long get_pll_core_divider(struct clk_hw *hw,
+						 unsigned long rate,
+						 unsigned long parent_rate,
+						 u32 *div_int, u32 *div_frac)
+{
+	u32 fbdiv_int, fbdiv_frac;
+	unsigned long calc_rate;
+	u64 shifted_fbdiv_int;
+	u64 div_fp64; /* 32.32 fixed point fraction. */
+
+	/* Factor of reference clock to VCO frequency. */
+	div_fp64 = (u64)(rate) << 32;
+	div_fp64 = DIV_ROUND_CLOSEST_ULL(div_fp64, parent_rate);
+
+	/* Round the fractional component at 24 bits. */
+	div_fp64 += 1 << (32 - 24 - 1);
+
+	fbdiv_int = div_fp64 >> 32;
+	fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff;
+
+	shifted_fbdiv_int = (u64)fbdiv_int << 24;
+	calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac);
+	calc_rate += BIT(23);
+	calc_rate >>= 24;
+
+	*div_int = fbdiv_int;
+	*div_frac = fbdiv_frac;
+
+	return calc_rate;
+}
+
+static int rp1_pll_core_set_rate(struct clk_hw *hw,
+				 unsigned long rate, unsigned long parent_rate)
+{
+	struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_core->clockman;
+	const struct rp1_pll_core_data *data = pll_core->data;
+	unsigned long calc_rate;
+	u32 fbdiv_int, fbdiv_frac;
+
+	/* Disable dividers to start with. */
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->fbdiv_int_reg, 0);
+	clockman_write(clockman, data->fbdiv_frac_reg, 0);
+	spin_unlock(&clockman->regs_lock);
+
+	calc_rate = get_pll_core_divider(hw, rate, parent_rate,
+					 &fbdiv_int, &fbdiv_frac);
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD);
+	clockman_write(clockman, data->fbdiv_int_reg, fbdiv_int);
+	clockman_write(clockman, data->fbdiv_frac_reg, fbdiv_frac);
+	spin_unlock(&clockman->regs_lock);
+
+	/* Check that reference frequency is no greater than VCO / 16. */
+	if (WARN_ON_ONCE(parent_rate > (rate / 16)))
+		return -ERANGE;
+
+	pll_core->cached_rate = calc_rate;
+
+	spin_lock(&clockman->regs_lock);
+	/* Don't need to divide ref unless parent_rate > (output freq / 16) */
+	clockman_write(clockman, data->cs_reg,
+		       clockman_read(clockman, data->cs_reg) |
+				     PLL_CS_REFDIV_MASK);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static unsigned long rp1_pll_core_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_core->clockman;
+	const struct rp1_pll_core_data *data = pll_core->data;
+	u32 fbdiv_int, fbdiv_frac;
+	unsigned long calc_rate;
+	u64 shifted_fbdiv_int;
+
+	fbdiv_int = clockman_read(clockman, data->fbdiv_int_reg);
+	fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg);
+
+	shifted_fbdiv_int = (u64)fbdiv_int << 24;
+	calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac);
+	calc_rate += BIT(23);
+	calc_rate >>= 24;
+
+	return calc_rate;
+}
+
+static long rp1_pll_core_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	u32 fbdiv_int, fbdiv_frac;
+
+	return get_pll_core_divider(hw, rate, *parent_rate,
+				    &fbdiv_int, &fbdiv_frac);
+}
+
+static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate,
+				  u32 *divider1, u32 *divider2)
+{
+	unsigned int div1, div2;
+	unsigned int best_div1 = 7, best_div2 = 7;
+	unsigned long best_rate_diff =
+		abs_diff(DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate);
+	unsigned long rate_diff, calc_rate;
+
+	for (div1 = 1; div1 <= 7; div1++) {
+		for (div2 = 1; div2 <= div1; div2++) {
+			calc_rate = DIV_ROUND_CLOSEST(parent_rate, div1 * div2);
+			rate_diff = abs_diff(calc_rate, rate);
+
+			if (calc_rate == rate) {
+				best_div1 = div1;
+				best_div2 = div2;
+				goto done;
+			} else if (rate_diff < best_rate_diff) {
+				best_div1 = div1;
+				best_div2 = div2;
+				best_rate_diff = rate_diff;
+			}
+		}
+	}
+
+done:
+	*divider1 = best_div1;
+	*divider2 = best_div2;
+}
+
+static int rp1_pll_set_rate(struct clk_hw *hw,
+			    unsigned long rate, unsigned long parent_rate)
+{
+	struct rp1_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll->clockman;
+	const struct rp1_pll_data *data = pll->data;
+
+	u32 prim, prim_div1, prim_div2;
+
+	get_pll_prim_dividers(rate, parent_rate, &prim_div1, &prim_div2);
+
+	spin_lock(&clockman->regs_lock);
+	prim = clockman_read(clockman, data->ctrl_reg);
+	prim &= ~PLL_PRIM_DIV1_MASK;
+	prim |= FIELD_PREP(PLL_PRIM_DIV1_MASK, prim_div1);
+	prim &= ~PLL_PRIM_DIV2_MASK;
+	prim |= FIELD_PREP(PLL_PRIM_DIV2_MASK, prim_div2);
+	clockman_write(clockman, data->ctrl_reg, prim);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct rp1_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll->clockman;
+	const struct rp1_pll_data *data = pll->data;
+	u32 prim, prim_div1, prim_div2;
+
+	prim = clockman_read(clockman, data->ctrl_reg);
+	prim_div1 = FIELD_GET(PLL_PRIM_DIV1_MASK, prim);
+	prim_div2 = FIELD_GET(PLL_PRIM_DIV2_MASK, prim);
+
+	if (!prim_div1 || !prim_div2) {
+		dev_err(clockman->dev, "%s: (%s) zero divider value\n",
+			__func__, clk_hw_get_name(hw));
+		return 0;
+	}
+
+	return DIV_ROUND_CLOSEST(parent_rate, prim_div1 * prim_div2);
+}
+
+static long rp1_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	u32 div1, div2;
+
+	get_pll_prim_dividers(rate, *parent_rate, &div1, &div2);
+
+	return DIV_ROUND_CLOSEST(*parent_rate, div1 * div2);
+}
+
+static int rp1_pll_ph_is_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_ph->clockman;
+	const struct rp1_pll_ph_data *data = pll_ph->data;
+
+	return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN);
+}
+
+static int rp1_pll_ph_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_ph->clockman;
+	const struct rp1_pll_ph_data *data = pll_ph->data;
+	u32 ph_reg;
+
+	/*
+	 * TODO: ensure the parent clock is enabled before
+	 * enabling its phase shifted child.
+	 */
+	spin_lock(&clockman->regs_lock);
+	ph_reg = clockman_read(clockman, data->ph_reg);
+	ph_reg |= data->phase << PLL_PH_PHASE_SHIFT;
+	ph_reg |= PLL_PH_EN;
+	clockman_write(clockman, data->ph_reg, ph_reg);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static void rp1_pll_ph_off(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = pll_ph->clockman;
+	const struct rp1_pll_ph_data *data = pll_ph->data;
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->ph_reg,
+		       clockman_read(clockman, data->ph_reg) & ~PLL_PH_EN);
+	spin_unlock(&clockman->regs_lock);
+}
+
+static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw);
+	const struct rp1_pll_ph_data *data = pll_ph->data;
+
+	return parent_rate / data->fixed_divider;
+}
+
+static long rp1_pll_ph_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *parent_rate)
+{
+	struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw);
+	const struct rp1_pll_ph_data *data = pll_ph->data;
+
+	return *parent_rate / data->fixed_divider;
+}
+
+static int rp1_pll_divider_is_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw);
+	struct rp1_clockman *clockman = divider->clockman;
+	const struct rp1_pll_data *data = divider->data;
+
+	return !(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_RST);
+}
+
+static int rp1_pll_divider_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw);
+	struct rp1_clockman *clockman = divider->clockman;
+	const struct rp1_pll_data *data = divider->data;
+
+	spin_lock(&clockman->regs_lock);
+	/* Check the implementation bit is set! */
+	WARN_ON(!(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_IMPL));
+	clockman_write(clockman, data->ctrl_reg,
+		       clockman_read(clockman, data->ctrl_reg) & ~PLL_SEC_RST);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static void rp1_pll_divider_off(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw);
+	struct rp1_clockman *clockman = divider->clockman;
+	const struct rp1_pll_data *data = divider->data;
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->ctrl_reg,
+		       clockman_read(clockman, data->ctrl_reg) | PLL_SEC_RST);
+	spin_unlock(&clockman->regs_lock);
+}
+
+static int rp1_pll_divider_set_rate(struct clk_hw *hw,
+				    unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw);
+	struct rp1_clockman *clockman = divider->clockman;
+	const struct rp1_pll_data *data = divider->data;
+	u32 div, sec;
+
+	div = DIV_ROUND_UP_ULL(parent_rate, rate);
+	div = clamp(div, 8u, 19u);
+
+	spin_lock(&clockman->regs_lock);
+	sec = clockman_read(clockman, data->ctrl_reg);
+	sec &= ~PLL_SEC_DIV_MASK;
+	sec |= FIELD_PREP(PLL_SEC_DIV_MASK, div);
+
+	/* Must keep the divider in reset to change the value. */
+	sec |= PLL_SEC_RST;
+	clockman_write(clockman, data->ctrl_reg, sec);
+
+	/* TODO: must sleep 10 pll vco cycles */
+	sec &= ~PLL_SEC_RST;
+	clockman_write(clockman, data->ctrl_reg, sec);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static unsigned long rp1_pll_divider_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long rp1_pll_divider_round_rate(struct clk_hw *hw,
+				       unsigned long rate,
+				       unsigned long *parent_rate)
+{
+	return clk_divider_ops.round_rate(hw, rate, parent_rate);
+}
+
+static int rp1_clock_is_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+
+	return !!(clockman_read(clockman, data->ctrl_reg) & CLK_CTRL_ENABLE);
+}
+
+static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+	u64 calc_rate;
+	u64 div;
+	u32 frac;
+
+	div = clockman_read(clockman, data->div_int_reg);
+	frac = (data->div_frac_reg != 0) ?
+		clockman_read(clockman, data->div_frac_reg) : 0;
+
+	/* If the integer portion of the divider is 0, treat it as 2^16 */
+	if (!div)
+		div = 1 << 16;
+
+	div = (div << CLK_DIV_FRAC_BITS) | (frac >> (32 - CLK_DIV_FRAC_BITS));
+
+	calc_rate = (u64)parent_rate << CLK_DIV_FRAC_BITS;
+	calc_rate = div64_u64(calc_rate, div);
+
+	return calc_rate;
+}
+
+static int rp1_clock_on(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->ctrl_reg,
+		       clockman_read(clockman, data->ctrl_reg) | CLK_CTRL_ENABLE);
+	/* If this is a GPCLK, turn on the output-enable */
+	if (data->oe_mask)
+		clockman_write(clockman, GPCLK_OE_CTRL,
+			       clockman_read(clockman, GPCLK_OE_CTRL) | data->oe_mask);
+	spin_unlock(&clockman->regs_lock);
+
+	return 0;
+}
+
+static void rp1_clock_off(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+
+	spin_lock(&clockman->regs_lock);
+	clockman_write(clockman, data->ctrl_reg,
+		       clockman_read(clockman, data->ctrl_reg) & ~CLK_CTRL_ENABLE);
+	/* If this is a GPCLK, turn off the output-enable */
+	if (data->oe_mask)
+		clockman_write(clockman, GPCLK_OE_CTRL,
+			       clockman_read(clockman, GPCLK_OE_CTRL) & ~data->oe_mask);
+	spin_unlock(&clockman->regs_lock);
+}
+
+static u32 rp1_clock_choose_div(unsigned long rate, unsigned long parent_rate,
+				const struct rp1_clock_data *data)
+{
+	u64 div;
+
+	/*
+	 * Due to earlier rounding, calculated parent_rate may differ from
+	 * expected value. Don't fail on a small discrepancy near unity divide.
+	 */
+	if (!rate || rate > parent_rate + (parent_rate >> CLK_DIV_FRAC_BITS))
+		return 0;
+
+	/*
+	 * Always express div in fixed-point format for fractional division;
+	 * If no fractional divider is present, the fraction part will be zero.
+	 */
+	if (data->div_frac_reg) {
+		div = (u64)parent_rate << CLK_DIV_FRAC_BITS;
+		div = DIV_ROUND_CLOSEST_ULL(div, rate);
+	} else {
+		div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
+		div <<= CLK_DIV_FRAC_BITS;
+	}
+
+	div = clamp(div,
+		    1ull << CLK_DIV_FRAC_BITS,
+		    (u64)data->div_int_max << CLK_DIV_FRAC_BITS);
+
+	return div;
+}
+
+static u8 rp1_clock_get_parent(struct clk_hw *hw)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+	u32 sel, ctrl;
+	u8 parent;
+
+	/* Sel is one-hot, so find the first bit set */
+	sel = clockman_read(clockman, data->sel_reg);
+	parent = ffs(sel) - 1;
+
+	/* sel == 0 implies the parent clock is not enabled yet. */
+	if (!sel) {
+		/* Read the clock src from the CTRL register instead */
+		ctrl = clockman_read(clockman, data->ctrl_reg);
+		parent = (ctrl & data->clk_src_mask) >> CLK_CTRL_SRC_SHIFT;
+	}
+
+	if (parent >= data->num_std_parents)
+		parent = AUX_SEL;
+
+	if (parent == AUX_SEL) {
+		/*
+		 * Clock parent is an auxiliary source, so get the parent from
+		 * the AUXSRC register field.
+		 */
+		ctrl = clockman_read(clockman, data->ctrl_reg);
+		parent = FIELD_GET(CLK_CTRL_AUXSRC_MASK, ctrl);
+		parent += data->num_std_parents;
+	}
+
+	return parent;
+}
+
+static int rp1_clock_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+	u32 ctrl, sel;
+
+	spin_lock(&clockman->regs_lock);
+	ctrl = clockman_read(clockman, data->ctrl_reg);
+
+	if (index >= data->num_std_parents) {
+		/* This is an aux source request */
+		if (index >= data->num_std_parents + data->num_aux_parents) {
+			spin_unlock(&clockman->regs_lock);
+			return -EINVAL;
+		}
+
+		/* Select parent from aux list */
+		ctrl &= ~CLK_CTRL_AUXSRC_MASK;
+		ctrl |= FIELD_PREP(CLK_CTRL_AUXSRC_MASK, index - data->num_std_parents);
+		/* Set src to aux list */
+		ctrl &= ~data->clk_src_mask;
+		ctrl |= (AUX_SEL << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask;
+	} else {
+		ctrl &= ~data->clk_src_mask;
+		ctrl |= (index << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask;
+	}
+
+	clockman_write(clockman, data->ctrl_reg, ctrl);
+	spin_unlock(&clockman->regs_lock);
+
+	sel = rp1_clock_get_parent(hw);
+	WARN_ONCE(sel != index, "(%s): Parent index req %u returned back %u\n",
+		  clk_hw_get_name(hw), index, sel);
+
+	return 0;
+}
+
+static int rp1_clock_set_rate_and_parent(struct clk_hw *hw,
+					 unsigned long rate,
+					 unsigned long parent_rate,
+					 u8 parent)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	struct rp1_clockman *clockman = clock->clockman;
+	const struct rp1_clock_data *data = clock->data;
+	u32 div = rp1_clock_choose_div(rate, parent_rate, data);
+
+	WARN_ONCE(rate > data->max_freq,
+		  "(%s): Requested rate (%lu) > max rate (%lu)\n",
+		  clk_hw_get_name(hw), rate, data->max_freq);
+
+	if (WARN_ONCE(!div,
+		      "clk divider calculated as 0! (%s, rate %lu, parent rate %lu)\n",
+		      clk_hw_get_name(hw), rate, parent_rate))
+		div = 1 << CLK_DIV_FRAC_BITS;
+
+	spin_lock(&clockman->regs_lock);
+
+	clockman_write(clockman, data->div_int_reg, div >> CLK_DIV_FRAC_BITS);
+	if (data->div_frac_reg)
+		clockman_write(clockman, data->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS));
+
+	spin_unlock(&clockman->regs_lock);
+
+	if (parent != 0xff)
+		rp1_clock_set_parent(hw, parent);
+
+	return 0;
+}
+
+static int rp1_clock_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long parent_rate)
+{
+	return rp1_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
+}
+
+static void rp1_clock_choose_div_and_prate(struct clk_hw *hw,
+					   int parent_idx,
+					   unsigned long rate,
+					   unsigned long *prate,
+					   unsigned long *calc_rate)
+{
+	struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw);
+	const struct rp1_clock_data *data = clock->data;
+	struct clk_hw *parent;
+	u32 div;
+	u64 tmp;
+
+	parent = clk_hw_get_parent_by_index(hw, parent_idx);
+
+	*prate = clk_hw_get_rate(parent);
+	div = rp1_clock_choose_div(rate, *prate, data);
+
+	if (!div) {
+		*calc_rate = 0;
+		return;
+	}
+
+	/* Recalculate to account for rounding errors */
+	tmp = (u64)*prate << CLK_DIV_FRAC_BITS;
+	tmp = div_u64(tmp, div);
+
+	/*
+	 * Prevent overclocks - if all parent choices result in
+	 * a downstream clock in excess of the maximum, then the
+	 * call to set the clock will fail.
+	 */
+	if (tmp > data->max_freq)
+		*calc_rate = 0;
+	else
+		*calc_rate = tmp;
+}
+
+static int rp1_clock_determine_rate(struct clk_hw *hw,
+				    struct clk_rate_request *req)
+{
+	struct clk_hw *parent, *best_parent = NULL;
+	unsigned long best_rate = 0;
+	unsigned long best_prate = 0;
+	unsigned long best_rate_diff = ULONG_MAX;
+	unsigned long prate, calc_rate;
+	size_t i;
+
+	/*
+	 * If the NO_REPARENT flag is set, try to use existing parent.
+	 */
+	if ((clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT)) {
+		i = rp1_clock_get_parent(hw);
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (parent) {
+			rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate,
+						       &calc_rate);
+			if (calc_rate > 0) {
+				req->best_parent_hw = parent;
+				req->best_parent_rate = prate;
+				req->rate = calc_rate;
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 * Select parent clock that results in the closest rate (lower or
+	 * higher)
+	 */
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+
+		rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate,
+					       &calc_rate);
+
+		if (abs_diff(calc_rate, req->rate) < best_rate_diff) {
+			best_parent = parent;
+			best_prate = prate;
+			best_rate = calc_rate;
+			best_rate_diff = abs_diff(calc_rate, req->rate);
+
+			if (best_rate_diff == 0)
+				break;
+		}
+	}
+
+	if (best_rate == 0)
+		return -EINVAL;
+
+	req->best_parent_hw = best_parent;
+	req->best_parent_rate = best_prate;
+	req->rate = best_rate;
+
+	return 0;
+}
+
+static const struct clk_ops rp1_pll_core_ops = {
+	.is_prepared = rp1_pll_core_is_on,
+	.prepare = rp1_pll_core_on,
+	.unprepare = rp1_pll_core_off,
+	.set_rate = rp1_pll_core_set_rate,
+	.recalc_rate = rp1_pll_core_recalc_rate,
+	.round_rate = rp1_pll_core_round_rate,
+};
+
+static const struct clk_ops rp1_pll_ops = {
+	.set_rate = rp1_pll_set_rate,
+	.recalc_rate = rp1_pll_recalc_rate,
+	.round_rate = rp1_pll_round_rate,
+};
+
+static const struct clk_ops rp1_pll_ph_ops = {
+	.is_prepared = rp1_pll_ph_is_on,
+	.prepare = rp1_pll_ph_on,
+	.unprepare = rp1_pll_ph_off,
+	.recalc_rate = rp1_pll_ph_recalc_rate,
+	.round_rate = rp1_pll_ph_round_rate,
+};
+
+static const struct clk_ops rp1_pll_divider_ops = {
+	.is_prepared = rp1_pll_divider_is_on,
+	.prepare = rp1_pll_divider_on,
+	.unprepare = rp1_pll_divider_off,
+	.set_rate = rp1_pll_divider_set_rate,
+	.recalc_rate = rp1_pll_divider_recalc_rate,
+	.round_rate = rp1_pll_divider_round_rate,
+};
+
+static const struct clk_ops rp1_clk_ops = {
+	.is_prepared = rp1_clock_is_on,
+	.prepare = rp1_clock_on,
+	.unprepare = rp1_clock_off,
+	.recalc_rate = rp1_clock_recalc_rate,
+	.get_parent = rp1_clock_get_parent,
+	.set_parent = rp1_clock_set_parent,
+	.set_rate_and_parent = rp1_clock_set_rate_and_parent,
+	.set_rate = rp1_clock_set_rate,
+	.determine_rate = rp1_clock_determine_rate,
+};
+
+static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman,
+				       struct rp1_clk_desc *desc)
+{
+	int ret;
+
+	desc->clockman = clockman;
+
+	ret = devm_clk_hw_register(clockman->dev, &desc->hw);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &desc->hw;
+}
+
+static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman,
+					       struct rp1_clk_desc *desc)
+{
+	const struct rp1_pll_data *divider_data = desc->data;
+	int ret;
+
+	desc->div.reg = clockman->regs + divider_data->ctrl_reg;
+	desc->div.shift = __ffs(PLL_SEC_DIV_MASK);
+	desc->div.width = __ffs(~(PLL_SEC_DIV_MASK >> desc->div.shift));
+	desc->div.flags = CLK_DIVIDER_ROUND_CLOSEST;
+	desc->div.lock = &clockman->regs_lock;
+	desc->div.hw.init = desc->hw.init;
+	desc->div.table = pll_sec_div_table;
+
+	desc->clockman = clockman;
+
+	ret = devm_clk_hw_register(clockman->dev, &desc->div.hw);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &desc->div.hw;
+}
+
+static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman,
+					 struct rp1_clk_desc *desc)
+{
+	const struct rp1_clock_data *clock_data = desc->data;
+	int ret;
+
+	if (WARN_ON_ONCE(MAX_CLK_PARENTS <
+	       clock_data->num_std_parents + clock_data->num_aux_parents))
+		return NULL;
+
+	/* There must be a gap for the AUX selector */
+	if (WARN_ON_ONCE(clock_data->num_std_parents > AUX_SEL &&
+			 desc->hw.init->parent_data[AUX_SEL].index != -1))
+		return NULL;
+
+	desc->clockman = clockman;
+
+	ret = devm_clk_hw_register(clockman->dev, &desc->hw);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &desc->hw;
+}
+
+/* Assignment helper macros for different clock types. */
+#define _REGISTER(f, ...)	{ .clk_register = f, __VA_ARGS__ }
+
+#define CLK_DATA(type, ...)	.data = &(struct type) { __VA_ARGS__ }
+
+#define REGISTER_PLL(...)	_REGISTER(&rp1_register_pll,		\
+					  __VA_ARGS__)
+
+#define REGISTER_PLL_DIV(...)	_REGISTER(&rp1_register_pll_divider,	\
+					  __VA_ARGS__)
+
+#define REGISTER_CLK(...)	_REGISTER(&rp1_register_clock,		\
+					  __VA_ARGS__)
+
+static struct rp1_clk_desc pll_sys_core_desc = REGISTER_PLL(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_sys_core",
+		(const struct clk_parent_data[]) { { .index = 0 } },
+		&rp1_pll_core_ops,
+		CLK_IS_CRITICAL
+	),
+	CLK_DATA(rp1_pll_core_data,
+		 .cs_reg = PLL_SYS_CS,
+		 .pwr_reg = PLL_SYS_PWR,
+		 .fbdiv_int_reg = PLL_SYS_FBDIV_INT,
+		 .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC,
+	)
+);
+
+static struct rp1_clk_desc pll_audio_core_desc = REGISTER_PLL(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_audio_core",
+		(const struct clk_parent_data[]) { { .index = 0 } },
+		&rp1_pll_core_ops,
+		CLK_IS_CRITICAL
+	),
+	CLK_DATA(rp1_pll_core_data,
+		 .cs_reg = PLL_AUDIO_CS,
+		 .pwr_reg = PLL_AUDIO_PWR,
+		 .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT,
+		 .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC,
+	)
+);
+
+static struct rp1_clk_desc pll_video_core_desc = REGISTER_PLL(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_video_core",
+		(const struct clk_parent_data[]) { { .index = 0 } },
+		&rp1_pll_core_ops,
+		CLK_IS_CRITICAL
+	),
+	CLK_DATA(rp1_pll_core_data,
+		 .cs_reg = PLL_VIDEO_CS,
+		 .pwr_reg = PLL_VIDEO_PWR,
+		 .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT,
+		 .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC,
+	)
+);
+
+static struct rp1_clk_desc pll_sys_desc = REGISTER_PLL(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_sys",
+		(const struct clk_parent_data[]) {
+			{ .hw = &pll_sys_core_desc.hw }
+		},
+		&rp1_pll_ops,
+		0
+	),
+	CLK_DATA(rp1_pll_data,
+		 .ctrl_reg = PLL_SYS_PRIM,
+		 .fc0_src = FC_NUM(0, 2),
+	)
+);
+
+static struct rp1_clk_desc pll_sys_sec_desc = REGISTER_PLL_DIV(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_sys_sec",
+		(const struct clk_parent_data[]) {
+			{ .hw = &pll_sys_core_desc.hw }
+		},
+		&rp1_pll_divider_ops,
+		0
+	),
+	CLK_DATA(rp1_pll_data,
+		 .ctrl_reg = PLL_SYS_SEC,
+		 .fc0_src = FC_NUM(2, 2),
+	)
+);
+
+static struct rp1_clk_desc clk_eth_tsu_desc = REGISTER_CLK(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"clk_eth_tsu",
+		(const struct clk_parent_data[]) { { .index = 0 } },
+		&rp1_clk_ops,
+		0
+	),
+	CLK_DATA(rp1_clock_data,
+		 .num_std_parents = 0,
+		 .num_aux_parents = 1,
+		 .ctrl_reg = CLK_ETH_TSU_CTRL,
+		 .div_int_reg = CLK_ETH_TSU_DIV_INT,
+		 .sel_reg = CLK_ETH_TSU_SEL,
+		 .div_int_max = DIV_INT_8BIT_MAX,
+		 .max_freq = 50 * HZ_PER_MHZ,
+		 .fc0_src = FC_NUM(5, 7),
+	)
+);
+
+static const struct clk_parent_data clk_eth_parents[] = {
+	{ .hw = &pll_sys_sec_desc.div.hw },
+	{ .hw = &pll_sys_desc.hw },
+};
+
+static struct rp1_clk_desc clk_eth_desc = REGISTER_CLK(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"clk_eth",
+		clk_eth_parents,
+		&rp1_clk_ops,
+		0
+	),
+	CLK_DATA(rp1_clock_data,
+		 .num_std_parents = 0,
+		 .num_aux_parents = 2,
+		 .ctrl_reg = CLK_ETH_CTRL,
+		 .div_int_reg = CLK_ETH_DIV_INT,
+		 .sel_reg = CLK_ETH_SEL,
+		 .div_int_max = DIV_INT_8BIT_MAX,
+		 .max_freq = 125 * HZ_PER_MHZ,
+		 .fc0_src = FC_NUM(4, 6),
+	)
+);
+
+static const struct clk_parent_data clk_sys_parents[] = {
+	{ .index = 0 },
+	{ .index = -1 },
+	{ .hw = &pll_sys_desc.hw },
+};
+
+static struct rp1_clk_desc clk_sys_desc = REGISTER_CLK(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"clk_sys",
+		clk_sys_parents,
+		&rp1_clk_ops,
+		CLK_IS_CRITICAL
+	),
+	CLK_DATA(rp1_clock_data,
+		 .num_std_parents = 3,
+		 .num_aux_parents = 0,
+		 .ctrl_reg = CLK_SYS_CTRL,
+		 .div_int_reg = CLK_SYS_DIV_INT,
+		 .sel_reg = CLK_SYS_SEL,
+		 .div_int_max = DIV_INT_24BIT_MAX,
+		 .max_freq = 200 * HZ_PER_MHZ,
+		 .fc0_src = FC_NUM(0, 4),
+		 .clk_src_mask = 0x3,
+	)
+);
+
+static struct rp1_clk_desc pll_sys_pri_ph_desc = REGISTER_PLL(
+	.hw.init = CLK_HW_INIT_PARENTS_DATA(
+		"pll_sys_pri_ph",
+		(const struct clk_parent_data[]) {
+			{ .hw = &pll_sys_desc.hw }
+		},
+		&rp1_pll_ph_ops,
+		0
+	),
+	CLK_DATA(rp1_pll_ph_data,
+		 .ph_reg = PLL_SYS_PRIM,
+		 .fixed_divider = 2,
+		 .phase = RP1_PLL_PHASE_0,
+		 .fc0_src = FC_NUM(1, 2),
+	)
+);
+
+static struct rp1_clk_desc *const clk_desc_array[] = {
+	[RP1_PLL_SYS_CORE] = &pll_sys_core_desc,
+	[RP1_PLL_AUDIO_CORE] = &pll_audio_core_desc,
+	[RP1_PLL_VIDEO_CORE] = &pll_video_core_desc,
+	[RP1_PLL_SYS] = &pll_sys_desc,
+	[RP1_CLK_ETH_TSU] = &clk_eth_tsu_desc,
+	[RP1_CLK_ETH] = &clk_eth_desc,
+	[RP1_CLK_SYS] = &clk_sys_desc,
+	[RP1_PLL_SYS_PRI_PH] = &pll_sys_pri_ph_desc,
+	[RP1_PLL_SYS_SEC] = &pll_sys_sec_desc,
+};
+
+static const struct regmap_range rp1_reg_ranges[] = {
+	regmap_reg_range(PLL_SYS_CS, PLL_SYS_SEC),
+	regmap_reg_range(PLL_AUDIO_CS, PLL_AUDIO_TERN),
+	regmap_reg_range(PLL_VIDEO_CS, PLL_VIDEO_SEC),
+	regmap_reg_range(GPCLK_OE_CTRL, GPCLK_OE_CTRL),
+	regmap_reg_range(CLK_SYS_CTRL, CLK_SYS_DIV_INT),
+	regmap_reg_range(CLK_SYS_SEL, CLK_SYS_SEL),
+	regmap_reg_range(CLK_SLOW_SYS_CTRL, CLK_SLOW_SYS_DIV_INT),
+	regmap_reg_range(CLK_SLOW_SYS_SEL, CLK_SLOW_SYS_SEL),
+	regmap_reg_range(CLK_DMA_CTRL, CLK_DMA_DIV_INT),
+	regmap_reg_range(CLK_DMA_SEL, CLK_DMA_SEL),
+	regmap_reg_range(CLK_UART_CTRL, CLK_UART_DIV_INT),
+	regmap_reg_range(CLK_UART_SEL, CLK_UART_SEL),
+	regmap_reg_range(CLK_ETH_CTRL, CLK_ETH_DIV_INT),
+	regmap_reg_range(CLK_ETH_SEL, CLK_ETH_SEL),
+	regmap_reg_range(CLK_PWM0_CTRL, CLK_PWM0_SEL),
+	regmap_reg_range(CLK_PWM1_CTRL, CLK_PWM1_SEL),
+	regmap_reg_range(CLK_AUDIO_IN_CTRL, CLK_AUDIO_IN_DIV_INT),
+	regmap_reg_range(CLK_AUDIO_IN_SEL, CLK_AUDIO_IN_SEL),
+	regmap_reg_range(CLK_AUDIO_OUT_CTRL, CLK_AUDIO_OUT_DIV_INT),
+	regmap_reg_range(CLK_AUDIO_OUT_SEL, CLK_AUDIO_OUT_SEL),
+	regmap_reg_range(CLK_I2S_CTRL, CLK_I2S_DIV_INT),
+	regmap_reg_range(CLK_I2S_SEL, CLK_I2S_SEL),
+	regmap_reg_range(CLK_MIPI0_CFG_CTRL, CLK_MIPI0_CFG_DIV_INT),
+	regmap_reg_range(CLK_MIPI0_CFG_SEL, CLK_MIPI0_CFG_SEL),
+	regmap_reg_range(CLK_MIPI1_CFG_CTRL, CLK_MIPI1_CFG_DIV_INT),
+	regmap_reg_range(CLK_MIPI1_CFG_SEL, CLK_MIPI1_CFG_SEL),
+	regmap_reg_range(CLK_PCIE_AUX_CTRL, CLK_PCIE_AUX_DIV_INT),
+	regmap_reg_range(CLK_PCIE_AUX_SEL, CLK_PCIE_AUX_SEL),
+	regmap_reg_range(CLK_USBH0_MICROFRAME_CTRL, CLK_USBH0_MICROFRAME_DIV_INT),
+	regmap_reg_range(CLK_USBH0_MICROFRAME_SEL, CLK_USBH0_MICROFRAME_SEL),
+	regmap_reg_range(CLK_USBH1_MICROFRAME_CTRL, CLK_USBH1_MICROFRAME_DIV_INT),
+	regmap_reg_range(CLK_USBH1_MICROFRAME_SEL, CLK_USBH1_MICROFRAME_SEL),
+	regmap_reg_range(CLK_USBH0_SUSPEND_CTRL, CLK_USBH0_SUSPEND_DIV_INT),
+	regmap_reg_range(CLK_USBH0_SUSPEND_SEL, CLK_USBH0_SUSPEND_SEL),
+	regmap_reg_range(CLK_USBH1_SUSPEND_CTRL, CLK_USBH1_SUSPEND_DIV_INT),
+	regmap_reg_range(CLK_USBH1_SUSPEND_SEL, CLK_USBH1_SUSPEND_SEL),
+	regmap_reg_range(CLK_ETH_TSU_CTRL, CLK_ETH_TSU_DIV_INT),
+	regmap_reg_range(CLK_ETH_TSU_SEL, CLK_ETH_TSU_SEL),
+	regmap_reg_range(CLK_ADC_CTRL, CLK_ADC_DIV_INT),
+	regmap_reg_range(CLK_ADC_SEL, CLK_ADC_SEL),
+	regmap_reg_range(CLK_SDIO_TIMER_CTRL, CLK_SDIO_TIMER_DIV_INT),
+	regmap_reg_range(CLK_SDIO_TIMER_SEL, CLK_SDIO_TIMER_SEL),
+	regmap_reg_range(CLK_SDIO_ALT_SRC_CTRL, CLK_SDIO_ALT_SRC_DIV_INT),
+	regmap_reg_range(CLK_SDIO_ALT_SRC_SEL, CLK_SDIO_ALT_SRC_SEL),
+	regmap_reg_range(CLK_GP0_CTRL, CLK_GP0_SEL),
+	regmap_reg_range(CLK_GP1_CTRL, CLK_GP1_SEL),
+	regmap_reg_range(CLK_GP2_CTRL, CLK_GP2_SEL),
+	regmap_reg_range(CLK_GP3_CTRL, CLK_GP3_SEL),
+	regmap_reg_range(CLK_GP4_CTRL, CLK_GP4_SEL),
+	regmap_reg_range(CLK_GP5_CTRL, CLK_GP5_SEL),
+	regmap_reg_range(CLK_SYS_RESUS_CTRL, CLK_SYS_RESUS_CTRL),
+	regmap_reg_range(CLK_SLOW_SYS_RESUS_CTRL, CLK_SLOW_SYS_RESUS_CTRL),
+	regmap_reg_range(FC0_REF_KHZ, FC0_RESULT),
+	regmap_reg_range(VIDEO_CLK_VEC_CTRL, VIDEO_CLK_VEC_DIV_INT),
+	regmap_reg_range(VIDEO_CLK_VEC_SEL, VIDEO_CLK_DPI_DIV_INT),
+	regmap_reg_range(VIDEO_CLK_DPI_SEL, VIDEO_CLK_MIPI1_DPI_SEL),
+};
+
+static const struct regmap_access_table rp1_reg_table = {
+	.yes_ranges = rp1_reg_ranges,
+	.n_yes_ranges = ARRAY_SIZE(rp1_reg_ranges),
+};
+
+static const struct regmap_config rp1_clk_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = PLL_VIDEO_SEC,
+	.name = "rp1-clk",
+	.rd_table = &rp1_reg_table,
+};
+
+static int rp1_clk_probe(struct platform_device *pdev)
+{
+	const size_t asize = ARRAY_SIZE(clk_desc_array);
+	struct rp1_clk_desc *desc;
+	struct device *dev = &pdev->dev;
+	struct rp1_clockman *clockman;
+	struct clk_hw **hws;
+	unsigned int i;
+
+	clockman = devm_kzalloc(dev, struct_size(clockman, onecell.hws, asize),
+				GFP_KERNEL);
+	if (!clockman)
+		return -ENOMEM;
+
+	spin_lock_init(&clockman->regs_lock);
+	clockman->dev = dev;
+
+	clockman->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(clockman->regs))
+		return PTR_ERR(clockman->regs);
+
+	clockman->regmap = devm_regmap_init_mmio(dev, clockman->regs,
+						 &rp1_clk_regmap_cfg);
+	if (IS_ERR(clockman->regmap)) {
+		dev_err_probe(dev, PTR_ERR(clockman->regmap),
+			      "could not init clock regmap\n");
+		return PTR_ERR(clockman->regmap);
+	}
+
+	clockman->onecell.num = asize;
+	hws = clockman->onecell.hws;
+
+	for (i = 0; i < asize; i++) {
+		desc = clk_desc_array[i];
+		if (desc && desc->clk_register && desc->data) {
+			hws[i] = desc->clk_register(clockman, desc);
+			if (IS_ERR_OR_NULL(hws[i]))
+				dev_err_probe(dev, PTR_ERR(hws[i]),
+					      "Unable to register clock: %s\n",
+					      clk_hw_get_name(hws[i]));
+		}
+	}
+
+	platform_set_drvdata(pdev, clockman);
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+					   &clockman->onecell);
+}
+
+static const struct of_device_id rp1_clk_of_match[] = {
+	{ .compatible = "raspberrypi,rp1-clocks" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, rp1_clk_of_match);
+
+static struct platform_driver rp1_clk_driver = {
+	.driver = {
+		.name = "rp1-clk",
+		.of_match_table = rp1_clk_of_match,
+	},
+	.probe = rp1_clk_probe,
+};
+
+module_platform_driver(rp1_clk_driver);
+
+MODULE_AUTHOR("Naushir Patuck <naush at raspberrypi.com>");
+MODULE_AUTHOR("Andrea della Porta <andrea.porta at suse.com>");
+MODULE_DESCRIPTION("RP1 clock driver");
+MODULE_LICENSE("GPL");
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:27 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:27 +0100
Subject: [PATCH v8 06/13] pinctrl: rp1: Implement RaspberryPi RP1 gpio support
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <511141fb10db44d0500de5a8e65ac1b3aa7316ed.1742418429.git.andrea.porta@suse.com>

The RP1 is an MFD supporting a gpio controller and /pinmux/pinctrl.
Add minimum support for the gpio only portion. The driver is in
pinctrl folder since upcoming patches will add the pinmux/pinctrl
support where the gpio part can be seen as an addition.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
Reviewed-by: Stefan Wahren <wahrenst at gmx.net>
---
 MAINTAINERS                   |   1 +
 drivers/pinctrl/Kconfig       |  11 +
 drivers/pinctrl/Makefile      |   1 +
 drivers/pinctrl/pinctrl-rp1.c | 790 ++++++++++++++++++++++++++++++++++
 4 files changed, 803 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-rp1.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 75263700370d..c2749c588809 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19752,6 +19752,7 @@ RASPBERRY PI RP1 PCI DRIVER
 M:	Andrea della Porta <andrea.porta at suse.com>
 S:	Maintained
 F:	drivers/clk/clk-rp1.c
+F:	drivers/pinctrl/pinctrl-rp1.c
 
 RC-CORE / LIRC FRAMEWORK
 M:	Sean Young <sean at mess.org>
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 95a8e2b9a614..53b265cabc26 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -612,6 +612,17 @@ config PINCTRL_MLXBF3
 	  each pin. This driver can also be built as a module called
 	  pinctrl-mlxbf3.
 
+config PINCTRL_RP1
+	tristate "Pinctrl driver for RP1"
+	depends on MISC_RP1
+	default MISC_RP1
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	help
+	  Enable the gpio and pinctrl/mux driver for RaspberryPi RP1
+	  multi function device.
+
 source "drivers/pinctrl/actions/Kconfig"
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index fba1c56624c0..6fb77de58545 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl-pic32.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
+obj-$(CONFIG_PINCTRL_RP1)       += pinctrl-rp1.o
 obj-$(CONFIG_PINCTRL_SCMI)	+= pinctrl-scmi.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c
new file mode 100644
index 000000000000..7ff2db0320ba
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -0,0 +1,790 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Raspberry Pi RP1 GPIO unit
+ *
+ * Copyright (C) 2023 Raspberry Pi Ltd.
+ *
+ * This driver is inspired by:
+ * pinctrl-bcm2835.c, please see original file for copyright information
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MODULE_NAME "pinctrl-rp1"
+#define RP1_NUM_GPIOS	54
+#define RP1_NUM_BANKS	3
+
+#define RP1_INT_EDGE_FALLING		BIT(0)
+#define RP1_INT_EDGE_RISING		BIT(1)
+#define RP1_INT_LEVEL_LOW		BIT(2)
+#define RP1_INT_LEVEL_HIGH		BIT(3)
+#define RP1_INT_MASK			GENMASK(3, 0)
+#define RP1_INT_EDGE_BOTH		(RP1_INT_EDGE_FALLING |	\
+					 RP1_INT_EDGE_RISING)
+
+#define RP1_FSEL_COUNT			9
+
+#define RP1_FSEL_ALT0			0x00
+#define RP1_FSEL_GPIO			0x05
+#define RP1_FSEL_NONE			0x09
+#define RP1_FSEL_NONE_HW		0x1f
+
+#define RP1_PAD_DRIVE_2MA		0x0
+#define RP1_PAD_DRIVE_4MA		0x1
+#define RP1_PAD_DRIVE_8MA		0x2
+#define RP1_PAD_DRIVE_12MA		0x3
+
+enum {
+	RP1_PUD_OFF			= 0,
+	RP1_PUD_DOWN			= 1,
+	RP1_PUD_UP			= 2,
+};
+
+enum {
+	RP1_DIR_OUTPUT			= 0,
+	RP1_DIR_INPUT			= 1,
+};
+
+enum {
+	RP1_OUTOVER_PERI		= 0,
+	RP1_OUTOVER_INVPERI		= 1,
+	RP1_OUTOVER_LOW			= 2,
+	RP1_OUTOVER_HIGH		= 3,
+};
+
+enum {
+	RP1_OEOVER_PERI			= 0,
+	RP1_OEOVER_INVPERI		= 1,
+	RP1_OEOVER_DISABLE		= 2,
+	RP1_OEOVER_ENABLE		= 3,
+};
+
+enum {
+	RP1_INOVER_PERI			= 0,
+	RP1_INOVER_INVPERI		= 1,
+	RP1_INOVER_LOW			= 2,
+	RP1_INOVER_HIGH			= 3,
+};
+
+enum {
+	RP1_GPIO_CTRL_IRQRESET_SET		= 0,
+	RP1_GPIO_CTRL_INT_CLR			= 1,
+	RP1_GPIO_CTRL_INT_SET			= 2,
+	RP1_GPIO_CTRL_OEOVER			= 3,
+	RP1_GPIO_CTRL_FUNCSEL			= 4,
+	RP1_GPIO_CTRL_OUTOVER			= 5,
+	RP1_GPIO_CTRL				= 6,
+};
+
+enum {
+	RP1_INTE_SET			= 0,
+	RP1_INTE_CLR			= 1,
+};
+
+enum {
+	RP1_RIO_OUT_SET			= 0,
+	RP1_RIO_OUT_CLR			= 1,
+	RP1_RIO_OE			= 2,
+	RP1_RIO_OE_SET			= 3,
+	RP1_RIO_OE_CLR			= 4,
+	RP1_RIO_IN			= 5,
+};
+
+enum {
+	RP1_PAD_SLEWFAST		= 0,
+	RP1_PAD_SCHMITT			= 1,
+	RP1_PAD_PULL			= 2,
+	RP1_PAD_DRIVE			= 3,
+	RP1_PAD_IN_ENABLE		= 4,
+	RP1_PAD_OUT_DISABLE		= 5,
+};
+
+static const struct reg_field rp1_gpio_fields[] = {
+	[RP1_GPIO_CTRL_IRQRESET_SET]	= REG_FIELD(0x2004, 28, 28),
+	[RP1_GPIO_CTRL_INT_CLR]		= REG_FIELD(0x3004, 20, 23),
+	[RP1_GPIO_CTRL_INT_SET]		= REG_FIELD(0x2004, 20, 23),
+	[RP1_GPIO_CTRL_OEOVER]		= REG_FIELD(0x0004, 14, 15),
+	[RP1_GPIO_CTRL_FUNCSEL]		= REG_FIELD(0x0004, 0, 4),
+	[RP1_GPIO_CTRL_OUTOVER]		= REG_FIELD(0x0004, 12, 13),
+	[RP1_GPIO_CTRL]			= REG_FIELD(0x0004, 0, 31),
+};
+
+static const struct reg_field rp1_inte_fields[] = {
+	[RP1_INTE_SET]			= REG_FIELD(0x2000, 0, 0),
+	[RP1_INTE_CLR]			= REG_FIELD(0x3000, 0, 0),
+};
+
+static const struct reg_field rp1_rio_fields[] = {
+	[RP1_RIO_OUT_SET]		= REG_FIELD(0x2000, 0, 0),
+	[RP1_RIO_OUT_CLR]		= REG_FIELD(0x3000, 0, 0),
+	[RP1_RIO_OE]			= REG_FIELD(0x0004, 0, 0),
+	[RP1_RIO_OE_SET]		= REG_FIELD(0x2004, 0, 0),
+	[RP1_RIO_OE_CLR]		= REG_FIELD(0x3004, 0, 0),
+	[RP1_RIO_IN]			= REG_FIELD(0x0008, 0, 0),
+};
+
+static const struct reg_field rp1_pad_fields[] = {
+	[RP1_PAD_SLEWFAST]		= REG_FIELD(0, 0, 0),
+	[RP1_PAD_SCHMITT]		= REG_FIELD(0, 1, 1),
+	[RP1_PAD_PULL]			= REG_FIELD(0, 2, 3),
+	[RP1_PAD_DRIVE]			= REG_FIELD(0, 4, 5),
+	[RP1_PAD_IN_ENABLE]		= REG_FIELD(0, 6, 6),
+	[RP1_PAD_OUT_DISABLE]		= REG_FIELD(0, 7, 7),
+};
+
+struct rp1_iobank_desc {
+	int min_gpio;
+	int num_gpios;
+	int gpio_offset;
+	int inte_offset;
+	int ints_offset;
+	int rio_offset;
+	int pads_offset;
+};
+
+struct rp1_pin_info {
+	u8 num;
+	u8 bank;
+	u8 offset;
+	u8 fsel;
+	u8 irq_type;
+
+	struct regmap_field *gpio[ARRAY_SIZE(rp1_gpio_fields)];
+	struct regmap_field *rio[ARRAY_SIZE(rp1_rio_fields)];
+	struct regmap_field *inte[ARRAY_SIZE(rp1_inte_fields)];
+	struct regmap_field *pad[ARRAY_SIZE(rp1_pad_fields)];
+};
+
+struct rp1_pinctrl {
+	struct device *dev;
+	void __iomem *gpio_base;
+	void __iomem *rio_base;
+	void __iomem *pads_base;
+	int irq[RP1_NUM_BANKS];
+	struct rp1_pin_info pins[RP1_NUM_GPIOS];
+
+	struct pinctrl_dev *pctl_dev;
+	struct gpio_chip gpio_chip;
+	struct pinctrl_gpio_range gpio_range;
+
+	raw_spinlock_t irq_lock[RP1_NUM_BANKS];
+};
+
+static const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = {
+	/*         gpio   inte    ints     rio    pads */
+	{  0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 },
+	{ 28,  6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 },
+	{ 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 },
+};
+
+static int rp1_pinconf_set(struct rp1_pin_info *pin,
+			   unsigned int offset, unsigned long *configs,
+			   unsigned int num_configs);
+
+static struct rp1_pin_info *rp1_get_pin(struct gpio_chip *chip,
+					unsigned int offset)
+{
+	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+
+	if (pc && offset < RP1_NUM_GPIOS)
+		return &pc->pins[offset];
+	return NULL;
+}
+
+static void rp1_input_enable(struct rp1_pin_info *pin, int value)
+{
+	regmap_field_write(pin->pad[RP1_PAD_IN_ENABLE], !!value);
+}
+
+static void rp1_output_enable(struct rp1_pin_info *pin, int value)
+{
+	regmap_field_write(pin->pad[RP1_PAD_OUT_DISABLE], !value);
+}
+
+static u32 rp1_get_fsel(struct rp1_pin_info *pin)
+{
+	u32 oeover, fsel;
+
+	regmap_field_read(pin->gpio[RP1_GPIO_CTRL_OEOVER], &oeover);
+	regmap_field_read(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], &fsel);
+
+	if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT)
+		fsel = RP1_FSEL_NONE;
+
+	return fsel;
+}
+
+static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
+{
+	if (fsel >= RP1_FSEL_COUNT)
+		fsel = RP1_FSEL_NONE_HW;
+
+	rp1_input_enable(pin, 1);
+	rp1_output_enable(pin, 1);
+
+	if (fsel == RP1_FSEL_NONE) {
+		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_DISABLE);
+	} else {
+		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OUTOVER], RP1_OUTOVER_PERI);
+		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_PERI);
+	}
+
+	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], fsel);
+}
+
+static int rp1_get_dir(struct rp1_pin_info *pin)
+{
+	unsigned int val;
+
+	regmap_field_read(pin->rio[RP1_RIO_OE], &val);
+
+	return !val ? RP1_DIR_INPUT : RP1_DIR_OUTPUT;
+}
+
+static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input)
+{
+	int reg = is_input ? RP1_RIO_OE_CLR : RP1_RIO_OE_SET;
+
+	regmap_field_write(pin->rio[reg], 1);
+}
+
+static int rp1_get_value(struct rp1_pin_info *pin)
+{
+	unsigned int val;
+
+	regmap_field_read(pin->rio[RP1_RIO_IN], &val);
+
+	return !!val;
+}
+
+static void rp1_set_value(struct rp1_pin_info *pin, int value)
+{
+	/* Assume the pin is already an output */
+	int reg = value ? RP1_RIO_OUT_SET : RP1_RIO_OUT_CLR;
+
+	regmap_field_write(pin->rio[reg], 1);
+}
+
+static int rp1_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+	int ret;
+
+	if (!pin)
+		return -EINVAL;
+
+	ret = rp1_get_value(pin);
+
+	return ret;
+}
+
+static void rp1_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+
+	if (pin)
+		rp1_set_value(pin, value);
+}
+
+static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+	u32 fsel;
+
+	if (!pin)
+		return -EINVAL;
+
+	fsel = rp1_get_fsel(pin);
+	if (fsel != RP1_FSEL_GPIO)
+		return -EINVAL;
+
+	return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ?
+		GPIO_LINE_DIRECTION_OUT :
+		GPIO_LINE_DIRECTION_IN;
+}
+
+static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+
+	if (!pin)
+		return -EINVAL;
+	rp1_set_dir(pin, RP1_DIR_INPUT);
+	rp1_set_fsel(pin, RP1_FSEL_GPIO);
+
+	return 0;
+}
+
+static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
+				     int value)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+
+	if (!pin)
+		return -EINVAL;
+	rp1_set_value(pin, value);
+	rp1_set_dir(pin, RP1_DIR_OUTPUT);
+	rp1_set_fsel(pin, RP1_FSEL_GPIO);
+
+	return 0;
+}
+
+static int rp1_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+			       unsigned long config)
+{
+	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
+	unsigned long configs[] = { config };
+
+	return rp1_pinconf_set(pin, offset, configs,
+			       ARRAY_SIZE(configs));
+}
+
+static const struct gpio_chip rp1_gpio_chip = {
+	.label = MODULE_NAME,
+	.owner = THIS_MODULE,
+	.request = gpiochip_generic_request,
+	.free = gpiochip_generic_free,
+	.direction_input = rp1_gpio_direction_input,
+	.direction_output = rp1_gpio_direction_output,
+	.get_direction = rp1_gpio_get_direction,
+	.get = rp1_gpio_get,
+	.set = rp1_gpio_set,
+	.base = -1,
+	.set_config = rp1_gpio_set_config,
+	.ngpio = RP1_NUM_GPIOS,
+	.can_sleep = false,
+};
+
+static void rp1_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
+	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+	const struct rp1_iobank_desc *bank;
+	int irq = irq_desc_get_irq(desc);
+	unsigned long ints;
+	int bit_pos;
+
+	if (pc->irq[0] == irq)
+		bank = &rp1_iobanks[0];
+	else if (pc->irq[1] == irq)
+		bank = &rp1_iobanks[1];
+	else
+		bank = &rp1_iobanks[2];
+
+	chained_irq_enter(host_chip, desc);
+
+	ints = readl(pc->gpio_base + bank->ints_offset);
+	for_each_set_bit(bit_pos, &ints, 32) {
+		struct rp1_pin_info *pin = rp1_get_pin(chip, bit_pos);
+
+		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
+						     bank->gpio_offset + bit_pos));
+	}
+
+	chained_irq_exit(host_chip, desc);
+}
+
+static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable)
+{
+	int reg = enable ? RP1_INTE_SET : RP1_INTE_CLR;
+
+	regmap_field_write(pin->inte[reg], 1);
+	if (!enable)
+		/* Clear any latched events */
+		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+}
+
+static void rp1_gpio_irq_enable(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	unsigned int gpio = irqd_to_hwirq(data);
+	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
+
+	rp1_gpio_irq_config(pin, true);
+}
+
+static void rp1_gpio_irq_disable(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	unsigned int gpio = irqd_to_hwirq(data);
+	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
+
+	rp1_gpio_irq_config(pin, false);
+}
+
+static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type)
+{
+	u32 irq_flags;
+
+	switch (type) {
+	case IRQ_TYPE_NONE:
+		irq_flags = 0;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		irq_flags = RP1_INT_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_flags = RP1_INT_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_flags = RP1_INT_EDGE_RISING | RP1_INT_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_flags = RP1_INT_LEVEL_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_flags = RP1_INT_LEVEL_LOW;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Clear them all */
+	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_CLR], RP1_INT_MASK);
+
+	/* Set those that are needed */
+	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_SET], irq_flags);
+	pin->irq_type = type;
+
+	return 0;
+}
+
+static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	unsigned int gpio = irqd_to_hwirq(data);
+	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
+	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+	int bank = pin->bank;
+	unsigned long flags;
+	int ret;
+
+	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
+
+	ret = rp1_irq_set_type(pin, type);
+	if (!ret) {
+		if (type & IRQ_TYPE_EDGE_BOTH)
+			irq_set_handler_locked(data, handle_edge_irq);
+		else
+			irq_set_handler_locked(data, handle_level_irq);
+	}
+
+	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+
+	return ret;
+}
+
+static void rp1_gpio_irq_ack(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	unsigned int gpio = irqd_to_hwirq(data);
+	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
+
+	/* Clear any latched events */
+	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+}
+
+static struct irq_chip rp1_gpio_irq_chip = {
+	.name = MODULE_NAME,
+	.irq_enable = rp1_gpio_irq_enable,
+	.irq_disable = rp1_gpio_irq_disable,
+	.irq_set_type = rp1_gpio_irq_set_type,
+	.irq_ack = rp1_gpio_irq_ack,
+	.irq_mask = rp1_gpio_irq_disable,
+	.irq_unmask = rp1_gpio_irq_enable,
+	.flags = IRQCHIP_IMMUTABLE,
+	GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
+{
+	regmap_field_write(pin->pad[RP1_PAD_PULL], arg & 0x3);
+}
+
+static int rp1_pinconf_set(struct rp1_pin_info *pin, unsigned int offset,
+			   unsigned long *configs, unsigned int num_configs)
+{
+	u32 param, arg;
+	int i;
+
+	if (!pin)
+		return -EINVAL;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			rp1_pull_config_set(pin, RP1_PUD_OFF);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			rp1_pull_config_set(pin, RP1_PUD_DOWN);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			rp1_pull_config_set(pin, RP1_PUD_UP);
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			rp1_input_enable(pin, arg);
+			break;
+
+		case PIN_CONFIG_OUTPUT_ENABLE:
+			rp1_output_enable(pin, arg);
+			break;
+
+		case PIN_CONFIG_OUTPUT:
+			rp1_set_value(pin, arg);
+			rp1_set_dir(pin, RP1_DIR_OUTPUT);
+			rp1_set_fsel(pin, RP1_FSEL_GPIO);
+			break;
+
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			regmap_field_write(pin->pad[RP1_PAD_SCHMITT], !!arg);
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			regmap_field_write(pin->pad[RP1_PAD_SLEWFAST], !!arg);
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			switch (arg) {
+			case 2:
+				arg = RP1_PAD_DRIVE_2MA;
+				break;
+			case 4:
+				arg = RP1_PAD_DRIVE_4MA;
+				break;
+			case 8:
+				arg = RP1_PAD_DRIVE_8MA;
+				break;
+			case 12:
+				arg = RP1_PAD_DRIVE_12MA;
+				break;
+			default:
+				return -ENOTSUPP;
+			}
+			regmap_field_write(pin->pad[RP1_PAD_DRIVE], arg);
+			break;
+
+		default:
+			return -ENOTSUPP;
+
+		} /* switch param type */
+	} /* for each config */
+
+	return 0;
+}
+
+static const struct of_device_id rp1_pinctrl_match[] = {
+	{ .compatible = "raspberrypi,rp1-gpio" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rp1_pinctrl_match);
+
+static struct rp1_pinctrl rp1_pinctrl_data = {};
+
+static const struct regmap_config rp1_pinctrl_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+	.name = "rp1-pinctrl",
+};
+
+static int rp1_gen_regfield(struct device *dev,
+			    const struct reg_field *array,
+			    size_t array_size,
+			    int reg_off,
+			    int pin_off,
+			    bool additive_offset,
+			    struct regmap *regmap,
+			    struct regmap_field *out[])
+{
+	struct reg_field regfield;
+	int k;
+
+	for (k = 0; k < array_size; k++) {
+		regfield = array[k];
+		regfield.reg = (additive_offset ? regfield.reg : 0) + reg_off;
+		if (pin_off >= 0) {
+			regfield.lsb = pin_off;
+			regfield.msb = regfield.lsb;
+		}
+		out[k] = devm_regmap_field_alloc(dev, regmap, regfield);
+
+		if (IS_ERR(out[k]))
+			return PTR_ERR(out[k]);
+	}
+
+	return 0;
+}
+
+static int rp1_pinctrl_probe(struct platform_device *pdev)
+{
+	struct regmap *gpio_regmap, *rio_regmap, *pads_regmap;
+	struct rp1_pinctrl *pc = &rp1_pinctrl_data;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct gpio_irq_chip *girq;
+	int err, i;
+
+	pc->dev = dev;
+	pc->gpio_chip = rp1_gpio_chip;
+	pc->gpio_chip.parent = dev;
+
+	pc->gpio_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pc->gpio_base))
+		return dev_err_probe(dev, PTR_ERR(pc->gpio_base), "could not get GPIO IO memory\n");
+
+	pc->rio_base = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(pc->rio_base))
+		return dev_err_probe(dev, PTR_ERR(pc->rio_base), "could not get RIO IO memory\n");
+
+	pc->pads_base = devm_platform_ioremap_resource(pdev, 2);
+	if (IS_ERR(pc->pads_base))
+		return dev_err_probe(dev, PTR_ERR(pc->pads_base), "could not get PADS IO memory\n");
+
+	gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base,
+					    &rp1_pinctrl_regmap_cfg);
+	if (IS_ERR(gpio_regmap))
+		return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n");
+
+	rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base,
+					   &rp1_pinctrl_regmap_cfg);
+	if (IS_ERR(rio_regmap))
+		return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n");
+
+	pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base,
+					    &rp1_pinctrl_regmap_cfg);
+	if (IS_ERR(pads_regmap))
+		return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n");
+
+	for (i = 0; i < RP1_NUM_BANKS; i++) {
+		const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
+		int j;
+
+		for (j = 0; j < bank->num_gpios; j++) {
+			struct rp1_pin_info *pin =
+				&pc->pins[bank->min_gpio + j];
+			int reg_off;
+
+			pin->num = bank->min_gpio + j;
+			pin->bank = i;
+			pin->offset = j;
+
+			reg_off = bank->gpio_offset + pin->offset *
+				  sizeof(u32) * 2;
+			err = rp1_gen_regfield(dev,
+					       rp1_gpio_fields,
+					       ARRAY_SIZE(rp1_gpio_fields),
+					       reg_off,
+					       -1,
+					       true,
+					       gpio_regmap,
+					       pin->gpio);
+
+			if (err)
+				return dev_err_probe(dev, err,
+						     "Unable to allocate regmap for gpio\n");
+
+			reg_off = bank->inte_offset;
+			err = rp1_gen_regfield(dev,
+					       rp1_inte_fields,
+					       ARRAY_SIZE(rp1_inte_fields),
+					       reg_off,
+					       pin->offset,
+					       true,
+					       gpio_regmap,
+					       pin->inte);
+
+			if (err)
+				return dev_err_probe(dev, err,
+						     "Unable to allocate regmap for inte\n");
+
+			reg_off = bank->rio_offset;
+			err = rp1_gen_regfield(dev,
+					       rp1_rio_fields,
+					       ARRAY_SIZE(rp1_rio_fields),
+					       reg_off,
+					       pin->offset,
+					       true,
+					       rio_regmap,
+					       pin->rio);
+
+			if (err)
+				return dev_err_probe(dev, err,
+						     "Unable to allocate regmap for rio\n");
+
+			reg_off = bank->pads_offset + pin->offset * sizeof(u32);
+			err = rp1_gen_regfield(dev,
+					       rp1_pad_fields,
+					       ARRAY_SIZE(rp1_pad_fields),
+					       reg_off,
+					       -1,
+					       false,
+					       pads_regmap,
+					       pin->pad);
+
+			if (err)
+				return dev_err_probe(dev, err,
+						     "Unable to allocate regmap for pad\n");
+		}
+
+		raw_spin_lock_init(&pc->irq_lock[i]);
+	}
+
+	girq = &pc->gpio_chip.irq;
+	girq->chip = &rp1_gpio_irq_chip;
+	girq->parent_handler = rp1_gpio_irq_handler;
+	girq->num_parents = RP1_NUM_BANKS;
+	girq->parents = pc->irq;
+	girq->default_type = IRQ_TYPE_NONE;
+	girq->handler = handle_level_irq;
+
+	/*
+	 * Use the same handler for all groups: this is necessary
+	 * since we use one gpiochip to cover all lines - the
+	 * irq handler then needs to figure out which group and
+	 * bank that was firing the IRQ and look up the per-group
+	 * and bank data.
+	 */
+	for (i = 0; i < RP1_NUM_BANKS; i++) {
+		pc->irq[i] = irq_of_parse_and_map(np, i);
+		if (!pc->irq[i]) {
+			girq->num_parents = i;
+			break;
+		}
+	}
+
+	platform_set_drvdata(pdev, pc);
+
+	err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
+	if (err)
+		return dev_err_probe(dev, err, "could not add GPIO chip\n");
+
+	return 0;
+}
+
+static struct platform_driver rp1_pinctrl_driver = {
+	.probe = rp1_pinctrl_probe,
+	.driver = {
+		.name = MODULE_NAME,
+		.of_match_table = rp1_pinctrl_match,
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(rp1_pinctrl_driver);
+
+MODULE_AUTHOR("Phil Elwell <phil at raspberrypi.com>");
+MODULE_AUTHOR("Andrea della Porta <andrea.porta at suse.com>");
+MODULE_DESCRIPTION("RP1 pinctrl/gpio driver");
+MODULE_LICENSE("GPL");
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:28 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:28 +0100
Subject: [PATCH v8 07/13] arm64: dts: rp1: Add support for RaspberryPi's RP1 device
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <99269f7762ec0124315e0e8977d9ca4f469f89ce.1742418429.git.andrea.porta@suse.com>

RaspberryPi RP1 is a multi function PCI endpoint device that
exposes several subperipherals via PCI BAR.
Add a dtb overlay that will be compiled into a binary blob
and linked in the RP1 driver.
This overlay offers just minimal support to represent the
RP1 device itself, the sub-peripherals will be added by
future patches.

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
---
 MAINTAINERS                                  |  1 +
 arch/arm64/boot/dts/broadcom/rp1-common.dtsi | 42 ++++++++++++++++++++
 arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi  | 14 +++++++
 3 files changed, 57 insertions(+)
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1-common.dtsi
 create mode 100644 arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi

diff --git a/MAINTAINERS b/MAINTAINERS
index c2749c588809..6e07b4fb1924 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19751,6 +19751,7 @@ F:	drivers/media/platform/raspberrypi/rp1-cfe/
 RASPBERRY PI RP1 PCI DRIVER
 M:	Andrea della Porta <andrea.porta at suse.com>
 S:	Maintained
+F:	arch/arm64/boot/dts/broadcom/rp1*.dts*
 F:	drivers/clk/clk-rp1.c
 F:	drivers/pinctrl/pinctrl-rp1.c
 
diff --git a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi
new file mode 100644
index 000000000000..5002a375eb0b
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/raspberrypi,rp1-clocks.h>
+
+pci_ep_bus: pci-ep-bus at 1 {
+	compatible = "simple-bus";
+	ranges = <0x00 0x40000000  0x01 0x00 0x00000000  0x00 0x00400000>;
+	dma-ranges = <0x10 0x00000000  0x43000000 0x10 0x00000000  0x10 0x00000000>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	rp1_clocks: clocks at 40018000 {
+		compatible = "raspberrypi,rp1-clocks";
+		reg = <0x00 0x40018000 0x0 0x10038>;
+		#clock-cells = <1>;
+		clocks = <&clk_rp1_xosc>;
+		assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>,
+				  <&rp1_clocks RP1_PLL_SYS>,
+				  <&rp1_clocks RP1_PLL_SYS_SEC>,
+				  <&rp1_clocks RP1_CLK_SYS>;
+		assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE
+				       <200000000>,  // RP1_PLL_SYS
+				       <125000000>,  // RP1_PLL_SYS_SEC
+				       <200000000>;  // RP1_CLK_SYS
+	};
+
+	rp1_gpio: pinctrl at 400d0000 {
+		compatible = "raspberrypi,rp1-gpio";
+		reg = <0x00 0x400d0000  0x0 0xc000>,
+		      <0x00 0x400e0000  0x0 0xc000>,
+		      <0x00 0x400f0000  0x0 0xc000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupts = <0 IRQ_TYPE_LEVEL_HIGH>,
+			     <1 IRQ_TYPE_LEVEL_HIGH>,
+			     <2 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
diff --git a/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi b/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi
new file mode 100644
index 000000000000..0ef30d7f1c35
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+rp1_nexus {
+	compatible = "pci1de4,1";
+	#address-cells = <3>;
+	#size-cells = <2>;
+	ranges = <0x01 0x00 0x00000000
+		  0x02000000 0x00 0x00000000
+		  0x0 0x400000>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	#include "rp1-common.dtsi"
+};
-- 
2.35.3



From andrea.porta at suse.com  Wed Mar 19 14:52:29 2025
From: andrea.porta at suse.com (Andrea della Porta)
Date: Wed, 19 Mar 2025 22:52:29 +0100
Subject: [PATCH v8 08/13] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <cover.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
Message-ID: <3fbc487bc0e4b855ffbee8ed62cfb6bf3b0592e8.1742418429.git.andrea.porta@suse.com>

The RaspberryPi RP1 is a PCI multi function device containing
peripherals ranging from Ethernet to USB controller, I2C, SPI
and others.

Implement a bare minimum driver to operate the RP1, leveraging
actual OF based driver implementations for the on-board peripherals
by loading a devicetree overlay during driver probe if the RP1
node is not already present in the DT.

The peripherals are accessed by mapping MMIO registers starting
from PCI BAR1 region.

With the overlay approach we can achieve more generic and agnostic
approach to managing this chipset, being that it is a PCI endpoint
and could possibly be reused in other hw implementations. The
presented approach is also used by Bootlin's Microchip LAN966x
patchset (see link) as well, for a similar chipset.
In this case, the inclusion tree for the DT overlay is as follow
(the arrow points to the includer):

 rp1-pci.dtso <---- rp1-common.dtsi

On the other hand, to ensure compatibility with downstream, this
driver can also work with a DT already comprising the RP1 node, so
the dynamically loaded overlay will not be used if the DT is already
fully defined.

The reason why this driver is contained in drivers/misc has
been paved by Bootlin's LAN966X driver, which first used the
overlay approach to implement non discoverable peripherals behind a
PCI bus. For RP1, the same arguments apply: it's not used as an SoC
since the driver code is not running on-chip and is not like an MFD
since it does not really need all the MFD infrastructure (shared regs,
etc.). So, for this particular use, misc has been proposed and deemed
as a good choice. For further details about that please check the links.

This driver is heavily based on downstream code from RaspberryPi
Foundation, and the original author is Phil Elwell.

Link: https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf
Link: https://lore.kernel.org/all/20240612140208.GC1504919 at google.com/
Link: https://lore.kernel.org/all/83f7fa09-d0e6-4f36-a27d-cee08979be2a at app.fastmail.com/
Link: https://lore.kernel.org/all/2024081356-mutable-everyday-6f9d at gregkh/
Link: https://lore.kernel.org/all/20240808154658.247873-1-herve.codina at bootlin.com/

Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
---
 MAINTAINERS                   |   1 +
 drivers/misc/Kconfig          |   1 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/rp1/Kconfig      |  20 ++
 drivers/misc/rp1/Makefile     |   3 +
 drivers/misc/rp1/rp1-pci.dtso |  25 +++
 drivers/misc/rp1/rp1_pci.c    | 333 ++++++++++++++++++++++++++++++++++
 drivers/pci/quirks.c          |   1 +
 include/linux/pci_ids.h       |   3 +
 9 files changed, 388 insertions(+)
 create mode 100644 drivers/misc/rp1/Kconfig
 create mode 100644 drivers/misc/rp1/Makefile
 create mode 100644 drivers/misc/rp1/rp1-pci.dtso
 create mode 100644 drivers/misc/rp1/rp1_pci.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6e07b4fb1924..a204075c4be7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19753,6 +19753,7 @@ M:	Andrea della Porta <andrea.porta at suse.com>
 S:	Maintained
 F:	arch/arm64/boot/dts/broadcom/rp1*.dts*
 F:	drivers/clk/clk-rp1.c
+F:	drivers/misc/rp1/
 F:	drivers/pinctrl/pinctrl-rp1.c
 
 RC-CORE / LIRC FRAMEWORK
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 56bc72c7ce4a..af8c3be967bf 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -649,4 +649,5 @@ source "drivers/misc/uacce/Kconfig"
 source "drivers/misc/pvpanic/Kconfig"
 source "drivers/misc/mchp_pci1xxxx/Kconfig"
 source "drivers/misc/keba/Kconfig"
+source "drivers/misc/rp1/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 545aad06d088..5df79dd90c9c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -75,3 +75,4 @@ lan966x-pci-objs		:= lan966x_pci.o
 lan966x-pci-objs		+= lan966x_pci.dtbo.o
 obj-$(CONFIG_MCHP_LAN966X_PCI)	+= lan966x-pci.o
 obj-y				+= keba/
+obj-$(CONFIG_MISC_RP1)		+= rp1/
diff --git a/drivers/misc/rp1/Kconfig b/drivers/misc/rp1/Kconfig
new file mode 100644
index 000000000000..5232e70d3079
--- /dev/null
+++ b/drivers/misc/rp1/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# RaspberryPi RP1 misc device
+#
+
+config MISC_RP1
+	tristate "RaspberryPi RP1 misc device"
+	depends on OF_IRQ && OF_OVERLAY && PCI_MSI && PCI_QUIRKS
+	select PCI_DYNAMIC_OF_NODES
+	help
+	  Support the RP1 peripheral chip found on Raspberry Pi 5 board.
+
+	  This device supports several sub-devices including e.g. Ethernet
+	  controller, USB controller, I2C, SPI and UART.
+
+	  The driver is responsible for enabling the DT node once the PCIe
+	  endpoint has been configured, and handling interrupts.
+
+	  This driver uses an overlay to load other drivers to support for
+	  RP1 internal sub-devices.
diff --git a/drivers/misc/rp1/Makefile b/drivers/misc/rp1/Makefile
new file mode 100644
index 000000000000..508b4cb05627
--- /dev/null
+++ b/drivers/misc/rp1/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MISC_RP1)		+= rp1-pci.o
+rp1-pci-objs			:= rp1_pci.o rp1-pci.dtbo.o
diff --git a/drivers/misc/rp1/rp1-pci.dtso b/drivers/misc/rp1/rp1-pci.dtso
new file mode 100644
index 000000000000..eea826b36e02
--- /dev/null
+++ b/drivers/misc/rp1/rp1-pci.dtso
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * The dts overlay is included from the dts directory so
+ * it can be possible to check it with CHECK_DTBS while
+ * also compile it from the driver source directory.
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+	fragment at 0 {
+		target-path="";
+		__overlay__ {
+			compatible = "pci1de4,1";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+
+			#include "arm64/broadcom/rp1-common.dtsi"
+		};
+	};
+};
diff --git a/drivers/misc/rp1/rp1_pci.c b/drivers/misc/rp1/rp1_pci.c
new file mode 100644
index 000000000000..c056749ff099
--- /dev/null
+++ b/drivers/misc/rp1/rp1_pci.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018-2025 Raspberry Pi Ltd.
+ *
+ * All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#define RP1_HW_IRQ_MASK		GENMASK(5, 0)
+
+#define REG_SET			0x800
+#define REG_CLR			0xc00
+
+/* MSI-X CFG registers start at 0x8 */
+#define MSIX_CFG(x) (0x8 + (4 * (x)))
+
+#define MSIX_CFG_IACK_EN        BIT(3)
+#define MSIX_CFG_IACK           BIT(2)
+#define MSIX_CFG_ENABLE         BIT(0)
+
+/* Address map */
+#define RP1_PCIE_APBS_BASE	0x108000
+
+/* Interrupts */
+#define RP1_INT_END		61
+
+/* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.lib */
+extern char __dtbo_rp1_pci_begin[];
+extern char __dtbo_rp1_pci_end[];
+
+struct rp1_dev {
+	struct pci_dev *pdev;
+	struct irq_domain *domain;
+	struct irq_data *pcie_irqds[64];
+	void __iomem *bar1;
+	int ovcs_id;	/* overlay changeset id */
+	bool level_triggered_irq[RP1_INT_END];
+};
+
+static void msix_cfg_set(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
+{
+	iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_SET + MSIX_CFG(hwirq));
+}
+
+static void msix_cfg_clr(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
+{
+	iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_CLR + MSIX_CFG(hwirq));
+}
+
+static void rp1_mask_irq(struct irq_data *irqd)
+{
+	struct rp1_dev *rp1 = irqd->domain->host_data;
+	struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
+
+	pci_msi_mask_irq(pcie_irqd);
+}
+
+static void rp1_unmask_irq(struct irq_data *irqd)
+{
+	struct rp1_dev *rp1 = irqd->domain->host_data;
+	struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
+
+	pci_msi_unmask_irq(pcie_irqd);
+}
+
+static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+	struct rp1_dev *rp1 = irqd->domain->host_data;
+	unsigned int hwirq = (unsigned int)irqd->hwirq;
+
+	switch (type) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		dev_dbg(&rp1->pdev->dev, "MSIX IACK EN for irq %u\n", hwirq);
+		msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
+		rp1->level_triggered_irq[hwirq] = true;
+	break;
+	case IRQ_TYPE_EDGE_RISING:
+		msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
+		rp1->level_triggered_irq[hwirq] = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct irq_chip rp1_irq_chip = {
+	.name		= "rp1_irq_chip",
+	.irq_mask	= rp1_mask_irq,
+	.irq_unmask	= rp1_unmask_irq,
+	.irq_set_type	= rp1_irq_set_type,
+};
+
+static void rp1_chained_handle_irq(struct irq_desc *desc)
+{
+	unsigned int hwirq = desc->irq_data.hwirq & RP1_HW_IRQ_MASK;
+	struct rp1_dev *rp1 = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned int virq;
+
+	chained_irq_enter(chip, desc);
+
+	virq = irq_find_mapping(rp1->domain, hwirq);
+	generic_handle_irq(virq);
+	if (rp1->level_triggered_irq[hwirq])
+		msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK);
+
+	chained_irq_exit(chip, desc);
+}
+
+static int rp1_irq_xlate(struct irq_domain *d, struct device_node *node,
+			 const u32 *intspec, unsigned int intsize,
+			 unsigned long *out_hwirq, unsigned int *out_type)
+{
+	struct rp1_dev *rp1 = d->host_data;
+	struct irq_data *pcie_irqd;
+	unsigned long hwirq;
+	int pcie_irq;
+	int ret;
+
+	ret = irq_domain_xlate_twocell(d, node, intspec, intsize,
+				       &hwirq, out_type);
+	if (ret)
+		return ret;
+
+	pcie_irq = pci_irq_vector(rp1->pdev, hwirq);
+	pcie_irqd = irq_get_irq_data(pcie_irq);
+	rp1->pcie_irqds[hwirq] = pcie_irqd;
+	*out_hwirq = hwirq;
+
+	return 0;
+}
+
+static int rp1_irq_activate(struct irq_domain *d, struct irq_data *irqd,
+			    bool reserve)
+{
+	struct rp1_dev *rp1 = d->host_data;
+
+	msix_cfg_set(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
+
+	return 0;
+}
+
+static void rp1_irq_deactivate(struct irq_domain *d, struct irq_data *irqd)
+{
+	struct rp1_dev *rp1 = d->host_data;
+
+	msix_cfg_clr(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
+}
+
+static const struct irq_domain_ops rp1_domain_ops = {
+	.xlate      = rp1_irq_xlate,
+	.activate   = rp1_irq_activate,
+	.deactivate = rp1_irq_deactivate,
+};
+
+static void rp1_unregister_interrupts(struct pci_dev *pdev)
+{
+	struct rp1_dev *rp1 = pci_get_drvdata(pdev);
+	int irq, i;
+
+	if (rp1->domain) {
+		for (i = 0; i < RP1_INT_END; i++) {
+			irq = irq_find_mapping(rp1->domain, i);
+			irq_dispose_mapping(irq);
+		}
+
+		irq_domain_remove(rp1->domain);
+	}
+
+	pci_free_irq_vectors(pdev);
+}
+
+static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	u32 dtbo_size = __dtbo_rp1_pci_end - __dtbo_rp1_pci_begin;
+	void *dtbo_start = __dtbo_rp1_pci_begin;
+	struct device *dev = &pdev->dev;
+	struct device_node *rp1_node;
+	bool skip_ovl = true;
+	struct rp1_dev *rp1;
+	int err = 0;
+	int i;
+
+	/*
+	 * Either use rp1_nexus node if already present in DT, or
+	 * set a flag to load it from overlay at runtime
+	 */
+	rp1_node = of_find_node_by_name(NULL, "rp1_nexus");
+	if (!rp1_node) {
+		rp1_node = dev_of_node(dev);
+		skip_ovl = false;
+	}
+
+	if (!rp1_node) {
+		dev_err(dev, "Missing of_node for device\n");
+		err = -EINVAL;
+		goto err_put_node;
+	}
+
+	rp1 = devm_kzalloc(&pdev->dev, sizeof(*rp1), GFP_KERNEL);
+	if (!rp1) {
+		err = -ENOMEM;
+		goto err_put_node;
+	}
+
+	rp1->pdev = pdev;
+
+	if (pci_resource_len(pdev, 1) <= 0x10000) {
+		dev_err(&pdev->dev,
+			"Not initialized - is the firmware running?\n");
+		err = -EINVAL;
+		goto err_put_node;
+	}
+
+	err = pcim_enable_device(pdev);
+	if (err < 0) {
+		err = dev_err_probe(&pdev->dev, err,
+				    "Enabling PCI device has failed");
+		goto err_put_node;
+	}
+
+	rp1->bar1 = pcim_iomap(pdev, 1, 0);
+	if (!rp1->bar1) {
+		dev_err(&pdev->dev, "Cannot map PCI BAR\n");
+		err = -EIO;
+		goto err_put_node;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_alloc_irq_vectors(pdev, RP1_INT_END, RP1_INT_END,
+				    PCI_IRQ_MSIX);
+	if (err < 0) {
+		err = dev_err_probe(&pdev->dev, err,
+				    "Failed to allocate MSI-X vectors\n");
+		goto err_put_node;
+	} else if (err != RP1_INT_END) {
+		dev_err(&pdev->dev, "Cannot allocate enough interrupts\n");
+		err = -EINVAL;
+		goto err_put_node;
+	}
+
+	pci_set_drvdata(pdev, rp1);
+	rp1->domain = irq_domain_add_linear(rp1_node, RP1_INT_END,
+					    &rp1_domain_ops, rp1);
+	if (!rp1->domain) {
+		dev_err(&pdev->dev, "Error creating IRQ domain\n");
+		err = -ENOMEM;
+		goto err_unregister_interrupts;
+	}
+
+	for (i = 0; i < RP1_INT_END; i++) {
+		unsigned int irq = irq_create_mapping(rp1->domain, i);
+
+		if (!irq) {
+			dev_err(&pdev->dev, "Failed to create irq mapping\n");
+			err = -EINVAL;
+			goto err_unregister_interrupts;
+		}
+
+		irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq);
+		irq_set_probe(irq);
+		irq_set_chained_handler_and_data(pci_irq_vector(pdev, i),
+						 rp1_chained_handle_irq, rp1);
+	}
+
+	if (!skip_ovl) {
+		err = of_overlay_fdt_apply(dtbo_start, dtbo_size, &rp1->ovcs_id,
+					   rp1_node);
+		if (err)
+			goto err_unregister_interrupts;
+	}
+
+	err = of_platform_default_populate(rp1_node, NULL, dev);
+	if (err) {
+		dev_err_probe(&pdev->dev, err, "Error populating devicetree\n");
+		goto err_unload_overlay;
+	}
+
+	return 0;
+
+err_unload_overlay:
+	of_overlay_remove(&rp1->ovcs_id);
+err_unregister_interrupts:
+	rp1_unregister_interrupts(pdev);
+err_put_node:
+	if (skip_ovl)
+		of_node_put(rp1_node);
+
+	return err;
+}
+
+static void rp1_remove(struct pci_dev *pdev)
+{
+	struct rp1_dev *rp1 = pci_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	of_platform_depopulate(dev);
+	of_overlay_remove(&rp1->ovcs_id);
+	rp1_unregister_interrupts(pdev);
+}
+
+static const struct pci_device_id dev_id_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, dev_id_table);
+
+static struct pci_driver rp1_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= dev_id_table,
+	.probe		= rp1_probe,
+	.remove		= rp1_remove,
+};
+
+module_pci_driver(rp1_driver);
+
+MODULE_AUTHOR("Phil Elwell <phil at raspberrypi.com>");
+MODULE_AUTHOR("Andrea della Porta <andrea.porta at suse.com>");
+MODULE_DESCRIPTION("RaspberryPi RP1 misc device");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b84ff7bade82..4dfda527c76b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -6283,6 +6283,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0, of_pci_make_dev_node);
 
 /*
  * Devices known to require a longer delay before first config space access
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index de5deb1a0118..b7a2c0fd589e 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2620,6 +2620,9 @@
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
 
+#define PCI_VENDOR_ID_RPI		0x1de4
+#define PCI_DEVICE_ID_RPI_RP1_C0	0x0001
+
 #define PCI_VENDOR_ID_ALIBABA		0x1ded
 
 #define PCI_VENDOR_ID_CXL		0x1e98
-- 
2.35.3



From martin.blumenstingl at googlemail.com  Wed Mar 19 15:26:40 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 19 Mar 2025 23:26:40 +0100
Subject: [PATCH v2 2/2] arm64: dts: amlogic: Add Ugoos AM3
In-Reply-To: <20250314-ugoos-am3-v2-2-422104b0cec5@posteo.net>
References: <20250314-ugoos-am3-v2-0-422104b0cec5@posteo.net> <20250314-ugoos-am3-v2-2-422104b0cec5@posteo.net>
Message-ID: <CAFBinCA1wa89vSo0TOs5yZWg_Fs8gt5vUerjhSNFAHMkANy6GQ@mail.gmail.com>

On Fri, Mar 14, 2025 at 12:11?AM J. Neusch?fer via B4 Relay
<devnull+j.ne.posteo.net at kernel.org> wrote:
>
> From: "J. Neusch?fer" <j.ne at posteo.net>
>
> The Ugoos AM3 is a small set-top box based on the Amlogic S912 SoC,
> with a board design that is very close to the Q20x development boards.
> The MMC max-frequency properties are copied from the downstream device
> tree.
>
>   https://ugoos.com/ugoos-am3-16g
>
> The following functionality has been tested and is known to work:
>  - debug serial port
>  - "update" button inside the case
>  - USB host mode, on all three ports
>  - HDMI video/audio output
>  - eMMC, MicroSD, and SDIO WLAN
>  - S/PDIF audio output
>  - Ethernet
>  - Infrared remote control input
>
> The following functionality doesn't seem to work:
>  - USB role switching and device mode on the "OTG" port
>  - case LED
>
> Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


From martin.blumenstingl at googlemail.com  Wed Mar 19 15:27:07 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 19 Mar 2025 23:27:07 +0100
Subject: [PATCH v5 1/2] dt-bindings: arm: amlogic: add S805Y and Mi TV Stick
In-Reply-To: <20250319190150.31529-3-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org> <20250319190150.31529-3-funderscore@postmarketos.org>
Message-ID: <CAFBinCC14dxYHWO1yMrGyvQigVR+h9qGaxUNjL49WXh-p5XMNg@mail.gmail.com>

On Wed, Mar 19, 2025 at 8:02?PM Ferass El Hafidi
<funderscore at postmarketos.org> wrote:
>
> Add support for the Amlogic S805Y SoC and the Xiaomi Mi TV Stick (aka.
> xiaomi-aquaman).  The S805Y is very similar to the S805X, with just a
> few minor differences.
>
> Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


From jpoimboe at kernel.org  Wed Mar 19 15:35:55 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Wed, 19 Mar 2025 15:35:55 -0700
Subject: [PATCH v2 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250319213707.1784775-2-song@kernel.org>
References: <20250319213707.1784775-1-song@kernel.org>
 <20250319213707.1784775-2-song@kernel.org>
Message-ID: <yrqgoc66te54tuffkrc74clsosiid2giw3gpc3kd3ddl4662tb@kiqh3ncfxwnl>

On Wed, Mar 19, 2025 at 02:37:06PM -0700, Song Liu wrote:
> +noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
> +			void *cookie, struct task_struct *task)
> +{
> +	struct kunwind_consume_entry_data data = {
> +		.consume_entry = consume_entry,
> +		.cookie = cookie,
> +	};
> +	int ret;
> +
> +	ret = kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL, true);
> +	if (ret == -ENOENT)
> +		ret = 0;

Is this check redundant with the -ENOENT check in do_kunwind() which
already converts ret to zero?

-- 
Josh


From martin.blumenstingl at googlemail.com  Wed Mar 19 15:36:14 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 19 Mar 2025 23:36:14 +0100
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for
 xiaomi-aquaman/Mi TV Stick
In-Reply-To: <20250319190150.31529-4-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org> <20250319190150.31529-4-funderscore@postmarketos.org>
Message-ID: <CAFBinCArRO-F59tOv9m27f+DV+qhy69OGUunGOAbDdfOdd5_Xg@mail.gmail.com>

Hello,

thanks for your contribution and sorry for the late reply!

On Wed, Mar 19, 2025 at 8:02?PM Ferass El Hafidi
<funderscore at postmarketos.org> wrote:
[...]
> +       au2: analog-amplifier {
> +               compatible = "simple-audio-amplifier";
> +               sound-name-prefix = "AU2";
> +               VCC-supply = <&vcc_5v>;
> +               enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
> +       };
I couldn't find any pictures online that show an analog audio output
(typically a 3.5mm socket).
Can you confirm that this is really present?

[...]
> +       sound {
> +               compatible = "amlogic,gx-sound-card";
> +               model = "XIAOMI-AQUAMAN";
> +               audio-aux-devs = <&au2>;
> +               audio-widgets = "Line", "Lineout";
> +               audio-routing = "AU2 INL", "ACODEC LOLN",
> +                               "AU2 INR", "ACODEC LORN",
> +                               "Lineout", "AU2 OUTL",
> +                               "Lineout", "AU2 OUTR";
If there's no analog audio in/out then this section can be cleaned up
as well - together with the references to acodec in the dai-links
below.

[...]
> +/* Wireless SDIO Module (Amlogic W155S1 / Realtek RTL8821CS) */
> +&sd_emmc_b {
question to Neil: since we know that there's two board variants out
there (with different wifi chipsets) - are dt overlays down the road
enough (to enable Bluetooth / wifi - depending on the chipset or board
revision) or do we need to split the whole .dts?


Best regards,
Martin


From andrew at lunn.ch  Wed Mar 19 15:39:44 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 19 Mar 2025 23:39:44 +0100
Subject: [PATCH net-next v3 3/5] net: stmmac: dwmac-rk: Move
 integrated_phy_powerup/down functions
In-Reply-To: <20250319214415.3086027-4-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-4-jonas@kwiboo.se>
Message-ID: <d7b3ec5c-2d74-4409-9894-8f2cb3e055f6@lunn.ch>

On Wed, Mar 19, 2025 at 09:44:07PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
> the integrated PHY on RK3228/RK3328. Current powerup/down operation is
> not compatible with the integrated PHY found in these SoCs.
> 
> Move the rk_gmac_integrated_phy_powerup/down functions to top of the
> file to prepare for them to be called directly by a GMAC variant
> specific powerup/down operation.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

> +#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
> +#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
> +
> +static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
> +{
> +	if (priv->ops->integrated_phy_powerup)
> +		priv->ops->integrated_phy_powerup(priv);
> +
> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
> +
> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);

I know you are just moving code around....

Do you know what these MACPHY_ID are? I hope it is not what you get
when you read PHY registers 2 and 3?

	Andrew


From martin.blumenstingl at googlemail.com  Wed Mar 19 15:46:11 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 19 Mar 2025 23:46:11 +0100
Subject: [GIT PULL] amlogic ARM64 DT updates for v6.15
In-Reply-To: <47683e40-aa0e-4d86-9226-94f7d56f34ae@app.fastmail.com>
References: <41ced8db-caeb-4deb-9193-9802fc603180@linaro.org> <47683e40-aa0e-4d86-9226-94f7d56f34ae@app.fastmail.com>
Message-ID: <CAFBinCCY4-sETrXoi5ELjXhnUYB+6q+A3M2FqaGCFprBxe31kA@mail.gmail.com>

Hi Arnd,

On Wed, Mar 19, 2025 at 9:58?PM Arnd Bergmann <arnd at arndb.de> wrote:
>
> On Mon, Mar 17, 2025, at 17:13, Neil Armstrong wrote:
> > Hi,
> >
> > Here's a changeset for Amlogic ARM64 DT, also switching to the new PWM bindings,
> > adding pinctrl support for Amlogic A4 SoC with a brand new binding style then
> > finally gpio_intc node for Amlogic A4 & A5 SoCs.
>
> I'll skip this one for 6.15, seeing that the branch contains both
> driver and devicetree changes, which messes up the way I send
> the contents.
There's an immutable branch in the linux-pinctrl tree from Linus.
I'm not sure on the exact process here (whether the contents of the
tag are fine and we're "just" missing a description, ...) so I'll let
Neil comment on this.

> From the description I also can't tell to what degree there is
> backwards compatibility in the new binding, I assume the changed
> PWM and pinctrl drivers continue to work find with the old dts
> but not the other way round, which is why you sent them together?
The PWM part is backwards compatible. The bindings are upstream since
commit 5fd61cc28171 ("dt-bindings: pwm: amlogic: Add a new binding for
meson8 pwm types").
The mentioned pinctrl binding / driver is completely new for the A4
SoCs, so there's nothing to be backwards compatible with.

Neil, for me it's fine to skip this one for 6.15 if it causes too much
work on your side.
Using the old PWM bindings for another release won't hurt anyone.
And I think the same goes for A4 pinctrl support as well as GPIO
interrupt controller nodes for A4/S5.


Best regards,
Martin


[0] https://lore.kernel.org/linux-gpio/CACRpkdZg-9Zr3f7zG36x7jGvT46FRfRJ40khNZDdYb01-BGigw at mail.gmail.com/


From peterx at redhat.com  Wed Mar 19 15:46:35 2025
From: peterx at redhat.com (Peter Xu)
Date: Wed, 19 Mar 2025 18:46:35 -0400
Subject: [PATCH v2 18/19] mm/arm64: Support large pfn mappings
In-Reply-To: <Z9tDjOk-JdV_fCY4@kbusch-mbp.dhcp.thefacebook.com>
References: <20240826204353.2228736-1-peterx@redhat.com>
 <20240826204353.2228736-19-peterx@redhat.com>
 <Z9tDjOk-JdV_fCY4@kbusch-mbp.dhcp.thefacebook.com>
Message-ID: <Z9tJMsJ4PzZk2ZQS@x1.local>

On Wed, Mar 19, 2025 at 04:22:04PM -0600, Keith Busch wrote:
> On Mon, Aug 26, 2024 at 04:43:52PM -0400, Peter Xu wrote:
> > +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
> > +#define pud_special(pte)	pte_special(pud_pte(pud))
> > +#define pud_mkspecial(pte)	pte_pud(pte_mkspecial(pud_pte(pud)))
> > +#endif
> 
> Sorry for such a late reply, but this looked a bit weird as I'm doing
> some backporting. Not that I'm actually interested in this arch, so I
> can't readily test this, but I believe the intention was to name the
> macro argument "pud", not "pte".

Probably no way to test it from anyone yet, as I don't see aarch64 selects
HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD, which means IIUC this two lines (before
PUD being enabled on aarch64) won't be compiled.. which also matches with
the test results in the cover letter, that we only tried pmd on arm.

The patch will still be needed though for pmd to work.

I can draft a patch to change this, but considering arm's PUD support isn't
there anyway.. maybe I should instead draft a change to remove these as
they're dead code so far, and see if anyone would like to collect it.

Thanks for reporting this.  I'll prepare something soon and keep you
posted.

-- 
Peter Xu



From kbusch at kernel.org  Wed Mar 19 15:53:18 2025
From: kbusch at kernel.org (Keith Busch)
Date: Wed, 19 Mar 2025 16:53:18 -0600
Subject: [PATCH v2 18/19] mm/arm64: Support large pfn mappings
In-Reply-To: <Z9tJMsJ4PzZk2ZQS@x1.local>
References: <20240826204353.2228736-1-peterx@redhat.com>
 <20240826204353.2228736-19-peterx@redhat.com>
 <Z9tDjOk-JdV_fCY4@kbusch-mbp.dhcp.thefacebook.com>
 <Z9tJMsJ4PzZk2ZQS@x1.local>
Message-ID: <Z9tK3gEchs9X0k7h@kbusch-mbp.dhcp.thefacebook.com>

On Wed, Mar 19, 2025 at 06:46:35PM -0400, Peter Xu wrote:
> On Wed, Mar 19, 2025 at 04:22:04PM -0600, Keith Busch wrote:
> > On Mon, Aug 26, 2024 at 04:43:52PM -0400, Peter Xu wrote:
> > > +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
> > > +#define pud_special(pte)	pte_special(pud_pte(pud))
> > > +#define pud_mkspecial(pte)	pte_pud(pte_mkspecial(pud_pte(pud)))
> > > +#endif
> > 
> > Sorry for such a late reply, but this looked a bit weird as I'm doing
> > some backporting. Not that I'm actually interested in this arch, so I
> > can't readily test this, but I believe the intention was to name the
> > macro argument "pud", not "pte".
> 
> Probably no way to test it from anyone yet, as I don't see aarch64 selects
> HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD, which means IIUC this two lines (before
> PUD being enabled on aarch64) won't be compiled.. which also matches with
> the test results in the cover letter, that we only tried pmd on arm.
> 
> The patch will still be needed though for pmd to work.
> 
> I can draft a patch to change this, but considering arm's PUD support isn't
> there anyway.. maybe I should instead draft a change to remove these as
> they're dead code so far, and see if anyone would like to collect it.
> 
> Thanks for reporting this.  I'll prepare something soon and keep you
> posted.

Thanks, good to know it wasn't reachable.

The reason I was conerned is because the only caller, insert_pfn_pud(),
just so happens to have a variable named "pud" in scope, but it's not
the pud passed into the macro. So if this macro was used, it would just
so happen to compile by that coincidence, but its using the wrong pud.


From jonas at kwiboo.se  Wed Mar 19 16:00:26 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 20 Mar 2025 00:00:26 +0100
Subject: [PATCH net-next v3 3/5] net: stmmac: dwmac-rk: Move
 integrated_phy_powerup/down functions
In-Reply-To: <d7b3ec5c-2d74-4409-9894-8f2cb3e055f6@lunn.ch>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-4-jonas@kwiboo.se>
 <d7b3ec5c-2d74-4409-9894-8f2cb3e055f6@lunn.ch>
Message-ID: <e766eb6d-618a-43a0-b1e1-954c2c3fbf0e@kwiboo.se>

Hi Andrew,

On 2025-03-19 23:39, Andrew Lunn wrote:
> On Wed, Mar 19, 2025 at 09:44:07PM +0000, Jonas Karlman wrote:
>> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
>> the integrated PHY on RK3228/RK3328. Current powerup/down operation is
>> not compatible with the integrated PHY found in these SoCs.
>>
>> Move the rk_gmac_integrated_phy_powerup/down functions to top of the
>> file to prepare for them to be called directly by a GMAC variant
>> specific powerup/down operation.
>>
>> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> 
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> 
>> +#define RK_GRF_CON2_MACPHY_ID		HIWORD_UPDATE(0x1234, 0xffff, 0)
>> +#define RK_GRF_CON3_MACPHY_ID		HIWORD_UPDATE(0x35, 0x3f, 0)
>> +
>> +static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
>> +{
>> +	if (priv->ops->integrated_phy_powerup)
>> +		priv->ops->integrated_phy_powerup(priv);
>> +
>> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
>> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
>> +
>> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
>> +	regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
> 
> I know you are just moving code around....
> 
> Do you know what these MACPHY_ID are? I hope it is not what you get
> when you read PHY registers 2 and 3?

I think it may be:

  GRF_MACPHY_CON2
  15:0   macphy_id / PHY ID Number, macphy_cfg_phy_id[15:0]

  GRF_MACPHY_CON3
  15:12  macphy_cfg_rev_nr / Manufacturer's Revision Number
  11:6   macphy_model_nr / Manufacturer's Model Number
  5:0    macphy_id / PHY ID Number, macphy_cfg_phy_id[21:16]

and

  MACPHY_PHY_IDENTIFIER1 - Address: 02
  15:0   PHY ID number / default:cfg_phy_id[15:0]

  MACPHY_PHY_IDENTIFIER2 - Address: 03
  15:10  PHY ID number / default:cfg_phy_id[21:16]
  9:4    Model number / default:cfg_model_nr[5:0]
  3:0    Revision number / default:cfg_rev_nr[3:0]

So likely what you get when you read PHY registers 2 and 3.

Regards,
Jonas

> 
> 	Andrew



From robh at kernel.org  Wed Mar 19 16:04:30 2025
From: robh at kernel.org (Rob Herring)
Date: Wed, 19 Mar 2025 18:04:30 -0500
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use of_reserved_mem_region_*
 functions for "memory-region"
In-Reply-To: <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>
References: <20250317232426.952188-1-robh@kernel.org> <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>
Message-ID: <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>

On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
<arnaud.pouliquen at foss.st.com> wrote:
>
> Hello Rob,
>
> On 3/18/25 00:24, Rob Herring (Arm) wrote:
> > Use the newly added of_reserved_mem_region_to_resource() and
> > of_reserved_mem_region_count() functions to handle "memory-region"
> > properties.
> >
> > The error handling is a bit different in some cases. Often
> > "memory-region" is optional, so failed lookup is not an error. But then
> > an error in of_reserved_mem_lookup() is treated as an error. However,
> > that distinction is not really important. Either the region is available
> > and usable or it is not. So now, it is just
> > of_reserved_mem_region_to_resource() which is checked for an error.
> >
> > Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> > ---
> > For v6.16
> >

[...]

> > diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> > index b02b36a3f515..9d2bd8904c49 100644
> > --- a/drivers/remoteproc/stm32_rproc.c
> > +++ b/drivers/remoteproc/stm32_rproc.c
> > @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
> >  {
> >       struct device *dev = rproc->dev.parent;
> >       struct device_node *np = dev->of_node;
> > -     struct of_phandle_iterator it;
> >       struct rproc_mem_entry *mem;
> > -     struct reserved_mem *rmem;
> >       u64 da;
> > -     int index = 0;
> > +     int index = 0, mr = 0;
> >
> >       /* Register associated reserved memory regions */
> > -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> > -     while (of_phandle_iterator_next(&it) == 0) {
> > -             rmem = of_reserved_mem_lookup(it.node);
> > -             if (!rmem) {
> > -                     of_node_put(it.node);
> > -                     dev_err(dev, "unable to acquire memory-region\n");
> > -                     return -EINVAL;
> > -             }
> > +     while (1) {
> > +             struct resource res;
> > +             int ret;
> > +
> > +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
> > +             if (ret)
> > +                     return 0;
> >
> > -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
> > -                     of_node_put(it.node);
> > -                     dev_err(dev, "memory region not valid %pa\n",
> > -                             &rmem->base);
> > +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
> > +                     dev_err(dev, "memory region not valid %pR\n", &res);
> >                       return -EINVAL;
> >               }
> >
> >               /*  No need to map vdev buffer */
> > -             if (strcmp(it.node->name, "vdev0buffer")) {
> > +             if (strcmp(res.name, "vdev0buffer")) {
>
> I tested your patches

Thank you.

> The update introduces a regression here. The strcmp function never returns 0.
> Indeed, it.node->name stores the memory region label "vdev0buffer," while
> res.name stores the memory region name "vdev0buffer at 10042000."
>
> Several remoteproc drivers may face the same issue as they embed similar code.

Indeed. I confused myself because node 'name' is without the
unit-address, but this is using the full name. I've replaced the
strcmp's with strstarts() to address this. I've updated my branch with
the changes.

Rob


From robh at kernel.org  Wed Mar 19 16:10:42 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 19 Mar 2025 18:10:42 -0500
Subject: [PATCH v5 0/2] Add support for Xiaomi Mi TV Stick
In-Reply-To: <20250319190150.31529-2-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
Message-ID: <174242564139.2499881.5985170981835885510.robh@kernel.org>


On Wed, 19 Mar 2025 19:01:48 +0000, Ferass El Hafidi wrote:
> This patch series aims to add initial support for the Xiaomi Mi TV
> Stick.
> 
> Xiaomi Mi TV Stick is a small Amlogic-based Android TV stick released in
> 2020, and known as `xiaomi-aquaman` internally (in the downstream kernel,
> u-boot, ...)
> Its specifications are as follows:
>  * Amlogic S805Y SoC (believed to be mostly identical to S805X)
>  * 8 GB eMMC
>  * 1 GB of RAM
>  * Wi-Fi + Bluetooth
>  * Android TV 9, upgradable to Android TV 10
>  * Google-certified
> 
> There are multiple variants:
>  * 1. Green PCB, manufactured in 2020, known UART pinout (helpfully
>    labeled on the board)
>  * 2. Blue PCB, not much documentation about it, presumably manufactured
>    between 2021 and 2023
>  * 3. Green PCB, manufactured in 2023/2024, known UART pinout, some layout
>    changes compared to the 2020 variant
> 
> Among these variants, there are many boards using multiple different
> Wi-Fi chips.  Supporting all of them is out of scope for this patch
> series.  However, there has been some work identifying Wi-Fi/Bluetooth
> since v4.  Some variants use a Realtek module while others use an
> Amlogic module.
> 
> As of the time of writing this has only been tested on the 3rd variant.
> It is believed that software-wise all three work mostly the same (if we
> don't count Wi-Fi/BT), but testing on the other variants would still be
> appreciated.  Sadly, booting Mainline linux is slightly more
> challenging on some versions of the original firmware.
> 
> The devicetree is based on the Amlogic P241 DTS.
> 
> Changes since v4 [1]:
>  * add Acked-by from krzk
>  * Wi-Fi on sd_emmc_b
> 
> Changes since v3 [2]:
>  * typo fix (`vbus-supply` in `&usb`)
> 
> Changes since v2 [3]:
>  * fix SoB/From mismatch
> 
> Changes since v1 [4]:
>  * remove useless nodes: cvbs-connector, ethmac, internal_phy, ir
>  * add `amlogic,s805y` DT binding section
>  * add S805Y dtsi: meson-gxl-s805y.dtsi
>  * adjust DT `model` to "Xiaomi Mi TV Stick (Aquaman)"
>  * explain the changes being done a bit more in the commit message for
>    the DT patch
>  * drop `clocks` and `clock-names` from pwm_ef (background: [5])
>  * change sound `model` to "XIAOMI-AQUAMAN"
> 
> More information is available on the postmarketOS wiki page [6].
> 
> [1]: https://lore.kernel.org/all/20250203174346.13737-1-funderscore at postmarketos.org/
> [2]: https://lore.kernel.org/all/20250203091453.15751-1-funderscore at postmarketos.org/
> [3]: https://lore.kernel.org/all/20250201193044.28856-1-funderscore at postmarketos.org/
> [4]: https://lore.kernel.org/all/20250131200319.19996-1-funderscore at postmarketos.org/
> [5]: https://lore.kernel.org/linux-amlogic/20241227212514.1376682-1-martin.blumenstingl at googlemail.com/
> 
> 
> Ferass El Hafidi (2):
>   dt-bindings: arm: amlogic: add S805Y and Mi TV Stick
>   arm64: dts: amlogic: add support for xiaomi-aquaman/Mi TV Stick
> 
>  .../devicetree/bindings/arm/amlogic.yaml      |   7 +
>  arch/arm64/boot/dts/amlogic/Makefile          |   1 +
>  .../meson-gxl-s805y-xiaomi-aquaman.dts        | 292 ++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxl-s805y.dtsi     |  10 +
>  4 files changed, 310 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
> 
> --
> 2.47.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/amlogic/' for 20250319190150.31529-2-funderscore at postmarketos.org:

Error: arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts:243.1-2 syntax error
FATAL ERROR: Unable to parse input tree
make[3]: *** [scripts/Makefile.dtbs:131: arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dtb] Error 1
make[2]: *** [scripts/Makefile.build:461: arch/arm64/boot/dts/amlogic] Error 2
make[2]: Target 'arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dtb' not remade because of errors.
make[1]: *** [/home/rob/proj/linux-dt-testing/Makefile:1475: amlogic/meson-gxl-s805y-xiaomi-aquaman.dtb] Error 2
make: *** [Makefile:248: __sub-make] Error 2
make: Target 'amlogic/meson-gxl-s905x-hwacom-amazetv.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-sml5442tw.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-phicomm-n1.dtb' not remade because of errors.
make: Target 'amlogic/meson-s4-s805x2-aq222.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905w-p281.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-s912-libretech-pc.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12a-sei510.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-q200.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-khadas-vim.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxlx-s905l-p271.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-mecool-kiii-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-vega-s96.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12a-fbx8am.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-bananapi-cm4-cm4io.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-c3-c308l-aw419.dtb' not remade because of errors.
make: Target 'amlogic/meson-axg-s400.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-nexbox-a1.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-dreambox-one.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-khadas-vim2.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-wetek-core2.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12a-radxa-zero.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-vega-s95-telos.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-libretech-cc-v2.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-a311d-khadas-vim3.dtb' not remade because of errors.
make: Target 'amlogic/meson-axg-jethome-jethub-j100.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-gsking-x.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-vega-s95-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-q201.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-p230.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-a311d-bananapi-m2s.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-wetek-play2.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-mecool-kii-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-axg-jethome-jethub-j110-rev-2.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-odroidc2.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-gt1-ultimate.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12a-x96-max.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-libretech-pc.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-p231.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-x96-air.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-vero4k.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-vega-s95-meta.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905w-tx3-mini.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-minix-neo-u9h.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s805x-libretech-ac.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-a95xf3-air-gbit.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-khadas-vim3l.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905d-vero4k-plus.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-h96-max.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-p212.dtb' not remade because of errors.
make: Target 'amlogic/meson-a1-ad401.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-odroid-go-ultra.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-radxa-zero2.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-x96-air-gbit.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-dreambox-two.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-bananapi-m5.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12a-u200.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxm-rbox-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-p201.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-a95xf3-air.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-a4-a113l2-ba400.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s805y-xiaomi-aquaman.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-bananapi-m2-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-p200.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-odroid-c4.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-s922x-bananapi-m2s.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-sei610.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-odroid-hc4.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-odroid-n2l.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-libretech-cc.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-c3-c302x-aw409.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905x-nexbox-a95x.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-a311d-libretech-cc.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-t7-a311d2-khadas-vim4.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s905w-jethome-jethub-j80.dtb' not remade because of errors.
make: Target 'amlogic/meson-sm1-s905d3-libretech-cc.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-a5-a113x2-av400.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-wetek-hub.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-s922x-khadas-vim3.dtb' not remade because of errors.
make: Target 'amlogic/amlogic-t7-a311d2-an400.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-kii-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-odroid-n2.dtb' not remade because of errors.
make: Target 'amlogic/meson-a1-ad402.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-nexbox-a95x.dtb' not remade because of errors.
make: Target 'amlogic/meson-axg-jethome-jethub-j110-rev-3.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-odroid-n2-plus.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-gtking-pro.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-ugoos-am6.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxl-s805x-p241.dtb' not remade because of errors.
make: Target 'amlogic/meson-g12b-gtking.dtb' not remade because of errors.
make: Target 'amlogic/meson-gxbb-nanopi-k2.dtb' not remade because of errors.







From robh at kernel.org  Wed Mar 19 16:10:44 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 19 Mar 2025 18:10:44 -0500
Subject: [PATCH v4 0/6] Add support for S4 audio
In-Reply-To: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
Message-ID: <174242564271.2499930.16784872359354582008.robh@kernel.org>


On Wed, 19 Mar 2025 15:04:43 +0800, jiebing chen wrote:
> Add s4 audio base driver.
> 
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
> Changes in v4:
> - fix dtb check warning
> - add maxItems of power domain for dt-bindings
> - fixed audio clock pads regmap base and reg offset
> - use dapm widget to control tocodec bclk and mclk enable
> - Link to v3: https://lore.kernel.org/r/20250228-audio_drvier-v3-0-dbfd30507e4c at amlogic.com
> 
> Changes in v3:
> - remove g12a tocodec switch event
> - Modify the incorrect title for dt-bindings
> - Link to v2: https://lore.kernel.org/r/20250214-audio_drvier-v2-0-37881fa37c9e at amlogic.com
> 
> Changes in v2:
> - remove tdm pad control and change tocodec base on g12a
> - change hifipll rate to support 24bit
> - add s4 audio clock
> - Link to v1: https://lore.kernel.org/r/20250113-audio_drvier-v1-0-8c14770f38a0 at amlogic.com
> 
> ---
> jiebing chen (6):
>       dt-bindings: clock: meson: Add audio power domain for s4 soc
>       dt-bindings: clock: axg-audio: Add mclk and sclk pad clock ids
>       dt-bindings: Asoc: axg-audio: Add s4 audio tocodec
>       ASoC: meson: g12a-toacodec: Add s4 tocodec driver
>       clk: meson: axg-audio: Add the mclk pad div for s4 chip
>       arm64: dts: amlogic: Add Amlogic S4 Audio
> 
>  .../bindings/clock/amlogic,axg-audio-clkc.yaml     |  20 +-
>  .../bindings/sound/amlogic,g12a-toacodec.yaml      |   1 +
>  .../boot/dts/amlogic/meson-s4-s805x2-aq222.dts     | 219 ++++++++++
>  arch/arm64/boot/dts/amlogic/meson-s4.dtsi          | 372 ++++++++++++++++-
>  drivers/clk/meson/axg-audio.c                      | 441 ++++++++++++++++++++-
>  drivers/clk/meson/axg-audio.h                      |   6 +
>  include/dt-bindings/clock/axg-audio-clkc.h         |  11 +
>  sound/soc/meson/g12a-toacodec.c                    |  46 +++
>  8 files changed, 1111 insertions(+), 5 deletions(-)
> ---
> base-commit: 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
> change-id: 20250110-audio_drvier-07a5381c494b
> 
> Best regards,
> --
> jiebing chen <jiebing.chen at amlogic.com>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/amlogic/' for 20250319-audio_drvier-v4-0-686867fad719 at amlogic.com:

arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dtb: sound: 'anyOf' conditional failed, one must be fixed:
	'clocks' is a required property
	'#clock-cells' is a required property
	from schema $id: http://devicetree.org/schemas/clock/clock.yaml#
arch/arm64/boot/dts/amlogic/meson-axg-s400.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-cm4io.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-axg-jethome-jethub-j100.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-gsking-x.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-a311d-bananapi-m2s.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-axg-jethome-jethub-j110-rev-2.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-x96-air.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air-gbit.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-h96-max.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12a-u200.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m2-pro.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-s922x-bananapi-m2s.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2l.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-odroid-hc4.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-a311d-libretech-cc.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-sm1-s905d3-libretech-cc.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-axg-jethome-jethub-j110-rev-3.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2-plus.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
	from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#







From andrew at lunn.ch  Wed Mar 19 16:22:27 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 00:22:27 +0100
Subject: [PATCH net-next v3 3/5] net: stmmac: dwmac-rk: Move
 integrated_phy_powerup/down functions
In-Reply-To: <e766eb6d-618a-43a0-b1e1-954c2c3fbf0e@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-4-jonas@kwiboo.se>
 <d7b3ec5c-2d74-4409-9894-8f2cb3e055f6@lunn.ch>
 <e766eb6d-618a-43a0-b1e1-954c2c3fbf0e@kwiboo.se>
Message-ID: <f6a6e6e6-c00d-4920-a3a3-8699e9a88b6e@lunn.ch>

> > Do you know what these MACPHY_ID are? I hope it is not what you get
> > when you read PHY registers 2 and 3?
> 
> I think it may be:
> 
>   GRF_MACPHY_CON2
>   15:0   macphy_id / PHY ID Number, macphy_cfg_phy_id[15:0]
> 
>   GRF_MACPHY_CON3
>   15:12  macphy_cfg_rev_nr / Manufacturer's Revision Number
>   11:6   macphy_model_nr / Manufacturer's Model Number
>   5:0    macphy_id / PHY ID Number, macphy_cfg_phy_id[21:16]
> 
> and
> 
>   MACPHY_PHY_IDENTIFIER1 - Address: 02
>   15:0   PHY ID number / default:cfg_phy_id[15:0]
> 
>   MACPHY_PHY_IDENTIFIER2 - Address: 03
>   15:10  PHY ID number / default:cfg_phy_id[21:16]
>   9:4    Model number / default:cfg_model_nr[5:0]
>   3:0    Revision number / default:cfg_rev_nr[3:0]
> 
> So likely what you get when you read PHY registers 2 and 3.

Ah:

drivers/net/phy/rockchip.c

#define INTERNAL_EPHY_ID                        0x1234d400

However, it is not clear where the d4 come from.

The problem here is the upper part should be an OUI from the vendor.
I doubt rockchip actually own this OUI. They do actually have the MAC
OUI: 10:DC:B6:90:00:00/28. I don't know if you can use a MAC OUI with
a PHY ID?

	Andrew


From andrew at lunn.ch  Wed Mar 19 16:27:18 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 00:27:18 +0100
Subject: [PATCH net-next v3 5/5] net: stmmac: dwmac-rk: Add initial
 support for RK3528 integrated PHY
In-Reply-To: <20250319214415.3086027-6-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-6-jonas@kwiboo.se>
Message-ID: <d53a2119-2650-4a87-af94-1b9c2297cf72@lunn.ch>

On Wed, Mar 19, 2025 at 09:44:09PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
> the integrated PHY on RK3228/RK3328.

What ID does this PHY have? Is it just the reset which is different,
or is it actually a different PHY, and the rockchip PHY driver needs
additions?

	Andrew


From jgg at ziepe.ca  Wed Mar 19 16:28:48 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 19 Mar 2025 20:28:48 -0300
Subject: [RFC PATCH v3 2/5] iommufd/device: Associate a kvm pointer to
 iommufd_device
In-Reply-To: <20250319173202.78988-3-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
 <20250319173202.78988-3-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319232848.GD126678@ziepe.ca>

On Wed, Mar 19, 2025 at 05:31:59PM +0000, Shameer Kolothum wrote:
> Add a struct kvm * to iommufd_device_bind() fn and associate it
> with idev if bind is successful.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
> ---
>  drivers/iommu/iommufd/device.c          | 5 ++++-
>  drivers/iommu/iommufd/iommufd_private.h | 2 ++
>  drivers/vfio/iommufd.c                  | 2 +-
>  include/linux/iommufd.h                 | 4 +++-
>  4 files changed, 10 insertions(+), 3 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>

I'd probably explain more in the commit message that this is to allow
VFIO to pass the KVM to iommufd so it can later be associated with
downstream objects like the viommu.

Jason


From gshan at redhat.com  Wed Mar 19 16:30:30 2025
From: gshan at redhat.com (Gavin Shan)
Date: Thu, 20 Mar 2025 09:30:30 +1000
Subject: [PATCH] firmware: psci: Fix refcount leak in psci_dt_init
In-Reply-To: <20250318151712.28763-1-linmq006@gmail.com>
References: <20250318151712.28763-1-linmq006@gmail.com>
Message-ID: <c69921bb-79a0-4644-a19d-9693d1dd638e@redhat.com>

On 3/19/25 1:17 AM, Miaoqian Lin wrote:
> Fix a reference counter leak in psci_dt_init() where of_node_put(np) was
> missing after of_find_matching_node_and_match() when np is unavailable.
> 
> Fixes: bff60792f994 ("arm64: psci: factor invocation code to drivers")
> Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
> ---
>   drivers/firmware/psci/psci.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 

With the fix tag corrected to the one, suggested by Mark.

Reviewed-by: Gavin Shan <gshan at redhat.com>

> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index a1ebbe9b73b1..38ca190d4a22 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
> @@ -804,8 +804,10 @@ int __init psci_dt_init(void)
>   
>   	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
>   
> -	if (!np || !of_device_is_available(np))
> +	if (!np || !of_device_is_available(np)) {
> +		of_node_put(np);
>   		return -ENODEV;
> +	}
>   
>   	init_fn = (psci_initcall_t)matched_np->data;
>   	ret = init_fn(np);



From jonas at kwiboo.se  Wed Mar 19 16:26:14 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 20 Mar 2025 00:26:14 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <20250318120003.2340652-2-amadeus@jmu.edu.cn>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
 <20250318120003.2340652-2-amadeus@jmu.edu.cn>
Message-ID: <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se>

Hi Chukun,

On 2025-03-18 13:00, Chukun Pan wrote:
> Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
> RK3328, but the driver does not support interrupts yet.

The device tree should describe the hardware, not what the driver
support, so interrupts should probably be included.

However, looking closer at TRM for i.e. RK3328, RK3568 and RK3588 it
look like the following description is not a true description of the
hardware.

Each PWM controller seem to support 4 channels, here (and for older RK
SoCs) we instead describe each channel and not the controller.

Maybe something like following would better represent the hardware:

	pwm0: pwm at ffa90000 {
		compatible = "rockchip,rk3528-pwm";
		reg = <0x0 0xffa90000 0x0 0x10000>;
		clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
		clock-names = "pwm", "pclk";
		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
	};

	pwm1: pwm at ffa98000 {
		compatible = "rockchip,rk3528-pwm";
		reg = <0x0 0xffa98000 0x0 0x10000>;
		clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
		clock-names = "pwm", "pclk";
		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
	};

Regards,
Jonas

> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++
>  1 file changed, 80 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 1af0d036cf32..621fc19ac0b3 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -465,6 +465,86 @@ uart7: serial at ffa28000 {
>  			status = "disabled";
>  		};
>  
> +		pwm0: pwm at ffa90000 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa90000 0x0 0x10>;
> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm1: pwm at ffa90010 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa90010 0x0 0x10>;
> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm2: pwm at ffa90020 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa90020 0x0 0x10>;
> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm3: pwm at ffa90030 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa90030 0x0 0x10>;
> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm4: pwm at ffa98000 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa98000 0x0 0x10>;
> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm5: pwm at ffa98010 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa98010 0x0 0x10>;
> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm6: pwm at ffa98020 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa98020 0x0 0x10>;
> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
> +		pwm7: pwm at ffa98030 {
> +			compatible = "rockchip,rk3528-pwm",
> +				     "rockchip,rk3328-pwm";
> +			reg = <0x0 0xffa98030 0x0 0x10>;
> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> +			clock-names = "pwm", "pclk";
> +			#pwm-cells = <3>;
> +			status = "disabled";
> +		};
> +
>  		saradc: adc at ffae0000 {
>  			compatible = "rockchip,rk3528-saradc";
>  			reg = <0x0 0xffae0000 0x0 0x10000>;



From jgg at ziepe.ca  Wed Mar 19 16:31:11 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 19 Mar 2025 20:31:11 -0300
Subject: [RFC PATCH v3 3/5] iommu/arm-smmu-v3-iommufd: Pass in kvm
 pointer to viommu_alloc
In-Reply-To: <20250319173202.78988-4-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
 <20250319173202.78988-4-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319233111.GE126678@ziepe.ca>

On Wed, Mar 19, 2025 at 05:32:00PM +0000, Shameer Kolothum wrote:
> diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
> index 69b88e8c7c26..e157d786f295 100644
> --- a/drivers/iommu/iommufd/viommu.c
> +++ b/drivers/iommu/iommufd/viommu.c
> @@ -47,7 +47,8 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
>  		goto out_put_hwpt;
>  	}
>  
> -	viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain,
> +	viommu = ops->viommu_alloc(idev->dev, idev->kvm,
> +				   hwpt_paging->common.domain,
>  				   ucmd->ictx, cmd->type);
>  	if (IS_ERR(viommu)) {
>  		rc = PTR_ERR(viommu);

This has a lifetime issue on the kvm pointer.

Because nothing is taking a refcount on the kvm we are relying on the
caller to hold the kvm refcount for the lifetime of the
iommufd_device_bind()/unbind() which is creating the idev.

However, the lifetime of the viommu object is not linked to the
lifetime of the idev. So the idev could be destroyed, and the kvm
refcount put before the viommu is destroyed.

Probably the right answer is to take a refcount on the kvm for the
viommu object somewhere along this path.

Jason


From jgg at ziepe.ca  Wed Mar 19 16:39:46 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 19 Mar 2025 20:39:46 -0300
Subject: [RFC PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Use KVM VMID for
 s2 stage
In-Reply-To: <20250319173202.78988-5-shameerali.kolothum.thodi@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
 <20250319173202.78988-5-shameerali.kolothum.thodi@huawei.com>
Message-ID: <20250319233946.GF126678@ziepe.ca>

On Wed, Mar 19, 2025 at 05:32:01PM +0000, Shameer Kolothum wrote:
> +static int arm_vsmmu_alloc_vmid(struct arm_smmu_device *smmu, struct kvm *kvm,
> +				bool *kvm_used)
> +{
> +#ifdef CONFIG_KVM
> +	/*
> +	 * There can only be one allocator for VMIDs active at once. If BTM is
> +	 * turned on then KVM's allocator always supplies the VMID, and the
> +	 * VMID is matched by CPU invalidation of the KVM S2. Right now there
> +	 * is no API to get an unused VMID from KVM so this also means BTM systems
> +	 * cannot support S2 without an associated KVM.
> +	 */
> +	if ((smmu->features & ARM_SMMU_FEAT_BTM)) {
> +		int vmid;
> +
> +		if (!kvm || !kvm_get_kvm_safe(kvm))
> +			return -EOPNOTSUPP;

Isn't kvm_get_kvm_safe() in modular KVM code most of the time? You can't
call it like this right?

Per my prior comments, I'm a little nervous to make drivers keep track
of this refcount instead of the core code but this does seem like it
could work..

I also think you should block using the S2 without a viommu & KVM in
BTM mode.. Maybe like this:

@@ -2938,8 +2938,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                cdptr = arm_smmu_alloc_cd_ptr(master, IOMMU_NO_PASID);
                if (!cdptr)
                        return -ENOMEM;
-       } else if (arm_smmu_ssids_in_use(&master->cd_table))
-               return -EBUSY;
+       } else {
+               if (arm_smmu_ssids_in_use(&master->cd_table))
+                       return -EBUSY;
+               /*
+                * S2 cannot be used when BTM is turned on without a VIOMMU and
+                * VMID shared with KVM
+                */
+               if (smmu->features & ARM_SMMU_FEAT_BTM)
+                       return -EOPNOTSUPP;
+       }

That more closely matches how this will eventually work when the VMID
allocation is properly made to be local to the viommu.

Jason


From heiko at sntech.de  Wed Mar 19 16:47:52 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 20 Mar 2025 00:47:52 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
 <20250318120003.2340652-2-amadeus@jmu.edu.cn>
 <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se>
Message-ID: <2499436.jE0xQCEvom@phil>

Am Donnerstag, 20. M?rz 2025, 00:26:14 MEZ schrieb Jonas Karlman:
> Hi Chukun,
> 
> On 2025-03-18 13:00, Chukun Pan wrote:
> > Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
> > RK3328, but the driver does not support interrupts yet.
> 
> The device tree should describe the hardware, not what the driver
> support, so interrupts should probably be included.
> 
> However, looking closer at TRM for i.e. RK3328, RK3568 and RK3588 it
> look like the following description is not a true description of the
> hardware.
> 
> Each PWM controller seem to support 4 channels, here (and for older RK
> SoCs) we instead describe each channel and not the controller.

Yep, that is something that did go wrong in the very early days.
And all other Rockchip socs also have the same issue - even back
to the rk3066.

So yes, at some point we should overhaul the thing.

But I think this is more involved, as right now everything is aimed
at the current single-channel status quo.


Heiko


> Maybe something like following would better represent the hardware:
> 
> 	pwm0: pwm at ffa90000 {
> 		compatible = "rockchip,rk3528-pwm";
> 		reg = <0x0 0xffa90000 0x0 0x10000>;
> 		clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> 		clock-names = "pwm", "pclk";
> 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
> 			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
> 	};
> 
> 	pwm1: pwm at ffa98000 {
> 		compatible = "rockchip,rk3528-pwm";
> 		reg = <0x0 0xffa98000 0x0 0x10000>;
> 		clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> 		clock-names = "pwm", "pclk";
> 		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
> 			     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
> 	};
> 
> Regards,
> Jonas
> 
> > 
> > Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++
> >  1 file changed, 80 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > index 1af0d036cf32..621fc19ac0b3 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> > @@ -465,6 +465,86 @@ uart7: serial at ffa28000 {
> >  			status = "disabled";
> >  		};
> >  
> > +		pwm0: pwm at ffa90000 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa90000 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm1: pwm at ffa90010 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa90010 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm2: pwm at ffa90020 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa90020 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm3: pwm at ffa90030 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa90030 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm4: pwm at ffa98000 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa98000 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm5: pwm at ffa98010 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa98010 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm6: pwm at ffa98020 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa98020 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> > +		pwm7: pwm at ffa98030 {
> > +			compatible = "rockchip,rk3528-pwm",
> > +				     "rockchip,rk3328-pwm";
> > +			reg = <0x0 0xffa98030 0x0 0x10>;
> > +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
> > +			clock-names = "pwm", "pclk";
> > +			#pwm-cells = <3>;
> > +			status = "disabled";
> > +		};
> > +
> >  		saradc: adc at ffae0000 {
> >  			compatible = "rockchip,rk3528-saradc";
> >  			reg = <0x0 0xffae0000 0x0 0x10000>;
> 
> 






From jonas at kwiboo.se  Wed Mar 19 16:52:34 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 20 Mar 2025 00:52:34 +0100
Subject: [PATCH net-next v3 5/5] net: stmmac: dwmac-rk: Add initial
 support for RK3528 integrated PHY
In-Reply-To: <d53a2119-2650-4a87-af94-1b9c2297cf72@lunn.ch>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-6-jonas@kwiboo.se>
 <d53a2119-2650-4a87-af94-1b9c2297cf72@lunn.ch>
Message-ID: <eabc0fb8-10cc-465c-9434-b0804418dcb6@kwiboo.se>

Hi Andrew,

On 2025-03-20 00:27, Andrew Lunn wrote:
> On Wed, Mar 19, 2025 at 09:44:09PM +0000, Jonas Karlman wrote:
>> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
>> the integrated PHY on RK3228/RK3328.
> 
> What ID does this PHY have? Is it just the reset which is different,
> or is it actually a different PHY, and the rockchip PHY driver needs
> additions?

Sorry, look like I missed to include the phy-id reported in this patch
and only included that detail in the related device tree patch [1].

This PHY seem to be different compared to the PHY used in older SoCs.

The PHY identified on addr 0x2 as 0044.1400 and in vendor kernel this
relate to the Rockchip RK630 PHY [2].

  #define RK630_PHY_ID				0x00441400

  /*
   * Fixed address:
   * Addr: 1 --- RK630 at S40
   *       2 --- RV1106 at T22
   */
  #define PHY_ADDR_S40				1
  #define PHY_ADDR_T22				2

[1] https://lore.kernel.org/all/20250310001254.1516138-2-jonas at kwiboo.se/
[2] https://github.com/armbian/linux-rockchip/blob/rk-6.1-rkr5/drivers/net/phy/rk630phy.c

Regards,
Jonas

> 
> 	Andrew



From heiko at sntech.de  Wed Mar 19 16:54:02 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 20 Mar 2025 00:54:02 +0100
Subject: [GIT PULL] Rockchip dts64 changes for 6.15 #3
Message-ID: <5552256.Sb9uPGUboI@phil>

Hi soc maintainers,

I made an error and accidentially applied a patch that was meant for
the mfd tree. Thankfully Stephen noticed that when the duplicate
commit appeared in linux-next.


Please pull.
Thanks
Heiko


The following changes since commit 73d246b4402c3356f6b3d13665de3a51eea7b555:

  arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0 (2025-03-15 15:49:00 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v6.15-rockchip-dts64-3

for you to fetch changes up to cee24bc73d4f3f47344a1a54100a69c72f1db061:

  Revert "dt-bindings: mfd: syscon: Add rk3528 QoS register compatible" (2025-03-19 00:22:18 +0100)

----------------------------------------------------------------
Revert of one commit that was applied accidentially and should instead
go through the MFD tree. It is already part of that tree as
commit 7f3e3e7228bb ("dt-bindings: mfd: syscon: Add rk3528 QoS register
compatible").

----------------------------------------------------------------
Heiko Stuebner (1):
      Revert "dt-bindings: mfd: syscon: Add rk3528 QoS register compatible"

 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 --
 1 file changed, 2 deletions(-)





From andi.shyti at kernel.org  Wed Mar 19 17:17:21 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Thu, 20 Mar 2025 01:17:21 +0100
Subject: [PATCH 2/4] i2c: pasemi: Improve error recovery
In-Reply-To: <20250222-pasemi-fixes-v1-2-d7ea33d50c5e@svenpeter.dev>
References: <20250222-pasemi-fixes-v1-0-d7ea33d50c5e@svenpeter.dev>
 <20250222-pasemi-fixes-v1-2-d7ea33d50c5e@svenpeter.dev>
Message-ID: <mp77oombs4xgr6sjj44ne7muybfrwejgehzv5xupeanh6udui3@ymgfesctindh>

Hi Sven,

On Sat, Feb 22, 2025 at 01:38:34PM +0000, Sven Peter via B4 Relay wrote:
> The hardware (supposedly) has a 25ms timeout for clock stretching
> and the driver uses 100ms which should be plenty.

Can we add this lines as a comment to the define you are adding?

> The error
> reocvery itself is however lacking.

...

> -static void pasemi_smb_clear(struct pasemi_smbus *smbus)
> +static int pasemi_smb_clear(struct pasemi_smbus *smbus)
>  {
>  	unsigned int status;
> +	int timeout = TRANSFER_TIMEOUT_MS;
>  
>  	status = reg_read(smbus, REG_SMSTA);
> +
> +	/* First wait for the bus to go idle */
> +	while ((status & (SMSTA_XIP | SMSTA_JAM)) && timeout--) {
> +		msleep(1);

Please, use usleep_range for 1 millisecond timeout.

> +		status = reg_read(smbus, REG_SMSTA);
> +	}

You could use here readx_poll_timeout() here.

> +
> +	if (timeout < 0) {
> +		dev_warn(smbus->dev, "Bus is still stuck (status 0x%08x)\n", status);

if it's an error, please use an error.

> +		return -EIO;
> +	}
> +
> +	/* If any badness happened or there is data in the FIFOs, reset the FIFOs */
> +	if ((status & (SMSTA_MRNE | SMSTA_JMD | SMSTA_MTO | SMSTA_TOM | SMSTA_MTN | SMSTA_MTA)) ||
> +		!(status & SMSTA_MTE))

Please, fixe the alignment here.

> +		pasemi_reset(smbus);
> +
> +	/* Clear the flags */
>  	reg_write(smbus, REG_SMSTA, status);
> +
> +	return 0;
>  }
>  
>  static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
>  {
> -	int timeout = 100;
> +	int timeout = TRANSFER_TIMEOUT_MS;
>  	unsigned int status;
>  
>  	if (smbus->use_irq) {
>  		reinit_completion(&smbus->irq_completion);
> -		reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
> -		wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100));
> +		/* XEN should be set when a transaction terminates, whether due to error or not */
> +		reg_write(smbus, REG_IMASK, SMSTA_XEN);
> +		wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(timeout));

what happens if the timeout expires?

>  		reg_write(smbus, REG_IMASK, 0);
>  		status = reg_read(smbus, REG_SMSTA);
>  	} else {

...

>  	struct pasemi_smbus *smbus = adapter->algo_data;
>  	int ret, i;
>  
> -	pasemi_smb_clear(smbus);
> +	if (pasemi_smb_clear(smbus))
> +		return -EIO;

Can we use

	ret = ...
	if (ret)
		return ret;

This way we return whatever comes from pasemi_smb_clear().

>  
>  	ret = 0;

This way we can remove this line, as well.

Andi


From andi.shyti at kernel.org  Wed Mar 19 17:23:25 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Thu, 20 Mar 2025 01:23:25 +0100
Subject: [PATCH 1/4] i2c: pasemi: Add registers bits and switch to BIT()
In-Reply-To: <20250222-pasemi-fixes-v1-1-d7ea33d50c5e@svenpeter.dev>
References: <20250222-pasemi-fixes-v1-0-d7ea33d50c5e@svenpeter.dev>
 <20250222-pasemi-fixes-v1-1-d7ea33d50c5e@svenpeter.dev>
Message-ID: <rjvak3c2k5a64jw4ef23i5uptg4zzl3u7lqszqbg56l4hqms77@hrkn5eydxwiy>

Hi Sven,

On Sat, Feb 22, 2025 at 01:38:33PM +0000, Sven Peter via B4 Relay wrote:
> From: Sven Peter <sven at svenpeter.dev>
> 
> Add the missing register bits to the defines and also switch
> those to use the BIT macro which is much more readable than
> using hardcoded masks
> 
> Co-developed-by: Hector Martin <marcan at marcan.st>
> Signed-off-by: Hector Martin <marcan at marcan.st>
> Signed-off-by: Sven Peter <sven at svenpeter.dev>

Just this patch merged to i2c/i2c-host.

Patch 3 and 4 look good, just some comments on patch 2.

Thanks,
Andi


From andrew at lunn.ch  Wed Mar 19 17:27:44 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 01:27:44 +0100
Subject: [PATCH net-next v3 5/5] net: stmmac: dwmac-rk: Add initial
 support for RK3528 integrated PHY
In-Reply-To: <eabc0fb8-10cc-465c-9434-b0804418dcb6@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-6-jonas@kwiboo.se>
 <d53a2119-2650-4a87-af94-1b9c2297cf72@lunn.ch>
 <eabc0fb8-10cc-465c-9434-b0804418dcb6@kwiboo.se>
Message-ID: <ab58c128-f598-4586-a912-0d6128934fcc@lunn.ch>

>   #define RK630_PHY_ID				0x00441400

O.K. different which is good.

>   /*
>    * Fixed address:
>    * Addr: 1 --- RK630 at S40
>    *       2 --- RV1106 at T22
>    */
>   #define PHY_ADDR_S40				1
>   #define PHY_ADDR_T22				2
> 
> [1] https://lore.kernel.org/all/20250310001254.1516138-2-jonas at kwiboo.se/
> [2] https://github.com/armbian/linux-rockchip/blob/rk-6.1-rkr5/drivers/net/phy/rk630phy.c

The vendor driver is going to need some cleanup before you post it....

    Andrew


From jeff.johnson at oss.qualcomm.com  Wed Mar 19 17:27:57 2025
From: jeff.johnson at oss.qualcomm.com (Jeff Johnson)
Date: Wed, 19 Mar 2025 17:27:57 -0700
Subject: [GIT PULL] Qualcomm Arm64 DeviceTree updates for v6.15
In-Reply-To: <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>
References: <20250317215921.2031880-1-andersson@kernel.org>
 <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>
Message-ID: <fe56b19d-6ec0-4b0e-a47d-9e4dc8d798a5@oss.qualcomm.com>

On 3/19/2025 2:10 PM, Arnd Bergmann wrote:
> On Mon, Mar 17, 2025, at 22:59, Bjorn Andersson wrote:
>>
>> Krzysztof Kozlowski (17):
>>       arm64: dts: qcom: sa8775p: Partially revert "arm64: dts: qcom: 
>> sa8775p: add QCrypto nodes"
>>       arm64: dts: qcom: qcs8300: Partially revert "arm64: dts: qcom: 
>> qcs8300: add QCrypto nodes"
>>       arm64: dts: qcom: x1e80100-slim7x: Drop incorrect 
>> qcom,ath12k-calibration-variant
>>       arm64: dts: qcom: msm8998: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: qrb2210-rb1: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: qrb4210-rb2: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sc7180: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sdm845: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sda660-ifc6560: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sm6115: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sm8150-hdk: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: qcm6490: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sa8775p-ride: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sc8280xp: Switch to undeprecated 
>> qcom,calibration-variant
>>       arm64: dts: qcom: sm8250-elish: Switch to undeprecated 
>> qcom,calibration-variant
> 
> This seeems to remove the properties that the drivers expect
> even in 6.14-rc7, so the branch is currently broken and I'll
> skip it for 6.15. Let's see how we should handle this properly
> in the next cycle, since it's too late now to fix it.
> 
>       Arnd
> 

The driver changes are in wireless-next.
+Johannes will you issue a wireless-next => net-next PR this week?

Seems like there should be a way to orchestrate these into v6.15.

/jeff




From Moudy.Ho at mediatek.com  Wed Mar 19 18:28:17 2025
From: Moudy.Ho at mediatek.com (=?utf-8?B?TW91ZHkgSG8gKOS9leWul+WOnyk=?=)
Date: Thu, 20 Mar 2025 01:28:17 +0000
Subject: [PATCH 2/4] dt-bindings: remoteproc: mediatek: Remove l1tcm for
 dual-core MT8188 SCP
In-Reply-To: <70c10764-121b-43f5-931e-84ffd666c594@collabora.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
	 <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
	 <70c10764-121b-43f5-931e-84ffd666c594@collabora.com>
Message-ID: <b0872ee008c3c6a2731f949d8c2be77aa49341f7.camel@mediatek.com>

On Wed, 2025-03-19 at 10:34 +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 18/03/25 23:22, N?colas F. R. A. Prado ha scritto:
> > The SCP present on MT8188 does not have an L1TCM memory region, but
> > the
> > binding incorrectly requires one for the dual-core description of
> > the
> > MT8188 SCP. Remove that requirement. Also update the minimum number
> > of
> > reg and reg-names to 1, since as this is a multi-core SCP with no
> > L1TCM memory, only the CFG memory region is present in the parent
> > node.
> > 
> > Fixes: 91e0d560b9fd ("dt-bindings: remoteproc: mediatek: Support
> > MT8188 dual-core SCP")
> > Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
> 
> As far as I know, the L1TCM is present on MT8188, and it's at
> 0x1070000 len 0x8000
> exactly like MT8195.
> 
> Moudy, are you able to please confirm or deny that?
> 
> Cheers,
> Angelo
> 
> 

Hi Angelo,

Unfortunately, during the transition from MT8195 to MT8188, the SCP
removed the L1TCM, retaining only the SRAM and config register.
For detailed hardware changes, you can refer to Tinghan's previous
description at the following link.

ref:
https://lore.kernel.org/all/20220715051821.30707-3-tinghan.shen at mediatek.com/

Sincerely,
Moudy Ho


From changyuanl at google.com  Wed Mar 19 18:55:50 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:50 -0700
Subject: [PATCH v5 15/16] memblock: add KHO support for reserve_mem
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-16-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

Linux has recently gained support for "reserve_mem": A mechanism to
allocate a region of memory early enough in boot that we can cross our
fingers and hope it stays at the same location during most boots, so we
can store for example ftrace buffers into it.

Thanks to KASLR, we can never be really sure that "reserve_mem"
allocations are static across kexec. Let's teach it KHO awareness so
that it serializes its reservations on kexec exit and deserializes them
again on boot, preserving the exact same mapping across kexec.

This is an example user for KHO in the KHO patch set to ensure we have
at least one (not very controversial) user in the tree before extending
KHO's use to more subsystems.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 mm/memblock.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 179 insertions(+)

diff --git a/mm/memblock.c b/mm/memblock.c
index d28abf3def1c..dd698c55b87e 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -17,6 +17,10 @@
 #include <linux/seq_file.h>
 #include <linux/memblock.h>
 
+#ifdef CONFIG_KEXEC_HANDOVER
+#include <linux/kexec_handover.h>
+#endif /* CONFIG_KEXEC_HANDOVER */
+
 #include <asm/sections.h>
 #include <linux/io.h>
 
@@ -2431,6 +2435,176 @@ int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *
 }
 EXPORT_SYMBOL_GPL(reserve_mem_find_by_name);
 
+#ifdef CONFIG_KEXEC_HANDOVER
+#define MEMBLOCK_KHO_NODE "memblock"
+#define MEMBLOCK_KHO_NODE_COMPATIBLE "memblock-v1"
+#define RESERVE_MEM_KHO_NODE_COMPATIBLE "reserve-mem-v1"
+
+static struct kho_node memblock_kho_node = KHO_NODE_INIT;
+
+static void reserve_mem_kho_reset(void)
+{
+	int i;
+	struct kho_node *node;
+
+	kho_remove_node(NULL, MEMBLOCK_KHO_NODE);
+	kho_remove_prop(&memblock_kho_node, "compatible", NULL);
+
+	for (i = 0; i < reserved_mem_count; i++) {
+		struct reserve_mem_table *map = &reserved_mem_table[i];
+
+		node = kho_remove_node(&memblock_kho_node, map->name);
+		if (IS_ERR(node))
+			continue;
+
+		kho_unpreserve_phys(map->start, map->size);
+
+		kho_remove_prop(node, "compatible", NULL);
+		kho_remove_prop(node, "start", NULL);
+		kho_remove_prop(node, "size", NULL);
+
+		kfree(node);
+	}
+}
+
+static int reserve_mem_kho_finalize(void)
+{
+	int i, err = 0;
+	struct kho_node *node;
+
+	if (!reserved_mem_count)
+		return NOTIFY_DONE;
+
+	err = kho_add_node(NULL, MEMBLOCK_KHO_NODE, &memblock_kho_node);
+	if (err == 1)
+		return NOTIFY_DONE;
+
+	err |= kho_add_string_prop(&memblock_kho_node, "compatible",
+				   MEMBLOCK_KHO_NODE_COMPATIBLE);
+
+	for (i = 0; i < reserved_mem_count; i++) {
+		struct reserve_mem_table *map = &reserved_mem_table[i];
+
+		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		if (!node) {
+			err = -ENOMEM;
+			break;
+		}
+
+		err |= kho_preserve_phys(map->start, map->size);
+
+		kho_init_node(node);
+		err |= kho_add_string_prop(node, "compatible",
+					   RESERVE_MEM_KHO_NODE_COMPATIBLE);
+		err |= kho_add_prop(node, "start", &map->start,
+				    sizeof(map->start));
+		err |= kho_add_prop(node, "size", &map->size,
+				    sizeof(map->size));
+		err |= kho_add_node(&memblock_kho_node, map->name, node);
+
+		if (err)
+			break;
+	}
+
+	if (err) {
+		pr_err("failed to save reserve_mem to KHO: %d\n", err);
+		reserve_mem_kho_reset();
+		return NOTIFY_STOP;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int reserve_mem_kho_notifier(struct notifier_block *self,
+				    unsigned long cmd, void *v)
+{
+	switch (cmd) {
+	case KEXEC_KHO_FINALIZE:
+		return reserve_mem_kho_finalize();
+	case KEXEC_KHO_UNFREEZE:
+		return NOTIFY_DONE;
+	default:
+		return NOTIFY_BAD;
+	}
+}
+
+static struct notifier_block reserve_mem_kho_nb = {
+	.notifier_call = reserve_mem_kho_notifier,
+};
+
+static int __init reserve_mem_init(void)
+{
+	if (!kho_is_enabled())
+		return 0;
+
+	return register_kho_notifier(&reserve_mem_kho_nb);
+}
+core_initcall(reserve_mem_init);
+
+static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size,
+					  phys_addr_t align)
+{
+	int err, len_start, len_size;
+	struct kho_in_node node, child;
+	const phys_addr_t *p_start, *p_size;
+
+	err = kho_get_node(NULL, MEMBLOCK_KHO_NODE, &node);
+	if (err)
+		return false;
+
+	err = kho_node_check_compatible(&node, MEMBLOCK_KHO_NODE_COMPATIBLE);
+	if (err) {
+		pr_warn("Node '%s' is incompatible with %s: %d\n",
+			MEMBLOCK_KHO_NODE, MEMBLOCK_KHO_NODE_COMPATIBLE, err);
+		return false;
+	}
+
+	err = kho_get_node(&node, name, &child);
+	if (err) {
+		pr_warn("Node '%s' has no child '%s': %d\n",
+			MEMBLOCK_KHO_NODE, name, err);
+		return false;
+	}
+	err = kho_node_check_compatible(&child, RESERVE_MEM_KHO_NODE_COMPATIBLE);
+	if (err) {
+		pr_warn("Node '%s/%s' is incompatible with %s: %d\n",
+			MEMBLOCK_KHO_NODE, name,
+			RESERVE_MEM_KHO_NODE_COMPATIBLE, err);
+		return false;
+	}
+
+	p_start = kho_get_prop(&child, "start", &len_start);
+	p_size = kho_get_prop(&child, "size", &len_size);
+	if (!p_start || len_start != sizeof(*p_start) || !p_size ||
+	    len_size != sizeof(*p_size)) {
+		return false;
+	}
+
+	if (*p_start & (align - 1)) {
+		pr_warn("KHO reserve-mem '%s' has wrong alignment (0x%lx, 0x%lx)\n",
+			name, (long)align, (long)*p_start);
+		return false;
+	}
+
+	if (*p_size != size) {
+		pr_warn("KHO reserve-mem '%s' has wrong size (0x%lx != 0x%lx)\n",
+			name, (long)*p_size, (long)size);
+		return false;
+	}
+
+	reserved_mem_add(*p_start, size, name);
+	pr_info("Revived memory reservation '%s' from KHO\n", name);
+
+	return true;
+}
+#else
+static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size,
+					  phys_addr_t align)
+{
+	return false;
+}
+#endif /* CONFIG_KEXEC_HANDOVER */
+
 /*
  * Parse reserve_mem=nn:align:name
  */
@@ -2486,6 +2660,11 @@ static int __init reserve_mem(char *p)
 	if (reserve_mem_find_by_name(name, &start, &tmp))
 		return -EBUSY;
 
+	/* Pick previous allocations up from KHO if available */
+	if (reserve_mem_kho_revive(name, size, align))
+		return 1;
+
+	/* TODO: Allocation must be outside of scratch region */
 	start = memblock_phys_alloc(size, align);
 	if (!start)
 		return -ENOMEM;
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:51 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:51 -0700
Subject: [PATCH v5 16/16] Documentation: add documentation for KHO
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-17-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

With KHO in place, let's add documentation that describes what it is and
how to use it.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 .../admin-guide/kernel-parameters.txt         |  25 ++++
 Documentation/kho/concepts.rst                |  70 +++++++++++
 Documentation/kho/fdt.rst                     |  62 +++++++++
 Documentation/kho/index.rst                   |  14 +++
 Documentation/kho/usage.rst                   | 118 ++++++++++++++++++
 Documentation/subsystem-apis.rst              |   1 +
 MAINTAINERS                                   |   1 +
 7 files changed, 291 insertions(+)
 create mode 100644 Documentation/kho/concepts.rst
 create mode 100644 Documentation/kho/fdt.rst
 create mode 100644 Documentation/kho/index.rst
 create mode 100644 Documentation/kho/usage.rst

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec8..d715c6d9dbb3 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2698,6 +2698,31 @@
 	kgdbwait	[KGDB,EARLY] Stop kernel execution and enter the
 			kernel debugger at the earliest opportunity.
 
+	kho=		[KEXEC,EARLY]
+			Format: { "0" | "1" | "off" | "on" | "y" | "n" }
+			Enables or disables Kexec HandOver.
+			"0" | "off" | "n" - kexec handover is disabled
+			"1" | "on" | "y" - kexec handover is enabled
+
+	kho_scratch=	[KEXEC,EARLY]
+			Format: ll[KMG],mm[KMG],nn[KMG] | nn%
+			Defines the size of the KHO scratch region. The KHO
+			scratch regions are physically contiguous memory
+			ranges that can only be used for non-kernel
+			allocations. That way, even when memory is heavily
+			fragmented with handed over memory, the kexeced
+			kernel will always have enough contiguous ranges to
+			bootstrap itself.
+
+			It is possible to specify the exact amount of
+			memory in the form of "ll[KMG],mm[KMG],nn[KMG]"
+			where the first parameter defines the size of a low
+			memory scratch area, the second parameter defines
+			the size of a global scratch area and the third
+			parameter defines the size of additional per-node
+			scratch areas.  The form "nn%" defines scale factor
+			(in percents) of memory that was used during boot.
+
 	kmac=		[MIPS] Korina ethernet MAC address.
 			Configure the RouterBoard 532 series on-chip
 			Ethernet adapter MAC address.
diff --git a/Documentation/kho/concepts.rst b/Documentation/kho/concepts.rst
new file mode 100644
index 000000000000..174e23404ebc
--- /dev/null
+++ b/Documentation/kho/concepts.rst
@@ -0,0 +1,70 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+.. _concepts:
+
+=======================
+Kexec Handover Concepts
+=======================
+
+Kexec HandOver (KHO) is a mechanism that allows Linux to preserve state -
+arbitrary properties as well as memory locations - across kexec.
+
+It introduces multiple concepts:
+
+KHO State tree
+==============
+
+Every KHO kexec carries a state tree, in the format of flattened device tree
+(FDT), that describes the state of the system. Device drivers can register to
+KHO to serialize their state before kexec. After KHO, device drivers can read
+the FDT and extract previous state.
+
+KHO only uses the FDT container format and libfdt library, but does not
+adhere to the same property semantics that normal device trees do: Properties
+are passed in native endianness and standardized properties like ``regs`` and
+``ranges`` do not exist, hence there are no ``#...-cells`` properties.
+
+Scratch Regions
+===============
+
+To boot into kexec, we need to have a physically contiguous memory range that
+contains no handed over memory. Kexec then places the target kernel and initrd
+into that region. The new kernel exclusively uses this region for memory
+allocations before during boot up to the initialization of the page allocator.
+
+We guarantee that we always have such regions through the scratch regions: On
+first boot KHO allocates several physically contiguous memory regions. Since
+after kexec these regions will be used by early memory allocations, there is a
+scratch region per NUMA node plus a scratch region to satisfy allocations
+requests that do not require particular NUMA node assignment.
+By default, size of the scratch region is calculated based on amount of memory
+allocated during boot. The ``kho_scratch`` kernel command line option may be
+used to explicitly define size of the scratch regions.
+The scratch regions are declared as CMA when page allocator is initialized so
+that their memory can be used during system lifetime. CMA gives us the
+guarantee that no handover pages land in that region, because handover pages
+must be at a static physical memory location and CMA enforces that only
+movable pages can be located inside.
+
+After KHO kexec, we ignore the ``kho_scratch`` kernel command line option and
+instead reuse the exact same region that was originally allocated. This allows
+us to recursively execute any amount of KHO kexecs. Because we used this region
+for boot memory allocations and as target memory for kexec blobs, some parts
+of that memory region may be reserved. These reservations are irrelevant for
+the next KHO, because kexec can overwrite even the original kernel.
+
+.. _finalization_phase:
+
+KHO finalization phase
+======================
+
+To enable user space based kexec file loader, the kernel needs to be able to
+provide the FDT that describes the previous kernel's state before
+performing the actual kexec. The process of generating that FDT is
+called serialization. When the FDT is generated, some properties
+of the system may become immutable because they are already written down
+in the FDT. That state is called the KHO finalization phase.
+
+With the in-kernel kexec file loader, i.e., using the syscall
+``kexec_file_load``, KHO FDT is not created until the actual kexec. Thus the
+finalization phase is much shorter. User space can optionally choose to generate
+the FDT early using the debugfs interface.
diff --git a/Documentation/kho/fdt.rst b/Documentation/kho/fdt.rst
new file mode 100644
index 000000000000..70b508533b77
--- /dev/null
+++ b/Documentation/kho/fdt.rst
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+=======
+KHO FDT
+=======
+
+KHO uses the flattened device tree (FDT) container format and libfdt
+library to create and parse the data that is passed between the
+kernels. The properties in KHO FDT are stored in native format and can
+include any data KHO users need to preserve. Parsing of FDT subnodes is
+responsibility of KHO users, except for nodes and properties defined by
+KHO itself.
+
+KHO nodes and properties
+========================
+
+Node ``preserved-memory``
+-------------------------
+
+KHO saves a special node named ``preserved-memory`` under the root node.
+This node contains the metadata for KHO to preserve pages across kexec.
+
+Property ``compatible``
+-----------------------
+
+The ``compatible`` property determines compatibility between the kernel
+that created the KHO FDT and the kernel that attempts to load it.
+If the kernel that loads the KHO FDT is not compatible with it, the entire
+KHO process will be bypassed.
+
+Examples
+========
+
+The following example demonstrates KHO FDT that preserves two memory
+regions create with ``reserve_mem`` kernel command line parameter::
+
+  /dts-v1/;
+
+  / {
+  	compatible = "kho-v1";
+
+  	memblock {
+  		compatible = "memblock-v1";
+
+  		region1 {
+  			compatible = "reserve-mem-v1";
+  			start = <0xc07a 0x4000000>;
+			size = <0x01 0x00>;
+  		};
+
+		region2 {
+			compatible = "reserve-mem-v1";
+			start = <0xc07b 0x4000000>;
+			size = <0x8000 0x00>;
+		};
+
+  	};
+
+	preserved-memory {
+                metadata = <0x00 0x00>;
+        };
+  };
diff --git a/Documentation/kho/index.rst b/Documentation/kho/index.rst
new file mode 100644
index 000000000000..d108c3f8d15c
--- /dev/null
+++ b/Documentation/kho/index.rst
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+========================
+Kexec Handover Subsystem
+========================
+
+.. toctree::
+   :maxdepth: 1
+
+   concepts
+   usage
+   fdt
+
+.. only::  subproject and html
diff --git a/Documentation/kho/usage.rst b/Documentation/kho/usage.rst
new file mode 100644
index 000000000000..b45dc58e8d3f
--- /dev/null
+++ b/Documentation/kho/usage.rst
@@ -0,0 +1,118 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+====================
+Kexec Handover Usage
+====================
+
+Kexec HandOver (KHO) is a mechanism that allows Linux to preserve state -
+arbitrary properties as well as memory locations - across kexec.
+
+This document expects that you are familiar with the base KHO
+:ref:`concepts <concepts>`. If you have not read
+them yet, please do so now.
+
+Prerequisites
+=============
+
+KHO is available when the ``CONFIG_KEXEC_HANDOVER`` config option is set to y
+at compile time. Every KHO producer may have its own config option that you
+need to enable if you would like to preserve their respective state across
+kexec.
+
+To use KHO, please boot the kernel with the ``kho=on`` command line
+parameter. You may use ``kho_scratch`` parameter to define size of the
+scratch regions. For example ``kho_scratch=16M,512M,256M`` will reserve a
+16 MiB low memory scratch area, a 512 MiB global scratch region, and 256 MiB
+per NUMA node scratch regions on boot.
+
+Perform a KHO kexec
+===================
+
+First, before you perform a KHO kexec, you can optionally move the system into
+the :ref:`KHO finalization phase <finalization_phase>` ::
+
+  $ echo 1 > /sys/kernel/debug/kho/out/finalize
+
+After this command, the KHO FDT is available in
+``/sys/kernel/debug/kho/out/fdt``.
+
+Next, load the target payload and kexec into it. It is important that you
+use the ``-s`` parameter to use the in-kernel kexec file loader, as user
+space kexec tooling currently has no support for KHO with the user space
+based file loader ::
+
+  # kexec -l Image --initrd=initrd -s
+  # kexec -e
+
+If you skipped finalization in the first step, ``kexec -e`` triggers
+FDT finalization automatically. The new kernel will boot up and contain
+some of the previous kernel's state.
+
+For example, if you used ``reserve_mem`` command line parameter to create
+an early memory reservation, the new kernel will have that memory at the
+same physical address as the old kernel.
+
+Unfreeze KHO FDT data
+=====================
+
+You can move the system out of KHO finalization phase by calling ::
+
+  $ echo 0 > /sys/kernel/debug/kho/out/finalize
+
+After this command, the KHO FDT is no longer available in
+``/sys/kernel/debug/kho/out/fdt``, and the states kept in KHO can be
+modified by other kernel subsystems again.
+
+debugfs Interfaces
+==================
+
+Currently KHO creates the following debugfs interfaces. Notice that these
+interfaces may change in the future. They will be moved to sysfs once KHO is
+stabilized.
+
+``/sys/kernel/debug/kho/out/finalize``
+    Kexec HandOver (KHO) allows Linux to transition the state of
+    compatible drivers into the next kexec'ed kernel. To do so,
+    device drivers will serialize their current state into an FDT.
+    While the state is serialized, they are unable to perform
+    any modifications to state that was serialized, such as
+    handed over memory allocations.
+
+    When this file contains "1", the system is in the transition
+    state. When contains "0", it is not. To switch between the
+    two states, echo the respective number into this file.
+
+``/sys/kernel/debug/kho/out/fdt_max``
+    KHO needs to allocate a buffer for the FDT that gets
+    generated before it knows the final size. By default, it
+    will allocate 10 MiB for it. You can write to this file
+    to modify the size of that allocation.
+
+``/sys/kernel/debug/kho/out/fdt``
+    When KHO state tree is finalized, the kernel exposes the
+    flattened device tree blob that carries its current KHO
+    state in this file. Kexec user space tooling can use this
+    as input file for the KHO payload image.
+
+``/sys/kernel/debug/kho/out/scratch_len``
+    To support continuous KHO kexecs, we need to reserve
+    physically contiguous memory regions that will always stay
+    available for future kexec allocations. This file describes
+    the length of these memory regions. Kexec user space tooling
+    can use this to determine where it should place its payload
+    images.
+
+``/sys/kernel/debug/kho/out/scratch_phys``
+    To support continuous KHO kexecs, we need to reserve
+    physically contiguous memory regions that will always stay
+    available for future kexec allocations. This file describes
+    the physical location of these memory regions. Kexec user space
+    tooling can use this to determine where it should place its
+    payload images.
+
+``/sys/kernel/debug/kho/in/fdt``
+    When the kernel was booted with Kexec HandOver (KHO),
+    the state tree that carries metadata about the previous
+    kernel's state is in this file in the format of flattened
+    device tree. This file may disappear when all consumers of
+    it finished to interpret their metadata.
diff --git a/Documentation/subsystem-apis.rst b/Documentation/subsystem-apis.rst
index b52ad5b969d4..5fc69d6ff9f0 100644
--- a/Documentation/subsystem-apis.rst
+++ b/Documentation/subsystem-apis.rst
@@ -90,3 +90,4 @@ Other subsystems
    peci/index
    wmi/index
    tee/index
+   kho/index
diff --git a/MAINTAINERS b/MAINTAINERS
index a000a277ccf7..d0df0b380e34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12828,6 +12828,7 @@ F:	include/linux/kernfs.h
 KEXEC
 L:	kexec at lists.infradead.org
 W:	http://kernel.org/pub/linux/utils/kernel/kexec/
+F:	Documentation/kho/
 F:	include/linux/kexec*.h
 F:	include/uapi/linux/kexec.h
 F:	kernel/kexec*
-- 
2.48.1.711.g2feabab25a-goog



From hans.zhang at cixtech.com  Wed Mar 19 19:14:02 2025
From: hans.zhang at cixtech.com (hans.zhang)
Date: Thu, 20 Mar 2025 10:14:02 +0800
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <20250319095511.hf3y2c6vbbnm3ien@thinkpad>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <Z9pffxeXHVOsoi4O@nchen-desktop> <20250319062534.ollh3s5t7znf5zqs@uda0492258>
 <Z9qO1f5MgNcwO5A4@nchen-desktop> <20250319095511.hf3y2c6vbbnm3ien@thinkpad>
Message-ID: <a8966792-fa0e-4e8e-aceb-427819ae4ef5@cixtech.com>



On 2025/3/19 17:55, manivannan.sadhasivam at linaro.org wrote:
> EXTERNAL EMAIL
> 
> On Wed, Mar 19, 2025 at 05:31:01PM +0800, Peter Chen wrote:
>> On 25-03-19 14:25:34, Siddharth Vadapalli wrote:
>>>>>
>>>>> Hello,
>>>>>
>>>>> This series enables support to build the PCIe Cadence Controller drivers
>>>>> and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
>>>>> Modules. The motivation for this series is that PCIe is not a necessity
>>>>> for booting the SoC, due to which it doesn't have to be a built-in
>>>>> module. Additionally, the defconfig doesn't enable the PCIe Cadence
>>>>> Controller drivers and the PCI J721E driver, due to which PCIe is not
>>>>> supported by default. Enabling the configs as of now (i.e. without this
>>>>> series) will result in built-in drivers i.e. a bloated Linux Image for
>>>>> everyone who doesn't have the PCIe Controller.
>>>>
>>>> If the user doesn't enable PCIe controller device through DTS/ACPI,
>>>> that's doesn't matter.
>>>
>>> The Linux Image for arm64 systems built using:
>>> arch/arm64/configs/defconfig
>>> will not have support for the Cadence PCIe Controller and the PCIe J721e
>>> driver, because these configs aren't enabled.
>>>
>>>>
>>>>> @@ -209,6 +209,12 @@ CONFIG_NFC=m
>>>>>   CONFIG_NFC_NCI=m
>>>>>   CONFIG_NFC_S3FWRN5_I2C=m
>>>>>   CONFIG_PCI=y
>>>>> +CONFIG_PCI_J721E=m
>>>>> +CONFIG_PCI_J721E_HOST=m
>>>>> +CONFIG_PCI_J721E_EP=m
>>>>> +CONFIG_PCIE_CADENCE=m
>>>>> +CONFIG_PCIE_CADENCE_HOST=m
>>>>> +CONFIG_PCIE_CADENCE_EP=m
>>>>
>>>> The common Cadence configuration will be select if the glue layer's
>>>> configuration is select according to Kconfig.
>>>>
>>>> Please do not set common configuration as module, some user may need
>>>> it as build-in like dw's. Considering the situation, the rootfs is at
>>>> NVMe.
>>>
>>> The common configuration at the moment is "DISABLED" i.e. no support for
>>> the Cadence Controller at all. Which "user" are you referring to? This
>>> series was introduced since having the drivers built-in was pushed back at:
>>
>> We are using Cadence controller, and prepare upstream radxa-o6 board
>> whose rootfs is at PCIe NVMe.
>>
> 
> It doesn't matter. Only criteria AFAIK to build the driver as built-in in
> defconfig is that it should be a depedency for console. For some time, storage
> was also a dependency, but for sure PCIe is not.
> 
> Moreover, CONFIG_BLK_DEV_NVME is built as a module in ARM64 defconfig. So it
> doesn't matter if you build PCIe controller driver as a built-in or not. You
> need to load the NVMe driver somehow.
> 
> So please use initramfs.
> 
>> You could build driver as module for TI glue layer, but don't force
>> other vendors using module as well, see dwc as an example please.
>>
> 
> DWC is a bad example here. Only reason the DWC drivers are not loadable is due
> to the in-built MSI controller implementation as irqchip. People tend to build
> the irqchip controllers as always built-in for some known issues. Even then some
> driver developers prefer to built them as loadable module but suppress unbind to
> avoid rmmoding the module.
Hi Mani,

I think the MSI RTL module provided by Synopsys PCIe controller IP is 
not a standard operation. The reason for this MSI module is probably to 
be used by some cpus that do not have ITS(LPI interrupt) designed. Or 
RISC-V SOC, etc. MSI is defined as an MSI/MSIX interrupt that starts 
with a direct write memory access.

There are also SOC vendors that do not use the built-in MSI RTL module. 
Instead, MSI/MSIX interrupts are transmitted directly to the GIC's ITS 
module via the GIC V3/V4 interface. For example, RK3588, they do not use 
the PCIe controller built-in MSI module. Some Qualcomm platforms also 
modify the PCIe controller's built-in MSI modules to connect each of 
them to 32 SPI interrupts to the GIC. I was under the impression that 
the SDM845 was designed that way. The only explanation is that SPI 
interrupts are faster than LPI interrupts without having to look up some 
tables.

So the dwc driver can also compile to ko?

Best regards,
Hans



From ck.hu at mediatek.com  Wed Mar 19 19:18:04 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Thu, 20 Mar 2025 02:18:04 +0000
Subject: [PATCH v8 4/5] media: platform: mediatek: isp: add mediatek
 ISP3.0 camsv
In-Reply-To: <20250122-add-mtk-isp-3-0-support-v8-4-a3d3731eef45@baylibre.com>
References: <20250122-add-mtk-isp-3-0-support-v8-0-a3d3731eef45@baylibre.com>
	 <20250122-add-mtk-isp-3-0-support-v8-4-a3d3731eef45@baylibre.com>
Message-ID: <b68208ea56f297fab0a0c290e73a8671366735b6.camel@mediatek.com>

On Wed, 2025-01-22 at 14:59 +0100, Julien Stephan wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> From: Phi-bang Nguyen <pnguyen at baylibre.com>
> 
> This driver provides a path to bypass the SoC ISP so that image data
> coming from the SENINF can go directly into memory without any image
> processing. This allows the use of an external ISP.
> 
> Signed-off-by: Phi-bang Nguyen <pnguyen at baylibre.com>
> Signed-off-by: Florian Sylvestre <fsylvestre at baylibre.com>
> [Paul Elder fix irq locking]
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> Co-developed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Co-developed-by: Julien Stephan <jstephan at baylibre.com>
> Signed-off-by: Julien Stephan <jstephan at baylibre.com>
> ---

[snip]

> +
> +void mtk_camsv_setup(struct mtk_cam_dev *cam_dev, unsigned int count,
> +                    u32 w, u32 h, u32 bpl, u32 mbus_fmt)
> +{
> +       const struct mtk_cam_conf *conf = cam_dev->conf;
> +       const struct mtk_cam_format_info *fmtinfo;
> +       struct mtk_cam_dev_buffer *buf;
> +       unsigned long flags;
> +       unsigned int i;
> +       u32 tmp;
> +
> +       for (i = 0; i < count; i++)
> +               mtk_camsv_fbc_inc(cam_dev);

I think you should call mtk_camsv_fbc_inc() only after mtk_camsv_update_buffers_add().

> +
> +       fmtinfo = mtk_cam_format_info_by_code(mbus_fmt);
> +
> +       mtk_camsv_tg_write(cam_dev, CAMSV_TG_SEN_MODE, conf->tg_sen_mode);
> +
> +       mtk_camsv_tg_write(cam_dev, CAMSV_TG_SEN_GRAB_PXL,
> +                            (w * fmtinfo->w_factor) << 16U);
> +
> +       mtk_camsv_tg_write(cam_dev, CAMSV_TG_SEN_GRAB_LIN, h << 16U);
> +
> +       /* YUV_U2S_DIS: disable YUV sensor unsigned to signed */
> +       mtk_camsv_tg_write(cam_dev, CAMSV_TG_PATH_CFG, 0x1000U);
> +
> +       /* Reset cam */
> +       mtk_camsv_write(cam_dev, CAMSV_SW_CTL, CAMSV_SW_RST);
> +       mtk_camsv_write(cam_dev, CAMSV_SW_CTL, 0x0U);
> +       mtk_camsv_write(cam_dev, CAMSV_SW_CTL, CAMSV_IMGO_RST_TRIG);
> +
> +       readl_poll_timeout_atomic(cam_dev->regs + CAMSV_SW_CTL, tmp,
> +                                 (tmp == (CAMSV_IMGO_RST_TRIG |
> +                                          CAMSV_IMGO_RST_ST)), 10, 200);
> +
> +       mtk_camsv_write(cam_dev, CAMSV_SW_CTL, 0x0U);
> +
> +       mtk_camsv_write(cam_dev, CAMSV_INT_EN, INT_ST_MASK_CAMSV);
> +
> +       mtk_camsv_write(cam_dev, CAMSV_MODULE_EN,
> +                         conf->module_en | fmtinfo->module_en_pak);
> +       mtk_camsv_write(cam_dev, CAMSV_FMT_SEL, fmtinfo->fmt_sel);
> +       mtk_camsv_write(cam_dev, CAMSV_PAK, fmtinfo->pak);
> +
> +       mtk_camsv_img0_write(cam_dev, CAMSV_IMGO_SV_XSIZE, bpl - 1U);
> +       mtk_camsv_img0_write(cam_dev, CAMSV_IMGO_SV_YSIZE, h - 1U);
> +
> +       mtk_camsv_img0_write(cam_dev, CAMSV_IMGO_SV_STRIDE,
> +                              fmtinfo->imgo_stride | bpl);
> +
> +       mtk_camsv_img0_write(cam_dev, CAMSV_IMGO_SV_CON, conf->imgo_con);
> +       mtk_camsv_img0_write(cam_dev, CAMSV_IMGO_SV_CON2, conf->imgo_con2);
> +
> +       /* Set buf addr */
> +       spin_lock_irqsave(&cam_dev->buf_list_lock, flags);
> +       buf = list_first_entry_or_null(&cam_dev->buf_list,
> +                                      struct mtk_cam_dev_buffer,
> +                                      list);
> +       if (buf)
> +               mtk_camsv_update_buffers_add(cam_dev, buf);
> +       spin_unlock_irqrestore(&cam_dev->buf_list_lock, flags);
> +
> +       /* CMOS_EN first */
> +       mtk_camsv_tg_write(cam_dev, CAMSV_TG_SEN_MODE,
> +                            mtk_camsv_tg_read(cam_dev, CAMSV_TG_SEN_MODE) |
> +                            CAMSV_TG_SEN_MODE_CMOS_EN);
> +
> +       /* finally, CAMSV_MODULE_EN : IMGO_EN */
> +       mtk_camsv_write(cam_dev, CAMSV_MODULE_EN,
> +                         mtk_camsv_read(cam_dev, CAMSV_MODULE_EN) |
> +                         CAMSV_MODULE_EN_IMGO_EN);
> +}
> +

[snip]

> +
> +static int mtk_camsv_runtime_resume(struct device *dev)
> +{
> +       struct mtk_cam_dev *cam_dev = dev_get_drvdata(dev);
> +       struct vb2_queue *vbq = &cam_dev->vdev.vbq;
> +       struct mtk_cam_dev_buffer *buf;
> +       unsigned long flags = 0;
> +       int ret;
> +
> +       ret = clk_bulk_prepare_enable(cam_dev->num_clks, cam_dev->clks);
> +       if (ret) {
> +               dev_err(dev, "failed to enable clock:%d\n", ret);
> +               return ret;
> +       }
> +
> +       if (vb2_is_streaming(vbq)) {
> +
> +               spin_lock_irqsave(&cam_dev->buf_list_lock, flags);
> +               buf = list_first_entry_or_null(&cam_dev->buf_list,
> +                                              struct mtk_cam_dev_buffer,
> +                                              list);
> +               if (buf)
> +                       mtk_camsv_update_buffers_add(cam_dev, buf);

I don't know, when suspend, the register value would be kept or not.
If register is not kept, I think you should re-program all register in mtk_camsv_setup().
But it seems it's not necessary, so the register is kept and you don't need to set register again.
So this mtk_camsv_update_buffers_add() is redundant.

> +
> +               spin_unlock_irqrestore(&cam_dev->buf_list_lock, flags);
> +
> +               /* Stream on the sub-device */
> +               ret = v4l2_subdev_enable_streams(&cam_dev->subdev,
> +                                                cam_dev->subdev_pads[MTK_CAM_CIO_PAD_VIDEO].index,
> +                                                BIT(0));
> +
> +               if (ret)
> +                       goto fail_no_stream;
> +       }
> +
> +       return 0;
> +
> +fail_no_stream:
> +       mtk_cam_vb2_return_all_buffers(cam_dev, VB2_BUF_STATE_QUEUED);
> +       return ret;
> +}
> +
> +static const struct dev_pm_ops mtk_camsv_pm_ops = {
> +       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> +                               pm_runtime_force_resume)
> +       SET_RUNTIME_PM_OPS(mtk_camsv_runtime_suspend,
> +                          mtk_camsv_runtime_resume, NULL)
> +};
> +#endif
> +

[snip]

> +/* -----------------------------------------------------------------------------
> + * Format Information
> + */
> +
> +static const struct mtk_cam_format_info mtk_cam_format_info[] = {
> +       {
> +               .fourcc = V4L2_PIX_FMT_SBGGR8,
> +               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
> +               .bpp = 8,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_8
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_8,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGBRG8,
> +               .code = MEDIA_BUS_FMT_SGBRG8_1X8,
> +               .bpp = 8,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_8
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_8,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGRBG8,
> +               .code = MEDIA_BUS_FMT_SGRBG8_1X8,
> +               .bpp = 8,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_8
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_8,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SRGGB8,
> +               .code = MEDIA_BUS_FMT_SRGGB8_1X8,
> +               .bpp = 8,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_8
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_8,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SBGGR10,

In stream_out_fmts[], it does not declare V4L2_PIX_FMT_SBGGR10.
So you may remove it in mtk_cam_format_info[], or add it in stream_out_fmts[].

> +               .code = MEDIA_BUS_FMT_SBGGR10_1X10,
> +               .bpp = 10,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_10
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_10,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGBRG10,

Ditto.

> +               .code = MEDIA_BUS_FMT_SGBRG10_1X10,
> +               .bpp = 10,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_10
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_10,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGRBG10,

Ditto.

> +               .code = MEDIA_BUS_FMT_SGRBG10_1X10,
> +               .bpp = 10,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_10
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_10,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SRGGB10,

Ditto.

> +               .code = MEDIA_BUS_FMT_SRGGB10_1X10,
> +               .bpp = 10,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_10
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_10,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SBGGR12,

Ditto.

> +               .code = MEDIA_BUS_FMT_SBGGR12_1X12,
> +               .bpp = 12,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_12
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_12,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGBRG12,

Ditto.

> +               .code = MEDIA_BUS_FMT_SGBRG12_1X12,
> +               .bpp = 12,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_12
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_12,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SGRBG12,

Ditto.

> +               .code = MEDIA_BUS_FMT_SGRBG12_1X12,
> +               .bpp = 12,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_12
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_12,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_SRGGB12,

Ditto.

> +               .code = MEDIA_BUS_FMT_SRGGB12_1X12,
> +               .bpp = 12,
> +               .w_factor = 1,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_EN,
> +               .pak = CAMSV_PAK_PAK_MODE_RAW_12
> +                       | CAMSV_PAK_PAK_DBL_MODE_2_PIXELS,
> +               .fmt_sel = CAMSV_FMT_SEL_TG1_FMT_RAW_12,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_32,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_UYVY,
> +               .code = MEDIA_BUS_FMT_UYVY8_1X16,
> +               .bpp = 16,
> +               .w_factor = 2,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_SEL,
> +               .pak = 0, /* ignored */
> +               .fmt_sel = CAMSV_FMT_SEL_IMGO_BUS_SIZE_16
> +                       | CAMSV_FMT_SEL_TG1_FMT_YUV422,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_16,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_VYUY,
> +               .code = MEDIA_BUS_FMT_VYUY8_1X16,
> +               .bpp = 16,
> +               .w_factor = 2,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_SEL,
> +               .pak = 0, /* ignored */
> +               .fmt_sel = CAMSV_FMT_SEL_IMGO_BUS_SIZE_16
> +                       | CAMSV_FMT_SEL_TG1_FMT_YUV422,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_16,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_YUYV,
> +               .code = MEDIA_BUS_FMT_YUYV8_1X16,
> +               .bpp = 16,
> +               .w_factor = 2,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_SEL,
> +               .pak = 0, /* ignored */
> +               .fmt_sel = CAMSV_FMT_SEL_IMGO_BUS_SIZE_16
> +                       | CAMSV_FMT_SEL_TG1_FMT_YUV422,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_16,
> +       }, {
> +               .fourcc = V4L2_PIX_FMT_YVYU,
> +               .code = MEDIA_BUS_FMT_YVYU8_1X16,
> +               .bpp = 16,
> +               .w_factor = 2,
> +               .module_en_pak = CAMSV_MODULE_EN_PAK_SEL,
> +               .pak = 0, /* ignored */
> +               .fmt_sel = CAMSV_FMT_SEL_IMGO_BUS_SIZE_16
> +                       | CAMSV_FMT_SEL_TG1_FMT_YUV422,
> +               .imgo_stride = CAMSV_IMGO_SV_STRIDE_BUS_SIZE_EN
> +                       | CAMSV_IMGO_SV_STRIDE_BUS_SIZE_16,
> +       },
> +};
> +

[snip]

> +
> +static void mtk_cam_vb2_buf_queue(struct vb2_buffer *vb)
> +{
> +       struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
> +       struct mtk_cam_dev_buffer *buf = to_mtk_cam_dev_buffer(vb);
> +       unsigned long flags;
> +
> +       /* Add the buffer into the tracking list */
> +       spin_lock_irqsave(&cam->buf_list_lock, flags);
> +       if (vb2_start_streaming_called(vb->vb2_queue) && list_empty(&cam->buf_list))
> +               mtk_camsv_update_buffers_add(cam, buf);
> +
> +       list_add_tail(&buf->list, &cam->buf_list);
> +       spin_unlock_irqrestore(&cam->buf_list_lock, flags);
> +       if (vb2_start_streaming_called(vb->vb2_queue))
> +               mtk_camsv_fbc_inc(cam);

I think you should call mtk_camsv_fbc_inc() just after mtk_camsv_update_buffers_add();

> +}
> +

[snip]

> +
> +static int mtk_cam_vidioc_try_fmt(struct file *file, void *fh,
> +                                 struct v4l2_format *f)
> +{
> +       struct mtk_cam_video_device *vdev = file_to_mtk_cam_video_device(file);
> +       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
> +       const struct mtk_cam_format_info *fmtinfo;
> +
> +       /* Validate pixelformat */
> +       if (!mtk_cam_dev_find_fmt(vdev->desc, pix_mp->pixelformat))
> +               pix_mp->pixelformat = vdev->desc->fmts[0];

In [1], it says return EINVAL when driver not support this buffer format.

[1] https://docs.kernel.org/userspace-api/media/v4l/vidioc-g-fmt.html#description

Regards,
CK

> +
> +       pix_mp->width = clamp_val(pix_mp->width, IMG_MIN_WIDTH, IMG_MAX_WIDTH);
> +       pix_mp->height = clamp_val(pix_mp->height, IMG_MIN_HEIGHT,
> +                                  IMG_MAX_HEIGHT);
> +
> +       pix_mp->num_planes = 1;
> +
> +       fmtinfo = mtk_cam_format_info_by_fourcc(pix_mp->pixelformat);
> +       calc_bpl_size_pix_mp(fmtinfo, pix_mp);
> +
> +       /* Constant format fields */
> +       pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
> +       pix_mp->field = V4L2_FIELD_NONE;
> +       pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> +       pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
> +       pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
> +
> +       return 0;
> +}
> +


From song at kernel.org  Wed Mar 19 19:20:28 2025
From: song at kernel.org (Song Liu)
Date: Wed, 19 Mar 2025 19:20:28 -0700
Subject: [PATCH v2 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <yrqgoc66te54tuffkrc74clsosiid2giw3gpc3kd3ddl4662tb@kiqh3ncfxwnl>
References: <20250319213707.1784775-1-song@kernel.org> <20250319213707.1784775-2-song@kernel.org>
 <yrqgoc66te54tuffkrc74clsosiid2giw3gpc3kd3ddl4662tb@kiqh3ncfxwnl>
Message-ID: <CAPhsuW6AUiu4CryCkskHxe=BEX=LA9P81MWX1aGSN4j0bqTFXw@mail.gmail.com>

On Wed, Mar 19, 2025 at 3:35?PM Josh Poimboeuf <jpoimboe at kernel.org> wrote:
>
> On Wed, Mar 19, 2025 at 02:37:06PM -0700, Song Liu wrote:
> > +noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
> > +                     void *cookie, struct task_struct *task)
> > +{
> > +     struct kunwind_consume_entry_data data = {
> > +             .consume_entry = consume_entry,
> > +             .cookie = cookie,
> > +     };
> > +     int ret;
> > +
> > +     ret = kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL, true);
> > +     if (ret == -ENOENT)
> > +             ret = 0;
>
> Is this check redundant with the -ENOENT check in do_kunwind() which
> already converts ret to zero?

Indeed. This check is redundant.

Thanks,
Song


From jiebing.chen at amlogic.com  Wed Mar 19 19:26:31 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 10:26:31 +0800
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <7084e271-8546-4a49-9eb8-ee3f647c529a@kernel.org>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
 <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>
 <9ae73d75-9c59-4255-8924-b456c86cbc01@amlogic.com>
 <7084e271-8546-4a49-9eb8-ee3f647c529a@kernel.org>
Message-ID: <e5d3741d-0f4e-4f92-9b1c-04b114892330@amlogic.com>


? 2025/3/20 3:31, Krzysztof Kozlowski ??:
> [ EXTERNAL EMAIL ]
>
> On 19/03/2025 11:09, Jiebing Chen wrote:
>> ? 2025/3/19 16:22, Krzysztof Kozlowski ??:
>>> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>>>
>>> [ EXTERNAL EMAIL ]
>>>
>>> On Wed, Mar 19, 2025 at 03:04:45PM +0800, jiebing chen wrote:
>>>> Add clock IDs for the mclk pads found on s4 SoCs
>>>>
>>>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>>>> ---
>>>>    include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++
>>> This belongs to the binding patch, usually.
>>>
>>> Anyway - do not ask us to do the work twice.
>>>
>>> <form letter>
>>> This is a friendly reminder during the review process.
>>>
>>> It looks like you received a tag and forgot to add it.
>>>
>>> If you do not know the process, here is a short explanation:
>>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
>>> versions of patchset, under or above your Signed-off-by tag, unless
>>> patch changed significantly (e.g. new properties added to the DT
>>> bindings). Tag is "received", when provided in a message replied to you
>>> on the mailing list. Tools like b4 can help here. However, there's no
>>> need to repost patches *only* to add the tags. The upstream maintainer
>>> will do that for tags received on the version they apply.
>>>
>>> Please read:
>>> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577
>>>
>>> If a tag was not added on purpose, please state why and what changed.
>>> </form letter>
>> thanks for your remind
> Are you going to do anything or you are going to ignore us?

sorry, i forget to use the b4 trailers -u to check the tag, you are 
great, we should check any message in https://lore.kernel.org/

some email might not received, fix it in another version, I will check 
all the missing comments, Thank you again

>
> Best regards,
> Krzysztof


From hans.zhang at cixtech.com  Wed Mar 19 19:26:46 2025
From: hans.zhang at cixtech.com (hans.zhang)
Date: Thu, 20 Mar 2025 10:26:46 +0800
Subject: [PATCH 0/4] Loadable Module support for PCIe Cadence and J721E
In-Reply-To: <a8966792-fa0e-4e8e-aceb-427819ae4ef5@cixtech.com>
References: <20250307103128.3287497-1-s-vadapalli@ti.com>
 <Z9pffxeXHVOsoi4O@nchen-desktop> <20250319062534.ollh3s5t7znf5zqs@uda0492258>
 <Z9qO1f5MgNcwO5A4@nchen-desktop> <20250319095511.hf3y2c6vbbnm3ien@thinkpad>
 <a8966792-fa0e-4e8e-aceb-427819ae4ef5@cixtech.com>
Message-ID: <2ac84de4-a421-4271-81e5-9b8489b37238@cixtech.com>



On 2025/3/20 10:14, hans.zhang wrote:
> EXTERNAL EMAIL
> 
> On 2025/3/19 17:55, manivannan.sadhasivam at linaro.org wrote:
>> EXTERNAL EMAIL
>>
>> On Wed, Mar 19, 2025 at 05:31:01PM +0800, Peter Chen wrote:
>>> On 25-03-19 14:25:34, Siddharth Vadapalli wrote:
>>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> This series enables support to build the PCIe Cadence Controller 
>>>>>> drivers
>>>>>> and the PCI J721E Application/Wrapper/Glue driver as Loadable Kernel
>>>>>> Modules. The motivation for this series is that PCIe is not a 
>>>>>> necessity
>>>>>> for booting the SoC, due to which it doesn't have to be a built-in
>>>>>> module. Additionally, the defconfig doesn't enable the PCIe Cadence
>>>>>> Controller drivers and the PCI J721E driver, due to which PCIe is not
>>>>>> supported by default. Enabling the configs as of now (i.e. without 
>>>>>> this
>>>>>> series) will result in built-in drivers i.e. a bloated Linux Image 
>>>>>> for
>>>>>> everyone who doesn't have the PCIe Controller.
>>>>>
>>>>> If the user doesn't enable PCIe controller device through DTS/ACPI,
>>>>> that's doesn't matter.
>>>>
>>>> The Linux Image for arm64 systems built using:
>>>> arch/arm64/configs/defconfig
>>>> will not have support for the Cadence PCIe Controller and the PCIe 
>>>> J721e
>>>> driver, because these configs aren't enabled.
>>>>
>>>>>
>>>>>> @@ -209,6 +209,12 @@ CONFIG_NFC=m
>>>>>> ? CONFIG_NFC_NCI=m
>>>>>> ? CONFIG_NFC_S3FWRN5_I2C=m
>>>>>> ? CONFIG_PCI=y
>>>>>> +CONFIG_PCI_J721E=m
>>>>>> +CONFIG_PCI_J721E_HOST=m
>>>>>> +CONFIG_PCI_J721E_EP=m
>>>>>> +CONFIG_PCIE_CADENCE=m
>>>>>> +CONFIG_PCIE_CADENCE_HOST=m
>>>>>> +CONFIG_PCIE_CADENCE_EP=m
>>>>>
>>>>> The common Cadence configuration will be select if the glue layer's
>>>>> configuration is select according to Kconfig.
>>>>>
>>>>> Please do not set common configuration as module, some user may need
>>>>> it as build-in like dw's. Considering the situation, the rootfs is at
>>>>> NVMe.
>>>>
>>>> The common configuration at the moment is "DISABLED" i.e. no support 
>>>> for
>>>> the Cadence Controller at all. Which "user" are you referring to? This
>>>> series was introduced since having the drivers built-in was pushed 
>>>> back at:
>>>
>>> We are using Cadence controller, and prepare upstream radxa-o6 board
>>> whose rootfs is at PCIe NVMe.
>>>
>>
>> It doesn't matter. Only criteria AFAIK to build the driver as built-in in
>> defconfig is that it should be a depedency for console. For some time, 
>> storage
>> was also a dependency, but for sure PCIe is not.
>>
>> Moreover, CONFIG_BLK_DEV_NVME is built as a module in ARM64 defconfig. 
>> So it
>> doesn't matter if you build PCIe controller driver as a built-in or 
>> not. You
>> need to load the NVMe driver somehow.
>>
>> So please use initramfs.
>>
>>> You could build driver as module for TI glue layer, but don't force
>>> other vendors using module as well, see dwc as an example please.
>>>
>>
>> DWC is a bad example here. Only reason the DWC drivers are not 
>> loadable is due
>> to the in-built MSI controller implementation as irqchip. People tend 
>> to build
>> the irqchip controllers as always built-in for some known issues. Even 
>> then some
>> driver developers prefer to built them as loadable module but suppress 
>> unbind to
>> avoid rmmoding the module.
> Hi Mani,
> 
> I think the MSI RTL module provided by Synopsys PCIe controller IP is
> not a standard operation. The reason for this MSI module is probably to
> be used by some cpus that do not have ITS(LPI interrupt) designed. Or
> RISC-V SOC, etc. MSI is defined as an MSI/MSIX interrupt that starts
> with a direct write memory access.
> 
> There are also SOC vendors that do not use the built-in MSI RTL module.
> Instead, MSI/MSIX interrupts are transmitted directly to the GIC's ITS
> module via the GIC V3/V4 interface. For example, RK3588, they do not use
> the PCIe controller built-in MSI module. Some Qualcomm platforms also
> modify the PCIe controller's built-in MSI modules to connect each of
> them to 32 SPI interrupts to the GIC. I was under the impression that
> the SDM845 was designed that way. The only explanation is that SPI
> interrupts are faster than LPI interrupts without having to look up some
> tables.
> 
> So the dwc driver can also compile to ko?

Additional reason:

Often in SOC design, the RTL designer does not understand the dwc-driver 
behavior and causes some RTL bugs, and the software needs to workaround. 
  As a result, the dwc driver of build-in cannot be used, and the dwc 
driver needs to be modified, which will make it easier to compile the 
dwc driver to module.

Best regards,
Hans




From changyuanl at google.com  Wed Mar 19 18:55:35 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:35 -0700
Subject: [PATCH v5 00/16] kexec: introduce Kexec HandOver (KHO)
Message-ID: <20250320015551.2157511-1-changyuanl@google.com>

Hi,

This is a next version of Alexander Graf and Mike Rapoport's
"kexec: introduce Kexec HandOver (KHO)" series
(https://lore.kernel.org/all/20250206132754.2596694-1-rppt at kernel.org/),
with bitmaps for preserving folios and address ranges, new hashtable-based
KHO state tree API, and reduced blackout window with kexec_file_load.

The patches are also available in git:
https://github.com/googleprodkernel/linux-liveupdate/tree/kho/v5

v4 -> v5:
  - New: Preserve folios and address ranges in bitmaps [1]. Removed the
    `mem` property.
  - New: Hash table based API for manipulating the KHO state tree.
  - Change the concept of "active phase" to "finalization phase". KHO
    users can add/remove data into/from KHO DT anytime before the
    finalization phase.
  - Decouple kexec_file_load and KHO FDT creation. kexec_file_load can be
    done before KHO FDT is created.
  - Update the example usecase (reserve_mem) using the new KHO API,
    replace underscores with dashes in reserve-mem fdt generation.
  - Drop the YAMLs for now and add a brief description of KHO FDT before
    KHO schema is stable.
  - Move all sysfs interfaces to debugfs.
  - Fixed the memblock test reported in [2].
  - Incorporate fix for kho_locate_mem_hole() with !CONFIG_KEXEC_HANDOVER
    [3] into "kexec: Add KHO support to kexec file loads".

[1] https://lore.kernel.org/all/20250212152336.GA3848889 at nvidia.com/
[2] https://lore.kernel.org/all/20250217040448.56xejbvsr2a73h4c at master/
[3] https://lore.kernel.org/all/20250214125402.90709-1-sourabhjain at linux.ibm.com/

= Original cover letter =

Kexec today considers itself purely a boot loader: When we enter the new
kernel, any state the previous kernel left behind is irrelevant and the
new kernel reinitializes the system.

However, there are use cases where this mode of operation is not what we
actually want. In virtualization hosts for example, we want to use kexec
to update the host kernel while virtual machine memory stays untouched.
When we add device assignment to the mix, we also need to ensure that
IOMMU and VFIO states are untouched. If we add PCIe peer to peer DMA, we
need to do the same for the PCI subsystem. If we want to kexec while an
SEV-SNP enabled virtual machine is running, we need to preserve the VM
context pages and physical memory. See "pkernfs: Persisting guest memory
and kernel/device state safely across kexec" Linux Plumbers
Conference 2023 presentation for details:

  https://lpc.events/event/17/contributions/1485/

To start us on the journey to support all the use cases above, this patch
implements basic infrastructure to allow hand over of kernel state across
kexec (Kexec HandOver, aka KHO). As a really simple example target, we use
memblock's reserve_mem.
With this patch set applied, memory that was reserved using "reserve_mem"
command line options remains intact after kexec and it is guaranteed to
reside at the same physical address.

== Alternatives ==

There are alternative approaches to (parts of) the problems above:

  * Memory Pools [1] - preallocated persistent memory region + allocator
  * PRMEM [2] - resizable persistent memory regions with fixed metadata
                pointer on the kernel command line + allocator
  * Pkernfs [3] - preallocated file system for in-kernel data with fixed
                  address location on the kernel command line
  * PKRAM [4] - handover of user space pages using a fixed metadata page
                specified via command line

All of the approaches above fundamentally have the same problem: They
require the administrator to explicitly carve out a physical memory
location because they have no mechanism outside of the kernel command
line to pass data (including memory reservations) between kexec'ing
kernels.

KHO provides that base foundation. We will determine later whether we
still need any of the approaches above for fast bulk memory handover of for
example IOMMU page tables. But IMHO they would all be users of KHO, with
KHO providing the foundational primitive to pass metadata and bulk memory
reservations as well as provide easy versioning for data.

== Overview ==

We introduce a metadata file that the kernels pass between each other. How
they pass it is architecture specific. The file's format is a Flattened
Device Tree (fdt) which has a generator and parser already included in
Linux. KHO is enabled in the kernel command line by `kho=on`. Drivers can
add/remove data into/from KHO root state tree hash-table anytime. When the
hash-table is converted to FDT (by kernel automatically in the case of
kexec_file_load or by the userspace manually through debugfs kho/out/finalize),
the kernel invokes callbacks to every driver that supports KHO to serialize
its state. When the actual kexec happens, the fdt is part of the image
set that we boot into. In addition, we keep a "scratch regions" available
for kexec: A physically contiguous memory regions that is guaranteed to
not have any memory that KHO would preserve. The new kernel bootstraps
itself using the scratch regions and sets all handed over memory as in use.
When drivers initialize that support KHO, they introspect the fdt and
recover their state from it. This includes memory reservations, where the
driver can either discard or claim reservations.

== Limitations ==

Currently KHO is only implemented for file based kexec. The kernel
interfaces in the patch set are already in place to support user space
kexec as well, but it is still not implemented it yet inside kexec tools.

== How to Use ==

To use the code, please boot the kernel with the "kho=on" command line
parameter.
KHO will automatically create scratch regions. If you want to set the
scratch size explicitly you can use "kho_scratch=" command line parameter.
For instance, "kho_scratch=16M,512M,256M" will reserve a 16 MiB low
memory scratch area, a 512 MiB global scratch region, and 256 MiB
per NUMA node scratch regions on boot.

Make sure to have a reserved memory range requested with reserv_mem
command line option. Then you invoke file based "kexec -l",

  # kexec -l Image --initrd=initrd -s
  # kexec -e

The new kernel will boot up and contain the previous kernel's reserve_mem
contents at the same physical address as the first kernel.

Optionally, you can finalize the KHO FDT early by

  # echo 1 > /sys/kernel/debug/kho/out/finalize

which allows you to preview the FDT to be passed to the next kernel at
/sys/kernel/debug/kho/out/fdt.

== Changelog ==

v3 -> v4:
  - Major rework of scrach management. Rather than force scratch memory
    allocations only very early in boot now we rely on scratch for all
    memblock allocations.
  - Use simple example usecase (reserv_mem instead of ftrace)
  - merge all KHO functionality into a single kernel/kexec_handover.c file
  - rename CONFIG_KEXEC_KHO to CONFIG_KEXEC_HANDOVER

v2 -> v3:
  - Fix make dt_binding_check
  - Add descriptions for each object
  - s/trace_flags/trace-flags/
  - s/global_trace/global-trace/
  - Make all additionalProperties false
  - Change subject to reflect subsysten (dt-bindings)
  - Fix indentation
  - Remove superfluous examples
  - Convert to 64bit syntax
  - Move to kho directory
  - s/"global_trace"/"global-trace"/
  - s/"global_trace"/"global-trace"/
  - s/"trace_flags"/"trace-flags"/
  - Fix wording
  - Add Documentation to MAINTAINERS file
  - Remove kho reference on read error
  - Move handover_dt unmap up
  - s/reserve_scratch_mem/mark_phys_as_cma/
  - Remove ifdeffery
  - Remove superfluous comment

v1 -> v2:
  - Removed: tracing: Introduce names for ring buffers
  - Removed: tracing: Introduce names for events
  - New: kexec: Add config option for KHO
  - New: kexec: Add documentation for KHO
  - New: tracing: Initialize fields before registering
  - New: devicetree: Add bindings for ftrace KHO
  - test bot warning fixes
  - Change kconfig option to ARCH_SUPPORTS_KEXEC_KHO
  - s/kho_reserve_mem/kho_reserve_previous_mem/g
  - s/kho_reserve/kho_reserve_scratch/g
  - Remove / reduce ifdefs
  - Select crc32
  - Leave anything that requires a name in trace.c to keep buffers
    unnamed entities
  - Put events as array into a property, use fingerprint instead of
    names to identify them
  - Reduce footprint without CONFIG_FTRACE_KHO
  - s/kho_reserve_mem/kho_reserve_previous_mem/g
  - make kho_get_fdt() const
  - Add stubs for return_mem and claim_mem
  - make kho_get_fdt() const
  - Get events as array from a property, use fingerprint instead of
    names to identify events
  - Change kconfig option to ARCH_SUPPORTS_KEXEC_KHO
  - s/kho_reserve_mem/kho_reserve_previous_mem/g
  - s/kho_reserve/kho_reserve_scratch/g
  - Leave the node generation code that needs to know the name in
    trace.c so that ring buffers can stay anonymous
  - s/kho_reserve/kho_reserve_scratch/g
  - Move kho enums out of ifdef
  - Move from names to fdt offsets. That way, trace.c can find the trace
    array offset and then the ring buffer code only needs to read out
    its per-CPU data. That way it can stay oblivient to its name.
  - Make kho_get_fdt() const

Alexander Graf (9):
  memblock: Add support for scratch memory
  kexec: add Kexec HandOver (KHO) generation helpers
  kexec: add KHO parsing support
  kexec: add KHO support to kexec file loads
  kexec: add config option for KHO
  arm64: add KHO support
  x86: add KHO support
  memblock: add KHO support for reserve_mem
  Documentation: add documentation for KHO

Changyuan Lyu (1):
  hashtable: add macro HASHTABLE_INIT

Mike Rapoport (Microsoft) (5):
  mm/mm_init: rename init_reserved_page to init_deferred_page
  memblock: add MEMBLOCK_RSRV_KERN flag
  memblock: introduce memmap_init_kho_scratch()
  kexec: enable KHO support for memory preservation
  x86/setup: use memblock_reserve_kern for memory used by kernel

steven chen (1):
  kexec: define functions to map and unmap segments

 .../admin-guide/kernel-parameters.txt         |   25 +
 Documentation/kho/concepts.rst                |   70 +
 Documentation/kho/fdt.rst                     |   62 +
 Documentation/kho/index.rst                   |   14 +
 Documentation/kho/usage.rst                   |  118 ++
 Documentation/subsystem-apis.rst              |    1 +
 MAINTAINERS                                   |    3 +-
 arch/arm64/Kconfig                            |    3 +
 arch/x86/Kconfig                              |    3 +
 arch/x86/boot/compressed/kaslr.c              |   52 +-
 arch/x86/include/asm/setup.h                  |    4 +
 arch/x86/include/uapi/asm/setup_data.h        |   13 +-
 arch/x86/kernel/e820.c                        |   18 +
 arch/x86/kernel/kexec-bzimage64.c             |   36 +
 arch/x86/kernel/setup.c                       |   41 +-
 arch/x86/realmode/init.c                      |    2 +
 drivers/of/fdt.c                              |   33 +
 drivers/of/kexec.c                            |   37 +
 include/linux/hashtable.h                     |    7 +-
 include/linux/kexec.h                         |   12 +
 include/linux/kexec_handover.h                |  202 ++
 include/linux/memblock.h                      |   41 +-
 kernel/Kconfig.kexec                          |   15 +
 kernel/Makefile                               |    1 +
 kernel/kexec_core.c                           |   58 +
 kernel/kexec_file.c                           |   19 +
 kernel/kexec_handover.c                       | 1755 +++++++++++++++++
 kernel/kexec_internal.h                       |   18 +
 mm/Kconfig                                    |    4 +
 mm/internal.h                                 |    2 +
 mm/memblock.c                                 |  303 ++-
 mm/mm_init.c                                  |   19 +-
 tools/testing/memblock/tests/alloc_api.c      |   22 +-
 .../memblock/tests/alloc_helpers_api.c        |    4 +-
 tools/testing/memblock/tests/alloc_nid_api.c  |   20 +-
 35 files changed, 2988 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/kho/concepts.rst
 create mode 100644 Documentation/kho/fdt.rst
 create mode 100644 Documentation/kho/index.rst
 create mode 100644 Documentation/kho/usage.rst
 create mode 100644 include/linux/kexec_handover.h
 create mode 100644 kernel/kexec_handover.c


base-commit: a7f2e10ecd8f18b83951b0bab47ddaf48f93bf47
--
2.48.1.711.g2feabab25a-goog


From changyuanl at google.com  Wed Mar 19 18:55:36 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:36 -0700
Subject: [PATCH v5 01/16] kexec: define functions to map and unmap segments
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-2-changyuanl@google.com>

From: steven chen <chenste at linux.microsoft.com>

Currently, the mechanism to map and unmap segments to the kimage
structure is not available to the subsystems outside of kexec.  This
functionality is needed when IMA is allocating the memory segments
during kexec 'load' operation.  Implement functions to map and unmap
segments to kimage.

Implement kimage_map_segment() to enable mapping of IMA buffer source
pages to the kimage structure post kexec 'load'.  This function,
accepting a kimage pointer, an address, and a size, will gather the
source pages within the specified address range, create an array of page
pointers, and map these to a contiguous virtual address range.  The
function returns the start of this range if successful, or NULL if
unsuccessful.

Implement kimage_unmap_segment() for unmapping segments
using vunmap().

Signed-off-by: Tushar Sugandhi <tusharsu at linux.microsoft.com>
Signed-off-by: steven chen <chenste at linux.microsoft.com>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/kexec.h |  5 ++++
 kernel/kexec_core.c   | 54 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f0e9f8eda7a3..fad04f3bcf1d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -467,6 +467,8 @@ extern bool kexec_file_dbg_print;
 #define kexec_dprintk(fmt, arg...) \
         do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
 
+void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
+void kimage_unmap_segment(void *buffer);
 #else /* !CONFIG_KEXEC_CORE */
 struct pt_regs;
 struct task_struct;
@@ -474,6 +476,9 @@ static inline void __crash_kexec(struct pt_regs *regs) { }
 static inline void crash_kexec(struct pt_regs *regs) { }
 static inline int kexec_should_crash(struct task_struct *p) { return 0; }
 static inline int kexec_crash_loaded(void) { return 0; }
+static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
+{ return NULL; }
+static inline void kimage_unmap_segment(void *buffer) { }
 #define kexec_in_progress false
 #endif /* CONFIG_KEXEC_CORE */
 
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index c0bdc1686154..640d252306ea 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -867,6 +867,60 @@ int kimage_load_segment(struct kimage *image,
 	return result;
 }
 
+void *kimage_map_segment(struct kimage *image,
+			 unsigned long addr, unsigned long size)
+{
+	unsigned long eaddr = addr + size;
+	unsigned long src_page_addr, dest_page_addr;
+	unsigned int npages;
+	struct page **src_pages;
+	int i;
+	kimage_entry_t *ptr, entry;
+	void *vaddr = NULL;
+
+	/*
+	 * Collect the source pages and map them in a contiguous VA range.
+	 */
+	npages = PFN_UP(eaddr) - PFN_DOWN(addr);
+	src_pages = kvmalloc_array(npages, sizeof(*src_pages), GFP_KERNEL);
+	if (!src_pages) {
+		pr_err("Could not allocate source pages array for destination %lx.\n", addr);
+		return NULL;
+	}
+
+	i = 0;
+	for_each_kimage_entry(image, ptr, entry) {
+		if (entry & IND_DESTINATION) {
+			dest_page_addr = entry & PAGE_MASK;
+		} else if (entry & IND_SOURCE) {
+			if (dest_page_addr >= addr && dest_page_addr < eaddr) {
+				src_page_addr = entry & PAGE_MASK;
+				src_pages[i++] =
+					virt_to_page(__va(src_page_addr));
+				if (i == npages)
+					break;
+				dest_page_addr += PAGE_SIZE;
+			}
+		}
+	}
+
+	/* Sanity check. */
+	WARN_ON(i < npages);
+
+	vaddr = vmap(src_pages, npages, VM_MAP, PAGE_KERNEL);
+	kvfree(src_pages);
+
+	if (!vaddr)
+		pr_err("Could not map segment source pages for destination %lx.\n", addr);
+
+	return vaddr;
+}
+
+void kimage_unmap_segment(void *segment_buffer)
+{
+	vunmap(segment_buffer);
+}
+
 struct kexec_load_limit {
 	/* Mutex protects the limit count. */
 	struct mutex mutex;
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:37 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:37 -0700
Subject: [PATCH v5 02/16] mm/mm_init: rename init_reserved_page to init_deferred_page
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-3-changyuanl@google.com>

From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>

When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, init_reserved_page()
function performs initialization of a struct page that would have been
deferred normally.

Rename it to init_deferred_page() to better reflect what the function does.

Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
 mm/mm_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/mm_init.c b/mm/mm_init.c
index 2630cc30147e..c4b425125bad 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -705,7 +705,7 @@ defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
 	return false;
 }
 
-static void __meminit init_reserved_page(unsigned long pfn, int nid)
+static void __meminit init_deferred_page(unsigned long pfn, int nid)
 {
 	pg_data_t *pgdat;
 	int zid;
@@ -739,7 +739,7 @@ static inline bool defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
 	return false;
 }
 
-static inline void init_reserved_page(unsigned long pfn, int nid)
+static inline void init_deferred_page(unsigned long pfn, int nid)
 {
 }
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
@@ -760,7 +760,7 @@ void __meminit reserve_bootmem_region(phys_addr_t start,
 		if (pfn_valid(start_pfn)) {
 			struct page *page = pfn_to_page(start_pfn);
 
-			init_reserved_page(start_pfn, nid);
+			init_deferred_page(start_pfn, nid);
 
 			/*
 			 * no need for atomic set_bit because the struct
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:38 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:38 -0700
Subject: [PATCH v5 03/16] memblock: add MEMBLOCK_RSRV_KERN flag
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-4-changyuanl@google.com>

From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>

to denote areas that were reserved for kernel use either directly with
memblock_reserve_kern() or via memblock allocations.

Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/memblock.h                      | 19 ++++++++-
 mm/memblock.c                                 | 40 +++++++++++++++----
 tools/testing/memblock/tests/alloc_api.c      | 22 +++++-----
 .../memblock/tests/alloc_helpers_api.c        |  4 +-
 tools/testing/memblock/tests/alloc_nid_api.c  | 20 +++++-----
 5 files changed, 73 insertions(+), 32 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index e79eb6ac516f..1037fd7aabf4 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -42,6 +42,9 @@ extern unsigned long long max_possible_pfn;
  * kernel resource tree.
  * @MEMBLOCK_RSRV_NOINIT: memory region for which struct pages are
  * not initialized (only for reserved regions).
+ * @MEMBLOCK_RSRV_KERN: memory region that is reserved for kernel use,
+ * either explictitly with memblock_reserve_kern() or via memblock
+ * allocation APIs. All memblock allocations set this flag.
  */
 enum memblock_flags {
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
@@ -50,6 +53,7 @@ enum memblock_flags {
 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
+	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
 };
 
 /**
@@ -116,7 +120,19 @@ int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid,
 int memblock_add(phys_addr_t base, phys_addr_t size);
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_phys_free(phys_addr_t base, phys_addr_t size);
-int memblock_reserve(phys_addr_t base, phys_addr_t size);
+int __memblock_reserve(phys_addr_t base, phys_addr_t size, int nid,
+		       enum memblock_flags flags);
+
+static __always_inline int memblock_reserve(phys_addr_t base, phys_addr_t size)
+{
+	return __memblock_reserve(base, size, NUMA_NO_NODE, 0);
+}
+
+static __always_inline int memblock_reserve_kern(phys_addr_t base, phys_addr_t size)
+{
+	return __memblock_reserve(base, size, NUMA_NO_NODE, MEMBLOCK_RSRV_KERN);
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
 int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
 #endif
@@ -477,6 +493,7 @@ static inline __init_memblock bool memblock_bottom_up(void)
 
 phys_addr_t memblock_phys_mem_size(void);
 phys_addr_t memblock_reserved_size(void);
+phys_addr_t memblock_reserved_kern_size(phys_addr_t limit, int nid);
 unsigned long memblock_estimated_nr_free_pages(void);
 phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
diff --git a/mm/memblock.c b/mm/memblock.c
index 95af35fd1389..e704e3270b32 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -491,7 +491,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
 	 * needn't do it
 	 */
 	if (!use_slab)
-		BUG_ON(memblock_reserve(addr, new_alloc_size));
+		BUG_ON(memblock_reserve_kern(addr, new_alloc_size));
 
 	/* Update slab flag */
 	*in_slab = use_slab;
@@ -641,7 +641,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
 #ifdef CONFIG_NUMA
 			WARN_ON(nid != memblock_get_region_node(rgn));
 #endif
-			WARN_ON(flags != rgn->flags);
+			WARN_ON(flags != MEMBLOCK_NONE && flags != rgn->flags);
 			nr_new++;
 			if (insert) {
 				if (start_rgn == -1)
@@ -901,14 +901,15 @@ int __init_memblock memblock_phys_free(phys_addr_t base, phys_addr_t size)
 	return memblock_remove_range(&memblock.reserved, base, size);
 }
 
-int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
+int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,
+				       int nid, enum memblock_flags flags)
 {
 	phys_addr_t end = base + size - 1;
 
-	memblock_dbg("%s: [%pa-%pa] %pS\n", __func__,
-		     &base, &end, (void *)_RET_IP_);
+	memblock_dbg("%s: [%pa-%pa] nid=%d flags=%x %pS\n", __func__,
+		     &base, &end, nid, flags, (void *)_RET_IP_);
 
-	return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);
+	return memblock_add_range(&memblock.reserved, base, size, nid, flags);
 }
 
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
@@ -1459,14 +1460,14 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
 again:
 	found = memblock_find_in_range_node(size, align, start, end, nid,
 					    flags);
-	if (found && !memblock_reserve(found, size))
+	if (found && !__memblock_reserve(found, size, nid, MEMBLOCK_RSRV_KERN))
 		goto done;
 
 	if (numa_valid_node(nid) && !exact_nid) {
 		found = memblock_find_in_range_node(size, align, start,
 						    end, NUMA_NO_NODE,
 						    flags);
-		if (found && !memblock_reserve(found, size))
+		if (found && !memblock_reserve_kern(found, size))
 			goto done;
 	}
 
@@ -1751,6 +1752,28 @@ phys_addr_t __init_memblock memblock_reserved_size(void)
 	return memblock.reserved.total_size;
 }
 
+phys_addr_t __init_memblock memblock_reserved_kern_size(phys_addr_t limit, int nid)
+{
+	struct memblock_region *r;
+	phys_addr_t total = 0;
+
+	for_each_reserved_mem_region(r) {
+		phys_addr_t size = r->size;
+
+		if (r->base > limit)
+			break;
+
+		if (r->base + r->size > limit)
+			size = limit - r->base;
+
+		if (nid == memblock_get_region_node(r) || !numa_valid_node(nid))
+			if (r->flags & MEMBLOCK_RSRV_KERN)
+				total += size;
+	}
+
+	return total;
+}
+
 /**
  * memblock_estimated_nr_free_pages - return estimated number of free pages
  * from memblock point of view
@@ -2397,6 +2420,7 @@ static const char * const flagname[] = {
 	[ilog2(MEMBLOCK_NOMAP)] = "NOMAP",
 	[ilog2(MEMBLOCK_DRIVER_MANAGED)] = "DRV_MNG",
 	[ilog2(MEMBLOCK_RSRV_NOINIT)] = "RSV_NIT",
+	[ilog2(MEMBLOCK_RSRV_KERN)] = "RSV_KERN",
 };
 
 static int memblock_debug_show(struct seq_file *m, void *private)
diff --git a/tools/testing/memblock/tests/alloc_api.c b/tools/testing/memblock/tests/alloc_api.c
index 68f1a75cd72c..c55f67dd367d 100644
--- a/tools/testing/memblock/tests/alloc_api.c
+++ b/tools/testing/memblock/tests/alloc_api.c
@@ -134,7 +134,7 @@ static int alloc_top_down_before_check(void)
 	PREFIX_PUSH();
 	setup_memblock();
 
-	memblock_reserve(memblock_end_of_DRAM() - total_size, r1_size);
+	memblock_reserve_kern(memblock_end_of_DRAM() - total_size, r1_size);
 
 	allocated_ptr = run_memblock_alloc(r2_size, SMP_CACHE_BYTES);
 
@@ -182,7 +182,7 @@ static int alloc_top_down_after_check(void)
 
 	total_size = r1.size + r2_size;
 
-	memblock_reserve(r1.base, r1.size);
+	memblock_reserve_kern(r1.base, r1.size);
 
 	allocated_ptr = run_memblock_alloc(r2_size, SMP_CACHE_BYTES);
 
@@ -231,8 +231,8 @@ static int alloc_top_down_second_fit_check(void)
 
 	total_size = r1.size + r2.size + r3_size;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc(r3_size, SMP_CACHE_BYTES);
 
@@ -285,8 +285,8 @@ static int alloc_in_between_generic_check(void)
 
 	total_size = r1.size + r2.size + r3_size;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc(r3_size, SMP_CACHE_BYTES);
 
@@ -422,7 +422,7 @@ static int alloc_limited_space_generic_check(void)
 	setup_memblock();
 
 	/* Simulate almost-full memory */
-	memblock_reserve(memblock_start_of_DRAM(), reserved_size);
+	memblock_reserve_kern(memblock_start_of_DRAM(), reserved_size);
 
 	allocated_ptr = run_memblock_alloc(available_size, SMP_CACHE_BYTES);
 
@@ -608,7 +608,7 @@ static int alloc_bottom_up_before_check(void)
 	PREFIX_PUSH();
 	setup_memblock();
 
-	memblock_reserve(memblock_start_of_DRAM() + r1_size, r2_size);
+	memblock_reserve_kern(memblock_start_of_DRAM() + r1_size, r2_size);
 
 	allocated_ptr = run_memblock_alloc(r1_size, SMP_CACHE_BYTES);
 
@@ -655,7 +655,7 @@ static int alloc_bottom_up_after_check(void)
 
 	total_size = r1.size + r2_size;
 
-	memblock_reserve(r1.base, r1.size);
+	memblock_reserve_kern(r1.base, r1.size);
 
 	allocated_ptr = run_memblock_alloc(r2_size, SMP_CACHE_BYTES);
 
@@ -705,8 +705,8 @@ static int alloc_bottom_up_second_fit_check(void)
 
 	total_size = r1.size + r2.size + r3_size;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc(r3_size, SMP_CACHE_BYTES);
 
diff --git a/tools/testing/memblock/tests/alloc_helpers_api.c b/tools/testing/memblock/tests/alloc_helpers_api.c
index 3ef9486da8a0..e5362cfd2ff3 100644
--- a/tools/testing/memblock/tests/alloc_helpers_api.c
+++ b/tools/testing/memblock/tests/alloc_helpers_api.c
@@ -163,7 +163,7 @@ static int alloc_from_top_down_no_space_above_check(void)
 	min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;
 
 	/* No space above this address */
-	memblock_reserve(min_addr, r2_size);
+	memblock_reserve_kern(min_addr, r2_size);
 
 	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
 
@@ -199,7 +199,7 @@ static int alloc_from_top_down_min_addr_cap_check(void)
 	start_addr = (phys_addr_t)memblock_start_of_DRAM();
 	min_addr = start_addr - SMP_CACHE_BYTES * 3;
 
-	memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size);
+	memblock_reserve_kern(start_addr + r1_size, MEM_SIZE - r1_size);
 
 	allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
 
diff --git a/tools/testing/memblock/tests/alloc_nid_api.c b/tools/testing/memblock/tests/alloc_nid_api.c
index 49bb416d34ff..562e4701b0e0 100644
--- a/tools/testing/memblock/tests/alloc_nid_api.c
+++ b/tools/testing/memblock/tests/alloc_nid_api.c
@@ -324,7 +324,7 @@ static int alloc_nid_min_reserved_generic_check(void)
 	min_addr = max_addr - r2_size;
 	reserved_base = min_addr - r1_size;
 
-	memblock_reserve(reserved_base, r1_size);
+	memblock_reserve_kern(reserved_base, r1_size);
 
 	allocated_ptr = run_memblock_alloc_nid(r2_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
@@ -374,7 +374,7 @@ static int alloc_nid_max_reserved_generic_check(void)
 	max_addr = memblock_end_of_DRAM() - r1_size;
 	min_addr = max_addr - r2_size;
 
-	memblock_reserve(max_addr, r1_size);
+	memblock_reserve_kern(max_addr, r1_size);
 
 	allocated_ptr = run_memblock_alloc_nid(r2_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
@@ -436,8 +436,8 @@ static int alloc_nid_top_down_reserved_with_space_check(void)
 	min_addr = r2.base + r2.size;
 	max_addr = r1.base;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc_nid(r3_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
@@ -499,8 +499,8 @@ static int alloc_nid_reserved_full_merge_generic_check(void)
 	min_addr = r2.base + r2.size;
 	max_addr = r1.base;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc_nid(r3_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
@@ -563,8 +563,8 @@ static int alloc_nid_top_down_reserved_no_space_check(void)
 	min_addr = r2.base + r2.size;
 	max_addr = r1.base;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc_nid(r3_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
@@ -909,8 +909,8 @@ static int alloc_nid_bottom_up_reserved_with_space_check(void)
 	min_addr = r2.base + r2.size;
 	max_addr = r1.base;
 
-	memblock_reserve(r1.base, r1.size);
-	memblock_reserve(r2.base, r2.size);
+	memblock_reserve_kern(r1.base, r1.size);
+	memblock_reserve_kern(r2.base, r2.size);
 
 	allocated_ptr = run_memblock_alloc_nid(r3_size, SMP_CACHE_BYTES,
 					       min_addr, max_addr,
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:39 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:39 -0700
Subject: [PATCH v5 04/16] memblock: Add support for scratch memory
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-5-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

With KHO (Kexec HandOver), we need a way to ensure that the new kernel
does not allocate memory on top of any memory regions that the previous
kernel was handing over. But to know where those are, we need to include
them in the memblock.reserved array which may not be big enough to hold
all ranges that need to be persisted across kexec. To resize the array,
we need to allocate memory. That brings us into a catch 22 situation.

The solution to that is limit memblock allocations to the scratch regions:
safe regions to operate in the case when there is memory that should remain
intact across kexec.

KHO provides several "scratch regions" as part of its metadata. These
scratch regions are contiguous memory blocks that known not to contain any
memory that should be persisted across kexec. These regions should be large
enough to accommodate all memblock allocations done by the kexeced kernel.

We introduce a new memblock_set_scratch_only() function that allows KHO to
indicate that any memblock allocation must happen from the scratch regions.

Later, we may want to perform another KHO kexec. For that, we reuse the
same scratch regions. To ensure that no eventually handed over data gets
allocated inside a scratch region, we flip the semantics of the scratch
region with memblock_clear_scratch_only(): After that call, no allocations
may happen from scratch memblock regions. We will lift that restriction
in the next patch.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
 include/linux/memblock.h | 20 +++++++++++++
 mm/Kconfig               |  4 +++
 mm/memblock.c            | 61 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 1037fd7aabf4..a83738b7218b 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -45,6 +45,11 @@ extern unsigned long long max_possible_pfn;
  * @MEMBLOCK_RSRV_KERN: memory region that is reserved for kernel use,
  * either explictitly with memblock_reserve_kern() or via memblock
  * allocation APIs. All memblock allocations set this flag.
+ * @MEMBLOCK_KHO_SCRATCH: memory region that kexec can pass to the next
+ * kernel in handover mode. During early boot, we do not know about all
+ * memory reservations yet, so we get scratch memory from the previous
+ * kernel that we know is good to use. It is the only memory that
+ * allocations may happen from in this phase.
  */
 enum memblock_flags {
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
@@ -54,6 +59,7 @@ enum memblock_flags {
 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
 	MEMBLOCK_RSRV_NOINIT	= 0x10,	/* don't initialize struct pages */
 	MEMBLOCK_RSRV_KERN	= 0x20,	/* memory reserved for kernel use */
+	MEMBLOCK_KHO_SCRATCH	= 0x40,	/* scratch memory for kexec handover */
 };
 
 /**
@@ -148,6 +154,8 @@ int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
 int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
 int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
 int memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t size);
+int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size);
+int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size);
 
 void memblock_free_all(void);
 void memblock_free(void *ptr, size_t size);
@@ -292,6 +300,11 @@ static inline bool memblock_is_driver_managed(struct memblock_region *m)
 	return m->flags & MEMBLOCK_DRIVER_MANAGED;
 }
 
+static inline bool memblock_is_kho_scratch(struct memblock_region *m)
+{
+	return m->flags & MEMBLOCK_KHO_SCRATCH;
+}
+
 int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
 			    unsigned long  *end_pfn);
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
@@ -620,5 +633,12 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end) { }
 static inline void memtest_report_meminfo(struct seq_file *m) { }
 #endif
 
+#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
+void memblock_set_kho_scratch_only(void);
+void memblock_clear_kho_scratch_only(void);
+#else
+static inline void memblock_set_kho_scratch_only(void) { }
+static inline void memblock_clear_kho_scratch_only(void) { }
+#endif
 
 #endif /* _LINUX_MEMBLOCK_H */
diff --git a/mm/Kconfig b/mm/Kconfig
index 1b501db06417..550bbafe5c0b 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -506,6 +506,10 @@ config HAVE_GUP_FAST
 	depends on MMU
 	bool
 
+# Enable memblock support for scratch memory which is needed for kexec handover
+config MEMBLOCK_KHO_SCRATCH
+	bool
+
 # Don't discard allocated memory used to track "memory" and "reserved" memblocks
 # after early boot, so it can still be used to test for validity of memory.
 # Also, memblocks are updated with memory hot(un)plug.
diff --git a/mm/memblock.c b/mm/memblock.c
index e704e3270b32..c0f7da7dff47 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -106,6 +106,13 @@ unsigned long min_low_pfn;
 unsigned long max_pfn;
 unsigned long long max_possible_pfn;
 
+#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
+/* When set to true, only allocate from MEMBLOCK_KHO_SCRATCH ranges */
+static bool kho_scratch_only;
+#else
+#define kho_scratch_only false
+#endif
+
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_MEMORY_REGIONS] __initdata_memblock;
 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
@@ -165,6 +172,10 @@ bool __init_memblock memblock_has_mirror(void)
 
 static enum memblock_flags __init_memblock choose_memblock_flags(void)
 {
+	/* skip non-scratch memory for kho early boot allocations */
+	if (kho_scratch_only)
+		return MEMBLOCK_KHO_SCRATCH;
+
 	return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
 }
 
@@ -924,6 +935,18 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
 }
 #endif
 
+#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
+__init_memblock void memblock_set_kho_scratch_only(void)
+{
+	kho_scratch_only = true;
+}
+
+__init_memblock void memblock_clear_kho_scratch_only(void)
+{
+	kho_scratch_only = false;
+}
+#endif
+
 /**
  * memblock_setclr_flag - set or clear flag for a memory region
  * @type: memblock type to set/clear flag for
@@ -1049,6 +1072,36 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
 				    MEMBLOCK_RSRV_NOINIT);
 }
 
+/**
+ * memblock_mark_kho_scratch - Mark a memory region as MEMBLOCK_KHO_SCRATCH.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Only memory regions marked with %MEMBLOCK_KHO_SCRATCH will be considered
+ * for allocations during early boot with kexec handover.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(&memblock.memory, base, size, 1,
+				    MEMBLOCK_KHO_SCRATCH);
+}
+
+/**
+ * memblock_clear_kho_scratch - Clear MEMBLOCK_KHO_SCRATCH flag for a
+ * specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(&memblock.memory, base, size, 0,
+				    MEMBLOCK_KHO_SCRATCH);
+}
+
 static bool should_skip_region(struct memblock_type *type,
 			       struct memblock_region *m,
 			       int nid, int flags)
@@ -1080,6 +1133,13 @@ static bool should_skip_region(struct memblock_type *type,
 	if (!(flags & MEMBLOCK_DRIVER_MANAGED) && memblock_is_driver_managed(m))
 		return true;
 
+	/*
+	 * In early alloc during kexec handover, we can only consider
+	 * MEMBLOCK_KHO_SCRATCH regions for the allocations
+	 */
+	if ((flags & MEMBLOCK_KHO_SCRATCH) && !memblock_is_kho_scratch(m))
+		return true;
+
 	return false;
 }
 
@@ -2421,6 +2481,7 @@ static const char * const flagname[] = {
 	[ilog2(MEMBLOCK_DRIVER_MANAGED)] = "DRV_MNG",
 	[ilog2(MEMBLOCK_RSRV_NOINIT)] = "RSV_NIT",
 	[ilog2(MEMBLOCK_RSRV_KERN)] = "RSV_KERN",
+	[ilog2(MEMBLOCK_KHO_SCRATCH)] = "KHO_SCRATCH",
 };
 
 static int memblock_debug_show(struct seq_file *m, void *private)
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:40 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:40 -0700
Subject: [PATCH v5 05/16] memblock: introduce memmap_init_kho_scratch()
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-6-changyuanl@google.com>

From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>

With deferred initialization of struct page it will be necessary to
initialize memory map for KHO scratch regions early.

Add memmap_init_kho_scratch() method that will allow such initialization
in upcoming patches.

Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
 include/linux/memblock.h |  2 ++
 mm/internal.h            |  2 ++
 mm/memblock.c            | 22 ++++++++++++++++++++++
 mm/mm_init.c             | 11 ++++++++---
 4 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index a83738b7218b..497e2c1364a6 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -636,9 +636,11 @@ static inline void memtest_report_meminfo(struct seq_file *m) { }
 #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
 void memblock_set_kho_scratch_only(void);
 void memblock_clear_kho_scratch_only(void);
+void memmap_init_kho_scratch_pages(void);
 #else
 static inline void memblock_set_kho_scratch_only(void) { }
 static inline void memblock_clear_kho_scratch_only(void) { }
+static inline void memmap_init_kho_scratch_pages(void) {}
 #endif
 
 #endif /* _LINUX_MEMBLOCK_H */
diff --git a/mm/internal.h b/mm/internal.h
index 20b3535935a3..8e45a2ae961a 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1053,6 +1053,8 @@ DECLARE_STATIC_KEY_TRUE(deferred_pages);
 bool __init deferred_grow_zone(struct zone *zone, unsigned int order);
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
+void init_deferred_page(unsigned long pfn, int nid);
+
 enum mminit_level {
 	MMINIT_WARNING,
 	MMINIT_VERIFY,
diff --git a/mm/memblock.c b/mm/memblock.c
index c0f7da7dff47..d5d406a5160a 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -945,6 +945,28 @@ __init_memblock void memblock_clear_kho_scratch_only(void)
 {
 	kho_scratch_only = false;
 }
+
+void __init_memblock memmap_init_kho_scratch_pages(void)
+{
+	phys_addr_t start, end;
+	unsigned long pfn;
+	int nid;
+	u64 i;
+
+	if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT))
+		return;
+
+	/*
+	 * Initialize struct pages for free scratch memory.
+	 * The struct pages for reserved scratch memory will be set up in
+	 * reserve_bootmem_region()
+	 */
+	__for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE,
+			     MEMBLOCK_KHO_SCRATCH, &start, &end, &nid) {
+		for (pfn = PFN_UP(start); pfn < PFN_DOWN(end); pfn++)
+			init_deferred_page(pfn, nid);
+	}
+}
 #endif
 
 /**
diff --git a/mm/mm_init.c b/mm/mm_init.c
index c4b425125bad..04441c258b05 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -705,7 +705,7 @@ defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
 	return false;
 }
 
-static void __meminit init_deferred_page(unsigned long pfn, int nid)
+static void __meminit __init_deferred_page(unsigned long pfn, int nid)
 {
 	pg_data_t *pgdat;
 	int zid;
@@ -739,11 +739,16 @@ static inline bool defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
 	return false;
 }
 
-static inline void init_deferred_page(unsigned long pfn, int nid)
+static inline void __init_deferred_page(unsigned long pfn, int nid)
 {
 }
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
+void __meminit init_deferred_page(unsigned long pfn, int nid)
+{
+	__init_deferred_page(pfn, nid);
+}
+
 /*
  * Initialised pages do not have PageReserved set. This function is
  * called for each range allocated by the bootmem allocator and
@@ -760,7 +765,7 @@ void __meminit reserve_bootmem_region(phys_addr_t start,
 		if (pfn_valid(start_pfn)) {
 			struct page *page = pfn_to_page(start_pfn);
 
-			init_deferred_page(start_pfn, nid);
+			__init_deferred_page(start_pfn, nid);
 
 			/*
 			 * no need for atomic set_bit because the struct
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:41 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:41 -0700
Subject: [PATCH v5 06/16] hashtable: add macro HASHTABLE_INIT
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-7-changyuanl@google.com>

Similar to HLIST_HEAD_INIT, HASHTABLE_INIT allows a hashtable embedded
in another structure to be initialized at compile time.

Example,

struct tree_node {
    DECLARE_HASHTABLE(properties, 4);
    DECLARE_HASHTABLE(sub_nodes, 4);
};

static struct tree_node root_node = {
    .properties = HASHTABLE_INIT(4),
    .sub_nodes = HASHTABLE_INIT(4),
};

Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/hashtable.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
index f6c666730b8c..27e07a436e2a 100644
--- a/include/linux/hashtable.h
+++ b/include/linux/hashtable.h
@@ -13,13 +13,14 @@
 #include <linux/hash.h>
 #include <linux/rculist.h>
 
+#define HASHTABLE_INIT(bits) { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
 #define DEFINE_HASHTABLE(name, bits)						\
-	struct hlist_head name[1 << (bits)] =					\
-			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+	struct hlist_head name[1 << (bits)] =	HASHTABLE_INIT(bits)	\
 
 #define DEFINE_READ_MOSTLY_HASHTABLE(name, bits)				\
 	struct hlist_head name[1 << (bits)] __read_mostly =			\
-			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+		HASHTABLE_INIT(bits)
 
 #define DECLARE_HASHTABLE(name, bits)                                   	\
 	struct hlist_head name[1 << (bits)]
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:42 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:42 -0700
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation helpers
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-8-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

Add the core infrastructure to generate Kexec HandOver metadata. Kexec
HandOver is a mechanism that allows Linux to preserve state - arbitrary
properties as well as memory locations - across kexec.

It does so using 2 concepts:

  1) State Tree - Every KHO kexec carries a state tree that describes the
     state of the system. The state tree is represented as hash-tables.
     Device drivers can add/remove their data into/from the state tree at
     system runtime. On kexec, the tree is converted to FDT (flattened
     device tree).

  2) Scratch Regions - CMA regions that we allocate in the first kernel.
     CMA gives us the guarantee that no handover pages land in those
     regions, because handover pages must be at a static physical memory
     location. We use these regions as the place to load future kexec
     images so that they won't collide with any handover data.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Pratyush Yadav <ptyadav at amazon.de>
Signed-off-by: Pratyush Yadav <ptyadav at amazon.de>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 MAINTAINERS                    |   2 +-
 include/linux/kexec_handover.h | 109 +++++
 kernel/Makefile                |   1 +
 kernel/kexec_handover.c        | 865 +++++++++++++++++++++++++++++++++
 mm/mm_init.c                   |   8 +
 5 files changed, 984 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/kexec_handover.h
 create mode 100644 kernel/kexec_handover.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 12852355bd66..a000a277ccf7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12828,7 +12828,7 @@ F:	include/linux/kernfs.h
 KEXEC
 L:	kexec at lists.infradead.org
 W:	http://kernel.org/pub/linux/utils/kernel/kexec/
-F:	include/linux/kexec.h
+F:	include/linux/kexec*.h
 F:	include/uapi/linux/kexec.h
 F:	kernel/kexec*
 
diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
new file mode 100644
index 000000000000..9cd9ad31e2d1
--- /dev/null
+++ b/include/linux/kexec_handover.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_KEXEC_HANDOVER_H
+#define LINUX_KEXEC_HANDOVER_H
+
+#include <linux/types.h>
+#include <linux/hashtable.h>
+#include <linux/notifier.h>
+
+struct kho_scratch {
+	phys_addr_t addr;
+	phys_addr_t size;
+};
+
+/* KHO Notifier index */
+enum kho_event {
+	KEXEC_KHO_FINALIZE = 0,
+	KEXEC_KHO_UNFREEZE = 1,
+};
+
+#define KHO_HASHTABLE_BITS 3
+#define KHO_NODE_INIT                                        \
+	{                                                    \
+		.props = HASHTABLE_INIT(KHO_HASHTABLE_BITS), \
+		.nodes = HASHTABLE_INIT(KHO_HASHTABLE_BITS), \
+	}
+
+struct kho_node {
+	struct hlist_node hlist;
+
+	const char *name;
+	DECLARE_HASHTABLE(props, KHO_HASHTABLE_BITS);
+	DECLARE_HASHTABLE(nodes, KHO_HASHTABLE_BITS);
+
+	struct list_head list;
+	bool visited;
+};
+
+#ifdef CONFIG_KEXEC_HANDOVER
+bool kho_is_enabled(void);
+void kho_init_node(struct kho_node *node);
+int kho_add_node(struct kho_node *parent, const char *name,
+		 struct kho_node *child);
+struct kho_node *kho_remove_node(struct kho_node *parent, const char *name);
+int kho_add_prop(struct kho_node *node, const char *key, const void *val,
+		 u32 size);
+void *kho_remove_prop(struct kho_node *node, const char *key, u32 *size);
+int kho_add_string_prop(struct kho_node *node, const char *key,
+			const char *val);
+
+int register_kho_notifier(struct notifier_block *nb);
+int unregister_kho_notifier(struct notifier_block *nb);
+
+void kho_memory_init(void);
+#else
+static inline bool kho_is_enabled(void)
+{
+	return false;
+}
+
+static inline void kho_init_node(struct kho_node *node)
+{
+}
+
+static inline int kho_add_node(struct kho_node *parent, const char *name,
+			       struct kho_node *child)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline struct kho_node *kho_remove_node(struct kho_node *parent,
+					       const char *name)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int kho_add_prop(struct kho_node *node, const char *key,
+			       const void *val, u32 size)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void *kho_remove_prop(struct kho_node *node, const char *key,
+				    u32 *size)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int kho_add_string_prop(struct kho_node *node, const char *key,
+				      const char *val)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int register_kho_notifier(struct notifier_block *nb)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int unregister_kho_notifier(struct notifier_block *nb)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void kho_memory_init(void)
+{
+}
+#endif /* CONFIG_KEXEC_HANDOVER */
+
+#endif /* LINUX_KEXEC_HANDOVER_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 87866b037fbe..cef5377c25cd 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_core.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
 obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o
+obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CGROUPS) += cgroup/
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
new file mode 100644
index 000000000000..df0d9debbb64
--- /dev/null
+++ b/kernel/kexec_handover.c
@@ -0,0 +1,865 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kexec_handover.c - kexec handover metadata processing
+ * Copyright (C) 2023 Alexander Graf <graf at amazon.com>
+ * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt at kernel.org>
+ * Copyright (C) 2024 Google LLC
+ */
+
+#define pr_fmt(fmt) "KHO: " fmt
+
+#include <linux/cma.h>
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/debugfs.h>
+#include <linux/memblock.h>
+#include <linux/notifier.h>
+#include <linux/kexec_handover.h>
+#include <linux/page-isolation.h>
+#include <linux/rwsem.h>
+#include <linux/xxhash.h>
+/*
+ * KHO is tightly coupled with mm init and needs access to some of mm
+ * internal APIs.
+ */
+#include "../mm/internal.h"
+#include "kexec_internal.h"
+
+static bool kho_enable __ro_after_init;
+
+bool kho_is_enabled(void)
+{
+	return kho_enable;
+}
+EXPORT_SYMBOL_GPL(kho_is_enabled);
+
+static int __init kho_parse_enable(char *p)
+{
+	return kstrtobool(p, &kho_enable);
+}
+early_param("kho", kho_parse_enable);
+
+/*
+ * With KHO enabled, memory can become fragmented because KHO regions may
+ * be anywhere in physical address space. The scratch regions give us a
+ * safe zones that we will never see KHO allocations from. This is where we
+ * can later safely load our new kexec images into and then use the scratch
+ * area for early allocations that happen before page allocator is
+ * initialized.
+ */
+static struct kho_scratch *kho_scratch;
+static unsigned int kho_scratch_cnt;
+
+static struct dentry *debugfs_root;
+
+struct kho_out {
+	struct blocking_notifier_head chain_head;
+
+	struct debugfs_blob_wrapper fdt_wrapper;
+	struct dentry *fdt_file;
+	struct dentry *dir;
+
+	struct rw_semaphore tree_lock;
+	struct kho_node root;
+
+	void *fdt;
+	u64 fdt_max;
+};
+
+static struct kho_out kho_out = {
+	.chain_head = BLOCKING_NOTIFIER_INIT(kho_out.chain_head),
+	.tree_lock = __RWSEM_INITIALIZER(kho_out.tree_lock),
+	.root = KHO_NODE_INIT,
+	.fdt_max = 10 * SZ_1M,
+};
+
+int register_kho_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&kho_out.chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_kho_notifier);
+
+int unregister_kho_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&kho_out.chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_kho_notifier);
+
+/* Helper functions for KHO state tree */
+
+struct kho_prop {
+	struct hlist_node hlist;
+
+	const char *key;
+	const void *val;
+	u32 size;
+};
+
+static unsigned long strhash(const char *s)
+{
+	return xxhash(s, strlen(s), 1120);
+}
+
+void kho_init_node(struct kho_node *node)
+{
+	hash_init(node->props);
+	hash_init(node->nodes);
+}
+EXPORT_SYMBOL_GPL(kho_init_node);
+
+/**
+ * kho_add_node - add a child node to a parent node.
+ * @parent: parent node to add to.
+ * @name: name of the child node.
+ * @child: child node to be added to @parent with @name.
+ *
+ * If @parent is NULL, @child is added to KHO state tree root node.
+ *
+ * @child must be a valid pointer through KHO FDT finalization.
+ * @name is duplicated and thus can have a short lifetime.
+ *
+ * Callers must use their own locking if there are concurrent accesses to
+ * @parent or @child.
+ *
+ * Return: 0 on success, 1 if @child is already in @parent with @name, or
+ *   - -EOPNOTSUPP: KHO is not enabled in the kernel command line,
+ *   - -ENOMEM: failed to duplicate @name,
+ *   - -EBUSY: KHO state tree has been converted to FDT,
+ *   - -EEXIST: another node of the same name has been added to the parent.
+ */
+int kho_add_node(struct kho_node *parent, const char *name,
+		 struct kho_node *child)
+{
+	unsigned long name_hash;
+	int ret = 0;
+	struct kho_node *node;
+	char *child_name;
+
+	if (!kho_enable)
+		return -EOPNOTSUPP;
+
+	if (!parent)
+		parent = &kho_out.root;
+
+	child_name = kstrdup(name, GFP_KERNEL);
+	if (!child_name)
+		return -ENOMEM;
+
+	name_hash = strhash(child_name);
+
+	if (parent == &kho_out.root)
+		down_write(&kho_out.tree_lock);
+	else
+		down_read(&kho_out.tree_lock);
+
+	if (kho_out.fdt) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	hash_for_each_possible(parent->nodes, node, hlist, name_hash) {
+		if (!strcmp(node->name, child_name)) {
+			ret = node == child ? 1 : -EEXIST;
+			break;
+		}
+	}
+
+	if (ret == 0) {
+		child->name = child_name;
+		hash_add(parent->nodes, &child->hlist, name_hash);
+	}
+
+out:
+	if (parent == &kho_out.root)
+		up_write(&kho_out.tree_lock);
+	else
+		up_read(&kho_out.tree_lock);
+
+	if (ret)
+		kfree(child_name);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kho_add_node);
+
+/**
+ * kho_remove_node - remove a child node from a parent node.
+ * @parent: parent node to look up for.
+ * @name: name of the child node.
+ *
+ * If @parent is NULL, KHO state tree root node is looked up.
+ *
+ * Callers must use their own locking if there are concurrent accesses to
+ * @parent or @child.
+ *
+ * Return: the pointer to the child node on success, or an error pointer,
+ *   - -EOPNOTSUPP: KHO is not enabled in the kernel command line,
+ *   - -ENOENT: no node named @name is found.
+ *   - -EBUSY: KHO state tree has been converted to FDT.
+ */
+struct kho_node *kho_remove_node(struct kho_node *parent, const char *name)
+{
+	struct kho_node *child, *ret = ERR_PTR(-ENOENT);
+	unsigned long name_hash;
+
+	if (!kho_enable)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	if (!parent)
+		parent = &kho_out.root;
+
+	name_hash = strhash(name);
+
+	if (parent == &kho_out.root)
+		down_write(&kho_out.tree_lock);
+	else
+		down_read(&kho_out.tree_lock);
+
+	if (kho_out.fdt) {
+		ret = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
+	hash_for_each_possible(parent->nodes, child, hlist, name_hash) {
+		if (!strcmp(child->name, name)) {
+			ret = child;
+			break;
+		}
+	}
+
+	if (!IS_ERR(ret)) {
+		hash_del(&ret->hlist);
+		kfree(ret->name);
+		ret->name = NULL;
+	}
+
+out:
+	if (parent == &kho_out.root)
+		up_write(&kho_out.tree_lock);
+	else
+		up_read(&kho_out.tree_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kho_remove_node);
+
+/**
+ * kho_add_prop - add a property to a node.
+ * @node: KHO node to add the property to.
+ * @key: key of the property.
+ * @val: pointer to the property value.
+ * @size: size of the property value in bytes.
+ *
+ * @val and @key must be valid pointers through KHO FDT finalization.
+ * Generally @key is a string literal with static lifetime.
+ *
+ * Callers must use their own locking if there are concurrent accesses to @node.
+ *
+ * Return: 0 on success, 1 if the value is already added with @key, or
+ *   - -ENOMEM: failed to allocate memory,
+ *   - -EBUSY: KHO state tree has been converted to FDT,
+ *   - -EEXIST: another property of the same key exists.
+ */
+int kho_add_prop(struct kho_node *node, const char *key, const void *val,
+		 u32 size)
+{
+	unsigned long key_hash;
+	int ret = 0;
+	struct kho_prop *prop, *p;
+
+	key_hash = strhash(key);
+	prop = kmalloc(sizeof(*prop), GFP_KERNEL);
+	if (!prop)
+		return -ENOMEM;
+
+	prop->key = key;
+	prop->val = val;
+	prop->size = size;
+
+	down_read(&kho_out.tree_lock);
+	if (kho_out.fdt) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	hash_for_each_possible(node->props, p, hlist, key_hash) {
+		if (!strcmp(p->key, key)) {
+			ret = (p->val == val && p->size == size) ? 1 : -EEXIST;
+			break;
+		}
+	}
+
+	if (!ret)
+		hash_add(node->props, &prop->hlist, key_hash);
+
+out:
+	up_read(&kho_out.tree_lock);
+
+	if (ret)
+		kfree(prop);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kho_add_prop);
+
+/**
+ * kho_add_string_prop - add a string property to a node.
+ *
+ * See kho_add_prop() for details.
+ */
+int kho_add_string_prop(struct kho_node *node, const char *key, const char *val)
+{
+	return kho_add_prop(node, key, val, strlen(val) + 1);
+}
+EXPORT_SYMBOL_GPL(kho_add_string_prop);
+
+/**
+ * kho_remove_prop - remove a property from a node.
+ * @node: KHO node to remove the property from.
+ * @key: key of the property.
+ * @size: if non-NULL, the property size is stored in it on success.
+ *
+ * Callers must use their own locking if there are concurrent accesses to @node.
+ *
+ * Return: the pointer to the property value, or
+ *   - -EBUSY: KHO state tree has been converted to FDT,
+ *   - -ENOENT: no property with @key is found.
+ */
+void *kho_remove_prop(struct kho_node *node, const char *key, u32 *size)
+{
+	struct kho_prop *p, *prop = NULL;
+	unsigned long key_hash;
+	void *ret = ERR_PTR(-ENOENT);
+
+	key_hash = strhash(key);
+
+	down_read(&kho_out.tree_lock);
+
+	if (kho_out.fdt) {
+		ret = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
+	hash_for_each_possible(node->props, p, hlist, key_hash) {
+		if (!strcmp(p->key, key)) {
+			prop = p;
+			break;
+		}
+	}
+
+	if (prop) {
+		ret = (void *)prop->val;
+		if (size)
+			*size = prop->size;
+		hash_del(&prop->hlist);
+		kfree(prop);
+	}
+
+out:
+	up_read(&kho_out.tree_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kho_remove_prop);
+
+static int kho_out_update_debugfs_fdt(void)
+{
+	int err = 0;
+
+	if (kho_out.fdt) {
+		kho_out.fdt_wrapper.data = kho_out.fdt;
+		kho_out.fdt_wrapper.size = fdt_totalsize(kho_out.fdt);
+		kho_out.fdt_file = debugfs_create_blob("fdt", 0400, kho_out.dir,
+						       &kho_out.fdt_wrapper);
+		if (IS_ERR(kho_out.fdt_file))
+			err = -ENOENT;
+	} else {
+		debugfs_remove(kho_out.fdt_file);
+	}
+
+	return err;
+}
+
+static int kho_unfreeze(void)
+{
+	int err;
+	void *fdt;
+
+	down_write(&kho_out.tree_lock);
+	fdt = kho_out.fdt;
+	kho_out.fdt = NULL;
+	up_write(&kho_out.tree_lock);
+
+	if (fdt)
+		kvfree(fdt);
+
+	err = blocking_notifier_call_chain(&kho_out.chain_head,
+					   KEXEC_KHO_UNFREEZE, NULL);
+	err = notifier_to_errno(err);
+
+	return notifier_to_errno(err);
+}
+
+static int kho_flatten_tree(void *fdt)
+{
+	int iter, err = 0;
+	struct kho_node *node, *sub_node;
+	struct list_head *ele;
+	struct kho_prop *prop;
+	LIST_HEAD(stack);
+
+	kho_out.root.visited = false;
+	list_add(&kho_out.root.list, &stack);
+
+	for (ele = stack.next; !list_is_head(ele, &stack); ele = stack.next) {
+		node = list_entry(ele, struct kho_node, list);
+
+		if (node->visited) {
+			err = fdt_end_node(fdt);
+			if (err)
+				return err;
+			list_del_init(ele);
+			continue;
+		}
+
+		err = fdt_begin_node(fdt, node->name);
+		if (err)
+			return err;
+
+		hash_for_each(node->props, iter, prop, hlist) {
+			err = fdt_property(fdt, prop->key, prop->val,
+					   prop->size);
+			if (err)
+				return err;
+		}
+
+		hash_for_each(node->nodes, iter, sub_node, hlist) {
+			sub_node->visited = false;
+			list_add(&sub_node->list, &stack);
+		}
+
+		node->visited = true;
+	}
+
+	return 0;
+}
+
+static int kho_convert_tree(void *buffer, int size)
+{
+	void *fdt = buffer;
+	int err = 0;
+
+	err = fdt_create(fdt, size);
+	if (err)
+		goto out;
+
+	err = fdt_finish_reservemap(fdt);
+	if (err)
+		goto out;
+
+	err = kho_flatten_tree(fdt);
+	if (err)
+		goto out;
+
+	err = fdt_finish(fdt);
+	if (err)
+		goto out;
+
+	err = fdt_check_header(fdt);
+	if (err)
+		goto out;
+
+out:
+	if (err) {
+		pr_err("failed to flatten state tree: %d\n", err);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int kho_finalize(void)
+{
+	int err = 0;
+	void *fdt;
+
+	fdt = kvmalloc(kho_out.fdt_max, GFP_KERNEL);
+	if (!fdt)
+		return -ENOMEM;
+
+	err = blocking_notifier_call_chain(&kho_out.chain_head,
+					   KEXEC_KHO_FINALIZE, NULL);
+	err = notifier_to_errno(err);
+	if (err)
+		goto unfreeze;
+
+	down_write(&kho_out.tree_lock);
+	kho_out.fdt = fdt;
+	up_write(&kho_out.tree_lock);
+
+	err = kho_convert_tree(fdt, kho_out.fdt_max);
+
+unfreeze:
+	if (err) {
+		int abort_err;
+
+		pr_err("Failed to convert KHO state tree: %d\n", err);
+
+		abort_err = kho_unfreeze();
+		if (abort_err)
+			pr_err("Failed to abort KHO state tree: %d\n",
+			       abort_err);
+	}
+
+	return err;
+}
+
+/* Handling for debug/kho/out */
+static int kho_out_finalize_get(void *data, u64 *val)
+{
+	*val = !!kho_out.fdt;
+
+	return 0;
+}
+
+static int kho_out_finalize_set(void *data, u64 _val)
+{
+	int ret = 0;
+	bool val = !!_val;
+
+	if (!kexec_trylock())
+		return -EBUSY;
+
+	if (val == !!kho_out.fdt) {
+		if (kho_out.fdt)
+			ret = -EEXIST;
+		else
+			ret = -ENOENT;
+		goto unlock;
+	}
+
+	if (val)
+		ret = kho_finalize();
+	else
+		ret = kho_unfreeze();
+
+	if (ret)
+		goto unlock;
+
+	ret = kho_out_update_debugfs_fdt();
+
+unlock:
+	kexec_unlock();
+	return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get,
+			 kho_out_finalize_set, "%llu\n");
+
+static int kho_out_fdt_max_get(void *data, u64 *val)
+{
+	*val = kho_out.fdt_max;
+
+	return 0;
+}
+
+static int kho_out_fdt_max_set(void *data, u64 val)
+{
+	int ret = 0;
+
+	if (!kexec_trylock()) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	/* FDT already exists, it's too late to change fdt_max */
+	if (kho_out.fdt) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	kho_out.fdt_max = val;
+
+unlock:
+	kexec_unlock();
+	return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_fdt_max, kho_out_fdt_max_get,
+			 kho_out_fdt_max_set, "%llu\n");
+
+static int scratch_phys_show(struct seq_file *m, void *v)
+{
+	for (int i = 0; i < kho_scratch_cnt; i++)
+		seq_printf(m, "0x%llx\n", kho_scratch[i].addr);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(scratch_phys);
+
+static int scratch_len_show(struct seq_file *m, void *v)
+{
+	for (int i = 0; i < kho_scratch_cnt; i++)
+		seq_printf(m, "0x%llx\n", kho_scratch[i].size);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(scratch_len);
+
+static __init int kho_out_debugfs_init(void)
+{
+	struct dentry *dir, *f;
+
+	dir = debugfs_create_dir("out", debugfs_root);
+	if (IS_ERR(dir))
+		return -ENOMEM;
+
+	f = debugfs_create_file("scratch_phys", 0400, dir, NULL,
+				&scratch_phys_fops);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	f = debugfs_create_file("scratch_len", 0400, dir, NULL,
+				&scratch_len_fops);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	f = debugfs_create_file("fdt_max", 0600, dir, NULL,
+				&fops_kho_out_fdt_max);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	f = debugfs_create_file("finalize", 0600, dir, NULL,
+				&fops_kho_out_finalize);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	kho_out.dir = dir;
+	return 0;
+
+err_rmdir:
+	debugfs_remove_recursive(dir);
+	return -ENOENT;
+}
+
+static __init int kho_init(void)
+{
+	int err;
+
+	if (!kho_enable)
+		return 0;
+
+	kho_out.root.name = "";
+	err = kho_add_string_prop(&kho_out.root, "compatible", "kho-v1");
+	if (err)
+		goto err_free_scratch;
+
+	debugfs_root = debugfs_create_dir("kho", NULL);
+	if (IS_ERR(debugfs_root)) {
+		err = -ENOENT;
+		goto err_free_scratch;
+	}
+
+	err = kho_out_debugfs_init();
+	if (err)
+		goto err_free_scratch;
+
+	for (int i = 0; i < kho_scratch_cnt; i++) {
+		unsigned long base_pfn = PHYS_PFN(kho_scratch[i].addr);
+		unsigned long count = kho_scratch[i].size >> PAGE_SHIFT;
+		unsigned long pfn;
+
+		for (pfn = base_pfn; pfn < base_pfn + count;
+		     pfn += pageblock_nr_pages)
+			init_cma_reserved_pageblock(pfn_to_page(pfn));
+	}
+
+	return 0;
+
+err_free_scratch:
+	for (int i = 0; i < kho_scratch_cnt; i++) {
+		void *start = __va(kho_scratch[i].addr);
+		void *end = start + kho_scratch[i].size;
+
+		free_reserved_area(start, end, -1, "");
+	}
+	kho_enable = false;
+	return err;
+}
+late_initcall(kho_init);
+
+/*
+ * The scratch areas are scaled by default as percent of memory allocated from
+ * memblock. A user can override the scale with command line parameter:
+ *
+ * kho_scratch=N%
+ *
+ * It is also possible to explicitly define size for a lowmem, a global and
+ * per-node scratch areas:
+ *
+ * kho_scratch=l[KMG],n[KMG],m[KMG]
+ *
+ * The explicit size definition takes precedence over scale definition.
+ */
+static unsigned int scratch_scale __initdata = 200;
+static phys_addr_t scratch_size_global __initdata;
+static phys_addr_t scratch_size_pernode __initdata;
+static phys_addr_t scratch_size_lowmem __initdata;
+
+static int __init kho_parse_scratch_size(char *p)
+{
+	unsigned long size, size_pernode, size_global;
+	char *endptr, *oldp = p;
+
+	if (!p)
+		return -EINVAL;
+
+	size = simple_strtoul(p, &endptr, 0);
+	if (*endptr == '%') {
+		scratch_scale = size;
+		pr_notice("scratch scale is %d percent\n", scratch_scale);
+	} else {
+		size = memparse(p, &p);
+		if (!size || p == oldp)
+			return -EINVAL;
+
+		if (*p != ',')
+			return -EINVAL;
+
+		oldp = p;
+		size_global = memparse(p + 1, &p);
+		if (!size_global || p == oldp)
+			return -EINVAL;
+
+		if (*p != ',')
+			return -EINVAL;
+
+		size_pernode = memparse(p + 1, &p);
+		if (!size_pernode)
+			return -EINVAL;
+
+		scratch_size_lowmem = size;
+		scratch_size_global = size_global;
+		scratch_size_pernode = size_pernode;
+		scratch_scale = 0;
+
+		pr_notice("scratch areas: lowmem: %lluMB global: %lluMB pernode: %lldMB\n",
+			  (u64)(scratch_size_lowmem >> 20),
+			  (u64)(scratch_size_global >> 20),
+			  (u64)(scratch_size_pernode >> 20));
+	}
+
+	return 0;
+}
+early_param("kho_scratch", kho_parse_scratch_size);
+
+static void __init scratch_size_update(void)
+{
+	phys_addr_t size;
+
+	if (!scratch_scale)
+		return;
+
+	size = memblock_reserved_kern_size(ARCH_LOW_ADDRESS_LIMIT,
+					   NUMA_NO_NODE);
+	size = size * scratch_scale / 100;
+	scratch_size_lowmem = round_up(size, CMA_MIN_ALIGNMENT_BYTES);
+
+	size = memblock_reserved_kern_size(MEMBLOCK_ALLOC_ANYWHERE,
+					   NUMA_NO_NODE);
+	size = size * scratch_scale / 100 - scratch_size_lowmem;
+	scratch_size_global = round_up(size, CMA_MIN_ALIGNMENT_BYTES);
+}
+
+static phys_addr_t __init scratch_size_node(int nid)
+{
+	phys_addr_t size;
+
+	if (scratch_scale) {
+		size = memblock_reserved_kern_size(MEMBLOCK_ALLOC_ANYWHERE,
+						   nid);
+		size = size * scratch_scale / 100;
+	} else {
+		size = scratch_size_pernode;
+	}
+
+	return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
+}
+
+/**
+ * kho_reserve_scratch - Reserve a contiguous chunk of memory for kexec
+ *
+ * With KHO we can preserve arbitrary pages in the system. To ensure we still
+ * have a large contiguous region of memory when we search the physical address
+ * space for target memory, let's make sure we always have a large CMA region
+ * active. This CMA region will only be used for movable pages which are not a
+ * problem for us during KHO because we can just move them somewhere else.
+ */
+static void __init kho_reserve_scratch(void)
+{
+	phys_addr_t addr, size;
+	int nid, i = 0;
+
+	if (!kho_enable)
+		return;
+
+	scratch_size_update();
+
+	/* FIXME: deal with node hot-plug/remove */
+	kho_scratch_cnt = num_online_nodes() + 2;
+	size = kho_scratch_cnt * sizeof(*kho_scratch);
+	kho_scratch = memblock_alloc(size, PAGE_SIZE);
+	if (!kho_scratch)
+		goto err_disable_kho;
+
+	/*
+	 * reserve scratch area in low memory for lowmem allocations in the
+	 * next kernel
+	 */
+	size = scratch_size_lowmem;
+	addr = memblock_phys_alloc_range(size, CMA_MIN_ALIGNMENT_BYTES, 0,
+					 ARCH_LOW_ADDRESS_LIMIT);
+	if (!addr)
+		goto err_free_scratch_desc;
+
+	kho_scratch[i].addr = addr;
+	kho_scratch[i].size = size;
+	i++;
+
+	/* reserve large contiguous area for allocations without nid */
+	size = scratch_size_global;
+	addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES);
+	if (!addr)
+		goto err_free_scratch_areas;
+
+	kho_scratch[i].addr = addr;
+	kho_scratch[i].size = size;
+	i++;
+
+	for_each_online_node(nid) {
+		size = scratch_size_node(nid);
+		addr = memblock_alloc_range_nid(size, CMA_MIN_ALIGNMENT_BYTES,
+						0, MEMBLOCK_ALLOC_ACCESSIBLE,
+						nid, true);
+		if (!addr)
+			goto err_free_scratch_areas;
+
+		kho_scratch[i].addr = addr;
+		kho_scratch[i].size = size;
+		i++;
+	}
+
+	return;
+
+err_free_scratch_areas:
+	for (i--; i >= 0; i--)
+		memblock_phys_free(kho_scratch[i].addr, kho_scratch[i].size);
+err_free_scratch_desc:
+	memblock_free(kho_scratch, kho_scratch_cnt * sizeof(*kho_scratch));
+err_disable_kho:
+	kho_enable = false;
+}
+
+void __init kho_memory_init(void)
+{
+	kho_reserve_scratch();
+}
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 04441c258b05..757659b7a26b 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -30,6 +30,7 @@
 #include <linux/crash_dump.h>
 #include <linux/execmem.h>
 #include <linux/vmstat.h>
+#include <linux/kexec_handover.h>
 #include "internal.h"
 #include "slab.h"
 #include "shuffle.h"
@@ -2661,6 +2662,13 @@ void __init mm_core_init(void)
 	report_meminit();
 	kmsan_init_shadow();
 	stack_depot_early_init();
+
+	/*
+	 * KHO memory setup must happen while memblock is still active, but
+	 * as close as possible to buddy initialization
+	 */
+	kho_memory_init();
+
 	mem_init();
 	kmem_cache_init();
 	/*
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:43 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:43 -0700
Subject: [PATCH v5 08/16] kexec: add KHO parsing support
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-9-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

When we have a KHO kexec, we get an FDT blob and scratch region to
populate the state of the system. Provide helper functions that allow
architecture code to easily handle memory reservations based on them and
give device drivers visibility into the KHO FDT and memory reservations
so they can recover their own state.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/kexec_handover.h |  48 ++++++
 kernel/kexec_handover.c        | 302 ++++++++++++++++++++++++++++++++-
 mm/memblock.c                  |   1 +
 3 files changed, 350 insertions(+), 1 deletion(-)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 9cd9ad31e2d1..c665ff6cd728 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -35,6 +35,10 @@ struct kho_node {
 	bool visited;
 };
 
+struct kho_in_node {
+	int offset;
+};
+
 #ifdef CONFIG_KEXEC_HANDOVER
 bool kho_is_enabled(void);
 void kho_init_node(struct kho_node *node);
@@ -51,6 +55,19 @@ int register_kho_notifier(struct notifier_block *nb);
 int unregister_kho_notifier(struct notifier_block *nb);
 
 void kho_memory_init(void);
+
+void kho_populate(phys_addr_t handover_fdt_phys, phys_addr_t scratch_phys,
+		  u64 scratch_len);
+
+int kho_get_node(const struct kho_in_node *parent, const char *name,
+		 struct kho_in_node *child);
+int kho_get_nodes(const struct kho_in_node *parent,
+		  int (*func)(const char *, const struct kho_in_node *, void *),
+		  void *data);
+const void *kho_get_prop(const struct kho_in_node *node, const char *key,
+			 u32 *size);
+int kho_node_check_compatible(const struct kho_in_node *node,
+			      const char *compatible);
 #else
 static inline bool kho_is_enabled(void)
 {
@@ -104,6 +121,37 @@ static inline int unregister_kho_notifier(struct notifier_block *nb)
 static inline void kho_memory_init(void)
 {
 }
+
+static inline void kho_populate(phys_addr_t handover_fdt_phys,
+				phys_addr_t scratch_phys, u64 scratch_len)
+{
+}
+
+static inline int kho_get_node(const struct kho_in_node *parent,
+			       const char *name, struct kho_in_node *child)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int kho_get_nodes(const struct kho_in_node *parent,
+				int (*func)(const char *,
+					    const struct kho_in_node *, void *),
+				void *data)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline const void *kho_get_prop(const struct kho_in_node *node,
+				       const char *key, u32 *size)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int kho_node_check_compatible(const struct kho_in_node *node,
+					    const char *compatible)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_KEXEC_HANDOVER */
 
 #endif /* LINUX_KEXEC_HANDOVER_H */
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index df0d9debbb64..6ebad2f023f9 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -73,6 +73,20 @@ static struct kho_out kho_out = {
 	.fdt_max = 10 * SZ_1M,
 };
 
+struct kho_in {
+	struct debugfs_blob_wrapper fdt_wrapper;
+	struct dentry *dir;
+	phys_addr_t kho_scratch_phys;
+	phys_addr_t fdt_phys;
+};
+
+static struct kho_in kho_in;
+
+static const void *kho_get_fdt(void)
+{
+	return kho_in.fdt_phys ? phys_to_virt(kho_in.fdt_phys) : NULL;
+}
+
 int register_kho_notifier(struct notifier_block *nb)
 {
 	return blocking_notifier_chain_register(&kho_out.chain_head, nb);
@@ -85,6 +99,144 @@ int unregister_kho_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(unregister_kho_notifier);
 
+/**
+ * kho_get_node - retrieve a node saved in KHO FDT.
+ * @parent: the parent node to look up for.
+ * @name: the name of the node to look for.
+ * @child: if a node named @name is found under @parent, it is stored in @child.
+ *
+ * If @parent is NULL, this function looks up for @name under KHO root node.
+ *
+ * Return: 0 on success, and @child is populated, error code on failure.
+ */
+int kho_get_node(const struct kho_in_node *parent, const char *name,
+		 struct kho_in_node *child)
+{
+	int parent_offset = 0;
+	int offset = 0;
+	const void *fdt = kho_get_fdt();
+
+	if (!fdt)
+		return -ENOENT;
+
+	if (!child)
+		return -EINVAL;
+
+	if (parent)
+		parent_offset = parent->offset;
+
+	offset = fdt_subnode_offset(fdt, parent_offset, name);
+	if (offset < 0)
+		return -ENOENT;
+
+	child->offset = offset;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kho_get_node);
+
+/**
+ * kho_get_nodes - iterate over all direct child nodes.
+ * @parent: the parent node to look for child nodes.
+ * @func: a function pointer to be called on each child node.
+ * @data: auxiliary data to be passed to @func.
+ *
+ * For every direct child node of @parent, @func is called with the child node
+ * name, the child node (a struct kho_in_node *), and @data.
+ *
+ * If @parent is NULL, this function iterates over the child nodes of the KHO
+ * root node.
+ *
+ * Return: 0 on success, error code on failure.
+ */
+int kho_get_nodes(const struct kho_in_node *parent,
+		  int (*func)(const char *, const struct kho_in_node *, void *),
+		  void *data)
+{
+	int parent_offset = 0;
+	struct kho_in_node child;
+	const char *name;
+	int ret = 0;
+	const void *fdt = kho_get_fdt();
+
+	if (!fdt)
+		return -ENOENT;
+
+	if (parent)
+		parent_offset = parent->offset;
+
+	fdt_for_each_subnode(child.offset, fdt, parent_offset) {
+		if (child.offset < 0)
+			return -EINVAL;
+
+		name = fdt_get_name(fdt, child.offset, NULL);
+
+		if (!name)
+			return -EINVAL;
+
+		ret = func(name, &child, data);
+
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kho_get_nodes);
+
+/**
+ * kho_get_prop - retrieve the property data stored in the KHO tree.
+ * @node: the node to look up for.
+ * @key: the key of the property.
+ * @size: a pointer to store the size of the data in bytes.
+ *
+ * Return: pointer to the data, and data size is stored in @size, or NULL on
+ * failure.
+ */
+const void *kho_get_prop(const struct kho_in_node *node, const char *key,
+			 u32 *size)
+{
+	int offset = 0;
+	u32 s;
+	const void *fdt = kho_get_fdt();
+
+	if (!fdt)
+		return NULL;
+
+	if (node)
+		offset = node->offset;
+
+	if (!size)
+		size = &s;
+
+	return fdt_getprop(fdt, offset, key, size);
+}
+EXPORT_SYMBOL_GPL(kho_get_prop);
+
+/**
+ * kho_node_check_compatible - check a node's compatible property.
+ * @node: the node to check.
+ * @compatible: the compatible stirng.
+ *
+ * Wrapper of fdt_node_check_compatible().
+ *
+ * Return: 0 if @compatible is in the node's "compatible" list, or
+ * error code on failure.
+ */
+int kho_node_check_compatible(const struct kho_in_node *node,
+			      const char *compatible)
+{
+	int result = 0;
+	const void *fdt = kho_get_fdt();
+
+	if (!fdt)
+		return -ENOENT;
+
+	result = fdt_node_check_compatible(fdt, node->offset, compatible);
+
+	return result ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(kho_node_check_compatible);
+
 /* Helper functions for KHO state tree */
 
 struct kho_prop {
@@ -605,6 +757,32 @@ static int scratch_len_show(struct seq_file *m, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(scratch_len);
 
+/* Handling for debugfs/kho/in */
+static __init int kho_in_debugfs_init(const void *fdt)
+{
+	struct dentry *file;
+	int err;
+
+	kho_in.dir = debugfs_create_dir("in", debugfs_root);
+	if (IS_ERR(kho_in.dir))
+		return PTR_ERR(kho_in.dir);
+
+	kho_in.fdt_wrapper.size = fdt_totalsize(fdt);
+	kho_in.fdt_wrapper.data = (void *)fdt;
+	file = debugfs_create_blob("fdt", 0400, kho_in.dir,
+				   &kho_in.fdt_wrapper);
+	if (IS_ERR(file)) {
+		err = PTR_ERR(file);
+		goto err_rmdir;
+	}
+
+	return 0;
+
+err_rmdir:
+	debugfs_remove(kho_in.dir);
+	return err;
+}
+
 static __init int kho_out_debugfs_init(void)
 {
 	struct dentry *dir, *f;
@@ -644,6 +822,7 @@ static __init int kho_out_debugfs_init(void)
 static __init int kho_init(void)
 {
 	int err;
+	const void *fdt = kho_get_fdt();
 
 	if (!kho_enable)
 		return 0;
@@ -663,6 +842,21 @@ static __init int kho_init(void)
 	if (err)
 		goto err_free_scratch;
 
+	if (fdt) {
+		err = kho_in_debugfs_init(fdt);
+		/*
+		 * Failure to create /sys/kernel/debug/kho/in does not prevent
+		 * reviving state from KHO and setting up KHO for the next
+		 * kexec.
+		 */
+		if (err)
+			pr_err("failed exposing handover FDT in debugfs\n");
+
+		kho_scratch = __va(kho_in.kho_scratch_phys);
+
+		return 0;
+	}
+
 	for (int i = 0; i < kho_scratch_cnt; i++) {
 		unsigned long base_pfn = PHYS_PFN(kho_scratch[i].addr);
 		unsigned long count = kho_scratch[i].size >> PAGE_SHIFT;
@@ -859,7 +1053,113 @@ static void __init kho_reserve_scratch(void)
 	kho_enable = false;
 }
 
+static void __init kho_release_scratch(void)
+{
+	phys_addr_t start, end;
+	u64 i;
+
+	memmap_init_kho_scratch_pages();
+
+	/*
+	 * Mark scratch mem as CMA before we return it. That way we
+	 * ensure that no kernel allocations happen on it. That means
+	 * we can reuse it as scratch memory again later.
+	 */
+	__for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE,
+			     MEMBLOCK_KHO_SCRATCH, &start, &end, NULL) {
+		ulong start_pfn = pageblock_start_pfn(PFN_DOWN(start));
+		ulong end_pfn = pageblock_align(PFN_UP(end));
+		ulong pfn;
+
+		for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages)
+			set_pageblock_migratetype(pfn_to_page(pfn),
+						  MIGRATE_CMA);
+	}
+}
+
 void __init kho_memory_init(void)
 {
-	kho_reserve_scratch();
+	if (!kho_get_fdt())
+		kho_reserve_scratch();
+	else
+		kho_release_scratch();
+}
+
+void __init kho_populate(phys_addr_t handover_fdt_phys,
+			 phys_addr_t scratch_phys, u64 scratch_len)
+{
+	void *handover_fdt;
+	struct kho_scratch *scratch;
+	u32 fdt_size = 0;
+
+	/* Determine the real size of the FDT */
+	handover_fdt =
+		early_memremap(handover_fdt_phys, sizeof(struct fdt_header));
+	if (!handover_fdt) {
+		pr_warn("setup: failed to memremap kexec FDT (0x%llx)\n",
+			handover_fdt_phys);
+		return;
+	}
+
+	if (fdt_check_header(handover_fdt)) {
+		pr_warn("setup: kexec handover FDT is invalid (0x%llx)\n",
+			handover_fdt_phys);
+		early_memunmap(handover_fdt, sizeof(struct fdt_header));
+		return;
+	}
+
+	fdt_size = fdt_totalsize(handover_fdt);
+	kho_in.fdt_phys = handover_fdt_phys;
+
+	early_memunmap(handover_fdt, sizeof(struct fdt_header));
+
+	/* Reserve the DT so we can still access it in late boot */
+	memblock_reserve(handover_fdt_phys, fdt_size);
+
+	kho_in.kho_scratch_phys = scratch_phys;
+	kho_scratch_cnt = scratch_len / sizeof(*kho_scratch);
+	scratch = early_memremap(scratch_phys, scratch_len);
+	if (!scratch) {
+		pr_warn("setup: failed to memremap kexec scratch (0x%llx)\n",
+			scratch_phys);
+		return;
+	}
+
+	/*
+	 * We pass a safe contiguous blocks of memory to use for early boot
+	 * purporses from the previous kernel so that we can resize the
+	 * memblock array as needed.
+	 */
+	for (int i = 0; i < kho_scratch_cnt; i++) {
+		struct kho_scratch *area = &scratch[i];
+		u64 size = area->size;
+
+		memblock_add(area->addr, size);
+
+		if (WARN_ON(memblock_mark_kho_scratch(area->addr, size))) {
+			pr_err("Kexec failed to mark the scratch region. Disabling KHO revival.");
+			kho_in.fdt_phys = 0;
+			scratch = NULL;
+			break;
+		}
+		pr_debug("Marked 0x%pa+0x%pa as scratch", &area->addr, &size);
+	}
+
+	early_memunmap(scratch, scratch_len);
+
+	if (!scratch)
+		return;
+
+	memblock_reserve(scratch_phys, scratch_len);
+
+	/*
+	 * Now that we have a viable region of scratch memory, let's tell
+	 * the memblocks allocator to only use that for any allocations.
+	 * That way we ensure that nothing scribbles over in use data while
+	 * we initialize the page tables which we will need to ingest all
+	 * memory reservations from the previous kernel.
+	 */
+	memblock_set_kho_scratch_only();
+
+	pr_info("setup: Found kexec handover data. Will skip init for some devices\n");
 }
diff --git a/mm/memblock.c b/mm/memblock.c
index d5d406a5160a..d28abf3def1c 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2374,6 +2374,7 @@ void __init memblock_free_all(void)
 	free_unused_memmap();
 	reset_all_zones_managed_pages();
 
+	memblock_clear_kho_scratch_only();
 	pages = free_low_memory_core_early();
 	totalram_pages_add(pages);
 }
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:44 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:44 -0700
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory preservation
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-10-changyuanl@google.com>

From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>

Introduce APIs allowing KHO users to preserve memory across kexec and
get access to that memory after boot of the kexeced kernel

kho_preserve_folio() - record a folio to be preserved over kexec
kho_restore_folio() - recreates the folio from the preserved memory
kho_preserve_phys() - record physically contiguous range to be
preserved over kexec.
kho_restore_phys() - recreates order-0 pages corresponding to the
preserved physical range

The memory preservations are tracked by two levels of xarrays to manage
chunks of per-order 512 byte bitmaps. For instance the entire 1G order
of a 1TB x86 system would fit inside a single 512 byte bitmap. For
order 0 allocations each bitmap will cover 16M of address space. Thus,
for 16G of memory at most 512K of bitmap memory will be needed for order 0.

At serialization time all bitmaps are recorded in a linked list of pages
for the next kernel to process and the physical address of the list is
recorded in KHO FDT.

The next kernel then processes that list, reserves the memory ranges and
later, when a user requests a folio or a physical range, KHO restores
corresponding memory map entries.

Suggested-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/kexec_handover.h |  38 +++
 kernel/kexec_handover.c        | 486 ++++++++++++++++++++++++++++++++-
 2 files changed, 522 insertions(+), 2 deletions(-)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index c665ff6cd728..d52a7b500f4c 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/hashtable.h>
 #include <linux/notifier.h>
+#include <linux/mm_types.h>
 
 struct kho_scratch {
 	phys_addr_t addr;
@@ -54,6 +55,13 @@ int kho_add_string_prop(struct kho_node *node, const char *key,
 int register_kho_notifier(struct notifier_block *nb);
 int unregister_kho_notifier(struct notifier_block *nb);
 
+int kho_preserve_folio(struct folio *folio);
+int kho_unpreserve_folio(struct folio *folio);
+int kho_preserve_phys(phys_addr_t phys, size_t size);
+int kho_unpreserve_phys(phys_addr_t phys, size_t size);
+struct folio *kho_restore_folio(phys_addr_t phys);
+void *kho_restore_phys(phys_addr_t phys, size_t size);
+
 void kho_memory_init(void);
 
 void kho_populate(phys_addr_t handover_fdt_phys, phys_addr_t scratch_phys,
@@ -118,6 +126,36 @@ static inline int unregister_kho_notifier(struct notifier_block *nb)
 	return -EOPNOTSUPP;
 }
 
+static inline int kho_preserve_folio(struct folio *folio)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int kho_unpreserve_folio(struct folio *folio)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int kho_preserve_phys(phys_addr_t phys, size_t size)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int kho_unpreserve_phys(phys_addr_t phys, size_t size)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline struct folio *kho_restore_folio(phys_addr_t phys)
+{
+	return NULL;
+}
+
+static inline void *kho_restore_phys(phys_addr_t phys, size_t size)
+{
+	return NULL;
+}
+
 static inline void kho_memory_init(void)
 {
 }
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index 6ebad2f023f9..592563c21369 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -62,6 +62,13 @@ struct kho_out {
 	struct rw_semaphore tree_lock;
 	struct kho_node root;
 
+	/**
+	 * Physical address of the first struct khoser_mem_chunk containing
+	 * serialized data from struct kho_mem_track.
+	 */
+	phys_addr_t first_chunk_phys;
+	struct kho_node preserved_memory;
+
 	void *fdt;
 	u64 fdt_max;
 };
@@ -70,6 +77,7 @@ static struct kho_out kho_out = {
 	.chain_head = BLOCKING_NOTIFIER_INIT(kho_out.chain_head),
 	.tree_lock = __RWSEM_INITIALIZER(kho_out.tree_lock),
 	.root = KHO_NODE_INIT,
+	.preserved_memory = KHO_NODE_INIT,
 	.fdt_max = 10 * SZ_1M,
 };
 
@@ -237,6 +245,461 @@ int kho_node_check_compatible(const struct kho_in_node *node,
 }
 EXPORT_SYMBOL_GPL(kho_node_check_compatible);
 
+/*
+ * Keep track of memory that is to be preserved across KHO.
+ *
+ * The serializing side uses two levels of xarrays to manage chunks of per-order
+ * 512 byte bitmaps. For instance the entire 1G order of a 1TB system would fit
+ * inside a single 512 byte bitmap. For order 0 allocations each bitmap will
+ * cover 16M of address space. Thus, for 16G of memory at most 512K
+ * of bitmap memory will be needed for order 0.
+ *
+ * This approach is fully incremental, as the serialization progresses folios
+ * can continue be aggregated to the tracker. The final step, immediately prior
+ * to kexec would serialize the xarray information into a linked list for the
+ * successor kernel to parse.
+ */
+
+#define PRESERVE_BITS (512 * 8)
+
+struct kho_mem_phys_bits {
+	DECLARE_BITMAP(preserve, PRESERVE_BITS);
+};
+
+struct kho_mem_phys {
+	/*
+	 * Points to kho_mem_phys_bits, a sparse bitmap array. Each bit is sized
+	 * to order.
+	 */
+	struct xarray phys_bits;
+};
+
+struct kho_mem_track {
+	/* Points to kho_mem_phys, each order gets its own bitmap tree */
+	struct xarray orders;
+};
+
+static struct kho_mem_track kho_mem_track;
+
+static void *xa_load_or_alloc(struct xarray *xa, unsigned long index, size_t sz)
+{
+	void *elm, *res;
+
+	elm = xa_load(xa, index);
+	if (elm)
+		return elm;
+
+	elm = kzalloc(sz, GFP_KERNEL);
+	if (!elm)
+		return ERR_PTR(-ENOMEM);
+
+	res = xa_cmpxchg(xa, index, NULL, elm, GFP_KERNEL);
+	if (xa_is_err(res))
+		res = ERR_PTR(xa_err(res));
+
+	if (res) {
+		kfree(elm);
+		return res;
+	}
+
+	return elm;
+}
+
+static void __kho_unpreserve(struct kho_mem_track *tracker, unsigned long pfn,
+			     unsigned int order)
+{
+	struct kho_mem_phys_bits *bits;
+	struct kho_mem_phys *physxa;
+	unsigned long pfn_hi = pfn >> order;
+
+	physxa = xa_load(&tracker->orders, order);
+	if (!physxa)
+		return;
+
+	bits = xa_load(&physxa->phys_bits, pfn_hi / PRESERVE_BITS);
+	if (!bits)
+		return;
+
+	clear_bit(pfn_hi % PRESERVE_BITS, bits->preserve);
+}
+
+static int __kho_preserve(struct kho_mem_track *tracker, unsigned long pfn,
+			  unsigned int order)
+{
+	struct kho_mem_phys_bits *bits;
+	struct kho_mem_phys *physxa;
+	unsigned long pfn_hi = pfn >> order;
+
+	might_sleep();
+
+	physxa = xa_load_or_alloc(&tracker->orders, order, sizeof(*physxa));
+	if (IS_ERR(physxa))
+		return PTR_ERR(physxa);
+
+	bits = xa_load_or_alloc(&physxa->phys_bits, pfn_hi / PRESERVE_BITS,
+				sizeof(*bits));
+	if (IS_ERR(bits))
+		return PTR_ERR(bits);
+
+	set_bit(pfn_hi % PRESERVE_BITS, bits->preserve);
+
+	return 0;
+}
+
+/**
+ * kho_preserve_folio - preserve a folio across KHO.
+ * @folio: folio to preserve
+ *
+ * Records that the entire folio is preserved across KHO. The order
+ * will be preserved as well.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_preserve_folio(struct folio *folio)
+{
+	unsigned long pfn = folio_pfn(folio);
+	unsigned int order = folio_order(folio);
+	int err;
+
+	if (!kho_enable)
+		return -EOPNOTSUPP;
+
+	down_read(&kho_out.tree_lock);
+	if (kho_out.fdt) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	err = __kho_preserve(&kho_mem_track, pfn, order);
+
+unlock:
+	up_read(&kho_out.tree_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kho_preserve_folio);
+
+/**
+ * kho_unpreserve_folio - unpreserve a folio
+ * @folio: folio to unpreserve
+ *
+ * Remove the record of a folio previously preserved by kho_preserve_folio().
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_unpreserve_folio(struct folio *folio)
+{
+	unsigned long pfn = folio_pfn(folio);
+	unsigned int order = folio_order(folio);
+	int err = 0;
+
+	down_read(&kho_out.tree_lock);
+	if (kho_out.fdt) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	__kho_unpreserve(&kho_mem_track, pfn, order);
+
+unlock:
+	up_read(&kho_out.tree_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_folio);
+
+/**
+ * kho_preserve_phys - preserve a physically contiguous range across KHO.
+ * @phys: physical address of the range
+ * @size: size of the range
+ *
+ * Records that the entire range from @phys to @phys + @size is preserved
+ * across KHO.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_preserve_phys(phys_addr_t phys, size_t size)
+{
+	unsigned long pfn = PHYS_PFN(phys), end_pfn = PHYS_PFN(phys + size);
+	unsigned int order = ilog2(end_pfn - pfn);
+	unsigned long failed_pfn;
+	int err = 0;
+
+	if (!kho_enable)
+		return -EOPNOTSUPP;
+
+	down_read(&kho_out.tree_lock);
+	if (kho_out.fdt) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	for (; pfn < end_pfn;
+	     pfn += (1 << order), order = ilog2(end_pfn - pfn)) {
+		err = __kho_preserve(&kho_mem_track, pfn, order);
+		if (err) {
+			failed_pfn = pfn;
+			break;
+		}
+	}
+
+	if (err)
+		for (pfn = PHYS_PFN(phys); pfn < failed_pfn;
+		     pfn += (1 << order), order = ilog2(end_pfn - pfn))
+			__kho_unpreserve(&kho_mem_track, pfn, order);
+
+unlock:
+	up_read(&kho_out.tree_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kho_preserve_phys);
+
+/**
+ * kho_unpreserve_phys - unpreserve a physically contiguous range
+ * @phys: physical address of the range
+ * @size: size of the range
+ *
+ * Remove the record of a range previously preserved by kho_preserve_phys().
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_unpreserve_phys(phys_addr_t phys, size_t size)
+{
+	unsigned long pfn = PHYS_PFN(phys), end_pfn = PHYS_PFN(phys + size);
+	unsigned int order = ilog2(end_pfn - pfn);
+	int err = 0;
+
+	down_read(&kho_out.tree_lock);
+	if (kho_out.fdt) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	for (; pfn < end_pfn; pfn += (1 << order), order = ilog2(end_pfn - pfn))
+		__kho_unpreserve(&kho_mem_track, pfn, order);
+
+unlock:
+	up_read(&kho_out.tree_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_phys);
+
+/* almost as free_reserved_page(), just don't free the page */
+static void kho_restore_page(struct page *page)
+{
+	ClearPageReserved(page);
+	init_page_count(page);
+	adjust_managed_page_count(page, 1);
+}
+
+struct folio *kho_restore_folio(phys_addr_t phys)
+{
+	struct page *page = pfn_to_online_page(PHYS_PFN(phys));
+	unsigned long order = page->private;
+
+	if (!page)
+		return NULL;
+
+	order = page->private;
+	if (order)
+		prep_compound_page(page, order);
+	else
+		kho_restore_page(page);
+
+	return page_folio(page);
+}
+EXPORT_SYMBOL_GPL(kho_restore_folio);
+
+void *kho_restore_phys(phys_addr_t phys, size_t size)
+{
+	unsigned long start_pfn, end_pfn, pfn;
+	void *va = __va(phys);
+
+	start_pfn = PFN_DOWN(phys);
+	end_pfn = PFN_UP(phys + size);
+
+	for (pfn = start_pfn; pfn < end_pfn; pfn++) {
+		struct page *page = pfn_to_online_page(pfn);
+
+		if (!page)
+			return NULL;
+		kho_restore_page(page);
+	}
+
+	return va;
+}
+EXPORT_SYMBOL_GPL(kho_restore_phys);
+
+#define KHOSER_PTR(type)          \
+	union {                   \
+		phys_addr_t phys; \
+		type ptr;         \
+	}
+#define KHOSER_STORE_PTR(dest, val)                 \
+	({                                          \
+		(dest).phys = virt_to_phys(val);    \
+		typecheck(typeof((dest).ptr), val); \
+	})
+#define KHOSER_LOAD_PTR(src) \
+	((src).phys ? (typeof((src).ptr))(phys_to_virt((src).phys)) : NULL)
+
+struct khoser_mem_bitmap_ptr {
+	phys_addr_t phys_start;
+	KHOSER_PTR(struct kho_mem_phys_bits *) bitmap;
+};
+
+struct khoser_mem_chunk;
+
+struct khoser_mem_chunk_hdr {
+	KHOSER_PTR(struct khoser_mem_chunk *) next;
+	unsigned int order;
+	unsigned int num_elms;
+};
+
+#define KHOSER_BITMAP_SIZE                                   \
+	((PAGE_SIZE - sizeof(struct khoser_mem_chunk_hdr)) / \
+	 sizeof(struct khoser_mem_bitmap_ptr))
+
+struct khoser_mem_chunk {
+	struct khoser_mem_chunk_hdr hdr;
+	struct khoser_mem_bitmap_ptr bitmaps[KHOSER_BITMAP_SIZE];
+};
+static_assert(sizeof(struct khoser_mem_chunk) == PAGE_SIZE);
+
+static struct khoser_mem_chunk *new_chunk(struct khoser_mem_chunk *cur_chunk,
+					  unsigned long order)
+{
+	struct khoser_mem_chunk *chunk;
+
+	chunk = (struct khoser_mem_chunk *)get_zeroed_page(GFP_KERNEL);
+	if (!chunk)
+		return NULL;
+	chunk->hdr.order = order;
+	if (cur_chunk)
+		KHOSER_STORE_PTR(cur_chunk->hdr.next, chunk);
+	return chunk;
+}
+
+static void kho_mem_ser_free(struct khoser_mem_chunk *first_chunk)
+{
+	struct khoser_mem_chunk *chunk = first_chunk;
+
+	while (chunk) {
+		unsigned long chunk_page = (unsigned long)chunk;
+
+		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
+		free_page(chunk_page);
+	}
+}
+
+/*
+ * Record all the bitmaps in a linked list of pages for the next kernel to
+ * process. Each chunk holds bitmaps of the same order and each block of bitmaps
+ * starts at a given physical address. This allows the bitmaps to be sparse. The
+ * xarray is used to store them in a tree while building up the data structure,
+ * but the KHO successor kernel only needs to process them once in order.
+ *
+ * All of this memory is normal kmalloc() memory and is not marked for
+ * preservation. The successor kernel will remain isolated to the scratch space
+ * until it completes processing this list. Once processed all the memory
+ * storing these ranges will be marked as free.
+ */
+static struct khoser_mem_chunk *kho_mem_serialize(void)
+{
+	struct kho_mem_track *tracker = &kho_mem_track;
+	struct khoser_mem_chunk *first_chunk = NULL;
+	struct khoser_mem_chunk *chunk = NULL;
+	struct kho_mem_phys *physxa;
+	unsigned long order;
+
+	xa_for_each(&tracker->orders, order, physxa) {
+		struct kho_mem_phys_bits *bits;
+		unsigned long phys;
+
+		chunk = new_chunk(chunk, order);
+		if (!chunk)
+			goto err_free;
+
+		if (!first_chunk)
+			first_chunk = chunk;
+
+		xa_for_each(&physxa->phys_bits, phys, bits) {
+			struct khoser_mem_bitmap_ptr *elm;
+
+			if (chunk->hdr.num_elms == ARRAY_SIZE(chunk->bitmaps)) {
+				chunk = new_chunk(chunk, order);
+				if (!chunk)
+					goto err_free;
+			}
+
+			elm = &chunk->bitmaps[chunk->hdr.num_elms];
+			chunk->hdr.num_elms++;
+			elm->phys_start = (phys * PRESERVE_BITS)
+					  << (order + PAGE_SHIFT);
+			KHOSER_STORE_PTR(elm->bitmap, bits);
+		}
+	}
+
+	return first_chunk;
+
+err_free:
+	kho_mem_ser_free(first_chunk);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void deserialize_bitmap(unsigned int order,
+			       struct khoser_mem_bitmap_ptr *elm)
+{
+	struct kho_mem_phys_bits *bitmap = KHOSER_LOAD_PTR(elm->bitmap);
+	unsigned long bit;
+
+	for_each_set_bit(bit, bitmap->preserve, PRESERVE_BITS) {
+		int sz = 1 << (order + PAGE_SHIFT);
+		phys_addr_t phys =
+			elm->phys_start + (bit << (order + PAGE_SHIFT));
+		struct page *page = phys_to_page(phys);
+
+		memblock_reserve(phys, sz);
+		memblock_reserved_mark_noinit(phys, sz);
+		page->private = order;
+	}
+}
+
+static void __init kho_mem_deserialize(void)
+{
+	struct khoser_mem_chunk *chunk;
+	struct kho_in_node preserved_mem;
+	const phys_addr_t *mem;
+	int err;
+	u32 len;
+
+	err = kho_get_node(NULL, "preserved-memory", &preserved_mem);
+	if (err) {
+		pr_err("no preserved-memory node: %d\n", err);
+		return;
+	}
+
+	mem = kho_get_prop(&preserved_mem, "metadata", &len);
+	if (!mem || len != sizeof(*mem)) {
+		pr_err("failed to get preserved memory bitmaps\n");
+		return;
+	}
+
+	chunk = *mem ? phys_to_virt(*mem) : NULL;
+	while (chunk) {
+		unsigned int i;
+
+		memblock_reserve(virt_to_phys(chunk), sizeof(*chunk));
+
+		for (i = 0; i != chunk->hdr.num_elms; i++)
+			deserialize_bitmap(chunk->hdr.order,
+					   &chunk->bitmaps[i]);
+		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
+	}
+}
+
 /* Helper functions for KHO state tree */
 
 struct kho_prop {
@@ -545,6 +1008,11 @@ static int kho_unfreeze(void)
 	if (fdt)
 		kvfree(fdt);
 
+	if (kho_out.first_chunk_phys) {
+		kho_mem_ser_free(phys_to_virt(kho_out.first_chunk_phys));
+		kho_out.first_chunk_phys = 0;
+	}
+
 	err = blocking_notifier_call_chain(&kho_out.chain_head,
 					   KEXEC_KHO_UNFREEZE, NULL);
 	err = notifier_to_errno(err);
@@ -633,6 +1101,7 @@ static int kho_finalize(void)
 {
 	int err = 0;
 	void *fdt;
+	struct khoser_mem_chunk *first_chunk;
 
 	fdt = kvmalloc(kho_out.fdt_max, GFP_KERNEL);
 	if (!fdt)
@@ -648,6 +1117,13 @@ static int kho_finalize(void)
 	kho_out.fdt = fdt;
 	up_write(&kho_out.tree_lock);
 
+	first_chunk = kho_mem_serialize();
+	if (IS_ERR(first_chunk)) {
+		err = PTR_ERR(first_chunk);
+		goto unfreeze;
+	}
+	kho_out.first_chunk_phys = first_chunk ? virt_to_phys(first_chunk) : 0;
+
 	err = kho_convert_tree(fdt, kho_out.fdt_max);
 
 unfreeze:
@@ -829,6 +1305,10 @@ static __init int kho_init(void)
 
 	kho_out.root.name = "";
 	err = kho_add_string_prop(&kho_out.root, "compatible", "kho-v1");
+	err |= kho_add_prop(&kho_out.preserved_memory, "metadata",
+			    &kho_out.first_chunk_phys, sizeof(phys_addr_t));
+	err |= kho_add_node(&kho_out.root, "preserved-memory",
+			    &kho_out.preserved_memory);
 	if (err)
 		goto err_free_scratch;
 
@@ -1079,10 +1559,12 @@ static void __init kho_release_scratch(void)
 
 void __init kho_memory_init(void)
 {
-	if (!kho_get_fdt())
+	if (!kho_get_fdt()) {
 		kho_reserve_scratch();
-	else
+	} else {
+		kho_mem_deserialize();
 		kho_release_scratch();
+	}
 }
 
 void __init kho_populate(phys_addr_t handover_fdt_phys,
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:45 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:45 -0700
Subject: [PATCH v5 10/16] kexec: add KHO support to kexec file loads
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-11-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

Kexec has 2 modes: A user space driven mode and a kernel driven mode.
For the kernel driven mode, kernel code determines the physical
addresses of all target buffers that the payload gets copied into.

With KHO, we can only safely copy payloads into the "scratch area".
Teach the kexec file loader about it, so it only allocates for that
area. In addition, enlighten it with support to ask the KHO subsystem
for its respective payloads to copy into target memory. Also teach the
KHO subsystem how to fill the images for file loads.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 include/linux/kexec.h   |   7 +++
 kernel/kexec_core.c     |   4 ++
 kernel/kexec_file.c     |  19 +++++++
 kernel/kexec_handover.c | 108 ++++++++++++++++++++++++++++++++++++++++
 kernel/kexec_internal.h |  18 +++++++
 5 files changed, 156 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index fad04f3bcf1d..d59eee60e36e 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -364,6 +364,13 @@ struct kimage {
 	size_t ima_buffer_size;
 #endif
 
+#ifdef CONFIG_KEXEC_HANDOVER
+	struct {
+		struct kexec_segment *scratch;
+		struct kexec_segment *fdt;
+	} kho;
+#endif
+
 	/* Core ELF header buffer */
 	void *elf_headers;
 	unsigned long elf_headers_sz;
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 640d252306ea..67fb9c0b3714 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1053,6 +1053,10 @@ int kernel_kexec(void)
 		goto Unlock;
 	}
 
+	error = kho_copy_fdt(kexec_image);
+	if (error)
+		goto Unlock;
+
 #ifdef CONFIG_KEXEC_JUMP
 	if (kexec_image->preserve_context) {
 		/*
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 3eedb8c226ad..070ef206f573 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -253,6 +253,11 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
 	/* IMA needs to pass the measurement list to the next kernel. */
 	ima_add_kexec_buffer(image);
 
+	/* If KHO is active, add its images to the list */
+	ret = kho_fill_kimage(image);
+	if (ret)
+		goto out;
+
 	/* Call image load handler */
 	ldata = kexec_image_load_default(image);
 
@@ -636,6 +641,14 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
 	if (kbuf->mem != KEXEC_BUF_MEM_UNKNOWN)
 		return 0;
 
+	/*
+	 * If KHO is active, only use KHO scratch memory. All other memory
+	 * could potentially be handed over.
+	 */
+	ret = kho_locate_mem_hole(kbuf, locate_mem_hole_callback);
+	if (ret <= 0)
+		return ret;
+
 	if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
 		ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);
 	else
@@ -764,6 +777,12 @@ static int kexec_calculate_store_digests(struct kimage *image)
 		if (ksegment->kbuf == pi->purgatory_buf)
 			continue;
 
+#ifdef CONFIG_KEXEC_HANDOVER
+		/* Skip KHO FDT as its contects are copied in kernel_kexec(). */
+		if (ksegment == image->kho.fdt)
+			continue;
+#endif
+
 		ret = crypto_shash_update(desc, ksegment->kbuf,
 					  ksegment->bufsz);
 		if (ret)
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index 592563c21369..5108e2cc1a22 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -245,6 +245,85 @@ int kho_node_check_compatible(const struct kho_in_node *node,
 }
 EXPORT_SYMBOL_GPL(kho_node_check_compatible);
 
+int kho_fill_kimage(struct kimage *image)
+{
+	ssize_t scratch_size;
+	int err = 0;
+
+	if (!kho_enable)
+		return 0;
+
+	/* Allocate target memory for KHO FDT */
+	struct kexec_buf fdt = {
+		.image = image,
+		.buffer = NULL,
+		.bufsz = 0,
+		.mem = KEXEC_BUF_MEM_UNKNOWN,
+		.memsz = kho_out.fdt_max,
+		.buf_align = SZ_64K, /* Makes it easier to map */
+		.buf_max = ULONG_MAX,
+		.top_down = true,
+	};
+	err = kexec_add_buffer(&fdt);
+	if (err) {
+		pr_err("failed to reserved a segment for KHO FDT: %d\n", err);
+		return err;
+	}
+	image->kho.fdt = &image->segment[image->nr_segments - 1];
+
+	scratch_size = sizeof(*kho_scratch) * kho_scratch_cnt;
+	struct kexec_buf scratch = {
+		.image = image,
+		.buffer = kho_scratch,
+		.bufsz = scratch_size,
+		.mem = KEXEC_BUF_MEM_UNKNOWN,
+		.memsz = scratch_size,
+		.buf_align = SZ_64K, /* Makes it easier to map */
+		.buf_max = ULONG_MAX,
+		.top_down = true,
+	};
+	err = kexec_add_buffer(&scratch);
+	if (err)
+		return err;
+	image->kho.scratch = &image->segment[image->nr_segments - 1];
+
+	return 0;
+}
+
+static int kho_walk_scratch(struct kexec_buf *kbuf,
+			    int (*func)(struct resource *, void *))
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < kho_scratch_cnt; i++) {
+		struct resource res = {
+			.start = kho_scratch[i].addr,
+			.end = kho_scratch[i].addr + kho_scratch[i].size - 1,
+		};
+
+		/* Try to fit the kimage into our KHO scratch region */
+		ret = func(&res, kbuf);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+int kho_locate_mem_hole(struct kexec_buf *kbuf,
+			int (*func)(struct resource *, void *))
+{
+	int ret;
+
+	if (!kho_enable || kbuf->image->type == KEXEC_TYPE_CRASH)
+		return 1;
+
+	ret = kho_walk_scratch(kbuf, func);
+
+	return ret == 1 ? 0 : -EADDRNOTAVAIL;
+}
+
 /*
  * Keep track of memory that is to be preserved across KHO.
  *
@@ -1141,6 +1220,35 @@ static int kho_finalize(void)
 	return err;
 }
 
+int kho_copy_fdt(struct kimage *image)
+{
+	int err = 0;
+	void *fdt;
+
+	if (!kho_enable || !image->file_mode)
+		return 0;
+
+	if (!kho_out.fdt) {
+		err = kho_finalize();
+		kho_out_update_debugfs_fdt();
+		if (err)
+			return err;
+	}
+
+	fdt = kimage_map_segment(image, image->kho.fdt->mem,
+				 PAGE_ALIGN(kho_out.fdt_max));
+	if (!fdt) {
+		pr_err("failed to vmap fdt ksegment in kimage\n");
+		return -ENOMEM;
+	}
+
+	memcpy(fdt, kho_out.fdt, fdt_totalsize(kho_out.fdt));
+
+	kimage_unmap_segment(fdt);
+
+	return 0;
+}
+
 /* Handling for debug/kho/out */
 static int kho_out_finalize_get(void *data, u64 *val)
 {
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index d35d9792402d..ec9555a4751d 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -39,4 +39,22 @@ extern size_t kexec_purgatory_size;
 #else /* CONFIG_KEXEC_FILE */
 static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
 #endif /* CONFIG_KEXEC_FILE */
+
+struct kexec_buf;
+
+#ifdef CONFIG_KEXEC_HANDOVER
+int kho_locate_mem_hole(struct kexec_buf *kbuf,
+			int (*func)(struct resource *, void *));
+int kho_fill_kimage(struct kimage *image);
+int kho_copy_fdt(struct kimage *image);
+#else
+static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
+				      int (*func)(struct resource *, void *))
+{
+	return 1;
+}
+
+static inline int kho_fill_kimage(struct kimage *image) { return 0; }
+static inline int kho_copy_fdt(struct kimage *image) { return 0; }
+#endif /* CONFIG_KEXEC_HANDOVER */
 #endif /* LINUX_KEXEC_INTERNAL_H */
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:47 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:47 -0700
Subject: [PATCH v5 12/16] arm64: add KHO support
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-13-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

We now have all bits in place to support KHO kexecs. Add awareness of
KHO in the kexec file as well as boot path for arm64 and adds the
respective kconfig option to the architecture so that it can use KHO
successfully.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 arch/arm64/Kconfig |  3 +++
 drivers/of/fdt.c   | 33 +++++++++++++++++++++++++++++++++
 drivers/of/kexec.c | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..c997b27b7da1 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1589,6 +1589,9 @@ config ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG
 config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG
 	def_bool y
 
+config ARCH_SUPPORTS_KEXEC_HANDOVER
+	def_bool y
+
 config ARCH_SUPPORTS_CRASH_DUMP
 	def_bool y
 
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index aedd0e2dcd89..73f80e3f7188 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -25,6 +25,7 @@
 #include <linux/serial_core.h>
 #include <linux/sysfs.h>
 #include <linux/random.h>
+#include <linux/kexec_handover.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
@@ -875,6 +876,35 @@ void __init early_init_dt_check_for_usable_mem_range(void)
 		memblock_add(rgn[i].base, rgn[i].size);
 }
 
+/**
+ * early_init_dt_check_kho - Decode info required for kexec handover from DT
+ */
+static void __init early_init_dt_check_kho(void)
+{
+	unsigned long node = chosen_node_offset;
+	u64 kho_start, scratch_start, scratch_size;
+	const __be32 *p;
+	int l;
+
+	if (!IS_ENABLED(CONFIG_KEXEC_HANDOVER) || (long)node < 0)
+		return;
+
+	p = of_get_flat_dt_prop(node, "linux,kho-fdt", &l);
+	if (l != (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32))
+		return;
+
+	kho_start = dt_mem_next_cell(dt_root_addr_cells, &p);
+
+	p = of_get_flat_dt_prop(node, "linux,kho-scratch", &l);
+	if (l != (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32))
+		return;
+
+	scratch_start = dt_mem_next_cell(dt_root_addr_cells, &p);
+	scratch_size = dt_mem_next_cell(dt_root_addr_cells, &p);
+
+	kho_populate(kho_start, scratch_start, scratch_size);
+}
+
 #ifdef CONFIG_SERIAL_EARLYCON
 
 int __init early_init_dt_scan_chosen_stdout(void)
@@ -1169,6 +1199,9 @@ void __init early_init_dt_scan_nodes(void)
 
 	/* Handle linux,usable-memory-range property */
 	early_init_dt_check_for_usable_mem_range();
+
+	/* Handle kexec handover */
+	early_init_dt_check_kho();
 }
 
 bool __init early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys)
diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
index 5b924597a4de..db7d7014d8b4 100644
--- a/drivers/of/kexec.c
+++ b/drivers/of/kexec.c
@@ -264,6 +264,38 @@ static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
 }
 #endif /* CONFIG_IMA_KEXEC */
 
+static int kho_add_chosen(const struct kimage *image, void *fdt, int chosen_node)
+{
+	int ret = 0;
+#ifdef CONFIG_KEXEC_HANDOVER
+	phys_addr_t dt_mem = 0;
+	phys_addr_t dt_len = 0;
+	phys_addr_t scratch_mem = 0;
+	phys_addr_t scratch_len = 0;
+
+	if (!image->kho.fdt || !image->kho.scratch)
+		return 0;
+
+	dt_mem = image->kho.fdt->mem;
+	dt_len = image->kho.fdt->memsz;
+
+	scratch_mem = image->kho.scratch->mem;
+	scratch_len = image->kho.scratch->bufsz;
+
+	pr_debug("Adding kho metadata to DT");
+
+	ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, "linux,kho-fdt",
+				       dt_mem, dt_len);
+	if (ret)
+		return ret;
+
+	ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, "linux,kho-scratch",
+				       scratch_mem, scratch_len);
+
+#endif /* CONFIG_KEXEC_HANDOVER */
+	return ret;
+}
+
 /*
  * of_kexec_alloc_and_setup_fdt - Alloc and setup a new Flattened Device Tree
  *
@@ -414,6 +446,11 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
 #endif
 	}
 
+	/* Add kho metadata if this is a KHO image */
+	ret = kho_add_chosen(image, fdt, chosen_node);
+	if (ret)
+		goto out;
+
 	/* add bootargs */
 	if (cmdline) {
 		ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:48 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:48 -0700
Subject: [PATCH v5 13/16] x86/setup: use memblock_reserve_kern for memory used
 by kernel
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-14-changyuanl@google.com>

From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>

memblock_reserve() does not distinguish memory used by firmware from memory
used by kernel.

The distinction is nice to have for accounting of early memory allocations
and reservations, but it is essential for kexec handover (kho) to know how
much memory kernel consumes during boot.

Use memblock_reserve_kern() to reserve kernel memory, such as kernel image,
initrd and setup data.

Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
 arch/x86/kernel/setup.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cebee310e200..ead370570eb2 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -220,8 +220,8 @@ static void __init cleanup_highmap(void)
 static void __init reserve_brk(void)
 {
 	if (_brk_end > _brk_start)
-		memblock_reserve(__pa_symbol(_brk_start),
-				 _brk_end - _brk_start);
+		memblock_reserve_kern(__pa_symbol(_brk_start),
+				      _brk_end - _brk_start);
 
 	/* Mark brk area as locked down and no longer taking any
 	   new allocations */
@@ -294,7 +294,7 @@ static void __init early_reserve_initrd(void)
 	    !ramdisk_image || !ramdisk_size)
 		return;		/* No initrd provided by bootloader */
 
-	memblock_reserve(ramdisk_image, ramdisk_end - ramdisk_image);
+	memblock_reserve_kern(ramdisk_image, ramdisk_end - ramdisk_image);
 }
 
 static void __init reserve_initrd(void)
@@ -347,7 +347,7 @@ static void __init add_early_ima_buffer(u64 phys_addr)
 	}
 
 	if (data->size) {
-		memblock_reserve(data->addr, data->size);
+		memblock_reserve_kern(data->addr, data->size);
 		ima_kexec_buffer_phys = data->addr;
 		ima_kexec_buffer_size = data->size;
 	}
@@ -447,7 +447,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 		len = sizeof(*data);
 		pa_next = data->next;
 
-		memblock_reserve(pa_data, sizeof(*data) + data->len);
+		memblock_reserve_kern(pa_data, sizeof(*data) + data->len);
 
 		if (data->type == SETUP_INDIRECT) {
 			len += data->len;
@@ -461,7 +461,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 			indirect = (struct setup_indirect *)data->data;
 
 			if (indirect->type != SETUP_INDIRECT)
-				memblock_reserve(indirect->addr, indirect->len);
+				memblock_reserve_kern(indirect->addr, indirect->len);
 		}
 
 		pa_data = pa_next;
@@ -649,8 +649,8 @@ static void __init early_reserve_memory(void)
 	 * __end_of_kernel_reserve symbol must be explicitly reserved with a
 	 * separate memblock_reserve() or they will be discarded.
 	 */
-	memblock_reserve(__pa_symbol(_text),
-			 (unsigned long)__end_of_kernel_reserve - (unsigned long)_text);
+	memblock_reserve_kern(__pa_symbol(_text),
+			      (unsigned long)__end_of_kernel_reserve - (unsigned long)_text);
 
 	/*
 	 * The first 4Kb of memory is a BIOS owned area, but generally it is
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:46 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:46 -0700
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-12-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

We have all generic code in place now to support Kexec with KHO. This
patch adds a config option that depends on architecture support to
enable KHO support.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 kernel/Kconfig.kexec | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
index 4d111f871951..57db99e758a8 100644
--- a/kernel/Kconfig.kexec
+++ b/kernel/Kconfig.kexec
@@ -95,6 +95,21 @@ config KEXEC_JUMP
 	  Jump between original kernel and kexeced kernel and invoke
 	  code in physical address mode via KEXEC
 
+config KEXEC_HANDOVER
+	bool "kexec handover"
+	depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
+	select MEMBLOCK_KHO_SCRATCH
+	select KEXEC_FILE
+	select DEBUG_FS
+	select LIBFDT
+	select CMA
+	select XXHASH
+	help
+	  Allow kexec to hand over state across kernels by generating and
+	  passing additional metadata to the target kernel. This is useful
+	  to keep data or state alive across the kexec. For this to work,
+	  both source and target kernels need to have this option enabled.
+
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	default ARCH_DEFAULT_CRASH_DUMP
-- 
2.48.1.711.g2feabab25a-goog



From changyuanl at google.com  Wed Mar 19 18:55:49 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Wed, 19 Mar 2025 18:55:49 -0700
Subject: [PATCH v5 14/16] x86: add KHO support
In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
Message-ID: <20250320015551.2157511-15-changyuanl@google.com>

From: Alexander Graf <graf at amazon.com>

We now have all bits in place to support KHO kexecs. This patch adds
awareness of KHO in the kexec file as well as boot path for x86 and
adds the respective kconfig option to the architecture so that it can
use KHO successfully.

In addition, it enlightens it decompression code with KHO so that its
KASLR location finder only considers memory regions that are not already
occupied by KHO memory.

Signed-off-by: Alexander Graf <graf at amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl at google.com>
Signed-off-by: Changyuan Lyu <changyuanl at google.com>
---
 arch/x86/Kconfig                       |  3 ++
 arch/x86/boot/compressed/kaslr.c       | 52 +++++++++++++++++++++++++-
 arch/x86/include/asm/setup.h           |  4 ++
 arch/x86/include/uapi/asm/setup_data.h | 13 ++++++-
 arch/x86/kernel/e820.c                 | 18 +++++++++
 arch/x86/kernel/kexec-bzimage64.c      | 36 ++++++++++++++++++
 arch/x86/kernel/setup.c                | 25 +++++++++++++
 arch/x86/realmode/init.c               |  2 +
 include/linux/kexec_handover.h         | 13 +++++--
 9 files changed, 161 insertions(+), 5 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0e27ebd7e36a..acd180e3002f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2091,6 +2091,9 @@ config ARCH_SUPPORTS_KEXEC_BZIMAGE_VERIFY_SIG
 config ARCH_SUPPORTS_KEXEC_JUMP
 	def_bool y
 
+config ARCH_SUPPORTS_KEXEC_HANDOVER
+	def_bool y
+
 config ARCH_SUPPORTS_CRASH_DUMP
 	def_bool X86_64 || (X86_32 && HIGHMEM)
 
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index f03d59ea6e40..ff1168881016 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -760,6 +760,55 @@ static void process_e820_entries(unsigned long minimum,
 	}
 }
 
+/*
+ * If KHO is active, only process its scratch areas to ensure we are not
+ * stepping onto preserved memory.
+ */
+#ifdef CONFIG_KEXEC_HANDOVER
+static bool process_kho_entries(unsigned long minimum, unsigned long image_size)
+{
+	struct kho_scratch *kho_scratch;
+	struct setup_data *ptr;
+	int i, nr_areas = 0;
+
+	ptr = (struct setup_data *)(unsigned long)boot_params_ptr->hdr.setup_data;
+	while (ptr) {
+		if (ptr->type == SETUP_KEXEC_KHO) {
+			struct kho_data *kho = (struct kho_data *)ptr->data;
+
+			kho_scratch = (void *)kho->scratch_addr;
+			nr_areas = kho->scratch_size / sizeof(*kho_scratch);
+
+			break;
+		}
+
+		ptr = (struct setup_data *)(unsigned long)ptr->next;
+	}
+
+	if (!nr_areas)
+		return false;
+
+	for (i = 0; i < nr_areas; i++) {
+		struct kho_scratch *area = &kho_scratch[i];
+		struct mem_vector region = {
+			.start = area->addr,
+			.size = area->size,
+		};
+
+		if (process_mem_region(&region, minimum, image_size))
+			break;
+	}
+
+	return true;
+}
+#else
+static inline bool process_kho_entries(unsigned long minimum,
+				       unsigned long image_size)
+{
+	return false;
+}
+#endif
+
 static unsigned long find_random_phys_addr(unsigned long minimum,
 					   unsigned long image_size)
 {
@@ -775,7 +824,8 @@ static unsigned long find_random_phys_addr(unsigned long minimum,
 		return 0;
 	}
 
-	if (!process_efi_entries(minimum, image_size))
+	if (!process_kho_entries(minimum, image_size) &&
+	    !process_efi_entries(minimum, image_size))
 		process_e820_entries(minimum, image_size);
 
 	phys_addr = slots_fetch_random();
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 85f4fde3515c..70e045321d4b 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -66,6 +66,10 @@ extern void x86_ce4100_early_setup(void);
 static inline void x86_ce4100_early_setup(void) { }
 #endif
 
+#ifdef CONFIG_KEXEC_HANDOVER
+#include <linux/kexec_handover.h>
+#endif
+
 #ifndef _SETUP
 
 #include <asm/espfix.h>
diff --git a/arch/x86/include/uapi/asm/setup_data.h b/arch/x86/include/uapi/asm/setup_data.h
index b111b0c18544..c258c37768ee 100644
--- a/arch/x86/include/uapi/asm/setup_data.h
+++ b/arch/x86/include/uapi/asm/setup_data.h
@@ -13,7 +13,8 @@
 #define SETUP_CC_BLOB			7
 #define SETUP_IMA			8
 #define SETUP_RNG_SEED			9
-#define SETUP_ENUM_MAX			SETUP_RNG_SEED
+#define SETUP_KEXEC_KHO			10
+#define SETUP_ENUM_MAX			SETUP_KEXEC_KHO
 
 #define SETUP_INDIRECT			(1<<31)
 #define SETUP_TYPE_MAX			(SETUP_ENUM_MAX | SETUP_INDIRECT)
@@ -78,6 +79,16 @@ struct ima_setup_data {
 	__u64 size;
 } __attribute__((packed));
 
+/*
+ * Locations of kexec handover metadata
+ */
+struct kho_data {
+	__u64 dt_addr;
+	__u64 dt_size;
+	__u64 scratch_addr;
+	__u64 scratch_size;
+} __attribute__((packed));
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI_ASM_X86_SETUP_DATA_H */
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 82b96ed9890a..0b81cd70b02a 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -1329,6 +1329,24 @@ void __init e820__memblock_setup(void)
 		memblock_add(entry->addr, entry->size);
 	}
 
+	/*
+	 * At this point with KHO we only allocate from scratch memory.
+	 * At the same time, we configure memblock to only allow
+	 * allocations from memory below ISA_END_ADDRESS which is not
+	 * a natural scratch region, because Linux ignores memory below
+	 * ISA_END_ADDRESS at runtime. Beside very few (if any) early
+	 * allocations, we must allocate real-mode trapoline below
+	 * ISA_END_ADDRESS.
+	 *
+	 * To make sure that we can actually perform allocations during
+	 * this phase, let's mark memory below ISA_END_ADDRESS as scratch
+	 * so we can allocate from there in a scratch-only world.
+	 *
+	 * After real mode trampoline is allocated, we clear scratch
+	 * marking from the memory below ISA_END_ADDRESS
+	 */
+	memblock_mark_kho_scratch(0, ISA_END_ADDRESS);
+
 	/* Throw away partial pages: */
 	memblock_trim_memory(PAGE_SIZE);
 
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 68530fad05f7..09d6a068b14c 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -233,6 +233,31 @@ setup_ima_state(const struct kimage *image, struct boot_params *params,
 #endif /* CONFIG_IMA_KEXEC */
 }
 
+static void setup_kho(const struct kimage *image, struct boot_params *params,
+		      unsigned long params_load_addr,
+		      unsigned int setup_data_offset)
+{
+#ifdef CONFIG_KEXEC_HANDOVER
+	struct setup_data *sd = (void *)params + setup_data_offset;
+	struct kho_data *kho = (void *)sd + sizeof(*sd);
+
+	sd->type = SETUP_KEXEC_KHO;
+	sd->len = sizeof(struct kho_data);
+
+	/* Only add if we have all KHO images in place */
+	if (!image->kho.fdt || !image->kho.scratch)
+		return;
+
+	/* Add setup data */
+	kho->dt_addr = image->kho.fdt->mem;
+	kho->dt_size = image->kho.fdt->memsz;
+	kho->scratch_addr = image->kho.scratch->mem;
+	kho->scratch_size = image->kho.scratch->bufsz;
+	sd->next = params->hdr.setup_data;
+	params->hdr.setup_data = params_load_addr + setup_data_offset;
+#endif /* CONFIG_KEXEC_HANDOVER */
+}
+
 static int
 setup_boot_parameters(struct kimage *image, struct boot_params *params,
 		      unsigned long params_load_addr,
@@ -312,6 +337,13 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
 				     sizeof(struct ima_setup_data);
 	}
 
+	if (IS_ENABLED(CONFIG_KEXEC_HANDOVER)) {
+		/* Setup space to store preservation metadata */
+		setup_kho(image, params, params_load_addr, setup_data_offset);
+		setup_data_offset += sizeof(struct setup_data) +
+				     sizeof(struct kho_data);
+	}
+
 	/* Setup RNG seed */
 	setup_rng_seed(params, params_load_addr, setup_data_offset);
 
@@ -479,6 +511,10 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 		kbuf.bufsz += sizeof(struct setup_data) +
 			      sizeof(struct ima_setup_data);
 
+	if (IS_ENABLED(CONFIG_KEXEC_HANDOVER))
+		kbuf.bufsz += sizeof(struct setup_data) +
+			      sizeof(struct kho_data);
+
 	params = kzalloc(kbuf.bufsz, GFP_KERNEL);
 	if (!params)
 		return ERR_PTR(-ENOMEM);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index ead370570eb2..e2c54181405b 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -385,6 +385,28 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size)
 }
 #endif
 
+static void __init add_kho(u64 phys_addr, u32 data_len)
+{
+#ifdef CONFIG_KEXEC_HANDOVER
+	struct kho_data *kho;
+	u64 addr = phys_addr + sizeof(struct setup_data);
+	u64 size = data_len - sizeof(struct setup_data);
+
+	kho = early_memremap(addr, size);
+	if (!kho) {
+		pr_warn("setup: failed to memremap kho data (0x%llx, 0x%llx)\n",
+			addr, size);
+		return;
+	}
+
+	kho_populate(kho->dt_addr, kho->scratch_addr, kho->scratch_size);
+
+	early_memunmap(kho, size);
+#else
+	pr_warn("Passed KHO data, but CONFIG_KEXEC_HANDOVER not set. Ignoring.\n");
+#endif
+}
+
 static void __init parse_setup_data(void)
 {
 	struct setup_data *data;
@@ -413,6 +435,9 @@ static void __init parse_setup_data(void)
 		case SETUP_IMA:
 			add_early_ima_buffer(pa_data);
 			break;
+		case SETUP_KEXEC_KHO:
+			add_kho(pa_data, data_len);
+			break;
 		case SETUP_RNG_SEED:
 			data = early_memremap(pa_data, data_len);
 			add_bootloader_randomness(data->data, data->len);
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f9bc444a3064..9b9f4534086d 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -65,6 +65,8 @@ void __init reserve_real_mode(void)
 	 * setup_arch().
 	 */
 	memblock_reserve(0, SZ_1M);
+
+	memblock_clear_kho_scratch(0, SZ_1M);
 }
 
 static void __init sme_sev_setup_real_mode(struct trampoline_header *th)
diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index d52a7b500f4c..2dd51a77d56c 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -3,9 +3,6 @@
 #define LINUX_KEXEC_HANDOVER_H
 
 #include <linux/types.h>
-#include <linux/hashtable.h>
-#include <linux/notifier.h>
-#include <linux/mm_types.h>
 
 struct kho_scratch {
 	phys_addr_t addr;
@@ -18,6 +15,15 @@ enum kho_event {
 	KEXEC_KHO_UNFREEZE = 1,
 };
 
+#ifdef _SETUP
+struct notifier_block;
+struct kho_node;
+struct folio;
+#else
+#include <linux/notifier.h>
+#include <linux/hashtable.h>
+#include <linux/mm_types.h>
+
 #define KHO_HASHTABLE_BITS 3
 #define KHO_NODE_INIT                                        \
 	{                                                    \
@@ -35,6 +41,7 @@ struct kho_node {
 	struct list_head list;
 	bool visited;
 };
+#endif /* _SETUP */
 
 struct kho_in_node {
 	int offset;
-- 
2.48.1.711.g2feabab25a-goog



From jiebing.chen at amlogic.com  Wed Mar 19 19:29:07 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 10:29:07 +0800
Subject: [PATCH v4 2/6] dt-bindings: clock: axg-audio: Add mclk and sclk
 pad clock ids
In-Reply-To: <e5d3741d-0f4e-4f92-9b1c-04b114892330@amlogic.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-2-686867fad719@amlogic.com>
 <20250319-daffy-classy-kangaroo-023e1f@krzk-bin>
 <9ae73d75-9c59-4255-8924-b456c86cbc01@amlogic.com>
 <7084e271-8546-4a49-9eb8-ee3f647c529a@kernel.org>
 <e5d3741d-0f4e-4f92-9b1c-04b114892330@amlogic.com>
Message-ID: <8253157a-bc8e-4c6e-8697-2fdaf7193bc8@amlogic.com>


? 2025/3/20 10:26, Jiebing Chen ??:
>
> ? 2025/3/20 3:31, Krzysztof Kozlowski ??:
>> [ EXTERNAL EMAIL ]
>>
>> On 19/03/2025 11:09, Jiebing Chen wrote:
>>> ? 2025/3/19 16:22, Krzysztof Kozlowski ??:
>>>> [You don't often get email from krzk at kernel.org. Learn why this is 
>>>> important at https://aka.ms/LearnAboutSenderIdentification ]
>>>>
>>>> [ EXTERNAL EMAIL ]
>>>>
>>>> On Wed, Mar 19, 2025 at 03:04:45PM +0800, jiebing chen wrote:
>>>>> Add clock IDs for the mclk pads found on s4 SoCs
>>>>>
>>>>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>>>>> ---
>>>>> ?? include/dt-bindings/clock/axg-audio-clkc.h | 11 +++++++++++
>>>> This belongs to the binding patch, usually.
>>>>
>>>> Anyway - do not ask us to do the work twice.
>>>>
>>>> <form letter>
>>>> This is a friendly reminder during the review process.
>>>>
>>>> It looks like you received a tag and forgot to add it.
>>>>
>>>> If you do not know the process, here is a short explanation:
>>>> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
>>>> versions of patchset, under or above your Signed-off-by tag, unless
>>>> patch changed significantly (e.g. new properties added to the DT
>>>> bindings). Tag is "received", when provided in a message replied to 
>>>> you
>>>> on the mailing list. Tools like b4 can help here. However, there's no
>>>> need to repost patches *only* to add the tags. The upstream maintainer
>>>> will do that for tags received on the version they apply.
>>>>
>>>> Please read:
>>>> https://elixir.bootlin.com/linux/v6.12-rc3/source/Documentation/process/submitting-patches.rst#L577 
>>>>
>>>>
>>>> If a tag was not added on purpose, please state why and what changed.
>>>> </form letter>
>>> thanks for your remind
>> Are you going to do anything or you are going to ignore us?
>
> Sorry, I forget retrieving the tags and will check all comments 
> carefully again. Thanks you!
>
>>
>> Best regards,
>> Krzysztof


From jiebing.chen at amlogic.com  Wed Mar 19 19:31:03 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 10:31:03 +0800
Subject: [PATCH v4 6/6] arm64: dts: amlogic: Add Amlogic S4 Audio
In-Reply-To: <37f65ad0-69fa-4031-86da-8b07828aff34@kernel.org>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-6-686867fad719@amlogic.com>
 <20250319-quizzical-coyote-of-assurance-d4c91d@krzk-bin>
 <9397d6d5-518d-4bd0-a34a-7a5f5e1201f1@amlogic.com>
 <37f65ad0-69fa-4031-86da-8b07828aff34@kernel.org>
Message-ID: <2ea32d85-1d96-4b40-909f-053f309861d4@amlogic.com>


? 2025/3/20 3:31, Krzysztof Kozlowski ??:
> [ EXTERNAL EMAIL ]
>
> On 19/03/2025 11:38, Jiebing Chen wrote:
>>>>    };
>>>>
>>>>    &pwm_ef {
>>>> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>>> index 957577d986c0675a503115e1ccbc4387c2051620..83edafc2646438e3e6b1945fa1c4b327254a4131 100644
>>>> --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>>> +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
>>>> @@ -11,7 +11,11 @@
>>>>    #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
>>>>    #include <dt-bindings/power/meson-s4-power.h>
>>>>    #include <dt-bindings/reset/amlogic,meson-s4-reset.h>
>>>> -
>>> Why?
>> The following files are included that the audio driver depends on
> Do you understand how emails work and patch review? I commented under
> your change, not unrelated code being there already.
Sorry, I will check the rule. Thanks you!
>> it is same as sm1 chip
>>
>>>> +#include <dt-bindings/clock/axg-audio-clkc.h>
>>>> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
>>>> +#include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h>
>>>> +#include <dt-bindings/sound/meson-g12a-toacodec.h>
>>>> +#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
>>> Old style was correct.
>> I didn't understand where you were referring to, I'm guessing that's
>> what it was about
> Read your patch.
>
>
>> the following changes to tdmif_a
>>
>> old:
>>
>> clock-names = "mclk", "sclk", "lrclk";
>>
>> new:
>> clock-names = "sclk", "lrclk","mclk";
>> it fix warning
> How is this related to the patch hunk?
>
> Do you understand how patch format works?
>
>
> ...
>
>>>>         timer {
>>>>                 compatible = "arm,armv8-timer";
>>>>                 interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
>>>> @@ -101,7 +135,6 @@ apb4: bus at fe000000 {
>>>>                         #address-cells = <2>;
>>>>                         #size-cells = <2>;
>>>>                         ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
>>>> -
>>> Why? What is happening in this patch - why are you changing so many
>>> other pieces?
> You did not respond here, so I assume you will fix this and do intensive
> review before posting next version.
>
>>>>                         clkc_periphs: clock-controller at 0 {
>>>>                                 compatible = "amlogic,s4-peripherals-clkc";
>>>>                                 reg = <0x0 0x0 0x0 0x49c>;
>>>> @@ -134,6 +167,17 @@ clkc_pll: clock-controller at 8000 {
>>>>                                 #clock-cells = <1>;
>>>>                         };
>>>>
>>>> +                     acodec: audio-controller at 1a000 {
>>>> +                             compatible = "amlogic,t9015";
>>>> +                             reg = <0x0 0x1A000 0x0 0x14>;
>>>> +                             #sound-dai-cells = <0>;
>>>> +                             sound-name-prefix = "ACODEC";
>>>> +                             clocks = <&clkc_periphs CLKID_ACODEC>;
>>>> +                             clock-names = "pclk";
>>>> +                             resets = <&reset RESET_ACODEC>;
>>>> +                             AVDD-supply = <&vddio_ao1v8>;
>>>> +                     };
>>>> +
>>>>                         watchdog at 2100 {
>>>>                                 compatible = "amlogic,s4-wdt", "amlogic,t7-wdt";
>>>>                                 reg = <0x0 0x2100 0x0 0x10>;
>>>> @@ -850,3 +894,327 @@ emmc: mmc at fe08c000 {
>>>>                 };
>>>>         };
>>>>    };
>>>> +
>>>> +&apb4 {
>>>> +     audio: bus at 330000 {
>>>> +             compatible = "simple-bus";
>>>> +             reg = <0x0 0x330000 0x0 0x1000>;
>>> That's not a simple bus in such case.
>> these code base on old dts like sm1/g12a, we didn't easily change any of
>> the relevant properties
>>
>> To be consistent with the previous one
> Still NAK.
>
> You cannot add bugs just to be consistent.
>
>
> Best regards,
> Krzysztof


From jiebing.chen at amlogic.com  Wed Mar 19 19:43:30 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 10:43:30 +0800
Subject: [PATCH v4 1/6] dt-bindings: clock: meson: Add audio power domain
 for s4 soc
In-Reply-To: <174237350819.971004.1098115771430334211.robh@kernel.org>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-1-686867fad719@amlogic.com>
 <174237350819.971004.1098115771430334211.robh@kernel.org>
Message-ID: <0096ba23-3433-4f98-92ee-321c3461dff0@amlogic.com>


? 2025/3/19 16:38, Rob Herring (Arm) ??:
> [ EXTERNAL EMAIL ]
>
> On Wed, 19 Mar 2025 15:04:44 +0800, jiebing chen wrote:
>> Audio power domain found on S4 device.it need to enable before audio work.
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   .../bindings/clock/amlogic,axg-audio-clkc.yaml       | 20 +++++++++++++++++++-
>>   1 file changed, 19 insertions(+), 1 deletion(-)
>>
> My bot found errors running 'make dt_binding_check' on your patch:

thanks for review, sorry , I missed your previous email, the mail was 
accidentally intercepted

pip3 install yamllint

DT_SCHEMA_FILES=Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml 
DT_CHECKER_FLAGS=-m make W=1 dt_binding_check

we can see these warnings, and fix it in next verison, thanks again

>
> yamllint warnings/errors:
> ./Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.yaml:105:7: [warning] wrong indentation: expected 4 but found 6 (indentation)
>
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.example.dtb: clock-controller at 0: reg: [[0, 0, 0, 180]] is too short
>          from schema $id: http://devicetree.org/schemas/clock/amlogic,axg-audio-clkc.yaml#
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250319-audio_drvier-v4-1-686867fad719 at amlogic.com
>
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.
>


From amadeus at jmu.edu.cn  Wed Mar 19 20:00:15 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 20 Mar 2025 11:00:15 +0800
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se>
References: <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se>
Message-ID: <20250320030015.177232-1-amadeus@jmu.edu.cn>

Hi,

> The device tree should describe the hardware, not what the driver
> support, so interrupts should probably be included.

Before I submitted, I noticed these two commits:

1. ARM: dts: rockchip: Drop interrupts property from pwm-rockchip nodes
https://github.com/torvalds/linux/commit/f98643d8daf3443e3b414a82d0cb3d745f8c8bbc

2. arm64: dts: rockchip: Drop interrupts property from rk3328 pwm-rockchip node
https://github.com/torvalds/linux/commit/1bbd894e2ae67faf52632bc9290ff926d9b741ea

So I removed the interrupts to avoid dtbs_check warnings.

Thanks,
Chukun

--
2.25.1



From hailong.fan at mediatek.com  Wed Mar 19 20:17:24 2025
From: hailong.fan at mediatek.com (hailong.fan)
Date: Thu, 20 Mar 2025 11:17:24 +0800
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <20250320031753.13669-1-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
Message-ID: <20250320031753.13669-2-hailong.fan@mediatek.com>

Add support of SOF on MediaTek mt8196 SoC.
MT8196 has a Cadence HiFi-5 DSP core that is responsible for running the
operating system and application programs. The IPC communication between
the AP and DSP is based on shared DRAM and mailbox interrupt.

Signed-off-by: hailong.fan <hailong.fan at mediatek.com>
---
 sound/soc/sof/mediatek/Kconfig                |   9 +
 sound/soc/sof/mediatek/Makefile               |   1 +
 sound/soc/sof/mediatek/mt8196/Makefile        |   4 +
 sound/soc/sof/mediatek/mt8196/mt8196-clk.c    | 100 +++
 sound/soc/sof/mediatek/mt8196/mt8196-clk.h    |  23 +
 sound/soc/sof/mediatek/mt8196/mt8196-loader.c |  61 ++
 sound/soc/sof/mediatek/mt8196/mt8196.c        | 650 ++++++++++++++++++
 sound/soc/sof/mediatek/mt8196/mt8196.h        | 109 +++
 8 files changed, 957 insertions(+)
 create mode 100644 sound/soc/sof/mediatek/mt8196/Makefile
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-clk.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-clk.h
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-loader.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196.h

diff --git a/sound/soc/sof/mediatek/Kconfig b/sound/soc/sof/mediatek/Kconfig
index 4a2eddf6009a..ff89c4b1e052 100644
--- a/sound/soc/sof/mediatek/Kconfig
+++ b/sound/soc/sof/mediatek/Kconfig
@@ -42,4 +42,13 @@ config SND_SOC_SOF_MT8195
 	  Say Y if you have such a device.
 	  If unsure select "N".
 
+config SND_SOC_SOF_MT8196
+	tristate "SOF support for MT8196 audio DSP"
+	select SND_SOC_SOF_MTK_COMMON
+	depends on MTK_ADSP_IPC
+	help
+	  This adds support for Sound Open Firmware for Mediatek platforms
+	  using the mt8196 processors.
+	  Say Y if you have such a device.
+	  If unsure select "N".
 endif ## SND_SOC_SOF_MTK_TOPLEVEL
diff --git a/sound/soc/sof/mediatek/Makefile b/sound/soc/sof/mediatek/Makefile
index 29c5afb2f3d6..3e36d538679e 100644
--- a/sound/soc/sof/mediatek/Makefile
+++ b/sound/soc/sof/mediatek/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_SND_SOC_SOF_MTK_COMMON) += mtk-adsp-common.o
 obj-$(CONFIG_SND_SOC_SOF_MT8195) += mt8195/
 obj-$(CONFIG_SND_SOC_SOF_MT8186) += mt8186/
+obj-$(CONFIG_SND_SOC_SOF_MT8196) += mt8196/
diff --git a/sound/soc/sof/mediatek/mt8196/Makefile b/sound/soc/sof/mediatek/mt8196/Makefile
new file mode 100644
index 000000000000..c9d10374b900
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+snd-sof-mt8196-objs := mt8196.o mt8196-clk.o mt8196-loader.o
+obj-$(CONFIG_SND_SOC_SOF_MT8196) += snd-sof-mt8196.o
+
diff --git a/sound/soc/sof/mediatek/mt8196/mt8196-clk.c b/sound/soc/sof/mediatek/mt8196/mt8196-clk.c
new file mode 100644
index 000000000000..80ea24ce4722
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/mt8196-clk.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Hailong Fan <hailong.fan at mediatek.com>
+ */
+
+// Hardware interface for mt8196 DSP clock
+
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include "../../sof-audio.h"
+#include "../../ops.h"
+#include "../adsp_helper.h"
+#include "mt8196.h"
+#include "mt8196-clk.h"
+
+static const char *adsp_clks[ADSP_CLK_MAX] = {
+	[CLK_TOP_ADSP_SEL] = "clk_top_adsp_sel",
+	[CLK_TOP_CLK26M] = "clk_top_clk26m",
+	[CLK_TOP_ADSPPLL] = "clk_top_adsppll",
+
+};
+
+int mt8196_adsp_init_clock(struct snd_sof_dev *sdev)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+	struct device *dev = sdev->dev;
+	int i;
+
+	priv->clk = devm_kcalloc(dev, ADSP_CLK_MAX, sizeof(*priv->clk), GFP_KERNEL);
+	if (!priv->clk)
+		return -ENOMEM;
+
+	for (i = 0; i < ADSP_CLK_MAX; i++) {
+		priv->clk[i] = devm_clk_get(dev, adsp_clks[i]);
+
+		if (IS_ERR(priv->clk[i]))
+			return PTR_ERR(priv->clk[i]);
+	}
+
+	return 0;
+}
+
+static int adsp_enable_all_clock(struct snd_sof_dev *sdev)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+	struct device *dev = sdev->dev;
+	int ret;
+
+	ret = clk_prepare_enable(priv->clk[CLK_TOP_ADSP_SEL]);
+	if (ret) {
+		dev_err(dev, "%s clk_prepare_enable(audiodsp) fail %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void adsp_disable_all_clock(struct snd_sof_dev *sdev)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	clk_disable_unprepare(priv->clk[CLK_TOP_ADSP_SEL]);
+}
+
+int mt8196_adsp_clock_on(struct snd_sof_dev *sdev)
+{
+	struct device *dev = sdev->dev;
+	int ret;
+
+	ret = adsp_enable_all_clock(sdev);
+	if (ret) {
+		dev_err(dev, "failed to adsp_enable_clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CK_EN,
+				      UART_BT_EN | DMA_AXI_EN | DMA1_EN,
+				      UART_BT_EN | DMA_AXI_EN | DMA1_EN);
+	if (ret < 0)
+		dev_err(sdev->dev, "Failed to update CK register: %d\n", ret);
+
+	ret = snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_UART_CTRL,
+				      UART_BCLK_CG | UART_RSTN,
+				      UART_BCLK_CG | UART_RSTN);
+	if (ret < 0)
+		dev_err(sdev->dev, "Failed to update UART register: %d\n", ret);
+
+
+	return 0;
+}
+
+void mt8196_adsp_clock_off(struct snd_sof_dev *sdev)
+{
+	snd_sof_dsp_write(sdev, DSP_REG_BAR, ADSP_UART_CTRL, 0);
+	adsp_disable_all_clock(sdev);
+}
+
diff --git a/sound/soc/sof/mediatek/mt8196/mt8196-clk.h b/sound/soc/sof/mediatek/mt8196/mt8196-clk.h
new file mode 100644
index 000000000000..766db95c9517
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/mt8196-clk.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Hailong Fan <hailong.fan at mediatek.com>
+ */
+
+#ifndef __MT8196_CLK_H
+#define __MT8196_CLK_H
+
+struct snd_sof_dev;
+
+/* DSP clock */
+enum adsp_clk_id {
+	CLK_TOP_ADSP_SEL,
+	CLK_TOP_CLK26M,
+	CLK_TOP_ADSPPLL,
+	ADSP_CLK_MAX
+};
+
+int mt8196_adsp_init_clock(struct snd_sof_dev *sdev);
+int mt8196_adsp_clock_on(struct snd_sof_dev *sdev);
+void mt8196_adsp_clock_off(struct snd_sof_dev *sdev);
+#endif
diff --git a/sound/soc/sof/mediatek/mt8196/mt8196-loader.c b/sound/soc/sof/mediatek/mt8196/mt8196-loader.c
new file mode 100644
index 000000000000..7053e5ca3c3f
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/mt8196-loader.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Hailong Fan <hailong.fan at mediatek.com>
+ */
+
+// Hardware interface for mt8196 DSP code loader
+
+#include <sound/sof.h>
+#include "mt8196.h"
+#include "../../ops.h"
+
+void mt8196_sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
+{
+	/* step1. clr ADSP_ALTVEC_C0 */
+	snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVEC_C0, 0);
+	snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVECSEL, 0);
+
+	/* step2. set core boot address */
+	snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVEC_C0, boot_addr);
+	snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVECSEL, ADSP_ALTVECSEL_C0);
+
+	/* step3. set RUNSTALL to stop core */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_RUNSTALL,
+				RUNSTALL, RUNSTALL);
+
+	/* enable mbox 0 & 1 IRQ */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_MBOX_IRQ_EN,
+				DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN,
+				DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN);
+
+	/* step4. assert core reset */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CFGREG_SW_RSTN,
+				SW_RSTN_C0 | SW_DBG_RSTN_C0,
+				SW_RSTN_C0 | SW_DBG_RSTN_C0);
+
+	/* hardware requirement */
+	udelay(1);
+
+	/* step5. release core reset */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CFGREG_SW_RSTN,
+				SW_RSTN_C0 | SW_DBG_RSTN_C0,
+				0);
+
+	/* step6. clear RUNSTALL to start core */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_RUNSTALL,
+				RUNSTALL, 0);
+}
+
+void mt8196_sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
+{
+	/* set RUNSTALL to stop core */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_RUNSTALL,
+				RUNSTALL, RUNSTALL);
+
+	/* assert core reset */
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CFGREG_SW_RSTN,
+				SW_RSTN_C0 | SW_DBG_RSTN_C0,
+				SW_RSTN_C0 | SW_DBG_RSTN_C0);
+}
+
diff --git a/sound/soc/sof/mediatek/mt8196/mt8196.c b/sound/soc/sof/mediatek/mt8196/mt8196.c
new file mode 100644
index 000000000000..364069ce9954
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/mt8196.c
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Hailong Fan <hailong.fan at mediatek.com>
+ */
+
+/*
+ * Hardware interface for audio DSP on mt8196
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/module.h>
+
+#include <sound/sof.h>
+#include <sound/sof/xtensa.h>
+#include "../../ops.h"
+#include "../../sof-of-dev.h"
+#include "../../sof-audio.h"
+#include "../adsp_helper.h"
+#include "../mtk-adsp-common.h"
+#include "mt8196.h"
+#include "mt8196-clk.h"
+
+static void sof_reg_write_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset, u32 value,
+				u8 bits, u8 len)
+{
+	u32 mask, val;
+	int ret;
+
+	mask = GENMASK(len + bits - 1, bits);
+	val = (value << bits) & mask;
+
+	ret = snd_sof_dsp_update_bits(sdev, bar, offset, mask, val);
+	if (ret < 0)
+		dev_err(sdev->dev, "Failed to update DSP register: %d\n", ret);
+}
+
+static u32 reg_read_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset, u8 bits, u8 len)
+{
+	u32 target_bit_field, curr_value;
+
+	target_bit_field = GENMASK(len + bits - 1, bits);
+	curr_value = snd_sof_dsp_read(sdev, bar, offset);
+
+	return (curr_value & target_bit_field) >> bits;
+}
+
+static int mt8196_get_mailbox_offset(struct snd_sof_dev *sdev)
+{
+	return MBOX_OFFSET;
+}
+
+static int mt8196_get_window_offset(struct snd_sof_dev *sdev, u32 id)
+{
+	return MBOX_OFFSET;
+}
+
+static int mt8196_send_msg(struct snd_sof_dev *sdev,
+			   struct snd_sof_ipc_msg *msg)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+			  msg->msg_size);
+
+	return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ);
+}
+
+static void mt8196_dsp_handle_reply(struct mtk_adsp_ipc *ipc)
+{
+	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
+	snd_sof_ipc_process_reply(priv->sdev, 0);
+	spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
+}
+
+static void mt8196_dsp_handle_request(struct mtk_adsp_ipc *ipc)
+{
+	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
+	u32 p; /* panic code */
+	int ret;
+
+	/* Read the message from the debug box. */
+	sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + sizeof(u32),
+			 &p, sizeof(p));
+
+	/* Check to see if the message is a panic code 0x0dead*** */
+	if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+		snd_sof_dsp_panic(priv->sdev, p, true);
+	} else {
+		snd_sof_ipc_msgs_rx(priv->sdev);
+
+		/* tell DSP cmd is done */
+		ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP);
+		if (ret)
+			dev_err(priv->dev, "request send ipc failed");
+	}
+}
+
+static struct mtk_adsp_ipc_ops dsp_ops = {
+	.handle_reply		= mt8196_dsp_handle_reply,
+	.handle_request		= mt8196_dsp_handle_request,
+};
+
+static int platform_parse_resource(struct platform_device *pdev, void *data)
+{
+	struct resource *mmio;
+	struct resource res;
+	struct device_node *mem_region;
+	struct device *dev = &pdev->dev;
+	struct mtk_adsp_chip_info *adsp = data;
+	int ret;
+
+	ret = of_reserved_mem_device_init(dev);
+	if (ret) {
+		dev_err(dev, "of_reserved_mem_device_init failed\n");
+		return ret;
+	}
+
+	mem_region = of_parse_phandle(dev->of_node, "memory-region", 1);
+	if (!mem_region) {
+		dev_err(dev, "no memory-region sysmem phandle\n");
+		return -ENODEV;
+	}
+
+	ret = of_address_to_resource(mem_region, 0, &res);
+	of_node_put(mem_region);
+	if (ret) {
+		dev_err(dev, "of_address_to_resource sysmem failed\n");
+		return ret;
+	}
+
+	adsp->pa_dram = (phys_addr_t)res.start;
+	if (adsp->pa_dram & DRAM_REMAP_MASK) {
+		dev_err(dev, "adsp memory(%#x) is not 4K-aligned\n",
+			(u32)adsp->pa_dram);
+		return -EINVAL;
+	}
+
+	adsp->dramsize = resource_size(&res);
+	if (adsp->dramsize < TOTAL_SIZE_SHARED_DRAM_FROM_TAIL) {
+		dev_err(dev, "adsp memory(%#x) is not enough for share\n",
+			adsp->dramsize);
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "dram pbase=%pa size=%#x\n", &adsp->pa_dram, adsp->dramsize);
+
+	mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+	if (!mmio) {
+		dev_err(dev, "no ADSP-CFG register resource\n");
+		return -ENXIO;
+	}
+
+	adsp->va_cfgreg = devm_ioremap_resource(dev, mmio);
+	if (IS_ERR(adsp->va_cfgreg))
+		return PTR_ERR(adsp->va_cfgreg);
+
+	adsp->pa_cfgreg = (phys_addr_t)mmio->start;
+	adsp->cfgregsize = resource_size(mmio);
+
+	mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
+	if (!mmio) {
+		dev_err(dev, "no SRAM resource\n");
+		return -ENXIO;
+	}
+
+	adsp->pa_sram = (phys_addr_t)mmio->start;
+	adsp->sramsize = resource_size(mmio);
+
+	dev_dbg(dev, "sram pbase=%pa size=%#x\n", &adsp->pa_sram, adsp->sramsize);
+
+	mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sec");
+	if (!mmio) {
+		dev_err(dev, "no SEC register resource\n");
+		return -ENXIO;
+	}
+
+	adsp->va_secreg = devm_ioremap_resource(dev, mmio);
+	if (IS_ERR(adsp->va_secreg))
+		return PTR_ERR(adsp->va_secreg);
+
+	adsp->pa_secreg = (phys_addr_t)mmio->start;
+	adsp->secregsize = resource_size(mmio);
+
+	dev_dbg(dev, "secreg pbase=%pa size=%#x\n", &adsp->pa_secreg, adsp->secregsize);
+
+	mmio = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bus");
+	if (!mmio) {
+		dev_err(dev, "no BUS register resource\n");
+		return -ENXIO;
+	}
+
+	adsp->va_busreg = devm_ioremap_resource(dev, mmio);
+	if (IS_ERR(adsp->va_busreg))
+		return PTR_ERR(adsp->va_busreg);
+
+	adsp->pa_busreg = (phys_addr_t)mmio->start;
+	adsp->busregsize = resource_size(mmio);
+
+	dev_dbg(dev, "busreg pbase=%pa, vbase=%pa, size=%#x\n", &adsp->pa_busreg,
+		&adsp->va_busreg, adsp->busregsize);
+
+	return 0;
+}
+
+static void adsp_sram_power_on(struct snd_sof_dev *sdev)
+{
+	int i;
+
+	for (i = 0; i < ADSP_SRAM_CHANNEL_NUM; i++) {
+		sof_reg_write_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_CON, 0, i, 1);
+		while (1) {
+			if (reg_read_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_ACK, i, 1) == 0)
+				break;
+		}
+	}
+}
+
+static void adsp_sram_power_off(struct snd_sof_dev *sdev)
+{
+	int i;
+
+	for (i = 0; i < ADSP_SRAM_CHANNEL_NUM; i++) {
+		sof_reg_write_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_CON, 1, i, 1);
+		while (1) {
+			if (reg_read_bits(sdev, DSP_BUSREG_BAR, ADSP_SRAM_POOL_ACK, i, 1) == 1)
+				break;
+		}
+	}
+}
+
+/*  Init the basic DSP DRAM address */
+static int adsp_memory_remap_init(struct snd_sof_dev *sdev, struct mtk_adsp_chip_info *adsp)
+{
+	u32 from, to;
+
+	from = ADSP_REMAP_REGION_FROM(DRAM_PHYS_BASE_FROM_DSP_VIEW, DSP_DRAM_SIZE);
+	to = (u32)ADSP_REMAP_REGION_TO(adsp->pa_dram);
+
+	snd_sof_dsp_write(sdev, DSP_BUSREG_BAR, AUDIO_BUS_CFG_RSV_10, from);
+	snd_sof_dsp_write(sdev, DSP_BUSREG_BAR, DSP_C0_EMI_MAP_ADDR, to);
+
+	snd_sof_dsp_update_bits(sdev, DSP_BUSREG_BAR, AUDIO_BUS_CFG_BUS_REMAP_CTRL, 1, 1);
+
+	return 0;
+}
+
+static int mt8196_run(struct snd_sof_dev *sdev)
+{
+	u32 adsp_bootup_addr;
+
+	adsp_bootup_addr = SRAM_PHYS_BASE_FROM_DSP_VIEW;
+	dev_dbg(sdev->dev, "HIFIxDSP boot from base : 0x%08X\n", adsp_bootup_addr);
+	mt8196_sof_hifixdsp_boot_sequence(sdev, adsp_bootup_addr);
+
+	return 0;
+}
+
+static int mt8196_dsp_probe(struct snd_sof_dev *sdev)
+{
+	struct platform_device *pdev = container_of(sdev->dev, struct platform_device, dev);
+	struct adsp_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	sdev->pdata->hw_pdata = priv;
+	priv->dev = sdev->dev;
+	priv->sdev = sdev;
+
+	priv->adsp = devm_kzalloc(&pdev->dev, sizeof(struct mtk_adsp_chip_info), GFP_KERNEL);
+	if (!priv->adsp)
+		return -ENOMEM;
+
+	ret = platform_parse_resource(pdev, priv->adsp);
+	if (ret)
+		return ret;
+
+	sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev,
+						       priv->adsp->pa_sram,
+						       priv->adsp->sramsize);
+	if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) {
+		dev_err(sdev->dev, "failed to ioremap base %pa size %#x\n",
+			&priv->adsp->pa_sram, priv->adsp->sramsize);
+		return -ENOMEM;
+	}
+
+	priv->adsp->va_sram = sdev->bar[SOF_FW_BLK_TYPE_IRAM];
+	dev_dbg(sdev->dev, "pa_sram %pa,va: %pa, size %#x\n",
+			&priv->adsp->pa_sram, &priv->adsp->va_sram, priv->adsp->sramsize);
+
+	sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap(sdev->dev,
+						       priv->adsp->pa_dram,
+						       priv->adsp->dramsize);
+
+	if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) {
+		dev_err(sdev->dev, "failed to ioremap base %pa size %#x\n",
+			&priv->adsp->pa_dram, priv->adsp->dramsize);
+		return -ENOMEM;
+	}
+
+	priv->adsp->va_dram = sdev->bar[SOF_FW_BLK_TYPE_SRAM];
+
+	dev_dbg(sdev->dev, "pa_dram %pa, va: %pa, size %#x\n",
+			&priv->adsp->pa_dram, &priv->adsp->va_dram, priv->adsp->dramsize);
+
+
+	sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg;
+	sdev->bar[DSP_SECREG_BAR] = priv->adsp->va_secreg;
+	sdev->bar[DSP_BUSREG_BAR] = priv->adsp->va_busreg;
+
+	sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM;
+	sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
+
+	/* set default mailbox offset for FW ready message */
+	sdev->dsp_box.offset = mt8196_get_mailbox_offset(sdev);
+
+	/* enable adsp clock before touching registers */
+	ret = mt8196_adsp_init_clock(sdev);
+	if (ret) {
+		dev_err(sdev->dev, "mt8196_adsp_init_clock failed\n");
+		return ret;
+	}
+
+	ret = mt8196_adsp_clock_on(sdev);
+	if (ret) {
+		dev_err(sdev->dev, "mt8196_adsp_clock_on fail!\n");
+		return ret;
+	}
+
+	ret = adsp_memory_remap_init(sdev, priv->adsp);
+	if (ret) {
+		dev_err(sdev->dev, "adsp_memory_remap_init fail!\n");
+		return ret;
+	}
+
+	adsp_sram_power_on(sdev);
+
+	priv->ipc_dev = platform_device_register_data(&pdev->dev, "mtk-adsp-ipc",
+						      PLATFORM_DEVID_NONE,
+						      pdev, sizeof(*pdev));
+	if (IS_ERR(priv->ipc_dev)) {
+		ret = PTR_ERR(priv->ipc_dev);
+		dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n");
+		goto err_adsp_off;
+	}
+
+	priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev);
+	if (!priv->dsp_ipc) {
+		ret = -EPROBE_DEFER;
+		dev_err(sdev->dev, "failed to get drvdata\n");
+		goto exit_pdev_unregister;
+	}
+
+	mtk_adsp_ipc_set_data(priv->dsp_ipc, priv);
+	priv->dsp_ipc->ops = &dsp_ops;
+
+	return 0;
+
+exit_pdev_unregister:
+	platform_device_unregister(priv->ipc_dev);
+err_adsp_off:
+	adsp_sram_power_off(sdev);
+	mt8196_adsp_clock_off(sdev);
+
+	return ret;
+}
+
+static void mt8196_dsp_remove(struct snd_sof_dev *sdev)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	platform_device_unregister(priv->ipc_dev);
+	mt8196_sof_hifixdsp_shutdown(sdev);
+	adsp_sram_power_off(sdev);
+	mt8196_adsp_clock_off(sdev);
+}
+
+static int mt8196_dsp_shutdown(struct snd_sof_dev *sdev)
+{
+	return snd_sof_suspend(sdev->dev);
+}
+
+static int mt8196_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_IO_CONFIG, ADSP_CLK_SEL, 0);
+	clk_set_parent(priv->clk[CLK_TOP_ADSP_SEL], priv->clk[CLK_TOP_CLK26M]);
+	mt8196_sof_hifixdsp_shutdown(sdev);
+	adsp_sram_power_off(sdev);
+	mt8196_adsp_clock_off(sdev);
+
+	return 0;
+}
+
+static int mt8196_dsp_resume(struct snd_sof_dev *sdev)
+{
+	int ret;
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	ret = mt8196_adsp_clock_on(sdev);
+	if (ret) {
+		dev_err(sdev->dev, "mt8196_adsp_clock_on fail!");
+		return ret;
+	}
+
+	clk_set_parent(priv->clk[CLK_TOP_ADSP_SEL], priv->clk[CLK_TOP_ADSPPLL]);
+	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_IO_CONFIG, ADSP_CLK_SEL, BIT(31));
+	adsp_sram_power_on(sdev);
+
+	return 0;
+}
+
+/* on mt8196 there is 1 to 1 match between type and BAR idx */
+static int mt8196_get_bar_index(struct snd_sof_dev *sdev, u32 type)
+{
+	return type;
+}
+
+static int mt8196_pcm_hw_params(struct snd_sof_dev *sdev,
+				struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_sof_platform_stream_params *platform_params)
+{
+	platform_params->cont_update_posn = 1;
+
+	return 0;
+}
+
+static snd_pcm_uframes_t mt8196_pcm_pointer(struct snd_sof_dev *sdev,
+					    struct snd_pcm_substream *substream)
+{
+	int ret;
+	snd_pcm_uframes_t pos;
+	struct snd_sof_pcm *spcm;
+	struct sof_ipc_stream_posn posn;
+	struct snd_sof_pcm_stream *stream;
+	struct snd_soc_component *scomp = sdev->component;
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+
+	spcm = snd_sof_find_spcm_dai(scomp, rtd);
+	if (!spcm) {
+		dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
+				     rtd->dai_link->id);
+		return 0;
+	}
+
+	stream = &spcm->stream[substream->stream];
+	ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
+	if (ret < 0) {
+		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
+		return 0;
+	}
+
+	memcpy(&stream->posn, &posn, sizeof(posn));
+	pos = spcm->stream[substream->stream].posn.host_posn;
+	pos = bytes_to_frames(substream->runtime, pos);
+
+	return pos;
+}
+
+static void mt8196_adsp_dump(struct snd_sof_dev *sdev, u32 flags)
+{
+	u32 dbg_pc, dbg_data, dbg_inst, dbg_ls0stat, dbg_status, faultinfo;
+
+	/* dump debug registers */
+	dbg_pc = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGPC);
+	dbg_data = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGDATA);
+	dbg_inst = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGINST);
+	dbg_ls0stat = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGLS0STAT);
+	dbg_status = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGSTATUS);
+	faultinfo = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PFAULTINFO);
+
+	dev_info(sdev->dev, "adsp dump : pc %#x, data %#x, dbg_inst %#x,",
+		 dbg_pc, dbg_data, dbg_inst);
+	dev_info(sdev->dev, "ls0stat %#x, status %#x, faultinfo %#x",
+		 dbg_ls0stat, dbg_status, faultinfo);
+
+	mtk_adsp_dump(sdev, flags);
+}
+
+/*
+ * DL_24CH, DL1, UL0, UL1, UL2 are registered as SOF FE, so creating the corresponding
+ * SOF BE to complete the pipeline.
+ */
+static struct snd_soc_dai_driver mt8196_dai[] = {
+{
+	.name = "SOF_DL_24CH",
+	.playback = {
+		.channels_min = CHAN_MIN,
+		.channels_max = CHAN_MAX,
+	},
+},
+{
+	.name = "SOF_DL1",
+	.playback = {
+		.channels_min = CHAN_MIN,
+		.channels_max = CHAN_MAX,
+	},
+},
+{
+	.name = "SOF_UL0",
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 2,
+	},
+},
+{
+	.name = "SOF_UL1",
+	.capture = {
+		.channels_min = CHAN_MIN,
+		.channels_max = CHAN_MAX,
+	},
+},
+{
+	.name = "SOF_UL2",
+	.capture = {
+		.channels_min = CHAN_MIN,
+		.channels_max = CHAN_MAX,
+	},
+},
+};
+
+/* mt8196 ops */
+static struct snd_sof_dsp_ops sof_mt8196_ops = {
+	/* probe and remove */
+	.probe		= mt8196_dsp_probe,
+	.remove		= mt8196_dsp_remove,
+	.shutdown	= mt8196_dsp_shutdown,
+
+	/* DSP core boot */
+	.run		= mt8196_run,
+
+	/* Block IO */
+	.block_read	= sof_block_read,
+	.block_write	= sof_block_write,
+
+	/* Mailbox IO */
+	.mailbox_read	= sof_mailbox_read,
+	.mailbox_write	= sof_mailbox_write,
+
+	/* Register IO */
+	.write		= sof_io_write,
+	.read		= sof_io_read,
+	.write64	= sof_io_write64,
+	.read64		= sof_io_read64,
+
+	/* ipc */
+	.send_msg		= mt8196_send_msg,
+	.get_mailbox_offset	= mt8196_get_mailbox_offset,
+	.get_window_offset	= mt8196_get_window_offset,
+	.ipc_msg_data		= sof_ipc_msg_data,
+	.set_stream_data_offset = sof_set_stream_data_offset,
+
+	/* misc */
+	.get_bar_index	= mt8196_get_bar_index,
+
+	/* stream callbacks */
+	.pcm_open	= sof_stream_pcm_open,
+	.pcm_hw_params	= mt8196_pcm_hw_params,
+	.pcm_pointer	= mt8196_pcm_pointer,
+	.pcm_close	= sof_stream_pcm_close,
+
+	/* firmware loading */
+	.load_firmware	= snd_sof_load_firmware_memcpy,
+
+	/* Firmware ops */
+	.dsp_arch_ops = &sof_xtensa_arch_ops,
+
+	/* DAI drivers */
+	.drv		= mt8196_dai,
+	.num_drv	= ARRAY_SIZE(mt8196_dai),
+
+	/* Debug information */
+	.dbg_dump = mt8196_adsp_dump,
+	.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
+
+	/* PM */
+	.suspend	= mt8196_dsp_suspend,
+	.resume		= mt8196_dsp_resume,
+
+	/* ALSA HW info flags */
+	.hw_info =	SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_PAUSE |
+			SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
+};
+
+static struct snd_sof_of_mach sof_mt8196_machs[] = {
+	{
+		.compatible = "mediatek,mt8196",
+		.sof_tplg_filename = "sof-mt8196.tplg",
+	},
+	{}
+};
+
+static const struct sof_dev_desc sof_of_mt8196_desc = {
+	.of_machines = sof_mt8196_machs,
+	.ipc_supported_mask	= BIT(SOF_IPC_TYPE_3),
+	.ipc_default		= SOF_IPC_TYPE_3,
+	.default_fw_path = {
+		[SOF_IPC_TYPE_3] = "mediatek/sof",
+	},
+	.default_tplg_path = {
+		[SOF_IPC_TYPE_3] = "mediatek/sof-tplg",
+	},
+	.default_fw_filename = {
+		[SOF_IPC_TYPE_3] = "sof-mt8196.ri",
+	},
+	.nocodec_tplg_filename = "sof-mt8196-nocodec.tplg",
+	.ops = &sof_mt8196_ops,
+};
+
+static const struct of_device_id sof_of_mt8196_ids[] = {
+	{ .compatible = "mediatek,mt8196-dsp", .data = &sof_of_mt8196_desc},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sof_of_mt8196_ids);
+
+/* DT driver definition */
+static struct platform_driver snd_sof_of_mt8196_driver = {
+	.probe = sof_of_probe,
+	.remove = sof_of_remove,
+	.shutdown = sof_of_shutdown,
+	.driver = {
+	.name = "sof-audio-of-mt8196",
+		.pm = &sof_of_pm,
+		.of_match_table = sof_of_mt8196_ids,
+	},
+};
+module_platform_driver(snd_sof_of_mt8196_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("SOF support for MT8196 platforms");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_MTK_COMMON");
diff --git a/sound/soc/sof/mediatek/mt8196/mt8196.h b/sound/soc/sof/mediatek/mt8196/mt8196.h
new file mode 100644
index 000000000000..ac2d5a7683e1
--- /dev/null
+++ b/sound/soc/sof/mediatek/mt8196/mt8196.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Hailong Fan <hailong.fan at mediatek.com>
+ */
+
+#ifndef __MT8196_H
+#define __MT8196_H
+
+struct mtk_adsp_chip_info;
+struct snd_sof_dev;
+
+#define DSP_REG_BAR			4
+#define DSP_SECREG_BAR			5
+#define DSP_BUSREG_BAR			6
+#define CHAN_MIN			1
+#define CHAN_MAX			2
+
+/*****************************************************************************
+ *                  R E G I S T E R       TABLE
+ *****************************************************************************/
+/* dsp cfg */
+#define ADSP_CFGREG_SW_RSTN		0x0000
+#define SW_DBG_RSTN_C0			BIT(0)
+#define SW_RSTN_C0			BIT(4)
+#define ADSP_IO_CONFIG			0x000C
+#define ADSP_CLK_SEL			BIT(31)
+#define ADSP_HIFI_RUNSTALL		0x0108
+#define TRACEMEMREADY			BIT(15)
+#define RUNSTALL			BIT(12)
+#define ADSP_IRQ_MASK			0x0030
+#define ADSP_DVFSRC_REQ			0x0040
+#define ADSP_DDREN_REQ_0		0x0044
+#define ADSP_SEMAPHORE			0x0064
+#define ADSP_WDT_CON_C0			0x007C
+#define ADSP_MBOX_IRQ_EN		0x009C
+#define DSP_MBOX0_IRQ_EN		BIT(0)
+#define DSP_MBOX1_IRQ_EN		BIT(1)
+#define DSP_MBOX2_IRQ_EN		BIT(2)
+#define DSP_MBOX3_IRQ_EN		BIT(3)
+#define DSP_MBOX4_IRQ_EN		BIT(4)
+#define DSP_PDEBUGPC			0x013C
+#define DSP_PDEBUGDATA			0x0140
+#define DSP_PDEBUGINST			0x0144
+#define DSP_PDEBUGLS0STAT		0x0148
+#define DSP_PDEBUGSTATUS		0x014C
+#define DSP_PFAULTINFO			0x0150
+#define ADSP_CK_EN			0x1000
+#define DMA1_EN				BIT(12)
+#define DMA_AXI_EN			BIT(13)
+#define UART_BT_EN			BIT(14)
+#define DMA_EN				BIT(4)
+#define UART_EN				BIT(5)
+#define ADSP_UART_CTRL			0x1010
+#define UART_BCLK_CG			BIT(0)
+#define UART_RSTN			BIT(3)
+
+/* dsp sec */
+#define ADSP_PRID			0x0
+#define ADSP_ALTVEC_C0			0x04
+#define ADSP_ALTVECSEL			0x0C
+#define MT8196_ADSP_ALTVECSEL_C0	1
+
+#define ADSP_ALTVECSEL_C0		MT8196_ADSP_ALTVECSEL_C0
+
+/* dsp bus */
+#define AUDIO_BUS_CFG_RSV_10		0x30
+#define ADSP_SRAM_POOL_CON		0x190
+#define ADSP_SRAM_POOL_ACK		0x1A0
+#define ADSP_SRAM_CHANNEL_NUM		6
+#define DSP_SRAM_POOL_PD_MASK		0xF00F /* [0:3] and [12:15] */
+#define DSP_C0_EMI_MAP_ADDR		0xA00  /* ADSP Core0 To EMI Address Remap */
+#define DSP_C0_DMAEMI_MAP_ADDR		0xA08  /* DMA0 To EMI Address Remap */
+#define AUDIO_BUS_CFG_BUS_REMAP_CTRL  0x016C
+#define AUDIO_BUS_DSP2EMI_REMAP0      0x0A00
+#define AUDIO_BUS_DSP2EMI_REMAP1      0x0A04
+#define AUDIO_BUS_DMA2EMI_REMAP0      0x0A08
+#define AUDIO_BUS_DMA2EMI_REMAP1      0x0A0C
+
+/* DSP memories */
+#define MBOX_OFFSET			0x500000 /* DRAM */
+#define MBOX_SIZE			0x1000   /* consistent with which in memory.h of sof fw */
+#define DSP_DRAM_SIZE			0x900000 /* 9M */
+
+/*remap dram between AP and DSP view, 4KB aligned*/
+#define SRAM_PHYS_BASE_FROM_DSP_VIEW	0x4e100000 /* MT8196 DSP view */
+#define DRAM_PHYS_BASE_FROM_DSP_VIEW	0x90000000 /* MT8196 DSP view */
+#define DRAM_REMAP_SHIFT		12
+#define DRAM_REMAP_MASK			0xFFF
+ /* remap */
+#define ADSP_REMAP_REGION
+#define ADSP_EMI_REMAP_SET_TOTAL    (4)
+#define EMI_REMAP_REGION			(AUDIO_BUS_CFG_RSV_10)
+#define EMI_REMAP_REPLACE			(AUDIO_BUS_DSP2EMI_REMAP0)
+#define EMI_REMAP_EN				(1U)
+#define ROUNDUP(a, b)				(((a) + ((b)-1)) & ~((b)-1))
+#define MIX_BEGIN_AND_END_ADDR(begin, end)		\
+					(((begin >> 16) & 0xFFFF) | (end & 0xFFFF0000))
+#define ADSP_REMAP_REGION_FROM(start, size)		MIX_BEGIN_AND_END_ADDR(start, \
+							ROUNDUP((start + size), 0x10000))
+#define ADSP_REMAP_REGION_TO(start)		((start >> 25) << 9)
+
+#define SIZE_SHARED_DRAM_DL			0x40000 /*Shared buffer for Downlink*/
+#define SIZE_SHARED_DRAM_UL			0x40000 /*Shared buffer for Uplink*/
+#define TOTAL_SIZE_SHARED_DRAM_FROM_TAIL	(SIZE_SHARED_DRAM_DL + SIZE_SHARED_DRAM_UL)
+
+void mt8196_sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr);
+void mt8196_sof_hifixdsp_shutdown(struct snd_sof_dev *sdev);
+#endif
-- 
2.45.2



From hailong.fan at mediatek.com  Wed Mar 19 20:17:23 2025
From: hailong.fan at mediatek.com (hailong.fan)
Date: Thu, 20 Mar 2025 11:17:23 +0800
Subject: [PATCH 0/2] ASoC: mediatek: Add support of SOF on Mediatek mt8196 SoC.
Message-ID: <20250320031753.13669-1-hailong.fan@mediatek.com>

Add support of MediaTek mt8196 SoC DSP to SOF.
This series is based on linux-next, tag: next-20250319.

---
This series patches dependent on:
[1]
https://lore.kernel.org/all/20250307032942.10447-1-guangjie.song at mediatek.com/
[2]
https://lore.kernel.org/all/20250307034454.12243-1-guangjie.song at mediatek.com/

hailong.fan (2):
  ASoC: SOF: MediaTek: Add mt8196 hardware support
  dt-bindings: dsp: mediatek: add mt8196 dsp document

 .../bindings/dsp/mediatek,mt8196-dsp.yaml     |  96 +++
 sound/soc/sof/mediatek/Kconfig                |   9 +
 sound/soc/sof/mediatek/Makefile               |   1 +
 sound/soc/sof/mediatek/mt8196/Makefile        |   4 +
 sound/soc/sof/mediatek/mt8196/mt8196-clk.c    | 100 +++
 sound/soc/sof/mediatek/mt8196/mt8196-clk.h    |  23 +
 sound/soc/sof/mediatek/mt8196/mt8196-loader.c |  61 ++
 sound/soc/sof/mediatek/mt8196/mt8196.c        | 650 ++++++++++++++++++
 sound/soc/sof/mediatek/mt8196/mt8196.h        | 109 +++
 9 files changed, 1053 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
 create mode 100644 sound/soc/sof/mediatek/mt8196/Makefile
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-clk.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-clk.h
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196-loader.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196.c
 create mode 100644 sound/soc/sof/mediatek/mt8196/mt8196.h

-- 
2.45.2



From hailong.fan at mediatek.com  Wed Mar 19 20:17:25 2025
From: hailong.fan at mediatek.com (hailong.fan)
Date: Thu, 20 Mar 2025 11:17:25 +0800
Subject: [PATCH 2/2] dt-bindings: dsp: mediatek: add mt8196 dsp document
In-Reply-To: <20250320031753.13669-1-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
Message-ID: <20250320031753.13669-3-hailong.fan@mediatek.com>

This patch adds mt8196 dsp document. The dsp is used for Sound Open
Firmware driver node. It includes registers,  clocks, memory regions,
and mailbox for dsp.

Signed-off-by: hailong.fan <hailong.fan at mediatek.com>
---
 .../bindings/dsp/mediatek,mt8196-dsp.yaml     | 96 +++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml

diff --git a/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
new file mode 100644
index 000000000000..62bcd97bd0f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dsp/mediatek,mt8196-dsp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek mt8196 DSP core
+
+maintainers:
+  - Hailong Fan <hailong.fan at mediatek.com>
+
+description: |
+  Some boards from mt8196 contain a DSP core used for
+  advanced pre- and post- audio processing.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-dsp
+
+  reg:
+    items:
+      - description: Address and size of the DSP Cfg registers
+      - description: Address and size of the DSP SRAM
+      - description: Address and size of the DSP secure registers
+      - description: Address and size of the DSP bus registers
+
+  reg-names:
+    items:
+      - const: cfg
+      - const: sram
+      - const: sec
+      - const: bus
+
+  clocks:
+    items:
+      - description: mux for dsp clock
+      - description: 26M clock
+      - description: ADSP PLL clock
+
+  clock-names:
+    items:
+      - const: adsp_sel
+      - const: clk26m
+      - const: adsppll
+
+  power-domains:
+    maxItems: 1
+
+  mboxes:
+    items:
+      - description: mailbox for receiving audio DSP requests.
+      - description: mailbox for transmitting requests to audio DSP.
+
+  mbox-names:
+    items:
+      - const: rx
+      - const: tx
+
+  memory-region:
+    items:
+      - description: dma buffer between host and DSP.
+      - description: DSP system memory.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - power-domains
+  - mbox-names
+  - mboxes
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt8196-clk.h>
+    #include <dt-bindings/power/mt8196-power.h>
+    adsp: adsp at 1a000000 {
+        compatible = "mediatek,mt8196-dsp";
+        reg = <0x1a000000 0x5000>,
+              <0x1a210000 0x80000>,
+              <0x1a345000 0x300>,
+              <0x1a00f000 0x1000>;
+        reg-names = "cfg", "sram", "sec", "bus";
+        power-domains = <&scpsys MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT>;
+        clocks = <&cksys_clk CLK_CK_ADSP_SEL>,
+                 <&cksys_clk CLK_CK_TCK_26M_MX9>,
+                 <&cksys_clk CLK_CK_ADSPPLL>;
+        clock-names = "adsp_sel",
+                      "clk26m",
+                      "adsppll";
+        mbox-names = "rx", "tx";
+        mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
+    };
-- 
2.45.2



From maobibo at loongson.cn  Wed Mar 19 20:30:43 2025
From: maobibo at loongson.cn (bibo mao)
Date: Thu, 20 Mar 2025 11:30:43 +0800
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <Z9nMHW-OqTLEqDRs@linux.dev>
References: <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org> <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org> <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com> <ed25f5a6-dad6-4b5e-b42b-58e6ced6c7a2@redhat.com>
 <Z9nMHW-OqTLEqDRs@linux.dev>
Message-ID: <bbb361bd-6cb8-7b9d-f689-d52bb1a05605@loongson.cn>



On 2025/3/19 ??3:40, Oliver Upton wrote:
> On Tue, Mar 18, 2025 at 08:35:38PM +0100, David Hildenbrand wrote:
>> On 18.03.25 20:27, Catalin Marinas wrote:
>>> On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
>>>> On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
>>>>> The memslot must also be created with a new flag ((2c) in the taxonomy
>>>>> above) that carries the "Please map VM_PFNMAP VMAs as cacheable". This
>>>>> flag is only allowed if (1) is valid.
>>>>>
>>>>> This results in the following behaviours:
>>>>>
>>>>> - If the VMM creates the memslot with the cacheable attribute without
>>>>>     (1) being advertised, we fail.
>>>>>
>>>>> - If the VMM creates the memslot without the cacheable attribute, we
>>>>>     map as NC, as it is today.
>>>>
>>>> Is that OK though?
>>>>
>>>> Now we have the MM page tables mapping this memory as cachable but KVM
>>>> and the guest is accessing it as non-cached.
>>>
>>> I don't think we should allow this.
>>>
>>>> I thought ARM tried hard to avoid creating such mismatches? This is
>>>> why the pgprot flags were used to drive this, not an opt-in flag. To
>>>> prevent userspace from forcing a mismatch.
>>>
>>> We have the vma->vm_page_prot when the memslot is added, so we could use
>>> this instead of additional KVM flags.
>>
>> I thought we try to avoid messing with the VMA when adding memslots; because
>> KVM_CAP_SYNC_MMU allows user space for changing the VMAs afterwards without
>> changing the memslot?
> 
> Any checks on the VMA at memslot creation is done out of courtesy to
> userspace so it 'fails fast'. We repeat checks on the VMA at the time of
> fault to handle userspace twiddling VMAs behind our back.
yes, I think it is better to add cachable attribute in memslot, it can 
be checked on the VMA at memslot creation. Also cache attribute can be 
abstracted with cachable/uc/wc type rather than detailed arch specified.

Regards
Bibo Mao
> 
> VM_MTE_ALLOWED is an example of this.
> 
> Thanks,
> Oliver
> 



From ck.hu at mediatek.com  Wed Mar 19 20:48:12 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Thu, 20 Mar 2025 03:48:12 +0000
Subject: [PATCH v8 2/5] dt-bindings: media: add mediatek ISP3.0 camsv
In-Reply-To: <20250122-add-mtk-isp-3-0-support-v8-2-a3d3731eef45@baylibre.com>
References: <20250122-add-mtk-isp-3-0-support-v8-0-a3d3731eef45@baylibre.com>
	 <20250122-add-mtk-isp-3-0-support-v8-2-a3d3731eef45@baylibre.com>
Message-ID: <05bbdb1a73b6a89928f41fe122c44d0ed60bce91.camel@mediatek.com>

On Wed, 2025-01-22 at 14:59 +0100, Julien Stephan wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> From: Phi-bang Nguyen <pnguyen at baylibre.com>
> 
> This adds the bindings, for the ISP3.0 camsv module embedded in
> some Mediatek SoC, such as the mt8365
> 
> Signed-off-by: Phi-bang Nguyen <pnguyen at baylibre.com>
> Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Julien Stephan <jstephan at baylibre.com>
> ---
>  .../bindings/media/mediatek,mt8365-camsv.yaml      | 109 +++++++++++++++++++++
>  MAINTAINERS                                        |   1 +
>  2 files changed, 110 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8365-camsv.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8365-camsv.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..723df7c1a900ff6b72be084e09dfcf0190dee62f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/mediatek,mt8365-camsv.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright (c) 2023 MediaTek, BayLibre
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/media/mediatek,mt8365-camsv.yaml*__;Iw!!CTRNKA9wMg0ARbw!iRvxYnT7ZXDP4KncH_JCUznZDORz1dGEnLx4A4_5zeTkC_E4NWDkBIBy_RQqOxulaBqQG2Lf8wXg4ytmdA$
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!iRvxYnT7ZXDP4KncH_JCUznZDORz1dGEnLx4A4_5zeTkC_E4NWDkBIBy_RQqOxulaBqQG2Lf8wUhRz0RJg$
> +
> +title: MediaTek CAMSV 3.0
> +
> +maintainers:
> +  - Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> +  - Julien Stephan <jstephan at baylibre.com>
> +  - Andy Hsieh <andy.hsieh at mediatek.com>
> +
> +description:
> +  The CAMSV is a video capture device that includes a DMA engine connected to
> +  the SENINF CSI-2 receivers. The number of CAMSVs depend on the SoC model.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8365-camsv
> +
> +  reg:
> +    items:
> +      - description: camsv base
> +      - description: img0 base
> +      - description: tg base
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: cam clock
> +      - description: camtg clock
> +      - description: camsv clock
> +
> +  clock-names:
> +    items:
> +      - const: cam
> +      - const: camtg
> +      - const: camsv
> +
> +  iommus:
> +    maxItems: 1
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port at 0:
> +        $ref: /schemas/graph.yaml#/properties/port
> +        description: Connection to the SENINF output
> +
> +    required:
> +      - port at 0
> +
> +required:
> +  - compatible
> +  - interrupts
> +  - clocks
> +  - clock-names
> +  - power-domains
> +  - iommus
> +  - ports
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/mediatek,mt8365-clk.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/memory/mediatek,mt8365-larb-port.h>

There is no larb property, so drop this.

Regards,
CK

> +    #include <dt-bindings/power/mediatek,mt8365-power.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        camsv at 15050000 {
> +            compatible = "mediatek,mt8365-camsv";
> +            reg = <0 0x15050000 0 0x0040>,
> +                  <0 0x15050208 0 0x0020>,
> +                  <0 0x15050400 0 0x0100>;
> +            interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_LOW>;
> +            clocks = <&camsys CLK_CAM>,
> +                     <&camsys CLK_CAMTG>,
> +                     <&camsys CLK_CAMSV0>;
> +            clock-names = "cam", "camtg", "camsv";
> +            iommus = <&iommu M4U_PORT_CAM_IMGO>;
> +            power-domains = <&spm MT8365_POWER_DOMAIN_CAM>;
> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +                port at 0 {
> +                    reg = <0>;
> +                    camsv1_endpoint: endpoint {
> +                        remote-endpoint = <&seninf_camsv1_endpoint>;
> +                    };
> +                };
> +            };
> +        };
> +    };
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a83db41ae0e9427e983e02f01aecb08193da3cd2..93d59c24befd990abd96ef585607992a6b231b72 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14759,6 +14759,7 @@ M:      Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>  M:     Julien Stephan <jstephan at baylibre.com>
>  M:     Andy Hsieh <andy.hsieh at mediatek.com>
>  S:     Supported
> +F:     Documentation/devicetree/bindings/media/mediatek,mt8365-camsv.yaml
>  F:     Documentation/devicetree/bindings/media/mediatek,mt8365-seninf.yaml
> 
>  MEDIATEK SMI DRIVER
> 
> --
> 2.47.1
> 
> 


From ck.hu at mediatek.com  Wed Mar 19 20:53:20 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Thu, 20 Mar 2025 03:53:20 +0000
Subject: [PATCH v8 5/5] arm64: dts: mediatek: mt8365: Add support for
 camera
In-Reply-To: <20250122-add-mtk-isp-3-0-support-v8-5-a3d3731eef45@baylibre.com>
References: <20250122-add-mtk-isp-3-0-support-v8-0-a3d3731eef45@baylibre.com>
	 <20250122-add-mtk-isp-3-0-support-v8-5-a3d3731eef45@baylibre.com>
Message-ID: <7a67beb636d0b342691b52a0fd39d5c7348fc074.camel@mediatek.com>

On Wed, 2025-01-22 at 14:59 +0100, Julien Stephan wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> Add base support for cameras for mt8365 platforms. This requires nodes
> for the sensor interface, camsv, and CSI receivers.
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Julien Stephan <jstephan at baylibre.com>
> ---

[snip]

> +
> +               camsv1: camsv at 15050000 {
> +                       compatible = "mediatek,mt8365-camsv";
> +                       reg = <0 0x15050000 0 0x0040>,
> +                             <0 0x15050208 0 0x0020>,
> +                             <0 0x15050400 0 0x0100>;
> +                       interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_LOW>;
> +                       clocks = <&camsys CLK_CAM>,
> +                                <&camsys CLK_CAMTG>,
> +                                <&camsys CLK_CAMSV0>;
> +                       clock-names = "cam", "camtg", "camsv";
> +                       iommus = <&iommu M4U_PORT_CAM_IMGO>;
> +                       mediatek,larb = <&larb2>;

binding document has no larb property, drop it.

> +                       power-domains = <&spm MT8365_POWER_DOMAIN_CAM>;
> +                       status = "disabled";
> +
> +                       ports {
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +                               port at 0 {
> +                                       reg = <0>;
> +                                       camsv1_endpoint: endpoint {
> +                                               remote-endpoint = <&seninf_camsv1_endpoint>;
> +                                       };
> +                               };
> +                       };
> +               };
> +
> +               camsv2: camsv at 15050800 {
> +                       compatible = "mediatek,mt8365-camsv";
> +                       reg = <0 0x15050800 0 0x0040>,
> +                             <0 0x15050228 0 0x0020>,
> +                             <0 0x15050c00 0 0x0100>;
> +                       interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_LOW>;
> +                       clocks = <&camsys CLK_CAM>,
> +                                <&camsys CLK_CAMTG>,
> +                                <&camsys CLK_CAMSV1>;
> +                       clock-names = "cam", "camtg", "camsv";
> +                       iommus = <&iommu M4U_PORT_CAM_IMGO>;
> +                       mediatek,larb = <&larb2>;

Ditto.

Regards,
CK

> +                       power-domains = <&spm MT8365_POWER_DOMAIN_CAM>;
> +                       status = "disabled";
> +
> +                       ports {
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +                               port at 0 {
> +                                       reg = <0>;
> +                                       camsv2_endpoint: endpoint {
> +                                               remote-endpoint = <&seninf_camsv2_endpoint>;
> +                                       };
> +                               };
> +                       };
> +               };
> +
>                 vdecsys: syscon at 16000000 {
>                         compatible = "mediatek,mt8365-vdecsys", "syscon";
>                         reg = <0 0x16000000 0 0x1000>;
> 
> --
> 2.47.1
> 
> 


From robh at kernel.org  Wed Mar 19 21:28:12 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Wed, 19 Mar 2025 23:28:12 -0500
Subject: [PATCH 2/2] dt-bindings: dsp: mediatek: add mt8196 dsp
 document
In-Reply-To: <20250320031753.13669-3-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
 <20250320031753.13669-3-hailong.fan@mediatek.com>
Message-ID: <174244489218.3285851.2715414657089059683.robh@kernel.org>


On Thu, 20 Mar 2025 11:17:25 +0800, hailong.fan wrote:
> This patch adds mt8196 dsp document. The dsp is used for Sound Open
> Firmware driver node. It includes registers,  clocks, memory regions,
> and mailbox for dsp.
> 
> Signed-off-by: hailong.fan <hailong.fan at mediatek.com>
> ---
>  .../bindings/dsp/mediatek,mt8196-dsp.yaml     | 96 +++++++++++++++++++
>  1 file changed, 96 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.example.dts:18:18: fatal error: dt-bindings/clock/mt8196-clk.h: No such file or directory
   18 |         #include <dt-bindings/clock/mt8196-clk.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.dtbs:131: Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1522: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250320031753.13669-3-hailong.fan at mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From anup at brainfault.org  Wed Mar 19 22:26:41 2025
From: anup at brainfault.org (Anup Patel)
Date: Thu, 20 Mar 2025 10:56:41 +0530
Subject: [PATCH v2 06/57] irqdomain: irqchip: Switch to of_fwnode_handle()
In-Reply-To: <20250319092951.37667-7-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org> <20250319092951.37667-7-jirislaby@kernel.org>
Message-ID: <CAAhSdy0dG0nn=-OTULCrzFDdT3E7keLdjxoHAf=s7nVzUSO5YA@mail.gmail.com>

On Wed, Mar 19, 2025 at 3:01?PM Jiri Slaby (SUSE) <jirislaby at kernel.org> wrote:
>
> of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
> defined of_fwnode_handle(). The former is in the process of being
> removed, so use the latter instead.
>
> Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
> Cc: Antoine Tenart <atenart at kernel.org>
> Cc: Sven Peter <sven at svenpeter.dev>
> Cc: Janne Grunau <j at jannau.net>
> Cc: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Gregory Clement <gregory.clement at bootlin.com>
> Cc: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Linus Walleij <linusw at kernel.org>
> Cc: Imre Kaloz <kaloz at openwrt.org>
> Cc: Herve Codina <herve.codina at bootlin.com>
> Cc: Huacai Chen <chenhuacai at kernel.org>
> Cc: WANG Xuerui <kernel at xen0n.name>
> Cc: Jiaxun Yang <jiaxun.yang at flygoat.com>
> Cc: Neil Armstrong <neil.armstrong at linaro.org>
> Cc: Kevin Hilman <khilman at baylibre.com>
> Cc: Jerome Brunet <jbrunet at baylibre.com>
> Cc: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> Cc: Anup Patel <anup at brainfault.org>
> Cc: Paul Walmsley <paul.walmsley at sifive.com>
> Cc: Palmer Dabbelt <palmer at dabbelt.com>
> Cc: Albert Ou <aou at eecs.berkeley.edu>
> Cc: Alexandre Ghiti <alex at ghiti.fr>
> Cc: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
> Cc: Alexandre Torgue <alexandre.torgue at foss.st.com>
> Cc: Nishanth Menon <nm at ti.com>
> Cc: Tero Kristo <kristo at kernel.org>
> Cc: Santosh Shilimkar <ssantosh at kernel.org>
> Cc: Kunihiko Hayashi <hayashi.kunihiko at socionext.com>
> Cc: Masami Hiramatsu <mhiramat at kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: asahi at lists.linux.dev
> Cc: loongarch at lists.linux.dev
> Cc: linux-mips at vger.kernel.org
> Cc: linux-amlogic at lists.infradead.org
> Cc: linux-riscv at lists.infradead.org
> Cc: linux-stm32 at st-md-mailman.stormreply.com

LGTM for irq-riscv-intc driver

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup

> ---
>  drivers/irqchip/irq-alpine-msi.c            | 2 +-
>  drivers/irqchip/irq-apple-aic.c             | 4 ++--
>  drivers/irqchip/irq-armada-370-xp.c         | 4 ++--
>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 2 +-
>  drivers/irqchip/irq-gic-v3.c                | 4 ++--
>  drivers/irqchip/irq-ixp4xx.c                | 2 +-
>  drivers/irqchip/irq-lan966x-oic.c           | 2 +-
>  drivers/irqchip/irq-loongarch-cpu.c         | 2 +-
>  drivers/irqchip/irq-loongson-eiointc.c      | 2 +-
>  drivers/irqchip/irq-loongson-htvec.c        | 2 +-
>  drivers/irqchip/irq-loongson-liointc.c      | 2 +-
>  drivers/irqchip/irq-loongson-pch-msi.c      | 2 +-
>  drivers/irqchip/irq-loongson-pch-pic.c      | 2 +-
>  drivers/irqchip/irq-ls-scfg-msi.c           | 2 +-
>  drivers/irqchip/irq-meson-gpio.c            | 2 +-
>  drivers/irqchip/irq-mvebu-gicp.c            | 2 +-
>  drivers/irqchip/irq-mvebu-odmi.c            | 2 +-
>  drivers/irqchip/irq-mvebu-sei.c             | 6 +++---
>  drivers/irqchip/irq-qcom-mpm.c              | 2 +-
>  drivers/irqchip/irq-riscv-intc.c            | 2 +-
>  drivers/irqchip/irq-sni-exiu.c              | 2 +-
>  drivers/irqchip/irq-stm32mp-exti.c          | 2 +-
>  drivers/irqchip/irq-ti-sci-inta.c           | 4 ++--
>  drivers/irqchip/irq-ti-sci-intr.c           | 2 +-
>  drivers/irqchip/irq-uniphier-aidet.c        | 2 +-
>  25 files changed, 31 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c
> index a1430ab60a8a..0207d35135da 100644
> --- a/drivers/irqchip/irq-alpine-msi.c
> +++ b/drivers/irqchip/irq-alpine-msi.c
> @@ -213,7 +213,7 @@ static int alpine_msix_init_domains(struct alpine_msix_data *priv,
>                 return -ENOMEM;
>         }
>
> -       msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
> +       msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node),
>                                                &alpine_msix_domain_info,
>                                                middle_domain);
>         if (!msi_domain) {
> diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c
> index 974dc088c853..032d66dceb8e 100644
> --- a/drivers/irqchip/irq-apple-aic.c
> +++ b/drivers/irqchip/irq-apple-aic.c
> @@ -1014,7 +1014,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
>
>         irqc->info.die_stride = off - start_off;
>
> -       irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node),
> +       irqc->hw_domain = irq_domain_create_tree(of_fwnode_handle(node),
>                                                  &aic_irq_domain_ops, irqc);
>         if (WARN_ON(!irqc->hw_domain))
>                 goto err_unmap;
> @@ -1067,7 +1067,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
>
>         if (is_kernel_in_hyp_mode()) {
>                 struct irq_fwspec mi = {
> -                       .fwnode         = of_node_to_fwnode(node),
> +                       .fwnode         = of_fwnode_handle(node),
>                         .param_count    = 3,
>                         .param          = {
>                                 [0]     = AIC_FIQ, /* This is a lie */
> diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
> index 2aa6a51e05d0..de98d16c1718 100644
> --- a/drivers/irqchip/irq-armada-370-xp.c
> +++ b/drivers/irqchip/irq-armada-370-xp.c
> @@ -353,7 +353,7 @@ static int __init mpic_msi_init(struct mpic *mpic, struct device_node *node,
>         if (!mpic->msi_inner_domain)
>                 return -ENOMEM;
>
> -       mpic->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), &mpic_msi_domain_info,
> +       mpic->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(node), &mpic_msi_domain_info,
>                                                      mpic->msi_inner_domain);
>         if (!mpic->msi_domain) {
>                 irq_domain_remove(mpic->msi_inner_domain);
> @@ -492,7 +492,7 @@ static int __init mpic_ipi_init(struct mpic *mpic, struct device_node *node)
>  {
>         int base_ipi;
>
> -       mpic->ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
> +       mpic->ipi_domain = irq_domain_create_linear(of_fwnode_handle(node), IPI_DOORBELL_NR,
>                                                     &mpic_ipi_domain_ops, mpic);
>         if (WARN_ON(!mpic->ipi_domain))
>                 return -ENOMEM;
> diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
> index 8e87fc35f8aa..11549d85f23b 100644
> --- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
> +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
> @@ -152,7 +152,7 @@ static void __init its_fsl_mc_of_msi_init(void)
>                 if (!of_property_read_bool(np, "msi-controller"))
>                         continue;
>
> -               its_fsl_mc_msi_init_one(of_node_to_fwnode(np),
> +               its_fsl_mc_msi_init_one(of_fwnode_handle(np),
>                                         np->full_name);
>         }
>  }
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 270d7a4d85a6..efc791c43d44 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -1826,7 +1826,7 @@ static int partition_domain_translate(struct irq_domain *d,
>
>         ppi_idx = __gic_get_ppi_index(ppi_intid);
>         ret = partition_translate_id(gic_data.ppi_descs[ppi_idx],
> -                                    of_node_to_fwnode(np));
> +                                    of_fwnode_handle(np));
>         if (ret < 0)
>                 return ret;
>
> @@ -2192,7 +2192,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
>
>                 part = &parts[part_idx];
>
> -               part->partition_id = of_node_to_fwnode(child_part);
> +               part->partition_id = of_fwnode_handle(child_part);
>
>                 pr_info("GIC: PPI partition %pOFn[%d] { ",
>                         child_part, part_idx);
> diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
> index f23b02f62a5c..a9a5a52b818a 100644
> --- a/drivers/irqchip/irq-ixp4xx.c
> +++ b/drivers/irqchip/irq-ixp4xx.c
> @@ -261,7 +261,7 @@ static int __init ixp4xx_of_init_irq(struct device_node *np,
>                 pr_crit("IXP4XX: could not ioremap interrupt controller\n");
>                 return -ENODEV;
>         }
> -       fwnode = of_node_to_fwnode(np);
> +       fwnode = of_fwnode_handle(np);
>
>         /* These chip variants have 64 interrupts */
>         is_356 = of_device_is_compatible(np, "intel,ixp43x-interrupt") ||
> diff --git a/drivers/irqchip/irq-lan966x-oic.c b/drivers/irqchip/irq-lan966x-oic.c
> index 41ac880e3b87..9445c3a6b1b0 100644
> --- a/drivers/irqchip/irq-lan966x-oic.c
> +++ b/drivers/irqchip/irq-lan966x-oic.c
> @@ -224,7 +224,7 @@ static int lan966x_oic_probe(struct platform_device *pdev)
>                 .exit           = lan966x_oic_chip_exit,
>         };
>         struct irq_domain_info d_info = {
> -               .fwnode         = of_node_to_fwnode(pdev->dev.of_node),
> +               .fwnode         = of_fwnode_handle(pdev->dev.of_node),
>                 .domain_flags   = IRQ_DOMAIN_FLAG_DESTROY_GC,
>                 .size           = LAN966X_OIC_NR_IRQ,
>                 .hwirq_max      = LAN966X_OIC_NR_IRQ,
> diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
> index e62dab4c97fc..950bc087e388 100644
> --- a/drivers/irqchip/irq-loongarch-cpu.c
> +++ b/drivers/irqchip/irq-loongarch-cpu.c
> @@ -100,7 +100,7 @@ static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
>  static int __init cpuintc_of_init(struct device_node *of_node,
>                                 struct device_node *parent)
>  {
> -       cpuintc_handle = of_node_to_fwnode(of_node);
> +       cpuintc_handle = of_fwnode_handle(of_node);
>
>         irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM,
>                                 &loongarch_cpu_intc_irq_domain_ops, NULL);
> diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
> index bb79e19dfb59..b2860eb2d32c 100644
> --- a/drivers/irqchip/irq-loongson-eiointc.c
> +++ b/drivers/irqchip/irq-loongson-eiointc.c
> @@ -554,7 +554,7 @@ static int __init eiointc_of_init(struct device_node *of_node,
>                 priv->vec_count = VEC_COUNT;
>
>         priv->node = 0;
> -       priv->domain_handle = of_node_to_fwnode(of_node);
> +       priv->domain_handle = of_fwnode_handle(of_node);
>
>         ret = eiointc_init(priv, parent_irq, 0);
>         if (ret < 0)
> diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c
> index 5da02c7ad0b3..d8558eb35044 100644
> --- a/drivers/irqchip/irq-loongson-htvec.c
> +++ b/drivers/irqchip/irq-loongson-htvec.c
> @@ -248,7 +248,7 @@ static int htvec_of_init(struct device_node *node,
>         }
>
>         err = htvec_init(res.start, resource_size(&res),
> -                       num_parents, parent_irq, of_node_to_fwnode(node));
> +                       num_parents, parent_irq, of_fwnode_handle(node));
>         if (err < 0)
>                 return err;
>
> diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
> index 2b1bd4a96665..95cade56e0be 100644
> --- a/drivers/irqchip/irq-loongson-liointc.c
> +++ b/drivers/irqchip/irq-loongson-liointc.c
> @@ -363,7 +363,7 @@ static int __init liointc_of_init(struct device_node *node,
>         }
>
>         err = liointc_init(res.start, resource_size(&res),
> -                       revision, of_node_to_fwnode(node), node);
> +                       revision, of_fwnode_handle(node), node);
>         if (err < 0)
>                 return err;
>
> diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
> index 9c62108b3ad5..c07876ae7b49 100644
> --- a/drivers/irqchip/irq-loongson-pch-msi.c
> +++ b/drivers/irqchip/irq-loongson-pch-msi.c
> @@ -243,7 +243,7 @@ static int pch_msi_of_init(struct device_node *node, struct device_node *parent)
>                 return -EINVAL;
>         }
>
> -       err = pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_node_to_fwnode(node));
> +       err = pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_fwnode_handle(node));
>         if (err < 0)
>                 return err;
>
> diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
> index 69efda35a8e7..62e6bf3a0611 100644
> --- a/drivers/irqchip/irq-loongson-pch-pic.c
> +++ b/drivers/irqchip/irq-loongson-pch-pic.c
> @@ -392,7 +392,7 @@ static int pch_pic_of_init(struct device_node *node,
>         }
>
>         err = pch_pic_init(res.start, resource_size(&res), vec_base,
> -                               parent_domain, of_node_to_fwnode(node), 0);
> +                               parent_domain, of_fwnode_handle(node), 0);
>         if (err < 0)
>                 return err;
>
> diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
> index 3cb80796cc7c..cbe11a8afe4f 100644
> --- a/drivers/irqchip/irq-ls-scfg-msi.c
> +++ b/drivers/irqchip/irq-ls-scfg-msi.c
> @@ -225,7 +225,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
>         }
>
>         msi_data->msi_domain = pci_msi_create_irq_domain(
> -                               of_node_to_fwnode(msi_data->pdev->dev.of_node),
> +                               of_fwnode_handle(msi_data->pdev->dev.of_node),
>                                 &ls_scfg_msi_domain_info,
>                                 msi_data->parent);
>         if (!msi_data->msi_domain) {
> diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
> index 0a25536a5d07..7d177626d64b 100644
> --- a/drivers/irqchip/irq-meson-gpio.c
> +++ b/drivers/irqchip/irq-meson-gpio.c
> @@ -607,7 +607,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
>
>         domain = irq_domain_create_hierarchy(parent_domain, 0,
>                                              ctl->params->nr_hwirq,
> -                                            of_node_to_fwnode(node),
> +                                            of_fwnode_handle(node),
>                                              &meson_gpio_irq_domain_ops,
>                                              ctl);
>         if (!domain) {
> diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
> index d67f93f6d750..521cc265c05e 100644
> --- a/drivers/irqchip/irq-mvebu-gicp.c
> +++ b/drivers/irqchip/irq-mvebu-gicp.c
> @@ -232,7 +232,7 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
>
>         inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
>                                                    gicp->spi_cnt,
> -                                                  of_node_to_fwnode(node),
> +                                                  of_fwnode_handle(node),
>                                                    &gicp_domain_ops, gicp);
>         if (!inner_domain)
>                 return -ENOMEM;
> diff --git a/drivers/irqchip/irq-mvebu-odmi.c b/drivers/irqchip/irq-mvebu-odmi.c
> index 28f7e81df94f..c1fcd4525e3b 100644
> --- a/drivers/irqchip/irq-mvebu-odmi.c
> +++ b/drivers/irqchip/irq-mvebu-odmi.c
> @@ -207,7 +207,7 @@ static int __init mvebu_odmi_init(struct device_node *node,
>
>         inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
>                                                    odmis_count * NODMIS_PER_FRAME,
> -                                                  of_node_to_fwnode(node),
> +                                                  of_fwnode_handle(node),
>                                                    &odmi_domain_ops, NULL);
>         if (!inner_domain) {
>                 ret = -ENOMEM;
> diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
> index ebd4a9014e8d..5030fcecdcc3 100644
> --- a/drivers/irqchip/irq-mvebu-sei.c
> +++ b/drivers/irqchip/irq-mvebu-sei.c
> @@ -402,7 +402,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
>         }
>
>         /* Create the root SEI domain */
> -       sei->sei_domain = irq_domain_create_linear(of_node_to_fwnode(node),
> +       sei->sei_domain = irq_domain_create_linear(of_fwnode_handle(node),
>                                                    (sei->caps->ap_range.size +
>                                                     sei->caps->cp_range.size),
>                                                    &mvebu_sei_domain_ops,
> @@ -418,7 +418,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
>         /* Create the 'wired' domain */
>         sei->ap_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
>                                                      sei->caps->ap_range.size,
> -                                                    of_node_to_fwnode(node),
> +                                                    of_fwnode_handle(node),
>                                                      &mvebu_sei_ap_domain_ops,
>                                                      sei);
>         if (!sei->ap_domain) {
> @@ -432,7 +432,7 @@ static int mvebu_sei_probe(struct platform_device *pdev)
>         /* Create the 'MSI' domain */
>         sei->cp_domain = irq_domain_create_hierarchy(sei->sei_domain, 0,
>                                                      sei->caps->cp_range.size,
> -                                                    of_node_to_fwnode(node),
> +                                                    of_fwnode_handle(node),
>                                                      &mvebu_sei_cp_domain_ops,
>                                                      sei);
>         if (!sei->cp_domain) {
> diff --git a/drivers/irqchip/irq-qcom-mpm.c b/drivers/irqchip/irq-qcom-mpm.c
> index 7942d8eb3d00..00c770e367d0 100644
> --- a/drivers/irqchip/irq-qcom-mpm.c
> +++ b/drivers/irqchip/irq-qcom-mpm.c
> @@ -447,7 +447,7 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
>
>         priv->domain = irq_domain_create_hierarchy(parent_domain,
>                                 IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP, pin_cnt,
> -                               of_node_to_fwnode(np), &qcom_mpm_ops, priv);
> +                               of_fwnode_handle(np), &qcom_mpm_ops, priv);
>         if (!priv->domain) {
>                 dev_err(dev, "failed to create MPM domain\n");
>                 ret = -ENOMEM;
> diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
> index f653c13de62b..e5805885394e 100644
> --- a/drivers/irqchip/irq-riscv-intc.c
> +++ b/drivers/irqchip/irq-riscv-intc.c
> @@ -242,7 +242,7 @@ static int __init riscv_intc_init(struct device_node *node,
>                 chip = &andes_intc_chip;
>         }
>
> -       return riscv_intc_init_common(of_node_to_fwnode(node), chip);
> +       return riscv_intc_init_common(of_fwnode_handle(node), chip);
>  }
>
>  IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
> diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
> index c7db617e1a2f..7d10bf6e5824 100644
> --- a/drivers/irqchip/irq-sni-exiu.c
> +++ b/drivers/irqchip/irq-sni-exiu.c
> @@ -249,7 +249,7 @@ static int __init exiu_dt_init(struct device_node *node,
>                 return -ENXIO;
>         }
>
> -       data = exiu_init(of_node_to_fwnode(node), &res);
> +       data = exiu_init(of_fwnode_handle(node), &res);
>         if (IS_ERR(data))
>                 return PTR_ERR(data);
>
> diff --git a/drivers/irqchip/irq-stm32mp-exti.c b/drivers/irqchip/irq-stm32mp-exti.c
> index cb83d6cc6113..649b84f12efc 100644
> --- a/drivers/irqchip/irq-stm32mp-exti.c
> +++ b/drivers/irqchip/irq-stm32mp-exti.c
> @@ -531,7 +531,7 @@ static int stm32mp_exti_domain_alloc(struct irq_domain *dm,
>                 if (ret)
>                         return ret;
>                 /* we only support one parent, so far */
> -               if (of_node_to_fwnode(out_irq.np) != dm->parent->fwnode)
> +               if (of_fwnode_handle(out_irq.np) != dm->parent->fwnode)
>                         return -EINVAL;
>
>                 of_phandle_args_to_fwspec(out_irq.np, out_irq.args,
> diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c
> index a887efba262c..38dfc1f9a56b 100644
> --- a/drivers/irqchip/irq-ti-sci-inta.c
> +++ b/drivers/irqchip/irq-ti-sci-inta.c
> @@ -233,7 +233,7 @@ static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_dom
>         INIT_LIST_HEAD(&vint_desc->list);
>
>         parent_node = of_irq_find_parent(dev_of_node(&inta->pdev->dev));
> -       parent_fwspec.fwnode = of_node_to_fwnode(parent_node);
> +       parent_fwspec.fwnode = of_fwnode_handle(parent_node);
>
>         if (of_device_is_compatible(parent_node, "arm,gic-v3")) {
>                 /* Parent is GIC */
> @@ -709,7 +709,7 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev)
>                 return -ENOMEM;
>         }
>
> -       msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node),
> +       msi_domain = ti_sci_inta_msi_create_irq_domain(of_fwnode_handle(node),
>                                                 &ti_sci_inta_msi_domain_info,
>                                                 domain);
>         if (!msi_domain) {
> diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c
> index b49a73106c69..686a8f69fd9c 100644
> --- a/drivers/irqchip/irq-ti-sci-intr.c
> +++ b/drivers/irqchip/irq-ti-sci-intr.c
> @@ -149,7 +149,7 @@ static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain,
>                 goto err_irqs;
>
>         parent_node = of_irq_find_parent(dev_of_node(intr->dev));
> -       fwspec.fwnode = of_node_to_fwnode(parent_node);
> +       fwspec.fwnode = of_fwnode_handle(parent_node);
>
>         if (of_device_is_compatible(parent_node, "arm,gic-v3")) {
>                 /* Parent is GIC */
> diff --git a/drivers/irqchip/irq-uniphier-aidet.c b/drivers/irqchip/irq-uniphier-aidet.c
> index 601f9343d5b3..6005c2d28dd9 100644
> --- a/drivers/irqchip/irq-uniphier-aidet.c
> +++ b/drivers/irqchip/irq-uniphier-aidet.c
> @@ -188,7 +188,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
>         priv->domain = irq_domain_create_hierarchy(
>                                         parent_domain, 0,
>                                         UNIPHIER_AIDET_NR_IRQS,
> -                                       of_node_to_fwnode(dev->of_node),
> +                                       of_fwnode_handle(dev->of_node),
>                                         &uniphier_aidet_domain_ops, priv);
>         if (!priv->domain)
>                 return -ENOMEM;
> --
> 2.49.0
>


From quic_wenbyao at quicinc.com  Wed Mar 19 22:54:59 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao)
Date: Thu, 20 Mar 2025 13:54:59 +0800
Subject: [PATCH v1 0/3] arm64: qcom: x1e80100-qcp: Add power supply and sideband signals config for PCIe3
Message-ID: <20250320055502.274849-1-quic_wenbyao@quicinc.com>

The first patch enable the PCI Power Control driver to control the power
state of PCI slots. The second patch add the bus topology of PCIe domain 3
on x1e80100 platform. The third patch add perst, wake and clkreq sideband
signals, and describe the regulators powering the rails of the PCI slots in
the devicetree for PCIe3 controller and PHY device.

Qiang Yu (3):
  arm64: defconfig: enable PCI Power Control for PCIe3
  arm64: dts: qcom: x1e80100: add bus topology for PCIe domain 3
  arm64: dts: qcom: x1e80100-qcp: Add power control and sideband signals
    for PCIe3

 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
 arch/arm64/boot/dts/qcom/x1e80100.dtsi    |  10 ++
 arch/arm64/configs/defconfig              |   1 +
 3 files changed, 130 insertions(+)


base-commit: 0a2f889128969dab41861b6e40111aa03dc57014
-- 
2.34.1



From quic_wenbyao at quicinc.com  Wed Mar 19 22:55:00 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao)
Date: Thu, 20 Mar 2025 13:55:00 +0800
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for PCIe3
In-Reply-To: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
Message-ID: <20250320055502.274849-2-quic_wenbyao@quicinc.com>

From: Qiang Yu <quic_qianyu at quicinc.com>

Enable the pwrctrl driver, which is utilized to manage the power supplies
of the devices connected to the PCI slots. This ensures that the voltage
rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
on/off if they are described under PCIe port device tree node.

Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 85ec2fba1..de86d1121 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
 CONFIG_PCI_ENDPOINT=y
 CONFIG_PCI_ENDPOINT_CONFIGFS=y
 CONFIG_PCI_EPF_TEST=m
+CONFIG_PCI_PWRCTL_SLOT=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_FW_LOADER_USER_HELPER=y
-- 
2.34.1



From quic_wenbyao at quicinc.com  Wed Mar 19 22:55:01 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao)
Date: Thu, 20 Mar 2025 13:55:01 +0800
Subject: [PATCH v1 2/3] arm64: dts: qcom: x1e80100: add bus topology for PCIe domain 3
In-Reply-To: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
Message-ID: <20250320055502.274849-3-quic_wenbyao@quicinc.com>

From: Qiang Yu <quic_qianyu at quicinc.com>

Add pcie3port node to represent the PCIe bridge of PCIe3 so that PCI slot
voltage rails can be described under this node in the board's dts.

Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
---
 arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
index 46b79fce9..32e8d400a 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
@@ -3287,6 +3287,16 @@ opp-128000000 {
 					opp-peak-kBps = <15753000 1>;
 				};
 			};
+			pcie3port: pcie at 0 {
+				device_type = "pci";
+				compatible = "pciclass,0604";
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				bus-range = <0x01 0xff>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+			};
 		};
 
 		pcie3_phy: phy at 1be0000 {
-- 
2.34.1



From quic_wenbyao at quicinc.com  Wed Mar 19 22:55:02 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao)
Date: Thu, 20 Mar 2025 13:55:02 +0800
Subject: [PATCH v1 3/3] arm64: dts: qcom: x1e80100-qcp: Add power control and sideband signals for PCIe3
In-Reply-To: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
Message-ID: <20250320055502.274849-4-quic_wenbyao@quicinc.com>

From: Qiang Yu <quic_qianyu at quicinc.com>

Add perst, wake and clkreq sideband signals and required regulators in
PCIe3 controller and PHY device tree node. Describe the voltage rails of
the x8 PCI slots for PCIe3 port.

Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
---
 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
index 28086a2bc..9cd313802 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
@@ -318,6 +318,48 @@ vreg_wcn_3p3: regulator-wcn-3p3 {
 		regulator-boot-on;
 	};
 
+	vreg_pcie_12v: regulator-pcie_12v {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VREG_PCIE_12V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+
+		gpio = <&pm8550ve_8_gpios 8 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pcie_x8_12v>;
+	};
+
+	vreg_pcie_3v3_aux: regulator-pcie_3v3_aux {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VREG_PCIE_3P3_AUX";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&pmc8380_3_gpios 8 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pm_sde7_aux_3p3_en>;
+	};
+
+	vreg_pcie_3v3: regulator-pcie_3v3 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VREG_PCIE_3P3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&pmc8380_3_gpios 6 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pm_sde7_main_3p3_en>;
+};
+
 	usb-1-ss0-sbu-mux {
 		compatible = "onnn,fsusb42", "gpio-sbu-mux";
 
@@ -907,6 +949,60 @@ &mdss_dp3_phy {
 	status = "okay";
 };
 
+&pm8550ve_8_gpios {
+	pcie_x8_12v: pcie-12v-default-state {
+		pins = "gpio8";
+		function = "normal";
+		output-enable;
+		output-high;
+		bias-pull-down;
+		power-source = <0>;
+	};
+};
+
+&pmc8380_3_gpios {
+	pm_sde7_aux_3p3_en: pcie-aux-3p3-default-state {
+		pins = "gpio8";
+		function = "normal";
+		output-enable;
+		output-high;
+		bias-pull-down;
+		power-source = <0>;
+	};
+
+	pm_sde7_main_3p3_en: pcie-main-3p3-default-state {
+		pins = "gpio6";
+		function = "normal";
+		output-enable;
+		output-high;
+		bias-pull-down;
+		power-source = <0>;
+	};
+};
+
+&pcie3 {
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_default>;
+	perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+	wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pcie3_phy {
+	vdda-phy-supply = <&vreg_l3j_0p8>;
+	vdda-pll-supply = <&vreg_l3e_1p2>;
+	vdda-qref-supply = <&vreg_l3c_0p8>;
+
+	status = "okay";
+};
+
+&pcie3port {
+	vpcie12v-supply = <&vreg_pcie_12v>;
+	vpcie3v3-supply = <&vreg_pcie_3v3>;
+	vpcie3v3aux-supply = <&vreg_pcie_3v3_aux>;
+};
+
 &pcie4 {
 	perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>;
 	wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
@@ -1118,6 +1214,29 @@ nvme_reg_en: nvme-reg-en-state {
 		bias-disable;
 	};
 
+	pcie3_default: pcie3-default-state {
+		clkreq-n-pins {
+			pins = "gpio144";
+			function = "pcie3_clk";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+
+		perst-n-pins {
+			pins = "gpio143";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-down;
+		};
+
+		wake-n-pins {
+		       pins = "gpio145";
+		       function = "gpio";
+		       drive-strength = <2>;
+		       bias-pull-up;
+		};
+	};
+
 	pcie4_default: pcie4-default-state {
 		clkreq-n-pins {
 			pins = "gpio147";
-- 
2.34.1



From akihiko.odaki at daynix.com  Wed Mar 19 23:03:35 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 20 Mar 2025 15:03:35 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <Z9sSMJAlf7cQ5viu@linux.dev>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
 <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
 <86ldt0n9w1.wl-maz@kernel.org> <Z9sSMJAlf7cQ5viu@linux.dev>
Message-ID: <0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>

On 2025/03/20 3:51, Oliver Upton wrote:
> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
>> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>> What about setting the flag automatically when a user fails to pin
>>> vCPUs to CPUs that are covered by one PMU? There would be no change if
>>> a user correctly pins vCPUs as it is. Otherwise, they will see a
>>> correct feature set advertised to the guest and the cycle counter
>>> working.
>>
>> How do you know that the affinity is "correct"? VCPU affinity can be
>> changed at any time. I, for one, do not want my VMs to change
>> behaviour because I let the vcpus bounce around as the scheduler sees
>> fit.

Checking the affinity when picking the default PMU; the vCPU affinity is 
the only thing that rules the choice of the default PMU even now.

Perhaps we may model the API as follows: introduce another "composite" 
PMU that works on any core but only exposes the cycle counter. Robust 
VMMs will choose it or one of hardware PMUs with 
KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according 
to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If the 
affinity is covered by one hardware PMU, that PMU will be chosen as the 
default. The "composite" PMU will be the default otherwise.

Regards,
Akihiko Odaki

>>
>> Honestly, this is not a can of worm I want to open. We already have a
>> pretty terrible userspace API for the PMU, let's not add to the
>> confusion. *If* we are going down the road of presenting a dumbed-down
>> PMU to the guest, it has to be an explicit buy-in from userspace.
> 
> I also have a very strong distaste for the crappy UAPI we have around a
> 'default' PMU. At the same time I do recognize this hurts practical
> usecases since some VMMs can't be bothered to configure the vPMU / vCPU
> pinning correctly.
> 
> I'm at least willing to plug my nose and do the following:
> 
>   1) When the VMM does not specify a vPMU type:
> 
>     - We continue to present the 'default' PMU (including event counters)
>       to the VM
> 
>     - KVM ensures that the fixed CPU cycle counter works on any PMUv3
>       implementation in the system, even if it is different from the
>       default
> 
>     - Otherwise, event counters will only count on the default
>       implementation and will not count on different PMUs
> 
>   2) Implement your suggestion of a UAPI where the VMM can select a PMU
>      that only has the CPU cycle counter and works on any PMUv3
>      implementation.
> 
> Either way KVM will need to have some special case handling of the fixed
> CPU cycle counter. That'd allow users to actually run Windows *now* and
> provide a clear mechanism for userspace to present a less-broken vPMU if
> it cares.
> 
> Thanks,
> Oliver



From jonas at kwiboo.se  Thu Mar 20 00:02:16 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Thu, 20 Mar 2025 08:02:16 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <2499436.jE0xQCEvom@phil>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
 <20250318120003.2340652-2-amadeus@jmu.edu.cn>
 <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se> <2499436.jE0xQCEvom@phil>
Message-ID: <0f0a35ba-d85d-49eb-92dd-7bc17358aeaf@kwiboo.se>

On 2025-03-20 00:47, Heiko Stuebner wrote:
> Am Donnerstag, 20. M?rz 2025, 00:26:14 MEZ schrieb Jonas Karlman:
>> Hi Chukun,
>>
>> On 2025-03-18 13:00, Chukun Pan wrote:
>>> Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
>>> RK3328, but the driver does not support interrupts yet.
>>
>> The device tree should describe the hardware, not what the driver
>> support, so interrupts should probably be included.
>>
>> However, looking closer at TRM for i.e. RK3328, RK3568 and RK3588 it
>> look like the following description is not a true description of the
>> hardware.
>>
>> Each PWM controller seem to support 4 channels, here (and for older RK
>> SoCs) we instead describe each channel and not the controller.
> 
> Yep, that is something that did go wrong in the very early days.
> And all other Rockchip socs also have the same issue - even back
> to the rk3066.

I see, look like the PWM has evolved something like following:

- The controller has always been 1 controller for 4 channels
- Initial versions only had 2 regs for interrupt outside of the 4x
  0x10 reg space, one for each channel
- FIFO was introduced for channel 3
- Interrupts for FIFO was introduced (in RK3399 or earlier)
- Additional features/regs was introduced (in PX30 or earlier)
- PWM_VERSION_ID = 0x02120b34 is used (in RK3308 and later)

> 
> So yes, at some point we should overhaul the thing.
> 
> But I think this is more involved, as right now everything is aimed
> at the current single-channel status quo.

I did a quick and dirty change in driver to use npwms = 4, and that was
a rather trivial change, see top commit at [1]. Minimum required change
in U-Boot also look to be very trivial.

  cat /sys/kernel/debug/pwm
  0: platform/ffa90000.pwm, 4 PWM devices
   pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
   pwm-1   (regulator-vdd-arm   ): requested enabled period: 5000 ns duty: 2250 ns polarity: inverse
   pwm-2   (regulator-vdd-logic ): requested enabled period: 5000 ns duty: 2800 ns polarity: inverse
   pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal

Not really seeing any reason not to describe these PWM controllers more
correctly, we need to start somewhere.

However, I have no idea on how to deal with historic and wrong bindings.
Driver could possible check if resource space is above 0x10 size and state
of PWM_VERSION_ID.

  PWM_VERSION_ID  0x005c  W  0x02120b34  PWM Version ID Register  

[1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250319-rk3528/

Regards,
Jonas

> 
> 
> Heiko
> 
> 
>> Maybe something like following would better represent the hardware:
>>
>> 	pwm0: pwm at ffa90000 {
>> 		compatible = "rockchip,rk3528-pwm";
>> 		reg = <0x0 0xffa90000 0x0 0x10000>;
>> 		clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>> 		clock-names = "pwm", "pclk";
>> 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
>> 			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
>> 	};
>>
>> 	pwm1: pwm at ffa98000 {
>> 		compatible = "rockchip,rk3528-pwm";
>> 		reg = <0x0 0xffa98000 0x0 0x10000>;
>> 		clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>> 		clock-names = "pwm", "pclk";
>> 		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
>> 			     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
>> 	};
>>
>> Regards,
>> Jonas
>>
>>>
>>> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
>>> ---
>>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++
>>>  1 file changed, 80 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> index 1af0d036cf32..621fc19ac0b3 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
>>> @@ -465,6 +465,86 @@ uart7: serial at ffa28000 {
>>>  			status = "disabled";
>>>  		};
>>>  
>>> +		pwm0: pwm at ffa90000 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa90000 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm1: pwm at ffa90010 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa90010 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm2: pwm at ffa90020 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa90020 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm3: pwm at ffa90030 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa90030 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm4: pwm at ffa98000 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa98000 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm5: pwm at ffa98010 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa98010 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm6: pwm at ffa98020 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa98020 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>> +		pwm7: pwm at ffa98030 {
>>> +			compatible = "rockchip,rk3528-pwm",
>>> +				     "rockchip,rk3328-pwm";
>>> +			reg = <0x0 0xffa98030 0x0 0x10>;
>>> +			clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>>> +			clock-names = "pwm", "pclk";
>>> +			#pwm-cells = <3>;
>>> +			status = "disabled";
>>> +		};
>>> +
>>>  		saradc: adc at ffae0000 {
>>>  			compatible = "rockchip,rk3528-saradc";
>>>  			reg = <0x0 0xffae0000 0x0 0x10000>;
>>
>>
> 
> 
> 
> 



From krzk at kernel.org  Thu Mar 20 00:10:48 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:10:48 +0100
Subject: [PATCH v5 02/16] mm/mm_init: rename init_reserved_page to
 init_deferred_page
In-Reply-To: <20250320015551.2157511-3-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-3-changyuanl@google.com>
Message-ID: <16b14662-d69b-478a-9e2f-a05c56f2c4ce@kernel.org>

On 20/03/2025 02:55, Changyuan Lyu wrote:
> From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> 
> When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, init_reserved_page()
> function performs initialization of a struct page that would have been
> deferred normally.
> 
> Rename it to init_deferred_page() to better reflect what the function does.
> 
> Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>

Incorrect DCO chain.

Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar 20 00:10:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:10:37 +0100
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <20250320015551.2157511-12-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com>
Message-ID: <d5f7379c-c66b-47f5-bc97-eab90ab34346@kernel.org>

On 20/03/2025 02:55, Changyuan Lyu wrote:
> From: Alexander Graf <graf at amazon.com>
> 
> We have all generic code in place now to support Kexec with KHO. This
> patch adds a config option that depends on architecture support to
> enable KHO support.
> 
> Signed-off-by: Alexander Graf <graf at amazon.com>
> Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> Signed-off-by: Changyuan Lyu <changyuanl at google.com>
What did you exactly co-develop here? Few changes does not mean you are
a co-developer.

Best regards,
Krzysztof


From krzk at kernel.org  Thu Mar 20 00:13:24 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:13:24 +0100
Subject: [PATCH v5 12/16] arm64: add KHO support
In-Reply-To: <20250320015551.2157511-13-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-13-changyuanl@google.com>
Message-ID: <55a5e3f3-1b3f-469b-bde0-69abfff826e4@kernel.org>

On 20/03/2025 02:55, Changyuan Lyu wrote:
>  
> +/**
> + * early_init_dt_check_kho - Decode info required for kexec handover from DT
> + */
> +static void __init early_init_dt_check_kho(void)
> +{
> +	unsigned long node = chosen_node_offset;
> +	u64 kho_start, scratch_start, scratch_size;
> +	const __be32 *p;
> +	int l;
> +
> +	if (!IS_ENABLED(CONFIG_KEXEC_HANDOVER) || (long)node < 0)
> +		return;
> +
> +	p = of_get_flat_dt_prop(node, "linux,kho-fdt", &l);


You are adding undocumented ABI for OF properties. That's not what was
explained last time.

NAK.


Best regards,
Krzysztof


From maobibo at loongson.cn  Thu Mar 20 00:24:12 2025
From: maobibo at loongson.cn (bibo mao)
Date: Thu, 20 Mar 2025 15:24:12 +0800
Subject: [PATCH v3 1/1] KVM: arm64: Allow cacheable stage 2 mapping using
 VMA flags
In-Reply-To: <bbb361bd-6cb8-7b9d-f689-d52bb1a05605@loongson.cn>
References: <86r033olwv.wl-maz@kernel.org>
 <SA1PR12MB7199500A3683B15A64B663D6B0D12@SA1PR12MB7199.namprd12.prod.outlook.com>
 <87tt7y7j6r.wl-maz@kernel.org>
 <SA1PR12MB7199B320DAE42A8D7038A78EB0D32@SA1PR12MB7199.namprd12.prod.outlook.com>
 <8634fcnh0n.wl-maz@kernel.org> <Z9h98RhunemcFhhz@arm.com>
 <86wmcmn0dp.wl-maz@kernel.org> <20250318125527.GP9311@nvidia.com>
 <Z9nJH38Em9XEx3U7@arm.com> <ed25f5a6-dad6-4b5e-b42b-58e6ced6c7a2@redhat.com>
 <Z9nMHW-OqTLEqDRs@linux.dev>
 <bbb361bd-6cb8-7b9d-f689-d52bb1a05605@loongson.cn>
Message-ID: <dff27537-97f9-ad46-b991-e1de6b589e3e@loongson.cn>



On 2025/3/20 ??11:30, bibo mao wrote:
> 
> 
> On 2025/3/19 ??3:40, Oliver Upton wrote:
>> On Tue, Mar 18, 2025 at 08:35:38PM +0100, David Hildenbrand wrote:
>>> On 18.03.25 20:27, Catalin Marinas wrote:
>>>> On Tue, Mar 18, 2025 at 09:55:27AM -0300, Jason Gunthorpe wrote:
>>>>> On Tue, Mar 18, 2025 at 09:39:30AM +0000, Marc Zyngier wrote:
>>>>>> The memslot must also be created with a new flag ((2c) in the 
>>>>>> taxonomy
>>>>>> above) that carries the "Please map VM_PFNMAP VMAs as cacheable". 
>>>>>> This
>>>>>> flag is only allowed if (1) is valid.
>>>>>>
>>>>>> This results in the following behaviours:
>>>>>>
>>>>>> - If the VMM creates the memslot with the cacheable attribute without
>>>>>> ??? (1) being advertised, we fail.
>>>>>>
>>>>>> - If the VMM creates the memslot without the cacheable attribute, we
>>>>>> ??? map as NC, as it is today.
>>>>>
>>>>> Is that OK though?
>>>>>
>>>>> Now we have the MM page tables mapping this memory as cachable but KVM
>>>>> and the guest is accessing it as non-cached.
>>>>
>>>> I don't think we should allow this.
>>>>
>>>>> I thought ARM tried hard to avoid creating such mismatches? This is
>>>>> why the pgprot flags were used to drive this, not an opt-in flag. To
>>>>> prevent userspace from forcing a mismatch.
>>>>
>>>> We have the vma->vm_page_prot when the memslot is added, so we could 
>>>> use
>>>> this instead of additional KVM flags.
>>>
>>> I thought we try to avoid messing with the VMA when adding memslots; 
>>> because
>>> KVM_CAP_SYNC_MMU allows user space for changing the VMAs afterwards 
>>> without
>>> changing the memslot?
>>
>> Any checks on the VMA at memslot creation is done out of courtesy to
>> userspace so it 'fails fast'. We repeat checks on the VMA at the time of
>> fault to handle userspace twiddling VMAs behind our back.
> yes, I think it is better to add cachable attribute in memslot, it can 
> be checked on the VMA at memslot creation. Also cache attribute can be 
> abstracted with cachable/uc/wc type rather than detailed arch specified.
Sorry, I do not state this clearly. My meaning is tor add cachable 
attribute in memslot. It is acquired from prot of VMA at memslot 
creation, and checked at S2 page fault fastpath.

So it is unnecessary to find vma at S2 page fault fastpath, only memslot 
is enough. And cache attribute write-combined should be added also since 
some GPU memory can be mapped with WC attribute in vfio-gpu driver.

Regards
Bibo Mao

> 
> Regards
> Bibo Mao
>>
>> VM_MTE_ALLOWED is an example of this.
>>
>> Thanks,
>> Oliver
>>
> 



From krzysztof.kozlowski at linaro.org  Thu Mar 20 00:26:14 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:26:14 +0100
Subject: [GIT PULL] Qualcomm Arm64 DeviceTree updates for v6.15
In-Reply-To: <fe56b19d-6ec0-4b0e-a47d-9e4dc8d798a5@oss.qualcomm.com>
References: <20250317215921.2031880-1-andersson@kernel.org>
 <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>
 <fe56b19d-6ec0-4b0e-a47d-9e4dc8d798a5@oss.qualcomm.com>
Message-ID: <e41292ab-3911-4031-bb91-ad458cdc5691@linaro.org>

On 20/03/2025 01:27, Jeff Johnson wrote:
> On 3/19/2025 2:10 PM, Arnd Bergmann wrote:
>> On Mon, Mar 17, 2025, at 22:59, Bjorn Andersson wrote:
>>>
>>> Krzysztof Kozlowski (17):
>>>       arm64: dts: qcom: sa8775p: Partially revert "arm64: dts: qcom: 
>>> sa8775p: add QCrypto nodes"
>>>       arm64: dts: qcom: qcs8300: Partially revert "arm64: dts: qcom: 
>>> qcs8300: add QCrypto nodes"
>>>       arm64: dts: qcom: x1e80100-slim7x: Drop incorrect 
>>> qcom,ath12k-calibration-variant
>>>       arm64: dts: qcom: msm8998: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: qrb2210-rb1: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: qrb4210-rb2: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sc7180: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sdm845: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sda660-ifc6560: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sm6115: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sm8150-hdk: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: qcm6490: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sa8775p-ride: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sc8280xp: Switch to undeprecated 
>>> qcom,calibration-variant
>>>       arm64: dts: qcom: sm8250-elish: Switch to undeprecated 
>>> qcom,calibration-variant
>>
>> This seeems to remove the properties that the drivers expect
>> even in 6.14-rc7, so the branch is currently broken and I'll
>> skip it for 6.15. Let's see how we should handle this properly
>> in the next cycle, since it's too late now to fix it.
>>
>>       Arnd
>>
> 
> The driver changes are in wireless-next.
> +Johannes will you issue a wireless-next => net-next PR this week?
> 
> Seems like there should be a way to orchestrate these into v6.15.

It does not matter, it would not make history bisectable. Just like I
explained in this patchset, it should wait for next cycle.

Best regards,
Krzysztof


From xueqi.zhang at mediatek.com  Thu Mar 20 00:36:18 2025
From: xueqi.zhang at mediatek.com (Xueqi Zhang)
Date: Thu, 20 Mar 2025 15:36:18 +0800
Subject: [PATCH 3/3] memory: mtk-smi: mt8196: Add smi support
In-Reply-To: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
References: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
Message-ID: <20250320073625.25225-4-xueqi.zhang@mediatek.com>

Add support for MT8196 SMI common and SMI LARB.
Since the MT8196 SMI connects with SMMU, rather than MTK_IOMMU,
it doesn't componet_add with mtk_iommu. Add a flag
MTK_SMI_FLAG_CONNECT_SMMUV3 for this.

Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 134 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 133 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index b9affa3c3185..bd68df23e40b 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -92,6 +92,7 @@
 #define MTK_SMI_FLAG_SW_FLAG		BIT(1)
 #define MTK_SMI_FLAG_SLEEP_CTL		BIT(2)
 #define MTK_SMI_FLAG_CFG_PORT_SEC_CTL	BIT(3)
+#define MTK_SMI_FLAG_CONNECT_SMMUV3	BIT(4)
 #define MTK_SMI_CAPS(flags, _x)		(!!((flags) & (_x)))
 
 struct mtk_smi_reg_pair {
@@ -275,6 +276,9 @@ static int mtk_smi_larb_config_port_gen2_general(struct device *dev)
 		}
 	}
 
+	if (MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_CONNECT_SMMUV3))
+		return 0;
+
 	for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
 		reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
 		reg |= F_MMU_EN;
@@ -410,6 +414,101 @@ static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
 	[28] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
 };
 
+static const u8 mtk_smi_larb_mt8196_ostd[][SMI_LARB_PORT_NR_MAX] = {
+	[0] = {0x4, 0x4, 0x40, 0x40, 0x1, 0x1, 0x2, 0x2, 0x4, 0x4,
+	       0x1, 0x1, 0x1,},
+	[1] = {0x4, 0x4, 0x40, 0x40, 0x32, 0x1, 0x2, 0x2, 0x2, 0x4,
+	       0x4, 0x2, 0x1, 0x1, 0x1, 0x1,},
+	[2] = {0x1, 0x1, 0x1, 0x1, 0x9, 0xb, 0x2a, 0x1, 0x1, 0x1,
+	       0x1, 0x1, 0x1, 0x1, 0x3, 0x1c, 0x1, 0x1,},
+	[3] = {0x2, 0x2, 0x2, 0x2, 0x1a, 0x20, 0x2a, 0x2, 0x1, 0x1,
+	       0x1, 0x1, 0x1, 0x2, 0x8, 0x1c, 0x1, 0x1,},
+	[4] = {0x40, 0x10, 0x10, 0x1, 0x4, 0x10, 0x8, 0x8,},
+	[5] = {0x10, 0x8, 0x40, 0x1e, 0x8, 0x8, 0x4, 0x1,},
+	[6] = {0x40, 0x12, 0x1,},
+	[7] = {0x20, 0x6, 0x6, 0x1, 0x1, 0x24, 0x2b, 0x7, 0x4, 0x1,
+	       0x1, 0xf, 0x3, 0x5, 0x8, 0x8, 0x3, 0x8, 0x5, 0x23,
+	       0x24, 0x4, 0x2, 0xb, 0x10, 0x17, 0x4, 0x8, 0x5, 0x1,
+	       0x1, 0x6,},
+	[8] = {0x20, 0x6, 0x6, 0x1, 0x1, 0x24, 0x2b, 0x7, 0x4, 0x1,
+	       0x1, 0xf, 0x3, 0x5, 0x8, 0x8, 0x3, 0x8, 0x5, 0x23,
+	       0x24, 0x4, 0x2, 0xb, 0x10, 0x17, 0x4, 0x8, 0x5, 0x1,
+	       0x1, 0x6,},
+	[9] = {0x2b, 0x8, 0x9, 0x31, 0x10, 0x26, 0x15, 0x13, 0x7, 0x4,
+	       0x1, 0x1, 0x7, 0xa, 0xb, 0x6, 0x1, 0x1, 0x1, 0x1,
+	       0x1, 0x1, 0xf, 0x9, 0x6, 0x3,},
+	[10] = {0x2b, 0x8, 0x20, 0x1d, 0x19, 0xf, 0x1, 0x3,},
+	[11] = {0x8, 0x16, 0x16, 0x24, 0x1, 0x1, 0x1, 0x3, 0x32, 0x1,
+		0x8, 0x10, 0x16, 0x2, 0x38,},
+	[12] = {0xa, 0xa, 0x1,},
+	[13] = {0x2, 0x20, 0x14, 0x1, 0x1, 0x2, 0x2,},
+	[14] = {0x2, 0x20, 0x14, 0x1, 0x2, 0x2,},
+	[15] = {0x2b, 0x7, 0x31, 0xa, 0x10, 0x10, 0x2b, 0x29, 0x7, 0x1,},
+	[16] = {0x4, 0x4, 0x12, 0x8, 0x8, 0x16, 0x8, 0x6, 0xe, 0x6,
+		0x1e, 0x18, 0x16, 0xe, 0x8, 0xe, 0x8, 0x2, 0x2,},
+	[17] = {0x18, 0x18, 0x8, 0x8, 0xc, 0x4, 0x2,},
+	[18] = {0xb, 0x1, 0x10, 0x1, 0x2,},
+	[19] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x2, 0x1, 0x1,
+		0x4, 0x2, 0x1,},
+	[20] = {0x2, 0x2, 0x2, 0x40, 0x40, 0x40, 0x1, 0x2, 0x2, 0x2,
+		0x4, 0x4, 0x4, 0x1, 0x1,},
+	[21] = {0x2, 0x2, 0x2, 0x40, 0x40, 0x40, 0x1, 0x32, 0x32, 0x32,
+		0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x2, 0x1,},
+	[22] = {0x8, 0x16, 0x16, 0x24, 0x1, 0x1, 0x1, 0x3, 0x32, 0x1,
+		0x8, 0x10, 0x16, 0x2, 0x38,},
+	[23] = {0x8, 0x16, 0x16, 0x24, 0x1, 0x1, 0x1, 0x3, 0x32, 0x1,
+		0x8, 0x10, 0x16, 0x2, 0x38,},
+	[24] = {0x20, 0x6, 0x6, 0x1, 0x1, 0x24, 0x2b, 0x7, 0x4, 0x1,
+		0x1, 0xf, 0x3, 0x5, 0x8, 0x8, 0x3, 0x8, 0x5, 0x23,
+		0x24, 0x4, 0x2, 0xb, 0x10, 0x17, 0x4, 0x8, 0x5, 0x1,
+		0x1, 0x6,},
+	[25] = {0x2, 0xc, 0x2, 0xc, 0x6, 0x6, 0x3, 0x3, 0x3, 0x1,
+		0x1, 0x2, 0x2,},
+	[26] = {0x2, 0xc, 0x2, 0xc, 0x6, 0x6, 0x3, 0x3, 0x3, 0x1,
+		0x1, 0x2, 0x2,},
+	[27] = {0x6, 0x2, 0xe, 0x6, 0x2, 0x14, 0x14, 0x4, 0x6,},
+	[28] = {0x2b, 0x8, 0x31, 0x10, 0x26, 0x15, 0x1, 0x10,},
+	[29] = {0x2, 0x2, 0x2, 0x2, 0x10, 0xe, 0x6, 0x6, 0x1, 0x1,
+		0x2, 0x2, 0x2, 0x2,},
+	[30] = {0x2, 0x2, 0x2, 0x2,},
+	[31] = {},
+	[32] = {0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x32, 0x32, 0x1, 0x2,},
+	[33] = {0xa, 0x1, 0x1, 0x1, 0xa, 0xa, 0xa, 0x1, 0x26, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x2, 0x1,},
+	[34] = {0x4, 0x4, 0x40, 0x40, 0x1, 0x1, 0x2, 0x2, 0x4, 0x4,
+		0x1, 0x1, 0x1,},
+	[35] = {0x4, 0x4, 0x40, 0x40, 0x32, 0x1, 0x2, 0x2, 0x2, 0x4,
+		0x4, 0x2, 0x1, 0x1, 0x1, 0x1,},
+	[36] = {0x2, 0x2, 0x2, 0x40, 0x40, 0x40, 0x1, 0x2, 0x2, 0x2,
+		0x4, 0x4, 0x4, 0x1, 0x1,},
+	[37] = {0x2, 0x2, 0x2, 0x40, 0x40, 0x40, 0x1, 0x32, 0x32, 0x32,
+		0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x2, 0x1,},
+	[38] = {0x29, 0x40, 0x40, 0x7, 0x4, 0x40, 0x4, 0x18, 0x1, 0x1,
+		0x1, 0x7, 0x4,},
+	[39] = {0x16, 0x4, 0x4, 0x8, 0x4, 0x6, 0x6, 0x13, 0x11, 0x20,
+		0x11, 0x1, 0x1, 0x1, 0x9, 0x8, 0x4, 0x6, 0x6,},
+	[40] = {0x9, 0x7, 0x7, 0xb, 0xf, 0x1d, 0x13, 0x6, 0x1, 0x1,
+		0x1, 0x6, 0x9, 0x7, 0xe, 0x3,},
+	[41] = {0x40, 0x8, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x8, 0x8, 0x8, 0x8, 0x8, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x1,},
+	[42] = {0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x8, 0x8, 0x8, 0x8, 0x8, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x1,},
+	[43] = {0x4, 0x4, 0x12, 0x8, 0x8, 0x16, 0x8, 0x6, 0xe, 0x6,
+		0x1e, 0x18, 0x16, 0xe, 0x8, 0xe, 0x8, 0x1, 0x1,},
+	[44] = {0x4, 0x4, 0x12, 0x8, 0x8, 0x16, 0x8, 0x6, 0xe, 0x6,
+		0x1e, 0x18, 0x16, 0xe, 0x8, 0xe, 0x8, 0x1, 0x1,},
+	[45] = {0x18, 0x18, 0x8, 0x8, 0xc, 0x4, 0x1,},
+	[46] = {0x18, 0x18, 0x8, 0x8, 0xc, 0x4, 0x1,},
+	[47] = {0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x8, 0x8, 0x8, 0x8, 0x8, 0x1, 0x1, 0x1, 0x1,
+		0x1, 0x1,},
+};
+
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
 	.port_in_larb = {
 		LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
@@ -470,6 +569,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = {
 	.ostd		            = mtk_smi_larb_mt8195_ostd,
 };
 
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8196 = {
+	.config_port                = mtk_smi_larb_config_port_gen2_general,
+	.flags_general	            = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
+				      MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CONNECT_SMMUV3,
+	.ostd		            = mtk_smi_larb_mt8196_ostd,
+};
+
 static const struct of_device_id mtk_smi_larb_of_ids[] = {
 	{.compatible = "mediatek,mt2701-smi-larb", .data = &mtk_smi_larb_mt2701},
 	{.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712},
@@ -482,6 +588,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
 	{.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188},
 	{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
 	{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
+	{.compatible = "mediatek,mt8196-smi-larb", .data = &mtk_smi_larb_mt8196},
 	{}
 };
 MODULE_DEVICE_TABLE(of, mtk_smi_larb_of_ids);
@@ -569,6 +676,7 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
 	struct device *dev = &pdev->dev;
+	bool connect_with_smmuv3;
 	int ret;
 
 	larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
@@ -580,6 +688,13 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	if (IS_ERR(larb->base))
 		return PTR_ERR(larb->base);
 
+	connect_with_smmuv3 = MTK_SMI_CAPS(larb->larb_gen->flags_general,
+					   MTK_SMI_FLAG_CONNECT_SMMUV3);
+	if (connect_with_smmuv3 && !IS_ENABLED(CONFIG_ARM_SMMU_V3)) {
+		dev_err(dev, " SMMU property conflict.\n");
+		return -EINVAL;
+	}
+
 	ret = mtk_smi_dts_clk_init(dev, &larb->smi, mtk_smi_larb_clks,
 				   MTK_SMI_LARB_REQ_CLK_NR, MTK_SMI_LARB_OPT_CLK_NR);
 	if (ret)
@@ -593,6 +708,10 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 	platform_set_drvdata(pdev, larb);
+
+	if (!connect_with_smmuv3)
+		return 0;
+
 	ret = component_add(dev, &mtk_smi_larb_component_ops);
 	if (ret)
 		goto err_pm_disable;
@@ -610,7 +729,8 @@ static void mtk_smi_larb_remove(struct platform_device *pdev)
 
 	device_link_remove(&pdev->dev, larb->smi_common_dev);
 	pm_runtime_disable(&pdev->dev);
-	component_del(&pdev->dev, &mtk_smi_larb_component_ops);
+	if (!MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_CONNECT_SMMUV3))
+		component_del(&pdev->dev, &mtk_smi_larb_component_ops);
 }
 
 static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
@@ -750,6 +870,16 @@ static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8195 = {
 	.has_gals = true,
 };
 
+static const struct mtk_smi_common_plat mtk_smi_common_mt8196 = {
+	.type     = MTK_SMI_GEN2,
+	.skip_rpm = true,
+};
+
+static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8196 = {
+	.type     = MTK_SMI_GEN2_SUB_COMM,
+	.skip_rpm = true,
+};
+
 static const struct mtk_smi_common_plat mtk_smi_common_mt8365 = {
 	.type     = MTK_SMI_GEN2,
 	.bus_sel  = F_MMU1_LARB(2) | F_MMU1_LARB(4),
@@ -770,6 +900,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
 	{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
 	{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
 	{.compatible = "mediatek,mt8195-smi-sub-common", .data = &mtk_smi_sub_common_mt8195},
+	{.compatible = "mediatek,mt8196-smi-common", .data = &mtk_smi_common_gen2},
+	{.compatible = "mediatek,mt8196-smi-sub-common", .data = &mtk_smi_sub_common_mt8196},
 	{.compatible = "mediatek,mt8365-smi-common", .data = &mtk_smi_common_mt8365},
 	{}
 };
-- 
2.46.0



From vulab at iscas.ac.cn  Thu Mar 20 00:36:57 2025
From: vulab at iscas.ac.cn (Wentao Liang)
Date: Thu, 20 Mar 2025 15:36:57 +0800
Subject: [PATCH] media: platform: Add hardware sync wait to fimc_is_hw_change_mode()
Message-ID: <20250320073658.1005-1-vulab@iscas.ac.cn>

In fimc_is_hw_change_mode(), the function changes camera modes without
waiting for hardware completion, risking corrupted data or system hangs
if subsequent operations proceed before the hardware is ready.

Add fimc_is_hw_wait_intmsr0_intmsd0() after mode configuration, ensuring
hardware state synchronization and stable interrupt handling.

Signed-off-by: Wentao Liang <vulab at iscas.ac.cn>
---
 drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c b/drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c
index 366e6393817d..5f9c44e825a5 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c
@@ -164,6 +164,7 @@ int fimc_is_hw_change_mode(struct fimc_is *is)
 	if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd)))
 		return -EINVAL;
 
+	fimc_is_hw_wait_intmsr0_intmsd0(is);
 	mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0));
 	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
 	mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2));
-- 
2.42.0.windows.2



From xueqi.zhang at mediatek.com  Thu Mar 20 00:36:15 2025
From: xueqi.zhang at mediatek.com (Xueqi Zhang)
Date: Thu, 20 Mar 2025 15:36:15 +0800
Subject: [PATCH 0/3] Add mt8196 SMI support
Message-ID: <20250320073625.25225-1-xueqi.zhang@mediatek.com>

Add mt8196 SMI support

This patchset add mt8196 SMI support. 8196 SMI has several differences
compared to previous ICs. MT8196 SMI has more than 32 SMI larbs.
It connects with SMMUv3, rather than MTK_IOMMU.MT8196 SMI commons is
backed up/restored by RTFF HW.

Xueqi Zhang (3):
  dt-bindings: memory: mediatek: Add mt8196 support
  memory: mtk-smi: Add a flag skip_rpm
  memory: mtk-smi: mt8196: Add smi support

 .../mediatek,smi-common.yaml                  |   4 +-
 .../memory-controllers/mediatek,smi-larb.yaml |   4 +-
 drivers/memory/mtk-smi.c                      | 145 +++++-
 .../dt-bindings/memory/mt8196-memory-port.h   | 460 ++++++++++++++++++
 include/dt-bindings/memory/mtk-memory-port.h  |   4 +-
 5 files changed, 609 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt8196-memory-port.h

-- 
2.46.0



From xueqi.zhang at mediatek.com  Thu Mar 20 00:36:17 2025
From: xueqi.zhang at mediatek.com (Xueqi Zhang)
Date: Thu, 20 Mar 2025 15:36:17 +0800
Subject: [PATCH 2/3] memory: mtk-smi: Add a flag skip_rpm
In-Reply-To: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
References: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
Message-ID: <20250320073625.25225-3-xueqi.zhang@mediatek.com>

MT8196 SMI commons is backed up/restored by RTFF HW.
It doesn't need SW control the register backup/store
in the runtime callback.Therefore, add a flag skip_rpm
to help skip RPM operations for SMI commons.

Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index a8f5467d6b31..b9affa3c3185 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -123,6 +123,7 @@ static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1
 struct mtk_smi_common_plat {
 	enum mtk_smi_type	type;
 	bool			has_gals;
+	bool			skip_rpm;
 	u32			bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
 
 	const struct mtk_smi_reg_pair	*init;
@@ -547,6 +548,9 @@ static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi,
 {
 	int i, ret;
 
+	if (smi->plat->skip_rpm)
+		return 0;
+
 	for (i = 0; i < clk_nr_required; i++)
 		smi->clks[i].id = clks[i];
 	ret = devm_clk_bulk_get(dev, clk_nr_required, smi->clks);
@@ -783,7 +787,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 	common->dev = dev;
 	common->plat = of_device_get_match_data(dev);
 
-	if (common->plat->has_gals) {
+	if (!common->plat->skip_rpm && common->plat->has_gals) {
 		if (common->plat->type == MTK_SMI_GEN2)
 			clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR;
 		else if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
@@ -814,13 +818,14 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 	}
 
 	/* link its smi-common if this is smi-sub-common */
-	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) {
+	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM && !common->plat->skip_rpm) {
 		ret = mtk_smi_device_link_common(dev, &common->smi_common_dev);
 		if (ret < 0)
 			return ret;
 	}
 
-	pm_runtime_enable(dev);
+	if (!common->plat->skip_rpm)
+		pm_runtime_enable(dev);
 	platform_set_drvdata(pdev, common);
 	return 0;
 }
-- 
2.46.0



From xueqi.zhang at mediatek.com  Thu Mar 20 00:36:16 2025
From: xueqi.zhang at mediatek.com (Xueqi Zhang)
Date: Thu, 20 Mar 2025 15:36:16 +0800
Subject: [PATCH 1/3] dt-bindings: memory: mediatek: Add mt8196 support
In-Reply-To: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
References: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
Message-ID: <20250320073625.25225-2-xueqi.zhang@mediatek.com>

Add mt8196 smi support in the bindings.
Since mt8196 has more than 32 SMI larbs, update 'mediatek,larb-id'
maximum to 63.

Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>
---
 .../mediatek,smi-common.yaml                  |   4 +-
 .../memory-controllers/mediatek,smi-larb.yaml |   4 +-
 .../dt-bindings/memory/mt8196-memory-port.h   | 460 ++++++++++++++++++
 include/dt-bindings/memory/mtk-memory-port.h  |   4 +-
 4 files changed, 468 insertions(+), 4 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt8196-memory-port.h

diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
index 2f36ac23604c..70418c3a227c 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
@@ -16,7 +16,7 @@ description: |
   MediaTek SMI have two generations of HW architecture, here is the list
   which generation the SoCs use:
   generation 1: mt2701 and mt7623.
-  generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195.
+  generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192, mt8195 and mt8196.
 
   There's slight differences between the two SMI, for generation 2, the
   register which control the iommu port is at each larb's register base. But
@@ -43,6 +43,8 @@ properties:
           - mediatek,mt8195-smi-common-vdo
           - mediatek,mt8195-smi-common-vpp
           - mediatek,mt8195-smi-sub-common
+          - mediatek,mt8196-smi-common
+          - mediatek,mt8196-smi-sub-common
           - mediatek,mt8365-smi-common
 
       - description: for mt7623
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
index 2381660b324c..a6b561ba217b 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
@@ -28,6 +28,7 @@ properties:
           - mediatek,mt8188-smi-larb
           - mediatek,mt8192-smi-larb
           - mediatek,mt8195-smi-larb
+          - mediatek,mt8196-smi-larb
 
       - description: for mt7623
         items:
@@ -65,7 +66,7 @@ properties:
   mediatek,larb-id:
     $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 0
-    maximum: 31
+    maximum: 63
     description: the hardware id of this larb. It's only required when this
       hardware id is not consecutive from its M4U point of view.
 
@@ -120,6 +121,7 @@ allOf:
               - mediatek,mt8188-smi-larb
               - mediatek,mt8192-smi-larb
               - mediatek,mt8195-smi-larb
+              - mediatek,mt8196-smi-larb
 
     then:
       required:
diff --git a/include/dt-bindings/memory/mt8196-memory-port.h b/include/dt-bindings/memory/mt8196-memory-port.h
new file mode 100644
index 000000000000..8fd29780311b
--- /dev/null
+++ b/include/dt-bindings/memory/mt8196-memory-port.h
@@ -0,0 +1,460 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Mingyuan Ma <mingyuan.ma at mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_MEMORY_MT8196_LARB_PORT_H_
+#define _DT_BINDINGS_MEMORY_MT8196_LARB_PORT_H_
+
+#include <dt-bindings/memory/mtk-memory-port.h>
+
+/* Larb0 -- 13 */
+#define MT8196_SMI_L0_P0_OVL_RDMA2_HDR                  MTK_M4U_ID(0, 0)
+#define MT8196_SMI_L0_P1_OVL_RDMA7_HDR		        MTK_M4U_ID(0, 1)
+#define MT8196_SMI_L0_P2_OVL_RDMA2			MTK_M4U_ID(0, 2)
+#define MT8196_SMI_L0_P3_OVL_RDMA7			MTK_M4U_ID(0, 3)
+#define MT8196_SMI_L0_P4_RESERVED			MTK_M4U_ID(0, 4)
+#define MT8196_SMI_L0_P5_RESERVED			MTK_M4U_ID(0, 5)
+#define MT8196_SMI_L0_P6_OVL_RDMA2_HDR_STASH		MTK_M4U_ID(0, 6)
+#define MT8196_SMI_L0_P7_OVL_RDMA7_HDR_STASH		MTK_M4U_ID(0, 7)
+#define MT8196_SMI_L0_P8_OVL_RDMA2_STASH		MTK_M4U_ID(0, 8)
+#define MT8196_SMI_L0_P9_OVL_RDMA7_STASH		MTK_M4U_ID(0, 9)
+#define MT8196_SMI_L0_P10_RESERVED			MTK_M4U_ID(0, 10)
+#define MT8196_SMI_L0_P11_RESERVED			MTK_M4U_ID(0, 11)
+#define MT8196_SMI_L0_P12_DISP_FAKE0			MTK_M4U_ID(0, 12)
+
+/* Larb1 -- 16 */
+#define MT8196_SMI_L1_P0_OVL_RDMA3_HDR		        MTK_M4U_ID(1, 0)
+#define MT8196_SMI_L1_P1_OVL_RDMA6_HDR		        MTK_M4U_ID(1, 1)
+#define MT8196_SMI_L1_P2_OVL_RDMA3			MTK_M4U_ID(1, 2)
+#define MT8196_SMI_L1_P3_OVL_RDMA6			MTK_M4U_ID(1, 3)
+#define MT8196_SMI_L1_P4_MDP_RDMA1			MTK_M4U_ID(1, 4)
+#define MT8196_SMI_L1_P5_RESERVED			MTK_M4U_ID(1, 5)
+#define MT8196_SMI_L1_P6_DISP_WDMA1			MTK_M4U_ID(1, 6)
+#define MT8196_SMI_L1_P7_OVL_RDMA3_HDR_STASH		MTK_M4U_ID(1, 7)
+#define MT8196_SMI_L1_P8_OVL_RDMA6_HDR_STASH		MTK_M4U_ID(1, 8)
+#define MT8196_SMI_L1_P9_OVL_RDMA3_STASH		MTK_M4U_ID(1, 9)
+#define MT8196_SMI_L1_P10_OVL_RDMA6_STASH		MTK_M4U_ID(1, 10)
+#define MT8196_SMI_L1_P11_MDP_RDMA1_STASH		MTK_M4U_ID(1, 11)
+#define MT8196_SMI_L1_P12_DISP_BWM0			MTK_M4U_ID(1, 12)
+#define MT8196_SMI_L1_P13_DISP_BWM0_STASH		MTK_M4U_ID(1, 13)
+#define MT8196_SMI_L1_P14_RESERVED			MTK_M4U_ID(1, 14)
+#define MT8196_SMI_L1_P15_DISP_FAKE1			MTK_M4U_ID(1, 15)
+
+/* Larb2 -- 18 */
+#define MT8196_SMI_L2_P0_MDP_RDMA2			MTK_M4U_ID(2, 0)
+#define MT8196_SMI_L2_P1_MDP_WROT2			MTK_M4U_ID(2, 1)
+#define MT8196_SMI_L2_P2_MDP_RDMA1			MTK_M4U_ID(2, 2)
+#define MT8196_SMI_L2_P3_MDP_WROT1			MTK_M4U_ID(2, 3)
+#define MT8196_SMI_L2_P4_MDP_RDMA0			MTK_M4U_ID(2, 4)
+#define MT8196_SMI_L2_P5_MDP_WROT0			MTK_M4U_ID(2, 5)
+#define MT8196_SMI_L2_P6_MDP_RROT0			MTK_M4U_ID(2, 6)
+#define MT8196_SMI_L2_P7_MDP_FG0			MTK_M4U_ID(2, 7)
+#define MT8196_SMI_L2_P8_RESERVED			MTK_M4U_ID(2, 8)
+#define MT8196_SMI_L2_P9_MDP_WROT2_STASH		MTK_M4U_ID(2, 9)
+#define MT8196_SMI_L2_P10_MDP_RDMA1_STASH		MTK_M4U_ID(2, 10)
+#define MT8196_SMI_L2_P11_MDP_WROT1_STASH		MTK_M4U_ID(2, 11)
+#define MT8196_SMI_L2_P12_MDP_RDMA0_STASH		MTK_M4U_ID(2, 12)
+#define MT8196_SMI_L2_P13_MDP_WROT0_STASH		MTK_M4U_ID(2, 13)
+#define MT8196_SMI_L2_P14_MDP_RROT0_STASH		MTK_M4U_ID(2, 14)
+#define MT8196_SMI_L2_P15_MDP_RDMA2_STASH		MTK_M4U_ID(2, 15)
+#define MT8196_SMI_L2_P16_RESERVED			MTK_M4U_ID(2, 16)
+#define MT8196_SMI_L2_P17_MDP_FAKE_ENG0		        MTK_M4U_ID(2, 17)
+
+/* Larb3 -- 18 */
+#define MT8196_SMI_L3_P0_MDP_RDMA2			MTK_M4U_ID(3, 0)
+#define MT8196_SMI_L3_P1_MDP_WROT2			MTK_M4U_ID(3, 1)
+#define MT8196_SMI_L3_P2_MDP_RDMA1			MTK_M4U_ID(3, 2)
+#define MT8196_SMI_L3_P3_MDP_WROT1			MTK_M4U_ID(3, 3)
+#define MT8196_SMI_L3_P4_MDP_RDMA0			MTK_M4U_ID(3, 4)
+#define MT8196_SMI_L3_P5_MDP_WROT0			MTK_M4U_ID(3, 5)
+#define MT8196_SMI_L3_P6_MDP_RROT0			MTK_M4U_ID(3, 6)
+#define MT8196_SMI_L3_P7_MDP_FG0			MTK_M4U_ID(3, 7)
+#define MT8196_SMI_L3_P8_RESERVED			MTK_M4U_ID(3, 8)
+#define MT8196_SMI_L3_P9_MDP_RDMA0_STASH		MTK_M4U_ID(3, 9)
+#define MT8196_SMI_L3_P10_MDP_WROT0_STASH		MTK_M4U_ID(3, 10)
+#define MT8196_SMI_L3_P11_MDP_RROT0_STASH		MTK_M4U_ID(3, 11)
+#define MT8196_SMI_L3_P12_MDP_RDMA2_STASH		MTK_M4U_ID(3, 12)
+#define MT8196_SMI_L3_P13_MDP_WROT2_STASH		MTK_M4U_ID(3, 13)
+#define MT8196_SMI_L3_P14_MDP_RDMA1_STASH		MTK_M4U_ID(3, 14)
+#define MT8196_SMI_L3_P15_MDP_WROT1_STASH		MTK_M4U_ID(3, 15)
+#define MT8196_SMI_L3_P16_RESERVED			MTK_M4U_ID(3, 16)
+#define MT8196_SMI_L3_P17_MDP_FAKE_ENG0		        MTK_M4U_ID(3, 17)
+
+/* Larb4 -- 8 */
+#define MT8196_SMI_L4_P0_VDEC_MC_C			MTK_M4U_ID(4, 0)
+#define MT8196_SMI_L4_P1_VDEC_UFO			MTK_M4U_ID(4, 1)
+#define MT8196_SMI_L4_P2_VDEC_PP			MTK_M4U_ID(4, 2)
+#define MT8196_SMI_L4_P3_VDEC_UFO_C			MTK_M4U_ID(4, 3)
+#define MT8196_SMI_L4_P4_VDEC_TILE			MTK_M4U_ID(4, 4)
+#define MT8196_SMI_L4_P5_VDEC_VLD			MTK_M4U_ID(4, 5)
+#define MT8196_SMI_L4_P6_VDEC_VLD2			MTK_M4U_ID(4, 6)
+#define MT8196_SMI_L4_P7_VDEC_AVC_MV			MTK_M4U_ID(4, 7)
+
+/* Larb5 -- 8 */
+#define MT8196_SMI_L5_P0_VDEC_LAT0_VLD		        MTK_M4U_ID(5, 0)
+#define MT8196_SMI_L5_P1_VDEC_LAT0_VLD2		        MTK_M4U_ID(5, 1)
+#define MT8196_SMI_L5_P2_VDEC_MC			MTK_M4U_ID(5, 2)
+#define MT8196_SMI_L5_P3_VDEC_UFO_ENC			MTK_M4U_ID(5, 3)
+#define MT8196_SMI_L5_P4_VDEC_LAT0_WDMA		        MTK_M4U_ID(5, 4)
+#define MT8196_SMI_L5_P5_VDEC_LAT0_AVC_MV		MTK_M4U_ID(5, 5)
+#define MT8196_SMI_L5_P6_VDEC_LAT0_TILE		        MTK_M4U_ID(5, 6)
+#define MT8196_SMI_L5_P7_VDEC_LAT0_UNIWRAP		MTK_M4U_ID(5, 7)
+
+/* Larb6 -- 3 */
+#define MT8196_SMI_L6_P0_VDEC_MC_PORT2		        MTK_M4U_ID(6, 0)
+#define MT8196_SMI_L6_P1_VDEC_UFO_ENC_C		        MTK_M4U_ID(6, 1)
+#define MT8196_SMI_L6_P2_VDEC_UNIWRAP			MTK_M4U_ID(6, 2)
+
+/* Larb7 -- 32 */
+#define MT8196_SMI_L7_P0_RCPU				MTK_M4U_ID(7, 0)
+#define MT8196_SMI_L7_P1_REC_FRM			MTK_M4U_ID(7, 1)
+#define MT8196_SMI_L7_P2_BS				MTK_M4U_ID(7, 2)
+#define MT8196_SMI_L7_P3_SVCOMV			        MTK_M4U_ID(7, 3)
+#define MT8196_SMI_L7_P4_RDCOMV			        MTK_M4U_ID(7, 4)
+#define MT8196_SMI_L7_P5_NBM_R			        MTK_M4U_ID(7, 5)
+#define MT8196_SMI_L7_P6_NBM_R_LITE			MTK_M4U_ID(7, 6)
+#define MT8196_SMI_L7_P7_JPGENC_YRD			MTK_M4U_ID(7, 7)
+#define MT8196_SMI_L7_P8_JPGENC_CRD			MTK_M4U_ID(7, 8)
+#define MT8196_SMI_L7_P9_JPGENC_QT			MTK_M4U_ID(7, 9)
+#define MT8196_SMI_L7_P10_FCS_SUB_W			MTK_M4U_ID(7, 10)
+#define MT8196_SMI_L7_P11_FCS_NBM_R			MTK_M4U_ID(7, 11)
+#define MT8196_SMI_L7_P12_WPP_BS			MTK_M4U_ID(7, 12)
+#define MT8196_SMI_L7_P13_WPP_RDMA			MTK_M4U_ID(7, 13)
+#define MT8196_SMI_L7_P14_DB_SYSRAM_W			MTK_M4U_ID(7, 14)
+#define MT8196_SMI_L7_P15_DB_SYSRAM_R			MTK_M4U_ID(7, 15)
+#define MT8196_SMI_L7_P16_JPGENC_BS			MTK_M4U_ID(7, 16)
+#define MT8196_SMI_L7_P17_JPGDEC_W			MTK_M4U_ID(7, 17)
+#define MT8196_SMI_L7_P18_JPGDEC_BS			MTK_M4U_ID(7, 18)
+#define MT8196_SMI_L7_P19_NBM_W			        MTK_M4U_ID(7, 19)
+#define MT8196_SMI_L7_P20_NBM_W_LITE			MTK_M4U_ID(7, 20)
+#define MT8196_SMI_L7_P21_CUR_LUMA			MTK_M4U_ID(7, 21)
+#define MT8196_SMI_L7_P22_CUR_CHROMA			MTK_M4U_ID(7, 22)
+#define MT8196_SMI_L7_P23_REF_LUMA			MTK_M4U_ID(7, 23)
+#define MT8196_SMI_L7_P24_REF_CHROMA			MTK_M4U_ID(7, 24)
+#define MT8196_SMI_L7_P25_FCS_SUB_R			MTK_M4U_ID(7, 25)
+#define MT8196_SMI_L7_P26_FCS_NBM_W			MTK_M4U_ID(7, 26)
+#define MT8196_SMI_L7_P27_JPGDEC_W_1			MTK_M4U_ID(7, 27)
+#define MT8196_SMI_L7_P28_JPGDEC_BS_1			MTK_M4U_ID(7, 28)
+#define MT8196_SMI_L7_P29_JPGDEC_HUF_1		        MTK_M4U_ID(7, 29)
+#define MT8196_SMI_L7_P30_JPGDEC_HUF			MTK_M4U_ID(7, 30)
+#define MT8196_SMI_L7_P31_EC_SYSRAM			MTK_M4U_ID(7, 31)
+
+/* Larb8 -- 32 */
+#define MT8196_SMI_L8_P0_RCPU				MTK_M4U_ID(8, 0)
+#define MT8196_SMI_L8_P1_REC_FRM			MTK_M4U_ID(8, 1)
+#define MT8196_SMI_L8_P2_BS				MTK_M4U_ID(8, 2)
+#define MT8196_SMI_L8_P3_SVCOMV			        MTK_M4U_ID(8, 3)
+#define MT8196_SMI_L8_P4_RDCOMV			        MTK_M4U_ID(8, 4)
+#define MT8196_SMI_L8_P5_NBM_R			        MTK_M4U_ID(8, 5)
+#define MT8196_SMI_L8_P6_NBM_R_LITE			MTK_M4U_ID(8, 6)
+#define MT8196_SMI_L8_P7_JPGENC_YRD			MTK_M4U_ID(8, 7)
+#define MT8196_SMI_L8_P8_JPGENC_CRD			MTK_M4U_ID(8, 8)
+#define MT8196_SMI_L8_P9_JPGENC_QT			MTK_M4U_ID(8, 9)
+#define MT8196_SMI_L8_P10_FCS_SUB_W			MTK_M4U_ID(8, 10)
+#define MT8196_SMI_L8_P11_FCS_NBM_R			MTK_M4U_ID(8, 11)
+#define MT8196_SMI_L8_P12_WPP_BS			MTK_M4U_ID(8, 12)
+#define MT8196_SMI_L8_P13_WPP_RDMA			MTK_M4U_ID(8, 13)
+#define MT8196_SMI_L8_P14_DB_SYSRAM_W			MTK_M4U_ID(8, 14)
+#define MT8196_SMI_L8_P15_DB_SYSRAM_R			MTK_M4U_ID(8, 15)
+#define MT8196_SMI_L8_P16_JPGENC_BS			MTK_M4U_ID(8, 16)
+#define MT8196_SMI_L8_P17_JPGDEC_W			MTK_M4U_ID(8, 17)
+#define MT8196_SMI_L8_P18_JPGDEC_BS			MTK_M4U_ID(8, 18)
+#define MT8196_SMI_L8_P19_NBM_W			        MTK_M4U_ID(8, 19)
+#define MT8196_SMI_L8_P20_NBM_W_LITE			MTK_M4U_ID(8, 20)
+#define MT8196_SMI_L8_P21_CUR_LUMA			MTK_M4U_ID(8, 21)
+#define MT8196_SMI_L8_P22_CUR_CHROMA			MTK_M4U_ID(8, 22)
+#define MT8196_SMI_L8_P23_REF_LUMA			MTK_M4U_ID(8, 23)
+#define MT8196_SMI_L8_P24_REF_CHROMA			MTK_M4U_ID(8, 24)
+#define MT8196_SMI_L8_P25_FCS_SUB_R			MTK_M4U_ID(8, 25)
+#define MT8196_SMI_L8_P26_FCS_NBM_W			MTK_M4U_ID(8, 26)
+#define MT8196_SMI_L8_P27_JPGDEC_W_1			MTK_M4U_ID(8, 27)
+#define MT8196_SMI_L8_P28_JPGDEC_BS_1			MTK_M4U_ID(8, 28)
+#define MT8196_SMI_L8_P29_JPGDEC_HUF_1		        MTK_M4U_ID(8, 29)
+#define MT8196_SMI_L8_P30_JPGDEC_HUF			MTK_M4U_ID(8, 30)
+#define MT8196_SMI_L8_P31_EC_SYSRAM			MTK_M4U_ID(8, 31)
+
+/* Larb20 -- 15 */
+#define MT8196_SMI_L20_P0_OVL_RDMA4_HDR		        MTK_M4U_ID(20, 0)
+#define MT8196_SMI_L20_P1_OVL_RDMA9_HDR		        MTK_M4U_ID(20, 1)
+#define MT8196_SMI_L20_P2_OVL_RDMA0_HDR		        MTK_M4U_ID(20, 2)
+#define MT8196_SMI_L20_P3_OVL_RDMA4			MTK_M4U_ID(20, 3)
+#define MT8196_SMI_L20_P4_OVL_RDMA9			MTK_M4U_ID(20, 4)
+#define MT8196_SMI_L20_P5_OVL_RDMA0			MTK_M4U_ID(20, 5)
+#define MT8196_SMI_L20_P6_RESERVED			MTK_M4U_ID(20, 6)
+#define MT8196_SMI_L20_P7_OVL_RDMA4_HDR_STASH		MTK_M4U_ID(20, 7)
+#define MT8196_SMI_L20_P8_OVL_RDMA9_HDR_STASH		MTK_M4U_ID(20, 8)
+#define MT8196_SMI_L20_P9_OVL_RDMA0_HDR_STASH		MTK_M4U_ID(20, 9)
+#define MT8196_SMI_L20_P10_OVL_RDMA4_STASH		MTK_M4U_ID(20, 10)
+#define MT8196_SMI_L20_P11_OVL_RDMA9_STASH		MTK_M4U_ID(20, 11)
+#define MT8196_SMI_L20_P12_OVL_RDMA0_STASH		MTK_M4U_ID(20, 12)
+#define MT8196_SMI_L20_P13_RESERVED			MTK_M4U_ID(20, 13)
+#define MT8196_SMI_L20_P14_RESERVED			MTK_M4U_ID(20, 14)
+
+/* Larb21 -- 18 */
+#define MT8196_SMI_L21_P0_OVL_RDMA5_HDR		        MTK_M4U_ID(21, 0)
+#define MT8196_SMI_L21_P1_OVL_RDMA8_HDR		        MTK_M4U_ID(21, 1)
+#define MT8196_SMI_L21_P2_OVL_RDMA1_HDR		        MTK_M4U_ID(21, 2)
+#define MT8196_SMI_L21_P3_OVL_RDMA5			MTK_M4U_ID(21, 3)
+#define MT8196_SMI_L21_P4_OVL_RDMA8			MTK_M4U_ID(21, 4)
+#define MT8196_SMI_L21_P5_OVL_RDMA1			MTK_M4U_ID(21, 5)
+#define MT8196_SMI_L21_P6_RESERVED			MTK_M4U_ID(21, 6)
+#define MT8196_SMI_L21_P7_MDP_RDMA0			MTK_M4U_ID(21, 7)
+#define MT8196_SMI_L21_P8_DISP_WDMA0			MTK_M4U_ID(21, 8)
+#define MT8196_SMI_L21_P9_DISP_UFBC_WDMA0		MTK_M4U_ID(21, 9)
+#define MT8196_SMI_L21_P10_OVL_RDMA5_HDR_STASH	        MTK_M4U_ID(21, 10)
+#define MT8196_SMI_L21_P11_OVL_RDMA8_HDR_STASH	        MTK_M4U_ID(21, 11)
+#define MT8196_SMI_L21_P12_OVL_RDMA1_HDR_STASH	        MTK_M4U_ID(21, 12)
+#define MT8196_SMI_L21_P13_OVL_RDMA5_STASH		MTK_M4U_ID(21, 13)
+#define MT8196_SMI_L21_P14_OVL_RDMA8_STASH		MTK_M4U_ID(21, 14)
+#define MT8196_SMI_L21_P15_OVL_RDMA1_STASH		MTK_M4U_ID(21, 15)
+#define MT8196_SMI_L21_P16_MDP_RDMA0_STASH		MTK_M4U_ID(21, 16)
+#define MT8196_SMI_L21_P17_RESERVED			MTK_M4U_ID(21, 17)
+
+/* Larb24 -- 32 */
+#define MT8196_SMI_L24_P0_RCPU			        MTK_M4U_ID(24, 0)
+#define MT8196_SMI_L24_P1_REC_FRM			MTK_M4U_ID(24, 1)
+#define MT8196_SMI_L24_P2_BS				MTK_M4U_ID(24, 2)
+#define MT8196_SMI_L24_P3_SVCOMV			MTK_M4U_ID(24, 3)
+#define MT8196_SMI_L24_P4_RDCOMV			MTK_M4U_ID(24, 4)
+#define MT8196_SMI_L24_P5_NBM_R			        MTK_M4U_ID(24, 5)
+#define MT8196_SMI_L24_P6_NBM_R_LITE			MTK_M4U_ID(24, 6)
+#define MT8196_SMI_L24_P7_JPGENC_YRD			MTK_M4U_ID(24, 7)
+#define MT8196_SMI_L24_P8_JPGENC_CRD			MTK_M4U_ID(24, 8)
+#define MT8196_SMI_L24_P9_JPGENC_QT			MTK_M4U_ID(24, 9)
+#define MT8196_SMI_L24_P10_FCS_SUB_W			MTK_M4U_ID(24, 10)
+#define MT8196_SMI_L24_P11_FCS_NBM_R			MTK_M4U_ID(24, 11)
+#define MT8196_SMI_L24_P12_WPP_BS			MTK_M4U_ID(24, 12)
+#define MT8196_SMI_L24_P13_WPP_RDMA			MTK_M4U_ID(24, 13)
+#define MT8196_SMI_L24_P14_DB_SYSRAM_W		        MTK_M4U_ID(24, 14)
+#define MT8196_SMI_L24_P15_DB_SYSRAM_R		        MTK_M4U_ID(24, 15)
+#define MT8196_SMI_L24_P16_JPGENC_BS			MTK_M4U_ID(24, 16)
+#define MT8196_SMI_L24_P17_JPGDEC_W			MTK_M4U_ID(24, 17)
+#define MT8196_SMI_L24_P18_JPGDEC_BS			MTK_M4U_ID(24, 18)
+#define MT8196_SMI_L24_P19_NBM_W			MTK_M4U_ID(24, 19)
+#define MT8196_SMI_L24_P20_NBM_W_LITE			MTK_M4U_ID(24, 20)
+#define MT8196_SMI_L24_P21_CUR_LUMA			MTK_M4U_ID(24, 21)
+#define MT8196_SMI_L24_P22_CUR_CHROMA			MTK_M4U_ID(24, 22)
+#define MT8196_SMI_L24_P23_REF_LUMA			MTK_M4U_ID(24, 23)
+#define MT8196_SMI_L24_P24_REF_CHROMA			MTK_M4U_ID(24, 24)
+#define MT8196_SMI_L24_P25_FCS_SUB_R			MTK_M4U_ID(24, 25)
+#define MT8196_SMI_L24_P26_FCS_NBM_W			MTK_M4U_ID(24, 26)
+#define MT8196_SMI_L24_P27_JPGDEC_W_1			MTK_M4U_ID(24, 27)
+#define MT8196_SMI_L24_P28_JPGDEC_BS_1		        MTK_M4U_ID(24, 28)
+#define MT8196_SMI_L24_P29_JPGDEC_HUF_1		        MTK_M4U_ID(24, 29)
+#define MT8196_SMI_L24_P30_JPGDEC_HUF			MTK_M4U_ID(24, 30)
+#define MT8196_SMI_L24_P31_EC_SYSRAM			MTK_M4U_ID(24, 31)
+
+/* Larb32 -- 10 */
+#define MT8196_SMI_L32_P0_DISP_RESERVED_0		MTK_M4U_ID(32, 0)
+#define MT8196_SMI_L32_P1_DISP_RESERVED_1		MTK_M4U_ID(32, 1)
+#define MT8196_SMI_L32_P2_DISP_RESERVED_2		MTK_M4U_ID(32, 2)
+#define MT8196_SMI_L32_P3_DISP_RESERVED_3		MTK_M4U_ID(32, 3)
+#define MT8196_SMI_L32_P4_DISP_POSTMASK0		MTK_M4U_ID(32, 4)
+#define MT8196_SMI_L32_P5_DISP_POSTMASK1		MTK_M4U_ID(32, 5)
+#define MT8196_SMI_L32_P6_DISP_MDP_RDMA0		MTK_M4U_ID(32, 6)
+#define MT8196_SMI_L32_P7_DISP_WDMA0			MTK_M4U_ID(32, 7)
+#define MT8196_SMI_L32_P8_DISP_FAKE_ENG0		MTK_M4U_ID(32, 8)
+#define MT8196_SMI_L32_P9_DISP_MDP_RDMA0_STASH	        MTK_M4U_ID(32, 9)
+
+/* Larb33 -- 16 */
+#define MT8196_SMI_L33_P0_DISP1_ODDMR0_DMRR0		MTK_M4U_ID(33, 0)
+#define MT8196_SMI_L33_P1_RESERVED			MTK_M4U_ID(33, 1)
+#define MT8196_SMI_L33_P2_RESERVED			MTK_M4U_ID(33, 2)
+#define MT8196_SMI_L33_P3_RESERVED			MTK_M4U_ID(33, 3)
+#define MT8196_SMI_L33_P4_DISP1_ODDMR0_DBIR		MTK_M4U_ID(33, 4)
+#define MT8196_SMI_L33_P5_DISP1_ODDMR0_ODR		MTK_M4U_ID(33, 5)
+#define MT8196_SMI_L33_P6_DISP1_ODDMR0_ODW		MTK_M4U_ID(33, 6)
+#define MT8196_SMI_L33_P7_RESERVED			MTK_M4U_ID(33, 7)
+#define MT8196_SMI_L33_P8_DISP1_GDMA0			MTK_M4U_ID(33, 8)
+#define MT8196_SMI_L33_P9_DISP1_MDP_RDMA1		MTK_M4U_ID(33, 9)
+#define MT8196_SMI_L33_P10_DISP1_WDMA1		        MTK_M4U_ID(33, 10)
+#define MT8196_SMI_L33_P11_DISP1_WDMA2		        MTK_M4U_ID(33, 11)
+#define MT8196_SMI_L33_P12_DISP1_WDMA3		        MTK_M4U_ID(33, 12)
+#define MT8196_SMI_L33_P13_DISP1_WDMA4		        MTK_M4U_ID(33, 13)
+#define MT8196_SMI_L33_P14_DISP1_MDP_RDMA1_STASH	MTK_M4U_ID(33, 14)
+#define MT8196_SMI_L33_P15_RESERVED			MTK_M4U_ID(33, 15)
+
+/* Larb34 -- 13 */
+#define MT8196_SMI_L34_P0_OVL_RDMA2_HDR		        MTK_M4U_ID(34, 0)
+#define MT8196_SMI_L34_P1_OVL_RDMA7_HDR		        MTK_M4U_ID(34, 1)
+#define MT8196_SMI_L34_P2_OVL_RDMA2			MTK_M4U_ID(34, 2)
+#define MT8196_SMI_L34_P3_OVL_RDMA7			MTK_M4U_ID(34, 3)
+#define MT8196_SMI_L34_P4_RESERVED			MTK_M4U_ID(34, 4)
+#define MT8196_SMI_L34_P5_RESERVED			MTK_M4U_ID(34, 5)
+#define MT8196_SMI_L34_P6_OVL_RDMA2_HDR_STASH		MTK_M4U_ID(34, 6)
+#define MT8196_SMI_L34_P7_OVL_RDMA7_HDR_STASH		MTK_M4U_ID(34, 7)
+#define MT8196_SMI_L34_P8_OVL_RDMA2_STASH		MTK_M4U_ID(34, 8)
+#define MT8196_SMI_L34_P9_OVL_RDMA7_STASH		MTK_M4U_ID(34, 9)
+#define MT8196_SMI_L34_P10_RESERVED			MTK_M4U_ID(34, 10)
+#define MT8196_SMI_L34_P11_RESERVED			MTK_M4U_ID(34, 11)
+#define MT8196_SMI_L34_P12_DISP_FAKE0			MTK_M4U_ID(34, 12)
+
+/* Larb35 -- 16 */
+#define MT8196_SMI_L35_P0_OVL_RDMA3_HDR		        MTK_M4U_ID(35, 0)
+#define MT8196_SMI_L35_P1_OVL_RDMA6_HDR		        MTK_M4U_ID(35, 1)
+#define MT8196_SMI_L35_P2_OVL_RDMA3			MTK_M4U_ID(35, 2)
+#define MT8196_SMI_L35_P3_OVL_RDMA6			MTK_M4U_ID(35, 3)
+#define MT8196_SMI_L35_P4_MDP_RDMA1			MTK_M4U_ID(35, 4)
+#define MT8196_SMI_L35_P5_RESERVED			MTK_M4U_ID(35, 5)
+#define MT8196_SMI_L35_P6_DISP_WDMA1			MTK_M4U_ID(35, 6)
+#define MT8196_SMI_L35_P7_OVL_RDMA3_HDR_STASH		MTK_M4U_ID(35, 7)
+#define MT8196_SMI_L35_P8_OVL_RDMA6_HDR_STASH		MTK_M4U_ID(35, 8)
+#define MT8196_SMI_L35_P9_OVL_RDMA3_STASH		MTK_M4U_ID(35, 9)
+#define MT8196_SMI_L35_P10_OVL_RDMA6_STASH		MTK_M4U_ID(35, 10)
+#define MT8196_SMI_L35_P11_MDP_RDMA1_STASH		MTK_M4U_ID(35, 11)
+#define MT8196_SMI_L35_P12_DISP_BWM0			MTK_M4U_ID(35, 12)
+#define MT8196_SMI_L35_P13_DISP_BWM0_STASH		MTK_M4U_ID(35, 13)
+#define MT8196_SMI_L35_P14_RESERVED			MTK_M4U_ID(35, 14)
+#define MT8196_SMI_L35_P15_DISP_FAKE1			MTK_M4U_ID(35, 15)
+
+/* Larb36 -- 15 */
+#define MT8196_SMI_L36_P0_OVL_RDMA4_HDR		        MTK_M4U_ID(36, 0)
+#define MT8196_SMI_L36_P1_OVL_RDMA9_HDR		        MTK_M4U_ID(36, 1)
+#define MT8196_SMI_L36_P2_OVL_RDMA0_HDR		        MTK_M4U_ID(36, 2)
+#define MT8196_SMI_L36_P3_OVL_RDMA4			MTK_M4U_ID(36, 3)
+#define MT8196_SMI_L36_P4_OVL_RDMA9			MTK_M4U_ID(36, 4)
+#define MT8196_SMI_L36_P5_OVL_RDMA0			MTK_M4U_ID(36, 5)
+#define MT8196_SMI_L36_P6_RESERVED			MTK_M4U_ID(36, 6)
+#define MT8196_SMI_L36_P7_OVL_RDMA4_HDR_STASH		MTK_M4U_ID(36, 7)
+#define MT8196_SMI_L36_P8_OVL_RDMA9_HDR_STASH		MTK_M4U_ID(36, 8)
+#define MT8196_SMI_L36_P9_OVL_RDMA0_HDR_STASH		MTK_M4U_ID(36, 9)
+#define MT8196_SMI_L36_P10_OVL_RDMA4_STASH		MTK_M4U_ID(36, 10)
+#define MT8196_SMI_L36_P11_OVL_RDMA9_STASH		MTK_M4U_ID(36, 11)
+#define MT8196_SMI_L36_P12_OVL_RDMA0_STASH		MTK_M4U_ID(36, 12)
+#define MT8196_SMI_L36_P13_RESERVED			MTK_M4U_ID(36, 13)
+#define MT8196_SMI_L36_P14_RESERVED			MTK_M4U_ID(36, 14)
+
+/* Larb37 -- 18 */
+#define MT8196_SMI_L37_P0_OVL_RDMA5_HDR		        MTK_M4U_ID(37, 0)
+#define MT8196_SMI_L37_P1_OVL_RDMA8_HDR		        MTK_M4U_ID(37, 1)
+#define MT8196_SMI_L37_P2_OVL_RDMA1_HDR		        MTK_M4U_ID(37, 2)
+#define MT8196_SMI_L37_P3_OVL_RDMA5			MTK_M4U_ID(37, 3)
+#define MT8196_SMI_L37_P4_OVL_RDMA8			MTK_M4U_ID(37, 4)
+#define MT8196_SMI_L37_P5_OVL_RDMA1			MTK_M4U_ID(37, 5)
+#define MT8196_SMI_L37_P6_RESERVED			MTK_M4U_ID(37, 6)
+#define MT8196_SMI_L37_P7_MDP_RDMA0			MTK_M4U_ID(37, 7)
+#define MT8196_SMI_L37_P8_DISP_WDMA0			MTK_M4U_ID(37, 8)
+#define MT8196_SMI_L37_P9_DISP_UFBC_WDMA0		MTK_M4U_ID(37, 9)
+#define MT8196_SMI_L37_P10_OVL_RDMA5_HDR_STASH	        MTK_M4U_ID(37, 10)
+#define MT8196_SMI_L37_P11_OVL_RDMA8_HDR_STASH	        MTK_M4U_ID(37, 11)
+#define MT8196_SMI_L37_P12_OVL_RDMA1_HDR_STASH	        MTK_M4U_ID(37, 12)
+#define MT8196_SMI_L37_P13_OVL_RDMA5_STASH		MTK_M4U_ID(37, 13)
+#define MT8196_SMI_L37_P14_OVL_RDMA8_STASH		MTK_M4U_ID(37, 14)
+#define MT8196_SMI_L37_P15_OVL_RDMA1_STASH		MTK_M4U_ID(37, 15)
+#define MT8196_SMI_L37_P16_MDP_RDMA0_STASH		MTK_M4U_ID(37, 16)
+#define MT8196_SMI_L37_P17_RESERVED			MTK_M4U_ID(37, 17)
+
+/* Larb41 -- 32 */
+#define MT8196_SMI_L41_P0_ADAB_FORMATTER_R		MTK_M4U_ID(41, 0)
+#define MT8196_SMI_L41_P1_REC_FRM			MTK_M4U_ID(41, 1)
+#define MT8196_SMI_L41_P2_ADAB_FORMATTER_W		MTK_M4U_ID(41, 2)
+#define MT8196_SMI_L41_P3_ADAB_CUR_LUMA_R		MTK_M4U_ID(41, 3)
+#define MT8196_SMI_L41_P4_ADAB_REF_LUMA_R		MTK_M4U_ID(41, 4)
+#define MT8196_SMI_L41_P5_NBM_R			        MTK_M4U_ID(41, 5)
+#define MT8196_SMI_L41_P6_NBM_R_LITE			MTK_M4U_ID(41, 6)
+#define MT8196_SMI_L41_P7_JPGENC_YRD			MTK_M4U_ID(41, 7)
+#define MT8196_SMI_L41_P8_JPGENC_CRD			MTK_M4U_ID(41, 8)
+#define MT8196_SMI_L41_P9_JPGENC_QT			MTK_M4U_ID(41, 9)
+#define MT8196_SMI_L41_P10_FCS_SUB_W			MTK_M4U_ID(41, 10)
+#define MT8196_SMI_L41_P11_FCS_NBM_R			MTK_M4U_ID(41, 11)
+#define MT8196_SMI_L41_P12_WPP_BS			MTK_M4U_ID(41, 12)
+#define MT8196_SMI_L41_P13_WPP_RDMA			MTK_M4U_ID(41, 13)
+#define MT8196_SMI_L41_P14_DB_SYSRAM_W		        MTK_M4U_ID(41, 14)
+#define MT8196_SMI_L41_P15_DB_SYSRAM_R		        MTK_M4U_ID(41, 15)
+#define MT8196_SMI_L41_P16_JPGENC_BS			MTK_M4U_ID(41, 16)
+#define MT8196_SMI_L41_P17_JPGDEC_W			MTK_M4U_ID(41, 17)
+#define MT8196_SMI_L41_P18_JPGDEC_BS			MTK_M4U_ID(41, 18)
+#define MT8196_SMI_L41_P19_NBM_W			MTK_M4U_ID(41, 19)
+#define MT8196_SMI_L41_P20_NBM_W_LITE			MTK_M4U_ID(41, 20)
+#define MT8196_SMI_L41_P21_CUR_LUMA			MTK_M4U_ID(41, 21)
+#define MT8196_SMI_L41_P22_CUR_CHROMA			MTK_M4U_ID(41, 22)
+#define MT8196_SMI_L41_P23_REF_LUMA			MTK_M4U_ID(41, 23)
+#define MT8196_SMI_L41_P24_REF_CHROMA			MTK_M4U_ID(41, 24)
+#define MT8196_SMI_L41_P25_FCS_SUB_R			MTK_M4U_ID(41, 25)
+#define MT8196_SMI_L41_P26_FCS_NBM_W			MTK_M4U_ID(41, 26)
+#define MT8196_SMI_L41_P27_JPGDEC_W_1			MTK_M4U_ID(41, 27)
+#define MT8196_SMI_L41_P28_JPGDEC_BS_1		        MTK_M4U_ID(41, 28)
+#define MT8196_SMI_L41_P29_JPGDEC_HUF_1		        MTK_M4U_ID(41, 29)
+#define MT8196_SMI_L41_P30_JPGDEC_HUF			MTK_M4U_ID(41, 30)
+#define MT8196_SMI_L41_P31_EC_SYSRAM			MTK_M4U_ID(41, 31)
+
+/* Larb42 -- 32 */
+#define MT8196_SMI_L42_P0_RCPU			        MTK_M4U_ID(42, 0)
+#define MT8196_SMI_L42_P1_REC_FRM			MTK_M4U_ID(42, 1)
+#define MT8196_SMI_L42_P2_BS				MTK_M4U_ID(42, 2)
+#define MT8196_SMI_L42_P3_SVCOMV			MTK_M4U_ID(42, 3)
+#define MT8196_SMI_L42_P4_RDCOMV			MTK_M4U_ID(42, 4)
+#define MT8196_SMI_L42_P5_NBM_R			        MTK_M4U_ID(42, 5)
+#define MT8196_SMI_L42_P6_NBM_R_LITE			MTK_M4U_ID(42, 6)
+#define MT8196_SMI_L42_P7_JPGENC_YRD			MTK_M4U_ID(42, 7)
+#define MT8196_SMI_L42_P8_JPGENC_CRD			MTK_M4U_ID(42, 8)
+#define MT8196_SMI_L42_P9_JPGENC_QT			MTK_M4U_ID(42, 9)
+#define MT8196_SMI_L42_P10_FCS_SUB_W			MTK_M4U_ID(42, 10)
+#define MT8196_SMI_L42_P11_FCS_NBM_R			MTK_M4U_ID(42, 11)
+#define MT8196_SMI_L42_P12_WPP_BS			MTK_M4U_ID(42, 12)
+#define MT8196_SMI_L42_P13_WPP_RDMA			MTK_M4U_ID(42, 13)
+#define MT8196_SMI_L42_P14_DB_SYSRAM_W		        MTK_M4U_ID(42, 14)
+#define MT8196_SMI_L42_P15_DB_SYSRAM_R		        MTK_M4U_ID(42, 15)
+#define MT8196_SMI_L42_P16_JPGENC_BS			MTK_M4U_ID(42, 16)
+#define MT8196_SMI_L42_P17_JPGDEC_W			MTK_M4U_ID(42, 17)
+#define MT8196_SMI_L42_P18_JPGDEC_BS			MTK_M4U_ID(42, 18)
+#define MT8196_SMI_L42_P19_NBM_W			MTK_M4U_ID(42, 19)
+#define MT8196_SMI_L42_P20_NBM_W_LITE			MTK_M4U_ID(42, 20)
+#define MT8196_SMI_L42_P21_CUR_LUMA			MTK_M4U_ID(42, 21)
+#define MT8196_SMI_L42_P22_CUR_CHROMA			MTK_M4U_ID(42, 22)
+#define MT8196_SMI_L42_P23_REF_LUMA			MTK_M4U_ID(42, 23)
+#define MT8196_SMI_L42_P24_REF_CHROMA			MTK_M4U_ID(42, 24)
+#define MT8196_SMI_L42_P25_FCS_SUB_R			MTK_M4U_ID(42, 25)
+#define MT8196_SMI_L42_P26_FCS_NBM_W			MTK_M4U_ID(42, 26)
+#define MT8196_SMI_L42_P27_JPGDEC_W_1			MTK_M4U_ID(42, 27)
+#define MT8196_SMI_L42_P28_JPGDEC_BS_1		        MTK_M4U_ID(42, 28)
+#define MT8196_SMI_L42_P29_JPGDEC_HUF_1		        MTK_M4U_ID(42, 29)
+#define MT8196_SMI_L42_P30_JPGDEC_HUF			MTK_M4U_ID(42, 30)
+#define MT8196_SMI_L42_P31_EC_SYSRAM			MTK_M4U_ID(42, 31)
+
+/* Larb47 -- 32 */
+#define MT8196_SMI_L47_P0_RCPU			        MTK_M4U_ID(47, 0)
+#define MT8196_SMI_L47_P1_REC_FRM			MTK_M4U_ID(47, 1)
+#define MT8196_SMI_L47_P2_BS				MTK_M4U_ID(47, 2)
+#define MT8196_SMI_L47_P3_SVCOMV			MTK_M4U_ID(47, 3)
+#define MT8196_SMI_L47_P4_RDCOMV			MTK_M4U_ID(47, 4)
+#define MT8196_SMI_L47_P5_NBM_R			        MTK_M4U_ID(47, 5)
+#define MT8196_SMI_L47_P6_NBM_R_LITE			MTK_M4U_ID(47, 6)
+#define MT8196_SMI_L47_P7_JPGENC_YRD			MTK_M4U_ID(47, 7)
+#define MT8196_SMI_L47_P8_JPGENC_CRD			MTK_M4U_ID(47, 8)
+#define MT8196_SMI_L47_P9_JPGENC_QT			MTK_M4U_ID(47, 9)
+#define MT8196_SMI_L47_P10_FCS_SUB_W			MTK_M4U_ID(47, 10)
+#define MT8196_SMI_L47_P11_FCS_NBM_R			MTK_M4U_ID(47, 11)
+#define MT8196_SMI_L47_P12_WPP_BS			MTK_M4U_ID(47, 12)
+#define MT8196_SMI_L47_P13_WPP_RDMA			MTK_M4U_ID(47, 13)
+#define MT8196_SMI_L47_P14_DB_SYSRAM_W		        MTK_M4U_ID(47, 14)
+#define MT8196_SMI_L47_P15_DB_SYSRAM_R		        MTK_M4U_ID(47, 15)
+#define MT8196_SMI_L47_P16_JPGENC_BS			MTK_M4U_ID(47, 16)
+#define MT8196_SMI_L47_P17_JPGDEC_W			MTK_M4U_ID(47, 17)
+#define MT8196_SMI_L47_P18_JPGDEC_BS			MTK_M4U_ID(47, 18)
+#define MT8196_SMI_L47_P19_NBM_W			MTK_M4U_ID(47, 19)
+#define MT8196_SMI_L47_P20_NBM_W_LITE			MTK_M4U_ID(47, 20)
+#define MT8196_SMI_L47_P21_CUR_LUMA			MTK_M4U_ID(47, 21)
+#define MT8196_SMI_L47_P22_CUR_CHROMA			MTK_M4U_ID(47, 22)
+#define MT8196_SMI_L47_P23_REF_LUMA			MTK_M4U_ID(47, 23)
+#define MT8196_SMI_L47_P24_REF_CHROMA			MTK_M4U_ID(47, 24)
+#define MT8196_SMI_L47_P25_FCS_SUB_R			MTK_M4U_ID(47, 25)
+#define MT8196_SMI_L47_P26_FCS_NBM_W			MTK_M4U_ID(47, 26)
+#define MT8196_SMI_L47_P27_JPGDEC_W_1			MTK_M4U_ID(47, 27)
+#define MT8196_SMI_L47_P28_JPGDEC_BS_1		        MTK_M4U_ID(47, 28)
+#define MT8196_SMI_L47_P29_JPGDEC_HUF_1		        MTK_M4U_ID(47, 29)
+#define MT8196_SMI_L47_P30_JPGDEC_HUF			MTK_M4U_ID(47, 30)
+#define MT8196_SMI_L47_P31_EC_SYSRAM			MTK_M4U_ID(47, 31)
+
+/* Fake larb48 */
+#define MT8196_SMI_L48_CCU0				MTK_M4U_ID(48, 0)
+#define MT8196_SMI_L48_CCU1				MTK_M4U_ID(48, 1)
+
+/* Fake larb49 */
+#define MT8196_SMI_L49_MMUP				MTK_M4U_ID(49, 0)
+#define MT8196_SMI_L49_GCE_D				MTK_M4U_ID(49, 1)
+#define MT8196_SMI_L49_GCE_M				MTK_M4U_ID(49, 2)
+
+#endif
diff --git a/include/dt-bindings/memory/mtk-memory-port.h b/include/dt-bindings/memory/mtk-memory-port.h
index 2f68a0511a25..fc47fcfc090e 100644
--- a/include/dt-bindings/memory/mtk-memory-port.h
+++ b/include/dt-bindings/memory/mtk-memory-port.h
@@ -6,10 +6,10 @@
 #ifndef __DT_BINDINGS_MEMORY_MTK_MEMORY_PORT_H_
 #define __DT_BINDINGS_MEMORY_MTK_MEMORY_PORT_H_
 
-#define MTK_LARB_NR_MAX			32
+#define MTK_LARB_NR_MAX			64
 
 #define MTK_M4U_ID(larb, port)		(((larb) << 5) | (port))
-#define MTK_M4U_TO_LARB(id)		(((id) >> 5) & 0x1f)
+#define MTK_M4U_TO_LARB(id)		(((id) >> 5) & 0x3f)
 #define MTK_M4U_TO_PORT(id)		((id) & 0x1f)
 
 #define MTK_IFAIOMMU_PERI_ID(port)	MTK_M4U_ID(0, port)
-- 
2.46.0



From luca.ceresoli at bootlin.com  Thu Mar 20 00:41:18 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 08:41:18 +0100
Subject: [PATCH v7 00/11] drm/bridge: add devm_drm_bridge_alloc() with
 bridge refcount
In-Reply-To: <20250319-stylish-lime-mongoose-0a18ad@houat>
References: <20250314-drm-bridge-refcount-v7-0-152571f8c694@bootlin.com>
	<20250314-daft-woodoo-cheetah-e029c5@houat>
	<20250317155607.68cff522@booty>
	<20250319-stylish-lime-mongoose-0a18ad@houat>
Message-ID: <20250320084118.347bafc9@booty>

Hello Mazime,

On Wed, 19 Mar 2025 17:16:53 +0100
Maxime Ripard <mripard at kernel.org> wrote:

> On Mon, Mar 17, 2025 at 03:56:07PM +0100, Luca Ceresoli wrote:
> > Hello Maxime,
> > 
> > On Fri, 14 Mar 2025 19:21:01 +0100
> > Maxime Ripard <mripard at kernel.org> wrote:
> >   
> > > Hi,
> > > 
> > > On Fri, Mar 14, 2025 at 11:31:13AM +0100, Luca Ceresoli wrote:  
> > > > This series improves the way DRM bridges are allocated and
> > > > initialized and makes them reference-counted. The goal of reference
> > > > counting is to avoid use-after-free by drivers which got a pointer
> > > > to a bridge and keep it stored and used even after the bridge has
> > > > been deallocated.
> > > > 
> > > > The overall goal is supporting Linux devices with a DRM pipeline
> > > > whose final components can be hot-plugged and hot-unplugged,
> > > > including one or more bridges. For more details see the big picture
> > > > [0].
> > > > 
> > > > DRM bridge drivers will have to be adapted to the new API, which is
> > > > pretty simple for most cases. Refcounting will have to be adopted
> > > > on the two sides: all functions returning a bridge pointer and all
> > > > code obtaining such a pointer. This series has just an overview of
> > > > some of those conversions, because for now the main goal is to
> > > > agree on the API.
> > > > 
> > > > Series layout:
> > > > 
> > > >  1. Add the new API and refcounting:
> > > > 
> > > >     drm/bridge: add devm_drm_bridge_alloc()
> > > >     drm/bridge: add support for refcounting
> > > > 
> > > >  2. get/put the reference in basic operations in the bridge core:
> > > > 
> > > >     drm/bridge: get/put the bridge reference in
> > > > drm_bridge_add/remove() drm/bridge: get/put the bridge reference in
> > > > drm_bridge_attach/detach()
> > > > 
> > > >  3. as an example of changes for bridge consumers, get a reference
> > > > for the bridge returned by drm_bridge_chain_get_first_bridge(),
> > > > have it put by all callers (all users will be covered later on
> > > > separately):
> > > > 
> > > >     drm/bridge: add a cleanup action for scope-based
> > > > drm_bridge_put() invocation drm/bridge: get the bridge returned by
> > > > drm_bridge_chain_get_first_bridge() drm/mxsfb: put the bridge
> > > > returned by drm_bridge_chain_get_first_bridge() drm/atomic-helper:
> > > > put the bridge returned by drm_bridge_chain_get_first_bridge()
> > > > drm/probe-helper: put the bridge returned by
> > > > drm_bridge_chain_get_first_bridge()
> > > > 
> > > >  4. convert a few bridge drivers (bridge providers) to the new API:
> > > > 
> > > >     drm/bridge: ti-sn65dsi83: use dynamic lifetime management
> > > >     drm/bridge: samsung-dsim: use dynamic lifetime management
> > > > 
> > > > This work was formerly a part of my v6 DRM bridge hotplug
> > > > series[0], now split as a standalone series with many improvements,
> > > > hence the "v7" version number.    
> > > 
> > > Except for one patch where I had comments, I think the series is in
> > > excellent shape. We're still missing a couple of things to close this
> > > topic though:
> > > 
> > >   - Converting the other bridge iterators/accessors to take / put the
> > > references  
> > 
> > I sent a couple in this series as you had asked, to show how conversion
> > looks like. But I have a large part of this conversion partially done
> > already, and it is the largest part of the refcounting work in terms of
> > touched files due to the large number of drivers using the iterators
> > and accessors. Here are the functions to convert:
> > 
> >  A) drm_bridge_chain_get_first_bridge
> >  B) drm_bridge_get_prev_bridge
> >  C) drm_bridge_get_next_bridge
> >  D) drm_for_each_bridge_in_chain
> >  E) drm_bridge_connector_init
> >  F) of_drm_find_bridge
> > 
> > A) is present in this series as an example but I don't think it should
> > be applied until all bridge drivers are converted to
> > drm_bridge_alloc(). Otherwise for not-yet-converted bridge drivers we'd
> > have drm_bridge_get/put() operating on an uninitialized kref, and
> > __drm_bridge_free() called on non-refcounted bridges, so I think we'd
> > see fireworks.
> > 
> > In the previous iteration I used drm_bridge_is_refcounted() in
> > drm_bridge_get/put() to allow a progressive migration, but if we want
> > to convert everything in a single run we need to first convert all
> > bridges to drm_bridge_alloc() and then convert all accessors.
> > 
> > The same reasoning applies to patches 3-4 which add get/put to
> > drm_bridge_add/remove() and _attach/detach().  
> 
> Agreed.
> 
> > B) to E) are ready in my work branch, about 20 patches in total.
> > Indeed item E) is a special case but it is handled there too.
> > 
> > Item F) is the beast, because of the reverse call graph of
> > of_drm_find_bridge() which includes drm_of_find_panel_or_bridge() and
> > then *_of_get_bridge(), each having a few dozen callers, and leading
> > to the panel_bridge topic. I have converted maybe half of the users of
> > accessors in F), it's 35 patches but it's the easy half and I still need
> > to tackle to hardest ones.  
> 
> One thing to keep in mind is that, while it's not correct, if the bridge
> has been allocated with devm_drm_bridge_alloc, it's not worse either. If
> you're not getting a reference to your pointer, the point is buggy,
> sure, but it's just as buggy as before, and in the same situations.
> 
> So we can make that gradually if it's more convenient.

I see your point, right. And definitely doing it in gradually will help.

> One way to solve it would be that, for example, of_drm_find_bridge is
> oddly named according to our convention and it would make more sense to
> be called drm_of_find_bridge().
> 
> So maybe we can just create drm_of_find_bridge() that takes a reference,
> make of_drm_find_bridge() deprecated in favour of drm_of_find_bridge(),
> add a TODO, and call it a day. People will gradually switch to the new
> API over time.

Thanks for the suggestion, I will certainly try this way when I get
back to the accessor conversion work. While increasing the number of
deprecated functions is not great, I'm starting to suspect a conversion
of _all_ the of_drm_find_bridge() users at once is not realistic.

> > >   - Documenting somewhere (possibly in drm_bridge_init?) that it
> > > really shouldn't be used anymore  
> > 
> > I'm afraid there is no drm_bridge_init(), bridge drivers just do
> > [devm_]kzalloc and set fields explicitly. So I don't think there is a
> > place to document this.  
> 
> Oh, right.
> 
> Then, drm_bridge_add() would be a good candidate too to mention that
> bridges must be allocated using devm_drm_bridge_alloc().

Sure. I'll add such a comment.

> > Overall, I think this could be the path forward, let me know if
> > youthink it should be done differently:
> > 
> >  A. have patches 1 and 2 of this series applied
> >     (why not, even patches 10-11)  
> 
> I had some comments on patch 2, but it's ok for me on principle.

Sorry, my wording was not clear. I really meant "have patches 1 and 2 of
this series applied after the improvements proposed". So hopefully the
v8 I'm sending today-ish. I'm going to send only patches 1, 2, 10 and
11. The other patches are not meant to be merged now, so I'm resending
them when appropriate.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From krzk at kernel.org  Thu Mar 20 00:49:36 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:49:36 +0100
Subject: [PATCH 2/2] dt-bindings: dsp: mediatek: add mt8196 dsp document
In-Reply-To: <20250320031753.13669-3-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
 <20250320031753.13669-3-hailong.fan@mediatek.com>
Message-ID: <20250320-divergent-soft-bird-bcd938@krzk-bin>

On Thu, Mar 20, 2025 at 11:17:25AM +0800, hailong.fan wrote:
> This patch adds mt8196 dsp document. The dsp is used for Sound Open
> Firmware driver node. It includes registers,  clocks, memory regions,
> and mailbox for dsp.
> 
> Signed-off-by: hailong.fan <hailong.fan at mediatek.com>

Don't use login as full name, but proper Latin-alphabet transcription or
original name in UTF.

This cannot be tested due to dependency, so limited review.

> ---
>  .../bindings/dsp/mediatek,mt8196-dsp.yaml     | 96 +++++++++++++++++++

Don't grow dsp directory. Either this is remoteproc or some sound
component, so place it accordingly.

>  1 file changed, 96 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
> 
> diff --git a/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
> new file mode 100644
> index 000000000000..62bcd97bd0f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
> @@ -0,0 +1,96 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/dsp/mediatek,mt8196-dsp.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Mediatek mt8196 DSP core
> +
> +maintainers:
> +  - Hailong Fan <hailong.fan at mediatek.com>
> +
> +description: |

Do not need '|' unless you need to preserve formatting.

> +  Some boards from mt8196 contain a DSP core used for

Boards or MT8196? If boards, how is this related to SoC in the first
place? Thus wrong compatible.

> +  advanced pre- and post- audio processing.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8196-dsp

If this is part of the SoC, then wrong description.

> +
> +  reg:
> +    items:
> +      - description: Address and size of the DSP Cfg registers

s/Address and size of the//

Write concise and accurate description. This cannot be anything else, so
no need to state obvious.

> +      - description: Address and size of the DSP SRAM
> +      - description: Address and size of the DSP secure registers
> +      - description: Address and size of the DSP bus registers
> +
> +  reg-names:
> +    items:
> +      - const: cfg
> +      - const: sram
> +      - const: sec
> +      - const: bus
> +
> +  clocks:
> +    items:
> +      - description: mux for dsp clock
> +      - description: 26M clock
> +      - description: ADSP PLL clock
> +
> +  clock-names:
> +    items:
> +      - const: adsp_sel
> +      - const: clk26m
> +      - const: adsppll
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  mboxes:
> +    items:
> +      - description: mailbox for receiving audio DSP requests.
> +      - description: mailbox for transmitting requests to audio DSP.
> +
> +  mbox-names:
> +    items:
> +      - const: rx
> +      - const: tx
> +
> +  memory-region:
> +    items:
> +      - description: dma buffer between host and DSP.
> +      - description: DSP system memory.
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - clock-names
> +  - power-domains
> +  - mbox-names
> +  - mboxes
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/mt8196-clk.h>
> +    #include <dt-bindings/power/mt8196-power.h>
> +    adsp: adsp at 1a000000 {

Drop unused label

> +        compatible = "mediatek,mt8196-dsp";
> +        reg = <0x1a000000 0x5000>,
> +              <0x1a210000 0x80000>,
> +              <0x1a345000 0x300>,
> +              <0x1a00f000 0x1000>;
> +        reg-names = "cfg", "sram", "sec", "bus";
> +        power-domains = <&scpsys MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT>;
> +        clocks = <&cksys_clk CLK_CK_ADSP_SEL>,
> +                 <&cksys_clk CLK_CK_TCK_26M_MX9>,
> +                 <&cksys_clk CLK_CK_ADSPPLL>;
> +        clock-names = "adsp_sel",
> +                      "clk26m",
> +                      "adsppll";
> +        mbox-names = "rx", "tx";
> +        mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;

Reverse order of mboxes and mbox-names properties. xxx-names follows the
xxx.

Best regards,
Krzysztof



From krzk at kernel.org  Thu Mar 20 00:52:00 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 08:52:00 +0100
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <20250320031753.13669-2-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
 <20250320031753.13669-2-hailong.fan@mediatek.com>
Message-ID: <20250320-cocky-adventurous-rooster-be2abd@krzk-bin>

On Thu, Mar 20, 2025 at 11:17:24AM +0800, hailong.fan wrote:
> +
> +void mt8196_sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
> +{
> +	/* set RUNSTALL to stop core */
> +	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_RUNSTALL,
> +				RUNSTALL, RUNSTALL);
> +
> +	/* assert core reset */
> +	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CFGREG_SW_RSTN,
> +				SW_RSTN_C0 | SW_DBG_RSTN_C0,
> +				SW_RSTN_C0 | SW_DBG_RSTN_C0);
> +}
> +

Drop stray blank line.

> diff --git a/sound/soc/sof/mediatek/mt8196/mt8196.c b/sound/soc/sof/mediatek/mt8196/mt8196.c
> new file mode 100644
> index 000000000000..364069ce9954
> --- /dev/null
> +++ b/sound/soc/sof/mediatek/mt8196/mt8196.c
> @@ -0,0 +1,650 @@
> +// SPDX-License-Identifier: GPL-2.0

Look here

> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + * Author: Hailong Fan <hailong.fan at mediatek.com>
> + */

...

> +
> +static const struct of_device_id sof_of_mt8196_ids[] = {
> +	{ .compatible = "mediatek,mt8196-dsp", .data = &sof_of_mt8196_desc},

Bindings are before users.

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sof_of_mt8196_ids);
> +
> +/* DT driver definition */
> +static struct platform_driver snd_sof_of_mt8196_driver = {
> +	.probe = sof_of_probe,
> +	.remove = sof_of_remove,
> +	.shutdown = sof_of_shutdown,
> +	.driver = {
> +	.name = "sof-audio-of-mt8196",
> +		.pm = &sof_of_pm,
> +		.of_match_table = sof_of_mt8196_ids,
> +	},
> +};
> +module_platform_driver(snd_sof_of_mt8196_driver);
> +
> +MODULE_LICENSE("Dual BSD/GPL");

And here Hm? Don't fake the licensing.

> +MODULE_DESCRIPTION("SOF support for MT8196 platforms");
> +MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");

Is this correct?


Best regards,
Krzysztof



From ardb at kernel.org  Thu Mar 20 00:57:47 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Thu, 20 Mar 2025 08:57:47 +0100
Subject: [RFC PATCH] arm64/mm: Remove randomization of the linear map
In-Reply-To: <20250318134949.3194334-2-ardb+git@google.com>
References: <20250318134949.3194334-2-ardb+git@google.com>
Message-ID: <CAMj1kXHXAYt0xLnx4=+qiCbnuF5U+9dzwnds1yd+vhTtpP5v3Q@mail.gmail.com>

On Tue, 18 Mar 2025 at 14:50, Ard Biesheuvel <ardb+git at google.com> wrote:
>
> From: Ard Biesheuvel <ardb at kernel.org>
>
> Since commit
>
>   97d6786e0669 ("arm64: mm: account for hotplug memory when randomizing the linear region")
>
> the decision whether or not to randomize the placement of the system's
> DRAM inside the linear map is based on the capabilities of the CPU
> rather than how much memory is present at boot time. This change was
> necessary because memory hotplug may result in DRAM appearing in places
> that are not covered by the linear region at all (and therefore
> unusable) if the decision is solely based on the memory map at boot.
>
> In the Android GKI kernel, which requires support for memory hotplug,
> and is built with a reduced virtual address space of only 39 bits wide,
> randomization of the linear map never happens in practice as a result.
> And even on arm64 kernels built with support for 48 bit virtual
> addressing, the wider PArange of recent CPUs means that linear map
> randomization is slowly becoming a feature that only works on systems
> that will soon be obsolete.
>
> So let's just remove this feature. We can always bring it back in an
> improved form if there is a real need for it.
>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Ryan Roberts <ryan.roberts at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Cc: Kees Cook <kees at kernel.org>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>

Additional note based on an off-list discussion with Kees and the KSPP team:

Initially, the randomization of the linear map was considered to be a
layer of defense against the abuse of writable linear aliases of
read-only mappings in the vmalloc range, such as module text and
rodata. This has been addressed in the meantime, by mapping the linear
region down to pages by default, and mapping linear aliases read-only
if the vmalloc mapping is read-only.

So considering that, and the fact that randomization of the linear map
occurs rarely if at all on recent CPUs, I think we should go ahead and
remove this feature.


From joro at 8bytes.org  Thu Mar 20 00:58:43 2025
From: joro at 8bytes.org (Joerg Roedel)
Date: Thu, 20 Mar 2025 08:58:43 +0100
Subject: [PATCH 0/3] Rockchip IOMMU fixes
In-Reply-To: <cover.1741886382.git.robin.murphy@arm.com>
References: <cover.1741886382.git.robin.murphy@arm.com>
Message-ID: <Z9vKs63e1s73MauO@8bytes.org>

On Thu, Mar 13, 2025 at 05:31:03PM +0000, Robin Murphy wrote:
> Hi all,
> 
> I was expecting my DT probing change to flush out issues, and it seems
> some weaknesses in rockchip-iommu were the first to show. The first two
> patches here get things working again for me on my RK3399 NanoPC-T4
> (with a console on HDMI exercising the VOP MMU), the 3rd patch just
> finishes the cleanup since I was there and could test it.
> 
> Thanks,
> Robin.
> 
> Robin Murphy (3):
>   iommu/rockchip: Allocate per-device data sensibly
>   iommu/rockchip: Register in a sensible order
>   iommu/rockchip: Retire global dma_dev workaround
> 
>  drivers/iommu/rockchip-iommu.c | 61 +++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 35 deletions(-)

Applied, thanks.


From linus.walleij at linaro.org  Thu Mar 20 01:15:34 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 20 Mar 2025 09:15:34 +0100
Subject: [PATCH v2 0/5] pinctrl: nuvoton: A few cleanups and a fix
In-Reply-To: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com>
Message-ID: <CACRpkdbTKytFgdqyDajpcfENagSXPZhG5hbpQiGF23VHqLd9_A@mail.gmail.com>

On Tue, Mar 18, 2025 at 11:59?AM Andy Shevchenko
<andriy.shevchenko at linux.intel.com> wrote:

> Convert Nuvoton drivers to use pin control provided data types
> and more of device property APIs.
>
> While doing that, fix one non-critical issue that sparse complains about.
>
> Compile tested only.

Patches LGTM and we are close to the merge window so I have
just applied them.

If there are any issues we can surely fix it up in -next.

Thanks Andy!

Yours,
Linus Walleij


From cleger at rivosinc.com  Thu Mar 20 01:16:07 2025
From: cleger at rivosinc.com (=?UTF-8?B?Q2zDqW1lbnQgTMOpZ2Vy?=)
Date: Thu, 20 Mar 2025 09:16:07 +0100
Subject: [PATCH v3 2/4] riscv: add support for SBI Supervisor Software
 Events extension
In-Reply-To: <20250319-46b625cf8b771616d4c7c053@orel>
References: <20241206163102.843505-1-cleger@rivosinc.com>
 <20241206163102.843505-3-cleger@rivosinc.com>
 <20250319-46b625cf8b771616d4c7c053@orel>
Message-ID: <b3fbd730-295f-4491-b0d6-d4e258941ae5@rivosinc.com>



On 19/03/2025 18:08, Andrew Jones wrote:
> On Fri, Dec 06, 2024 at 05:30:58PM +0100, Cl?ment L?ger wrote:
> ...
>> +int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cpu)
>> +{
>> +	void *stack;
>> +
>> +	arch_evt->evt_id = evt_id;
>> +	stack = sse_stack_alloc(cpu, SSE_STACK_SIZE);
>> +	if (!stack)
>> +		return -ENOMEM;
>> +
>> +	arch_evt->stack = stack + SSE_STACK_SIZE;
>> +
>> +	if (sse_init_scs(cpu, arch_evt))
>> +		goto free_stack;
>> +
>> +	if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
>> +		arch_evt->interrupted_state_phys =
>> +				per_cpu_ptr_to_phys(&arch_evt->interrupted);
>> +	} else {
>> +		arch_evt->interrupted_state_phys =
>> +				virt_to_phys(&arch_evt->interrupted);
>> +	}
>> +
>> +	return 0;
> 
> Hi Cl?ment,
> 
> Testing SSE support with tools/testing/selftests/kvm/riscv/sbi_pmu_test
> led to an opensbi sbi_trap_error because the output_phys_lo address passed
> to sbi_sse_read_attrs() wasn't a physical address. The reason is that
> is_kernel_percpu_address() can only be used on static percpu addresses,
> but local sse events get their percpu addresses with alloc_percpu(), so
> is_kernel_percpu_address() was returning false even for local events. I
> made the following changes to get things working.

Hi Andrew,

Did something changed recently ? Because I tested that when it was send
(PMU + some kernel internal testsuite) and didn't saw that. Anyway, I'll
respin it with your changes as well.

Thanks !

Cl?ment

> 
> Thanks,
> drew
> 
> diff --git a/arch/riscv/kernel/sse.c b/arch/riscv/kernel/sse.c
> index b48ae69dad8d..f46893946086 100644
> --- a/arch/riscv/kernel/sse.c
> +++ b/arch/riscv/kernel/sse.c
> @@ -100,12 +100,12 @@ int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cp
>         if (sse_init_scs(cpu, arch_evt))
>                 goto free_stack;
> 
> -       if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
> +       if (sse_event_is_global(evt_id)) {
>                 arch_evt->interrupted_state_phys =
> -                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
> +                               virt_to_phys(&arch_evt->interrupted);
>         } else {
>                 arch_evt->interrupted_state_phys =
> -                               virt_to_phys(&arch_evt->interrupted);
> +                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
>         }
> 
>         return 0;
> diff --git a/drivers/firmware/riscv/riscv_sse.c b/drivers/firmware/riscv/riscv_sse.c
> index 511db9ad7a9e..fef375046f75 100644
> --- a/drivers/firmware/riscv/riscv_sse.c
> +++ b/drivers/firmware/riscv/riscv_sse.c
> @@ -62,11 +62,6 @@ void sse_handle_event(struct sse_event_arch_data *arch_event,
>                         ret);
>  }
> 
> -static bool sse_event_is_global(u32 evt)
> -{
> -       return !!(evt & SBI_SSE_EVENT_GLOBAL);
> -}
> -
>  static
>  struct sse_event *sse_event_get(u32 evt)
>  {
> diff --git a/include/linux/riscv_sse.h b/include/linux/riscv_sse.h
> index 16700677f1e8..06b757b036b0 100644
> --- a/include/linux/riscv_sse.h
> +++ b/include/linux/riscv_sse.h
> @@ -8,6 +8,7 @@
> 
>  #include <linux/types.h>
>  #include <linux/linkage.h>
> +#include <asm/sbi.h>
> 
>  struct sse_event;
>  struct pt_regs;
> @@ -16,6 +17,11 @@ struct ghes;
> 
>  typedef int (sse_event_handler)(u32 event_num, void *arg, struct pt_regs *regs);
> 
> +static inline bool sse_event_is_global(u32 evt)
> +{
> +       return !!(evt & SBI_SSE_EVENT_GLOBAL);
> +}
> +
>  #ifdef CONFIG_RISCV_SSE
> 
>  struct sse_event *sse_event_register(u32 event_num, u32 priority,



From mazziesaccount at gmail.com  Thu Mar 20 01:21:45 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 20 Mar 2025 10:21:45 +0200
Subject: [PATCH v9 5/8] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1742457420.git.mazziesaccount@gmail.com>
References: <cover.1742457420.git.mazziesaccount@gmail.com>
Message-ID: <bd0a5b7cb9b98319941ea246953866c61fba6540.1742457420.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
help drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-properties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

---
NOTE: This change now drops a print "no channel children" which used to
be printed if no channel nodes were found. It also changes the return
value from -ENODEV to -ENOENT.

Revision history:
v8 =>
 - No changes
v7 => v8:
 - drop explicit "no channels check". It is now done inside the
   devm_iio_adc_device_alloc_chaninfo_se().
v6 => v7:
 - Fix function name in the commit message
v5 => v6:
 - Commit message typofix
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 39 +++++++++++-------------------
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..2428ea69d676 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,36 +150,23 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
-	if (num_channels == 0)
-		return dev_err_probe(dev, -ENODEV, "no channel children\n");
-
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
 
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
@@ -271,3 +259,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250320/4746f8a3/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 20 01:22:14 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 20 Mar 2025 10:22:14 +0200
Subject: [PATCH v9 7/8] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1742457420.git.mazziesaccount@gmail.com>
References: <cover.1742457420.git.mazziesaccount@gmail.com>
Message-ID: <c81db29201f10b50f03971bc43fc6fc1c63ec4c8.1742457420.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
v2 =>
 - No changes
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250320/1922efa4/attachment.sig>

From Chun-Jen.Tseng at mediatek.com  Thu Mar 20 01:22:20 2025
From: Chun-Jen.Tseng at mediatek.com (=?utf-8?B?Q2h1bi1KZW4gVHNlbmcgKOabvuS/iuS7gSk=?=)
Date: Thu, 20 Mar 2025 08:22:20 +0000
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
	 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
	 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
Message-ID: <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>

Hi viresh,

Thanks your review and reply.

The struct mtk_cpu_dvfs_info instance is per-policy and the reg_lock is
also in this structure. when I have two "policy-0" and "policy-6" use
the same mtk_cpufreq_set_target() function but the info->reg_lock?
is from 2 instance(policy-0 and policy-6). when the policy-0 and
policy-6 call set_target target, the mutex_lock is locked by per-
policy. So, I change to global lock avoid per-policy lock.

BRs,

Mark Tseng

On Wed, 2025-02-19 at 11:12 +0530, Viresh Kumar wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 14-02-25, 15:43, Mark Tseng wrote:
> > In mtk_cpufreq_set_target() is re-enter function but the mutex lock
> > decalre in mtk_cpu_dvfs_info structure for each policy. It should
> > change to global variable for critical session avoid race condition
> > with 2 or more policy.
> 
> And what exactly is the race condition here ? Can you please explain
> that ?
> Since the struct mtk_cpu_dvfs_info instance is per-policy, I don't
> think there
> is any race here.
> 
> The lock was introduced earlier to avoid a potential race with
> notifiers, but it
> has nothing to do with calling target simultaneously.
> 
> commit c210063b40ac ("cpufreq: mediatek: Add opp notification
> support")
> 
> --
> viresh

From Chun-Jen.Tseng at mediatek.com  Thu Mar 20 01:25:07 2025
From: Chun-Jen.Tseng at mediatek.com (=?utf-8?B?Q2h1bi1KZW4gVHNlbmcgKOabvuS/iuS7gSk=?=)
Date: Thu, 20 Mar 2025 08:25:07 +0000
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <23e24631-aee4-43cc-8f85-29ec58241c03@stanley.mountain>
References: <23e24631-aee4-43cc-8f85-29ec58241c03@stanley.mountain>
Message-ID: <9ba3d616d3c65403dbc71128572416d9a40fb968.camel@mediatek.com>

Hi Dan,

Thanks your remind. I will be careful and fix it before submit new
patch.

BRs,

Mark Tseng


On Wed, 2025-02-19 at 10:23 +0300, Dan Carpenter wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Hi Mark,
> 
> kernel test robot noticed the following build warnings:
> 
> https://urldefense.com/v3/__https://git-scm.com/docs/git-format-patch*_base_tree_information__;Iw!!CTRNKA9wMg0ARbw!ixPI3aPvvJSSIiRSm4TttWZyeSNnZsdzX-4zYkY7Ax1faRLZBJ7JW3Fmf7O8BYXiyHlxDC6aauOslVt8KEW_jViJAkm7uw$
> ?]
> 
> url:???
> https://urldefense.com/v3/__https://github.com/intel-lab-lkp/linux/commits/Mark-Tseng/cpufreq-mediatek-using-global-lock-avoid-race-condition/20250214-154521__;!!CTRNKA9wMg0ARbw!ixPI3aPvvJSSIiRSm4TttWZyeSNnZsdzX-4zYkY7Ax1faRLZBJ7JW3Fmf7O8BYXiyHlxDC6aauOslVt8KEW_jVj9Egobdw$
> base:??
> https://urldefense.com/v3/__https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git__;!!CTRNKA9wMg0ARbw!ixPI3aPvvJSSIiRSm4TttWZyeSNnZsdzX-4zYkY7Ax1faRLZBJ7JW3Fmf7O8BYXiyHlxDC6aauOslVt8KEW_jVg7ujqlQw$
> ? linux-next
> patch link:???
> https://lore.kernel.org/r/20250214074353.1169864-2-chun-jen.tseng%40mediatek.com
> patch subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock
> avoid race condition
> config: sparc-randconfig-r071-20250218
> (https://urldefense.com/v3/__https://download.01.org/0day-ci/archive/
> 20250219/202502190807.fz6fs2jz-lkp at intel.com/config__;!!CTRNKA9wMg0AR
> bw!ixPI3aPvvJSSIiRSm4TttWZyeSNnZsdzX-
> 4zYkY7Ax1faRLZBJ7JW3Fmf7O8BYXiyHlxDC6aauOslVt8KEW_jVhUidk_DA$?)
> compiler: sparc64-linux-gcc (GCC) 14.2.0
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new
> version of
> the same patch/commit), kindly add following tags
> > Reported-by: kernel test robot <lkp at intel.com>
> > Reported-by: Dan Carpenter <dan.carpenter at linaro.org>
> > Closes:
> > https://lore.kernel.org/r/202502190807.fz6fs2jz-lkp at intel.com/
> 
> smatch warnings:
> drivers/cpufreq/mediatek-cpufreq.c:367 mtk_cpufreq_opp_notifier()
> warn: inconsistent returns 'global &mtk_policy_lock'.
> 
> vim +367 drivers/cpufreq/mediatek-cpufreq.c
> 
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 317? static int mtk_cpufreq_opp_notifier(struct notifier_block
> *nb,
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 318???????????????????????????????????? unsigned long event,
> void *data)
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 319? {
> 5f81d7eeae239d drivers/cpufreq/mediatek-cpufreq.c Mark Tseng??? 2025-
> 02-14? 320???????? struct dev_pm_opp *opp;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 321???????? struct dev_pm_opp *new_opp;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 322???????? struct mtk_cpu_dvfs_info *info;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 323???????? unsigned long freq, volt;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 324???????? struct cpufreq_policy *policy;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 325???????? int ret = 0;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 326
> 5f81d7eeae239d drivers/cpufreq/mediatek-cpufreq.c Mark Tseng??? 2025-
> 02-14? 327???????? mutex_lock(&mtk_policy_lock);
> 5f81d7eeae239d drivers/cpufreq/mediatek-cpufreq.c Mark Tseng??? 2025-
> 02-14? 328???????? opp = data;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 329???????? info = container_of(nb, struct mtk_cpu_dvfs_info,
> opp_nb);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 330
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 331???????? if (event == OPP_EVENT_ADJUST_VOLTAGE) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 332???????????????? freq = dev_pm_opp_get_freq(opp);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 333
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 334???????????????? if (info->current_freq == freq) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 335???????????????????????? volt =
> dev_pm_opp_get_voltage(opp);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 336???????????????????????? ret =
> mtk_cpufreq_set_voltage(info, volt);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 337???????????????????????? if (ret)
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 338???????????????????????????????? dev_err(info->cpu_dev,
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 339???????????????????????????????????????? "failed to scale
> voltage: %d\n", ret);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 340???????????????? }
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 341???????? } else if (event == OPP_EVENT_DISABLE) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 342???????????????? freq = dev_pm_opp_get_freq(opp);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 343
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 344???????????????? /* case of current opp item is disabled */
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 345???????????????? if (info->current_freq == freq) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 346???????????????????????? freq = 1;
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 347???????????????????????? new_opp =
> dev_pm_opp_find_freq_ceil(info->cpu_dev,
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05?
> 348????????????????????????????????????????????????????????????
> &freq);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 349???????????????????????? if (IS_ERR(new_opp)) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 350???????????????????????????????? dev_err(info->cpu_dev,
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 351???????????????????????????????????????? "all opp items are
> disabled\n");
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 352???????????????????????????????? ret = PTR_ERR(new_opp);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 353???????????????????????????????? return
> notifier_from_errno(ret);
> 
> mutex_unlock(&mtk_policy_lock) before returning.
> 
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 354???????????????????????? }
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 355
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 356???????????????????????? dev_pm_opp_put(new_opp);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 357???????????????????????? policy = cpufreq_cpu_get(info-
> >opp_cpu);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 358???????????????????????? if (policy) {
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 359????????????????????????????????
> cpufreq_driver_target(policy, freq / 1000,
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 360??????????????????????????????????????????????????????
> CPUFREQ_RELATION_L);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 361???????????????????????????????? cpufreq_cpu_put(policy);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 362???????????????????????? }
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 363???????????????? }
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 364???????? }
> 5f81d7eeae239d drivers/cpufreq/mediatek-cpufreq.c Mark Tseng??? 2025-
> 02-14? 365???????? mutex_unlock(&mtk_policy_lock);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 366
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05 @367???????? return notifier_from_errno(ret);
> c210063b40acab drivers/cpufreq/mediatek-cpufreq.c Rex-BC Chen?? 2022-
> 05-05? 368? }
> 
> --
> 0-DAY CI Kernel Test Service
> https://urldefense.com/v3/__https://github.com/intel/lkp-tests/wiki__;!!CTRNKA9wMg0ARbw!ixPI3aPvvJSSIiRSm4TttWZyeSNnZsdzX-4zYkY7Ax1faRLZBJ7JW3Fmf7O8BYXiyHlxDC6aauOslVt8KEW_jVii1cx6tQ$
> 


From neil.armstrong at linaro.org  Thu Mar 20 01:27:23 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Thu, 20 Mar 2025 09:27:23 +0100
Subject: [GIT PULL] amlogic ARM64 DT updates for v6.15
In-Reply-To: <47683e40-aa0e-4d86-9226-94f7d56f34ae@app.fastmail.com>
References: <41ced8db-caeb-4deb-9193-9802fc603180@linaro.org>
 <47683e40-aa0e-4d86-9226-94f7d56f34ae@app.fastmail.com>
Message-ID: <49026ae3-bf51-40ee-990a-e1cfc03e0c35@linaro.org>

Hi,

On 19/03/2025 21:57, Arnd Bergmann wrote:
> On Mon, Mar 17, 2025, at 17:13, Neil Armstrong wrote:
>> Hi,
>>
>> Here's a changeset for Amlogic ARM64 DT, also switching to the new PWM bindings,
>> adding pinctrl support for Amlogic A4 SoC with a brand new binding style then
>> finally gpio_intc node for Amlogic A4 & A5 SoCs.
> 
> I'll skip this one for 6.15, seeing that the branch contains both
> driver and devicetree changes, which messes up the way I send
> the contents.

Sure, I can strip out the pinctrl DT changes, since they can definitely wait another cycle.

> 
>  From the description I also can't tell to what degree there is
> backwards compatibility in the new binding, I assume the changed
> PWM and pinctrl drivers continue to work find with the old dts
> but not the other way round, which is why you sent them together?

For the PWM bindings, they are in -next for a long time already, and
everything was done to keep the old bindings still work over time.

So we're pretty confident it works fine since it has run over CI for
multiple months.

I'll resent a new PR without the new A4 pinctrl changes.

Thanks,
Neil

> 
>       Arnd



From lkp at intel.com  Thu Mar 20 01:29:52 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 20 Mar 2025 16:29:52 +0800
Subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
In-Reply-To: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
Message-ID: <202503201641.wf8Oe0aR-lkp@intel.com>

Hi jiebing,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab]

url:    https://github.com/intel-lab-lkp/linux/commits/jiebing-chen-via-B4-Relay/dt-bindings-clock-meson-Add-audio-power-domain-for-s4-soc/20250319-151110
base:   6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
patch link:    https://lore.kernel.org/r/20250319-audio_drvier-v4-4-686867fad719%40amlogic.com
patch subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250320/202503201641.wf8Oe0aR-lkp at intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250320/202503201641.wf8Oe0aR-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503201641.wf8Oe0aR-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> sound/soc/meson/g12a-toacodec.c:135:38: warning: unused variable 's4_toacodec_clk_enable' [-Wunused-const-variable]
     135 | static const struct snd_kcontrol_new s4_toacodec_clk_enable =
         |                                      ^~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +/s4_toacodec_clk_enable +135 sound/soc/meson/g12a-toacodec.c

   112	
   113	static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0,
   114				    CTRL0_DAT_SEL_LSB,
   115				    g12a_toacodec_mux_texts);
   116	
   117	static SOC_ENUM_SINGLE_DECL(sm1_toacodec_mux_enum, TOACODEC_CTRL0,
   118				    CTRL0_DAT_SEL_SM1_LSB,
   119				    g12a_toacodec_mux_texts);
   120	
   121	static const struct snd_kcontrol_new g12a_toacodec_mux =
   122		SOC_DAPM_ENUM_EXT("Source", g12a_toacodec_mux_enum,
   123				  snd_soc_dapm_get_enum_double,
   124				  g12a_toacodec_mux_put_enum);
   125	
   126	static const struct snd_kcontrol_new sm1_toacodec_mux =
   127		SOC_DAPM_ENUM_EXT("Source", sm1_toacodec_mux_enum,
   128				  snd_soc_dapm_get_enum_double,
   129				  g12a_toacodec_mux_put_enum);
   130	
   131	static const struct snd_kcontrol_new g12a_toacodec_out_enable =
   132		SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
   133					    CTRL0_ENABLE_SHIFT, 1, 0);
   134	
 > 135	static const struct snd_kcontrol_new s4_toacodec_clk_enable =
   136		SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
   137				CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
   138	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From krzk at kernel.org  Thu Mar 20 01:30:46 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 09:30:46 +0100
Subject: [PATCH v5 12/16] arm64: add KHO support
In-Reply-To: <55a5e3f3-1b3f-469b-bde0-69abfff826e4@kernel.org>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-13-changyuanl@google.com>
 <55a5e3f3-1b3f-469b-bde0-69abfff826e4@kernel.org>
Message-ID: <20250320-muscular-cougar-of-apotheosis-e4c80b@krzk-bin>

On Thu, Mar 20, 2025 at 08:13:24AM +0100, Krzysztof Kozlowski wrote:
> On 20/03/2025 02:55, Changyuan Lyu wrote:
> >  
> > +/**
> > + * early_init_dt_check_kho - Decode info required for kexec handover from DT
> > + */
> > +static void __init early_init_dt_check_kho(void)
> > +{
> > +	unsigned long node = chosen_node_offset;
> > +	u64 kho_start, scratch_start, scratch_size;
> > +	const __be32 *p;
> > +	int l;
> > +
> > +	if (!IS_ENABLED(CONFIG_KEXEC_HANDOVER) || (long)node < 0)
> > +		return;
> > +
> > +	p = of_get_flat_dt_prop(node, "linux,kho-fdt", &l);
> 
> 
> You are adding undocumented ABI for OF properties. That's not what was
> explained last time.
> 
> NAK.

Also there are checkpatch warnings :/

Best regards,
Krzysztof



From mazziesaccount at gmail.com  Thu Mar 20 01:20:32 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 20 Mar 2025 10:20:32 +0200
Subject: [PATCH v9 0/8] Support ROHM BD79124 ADC
Message-ID: <cover.1742457420.git.mazziesaccount@gmail.com>

Support ROHM BD79124 ADC.

This series adds also couple of IIO ADC helper functions for parsing the
channel information from the device tree. There are also new helpers
included for iterating and counting firmware child nodes with a specific
name.

The rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.

There has been some discussion about how useful these ADC helpers are,
and whether they should support also differential and single ended channel
configurations. This version does not include support for those - with the
benefit of reduced complexity and easier to use API.

NOTE: The rzg2l_adc and the sun20i-gpadc are untested as I lack of relevant
HW. They have been compile tested only.

The ROHM BD79124 ADC itself is quite usual stuff. 12-bit, 8-channel ADC
with threshold monitoring.

Except that:
 - each ADC input pin can be configured as a general purpose output.
 - manually starting an ADC conversion and reading the result would
   require the I2C _master_ to do clock stretching(!) for the duration
   of the conversion... Let's just say this is not well supported.
 - IC supports 'autonomous measurement mode' and storing latest results
   to the result registers. This mode is used by the driver due to the
   "peculiar" I2C when doing manual reads.

Furthermore, the ADC uses this continuous autonomous measuring,
and the IC keeps producing new 'out of window' IRQs if measurements are
out of window - the driver disables the event for 1 seconds when sending
it to user. This prevents generating storm of events

Revision history:

v8 => v9:
 - Drop the gianfar and the thp7312 drivers from the series to limit the
   review noise and to simplify the merging. They can be submitted later
   as separate changes.
 - Drop the fwnode_for_each_available_named_child() as suggested by
   Sakari.
 - BD79124 driver styling and fixes

v7 => v8:
  property helpers:
    - Fix the example in fwnode_get_named_child_node_count() documentation
      to use the fwnode_get_named_child_node_count() and not the
      device_get_named_child_node_count()
    - Fix the rest of the new macro's indentiations
  adc helpers:
    - Treat 0 ADC channels as an error in
      devm_iio_adc_device_alloc_chaninfo_se().
  rzg2l_adc / sun20i-gpadc:
    - Drop zero channels check from the ADC drivers using
      devm_iio_adc_device_alloc_chaninfo_se()
  BD79124:
    - Use unsigned for regmap values
    - Commit message fine tuning
    - Check devm_mutex_init() return value
    - Handle 'ALL pins as ADC or GPO' cleanly in BD79124 driver
    - BD79124 styling / typofixes

v6 => v7:
 - Inline device_get_named_child_node_count()
 - Fix kernel-doc for fwnode_get_named_child_node_count()
 - Minor styling fixes
 More accurate changelog in individual patches.

v5 => v6:
 - Drop applied patch
 - Add *_for_each_named_child_* iterators
 - Add a patch converting the thp7312 driver to use the new helper
 - Styling and minor things pointed by reviewers

v4 => v5: Fixes as per various review comments. Most notably:
 - Drop the patch making the TI's ADC driver to respect device tree.
 - Add (RFC) patch converting gianfar driver to use new name child-node
   counting API as suggested by Andy.
 - Add fwnode_get_child_node_count_named() as suggested by Rob.
 - rebase to v6.14-rc5
 More accurate changelog in individual patches.

v3 => v4:
 - Drop the ADC helper support for differential channels
 - Drop the ADC helper for getting only channel IDs by fwnode.
 - "Promote" the function counting the number of child nodes with a
   specific name to the property.h (As suggested by Jonathan).
 - Add ADC helpers to a namespace.
 - Rebase on v6.14-rc3
 - More minor changes described in individual patches.

v2 => v3:
 - Restrict BD79124 channel numbers as suggested by Conor and add
   Conor's Reviewed-by tag.
 - Support differential and single-ended inputs
 - Convert couple of existing drivers to use the added ADC helpers
 - Minor fixes based on reviews
Link to v2:
https://lore.kernel.org/all/cover.1738761899.git.mazziesaccount at gmail.com/

RFC v1 => v2:
 - Drop MFD and pinmux.
 - Automatically re-enable events after 1 second.
 - Export fwnode parsing helpers for finding the ADC channels.

---

Matti Vaittinen (8):
  dt-bindings: ROHM BD79124 ADC/GPO
  property: Add functions to iterate named child
  iio: adc: add helpers for parsing ADC nodes
  iio: adc: rzg2l_adc: Use adc-helpers
  iio: adc: sun20i-gpadc: Use adc-helpers
  iio: adc: Support ROHM BD79124 ADC
  MAINTAINERS: Add IIO ADC helpers
  MAINTAINERS: Add ROHM BD79124 ADC/GPO

 .../bindings/iio/adc/rohm,bd79124.yaml        |  114 ++
 MAINTAINERS                                   |   12 +
 drivers/base/property.c                       |   27 +
 drivers/iio/adc/Kconfig                       |   17 +
 drivers/iio/adc/Makefile                      |    3 +
 drivers/iio/adc/industrialio-adc.c            |   82 ++
 drivers/iio/adc/rohm-bd79124.c                | 1138 +++++++++++++++++
 drivers/iio/adc/rzg2l_adc.c                   |   39 +-
 drivers/iio/adc/sun20i-gpadc-iio.c            |   39 +-
 include/linux/iio/adc-helpers.h               |   27 +
 include/linux/property.h                      |   20 +
 11 files changed, 1470 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 drivers/iio/adc/rohm-bd79124.c
 create mode 100644 include/linux/iio/adc-helpers.h


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250320/31e97b81/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 20 01:21:02 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 20 Mar 2025 10:21:02 +0200
Subject: [PATCH v9 2/8] property: Add functions to iterate named child
In-Reply-To: <cover.1742457420.git.mazziesaccount@gmail.com>
References: <cover.1742457420.git.mazziesaccount@gmail.com>
Message-ID: <fd959b10904a401d3f6fb855933be1a4750ef670.1742457420.git.mazziesaccount@gmail.com>

There are a few use-cases where child nodes with a specific name need to
be parsed. Code like:

fwnode_for_each_child_node()
	if (fwnode_name_eq())
		...

can be found from a various drivers/subsystems. Adding a macro for this
can simplify things a bit.

In a few cases the data from the found nodes is later added to an array,
which is allocated based on the number of found nodes. One example of
such use is the IIO subsystem's ADC channel nodes, where the relevant
nodes are named as channel[@N].

Add helpers for iterating and counting device's sub-nodes with certain
name instead of open-coding this in every user.

Suggested-by: Jonathan Cameron <jic23 at kernel.org>
Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
Reviewed-by: Marcelo Schmitt <marcelo.schmitt1 at gmail.com>
---
Revision history:
v8 => v9:
 - Drop the fwnode_for_each_available_named_child_node() as suggested
   by Sakari during v8 review:
   https://lore.kernel.org/all/Z9mQPJwnKAkPHriT at kekkonen.localdomain/
v7 => v8:
 - Fix the example in fwnode_get_named_child_node_count() documentation
   to use the fwnode_get_named_child_node_count() and not the
   device_get_named_child_node_count()
 - Fix the rest of the new macro's indentiations
v6 => v7:
 - Improve kerneldoc
 - Inline device_get_named_child_node_count() and change it to call
   fwnode_get_named_child_node_count() inside
 - Fix indentiation of the new macros
v5 => v6:
 - Add helpers to also iterate through the nodes.
v4 => v5:
 - Use given name instead of string 'channel' when counting the nodes
 - Add also fwnode_get_child_node_count_named() as suggested by Rob.
v3 => v4:
 - New patch as suggested by Jonathan, see discussion in:
https://lore.kernel.org/lkml/20250223161338.5c896280 at jic23-huawei/
---
 drivers/base/property.c  | 27 +++++++++++++++++++++++++++
 include/linux/property.h | 20 ++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index c1392743df9c..f42f32ff45fc 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -945,6 +945,33 @@ unsigned int device_get_child_node_count(const struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_child_node_count);
 
+/**
+ * fwnode_get_named_child_node_count - number of child nodes with given name
+ * @fwnode: Node which child nodes are counted.
+ * @name: String to match child node name against.
+ *
+ * Scan child nodes and count all the nodes with a specific name. Potential
+ * 'number' -ending after the 'at sign' for scanned names is ignored.
+ * E.g.::
+ *   fwnode_get_named_child_node_count(fwnode, "channel");
+ * would match all the nodes::
+ *   channel { }, channel at 0 {}, channel at 0xabba {}...
+ *
+ * Return: the number of child nodes with a matching name for a given device.
+ */
+unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
+					       const char *name)
+{
+	struct fwnode_handle *child;
+	unsigned int count = 0;
+
+	fwnode_for_each_named_child_node(fwnode, child, name)
+		count++;
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_named_child_node_count);
+
 bool device_dma_supported(const struct device *dev)
 {
 	return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
diff --git a/include/linux/property.h b/include/linux/property.h
index e214ecd241eb..3e83babac0b0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -167,6 +167,10 @@ struct fwnode_handle *fwnode_get_next_available_child_node(
 	for (child = fwnode_get_next_child_node(fwnode, NULL); child;	\
 	     child = fwnode_get_next_child_node(fwnode, child))
 
+#define fwnode_for_each_named_child_node(fwnode, child, name)		\
+	fwnode_for_each_child_node(fwnode, child)			\
+		if (!fwnode_name_eq(child, name)) { } else
+
 #define fwnode_for_each_available_child_node(fwnode, child)		       \
 	for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
 	     child = fwnode_get_next_available_child_node(fwnode, child))
@@ -178,11 +182,19 @@ struct fwnode_handle *device_get_next_child_node(const struct device *dev,
 	for (child = device_get_next_child_node(dev, NULL); child;	\
 	     child = device_get_next_child_node(dev, child))
 
+#define device_for_each_named_child_node(dev, child, name)		\
+	device_for_each_child_node(dev, child)				\
+		if (!fwnode_name_eq(child, name)) { } else
+
 #define device_for_each_child_node_scoped(dev, child)			\
 	for (struct fwnode_handle *child __free(fwnode_handle) =	\
 		device_get_next_child_node(dev, NULL);			\
 	     child; child = device_get_next_child_node(dev, child))
 
+#define device_for_each_named_child_node_scoped(dev, child, name)	\
+	device_for_each_child_node_scoped(dev, child)			\
+		if (!fwnode_name_eq(child, name)) { } else
+
 struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
 						  const char *childname);
 struct fwnode_handle *device_get_named_child_node(const struct device *dev,
@@ -210,6 +222,14 @@ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
 
 unsigned int device_get_child_node_count(const struct device *dev);
 
+unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
+					       const char *name);
+static inline unsigned int device_get_named_child_node_count(const struct device *dev,
+							     const char *name)
+{
+	return fwnode_get_named_child_node_count(dev_fwnode(dev), name);
+}
+
 static inline int device_property_read_u8(const struct device *dev,
 					  const char *propname, u8 *val)
 {
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250320/0ff4f88b/attachment.sig>

From mazziesaccount at gmail.com  Thu Mar 20 01:21:16 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Thu, 20 Mar 2025 10:21:16 +0200
Subject: [PATCH v9 3/8] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1742457420.git.mazziesaccount@gmail.com>
References: <cover.1742457420.git.mazziesaccount@gmail.com>
Message-ID: <299f990caf58d77cc24200e8d75655661f16050e.1742457420.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

---
Revision history:
v8 =>
 - No changes
v7 => v8:
 devm_iio_adc_device_alloc_chaninfo_se():
 - Treat all negative values for the max ID as 'don't care'
 - Return -ENOENT instead of '0' if no channels were found.
v5 => v6:
 - Adapt to changed fwnode helper names
 - Fix spelling
v4 => v5:
 - Inline iio_adc_device_num_channels()
 - Fix Indenting function parameters
 - Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 82 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 114 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..b4057230e749
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use negative value if no
+ *			checking is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on success. Negative value to indicate
+ *		failure. Specifically, -ENOENT if no channel nodes were found.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 0)
+		return num_chan;
+
+	if (!num_chan)
+		return -ENOENT;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_named_child_node_scoped(dev, child, "channel") {
+		u32 ch;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id >= 0 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..56b092a2a4c4
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_named_child_node_count(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.48.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250320/7486e261/attachment.sig>

From Chun-Jen.Tseng at mediatek.com  Thu Mar 20 01:34:51 2025
From: Chun-Jen.Tseng at mediatek.com (=?utf-8?B?Q2h1bi1KZW4gVHNlbmcgKOabvuS/iuS7gSk=?=)
Date: Thu, 20 Mar 2025 08:34:51 +0000
Subject: [PATCH v3 2/3] cpufreq: mediatek: Add CPUFREQ_ASYNC_NOTIFICATION
 flag
In-Reply-To: <20250219054543.4xt4tixsauwoqpst@vireshk-i7>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
	 <20250214074353.1169864-3-chun-jen.tseng@mediatek.com>
	 <20250219054543.4xt4tixsauwoqpst@vireshk-i7>
Message-ID: <21e1b622c2968a5549b2ff37e4ba329a557968b6.camel@mediatek.com>

Hi viresh,

For CCI and ARMPLL in different driver, I need to change ARMPLL first
then use cpufreq notify CCI driver. it can avoid CCI driver get wrong
ARMPLL frequency and choose WRONG frequency.

BRs,

Mark Tseng


On Wed, 2025-02-19 at 11:15 +0530, Viresh Kumar wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 14-02-25, 15:43, Mark Tseng wrote:
> > Add CPUFREQ_ASYNC_NOTIFICATION flages for cpufreq policy because
> > some of
> > process will get CPU frequency by cpufreq sysfs node. It may get
> > wrong
> > frequency then call cpufreq_out_of_sync() to fixed frequency.
> 
> That's not why CPUFREQ_ASYNC_NOTIFICATION is used. It is used only
> for the cases
> where the target()/target_index() callback defers the work to some
> other entity
> (like a workqueue) and it is not guaranteed that the frequency will
> be changed
> before these helpers return.
> 
> I don't think your patch is required.
> 
> --
> viresh


From jbrunet at baylibre.com  Thu Mar 20 01:42:39 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 20 Mar 2025 09:42:39 +0100
Subject: [PATCH v4 5/6] clk: meson: axg-audio: Add the mclk pad div for
 s4 chip
In-Reply-To: <20250319-audio_drvier-v4-5-686867fad719@amlogic.com> (jiebing
	chen via's message of "Wed, 19 Mar 2025 15:04:48 +0800")
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
	<20250319-audio_drvier-v4-5-686867fad719@amlogic.com>
Message-ID: <1jldt02iv4.fsf@starbuckisacylon.baylibre.com>

On Wed 19 Mar 2025 at 15:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:

> From: jiebing chen <jiebing.chen at amlogic.com>
>
> Add mclk pad div support, Increased the number of lrclk
> and sclk pads to five
>
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  drivers/clk/meson/axg-audio.c | 441 +++++++++++++++++++++++++++++++++++++++++-
>  drivers/clk/meson/axg-audio.h |   6 +
>  2 files changed, 445 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
> index 9df627b142f89788966ede0262aaaf39e13f0b49..50e7c78ddb98ee08121690633c8113489503bc04 100644
> --- a/drivers/clk/meson/axg-audio.c
> +++ b/drivers/clk/meson/axg-audio.c
> @@ -323,6 +323,16 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
>  	AUD_MUX(_name, _reg, 0x7, _shift, 0, _parents,		\
>  		CLK_SET_RATE_NO_REPARENT)
>  
> +#define AUD_MCLK_PAD_MUX(_name, _reg, _shift)					\
> +	AUD_MUX(_name##_sel, _reg, 0x7, _shift, CLK_MUX_ROUND_CLOSEST,			\
> +		mclk_pad_ctrl_parent_data, 0)
> +#define AUD_MCLK_PAD_DIV(_name, _reg, _shift)					\
> +	AUD_DIV(_name##_div, _reg, _shift, 8, CLK_DIVIDER_ROUND_CLOSEST,			\
> +		aud_##_name##_sel, CLK_SET_RATE_PARENT)
> +#define AUD_MCLK_PAD_GATE(_name, _reg, _shift)					\
> +	AUD_GATE(_name, _reg, _shift, aud_##_name##_div,			\
> +		 CLK_SET_RATE_PARENT)
> +
>  /* Common Clocks */
>  static struct clk_regmap ddr_arb =
>  	AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
> @@ -826,6 +836,49 @@ static struct clk_regmap sm1_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
>  static struct clk_regmap sm1_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
>  	tdm_sclk_pad_2, AUDIO_SM1_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
>  
> +static struct clk_regmap s4_tdm_mclk_pad0_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 8);
> +static struct clk_regmap s4_tdm_mclk_pad1_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 24);
> +static struct clk_regmap s4_tdm_mclk_pad2_sel =
> +	AUD_MCLK_PAD_MUX(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 8);
> +
> +static struct clk_regmap s4_tdm_mclk_pad0_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 0);
> +static struct clk_regmap s4_tdm_mclk_pad1_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 16);
> +static struct clk_regmap s4_tdm_mclk_pad2_div =
> +	AUD_MCLK_PAD_DIV(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 0);
> +
> +static struct clk_regmap s4_tdm_mclk_pad_0 =
> +	AUD_MCLK_PAD_GATE(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 15);
> +static struct clk_regmap s4_tdm_mclk_pad_1 =
> +	AUD_MCLK_PAD_GATE(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 31);
> +static struct clk_regmap s4_tdm_mclk_pad_2 =
> +	AUD_MCLK_PAD_GATE(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 15);
> +
> +static struct clk_regmap s4_tdm_sclk_pad_0 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL0, 0, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_1 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL0, 4, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_2 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL0, 8, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_3 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL0, 16, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_sclk_pad_4 =
> +	AUD_TDM_PAD_CTRL(tdm_sclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL0, 20, lrclk_pad_ctrl_parent_data);
> +
> +static struct clk_regmap s4_tdm_lrclk_pad_0 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL1, 0, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_1 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL1, 4, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_2 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL1, 8, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_3 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL1, 16, lrclk_pad_ctrl_parent_data);
> +static struct clk_regmap s4_tdm_lrclk_pad_4 =
> +	AUD_TDM_PAD_CTRL(tdm_lrclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL1, 20, lrclk_pad_ctrl_parent_data);
> +
>  /*
>   * Array of all clocks provided by this provider
>   * The input clocks of the controller will be populated at runtime
> @@ -1257,6 +1310,177 @@ static struct clk_hw *sm1_audio_hw_clks[] = {
>  	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
>  };
>  
> +/*
> + * Array of all S4 clocks provided by this provider
> + * The input clocks of the controller will be populated at runtime
> + */
> +static struct clk_hw *s4_audio_hw_clks[] = {
> +	[AUD_CLKID_DDR_ARB]		= &ddr_arb.hw,
> +	[AUD_CLKID_PDM]			= &pdm.hw,
> +	[AUD_CLKID_TDMIN_A]		= &tdmin_a.hw,
> +	[AUD_CLKID_TDMIN_B]		= &tdmin_b.hw,
> +	[AUD_CLKID_TDMIN_C]		= &tdmin_c.hw,
> +	[AUD_CLKID_TDMIN_LB]		= &tdmin_lb.hw,
> +	[AUD_CLKID_TDMOUT_A]		= &tdmout_a.hw,
> +	[AUD_CLKID_TDMOUT_B]		= &tdmout_b.hw,
> +	[AUD_CLKID_TDMOUT_C]		= &tdmout_c.hw,
> +	[AUD_CLKID_FRDDR_A]		= &frddr_a.hw,
> +	[AUD_CLKID_FRDDR_B]		= &frddr_b.hw,
> +	[AUD_CLKID_FRDDR_C]		= &frddr_c.hw,
> +	[AUD_CLKID_TODDR_A]		= &toddr_a.hw,
> +	[AUD_CLKID_TODDR_B]		= &toddr_b.hw,
> +	[AUD_CLKID_TODDR_C]		= &toddr_c.hw,
> +	[AUD_CLKID_LOOPBACK]		= &loopback.hw,
> +	[AUD_CLKID_SPDIFIN]		= &spdifin.hw,
> +	[AUD_CLKID_SPDIFOUT]		= &spdifout.hw,
> +	[AUD_CLKID_RESAMPLE]		= &resample.hw,
> +	[AUD_CLKID_SPDIFOUT_B]		= &spdifout_b.hw,
> +	[AUD_CLKID_MST_A_MCLK_SEL]	= &sm1_mst_a_mclk_sel.hw,
> +	[AUD_CLKID_MST_B_MCLK_SEL]	= &sm1_mst_b_mclk_sel.hw,
> +	[AUD_CLKID_MST_C_MCLK_SEL]	= &sm1_mst_c_mclk_sel.hw,
> +	[AUD_CLKID_MST_D_MCLK_SEL]	= &sm1_mst_d_mclk_sel.hw,
> +	[AUD_CLKID_MST_E_MCLK_SEL]	= &sm1_mst_e_mclk_sel.hw,
> +	[AUD_CLKID_MST_F_MCLK_SEL]	= &sm1_mst_f_mclk_sel.hw,
> +	[AUD_CLKID_MST_A_MCLK_DIV]	= &sm1_mst_a_mclk_div.hw,
> +	[AUD_CLKID_MST_B_MCLK_DIV]	= &sm1_mst_b_mclk_div.hw,
> +	[AUD_CLKID_MST_C_MCLK_DIV]	= &sm1_mst_c_mclk_div.hw,
> +	[AUD_CLKID_MST_D_MCLK_DIV]	= &sm1_mst_d_mclk_div.hw,
> +	[AUD_CLKID_MST_E_MCLK_DIV]	= &sm1_mst_e_mclk_div.hw,
> +	[AUD_CLKID_MST_F_MCLK_DIV]	= &sm1_mst_f_mclk_div.hw,
> +	[AUD_CLKID_MST_A_MCLK]		= &sm1_mst_a_mclk.hw,
> +	[AUD_CLKID_MST_B_MCLK]		= &sm1_mst_b_mclk.hw,
> +	[AUD_CLKID_MST_C_MCLK]		= &sm1_mst_c_mclk.hw,
> +	[AUD_CLKID_MST_D_MCLK]		= &sm1_mst_d_mclk.hw,
> +	[AUD_CLKID_MST_E_MCLK]		= &sm1_mst_e_mclk.hw,
> +	[AUD_CLKID_MST_F_MCLK]		= &sm1_mst_f_mclk.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK_SEL]	= &spdifout_clk_sel.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK_DIV]	= &spdifout_clk_div.hw,
> +	[AUD_CLKID_SPDIFOUT_CLK]	= &spdifout_clk.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK_SEL]	= &spdifout_b_clk_sel.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK_DIV]	= &spdifout_b_clk_div.hw,
> +	[AUD_CLKID_SPDIFOUT_B_CLK]	= &spdifout_b_clk.hw,
> +	[AUD_CLKID_SPDIFIN_CLK_SEL]	= &spdifin_clk_sel.hw,
> +	[AUD_CLKID_SPDIFIN_CLK_DIV]	= &spdifin_clk_div.hw,
> +	[AUD_CLKID_SPDIFIN_CLK]		= &spdifin_clk.hw,
> +	[AUD_CLKID_PDM_DCLK_SEL]	= &pdm_dclk_sel.hw,
> +	[AUD_CLKID_PDM_DCLK_DIV]	= &pdm_dclk_div.hw,
> +	[AUD_CLKID_PDM_DCLK]		= &pdm_dclk.hw,
> +	[AUD_CLKID_PDM_SYSCLK_SEL]	= &pdm_sysclk_sel.hw,
> +	[AUD_CLKID_PDM_SYSCLK_DIV]	= &pdm_sysclk_div.hw,
> +	[AUD_CLKID_PDM_SYSCLK]		= &pdm_sysclk.hw,
> +	[AUD_CLKID_MST_A_SCLK_PRE_EN]	= &mst_a_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_B_SCLK_PRE_EN]	= &mst_b_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_C_SCLK_PRE_EN]	= &mst_c_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_D_SCLK_PRE_EN]	= &mst_d_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_E_SCLK_PRE_EN]	= &mst_e_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_F_SCLK_PRE_EN]	= &mst_f_sclk_pre_en.hw,
> +	[AUD_CLKID_MST_A_SCLK_DIV]	= &mst_a_sclk_div.hw,
> +	[AUD_CLKID_MST_B_SCLK_DIV]	= &mst_b_sclk_div.hw,
> +	[AUD_CLKID_MST_C_SCLK_DIV]	= &mst_c_sclk_div.hw,
> +	[AUD_CLKID_MST_D_SCLK_DIV]	= &mst_d_sclk_div.hw,
> +	[AUD_CLKID_MST_E_SCLK_DIV]	= &mst_e_sclk_div.hw,
> +	[AUD_CLKID_MST_F_SCLK_DIV]	= &mst_f_sclk_div.hw,
> +	[AUD_CLKID_MST_A_SCLK_POST_EN]	= &mst_a_sclk_post_en.hw,
> +	[AUD_CLKID_MST_B_SCLK_POST_EN]	= &mst_b_sclk_post_en.hw,
> +	[AUD_CLKID_MST_C_SCLK_POST_EN]	= &mst_c_sclk_post_en.hw,
> +	[AUD_CLKID_MST_D_SCLK_POST_EN]	= &mst_d_sclk_post_en.hw,
> +	[AUD_CLKID_MST_E_SCLK_POST_EN]	= &mst_e_sclk_post_en.hw,
> +	[AUD_CLKID_MST_F_SCLK_POST_EN]	= &mst_f_sclk_post_en.hw,
> +	[AUD_CLKID_MST_A_SCLK]		= &mst_a_sclk.hw,
> +	[AUD_CLKID_MST_B_SCLK]		= &mst_b_sclk.hw,
> +	[AUD_CLKID_MST_C_SCLK]		= &mst_c_sclk.hw,
> +	[AUD_CLKID_MST_D_SCLK]		= &mst_d_sclk.hw,
> +	[AUD_CLKID_MST_E_SCLK]		= &mst_e_sclk.hw,
> +	[AUD_CLKID_MST_F_SCLK]		= &mst_f_sclk.hw,
> +	[AUD_CLKID_MST_A_LRCLK_DIV]	= &mst_a_lrclk_div.hw,
> +	[AUD_CLKID_MST_B_LRCLK_DIV]	= &mst_b_lrclk_div.hw,
> +	[AUD_CLKID_MST_C_LRCLK_DIV]	= &mst_c_lrclk_div.hw,
> +	[AUD_CLKID_MST_D_LRCLK_DIV]	= &mst_d_lrclk_div.hw,
> +	[AUD_CLKID_MST_E_LRCLK_DIV]	= &mst_e_lrclk_div.hw,
> +	[AUD_CLKID_MST_F_LRCLK_DIV]	= &mst_f_lrclk_div.hw,
> +	[AUD_CLKID_MST_A_LRCLK]		= &mst_a_lrclk.hw,
> +	[AUD_CLKID_MST_B_LRCLK]		= &mst_b_lrclk.hw,
> +	[AUD_CLKID_MST_C_LRCLK]		= &mst_c_lrclk.hw,
> +	[AUD_CLKID_MST_D_LRCLK]		= &mst_d_lrclk.hw,
> +	[AUD_CLKID_MST_E_LRCLK]		= &mst_e_lrclk.hw,
> +	[AUD_CLKID_MST_F_LRCLK]		= &mst_f_lrclk.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_SEL]	= &tdmin_a_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_SEL]	= &tdmin_b_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_SEL]	= &tdmin_c_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_SEL]	= &tdmin_lb_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_SEL]	= &tdmout_a_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_SEL]	= &tdmout_b_sclk_sel.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_SEL]	= &tdmout_c_sclk_sel.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_PRE_EN]	= &tdmin_a_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_PRE_EN]	= &tdmin_b_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_PRE_EN]	= &tdmin_c_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &tdmin_lb_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &tdmout_a_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &tdmout_b_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &tdmout_c_sclk_pre_en.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &tdmin_a_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &tdmin_b_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &tdmin_c_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &tdmin_lb_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &tdmout_a_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &tdmout_b_sclk_post_en.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &tdmout_c_sclk_post_en.hw,
> +	[AUD_CLKID_TDMIN_A_SCLK]	= &tdmin_a_sclk.hw,
> +	[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
> +	[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
> +	[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
> +	[AUD_CLKID_TDMOUT_A_SCLK]	= &g12a_tdmout_a_sclk.hw,
> +	[AUD_CLKID_TDMOUT_B_SCLK]	= &g12a_tdmout_b_sclk.hw,
> +	[AUD_CLKID_TDMOUT_C_SCLK]	= &g12a_tdmout_c_sclk.hw,
> +	[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
> +	[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
> +	[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
> +	[AUD_CLKID_TDMIN_LB_LRCLK]	= &tdmin_lb_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_A_LRCLK]	= &tdmout_a_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_B_LRCLK]	= &tdmout_b_lrclk.hw,
> +	[AUD_CLKID_TDMOUT_C_LRCLK]	= &tdmout_c_lrclk.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0]	= &s4_tdm_mclk_pad_0.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1]	= &s4_tdm_mclk_pad_1.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD0]	= &s4_tdm_lrclk_pad_0.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD1]	= &s4_tdm_lrclk_pad_1.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD2]	= &s4_tdm_lrclk_pad_2.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD0]	= &s4_tdm_sclk_pad_0.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD1]	= &s4_tdm_sclk_pad_1.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD2]	= &s4_tdm_sclk_pad_2.hw,
> +	[AUD_CLKID_TOP]			= &sm1_aud_top.hw,
> +	[AUD_CLKID_TORAM]		= &toram.hw,
> +	[AUD_CLKID_EQDRC]		= &eqdrc.hw,
> +	[AUD_CLKID_RESAMPLE_B]		= &resample_b.hw,
> +	[AUD_CLKID_TOVAD]		= &tovad.hw,
> +	[AUD_CLKID_LOCKER]		= &locker.hw,
> +	[AUD_CLKID_SPDIFIN_LB]		= &spdifin_lb.hw,
> +	[AUD_CLKID_FRDDR_D]		= &frddr_d.hw,
> +	[AUD_CLKID_TODDR_D]		= &toddr_d.hw,
> +	[AUD_CLKID_LOOPBACK_B]		= &loopback_b.hw,
> +	[AUD_CLKID_CLK81_EN]		= &sm1_clk81_en.hw,
> +	[AUD_CLKID_SYSCLK_A_DIV]	= &sm1_sysclk_a_div.hw,
> +	[AUD_CLKID_SYSCLK_A_EN]		= &sm1_sysclk_a_en.hw,
> +	[AUD_CLKID_SYSCLK_B_DIV]	= &sm1_sysclk_b_div.hw,
> +	[AUD_CLKID_SYSCLK_B_EN]		= &sm1_sysclk_b_en.hw,
> +	[AUD_CLKID_EARCRX]		= &earcrx.hw,
> +	[AUD_CLKID_EARCRX_CMDC_SEL]	= &sm1_earcrx_cmdc_clk_sel.hw,
> +	[AUD_CLKID_EARCRX_CMDC_DIV]	= &sm1_earcrx_cmdc_clk_div.hw,
> +	[AUD_CLKID_EARCRX_CMDC]		= &sm1_earcrx_cmdc_clk.hw,
> +	[AUD_CLKID_EARCRX_DMAC_SEL]	= &sm1_earcrx_dmac_clk_sel.hw,
> +	[AUD_CLKID_EARCRX_DMAC_DIV]	= &sm1_earcrx_dmac_clk_div.hw,
> +	[AUD_CLKID_EARCRX_DMAC]		= &sm1_earcrx_dmac_clk.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0_SEL]		= &s4_tdm_mclk_pad0_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1_SEL]       = &s4_tdm_mclk_pad1_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD0_DIV]		= &s4_tdm_mclk_pad0_div.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD1_DIV]       = &s4_tdm_mclk_pad1_div.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2]	        = &s4_tdm_mclk_pad_2.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2_SEL]		= &s4_tdm_mclk_pad2_sel.hw,
> +	[AUD_CLKID_TDM_MCLK_PAD2_DIV]       = &s4_tdm_mclk_pad2_div.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD3]	= &s4_tdm_sclk_pad_3.hw,
> +	[AUD_CLKID_TDM_SCLK_PAD4]	= &s4_tdm_sclk_pad_4.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD3]	= &s4_tdm_lrclk_pad_3.hw,
> +	[AUD_CLKID_TDM_LRCLK_PAD4]	= &s4_tdm_lrclk_pad_4.hw,
> +};
>  
>  /* Convenience table to populate regmap in .probe(). */
>  static struct clk_regmap *const axg_clk_regmaps[] = {
> @@ -1678,6 +1902,177 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
>  	&sm1_earcrx_dmac_clk,
>  };
>  
> +static struct clk_regmap *const s4_clk_regmaps[] = {
> +	&ddr_arb,
> +	&pdm,
> +	&tdmin_a,
> +	&tdmin_b,
> +	&tdmin_c,
> +	&tdmin_lb,
> +	&tdmout_a,
> +	&tdmout_b,
> +	&tdmout_c,
> +	&frddr_a,
> +	&frddr_b,
> +	&frddr_c,
> +	&toddr_a,
> +	&toddr_b,
> +	&toddr_c,
> +	&loopback,
> +	&spdifin,
> +	&spdifout,
> +	&resample,
> +	&spdifout_b,
> +	&sm1_mst_a_mclk_sel,
> +	&sm1_mst_b_mclk_sel,
> +	&sm1_mst_c_mclk_sel,
> +	&sm1_mst_d_mclk_sel,
> +	&sm1_mst_e_mclk_sel,
> +	&sm1_mst_f_mclk_sel,
> +	&sm1_mst_a_mclk_div,
> +	&sm1_mst_b_mclk_div,
> +	&sm1_mst_c_mclk_div,
> +	&sm1_mst_d_mclk_div,
> +	&sm1_mst_e_mclk_div,
> +	&sm1_mst_f_mclk_div,
> +	&sm1_mst_a_mclk,
> +	&sm1_mst_b_mclk,
> +	&sm1_mst_c_mclk,
> +	&sm1_mst_d_mclk,
> +	&sm1_mst_e_mclk,
> +	&sm1_mst_f_mclk,
> +	&spdifout_clk_sel,
> +	&spdifout_clk_div,
> +	&spdifout_clk,
> +	&spdifin_clk_sel,
> +	&spdifin_clk_div,
> +	&spdifin_clk,
> +	&pdm_dclk_sel,
> +	&pdm_dclk_div,
> +	&pdm_dclk,
> +	&pdm_sysclk_sel,
> +	&pdm_sysclk_div,
> +	&pdm_sysclk,
> +	&mst_a_sclk_pre_en,
> +	&mst_b_sclk_pre_en,
> +	&mst_c_sclk_pre_en,
> +	&mst_d_sclk_pre_en,
> +	&mst_e_sclk_pre_en,
> +	&mst_f_sclk_pre_en,
> +	&mst_a_sclk_div,
> +	&mst_b_sclk_div,
> +	&mst_c_sclk_div,
> +	&mst_d_sclk_div,
> +	&mst_e_sclk_div,
> +	&mst_f_sclk_div,
> +	&mst_a_sclk_post_en,
> +	&mst_b_sclk_post_en,
> +	&mst_c_sclk_post_en,
> +	&mst_d_sclk_post_en,
> +	&mst_e_sclk_post_en,
> +	&mst_f_sclk_post_en,
> +	&mst_a_sclk,
> +	&mst_b_sclk,
> +	&mst_c_sclk,
> +	&mst_d_sclk,
> +	&mst_e_sclk,
> +	&mst_f_sclk,
> +	&mst_a_lrclk_div,
> +	&mst_b_lrclk_div,
> +	&mst_c_lrclk_div,
> +	&mst_d_lrclk_div,
> +	&mst_e_lrclk_div,
> +	&mst_f_lrclk_div,
> +	&mst_a_lrclk,
> +	&mst_b_lrclk,
> +	&mst_c_lrclk,
> +	&mst_d_lrclk,
> +	&mst_e_lrclk,
> +	&mst_f_lrclk,
> +	&tdmin_a_sclk_sel,
> +	&tdmin_b_sclk_sel,
> +	&tdmin_c_sclk_sel,
> +	&tdmin_lb_sclk_sel,
> +	&tdmout_a_sclk_sel,
> +	&tdmout_b_sclk_sel,
> +	&tdmout_c_sclk_sel,
> +	&tdmin_a_sclk_pre_en,
> +	&tdmin_b_sclk_pre_en,
> +	&tdmin_c_sclk_pre_en,
> +	&tdmin_lb_sclk_pre_en,
> +	&tdmout_a_sclk_pre_en,
> +	&tdmout_b_sclk_pre_en,
> +	&tdmout_c_sclk_pre_en,
> +	&tdmin_a_sclk_post_en,
> +	&tdmin_b_sclk_post_en,
> +	&tdmin_c_sclk_post_en,
> +	&tdmin_lb_sclk_post_en,
> +	&tdmout_a_sclk_post_en,
> +	&tdmout_b_sclk_post_en,
> +	&tdmout_c_sclk_post_en,
> +	&tdmin_a_sclk,
> +	&tdmin_b_sclk,
> +	&tdmin_c_sclk,
> +	&tdmin_lb_sclk,
> +	&g12a_tdmout_a_sclk,
> +	&g12a_tdmout_b_sclk,
> +	&g12a_tdmout_c_sclk,
> +	&tdmin_a_lrclk,
> +	&tdmin_b_lrclk,
> +	&tdmin_c_lrclk,
> +	&tdmin_lb_lrclk,
> +	&tdmout_a_lrclk,
> +	&tdmout_b_lrclk,
> +	&tdmout_c_lrclk,
> +	&spdifout_b_clk_sel,
> +	&spdifout_b_clk_div,
> +	&spdifout_b_clk,
> +	&sm1_aud_top,
> +	&toram,
> +	&eqdrc,
> +	&resample_b,
> +	&tovad,
> +	&locker,
> +	&spdifin_lb,
> +	&frddr_d,
> +	&toddr_d,
> +	&loopback_b,
> +	&sm1_clk81_en,
> +	&sm1_sysclk_a_div,
> +	&sm1_sysclk_a_en,
> +	&sm1_sysclk_b_div,
> +	&sm1_sysclk_b_en,
> +	&earcrx,
> +	&sm1_earcrx_cmdc_clk_sel,
> +	&sm1_earcrx_cmdc_clk_div,
> +	&sm1_earcrx_cmdc_clk,
> +	&sm1_earcrx_dmac_clk_sel,
> +	&sm1_earcrx_dmac_clk_div,
> +	&sm1_earcrx_dmac_clk,
> +};
> +
> +static struct clk_regmap *const s4_clk_pad_regmaps[] = {
> +	&s4_tdm_mclk_pad_0,
> +	&s4_tdm_mclk_pad_1,
> +	&s4_tdm_mclk_pad_2,
> +	&s4_tdm_lrclk_pad_0,
> +	&s4_tdm_lrclk_pad_1,
> +	&s4_tdm_lrclk_pad_2,
> +	&s4_tdm_lrclk_pad_3,
> +	&s4_tdm_lrclk_pad_4,
> +	&s4_tdm_sclk_pad_0,
> +	&s4_tdm_sclk_pad_1,
> +	&s4_tdm_sclk_pad_2,
> +	&s4_tdm_sclk_pad_3,
> +	&s4_tdm_sclk_pad_4,
> +	&s4_tdm_mclk_pad0_sel,
> +	&s4_tdm_mclk_pad1_sel,
> +	&s4_tdm_mclk_pad0_div,
> +	&s4_tdm_mclk_pad1_div,
> +	&s4_tdm_mclk_pad2_sel,
> +	&s4_tdm_mclk_pad2_div,
> +};
> +
>  struct axg_audio_reset_data {
>  	struct reset_controller_dev rstc;
>  	struct regmap *map;
> @@ -1764,13 +2159,20 @@ static struct regmap_config axg_audio_regmap_cfg = {
>  
>  struct audioclk_data {
>  	struct clk_regmap *const *regmap_clks;
> +	struct clk_regmap *const *regmap_clks_pads;
>  	unsigned int regmap_clk_num;
> +	unsigned int regmap_clk_pads_num;
>  	struct meson_clk_hw_data hw_clks;
>  	unsigned int reset_offset;
>  	unsigned int reset_num;
>  	unsigned int max_register;
>  };
>  
> +static int audio_clock_pad_is_new_regmap(struct device_node *np)
> +{
> +	return of_device_is_compatible(np, "amlogic,s4-audio-clkc");
> +}
> +
>  static int axg_audio_clkc_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -1812,6 +2214,25 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>  	for (i = 0; i < data->regmap_clk_num; i++)
>  		data->regmap_clks[i]->map = map;
>  
> +	/* some amlogic chip clock pad reg domian is different */
> +	if (audio_clock_pad_is_new_regmap(dev->of_node)) {
> +		struct resource *res;
> +		static const struct regmap_config aud_regmap_config = {
> +			.reg_bits = 32,
> +			.val_bits = 32,
> +			.reg_stride = 4,
> +		};
> +		regs = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
> +		if (IS_ERR(regs))
> +			return PTR_ERR(regs);
> +		aud_regmap_config.max_register = resource_size(res) - 4;
> +		aud_regmap_config.name =
> +			devm_kasprintf(dev, GFP_KERNEL, "%s-%s", dev->of_node->name, "pads");
> +		map = devm_regmap_init_mmio(dev, regs, &aud_regmap_config);
> +		/* Populate clk pad regmap for the regmap backed clocks */
> +		for (i = 0; i < data->regmap_clk_pads_num; i++)
> +			data->regmap_clks_pads[i]->map = map;
> +	}

This adds complexity for no good reason.
Deal with pad clock in a distinct controller


>  	/* Take care to skip the registered input clocks */
>  	for (i = AUD_CLKID_DDR_ARB; i < data->hw_clks.num; i++) {
>  		const char *name;
> @@ -1822,7 +2243,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>  			continue;
>  
>  		name = hw->init->name;
> -
>  		ret = devm_clk_hw_register(dev, hw);
>  		if (ret) {
>  			dev_err(dev, "failed to register clock %s\n", name);
> @@ -1886,6 +2306,20 @@ static const struct audioclk_data sm1_audioclk_data = {
>  	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
>  };
>  
> +static const struct audioclk_data s4_audioclk_data = {
> +	.regmap_clks = s4_clk_regmaps,
> +	.regmap_clk_num = ARRAY_SIZE(s4_clk_regmaps),
> +	.regmap_clks_pads = s4_clk_pad_regmaps,
> +	.regmap_clk_pads_num = ARRAY_SIZE(s4_clk_pad_regmaps),
> +	.hw_clks = {
> +		.hws = s4_audio_hw_clks,
> +		.num = ARRAY_SIZE(s4_audio_hw_clks),
> +	},
> +	.reset_offset = AUDIO_SM1_SW_RESET0,
> +	.reset_num = 39,
> +	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
> +};
> +
>  static const struct of_device_id clkc_match_table[] = {
>  	{
>  		.compatible = "amlogic,axg-audio-clkc",
> @@ -1896,7 +2330,10 @@ static const struct of_device_id clkc_match_table[] = {
>  	}, {
>  		.compatible = "amlogic,sm1-audio-clkc",
>  		.data = &sm1_audioclk_data
> -	}, {}
> +	}, {
> +		.compatible = "amlogic,s4-audio-clkc",
> +		.data = &s4_audioclk_data
> +	}, { }
>  };
>  MODULE_DEVICE_TABLE(of, clkc_match_table);
>  
> diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
> index 9e7765b630c96a8029140539ffda789b7db5277a..24233c40171034eba86c699db0200f07555926af 100644
> --- a/drivers/clk/meson/axg-audio.h
> +++ b/drivers/clk/meson/axg-audio.h
> @@ -67,4 +67,10 @@
>  #define AUDIO_EARCRX_CMDC_CLK_CTRL	0x0D0
>  #define AUDIO_EARCRX_DMAC_CLK_CTRL	0x0D4
>  
> +/* s4 clock pads use new reg base */
> +#define AUDIO_S4_MCLK_PAD_CTRL0 0x0
> +#define AUDIO_S4_MCLK_PAD_CTRL1 0x4
> +#define AUDIO_S4_SCLK_PAD_CTRL0 0x8
> +#define AUDIO_S4_SCLK_PAD_CTRL1 0xC
> +
>  #endif /*__AXG_AUDIO_CLKC_H */

-- 
Jerome


From neil.armstrong at linaro.org  Thu Mar 20 01:42:46 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Thu, 20 Mar 2025 09:42:46 +0100
Subject: [GIT PULL v2] amlogic ARM64 DT updates for v6.15
Message-ID: <f6fb1b2b-955d-4271-b772-0a75fdba1e48@linaro.org>

Hi,

Here's a changeset for Amlogic ARM64 DT, switching to the new PWM bindings
which has been in -next for the last 3 months and the driver was designed to
fully support the old and new bindings, and finally adding gpio_intc
node for Amlogic A4 & A5 SoCs.

I removed the pinctrl changes, since they can wait another cycle.

Thanks,
Neil

The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

   https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git tags/amlogic-arm64-dt-for-v6.15-v2

for you to fetch changes up to 67c2799bf11fd0f1323579dead240bfda5b6a3b6:

   arm64: dts: Add gpio_intc node for Amlogic A5 SoCs (2025-03-20 09:31:41 +0100)

----------------------------------------------------------------
Amlogic ARM64 DT changes for v6.15 (v2):
- switch to the new PWM controller binding
- Add gpio_intc node for Amlogic A4 & A5 SoCs

----------------------------------------------------------------
Martin Blumenstingl (3):
       arm64: dts: amlogic: gx: switch to the new PWM controller binding
       arm64: dts: amlogic: axg: switch to the new PWM controller binding
       arm64: dts: amlogic: g12: switch to the new PWM controller binding

Xianwei Zhao (2):
       arm64: dts: Add gpio_intc node for Amlogic A4 SoCs
       arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

  arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        | 21 ++++++++++++++
  arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        | 12 ++++++++
  arch/arm64/boot/dts/amlogic/meson-axg.dtsi         | 24 +++++++++++++---
  arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi  | 33 ++++++++++++++++++----
  arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts  |  4 ---
  .../boot/dts/amlogic/meson-g12a-radxa-zero.dts     |  4 ---
  arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts  |  4 ---
  arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts    |  2 --
  arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts |  4 ---
  .../dts/amlogic/meson-g12b-a311d-libretech-cc.dts  |  2 --
  .../boot/dts/amlogic/meson-g12b-bananapi-cm4.dtsi  |  4 ---
  .../boot/dts/amlogic/meson-g12b-bananapi.dtsi      |  4 ---
  .../boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi   |  4 ---
  arch/arm64/boot/dts/amlogic/meson-g12b-odroid.dtsi |  4 ---
  .../boot/dts/amlogic/meson-g12b-radxa-zero2.dts    |  8 ------
  arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi   |  6 ----
  .../boot/dts/amlogic/meson-gx-libretech-pc.dtsi    |  6 ----
  .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  2 --
  arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |  8 +++---
  .../boot/dts/amlogic/meson-gxbb-nanopi-k2.dts      |  2 --
  .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    |  2 --
  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  2 --
  .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |  2 --
  arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi  |  2 --
  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 25 ++++++++++++++++
  .../boot/dts/amlogic/meson-gxl-s805x-p241.dts      |  2 --
  .../amlogic/meson-gxl-s905w-jethome-jethub-j80.dts |  2 --
  .../dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts |  2 --
  .../dts/amlogic/meson-gxl-s905x-khadas-vim.dts     |  2 --
  .../dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts    |  2 --
  .../boot/dts/amlogic/meson-gxl-s905x-p212.dtsi     |  2 --
  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi         | 25 ++++++++++++++++
  .../boot/dts/amlogic/meson-gxm-khadas-vim2.dts     |  4 ---
  arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts |  2 --
  .../dts/amlogic/meson-libretech-cottonwood.dtsi    |  6 ----
  arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi   |  6 ----
  .../arm64/boot/dts/amlogic/meson-sm1-bananapi.dtsi |  2 --
  .../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts    |  2 --
  arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi  |  2 --
  arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts   |  6 ----
  40 files changed, 135 insertions(+), 123 deletions(-)


From jbrunet at baylibre.com  Thu Mar 20 01:46:36 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 20 Mar 2025 09:46:36 +0100
Subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
In-Reply-To: <20250319-audio_drvier-v4-4-686867fad719@amlogic.com> (jiebing
	chen via's message of "Wed, 19 Mar 2025 15:04:47 +0800")
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
	<20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
Message-ID: <1jfrj82ioj.fsf@starbuckisacylon.baylibre.com>

On Wed 19 Mar 2025 at 15:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:

> From: jiebing chen <jiebing.chen at amlogic.com>
>
> S4 tocodec support 8 lane to input, It need to enable
> bclk and mclk control bit when work
>
> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
> ---
>  sound/soc/meson/g12a-toacodec.c | 46 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
>
> diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
> index 531bb8707a3ec4c47814d6a0676d5c62c705da75..88f9adabb3b5d7d8881fa110f1d0d51e9ac9c60e 100644
> --- a/sound/soc/meson/g12a-toacodec.c
> +++ b/sound/soc/meson/g12a-toacodec.c
> @@ -41,6 +41,9 @@
>  #define  CTRL0_BCLK_SEL_LSB		4
>  #define  CTRL0_MCLK_SEL			GENMASK(2, 0)
>  
> +#define CTRL0_BCLK_ENABLE_SHIFT		30
> +#define CTRL0_MCLK_ENABLE_SHIFT		29
> +
>  #define TOACODEC_OUT_CHMAX		2
>  
>  struct g12a_toacodec {
> @@ -129,6 +132,10 @@ static const struct snd_kcontrol_new g12a_toacodec_out_enable =
>  	SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
>  				    CTRL0_ENABLE_SHIFT, 1, 0);
>  
> +static const struct snd_kcontrol_new s4_toacodec_clk_enable =
> +	SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
> +			CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
> +

I think I remember commenting on this already.

>  static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
>  	SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
>  			 &g12a_toacodec_mux),
> @@ -143,6 +150,19 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
>  			    &g12a_toacodec_out_enable),
>  };
>  
> +/*
> + * FIXME:
> + * On this soc, tocodec need enable mclk and bclk control
> + * just enable it when dapm power widget power on.
> + */
> +
> +static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
> +	SND_SOC_DAPM_MUX("SRC", TOACODEC_CTRL0, CTRL0_BCLK_ENABLE_SHIFT, 0,
> +			 &sm1_toacodec_mux),
> +	SND_SOC_DAPM_SWITCH("OUT EN", TOACODEC_CTRL0, CTRL0_MCLK_ENABLE_SHIFT, 0,
> +			    &g12a_toacodec_out_enable),
> +};
> +
>  static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
>  					 struct snd_pcm_hw_params *params,
>  					 struct snd_soc_dai *dai)
> @@ -236,6 +256,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
>  	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
>  };
>  
> +static const struct snd_kcontrol_new s4_toacodec_controls[] = {
> +	SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 7, 0),
> +};
> +
>  static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
>  	.probe			= g12a_toacodec_component_probe,
>  	.controls		= g12a_toacodec_controls,
> @@ -258,6 +282,17 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
>  	.endianness		= 1,
>  };
>  
> +static const struct snd_soc_component_driver s4_toacodec_component_drv = {
> +	.probe			= sm1_toacodec_component_probe,
> +	.controls		= s4_toacodec_controls,
> +	.num_controls		= ARRAY_SIZE(s4_toacodec_controls),
> +	.dapm_widgets		= s4_toacodec_widgets,
> +	.num_dapm_widgets	= ARRAY_SIZE(s4_toacodec_widgets),
> +	.dapm_routes		= g12a_toacodec_routes,
> +	.num_dapm_routes	= ARRAY_SIZE(g12a_toacodec_routes),
> +	.endianness		= 1,
> +};
> +
>  static const struct regmap_config g12a_toacodec_regmap_cfg = {
>  	.reg_bits	= 32,
>  	.val_bits	= 32,
> @@ -278,6 +313,13 @@ static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
>  	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
>  };
>  
> +static const struct g12a_toacodec_match_data s4_toacodec_match_data = {
> +	.component_drv	= &s4_toacodec_component_drv,
> +	.field_dat_sel	= REG_FIELD(TOACODEC_CTRL0, 19, 20),
> +	.field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
> +	.field_bclk_sel	= REG_FIELD(TOACODEC_CTRL0, 4, 6),
> +};
> +
>  static const struct of_device_id g12a_toacodec_of_match[] = {
>  	{
>  		.compatible = "amlogic,g12a-toacodec",
> @@ -287,6 +329,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
>  		.compatible = "amlogic,sm1-toacodec",
>  		.data = &sm1_toacodec_match_data,
>  	},
> +	{
> +		.compatible = "amlogic,s4-toacodec",
> +		.data = &s4_toacodec_match_data,
> +	},
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);

-- 
Jerome


From amergnat at baylibre.com  Thu Mar 20 01:48:44 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Thu, 20 Mar 2025 09:48:44 +0100
Subject: [PATCH v8 0/3] Add display support for the MT8365-EVK board
Message-ID: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>

The purpose of this series is to add the display support for the mt8365-evk.

This is the list of HWs / IPs support added:
- Connectors (HW):
  - HDMI
  - MIPI DSI (Mobile Industry Processor Interface Display Serial Interface)
- HDMI bridge (it66121)
- DSI pannel (startek,kd070fhfid015)
- SoC display blocks (IP):
  - OVL0 (Overlay)
  - RDMA0 (Data Path Read DMA)
  - Color0
  - CCorr0 (Color Correction)
  - AAL0 (Adaptive Ambient Light)
  - GAMMA0
  - Dither0
  - DSI0 (Display Serial Interface)
  - RDMA1 (Data Path Read DMA)
  - DPI0 (Display Parallel Interface)

The Mediatek DSI, DPI and DRM drivers are also improved.

The series is rebased on top of Angelo's series [1] to
use the OF graphs support.

Update 03/20/25:
According to Angelo's comment, the DSI fix in the previous version
doesn't fix the root issue.
Then, the "drm/mediatek: dsi: Improves the DSI lane setup robustness"
as been replaced by two other patch to fix the DSI power on sequence
and remove custom power function.

Regards,
Alex

Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
---
Changes in v8:
- Patch merged, then removed from the series:
  - dt-bindings: display: mediatek: dpi: add power-domains example
  - drm/mediatek: add MT8365 SoC support
  - arm64: dts: mediatek: add display blocks support for the MT8365 SoC
  - arm64: dts: mediatek: add display support for mt8365-evk
- Patch removed:
  - drm/mediatek: dsi: Improves the DSI lane setup robustness
- Patch added:
  - drm/panel: startek-kd070fhfid015: add another init step
  - drm/mediatek: dsi: remove custom init part
- Remove MTK custom init function for the DSI driver to avoid conflict
  with what the DRM APIs provide.
- Link to v7: https://lore.kernel.org/r/20231023-display-support-v7-0-6703f3e26831 at baylibre.com

Changes in v7:
- Improve defconfig commit description
- Add comment in the DTS about pins clash with ethernet and HDMI (DPI0)
- Link to v6: https://lore.kernel.org/r/20231023-display-support-v6-0-c6af4f34f4d8 at baylibre.com

Changes in v6:
- Fix DPI binding: remove the duplicated property (power-domains).
- Squash defconfig commit.
- Fix the property order in the DTS.
- Link to v5: https://lore.kernel.org/r/20231023-display-support-v5-0-3905f1e4b835 at baylibre.com

Changes in v5:
- Patch merged, then removed from the series:
  - dt-bindings: display: mediatek: rdma: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: ovl: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: gamma: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: dpi: add compatible for MT8365
  - dt-bindings: display: mediatek: dsi: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: dither: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: color: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: ccorr: add compatible for MT8365 SoC
  - dt-bindings: display: mediatek: aal: add compatible for MT8365 SoC
- Enable STARTEK KD070FHFID015 panel in the defconfig.
- Rebase on top of 6.13-rc6.
- Link to v4: https://lore.kernel.org/all/20231023-display-support-v4-0-ed82eb168fb1 at baylibre.com

Changes in v4:
- Patch merged, then removed from the series:
  - dt-bindings: display: mediatek: dpi: add power-domains property
  - dt-bindings: pwm: mediatek,pwm-disp: add compatible for mt8365 SoC
  - clk: mediatek: mt8365-mm: fix DPI0 parent
- Remove mediatek,mt8365-dpi compatible from mtk_drm_drv.c because it
  use the mt8192's data. It's a miss.
- Add MT8365 OF graphs support, remove the hardcoded display path and
  rebase on top of Angelo's series [1].
- Link to v3: https://lore.kernel.org/r/20231023-display-support-v3-0-53388f3ed34b at baylibre.com

Changes in v3:
- Drop "drm/mediatek: add mt8365 dpi support" because it's the same
  config as mt8192 SoC
- Drop "dt-bindings: pwm: mediatek,pwm-disp: add power-domains property"
  because an equivalent patch has been merge already.
- Add DPI clock fix in a separate commit.
- Improve DTS(I) readability.
- Link to v2: https://lore.kernel.org/r/20231023-display-support-v2-0-33ce8864b227 at baylibre.com

Changes in v2:
- s/binding/compatible/ in commit messages/titles.
- Improve commit messages as Conor suggest.
- pwm-disp: Set power domain property for MT8365. This one is optionnal
  and can be used for other SoC.
- Fix mediatek,dsi.yaml issue.
- Remove the extra clock in the DPI node/driver and fix the dpi clock
  parenting to be consistent with the DPI clock assignement.
- Link to v1: https://lore.kernel.org/r/20231023-display-support-v1-0-5c860ed5c33b at baylibre.com

[1] https://lore.kernel.org/lkml/20240516081104.83458-1-angelogioacchino.delregno at collabora.com/

---
Alexandre Mergnat (3):
      arm64: defconfig: enable display support for mt8365-evk
      drm/panel: startek-kd070fhfid015: add another init step
      drm/mediatek: dsi: remove custom init part

 arch/arm64/configs/defconfig                       |  2 ++
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c            |  2 --
 drivers/gpu/drm/mediatek/mtk_disp_drv.h            |  2 --
 drivers/gpu/drm/mediatek/mtk_dsi.c                 | 16 --------------
 .../gpu/drm/panel/panel-startek-kd070fhfid015.c    | 25 +++++++++++++---------
 5 files changed, 17 insertions(+), 30 deletions(-)
---
base-commit: 72e8ab284ff34785ec292f79610de5fcf3825b32
change-id: 20231023-display-support-c6418b30e419

Best regards,
-- 
Alexandre Mergnat <amergnat at baylibre.com>



From amergnat at baylibre.com  Thu Mar 20 01:48:45 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Thu, 20 Mar 2025 09:48:45 +0100
Subject: [PATCH v8 1/3] arm64: defconfig: enable display support for
 mt8365-evk
In-Reply-To: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
Message-ID: <20231023-display-support-v8-1-c2dd7b0fb2bd@baylibre.com>

Enable the DRM HDMI connector support and the MIPI-DSI display
Startek KD070FHFID015 panel to have HDMI and DSI display working
on the mt8365-evk board.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index c62831e615863..1e2963a13500b 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -897,9 +897,11 @@ CONFIG_DRM_PANEL_NOVATEK_NT36672E=m
 CONFIG_DRM_PANEL_RAYDIUM_RM67191=m
 CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20=m
 CONFIG_DRM_PANEL_SITRONIX_ST7703=m
+CONFIG_DRM_PANEL_STARTEK_KD070FHFID015=m
 CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
 CONFIG_DRM_PANEL_VISIONOX_VTDR6130=m
 CONFIG_DRM_FSL_LDB=m
+CONFIG_DRM_DISPLAY_CONNECTOR=m
 CONFIG_DRM_LONTIUM_LT8912B=m
 CONFIG_DRM_LONTIUM_LT9611=m
 CONFIG_DRM_LONTIUM_LT9611UXC=m

-- 
2.25.1



From amergnat at baylibre.com  Thu Mar 20 01:48:46 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Thu, 20 Mar 2025 09:48:46 +0100
Subject: [PATCH v8 2/3] drm/panel: startek-kd070fhfid015: add another init
 step
In-Reply-To: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
Message-ID: <20231023-display-support-v8-2-c2dd7b0fb2bd@baylibre.com>

Currently, the panel set power, set gpio and enable the display link
in stk_panel_prepare, pointed by drm_panel_funcs.prepare, called by
panel_bridge_atomic_pre_enable, pointed by
drm_bridge_funcs.atomic_pre_enable. According to the drm_bridge.h,
atomic_pre_enable must not enable the display link

Since the DSI driver is properly inited by the DRM, the panel try to
communicate with the panel before DSI is powered on.

To solve that, use stk_panel_enable to enable the display link because
it's called after the mtk_dsi_bridge_atomic_pre_enable which is power
on the DSI.

Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
---
 .../gpu/drm/panel/panel-startek-kd070fhfid015.c    | 25 +++++++++++++---------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
index c0c95355b7435..bc3c4038bf4f5 100644
--- a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
+++ b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
@@ -135,19 +135,9 @@ static int stk_panel_prepare(struct drm_panel *panel)
 	gpiod_set_value(stk->enable_gpio, 1);
 	mdelay(20);
 	gpiod_set_value(stk->reset_gpio, 1);
-	mdelay(10);
-	ret = stk_panel_init(stk);
-	if (ret < 0)
-		goto poweroff;
-
-	ret = stk_panel_on(stk);
-	if (ret < 0)
-		goto poweroff;
 
 	return 0;
 
-poweroff:
-	regulator_disable(stk->supplies[POWER].consumer);
 iovccoff:
 	regulator_disable(stk->supplies[IOVCC].consumer);
 	gpiod_set_value(stk->reset_gpio, 0);
@@ -156,6 +146,20 @@ static int stk_panel_prepare(struct drm_panel *panel)
 	return ret;
 }
 
+static int stk_panel_enable(struct drm_panel *panel)
+{
+	struct stk_panel *stk = to_stk_panel(panel);
+	int ret;
+
+	ret = stk_panel_init(stk);
+	if (ret < 0)
+		return ret;
+
+	ret = stk_panel_on(stk);
+
+	return ret;
+}
+
 static const struct drm_display_mode default_mode = {
 		.clock = 163204,
 		.hdisplay = 1200,
@@ -239,6 +243,7 @@ drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
 }
 
 static const struct drm_panel_funcs stk_panel_funcs = {
+	.enable = stk_panel_enable,
 	.unprepare = stk_panel_unprepare,
 	.prepare = stk_panel_prepare,
 	.get_modes = stk_panel_get_modes,

-- 
2.25.1



From amergnat at baylibre.com  Thu Mar 20 01:48:47 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Thu, 20 Mar 2025 09:48:47 +0100
Subject: [PATCH v8 3/3] drm/mediatek: dsi: remove custom init part
In-Reply-To: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
Message-ID: <20231023-display-support-v8-3-c2dd7b0fb2bd@baylibre.com>

To be aligned with the DRM framework and avoid DSI power being driven
by two different entities, remove the custom function and keep the DRM
API to initialize the DSI.

Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c |  2 --
 drivers/gpu/drm/mediatek/mtk_disp_drv.h |  2 --
 drivers/gpu/drm/mediatek/mtk_dsi.c      | 16 ----------------
 3 files changed, 20 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index edc6417639e64..d86eed0d279d3 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -317,8 +317,6 @@ static const struct mtk_ddp_comp_funcs ddp_dsc = {
 };
 
 static const struct mtk_ddp_comp_funcs ddp_dsi = {
-	.start = mtk_dsi_ddp_start,
-	.stop = mtk_dsi_ddp_stop,
 	.encoder_index = mtk_dsi_encoder_index,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 04217a36939cd..5657854fa2f9e 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -47,8 +47,6 @@ void mtk_dpi_start(struct device *dev);
 void mtk_dpi_stop(struct device *dev);
 unsigned int mtk_dpi_encoder_index(struct device *dev);
 
-void mtk_dsi_ddp_start(struct device *dev);
-void mtk_dsi_ddp_stop(struct device *dev);
 unsigned int mtk_dsi_encoder_index(struct device *dev);
 
 int mtk_gamma_clk_enable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index e61b9bc68e9a3..b813b49340420 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -787,7 +787,6 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
 {
 	if (dsi->enabled)
 		return;
-
 	mtk_dsi_lane_ready(dsi);
 	mtk_dsi_set_mode(dsi);
 	mtk_dsi_clk_hs_mode(dsi, 1);
@@ -893,20 +892,6 @@ static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = {
 	.mode_set = mtk_dsi_bridge_mode_set,
 };
 
-void mtk_dsi_ddp_start(struct device *dev)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	mtk_dsi_poweron(dsi);
-}
-
-void mtk_dsi_ddp_stop(struct device *dev)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	mtk_dsi_poweroff(dsi);
-}
-
 static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
 {
 	int ret;
@@ -1243,7 +1228,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	}
 
 	init_waitqueue_head(&dsi->irq_wait_queue);
-
 	platform_set_drvdata(pdev, dsi);
 
 	dsi->bridge.funcs = &mtk_dsi_bridge_funcs;

-- 
2.25.1



From jiebing.chen at amlogic.com  Thu Mar 20 01:53:19 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 16:53:19 +0800
Subject: [PATCH v4 4/6] ASoC: meson: g12a-toacodec: Add s4 tocodec driver
In-Reply-To: <1jfrj82ioj.fsf@starbuckisacylon.baylibre.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-4-686867fad719@amlogic.com>
 <1jfrj82ioj.fsf@starbuckisacylon.baylibre.com>
Message-ID: <1d2f7290-a126-4e6a-a4be-17320ac8e3b9@amlogic.com>


? 2025/3/20 16:46, Jerome Brunet ??:
> [ EXTERNAL EMAIL ]
>
> On Wed 19 Mar 2025 at 15:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:
>
>> From: jiebing chen <jiebing.chen at amlogic.com>
>>
>> S4 tocodec support 8 lane to input, It need to enable
>> bclk and mclk control bit when work
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   sound/soc/meson/g12a-toacodec.c | 46 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 46 insertions(+)
>>
>> diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c
>> index 531bb8707a3ec4c47814d6a0676d5c62c705da75..88f9adabb3b5d7d8881fa110f1d0d51e9ac9c60e 100644
>> --- a/sound/soc/meson/g12a-toacodec.c
>> +++ b/sound/soc/meson/g12a-toacodec.c
>> @@ -41,6 +41,9 @@
>>   #define  CTRL0_BCLK_SEL_LSB          4
>>   #define  CTRL0_MCLK_SEL                      GENMASK(2, 0)
>>
>> +#define CTRL0_BCLK_ENABLE_SHIFT              30
>> +#define CTRL0_MCLK_ENABLE_SHIFT              29
>> +
>>   #define TOACODEC_OUT_CHMAX           2
>>
>>   struct g12a_toacodec {
>> @@ -129,6 +132,10 @@ static const struct snd_kcontrol_new g12a_toacodec_out_enable =
>>        SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0,
>>                                    CTRL0_ENABLE_SHIFT, 1, 0);
>>
>> +static const struct snd_kcontrol_new s4_toacodec_clk_enable =
>> +     SOC_DAPM_DOUBLE("Switch", TOACODEC_CTRL0,
>> +                     CTRL0_BCLK_ENABLE_SHIFT, CTRL0_MCLK_ENABLE_SHIFT, 1, 0);
>> +
> I think I remember commenting on this already.

HI, Jerome

This line is only defined and not used, it should be delete in next version

We put the enable of bclk on wiget in dapm when dapm power on, help to 
review

this method

+static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
+     SND_SOC_DAPM_MUX("SRC", TOACODEC_CTRL0, CTRL0_BCLK_ENABLE_SHIFT, 0,
+                      &sm1_toacodec_mux),
+     SND_SOC_DAPM_SWITCH("OUT EN", TOACODEC_CTRL0, CTRL0_MCLK_ENABLE_SHIFT, 0,
+                         &g12a_toacodec_out_enable),
+};
+

>
>>   static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = {
>>        SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0,
>>                         &g12a_toacodec_mux),
>> @@ -143,6 +150,19 @@ static const struct snd_soc_dapm_widget sm1_toacodec_widgets[] = {
>>                            &g12a_toacodec_out_enable),
>>   };
>>
>> +/*
>> + * FIXME:
>> + * On this soc, tocodec need enable mclk and bclk control
>> + * just enable it when dapm power widget power on.
>> + */
>> +
>> +static const struct snd_soc_dapm_widget s4_toacodec_widgets[] = {
>> +     SND_SOC_DAPM_MUX("SRC", TOACODEC_CTRL0, CTRL0_BCLK_ENABLE_SHIFT, 0,
>> +                      &sm1_toacodec_mux),
>> +     SND_SOC_DAPM_SWITCH("OUT EN", TOACODEC_CTRL0, CTRL0_MCLK_ENABLE_SHIFT, 0,
>> +                         &g12a_toacodec_out_enable),
>> +};
>> +
>>   static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream,
>>                                         struct snd_pcm_hw_params *params,
>>                                         struct snd_soc_dai *dai)
>> @@ -236,6 +256,10 @@ static const struct snd_kcontrol_new sm1_toacodec_controls[] = {
>>        SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 3, 0),
>>   };
>>
>> +static const struct snd_kcontrol_new s4_toacodec_controls[] = {
>> +     SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL_SM1, 7, 0),
>> +};
>> +
>>   static const struct snd_soc_component_driver g12a_toacodec_component_drv = {
>>        .probe                  = g12a_toacodec_component_probe,
>>        .controls               = g12a_toacodec_controls,
>> @@ -258,6 +282,17 @@ static const struct snd_soc_component_driver sm1_toacodec_component_drv = {
>>        .endianness             = 1,
>>   };
>>
>> +static const struct snd_soc_component_driver s4_toacodec_component_drv = {
>> +     .probe                  = sm1_toacodec_component_probe,
>> +     .controls               = s4_toacodec_controls,
>> +     .num_controls           = ARRAY_SIZE(s4_toacodec_controls),
>> +     .dapm_widgets           = s4_toacodec_widgets,
>> +     .num_dapm_widgets       = ARRAY_SIZE(s4_toacodec_widgets),
>> +     .dapm_routes            = g12a_toacodec_routes,
>> +     .num_dapm_routes        = ARRAY_SIZE(g12a_toacodec_routes),
>> +     .endianness             = 1,
>> +};
>> +
>>   static const struct regmap_config g12a_toacodec_regmap_cfg = {
>>        .reg_bits       = 32,
>>        .val_bits       = 32,
>> @@ -278,6 +313,13 @@ static const struct g12a_toacodec_match_data sm1_toacodec_match_data = {
>>        .field_bclk_sel = REG_FIELD(TOACODEC_CTRL0, 4, 6),
>>   };
>>
>> +static const struct g12a_toacodec_match_data s4_toacodec_match_data = {
>> +     .component_drv  = &s4_toacodec_component_drv,
>> +     .field_dat_sel  = REG_FIELD(TOACODEC_CTRL0, 19, 20),
>> +     .field_lrclk_sel = REG_FIELD(TOACODEC_CTRL0, 12, 14),
>> +     .field_bclk_sel = REG_FIELD(TOACODEC_CTRL0, 4, 6),
>> +};
>> +
>>   static const struct of_device_id g12a_toacodec_of_match[] = {
>>        {
>>                .compatible = "amlogic,g12a-toacodec",
>> @@ -287,6 +329,10 @@ static const struct of_device_id g12a_toacodec_of_match[] = {
>>                .compatible = "amlogic,sm1-toacodec",
>>                .data = &sm1_toacodec_match_data,
>>        },
>> +     {
>> +             .compatible = "amlogic,s4-toacodec",
>> +             .data = &s4_toacodec_match_data,
>> +     },
>>        {}
>>   };
>>   MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match);
> --
> Jerome


From jiebing.chen at amlogic.com  Thu Mar 20 01:59:30 2025
From: jiebing.chen at amlogic.com (Jiebing Chen)
Date: Thu, 20 Mar 2025 16:59:30 +0800
Subject: [PATCH v4 5/6] clk: meson: axg-audio: Add the mclk pad div for s4
 chip
In-Reply-To: <1jldt02iv4.fsf@starbuckisacylon.baylibre.com>
References: <20250319-audio_drvier-v4-0-686867fad719@amlogic.com>
 <20250319-audio_drvier-v4-5-686867fad719@amlogic.com>
 <1jldt02iv4.fsf@starbuckisacylon.baylibre.com>
Message-ID: <c3acf2bb-c067-41d8-982c-4cdbafb86944@amlogic.com>


? 2025/3/20 16:42, Jerome Brunet ??:
> [ EXTERNAL EMAIL ]
>
> On Wed 19 Mar 2025 at 15:04, jiebing chen via B4 Relay <devnull+jiebing.chen.amlogic.com at kernel.org> wrote:
>
>> From: jiebing chen <jiebing.chen at amlogic.com>
>>
>> Add mclk pad div support, Increased the number of lrclk
>> and sclk pads to five
>>
>> Signed-off-by: jiebing chen <jiebing.chen at amlogic.com>
>> ---
>>   drivers/clk/meson/axg-audio.c | 441 +++++++++++++++++++++++++++++++++++++++++-
>>   drivers/clk/meson/axg-audio.h |   6 +
>>   2 files changed, 445 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
>> index 9df627b142f89788966ede0262aaaf39e13f0b49..50e7c78ddb98ee08121690633c8113489503bc04 100644
>> --- a/drivers/clk/meson/axg-audio.c
>> +++ b/drivers/clk/meson/axg-audio.c
>> @@ -323,6 +323,16 @@ static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
>>        AUD_MUX(_name, _reg, 0x7, _shift, 0, _parents,          \
>>                CLK_SET_RATE_NO_REPARENT)
>>
>> +#define AUD_MCLK_PAD_MUX(_name, _reg, _shift)                                        \
>> +     AUD_MUX(_name##_sel, _reg, 0x7, _shift, CLK_MUX_ROUND_CLOSEST,                  \
>> +             mclk_pad_ctrl_parent_data, 0)
>> +#define AUD_MCLK_PAD_DIV(_name, _reg, _shift)                                        \
>> +     AUD_DIV(_name##_div, _reg, _shift, 8, CLK_DIVIDER_ROUND_CLOSEST,                        \
>> +             aud_##_name##_sel, CLK_SET_RATE_PARENT)
>> +#define AUD_MCLK_PAD_GATE(_name, _reg, _shift)                                       \
>> +     AUD_GATE(_name, _reg, _shift, aud_##_name##_div,                        \
>> +              CLK_SET_RATE_PARENT)
>> +
>>   /* Common Clocks */
>>   static struct clk_regmap ddr_arb =
>>        AUD_PCLK_GATE(ddr_arb, AUDIO_CLK_GATE_EN, 0);
>> @@ -826,6 +836,49 @@ static struct clk_regmap sm1_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
>>   static struct clk_regmap sm1_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
>>        tdm_sclk_pad_2, AUDIO_SM1_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
>>
>> +static struct clk_regmap s4_tdm_mclk_pad0_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 8);
>> +static struct clk_regmap s4_tdm_mclk_pad1_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 24);
>> +static struct clk_regmap s4_tdm_mclk_pad2_sel =
>> +     AUD_MCLK_PAD_MUX(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 8);
>> +
>> +static struct clk_regmap s4_tdm_mclk_pad0_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 0);
>> +static struct clk_regmap s4_tdm_mclk_pad1_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 16);
>> +static struct clk_regmap s4_tdm_mclk_pad2_div =
>> +     AUD_MCLK_PAD_DIV(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 0);
>> +
>> +static struct clk_regmap s4_tdm_mclk_pad_0 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad0, AUDIO_S4_MCLK_PAD_CTRL0, 15);
>> +static struct clk_regmap s4_tdm_mclk_pad_1 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad1, AUDIO_S4_MCLK_PAD_CTRL0, 31);
>> +static struct clk_regmap s4_tdm_mclk_pad_2 =
>> +     AUD_MCLK_PAD_GATE(mclk_pad2, AUDIO_S4_MCLK_PAD_CTRL1, 15);
>> +
>> +static struct clk_regmap s4_tdm_sclk_pad_0 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL0, 0, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_1 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL0, 4, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_2 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL0, 8, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_3 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL0, 16, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_sclk_pad_4 =
>> +     AUD_TDM_PAD_CTRL(tdm_sclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL0, 20, lrclk_pad_ctrl_parent_data);
>> +
>> +static struct clk_regmap s4_tdm_lrclk_pad_0 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_0, AUDIO_S4_SCLK_PAD_CTRL1, 0, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_1 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_1, AUDIO_S4_SCLK_PAD_CTRL1, 4, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_2 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_2, AUDIO_S4_SCLK_PAD_CTRL1, 8, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_3 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_3, AUDIO_S4_SCLK_PAD_CTRL1, 16, lrclk_pad_ctrl_parent_data);
>> +static struct clk_regmap s4_tdm_lrclk_pad_4 =
>> +     AUD_TDM_PAD_CTRL(tdm_lrclk_pad_4, AUDIO_S4_SCLK_PAD_CTRL1, 20, lrclk_pad_ctrl_parent_data);
>> +
>>   /*
>>    * Array of all clocks provided by this provider
>>    * The input clocks of the controller will be populated at runtime
>> @@ -1257,6 +1310,177 @@ static struct clk_hw *sm1_audio_hw_clks[] = {
>>        [AUD_CLKID_EARCRX_DMAC]         = &sm1_earcrx_dmac_clk.hw,
>>   };
>>
>> +/*
>> + * Array of all S4 clocks provided by this provider
>> + * The input clocks of the controller will be populated at runtime
>> + */
>> +static struct clk_hw *s4_audio_hw_clks[] = {
>> +     [AUD_CLKID_DDR_ARB]             = &ddr_arb.hw,
>> +     [AUD_CLKID_PDM]                 = &pdm.hw,
>> +     [AUD_CLKID_TDMIN_A]             = &tdmin_a.hw,
>> +     [AUD_CLKID_TDMIN_B]             = &tdmin_b.hw,
>> +     [AUD_CLKID_TDMIN_C]             = &tdmin_c.hw,
>> +     [AUD_CLKID_TDMIN_LB]            = &tdmin_lb.hw,
>> +     [AUD_CLKID_TDMOUT_A]            = &tdmout_a.hw,
>> +     [AUD_CLKID_TDMOUT_B]            = &tdmout_b.hw,
>> +     [AUD_CLKID_TDMOUT_C]            = &tdmout_c.hw,
>> +     [AUD_CLKID_FRDDR_A]             = &frddr_a.hw,
>> +     [AUD_CLKID_FRDDR_B]             = &frddr_b.hw,
>> +     [AUD_CLKID_FRDDR_C]             = &frddr_c.hw,
>> +     [AUD_CLKID_TODDR_A]             = &toddr_a.hw,
>> +     [AUD_CLKID_TODDR_B]             = &toddr_b.hw,
>> +     [AUD_CLKID_TODDR_C]             = &toddr_c.hw,
>> +     [AUD_CLKID_LOOPBACK]            = &loopback.hw,
>> +     [AUD_CLKID_SPDIFIN]             = &spdifin.hw,
>> +     [AUD_CLKID_SPDIFOUT]            = &spdifout.hw,
>> +     [AUD_CLKID_RESAMPLE]            = &resample.hw,
>> +     [AUD_CLKID_SPDIFOUT_B]          = &spdifout_b.hw,
>> +     [AUD_CLKID_MST_A_MCLK_SEL]      = &sm1_mst_a_mclk_sel.hw,
>> +     [AUD_CLKID_MST_B_MCLK_SEL]      = &sm1_mst_b_mclk_sel.hw,
>> +     [AUD_CLKID_MST_C_MCLK_SEL]      = &sm1_mst_c_mclk_sel.hw,
>> +     [AUD_CLKID_MST_D_MCLK_SEL]      = &sm1_mst_d_mclk_sel.hw,
>> +     [AUD_CLKID_MST_E_MCLK_SEL]      = &sm1_mst_e_mclk_sel.hw,
>> +     [AUD_CLKID_MST_F_MCLK_SEL]      = &sm1_mst_f_mclk_sel.hw,
>> +     [AUD_CLKID_MST_A_MCLK_DIV]      = &sm1_mst_a_mclk_div.hw,
>> +     [AUD_CLKID_MST_B_MCLK_DIV]      = &sm1_mst_b_mclk_div.hw,
>> +     [AUD_CLKID_MST_C_MCLK_DIV]      = &sm1_mst_c_mclk_div.hw,
>> +     [AUD_CLKID_MST_D_MCLK_DIV]      = &sm1_mst_d_mclk_div.hw,
>> +     [AUD_CLKID_MST_E_MCLK_DIV]      = &sm1_mst_e_mclk_div.hw,
>> +     [AUD_CLKID_MST_F_MCLK_DIV]      = &sm1_mst_f_mclk_div.hw,
>> +     [AUD_CLKID_MST_A_MCLK]          = &sm1_mst_a_mclk.hw,
>> +     [AUD_CLKID_MST_B_MCLK]          = &sm1_mst_b_mclk.hw,
>> +     [AUD_CLKID_MST_C_MCLK]          = &sm1_mst_c_mclk.hw,
>> +     [AUD_CLKID_MST_D_MCLK]          = &sm1_mst_d_mclk.hw,
>> +     [AUD_CLKID_MST_E_MCLK]          = &sm1_mst_e_mclk.hw,
>> +     [AUD_CLKID_MST_F_MCLK]          = &sm1_mst_f_mclk.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &spdifout_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &spdifout_clk_div.hw,
>> +     [AUD_CLKID_SPDIFOUT_CLK]        = &spdifout_clk.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK_SEL]  = &spdifout_b_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK_DIV]  = &spdifout_b_clk_div.hw,
>> +     [AUD_CLKID_SPDIFOUT_B_CLK]      = &spdifout_b_clk.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK_SEL]     = &spdifin_clk_sel.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK_DIV]     = &spdifin_clk_div.hw,
>> +     [AUD_CLKID_SPDIFIN_CLK]         = &spdifin_clk.hw,
>> +     [AUD_CLKID_PDM_DCLK_SEL]        = &pdm_dclk_sel.hw,
>> +     [AUD_CLKID_PDM_DCLK_DIV]        = &pdm_dclk_div.hw,
>> +     [AUD_CLKID_PDM_DCLK]            = &pdm_dclk.hw,
>> +     [AUD_CLKID_PDM_SYSCLK_SEL]      = &pdm_sysclk_sel.hw,
>> +     [AUD_CLKID_PDM_SYSCLK_DIV]      = &pdm_sysclk_div.hw,
>> +     [AUD_CLKID_PDM_SYSCLK]          = &pdm_sysclk.hw,
>> +     [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &mst_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &mst_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &mst_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &mst_d_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &mst_e_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &mst_f_sclk_pre_en.hw,
>> +     [AUD_CLKID_MST_A_SCLK_DIV]      = &mst_a_sclk_div.hw,
>> +     [AUD_CLKID_MST_B_SCLK_DIV]      = &mst_b_sclk_div.hw,
>> +     [AUD_CLKID_MST_C_SCLK_DIV]      = &mst_c_sclk_div.hw,
>> +     [AUD_CLKID_MST_D_SCLK_DIV]      = &mst_d_sclk_div.hw,
>> +     [AUD_CLKID_MST_E_SCLK_DIV]      = &mst_e_sclk_div.hw,
>> +     [AUD_CLKID_MST_F_SCLK_DIV]      = &mst_f_sclk_div.hw,
>> +     [AUD_CLKID_MST_A_SCLK_POST_EN]  = &mst_a_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_B_SCLK_POST_EN]  = &mst_b_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_C_SCLK_POST_EN]  = &mst_c_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_D_SCLK_POST_EN]  = &mst_d_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_E_SCLK_POST_EN]  = &mst_e_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_F_SCLK_POST_EN]  = &mst_f_sclk_post_en.hw,
>> +     [AUD_CLKID_MST_A_SCLK]          = &mst_a_sclk.hw,
>> +     [AUD_CLKID_MST_B_SCLK]          = &mst_b_sclk.hw,
>> +     [AUD_CLKID_MST_C_SCLK]          = &mst_c_sclk.hw,
>> +     [AUD_CLKID_MST_D_SCLK]          = &mst_d_sclk.hw,
>> +     [AUD_CLKID_MST_E_SCLK]          = &mst_e_sclk.hw,
>> +     [AUD_CLKID_MST_F_SCLK]          = &mst_f_sclk.hw,
>> +     [AUD_CLKID_MST_A_LRCLK_DIV]     = &mst_a_lrclk_div.hw,
>> +     [AUD_CLKID_MST_B_LRCLK_DIV]     = &mst_b_lrclk_div.hw,
>> +     [AUD_CLKID_MST_C_LRCLK_DIV]     = &mst_c_lrclk_div.hw,
>> +     [AUD_CLKID_MST_D_LRCLK_DIV]     = &mst_d_lrclk_div.hw,
>> +     [AUD_CLKID_MST_E_LRCLK_DIV]     = &mst_e_lrclk_div.hw,
>> +     [AUD_CLKID_MST_F_LRCLK_DIV]     = &mst_f_lrclk_div.hw,
>> +     [AUD_CLKID_MST_A_LRCLK]         = &mst_a_lrclk.hw,
>> +     [AUD_CLKID_MST_B_LRCLK]         = &mst_b_lrclk.hw,
>> +     [AUD_CLKID_MST_C_LRCLK]         = &mst_c_lrclk.hw,
>> +     [AUD_CLKID_MST_D_LRCLK]         = &mst_d_lrclk.hw,
>> +     [AUD_CLKID_MST_E_LRCLK]         = &mst_e_lrclk.hw,
>> +     [AUD_CLKID_MST_F_LRCLK]         = &mst_f_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &tdmin_a_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &tdmin_b_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &tdmin_c_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &tdmin_lb_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &tdmout_a_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &tdmout_b_sclk_sel.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &tdmout_c_sclk_sel.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &tdmin_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &tdmin_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &tdmin_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &tdmin_lb_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &tdmout_a_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &tdmout_b_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &tdmout_c_sclk_pre_en.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &tdmin_a_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &tdmin_b_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &tdmin_c_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &tdmin_lb_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &tdmout_a_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &tdmout_b_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &tdmout_c_sclk_post_en.hw,
>> +     [AUD_CLKID_TDMIN_A_SCLK]        = &tdmin_a_sclk.hw,
>> +     [AUD_CLKID_TDMIN_B_SCLK]        = &tdmin_b_sclk.hw,
>> +     [AUD_CLKID_TDMIN_C_SCLK]        = &tdmin_c_sclk.hw,
>> +     [AUD_CLKID_TDMIN_LB_SCLK]       = &tdmin_lb_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_A_SCLK]       = &g12a_tdmout_a_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_B_SCLK]       = &g12a_tdmout_b_sclk.hw,
>> +     [AUD_CLKID_TDMOUT_C_SCLK]       = &g12a_tdmout_c_sclk.hw,
>> +     [AUD_CLKID_TDMIN_A_LRCLK]       = &tdmin_a_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_B_LRCLK]       = &tdmin_b_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_C_LRCLK]       = &tdmin_c_lrclk.hw,
>> +     [AUD_CLKID_TDMIN_LB_LRCLK]      = &tdmin_lb_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_A_LRCLK]      = &tdmout_a_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_B_LRCLK]      = &tdmout_b_lrclk.hw,
>> +     [AUD_CLKID_TDMOUT_C_LRCLK]      = &tdmout_c_lrclk.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0]       = &s4_tdm_mclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1]       = &s4_tdm_mclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD0]      = &s4_tdm_lrclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD1]      = &s4_tdm_lrclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD2]      = &s4_tdm_lrclk_pad_2.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD0]       = &s4_tdm_sclk_pad_0.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD1]       = &s4_tdm_sclk_pad_1.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD2]       = &s4_tdm_sclk_pad_2.hw,
>> +     [AUD_CLKID_TOP]                 = &sm1_aud_top.hw,
>> +     [AUD_CLKID_TORAM]               = &toram.hw,
>> +     [AUD_CLKID_EQDRC]               = &eqdrc.hw,
>> +     [AUD_CLKID_RESAMPLE_B]          = &resample_b.hw,
>> +     [AUD_CLKID_TOVAD]               = &tovad.hw,
>> +     [AUD_CLKID_LOCKER]              = &locker.hw,
>> +     [AUD_CLKID_SPDIFIN_LB]          = &spdifin_lb.hw,
>> +     [AUD_CLKID_FRDDR_D]             = &frddr_d.hw,
>> +     [AUD_CLKID_TODDR_D]             = &toddr_d.hw,
>> +     [AUD_CLKID_LOOPBACK_B]          = &loopback_b.hw,
>> +     [AUD_CLKID_CLK81_EN]            = &sm1_clk81_en.hw,
>> +     [AUD_CLKID_SYSCLK_A_DIV]        = &sm1_sysclk_a_div.hw,
>> +     [AUD_CLKID_SYSCLK_A_EN]         = &sm1_sysclk_a_en.hw,
>> +     [AUD_CLKID_SYSCLK_B_DIV]        = &sm1_sysclk_b_div.hw,
>> +     [AUD_CLKID_SYSCLK_B_EN]         = &sm1_sysclk_b_en.hw,
>> +     [AUD_CLKID_EARCRX]              = &earcrx.hw,
>> +     [AUD_CLKID_EARCRX_CMDC_SEL]     = &sm1_earcrx_cmdc_clk_sel.hw,
>> +     [AUD_CLKID_EARCRX_CMDC_DIV]     = &sm1_earcrx_cmdc_clk_div.hw,
>> +     [AUD_CLKID_EARCRX_CMDC]         = &sm1_earcrx_cmdc_clk.hw,
>> +     [AUD_CLKID_EARCRX_DMAC_SEL]     = &sm1_earcrx_dmac_clk_sel.hw,
>> +     [AUD_CLKID_EARCRX_DMAC_DIV]     = &sm1_earcrx_dmac_clk_div.hw,
>> +     [AUD_CLKID_EARCRX_DMAC]         = &sm1_earcrx_dmac_clk.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0_SEL]           = &s4_tdm_mclk_pad0_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1_SEL]       = &s4_tdm_mclk_pad1_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD0_DIV]           = &s4_tdm_mclk_pad0_div.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD1_DIV]       = &s4_tdm_mclk_pad1_div.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2]               = &s4_tdm_mclk_pad_2.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2_SEL]           = &s4_tdm_mclk_pad2_sel.hw,
>> +     [AUD_CLKID_TDM_MCLK_PAD2_DIV]       = &s4_tdm_mclk_pad2_div.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD3]       = &s4_tdm_sclk_pad_3.hw,
>> +     [AUD_CLKID_TDM_SCLK_PAD4]       = &s4_tdm_sclk_pad_4.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD3]      = &s4_tdm_lrclk_pad_3.hw,
>> +     [AUD_CLKID_TDM_LRCLK_PAD4]      = &s4_tdm_lrclk_pad_4.hw,
>> +};
>>
>>   /* Convenience table to populate regmap in .probe(). */
>>   static struct clk_regmap *const axg_clk_regmaps[] = {
>> @@ -1678,6 +1902,177 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
>>        &sm1_earcrx_dmac_clk,
>>   };
>>
>> +static struct clk_regmap *const s4_clk_regmaps[] = {
>> +     &ddr_arb,
>> +     &pdm,
>> +     &tdmin_a,
>> +     &tdmin_b,
>> +     &tdmin_c,
>> +     &tdmin_lb,
>> +     &tdmout_a,
>> +     &tdmout_b,
>> +     &tdmout_c,
>> +     &frddr_a,
>> +     &frddr_b,
>> +     &frddr_c,
>> +     &toddr_a,
>> +     &toddr_b,
>> +     &toddr_c,
>> +     &loopback,
>> +     &spdifin,
>> +     &spdifout,
>> +     &resample,
>> +     &spdifout_b,
>> +     &sm1_mst_a_mclk_sel,
>> +     &sm1_mst_b_mclk_sel,
>> +     &sm1_mst_c_mclk_sel,
>> +     &sm1_mst_d_mclk_sel,
>> +     &sm1_mst_e_mclk_sel,
>> +     &sm1_mst_f_mclk_sel,
>> +     &sm1_mst_a_mclk_div,
>> +     &sm1_mst_b_mclk_div,
>> +     &sm1_mst_c_mclk_div,
>> +     &sm1_mst_d_mclk_div,
>> +     &sm1_mst_e_mclk_div,
>> +     &sm1_mst_f_mclk_div,
>> +     &sm1_mst_a_mclk,
>> +     &sm1_mst_b_mclk,
>> +     &sm1_mst_c_mclk,
>> +     &sm1_mst_d_mclk,
>> +     &sm1_mst_e_mclk,
>> +     &sm1_mst_f_mclk,
>> +     &spdifout_clk_sel,
>> +     &spdifout_clk_div,
>> +     &spdifout_clk,
>> +     &spdifin_clk_sel,
>> +     &spdifin_clk_div,
>> +     &spdifin_clk,
>> +     &pdm_dclk_sel,
>> +     &pdm_dclk_div,
>> +     &pdm_dclk,
>> +     &pdm_sysclk_sel,
>> +     &pdm_sysclk_div,
>> +     &pdm_sysclk,
>> +     &mst_a_sclk_pre_en,
>> +     &mst_b_sclk_pre_en,
>> +     &mst_c_sclk_pre_en,
>> +     &mst_d_sclk_pre_en,
>> +     &mst_e_sclk_pre_en,
>> +     &mst_f_sclk_pre_en,
>> +     &mst_a_sclk_div,
>> +     &mst_b_sclk_div,
>> +     &mst_c_sclk_div,
>> +     &mst_d_sclk_div,
>> +     &mst_e_sclk_div,
>> +     &mst_f_sclk_div,
>> +     &mst_a_sclk_post_en,
>> +     &mst_b_sclk_post_en,
>> +     &mst_c_sclk_post_en,
>> +     &mst_d_sclk_post_en,
>> +     &mst_e_sclk_post_en,
>> +     &mst_f_sclk_post_en,
>> +     &mst_a_sclk,
>> +     &mst_b_sclk,
>> +     &mst_c_sclk,
>> +     &mst_d_sclk,
>> +     &mst_e_sclk,
>> +     &mst_f_sclk,
>> +     &mst_a_lrclk_div,
>> +     &mst_b_lrclk_div,
>> +     &mst_c_lrclk_div,
>> +     &mst_d_lrclk_div,
>> +     &mst_e_lrclk_div,
>> +     &mst_f_lrclk_div,
>> +     &mst_a_lrclk,
>> +     &mst_b_lrclk,
>> +     &mst_c_lrclk,
>> +     &mst_d_lrclk,
>> +     &mst_e_lrclk,
>> +     &mst_f_lrclk,
>> +     &tdmin_a_sclk_sel,
>> +     &tdmin_b_sclk_sel,
>> +     &tdmin_c_sclk_sel,
>> +     &tdmin_lb_sclk_sel,
>> +     &tdmout_a_sclk_sel,
>> +     &tdmout_b_sclk_sel,
>> +     &tdmout_c_sclk_sel,
>> +     &tdmin_a_sclk_pre_en,
>> +     &tdmin_b_sclk_pre_en,
>> +     &tdmin_c_sclk_pre_en,
>> +     &tdmin_lb_sclk_pre_en,
>> +     &tdmout_a_sclk_pre_en,
>> +     &tdmout_b_sclk_pre_en,
>> +     &tdmout_c_sclk_pre_en,
>> +     &tdmin_a_sclk_post_en,
>> +     &tdmin_b_sclk_post_en,
>> +     &tdmin_c_sclk_post_en,
>> +     &tdmin_lb_sclk_post_en,
>> +     &tdmout_a_sclk_post_en,
>> +     &tdmout_b_sclk_post_en,
>> +     &tdmout_c_sclk_post_en,
>> +     &tdmin_a_sclk,
>> +     &tdmin_b_sclk,
>> +     &tdmin_c_sclk,
>> +     &tdmin_lb_sclk,
>> +     &g12a_tdmout_a_sclk,
>> +     &g12a_tdmout_b_sclk,
>> +     &g12a_tdmout_c_sclk,
>> +     &tdmin_a_lrclk,
>> +     &tdmin_b_lrclk,
>> +     &tdmin_c_lrclk,
>> +     &tdmin_lb_lrclk,
>> +     &tdmout_a_lrclk,
>> +     &tdmout_b_lrclk,
>> +     &tdmout_c_lrclk,
>> +     &spdifout_b_clk_sel,
>> +     &spdifout_b_clk_div,
>> +     &spdifout_b_clk,
>> +     &sm1_aud_top,
>> +     &toram,
>> +     &eqdrc,
>> +     &resample_b,
>> +     &tovad,
>> +     &locker,
>> +     &spdifin_lb,
>> +     &frddr_d,
>> +     &toddr_d,
>> +     &loopback_b,
>> +     &sm1_clk81_en,
>> +     &sm1_sysclk_a_div,
>> +     &sm1_sysclk_a_en,
>> +     &sm1_sysclk_b_div,
>> +     &sm1_sysclk_b_en,
>> +     &earcrx,
>> +     &sm1_earcrx_cmdc_clk_sel,
>> +     &sm1_earcrx_cmdc_clk_div,
>> +     &sm1_earcrx_cmdc_clk,
>> +     &sm1_earcrx_dmac_clk_sel,
>> +     &sm1_earcrx_dmac_clk_div,
>> +     &sm1_earcrx_dmac_clk,
>> +};
>> +
>> +static struct clk_regmap *const s4_clk_pad_regmaps[] = {
>> +     &s4_tdm_mclk_pad_0,
>> +     &s4_tdm_mclk_pad_1,
>> +     &s4_tdm_mclk_pad_2,
>> +     &s4_tdm_lrclk_pad_0,
>> +     &s4_tdm_lrclk_pad_1,
>> +     &s4_tdm_lrclk_pad_2,
>> +     &s4_tdm_lrclk_pad_3,
>> +     &s4_tdm_lrclk_pad_4,
>> +     &s4_tdm_sclk_pad_0,
>> +     &s4_tdm_sclk_pad_1,
>> +     &s4_tdm_sclk_pad_2,
>> +     &s4_tdm_sclk_pad_3,
>> +     &s4_tdm_sclk_pad_4,
>> +     &s4_tdm_mclk_pad0_sel,
>> +     &s4_tdm_mclk_pad1_sel,
>> +     &s4_tdm_mclk_pad0_div,
>> +     &s4_tdm_mclk_pad1_div,
>> +     &s4_tdm_mclk_pad2_sel,
>> +     &s4_tdm_mclk_pad2_div,
>> +};
>> +
>>   struct axg_audio_reset_data {
>>        struct reset_controller_dev rstc;
>>        struct regmap *map;
>> @@ -1764,13 +2159,20 @@ static struct regmap_config axg_audio_regmap_cfg = {
>>
>>   struct audioclk_data {
>>        struct clk_regmap *const *regmap_clks;
>> +     struct clk_regmap *const *regmap_clks_pads;
>>        unsigned int regmap_clk_num;
>> +     unsigned int regmap_clk_pads_num;
>>        struct meson_clk_hw_data hw_clks;
>>        unsigned int reset_offset;
>>        unsigned int reset_num;
>>        unsigned int max_register;
>>   };
>>
>> +static int audio_clock_pad_is_new_regmap(struct device_node *np)
>> +{
>> +     return of_device_is_compatible(np, "amlogic,s4-audio-clkc");
>> +}
>> +
>>   static int axg_audio_clkc_probe(struct platform_device *pdev)
>>   {
>>        struct device *dev = &pdev->dev;
>> @@ -1812,6 +2214,25 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>>        for (i = 0; i < data->regmap_clk_num; i++)
>>                data->regmap_clks[i]->map = map;
>>
>> +     /* some amlogic chip clock pad reg domian is different */
>> +     if (audio_clock_pad_is_new_regmap(dev->of_node)) {
>> +             struct resource *res;
>> +             static const struct regmap_config aud_regmap_config = {
>> +                     .reg_bits = 32,
>> +                     .val_bits = 32,
>> +                     .reg_stride = 4,
>> +             };
>> +             regs = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
>> +             if (IS_ERR(regs))
>> +                     return PTR_ERR(regs);
>> +             aud_regmap_config.max_register = resource_size(res) - 4;
>> +             aud_regmap_config.name =
>> +                     devm_kasprintf(dev, GFP_KERNEL, "%s-%s", dev->of_node->name, "pads");
>> +             map = devm_regmap_init_mmio(dev, regs, &aud_regmap_config);
>> +             /* Populate clk pad regmap for the regmap backed clocks */
>> +             for (i = 0; i < data->regmap_clk_pads_num; i++)
>> +                     data->regmap_clks_pads[i]->map = map;
>> +     }
> This adds complexity for no good reason.
> Deal with pad clock in a distinct controller

this is a good idea, we only add a new clock pad distinct controller in 
dts, thanks

>
>
>>        /* Take care to skip the registered input clocks */
>>        for (i = AUD_CLKID_DDR_ARB; i < data->hw_clks.num; i++) {
>>                const char *name;
>> @@ -1822,7 +2243,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
>>                        continue;
>>
>>                name = hw->init->name;
>> -
>>                ret = devm_clk_hw_register(dev, hw);
>>                if (ret) {
>>                        dev_err(dev, "failed to register clock %s\n", name);
>> @@ -1886,6 +2306,20 @@ static const struct audioclk_data sm1_audioclk_data = {
>>        .max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
>>   };
>>
>> +static const struct audioclk_data s4_audioclk_data = {
>> +     .regmap_clks = s4_clk_regmaps,
>> +     .regmap_clk_num = ARRAY_SIZE(s4_clk_regmaps),
>> +     .regmap_clks_pads = s4_clk_pad_regmaps,
>> +     .regmap_clk_pads_num = ARRAY_SIZE(s4_clk_pad_regmaps),
>> +     .hw_clks = {
>> +             .hws = s4_audio_hw_clks,
>> +             .num = ARRAY_SIZE(s4_audio_hw_clks),
>> +     },
>> +     .reset_offset = AUDIO_SM1_SW_RESET0,
>> +     .reset_num = 39,
>> +     .max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
>> +};
>> +
>>   static const struct of_device_id clkc_match_table[] = {
>>        {
>>                .compatible = "amlogic,axg-audio-clkc",
>> @@ -1896,7 +2330,10 @@ static const struct of_device_id clkc_match_table[] = {
>>        }, {
>>                .compatible = "amlogic,sm1-audio-clkc",
>>                .data = &sm1_audioclk_data
>> -     }, {}
>> +     }, {
>> +             .compatible = "amlogic,s4-audio-clkc",
>> +             .data = &s4_audioclk_data
>> +     }, { }
>>   };
>>   MODULE_DEVICE_TABLE(of, clkc_match_table);
>>
>> diff --git a/drivers/clk/meson/axg-audio.h b/drivers/clk/meson/axg-audio.h
>> index 9e7765b630c96a8029140539ffda789b7db5277a..24233c40171034eba86c699db0200f07555926af 100644
>> --- a/drivers/clk/meson/axg-audio.h
>> +++ b/drivers/clk/meson/axg-audio.h
>> @@ -67,4 +67,10 @@
>>   #define AUDIO_EARCRX_CMDC_CLK_CTRL   0x0D0
>>   #define AUDIO_EARCRX_DMAC_CLK_CTRL   0x0D4
>>
>> +/* s4 clock pads use new reg base */
>> +#define AUDIO_S4_MCLK_PAD_CTRL0 0x0
>> +#define AUDIO_S4_MCLK_PAD_CTRL1 0x4
>> +#define AUDIO_S4_SCLK_PAD_CTRL0 0x8
>> +#define AUDIO_S4_SCLK_PAD_CTRL1 0xC
>> +
>>   #endif /*__AXG_AUDIO_CLKC_H */
> --
> Jerome


From maz at kernel.org  Thu Mar 20 02:10:59 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 20 Mar 2025 09:10:59 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
	<86msdhmemw.wl-maz@kernel.org>
	<cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
	<86ldt0n9w1.wl-maz@kernel.org>
	<Z9sSMJAlf7cQ5viu@linux.dev>
	<0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
Message-ID: <86iko4m5i4.wl-maz@kernel.org>

On Thu, 20 Mar 2025 06:03:35 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/20 3:51, Oliver Upton wrote:
> > On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
> >> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >>> What about setting the flag automatically when a user fails to pin
> >>> vCPUs to CPUs that are covered by one PMU? There would be no change if
> >>> a user correctly pins vCPUs as it is. Otherwise, they will see a
> >>> correct feature set advertised to the guest and the cycle counter
> >>> working.
> >> 
> >> How do you know that the affinity is "correct"? VCPU affinity can be
> >> changed at any time. I, for one, do not want my VMs to change
> >> behaviour because I let the vcpus bounce around as the scheduler sees
> >> fit.
> 
> Checking the affinity when picking the default PMU; the vCPU affinity
> is the only thing that rules the choice of the default PMU even now.
>
> Perhaps we may model the API as follows: introduce another "composite"
> PMU that works on any core but only exposes the cycle counter. Robust
> VMMs will choose it or one of hardware PMUs with
> KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according
> to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If
> the affinity is covered by one hardware PMU, that PMU will be chosen
> as the default. The "composite" PMU will be the default otherwise.

This makes no sense to me. A VCPU is always affine to a PMU, because
we do not support configurations where only some CPUs have a PMU. This
is an all-or-nothing situation.

More importantly, you keep suggesting the same "new default", and I
keep saying NO.

My position is clear: if you want a *new* behaviour, you *must* add a
new flag that the VMM explicitly provides to enable this CC-only PMU.
No change in default behaviour at all.

I'm not going to move from that.

	M.

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Thu Mar 20 02:19:02 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 20 Mar 2025 09:19:02 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <Z9sSMJAlf7cQ5viu@linux.dev>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
	<86msdhmemw.wl-maz@kernel.org>
	<cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
	<86ldt0n9w1.wl-maz@kernel.org>
	<Z9sSMJAlf7cQ5viu@linux.dev>
Message-ID: <86h63om54p.wl-maz@kernel.org>

On Wed, 19 Mar 2025 18:51:28 +0000,
Oliver Upton <oliver.upton at linux.dev> wrote:
> 
> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
> > On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> > > What about setting the flag automatically when a user fails to pin
> > > vCPUs to CPUs that are covered by one PMU? There would be no change if
> > > a user correctly pins vCPUs as it is. Otherwise, they will see a
> > > correct feature set advertised to the guest and the cycle counter
> > > working.
> > 
> > How do you know that the affinity is "correct"? VCPU affinity can be
> > changed at any time. I, for one, do not want my VMs to change
> > behaviour because I let the vcpus bounce around as the scheduler sees
> > fit.
> > 
> > Honestly, this is not a can of worm I want to open. We already have a
> > pretty terrible userspace API for the PMU, let's not add to the
> > confusion. *If* we are going down the road of presenting a dumbed-down
> > PMU to the guest, it has to be an explicit buy-in from userspace.
> 
> I also have a very strong distaste for the crappy UAPI we have around a
> 'default' PMU. At the same time I do recognize this hurts practical
> usecases since some VMMs can't be bothered to configure the vPMU / vCPU
> pinning correctly.
> 
> I'm at least willing to plug my nose and do the following:
> 
>  1) When the VMM does not specify a vPMU type:
> 
>    - We continue to present the 'default' PMU (including event counters)
>      to the VM
> 
>    - KVM ensures that the fixed CPU cycle counter works on any PMUv3
>      implementation in the system, even if it is different from the
>      default
> 
>    - Otherwise, event counters will only count on the default
>      implementation and will not count on different PMUs

I think this is confusing. The CC is counting, but nothing else, and
people using the cycle counters in conjunction with other events (a
very common use case) will not be able to correlate things correctly.
The current behaviour is, for all its sins, at least consistent.

> 
>  2) Implement your suggestion of a UAPI where the VMM can select a PMU
>     that only has the CPU cycle counter and works on any PMUv3
>     implementation.
> 
> Either way KVM will need to have some special case handling of the fixed
> CPU cycle counter. That'd allow users to actually run Windows *now* and
> provide a clear mechanism for userspace to present a less-broken vPMU if
> it cares.

Honestly, I don't care about one guest or another. My point is that if
we are changing the behaviour of the PMU to deal with this sort of
things, then it has to be a userspace buy-in.

	M.

-- 
Without deviation from the norm, progress is not possible.


From arnaud.pouliquen at foss.st.com  Thu Mar 20 02:21:26 2025
From: arnaud.pouliquen at foss.st.com (Arnaud POULIQUEN)
Date: Thu, 20 Mar 2025 10:21:26 +0100
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use
 of_reserved_mem_region_* functions for "memory-region"
In-Reply-To: <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
References: <20250317232426.952188-1-robh@kernel.org>
 <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>
 <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
Message-ID: <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>



On 3/20/25 00:04, Rob Herring wrote:
> On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
> <arnaud.pouliquen at foss.st.com> wrote:
>>
>> Hello Rob,
>>
>> On 3/18/25 00:24, Rob Herring (Arm) wrote:
>>> Use the newly added of_reserved_mem_region_to_resource() and
>>> of_reserved_mem_region_count() functions to handle "memory-region"
>>> properties.
>>>
>>> The error handling is a bit different in some cases. Often
>>> "memory-region" is optional, so failed lookup is not an error. But then
>>> an error in of_reserved_mem_lookup() is treated as an error. However,
>>> that distinction is not really important. Either the region is available
>>> and usable or it is not. So now, it is just
>>> of_reserved_mem_region_to_resource() which is checked for an error.
>>>
>>> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
>>> ---
>>> For v6.16
>>>
> 
> [...]
> 
>>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
>>> index b02b36a3f515..9d2bd8904c49 100644
>>> --- a/drivers/remoteproc/stm32_rproc.c
>>> +++ b/drivers/remoteproc/stm32_rproc.c
>>> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>>>  {
>>>       struct device *dev = rproc->dev.parent;
>>>       struct device_node *np = dev->of_node;
>>> -     struct of_phandle_iterator it;
>>>       struct rproc_mem_entry *mem;
>>> -     struct reserved_mem *rmem;
>>>       u64 da;
>>> -     int index = 0;
>>> +     int index = 0, mr = 0;
>>>
>>>       /* Register associated reserved memory regions */
>>> -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
>>> -     while (of_phandle_iterator_next(&it) == 0) {
>>> -             rmem = of_reserved_mem_lookup(it.node);
>>> -             if (!rmem) {
>>> -                     of_node_put(it.node);
>>> -                     dev_err(dev, "unable to acquire memory-region\n");
>>> -                     return -EINVAL;
>>> -             }
>>> +     while (1) {
>>> +             struct resource res;
>>> +             int ret;
>>> +
>>> +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
>>> +             if (ret)
>>> +                     return 0;
>>>
>>> -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
>>> -                     of_node_put(it.node);
>>> -                     dev_err(dev, "memory region not valid %pa\n",
>>> -                             &rmem->base);
>>> +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
>>> +                     dev_err(dev, "memory region not valid %pR\n", &res);
>>>                       return -EINVAL;
>>>               }
>>>
>>>               /*  No need to map vdev buffer */
>>> -             if (strcmp(it.node->name, "vdev0buffer")) {
>>> +             if (strcmp(res.name, "vdev0buffer")) {
>>
>> I tested your patches
> 
> Thank you.
> 
>> The update introduces a regression here. The strcmp function never returns 0.
>> Indeed, it.node->name stores the memory region label "vdev0buffer," while
>> res.name stores the memory region name "vdev0buffer at 10042000."
>>
>> Several remoteproc drivers may face the same issue as they embed similar code.
> 
> Indeed. I confused myself because node 'name' is without the
> unit-address, but this is using the full name. I've replaced the
> strcmp's with strstarts() to address this. I've updated my branch with
> the changes.

This is not enough as the remoteproc core function rproc_find_carveout_by_name()
also compares the memory names. With the following additional fix, it is working
on my STM32MP15-DK board.

@@ -309,11 +309,11 @@ rproc_find_carveout_by_name(struct rproc *rproc, const
char *name, ...)
 	vsnprintf(_name, sizeof(_name), name, args);
 	va_end(args);

 	list_for_each_entry(carveout, &rproc->carveouts, node) {
 		/* Compare carveout and requested names */
-		if (!strcmp(carveout->name, _name)) {
+		if (strstarts(carveout->name, _name)) {
 			mem = carveout;
 			break;
 		}
 	}

I just wonder if would not be more suitable to address this using the
"memory-region-names" field.

The drawback is that we would break compatibility with legacy boards...

I let Mathieu and Bjorn review and comment


Else with the fix in rproc_find_carveout_by_name(),

-for the stm32_rproc:
reviewed-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
tested-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>

- for the st_remoteproc
reviewed-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>

Thanks,
Arnaud


> 
> Rob


From sumit.garg at kernel.org  Thu Mar 20 02:25:35 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Thu, 20 Mar 2025 14:55:35 +0530
Subject: [PATCH v6 03/10] optee: account for direction while converting
 parameters
In-Reply-To: <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org>
 <Z9K2RQYuXSJc8Y1E@sumit-X1>
 <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com>
Message-ID: <Z9vfD4UWSrqSTPnP@sumit-X1>

Hi Jens,

On Mon, Mar 17, 2025 at 08:42:01AM +0100, Jens Wiklander wrote:
> Hi Sumit,
> 
> On Thu, Mar 13, 2025 at 11:41?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> >
> > Hi Jens,
> >
> > On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> > > The OP-TEE backend driver has two internal function pointers to convert
> > > between the subsystem type struct tee_param and the OP-TEE type struct
> > > optee_msg_param.
> > >
> > > The conversion is done from one of the types to the other, which is then
> > > involved in some operation and finally converted back to the original
> > > type. When converting to prepare the parameters for the operation, all
> > > fields must be taken into account, but then converting back, it's enough
> > > to update only out-values and out-sizes. So, an update_out parameter is
> > > added to the conversion functions to tell if all or only some fields
> > > must be copied.
> > >
> > > This is needed in a later patch where it might get confusing when
> > > converting back in from_msg_param() callback since an allocated
> > > restricted SHM can be using the sec_world_id of the used restricted
> > > memory pool and that doesn't translate back well.
> > >
> > > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > > ---
> > >  drivers/tee/optee/call.c          | 10 ++--
> > >  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
> > >  drivers/tee/optee/optee_private.h | 42 +++++++++++------
> > >  drivers/tee/optee/rpc.c           | 31 +++++++++----
> > >  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
> > >  5 files changed, 144 insertions(+), 58 deletions(-)
> > >
> > > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > > index 16eb953e14bb..f1533b894726 100644
> > > --- a/drivers/tee/optee/call.c
> > > +++ b/drivers/tee/optee/call.c
> > > @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
> > >       export_uuid(msg_arg->params[1].u.octets, &client_uuid);
> > >
> > >       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> > > -                                   arg->num_params, param);
> > > +                                   arg->num_params, param,
> > > +                                   false /*!update_out*/);
> > >       if (rc)
> > >               goto out;
> > >
> > > @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
> > >       }
> > >
> > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > -                                    msg_arg->params + 2)) {
> > > +                                    msg_arg->params + 2,
> > > +                                    true /*update_out*/)) {
> > >               arg->ret = TEEC_ERROR_COMMUNICATION;
> > >               arg->ret_origin = TEEC_ORIGIN_COMMS;
> > >               /* Close session again to avoid leakage */
> > > @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > >       msg_arg->cancel_id = arg->cancel_id;
> > >
> > >       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> > > -                                   param);
> > > +                                   param, false /*!update_out*/);
> > >       if (rc)
> > >               goto out;
> > >
> > > @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > >       }
> > >
> > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > -                                    msg_arg->params)) {
> > > +                                    msg_arg->params, true /*update_out*/)) {
> > >               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
> > >               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
> > >       }
> > > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > > index 4ca1d5161b82..e4b08cd195f3 100644
> > > --- a/drivers/tee/optee/ffa_abi.c
> > > +++ b/drivers/tee/optee/ffa_abi.c
> > > @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
> > >   */
> > >
> > >  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > -                                u32 attr, const struct optee_msg_param *mp)
> > > +                                u32 attr, const struct optee_msg_param *mp,
> > > +                                bool update_out)
> > >  {
> > >       struct tee_shm *shm = NULL;
> > >       u64 offs_high = 0;
> > >       u64 offs_low = 0;
> > >
> > > +     if (update_out) {
> > > +             if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> > > +                     return;
> > > +             goto out;
> > > +     }
> > > +
> > >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> > >                 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> > > -     p->u.memref.size = mp->u.fmem.size;
> > >
> > >       if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
> > >               shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> > > @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > >               offs_high = mp->u.fmem.offs_high;
> > >       }
> > >       p->u.memref.shm_offs = offs_low | offs_high << 32;
> > > +out:
> > > +     p->u.memref.size = mp->u.fmem.size;
> > >  }
> > >
> > >  /**
> > > @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > >   * @params:  subsystem internal parameter representation
> > >   * @num_params:      number of elements in the parameter arrays
> > >   * @msg_params:      OPTEE_MSG parameters
> > > + * @update_out: update parameter for output only
> > >   *
> > >   * Returns 0 on success or <0 on failure
> > >   */
> > >  static int optee_ffa_from_msg_param(struct optee *optee,
> > >                                   struct tee_param *params, size_t num_params,
> > > -                                 const struct optee_msg_param *msg_params)
> > > +                                 const struct optee_msg_param *msg_params,
> > > +                                 bool update_out)
> > >  {
> > >       size_t n;
> > >
> > > @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > >
> > >               switch (attr) {
> > >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > > +                     if (update_out)
> > > +                             break;
> > >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > >                       memset(&p->u, 0, sizeof(p->u));
> > >                       break;
> > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> > >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > > -                     optee_from_msg_param_value(p, attr, mp);
> > > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> > >                       break;
> > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
> > >               case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
> > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> > > -                     from_msg_param_ffa_mem(optee, p, attr, mp);
> > > +                     from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
> > >                       break;
> > >               default:
> > >                       return -EINVAL;
> > > @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > >  }
> > >
> > >  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > -                             const struct tee_param *p)
> > > +                             const struct tee_param *p, bool update_out)
> > >  {
> > >       struct tee_shm *shm = p->u.memref.shm;
> > >
> > > +     if (update_out) {
> > > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > > +                     return 0;
> > > +             goto out;
> > > +     }
> > > +
> > >       mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
> > >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> > >
> > > @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > >               memset(&mp->u, 0, sizeof(mp->u));
> > >               mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
> > >       }
> > > +out:
> > >       mp->u.fmem.size = p->u.memref.size;
> > >
> > >       return 0;
> > > @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > >   * @optee:   main service struct
> > >   * @msg_params:      OPTEE_MSG parameters
> > >   * @num_params:      number of elements in the parameter arrays
> > > - * @params:  subsystem itnernal parameter representation
> > > + * @params:  subsystem internal parameter representation
> > > + * @update_out: update parameter for output only
> > >   * Returns 0 on success or <0 on failure
> > >   */
> > >  static int optee_ffa_to_msg_param(struct optee *optee,
> > >                                 struct optee_msg_param *msg_params,
> > >                                 size_t num_params,
> > > -                               const struct tee_param *params)
> > > +                               const struct tee_param *params,
> > > +                               bool update_out)
> > >  {
> > >       size_t n;
> > >
> > > @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
> > >
> > >               switch (p->attr) {
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > +                     if (update_out)
> > > +                             break;
> > >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > >                       memset(&mp->u, 0, sizeof(mp->u));
> > >                       break;
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > -                     optee_to_msg_param_value(mp, p);
> > > +                     optee_to_msg_param_value(mp, p, update_out);
> > >                       break;
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > -                     if (to_msg_param_ffa_mem(mp, p))
> > > +                     if (to_msg_param_ffa_mem(mp, p, update_out))
> > >                               return -EINVAL;
> > >                       break;
> > >               default:
> >
> > Can we rather handle it as follows to improve code readability and
> > maintainence long term? Ditto for all other places.
> >
> > static int optee_ffa_to_msg_param(struct optee *optee,
> >                                   struct optee_msg_param *msg_params,
> >                                   size_t num_params,
> >                                   const struct tee_param *params,
> >                                   bool update_out)
> > {
> >         size_t n;
> >
> >         for (n = 0; n < num_params; n++) {
> >                 const struct tee_param *p = params + n;
> >                 struct optee_msg_param *mp = msg_params + n;
> >
> >                 if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
> >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
> >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
> >                     continue;
> 
> You're missing updating the length field for memrefs.
>

Do we need to update length field for input memrefs when update_out is
set? I don't see that happening in your existing patch too.

-Sumit

> Cheers,
> Jens
> 
> >
> >                 switch (p->attr) {
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> >                         mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> >                         memset(&mp->u, 0, sizeof(mp->u));
> >                         break;
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> >                         optee_to_msg_param_value(mp, p);
> >                         break;
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> >                         if (to_msg_param_ffa_mem(mp, p))
> >                                 return -EINVAL;
> >                         break;
> >                 default:
> >                         return -EINVAL;
> >                 }
> >         }
> >
> >         return 0;
> > }
> >
> > -Sumit


From krzk at kernel.org  Thu Mar 20 02:25:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 10:25:53 +0100
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <20250305053823.2048217-7-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
Message-ID: <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>

On 05/03/2025 06:38, Peter Chen wrote:
> Using this entry as the maintainers information for CIX SKY series SoCs.
> 
> Acked-by: Fugang Duan <fugang.duan at cixtech.com>
> Signed-off-by: Peter Chen <peter.chen at cixtech.com>
> ---
> Changes for v4
> - Add two dts files as maintained files
> 
>  MAINTAINERS | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index efee40ea589f..edf26cf11ee2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2354,6 +2354,16 @@ F:	arch/arm/boot/compressed/misc-ep93xx.h
>  F:	arch/arm/mach-ep93xx/
>  F:	drivers/iio/adc/ep93xx_adc.c
>  
> +ARM/CIX SKY ARM ARCHITECTURE
> +M:	Peter Chen <peter.chen at cixtech.com>
> +M:	Fugang Duan <fugang.duan at cixtech.com>
> +R:	CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
> +L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/arm/cix.yaml
> +F:	arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> +F:	arch/arm64/boot/dts/cix/sky1.dtsi

Instead:
arch/arm64/boot/dts/cix/

or if you think there will be more different architectures coming from
cix, which you will not maintain, then useful would be a "sky" subdirectory.

Best regards,
Krzysztof


From shameerali.kolothum.thodi at huawei.com  Thu Mar 20 02:30:45 2025
From: shameerali.kolothum.thodi at huawei.com (Shameerali Kolothum Thodi)
Date: Thu, 20 Mar 2025 09:30:45 +0000
Subject: [RFC PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Use KVM VMID for s2
 stage
In-Reply-To: <20250319233946.GF126678@ziepe.ca>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
 <20250319173202.78988-5-shameerali.kolothum.thodi@huawei.com>
 <20250319233946.GF126678@ziepe.ca>
Message-ID: <f654ae10e55e4142acb83eb926bb80b2@huawei.com>



> -----Original Message-----
> From: Jason Gunthorpe <jgg at ziepe.ca>
> Sent: Wednesday, March 19, 2025 11:40 PM
> To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi at huawei.com>
> Cc: kvmarm at lists.linux.dev; iommu at lists.linux.dev; linux-arm-
> kernel at lists.infradead.org; Linuxarm <linuxarm at huawei.com>;
> kevin.tian at intel.com; alex.williamson at redhat.com; maz at kernel.org;
> oliver.upton at linux.dev; will at kernel.org; robin.murphy at arm.com;
> nicolinc at nvidia.com; jean-philippe at linaro.org; Jonathan Cameron
> <jonathan.cameron at huawei.com>
> Subject: Re: [RFC PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Use KVM
> VMID for s2 stage
> 
> On Wed, Mar 19, 2025 at 05:32:01PM +0000, Shameer Kolothum wrote:
> > +static int arm_vsmmu_alloc_vmid(struct arm_smmu_device *smmu,
> struct kvm *kvm,
> > +				bool *kvm_used)
> > +{
> > +#ifdef CONFIG_KVM
> > +	/*
> > +	 * There can only be one allocator for VMIDs active at once. If BTM
> is
> > +	 * turned on then KVM's allocator always supplies the VMID, and
> the
> > +	 * VMID is matched by CPU invalidation of the KVM S2. Right now
> there
> > +	 * is no API to get an unused VMID from KVM so this also means
> BTM systems
> > +	 * cannot support S2 without an associated KVM.
> > +	 */
> > +	if ((smmu->features & ARM_SMMU_FEAT_BTM)) {
> > +		int vmid;
> > +
> > +		if (!kvm || !kvm_get_kvm_safe(kvm))
> > +			return -EOPNOTSUPP;
> 
> Isn't kvm_get_kvm_safe() in modular KVM code most of the time? You can't
> call it like this right?

I think it is safe since KVM is not modular for ARM64. And that is one of the
reasons I thought I will hold the KVM reference here as we don't have to go
through the symbol_get/put calls here. Also IOMMUFD is not using the kvm
pointer at the moment. Probably I should add some comments in IOMMUFD
to make it clear.

However I just realized that in patch #1 I should EXPORT the
kvm_arm_pinned_vmid_get/put functions as smmuv3 driver can be built
modular. 

> 
> Per my prior comments, I'm a little nervous to make drivers keep track
> of this refcount instead of the core code but this does seem like it
> could work..
> 
> I also think you should block using the S2 without a viommu & KVM in
> BTM mode.. Maybe like this:
> 
> @@ -2938,8 +2938,16 @@ static int arm_smmu_attach_dev(struct
> iommu_domain *domain, struct device *dev)
>                 cdptr = arm_smmu_alloc_cd_ptr(master, IOMMU_NO_PASID);
>                 if (!cdptr)
>                         return -ENOMEM;
> -       } else if (arm_smmu_ssids_in_use(&master->cd_table))
> -               return -EBUSY;
> +       } else {
> +               if (arm_smmu_ssids_in_use(&master->cd_table))
> +                       return -EBUSY;
> +               /*
> +                * S2 cannot be used when BTM is turned on without a VIOMMU
> and
> +                * VMID shared with KVM
> +                */
> +               if (smmu->features & ARM_SMMU_FEAT_BTM)
> +                       return -EOPNOTSUPP;
> +       }
> 
> That more closely matches how this will eventually work when the VMID
> allocation is properly made to be local to the viommu.

Ok. Will update.

Thanks,
Shameer


From eb at emlix.com  Thu Mar 20 02:19:12 2025
From: eb at emlix.com (Rolf Eike Beer)
Date: Thu, 20 Mar 2025 10:19:12 +0100
Subject: [PATCH 5/6] iommu: make inclusion of arm/arm-smmu-v3 directory conditional
In-Reply-To: <12652899.O9o76ZdvQC@devpool47.emlix.com>
References: <12652899.O9o76ZdvQC@devpool47.emlix.com>
Message-ID: <6164975.lOV4Wx5bFT@devpool47.emlix.com>

Nothing in there is active if CONFIG_ARM_SMMU_V3 is not enabled, so the whole
directory can depend on that switch as well.

Fixes: e86d1aa8b60f ("iommu/arm-smmu: Move Arm SMMU drivers into their own subdirectory")
Signed-off-by: Rolf Eike Beer <eb at emlix.com>
---
 drivers/iommu/arm/Makefile             | 3 ++-
 drivers/iommu/arm/arm-smmu-v3/Makefile | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/Makefile b/drivers/iommu/arm/Makefile
index 0f9efeab709f..35a7e13eef34 100644
--- a/drivers/iommu/arm/Makefile
+++ b/drivers/iommu/arm/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-y += arm-smmu/ arm-smmu-v3/
+obj-y += arm-smmu/
+obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3/
diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm-smmu-v3/Makefile
index 493a659cc66b..6cc7c8557b9e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
+obj-y += arm_smmu_v3.o
 arm_smmu_v3-y := arm-smmu-v3.o
 arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) += arm-smmu-v3-iommufd.o
 arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
-- 
2.49.0



-- 
Rolf Eike Beer

emlix GmbH
Headquarters: Berliner Str. 12, 37073 G?ttingen, Germany
Phone +49 (0)551 30664-0, e-mail info at emlix.com
District Court of G?ttingen, Registry Number HR B 3160
Managing Directors: Heike Jordan, Dr. Uwe Kracke
VAT ID No. DE 205 198 055
Office Berlin: Panoramastr. 1, 10178 Berlin, Germany
Office Bonn: Bachstr. 6, 53115 Bonn, Germany
http://www.emlix.com

emlix - your embedded Linux partner




From maz at kernel.org  Thu Mar 20 02:36:37 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 20 Mar 2025 09:36:37 +0000
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <20250305053823.2048217-6-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
	<20250305053823.2048217-6-peter.chen@cixtech.com>
Message-ID: <86frj8m4be.wl-maz@kernel.org>

On Wed, 05 Mar 2025 05:38:22 +0000,
Peter Chen <peter.chen at cixtech.com> wrote:
> 
> +	pmu-a520 {
> +		compatible = "arm,cortex-a520-pmu";
> +		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> +	};
> +
> +	pmu-a720 {
> +		compatible = "arm,cortex-a720-pmu";
> +		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> +	};
> +
> +	pmu-spe {
> +		compatible = "arm,statistical-profiling-extension-v1";
> +		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
> +	};

SPE should follow the same model as the PMU, as each CPU has its own
SPE implementation, exposing different micro-architectural details.

The rest looks OK.

	M.

-- 
Without deviation from the norm, progress is not possible.


From arnaud.pouliquen at foss.st.com  Thu Mar 20 02:37:13 2025
From: arnaud.pouliquen at foss.st.com (Arnaud POULIQUEN)
Date: Thu, 20 Mar 2025 10:37:13 +0100
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use
 of_reserved_mem_region_* functions for "memory-region"
In-Reply-To: <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>
References: <20250317232426.952188-1-robh@kernel.org>
 <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>
 <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
 <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>
Message-ID: <05adb008-c4f0-4003-aef4-6ce6dbbfd392@foss.st.com>



On 3/20/25 10:21, Arnaud POULIQUEN wrote:
> 
> 
> On 3/20/25 00:04, Rob Herring wrote:
>> On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
>> <arnaud.pouliquen at foss.st.com> wrote:
>>>
>>> Hello Rob,
>>>
>>> On 3/18/25 00:24, Rob Herring (Arm) wrote:
>>>> Use the newly added of_reserved_mem_region_to_resource() and
>>>> of_reserved_mem_region_count() functions to handle "memory-region"
>>>> properties.
>>>>
>>>> The error handling is a bit different in some cases. Often
>>>> "memory-region" is optional, so failed lookup is not an error. But then
>>>> an error in of_reserved_mem_lookup() is treated as an error. However,
>>>> that distinction is not really important. Either the region is available
>>>> and usable or it is not. So now, it is just
>>>> of_reserved_mem_region_to_resource() which is checked for an error.
>>>>
>>>> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
>>>> ---
>>>> For v6.16
>>>>
>>
>> [...]
>>
>>>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
>>>> index b02b36a3f515..9d2bd8904c49 100644
>>>> --- a/drivers/remoteproc/stm32_rproc.c
>>>> +++ b/drivers/remoteproc/stm32_rproc.c
>>>> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>>>>  {
>>>>       struct device *dev = rproc->dev.parent;
>>>>       struct device_node *np = dev->of_node;
>>>> -     struct of_phandle_iterator it;
>>>>       struct rproc_mem_entry *mem;
>>>> -     struct reserved_mem *rmem;
>>>>       u64 da;
>>>> -     int index = 0;
>>>> +     int index = 0, mr = 0;
>>>>
>>>>       /* Register associated reserved memory regions */
>>>> -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
>>>> -     while (of_phandle_iterator_next(&it) == 0) {
>>>> -             rmem = of_reserved_mem_lookup(it.node);
>>>> -             if (!rmem) {
>>>> -                     of_node_put(it.node);
>>>> -                     dev_err(dev, "unable to acquire memory-region\n");
>>>> -                     return -EINVAL;
>>>> -             }
>>>> +     while (1) {
>>>> +             struct resource res;
>>>> +             int ret;
>>>> +
>>>> +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
>>>> +             if (ret)
>>>> +                     return 0;
>>>>
>>>> -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
>>>> -                     of_node_put(it.node);
>>>> -                     dev_err(dev, "memory region not valid %pa\n",
>>>> -                             &rmem->base);
>>>> +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
>>>> +                     dev_err(dev, "memory region not valid %pR\n", &res);
>>>>                       return -EINVAL;
>>>>               }
>>>>
>>>>               /*  No need to map vdev buffer */
>>>> -             if (strcmp(it.node->name, "vdev0buffer")) {
>>>> +             if (strcmp(res.name, "vdev0buffer")) {
>>>
>>> I tested your patches
>>
>> Thank you.
>>
>>> The update introduces a regression here. The strcmp function never returns 0.
>>> Indeed, it.node->name stores the memory region label "vdev0buffer," while
>>> res.name stores the memory region name "vdev0buffer at 10042000."
>>>
>>> Several remoteproc drivers may face the same issue as they embed similar code.
>>
>> Indeed. I confused myself because node 'name' is without the
>> unit-address, but this is using the full name. I've replaced the
>> strcmp's with strstarts() to address this. I've updated my branch with
>> the changes.
> 
> This is not enough as the remoteproc core function rproc_find_carveout_by_name()
> also compares the memory names. With the following additional fix, it is working
> on my STM32MP15-DK board.
> 
> @@ -309,11 +309,11 @@ rproc_find_carveout_by_name(struct rproc *rproc, const
> char *name, ...)
>  	vsnprintf(_name, sizeof(_name), name, args);
>  	va_end(args);
> 
>  	list_for_each_entry(carveout, &rproc->carveouts, node) {
>  		/* Compare carveout and requested names */
> -		if (!strcmp(carveout->name, _name)) {
> +		if (strstarts(carveout->name, _name)) {
>  			mem = carveout;
>  			break;
>  		}
>  	}
> 
> I just wonder if would not be more suitable to address this using the
> "memory-region-names" field.
> 
> The drawback is that we would break compatibility with legacy boards...

Errata:
The drawback is that we would break compatibility with legacy DTs...

> 
> I let Mathieu and Bjorn review and comment
> 
> 
> Else with the fix in rproc_find_carveout_by_name(),
> 
> -for the stm32_rproc:
> reviewed-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
> tested-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
> 
> - for the st_remoteproc
> reviewed-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
> 
> Thanks,
> Arnaud
> 
> 
>>
>> Rob
> _______________________________________________
> Linux-stm32 mailing list
> Linux-stm32 at st-md-mailman.stormreply.com
> https://st-md-mailman.stormreply.com/mailman/listinfo/linux-stm32


From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 20 02:42:10 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 20 Mar 2025 17:42:10 +0800
Subject: [PATCH v5 3/3] arm64: dts: amlogic: Add A5 Reset Controller
In-Reply-To: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
References: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
Message-ID: <20250320-a4-a5-reset-v5-3-296f83bf733d@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add the device node and related header file for Amlogic
A5 reset controller.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Link: https://lore.kernel.org/r/20240918074211.8067-4-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h | 95 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi    |  8 +++
 2 files changed, 103 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdf0f515962097c606e4c53badb19df7d21606ec
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __DTS_AMLOGIC_A5_RESET_H
+#define __DTS_AMLOGIC_A5_RESET_H
+
+/* RESET0 */
+/*						0-3 */
+#define RESET_USB				4
+/*						5-7 */
+#define RESET_USBPHY20				8
+/*						9 */
+#define RESET_USB2DRD				10
+/*						11-31 */
+
+/* RESET1 */
+#define RESET_AUDIO				32
+#define RESET_AUDIO_VAD				33
+/*                                              34 */
+#define RESET_DDR_APB				35
+#define RESET_DDR				36
+/*						37-40 */
+#define RESET_DSPA_DEBUG			41
+/*                                              42 */
+#define RESET_DSPA				43
+/*						44-46 */
+#define RESET_NNA				47
+#define RESET_ETHERNET				48
+/*						49-63 */
+
+/* RESET2 */
+#define RESET_ABUS_ARB				64
+#define RESET_IRCTRL				65
+/*						66 */
+#define RESET_TS_PLL				67
+/*						68-72 */
+#define RESET_SPICC_0				73
+#define RESET_SPICC_1				74
+#define RESET_RSA				75
+
+/*						76-79 */
+#define RESET_MSR_CLK				80
+#define RESET_SPIFC				81
+#define RESET_SAR_ADC				82
+/*						83-90 */
+#define RESET_WATCHDOG				91
+/*						92-95 */
+
+/* RESET3 */
+/*						96-127 */
+
+/* RESET4 */
+#define RESET_RTC				128
+/*						129-131 */
+#define RESET_PWM_AB				132
+#define RESET_PWM_CD				133
+#define RESET_PWM_EF				134
+#define RESET_PWM_GH				135
+/*						104-105 */
+#define RESET_UART_A				138
+#define RESET_UART_B				139
+#define RESET_UART_C				140
+#define RESET_UART_D				141
+#define RESET_UART_E				142
+/*						143*/
+#define RESET_I2C_S_A				144
+#define RESET_I2C_M_A				145
+#define RESET_I2C_M_B				146
+#define RESET_I2C_M_C				147
+#define RESET_I2C_M_D				148
+/*						149-151 */
+#define RESET_SDEMMC_A				152
+/*						153 */
+#define RESET_SDEMMC_C				154
+/*						155-159*/
+
+/* RESET5 */
+/*						160-175 */
+#define RESET_BRG_AO_NIC_SYS			176
+#define RESET_BRG_AO_NIC_DSPA			177
+#define RESET_BRG_AO_NIC_MAIN			178
+#define RESET_BRG_AO_NIC_AUDIO			179
+/*						180-183 */
+#define RESET_BRG_AO_NIC_ALL			184
+#define RESET_BRG_NIC_NNA			185
+#define RESET_BRG_NIC_SDIO			186
+#define RESET_BRG_NIC_EMMC			187
+#define RESET_BRG_NIC_DSU			188
+#define RESET_BRG_NIC_SYSCLK			189
+#define RESET_BRG_NIC_MAIN			190
+#define RESET_BRG_NIC_ALL			191
+
+#endif
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 32ed1776891bc7d1befd01a76c76048631606f5a..b1da8cbaa25a1844312a23bc39eb876df3c60df5 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include "amlogic-a4-common.dtsi"
+#include "amlogic-a5-reset.h"
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
 / {
 	cpus {
@@ -50,6 +51,13 @@ pwrc: power-controller {
 };
 
 &apb {
+	reset: reset-controller at 2000 {
+		compatible = "amlogic,a5-reset",
+			     "amlogic,meson-s4-reset";
+		reg = <0x0 0x2000 0x0 0x98>;
+		#reset-cells = <1>;
+	};
+
 	gpio_intc: interrupt-controller at 4080 {
 		compatible = "amlogic,a5-gpio-intc",
 			     "amlogic,meson-gpio-intc";

-- 
2.37.1




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 20 02:42:09 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 20 Mar 2025 17:42:09 +0800
Subject: [PATCH v5 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
References: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
Message-ID: <20250320-a4-a5-reset-v5-2-296f83bf733d@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add the device node and related header file for Amlogic
A4 reset controller.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Link: https://lore.kernel.org/r/20240918074211.8067-3-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h | 93 ++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi    |  8 +++
 2 files changed, 101 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6a4c90bab3cf7cfaa3c98c522bed5e455b73bd3
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __DTS_AMLOGIC_A4_RESET_H
+#define __DTS_AMLOGIC_A4_RESET_H
+
+/* RESET0 */
+/*						0-3 */
+#define RESET_USB				4
+/*						5-6*/
+#define RESET_U2PHY22				7
+#define RESET_USBPHY20				8
+#define RESET_U2PHY21				9
+#define RESET_USB2DRD				10
+#define RESET_U2H				11
+#define RESET_LED_CTRL				12
+/*						13-31 */
+
+/* RESET1 */
+#define RESET_AUDIO				32
+#define RESET_AUDIO_VAD				33
+/*						34*/
+#define RESET_DDR_APB				35
+#define RESET_DDR				36
+#define RESET_VOUT_VENC				37
+#define RESET_VOUT				38
+/*						39-47 */
+#define RESET_ETHERNET				48
+/*						49-63 */
+
+/* RESET2 */
+#define RESET_DEVICE_MMC_ARB			64
+#define RESET_IRCTRL				65
+/*						66*/
+#define RESET_TS_PLL				67
+/*						68-72*/
+#define RESET_SPICC_0				73
+#define RESET_SPICC_1				74
+/*						75-79*/
+#define RESET_MSR_CLK				80
+/*						81*/
+#define RESET_SAR_ADC				82
+/*						83-87*/
+#define RESET_ACODEC				88
+/*						89-90*/
+#define RESET_WATCHDOG				91
+/*						92-95*/
+
+/* RESET3 */
+/*						96-127 */
+
+/* RESET4 */
+/*						128-131 */
+#define RESET_PWM_AB				132
+#define RESET_PWM_CD				133
+#define RESET_PWM_EF				134
+#define RESET_PWM_GH				135
+/*						136-137*/
+#define RESET_UART_A				138
+#define RESET_UART_B				139
+/*						140*/
+#define RESET_UART_D				141
+#define RESET_UART_E				142
+/*						143-144*/
+#define RESET_I2C_M_A				145
+#define RESET_I2C_M_B				146
+#define RESET_I2C_M_C				147
+#define RESET_I2C_M_D				148
+/*						149-151*/
+#define RESET_SDEMMC_A				152
+/*						153*/
+#define RESET_SDEMMC_C				154
+/*						155-159*/
+
+/* RESET5 */
+/*						160-175*/
+#define RESET_BRG_AO_NIC_SYS			176
+/*						177*/
+#define RESET_BRG_AO_NIC_MAIN			178
+#define RESET_BRG_AO_NIC_AUDIO			179
+/*						180-183*/
+#define RESET_BRG_AO_NIC_ALL			184
+/*						185*/
+#define RESET_BRG_NIC_SDIO			186
+#define RESET_BRG_NIC_EMMC			187
+#define RESET_BRG_NIC_DSU			188
+#define RESET_BRG_NIC_CLK81			189
+#define RESET_BRG_NIC_MAIN			190
+#define RESET_BRG_NIC_ALL			191
+
+#endif
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index fa80fa365f13c4a93f5577f78bf2b3369cb91cb8..6537153b3026af1bf9d1df0a196619b716553cde 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include "amlogic-a4-common.dtsi"
+#include "amlogic-a4-reset.h"
 #include <dt-bindings/power/amlogic,a4-pwrc.h>
 #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 / {
@@ -51,6 +52,13 @@ pwrc: power-controller {
 };
 
 &apb {
+	reset: reset-controller at 2000 {
+		compatible = "amlogic,a4-reset",
+			     "amlogic,meson-s4-reset";
+		reg = <0x0 0x2000 0x0 0x98>;
+		#reset-cells = <1>;
+	};
+
 	gpio_intc: interrupt-controller at 4080 {
 		compatible = "amlogic,a4-gpio-intc",
 			     "amlogic,meson-gpio-intc";

-- 
2.37.1




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 20 02:42:08 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 20 Mar 2025 17:42:08 +0800
Subject: [PATCH v5 1/3] dt-bindings: reset: Add compatible for Amlogic
 A4/A5 Reset Controller
In-Reply-To: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
References: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
Message-ID: <20250320-a4-a5-reset-v5-1-296f83bf733d@amlogic.com>

From: Zelong Dong <zelong.dong at amlogic.com>

Add compatibles for Amlogic A4 and A5 reset controllers,
which fall back to 'amlogic,meson-s4-reset'.

Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
Acked-by: Conor Dooley <conor.dooley at microchip.com>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
Link: https://lore.kernel.org/r/20240918074211.8067-2-zelong.dong at amlogic.com
Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
---
 .../bindings/reset/amlogic,meson-reset.yaml        | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
index 695ef38a7bb346c92b4cf428e7615d45682c940a..150e95c0d9bed74c7045942610a311114a257889 100644
--- a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
@@ -12,14 +12,20 @@ maintainers:
 
 properties:
   compatible:
-    enum:
-      - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
-      - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
-      - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
-      - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
-      - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
-      - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
-      - amlogic,t7-reset
+    oneOf:
+      - enum:
+          - amlogic,meson8b-reset # Reset Controller on Meson8b and compatible SoCs
+          - amlogic,meson-gxbb-reset # Reset Controller on GXBB and compatible SoCs
+          - amlogic,meson-axg-reset # Reset Controller on AXG and compatible SoCs
+          - amlogic,meson-a1-reset # Reset Controller on A1 and compatible SoCs
+          - amlogic,meson-s4-reset # Reset Controller on S4 and compatible SoCs
+          - amlogic,c3-reset # Reset Controller on C3 and compatible SoCs
+          - amlogic,t7-reset
+      - items:
+          - enum:
+              - amlogic,a4-reset
+              - amlogic,a5-reset
+          - const: amlogic,meson-s4-reset
 
   reg:
     maxItems: 1

-- 
2.37.1




From devnull+kelvin.zhang.amlogic.com at kernel.org  Thu Mar 20 02:42:07 2025
From: devnull+kelvin.zhang.amlogic.com at kernel.org (Kelvin Zhang via B4 Relay)
Date: Thu, 20 Mar 2025 17:42:07 +0800
Subject: [PATCH v5 0/3] Add support for Amlogic A4/A5 Reset
Message-ID: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>

Add dt-binding compatibles and device nodes for Amlogic A4/A5 reset.

Imported from f20240918074211.8067-1-zelong.dong at amlogic.com

Changes in v5:
- Rebasing on top of the latest upstream changes.
- Link to v4: https://lore.kernel.org/r/20250313-a4-a5-reset-v4-0-8076f684d6cf at amlogic.com

Changes in v4:
- Remove the superfluous 'items' in the dt-binding.
- Rebasing due to recent upstream changes.
- Link to v3: https://lore.kernel.org/all/20240918074211.8067-1-zelong.dong at amlogic.com/

Changes in v3:
- rebase on 'amlogic,t7-reset' patchset
- Link to v2: https://lore.kernel.org/all/20240715051217.5286-1-zelong.dong at amlogic.com/

Changes in v2:
- remove 'amlogic,t7-reset'
- move 'amlogic,c3-reset' to the other enum list
- move reset node from amlogic-a4-common.dtsi to
  amlogic-a4.dtsi/amlogic-a5.dtsi
- Link to v1: https://lore.kernel.org/all/20240703061610.37217-1-zelong.dong at amlogic.com/

---
Zelong Dong (3):
  dt-bindings: reset: Add compatible for Amlogic A4/A5 Reset Controller
  arm64: dts: amlogic: Add Amlogic A4 reset controller
  arm64: dts: amlogic: Add Amlogic A5 reset controller

 .../bindings/reset/amlogic,meson-reset.yaml   | 23 +++--
 .../arm64/boot/dts/amlogic/amlogic-a4-reset.h | 93 ++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi   | 10 ++
 .../arm64/boot/dts/amlogic/amlogic-a5-reset.h | 95 +++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi   | 10 ++
 5 files changed, 223 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
 create mode 100644 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h

--
2.35.1

---
Zelong Dong (3):
      dt-bindings: reset: Add compatible for Amlogic A4/A5 Reset Controller
      arm64: dts: amlogic: Add A4 Reset Controller
      arm64: dts: amlogic: Add A5 Reset Controller

 .../bindings/reset/amlogic,meson-reset.yaml        | 22 +++--
 arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h     | 93 +++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  8 ++
 arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h     | 95 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  8 ++
 5 files changed, 218 insertions(+), 8 deletions(-)
---
base-commit: ff7f9b199e3f4cc7d61df5a9a26a7cbb5c1492e6
change-id: 20250313-a4-a5-reset-6696e5b18e10

Best regards,
-- 
Kelvin Zhang <kelvin.zhang at amlogic.com>




From andy.shevchenko at gmail.com  Thu Mar 20 02:45:28 2025
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Thu, 20 Mar 2025 11:45:28 +0200
Subject: [PATCH v2 0/5] pinctrl: nuvoton: A few cleanups and a fix
In-Reply-To: <CACRpkdbTKytFgdqyDajpcfENagSXPZhG5hbpQiGF23VHqLd9_A@mail.gmail.com>
References: <20250318105932.2090926-1-andriy.shevchenko@linux.intel.com> <CACRpkdbTKytFgdqyDajpcfENagSXPZhG5hbpQiGF23VHqLd9_A@mail.gmail.com>
Message-ID: <CAHp75Ve_cF=zdZuZxSO6H1FXrCbAc1EXyHhCWw8K3Tc_Q2p8tA@mail.gmail.com>

On Thu, Mar 20, 2025 at 10:15?AM Linus Walleij <linus.walleij at linaro.org> wrote:
> On Tue, Mar 18, 2025 at 11:59?AM Andy Shevchenko
> <andriy.shevchenko at linux.intel.com> wrote:

> > Convert Nuvoton drivers to use pin control provided data types
> > and more of device property APIs.
> >
> > While doing that, fix one non-critical issue that sparse complains about.
> >
> > Compile tested only.
>
> Patches LGTM and we are close to the merge window so I have
> just applied them.
>
> If there are any issues we can surely fix it up in -next.
>
> Thanks Andy!

Thank you!


-- 
With Best Regards,
Andy Shevchenko


From akihiko.odaki at daynix.com  Thu Mar 20 02:52:59 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Thu, 20 Mar 2025 18:52:59 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86iko4m5i4.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
 <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
 <86ldt0n9w1.wl-maz@kernel.org> <Z9sSMJAlf7cQ5viu@linux.dev>
 <0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
 <86iko4m5i4.wl-maz@kernel.org>
Message-ID: <ba9cd6d2-1ee5-478a-8102-42b4dac411ce@daynix.com>

On 2025/03/20 18:10, Marc Zyngier wrote:
> On Thu, 20 Mar 2025 06:03:35 +0000,
> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>
>> On 2025/03/20 3:51, Oliver Upton wrote:
>>> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
>>>> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>>>> What about setting the flag automatically when a user fails to pin
>>>>> vCPUs to CPUs that are covered by one PMU? There would be no change if
>>>>> a user correctly pins vCPUs as it is. Otherwise, they will see a
>>>>> correct feature set advertised to the guest and the cycle counter
>>>>> working.
>>>>
>>>> How do you know that the affinity is "correct"? VCPU affinity can be
>>>> changed at any time. I, for one, do not want my VMs to change
>>>> behaviour because I let the vcpus bounce around as the scheduler sees
>>>> fit.
>>
>> Checking the affinity when picking the default PMU; the vCPU affinity
>> is the only thing that rules the choice of the default PMU even now.
>>
>> Perhaps we may model the API as follows: introduce another "composite"
>> PMU that works on any core but only exposes the cycle counter. Robust
>> VMMs will choose it or one of hardware PMUs with
>> KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according
>> to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If
>> the affinity is covered by one hardware PMU, that PMU will be chosen
>> as the default. The "composite" PMU will be the default otherwise.
> 
> This makes no sense to me. A VCPU is always affine to a PMU, because
> we do not support configurations where only some CPUs have a PMU. This
> is an all-or-nothing situation.

At least isn't it fine to have the composite PMU with a new value for 
KVM_ARM_VCPU_PMU_V3_SET_PMU?

> 
> More importantly, you keep suggesting the same "new default", and I
> keep saying NO.
> 
> My position is clear: if you want a *new* behaviour, you *must* add a
> new flag that the VMM explicitly provides to enable this CC-only PMU.
> No change in default behaviour at all.
> 
> I'm not going to move from that.

Why not? It will not break anything guaranteed to work in the past.

Currently KVM only guarantees that the emulated PMU correctly counts 
only when
1) the vCPU affinity is contained by one PMU and
2) it will not expand

Breaking these conditions will make the behavior of the emulated PMU 
undefined. Now I'm proposing to remove 1).

Regards,
Akihiko Odaki

> 
> 	M.
> 



From wthai at nvidia.com  Thu Mar 20 02:54:48 2025
From: wthai at nvidia.com (Willie Thai)
Date: Thu, 20 Mar 2025 09:54:48 +0000
Subject: [PATCH] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <66608647-0ac8-44ad-b1af-f9bd0e120696@molgen.mpg.de>
References: <66608647-0ac8-44ad-b1af-f9bd0e120696@molgen.mpg.de>
Message-ID: <20250320095448.55851-1-wthai@nvidia.com>

Dear  Paul,

Sorry I respond to your feedback late.

> Dear Willie,
> 
> 
> Thank you for the patch.
> 
> Am 24.01.25 um 06:18 schrieb Willie Thai:
>> From: wthai <wthai at willie-obmc-builder.nvidia.com>
> 
> Please use your full name.
> 
>      $ git config --global user.name "Willie Thai"
>      $ git commit --amend --author="Willie Thai <wthai at nvidia.com>"
> 
> Also is this the wanted email address?
> 
>> The GB200NVL BMC is an Aspeed Ast2600 based BMC
> 
> AST [1]
> 
> [1]: https://www.aspeedtech.com/server_ast2600/
> 
>> for Nvidia Blackwell GB200NVL platform.
> 
> If possible, please add reference to datasheets.
> 
>> Signed-off-by: wthai <wthai at nvidia.com>
> 
> Ditto, regarding the name.
> 
>> ---
>>   .../bindings/arm/aspeed/aspeed.yaml           |    1 +
>>   arch/arm/boot/dts/aspeed/Makefile             |    1 +
>>   .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1352 +++++++++++++++++
>>   3 files changed, 1354 insertions(+)
>>   create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> 
>> diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> index 2f92b8ab08fa..0a6f3654dcb5 100644
>> --- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> +++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> @@ -96,6 +96,7 @@ properties:
>>                 - inventec,starscream-bmc
>>                 - inventec,transformer-bmc
>>                 - jabil,rbp-bmc
>> +              - nvidia,gb200nvl-bmc
>>                 - qcom,dc-scm-v1-bmc
>>                 - quanta,s6q-bmc
>>                 - ufispace,ncplite-bmc
>> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
>> index c4f064e4b073..0dc5240866f3 100644
>> --- a/arch/arm/boot/dts/aspeed/Makefile
>> +++ b/arch/arm/boot/dts/aspeed/Makefile
>> @@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>>   	aspeed-bmc-lenovo-hr630.dtb \
>>   	aspeed-bmc-lenovo-hr855xg2.dtb \
>>   	aspeed-bmc-microsoft-olympus.dtb \
>> +	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
>>   	aspeed-bmc-opp-lanyang.dtb \
>>   	aspeed-bmc-opp-mowgli.dtb \
>>   	aspeed-bmc-opp-nicole.dtb \
>> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> new file mode 100644
>> index 000000000000..91d025229aba
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
>> @@ -0,0 +1,1352 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/dts-v1/;
>> +
>> +#include "aspeed-g6.dtsi"
>> +#include <dt-bindings/gpio/aspeed-gpio.h>
>> +#include <dt-bindings/leds/common.h>
>> +
>> +&gpio0 {
>> +	gpio-line-names =
>> +
>> +	/* gpio-line-names are the combination of <signal>-<I/O> , "" is the placeholder for the unused pins
>> +	*/
>> +
>> +	/* 208 (26*8) 3.3V GPIOs */
>> +
>> +	/*A0-A7*/
>> +	"", "", "", "", "", "", "", "",
> 
> Other files seem to put it in one line.

Mostly, we can put all the definitions in one line, but some will exceed the line length limit.
That will create a warning in checkpatch.pl, I will try to put them in one line except those exceed the length limit.

> 
>> +
>> +	/*B0-B7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*C0-C7*/
>> +	"SGPIO_I2C_MUX_SEL-O",
>> +	"", "", "", "", "", "", "",
>> +
>> +	/*D0-D7*/
>> +	"", "", "",
>> +	"UART1_MUX_SEL-O",
>> +	"",
>> +	"FPGA_PEX_RST_L-O",
>> +	"", "",
>> +
>> +	/*E0-E7*/
>> +	"RTL8221_PHY_RST_L-O",
>> +	"RTL8211_PHY_INT_L-I",
>> +	"",
>> +	"UART3_MUX_SEL-O",
>> +	"", "", "",
>> +	"SGPIO_BMC_EN-O",
>> +
>> +	/*F0-F7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*G0-G7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*H0-H7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*I0-I7*/
>> +	"", "", "", "", "",
>> +	"QSPI2_RST_L-O",
>> +	"GLOBAL_WP_BMC-O",
>> +	"BMC_DDR4_TEN-O",
>> +
>> +	/*J0-J7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*K0-K7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*L0-L7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*M0-M7*/
>> +	"PCIE_EP_RST_EN-O",
>> +	"BMC_FRU_WP-O",
>> +	"HMC_RESET_L-O",
>> +	"STBY_POWER_EN-O",
>> +	"STBY_POWER_PG-I",
>> +	"PCIE_EP_RST_L-O",
>> +	"", "",
>> +
>> +	/*N0-N7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*O0-O7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*P0-P7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*Q0-Q7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*R0-R7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*S0-S7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*T0-T7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*U0-U7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*V0-V7*/
>> +	"AP_EROT_REQ-O",
>> +	"EROT_AP_GNT-I",
>> +	"",
>> +	"",
>> +	"PCB_TEMP_ALERT-I",
>> +	"", "", "",
>> +
>> +	/*W0-W7*/
>> +	"", "", "", "", "", "", "", "",
>> +
>> +	/*X0-X7*/
>> +	"", "",
>> +	"TPM_MUX_SEL-O",
>> +	"", "", "", "", "",
>> +
>> +	/*Y0-Y7*/
>> +	"", "", "",
>> +	"EMMC_RST-O",
>> +	"","", "", "",
>> +
>> +	/*Z0-Z7*/
>> +	"BMC_READY-O",
>> +	"", "", "", "", "", "", "";
>> +};
>> +
>> +&sgpiom0 {
>> +	status="okay";
>> +	ngpios = <128>;
>> +
>> +	gpio-line-names =
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"RUN_POWER_FAULT_L-I",
>> +	"SYS_RST_IN_L-O",
>> +	"RUN_POWER_PG-I",
>> +	"PWR_BRAKE_L-O",
>> +	"SYS_RST_OUT_L-I",
>> +	"RUN_POWER_EN-O",
>> +	"L0L1_RST_REQ_OUT_L-I",
>> +	"SHDN_FORCE_L-O",
>> +	"L2_RST_REQ_OUT_L-I",
>> +	"SHDN_REQ_L-O",
>> +	"SHDN_OK_L-I",
>> +	"UID_LED_N-O",
>> +	"BMC_I2C1_FPGA_ALERT_L-I",
>> +	"SYS_FAULT_LED_N-O",
>> +	"BMC_I2C0_FPGA_ALERT_L-I",
>> +	"PWR_LED_N-O",
>> +	"FPGA_RSVD_FFU3-I",
>> +	"",
>> +	"FPGA_RSVD_FFU2-I",
>> +	"",
>> +	"FPGA_RSVD_FFU1-I",
>> +	"",
>> +	"FPGA_RSVD_FFU0-I",
>> +	"BMC_I2C_SSIF_ALERT_L-O",
>> +	"CPU_BOOT_DONE-I",
>> +	"JTAG_MUX_SELECT-O",
>> +	"SPI_BMC_FPGA_INT_L-I",
>> +	"RTC_CLR_L-O",
>> +	"THERM_BB_WARN_L-I",
>> +	"UART_MUX_SEL-O",
>> +	"THERM_BB_OVERT_L-I",
>> +	"",
>> +	"CPU0_UPHY3_PRSNT1_L-I",
>> +	"IOBRD0_RUN_POWER_EN-O",
>> +	"CPU0_UPHY3_PRSNT0_L-I",
>> +	"IOBRD1_RUN_POWER_EN-O",
>> +	"CPU0_UPHY2_PRSNT1_L-I",
>> +	"FPGA_RSVD_FFU4-O",
>> +	"CPU0_UPHY2_PRSNT0_L-I",
>> +	"FPGA_RSVD_FFU5-O",
>> +	"CPU0_UPHY1_PRSNT1_L-I",
>> +	"FPGA_RSVD_FFU6-O",
>> +	"CPU0_UPHY1_PRSNT0_L-I",
>> +	"FPGA_RSVD_FFU7-O",
>> +	"CPU0_UPHY0_PRSNT1_L-I",
>> +	"RSVD_NV_PLT_DETECT-O",
>> +	"CPU0_UPHY0_PRSNT0_L-I",
>> +	"SPI1_INT_L-O",
>> +	"CPU1_UPHY3_PRSNT1_L-I",
>> +	"",
>> +	"CPU1_UPHY3_PRSNT0_L-I",
>> +	"HMC_EROT_MUX_STATUS",
>> +	"CPU1_UPHY2_PRSNT1_L-I",
>> +	"",
>> +	"CPU1_UPHY2_PRSNT0_L-I",
>> +	"",
>> +	"CPU1_UPHY1_PRSNT1_L-I",
>> +	"",
>> +	"CPU1_UPHY1_PRSNT0_L-I",
>> +	"",
>> +	"CPU1_UPHY0_PRSNT1_L-I",
>> +	"",
>> +	"CPU1_UPHY0_PRSNT0_L-I",
>> +	"",
>> +	"FAN1_PRESENT_L-I",
>> +	"",
>> +	"FAN0_PRESENT_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"IPEX_CABLE_PRSNT_L-I",
>> +	"",
>> +	"M2_1_PRSNT_L-I",
>> +	"",
>> +	"M2_0_PRSNT_L-I",
>> +	"",
>> +	"CPU1_UPHY4_PRSNT1_L-I",
>> +	"",
>> +	"CPU0_UPHY4_PRSNT0_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"I2C_RTC_ALERT_L-I",
>> +	"",
>> +	"FAN7_PRESENT_L-I",
>> +	"",
>> +	"FAN6_PRESENT_L-I",
>> +	"",
>> +	"FAN5_PRESENT_L-I",
>> +	"",
>> +	"FAN4_PRESENT_L-I",
>> +	"",
>> +	"FAN3_PRESENT_L-I",
>> +	"",
>> +	"FAN2_PRESENT_L-I",
>> +	"",
>> +	"IOBRD0_IOX_INT_L-I",
>> +	"",
>> +	"IOBRD1_PRSNT_L-I",
>> +	"",
>> +	"IOBRD0_PRSNT_L-I",
>> +	"",
>> +	"IOBRD1_PWR_GOOD-I",
>> +	"",
>> +	"IOBRD0_PWR_GOOD-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"FAN_FAIL_IN_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"PDB_CABLE_PRESENT_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"CHASSIS_PWR_BRK_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"IOBRD1_IOX_INT_L-I",
>> +	"",
>> +	"10GBE_SMBALRT_L-I",
>> +	"",
>> +	"PCIE_WAKE_L-I",
>> +	"",
>> +	"I2C_M21_ALERT_L-I",
>> +	"",
>> +	"I2C_M20_ALERT_L-I",
>> +	"",
>> +	"TRAY_FAST_SHDN_L-I",
>> +	"",
>> +	"UID_BTN_N-I",
>> +	"",
>> +	"PWR_BTN_L-I",
>> +	"",
>> +	"PSU_SMB_ALERT_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"NODE_LOC_ID[0]-I",
>> +	"",
>> +	"NODE_LOC_ID[1]-I",
>> +	"",
>> +	"NODE_LOC_ID[2]-I",
>> +	"",
>> +	"NODE_LOC_ID[3]-I",
>> +	"",
>> +	"NODE_LOC_ID[4]-I",
>> +	"",
>> +	"NODE_LOC_ID[5]-I",
>> +	"",
>> +	"FAN10_PRESENT_L-I",
>> +	"",
>> +	"FAN9_PRESENT_L-I",
>> +	"",
>> +	"FAN8_PRESENT_L-I",
>> +	"",
>> +	"FPGA1_READY_HMC-I",
>> +	"",
>> +	"DP_HPD-I",
>> +	"",
>> +	"HMC_I2C3_FPGA_ALERT_L-I",
>> +	"",
>> +	"HMC_I2C2_FPGA_ALERT_L-I",
>> +	"",
>> +	"FPGA0_READY_HMC-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"LEAK_DETECT_ALERT_L-I",
>> +	"",
>> +	"MOD1_B2B_CABLE_PRESENT_L-I",
>> +	"",
>> +	"MOD1_CLINK_CABLE_PRESENT_L-I",
>> +	"",
>> +	"FAN11_PRESENT_L-I",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"RSVD_SGPIO_IN_CRC[0]",
>> +	"RSVD_SGPIO_O_CRC[7]",
>> +	"RSVD_SGPIO_IN_CRC[1]",
>> +	"RSVD_SGPIO_O_CRC[6]",
>> +	"RSVD_SGPIO_IN_CRC[2]",
>> +	"RSVD_SGPIO_O_CRC[5]",
>> +	"RSVD_SGPIO_IN_CRC[3]",
>> +	"RSVD_SGPIO_O_CRC[4]",
>> +	"RSVD_SGPIO_IN_CRC[4]",
>> +	"RSVD_SGPIO_O_CRC[3]",
>> +	"RSVD_SGPIO_IN_CRC[5]",
>> +	"RSVD_SGPIO_O_CRC[2]",
>> +	"RSVD_SGPIO_IN_CRC[6]",
>> +	"RSVD_SGPIO_O_CRC[1]",
>> +	"RSVD_SGPIO_IN_CRC[7]",
>> +	"RSVD_SGPIO_O_CRC[0]";
>> +};
>> +
>> +// EMMC group that excludes WP pin
>> +&pinctrl {
>> +	pinctrl_emmcg5_default: emmcg5_default {
>> +		function = "EMMC";
>> +		groups = "EMMCG5";
>> +	};
>> +};
>> +
>> +/ {
>> +	model = "AST2600 GB200NVL BMC";
>> +	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";
>> +
>> +	aliases {
>> +		serial2 = &uart3;
>> +		serial4 = &uart5;
>> +		i2c16   = &imux16;
>> +		i2c17   = &imux17;
>> +		i2c18   = &imux18;
>> +		i2c19   = &imux19;
>> +		i2c20   = &imux20;
>> +		i2c21   = &imux21;
>> +		i2c22   = &imux22;
>> +		i2c23   = &imux23;
>> +		i2c24   = &imux24;
>> +		i2c25   = &imux25;
>> +		i2c26   = &imux26;
>> +		i2c27   = &imux27;
>> +		i2c28   = &imux28;
>> +		i2c29   = &imux29;
>> +		i2c30   = &imux30;
>> +		i2c31   = &imux31;
>> +		i2c32   = &imux32;
>> +		i2c33   = &imux33;
>> +		i2c34   = &imux34;
>> +		i2c35   = &imux35;
>> +		i2c36   = &imux36;
>> +		i2c37   = &imux37;
>> +		i2c38   = &imux38;
>> +		i2c39   = &imux39;
>> +		i2c40	= &e1si2c0;
>> +		i2c41	= &e1si2c1;
>> +		i2c42	= &e1si2c2;
>> +		i2c43	= &e1si2c3;
>> +		i2c44	= &e1si2c4;
>> +		i2c45	= &e1si2c5;
>> +		i2c46	= &e1si2c6;
>> +		i2c47	= &e1si2c7;
>> +		i2c48	= &i2c5mux0;
>> +		i2c49   = &m2riser;
>> +		i2c50	= &i2c5mux2;
>> +		i2c51	= &i2c5mux3;
>> +	};
>> +
>> +	chosen {
>> +		stdout-path = &uart5;
>> +		bootargs = "console=tty0 console=ttyS4,115200n8 earlyprintk";
>> +	};
>> +
>> +	memory at 80000000 {
>> +		device_type = "memory";
>> +		reg = <0x80000000 0x80000000>;
>> +	};
>> +
>> +	reserved-memory {
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		ranges;
>> +
>> +		vga_memory: framebuffer at 9f000000 {
>> +			no-map;
>> +			reg = <0x9f000000 0x01000000>; /* 16M */
>> +		};
>> +
>> +		ramoops at a0000000 {
>> +			compatible = "ramoops";
>> +			reg = <0xa0000000 0x100000>; /* 1MB */
>> +			record-size = <0x10000>; /* 64KB */
>> +			max-reason = <2>; /* KMSG_DUMP_OOPS */
>> +		};
>> +
>> +		gfx_memory: framebuffer {
>> +			size = <0x01000000>;
>> +			alignment = <0x01000000>;
>> +			compatible = "shared-dma-pool";
>> +			reusable;
>> +		};
>> +
>> +		video_engine_memory: jpegbuffer {
>> +			size = <0x02000000>;	/* 32M */
>> +			alignment = <0x01000000>;
>> +			compatible = "shared-dma-pool";
>> +			reusable;
>> +		};
>> +	};
>> +
>> +	power-gpios{
>> +		n2-gpios = <&gpio0 ASPEED_GPIO(N, 2) (GPIO_ACTIVE_HIGH|GPIO_PULL_UP)>;
>> +		n3-gpios = <&gpio0 ASPEED_GPIO(N, 3) (GPIO_ACTIVE_HIGH|GPIO_PULL_UP)>;
>> +	};
>> +
>> +	leds {
>> +		compatible = "gpio-leds";
>> +		uid_led {
>> +			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
>> +		};
>> +		fault_led {
>> +			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
>> +		};
>> +		power_led {
>> +			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
>> +		};
>> +
>> +		// Non-LEDs:
>> +		//   BMC_READY-O GPIO pin (not an LED) is being bound to the GPIO LED driver.
>> +		// Notes:
>> +		// * This is a workaround and leverages the GPIO LED driver to enable control of
>> +		//   reset tolerance and still allow the GPIO to be controlled from user space.
> 
> Add this also to the commit message?
> 
>> +		// * The standard Linux GPIO driver allows control of reset tolerance, however
>> +		//   does not expose user space APIs for user space control of the GPIO pin.
>> +		// * GPIO_TRANSITORY = reset tolerance is disabled
>> +		// * Any non-leds should be added below this line.
> 
> Use C89 style comments? (Though it?s inconsistent and I do not know if 
> there is a guideline.)

Sure, will fix.

> 
>> +		bmc_ready_noled {
>> +			gpios = <&gpio0 ASPEED_GPIO(Z, 0) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>;
>> +		};
>> +	};
>> +
>> +	buttons {
>> +		power-btn {
>> +			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
>> +		};
>> +		uid-btn {
>> +			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
>> +		};
>> +	};
>> +};
>> +
>> +// Enabled Primary flash on FMC for bring up activity
> 
> Imperative mood: Enable.

Sure, will fix.

> 
>> +&fmc {
>> +	status = "okay";
>> +	flash at 0 {
>> +		status = "okay";
>> +		compatible = "jedec,spi-nor";
>> +		label = "bmc";
>> +		spi-max-frequency = <50000000>;
>> +		partitions {
>> +			compatible = "fixed-partitions";
>> +			#address-cells = <1>;
>> +			#size-cells = <1>;
>> +
>> +			u-boot at 0 {
>> +				reg = <0x0 0xe0000>; // 896KB
>> +				label = "u-boot";
>> +			};
>> +
>> +			kernel at 100000 {
>> +				reg = <0x100000 0x900000>; // 9MB
>> +				label = "kernel";
>> +			};
>> +
>> +			rofs at a00000 {
>> +				reg = <0xa00000 0x35FF000>; // 55292KB (extends to end of 64MB SPI - 4KB)
>> +				label = "rofs";
> 
> Just my ignorance about how the calculations are done, and why some 
> holes are left.

We reserved some space for security feature.

> 
>> +			};
>> +		};
>> +	};
>> +};
>> +
>> +&fmcraw {
>> +	status = "okay";
>> +	spidev at 0 {
>> +		compatible = "hgx,glacier";
>> +		status = "okay";
>> +	};
>> +};
>> +
>> +&spi1raw {
>> +	status = "okay";
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_spi1_default>;
>> +	spidev at 0 {
>> +		spi-max-frequency = <25000000>;
>> +		compatible = "hgx,glacier";
>> +		status = "okay";
>> +	};
>> +};
>> +
>> +&spi2 {
>> +	status = "okay";
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_spi2_default>;
>> +
>> +	// Data SPI is 64MB in size
>> +	flash at 0 {
>> +		status = "okay";
>> +		label = "config";
>> +		spi-max-frequency = <50000000>;
>> +		partitions {
>> +			compatible = "fixed-partitions";
>> +			#address-cells = <1>;
>> +			#size-cells = <1>;
>> +
>> +			u-boot-env at 0 {
>> +				reg = <0x0 0x40000>;            // 256KB at offset 0
>> +				label = "u-boot-env";
>> +			};
>> +
>> +			rwfs at 40000 {
>> +				reg = <0x40000 0x1000000>;      // 16MB at offset 0x40000
>> +				label = "rwfs";
>> +			};
>> +
>> +			log at 0x1040000 {
>> +				reg = <0x1040000 0x2800000>;    // 40MB at offset 0x1040000
>> +				label = "log";                  // Move log to EMMC, make this unused
>> +			};
>> +		};
>> +	};
>> +};
>> +
>> +&uart1 {
>> +	status = "okay";
>> +};
>> +
>> +&uart3 {
>> +	//Enabling SOL
> 
> Add space after //.

Sure, will fix.

> 
>> +	status = "okay";
>> +};
>> +
>> +&uart5 {
>> +	// BMC Debug Console
>> +	status = "okay";
>> +};
>> +
>> +&uart_routing {
>> +	status = "okay";
>> +};
>> +
>> +// MAC1 (per schematics, 1-based MAC1-MAC4) of AST2600 connected to external PHY
>> +// This is "mac0" in zero-based DTS
>> +&mdio0 {
>> +	status = "okay";
>> +	ethphy0: ethernet-phy at 0 {
>> +		compatible = "ethernet-phy-ieee802.3-c22";
>> +		reg = <0>;
>> +	};
>> +
>> +};
>> +
>> +&mdio3 {
>> +	status = "okay";
>> +	ethphy3: ethernet-phy at 2 {
>> +		compatible = "ethernet-phy-ieee802.3-c22";
>> +		reg = <2>;
>> +	};
>> +};
>> +
>> +&mac0 {
>> +	status = "okay";
>> +	pinctrl-names = "default";
>> +	phy-mode = "rgmii-rxid";
>> +	max-speed = <1000>;
>> +	phy-handle = <&ethphy3>;
>> +	pinctrl-0 = <&pinctrl_rgmii1_default>;
>> +};
>> +
>> +&mac2 {
>> +	status = "okay";
>> +	phy-mode = "rmii";
>> +	use-ncsi;
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_rmii3_default>;
>> +};
>> +
>> +// Enable emmc
>> +&emmc_controller {
>> +	status = "okay";
>> +};
>> +
>> +&emmc {
>> +	non-removable;
>> +	pinctrl-0 = <&pinctrl_emmcg5_default>;
>> +	bus-width = <4>;
>> +	max-frequency = <52000000>;
>> +	clk-phase-mmc-hs200 = <9>, <225>;
>> +};
>> +
>> +/*
>> +* Enable USB port A as device (via the virtual hub) to host
>> +*/
> 
> Please align.
> 

Sure, will fix.

>> +&vhub {
>> +	status = "okay";
>> +	pinctrl-names = "default";
>> +	/*
>> +	Uncomment below line to enable internal EHCI controller
>> +	Current config uses xHCI Port1
>> +	*/
> 
> Use common comment styles?
> 

Sure, will fix.

>> +	// pinctrl-0 = <&pinctrl_usb2adp_default>;
>> +};
>> +
>> +&video {
>> +	status = "okay";
>> +	memory-region = <&video_engine_memory>;
>> +};
>> +
>> +// USB 2.0 to HMC, on USB Port B
>> +&ehci1 {
>> +	status = "okay";
>> +};
>> +
>> +// USB 1.0
>> +&uhci {
>> +	status = "okay";
>> +};
>> +
>> +// I2C1, SSIF IPMI interface
>> +&i2c0 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	disable-master = <1>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +	ssif-bmc at 10 {
>> +		compatible = "ssif-bmc";
>> +		alert-gpio = <&sgpiom0 39 GPIO_ACTIVE_LOW>;
>> +		pulse_width_us = <5>;
>> +		timeout_ms = <4995>;
>> +		reg = <0x10>;
>> +	};
>> +};
>> +
>> +// I2C2
>> +// BMC_I2C1_FPGA - Secondary FPGA
>> +// HMC EROT
>> +&i2c1 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	multi-master;
>> +	i2c-scl-clk-low-timeout-us = <32000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +};
>> +
>> +// I2C4
>> +&i2c3 {
>> +	status = "disabled";
>> +};
>> +
>> +// I2C5
>> +// RTC Driver
>> +// IO Expander
>> +&i2c4 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +	// Module 0, Expander @0x21
>> +	exp4: pca9555 at 21 {
>> +		compatible = "nxp,pca9555";
>> +		reg = <0x21>;
>> +		gpio-controller;
>> +		#gpio-cells = <2>;
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		interrupt-parent = <&gpio1>;
>> +		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
>> +
>> +		gpio-line-names =
>> +			"RTC_MUX_SEL-O",
>> +			"PCI_MUX_SEL-O",
>> +			"TPM_MUX_SEL-O",
>> +			"FAN_MUX-SEL-O",
>> +			"SGMII_MUX_SEL-O",
>> +			"DP_MUX_SEL-O",
>> +			"UPHY3_USB_SEL-O",
>> +			"NCSI_MUX_SEL-O",
>> +			"BMC_PHY_RST-O",
>> +			"RTC_CLR_L-O",
>> +			"BMC_12V_CTRL-O",
>> +			"PS_RUN_IO0_PG-I",
>> +			"",
>> +			"",
>> +			"",
>> +			"";
>> +	};
>> +};
>> +
>> +// I2C6
>> +// Module 0/1 I2C MUX x3
>> +&i2c5 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	multi-master;
>> +	i2c-scl-clk-low-timeout-us = <32000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +
>> +	i2c-switch at 71 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x71>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux16: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux17: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux18: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux19: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	i2c-switch at 72 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x72>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux20: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux21: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux22: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux23: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	i2c-switch at 73 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x73>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux24: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux25: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux26: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux27: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	//A MUX for a riser with a secondary M.2 installed.
> 
> Add a space.
> 

Sure, will fix.

>> +	i2c-switch at 74 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x74>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		i2c5mux0: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		//Optional/secondary M.2 drive slot
> 
> Ditto.
> 

Sure, will fix.

>> +		m2riser: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		i2c5mux2: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		i2c5mux3: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	i2c-switch at 75 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x75>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux28: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux29: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux30: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux31: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	i2c-switch at 76 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x76>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux32: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux33: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux34: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux35: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +
>> +	i2c-switch at 77 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x77>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		imux36: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		imux37: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		imux38: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		imux39: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +};
>> +
>> +// I2C7
>> +// Module 0/1 Leak Sensors
>> +// Module 0/1 Fan Controllers
>> +&i2c6 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +	hsc at 12 {
>> +		compatible = "ti,lm5066i";
>> +		reg = <0x12>;
>> +		shunt-resistor-micro-ohms = <190>;
>> +		status = "okay";
>> +	};
>> +	hsc at 14 {
>> +		compatible = "ti,lm5066i";
>> +		reg = <0x14>;
>> +		shunt-resistor-micro-ohms = <190>;
>> +		status = "okay";
>> +	};
>> +	max31790_1 {
>> +		compatible = "maxim,max31790";
>> +		reg = <0x20>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +	};
>> +	max31790_2 {
>> +		compatible = "maxim,max31790";
>> +		reg = <0x23>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +	};
>> +	max31790_3 {
>> +		compatible = "maxim,max31790";
>> +		reg = <0x2c>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +	};
>> +	max31790_4 {
>> +		compatible = "maxim,max31790";
>> +		reg = <0x2f>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +	};
>> +};
>> +
>> +// I2C9
>> +// M.2
>> +&i2c8 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	multi-master;
>> +	i2c-scl-clk-low-timeout-us = <32000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +};
>> +
>> +// I2C10
>> +// HMC IO Expander
>> +// Module 0/1 IO Expanders
>> +&i2c9 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +	// Module 0, Expander @0x20
>> +	exp0: pca9555 at 20 {
>> +		compatible = "nxp,pca9555";
>> +		reg = <0x20>;
>> +		gpio-controller;
>> +		#gpio-cells = <2>;
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		interrupt-parent = <&gpio1>;
>> +		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
>> +
>> +		gpio-line-names =
>> +		"FPGA_THERM_OVERT_L-I",
>> +		"FPGA_READY_BMC-I",
>> +		"HMC_BMC_DETECT-O",
>> +		"HMC_PGOOD-O",
>> +		"",
>> +		"BMC_STBY_CYCLE-O",
>> +		"FPGA_EROT_FATAL_ERROR_L-I",
>> +		"WP_HW_EXT_CTRL_L-O",
>> +		"EROT_FPGA_RST_L-O",
>> +		"FPGA_EROT_RECOVERY_L-O",
>> +		"BMC_EROT_FPGA_SPI_MUX_SEL-O",
>> +		"USB_HUB_RESET_L-O",
>> +		"NCSI_CS1_SEL-O",
>> +		"SGPIO_EN_L-O",
>> +		"B2B_IOEXP_INT_L-I",
>> +		"I2C_BUS_MUX_RESET_L-O";
>> +	};
>> +
>> +	// Module 1, Expander @0x21
>> +	exp1: pca9555 at 21 {
>> +		compatible = "nxp,pca9555";
>> +		reg = <0x21>;
>> +		gpio-controller;
>> +		#gpio-cells = <2>;
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		interrupt-parent = <&gpio1>;
>> +		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
>> +
>> +		gpio-line-names =
>> +		"SEC_FPGA_THERM_OVERT_L-I",
>> +		"SEC_FPGA_READY_BMC-I",
>> +		"",
>> +		"",
>> +		"",
>> +		"",
>> +		"SEC_FPGA_EROT_FATAL_ERROR_L-I",
>> +		"SEC_WP_HW_EXT_CTRL_L-O",
>> +		"SEC_EROT_FPGA_RST_L-O",
>> +		"SEC_FPGA_EROT_RECOVERY_L-O",
>> +		"SEC_BMC_EROT_FPGA_SPI_MUX_SEL-O",
>> +		"",
>> +		"",
>> +		"",
>> +		"",
>> +		"SEC_I2C_BUS_MUX_RESET_L-O";
>> +	};
>> +
>> +	// HMC Expander @0x27
>> +	exp2: pca9555 at 27 {
>> +		compatible = "nxp,pca9555";
>> +		reg = <0x27>;
>> +		gpio-controller;
>> +		#gpio-cells = <2>;
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		interrupt-parent = <&gpio1>;
>> +		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
>> +
>> +		gpio-line-names =
>> +		"HMC_PRSNT_L-I",
>> +		"HMC_READY-I",
>> +		"HMC_EROT_FATAL_ERROR_L-I",
>> +		"I2C_MUX_SEL-O",
>> +		"HMC_EROT_SPI_MUX_SEL-O",
>> +		"HMC_EROT_RECOVERY_L-O",
>> +		"HMC_EROT_RST_L-O",
>> +		"GLOBAL_WP_HMC-O",
>> +		"FPGA_RST_L-O",
>> +		"USB2_HUB_RST-O",
>> +		"CPU_UART_MUX_SEL-O",
>> +		"",
>> +		"",
>> +		"",
>> +		"",
>> +		"";
>> +	};
>> +	// HMC Expander @0x74
>> +	exp3: pca9555 at 74 {
>> +		compatible = "nxp,pca9555";
>> +		reg = <0x74>;
>> +		gpio-controller;
>> +		#gpio-cells = <2>;
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		interrupt-parent = <&gpio1>;
>> +		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
>> +
>> +		gpio-line-names =
>> +		"IOB_PRSNT_L",
>> +		"IOB_DP_HPD",
>> +		"IOX_BMC_RESET",
>> +		"IOB_IOEXP_INT_L",
>> +		"IOB_UID_LED_L",
>> +		"IOB_UID_BTN_L",
>> +		"IOB_SYS_RST_BTN_L",
>> +		"IOB_PWR_LED_L",
>> +		"IOB_PWR_BTN_L",
>> +		"IOB_PHY_RST",
>> +		"CPLD_JTAG_MUX_SEL",
>> +		"",
>> +		"",
>> +		"",
>> +		"",
>> +		"";
>> +	};
>> +};
>> +
>> +// I2C11
>> +// BMC FRU EEPROM
>> +// BMC Temp Sensor
>> +&i2c10 {
>> +	status = "okay";
>> +	clock-frequency = <400000>;
>> +	i2c-tck-thddat-config = <0x0099EC00>;
>> +	// BMC FRU EEPROM - 256 bytes
>> +	eeprom at 50 {
>> +		compatible = "atmel,24c02";
>> +		reg = <0x50>;
>> +		pagesize = <8>;
>> +	};
>> +};
>> +
>> +// I2C12
>> +&i2c11 {
>> +	status = "disabled";
>> +};
>> +
>> +// I2C13
>> +&i2c12 {
>> +	status = "disabled";
>> +};
>> +
>> +// I2C14
>> +// Module 0 UPHY3 SMBus
>> +&i2c13 {
>> +	status = "disabled";
>> +};
>> +
>> +// I2C15
>> +// Module 1 UPHY3 SMBus
>> +&i2c14 {
>> +	status = "okay";
>> +	clock-frequency = <100000>;
>> +	multi-master;
>> +	i2c-scl-clk-low-timeout-us = <32000>;
>> +	i2c-tck-thddat-config = <0x00EFD000>;
>> +
>> +	//E1.S drive slot 0-3
>> +	i2c-switch at 77 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x77>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		e1si2c0: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		e1si2c1: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		e1si2c2: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		e1si2c3: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +};
>> +
>> +// I2C16
>> +&i2c15 {
>> +	status = "okay";
>> +	clock-frequency = <100000>;
>> +	multi-master;
>> +	i2c-scl-clk-low-timeout-us = <32000>;
>> +	i2c-tck-thddat-config = <0x00EFD000>;
>> +
>> +	//E1.S drive slot 4-7
>> +	i2c-switch at 77 {
>> +		compatible = "nxp,pca9546";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0x77>;
>> +		i2c-mux-idle-disconnect;
>> +
>> +		e1si2c4: i2c at 0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +
>> +		e1si2c5: i2c at 1 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <1>;
>> +		};
>> +
>> +		e1si2c6: i2c at 2 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <2>;
>> +		};
>> +
>> +		e1si2c7: i2c at 3 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <3>;
>> +		};
>> +	};
>> +};
>> +
>> +// PCIe RC
>> +&pcie {
>> +	status = "okay";
>> +
>> +	interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
>> +
>> +	pcie_intc0: legacy-interrupt-controller {
>> +		interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
>> +	};
>> +};
>> +
>> +// Bridge between AHB bus and PCIe RC.
> 
> No dot/period needed at the end.
> 
>> +&h2x {
>> +	status = "okay";
>> +};
>> +
>> +&mctp {
>> +	status = "okay";
>> +};
>> +
>> +&jtag0 {
>> +	status = "okay";
>> +};
>> +
>> +&jtag1 {
>> +	mux-gpios = <&sgpiom0 41 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
>> +	status = "okay";
>> +};
>> +
>> +&rng {
>> +	status = "okay";
>> +};
>> +


From peter.chen at cixtech.com  Thu Mar 20 02:57:13 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Thu, 20 Mar 2025 17:57:13 +0800
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts
 support
In-Reply-To: <86frj8m4be.wl-maz@kernel.org>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-6-peter.chen@cixtech.com>
 <86frj8m4be.wl-maz@kernel.org>
Message-ID: <Z9vmeTj68LmwinPD@nchen-desktop>

On 25-03-20 09:36:37, Marc Zyngier wrote:
> Peter Chen <peter.chen at cixtech.com> wrote:
> >
> > +     pmu-a520 {
> > +             compatible = "arm,cortex-a520-pmu";
> > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> > +     };
> > +
> > +     pmu-a720 {
> > +             compatible = "arm,cortex-a720-pmu";
> > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> > +     };
> > +
> > +     pmu-spe {
> > +             compatible = "arm,statistical-profiling-extension-v1";
> > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
> > +     };
> 
> SPE should follow the same model as the PMU, as each CPU has its own
> SPE implementation, exposing different micro-architectural details.
> 

Hi Marc,

Thanks for your reply. But there is only one compatible string
"statistical-profiling-extension-v1" at drivers/perf/arm_spe_pmu.c,
how could differentiate pmu-spe-a720 and pmu-spe-a520, do I need
to change arm_spe_pmu.c as well?

-- 

Best regards,
Peter


From amadeus at jmu.edu.cn  Thu Mar 20 03:00:02 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 20 Mar 2025 18:00:02 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: rk3528: Add CPU frequency scaling support
In-Reply-To: <20250320100002.332720-1-amadeus@jmu.edu.cn>
References: <20250320100002.332720-1-amadeus@jmu.edu.cn>
Message-ID: <20250320100002.332720-2-amadeus@jmu.edu.cn>

By default, the CPUs on RK3528 operates at 1.5GHz. Add CPU frequency and
voltage mapping to the device tree to enable dynamic scaling via cpufreq.

The OPP values come from downstream kernel[1], and voltage is chosen from
the one that makes the actual frequency close to the displayed frequency.

[1] https://github.com/rockchip-linux/kernel/blob/develop-5.10/arch/arm64/boot/dts/rockchip/rk3528.dtsi

Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
---
 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 64 ++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
index 621fc19ac0b3..9dae18c3c770 100644
--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -61,6 +61,7 @@ cpu0: cpu at 0 {
 			device_type = "cpu";
 			enable-method = "psci";
 			clocks = <&scmi_clk SCMI_CLK_CPU>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 
 		cpu1: cpu at 1 {
@@ -69,6 +70,7 @@ cpu1: cpu at 1 {
 			device_type = "cpu";
 			enable-method = "psci";
 			clocks = <&scmi_clk SCMI_CLK_CPU>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 
 		cpu2: cpu at 2 {
@@ -77,6 +79,7 @@ cpu2: cpu at 2 {
 			device_type = "cpu";
 			enable-method = "psci";
 			clocks = <&scmi_clk SCMI_CLK_CPU>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 
 		cpu3: cpu at 3 {
@@ -85,6 +88,7 @@ cpu3: cpu at 3 {
 			device_type = "cpu";
 			enable-method = "psci";
 			clocks = <&scmi_clk SCMI_CLK_CPU>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 	};
 
@@ -103,6 +107,66 @@ scmi_clk: protocol at 14 {
 		};
 	};
 
+	cpu0_opp_table: opp-table-0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-microvolt = <825000 825000 1100000>;
+			clock-latency-ns = <40000>;
+			opp-suspend;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <825000 825000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-816000000 {
+			opp-hz = /bits/ 64 <816000000>;
+			opp-microvolt = <825000 825000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-1008000000 {
+			opp-hz = /bits/ 64 <1008000000>;
+			opp-microvolt = <850000 850000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <850000 850000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-1416000000 {
+			opp-hz = /bits/ 64 <1416000000>;
+			opp-microvolt = <925000 925000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-1608000000 {
+			opp-hz = /bits/ 64 <1608000000>;
+			opp-microvolt = <975000 975000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-1800000000 {
+			opp-hz = /bits/ 64 <1800000000>;
+			opp-microvolt = <1037500 1037500 1100000>;
+			clock-latency-ns = <40000>;
+		};
+
+		opp-2016000000 {
+			opp-hz = /bits/ 64 <2016000000>;
+			opp-microvolt = <1100000 1100000 1100000>;
+			clock-latency-ns = <40000>;
+		};
+	};
+
 	psci {
 		compatible = "arm,psci-1.0", "arm,psci-0.2";
 		method = "smc";
-- 
2.25.1



From amadeus at jmu.edu.cn  Thu Mar 20 03:00:01 2025
From: amadeus at jmu.edu.cn (Chukun Pan)
Date: Thu, 20 Mar 2025 18:00:01 +0800
Subject: [PATCH 0/1] arm64: dts: rockchip: rk3528: Add CPU frequency scaling support
Message-ID: <20250320100002.332720-1-amadeus@jmu.edu.cn>

This series depends on the pwm series:
https://lore.kernel.org/lkml/20250318120003.2340652-1-amadeus at jmu.edu.cn/

By default, the CPUs on RK3528 operates at 1.5GHz. Add CPU frequency and
voltage mapping to the device tree to enable dynamic scaling via cpufreq.

OPP values come from the downstream kernel, and voltage is chosen from
the one that makes the actual frequency close to the displayed frequency.

Here are the test results using mhz [1] on Radxa E20C:

------------------
display |  actual
 408MHz |  395MHz
 600MHz |  593MHz
 816MHz |  833MHz
1008MHz | 1089MHz
1200MHz | 1215MHz
1416MHz | 1428MHz
1608MHz | 1640MHz
1800MHz | 1804MHz
2016MHz | 1952MHz
------------------

If we want the actual frequency to reach 2016MHz, the voltage
needs to reach 1.13V (+0.03V), not sure if it is safe.
The maximum opp-table voltage of downstream kernel is 1.1V.

Jonas previously suggested using the maximum voltage of the
downstream opp-table due to differences in silicon quality.
However, this will make the actual frequency difference a
bit large. Here are his test results using maximum voltage:

--------
 4 boards (E20C, ROCK 2A, ROCK 2F)

 408000:  873mV   394MHz   394MHz   394MHz   394MHz
 600000:  873mV   592MHz   592MHz   592MHz   592MHz
 816000:  873mV   941MHz   977MHz   954MHz   953MHz
1008000:  873mV  1148MHz  1186MHz  1169MHz  1168MHz
1200000:  900mV  1368MHz  1380MHz  1366MHz  1360MHz
1416000:  964mV  1547MHz  1554MHz  1547MHz  1534MHz
1608000: 1014mV  1734MHz  1768MHz  1770MHz  1740MHz
1800000: 1064mV  1850MHz  1883MHz  1887MHz  1854MHz
2016000: 1100mV  1931MHz  1963MHz  1970MHz  1933MHz
--------

The downstream kernel reads the efuse value from otp to
select the voltage, usually using opp-microvolt-L3.

[1] https://github.com/wtarreau/mhz.git

Chukun Pan (1):
  arm64: dts: rockchip: rk3528: Add CPU frequency scaling support

 arch/arm64/boot/dts/rockchip/rk3528.dtsi | 64 ++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

-- 
2.25.1



From wthai at nvidia.com  Thu Mar 20 03:02:02 2025
From: wthai at nvidia.com (Willie Thai)
Date: Thu, 20 Mar 2025 10:02:02 +0000
Subject: [PATCH v2] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <174178473498.434308.6316925758588470688.robh@kernel.org>
References: <174178473498.434308.6316925758588470688.robh@kernel.org>
Message-ID: <20250320100202.56205-1-wthai@nvidia.com>

Hi Rob,

Thanks for your comment.

> My bot found new DTB warnings on the .dts files added or changed in this
> series.
> 
> Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
> are fixed by another series. Ultimately, it is up to the platform
> maintainer whether these warnings are acceptable or not. No need to reply
> unless the platform maintainer has comments.
> 
> If you already ran DT checks and didn't see these error(s), then
> make sure dt-schema is up to date:
> 
>   pip3 install dtschema --upgrade
> 
> 
> New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250312045802.4115029-1-wthai at nvidia.com:
> 
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /: compatible: 'oneOf' conditional failed, one must be fixed:
> 	'nvidia,gb200nvl-bmc' is not one of ['delta,ahe50dc-bmc', 'facebook,galaxy100-bmc', 'facebook,wedge100-bmc', 'facebook,wedge40-bmc', 'microsoft,olympus-bmc', 'quanta,q71l-bmc', 'tyan,palmetto-bmc', 'yadro,vesnin-bmc']
> 	'nvidia,gb200nvl-bmc' is not one of ['amd,daytonax-bmc', 'amd,ethanolx-bmc', 'ampere,mtjade-bmc', 'aspeed,ast2500-evb', 'asrock,e3c246d4i-bmc', 'asrock,e3c256d4i-bmc', 'asrock,romed8hm3-bmc', 'asrock,spc621d8hm3-bmc', 'asrock,x570d4u-bmc', 'bytedance,g220a-bmc', 'facebook,cmm-bmc', 'facebook,minipack-bmc', 'facebook,tiogapass-bmc', 'facebook,yamp-bmc', 'facebook,yosemitev2-bmc', 'facebook,wedge400-bmc', 'hxt,stardragon4800-rep2-bmc', 'ibm,mihawk-bmc', 'ibm,mowgli-bmc', 'ibm,romulus-bmc', 'ibm,swift-bmc', 'ibm,witherspoon-bmc', 'ingrasys,zaius-bmc', 'inspur,fp5280g2-bmc', 'inspur,nf5280m6-bmc', 'inspur,on5263m5-bmc', 'intel,s2600wf-bmc', 'inventec,lanyang-bmc', 'lenovo,hr630-bmc', 'lenovo,hr855xg2-bmc', 'portwell,neptune-bmc', 'qcom,centriq2400-rep-bmc', 'supermicro,x11spi-bmc', 'tyan,s7106-bmc', 'tyan,s8036-bmc', 'yadro,nicole-bmc', 'yadro,vegman-n110-bmc', 'yadro,vegman-rx20-bmc', 'yadro,vegman-sx20-bmc']
> 	'nvidia,gb200nvl-bmc' is not one of ['ampere,mtjefferson-bmc', 'ampere,mtmitchell-bmc', 'aspeed,ast2600-evb', 'aspeed,ast2600-evb-a1', 'asus,x4tf-bmc', 'facebook,bletchley-bmc', 'facebook,catalina-bmc', 'facebook,cloudripper-bmc', 'facebook,elbert-bmc', 'facebook,fuji-bmc', 'facebook,greatlakes-bmc', 'facebook,harma-bmc', 'facebook,minerva-cmc', 'facebook,yosemite4-bmc', 'ibm,blueridge-bmc', 'ibm,everest-bmc', 'ibm,fuji-bmc', 'ibm,rainier-bmc', 'ibm,sbp1-bmc', 'ibm,system1-bmc', 'ibm,tacoma-bmc', 'inventec,starscream-bmc', 'inventec,transformer-bmc', 'jabil,rbp-bmc', 'qcom,dc-scm-v1-bmc', 'quanta,s6q-bmc', 'ufispace,ncplite-bmc']
> 	'aspeed,ast2400' was expected
> 	'aspeed,ast2500' was expected
> 	from schema $id: http://devicetree.org/schemas/arm/aspeed/aspeed.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /: failed to match any schema with compatible: ['nvidia,gb200nvl-bmc', 'aspeed,ast2600']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
> 	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pinctrl: emmcg5_default:groups:0: 'EMMCG5' is not one of ['ADC0', 'ADC1', 'ADC10', 'ADC11', 'ADC12', 'ADC13', 'ADC14', 'ADC15', 'ADC2', 'ADC3', 'ADC4', 'ADC5', 'ADC6', 'ADC7', 'ADC8', 'ADC9', 'BMCINT', 'EMMCG1', 'EMMCG4', 'EMMCG8', 'ESPI', 'ESPIALT', 'FSI1', 'FSI2', 'FWQSPI', 'FWSPIABR', 'FWSPID', 'FWSPIWP', 'GPIT0', 'GPIT1', 'GPIT2', 'GPIT3', 'GPIT4', 'GPIT5', 'GPIT6', 'GPIT7', 'GPIU0', 'GPIU1', 'GPIU2', 'GPIU3', 'GPIU4', 'GPIU5', 'GPIU6', 'GPIU7', 'HVI3C3', 'HVI3C4', 'I2C1', 'I2C10', 'I2C11', 'I2C12', 'I2C13', 'I2C14', 'I2C15', 'I2C16', 'I2C2', 'I2C3', 'I2C4', 'I2C5', 'I2C6', 'I2C7', 'I2C8', 'I2C9', 'I3C1', 'I3C2', 'I3C3', 'I3C4', 'I3C5', 'I3C6', 'JTAGM', 'LHPD', 'LHSIRQ', 'LPC', 'LPCHC', 'LPCPD', 'LPCPME', 'LPCSMI', 'LSIRQ', 'MACLINK1', 'MACLINK2', 'MACLINK3', 'MACLINK4', 'MDIO1', 'MDIO2', 'MDIO3', 'MDIO4', 'NCSI3', 'NCSI4', 'NCTS1', 'NCTS2', 'NCTS3', 'NCTS4', 'NDCD1', 'NDCD2', 'NDCD3', 'NDCD4', 'NDSR1', 'NDSR2', 'NDSR3'
>  , 'NDSR4', 'NDTR1', 'NDTR2', 'NDTR3', 'NDTR4', 'NRI1', 'NRI2', 'NRI3', 'NRI4', 'NRTS1', 'NRTS2', 'NRTS3', 'NRTS4', 'OSCCLK', 'PEWAKE', 'PWM0', 'PWM1', 'PWM10G0', 'PWM10G1', 'PWM11G0', 'PWM11G1', 'PWM12G0', 'PWM12G1', 'PWM13G0', 'PWM13G1', 'PWM14G0', 'PWM14G1', 'PWM15G0', 'PWM15G1', 'PWM2', 'PWM3', 'PWM4', 'PWM5', 'PWM6', 'PWM7', 'PWM8G0', 'PWM8G1', 'PWM9G0', 'PWM9G1', 'QSPI1', 'QSPI2', 'RGMII1', 'RGMII2', 'RGMII3', 'RGMII4', 'RMII1', 'RMII2', 'RMII3', 'RMII4', 'RXD1', 'RXD2', 'RXD3', 'RXD4', 'SALT1', 'SALT10G0', 'SALT10G1', 'SALT11G0', 'SALT11G1', 'SALT12G0', 'SALT12G1', 'SALT13G0', 'SALT13G1', 'SALT14G0', 'SALT14G1', 'SALT15G0', 'SALT15G1', 'SALT16G0', 'SALT16G1', 'SALT2', 'SALT3', 'SALT4', 'SALT5', 'SALT6', 'SALT7', 'SALT8', 'SALT9G0', 'SALT9G1', 'SD1', 'SD2', 'SD3', 'SGPM1', 'SGPM2', 'SGPS1', 'SGPS2', 'SIOONCTRL', 'SIOPBI', 'SIOPBO', 'SIOPWREQ', 'SIOPWRGD', 'SIOS3', 'SIOS5', 'SIOSCI', 'SPI1', 'SPI1ABR', 'SPI1CS1', 'SPI1WP', 'SPI2', 'SPI2CS1', 'SPI2CS2', 'TACH0', 'TACH1', 'TACH10'
>  , 'TACH11', 'TACH12', 'TACH13', 'TACH14', 'TACH15', 'TACH2', 'TACH3', 'TACH4', 'TACH5', 'TACH6', 'TACH7', 'TACH8', 'TACH9', 'THRU0', 'THRU1', 'THRU2', 'THRU3', 'TXD1', 'TXD2', 'TXD3', 'TXD4', 'UART10', 'UART11', 'UART12G0', 'UART12G1', 'UART13G0', 'UART13G1', 'UART6', 'UART7', 'UART8', 'UART9', 'USBA', 'USBB', 'VB', 'VGAHS', 'VGAVS', 'WDTRST1', 'WDTRST2', 'WDTRST3', 'WDTRST4']
> 	from schema $id: http://devicetree.org/schemas/pinctrl/aspeed,ast2600-pinctrl.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
> 	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
> 	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
> 	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c at 80: Unevaluated properties are not allowed ('disable-master' was unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/aspeed,i2c.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 71: $nodename:0: 'i2c-switch at 71' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 71: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: $nodename:0: 'i2c-switch at 74' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 72: $nodename:0: 'i2c-switch at 72' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 72: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 73: $nodename:0: 'i2c-switch at 73' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 73: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 70: $nodename:0: 'i2c-switch at 70' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 70: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 75: $nodename:0: 'i2c-switch at 75' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 75: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: $nodename:0: 'i2c-switch at 74' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 74: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 76: $nodename:0: 'i2c-switch at 76' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 76: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 23: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 2c: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: max31790 at 2f: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 27: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pca9555 at 74: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> 	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: $nodename:0: 'i2c-switch at 77' does not match '^(i2c-?)?mux'
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c-switch at 77: Unevaluated properties are not allowed ('#address-cells', '#size-cells', 'i2c at 0', 'i2c at 1', 'i2c at 2', 'i2c at 3' were unexpected)
> 	from schema $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
> 	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
> 	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']


Will add the binding into the yaml file in the next version.

The other warnings are coming from the dtsi itself.

From lkp at intel.com  Thu Mar 20 03:05:57 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 20 Mar 2025 18:05:57 +0800
Subject: [PATCH v4 5/6] clk: meson: axg-audio: Add the mclk pad div for
 s4 chip
In-Reply-To: <20250319-audio_drvier-v4-5-686867fad719@amlogic.com>
References: <20250319-audio_drvier-v4-5-686867fad719@amlogic.com>
Message-ID: <202503201714.sI6HIkYs-lkp@intel.com>

Hi jiebing,

kernel test robot noticed the following build errors:

[auto build test ERROR on 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab]

url:    https://github.com/intel-lab-lkp/linux/commits/jiebing-chen-via-B4-Relay/dt-bindings-clock-meson-Add-audio-power-domain-for-s4-soc/20250319-151110
base:   6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
patch link:    https://lore.kernel.org/r/20250319-audio_drvier-v4-5-686867fad719%40amlogic.com
patch subject: [PATCH v4 5/6] clk: meson: axg-audio: Add the mclk pad div for s4 chip
config: arm64-randconfig-001-20250320 (https://download.01.org/0day-ci/archive/20250320/202503201714.sI6HIkYs-lkp at intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 87916f8c32ebd8e284091db9b70339df57fd1e90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250320/202503201714.sI6HIkYs-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503201714.sI6HIkYs-lkp at intel.com/

All errors (new ones prefixed by >>):

>> drivers/clk/meson/axg-audio.c:2228:34: error: cannot assign to variable 'aud_regmap_config' with const-qualified type 'const struct regmap_config'
    2228 |                 aud_regmap_config.max_register = resource_size(res) - 4;
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
   drivers/clk/meson/axg-audio.c:2220:37: note: variable 'aud_regmap_config' declared const here
    2220 |                 static const struct regmap_config aud_regmap_config = {
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
    2221 |                         .reg_bits = 32,
         |                         ~~~~~~~~~~~~~~~
    2222 |                         .val_bits = 32,
         |                         ~~~~~~~~~~~~~~~
    2223 |                         .reg_stride = 4,
         |                         ~~~~~~~~~~~~~~~~
    2224 |                 };
         |                 ~
   drivers/clk/meson/axg-audio.c:2229:26: error: cannot assign to variable 'aud_regmap_config' with const-qualified type 'const struct regmap_config'
    2229 |                 aud_regmap_config.name =
         |                 ~~~~~~~~~~~~~~~~~~~~~~ ^
   drivers/clk/meson/axg-audio.c:2220:37: note: variable 'aud_regmap_config' declared const here
    2220 |                 static const struct regmap_config aud_regmap_config = {
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
    2221 |                         .reg_bits = 32,
         |                         ~~~~~~~~~~~~~~~
    2222 |                         .val_bits = 32,
         |                         ~~~~~~~~~~~~~~~
    2223 |                         .reg_stride = 4,
         |                         ~~~~~~~~~~~~~~~~
    2224 |                 };
         |                 ~
   2 errors generated.


vim +2228 drivers/clk/meson/axg-audio.c

  2175	
  2176	static int axg_audio_clkc_probe(struct platform_device *pdev)
  2177	{
  2178		struct device *dev = &pdev->dev;
  2179		const struct audioclk_data *data;
  2180		struct axg_audio_reset_data *rst;
  2181		struct regmap *map;
  2182		void __iomem *regs;
  2183		struct clk_hw *hw;
  2184		struct clk *clk;
  2185		int ret, i;
  2186	
  2187		data = of_device_get_match_data(dev);
  2188		if (!data)
  2189			return -EINVAL;
  2190	
  2191		regs = devm_platform_ioremap_resource(pdev, 0);
  2192		if (IS_ERR(regs))
  2193			return PTR_ERR(regs);
  2194	
  2195		axg_audio_regmap_cfg.max_register = data->max_register;
  2196		map = devm_regmap_init_mmio(dev, regs, &axg_audio_regmap_cfg);
  2197		if (IS_ERR(map)) {
  2198			dev_err(dev, "failed to init regmap: %ld\n", PTR_ERR(map));
  2199			return PTR_ERR(map);
  2200		}
  2201	
  2202		/* Get the mandatory peripheral clock */
  2203		clk = devm_clk_get_enabled(dev, "pclk");
  2204		if (IS_ERR(clk))
  2205			return PTR_ERR(clk);
  2206	
  2207		ret = device_reset(dev);
  2208		if (ret) {
  2209			dev_err_probe(dev, ret, "failed to reset device\n");
  2210			return ret;
  2211		}
  2212	
  2213		/* Populate regmap for the regmap backed clocks */
  2214		for (i = 0; i < data->regmap_clk_num; i++)
  2215			data->regmap_clks[i]->map = map;
  2216	
  2217		/* some amlogic chip clock pad reg domian is different */
  2218		if (audio_clock_pad_is_new_regmap(dev->of_node)) {
  2219			struct resource *res;
  2220			static const struct regmap_config aud_regmap_config = {
  2221				.reg_bits = 32,
  2222				.val_bits = 32,
  2223				.reg_stride = 4,
  2224			};
  2225			regs = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
  2226			if (IS_ERR(regs))
  2227				return PTR_ERR(regs);
> 2228			aud_regmap_config.max_register = resource_size(res) - 4;
  2229			aud_regmap_config.name =
  2230				devm_kasprintf(dev, GFP_KERNEL, "%s-%s", dev->of_node->name, "pads");
  2231			map = devm_regmap_init_mmio(dev, regs, &aud_regmap_config);
  2232			/* Populate clk pad regmap for the regmap backed clocks */
  2233			for (i = 0; i < data->regmap_clk_pads_num; i++)
  2234				data->regmap_clks_pads[i]->map = map;
  2235		}
  2236		/* Take care to skip the registered input clocks */
  2237		for (i = AUD_CLKID_DDR_ARB; i < data->hw_clks.num; i++) {
  2238			const char *name;
  2239	
  2240			hw = data->hw_clks.hws[i];
  2241			/* array might be sparse */
  2242			if (!hw)
  2243				continue;
  2244	
  2245			name = hw->init->name;
  2246			ret = devm_clk_hw_register(dev, hw);
  2247			if (ret) {
  2248				dev_err(dev, "failed to register clock %s\n", name);
  2249				return ret;
  2250			}
  2251		}
  2252	
  2253		ret = devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, (void *)&data->hw_clks);
  2254		if (ret)
  2255			return ret;
  2256	
  2257		/* Stop here if there is no reset */
  2258		if (!data->reset_num)
  2259			return 0;
  2260	
  2261		rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
  2262		if (!rst)
  2263			return -ENOMEM;
  2264	
  2265		rst->map = map;
  2266		rst->offset = data->reset_offset;
  2267		rst->rstc.nr_resets = data->reset_num;
  2268		rst->rstc.ops = &axg_audio_rstc_ops;
  2269		rst->rstc.of_node = dev->of_node;
  2270		rst->rstc.owner = THIS_MODULE;
  2271	
  2272		return devm_reset_controller_register(dev, &rst->rstc);
  2273	}
  2274	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From patchwork-bot+netdevbpf at kernel.org  Thu Mar 20 03:30:37 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Thu, 20 Mar 2025 10:30:37 +0000
Subject: [PATCH net] net: ti: icssg-prueth: Add lock to stats
In-Reply-To: <20250314102721.1394366-1-danishanwar@ti.com>
References: <20250314102721.1394366-1-danishanwar@ti.com>
Message-ID: <174246663785.1712233.14659376394563532017.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri, 14 Mar 2025 15:57:21 +0530 you wrote:
> Currently the API emac_update_hardware_stats() reads different ICSSG
> stats without any lock protection.
> 
> This API gets called by .ndo_get_stats64() which is only under RCU
> protection and nothing else. Add lock to this API so that the reading of
> statistics happens during lock.
> 
> [...]

Here is the summary with links:
  - [net] net: ti: icssg-prueth: Add lock to stats
    https://git.kernel.org/netdev/net/c/47a9b5e52abd

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From angelogioacchino.delregno at collabora.com  Thu Mar 20 03:33:45 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 11:33:45 +0100
Subject: [PATCH 2/4] dt-bindings: remoteproc: mediatek: Remove l1tcm for
 dual-core MT8188 SCP
In-Reply-To: <b0872ee008c3c6a2731f949d8c2be77aa49341f7.camel@mediatek.com>
References: <20250318-scp-dual-core-mt8390-v1-0-8733e192cc73@collabora.com>
 <20250318-scp-dual-core-mt8390-v1-2-8733e192cc73@collabora.com>
 <70c10764-121b-43f5-931e-84ffd666c594@collabora.com>
 <b0872ee008c3c6a2731f949d8c2be77aa49341f7.camel@mediatek.com>
Message-ID: <be4af783-3b98-439b-be3d-30d6ff520d2e@collabora.com>

Il 20/03/25 02:28, Moudy Ho (???) ha scritto:
> On Wed, 2025-03-19 at 10:34 +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 18/03/25 23:22, N?colas F. R. A. Prado ha scritto:
>>> The SCP present on MT8188 does not have an L1TCM memory region, but
>>> the
>>> binding incorrectly requires one for the dual-core description of
>>> the
>>> MT8188 SCP. Remove that requirement. Also update the minimum number
>>> of
>>> reg and reg-names to 1, since as this is a multi-core SCP with no
>>> L1TCM memory, only the CFG memory region is present in the parent
>>> node.
>>>
>>> Fixes: 91e0d560b9fd ("dt-bindings: remoteproc: mediatek: Support
>>> MT8188 dual-core SCP")
>>> Signed-off-by: N?colas F. R. A. Prado <nfraprado at collabora.com>
>>
>> As far as I know, the L1TCM is present on MT8188, and it's at
>> 0x1070000 len 0x8000
>> exactly like MT8195.
>>
>> Moudy, are you able to please confirm or deny that?
>>
>> Cheers,
>> Angelo
>>
>>
> 
> Hi Angelo,
> 
> Unfortunately, during the transition from MT8195 to MT8188, the SCP
> removed the L1TCM, retaining only the SRAM and config register.
> For detailed hardware changes, you can refer to Tinghan's previous
> description at the following link.
> 
> ref:
> https://lore.kernel.org/all/20220715051821.30707-3-tinghan.shen at mediatek.com/
> 
Thanks Moudy!

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>


From naresh.kamboju at linaro.org  Thu Mar 20 03:33:32 2025
From: naresh.kamboju at linaro.org (Naresh Kamboju)
Date: Thu, 20 Mar 2025 16:03:32 +0530
Subject: Fast model boot failure with Linux next-20250312
In-Reply-To: <Z9ra3I2axii2HRVb@J2N7QTR9R3>
References: <CA+G9fYvPu+MQKhYyPZSSDpAn-zhRGmeHQ8hJksT_cdDdxfbB-g@mail.gmail.com>
 <Z9ra3I2axii2HRVb@J2N7QTR9R3>
Message-ID: <CA+G9fYuw_jXCz07Dsk46QXQr3+y5-NfkC30ZNh+XmyeWgibQhA@mail.gmail.com>

On Wed, 19 Mar 2025 at 20:25, Mark Rutland <mark.rutland at arm.com> wrote:
>
> On Wed, Mar 19, 2025 at 08:07:47PM +0530, Naresh Kamboju wrote:
> > Regressions on the arm64 Fast Model (FVP-AEMvA) caused boot failures starting
> > with Linux next-20250312 and persisting through next-20250319.
> >
> > First seen on the next-20250312
> >  Good: next-20250311
> >  Bad:  next-20250312 .. next-20250319
> >
> > Regressions found on FVP:
> >  - boot
> >
> > Regression Analysis:
> >  - New regression? Yes
> >  - Reproducible? Yes
> >
> > Boot regression: Fast model boot failure with Linux next-20250312
> > Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>
> >
> > Anders bisected this to this commit id,
> >
> > # first bad commit:
> >   [858c7bfcb35e1100b58bb63c9f562d86e09418d9]
> >   arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
> >
> > NOTE:
> >   LKFT is currently running FVP Fast Models version 11.24.
> >   Planned upgrade to the Fast Models version 11.28 in this sprint.
>
> What firmware (and version therof) are you running within the model?

Fast Models [11.24.11 (Nov 29 2023)]
Booting Trusted Firmware
BL1: v2.9(release):v2.9.0
BL2: v2.9(release):v2.9.0
BL31: v2.9(release):v2.9.0
UEFI firmware (version  built at 22:31:25 on May 26 2023)
UEFI v2.70 (EDK II, 0x00010000)

We need to update the firmware version at our end.

>
> For example, if the EL3 firmware lacks support for FEAT_FGT2 or
> FEAT_PMUv3p9, the kernel will trap to EL3 early during boot and die.
>
> It would be really helpful if you could capture that in the report in
> future.
>
> Mark.
>
> >
> > ## Boot log
> >   <No crash log on the console>
> >
> > ## Source
> > * Kernel version: 6.14.0-rc7
> > * Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
> > * Git sha: ff7f9b199e3f4cc7d61df5a9a26a7cbb5c1492e6
> > * Git describe: next-20250319
> > * Project details:
> > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319
> > * DUT: arm64 Fast Model (FVP-AEMvA)
> > * Toolchains: gcc-13 and clang-20
> >
> > ## Build
> > * Build log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/log
> > * Build history:
> > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675685/suite/boot/test/gcc-13-lkftconfig/history/
> > * Build details:
> > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/
> > * Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/
> > * Kernel config:
> > https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/config
> >
> > --
> > Linaro LKFT
> > https://lkft.linaro.org
> >

- Naresh


From naresh.kamboju at linaro.org  Thu Mar 20 03:35:14 2025
From: naresh.kamboju at linaro.org (Naresh Kamboju)
Date: Thu, 20 Mar 2025 16:05:14 +0530
Subject: stable-rc: Fast model boot fail Internal error Oops BTI - kernfs_iop_permission
Message-ID: <CA+G9fYtucEt8Hp6RsV0o+OWSz1E=hXBvhHa-P9C-bPnb7cyGaQ@mail.gmail.com>

Regressions on arm64 Fast model (FVP-aemva) boot failed with stable-rc 6.13.

First seen on the stable-rc 6.13.8-rc1
 Good: v6.13.8
 Bad:  6.13.8-rc1 (v6.13.7-242-g14de9a7d510f)

Regressions found on FVP:
 - boot

Regression Analysis:
 - New regression? Yes
 - Reproducible? Yes

Boot regression: Fast model boot fail Internal error Oops BTI
Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>

NOTE:
  LKFT is currently running FVP Fast Models version 11.24.
  Planned upgrade to the Fast Models version 11.28 in this sprint.

## Boot log
[   12.812790] Internal error: Oops - BTI: 0000000036000002 [#1] PREEMPT SMP
[   12.812886] Modules linked in: drm fuse backlight ip_tables x_tables
[   12.813120] CPU: 6 UID: 0 PID: 136 Comm: udevadm Not tainted 6.13.8-rc1 #1
[   12.813245] Hardware name: FVP Base RevC (DT)
[   12.813317] pstate: 163402809 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=-c)
[   12.813450] pc : kernfs_iop_permission+0x4/0xe4
[   12.813585] lr : inode_permission+0xb8/0x174
[   12.813728] sp : ffff800080d63bb0
[   12.813796] x29: ffff800080d63bc0 x28: 0000000000002e2e x27: 00000000fffffff6
[   12.813978] x26: 0000000000000030 x25: 2f2f2f2f2f2f2f2f x24: 61c8864680b583eb
[   12.814161] x23: 0000000000000000 x22: fefefefefefefeff x21: ffffa991682c84b8
[   12.814344] x20: ffff0008006704d0 x19: 0000000000000001 x18: 00000000fffffffb
[   12.814525] x17: ffff000801bf8021 x16: e0acaabd2f000000 x15: ffffffffff000000
[   12.814711] x14: 0000000000000002 x13: ffffffffffffffff x12: 0000002e00000000
[   12.814893] x11: 0000002d00000000 x10: 0000002d00000000 x9 : ffff0008006704d0
[   12.815076] x8 : ffffa991665f0ff8 x7 : 0000000000000000 x6 : 0000000000000000
[   12.815253] x5 : 0000000000000000 x4 : 0000000000004050 x3 : 2f7375622f737973
[   12.815432] x2 : 0000000000000001 x1 : ffff0008006704d0 x0 : ffffa991682c84b8
[   12.815613] Call trace:
[   12.815670]  kernfs_iop_permission+0x4/0xe4 (P)
[   12.815830]  link_path_walk+0x2b8/0x388
[   12.815962]  path_lookupat+0x68/0x120
[   12.816073]  filename_lookup+0xe0/0x1e0
[   12.816196]  do_readlinkat+0x6c/0x1d8
[   12.816337]  __arm64_sys_readlinkat+0x20/0x30
[   12.816481]  invoke_syscall+0x40/0xf8
[   12.816623]  el0_svc_common+0xa8/0xd8
[   12.816765]  do_el0_svc+0x1c/0x28
[   12.816904]  el0_svc+0x38/0x68
[   12.817050]  el0t_64_sync_handler+0x78/0x108
[   12.817203]  el0t_64_sync+0x198/0x19c
[   12.817359] Code: a8c27bfd d50323bf d65f03c0 d503245f (373806c2)
[   12.817444] ---[ end trace 0000000000000000 ]---


## Source
* Kernel version: 6.13.8-rc1
* Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* Git sha: 14de9a7d510fcfb3bd35e275eda09724bda4d440
* Git describe: v6.13.7-242-g14de9a7d510f
* Project details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/

## Build
* Build log: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/log
* Build history:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/history/
* Build details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/
* Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uXZoz8Lc7Ue3i4mVWAM8Y800oz/
* Kernel config:
https://storage.tuxsuite.com/public/linaro/lkft/builds/2uXZoz8Lc7Ue3i4mVWAM8Y800oz/config


--
Linaro LKFT
https://lkft.linaro.org


From jackmanb at google.com  Thu Mar 20 03:44:38 2025
From: jackmanb at google.com (Brendan Jackman)
Date: Thu, 20 Mar 2025 10:44:38 +0000
Subject: [PATCH RFC v2 04/29] mm: asi: Add infrastructure for boot-time enablement
In-Reply-To: <Z9sRQ0cK0rupEiT-@google.com>
References: <20250110-asi-rfc-v2-v2-0-8419288bc805@google.com>
 <20250110-asi-rfc-v2-v2-4-8419288bc805@google.com> <20250319172935.GMZ9r-_zzXhyhHBLfj@fat_crate.local>
 <Z9sRQ0cK0rupEiT-@google.com>
Message-ID: <D8L164U8HBTB.G5MS86AIISLM@google.com>

On Wed Mar 19, 2025 at 6:47 PM UTC, Yosry Ahmed wrote:
> On Wed, Mar 19, 2025 at 06:29:35PM +0100, Borislav Petkov wrote:
> > On Fri, Jan 10, 2025 at 06:40:30PM +0000, Brendan Jackman wrote:
> > > Add a boot time parameter to control the newly added X86_FEATURE_ASI.
> > > "asi=on" or "asi=off" can be used in the kernel command line to enable
> > > or disable ASI at boot time. If not specified, ASI enablement depends
> > > on CONFIG_ADDRESS_SPACE_ISOLATION_DEFAULT_ON, which is off by default.
> > 
> > I don't know yet why we need this default-on thing...
>
> It's a convenience to avoid needing to set asi=on if you want ASI to be
> on by default. It's similar to HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON
> or ZSWAP_DEFAULT_ON.
>
> [..]
> > > @@ -175,7 +184,11 @@ static __always_inline bool asi_is_restricted(void)
> > >  	return (bool)asi_get_current();
> > >  }
> > >  
> > > -/* If we exit/have exited, can we stay that way until the next asi_enter? */
> > > +/*
> > > + * If we exit/have exited, can we stay that way until the next asi_enter?
> > 
> > What is that supposed to mean here?
>
> asi_is_relaxed() checks if the thread is outside an ASI critical
> section.
>
> I say "the thread" because it will also return true if we are executing
> an interrupt that arrived during the critical section, even though the
> interrupt handler is not technically part of the critical section.
>
> Now the reason it says "if we exit we stay that way" is probably
> referring to the fact that an asi_exit() when interrupting a critical
> section will be undone in the interrupt epilogue by re-entering ASI.
>
> I agree the wording here is confusing. We should probably describe this
> more explicitly and probably rename the function after the API
> discussions you had in the previous patch.

Yeah, this is confusing. It's trying to very concisely define the
concept of "relaxed" but now I see it through Boris' eyes I realise
it's really unhelpful to try and do that. And yeah we should probably
just rework the terminology/API.

To re-iterate what Yosry said, aside from my too-clever comment style
the more fundamental thing that's confusing here is that, using the
terminology currently in the code there are two concepts at play:

- The critical section: this is the path from asi_enter() to
  asi_relax(). The critical section can be interrupted, and code
  running in those interupts is not said to be "in the critical
  section".

- Being "tense" vs "relaxed". Being "tense" means the _task_ is in a
  critical section, but the current code might not be.

This distinction is theoretically relevant because e.g. it's a bug to
access sensitive data in a critical section, but it's OK to access it
while in the tense state (we will switch to the restricted address
space, but this is OK because we will have a chance to asi_enter()
again before we get back to the untrusted code). 

BTW, just to be clear:

1. Both of these are only relevant to code that's pretty deeply aware
   of ASI. (TLB flushing code, entry code, stuff like that).

2. To be honest whenever you write:

     if (asi_in_critical_section())

   You probably mean:

     if (WARN_ON(asi_in_critical_section()))

   For example if we try to flush the TLB in the critical section,
   there's a thing we can do to handle it. But that really shouldn't
   be necessary.  We want the critical section code to be very small
   and straight-line code.

   And indeed in the present code we don't use
   asi_in_critical_section() for anything bur WARNing.

> asi_is_relaxed() checks if the thread is outside an ASI critical
> section.

Now I see it written this way, this is probably the best way to
conceptualise it. Instead of having two concepts "tense/relaxed" vs
"ASI critical section" we could just say "the task is in a critical
section" vs "the CPU is in a critical section". So we could have
something like:

bool asi_task_critical(void);
bool asi_cpu_critical(void);

(They could also accept an argument for the task/CPU, but I can't see
any reason why you'd peek at another context like that).

--

For everything else, Ack to Boris or +1 to Yosry respectively.


From peter.chen at cixtech.com  Thu Mar 20 03:49:47 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Thu, 20 Mar 2025 18:49:47 +0800
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
 <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>
Message-ID: <Z9vyy7f5NOPyzUES@nchen-desktop>

On 25-03-20 10:25:53, Krzysztof Kozlowski wrote:
> EXTERNAL EMAIL
> 
> On 05/03/2025 06:38, Peter Chen wrote:
> > Using this entry as the maintainers information for CIX SKY series SoCs.
> >
> > Acked-by: Fugang Duan <fugang.duan at cixtech.com>
> > Signed-off-by: Peter Chen <peter.chen at cixtech.com>
> > ---
> > Changes for v4
> > - Add two dts files as maintained files
> >
> >  MAINTAINERS | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index efee40ea589f..edf26cf11ee2 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -2354,6 +2354,16 @@ F:     arch/arm/boot/compressed/misc-ep93xx.h
> >  F:   arch/arm/mach-ep93xx/
> >  F:   drivers/iio/adc/ep93xx_adc.c
> >
> > +ARM/CIX SKY ARM ARCHITECTURE
> > +M:   Peter Chen <peter.chen at cixtech.com>
> > +M:   Fugang Duan <fugang.duan at cixtech.com>
> > +R:   CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
> > +L:   linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > +S:   Maintained
> > +F:   Documentation/devicetree/bindings/arm/cix.yaml
> > +F:   arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> > +F:   arch/arm64/boot/dts/cix/sky1.dtsi
> 
> Instead:
> arch/arm64/boot/dts/cix/
> 
> or if you think there will be more different architectures coming from
> cix, which you will not maintain, then useful would be a "sky" subdirectory.
> 
Hi Krzysztof,

Thanks for your comment, CIX is Arm SoC based silicon design
company, we may have different SoC style for middle end in future.
So, for that SoC series, it may not name sky.

-- 

Best regards,
Peter


From funderscore at postmarketos.org  Thu Mar 20 04:03:38 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Thu, 20 Mar 2025 11:03:38 +0000
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for
 xiaomi-aquaman/Mi TV Stick
In-Reply-To: <CAFBinCArRO-F59tOv9m27f+DV+qhy69OGUunGOAbDdfOdd5_Xg@mail.gmail.com>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
 <20250319190150.31529-4-funderscore@postmarketos.org>
 <CAFBinCArRO-F59tOv9m27f+DV+qhy69OGUunGOAbDdfOdd5_Xg@mail.gmail.com>
Message-ID: <D8L1KOJC0NJD.3QJBLQ0Z1FI62@postmarketos.org>

On Wed Mar 19, 2025 at 10:36 PM UTC, Martin Blumenstingl wrote:
> Hello,
>
> thanks for your contribution and sorry for the late reply!
>
> On Wed, Mar 19, 2025 at 8:02?PM Ferass El Hafidi
> <funderscore at postmarketos.org> wrote:
> [...]
> > +       au2: analog-amplifier {
> > +               compatible = "simple-audio-amplifier";
> > +               sound-name-prefix = "AU2";
> > +               VCC-supply = <&vcc_5v>;
> > +               enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
> > +       };
> I couldn't find any pictures online that show an analog audio output
> (typically a 3.5mm socket).
> Can you confirm that this is really present?
>
> [...]
> > +       sound {
> > +               compatible = "amlogic,gx-sound-card";
> > +               model = "XIAOMI-AQUAMAN";
> > +               audio-aux-devs = <&au2>;
> > +               audio-widgets = "Line", "Lineout";
> > +               audio-routing = "AU2 INL", "ACODEC LOLN",
> > +                               "AU2 INR", "ACODEC LORN",
> > +                               "Lineout", "AU2 OUTL",
> > +                               "Lineout", "AU2 OUTR";
> If there's no analog audio in/out then this section can be cleaned up
> as well - together with the references to acodec in the dai-links
> below.

Oops, completely overlooked those.  Will fix in v6.  There indeed is no 
analog audio output.

>
> [...]
> > +/* Wireless SDIO Module (Amlogic W155S1 / Realtek RTL8821CS) */
> > +&sd_emmc_b {
> question to Neil: since we know that there's two board variants out
> there (with different wifi chipsets) - are dt overlays down the road
> enough (to enable Bluetooth / wifi - depending on the chipset or board
> revision) or do we need to split the whole .dts?
>

So far W155S1 and RTL8821CS are the *known* chipsets used, but there may 
be others.  Right now it's not my main concern, as W155S1 is not
supported in Mainline, as far as I know, and I can't test RTL8821CS
because my variant seems to have the former.

>
> Best regards,
> Martin

Regards.


From ryan.roberts at arm.com  Thu Mar 20 04:24:50 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 20 Mar 2025 11:24:50 +0000
Subject: [RFC PATCH] arm64/mm: Remove randomization of the linear map
In-Reply-To: <CAMj1kXHXAYt0xLnx4=+qiCbnuF5U+9dzwnds1yd+vhTtpP5v3Q@mail.gmail.com>
References: <20250318134949.3194334-2-ardb+git@google.com>
 <CAMj1kXHXAYt0xLnx4=+qiCbnuF5U+9dzwnds1yd+vhTtpP5v3Q@mail.gmail.com>
Message-ID: <2cb92aaf-900e-4a30-beeb-50081afc85ec@arm.com>

On 20/03/2025 07:57, Ard Biesheuvel wrote:
> On Tue, 18 Mar 2025 at 14:50, Ard Biesheuvel <ardb+git at google.com> wrote:
>>
>> From: Ard Biesheuvel <ardb at kernel.org>
>>
>> Since commit
>>
>>   97d6786e0669 ("arm64: mm: account for hotplug memory when randomizing the linear region")
>>
>> the decision whether or not to randomize the placement of the system's
>> DRAM inside the linear map is based on the capabilities of the CPU
>> rather than how much memory is present at boot time. This change was
>> necessary because memory hotplug may result in DRAM appearing in places
>> that are not covered by the linear region at all (and therefore
>> unusable) if the decision is solely based on the memory map at boot.
>>
>> In the Android GKI kernel, which requires support for memory hotplug,
>> and is built with a reduced virtual address space of only 39 bits wide,
>> randomization of the linear map never happens in practice as a result.
>> And even on arm64 kernels built with support for 48 bit virtual
>> addressing, the wider PArange of recent CPUs means that linear map
>> randomization is slowly becoming a feature that only works on systems
>> that will soon be obsolete.
>>
>> So let's just remove this feature. We can always bring it back in an
>> improved form if there is a real need for it.

The argument certainly makes sense to me.

>>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
>> Cc: Kees Cook <kees at kernel.org>
>> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> 
> Additional note based on an off-list discussion with Kees and the KSPP team:
> 
> Initially, the randomization of the linear map was considered to be a
> layer of defense against the abuse of writable linear aliases of
> read-only mappings in the vmalloc range, such as module text and
> rodata. 

I would have assumed that there is already a level of randomization for this use
case because vmalloc will be allocating random pages from the buddy, so the
location of a given vmalloc alias in the linear map is already somewhat random?

Perhaps the regions of interest are allocated early in boot when the pages the
buddy gives you are still pretty predictable? In this case could there be any
argument for adding a capability to the buddy to give out somewhat randomised
pages, at least during boot?

> This has been addressed in the meantime, by mapping the linear
> region down to pages by default, and mapping linear aliases read-only
> if the vmalloc mapping is read-only.
> 
> So considering that, and the fact that randomization of the linear map
> occurs rarely if at all on recent CPUs, I think we should go ahead and
> remove this feature.



From matt.coster at imgtec.com  Thu Mar 20 04:32:11 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:11 +0000
Subject: [PATCH v4 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-1-d987cf4ca439@imgtec.com>

The first compatible strings added for the AXE-1-16M are not sufficient to
accurately describe all the IMG Rogue GPUs. The current "img,img-axe"
string refers to the entire family of Series AXE GPUs, but this is
primarily a marketing term and does not denote a level of hardware
similarity any greater than just "Rogue".

The more specific "img,img-axe-1-16m" string refers to individual AXE-1-16M
GPU. For example, unlike the rest of the Series AXE GPUs, the AXE-1-16M
only uses a single power domain.

The situation is actually slightly worse than described in the first
paragraph, since many "series" (such as Series BXS found in the TI AM68
among others and added later in this series) contain cores with both Rogue
and Volcanic architectures.

Besides attempting to move away from vague groupings defined only
by marketing terms, we want to draw a line between properties inherent to
the IP core and choices made by the silicon vendor at integration time.
For instance, the number of power domains is a property of the IP core,
whereas the decision to use one or multiple clocks is a vendor one.

In the original compatible strings, we must use "ti,am62-gpu" to constrain
both of these properties since the number of power domains cannot be fixed
for "img,img-axe".

Work is currently underway to add support for volcanic-based Imagination
GPUs, for which bindings will be added in "img,powervr-volcanic.yaml".
As alluded to previously, the split between rogue and volcanic cores is
non-obvious at times, so add a generic top-level "img,img-rogue" compatible
string here to allow for simpler differentiation in devicetrees without
referring back to the bindings.

The currently supported GPU (AXE-1-16M) only requires a single power
domain. Subsequent patches will add support for BXS-4-64 MC1, which has
two power domains. Add infrastructure now to allow for this.

Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
are DMA devices. The decision for coherency is made at integration time and
this property should be applied wherever it accurately describes the
vendor integration.

Note that the new required properties for power domains are conditional on
the new base compatible string to avoid an ABI break.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- Add img,img-rogue back to ti,am62-gpu compatible strings to allow
  compatibility with older kernels
- Revert change to power-domains property and add proper constraint
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f at imgtec.com
Changes in v3:
- Remove unnecessary example
- Remove second power domain details, add these where they're used instead
- Avoid ABI breaks by limiting new required properties to new compatible
  strings and making all binding changes in a single patch.
- Links to v2:
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
  https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
---
 .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 44 +++++++++++++++++++---
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 256e252f8087fa0d6081f771a01601d34b66fe19..2a692feb5bcd526788117fce7934eef9521b364d 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -12,10 +12,23 @@ maintainers:
 
 properties:
   compatible:
-    items:
-      - enum:
-          - ti,am62-gpu
-      - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
+    oneOf:
+      - items:
+          - enum:
+              - ti,am62-gpu
+          - const: img,img-axe-1-16m
+          # This deprecated element must be kept around to allow old kernels to
+          # work with newer dts.
+          - const: img,img-axe
+          - const: img,img-rogue
+
+      # This legacy combination of compatible strings was introduced early on
+      # before the more specific GPU identifiers were used.
+      - items:
+          - enum:
+              - ti,am62-gpu
+          - const: img,img-axe
+        deprecated: true
 
   reg:
     maxItems: 1
@@ -35,8 +48,15 @@ properties:
     maxItems: 1
 
   power-domains:
+    minItems: 1
     maxItems: 1
 
+  power-domain-names:
+    items:
+      - const: a
+
+  dma-coherent: true
+
 required:
   - compatible
   - reg
@@ -47,6 +67,18 @@ required:
 additionalProperties: false
 
 allOf:
+  # Constraints added alongside the new compatible strings that would otherwise
+  # create an ABI break.
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: img,img-rogue
+    then:
+      required:
+        - power-domains
+        - power-domain-names
+
   - if:
       properties:
         compatible:
@@ -64,10 +96,12 @@ examples:
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
     gpu at fd00000 {
-        compatible = "ti,am62-gpu", "img,img-axe";
+        compatible = "ti,am62-gpu", "img,img-axe-1-16m", "img,img-axe",
+                     "img,img-rogue";
         reg = <0x0fd00000 0x20000>;
         clocks = <&k3_clks 187 0>;
         clock-names = "core";
         interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
         power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+        power-domain-names = "a";
     };

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:13 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:13 +0000
Subject: [PATCH v4 03/18] drm/imagination: Update register defs for newer
 GPUs
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-3-d987cf4ca439@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Update the register define header to a newer version that covers more
recent GPUs, including BXS-4-64.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-3-143b3dbef02f at imgtec.com
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h | 153 +++++++++++++++++++++---
 1 file changed, 134 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h b/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
index 2a90d02796d3e071b18e18dead105e29798bcddc..790c97f80a2ac03ac76b933d009a2f9cfc6003f7 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h
@@ -827,6 +827,120 @@
 #define ROGUE_CR_EVENT_STATUS_TLA_COMPLETE_CLRMSK 0xFFFFFFFEU
 #define ROGUE_CR_EVENT_STATUS_TLA_COMPLETE_EN 0x00000001U
 
+/* Register ROGUE_CR_EVENT_CLEAR */
+#define ROGUE_CR_EVENT_CLEAR 0x0138U
+#define ROGUE_CR_EVENT_CLEAR__ROGUEXE__MASKFULL 0x00000000E01DFFFFULL
+#define ROGUE_CR_EVENT_CLEAR__SIGNALS__MASKFULL 0x00000000E007FFFFULL
+#define ROGUE_CR_EVENT_CLEAR_MASKFULL 0x00000000FFFFFFFFULL
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_SHIFT 31U
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_CLRMSK 0x7FFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_FENCE_FINISHED_EN 0x80000000U
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_SHIFT 30U
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_CLRMSK 0xBFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_BUFFER_STALL_EN 0x40000000U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_SHIFT 29U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_CLRMSK 0xDFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_SIGNAL_FAILURE_EN 0x20000000U
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_SHIFT 28U
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_CLRMSK 0xEFFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_DPX_OUT_OF_MEMORY_EN 0x10000000U
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_SHIFT 27U
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_CLRMSK 0xF7FFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_DPX_MMU_PAGE_FAULT_EN 0x08000000U
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_SHIFT 26U
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_CLRMSK 0xFBFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RPM_OUT_OF_MEMORY_EN 0x04000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_SHIFT 25U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_CLRMSK 0xFDFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC3_FINISHED_EN 0x02000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_SHIFT 24U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_CLRMSK 0xFEFFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC2_FINISHED_EN 0x01000000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_SHIFT 23U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_CLRMSK 0xFF7FFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC1_FINISHED_EN 0x00800000U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_SHIFT 22U
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_CLRMSK 0xFFBFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_FBA_FC0_FINISHED_EN 0x00400000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_SHIFT 21U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_CLRMSK 0xFFDFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC3_FINISHED_EN 0x00200000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_SHIFT 20U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_CLRMSK 0xFFEFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC2_FINISHED_EN 0x00100000U
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_SHIFT 20U
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_CLRMSK 0xFFEFFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SAFETY_EN 0x00100000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_SHIFT 19U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_CLRMSK 0xFFF7FFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC1_FINISHED_EN 0x00080000U
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_SHIFT 19U
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_CLRMSK 0xFFF7FFFFU
+#define ROGUE_CR_EVENT_CLEAR_SLAVE_REQ_EN 0x00080000U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_SHIFT 18U
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_CLRMSK 0xFFFBFFFFU
+#define ROGUE_CR_EVENT_CLEAR_RDM_FC0_FINISHED_EN 0x00040000U
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_SHIFT 18U
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_CLRMSK 0xFFFBFFFFU
+#define ROGUE_CR_EVENT_CLEAR_TDM_CONTEXT_STORE_FINISHED_EN 0x00040000U
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_SHIFT 17U
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_CLRMSK 0xFFFDFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SHG_FINISHED_EN 0x00020000U
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_SHIFT 17U
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_CLRMSK 0xFFFDFFFFU
+#define ROGUE_CR_EVENT_CLEAR_SPFILTER_SIGNAL_UPDATE_EN 0x00020000U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_SHIFT 16U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_BUFFER_STALL_EN 0x00010000U
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_SHIFT 15U
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_CLRMSK 0xFFFF7FFFU
+#define ROGUE_CR_EVENT_CLEAR_USC_TRIGGER_EN 0x00008000U
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_SHIFT 14U
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_CLRMSK 0xFFFFBFFFU
+#define ROGUE_CR_EVENT_CLEAR_ZLS_FINISHED_EN 0x00004000U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_SHIFT 13U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_CLRMSK 0xFFFFDFFFU
+#define ROGUE_CR_EVENT_CLEAR_GPIO_ACK_EN 0x00002000U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_SHIFT 12U
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_CLRMSK 0xFFFFEFFFU
+#define ROGUE_CR_EVENT_CLEAR_GPIO_REQ_EN 0x00001000U
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_SHIFT 11U
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_CLRMSK 0xFFFFF7FFU
+#define ROGUE_CR_EVENT_CLEAR_POWER_ABORT_EN 0x00000800U
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_SHIFT 10U
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_CLRMSK 0xFFFFFBFFU
+#define ROGUE_CR_EVENT_CLEAR_POWER_COMPLETE_EN 0x00000400U
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_SHIFT 9U
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_CLRMSK 0xFFFFFDFFU
+#define ROGUE_CR_EVENT_CLEAR_MMU_PAGE_FAULT_EN 0x00000200U
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_SHIFT 8U
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_CLRMSK 0xFFFFFEFFU
+#define ROGUE_CR_EVENT_CLEAR_PM_3D_MEM_FREE_EN 0x00000100U
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_SHIFT 7U
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_CLRMSK 0xFFFFFF7FU
+#define ROGUE_CR_EVENT_CLEAR_PM_OUT_OF_MEMORY_EN 0x00000080U
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_SHIFT 6U
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_CLRMSK 0xFFFFFFBFU
+#define ROGUE_CR_EVENT_CLEAR_TA_TERMINATE_EN 0x00000040U
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_SHIFT 5U
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_CLRMSK 0xFFFFFFDFU
+#define ROGUE_CR_EVENT_CLEAR_TA_FINISHED_EN 0x00000020U
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_SHIFT 4U
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_CLRMSK 0xFFFFFFEFU
+#define ROGUE_CR_EVENT_CLEAR_ISP_END_MACROTILE_EN 0x00000010U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_SHIFT 3U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_CLRMSK 0xFFFFFFF7U
+#define ROGUE_CR_EVENT_CLEAR_PIXELBE_END_RENDER_EN 0x00000008U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_SHIFT 2U
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_CLRMSK 0xFFFFFFFBU
+#define ROGUE_CR_EVENT_CLEAR_COMPUTE_FINISHED_EN 0x00000004U
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_SHIFT 1U
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_CLRMSK 0xFFFFFFFDU
+#define ROGUE_CR_EVENT_CLEAR_KERNEL_FINISHED_EN 0x00000002U
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_SHIFT 0U
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_EVENT_CLEAR_TLA_COMPLETE_EN 0x00000001U
+
 /* Register ROGUE_CR_TIMER */
 #define ROGUE_CR_TIMER 0x0160U
 #define ROGUE_CR_TIMER_MASKFULL 0x8000FFFFFFFFFFFFULL
@@ -6031,25 +6145,6 @@
 #define ROGUE_CR_MULTICORE_COMPUTE_CTRL_COMMON_GPU_ENABLE_SHIFT 0U
 #define ROGUE_CR_MULTICORE_COMPUTE_CTRL_COMMON_GPU_ENABLE_CLRMSK 0xFFFFFF00U
 
-/* Register ROGUE_CR_ECC_RAM_ERR_INJ */
-#define ROGUE_CR_ECC_RAM_ERR_INJ 0xF340U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MASKFULL 0x000000000000001FULL
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_SHIFT 4U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_CLRMSK 0xFFFFFFEFU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_SLC_SIDEKICK_EN 0x00000010U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_SHIFT 3U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_CLRMSK 0xFFFFFFF7U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_USC_EN 0x00000008U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_SHIFT 2U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_CLRMSK 0xFFFFFFFBU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_EN 0x00000004U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_SHIFT 1U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_CLRMSK 0xFFFFFFFDU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_RASCAL_EN 0x00000002U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_SHIFT 0U
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_CLRMSK 0xFFFFFFFEU
-#define ROGUE_CR_ECC_RAM_ERR_INJ_MARS_EN 0x00000001U
-
 /* Register ROGUE_CR_ECC_RAM_INIT_KICK */
 #define ROGUE_CR_ECC_RAM_INIT_KICK 0xF348U
 #define ROGUE_CR_ECC_RAM_INIT_KICK_MASKFULL 0x000000000000001FULL
@@ -6163,6 +6258,26 @@
 #define ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE__GPU_PAGE_FAULT_CLRMSK 0xFFFFFFFEU
 #define ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE__GPU_PAGE_FAULT_EN 0x00000001U
 
+/* Register ROGUE_CR_FAULT_FW_STATUS */
+#define ROGUE_CR_FAULT_FW_STATUS 0xF3B0U
+#define ROGUE_CR_FAULT_FW_STATUS_MASKFULL 0x0000000000010001ULL
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_SHIFT 16U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_CORRECT_EN 0x00010000U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_SHIFT 0U
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_FAULT_FW_STATUS_CPU_DETECT_EN 0x00000001U
+
+/* Register ROGUE_CR_FAULT_FW_CLEAR */
+#define ROGUE_CR_FAULT_FW_CLEAR 0xF3B8U
+#define ROGUE_CR_FAULT_FW_CLEAR_MASKFULL 0x0000000000010001ULL
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_SHIFT 16U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_CLRMSK 0xFFFEFFFFU
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_CORRECT_EN 0x00010000U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_SHIFT 0U
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_CLRMSK 0xFFFFFFFEU
+#define ROGUE_CR_FAULT_FW_CLEAR_CPU_DETECT_EN 0x00000001U
+
 /* Register ROGUE_CR_MTS_SAFETY_EVENT_ENABLE */
 #define ROGUE_CR_MTS_SAFETY_EVENT_ENABLE__ROGUEXE 0xF3D8U
 #define ROGUE_CR_MTS_SAFETY_EVENT_ENABLE__ROGUEXE__MASKFULL 0x000000000000007FULL

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:22 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:22 +0000
Subject: [PATCH v4 12/18] drm/imagination: Use callbacks for fw irq
 handling
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-12-d987cf4ca439@imgtec.com>

This allows for more versatility in checking and clearing firmware
registers used for interrupt handling.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-12-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-14-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-14-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h  | 18 +++++++++++++
 drivers/gpu/drm/imagination/pvr_fw.h      | 45 +++++++++----------------------
 drivers/gpu/drm/imagination/pvr_fw_meta.c | 22 ++++++++++-----
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 22 ++++++++++-----
 4 files changed, 63 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 12bf0b9e5bfb48ef9e5ed9faa44e0896b7555f49..eb5da8c7040fc9e9751f433279cb0c92fd4d1336 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -739,4 +739,22 @@ pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
 					      __union_size, __member_size);  \
 	})
 
+/*
+ * These utility functions should more properly be placed in pvr_fw.h, but that
+ * would cause a dependency cycle between that header and this one. Since
+ * they're primarily used in pvr_device.c, let's put them in here for now.
+ */
+
+static __always_inline bool
+pvr_fw_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_dev->fw_dev.defs->irq_pending(pvr_dev);
+}
+
+static __always_inline void
+pvr_fw_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_dev->fw_dev.defs->irq_clear(pvr_dev);
+}
+
 #endif /* PVR_DEVICE_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 88ad713468ce3a1ee459b04dde5363c24791a4f1..ab69f40a7fbc6304171f16dd16d825a68b0362a5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -167,29 +167,22 @@ struct pvr_fw_defs {
 	int (*wrapper_init)(struct pvr_device *pvr_dev);
 
 	/**
-	 * @irq: FW Interrupt information.
+	 * @irq_pending: Check interrupt status register for pending interrupts.
 	 *
-	 * Those are processor dependent, and should be initialized by the
-	 * processor backend in pvr_fw_funcs::init().
+	 * @pvr_dev: Target PowerVR device.
+	 *
+	 * This function is mandatory.
 	 */
-	struct {
-		/** @status_reg: FW interrupt status register. */
-		u32 status_reg;
+	bool (*irq_pending)(struct pvr_device *pvr_dev);
 
-		/**
-		 * @clear_reg: FW interrupt clear register.
-		 *
-		 * If @status_reg == @clear_reg, we clear by write a bit to zero,
-		 * otherwise we clear by writing a bit to one.
-		 */
-		u32 clear_reg;
-
-		/** @status_mask: Bitmask of events to listen for in the status_reg. */
-		u32 status_mask;
-
-		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
-		u32 clear_mask;
-	} irq;
+	/**
+	 * @irq_clear: Clear pending interrupts.
+	 *
+	 * @pvr_dev: Target PowerVR device.
+	 *
+	 * This function is mandatory.
+	 */
+	void (*irq_clear)(struct pvr_device *pvr_dev);
 
 	/**
 	 * @has_fixed_data_addr: Specify whether the firmware fixed data must be loaded at the
@@ -390,18 +383,6 @@ struct pvr_fw_device {
 	} fw_objs;
 };
 
-#define pvr_fw_irq_read_reg(pvr_dev, name) \
-	pvr_cr_read32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg)
-
-#define pvr_fw_irq_write_reg(pvr_dev, name, value) \
-	pvr_cr_write32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg, value)
-
-#define pvr_fw_irq_pending(pvr_dev) \
-	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.status_mask)
-
-#define pvr_fw_irq_clear(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
-
 enum pvr_fw_processor_type {
 	PVR_FW_PROCESSOR_TYPE_META = 0,
 	PVR_FW_PROCESSOR_TYPE_MIPS,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index 62ddfea6b7306784b979ce209bfdf4a9938f8984..d72e0eae9e4b16cb31c48797ffcf5138d2728862 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -533,6 +533,20 @@ pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			 fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size);
 }
 
+static bool
+pvr_meta_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_META_SP_MSLVIRQSTATUS) &
+	       ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN;
+}
+
+static void
+pvr_meta_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_META_SP_MSLVIRQSTATUS,
+		       ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
+}
+
 const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.init = pvr_meta_init,
 	.fw_process = pvr_meta_fw_process,
@@ -540,11 +554,7 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.vm_unmap = pvr_meta_vm_unmap,
 	.get_fw_addr_with_offset = pvr_meta_get_fw_addr_with_offset,
 	.wrapper_init = pvr_meta_wrapper_init,
-	.irq = {
-		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
-		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
-	},
+	.irq_pending = pvr_meta_irq_pending,
+	.irq_clear = pvr_meta_irq_clear,
 	.has_fixed_data_addr = false,
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 2c3172841886b70eb7a9992ec3851f18adcad8d5..524a9bd0a20b64c509f5708cc61d93b4c864b835 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -227,6 +227,20 @@ pvr_mips_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
 	       ROGUE_FW_HEAP_MIPS_BASE;
 }
 
+static bool
+pvr_mips_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS) &
+	       ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN;
+}
+
+static void
+pvr_mips_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
+		       ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN);
+}
+
 const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.init = pvr_mips_init,
 	.fini = pvr_mips_fini,
@@ -235,11 +249,7 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.vm_unmap = pvr_vm_mips_unmap,
 	.get_fw_addr_with_offset = pvr_mips_get_fw_addr_with_offset,
 	.wrapper_init = pvr_mips_wrapper_init,
-	.irq = {
-		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
-		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
-		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
-		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
-	},
+	.irq_pending = pvr_mips_irq_pending,
+	.irq_clear = pvr_mips_irq_clear,
 	.has_fixed_data_addr = true,
 };

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:15 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:15 +0000
Subject: [PATCH v4 05/18] drm/imagination: Add power domain control
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-5-d987cf4ca439@imgtec.com>

The first supported GPU only used a single power domain so this was
automatically handled by the device runtime.

In order to support multiple power domains, they must be enumerated from
devicetree and linked to both the GPU device and each other to ensure
correct power sequencing at start time.

For all Imagination Rogue GPUs, power domains are named "a", "b", etc. and
the sequence A->B->... is always valid for startup with the reverse true
for shutdown. Note this is not always the *only* valid sequence, but it's
simple and does not require special-casing for different GPU power
topologies.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-5-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-6-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-6-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h |   8 +++
 drivers/gpu/drm/imagination/pvr_drv.c    |   7 ++
 drivers/gpu/drm/imagination/pvr_power.c  | 114 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_power.h  |   3 +
 4 files changed, 132 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 6d0dfacb677b46a880f37f419dfa7b67c68fe63d..2dd8a8885fe07078896d669d822525fb2b7bab51 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -18,6 +18,7 @@
 #include <linux/bits.h>
 #include <linux/compiler_attributes.h>
 #include <linux/compiler_types.h>
+#include <linux/device.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
@@ -131,6 +132,13 @@ struct pvr_device {
 	 */
 	struct clk *mem_clk;
 
+	struct pvr_device_power {
+		struct device **domain_devs;
+		struct device_link **domain_links;
+
+		u32 domain_count;
+	} power;
+
 	/** @irq: IRQ number. */
 	int irq;
 
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 3130193f8fffc185e630a293be53374bdc4b7ce0..ac4f5855c5692f0956862cebdbf76b16d8da9a81 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1411,6 +1411,10 @@ pvr_probe(struct platform_device *plat_dev)
 
 	platform_set_drvdata(plat_dev, drm_dev);
 
+	err = pvr_power_domains_init(pvr_dev);
+	if (err)
+		return err;
+
 	init_rwsem(&pvr_dev->reset_sem);
 
 	pvr_context_device_init(pvr_dev);
@@ -1450,6 +1454,8 @@ pvr_probe(struct platform_device *plat_dev)
 err_context_fini:
 	pvr_context_device_fini(pvr_dev);
 
+	pvr_power_domains_fini(pvr_dev);
+
 	return err;
 }
 
@@ -1470,6 +1476,7 @@ static void pvr_remove(struct platform_device *plat_dev)
 	pvr_watchdog_fini(pvr_dev);
 	pvr_queue_device_fini(pvr_dev);
 	pvr_context_device_fini(pvr_dev);
+	pvr_power_domains_fini(pvr_dev);
 }
 
 static const struct of_device_id dt_match[] = {
diff --git a/drivers/gpu/drm/imagination/pvr_power.c b/drivers/gpu/drm/imagination/pvr_power.c
index ba7816fd28ec77e6ca5ce408302a413ce1afeb6e..19b079b357df78e8bcdecfa377fc9c05b6e8e4b0 100644
--- a/drivers/gpu/drm/imagination/pvr_power.c
+++ b/drivers/gpu/drm/imagination/pvr_power.c
@@ -10,10 +10,13 @@
 
 #include <drm/drm_drv.h>
 #include <drm/drm_managed.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/timer.h>
 #include <linux/types.h>
@@ -431,3 +434,114 @@ pvr_watchdog_fini(struct pvr_device *pvr_dev)
 {
 	cancel_delayed_work_sync(&pvr_dev->watchdog.work);
 }
+
+int pvr_power_domains_init(struct pvr_device *pvr_dev)
+{
+	struct device *dev = from_pvr_device(pvr_dev)->dev;
+
+	struct device_link **domain_links __free(kfree) = NULL;
+	struct device **domain_devs __free(kfree) = NULL;
+	int domain_count;
+	int link_count;
+
+	char dev_name[2] = "a";
+	int err;
+	int i;
+
+	domain_count = of_count_phandle_with_args(dev->of_node, "power-domains",
+						  "#power-domain-cells");
+	if (domain_count < 0)
+		return domain_count;
+
+	if (domain_count <= 1)
+		return 0;
+
+	link_count = domain_count + (domain_count - 1);
+
+	domain_devs = kcalloc(domain_count, sizeof(*domain_devs), GFP_KERNEL);
+	if (!domain_devs)
+		return -ENOMEM;
+
+	domain_links = kcalloc(link_count, sizeof(*domain_links), GFP_KERNEL);
+	if (!domain_links)
+		return -ENOMEM;
+
+	for (i = 0; i < domain_count; i++) {
+		struct device *domain_dev;
+
+		dev_name[0] = 'a' + i;
+		domain_dev = dev_pm_domain_attach_by_name(dev, dev_name);
+		if (IS_ERR_OR_NULL(domain_dev)) {
+			err = domain_dev ? PTR_ERR(domain_dev) : -ENODEV;
+			goto err_detach;
+		}
+
+		domain_devs[i] = domain_dev;
+	}
+
+	for (i = 0; i < domain_count; i++) {
+		struct device_link *link;
+
+		link = device_link_add(dev, domain_devs[i], DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+		if (!link) {
+			err = -ENODEV;
+			goto err_unlink;
+		}
+
+		domain_links[i] = link;
+	}
+
+	for (i = domain_count; i < link_count; i++) {
+		struct device_link *link;
+
+		link = device_link_add(domain_devs[i - domain_count + 1],
+				       domain_devs[i - domain_count],
+				       DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+		if (!link) {
+			err = -ENODEV;
+			goto err_unlink;
+		}
+
+		domain_links[i] = link;
+	}
+
+	pvr_dev->power = (struct pvr_device_power){
+		.domain_devs = no_free_ptr(domain_devs),
+		.domain_links = no_free_ptr(domain_links),
+		.domain_count = domain_count,
+	};
+
+	return 0;
+
+err_unlink:
+	while (--i >= 0)
+		device_link_del(domain_links[i]);
+
+	i = domain_count;
+
+err_detach:
+	while (--i >= 0)
+		dev_pm_domain_detach(domain_devs[i], true);
+
+	return err;
+}
+
+void pvr_power_domains_fini(struct pvr_device *pvr_dev)
+{
+	const int domain_count = pvr_dev->power.domain_count;
+
+	int i = domain_count + (domain_count - 1);
+
+	while (--i >= 0)
+		device_link_del(pvr_dev->power.domain_links[i]);
+
+	i = domain_count;
+
+	while (--i >= 0)
+		dev_pm_domain_detach(pvr_dev->power.domain_devs[i], true);
+
+	kfree(pvr_dev->power.domain_links);
+	kfree(pvr_dev->power.domain_devs);
+
+	pvr_dev->power = (struct pvr_device_power){ 0 };
+}
diff --git a/drivers/gpu/drm/imagination/pvr_power.h b/drivers/gpu/drm/imagination/pvr_power.h
index 9a9312dcb2dab7d36ee8ff7f69e69d126c5469a9..ada85674a7ca762dcf92df40424230e1c3910342 100644
--- a/drivers/gpu/drm/imagination/pvr_power.h
+++ b/drivers/gpu/drm/imagination/pvr_power.h
@@ -38,4 +38,7 @@ pvr_power_put(struct pvr_device *pvr_dev)
 	return pm_runtime_put(drm_dev->dev);
 }
 
+int pvr_power_domains_init(struct pvr_device *pvr_dev);
+void pvr_power_domains_fini(struct pvr_device *pvr_dev);
+
 #endif /* PVR_POWER_H */

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:10 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:10 +0000
Subject: [PATCH v4 00/18] Imagination BXS-4-64 MC1 GPU support
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>

This GPU is found in the TI AM68 family of SoCs, with initial support
added to the k3-j721s2 devicetree and tested on a TI SK-AM68 board.

A suitable firmware binary can currently be found in the IMG
linux-firmware repository[1] as powervr/rogue_36.53.104.796_v1.fw.

No new UAPI will be necessary for this platform as it is sufficiently
similar to the already supported AXE-1-16M.

UMD support is close to being complete. We're now able to pass >92% of
Vulkan conformance on our Mesa development branch. The compiler has been
undergoing a significant rework needed to accomodate the BXS-4-64, as
well as to make it more flexible to support additional Rogue GPUs going
forward. The first part of this rework landed in Mesa in [2], and the
next chunk is currently in review in [3].

There are several dt-bindings changes at the beginning of this series.
We expect the result to be versatile enough to handle all Imagination
Rogue GPUs while being a strong foundation to build bindings for the
newer Volcanic architecture (for which we're currently developing
support).

The DTS changes at the end of the series are marked [DO NOT MERGE]. Once
the series is reviewed, we will request these be taken through the
relevant tree.

This version of the series depends on a patch[4] which exists in
drm-misc-fixes, but has not yet made it back to drm-misc-next (the
target of this series). That patch adds the function pvr_vm_unmap_obj()
which is used in patch 14 ("drm/imagination: Add RISC-V firmware
processor support").

[1]: https://gitlab.freedesktop.org/imagination/linux-firmware/-/tree/powervr
[2]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258
[3]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33998
[4]: https://lore.kernel.org/r/20250226-hold-drm_gem_gpuva-lock-for-unmap-v2-1-3fdacded227f at imgtec.com

---
Changes in v4:
- Update status of UMD support (cover)
- Fix backwards compatibility of new compatible strings (P1)
- Fix power-domains property constraints (P1/P2)
- Fix power-domain-names property constraints (P2)
- Only invoke pvr_device_safety_irq_clear() if has_safety_events is set
  (P7)
- Use pvr_vm_unmap_obj() in pvr_riscv_vm_unmap() (P14)
- Fix formatting of pvr_riscv_fw_process() signature (P14)
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-0-143b3dbef02f at imgtec.com

Changes in v3:
- Reorder some patches to ensure the proper sequencing
- Update status of UMD support (cover)
- Don't use more specific compatible strings when not required (P1)
- Avoid ABI break by limiting new required properties to new compatible
  strings (P2)
- Move power domain changes to the patch in which they're used (P2/P5)
- Update register definitions (P3) [Thanks, Alessio!]
- Don't use more specific compatible strings when not required (P4)
- Enhanced commit messages (P4)
- Remove unnecessary example (P5)
- Add proper fixes for threaded IRQs (P6) [Thanks, Alessio!]
- Include fix for a separate IRQ issue (P7) [Thanks, Alessio!]
- Don't enable firmware debug module (was P13 in v2, also in P14)
- Change from a workaround to a regular codepath (P15)
- Drop platform overrides framework (was P18 in v2, also in P16)
- Mark DTS changes [DO NOT MERGE] (P17/P18)
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-0-3fd45d9fb0cf at imgtec.com

Changes in v2:
- Clarified justification for compatible strings (P1)
- Simplified clocks constraints (P2)
- Simplified power-domains constraints (P3/P4)
- Use normal reg syntax for 64-bit values (P8/P21)
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-0-4ed30e865892 at imgtec.com

---
Alessio Belle (3):
      drm/imagination: Update register defs for newer GPUs
      drm/imagination: Mask GPU IRQs in threaded handler
      drm/imagination: Handle Rogue safety event IRQs

Matt Coster (14):
      dt-bindings: gpu: img: Future-proofing enhancements
      dt-bindings: gpu: img: Add BXS-4-64 devicetree bindings
      drm/imagination: Use new generic compatible string
      drm/imagination: Add power domain control
      drm/imagination: Remove firmware enable_reg
      drm/imagination: Rename event_mask -> status_mask
      drm/imagination: Make has_fixed_data_addr a value
      drm/imagination: Use a lookup table for fw defs
      drm/imagination: Use callbacks for fw irq handling
      drm/imagination: Move ELF fw utils to common file
      drm/imagination: Use cached memory with dma_coherent
      drm/imagination: Add support for TI AM68 GPU
      [DO NOT MERGE] arm64: dts: ti: k3-am62: New GPU binding details
      [DO NOT MERGE] arm64: dts: ti: k3-j721s2: Add GPU node

Sarah Walker (1):
      drm/imagination: Add RISC-V firmware processor support

 .../devicetree/bindings/gpu/img,powervr-rogue.yaml |  81 +++++++++-
 arch/arm64/boot/dts/ti/k3-am62-main.dtsi           |   4 +-
 arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi         |  12 ++
 drivers/gpu/drm/imagination/Makefile               |   2 +
 drivers/gpu/drm/imagination/pvr_device.c           | 126 ++++++++++++++--
 drivers/gpu/drm/imagination/pvr_device.h           |  31 +++-
 drivers/gpu/drm/imagination/pvr_drv.c              |  16 ++
 drivers/gpu/drm/imagination/pvr_fw.c               |  28 +++-
 drivers/gpu/drm/imagination/pvr_fw.h               |  85 +++++------
 drivers/gpu/drm/imagination/pvr_fw_meta.c          |  23 +--
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  82 ++--------
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         | 165 +++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_fw_startstop.c     |  17 +++
 drivers/gpu/drm/imagination/pvr_fw_util.c          |  67 +++++++++
 drivers/gpu/drm/imagination/pvr_gem.c              |  10 +-
 drivers/gpu/drm/imagination/pvr_gem.h              |   6 +-
 drivers/gpu/drm/imagination/pvr_mmu.c              |   8 +-
 drivers/gpu/drm/imagination/pvr_power.c            | 114 ++++++++++++++
 drivers/gpu/drm/imagination/pvr_power.h            |   3 +
 drivers/gpu/drm/imagination/pvr_rogue_cr_defs.h    | 153 ++++++++++++++++---
 drivers/gpu/drm/imagination/pvr_rogue_riscv.h      |  41 +++++
 21 files changed, 896 insertions(+), 178 deletions(-)
---
base-commit: d034e6f7ea8ddc866d4ac59c104e18675b13975b
change-id: 20241021-sets-bxs-4-64-patch-v1-44cdf9cc555f



From matt.coster at imgtec.com  Thu Mar 20 04:32:16 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:16 +0000
Subject: [PATCH v4 06/18] drm/imagination: Mask GPU IRQs in threaded
 handler
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-6-d987cf4ca439@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Pass IRQF_ONESHOT flag to request_threaded_irq(), so that interrupts will
be masked by the kernel until the end of the threaded IRQ handler. Since
the calls to pvr_fw_irq_enable() and pvr_fw_irq_disable() are now
redundant, remove them.

Interrupts to the host from the soon-to-be-added RISC-V firmware
processors cannot be masked in hardware. This change allows us to continue
using the threaded handler in GPUs with a RISC-V firmware.

For simplicity, the same approach is taken for all firmware processors.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-6-143b3dbef02f at imgtec.com
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_device.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index 1704c0268589bdeb65fa6535f9ec63182b0a3e94..b6ce936f07c8bb26d240e50b72a1d991dbe4b045 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -169,8 +169,6 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 		ret = IRQ_HANDLED;
 	}
 
-	/* Unmask FW irqs before returning, so new interrupts can be received. */
-	pvr_fw_irq_enable(pvr_dev);
 	return ret;
 }
 
@@ -181,10 +179,6 @@ static irqreturn_t pvr_device_irq_handler(int irq, void *data)
 	if (!pvr_fw_irq_pending(pvr_dev))
 		return IRQ_NONE; /* Spurious IRQ - ignore. */
 
-	/* Mask the FW interrupts before waking up the thread. Will be unmasked
-	 * when the thread handler is done processing events.
-	 */
-	pvr_fw_irq_disable(pvr_dev);
 	return IRQ_WAKE_THREAD;
 }
 
@@ -213,9 +207,13 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 	pvr_fw_irq_clear(pvr_dev);
 	pvr_fw_irq_enable(pvr_dev);
 
+	/*
+	 * The ONESHOT flag ensures IRQs are masked while the thread handler is
+	 * running.
+	 */
 	return request_threaded_irq(pvr_dev->irq, pvr_device_irq_handler,
 				    pvr_device_irq_thread_handler,
-				    IRQF_SHARED, "gpu", pvr_dev);
+				    IRQF_SHARED | IRQF_ONESHOT, "gpu", pvr_dev);
 }
 
 /**

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:17 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:17 +0000
Subject: [PATCH v4 07/18] drm/imagination: Handle Rogue safety event IRQs
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-7-d987cf4ca439@imgtec.com>

From: Alessio Belle <alessio.belle at imgtec.com>

Extend interrupt handling logic to check for safety event IRQs, then clear
and handle them in the IRQ handler thread.

Safety events need to be checked and cleared with a different set of GPU
registers than those the IRQ handler has been using so far.

Only two safety events need to be handled on the host: FW fault (ECC error
correction or detection) and device watchdog timeout. Handling right now
simply consists of clearing any error and logging the event. If either of
these events results in an unrecoverable GPU or FW, the driver will
eventually attempt to recover from it e.g. via pvr_power_reset().

Note that Rogue GPUs may send interrupts to the host for all types of
safety events, not just the two above. For events not handled by the host,
clearing the associated interrupt is sufficient.

Signed-off-by: Alessio Belle <alessio.belle at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- Only invoke pvr_device_safety_irq_clear() if has_safety_events is set
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-7-143b3dbef02f at imgtec.com
Changes in v3:
- Added
---
 drivers/gpu/drm/imagination/pvr_device.c | 113 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/imagination/pvr_device.h |   3 +
 drivers/gpu/drm/imagination/pvr_fw.c     |   3 +
 3 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index b6ce936f07c8bb26d240e50b72a1d991dbe4b045..a47dd1dd82432f1d66ff90aca26b7b264f4068df 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -146,9 +146,61 @@ static void pvr_device_process_active_queues(struct pvr_device *pvr_dev)
 	mutex_unlock(&pvr_dev->queues.lock);
 }
 
+static bool pvr_device_safety_irq_pending(struct pvr_device *pvr_dev)
+{
+	u32 events;
+
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	events = pvr_cr_read32(pvr_dev, ROGUE_CR_EVENT_STATUS);
+
+	return (events & ROGUE_CR_EVENT_STATUS_SAFETY_EN) != 0;
+}
+
+static void pvr_device_safety_irq_clear(struct pvr_device *pvr_dev)
+{
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	pvr_cr_write32(pvr_dev, ROGUE_CR_EVENT_CLEAR,
+		       ROGUE_CR_EVENT_CLEAR_SAFETY_EN);
+}
+
+static void pvr_device_handle_safety_events(struct pvr_device *pvr_dev)
+{
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
+	u32 events;
+
+	WARN_ON_ONCE(!pvr_dev->has_safety_events);
+
+	events = pvr_cr_read32(pvr_dev, ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE);
+
+	/* Handle only these events on the host and leave the rest to the FW. */
+	events &= ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__FAULT_FW_EN |
+		ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__WATCHDOG_TIMEOUT_EN;
+
+	pvr_cr_write32(pvr_dev, ROGUE_CR_SAFETY_EVENT_CLEAR__ROGUEXE, events);
+
+	if (events & ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__FAULT_FW_EN) {
+		u32 fault_fw = pvr_cr_read32(pvr_dev, ROGUE_CR_FAULT_FW_STATUS);
+
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FAULT_FW_CLEAR, fault_fw);
+
+		drm_info(drm_dev, "Safety event: FW fault (mask=0x%08x)\n", fault_fw);
+	}
+
+	if (events & ROGUE_CR_SAFETY_EVENT_STATUS__ROGUEXE__WATCHDOG_TIMEOUT_EN) {
+		/*
+		 * The watchdog timer is disabled by the driver so this event
+		 * should never be fired.
+		 */
+		drm_info(drm_dev, "Safety event: Watchdog timeout\n");
+	}
+}
+
 static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 {
 	struct pvr_device *pvr_dev = data;
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
 	irqreturn_t ret = IRQ_NONE;
 
 	/* We are in the threaded handler, we can keep dequeuing events until we
@@ -164,24 +216,76 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
 			pvr_device_process_active_queues(pvr_dev);
 		}
 
-		pm_runtime_mark_last_busy(from_pvr_device(pvr_dev)->dev);
+		pm_runtime_mark_last_busy(drm_dev->dev);
 
 		ret = IRQ_HANDLED;
 	}
 
+	if (pvr_dev->has_safety_events) {
+		int err;
+
+		/*
+		 * Ensure the GPU is powered on since some safety events (such
+		 * as ECC faults) can happen outside of job submissions, which
+		 * are otherwise the only time a power reference is held.
+		 */
+		err = pvr_power_get(pvr_dev);
+		if (err) {
+			drm_err_ratelimited(drm_dev,
+					    "%s: could not take power reference (%d)\n",
+					    __func__, err);
+			return ret;
+		}
+
+		while (pvr_device_safety_irq_pending(pvr_dev)) {
+			pvr_device_safety_irq_clear(pvr_dev);
+			pvr_device_handle_safety_events(pvr_dev);
+
+			ret = IRQ_HANDLED;
+		}
+
+		pvr_power_put(pvr_dev);
+	}
+
 	return ret;
 }
 
 static irqreturn_t pvr_device_irq_handler(int irq, void *data)
 {
 	struct pvr_device *pvr_dev = data;
+	bool safety_irq_pending = false;
+
+	if (pvr_dev->has_safety_events)
+		safety_irq_pending = pvr_device_safety_irq_pending(pvr_dev);
 
-	if (!pvr_fw_irq_pending(pvr_dev))
+	if (!pvr_fw_irq_pending(pvr_dev) && !safety_irq_pending)
 		return IRQ_NONE; /* Spurious IRQ - ignore. */
 
 	return IRQ_WAKE_THREAD;
 }
 
+static void pvr_device_safety_irq_init(struct pvr_device *pvr_dev)
+{
+	u32 num_ecc_rams = 0;
+
+	/*
+	 * Safety events are an optional feature of the RogueXE platform. They
+	 * are only enabled if at least one of ECC memory or the watchdog timer
+	 * are present in HW. While safety events can be generated by other
+	 * systems, that will never happen if the above mentioned hardware is
+	 * not present.
+	 */
+	if (!PVR_HAS_FEATURE(pvr_dev, roguexe)) {
+		pvr_dev->has_safety_events = false;
+		return;
+	}
+
+	PVR_FEATURE_VALUE(pvr_dev, ecc_rams, &num_ecc_rams);
+
+	pvr_dev->has_safety_events =
+		num_ecc_rams > 0 || PVR_HAS_FEATURE(pvr_dev, watchdog_timer);
+}
+
 /**
  * pvr_device_irq_init() - Initialise IRQ required by a PowerVR device
  * @pvr_dev: Target PowerVR device.
@@ -199,6 +303,8 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 
 	init_waitqueue_head(&pvr_dev->kccb.rtn_q);
 
+	pvr_device_safety_irq_init(pvr_dev);
+
 	pvr_dev->irq = platform_get_irq(plat_dev, 0);
 	if (pvr_dev->irq < 0)
 		return pvr_dev->irq;
@@ -207,6 +313,9 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 	pvr_fw_irq_clear(pvr_dev);
 	pvr_fw_irq_enable(pvr_dev);
 
+	if (pvr_dev->has_safety_events)
+		pvr_device_safety_irq_clear(pvr_dev);
+
 	/*
 	 * The ONESHOT flag ensures IRQs are masked while the thread handler is
 	 * running.
diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 2dd8a8885fe07078896d669d822525fb2b7bab51..6c01d96657de6dc3904ef5ca28365f06cfe0f40b 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -308,6 +308,9 @@ struct pvr_device {
 	 *  struct pvr_file.
 	 */
 	spinlock_t ctx_list_lock;
+
+	/** @has_safety_events: Whether this device can raise safety events. */
+	bool has_safety_events;
 };
 
 /**
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index d09c4c68411627714c14dee5ed4e61b07baca1ba..555b5ca4a27de78ac092bf94c601d284abe41ea6 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -441,6 +441,9 @@ fw_runtime_cfg_init(void *cpu_ptr, void *priv)
 	runtime_cfg->active_pm_latency_persistant = true;
 	WARN_ON(PVR_FEATURE_VALUE(pvr_dev, num_clusters,
 				  &runtime_cfg->default_dusts_num_init) != 0);
+
+	/* Keep watchdog timer disabled. */
+	runtime_cfg->wdg_period_us = 0;
 }
 
 static void

-- 
2.49.0



From ajones at ventanamicro.com  Thu Mar 20 04:52:50 2025
From: ajones at ventanamicro.com (Andrew Jones)
Date: Thu, 20 Mar 2025 12:52:50 +0100
Subject: [PATCH v3 2/4] riscv: add support for SBI Supervisor Software
 Events extension
In-Reply-To: <b3fbd730-295f-4491-b0d6-d4e258941ae5@rivosinc.com>
References: <20241206163102.843505-1-cleger@rivosinc.com>
 <20241206163102.843505-3-cleger@rivosinc.com>
 <20250319-46b625cf8b771616d4c7c053@orel>
 <b3fbd730-295f-4491-b0d6-d4e258941ae5@rivosinc.com>
Message-ID: <20250320-5f9612f1b503c79c9b185b10@orel>

On Thu, Mar 20, 2025 at 09:16:07AM +0100, Cl?ment L?ger wrote:
> 
> 
> On 19/03/2025 18:08, Andrew Jones wrote:
> > On Fri, Dec 06, 2024 at 05:30:58PM +0100, Cl?ment L?ger wrote:
> > ...
> >> +int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cpu)
> >> +{
> >> +	void *stack;
> >> +
> >> +	arch_evt->evt_id = evt_id;
> >> +	stack = sse_stack_alloc(cpu, SSE_STACK_SIZE);
> >> +	if (!stack)
> >> +		return -ENOMEM;
> >> +
> >> +	arch_evt->stack = stack + SSE_STACK_SIZE;
> >> +
> >> +	if (sse_init_scs(cpu, arch_evt))
> >> +		goto free_stack;
> >> +
> >> +	if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
> >> +		arch_evt->interrupted_state_phys =
> >> +				per_cpu_ptr_to_phys(&arch_evt->interrupted);
> >> +	} else {
> >> +		arch_evt->interrupted_state_phys =
> >> +				virt_to_phys(&arch_evt->interrupted);
> >> +	}
> >> +
> >> +	return 0;
> > 
> > Hi Cl?ment,
> > 
> > Testing SSE support with tools/testing/selftests/kvm/riscv/sbi_pmu_test
> > led to an opensbi sbi_trap_error because the output_phys_lo address passed
> > to sbi_sse_read_attrs() wasn't a physical address. The reason is that
> > is_kernel_percpu_address() can only be used on static percpu addresses,
> > but local sse events get their percpu addresses with alloc_percpu(), so
> > is_kernel_percpu_address() was returning false even for local events. I
> > made the following changes to get things working.
> 
> Hi Andrew,
> 
> Did something changed recently ? Because I tested that when it was send
> (PMU + some kernel internal testsuite) and didn't saw that. Anyway, I'll
> respin it with your changes as well.

It depends on the kernel config. Configs that don't have many
alloc_percpu() calls prior to the one made by sse can work, because,
iiuc, alloc_percpu() will get its allocation from the percpu allocator's
first chunk until that chunck fills up. The first chunck is shared with
the static allocations.

Thanks,
drew

> 
> Thanks !
> 
> Cl?ment
> 
> > 
> > Thanks,
> > drew
> > 
> > diff --git a/arch/riscv/kernel/sse.c b/arch/riscv/kernel/sse.c
> > index b48ae69dad8d..f46893946086 100644
> > --- a/arch/riscv/kernel/sse.c
> > +++ b/arch/riscv/kernel/sse.c
> > @@ -100,12 +100,12 @@ int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cp
> >         if (sse_init_scs(cpu, arch_evt))
> >                 goto free_stack;
> > 
> > -       if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
> > +       if (sse_event_is_global(evt_id)) {
> >                 arch_evt->interrupted_state_phys =
> > -                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
> > +                               virt_to_phys(&arch_evt->interrupted);
> >         } else {
> >                 arch_evt->interrupted_state_phys =
> > -                               virt_to_phys(&arch_evt->interrupted);
> > +                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
> >         }
> > 
> >         return 0;
> > diff --git a/drivers/firmware/riscv/riscv_sse.c b/drivers/firmware/riscv/riscv_sse.c
> > index 511db9ad7a9e..fef375046f75 100644
> > --- a/drivers/firmware/riscv/riscv_sse.c
> > +++ b/drivers/firmware/riscv/riscv_sse.c
> > @@ -62,11 +62,6 @@ void sse_handle_event(struct sse_event_arch_data *arch_event,
> >                         ret);
> >  }
> > 
> > -static bool sse_event_is_global(u32 evt)
> > -{
> > -       return !!(evt & SBI_SSE_EVENT_GLOBAL);
> > -}
> > -
> >  static
> >  struct sse_event *sse_event_get(u32 evt)
> >  {
> > diff --git a/include/linux/riscv_sse.h b/include/linux/riscv_sse.h
> > index 16700677f1e8..06b757b036b0 100644
> > --- a/include/linux/riscv_sse.h
> > +++ b/include/linux/riscv_sse.h
> > @@ -8,6 +8,7 @@
> > 
> >  #include <linux/types.h>
> >  #include <linux/linkage.h>
> > +#include <asm/sbi.h>
> > 
> >  struct sse_event;
> >  struct pt_regs;
> > @@ -16,6 +17,11 @@ struct ghes;
> > 
> >  typedef int (sse_event_handler)(u32 event_num, void *arg, struct pt_regs *regs);
> > 
> > +static inline bool sse_event_is_global(u32 evt)
> > +{
> > +       return !!(evt & SBI_SSE_EVENT_GLOBAL);
> > +}
> > +
> >  #ifdef CONFIG_RISCV_SSE
> > 
> >  struct sse_event *sse_event_register(u32 event_num, u32 priority,
> 


From angelogioacchino.delregno at collabora.com  Thu Mar 20 04:53:00 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 12:53:00 +0100
Subject: [PATCH] ASoC: SOF: mediatek: Commonize duplicated functions
Message-ID: <20250320115300.137410-1-angelogioacchino.delregno@collabora.com>

In order to reduce duplication, move the ADSP mailbox callbacks
handle_reply(), handle_request(), and other common SOF callbacks
send_msg(), get_bar_index(), pcm_hw_params() and pcm_pointer()
to the mtk-adsp-common.c file.

This cleanup brings no functional differences.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 sound/soc/sof/mediatek/mt8186/mt8186.c   | 105 ++----------------
 sound/soc/sof/mediatek/mt8195/mt8195.c   | 105 ++----------------
 sound/soc/sof/mediatek/mtk-adsp-common.c | 130 +++++++++++++++++++++++
 sound/soc/sof/mediatek/mtk-adsp-common.h |  10 ++
 4 files changed, 152 insertions(+), 198 deletions(-)

diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c
index 31437fdd4e92..a5291099493e 100644
--- a/sound/soc/sof/mediatek/mt8186/mt8186.c
+++ b/sound/soc/sof/mediatek/mt8186/mt8186.c
@@ -22,7 +22,6 @@
 #include <sound/sof/xtensa.h>
 #include "../../ops.h"
 #include "../../sof-of-dev.h"
-#include "../../sof-audio.h"
 #include "../adsp_helper.h"
 #include "../mtk-adsp-common.h"
 #include "mt8186.h"
@@ -38,53 +37,9 @@ static int mt8186_get_window_offset(struct snd_sof_dev *sdev, u32 id)
 	return MBOX_OFFSET;
 }
 
-static int mt8186_send_msg(struct snd_sof_dev *sdev,
-			   struct snd_sof_ipc_msg *msg)
-{
-	struct adsp_priv *priv = sdev->pdata->hw_pdata;
-
-	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
-			  msg->msg_size);
-
-	return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ);
-}
-
-static void mt8186_dsp_handle_reply(struct mtk_adsp_ipc *ipc)
-{
-	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
-	snd_sof_ipc_process_reply(priv->sdev, 0);
-	spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
-}
-
-static void mt8186_dsp_handle_request(struct mtk_adsp_ipc *ipc)
-{
-	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
-	u32 p; /* panic code */
-	int ret;
-
-	/* Read the message from the debug box. */
-	sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4,
-			 &p, sizeof(p));
-
-	/* Check to see if the message is a panic code 0x0dead*** */
-	if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
-		snd_sof_dsp_panic(priv->sdev, p, true);
-	} else {
-		snd_sof_ipc_msgs_rx(priv->sdev);
-
-		/* tell DSP cmd is done */
-		ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP);
-		if (ret)
-			dev_err(priv->dev, "request send ipc failed");
-	}
-}
-
 static const struct mtk_adsp_ipc_ops dsp_ops = {
-	.handle_reply		= mt8186_dsp_handle_reply,
-	.handle_request		= mt8186_dsp_handle_request,
+	.handle_reply		= mtk_adsp_handle_reply,
+	.handle_request		= mtk_adsp_handle_request,
 };
 
 static int platform_parse_resource(struct platform_device *pdev, void *data)
@@ -381,54 +336,6 @@ static int mt8186_dsp_resume(struct snd_sof_dev *sdev)
 	return ret;
 }
 
-/* on mt8186 there is 1 to 1 match between type and BAR idx */
-static int mt8186_get_bar_index(struct snd_sof_dev *sdev, u32 type)
-{
-	return type;
-}
-
-static int mt8186_pcm_hw_params(struct snd_sof_dev *sdev,
-				struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params,
-				struct snd_sof_platform_stream_params *platform_params)
-{
-	platform_params->cont_update_posn = 1;
-
-	return 0;
-}
-
-static snd_pcm_uframes_t mt8186_pcm_pointer(struct snd_sof_dev *sdev,
-					    struct snd_pcm_substream *substream)
-{
-	int ret;
-	snd_pcm_uframes_t pos;
-	struct snd_sof_pcm *spcm;
-	struct sof_ipc_stream_posn posn;
-	struct snd_sof_pcm_stream *stream;
-	struct snd_soc_component *scomp = sdev->component;
-	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
-	spcm = snd_sof_find_spcm_dai(scomp, rtd);
-	if (!spcm) {
-		dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
-				     rtd->dai_link->id);
-		return 0;
-	}
-
-	stream = &spcm->stream[substream->stream];
-	ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
-	if (ret < 0) {
-		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
-		return 0;
-	}
-
-	memcpy(&stream->posn, &posn, sizeof(posn));
-	pos = spcm->stream[substream->stream].posn.host_posn;
-	pos = bytes_to_frames(substream->runtime, pos);
-
-	return pos;
-}
-
 static void mt8186_adsp_dump(struct snd_sof_dev *sdev, u32 flags)
 {
 	u32 dbg_pc, dbg_data, dbg_inst, dbg_ls0stat, dbg_status, faultinfo;
@@ -505,19 +412,19 @@ static const struct snd_sof_dsp_ops sof_mt8186_ops = {
 	.read64		= sof_io_read64,
 
 	/* ipc */
-	.send_msg		= mt8186_send_msg,
+	.send_msg		= mtk_adsp_send_msg,
 	.get_mailbox_offset	= mt8186_get_mailbox_offset,
 	.get_window_offset	= mt8186_get_window_offset,
 	.ipc_msg_data		= sof_ipc_msg_data,
 	.set_stream_data_offset = sof_set_stream_data_offset,
 
 	/* misc */
-	.get_bar_index	= mt8186_get_bar_index,
+	.get_bar_index	= mtk_adsp_get_bar_index,
 
 	/* stream callbacks */
 	.pcm_open	= sof_stream_pcm_open,
-	.pcm_hw_params	= mt8186_pcm_hw_params,
-	.pcm_pointer	= mt8186_pcm_pointer,
+	.pcm_hw_params	= mtk_adsp_stream_pcm_hw_params,
+	.pcm_pointer	= mtk_adsp_stream_pcm_pointer,
 	.pcm_close	= sof_stream_pcm_close,
 
 	/* firmware loading */
diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c
index 371563d7ce79..498d417e2829 100644
--- a/sound/soc/sof/mediatek/mt8195/mt8195.c
+++ b/sound/soc/sof/mediatek/mt8195/mt8195.c
@@ -22,7 +22,6 @@
 #include <sound/sof/xtensa.h>
 #include "../../ops.h"
 #include "../../sof-of-dev.h"
-#include "../../sof-audio.h"
 #include "../adsp_helper.h"
 #include "../mtk-adsp-common.h"
 #include "mt8195.h"
@@ -38,53 +37,9 @@ static int mt8195_get_window_offset(struct snd_sof_dev *sdev, u32 id)
 	return MBOX_OFFSET;
 }
 
-static int mt8195_send_msg(struct snd_sof_dev *sdev,
-			   struct snd_sof_ipc_msg *msg)
-{
-	struct adsp_priv *priv = sdev->pdata->hw_pdata;
-
-	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
-			  msg->msg_size);
-
-	return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ);
-}
-
-static void mt8195_dsp_handle_reply(struct mtk_adsp_ipc *ipc)
-{
-	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
-	snd_sof_ipc_process_reply(priv->sdev, 0);
-	spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
-}
-
-static void mt8195_dsp_handle_request(struct mtk_adsp_ipc *ipc)
-{
-	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
-	u32 p; /* panic code */
-	int ret;
-
-	/* Read the message from the debug box. */
-	sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4,
-			 &p, sizeof(p));
-
-	/* Check to see if the message is a panic code 0x0dead*** */
-	if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
-		snd_sof_dsp_panic(priv->sdev, p, true);
-	} else {
-		snd_sof_ipc_msgs_rx(priv->sdev);
-
-		/* tell DSP cmd is done */
-		ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP);
-		if (ret)
-			dev_err(priv->dev, "request send ipc failed");
-	}
-}
-
 static const struct mtk_adsp_ipc_ops dsp_ops = {
-	.handle_reply		= mt8195_dsp_handle_reply,
-	.handle_request		= mt8195_dsp_handle_request,
+	.handle_reply		= mtk_adsp_handle_reply,
+	.handle_request		= mtk_adsp_handle_request,
 };
 
 static int platform_parse_resource(struct platform_device *pdev, void *data)
@@ -400,54 +355,6 @@ static int mt8195_dsp_resume(struct snd_sof_dev *sdev)
 	return ret;
 }
 
-/* on mt8195 there is 1 to 1 match between type and BAR idx */
-static int mt8195_get_bar_index(struct snd_sof_dev *sdev, u32 type)
-{
-	return type;
-}
-
-static int mt8195_pcm_hw_params(struct snd_sof_dev *sdev,
-				struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params,
-				struct snd_sof_platform_stream_params *platform_params)
-{
-	platform_params->cont_update_posn = 1;
-
-	return 0;
-}
-
-static snd_pcm_uframes_t mt8195_pcm_pointer(struct snd_sof_dev *sdev,
-					    struct snd_pcm_substream *substream)
-{
-	int ret;
-	snd_pcm_uframes_t pos;
-	struct snd_sof_pcm *spcm;
-	struct sof_ipc_stream_posn posn;
-	struct snd_sof_pcm_stream *stream;
-	struct snd_soc_component *scomp = sdev->component;
-	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
-
-	spcm = snd_sof_find_spcm_dai(scomp, rtd);
-	if (!spcm) {
-		dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
-				     rtd->dai_link->id);
-		return 0;
-	}
-
-	stream = &spcm->stream[substream->stream];
-	ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
-	if (ret < 0) {
-		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
-		return 0;
-	}
-
-	memcpy(&stream->posn, &posn, sizeof(posn));
-	pos = spcm->stream[substream->stream].posn.host_posn;
-	pos = bytes_to_frames(substream->runtime, pos);
-
-	return pos;
-}
-
 static void mt8195_adsp_dump(struct snd_sof_dev *sdev, u32 flags)
 {
 	u32 dbg_pc, dbg_data, dbg_bus0, dbg_bus1, dbg_inst;
@@ -529,19 +436,19 @@ static const struct snd_sof_dsp_ops sof_mt8195_ops = {
 	.read64		= sof_io_read64,
 
 	/* ipc */
-	.send_msg		= mt8195_send_msg,
+	.send_msg		= mtk_adsp_send_msg,
 	.get_mailbox_offset	= mt8195_get_mailbox_offset,
 	.get_window_offset	= mt8195_get_window_offset,
 	.ipc_msg_data		= sof_ipc_msg_data,
 	.set_stream_data_offset = sof_set_stream_data_offset,
 
 	/* misc */
-	.get_bar_index	= mt8195_get_bar_index,
+	.get_bar_index	= mtk_adsp_get_bar_index,
 
 	/* stream callbacks */
 	.pcm_open	= sof_stream_pcm_open,
-	.pcm_hw_params	= mt8195_pcm_hw_params,
-	.pcm_pointer	= mt8195_pcm_pointer,
+	.pcm_hw_params	= mtk_adsp_stream_pcm_hw_params,
+	.pcm_pointer	= mtk_adsp_stream_pcm_pointer,
 	.pcm_close	= sof_stream_pcm_close,
 
 	/* firmware loading */
diff --git a/sound/soc/sof/mediatek/mtk-adsp-common.c b/sound/soc/sof/mediatek/mtk-adsp-common.c
index 20bcf5590eb8..01bbadb160ff 100644
--- a/sound/soc/sof/mediatek/mtk-adsp-common.c
+++ b/sound/soc/sof/mediatek/mtk-adsp-common.c
@@ -12,8 +12,11 @@
  */
 
 #include <linux/module.h>
+#include <sound/asound.h>
 #include <sound/sof/xtensa.h>
 #include "../ops.h"
+#include "../sof-audio.h"
+#include "adsp_helper.h"
 #include "mtk-adsp-common.h"
 
 /**
@@ -81,5 +84,132 @@ void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags)
 }
 EXPORT_SYMBOL(mtk_adsp_dump);
 
+/**
+ * mtk_adsp_send_msg - Send message to Audio DSP
+ * @sdev: SOF device
+ * @msg: SOF IPC Message to send
+ */
+int mtk_adsp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+	struct adsp_priv *priv = sdev->pdata->hw_pdata;
+
+	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+			  msg->msg_size);
+
+	return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ);
+}
+EXPORT_SYMBOL(mtk_adsp_send_msg);
+
+/**
+ * mtk_adsp_handle_reply - Handle reply from the Audio DSP through Mailbox
+ * @ipc: ADSP IPC handle
+ */
+void mtk_adsp_handle_reply(struct mtk_adsp_ipc *ipc)
+{
+	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
+	snd_sof_ipc_process_reply(priv->sdev, 0);
+	spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
+}
+EXPORT_SYMBOL(mtk_adsp_handle_reply);
+
+/**
+ * mtk_adsp_handle_request - Handle request from the Audio DSP through Mailbox
+ * @ipc: ADSP IPC handle
+ */
+void mtk_adsp_handle_request(struct mtk_adsp_ipc *ipc)
+{
+	struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
+	u32 panic_code;
+	int ret;
+
+	/* Read the message from the debug box. */
+	sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4,
+			 &panic_code, sizeof(panic_code));
+
+	/* Check to see if the message is a panic code 0x0dead*** */
+	if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+		snd_sof_dsp_panic(priv->sdev, panic_code, true);
+	} else {
+		snd_sof_ipc_msgs_rx(priv->sdev);
+
+		/* Tell DSP cmd is done */
+		ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP);
+		if (ret)
+			dev_err(priv->dev, "request send ipc failed");
+	}
+}
+EXPORT_SYMBOL(mtk_adsp_handle_request);
+
+/**
+ * mtk_adsp_get_bar_index - Map section type with BAR idx
+ * @sdev: SOF device
+ * @type: Section type as described by snd_sof_fw_blk_type
+ *
+ * MediaTek Audio DSPs have a 1:1 match between type and BAR idx
+ */
+int mtk_adsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
+{
+	return type;
+}
+EXPORT_SYMBOL(mtk_adsp_get_bar_index);
+
+/**
+ * mtk_adsp_stream_pcm_hw_params - Platform specific host stream hw params
+ * @sdev: SOF device
+ * @substream: PCM Substream
+ * @params: hw params
+ * @platform_params: Platform specific SOF stream parameters
+ */
+int mtk_adsp_stream_pcm_hw_params(struct snd_sof_dev *sdev,
+				  struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_sof_platform_stream_params *platform_params)
+{
+	platform_params->cont_update_posn = 1;
+	return 0;
+}
+EXPORT_SYMBOL(mtk_adsp_stream_pcm_hw_params);
+
+/**
+ * mtk_adsp_stream_pcm_pointer - Get host stream pointer
+ * @sdev: SOF device
+ * @substream: PCM substream
+ */
+snd_pcm_uframes_t mtk_adsp_stream_pcm_pointer(struct snd_sof_dev *sdev,
+					      struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct snd_soc_component *scomp = sdev->component;
+	struct snd_sof_pcm_stream *stream;
+	struct sof_ipc_stream_posn posn;
+	struct snd_sof_pcm *spcm;
+	snd_pcm_uframes_t pos;
+	int ret;
+
+	spcm = snd_sof_find_spcm_dai(scomp, rtd);
+	if (!spcm) {
+		dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
+				     rtd->dai_link->id);
+		return 0;
+	}
+
+	stream = &spcm->stream[substream->stream];
+	ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn));
+	if (ret < 0) {
+		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
+		return 0;
+	}
+
+	memcpy(&stream->posn, &posn, sizeof(posn));
+	pos = spcm->stream[substream->stream].posn.host_posn;
+	pos = bytes_to_frames(substream->runtime, pos);
+
+	return pos;
+}
+EXPORT_SYMBOL(mtk_adsp_stream_pcm_pointer);
+
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("SOF helpers for MTK ADSP platforms");
diff --git a/sound/soc/sof/mediatek/mtk-adsp-common.h b/sound/soc/sof/mediatek/mtk-adsp-common.h
index 612cff1f38f7..dc36b91d6779 100644
--- a/sound/soc/sof/mediatek/mtk-adsp-common.h
+++ b/sound/soc/sof/mediatek/mtk-adsp-common.h
@@ -7,4 +7,14 @@
 #define MTK_ADSP_STACK_DUMP_SIZE 32
 
 void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags);
+int mtk_adsp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg);
+void mtk_adsp_handle_reply(struct mtk_adsp_ipc *ipc);
+void mtk_adsp_handle_request(struct mtk_adsp_ipc *ipc);
+int mtk_adsp_get_bar_index(struct snd_sof_dev *sdev, u32 type);
+int mtk_adsp_stream_pcm_hw_params(struct snd_sof_dev *sdev,
+				  struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_sof_platform_stream_params *platform_params);
+snd_pcm_uframes_t mtk_adsp_stream_pcm_pointer(struct snd_sof_dev *sdev,
+					      struct snd_pcm_substream *substream);
 #endif
-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Thu Mar 20 04:57:56 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 12:57:56 +0100
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <20250320031753.13669-2-hailong.fan@mediatek.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
 <20250320031753.13669-2-hailong.fan@mediatek.com>
Message-ID: <816dd6ea-0e5f-4d8f-a5eb-99d0670e0d43@collabora.com>

Il 20/03/25 04:17, hailong.fan ha scritto:
> Add support of SOF on MediaTek mt8196 SoC.
> MT8196 has a Cadence HiFi-5 DSP core that is responsible for running the
> operating system and application programs. The IPC communication between
> the AP and DSP is based on shared DRAM and mailbox interrupt.
> 
> Signed-off-by: hailong.fan <hailong.fan at mediatek.com>

Hello Hailong,

after seeing this series, I acknowledged that the functions that were duplicated
between MT8188 and MT8195 are, in reality, common between more than just those,
as they are the same in your submission for MT8196.

Therefore, I've send a commit that commonizes those, reducing useless code
duplication.

Can you please rebase your series on top of [1]?

Thanks,
Angelo

[1]: 
https://lore.kernel.org/all/20250320115300.137410-1-angelogioacchino.delregno at collabora.com/



From mark.rutland at arm.com  Thu Mar 20 04:59:54 2025
From: mark.rutland at arm.com (Mark Rutland)
Date: Thu, 20 Mar 2025 11:59:54 +0000
Subject: stable-rc: Fast model boot fail Internal error Oops BTI -
 kernfs_iop_permission
In-Reply-To: <CA+G9fYtucEt8Hp6RsV0o+OWSz1E=hXBvhHa-P9C-bPnb7cyGaQ@mail.gmail.com>
References: <CA+G9fYtucEt8Hp6RsV0o+OWSz1E=hXBvhHa-P9C-bPnb7cyGaQ@mail.gmail.com>
Message-ID: <Z9wDOguDLJ17juz2@J2N7QTR9R3.cambridge.arm.com>

On Thu, Mar 20, 2025 at 04:05:14PM +0530, Naresh Kamboju wrote:
> Regressions on arm64 Fast model (FVP-aemva) boot failed with stable-rc 6.13.
> 
> First seen on the stable-rc 6.13.8-rc1
>  Good: v6.13.8
>  Bad:  6.13.8-rc1 (v6.13.7-242-g14de9a7d510f)

That "Good" tag doesn't look right. Is that meant to be v6.13.7?

AFAICT there is no v6.13.8 tag yet.

> Regressions found on FVP:
>  - boot
> 
> Regression Analysis:
>  - New regression? Yes
>  - Reproducible? Yes

Can you bisect this?

> Boot regression: Fast model boot fail Internal error Oops BTI
> Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>
> 
> NOTE:
>   LKFT is currently running FVP Fast Models version 11.24.
>   Planned upgrade to the Fast Models version 11.28 in this sprint.
> 
> ## Boot log
> [   12.812790] Internal error: Oops - BTI: 0000000036000002 [#1] PREEMPT SMP
> [   12.812886] Modules linked in: drm fuse backlight ip_tables x_tables
> [   12.813120] CPU: 6 UID: 0 PID: 136 Comm: udevadm Not tainted 6.13.8-rc1 #1
> [   12.813245] Hardware name: FVP Base RevC (DT)
> [   12.813317] pstate: 163402809 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=-c)
> [   12.813450] pc : kernfs_iop_permission+0x4/0xe4
> [   12.813585] lr : inode_permission+0xb8/0x174

This is one instruction into kernfs_iop_permission(), which suggests
that either the caller has branched to a corrupted address, or somehow
the model has skipped the BTI.

> [   12.813728] sp : ffff800080d63bb0
> [   12.813796] x29: ffff800080d63bc0 x28: 0000000000002e2e x27: 00000000fffffff6
> [   12.813978] x26: 0000000000000030 x25: 2f2f2f2f2f2f2f2f x24: 61c8864680b583eb
> [   12.814161] x23: 0000000000000000 x22: fefefefefefefeff x21: ffffa991682c84b8
> [   12.814344] x20: ffff0008006704d0 x19: 0000000000000001 x18: 00000000fffffffb
> [   12.814525] x17: ffff000801bf8021 x16: e0acaabd2f000000 x15: ffffffffff000000
> [   12.814711] x14: 0000000000000002 x13: ffffffffffffffff x12: 0000002e00000000
> [   12.814893] x11: 0000002d00000000 x10: 0000002d00000000 x9 : ffff0008006704d0
> [   12.815076] x8 : ffffa991665f0ff8 x7 : 0000000000000000 x6 : 0000000000000000
> [   12.815253] x5 : 0000000000000000 x4 : 0000000000004050 x3 : 2f7375622f737973
> [   12.815432] x2 : 0000000000000001 x1 : ffff0008006704d0 x0 : ffffa991682c84b8
> [   12.815613] Call trace:
> [   12.815670]  kernfs_iop_permission+0x4/0xe4 (P)
> [   12.815830]  link_path_walk+0x2b8/0x388
> [   12.815962]  path_lookupat+0x68/0x120
> [   12.816073]  filename_lookup+0xe0/0x1e0
> [   12.816196]  do_readlinkat+0x6c/0x1d8
> [   12.816337]  __arm64_sys_readlinkat+0x20/0x30
> [   12.816481]  invoke_syscall+0x40/0xf8
> [   12.816623]  el0_svc_common+0xa8/0xd8
> [   12.816765]  do_el0_svc+0x1c/0x28
> [   12.816904]  el0_svc+0x38/0x68
> [   12.817050]  el0t_64_sync_handler+0x78/0x108
> [   12.817203]  el0t_64_sync+0x198/0x19c
> [   12.817359] Code: a8c27bfd d50323bf d65f03c0 d503245f (373806c2)
                                                  ^^^^^^^^
						  BTI C

As we can see here, there's a BTI C immediately beafore the instruction
that triggers the BTI exception, so as above either the call has branch
to a bogus address or the model has somehow skipepd the BTI.

Assuming there isn't a model bug, this is likely to be either a bug in
inode_permission(), or some sort of memory corruption.

Mark.

> [   12.817444] ---[ end trace 0000000000000000 ]---
> 
> 
> ## Source
> * Kernel version: 6.13.8-rc1
> * Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
> * Git sha: 14de9a7d510fcfb3bd35e275eda09724bda4d440
> * Git describe: v6.13.7-242-g14de9a7d510f
> * Project details:
> https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/
> 
> ## Build
> * Build log: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/log
> * Build history:
> https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/history/
> * Build details:
> https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.13.y/build/v6.13.7-242-g14de9a7d510f/testrun/27684866/suite/boot/test/clang-20-lkftconfig-no-kselftest-frag/
> * Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uXZoz8Lc7Ue3i4mVWAM8Y800oz/
> * Kernel config:
> https://storage.tuxsuite.com/public/linaro/lkft/builds/2uXZoz8Lc7Ue3i4mVWAM8Y800oz/config
> 
> 
> --
> Linaro LKFT
> https://lkft.linaro.org


From daniel.baluta at nxp.com  Thu Mar 20 05:09:50 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:50 +0200
Subject: [PATCH v7 0/5] Configure imx8mp dsp node for rproc usage
Message-ID: <20250320121004.2542314-1-daniel.baluta@nxp.com>

DSP found in i.MX8MP SOC can be used by multiple frameworks in order to
enable various applications:                                                                                                                                                            
        - rproc/rpmsg framework, used to load for example Zephyr samples
        - Sound Open Firmware, used to enable various audio processing
          pipelines.

Current dsp node was configured with SOF in mind but it doesn't work
well with imx8mp-evk dts. SOF controls audio IPs from firmware side
while imx8mp-evk.dts preffers to control audio IPs from Linux side.

So, configure 'dsp' node to be used with rproc scenario and later will
add a separate dts or an overlay to configure the node for SOF.

This patch series configures and enables dsp node to be used with rproc.

Changes since v6:
	- addressed Alexander Stein comments
	- enable mu2 separately in patch 5/5
	- put "status" always as the last in node definition

Changes since v5:
       - do not enable mu2 node by default
       - fix dt_bindings errors

Changes since v4:
(https://lore.kernel.org/linux-arm-kernel/Z6zGLn3B6SVXhTV1 at lizhi-Precision-Tower-5810/T/)???????????????????????????????????????????????????????????????????????????????????????????????
       - after comments received on v4, we implemented the run/stall
         bits using reset controller API (changes merged ->
https://patchwork.kernel.org/project/linux-arm-kernel/cover/20250311085812.1296243-1-daniel.baluta at nxp.com/)
        - drop patches related to DSP run/stall/reset via syscon
       - picked up patch related to using run_stall via reset
         controller API.


Daniel Baluta (5):
  arm64: dts: imx8mp: Use resets property
  arm64: dts: imx8mp: Add mu2 root clock
  arm64: dts: imx8mp: Configure dsp node for rproc usage
  arm64: dts: imx8mp: Add DSP clocks
  arm64: dts: Enable DSP node for remoteproc usage

 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 14 +++++++++++++
 arch/arm64/boot/dts/freescale/imx8mp.dtsi    | 22 +++++++++++++-------
 2 files changed, 29 insertions(+), 7 deletions(-)

-- 
2.43.0



From daniel.baluta at nxp.com  Thu Mar 20 05:09:51 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:51 +0200
Subject: [PATCH v7 1/5] arm64: dts: imx8mp: Use resets property
In-Reply-To: <20250320121004.2542314-1-daniel.baluta@nxp.com>
References: <20250320121004.2542314-1-daniel.baluta@nxp.com>
Message-ID: <20250320121004.2542314-2-daniel.baluta@nxp.com>

Add resets property to dsp node in order to be able to control the dsp
run/stall bit from audio block control.

Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index ce6793b2d57e..3b725fe442d0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/imx8mp-clock.h>
 #include <dt-bindings/power/imx8mp-power.h>
 #include <dt-bindings/reset/imx8mp-reset.h>
+#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interconnect/fsl,imx8mp.h>
@@ -2422,6 +2423,8 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
+			reset-names = "runstall";
 			status = "disabled";
 		};
 	};
-- 
2.43.0



From daniel.baluta at nxp.com  Thu Mar 20 05:09:52 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:52 +0200
Subject: [PATCH v7 2/5] arm64: dts: imx8mp: Add mu2 root clock
In-Reply-To: <20250320121004.2542314-1-daniel.baluta@nxp.com>
References: <20250320121004.2542314-1-daniel.baluta@nxp.com>
Message-ID: <20250320121004.2542314-3-daniel.baluta@nxp.com>

Enable MU2 node and add mu2 root clock.
MU2 is used to communicate with DSP core.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 3b725fe442d0..fc0d244cfd1e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -1253,6 +1253,7 @@ mu2: mailbox at 30e60000 {
 				reg = <0x30e60000 0x10000>;
 				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
 				#mbox-cells = <2>;
+				clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_MU2_ROOT>;
 				status = "disabled";
 			};
 
-- 
2.43.0



From daniel.baluta at nxp.com  Thu Mar 20 05:09:53 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:53 +0200
Subject: [PATCH v7 3/5] arm64: dts: imx8mp: Configure dsp node for rproc usage
In-Reply-To: <20250320121004.2542314-1-daniel.baluta@nxp.com>
References: <20250320121004.2542314-1-daniel.baluta@nxp.com>
Message-ID: <20250320121004.2542314-4-daniel.baluta@nxp.com>

DSP can be used with various frameworks (e.g audio firmware, rproc).
Currently 'dsp' configuration is intended for audio firmware but it
doesn't work well with board level DTs (e.g imx8mp-evk) because
board level DT enables audio related IPs (e.g SAI) while audio firmware
needs this IPs disabled (because firmware will configure them).

So, configure 'dsp' node to be used with rproc. This way users will be
able to use board DT to use the DSP as long as they don't clash with
Audio IP configurations.

More comples usage of 'dsp' node (e.g by audio firmware) will need to
create a separate dts file (or an overlay).

This change follows the approach taken for other i.MX8 boards
in commit 391a319c81f6d7 ("arm64: dts: imx8-ss-audio: configure dsp node
for rproc usage")

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index fc0d244cfd1e..708d3f61b4e1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -281,7 +281,7 @@ reserved-memory {
 		ranges;
 
 		dsp_reserved: dsp at 92400000 {
-			reg = <0 0x92400000 0 0x2000000>;
+			reg = <0 0x92400000 0 0x1000000>;
 			no-map;
 			status = "disabled";
 		};
@@ -2417,13 +2417,12 @@ usb_dwc3_1: usb at 38200000 {
 		};
 
 		dsp: dsp at 3b6e8000 {
-			compatible = "fsl,imx8mp-dsp";
+			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
-			mbox-names = "txdb0", "txdb1",
-				"rxdb0", "rxdb1";
-			mboxes = <&mu2 2 0>, <&mu2 2 1>,
-				<&mu2 3 0>, <&mu2 3 1>;
-			memory-region = <&dsp_reserved>;
+			power-domains = <&pgc_audio>;
+			mbox-names = "tx", "rx", "rxdb";
+			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
+			firmware-name = "imx/dsp/hifi4.bin";
 			resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>;
 			reset-names = "runstall";
 			status = "disabled";
-- 
2.43.0



From daniel.baluta at nxp.com  Thu Mar 20 05:09:54 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:54 +0200
Subject: [PATCH v7 4/5] arm64: dts: imx8mp: Add DSP clocks
In-Reply-To: <20250320121004.2542314-1-daniel.baluta@nxp.com>
References: <20250320121004.2542314-1-daniel.baluta@nxp.com>
Message-ID: <20250320121004.2542314-5-daniel.baluta@nxp.com>

DSP core needs ocram, core and debug clocks.

Reviewed-by: Iuliana Prodan <iuliana.prodan at nxp.com>
Reviewed-by: Peng Fan <peng.fan at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 708d3f61b4e1..c017eb98c49d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -2419,6 +2419,11 @@ usb_dwc3_1: usb at 38200000 {
 		dsp: dsp at 3b6e8000 {
 			compatible = "fsl,imx8mp-hifi4";
 			reg = <0x3b6e8000 0x88000>;
+			clocks = <&audio_blk_ctrl  IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_OCRAMA_IPG>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSP_ROOT>,
+				<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSPDBG_ROOT>;
+			clock-names = "ipg", "ocram", "core", "debug";
 			power-domains = <&pgc_audio>;
 			mbox-names = "tx", "rx", "rxdb";
 			mboxes = <&mu2 0 0>, <&mu2 1 0>, <&mu2 3 0>;
-- 
2.43.0



From daniel.baluta at nxp.com  Thu Mar 20 05:09:55 2025
From: daniel.baluta at nxp.com (Daniel Baluta)
Date: Thu, 20 Mar 2025 14:09:55 +0200
Subject: [PATCH v7 5/5] arm64: dts: Enable DSP node for remoteproc usage
In-Reply-To: <20250320121004.2542314-1-daniel.baluta@nxp.com>
References: <20250320121004.2542314-1-daniel.baluta@nxp.com>
Message-ID: <20250320121004.2542314-6-daniel.baluta@nxp.com>

Enable all relevant nodes to support remoteproc with imx8mp-evk board.
	- add rproc specific memory regions
	- enable dsp_reserved node
	- enable mu2 node
	- enable dsp node

Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index c26954e5a605..9ab3ee93a35b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -309,6 +309,16 @@ &aud2htx {
 	status = "okay";
 };
 
+&dsp_reserved {
+	status = "okay";
+};
+
+&dsp {
+	memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
+			<&dsp_vdev0vring1>, <&dsp_reserved>;
+	status = "okay";
+};
+
 &eqos {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_eqos>;
@@ -690,6 +700,10 @@ dsi_out: endpoint {
 	};
 };
 
+&mu2 {
+	status = "okay";
+};
+
 &pcie_phy {
 	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
 	clocks = <&pcie0_refclk>;
-- 
2.43.0



From angelogioacchino.delregno at collabora.com  Thu Mar 20 05:11:56 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 13:11:56 +0100
Subject: [PATCH 2/3] memory: mtk-smi: Add a flag skip_rpm
In-Reply-To: <20250320073625.25225-3-xueqi.zhang@mediatek.com>
References: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
 <20250320073625.25225-3-xueqi.zhang@mediatek.com>
Message-ID: <46e0e1f1-e094-40f9-99f9-22678bb40d39@collabora.com>

Il 20/03/25 08:36, Xueqi Zhang ha scritto:
> MT8196 SMI commons is backed up/restored by RTFF HW.
> It doesn't need SW control the register backup/store
> in the runtime callback.Therefore, add a flag skip_rpm
> to help skip RPM operations for SMI commons.
> 
> Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>

So the MT8196 SMI common doesn't require any clocks?

That's fine for me, but this looks bloody similar to MT6989's SMI common, which
is SMI GEN3 and not GEN2....

....so, are you sure that you need a `skip_rpm` flag and not new MTK_SMI_GEN3 and
MTK_SMI_GEN3_SUB_COMM types? :-)

Regards,
Angelo

> ---
>   drivers/memory/mtk-smi.c | 11 ++++++++---
>   1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index a8f5467d6b31..b9affa3c3185 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -123,6 +123,7 @@ static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1
>   struct mtk_smi_common_plat {
>   	enum mtk_smi_type	type;
>   	bool			has_gals;
> +	bool			skip_rpm;
>   	u32			bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
>   
>   	const struct mtk_smi_reg_pair	*init;
> @@ -547,6 +548,9 @@ static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi,
>   {
>   	int i, ret;
>   
> +	if (smi->plat->skip_rpm)
> +		return 0;
> +
>   	for (i = 0; i < clk_nr_required; i++)
>   		smi->clks[i].id = clks[i];
>   	ret = devm_clk_bulk_get(dev, clk_nr_required, smi->clks);
> @@ -783,7 +787,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
>   	common->dev = dev;
>   	common->plat = of_device_get_match_data(dev);
>   
> -	if (common->plat->has_gals) {
> +	if (!common->plat->skip_rpm && common->plat->has_gals) {
>   		if (common->plat->type == MTK_SMI_GEN2)
>   			clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR;
>   		else if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
> @@ -814,13 +818,14 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
>   	}
>   
>   	/* link its smi-common if this is smi-sub-common */
> -	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) {
> +	if (common->plat->type == MTK_SMI_GEN2_SUB_COMM && !common->plat->skip_rpm) {
>   		ret = mtk_smi_device_link_common(dev, &common->smi_common_dev);
>   		if (ret < 0)
>   			return ret;
>   	}
>   
> -	pm_runtime_enable(dev);
> +	if (!common->plat->skip_rpm)
> +		pm_runtime_enable(dev);
>   	platform_set_drvdata(pdev, common);
>   	return 0;
>   }




From parth105105 at gmail.com  Thu Mar 20 05:22:59 2025
From: parth105105 at gmail.com (Parth Pancholi)
Date: Thu, 20 Mar 2025 13:22:59 +0100
Subject: [PATCH v1] arm64: dts: ti: k3-j784s4-main: Enable ACSPCIE outputs for PCIe interfaces
Message-ID: <20250320122259.525613-1-parth105105@gmail.com>

From: Parth Pancholi <parth.pancholi at toradex.com>

TI J784S4-based devices, such as the AM69 SoC, provide PCIE_REFCLK outputs
from the SoC, which can be used to clock external PCIe endpoint devices.
Each PCIE_REFCLK output is enabled via the corresponding ACSPCIE clock buffer,
with each buffer supporting two PADs to provide reference clocks for two
associated PCIe instances. The mappings are as follows:
        - PCIe0 -> ACSPCIE1 PAD0
        - PCIe1 -> ACSPCIE0 PAD0
        - PCIe2 -> ACSPCIE1 PAD1
        - PCIe3 -> ACSPCIE0 PAD1

This patch enables each ACSPCIE module and its corresponding PADs to ensure
that all PCIE_REFCLK outputs are functional.

This change have been tested on an AM69-based custom hardware platform,
where all four PCIe instances (PCIe0, PCIe1, PCIe2, and PCIe3) with the
internal PCIE_REFCLK are utilized with various endpoint devices such as
a WiFi card, NVMe SSD, and PCIe-to-USB bridge.

Link: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1484211/am69-pcie-refclk-out-and-acspcie-mappings
Signed-off-by: Parth Pancholi <parth.pancholi at toradex.com>
---
This change depends on https://lore.kernel.org/all/20241209085157.1203168-1-s-vadapalli at ti.com/
---
 .../boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi      | 10 ++++++++--
 arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi             | 10 ++++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
index 591609f3194c..854fdf7b771e 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
@@ -132,6 +132,11 @@ acspcie0_proxy_ctrl: clock-controller at 1a090 {
 			compatible = "ti,j784s4-acspcie-proxy-ctrl", "syscon";
 			reg = <0x1a090 0x4>;
 		};
+
+		acspcie1_proxy_ctrl: clock-controller at 1a094 {
+			compatible = "ti,j784s4-acspcie-proxy-ctrl", "syscon";
+			reg = <0x1a094 0x4>;
+		};
 	};
 
 	main_ehrpwm0: pwm at 3000000 {
@@ -1067,11 +1072,12 @@ pcie0_rc: pcie at 2900000 {
 		interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
 		device_type = "pci";
 		ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
+		ti,syscon-acspcie-proxy-ctrl = <&acspcie1_proxy_ctrl 0x1>;
 		max-link-speed = <3>;
 		num-lanes = <4>;
 		power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 332 0>;
-		clock-names = "fck";
+		clocks = <&k3_clks 332 0>, <&serdes1 CDNS_TORRENT_REFCLK_DRIVER>;
+		clock-names = "fck", "pcie_refclk";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		bus-range = <0x0 0xff>;
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index 0160fe0da983..ebbc315649d0 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -34,8 +34,8 @@ pcie2_rc: pcie at 2920000 {
 		max-link-speed = <3>;
 		num-lanes = <2>;
 		power-domains = <&k3_pds 334 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 334 0>;
-		clock-names = "fck";
+		clocks = <&k3_clks 334 0>, <&serdes1 CDNS_TORRENT_REFCLK_DRIVER>;
+		clock-names = "fck", "pcie_refclk";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		bus-range = <0x0 0xff>;
@@ -45,6 +45,7 @@ pcie2_rc: pcie at 2920000 {
 		dma-coherent;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
 		ti,syscon-pcie-ctrl = <&pcie2_ctrl 0x0>;
+		ti,syscon-acspcie-proxy-ctrl = <&acspcie1_proxy_ctrl 0x3>;
 		status = "disabled";
 	};
 
@@ -63,8 +64,8 @@ pcie3_rc: pcie at 2930000 {
 		max-link-speed = <3>;
 		num-lanes = <2>;
 		power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 335 0>;
-		clock-names = "fck";
+		clocks = <&k3_clks 335 0>, <&serdes0 CDNS_TORRENT_REFCLK_DRIVER>;
+		clock-names = "fck", "pcie_refclk";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		bus-range = <0x0 0xff>;
@@ -74,6 +75,7 @@ pcie3_rc: pcie at 2930000 {
 		dma-coherent;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
 		ti,syscon-pcie-ctrl = <&pcie3_ctrl 0x0>;
+		ti,syscon-acspcie-proxy-ctrl = <&acspcie0_proxy_ctrl 0x3>;
 		status = "disabled";
 	};
 
-- 
2.34.1



From matt.coster at imgtec.com  Thu Mar 20 04:32:12 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:12 +0000
Subject: [PATCH v4 02/18] dt-bindings: gpu: img: Add BXS-4-64 devicetree
 bindings
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-2-d987cf4ca439@imgtec.com>

Unlike AXE-1-16M, BXS-4-64 uses two power domains.

Like the existing AXE-1-16M integration, BXS-4-64 uses the single clock
integration in the TI k3-j721s2.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- Add minItems: 1 to power-domain-names so we don't break single domain
  bindings
- Add back power-domains to conditional constraints to match
  power-domain-names
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-2-143b3dbef02f at imgtec.com
Changes in v3:
- Include adding the second power domain so it's in context
- Remove unnecessary example
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-8-3fd45d9fb0cf at imgtec.com
Changes in v2:
- Use normal reg syntax for 64-bit values
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-8-4ed30e865892 at imgtec.com
---
 .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 37 ++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 2a692feb5bcd526788117fce7934eef9521b364d..f82139f3b2c897bafd36e794cb7466941cc14e65 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -21,6 +21,11 @@ properties:
           # work with newer dts.
           - const: img,img-axe
           - const: img,img-rogue
+      - items:
+          - enum:
+              - ti,j721s2-gpu
+          - const: img,img-bxs-4-64
+          - const: img,img-rogue
 
       # This legacy combination of compatible strings was introduced early on
       # before the more specific GPU identifiers were used.
@@ -49,11 +54,13 @@ properties:
 
   power-domains:
     minItems: 1
-    maxItems: 1
+    maxItems: 2
 
   power-domain-names:
     items:
       - const: a
+      - const: b
+    minItems: 1
 
   dma-coherent: true
 
@@ -83,7 +90,33 @@ allOf:
       properties:
         compatible:
           contains:
-            const: ti,am62-gpu
+            const: img,img-axe-1-16m
+    then:
+      properties:
+        power-domains:
+          maxItems: 1
+        power-domain-names:
+          maxItems: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: img,img-bxs-4-64
+    then:
+      properties:
+        power-domains:
+          minItems: 2
+        power-domain-names:
+          minItems: 2
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            anyOf:
+              - const: ti,am62-gpu
+              - const: ti,j721s2-gpu
     then:
       properties:
         clocks:

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:14 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:14 +0000
Subject: [PATCH v4 04/18] drm/imagination: Use new generic compatible
 string
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-4-d987cf4ca439@imgtec.com>

Follow-on from the companion dt-bindings change ("dt-bindings: gpu: img:
More explicit compatible strings"), deprecating "img,img-axe" in favour of
the more explicit combination of "img,img-rogue" and "img,img-axe-1-16m".

Since all relevant details are interrogated from the device at runtime,
we can match on the generic "img,img-rogue" and avoid adding more entries
with NULL data members (barring hardware quirks).

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-4-143b3dbef02f at imgtec.com
Changes in v3:
- Don't use more specific compatible strings when not required
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-5-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-5-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_drv.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 0639502137b4431dc23a349476572cc898d1f8d0..3130193f8fffc185e630a293be53374bdc4b7ce0 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1473,6 +1473,13 @@ static void pvr_remove(struct platform_device *plat_dev)
 }
 
 static const struct of_device_id dt_match[] = {
+	{ .compatible = "img,img-rogue", .data = NULL },
+
+	/*
+	 * This legacy compatible string was introduced early on before the more generic
+	 * "img,img-rogue" was added. Keep it around here for compatibility, but never use
+	 * "img,img-axe" in new devicetrees.
+	 */
 	{ .compatible = "img,img-axe", .data = NULL },
 	{}
 };

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:25 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:25 +0000
Subject: [PATCH v4 15/18] drm/imagination: Use cached memory with
 dma_coherent
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-15-d987cf4ca439@imgtec.com>

The TI k3-j721s2 platform does not allow us to use uncached memory
(which is what the driver currently does) without disabling cache snooping
on the AXI ACE-Lite interface, which would be too much of a performance
hit.

Given the platform is dma-coherent, we can simply force all
device-accessible memory allocations through the CPU cache. In fact, this
can be done whenever the dma_coherent attribute is present.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-15-143b3dbef02f at imgtec.com
Changes in v3:
- Change from a workaround to a regular codepath
- Add missing <linux/property.h> include
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-19-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-19-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_gem.c | 10 +++++++---
 drivers/gpu/drm/imagination/pvr_gem.h |  6 ++++--
 drivers/gpu/drm/imagination/pvr_mmu.c |  8 +++++++-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_gem.c b/drivers/gpu/drm/imagination/pvr_gem.c
index 6a8c81fe8c1e85c2130a4fe90fce35b6a2be35aa..9467cd563339cd5bf62ff92edba115ed5721ee76 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.c
+++ b/drivers/gpu/drm/imagination/pvr_gem.c
@@ -19,6 +19,7 @@
 #include <linux/log2.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
+#include <linux/property.h>
 #include <linux/refcount.h>
 #include <linux/scatterlist.h>
 
@@ -336,6 +337,7 @@ struct drm_gem_object *pvr_gem_create_object(struct drm_device *drm_dev, size_t
 struct pvr_gem_object *
 pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 {
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
 	struct drm_gem_shmem_object *shmem_obj;
 	struct pvr_gem_object *pvr_obj;
 	struct sg_table *sgt;
@@ -345,7 +347,10 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 	if (size == 0 || !pvr_gem_object_flags_validate(flags))
 		return ERR_PTR(-EINVAL);
 
-	shmem_obj = drm_gem_shmem_create(from_pvr_device(pvr_dev), size);
+	if (device_get_dma_attr(drm_dev->dev) == DEV_DMA_COHERENT)
+		flags |= PVR_BO_CPU_CACHED;
+
+	shmem_obj = drm_gem_shmem_create(drm_dev, size);
 	if (IS_ERR(shmem_obj))
 		return ERR_CAST(shmem_obj);
 
@@ -360,8 +365,7 @@ pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
 		goto err_shmem_object_free;
 	}
 
-	dma_sync_sgtable_for_device(shmem_obj->base.dev->dev, sgt,
-				    DMA_BIDIRECTIONAL);
+	dma_sync_sgtable_for_device(drm_dev->dev, sgt, DMA_BIDIRECTIONAL);
 
 	/*
 	 * Do this last because pvr_gem_object_zero() requires a fully
diff --git a/drivers/gpu/drm/imagination/pvr_gem.h b/drivers/gpu/drm/imagination/pvr_gem.h
index e0e5ea509a2e88a437b8d241ea13c7bab2220f56..c99f30cc62088c030bd8a806df79b738b62a968f 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.h
+++ b/drivers/gpu/drm/imagination/pvr_gem.h
@@ -44,8 +44,10 @@ struct pvr_file;
  * Bits not defined anywhere are "undefined".
  *
  * CPU mapping options
- *    :PVR_BO_CPU_CACHED: By default, all GEM objects are mapped write-combined on the CPU. Set this
- *       flag to override this behaviour and map the object cached.
+ *    :PVR_BO_CPU_CACHED: By default, all GEM objects are mapped write-combined on the CPU. Set
+ *       this flag to override this behaviour and map the object cached. If the dma_coherent
+ *       property is present in devicetree, all allocations will be mapped as if this flag was set.
+ *       This does not require any additional consideration at allocation time.
  *
  * Firmware options
  *    :PVR_BO_FW_NO_CLEAR_ON_RESET: By default, all FW objects are cleared and reinitialised on hard
diff --git a/drivers/gpu/drm/imagination/pvr_mmu.c b/drivers/gpu/drm/imagination/pvr_mmu.c
index 4fe70610ed94cf707e631f8148af081a94f97327..450d476d183f0173d0ef03f0d8897fbeb04831a2 100644
--- a/drivers/gpu/drm/imagination/pvr_mmu.c
+++ b/drivers/gpu/drm/imagination/pvr_mmu.c
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kmemleak.h>
 #include <linux/minmax.h>
+#include <linux/property.h>
 #include <linux/sizes.h>
 
 #define PVR_SHIFT_FROM_SIZE(size_) (__builtin_ctzll(size_))
@@ -259,6 +260,7 @@ pvr_mmu_backing_page_init(struct pvr_mmu_backing_page *page,
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
 
 	struct page *raw_page;
+	pgprot_t prot;
 	int err;
 
 	dma_addr_t dma_addr;
@@ -268,7 +270,11 @@ pvr_mmu_backing_page_init(struct pvr_mmu_backing_page *page,
 	if (!raw_page)
 		return -ENOMEM;
 
-	host_ptr = vmap(&raw_page, 1, VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+	prot = PAGE_KERNEL;
+	if (device_get_dma_attr(dev) != DEV_DMA_COHERENT)
+		prot = pgprot_writecombine(prot);
+
+	host_ptr = vmap(&raw_page, 1, VM_MAP, prot);
 	if (!host_ptr) {
 		err = -ENOMEM;
 		goto err_free_page;

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:23 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:23 +0000
Subject: [PATCH v4 13/18] drm/imagination: Move ELF fw utils to common file
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-13-d987cf4ca439@imgtec.com>

Currently only MIPS firmware processors use ELF-formatted firmware. When
adding support for RISC-V firmware processors, it will be useful to have
ELF handling functions ready to go.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-13-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-16-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-16-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/Makefile      |  1 +
 drivers/gpu/drm/imagination/pvr_fw.h      |  5 +++
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 59 +--------------------------
 drivers/gpu/drm/imagination/pvr_fw_util.c | 67 +++++++++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile
index 9bc6a3884c2239e44265f3cdebee149841b270de..077e4762c7c383b6e339da1584c3865d830ef8d6 100644
--- a/drivers/gpu/drm/imagination/Makefile
+++ b/drivers/gpu/drm/imagination/Makefile
@@ -16,6 +16,7 @@ powervr-y := \
 	pvr_fw_mips.o \
 	pvr_fw_startstop.o \
 	pvr_fw_trace.o \
+	pvr_fw_util.o \
 	pvr_gem.o \
 	pvr_hwrt.o \
 	pvr_job.o \
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index ab69f40a7fbc6304171f16dd16d825a68b0362a5..e120eae06bf78633b5bae79a77adac63aa5e06d3 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -478,4 +478,9 @@ pvr_fw_object_get_fw_addr(struct pvr_fw_object *fw_obj, u32 *fw_addr_out)
 	pvr_fw_object_get_fw_addr_offset(fw_obj, 0, fw_addr_out);
 }
 
+/* Util functions defined in pvr_fw_util.c. These are intended for use in pvr_fw_<arch>.c files. */
+int
+pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
+				  u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr);
+
 #endif /* PVR_FW_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 524a9bd0a20b64c509f5708cc61d93b4c864b835..7f341ceb0661c61ac059654faeec91e149036467 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -8,7 +8,6 @@
 #include "pvr_rogue_mips.h"
 #include "pvr_vm_mips.h"
 
-#include <linux/elf.h>
 #include <linux/err.h>
 #include <linux/types.h>
 
@@ -16,60 +15,6 @@
 #define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */
 #define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M
 
-/**
- * process_elf_command_stream() - Process ELF firmware image and populate
- *                                firmware sections
- * @pvr_dev: Device pointer.
- * @fw: Pointer to firmware image.
- * @fw_code_ptr: Pointer to FW code section.
- * @fw_data_ptr: Pointer to FW data section.
- * @fw_core_code_ptr: Pointer to FW coremem code section.
- * @fw_core_data_ptr: Pointer to FW coremem data section.
- *
- * Returns :
- *  * 0 on success, or
- *  * -EINVAL on any error in ELF command stream.
- */
-static int
-process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
-			   u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr)
-{
-	struct elf32_hdr *header = (struct elf32_hdr *)fw;
-	struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff);
-	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
-	u32 entry;
-	int err;
-
-	for (entry = 0; entry < header->e_phnum; entry++, program_header++) {
-		void *write_addr;
-
-		/* Only consider loadable entries in the ELF segment table */
-		if (program_header->p_type != PT_LOAD)
-			continue;
-
-		err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr,
-					      program_header->p_memsz, fw_code_ptr, fw_data_ptr,
-					      fw_core_code_ptr, fw_core_data_ptr, &write_addr);
-		if (err) {
-			drm_err(drm_dev,
-				"Addr 0x%x (size: %d) not found in any firmware segment",
-				program_header->p_vaddr, program_header->p_memsz);
-			return err;
-		}
-
-		/* Write to FW allocation only if available */
-		if (write_addr) {
-			memcpy(write_addr, fw + program_header->p_offset,
-			       program_header->p_filesz);
-
-			memset((u8 *)write_addr + program_header->p_filesz, 0,
-			       program_header->p_memsz - program_header->p_filesz);
-		}
-	}
-
-	return 0;
-}
-
 static int
 pvr_mips_init(struct pvr_device *pvr_dev)
 {
@@ -100,8 +45,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	u32 page_nr;
 	int err;
 
-	err = process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr, fw_core_code_ptr,
-					 fw_core_data_ptr);
+	err = pvr_fw_process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr,
+						fw_core_code_ptr, fw_core_data_ptr);
 	if (err)
 		return err;
 
diff --git a/drivers/gpu/drm/imagination/pvr_fw_util.c b/drivers/gpu/drm/imagination/pvr_fw_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bc8a5c48e9b0eed2045607ab2cfed80a60a32b5
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_fw_util.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#include "pvr_device.h"
+#include "pvr_fw.h"
+
+#include <drm/drm_device.h>
+#include <drm/drm_print.h>
+
+#include <linux/elf.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+/**
+ * pvr_fw_process_elf_command_stream() - Process ELF firmware image and populate
+ *                                       firmware sections
+ * @pvr_dev: Device pointer.
+ * @fw: Pointer to firmware image.
+ * @fw_code_ptr: Pointer to FW code section.
+ * @fw_data_ptr: Pointer to FW data section.
+ * @fw_core_code_ptr: Pointer to FW coremem code section.
+ * @fw_core_data_ptr: Pointer to FW coremem data section.
+ *
+ * Returns :
+ *  * 0 on success, or
+ *  * -EINVAL on any error in ELF command stream.
+ */
+int
+pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw,
+				  u8 *fw_code_ptr, u8 *fw_data_ptr,
+				  u8 *fw_core_code_ptr, u8 *fw_core_data_ptr)
+{
+	struct elf32_hdr *header = (struct elf32_hdr *)fw;
+	struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff);
+	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
+	u32 entry;
+	int err;
+
+	for (entry = 0; entry < header->e_phnum; entry++, program_header++) {
+		void *write_addr;
+
+		/* Only consider loadable entries in the ELF segment table */
+		if (program_header->p_type != PT_LOAD)
+			continue;
+
+		err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr,
+					      program_header->p_memsz, fw_code_ptr, fw_data_ptr,
+					      fw_core_code_ptr, fw_core_data_ptr, &write_addr);
+		if (err) {
+			drm_err(drm_dev,
+				"Addr 0x%x (size: %d) not found in any firmware segment",
+				program_header->p_vaddr, program_header->p_memsz);
+			return err;
+		}
+
+		/* Write to FW allocation only if available */
+		if (write_addr) {
+			memcpy(write_addr, fw + program_header->p_offset,
+			       program_header->p_filesz);
+
+			memset((u8 *)write_addr + program_header->p_filesz, 0,
+			       program_header->p_memsz - program_header->p_filesz);
+		}
+	}
+
+	return 0;
+}

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:28 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:28 +0000
Subject: [PATCH DO NOT MERGE v4 18/18] arm64: dts: ti: k3-j721s2: Add GPU
 node
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-18-d987cf4ca439@imgtec.com>

The J721S2 binding is based on the TI downstream binding in 54b0f2a00d92
("arm64: dts: ti: k3-j721s2-main: add gpu node") from [1] but with updated
compatible strings.

The clock[2] and power[3] indices were verified from docs, but the
source of the interrupt index remains elusive.

[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel
[2]: https://downloads.ti.com/tisci/esd/latest/5_soc_doc/j721s2/clocks.html
[3]: https://downloads.ti.com/tisci/esd/latest/5_soc_doc/j721s2/devices.html

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-18-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-21-3fd45d9fb0cf at imgtec.com
Changes in v2:
- Use normal reg syntax for 64-bit values
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-21-4ed30e865892 at imgtec.com
---
 arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 92bf48fdbeba45ecca8c854db5f72fd3666239c5..a79ac41b2c1f51b7193e6133864428bd35a5e835 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -2048,4 +2048,16 @@ watchdog8: watchdog at 23f0000 {
 		/* reserved for MAIN_R5F1_1 */
 		status = "reserved";
 	};
+
+	gpu: gpu at 4e20000000 {
+		compatible = "ti,j721s2-gpu", "img,img-bxs-4-64", "img,img-rogue";
+		reg = <0x4e 0x20000000 0x00 0x80000>;
+		clocks = <&k3_clks 130 1>;
+		clock-names = "core";
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>,
+				<&k3_pds 373 TI_SCI_PD_EXCLUSIVE>;
+		power-domain-names = "a", "b";
+		dma-coherent;
+	};
 };

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:19 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:19 +0000
Subject: [PATCH v4 09/18] drm/imagination: Rename event_mask -> status_mask
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-9-d987cf4ca439@imgtec.com>

Now that enable_reg isn't used, rename the previously shared event_mask to
status_mask since it's only used with status_reg.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-9-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-11-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-11-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_fw.h      | 6 +++---
 drivers/gpu/drm/imagination/pvr_fw_meta.c | 2 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 29bae4bc244a243a6a95bcf838d924060cc043e2..eead744835726712622d5aba9b3480fe264a089f 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -199,8 +199,8 @@ struct pvr_fw_defs {
 		 */
 		u32 clear_reg;
 
-		/** @event_mask: Bitmask of events to listen for in the status_reg. */
-		u32 event_mask;
+		/** @status_mask: Bitmask of events to listen for in the status_reg. */
+		u32 status_mask;
 
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
 		u32 clear_mask;
@@ -404,7 +404,7 @@ struct pvr_fw_device {
 	pvr_cr_write32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg, value)
 
 #define pvr_fw_irq_pending(pvr_dev) \
-	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.event_mask)
+	(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.status_mask)
 
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index a51eec867884b24767f23b3b34cd7029cb660f48..6786e0153970691fa51ba3a0e62c00a46244a3a3 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -550,7 +550,7 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.irq = {
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
-		.event_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
+		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
 		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
 	},
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index c810a67eeecf1016064e76baf534e31a44c859b5..f195c602bb112066e88210d0106cb5ffc0a9abc6 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -245,7 +245,7 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.irq = {
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
-		.event_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
+		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
 		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
 	},
 };

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:26 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:26 +0000
Subject: [PATCH v4 16/18] drm/imagination: Add support for TI AM68 GPU
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-16-d987cf4ca439@imgtec.com>

Since we already added a generic compatible string for all IMG Rogue GPUs
("img,img-rogue"), all that's needed here is to link the appropriate
firmware for the BXS-4-64 GPU in the AM68.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-16-143b3dbef02f at imgtec.com
Changes in v3:
- Remove device overrides
- Remove specific compatible string
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-20-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-20-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index ac4f5855c5692f0956862cebdbf76b16d8da9a81..b058ec183bb30ab5c3db17ebaadf2754520a2a1f 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -44,6 +44,7 @@
  * This driver supports the following PowerVR/IMG graphics cores from Imagination Technologies:
  *
  * * AXE-1-16M (found in Texas Instruments AM62)
+ * * BXS-4-64 MC1 (found in Texas Instruments J721S2/AM68)
  */
 
 /**
@@ -1512,3 +1513,4 @@ MODULE_DESCRIPTION(PVR_DRIVER_DESC);
 MODULE_LICENSE("Dual MIT/GPL");
 MODULE_IMPORT_NS("DMA_BUF");
 MODULE_FIRMWARE("powervr/rogue_33.15.11.3_v1.fw");
+MODULE_FIRMWARE("powervr/rogue_36.53.104.796_v1.fw");

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:21 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:21 +0000
Subject: [PATCH v4 11/18] drm/imagination: Use a lookup table for fw defs
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-11-d987cf4ca439@imgtec.com>

With more than two firmware processor types, the if/else chain in
pvr_fw_init() gets a bit ridiculous. Use a static array indexed on
pvr_fw_processor_type (which is now a proper enum instead of #defines)
instead.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-11-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-13-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-13-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.h |  4 ----
 drivers/gpu/drm/imagination/pvr_fw.c     | 21 ++++++++++++++++-----
 drivers/gpu/drm/imagination/pvr_fw.h     |  7 +++++++
 3 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 6c01d96657de6dc3904ef5ca28365f06cfe0f40b..12bf0b9e5bfb48ef9e5ed9faa44e0896b7555f49 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -739,8 +739,4 @@ pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
 					      __union_size, __member_size);  \
 	})
 
-#define PVR_FW_PROCESSOR_TYPE_META  0
-#define PVR_FW_PROCESSOR_TYPE_MIPS  1
-#define PVR_FW_PROCESSOR_TYPE_RISCV 2
-
 #endif /* PVR_DEVICE_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index 74ea83b5c1a5f1edd79d2f5ccf1c6b1b400524a9..a69c3c306a1c1de0a9587c003e1e03e4604cca81 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -942,16 +942,27 @@ pvr_fw_validate_init_device_info(struct pvr_device *pvr_dev)
 int
 pvr_fw_init(struct pvr_device *pvr_dev)
 {
+	static const struct pvr_fw_defs *fw_defs[PVR_FW_PROCESSOR_TYPE_COUNT] = {
+		[PVR_FW_PROCESSOR_TYPE_META] = &pvr_fw_defs_meta,
+		[PVR_FW_PROCESSOR_TYPE_MIPS] = &pvr_fw_defs_mips,
+		[PVR_FW_PROCESSOR_TYPE_RISCV] = NULL,
+	};
+
 	u32 kccb_size_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT;
 	u32 kccb_rtn_size = (1 << kccb_size_log2) * sizeof(*pvr_dev->kccb.rtn);
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
 	int err;
 
-	if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_META)
-		fw_dev->defs = &pvr_fw_defs_meta;
-	else if (fw_dev->processor_type == PVR_FW_PROCESSOR_TYPE_MIPS)
-		fw_dev->defs = &pvr_fw_defs_mips;
-	else
+	if (fw_dev->processor_type >= PVR_FW_PROCESSOR_TYPE_COUNT)
+		return -EINVAL;
+
+	fw_dev->defs = fw_defs[fw_dev->processor_type];
+
+	/*
+	 * Not all firmware processor types are currently supported.
+	 * Once they are, this check can be removed.
+	 */
+	if (!fw_dev->defs)
 		return -EINVAL;
 
 	err = fw_dev->defs->init(pvr_dev);
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 180d310074e3585c641e540a9e2576b5ab2a5705..88ad713468ce3a1ee459b04dde5363c24791a4f1 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -402,6 +402,13 @@ struct pvr_fw_device {
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
 
+enum pvr_fw_processor_type {
+	PVR_FW_PROCESSOR_TYPE_META = 0,
+	PVR_FW_PROCESSOR_TYPE_MIPS,
+	PVR_FW_PROCESSOR_TYPE_RISCV,
+	PVR_FW_PROCESSOR_TYPE_COUNT,
+};
+
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
 

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:24 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:24 +0000
Subject: [PATCH v4 14/18] drm/imagination: Add RISC-V firmware processor
 support
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-14-d987cf4ca439@imgtec.com>

From: Sarah Walker <sarah.walker at imgtec.com>

Newer PowerVR GPUs (such as the BXS-4-64 MC1) use a RISC-V firmware
processor instead of the previous MIPS or META.

The current version of this patch depends on a patch[1] which exists in
drm-misc-fixes, but has not yet made it back to drm-misc-next (the
target of this patch). That patch adds the function pvr_vm_unmap_obj()
which is used here.

[1]: https://lore.kernel.org/r/20250226-hold-drm_gem_gpuva-lock-for-unmap-v2-1-3fdacded227f at imgtec.com

Signed-off-by: Sarah Walker <sarah.walker at imgtec.com>
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- Use pvr_vm_unmap_obj() in pvr_riscv_vm_unmap()
- Fix formatting of pvr_riscv_fw_process() signature
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-14-143b3dbef02f at imgtec.com
Changes in v3:
- Don't enable debug module
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-17-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-17-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/Makefile           |   1 +
 drivers/gpu/drm/imagination/pvr_fw.c           |  18 +--
 drivers/gpu/drm/imagination/pvr_fw.h           |  10 ++
 drivers/gpu/drm/imagination/pvr_fw_riscv.c     | 165 +++++++++++++++++++++++++
 drivers/gpu/drm/imagination/pvr_fw_startstop.c |  17 +++
 drivers/gpu/drm/imagination/pvr_rogue_riscv.h  |  41 ++++++
 6 files changed, 244 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/imagination/Makefile b/drivers/gpu/drm/imagination/Makefile
index 077e4762c7c383b6e339da1584c3865d830ef8d6..d748ad9d62e092ed7c3d772214ccd327818d507f 100644
--- a/drivers/gpu/drm/imagination/Makefile
+++ b/drivers/gpu/drm/imagination/Makefile
@@ -14,6 +14,7 @@ powervr-y := \
 	pvr_fw.o \
 	pvr_fw_meta.o \
 	pvr_fw_mips.o \
+	pvr_fw_riscv.o \
 	pvr_fw_startstop.o \
 	pvr_fw_trace.o \
 	pvr_fw_util.o \
diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index a69c3c306a1c1de0a9587c003e1e03e4604cca81..b1379ae46efd8139663c44aa1c3c565908b15aad 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -945,7 +945,7 @@ pvr_fw_init(struct pvr_device *pvr_dev)
 	static const struct pvr_fw_defs *fw_defs[PVR_FW_PROCESSOR_TYPE_COUNT] = {
 		[PVR_FW_PROCESSOR_TYPE_META] = &pvr_fw_defs_meta,
 		[PVR_FW_PROCESSOR_TYPE_MIPS] = &pvr_fw_defs_mips,
-		[PVR_FW_PROCESSOR_TYPE_RISCV] = NULL,
+		[PVR_FW_PROCESSOR_TYPE_RISCV] = &pvr_fw_defs_riscv,
 	};
 
 	u32 kccb_size_log2 = ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT;
@@ -958,13 +958,6 @@ pvr_fw_init(struct pvr_device *pvr_dev)
 
 	fw_dev->defs = fw_defs[fw_dev->processor_type];
 
-	/*
-	 * Not all firmware processor types are currently supported.
-	 * Once they are, this check can be removed.
-	 */
-	if (!fw_dev->defs)
-		return -EINVAL;
-
 	err = fw_dev->defs->init(pvr_dev);
 	if (err)
 		return err;
@@ -1470,6 +1463,15 @@ void pvr_fw_object_get_fw_addr_offset(struct pvr_fw_object *fw_obj, u32 offset,
 	*fw_addr_out = pvr_dev->fw_dev.defs->get_fw_addr_with_offset(fw_obj, offset);
 }
 
+u64
+pvr_fw_obj_get_gpu_addr(struct pvr_fw_object *fw_obj)
+{
+	struct pvr_device *pvr_dev = to_pvr_device(gem_from_pvr_gem(fw_obj->gem)->dev);
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+
+	return fw_dev->fw_heap_info.gpu_addr + fw_obj->fw_addr_offset;
+}
+
 /*
  * pvr_fw_hard_reset() - Re-initialise the FW code and data segments, and reset all global FW
  *                       structures
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index e120eae06bf78633b5bae79a77adac63aa5e06d3..1404dd492d7cd82d62dd407a780efcae34d9bf2d 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -392,6 +392,7 @@ enum pvr_fw_processor_type {
 
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
+extern const struct pvr_fw_defs pvr_fw_defs_riscv;
 
 int pvr_fw_validate_init_device_info(struct pvr_device *pvr_dev);
 int pvr_fw_init(struct pvr_device *pvr_dev);
@@ -478,6 +479,15 @@ pvr_fw_object_get_fw_addr(struct pvr_fw_object *fw_obj, u32 *fw_addr_out)
 	pvr_fw_object_get_fw_addr_offset(fw_obj, 0, fw_addr_out);
 }
 
+u64
+pvr_fw_obj_get_gpu_addr(struct pvr_fw_object *fw_obj);
+
+static __always_inline size_t
+pvr_fw_obj_get_object_size(struct pvr_fw_object *fw_obj)
+{
+	return pvr_gem_object_size(fw_obj->gem);
+}
+
 /* Util functions defined in pvr_fw_util.c. These are intended for use in pvr_fw_<arch>.c files. */
 int
 pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_riscv.c b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc13d483be9a3edd97cad3850e4edf312d5b16b6
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#include "pvr_device.h"
+#include "pvr_fw.h"
+#include "pvr_fw_info.h"
+#include "pvr_fw_mips.h"
+#include "pvr_gem.h"
+#include "pvr_rogue_cr_defs.h"
+#include "pvr_rogue_riscv.h"
+#include "pvr_vm.h"
+
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/ktime.h>
+#include <linux/types.h>
+
+#define ROGUE_FW_HEAP_RISCV_SHIFT 25 /* 32 MB */
+#define ROGUE_FW_HEAP_RISCV_SIZE (1u << ROGUE_FW_HEAP_RISCV_SHIFT)
+
+static int
+pvr_riscv_wrapper_init(struct pvr_device *pvr_dev)
+{
+	const u64 common_opts =
+		((u64)(ROGUE_FW_HEAP_RISCV_SIZE >> FWCORE_ADDR_REMAP_CONFIG0_SIZE_ALIGNSHIFT)
+		 << ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_SIZE_SHIFT) |
+		((u64)MMU_CONTEXT_MAPPING_FWPRIV
+		 << FWCORE_ADDR_REMAP_CONFIG0_MMU_CONTEXT_SHIFT);
+
+	u64 code_addr = pvr_fw_obj_get_gpu_addr(pvr_dev->fw_dev.mem.code_obj);
+	u64 data_addr = pvr_fw_obj_get_gpu_addr(pvr_dev->fw_dev.mem.data_obj);
+
+	/* This condition allows us to OR the addresses into the register directly. */
+	static_assert(ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_SHIFT ==
+		      ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_ALIGNSHIFT);
+
+	WARN_ON(code_addr & ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_CLRMSK);
+	WARN_ON(data_addr & ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG1_DEVVADDR_CLRMSK);
+
+	pvr_cr_write64(pvr_dev, ROGUE_RISCVFW_REGION_REMAP_CR(BOOTLDR_CODE),
+		       code_addr | common_opts | ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_FETCH_EN_EN);
+
+	pvr_cr_write64(pvr_dev, ROGUE_RISCVFW_REGION_REMAP_CR(BOOTLDR_DATA),
+		       data_addr | common_opts |
+			       ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0_LOAD_STORE_EN_EN);
+
+	/* Garten IDLE bit controlled by RISC-V. */
+	pvr_cr_write64(pvr_dev, ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG,
+		       ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
+
+	return 0;
+}
+
+struct rogue_riscv_fw_boot_data {
+	u64 coremem_code_dev_vaddr;
+	u64 coremem_data_dev_vaddr;
+	u32 coremem_code_fw_addr;
+	u32 coremem_data_fw_addr;
+	u32 coremem_code_size;
+	u32 coremem_data_size;
+	u32 flags;
+	u32 reserved;
+};
+
+static int
+pvr_riscv_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
+		     u8 *fw_code_ptr, u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr,
+		     u32 core_code_alloc_size)
+{
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+	struct pvr_fw_mem *fw_mem = &fw_dev->mem;
+	struct rogue_riscv_fw_boot_data *boot_data;
+	int err;
+
+	err = pvr_fw_process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr,
+						fw_core_code_ptr, fw_core_data_ptr);
+	if (err)
+		goto err_out;
+
+	boot_data = (struct rogue_riscv_fw_boot_data *)fw_data_ptr;
+
+	if (fw_mem->core_code_obj) {
+		boot_data->coremem_code_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_code_obj);
+		pvr_fw_object_get_fw_addr(fw_mem->core_code_obj, &boot_data->coremem_code_fw_addr);
+		boot_data->coremem_code_size = pvr_fw_obj_get_object_size(fw_mem->core_code_obj);
+	}
+
+	if (fw_mem->core_data_obj) {
+		boot_data->coremem_data_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_data_obj);
+		pvr_fw_object_get_fw_addr(fw_mem->core_data_obj, &boot_data->coremem_data_fw_addr);
+		boot_data->coremem_data_size = pvr_fw_obj_get_object_size(fw_mem->core_data_obj);
+	}
+
+	return 0;
+
+err_out:
+	return err;
+}
+
+static int
+pvr_riscv_init(struct pvr_device *pvr_dev)
+{
+	pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_RISCV_SHIFT, 0);
+
+	return 0;
+}
+
+static u32
+pvr_riscv_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
+{
+	u32 fw_addr = fw_obj->fw_addr_offset + offset;
+
+	/* RISC-V cacheability is determined by address. */
+	if (fw_obj->gem->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
+		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_UNCACHED_DATA);
+	else
+		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_CACHED_DATA);
+
+	return fw_addr;
+}
+
+static int
+pvr_riscv_vm_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
+{
+	struct pvr_gem_object *pvr_obj = fw_obj->gem;
+
+	return pvr_vm_map(pvr_dev->kernel_vm_ctx, pvr_obj, 0, fw_obj->fw_mm_node.start,
+			  pvr_gem_object_size(pvr_obj));
+}
+
+static void
+pvr_riscv_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
+{
+	struct pvr_gem_object *pvr_obj = fw_obj->gem;
+
+	pvr_vm_unmap_obj(pvr_dev->kernel_vm_ctx, pvr_obj,
+			 fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size);
+}
+
+static bool
+pvr_riscv_irq_pending(struct pvr_device *pvr_dev)
+{
+	return pvr_cr_read32(pvr_dev, ROGUE_CR_IRQ_OS0_EVENT_STATUS) &
+	       ROGUE_CR_IRQ_OS0_EVENT_STATUS_SOURCE_EN;
+}
+
+static void
+pvr_riscv_irq_clear(struct pvr_device *pvr_dev)
+{
+	pvr_cr_write32(pvr_dev, ROGUE_CR_IRQ_OS0_EVENT_CLEAR,
+		       ROGUE_CR_IRQ_OS0_EVENT_CLEAR_SOURCE_EN);
+}
+
+const struct pvr_fw_defs pvr_fw_defs_riscv = {
+	.init = pvr_riscv_init,
+	.fw_process = pvr_riscv_fw_process,
+	.vm_map = pvr_riscv_vm_map,
+	.vm_unmap = pvr_riscv_vm_unmap,
+	.get_fw_addr_with_offset = pvr_riscv_get_fw_addr_with_offset,
+	.wrapper_init = pvr_riscv_wrapper_init,
+	.irq_pending = pvr_riscv_irq_pending,
+	.irq_clear = pvr_riscv_irq_clear,
+	.has_fixed_data_addr = false,
+};
diff --git a/drivers/gpu/drm/imagination/pvr_fw_startstop.c b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
index 36cec227cfe3cf5b1e293f48b164bb1be1b0ea54..dcbb9903e791e600db22d334b2e9580057edc89b 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_startstop.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_startstop.c
@@ -49,6 +49,14 @@ rogue_bif_init(struct pvr_device *pvr_dev)
 
 	pvr_cr_write64(pvr_dev, BIF_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV),
 		       pc_addr);
+
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
+		pc_addr = (((u64)pc_dma_addr >> ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_ALIGNSHIFT)
+			   << ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT) &
+			  ~ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_CLRMSK;
+
+		pvr_cr_write64(pvr_dev, FWCORE_MEM_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV), pc_addr);
+	}
 }
 
 static int
@@ -114,6 +122,9 @@ pvr_fw_start(struct pvr_device *pvr_dev)
 		(void)pvr_cr_read32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE); /* Fence write */
 	}
 
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV)
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 0);
+
 	/* Set Rogue in soft-reset. */
 	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);
 	if (has_reset2)
@@ -167,6 +178,12 @@ pvr_fw_start(struct pvr_device *pvr_dev)
 	/* ... and afterwards. */
 	udelay(3);
 
+	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
+		/* Boot the FW. */
+		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 1);
+		udelay(3);
+	}
+
 	return 0;
 
 err_reset:
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_riscv.h b/drivers/gpu/drm/imagination/pvr_rogue_riscv.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a070e24fa6a8bb44ff1e421ae6750cbf724d346
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_rogue_riscv.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/* Copyright (c) 2024 Imagination Technologies Ltd. */
+
+#ifndef PVR_ROGUE_RISCV_H
+#define PVR_ROGUE_RISCV_H
+
+#include "pvr_rogue_cr_defs.h"
+
+#include <linux/bitops.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+#define ROGUE_RISCVFW_REGION_SIZE SZ_256M
+#define ROGUE_RISCVFW_REGION_SHIFT __ffs(ROGUE_RISCVFW_REGION_SIZE)
+
+enum rogue_riscvfw_region {
+	ROGUE_RISCV_REGION__RESERVED_0 = 0,
+	ROGUE_RISCV_REGION__RESERVED_1,
+	ROGUE_RISCV_REGION_SOCIF,
+	ROGUE_RISCV_REGION__RESERVED_3,
+	ROGUE_RISCV_REGION__RESERVED_4,
+	ROGUE_RISCV_REGION_BOOTLDR_DATA,
+	ROGUE_RISCV_REGION_SHARED_CACHED_DATA,
+	ROGUE_RISCV_REGION__RESERVED_7,
+	ROGUE_RISCV_REGION_COREMEM,
+	ROGUE_RISCV_REGION__RESERVED_9,
+	ROGUE_RISCV_REGION__RESERVED_A,
+	ROGUE_RISCV_REGION__RESERVED_B,
+	ROGUE_RISCV_REGION_BOOTLDR_CODE,
+	ROGUE_RISCV_REGION_SHARED_UNCACHED_DATA,
+	ROGUE_RISCV_REGION__RESERVED_E,
+	ROGUE_RISCV_REGION__RESERVED_F,
+
+	ROGUE_RISCV_REGION__COUNT,
+};
+
+#define ROGUE_RISCVFW_REGION_BASE(r) ((u32)(ROGUE_RISCV_REGION_##r) << ROGUE_RISCVFW_REGION_SHIFT)
+#define ROGUE_RISCVFW_REGION_REMAP_CR(r) \
+	(ROGUE_CR_FWCORE_ADDR_REMAP_CONFIG0 + (u32)(ROGUE_RISCV_REGION_##r) * 8U)
+
+#endif /* PVR_ROGUE_RISCV_H */

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:18 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:18 +0000
Subject: [PATCH v4 08/18] drm/imagination: Remove firmware enable_reg
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-8-d987cf4ca439@imgtec.com>

After a previous commit ("drm/imagination: Mask GPU IRQs in threaded
handler"), this register is now only used to enable firmware interrupts at
start-of-day. This is, however, unnecessary since they are enabled by
default.

In addition, the soon-to-be-added RISC-V firmware processors do not have
an equivalent register.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-8-143b3dbef02f at imgtec.com
Changes in v3:
- Reference a different commit removing use of enable/disable ops.
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-10-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-10-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_device.c  |  1 -
 drivers/gpu/drm/imagination/pvr_fw.h      | 11 +----------
 drivers/gpu/drm/imagination/pvr_fw_meta.c |  1 -
 drivers/gpu/drm/imagination/pvr_fw_mips.c |  1 -
 4 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index a47dd1dd82432f1d66ff90aca26b7b264f4068df..1e488a30c7840466574c7fc3648ab93edfb46354 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -311,7 +311,6 @@ pvr_device_irq_init(struct pvr_device *pvr_dev)
 
 	/* Clear any pending events before requesting the IRQ line. */
 	pvr_fw_irq_clear(pvr_dev);
-	pvr_fw_irq_enable(pvr_dev);
 
 	if (pvr_dev->has_safety_events)
 		pvr_device_safety_irq_clear(pvr_dev);
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index b7966bd574a924862b7877c175fa2b5d757d89db..29bae4bc244a243a6a95bcf838d924060cc043e2 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -188,9 +188,6 @@ struct pvr_fw_defs {
 	 * processor backend in pvr_fw_funcs::init().
 	 */
 	struct {
-		/** @enable_reg: FW interrupt enable register. */
-		u32 enable_reg;
-
 		/** @status_reg: FW interrupt status register. */
 		u32 status_reg;
 
@@ -202,7 +199,7 @@ struct pvr_fw_defs {
 		 */
 		u32 clear_reg;
 
-		/** @event_mask: Bitmask of events to listen for. */
+		/** @event_mask: Bitmask of events to listen for in the status_reg. */
 		u32 event_mask;
 
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
@@ -412,12 +409,6 @@ struct pvr_fw_device {
 #define pvr_fw_irq_clear(pvr_dev) \
 	pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
 
-#define pvr_fw_irq_enable(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, enable, (pvr_dev)->fw_dev.defs->irq.event_mask)
-
-#define pvr_fw_irq_disable(pvr_dev) \
-	pvr_fw_irq_write_reg(pvr_dev, enable, 0)
-
 extern const struct pvr_fw_defs pvr_fw_defs_meta;
 extern const struct pvr_fw_defs pvr_fw_defs_mips;
 
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index 6d13864851fc2e83bdaa94f16435b97841e5de94..a51eec867884b24767f23b3b34cd7029cb660f48 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -548,7 +548,6 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.wrapper_init = pvr_meta_wrapper_init,
 	.has_fixed_data_addr = pvr_meta_has_fixed_data_addr,
 	.irq = {
-		.enable_reg = ROGUE_CR_META_SP_MSLVIRQENABLE,
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.event_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 0bed0257e2ab75f66d8b8966b2ceac6342396fb5..c810a67eeecf1016064e76baf534e31a44c859b5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -243,7 +243,6 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.wrapper_init = pvr_mips_wrapper_init,
 	.has_fixed_data_addr = pvr_mips_has_fixed_data_addr,
 	.irq = {
-		.enable_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_ENABLE,
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
 		.event_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:27 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:27 +0000
Subject: [PATCH DO NOT MERGE v4 17/18] arm64: dts: ti: k3-am62: New GPU
 binding details
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-17-d987cf4ca439@imgtec.com>

Use the new compatible string introduced earlier (in "dt-bindings: gpu:
img: More explicit compatible strings") and add a name to the single power
domain for this GPU (introduced in "dt-bindings: gpu: img: Power domain
details").

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-17-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-7-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-7-4ed30e865892 at imgtec.com
---
 arch/arm64/boot/dts/ti/k3-am62-main.dtsi | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 7d355aa73ea2116723735f70b9351cefcd8bc118..d17b25cae196b08d24adbe7c913ccaba7eed37eb 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -691,12 +691,14 @@ ospi0: spi at fc40000 {
 	};
 
 	gpu: gpu at fd00000 {
-		compatible = "ti,am62-gpu", "img,img-axe";
+		compatible = "ti,am62-gpu", "img,img-axe-1-16m", "img,img-axe",
+			     "img,img-rogue";
 		reg = <0x00 0x0fd00000 0x00 0x20000>;
 		clocks = <&k3_clks 187 0>;
 		clock-names = "core";
 		interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 		power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+		power-domain-names = "a";
 	};
 
 	cpsw3g: ethernet at 8000000 {

-- 
2.49.0



From matt.coster at imgtec.com  Thu Mar 20 04:32:20 2025
From: matt.coster at imgtec.com (Matt Coster)
Date: Thu, 20 Mar 2025 11:32:20 +0000
Subject: [PATCH v4 10/18] drm/imagination: Make has_fixed_data_addr a value
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
Message-ID: <20250320-sets-bxs-4-64-patch-v1-v4-10-d987cf4ca439@imgtec.com>

This is currently a callback function which takes no parameters; there's
no reason for this so let's make it a straightforward value in pvr_fw_defs.

Signed-off-by: Matt Coster <matt.coster at imgtec.com>
---
Changes in v4:
- None
- Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-10-143b3dbef02f at imgtec.com
Changes in v3:
- None
- Link to v2: https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-11-3fd45d9fb0cf at imgtec.com
Changes in v2:
- None
- Link to v1: https://lore.kernel.org/r/20241105-sets-bxs-4-64-patch-v1-v1-12-4ed30e865892 at imgtec.com
---
 drivers/gpu/drm/imagination/pvr_fw.c      |  2 +-
 drivers/gpu/drm/imagination/pvr_fw.h      | 23 ++++++++---------------
 drivers/gpu/drm/imagination/pvr_fw_meta.c |  8 +-------
 drivers/gpu/drm/imagination/pvr_fw_mips.c |  8 +-------
 4 files changed, 11 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index 555b5ca4a27de78ac092bf94c601d284abe41ea6..74ea83b5c1a5f1edd79d2f5ccf1c6b1b400524a9 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -666,7 +666,7 @@ pvr_fw_process(struct pvr_device *pvr_dev)
 		return PTR_ERR(fw_code_ptr);
 	}
 
-	if (pvr_dev->fw_dev.defs->has_fixed_data_addr()) {
+	if (pvr_dev->fw_dev.defs->has_fixed_data_addr) {
 		u32 base_addr = private_data->base_addr & pvr_dev->fw_dev.fw_heap_info.offset_mask;
 
 		fw_data_ptr =
diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index eead744835726712622d5aba9b3480fe264a089f..180d310074e3585c641e540a9e2576b5ab2a5705 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -166,21 +166,6 @@ struct pvr_fw_defs {
 	 */
 	int (*wrapper_init)(struct pvr_device *pvr_dev);
 
-	/**
-	 * @has_fixed_data_addr:
-	 *
-	 * Called to check if firmware fixed data must be loaded at the address given by the
-	 * firmware layout table.
-	 *
-	 * This function is mandatory.
-	 *
-	 * Returns:
-	 *  * %true if firmware fixed data must be loaded at the address given by the firmware
-	 *    layout table.
-	 *  * %false otherwise.
-	 */
-	bool (*has_fixed_data_addr)(void);
-
 	/**
 	 * @irq: FW Interrupt information.
 	 *
@@ -205,6 +190,14 @@ struct pvr_fw_defs {
 		/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
 		u32 clear_mask;
 	} irq;
+
+	/**
+	 * @has_fixed_data_addr: Specify whether the firmware fixed data must be loaded at the
+	 *                       address given by the firmware layout table.
+	 *
+	 * This value is mandatory.
+	 */
+	bool has_fixed_data_addr;
 };
 
 /**
diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c
index 6786e0153970691fa51ba3a0e62c00a46244a3a3..62ddfea6b7306784b979ce209bfdf4a9938f8984 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_meta.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c
@@ -533,12 +533,6 @@ pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			 fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size);
 }
 
-static bool
-pvr_meta_has_fixed_data_addr(void)
-{
-	return false;
-}
-
 const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.init = pvr_meta_init,
 	.fw_process = pvr_meta_fw_process,
@@ -546,11 +540,11 @@ const struct pvr_fw_defs pvr_fw_defs_meta = {
 	.vm_unmap = pvr_meta_vm_unmap,
 	.get_fw_addr_with_offset = pvr_meta_get_fw_addr_with_offset,
 	.wrapper_init = pvr_meta_wrapper_init,
-	.has_fixed_data_addr = pvr_meta_has_fixed_data_addr,
 	.irq = {
 		.status_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.clear_reg = ROGUE_CR_META_SP_MSLVIRQSTATUS,
 		.status_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN,
 		.clear_mask = ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK,
 	},
+	.has_fixed_data_addr = false,
 };
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index f195c602bb112066e88210d0106cb5ffc0a9abc6..2c3172841886b70eb7a9992ec3851f18adcad8d5 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -227,12 +227,6 @@ pvr_mips_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
 	       ROGUE_FW_HEAP_MIPS_BASE;
 }
 
-static bool
-pvr_mips_has_fixed_data_addr(void)
-{
-	return true;
-}
-
 const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.init = pvr_mips_init,
 	.fini = pvr_mips_fini,
@@ -241,11 +235,11 @@ const struct pvr_fw_defs pvr_fw_defs_mips = {
 	.vm_unmap = pvr_vm_mips_unmap,
 	.get_fw_addr_with_offset = pvr_mips_get_fw_addr_with_offset,
 	.wrapper_init = pvr_mips_wrapper_init,
-	.has_fixed_data_addr = pvr_mips_has_fixed_data_addr,
 	.irq = {
 		.status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS,
 		.clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR,
 		.status_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN,
 		.clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN,
 	},
+	.has_fixed_data_addr = true,
 };

-- 
2.49.0



From cleger at rivosinc.com  Thu Mar 20 05:26:00 2025
From: cleger at rivosinc.com (=?UTF-8?B?Q2zDqW1lbnQgTMOpZ2Vy?=)
Date: Thu, 20 Mar 2025 13:26:00 +0100
Subject: [PATCH v3 2/4] riscv: add support for SBI Supervisor Software
 Events extension
In-Reply-To: <20250320-5f9612f1b503c79c9b185b10@orel>
References: <20241206163102.843505-1-cleger@rivosinc.com>
 <20241206163102.843505-3-cleger@rivosinc.com>
 <20250319-46b625cf8b771616d4c7c053@orel>
 <b3fbd730-295f-4491-b0d6-d4e258941ae5@rivosinc.com>
 <20250320-5f9612f1b503c79c9b185b10@orel>
Message-ID: <8115698f-3cf7-4a6a-83cf-9dc288c84ee0@rivosinc.com>



On 20/03/2025 12:52, Andrew Jones wrote:
> On Thu, Mar 20, 2025 at 09:16:07AM +0100, Cl?ment L?ger wrote:
>>
>>
>> On 19/03/2025 18:08, Andrew Jones wrote:
>>> On Fri, Dec 06, 2024 at 05:30:58PM +0100, Cl?ment L?ger wrote:
>>> ...
>>>> +int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cpu)
>>>> +{
>>>> +	void *stack;
>>>> +
>>>> +	arch_evt->evt_id = evt_id;
>>>> +	stack = sse_stack_alloc(cpu, SSE_STACK_SIZE);
>>>> +	if (!stack)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	arch_evt->stack = stack + SSE_STACK_SIZE;
>>>> +
>>>> +	if (sse_init_scs(cpu, arch_evt))
>>>> +		goto free_stack;
>>>> +
>>>> +	if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
>>>> +		arch_evt->interrupted_state_phys =
>>>> +				per_cpu_ptr_to_phys(&arch_evt->interrupted);
>>>> +	} else {
>>>> +		arch_evt->interrupted_state_phys =
>>>> +				virt_to_phys(&arch_evt->interrupted);
>>>> +	}
>>>> +
>>>> +	return 0;
>>>
>>> Hi Cl?ment,
>>>
>>> Testing SSE support with tools/testing/selftests/kvm/riscv/sbi_pmu_test
>>> led to an opensbi sbi_trap_error because the output_phys_lo address passed
>>> to sbi_sse_read_attrs() wasn't a physical address. The reason is that
>>> is_kernel_percpu_address() can only be used on static percpu addresses,
>>> but local sse events get their percpu addresses with alloc_percpu(), so
>>> is_kernel_percpu_address() was returning false even for local events. I
>>> made the following changes to get things working.
>>
>> Hi Andrew,
>>
>> Did something changed recently ? Because I tested that when it was send
>> (PMU + some kernel internal testsuite) and didn't saw that. Anyway, I'll
>> respin it with your changes as well.
> 
> It depends on the kernel config. Configs that don't have many
> alloc_percpu() calls prior to the one made by sse can work, because,
> iiuc, alloc_percpu() will get its allocation from the percpu allocator's
> first chunk until that chunck fills up. The first chunck is shared with
> the static allocations.

Makes sense ! Thanks, I'll look at it.

> 
> Thanks,
> drew
> 
>>
>> Thanks !
>>
>> Cl?ment
>>
>>>
>>> Thanks,
>>> drew
>>>
>>> diff --git a/arch/riscv/kernel/sse.c b/arch/riscv/kernel/sse.c
>>> index b48ae69dad8d..f46893946086 100644
>>> --- a/arch/riscv/kernel/sse.c
>>> +++ b/arch/riscv/kernel/sse.c
>>> @@ -100,12 +100,12 @@ int arch_sse_init_event(struct sse_event_arch_data *arch_evt, u32 evt_id, int cp
>>>         if (sse_init_scs(cpu, arch_evt))
>>>                 goto free_stack;
>>>
>>> -       if (is_kernel_percpu_address((unsigned long)&arch_evt->interrupted)) {
>>> +       if (sse_event_is_global(evt_id)) {
>>>                 arch_evt->interrupted_state_phys =
>>> -                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
>>> +                               virt_to_phys(&arch_evt->interrupted);
>>>         } else {
>>>                 arch_evt->interrupted_state_phys =
>>> -                               virt_to_phys(&arch_evt->interrupted);
>>> +                               per_cpu_ptr_to_phys(&arch_evt->interrupted);
>>>         }
>>>
>>>         return 0;
>>> diff --git a/drivers/firmware/riscv/riscv_sse.c b/drivers/firmware/riscv/riscv_sse.c
>>> index 511db9ad7a9e..fef375046f75 100644
>>> --- a/drivers/firmware/riscv/riscv_sse.c
>>> +++ b/drivers/firmware/riscv/riscv_sse.c
>>> @@ -62,11 +62,6 @@ void sse_handle_event(struct sse_event_arch_data *arch_event,
>>>                         ret);
>>>  }
>>>
>>> -static bool sse_event_is_global(u32 evt)
>>> -{
>>> -       return !!(evt & SBI_SSE_EVENT_GLOBAL);
>>> -}
>>> -
>>>  static
>>>  struct sse_event *sse_event_get(u32 evt)
>>>  {
>>> diff --git a/include/linux/riscv_sse.h b/include/linux/riscv_sse.h
>>> index 16700677f1e8..06b757b036b0 100644
>>> --- a/include/linux/riscv_sse.h
>>> +++ b/include/linux/riscv_sse.h
>>> @@ -8,6 +8,7 @@
>>>
>>>  #include <linux/types.h>
>>>  #include <linux/linkage.h>
>>> +#include <asm/sbi.h>
>>>
>>>  struct sse_event;
>>>  struct pt_regs;
>>> @@ -16,6 +17,11 @@ struct ghes;
>>>
>>>  typedef int (sse_event_handler)(u32 event_num, void *arg, struct pt_regs *regs);
>>>
>>> +static inline bool sse_event_is_global(u32 evt)
>>> +{
>>> +       return !!(evt & SBI_SSE_EVENT_GLOBAL);
>>> +}
>>> +
>>>  #ifdef CONFIG_RISCV_SSE
>>>
>>>  struct sse_event *sse_event_register(u32 event_num, u32 priority,
>>



From jgg at ziepe.ca  Thu Mar 20 05:27:19 2025
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Thu, 20 Mar 2025 09:27:19 -0300
Subject: [RFC PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Use KVM VMID for
 s2 stage
In-Reply-To: <f654ae10e55e4142acb83eb926bb80b2@huawei.com>
References: <20250319173202.78988-1-shameerali.kolothum.thodi@huawei.com>
 <20250319173202.78988-5-shameerali.kolothum.thodi@huawei.com>
 <20250319233946.GF126678@ziepe.ca>
 <f654ae10e55e4142acb83eb926bb80b2@huawei.com>
Message-ID: <20250320122719.GI126678@ziepe.ca>

On Thu, Mar 20, 2025 at 09:30:45AM +0000, Shameerali Kolothum Thodi wrote:
> > Isn't kvm_get_kvm_safe() in modular KVM code most of the time? You can't
> > call it like this right?
> 
> I think it is safe since KVM is not modular for ARM64. And that is one of the
> reasons I thought I will hold the KVM reference here as we don't have to go
> through the symbol_get/put calls here. Also IOMMUFD is not using the kvm
> pointer at the moment. Probably I should add some comments in IOMMUFD
> to make it clear.

Oh I didn't know that.. Interesting simplification

> > That more closely matches how this will eventually work when the VMID
> > allocation is properly made to be local to the viommu.
> 
> Ok. Will update.

You should also block creating a VIOMMU without a KVM for the same
reason.. Really isolate the S2 to only being usable with the KVM
shared VMID.

Jason


From angelogioacchino.delregno at collabora.com  Thu Mar 20 05:37:49 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 13:37:49 +0100
Subject: [PATCH v8 2/3] drm/panel: startek-kd070fhfid015: add another init
 step
In-Reply-To: <20231023-display-support-v8-2-c2dd7b0fb2bd@baylibre.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
 <20231023-display-support-v8-2-c2dd7b0fb2bd@baylibre.com>
Message-ID: <d70b62f8-e24e-4a10-8c6b-18d2e19f1337@collabora.com>

Il 20/03/25 09:48, Alexandre Mergnat ha scritto:
> Currently, the panel set power, set gpio and enable the display link
> in stk_panel_prepare, pointed by drm_panel_funcs.prepare, called by
> panel_bridge_atomic_pre_enable, pointed by
> drm_bridge_funcs.atomic_pre_enable. According to the drm_bridge.h,
> atomic_pre_enable must not enable the display link
> 
> Since the DSI driver is properly inited by the DRM, the panel try to
> communicate with the panel before DSI is powered on.
> 

The panel driver shall still be able to send commands in the .prepare() callback
and if this is not happening anymore... well, there's a problem!

> To solve that, use stk_panel_enable to enable the display link because
> it's called after the mtk_dsi_bridge_atomic_pre_enable which is power
> on the DSI.
> 
> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
> ---
>   .../gpu/drm/panel/panel-startek-kd070fhfid015.c    | 25 +++++++++++++---------
>   1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
> index c0c95355b7435..bc3c4038bf4f5 100644
> --- a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
> +++ b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
> @@ -135,19 +135,9 @@ static int stk_panel_prepare(struct drm_panel *panel)
>   	gpiod_set_value(stk->enable_gpio, 1);
>   	mdelay(20);
>   	gpiod_set_value(stk->reset_gpio, 1);
> -	mdelay(10);
> -	ret = stk_panel_init(stk);
> -	if (ret < 0)
> -		goto poweroff;

Also, you're moving both init and set_display_on to the enable callback...
this is suboptimal.

You should do the DrIC setup in .prepare() (can include SLEEP OUT), and then you
should have a .enable() callback that calls DISP ON, a .disable() callback that
calls DISP OFF, and .unprepare() that turns everything off.

Cheers,
Angelo

> -
> -	ret = stk_panel_on(stk);
> -	if (ret < 0)
> -		goto poweroff;
>   
>   	return 0;
>   
> -poweroff:
> -	regulator_disable(stk->supplies[POWER].consumer);
>   iovccoff:
>   	regulator_disable(stk->supplies[IOVCC].consumer);
>   	gpiod_set_value(stk->reset_gpio, 0);
> @@ -156,6 +146,20 @@ static int stk_panel_prepare(struct drm_panel *panel)
>   	return ret;
>   }
>   
> +static int stk_panel_enable(struct drm_panel *panel)
> +{
> +	struct stk_panel *stk = to_stk_panel(panel);
> +	int ret;
> +
> +	ret = stk_panel_init(stk);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = stk_panel_on(stk);
> +
> +	return ret;
> +}
> +
>   static const struct drm_display_mode default_mode = {
>   		.clock = 163204,
>   		.hdisplay = 1200,
> @@ -239,6 +243,7 @@ drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
>   }
>   
>   static const struct drm_panel_funcs stk_panel_funcs = {
> +	.enable = stk_panel_enable,
>   	.unprepare = stk_panel_unprepare,
>   	.prepare = stk_panel_prepare,
>   	.get_modes = stk_panel_get_modes,
> 





From angelogioacchino.delregno at collabora.com  Thu Mar 20 05:40:06 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Thu, 20 Mar 2025 13:40:06 +0100
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <20250320-cocky-adventurous-rooster-be2abd@krzk-bin>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
 <20250320031753.13669-2-hailong.fan@mediatek.com>
 <20250320-cocky-adventurous-rooster-be2abd@krzk-bin>
Message-ID: <204c40d5-de0f-42d0-bc86-d17606c4929f@collabora.com>

Il 20/03/25 08:52, Krzysztof Kozlowski ha scritto:
> On Thu, Mar 20, 2025 at 11:17:24AM +0800, hailong.fan wrote:
>> +
>> +void mt8196_sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
>> +{
>> +	/* set RUNSTALL to stop core */
>> +	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_RUNSTALL,
>> +				RUNSTALL, RUNSTALL);
>> +
>> +	/* assert core reset */
>> +	snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_CFGREG_SW_RSTN,
>> +				SW_RSTN_C0 | SW_DBG_RSTN_C0,
>> +				SW_RSTN_C0 | SW_DBG_RSTN_C0);
>> +}
>> +
> 
> Drop stray blank line.
> 
>> diff --git a/sound/soc/sof/mediatek/mt8196/mt8196.c b/sound/soc/sof/mediatek/mt8196/mt8196.c
>> new file mode 100644
>> index 000000000000..364069ce9954
>> --- /dev/null
>> +++ b/sound/soc/sof/mediatek/mt8196/mt8196.c
>> @@ -0,0 +1,650 @@
>> +// SPDX-License-Identifier: GPL-2.0
> 
> Look here
> 
>> +/*
>> + * Copyright (c) 2025 MediaTek Inc.
>> + * Author: Hailong Fan <hailong.fan at mediatek.com>
>> + */
> 
> ...
> 
>> +
>> +static const struct of_device_id sof_of_mt8196_ids[] = {
>> +	{ .compatible = "mediatek,mt8196-dsp", .data = &sof_of_mt8196_desc},
> 
> Bindings are before users.
> 
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(of, sof_of_mt8196_ids);
>> +
>> +/* DT driver definition */
>> +static struct platform_driver snd_sof_of_mt8196_driver = {
>> +	.probe = sof_of_probe,
>> +	.remove = sof_of_remove,
>> +	.shutdown = sof_of_shutdown,
>> +	.driver = {
>> +	.name = "sof-audio-of-mt8196",
>> +		.pm = &sof_of_pm,
>> +		.of_match_table = sof_of_mt8196_ids,
>> +	},
>> +};
>> +module_platform_driver(snd_sof_of_mt8196_driver);
>> +
>> +MODULE_LICENSE("Dual BSD/GPL");
> 
> And here Hm? Don't fake the licensing.
> 
>> +MODULE_DESCRIPTION("SOF support for MT8196 platforms");
>> +MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
> 
> Is this correct?
> 

The import namespace you mean? yes, that's for sof_xtensa_arch_ops :-)

Cheers

> 
> Best regards,
> Krzysztof
> 




From andrew at lunn.ch  Thu Mar 20 05:52:24 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 13:52:24 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Add gmac phy reset GPIO
In-Reply-To: <49f66206fccc714a8745b9ac35247615ad5cc369.1742331667.git.ukleinek@kernel.org>
References: <cover.1742331667.git.ukleinek@kernel.org>
 <49f66206fccc714a8745b9ac35247615ad5cc369.1742331667.git.ukleinek@kernel.org>
Message-ID: <4eaa58b6-72e2-4b83-ab82-500022c90461@lunn.ch>

On Tue, Mar 18, 2025 at 10:08:46PM +0100, Uwe Kleine-K?nig wrote:
> While looking through the vendor U-Boot code Heiko spotted that a SoC
> GPIO is connected to the ethernet phy's reset pin. Add the respective
> reset-gpios property with pinmuxing for the GPIO to the phy node.
> 
> Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> index 70e88769e21c..411f8ac7994b 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts
> @@ -485,6 +485,10 @@ rgmii_phy0: ethernet-phy at 3 {
>  		/* Motorcomm YT8521 phy */
>  		compatible = "ethernet-phy-ieee802.3-c22";
>  		reg = <0x3>;
> +		pinctrl-0 = <&eth_phy0_reset_pin>;
> +		pinctrl-names = "default";
> +		reset-assert-us = <10000>;
> +		reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>;

Sometimes a reset-deassert-us property is needed, in order to give the
PHY time to get ready. But i assume you have tested this with lots of
reboot.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From andrew at lunn.ch  Thu Mar 20 05:52:36 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 13:52:36 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Correct gmac phy address
In-Reply-To: <6b8ef7e37e646f4cd399ceb2f46017644d76da9d.1742331667.git.ukleinek@kernel.org>
References: <cover.1742331667.git.ukleinek@kernel.org>
 <6b8ef7e37e646f4cd399ceb2f46017644d76da9d.1742331667.git.ukleinek@kernel.org>
Message-ID: <a9df5da5-b37f-4d59-9cb4-1285fe25e3a7@lunn.ch>

On Tue, Mar 18, 2025 at 10:08:45PM +0100, Uwe Kleine-K?nig wrote:
> The Motorcomm Phy can be talked to on mdio broadcast address 0, but the
> actuall address is 3. Adapt the reg property and node name accordingly.
> 
> Signed-off-by: Uwe Kleine-K?nig <uwe at kleine-koenig.org>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From horms at kernel.org  Thu Mar 20 05:53:49 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 20 Mar 2025 12:53:49 +0000
Subject: [PATCH net-next 1/3] net: ti: prueth: Fix kernel warning while
 bringing down network interface
In-Reply-To: <20250317101551.1005706-2-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
 <20250317101551.1005706-2-m-malladi@ti.com>
Message-ID: <20250320125349.GN280585@kernel.org>

On Mon, Mar 17, 2025 at 03:45:48PM +0530, Meghana Malladi wrote:
> During network interface initialization, the NIC driver needs to register
> its Rx queue with the XDP, to ensure the incoming XDP buffer carries a
> pointer reference to this info and is stored inside xdp_rxq_info.
> 
> While this struct isn't tied to XDP prog, if there are any changes in
> Rx queue, the NIC driver needs to stop the Rx queue by unregistering
> with XDP before purging and reallocating memory. Drop page_pool destroy
> during Rx channel reset and this is already handled by XDP during
> xdp_rxq_info_unreg (Rx queue unregister), failing to do will cause the
> following warning:
> 
> [  271.494611] ------------[ cut here ]------------
> [  271.494629] WARNING: CPU: 0 PID: 2453 at /net/core/page_pool.c:1108 0xffff8000808d5f60

I think it would be nice to include a bit more of the stack trace here.

> 
> Fixes: 46eeb90f03e0 ("net: ti: icssg-prueth: Use page_pool API for RX buffer allocation")
> Signed-off-by: Meghana Malladi <m-malladi at ti.com>

It is a shame that we now have more asymmetry regarding
the allocation of the pool and unwind on error prueth_prepare_rx_chan().

But if I see things correctly the freeing of the pool via
xdp_rxq_info_unreg() is unconditional. And with that in mind
I agree the approach taken by this patch makes sense.

Reviewed-by: Simon Horman <horms at kernel.org>

...


From horms at kernel.org  Thu Mar 20 05:54:08 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 20 Mar 2025 12:54:08 +0000
Subject: [PATCH net-next 2/3] net: ti: prueth: Fix possible NULL pointer
 dereference inside emac_xmit_xdp_frame()
In-Reply-To: <20250317101551.1005706-3-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
 <20250317101551.1005706-3-m-malladi@ti.com>
Message-ID: <20250320125408.GO280585@kernel.org>

On Mon, Mar 17, 2025 at 03:45:49PM +0530, Meghana Malladi wrote:
> There is an error check inside emac_xmit_xdp_frame() function which
> is called when the driver wants to transmit XDP frame, to check if
> the allocated tx descriptor is NULL, if true to exit and return
> ICSSG_XDP_CONSUMED implying failure in transmission.
> 
> In this case trying to free a descriptor which is NULL will result
> in kernel crash due to NULL pointer dereference. Fix this error handling
> and increase netdev tx_dropped stats in the caller of this function
> if the function returns ICSSG_XDP_CONSUMED.
> 
> Fixes: 62aa3246f462 ("net: ti: icssg-prueth: Add XDP support")
> Signed-off-by: Meghana Malladi <m-malladi at ti.com>

Reviewed-by: Simon Horman <horms at kernel.org>



From horms at kernel.org  Thu Mar 20 05:54:26 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 20 Mar 2025 12:54:26 +0000
Subject: [PATCH net-next 3/3] net: ti: icss-iep: Fix possible NULL
 pointer dereference for perout request
In-Reply-To: <20250317101551.1005706-4-m-malladi@ti.com>
References: <20250317101551.1005706-1-m-malladi@ti.com>
 <20250317101551.1005706-4-m-malladi@ti.com>
Message-ID: <20250320125426.GP280585@kernel.org>

On Mon, Mar 17, 2025 at 03:45:50PM +0530, Meghana Malladi wrote:
> Whenever there is a perout request from the user application,
> kernel receives req structure containing the configuration info
> for that req. Add NULL pointer handling for perout request if
> that req struct points to NULL.
> 
> Fixes: e5b456a14215 ("net: ti: icss-iep: Add pwidth configuration for perout signal")
> Signed-off-by: Meghana Malladi <m-malladi at ti.com>

Reviewed-by: Simon Horman <horms at kernel.org>



From andyshrk at 163.com  Thu Mar 20 05:56:04 2025
From: andyshrk at 163.com (Andy Yan)
Date: Thu, 20 Mar 2025 20:56:04 +0800 (CST)
Subject: [PATCH] arm64: dts: rockchip: aliase sdhci as mmc0 for
 rk3566 box demo
In-Reply-To: <19b62068.1082.193ed25f901.Coremail.andyshrk@163.com>
References: <20241221104920.4193034-1-andyshrk@163.com>
 <24438615.ouqheUzb2q@diego>
 <19b62068.1082.193ed25f901.Coremail.andyshrk@163.com>
Message-ID: <2ae3fb1a.ad30.195b3a0087e.Coremail.andyshrk@163.com>

Hi Heiko?

At 2024-12-22 14:55:09, "Andy Yan" <andyshrk at 163.com> wrote:
>
>Hi Heiko?
>At 2024-12-21 20:55:02, "Heiko St?bner" <heiko at sntech.de> wrote:
>>Hi Andy,
>>
>>Am Samstag, 21. Dezember 2024, 11:49:07 CET schrieb Andy Yan:
>>> From: Andy Yan <andy.yan at rock-chips.com>
>>> 
>>> Follow most others rk356x based boards, and u-boot only use mmc0/1
>>> as mmc boot targets, so aliase sdhci as mmc0.
>>> 
>>> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
>>> ---
>>> 
>>>  arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts | 6 +++---
>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>> 
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
>>> index 41b4cd5a4220..7d0eedf1bd0d 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
>>> @@ -19,9 +19,9 @@ / {
>>>  
>>>  	aliases {
>>>  		ethernet0 = &gmac1;
>>> -		mmc0 = &sdmmc0;
>>> -		mmc1 = &sdmmc1;
>>> -		mmc2 = &sdhci;
>>> +		mmc0 = &sdhci;
>>> +		mmc1 = &sdmmc0;
>>> +		mmc2 = &sdmmc1;
>>
>>sorry, but that won't be possible :-( .
>>
>>The original aliases for the mmc order were added over 2 years ago
>>(november 2022) and became part of the ABI then.
>
>Yes,  the patch for this board was submitted by me.
>This is a tv box  evaluation demo board that we use internally?and it is not sold to the public.
>I submitted it to the mainline because it is small, compact and streamlined, it easy for me
>to use it  test the mainline vop2 driver. 
>I think i am currently the only user who will use this board run the mainline kernel.
>I'm not sure if we can let it go.


So far, no one has come forward to claim that they are using this board.
Actually, as I mentioned before, currently, it is only me who is using this
board to do some DRM-related tests. Could you consider merging it? 
If later on someone really comes forward and claims that this modification
has affected it, we can still revert this patch.

>
>
>>
>>Imagine someone using that board with a rootfs=/dev/mmcblk2p1 part
>>in the commandline to mount the old sdhci-part1 as rootfs, but now
>>you reorder the controllers, so so that commandline would try to access
>>sdmmc1, so their system won't boot anymore after just a simple kernel
>>update.
>>
>>Breaking people's setup is one of those big no-go-s in the kernel, so
>>sadly you'll need to live with the existing order.
>>
>>
>>Heiko
>>
>>

From jens.wiklander at linaro.org  Thu Mar 20 06:00:57 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Thu, 20 Mar 2025 14:00:57 +0100
Subject: [PATCH v6 03/10] optee: account for direction while converting parameters
In-Reply-To: <Z9vfD4UWSrqSTPnP@sumit-X1>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org> <Z9K2RQYuXSJc8Y1E@sumit-X1>
 <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com> <Z9vfD4UWSrqSTPnP@sumit-X1>
Message-ID: <CAHUa44HY-jZCoDXKnx-f4gBoABRVdh1+6PA1AYHSva9aL=rDAA@mail.gmail.com>

Hi Sumit,

On Thu, Mar 20, 2025 at 10:25?AM Sumit Garg <sumit.garg at kernel.org> wrote:
>
> Hi Jens,
>
> On Mon, Mar 17, 2025 at 08:42:01AM +0100, Jens Wiklander wrote:
> > Hi Sumit,
> >
> > On Thu, Mar 13, 2025 at 11:41?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> > >
> > > Hi Jens,
> > >
> > > On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> > > > The OP-TEE backend driver has two internal function pointers to convert
> > > > between the subsystem type struct tee_param and the OP-TEE type struct
> > > > optee_msg_param.
> > > >
> > > > The conversion is done from one of the types to the other, which is then
> > > > involved in some operation and finally converted back to the original
> > > > type. When converting to prepare the parameters for the operation, all
> > > > fields must be taken into account, but then converting back, it's enough
> > > > to update only out-values and out-sizes. So, an update_out parameter is
> > > > added to the conversion functions to tell if all or only some fields
> > > > must be copied.
> > > >
> > > > This is needed in a later patch where it might get confusing when
> > > > converting back in from_msg_param() callback since an allocated
> > > > restricted SHM can be using the sec_world_id of the used restricted
> > > > memory pool and that doesn't translate back well.
> > > >
> > > > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > > > ---
> > > >  drivers/tee/optee/call.c          | 10 ++--
> > > >  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
> > > >  drivers/tee/optee/optee_private.h | 42 +++++++++++------
> > > >  drivers/tee/optee/rpc.c           | 31 +++++++++----
> > > >  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
> > > >  5 files changed, 144 insertions(+), 58 deletions(-)
> > > >
> > > > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > > > index 16eb953e14bb..f1533b894726 100644
> > > > --- a/drivers/tee/optee/call.c
> > > > +++ b/drivers/tee/optee/call.c
> > > > @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
> > > >       export_uuid(msg_arg->params[1].u.octets, &client_uuid);
> > > >
> > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> > > > -                                   arg->num_params, param);
> > > > +                                   arg->num_params, param,
> > > > +                                   false /*!update_out*/);
> > > >       if (rc)
> > > >               goto out;
> > > >
> > > > @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
> > > >       }
> > > >
> > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > -                                    msg_arg->params + 2)) {
> > > > +                                    msg_arg->params + 2,
> > > > +                                    true /*update_out*/)) {
> > > >               arg->ret = TEEC_ERROR_COMMUNICATION;
> > > >               arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > >               /* Close session again to avoid leakage */
> > > > @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > >       msg_arg->cancel_id = arg->cancel_id;
> > > >
> > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> > > > -                                   param);
> > > > +                                   param, false /*!update_out*/);
> > > >       if (rc)
> > > >               goto out;
> > > >
> > > > @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > >       }
> > > >
> > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > -                                    msg_arg->params)) {
> > > > +                                    msg_arg->params, true /*update_out*/)) {
> > > >               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
> > > >               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > >       }
> > > > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > > > index 4ca1d5161b82..e4b08cd195f3 100644
> > > > --- a/drivers/tee/optee/ffa_abi.c
> > > > +++ b/drivers/tee/optee/ffa_abi.c
> > > > @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
> > > >   */
> > > >
> > > >  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > -                                u32 attr, const struct optee_msg_param *mp)
> > > > +                                u32 attr, const struct optee_msg_param *mp,
> > > > +                                bool update_out)
> > > >  {
> > > >       struct tee_shm *shm = NULL;
> > > >       u64 offs_high = 0;
> > > >       u64 offs_low = 0;
> > > >
> > > > +     if (update_out) {
> > > > +             if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> > > > +                     return;
> > > > +             goto out;
> > > > +     }
> > > > +
> > > >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> > > >                 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> > > > -     p->u.memref.size = mp->u.fmem.size;
> > > >
> > > >       if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
> > > >               shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> > > > @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > >               offs_high = mp->u.fmem.offs_high;
> > > >       }
> > > >       p->u.memref.shm_offs = offs_low | offs_high << 32;
> > > > +out:
> > > > +     p->u.memref.size = mp->u.fmem.size;
> > > >  }
> > > >
> > > >  /**
> > > > @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > >   * @params:  subsystem internal parameter representation
> > > >   * @num_params:      number of elements in the parameter arrays
> > > >   * @msg_params:      OPTEE_MSG parameters
> > > > + * @update_out: update parameter for output only
> > > >   *
> > > >   * Returns 0 on success or <0 on failure
> > > >   */
> > > >  static int optee_ffa_from_msg_param(struct optee *optee,
> > > >                                   struct tee_param *params, size_t num_params,
> > > > -                                 const struct optee_msg_param *msg_params)
> > > > +                                 const struct optee_msg_param *msg_params,
> > > > +                                 bool update_out)
> > > >  {
> > > >       size_t n;
> > > >
> > > > @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > >
> > > >               switch (attr) {
> > > >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > > > +                     if (update_out)
> > > > +                             break;
> > > >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > >                       memset(&p->u, 0, sizeof(p->u));
> > > >                       break;
> > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > > > -                     optee_from_msg_param_value(p, attr, mp);
> > > > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> > > >                       break;
> > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
> > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
> > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> > > > -                     from_msg_param_ffa_mem(optee, p, attr, mp);
> > > > +                     from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
> > > >                       break;
> > > >               default:
> > > >                       return -EINVAL;
> > > > @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > >  }
> > > >
> > > >  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > -                             const struct tee_param *p)
> > > > +                             const struct tee_param *p, bool update_out)
> > > >  {
> > > >       struct tee_shm *shm = p->u.memref.shm;
> > > >
> > > > +     if (update_out) {
> > > > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > > > +                     return 0;
> > > > +             goto out;
> > > > +     }
> > > > +
> > > >       mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
> > > >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> > > >
> > > > @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > >               memset(&mp->u, 0, sizeof(mp->u));
> > > >               mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
> > > >       }
> > > > +out:
> > > >       mp->u.fmem.size = p->u.memref.size;
> > > >
> > > >       return 0;
> > > > @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > >   * @optee:   main service struct
> > > >   * @msg_params:      OPTEE_MSG parameters
> > > >   * @num_params:      number of elements in the parameter arrays
> > > > - * @params:  subsystem itnernal parameter representation
> > > > + * @params:  subsystem internal parameter representation
> > > > + * @update_out: update parameter for output only
> > > >   * Returns 0 on success or <0 on failure
> > > >   */
> > > >  static int optee_ffa_to_msg_param(struct optee *optee,
> > > >                                 struct optee_msg_param *msg_params,
> > > >                                 size_t num_params,
> > > > -                               const struct tee_param *params)
> > > > +                               const struct tee_param *params,
> > > > +                               bool update_out)
> > > >  {
> > > >       size_t n;
> > > >
> > > > @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
> > > >
> > > >               switch (p->attr) {
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > > +                     if (update_out)
> > > > +                             break;
> > > >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > >                       memset(&mp->u, 0, sizeof(mp->u));
> > > >                       break;
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > > -                     optee_to_msg_param_value(mp, p);
> > > > +                     optee_to_msg_param_value(mp, p, update_out);
> > > >                       break;
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > > -                     if (to_msg_param_ffa_mem(mp, p))
> > > > +                     if (to_msg_param_ffa_mem(mp, p, update_out))
> > > >                               return -EINVAL;
> > > >                       break;
> > > >               default:
> > >
> > > Can we rather handle it as follows to improve code readability and
> > > maintainence long term? Ditto for all other places.
> > >
> > > static int optee_ffa_to_msg_param(struct optee *optee,
> > >                                   struct optee_msg_param *msg_params,
> > >                                   size_t num_params,
> > >                                   const struct tee_param *params,
> > >                                   bool update_out)
> > > {
> > >         size_t n;
> > >
> > >         for (n = 0; n < num_params; n++) {
> > >                 const struct tee_param *p = params + n;
> > >                 struct optee_msg_param *mp = msg_params + n;
> > >
> > >                 if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
> > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
> > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
> > >                     continue;
> >
> > You're missing updating the length field for memrefs.
> >
>
> Do we need to update length field for input memrefs when update_out is
> set? I don't see that happening in your existing patch too.

I'm sorry, I was unclear. The update_out parameter means only the
output fields should be updated, not the attribute, offsets, ids, etc.
That is, the length field for memrefs, and the value fields a, b, c
for value params. Some of the memrefs aren't translated one-to-one
with SDP, but the length field can and must be updated.

Cheers,
Jens

>
> -Sumit
>
> > Cheers,
> > Jens
> >
> > >
> > >                 switch (p->attr) {
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > >                         mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > >                         memset(&mp->u, 0, sizeof(mp->u));
> > >                         break;
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > >                         optee_to_msg_param_value(mp, p);
> > >                         break;
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > >                         if (to_msg_param_ffa_mem(mp, p))
> > >                                 return -EINVAL;
> > >                         break;
> > >                 default:
> > >                         return -EINVAL;
> > >                 }
> > >         }
> > >
> > >         return 0;
> > > }
> > >
> > > -Sumit


From ansuelsmth at gmail.com  Thu Mar 20 06:00:23 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:23 +0100
Subject: [PATCH v2 00/11] airoha: en7581: clk cleanup + USB support
Message-ID: <20250320130054.4804-1-ansuelsmth@gmail.com>

This series implement all the changes required to correctly handle
USB support for the Airoha EN7581 SoC.

The first few patch are cleanup for the clock driver and the
introduction of the SCU SSR SoC driver.

The SoC always support USB 2.0 but for USB 3.0 it needs additional
configuration for the Serdes port. Such port can be either configured
for USB usage or for PCIe lines or HSGMII and these are configured
in the SCU space.

The xHCI USB is based on the Mediatek implementation but the PHY
handling although conceptually similar, is indded different compared
to Mediatek due to SSR checks and different port power up.

The SSR driver expose an API to poll the current status of the Serdes
port and the USB PHY driver validates it. Refer to the specific commit
for additional info.

Consider that there is currently an inconsistency as AN7581 and
EN7581 refer to the same thing. This is due to the fact that
the SoC born under EcoNet but then was acquired by Airoha.

Changes v2:
- Drop changes for simple-mfd
- Rework PHY node structure to single node
- Drop port-id property in favor of serdes-port and
  usb2-monitor-clock-sel
- Make the SSR driver probe from the clock driver

Christian Marangi (11):
  clk: en7523: convert driver to regmap API
  clk: en7523: generalize register clocks function
  dt-bindings: clock: en7523: add Documentation for Airoha AN7581 SCU
    SSR
  soc: airoha: add support for configuring SCU SSR Serdes port
  clk: en7523: define and register SoC SCU SSR driver for EN7581
  soc: airoha: scu-ssr: expose API to read current Serdes Port mode
  dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
  phy: move Airoha PCIe PHY driver to dedicated directory
  phy: airoha: Add support for Airoha AN7581 USB PHY
  usb: host: add ARCH_AIROHA in XHCI MTK dependency
  arm64: dts: airoha: en7581: add USB nodes

 .../bindings/clock/airoha,en7523-scu.yaml     |  101 +-
 .../bindings/phy/airoha,an7581-usb-phy.yaml   |   83 ++
 MAINTAINERS                                   |   21 +-
 arch/arm64/boot/dts/airoha/en7581.dtsi        |   49 +
 drivers/clk/clk-en7523.c                      |  340 +++--
 drivers/phy/Kconfig                           |   11 +-
 drivers/phy/Makefile                          |    5 +-
 drivers/phy/airoha/Kconfig                    |   23 +
 drivers/phy/airoha/Makefile                   |    4 +
 drivers/phy/airoha/phy-airoha-pcie-regs.h     |  494 +++++++
 drivers/phy/airoha/phy-airoha-pcie.c          | 1290 +++++++++++++++++
 drivers/phy/airoha/phy-airoha-usb.c           |  571 ++++++++
 drivers/soc/Kconfig                           |    1 +
 drivers/soc/Makefile                          |    1 +
 drivers/soc/airoha/Kconfig                    |   18 +
 drivers/soc/airoha/Makefile                   |    3 +
 drivers/soc/airoha/airoha-scu-ssr.c           |  271 ++++
 drivers/usb/host/Kconfig                      |    2 +-
 .../dt-bindings/phy/airoha,an7581-usb-phy.h   |   11 +
 include/dt-bindings/soc/airoha,scu-ssr.h      |   11 +
 include/linux/clk/clk-en7523.h                |   10 +
 include/linux/soc/airoha/airoha-scu-ssr.h     |   34 +
 22 files changed, 3202 insertions(+), 152 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-airoha-pcie-regs.h
 create mode 100644 drivers/phy/airoha/phy-airoha-pcie.c
 create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
 create mode 100644 drivers/soc/airoha/Kconfig
 create mode 100644 drivers/soc/airoha/Makefile
 create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
 create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h
 create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
 create mode 100644 include/linux/clk/clk-en7523.h
 create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h

-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:24 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:24 +0100
Subject: [PATCH v2 01/11] clk: en7523: convert driver to regmap API
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-2-ansuelsmth@gmail.com>

Convert driver to regmap API, in preparation for support of Airoha
AN7583 as the SCU will be an MFD and the regmap will be provided in the
parent node. Also Airoha EN7581 benefits from this in preparation of USB
support that required checking and configuring SCU SSR bits.

While at it also cleanup some register mask and use bitfield macro.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c | 137 ++++++++++++++++++++++-----------------
 1 file changed, 76 insertions(+), 61 deletions(-)

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 15bbdeb60b8e..314e7450313f 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
@@ -34,6 +35,7 @@
 #define   REG_RESET_CONTROL_PCIE2	BIT(26)
 /* EN7581 */
 #define REG_NP_SCU_PCIC			0x88
+#define REG_PCIE_CTRL			GENMASK(7, 0)
 #define REG_NP_SCU_SSTR			0x9c
 #define REG_PCIE_XSI0_SEL_MASK		GENMASK(14, 13)
 #define REG_PCIE_XSI1_SEL_MASK		GENMASK(12, 11)
@@ -63,14 +65,14 @@ struct en_clk_desc {
 };
 
 struct en_clk_gate {
-	void __iomem *base;
+	struct regmap *map;
 	struct clk_hw hw;
 };
 
 struct en_rst_data {
 	const u16 *bank_ofs;
 	const u16 *idx_map;
-	void __iomem *base;
+	struct regmap *map;
 	struct reset_controller_dev rcdev;
 };
 
@@ -388,44 +390,44 @@ static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
 static int en7523_pci_is_enabled(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+	u32 val;
 
-	return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
+	regmap_read(cg->map, REG_PCI_CONTROL, &val);
+	return !!(val & REG_PCI_CONTROL_REFCLK_EN1);
 }
 
 static int en7523_pci_prepare(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	/* Need to pull device low before reset */
-	val = readl(np_base + REG_PCI_CONTROL);
-	val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL,
+			  REG_PCI_CONTROL_PERSTOUT1 |
+			  REG_PCI_CONTROL_PERSTOUT);
 	usleep_range(1000, 2000);
 
 	/* Enable PCIe port 1 */
-	val |= REG_PCI_CONTROL_REFCLK_EN1;
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL,
+			REG_PCI_CONTROL_REFCLK_EN1);
 	usleep_range(1000, 2000);
 
 	/* Reset to default */
-	val = readl(np_base + REG_RESET_CONTROL1);
 	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
 	       REG_RESET_CONTROL_PCIEHB;
-	writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+	regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
 	usleep_range(1000, 2000);
-	writel(val | mask, np_base + REG_RESET_CONTROL1);
+	regmap_set_bits(map, REG_RESET_CONTROL1, mask);
 	msleep(100);
-	writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+	regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
 	usleep_range(5000, 10000);
 
 	/* Release device */
 	mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val & ~mask, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, mask);
 	usleep_range(1000, 2000);
-	writel(val | mask, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL, mask);
 	msleep(250);
 
 	return 0;
@@ -434,16 +436,13 @@ static int en7523_pci_prepare(struct clk_hw *hw)
 static void en7523_pci_unprepare(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val;
+	struct regmap *map = cg->map;
 
-	val = readl(np_base + REG_PCI_CONTROL);
-	val &= ~REG_PCI_CONTROL_REFCLK_EN1;
-	writel(val, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, REG_PCI_CONTROL_REFCLK_EN1);
 }
 
 static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
-					       void __iomem *np_base)
+					       struct regmap *clk_map)
 {
 	const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
 	struct clk_init_data init = {
@@ -456,7 +455,7 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
 	if (!cg)
 		return NULL;
 
-	cg->base = np_base;
+	cg->map = clk_map;
 	cg->hw.init = &init;
 
 	if (init.ops->unprepare)
@@ -474,21 +473,20 @@ static int en7581_pci_is_enabled(struct clk_hw *hw)
 	u32 val, mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
-	val = readl(cg->base + REG_PCI_CONTROL);
+	regmap_read(cg->map, REG_PCI_CONTROL, &val);
 	return (val & mask) == mask;
 }
 
 static int en7581_pci_enable(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
 	       REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
 	       REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val | mask, np_base + REG_PCI_CONTROL);
+	regmap_set_bits(map, REG_PCI_CONTROL, mask);
 
 	return 0;
 }
@@ -496,19 +494,18 @@ static int en7581_pci_enable(struct clk_hw *hw)
 static void en7581_pci_disable(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
-	void __iomem *np_base = cg->base;
-	u32 val, mask;
+	struct regmap *map = cg->map;
+	u32 mask;
 
 	mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
 	       REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
 	       REG_PCI_CONTROL_PERSTOUT;
-	val = readl(np_base + REG_PCI_CONTROL);
-	writel(val & ~mask, np_base + REG_PCI_CONTROL);
+	regmap_clear_bits(map, REG_PCI_CONTROL, mask);
 	usleep_range(1000, 2000);
 }
 
 static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   void __iomem *base, void __iomem *np_base)
+				   struct regmap *map, struct regmap *clk_map)
 {
 	struct clk_hw *hw;
 	u32 rate;
@@ -517,10 +514,12 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
 		const struct en_clk_desc *desc = &en7523_base_clks[i];
 		u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		u32 val = readl(base + desc->base_reg);
+		u32 val;
+
+		regmap_read(map, desc->base_reg, &val);
 
 		rate = en7523_get_base_rate(desc, val);
-		val = readl(base + reg);
+		regmap_read(map, reg, &val);
 		rate /= en7523_get_div(desc, val);
 
 		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
@@ -533,30 +532,47 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 		clk_data->hws[desc->id] = hw;
 	}
 
-	hw = en7523_register_pcie_clk(dev, np_base);
+	hw = en7523_register_pcie_clk(dev, clk_map);
 	clk_data->hws[EN7523_CLK_PCIE] = hw;
 }
 
+static const struct regmap_config en7523_clk_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
 static int en7523_clk_hw_init(struct platform_device *pdev,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	void __iomem *base, *np_base;
+	struct regmap *map, *clk_map;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	map = devm_regmap_init_mmio(&pdev->dev, base,
+				    &en7523_clk_regmap_config);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
 	np_base = devm_platform_ioremap_resource(pdev, 1);
 	if (IS_ERR(np_base))
 		return PTR_ERR(np_base);
 
-	en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
+	clk_map = devm_regmap_init_mmio(&pdev->dev, np_base,
+					&en7523_clk_regmap_config);
+	if (IS_ERR(clk_map))
+		return PTR_ERR(clk_map);
+
+	en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
 
 	return 0;
 }
 
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, void __iomem *base)
+				   struct regmap *map, struct regmap *clk_map)
 {
 	struct clk_hw *hw;
 	u32 rate;
@@ -593,7 +609,7 @@ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_dat
 		clk_data->hws[desc->id] = hw;
 	}
 
-	hw = en7523_register_pcie_clk(dev, base);
+	hw = en7523_register_pcie_clk(dev, clk_map);
 	clk_data->hws[EN7523_CLK_PCIE] = hw;
 }
 
@@ -601,15 +617,10 @@ static int en7523_reset_update(struct reset_controller_dev *rcdev,
 			       unsigned long id, bool assert)
 {
 	struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
-	void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
-	u32 val;
+	u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
 
-	val = readl(addr);
-	if (assert)
-		val |= BIT(id % RST_NR_PER_BANK);
-	else
-		val &= ~BIT(id % RST_NR_PER_BANK);
-	writel(val, addr);
+	regmap_update_bits(rst_data->map, addr, BIT(id % RST_NR_PER_BANK),
+			   assert ? BIT(id % RST_NR_PER_BANK) : 0);
 
 	return 0;
 }
@@ -630,9 +641,11 @@ static int en7523_reset_status(struct reset_controller_dev *rcdev,
 			       unsigned long id)
 {
 	struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
-	void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
+	u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
+	u32 val;
 
-	return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
+	regmap_read(rst_data->map, addr, &val);
+	return !!(val & BIT(id % RST_NR_PER_BANK));
 }
 
 static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
@@ -652,7 +665,7 @@ static const struct reset_control_ops en7581_reset_ops = {
 	.status = en7523_reset_status,
 };
 
-static int en7581_reset_register(struct device *dev, void __iomem *base)
+static int en7581_reset_register(struct device *dev, struct regmap *map)
 {
 	struct en_rst_data *rst_data;
 
@@ -662,7 +675,7 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
 
 	rst_data->bank_ofs = en7581_rst_ofs;
 	rst_data->idx_map = en7581_rst_map;
-	rst_data->base = base;
+	rst_data->map = map;
 
 	rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
 	rst_data->rcdev.of_xlate = en7523_reset_xlate;
@@ -678,9 +691,8 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
 static int en7581_clk_hw_init(struct platform_device *pdev,
 			      struct clk_hw_onecell_data *clk_data)
 {
-	struct regmap *map;
+	struct regmap *map, *clk_map;
 	void __iomem *base;
-	u32 val;
 
 	map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
 	if (IS_ERR(map))
@@ -690,15 +702,18 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	en7581_register_clocks(&pdev->dev, clk_data, map, base);
+	clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
+	if (IS_ERR(clk_map))
+		return PTR_ERR(clk_map);
+
+	en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
 
-	val = readl(base + REG_NP_SCU_SSTR);
-	val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
-	writel(val, base + REG_NP_SCU_SSTR);
-	val = readl(base + REG_NP_SCU_PCIC);
-	writel(val | 3, base + REG_NP_SCU_PCIC);
+	regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
+			  REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+	regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
+			   FIELD_PREP(REG_PCIE_CTRL, 3));
 
-	return en7581_reset_register(&pdev->dev, base);
+	return en7581_reset_register(&pdev->dev, clk_map);
 }
 
 static int en7523_clk_probe(struct platform_device *pdev)
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:25 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:25 +0100
Subject: [PATCH v2 02/11] clk: en7523: generalize register clocks function
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-3-ansuelsmth@gmail.com>

Generalize register clocks function for Airoha EN7523 and EN7581 clocks
driver. The same logic is applied for both clock hence code can be
reduced and simplified by putting the base_clocks struct in the soc_data
and passing that to a generic register clocks function.

There is always the pattern where the last clock is always the PCIe one.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c | 130 ++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 77 deletions(-)

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 314e7450313f..2a74bc8fed24 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -78,8 +78,10 @@ struct en_rst_data {
 
 struct en_clk_soc_data {
 	u32 num_clocks;
+	const struct en_clk_desc *base_clks;
 	const struct clk_ops pcie_ops;
 	int (*hw_init)(struct platform_device *pdev,
+		       const struct en_clk_soc_data *soc_data,
 		       struct clk_hw_onecell_data *clk_data);
 };
 
@@ -467,6 +469,50 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
 	return &cg->hw;
 }
 
+static void en75xx_register_clocks(struct device *dev,
+				   const struct en_clk_soc_data *soc_data,
+				   struct clk_hw_onecell_data *clk_data,
+				   struct regmap *map, struct regmap *clk_map)
+{
+	struct clk_hw *hw;
+	u32 rate;
+	int i;
+
+	for (i = 0; i < soc_data->num_clocks - 1; i++) {
+		const struct en_clk_desc *desc = &soc_data->base_clks[i];
+		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+		int err;
+
+		err = regmap_read(map, desc->base_reg, &val);
+		if (err) {
+			pr_err("Failed reading fixed clk rate %s: %d\n",
+			       desc->name, err);
+			continue;
+		}
+		rate = en7523_get_base_rate(desc, val);
+
+		err = regmap_read(map, reg, &val);
+		if (err) {
+			pr_err("Failed reading fixed clk div %s: %d\n",
+			       desc->name, err);
+			continue;
+		}
+		rate /= en7523_get_div(desc, val);
+
+		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register clk %s: %ld\n",
+			       desc->name, PTR_ERR(hw));
+			continue;
+		}
+
+		clk_data->hws[desc->id] = hw;
+	}
+
+	hw = en7523_register_pcie_clk(dev, clk_map);
+	clk_data->hws[soc_data->num_clocks] = hw;
+}
+
 static int en7581_pci_is_enabled(struct clk_hw *hw)
 {
 	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
@@ -504,38 +550,6 @@ static void en7581_pci_disable(struct clk_hw *hw)
 	usleep_range(1000, 2000);
 }
 
-static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, struct regmap *clk_map)
-{
-	struct clk_hw *hw;
-	u32 rate;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7523_base_clks[i];
-		u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		u32 val;
-
-		regmap_read(map, desc->base_reg, &val);
-
-		rate = en7523_get_base_rate(desc, val);
-		regmap_read(map, reg, &val);
-		rate /= en7523_get_div(desc, val);
-
-		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
-		if (IS_ERR(hw)) {
-			pr_err("Failed to register clk %s: %ld\n",
-			       desc->name, PTR_ERR(hw));
-			continue;
-		}
-
-		clk_data->hws[desc->id] = hw;
-	}
-
-	hw = en7523_register_pcie_clk(dev, clk_map);
-	clk_data->hws[EN7523_CLK_PCIE] = hw;
-}
-
 static const struct regmap_config en7523_clk_regmap_config = {
 	.reg_bits = 32,
 	.val_bits = 32,
@@ -543,6 +557,7 @@ static const struct regmap_config en7523_clk_regmap_config = {
 };
 
 static int en7523_clk_hw_init(struct platform_device *pdev,
+			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	void __iomem *base, *np_base;
@@ -566,53 +581,11 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(clk_map))
 		return PTR_ERR(clk_map);
 
-	en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
+	en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
 
 	return 0;
 }
 
-static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
-				   struct regmap *map, struct regmap *clk_map)
-{
-	struct clk_hw *hw;
-	u32 rate;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7581_base_clks[i];
-		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
-		int err;
-
-		err = regmap_read(map, desc->base_reg, &val);
-		if (err) {
-			pr_err("Failed reading fixed clk rate %s: %d\n",
-			       desc->name, err);
-			continue;
-		}
-		rate = en7523_get_base_rate(desc, val);
-
-		err = regmap_read(map, reg, &val);
-		if (err) {
-			pr_err("Failed reading fixed clk div %s: %d\n",
-			       desc->name, err);
-			continue;
-		}
-		rate /= en7523_get_div(desc, val);
-
-		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
-		if (IS_ERR(hw)) {
-			pr_err("Failed to register clk %s: %ld\n",
-			       desc->name, PTR_ERR(hw));
-			continue;
-		}
-
-		clk_data->hws[desc->id] = hw;
-	}
-
-	hw = en7523_register_pcie_clk(dev, clk_map);
-	clk_data->hws[EN7523_CLK_PCIE] = hw;
-}
-
 static int en7523_reset_update(struct reset_controller_dev *rcdev,
 			       unsigned long id, bool assert)
 {
@@ -689,6 +662,7 @@ static int en7581_reset_register(struct device *dev, struct regmap *map)
 }
 
 static int en7581_clk_hw_init(struct platform_device *pdev,
+			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	struct regmap *map, *clk_map;
@@ -706,7 +680,7 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	if (IS_ERR(clk_map))
 		return PTR_ERR(clk_map);
 
-	en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
+	en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
 
 	regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
 			  REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
@@ -732,7 +706,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	clk_data->num = soc_data->num_clocks;
-	r = soc_data->hw_init(pdev, clk_data);
+	r = soc_data->hw_init(pdev, soc_data, clk_data);
 	if (r)
 		return r;
 
@@ -740,6 +714,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
 }
 
 static const struct en_clk_soc_data en7523_data = {
+	.base_clks = en7523_base_clks,
 	.num_clocks = ARRAY_SIZE(en7523_base_clks) + 1,
 	.pcie_ops = {
 		.is_enabled = en7523_pci_is_enabled,
@@ -750,6 +725,7 @@ static const struct en_clk_soc_data en7523_data = {
 };
 
 static const struct en_clk_soc_data en7581_data = {
+	.base_clks = en7581_base_clks,
 	/* We increment num_clocks by 1 to account for additional PCIe clock */
 	.num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
 	.pcie_ops = {
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:31 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:31 +0100
Subject: [PATCH v2 08/11] phy: move Airoha PCIe PHY driver to dedicated directory
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-9-ansuelsmth@gmail.com>

To keep the generic PHY directory tidy, move the PCIe PHY driver to a
dedicated directory.

This is also in preparation for support of the Airoha USB PHY driver.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                               |    4 +-
 drivers/phy/Kconfig                       |   11 +-
 drivers/phy/Makefile                      |    5 +-
 drivers/phy/airoha/Kconfig                |   13 +
 drivers/phy/airoha/Makefile               |    3 +
 drivers/phy/airoha/phy-airoha-pcie-regs.h |  494 ++++++++
 drivers/phy/airoha/phy-airoha-pcie.c      | 1290 +++++++++++++++++++++
 7 files changed, 1806 insertions(+), 14 deletions(-)
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-airoha-pcie-regs.h
 create mode 100644 drivers/phy/airoha/phy-airoha-pcie.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c4a374da2b12..4e11db5d203a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -733,8 +733,8 @@ M:	Lorenzo Bianconi <lorenzo at kernel.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
-F:	drivers/phy/phy-airoha-pcie-regs.h
-F:	drivers/phy/phy-airoha-pcie.c
+F:	drivers/phy/airoha/phy-airoha-pcie-regs.h
+F:	drivers/phy/airoha/phy-airoha-pcie.c
 
 AIROHA SCU SSR DRIVER
 M:	Christian Marangi <ansuelsmth at gmail.com>
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d58efe998ec..7f9f5b786643 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -72,16 +72,6 @@ config PHY_CAN_TRANSCEIVER
 	  functional modes using gpios and sets the attribute max link
 	  rate, for CAN drivers.
 
-config PHY_AIROHA_PCIE
-	tristate "Airoha PCIe-PHY Driver"
-	depends on ARCH_AIROHA || COMPILE_TEST
-	depends on OF
-	select GENERIC_PHY
-	help
-	  Say Y here to add support for Airoha PCIe PHY driver.
-	  This driver create the basic PHY instance and provides initialize
-	  callback for PCIe GEN3 port.
-
 config PHY_NXP_PTN3222
 	tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
 	depends on I2C
@@ -93,6 +83,7 @@ config PHY_NXP_PTN3222
 	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
 	  Speed and High Speed.
 
+source "drivers/phy/airoha/Kconfig"
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/broadcom/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e281442acc75..9ab557db59e6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -10,9 +10,10 @@ obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
-obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
+
 obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
-obj-y					+= allwinner/	\
+obj-y					+= airoha/	\
+					   allwinner/	\
 					   amlogic/	\
 					   broadcom/	\
 					   cadence/	\
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
new file mode 100644
index 000000000000..70b7eac4a2bf
--- /dev/null
+++ b/drivers/phy/airoha/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Phy drivers for Airoha devices
+#
+config PHY_AIROHA_PCIE
+	tristate "Airoha PCIe-PHY Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Say Y here to add support for Airoha PCIe PHY driver.
+	  This driver create the basic PHY instance and provides initialize
+	  callback for PCIe GEN3 port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
new file mode 100644
index 000000000000..3222f749546b
--- /dev/null
+++ b/drivers/phy/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
diff --git a/drivers/phy/airoha/phy-airoha-pcie-regs.h b/drivers/phy/airoha/phy-airoha-pcie-regs.h
new file mode 100644
index 000000000000..b938a7b468fe
--- /dev/null
+++ b/drivers/phy/airoha/phy-airoha-pcie-regs.h
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 AIROHA Inc
+ * Author: Lorenzo Bianconi <lorenzo at kernel.org>
+ */
+
+#ifndef _PHY_AIROHA_PCIE_H
+#define _PHY_AIROHA_PCIE_H
+
+/* CSR_2L */
+#define REG_CSR_2L_CMN				0x0000
+#define CSR_2L_PXP_CMN_LANE_EN			BIT(0)
+#define CSR_2L_PXP_CMN_TRIM_MASK		GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_IB_EXT			0x0004
+#define REG_CSR_2L_JCPLL_LPF_SHCK_EN		BIT(8)
+#define CSR_2L_PXP_JCPLL_CHP_IBIAS		GENMASK(21, 16)
+#define CSR_2L_PXP_JCPLL_CHP_IOFST		GENMASK(29, 24)
+
+#define REG_CSR_2L_JCPLL_LPF_BR			0x0008
+#define CSR_2L_PXP_JCPLL_LPF_BR			GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_LPF_BC			GENMASK(12, 8)
+#define CSR_2L_PXP_JCPLL_LPF_BP			GENMASK(20, 16)
+#define CSR_2L_PXP_JCPLL_LPF_BWR		GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_LPF_BWC		0x000c
+#define CSR_2L_PXP_JCPLL_LPF_BWC		GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_KBAND_CODE		GENMASK(23, 16)
+#define CSR_2L_PXP_JCPLL_KBAND_DIV		GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_KBAND_KFC		0x0010
+#define CSR_2L_PXP_JCPLL_KBAND_KFC		GENMASK(1, 0)
+#define CSR_2L_PXP_JCPLL_KBAND_KF		GENMASK(9, 8)
+#define CSR_2L_PXP_JCPLL_KBAND_KS		GENMASK(17, 16)
+#define CSR_2L_PXP_JCPLL_POSTDIV_EN		BIT(24)
+
+#define REG_CSR_2L_JCPLL_MMD_PREDIV_MODE	0x0014
+#define CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE	GENMASK(1, 0)
+#define CSR_2L_PXP_JCPLL_POSTDIV_D2		BIT(16)
+#define CSR_2L_PXP_JCPLL_POSTDIV_D5		BIT(24)
+
+#define CSR_2L_PXP_JCPLL_MONCK			0x0018
+#define CSR_2L_PXP_JCPLL_REFIN_DIV		GENMASK(25, 24)
+
+#define REG_CSR_2L_JCPLL_RST_DLY		0x001c
+#define CSR_2L_PXP_JCPLL_RST_DLY		GENMASK(2, 0)
+#define CSR_2L_PXP_JCPLL_RST			BIT(8)
+#define CSR_2L_PXP_JCPLL_SDM_DI_EN		BIT(16)
+#define CSR_2L_PXP_JCPLL_SDM_DI_LS		GENMASK(25, 24)
+
+#define REG_CSR_2L_JCPLL_SDM_IFM		0x0020
+#define CSR_2L_PXP_JCPLL_SDM_IFM		BIT(0)
+
+#define REG_CSR_2L_JCPLL_SDM_HREN		0x0024
+#define CSR_2L_PXP_JCPLL_SDM_HREN		BIT(0)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_EN		BIT(8)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_GAIN		GENMASK(18, 16)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_VREF		GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_TCL_CMP		0x0028
+#define CSR_2L_PXP_JCPLL_TCL_LPF_EN		BIT(16)
+#define CSR_2L_PXP_JCPLL_TCL_LPF_BW		GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_VCODIV			0x002c
+#define CSR_2L_PXP_JCPLL_VCO_CFIX		GENMASK(9, 8)
+#define CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN		BIT(16)
+#define CSR_2L_PXP_JCPLL_VCO_SCAPWR		GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_VCO_TCLVAR		0x0030
+#define CSR_2L_PXP_JCPLL_VCO_TCLVAR		GENMASK(2, 0)
+
+#define REG_CSR_2L_JCPLL_SSC				0x0038
+#define CSR_2L_PXP_JCPLL_SSC_EN			BIT(0)
+#define CSR_2L_PXP_JCPLL_SSC_PHASE_INI		BIT(8)
+#define CSR_2L_PXP_JCPLL_SSC_TRI_EN		BIT(16)
+
+#define REG_CSR_2L_JCPLL_SSC_DELTA1		0x003c
+#define CSR_2L_PXP_JCPLL_SSC_DELTA1		GENMASK(15, 0)
+#define CSR_2L_PXP_JCPLL_SSC_DELTA		GENMASK(31, 16)
+
+#define REG_CSR_2L_JCPLL_SSC_PERIOD		0x0040
+#define CSR_2L_PXP_JCPLL_SSC_PERIOD		GENMASK(15, 0)
+
+#define REG_CSR_2L_JCPLL_TCL_VTP_EN		0x004c
+#define CSR_2L_PXP_JCPLL_SPARE_LOW		GENMASK(31, 24)
+
+#define REG_CSR_2L_JCPLL_TCL_KBAND_VREF		0x0050
+#define CSR_2L_PXP_JCPLL_TCL_KBAND_VREF		GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN	BIT(24)
+
+#define REG_CSR_2L_750M_SYS_CK			0x0054
+#define CSR_2L_PXP_TXPLL_LPF_SHCK_EN		BIT(16)
+#define CSR_2L_PXP_TXPLL_CHP_IBIAS		GENMASK(29, 24)
+
+#define REG_CSR_2L_TXPLL_CHP_IOFST		0x0058
+#define CSR_2L_PXP_TXPLL_CHP_IOFST		GENMASK(5, 0)
+#define CSR_2L_PXP_TXPLL_LPF_BR			GENMASK(12, 8)
+#define CSR_2L_PXP_TXPLL_LPF_BC			GENMASK(20, 16)
+#define CSR_2L_PXP_TXPLL_LPF_BP			GENMASK(28, 24)
+
+#define REG_CSR_2L_TXPLL_LPF_BWR		0x005c
+#define CSR_2L_PXP_TXPLL_LPF_BWR		GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_LPF_BWC		GENMASK(12, 8)
+#define CSR_2L_PXP_TXPLL_KBAND_CODE		GENMASK(31, 24)
+
+#define REG_CSR_2L_TXPLL_KBAND_DIV		0x0060
+#define CSR_2L_PXP_TXPLL_KBAND_DIV		GENMASK(2, 0)
+#define CSR_2L_PXP_TXPLL_KBAND_KFC		GENMASK(9, 8)
+#define CSR_2L_PXP_TXPLL_KBAND_KF		GENMASK(17, 16)
+#define CSR_2L_PXP_txpll_KBAND_KS		GENMASK(25, 24)
+
+#define REG_CSR_2L_TXPLL_POSTDIV		0x0064
+#define CSR_2L_PXP_TXPLL_POSTDIV_EN		BIT(0)
+#define CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE	GENMASK(9, 8)
+#define CSR_2L_PXP_TXPLL_PHY_CK1_EN		BIT(24)
+
+#define REG_CSR_2L_TXPLL_PHY_CK2		0x0068
+#define CSR_2L_PXP_TXPLL_REFIN_INTERNAL		BIT(24)
+
+#define REG_CSR_2L_TXPLL_REFIN_DIV		0x006c
+#define CSR_2L_PXP_TXPLL_REFIN_DIV		GENMASK(1, 0)
+#define CSR_2L_PXP_TXPLL_RST_DLY		GENMASK(10, 8)
+#define CSR_2L_PXP_TXPLL_PLL_RSTB		BIT(16)
+
+#define REG_CSR_2L_TXPLL_SDM_DI_LS		0x0070
+#define CSR_2L_PXP_TXPLL_SDM_DI_LS		GENMASK(1, 0)
+#define CSR_2L_PXP_TXPLL_SDM_IFM		BIT(8)
+#define CSR_2L_PXP_TXPLL_SDM_ORD		GENMASK(25, 24)
+
+#define REG_CSR_2L_TXPLL_SDM_OUT		0x0074
+#define CSR_2L_PXP_TXPLL_TCL_AMP_EN		BIT(16)
+#define CSR_2L_PXP_TXPLL_TCL_AMP_GAIN		GENMASK(26, 24)
+
+#define REG_CSR_2L_TXPLL_TCL_AMP_VREF		0x0078
+#define CSR_2L_PXP_TXPLL_TCL_AMP_VREF		GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_TCL_LPF_EN		BIT(24)
+
+#define REG_CSR_2L_TXPLL_TCL_LPF_BW		0x007c
+#define CSR_2L_PXP_TXPLL_TCL_LPF_BW		GENMASK(2, 0)
+#define CSR_2L_PXP_TXPLL_VCO_CFIX		GENMASK(17, 16)
+#define CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN		BIT(24)
+
+#define REG_CSR_2L_TXPLL_VCO_SCAPWR		0x0080
+#define CSR_2L_PXP_TXPLL_VCO_SCAPWR		GENMASK(2, 0)
+
+#define REG_CSR_2L_TXPLL_SSC			0x0084
+#define CSR_2L_PXP_TXPLL_SSC_EN			BIT(0)
+#define CSR_2L_PXP_TXPLL_SSC_PHASE_INI		BIT(8)
+
+#define REG_CSR_2L_TXPLL_SSC_DELTA1		0x0088
+#define CSR_2L_PXP_TXPLL_SSC_DELTA1		GENMASK(15, 0)
+#define CSR_2L_PXP_TXPLL_SSC_DELTA		GENMASK(31, 16)
+
+#define REG_CSR_2L_TXPLL_SSC_PERIOD		0x008c
+#define CSR_2L_PXP_txpll_SSC_PERIOD		GENMASK(15, 0)
+
+#define REG_CSR_2L_TXPLL_VTP			0x0090
+#define CSR_2L_PXP_TXPLL_VTP_EN			BIT(0)
+
+#define REG_CSR_2L_TXPLL_TCL_VTP		0x0098
+#define CSR_2L_PXP_TXPLL_SPARE_L		GENMASK(31, 24)
+
+#define REG_CSR_2L_TXPLL_TCL_KBAND_VREF		0x009c
+#define CSR_2L_PXP_TXPLL_TCL_KBAND_VREF		GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN	BIT(24)
+
+#define REG_CSR_2L_TXPLL_POSTDIV_D256		0x00a0
+#define CSR_2L_PXP_CLKTX0_AMP			GENMASK(10, 8)
+#define CSR_2L_PXP_CLKTX0_OFFSET		GENMASK(17, 16)
+#define CSR_2L_PXP_CLKTX0_SR			GENMASK(25, 24)
+
+#define REG_CSR_2L_CLKTX0_FORCE_OUT1		0x00a4
+#define CSR_2L_PXP_CLKTX0_HZ			BIT(8)
+#define CSR_2L_PXP_CLKTX0_IMP_SEL		GENMASK(20, 16)
+#define CSR_2L_PXP_CLKTX1_AMP			GENMASK(26, 24)
+
+#define REG_CSR_2L_CLKTX1_OFFSET		0x00a8
+#define CSR_2L_PXP_CLKTX1_OFFSET		GENMASK(1, 0)
+#define CSR_2L_PXP_CLKTX1_SR			GENMASK(9, 8)
+#define CSR_2L_PXP_CLKTX1_HZ			BIT(24)
+
+#define REG_CSR_2L_CLKTX1_IMP_SEL		0x00ac
+#define CSR_2L_PXP_CLKTX1_IMP_SEL		GENMASK(4, 0)
+
+#define REG_CSR_2L_PLL_CMN_RESERVE0		0x00b0
+#define CSR_2L_PXP_PLL_RESERVE_MASK		GENMASK(15, 0)
+
+#define REG_CSR_2L_TX0_CKLDO			0x00cc
+#define CSR_2L_PXP_TX0_CKLDO_EN			BIT(0)
+#define CSR_2L_PXP_TX0_DMEDGEGEN_EN		BIT(24)
+
+#define REG_CSR_2L_TX1_CKLDO			0x00e8
+#define CSR_2L_PXP_TX1_CKLDO_EN			BIT(0)
+#define CSR_2L_PXP_TX1_DMEDGEGEN_EN		BIT(24)
+
+#define REG_CSR_2L_TX1_MULTLANE			0x00ec
+#define CSR_2L_PXP_TX1_MULTLANE_EN		BIT(0)
+
+#define REG_CSR_2L_RX0_REV0			0x00fc
+#define CSR_2L_PXP_VOS_PNINV			GENMASK(19, 18)
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE		GENMASK(22, 20)
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE		GENMASK(26, 24)
+
+#define REG_CSR_2L_RX0_PHYCK_DIV		0x0100
+#define CSR_2L_PXP_RX0_PHYCK_SEL		GENMASK(9, 8)
+#define CSR_2L_PXP_RX0_PHYCK_RSTB		BIT(16)
+#define CSR_2L_PXP_RX0_TDC_CK_SEL		BIT(24)
+
+#define REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV	0x0104
+#define CSR_2L_PXP_CDR0_PD_EDGE_DISABLE		BIT(8)
+
+#define REG_CSR_2L_CDR0_LPF_RATIO		0x0110
+#define CSR_2L_PXP_CDR0_LPF_TOP_LIM		GENMASK(26, 8)
+
+#define REG_CSR_2L_CDR0_PR_INJ_MODE		0x011c
+#define CSR_2L_PXP_CDR0_INJ_FORCE_OFF		BIT(24)
+
+#define REG_CSR_2L_CDR0_PR_BETA_DAC		0x0120
+#define CSR_2L_PXP_CDR0_PR_BETA_SEL		GENMASK(19, 16)
+#define CSR_2L_PXP_CDR0_PR_KBAND_DIV		GENMASK(26, 24)
+
+#define REG_CSR_2L_CDR0_PR_VREG_IBAND		0x0124
+#define CSR_2L_PXP_CDR0_PR_VREG_IBAND		GENMASK(2, 0)
+#define CSR_2L_PXP_CDR0_PR_VREG_CKBUF		GENMASK(10, 8)
+
+#define REG_CSR_2L_CDR0_PR_CKREF_DIV		0x0128
+#define CSR_2L_PXP_CDR0_PR_CKREF_DIV		GENMASK(1, 0)
+
+#define REG_CSR_2L_CDR0_PR_MONCK		0x012c
+#define CSR_2L_PXP_CDR0_PR_MONCK_ENABLE		BIT(0)
+#define CSR_2L_PXP_CDR0_PR_RESERVE0		GENMASK(19, 16)
+
+#define REG_CSR_2L_CDR0_PR_COR_HBW		0x0130
+#define CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON		BIT(8)
+#define CSR_2L_PXP_CDR0_PR_CKREF_DIV1		GENMASK(17, 16)
+
+#define REG_CSR_2L_CDR0_PR_MONPI		0x0134
+#define CSR_2L_PXP_CDR0_PR_XFICK_EN		BIT(8)
+
+#define REG_CSR_2L_RX0_SIGDET_DCTEST		0x0140
+#define CSR_2L_PXP_RX0_SIGDET_LPF_CTRL		GENMASK(9, 8)
+#define CSR_2L_PXP_RX0_SIGDET_PEAK		GENMASK(25, 24)
+
+#define REG_CSR_2L_RX0_SIGDET_VTH_SEL		0x0144
+#define CSR_2L_PXP_RX0_SIGDET_VTH_SEL		GENMASK(4, 0)
+#define CSR_2L_PXP_RX0_FE_VB_EQ1_EN		BIT(24)
+
+#define REG_CSR_2L_PXP_RX0_FE_VB_EQ2		0x0148
+#define CSR_2L_PXP_RX0_FE_VB_EQ2_EN		BIT(0)
+#define CSR_2L_PXP_RX0_FE_VB_EQ3_EN		BIT(8)
+#define CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB		BIT(16)
+
+#define REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS	0x0158
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS		GENMASK(29, 24)
+
+#define REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS		0x015c
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS		GENMASK(5, 0)
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS		GENMASK(13, 8)
+
+#define REG_CSR_2L_RX1_REV0			0x01b4
+
+#define REG_CSR_2L_RX1_PHYCK_DIV		0x01b8
+#define CSR_2L_PXP_RX1_PHYCK_SEL		GENMASK(9, 8)
+#define CSR_2L_PXP_RX1_PHYCK_RSTB		BIT(16)
+#define CSR_2L_PXP_RX1_TDC_CK_SEL		BIT(24)
+
+#define REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV	0x01bc
+#define CSR_2L_PXP_CDR1_PD_EDGE_DISABLE		BIT(8)
+
+#define REG_CSR_2L_CDR1_PR_BETA_DAC		0x01d8
+#define CSR_2L_PXP_CDR1_PR_BETA_SEL		GENMASK(19, 16)
+#define CSR_2L_PXP_CDR1_PR_KBAND_DIV		GENMASK(26, 24)
+
+#define REG_CSR_2L_CDR1_PR_MONCK		0x01e4
+#define CSR_2L_PXP_CDR1_PR_MONCK_ENABLE		BIT(0)
+#define CSR_2L_PXP_CDR1_PR_RESERVE0		GENMASK(19, 16)
+
+#define REG_CSR_2L_CDR1_LPF_RATIO		0x01c8
+#define CSR_2L_PXP_CDR1_LPF_TOP_LIM		GENMASK(26, 8)
+
+#define REG_CSR_2L_CDR1_PR_INJ_MODE		0x01d4
+#define CSR_2L_PXP_CDR1_INJ_FORCE_OFF		BIT(24)
+
+#define REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL	0x01dc
+#define CSR_2L_PXP_CDR1_PR_VREG_IBAND		GENMASK(2, 0)
+#define CSR_2L_PXP_CDR1_PR_VREG_CKBUF		GENMASK(10, 8)
+
+#define REG_CSR_2L_CDR1_PR_CKREF_DIV		0x01e0
+#define CSR_2L_PXP_CDR1_PR_CKREF_DIV		GENMASK(1, 0)
+
+#define REG_CSR_2L_CDR1_PR_COR_HBW		0x01e8
+#define CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON		BIT(8)
+#define CSR_2L_PXP_CDR1_PR_CKREF_DIV1		GENMASK(17, 16)
+
+#define REG_CSR_2L_CDR1_PR_MONPI		0x01ec
+#define CSR_2L_PXP_CDR1_PR_XFICK_EN		BIT(8)
+
+#define REG_CSR_2L_RX1_DAC_RANGE_EYE		0x01f4
+#define CSR_2L_PXP_RX1_SIGDET_LPF_CTRL		GENMASK(25, 24)
+
+#define REG_CSR_2L_RX1_SIGDET_NOVTH		0x01f8
+#define CSR_2L_PXP_RX1_SIGDET_PEAK		GENMASK(9, 8)
+#define CSR_2L_PXP_RX1_SIGDET_VTH_SEL		GENMASK(20, 16)
+
+#define REG_CSR_2L_RX1_FE_VB_EQ1		0x0200
+#define CSR_2L_PXP_RX1_FE_VB_EQ1_EN		BIT(0)
+#define CSR_2L_PXP_RX1_FE_VB_EQ2_EN		BIT(8)
+#define CSR_2L_PXP_RX1_FE_VB_EQ3_EN		BIT(16)
+#define CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB		BIT(24)
+
+#define REG_CSR_2L_RX1_OSCAL_VGA1IOS		0x0214
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS		GENMASK(5, 0)
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS		GENMASK(13, 8)
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS		GENMASK(21, 16)
+
+/* PMA */
+#define REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1	0x0004
+#define PCIE_LCPLL_MAN_PWDB			BIT(0)
+
+#define REG_PCIE_PMA_SEQUENCE_DISB_CTRL1	0x010c
+#define PCIE_DISB_RX_SDCAL_EN			BIT(0)
+
+#define REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1	0x0114
+#define PCIE_FORCE_RX_SDCAL_EN			BIT(0)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET1		0x014c
+#define PCIE_PLL_FT_LOCK_CYCLECNT		GENMASK(15, 0)
+#define PCIE_PLL_FT_UNLOCK_CYCLECNT		GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET2		0x0150
+#define PCIE_LOCK_TARGET_BEG			GENMASK(15, 0)
+#define PCIE_LOCK_TARGET_END			GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET3		0x0154
+#define PCIE_UNLOCK_TARGET_BEG			GENMASK(15, 0)
+#define PCIE_UNLOCK_TARGET_END			GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET4		0x0158
+#define PCIE_FREQLOCK_DET_EN			GENMASK(2, 0)
+#define PCIE_LOCK_LOCKTH			GENMASK(11, 8)
+#define PCIE_UNLOCK_LOCKTH			GENMASK(15, 12)
+
+#define REG_PCIE_PMA_SS_RX_CAL1			0x0160
+#define REG_PCIE_PMA_SS_RX_CAL2			0x0164
+#define PCIE_CAL_OUT_OS				GENMASK(11, 8)
+
+#define REG_PCIE_PMA_SS_RX_SIGDET0		0x0168
+#define PCIE_SIGDET_WIN_NONVLD_TIMES		GENMASK(28, 24)
+
+#define REG_PCIE_PMA_TX_RESET			0x0260
+#define PCIE_TX_TOP_RST				BIT(0)
+#define PCIE_TX_CAL_RST				BIT(8)
+
+#define REG_PCIE_PMA_RX_FORCE_MODE0		0x0294
+#define PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL	GENMASK(1, 0)
+
+#define REG_PCIE_PMA_SS_DA_XPON_PWDB0		0x034c
+#define PCIE_DA_XPON_CDR_PR_PWDB		BIT(8)
+
+#define REG_PCIE_PMA_SW_RESET			0x0460
+#define PCIE_SW_RX_FIFO_RST			BIT(0)
+#define PCIE_SW_RX_RST				BIT(1)
+#define PCIE_SW_TX_RST				BIT(2)
+#define PCIE_SW_PMA_RST				BIT(3)
+#define PCIE_SW_ALLPCS_RST			BIT(4)
+#define PCIE_SW_REF_RST				BIT(5)
+#define PCIE_SW_TX_FIFO_RST			BIT(6)
+#define PCIE_SW_XFI_TXPCS_RST			BIT(7)
+#define PCIE_SW_XFI_RXPCS_RST			BIT(8)
+#define PCIE_SW_XFI_RXPCS_BIST_RST		BIT(9)
+#define PCIE_SW_HSG_TXPCS_RST			BIT(10)
+#define PCIE_SW_HSG_RXPCS_RST			BIT(11)
+#define PCIE_PMA_SW_RST				(PCIE_SW_RX_FIFO_RST | \
+						 PCIE_SW_RX_RST | \
+						 PCIE_SW_TX_RST | \
+						 PCIE_SW_PMA_RST | \
+						 PCIE_SW_ALLPCS_RST | \
+						 PCIE_SW_REF_RST | \
+						 PCIE_SW_TX_FIFO_RST | \
+						 PCIE_SW_XFI_TXPCS_RST | \
+						 PCIE_SW_XFI_RXPCS_RST | \
+						 PCIE_SW_XFI_RXPCS_BIST_RST | \
+						 PCIE_SW_HSG_TXPCS_RST | \
+						 PCIE_SW_HSG_RXPCS_RST)
+
+#define REG_PCIE_PMA_RO_RX_FREQDET		0x0530
+#define PCIE_RO_FBCK_LOCK			BIT(0)
+#define PCIE_RO_FL_OUT				GENMASK(31, 16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC	0x0794
+#define PCIE_FORCE_DA_PXP_CDR_PR_IDAC		GENMASK(10, 0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC	BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW	BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW	0x0798
+#define PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW		GENMASK(30, 0)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS	0x079c
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW	BIT(16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW	0x0800
+#define PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW		GENMASK(30, 0)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB	0x081c
+#define PCIE_FORCE_DA_PXP_CDR_PD_PWDB		BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB	BIT(8)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C	0x0820
+#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN	BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN	BIT(8)
+#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN	BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN	BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB	0x0824
+#define PCIE_FORCE_DA_PXP_CDR_PR_PWDB			BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB		BIT(24)
+
+#define REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT	0x0828
+#define PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN	BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN	BIT(8)
+#define PCIE_FORCE_DA_PXP_JCPLL_EN		BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_EN		BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST	0x0084c
+#define PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB	BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB	BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT	0x0854
+#define PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN	BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN	BIT(8)
+#define PCIE_FORCE_DA_PXP_TXPLL_EN		BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_EN		BIT(24)
+
+#define REG_PCIE_PMA_SCAN_MODE				0x0884
+#define PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN		BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN	BIT(8)
+
+#define REG_PCIE_PMA_DIG_RESERVE_13		0x08bc
+#define PCIE_FLL_IDAC_PCIEG1			GENMASK(10, 0)
+#define PCIE_FLL_IDAC_PCIEG2			GENMASK(26, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_14		0x08c0
+#define PCIE_FLL_IDAC_PCIEG3			GENMASK(10, 0)
+#define PCIE_FLL_LOAD_EN			BIT(16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL	0x088c
+#define PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL		GENMASK(1, 0)
+#define PCIE_FORCE_SEL_DA_PXP_RX_FE_GAIN_CTRL		BIT(8)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB	0x0894
+#define PCIE_FORCE_DA_PXP_RX_FE_PWDB		BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB	BIT(8)
+
+#define REG_PCIE_PMA_DIG_RESERVE_12		0x08b8
+#define PCIE_FORCE_PMA_RX_SPEED			GENMASK(7, 4)
+#define PCIE_FORCE_SEL_PMA_RX_SPEED		BIT(7)
+
+#define REG_PCIE_PMA_DIG_RESERVE_17		0x08e0
+
+#define REG_PCIE_PMA_DIG_RESERVE_18		0x08e4
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G1		GENMASK(4, 0)
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G2		GENMASK(12, 8)
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G3		GENMASK(20, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_19		0x08e8
+#define PCIE_PCP_RX_REV0_PCIE_GEN1		GENMASK(31, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_20		0x08ec
+#define PCIE_PCP_RX_REV0_PCIE_GEN2		GENMASK(15, 0)
+#define PCIE_PCP_RX_REV0_PCIE_GEN3		GENMASK(31, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_21		0x08f0
+#define REG_PCIE_PMA_DIG_RESERVE_22		0x08f4
+#define REG_PCIE_PMA_DIG_RESERVE_27		0x0908
+#define REG_PCIE_PMA_DIG_RESERVE_30		0x0914
+
+/* DTIME */
+#define REG_PCIE_PEXTP_DIG_GLB44		0x00
+#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL	GENMASK(7, 0)
+#define PCIE_XTP_RXDET_EN_STB_T_SEL		GENMASK(15, 8)
+#define PCIE_XTP_RXDET_FINISH_STB_T_SEL		GENMASK(23, 16)
+#define PCIE_XTP_TXPD_TX_DATA_EN_DLY		GENMASK(27, 24)
+#define PCIE_XTP_TXPD_RXDET_DONE_CDT		BIT(28)
+#define PCIE_XTP_RXDET_LATCH_STB_T_SEL		GENMASK(31, 29)
+
+/* RX AEQ */
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P0		0x0000
+#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT	GENMASK(7, 0)
+#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN	BIT(8)
+#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT	GENMASK(31, 16)
+
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P1		0x0100
+
+#endif /* _PHY_AIROHA_PCIE_H */
diff --git a/drivers/phy/airoha/phy-airoha-pcie.c b/drivers/phy/airoha/phy-airoha-pcie.c
new file mode 100644
index 000000000000..56e9ade8a9fd
--- /dev/null
+++ b/drivers/phy/airoha/phy-airoha-pcie.c
@@ -0,0 +1,1290 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 AIROHA Inc
+ * Author: Lorenzo Bianconi <lorenzo at kernel.org>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "phy-airoha-pcie-regs.h"
+
+#define LEQ_LEN_CTRL_MAX_VAL	7
+#define FREQ_LOCK_MAX_ATTEMPT	10
+
+/* PCIe-PHY initialization time in ms needed by the hw to complete */
+#define PHY_HW_INIT_TIME_MS	30
+
+enum airoha_pcie_port_gen {
+	PCIE_PORT_GEN1 = 1,
+	PCIE_PORT_GEN2,
+	PCIE_PORT_GEN3,
+};
+
+/**
+ * struct airoha_pcie_phy - PCIe phy driver main structure
+ * @dev: pointer to device
+ * @phy: pointer to generic phy
+ * @csr_2l: Analogic lane IO mapped register base address
+ * @pma0: IO mapped register base address of PMA0-PCIe
+ * @pma1: IO mapped register base address of PMA1-PCIe
+ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
+ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
+ * @rx_aeq: IO mapped register base address of Rx AEQ training
+ */
+struct airoha_pcie_phy {
+	struct device *dev;
+	struct phy *phy;
+	void __iomem *csr_2l;
+	void __iomem *pma0;
+	void __iomem *pma1;
+	void __iomem *p0_xr_dtime;
+	void __iomem *p1_xr_dtime;
+	void __iomem *rx_aeq;
+};
+
+static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
+{
+	u32 val = readl(reg) & ~mask;
+
+	writel(val, reg);
+}
+
+static void airoha_phy_set_bits(void __iomem *reg, u32 mask)
+{
+	u32 val = readl(reg) | mask;
+
+	writel(val, reg);
+}
+
+static void airoha_phy_update_bits(void __iomem *reg, u32 mask, u32 val)
+{
+	u32 tmp = readl(reg);
+
+	tmp &= ~mask;
+	tmp |= val & mask;
+	writel(tmp, reg);
+}
+
+#define airoha_phy_update_field(reg, mask, val)					\
+	do {									\
+		BUILD_BUG_ON_MSG(!__builtin_constant_p((mask)),			\
+				 "mask is not constant");			\
+		airoha_phy_update_bits((reg), (mask),				\
+				       FIELD_PREP((mask), (val)));		\
+	} while (0)
+
+#define airoha_phy_csr_2l_clear_bits(pcie_phy, reg, mask)			\
+	airoha_phy_clear_bits((pcie_phy)->csr_2l + (reg), (mask))
+#define airoha_phy_csr_2l_set_bits(pcie_phy, reg, mask)				\
+	airoha_phy_set_bits((pcie_phy)->csr_2l + (reg), (mask))
+#define airoha_phy_csr_2l_update_field(pcie_phy, reg, mask, val)		\
+	airoha_phy_update_field((pcie_phy)->csr_2l + (reg), (mask), (val))
+#define airoha_phy_pma0_clear_bits(pcie_phy, reg, mask)				\
+	airoha_phy_clear_bits((pcie_phy)->pma0 + (reg), (mask))
+#define airoha_phy_pma1_clear_bits(pcie_phy, reg, mask)				\
+	airoha_phy_clear_bits((pcie_phy)->pma1 + (reg), (mask))
+#define airoha_phy_pma0_set_bits(pcie_phy, reg, mask)				\
+	airoha_phy_set_bits((pcie_phy)->pma0 + (reg), (mask))
+#define airoha_phy_pma1_set_bits(pcie_phy, reg, mask)				\
+	airoha_phy_set_bits((pcie_phy)->pma1 + (reg), (mask))
+#define airoha_phy_pma0_update_field(pcie_phy, reg, mask, val)			\
+	airoha_phy_update_field((pcie_phy)->pma0 + (reg), (mask), (val))
+#define airoha_phy_pma1_update_field(pcie_phy, reg, mask, val)			\
+	airoha_phy_update_field((pcie_phy)->pma1 + (reg), (mask), (val))
+
+static void
+airoha_phy_init_lane0_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
+				      enum airoha_pcie_port_gen gen)
+{
+	u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
+	u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
+	u32 pr_idac, val, cdr_pr_idac_tmp = 0;
+	int i;
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
+				 PCIE_LCPLL_MAN_PWDB);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+				     PCIE_LOCK_TARGET_BEG,
+				     fl_out_target - 100);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+				     PCIE_LOCK_TARGET_END,
+				     fl_out_target + 100);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+				     PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+				     PCIE_LOCK_LOCKTH, 0x3);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+				     PCIE_UNLOCK_TARGET_BEG,
+				     fl_out_target - 100);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+				     PCIE_UNLOCK_TARGET_END,
+				     fl_out_target + 100);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+				     PCIE_PLL_FT_UNLOCK_CYCLECNT,
+				     lock_cyclecnt);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+				     PCIE_UNLOCK_LOCKTH, 0x3);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
+				   CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				   PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				 PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+
+	for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
+		airoha_phy_pma0_update_field(pcie_phy,
+				REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
+		airoha_phy_pma0_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = FIELD_GET(PCIE_RO_FL_OUT,
+				readl(pcie_phy->pma0 +
+				      REG_PCIE_PMA_RO_RX_FREQDET));
+		if (val > fl_out_target)
+			cdr_pr_idac_tmp = i << 8;
+	}
+
+	for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
+		pr_idac = cdr_pr_idac_tmp | (0x1 << i);
+		airoha_phy_pma0_update_field(pcie_phy,
+				REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
+		airoha_phy_pma0_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = FIELD_GET(PCIE_RO_FL_OUT,
+				readl(pcie_phy->pma0 +
+				      REG_PCIE_PMA_RO_RX_FREQDET));
+		if (val < fl_out_target)
+			pr_idac &= ~(0x1 << i);
+
+		cdr_pr_idac_tmp = pr_idac;
+	}
+
+	airoha_phy_pma0_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				     PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
+				     cdr_pr_idac_tmp);
+
+	for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
+		u32 val;
+
+		airoha_phy_pma0_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = readl(pcie_phy->pma0 + REG_PCIE_PMA_RO_RX_FREQDET);
+		if (val & PCIE_RO_FBCK_LOCK)
+			break;
+	}
+
+	/* turn off force mode and update band values */
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
+				     CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
+
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+	if (gen == PCIE_PORT_GEN3) {
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_14,
+					     PCIE_FLL_IDAC_PCIEG3,
+					     cdr_pr_idac_tmp);
+	} else {
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_13,
+					     PCIE_FLL_IDAC_PCIEG1,
+					     cdr_pr_idac_tmp);
+		airoha_phy_pma0_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_13,
+					     PCIE_FLL_IDAC_PCIEG2,
+					     cdr_pr_idac_tmp);
+	}
+}
+
+static void
+airoha_phy_init_lane1_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
+				      enum airoha_pcie_port_gen gen)
+{
+	u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
+	u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
+	u32 pr_idac, val, cdr_pr_idac_tmp = 0;
+	int i;
+
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
+				 PCIE_LCPLL_MAN_PWDB);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+				     PCIE_LOCK_TARGET_BEG,
+				     fl_out_target - 100);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+				     PCIE_LOCK_TARGET_END,
+				     fl_out_target + 100);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+				     PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+				     PCIE_LOCK_LOCKTH, 0x3);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+				     PCIE_UNLOCK_TARGET_BEG,
+				     fl_out_target - 100);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+				     PCIE_UNLOCK_TARGET_END,
+				     fl_out_target + 100);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+				     PCIE_PLL_FT_UNLOCK_CYCLECNT,
+				     lock_cyclecnt);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+				     PCIE_UNLOCK_LOCKTH, 0x3);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
+				   CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
+
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				   PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				 PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+
+	for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
+		airoha_phy_pma1_update_field(pcie_phy,
+				REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
+		airoha_phy_pma1_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = FIELD_GET(PCIE_RO_FL_OUT,
+				readl(pcie_phy->pma1 +
+				      REG_PCIE_PMA_RO_RX_FREQDET));
+		if (val > fl_out_target)
+			cdr_pr_idac_tmp = i << 8;
+	}
+
+	for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
+		pr_idac = cdr_pr_idac_tmp | (0x1 << i);
+		airoha_phy_pma1_update_field(pcie_phy,
+				REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
+		airoha_phy_pma1_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = FIELD_GET(PCIE_RO_FL_OUT,
+				readl(pcie_phy->pma1 +
+				      REG_PCIE_PMA_RO_RX_FREQDET));
+		if (val < fl_out_target)
+			pr_idac &= ~(0x1 << i);
+
+		cdr_pr_idac_tmp = pr_idac;
+	}
+
+	airoha_phy_pma1_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				     PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
+				     cdr_pr_idac_tmp);
+
+	for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
+		u32 val;
+
+		airoha_phy_pma1_clear_bits(pcie_phy,
+					   REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					   PCIE_FREQLOCK_DET_EN);
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_SS_RX_FREQ_DET4,
+					     PCIE_FREQLOCK_DET_EN, 0x3);
+
+		usleep_range(10000, 15000);
+
+		val = readl(pcie_phy->pma1 + REG_PCIE_PMA_RO_RX_FREQDET);
+		if (val & PCIE_RO_FBCK_LOCK)
+			break;
+	}
+
+	/* turn off force mode and update band values */
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
+				     CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
+
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				   PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+	if (gen == PCIE_PORT_GEN3) {
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_14,
+					     PCIE_FLL_IDAC_PCIEG3,
+					     cdr_pr_idac_tmp);
+	} else {
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_13,
+					     PCIE_FLL_IDAC_PCIEG1,
+					     cdr_pr_idac_tmp);
+		airoha_phy_pma1_update_field(pcie_phy,
+					     REG_PCIE_PMA_DIG_RESERVE_13,
+					     PCIE_FLL_IDAC_PCIEG2,
+					     cdr_pr_idac_tmp);
+	}
+}
+
+static void airoha_pcie_phy_init_default(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CMN,
+				       CSR_2L_PXP_CMN_TRIM_MASK, 0x10);
+	writel(0xcccbcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_21);
+	writel(0xcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_22);
+	writel(0xcccbcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_21);
+	writel(0xcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_22);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CMN,
+				   CSR_2L_PXP_CMN_LANE_EN);
+}
+
+static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_TXPLL_POSTDIV_D256,
+				       CSR_2L_PXP_CLKTX0_AMP, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_CLKTX0_FORCE_OUT1,
+				       CSR_2L_PXP_CLKTX1_AMP, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_TXPLL_POSTDIV_D256,
+				       CSR_2L_PXP_CLKTX0_OFFSET, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+				       CSR_2L_PXP_CLKTX1_OFFSET, 0x2);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX0_FORCE_OUT1,
+				     CSR_2L_PXP_CLKTX0_HZ);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+				     CSR_2L_PXP_CLKTX1_HZ);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_CLKTX0_FORCE_OUT1,
+				       CSR_2L_PXP_CLKTX0_IMP_SEL, 0x12);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_IMP_SEL,
+				       CSR_2L_PXP_CLKTX1_IMP_SEL, 0x12);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV_D256,
+				     CSR_2L_PXP_CLKTX0_SR);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+				     CSR_2L_PXP_CLKTX1_SR);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
+				       CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
+}
+
+static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				 PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
+				 PCIE_SW_RX_RST);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				 PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
+				 PCIE_SW_RX_RST);
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
+				 PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
+				 PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
+}
+
+static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
+{
+	writel(0x2a00090b, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_17);
+	writel(0x2a00090b, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_17);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONPI,
+				   CSR_2L_PXP_CDR0_PR_XFICK_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONPI,
+				   CSR_2L_PXP_CDR1_PR_XFICK_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy,
+				     REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV,
+				     CSR_2L_PXP_CDR0_PD_EDGE_DISABLE);
+	airoha_phy_csr_2l_clear_bits(pcie_phy,
+				     REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV,
+				     CSR_2L_PXP_CDR1_PD_EDGE_DISABLE);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
+				       CSR_2L_PXP_RX0_PHYCK_SEL, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
+				       CSR_2L_PXP_RX1_PHYCK_SEL, 0x1);
+}
+
+static void airoha_pcie_phy_init_jcpll(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				   PCIE_FORCE_DA_PXP_JCPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				   PCIE_FORCE_DA_PXP_JCPLL_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_VTP_EN,
+				       CSR_2L_PXP_JCPLL_SPARE_LOW, 0x20);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+				   CSR_2L_PXP_JCPLL_RST);
+	writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_JCPLL_SSC_DELTA1);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
+				     CSR_2L_PXP_JCPLL_SSC_PERIOD);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				     CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				     CSR_2L_PXP_JCPLL_SSC_TRI_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+				       CSR_2L_PXP_JCPLL_LPF_BR, 0xa);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+				       CSR_2L_PXP_JCPLL_LPF_BP, 0xc);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+				       CSR_2L_PXP_JCPLL_LPF_BC, 0x1f);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+				       CSR_2L_PXP_JCPLL_LPF_BWC, 0x1e);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+				       CSR_2L_PXP_JCPLL_LPF_BWR, 0xa);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+				       CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
+				       0x1);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, CSR_2L_PXP_JCPLL_MONCK,
+				     CSR_2L_PXP_JCPLL_REFIN_DIV);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
+	airoha_phy_pma0_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
+				     PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
+				     0x50000000);
+	airoha_phy_pma1_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
+				     PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
+				     0x50000000);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy,
+				   REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+				   CSR_2L_PXP_JCPLL_POSTDIV_D5);
+	airoha_phy_csr_2l_set_bits(pcie_phy,
+				   REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+				   CSR_2L_PXP_JCPLL_POSTDIV_D2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+				       CSR_2L_PXP_JCPLL_RST_DLY, 0x4);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+				     CSR_2L_PXP_JCPLL_SDM_DI_LS);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
+				     CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+				     CSR_2L_PXP_JCPLL_CHP_IOFST);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+				       CSR_2L_PXP_JCPLL_CHP_IBIAS, 0xc);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+				       CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
+				       0x1);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+				   CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+				       CSR_2L_PXP_JCPLL_VCO_CFIX, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+				       CSR_2L_PXP_JCPLL_VCO_SCAPWR, 0x4);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+				     REG_CSR_2L_JCPLL_LPF_SHCK_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+				   CSR_2L_PXP_JCPLL_POSTDIV_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+				     CSR_2L_PXP_JCPLL_KBAND_KFC);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+				       CSR_2L_PXP_JCPLL_KBAND_KF, 0x3);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+				     CSR_2L_PXP_JCPLL_KBAND_KS);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+				       CSR_2L_PXP_JCPLL_KBAND_DIV, 0x1);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
+				   PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+				       CSR_2L_PXP_JCPLL_KBAND_CODE, 0xe4);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+				   CSR_2L_PXP_JCPLL_TCL_AMP_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
+				   CSR_2L_PXP_JCPLL_TCL_LPF_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
+				       CSR_2L_PXP_JCPLL_TCL_KBAND_VREF, 0xf);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+				       CSR_2L_PXP_JCPLL_TCL_AMP_GAIN, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+				       CSR_2L_PXP_JCPLL_TCL_AMP_VREF, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
+				       CSR_2L_PXP_JCPLL_TCL_LPF_BW, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCO_TCLVAR,
+				       CSR_2L_PXP_JCPLL_VCO_TCLVAR, 0x3);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_JCPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_JCPLL_EN);
+}
+
+static void airoha_pcie_phy_txpll(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				   PCIE_FORCE_DA_PXP_TXPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				   PCIE_FORCE_DA_PXP_TXPLL_EN);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+				   CSR_2L_PXP_TXPLL_PLL_RSTB);
+	writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC_PERIOD,
+				     CSR_2L_PXP_txpll_SSC_PERIOD);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+				       CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+				       CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+				     CSR_2L_PXP_TXPLL_REFIN_DIV);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+				       CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+	airoha_phy_pma0_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
+				     PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
+				     0xc800000);
+	airoha_phy_pma1_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
+				     PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
+				     0xc800000);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+				     CSR_2L_PXP_TXPLL_SDM_IFM);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+				     CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+				       CSR_2L_PXP_TXPLL_RST_DLY, 0x4);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+				     CSR_2L_PXP_TXPLL_SDM_DI_LS);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+				       CSR_2L_PXP_TXPLL_SDM_ORD, 0x3);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+				     CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
+	writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+				       CSR_2L_PXP_TXPLL_LPF_BP, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+				       CSR_2L_PXP_TXPLL_LPF_BC, 0x18);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+				       CSR_2L_PXP_TXPLL_LPF_BR, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+				       CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+				       CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_VTP,
+				       CSR_2L_PXP_TXPLL_SPARE_L, 0x1);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+				     CSR_2L_PXP_TXPLL_LPF_BWC);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+				     CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+				     CSR_2L_PXP_TXPLL_REFIN_DIV);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+				   CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_VCO_SCAPWR,
+				       CSR_2L_PXP_TXPLL_VCO_SCAPWR, 0x7);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+				       CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+				     CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+				     CSR_2L_PXP_TXPLL_LPF_BWR);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
+				   CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+				     CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_VTP,
+				     CSR_2L_PXP_TXPLL_VTP_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+				     CSR_2L_PXP_TXPLL_PHY_CK1_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
+				   CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+				     CSR_2L_PXP_TXPLL_SSC_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+				     CSR_2L_PXP_TXPLL_LPF_SHCK_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+				     CSR_2L_PXP_TXPLL_POSTDIV_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+				     CSR_2L_PXP_TXPLL_KBAND_KFC);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+				       CSR_2L_PXP_TXPLL_KBAND_KF, 0x3);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+				       CSR_2L_PXP_txpll_KBAND_KS, 0x1);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+				       CSR_2L_PXP_TXPLL_KBAND_DIV, 0x4);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+				       CSR_2L_PXP_TXPLL_KBAND_CODE, 0xe4);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
+				   CSR_2L_PXP_TXPLL_TCL_AMP_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_AMP_VREF,
+				   CSR_2L_PXP_TXPLL_TCL_LPF_EN);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+				       CSR_2L_PXP_TXPLL_TCL_KBAND_VREF, 0xf);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
+				       CSR_2L_PXP_TXPLL_TCL_AMP_GAIN, 0x3);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_TXPLL_TCL_AMP_VREF,
+				       CSR_2L_PXP_TXPLL_TCL_AMP_VREF, 0xb);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+				       CSR_2L_PXP_TXPLL_TCL_LPF_BW, 0x3);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_TXPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+				 PCIE_FORCE_DA_PXP_TXPLL_EN);
+}
+
+static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
+				       CSR_2L_PXP_JCPLL_SSC_DELTA1, 0x106);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
+				       CSR_2L_PXP_JCPLL_SSC_DELTA, 0x106);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
+				       CSR_2L_PXP_JCPLL_SSC_PERIOD, 0x31b);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				   CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				   CSR_2L_PXP_JCPLL_SSC_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
+				   CSR_2L_PXP_JCPLL_SDM_IFM);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+				   CSR_2L_PXP_JCPLL_SDM_HREN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+				     CSR_2L_PXP_JCPLL_SDM_DI_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				   CSR_2L_PXP_JCPLL_SSC_TRI_EN);
+}
+
+static void
+airoha_pcie_phy_set_rxlan0_signal_detect(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
+				   CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON);
+
+	usleep_range(100, 200);
+
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
+				     PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+				     PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+				     PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
+				       CSR_2L_PXP_RX0_SIGDET_PEAK, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
+				       CSR_2L_PXP_RX0_SIGDET_VTH_SEL, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+				       CSR_2L_PXP_VOS_PNINV, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
+				       CSR_2L_PXP_RX0_SIGDET_LPF_CTRL, 0x1);
+
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
+				     PCIE_CAL_OUT_OS, 0x0);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
+				   CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+				 PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+	airoha_phy_pma0_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+				     PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
+				     PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
+				     PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
+	airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
+				   PCIE_DISB_RX_SDCAL_EN);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+				 PCIE_FORCE_RX_SDCAL_EN);
+	usleep_range(150, 200);
+	airoha_phy_pma0_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+				   PCIE_FORCE_RX_SDCAL_EN);
+}
+
+static void
+airoha_pcie_phy_set_rxlan1_signal_detect(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
+				   CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON);
+
+	usleep_range(100, 200);
+
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
+				     PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+				     PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+				     PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
+				       CSR_2L_PXP_RX1_SIGDET_PEAK, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
+				       CSR_2L_PXP_RX1_SIGDET_VTH_SEL, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+				       CSR_2L_PXP_VOS_PNINV, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_DAC_RANGE_EYE,
+				       CSR_2L_PXP_RX1_SIGDET_LPF_CTRL, 0x1);
+
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
+				     PCIE_CAL_OUT_OS, 0x0);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
+				   CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB);
+
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+				 PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+	airoha_phy_pma1_update_field(pcie_phy,
+				     REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+				     PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
+				     PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
+				     PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
+	airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
+				   PCIE_DISB_RX_SDCAL_EN);
+
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+				 PCIE_FORCE_RX_SDCAL_EN);
+	usleep_range(150, 200);
+	airoha_phy_pma1_clear_bits(pcie_phy,
+				   REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+				   PCIE_FORCE_RX_SDCAL_EN);
+}
+
+static void airoha_pcie_phy_set_rxflow(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
+				 PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
+				 PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
+
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
+				 PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
+	airoha_phy_pma0_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
+				 PCIE_FORCE_DA_PXP_RX_FE_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
+				 PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
+	airoha_phy_pma1_set_bits(pcie_phy,
+				 REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
+				 PCIE_FORCE_DA_PXP_RX_FE_PWDB |
+				 PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
+				   CSR_2L_PXP_RX0_PHYCK_RSTB |
+				   CSR_2L_PXP_RX0_TDC_CK_SEL);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
+				   CSR_2L_PXP_RX1_PHYCK_RSTB |
+				   CSR_2L_PXP_RX1_TDC_CK_SEL);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				 PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
+				 PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
+				 PCIE_SW_TX_FIFO_RST);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				 PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
+				 PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
+				 PCIE_SW_TX_FIFO_RST);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
+				   CSR_2L_PXP_RX0_FE_VB_EQ2_EN |
+				   CSR_2L_PXP_RX0_FE_VB_EQ3_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
+				   CSR_2L_PXP_RX0_FE_VB_EQ1_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
+				   CSR_2L_PXP_RX1_FE_VB_EQ1_EN |
+				   CSR_2L_PXP_RX1_FE_VB_EQ2_EN |
+				   CSR_2L_PXP_RX1_FE_VB_EQ3_EN);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+				       CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+				       CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+				       CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+				       CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
+}
+
+static void airoha_pcie_phy_set_pr(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
+				       CSR_2L_PXP_CDR0_PR_VREG_IBAND, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
+				       CSR_2L_PXP_CDR0_PR_VREG_CKBUF, 0x5);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_CKREF_DIV,
+				     CSR_2L_PXP_CDR0_PR_CKREF_DIV);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
+				     CSR_2L_PXP_CDR0_PR_CKREF_DIV1);
+
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
+				       CSR_2L_PXP_CDR1_PR_VREG_IBAND, 0x5);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
+				       CSR_2L_PXP_CDR1_PR_VREG_CKBUF, 0x5);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_CKREF_DIV,
+				     CSR_2L_PXP_CDR1_PR_CKREF_DIV);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
+				     CSR_2L_PXP_CDR1_PR_CKREF_DIV1);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_LPF_RATIO,
+				       CSR_2L_PXP_CDR0_LPF_TOP_LIM, 0x20000);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_LPF_RATIO,
+				       CSR_2L_PXP_CDR1_LPF_TOP_LIM, 0x20000);
+
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
+				       CSR_2L_PXP_CDR0_PR_BETA_SEL, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
+				       CSR_2L_PXP_CDR1_PR_BETA_SEL, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
+				       CSR_2L_PXP_CDR0_PR_KBAND_DIV, 0x4);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
+				       CSR_2L_PXP_CDR1_PR_KBAND_DIV, 0x4);
+}
+
+static void airoha_pcie_phy_set_txflow(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
+				   CSR_2L_PXP_TX0_CKLDO_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
+				   CSR_2L_PXP_TX1_CKLDO_EN);
+
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
+				   CSR_2L_PXP_TX0_DMEDGEGEN_EN);
+	airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
+				   CSR_2L_PXP_TX1_DMEDGEGEN_EN);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TX1_MULTLANE,
+				     CSR_2L_PXP_TX1_MULTLANE_EN);
+}
+
+static void airoha_pcie_phy_set_rx_mode(struct airoha_pcie_phy *pcie_phy)
+{
+	writel(0x804000, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_27);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
+				 0x77700);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
+				     CSR_2L_PXP_CDR0_PR_MONCK_ENABLE);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
+				       CSR_2L_PXP_CDR0_PR_RESERVE0, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS,
+				       CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS, 0x19);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
+				       CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS, 0x19);
+	airoha_phy_csr_2l_update_field(pcie_phy,
+				       REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
+				       CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS, 0x14);
+
+	writel(0x804000, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_27);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+				     PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
+
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
+				 0x77700);
+
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
+				     CSR_2L_PXP_CDR1_PR_MONCK_ENABLE);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
+				       CSR_2L_PXP_CDR1_PR_RESERVE0, 0x2);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+				       CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS, 0x19);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+				       CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS, 0x19);
+	airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+				       CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS, 0x14);
+}
+
+static void airoha_pcie_phy_load_kflow(struct airoha_pcie_phy *pcie_phy)
+{
+	airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+				     PCIE_FORCE_PMA_RX_SPEED, 0xa);
+	airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+				     PCIE_FORCE_PMA_RX_SPEED, 0xa);
+	airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
+	airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
+
+	airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+				   PCIE_FORCE_PMA_RX_SPEED);
+	airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+				   PCIE_FORCE_PMA_RX_SPEED);
+	usleep_range(100, 200);
+
+	airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
+	airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
+}
+
+/**
+ * airoha_pcie_phy_init() - Initialize the phy
+ * @phy: the phy to be initialized
+ *
+ * Initialize the phy registers.
+ * The hardware settings will be reset during suspend, it should be
+ * reinitialized when the consumer calls phy_init() again on resume.
+ */
+static int airoha_pcie_phy_init(struct phy *phy)
+{
+	struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	/* Setup Tx-Rx detection time */
+	val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
+	      FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
+	      FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
+	      FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
+	      FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
+	writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
+	writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
+	/* Setup Rx AEQ training time */
+	val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
+	      FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
+	writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
+	writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
+
+	/* enable load FLL-K flow */
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
+				 PCIE_FLL_LOAD_EN);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
+				 PCIE_FLL_LOAD_EN);
+
+	airoha_pcie_phy_init_default(pcie_phy);
+	airoha_pcie_phy_init_clk_out(pcie_phy);
+	airoha_pcie_phy_init_csr_2l(pcie_phy);
+
+	usleep_range(100, 200);
+
+	airoha_pcie_phy_init_rx(pcie_phy);
+	/* phase 1, no ssc for K TXPLL */
+	airoha_pcie_phy_init_jcpll(pcie_phy);
+
+	usleep_range(500, 600);
+
+	/* TX PLL settings */
+	airoha_pcie_phy_txpll(pcie_phy);
+
+	usleep_range(200, 300);
+
+	/* SSC JCPLL setting */
+	airoha_pcie_phy_init_ssc_jcpll(pcie_phy);
+
+	usleep_range(100, 200);
+
+	/* Rx lan0 signal detect */
+	airoha_pcie_phy_set_rxlan0_signal_detect(pcie_phy);
+	/* Rx lan1 signal detect */
+	airoha_pcie_phy_set_rxlan1_signal_detect(pcie_phy);
+	/* RX FLOW */
+	airoha_pcie_phy_set_rxflow(pcie_phy);
+
+	usleep_range(100, 200);
+
+	airoha_pcie_phy_set_pr(pcie_phy);
+	/* TX FLOW */
+	airoha_pcie_phy_set_txflow(pcie_phy);
+
+	usleep_range(100, 200);
+	/* RX mode setting */
+	airoha_pcie_phy_set_rx_mode(pcie_phy);
+	/* Load K-Flow */
+	airoha_pcie_phy_load_kflow(pcie_phy);
+	airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+				   PCIE_DA_XPON_CDR_PR_PWDB);
+	airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+				   PCIE_DA_XPON_CDR_PR_PWDB);
+
+	usleep_range(100, 200);
+
+	airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+				 PCIE_DA_XPON_CDR_PR_PWDB);
+	airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+				 PCIE_DA_XPON_CDR_PR_PWDB);
+
+	/* Wait for the PCIe PHY to complete initialization before returning */
+	msleep(PHY_HW_INIT_TIME_MS);
+
+	return 0;
+}
+
+static int airoha_pcie_phy_exit(struct phy *phy)
+{
+	struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+	airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				   PCIE_PMA_SW_RST);
+	airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+				   PCIE_PMA_SW_RST);
+	airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+				     CSR_2L_PXP_JCPLL_SSC_PHASE_INI |
+				     CSR_2L_PXP_JCPLL_SSC_TRI_EN |
+				     CSR_2L_PXP_JCPLL_SSC_EN);
+
+	return 0;
+}
+
+static const struct phy_ops airoha_pcie_phy_ops = {
+	.init = airoha_pcie_phy_init,
+	.exit = airoha_pcie_phy_exit,
+	.owner = THIS_MODULE,
+};
+
+static int airoha_pcie_phy_probe(struct platform_device *pdev)
+{
+	struct airoha_pcie_phy *pcie_phy;
+	struct device *dev = &pdev->dev;
+	struct phy_provider *provider;
+
+	pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL);
+	if (!pcie_phy)
+		return -ENOMEM;
+
+	pcie_phy->csr_2l = devm_platform_ioremap_resource_byname(pdev, "csr-2l");
+	if (IS_ERR(pcie_phy->csr_2l))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->csr_2l),
+				     "Failed to map phy-csr-2l base\n");
+
+	pcie_phy->pma0 = devm_platform_ioremap_resource_byname(pdev, "pma0");
+	if (IS_ERR(pcie_phy->pma0))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->pma0),
+				     "Failed to map phy-pma0 base\n");
+
+	pcie_phy->pma1 = devm_platform_ioremap_resource_byname(pdev, "pma1");
+	if (IS_ERR(pcie_phy->pma1))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->pma1),
+				     "Failed to map phy-pma1 base\n");
+
+	pcie_phy->phy = devm_phy_create(dev, dev->of_node, &airoha_pcie_phy_ops);
+	if (IS_ERR(pcie_phy->phy))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
+				     "Failed to create PCIe phy\n");
+
+	pcie_phy->p0_xr_dtime =
+		devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
+	if (IS_ERR(pcie_phy->p0_xr_dtime))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
+				     "Failed to map P0 Tx-Rx dtime base\n");
+
+	pcie_phy->p1_xr_dtime =
+		devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
+	if (IS_ERR(pcie_phy->p1_xr_dtime))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
+				     "Failed to map P1 Tx-Rx dtime base\n");
+
+	pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
+	if (IS_ERR(pcie_phy->rx_aeq))
+		return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
+				     "Failed to map Rx AEQ base\n");
+
+	pcie_phy->dev = dev;
+	phy_set_drvdata(pcie_phy->phy, pcie_phy);
+
+	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(provider))
+		return dev_err_probe(dev, PTR_ERR(provider),
+				     "PCIe phy probe failed\n");
+
+	return 0;
+}
+
+static const struct of_device_id airoha_pcie_phy_of_match[] = {
+	{ .compatible = "airoha,en7581-pcie-phy" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match);
+
+static struct platform_driver airoha_pcie_phy_driver = {
+	.probe	= airoha_pcie_phy_probe,
+	.driver	= {
+		.name = "airoha-pcie-phy",
+		.of_match_table = airoha_pcie_phy_of_match,
+	},
+};
+module_platform_driver(airoha_pcie_phy_driver);
+
+MODULE_DESCRIPTION("Airoha PCIe PHY driver");
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo at kernel.org>");
+MODULE_LICENSE("GPL");
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:32 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:32 +0100
Subject: [PATCH v2 09/11] phy: airoha: Add support for Airoha AN7581 USB PHY
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-10-ansuelsmth@gmail.com>

Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
USB port with USB 2.0 mode always supported and USB 3.0 mode available
only if the Serdes port is correctly configured for USB 3.0.

On xLate probe, the Serdes mode is validated and the driver return error
if the Serdes mode doesn't reflect the expected mode. This is required
as Serdes mode are controlled by the SCU SSR bits and can be either USB
3.0 mode or HSGMII or PCIe 2. In such case USB 3.0 won't work.

If the USB 3.0 mode is not supported, the modes needs to be also
disabled in the xHCI node or the driver will report unsable clock and
fail probe.

Also USB 3.0 PHY instance are provided only if the airoha,serdes-port
property is defined in DT, if it's not then USB 3.0 PHY is assumed not
supported.
For USB 2.0 Slew Rate calibration, airoha,usb2-monitor-clk-sel is
mandatory and is used to select the monitor clock for calibration.

Normally it's 1 for USB port 1 and 2 for USB port 2.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                         |   1 +
 drivers/phy/airoha/Kconfig          |  10 +
 drivers/phy/airoha/Makefile         |   1 +
 drivers/phy/airoha/phy-airoha-usb.c | 571 ++++++++++++++++++++++++++++
 4 files changed, 583 insertions(+)
 create mode 100644 drivers/phy/airoha/phy-airoha-usb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4e11db5d203a..f8208994d190 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -759,6 +759,7 @@ M:	Christian Marangi <ansuelsmth at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+F:	drivers/phy/airoha/phy-airoha-usb.c
 F:	include/dt-bindings/phy/airoha,an7581-usb-phy.h
 
 AIRSPY MEDIA DRIVER
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
index 70b7eac4a2bf..0675d8f2f9d1 100644
--- a/drivers/phy/airoha/Kconfig
+++ b/drivers/phy/airoha/Kconfig
@@ -11,3 +11,13 @@ config PHY_AIROHA_PCIE
 	  Say Y here to add support for Airoha PCIe PHY driver.
 	  This driver create the basic PHY instance and provides initialize
 	  callback for PCIe GEN3 port.
+
+config PHY_AIROHA_USB
+	tristate "Airoha USB PHY Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Say 'Y' here to add support for Airoha USB PHY driver.
+	  This driver create the basic PHY instance and provides initialize
+	  callback for USB port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
index 3222f749546b..fd188d08c412 100644
--- a/drivers/phy/airoha/Makefile
+++ b/drivers/phy/airoha/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
+obj-$(CONFIG_PHY_AIROHA_USB)		+= phy-airoha-usb.o
diff --git a/drivers/phy/airoha/phy-airoha-usb.c b/drivers/phy/airoha/phy-airoha-usb.c
new file mode 100644
index 000000000000..72a3ee14b7a6
--- /dev/null
+++ b/drivers/phy/airoha/phy-airoha-usb.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
+#include <linux/bitfield.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/airoha/airoha-scu-ssr.h>
+
+/* U2PHY */
+#define AIROHA_USB_PHY_FMCR0			0x100
+#define   AIROHA_USB_PHY_MONCLK_SEL		GENMASK(27, 26)
+#define   AIROHA_USB_PHY_MONCLK_SEL0		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x0)
+#define   AIROHA_USB_PHY_MONCLK_SEL1		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x1)
+#define   AIROHA_USB_PHY_MONCLK_SEL2		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x2)
+#define   AIROHA_USB_PHY_MONCLK_SEL3		FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x3)
+#define   AIROHA_USB_PHY_FREQDET_EN		BIT(24)
+#define   AIROHA_USB_PHY_CYCLECNT		GENMASK(23, 0)
+#define AIROHA_USB_PHY_FMMONR0			0x10c
+#define   AIROHA_USB_PHY_USB_FM_OUT		GENMASK(31, 0)
+#define AIROHA_USB_PHY_FMMONR1			0x110
+#define   AIROHA_USB_PHY_FRCK_EN		BIT(8)
+
+#define AIROHA_USB_PHY_USBPHYACR4		0x310
+#define   AIROHA_USB_PHY_USB20_FS_CR		GENMASK(10, 8)
+#define   AIROHA_USB_PHY_USB20_FS_CR_MAX	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x0)
+#define   AIROHA_USB_PHY_USB20_FS_CR_NORMAL	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x2)
+#define   AIROHA_USB_PHY_USB20_FS_CR_SMALLER	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x4)
+#define   AIROHA_USB_PHY_USB20_FS_CR_MIN	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x6)
+#define   AIROHA_USB_PHY_USB20_FS_SR		GENMASK(2, 0)
+#define   AIROHA_USB_PHY_USB20_FS_SR_MAX	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x0)
+#define   AIROHA_USB_PHY_USB20_FS_SR_NORMAL	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x2)
+#define   AIROHA_USB_PHY_USB20_FS_SR_SMALLER	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x4)
+#define   AIROHA_USB_PHY_USB20_FS_SR_MIN	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x6)
+#define AIROHA_USB_PHY_USBPHYACR5		0x314
+#define   AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN	BIT(15)
+#define   AIROHA_USB_PHY_USB20_HSTX_SRCTRL	GENMASK(14, 12)
+#define AIROHA_USB_PHY_USBPHYACR6		0x318
+#define   AIROHA_USB_PHY_USB20_BC11_SW_EN	BIT(23)
+#define   AIROHA_USB_PHY_USB20_DISCTH		GENMASK(7, 4)
+#define   AIROHA_USB_PHY_USB20_DISCTH_400	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x0)
+#define   AIROHA_USB_PHY_USB20_DISCTH_420	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x1)
+#define   AIROHA_USB_PHY_USB20_DISCTH_440	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x2)
+#define   AIROHA_USB_PHY_USB20_DISCTH_460	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x3)
+#define   AIROHA_USB_PHY_USB20_DISCTH_480	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x4)
+#define   AIROHA_USB_PHY_USB20_DISCTH_500	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x5)
+#define   AIROHA_USB_PHY_USB20_DISCTH_520	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x6)
+#define   AIROHA_USB_PHY_USB20_DISCTH_540	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x7)
+#define   AIROHA_USB_PHY_USB20_DISCTH_560	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x8)
+#define   AIROHA_USB_PHY_USB20_DISCTH_580	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x9)
+#define   AIROHA_USB_PHY_USB20_DISCTH_600	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xa)
+#define   AIROHA_USB_PHY_USB20_DISCTH_620	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xb)
+#define   AIROHA_USB_PHY_USB20_DISCTH_640	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xc)
+#define   AIROHA_USB_PHY_USB20_DISCTH_660	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xd)
+#define   AIROHA_USB_PHY_USB20_DISCTH_680	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xe)
+#define   AIROHA_USB_PHY_USB20_DISCTH_700	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xf)
+#define   AIROHA_USB_PHY_USB20_SQTH		GENMASK(3, 0)
+#define   AIROHA_USB_PHY_USB20_SQTH_85		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x0)
+#define   AIROHA_USB_PHY_USB20_SQTH_90		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x1)
+#define   AIROHA_USB_PHY_USB20_SQTH_95		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x2)
+#define   AIROHA_USB_PHY_USB20_SQTH_100		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x3)
+#define   AIROHA_USB_PHY_USB20_SQTH_105		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x4)
+#define   AIROHA_USB_PHY_USB20_SQTH_110		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x5)
+#define   AIROHA_USB_PHY_USB20_SQTH_115		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x6)
+#define   AIROHA_USB_PHY_USB20_SQTH_120		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x7)
+#define   AIROHA_USB_PHY_USB20_SQTH_125		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x8)
+#define   AIROHA_USB_PHY_USB20_SQTH_130		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x9)
+#define   AIROHA_USB_PHY_USB20_SQTH_135		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xa)
+#define   AIROHA_USB_PHY_USB20_SQTH_140		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xb)
+#define   AIROHA_USB_PHY_USB20_SQTH_145		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xc)
+#define   AIROHA_USB_PHY_USB20_SQTH_150		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xd)
+#define   AIROHA_USB_PHY_USB20_SQTH_155		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xe)
+#define   AIROHA_USB_PHY_USB20_SQTH_160		FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xf)
+
+#define AIROHA_USB_PHY_U2PHYDTM1		0x36c
+#define   AIROHA_USB_PHY_FORCE_IDDIG		BIT(9)
+#define   AIROHA_USB_PHY_IDDIG			BIT(1)
+
+#define AIROHA_USB_PHY_GPIO_CTLD		0x80c
+#define   AIROHA_USB_PHY_C60802_GPIO_CTLD	GENMASK(31, 0)
+#define     AIROHA_USB_PHY_SSUSB_IP_SW_RST	BIT(31)
+#define     AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN	BIT(30)
+#define     AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29)
+#define     AIROHA_USB_PHY_SSUSB_SW_RST		BIT(28)
+
+#define AIROHA_USB_PHY_U3_PHYA_REG0		0xb00
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV		GENMASK(29, 28)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_2		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x0)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_4		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x1)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_8		FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x2)
+#define   AIROHA_USB_PHY_SSUSB_BG_DIV_16	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x3)
+#define AIROHA_USB_PHY_U3_PHYA_REG1		0xb04
+#define   AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE	GENMASK(25, 10)
+#define AIROHA_USB_PHY_U3_PHYA_REG6		0xb18
+#define   AIROHA_USB_PHY_SSUSB_CDR_RESERVE	GENMASK(31, 24)
+#define AIROHA_USB_PHY_U3_PHYA_REG8		0xb20
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY	GENMASK(7, 6)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x0)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x1)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x2)
+#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216	FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x3)
+
+#define AIROHA_USB_PHY_U3_PHYA_DA_REG19		0xc38
+#define   AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0)
+
+#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT	1024
+#define AIROHA_USB_PHY_REF_CK			20
+#define AIROHA_USB_PHY_U2_SR_COEF		28
+#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR	1000
+
+#define AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION	0x5
+#define AIROHA_USB_PHY_FREQDET_SLEEP		1000 /* 1ms */
+#define AIROHA_USB_PHY_FREQDET_TIMEOUT		(AIROHA_USB_PHY_FREQDET_SLEEP * 10)
+
+struct airoha_usb_phy_instance {
+	struct phy *phy;
+	u32 type;
+};
+
+enum airoha_usb_phy_instance_type {
+	AIROHA_PHY_USB2,
+	AIROHA_PHY_USB3,
+
+	AIROHA_PHY_USB_MAX,
+};
+
+struct airoha_usb_phy_priv {
+	struct device *dev;
+	struct regmap *regmap;
+
+	unsigned int monclk_sel;
+	unsigned int serdes_port;
+
+	struct airoha_usb_phy_instance *phys[AIROHA_PHY_USB_MAX];
+};
+
+static void airoha_usb_phy_u2_slew_rate_calibration(struct airoha_usb_phy_priv *priv)
+{
+	u32 fm_out;
+	u32 srctrl;
+
+	/* Enable HS TX SR calibration */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Enable Free run clock */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+			AIROHA_USB_PHY_FRCK_EN);
+
+	/* Select Monitor Clock */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			   AIROHA_USB_PHY_MONCLK_SEL,
+			   FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL,
+				      priv->monclk_sel));
+
+	/* Set cyclecnt */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			   AIROHA_USB_PHY_CYCLECNT,
+			   FIELD_PREP(AIROHA_USB_PHY_CYCLECNT,
+				      AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT));
+
+	/* Enable Frequency meter */
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Timeout can happen and we will apply workaround at the end */
+	regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out,
+				 fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
+				 AIROHA_USB_PHY_FREQDET_TIMEOUT);
+
+	/* Disable Frequency meter */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+			  AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Disable Free run clock */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+			  AIROHA_USB_PHY_FRCK_EN);
+
+	/* Disable HS TX SR calibration */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			  AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Frequency was not detected, use default SR calibration value */
+	if (!fm_out) {
+		srctrl = AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION;
+		dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n");
+	} else {
+		/* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
+		srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF;
+		srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out;
+		srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR);
+		dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl);
+	}
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+			   AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
+			   FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
+}
+
+static void airoha_usb_phy_u2_init(struct airoha_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+			   AIROHA_USB_PHY_USB20_FS_CR,
+			   AIROHA_USB_PHY_USB20_FS_CR_MIN);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+			   AIROHA_USB_PHY_USB20_FS_SR,
+			   AIROHA_USB_PHY_USB20_FS_SR_NORMAL);
+
+	/* FIXME: evaluate if needed */
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			   AIROHA_USB_PHY_USB20_SQTH,
+			   AIROHA_USB_PHY_USB20_SQTH_130);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			   AIROHA_USB_PHY_USB20_DISCTH,
+			   AIROHA_USB_PHY_USB20_DISCTH_600);
+
+	/* Enable the USB port and then disable after calibration */
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	airoha_usb_phy_u2_slew_rate_calibration(priv);
+
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+}
+
+/*
+ * USB 3.0 mode can only work if USB serdes is correctly set.
+ * This is validated in xLate function.
+ */
+static void airoha_usb_phy_u3_init(struct airoha_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8,
+			   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY,
+			   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32);
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6,
+			   AIROHA_USB_PHY_SSUSB_CDR_RESERVE,
+			   FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe));
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0,
+			   AIROHA_USB_PHY_SSUSB_BG_DIV,
+			   AIROHA_USB_PHY_SSUSB_BG_DIV_4);
+
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1,
+			FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600));
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19,
+			   AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3,
+			   FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43));
+}
+
+static int airoha_usb_phy_init(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		airoha_usb_phy_u2_init(priv);
+		break;
+	case PHY_TYPE_USB3:
+		airoha_usb_phy_u3_init(priv);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int airoha_usb_phy_u2_power_on(struct airoha_usb_phy_priv *priv)
+{
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_u3_power_on(struct airoha_usb_phy_priv *priv)
+{
+	regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+			  AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+			  AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN |
+			  AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST |
+			  AIROHA_USB_PHY_SSUSB_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_power_on(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		airoha_usb_phy_u2_power_on(priv);
+		break;
+	case PHY_TYPE_USB3:
+		airoha_usb_phy_u3_power_on(priv);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int airoha_usb_phy_u2_power_off(struct airoha_usb_phy_priv *priv)
+{
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_u3_power_off(struct airoha_usb_phy_priv *priv)
+{
+	regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+			AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+			AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int airoha_usb_phy_power_off(struct phy *phy)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		airoha_usb_phy_u2_power_off(priv);
+		break;
+	case PHY_TYPE_USB3:
+		airoha_usb_phy_u3_power_off(priv);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int airoha_usb_phy_u2_set_mode(struct airoha_usb_phy_priv *priv,
+				      enum phy_mode mode)
+{
+	u32 val;
+
+	/*
+	 * For Device and Host mode, enable force IDDIG.
+	 * For Device set IDDIG, for Host clear IDDIG.
+	 * For OTG disable force and clear IDDIG bit while at it.
+	 */
+	switch (mode) {
+	case PHY_MODE_USB_DEVICE:
+		val = AIROHA_USB_PHY_IDDIG;
+		break;
+	case PHY_MODE_USB_HOST:
+		val = AIROHA_USB_PHY_FORCE_IDDIG |
+		      AIROHA_USB_PHY_FORCE_IDDIG;
+		break;
+	case PHY_MODE_USB_OTG:
+		val = 0;
+		break;
+	default:
+		return 0;
+	}
+
+	regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1,
+			   AIROHA_USB_PHY_FORCE_IDDIG |
+			   AIROHA_USB_PHY_IDDIG, val);
+
+	return 0;
+}
+
+static int airoha_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	if (instance->type == PHY_TYPE_USB2)
+		return airoha_usb_phy_u2_set_mode(priv, mode);
+
+	return 0;
+}
+
+static struct phy *airoha_usb_phy_xlate(struct device *dev,
+					const struct of_phandle_args *args)
+{
+	struct airoha_usb_phy_priv *priv = dev_get_drvdata(dev);
+	struct airoha_usb_phy_instance *instance = NULL;
+	int phy_type;
+	int index;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	phy_type = args->args[0];
+	if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) {
+		dev_err(dev, "unsupported device type: %d\n", phy_type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < AIROHA_PHY_USB_MAX; index++)
+		if (priv->phys[index] &&
+		    phy_type == priv->phys[index]->type) {
+			instance = priv->phys[index];
+			break;
+		}
+
+	if (!instance) {
+		dev_err(dev, "failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Validate Serdes for USB 3.0 */
+	if (instance->type == PHY_TYPE_USB3) {
+		int serdes_mode;
+
+		serdes_mode = airoha_scu_ssr_get_serdes_mode(dev, priv->serdes_port);
+		if (serdes_mode < 0) {
+			dev_err(dev, "failed validating serdes mode: %d\n",
+				serdes_mode);
+			return ERR_PTR(serdes_mode);
+		}
+
+		if (serdes_mode != AIROHA_SCU_SERDES_MODE_USB3) {
+			dev_err(dev, "wrong serdes mode for port\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return instance->phy;
+}
+
+static const struct phy_ops airoha_phy = {
+	.init		= airoha_usb_phy_init,
+	.power_on	= airoha_usb_phy_power_on,
+	.power_off	= airoha_usb_phy_power_off,
+	.set_mode	= airoha_usb_phy_set_mode,
+	.owner		= THIS_MODULE,
+};
+
+static const struct regmap_config airoha_usb_phy_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int airoha_usb_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct airoha_usb_phy_priv *priv;
+	struct device *dev = &pdev->dev;
+	void *base;
+	int index;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	ret = of_property_read_u32(dev->of_node, "airoha,usb2-monitor-clk-sel",
+				   &priv->monclk_sel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Monitor clock selection is mandatory for USB PHY calibration.\n");
+
+	if (priv->monclk_sel > 3)
+		return dev_err_probe(dev, -EINVAL, "only 4 Monitor clock are selectable on the SoC.\n");
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	priv->regmap = devm_regmap_init_mmio(dev, base, &airoha_usb_phy_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	platform_set_drvdata(pdev, priv);
+
+	for (index = 0; index < AIROHA_PHY_USB_MAX; index++) {
+		struct airoha_usb_phy_instance *instance;
+		unsigned int phy_type;
+
+		switch (index) {
+		case AIROHA_PHY_USB2:
+			phy_type = PHY_TYPE_USB2;
+			break;
+		case AIROHA_PHY_USB3:
+			phy_type = PHY_TYPE_USB3;
+			break;
+		}
+
+		/* Skip registering USB3 instance if not supported */
+		if (phy_type == PHY_TYPE_USB3) {
+			ret = of_property_read_u32(dev->of_node, "airoha,serdes-port",
+						   &priv->serdes_port);
+			if (ret)
+				continue;
+
+			/* With Serdes Port property, SCU is required */
+			if (!of_property_present(dev->of_node, "airoha,scu"))
+				return dev_err_probe(dev, ret, "missing required SCU definition.\n");
+		}
+
+		instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+		if (!instance)
+			return -ENOMEM;
+
+		instance->type = phy_type;
+		priv->phys[index] = instance;
+
+		instance->phy = devm_phy_create(dev, NULL, &airoha_phy);
+		if (IS_ERR(instance->phy))
+			return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n");
+
+		phy_set_drvdata(instance->phy, instance);
+	}
+
+	phy_provider = devm_of_phy_provider_register(&pdev->dev, airoha_usb_phy_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id airoha_phy_id_table[] = {
+	{ .compatible = "airoha,an7581-usb-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
+
+static struct platform_driver airoha_usb_driver = {
+	.probe		= airoha_usb_phy_probe,
+	.driver		= {
+		.name	= "airoha-usb-phy",
+		.of_match_table = airoha_phy_id_table,
+	},
+};
+
+module_platform_driver(airoha_usb_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Airoha USB PHY driver");
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:33 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:33 +0100
Subject: [PATCH v2 10/11] usb: host: add ARCH_AIROHA in XHCI MTK dependency
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-11-ansuelsmth@gmail.com>

Airoha SoC use the same register map a logic of the Mediatek xHCI
driver, hence add it to the dependency list to permit compilation also
on this ARCH.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/usb/host/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d011d6c753ed..9d8626f36ca6 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -71,7 +71,7 @@ config USB_XHCI_HISTB
 config USB_XHCI_MTK
 	tristate "xHCI support for MediaTek SoCs"
 	select MFD_SYSCON
-	depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST
+	depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || ARCH_AIROHA || COMPILE_TEST
 	help
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in MediaTek SoCs.
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:34 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:34 +0100
Subject: [PATCH v2 11/11] arm64: dts: airoha: en7581: add USB nodes
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-12-ansuelsmth@gmail.com>

Add USB nodes required for USB support of Airoha EN7581 with the correct
define of Serdes Port and Monitor Clock for USB 2.0 calibration.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 arch/arm64/boot/dts/airoha/en7581.dtsi | 49 ++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/arch/arm64/boot/dts/airoha/en7581.dtsi b/arch/arm64/boot/dts/airoha/en7581.dtsi
index 26b136940917..d1cec63bb77f 100644
--- a/arch/arm64/boot/dts/airoha/en7581.dtsi
+++ b/arch/arm64/boot/dts/airoha/en7581.dtsi
@@ -3,7 +3,10 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/en7523-clk.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/airoha,an7581-usb-phy.h>
 #include <dt-bindings/reset/airoha,en7581-reset.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
 
 / {
 	interrupt-parent = <&gic>;
@@ -195,6 +198,52 @@ rng at 1faa1000 {
 			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		usb0: usb at 1fab0000 {
+			compatible = "mediatek,mtk-xhci";
+			reg = <0x0 0x1fab0000 0x0 0x3e00>,
+				<0x0 0x1fab3e00 0x0 0x100>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+
+			phys = <&usb0_phy PHY_TYPE_USB2>, <&usb0_phy PHY_TYPE_USB3>;
+
+			status = "disabled";
+		};
+
+		usb0_phy: phy at 1fac0000 {
+			compatible = "airoha,an7581-usb-phy";
+			reg = <0x0 0x1fac0000 0x0 0x10000>;
+
+			airoha,scu = <&scuclk>;
+			airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL1>;
+			airoha,serdes-port = <AIROHA_SCU_SERDES_USB1>;
+
+			#phy-cells = <1>;
+		};
+
+		usb1: usb at 1fad0000 {
+			compatible = "mediatek,mtk-xhci";
+			reg = <0x0 0x1fad0000 0x0 0x3e00>,
+				<0x0 0x1fad3e00 0x0 0x100>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+
+			phys = <&usb1_phy PHY_TYPE_USB2>, <&usb1_phy PHY_TYPE_USB3>;
+
+			status = "disabled";
+		};
+
+		usb1_phy: phy at 1fae0000 {
+			compatible = "airoha,an7581-usb-phy";
+			reg = <0x0 0x1fae0000 0x0 0x10000>;
+
+			airoha,scu = <&scuclk>;
+			airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL2>;
+			airoha,serdes-port = <AIROHA_SCU_SERDES_USB2>;
+
+			#phy-cells = <1>;
+		};
+
 		system-controller at 1fbf0200 {
 			compatible = "airoha,en7581-gpio-sysctl", "syscon",
 				     "simple-mfd";
-- 
2.48.1



From peter.griffin at linaro.org  Thu Mar 20 06:17:53 2025
From: peter.griffin at linaro.org (Peter Griffin)
Date: Thu, 20 Mar 2025 13:17:53 +0000
Subject: [PATCH v5 2/5] pinctrl: samsung: refactor drvdata suspend &
 resume callbacks
In-Reply-To: <5ff8d26d-65bd-4b99-90b1-ae01f0ee9eb7@kernel.org>
References: <20250312-pinctrl-fltcon-suspend-v5-0-d98d5b271242@linaro.org>
 <20250312-pinctrl-fltcon-suspend-v5-2-d98d5b271242@linaro.org> <5ff8d26d-65bd-4b99-90b1-ae01f0ee9eb7@kernel.org>
Message-ID: <CADrjBPqPRR+yH=B_pSFNMTqqvQaHZPckw=OaeGZa34icb0WbFw@mail.gmail.com>

Hi Krzysztof,

Thanks for the review feedback.

On Tue, 18 Mar 2025 at 19:47, Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 12/03/2025 22:58, Peter Griffin wrote:
> > Move the call of drvdata->suspend()/resume into the loop which is
> > iterating drvdata for each bank.
>
>
> Side effect is that now each drvdata->suspend will be called before
> saving registers. Please mention it here and this lead me to one more
> comment.

Yes drvdata->suspend() gets called slightly earlier after this patch.
I can mention that in the commit message

>
> > This allows the clk_enable() and clk_disable() logic to be removed
>
>
> For suspend path - yes. For resume path - nothing changed, because
> drvdata->resume(drvdata) was called with clock enabled.

The clk_enable() / clk_disable() has been removed from both the
drvdata->suspend() and drvdata->resume() callbacks

>
> > from each callback, and also avoids iterating the same loop again
> > in the next function.
>
> ...
>
> > diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
> > index 963060920301ec90affb2ee6d758d3d602ffb4a9..375634d8cc79d6533603e3eed562452181e2ee25 100644
> > --- a/drivers/pinctrl/samsung/pinctrl-samsung.c
> > +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
> > @@ -1349,6 +1349,9 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> >               const u8 *widths = bank->type->fld_width;
> >               enum pincfg_type type;
> >
> > +             if (drvdata->suspend)
> > +                     drvdata->suspend(bank);
>
> Here suspend() is called before saving common register state (was
> *after*)...
>
> > +
> >               /* Registers without a powerdown config aren't lost */
> >               if (!widths[PINCFG_TYPE_CON_PDN])
> >                       continue;
> > @@ -1373,8 +1376,6 @@ static int __maybe_unused samsung_pinctrl_suspend(struct device *dev)
> >
> >       clk_disable(drvdata->pclk);
> >
> > -     if (drvdata->suspend)
> > -             drvdata->suspend(drvdata);
> >       if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable)
> >               drvdata->retention_ctrl->enable(drvdata);
> >
> > @@ -1406,9 +1407,6 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> >               return ret;
> >       }
> >
> > -     if (drvdata->resume)
> > -             drvdata->resume(drvdata);
> > -
> >       for (i = 0; i < drvdata->nr_banks; i++) {
> >               struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
> >               void __iomem *reg = bank->pctl_base + bank->pctl_offset;
> > @@ -1416,6 +1414,9 @@ static int __maybe_unused samsung_pinctrl_resume(struct device *dev)
> >               const u8 *widths = bank->type->fld_width;
> >               enum pincfg_type type;
> >
> > +             if (drvdata->resume)
> > +                     drvdata->resume(bank);
>
> But this is not symmetrically reversed now - resume() is before
> restoring from saved state.
>
> Maybe this change is intentional, but then it should be expressed in
> commit msg and in commit why this was chosen.
>
> I guess you decided to do that way only because of code:
>         if (!widths[PINCFG_TYPE_CON_PDN])

Yes exactly it was the above line, and trying to avoid iterating the
loop a second time.

> This code should be symmetrically reversed, otherwise it just raises
> questions. For saving register state, it does not really matter, but in
> general if we assume driver-specific suspend callback is run the last,
> then driver-specific resume callback should be first, no?

As you say it's just saving/restoring some registers so I don't
believe the ordering matters. But if you would like it to be kept
symmetrically reversed I could switch back to calling it in almost the
same place as before this patch (just moving it a couple lines up
before the clk_disable() and iterate the loop again.

for (i = 0; i < drvdata->nr_banks; i++)
    drvdata->suspend(bank);

and similar for drvdata->resume(). Then the ordering should be exactly
the same as prior to this patch.

Thanks,

Peter


From andrew at lunn.ch  Thu Mar 20 06:19:00 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 14:19:00 +0100
Subject: [PATCH net-next v3 4/5] net: stmmac: dwmac-rk: Add
 integrated_phy_powerdown operation
In-Reply-To: <20250319214415.3086027-5-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-5-jonas@kwiboo.se>
Message-ID: <682212d9-becb-4325-9b0f-541c96a9270d@lunn.ch>

On Wed, Mar 19, 2025 at 09:44:08PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
> the integrated PHY on RK3228/RK3328. Current powerup/down operation is
> not compatible with the integrated PHY found in these newer SoCs.
> 
> Add a new integrated_phy_powerdown operation and change the call chain
> for integrated_phy_powerup to prepare support for the integrated PHY
> found in these newer SoCs.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From andrew at lunn.ch  Thu Mar 20 06:20:23 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 14:20:23 +0100
Subject: [PATCH net-next v3 5/5] net: stmmac: dwmac-rk: Add initial
 support for RK3528 integrated PHY
In-Reply-To: <20250319214415.3086027-6-jonas@kwiboo.se>
References: <20250319214415.3086027-1-jonas@kwiboo.se>
 <20250319214415.3086027-6-jonas@kwiboo.se>
Message-ID: <b918b36e-e4d8-48a6-bac8-6aacafe129b6@lunn.ch>

On Wed, Mar 19, 2025 at 09:44:09PM +0000, Jonas Karlman wrote:
> Rockchip RK3528 (and RV1106) has a different integrated PHY compared to
> the integrated PHY on RK3228/RK3328. Current powerup/down operation is
> not compatible with the integrated PHY found in these newer SoCs.
> 
> Add operations to powerup/down the integrated PHY found in RK3528.
> Use helpers that can be used by other GMAC variants in the future.
> 
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From suzuki.poulose at arm.com  Thu Mar 20 06:24:25 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 20 Mar 2025 13:24:25 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250319150533.37440-3-miko.lenczewski@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
Message-ID: <f9c5839e-5d55-497e-9df3-ab778c4eae72@arm.com>

On 19/03/2025 15:05, Miko?aj Lenczewski wrote:
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for, as well as a kernel commandline parameter to optionally
> disable BBML2 altogether.
> 
> This is a system feature as we might have a big.LITTLE architecture
> where some cores support BBML2 and some don't, but we want all cores to
> be available and BBM to default to level 0 (as opposed to having cores
> without BBML2 not coming online).
> 
> To support BBML2 in as wide a range of contexts as we can, we want not
> only the architectural guarantees that BBML2 makes, but additionally
> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
> us having to prove that no recursive faults can be induced in any path
> that uses BBML2, allowing its use for arbitrary kernel mappings.
> Support detection of such CPUs.
> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> ---
>   .../admin-guide/kernel-parameters.txt         |  3 +
>   arch/arm64/Kconfig                            | 11 +++
>   arch/arm64/include/asm/cpucaps.h              |  2 +
>   arch/arm64/include/asm/cpufeature.h           |  5 ++
>   arch/arm64/kernel/cpufeature.c                | 68 +++++++++++++++++++
>   arch/arm64/kernel/pi/idreg-override.c         |  2 +
>   arch/arm64/tools/cpucaps                      |  1 +
>   7 files changed, 92 insertions(+)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fb8752b42ec8..3e4cc917a07e 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -453,6 +453,9 @@
>   	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>   			32 bit applications.
>   
> +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> +			2 support
> +
>   	arm64.nobti	[ARM64] Unconditionally disable Branch Target
>   			Identification support
>   
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..49deda2b22ae 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>   	  The feature introduces new assembly instructions, and they were
>   	  support when binutils >= 2.30.
>   
> +config ARM64_BBML2_NOABORT
> +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
> +	default y
> +	help
> +	  FEAT_BBM provides detection of support levels for break-before-make
> +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
> +	  can be relaxed to improve performance. We additonally require the
> +	  property that the implementation cannot ever raise TLB Conflict Aborts.
> +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
> +	  even if the system supports BBM level 2.

minor nit: Should we mention that the feature can be disabled at runtime 
using a kernel parameter ?

> +
>   endmenu # "ARMv8.4 architectural features"
>   
>   menu "ARMv8.5 architectural features"
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 0b5ca6e0eb09..2d6db33d4e45 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>   		return IS_ENABLED(CONFIG_ARM64_PAN);
>   	case ARM64_HAS_EPAN:
>   		return IS_ENABLED(CONFIG_ARM64_EPAN);
> +	case ARM64_HAS_BBML2_NOABORT:
> +		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>   	case ARM64_SVE:
>   		return IS_ENABLED(CONFIG_ARM64_SVE);
>   	case ARM64_SME:
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index e0e4478f5fb5..108ef3fbbc00 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
>   	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>   }
>   
> +static inline bool system_supports_bbml2_noabort(void)
> +{
> +	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
> +}
> +
>   int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>   bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>   
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index d561cf3b8ac7..1a4adcda267b 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>   	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>   }
>   
> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> +{
> +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
> +	 * as possible. This list is therefore an allow-list of known-good
> +	 * implementations that both support bbml2 and additionally, fulfill the
> +	 * extra constraint of never generating TLB conflict aborts when using
> +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> +	 * kernel contexts difficult to prove safe against recursive aborts).
> +	 *
> +	 * Note that implementations can only be considered "known-good" if their
> +	 * implementors attest to the fact that the implementation never raises
> +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
> +	 */
> +	static const struct midr_range supports_bbml2_noabort_list[] = {
> +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> +		{}
> +	};
> +
> +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
> +}
> +
> +static inline unsigned int cpu_read_midr(int cpu)
> +{
> +	WARN_ON_ONCE(!cpu_online(cpu));
> +
> +	return per_cpu(cpu_data, cpu).reg_midr;
> +}
> +
> +static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
> +{
> +	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
> +		return false;
> +
> +	if (scope & SCOPE_SYSTEM) {
> +		int cpu;
> +
> +		/* We are a boot CPU, and must verify that all enumerated boot

minor nit: See Documentation/process/coding-style.rst,
Section 8 Commenting.

		/*
		 * <multi-line comment>
		 */

> +		 * CPUs have MIDR values within our allowlist. Otherwise, we do
> +		 * not allow the BBML2 feature to avoid potential faults when
> +		 * the insufficient CPUs access memory regions using BBML2
> +		 * semantics.
> +		 */
> +		for_each_online_cpu(cpu) {
> +			if (!cpu_has_bbml2_noabort(cpu_read_midr(cpu)))
> +				return false;
> +		}
> +	} else if (scope & SCOPE_LOCAL_CPU) {
> +		/* We are a hot-plugged CPU, so must only check our MIDR.

minot nit: same as above

Rest looks good to me.

Suzuki



> +		 * If we have the correct MIDR, but the kernel booted on an
> +		 * insufficient CPU, we will not use BBML2 (this is safe). If
> +		 * we have an incorrect MIDR, but the kernel booted on a
> +		 * sufficient CPU, we will not bring up this CPU.
> +		 */
> +		if (!cpu_has_bbml2_noabort(read_cpuid_id()))
> +			return false;
> +	}
> +
> +	return has_cpuid_feature(caps, scope);
> +}
> +
>   #ifdef CONFIG_ARM64_PAN
>   static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
>   {
> @@ -2926,6 +2987,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>   		.matches = has_cpuid_feature,
>   		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
>   	},
> +	{
> +		.desc = "BBM Level 2 without conflict abort",
> +		.capability = ARM64_HAS_BBML2_NOABORT,
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.matches = has_bbml2_noabort,
> +		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
> +	},
>   	{
>   		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
>   		.capability = ARM64_HAS_LPA2,
> diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
> index c6b185b885f7..803a0c99f7b4 100644
> --- a/arch/arm64/kernel/pi/idreg-override.c
> +++ b/arch/arm64/kernel/pi/idreg-override.c
> @@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
>   	.override	= &id_aa64mmfr2_override,
>   	.fields		= {
>   		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
> +		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
>   		{}
>   	},
>   };
> @@ -246,6 +247,7 @@ static const struct {
>   	{ "rodata=off",			"arm64_sw.rodataoff=1" },
>   	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
>   	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
> +	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
>   };
>   
>   static int __init parse_hexdigit(const char *p, u64 *v)
> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
> index 1e65f2fb45bd..b03a375e5507 100644
> --- a/arch/arm64/tools/cpucaps
> +++ b/arch/arm64/tools/cpucaps
> @@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
>   HAS_ADDRESS_AUTH_IMP_DEF
>   HAS_AMU_EXTN
>   HAS_ARMv8_4_TTL
> +HAS_BBML2_NOABORT
>   HAS_CACHE_DIC
>   HAS_CACHE_IDC
>   HAS_CNP



From ansuelsmth at gmail.com  Thu Mar 20 06:00:26 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:26 +0100
Subject: [PATCH v2 03/11] dt-bindings: clock: en7523: add Documentation for Airoha AN7581 SCU SSR
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-4-ansuelsmth@gmail.com>

The Airoha AN7581 SoC have in the SCU register space particular
address that control how some peripheral are configured.

These are toggeled in the System Status Register and are used to
toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).

Modes are mutually exclusive and selecting one mode cause the
other feature to not work (example a mode in USB 3.0 cause PCIe
port 2 to not work) This depends also on what is physically
connected to the Hardware and needs to correctly reflect the
System Status Register bits.

Special care is needed for PCIe port 0 in 2 line mode that
requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
mode.

Expose these configuration as an enum of strings in the SCU node and
also add dt-bindings header to reference each serdes port in DT.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/clock/airoha,en7523-scu.yaml     | 101 ++++++++++++++++--
 MAINTAINERS                                   |   7 ++
 include/dt-bindings/soc/airoha,scu-ssr.h      |  11 ++
 3 files changed, 110 insertions(+), 9 deletions(-)
 create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h

diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
index fe2c5c1baf43..637ce0e06619 100644
--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
@@ -9,6 +9,7 @@ title: EN7523 Clock
 maintainers:
   - Felix Fietkau <nbd at nbd.name>
   - John Crispin <nbd at nbd.name>
+  - Christian Marangi <ansuelsmth at gmail.com>
 
 description: |
   This node defines the System Control Unit of the EN7523 SoC,
@@ -26,6 +27,23 @@ description: |
 
   The clocks are provided inside a system controller node.
 
+  The System Control Unit may also set different mode for the Serdes ports
+  present on the SoC.
+
+  These are toggeled in the System Status Register and are used to
+  toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
+  or setup port for PCIe mode or Ethernet mode (HSGMII/USXGMII).
+
+  Modes are mutually exclusive and selecting one mode cause the
+  other feature to not work (example a mode in USB 3.0 cause PCIe
+  port 2 to not work) This depends also on what is physically
+  connected to the Hardware and needs to correctly reflect the
+  System Status Register bits.
+
+  Special care is needed for PCIe port 0 in 2 line mode that
+  requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
+  mode.
+
 properties:
   compatible:
     items:
@@ -49,6 +67,40 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,serdes-wifi1:
+    description: Configure the WiFi1 Serdes port
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - pcie0_x2
+      - pcie0_x1
+      - ethernet
+    default: pcie0_x1
+
+  airoha,serdes-wifi2:
+    description: Configure the WiFi2 Serdes port
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - pcie0_x2
+      - pcie1_x1
+      - ethernet
+    default: pcie1_x1
+
+  airoha,serdes-usb1:
+    description: Configure the USB1 Serdes port
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - usb3
+      - ethernet
+    default: usb3
+
+  airoha,serdes-usb2:
+    description: Configure the USB2 Serdes port
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - usb3
+      - pcie2_x1
+    default: usb3
+
 required:
   - compatible
   - reg
@@ -64,6 +116,12 @@ allOf:
         reg:
           minItems: 2
 
+        airoha,serdes-wifi1: false
+        airoha,serdes-wifi2: false
+
+        airoha,serdes-usb1: false
+        airoha,serdes-usb2: false
+
         '#reset-cells': false
 
   - if:
@@ -75,6 +133,24 @@ allOf:
         reg:
           maxItems: 1
 
+  - if:
+      properties:
+        airoha,serdes-wifi1:
+          const: pcie0_x2
+    then:
+      properties:
+        airoha,serdes-wifi2:
+          const: pcie0_x2
+
+  - if:
+      properties:
+        airoha,serdes-wifi2:
+          const: pcie0_x2
+    then:
+      properties:
+        airoha,serdes-wifi1:
+          const: pcie0_x2
+
 additionalProperties: false
 
 examples:
@@ -87,15 +163,22 @@ examples:
       #clock-cells = <1>;
     };
 
+  # Example SCU node with Serdes set to PCIe0 to x2 mode
+  # and USB2 set to PCIe2 to x1 mode
   - |
     soc {
-      #address-cells = <2>;
-      #size-cells = <2>;
-
-      scuclk: clock-controller at 1fb00000 {
-        compatible = "airoha,en7581-scu";
-        reg = <0x0 0x1fb00000 0x0 0x970>;
-              #clock-cells = <1>;
-              #reset-cells = <1>;
-      };
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        scuclk: clock-controller at 1fb00000 {
+            compatible = "airoha,en7581-scu";
+            reg = <0x0 0x1fb00000 0x0 0x970>;
+
+            airoha,serdes-wifi1 = "pcie0_x2";
+            airoha,serdes-wifi2 = "pcie0_x2";
+            airoha,serdes-usb2 = "pcie2_x1";
+
+            #clock-cells = <1>;
+            #reset-cells = <1>;
+        };
     };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3eee238c2ea2..9944845ae9f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -736,6 +736,13 @@ F:	Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
 F:	drivers/phy/phy-airoha-pcie-regs.h
 F:	drivers/phy/phy-airoha-pcie.c
 
+AIROHA SCU SSR DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
+F:	include/dt-bindings/soc/airoha,scu-ssr.h
+
 AIROHA SPI SNFI DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
 M:	Ray Liu <ray.liu at airoha.com>
diff --git a/include/dt-bindings/soc/airoha,scu-ssr.h b/include/dt-bindings/soc/airoha,scu-ssr.h
new file mode 100644
index 000000000000..915f3cde7c1a
--- /dev/null
+++ b/include/dt-bindings/soc/airoha,scu-ssr.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef __DT_BINDINGS_AIROHA_SCU_SSR_H
+#define __DT_BINDINGS_AIROHA_SCU_SSR_H
+
+#define AIROHA_SCU_SERDES_WIFI1		0
+#define AIROHA_SCU_SERDES_WIFI2		1
+#define AIROHA_SCU_SERDES_USB1		2
+#define AIROHA_SCU_SERDES_USB2		3
+
+#endif /* __DT_BINDINGS_AIROHA_SCU_SSR_H */
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:27 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:27 +0100
Subject: [PATCH v2 04/11] soc: airoha: add support for configuring SCU SSR Serdes port
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-5-ansuelsmth@gmail.com>

Add support for configuring SCU SSR Serdes port. Airoha AN7581 SoC can
configure the different Serdes port by toggling bits in the SCU register
space.

Port Serdes mode are mutually exclusive, force example the USB2 Serdes port
can either used for USB 3.0 or PCIe 2 port. Enabling USB 3.0 makes the
PCIe 2 to not work.

The current supported Serdes port are:
- WiFi 1 and defaults to PCIe0 1 line mode
- Wifi 2 and defaults to PCIe1 1 line mode
- USB 1 and defaults to USB 3.0 mode
- USB 2 and defaults to USB 3.0 mode

WiFi 1, WiFi 2 and USB 1 also support a particular Ethernet mode that
can toggle between USXGMII or HSGMII mode (USB 1 only to HSGMII)
Such mode doesn't configure bits as specific Ethernet PCS driver will
take care of configuring the Serdes mode based on what is required.

This driver is to correctly setup these bits.
Single driver can't independently set the Serdes port mode as that
would cause a conflict if someone declare, for example, in DT
(and enable) PCIe 2 port and USB2 3.0 port.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 MAINTAINERS                               |   2 +
 drivers/soc/Kconfig                       |   1 +
 drivers/soc/Makefile                      |   1 +
 drivers/soc/airoha/Kconfig                |  18 ++
 drivers/soc/airoha/Makefile               |   3 +
 drivers/soc/airoha/airoha-scu-ssr.c       | 221 ++++++++++++++++++++++
 include/linux/soc/airoha/airoha-scu-ssr.h |  23 +++
 7 files changed, 269 insertions(+)
 create mode 100644 drivers/soc/airoha/Kconfig
 create mode 100644 drivers/soc/airoha/Makefile
 create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
 create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9944845ae9f5..7cd54c70aeed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -741,7 +741,9 @@ M:	Christian Marangi <ansuelsmth at gmail.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/soc/airoha/airoha,an7581-scu-ssr.yaml
+F:	drivers/soc/airoha/airoha-scu-ssr.c
 F:	include/dt-bindings/soc/airoha,scu-ssr.h
+F:	include/linux/soc/airoha/airoha-scu-ssr.h
 
 AIROHA SPI SNFI DRIVER
 M:	Lorenzo Bianconi <lorenzo at kernel.org>
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 6a8daeb8c4b9..21bacefd2e06 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/airoha/Kconfig"
 source "drivers/soc/amlogic/Kconfig"
 source "drivers/soc/apple/Kconfig"
 source "drivers/soc/aspeed/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 2037a8695cb2..2b4027837d60 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-y				+= airoha/
 obj-y				+= apple/
 obj-y				+= aspeed/
 obj-$(CONFIG_ARCH_AT91)		+= atmel/
diff --git a/drivers/soc/airoha/Kconfig b/drivers/soc/airoha/Kconfig
new file mode 100644
index 000000000000..56c677f8238d
--- /dev/null
+++ b/drivers/soc/airoha/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config AIROHA_SCU_SSR
+	tristate "Airoha SCU SSR Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	help
+	  Say 'Y' here to add support for Airoha SCU SSR driver.
+
+	  Airoha SoC pheriperal (like USB/PCIe/Ethernet port) are
+	  selected by toggling specific bit. Serdes Port line
+	  are mutually exclusive such as selecting PCIe port 2
+	  disable support for USB port 2 3.0 mode.
+
+	  This driver is used to configure such bit and expose
+	  an API to read the current status from a user of such
+	  Serdes lines.
+
diff --git a/drivers/soc/airoha/Makefile b/drivers/soc/airoha/Makefile
new file mode 100644
index 000000000000..530825251ae9
--- /dev/null
+++ b/drivers/soc/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_AIROHA_SCU_SSR)		+= airoha-scu-ssr.o
diff --git a/drivers/soc/airoha/airoha-scu-ssr.c b/drivers/soc/airoha/airoha-scu-ssr.c
new file mode 100644
index 000000000000..29e17577e9a4
--- /dev/null
+++ b/drivers/soc/airoha/airoha-scu-ssr.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth at gmail.com>
+ */
+
+#include <dt-bindings/soc/airoha,scu-ssr.h>
+#include <linux/bitfield.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/airoha/airoha-scu-ssr.h>
+
+#define AIROHA_SCU_PCIC			0x88
+#define   AIROHA_SCU_PCIE_2LANE_MODE	BIT(14)
+
+#define AIROHA_SCU_SSR3			0x94
+#define   AIROHA_SCU_SSUSB_HSGMII_SEL	BIT(29)
+
+#define AIROHA_SCU_SSTR			0x9c
+#define   AIROHA_SCU_PCIE_XSI0_SEL	GENMASK(14, 13)
+#define   AIROHA_SCU_PCIE_XSI0_SEL_PCIE	FIELD_PREP_CONST(AIROHA_SCU_PCIE_XSI0_SEL, 0x0)
+#define   AIROHA_SCU_PCIE_XSI1_SEL	GENMASK(12, 11)
+#define   AIROHA_SCU_PCIE_XSI1_SEL_PCIE	FIELD_PREP_CONST(AIROHA_SCU_PCIE_XSI0_SEL, 0x0)
+#define   AIROHA_SCU_USB_PCIE_SEL	BIT(3)
+
+#define AIROHA_SCU_MAX_SERDES_PORT	4
+
+struct airoha_scu_ssr_priv {
+	struct device *dev;
+	struct regmap *regmap;
+
+	unsigned int serdes_port[AIROHA_SCU_MAX_SERDES_PORT];
+};
+
+static const char * const airoha_scu_serdes_mode_to_str[] = {
+	[AIROHA_SCU_SERDES_MODE_PCIE0_X1] = "pcie0_x1",
+	[AIROHA_SCU_SERDES_MODE_PCIE0_X2] = "pcie0_x2",
+	[AIROHA_SCU_SERDES_MODE_PCIE1_X1] = "pcie1_x1",
+	[AIROHA_SCU_SERDES_MODE_PCIE2_X1] = "pcie2_x1",
+	[AIROHA_SCU_SERDES_MODE_USB3] = "usb3",
+	[AIROHA_SCU_SERDES_MODE_ETHERNET] = "ethernet",
+};
+
+static int airoha_scu_serdes_str_to_mode(const char *serdes_str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(airoha_scu_serdes_mode_to_str); i++)
+		if (!strncmp(serdes_str, airoha_scu_serdes_mode_to_str[i],
+			     strlen(airoha_scu_serdes_mode_to_str[i])))
+			return i;
+
+	return -EINVAL;
+}
+
+static int airoha_scu_ssr_apply_modes(struct airoha_scu_ssr_priv *priv)
+{
+	int ret;
+
+	/*
+	 * This is a very bad scenario and needs to be correctly warned
+	 * as it cause PCIe malfunction.
+	 */
+	if ((priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SERDES_MODE_PCIE0_X2 &&
+	     priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] != AIROHA_SCU_SERDES_MODE_PCIE0_X2) ||
+	    (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] != AIROHA_SCU_SERDES_MODE_PCIE0_X2 &&
+	     priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SERDES_MODE_PCIE0_X2)) {
+		WARN(true, "Wrong Serdes configuration for PCIe0 2 Line mode. Please check DT.\n");
+		return -EINVAL;
+	}
+
+	/* PCS driver takes care of setting the SCU bit for HSGMII or USXGMII */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SERDES_MODE_PCIE0_X1 ||
+	    priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SERDES_MODE_PCIE0_X2) {
+		ret = regmap_update_bits(priv->regmap, AIROHA_SCU_SSTR,
+					 AIROHA_SCU_PCIE_XSI0_SEL,
+					 AIROHA_SCU_PCIE_XSI0_SEL_PCIE);
+		if (ret)
+			return ret;
+	}
+
+	/* PCS driver takes care of setting the SCU bit for HSGMII or USXGMII */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SERDES_MODE_PCIE1_X1 ||
+	    priv->serdes_port[AIROHA_SCU_SERDES_WIFI2] == AIROHA_SCU_SERDES_MODE_PCIE0_X2) {
+		ret = regmap_update_bits(priv->regmap, AIROHA_SCU_SSTR,
+					 AIROHA_SCU_PCIE_XSI1_SEL,
+					 AIROHA_SCU_PCIE_XSI1_SEL_PCIE);
+		if (ret)
+			return ret;
+	}
+
+	/* Toggle PCIe0 2 Line mode if enabled or not */
+	if (priv->serdes_port[AIROHA_SCU_SERDES_WIFI1] == AIROHA_SCU_SERDES_MODE_PCIE0_X2)
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_PCIC,
+				      AIROHA_SCU_PCIE_2LANE_MODE);
+	else
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_PCIC,
+					AIROHA_SCU_PCIE_2LANE_MODE);
+	if (ret)
+		return ret;
+
+	if (priv->serdes_port[AIROHA_SCU_SERDES_USB1] == AIROHA_SCU_SERDES_MODE_ETHERNET)
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_SSR3,
+					AIROHA_SCU_SSUSB_HSGMII_SEL);
+	else
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_SSR3,
+				      AIROHA_SCU_SSUSB_HSGMII_SEL);
+	if (ret)
+		return ret;
+
+	if (priv->serdes_port[AIROHA_SCU_SERDES_USB2] == AIROHA_SCU_SERDES_MODE_PCIE2_X1)
+		ret = regmap_clear_bits(priv->regmap, AIROHA_SCU_SSTR,
+					AIROHA_SCU_USB_PCIE_SEL);
+	else
+		ret = regmap_set_bits(priv->regmap, AIROHA_SCU_SSTR,
+				      AIROHA_SCU_USB_PCIE_SEL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int airoha_scu_ssr_parse_mode(struct device *dev,
+				     struct airoha_scu_ssr_priv *priv,
+				     const char *property_name, unsigned int port,
+				     unsigned int default_mode)
+{
+	const struct airoha_scu_ssr_serdes_info *port_info;
+	const struct airoha_scu_ssr_data *pdata;
+	const char *serdes_mode;
+	int mode, i;
+
+	pdata = dev->platform_data;
+
+	if (of_property_read_string(dev->of_node, property_name,
+				    &serdes_mode)) {
+		priv->serdes_port[port] = default_mode;
+		return 0;
+	}
+
+	mode = airoha_scu_serdes_str_to_mode(serdes_mode);
+	if (mode) {
+		dev_err(dev, "invalid mode %s for %s\n", serdes_mode, property_name);
+		return mode;
+	}
+
+	port_info = &pdata->ports_info[port];
+	for (i = 0; i < port_info->num_modes; i++) {
+		if (port_info->possible_modes[i] == mode) {
+			priv->serdes_port[port] = mode;
+			return 0;
+		}
+	}
+
+	dev_err(dev, "mode %s not supported for %s", serdes_mode, property_name);
+	return -EINVAL;
+}
+
+static int airoha_scu_ssr_probe(struct platform_device *pdev)
+{
+	struct airoha_scu_ssr_priv *priv;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	/* Get regmap from MFD */
+	priv->regmap = dev_get_regmap(dev->parent, NULL);
+	if (!priv->regmap)
+		return -EINVAL;
+
+	ret = airoha_scu_ssr_parse_mode(dev, priv, "airoha,serdes-wifi1",
+					AIROHA_SCU_SERDES_WIFI1,
+					AIROHA_SCU_SERDES_MODE_PCIE0_X1);
+	if (ret)
+		return ret;
+
+	ret = airoha_scu_ssr_parse_mode(dev, priv, "airoha,serdes-wifi2",
+					AIROHA_SCU_SERDES_WIFI2,
+					AIROHA_SCU_SERDES_MODE_PCIE1_X1);
+	if (ret)
+		return ret;
+
+	ret = airoha_scu_ssr_parse_mode(dev, priv, "airoha,serdes-usb1",
+					AIROHA_SCU_SERDES_USB1,
+					AIROHA_SCU_SERDES_MODE_USB3);
+	if (ret)
+		return ret;
+
+	ret = airoha_scu_ssr_parse_mode(dev, priv, "airoha,serdes-usb2",
+					AIROHA_SCU_SERDES_USB2,
+					AIROHA_SCU_SERDES_MODE_USB3);
+	if (ret)
+		return ret;
+
+	ret = airoha_scu_ssr_apply_modes(priv);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static struct platform_driver airoha_scu_ssr_driver = {
+	.probe		= airoha_scu_ssr_probe,
+	.driver		= {
+		.name	= "airoha-scu-ssr",
+	},
+};
+
+module_platform_driver(airoha_scu_ssr_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Airoha SCU SSR/STR driver");
diff --git a/include/linux/soc/airoha/airoha-scu-ssr.h b/include/linux/soc/airoha/airoha-scu-ssr.h
new file mode 100644
index 000000000000..0224c0340b6d
--- /dev/null
+++ b/include/linux/soc/airoha/airoha-scu-ssr.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __AIROHA_SCU_SSR__
+#define __AIROHA_SCU_SSR__
+
+enum airoha_scu_serdes_modes {
+	AIROHA_SCU_SERDES_MODE_PCIE0_X1,
+	AIROHA_SCU_SERDES_MODE_PCIE0_X2,
+	AIROHA_SCU_SERDES_MODE_PCIE1_X1,
+	AIROHA_SCU_SERDES_MODE_PCIE2_X1,
+	AIROHA_SCU_SERDES_MODE_USB3,
+	AIROHA_SCU_SERDES_MODE_ETHERNET,
+};
+
+struct airoha_scu_ssr_serdes_info {
+	unsigned int *possible_modes;
+	unsigned int num_modes;
+};
+
+struct airoha_scu_ssr_data {
+	const struct airoha_scu_ssr_serdes_info *ports_info;
+};
+
+#endif
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:28 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:28 +0100
Subject: [PATCH v2 05/11] clk: en7523: define and register SoC SCU SSR driver for EN7581
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-6-ansuelsmth@gmail.com>

Define all the possible interface modes and register the SoC SCU SSR
platform driver for EN7581.

Failing to register the SCU SSR driver is not a critical error (example
the SoC driver is not enable) but will prevent PCIe or USB port to
function correctly.

Reference to the SSR pdev are stored in the new en7523 priv struct.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/clk/clk-en7523.c       | 99 ++++++++++++++++++++++++++++++++--
 include/linux/clk/clk-en7523.h | 10 ++++
 2 files changed, 106 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/clk/clk-en7523.h

diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 2a74bc8fed24..1f11fa769090 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -3,14 +3,17 @@
 #include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/clk-en7523.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/reset-controller.h>
+#include <linux/soc/airoha/airoha-scu-ssr.h>
 #include <dt-bindings/clock/en7523-clk.h>
 #include <dt-bindings/reset/airoha,en7581-reset.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
 
 #define RST_NR_PER_BANK			32
 
@@ -81,6 +84,7 @@ struct en_clk_soc_data {
 	const struct en_clk_desc *base_clks;
 	const struct clk_ops pcie_ops;
 	int (*hw_init)(struct platform_device *pdev,
+		       struct en_clk_priv *priv,
 		       const struct en_clk_soc_data *soc_data,
 		       struct clk_hw_onecell_data *clk_data);
 };
@@ -361,6 +365,51 @@ static const u16 en7581_rst_map[] = {
 	[EN7581_XPON_MAC_RST]		= RST_NR_PER_BANK + 31,
 };
 
+static unsigned int an7581_serdes_wifi1_possible_modes[] = {
+	AIROHA_SCU_SERDES_MODE_PCIE0_X1,
+	AIROHA_SCU_SERDES_MODE_PCIE0_X2,
+	AIROHA_SCU_SERDES_MODE_ETHERNET,
+};
+
+static unsigned int an7581_serdes_wifi2_possible_modes[] = {
+	AIROHA_SCU_SERDES_MODE_PCIE1_X1,
+	AIROHA_SCU_SERDES_MODE_PCIE0_X2,
+	AIROHA_SCU_SERDES_MODE_ETHERNET,
+};
+
+static unsigned int an7581_serdes_usb1_possible_modes[] = {
+	AIROHA_SCU_SERDES_MODE_USB3,
+	AIROHA_SCU_SERDES_MODE_ETHERNET,
+};
+
+static unsigned int an7581_serdes_usb2_possible_modes[] = {
+	AIROHA_SCU_SERDES_MODE_PCIE2_X1,
+	AIROHA_SCU_SERDES_MODE_ETHERNET,
+};
+
+static const struct airoha_scu_ssr_serdes_info an7581_ports_info[] = {
+	[AIROHA_SCU_SERDES_WIFI1] = {
+		.possible_modes = an7581_serdes_wifi1_possible_modes,
+		.num_modes = ARRAY_SIZE(an7581_serdes_wifi1_possible_modes),
+	},
+	[AIROHA_SCU_SERDES_WIFI2] = {
+		.possible_modes = an7581_serdes_wifi2_possible_modes,
+		.num_modes = ARRAY_SIZE(an7581_serdes_wifi2_possible_modes),
+	},
+	[AIROHA_SCU_SERDES_USB1] = {
+		.possible_modes = an7581_serdes_usb1_possible_modes,
+		.num_modes = ARRAY_SIZE(an7581_serdes_usb1_possible_modes),
+	},
+	[AIROHA_SCU_SERDES_USB2] = {
+		.possible_modes = an7581_serdes_usb2_possible_modes,
+		.num_modes = ARRAY_SIZE(an7581_serdes_usb2_possible_modes),
+	},
+};
+
+static const struct airoha_scu_ssr_data an7581_scu_ssr_data = {
+	.ports_info = an7581_ports_info,
+};
+
 static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
 {
 	if (!desc->base_bits)
@@ -557,6 +606,7 @@ static const struct regmap_config en7523_clk_regmap_config = {
 };
 
 static int en7523_clk_hw_init(struct platform_device *pdev,
+			      struct en_clk_priv *priv,
 			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
@@ -661,12 +711,38 @@ static int en7581_reset_register(struct device *dev, struct regmap *map)
 	return devm_reset_controller_register(dev, &rst_data->rcdev);
 }
 
+static void en7581_clk_register_ssr(struct platform_device *pdev,
+				    struct en_clk_priv *priv)
+{
+	struct platform_device_info pinfo = { };
+	struct platform_device *ssr_pdev;
+
+	pinfo.name = "airoha-scu-ssr";
+	pinfo.parent = &pdev->dev;
+	pinfo.id = PLATFORM_DEVID_AUTO;
+	pinfo.fwnode = of_fwnode_handle(pdev->dev.of_node);
+	pinfo.of_node_reused = true;
+	pinfo.data = &an7581_scu_ssr_data;
+	pinfo.size_data = sizeof(an7581_scu_ssr_data);
+
+	ssr_pdev = platform_device_register_data(&pdev->dev, "airoha-scu-ssr",
+						 PLATFORM_DEVID_AUTO,
+						 &an7581_scu_ssr_data,
+						 sizeof(an7581_scu_ssr_data));
+	if (IS_ERR(ssr_pdev))
+		dev_warn_probe(&pdev->dev, PTR_ERR(ssr_pdev), "failed to register SCU SSR driver.\n");
+
+	priv->ssr_pdev = ssr_pdev;
+}
+
 static int en7581_clk_hw_init(struct platform_device *pdev,
+			      struct en_clk_priv *priv,
 			      const struct en_clk_soc_data *soc_data,
 			      struct clk_hw_onecell_data *clk_data)
 {
 	struct regmap *map, *clk_map;
 	void __iomem *base;
+	int ret;
 
 	map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
 	if (IS_ERR(map))
@@ -687,7 +763,13 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
 			   FIELD_PREP(REG_PCIE_CTRL, 3));
 
-	return en7581_reset_register(&pdev->dev, clk_map);
+	ret = en7581_reset_register(&pdev->dev, clk_map);
+	if (ret)
+		return ret;
+
+	en7581_clk_register_ssr(pdev, priv);
+
+	return 0;
 }
 
 static int en7523_clk_probe(struct platform_device *pdev)
@@ -695,10 +777,15 @@ static int en7523_clk_probe(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	const struct en_clk_soc_data *soc_data;
 	struct clk_hw_onecell_data *clk_data;
+	struct en_clk_priv *priv;
 	int r;
 
 	soc_data = device_get_match_data(&pdev->dev);
 
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
 	clk_data = devm_kzalloc(&pdev->dev,
 				struct_size(clk_data, hws, soc_data->num_clocks),
 				GFP_KERNEL);
@@ -706,11 +793,17 @@ static int en7523_clk_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	clk_data->num = soc_data->num_clocks;
-	r = soc_data->hw_init(pdev, soc_data, clk_data);
+	r = soc_data->hw_init(pdev, priv, soc_data, clk_data);
 	if (r)
 		return r;
 
-	return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+	if (r)
+		return r;
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
 }
 
 static const struct en_clk_soc_data en7523_data = {
diff --git a/include/linux/clk/clk-en7523.h b/include/linux/clk/clk-en7523.h
new file mode 100644
index 000000000000..fc3b320dc7e9
--- /dev/null
+++ b/include/linux/clk/clk-en7523.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __LINUX_CLK_EN7523_H_
+#define __LINUX_CLK_EN7523_H_
+
+struct en_clk_priv {
+	struct platform_device *ssr_pdev;
+};
+
+#endif
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:29 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:29 +0100
Subject: [PATCH v2 06/11] soc: airoha: scu-ssr: expose API to read current Serdes Port mode
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-7-ansuelsmth@gmail.com>

Expose an API to read the current Serdes Port mode. This is needed for
pheriperal attached to the Serdes mode to validate the Serdes port is in
the correct mode.

Each driver will have to define in DT the phandle airoha,scu
pointing to the SCU node to make use of this API.

Function airoha_scu_ssr_get_serdes_mode() will then parse the phandle,
and extract tha Serdes Port state from the SCU SSR driver priv.

Driver will use the new API airoha_scu_ssr_get_serdes_mode() by passing
the dev and the serdes mode reference from dt-bindings header.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/soc/airoha/airoha-scu-ssr.c       | 50 +++++++++++++++++++++++
 include/linux/soc/airoha/airoha-scu-ssr.h | 11 +++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/soc/airoha/airoha-scu-ssr.c b/drivers/soc/airoha/airoha-scu-ssr.c
index 29e17577e9a4..3fbc36f793d0 100644
--- a/drivers/soc/airoha/airoha-scu-ssr.c
+++ b/drivers/soc/airoha/airoha-scu-ssr.c
@@ -5,6 +5,7 @@
 
 #include <dt-bindings/soc/airoha,scu-ssr.h>
 #include <linux/bitfield.h>
+#include <linux/clk/clk-en7523.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -54,6 +55,55 @@ static int airoha_scu_serdes_str_to_mode(const char *serdes_str)
 	return -EINVAL;
 }
 
+/**
+ * airoha_scu_ssr_get_serdes_mode - Get current Mode for Serdes Port
+ * @dev: Device pointer of the Serdes Port peripheral
+ * @port: Reference number of the Serdes Port
+ *
+ * Parse the phandle pointed by the Device Node property
+ * "airoha,scu" present in Devide Node of dev and get
+ * the current Mode of the Serdes Port reference by port
+ *
+ * Return the mode or a negative error code. If the pdev
+ * or the driver data for the SCU can't be found,
+ * -EPROBE_DEFER is returned.
+ */
+int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+				   unsigned int port)
+{
+	struct airoha_scu_ssr_priv *priv;
+	struct en_clk_priv *clk_priv;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	np = of_parse_phandle(dev->of_node, "airoha,scu", 0);
+	if (!np)
+		return -ENODEV;
+
+	if (!of_device_is_available(np)) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(np);
+	of_node_put(np);
+	if (!pdev || !platform_get_drvdata(pdev)) {
+		if (pdev)
+			put_device(&pdev->dev);
+		return -EPROBE_DEFER;
+	}
+
+	/*
+	 * Get pdev from clk priv. Clock driver register
+	 * SSR driver hence it can be assumed present.
+	 */
+	clk_priv = platform_get_drvdata(pdev);
+	priv = platform_get_drvdata(clk_priv->ssr_pdev);
+
+	return priv->serdes_port[port];
+}
+EXPORT_SYMBOL_GPL(airoha_scu_ssr_get_serdes_mode);
+
 static int airoha_scu_ssr_apply_modes(struct airoha_scu_ssr_priv *priv)
 {
 	int ret;
diff --git a/include/linux/soc/airoha/airoha-scu-ssr.h b/include/linux/soc/airoha/airoha-scu-ssr.h
index 0224c0340b6d..81f2c1b57889 100644
--- a/include/linux/soc/airoha/airoha-scu-ssr.h
+++ b/include/linux/soc/airoha/airoha-scu-ssr.h
@@ -20,4 +20,15 @@ struct airoha_scu_ssr_data {
 	const struct airoha_scu_ssr_serdes_info *ports_info;
 };
 
+#if IS_ENABLED(CONFIG_AIROHA_SCU_SSR)
+int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+				   unsigned int port);
+#else
+static inline int airoha_scu_ssr_get_serdes_mode(struct device *dev,
+						 unsigned int port);
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
 #endif
-- 
2.48.1



From ansuelsmth at gmail.com  Thu Mar 20 06:00:30 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 14:00:30 +0100
Subject: [PATCH v2 07/11] dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <20250320130054.4804-8-ansuelsmth@gmail.com>

Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
for the USB controller.

Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
always supported. The USB 3.0 mode is optional and depends on the Serdes
mode currently configured on the system for the USB port.

If the airoha,serdes-port property is not declared, it's assumed USB 3.0
mode is not supported, as the Serdes mode can't be validated.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../bindings/phy/airoha,an7581-usb-phy.yaml   | 83 +++++++++++++++++++
 MAINTAINERS                                   |  7 ++
 .../dt-bindings/phy/airoha,an7581-usb-phy.h   | 11 +++
 3 files changed, 101 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
 create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h

diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
new file mode 100644
index 000000000000..39ceaded5d0e
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7581 SoC USB PHY
+
+maintainers:
+  - Christian Marangi <ansuelsmth at gmail.com>
+
+description: >
+  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
+
+  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
+  always supported. The USB 3.0 mode is optional and depends on the Serdes
+  mode currently configured on the system for the USB port.
+
+  If the airoha,serdes-port property is not declared, it's assumed USB 3.0
+  mode is not supported, as the Serdes mode can't be validated.
+
+properties:
+  compatible:
+    const: airoha,an7581-usb-phy
+
+  reg:
+    maxItems: 1
+
+
+  airoha,usb2-monitor-clk-sel:
+    description: Describe what oscillator across the available 4
+      should be selected for USB 2.0 Slew Rate calibration.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3]
+
+  airoha,serdes-port:
+    description: Describe what Serdes Port is attached to the USB 3.0 port.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3]
+
+  airoha,scu:
+    description: Phandle to the SCU node for USB 3.0 Serdes mode validation.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  '#phy-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - airoha,usb2-monitor-clk-sel
+  - '#phy-cells'
+
+dependentRequired:
+  airoha,serdes-port: [ 'airoha,scu' ]
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/phy/airoha,an7581-usb-phy.h>
+    #include <dt-bindings/soc/airoha,scu-ssr.h>
+
+    phy at 1fac0000 {
+        compatible = "airoha,an7581-usb-phy";
+        reg = <0x1fac0000 0x10000>;
+
+        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL1>;
+        airoha,scu = <&scu>;
+        airoha,serdes-port = <AIROHA_SCU_SERDES_USB1>;
+
+        #phy-cells = <1>;
+    };
+
+    phy at 1fae0000 {
+        compatible = "airoha,an7581-usb-phy";
+        reg = <0x1fae0000 0x10000>;
+
+        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL2>;
+
+        #phy-cells = <1>;
+    };
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 7cd54c70aeed..c4a374da2b12 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -754,6 +754,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
 F:	drivers/spi/spi-airoha-snfi.c
 
+AIROHA USB PHY DRIVER
+M:	Christian Marangi <ansuelsmth at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+F:	include/dt-bindings/phy/airoha,an7581-usb-phy.h
+
 AIRSPY MEDIA DRIVER
 L:	linux-media at vger.kernel.org
 S:	Orphan
diff --git a/include/dt-bindings/phy/airoha,an7581-usb-phy.h b/include/dt-bindings/phy/airoha,an7581-usb-phy.h
new file mode 100644
index 000000000000..efbb0ae75e3a
--- /dev/null
+++ b/include/dt-bindings/phy/airoha,an7581-usb-phy.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+
+#ifndef _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_
+#define _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_
+
+#define AIROHA_USB2_MONCLK_SEL0                 0
+#define AIROHA_USB2_MONCLK_SEL1                 1
+#define AIROHA_USB2_MONCLK_SEL2                 2
+#define AIROHA_USB2_MONCLK_SEL3                 3
+
+#endif
-- 
2.48.1



From patrice.chotard at foss.st.com  Thu Mar 20 06:28:51 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Thu, 20 Mar 2025 14:28:51 +0100
Subject: [PATCH v5 4/8] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <f508b96e-81c8-41bd-baca-ebd1b4419904@kernel.org>
References: <20250219080059.367045-1-patrice.chotard@foss.st.com>
 <20250219080059.367045-5-patrice.chotard@foss.st.com>
 <eaf1ecca-4fde-4128-8590-6013c3a13a04@kernel.org>
 <8b1b7df5-07f4-4f95-88e7-4e95ee909ffd@foss.st.com>
 <ac119dba-6e73-496c-97e1-d59ac0fe4a27@kernel.org>
 <06244bfb-1bd0-4a07-a928-3d2e68a89259@foss.st.com>
 <f508b96e-81c8-41bd-baca-ebd1b4419904@kernel.org>
Message-ID: <1e3498a2-9279-4363-a0d9-8187933f6691@foss.st.com>



On 3/19/25 08:37, Krzysztof Kozlowski wrote:
> On 18/03/2025 14:40, Patrice CHOTARD wrote:
>>
>>
>> On 3/13/25 08:33, Krzysztof Kozlowski wrote:
>>> On 12/03/2025 15:23, Patrice CHOTARD wrote:
>>>>>> +static int stm32_omm_disable_child(struct device *dev)
>>>>>> +{
>>>>>> +	struct stm32_omm *omm = dev_get_drvdata(dev);
>>>>>> +	struct reset_control *reset;
>>>>>> +	int ret;
>>>>>> +	u8 i;
>>>>>> +
>>>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>>>> +		ret = clk_prepare_enable(omm->child[i].clk);
>>>>>> +		if (ret) {
>>>>>> +			dev_err(dev, "Can not enable clock\n");
>>>>>> +			return ret;
>>>>>> +		}
>>>>>> +
>>>>>> +		reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
>>>>>> +		if (IS_ERR(reset)) {
>>>>>> +			dev_err(dev, "Can't get child reset\n");
>>>>>
>>>>> Why do you get reset of child? Parent is not suppposed to poke there.
>>>>> You might not have the reset there in the first place and it would not
>>>>> be an error.
>>>>
>>>> By ressetting child (OSPI), we ensure they are disabled and in a known state.
>>>> See the comment below.
>>>>
>>>>>
>>>>>
>>>>>> +			return PTR_ERR(reset);
>>>>>> +		};
>>>>>> +
>>>>>> +		/* reset OSPI to ensure CR_EN bit is set to 0 */
>>>>>> +		reset_control_assert(reset);
>>>>>> +		udelay(2);
>>>>>> +		reset_control_deassert(reset);
>>>>>
>>>>> No, the child should handle this, not parent.
>>>>
>>>> Octo Memory Manager can only be configured if both child are disabled.
>>>> That's why here, parent handles this.
>>>
>>> So if device by any chance started and is doing some useful work, then
>>> you cancel that work and reset it?
>>
>> stm32_omm_configure() is only called if we get access granted on both children.
>> That means we are authorized to use these devices, so we can reset them.
>>
>>>
>>> And what if child does not have reset line? Your binding allows that, so
>>> how is it supposed to work then?
>>
>> Ah yes, you are right, the OSPI bindings need to be updated
>> by requiring reset lines and the driver spi-stm32-ospi.c as well.
>> I will send a fix for that.
>>
>> Thanks for pointing this.
>>
>>>
>>> This also leads me to questions about bindings - if you need to assert
>>> some reset, doesn't it mean that these resets are also coming through
>>> this device so they are part of this device node?
>>
>> As we are able to retrieve children's reset from their respective node,
>> if you don't mind, OMM bindings can be kept as it's currently.
> 
> But that is what the entire discussion is about - I do mind. I said it
> already - you are not supposed to poke into child's node.
> 
> If you need to toggle child's resources, then I claim these are your
> resources as well.

Hi Krzysztof 

Ok i will update both OMM driver and bindings accordingly.

> 
>>
>> And another information, on some MP2 SoCs family, there is only one 
>> OSPI instance. So for these SoCs, there is no Octo Memory Manager.
>>
>>>
>>>>
>>>>>
>>>>>> +
>>>>>> +		reset_control_put(reset);
>>>>>> +		clk_disable_unprepare(omm->child[i].clk);
>>>>>> +	}
>>>>>> +
>>>>>> +	return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int stm32_omm_probe(struct platform_device *pdev)
>>>>>> +{
>>>>>> +	struct platform_device *vdev;
>>>>>> +	struct device *dev = &pdev->dev;
>>>>>> +	struct stm32_omm *omm;
>>>>>> +	struct clk *clk;
>>>>>> +	int ret;
>>>>>> +	u8 child_access_granted = 0;
>>>>>
>>>>> Keep inits/assignments together
>>>>
>>>> ok
>>>>
>>>>>
>>>>>> +	u8 i, j;
>>>>>> +	bool child_access[OMM_CHILD_NB];
>>>>>> +
>>>>>> +	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
>>>>>> +	if (!omm)
>>>>>> +		return -ENOMEM;
>>>>>> +
>>>>>> +	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
>>>>>> +	if (IS_ERR(omm->io_base))
>>>>>> +		return PTR_ERR(omm->io_base);
>>>>>> +
>>>>>> +	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
>>>>>> +	if (IS_ERR(omm->mm_res))
>>>>>> +		return PTR_ERR(omm->mm_res);
>>>>>> +
>>>>>> +	/* check child's access */
>>>>>> +	for_each_child_of_node_scoped(dev->of_node, child) {
>>>>>> +		if (omm->nb_child >= OMM_CHILD_NB) {
>>>>>> +			dev_err(dev, "Bad DT, found too much children\n");
>>>>>> +			ret = -E2BIG;
>>>>>> +			goto err_clk_release;
>>>>>> +		}
>>>>>> +
>>>>>> +		if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
>>>>>> +			ret = -EINVAL;
>>>>>> +			goto err_clk_release;
>>>>>> +		}
>>>>>> +
>>>>>> +		ret = stm32_omm_check_access(dev, child);
>>>>>> +		if (ret < 0 && ret != -EACCES)
>>>>>> +			goto err_clk_release;
>>>>>> +
>>>>>> +		child_access[omm->nb_child] = false;
>>>>>> +		if (!ret) {
>>>>>> +			child_access_granted++;
>>>>>> +			child_access[omm->nb_child] = true;
>>>>>> +		}
>>>>>> +
>>>>>> +		omm->child[omm->nb_child].node = child;
>>>>>> +
>>>>>> +		clk = of_clk_get(child, 0);
>>>>>
>>>>> Why are you taking children clock? And why with this API, not clk_get?
>>>>
>>>> I need children's clock to reset them.
>>>
>>>
>>> The device driver should reset its device. It is not a discoverable bus,
>>> that would explain power sequencing from the parent.
>>>
>>>> Why of_clk_get() usage is a problem here ? i can't get your point ?
>>>
>>> Because it is not the API which device drivers should use. You should
>>> use clk_get or devm_clk_get.
>>
>>
>> ok, i will update this part using clk_get().
>>
>>>
>>>
>>>>
>>>>> This looks like mixing clock provider in the clock consumer.
>>>>>
>>>>>> +		if (IS_ERR(clk)) {
>>>>>> +			dev_err(dev, "Can't get child clock\n");
>>>>>
>>>>> Syntax is always return dev_err_probe (or ret = dev_err_probe).
>>>>
>>>> ok
>>>>
>>>>>
>>>>>> +			ret = PTR_ERR(clk);
>>>>>> +			goto err_clk_release;
>>>>>> +		};
>>>>>> +
>>>>>> +		omm->child[omm->nb_child].clk = clk;
>>>>>> +		omm->nb_child++;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (omm->nb_child != OMM_CHILD_NB) {
>>>>>> +		ret = -EINVAL;
>>>>>> +		goto err_clk_release;
>>>>>> +	}
>>>>>> +
>>>>>> +	platform_set_drvdata(pdev, omm);
>>>>>> +
>>>>>> +	pm_runtime_enable(dev);
>>>>>> +
>>>>>> +	/* check if OMM's resource access is granted */
>>>>>> +	ret = stm32_omm_check_access(dev, dev->of_node);
>>>>>> +	if (ret < 0 && ret != -EACCES)
>>>>>> +		goto err_clk_release;
>>>>>> +
>>>>>> +	if (!ret && child_access_granted == OMM_CHILD_NB) {
>>>>>> +		/* Ensure both OSPI instance are disabled before configuring OMM */
>>>>>> +		ret = stm32_omm_disable_child(dev);
>>>>>> +		if (ret)
>>>>>> +			goto err_clk_release;
>>>>>> +
>>>>>> +		ret = stm32_omm_configure(dev);
>>>>>> +		if (ret)
>>>>>> +			goto err_clk_release;
>>>>>> +	} else {
>>>>>> +		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
>>>>>> +		/*
>>>>>> +		 * AMCR can't be set, so check if current value is coherent
>>>>>> +		 * with memory-map areas defined in DT
>>>>>> +		 */
>>>>>> +		ret = stm32_omm_set_amcr(dev, false);
>>>>>> +		if (ret)
>>>>>> +			goto err_clk_release;
>>>>>> +	}
>>>>>> +
>>>>>> +	/* for each child, if resource access is granted and status "okay", probe it */
>>>>>> +	for (i = 0; i < omm->nb_child; i++) {
>>>>>> +		if (!child_access[i] || !of_device_is_available(omm->child[i].node))
>>>>>
>>>>> If you have a device available, why do you create one more platform device?
>>>>>
>>>>>> +			continue;
>>>>>> +
>>>>>> +		vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
>>>>>
>>>>> Why you cannot just populate the children?
>>>>
>>>> I can't use of_platform_populate(), by default it will populate all OMM's child.
>>>> Whereas here, we want to probe only the OMM's child which match our criteria.  
>>>
>>>
>>> Why wouldn't you populate everyone? The task of bus driver is not to
>>> filter out DT. If you got such DT - with all device nodes - you are
>>> expected to populate all of them. Otherwise, if you do not want all of
>>> them, it is expected that firmware or bootloader will give you DT
>>> without these nodes.
>>
>> We don't want to populate every child by default because we can get 
>> cases where one child is shared between Cortex A and Cortex M.
> 
> But in such case DTB would not have that child enabled.
> 
>> That's why we must check if access is granted which ensure that 
>> firewall semaphore is available (RIFSC semaphore in our case).
> 
> If you do not have access, means child is assigned to other processor,
> right? In that case that child would not have been enabled in your DTB.
> 
> Fix your DTB instead of creating another layer of handling children
> inside drivers.

In fact, initially, we wanted to avoid to trigger Illegal Access in case user 
didn't use correct DT, that's why, here, double checks have been implemented.
But Ok, i will clean this part and simply populate children.

Thanks
Patrice.

> 
> 
> Best regards,
> Krzysztof


From ardb at kernel.org  Thu Mar 20 06:37:08 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Thu, 20 Mar 2025 14:37:08 +0100
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250319150533.37440-3-miko.lenczewski@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com> <20250319150533.37440-3-miko.lenczewski@arm.com>
Message-ID: <CAMj1kXFOofRCiVHxxxBZMGQHRH-ghtqNxgd=uww9D4sr4vvjEQ@mail.gmail.com>

On Wed, 19 Mar 2025 at 16:06, Miko?aj Lenczewski
<miko.lenczewski at arm.com> wrote:
>
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for, as well as a kernel commandline parameter to optionally
> disable BBML2 altogether.
>
> This is a system feature as we might have a big.LITTLE architecture
> where some cores support BBML2 and some don't, but we want all cores to
> be available and BBM to default to level 0 (as opposed to having cores
> without BBML2 not coming online).
>
> To support BBML2 in as wide a range of contexts as we can, we want not
> only the architectural guarantees that BBML2 makes, but additionally
> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
> us having to prove that no recursive faults can be induced in any path
> that uses BBML2, allowing its use for arbitrary kernel mappings.
> Support detection of such CPUs.
>
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |  3 +
>  arch/arm64/Kconfig                            | 11 +++
>  arch/arm64/include/asm/cpucaps.h              |  2 +
>  arch/arm64/include/asm/cpufeature.h           |  5 ++
>  arch/arm64/kernel/cpufeature.c                | 68 +++++++++++++++++++
>  arch/arm64/kernel/pi/idreg-override.c         |  2 +
>  arch/arm64/tools/cpucaps                      |  1 +
>  7 files changed, 92 insertions(+)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fb8752b42ec8..3e4cc917a07e 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -453,6 +453,9 @@
>         arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>                         32 bit applications.
>
> +       arm64.nobbml2   [ARM64] Unconditionally disable Break-Before-Make Level
> +                       2 support
> +
>         arm64.nobti     [ARM64] Unconditionally disable Branch Target
>                         Identification support
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 940343beb3d4..49deda2b22ae 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>           The feature introduces new assembly instructions, and they were
>           support when binutils >= 2.30.
>
> +config ARM64_BBML2_NOABORT
> +       bool "Enable support for Break-Before-Make Level 2 detection and usage"
> +       default y
> +       help
> +         FEAT_BBM provides detection of support levels for break-before-make
> +         sequences. If BBM level 2 is supported, some TLB maintenance requirements
> +         can be relaxed to improve performance. We additonally require the
> +         property that the implementation cannot ever raise TLB Conflict Aborts.
> +         Selecting N causes the kernel to fallback to BBM level 0 behaviour
> +         even if the system supports BBM level 2.
> +
>  endmenu # "ARMv8.4 architectural features"
>
>  menu "ARMv8.5 architectural features"
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 0b5ca6e0eb09..2d6db33d4e45 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>                 return IS_ENABLED(CONFIG_ARM64_PAN);
>         case ARM64_HAS_EPAN:
>                 return IS_ENABLED(CONFIG_ARM64_EPAN);
> +       case ARM64_HAS_BBML2_NOABORT:
> +               return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>         case ARM64_SVE:
>                 return IS_ENABLED(CONFIG_ARM64_SVE);
>         case ARM64_SME:
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index e0e4478f5fb5..108ef3fbbc00 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
>         return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>  }
>
> +static inline bool system_supports_bbml2_noabort(void)
> +{
> +       return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
> +}
> +
>  int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>  bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index d561cf3b8ac7..1a4adcda267b 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>         return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>  }
>
> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> +{

We generally start these block comments with just /* on the first line

> +       /* We want to allow usage of bbml2 in as wide a range of kernel contexts
> +        * as possible. This list is therefore an allow-list of known-good
> +        * implementations that both support bbml2 and additionally, fulfill the
> +        * extra constraint of never generating TLB conflict aborts when using
> +        * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> +        * kernel contexts difficult to prove safe against recursive aborts).
> +        *
> +        * Note that implementations can only be considered "known-good" if their
> +        * implementors attest to the fact that the implementation never raises
> +        * TLBI conflict aborts for bbml2 mapping granularity changes.
> +        */
> +       static const struct midr_range supports_bbml2_noabort_list[] = {
> +               MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> +               MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> +               {}
> +       };
> +

Why on earth is this needed? Is there nothing in the architecture that
can inform us about this? That seems like a huge oversight to me ...


From glaroque at baylibre.com  Thu Mar 20 06:41:45 2025
From: glaroque at baylibre.com (Guillaume La Roque)
Date: Thu, 20 Mar 2025 14:41:45 +0100
Subject: [PATCH v2] firmware: config: ti-sci: Default set to ARCH_K3 for
 the ti sci driver
In-Reply-To: <c506a805-9221-4afe-8d98-af0ca97a1fd2@app.fastmail.com>
References: <20250220-ti-firmware-v2-1-ff26883c6ce9@baylibre.com>
 <c506a805-9221-4afe-8d98-af0ca97a1fd2@app.fastmail.com>
Message-ID: <818de9a7-b308-4e00-9eba-3f58e1d89bbd@baylibre.com>

Le 19/03/2025 ? 22:45, Arnd Bergmann a ?crit?:
> On Thu, Feb 20, 2025, at 14:31, Guillaume La Roque wrote:
>> With ARCH_K3=y we cannot enable TI_SCI_PROTOCOL=m because
>> ARCH_K3 selects TI_SCI_PROTOCOL.
>>
>> Modify the logic to enable TI_SCI_PROTOCOL by default when ARCH_K3=y
>> allowing us to submit a future patch to remove select on ARCH_K3 without
>> breaking existing users.
>>
>> Signed-off-by: Guillaume La Roque <glaroque at baylibre.com>
>> ---
>> Link to comment done on last serie [1] we come back on first version of
>> series[2] to not use imply but set deps on ARCH_K3 in driver directly.
>> An other patch will be sent to update Kconfig.platform when this patch
>> is merged.
> I just merged the patch and hadn't seen the earlier discussion,
> just two small notes from me:
>
> - thanks for doing it this way instead of the backwards 'imply'
> - there is really no need to split it into two steps, since the
>    change to the Kconfig.platforms file logically goes with this
>    one and I would merge both through the SoC tree, having it
>    as a single patch would make sense.
>
>          Arnd

Hi,

thanks for merged.

i do what we ask me in review in fact or perhaps i misunderstand sorry 
for that.

Guillaume



From ryan.roberts at arm.com  Thu Mar 20 07:01:38 2025
From: ryan.roberts at arm.com (Ryan Roberts)
Date: Thu, 20 Mar 2025 14:01:38 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <CAMj1kXFOofRCiVHxxxBZMGQHRH-ghtqNxgd=uww9D4sr4vvjEQ@mail.gmail.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
 <CAMj1kXFOofRCiVHxxxBZMGQHRH-ghtqNxgd=uww9D4sr4vvjEQ@mail.gmail.com>
Message-ID: <2cbca34c-477c-4055-b388-a13bb6c22b4d@arm.com>

On 20/03/2025 13:37, Ard Biesheuvel wrote:
> On Wed, 19 Mar 2025 at 16:06, Miko?aj Lenczewski
> <miko.lenczewski at arm.com> wrote:
>>
>> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
>> and this commit adds a dedicated BBML2 cpufeature to test against
>> support for, as well as a kernel commandline parameter to optionally
>> disable BBML2 altogether.
>>
>> This is a system feature as we might have a big.LITTLE architecture
>> where some cores support BBML2 and some don't, but we want all cores to
>> be available and BBM to default to level 0 (as opposed to having cores
>> without BBML2 not coming online).
>>
>> To support BBML2 in as wide a range of contexts as we can, we want not
>> only the architectural guarantees that BBML2 makes, but additionally
>> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
>> us having to prove that no recursive faults can be induced in any path
>> that uses BBML2, allowing its use for arbitrary kernel mappings.
>> Support detection of such CPUs.
>>
>> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
>> ---
>>  .../admin-guide/kernel-parameters.txt         |  3 +
>>  arch/arm64/Kconfig                            | 11 +++
>>  arch/arm64/include/asm/cpucaps.h              |  2 +
>>  arch/arm64/include/asm/cpufeature.h           |  5 ++
>>  arch/arm64/kernel/cpufeature.c                | 68 +++++++++++++++++++
>>  arch/arm64/kernel/pi/idreg-override.c         |  2 +
>>  arch/arm64/tools/cpucaps                      |  1 +
>>  7 files changed, 92 insertions(+)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index fb8752b42ec8..3e4cc917a07e 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -453,6 +453,9 @@
>>         arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>>                         32 bit applications.
>>
>> +       arm64.nobbml2   [ARM64] Unconditionally disable Break-Before-Make Level
>> +                       2 support
>> +
>>         arm64.nobti     [ARM64] Unconditionally disable Branch Target
>>                         Identification support
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 940343beb3d4..49deda2b22ae 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>>           The feature introduces new assembly instructions, and they were
>>           support when binutils >= 2.30.
>>
>> +config ARM64_BBML2_NOABORT
>> +       bool "Enable support for Break-Before-Make Level 2 detection and usage"
>> +       default y
>> +       help
>> +         FEAT_BBM provides detection of support levels for break-before-make
>> +         sequences. If BBM level 2 is supported, some TLB maintenance requirements
>> +         can be relaxed to improve performance. We additonally require the
>> +         property that the implementation cannot ever raise TLB Conflict Aborts.
>> +         Selecting N causes the kernel to fallback to BBM level 0 behaviour
>> +         even if the system supports BBM level 2.
>> +
>>  endmenu # "ARMv8.4 architectural features"
>>
>>  menu "ARMv8.5 architectural features"
>> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
>> index 0b5ca6e0eb09..2d6db33d4e45 100644
>> --- a/arch/arm64/include/asm/cpucaps.h
>> +++ b/arch/arm64/include/asm/cpucaps.h
>> @@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
>>                 return IS_ENABLED(CONFIG_ARM64_PAN);
>>         case ARM64_HAS_EPAN:
>>                 return IS_ENABLED(CONFIG_ARM64_EPAN);
>> +       case ARM64_HAS_BBML2_NOABORT:
>> +               return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
>>         case ARM64_SVE:
>>                 return IS_ENABLED(CONFIG_ARM64_SVE);
>>         case ARM64_SME:
>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
>> index e0e4478f5fb5..108ef3fbbc00 100644
>> --- a/arch/arm64/include/asm/cpufeature.h
>> +++ b/arch/arm64/include/asm/cpufeature.h
>> @@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
>>         return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
>>  }
>>
>> +static inline bool system_supports_bbml2_noabort(void)
>> +{
>> +       return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
>> +}
>> +
>>  int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
>>  bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>>
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index d561cf3b8ac7..1a4adcda267b 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>>         return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>>  }
>>
>> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>> +{
> 
> We generally start these block comments with just /* on the first line
> 
>> +       /* We want to allow usage of bbml2 in as wide a range of kernel contexts
>> +        * as possible. This list is therefore an allow-list of known-good
>> +        * implementations that both support bbml2 and additionally, fulfill the
>> +        * extra constraint of never generating TLB conflict aborts when using
>> +        * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
>> +        * kernel contexts difficult to prove safe against recursive aborts).
>> +        *
>> +        * Note that implementations can only be considered "known-good" if their
>> +        * implementors attest to the fact that the implementation never raises
>> +        * TLBI conflict aborts for bbml2 mapping granularity changes.
>> +        */
>> +       static const struct midr_range supports_bbml2_noabort_list[] = {
>> +               MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
>> +               MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
>> +               {}
>> +       };
>> +
> 
> Why on earth is this needed? Is there nothing in the architecture that
> can inform us about this? That seems like a huge oversight to me ...

Currently the architecture can only tell us about the BBM support level.
Currently level 2 is the highest and that permits an implementation to raise a
conflict abort instead of handling it in HW.

Since this series only relies on BBML2 for user space memory, we believe we
could contain and handle any conflict abort safely (the first version of this
series handled the abort). But Yang Shi has a series on list that aims to use
BBML2 to enable dynamically splitting the linear map. It becomes much harder to
reason about the safety of any conflict abort in that case.

Will was keen to take this approach were we decide if the HW supports
"BBML2+NOABORT" semanitics based on the MIDR. Plans are in flight to fix the
arch so we can tidy this up long term, but Will didn't want to hold up Ampere.

Thanks,
Ryan




From robin.murphy at arm.com  Thu Mar 20 07:21:28 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 20 Mar 2025 14:21:28 +0000
Subject: [PATCH] iommu: Split out and tidy up Arm Kconfig
Message-ID: <a614ec86ba78c09cd16e348f633f6bb38793391f.1742480488.git.robin.murphy@arm.com>

There are quite a lot of options for the Arm drivers, still all buried
in the top-level Kconfig. For ease of use and consistency with all the
other subdirectories, break these out into drivers/arm. For similar
clarity and self-consistency, also tweak the ARM_SMMU sub-options to use
"if" instead of "depends", to match ARM_SMMU_V3. Lastly also clean up
the slightly messy description of ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT as
highlighted by Geert - by now we really shouldn't need commentary on
v4.x kernel behaviour anyway - and downgrade it to EXPERT as the first
step in the 6-year-old threat to remove it entirely.

Cc: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/iommu/Kconfig     | 157 +-------------------------------------
 drivers/iommu/arm/Kconfig | 144 ++++++++++++++++++++++++++++++++++
 2 files changed, 145 insertions(+), 156 deletions(-)
 create mode 100644 drivers/iommu/arm/Kconfig

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d935b59abb35..5ad3b7b8bfeb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -193,6 +193,7 @@ config MSM_IOMMU
 	  If unsure, say N here.
 
 source "drivers/iommu/amd/Kconfig"
+source "drivers/iommu/arm/Kconfig"
 source "drivers/iommu/intel/Kconfig"
 source "drivers/iommu/iommufd/Kconfig"
 source "drivers/iommu/riscv/Kconfig"
@@ -315,150 +316,6 @@ config APPLE_DART
 
 	  Say Y here if you are using an Apple SoC.
 
-# ARM IOMMU support
-config ARM_SMMU
-	tristate "ARM Ltd. System MMU (SMMU) Support"
-	depends on ARM64 || ARM || COMPILE_TEST
-	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
-	select IOMMU_API
-	select IOMMU_IO_PGTABLE_LPAE
-	select ARM_DMA_USE_IOMMU if ARM
-	help
-	  Support for implementations of the ARM System MMU architecture
-	  versions 1 and 2.
-
-	  Say Y here if your SoC includes an IOMMU device implementing
-	  the ARM SMMU architecture.
-
-config ARM_SMMU_LEGACY_DT_BINDINGS
-	bool "Support the legacy \"mmu-masters\" devicetree bindings"
-	depends on ARM_SMMU=y && OF
-	help
-	  Support for the badly designed and deprecated "mmu-masters"
-	  devicetree bindings. This allows some DMA masters to attach
-	  to the SMMU but does not provide any support via the DMA API.
-	  If you're lucky, you might be able to get VFIO up and running.
-
-	  If you say Y here then you'll make me very sad. Instead, say N
-	  and move your firmware to the utopian future that was 2016.
-
-config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT
-	bool "Default to disabling bypass on ARM SMMU v1 and v2"
-	depends on ARM_SMMU
-	default y
-	help
-	  Say Y here to (by default) disable bypass streams such that
-	  incoming transactions from devices that are not attached to
-	  an iommu domain will report an abort back to the device and
-	  will not be allowed to pass through the SMMU.
-
-	  Any old kernels that existed before this KConfig was
-	  introduced would default to _allowing_ bypass (AKA the
-	  equivalent of NO for this config).  However the default for
-	  this option is YES because the old behavior is insecure.
-
-	  There are few reasons to allow unmatched stream bypass, and
-	  even fewer good ones.  If saying YES here breaks your board
-	  you should work on fixing your board.  This KConfig option
-	  is expected to be removed in the future and we'll simply
-	  hardcode the bypass disable in the code.
-
-	  NOTE: the kernel command line parameter
-	  'arm-smmu.disable_bypass' will continue to override this
-	  config.
-
-config ARM_SMMU_MMU_500_CPRE_ERRATA
-	bool "Enable errata workaround for CPRE in SMMU reset path"
-	depends on ARM_SMMU
-	default y
-	help
-	  Say Y here (by default) to apply workaround to disable
-	  MMU-500's next-page prefetcher for sake of 4 known errata.
-
-	  Say N here only when it is sure that any errata related to
-	  prefetch enablement are not applicable on the platform.
-	  Refer silicon-errata.rst for info on errata IDs.
-
-config ARM_SMMU_QCOM
-	def_tristate y
-	depends on ARM_SMMU && ARCH_QCOM
-	select QCOM_SCM
-	help
-	  When running on a Qualcomm platform that has the custom variant
-	  of the ARM SMMU, this needs to be built into the SMMU driver.
-
-config ARM_SMMU_QCOM_DEBUG
-	bool "ARM SMMU QCOM implementation defined debug support"
-	depends on ARM_SMMU_QCOM=y
-	help
-	  Support for implementation specific debug features in ARM SMMU
-	  hardware found in QTI platforms. This include support for
-	  the Translation Buffer Units (TBU) that can be used to obtain
-	  additional information when debugging memory management issues
-	  like context faults.
-
-	  Say Y here to enable debug for issues such as context faults
-	  or TLB sync timeouts which requires implementation defined
-	  register dumps.
-
-config ARM_SMMU_V3
-	tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
-	depends on ARM64
-	select IOMMU_API
-	select IOMMU_IO_PGTABLE_LPAE
-	select GENERIC_MSI_IRQ
-	select IOMMUFD_DRIVER if IOMMUFD
-	help
-	  Support for implementations of the ARM System MMU architecture
-	  version 3 providing translation support to a PCIe root complex.
-
-	  Say Y here if your system includes an IOMMU device implementing
-	  the ARM SMMUv3 architecture.
-
-if ARM_SMMU_V3
-config ARM_SMMU_V3_SVA
-	bool "Shared Virtual Addressing support for the ARM SMMUv3"
-	select IOMMU_SVA
-	select IOMMU_IOPF
-	select MMU_NOTIFIER
-	help
-	  Support for sharing process address spaces with devices using the
-	  SMMUv3.
-
-	  Say Y here if your system supports SVA extensions such as PCIe PASID
-	  and PRI.
-
-config ARM_SMMU_V3_IOMMUFD
-	bool "Enable IOMMUFD features for ARM SMMUv3 (EXPERIMENTAL)"
-	depends on IOMMUFD
-	help
-	  Support for IOMMUFD features intended to support virtual machines
-	  with accelerated virtual IOMMUs.
-
-	  Say Y here if you are doing development and testing on this feature.
-
-config ARM_SMMU_V3_KUNIT_TEST
-	tristate "KUnit tests for arm-smmu-v3 driver"  if !KUNIT_ALL_TESTS
-	depends on KUNIT
-	depends on ARM_SMMU_V3_SVA
-	default KUNIT_ALL_TESTS
-	help
-	  Enable this option to unit-test arm-smmu-v3 driver functions.
-
-	  If unsure, say N.
-
-config TEGRA241_CMDQV
-	bool "NVIDIA Tegra241 CMDQ-V extension support for ARM SMMUv3"
-	depends on ACPI
-	help
-	  Support for NVIDIA CMDQ-Virtualization extension for ARM SMMUv3. The
-	  CMDQ-V extension is similar to v3.3 ECMDQ for multi command queues
-	  support, except with virtualization capabilities.
-
-	  Say Y here if your system is NVIDIA Tegra241 (Grace) or it has the same
-	  CMDQ-V extension.
-endif
-
 config S390_IOMMU
 	def_bool y if S390 && PCI
 	depends on S390 && PCI
@@ -495,18 +352,6 @@ config MTK_IOMMU_V1
 
 	  if unsure, say N here.
 
-config QCOM_IOMMU
-	# Note: iommu drivers cannot (yet?) be built as modules
-	bool "Qualcomm IOMMU Support"
-	depends on ARCH_QCOM || COMPILE_TEST
-	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
-	select QCOM_SCM
-	select IOMMU_API
-	select IOMMU_IO_PGTABLE_LPAE
-	select ARM_DMA_USE_IOMMU
-	help
-	  Support for IOMMU on certain Qualcomm SoCs.
-
 config HYPERV_IOMMU
 	bool "Hyper-V IRQ Handling"
 	depends on HYPERV && X86
diff --git a/drivers/iommu/arm/Kconfig b/drivers/iommu/arm/Kconfig
new file mode 100644
index 000000000000..ef42bbe07dbe
--- /dev/null
+++ b/drivers/iommu/arm/Kconfig
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# ARM IOMMU support
+config ARM_SMMU
+	tristate "ARM Ltd. System MMU (SMMU) Support"
+	depends on ARM64 || ARM || COMPILE_TEST
+	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
+	select IOMMU_API
+	select IOMMU_IO_PGTABLE_LPAE
+	select ARM_DMA_USE_IOMMU if ARM
+	help
+	  Support for implementations of the ARM System MMU architecture
+	  versions 1 and 2.
+
+	  Say Y here if your SoC includes an IOMMU device implementing
+	  the ARM SMMU architecture.
+
+if ARM_SMMU
+config ARM_SMMU_LEGACY_DT_BINDINGS
+	bool "Support the legacy \"mmu-masters\" devicetree bindings"
+	depends on ARM_SMMU=y && OF
+	help
+	  Support for the badly designed and deprecated "mmu-masters"
+	  devicetree bindings. This allows some DMA masters to attach
+	  to the SMMU but does not provide any support via the DMA API.
+	  If you're lucky, you might be able to get VFIO up and running.
+
+	  If you say Y here then you'll make me very sad. Instead, say N
+	  and move your firmware to the utopian future that was 2016.
+
+config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT
+	bool "Disable unmatched stream bypass by default" if EXPERT
+	default y
+	help
+	  If your firmware is broken and fails to describe StreamIDs which
+	  Linux should know about in order to manage the SMMU correctly and
+	  securely, and you don't want to boot with the 'arm-smmu.disable_bypass=0'
+	  command line parameter, then as a last resort you can turn it off
+	  by default here. But don't. This option may be removed at any time.
+
+	  Note that 'arm-smmu.disable_bypass=1' will still take precedence.
+
+config ARM_SMMU_MMU_500_CPRE_ERRATA
+	bool "Enable errata workaround for CPRE in SMMU reset path"
+	default y
+	help
+	  Say Y here (by default) to apply workaround to disable
+	  MMU-500's next-page prefetcher for sake of 4 known errata.
+
+	  Say N here only when it is sure that any errata related to
+	  prefetch enablement are not applicable on the platform.
+	  Refer silicon-errata.rst for info on errata IDs.
+
+config ARM_SMMU_QCOM
+	def_tristate y
+	depends on ARCH_QCOM
+	select QCOM_SCM
+	help
+	  When running on a Qualcomm platform that has the custom variant
+	  of the ARM SMMU, this needs to be built into the SMMU driver.
+
+config ARM_SMMU_QCOM_DEBUG
+	bool "ARM SMMU QCOM implementation defined debug support"
+	depends on ARM_SMMU_QCOM=y
+	help
+	  Support for implementation specific debug features in ARM SMMU
+	  hardware found in QTI platforms. This include support for
+	  the Translation Buffer Units (TBU) that can be used to obtain
+	  additional information when debugging memory management issues
+	  like context faults.
+
+	  Say Y here to enable debug for issues such as context faults
+	  or TLB sync timeouts which requires implementation defined
+	  register dumps.
+endif
+
+config ARM_SMMU_V3
+	tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
+	depends on ARM64
+	select IOMMU_API
+	select IOMMU_IO_PGTABLE_LPAE
+	select GENERIC_MSI_IRQ
+	select IOMMUFD_DRIVER if IOMMUFD
+	help
+	  Support for implementations of the ARM System MMU architecture
+	  version 3 providing translation support to a PCIe root complex.
+
+	  Say Y here if your system includes an IOMMU device implementing
+	  the ARM SMMUv3 architecture.
+
+if ARM_SMMU_V3
+config ARM_SMMU_V3_SVA
+	bool "Shared Virtual Addressing support for the ARM SMMUv3"
+	select IOMMU_SVA
+	select IOMMU_IOPF
+	select MMU_NOTIFIER
+	help
+	  Support for sharing process address spaces with devices using the
+	  SMMUv3.
+
+	  Say Y here if your system supports SVA extensions such as PCIe PASID
+	  and PRI.
+
+config ARM_SMMU_V3_IOMMUFD
+	bool "Enable IOMMUFD features for ARM SMMUv3 (EXPERIMENTAL)"
+	depends on IOMMUFD
+	help
+	  Support for IOMMUFD features intended to support virtual machines
+	  with accelerated virtual IOMMUs.
+
+	  Say Y here if you are doing development and testing on this feature.
+
+config ARM_SMMU_V3_KUNIT_TEST
+	tristate "KUnit tests for arm-smmu-v3 driver"  if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	depends on ARM_SMMU_V3_SVA
+	default KUNIT_ALL_TESTS
+	help
+	  Enable this option to unit-test arm-smmu-v3 driver functions.
+
+	  If unsure, say N.
+
+config TEGRA241_CMDQV
+	bool "NVIDIA Tegra241 CMDQ-V extension support for ARM SMMUv3"
+	depends on ACPI
+	help
+	  Support for NVIDIA CMDQ-Virtualization extension for ARM SMMUv3. The
+	  CMDQ-V extension is similar to v3.3 ECMDQ for multi command queues
+	  support, except with virtualization capabilities.
+
+	  Say Y here if your system is NVIDIA Tegra241 (Grace) or it has the same
+	  CMDQ-V extension.
+endif
+
+config QCOM_IOMMU
+	# Note: iommu drivers cannot (yet?) be built as modules
+	bool "Qualcomm IOMMU Support"
+	depends on ARCH_QCOM || COMPILE_TEST
+	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
+	select QCOM_SCM
+	select IOMMU_API
+	select IOMMU_IO_PGTABLE_LPAE
+	select ARM_DMA_USE_IOMMU
+	help
+	  Support for IOMMU on certain Qualcomm SoCs.
-- 
2.39.2.101.g768bb238c484.dirty



From linus.walleij at linaro.org  Thu Mar 20 07:26:12 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 20 Mar 2025 15:26:12 +0100
Subject: [PATCH -next v6 1/8] entry: Split generic entry into generic exception and syscall entry
In-Reply-To: <20250213130007.1418890-2-ruanjinjie@huawei.com>
References: <20250213130007.1418890-2-ruanjinjie@huawei.com>
Message-ID: <20250320142612.396250-1-linus.walleij@linaro.org>

> Currently CONFIG_GENERIC_ENTRY enables both the generic exception
> entry logic and the generic syscall entry logic, which are otherwise
> loosely coupled.
>
> Introduce separate config options for these so that archtiectures can
> select the two independently. This will make it easier for
> architectures to migrate to generic entry code.
>
> Suggested-by: Mark Rutland <mark.rutland at arm.com>
> Signed-off-by: Jinjie Ruan <ruanjinjie at huawei.com>

If the generic entry maintainer (hi Thomas) thinks this patch is
OK it would be nice to have it applied because it will also make
the ARM32 transition to generic entry easier as we can work on
exception and syscall entry each in isolation.

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From james.clark at linaro.org  Thu Mar 20 07:34:10 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:10 +0000
Subject: [PATCH v3 1/7] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-1-d3145c153820@linaro.org>

The self hosted claim tag will be reset on device probe in a later
commit. We'll want to do this before coresight_register() is called so
won't have a coresight_device and have to use cs_access instead.

Also make them public and create locked and unlocked versions for
later use.

These look functions look like they set the whole tags register as one
value, but they only set and clear the self hosted bit using a SET/CLR
bits mechanism so also rename the functions to reflect this better.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 27 +++++++++++++++++++--------
 include/linux/coresight.h                    |  3 ++-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index fb43ef6a3b1f..8471aefeac76 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -144,19 +144,30 @@ static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
 	return coresight_read_claim_tags(csdev) != 0;
 }
 
-static inline void coresight_set_claim_tags(struct coresight_device *csdev)
+static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
 	isb();
 }
 
-static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
+void coresight_clear_self_claim_tag(struct csdev_access *csa)
 {
-	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
+	if (csa->io_mem)
+		CS_UNLOCK(csa->base);
+	coresight_clear_self_claim_tag_unlocked(csa);
+	if (csa->io_mem)
+		CS_LOCK(csa->base);
+}
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
+
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
+{
+	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMCLR);
 	isb();
 }
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
 
 /*
  * coresight_claim_device_unlocked : Claim the device for self-hosted usage
@@ -176,11 +187,11 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
 	if (coresight_is_claimed_any(csdev))
 		return -EBUSY;
 
-	coresight_set_claim_tags(csdev);
+	coresight_set_self_claim_tag(csdev);
 	if (coresight_is_claimed_self_hosted(csdev))
 		return 0;
-	/* There was a race setting the tags, clean up and fail */
-	coresight_clear_claim_tags(csdev);
+	/* There was a race setting the tag, clean up and fail */
+	coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	return -EBUSY;
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
@@ -201,7 +212,7 @@ int coresight_claim_device(struct coresight_device *csdev)
 EXPORT_SYMBOL_GPL(coresight_claim_device);
 
 /*
- * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
+ * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
  * Called with CS_UNLOCKed for the component.
  */
 void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
@@ -211,7 +222,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		return;
 
 	if (coresight_is_claimed_self_hosted(csdev))
-		coresight_clear_claim_tags(csdev);
+		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
 		 * The external agent may have not honoured our claim
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d79a242b271d..00134a80d358 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
 
 extern int coresight_claim_device(struct coresight_device *csdev);
 extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
-
+void coresight_clear_self_claim_tag(struct csdev_access *csa);
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
 extern void coresight_disclaim_device(struct coresight_device *csdev);
 extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
 extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:11 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:11 +0000
Subject: [PATCH v3 2/7] coresight: Only check bottom two claim bits
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-2-d3145c153820@linaro.org>

The use of the whole register and == could break the claim mechanism if
any of the other bits are used in the future. The referenced doc "PSCI -
ARM DEN 0022D" also says to only read and clear the bottom two bits.

Use FIELD_GET() to extract only the relevant part.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 3 ++-
 drivers/hwtracing/coresight/coresight-priv.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 8471aefeac76..26d149a4c579 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -131,7 +131,8 @@ coresight_find_out_connection(struct coresight_device *csdev,
 
 static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
 {
-	return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
+	return FIELD_GET(CORESIGHT_CLAIM_MASK,
+			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
 static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 82644aff8d2b..38bb4e8b50ef 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -35,6 +35,7 @@ extern const struct device_type coresight_dev_type[];
  * Coresight device CLAIM protocol.
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
+#define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
 #define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
 
 #define TIMEOUT_US		100

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:13 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:13 +0000
Subject: [PATCH v3 4/7] coresight: etm3x: Convert raw base pointer to
 struct coresight access
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-4-d3145c153820@linaro.org>

This is so that etm3x can use the new claim tag functions which take a
csa pointer in a later commit.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm.h        |  6 ++---
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 27 +++++++++++-----------
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +++----
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index 171f1384f7c0..1d753cca2943 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -229,7 +229,7 @@ struct etm_config {
  * @config:	structure holding configuration parameters.
  */
 struct etm_drvdata {
-	void __iomem			*base;
+	struct csdev_access		csa;
 	struct clk			*atclk;
 	struct coresight_device		*csdev;
 	spinlock_t			spinlock;
@@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		writel_relaxed(val, drvdata->base + off);
+		writel_relaxed(val, drvdata->csa.base + off);
 	}
 }
 
@@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		val = readl_relaxed(drvdata->base + off);
+		val = readl_relaxed(drvdata->csa.base + off);
 	}
 
 	return val;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index 8927bfaf3af2..cfd463ac715c 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
 {
 	u32 etmpdcr;
 
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr |= ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 	/* Ensure pwrup completes before subsequent cp14 accesses */
 	mb();
 	isb();
@@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
 	/* Ensure pending cp14 accesses complete before clearing pwrup */
 	mb();
 	isb();
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr &= ~ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 }
 
 /**
@@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	rc = coresight_claim_device_unlocked(csdev);
 	if (rc)
@@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	etm_clr_prog(drvdata);
 
 done:
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
 		drvdata->cpu, rc);
@@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	etm_set_prog(drvdata);
 
 	/* Read back sequencer and counters for post trace analysis */
@@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev,
 		"cpu: %d disable smp call done\n", drvdata->cpu);
@@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* Setting the prog bit disables tracing immediately */
 	etm_set_prog(drvdata);
@@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	/*
 	 * perf will release trace ids when _free_aux()
@@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
 	/* Make sure all registers are accessible */
 	etm_os_unlock(drvdata);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* First dummy read */
 	(void)etm_readl(drvdata, ETMPDSR);
@@ -766,7 +766,7 @@ static void etm_init_arch_data(void *info)
 
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 }
 
 static int __init etm_hp_setup(void)
@@ -827,8 +827,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	drvdata->base = base;
-	desc.access = CSDEV_ACCESS_IOMEM(base);
+	desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
 
 	spin_lock_init(&drvdata->spinlock);
 
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
index b9006451f515..762109307b86 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
@@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
 
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	val = etm_readl(drvdata, ETMSR);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);
 
@@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:14 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:14 +0000
Subject: [PATCH v3 5/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-5-d3145c153820@linaro.org>

This can be left behind from a crashed kernel after a kexec so clear it
when probing each device. Clearing the self hosted bit even when claimed
externally is harmless, so do it unconditionally.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 1 +
 drivers/hwtracing/coresight/coresight-cti-core.c   | 2 ++
 drivers/hwtracing/coresight/coresight-etb10.c      | 2 ++
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 1 +
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 ++
 drivers/hwtracing/coresight/coresight-funnel.c     | 1 +
 drivers/hwtracing/coresight/coresight-replicator.c | 1 +
 drivers/hwtracing/coresight/coresight-tmc-core.c   | 1 +
 8 files changed, 11 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index fa170c966bc3..deaacfd875af 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
 	catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
 	catu_desc.ops = &catu_ops;
 
+	coresight_clear_self_claim_tag(&catu_desc.access);
 	drvdata->csdev = coresight_register(&catu_desc);
 	if (IS_ERR(drvdata->csdev))
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 80f6265e3740..8fb30dd73fd2 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	cti_desc.ops = &cti_ops;
 	cti_desc.groups = drvdata->ctidev.con_groups;
 	cti_desc.dev = dev;
+
+	coresight_clear_self_claim_tag(&cti_desc.access);
 	drvdata->csdev = coresight_register(&cti_desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 7948597d483d..2bfcb669aa84 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.pdata = pdata;
 	desc.dev = dev;
 	desc.groups = coresight_etb_groups;
+
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev))
 		return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index cfd463ac715c..1c6204e14422 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -764,6 +764,7 @@ static void etm_init_arch_data(void *info)
 	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
+	coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
 	CS_LOCK(drvdata->csa.base);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e5972f16abff..52c9aa56e8b9 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1372,6 +1372,8 @@ static void etm4_init_arch_data(void *info)
 	drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
 	/* NUMCNTR, bits[30:28] number of counters available for tracing */
 	drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
+
+	coresight_clear_self_claim_tag_unlocked(csa);
 	etm4_cs_lock(drvdata, csa);
 	cpu_detect_trace_filtering(drvdata);
 }
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 0541712b2bcb..7249cc356ccb 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
 		drvdata->base = base;
 		desc.groups = coresight_funnel_groups;
 		desc.access = CSDEV_ACCESS_IOMEM(base);
+		coresight_clear_self_claim_tag(&desc.access);
 	}
 
 	dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index ee7ee79f6cf7..b2acd4535c74 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -284,6 +284,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
 	desc.pdata = dev->platform_data;
 	desc.dev = dev;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index a7814e8e657b..a09579eff3fd 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -869,6 +869,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
 	dev->platform_data = pdata;
 	desc.pdata = pdata;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:15 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:15 +0000
Subject: [PATCH v3 6/7] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-6-d3145c153820@linaro.org>

These are all static and in one compilation unit so the inline has no
effect on the binary. Except if FTRACE is enabled, then some functions
which were already not inlined now get the nops added which allows them
to be traced.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 11 +++++----
 drivers/hwtracing/coresight/coresight-core.c       | 14 ++++++------
 drivers/hwtracing/coresight/coresight-etb10.c      |  2 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c |  8 +++----
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 ++--
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++++++++++-----------
 drivers/hwtracing/coresight/coresight-replicator.c |  2 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 ++---
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  8 +++----
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++++++-------
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 +++++++--------
 12 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index deaacfd875af..6f411db24a54 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -113,9 +113,8 @@ typedef u64 cate_t;
  * containing the data page pointer for @offset. If @daddrp is not NULL,
  * @daddrp points the DMA address of the beginning of the table.
  */
-static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
-				     unsigned long offset,
-				     dma_addr_t *daddrp)
+static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
+			      dma_addr_t *daddrp)
 {
 	unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
 	unsigned int table_nr, pg_idx, pg_offset;
@@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
 }
 
 #else
-static inline void catu_dump_table(struct tmc_sg_table *catu_table)
+static void catu_dump_table(struct tmc_sg_table *catu_table)
 {
 }
 #endif
 
-static inline cate_t catu_make_entry(dma_addr_t addr)
+static cate_t catu_make_entry(dma_addr_t addr)
 {
 	return addr ? CATU_VALID_ENTRY(addr) : 0;
 }
@@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
 };
 
 
-static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
+static int catu_wait_for_ready(struct catu_drvdata *drvdata)
 {
 	struct csdev_access *csa = &drvdata->csdev->access;
 
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 2b5a7cceb719..074dbf8a6876 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -129,13 +129,13 @@ coresight_find_out_connection(struct coresight_device *csdev,
 	return ERR_PTR(-ENODEV);
 }
 
-static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
+static u32 coresight_read_claim_tags(struct coresight_device *csdev)
 {
 	return FIELD_GET(CORESIGHT_CLAIM_MASK,
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
+static void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
@@ -604,7 +604,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
  * Return true in successful case and power up the device.
  * Return false when failed to get reference of module.
  */
-static inline bool coresight_get_ref(struct coresight_device *csdev)
+static bool coresight_get_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -623,7 +623,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
  *
  * @csdev: The coresight device to decrement a reference from.
  */
-static inline void coresight_put_ref(struct coresight_device *csdev)
+static void coresight_put_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -846,7 +846,7 @@ void coresight_release_path(struct coresight_path *path)
 }
 
 /* return true if the device is a suitable type for a default sink */
-static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
+static bool coresight_is_def_sink_type(struct coresight_device *csdev)
 {
 	/* sink & correct subtype */
 	if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
@@ -1410,8 +1410,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
  *
  * Returns the index of the entry, when found. Otherwise, -ENOENT.
  */
-static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
-					      struct fwnode_handle *fwnode)
+static int coresight_search_device_idx(struct coresight_dev_list *dict,
+				       struct fwnode_handle *fwnode)
 {
 	int i;
 
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 2bfcb669aa84..d5efb085b30d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -95,7 +95,7 @@ struct etb_drvdata {
 static int etb_set_buffer(struct coresight_device *csdev,
 			  struct perf_output_handle *handle);
 
-static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
+static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
 {
 	return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
 }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 52c9aa56e8b9..2ca35ef35f77 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
  *		TRCIDR4.NUMPC > 0b0000 .
  *		TRCSSCSR<n>.PC == 0b1
  */
-static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
+static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
 {
 	return (n < drvdata->nr_ss_cmp) &&
 	       drvdata->nr_pe &&
@@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
 	isb();
 }
 
-static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
+static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
 				      struct csdev_access *csa)
 {
 	WARN_ON(drvdata->cpu != smp_processor_id());
@@ -1070,7 +1070,7 @@ static const struct coresight_ops etm4_cs_ops = {
 	.source_ops	= &etm4_source_ops,
 };
 
-static inline bool cpu_supports_sysreg_trace(void)
+static bool cpu_supports_sysreg_trace(void)
 {
 	u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
 
@@ -1378,7 +1378,7 @@ static void etm4_init_arch_data(void *info)
 	cpu_detect_trace_filtering(drvdata);
 }
 
-static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
+static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
 {
 	return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
 }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index fdd0956fecb3..49d5fb87a74b 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
 	return reg.data;
 }
 
-static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
+static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
 {
 	struct dev_ext_attribute *eattr;
 
@@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
 	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
 }
 
-static inline bool
+static bool
 etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
 {
 	switch (offset) {
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index 8192ba3279f0..0db64c5f4995 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
 EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
 
 #ifdef CONFIG_OF
-static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
+static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
 {
 	return of_property_read_bool(ep, "slave-mode");
 }
@@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
 	return parent;
 }
 
-static inline struct device_node *
+static struct device_node *
 of_coresight_get_output_ports_node(const struct device_node *node)
 {
 	return of_get_child_by_name(node, "out-ports");
@@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
 	return 0;
 }
 #else
-static inline int
+static int
 of_get_coresight_platform_data(struct device *dev,
 			       struct coresight_platform_data *pdata)
 {
 	return -ENOENT;
 }
 
-static inline int of_coresight_get_cpu(struct device *dev)
+static int of_coresight_get_cpu(struct device *dev)
 {
 	return -ENODEV;
 }
@@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
 #define ACPI_CORESIGHT_LINK_SLAVE	0
 #define ACPI_CORESIGHT_LINK_MASTER	1
 
-static inline bool is_acpi_guid(const union acpi_object *obj)
+static bool is_acpi_guid(const union acpi_object *obj)
 {
 	return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
 }
@@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
  * acpi_guid_matches	- Checks if the given object is a GUID object and
  * that it matches the supplied the GUID.
  */
-static inline bool acpi_guid_matches(const union acpi_object *obj,
+static bool acpi_guid_matches(const union acpi_object *obj,
 				   const guid_t *guid)
 {
 	return is_acpi_guid(obj) &&
 	       guid_equal((guid_t *)obj->buffer.pointer, guid);
 }
 
-static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
+static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
 {
 	return acpi_guid_matches(obj, &acpi_graph_uuid);
 }
 
-static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
+static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
 {
 	return acpi_guid_matches(obj, &coresight_graph_uuid);
 }
 
-static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
+static bool is_acpi_coresight_graph(const union acpi_object *obj)
 {
 	const union acpi_object *graphid, *guid, *links;
 
@@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
  *	}, // End of ACPI Graph Property
  *  })
  */
-static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
+static bool acpi_validate_dsd_graph(const union acpi_object *graph)
 {
 	int i, n;
 	const union acpi_object *rev, *nr_graphs;
@@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
 	return NULL;
 }
 
-static inline bool
+static bool
 acpi_validate_coresight_graph(const union acpi_object *cs_graph)
 {
 	int nlinks;
@@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
 
 #else
 
-static inline int
+static int
 acpi_get_coresight_platform_data(struct device *dev,
 				 struct coresight_platform_data *pdata)
 {
 	return -ENOENT;
 }
 
-static inline int acpi_coresight_get_cpu(struct device *dev)
+static int acpi_coresight_get_cpu(struct device *dev)
 {
 	return -ENODEV;
 }
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index b2acd4535c74..52beb2fc4094 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
 /*
  * replicator_reset : Reset the replicator configuration to sane values.
  */
-static inline void replicator_reset(struct replicator_drvdata *drvdata)
+static void replicator_reset(struct replicator_drvdata *drvdata)
 {
 	if (drvdata->base)
 		dynamic_replicator_reset(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 26f9339f38b9..8c0741583a2c 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -301,7 +301,7 @@ static const struct coresight_ops stm_cs_ops = {
 	.source_ops	= &stm_source_ops,
 };
 
-static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
+static bool stm_addr_unaligned(const void *addr, u8 write_bytes)
 {
 	return ((unsigned long)addr & (write_bytes - 1));
 }
@@ -685,7 +685,7 @@ static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)
 	return of_address_to_resource(np, index, res);
 }
 #else
-static inline int of_stm_get_stimulus_area(struct device *dev,
+static int of_stm_get_stimulus_area(struct device *dev,
 					   struct resource *res)
 {
 	return -ENOENT;
@@ -729,7 +729,7 @@ static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)
 	return rc;
 }
 #else
-static inline int acpi_stm_get_stimulus_area(struct device *dev,
+static int acpi_stm_get_stimulus_area(struct device *dev,
 					     struct resource *res)
 {
 	return -ENOENT;
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
index 213b4159b062..2b40e556be87 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -10,7 +10,7 @@
 #include "coresight-syscfg-configfs.h"
 
 /* create a default ci_type. */
-static inline struct config_item_type *cscfg_create_ci_type(void)
+static struct config_item_type *cscfg_create_ci_type(void)
 {
 	struct config_item_type *ci_type;
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index a09579eff3fd..6f6d51c13454 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -287,8 +287,8 @@ static int tmc_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
-					  loff_t pos, size_t len, char **bufpp)
+static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len,
+				   char **bufpp)
 {
 	switch (drvdata->config_type) {
 	case TMC_CONFIG_TYPE_ETB:
@@ -591,7 +591,7 @@ static const struct attribute_group *coresight_etr_groups[] = {
 	NULL,
 };
 
-static inline bool tmc_etr_can_use_sg(struct device *dev)
+static bool tmc_etr_can_use_sg(struct device *dev)
 {
 	int ret;
 	u8 val_u8;
@@ -621,7 +621,7 @@ static inline bool tmc_etr_can_use_sg(struct device *dev)
 	return false;
 }
 
-static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
+static bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
 {
 	u32 auth = readl_relaxed(drvdata->base + TMC_AUTHSTATUS);
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 76a8cb29b68a..3f31ad2ae65d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -125,7 +125,7 @@ struct etr_sg_table {
  * If we spill over to a new page for mapping 1 entry, we could as
  * well replace the link entry of the previous page with the last entry.
  */
-static inline unsigned long __attribute_const__
+static unsigned long __attribute_const__
 tmc_etr_sg_table_entries(int nr_pages)
 {
 	unsigned long nr_sgpages = nr_pages * ETR_SG_PAGES_PER_SYSPAGE;
@@ -239,13 +239,13 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
 	return -ENOMEM;
 }
 
-static inline long
+static long
 tmc_sg_get_data_page_offset(struct tmc_sg_table *sg_table, dma_addr_t addr)
 {
 	return tmc_pages_get_offset(&sg_table->data_pages, addr);
 }
 
-static inline void tmc_free_table_pages(struct tmc_sg_table *sg_table)
+static void tmc_free_table_pages(struct tmc_sg_table *sg_table)
 {
 	if (sg_table->table_vaddr)
 		vunmap(sg_table->table_vaddr);
@@ -481,7 +481,7 @@ static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table)
 	dev_dbg(sg_table->dev, "******* End of Table *****\n");
 }
 #else
-static inline void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
+static void tmc_etr_sg_table_dump(struct etr_sg_table *etr_table) {}
 #endif
 
 /*
@@ -886,10 +886,8 @@ void tmc_etr_remove_catu_ops(void)
 }
 EXPORT_SYMBOL_GPL(tmc_etr_remove_catu_ops);
 
-static inline int tmc_etr_mode_alloc_buf(int mode,
-					 struct tmc_drvdata *drvdata,
-					 struct etr_buf *etr_buf, int node,
-					 void **pages)
+static int tmc_etr_mode_alloc_buf(int mode, struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
+				  int node, void **pages)
 {
 	int rc = -EINVAL;
 
@@ -1009,7 +1007,7 @@ static ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf,
 	return etr_buf->ops->get_data(etr_buf, (u64)offset, len, bufpp);
 }
 
-static inline s64
+static s64
 tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
 {
 	ssize_t len;
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index fff67aac8418..8267dd1a2130 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -160,22 +160,22 @@ static void trbe_check_errata(struct trbe_cpudata *cpudata)
 	}
 }
 
-static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
+static bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
 {
 	return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata);
 }
 
-static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
+static bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE);
 }
 
-static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
+static bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE);
 }
 
-static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
+static bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
 {
 	/*
 	 * Errata affected TRBE implementation will need TSB CSYNC and
@@ -185,7 +185,7 @@ static inline bool trbe_needs_drain_after_disable(struct trbe_cpudata *cpudata)
 	return trbe_has_erratum(cpudata, TRBE_NEEDS_DRAIN_AFTER_DISABLE);
 }
 
-static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
+static bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudata)
 {
 	/*
 	 * Errata affected TRBE implementation will need an additional
@@ -196,7 +196,7 @@ static inline bool trbe_needs_ctxt_sync_after_enable(struct trbe_cpudata *cpudat
 	return trbe_has_erratum(cpudata, TRBE_NEEDS_CTXT_SYNC_AFTER_ENABLE);
 }
 
-static inline bool trbe_is_broken(struct trbe_cpudata *cpudata)
+static bool trbe_is_broken(struct trbe_cpudata *cpudata)
 {
 	return trbe_has_erratum(cpudata, TRBE_IS_BROKEN);
 }
@@ -208,13 +208,13 @@ static int trbe_alloc_node(struct perf_event *event)
 	return cpu_to_node(event->cpu);
 }
 
-static inline void trbe_drain_buffer(void)
+static void trbe_drain_buffer(void)
 {
 	tsb_csync();
 	dsb(nsh);
 }
 
-static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
+static void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
 {
 	/*
 	 * Enable the TRBE without clearing LIMITPTR which
@@ -231,7 +231,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr)
 		isb();
 }
 
-static inline void set_trbe_disabled(struct trbe_cpudata *cpudata)
+static void set_trbe_disabled(struct trbe_cpudata *cpudata)
 {
 	u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
 

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:12 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:12 +0000
Subject: [PATCH v3 3/7] coresight: Add claim tag warnings and debug
 messages
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-3-d3145c153820@linaro.org>

Add a dev_dbg() message so that external debugger conflicts are more
visible. There are multiple reasons for -EBUSY so a message for this
particular one could be helpful. Add errors for and enumerate all the
other cases that are impossible.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 51 +++++++++++++++++-----------
 drivers/hwtracing/coresight/coresight-priv.h |  5 ++-
 2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 26d149a4c579..2b5a7cceb719 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -135,16 +135,6 @@ static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
-}
-
-static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags(csdev) != 0;
-}
-
 static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
@@ -182,18 +172,41 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
  */
 int coresight_claim_device_unlocked(struct coresight_device *csdev)
 {
+	int tag;
+	struct csdev_access *csa;
+
 	if (WARN_ON(!csdev))
 		return -EINVAL;
 
-	if (coresight_is_claimed_any(csdev))
+	csa = &csdev->access;
+	tag = coresight_read_claim_tags(csdev);
+
+	switch (tag) {
+	case CORESIGHT_CLAIM_FREE:
+		coresight_set_self_claim_tag(csdev);
+		if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
+			return 0;
+
+		/* There was a race setting the tag, clean up and fail */
+		coresight_clear_self_claim_tag_unlocked(csa);
+		dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
 		return -EBUSY;
 
-	coresight_set_self_claim_tag(csdev);
-	if (coresight_is_claimed_self_hosted(csdev))
-		return 0;
-	/* There was a race setting the tag, clean up and fail */
-	coresight_clear_self_claim_tag_unlocked(&csdev->access);
-	return -EBUSY;
+	case CORESIGHT_CLAIM_EXTERNAL:
+		/* External debug is an expected state, so log and report BUSY */
+		dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
+		return -EBUSY;
+
+	default:
+	case CORESIGHT_CLAIM_SELF_HOSTED:
+	case CORESIGHT_CLAIM_INVALID:
+		/*
+		 * Warn here because we clear a lingering self hosted tag
+		 * on probe, so other tag combinations are impossible.
+		 */
+		dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
+		return -EBUSY;
+	}
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
 
@@ -222,7 +235,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 	if (WARN_ON(!csdev))
 		return;
 
-	if (coresight_is_claimed_self_hosted(csdev))
+	if (coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
 		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
@@ -230,7 +243,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		 * and has manipulated it. Or something else has seriously
 		 * gone wrong in our driver.
 		 */
-		WARN_ON_ONCE(1);
+		dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
 }
 EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
 
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 38bb4e8b50ef..6e8cf55aee0a 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -36,7 +36,10 @@ extern const struct device_type coresight_dev_type[];
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
 #define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
-#define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
+#define CORESIGHT_CLAIM_FREE		0
+#define CORESIGHT_CLAIM_EXTERNAL	1
+#define CORESIGHT_CLAIM_SELF_HOSTED	2
+#define CORESIGHT_CLAIM_INVALID		3
 
 #define TIMEOUT_US		100
 #define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)

-- 
2.34.1



From james.clark at linaro.org  Thu Mar 20 07:34:16 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:16 +0000
Subject: [PATCH v3 7/7] coresight: Remove extern from function declarations
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <20250320-james-coresight-claim-tags-v3-7-d3145c153820@linaro.org>

Function declarations are extern by default so remove the extra noise
and inconsistency.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-priv.h | 14 +++++------
 include/linux/coresight.h                    | 35 ++++++++++++++--------------
 2 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 6e8cf55aee0a..ce91e0fbb497 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -60,10 +60,8 @@ struct cs_off_attribute {
 	u32 off;
 };
 
-extern ssize_t coresight_simple_show32(struct device *_dev,
-				     struct device_attribute *attr, char *buf);
-extern ssize_t coresight_simple_show_pair(struct device *_dev,
-				     struct device_attribute *attr, char *buf);
+ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
+ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf);
 
 #define coresight_simple_reg32(name, offset)				\
 	(&((struct cs_off_attribute[]) {				\
@@ -160,8 +158,8 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
 				   enum cs_mode mode);
 
 #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
-extern int etm_readl_cp14(u32 off, unsigned int *val);
-extern int etm_writel_cp14(u32 off, u32 val);
+int etm_readl_cp14(u32 off, unsigned int *val);
+int etm_writel_cp14(u32 off, u32 val);
 #else
 static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
 static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
@@ -172,8 +170,8 @@ struct cti_assoc_op {
 	void (*remove)(struct coresight_device *csdev);
 };
 
-extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
-extern void coresight_remove_cti_ops(void);
+void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
+void coresight_remove_cti_ops(void);
 
 /*
  * Macros and inline functions to handle CoreSight UCI data and driver
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 00134a80d358..8cb07c132b01 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -671,28 +671,27 @@ static inline void coresight_set_mode(struct coresight_device *csdev,
 	local_set(&csdev->mode, new_mode);
 }
 
-extern struct coresight_device *
-coresight_register(struct coresight_desc *desc);
-extern void coresight_unregister(struct coresight_device *csdev);
-extern int coresight_enable_sysfs(struct coresight_device *csdev);
-extern void coresight_disable_sysfs(struct coresight_device *csdev);
-extern int coresight_timeout(struct csdev_access *csa, u32 offset,
-			     int position, int value);
+struct coresight_device *coresight_register(struct coresight_desc *desc);
+void coresight_unregister(struct coresight_device *csdev);
+int coresight_enable_sysfs(struct coresight_device *csdev);
+void coresight_disable_sysfs(struct coresight_device *csdev);
+int coresight_timeout(struct csdev_access *csa, u32 offset, int position, int value);
 typedef void (*coresight_timeout_cb_t) (struct csdev_access *, u32, int, int);
-extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
-					int position, int value,
-					coresight_timeout_cb_t cb);
+int coresight_timeout_action(struct csdev_access *csa, u32 offset, int position, int value,
+			     coresight_timeout_cb_t cb);
+int coresight_claim_device(struct coresight_device *csdev);
+int coresight_claim_device_unlocked(struct coresight_device *csdev);
 
-extern int coresight_claim_device(struct coresight_device *csdev);
-extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
+int coresight_claim_device(struct coresight_device *csdev);
+int coresight_claim_device_unlocked(struct coresight_device *csdev);
 void coresight_clear_self_claim_tag(struct csdev_access *csa);
 void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
-extern void coresight_disclaim_device(struct coresight_device *csdev);
-extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
-extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
+void coresight_disclaim_device(struct coresight_device *csdev);
+void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
+char *coresight_alloc_device_name(struct coresight_dev_list *devs,
 					 struct device *dev);
 
-extern bool coresight_loses_context_with_cpu(struct device *dev);
+bool coresight_loses_context_with_cpu(struct device *dev);
 
 u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset);
 u32 coresight_read32(struct coresight_device *csdev, u32 offset);
@@ -705,8 +704,8 @@ void coresight_relaxed_write64(struct coresight_device *csdev,
 			       u64 val, u32 offset);
 void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset);
 
-extern int coresight_get_cpu(struct device *dev);
-extern int coresight_get_static_trace_id(struct device *dev, u32 *id);
+int coresight_get_cpu(struct device *dev);
+int coresight_get_static_trace_id(struct device *dev, u32 *id);
 
 struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
 struct coresight_connection *

-- 
2.34.1



From corbet at lwn.net  Thu Mar 20 07:45:03 2025
From: corbet at lwn.net (Jonathan Corbet)
Date: Thu, 20 Mar 2025 08:45:03 -0600
Subject: [PATCH v5 16/16] Documentation: add documentation for KHO
In-Reply-To: <20250320015551.2157511-17-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-17-changyuanl@google.com>
Message-ID: <87wmcj69sg.fsf@trenco.lwn.net>

Changyuan Lyu <changyuanl at google.com> writes:

> From: Alexander Graf <graf at amazon.com>
>
> With KHO in place, let's add documentation that describes what it is and
> how to use it.
>
> Signed-off-by: Alexander Graf <graf at amazon.com>
> Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |  25 ++++
>  Documentation/kho/concepts.rst                |  70 +++++++++++
>  Documentation/kho/fdt.rst                     |  62 +++++++++
>  Documentation/kho/index.rst                   |  14 +++
>  Documentation/kho/usage.rst                   | 118 ++++++++++++++++++
>  Documentation/subsystem-apis.rst              |   1 +
>  MAINTAINERS                                   |   1 +
>  7 files changed, 291 insertions(+)
>  create mode 100644 Documentation/kho/concepts.rst
>  create mode 100644 Documentation/kho/fdt.rst
>  create mode 100644 Documentation/kho/index.rst
>  create mode 100644 Documentation/kho/usage.rst

I will ask again: please let's not create another top-level docs
directory for this...?  It looks like it belongs in the admin guide to
me.

Thanks,

jon


From Markus.Elfring at web.de  Thu Mar 20 07:48:16 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Thu, 20 Mar 2025 15:48:16 +0100
Subject: [PATCH] pinctrl: at91: Add error handling for
 pinctrl_utils_add_map_mux()
In-Reply-To: <20250318030717.781-1-vulab@iscas.ac.cn>
References: <20250318030717.781-1-vulab@iscas.ac.cn>
Message-ID: <79b776fe-7fcf-4cf8-9d3f-bd5f4e66344e@web.de>

> In atmel_pctl_dt_subnode_to_map(), the return value of
> pinctrl_utils_add_map_mux() needs to be checked, for the function
> will fail to associate group when the group map is full. ?

Please improve such a change description another bit.


> propagate the error code to caller function when the function fails.

                                                                call failed?

How do you think about to add any tags (like ?Fixes? and ?Cc?) accordingly?
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc7#n145

Regards,
Markus


From james.clark at linaro.org  Thu Mar 20 07:34:09 2025
From: james.clark at linaro.org (James Clark)
Date: Thu, 20 Mar 2025 14:34:09 +0000
Subject: [PATCH v3 0/7] coresight: Clear self hosted claim tag on probe
Message-ID: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>

I've gotten stuck a few times with unusable Coresight after a warm boot
due to lingering claim tags, especially when testing the Coresight
panic patchsets.

This change does some tidy ups, adds some debug messages and clears the
self hosted claim tag on probe. The last two commits are unrelated
tidyups but they touch some of the same functions so to avoid extra
conflicts I'm including them here.

This gets as far as fixing the claim tag issue, but there is some other
state not being cleared on probe that results in the following error.
This can be fixed up as a later change:

  coresight tmc_etf0: timeout while waiting for TMC to be Ready
  coresight tmc_etf0: Failed to enable : TMC is not ready

Changes in v3:
- Collapse rename and locked/unlocked addition commits of
  coresight_clear_self_claim_tag() so we don't change the name twice.
- Make coresight_clear_self_claim_tag() a bit more generic by only
  doing UNLOCK for MMIO devices (although there is no use of this right
  now)
- Link to v2: https://lore.kernel.org/r/20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e at linaro.org

Changes in v2:
 * Revert most of the interface changes, just call
   coresight_clear_self_claim_tag() directly. This is possible because
   we're not doing the read first, so it has fewer knock on effects.
 * Split out the change to add struct cs_access to etm3x
 * Add another warning for racing with external debugger

--
2.34.1

---
James Clark (7):
      coresight: Convert tag clear function to take a struct cs_access
      coresight: Only check bottom two claim bits
      coresight: Add claim tag warnings and debug messages
      coresight: etm3x: Convert raw base pointer to struct coresight access
      coresight: Clear self hosted claim tag on probe
      coresight: Remove inlines from static function definitions
      coresight: Remove extern from function declarations

 drivers/hwtracing/coresight/coresight-catu.c       | 12 +--
 drivers/hwtracing/coresight/coresight-core.c       | 87 ++++++++++++++--------
 drivers/hwtracing/coresight/coresight-cti-core.c   |  2 +
 drivers/hwtracing/coresight/coresight-etb10.c      |  4 +-
 drivers/hwtracing/coresight/coresight-etm.h        |  6 +-
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 28 +++----
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++-
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 +-
 drivers/hwtracing/coresight/coresight-funnel.c     |  1 +
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++----
 drivers/hwtracing/coresight/coresight-priv.h       | 20 ++---
 drivers/hwtracing/coresight/coresight-replicator.c |  3 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 +-
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  9 ++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++--
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 ++---
 include/linux/coresight.h                          | 40 +++++-----
 19 files changed, 168 insertions(+), 134 deletions(-)
---
base-commit: 5442d22da7dbff3ba8c6720fc6f23ea4934d402d
change-id: 20250317-james-coresight-claim-tags-ae1461f1f5e0

Best regards,
-- 
James Clark <james.clark at linaro.org>



From arnd at arndb.de  Thu Mar 20 07:49:08 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 20 Mar 2025 15:49:08 +0100
Subject: [PATCH v2 04/11] soc: airoha: add support for configuring SCU SSR Serdes
 port
In-Reply-To: <20250320130054.4804-5-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
 <20250320130054.4804-5-ansuelsmth@gmail.com>
Message-ID: <d6e27266-dc5b-4ef8-b708-21cedd06621e@app.fastmail.com>

On Thu, Mar 20, 2025, at 14:00, Christian Marangi wrote:
> Add support for configuring SCU SSR Serdes port. Airoha AN7581 SoC can
> configure the different Serdes port by toggling bits in the SCU register
> space.
>
> Port Serdes mode are mutually exclusive, force example the USB2 Serdes port
> can either used for USB 3.0 or PCIe 2 port. Enabling USB 3.0 makes the
> PCIe 2 to not work.
>
> The current supported Serdes port are:
> - WiFi 1 and defaults to PCIe0 1 line mode
> - Wifi 2 and defaults to PCIe1 1 line mode
> - USB 1 and defaults to USB 3.0 mode
> - USB 2 and defaults to USB 3.0 mode
>
> WiFi 1, WiFi 2 and USB 1 also support a particular Ethernet mode that
> can toggle between USXGMII or HSGMII mode (USB 1 only to HSGMII)
> Such mode doesn't configure bits as specific Ethernet PCS driver will
> take care of configuring the Serdes mode based on what is required.
>
> This driver is to correctly setup these bits.
> Single driver can't independently set the Serdes port mode as that
> would cause a conflict if someone declare, for example, in DT
> (and enable) PCIe 2 port and USB2 3.0 port.
>
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>

I think serdes drivers are usually implement in the drivers/phy
layer, and I see there is already a drivers/phy/phy-airoha-pcie.c,
which may or may not overlap with this one (I have not looked at
the details).

Have you tried to use the phy subsystem interface here instead
of creating a custom in-kernel interface?

      Arnd


From ansuelsmth at gmail.com  Thu Mar 20 07:59:06 2025
From: ansuelsmth at gmail.com (Christian Marangi)
Date: Thu, 20 Mar 2025 15:59:06 +0100
Subject: [PATCH v2 04/11] soc: airoha: add support for configuring SCU
 SSR Serdes port
In-Reply-To: <d6e27266-dc5b-4ef8-b708-21cedd06621e@app.fastmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
 <20250320130054.4804-5-ansuelsmth@gmail.com>
 <d6e27266-dc5b-4ef8-b708-21cedd06621e@app.fastmail.com>
Message-ID: <67dc2d3e.050a0220.2e39a4.c3f0@mx.google.com>

On Thu, Mar 20, 2025 at 03:49:08PM +0100, Arnd Bergmann wrote:
> On Thu, Mar 20, 2025, at 14:00, Christian Marangi wrote:
> > Add support for configuring SCU SSR Serdes port. Airoha AN7581 SoC can
> > configure the different Serdes port by toggling bits in the SCU register
> > space.
> >
> > Port Serdes mode are mutually exclusive, force example the USB2 Serdes port
> > can either used for USB 3.0 or PCIe 2 port. Enabling USB 3.0 makes the
> > PCIe 2 to not work.
> >
> > The current supported Serdes port are:
> > - WiFi 1 and defaults to PCIe0 1 line mode
> > - Wifi 2 and defaults to PCIe1 1 line mode
> > - USB 1 and defaults to USB 3.0 mode
> > - USB 2 and defaults to USB 3.0 mode
> >
> > WiFi 1, WiFi 2 and USB 1 also support a particular Ethernet mode that
> > can toggle between USXGMII or HSGMII mode (USB 1 only to HSGMII)
> > Such mode doesn't configure bits as specific Ethernet PCS driver will
> > take care of configuring the Serdes mode based on what is required.
> >
> > This driver is to correctly setup these bits.
> > Single driver can't independently set the Serdes port mode as that
> > would cause a conflict if someone declare, for example, in DT
> > (and enable) PCIe 2 port and USB2 3.0 port.
> >
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> 
> I think serdes drivers are usually implement in the drivers/phy
> layer, and I see there is already a drivers/phy/phy-airoha-pcie.c,
> which may or may not overlap with this one (I have not looked at
> the details).
> 
> Have you tried to use the phy subsystem interface here instead
> of creating a custom in-kernel interface?
>

These really set 1-2 bit and I think PHY can't describe PCIe in x2 mode
or in x1. Also I think PHY is used for more advanced stuff and usually
have dedicated register/maps. This is really to configure 1-2 bit and
provide the mode, nothing else... no enable, no power up.

Do you think a it's possible to implement a ""read-only"" PHY driver?

The PCIe x2 mode maybe can be modelled with
phy-cells = <2> and adding a extra entry to enforce x2 line mode?

But I feel it would be wrong to say that the SCU expose PHY as it won't
be true.

Honestly we should really consider starting to implement a generic
provider for these stuff... it's not the first time we have bit that
configure part of the entire system.

For example this is very common for QCOM with TCSR and also for Mediatek
with the TPHY. (but TPHY is at least more realistic as it can enable and
disable serdes port... here it's just 1 bit)

-- 
	Ansuel


From potin.lai.pt at gmail.com  Thu Mar 20 08:21:58 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:58 +0800
Subject: [PATCH v5 08/10] ARM: dts: aspeed: catalina: Enable multi-master
 on additional I2C buses
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-8-e161be6583a7@gmail.com>

Update the device tree to enable `multi-master` mode on I2C buses shared
between the host BMC and the NV module with HMC. This ensures proper bus
arbitration and coordination in multi-master environments, preventing
communication conflicts and improving reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 1e1bcc9ac2f0..abf15d322605 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -815,6 +815,7 @@ ssif-bmc at 10 {
 
 &i2c12 {
 	status = "okay";
+	multi-master;
 
 	// Module 1 FRU EEPROM
 	eeprom at 50 {
@@ -825,6 +826,7 @@ eeprom at 50 {
 
 &i2c13 {
 	status = "okay";
+	multi-master;
 
 	// Module 0 FRU EEPROM
 	eeprom at 50 {

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:59 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:59 +0800
Subject: [PATCH v5 09/10] ARM: dts: aspeed: catalina: Update CBC FRU EEPROM
 I2C bus and address
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-9-e161be6583a7@gmail.com>

Revise the I2C bus and address for the Cable Backplane Cartridge (CBC)
FRU EEPROM in the Catalina device tree.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index abf15d322605..653afacc7af4 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -822,6 +822,12 @@ eeprom at 50 {
 		compatible = "atmel,24c64";
 		reg = <0x50>;
 	};
+
+	// Secondary CBC FRU EEPROM
+	eeprom at 54 {
+		compatible = "atmel,24c02";
+		reg = <0x54>;
+	};
 };
 
 &i2c13 {
@@ -834,18 +840,12 @@ eeprom at 50 {
 		reg = <0x50>;
 	};
 
-	// Left CBC FRU EEPROM
+	// Primary CBC FRU EEPROM
 	eeprom at 54 {
 		compatible = "atmel,24c02";
 		reg = <0x54>;
 	};
 
-	// Right CBC FRU EEPROM
-	eeprom at 55 {
-		compatible = "atmel,24c02";
-		reg = <0x55>;
-	};
-
 	// HMC FRU EEPROM
 	eeprom at 57 {
 		compatible = "atmel,24c02";

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:22:00 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:22:00 +0800
Subject: [PATCH v5 10/10] ARM: dts: aspeed: catalina: Enable MCTP support
 for NIC management
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-10-e161be6583a7@gmail.com>

Add the `mctp-controller` property and MCTP nodes to enable support for
backend NIC management via PLDM over MCTP.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 653afacc7af4..6eb6c5889113 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -186,18 +186,23 @@ flash at 1 {
 
 &i2c0 {
 	status = "okay";
+	multi-master;
+	mctp at 10 {
+		compatible = "mctp-i2c-controller";
+		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+	};
 
 	i2c-mux at 71 {
 		compatible = "nxp,pca9546";
 		reg = <0x71>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		i2c-mux-idle-disconnect;
 
 		i2c0mux0ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+			mctp-controller;
 
 			// IOB0 NIC0 TEMP
 			temperature-sensor at 1f {
@@ -214,6 +219,7 @@ i2c0mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+			mctp-controller;
 
 			// IOB0 NIC1 TEMP
 			temperature-sensor at 1f {
@@ -305,12 +311,12 @@ i2c-mux at 75 {
 		reg = <0x75>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		i2c-mux-idle-disconnect;
 
 		i2c0mux3ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+			mctp-controller;
 
 			// IOB1 NIC0 TEMP
 			temperature-sensor at 1f {
@@ -327,6 +333,7 @@ i2c0mux3ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+			mctp-controller;
 
 			// IOB1 NIC1 TEMP
 			temperature-sensor at 1f {

-- 
2.31.1



From kajetan.puchalski at arm.com  Thu Mar 20 08:28:49 2025
From: kajetan.puchalski at arm.com (Kajetan Puchalski)
Date: Thu, 20 Mar 2025 15:28:49 +0000
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <Z9vyy7f5NOPyzUES@nchen-desktop>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
 <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>
 <Z9vyy7f5NOPyzUES@nchen-desktop>
Message-ID: <zsmeh4ukuspyetowryqi3blcquxlua5wzy5ibgy7lupryr5txx@74ic6drtremv>

On Thu, Mar 20, 2025 at 06:49:47PM +0800, Peter Chen wrote:

(...)

> > > +ARM/CIX SKY ARM ARCHITECTURE
> > > +M:   Peter Chen <peter.chen at cixtech.com>
> > > +M:   Fugang Duan <fugang.duan at cixtech.com>
> > > +R:   CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
> > > +L:   linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > > +S:   Maintained
> > > +F:   Documentation/devicetree/bindings/arm/cix.yaml
> > > +F:   arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> > > +F:   arch/arm64/boot/dts/cix/sky1.dtsi
> >
> > Instead:
> > arch/arm64/boot/dts/cix/
> >
> > or if you think there will be more different architectures coming from
> > cix, which you will not maintain, then useful would be a "sky" subdirectory.
> >
> Hi Krzysztof,
>
> Thanks for your comment, CIX is Arm SoC based silicon design
> company, we may have different SoC style for middle end in future.
> So, for that SoC series, it may not name sky.

I believe the idea is that the file should either say

+F:   arch/arm64/boot/dts/cix/

if the two of you intend to be maintainers for everything under cix/.
You don't need to list every specific file.

Otherwise it should say

+F:   arch/arm64/boot/dts/cix/sky/

with its own subdirectory if you only intend to be maintaining the sky family.

> --
>
> Best regards,
> Peter


From cheick.traore at foss.st.com  Thu Mar 20 08:25:40 2025
From: cheick.traore at foss.st.com (Cheick Traore)
Date: Thu, 20 Mar 2025 16:25:40 +0100
Subject: [PATCH] serial: stm32: do not deassert RS485 RTS GPIO prematurely
Message-ID: <20250320152540.709091-1-cheick.traore@foss.st.com>

If stm32_usart_start_tx is called with an empty xmit buffer, RTS GPIO
could be deasserted prematurely, as bytes in TX FIFO are still
transmitting.
So this patch remove rts disable when xmit buffer is empty.

Fixes: d7c76716169d ("serial: stm32: Use TC interrupt to deassert GPIO RTS in RS485 mode")
Signed-off-by: Cheick Traore <cheick.traore at foss.st.com>
---
 drivers/tty/serial/stm32-usart.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 4c97965ec43b..ad06b760cfca 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -965,10 +965,8 @@ static void stm32_usart_start_tx(struct uart_port *port)
 {
 	struct tty_port *tport = &port->state->port;
 
-	if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) {
-		stm32_usart_rs485_rts_disable(port);
+	if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char)
 		return;
-	}
 
 	stm32_usart_rs485_rts_enable(port);
 
-- 
2.34.1



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:09 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:09 +0100
Subject: [PATCH v8 0/5] drm/bridge: add devm_drm_bridge_alloc() with bridge
 refcount
Message-ID: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>

This series improves the way DRM bridges are allocated and initialized and
makes them reference-counted. The goal of reference counting is to avoid
use-after-free by drivers which got a pointer to a bridge and keep it
stored and used even after the bridge has been deallocated.

The overall goal is supporting Linux devices with a DRM pipeline whose
final components can be hot-plugged and hot-unplugged, including one or
more bridges. For more details see the big picture [0].

DRM bridge drivers will have to be adapted to the new API -- the change is
trivial for most cases. This series converts two of them to serve as an
example. The remaining ones will be done as a follow-up after this first
part is merged.

After that, refcounting will have to be added on the two sides: all
functions returning a bridge pointer and all code obtaining such a
pointer. A few examples have been sent in v7 (link below), they are OK, but
I removed them from v8 because they must be merged only after converting
all bridges.

Here's the grand plan:

 A. add new alloc API and refcounting (this series, at least patches 1-3)
 B. after (A), convert all bridge drivers to new API
 C. after (A), add documentation and kunit tests
 D. after (B), add get/put to drm_bridge_add/remove() + attach/detech()
    (patches 3-4 in the v7 series)
 E. after (B), convert accessors (including patches 5-9 in the v7 series
    which convert drm_bridge_chain_get_first_bridge() and its users);
    this is a large work and can be done in chunks

Series layout:

 1. Add the new API and refcounting:

    drm/bridge: add devm_drm_bridge_alloc()
    drm/bridge: add support for refcounting
    drm/bridge: deprecate old-style bridge allocation

 2. convert a few bridge drivers (bridge providers) to the new API:

    drm/bridge: ti-sn65dsi83: use dynamic lifetime management
    drm/bridge: samsung-dsim: use dynamic lifetime management

[0] https://lore.kernel.org/dri-devel/20250206-hotplug-drm-bridge-v6-0-9d6f2c9c3058 at bootlin.com/

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---
Changes in v8:
- Applied requested changes to patch 2
- Add R-by to other patches
- Removed v7 patches 3-9: they are OK but must wait until all bridge
  drivers are converted to the new API
- Added patch to deprecate old-style bridge allocation
- Link to v7: https://lore.kernel.org/r/20250314-drm-bridge-refcount-v7-0-152571f8c694 at bootlin.com

---
Luca Ceresoli (5):
      drm/bridge: add devm_drm_bridge_alloc()
      drm/bridge: add support for refcounting
      drm/bridge: deprecate old-style bridge allocation
      drm/bridge: ti-sn65dsi83: use dynamic lifetime management
      drm/bridge: samsung-dsim: use dynamic lifetime management

 drivers/gpu/drm/bridge/samsung-dsim.c |  7 ++-
 drivers/gpu/drm/bridge/ti-sn65dsi83.c |  7 ++-
 drivers/gpu/drm/drm_bridge.c          | 96 +++++++++++++++++++++++++++++++++++
 include/drm/drm_bridge.h              | 36 +++++++++++++
 4 files changed, 138 insertions(+), 8 deletions(-)
---
base-commit: c940d00c7306a77ec293661abca634756207c885
change-id: 20250314-drm-bridge-refcount-58d9503503f6

Best regards,
-- 
Luca Ceresoli <luca.ceresoli at bootlin.com>



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:10 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:10 +0100
Subject: [PATCH v8 1/5] drm/bridge: add devm_drm_bridge_alloc()
In-Reply-To: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
Message-ID: <20250320-drm-bridge-refcount-v8-1-b3ddaa9f1368@bootlin.com>

Add a macro to allocate and initialize a DRM bridge embedded within a
private driver struct.

Compared to current practice, which is based on [devm_]kzalloc() allocation
followed by open-coded initialization of fields, this allows to have a
common and explicit API to allocate and initialize DRM bridges.

Besides being useful to consolidate bridge driver code, this is a
fundamental step in preparation for adding dynamic lifetime to bridges
based on refcount.

Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---

Changes in v8: none

Changes in v7:
- in v6 this was part of "drm/bridge: add support for refcounted DRM
  bridges", now split to a separate patch
---
 drivers/gpu/drm/drm_bridge.c | 22 ++++++++++++++++++++++
 include/drm/drm_bridge.h     | 17 +++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index ef98e21dc593f38a2d3c67b850032ece38bec5e8..84fa1a1330cbabd309526829fff70971cfed1dcd 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -199,6 +199,28 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
+			      const struct drm_bridge_funcs *funcs)
+{
+	void *container;
+	struct drm_bridge *bridge;
+
+	if (!funcs) {
+		dev_warn(dev, "Missing funcs pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	container = devm_kzalloc(dev, size, GFP_KERNEL);
+	if (!container)
+		return ERR_PTR(-ENOMEM);
+
+	bridge = container + offset;
+	bridge->funcs = funcs;
+
+	return container;
+}
+EXPORT_SYMBOL(__devm_drm_bridge_alloc);
+
 /**
  * drm_bridge_add - add the given bridge to the global bridge list
  *
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index cdad3b78a195aa39776c93e2371217d3d3fb6064..a59277674d5a2937e324d3ce48f934418788053f 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -941,6 +941,23 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
 	return container_of(priv, struct drm_bridge, base);
 }
 
+void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
+			      const struct drm_bridge_funcs *funcs);
+
+/**
+ * devm_drm_bridge_alloc - Allocate and initialize a bridge
+ * @dev: struct device of the bridge device
+ * @type: the type of the struct which contains struct &drm_bridge
+ * @member: the name of the &drm_bridge within @type
+ * @funcs: callbacks for this bridge
+ *
+ * Returns:
+ * Pointer to new bridge, or ERR_PTR on failure.
+ */
+#define devm_drm_bridge_alloc(dev, type, member, funcs) \
+	((type *)__devm_drm_bridge_alloc(dev, sizeof(type), \
+					 offsetof(type, member), funcs))
+
 void drm_bridge_add(struct drm_bridge *bridge);
 int devm_drm_bridge_add(struct device *dev, struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);

-- 
2.48.1



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:11 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:11 +0100
Subject: [PATCH v8 2/5] drm/bridge: add support for refcounting
In-Reply-To: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
Message-ID: <20250320-drm-bridge-refcount-v8-2-b3ddaa9f1368@bootlin.com>

DRM bridges are currently considered as a fixed element of a DRM card, and
thus their lifetime is assumed to extend for as long as the card
exists. New use cases, such as hot-pluggable hardware with video bridges,
require DRM bridges to be added to and removed from a DRM card without
tearing the card down. This is possible for connectors already (used by DP
MST), it is now needed for DRM bridges as well.

As a first preliminary step, make bridges reference-counted to allow a
struct drm_bridge (along with the private driver structure embedding it) to
stay allocated even after the driver has been removed, until the last
reference is put.

Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

Changes in v8:
 - move back drm_bridge_get/put() to the .c file, make __drm_bridge_free
   private
 - move back drm_bridge_put_void() to .c, not used in this series outside
   of drm_bridge.c
 - remove drm_bridge_put_and_clear(), not used in this series
 - minor docs and coding style tweaks

Changes in v7:
 - export drm_bridge_put_void
 - struct drm_bridge: use container pointer instead of container_offset
 - remove drm_bridge_is_refcounted()
 - remove all DRM_DEBUG()s
 - drm_bridge_get/put: accept NULL pointer and return the bridge pointer to
   allow pass-through calls
 - extract to separate patches:
    - the addition of drm_bridge_alloc
    - the addition of drm_bridge_get/put() to drm_bridge_add/remove()
    - the addition of drm_bridge_get/put() to drm_bridge_attach/detach()
 - fix a typo, slightly improve kerneldoc

Changes in v6:
 - use drm_warn, not WARN_ON (Jani Nikula)
 - Add devm_drm_bridge_alloc() to replace drm_bridge_init() (similar to
   drmm_encoder_alloc)
 - Remove .destroy func: deallocation is done via the struct offset
   computed by the devm_drm_bridge_alloc() macro
 - use fixed free callback, as the same callback is used in all cases
   anyway (remove free_cb, add bool is_refcounted)
 - add drm_bridge_get/put() to drm_bridge_attach/detach() (add the bridge
   to a list)
 - make some DRM_DEBUG() strings more informative

This patch was added in v5.
---
 drivers/gpu/drm/drm_bridge.c | 72 +++++++++++++++++++++++++++++++++++++++++++-
 include/drm/drm_bridge.h     | 19 ++++++++++++
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 84fa1a1330cbabd309526829fff70971cfed1dcd..2f2ecb73308e601b1a53ec8e7110933cef59b5da 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -199,23 +199,93 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+static void __drm_bridge_free(struct kref *kref)
+{
+	struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
+
+	kfree(bridge->container);
+}
+
+/**
+ * drm_bridge_get - Acquire a bridge reference
+ * @bridge: DRM bridge
+ *
+ * This function increments the bridge's refcount.
+ *
+ * Returns:
+ * Pointer to @bridge.
+ */
+struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge)
+{
+	if (!bridge)
+		return bridge;
+
+	kref_get(&bridge->refcount);
+
+	return bridge;
+}
+EXPORT_SYMBOL(drm_bridge_get);
+
+/**
+ * drm_bridge_put - Release a bridge reference
+ * @bridge: DRM bridge
+ *
+ * This function decrements the bridge's reference count and frees the
+ * object if the reference count drops to zero.
+ *
+ * Returns:
+ * Pointer to @bridge.
+ */
+struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge)
+{
+	if (!bridge)
+		return bridge;
+
+	kref_put(&bridge->refcount, __drm_bridge_free);
+
+	return bridge;
+}
+EXPORT_SYMBOL(drm_bridge_put);
+
+/**
+ * drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
+ *
+ * @data: pointer to @struct drm_bridge, cast to a void pointer
+ *
+ * Wrapper of drm_bridge_put() to be used when a function taking a void
+ * pointer is needed, for example as a devm action.
+ */
+static void drm_bridge_put_void(void *data)
+{
+	struct drm_bridge *bridge = (struct drm_bridge *)data;
+
+	drm_bridge_put(bridge);
+}
+
 void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
 			      const struct drm_bridge_funcs *funcs)
 {
 	void *container;
 	struct drm_bridge *bridge;
+	int err;
 
 	if (!funcs) {
 		dev_warn(dev, "Missing funcs pointer\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	container = devm_kzalloc(dev, size, GFP_KERNEL);
+	container = kzalloc(size, GFP_KERNEL);
 	if (!container)
 		return ERR_PTR(-ENOMEM);
 
 	bridge = container + offset;
+	bridge->container = container;
 	bridge->funcs = funcs;
+	kref_init(&bridge->refcount);
+
+	err = devm_add_action_or_reset(dev, drm_bridge_put_void, bridge);
+	if (err)
+		return ERR_PTR(err);
 
 	return container;
 }
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index a59277674d5a2937e324d3ce48f934418788053f..076f40c17dd86b224bbe6517b71f1aa6c24bfbd7 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -840,6 +840,18 @@ struct drm_bridge {
 	const struct drm_bridge_timings *timings;
 	/** @funcs: control functions */
 	const struct drm_bridge_funcs *funcs;
+
+	/**
+	 * @container: Pointer to the private driver struct embedding this
+	 * @struct drm_bridge.
+	 */
+	void *container;
+
+	/**
+	 * @refcount: reference count of users referencing this bridge.
+	 */
+	struct kref refcount;
+
 	/** @driver_private: pointer to the bridge driver's internal context */
 	void *driver_private;
 	/** @ops: bitmask of operations supported by the bridge */
@@ -941,6 +953,9 @@ drm_priv_to_bridge(struct drm_private_obj *priv)
 	return container_of(priv, struct drm_bridge, base);
 }
 
+struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge);
+struct drm_bridge *drm_bridge_put(struct drm_bridge *bridge);
+
 void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
 			      const struct drm_bridge_funcs *funcs);
 
@@ -951,6 +966,10 @@ void *__devm_drm_bridge_alloc(struct device *dev, size_t size, size_t offset,
  * @member: the name of the &drm_bridge within @type
  * @funcs: callbacks for this bridge
  *
+ * The reference count of the returned bridge is initialized to 1. This
+ * reference will be automatically dropped via devm (by calling
+ * drm_bridge_put()) when @dev is removed.
+ *
  * Returns:
  * Pointer to new bridge, or ERR_PTR on failure.
  */

-- 
2.48.1



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:12 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:12 +0100
Subject: [PATCH v8 3/5] drm/bridge: deprecate old-style bridge allocation
In-Reply-To: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
Message-ID: <20250320-drm-bridge-refcount-v8-3-b3ddaa9f1368@bootlin.com>

All DRM bridges are now supposed to be allocated using
devm_drm_bridge_alloc(), which is cleaner and necessary to support
refcounting.

Deprecate old school allocation using kzalloc and derivatives. In the
absence of a drm_bridge_init() or such initialization function, document
the deprecation on the first DRM bridge core function that is called after
allocation, i.e. drm_bridge_add().

Suggested-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>

---

This patch was added in v8.
---
 drivers/gpu/drm/drm_bridge.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 2f2ecb73308e601b1a53ec8e7110933cef59b5da..17659b1cbdeae04e10b76f2aabc8ebba65c4f6e1 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -295,6 +295,10 @@ EXPORT_SYMBOL(__devm_drm_bridge_alloc);
  * drm_bridge_add - add the given bridge to the global bridge list
  *
  * @bridge: bridge control structure
+ *
+ * The bridge to be added must have been allocated by
+ * devm_drm_bridge_alloc(). Old-style allocation by kzalloc(),
+ * devm_kzalloc() and similar is deprecated.
  */
 void drm_bridge_add(struct drm_bridge *bridge)
 {

-- 
2.48.1



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:13 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:13 +0100
Subject: [PATCH v8 4/5] drm/bridge: ti-sn65dsi83: use dynamic lifetime
 management
In-Reply-To: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
Message-ID: <20250320-drm-bridge-refcount-v8-4-b3ddaa9f1368@bootlin.com>

Allow this bridge to be removable without dangling pointers and
use-after-free, together with proper use of drm_bridge_get() and _put() by
consumers.

Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---

Changes in v8: none
Changes in v7: none

Changed in v6:
 - Update to use devm_drm_bridge_alloc(), remove .destroy

This patch was added in v5.
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 6e0ba427c2582c33f7b95634a18dcda9ac28267f..4efb62376e196d8bb5e9f58867e5c0e1624391db 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -947,9 +947,9 @@ static int sn65dsi83_probe(struct i2c_client *client)
 	struct sn65dsi83 *ctx;
 	int ret;
 
-	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
+	ctx = devm_drm_bridge_alloc(dev, struct sn65dsi83, bridge, &sn65dsi83_funcs);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
 
 	ctx->dev = dev;
 	INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work);
@@ -989,7 +989,6 @@ static int sn65dsi83_probe(struct i2c_client *client)
 	dev_set_drvdata(dev, ctx);
 	i2c_set_clientdata(client, ctx);
 
-	ctx->bridge.funcs = &sn65dsi83_funcs;
 	ctx->bridge.of_node = dev->of_node;
 	ctx->bridge.pre_enable_prev_first = true;
 	ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS;

-- 
2.48.1



From luca.ceresoli at bootlin.com  Thu Mar 20 08:42:14 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Thu, 20 Mar 2025 16:42:14 +0100
Subject: [PATCH v8 5/5] drm/bridge: samsung-dsim: use dynamic lifetime
 management
In-Reply-To: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-0-b3ddaa9f1368@bootlin.com>
Message-ID: <20250320-drm-bridge-refcount-v8-5-b3ddaa9f1368@bootlin.com>

Allow this bridge to be removable without dangling pointers and
use-after-free, together with proper use of drm_bridge_get() and _put() by
consumers.

Reviewed-by: Maxime Ripard <mripard at kernel.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
---

Changes in v8: none

This patch was added in v7.
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 55ac6bd5da08c037aa7974df679d51e72bc54faf..0014c497e3fe7d8349a119dbdda30d65d816cccf 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1936,9 +1936,9 @@ int samsung_dsim_probe(struct platform_device *pdev)
 	struct samsung_dsim *dsi;
 	int ret, i;
 
-	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
-	if (!dsi)
-		return -ENOMEM;
+	dsi = devm_drm_bridge_alloc(dev, struct samsung_dsim, bridge, &samsung_dsim_bridge_funcs);
+	if (IS_ERR(dsi))
+		return PTR_ERR(dsi);
 
 	init_completion(&dsi->completed);
 	spin_lock_init(&dsi->transfer_lock);
@@ -2008,7 +2008,6 @@ int samsung_dsim_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
-	dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 

-- 
2.48.1



From yeoreum.yun at arm.com  Thu Mar 20 08:48:49 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Thu, 20 Mar 2025 15:48:49 +0000
Subject: [PATCH v3 0/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
Message-ID: <Z9w44Qq7Mo+kTWZ9@e129823.arm.com>

On Thu, Mar 20, 2025 at 02:34:09PM +0000, James Clark wrote:
> I've gotten stuck a few times with unusable Coresight after a warm boot
> due to lingering claim tags, especially when testing the Coresight
> panic patchsets.
>
> This change does some tidy ups, adds some debug messages and clears the
> self hosted claim tag on probe. The last two commits are unrelated
> tidyups but they touch some of the same functions so to avoid extra
> conflicts I'm including them here.
>
> This gets as far as fixing the claim tag issue, but there is some other
> state not being cleared on probe that results in the following error.
> This can be fixed up as a later change:
>
>   coresight tmc_etf0: timeout while waiting for TMC to be Ready
>   coresight tmc_etf0: Failed to enable : TMC is not ready
>
> Changes in v3:
> - Collapse rename and locked/unlocked addition commits of
>   coresight_clear_self_claim_tag() so we don't change the name twice.
> - Make coresight_clear_self_claim_tag() a bit more generic by only
>   doing UNLOCK for MMIO devices (although there is no use of this right
>   now)
> - Link to v2: https://lore.kernel.org/r/20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e at linaro.org
>
> Changes in v2:
>  * Revert most of the interface changes, just call
>    coresight_clear_self_claim_tag() directly. This is possible because
>    we're not doing the read first, so it has fewer knock on effects.
>  * Split out the change to add struct cs_access to etm3x
>  * Add another warning for racing with external debugger
>
> --
> 2.34.1
>
> ---
> James Clark (7):
>       coresight: Convert tag clear function to take a struct cs_access
>       coresight: Only check bottom two claim bits
>       coresight: Add claim tag warnings and debug messages
>       coresight: etm3x: Convert raw base pointer to struct coresight access
>       coresight: Clear self hosted claim tag on probe
>       coresight: Remove inlines from static function definitions
>       coresight: Remove extern from function declarations
>
>  drivers/hwtracing/coresight/coresight-catu.c       | 12 +--
>  drivers/hwtracing/coresight/coresight-core.c       | 87 ++++++++++++++--------
>  drivers/hwtracing/coresight/coresight-cti-core.c   |  2 +
>  drivers/hwtracing/coresight/coresight-etb10.c      |  4 +-
>  drivers/hwtracing/coresight/coresight-etm.h        |  6 +-
>  drivers/hwtracing/coresight/coresight-etm3x-core.c | 28 +++----
>  .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +-
>  drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++-
>  .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 +-
>  drivers/hwtracing/coresight/coresight-funnel.c     |  1 +
>  drivers/hwtracing/coresight/coresight-platform.c   | 26 +++----
>  drivers/hwtracing/coresight/coresight-priv.h       | 20 ++---
>  drivers/hwtracing/coresight/coresight-replicator.c |  3 +-
>  drivers/hwtracing/coresight/coresight-stm.c        |  6 +-
>  .../coresight/coresight-syscfg-configfs.c          |  2 +-
>  drivers/hwtracing/coresight/coresight-tmc-core.c   |  9 ++-
>  drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++--
>  drivers/hwtracing/coresight/coresight-trbe.c       | 18 ++---
>  include/linux/coresight.h                          | 40 +++++-----
>  19 files changed, 168 insertions(+), 134 deletions(-)
> ---
> base-commit: 5442d22da7dbff3ba8c6720fc6f23ea4934d402d
> change-id: 20250317-james-coresight-claim-tags-ae1461f1f5e0
>
> Best regards,
> --
> James Clark <james.clark at linaro.org>

Look good to me

Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>


From nm at ti.com  Thu Mar 20 08:22:53 2025
From: nm at ti.com (Nishanth Menon)
Date: Thu, 20 Mar 2025 10:22:53 -0500
Subject: [PATCH v1] arm64: dts: ti: k3-j784s4-main: Enable ACSPCIE
 outputs for PCIe interfaces
In-Reply-To: <20250320122259.525613-1-parth105105@gmail.com>
References: <20250320122259.525613-1-parth105105@gmail.com>
Message-ID: <20250320152253.rm7zavvnqvzmy6pv@galore>

On 13:22-20250320, Parth Pancholi wrote:
> From: Parth Pancholi <parth.pancholi at toradex.com>
> 
> TI J784S4-based devices, such as the AM69 SoC, provide PCIE_REFCLK outputs
> from the SoC, which can be used to clock external PCIe endpoint devices.
> Each PCIE_REFCLK output is enabled via the corresponding ACSPCIE clock buffer,
> with each buffer supporting two PADs to provide reference clocks for two
> associated PCIe instances. The mappings are as follows:
>         - PCIe0 -> ACSPCIE1 PAD0
>         - PCIe1 -> ACSPCIE0 PAD0
>         - PCIe2 -> ACSPCIE1 PAD1
>         - PCIe3 -> ACSPCIE0 PAD1
> 
> This patch enables each ACSPCIE module and its corresponding PADs to ensure
> that all PCIE_REFCLK outputs are functional.
> 
> This change have been tested on an AM69-based custom hardware platform,
> where all four PCIe instances (PCIe0, PCIe1, PCIe2, and PCIe3) with the
> internal PCIE_REFCLK are utilized with various endpoint devices such as
> a WiFi card, NVMe SSD, and PCIe-to-USB bridge.
> 
> Link: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1484211/am69-pcie-refclk-out-and-acspcie-mappings
> Signed-off-by: Parth Pancholi <parth.pancholi at toradex.com>
> ---
> This change depends on https://lore.kernel.org/all/20241209085157.1203168-1-s-vadapalli at ti.com/
> ---
>  .../boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi      | 10 ++++++++--
>  arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi             | 10 ++++++----
>  2 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
> index 591609f3194c..854fdf7b771e 100644
> --- a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
> @@ -132,6 +132,11 @@ acspcie0_proxy_ctrl: clock-controller at 1a090 {
>  			compatible = "ti,j784s4-acspcie-proxy-ctrl", "syscon";
>  			reg = <0x1a090 0x4>;
>  		};
> +
> +		acspcie1_proxy_ctrl: clock-controller at 1a094 {
> +			compatible = "ti,j784s4-acspcie-proxy-ctrl", "syscon";

We have the same challenge with bindings as well?

> +			reg = <0x1a094 0x4>;
> +		};
>  	};
>  
>  	main_ehrpwm0: pwm at 3000000 {
> @@ -1067,11 +1072,12 @@ pcie0_rc: pcie at 2900000 {
>  		interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
>  		device_type = "pci";
>  		ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
> +		ti,syscon-acspcie-proxy-ctrl = <&acspcie1_proxy_ctrl 0x1>;
>  		max-link-speed = <3>;
>  		num-lanes = <4>;
>  		power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
> -		clocks = <&k3_clks 332 0>;
> -		clock-names = "fck";
> +		clocks = <&k3_clks 332 0>, <&serdes1 CDNS_TORRENT_REFCLK_DRIVER>;
> +		clock-names = "fck", "pcie_refclk";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		bus-range = <0x0 0xff>;
> diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> index 0160fe0da983..ebbc315649d0 100644
> --- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> @@ -34,8 +34,8 @@ pcie2_rc: pcie at 2920000 {
>  		max-link-speed = <3>;
>  		num-lanes = <2>;
>  		power-domains = <&k3_pds 334 TI_SCI_PD_EXCLUSIVE>;
> -		clocks = <&k3_clks 334 0>;
> -		clock-names = "fck";
> +		clocks = <&k3_clks 334 0>, <&serdes1 CDNS_TORRENT_REFCLK_DRIVER>;
> +		clock-names = "fck", "pcie_refclk";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		bus-range = <0x0 0xff>;
> @@ -45,6 +45,7 @@ pcie2_rc: pcie at 2920000 {
>  		dma-coherent;
>  		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
>  		ti,syscon-pcie-ctrl = <&pcie2_ctrl 0x0>;
> +		ti,syscon-acspcie-proxy-ctrl = <&acspcie1_proxy_ctrl 0x3>;
>  		status = "disabled";
>  	};
>  
> @@ -63,8 +64,8 @@ pcie3_rc: pcie at 2930000 {
>  		max-link-speed = <3>;
>  		num-lanes = <2>;
>  		power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
> -		clocks = <&k3_clks 335 0>;
> -		clock-names = "fck";
> +		clocks = <&k3_clks 335 0>, <&serdes0 CDNS_TORRENT_REFCLK_DRIVER>;
> +		clock-names = "fck", "pcie_refclk";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		bus-range = <0x0 0xff>;
> @@ -74,6 +75,7 @@ pcie3_rc: pcie at 2930000 {
>  		dma-coherent;
>  		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
>  		ti,syscon-pcie-ctrl = <&pcie3_ctrl 0x0>;
> +		ti,syscon-acspcie-proxy-ctrl = <&acspcie0_proxy_ctrl 0x3>;
>  		status = "disabled";
>  	};
>  
> -- 
> 2.34.1
> 

-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D


From lkp at intel.com  Thu Mar 20 08:23:22 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 20 Mar 2025 23:23:22 +0800
Subject: [soc:qcom/defconfig] BUILD SUCCESS
 dd20903cc09ac40e71096370a9564e6523e87c22
Message-ID: <202503202315.OVMstnDa-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git qcom/defconfig
branch HEAD: dd20903cc09ac40e71096370a9564e6523e87c22  arm64: defconfig: Enable USB retimer and redriver

elapsed time: 1456m

configs tested: 152
configs skipped: 204

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
alpha                            allyesconfig    clang-19
alpha                               defconfig    gcc-14.2.0
arc                              allmodconfig    clang-19
arc                               allnoconfig    gcc-14.2.0
arc                              allyesconfig    clang-19
arc                                 defconfig    gcc-14.2.0
arc                            hsdk_defconfig    clang-15
arc                   randconfig-001-20250320    gcc-7.5.0
arc                   randconfig-002-20250320    gcc-7.5.0
arm                              allmodconfig    clang-19
arm                               allnoconfig    gcc-14.2.0
arm                              allyesconfig    clang-19
arm                       aspeed_g5_defconfig    clang-15
arm                                 defconfig    gcc-14.2.0
arm                             mxs_defconfig    clang-15
arm                   randconfig-001-20250320    gcc-7.5.0
arm                   randconfig-002-20250320    gcc-7.5.0
arm                   randconfig-003-20250320    gcc-7.5.0
arm                   randconfig-004-20250320    gcc-7.5.0
arm                           tegra_defconfig    clang-15
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-14.2.0
arm64                               defconfig    clang-15
arm64                               defconfig    gcc-14.2.0
arm64                 randconfig-001-20250320    clang-21
arm64                 randconfig-001-20250320    gcc-7.5.0
arm64                 randconfig-002-20250320    clang-21
arm64                 randconfig-002-20250320    gcc-7.5.0
arm64                 randconfig-003-20250320    clang-19
arm64                 randconfig-003-20250320    gcc-7.5.0
arm64                 randconfig-004-20250320    gcc-7.5.0
arm64                 randconfig-004-20250320    gcc-8.5.0
csky                              allnoconfig    gcc-14.2.0
csky                                defconfig    gcc-14.2.0
csky                  randconfig-001-20250320    gcc-12.4.0
csky                  randconfig-002-20250320    gcc-12.4.0
hexagon                          allmodconfig    clang-19
hexagon                           allnoconfig    gcc-14.2.0
hexagon                          allyesconfig    clang-19
hexagon                             defconfig    gcc-14.2.0
hexagon               randconfig-001-20250320    gcc-12.4.0
hexagon               randconfig-002-20250320    gcc-12.4.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    clang-20
i386                             allyesconfig    clang-20
i386                                defconfig    clang-20
i386                  randconfig-001-20250320    clang-20
i386                  randconfig-002-20250320    clang-20
i386                  randconfig-003-20250320    clang-20
i386                  randconfig-004-20250320    clang-20
i386                  randconfig-005-20250320    clang-20
i386                  randconfig-006-20250320    clang-20
i386                  randconfig-007-20250320    clang-20
i386                  randconfig-011-20250320    gcc-12
i386                  randconfig-012-20250320    gcc-12
i386                  randconfig-013-20250320    gcc-12
i386                  randconfig-014-20250320    gcc-12
i386                  randconfig-015-20250320    gcc-12
i386                  randconfig-016-20250320    gcc-12
i386                  randconfig-017-20250320    gcc-12
loongarch                        allmodconfig    gcc-14.2.0
loongarch                         allnoconfig    gcc-14.2.0
loongarch                           defconfig    gcc-14.2.0
loongarch                 loongson3_defconfig    clang-15
loongarch             randconfig-001-20250320    gcc-12.4.0
loongarch             randconfig-002-20250320    gcc-12.4.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
m68k                                defconfig    gcc-14.2.0
microblaze                       allmodconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
microblaze                       allyesconfig    gcc-14.2.0
microblaze                          defconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
mips                         rt305x_defconfig    clang-15
nios2                             allnoconfig    gcc-14.2.0
nios2                               defconfig    gcc-14.2.0
nios2                 randconfig-001-20250320    gcc-12.4.0
nios2                 randconfig-002-20250320    gcc-12.4.0
openrisc                          allnoconfig    clang-15
openrisc                         allyesconfig    gcc-14.2.0
parisc                           allmodconfig    gcc-14.2.0
parisc                            allnoconfig    clang-15
parisc                           allyesconfig    gcc-14.2.0
parisc                randconfig-001-20250320    gcc-12.4.0
parisc                randconfig-002-20250320    gcc-12.4.0
parisc64                            defconfig    gcc-14.2.0
powerpc                          allmodconfig    gcc-14.2.0
powerpc                           allnoconfig    clang-15
powerpc                          allyesconfig    gcc-14.2.0
powerpc                      arches_defconfig    clang-15
powerpc                      bamboo_defconfig    clang-15
powerpc                 mpc8313_rdb_defconfig    clang-15
powerpc               randconfig-001-20250320    gcc-12.4.0
powerpc               randconfig-002-20250320    gcc-12.4.0
powerpc               randconfig-003-20250320    gcc-12.4.0
powerpc64             randconfig-001-20250320    gcc-12.4.0
powerpc64             randconfig-002-20250320    gcc-12.4.0
powerpc64             randconfig-003-20250320    gcc-12.4.0
riscv                            allmodconfig    gcc-14.2.0
riscv                             allnoconfig    clang-15
riscv                            allyesconfig    gcc-14.2.0
s390                             allmodconfig    gcc-14.2.0
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                        dreamcast_defconfig    clang-15
sh                            migor_defconfig    clang-15
sh                          sdk7780_defconfig    clang-15
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-15
um                               allyesconfig    clang-19
x86_64                           alldefconfig    clang-15
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250320    clang-20
x86_64      buildonly-randconfig-002-20250320    clang-20
x86_64      buildonly-randconfig-003-20250320    clang-20
x86_64      buildonly-randconfig-004-20250320    clang-20
x86_64      buildonly-randconfig-005-20250320    clang-20
x86_64      buildonly-randconfig-006-20250320    clang-20
x86_64                              defconfig    clang-20
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20250320    clang-20
x86_64                randconfig-002-20250320    clang-20
x86_64                randconfig-003-20250320    clang-20
x86_64                randconfig-004-20250320    clang-20
x86_64                randconfig-005-20250320    clang-20
x86_64                randconfig-006-20250320    clang-20
x86_64                randconfig-007-20250320    clang-20
x86_64                randconfig-008-20250320    clang-20
x86_64                randconfig-071-20250320    gcc-12
x86_64                randconfig-072-20250320    gcc-12
x86_64                randconfig-073-20250320    gcc-12
x86_64                randconfig-074-20250320    gcc-12
x86_64                randconfig-075-20250320    gcc-12
x86_64                randconfig-076-20250320    gcc-12
x86_64                randconfig-077-20250320    gcc-12
x86_64                randconfig-078-20250320    gcc-12
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    clang-18
x86_64                         rhel-9.4-kunit    clang-18
x86_64                           rhel-9.4-ltp    clang-18
x86_64                          rhel-9.4-rust    clang-18
xtensa                            allnoconfig    gcc-14.2.0
xtensa                       common_defconfig    clang-15

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From potin.lai.pt at gmail.com  Thu Mar 20 08:21:50 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:50 +0800
Subject: [PATCH v5 00/10] ARM: dts: aspeed: catalina: Update DTS to support
 Catalina PVT hardware
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>

Update the DTS file for the Catalina platform based on the PVT hardware
changes.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
Changes in v5:
- Revise CBC FRU eeprom i2c bus and address
- Add MCTP support for backend NIC monitoring via PLDM over MCTP
- Link to v4: https://lore.kernel.org/r/20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014 at gmail.com

Changes in v4:
- Split a single commit into multiple smaller commits to reduce complexity.
- Add `multi-master` into i2c12 & i2c13  
- Link to v3: https://lore.kernel.org/r/20250114-potin-catalina-dts-update-20250102-v3-1-14981744b2fe at gmail.com

Changes in v3:
- Remove delta_brick nodes due to compatible string not supported
- Link to v2: https://lore.kernel.org/r/20250113-potin-catalina-dts-update-20250102-v2-1-1725117fe7a9 at gmail.com

Changes in v2:
- Add delta_brick nodes to support PDB brick board
- Link to v1: https://lore.kernel.org/r/20250103-potin-catalina-dts-update-20250102-v1-1-b0b7a523c968 at gmail.com

---
Potin Lai (10):
      ARM: dts: aspeed: catalina: Add IO Mezz board thermal sensor nodes
      ARM: dts: aspeed: catalina: Add Front IO board remote thermal sensor
      ARM: dts: aspeed: catalina: Add MP5990 power sensor node
      ARM: dts: aspeed: catalina: Add fan controller support
      ARM: dts: aspeed: catalina: Add second source fan controller support
      ARM: dts: aspeed: catalina: Add second source HSC node support
      ARM: dts: aspeed: catalina: Remove INA238 and INA230 nodes
      ARM: dts: aspeed: catalina: Enable multi-master on additional I2C buses
      ARM: dts: aspeed: catalina: Update CBC FRU EEPROM I2C bus and address
      ARM: dts: aspeed: catalina: Enable MCTP support for NIC management

 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 197 +++++++++++++++------
 1 file changed, 144 insertions(+), 53 deletions(-)
---
base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
change-id: 20250102-potin-catalina-dts-update-20250102-914b06a4bdba

Best regards,
-- 
Potin Lai <potin.lai.pt at gmail.com>



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:51 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:51 +0800
Subject: [PATCH v5 01/10] ARM: dts: aspeed: catalina: Add IO Mezz board
 thermal sensor nodes
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-1-e161be6583a7@gmail.com>

Add thermal sensor nodes for the IO Mezzanine (IO Mezz) board in the
Catalina platform device tree. These nodes enable temperature monitoring
for the backend NIC, improving thermal management and monitoring
capabilities.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index c151984289bc..d5d99a945ee4 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -198,6 +198,12 @@ i2c0mux0ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB0 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -208,6 +214,12 @@ i2c0mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB0 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch3: i2c at 3 {
 			#address-cells = <1>;
@@ -299,6 +311,12 @@ i2c0mux3ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB1 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -309,6 +327,12 @@ i2c0mux3ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB1 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:52 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:52 +0800
Subject: [PATCH v5 02/10] ARM: dts: aspeed: catalina: Add Front IO board
 remote thermal sensor
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-2-e161be6583a7@gmail.com>

Add a remote thermal sensor node for the Front IO board in the Catalina
platform device tree. This sensor enables monitoring of the inlet
temperature.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index d5d99a945ee4..307af99e833c 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -544,6 +544,12 @@ temperature-sensor at 4b {
 				compatible = "ti,tmp75";
 				reg = <0x4b>;
 			};
+
+			// FIO REMOTE TEMP SENSOR
+			temperature-sensor at 4f {
+				compatible = "ti,tmp75";
+				reg = <0x4f>;
+			};
 		};
 	};
 };

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:53 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:53 +0800
Subject: [PATCH v5 03/10] ARM: dts: aspeed: catalina: Add MP5990 power
 sensor node
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-3-e161be6583a7@gmail.com>

Add a device tree node for the MP5990 power sensor to enable monitoring of
the P12V supplying power to the fans.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 307af99e833c..f5f47245796a 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -428,6 +428,10 @@ i2c1mux0ch0: i2c at 0 {
 			#size-cells = <0>;
 			reg = <0x0>;
 
+			power-sensor at 22 {
+				compatible = "mps,mp5990";
+				reg = <0x22>;
+			};
 			power-sensor at 41 {
 				compatible = "ti,ina238";
 				reg = <0x41>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:54 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:54 +0800
Subject: [PATCH v5 04/10] ARM: dts: aspeed: catalina: Add fan controller
 support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-4-e161be6583a7@gmail.com>

Add device tree nodes for the MAX31790 fan controllers on the Power
Distribution Board (PDB). These nodes enable fan speed control and
monitoring, improving thermal management and system reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index f5f47245796a..fd22add90449 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -466,6 +466,15 @@ i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x2>;
+
+			pwm at 21{
+				compatible = "maxim,max31790";
+				reg = <0x21>;
+			};
+			pwm at 27{
+				compatible = "maxim,max31790";
+				reg = <0x27>;
+			};
 		};
 		i2c1mux0ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:55 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:55 +0800
Subject: [PATCH v5 05/10] ARM: dts: aspeed: catalina: Add second source fan
 controller support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-5-e161be6583a7@gmail.com>

Add device tree nodes for the NCT7363 fan controllers on the second-source
Power Distribution Board (PDB).

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index fd22add90449..9cbb296dcd9e 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -467,6 +467,82 @@ i2c1mux0ch2: i2c at 2 {
 			#size-cells = <0>;
 			reg = <0x2>;
 
+			hwmon0: hwmon at 1 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x01>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&hwmon0 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&hwmon0 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&hwmon0 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&hwmon0 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&hwmon0 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&hwmon0 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&hwmon0 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&hwmon0 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
+			hwmon1: hwmon at 2 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x02>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&hwmon1 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&hwmon1 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&hwmon1 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&hwmon1 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&hwmon1 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&hwmon1 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&hwmon1 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&hwmon1 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
 			pwm at 21{
 				compatible = "maxim,max31790";
 				reg = <0x21>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:56 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:56 +0800
Subject: [PATCH v5 06/10] ARM: dts: aspeed: catalina: Add second source HSC
 node support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-6-e161be6583a7@gmail.com>

Add device tree nodes for the XDP710 Hot-Swap Controller (HSC) to support
the Power Distribution Board (PDB) with a second-source configuration.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 9cbb296dcd9e..cf8a31b50074 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -562,6 +562,14 @@ i2c1mux0ch4: i2c at 4 {
 			#size-cells = <0>;
 			reg = <0x4>;
 
+			power-monitor at 13 {
+				compatible = "infineon,xdp710";
+				reg = <0x13>;
+			};
+			power-monitor at 1c {
+				compatible = "infineon,xdp710";
+				reg = <0x1c>;
+			};
 			power-monitor at 42 {
 				compatible = "lltc,ltc4287";
 				reg = <0x42>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Thu Mar 20 08:21:57 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Thu, 20 Mar 2025 23:21:57 +0800
Subject: [PATCH v5 07/10] ARM: dts: aspeed: catalina: Remove INA238 and
 INA230 nodes
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
Message-ID: <20250320-potin-catalina-dts-update-20250102-v5-7-e161be6583a7@gmail.com>

Remove INA238 and INA230 power sensor nodes from the device tree (DTS) due
to incompatibility with the second-source ISL28022, which shares the same
I2C address.

Move the driver probe to userspace to handle sensor dynamically.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 45 ----------------------
 1 file changed, 45 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index cf8a31b50074..1e1bcc9ac2f0 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -432,35 +432,11 @@ power-sensor at 22 {
 				compatible = "mps,mp5990";
 				reg = <0x22>;
 			};
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 42 {
-				compatible = "ti,ina238";
-				reg = <0x42>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 44 {
-				compatible = "ti,ina238";
-				reg = <0x44>;
-				shunt-resistor = <500>;
-			};
 		};
 		i2c1mux0ch1: i2c at 1 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x1>;
-
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-			};
-			power-sensor at 43 {
-				compatible = "ti,ina238";
-				reg = <0x43>;
-			};
 		};
 		i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;
@@ -753,27 +729,6 @@ i2c5mux0ch7: i2c at 7 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <7>;
-
-			power-sensor at 40 {
-				compatible = "ti,ina230";
-				reg = <0x40>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 41 {
-				compatible = "ti,ina230";
-				reg = <0x41>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 44 {
-				compatible = "ti,ina230";
-				reg = <0x44>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 45 {
-				compatible = "ti,ina230";
-				reg = <0x45>;
-				shunt-resistor = <2000>;
-			};
 		};
 	};
 };

-- 
2.31.1



From andre.przywara at arm.com  Thu Mar 20 08:55:57 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 20 Mar 2025 15:55:57 +0000
Subject: [PATCH] cpufreq: sun50i: prevent out-of-bounds access
Message-ID: <20250320155557.211211-1-andre.przywara@arm.com>

A KASAN enabled kernel reports an out-of-bounds access when handling the
nvmem cell in the sun50i cpufreq driver:
==================================================================
BUG: KASAN: slab-out-of-bounds in sun50i_cpufreq_nvmem_probe+0x180/0x3d4
Read of size 4 at addr ffff000006bf31e0 by task kworker/u16:1/38

This is because the DT specifies the nvmem cell as covering only two
bytes, but we use a u32 pointer to read the value. DTs for other SoCs
indeed specify 4 bytes, so we cannot just shorten the variable to a u16.

Fortunately nvmem_cell_read() allows to return the length of the nvmem
cell, in bytes, so we can use that information to only access the valid
portion of the data.
To cover multiple cell sizes, use memcpy() to copy the information into a
zeroed u32 buffer, then also make sure we always read the data in little
endian fashion, as this is how the data is stored in the SID efuses.

Fixes: 6cc4bcceff9a ("cpufreq: sun50i: Refactor speed bin decoding")
Reported-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 17d6a149f580d..c48ed04b82335 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -194,7 +194,9 @@ static int sun50i_cpufreq_get_efuse(void)
 	struct nvmem_cell *speedbin_nvmem;
 	const struct of_device_id *match;
 	struct device *cpu_dev;
-	u32 *speedbin;
+	void *speedbin_ptr;
+	u32 speedbin = 0;
+	size_t len;
 	int ret;
 
 	cpu_dev = get_cpu_device(0);
@@ -217,14 +219,18 @@ static int sun50i_cpufreq_get_efuse(void)
 		return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
 				     "Could not get nvmem cell\n");
 
-	speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
+	speedbin_ptr = nvmem_cell_read(speedbin_nvmem, &len);
 	nvmem_cell_put(speedbin_nvmem);
-	if (IS_ERR(speedbin))
-		return PTR_ERR(speedbin);
+	if (IS_ERR(speedbin_ptr))
+		return PTR_ERR(speedbin_ptr);
 
-	ret = opp_data->efuse_xlate(*speedbin);
+	if (len <= 4)
+		memcpy(&speedbin, speedbin_ptr, len);
+	speedbin = le32_to_cpu(speedbin);
 
-	kfree(speedbin);
+	ret = opp_data->efuse_xlate(speedbin);
+
+	kfree(speedbin_ptr);
 
 	return ret;
 };
-- 
2.46.3



From namhyung at kernel.org  Thu Mar 20 09:00:41 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 20 Mar 2025 09:00:41 -0700
Subject: [PATCH v1] perf cpumap: Increment reference count for online
 cpumap
In-Reply-To: <20250318171914.145616-1-irogers@google.com>
References: <20250318171914.145616-1-irogers@google.com>
Message-ID: <174248644166.3704425.11921703615469719002.b4-ty@kernel.org>

On Tue, 18 Mar 2025 10:19:14 -0700, Ian Rogers wrote:
> Thomas Richter <tmricht at linux.ibm.com> reported a double put on the
> cpumap for the placeholder core PMU:
> https://lore.kernel.org/lkml/20250318095132.1502654-3-tmricht at linux.ibm.com/
> Requiring the caller to get the cpumap is not how these things are
> usually done, switch cpu_map__online to do the get and then fix up any
> use cases where a put is needed.
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From christophe.leroy at csgroup.eu  Thu Mar 20 08:57:29 2025
From: christophe.leroy at csgroup.eu (Christophe Leroy)
Date: Thu, 20 Mar 2025 16:57:29 +0100
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <20241115152055.279732-1-linux@treblig.org>
References: <20241115152055.279732-1-linux@treblig.org>
Message-ID: <f79c2e97-2d50-467d-9852-c64971f11370@csgroup.eu>

Ioana,

Le 15/11/2024 ? 16:20, linux at treblig.org a ?crit?:
> [Vous ne recevez pas souvent de courriers de linux at treblig.org. D?couvrez pourquoi ceci est important ? https://aka.ms/LearnAboutSenderIdentification ]
> 
> From: "Dr. David Alan Gilbert" <linux at treblig.org>
> 
> fsl_mc_allocator_driver_exit() was added explicitly by
> commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> but was never used.
> 
> Remove it.
> 
> fsl_mc_portal_reset() was added in 2015 by
> commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> but was never used.
> 
> Remove it.
> 
> fsl_mc_portal_reset() was the only caller of dpmcp_reset().
> 
> Remove it.
> 
> Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>

Can you ack this patch ?

Thanks
Christophe

> ---
>   drivers/bus/fsl-mc/dpmcp.c            | 22 ----------------------
>   drivers/bus/fsl-mc/fsl-mc-allocator.c |  5 -----
>   drivers/bus/fsl-mc/fsl-mc-private.h   |  6 ------
>   drivers/bus/fsl-mc/mc-io.c            | 20 --------------------
>   include/linux/fsl/mc.h                |  2 --
>   5 files changed, 55 deletions(-)
> 
> diff --git a/drivers/bus/fsl-mc/dpmcp.c b/drivers/bus/fsl-mc/dpmcp.c
> index 5fbd0dbde24a..7816c0a728ef 100644
> --- a/drivers/bus/fsl-mc/dpmcp.c
> +++ b/drivers/bus/fsl-mc/dpmcp.c
> @@ -75,25 +75,3 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
>          /* send command to mc*/
>          return mc_send_command(mc_io, &cmd);
>   }
> -
> -/**
> - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
> - * @mc_io:     Pointer to MC portal's I/O object
> - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
> - * @token:     Token of DPMCP object
> - *
> - * Return:     '0' on Success; Error code otherwise.
> - */
> -int dpmcp_reset(struct fsl_mc_io *mc_io,
> -               u32 cmd_flags,
> -               u16 token)
> -{
> -       struct fsl_mc_command cmd = { 0 };
> -
> -       /* prepare command */
> -       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
> -                                         cmd_flags, token);
> -
> -       /* send command to mc*/
> -       return mc_send_command(mc_io, &cmd);
> -}
> diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
> index b5e8c021fa1f..6c3beb82dd1b 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
> @@ -656,8 +656,3 @@ int __init fsl_mc_allocator_driver_init(void)
>   {
>          return fsl_mc_driver_register(&fsl_mc_allocator_driver);
>   }
> -
> -void fsl_mc_allocator_driver_exit(void)
> -{
> -       fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
> -}
> diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
> index b3520ea1b9f4..e1b7ec3ed1a7 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-private.h
> +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
> @@ -66,10 +66,6 @@ int dpmcp_close(struct fsl_mc_io *mc_io,
>                  u32 cmd_flags,
>                  u16 token);
> 
> -int dpmcp_reset(struct fsl_mc_io *mc_io,
> -               u32 cmd_flags,
> -               u16 token);
> -
>   /*
>    * Data Path Resource Container (DPRC) API
>    */
> @@ -631,8 +627,6 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
> 
>   int __init fsl_mc_allocator_driver_init(void);
> 
> -void fsl_mc_allocator_driver_exit(void);
> -
>   void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
> 
>   void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
> diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
> index 95b10a6cf307..a0ad7866cbfc 100644
> --- a/drivers/bus/fsl-mc/mc-io.c
> +++ b/drivers/bus/fsl-mc/mc-io.c
> @@ -263,23 +263,3 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
>          dpmcp_dev->consumer_link = NULL;
>   }
>   EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
> -
> -/**
> - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
> - *
> - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
> - */
> -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
> -{
> -       int error;
> -       struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
> -
> -       error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
> -       if (error < 0) {
> -               dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
> -               return error;
> -       }
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
> diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
> index c90ec889bfc2..37316a58d2ed 100644
> --- a/include/linux/fsl/mc.h
> +++ b/include/linux/fsl/mc.h
> @@ -417,8 +417,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
> 
>   void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
> 
> -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
> -
>   int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
>                                          enum fsl_mc_pool_type pool_type,
>                                          struct fsl_mc_device **new_mc_adev);
> --
> 2.47.0
> 



From krzk at kernel.org  Thu Mar 20 09:20:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Thu, 20 Mar 2025 17:20:32 +0100
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <Z9vyy7f5NOPyzUES@nchen-desktop>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
 <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>
 <Z9vyy7f5NOPyzUES@nchen-desktop>
Message-ID: <7ed2af14-7677-4188-b77b-7f3c325d40a4@kernel.org>

On 20/03/2025 11:49, Peter Chen wrote:
> On 25-03-20 10:25:53, Krzysztof Kozlowski wrote:
>> EXTERNAL EMAIL
>>
>> On 05/03/2025 06:38, Peter Chen wrote:
>>> Using this entry as the maintainers information for CIX SKY series SoCs.
>>>
>>> Acked-by: Fugang Duan <fugang.duan at cixtech.com>
>>> Signed-off-by: Peter Chen <peter.chen at cixtech.com>
>>> ---
>>> Changes for v4
>>> - Add two dts files as maintained files
>>>
>>>  MAINTAINERS | 10 ++++++++++
>>>  1 file changed, 10 insertions(+)
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index efee40ea589f..edf26cf11ee2 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -2354,6 +2354,16 @@ F:     arch/arm/boot/compressed/misc-ep93xx.h
>>>  F:   arch/arm/mach-ep93xx/
>>>  F:   drivers/iio/adc/ep93xx_adc.c
>>>
>>> +ARM/CIX SKY ARM ARCHITECTURE
>>> +M:   Peter Chen <peter.chen at cixtech.com>
>>> +M:   Fugang Duan <fugang.duan at cixtech.com>
>>> +R:   CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
>>> +L:   linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>>> +S:   Maintained
>>> +F:   Documentation/devicetree/bindings/arm/cix.yaml
>>> +F:   arch/arm64/boot/dts/cix/sky1-orion-o6.dts
>>> +F:   arch/arm64/boot/dts/cix/sky1.dtsi
>>
>> Instead:
>> arch/arm64/boot/dts/cix/
>>
>> or if you think there will be more different architectures coming from
>> cix, which you will not maintain, then useful would be a "sky" subdirectory.
>>
> Hi Krzysztof,
> 
> Thanks for your comment, CIX is Arm SoC based silicon design
> company, we may have different SoC style for middle end in future.
> So, for that SoC series, it may not name sky.

Your Kconfig says ARCH_CIX :/

Anyway, listing individual files is pointless, so if you are not going
to maintain entire arch, then create subdir. Otherwise why creating so
many entries? The biggest upstreamed SoC vendor (by number of SoCs and
boards has one entry.


Best regards,
Krzysztof


From parth105105 at gmail.com  Thu Mar 20 09:26:51 2025
From: parth105105 at gmail.com (Parth Panchoil)
Date: Thu, 20 Mar 2025 17:26:51 +0100
Subject: [PATCH v1] arm64: dts: ti: k3-j784s4-main: Enable ACSPCIE
 outputs for PCIe interfaces
In-Reply-To: <20250320152253.rm7zavvnqvzmy6pv@galore>
References: <20250320122259.525613-1-parth105105@gmail.com>
	 <20250320152253.rm7zavvnqvzmy6pv@galore>
Message-ID: <0513632151e0b5e49ec73c2d8d6a41f02af17181.camel@gmail.com>

On Thu, 2025-03-20 at 10:22 -0500, Nishanth Menon wrote:
> On 13:22-20250320, Parth Pancholi wrote:
> > From: Parth Pancholi <parth.pancholi at toradex.com>
> > 
> > TI J784S4-based devices, such as the AM69 SoC, provide PCIE_REFCLK
> > outputs
> > from the SoC, which can be used to clock external PCIe endpoint
> > devices.
> > Each PCIE_REFCLK output is enabled via the corresponding ACSPCIE
> > clock buffer,
> > with each buffer supporting two PADs to provide reference clocks
> > for two
> > associated PCIe instances. The mappings are as follows:
> > ??????? - PCIe0 -> ACSPCIE1 PAD0
> > ??????? - PCIe1 -> ACSPCIE0 PAD0
> > ??????? - PCIe2 -> ACSPCIE1 PAD1
> > ??????? - PCIe3 -> ACSPCIE0 PAD1
> > 
> > This patch enables each ACSPCIE module and its corresponding PADs
> > to ensure
> > that all PCIE_REFCLK outputs are functional.
> > 
> > This change have been tested on an AM69-based custom hardware
> > platform,
> > where all four PCIe instances (PCIe0, PCIe1, PCIe2, and PCIe3) with
> > the
> > internal PCIE_REFCLK are utilized with various endpoint devices
> > such as
> > a WiFi card, NVMe SSD, and PCIe-to-USB bridge.
> > 
> > Link:
> > https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1484211/am69-pcie-refclk-out-and-acspcie-mappings
> > Signed-off-by: Parth Pancholi <parth.pancholi at toradex.com>
> > ---
> > This change depends on
> > https://lore.kernel.org/all/20241209085157.1203168-1-s-vadapalli at ti.com/
> > ---
> > ?.../boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi????? | 10
> > ++++++++--
> > ?arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi???????????? | 10
> > ++++++----
> > ?2 files changed, 14 insertions(+), 6 deletions(-)
> > 
> > diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-
> > common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-
> > common.dtsi
> > index 591609f3194c..854fdf7b771e 100644
> > --- a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
> > +++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
> > @@ -132,6 +132,11 @@ acspcie0_proxy_ctrl: clock-controller at 1a090 {
> > ????????????????????????compatible = "ti,j784s4-acspcie-proxy-
> > ctrl", "syscon";
> > ????????????????????????reg = <0x1a090 0x4>;
> > ????????????????};
> > +
> > +???????????????acspcie1_proxy_ctrl: clock-controller at 1a094 {
> > +???????????????????????compatible = "ti,j784s4-acspcie-proxy-
> > ctrl", "syscon";
> 
> We have the same challenge with bindings as well?

I believe the binding challenges have been resolved.
I tested on both 'ti-next' and 'next-20250320' with these two changes
applied on top, and the DT checker did not report any issues.

$ git log --oneline
c1d1735f9bf1 (HEAD) arm64: dts: ti: k3-j784s4-main: Enable ACSPCIE
outputs for PCIe interfaces
7cebddd4b6b3 arm64: dts: ti: k3-j784s4-j742s2-main-common: Enable
ACSPCIE output for PCIe1
15b2ed044c78 (mainline_ti/ti-next, mainline_ti/HEAD, ti-next) Merge
branch 'ti-k3-config-next' into ti-next

$ make CHECK_DTBS=y ti/k3-am69-sk.dtb W=1
  DTC [C] arch/arm64/boot/dts/ti/k3-am69-sk.dtb
$

$ git log --oneline
04cf02fe8b01 (HEAD) arm64: dts: ti: k3-j784s4-main: Enable ACSPCIE
outputs for PCIe interfaces
ffccd1b771aa arm64: dts: ti: k3-j784s4-j742s2-main-common: Enable
ACSPCIE output for PCIe1
73b8c1dbc250 (tag: next-20250320, linux_next/master) Add linux-next
specific files for 20250320

$ make CHECK_DTBS=y ti/k3-am69-sk.dtb W=1
  DTC [C] arch/arm64/boot/dts/ti/k3-am69-sk.dtb
$

> 
> > +???????????????????????reg = <0x1a094 0x4>;
> > +???????????????};
> > ????????};
> > ?
> > ????????main_ehrpwm0: pwm at 3000000 {
> > @@ -1067,11 +1072,12 @@ pcie0_rc: pcie at 2900000 {
> > ????????????????interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
> > ????????????????device_type = "pci";
> > ????????????????ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
> > +???????????????ti,syscon-acspcie-proxy-ctrl =
> > <&acspcie1_proxy_ctrl 0x1>;
> > ????????????????max-link-speed = <3>;
> > ????????????????num-lanes = <4>;
> > ????????????????power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
> > -???????????????clocks = <&k3_clks 332 0>;
> > -???????????????clock-names = "fck";
> > +???????????????clocks = <&k3_clks 332 0>, <&serdes1
> > CDNS_TORRENT_REFCLK_DRIVER>;
> > +???????????????clock-names = "fck", "pcie_refclk";
> > ????????????????#address-cells = <3>;
> > ????????????????#size-cells = <2>;
> > ????????????????bus-range = <0x0 0xff>;
> > diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> > b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> > index 0160fe0da983..ebbc315649d0 100644
> > --- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> > +++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
> > @@ -34,8 +34,8 @@ pcie2_rc: pcie at 2920000 {
> > ????????????????max-link-speed = <3>;
> > ????????????????num-lanes = <2>;
> > ????????????????power-domains = <&k3_pds 334 TI_SCI_PD_EXCLUSIVE>;
> > -???????????????clocks = <&k3_clks 334 0>;
> > -???????????????clock-names = "fck";
> > +???????????????clocks = <&k3_clks 334 0>, <&serdes1
> > CDNS_TORRENT_REFCLK_DRIVER>;
> > +???????????????clock-names = "fck", "pcie_refclk";
> > ????????????????#address-cells = <3>;
> > ????????????????#size-cells = <2>;
> > ????????????????bus-range = <0x0 0xff>;
> > @@ -45,6 +45,7 @@ pcie2_rc: pcie at 2920000 {
> > ????????????????dma-coherent;
> > ????????????????dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000
> > 0x0>;
> > ????????????????ti,syscon-pcie-ctrl = <&pcie2_ctrl 0x0>;
> > +???????????????ti,syscon-acspcie-proxy-ctrl =
> > <&acspcie1_proxy_ctrl 0x3>;
> > ????????????????status = "disabled";
> > ????????};
> > ?
> > @@ -63,8 +64,8 @@ pcie3_rc: pcie at 2930000 {
> > ????????????????max-link-speed = <3>;
> > ????????????????num-lanes = <2>;
> > ????????????????power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
> > -???????????????clocks = <&k3_clks 335 0>;
> > -???????????????clock-names = "fck";
> > +???????????????clocks = <&k3_clks 335 0>, <&serdes0
> > CDNS_TORRENT_REFCLK_DRIVER>;
> > +???????????????clock-names = "fck", "pcie_refclk";
> > ????????????????#address-cells = <3>;
> > ????????????????#size-cells = <2>;
> > ????????????????bus-range = <0x0 0xff>;
> > @@ -74,6 +75,7 @@ pcie3_rc: pcie at 2930000 {
> > ????????????????dma-coherent;
> > ????????????????dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000
> > 0x0>;
> > ????????????????ti,syscon-pcie-ctrl = <&pcie3_ctrl 0x0>;
> > +???????????????ti,syscon-acspcie-proxy-ctrl =
> > <&acspcie0_proxy_ctrl 0x3>;
> > ????????????????status = "disabled";
> > ????????};
> > ?
> > -- 
> > 2.34.1
> > 
> 


From catalin.marinas at arm.com  Thu Mar 20 09:36:31 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 20 Mar 2025 16:36:31 +0000
Subject: [PATCH] arm64: mm: Don't use %pK through printk
In-Reply-To: <20250217-restricted-pointers-arm64-v1-1-14bb1f516b01@linutronix.de>
References: <20250217-restricted-pointers-arm64-v1-1-14bb1f516b01@linutronix.de>
Message-ID: <174248858719.1537208.2049891754496228944.b4-ty@arm.com>

On Mon, 17 Feb 2025 08:39:06 +0100, Thomas Wei?schuh wrote:
> Restricted pointers ("%pK") are not meant to be used through printk().
> It can unintentionally expose security sensitive, raw pointer values.
> 
> Use regular pointer formatting instead.
> 
> 

Applied to arm64 (for-next/misc), thanks!

[1/1] arm64: mm: Don't use %pK through printk
      https://git.kernel.org/arm64/c/892d20acf36c

-- 
Catalin



From wthai at nvidia.com  Thu Mar 20 09:46:33 2025
From: wthai at nvidia.com (Willie Thai)
Date: Thu, 20 Mar 2025 16:46:33 +0000
Subject: [PATCH v3 2/2] dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
In-Reply-To: <20250320164633.101331-1-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
Message-ID: <20250320164633.101331-3-wthai@nvidia.com>

This patch adds a binding for GB200NVL BMC.

The GB200NVL BMC is an Aspeed Ast2600 based BMC for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Link: https://www.aspeedtech.com/server_ast2600/ [1]
Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 01333ac111fb..a3736f134130 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -98,6 +98,7 @@ properties:
               - inventec,starscream-bmc
               - inventec,transformer-bmc
               - jabil,rbp-bmc
+              - nvidia,gb200nvl-bmc
               - qcom,dc-scm-v1-bmc
               - quanta,s6q-bmc
               - ufispace,ncplite-bmc
-- 
2.25.1



From wthai at nvidia.com  Thu Mar 20 09:46:31 2025
From: wthai at nvidia.com (Willie Thai)
Date: Thu, 20 Mar 2025 16:46:31 +0000
Subject: [PATCH v3 0/2] Add device tree for Nvidia's GB200NVL BMC
Message-ID: <20250320164633.101331-1-wthai@nvidia.com>

The GB200NVL BMC is an Aspeed Ast2600 based BMC
for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Rob Herring <robh at kernel.org>
Cc: Paul Menzel <pmenzel at molgen.mpg.de>
Link: https://www.aspeedtech.com/server_ast2600/ [1]
Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes v1 -> v2:
  - Fix the SOB name [Krzysztof]
  - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
  - Fix DTS coding style [Krzysztof]
  - Move pinctrl override to the bottom [Krzysztof]
  - Drop bootargs [Krzysztof]
  - Follow DTS coding style and change naming for leds node [Krzysztof]
  - Change flash 0 status property [Krzysztof]
  - Change the phy-mode to rgmii [Andrew]
  - Remove the max-speed in mac0 [Andrew]
  - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
Changes v2 -> v3:
  - Fix missing new line [Krzysztof]
  - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
  - Fix DTS coding style [Krzysztof]
  - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
  - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
  - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
---

Willie Thai (2):
  ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
  dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC

 .../bindings/arm/aspeed/aspeed.yaml           |    1 +
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1168 +++++++++++++++++
 3 files changed, 1170 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts

-- 
2.25.1



From wthai at nvidia.com  Thu Mar 20 09:46:32 2025
From: wthai at nvidia.com (Willie Thai)
Date: Thu, 20 Mar 2025 16:46:32 +0000
Subject: [PATCH v3 1/2] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <20250320164633.101331-1-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
Message-ID: <20250320164633.101331-2-wthai@nvidia.com>

The GB200NVL BMC is an Aspeed Ast2600 based BMC
for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Rob Herring <robh at kernel.org>
Cc: Paul Menzel <pmenzel at molgen.mpg.de>
Link: https://www.aspeedtech.com/server_ast2600/ [1]
Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes v1 -> v2:
  - Fix the SOB name [Krzysztof]
  - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
  - Fix DTS coding style [Krzysztof]
  - Move pinctrl override to the bottom [Krzysztof]
  - Drop bootargs [Krzysztof]
  - Follow DTS coding style and change naming for leds node [Krzysztof]
  - Change flash 0 status property [Krzysztof]
  - Change the phy-mode to rgmii [Andrew]
  - Remove the max-speed in mac0 [Andrew]
  - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
Changes v2 -> v3:
  - Fix missing new line [Krzysztof]
  - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
  - Fix DTS coding style [Krzysztof]
  - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
  - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
  - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
---
---
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1168 +++++++++++++++++
 2 files changed, 1169 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..20fd357a1ee9 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-bmc-lenovo-hr630.dtb \
 	aspeed-bmc-lenovo-hr855xg2.dtb \
 	aspeed-bmc-microsoft-olympus.dtb \
+	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
 	aspeed-bmc-opp-lanyang.dtb \
 	aspeed-bmc-opp-mowgli.dtb \
 	aspeed-bmc-opp-nicole.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
new file mode 100644
index 000000000000..0370a7b25181
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
@@ -0,0 +1,1168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "AST2600 GB200NVL BMC";
+	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";
+
+	aliases {
+		serial2 = &uart3;
+		serial4 = &uart5;
+		i2c16   = &imux16;
+		i2c17   = &imux17;
+		i2c18   = &imux18;
+		i2c19   = &imux19;
+		i2c20   = &imux20;
+		i2c21   = &imux21;
+		i2c22   = &imux22;
+		i2c23   = &imux23;
+		i2c24   = &imux24;
+		i2c25   = &imux25;
+		i2c26   = &imux26;
+		i2c27   = &imux27;
+		i2c28   = &imux28;
+		i2c29   = &imux29;
+		i2c30   = &imux30;
+		i2c31   = &imux31;
+		i2c32   = &imux32;
+		i2c33   = &imux33;
+		i2c34   = &imux34;
+		i2c35   = &imux35;
+		i2c36   = &imux36;
+		i2c37   = &imux37;
+		i2c38   = &imux38;
+		i2c39   = &imux39;
+		i2c40	= &e1si2c0;
+		i2c41	= &e1si2c1;
+		i2c42	= &e1si2c2;
+		i2c43	= &e1si2c3;
+		i2c44	= &e1si2c4;
+		i2c45	= &e1si2c5;
+		i2c46	= &e1si2c6;
+		i2c47	= &e1si2c7;
+		i2c48	= &i2c17mux0;
+		i2c49	= &i2c17mux1;
+		i2c50	= &i2c17mux2;
+		i2c51	= &i2c17mux3;
+		i2c52	= &i2c25mux0;
+		i2c53	= &i2c25mux1;
+		i2c54	= &i2c25mux2;
+		i2c55	= &i2c25mux3;
+		i2c56	= &i2c29mux0;
+		i2c57	= &i2c29mux1;
+		i2c58	= &i2c29mux2;
+		i2c59	= &i2c29mux3;
+	};
+
+	chosen {
+		stdout-path = &uart5;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vga_memory: framebuffer at 9f000000 {
+			no-map;
+			reg = <0x9f000000 0x01000000>; /* 16M */
+		};
+
+		ramoops at a0000000 {
+			compatible = "ramoops";
+			reg = <0xa0000000 0x100000>; /* 1MB */
+			record-size = <0x10000>; /* 64KB */
+			max-reason = <2>; /* KMSG_DUMP_OOPS */
+		};
+
+		gfx_memory: framebuffer {
+			size = <0x01000000>;
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+
+		video_engine_memory: jpegbuffer {
+			size = <0x02000000>;	/* 32M */
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led-0 {
+			label = "uid_led";
+			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
+		};
+		led-1 {
+			label = "fault_led";
+			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
+		};
+		led-2 {
+			label = "power_led";
+			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
+		};
+
+	};
+
+	buttons {
+		button-power {
+			label = "power-btn";
+			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
+		};
+		button-uid {
+			label = "uid-btn";
+			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+};
+
+// Enable Primary flash on FMC for bring up activity
+&fmc {
+	status = "okay";
+	flash at 0 {
+		status = "okay";
+		compatible = "jedec,spi-nor";
+		label = "bmc";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot at 0 {
+				// 896KB
+				reg = <0x0 0xe0000>;
+				label = "u-boot";
+			};
+
+			kernel at 100000 {
+				// 9MB
+				reg = <0x100000 0x900000>;
+				label = "kernel";
+			};
+
+			rofs at a00000 {
+				// 55292KB (extends to end of 64MB SPI - 4KB)
+				reg = <0xa00000 0x35FF000>;
+				label = "rofs";
+			};
+		};
+	};
+};
+
+&spi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi2_default>;
+
+	// Data SPI is 64MB in size
+	flash at 0 {
+		status = "okay";
+		label = "config";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot-env at 0 {
+				// 256KB
+				reg = <0x0 0x40000>;
+				label = "u-boot-env";
+			};
+
+			rwfs at 40000 {
+				// 16MB
+				reg = <0x40000 0x1000000>;
+				label = "rwfs";
+			};
+
+			log at 1040000 {
+				// 40MB
+				reg = <0x1040000 0x2800000>;
+				label = "log";
+			};
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart3 {
+	// Enabling SOL
+	status = "okay";
+};
+
+&uart5 {
+	// BMC Debug Console
+	status = "okay";
+};
+
+&uart_routing {
+	status = "okay";
+};
+
+&mac2 {
+	status = "okay";
+	phy-mode = "rmii";
+	use-ncsi;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii3_default>;
+};
+
+// Enable emmc
+&emmc_controller {
+	status = "okay";
+};
+
+&emmc {
+	non-removable;
+	pinctrl-0 = <&pinctrl_emmcg5_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	clk-phase-mmc-hs200 = <9>, <225>;
+};
+
+/*
+ * Enable USB port A as device (via the virtual hub) to host
+ */
+&vhub {
+	status = "okay";
+	pinctrl-names = "default";
+	/*
+	 * Uncomment below line to enable internal EHCI controller
+	 * Current config uses xHCI Port1
+	 */
+};
+
+&video {
+	status = "okay";
+	memory-region = <&video_engine_memory>;
+};
+
+// USB 2.0 to HMC, on USB Port B
+&ehci1 {
+	status = "okay";
+};
+
+// USB 1.0
+&uhci {
+	status = "okay";
+};
+
+&sgpiom0 {
+	status="okay";
+	ngpios = <128>;
+	gpio-line-names =
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RUN_POWER_FAULT_L-I","SYS_RST_IN_L-O",
+		"RUN_POWER_PG-I","PWR_BRAKE_L-O",
+		"SYS_RST_OUT_L-I","RUN_POWER_EN-O",
+		"L0L1_RST_REQ_OUT_L-I","SHDN_FORCE_L-O",
+		"L2_RST_REQ_OUT_L-I","SHDN_REQ_L-O",
+		"SHDN_OK_L-I","UID_LED_N-O",
+		"BMC_I2C1_FPGA_ALERT_L-I","SYS_FAULT_LED_N-O",
+		"BMC_I2C0_FPGA_ALERT_L-I","PWR_LED_N-O",
+		"FPGA_RSVD_FFU3-I","",
+		"FPGA_RSVD_FFU2-I","",
+		"FPGA_RSVD_FFU1-I","",
+		"FPGA_RSVD_FFU0-I","BMC_I2C_SSIF_ALERT_L-O",
+		"CPU_BOOT_DONE-I","JTAG_MUX_SELECT-O",
+		"SPI_BMC_FPGA_INT_L-I","RTC_CLR_L-O",
+		"THERM_BB_WARN_L-I","UART_MUX_SEL-O",
+		"THERM_BB_OVERT_L-I","",
+		"CPU0_UPHY3_PRSNT1_L-I","IOBRD0_RUN_POWER_EN-O",
+		"CPU0_UPHY3_PRSNT0_L-I","IOBRD1_RUN_POWER_EN-O",
+		"CPU0_UPHY2_PRSNT1_L-I","FPGA_RSVD_FFU4-O",
+		"CPU0_UPHY2_PRSNT0_L-I","FPGA_RSVD_FFU5-O",
+		"CPU0_UPHY1_PRSNT1_L-I","FPGA_RSVD_FFU6-O",
+		"CPU0_UPHY1_PRSNT0_L-I","FPGA_RSVD_FFU7-O",
+		"CPU0_UPHY0_PRSNT1_L-I","RSVD_NV_PLT_DETECT-O",
+		"CPU0_UPHY0_PRSNT0_L-I","SPI1_INT_L-O",
+		"CPU1_UPHY3_PRSNT1_L-I","",
+		"CPU1_UPHY3_PRSNT0_L-I","HMC_EROT_MUX_STATUS",
+		"CPU1_UPHY2_PRSNT1_L-I","",
+		"CPU1_UPHY2_PRSNT0_L-I","",
+		"CPU1_UPHY1_PRSNT1_L-I","",
+		"CPU1_UPHY1_PRSNT0_L-I","",
+		"CPU1_UPHY0_PRSNT1_L-I","",
+		"CPU1_UPHY0_PRSNT0_L-I","",
+		"FAN1_PRESENT_L-I","",
+		"FAN0_PRESENT_L-I","",
+		"","",
+		"IPEX_CABLE_PRSNT_L-I","",
+		"M2_1_PRSNT_L-I","",
+		"M2_0_PRSNT_L-I","",
+		"CPU1_UPHY4_PRSNT1_L-I","",
+		"CPU0_UPHY4_PRSNT0_L-I","",
+		"","",
+		"I2C_RTC_ALERT_L-I","",
+		"FAN7_PRESENT_L-I","",
+		"FAN6_PRESENT_L-I","",
+		"FAN5_PRESENT_L-I","",
+		"FAN4_PRESENT_L-I","",
+		"FAN3_PRESENT_L-I","",
+		"FAN2_PRESENT_L-I","",
+		"IOBRD0_IOX_INT_L-I","",
+		"IOBRD1_PRSNT_L-I","",
+		"IOBRD0_PRSNT_L-I","",
+		"IOBRD1_PWR_GOOD-I","",
+		"IOBRD0_PWR_GOOD-I","",
+		"","",
+		"","",
+		"FAN_FAIL_IN_L-I","",
+		"","",
+		"","",
+		"","",
+		"PDB_CABLE_PRESENT_L-I","",
+		"","",
+		"CHASSIS_PWR_BRK_L-I","",
+		"","",
+		"IOBRD1_IOX_INT_L-I","",
+		"10GBE_SMBALRT_L-I","",
+		"PCIE_WAKE_L-I","",
+		"I2C_M21_ALERT_L-I","",
+		"I2C_M20_ALERT_L-I","",
+		"TRAY_FAST_SHDN_L-I","",
+		"UID_BTN_N-I","",
+		"PWR_BTN_L-I","",
+		"PSU_SMB_ALERT_L-I","",
+		"","",
+		"","",
+		"NODE_LOC_ID[0]-I","",
+		"NODE_LOC_ID[1]-I","",
+		"NODE_LOC_ID[2]-I","",
+		"NODE_LOC_ID[3]-I","",
+		"NODE_LOC_ID[4]-I","",
+		"NODE_LOC_ID[5]-I","",
+		"FAN10_PRESENT_L-I","",
+		"FAN9_PRESENT_L-I","",
+		"FAN8_PRESENT_L-I","",
+		"FPGA1_READY_HMC-I","",
+		"DP_HPD-I","",
+		"HMC_I2C3_FPGA_ALERT_L-I","",
+		"HMC_I2C2_FPGA_ALERT_L-I","",
+		"FPGA0_READY_HMC-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"LEAK_DETECT_ALERT_L-I","",
+		"MOD1_B2B_CABLE_PRESENT_L-I","",
+		"MOD1_CLINK_CABLE_PRESENT_L-I","",
+		"FAN11_PRESENT_L-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RSVD_SGPIO_IN_CRC[0]","RSVD_SGPIO_O_CRC[7]",
+		"RSVD_SGPIO_IN_CRC[1]","RSVD_SGPIO_O_CRC[6]",
+		"RSVD_SGPIO_IN_CRC[2]","RSVD_SGPIO_O_CRC[5]",
+		"RSVD_SGPIO_IN_CRC[3]","RSVD_SGPIO_O_CRC[4]",
+		"RSVD_SGPIO_IN_CRC[4]","RSVD_SGPIO_O_CRC[3]",
+		"RSVD_SGPIO_IN_CRC[5]","RSVD_SGPIO_O_CRC[2]",
+		"RSVD_SGPIO_IN_CRC[6]","RSVD_SGPIO_O_CRC[1]",
+		"RSVD_SGPIO_IN_CRC[7]","RSVD_SGPIO_O_CRC[0]";
+};
+
+// I2C1, SSIF IPMI interface
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	disable-master = <1>;
+	ssif-bmc at 10 {
+		compatible = "ssif-bmc";
+		reg = <0x10>;
+	};
+};
+
+// I2C2
+// BMC_I2C1_FPGA - Secondary FPGA
+// HMC EROT
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C3
+// BMC_I2C0_FPGA - Primary FPGA
+// HMC FRU EEPROM
+&i2c2 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C4
+&i2c3 {
+	status = "disabled";
+};
+
+// I2C5
+// RTC Driver
+// IO Expander
+&i2c4 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// Module 0, Expander @0x21
+	exp4: gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"RTC_MUX_SEL-O",
+			"PCI_MUX_SEL-O",
+			"TPM_MUX_SEL-O",
+			"FAN_MUX-SEL-O",
+			"SGMII_MUX_SEL-O",
+			"DP_MUX_SEL-O",
+			"UPHY3_USB_SEL-O",
+			"NCSI_MUX_SEL-O",
+			"BMC_PHY_RST-O",
+			"RTC_CLR_L-O",
+			"BMC_12V_CTRL-O",
+			"PS_RUN_IO0_PG-I",
+			"",
+			"",
+			"",
+			"";
+	};
+};
+
+// I2C6
+// Module 0/1 I2C MUX x3
+&i2c5 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+
+	i2c-mux at 71 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+		i2c-mux-idle-disconnect;
+
+		imux16: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux17: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c17mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c17mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c17mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c17mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux18: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux19: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 72 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x72>;
+		i2c-mux-idle-disconnect;
+
+		imux20: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux21: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				gpio-line-names =
+					"RST_CX_0_L-O",
+					"RST_CX_1_L-O",
+					"CX0_SSD0_PRSNT_L-I",
+					"CX1_SSD1_PRSNT_L-I",
+					"CX_BOOT_CMPLT_CX0-I",
+					"CX_BOOT_CMPLT_CX1-I",
+					"CX_TWARN_CX0_L-I",
+					"CX_TWARN_CX1_L-I",
+					"CX_OVT_SHDN_CX0-I",
+					"CX_OVT_SHDN_CX1-I",
+					"FNP_L_CX0-O",
+					"FNP_L_CX1-O",
+					"",
+					"MCU_GPIO-I",
+					"MCU_RST_N-O",
+					"MCU_RECOVERY_N-O";
+			};
+		};
+
+		imux22: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux23: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 73 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x73>;
+		i2c-mux-idle-disconnect;
+
+		imux24: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux25: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 70 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x70>;
+				i2c-mux-idle-disconnect;
+
+				i2c25mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c25mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c25mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c25mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux26: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux27: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 75 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		i2c-mux-idle-disconnect;
+
+		imux28: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux29: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c29mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c29mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c29mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c29mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux30: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux31: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 76 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x76>;
+		i2c-mux-idle-disconnect;
+
+		imux32: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux33: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				gpio-line-names =
+					"SEC_RST_CX_0_L-O",
+					"SEC_RST_CX_1_L-O",
+					"SEC_CX0_SSD0_PRSNT_L-I",
+					"SEC_CX1_SSD1_PRSNT_L-I",
+					"SEC_CX_BOOT_CMPLT_CX0-I",
+					"SEC_CX_BOOT_CMPLT_CX1-I",
+					"SEC_CX_TWARN_CX0_L-I",
+					"SEC_CX_TWARN_CX1_L-I",
+					"SEC_CX_OVT_SHDN_CX0-I",
+					"SEC_CX_OVT_SHDN_CX1-I",
+					"SEC_FNP_L_CX0-O",
+					"SEC_FNP_L_CX1-O",
+					"",
+					"SEC_MCU_GPIO-I",
+					"SEC_MCU_RST_N-O",
+					"SEC_MCU_RECOVERY_N-O";
+				};
+		};
+
+		imux34: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux35: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		imux36: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux37: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		imux38: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux39: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C7
+// Module 0/1 Leak Sensors
+// Module 0/1 Fan Controllers
+&i2c6 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pmic at 12 {
+		compatible = "ti,lm5066i";
+		reg = <0x12>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+	pmic at 14 {
+		compatible = "ti,lm5066i";
+		reg = <0x14>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+	pwm at 20 {
+		compatible = "maxim,max31790";
+		reg = <0x20>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	pwm at 23 {
+		compatible = "maxim,max31790";
+		reg = <0x23>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	pwm at 2c {
+		compatible = "maxim,max31790";
+		reg = <0x2c>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+	pwm at 2f {
+		compatible = "maxim,max31790";
+		reg = <0x2f>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+};
+
+// I2C9
+// M.2
+&i2c8 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C10
+// HMC IO Expander
+// Module 0/1 IO Expanders
+&i2c9 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// Module 0, Expander @0x20
+	exp0: gpio at 20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"FPGA_THERM_OVERT_L-I",
+			"FPGA_READY_BMC-I",
+			"HMC_BMC_DETECT-O",
+			"HMC_PGOOD-O",
+			"",
+			"BMC_STBY_CYCLE-O",
+			"FPGA_EROT_FATAL_ERROR_L-I",
+			"WP_HW_EXT_CTRL_L-O",
+			"EROT_FPGA_RST_L-O",
+			"FPGA_EROT_RECOVERY_L-O",
+			"BMC_EROT_FPGA_SPI_MUX_SEL-O",
+			"USB_HUB_RESET_L-O",
+			"NCSI_CS1_SEL-O",
+			"SGPIO_EN_L-O",
+			"B2B_IOEXP_INT_L-I",
+			"I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// Module 1, Expander @0x21
+	exp1: gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"SEC_FPGA_THERM_OVERT_L-I",
+			"SEC_FPGA_READY_BMC-I",
+			"",
+			"",
+			"",
+			"",
+			"SEC_FPGA_EROT_FATAL_ERROR_L-I",
+			"SEC_WP_HW_EXT_CTRL_L-O",
+			"SEC_EROT_FPGA_RST_L-O",
+			"SEC_FPGA_EROT_RECOVERY_L-O",
+			"SEC_BMC_EROT_FPGA_SPI_MUX_SEL-O",
+			"SEC_USB2_HUB_RST_L-O",
+			"",
+			"",
+			"",
+			"SEC_I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// HMC Expander @0x27
+	exp2: gpio at 27 {
+		compatible = "nxp,pca9555";
+		reg = <0x27>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"HMC_PRSNT_L-I",
+			"HMC_READY-I",
+			"HMC_EROT_FATAL_ERROR_L-I",
+			"I2C_MUX_SEL-O",
+			"HMC_EROT_SPI_MUX_SEL-O",
+			"HMC_EROT_RECOVERY_L-O",
+			"HMC_EROT_RST_L-O",
+			"GLOBAL_WP_HMC-O",
+			"FPGA_RST_L-O",
+			"USB2_HUB_RST-O",
+			"CPU_UART_MUX_SEL-O",
+			"",
+			"",
+			"",
+			"",
+			"";
+	};
+	// HMC Expander @0x74
+	exp3: gpio at 74 {
+		compatible = "nxp,pca9555";
+		reg = <0x74>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"IOB_PRSNT_L",
+			"IOB_DP_HPD",
+			"IOX_BMC_RESET",
+			"IOB_IOEXP_INT_L",
+			"IOB_UID_LED_L",
+			"IOB_UID_BTN_L",
+			"IOB_SYS_RST_BTN_L",
+			"IOB_PWR_LED_L",
+			"IOB_PWR_BTN_L",
+			"IOB_PHY_RST",
+			"CPLD_JTAG_MUX_SEL",
+			"",
+			"",
+			"",
+			"",
+			"";
+	};
+};
+
+// I2C11
+// BMC FRU EEPROM
+// BMC Temp Sensor
+&i2c10 {
+	status = "okay";
+	clock-frequency = <400000>;
+	// BMC FRU EEPROM - 256 bytes
+	eeprom at 50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <8>;
+	};
+};
+
+// I2C12
+&i2c11 {
+	status = "disabled";
+};
+
+// I2C13
+&i2c12 {
+	status = "disabled";
+};
+
+// I2C14
+// Module 0 UPHY3 SMBus
+&i2c13 {
+	status = "disabled";
+};
+
+// I2C15
+// Module 1 UPHY3 SMBus
+&i2c14 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+
+	//E1.S drive slot 0-3
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C16
+&i2c15 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+
+	//E1.S drive slot 4-7
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c4: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c5: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c6: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c7: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+&rng {
+	status = "okay";
+};
+
+&gpio0 {
+	gpio-line-names =
+		/*A0-A7*/ "", "", "", "", "", "", "", "",
+		/*B0-B7*/ "", "", "", "", "", "", "", "",
+		/*C0-C7*/ "SGPIO_I2C_MUX_SEL-O", "", "", "", "", "", "", "",
+		/*D0-D7*/ "", "", "", "UART1_MUX_SEL-O", "", "FPGA_PEX_RST_L-O", "", "",
+		/*E0-E7*/ "RTL8221_PHY_RST_L-O", "RTL8211_PHY_INT_L-I",	"", "UART3_MUX_SEL-O",
+					"", "", "", "SGPIO_BMC_EN-O",
+		/*F0-F7*/ "", "", "", "", "", "", "", "",
+		/*G0-G7*/ "", "", "", "", "", "", "", "",
+		/*H0-H7*/ "", "", "", "", "", "", "", "",
+		/*I0-I7*/ "", "", "", "", "", "QSPI2_RST_L-O", "GLOBAL_WP_BMC-O", "BMC_DDR4_TEN-O",
+		/*J0-J7*/ "", "", "", "", "", "", "", "",
+		/*K0-K7*/ "", "", "", "", "", "", "", "",
+		/*L0-L7*/ "", "", "", "", "", "", "", "",
+		/*M0-M7*/ "PCIE_EP_RST_EN-O", "BMC_FRU_WP-O", "HMC_RESET_L-O", "STBY_POWER_EN-O",
+					"STBY_POWER_PG-I", "PCIE_EP_RST_L-O", "", "",
+		/*N0-N7*/ "", "", "", "", "", "", "", "",
+		/*O0-O7*/ "", "", "", "", "", "", "", "",
+		/*P0-P7*/ "", "", "", "", "", "", "", "",
+		/*Q0-Q7*/ "", "", "", "", "", "", "", "",
+		/*R0-R7*/ "", "", "", "", "", "", "", "",
+		/*S0-S7*/ "", "", "", "", "", "", "", "",
+		/*T0-T7*/ "", "", "", "", "", "", "", "",
+		/*U0-U7*/ "", "", "", "", "", "", "", "",
+		/*V0-V7*/ "AP_EROT_REQ-O", "EROT_AP_GNT-I", "", "","PCB_TEMP_ALERT-I", "","", "",
+		/*W0-W7*/ "", "", "", "", "", "", "", "",
+		/*X0-X7*/ "", "", "TPM_MUX_SEL-O", "", "", "", "", "",
+		/*Y0-Y7*/ "", "", "", "EMMC_RST-O", "","", "", "",
+		/*Z0-Z7*/ "BMC_READY-O","", "", "", "", "", "", "";
+};
+
+&gpio1 {
+	/* 36 1.8V GPIOs */
+	gpio-line-names =
+		/*A0-A7*/ "", "", "", "", "", "", "", "",
+		/*B0-B7*/ "", "", "", "", "", "", "IO_EXPANDER_INT_L-I","",
+		/*C0-C7*/ "", "", "", "", "", "", "", "",
+		/*D0-D7*/ "", "", "", "", "", "", "SPI_HOST_TPM_RST_L-O", "SPI_BMC_FPGA_INT_L-I",
+		/*E0-E7*/ "", "", "", "", "", "", "", "";
+};
+
+// EMMC group that excludes WP pin
+&pinctrl {
+	pinctrl_emmcg5_default: emmcg5_default {
+		function = "EMMC";
+		groups = "EMMCG5";
+	};
+};
-- 
2.25.1



From andrew at lunn.ch  Thu Mar 20 09:54:59 2025
From: andrew at lunn.ch (Andrew Lunn)
Date: Thu, 20 Mar 2025 17:54:59 +0100
Subject: [PATCH v3 1/2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250320164633.101331-2-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
 <20250320164633.101331-2-wthai@nvidia.com>
Message-ID: <fbf6a89b-80c4-47f3-9dad-2725c040e041@lunn.ch>

>   - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]

For this part only:

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

    Andrew


From andersson at kernel.org  Thu Mar 20 09:56:37 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Thu, 20 Mar 2025 11:56:37 -0500
Subject: [GIT PULL] Qualcomm Arm64 DeviceTree updates for v6.15
In-Reply-To: <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>
References: <20250317215921.2031880-1-andersson@kernel.org>
 <a2132f78-f113-460a-b7ea-022a39e4e64b@app.fastmail.com>
Message-ID: <i7x76sr4njtoijtte453b7bhubiirpot3hzck7j6umyjhmay5h@ui77ajauxmzc>

On Wed, Mar 19, 2025 at 10:10:31PM +0100, Arnd Bergmann wrote:
> On Mon, Mar 17, 2025, at 22:59, Bjorn Andersson wrote:
> >
> > Krzysztof Kozlowski (17):
> >       arm64: dts: qcom: sa8775p: Partially revert "arm64: dts: qcom: 
> > sa8775p: add QCrypto nodes"
> >       arm64: dts: qcom: qcs8300: Partially revert "arm64: dts: qcom: 
> > qcs8300: add QCrypto nodes"
> >       arm64: dts: qcom: x1e80100-slim7x: Drop incorrect 
> > qcom,ath12k-calibration-variant
> >       arm64: dts: qcom: msm8998: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: qrb2210-rb1: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: qrb4210-rb2: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sc7180: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sdm845: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sda660-ifc6560: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sm6115: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sm8150-hdk: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: qcm6490: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sa8775p-ride: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sc8280xp: Switch to undeprecated 
> > qcom,calibration-variant
> >       arm64: dts: qcom: sm8250-elish: Switch to undeprecated 
> > qcom,calibration-variant
> 
> This seeems to remove the properties that the drivers expect
> even in 6.14-rc7, so the branch is currently broken and I'll
> skip it for 6.15. Let's see how we should handle this properly
> in the next cycle, since it's too late now to fix it.
> 

Sorry about that. I didn't spot the comment(s) that these patches
shouldn't be merged until v6.16.

I think for this case it's okay not to provide more forwards
compatibility than a single release, so picking them up then should be
fine.

Regards,
Bjorn


From miko.lenczewski at arm.com  Thu Mar 20 10:06:10 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 20 Mar 2025 17:06:10 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <CAMj1kXFOofRCiVHxxxBZMGQHRH-ghtqNxgd=uww9D4sr4vvjEQ@mail.gmail.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
 <CAMj1kXFOofRCiVHxxxBZMGQHRH-ghtqNxgd=uww9D4sr4vvjEQ@mail.gmail.com>
Message-ID: <20250320170610.GA487465@e133081.arm.com>

On Thu, Mar 20, 2025 at 02:37:08PM +0100, Ard Biesheuvel wrote:
> On Wed, 19 Mar 2025 at 16:06, Miko?aj Lenczewski
> <miko.lenczewski at arm.com> wrote:
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index d561cf3b8ac7..1a4adcda267b 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
> >         return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
> >  }
> >
> > +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> > +{
> 
> We generally start these block comments with just /* on the first line

My bad for the oversight. Will fix this, thanks.

-- 
Kind regards,
Miko?aj Lenczewski


From miko.lenczewski at arm.com  Thu Mar 20 10:09:36 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 20 Mar 2025 17:09:36 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <f9c5839e-5d55-497e-9df3-ab778c4eae72@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
 <f9c5839e-5d55-497e-9df3-ab778c4eae72@arm.com>
Message-ID: <20250320170936.GB487465@e133081.arm.com>

On Thu, Mar 20, 2025 at 01:24:25PM +0000, Suzuki K Poulose wrote:
> On 19/03/2025 15:05, Miko?aj Lenczewski wrote:
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > index fb8752b42ec8..3e4cc917a07e 100644
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -453,6 +453,9 @@
> >   	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
> >   			32 bit applications.
> > +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> > +			2 support
> > +
> >   	arm64.nobti	[ARM64] Unconditionally disable Branch Target
> >   			Identification support
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 940343beb3d4..49deda2b22ae 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
> >   	  The feature introduces new assembly instructions, and they were
> >   	  support when binutils >= 2.30.
> > +config ARM64_BBML2_NOABORT
> > +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
> > +	default y
> > +	help
> > +	  FEAT_BBM provides detection of support levels for break-before-make
> > +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
> > +	  can be relaxed to improve performance. We additonally require the
> > +	  property that the implementation cannot ever raise TLB Conflict Aborts.
> > +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
> > +	  even if the system supports BBM level 2.
> 
> minor nit: Should we mention that the feature can be disabled at runtime
> using a kernel parameter ?

Yes, this sounds very reasonable, I should have thought of that. Will
mention the commandline parameter in the kconfig option documentation.

> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index d561cf3b8ac7..1a4adcda267b 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
> >   	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
> >   }
> > +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
> > +{
> > +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
> > +	 * as possible. This list is therefore an allow-list of known-good
> > +	 * implementations that both support bbml2 and additionally, fulfill the
> > +	 * extra constraint of never generating TLB conflict aborts when using
> > +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
> > +	 * kernel contexts difficult to prove safe against recursive aborts).
> > +	 *
> > +	 * Note that implementations can only be considered "known-good" if their
> > +	 * implementors attest to the fact that the implementation never raises
> > +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
> > +	 */
> > +	static const struct midr_range supports_bbml2_noabort_list[] = {
> > +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
> > +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
> > +		{}
> > +	};
> > +
> > +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
> > +}
> > +
> > +static inline unsigned int cpu_read_midr(int cpu)
> > +{
> > +	WARN_ON_ONCE(!cpu_online(cpu));
> > +
> > +	return per_cpu(cpu_data, cpu).reg_midr;
> > +}
> > +
> > +static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
> > +{
> > +	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
> > +		return false;
> > +
> > +	if (scope & SCOPE_SYSTEM) {
> > +		int cpu;
> > +
> > +		/* We are a boot CPU, and must verify that all enumerated boot
> 
> minor nit: See Documentation/process/coding-style.rst,
> Section 8 Commenting.

My bad, had skimmed the coding style at one point but clearly missed or
forgot the section on comments. Will fix up this and all other instances
of the same issue.

-- 
Kind regards,
Miko?aj Lenczewski


From suzuki.poulose at arm.com  Thu Mar 20 10:11:25 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Thu, 20 Mar 2025 17:11:25 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250320170936.GB487465@e133081.arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
 <f9c5839e-5d55-497e-9df3-ab778c4eae72@arm.com>
 <20250320170936.GB487465@e133081.arm.com>
Message-ID: <952cc3ea-ca11-43a3-a8f4-36e3bbb1fa84@arm.com>

On 20/03/2025 17:09, Miko?aj Lenczewski wrote:
> On Thu, Mar 20, 2025 at 01:24:25PM +0000, Suzuki K Poulose wrote:
>> On 19/03/2025 15:05, Miko?aj Lenczewski wrote:
>>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>>> index fb8752b42ec8..3e4cc917a07e 100644
>>> --- a/Documentation/admin-guide/kernel-parameters.txt
>>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>>> @@ -453,6 +453,9 @@
>>>    	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
>>>    			32 bit applications.
>>> +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
>>> +			2 support
>>> +
>>>    	arm64.nobti	[ARM64] Unconditionally disable Branch Target
>>>    			Identification support
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 940343beb3d4..49deda2b22ae 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
>>>    	  The feature introduces new assembly instructions, and they were
>>>    	  support when binutils >= 2.30.
>>> +config ARM64_BBML2_NOABORT
>>> +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
>>> +	default y
>>> +	help
>>> +	  FEAT_BBM provides detection of support levels for break-before-make
>>> +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
>>> +	  can be relaxed to improve performance. We additonally require the
>>> +	  property that the implementation cannot ever raise TLB Conflict Aborts.
>>> +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
>>> +	  even if the system supports BBM level 2.
>>
>> minor nit: Should we mention that the feature can be disabled at runtime
>> using a kernel parameter ?
> 
> Yes, this sounds very reasonable, I should have thought of that. Will
> mention the commandline parameter in the kconfig option documentation.

And also may be mention this in the patch description and may be also
add the rationale for providing this tunable.

Cheers
Suzuki


> 
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index d561cf3b8ac7..1a4adcda267b 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -2176,6 +2176,67 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
>>>    	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
>>>    }
>>> +static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
>>> +{
>>> +	/* We want to allow usage of bbml2 in as wide a range of kernel contexts
>>> +	 * as possible. This list is therefore an allow-list of known-good
>>> +	 * implementations that both support bbml2 and additionally, fulfill the
>>> +	 * extra constraint of never generating TLB conflict aborts when using
>>> +	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
>>> +	 * kernel contexts difficult to prove safe against recursive aborts).
>>> +	 *
>>> +	 * Note that implementations can only be considered "known-good" if their
>>> +	 * implementors attest to the fact that the implementation never raises
>>> +	 * TLBI conflict aborts for bbml2 mapping granularity changes.
>>> +	 */
>>> +	static const struct midr_range supports_bbml2_noabort_list[] = {
>>> +		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
>>> +		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
>>> +		{}
>>> +	};
>>> +
>>> +	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
>>> +}
>>> +
>>> +static inline unsigned int cpu_read_midr(int cpu)
>>> +{
>>> +	WARN_ON_ONCE(!cpu_online(cpu));
>>> +
>>> +	return per_cpu(cpu_data, cpu).reg_midr;
>>> +}
>>> +
>>> +static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
>>> +{
>>> +	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
>>> +		return false;
>>> +
>>> +	if (scope & SCOPE_SYSTEM) {
>>> +		int cpu;
>>> +
>>> +		/* We are a boot CPU, and must verify that all enumerated boot
>>
>> minor nit: See Documentation/process/coding-style.rst,
>> Section 8 Commenting.
> 
> My bad, had skimmed the coding style at one point but clearly missed or
> forgot the section on comments. Will fix up this and all other instances
> of the same issue.
> 



From herve.codina at bootlin.com  Thu Mar 20 10:15:08 2025
From: herve.codina at bootlin.com (Herve Codina)
Date: Thu, 20 Mar 2025 18:15:08 +0100
Subject: [PATCH v2 06/57] irqdomain: irqchip: Switch to
 of_fwnode_handle()
In-Reply-To: <20250319092951.37667-7-jirislaby@kernel.org>
References: <20250319092951.37667-1-jirislaby@kernel.org>
	<20250319092951.37667-7-jirislaby@kernel.org>
Message-ID: <20250320181508.132c4636@bootlin.com>

Hi Jiri,

On Wed, 19 Mar 2025 10:28:59 +0100
"Jiri Slaby (SUSE)" <jirislaby at kernel.org> wrote:

> of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
> defined of_fwnode_handle(). The former is in the process of being
> removed, so use the latter instead.
> 
> Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>

Reviewed-by: Herve Codina <herve.codina at bootlin.com>
Acked-by: Herve Codina <herve.codina at bootlin.com> # irq-lan966x-oic

Best regards,
Herv?


From changyuanl at google.com  Thu Mar 20 10:15:45 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Thu, 20 Mar 2025 10:15:45 -0700
Subject: [PATCH v5 02/16] mm/mm_init: rename init_reserved_page to init_deferred_page
In-Reply-To: <16b14662-d69b-478a-9e2f-a05c56f2c4ce@kernel.org>
References: <16b14662-d69b-478a-9e2f-a05c56f2c4ce@kernel.org>
Message-ID: <20250320171545.2324955-1-changyuanl@google.com>

Hi Krzysztof,

On Thu, Mar 20, 2025 at 08:10:48 +0100, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> On 20/03/2025 02:55, Changyuan Lyu wrote:
> > From: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> >
> > When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, init_reserved_page()
> > function performs initialization of a struct page that would have been
> > deferred normally.
> >
> > Rename it to init_deferred_page() to better reflect what the function does.
> >
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>

Signed-off-by: Changyuan Lyu <changyuanl at google.com>

>
> Incorrect DCO chain.
>

Thanks for the reminder! I missed "Signed-off-by" in a few patches from
Mike and Alex where I did not make any changes. I will fix them in the
next version.

Best,
Changyuan


From song at kernel.org  Thu Mar 20 10:15:57 2025
From: song at kernel.org (Song Liu)
Date: Thu, 20 Mar 2025 10:15:57 -0700
Subject: [PATCH v3 0/2] arm64: livepatch: Enable livepatch without sframe
Message-ID: <20250320171559.3423224-1-song@kernel.org>

There are recent efforts to enable livepatch for arm64, with sframe [1] or
without sframe [2]. This set tries to enable livepatch without sframe. Some
of the code, however, are from [1].

Although the sframe implementation is more promising in longer term, it
suffers from the following issues:

  1. sframe is not yet supported in llvm;
  2. There is still bug in binutil [3], so that we cannot yet use sframe
     with gcc;
  3. sframe unwinder hasn't been fully verified in the kernel.

On the other hand, arm64 processors have become more and more important in
the data center world. Therefore, it is getting critical to support
livepatching of arm64 kernels.

With recent change in arm64 unwinder [4], it is possible to reliably
livepatch arm64 kernels without sframe. This is because we do not need
arch_stack_walk_reliable() to get reliable stack trace in all scenarios.
Instead, we only need arch_stack_walk_reliable() to detect when the
stack trace is not reliable, then the livepatch logic can retry the patch
transition at a later time.

Given the increasing need of livepatching, and relatively long time before
sframe is fully ready (for both gcc and clang), we would like to enable
livepatch without sframe.

Thanks!

[1] https://lore.kernel.org/live-patching/20250127213310.2496133-1-wnliu at google.com/
[2] https://lore.kernel.org/live-patching/20250129232936.1795412-1-song at kernel.org/
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=32589
[4] https://lore.kernel.org/linux-arm-kernel/20241017092538.1859841-1-mark.rutland at arm.com/

Changes v2 => v3:
1. Remove a redundant check for -ENOENT. (Josh Poimboeuf)
2. Add Tested-by and Acked-by on v1. (I forgot to add them in v2.)

v2: https://lore.kernel.org/live-patching/20250319213707.1784775-1-song at kernel.org/

Changes v1 => v2:

1. Rework arch_stack_walk_reliable().

v1: https://lore.kernel.org/live-patching/20250308012742.3208215-1-song at kernel.org/

Song Liu (2):
  arm64: Implement arch_stack_walk_reliable
  arm64: Implement HAVE_LIVEPATCH

 arch/arm64/Kconfig                   |  3 ++
 arch/arm64/include/asm/thread_info.h |  4 +-
 arch/arm64/kernel/entry-common.c     |  4 ++
 arch/arm64/kernel/stacktrace.c       | 66 +++++++++++++++++++++-------
 4 files changed, 60 insertions(+), 17 deletions(-)

--
2.47.1


From song at kernel.org  Thu Mar 20 10:15:58 2025
From: song at kernel.org (Song Liu)
Date: Thu, 20 Mar 2025 10:15:58 -0700
Subject: [PATCH v3 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250320171559.3423224-1-song@kernel.org>
References: <20250320171559.3423224-1-song@kernel.org>
Message-ID: <20250320171559.3423224-2-song@kernel.org>

With proper exception boundary detection, it is possible to implment
arch_stack_walk_reliable without sframe.

Note that, arch_stack_walk_reliable does not guarantee getting reliable
stack in all scenarios. Instead, it can reliably detect when the stack
trace is not reliable, which is enough to provide reliable livepatching.

Signed-off-by: Song Liu <song at kernel.org>
---
 arch/arm64/Kconfig             |  2 +-
 arch/arm64/kernel/stacktrace.c | 66 +++++++++++++++++++++++++---------
 2 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 701d980ea921..31d5e1ee6089 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -276,6 +276,7 @@ config ARM64
 	select HAVE_SOFTIRQ_ON_OWN_STACK
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
+	select HAVE_RELIABLE_STACKTRACE
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2500,4 +2501,3 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
-
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 1d9d51d7627f..7e07911d8694 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -56,6 +56,7 @@ struct kunwind_state {
 	enum kunwind_source source;
 	union unwind_flags flags;
 	struct pt_regs *regs;
+	bool end_on_unreliable;
 };
 
 static __always_inline void
@@ -230,8 +231,26 @@ kunwind_next_frame_record(struct kunwind_state *state)
 	new_fp = READ_ONCE(record->fp);
 	new_pc = READ_ONCE(record->lr);
 
-	if (!new_fp && !new_pc)
-		return kunwind_next_frame_record_meta(state);
+	if (!new_fp && !new_pc) {
+		int ret;
+
+		ret = kunwind_next_frame_record_meta(state);
+		if (ret < 0) {
+			/*
+			 * This covers two different conditions:
+			 *  1. ret == -ENOENT, unwinding is done.
+			 *  2. ret == -EINVAL, unwinding hit error.
+			 */
+			return ret;
+		}
+		/*
+		 * Searching across exception boundaries. The stack is now
+		 * unreliable.
+		 */
+		if (state->end_on_unreliable)
+			return -EINVAL;
+		return 0;
+	}
 
 	unwind_consume_stack(&state->common, info, fp, sizeof(*record));
 
@@ -277,21 +296,24 @@ kunwind_next(struct kunwind_state *state)
 
 typedef bool (*kunwind_consume_fn)(const struct kunwind_state *state, void *cookie);
 
-static __always_inline void
+static __always_inline int
 do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 	   void *cookie)
 {
-	if (kunwind_recover_return_address(state))
-		return;
+	int ret;
 
-	while (1) {
-		int ret;
+	ret = kunwind_recover_return_address(state);
+	if (ret)
+		return ret;
 
+	while (1) {
 		if (!consume_state(state, cookie))
-			break;
+			return -EINVAL;
 		ret = kunwind_next(state);
+		if (ret == -ENOENT)
+			return 0;
 		if (ret < 0)
-			break;
+			return ret;
 	}
 }
 
@@ -324,10 +346,10 @@ do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
 			: stackinfo_get_unknown();		\
 	})
 
-static __always_inline void
+static __always_inline int
 kunwind_stack_walk(kunwind_consume_fn consume_state,
 		   void *cookie, struct task_struct *task,
-		   struct pt_regs *regs)
+		   struct pt_regs *regs, bool end_on_unreliable)
 {
 	struct stack_info stacks[] = {
 		stackinfo_get_task(task),
@@ -348,11 +370,12 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 			.stacks = stacks,
 			.nr_stacks = ARRAY_SIZE(stacks),
 		},
+		.end_on_unreliable = end_on_unreliable,
 	};
 
 	if (regs) {
 		if (task != current)
-			return;
+			return -EINVAL;
 		kunwind_init_from_regs(&state, regs);
 	} else if (task == current) {
 		kunwind_init_from_caller(&state);
@@ -360,7 +383,7 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 		kunwind_init_from_task(&state, task);
 	}
 
-	do_kunwind(&state, consume_state, cookie);
+	return do_kunwind(&state, consume_state, cookie);
 }
 
 struct kunwind_consume_entry_data {
@@ -384,7 +407,18 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 		.cookie = cookie,
 	};
 
-	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
+	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs, false);
+}
+
+noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
+			void *cookie, struct task_struct *task)
+{
+	struct kunwind_consume_entry_data data = {
+		.consume_entry = consume_entry,
+		.cookie = cookie,
+	};
+
+	return kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, NULL, true);
 }
 
 struct bpf_unwind_consume_entry_data {
@@ -409,7 +443,7 @@ noinline noinstr void arch_bpf_stack_walk(bool (*consume_entry)(void *cookie, u6
 		.cookie = cookie,
 	};
 
-	kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL);
+	kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL, false);
 }
 
 static const char *state_source_string(const struct kunwind_state *state)
@@ -456,7 +490,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
 		return;
 
 	printk("%sCall trace:\n", loglvl);
-	kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs);
+	kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs, false);
 
 	put_task_stack(tsk);
 }
-- 
2.47.1



From song at kernel.org  Thu Mar 20 10:15:59 2025
From: song at kernel.org (Song Liu)
Date: Thu, 20 Mar 2025 10:15:59 -0700
Subject: [PATCH v3 2/2] arm64: Implement HAVE_LIVEPATCH
In-Reply-To: <20250320171559.3423224-1-song@kernel.org>
References: <20250320171559.3423224-1-song@kernel.org>
Message-ID: <20250320171559.3423224-3-song@kernel.org>

This is largely based on [1] by Suraj Jitindar Singh.

Test coverage:

- Passed manual tests with samples/livepatch.
- Passed all but test-kprobe.sh in selftests/livepatch.
  test-kprobe.sh is expected to fail, because arm64 doesn't have
  KPROBES_ON_FTRACE.
- Passed tests with kpatch-build [2]. (This version includes commits that
  are not merged to upstream kpatch yet).

[1] https://lore.kernel.org/all/20210604235930.603-1-surajjs at amazon.com/
[2] https://github.com/liu-song-6/kpatch/tree/fb-6.13
Cc: Suraj Jitindar Singh <surajjs at amazon.com>
Cc: Torsten Duwe <duwe at suse.de>
Signed-off-by: Song Liu <song at kernel.org>
Acked-by: Miroslav Benes <mbenes at suse.cz>
Tested-by: Breno Leitao <leitao at debian.org>
---
 arch/arm64/Kconfig                   | 3 +++
 arch/arm64/include/asm/thread_info.h | 4 +++-
 arch/arm64/kernel/entry-common.c     | 4 ++++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 31d5e1ee6089..dbd237b13b21 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -277,6 +277,7 @@ config ARM64
 	select USER_STACKTRACE_SUPPORT
 	select VDSO_GETRANDOM
 	select HAVE_RELIABLE_STACKTRACE
+	select HAVE_LIVEPATCH
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -2501,3 +2502,5 @@ endmenu # "CPU Power Management"
 source "drivers/acpi/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
+
+source "kernel/livepatch/Kconfig"
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 1114c1c3300a..4ac42e13032b 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -64,6 +64,7 @@ void arch_setup_new_exec(void);
 #define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
 #define TIF_MTE_ASYNC_FAULT	5	/* MTE Asynchronous Tag Check Fault */
 #define TIF_NOTIFY_SIGNAL	6	/* signal notifications exist */
+#define TIF_PATCH_PENDING	7	/* pending live patching update */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing */
 #define TIF_SYSCALL_TRACEPOINT	10	/* syscall tracepoint for ftrace */
@@ -92,6 +93,7 @@ void arch_setup_new_exec(void);
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
+#define _TIF_PATCH_PENDING	(1 << TIF_PATCH_PENDING)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
@@ -103,7 +105,7 @@ void arch_setup_new_exec(void);
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
 				 _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
-				 _TIF_NOTIFY_SIGNAL)
+				 _TIF_NOTIFY_SIGNAL | _TIF_PATCH_PENDING)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index b260ddc4d3e9..b537af333b42 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -8,6 +8,7 @@
 #include <linux/context_tracking.h>
 #include <linux/kasan.h>
 #include <linux/linkage.h>
+#include <linux/livepatch.h>
 #include <linux/lockdep.h>
 #include <linux/ptrace.h>
 #include <linux/resume_user_mode.h>
@@ -144,6 +145,9 @@ static void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 				       (void __user *)NULL, current);
 		}
 
+		if (thread_flags & _TIF_PATCH_PENDING)
+			klp_update_patch_state(current);
+
 		if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
 			do_signal(regs);
 
-- 
2.47.1



From changyuanl at google.com  Thu Mar 20 10:18:02 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Thu, 20 Mar 2025 10:18:02 -0700
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <d5f7379c-c66b-47f5-bc97-eab90ab34346@kernel.org>
References: <d5f7379c-c66b-47f5-bc97-eab90ab34346@kernel.org>
Message-ID: <20250320171802.2325561-1-changyuanl@google.com>

Hi Krzysztof,

On Thu, Mar 20, 2025 at 08:10:37 +0100, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> On 20/03/2025 02:55, Changyuan Lyu wrote:
> > From: Alexander Graf <graf at amazon.com>
> >
> > We have all generic code in place now to support Kexec with KHO. This
> > patch adds a config option that depends on architecture support to
> > enable KHO support.
> >
> > Signed-off-by: Alexander Graf <graf at amazon.com>
> > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> What did you exactly co-develop here? Few changes does not mean you are
> a co-developer.

I proposed and implemented the hashtable-based state tree API in the
previous patch "kexec: add Kexec HandOver (KHO) generation helpers" [1]
and then added `select XXHASH` here. If one line of change is not
qualified for "Co-developed-by", I will remove it from the commit message
in the next version.

[1] https://lore.kernel.org/all/20250320015551.2157511-8-changyuanl at google.com/

Best,
Changyuan


From andreyknvl at gmail.com  Thu Mar 20 10:25:04 2025
From: andreyknvl at gmail.com (Andrey Konovalov)
Date: Thu, 20 Mar 2025 18:25:04 +0100
Subject: [PATCH v2 2/2] kasan: Add strscpy() test to trigger tag fault on arm64
In-Reply-To: <20250318214035.481950-3-pcc@google.com>
References: <20250318214035.481950-1-pcc@google.com> <20250318214035.481950-3-pcc@google.com>
Message-ID: <CA+fCnZfG79JmGG9rj7KbE=9yX-EM4e8CXDSm5F9=YEmgyX5v3w@mail.gmail.com>

On Tue, Mar 18, 2025 at 10:41?PM Peter Collingbourne <pcc at google.com> wrote:
>
> From: Vincenzo Frascino <vincenzo.frascino at arm.com>
>
> When we invoke strscpy() with a maximum size of N bytes, it assumes
> that:
> - It can always read N bytes from the source.
> - It always write N bytes (zero-padded) to the destination.
>
> On aarch64 with Memory Tagging Extension enabled if we pass an N that is
> bigger then the source buffer, it triggers an MTE fault.
>
> Implement a KASAN KUnit test that triggers the issue with the current
> implementation of read_word_at_a_time() on aarch64 with MTE enabled.
>
> Cc: Will Deacon <will at kernel.org>
> Signed-off-by: Vincenzo Frascino <vincenzo.frascino at arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> Co-developed-by: Peter Collingbourne <pcc at google.com>
> Signed-off-by: Peter Collingbourne <pcc at google.com>
> Link: https://linux-review.googlesource.com/id/If88e396b9e7c058c1a4b5a252274120e77b1898a
> ---
> v2:
> - rebased
> - fixed test failure
>
>  mm/kasan/kasan_test_c.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
> index 59d673400085f..c4bb3ee497b54 100644
> --- a/mm/kasan/kasan_test_c.c
> +++ b/mm/kasan/kasan_test_c.c
> @@ -1570,7 +1570,9 @@ static void kasan_memcmp(struct kunit *test)
>  static void kasan_strings(struct kunit *test)
>  {
>         char *ptr;
> -       size_t size = 24;
> +       char *src, *src2;
> +       u8 tag;
> +       size_t size = 2 * KASAN_GRANULE_SIZE;
>
>         /*
>          * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT.
> @@ -1581,6 +1583,33 @@ static void kasan_strings(struct kunit *test)
>         ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
>         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
>
> +       src = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
> +       strscpy(src, "f0cacc1a00000000f0cacc1a00000000", size);
> +
> +       tag = get_tag(src);
> +
> +       src2 = src + KASAN_GRANULE_SIZE;
> +
> +       /*
> +        * Shorten string and poison the granule after it so that the unaligned
> +        * read in strscpy() triggers a tag mismatch.
> +        */
> +       src[KASAN_GRANULE_SIZE - 1] = '\0';
> +       kasan_poison(src2, KASAN_GRANULE_SIZE, tag + 1, false);
> +
> +       /*
> +        * The expected size does not include the terminator '\0'
> +        * so it is (KASAN_GRANULE_SIZE - 2) ==
> +        * KASAN_GRANULE_SIZE - ("initial removed character" + "\0").
> +        */
> +       KUNIT_EXPECT_EQ(test, KASAN_GRANULE_SIZE - 2,
> +                       strscpy(ptr, src + 1, size));
> +
> +       /* Undo operations above. */
> +       src[KASAN_GRANULE_SIZE - 1] = '0';
> +       kasan_poison(src2, KASAN_GRANULE_SIZE, tag, false);
> +
> +       kfree(src);

I have trouble understanding what this code is doing...

So the goal is to call strcpy with such an address, that the first 8
bytes (partially) cover 2 granules, one accessible and the other is
not?

If so, can we not do something like:

src = kmalloc(KASAN_GRANULE_SIZE, GFP_KERNEL | __GFP_ZERO);
strscpy(src, "aabbcceeddeeffg\0", size);
strscpy(ptr, src + KASAN_GRANULE_SIZE - 2, sizeof(unsigned long));

Otherwise, this code needs more explanatory comments and it's probably
better to move it out to a helper function.

>         kfree(ptr);
>
>         /*
> --
> 2.49.0.395.g12beb8f557-goog
>


From miko.lenczewski at arm.com  Thu Mar 20 10:13:47 2025
From: miko.lenczewski at arm.com (=?utf-8?Q?Miko=C5=82aj?= Lenczewski)
Date: Thu, 20 Mar 2025 17:13:47 +0000
Subject: [PATCH v4 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <952cc3ea-ca11-43a3-a8f4-36e3bbb1fa84@arm.com>
References: <20250319150533.37440-2-miko.lenczewski@arm.com>
 <20250319150533.37440-3-miko.lenczewski@arm.com>
 <f9c5839e-5d55-497e-9df3-ab778c4eae72@arm.com>
 <20250320170936.GB487465@e133081.arm.com>
 <952cc3ea-ca11-43a3-a8f4-36e3bbb1fa84@arm.com>
Message-ID: <20250320171347.GA494995@e133081.arm.com>

On Thu, Mar 20, 2025 at 05:11:25PM +0000, Suzuki K Poulose wrote:
> On 20/03/2025 17:09, Miko?aj Lenczewski wrote:
> > On Thu, Mar 20, 2025 at 01:24:25PM +0000, Suzuki K Poulose wrote:
> > > On 19/03/2025 15:05, Miko?aj Lenczewski wrote:
> > > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > > > index fb8752b42ec8..3e4cc917a07e 100644
> > > > --- a/Documentation/admin-guide/kernel-parameters.txt
> > > > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > > > @@ -453,6 +453,9 @@
> > > >    	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
> > > >    			32 bit applications.
> > > > +	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
> > > > +			2 support
> > > > +
> > > >    	arm64.nobti	[ARM64] Unconditionally disable Branch Target
> > > >    			Identification support
> > > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > > > index 940343beb3d4..49deda2b22ae 100644
> > > > --- a/arch/arm64/Kconfig
> > > > +++ b/arch/arm64/Kconfig
> > > > @@ -2057,6 +2057,17 @@ config ARM64_TLB_RANGE
> > > >    	  The feature introduces new assembly instructions, and they were
> > > >    	  support when binutils >= 2.30.
> > > > +config ARM64_BBML2_NOABORT
> > > > +	bool "Enable support for Break-Before-Make Level 2 detection and usage"
> > > > +	default y
> > > > +	help
> > > > +	  FEAT_BBM provides detection of support levels for break-before-make
> > > > +	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
> > > > +	  can be relaxed to improve performance. We additonally require the
> > > > +	  property that the implementation cannot ever raise TLB Conflict Aborts.
> > > > +	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
> > > > +	  even if the system supports BBM level 2.
> > > 
> > > minor nit: Should we mention that the feature can be disabled at runtime
> > > using a kernel parameter ?
> > 
> > Yes, this sounds very reasonable, I should have thought of that. Will
> > mention the commandline parameter in the kconfig option documentation.
> 
> And also may be mention this in the patch description and may be also
> add the rationale for providing this tunable.
> 
> Cheers
> Suzuki
> 

Will do! :)

-- 
Kind regards,
Miko?aj Lenczewski


From maz at kernel.org  Thu Mar 20 10:14:48 2025
From: maz at kernel.org (Marc Zyngier)
Date: Thu, 20 Mar 2025 17:14:48 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <ba9cd6d2-1ee5-478a-8102-42b4dac411ce@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
	<86msdhmemw.wl-maz@kernel.org>
	<cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
	<86ldt0n9w1.wl-maz@kernel.org>
	<Z9sSMJAlf7cQ5viu@linux.dev>
	<0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
	<86iko4m5i4.wl-maz@kernel.org>
	<ba9cd6d2-1ee5-478a-8102-42b4dac411ce@daynix.com>
Message-ID: <86cyebmxo7.wl-maz@kernel.org>

On Thu, 20 Mar 2025 09:52:59 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/20 18:10, Marc Zyngier wrote:
> > On Thu, 20 Mar 2025 06:03:35 +0000,
> > Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >> 
> >> On 2025/03/20 3:51, Oliver Upton wrote:
> >>> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
> >>>> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >>>>> What about setting the flag automatically when a user fails to pin
> >>>>> vCPUs to CPUs that are covered by one PMU? There would be no change if
> >>>>> a user correctly pins vCPUs as it is. Otherwise, they will see a
> >>>>> correct feature set advertised to the guest and the cycle counter
> >>>>> working.
> >>>> 
> >>>> How do you know that the affinity is "correct"? VCPU affinity can be
> >>>> changed at any time. I, for one, do not want my VMs to change
> >>>> behaviour because I let the vcpus bounce around as the scheduler sees
> >>>> fit.
> >> 
> >> Checking the affinity when picking the default PMU; the vCPU affinity
> >> is the only thing that rules the choice of the default PMU even now.
> >> 
> >> Perhaps we may model the API as follows: introduce another "composite"
> >> PMU that works on any core but only exposes the cycle counter. Robust
> >> VMMs will choose it or one of hardware PMUs with
> >> KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according
> >> to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If
> >> the affinity is covered by one hardware PMU, that PMU will be chosen
> >> as the default. The "composite" PMU will be the default otherwise.
> > 
> > This makes no sense to me. A VCPU is always affine to a PMU, because
> > we do not support configurations where only some CPUs have a PMU. This
> > is an all-or-nothing situation.
> 
> At least isn't it fine to have the composite PMU with a new value for
> KVM_ARM_VCPU_PMU_V3_SET_PMU?

Not sure KVM_ARM_VCPU_PMU_V3_SET_PMU is the right hook (it takes a PMU
'type', which is under control of the perf subsystem). But if we can
find a value that is guaranteed to be unique, why not.

> > More importantly, you keep suggesting the same "new default", and I
> > keep saying NO.
> > 
> > My position is clear: if you want a *new* behaviour, you *must* add a
> > new flag that the VMM explicitly provides to enable this CC-only PMU.
> > No change in default behaviour at all.
> > 
> > I'm not going to move from that.
> 
> Why not? It will not break anything guaranteed to work in the past.

It doesn't have to be guaranteed. It just has to *exist*. That's the
Linux ABI for you.

> Currently KVM only guarantees that the emulated PMU correctly counts
> only when
> 1) the vCPU affinity is contained by one PMU and
> 2) it will not expand
> 
> Breaking these conditions will make the behavior of the emulated PMU
> undefined. Now I'm proposing to remove 1).

And I'm saying no to that. I'm also getting tired of arguing the same
point on and on.

We currently have two different behaviours:

- either you explicitly set a PMU, and the affinity of this PMU
  constraints the affinity of the vcpus. The vcpus are not allowed to
  run outside of this affinity. Everything counts all the time.

- or you don't explicitly set a PMU, and a default PMU will be picked
  from the current affinity of the first vcpu. Your vcpus will be able
  to run anywhere, but the virtual PMU will *only* count when the
  vcpus are affine to the default PMU. When the vcpus are not affine
  to default PMU, *nothing* counts.

These two behaviours are ABI. They are not changing. They don't get
relaxed, they don't get tightened, they stay just as they are,
forever.

You want a *third* behaviour, go ahead. Define it the way you want.
But the behaviours described above will stay unchanged.

I'm looking forward to your patches implementing it, but I am also
done arguing on it.

	M.

-- 
Without deviation from the norm, progress is not possible.


From linux at armlinux.org.uk  Thu Mar 20 10:27:16 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 17:27:16 +0000
Subject: suspend-to-ram resume fails on Tegra Jetson Xavier NX
Message-ID: <Z9xP9IpLD04O5KPY@shell.armlinux.org.uk>

Hi,

I'm struggling with a deadlock in the _noirq paths when resuming from
suspend-to-ram. with 6.14-rc6 (specifically net-next).

Having thrown lots of debug into kernel/power/suspend.c and
drivers/base/power/main.c, what I observe is:

1. /sys/power/pm_async is 1. If this is set to 0, then the problem does
   not manifest.

2. it seems the sync/async resume doesn't order correctly. With my own
   debugging in place, I see:

CPU5 is up
resume: suspend_enter:471
resume: dpm_resume_noirq:794
resume: dpm_noirq_resume_devices:742
 faux: PM: trying async resume (async=0)
 faux: PM:   -- will resume sync
 platform: PM: trying async resume (async=0)
 platform: PM:   -- will resume sync
 cpu: PM: trying async resume (async=0)
 cpu: PM:   -- will resume sync
cpu cpu0: PM: trying async resume (async=0)
cpu cpu0: PM:   -- will resume sync
...
tegra-bpmp bpmp: PM: trying async resume (async=0)
tegra-bpmp bpmp: PM:   -- will resume sync
platform 17000000.gpu: PM: trying async resume (async=0)
platform 17000000.gpu: PM:   -- will resume sync
platform 13e00000.host1x: PM: trying async resume (async=0)
platform 13e00000.host1x: PM:   -- will resume sync
...
tegra-bpmp-i2c bpmp:i2c: PM: trying async resume (async=0)
tegra-bpmp-i2c bpmp:i2c: PM:   -- will resume sync

*** Note - bpmp:i2c is on the dpm_noirq_list after 13e00000.host1x
and is being resumed synchronously.

i2c i2c-0: PM: trying async resume (async=1)
i2c-dev i2c-0: PM: trying async resume (async=0)
i2c i2c-0: PM: device_resume_noirq:650
i2c-dev i2c-0: PM:   -- will resume sync
max77620 0-003c: PM: trying async resume (async=1)
max77620-pinctrl max20024-pinctrl: PM: trying async resume (async=0)
max77620 0-003c: PM: device_resume_noirq:650
...
i2c i2c-0: PM: waiting for parent (bpmp:i2c)
max77620 0-003c: PM: waiting for parent (i2c-0)
...
tegra-bpmp bpmp: PM: device_resume_noirq:650
tegra-bpmp bpmp: PM: waiting for parent (platform)
tegra-bpmp bpmp: PM: parent wait finished, waiting for suppliers
tegra-bpmp bpmp: PM: waiting for supplier 2c00000.memory-controller
tegra-bpmp bpmp: PM: supplier finished
tegra-bpmp bpmp: PM: waiting for supplier 3c00000.hsp
tegra-bpmp bpmp: PM: supplier finished
tegra-bpmp bpmp: PM: suppliers finished
tegra-bpmp bpmp: PM: -- resume_noirq: tegra_bpmp_resume (sync)
tegra-bpmp bpmp: PM: -- complete
...
platform 13e00000.host1x: PM: device_resume_noirq:650
platform 13e00000.host1x: PM: waiting for parent (bus at 0)
platform 13e00000.host1x: PM: parent wait finished, waiting for suppliers
platform 13e00000.host1x: PM: waiting for supplier 2c60000.external-memory-controller
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier 2c00000.memory-controller
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier 2200000.gpio
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier bpmp
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier regulator-vdd-hdmi
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier bus at 0
platform 13e00000.host1x: PM: supplier finished
platform 13e00000.host1x: PM: waiting for supplier 0-003c

Here we die - with interrupts off, so none of the kernel lockup
detectors are functional, so without debug the console is completely
silent.

13e00000.host1x is not bound to a driver (it failed its probe), but
is being synchronously resumed. It is waiting for 0-003c to be resumed.

0-003c is being resumed asynchronously, and is waiting for i2c-0 to
be resumed.

i2c-0 is being resumed asynchronously, and is waiting for bpmp:i2c to
be resumed.

bpmp:i2c is not *yet* being resumed, because it is to be resumed
synchronously, and is on the dpm_noirq_list after 13e00000.host1x.
This results in a silently dead system on resume.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From horms at kernel.org  Thu Mar 20 10:31:54 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 20 Mar 2025 17:31:54 +0000
Subject: [net-next PATCH v12 02/13] dt-bindings: net: Document support
 for Airoha AN8855 Switch Virtual MDIO
In-Reply-To: <20250309172717.9067-3-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-3-ansuelsmth@gmail.com>
Message-ID: <20250320173154.GE892515@horms.kernel.org>

On Sun, Mar 09, 2025 at 06:26:47PM +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 Virtual MDIO Passtrough. This is needed

nit: passthrough

> as AN8855 require special handling as the same address on the MDIO bus is
> shared for both Switch and PHY and special handling for the page
> configuration is needed to switch accessing to Switch address space
> or PHY.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
> ---
>  .../bindings/net/airoha,an8855-mdio.yaml      | 56 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 57 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
> new file mode 100644
> index 000000000000..3078277bf478
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml
> @@ -0,0 +1,56 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/airoha,an8855-mdio.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 MDIO Passtrough

Ditto.

> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description:
> +  Airoha AN8855 Virtual MDIO Passtrough. This is needed as AN8855

Ditto.

> +  require special handling as the same address on the MDIO bus is
> +  shared for both Switch and PHY and special handling for the page
> +  configuration is needed to switch accessing to Switch address space
> +  or PHY.

...


From horms at kernel.org  Thu Mar 20 10:32:37 2025
From: horms at kernel.org (Simon Horman)
Date: Thu, 20 Mar 2025 17:32:37 +0000
Subject: [net-next PATCH v12 03/13] dt-bindings: net: dsa: Document
 support for Airoha AN8855 DSA Switch
In-Reply-To: <20250309172717.9067-4-ansuelsmth@gmail.com>
References: <20250309172717.9067-1-ansuelsmth@gmail.com>
 <20250309172717.9067-4-ansuelsmth@gmail.com>
Message-ID: <20250320173237.GF892515@horms.kernel.org>

On Sun, Mar 09, 2025 at 06:26:48PM +0100, Christian Marangi wrote:
> Document support for Airoha AN8855 5-port Gigabit Switch.
> 
> It does expose the 5 Internal PHYs on the MDIO bus and each port
> can access the Switch register space by configurting the PHY page.

nit: configuring

> 
> Each internal PHY might require calibration with the fused EFUSE on
> the switch exposed by the Airoha AN8855 SoC NVMEM.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../net/dsa/airoha,an8855-switch.yaml         | 105 ++++++++++++++++++
>  MAINTAINERS                                   |   1 +
>  2 files changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> new file mode 100644
> index 000000000000..63bcbebd6a29
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml
> @@ -0,0 +1,105 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/dsa/airoha,an8855-switch.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN8855 Gigabit Switch
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  Airoha AN8855 is a 5-port Gigabit Switch.
> +
> +  It does expose the 5 Internal PHYs on the MDIO bus and each port
> +  can access the Switch register space by configurting the PHY page.

Ditto.

> +
> +  Each internal PHY might require calibration with the fused EFUSE on
> +  the switch exposed by the Airoha AN8855 SoC NVMEM.

...


From wnliu at google.com  Thu Mar 20 10:46:41 2025
From: wnliu at google.com (Weinan Liu)
Date: Thu, 20 Mar 2025 17:46:41 +0000
Subject: [PATCH v3 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250320171559.3423224-2-song@kernel.org>
References: <20250320171559.3423224-2-song@kernel.org>
Message-ID: <20250320174642.855602-1-wnliu@google.com>

On Thu, Mar 20, 2025 at 10:16?AM Song Liu <song at kernel.org> wrote:
>
>  static __always_inline void
> @@ -230,8 +231,26 @@ kunwind_next_frame_record(struct kunwind_state *state)
>         new_fp = READ_ONCE(record->fp);
>         new_pc = READ_ONCE(record->lr);
>
> -       if (!new_fp && !new_pc)
> -               return kunwind_next_frame_record_meta(state);
> +       if (!new_fp && !new_pc) {
> +               int ret;
> +
> +               ret = kunwind_next_frame_record_meta(state);

The exception case kunwind_next_regs_pc() will return 0 when unwind success.
Should we return a different value for the success case of kunwind_next_regs_pc()?


> +               if (ret < 0) {
> +                       /*
> +                        * This covers two different conditions:
> +                        *  1. ret == -ENOENT, unwinding is done.
> +                        *  2. ret == -EINVAL, unwinding hit error.
> +                        */
> +                       return ret;
> +               }
> +               /*
> +                * Searching across exception boundaries. The stack is now
> +                * unreliable.
> +                */
> +               if (state->end_on_unreliable)
> +                       return -EINVAL;
> +               return 0;
> +       }



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:12 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:12 +0000
Subject: [RFC PATCH 0/6] Cache coherency management subsystem
Message-ID: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>

Note that I've only a vague idea of who will care about this
so please do +CC others as needed.

On x86 there is the much loved WBINVD instruction that causes a write back
and invalidate of all caches in the system. It is expensive but it is
necessary in a few corner cases. These are cases where the contents of
Physical Memory may change without any writes from the host. Whilst there
are a few reasons this might happen, the one I care about here is when
we are adding or removing mappings on CXL. So typically going from
there being actual memory at a host Physical Address to nothing there
(reads as zero, writes dropped) or visa-versa. That involves the
reprogramming of address decoders (HDM Decoders); in the near future
it may also include the device offering dynamic capacity extents. The
thing that makes it very hard to handle with CPU flushes is that the
instructions are normally VA based and not guaranteed to reach beyond
the Point of Coherence or similar. You might be able to (ab)use
various flush operations intended to ensure persistence memory but
in general they don't work either.

So on other architectures such as ARM64 we have no instruction similar to
WBINVD but we may have device interfaces in the system that provide a way
to ensure a PA range undergoes the write back and invalidate action. This
RFC is to find a way to support those cache maintenance device interfaces.
The ones I know about are much more flexible than WBINVD, allowing
invalidation of particular PA ranges, or a much richer set of flush types
(not supported yet as not needed for upstream use cases).

To illustrate how a solution might work, I've taken both a HiSilicon
design (slight quirk as registers overlap with existing PMU driver)
and more controversially a firmware interface proposal from ARM
(wrapped up in made up ACPI) that was dropped from the released spec
but for which the alpha spec is still available.

Why drivers/cache?
- Mainly because it exists and smells like a reasonable place.
- Conor, you are maintainer for this currently do you mind us putting this
  stuff in there?

Why not just register a singleton function pointer?
- Systems may include multiple cache control devices, responsible
  for different parts of the PA address range (interleaving etc make
  this complex).  They may not all share a common hardware interface.
- A device class is more convenient than managing multiple homogeneous
  device instances within a driver.
- Disadvantage is that we need this small class

Generalizing to more arch?
- I've started with ARM64, but if useful elsewhere the small amount
  of arch code could be moved to a generic location.

QEMU emulation code at
http://gitlab.com/jic23/qemu cxl-2025-03-20 

Why an RFC?
- I'm really just looking for feedback on whether the class approach
  is the way to go at this stage.  I'm not strongly attached to it but
  it feels like the right balance of complexity and flexibility to me.
- I made up the ACPI spec - it's not documented, non official and
  honestly needs work. I would however like to get feedback on whether
  it is something we want to try and get through the ACPI Working group
  as a much improved code first proposal?  The potential justification
  being to avoid the need for lots trivial drivers where maybe a bit
  of DSDT interpreted code does the job better.

Jonathan Cameron (3):
  cache: coherency device class
  acpi: PoC of Cache control via ACPI0019 and _DSM
  Hack: Pretend we have PSCI 1.2

Yicong Yang (3):
  memregion: Support fine grained invalidate by
    cpu_cache_invalidate_memregion()
  arm64: Support ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
  cache: Support cache maintenance for HiSilicon SoC Hydra Home Agent

 arch/arm64/Kconfig                  |   1 +
 arch/arm64/include/asm/cacheflush.h |  14 ++
 arch/arm64/mm/flush.c               |  42 ++++++
 arch/x86/mm/pat/set_memory.c        |   2 +-
 drivers/acpi/Makefile               |   1 +
 drivers/cache/Kconfig               |  26 ++++
 drivers/cache/Makefile              |   4 +
 drivers/cache/acpi_cache_control.c  | 157 ++++++++++++++++++++++
 drivers/cache/coherency_core.c      | 130 +++++++++++++++++++
 drivers/cache/hisi_soc_hha.c        | 193 ++++++++++++++++++++++++++++
 drivers/cxl/core/region.c           |   6 +-
 drivers/firmware/psci/psci.c        |   2 +
 drivers/nvdimm/region.c             |   3 +-
 drivers/nvdimm/region_devs.c        |   3 +-
 include/linux/cache_coherency.h     |  60 +++++++++
 include/linux/memregion.h           |   8 +-
 16 files changed, 646 insertions(+), 6 deletions(-)
 create mode 100644 drivers/cache/acpi_cache_control.c
 create mode 100644 drivers/cache/coherency_core.c
 create mode 100644 drivers/cache/hisi_soc_hha.c
 create mode 100644 include/linux/cache_coherency.h

-- 
2.43.0



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:13 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:13 +0000
Subject: [RFC PATCH 1/6] memregion: Support fine grained invalidate by cpu_cache_invalidate_memregion()
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-2-Jonathan.Cameron@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Extend cpu_cache_invalidate_memregion() to support invalidate certain
range of memory. Control of types of invalidation is left for when
usecases turn up. For now everything is Clean and Invalidate.

Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 arch/x86/mm/pat/set_memory.c | 2 +-
 drivers/cxl/core/region.c    | 6 +++++-
 drivers/nvdimm/region.c      | 3 ++-
 drivers/nvdimm/region_devs.c | 3 ++-
 include/linux/memregion.h    | 8 ++++++--
 5 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index ef4514d64c05..5d2adec1b0d4 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -354,7 +354,7 @@ bool cpu_cache_has_invalidate_memregion(void)
 }
 EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, "DEVMEM");
 
-int cpu_cache_invalidate_memregion(int res_desc)
+int cpu_cache_invalidate_memregion(int res_desc, phys_addr_t start, size_t len)
 {
 	if (WARN_ON_ONCE(!cpu_cache_has_invalidate_memregion()))
 		return -ENXIO;
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index e8d11a988fd9..6d1c9eee4cd9 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -238,7 +238,11 @@ static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
 		}
 	}
 
-	cpu_cache_invalidate_memregion(IORES_DESC_CXL);
+	if (!cxlr->params.res)
+		return -ENXIO;
+	cpu_cache_invalidate_memregion(IORES_DESC_CXL,
+				       cxlr->params.res->start,
+				       resource_size(cxlr->params.res));
 	return 0;
 }
 
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c
index 88dc062af5f8..033e40f4dc52 100644
--- a/drivers/nvdimm/region.c
+++ b/drivers/nvdimm/region.c
@@ -110,7 +110,8 @@ static void nd_region_remove(struct device *dev)
 	 * here is ok.
 	 */
 	if (cpu_cache_has_invalidate_memregion())
-		cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY);
+		cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY,
+					       0, -1);
 }
 
 static int child_notify(struct device *dev, void *data)
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 37417ce5ec7b..eefd294a0f13 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -90,7 +90,8 @@ static int nd_region_invalidate_memregion(struct nd_region *nd_region)
 		}
 	}
 
-	cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY);
+	cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY,
+				       0, -1);
 out:
 	for (i = 0; i < nd_region->ndr_mappings; i++) {
 		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
diff --git a/include/linux/memregion.h b/include/linux/memregion.h
index c01321467789..91d088ee3695 100644
--- a/include/linux/memregion.h
+++ b/include/linux/memregion.h
@@ -28,6 +28,9 @@ static inline void memregion_free(int id)
  * cpu_cache_invalidate_memregion - drop any CPU cached data for
  *     memregions described by @res_desc
  * @res_desc: one of the IORES_DESC_* types
+ * @start: start physical address of the target memory region.
+ * @len: length of the target memory region. -1 for all the regions of
+ *       the target type.
  *
  * Perform cache maintenance after a memory event / operation that
  * changes the contents of physical memory in a cache-incoherent manner.
@@ -46,7 +49,7 @@ static inline void memregion_free(int id)
  * the cache maintenance.
  */
 #ifdef CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
-int cpu_cache_invalidate_memregion(int res_desc);
+int cpu_cache_invalidate_memregion(int res_desc, phys_addr_t start, size_t len);
 bool cpu_cache_has_invalidate_memregion(void);
 #else
 static inline bool cpu_cache_has_invalidate_memregion(void)
@@ -54,7 +57,8 @@ static inline bool cpu_cache_has_invalidate_memregion(void)
 	return false;
 }
 
-static inline int cpu_cache_invalidate_memregion(int res_desc)
+static inline int cpu_cache_invalidate_memregion(int res_desc,
+						 phys_addr_t start, size_t len)
 {
 	WARN_ON_ONCE("CPU cache invalidation required");
 	return -ENXIO;
-- 
2.43.0



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:14 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:14 +0000
Subject: [RFC PATCH 2/6] arm64: Support ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-3-Jonathan.Cameron@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION provides the mechanism for
invalidate certain memory regions in a cache-incoherent manner.
Currently is used by NVIDMM and CXL memory. This is mainly done
by the system component and is implementation define per spec.
Provides a method for the platforms register their own invalidate
method and implement ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION.

Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
---
 arch/arm64/Kconfig                  |  1 +
 arch/arm64/include/asm/cacheflush.h | 14 ++++++++++
 arch/arm64/mm/flush.c               | 42 +++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..11ecd20ec3b8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -21,6 +21,7 @@ config ARM64
 	select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
 	select ARCH_HAS_CACHE_LINE_SIZE
 	select ARCH_HAS_CC_PLATFORM
+	select ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
 	select ARCH_HAS_CRC32
 	select ARCH_HAS_CRC_T10DIF if KERNEL_MODE_NEON
 	select ARCH_HAS_CURRENT_STACK_POINTER
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 28ab96e808ef..b8eb8738c965 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -139,6 +139,20 @@ static __always_inline void icache_inval_all_pou(void)
 	dsb(ish);
 }
 
+#ifdef CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
+
+#include <linux/memregion.h>
+
+struct system_cache_flush_method {
+	int (*invalidate_memregion)(int res_desc,
+				    phys_addr_t start, size_t len);
+};
+
+void arm64_set_sys_cache_flush_method(const struct system_cache_flush_method *method);
+void arm64_clr_sys_cache_flush_method(const struct system_cache_flush_method *method);
+
+#endif /* CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION */
+
 #include <asm-generic/cacheflush.h>
 
 #endif /* __ASM_CACHEFLUSH_H */
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index 013eead9b695..d822406d925d 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/libnvdimm.h>
 #include <linux/pagemap.h>
+#include <linux/memregion.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
@@ -100,3 +101,44 @@ void arch_invalidate_pmem(void *addr, size_t size)
 }
 EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
 #endif
+
+#ifdef CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
+
+static const struct system_cache_flush_method *scfm_data;
+DEFINE_SPINLOCK(scfm_lock);
+
+void arm64_set_sys_cache_flush_method(const struct system_cache_flush_method *method)
+{
+	guard(spinlock_irqsave)(&scfm_lock);
+	if (scfm_data || !method || !method->invalidate_memregion)
+		return;
+
+	scfm_data = method;
+}
+EXPORT_SYMBOL_GPL(arm64_set_sys_cache_flush_method);
+
+void arm64_clr_sys_cache_flush_method(const struct system_cache_flush_method *method)
+{
+	guard(spinlock_irqsave)(&scfm_lock);
+	if (scfm_data && scfm_data == method)
+		scfm_data = NULL;
+}
+
+int cpu_cache_invalidate_memregion(int res_desc, phys_addr_t start, size_t len)
+{
+	guard(spinlock_irqsave)(&scfm_lock);
+	if (!scfm_data)
+		return -EOPNOTSUPP;
+
+	return scfm_data->invalidate_memregion(res_desc, start, len);
+}
+EXPORT_SYMBOL_NS_GPL(cpu_cache_invalidate_memregion, "DEVMEM");
+
+bool cpu_cache_has_invalidate_memregion(void)
+{
+	guard(spinlock_irqsave)(&scfm_lock);
+	return !!scfm_data;
+}
+EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, "DEVMEM");
+
+#endif /* CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION */
-- 
2.43.0



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:15 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:15 +0000
Subject: [RFC PATCH 3/6] cache: coherency device class
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-4-Jonathan.Cameron@huawei.com>

Some systems contain devices that are capable of issuing certain cache
invalidation messages to all components in the system.  A typical use
is when the memory backing a physical address is being changed, such
as when a region is configured for CXL or a dynamic capacity event
occurs.

These perform a similar action to the WBINVD instruction on x86 but
may provide finer granularity and/or a richer set of actions.

Add a tiny device class to which drivers may register. Each driver
provides an ops structure and the first op is Write Back and Invalidate
by PA Range. The driver may over invalidate.

An optional completion check is also provided. If present that should
be called to ensure that the action has finished.

If multiple agents are present in the system each should register
with this class and the core code will issue the invalidate to all
of them before checking for completion on each. This is done
to avoid need for filtering in the core code which can become complex
when interleave, potentially across different cache coherency hardware,
is going on, so it is easier to tell everyone and let those who don't
care do nothing.

RFC question:
1. Location.  Conor, do you mind us putting this in drivers/cache?
   I'm more than happy to add a maintainers entry and not make this
   your problem!
2. Need to figure out if all agents have turned up yet?  No idea how
   to ensure this.
3. Is just iterating over devices registered with the class the
   simplest solution?
4. Given we have a nice device class, to which we can add sysfs
   attributes, what info might be useful to userspace? It might
   be useful to indicate how expensive a flush might be for example
   or where in the topology of the system it is being triggered?

Signed-off-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
---
 drivers/cache/Kconfig           |   6 ++
 drivers/cache/Makefile          |   2 +
 drivers/cache/coherency_core.c  | 130 ++++++++++++++++++++++++++++++++
 include/linux/cache_coherency.h |  60 +++++++++++++++
 4 files changed, 198 insertions(+)

diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index db51386c663a..45dc4b2935e7 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -1,6 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
 menu "Cache Drivers"
 
+config CACHE_COHERENCY_CLASS
+	bool "Cache coherency control class"
+	help
+	  Class to which coherency control drivers register allowing core kernel
+	  subsystems to issue invalidations and similar coherency operations.
+
 config AX45MP_L2_CACHE
 	bool "Andes Technology AX45MP L2 Cache controller"
 	depends on RISCV
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index 55c5e851034d..b72b20f4248f 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -3,3 +3,5 @@
 obj-$(CONFIG_AX45MP_L2_CACHE)		+= ax45mp_cache.o
 obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
 obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
+
+obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o
diff --git a/drivers/cache/coherency_core.c b/drivers/cache/coherency_core.c
new file mode 100644
index 000000000000..52cb4ceae00c
--- /dev/null
+++ b/drivers/cache/coherency_core.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Class to manage OS controlled coherency agents within the system.
+ * Specifically to enable operations such as write back and invalidate.
+ *
+ * Copyright: Huawei 2025
+ * Some elements based on fwctl class as an example of a modern
+ * lightweight class.
+ */
+
+#include <linux/cache_coherency.h>
+#include <linux/container_of.h>
+#include <linux/idr.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+
+static DEFINE_IDA(cache_coherency_ida);
+
+static void cache_coherency_device_release(struct device *device)
+{
+	struct cache_coherency_device *ccd =
+		container_of(device, struct cache_coherency_device, dev);
+
+	ida_free(&cache_coherency_ida, ccd->id);
+}
+
+static struct class cache_coherency_class = {
+	.name = "cache_coherency",
+	.dev_release = cache_coherency_device_release,
+};
+
+static int cache_inval_one(struct device *dev, void *data)
+{
+	struct cache_coherency_device *ccd =
+		container_of(dev, struct cache_coherency_device, dev);
+
+	if (!ccd->ops)
+		return -EINVAL;
+
+	return ccd->ops->wbinv(ccd, data);
+}
+
+static int cache_inval_done_one(struct device *dev, void *data)
+{
+	struct cache_coherency_device *ccd =
+		container_of(dev, struct cache_coherency_device, dev);
+	if (!ccd->ops)
+		return -EINVAL;
+
+	return ccd->ops->done(ccd);
+}
+
+static int cache_invalidate_memregion(int res_desc,
+				      phys_addr_t addr, size_t size)
+{
+	int ret;
+	struct cc_inval_params params = {
+		.addr = addr,
+		.size = size,
+	};
+
+	ret = class_for_each_device(&cache_coherency_class, NULL, &params,
+				    cache_inval_one);
+	if (ret)
+		return ret;
+
+	return class_for_each_device(&cache_coherency_class, NULL, NULL,
+				     cache_inval_done_one);
+}
+
+static const struct system_cache_flush_method cache_flush_method = {
+	.invalidate_memregion = cache_invalidate_memregion,
+};
+
+struct cache_coherency_device *
+_cache_coherency_alloc_device(struct device *parent,
+			      const struct coherency_ops *ops, size_t size)
+{
+
+	if (!ops || !ops->wbinv)
+		return NULL;
+
+	struct cache_coherency_device *ccd __free(kfree) = kzalloc(size, GFP_KERNEL);
+
+	if (!ccd)
+		return NULL;
+
+	ccd->dev.class = &cache_coherency_class;
+	ccd->dev.parent = parent;
+	ccd->ops = ops;
+	ccd->id = ida_alloc(&cache_coherency_ida, GFP_KERNEL);
+
+	if (dev_set_name(&ccd->dev, "cache_coherency%d", ccd->id))
+		return NULL;
+
+ 	device_initialize(&ccd->dev);
+
+	return_ptr(ccd);
+}
+EXPORT_SYMBOL_NS_GPL(_cache_coherency_alloc_device, "CACHE_COHERENCY");
+
+int cache_coherency_device_register(struct cache_coherency_device *ccd)
+{
+	return device_add(&ccd->dev);
+}
+EXPORT_SYMBOL_NS_GPL(cache_coherency_device_register, "CACHE_COHERENCY");
+
+void cache_coherency_device_unregister(struct cache_coherency_device *ccd)
+{
+	device_del(&ccd->dev);
+}
+EXPORT_SYMBOL_NS_GPL(cache_coherency_device_unregister, "CACHE_COHERENCY");
+
+static int __init cache_coherency_init(void)
+{
+	int ret;
+
+	ret = class_register(&cache_coherency_class);
+	if (ret)
+		return ret;
+
+	//TODO: generalize
+	arm64_set_sys_cache_flush_method(&cache_flush_method);
+
+	return 0;
+}
+subsys_initcall(cache_coherency_init);
diff --git a/include/linux/cache_coherency.h b/include/linux/cache_coherency.h
new file mode 100644
index 000000000000..d49be27ad4f1
--- /dev/null
+++ b/include/linux/cache_coherency.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Cache coherency device drivers
+ *
+ * Copyright Huawei 2025
+ */
+#ifndef _LINUX_CACHE_COHERENCY_H_
+#define _LINUX_CACHE_COHERENCY_H_
+
+#include <linux/cleanup.h>
+#include <linux/device.h>
+
+struct cache_coherency_device;
+struct cc_inval_params {
+	phys_addr_t addr;
+	size_t size;
+};
+struct coherency_ops {
+	int (*wbinv)(struct cache_coherency_device *ccd, struct cc_inval_params *invp);
+	int (*done)(struct cache_coherency_device *ccd);
+};
+
+struct cache_coherency_device {
+	struct device dev;
+	const struct coherency_ops *ops;
+	int id;
+};
+
+int cache_coherency_device_register(struct cache_coherency_device *ccd);
+void cache_coherency_device_unregister(struct cache_coherency_device *ccd);
+
+struct cache_coherency_device *
+_cache_coherency_alloc_device(struct device *parent,
+			      const struct coherency_ops *ops, size_t size);
+
+#define cache_coherency_alloc_device(parent, ops, drv_struct, member)		\
+	({									\
+		static_assert(__same_type(struct cache_coherency_device,	\
+					  ((drv_struct *)NULL)->member));	\
+		static_assert(offsetof(drv_struct, member) == 0);		\
+		(drv_struct *)_cache_coherency_alloc_device(parent, ops,	\
+							sizeof(drv_struct));	\
+	})
+
+static inline struct cache_coherency_device *
+	cache_coherency_device_get(struct cache_coherency_device *ccd)
+{
+	get_device(&ccd->dev);
+	return ccd;
+}
+
+static inline void cache_coherency_device_put(struct cache_coherency_device *ccd)
+{
+	put_device(&ccd->dev);
+}
+
+DEFINE_FREE(cache_coherency_device, struct cache_coherency_device *,
+	    if (_T) cache_coherency_device_put(_T));
+
+#endif
-- 
2.43.0



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:16 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:16 +0000
Subject: [RFC PATCH 4/6] cache: Support cache maintenance for HiSilicon SoC Hydra Home Agent
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-5-Jonathan.Cameron@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Hydra Home Agent is a device used for maintain cache coherency, add
support of cache maintenance operations for it.

Same as HiSilicon L3 cache and L3 cache PMU, memory resource of HHA
conflicts with that of HHA PMU.  Same workaround is implemented here to
workaround resource conflict check.

Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Co-developed-by: Yushan Wang <wangyushan12 at huawei.com>
Signed-off-by: Yushan Wang <wangyushan12 at huawei.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
---
 drivers/cache/Kconfig        |  12 +++
 drivers/cache/Makefile       |   1 +
 drivers/cache/hisi_soc_hha.c | 193 +++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+)

diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 45dc4b2935e7..6dab014bc581 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -6,6 +6,18 @@ config CACHE_COHERENCY_CLASS
 	help
 	  Class to which coherency control drivers register allowing core kernel
 	  subsystems to issue invalidations and similar coherency operations.
+if CACHE_COHERENCY_CLASS
+
+config HISI_SOC_HHA
+	tristate "HiSilicon Hydra Home Agent (HHA) device driver"
+	depends on ARM64 && ACPI || COMPILE_TEST
+	help
+	  The Hydra Home Agent (HHA) is responsible of cache coherency
+	  on SoC. This drivers provides cache maintenance functions of HHA.
+
+	  This driver can be built as a module. If so, the module will be
+	  called hisi_soc_hha.
+endif
 
 config AX45MP_L2_CACHE
 	bool "Andes Technology AX45MP L2 Cache controller"
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index b72b20f4248f..48b319984b45 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
 obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
 
 obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o
+obj-$(CONFIG_HISI_SOC_HHA)		+= hisi_soc_hha.o
diff --git a/drivers/cache/hisi_soc_hha.c b/drivers/cache/hisi_soc_hha.c
new file mode 100644
index 000000000000..c2af06e5839e
--- /dev/null
+++ b/drivers/cache/hisi_soc_hha.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for HiSilicon Hydra Home Agent (HHA).
+ *
+ * Copyright (c) 2024 HiSilicon Technologies Co., Ltd.
+ * Author: Yicong Yang <yangyicong at hisilicon.com>
+ *         Yushan Wang <wangyushan12 at huawei.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitfield.h>
+#include <linux/cacheflush.h>
+#include <linux/cache_coherency.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/memregion.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#define HISI_HHA_CTRL		0x5004
+#define   HISI_HHA_CTRL_EN	BIT(0)
+#define   HISI_HHA_CTRL_RANGE	BIT(1)
+#define   HISI_HHA_CTRL_TYPE	GENMASK(3, 2)
+#define HISI_HHA_START_L	0x5008
+#define HISI_HHA_START_H	0x500c
+#define HISI_HHA_LEN_L		0x5010
+#define HISI_HHA_LEN_H		0x5014
+
+/* The maintain operation performs in a 128 Byte granularity */
+#define HISI_HHA_MAINT_ALIGN	128
+
+#define HISI_HHA_POLL_GAP_US		10
+#define HISI_HHA_POLL_TIMEOUT_US	50000
+
+struct hisi_soc_hha {
+	struct cache_coherency_device ccd;
+	/* Locks HHA instance to forbid overlapping access. */
+	spinlock_t lock;
+	void __iomem *base;
+};
+
+static bool hisi_hha_cache_maintain_wait_finished(struct hisi_soc_hha *soc_hha)
+{
+	u32 val;
+
+	return !readl_poll_timeout_atomic(soc_hha->base + HISI_HHA_CTRL, val,
+					  !(val & HISI_HHA_CTRL_EN),
+					  HISI_HHA_POLL_GAP_US,
+					  HISI_HHA_POLL_TIMEOUT_US);
+}
+
+static int hisi_hha_cache_do_maintain(struct hisi_soc_hha *soc_hha,
+				      phys_addr_t addr, size_t size)
+{
+	int ret = 0;
+	u32 reg;
+
+	if (!size || !IS_ALIGNED(size, HISI_HHA_MAINT_ALIGN))
+		return -EINVAL;
+
+	/*
+	 * Hardware will maintain in a range of
+	 * [addr, addr + size + HISI_HHA_MAINT_ALIGN]
+	 */
+	size -= HISI_HHA_MAINT_ALIGN;
+
+	guard(spinlock)(&soc_hha->lock);
+
+	if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
+		return -EBUSY;
+
+	writel(lower_32_bits(addr), soc_hha->base + HISI_HHA_START_L);
+	writel(upper_32_bits(addr), soc_hha->base + HISI_HHA_START_H);
+	writel(lower_32_bits(size), soc_hha->base + HISI_HHA_LEN_L);
+	writel(upper_32_bits(size), soc_hha->base + HISI_HHA_LEN_H);
+
+	reg = FIELD_PREP(HISI_HHA_CTRL_TYPE, 1); /* Clean Invalid */
+	reg |= HISI_HHA_CTRL_RANGE | HISI_HHA_CTRL_EN;
+	writel(reg, soc_hha->base + HISI_HHA_CTRL);
+
+	return ret;
+}
+
+static int hisi_hha_cache_poll_maintain_done(struct hisi_soc_hha *soc_hha,
+					     phys_addr_t addr, size_t size)
+{
+	guard(spinlock)(&soc_hha->lock);
+
+	if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int hisi_soc_hha_wbinv(struct cache_coherency_device *ccd, struct cc_inval_params *invp)
+{
+	struct hisi_soc_hha *hha = container_of(ccd, struct hisi_soc_hha, ccd);
+
+	return hisi_hha_cache_do_maintain(hha, invp->addr, invp->size);
+}
+
+static int hisi_soc_hha_done(struct cache_coherency_device *ccd)
+{
+	struct hisi_soc_hha *hha = container_of(ccd, struct hisi_soc_hha, ccd);
+
+	return hisi_hha_cache_poll_maintain_done(hha, 0, 0);
+}
+
+static const struct coherency_ops hha_ops = {
+	.wbinv = hisi_soc_hha_wbinv,
+	.done = hisi_soc_hha_done,
+};
+
+DEFINE_FREE(hisi_soc_hha, struct hisi_soc_hha *, if (_T) cache_coherency_device_put(&_T->ccd))
+static int hisi_soc_hha_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+
+	struct hisi_soc_hha *soc_hha __free(hisi_soc_hha) =
+		cache_coherency_alloc_device(&pdev->dev, &hha_ops,
+					     struct hisi_soc_hha, ccd);
+	if (!soc_hha)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, soc_hha);
+
+	spin_lock_init(&soc_hha->lock);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	/*
+	 * HHA cache driver share the same register region with HHA uncore PMU
+	 * driver in hardware's perspective, none of them should reserve the
+	 * resource to itself only.  Here exclusive access verification is
+	 * avoided by calling devm_ioremap instead of devm_ioremap_resource to
+	 * allow both drivers to exist at the same time.
+	 */
+	soc_hha->base = ioremap(mem->start, resource_size(mem));
+	if (IS_ERR_OR_NULL(soc_hha->base)) {
+		return dev_err_probe(&pdev->dev, PTR_ERR(soc_hha->base),
+				     "failed to remap io memory");
+	}
+
+	ret = cache_coherency_device_register(&soc_hha->ccd);
+	if (ret) {
+		iounmap(soc_hha->base);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, no_free_ptr(soc_hha));
+	return 0;
+}
+
+static void hisi_soc_hha_remove(struct platform_device *pdev)
+{
+	struct hisi_soc_hha *soc_hha = platform_get_drvdata(pdev);
+
+	cache_coherency_device_unregister(&soc_hha->ccd);
+	iounmap(soc_hha->base);
+	cache_coherency_device_put(&soc_hha->ccd);
+}
+
+static const struct acpi_device_id hisi_soc_hha_ids[] = {
+	{ "HISI0511", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_soc_hha_ids);
+
+static struct platform_driver hisi_soc_hha_driver = {
+	.driver = {
+		.name = "hisi_soc_hha",
+		.acpi_match_table = hisi_soc_hha_ids,
+	},
+	.probe = hisi_soc_hha_probe,
+	.remove = hisi_soc_hha_remove,
+};
+
+module_platform_driver(hisi_soc_hha_driver);
+
+MODULE_IMPORT_NS("CACHE_COHERENCY");
+MODULE_DESCRIPTION("Hisilicon Hydra Home Agent driver supporting cache maintenance");
+MODULE_AUTHOR("Yicong Yang <yangyicong at hisilicon.com>");
+MODULE_AUTHOR("Yushan Wang <wangyushan12 at huawei.com>");
+MODULE_LICENSE("GPL");
-- 
2.43.0



From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:17 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:17 +0000
Subject: [RFC PATCH 5/6] acpi: PoC of Cache control via ACPI0019 and _DSM
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-6-Jonathan.Cameron@huawei.com>

Do not merge. This is the bare outline of what may become an ACPI
code first specification proposal.

>From various discussions, it has become clear that there is some desire not
to end up needing a cache flushing driver for every host that supports the
flush by PA range functionality that is needed for CXL and similar
disagregated memory pools where the host PA mapping to actual memory may
change over time and where various races can occur with prefetchers making
it hard to use CPU instructions to flush all stale data out.

There was once an ARM PSCI specification [1] that defined a firmware
interface to solve this problem.  However that meant dropping into
a more privileged mode, or chatting to an external firmware. That was
overkill for those systems that provide a simple MMIO register interface
for these operations. That specification never made it beyond alpha level.

For the typical class of machine that actually uses these disaggregated
pools, ACPI can potentially provide the same benefits with a great deal more
flexibility.  A _DSM in DSDT via operation regions, may be used to do any of:
1) Make firmware calls
2) Operate a register based state machine.
3) Most other things you might dream of.

This was prototyped against an implementation of the ARM specification
in [1] wrapped up in _DSM magic. That was chosen to give a second
(be it abandoned) example of how this cache control class can be used.

DSDT blob example that uses PSCI underneath.

Device (CCT0)
{
     Name (_HID, "ACPI0019")  // _HID: Hardware ID
     Name (_UID, Zero)  // _UID: Unique ID
     OperationRegion (AFFH, FFixedHW, One, 0x90)
     Field (AFFH, BufferAcc, NoLock, Preserve)
     {
         AFFX,   1152
     }

     Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
     {
         If ((Arg0 == ToUUID ("61fdc7d5-1468-4807-b565-515bf6b75319") /* Unknown UUID */))
         {
             If ((Arg2 == Zero))
	     {
                 Return (Buffer (One)
                 {
                     0x0F                                             // .
                 })
             }

             If ((Arg2 == One))
             {
                 Name (CCR1, Buffer (0x08)
                 {
                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // ........
                 })
                 CreateDWordField (CCR1, Zero, RRR1)
                 CCR1 = AFFX = Buffer (0x10)
                 {
                      /* 0000 */  0x17, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00,  // ........
                     /* 0008 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // ........
                 }
                 Name (CCOP, Zero)
                 CCOP = RRR1 /* \_SB_.CCT0._DSM.RRR1 */
                 CCR1 = AFFX = Buffer (0x10)
                 {
                     /* 0000 */  0x17, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00,  // ........
                     /* 0008 */  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // ........
                 }
                 Name (CCLA, Zero)
                 CCLA = RRR1 /* \_SB_.CCT0._DSM.RRR1 */
                 CCR1 = AFFX = Buffer (0x10)
                 {
                      /* 0000 */  0x17, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00,  // ........
                      /* 0008 */  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // ........
                 }
                 Name (CCRL, Zero)
                 CCRL = RRR1 /* \_SB_.CCT0._DSM.RRR1 */
                 Return (Package (0x04)
                 {
                     CCOP,
                     CCLA,
                     CCRL,
                     One
                 })
            }
            If ((Arg2 == 0x02))
            {
                If (!((ObjectType (Arg3) == 0x04) && (SizeOf (Arg3) == 0x03)))
                {
                    Return (One)
                }

                Name (BUFF, Buffer (0x28)
                {
                    /* 0000 */  0x16, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00,  // ........
                    /* 0008 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ........
                    /* 0010 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ........
                    /* 0018 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ........
                    /* 0020 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // ........
                 })
                 CreateQWordField (BUFF, 0x08, BFBA)
                 CreateQWordField (BUFF, 0x10, BFSZ)
                 CreateQWordField (BUFF, 0x20, BFFL)
                 Local0 = Arg3 [Zero]
                 BFBA = DerefOf (Local0)
                 Local0 = Arg3 [One]
                 BFSZ = DerefOf (Local0)
                 Local0 = Arg3 [0x02]
                 Local1 = DerefOf (Local0)
                 If ((Local1 != Zero))
                 {
                     Return (One)
                 }

                 AFFX = BUFF /* \_SB_.CCT0._DSM.BUFF */
                 Return (Zero)
             }

             If ((Arg2 == 0x03))
             {
                 Return (Zero)
             }
         }
    }
}

Link: https://developer.arm.com/documentation/den0022/falp1/?lang=en [1]
Signed-off-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
---
 drivers/acpi/Makefile              |   1 +
 drivers/cache/Kconfig              |   8 ++
 drivers/cache/Makefile             |   1 +
 drivers/cache/acpi_cache_control.c | 157 +++++++++++++++++++++++++++++
 4 files changed, 167 insertions(+)

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40208a0f5dfb..fcb6635d27d8 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -129,3 +129,4 @@ obj-$(CONFIG_ACPI_VIOT)		+= viot.o
 
 obj-$(CONFIG_RISCV)		+= riscv/
 obj-$(CONFIG_X86)		+= x86/
+
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 6dab014bc581..5569af0903c4 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -17,6 +17,14 @@ config HISI_SOC_HHA
 
 	  This driver can be built as a module. If so, the module will be
 	  called hisi_soc_hha.
+
+config ACPI_CACHE_CONTROL
+       tristate "ACPI cache maintenance"
+       depends on ARM64
+       help
+         ACPI0019 device ID in DSDT identifies an interface that may be used
+	 to carry out certain forms of cache flush operation.
+
 endif
 
 config AX45MP_L2_CACHE
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index 48b319984b45..9f0679a6dab1 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
 
 obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o
 obj-$(CONFIG_HISI_SOC_HHA)		+= hisi_soc_hha.o
+obj-$(CONFIG_ACPI_CACHE_CONTROL)   	+= acpi_cache_control.o
diff --git a/drivers/cache/acpi_cache_control.c b/drivers/cache/acpi_cache_control.c
new file mode 100644
index 000000000000..d5b91f505a26
--- /dev/null
+++ b/drivers/cache/acpi_cache_control.c
@@ -0,0 +1,157 @@
+
+#include <linux/acpi.h>
+#include <linux/cache_coherency.h>
+#include <linux/cleanup.h>
+#include <asm/cacheflush.h>
+
+struct acpi_cache_control {
+	struct cache_coherency_device ccd;
+	/* Stuff */
+};
+
+static const guid_t testguid =
+	GUID_INIT(0x61FDC7D5, 0x1468, 0x4807,
+		0xB5, 0x65, 0x51, 0x5B, 0xF6, 0xB7, 0x53, 0x19);
+
+static int acpi_cache_control_query(struct acpi_device *device)
+{
+	union acpi_object *out_obj;
+
+	out_obj = acpi_evaluate_dsm(device->handle, &testguid, 1, 1, NULL);//&in_obj);
+	if (out_obj->package.count < 4) {
+		printk("Only partial capabilities received\n");
+		return -EINVAL;
+	}
+	for (int i = 0; i < out_obj->package.count; i++)
+		if (out_obj->package.elements[i].type != 1) {
+			printk("Element %d not integer\n", i);
+			return -EINVAL;
+		}
+	switch (out_obj->package.elements[0].integer.value) {
+	case 0:
+		printk("Supports range\n");
+		break;
+	case 1:
+		printk("Full flush only\n");
+		break;
+	default:
+		printk("unknown op type %llx\n",
+			out_obj->package.elements[0].integer.value);
+		break;
+	}
+
+	printk("Latency is %lld msecs\n",
+		out_obj->package.elements[1].integer.value);
+	printk("Min delay between calls is %lld msecs\n",
+		out_obj->package.elements[2].integer.value);
+
+	if (out_obj->package.elements[3].integer.value & BIT(0))
+		printk("CLEAN_INVALIDATE\n");
+	if (out_obj->package.elements[3].integer.value & BIT(1))
+		printk("CLEAN\n");
+	if (out_obj->package.elements[3].integer.value & BIT(2))
+		printk("INVALIDATE\n");
+	ACPI_FREE(out_obj);
+	return 0;
+}
+
+static int acpi_cache_control_inval(struct acpi_device *device, u64 base, u64 size)
+{
+	union acpi_object *out_obj;
+	union acpi_object in_array[] = {
+		[0].integer = { ACPI_TYPE_INTEGER, base },
+		[1].integer = { ACPI_TYPE_INTEGER, size },
+		[2].integer = { ACPI_TYPE_INTEGER, 0 }, // Clean invalidate
+	};
+	union acpi_object in_obj = {
+		.package = {
+			.type = ACPI_TYPE_PACKAGE,
+			.count = ARRAY_SIZE(in_array),
+			.elements = in_array,
+		},
+	};
+
+	out_obj = acpi_evaluate_dsm(device->handle, &testguid, 1, 2, &in_obj);
+	printk("out type %d\n", out_obj->type);
+	printk("out val %lld\n", out_obj->integer.value);
+	ACPI_FREE(out_obj);
+	return 0;
+}
+
+static int acpi_cc_wbinv(struct cache_coherency_device *ccd,
+			 struct cc_inval_params *invp)
+{
+	struct acpi_device *acpi_dev =
+		container_of(ccd->dev.parent, struct acpi_device, dev);
+
+	return acpi_cache_control_inval(acpi_dev, invp->addr, invp->size);
+}
+
+static int acpi_cc_done(struct cache_coherency_device *ccd)
+{
+	/* Todo */
+	return 0;
+}
+
+static const struct coherency_ops acpi_cc_ops = {
+	.wbinv = acpi_cc_wbinv,
+	.done = acpi_cc_done,
+};
+
+DEFINE_FREE(acpi_cache_control, struct acpi_cache_control *,
+	if (_T) cache_coherency_device_put(&_T->ccd));
+
+static int acpi_cache_control_add(struct acpi_device *device)
+{
+	int ret;
+
+	printk("ACPI device bound\n");
+
+	ret = acpi_cache_control_query(device);
+	if (ret)
+		return ret;
+
+	struct acpi_cache_control *acpi_cc __free(acpi_cache_control) =
+		cache_coherency_alloc_device(&device->dev, &acpi_cc_ops,
+					struct acpi_cache_control, ccd);
+	if (!acpi_cc)
+		return -ENOMEM;
+
+	ret = cache_coherency_device_register(&acpi_cc->ccd);
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(&device->dev, acpi_cc);
+	return 0;
+}
+
+static void acpi_cache_control_del(struct acpi_device *device)
+{
+	struct acpi_cache_control *acpi_cc = dev_get_drvdata(&device->dev);
+
+	cache_coherency_device_unregister(&acpi_cc->ccd);
+	cache_coherency_device_put(&acpi_cc->ccd);
+}
+
+static const struct acpi_device_id acpi_cache_control_ids[] = {
+	{ "ACPI0019" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(acpi, acpi_cache_control_ids);
+
+static struct acpi_driver acpi_cache_control_driver = {
+	.name = "acpi_cache_control",
+	.ids = acpi_cache_control_ids,
+	.ops = {
+		.add = acpi_cache_control_add,
+		.remove = acpi_cache_control_del,
+	},
+};
+
+module_acpi_driver(acpi_cache_control_driver);
+
+MODULE_IMPORT_NS("CACHE_COHERENCY");
+MODULE_AUTHOR("Jonathan Cameron <Jonathan.Cameron at huawei.com>");
+MODULE_DESCRIPTION("HACKS HACKS HACKS");
+MODULE_LICENSE("GPL");
-- 
2.43.0



From oliver.upton at linux.dev  Thu Mar 20 10:44:03 2025
From: oliver.upton at linux.dev (Oliver Upton)
Date: Thu, 20 Mar 2025 17:44:03 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86h63om54p.wl-maz@kernel.org>
References: <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
 <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
 <86ldt0n9w1.wl-maz@kernel.org>
 <Z9sSMJAlf7cQ5viu@linux.dev>
 <86h63om54p.wl-maz@kernel.org>
Message-ID: <Z9xT4_fwCgp7VSgC@linux.dev>

On Thu, Mar 20, 2025 at 09:19:02AM +0000, Marc Zyngier wrote:
> On Wed, 19 Mar 2025 18:51:28 +0000, Oliver Upton <oliver.upton at linux.dev> wrote:
> > I'm at least willing to plug my nose and do the following:
> > 
> >  1) When the VMM does not specify a vPMU type:
> > 
> >    - We continue to present the 'default' PMU (including event counters)
> >      to the VM
> > 
> >    - KVM ensures that the fixed CPU cycle counter works on any PMUv3
> >      implementation in the system, even if it is different from the
> >      default
> > 
> >    - Otherwise, event counters will only count on the default
> >      implementation and will not count on different PMUs
> 
> I think this is confusing. The CC is counting, but nothing else, and
> people using the cycle counters in conjunction with other events (a
> very common use case) will not be able to correlate things correctly.
> The current behaviour is, for all its sins, at least consistent.

You of course have a good point. What Windows is doing is definitely an
outlier.

> > 
> >  2) Implement your suggestion of a UAPI where the VMM can select a PMU
> >     that only has the CPU cycle counter and works on any PMUv3
> >     implementation.
> > 
> > Either way KVM will need to have some special case handling of the fixed
> > CPU cycle counter. That'd allow users to actually run Windows *now* and
> > provide a clear mechanism for userspace to present a less-broken vPMU if
> > it cares.
> 
> Honestly, I don't care about one guest or another. My point is that if
> we are changing the behaviour of the PMU to deal with this sort of
> things, then it has to be a userspace buy-in.

I'm fine with just the user buy-in then. But I still do care about the
guest compatibility issue, especially since the end user of all this
crap is unlikely to know/care about the fine details of the
implementation.

So, Akihiko, I would *greatly* appreciate it if you propose a complete
solution to the problem, including the KVM and VMM patches to make it
all work.

Thanks,
Oliver


From Jonathan.Cameron at huawei.com  Thu Mar 20 10:41:18 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Thu, 20 Mar 2025 17:41:18 +0000
Subject: [RFC PATCH 6/6] Hack: Pretend we have PSCI 1.2
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250320174118.39173-7-Jonathan.Cameron@huawei.com>

Need to update QEMU to PSCI 1.2. In meantime lie.
This is just here to aid testing, not for review!

Signed-off-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
---
 drivers/firmware/psci/psci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index a1ebbe9b73b1..6a7a6e91fcc4 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -646,6 +646,8 @@ static void __init psci_init_smccc(void)
 		}
 	}
 
+	/* Hack until qemu version stuff updated */
+	arm_smccc_version_init(ARM_SMCCC_VERSION_1_2, psci_conduit);
 	/*
 	 * Conveniently, the SMCCC and PSCI versions are encoded the
 	 * same way. No, this isn't accidental.
-- 
2.43.0



From song at kernel.org  Thu Mar 20 10:54:32 2025
From: song at kernel.org (Song Liu)
Date: Thu, 20 Mar 2025 10:54:32 -0700
Subject: [PATCH v3 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250320174642.855602-1-wnliu@google.com>
References: <20250320171559.3423224-2-song@kernel.org> <20250320174642.855602-1-wnliu@google.com>
Message-ID: <CAPhsuW7RAXHRt3c+8DYqirPFRA+Sdw4ZNJ+Ad1uSiAHGOJ9RSA@mail.gmail.com>

On Thu, Mar 20, 2025 at 10:46?AM Weinan Liu <wnliu at google.com> wrote:
>
> On Thu, Mar 20, 2025 at 10:16?AM Song Liu <song at kernel.org> wrote:
> >
> >  static __always_inline void
> > @@ -230,8 +231,26 @@ kunwind_next_frame_record(struct kunwind_state *state)
> >         new_fp = READ_ONCE(record->fp);
> >         new_pc = READ_ONCE(record->lr);
> >
> > -       if (!new_fp && !new_pc)
> > -               return kunwind_next_frame_record_meta(state);
> > +       if (!new_fp && !new_pc) {
> > +               int ret;
> > +
> > +               ret = kunwind_next_frame_record_meta(state);
>
> The exception case kunwind_next_regs_pc() will return 0 when unwind success.
> Should we return a different value for the success case of kunwind_next_regs_pc()?

I am assuming once the unwinder hits an exception boundary, the stack is not
100% reliable. This does mean we will return -EINVAL for some reliable stack
walk, but this is safer and good enough for livepatch. IIUC, SFrame based
unwinder should not have this limitation.

Thanks,
Song

>
> > +               if (ret < 0) {
> > +                       /*
> > +                        * This covers two different conditions:
> > +                        *  1. ret == -ENOENT, unwinding is done.
> > +                        *  2. ret == -EINVAL, unwinding hit error.
> > +                        */
> > +                       return ret;
> > +               }
> > +               /*
> > +                * Searching across exception boundaries. The stack is now
> > +                * unreliable.
> > +                */
> > +               if (state->end_on_unreliable)
> > +                       return -EINVAL;
> > +               return 0;
> > +       }
>


From robh at kernel.org  Thu Mar 20 11:02:11 2025
From: robh at kernel.org (Rob Herring)
Date: Thu, 20 Mar 2025 13:02:11 -0500
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use of_reserved_mem_region_*
 functions for "memory-region"
In-Reply-To: <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>
References: <20250317232426.952188-1-robh@kernel.org> <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com> <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
 <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>
Message-ID: <CAL_JsqJZkEpx26=ro_y8hHA2x1Zm6z_SFOQHjQ-WzUa-gy+s0w@mail.gmail.com>

On Thu, Mar 20, 2025 at 4:23?AM Arnaud POULIQUEN
<arnaud.pouliquen at foss.st.com> wrote:
>
>
>
> On 3/20/25 00:04, Rob Herring wrote:
> > On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
> > <arnaud.pouliquen at foss.st.com> wrote:
> >>
> >> Hello Rob,
> >>
> >> On 3/18/25 00:24, Rob Herring (Arm) wrote:
> >>> Use the newly added of_reserved_mem_region_to_resource() and
> >>> of_reserved_mem_region_count() functions to handle "memory-region"
> >>> properties.
> >>>
> >>> The error handling is a bit different in some cases. Often
> >>> "memory-region" is optional, so failed lookup is not an error. But then
> >>> an error in of_reserved_mem_lookup() is treated as an error. However,
> >>> that distinction is not really important. Either the region is available
> >>> and usable or it is not. So now, it is just
> >>> of_reserved_mem_region_to_resource() which is checked for an error.
> >>>
> >>> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> >>> ---
> >>> For v6.16
> >>>
> >
> > [...]
> >
> >>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> >>> index b02b36a3f515..9d2bd8904c49 100644
> >>> --- a/drivers/remoteproc/stm32_rproc.c
> >>> +++ b/drivers/remoteproc/stm32_rproc.c
> >>> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
> >>>  {
> >>>       struct device *dev = rproc->dev.parent;
> >>>       struct device_node *np = dev->of_node;
> >>> -     struct of_phandle_iterator it;
> >>>       struct rproc_mem_entry *mem;
> >>> -     struct reserved_mem *rmem;
> >>>       u64 da;
> >>> -     int index = 0;
> >>> +     int index = 0, mr = 0;
> >>>
> >>>       /* Register associated reserved memory regions */
> >>> -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> >>> -     while (of_phandle_iterator_next(&it) == 0) {
> >>> -             rmem = of_reserved_mem_lookup(it.node);
> >>> -             if (!rmem) {
> >>> -                     of_node_put(it.node);
> >>> -                     dev_err(dev, "unable to acquire memory-region\n");
> >>> -                     return -EINVAL;
> >>> -             }
> >>> +     while (1) {
> >>> +             struct resource res;
> >>> +             int ret;
> >>> +
> >>> +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
> >>> +             if (ret)
> >>> +                     return 0;
> >>>
> >>> -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
> >>> -                     of_node_put(it.node);
> >>> -                     dev_err(dev, "memory region not valid %pa\n",
> >>> -                             &rmem->base);
> >>> +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
> >>> +                     dev_err(dev, "memory region not valid %pR\n", &res);
> >>>                       return -EINVAL;
> >>>               }
> >>>
> >>>               /*  No need to map vdev buffer */
> >>> -             if (strcmp(it.node->name, "vdev0buffer")) {
> >>> +             if (strcmp(res.name, "vdev0buffer")) {
> >>
> >> I tested your patches
> >
> > Thank you.
> >
> >> The update introduces a regression here. The strcmp function never returns 0.
> >> Indeed, it.node->name stores the memory region label "vdev0buffer," while
> >> res.name stores the memory region name "vdev0buffer at 10042000."
> >>
> >> Several remoteproc drivers may face the same issue as they embed similar code.
> >
> > Indeed. I confused myself because node 'name' is without the
> > unit-address, but this is using the full name. I've replaced the
> > strcmp's with strstarts() to address this. I've updated my branch with
> > the changes.
>
> This is not enough as the remoteproc core function rproc_find_carveout_by_name()
> also compares the memory names. With the following additional fix, it is working
> on my STM32MP15-DK board.
>
> @@ -309,11 +309,11 @@ rproc_find_carveout_by_name(struct rproc *rproc, const
> char *name, ...)
>         vsnprintf(_name, sizeof(_name), name, args);
>         va_end(args);
>
>         list_for_each_entry(carveout, &rproc->carveouts, node) {
>                 /* Compare carveout and requested names */
> -               if (!strcmp(carveout->name, _name)) {
> +               if (strstarts(carveout->name, _name)) {
>                         mem = carveout;
>                         break;
>                 }
>         }
>
> I just wonder if would not be more suitable to address this using the
> "memory-region-names" field.

That would be better as you shouldn't really care what a provider node
name is where-as "memory-region-names" is meaningful to the driver.

>
> The drawback is that we would break compatibility with legacy boards...

So not an option.

I think I'll have to fix this within the reserved mem code storing the
name or do something like the diff below. I'd like to avoid the
former. Using the original device_node.name is also problematic
because I want to get rid of it. We redundantly store the node name
with and without the unit-address. There's a lot of places like this
one where we hand out the pointer with no lifetime.

diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 1e949694d365..cdee87c6ffe0 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -239,7 +239,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
                                                   resource_size(&res), da,
                                                   stm32_rproc_mem_alloc,
                                                   stm32_rproc_mem_release,
-                                                  res.name);
+                                                  "%.*s",
strchrnul(res.name, '@') - res.name, res.name);

                        if (mem)
                                rproc_coredump_add_segment(rproc, da,
@@ -249,7 +249,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
                        mem = rproc_of_resm_mem_entry_init(dev, index,
                                                           resource_size(&res),
                                                           res.start,
-                                                          res.name);
+                                                          "vdev0buffer");
                }

                if (!mem) {


From robh at kernel.org  Thu Mar 20 11:26:13 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 20 Mar 2025 13:26:13 -0500
Subject: [PATCH v2 00/11] airoha: en7581: clk cleanup + USB support
In-Reply-To: <20250320130054.4804-1-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
Message-ID: <174249492019.658064.14719387276656076364.robh@kernel.org>


On Thu, 20 Mar 2025 14:00:23 +0100, Christian Marangi wrote:
> This series implement all the changes required to correctly handle
> USB support for the Airoha EN7581 SoC.
> 
> The first few patch are cleanup for the clock driver and the
> introduction of the SCU SSR SoC driver.
> 
> The SoC always support USB 2.0 but for USB 3.0 it needs additional
> configuration for the Serdes port. Such port can be either configured
> for USB usage or for PCIe lines or HSGMII and these are configured
> in the SCU space.
> 
> The xHCI USB is based on the Mediatek implementation but the PHY
> handling although conceptually similar, is indded different compared
> to Mediatek due to SSR checks and different port power up.
> 
> The SSR driver expose an API to poll the current status of the Serdes
> port and the USB PHY driver validates it. Refer to the specific commit
> for additional info.
> 
> Consider that there is currently an inconsistency as AN7581 and
> EN7581 refer to the same thing. This is due to the fact that
> the SoC born under EcoNet but then was acquired by Airoha.
> 
> Changes v2:
> - Drop changes for simple-mfd
> - Rework PHY node structure to single node
> - Drop port-id property in favor of serdes-port and
>   usb2-monitor-clock-sel
> - Make the SSR driver probe from the clock driver
> 
> Christian Marangi (11):
>   clk: en7523: convert driver to regmap API
>   clk: en7523: generalize register clocks function
>   dt-bindings: clock: en7523: add Documentation for Airoha AN7581 SCU
>     SSR
>   soc: airoha: add support for configuring SCU SSR Serdes port
>   clk: en7523: define and register SoC SCU SSR driver for EN7581
>   soc: airoha: scu-ssr: expose API to read current Serdes Port mode
>   dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
>   phy: move Airoha PCIe PHY driver to dedicated directory
>   phy: airoha: Add support for Airoha AN7581 USB PHY
>   usb: host: add ARCH_AIROHA in XHCI MTK dependency
>   arm64: dts: airoha: en7581: add USB nodes
> 
>  .../bindings/clock/airoha,en7523-scu.yaml     |  101 +-
>  .../bindings/phy/airoha,an7581-usb-phy.yaml   |   83 ++
>  MAINTAINERS                                   |   21 +-
>  arch/arm64/boot/dts/airoha/en7581.dtsi        |   49 +
>  drivers/clk/clk-en7523.c                      |  340 +++--
>  drivers/phy/Kconfig                           |   11 +-
>  drivers/phy/Makefile                          |    5 +-
>  drivers/phy/airoha/Kconfig                    |   23 +
>  drivers/phy/airoha/Makefile                   |    4 +
>  drivers/phy/airoha/phy-airoha-pcie-regs.h     |  494 +++++++
>  drivers/phy/airoha/phy-airoha-pcie.c          | 1290 +++++++++++++++++
>  drivers/phy/airoha/phy-airoha-usb.c           |  571 ++++++++
>  drivers/soc/Kconfig                           |    1 +
>  drivers/soc/Makefile                          |    1 +
>  drivers/soc/airoha/Kconfig                    |   18 +
>  drivers/soc/airoha/Makefile                   |    3 +
>  drivers/soc/airoha/airoha-scu-ssr.c           |  271 ++++
>  drivers/usb/host/Kconfig                      |    2 +-
>  .../dt-bindings/phy/airoha,an7581-usb-phy.h   |   11 +
>  include/dt-bindings/soc/airoha,scu-ssr.h      |   11 +
>  include/linux/clk/clk-en7523.h                |   10 +
>  include/linux/soc/airoha/airoha-scu-ssr.h     |   34 +
>  22 files changed, 3202 insertions(+), 152 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
>  create mode 100644 drivers/phy/airoha/Kconfig
>  create mode 100644 drivers/phy/airoha/Makefile
>  create mode 100644 drivers/phy/airoha/phy-airoha-pcie-regs.h
>  create mode 100644 drivers/phy/airoha/phy-airoha-pcie.c
>  create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
>  create mode 100644 drivers/soc/airoha/Kconfig
>  create mode 100644 drivers/soc/airoha/Makefile
>  create mode 100644 drivers/soc/airoha/airoha-scu-ssr.c
>  create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h
>  create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
>  create mode 100644 include/linux/clk/clk-en7523.h
>  create mode 100644 include/linux/soc/airoha/airoha-scu-ssr.h
> 
> --
> 2.48.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/airoha/' for 20250320130054.4804-1-ansuelsmth at gmail.com:

arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fab0000: compatible:0: 'mediatek,mtk-xhci' is not one of ['mediatek,mt2701-xhci', 'mediatek,mt2712-xhci', 'mediatek,mt7622-xhci', 'mediatek,mt7623-xhci', 'mediatek,mt7629-xhci', 'mediatek,mt7986-xhci', 'mediatek,mt7988-xhci', 'mediatek,mt8173-xhci', 'mediatek,mt8183-xhci', 'mediatek,mt8186-xhci', 'mediatek,mt8188-xhci', 'mediatek,mt8192-xhci', 'mediatek,mt8195-xhci', 'mediatek,mt8365-xhci']
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fab0000: compatible: ['mediatek,mtk-xhci'] is too short
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fad0000: compatible:0: 'mediatek,mtk-xhci' is not one of ['mediatek,mt2701-xhci', 'mediatek,mt2712-xhci', 'mediatek,mt7622-xhci', 'mediatek,mt7623-xhci', 'mediatek,mt7629-xhci', 'mediatek,mt7986-xhci', 'mediatek,mt7988-xhci', 'mediatek,mt8173-xhci', 'mediatek,mt8183-xhci', 'mediatek,mt8186-xhci', 'mediatek,mt8188-xhci', 'mediatek,mt8192-xhci', 'mediatek,mt8195-xhci', 'mediatek,mt8365-xhci']
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
arch/arm64/boot/dts/airoha/en7581-evb.dtb: usb at 1fad0000: compatible: ['mediatek,mtk-xhci'] is too short
	from schema $id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#







From robh at kernel.org  Thu Mar 20 11:26:16 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 20 Mar 2025 13:26:16 -0500
Subject: [PATCH v3 0/2] Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <20250320164633.101331-1-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
Message-ID: <174249492169.658140.8130213005563532857.robh@kernel.org>


On Thu, 20 Mar 2025 16:46:31 +0000, Willie Thai wrote:
> The GB200NVL BMC is an Aspeed Ast2600 based BMC
> for Nvidia Blackwell GB200NVL platform.
> Reference to Ast2600 SOC [1].
> Reference to Blackwell GB200NVL Platform [2].
> 
> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Cc: Krzysztof Kozlowski <krzk at kernel.org>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Paul Menzel <pmenzel at molgen.mpg.de>
> Link: https://www.aspeedtech.com/server_ast2600/ [1]
> Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---
> Changes v1 -> v2:
>   - Fix the SOB name [Krzysztof]
>   - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
>   - Fix DTS coding style [Krzysztof]
>   - Move pinctrl override to the bottom [Krzysztof]
>   - Drop bootargs [Krzysztof]
>   - Follow DTS coding style and change naming for leds node [Krzysztof]
>   - Change flash 0 status property [Krzysztof]
>   - Change the phy-mode to rgmii [Andrew]
>   - Remove the max-speed in mac0 [Andrew]
>   - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
> Changes v2 -> v3:
>   - Fix missing new line [Krzysztof]
>   - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
>   - Fix DTS coding style [Krzysztof]
>   - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
>   - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
>   - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
> ---
> 
> Willie Thai (2):
>   ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
>   dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
> 
>  .../bindings/arm/aspeed/aspeed.yaml           |    1 +
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1168 +++++++++++++++++
>  3 files changed, 1170 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> 
> --
> 2.25.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250320164633.101331-1-wthai at nvidia.com:

arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pinctrl: emmcg5_default:groups:0: 'EMMCG5' is not one of ['ADC0', 'ADC1', 'ADC10', 'ADC11', 'ADC12', 'ADC13', 'ADC14', 'ADC15', 'ADC2', 'ADC3', 'ADC4', 'ADC5', 'ADC6', 'ADC7', 'ADC8', 'ADC9', 'BMCINT', 'EMMCG1', 'EMMCG4', 'EMMCG8', 'ESPI', 'ESPIALT', 'FSI1', 'FSI2', 'FWQSPI', 'FWSPIABR', 'FWSPID', 'FWSPIWP', 'GPIT0', 'GPIT1', 'GPIT2', 'GPIT3', 'GPIT4', 'GPIT5', 'GPIT6', 'GPIT7', 'GPIU0', 'GPIU1', 'GPIU2', 'GPIU3', 'GPIU4', 'GPIU5', 'GPIU6', 'GPIU7', 'HVI3C3', 'HVI3C4', 'I2C1', 'I2C10', 'I2C11', 'I2C12', 'I2C13', 'I2C14', 'I2C15', 'I2C16', 'I2C2', 'I2C3', 'I2C4', 'I2C5', 'I2C6', 'I2C7', 'I2C8', 'I2C9', 'I3C1', 'I3C2', 'I3C3', 'I3C4', 'I3C5', 'I3C6', 'JTAGM', 'LHPD', 'LHSIRQ', 'LPC', 'LPCHC', 'LPCPD', 'LPCPME', 'LPCSMI', 'LSIRQ', 'MACLINK1', 'MACLINK2', 'MACLINK3', 'MACLINK4', 'MDIO1', 'MDIO2', 'MDIO3', 'MDIO4', 'NCSI3', 'NCSI4', 'NCTS1', 'NCTS2', 'NCTS3', 'NCTS4', 'NDCD1', 'NDCD2', 'NDCD3', 'NDCD4', 'NDSR1', 'NDSR2', 'NDSR3'
 , 'NDSR4', 'NDTR1', 'NDTR2', 'NDTR3', 'NDTR4', 'NRI1', 'NRI2', 'NRI3', 'NRI4', 'NRTS1', 'NRTS2', 'NRTS3', 'NRTS4', 'OSCCLK', 'PEWAKE', 'PWM0', 'PWM1', 'PWM10G0', 'PWM10G1', 'PWM11G0', 'PWM11G1', 'PWM12G0', 'PWM12G1', 'PWM13G0', 'PWM13G1', 'PWM14G0', 'PWM14G1', 'PWM15G0', 'PWM15G1', 'PWM2', 'PWM3', 'PWM4', 'PWM5', 'PWM6', 'PWM7', 'PWM8G0', 'PWM8G1', 'PWM9G0', 'PWM9G1', 'QSPI1', 'QSPI2', 'RGMII1', 'RGMII2', 'RGMII3', 'RGMII4', 'RMII1', 'RMII2', 'RMII3', 'RMII4', 'RXD1', 'RXD2', 'RXD3', 'RXD4', 'SALT1', 'SALT10G0', 'SALT10G1', 'SALT11G0', 'SALT11G1', 'SALT12G0', 'SALT12G1', 'SALT13G0', 'SALT13G1', 'SALT14G0', 'SALT14G1', 'SALT15G0', 'SALT15G1', 'SALT16G0', 'SALT16G1', 'SALT2', 'SALT3', 'SALT4', 'SALT5', 'SALT6', 'SALT7', 'SALT8', 'SALT9G0', 'SALT9G1', 'SD1', 'SD2', 'SD3', 'SGPM1', 'SGPM2', 'SGPS1', 'SGPS2', 'SIOONCTRL', 'SIOPBI', 'SIOPBO', 'SIOPWREQ', 'SIOPWRGD', 'SIOS3', 'SIOS5', 'SIOSCI', 'SPI1', 'SPI1ABR', 'SPI1CS1', 'SPI1WP', 'SPI2', 'SPI2CS1', 'SPI2CS2', 'TACH0', 'TACH1', 'TACH10'
 , 'TACH11', 'TACH12', 'TACH13', 'TACH14', 'TACH15', 'TACH2', 'TACH3', 'TACH4', 'TACH5', 'TACH6', 'TACH7', 'TACH8', 'TACH9', 'THRU0', 'THRU1', 'THRU2', 'THRU3', 'TXD1', 'TXD2', 'TXD3', 'TXD4', 'UART10', 'UART11', 'UART12G0', 'UART12G1', 'UART13G0', 'UART13G1', 'UART6', 'UART7', 'UART8', 'UART9', 'USBA', 'USBB', 'VB', 'VGAHS', 'VGAVS', 'WDTRST1', 'WDTRST2', 'WDTRST3', 'WDTRST4']
	from schema $id: http://devicetree.org/schemas/pinctrl/aspeed,ast2600-pinctrl.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c at 80: Unevaluated properties are not allowed ('disable-master' was unexpected)
	from schema $id: http://devicetree.org/schemas/i2c/aspeed,i2c.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 23: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 2c: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 2f: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 27: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 74: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']







From romank at linux.microsoft.com  Thu Mar 20 11:47:18 2025
From: romank at linux.microsoft.com (Roman Kisel)
Date: Thu, 20 Mar 2025 11:47:18 -0700
Subject: [PATCH hyperv-next v6 02/11] arm64: hyperv: Use SMCCC to detect
 hypervisor presence
In-Reply-To: <BN7PR02MB414871F1A3D8EF3809391F2FD4D92@BN7PR02MB4148.namprd02.prod.outlook.com>
References: <20250315001931.631210-1-romank@linux.microsoft.com>
 <20250315001931.631210-3-romank@linux.microsoft.com>
 <Z9gJlQgV3hm1kxY0@J2N7QTR9R3.cambridge.arm.com>
 <BN7PR02MB414871F1A3D8EF3809391F2FD4D92@BN7PR02MB4148.namprd02.prod.outlook.com>
Message-ID: <42a1a90b-ae3e-47df-ad6c-500055e69218@linux.microsoft.com>



On 3/19/2025 3:11 PM, Michael Kelley wrote:
> From: Mark Rutland <mark.rutland at arm.com> Sent: Monday, March 17, 2025 4:38 AM

>>
>> The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use
>> prior to the ifdeffery looks misplaced.
> 
> FWIW, include/linux/acpi.h has
> 
> #define acpi_disabled 1
> 
> when !CONFIG_ACPI.  But I agree that using a stub is better.

Thanks, Michael! I didn't "fact-checked" what was suggested indeed.
Agreed that the stub makes the code look better.

> 
> Michael
> 
>>
>> Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED().
>> Otherwise, use a stub, e.g.
>>
>> | #ifdef CONFIG_ACPI
>> | static bool __init hyperv_detect_via_acpi(void)
>> | {
>> | 	if (acpi_disabled)
>> | 		return false;
>> |
>> | 	if (acpi_gbl_FADT.header.revision < 6)
>> | 		return false;
>> |
>> | 	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
>> | }
>> | #else
>> | static inline bool hyperv_detect_via_acpi(void) { return false; }
>> | #endif
>>
>> Mark.
>>
>>> +static bool __init hyperv_detect_via_smccc(void)
>>> +{
>>> +	uuid_t hyperv_uuid = UUID_INIT(
>>> +		0x4d32ba58, 0x4764, 0xcd24,
>>> +		0x75, 0x6c, 0xef, 0x8e,
>>> +		0x24, 0x70, 0x59, 0x16);
>>> +
>>> +	return arm_smccc_hyp_present(&hyperv_uuid);
>>> +}
>>> +
>>>   static int __init hyperv_init(void)
>>>   {
>>>   	struct hv_get_vp_registers_output	result;
>>> @@ -35,13 +70,11 @@ static int __init hyperv_init(void)
>>>
>>>   	/*
>>>   	 * Allow for a kernel built with CONFIG_HYPERV to be running in
>>> -	 * a non-Hyper-V environment, including on DT instead of ACPI.
>>> +	 * a non-Hyper-V environment.
>>> +	 *
>>>   	 * In such cases, do nothing and return success.
>>>   	 */
>>> -	if (acpi_disabled)
>>> -		return 0;
>>> -
>>> -	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
>>> +	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
>>>   		return 0;
>>>
>>>   	/* Setup the guest ID */
>>> --
>>> 2.43.0
>>>
> 

-- 
Thank you,
Roman



From faith.ekstrand at collabora.com  Thu Mar 20 12:29:04 2025
From: faith.ekstrand at collabora.com (Faith Ekstrand)
Date: Thu, 20 Mar 2025 14:29:04 -0500
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
Message-ID: <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>

---- On Fri, 14 Mar 2025 18:23:16 -0500 Alyssa Rosenzweig  wrote ---

 > This adds the UAPI for the Asahi driver targeting the GPU in the Apple 
 > M1 and M2 series systems on chip. The UAPI design is based on other 
 > modern Vulkan-capable drivers, including Xe and Panthor. Memory 
 > management is based on explicit VM management. Synchronization is 
 > exclusively explicit sync. 
 >  
 > This UAPI is validated against our open source Mesa stack, which is 
 > fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and 
 > Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the 
 > VM_BIND mechanism. 
 >  
 > This patch adds the standalone UAPI header. It is implemented by an open 
 > source DRM driver written in Rust. We fully intend to upstream this 
 > driver when possible. However, as a production graphics driver, it 
 > depends on a significant number of Rust abstractions that will take a 
 > long time to upstream. In the mean time, our userspace is upstream in 
 > Mesa but is not allowed to probe with upstream Mesa as the UAPI is not 
 > yet reviewed and merged in the upstream kernel. Although we ship a 
 > patched Mesa in Fedora Asahi Remix, any containers shipping upstream 
 > Mesa builds are broken for our users, including upstream Flatpak and 
 > Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa 
 > and virglrenderer, which complicates bisects. 
 >  
 > The intention in sending out this patch is for this UAPI to be 
 > thoroughly reviewed. Once we as the DRM community are satisfied with the 
 > UAPI, this header lands signifying that the UAPI is stable and must only 
 > be evolved in backwards-compatible ways; it will be the UAPI implemented 
 > in the DRM driver that eventually lands upstream. That promise lets us 
 > enable upstream Mesa, solving all these issues while the upstream Rust 
 > abstractions are developed. 

I'm good with this. There's a slim possibility that upstream may evolve in ways that make the current UAPI tricky to implement. However, given that it's based on prior art from the nouveau, Intel, and panfrost teams and that you've been shipping it in production for a while, I think that possibility is pretty remote.

 > https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v3 contains 
 > the DRM driver implementing this proposed UAPI. 
 >  
 > https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains 
 > the Mesa patches to implement this proposed UAPI. It is mirrored at 
 > https://github.com/alyssarosenzweig/mesa/tree/agx-uapi-v3 to allow 
 > continued review during upcoming gitlab.freedesktop.org downtime. 
 >  
 > That Linux and Mesa branch together give a complete graphics/compute 
 > stack on top of this UAPI. 
 >  
 > Co-developed-by: Asahi Lina lina at asahilina.net> 
 > Signed-off-by: Asahi Lina lina at asahilina.net> 
 > Signed-off-by: Alyssa Rosenzweig alyssa at rosenzweig.io> 
 > --- 
 > Changes in v3: 
 > - Merge load/store/partial fields for depth/stencil as discussed with 
 >  Faith. This shrinks the submit a lot with little loss of 
 >  functionality. There's maaaybe a use case for splitting out depth load 
 >  base (only) later. But it's easier to add uAPI than remove it! 
 > - Make usc_exec_base per-queue instead of per-command. No use case for 
 >  doing it finer grained, and this shrinks the submits and simplifies 
 >  userspace handling. 
 > - Improve descriptions. 
 > - Reorder/shrink fields to remove padding. 
 > - Use full names for vdm/cdm_ctrl_stream_base 
 > - Link to v2: https://lore.kernel.org/r/20250313-agx-uapi-v2-1-59cc53a59ea3 at rosenzweig.io 
 >  
 > Changes in v2: 
 > - Flatten submits. Previously, the submit ioctl pointed to an array of 
 >  command structures, which each pointed to separate payload structures, 
 >  which pointed to attachment structures. This is a lot of indirection, 
 >  which complicates greatly virtgpu. In the new approach, the submit 
 >  ioctl points to a single contiguous blob of plain-old-data, no CPU 
 >  pointers, copied from userspace in one go and suitable as virtgpu wire 
 >  protocol. 
 > - Remove vm_page_size, userspace has to hardcode it anyway. 
 > - Turn random #defines into enums for better kernel doc, etc. 
 > - Improve comments, particularly around barriers[]. 
 > - Rename various flags/fields to better match canonical names when known 
 >  (a lot of the names are pulled from the drivers/gpu/drm/imagination, 
 >  naturally). 
 > - Drop unnecessary encoder_id, cmd_id handles. 
 > - Fix padding in submit ioctl (thanks Ryan). 
 > - Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io 
 > --- 
 >  Documentation/gpu/driver-uapi.rst |    5 + 
 >  MAINTAINERS                       |    1 + 
 >  include/uapi/drm/asahi_drm.h      | 1123 +++++++++++++++++++++++++++++++++++++ 
 >  3 files changed, 1129 insertions(+) 
 >  
 > diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst 
 > index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644 
 > --- a/Documentation/gpu/driver-uapi.rst 
 > +++ b/Documentation/gpu/driver-uapi.rst 
 > @@ -27,3 +27,8 @@ drm/xe uAPI 
 >  =========== 
 >  
 >  .. kernel-doc:: include/uapi/drm/xe_drm.h 
 > + 
 > +drm/asahi uAPI 
 > +================ 
 > + 
 > +.. kernel-doc:: include/uapi/drm/asahi_drm.h 
 > diff --git a/MAINTAINERS b/MAINTAINERS 
 > index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644 
 > --- a/MAINTAINERS 
 > +++ b/MAINTAINERS 
 > @@ -2256,6 +2256,7 @@ F:????drivers/watchdog/apple_wdt.c 
 >  F:????include/dt-bindings/interrupt-controller/apple-aic.h 
 >  F:????include/dt-bindings/pinctrl/apple.h 
 >  F:????include/linux/soc/apple/* 
 > +F:????include/uapi/drm/asahi_drm.h 
 >  
 >  ARM/ARTPEC MACHINE SUPPORT 
 >  M:????Jesper Nilsson jesper.nilsson at axis.com> 
 > diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h 
 > new file mode 100644 
 > index 0000000000000000000000000000000000000000..8954e71f0592c09c84da1b0783d973e0637b5559 
 > --- /dev/null 
 > +++ b/include/uapi/drm/asahi_drm.h 
 > @@ -0,0 +1,1123 @@ 
 > +/* SPDX-License-Identifier: MIT */ 
 > +/* 
 > + * Copyright (C) The Asahi Linux Contributors 
 > + * Copyright (C) 2018-2023 Collabora Ltd. 
 > + * Copyright (C) 2014-2018 Broadcom 
 > + */ 
 > +#ifndef _ASAHI_DRM_H_ 
 > +#define _ASAHI_DRM_H_ 
 > + 
 > +#include "drm.h" 
 > + 
 > +#if defined(__cplusplus) 
 > +extern "C" { 
 > +#endif 
 > + 
 > +/** 
 > + * DOC: Introduction to the Asahi UAPI 
 > + * 
 > + * This documentation describes the Asahi IOCTLs. 
 > + * 
 > + * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed 
 > + * from Panthor): 
 > + * 
 > + * - Structures must be aligned on 64-bit/8-byte. If the object is not 
 > + *   naturally aligned, a padding field must be added. 
 > + * - Fields must be explicitly aligned to their natural type alignment with 
 > + *   pad[0..N] fields. 
 > + * - All padding fields will be checked by the driver to make sure they are 
 > + *   zeroed. 
 > + * - Flags can be added, but not removed/replaced. 
 > + * - New fields can be added to the main structures (the structures 
 > + *   directly passed to the ioctl). Those fields can be added at the end of 
 > + *   the structure, or replace existing padding fields. Any new field being 
 > + *   added must preserve the behavior that existed before those fields were 
 > + *   added when a value of zero is passed. 
 > + * - New fields can be added to indirect objects (objects pointed by the 
 > + *   main structure), iff those objects are passed a size to reflect the 
 > + *   size known by the userspace driver (see 
 > + *   drm_asahi_command::cmd_buffer_size). 
 > + * - If the kernel driver is too old to know some fields, those will be 
 > + *   ignored if zero, and otherwise rejected (and so will be zero on output). 
 > + * - If userspace is too old to know some fields, those will be zeroed 
 > + *   (input) before the structure is parsed by the kernel driver. 
 > + * - Each new flag/field addition must come with a driver version update so 
 > + *   the userspace driver doesn't have to trial and error to know which 
 > + *   flags are supported. 
 > + * - Structures should not contain unions, as this would defeat the 
 > + *   extensibility of such structures. 
 > + * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed 
 > + *   at the end of the drm_asahi_ioctl_id enum. 
 > + */ 
 > + 
 > +/** 
 > + * enum drm_asahi_ioctl_id - IOCTL IDs 
 > + * 
 > + * Place new ioctls at the end, don't re-order, don't replace or remove entries. 
 > + * 
 > + * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx 
 > + * definitions instead. 
 > + */ 
 > +enum drm_asahi_ioctl_id { 
 > +????/** @DRM_ASAHI_GET_PARAMS: Query device properties. */ 
 > +????DRM_ASAHI_GET_PARAMS = 0, 
 > + 
 > +????/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */ 
 > +????DRM_ASAHI_VM_CREATE, 
 > + 
 > +????/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */ 
 > +????DRM_ASAHI_VM_DESTROY, 
 > + 
 > +????/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */ 
 > +????DRM_ASAHI_GEM_CREATE, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a 
 > +???? * given GEM handle. 
 > +???? */ 
 > +????DRM_ASAHI_GEM_MMAP_OFFSET, 
 > + 
 > +????/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */ 
 > +????DRM_ASAHI_GEM_BIND, 

I was about to complain about the GEM_BIND name but I actually prefer it. Given that it binds a single GEM object to a given range in a given VM, I think it makes sense to have it be an option on the GEM object. If and when you implement a bind queue, you can use VM_BIND for the new multi-bind ioctl and that will be an operation on the VM that says "bind all this stuff, here's some fences to know when."

 > + 
 > +????/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */ 
 > +????DRM_ASAHI_QUEUE_CREATE, 
 > + 
 > +????/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */ 
 > +????DRM_ASAHI_QUEUE_DESTROY, 
 > + 
 > +????/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */ 
 > +????DRM_ASAHI_SUBMIT, 
 > + 
 > +????/** @DRM_ASAHI_GET_TIME: Query device time. */ 
 > +????DRM_ASAHI_GET_TIME, 
 > + 
 > +????/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */ 
 > +????DRM_ASAHI_GEM_BIND_OBJECT, 
 > +}; 
 > + 
 > +#define DRM_ASAHI_MAX_CLUSTERS????64 
 > + 
 > +/** 
 > + * struct drm_asahi_params_global - Global parameters. 
 > + * 
 > + * This struct may be queried by drm_asahi_get_params. 
 > + */ 
 > +struct drm_asahi_params_global { 
 > +????/** @features: Feature bits from drm_asahi_feature */ 
 > +????__u64 features; 
 > + 
 > +????/** @gpu_generation: GPU generation, e.g. 13 for G13G */ 
 > +????__u32 gpu_generation; 
 > + 
 > +????/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */ 
 > +????__u32 gpu_variant; 
 > + 
 > +????/** 
 > +???? * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or 
 > +???? * 0x21 for 'C1' 
 > +???? */ 
 > +????__u32 gpu_revision; 
 > + 
 > +????/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */ 
 > +????__u32 chip_id; 
 > + 
 > +????/** @num_dies: Number of dies in the SoC */ 
 > +????__u32 num_dies; 
 > + 
 > +????/** @num_clusters_total: Number of GPU clusters (across all dies) */ 
 > +????__u32 num_clusters_total; 
 > + 
 > +????/** 
 > +???? * @num_cores_per_cluster: Number of logical cores per cluster 
 > +???? * (including inactive/nonexistent) 
 > +???? */ 
 > +????__u32 num_cores_per_cluster; 
 > + 
 > +????/** @num_frags_per_cluster: Number of frags per cluster */ 
 > +????__u32 num_frags_per_cluster; 
 > + 
 > +????/** @num_gps_per_cluster: Number of GPs per cluster */ 
 > +????__u32 num_gps_per_cluster; 
 > + 
 > +????/** @max_power_mw: Maximum GPU power consumption */ 
 > +????__u32 max_power_mw; 
 > + 
 > +????/** @core_masks: Bitmask of present/enabled cores per cluster */ 
 > +????__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; 
 > + 
 > +????/** @timer_frequency_hz: Clock frequency for timestamps */ 
 > +????__u64 timer_frequency_hz; 
 > + 
 > +????/** @min_frequency_khz: Minimum GPU core clock frequency */ 
 > +????__u32 min_frequency_khz; 
 > + 
 > +????/** @max_frequency_khz: Maximum GPU core clock frequency */ 
 > +????__u32 max_frequency_khz; 
 > + 
 > +????/** @vm_user_start: VM user range start VMA */ 
 > +????__u64 vm_user_start; 
 > + 
 > +????/** @vm_user_end: VM user range end VMA */ 
 > +????__u64 vm_user_end; 

Does this have to be chosen by the kernel? Are there fixed addresses chosen by the firmware which need to be respected? Or is this just the range of valid GPU addresses? I also see kernel start/end being passed in at VM creation. I'm confused. At the very least, this needs a much better comment than the one above.

 > + 
 > +????/** 
 > +???? * @vm_kernel_min_size: Minimum kernel VMA window size within user 
 > +???? * range 
 > +???? */ 
 > +????__u64 vm_kernel_min_size; 
 > + 
 > +????/** 
 > +???? * @max_commands_per_submission: Maximum number of supported commands 
 > +???? * per submission 
 > +???? */ 
 > +????__u32 max_commands_per_submission; 

Pain. But we have this in nouveau as well, so...

 > + 
 > +????/** 
 > +???? * @max_attachments: Maximum number of drm_asahi_attachment's per 
 > +???? * command 
 > +???? */ 
 > +????__u32 max_attachments; 
 > + 
 > +????/** 
 > +???? * @firmware_version: GPU firmware version, as 4 integers 
 > +???? */ 
 > +????__u32 firmware_version[4]; 

There's a part of me that's like "This should never matter. You shouldn't expose that detail to userspace!" but let's be real...

 > + 
 > +????/** 
 > +???? * @user_timestamp_frequency_hz: Timebase frequency for user timestamps 
 > +???? */ 
 > +????__u64 user_timestamp_frequency_hz; 

Why is this different? What are user timestamps and how are they different from GPU timestamps?

 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_feature - Feature bits 
 > + * 
 > + * This covers only features that userspace cannot infer from the architecture 
 > + * version. Most features don't need to be here. 
 > + */ 
 > +enum drm_asahi_feature { 
 > +????/** 
 > +???? * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader 
 > +???? * loads of unmapped memory will return zero. Shader stores to unmapped 
 > +???? * memory will be silently discarded. Note that only shader load/store 
 > +???? * is affected. Other hardware units are not affected, notably including 
 > +???? * texture sampling. 
 > +???? */ 
 > +????DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0, 
 > +}; 

This makes me a little nervous. Why isn't this a bit you can set on VM creation? If it's something that's chosen by the kernel and which userspace can query but not change, that seems problematic from a backwards compatiblity PoV.

Need to stop here for now.  I'll be back with more comments later.

~Faith


 > + 
 > +/** 
 > + * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS 
 > + */ 
 > +struct drm_asahi_get_params { 
 > +????/** @param_group: Parameter group to fetch (MBZ) */ 
 > +????__u32 param_group; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > + 
 > +????/** @pointer: User pointer to write parameter struct */ 
 > +????__u64 pointer; 
 > + 
 > +????/** @size: Size of user buffer, max size supported on return */ 
 > +????__u64 size; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE 
 > + */ 
 > +struct drm_asahi_vm_create { 
 > +????/** @kernel_start: Start of the kernel-reserved address range */ 
 > +????__u64 kernel_start; 
 > + 
 > +????/** @kernel_end: End of the kernel-reserved address range */ 
 > +????__u64 kernel_end; 
 > + 
 > +????/** @vm_id: Returned VM ID */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY 
 > + */ 
 > +struct drm_asahi_vm_destroy { 
 > +????/** @vm_id: VM ID to be destroyed */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_gem_flags - Flags for GEM creation 
 > + */ 
 > +enum drm_asahi_gem_flags { 
 > +????/** 
 > +???? * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback. 
 > +???? * 
 > +???? * Map as writeback instead of write-combine. This optimizes for CPU 
 > +???? * reads. 
 > +???? */ 
 > +????DRM_ASAHI_GEM_WRITEBACK = (1L << 0), 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports). 
 > +???? */ 
 > +????DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1), 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE 
 > + */ 
 > +struct drm_asahi_gem_create { 
 > +????/** @size: Size of the BO */ 
 > +????__u64 size; 
 > + 
 > +????/** @flags: Combination of drm_asahi_gem_flags flags. */ 
 > +????__u32 flags; 
 > + 
 > +????/** 
 > +???? * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set 
 > +???? */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @handle: Returned GEM handle for the BO */ 
 > +????__u32 handle; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_gem_mmap_offset - Arguments passed to 
 > + * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET 
 > + */ 
 > +struct drm_asahi_gem_mmap_offset { 
 > +????/** @handle: Handle for the object being mapped. */ 
 > +????__u32 handle; 
 > + 
 > +????/** @flags: Must be zero */ 
 > +????__u32 flags; 
 > + 
 > +????/** @offset: The fake offset to use for subsequent mmap call */ 
 > +????__u64 offset; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_bind_op - Bind operation 
 > + */ 
 > +enum drm_asahi_bind_op { 
 > +????/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */ 
 > +????DRM_ASAHI_BIND_OP_BIND = 0, 
 > + 
 > +????/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */ 
 > +????DRM_ASAHI_BIND_OP_UNBIND = 1, 
 > + 
 > +????/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */ 
 > +????DRM_ASAHI_BIND_OP_UNBIND_ALL = 2, 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_bind_flags - Flags for GEM binding 
 > + */ 
 > +enum drm_asahi_bind_flags { 
 > +????/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */ 
 > +????DRM_ASAHI_BIND_READ = (1L << 0), 
 > + 
 > +????/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */ 
 > +????DRM_ASAHI_BIND_WRITE = (1L << 1), 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly 
 > +???? * across the VA range. 
 > +???? * 
 > +???? * This is useful to fill a VA range with scratch pages or zero pages. 
 > +???? * It is intended as a mechanism to accelerate sparse. 
 > +???? */ 
 > +????DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2), 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_gem_bind - Arguments passed to 
 > + * DRM_IOCTL_ASAHI_GEM_BIND 
 > + */ 
 > +struct drm_asahi_gem_bind { 
 > +????/** @op: Bind operation (enum drm_asahi_bind_op) */ 
 > +????__u32 op; 
 > + 
 > +????/** @flags: Combination of drm_asahi_bind_flags flags. */ 
 > +????__u32 flags; 
 > + 
 > +????/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */ 
 > +????__u32 handle; 
 > + 
 > +????/** @vm_id: The ID of the VM to operate on */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @offset: Offset into the object (BIND only) */ 
 > +????__u64 offset; 
 > + 
 > +????/** 
 > +???? * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only) 
 > +???? */ 
 > +????__u64 range; 
 > + 
 > +????/** @addr: Address to bind to (BIND or UNBIND only) */ 
 > +????__u64 addr; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_bind_object_op - Special object bind operation 
 > + */ 
 > +enum drm_asahi_bind_object_op { 
 > +????/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */ 
 > +????DRM_ASAHI_BIND_OBJECT_OP_BIND = 0, 
 > + 
 > +????/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */ 
 > +????DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1, 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_bind_object_flags - Special object bind flags 
 > + */ 
 > +enum drm_asahi_bind_object_flags { 
 > +????/** 
 > +???? * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp 
 > +???? * buffer. 
 > +???? */ 
 > +????DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0), 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_gem_bind_object - Arguments passed to 
 > + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT 
 > + */ 
 > +struct drm_asahi_gem_bind_object { 
 > +????/** @op: Bind operation (enum drm_asahi_bind_object_op) */ 
 > +????__u32 op; 
 > + 
 > +????/** @flags: Combination of drm_asahi_bind_object_flags flags. */ 
 > +????__u32 flags; 
 > + 
 > +????/** @handle: GEM object to bind/unbind (BIND) */ 
 > +????__u32 handle; 
 > + 
 > +????/** @vm_id: The ID of the VM to operate on (MBZ currently) */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @offset: Offset into the object (BIND only) */ 
 > +????__u64 offset; 
 > + 
 > +????/** @range: Number of bytes to bind/unbind (BIND only) */ 
 > +????__u64 range; 
 > + 
 > +????/** @object_handle: Object handle (out for BIND, in for UNBIND) */ 
 > +????__u32 object_handle; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_cmd_type - Command type 
 > + */ 
 > +enum drm_asahi_cmd_type { 
 > +????/** 
 > +???? * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render 
 > +???? * subqueue. Combined vertex and fragment operation. 
 > +???? * 
 > +???? * Followed by a @drm_asahi_cmd_render payload. 
 > +???? */ 
 > +????DRM_ASAHI_CMD_RENDER = 0, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue. 
 > +???? * 
 > +???? * Followed by a @drm_asahi_cmd_compute payload. 
 > +???? */ 
 > +????DRM_ASAHI_CMD_COMPUTE = 1, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set 
 > +???? * attachments for subsequent vertex shaders in the same submit. 
 > +???? * 
 > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 > +???? */ 
 > +????DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set 
 > +???? * attachments for subsequent fragment shaders in the same submit. 
 > +???? * 
 > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 > +???? */ 
 > +????DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set 
 > +???? * attachments for subsequent compute shaders in the same submit. 
 > +???? * 
 > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 > +???? */ 
 > +????DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4, 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_queue_cap - Queue capabilities 
 > + */ 
 > +enum drm_asahi_queue_cap { 
 > +????/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */ 
 > +????DRM_ASAHI_QUEUE_CAP_RENDER????= (1UL << DRM_ASAHI_CMD_RENDER), 
 > + 
 > +????/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */ 
 > +????DRM_ASAHI_QUEUE_CAP_COMPUTE????= (1UL << DRM_ASAHI_CMD_COMPUTE), 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_queue_create - Arguments passed to 
 > + * DRM_IOCTL_ASAHI_QUEUE_CREATE 
 > + */ 
 > +struct drm_asahi_queue_create { 
 > +????/** @flags: MBZ */ 
 > +????__u32 flags; 
 > + 
 > +????/** @vm_id: The ID of the VM this queue is bound to */ 
 > +????__u32 vm_id; 
 > + 
 > +????/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */ 
 > +????__u32 queue_caps; 
 > + 
 > +????/** @priority: Queue priority, 0-3 */ 
 > +????__u32 priority; 
 > + 
 > +????/** @queue_id: The returned queue ID */ 
 > +????__u32 queue_id; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > + 
 > +????/** 
 > +???? * @usc_exec_base: GPU base address for all USC binaries (shaders) on 
 > +???? * this queue. USC addresses are 32-bit relative to this 64-bit base. 
 > +???? * 
 > +???? * This sets the following registers on all queue commands: 
 > +???? * 
 > +???? *????USC_EXEC_BASE_TA  (vertex) 
 > +???? *????USC_EXEC_BASE_ISP (fragment) 
 > +???? *????USC_EXEC_BASE_CP  (compute) 
 > +???? * 
 > +???? * While the hardware lets us configure these independently per command, 
 > +???? * we do not have a use case for this. Instead, we expect userspace to 
 > +???? * fix a 4GiB VA carveout for USC memory and pass its base address here. 
 > +???? */ 
 > +????__u64 usc_exec_base; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_queue_destroy - Arguments passed to 
 > + * DRM_IOCTL_ASAHI_QUEUE_DESTROY 
 > + */ 
 > +struct drm_asahi_queue_destroy { 
 > +????/** @queue_id: The queue ID to be destroyed */ 
 > +????__u32 queue_id; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_sync_type - Sync item type 
 > + */ 
 > +enum drm_asahi_sync_type { 
 > +????/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */ 
 > +????DRM_ASAHI_SYNC_SYNCOBJ = 0, 
 > + 
 > +????/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */ 
 > +????DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1, 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_sync - Sync item 
 > + */ 
 > +struct drm_asahi_sync { 
 > +????/** @sync_type: One of drm_asahi_sync_type */ 
 > +????__u32 sync_type; 
 > + 
 > +????/** @handle: The sync object handle */ 
 > +????__u32 handle; 
 > + 
 > +????/** @timeline_value: Timeline value for timeline sync objects */ 
 > +????__u64 timeline_value; 
 > +}; 
 > + 
 > +/** 
 > + * enum drm_asahi_subqueue - Subqueue within a queue 
 > + */ 
 > +enum drm_asahi_subqueue { 
 > +????/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */ 
 > +????DRM_ASAHI_SUBQUEUE_RENDER = 0, 
 > + 
 > +????/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */ 
 > +????DRM_ASAHI_SUBQUEUE_COMPUTE = 1, 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2 
 > +???? * for struct alignment 
 > +???? */ 
 > +????DRM_ASAHI_SUBQUEUE_COUNT = 2, 
 > +}; 
 > + 
 > +/** 
 > + * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier 
 > + * 
 > + * This special value may be passed in to drm_asahi_command::barriers[] to 
 > + * indicate that the respective subqueue should not wait on any previous work. 
 > + */ 
 > +#define DRM_ASAHI_BARRIER_NONE (0xFFFFu) 
 > + 
 > +/** 
 > + * struct drm_asahi_cmd_header - Top level command structure 
 > + */ 
 > +struct drm_asahi_cmd_header { 
 > +????/** @cmd_type: One of drm_asahi_cmd_type */ 
 > +????__u16 cmd_type; 
 > + 
 > +????/** 
 > +???? * @size: Size of this command, not including this header. 
 > +???? * 
 > +???? * For hardware commands, this enables extensibility of commands without 
 > +???? * requiring extra command types.  Passing a command that is shorter 
 > +???? * than expected is explicitly allowed for backwards-compatability. 
 > +???? * Truncated fields will be zeroed. 
 > +???? * 
 > +???? * For the synthetic attachment setting commands, this implicitly 
 > +???? * encodes the number of attachments. These commands take multiple 
 > +???? * fixed-size @drm_asahi_attachment structures as their payload, so size 
 > +???? * equals number of attachments * sizeof(struct drm_asahi_attachment). 
 > +???? */ 
 > +????__u16 size; 
 > + 
 > +????/** 
 > +???? * @barriers: Array of command indices per subqueue to wait on. 
 > +???? * 
 > +???? * Barriers are indices relative to the beginning of a given submit. A 
 > +???? * barrier of 0 waits on commands submitted to the subqueue in previous 
 > +???? * submit ioctls. A barrier of N waits on N previous commands on the 
 > +???? * subqueue within the current submit ioctl. As a special case, passing 
 > +???? * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the 
 > +???? * subqueue. 
 > +???? * 
 > +???? * Examples: 
 > +???? * 
 > +???? *   (0, 0): This waits on all previous work. 
 > +???? * 
 > +???? *   (NONE, 0): This waits on previously submitted compute commands but 
 > +???? *   does not wait on any render commands. 
 > +???? * 
 > +???? *   (1, NONE): This waits on the first render command in the submit. 
 > +???? *   This only makes sense if there are multiple render commands in the 
 > +???? *   same submit. 
 > +???? * 
 > +???? * Barriers only make sense for hardware commands. Synthetic software 
 > +???? * commands to set attachments must pass (NONE, NONE) here. 
 > +???? */ 
 > +????__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT]; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT 
 > + */ 
 > +struct drm_asahi_submit { 
 > +????/** 
 > +???? * @in_syncs: An optional array of drm_asahi_sync to wait on before 
 > +???? * starting this job. 
 > +???? */ 
 > +????__u64 in_syncs; 
 > + 
 > +????/** 
 > +???? * @out_syncs: An optional array of drm_asahi_sync objects to signal 
 > +???? * upon completion. 
 > +???? */ 
 > +????__u64 out_syncs; 
 > + 
 > +????/** 
 > +???? * @cmdbuf: Pointer to the command buffer to submit. 
 > +???? * 
 > +???? * This is a flat command buffer. By design, it contains no CPU 
 > +???? * pointers, which makes it suitable for a virtgpu wire protocol without 
 > +???? * requiring any serializing/deserializing step. 
 > +???? * 
 > +???? * It consists of a series of commands. Each command begins with a 
 > +???? * fixed-size @drm_asahi_cmd_header and is followed by a variable-length 
 > +???? * payload according to the type and size in the header. 
 > +???? */ 
 > +????__u64 cmdbuf; 
 > + 
 > +????/** @flags: Flags for command submission (MBZ) */ 
 > +????__u32 flags; 
 > + 
 > +????/** @queue_id: The queue ID to be submitted to */ 
 > +????__u32 queue_id; 
 > + 
 > +????/** 
 > +???? * @in_sync_count: Number of sync objects to wait on before starting 
 > +???? * this job. 
 > +???? */ 
 > +????__u32 in_sync_count; 
 > + 
 > +????/** 
 > +???? * @out_sync_count: Number of sync objects to signal upon completion of 
 > +???? * this job. 
 > +???? */ 
 > +????__u32 out_sync_count; 
 > + 
 > +????/** @cmdbuf_size: Command buffer size in bytes */ 
 > +????__u32 cmdbuf_size; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_attachment - Describe an "attachment". 
 > + * 
 > + * Attachments are any memory written by shaders, notably including render 
 > + * target attachments written by the end-of-tile program. This is purely a hint 
 > + * about the accessed memory regions. It is optional to specify, which is 
 > + * fortunate as it cannot be specified precisely with bindless access anyway. 
 > + * But where possible, it's probably a good idea for userspace to include these 
 > + * hints, forwarded to the firmware. 
 > + */ 
 > +struct drm_asahi_attachment { 
 > +????/** @pointer: Base address of the attachment */ 
 > +????__u64 pointer; 
 > + 
 > +????/** @size: Size of the attachment in bytes */ 
 > +????__u64 size; 
 > + 
 > +????/** @pad: MBZ */ 
 > +????__u32 pad; 
 > + 
 > +????/** @flags: MBZ */ 
 > +????__u32 flags; 
 > +}; 
 > + 
 > +enum drm_asahi_render_flags { 
 > +????/** 
 > +???? * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch 
 > +???? * memory. 
 > +???? */ 
 > +????DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0), 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles. 
 > +???? * This must be set when clearing render targets. 
 > +???? */ 
 > +????DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1), 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single 
 > +???? * cluster (on multicluster GPUs) 
 > +???? * 
 > +???? * This harms performance but can workaround certain sync/coherency 
 > +???? * bugs, and therefore is useful for debugging. 
 > +???? */ 
 > +????DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2), 
 > + 
 > +????/** 
 > +???? * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula. 
 > +???? * 
 > +???? * Graphics specifications contain two alternate formulas for depth 
 > +???? * bias, a float formula used with floating-point depth buffers and an 
 > +???? * integer formula using with unorm depth buffers. This flag specifies 
 > +???? * that the integer formula should be used. If omitted, the float 
 > +???? * formula is used instead. 
 > +???? * 
 > +???? * This corresponds to bit 18 of the relevant hardware control register, 
 > +???? * so we match that here for efficiency. 
 > +???? */ 
 > +????DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18), 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer. 
 > + * 
 > + * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit. 
 > + * There are three hardware registers for each field respectively for loads, 
 > + * stores, and partial renders. In practice, it makes sense to set all to the 
 > + * same values, except in exceptional cases not yet implemented in userspace, so 
 > + * we do not duplicate here for simplicity/efficiency. 
 > + */ 
 > +struct drm_asahi_zls_buffer { 
 > +????/** @base: Base address of the buffer */ 
 > +????__u64 base; 
 > + 
 > +????/** 
 > +???? * @comp_base: If the load buffer is compressed, address of the 
 > +???? * compression metadata section. 
 > +???? */ 
 > +????__u64 comp_base; 
 > + 
 > +????/** 
 > +???? * @stride: If layered rendering is enabled, the number of bytes 
 > +???? * between each layer of the buffer. 
 > +???? */ 
 > +????__u32 stride; 
 > + 
 > +????/** 
 > +???? * @comp_stride: If layered rendering is enabled, the number of bytes 
 > +???? * between each layer of the compression metadata. 
 > +???? */ 
 > +????__u32 comp_stride; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_timestamp - Describe a timestamp write. 
 > + * 
 > + * The firmware can optionally write the GPU timestamp at render pass 
 > + * granularities, but it needs to be mapped specially via 
 > + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to 
 > + * write as a handle-offset pair, rather than a GPU address like normal. 
 > + */ 
 > +struct drm_asahi_timestamp { 
 > +????/** 
 > +???? * @handle: Handle of the timestamp buffer, or 0 to skip this 
 > +???? * timestamp. If nonzero, this must equal the value returned in 
 > +???? * drm_asahi_gem_bind_object::object_handle. 
 > +???? */ 
 > +????__u32 handle; 
 > + 
 > +????/** @offset: Offset to write into the timestamp buffer */ 
 > +????__u32 offset; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_timestamps - Describe timestamp writes. 
 > + * 
 > + * Each operation that can be timestamped, can be timestamped at the start and 
 > + * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled 
 > + * together into drm_asahi_timestamps. 
 > + */ 
 > +struct drm_asahi_timestamps { 
 > +????/** @start: Timestamp recorded at the start of the operation */ 
 > +????struct drm_asahi_timestamp start; 
 > + 
 > +????/** @end: Timestamp recorded at the end of the operation */ 
 > +????struct drm_asahi_timestamp end; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_helper_program - Describe helper program configuration. 
 > + * 
 > + * The helper program is a compute-like kernel required for various hardware 
 > + * functionality. Its most important role is dynamically allocating 
 > + * scratch/stack memory for individual subgroups, by partitioning a static 
 > + * allocation shared for the whole device. It is supplied by userspace via 
 > + * drm_asahi_helper_program and internally dispatched by the hardware as needed. 
 > + */ 
 > +struct drm_asahi_helper_program { 
 > +????/** 
 > +???? * @binary: USC address to the helper program binary. This is a tagged 
 > +???? * pointer with configuration in the bottom bits. 
 > +???? */ 
 > +????__u32 binary; 
 > + 
 > +????/** @cfg: Configuration bits for the helper program. */ 
 > +????__u32 cfg; 
 > + 
 > +????/** 
 > +???? * @data: Data passed to the helper program. This value is not 
 > +???? * interpreted by the kernel, firmware, or hardware in any way. It is 
 > +???? * simply a sideband for userspace, set with the submit ioctl and read 
 > +???? * via special registers inside the helper program. 
 > +???? * 
 > +???? * In practice, userspace will pass a 64-bit GPU VA here pointing to the 
 > +???? * actual arguments, which presumably don't fit in 64-bits. 
 > +???? */ 
 > +????__u64 data; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_bg_eot - Describe a background or end-of-tile program. 
 > + * 
 > + * The background and end-of-tile programs are dispatched by the hardware at the 
 > + * beginning and end of rendering. As the hardware "tilebuffer" is simply local 
 > + * memory, these programs are necessary to implement API-level render targets. 
 > + * The fragment-like background program is responsible for loading either the 
 > + * clear colour or the existing render target contents, while the compute-like 
 > + * end-of-tile program stores the tilebuffer contents to memory. 
 > + */ 
 > +struct drm_asahi_bg_eot { 
 > +????/** 
 > +???? * @usc: USC address of the hardware USC words binding resources 
 > +???? * (including images and uniforms) and the program itself. Note this is 
 > +???? * an additional layer of indirection compared to the helper program, 
 > +???? * avoiding the need for a sideband for data. This is a tagged pointer 
 > +???? * with additional configuration in the bottom bits. 
 > +???? */ 
 > +????__u32 usc; 
 > + 
 > +????/** 
 > +???? * @rsrc_spec: Resource specifier for the program. This is a packed 
 > +???? * hardware data structure describing the required number of registers, 
 > +???? * uniforms, bound textures, and bound samplers. 
 > +???? */ 
 > +????__u32 rsrc_spec; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_cmd_render - Command to submit 3D 
 > + * 
 > + * This command submits a single render pass. The hardware control stream may 
 > + * include many draws and subpasses, but within the command, the framebuffer 
 > + * dimensions and attachments are fixed. 
 > + * 
 > + * The hardware requires the firmware to set a large number of Control Registers 
 > + * setting up state at render pass granularity before each command rendering 3D. 
 > + * The firmware bundles this state into data structures. Unfortunately, we 
 > + * cannot expose either any of that directly to userspace, because the 
 > + * kernel-firmware ABI is not stable. Although we can guarantee the firmware 
 > + * updates in tandem with the kernel, we cannot break old userspace when 
 > + * upgrading the firmware and kernel. Therefore, we need to abstract well the 
 > + * data structures to avoid tying our hands with future firmwares. 
 > + * 
 > + * The bulk of drm_asahi_cmd_render therefore consists of values of hardware 
 > + * control registers, marshalled via the firmware interface. 
 > + * 
 > + * The framebuffer/tilebuffer dimensions are also specified here. In addition to 
 > + * being passed to the firmware/hardware, the kernel requires these dimensions 
 > + * to calculate various essential tiling-related data structures. It is 
 > + * unfortunate that our submits are heavier than on vendors with saner 
 > + * hardware-software interfaces. The upshot is all of this information is 
 > + * readily available to userspace with all current APIs. 
 > + * 
 > + * It looks odd - but it's not overly burdensome and it ensures we can remain 
 > + * compatible with old userspace. 
 > + */ 
 > +struct drm_asahi_cmd_render { 
 > +????/** @flags: Combination of drm_asahi_render_flags flags. */ 
 > +????__u32 flags; 
 > + 
 > +????/** 
 > +???? * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the 
 > +???? * depth/stencil width/height, which may differ from the framebuffer 
 > +???? * width/height. 
 > +???? */ 
 > +????__u32 isp_zls_pixels; 
 > + 
 > +????/** 
 > +???? * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU 
 > +???? * address to the beginning of the VDM control stream. 
 > +???? */ 
 > +????__u64 vdm_ctrl_stream_base; 
 > + 
 > +????/** @vertex_helper: Helper program used for the vertex shader */ 
 > +????struct drm_asahi_helper_program vertex_helper; 
 > + 
 > +????/** @fragment_helper: Helper program used for the fragment shader */ 
 > +????struct drm_asahi_helper_program fragment_helper; 
 > + 
 > +????/** 
 > +???? * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an 
 > +???? * array of scissor descriptors indexed in the render pass. 
 > +???? */ 
 > +????__u64 isp_scissor_base; 
 > + 
 > +????/** 
 > +???? * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an 
 > +???? * array of depth bias values indexed in the render pass. 
 > +???? */ 
 > +????__u64 isp_dbias_base; 
 > + 
 > +????/** 
 > +???? * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an 
 > +???? * array of occlusion query results written by the render pass. 
 > +???? */ 
 > +????__u64 isp_oclqry_base; 
 > + 
 > +????/** @depth: Depth buffer */ 
 > +????struct drm_asahi_zls_buffer depth; 
 > + 
 > +????/** @stencil: Stencil buffer */ 
 > +????struct drm_asahi_zls_buffer stencil; 
 > + 
 > +????/** @zls_ctrl: ZLS_CTRL register value */ 
 > +????__u64 zls_ctrl; 
 > + 
 > +????/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */ 
 > +????__u64 ppp_multisamplectl; 
 > + 
 > +????/** 
 > +???? * @sampler_heap: Base address of the sampler heap. This heap is used 
 > +???? * for both vertex shaders and fragment shaders. The registers are 
 > +???? * per-stage, but there is no known use case for separate heaps. 
 > +???? */ 
 > +????__u64 sampler_heap; 
 > + 
 > +????/** @ppp_ctrl: PPP_CTRL register value */ 
 > +????__u32 ppp_ctrl; 
 > + 
 > +????/** @width_px: Framebuffer width in pixels */ 
 > +????__u16 width_px; 
 > + 
 > +????/** @height_px: Framebuffer height in pixels */ 
 > +????__u16 height_px; 
 > + 
 > +????/** @layers: Number of layers in the framebuffer */ 
 > +????__u16 layers; 
 > + 
 > +????/** @sampler_count: Number of samplers in the sampler heap. */ 
 > +????__u16 sampler_count; 
 > + 
 > +????/** @utile_width_px: Width of a logical tilebuffer tile in pixels */ 
 > +????__u8 utile_width_px; 
 > + 
 > +????/** @utile_height_px: Height of a logical tilebuffer tile in pixels */ 
 > +????__u8 utile_height_px; 
 > + 
 > +????/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */ 
 > +????__u8 samples; 
 > + 
 > +????/** @sample_size_B: # of bytes in the tilebuffer required per sample. */ 
 > +????__u8 sample_size_B; 
 > + 
 > +????/** 
 > +???? * @isp_merge_upper_x: 32-bit float used in the hardware triangle 
 > +???? * merging. Calculate as: tan(60 deg) * width. 
 > +???? * 
 > +???? * Making these values UAPI avoids requiring floating-point calculations 
 > +???? * in the kernel in the hot path. 
 > +???? */ 
 > +????__u32 isp_merge_upper_x; 
 > + 
 > +????/** 
 > +???? * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height. 
 > +???? * See @isp_merge_upper_x. 
 > +???? */ 
 > +????__u32 isp_merge_upper_y; 
 > + 
 > +????/** @bg: Background program run for each tile at the start */ 
 > +????struct drm_asahi_bg_eot bg; 
 > + 
 > +????/** @eot: End-of-tile program ran for each tile at the end */ 
 > +????struct drm_asahi_bg_eot eot; 
 > + 
 > +????/** 
 > +???? * @partial_bg: Background program ran at the start of each tile when 
 > +???? * resuming the render pass during a partial render. 
 > +???? */ 
 > +????struct drm_asahi_bg_eot partial_bg; 
 > + 
 > +????/** 
 > +???? * @partial_eot: End-of-tile program ran at the end of each tile when 
 > +???? * pausing the render pass during a partial render. 
 > +???? */ 
 > +????struct drm_asahi_bg_eot partial_eot; 
 > + 
 > +????/** 
 > +???? * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth 
 > +???? * buffer clear value, encoded in the depth buffer's format: either a 
 > +???? * 32-bit float or a 16-bit unorm (with upper bits zeroed). 
 > +???? */ 
 > +????__u32 isp_bgobjdepth; 
 > + 
 > +????/** 
 > +???? * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits 
 > +???? * contain the stencil buffer clear value. 
 > +???? */ 
 > +????__u32 isp_bgobjvals; 
 > + 
 > +????/** @ts_vtx: Timestamps for the vertex portion of the render */ 
 > +????struct drm_asahi_timestamps ts_vtx; 
 > + 
 > +????/** @ts_frag: Timestamps for the fragment portion of the render */ 
 > +????struct drm_asahi_timestamps ts_frag; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_cmd_compute - Command to submit compute 
 > + * 
 > + * This command submits a control stream consisting of compute dispatches. There 
 > + * is essentially no limit on how many compute dispatches may be included in a 
 > + * single compute command, although timestamps are at command granularity. 
 > + */ 
 > +struct drm_asahi_cmd_compute { 
 > +????/** @flags: MBZ */ 
 > +????__u32 flags; 
 > + 
 > +????/** @sampler_count: Number of samplers in the sampler heap. */ 
 > +????__u32 sampler_count; 
 > + 
 > +????/** 
 > +???? * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU 
 > +???? * address to the beginning of the CDM control stream. 
 > +???? */ 
 > +????__u64 cdm_ctrl_stream_base; 
 > + 
 > +????/** 
 > +???? * @cdm_ctrl_stream_end: GPU base address to the end of the hardware 
 > +???? * control stream. Note this only considers the first contiguous segment 
 > +???? * of the control stream, as the stream might jump elsewhere. 
 > +???? */ 
 > +????__u64 cdm_ctrl_stream_end; 
 > + 
 > +????/** @sampler_heap: Base address of the sampler heap. */ 
 > +????__u64 sampler_heap; 
 > + 
 > +????/** @helper: Helper program used for this compute shader */ 
 > +????struct drm_asahi_helper_program helper; 
 > + 
 > +????/** @ts: Timestamps for the compute command */ 
 > +????struct drm_asahi_timestamps ts; 
 > +}; 
 > + 
 > +/** 
 > + * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME 
 > + */ 
 > +struct drm_asahi_get_time { 
 > +????/** @flags: MBZ. */ 
 > +????__u64 flags; 
 > + 
 > +????/** @gpu_timestamp: On return, the current GPU timestamp */ 
 > +????__u64 gpu_timestamp; 
 > +}; 
 > + 
 > +/** 
 > + * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number 
 > + * @__access: Access type. Must be R, W or RW. 
 > + * @__id: One of the DRM_ASAHI_xxx id. 
 > + * @__type: Suffix of the type being passed to the IOCTL. 
 > + * 
 > + * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx 
 > + * values instead. 
 > + * 
 > + * Return: An IOCTL number to be passed to ioctl() from userspace. 
 > + */ 
 > +#define DRM_IOCTL_ASAHI(__access, __id, __type) \ 
 > +????DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \ 
 > +????????????   struct drm_asahi_ ## __type) 
 > + 
 > +/* Note: this is an enum so that it can be resolved by Rust bindgen. */ 
 > +enum { 
 > +????DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params), 
 > +????DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create), 
 > +????DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy), 
 > +????DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create), 
 > +????DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset), 
 > +????DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind), 
 > +????DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create), 
 > +????DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy), 
 > +????DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit), 
 > +????DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time), 
 > +????DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object), 
 > +}; 
 > + 
 > +#if defined(__cplusplus) 
 > +} 
 > +#endif 
 > + 
 > +#endif /* _ASAHI_DRM_H_ */ 
 >  
 > --- 
 > base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2 
 > change-id: 20250307-agx-uapi-930579437f19 
 >  
 > Best regards, 
 > -- 
 > Alyssa Rosenzweig alyssa at rosenzweig.io> 
 >  
 > 



From cki-project at redhat.com  Thu Mar 20 13:02:04 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Thu, 20 Mar 2025 20:02:04 -0000
Subject: =?utf-8?b?4p2M?= FAIL: Test report for for-kernelci (6.14.0-rc7,
 upstream-arm-next, 8571575d)
Message-ID: <55408.125032016020602450@us-mta-650.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: FAILED
             Merge: OK
           Compile: FAILED


Kernel information:
    Commit message: Merge remote-tracking branch 'will/for-next/perf' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1727130494

One or more kernel builds failed:
    Unrecognized or new issues:
         aarch64 - https://datawarehouse.cki-project.org/kcidb/builds/redhat:1727130494-aarch64-kernel


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From ilkka at os.amperecomputing.com  Thu Mar 20 13:10:09 2025
From: ilkka at os.amperecomputing.com (Ilkka Koskinen)
Date: Thu, 20 Mar 2025 13:10:09 -0700 (PDT)
Subject: [PATCH 1/2] perf vendor events arm64: AmpereOne/AmpereOneX: Mark
 LD_RETIRED impacted by errata
In-Reply-To: <9fe071f9-27bb-4694-ace5-f23eb0d0e50d@linaro.org>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com> <20250313201559.11332-2-ilkka@os.amperecomputing.com> <9fe071f9-27bb-4694-ace5-f23eb0d0e50d@linaro.org>
Message-ID: <6a88e749-51e1-fe61-5122-f4c046dd3485@os.amperecomputing.com>


Hi James,

On Tue, 18 Mar 2025, James Clark wrote:
> On 13/03/2025 8:15 pm, Ilkka Koskinen wrote:
>> Atomic instructions are both memory-reading and memory-writing
>> instructions and so should be counted by both LD_RETIRED and ST_RETIRED
>> performance monitoring events. However LD_RETIRED does not count atomic
>> instructions.
>> 
>> Signed-off-by: Ilkka Koskinen <ilkka at os.amperecomputing.com>
>> ---
>>   tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json | 4 +++-
>>   .../perf/pmu-events/arch/arm64/ampere/ampereonex/memory.json  | 4 +++-
>>   2 files changed, 6 insertions(+), 2 deletions(-)
>> 
>> diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json 
>> b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
>> index 0711782bfa6b..13382d29b25f 100644
>> --- a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
>> +++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/memory.json
>> @@ -1,6 +1,8 @@
>>   [
>>       {
>> -        "ArchStdEvent": "LD_RETIRED"
>> +        "ArchStdEvent": "LD_RETIRED",
>> +        "Errata": "Errata AC03_CPU_52",
>> +        "BriefDescription": "Instruction architecturally executed, 
>> condition code check pass, load. Impacted by errata -"
>
> I think this could also have a 'Fixes:' tag, either way:
>
> Reviewed-by: James Clark <james.clark at linaro.org>

Yeah, that's true. I guess, I was thinking about using 'Fixes' more on 
broken patches rather than when adding a patch dealing with a new hw 
errata. Well, given you're find with this, I don't think I'll resubmit it
with a Fixes tag this time.

Cheers, Ilkka


From qasdev00 at gmail.com  Thu Mar 20 13:19:14 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Thu, 20 Mar 2025 20:19:14 +0000
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in mt7996_mac_sta_add_links
Message-ID: <20250320201914.48159-1-qasdev00@gmail.com>

If link_conf_dereference_protected() or mt7996_vif_link() 
or link_sta_dereference_protected() fail the code jumps to
the error_unlink label and returns ret which is uninitialised.

Fix this by setting err before jumping to error_unlink.

Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 91c64e3a0860..78f7f1fc867e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			continue;
 
 		link_conf = link_conf_dereference_protected(vif, link_id);
-		if (!link_conf)
+		if (!link_conf) {
+			err = -EINVAL;
 			goto error_unlink;
+		}
 
 		link = mt7996_vif_link(dev, vif, link_id);
-		if (!link)
+		if (!link) {
+			err = -EINVAL;
 			goto error_unlink;
+		}
 
 		link_sta = link_sta_dereference_protected(sta, link_id);
-		if (!link_sta)
+		if (!link_sta) {
+			err = -EINVAL
 			goto error_unlink;
+		}
 
 		err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
 					       link_id);
-- 
2.39.5



From robh at kernel.org  Thu Mar 20 13:32:12 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 20 Mar 2025 15:32:12 -0500
Subject: [PATCH v4 01/18] dt-bindings: gpu: img: Future-proofing
 enhancements
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-1-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
 <20250320-sets-bxs-4-64-patch-v1-v4-1-d987cf4ca439@imgtec.com>
Message-ID: <174250273222.1046427.15822439763542356679.robh@kernel.org>


On Thu, 20 Mar 2025 11:32:11 +0000, Matt Coster wrote:
> The first compatible strings added for the AXE-1-16M are not sufficient to
> accurately describe all the IMG Rogue GPUs. The current "img,img-axe"
> string refers to the entire family of Series AXE GPUs, but this is
> primarily a marketing term and does not denote a level of hardware
> similarity any greater than just "Rogue".
> 
> The more specific "img,img-axe-1-16m" string refers to individual AXE-1-16M
> GPU. For example, unlike the rest of the Series AXE GPUs, the AXE-1-16M
> only uses a single power domain.
> 
> The situation is actually slightly worse than described in the first
> paragraph, since many "series" (such as Series BXS found in the TI AM68
> among others and added later in this series) contain cores with both Rogue
> and Volcanic architectures.
> 
> Besides attempting to move away from vague groupings defined only
> by marketing terms, we want to draw a line between properties inherent to
> the IP core and choices made by the silicon vendor at integration time.
> For instance, the number of power domains is a property of the IP core,
> whereas the decision to use one or multiple clocks is a vendor one.
> 
> In the original compatible strings, we must use "ti,am62-gpu" to constrain
> both of these properties since the number of power domains cannot be fixed
> for "img,img-axe".
> 
> Work is currently underway to add support for volcanic-based Imagination
> GPUs, for which bindings will be added in "img,powervr-volcanic.yaml".
> As alluded to previously, the split between rogue and volcanic cores is
> non-obvious at times, so add a generic top-level "img,img-rogue" compatible
> string here to allow for simpler differentiation in devicetrees without
> referring back to the bindings.
> 
> The currently supported GPU (AXE-1-16M) only requires a single power
> domain. Subsequent patches will add support for BXS-4-64 MC1, which has
> two power domains. Add infrastructure now to allow for this.
> 
> Also allow the dma-coherent property to be added to IMG Rogue GPUs, which
> are DMA devices. The decision for coherency is made at integration time and
> this property should be applied wherever it accurately describes the
> vendor integration.
> 
> Note that the new required properties for power domains are conditional on
> the new base compatible string to avoid an ABI break.
> 
> Signed-off-by: Matt Coster <matt.coster at imgtec.com>
> ---
> Changes in v4:
> - Add img,img-rogue back to ti,am62-gpu compatible strings to allow
>   compatibility with older kernels
> - Revert change to power-domains property and add proper constraint
> - Link to v3: https://lore.kernel.org/r/20250310-sets-bxs-4-64-patch-v1-v3-1-143b3dbef02f at imgtec.com
> Changes in v3:
> - Remove unnecessary example
> - Remove second power domain details, add these where they're used instead
> - Avoid ABI breaks by limiting new required properties to new compatible
>   strings and making all binding changes in a single patch.
> - Links to v2:
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-1-3fd45d9fb0cf at imgtec.com
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-3-3fd45d9fb0cf at imgtec.com
>   https://lore.kernel.org/r/20241118-sets-bxs-4-64-patch-v1-v2-4-3fd45d9fb0cf at imgtec.com
> ---
>  .../devicetree/bindings/gpu/img,powervr-rogue.yaml | 44 +++++++++++++++++++---
>  1 file changed, 39 insertions(+), 5 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml: properties:power-domains: 'anyOf' conditional failed, one must be fixed:
	'minItems' is not one of ['maxItems', 'description', 'deprecated']
		hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
	'minItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
	'maxItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
	1 is less than the minimum of 2
		hint: Arrays must be described with a combination of minItems/maxItems/items
	hint: cell array properties must define how many entries and what the entries are when there is more than one entry.
	from schema $id: http://devicetree.org/meta-schemas/power-domain.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250320-sets-bxs-4-64-patch-v1-v4-1-d987cf4ca439 at imgtec.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From lkp at intel.com  Thu Mar 20 14:02:10 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 05:02:10 +0800
Subject: [soc:soc/drivers 22/24]
 drivers/platform/cznic/turris-signing-key.c:25:55: warning: omitting the
 parameter name in a function definition is a C23 extension
Message-ID: <202503210450.AoOpbJXC-lkp@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
head:   ba8755ab541fc629948233125db870d4dbf00a75
commit: df94a2f1eb455b57dd01f9b64419e3163d44df7f [22/24] platform: cznic: turris-omnia-mcu: Add support for digital message signing with HW private key
config: arm-randconfig-001-20250321 (https://download.01.org/0day-ci/archive/20250321/202503210450.AoOpbJXC-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250321/202503210450.AoOpbJXC-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503210450.AoOpbJXC-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/platform/cznic/turris-signing-key.c:25:55: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions]
      25 | static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
         |                                                       ^
   drivers/platform/cznic/turris-signing-key.c:25:87: warning: omitting the parameter name in a function definition is a C23 extension [-Wc23-extensions]
      25 | static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
         |                                                                                       ^
   2 warnings generated.


vim +25 drivers/platform/cznic/turris-signing-key.c

0b28b7080ef5a3 Marek Beh?n 2025-02-04  24  
0b28b7080ef5a3 Marek Beh?n 2025-02-04 @25  static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
0b28b7080ef5a3 Marek Beh?n 2025-02-04  26  {
0b28b7080ef5a3 Marek Beh?n 2025-02-04  27  	return 0;
0b28b7080ef5a3 Marek Beh?n 2025-02-04  28  }
0b28b7080ef5a3 Marek Beh?n 2025-02-04  29  

:::::: The code at line 25 was first introduced by commit
:::::: 0b28b7080ef5a323c3afa3860c3d45d627629830 platform: cznic: Add keyctl helpers for Turris platform

:::::: TO: Marek Beh?n <kabel at kernel.org>
:::::: CC: Arnd Bergmann <arnd at arndb.de>

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From gregkh at linuxfoundation.org  Thu Mar 20 14:12:15 2025
From: gregkh at linuxfoundation.org (Greg KH)
Date: Thu, 20 Mar 2025 14:12:15 -0700
Subject: [RFC PATCH 3/6] cache: coherency device class
In-Reply-To: <20250320174118.39173-4-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
 <20250320174118.39173-4-Jonathan.Cameron@huawei.com>
Message-ID: <2025032013-venus-request-b026@gregkh>

On Thu, Mar 20, 2025 at 05:41:15PM +0000, Jonathan Cameron wrote:
> --- a/drivers/cache/Kconfig
> +++ b/drivers/cache/Kconfig
> @@ -1,6 +1,12 @@
>  # SPDX-License-Identifier: GPL-2.0
>  menu "Cache Drivers"
>  
> +config CACHE_COHERENCY_CLASS
> +	bool "Cache coherency control class"

Why can't this be a module?  And why would anyone want to turn it off?

> +	help
> +	  Class to which coherency control drivers register allowing core kernel
> +	  subsystems to issue invalidations and similar coherency operations.

What "core kernel subsystems"?

> +
>  config AX45MP_L2_CACHE
>  	bool "Andes Technology AX45MP L2 Cache controller"
>  	depends on RISCV

Shouldn't all of these now depend on CACHE_COHERENCY_CLASS?

> diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
> index 55c5e851034d..b72b20f4248f 100644
> --- a/drivers/cache/Makefile
> +++ b/drivers/cache/Makefile
> @@ -3,3 +3,5 @@
>  obj-$(CONFIG_AX45MP_L2_CACHE)		+= ax45mp_cache.o
>  obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
>  obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
> +
> +obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o

Why the blank line?

> diff --git a/drivers/cache/coherency_core.c b/drivers/cache/coherency_core.c
> new file mode 100644
> index 000000000000..52cb4ceae00c
> --- /dev/null
> +++ b/drivers/cache/coherency_core.c
> @@ -0,0 +1,130 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Class to manage OS controlled coherency agents within the system.
> + * Specifically to enable operations such as write back and invalidate.
> + *
> + * Copyright: Huawei 2025
> + * Some elements based on fwctl class as an example of a modern
> + * lightweight class.
> + */
> +
> +#include <linux/cache_coherency.h>
> +#include <linux/container_of.h>
> +#include <linux/idr.h>
> +#include <linux/fs.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include <asm/cacheflush.h>
> +
> +static DEFINE_IDA(cache_coherency_ida);
> +
> +static void cache_coherency_device_release(struct device *device)
> +{
> +	struct cache_coherency_device *ccd =
> +		container_of(device, struct cache_coherency_device, dev);
> +
> +	ida_free(&cache_coherency_ida, ccd->id);
> +}
> +
> +static struct class cache_coherency_class = {
> +	.name = "cache_coherency",
> +	.dev_release = cache_coherency_device_release,
> +};
> +
> +static int cache_inval_one(struct device *dev, void *data)
> +{
> +	struct cache_coherency_device *ccd =
> +		container_of(dev, struct cache_coherency_device, dev);
> +
> +	if (!ccd->ops)
> +		return -EINVAL;
> +
> +	return ccd->ops->wbinv(ccd, data);
> +}
> +
> +static int cache_inval_done_one(struct device *dev, void *data)
> +{
> +	struct cache_coherency_device *ccd =
> +		container_of(dev, struct cache_coherency_device, dev);
> +	if (!ccd->ops)
> +		return -EINVAL;
> +
> +	return ccd->ops->done(ccd);
> +}
> +
> +static int cache_invalidate_memregion(int res_desc,
> +				      phys_addr_t addr, size_t size)
> +{
> +	int ret;
> +	struct cc_inval_params params = {
> +		.addr = addr,
> +		.size = size,
> +	};
> +
> +	ret = class_for_each_device(&cache_coherency_class, NULL, &params,
> +				    cache_inval_one);
> +	if (ret)
> +		return ret;
> +
> +	return class_for_each_device(&cache_coherency_class, NULL, NULL,
> +				     cache_inval_done_one);
> +}
> +
> +static const struct system_cache_flush_method cache_flush_method = {
> +	.invalidate_memregion = cache_invalidate_memregion,
> +};
> +
> +struct cache_coherency_device *
> +_cache_coherency_alloc_device(struct device *parent,
> +			      const struct coherency_ops *ops, size_t size)
> +{
> +
> +	if (!ops || !ops->wbinv)
> +		return NULL;
> +
> +	struct cache_coherency_device *ccd __free(kfree) = kzalloc(size, GFP_KERNEL);
> +
> +	if (!ccd)
> +		return NULL;
> +
> +	ccd->dev.class = &cache_coherency_class;
> +	ccd->dev.parent = parent;
> +	ccd->ops = ops;
> +	ccd->id = ida_alloc(&cache_coherency_ida, GFP_KERNEL);
> +
> +	if (dev_set_name(&ccd->dev, "cache_coherency%d", ccd->id))
> +		return NULL;
> +
> + 	device_initialize(&ccd->dev);
> +
> +	return_ptr(ccd);
> +}
> +EXPORT_SYMBOL_NS_GPL(_cache_coherency_alloc_device, "CACHE_COHERENCY");
> +
> +int cache_coherency_device_register(struct cache_coherency_device *ccd)
> +{
> +	return device_add(&ccd->dev);
> +}
> +EXPORT_SYMBOL_NS_GPL(cache_coherency_device_register, "CACHE_COHERENCY");
> +
> +void cache_coherency_device_unregister(struct cache_coherency_device *ccd)
> +{
> +	device_del(&ccd->dev);
> +}
> +EXPORT_SYMBOL_NS_GPL(cache_coherency_device_unregister, "CACHE_COHERENCY");
> +
> +static int __init cache_coherency_init(void)
> +{
> +	int ret;
> +
> +	ret = class_register(&cache_coherency_class);
> +	if (ret)
> +		return ret;
> +
> +	//TODO: generalize
> +	arm64_set_sys_cache_flush_method(&cache_flush_method);

I'm guessing this will blow up the build on non-x86 builds :)

> +struct cache_coherency_device {
> +	struct device dev;
> +	const struct coherency_ops *ops;
> +	int id;
> +};

Classes are normally for user/kernel apis, what is this going to be used
for?  I don't see any new user/kernel apis happening, so why do you need
a struct device to be created?

thanks,

greg k-h


From andi.shyti at kernel.org  Thu Mar 20 14:29:20 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Thu, 20 Mar 2025 22:29:20 +0100
Subject: [PATCH v2] i2c: iproc: Refactor prototype and remove redundant
 error checks
In-Reply-To: <20250121084818.2719-1-vulab@iscas.ac.cn>
References: <20250121084818.2719-1-vulab@iscas.ac.cn>
Message-ID: <brmzhl77j2lk7bghy5iuzeifar2fdwa6nhhzfywm7xvlidxwjm@3x4cy4f6pxvf>

Hi Wentao,

...

> @@ -1169,9 +1165,7 @@ static int bcm_iproc_i2c_resume(struct device *dev)
>  	 * Power domain could have been shut off completely in system deep
>  	 * sleep, so re-initialize the block here
>  	 */
> -	ret = bcm_iproc_i2c_init(iproc_i2c);
> -	if (ret)
> -		return ret;
> +	bcm_iproc_i2c_init(iproc_i2c);

This caused a:

   warning: unused variable ?ret?

Please, make sure next time to compile properly before submitting
patches. For now I fixed the warning and merged your patch to
i2c/i2c-hist.

Thanks,
Andi

>  
>  	/* configure to the desired bus speed */
>  	val = iproc_i2c_rd_reg(iproc_i2c, TIM_CFG_OFFSET);
> -- 
> 2.42.0.windows.2
> 


From faith.ekstrand at collabora.com  Thu Mar 20 14:42:57 2025
From: faith.ekstrand at collabora.com (Faith Ekstrand)
Date: Thu, 20 Mar 2025 16:42:57 -0500
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io> <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
Message-ID: <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>

---- On Thu, 20 Mar 2025 14:29:04 -0500 Faith Ekstrand  wrote ---

 > ---- On Fri, 14 Mar 2025 18:23:16 -0500 Alyssa Rosenzweig  wrote --- 
 >  
 >  > This adds the UAPI for the Asahi driver targeting the GPU in the Apple 
 >  > M1 and M2 series systems on chip. The UAPI design is based on other 
 >  > modern Vulkan-capable drivers, including Xe and Panthor. Memory 
 >  > management is based on explicit VM management. Synchronization is 
 >  > exclusively explicit sync. 
 >  > 
 >  > This UAPI is validated against our open source Mesa stack, which is 
 >  > fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and 
 >  > Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the 
 >  > VM_BIND mechanism. 
 >  > 
 >  > This patch adds the standalone UAPI header. It is implemented by an open 
 >  > source DRM driver written in Rust. We fully intend to upstream this 
 >  > driver when possible. However, as a production graphics driver, it 
 >  > depends on a significant number of Rust abstractions that will take a 
 >  > long time to upstream. In the mean time, our userspace is upstream in 
 >  > Mesa but is not allowed to probe with upstream Mesa as the UAPI is not 
 >  > yet reviewed and merged in the upstream kernel. Although we ship a 
 >  > patched Mesa in Fedora Asahi Remix, any containers shipping upstream 
 >  > Mesa builds are broken for our users, including upstream Flatpak and 
 >  > Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa 
 >  > and virglrenderer, which complicates bisects. 
 >  > 
 >  > The intention in sending out this patch is for this UAPI to be 
 >  > thoroughly reviewed. Once we as the DRM community are satisfied with the 
 >  > UAPI, this header lands signifying that the UAPI is stable and must only 
 >  > be evolved in backwards-compatible ways; it will be the UAPI implemented 
 >  > in the DRM driver that eventually lands upstream. That promise lets us 
 >  > enable upstream Mesa, solving all these issues while the upstream Rust 
 >  > abstractions are developed. 
 >  
 > I'm good with this. There's a slim possibility that upstream may evolve in ways that make the current UAPI tricky to implement. However, given that it's based on prior art from the nouveau, Intel, and panfrost teams and that you've been shipping it in production for a while, I think that possibility is pretty remote. 
 >  
 >  > https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v3 contains 
 >  > the DRM driver implementing this proposed UAPI. 
 >  > 
 >  > https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains 
 >  > the Mesa patches to implement this proposed UAPI. It is mirrored at 
 >  > https://github.com/alyssarosenzweig/mesa/tree/agx-uapi-v3 to allow 
 >  > continued review during upcoming gitlab.freedesktop.org downtime. 
 >  > 
 >  > That Linux and Mesa branch together give a complete graphics/compute 
 >  > stack on top of this UAPI. 
 >  > 
 >  > Co-developed-by: Asahi Lina lina at asahilina.net> 
 >  > Signed-off-by: Asahi Lina lina at asahilina.net> 
 >  > Signed-off-by: Alyssa Rosenzweig alyssa at rosenzweig.io> 
 >  > --- 
 >  > Changes in v3: 
 >  > - Merge load/store/partial fields for depth/stencil as discussed with 
 >  >  Faith. This shrinks the submit a lot with little loss of 
 >  >  functionality. There's maaaybe a use case for splitting out depth load 
 >  >  base (only) later. But it's easier to add uAPI than remove it! 
 >  > - Make usc_exec_base per-queue instead of per-command. No use case for 
 >  >  doing it finer grained, and this shrinks the submits and simplifies 
 >  >  userspace handling. 
 >  > - Improve descriptions. 
 >  > - Reorder/shrink fields to remove padding. 
 >  > - Use full names for vdm/cdm_ctrl_stream_base 
 >  > - Link to v2: https://lore.kernel.org/r/20250313-agx-uapi-v2-1-59cc53a59ea3 at rosenzweig.io 
 >  > 
 >  > Changes in v2: 
 >  > - Flatten submits. Previously, the submit ioctl pointed to an array of 
 >  >  command structures, which each pointed to separate payload structures, 
 >  >  which pointed to attachment structures. This is a lot of indirection, 
 >  >  which complicates greatly virtgpu. In the new approach, the submit 
 >  >  ioctl points to a single contiguous blob of plain-old-data, no CPU 
 >  >  pointers, copied from userspace in one go and suitable as virtgpu wire 
 >  >  protocol. 
 >  > - Remove vm_page_size, userspace has to hardcode it anyway. 
 >  > - Turn random #defines into enums for better kernel doc, etc. 
 >  > - Improve comments, particularly around barriers[]. 
 >  > - Rename various flags/fields to better match canonical names when known 
 >  >  (a lot of the names are pulled from the drivers/gpu/drm/imagination, 
 >  >  naturally). 
 >  > - Drop unnecessary encoder_id, cmd_id handles. 
 >  > - Fix padding in submit ioctl (thanks Ryan). 
 >  > - Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io 
 >  > --- 
 >  >  Documentation/gpu/driver-uapi.rst |    5 + 
 >  >  MAINTAINERS                       |    1 + 
 >  >  include/uapi/drm/asahi_drm.h      | 1123 +++++++++++++++++++++++++++++++++++++ 
 >  >  3 files changed, 1129 insertions(+) 
 >  > 
 >  > diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst 
 >  > index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644 
 >  > --- a/Documentation/gpu/driver-uapi.rst 
 >  > +++ b/Documentation/gpu/driver-uapi.rst 
 >  > @@ -27,3 +27,8 @@ drm/xe uAPI 
 >  >  =========== 
 >  > 
 >  >  .. kernel-doc:: include/uapi/drm/xe_drm.h 
 >  > + 
 >  > +drm/asahi uAPI 
 >  > +================ 
 >  > + 
 >  > +.. kernel-doc:: include/uapi/drm/asahi_drm.h 
 >  > diff --git a/MAINTAINERS b/MAINTAINERS 
 >  > index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644 
 >  > --- a/MAINTAINERS 
 >  > +++ b/MAINTAINERS 
 >  > @@ -2256,6 +2256,7 @@ F:????drivers/watchdog/apple_wdt.c 
 >  >  F:????include/dt-bindings/interrupt-controller/apple-aic.h 
 >  >  F:????include/dt-bindings/pinctrl/apple.h 
 >  >  F:????include/linux/soc/apple/* 
 >  > +F:????include/uapi/drm/asahi_drm.h 
 >  > 
 >  >  ARM/ARTPEC MACHINE SUPPORT 
 >  >  M:????Jesper Nilsson jesper.nilsson at axis.com> 
 >  > diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h 
 >  > new file mode 100644 
 >  > index 0000000000000000000000000000000000000000..8954e71f0592c09c84da1b0783d973e0637b5559 
 >  > --- /dev/null 
 >  > +++ b/include/uapi/drm/asahi_drm.h 
 >  > @@ -0,0 +1,1123 @@ 
 >  > +/* SPDX-License-Identifier: MIT */ 
 >  > +/* 
 >  > + * Copyright (C) The Asahi Linux Contributors 
 >  > + * Copyright (C) 2018-2023 Collabora Ltd. 
 >  > + * Copyright (C) 2014-2018 Broadcom 
 >  > + */ 
 >  > +#ifndef _ASAHI_DRM_H_ 
 >  > +#define _ASAHI_DRM_H_ 
 >  > + 
 >  > +#include "drm.h" 
 >  > + 
 >  > +#if defined(__cplusplus) 
 >  > +extern "C" { 
 >  > +#endif 
 >  > + 
 >  > +/** 
 >  > + * DOC: Introduction to the Asahi UAPI 
 >  > + * 
 >  > + * This documentation describes the Asahi IOCTLs. 
 >  > + * 
 >  > + * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed 
 >  > + * from Panthor): 
 >  > + * 
 >  > + * - Structures must be aligned on 64-bit/8-byte. If the object is not 
 >  > + *   naturally aligned, a padding field must be added. 
 >  > + * - Fields must be explicitly aligned to their natural type alignment with 
 >  > + *   pad[0..N] fields. 
 >  > + * - All padding fields will be checked by the driver to make sure they are 
 >  > + *   zeroed. 
 >  > + * - Flags can be added, but not removed/replaced. 
 >  > + * - New fields can be added to the main structures (the structures 
 >  > + *   directly passed to the ioctl). Those fields can be added at the end of 
 >  > + *   the structure, or replace existing padding fields. Any new field being 
 >  > + *   added must preserve the behavior that existed before those fields were 
 >  > + *   added when a value of zero is passed. 
 >  > + * - New fields can be added to indirect objects (objects pointed by the 
 >  > + *   main structure), iff those objects are passed a size to reflect the 
 >  > + *   size known by the userspace driver (see 
 >  > + *   drm_asahi_command::cmd_buffer_size). 
 >  > + * - If the kernel driver is too old to know some fields, those will be 
 >  > + *   ignored if zero, and otherwise rejected (and so will be zero on output). 
 >  > + * - If userspace is too old to know some fields, those will be zeroed 
 >  > + *   (input) before the structure is parsed by the kernel driver. 
 >  > + * - Each new flag/field addition must come with a driver version update so 
 >  > + *   the userspace driver doesn't have to trial and error to know which 
 >  > + *   flags are supported. 
 >  > + * - Structures should not contain unions, as this would defeat the 
 >  > + *   extensibility of such structures. 
 >  > + * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed 
 >  > + *   at the end of the drm_asahi_ioctl_id enum. 
 >  > + */ 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_ioctl_id - IOCTL IDs 
 >  > + * 
 >  > + * Place new ioctls at the end, don't re-order, don't replace or remove entries. 
 >  > + * 
 >  > + * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx 
 >  > + * definitions instead. 
 >  > + */ 
 >  > +enum drm_asahi_ioctl_id { 
 >  > +????/** @DRM_ASAHI_GET_PARAMS: Query device properties. */ 
 >  > +????DRM_ASAHI_GET_PARAMS = 0, 
 >  > + 
 >  > +????/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */ 
 >  > +????DRM_ASAHI_VM_CREATE, 
 >  > + 
 >  > +????/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */ 
 >  > +????DRM_ASAHI_VM_DESTROY, 
 >  > + 
 >  > +????/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */ 
 >  > +????DRM_ASAHI_GEM_CREATE, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a 
 >  > +???? * given GEM handle. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_GEM_MMAP_OFFSET, 
 >  > + 
 >  > +????/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */ 
 >  > +????DRM_ASAHI_GEM_BIND, 
 >  
 > I was about to complain about the GEM_BIND name but I actually prefer it. Given that it binds a single GEM object to a given range in a given VM, I think it makes sense to have it be an option on the GEM object. If and when you implement a bind queue, you can use VM_BIND for the new multi-bind ioctl and that will be an operation on the VM that says "bind all this stuff, here's some fences to know when." 
 >  
 >  > + 
 >  > +????/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */ 
 >  > +????DRM_ASAHI_QUEUE_CREATE, 
 >  > + 
 >  > +????/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */ 
 >  > +????DRM_ASAHI_QUEUE_DESTROY, 
 >  > + 
 >  > +????/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */ 
 >  > +????DRM_ASAHI_SUBMIT, 
 >  > + 
 >  > +????/** @DRM_ASAHI_GET_TIME: Query device time. */ 
 >  > +????DRM_ASAHI_GET_TIME, 
 >  > + 
 >  > +????/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */ 
 >  > +????DRM_ASAHI_GEM_BIND_OBJECT, 
 >  > +}; 
 >  > + 
 >  > +#define DRM_ASAHI_MAX_CLUSTERS????64 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_params_global - Global parameters. 
 >  > + * 
 >  > + * This struct may be queried by drm_asahi_get_params. 
 >  > + */ 
 >  > +struct drm_asahi_params_global { 
 >  > +????/** @features: Feature bits from drm_asahi_feature */ 
 >  > +????__u64 features; 
 >  > + 
 >  > +????/** @gpu_generation: GPU generation, e.g. 13 for G13G */ 
 >  > +????__u32 gpu_generation; 
 >  > + 
 >  > +????/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */ 
 >  > +????__u32 gpu_variant; 
 >  > + 
 >  > +????/** 
 >  > +???? * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or 
 >  > +???? * 0x21 for 'C1' 
 >  > +???? */ 
 >  > +????__u32 gpu_revision; 
 >  > + 
 >  > +????/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */ 
 >  > +????__u32 chip_id; 
 >  > + 
 >  > +????/** @num_dies: Number of dies in the SoC */ 
 >  > +????__u32 num_dies; 
 >  > + 
 >  > +????/** @num_clusters_total: Number of GPU clusters (across all dies) */ 
 >  > +????__u32 num_clusters_total; 
 >  > + 
 >  > +????/** 
 >  > +???? * @num_cores_per_cluster: Number of logical cores per cluster 
 >  > +???? * (including inactive/nonexistent) 
 >  > +???? */ 
 >  > +????__u32 num_cores_per_cluster; 
 >  > + 
 >  > +????/** @num_frags_per_cluster: Number of frags per cluster */ 
 >  > +????__u32 num_frags_per_cluster; 
 >  > + 
 >  > +????/** @num_gps_per_cluster: Number of GPs per cluster */ 
 >  > +????__u32 num_gps_per_cluster; 
 >  > + 
 >  > +????/** @max_power_mw: Maximum GPU power consumption */ 
 >  > +????__u32 max_power_mw; 
 >  > + 
 >  > +????/** @core_masks: Bitmask of present/enabled cores per cluster */ 
 >  > +????__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; 
 >  > + 
 >  > +????/** @timer_frequency_hz: Clock frequency for timestamps */ 
 >  > +????__u64 timer_frequency_hz; 
 >  > + 
 >  > +????/** @min_frequency_khz: Minimum GPU core clock frequency */ 
 >  > +????__u32 min_frequency_khz; 
 >  > + 
 >  > +????/** @max_frequency_khz: Maximum GPU core clock frequency */ 
 >  > +????__u32 max_frequency_khz; 
 >  > + 
 >  > +????/** @vm_user_start: VM user range start VMA */ 
 >  > +????__u64 vm_user_start; 
 >  > + 
 >  > +????/** @vm_user_end: VM user range end VMA */ 
 >  > +????__u64 vm_user_end; 
 >  
 > Does this have to be chosen by the kernel? Are there fixed addresses chosen by the firmware which need to be respected? Or is this just the range of valid GPU addresses? I also see kernel start/end being passed in at VM creation. I'm confused. At the very least, this needs a much better comment than the one above. 
 >  
 >  > + 
 >  > +????/** 
 >  > +???? * @vm_kernel_min_size: Minimum kernel VMA window size within user 
 >  > +???? * range 
 >  > +???? */ 
 >  > +????__u64 vm_kernel_min_size; 
 >  > + 
 >  > +????/** 
 >  > +???? * @max_commands_per_submission: Maximum number of supported commands 
 >  > +???? * per submission 
 >  > +???? */ 
 >  > +????__u32 max_commands_per_submission; 
 >  
 > Pain. But we have this in nouveau as well, so... 
 >  
 >  > + 
 >  > +????/** 
 >  > +???? * @max_attachments: Maximum number of drm_asahi_attachment's per 
 >  > +???? * command 
 >  > +???? */ 
 >  > +????__u32 max_attachments; 
 >  > + 
 >  > +????/** 
 >  > +???? * @firmware_version: GPU firmware version, as 4 integers 
 >  > +???? */ 
 >  > +????__u32 firmware_version[4]; 
 >  
 > There's a part of me that's like "This should never matter. You shouldn't expose that detail to userspace!" but let's be real... 
 >  
 >  > + 
 >  > +????/** 
 >  > +???? * @user_timestamp_frequency_hz: Timebase frequency for user timestamps 
 >  > +???? */ 
 >  > +????__u64 user_timestamp_frequency_hz; 
 >  
 > Why is this different? What are user timestamps and how are they different from GPU timestamps? 
 >  
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_feature - Feature bits 
 >  > + * 
 >  > + * This covers only features that userspace cannot infer from the architecture 
 >  > + * version. Most features don't need to be here. 
 >  > + */ 
 >  > +enum drm_asahi_feature { 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader 
 >  > +???? * loads of unmapped memory will return zero. Shader stores to unmapped 
 >  > +???? * memory will be silently discarded. Note that only shader load/store 
 >  > +???? * is affected. Other hardware units are not affected, notably including 
 >  > +???? * texture sampling. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0, 
 >  > +}; 
 >  
 > This makes me a little nervous. Why isn't this a bit you can set on VM creation? If it's something that's chosen by the kernel and which userspace can query but not change, that seems problematic from a backwards compatiblity PoV. 
 >  
 > Need to stop here for now.  I'll be back with more comments later. 
 >  
 > ~Faith 
 >  
 >  
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS 
 >  > + */ 
 >  > +struct drm_asahi_get_params { 
 >  > +????/** @param_group: Parameter group to fetch (MBZ) */ 
 >  > +????__u32 param_group; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > + 
 >  > +????/** @pointer: User pointer to write parameter struct */ 
 >  > +????__u64 pointer; 
 >  > + 
 >  > +????/** @size: Size of user buffer, max size supported on return */ 
 >  > +????__u64 size; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE 
 >  > + */ 
 >  > +struct drm_asahi_vm_create { 
 >  > +????/** @kernel_start: Start of the kernel-reserved address range */ 
 >  > +????__u64 kernel_start; 
 >  > + 
 >  > +????/** @kernel_end: End of the kernel-reserved address range */ 
 >  > +????__u64 kernel_end; 
 >  > + 
 >  > +????/** @vm_id: Returned VM ID */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY 
 >  > + */ 
 >  > +struct drm_asahi_vm_destroy { 
 >  > +????/** @vm_id: VM ID to be destroyed */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_gem_flags - Flags for GEM creation 
 >  > + */ 
 >  > +enum drm_asahi_gem_flags { 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback. 
 >  > +???? * 
 >  > +???? * Map as writeback instead of write-combine. This optimizes for CPU 
 >  > +???? * reads. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_GEM_WRITEBACK = (1L << 0), 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports). 
 >  > +???? */ 
 >  > +????DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1), 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE 
 >  > + */ 
 >  > +struct drm_asahi_gem_create { 
 >  > +????/** @size: Size of the BO */ 
 >  > +????__u64 size; 
 >  > + 
 >  > +????/** @flags: Combination of drm_asahi_gem_flags flags. */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** 
 >  > +???? * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set 
 >  > +???? */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @handle: Returned GEM handle for the BO */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_gem_mmap_offset - Arguments passed to 
 >  > + * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET 
 >  > + */ 
 >  > +struct drm_asahi_gem_mmap_offset { 
 >  > +????/** @handle: Handle for the object being mapped. */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @flags: Must be zero */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @offset: The fake offset to use for subsequent mmap call */ 
 >  > +????__u64 offset; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_bind_op - Bind operation 
 >  > + */ 
 >  > +enum drm_asahi_bind_op { 
 >  > +????/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */ 
 >  > +????DRM_ASAHI_BIND_OP_BIND = 0, 
 >  > + 
 >  > +????/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */ 
 >  > +????DRM_ASAHI_BIND_OP_UNBIND = 1, 
 >  > + 
 >  > +????/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */ 
 >  > +????DRM_ASAHI_BIND_OP_UNBIND_ALL = 2, 

Do you use this? We don't have it in nouveau and NVK gets by fine. Or does the asahi kernel do something where it expects you to unbind everything before the buffer is really destroyed? I think I remember talking to Lina about this a while ago but I don't remember the details.

 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_bind_flags - Flags for GEM binding 
 >  > + */ 
 >  > +enum drm_asahi_bind_flags { 
 >  > +????/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */ 
 >  > +????DRM_ASAHI_BIND_READ = (1L << 0), 
 >  > + 
 >  > +????/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */ 
 >  > +????DRM_ASAHI_BIND_WRITE = (1L << 1), 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly 
 >  > +???? * across the VA range. 
 >  > +???? * 
 >  > +???? * This is useful to fill a VA range with scratch pages or zero pages. 
 >  > +???? * It is intended as a mechanism to accelerate sparse. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2), 

Does this require the BO to be a single page? If so, does it require offset==0? Or does it just take whatever page is at the specified offset?

 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_gem_bind - Arguments passed to 
 >  > + * DRM_IOCTL_ASAHI_GEM_BIND 
 >  > + */ 
 >  > +struct drm_asahi_gem_bind { 
 >  > +????/** @op: Bind operation (enum drm_asahi_bind_op) */ 
 >  > +????__u32 op; 
 >  > + 
 >  > +????/** @flags: Combination of drm_asahi_bind_flags flags. */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @vm_id: The ID of the VM to operate on */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @offset: Offset into the object (BIND only) */ 

I guess this makes it look like SINGLE_PAGE requires offset==0?

 >  > +????__u64 offset; 
 >  > + 
 >  > +????/** 
 >  > +???? * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only) 
 >  > +???? */ 
 >  > +????__u64 range; 
 >  > + 
 >  > +????/** @addr: Address to bind to (BIND or UNBIND only) */ 
 >  > +????__u64 addr; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_bind_object_op - Special object bind operation 
 >  > + */ 
 >  > +enum drm_asahi_bind_object_op { 
 >  > +????/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */ 
 >  > +????DRM_ASAHI_BIND_OBJECT_OP_BIND = 0, 
 >  > + 
 >  > +????/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */ 
 >  > +????DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1, 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_bind_object_flags - Special object bind flags 
 >  > + */ 
 >  > +enum drm_asahi_bind_object_flags { 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp 
 >  > +???? * buffer. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0), 

Thanks. I hate it. But I guess NVIDIA has special pages, too. 

 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_gem_bind_object - Arguments passed to 
 >  > + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT 
 >  > + */ 
 >  > +struct drm_asahi_gem_bind_object { 
 >  > +????/** @op: Bind operation (enum drm_asahi_bind_object_op) */ 
 >  > +????__u32 op; 
 >  > + 
 >  > +????/** @flags: Combination of drm_asahi_bind_object_flags flags. */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @handle: GEM object to bind/unbind (BIND) */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @vm_id: The ID of the VM to operate on (MBZ currently) */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @offset: Offset into the object (BIND only) */ 
 >  > +????__u64 offset; 
 >  > + 
 >  > +????/** @range: Number of bytes to bind/unbind (BIND only) */ 
 >  > +????__u64 range; 
 >  > + 
 >  > +????/** @object_handle: Object handle (out for BIND, in for UNBIND) */ 
 >  > +????__u32 object_handle; 

How is this different from the GEM handle? I mean, I know it's different, but What is this handle for? Just a thing we can pass in later?

 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_cmd_type - Command type 
 >  > + */ 
 >  > +enum drm_asahi_cmd_type { 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render 
 >  > +???? * subqueue. Combined vertex and fragment operation. 
 >  > +???? * 
 >  > +???? * Followed by a @drm_asahi_cmd_render payload. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_CMD_RENDER = 0, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue. 
 >  > +???? * 
 >  > +???? * Followed by a @drm_asahi_cmd_compute payload. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_CMD_COMPUTE = 1, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set 
 >  > +???? * attachments for subsequent vertex shaders in the same submit. 
 >  > +???? * 
 >  > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set 
 >  > +???? * attachments for subsequent fragment shaders in the same submit. 
 >  > +???? * 
 >  > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set 
 >  > +???? * attachments for subsequent compute shaders in the same submit. 
 >  > +???? * 
 >  > +???? * Followed by (possibly multiple) @drm_asahi_attachment payloads. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4, 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_queue_cap - Queue capabilities 
 >  > + */ 
 >  > +enum drm_asahi_queue_cap { 
 >  > +????/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */ 
 >  > +????DRM_ASAHI_QUEUE_CAP_RENDER????= (1UL << DRM_ASAHI_CMD_RENDER), 
 >  > + 
 >  > +????/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */ 
 >  > +????DRM_ASAHI_QUEUE_CAP_COMPUTE????= (1UL << DRM_ASAHI_CMD_COMPUTE), 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_queue_create - Arguments passed to 
 >  > + * DRM_IOCTL_ASAHI_QUEUE_CREATE 
 >  > + */ 
 >  > +struct drm_asahi_queue_create { 
 >  > +????/** @flags: MBZ */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @vm_id: The ID of the VM this queue is bound to */ 
 >  > +????__u32 vm_id; 
 >  > + 
 >  > +????/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */ 
 >  > +????__u32 queue_caps; 
 >  > + 
 >  > +????/** @priority: Queue priority, 0-3 */ 
 >  > +????__u32 priority; 

Is one of these priorities REALTIME and only usable by privileged apps? If so, maybe document that and/or have an enum?

 >  > + 
 >  > +????/** @queue_id: The returned queue ID */ 
 >  > +????__u32 queue_id; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > + 
 >  > +????/** 
 >  > +???? * @usc_exec_base: GPU base address for all USC binaries (shaders) on 
 >  > +???? * this queue. USC addresses are 32-bit relative to this 64-bit base. 
 >  > +???? * 
 >  > +???? * This sets the following registers on all queue commands: 
 >  > +???? * 
 >  > +???? *????USC_EXEC_BASE_TA  (vertex) 
 >  > +???? *????USC_EXEC_BASE_ISP (fragment) 
 >  > +???? *????USC_EXEC_BASE_CP  (compute) 
 >  > +???? * 
 >  > +???? * While the hardware lets us configure these independently per command, 
 >  > +???? * we do not have a use case for this. Instead, we expect userspace to 
 >  > +???? * fix a 4GiB VA carveout for USC memory and pass its base address here. 
 >  > +???? */ 
 >  > +????__u64 usc_exec_base; 

I mean, you could have a command for this or or something but meh. That can be an extension on top of the current UAPI later if it's ever needed.

 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_queue_destroy - Arguments passed to 
 >  > + * DRM_IOCTL_ASAHI_QUEUE_DESTROY 
 >  > + */ 
 >  > +struct drm_asahi_queue_destroy { 
 >  > +????/** @queue_id: The queue ID to be destroyed */ 
 >  > +????__u32 queue_id; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_sync_type - Sync item type 
 >  > + */ 
 >  > +enum drm_asahi_sync_type { 
 >  > +????/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */ 
 >  > +????DRM_ASAHI_SYNC_SYNCOBJ = 0, 
 >  > + 
 >  > +????/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */ 
 >  > +????DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1, 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_sync - Sync item 
 >  > + */ 
 >  > +struct drm_asahi_sync { 
 >  > +????/** @sync_type: One of drm_asahi_sync_type */ 
 >  > +????__u32 sync_type; 
 >  > + 
 >  > +????/** @handle: The sync object handle */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @timeline_value: Timeline value for timeline sync objects */ 
 >  > +????__u64 timeline_value; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * enum drm_asahi_subqueue - Subqueue within a queue 
 >  > + */ 
 >  > +enum drm_asahi_subqueue { 
 >  > +????/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */ 
 >  > +????DRM_ASAHI_SUBQUEUE_RENDER = 0, 
 >  > + 
 >  > +????/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */ 
 >  > +????DRM_ASAHI_SUBQUEUE_COMPUTE = 1, 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2 
 >  > +???? * for struct alignment 
 >  > +???? */ 
 >  > +????DRM_ASAHI_SUBQUEUE_COUNT = 2, 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier 
 >  > + * 
 >  > + * This special value may be passed in to drm_asahi_command::barriers[] to 
 >  > + * indicate that the respective subqueue should not wait on any previous work. 
 >  > + */ 
 >  > +#define DRM_ASAHI_BARRIER_NONE (0xFFFFu) 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_cmd_header - Top level command structure 
 >  > + */ 
 >  > +struct drm_asahi_cmd_header { 
 >  > +????/** @cmd_type: One of drm_asahi_cmd_type */ 
 >  > +????__u16 cmd_type; 
 >  > + 
 >  > +????/** 
 >  > +???? * @size: Size of this command, not including this header. 
 >  > +???? * 
 >  > +???? * For hardware commands, this enables extensibility of commands without 
 >  > +???? * requiring extra command types.  Passing a command that is shorter 
 >  > +???? * than expected is explicitly allowed for backwards-compatability. 
 >  > +???? * Truncated fields will be zeroed. 
 >  > +???? * 
 >  > +???? * For the synthetic attachment setting commands, this implicitly 
 >  > +???? * encodes the number of attachments. These commands take multiple 
 >  > +???? * fixed-size @drm_asahi_attachment structures as their payload, so size 
 >  > +???? * equals number of attachments * sizeof(struct drm_asahi_attachment). 
 >  > +???? */ 
 >  > +????__u16 size; 
 >  > + 
 >  > +????/** 
 >  > +???? * @barriers: Array of command indices per subqueue to wait on. 
 >  > +???? * 
 >  > +???? * Barriers are indices relative to the beginning of a given submit. A 
 >  > +???? * barrier of 0 waits on commands submitted to the subqueue in previous 
 >  > +???? * submit ioctls. A barrier of N waits on N previous commands on the 
 >  > +???? * subqueue within the current submit ioctl. As a special case, passing 
 >  > +???? * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the 
 >  > +???? * subqueue. 
 >  > +???? * 
 >  > +???? * Examples: 
 >  > +???? * 
 >  > +???? *   (0, 0): This waits on all previous work. 
 >  > +???? * 
 >  > +???? *   (NONE, 0): This waits on previously submitted compute commands but 
 >  > +???? *   does not wait on any render commands. 
 >  > +???? * 
 >  > +???? *   (1, NONE): This waits on the first render command in the submit. 
 >  > +???? *   This only makes sense if there are multiple render commands in the 
 >  > +???? *   same submit. 
 >  > +???? * 
 >  > +???? * Barriers only make sense for hardware commands. Synthetic software 
 >  > +???? * commands to set attachments must pass (NONE, NONE) here. 
 >  > +???? */ 
 >  > +????__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT]; 

I'm not sure how good of an idea this is. You said in the comment above that SUBQUEUE_COUNT must be a power of 2. However, once you use it to size an array in the command header, it can never change ever. I'm not sure what to do about that. The command header being 8B is kinda nice... But also, will we ever need more than 2? I'd hate to have to change the size of the header.

Another option would be to potentially have a barrier command which would then be extensible but that sounds kinda annoying.

 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT 
 >  > + */ 
 >  > +struct drm_asahi_submit { 
 >  > +????/** 
 >  > +???? * @in_syncs: An optional array of drm_asahi_sync to wait on before 
 >  > +???? * starting this job. 
 >  > +???? */ 
 >  > +????__u64 in_syncs; 
 >  > + 
 >  > +????/** 
 >  > +???? * @out_syncs: An optional array of drm_asahi_sync objects to signal 
 >  > +???? * upon completion. 
 >  > +???? */ 
 >  > +????__u64 out_syncs; 
 >  > + 
 >  > +????/** 
 >  > +???? * @cmdbuf: Pointer to the command buffer to submit. 
 >  > +???? * 
 >  > +???? * This is a flat command buffer. By design, it contains no CPU 
 >  > +???? * pointers, which makes it suitable for a virtgpu wire protocol without 
 >  > +???? * requiring any serializing/deserializing step. 
 >  > +???? * 
 >  > +???? * It consists of a series of commands. Each command begins with a 
 >  > +???? * fixed-size @drm_asahi_cmd_header and is followed by a variable-length 
 >  > +???? * payload according to the type and size in the header. 
 >  > +???? */ 
 >  > +????__u64 cmdbuf; 
 >  > + 
 >  > +????/** @flags: Flags for command submission (MBZ) */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @queue_id: The queue ID to be submitted to */ 
 >  > +????__u32 queue_id; 
 >  > + 
 >  > +????/** 
 >  > +???? * @in_sync_count: Number of sync objects to wait on before starting 
 >  > +???? * this job. 
 >  > +???? */ 
 >  > +????__u32 in_sync_count; 
 >  > + 
 >  > +????/** 
 >  > +???? * @out_sync_count: Number of sync objects to signal upon completion of 
 >  > +???? * this job. 
 >  > +???? */ 
 >  > +????__u32 out_sync_count; 
 >  > + 
 >  > +????/** @cmdbuf_size: Command buffer size in bytes */ 
 >  > +????__u32 cmdbuf_size; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_attachment - Describe an "attachment". 
 >  > + * 
 >  > + * Attachments are any memory written by shaders, notably including render 
 >  > + * target attachments written by the end-of-tile program. This is purely a hint 
 >  > + * about the accessed memory regions. It is optional to specify, which is 
 >  > + * fortunate as it cannot be specified precisely with bindless access anyway. 
 >  > + * But where possible, it's probably a good idea for userspace to include these 
 >  > + * hints, forwarded to the firmware. 
 >  > + */ 
 >  > +struct drm_asahi_attachment { 
 >  > +????/** @pointer: Base address of the attachment */ 
 >  > +????__u64 pointer; 
 >  > + 
 >  > +????/** @size: Size of the attachment in bytes */ 
 >  > +????__u64 size; 
 >  > + 
 >  > +????/** @pad: MBZ */ 
 >  > +????__u32 pad; 
 >  > + 
 >  > +????/** @flags: MBZ */ 
 >  > +????__u32 flags; 
 >  > +}; 
 >  > + 
 >  > +enum drm_asahi_render_flags { 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch 
 >  > +???? * memory. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0), 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles. 
 >  > +???? * This must be set when clearing render targets. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1), 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single 
 >  > +???? * cluster (on multicluster GPUs) 
 >  > +???? * 
 >  > +???? * This harms performance but can workaround certain sync/coherency 
 >  > +???? * bugs, and therefore is useful for debugging. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2), 
 >  > + 
 >  > +????/** 
 >  > +???? * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula. 
 >  > +???? * 
 >  > +???? * Graphics specifications contain two alternate formulas for depth 
 >  > +???? * bias, a float formula used with floating-point depth buffers and an 
 >  > +???? * integer formula using with unorm depth buffers. This flag specifies 
 >  > +???? * that the integer formula should be used. If omitted, the float 
 >  > +???? * formula is used instead. 
 >  > +???? * 
 >  > +???? * This corresponds to bit 18 of the relevant hardware control register, 
 >  > +???? * so we match that here for efficiency. 
 >  > +???? */ 
 >  > +????DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18), 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer. 
 >  > + * 
 >  > + * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit. 
 >  > + * There are three hardware registers for each field respectively for loads, 
 >  > + * stores, and partial renders. In practice, it makes sense to set all to the 
 >  > + * same values, except in exceptional cases not yet implemented in userspace, so 
 >  > + * we do not duplicate here for simplicity/efficiency. 
 >  > + */ 
 >  > +struct drm_asahi_zls_buffer { 
 >  > +????/** @base: Base address of the buffer */ 
 >  > +????__u64 base; 
 >  > + 
 >  > +????/** 
 >  > +???? * @comp_base: If the load buffer is compressed, address of the 
 >  > +???? * compression metadata section. 
 >  > +???? */ 
 >  > +????__u64 comp_base; 
 >  > + 
 >  > +????/** 
 >  > +???? * @stride: If layered rendering is enabled, the number of bytes 
 >  > +???? * between each layer of the buffer. 
 >  > +???? */ 
 >  > +????__u32 stride; 
 >  > + 
 >  > +????/** 
 >  > +???? * @comp_stride: If layered rendering is enabled, the number of bytes 
 >  > +???? * between each layer of the compression metadata. 
 >  > +???? */ 
 >  > +????__u32 comp_stride; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_timestamp - Describe a timestamp write. 
 >  > + * 
 >  > + * The firmware can optionally write the GPU timestamp at render pass 
 >  > + * granularities, but it needs to be mapped specially via 
 >  > + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to 
 >  > + * write as a handle-offset pair, rather than a GPU address like normal. 

Given that this struct is embedded in other structs, it might be worth a comment saying it can never be extended without breaking those structs.

 >  > + */ 
 >  > +struct drm_asahi_timestamp { 
 >  > +????/** 
 >  > +???? * @handle: Handle of the timestamp buffer, or 0 to skip this 
 >  > +???? * timestamp. If nonzero, this must equal the value returned in 
 >  > +???? * drm_asahi_gem_bind_object::object_handle. 
 >  > +???? */ 
 >  > +????__u32 handle; 
 >  > + 
 >  > +????/** @offset: Offset to write into the timestamp buffer */ 
 >  > +????__u32 offset; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_timestamps - Describe timestamp writes. 
 >  > + * 
 >  > + * Each operation that can be timestamped, can be timestamped at the start and 
 >  > + * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled 
 >  > + * together into drm_asahi_timestamps. 

Same comment here. This struct is not extensible.

 >  > + */ 
 >  > +struct drm_asahi_timestamps { 
 >  > +????/** @start: Timestamp recorded at the start of the operation */ 
 >  > +????struct drm_asahi_timestamp start; 
 >  > + 
 >  > +????/** @end: Timestamp recorded at the end of the operation */ 
 >  > +????struct drm_asahi_timestamp end; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_helper_program - Describe helper program configuration. 
 >  > + * 
 >  > + * The helper program is a compute-like kernel required for various hardware 
 >  > + * functionality. Its most important role is dynamically allocating 
 >  > + * scratch/stack memory for individual subgroups, by partitioning a static 
 >  > + * allocation shared for the whole device. It is supplied by userspace via 
 >  > + * drm_asahi_helper_program and internally dispatched by the hardware as needed. 

Same comment here. This struct is not extensible.

 >  > + */ 
 >  > +struct drm_asahi_helper_program { 
 >  > +????/** 
 >  > +???? * @binary: USC address to the helper program binary. This is a tagged 
 >  > +???? * pointer with configuration in the bottom bits. 
 >  > +???? */ 
 >  > +????__u32 binary; 
 >  > + 
 >  > +????/** @cfg: Configuration bits for the helper program. */ 
 >  > +????__u32 cfg; 

There's configuratin bits here and in the binary pointer abov?

 >  > + 
 >  > +????/** 
 >  > +???? * @data: Data passed to the helper program. This value is not 
 >  > +???? * interpreted by the kernel, firmware, or hardware in any way. It is 
 >  > +???? * simply a sideband for userspace, set with the submit ioctl and read 
 >  > +???? * via special registers inside the helper program. 
 >  > +???? * 
 >  > +???? * In practice, userspace will pass a 64-bit GPU VA here pointing to the 
 >  > +???? * actual arguments, which presumably don't fit in 64-bits. 
 >  > +???? */ 
 >  > +????__u64 data; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_bg_eot - Describe a background or end-of-tile program. 
 >  > + * 
 >  > + * The background and end-of-tile programs are dispatched by the hardware at the 
 >  > + * beginning and end of rendering. As the hardware "tilebuffer" is simply local 
 >  > + * memory, these programs are necessary to implement API-level render targets. 
 >  > + * The fragment-like background program is responsible for loading either the 
 >  > + * clear colour or the existing render target contents, while the compute-like 
 >  > + * end-of-tile program stores the tilebuffer contents to memory. 

Same comment here. This struct is not extensible.

 >  > + */ 
 >  > +struct drm_asahi_bg_eot { 
 >  > +????/** 
 >  > +???? * @usc: USC address of the hardware USC words binding resources 
 >  > +???? * (including images and uniforms) and the program itself. Note this is 
 >  > +???? * an additional layer of indirection compared to the helper program, 
 >  > +???? * avoiding the need for a sideband for data. This is a tagged pointer 
 >  > +???? * with additional configuration in the bottom bits. 
 >  > +???? */ 
 >  > +????__u32 usc; 
 >  > + 
 >  > +????/** 
 >  > +???? * @rsrc_spec: Resource specifier for the program. This is a packed 
 >  > +???? * hardware data structure describing the required number of registers, 
 >  > +???? * uniforms, bound textures, and bound samplers. 
 >  > +???? */ 
 >  > +????__u32 rsrc_spec; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_cmd_render - Command to submit 3D 
 >  > + * 
 >  > + * This command submits a single render pass. The hardware control stream may 
 >  > + * include many draws and subpasses, but within the command, the framebuffer 
 >  > + * dimensions and attachments are fixed. 
 >  > + * 
 >  > + * The hardware requires the firmware to set a large number of Control Registers 
 >  > + * setting up state at render pass granularity before each command rendering 3D. 
 >  > + * The firmware bundles this state into data structures. Unfortunately, we 
 >  > + * cannot expose either any of that directly to userspace, because the 
 >  > + * kernel-firmware ABI is not stable. Although we can guarantee the firmware 
 >  > + * updates in tandem with the kernel, we cannot break old userspace when 
 >  > + * upgrading the firmware and kernel. Therefore, we need to abstract well the 
 >  > + * data structures to avoid tying our hands with future firmwares. 
 >  > + * 
 >  > + * The bulk of drm_asahi_cmd_render therefore consists of values of hardware 
 >  > + * control registers, marshalled via the firmware interface. 
 >  > + * 
 >  > + * The framebuffer/tilebuffer dimensions are also specified here. In addition to 
 >  > + * being passed to the firmware/hardware, the kernel requires these dimensions 
 >  > + * to calculate various essential tiling-related data structures. It is 
 >  > + * unfortunate that our submits are heavier than on vendors with saner 
 >  > + * hardware-software interfaces. The upshot is all of this information is 
 >  > + * readily available to userspace with all current APIs. 
 >  > + * 
 >  > + * It looks odd - but it's not overly burdensome and it ensures we can remain 
 >  > + * compatible with old userspace. 
 >  > + */ 
 >  > +struct drm_asahi_cmd_render { 
 >  > +????/** @flags: Combination of drm_asahi_render_flags flags. */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the 
 >  > +???? * depth/stencil width/height, which may differ from the framebuffer 
 >  > +???? * width/height. 
 >  > +???? */ 
 >  > +????__u32 isp_zls_pixels; 
 >  > + 
 >  > +????/** 
 >  > +???? * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU 
 >  > +???? * address to the beginning of the VDM control stream. 
 >  > +???? */ 
 >  > +????__u64 vdm_ctrl_stream_base; 
 >  > + 
 >  > +????/** @vertex_helper: Helper program used for the vertex shader */ 
 >  > +????struct drm_asahi_helper_program vertex_helper; 
 >  > + 
 >  > +????/** @fragment_helper: Helper program used for the fragment shader */ 
 >  > +????struct drm_asahi_helper_program fragment_helper; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an 
 >  > +???? * array of scissor descriptors indexed in the render pass. 
 >  > +???? */ 
 >  > +????__u64 isp_scissor_base; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an 
 >  > +???? * array of depth bias values indexed in the render pass. 
 >  > +???? */ 
 >  > +????__u64 isp_dbias_base; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an 
 >  > +???? * array of occlusion query results written by the render pass. 
 >  > +???? */ 
 >  > +????__u64 isp_oclqry_base; 
 >  > + 
 >  > +????/** @depth: Depth buffer */ 
 >  > +????struct drm_asahi_zls_buffer depth; 
 >  > + 
 >  > +????/** @stencil: Stencil buffer */ 
 >  > +????struct drm_asahi_zls_buffer stencil; 
 >  > + 
 >  > +????/** @zls_ctrl: ZLS_CTRL register value */ 
 >  > +????__u64 zls_ctrl; 
 >  > + 
 >  > +????/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */ 
 >  > +????__u64 ppp_multisamplectl; 
 >  > + 
 >  > +????/** 
 >  > +???? * @sampler_heap: Base address of the sampler heap. This heap is used 
 >  > +???? * for both vertex shaders and fragment shaders. The registers are 
 >  > +???? * per-stage, but there is no known use case for separate heaps. 
 >  > +???? */ 
 >  > +????__u64 sampler_heap; 
 >  > + 
 >  > +????/** @ppp_ctrl: PPP_CTRL register value */ 
 >  > +????__u32 ppp_ctrl; 
 >  > + 
 >  > +????/** @width_px: Framebuffer width in pixels */ 
 >  > +????__u16 width_px; 
 >  > + 
 >  > +????/** @height_px: Framebuffer height in pixels */ 
 >  > +????__u16 height_px; 
 >  > + 
 >  > +????/** @layers: Number of layers in the framebuffer */ 
 >  > +????__u16 layers; 
 >  > + 
 >  > +????/** @sampler_count: Number of samplers in the sampler heap. */ 
 >  > +????__u16 sampler_count; 
 >  > + 
 >  > +????/** @utile_width_px: Width of a logical tilebuffer tile in pixels */ 
 >  > +????__u8 utile_width_px; 
 >  > + 
 >  > +????/** @utile_height_px: Height of a logical tilebuffer tile in pixels */ 
 >  > +????__u8 utile_height_px; 
 >  > + 
 >  > +????/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */ 
 >  > +????__u8 samples; 
 >  > + 
 >  > +????/** @sample_size_B: # of bytes in the tilebuffer required per sample. */ 
 >  > +????__u8 sample_size_B; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_merge_upper_x: 32-bit float used in the hardware triangle 
 >  > +???? * merging. Calculate as: tan(60 deg) * width. 
 >  > +???? * 
 >  > +???? * Making these values UAPI avoids requiring floating-point calculations 
 >  > +???? * in the kernel in the hot path. 
 >  > +???? */ 
 >  > +????__u32 isp_merge_upper_x; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height. 
 >  > +???? * See @isp_merge_upper_x. 
 >  > +???? */ 
 >  > +????__u32 isp_merge_upper_y; 
 >  > + 
 >  > +????/** @bg: Background program run for each tile at the start */ 
 >  > +????struct drm_asahi_bg_eot bg; 
 >  > + 
 >  > +????/** @eot: End-of-tile program ran for each tile at the end */ 
 >  > +????struct drm_asahi_bg_eot eot; 
 >  > + 
 >  > +????/** 
 >  > +???? * @partial_bg: Background program ran at the start of each tile when 
 >  > +???? * resuming the render pass during a partial render. 
 >  > +???? */ 
 >  > +????struct drm_asahi_bg_eot partial_bg; 
 >  > + 
 >  > +????/** 
 >  > +???? * @partial_eot: End-of-tile program ran at the end of each tile when 
 >  > +???? * pausing the render pass during a partial render. 
 >  > +???? */ 
 >  > +????struct drm_asahi_bg_eot partial_eot; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth 
 >  > +???? * buffer clear value, encoded in the depth buffer's format: either a 
 >  > +???? * 32-bit float or a 16-bit unorm (with upper bits zeroed). 
 >  > +???? */ 
 >  > +????__u32 isp_bgobjdepth; 
 >  > + 
 >  > +????/** 
 >  > +???? * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits 
 >  > +???? * contain the stencil buffer clear value. 
 >  > +???? */ 
 >  > +????__u32 isp_bgobjvals; 
 >  > + 
 >  > +????/** @ts_vtx: Timestamps for the vertex portion of the render */ 
 >  > +????struct drm_asahi_timestamps ts_vtx; 
 >  > + 
 >  > +????/** @ts_frag: Timestamps for the fragment portion of the render */ 
 >  > +????struct drm_asahi_timestamps ts_frag; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_cmd_compute - Command to submit compute 
 >  > + * 
 >  > + * This command submits a control stream consisting of compute dispatches. There 
 >  > + * is essentially no limit on how many compute dispatches may be included in a 
 >  > + * single compute command, although timestamps are at command granularity. 
 >  > + */ 
 >  > +struct drm_asahi_cmd_compute { 
 >  > +????/** @flags: MBZ */ 
 >  > +????__u32 flags; 
 >  > + 
 >  > +????/** @sampler_count: Number of samplers in the sampler heap. */ 
 >  > +????__u32 sampler_count; 
 >  > + 
 >  > +????/** 
 >  > +???? * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU 
 >  > +???? * address to the beginning of the CDM control stream. 
 >  > +???? */ 
 >  > +????__u64 cdm_ctrl_stream_base; 
 >  > + 
 >  > +????/** 
 >  > +???? * @cdm_ctrl_stream_end: GPU base address to the end of the hardware 
 >  > +???? * control stream. Note this only considers the first contiguous segment 
 >  > +???? * of the control stream, as the stream might jump elsewhere. 
 >  > +???? */ 
 >  > +????__u64 cdm_ctrl_stream_end; 
 >  > + 
 >  > +????/** @sampler_heap: Base address of the sampler heap. */ 
 >  > +????__u64 sampler_heap; 
 >  > + 
 >  > +????/** @helper: Helper program used for this compute shader */ 
 >  > +????struct drm_asahi_helper_program helper; 
 >  > + 
 >  > +????/** @ts: Timestamps for the compute command */ 
 >  > +????struct drm_asahi_timestamps ts; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME 
 >  > + */ 
 >  > +struct drm_asahi_get_time { 
 >  > +????/** @flags: MBZ. */ 
 >  > +????__u64 flags; 
 >  > + 
 >  > +????/** @gpu_timestamp: On return, the current GPU timestamp */ 
 >  > +????__u64 gpu_timestamp; 
 >  > +}; 
 >  > + 
 >  > +/** 
 >  > + * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number 
 >  > + * @__access: Access type. Must be R, W or RW. 
 >  > + * @__id: One of the DRM_ASAHI_xxx id. 
 >  > + * @__type: Suffix of the type being passed to the IOCTL. 
 >  > + * 
 >  > + * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx 
 >  > + * values instead. 
 >  > + * 
 >  > + * Return: An IOCTL number to be passed to ioctl() from userspace. 
 >  > + */ 
 >  > +#define DRM_IOCTL_ASAHI(__access, __id, __type) \ 
 >  > +????DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \ 
 >  > +????????????   struct drm_asahi_ ## __type) 
 >  > + 
 >  > +/* Note: this is an enum so that it can be resolved by Rust bindgen. */ 
 >  > +enum { 
 >  > +????DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params), 
 >  > +????DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create), 
 >  > +????DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy), 
 >  > +????DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create), 
 >  > +????DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset), 
 >  > +????DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind), 
 >  > +????DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create), 
 >  > +????DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy), 
 >  > +????DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit), 
 >  > +????DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time), 
 >  > +????DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object), 
 >  > +}; 

Woo! I made it to the end. I think that's all for now. I mostly asked a lot of questions.

~Faith


 >  > + 
 >  > +#if defined(__cplusplus) 
 >  > +} 
 >  > +#endif 
 >  > + 
 >  > +#endif /* _ASAHI_DRM_H_ */ 
 >  > 
 >  > --- 
 >  > base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2 
 >  > change-id: 20250307-agx-uapi-930579437f19 
 >  > 
 >  > Best regards, 
 >  > -- 
 >  > Alyssa Rosenzweig alyssa at rosenzweig.io> 
 >  > 
 >  > 
 >  
 > 



From bryan.odonoghue at linaro.org  Thu Mar 20 15:01:37 2025
From: bryan.odonoghue at linaro.org (Bryan O'Donoghue)
Date: Thu, 20 Mar 2025 22:01:37 +0000
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for
 PCIe3
In-Reply-To: <20250320055502.274849-2-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <zqBb_94gbwLzHgbAiLqgbuGg9wmeV1jUxHOsMXDdZToeTtRrtUimm8ra7GB48DXWU-ZOvC5mO8EY0uvxz46ISg==@protonmail.internalid>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com>
Message-ID: <fff943a6-4322-43d0-9821-08375bc5376c@linaro.org>

On 20/03/2025 05:55, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Enable the pwrctrl driver, which is utilized to manage the power supplies
> of the devices connected to the PCI slots. This ensures that the voltage
> rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
> on/off if they are described under PCIe port device tree node.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>   arch/arm64/configs/defconfig | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 85ec2fba1..de86d1121 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
>   CONFIG_PCI_ENDPOINT=y
>   CONFIG_PCI_ENDPOINT_CONFIGFS=y
>   CONFIG_PCI_EPF_TEST=m
> +CONFIG_PCI_PWRCTL_SLOT=y
>   CONFIG_DEVTMPFS=y
>   CONFIG_DEVTMPFS_MOUNT=y
>   CONFIG_FW_LOADER_USER_HELPER=y
> --
> 2.34.1
> 
> 

PCI_PWRCTL_SLOT is a tristate symbol why be a "y" instead of an "m" i.e. 
compile this into the kernel instead of having it be a module ?

---
bod


From bryan.odonoghue at linaro.org  Thu Mar 20 15:06:31 2025
From: bryan.odonoghue at linaro.org (Bryan O'Donoghue)
Date: Thu, 20 Mar 2025 22:06:31 +0000
Subject: [PATCH v1 2/3] arm64: dts: qcom: x1e80100: add bus topology for
 PCIe domain 3
In-Reply-To: <20250320055502.274849-3-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <U9NTFHDe_r-uUozJFJGmc7VpxMDx39onKby4M3B_sy0jJ2fr7-iXkS801m2slu8PXanf7Y7faBxuZ8fzWiKxTg==@protonmail.internalid>
 <20250320055502.274849-3-quic_wenbyao@quicinc.com>
Message-ID: <7dc8700f-0d53-45f5-bfff-2bec71c7053e@linaro.org>

On 20/03/2025 05:55, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Add pcie3port node to represent the PCIe bridge of PCIe3 so that PCI slot
> voltage rails can be described under this node in the board's dts.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>   arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> index 46b79fce9..32e8d400a 100644
> --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> @@ -3287,6 +3287,16 @@ opp-128000000 {
>   					opp-peak-kBps = <15753000 1>;
>   				};
>   			};
> +			pcie3port: pcie at 0 { 

Missing newline, please check your dtb checks.


> +				device_type = "pci";
> +				compatible = "pciclass,0604";
> +				reg = <0x0 0x0 0x0 0x0 0x0>;
> +				bus-range = <0x01 0xff>;
> +
> +				#address-cells = <3>;
> +				#size-cells = <2>;
> +				ranges;
> +			};
>   		};

Why is pice3port the only port to be enabled ?

What about the other ports ?
>   		pcie3_phy: phy at 1be0000 {
> --
> 2.34.1
> 
> 

---
bod


From linux at armlinux.org.uk  Thu Mar 20 15:11:06 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:06 +0000
Subject: [PATCH net-next 0/5] net: improve stmmac resume rx clocking
Message-ID: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>

Hi,

stmmac has had a long history of problems with resuming, illustrated by
reset failure due to the receive clock not running.

Several attempts have been attempted over the years to address this
issue, such as moving phylink_start() (now phylink_resume()) super
early in stmmac_resume() in commit 90702dcd19c0 ("net: stmmac: fix MAC
not working when system resume back with WoL a ctive.") However, this
has the downside that stmmac_mac_link_up() can (and demonstrably is)
called before or during the driver initialisation in another thread.
This can cause issues as packets could begin to be queued, and the
transmit/receive enable bits will be set before any initialisation has
been done.

Another attempt is used by dwmac-socfpga.c in commit 2d871aa07136 ("net:
stmmac: add platform init/exit for Altera's ARM socfpga") which
pre-dates the above commit.

Neither of these two approaches consider the effect of EEE with a PHY
that supports receive clock-stop and has that feature enabled (which
the stmmac driver does enable). If the link is up, then there is the
possibility for the receive path to be in low-power mode, and the PHY
may stop its receive clock.

This series addresses these issues by (each is not necessarily a
separate patch):

1) introducing phylink_prepare_resume(), which can be used by MAC
   drivers to ensure that the PHY is resumed prior to doing any
   re-initialisation work. This call is added to stmmac_resume().

2) moving phylink_resume() after all re-initialisation has completed,
   thereby ensuring that the hardware is ready to be enabled for
   packet reception/transmission.

3) with (1) and (2) addressed, the need for socfpga to have a private
   work-around is no longer necessary, so it is removed.

4) introducing phylink functions to block/unblock the receive clock-
   stop at the PHY. As these require PHY access over the MDIO bus,
   they can sleep, so are not suitable for atomic access.

5) the stmmac hardware requires the receive clock to be running for
   reset to complete. Depending on synthesis options, this requirement
   may also extend to writing various registers as well, e.g. setting
   the MAC address, writing some of the vlan registers, etc. Full
   details are in the databook.

   We add blocking/unblocking of the PHY receive clock-stop around
   parts of the main stmmac driver where we have a context that we
   can sleep. These are wrapped with the new phylink functions.

   However, depending on synthesis options, there could be other
   places where the net core calls the driver with a BH-disabled
   context where we can't sleep, and thus can't block the PHY from
   disabling its receive clock. These are documented with FIXME
   comments.

Given the last paragraph above, I am wondering whether a better
approach would be to ensure that receive clock-stop is always disabled
at the PHY with stmmac. From what I can see, implementations do not
document to this level of detail, which makes it difficult to tell
which registers require the receive clock to be running to behave
correctly.

This patch series has been tested on the Tegra194 Jetson Xavier NX
board kindly donated by NVidia, with two additional patches that are
pending in patchwork - the first is required to have EEE's LPI mode
passed through to the MAC on this platform to allow testing under
PHY clock-stop scenarios. The second is a bug fix for PHYLIB and
makes "eee off" functional, but should not affect this series.

All patches on top of net-next commit f749448ce9f1 ("Merge branch
'net-mlx5-hw-steering-cleanups'")

https://patchwork.kernel.org/project/netdevbpf/patch/E1ttnHW-00785s-Uq at rmk-PC.armlinux.org.uk/
https://patchwork.kernel.org/project/netdevbpf/patch/E1ttmWN-0077Mb-Q6 at rmk-PC.armlinux.org.uk/

 .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c    | 18 -----
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 46 ++++++++++--
 drivers/net/phy/phylink.c                          | 84 ++++++++++++++++++++++
 include/linux/phylink.h                            |  4 ++
 4 files changed, 129 insertions(+), 23 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From rmk+kernel at armlinux.org.uk  Thu Mar 20 15:11:07 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:07 +0000
Subject: [PATCH net-next 1/5] net: phylink: add phylink_prepare_resume()
In-Reply-To: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
References: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
Message-ID: <E1tvO6V-008Vjb-AP@rmk-PC.armlinux.org.uk>

When the system is suspended, the PHY may be placed in low-power mode
by setting the BMCR 0.11 Power down bit. IEEE 802.3 states that the
behaviour of the PHY in this state is implementation specific, and
the PHY is not required to meet the RX_CLK and TX_CLK requirements.
Essentially, this means that a PHY may stop the clocks that it is
generating while in power down state.

However, MACs exist which require the clocks from the PHY to be running
in order to properly resume. phylink_prepare_resume() provides them
with a way to clear the Power down bit early.

Note, however, that IEEE 802.3 gives PHYs up to 500ms grace before the
transmit and receive clocks meet the requirements after clearing the
power down bit.

Add a resume preparation function, which will ensure that the receive
clock from the PHY is appropriately configured while resuming.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 25 +++++++++++++++++++++++++
 include/linux/phylink.h   |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 0f70a7f3dfcc..1b76ddc286fe 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -2481,6 +2481,31 @@ void phylink_suspend(struct phylink *pl, bool mac_wol)
 }
 EXPORT_SYMBOL_GPL(phylink_suspend);
 
+/**
+ * phylink_prepare_resume() - prepare to resume a network device
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Optional, but if called must be called prior to phylink_resume().
+ *
+ * Prepare to resume a network device, preparing the PHY as necessary.
+ */
+void phylink_prepare_resume(struct phylink *pl)
+{
+	struct phy_device *phydev = pl->phydev;
+
+	ASSERT_RTNL();
+
+	/* IEEE 802.3 22.2.4.1.5 allows PHYs to stop their receive clock
+	 * when PDOWN is set. However, some MACs require RXC to be running
+	 * in order to resume. If the MAC requires RXC, and we have a PHY,
+	 * then resume the PHY. Note that 802.3 allows PHYs 500ms before
+	 * the clock meets requirements. We do not implement this delay.
+	 */
+	if (pl->config->mac_requires_rxc && phydev && phydev->suspended)
+		phy_resume(phydev);
+}
+EXPORT_SYMBOL_GPL(phylink_prepare_resume);
+
 /**
  * phylink_resume() - handle a network device resume event
  * @pl: a pointer to a &struct phylink returned from phylink_create()
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 79876c84ae81..06f1b649f173 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -707,6 +707,7 @@ void phylink_start(struct phylink *);
 void phylink_stop(struct phylink *);
 
 void phylink_suspend(struct phylink *pl, bool mac_wol);
+void phylink_prepare_resume(struct phylink *pl);
 void phylink_resume(struct phylink *pl);
 
 void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Thu Mar 20 15:11:12 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:12 +0000
Subject: [PATCH net-next 2/5] net: stmmac: address non-LPI resume failures
 properly
In-Reply-To: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
References: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
Message-ID: <E1tvO6a-008Vjh-FG@rmk-PC.armlinux.org.uk>

The Synopsys Designware GMAC core databook requires all clocks to be
active in order to complete software reset, which we perform during
resume.

However, IEEE 802.3 allows a PHY to stop its clocks when placed in
low-power mode, which happens when the system is suspended and WoL
is not enabled.

As an attempt to work around this, commit 36d18b5664ef ("net: stmmac:
start phylink instance before stmmac_hw_setup()") started phylink
early, but this has the side effect that the mac_link_up() method may
be called before or during the initialisation of GMAC hardware.

We also have the socfpga glue driver directly calling phy_resume()
also as an attempt to work around this.

In a previous commit, phylink_prepare_resume() has been introduced
to give MAC drivers a way to ensure that the PHY is resumed prior to
their initialisation of their MAC hardware. This commit adds the call,
and moves the phylink_resume() call back to where it should be before
the aforementioned commit.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a6a533d8a45b..860f800cd014 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7936,12 +7936,12 @@ int stmmac_resume(struct device *dev)
 	}
 
 	rtnl_lock();
-	phylink_resume(priv->phylink);
-	if (device_may_wakeup(priv->device) && !priv->plat->pmt)
-		phylink_speed_up(priv->phylink);
-	rtnl_unlock();
 
-	rtnl_lock();
+	/* Prepare the PHY to resume, ensuring that its clocks which are
+	 * necessary for the MAC DMA reset to complete are running
+	 */
+	phylink_prepare_resume(priv->phylink);
+
 	mutex_lock(&priv->lock);
 
 	stmmac_reset_queues_param(priv);
@@ -7959,6 +7959,15 @@ int stmmac_resume(struct device *dev)
 	stmmac_enable_all_dma_irq(priv);
 
 	mutex_unlock(&priv->lock);
+
+	/* phylink_resume() must be called after the hardware has been
+	 * initialised because it may bring the link up immediately in a
+	 * workqueue thread, which will race with initialisation.
+	 */
+	phylink_resume(priv->phylink);
+	if (device_may_wakeup(priv->device) && !priv->plat->pmt)
+		phylink_speed_up(priv->phylink);
+
 	rtnl_unlock();
 
 	netif_device_attach(ndev);
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Thu Mar 20 15:11:17 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:17 +0000
Subject: [PATCH net-next 3/5] net: stmmac: socfpga: remove phy_resume() call
In-Reply-To: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
References: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
Message-ID: <E1tvO6f-008Vjn-J1@rmk-PC.armlinux.org.uk>

As the previous commit addressed DWGMAC resuming with a PHY in
suspended state, there is now no need for socfpga to work around
this. Remove this code.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../ethernet/stmicro/stmmac/dwmac-socfpga.c    | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 6b78ae730466..116855658559 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -523,24 +523,6 @@ static int socfpga_dwmac_resume(struct device *dev)
 
 	dwmac_priv->ops->set_phy_mode(priv->plat->bsp_priv);
 
-	/* Before the enet controller is suspended, the phy is suspended.
-	 * This causes the phy clock to be gated. The enet controller is
-	 * resumed before the phy, so the clock is still gated "off" when
-	 * the enet controller is resumed. This code makes sure the phy
-	 * is "resumed" before reinitializing the enet controller since
-	 * the enet controller depends on an active phy clock to complete
-	 * a DMA reset. A DMA reset will "time out" if executed
-	 * with no phy clock input on the Synopsys enet controller.
-	 * Verified through Synopsys Case #8000711656.
-	 *
-	 * Note that the phy clock is also gated when the phy is isolated.
-	 * Phy "suspend" and "isolate" controls are located in phy basic
-	 * control register 0, and can be modified by the phy driver
-	 * framework.
-	 */
-	if (ndev->phydev)
-		phy_resume(ndev->phydev);
-
 	return stmmac_resume(dev);
 }
 #endif /* CONFIG_PM_SLEEP */
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Thu Mar 20 15:11:22 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:22 +0000
Subject: [PATCH net-next 4/5] net: phylink: add functions to block/unblock rx
 clock stop
In-Reply-To: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
References: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
Message-ID: <E1tvO6k-008Vjt-MZ@rmk-PC.armlinux.org.uk>

Some MACs require the PHY receive clock to be running to complete setup
actions. This may fail if the PHY has negotiated EEE, the MAC supports
receive clock stop, and the link has entered LPI state. Provide a pair
of APIs that MAC drivers can use to temporarily block the PHY disabling
the receive clock.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 59 +++++++++++++++++++++++++++++++++++++++
 include/linux/phylink.h   |  3 ++
 2 files changed, 62 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 1b76ddc286fe..2cf389c68913 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -89,6 +89,7 @@ struct phylink {
 	bool mac_enable_tx_lpi;
 	bool mac_tx_clk_stop;
 	u32 mac_tx_lpi_timer;
+	u8 mac_rx_clk_stop_blocked;
 
 	struct sfp_bus *sfp_bus;
 	bool sfp_may_have_phy;
@@ -2437,6 +2438,64 @@ void phylink_stop(struct phylink *pl)
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
+/**
+ * phylink_rx_clk_stop_block() - block PHY ability to stop receive clock in LPI
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Disable the PHY's ability to stop the receive clock while the receive path
+ * is in EEE LPI state, until the number of calls to phylink_rx_clk_stop_block()
+ * are balanced by calls to phylink_rx_clk_stop_unblock().
+ */
+void phylink_rx_clk_stop_block(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == U8_MAX) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Disable PHY receive clock stop if this is the first time this
+	 * function has been called and clock-stop was previously enabled.
+	 */
+	if (pl->mac_rx_clk_stop_blocked++ == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, false);
+}
+EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_block);
+
+/**
+ * phylink_rx_clk_stop_unblock() - unblock PHY ability to stop receive clock
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * All calls to phylink_rx_clk_stop_block() must be balanced with a
+ * corresponding call to phylink_rx_clk_stop_unblock() to restore the PHYs
+ * ability to stop the receive clock when the receive path is in EEE LPI mode.
+ */
+void phylink_rx_clk_stop_unblock(struct phylink *pl)
+{
+	ASSERT_RTNL();
+
+	if (pl->mac_rx_clk_stop_blocked == 0) {
+		phylink_warn(pl, "%s called too many times - ignoring\n",
+			     __func__);
+		dump_stack();
+		return;
+	}
+
+	/* Re-enable PHY receive clock stop if the number of unblocks matches
+	 * the number of calls to the block function above.
+	 */
+	if (--pl->mac_rx_clk_stop_blocked == 0 &&
+	    pl->mac_supports_eee_ops && pl->phydev &&
+	    pl->config->eee_rx_clk_stop_enable)
+		phy_eee_rx_clock_stop(pl->phydev, true);
+}
+EXPORT_SYMBOL_GPL(phylink_rx_clk_stop_unblock);
+
 /**
  * phylink_suspend() - handle a network device suspend event
  * @pl: a pointer to a &struct phylink returned from phylink_create()
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 06f1b649f173..1f5773ab5660 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -706,6 +706,9 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
 void phylink_start(struct phylink *);
 void phylink_stop(struct phylink *);
 
+void phylink_rx_clk_stop_block(struct phylink *);
+void phylink_rx_clk_stop_unblock(struct phylink *);
+
 void phylink_suspend(struct phylink *pl, bool mac_wol);
 void phylink_prepare_resume(struct phylink *pl);
 void phylink_resume(struct phylink *pl);
-- 
2.30.2



From rmk+kernel at armlinux.org.uk  Thu Mar 20 15:11:27 2025
From: rmk+kernel at armlinux.org.uk (Russell King (Oracle))
Date: Thu, 20 Mar 2025 22:11:27 +0000
Subject: [PATCH net-next 5/5] net: stmmac: block PHY RXC clock-stop
In-Reply-To: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
References: <Z9ySeo61VYTClIJJ@shell.armlinux.org.uk>
Message-ID: <E1tvO6p-008Vjz-Qy@rmk-PC.armlinux.org.uk>

The DesignWare core requires the receive clock to be running during
certain operations. Ensure that we block PHY RXC clock-stop during
these operations.

This is a best-efforts change - not everywhere can be covered by this
because of net's core locking, which means we can't access the MDIO
bus to configure the PHY to disable RXC clock-stop in certain areas.
These are marked with FIXME comments.

Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 860f800cd014..a4f2c98e851a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3484,9 +3484,18 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
 	if (priv->hw->phylink_pcs)
 		phylink_pcs_pre_init(priv->phylink, priv->hw->phylink_pcs);
 
+	/* Note that clk_rx_i must be running for reset to complete. This
+	 * clock may also be required when setting the MAC address.
+	 *
+	 * Block the receive clock stop for LPI mode at the PHY in case
+	 * the link is established with EEE mode active.
+	 */
+	phylink_rx_clk_stop_block(priv->phylink);
+
 	/* DMA initialization and SW reset */
 	ret = stmmac_init_dma_engine(priv);
 	if (ret < 0) {
+		phylink_rx_clk_stop_unblock(priv->phylink);
 		netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
 			   __func__);
 		return ret;
@@ -3494,6 +3503,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
 
 	/* Copy the MAC addr into the HW  */
 	stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 
 	/* PS and related bits will be programmed according to the speed */
 	if (priv->hw->pcs) {
@@ -3604,7 +3614,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
 	/* Start the ball rolling... */
 	stmmac_start_all_dma(priv);
 
+	phylink_rx_clk_stop_block(priv->phylink);
 	stmmac_set_hw_vlan_mode(priv, priv->hw);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 
 	return 0;
 }
@@ -5888,6 +5900,9 @@ static void stmmac_tx_timeout(struct net_device *dev, unsigned int txqueue)
  *  whenever multicast addresses must be enabled/disabled.
  *  Return value:
  *  void.
+ *
+ *  FIXME: This may need RXC to be running, but it may be called with BH
+ *  disabled, which means we can't call phylink_rx_clk_stop*().
  */
 static void stmmac_set_rx_mode(struct net_device *dev)
 {
@@ -6020,7 +6035,9 @@ static int stmmac_set_features(struct net_device *netdev,
 	else
 		priv->hw->hw_vlan_en = false;
 
+	phylink_rx_clk_stop_block(priv->phylink);
 	stmmac_set_hw_vlan_mode(priv, priv->hw);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 
 	return 0;
 }
@@ -6304,7 +6321,9 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
 	if (ret)
 		goto set_mac_error;
 
+	phylink_rx_clk_stop_block(priv->phylink);
 	stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 
 set_mac_error:
 	pm_runtime_put(priv->device);
@@ -6660,6 +6679,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
 	return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
 }
 
+/* FIXME: This may need RXC to be running, but it may be called with BH
+ * disabled, which means we can't call phylink_rx_clk_stop*().
+ */
 static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
@@ -6691,6 +6713,9 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
 	return ret;
 }
 
+/* FIXME: This may need RXC to be running, but it may be called with BH
+ * disabled, which means we can't call phylink_rx_clk_stop*().
+ */
 static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
@@ -7951,9 +7976,11 @@ int stmmac_resume(struct device *dev)
 
 	stmmac_hw_setup(ndev, false);
 	stmmac_init_coalesce(priv);
+	phylink_rx_clk_stop_block(priv->phylink);
 	stmmac_set_rx_mode(ndev);
 
 	stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
+	phylink_rx_clk_stop_unblock(priv->phylink);
 
 	stmmac_enable_all_queues(priv);
 	stmmac_enable_all_dma_irq(priv);
-- 
2.30.2



From andi.shyti at kernel.org  Thu Mar 20 15:13:03 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Thu, 20 Mar 2025 23:13:03 +0100
Subject: [PATCH v4 1/2] aspeed: i2c: add clock duty cycle property
In-Reply-To: <20220610054722.32229-2-potin.lai.pt@gmail.com>
References: <20220610054722.32229-1-potin.lai.pt@gmail.com>
 <20220610054722.32229-2-potin.lai.pt@gmail.com>
Message-ID: <jcznjekoig6n5jtispbgxn6ingzteodwb5lib77evsvvufldoh@ia57mjlvie5k>

Hi Potin,

On Fri, Jun 10, 2022 at 01:47:21PM +0800, Potin Lai wrote:
> Introduce i2c-clk-high-min-percent property for setting a minimum clock
> high percentage.
> 
> This driver calculate clk_high and clk_low with giving duty cycle. If it
> could not find a suit clk_high and clk_low, it apply default duty cycle
> 50%.
> 
> Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>

if you have still interest in getting this patch applied, may I
ask you to please resubmit it?

Thanks,
Andi


From bryan.odonoghue at linaro.org  Thu Mar 20 15:08:38 2025
From: bryan.odonoghue at linaro.org (Bryan O'Donoghue)
Date: Thu, 20 Mar 2025 22:08:38 +0000
Subject: [PATCH v1 3/3] arm64: dts: qcom: x1e80100-qcp: Add power control
 and sideband signals for PCIe3
In-Reply-To: <20250320055502.274849-4-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <w7mbnqG7DHPCH6hVoSu4E2p8pV7Rw6uvurlK-CUxF7TYQ53fFyagxmLUCmCTfG0DOUgIQn7GdppXgBlq8Gyv9Q==@protonmail.internalid>
 <20250320055502.274849-4-quic_wenbyao@quicinc.com>
Message-ID: <54c588be-d630-4901-8885-a042b477f168@linaro.org>

On 20/03/2025 05:55, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Add perst, wake and clkreq sideband signals and required regulators in
> PCIe3 controller and PHY device tree node. Describe the voltage rails of
> the x8 PCI slots for PCIe3 port.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>   arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
>   1 file changed, 119 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> index 28086a2bc..9cd313802 100644
> --- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> +++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> @@ -318,6 +318,48 @@ vreg_wcn_3p3: regulator-wcn-3p3 {
>   		regulator-boot-on;
>   	};
> 
> +	vreg_pcie_12v: regulator-pcie_12v {
> +		compatible = "regulator-fixed";
> +
> +		regulator-name = "VREG_PCIE_12V";
> +		regulator-min-microvolt = <12000000>;
> +		regulator-max-microvolt = <12000000>;
> +
> +		gpio = <&pm8550ve_8_gpios 8 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pcie_x8_12v>;
> +	};
> +
> +	vreg_pcie_3v3_aux: regulator-pcie_3v3_aux {
> +		compatible = "regulator-fixed";
> +
> +		regulator-name = "VREG_PCIE_3P3_AUX";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +
> +		gpio = <&pmc8380_3_gpios 8 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pm_sde7_aux_3p3_en>;
> +	};
> +
> +	vreg_pcie_3v3: regulator-pcie_3v3 {
> +		compatible = "regulator-fixed";
> +
> +		regulator-name = "VREG_PCIE_3P3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +
> +		gpio = <&pmc8380_3_gpios 6 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pm_sde7_main_3p3_en>;
> +};
> +
>   	usb-1-ss0-sbu-mux {
>   		compatible = "onnn,fsusb42", "gpio-sbu-mux";
> 
> @@ -907,6 +949,60 @@ &mdss_dp3_phy {
>   	status = "okay";
>   };
> 
> +&pm8550ve_8_gpios {
> +	pcie_x8_12v: pcie-12v-default-state {
> +		pins = "gpio8";
> +		function = "normal";
> +		output-enable;
> +		output-high;
> +		bias-pull-down;
> +		power-source = <0>;
> +	};
> +};
> +
> +&pmc8380_3_gpios {
> +	pm_sde7_aux_3p3_en: pcie-aux-3p3-default-state {
> +		pins = "gpio8";
> +		function = "normal";
> +		output-enable;
> +		output-high;
> +		bias-pull-down;
> +		power-source = <0>;
> +	};
> +
> +	pm_sde7_main_3p3_en: pcie-main-3p3-default-state {
> +		pins = "gpio6";
> +		function = "normal";
> +		output-enable;
> +		output-high;
> +		bias-pull-down;
> +		power-source = <0>;
> +	};
> +};
> +
> +&pcie3 {
> +
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie3_default>;
> +	perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
> +	wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&pcie3_phy {
> +	vdda-phy-supply = <&vreg_l3j_0p8>;
> +	vdda-pll-supply = <&vreg_l3e_1p2>;
> +	vdda-qref-supply = <&vreg_l3c_0p8>;
> +
> +	status = "okay";
> +};
> +
> +&pcie3port {
> +	vpcie12v-supply = <&vreg_pcie_12v>;
> +	vpcie3v3-supply = <&vreg_pcie_3v3>;
> +	vpcie3v3aux-supply = <&vreg_pcie_3v3_aux>;
> +};
> +
>   &pcie4 {
>   	perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>;
>   	wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
> @@ -1118,6 +1214,29 @@ nvme_reg_en: nvme-reg-en-state {
>   		bias-disable;
>   	};
> 
> +	pcie3_default: pcie3-default-state {
> +		clkreq-n-pins {
> +			pins = "gpio144";
> +			function = "pcie3_clk";
> +			drive-strength = <2>;
> +			bias-pull-up;
> +		};
> +
> +		perst-n-pins {
> +			pins = "gpio143";
> +			function = "gpio";
> +			drive-strength = <2>;
> +			bias-pull-down;
> +		};
> +
> +		wake-n-pins {
> +		       pins = "gpio145";
> +		       function = "gpio";
> +		       drive-strength = <2>;
> +		       bias-pull-up;
> +		};
> +	};
> +
>   	pcie4_default: pcie4-default-state {
>   		clkreq-n-pins {
>   			pins = "gpio147";
> --
> 2.34.1
> 
> 

Recommend breaking this patch into at least two patches @ the and

-> Add power control
-> Add sideband signals

if your patch title requires an and its usually a good indicator of a 
place to break that patch into different parts.

---
bod


From daniel at makrotopia.org  Thu Mar 20 15:08:42 2025
From: daniel at makrotopia.org (Daniel Golle)
Date: Thu, 20 Mar 2025 22:08:42 +0000
Subject: [PATCH v5 1/1] i2c: mediatek: add runtime PM operations and bus
 regulator control
In-Reply-To: <fqicrglyug7gmkmysok7hilhmkyhxmnkztzv4iffgry6xce6t3@2i6b2ihfu4rb>
References: <20250314145407.2900190-1-zoie.lin@mediatek.com>
 <fqicrglyug7gmkmysok7hilhmkyhxmnkztzv4iffgry6xce6t3@2i6b2ihfu4rb>
Message-ID: <Z9yR6pyg1mtqKynh@makrotopia.org>

Hi Andi,
Hi Zoie,

On Wed, Mar 19, 2025 at 12:34:53AM +0100, Andi Shyti wrote:
> Hi Zoie,
> 
> On Fri, Mar 14, 2025 at 10:53:43PM +0800, Zoie Lin wrote:
> > Introduce support for runtime PM operations in
> > the I2C driver, enabling runtime suspend and resume functionality.
> > 
> > Although in most platforms, the bus power of i2c is always
> > on, some platforms disable the i2c bus power in order to meet
> > low power request.
> > 
> > This implementation includes bus regulator control to facilitate
> > proper handling of the bus power based on platform requirements.
> > 
> > Signed-off-by: Zoie Lin <zoie.lin at mediatek.com>
> 
> merged to i2c/i2c-host.

the change causes a crash during boot on MT7988 which typically uses
one of its I2C busses to connect a Richtek RT5190A PMIC.

[    1.465158] SError Interrupt on CPU3, code 0x00000000bf000002 -- SError
[    1.465170] CPU: 3 UID: 0 PID: 40 Comm: kworker/u16:1 Not tainted 6.14.0-rc7-next-20250320+ #0 NONE 
[    1.465178] Hardware name: SmartRG SDG-9000 (DT)
[    1.465180] Workqueue: async async_run_entry_fn
[    1.465194] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    1.465199] pc : mtk_i2c_transfer+0x27c/0x1108
[    1.465208] lr : mtk_i2c_transfer+0x224/0x1108
[    1.465212] sp : ffffffc0821538e0
[    1.465213] x29: ffffffc0821538e0 x28: 0000000000000000 x27: ffffffc082153a00
[    1.465220] x26: 00000000ffff8b62 x25: ffffffc080f3b000 x24: 0000000000000000
[    1.465225] x23: 0000000000000001 x22: ffffff80c0ba7810 x21: 000000000000000f
[    1.465230] x20: ffffffc082153a10 x19: ffffff80c9620080 x18: 0000000000000014
[    1.465236] x17: 000000005f52c058 x16: 00000000c071d659 x15: 0000000013b9e9aa
[    1.465241] x14: 00000000305bde35 x13: ffffff80c5f222e8 x12: ffffff80c5f222b0
[    1.465246] x11: 0000000000001e20 x10: ffffffc0811097d8 x9 : 0000000000000001
[    1.465251] x8 : ffffffc082153830 x7 : ffffffc0821538a0 x6 : ffffffc082153840
[    1.465256] x5 : 000000000000ffed x4 : 0000000000000003 x3 : ffffffc080b798b0
[    1.465260] x2 : 0000000000000000 x1 : ffffffc080b797d8 x0 : 0000000000000064
[    1.465267] Kernel panic - not syncing: Asynchronous SError Interrupt
[    1.465269] SMP: stopping secondary CPUs
[    1.465281] Kernel Offset: disabled
[    1.465282] CPU features: 0x0000,00000040,00000000,8200400b
[    1.465286] Memory Limit: none
[    1.466353] 
[    1.466355] ================================
[    1.466356] WARNING: inconsistent lock state
[    1.466357] 6.14.0-rc7-next-20250320+ #0 Not tainted
[    1.466360] --------------------------------
[    1.466361] inconsistent {INITIAL USE} -> {IN-NMI} usage.
[    1.466364] kworker/u16:1/40 [HC1[1]:SC0[0]:HE0:SE1] takes:
[    1.466369] ffffff80c0357940 (&prz->buffer_lock){....}-{2:2}, at: buffer_size_add+0x68/0x84
[    1.466384] {INITIAL USE} state was registered at:
[    1.466386]   lock_acquire+0xf4/0x2d8
[    1.466391]   _raw_spin_lock_irqsave+0x5c/0x80
[    1.466399]   buffer_size_add+0x68/0x84
[    1.466404]   persistent_ram_write+0x44/0x11c
[    1.466410]   ramoops_pstore_write+0x150/0x1c4
[    1.466415]   pstore_console_write+0x4c/0x5c
[    1.466420]   console_flush_all+0x2ac/0x490
[    1.466425]   console_unlock+0x68/0x144
[    1.466430]   vprintk_emit+0x168/0x3ac
[    1.466434]   vprintk_default+0x34/0x3c
[    1.466439]   vprintk+0x24/0x2c
[    1.466444]   _printk+0x48/0x50
[    1.466448]   register_console+0x370/0x4c4
[    1.466453]   pstore_register+0x18c/0x37c
[    1.466457]   ramoops_probe+0x2e8/0x5c4
[    1.466461]   platform_probe+0x64/0xbc
[    1.466467]   really_probe+0xbc/0x388
[    1.466470]   __driver_probe_device+0x78/0x154
[    1.466474]   driver_probe_device+0x3c/0xd4
[    1.466477]   __device_attach_driver+0xb0/0x144
[    1.466480]   bus_for_each_drv+0x6c/0xb0
[    1.466486]   __device_attach+0x9c/0x19c
[    1.466489]   device_initial_probe+0x10/0x18
[    1.466493]   bus_probe_device+0xa8/0xac
[    1.466495]   device_add+0x58c/0x790
[    1.466500]   of_device_add+0x4c/0x58
[    1.466507]   of_platform_device_create_pdata+0x9c/0x118
[    1.466512]   of_platform_default_populate_init+0x4c/0xf0
[    1.466519]   do_one_initcall+0x64/0x324
[    1.466524]   kernel_init_freeable+0x298/0x4f0
[    1.466530]   kernel_init+0x1c/0x1c8
[    1.466534]   ret_from_fork+0x10/0x20
[    1.466538] irq event stamp: 3498
[    1.466539] hardirqs last  enabled at (3497): [<ffffffc080ac0b78>] _raw_spin_unlock_irqrestore+0x54/0x74
[    1.466546] hardirqs last disabled at (3498): [<ffffffc080ab43c4>] el1h_64_error_handler+0x20/0x48
[    1.466551] softirqs last  enabled at (3392): [<ffffffc08004af28>] handle_softirqs+0x46c/0x484
[    1.466558] softirqs last disabled at (3381): [<ffffffc080010170>] __do_softirq+0x10/0x18
[    1.466562] 
[    1.466562] other info that might help us debug this:
[    1.466564]  Possible unsafe locking scenario:
[    1.466564] 
[    1.466565]        CPU0
[    1.466566]        ----
[    1.466567]   lock(&prz->buffer_lock);
[    1.466570]   <Interrupt>
[    1.466571]     lock(&prz->buffer_lock);
[    1.466573] 
[    1.466573]  *** DEADLOCK ***
[    1.466573] 
[    1.466575] 5 locks held by kworker/u16:1/40:
[    1.466578]  #0: ffffff80c01b2148 ((wq_completion)async){+.+.}-{0:0}, at: process_one_work+0x1a8/0x610
[    1.466588]  #1: ffffffc082153dd8 ((work_completion)(&entry->work)){+.+.}-{0:0}, at: process_one_work+0x1d0/0x610
[    1.466598]  #2: ffffff80c7b3f908 (&dev->mutex){....}-{4:4}, at: __device_attach_async_helper+0x28/0xec
[    1.466606]  #3: ffffff80c5f22068 (rt5190a_regulator:443:(&rt5190a_regmap_config)->lock){+.+.}-{4:4}, at: regmap_lock_mutex+0x10/0x18
[    1.466617]  #4: ffffff80c9620100 (i2c_register_adapter){+.+.}-{4:4}, at: i2c_adapter_lock_bus+0x20/0x2c
[    1.466629] 
[    1.466629] stack backtrace:
[    1.466630] CPU: 3 UID: 0 PID: 40 Comm: kworker/u16:1 Not tainted 6.14.0-rc7-next-20250320+ #0 NONE 
[    1.466635] Hardware name: SmartRG SDG-9000 (DT)
[    1.466637] Workqueue: async async_run_entry_fn
[    1.466643] Call trace:
[    1.466645]  show_stack+0x14/0x1c (C)
[    1.466653]  dump_stack_lvl+0x30/0xc0
[    1.466657]  dump_stack+0x14/0x1c
[    1.466661]  print_usage_bug.part.0+0x26c/0x318
[    1.466665]  lock_acquire+0x280/0x2d8
[    1.466669]  _raw_spin_lock_irqsave+0x5c/0x80
[    1.466676]  buffer_size_add+0x68/0x84
[    1.466681]  persistent_ram_write+0x44/0x11c
[    1.466687]  ramoops_pstore_write+0xc8/0x1c4
[    1.466692]  pstore_dump+0x16c/0x300
[    1.466697]  kmsg_dump_desc+0xc0/0x194
[    1.466703]  panic+0x170/0x38c
[    1.466708]  nmi_panic+0x50/0x64
[    1.466712]  arm64_serror_panic+0x60/0x70
[    1.466715]  do_serror+0x38/0x68
[    1.466719]  el1h_64_error_handler+0x34/0x48
[    1.466723]  el1h_64_error+0x70/0x74
[    1.466727]  mtk_i2c_transfer+0x27c/0x1108 (P)
[    1.466732]  __i2c_transfer+0x1f8/0x948
[    1.466736]  i2c_transfer+0x90/0xe8
[    1.466739]  regmap_i2c_read+0x48/0x70
[    1.466744]  _regmap_raw_read+0x110/0x328
[    1.466750]  regmap_raw_read+0x130/0x240
[    1.466755]  rt5190a_probe+0x88/0x53c
[    1.466761]  i2c_device_probe+0x154/0x2ec
[    1.466764]  really_probe+0xbc/0x388
[    1.466768]  __driver_probe_device+0x78/0x154
[    1.466772]  driver_probe_device+0x3c/0xd4
[    1.466776]  __device_attach_driver+0xb0/0x144
[    1.466780]  bus_for_each_drv+0x6c/0xb0
[    1.466785]  __device_attach_async_helper+0x80/0xec
[    1.466790]  async_run_entry_fn+0x34/0x17c
[    1.466794]  process_one_work+0x224/0x610
[    1.466799]  worker_thread+0x1b4/0x348
[    1.466804]  kthread+0x108/0x1d4
[    1.466808]  ret_from_fork+0x10/0x20

Reverting commit 4b60b1b58696 (i2c: mediatek: add runtime PM operations
and bus regulator control") fixes the issue.


From andi.shyti at kernel.org  Thu Mar 20 15:18:17 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Thu, 20 Mar 2025 23:18:17 +0100
Subject: [RESEND 0/3] i2c: at91: Fixes and updates
In-Reply-To: <20220614101347.16910-1-codrin.ciubotariu@microchip.com>
References: <20220614101347.16910-1-codrin.ciubotariu@microchip.com>
Message-ID: <odbnk4zvjprs4ipdtxjeurdrubx3eu7zcmxkpwodlz6idnw3t7@6d2a4hl4dpe2>

Hi Codrin,

> Codrin Ciubotariu (3):
>   i2c: at91: move i2c_recover_bus() outside of at91_do_twi_transfer()
>   i2c: at91: keep the controller disabled when it is not used
>   i2c: at91: add advanced digital filtering support for SAMA5D4

if you still have interest in applying this patch, may I please
ask you to resend it?

Thanks,
Andi


From lkp at intel.com  Thu Mar 20 15:33:12 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 06:33:12 +0800
Subject: [soc:soc/defconfig] BUILD SUCCESS
 701340d3b78bcd72fee54aa481b5a4ac84c7ff2a
Message-ID: <202503210606.Ux5TtELF-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/defconfig
branch HEAD: 701340d3b78bcd72fee54aa481b5a4ac84c7ff2a  Merge tag 'qcom-arm64-defconfig-for-6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/defconfig

elapsed time: 1444m

configs tested: 13
configs skipped: 119

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
arm               allmodconfig    gcc-14.2.0
arm                allnoconfig    clang-21
arm               allyesconfig    gcc-14.2.0
arm    randconfig-001-20250320    clang-20
arm    randconfig-002-20250320    clang-16
arm    randconfig-003-20250320    gcc-8.5.0
arm    randconfig-004-20250320    gcc-6.5.0
arm64             allmodconfig    clang-19
arm64              allnoconfig    gcc-14.2.0
arm64  randconfig-001-20250320    clang-21
arm64  randconfig-002-20250320    clang-21
arm64  randconfig-003-20250320    clang-19
arm64  randconfig-004-20250320    gcc-8.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From lkp at intel.com  Thu Mar 20 15:33:19 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 06:33:19 +0800
Subject: [soc:soc/arm] BUILD SUCCESS
 911a44cf6ddcb809ef5a5e0345986285a62ef462
Message-ID: <202503210613.9HDHKE0X-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/arm
branch HEAD: 911a44cf6ddcb809ef5a5e0345986285a62ef462  Merge tag 'at91-soc-6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/arm

elapsed time: 1444m

configs tested: 239
configs skipped: 4

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
alpha                            allyesconfig    clang-19
alpha                            allyesconfig    gcc-9.3.0
alpha                               defconfig    gcc-14.2.0
arc                              allmodconfig    clang-19
arc                              allmodconfig    gcc-14.2.0
arc                               allnoconfig    gcc-14.2.0
arc                              allyesconfig    clang-19
arc                              allyesconfig    gcc-14.2.0
arc                                 defconfig    gcc-14.2.0
arc                         haps_hs_defconfig    gcc-14.2.0
arc                        nsimosci_defconfig    gcc-14.2.0
arc                   randconfig-001-20250320    gcc-10.5.0
arc                   randconfig-001-20250321    clang-21
arc                   randconfig-002-20250320    gcc-8.5.0
arc                   randconfig-002-20250321    clang-21
arm                              allmodconfig    clang-19
arm                              allmodconfig    gcc-14.2.0
arm                               allnoconfig    gcc-14.2.0
arm                              allyesconfig    clang-19
arm                              allyesconfig    gcc-14.2.0
arm                         assabet_defconfig    gcc-14.2.0
arm                                 defconfig    gcc-14.2.0
arm                            dove_defconfig    gcc-14.2.0
arm                   randconfig-001-20250320    clang-20
arm                   randconfig-001-20250321    clang-21
arm                   randconfig-002-20250320    clang-16
arm                   randconfig-002-20250321    clang-21
arm                   randconfig-003-20250320    gcc-8.5.0
arm                   randconfig-003-20250321    clang-21
arm                   randconfig-004-20250320    gcc-7.5.0
arm                   randconfig-004-20250321    clang-21
arm                           sama7_defconfig    gcc-14.2.0
arm                           stm32_defconfig    gcc-14.2.0
arm                       versatile_defconfig    gcc-14.2.0
arm                         wpcm450_defconfig    gcc-14.2.0
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-14.2.0
arm64                               defconfig    gcc-14.2.0
arm64                 randconfig-001-20250320    clang-21
arm64                 randconfig-001-20250321    clang-21
arm64                 randconfig-002-20250320    clang-21
arm64                 randconfig-002-20250321    clang-21
arm64                 randconfig-003-20250320    clang-19
arm64                 randconfig-003-20250321    clang-21
arm64                 randconfig-004-20250320    gcc-8.5.0
arm64                 randconfig-004-20250321    clang-21
csky                              allnoconfig    gcc-14.2.0
csky                                defconfig    gcc-14.2.0
csky                  randconfig-001-20250320    gcc-10.5.0
csky                  randconfig-001-20250321    gcc-7.5.0
csky                  randconfig-002-20250320    gcc-14.2.0
csky                  randconfig-002-20250321    gcc-7.5.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    clang-19
hexagon                           allnoconfig    gcc-14.2.0
hexagon                          allyesconfig    clang-19
hexagon                          allyesconfig    clang-21
hexagon                             defconfig    gcc-14.2.0
hexagon               randconfig-001-20250320    clang-18
hexagon               randconfig-001-20250321    gcc-7.5.0
hexagon               randconfig-002-20250320    clang-21
hexagon               randconfig-002-20250321    gcc-7.5.0
i386                             allmodconfig    clang-20
i386                             allmodconfig    gcc-12
i386                              allnoconfig    clang-20
i386                              allnoconfig    gcc-12
i386                             allyesconfig    clang-20
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250320    gcc-12
i386        buildonly-randconfig-002-20250320    clang-20
i386        buildonly-randconfig-003-20250320    clang-20
i386        buildonly-randconfig-004-20250320    clang-20
i386        buildonly-randconfig-005-20250320    gcc-12
i386        buildonly-randconfig-006-20250320    clang-20
i386                                defconfig    clang-20
i386                  randconfig-001-20250321    clang-20
i386                  randconfig-002-20250321    clang-20
i386                  randconfig-003-20250321    clang-20
i386                  randconfig-004-20250321    clang-20
i386                  randconfig-005-20250321    clang-20
i386                  randconfig-006-20250321    clang-20
i386                  randconfig-007-20250321    clang-20
i386                  randconfig-011-20250321    clang-20
i386                  randconfig-012-20250321    clang-20
i386                  randconfig-013-20250321    clang-20
i386                  randconfig-014-20250321    clang-20
i386                  randconfig-015-20250321    clang-20
i386                  randconfig-016-20250321    clang-20
i386                  randconfig-017-20250321    clang-20
loongarch                        allmodconfig    gcc-12.4.0
loongarch                         allnoconfig    gcc-14.2.0
loongarch                           defconfig    gcc-14.2.0
loongarch             randconfig-001-20250320    gcc-14.2.0
loongarch             randconfig-001-20250321    gcc-7.5.0
loongarch             randconfig-002-20250320    gcc-12.4.0
loongarch             randconfig-002-20250321    gcc-7.5.0
m68k                             allmodconfig    gcc-8.5.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-6.5.0
m68k                                defconfig    gcc-14.2.0
microblaze                       allmodconfig    gcc-9.3.0
microblaze                        allnoconfig    gcc-14.2.0
microblaze                       allyesconfig    gcc-9.3.0
microblaze                          defconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
mips                   sb1250_swarm_defconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                               defconfig    gcc-14.2.0
nios2                 randconfig-001-20250320    gcc-6.5.0
nios2                 randconfig-001-20250321    gcc-7.5.0
nios2                 randconfig-002-20250320    gcc-12.4.0
nios2                 randconfig-002-20250321    gcc-7.5.0
openrisc                          allnoconfig    clang-15
openrisc                         allyesconfig    gcc-14.2.0
openrisc                            defconfig    gcc-12
openrisc                  or1klitex_defconfig    gcc-14.2.0
parisc                           allmodconfig    gcc-14.2.0
parisc                            allnoconfig    clang-15
parisc                           allyesconfig    gcc-14.2.0
parisc                              defconfig    gcc-12
parisc                randconfig-001-20250320    gcc-13.3.0
parisc                randconfig-001-20250321    gcc-7.5.0
parisc                randconfig-002-20250320    gcc-11.5.0
parisc                randconfig-002-20250321    gcc-7.5.0
parisc64                            defconfig    gcc-14.2.0
powerpc                          allmodconfig    gcc-14.2.0
powerpc                           allnoconfig    clang-15
powerpc                          allyesconfig    clang-21
powerpc                          allyesconfig    gcc-14.2.0
powerpc                     mpc83xx_defconfig    gcc-14.2.0
powerpc               randconfig-001-20250320    gcc-6.5.0
powerpc               randconfig-001-20250321    gcc-7.5.0
powerpc               randconfig-002-20250320    clang-21
powerpc               randconfig-002-20250321    gcc-7.5.0
powerpc               randconfig-003-20250320    clang-21
powerpc               randconfig-003-20250321    gcc-7.5.0
powerpc                     tqm5200_defconfig    gcc-14.2.0
powerpc                     tqm8541_defconfig    gcc-14.2.0
powerpc64             randconfig-001-20250320    clang-21
powerpc64             randconfig-001-20250321    gcc-7.5.0
powerpc64             randconfig-002-20250320    gcc-8.5.0
powerpc64             randconfig-002-20250321    gcc-7.5.0
powerpc64             randconfig-003-20250320    clang-21
powerpc64             randconfig-003-20250321    gcc-7.5.0
riscv                            allmodconfig    clang-21
riscv                            allmodconfig    gcc-14.2.0
riscv                             allnoconfig    clang-15
riscv                            allyesconfig    clang-16
riscv                            allyesconfig    gcc-14.2.0
riscv                               defconfig    gcc-12
riscv                 randconfig-001-20250320    clang-21
riscv                 randconfig-001-20250321    gcc-6.5.0
riscv                 randconfig-002-20250320    gcc-8.5.0
riscv                 randconfig-002-20250321    gcc-6.5.0
s390                             alldefconfig    gcc-14.2.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    gcc-14.2.0
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                             allyesconfig    gcc-8.5.0
s390                          debug_defconfig    gcc-14.2.0
s390                                defconfig    gcc-12
s390                  randconfig-001-20250320    gcc-5.5.0
s390                  randconfig-001-20250321    gcc-6.5.0
s390                  randconfig-002-20250320    gcc-7.5.0
s390                  randconfig-002-20250321    gcc-6.5.0
sh                               allmodconfig    gcc-14.2.0
sh                               allmodconfig    gcc-9.3.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                                  defconfig    gcc-12
sh                    randconfig-001-20250320    gcc-14.2.0
sh                    randconfig-001-20250321    gcc-6.5.0
sh                    randconfig-002-20250320    gcc-10.5.0
sh                    randconfig-002-20250321    gcc-6.5.0
sparc                            allmodconfig    gcc-14.2.0
sparc                            allmodconfig    gcc-6.5.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250320    gcc-7.5.0
sparc                 randconfig-001-20250321    gcc-6.5.0
sparc                 randconfig-002-20250320    gcc-7.5.0
sparc                 randconfig-002-20250321    gcc-6.5.0
sparc64                             defconfig    gcc-12
sparc64               randconfig-001-20250320    gcc-5.5.0
sparc64               randconfig-001-20250321    gcc-6.5.0
sparc64               randconfig-002-20250320    gcc-13.3.0
sparc64               randconfig-002-20250321    gcc-6.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-15
um                               allyesconfig    clang-19
um                               allyesconfig    gcc-12
um                                  defconfig    gcc-12
um                             i386_defconfig    gcc-12
um                    randconfig-001-20250320    gcc-12
um                    randconfig-001-20250321    gcc-6.5.0
um                    randconfig-002-20250320    clang-16
um                    randconfig-002-20250321    gcc-6.5.0
um                           x86_64_defconfig    gcc-12
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250320    clang-20
x86_64      buildonly-randconfig-001-20250321    clang-20
x86_64      buildonly-randconfig-002-20250320    gcc-12
x86_64      buildonly-randconfig-002-20250321    clang-20
x86_64      buildonly-randconfig-003-20250320    clang-20
x86_64      buildonly-randconfig-003-20250321    clang-20
x86_64      buildonly-randconfig-004-20250320    clang-20
x86_64      buildonly-randconfig-004-20250321    clang-20
x86_64      buildonly-randconfig-005-20250320    clang-20
x86_64      buildonly-randconfig-005-20250321    clang-20
x86_64      buildonly-randconfig-006-20250320    gcc-12
x86_64      buildonly-randconfig-006-20250321    clang-20
x86_64                              defconfig    clang-20
x86_64                              defconfig    gcc-11
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20250321    clang-20
x86_64                randconfig-002-20250321    clang-20
x86_64                randconfig-003-20250321    clang-20
x86_64                randconfig-004-20250321    clang-20
x86_64                randconfig-005-20250321    clang-20
x86_64                randconfig-006-20250321    clang-20
x86_64                randconfig-007-20250321    clang-20
x86_64                randconfig-008-20250321    clang-20
x86_64                randconfig-071-20250321    gcc-12
x86_64                randconfig-072-20250321    gcc-12
x86_64                randconfig-073-20250321    gcc-12
x86_64                randconfig-074-20250321    gcc-12
x86_64                randconfig-075-20250321    gcc-12
x86_64                randconfig-076-20250321    gcc-12
x86_64                randconfig-077-20250321    gcc-12
x86_64                randconfig-078-20250321    gcc-12
x86_64                               rhel-9.4    clang-20
xtensa                            allnoconfig    gcc-14.2.0
xtensa                  audio_kc705_defconfig    gcc-14.2.0
xtensa                randconfig-001-20250320    gcc-9.3.0
xtensa                randconfig-001-20250321    gcc-6.5.0
xtensa                randconfig-002-20250320    gcc-11.5.0
xtensa                randconfig-002-20250321    gcc-6.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From broonie at kernel.org  Thu Mar 20 15:54:45 2025
From: broonie at kernel.org (Mark Brown)
Date: Thu, 20 Mar 2025 22:54:45 +0000
Subject: [PATCH] ASoC: SOF: mediatek: Commonize duplicated functions
In-Reply-To: <20250320115300.137410-1-angelogioacchino.delregno@collabora.com>
References: <20250320115300.137410-1-angelogioacchino.delregno@collabora.com>
Message-ID: <174251128562.367646.10336285275014385543.b4-ty@kernel.org>

On Thu, 20 Mar 2025 12:53:00 +0100, AngeloGioacchino Del Regno wrote:
> In order to reduce duplication, move the ADSP mailbox callbacks
> handle_reply(), handle_request(), and other common SOF callbacks
> send_msg(), get_bar_index(), pcm_hw_params() and pcm_pointer()
> to the mtk-adsp-common.c file.
> 
> This cleanup brings no functional differences.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: SOF: mediatek: Commonize duplicated functions
      commit: 24489150c5d9afea54c6909ba05c4dbdd8846dc0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From changyuanl at google.com  Thu Mar 20 16:29:56 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Thu, 20 Mar 2025 16:29:56 -0700
Subject: [PATCH v5 12/16] arm64: add KHO support
In-Reply-To: <55a5e3f3-1b3f-469b-bde0-69abfff826e4@kernel.org>
References: <55a5e3f3-1b3f-469b-bde0-69abfff826e4@kernel.org>
Message-ID: <20250320232956.327827-1-changyuanl@google.com>

Hi, Krzysztof

On Thu, Mar 20, 2025 at 08:13:24 +0100, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> On 20/03/2025 02:55, Changyuan Lyu wrote:
> >
> > +/**
> > + * early_init_dt_check_kho - Decode info required for kexec handover from DT
> > + */
> > +static void __init early_init_dt_check_kho(void)
> > +{
> > +	unsigned long node = chosen_node_offset;
> > +	u64 kho_start, scratch_start, scratch_size;
> > +	const __be32 *p;
> > +	int l;
> > +
> > +	if (!IS_ENABLED(CONFIG_KEXEC_HANDOVER) || (long)node < 0)
> > +		return;
> > +
> > +	p = of_get_flat_dt_prop(node, "linux,kho-fdt", &l);
>
>
> You are adding undocumented ABI for OF properties. That's not what was
> explained last time.

Thanks for the reminder! Sorry I missed [1].
I drafted a PR to add the documentation:
https://github.com/devicetree-org/dt-schema/pull/158 .

[1] https://lore.kernel.org/all/b1e59928-b2f4-47d4-87b8-424234c52f8d at kernel.org/

Best,
Changyuan


From namhyung at kernel.org  Thu Mar 20 16:59:17 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Thu, 20 Mar 2025 16:59:17 -0700
Subject: [PATCH v7 00/14] perf: Support multiple system call tables in
 the build
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <Z9yr1dnrX0DgDHgn@google.com>

On Tue, Mar 18, 2025 at 10:07:27PM -0700, Ian Rogers wrote:
> This work builds on the clean up of system call tables and removal of
> libaudit by Charlie Jenkins <charlie at rivosinc.com>.
> 
> The system call table in perf trace is used to map system call numbers
> to names and vice versa. Prior to these changes, a single table
> matching the perf binary's build was present. The table would be
> incorrect if tracing say a 32-bit binary from a 64-bit version of
> perf, the names and numbers wouldn't match.
> 
> Change the build so that a single system call file is built and the
> potentially multiple tables are identifiable from the ELF machine type
> of the process being examined. To determine the ELF machine type, the
> executable's maps are searched and the associated DSOs ELF headers are
> read. When this fails and when live, /proc/pid/exe's ELF header is
> read. Fallback to using the perf's binary type when unknown.
> 
> Remove some runtime types used by the system call tables and make
> equivalents generated at build time.
> 
> v7: Rebase for dso data locking changes. Don't NULL check before
>     btf__free (Arnaldo). Add patch to clean up perf trace's evlist to
>     make leak sanitizer happier.
> 
> v6: Incorporate Namhyung's fixes:
>     https://lore.kernel.org/lkml/Z9PCjQ8PhOadVGQ8 at google.com/
>     https://lore.kernel.org/lkml/Z9YHCzINiu4uBQ8B at google.com/
>     Which highlighted an issue with syscall pointers becoming
>     stale. Add a patch 12 to make the syscall table a table of
>     pointers that don't move so that struct syscalls don't move. Add a
>     patch 13 fixing a BTF memory leak.
> 
> v5: Add byte swap to dso__e_machine and fix comment as suggested by
>     Namhyung.
> 
> v4: Add reading the e_machine from the thread's maps dsos, only read
>     from /proc/pid/exe on failure and when live as requested by
>     Namhyung. Add patches to add dso comments and remove unused
>     dso_data variables that are unused without libunwind.
> 
> v3: Add Charlie's reviewed-by tags. Incorporate feedback from Arnd
>     Bergmann <arnd at arndb.de> on additional optional column and MIPS
>     system call numbering. Rebase past Namhyung's global system call
>     statistics and add comments that they don't yet support an
>     e_machine other than EM_HOST.
> 
> v2: Change the 1 element cache for the last table as suggested by
>     Howard Chu, add Howard's reviewed-by tags.
>     Add a comment and apology to Charlie for not doing better in
>     guiding:
>     https://lore.kernel.org/all/20250114-perf_syscall_arch_runtime-v1-1-5b304e408e11 at rivosinc.com/
>     After discussion on v1 and he agreed this patch series would be
>     the better direction.
> 
> Ian Rogers (14):
>   perf dso: Move libunwind dso_data variables into ifdef
>   perf dso: kernel-doc for enum dso_binary_type
>   perf syscalltbl: Remove syscall_table.h
>   perf trace: Reorganize syscalls
>   perf syscalltbl: Remove struct syscalltbl
>   perf dso: Add support for reading the e_machine type for a dso
>   perf thread: Add support for reading the e_machine type for a thread
>   perf trace beauty: Add syscalltbl.sh generating all system call tables
>   perf syscalltbl: Use lookup table containing multiple architectures
>   perf build: Remove Makefile.syscalls
>   perf syscalltbl: Mask off ABI type for MIPS system calls
>   perf trace: Make syscall table stable
>   perf trace: Fix BTF memory leak
>   perf trace: Fix evlist memory leak

Reviewed-by: Namhyung Kim <namhyung at kernel.org>

Thanks,
Namhyung

> 
>  tools/perf/Makefile.perf                      |  10 +-
>  tools/perf/arch/alpha/entry/syscalls/Kbuild   |   2 -
>  .../alpha/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/alpha/include/syscall_table.h |   2 -
>  tools/perf/arch/arc/entry/syscalls/Kbuild     |   2 -
>  .../arch/arc/entry/syscalls/Makefile.syscalls |   3 -
>  tools/perf/arch/arc/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm/entry/syscalls/Kbuild     |   4 -
>  .../arch/arm/entry/syscalls/Makefile.syscalls |   2 -
>  tools/perf/arch/arm/include/syscall_table.h   |   2 -
>  tools/perf/arch/arm64/entry/syscalls/Kbuild   |   3 -
>  .../arm64/entry/syscalls/Makefile.syscalls    |   6 -
>  tools/perf/arch/arm64/include/syscall_table.h |   8 -
>  tools/perf/arch/csky/entry/syscalls/Kbuild    |   2 -
>  .../csky/entry/syscalls/Makefile.syscalls     |   3 -
>  tools/perf/arch/csky/include/syscall_table.h  |   2 -
>  .../perf/arch/loongarch/entry/syscalls/Kbuild |   2 -
>  .../entry/syscalls/Makefile.syscalls          |   3 -
>  .../arch/loongarch/include/syscall_table.h    |   2 -
>  tools/perf/arch/mips/entry/syscalls/Kbuild    |   2 -
>  .../mips/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/mips/include/syscall_table.h  |   2 -
>  tools/perf/arch/parisc/entry/syscalls/Kbuild  |   3 -
>  .../parisc/entry/syscalls/Makefile.syscalls   |   6 -
>  .../perf/arch/parisc/include/syscall_table.h  |   8 -
>  tools/perf/arch/powerpc/entry/syscalls/Kbuild |   3 -
>  .../powerpc/entry/syscalls/Makefile.syscalls  |   6 -
>  .../perf/arch/powerpc/include/syscall_table.h |   8 -
>  tools/perf/arch/riscv/entry/syscalls/Kbuild   |   2 -
>  .../riscv/entry/syscalls/Makefile.syscalls    |   4 -
>  tools/perf/arch/riscv/include/syscall_table.h |   8 -
>  tools/perf/arch/s390/entry/syscalls/Kbuild    |   2 -
>  .../s390/entry/syscalls/Makefile.syscalls     |   5 -
>  tools/perf/arch/s390/include/syscall_table.h  |   2 -
>  tools/perf/arch/sh/entry/syscalls/Kbuild      |   2 -
>  .../arch/sh/entry/syscalls/Makefile.syscalls  |   4 -
>  tools/perf/arch/sh/include/syscall_table.h    |   2 -
>  tools/perf/arch/sparc/entry/syscalls/Kbuild   |   3 -
>  .../sparc/entry/syscalls/Makefile.syscalls    |   5 -
>  tools/perf/arch/sparc/include/syscall_table.h |   8 -
>  tools/perf/arch/x86/entry/syscalls/Kbuild     |   3 -
>  .../arch/x86/entry/syscalls/Makefile.syscalls |   6 -
>  tools/perf/arch/x86/include/syscall_table.h   |   8 -
>  tools/perf/arch/xtensa/entry/syscalls/Kbuild  |   2 -
>  .../xtensa/entry/syscalls/Makefile.syscalls   |   4 -
>  .../perf/arch/xtensa/include/syscall_table.h  |   2 -
>  tools/perf/builtin-trace.c                    | 339 ++++++++++++------
>  tools/perf/scripts/Makefile.syscalls          |  61 ----
>  tools/perf/scripts/syscalltbl.sh              |  86 -----
>  tools/perf/trace/beauty/syscalltbl.sh         | 274 ++++++++++++++
>  tools/perf/util/dso.c                         |  89 +++++
>  tools/perf/util/dso.h                         |  62 ++++
>  tools/perf/util/symbol-elf.c                  |  27 --
>  tools/perf/util/syscalltbl.c                  | 148 ++++----
>  tools/perf/util/syscalltbl.h                  |  22 +-
>  tools/perf/util/thread.c                      |  80 +++++
>  tools/perf/util/thread.h                      |  14 +-
>  57 files changed, 839 insertions(+), 543 deletions(-)
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/alpha/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/alpha/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/arm64/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/arm64/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/csky/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/csky/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/loongarch/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/loongarch/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/mips/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/mips/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/parisc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/parisc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/powerpc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/riscv/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/riscv/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/s390/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/s390/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sh/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sh/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/sparc/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/sparc/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/x86/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/x86/include/syscall_table.h
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Kbuild
>  delete mode 100644 tools/perf/arch/xtensa/entry/syscalls/Makefile.syscalls
>  delete mode 100644 tools/perf/arch/xtensa/include/syscall_table.h
>  delete mode 100644 tools/perf/scripts/Makefile.syscalls
>  delete mode 100755 tools/perf/scripts/syscalltbl.sh
>  create mode 100755 tools/perf/trace/beauty/syscalltbl.sh
> 
> -- 
> 2.49.0.rc1.451.g8f38331e32-goog
> 


From broonie at kernel.org  Thu Mar 20 17:16:02 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:02 +0000
Subject: [PATCH 6.6 2/8] KVM: arm64: Unconditionally save+flush host
 FPSIMD/SVE/SME state
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-2-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 25 -------------------------
 arch/arm64/kvm/fpsimd.c    | 31 ++++++++-----------------------
 2 files changed, 8 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 0137d987631e089c935560eccbc678a258580232..bd4f6c6ee0f318e1f60d40755c0f4915edb415b8 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1707,31 +1707,6 @@ void fpsimd_signal_preserve_current_state(void)
 		sve_to_fpsimd(current);
 }
 
-/*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
 /*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 8c1d0d4853df48abf4d089bbde153bcee8d0e6d0..8b55de502c8c220e15e3a6b782d5012b9349b612 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -79,14 +79,16 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	vcpu->arch.fp_state = FP_STATE_HOST_OWNED;
+	fpsimd_save_and_flush_cpu_state();
+	vcpu->arch.fp_state = FP_STATE_FREE;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -96,23 +98,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			vcpu->arch.fp_state = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 }
 

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:03 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:03 +0000
Subject: [PATCH 6.6 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-3-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       | 1 -
 arch/arm64/kvm/fpsimd.c                 | 2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ----
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 1 -
 4 files changed, 8 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 6a165ec5d3b74ece3e98e7bf45f3ea94cc30e6ec..3891963d42e00c8f999886dc5d7322bbacbc6c7f 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -535,7 +535,6 @@ struct kvm_vcpu_arch {
 	struct kvm_guest_debug_arch vcpu_debug_state;
 	struct kvm_guest_debug_arch external_debug_state;
 
-	struct user_fpsimd_state *host_fpsimd_state;	/* hyp VA */
 	struct task_struct *parent_task;
 
 	struct {
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 8b55de502c8c220e15e3a6b782d5012b9349b612..7c36d2a7aa3196056f76acfe8f9c41763ed67d9d 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -49,8 +49,6 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
-	vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
-
 	/*
 	 * We need to keep current's task_struct pinned until its data has been
 	 * unshared with the hypervisor to make sure it is not re-used by the
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 9cfe6bd1dbe459cb3588bccd94359369a546947e..1cdc8d161e7dd3aeeb6b03170e239b0c1ace7790 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -321,10 +321,6 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 	}
 	isb();
 
-	/* Write out the host state if it's in the registers */
-	if (vcpu->arch.fp_state == FP_STATE_HOST_OWNED)
-		__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
-
 	/* Restore the guest state */
 	if (sve_guest)
 		__hyp_sve_restore_guest(vcpu);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 67cc07283e642ab07e1c98c5745e2c6a2dd4f36e..8390173f7f5b38e01c04ae6563853df11a1c3df2 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -41,7 +41,6 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
 	hyp_vcpu->vcpu.arch.fp_state	= host_vcpu->arch.fp_state;
 
 	hyp_vcpu->vcpu.arch.debug_ptr	= kern_hyp_va(host_vcpu->arch.debug_ptr);
-	hyp_vcpu->vcpu.arch.host_fpsimd_state = host_vcpu->arch.host_fpsimd_state;
 
 	hyp_vcpu->vcpu.arch.vsesr_el2	= host_vcpu->arch.vsesr_el2;
 

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:04 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:04 +0000
Subject: [PATCH 6.6 4/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.ZEN
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-4-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 16 ----------------
 2 files changed, 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3891963d42e00c8f999886dc5d7322bbacbc6c7f..9c1056d6f6859522dcee4b8c4e4804a7abac93d5 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -717,8 +717,6 @@ struct kvm_vcpu_arch {
 /* vcpu running in HYP context */
 #define VCPU_HYP_CONTEXT	__vcpu_single_flag(iflags, BIT(7))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 7c36d2a7aa3196056f76acfe8f9c41763ed67d9d..f1fe7abbcb83393e7c3402405bb7b1fdbf6024ff 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -88,10 +88,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	vcpu->arch.fp_state = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -189,18 +185,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 		}
 
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:05 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:05 +0000
Subject: [PATCH 6.6 5/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.SMEN
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-5-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 23 -----------------------
 2 files changed, 25 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9c1056d6f6859522dcee4b8c4e4804a7abac93d5..27c53b603d693d1cfe8d81f94a59d3afb665be8e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -717,8 +717,6 @@ struct kvm_vcpu_arch {
 /* vcpu running in HYP context */
 #define VCPU_HYP_CONTEXT	__vcpu_single_flag(iflags, BIT(7))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index f1fe7abbcb83393e7c3402405bb7b1fdbf6024ff..0492a1fc718130934f8bada836fe42bea6db7abb 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -87,12 +87,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	vcpu->arch.fp_state = FP_STATE_FREE;
-
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
 }
 
 /*
@@ -157,23 +151,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0,
-					 CPACR_EL1_SMEN_EL0EN |
-					 CPACR_EL1_SMEN_EL1EN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) {
 		if (vcpu_has_sve(vcpu)) {
 			__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:06 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:06 +0000
Subject: [PATCH 6.6 6/8] KVM: arm64: Refactor exit handlers
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-6-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 27 +++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  9 ++++-----
 3 files changed, 25 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 1cdc8d161e7dd3aeeb6b03170e239b0c1ace7790..db9570affe09d36f2fe4641789a24111303be5a2 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -592,23 +592,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -638,20 +631,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -681,7 +663,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 1026be1964d9664b8b6de19e048aba91ee6463b0..aa827e2a2b1e5b2c67304221706f406b42ceafb2 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -225,21 +225,22 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
 	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (kvm_vm_is_protected(kvm) && vcpu_mode_is_32bit(vcpu)) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -252,6 +253,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 448b17080d3617cbf5d2fceec7e7fa62866760d4..d0c7725879a7b38cea53f1dfb111933e0ad89845 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -172,13 +172,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_PAC]		= kvm_hyp_handle_ptrauth,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -198,6 +195,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:07 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:07 +0000
Subject: [PATCH 6.6 7/8] KVM: arm64: Mark some header functions as inline
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-7-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index db9570affe09d36f2fe4641789a24111303be5a2..77a9f68ca4904a2b39ca59b7ee7cf54b9fe11f66 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -279,7 +279,7 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -518,7 +518,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -541,7 +541,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -550,19 +550,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:08 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:08 +0000
Subject: [PATCH 6.6 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-8-0b3a6a14ea53@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ v6.6 lacks pKVM saving of host SVE state, pull in discovery of maximum
  host VL separately -- broonie ]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       |  1 +
 arch/arm64/include/asm/kvm_hyp.h        |  1 +
 arch/arm64/kvm/fpsimd.c                 | 19 ++++++------
 arch/arm64/kvm/hyp/entry.S              |  5 +++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 55 +++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      | 12 ++-----
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  2 ++
 arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
 arch/arm64/kvm/reset.c                  |  3 ++
 10 files changed, 113 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27c53b603d693d1cfe8d81f94a59d3afb665be8e..df73e452d2cc0e5fd815d398a932763a5aa7607a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -73,6 +73,7 @@ static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; };
 #endif
 
 extern unsigned int __ro_after_init kvm_sve_max_vl;
+extern unsigned int __ro_after_init kvm_host_sve_max_vl;
 int __init kvm_arm_init_sve(void);
 
 u32 __attribute_const__ kvm_target_cpu(void);
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 66efd67ea7e8d6dd98dc6088a6004fdb646df2a3..51cd106cd840a006264d9a316f2dc6332e8327ad 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -145,5 +145,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val);
 
 extern unsigned long kvm_nvhe_sym(__icache_flags);
 extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
+extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
 
 #endif /* __ARM64_KVM_HYP_H__ */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 0492a1fc718130934f8bada836fe42bea6db7abb..e57db49ea468e41e411fd896321c3b1b87a098ec 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -152,15 +152,16 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) {
-		if (vcpu_has_sve(vcpu)) {
-			__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);
-
-			/* Restore the VL that was saved when bound to the CPU */
-			if (!has_vhe())
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
+		/*
+		 * Flush (save and invalidate) the fpsimd/sve state so that if
+		 * the host tries to use fpsimd/sve, it's not using stale data
+		 * from the guest.
+		 *
+		 * Flushing the state sets the TIF_FOREIGN_FPSTATE bit for the
+		 * context unconditionally, in both nVHE and VHE. This allows
+		 * the kernel to restore the fpsimd/sve state, including ZCR_EL1
+		 * when needed.
+		 */
 		fpsimd_save_and_flush_cpu_state();
 	}
 
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index f3aa7738b477d6a83e41db42cc161fc6f9aa6291..f02d5701fc21c685122aa5ba92309f7f4def3ae3 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 77a9f68ca4904a2b39ca59b7ee7cf54b9fe11f66..526085401f66387137a0d78d1d520af8b2306e43 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -273,6 +273,61 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
 	write_sysreg_el1(__vcpu_sys_reg(vcpu, ZCR_EL1), SYS_ZCR);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs(vcpu))
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, ZCR_EL1);
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs(vcpu))
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, ZCR_EL1) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 /*
  * We trap the first access to the FP/SIMD to save the host context and
  * restore the guest context lazily.
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 8390173f7f5b38e01c04ae6563853df11a1c3df2..350d1775a5ce880ac23bb7adddbed644e45d0e40 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -95,7 +96,9 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -416,15 +419,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		if (has_hvhe())
-			sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN |
-							CPACR_EL1_ZEN_EL0EN));
-		else
-			sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0);
-		isb();
-		sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 9e7612343ad66d3dc13b8ee858a4e61e917901c9..03acc8343c5d1b23ce0ea1fa2fcabaf2a93902c5 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -18,6 +18,8 @@ unsigned long __icache_flags;
 /* Used by kvm_get_vttbr(). */
 unsigned int kvm_arm_vmid_bits;
 
+unsigned int kvm_host_sve_max_vl;
+
 /*
  * Set trap register values based on features in ID_AA64PFR0.
  */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index aa827e2a2b1e5b2c67304221706f406b42ceafb2..27ad6933bec003d722d3d66519b6225cd207cad7 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs(vcpu))
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 
 		if (!guest_owns_fp_regs(vcpu))
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs(vcpu))
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index d0c7725879a7b38cea53f1dfb111933e0ad89845..31304da0d617313244caff582853965a7a206f72 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -212,6 +212,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * ARM erratum 1165522 requires us to configure both stage 1 and
 	 * stage 2 translation for the guest context before we clear
@@ -247,6 +249,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED)
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 7a65a35ee4ac4165b4147c724d28b59f8150a0d2..43a53a403f5102c81bba0d928c0f78331f800269 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -46,11 +46,14 @@ static u32 __ro_after_init kvm_ipa_limit;
 				 PSR_AA32_I_BIT | PSR_AA32_F_BIT)
 
 unsigned int __ro_after_init kvm_sve_max_vl;
+unsigned int __ro_after_init kvm_host_sve_max_vl;
 
 int __init kvm_arm_init_sve(void)
 {
 	if (system_supports_sve()) {
 		kvm_sve_max_vl = sve_max_virtualisable_vl();
+		kvm_host_sve_max_vl = sve_max_vl();
+		kvm_nvhe_sym(kvm_host_sve_max_vl) = kvm_host_sve_max_vl;
 
 		/*
 		 * The get_sve_reg()/set_sve_reg() ioctl interface will need

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:21:22 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:21:22 +0000
Subject: [PATCH 6.12 v2 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250321-stable-sve-6-12-v2-3-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
 <20250321-stable-sve-6-12-v2-3-417ca2278d18@kernel.org>
Message-ID: <e01d14ee-4071-4871-8b6c-acc24c9b862f@sirena.org.uk>

On Fri, Mar 21, 2025 at 12:12:59AM +0000, Mark Brown wrote:
> From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

> 
> Now that the host eagerly saves its own FPSIMD/SVE/SME state,
> non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
> and the code to do this is never used. Protected KVM still needs to
> save/restore the host FPSIMD/SVE state to avoid leaking guest state to
> the host (and to avoid revealing to the host whether the guest used
> FPSIMD/SVE/SME), and that code needs to be retained.
> 
> Remove the unused code and data structures.
> 
> To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
> VHE hyp code, the nVHE/hVHE version is moved into the shared switch
> header, where it is only invoked when KVM is in protected mode.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Reviewed-by: Mark Brown <broonie at kernel.org>
> Tested-by: Mark Brown <broonie at kernel.org>
> Acked-by: Will Deacon <will at kernel.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Fuad Tabba <tabba at google.com>
> Cc: Marc Zyngier <maz at kernel.org>
> Cc: Oliver Upton <oliver.upton at linux.dev>
> Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
> Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
>  arch/arm64/include/asm/kvm_host.h       | 20 +++++---------------
>  arch/arm64/kvm/arm.c                    |  8 --------
>  arch/arm64/kvm/fpsimd.c                 |  2 --
>  arch/arm64/kvm/hyp/include/hyp/switch.h | 25 +++++++++++++++++++++++--
>  arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  2 +-
>  arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ----------------------------
>  arch/arm64/kvm/hyp/vhe/switch.c         |  8 --------
>  7 files changed, 29 insertions(+), 64 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index d148cf578cb84e7dec4d1add2afa60a3c7a1e041..d8802490b25cba65369f03d94627a2624f14b072 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -602,23 +602,13 @@ struct kvm_host_data {
>  	struct kvm_cpu_context host_ctxt;
>  
>  	/*
> -	 * All pointers in this union are hyp VA.
> +	 * Hyp VA.
>  	 * sve_state is only used in pKVM and if system_supports_sve().
>  	 */
> -	union {
> -		struct user_fpsimd_state *fpsimd_state;
> -		struct cpu_sve_state *sve_state;
> -	};
> -
> -	union {
> -		/* HYP VA pointer to the host storage for FPMR */
> -		u64	*fpmr_ptr;
> -		/*
> -		 * Used by pKVM only, as it needs to provide storage
> -		 * for the host
> -		 */
> -		u64	fpmr;
> -	};
> +	struct cpu_sve_state *sve_state;
> +
> +	/* Used by pKVM only. */
> +	u64	fpmr;
>  
>  	/* Ownership of the FP regs */
>  	enum {
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index e6f0443210a8b7a65f616b25b2e6f74a05683ed6..634d3f62481827a3bf3aba6bf78cafed71b5bd32 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -2476,14 +2476,6 @@ static void finalize_init_hyp_mode(void)
>  			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
>  				kern_hyp_va(sve_state);
>  		}
> -	} else {
> -		for_each_possible_cpu(cpu) {
> -			struct user_fpsimd_state *fpsimd_state;
> -
> -			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
> -			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
> -				kern_hyp_va(fpsimd_state);
> -		}
>  	}
>  }
>  
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5..2ee6bde85235581d6bc9cba7e578c55875b5d5a1 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
>  	 */
>  	fpsimd_save_and_flush_cpu_state();
>  	*host_data_ptr(fp_owner) = FP_STATE_FREE;
> -	*host_data_ptr(fpsimd_state) = NULL;
> -	*host_data_ptr(fpmr_ptr) = NULL;
>  
>  	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
>  	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
> diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
> index 5310fe1da6165bcdedfb5ce61bce353e4c9dd58b..a7f6a653f33718d1a25e232608e63ea287f2a672 100644
> --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
> +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
> @@ -344,7 +344,28 @@ static inline void __hyp_sve_save_host(void)
>  			 true);
>  }
>  
> -static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
> +static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
> +{
> +	/*
> +	 * Non-protected kvm relies on the host restoring its sve state.
> +	 * Protected kvm restores the host's sve state as not to reveal that
> +	 * fpsimd was used by a guest nor leak upper sve bits.
> +	 */
> +	if (system_supports_sve()) {
> +		__hyp_sve_save_host();
> +
> +		/* Re-enable SVE traps if not supported for the guest vcpu. */
> +		if (!vcpu_has_sve(vcpu))
> +			cpacr_clear_set(CPACR_ELx_ZEN, 0);
> +
> +	} else {
> +		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
> +	}
> +
> +	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
> +		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
> +}
> +
>  
>  /*
>   * We trap the first access to the FP/SIMD to save the host context and
> @@ -394,7 +415,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
>  	isb();
>  
>  	/* Write out the host state if it's in the registers */
> -	if (host_owns_fp_regs())
> +	if (is_protected_kvm_enabled() && host_owns_fp_regs())
>  		kvm_hyp_save_fpsimd_host(vcpu);
>  
>  	/* Restore the guest state */
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index fefc89209f9e41c95478f6770881eb314a38b4c2..4e757a77322c9efc59cdff501745f7c80d452358 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
>  	if (system_supports_sve())
>  		__hyp_sve_restore_host();
>  	else
> -		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
> +		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
>  
>  	if (has_fpmr)
>  		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
> diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
> index 81d933a71310fd1132b2450cd08108e071a2cf78..3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7 100644
> --- a/arch/arm64/kvm/hyp/nvhe/switch.c
> +++ b/arch/arm64/kvm/hyp/nvhe/switch.c
> @@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
>  		kvm_handle_pvm_sysreg(vcpu, exit_code));
>  }
>  
> -static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
> -{
> -	/*
> -	 * Non-protected kvm relies on the host restoring its sve state.
> -	 * Protected kvm restores the host's sve state as not to reveal that
> -	 * fpsimd was used by a guest nor leak upper sve bits.
> -	 */
> -	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
> -		__hyp_sve_save_host();
> -
> -		/* Re-enable SVE traps if not supported for the guest vcpu. */
> -		if (!vcpu_has_sve(vcpu))
> -			cpacr_clear_set(CPACR_ELx_ZEN, 0);
> -
> -	} else {
> -		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
> -	}
> -
> -	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
> -		u64 val = read_sysreg_s(SYS_FPMR);
> -
> -		if (unlikely(is_protected_kvm_enabled()))
> -			*host_data_ptr(fpmr) = val;
> -		else
> -			**host_data_ptr(fpmr_ptr) = val;
> -	}
> -}
> -
>  static const exit_handler_fn hyp_exit_handlers[] = {
>  	[0 ... ESR_ELx_EC_MAX]		= NULL,
>  	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
> diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
> index 80581b1c399595fd64d0ccada498edac322480a6..e7ca0424107adec2371ae4553ebab9857c60b6d9 100644
> --- a/arch/arm64/kvm/hyp/vhe/switch.c
> +++ b/arch/arm64/kvm/hyp/vhe/switch.c
> @@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
>  	return true;
>  }
>  
> -static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
> -{
> -	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
> -
> -	if (kvm_has_fpmr(vcpu->kvm))
> -		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
> -}
> -
>  static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
>  {
>  	int ret = -EINVAL;
> 
> -- 
> 2.39.5
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/18128799/attachment.sig>

From andi.shyti at kernel.org  Thu Mar 20 17:34:02 2025
From: andi.shyti at kernel.org (Andi Shyti)
Date: Fri, 21 Mar 2025 01:34:02 +0100
Subject: [PATCH v5 1/1] i2c: mediatek: add runtime PM operations and bus
 regulator control
In-Reply-To: <Z9yR6pyg1mtqKynh@makrotopia.org>
References: <20250314145407.2900190-1-zoie.lin@mediatek.com>
 <fqicrglyug7gmkmysok7hilhmkyhxmnkztzv4iffgry6xce6t3@2i6b2ihfu4rb>
 <Z9yR6pyg1mtqKynh@makrotopia.org>
Message-ID: <em2y3tkiwlxc45f4sjtzdd3oy4v5zpqgdpqfppyzah2ilzidg2@wn6cnrezygpl>

Hi Daniel,

On Thu, Mar 20, 2025 at 10:08:42PM +0000, Daniel Golle wrote:
> On Wed, Mar 19, 2025 at 12:34:53AM +0100, Andi Shyti wrote:
> > On Fri, Mar 14, 2025 at 10:53:43PM +0800, Zoie Lin wrote:
> > > Introduce support for runtime PM operations in
> > > the I2C driver, enabling runtime suspend and resume functionality.
> > > 
> > > Although in most platforms, the bus power of i2c is always
> > > on, some platforms disable the i2c bus power in order to meet
> > > low power request.
> > > 
> > > This implementation includes bus regulator control to facilitate
> > > proper handling of the bus power based on platform requirements.
> > > 
> > > Signed-off-by: Zoie Lin <zoie.lin at mediatek.com>
> > 
> > merged to i2c/i2c-host.
> 
> the change causes a crash during boot on MT7988 which typically uses
> one of its I2C busses to connect a Richtek RT5190A PMIC.

Thanks a lot for testing it. I removed the commit.

Andi


From broonie at kernel.org  Thu Mar 20 17:10:10 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:10 +0000
Subject: [PATCH 6.13 v2 1/8] KVM: arm64: Calculate cptr_el2 traps on
 activating traps
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-1-3150e3370c40@kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  1 -
 arch/arm64/kvm/arm.c              |  1 -
 arch/arm64/kvm/hyp/nvhe/pkvm.c    | 30 -----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  | 51 ++++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 51 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index c85aa4f1def810a08e7bfa4ab181760839521c25..6762dadce45deb657b6e8df3e14dc9fbef884f1d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -708,7 +708,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3b3ecfed294f2be5bf545f4e89ba6e53415625f5..591f512ab072963424f4b2287a1a572fc72bd639 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1569,7 +1569,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 071993c16de81ca0b0181c56d0598b1b026ae018..6405fa30f961723c0da0761be079e09f91b7e8e1 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -31,8 +31,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -62,21 +60,10 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -106,7 +93,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -133,21 +119,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -198,10 +175,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
@@ -236,7 +209,6 @@ static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
  */
 static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 	vcpu->arch.mdcr_el2 = 0;
 
 	pkvm_vcpu_reset_hcr(vcpu);
@@ -693,8 +665,6 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index cc69106734ca732ba9276ac1eaf84be3e7381648..81d933a71310fd1132b2450cd08108e071a2cf78 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
+
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:09 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:09 +0000
Subject: [PATCH 6.13 v2 0/8] KVM: arm64: Backport of SVE fixes to v6.13
Message-ID: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>

This series backports some recent fixes for SVE/KVM interactions from
Mark Rutland to v6.13.

Signed-off-by: Mark Brown <broonie at kernel.org>
---
Changes in v2:
- Remove an erronious kern_hyp_va().
- Move standard cherry pick to stable format in patch 8.
- Link to v1: https://lore.kernel.org/r/20250312-stable-sve-6-13-v1-0-c7ba07a6f4f7 at kernel.org

---
Fuad Tabba (1):
      KVM: arm64: Calculate cptr_el2 traps on activating traps

Mark Rutland (7):
      KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
      KVM: arm64: Remove host FPSIMD saving for non-protected KVM
      KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
      KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
      KVM: arm64: Refactor exit handlers
      KVM: arm64: Mark some header functions as inline
      KVM: arm64: Eagerly switch ZCR_EL{1,2}

 arch/arm64/include/asm/kvm_host.h       |  25 ++----
 arch/arm64/kernel/fpsimd.c              |  25 ------
 arch/arm64/kvm/arm.c                    |   9 ---
 arch/arm64/kvm/fpsimd.c                 | 100 ++----------------------
 arch/arm64/kvm/hyp/entry.S              |   5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 133 ++++++++++++++++++++++---------
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  11 +--
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  30 -------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 134 ++++++++++++++++++--------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  21 ++---
 10 files changed, 201 insertions(+), 292 deletions(-)
---
base-commit: 648e04a805652f513af04b47035cde896addf9b0
change-id: 20250227-stable-sve-6-13-5ceaf408b5f7

Best regards,
-- 
Mark Brown <broonie at kernel.org>



From broonie at kernel.org  Thu Mar 20 17:10:11 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:11 +0000
Subject: [PATCH 6.13 v2 2/8] KVM: arm64: Unconditionally save+flush host
 FPSIMD/SVE/SME state
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-2-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 25 -------------------------
 arch/arm64/kvm/fpsimd.c    | 35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 8c4c1a2186cc510a7826d15ec36225857c07ed71..ec68d520b7ca70e7395bab4bc78fc9a7405d6b92 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void)
 		sve_to_fpsimd(current);
 }
 
-/*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
 /*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index ea5484ce1f3ba3121b6938bda15f7a8057d49051..efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:13 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:13 +0000
Subject: [PATCH 6.13 v2 4/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.ZEN
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-4-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 16 ----------------
 2 files changed, 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0b39888e86d6d40fea56bb6cb8ccdbaf480d0d55..fe25d411d3d8efbe19d5ffba8ea23bf98eb06c38 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 2ee6bde85235581d6bc9cba7e578c55875b5d5a1..4127abfd319c2c683d2281efa52a6abe5fac67ee 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:14 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:14 +0000
Subject: [PATCH 6.13 v2 5/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.SMEN
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-5-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 21 ---------------------
 2 files changed, 23 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fe25d411d3d8efbe19d5ffba8ea23bf98eb06c38..06e3cfc9a73b8c95712580b13b926b6471a16be7 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 4127abfd319c2c683d2281efa52a6abe5fac67ee..f64724197958e0d8a4ec17deb1f9826ce3625eb7 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:15 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:15 +0000
Subject: [PATCH 6.13 v2 6/8] KVM: arm64: Refactor exit handlers
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-6-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 7601d741bc2ae77ca9f359e4901926a5feac48b9..e330a7825b56f14ccb144810bc0d31f7f400fb22 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -666,23 +666,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -712,20 +705,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -755,7 +737,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7..ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index e7ca0424107adec2371ae4553ebab9857c60b6d9..46c1f5caf007331cdbbc806a184e9b4721042fc0 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:16 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:16 +0000
Subject: [PATCH 6.13 v2 7/8] KVM: arm64: Mark some header functions as
 inline
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-7-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index e330a7825b56f14ccb144810bc0d31f7f400fb22..300ec597cf1257954019f50cce44d662d6420790 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -326,7 +326,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -404,7 +404,7 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -595,7 +595,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -615,7 +615,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -624,19 +624,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:17 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:17 +0000
Subject: [PATCH 6.13 v2 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-8-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/fpsimd.c                 | 30 -----------------
 arch/arm64/kvm/hyp/entry.S              |  5 +++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  9 ++---
 arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
 6 files changed, 100 insertions(+), 40 deletions(-)

diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index f64724197958e0d8a4ec17deb1f9826ce3625eb7..3cbb999419af7bb31ce9cec2baafcad00491610a 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 4433a234aa9ba242f43b943d22011b5ddacd8af7..9f4e8d68ab505cf4a7aa8673643d9b47ca1bc7cb 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 300ec597cf1257954019f50cce44d662d6420790..bcf3a537aac36c705b60a2b99df6061ae110a934 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,6 +375,65 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 7262983c75fbc18ab44f52753bff1dd9167a68d3..d78a89c9a4ae1e46e946f35f7bf1c3396a99ecc3 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -179,7 +180,9 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -480,12 +483,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494..a1245fa838319544f3770a05a58eeed5233f0324 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 46c1f5caf007331cdbbc806a184e9b4721042fc0..496abfd3646b9858e95e06a79edec11eee3a5893 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:10:12 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:10:12 +0000
Subject: [PATCH 6.13 v2 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
References: <20250321-stable-sve-6-13-v2-0-3150e3370c40@kernel.org>
Message-ID: <20250321-stable-sve-6-13-v2-3-3150e3370c40@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[CPACR_EL1_ZEN -> CPACR_ELx_ZEN -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       | 20 +++++---------------
 arch/arm64/kvm/arm.c                    |  8 --------
 arch/arm64/kvm/fpsimd.c                 |  2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h | 25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  8 --------
 7 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 6762dadce45deb657b6e8df3e14dc9fbef884f1d..0b39888e86d6d40fea56bb6cb8ccdbaf480d0d55 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -613,23 +613,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
-
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	struct cpu_sve_state *sve_state;
+
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 591f512ab072963424f4b2287a1a572fc72bd639..78acbd589968771674f6cecaea6d9254eaeb6b8a 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2468,14 +2468,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5..2ee6bde85235581d6bc9cba7e578c55875b5d5a1 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 34f53707892dfe7bba41620e7adb65f1f8376018..7601d741bc2ae77ca9f359e4901926a5feac48b9 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,7 +375,28 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -425,7 +446,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 6aa0b13d86e581a36ed529bcd932498045d2d6df..7262983c75fbc18ab44f52753bff1dd9167a68d3 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 81d933a71310fd1132b2450cd08108e071a2cf78..3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 80581b1c399595fd64d0ccada498edac322480a6..e7ca0424107adec2371ae4553ebab9857c60b6d9 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:12:56 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:12:56 +0000
Subject: [PATCH 6.12 v2 0/8] KVM: arm64: Backport of SVE fixes to v6.12
Message-ID: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>

This series backports some recent fixes for SVE/KVM interactions from
Mark Rutland to v6.12.

Signed-off-by: Mark Brown <broonie at kernel.org>
---
Changes in v2:
- Remove an erronious kern_hyp_va().
- Link to v1: https://lore.kernel.org/r/20250314-stable-sve-6-12-v1-0-ddc16609d9ba at kernel.org

---
Fuad Tabba (1):
      KVM: arm64: Calculate cptr_el2 traps on activating traps

Mark Rutland (7):
      KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
      KVM: arm64: Remove host FPSIMD saving for non-protected KVM
      KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
      KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
      KVM: arm64: Refactor exit handlers
      KVM: arm64: Mark some header functions as inline
      KVM: arm64: Eagerly switch ZCR_EL{1,2}

 arch/arm64/include/asm/kvm_host.h       |  25 ++----
 arch/arm64/kernel/fpsimd.c              |  25 ------
 arch/arm64/kvm/arm.c                    |   9 ---
 arch/arm64/kvm/fpsimd.c                 | 100 ++----------------------
 arch/arm64/kvm/hyp/entry.S              |   5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 133 ++++++++++++++++++++++---------
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  11 +--
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  29 -------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 134 ++++++++++++++++++--------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  21 ++---
 10 files changed, 201 insertions(+), 291 deletions(-)
---
base-commit: e9cc806c0152fa9993f817cebf42989a3e2530bb
change-id: 20250227-stable-sve-6-12-777778ad28fb

Best regards,
-- 
Mark Brown <broonie at kernel.org>



From broonie at kernel.org  Thu Mar 20 17:12:57 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:12:57 +0000
Subject: [PATCH 6.12 v2 1/8] KVM: arm64: Calculate cptr_el2 traps on
 activating traps
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-1-417ca2278d18@kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  1 -
 arch/arm64/kvm/arm.c              |  1 -
 arch/arm64/kvm/hyp/nvhe/pkvm.c    | 29 ----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  | 51 ++++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1bf70fa1045dcd6704bdcd233767cdb7522b316f..d148cf578cb84e7dec4d1add2afa60a3c7a1e041 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -697,7 +697,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3cf65daa75a51f71fa7168016f8c3d81dc326cca..e6f0443210a8b7a65f616b25b2e6f74a05683ed6 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1577,7 +1577,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 077d4098548d2c87abdd3931285d87798d63adb3..7c464340bcd078df58b74164707f263a6bdb0272 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -28,8 +28,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -59,21 +57,10 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -103,7 +90,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -130,21 +116,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -195,10 +172,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 /*
@@ -579,8 +552,6 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index cc69106734ca732ba9276ac1eaf84be3e7381648..81d933a71310fd1132b2450cd08108e071a2cf78 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
+
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:12:59 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:12:59 +0000
Subject: [PATCH 6.12 v2 3/8] KVM: arm64: Remove host FPSIMD saving for
 non-protected KVM
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-3-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h       | 20 +++++---------------
 arch/arm64/kvm/arm.c                    |  8 --------
 arch/arm64/kvm/fpsimd.c                 |  2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h | 25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  8 --------
 7 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d148cf578cb84e7dec4d1add2afa60a3c7a1e041..d8802490b25cba65369f03d94627a2624f14b072 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -602,23 +602,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
-
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	struct cpu_sve_state *sve_state;
+
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index e6f0443210a8b7a65f616b25b2e6f74a05683ed6..634d3f62481827a3bf3aba6bf78cafed71b5bd32 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2476,14 +2476,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5..2ee6bde85235581d6bc9cba7e578c55875b5d5a1 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 5310fe1da6165bcdedfb5ce61bce353e4c9dd58b..a7f6a653f33718d1a25e232608e63ea287f2a672 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,7 +344,28 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -394,7 +415,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index fefc89209f9e41c95478f6770881eb314a38b4c2..4e757a77322c9efc59cdff501745f7c80d452358 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 81d933a71310fd1132b2450cd08108e071a2cf78..3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 80581b1c399595fd64d0ccada498edac322480a6..e7ca0424107adec2371ae4553ebab9857c60b6d9 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:12:58 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:12:58 +0000
Subject: [PATCH 6.12 v2 2/8] KVM: arm64: Unconditionally save+flush host
 FPSIMD/SVE/SME state
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-2-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 25 -------------------------
 arch/arm64/kvm/fpsimd.c    | 35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 6d21971ae5594f32947480cfa168db400a69a283..f38d22dac140f1b2a8de3f2f2ba1e5da22d2d1c8 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void)
 		sve_to_fpsimd(current);
 }
 
-/*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
 /*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index ea5484ce1f3ba3121b6938bda15f7a8057d49051..efb54ed60fe1d1d8a904b10a4a4bd3c820d9dac5 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:13:00 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:13:00 +0000
Subject: [PATCH 6.12 v2 4/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.ZEN
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-4-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 16 ----------------
 2 files changed, 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d8802490b25cba65369f03d94627a2624f14b072..1a126fa657fcde3433f37f3aaf464a5b6a5f095d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 2ee6bde85235581d6bc9cba7e578c55875b5d5a1..4127abfd319c2c683d2281efa52a6abe5fac67ee 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:13:01 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:13:01 +0000
Subject: [PATCH 6.12 v2 5/8] KVM: arm64: Remove VHE host restore of
 CPACR_EL1.SMEN
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-5-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h |  2 --
 arch/arm64/kvm/fpsimd.c           | 21 ---------------------
 2 files changed, 23 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1a126fa657fcde3433f37f3aaf464a5b6a5f095d..122a1e12582c0584bce86c5416ef7d150f90fe95 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 4127abfd319c2c683d2281efa52a6abe5fac67ee..f64724197958e0d8a4ec17deb1f9826ce3625eb7 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:13:02 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:13:02 +0000
Subject: [PATCH 6.12 v2 6/8] KVM: arm64: Refactor exit handlers
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-6-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |  9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index a7f6a653f33718d1a25e232608e63ea287f2a672..e14aba19847f2c66c202a869b5173f25a9a7f66e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -635,23 +635,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -681,20 +674,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -724,7 +706,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 3ce16f90fe6af7be21bc7b84a9d8b3905b8b08a7..ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index e7ca0424107adec2371ae4553ebab9857c60b6d9..46c1f5caf007331cdbbc806a184e9b4721042fc0 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:13:03 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:13:03 +0000
Subject: [PATCH 6.12 v2 7/8] KVM: arm64: Mark some header functions as
 inline
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-7-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index e14aba19847f2c66c202a869b5173f25a9a7f66e..c1ab31429a0e5fab97cd06c3b7b6e378170bd99d 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -295,7 +295,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -373,7 +373,7 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -564,7 +564,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -584,7 +584,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -593,19 +593,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:13:04 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:13:04 +0000
Subject: [PATCH 6.12 v2 8/8] KVM: arm64: Eagerly switch ZCR_EL{1,2}
In-Reply-To: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
References: <20250321-stable-sve-6-12-v2-0-417ca2278d18@kernel.org>
Message-ID: <20250321-stable-sve-6-12-v2-8-417ca2278d18@kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/kvm/fpsimd.c                 | 30 -----------------
 arch/arm64/kvm/hyp/entry.S              |  5 +++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 59 +++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  9 ++---
 arch/arm64/kvm/hyp/nvhe/switch.c        | 33 +++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |  4 +++
 6 files changed, 100 insertions(+), 40 deletions(-)

diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index f64724197958e0d8a4ec17deb1f9826ce3625eb7..3cbb999419af7bb31ce9cec2baafcad00491610a 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 4433a234aa9ba242f43b943d22011b5ddacd8af7..9f4e8d68ab505cf4a7aa8673643d9b47ca1bc7cb 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index c1ab31429a0e5fab97cd06c3b7b6e378170bd99d..cc9cb63959463a7ddb35d868b17e485b1223d507 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,6 +344,65 @@ static inline void __hyp_sve_save_host(void)
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 4e757a77322c9efc59cdff501745f7c80d452358..75f7e386de75bc3d329a0e94ca50a043813979fc 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -177,7 +178,9 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -486,12 +489,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index ee74006c47bc44ca1d9bdf1ce7d4d8a41cf8e494..a1245fa838319544f3770a05a58eeed5233f0324 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 46c1f5caf007331cdbbc806a184e9b4721042fc0..496abfd3646b9858e95e06a79edec11eee3a5893 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())

-- 
2.39.5



From broonie at kernel.org  Thu Mar 20 17:16:00 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:00 +0000
Subject: [PATCH 6.6 0/8] KVM: arm64: Backport of SVE fixes to v6.6
Message-ID: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>

This series backports some recent fixes for SVE/KVM interactions from
Mark Rutland to v6.6.

Signed-off-by: Mark Brown <broonie at kernel.org>
---
Fuad Tabba (1):
      KVM: arm64: Calculate cptr_el2 traps on activating traps

Mark Rutland (7):
      KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
      KVM: arm64: Remove host FPSIMD saving for non-protected KVM
      KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
      KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
      KVM: arm64: Refactor exit handlers
      KVM: arm64: Mark some header functions as inline
      KVM: arm64: Eagerly switch ZCR_EL{1,2}

 arch/arm64/include/asm/kvm_host.h       |   7 +--
 arch/arm64/include/asm/kvm_hyp.h        |   1 +
 arch/arm64/kernel/fpsimd.c              |  25 --------
 arch/arm64/kvm/arm.c                    |   1 -
 arch/arm64/kvm/fpsimd.c                 |  89 +++++----------------------
 arch/arm64/kvm/hyp/entry.S              |   5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h | 106 +++++++++++++++++++++-----------
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |  15 +----
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |  29 +--------
 arch/arm64/kvm/hyp/nvhe/switch.c        | 106 ++++++++++++++++++++++----------
 arch/arm64/kvm/hyp/vhe/switch.c         |  13 ++--
 arch/arm64/kvm/reset.c                  |   3 +
 12 files changed, 182 insertions(+), 218 deletions(-)
---
base-commit: 594a1dd5138a6bbaa1697e5648cce23d2520eba9
change-id: 20250227-stable-sve-6-6-e795d85262b9

Best regards,
-- 
Mark Brown <broonie at kernel.org>



From broonie at kernel.org  Thu Mar 20 17:16:01 2025
From: broonie at kernel.org (Mark Brown)
Date: Fri, 21 Mar 2025 00:16:01 +0000
Subject: [PATCH 6.6 1/8] KVM: arm64: Calculate cptr_el2 traps on activating
 traps
In-Reply-To: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
References: <20250321-stable-sve-6-6-v1-0-0b3a6a14ea53@kernel.org>
Message-ID: <20250321-stable-sve-6-6-v1-1-0b3a6a14ea53@kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 arch/arm64/include/asm/kvm_host.h  |  1 -
 arch/arm64/kvm/arm.c               |  1 -
 arch/arm64/kvm/hyp/nvhe/hyp-main.c |  2 --
 arch/arm64/kvm/hyp/nvhe/pkvm.c     | 27 --------------------
 arch/arm64/kvm/hyp/nvhe/switch.c   | 52 +++++++++++++++++++++++---------------
 5 files changed, 32 insertions(+), 51 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index b84ed3ad91a9eba3a30a6081371f2ec98963de06..6a165ec5d3b74ece3e98e7bf45f3ea94cc30e6ec 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -486,7 +486,6 @@ struct kvm_vcpu_arch {
 	/* Values of trap registers for the guest. */
 	u64 hcr_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Values of trap registers for the host before guest entry. */
 	u64 mdcr_el2_host;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index ffdc2c4d07ee83dbeb78b76d93f700f53af35be6..9818cde948ca9c7028220322aea4ff3706542c93 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1309,7 +1309,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 2385fd03ed87c6c0450a1c2dbe830e95ce235ecc..67cc07283e642ab07e1c98c5745e2c6a2dd4f36e 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -36,7 +36,6 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
 
 	hyp_vcpu->vcpu.arch.hcr_el2	= host_vcpu->arch.hcr_el2;
 	hyp_vcpu->vcpu.arch.mdcr_el2	= host_vcpu->arch.mdcr_el2;
-	hyp_vcpu->vcpu.arch.cptr_el2	= host_vcpu->arch.cptr_el2;
 
 	hyp_vcpu->vcpu.arch.iflags	= host_vcpu->arch.iflags;
 	hyp_vcpu->vcpu.arch.fp_state	= host_vcpu->arch.fp_state;
@@ -59,7 +58,6 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
 	host_vcpu->arch.ctxt		= hyp_vcpu->vcpu.arch.ctxt;
 
 	host_vcpu->arch.hcr_el2		= hyp_vcpu->vcpu.arch.hcr_el2;
-	host_vcpu->arch.cptr_el2	= hyp_vcpu->vcpu.arch.cptr_el2;
 
 	host_vcpu->arch.fault		= hyp_vcpu->vcpu.arch.fault;
 
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 8033ef353a5da406dba355ab73854dfa39e93c27..9e7612343ad66d3dc13b8ee858a4e61e917901c9 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -26,8 +26,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -57,21 +55,10 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -101,7 +88,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -128,17 +114,8 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -189,10 +166,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 /*
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index c353a06ee7e6d624b41997021379b7b4cf77453d..1026be1964d9664b8b6de19e048aba91ee6463b0 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,34 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~(CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN);
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs(vcpu)) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
-	if (!guest_owns_fp_regs(vcpu)) {
-		if (has_hvhe())
-			val &= ~(CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |
-				 CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs(vcpu))
+			val |= CPTR_EL2_TZ;
+
+		if (!guest_owns_fp_regs(vcpu))
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs(vcpu))
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

-- 
2.39.5



From dsimic at manjaro.org  Thu Mar 20 17:38:08 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Fri, 21 Mar 2025 01:38:08 +0100
Subject: [PATCH] arm64: dts: rockchip: Allow Turing RK1 cooling fan to
 spin down
In-Reply-To: <20250315204852.1247992-1-CFSworks@gmail.com>
References: <20250315204852.1247992-1-CFSworks@gmail.com>
Message-ID: <e1cdc3a39b9201cb115b12b559899aee@manjaro.org>

Hello Sam,

On 2025-03-15 21:48, Sam Edwards wrote:
> The RK3588 thermal sensor driver only receives interrupts when a
> higher-temperature threshold is crossed; it cannot notify when the
> sensor cools back off. As a result, the driver must poll for 
> temperature
> changes to detect when the conditions for a thermal trip are no longer
> met. However, it only does so if the DT enables polling.
> 
> Before this patch, the RK1 DT did not enable polling, causing the fan 
> to
> continue running at the speed corresponding to the highest temperature
> reached.
> 
> Follow suit with similar RK3588 boards by setting a polling-delay of
> 1000ms, enabling the driver to detect when the sensor cools back off,
> allowing the fan speed to decrease as appropriate.
> 
> Fixes: 7c8ec5e6b9d6 ("arm64: dts: rockchip: Enable automatic fan
> control on Turing RK1")
> Signed-off-by: Sam Edwards <CFSworks at gmail.com>
> ---
>  arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> index 6bc46734cc14..0270bffce195 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> @@ -214,6 +214,8 @@ rgmii_phy: ethernet-phy at 1 {
>  };
> 
>  &package_thermal {
> +	polling-delay = <1000>;
> +
>  	trips {
>  		package_active1: trip-active1 {
>  			temperature = <45000>;

Thanks for the patch, it's looking good to me, with some related
thoughts below.  Please, feel free to include:

Reviewed-by: Dragan Simic <dsimic at manjaro.org>

After a quick look at the RK3588 TRM Part 1, it seems possible
to actually generate additional interrupts when the TSADC channel
temperature readouts reach predefined low thresholds.  Moreover,
avoiding the polling would actually help the SoC cool down a tiny
bit faster, which makes it worth detailed investigation in my book,
despite not being used by the downstream kernel code.


From andrew at codeconstruct.com.au  Thu Mar 20 17:39:29 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Fri, 21 Mar 2025 11:09:29 +1030
Subject: [PATCH v4 1/2] dt-bindings: arm: aspeed: Add AMD Onyx BMC
 compatible
In-Reply-To: <174233663954.4094319.18412685456723022993.robh@kernel.org>
References: <20250318174730.1921983-1-Rajaganesh.Rathinasabapathi@amd.com>
	 <174233663954.4094319.18412685456723022993.robh@kernel.org>
Message-ID: <158f6e8e6c41250d6b88c5f2b5dc6df5d728222b.camel@codeconstruct.com.au>

On Tue, 2025-03-18 at 17:26 -0500, Rob Herring (Arm) wrote:
> 
> On Tue, 18 Mar 2025 12:47:29 -0500, Rajaganesh Rathinasabapathi wrote:
> > Document new AMD Onyx BMC board compatibles
> > 
> > Signed-off-by: Rajaganesh Rathinasabapathi <Rajaganesh.Rathinasabapathi at amd.com>
> > ---
> > ?Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
> > ?1 file changed, 1 insertion(+)
> > 
> 
> 
> My bot found new DTB warnings on the .dts files added or changed in this
> series.
> 
> Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
> are fixed by another series. Ultimately, it is up to the platform
> maintainer whether these warnings are acceptable or not. No need to reply
> unless the platform maintainer has comments.
> 
> If you already ran DT checks and didn't see these error(s), then
> make sure dt-schema is up to date:
> 
> ? pip3 install dtschema --upgrade
> 
> 
> New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250318174730.1921983-1-Rajaganesh.Rathinasabapathi at amd.com:
> 
...
> 
> arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: mbeeprom at 50: $nodename:0: 'mbeeprom at 50' does not match '^eeprom@[0-9a-f]{1,2}$'
> ????????from schema $id: http://devicetree.org/schemas/eeprom/at24.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-amd-onyx.dtb: mbeeprom at 50: Unevaluated properties are not allowed ('$nodename' was unexpected)
> ????????from schema $id: http://devicetree.org/schemas/eeprom/at24.yaml#

Rajaganesh: Please fix these warnings before you send v5.

Andrew


From ck.hu at mediatek.com  Thu Mar 20 17:59:46 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Fri, 21 Mar 2025 00:59:46 +0000
Subject: [PATCH v8 3/3] drm/mediatek: dsi: remove custom init part
In-Reply-To: <20231023-display-support-v8-3-c2dd7b0fb2bd@baylibre.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
	 <20231023-display-support-v8-3-c2dd7b0fb2bd@baylibre.com>
Message-ID: <c0f31248f8ea936147445d92f7e39d93f5d47c35.camel@mediatek.com>

On Thu, 2025-03-20 at 09:48 +0100, Alexandre Mergnat wrote:
> External email : Please do not click links or open attachments until you have verified the sender or the content.
> 
> 
> To be aligned with the DRM framework and avoid DSI power being driven
> by two different entities, remove the custom function and keep the DRM
> API to initialize the DSI.

In MT8173, need this custom init so dsi could work correctly.
I'm not sure it's software problem or hardware problem.
If it's hardware problem, this custom init could not be removed.
If it's software problem, it may be fixed in current version.
But I don't know it's fixed or not.
So I need someone to test this patch in MT8173 platform.
Otherwise, I could not apply this patch.

Regards,
CK

> 
> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.c |  2 --
>  drivers/gpu/drm/mediatek/mtk_disp_drv.h |  2 --
>  drivers/gpu/drm/mediatek/mtk_dsi.c      | 16 ----------------
>  3 files changed, 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index edc6417639e64..d86eed0d279d3 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -317,8 +317,6 @@ static const struct mtk_ddp_comp_funcs ddp_dsc = {
>  };
> 
>  static const struct mtk_ddp_comp_funcs ddp_dsi = {
> -       .start = mtk_dsi_ddp_start,
> -       .stop = mtk_dsi_ddp_stop,
>         .encoder_index = mtk_dsi_encoder_index,
>  };
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 04217a36939cd..5657854fa2f9e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -47,8 +47,6 @@ void mtk_dpi_start(struct device *dev);
>  void mtk_dpi_stop(struct device *dev);
>  unsigned int mtk_dpi_encoder_index(struct device *dev);
> 
> -void mtk_dsi_ddp_start(struct device *dev);
> -void mtk_dsi_ddp_stop(struct device *dev);
>  unsigned int mtk_dsi_encoder_index(struct device *dev);
> 
>  int mtk_gamma_clk_enable(struct device *dev);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index e61b9bc68e9a3..b813b49340420 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -787,7 +787,6 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
>  {
>         if (dsi->enabled)
>                 return;
> -
>         mtk_dsi_lane_ready(dsi);
>         mtk_dsi_set_mode(dsi);
>         mtk_dsi_clk_hs_mode(dsi, 1);
> @@ -893,20 +892,6 @@ static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = {
>         .mode_set = mtk_dsi_bridge_mode_set,
>  };
> 
> -void mtk_dsi_ddp_start(struct device *dev)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       mtk_dsi_poweron(dsi);
> -}
> -
> -void mtk_dsi_ddp_stop(struct device *dev)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       mtk_dsi_poweroff(dsi);
> -}
> -
>  static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -1243,7 +1228,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>         }
> 
>         init_waitqueue_head(&dsi->irq_wait_queue);
> -
>         platform_set_drvdata(pdev, dsi);
> 
>         dsi->bridge.funcs = &mtk_dsi_bridge_funcs;
> 
> --
> 2.25.1
> 


From andrew at codeconstruct.com.au  Thu Mar 20 18:06:53 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Fri, 21 Mar 2025 11:36:53 +1030
Subject: [PATCH v3 2/2] dt-bindings: arm: aspeed: add Nvidia's GB200NVL
 BMC
In-Reply-To: <20250320164633.101331-3-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
	 <20250320164633.101331-3-wthai@nvidia.com>
Message-ID: <585c2b050a44f4009b3a61cab69f800c88a0cf5e.camel@codeconstruct.com.au>

Hi Willie,

On Thu, 2025-03-20 at 16:46 +0000, Willie Thai wrote:
> This patch adds a binding for GB200NVL BMC.
> 
> The GB200NVL BMC is an Aspeed Ast2600 based BMC for Nvidia Blackwell
> GB200NVL platform.
> Reference to Ast2600 SOC [1].
> Reference to Blackwell GB200NVL Platform [2].
> 
> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Link: https://www.aspeedtech.com/server_ast2600/?[1]
> Link:
> https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703?[2]
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---
> ?Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
> ?1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> index 01333ac111fb..a3736f134130 100644
> --- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> +++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> @@ -98,6 +98,7 @@ properties:
> ?????????????? - inventec,starscream-bmc
> ?????????????? - inventec,transformer-bmc
> ?????????????? - jabil,rbp-bmc
> +????????????? - nvidia,gb200nvl-bmc
> ?????????????? - qcom,dc-scm-v1-bmc
> ?????????????? - quanta,s6q-bmc
> ?????????????? - ufispace,ncplite-bmc

Please order this patch first in your series, before the devicetree.

Andrew


From andrew at codeconstruct.com.au  Thu Mar 20 18:06:37 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Fri, 21 Mar 2025 11:36:37 +1030
Subject: [PATCH v3 0/2] Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <174249492169.658140.8130213005563532857.robh@kernel.org>
References: <20250320164633.101331-1-wthai@nvidia.com>
	 <174249492169.658140.8130213005563532857.robh@kernel.org>
Message-ID: <4471e1948ab420ae0574e1442d445800bc19240c.camel@codeconstruct.com.au>

Hi Willie,

On Thu, 2025-03-20 at 13:26 -0500, Rob Herring (Arm) wrote:
> 
> On Thu, 20 Mar 2025 16:46:31 +0000, Willie Thai wrote:
> > The GB200NVL BMC is an Aspeed Ast2600 based BMC
> > for Nvidia Blackwell GB200NVL platform.
> > Reference to Ast2600 SOC [1].
> > Reference to Blackwell GB200NVL Platform [2].
> > 
> > Co-developed-by: Mars Yang <maryang at nvidia.com>
> > Signed-off-by: Mars Yang <maryang at nvidia.com>
> > Cc: Krzysztof Kozlowski <krzk at kernel.org>
> > Cc: Andrew Lunn <andrew at lunn.ch>
> > Cc: Rob Herring <robh at kernel.org>
> > Cc: Paul Menzel <pmenzel at molgen.mpg.de>
> > Link: https://www.aspeedtech.com/server_ast2600/?[1]
> > Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703?[2]
> > Signed-off-by: Willie Thai <wthai at nvidia.com>
> > ---
> > Changes v1 -> v2:
> > ? - Fix the SOB name [Krzysztof]
> > ? - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
> > ? - Fix DTS coding style [Krzysztof]
> > ? - Move pinctrl override to the bottom [Krzysztof]
> > ? - Drop bootargs [Krzysztof]
> > ? - Follow DTS coding style and change naming for leds node [Krzysztof]
> > ? - Change flash 0 status property [Krzysztof]
> > ? - Change the phy-mode to rgmii [Andrew]
> > ? - Remove the max-speed in mac0 [Andrew]
> > ? - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
> > Changes v2 -> v3:
> > ? - Fix missing new line [Krzysztof]
> > ? - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
> > ? - Fix DTS coding style [Krzysztof]
> > ? - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
> > ? - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
> > ? - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
> > ---
> > 
> > Willie Thai (2):
> > ? ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
> > ? dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
> > 
> > ?.../bindings/arm/aspeed/aspeed.yaml?????????? |??? 1 +
> > ?arch/arm/boot/dts/aspeed/Makefile???????????? |??? 1 +
> > ?.../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1168 +++++++++++++++++
> > ?3 files changed, 1170 insertions(+)
> > ?create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> > 
> > --
> > 2.25.1
> > 
> > 
> > 
> 
> 
> My bot found new DTB warnings on the .dts files added or changed in this
> series.
> 
> Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
> are fixed by another series. Ultimately, it is up to the platform
> maintainer whether these warnings are acceptable or not. No need to reply
> unless the platform maintainer has comments.
> 
> If you already ran DT checks and didn't see these error(s), then
> make sure dt-schema is up to date:
> 
> ? pip3 install dtschema --upgrade
> 
> 
> New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250320164633.101331-1-wthai at nvidia.com:
> 
...

> 
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pinctrl: emmcg5_default:groups:0: 'EMMCG5' is not one of ['ADC0', 'ADC1', 'ADC10', 'ADC11', 'ADC12', 'ADC13', 'ADC14', 'ADC15', 'ADC2', 'ADC3', 'ADC4', 'ADC5', 'ADC6', 'ADC7', 'ADC8', 'ADC9', 'BMCINT', 'EMMCG1', 'EMMCG4', 'EMMCG8', 'ESPI', 'ESPIALT', 'FSI1', 'FSI2', 'FWQSPI', 'FWSPIABR', 'FWSPID', 'FWSPIWP', 'GPIT0', 'GPIT1', 'GPIT2', 'GPIT3', 'GPIT4', 'GPIT5', 'GPIT6', 'GPIT7', 'GPIU0', 'GPIU1', 'GPIU2', 'GPIU3', 'GPIU4', 'GPIU5', 'GPIU6', 'GPIU7', 'HVI3C3', 'HVI3C4', 'I2C1', 'I2C10', 'I2C11', 'I2C12', 'I2C13', 'I2C14', 'I2C15', 'I2C16', 'I2C2', 'I2C3', 'I2C4', 'I2C5', 'I2C6', 'I2C7', 'I2C8', 'I2C9', 'I3C1', 'I3C2', 'I3C3', 'I3C4', 'I3C5', 'I3C6', 'JTAGM', 'LHPD', 'LHSIRQ', 'LPC', 'LPCHC', 'LPCPD', 'LPCPME', 'LPCSMI', 'LSIRQ', 'MACLINK1', 'MACLINK2', 'MACLINK3', 'MACLINK4', 'MDIO1', 'MDIO2', 'MDIO3', 'MDIO4', 'NCSI3', 'NCSI4', 'NCTS1', 'NCTS2', 'NCTS3', 'NCTS4', 'NDCD1', 'NDCD2', 'NDCD3', 'NDCD4', 'NDSR1', 'NDSR2', 'NDSR3'
> ?, 'NDSR4', 'NDTR1', 'NDTR2', 'NDTR3', 'NDTR4', 'NRI1', 'NRI2', 'NRI3', 'NRI4', 'NRTS1', 'NRTS2', 'NRTS3', 'NRTS4', 'OSCCLK', 'PEWAKE', 'PWM0', 'PWM1', 'PWM10G0', 'PWM10G1', 'PWM11G0', 'PWM11G1', 'PWM12G0', 'PWM12G1', 'PWM13G0', 'PWM13G1', 'PWM14G0', 'PWM14G1', 'PWM15G0', 'PWM15G1', 'PWM2', 'PWM3', 'PWM4', 'PWM5', 'PWM6', 'PWM7', 'PWM8G0', 'PWM8G1', 'PWM9G0', 'PWM9G1', 'QSPI1', 'QSPI2', 'RGMII1', 'RGMII2', 'RGMII3', 'RGMII4', 'RMII1', 'RMII2', 'RMII3', 'RMII4', 'RXD1', 'RXD2', 'RXD3', 'RXD4', 'SALT1', 'SALT10G0', 'SALT10G1', 'SALT11G0', 'SALT11G1', 'SALT12G0', 'SALT12G1', 'SALT13G0', 'SALT13G1', 'SALT14G0', 'SALT14G1', 'SALT15G0', 'SALT15G1', 'SALT16G0', 'SALT16G1', 'SALT2', 'SALT3', 'SALT4', 'SALT5', 'SALT6', 'SALT7', 'SALT8', 'SALT9G0', 'SALT9G1', 'SD1', 'SD2', 'SD3', 'SGPM1', 'SGPM2', 'SGPS1', 'SGPS2', 'SIOONCTRL', 'SIOPBI', 'SIOPBO', 'SIOPWREQ', 'SIOPWRGD', 'SIOS3', 'SIOS5', 'SIOSCI', 'SPI1', 'SPI1ABR', 'SPI1CS1', 'SPI1WP', 'SPI2', 'SPI2CS1', 'SPI2CS2', 'TACH0', 'TACH1', 'TACH10'
> ?, 'TACH11', 'TACH12', 'TACH13', 'TACH14', 'TACH15', 'TACH2', 'TACH3', 'TACH4', 'TACH5', 'TACH6', 'TACH7', 'TACH8', 'TACH9', 'THRU0', 'THRU1', 'THRU2', 'THRU3', 'TXD1', 'TXD2', 'TXD3', 'TXD4', 'UART10', 'UART11', 'UART12G0', 'UART12G1', 'UART13G0', 'UART13G1', 'UART6', 'UART7', 'UART8', 'UART9', 'USBA', 'USBB', 'VB', 'VGAHS', 'VGAVS', 'WDTRST1', 'WDTRST2', 'WDTRST3', 'WDTRST4']
> ????????from schema $id: http://devicetree.org/schemas/pinctrl/aspeed,ast2600-pinctrl.yaml#

...

> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: i2c at 80: Unevaluated properties are not allowed ('disable-master' was unexpected)
> ????????from schema $id: http://devicetree.org/schemas/i2c/aspeed,i2c.yaml#

...

> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 23: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 2c: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: pwm at 2f: '#address-cells', '#size-cells' do not match any of the regexes: '^fan-[0-9]+$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 20: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 21: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 27: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#
> arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: gpio at 74: '#address-cells', '#size-cells' do not match any of the regexes: '^(hog-[0-9]+|.+-hog(-[0-9]+)?)$', 'pinctrl-[0-9]+'
> ????????from schema $id: http://devicetree.org/schemas/gpio/gpio-pca95xx.yaml#

Please fix all of the warnings highlighted above before submitting v4.

Thanks,

Andrew


From andrew at codeconstruct.com.au  Thu Mar 20 18:17:22 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Fri, 21 Mar 2025 11:47:22 +1030
Subject: [PATCH v5 05/10] ARM: dts: aspeed: catalina: Add second source
 fan controller support
In-Reply-To: <20250320-potin-catalina-dts-update-20250102-v5-5-e161be6583a7@gmail.com>
References: <20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7@gmail.com>
	 <20250320-potin-catalina-dts-update-20250102-v5-5-e161be6583a7@gmail.com>
Message-ID: <26a1d17c47c5ca6036dd58ac3b953daeec9f5ef8.camel@codeconstruct.com.au>

Hi Potin,

On Thu, 2025-03-20 at 23:21 +0800, Potin Lai wrote:
> Add device tree nodes for the NCT7363 fan controllers on the second-
> source
> Power Distribution Board (PDB).
> 
> Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
> ---
> ?.../dts/aspeed/aspeed-bmc-facebook-catalina.dts??? | 76
> ++++++++++++++++++++++
> ?1 file changed, 76 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-
> catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-
> catalina.dts
> index fd22add90449..9cbb296dcd9e 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
> @@ -467,6 +467,82 @@ i2c1mux0ch2: i2c at 2 {
> ????????????????????????#size-cells = <0>;
> ????????????????????????reg = <0x2>;
> ?
> +???????????????????????hwmon0: hwmon at 1 {

There might be instances of calling nodes and labels 'hwmon' in other
(BMC) devicetrees, but I don't think we should continue that practice.
I think in this case it should be 'fan-controller'.

hwmon is the name of a kernel subsystem, not a class of hardware. The
devicetrees should describe the hardware (and not concepts from the
kernel).


> +???????????????????????????????compatible = "nuvoton,nct7363";
> +???????????????????????????????reg = <0x01>;
> +???????????????????????????????#pwm-cells = <2>;
> +
> +???????????????????????????????fan-9 {
> +???????????????????????????????????????pwms = <&hwmon0 0 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x09>;
> +???????????????????????????????};
> +???????????????????????????????fan-11 {
> +???????????????????????????????????????pwms = <&hwmon0 0 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0b>;
> +???????????????????????????????};
> +???????????????????????????????fan-10 {
> +???????????????????????????????????????pwms = <&hwmon0 4 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0a>;
> +???????????????????????????????};
> +???????????????????????????????fan-13 {
> +???????????????????????????????????????pwms = <&hwmon0 4 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0d>;
> +???????????????????????????????};
> +???????????????????????????????fan-15 {
> +???????????????????????????????????????pwms = <&hwmon0 6 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0f>;
> +???????????????????????????????};
> +???????????????????????????????fan-1 {
> +???????????????????????????????????????pwms = <&hwmon0 6 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x01>;
> +???????????????????????????????};
> +???????????????????????????????fan-0 {
> +???????????????????????????????????????pwms = <&hwmon0 10 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x00>;
> +???????????????????????????????};
> +???????????????????????????????fan-3 {
> +???????????????????????????????????????pwms = <&hwmon0 10 40000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x03>;
> +???????????????????????????????};
> +???????????????????????};
> +???????????????????????hwmon1: hwmon at 2 {

As above.

Andrew

From cfsworks at gmail.com  Thu Mar 20 18:20:20 2025
From: cfsworks at gmail.com (Sam Edwards)
Date: Thu, 20 Mar 2025 18:20:20 -0700
Subject: [PATCH] arm64: dts: rockchip: Allow Turing RK1 cooling fan to
 spin down
In-Reply-To: <e1cdc3a39b9201cb115b12b559899aee@manjaro.org>
References: <20250315204852.1247992-1-CFSworks@gmail.com> <e1cdc3a39b9201cb115b12b559899aee@manjaro.org>
Message-ID: <CAH5Ym4hqkMMBsT7XEz_f+TCng+0X2m0nV_Kdr-LAPBqgENgr5A@mail.gmail.com>

On Thu, Mar 20, 2025 at 5:38?PM Dragan Simic <dsimic at manjaro.org> wrote:
>
> Hello Sam,
>
> On 2025-03-15 21:48, Sam Edwards wrote:
> > The RK3588 thermal sensor driver only receives interrupts when a
> > higher-temperature threshold is crossed; it cannot notify when the
> > sensor cools back off. As a result, the driver must poll for
> > temperature
> > changes to detect when the conditions for a thermal trip are no longer
> > met. However, it only does so if the DT enables polling.
> >
> > Before this patch, the RK1 DT did not enable polling, causing the fan
> > to
> > continue running at the speed corresponding to the highest temperature
> > reached.
> >
> > Follow suit with similar RK3588 boards by setting a polling-delay of
> > 1000ms, enabling the driver to detect when the sensor cools back off,
> > allowing the fan speed to decrease as appropriate.
> >
> > Fixes: 7c8ec5e6b9d6 ("arm64: dts: rockchip: Enable automatic fan
> > control on Turing RK1")
> > Signed-off-by: Sam Edwards <CFSworks at gmail.com>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> > b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> > index 6bc46734cc14..0270bffce195 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
> > @@ -214,6 +214,8 @@ rgmii_phy: ethernet-phy at 1 {
> >  };
> >
> >  &package_thermal {
> > +     polling-delay = <1000>;
> > +
> >       trips {
> >               package_active1: trip-active1 {
> >                       temperature = <45000>;
>
> Thanks for the patch, it's looking good to me, with some related
> thoughts below.  Please, feel free to include:
>
> Reviewed-by: Dragan Simic <dsimic at manjaro.org>
>
> After a quick look at the RK3588 TRM Part 1, it seems possible
> to actually generate additional interrupts when the TSADC channel
> temperature readouts reach predefined low thresholds.  Moreover,

Hi Dragan,

Ooh, I see that now!

It seems to be as simple as adding a `.set_cooloff_temp = ...` that
writes the lower thresholds to TSADC_COMP#_LOW_INT and sets the
necessary bits in TSADC_LT_EN+TSADC_LT_INT_EN. Since the driver
already rescans all temperatures on any interrupt and acknowledges all
interrupt status bits indiscriminately, I don't anticipate any other
necessary changes.

I can easily take care of that this weekend or next if that plan
sounds good to you. However, since *this* patch is a Fixes:, I'd
rather land it as-is first and handle the above separately. :)

> avoiding the polling would actually help the SoC cool down a tiny
> bit faster, which makes it worth detailed investigation in my book,
> despite not being used by the downstream kernel code.

Do you mean "spin down the fan a tiny bit faster" (since it would
detect the cool-off without needing to poll for it), or are you
emphasizing saving CPU cycles that would otherwise be spent polling?

Thanks for the tip,
Sam


From peter.chen at cixtech.com  Thu Mar 20 18:40:00 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Fri, 21 Mar 2025 09:40:00 +0800
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <zsmeh4ukuspyetowryqi3blcquxlua5wzy5ibgy7lupryr5txx@74ic6drtremv>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
 <7419360a-abc0-44cf-8d55-8f5fad8e9079@kernel.org>
 <Z9vyy7f5NOPyzUES@nchen-desktop>
 <zsmeh4ukuspyetowryqi3blcquxlua5wzy5ibgy7lupryr5txx@74ic6drtremv>
Message-ID: <Z9zDcMRVqAcJW8H7@nchen-desktop>

On 25-03-20 15:28:49, Kajetan Puchalski wrote:
> 
> > > > +ARM/CIX SKY ARM ARCHITECTURE
> > > > +M:   Peter Chen <peter.chen at cixtech.com>
> > > > +M:   Fugang Duan <fugang.duan at cixtech.com>
> > > > +R:   CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
> > > > +L:   linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> > > > +S:   Maintained
> > > > +F:   Documentation/devicetree/bindings/arm/cix.yaml
> > > > +F:   arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> > > > +F:   arch/arm64/boot/dts/cix/sky1.dtsi
> > >
> > > Instead:
> > > arch/arm64/boot/dts/cix/
> > >
> > > or if you think there will be more different architectures coming from
> > > cix, which you will not maintain, then useful would be a "sky" subdirectory.
> > >
> > Hi Krzysztof,
> >
> > Thanks for your comment, CIX is Arm SoC based silicon design
> > company, we may have different SoC style for middle end in future.
> > So, for that SoC series, it may not name sky.
> 
> I believe the idea is that the file should either say
> 
> +F:   arch/arm64/boot/dts/cix/
> 
> if the two of you intend to be maintainers for everything under cix/.
> You don't need to list every specific file.
> 
> Otherwise it should say
> 
> +F:   arch/arm64/boot/dts/cix/sky/
> 
> with its own subdirectory if you only intend to be maintaining the sky family.

Hi Kajetan & Krzysztof,

Thanks for your valuable comments. We prefer maintain the entire
CIX architecture under one entry, I will change maintain information
like below:

ARM/CIX SOC SUPPORT
M:	Peter Chen <peter.chen at cixtech.com>
M:	Fugang Duan <fugang.duan at cixtech.com>
R:	CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
S:	Maintained
F:	Documentation/devicetree/bindings/arm/cix.yaml
F:	arch/arm64/boot/dts/cix/

-- 

Best regards,
Peter


From baolu.lu at linux.intel.com  Thu Mar 20 19:11:44 2025
From: baolu.lu at linux.intel.com (Baolu Lu)
Date: Fri, 21 Mar 2025 10:11:44 +0800
Subject: [PATCH 5/6] iommu: make inclusion of arm/arm-smmu-v3 directory
 conditional
In-Reply-To: <6164975.lOV4Wx5bFT@devpool47.emlix.com>
References: <12652899.O9o76ZdvQC@devpool47.emlix.com>
 <6164975.lOV4Wx5bFT@devpool47.emlix.com>
Message-ID: <3506c422-6508-42f6-8624-b968b7ffba08@linux.intel.com>

On 3/20/25 17:19, Rolf Eike Beer wrote:
> Nothing in there is active if CONFIG_ARM_SMMU_V3 is not enabled, so the whole
> directory can depend on that switch as well.
> 
> Fixes: e86d1aa8b60f ("iommu/arm-smmu: Move Arm SMMU drivers into their own subdirectory")
> Signed-off-by: Rolf Eike Beer<eb at emlix.com>

Reviewed-by: Lu Baolu <baolu.lu at linux.intel.com>


From dsimic at manjaro.org  Thu Mar 20 19:19:30 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Fri, 21 Mar 2025 03:19:30 +0100
Subject: [PATCH] arm64: dts: rockchip: Allow Turing RK1 cooling fan to
 spin down
In-Reply-To: <CAH5Ym4hqkMMBsT7XEz_f+TCng+0X2m0nV_Kdr-LAPBqgENgr5A@mail.gmail.com>
References: <20250315204852.1247992-1-CFSworks@gmail.com>
 <e1cdc3a39b9201cb115b12b559899aee@manjaro.org>
 <CAH5Ym4hqkMMBsT7XEz_f+TCng+0X2m0nV_Kdr-LAPBqgENgr5A@mail.gmail.com>
Message-ID: <57bb477925efc74a0ea11b20321fa661@manjaro.org>

Hello Sam,

On 2025-03-21 02:20, Sam Edwards wrote:
> On Thu, Mar 20, 2025 at 5:38?PM Dragan Simic <dsimic at manjaro.org> 
> wrote:
>> On 2025-03-15 21:48, Sam Edwards wrote:
>> > The RK3588 thermal sensor driver only receives interrupts when a
>> > higher-temperature threshold is crossed; it cannot notify when the
>> > sensor cools back off. As a result, the driver must poll for
>> > temperature
>> > changes to detect when the conditions for a thermal trip are no longer
>> > met. However, it only does so if the DT enables polling.
>> >
>> > Before this patch, the RK1 DT did not enable polling, causing the fan
>> > to
>> > continue running at the speed corresponding to the highest temperature
>> > reached.
>> >
>> > Follow suit with similar RK3588 boards by setting a polling-delay of
>> > 1000ms, enabling the driver to detect when the sensor cools back off,
>> > allowing the fan speed to decrease as appropriate.
>> >
>> > Fixes: 7c8ec5e6b9d6 ("arm64: dts: rockchip: Enable automatic fan
>> > control on Turing RK1")
>> > Signed-off-by: Sam Edwards <CFSworks at gmail.com>
>> > ---
>> >  arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 2 ++
>> >  1 file changed, 2 insertions(+)
>> >
>> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
>> > b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
>> > index 6bc46734cc14..0270bffce195 100644
>> > --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
>> > +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
>> > @@ -214,6 +214,8 @@ rgmii_phy: ethernet-phy at 1 {
>> >  };
>> >
>> >  &package_thermal {
>> > +     polling-delay = <1000>;
>> > +
>> >       trips {
>> >               package_active1: trip-active1 {
>> >                       temperature = <45000>;
>> 
>> Thanks for the patch, it's looking good to me, with some related
>> thoughts below.  Please, feel free to include:
>> 
>> Reviewed-by: Dragan Simic <dsimic at manjaro.org>
>> 
>> After a quick look at the RK3588 TRM Part 1, it seems possible
>> to actually generate additional interrupts when the TSADC channel
>> temperature readouts reach predefined low thresholds.  Moreover,
> 
> It seems to be as simple as adding a `.set_cooloff_temp = ...` that
> writes the lower thresholds to TSADC_COMP#_LOW_INT and sets the
> necessary bits in TSADC_LT_EN+TSADC_LT_INT_EN. Since the driver
> already rescans all temperatures on any interrupt and acknowledges all
> interrupt status bits indiscriminately, I don't anticipate any other
> necessary changes.

Hmm, I'm afraid it isn't that simple...  See, the entire thermal
framework is rather complex and there may be hidden issues, because
such handling of the cooldown events probably isn't the most common
variant on all boards supported upstream.

Even if everything is fine there, with the dynamic reassigning of
the cooldown thresholds and everything else, which hopefully is, :)
generating and handling the LT_INT interrupts, at the first glance,
requires rather major changes to the driver because it introduces
a different class of interrupts, for which the amount of required
changes isn't exactly small.

> I can easily take care of that this weekend or next if that plan
> sounds good to you. However, since *this* patch is a Fixes:, I'd
> rather land it as-is first and handle the above separately. :)

I totally agree that this patch needs to get merged first, perhaps
even as a v2 that would include "Cc: stable" as well.

Regarding adding support for LT_INT interrupts, frankly, I'd much
rather leave that do be done as part of my upcoming major rework
of the OPPs by introducing the SoC binning.  As part of that, I'll
do a whole lot of testing on different boards with different SoCs
and their different variants, which should ensure that everything
works as expected, including the LT_INT stuff.

>> avoiding the polling would actually help the SoC cool down a tiny
>> bit faster, which makes it worth detailed investigation in my book,
>> despite not being used by the downstream kernel code.
> 
> Do you mean "spin down the fan a tiny bit faster" (since it would
> detect the cool-off without needing to poll for it), or are you
> emphasizing saving CPU cycles that would otherwise be spent polling?

Technically both, :) but of course, the primary goal would be to make
the CPU not do what it doesn't really have to, and spinning down the
fan faster would be just an additional benefit.  It isn't going to
make some huge difference in the CPU load (or better said, in the
"background noise"), but again, every tiny bit counts.

When it comes to the HT_INT interrupts, they're obviously much more
important, because there must not be any delays when (over)heating
happens.  That isn't so critical with the LT_INT interrupts, which
is probably the reason why the downstream kernel code uses HT_INT
interrupts only.


From devnull+xianwei.zhao.amlogic.com at kernel.org  Thu Mar 20 19:23:55 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Fri, 21 Mar 2025 10:23:55 +0800
Subject: [PATCH] arm64: dts: amlogic: a4: fix dtb compilation warning
 issues
Message-ID: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

When use command 'make ARCH=arm64 dtbs_check W=1' to compile dtb,
a warning message appears.
"Warning (simple_bus_reg): /soc/bus at fe000000/pinctrl:
missing or empty reg/ranges property"

Add the unit address to the pinctrl node to fix it.

Fixes: ce78f679e08c ("arm64: dts: amlogic: a4: add pinctrl node")
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 102 +++++++++++++++-------------
 1 file changed, 55 insertions(+), 47 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index fa80fa365f13..582e0043024b 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -51,87 +51,52 @@ pwrc: power-controller {
 };
 
 &apb {
-	gpio_intc: interrupt-controller at 4080 {
-		compatible = "amlogic,a4-gpio-intc",
-			     "amlogic,meson-gpio-intc";
-		reg = <0x0 0x4080 0x0 0x20>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		amlogic,channel-interrupts =
-			<10 11 12 13 14 15 16 17 18 19 20 21>;
-	};
-
-	gpio_ao_intc: interrupt-controller at 8e72c {
-		compatible = "amlogic,a4-gpio-ao-intc",
-			     "amlogic,meson-gpio-intc";
-		reg = <0x0 0x8e72c 0x0 0x0c>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		amlogic,channel-interrupts = <140 141>;
-	};
-
-	periphs_pinctrl: pinctrl {
+	periphs_pinctrl: pinctrl at 4000 {
 		compatible = "amlogic,pinctrl-a4";
 		#address-cells = <2>;
 		#size-cells = <2>;
-		ranges;
+		ranges = <0x0 0x0 0x0 0x4000 0x0 0x280>;
 
-		gpiox: gpio at 4100 {
-			reg = <0 0x4100 0 0x40>, <0 0x400c 0 0xc>;
+		gpiox: gpio at 100 {
+			reg = <0 0x100 0 0x40>, <0 0xc 0 0xc>;
 			reg-names = "gpio", "mux";
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_X<<8) 18>;
 		};
 
-		gpiot: gpio at 4140 {
-			reg = <0 0x4140 0 0x40>, <0 0x402c 0 0xc>;
+		gpiot: gpio at 140 {
+			reg = <0 0x140 0 0x40>, <0 0x2c 0 0xc>;
 			reg-names = "gpio", "mux";
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_T<<8) 23>;
 		};
 
-		gpiod: gpio at 4180 {
-			reg = <0 0x4180 0 0x40>, <0 0x4040 0 0x8>;
+		gpiod: gpio at 180 {
+			reg = <0 0x180 0 0x40>, <0 0x40 0 0x8>;
 			reg-names = "gpio", "mux";
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_D<<8) 16>;
 		};
 
-		gpioe: gpio at 41c0 {
-			reg = <0 0x41c0 0 0x40>, <0 0x4048 0 0x4>;
+		gpioe: gpio at 1c0 {
+			reg = <0 0x1c0 0 0x40>, <0 0x48 0 0x4>;
 			reg-names = "gpio", "mux";
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_E<<8) 2>;
 		};
 
-		gpiob: gpio at 4240 {
-			reg = <0 0x4240 0 0x40>, <0 0x4000 0 0x8>;
+		gpiob: gpio at 240 {
+			reg = <0 0x240 0 0x40>, <0 0 0 0x8>;
 			reg-names = "gpio", "mux";
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_B<<8) 14>;
 		};
 
-		gpioao: gpio at 8e704 {
-			reg = <0 0x8e704 0 0x16>, <0 0x8e700 0 0x4>;
-			reg-names = "gpio", "mux";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_AO<<8) 7>;
-		};
-
-		test_n: gpio at 8e744 {
-			reg = <0 0x8e744 0 0x20>;
-			reg-names = "gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
-		};
-
 		func-uart-a {
 			uart_a_default: group-uart-a-pins1 {
 				pinmux = <AML_PINMUX(AMLOGIC_GPIO_X, 11, 1)>,
@@ -186,4 +151,47 @@ uart_e_default: group-uart-e-pins {
 			};
 		};
 	};
+
+	gpio_intc: interrupt-controller at 4080 {
+		compatible = "amlogic,a4-gpio-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x4080 0x0 0x20>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts =
+			<10 11 12 13 14 15 16 17 18 19 20 21>;
+	};
+
+	ao_pinctrl: pinctrl at 8e700 {
+		compatible = "amlogic,pinctrl-a4";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x0 0x0 0x0 0x8e700 0x0 0x80>;
+
+		gpioao: gpio at 4 {
+			reg = <0 0x4 0 0x16>, <0 0 0 0x4>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_AO<<8) 7>;
+		};
+
+		test_n: gpio at 44 {
+			reg = <0 0x44 0 0x20>;
+			reg-names = "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
+		};
+	};
+
+	gpio_ao_intc: interrupt-controller at 8e72c {
+		compatible = "amlogic,a4-gpio-ao-intc",
+			     "amlogic,meson-gpio-intc";
+		reg = <0x0 0x8e72c 0x0 0x0c>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		amlogic,channel-interrupts = <140 141>;
+	};
+
 };

---
base-commit: 73a143e436311183186ab4b365a84c662f2c9651
change-id: 20250317-fix-a4-pinctrl-node-9babfd44e085

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From lkp at intel.com  Thu Mar 20 19:41:39 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 10:41:39 +0800
Subject: [soc:soc/drivers 20/24] ERROR: modpost: "__ffsdi2"
 [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
Message-ID: <202503211029.DnQpqsJs-lkp@intel.com>

Hi Marek,

First bad commit (maybe != root cause):

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
head:   ba8755ab541fc629948233125db870d4dbf00a75
commit: ee7f8ed72990f28657b5bf598e695fcf4633f4ed [20/24] platform: cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/config)
compiler: sh4-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503211029.DnQpqsJs-lkp at intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

ERROR: modpost: "__delay" [drivers/net/mdio/mdio-cavium.ko] undefined!
ERROR: modpost: "devm_of_clk_add_hw_provider" [drivers/media/i2c/tc358746.ko] undefined!
ERROR: modpost: "devm_clk_hw_register" [drivers/media/i2c/tc358746.ko] undefined!
ERROR: modpost: "of_clk_hw_simple_get" [drivers/media/i2c/tc358746.ko] undefined!
>> ERROR: modpost: "__ffsdi2" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From pcc at google.com  Thu Mar 20 19:41:50 2025
From: pcc at google.com (Peter Collingbourne)
Date: Thu, 20 Mar 2025 19:41:50 -0700
Subject: [PATCH v2 2/2] kasan: Add strscpy() test to trigger tag fault on arm64
In-Reply-To: <CA+fCnZfG79JmGG9rj7KbE=9yX-EM4e8CXDSm5F9=YEmgyX5v3w@mail.gmail.com>
References: <20250318214035.481950-1-pcc@google.com> <20250318214035.481950-3-pcc@google.com>
 <CA+fCnZfG79JmGG9rj7KbE=9yX-EM4e8CXDSm5F9=YEmgyX5v3w@mail.gmail.com>
Message-ID: <CAMn1gO4k-d+8ZwndJhF5Sudr+kWDABe+3Wq=iBhcg3tDwJ60Bg@mail.gmail.com>

On Thu, Mar 20, 2025 at 10:25?AM Andrey Konovalov <andreyknvl at gmail.com> wrote:
>
> On Tue, Mar 18, 2025 at 10:41?PM Peter Collingbourne <pcc at google.com> wrote:
> >
> > From: Vincenzo Frascino <vincenzo.frascino at arm.com>
> >
> > When we invoke strscpy() with a maximum size of N bytes, it assumes
> > that:
> > - It can always read N bytes from the source.
> > - It always write N bytes (zero-padded) to the destination.
> >
> > On aarch64 with Memory Tagging Extension enabled if we pass an N that is
> > bigger then the source buffer, it triggers an MTE fault.
> >
> > Implement a KASAN KUnit test that triggers the issue with the current
> > implementation of read_word_at_a_time() on aarch64 with MTE enabled.
> >
> > Cc: Will Deacon <will at kernel.org>
> > Signed-off-by: Vincenzo Frascino <vincenzo.frascino at arm.com>
> > Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> > Co-developed-by: Peter Collingbourne <pcc at google.com>
> > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > Link: https://linux-review.googlesource.com/id/If88e396b9e7c058c1a4b5a252274120e77b1898a
> > ---
> > v2:
> > - rebased
> > - fixed test failure
> >
> >  mm/kasan/kasan_test_c.c | 31 ++++++++++++++++++++++++++++++-
> >  1 file changed, 30 insertions(+), 1 deletion(-)
> >
> > diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
> > index 59d673400085f..c4bb3ee497b54 100644
> > --- a/mm/kasan/kasan_test_c.c
> > +++ b/mm/kasan/kasan_test_c.c
> > @@ -1570,7 +1570,9 @@ static void kasan_memcmp(struct kunit *test)
> >  static void kasan_strings(struct kunit *test)
> >  {
> >         char *ptr;
> > -       size_t size = 24;
> > +       char *src, *src2;
> > +       u8 tag;
> > +       size_t size = 2 * KASAN_GRANULE_SIZE;
> >
> >         /*
> >          * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT.
> > @@ -1581,6 +1583,33 @@ static void kasan_strings(struct kunit *test)
> >         ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
> >         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
> >
> > +       src = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
> > +       strscpy(src, "f0cacc1a00000000f0cacc1a00000000", size);
> > +
> > +       tag = get_tag(src);
> > +
> > +       src2 = src + KASAN_GRANULE_SIZE;
> > +
> > +       /*
> > +        * Shorten string and poison the granule after it so that the unaligned
> > +        * read in strscpy() triggers a tag mismatch.
> > +        */
> > +       src[KASAN_GRANULE_SIZE - 1] = '\0';
> > +       kasan_poison(src2, KASAN_GRANULE_SIZE, tag + 1, false);
> > +
> > +       /*
> > +        * The expected size does not include the terminator '\0'
> > +        * so it is (KASAN_GRANULE_SIZE - 2) ==
> > +        * KASAN_GRANULE_SIZE - ("initial removed character" + "\0").
> > +        */
> > +       KUNIT_EXPECT_EQ(test, KASAN_GRANULE_SIZE - 2,
> > +                       strscpy(ptr, src + 1, size));
> > +
> > +       /* Undo operations above. */
> > +       src[KASAN_GRANULE_SIZE - 1] = '0';
> > +       kasan_poison(src2, KASAN_GRANULE_SIZE, tag, false);
> > +
> > +       kfree(src);
>
> I have trouble understanding what this code is doing...
>
> So the goal is to call strcpy with such an address, that the first 8
> bytes (partially) cover 2 granules, one accessible and the other is
> not?

The first 16 bytes, but yes.

> If so, can we not do something like:
>
> src = kmalloc(KASAN_GRANULE_SIZE, GFP_KERNEL | __GFP_ZERO);
> strscpy(src, "aabbcceeddeeffg\0", size);
> strscpy(ptr, src + KASAN_GRANULE_SIZE - 2, sizeof(unsigned long));

Yes, something like that should work as well. Let me send a v3.

Peter

> Otherwise, this code needs more explanatory comments and it's probably
> better to move it out to a helper function.
>
> >         kfree(ptr);
> >
> >         /*
> > --
> > 2.49.0.395.g12beb8f557-goog
> >


From lkp at intel.com  Thu Mar 20 19:41:40 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 10:41:40 +0800
Subject: [soc:soc/drivers 22/24]
 drivers/platform/cznic/turris-signing-key.c:25:55: warning: omitting the
 parameter name in a function definition is a C2x extension
Message-ID: <202503211042.Uf5Ln7hI-lkp@intel.com>

Hi Marek,

First bad commit (maybe != root cause):

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
head:   ba8755ab541fc629948233125db870d4dbf00a75
commit: df94a2f1eb455b57dd01f9b64419e3163d44df7f [22/24] platform: cznic: turris-omnia-mcu: Add support for digital message signing with HW private key
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20250321/202503211042.Uf5Ln7hI-lkp at intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250321/202503211042.Uf5Ln7hI-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503211042.Uf5Ln7hI-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/platform/cznic/turris-signing-key.c:25:55: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
      25 | static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
         |                                                       ^
   drivers/platform/cznic/turris-signing-key.c:25:87: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
      25 | static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
         |                                                                                       ^
   2 warnings generated.


vim +25 drivers/platform/cznic/turris-signing-key.c

0b28b7080ef5a3 Marek Beh?n 2025-02-04  24  
0b28b7080ef5a3 Marek Beh?n 2025-02-04 @25  static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
0b28b7080ef5a3 Marek Beh?n 2025-02-04  26  {
0b28b7080ef5a3 Marek Beh?n 2025-02-04  27  	return 0;
0b28b7080ef5a3 Marek Beh?n 2025-02-04  28  }
0b28b7080ef5a3 Marek Beh?n 2025-02-04  29  

:::::: The code at line 25 was first introduced by commit
:::::: 0b28b7080ef5a323c3afa3860c3d45d627629830 platform: cznic: Add keyctl helpers for Turris platform

:::::: TO: Marek Beh?n <kabel at kernel.org>
:::::: CC: Arnd Bergmann <arnd at arndb.de>

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From quic_nguyenb at quicinc.com  Thu Mar 20 20:18:24 2025
From: quic_nguyenb at quicinc.com (Bao D. Nguyen)
Date: Thu, 20 Mar 2025 20:18:24 -0700
Subject: [PATCH v4 1/1] scsi: ufs: core: add device level exception support
Message-ID: <4370b3a3b5a5675bb3e75aaa48a273674c159339.1742526978.git.quic_nguyenb@quicinc.com>

The ufs device JEDEC specification version 4.1 adds support for the
device level exception events. To support this new device level
exception feature, expose two new sysfs nodes below to provide
the user space access to the device level exception information.
/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id

The device_lvl_exception_count sysfs node reports the number of
device level exceptions that have occurred since the last time
this variable is reset. Writing a value of 0 will reset it.
The device_lvl_exception_id reports the exception ID which is the
qDeviceLevelExceptionID attribute of the device JEDEC specifications
version 4.1 and later. The user space application can query these
sysfs nodes to get more information about the device level exception.

Signed-off-by: Bao D. Nguyen <quic_nguyenb at quicinc.com>
Reviewed-by: Peter Wang <peter.wang at mediatek.com>
---
Changes in v4:
1. Changed the hba->dev_lvl_exception_count to atomic_t type. Removed
the spinlock() around hba->dev_lvl_exception_count accesses
(Peter's and Bart's comments).

Changes in v3:
1. Add protection for hba->dev_lvl_exception_count accesses in different
contexts (Bart's comment).

Changes in v2:
1. Addressed Mani's comments:
   - Update the documentation of dev_lvl_exception_count to read/write.
   - Rephrase the description of the Documentation and commit text.
   - Remove the export of ufshcd_read_device_lvl_exception_id().
2. Addressed Bart's comments:
   - Rename dev_lvl_exception sysfs node to dev_lvl_exception_count.
   - Update the documentation of the sysfs nodes.
   - Skip comment about sysfs_notify() being used in interrupt
     context because Avri already addressed it.
---
 Documentation/ABI/testing/sysfs-driver-ufs | 27 ++++++++++++++
 drivers/ufs/core/ufs-sysfs.c               | 54 +++++++++++++++++++++++++++
 drivers/ufs/core/ufshcd-priv.h             |  1 +
 drivers/ufs/core/ufshcd.c                  | 60 ++++++++++++++++++++++++++++++
 include/uapi/scsi/scsi_bsg_ufs.h           |  9 +++++
 include/ufs/ufs.h                          |  5 ++-
 include/ufs/ufshcd.h                       |  5 +++
 7 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index ae01912..6a6c35a 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -1604,3 +1604,30 @@ Description:
 		prevent the UFS from frequently performing clock gating/ungating.
 
 		The attribute is read/write.
+
+What:		/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
+What:		/sys/bus/platform/devices/*.ufs/device_lvl_exception_count
+Date:		March 2025
+Contact:	Bao D. Nguyen <quic_nguyenb at quicinc.com>
+Description:
+		This attribute is applicable to ufs devices compliant to the JEDEC
+		specifications version 4.1 or later. The device_lvl_exception_count
+		is a counter indicating the number of times the device level exceptions
+		have occurred since the last time this variable is reset.
+		Writing a 0 value to this attribute will reset the device_lvl_exception_count.
+		If the device_lvl_exception_count reads a positive value, the user
+		application should read the device_lvl_exception_id attribute to know more
+		information about the exception.
+		This attribute is read/write.
+
+What:		/sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id
+What:		/sys/bus/platform/devices/*.ufs/device_lvl_exception_id
+Date:		March 2025
+Contact:	Bao D. Nguyen <quic_nguyenb at quicinc.com>
+Description:
+		Reading the device_lvl_exception_id returns the qDeviceLevelExceptionID
+		attribute of the ufs device JEDEC specification version 4.1. The definition
+		of the qDeviceLevelExceptionID is the ufs device vendor specific implementation.
+		Refer to the device manufacturer datasheet for more information
+		on the meaning of the qDeviceLevelExceptionID attribute value.
+		The attribute is read only.
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 90b5ab6..634cf16 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -466,6 +466,56 @@ static ssize_t critical_health_show(struct device *dev,
 	return sysfs_emit(buf, "%d\n", hba->critical_health_count);
 }
 
+static ssize_t device_lvl_exception_count_show(struct device *dev,
+					       struct device_attribute *attr,
+					       char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return -EOPNOTSUPP;
+
+	return sysfs_emit(buf, "%u\n", atomic_read(&hba->dev_lvl_exception_count));
+}
+
+static ssize_t device_lvl_exception_count_store(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	unsigned int value;
+
+	if (kstrtouint(buf, 0, &value))
+		return -EINVAL;
+
+	/* the only supported usecase is to reset the dev_lvl_exception_count */
+	if (value)
+		return -EINVAL;
+
+	atomic_set(&hba->dev_lvl_exception_count, 0);
+
+	return count;
+}
+
+static ssize_t device_lvl_exception_id_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	u64 exception_id;
+	int err;
+
+	ufshcd_rpm_get_sync(hba);
+	err = ufshcd_read_device_lvl_exception_id(hba, &exception_id);
+	ufshcd_rpm_put_sync(hba);
+
+	if (err)
+		return err;
+
+	hba->dev_lvl_exception_id = exception_id;
+	return sysfs_emit(buf, "%llu\n", exception_id);
+}
+
 static DEVICE_ATTR_RW(rpm_lvl);
 static DEVICE_ATTR_RO(rpm_target_dev_state);
 static DEVICE_ATTR_RO(rpm_target_link_state);
@@ -479,6 +529,8 @@ static DEVICE_ATTR_RW(wb_flush_threshold);
 static DEVICE_ATTR_RW(rtc_update_ms);
 static DEVICE_ATTR_RW(pm_qos_enable);
 static DEVICE_ATTR_RO(critical_health);
+static DEVICE_ATTR_RW(device_lvl_exception_count);
+static DEVICE_ATTR_RO(device_lvl_exception_id);
 
 static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
 	&dev_attr_rpm_lvl.attr,
@@ -494,6 +546,8 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
 	&dev_attr_rtc_update_ms.attr,
 	&dev_attr_pm_qos_enable.attr,
 	&dev_attr_critical_health.attr,
+	&dev_attr_device_lvl_exception_count.attr,
+	&dev_attr_device_lvl_exception_id.attr,
 	NULL
 };
 
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 10b4a19..d0a2c96 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -94,6 +94,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 			     enum query_opcode desc_op);
 
 int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
+int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id);
 
 /* Wrapper functions for safely calling variant operations */
 static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 4e1e214..86ef716 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -6013,6 +6013,43 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
 				__func__, err);
 }
 
+int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id)
+{
+	struct utp_upiu_query_response_v4_0 *upiu_resp;
+	struct ufs_query_req *request = NULL;
+	struct ufs_query_res *response = NULL;
+	int err;
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return -EOPNOTSUPP;
+
+	ufshcd_hold(hba);
+	mutex_lock(&hba->dev_cmd.lock);
+
+	ufshcd_init_query(hba, &request, &response,
+			  UPIU_QUERY_OPCODE_READ_ATTR,
+			  QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID, 0, 0);
+
+	request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
+
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+	if (err) {
+		dev_err(hba->dev, "%s: failed to read device level exception %d\n",
+			__func__, err);
+		goto out;
+	}
+
+	upiu_resp = (struct utp_upiu_query_response_v4_0 *)response;
+	*exception_id = get_unaligned_be64(&upiu_resp->value);
+
+out:
+	mutex_unlock(&hba->dev_cmd.lock);
+	ufshcd_release(hba);
+
+	return err;
+}
+
 static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn)
 {
 	u8 index;
@@ -6240,6 +6277,11 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
 		sysfs_notify(&hba->dev->kobj, NULL, "critical_health");
 	}
 
+	if (status & hba->ee_drv_mask & MASK_EE_DEV_LVL_EXCEPTION) {
+		atomic_inc(&hba->dev_lvl_exception_count);
+		sysfs_notify(&hba->dev->kobj, NULL, "device_lvl_exception_count");
+	}
+
 	ufs_debugfs_exception_event(hba, status);
 }
 
@@ -8139,6 +8181,22 @@ static void ufshcd_temp_notif_probe(struct ufs_hba *hba, const u8 *desc_buf)
 	}
 }
 
+static void ufshcd_device_lvl_exception_probe(struct ufs_hba *hba, u8 *desc_buf)
+{
+	u32 ext_ufs_feature;
+
+	if (hba->dev_info.wspecversion < 0x410)
+		return;
+
+	ext_ufs_feature = get_unaligned_be32(desc_buf +
+				DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+	if (!(ext_ufs_feature & UFS_DEV_LVL_EXCEPTION_SUP))
+		return;
+
+	atomic_set(&hba->dev_lvl_exception_count, 0);
+	ufshcd_enable_ee(hba, MASK_EE_DEV_LVL_EXCEPTION);
+}
+
 static void ufshcd_set_rtt(struct ufs_hba *hba)
 {
 	struct ufs_dev_info *dev_info = &hba->dev_info;
@@ -8339,6 +8397,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
 
 	ufs_init_rtc(hba, desc_buf);
 
+	ufshcd_device_lvl_exception_probe(hba, desc_buf);
+
 	/*
 	 * ufshcd_read_string_desc returns size of the string
 	 * reset the error value
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 8c29e49..8b61dff 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -143,6 +143,15 @@ struct utp_upiu_query_v4_0 {
 	__be32 reserved;
 };
 
+struct utp_upiu_query_response_v4_0 {
+	__u8 opcode;
+	__u8 idn;
+	__u8 index;
+	__u8 selector;
+	__be64 value;
+	__be32 reserved;
+} __attribute__((__packed__));
+
 /**
  * struct utp_upiu_cmd - Command UPIU structure
  * @exp_data_transfer_len: Data Transfer Length DW-3
diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h
index 8a24ed5..1c47136 100644
--- a/include/ufs/ufs.h
+++ b/include/ufs/ufs.h
@@ -180,7 +180,8 @@ enum attr_idn {
 	QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE       = 0x1D,
 	QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST    = 0x1E,
 	QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE        = 0x1F,
-	QUERY_ATTR_IDN_TIMESTAMP		= 0x30
+	QUERY_ATTR_IDN_TIMESTAMP		= 0x30,
+	QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID     = 0x34,
 };
 
 /* Descriptor idn for Query requests */
@@ -390,6 +391,7 @@ enum {
 	UFS_DEV_EXT_TEMP_NOTIF		= BIT(6),
 	UFS_DEV_HPB_SUPPORT		= BIT(7),
 	UFS_DEV_WRITE_BOOSTER_SUP	= BIT(8),
+	UFS_DEV_LVL_EXCEPTION_SUP       = BIT(12),
 };
 #define UFS_DEV_HPB_SUPPORT_VERSION		0x310
 
@@ -419,6 +421,7 @@ enum {
 	MASK_EE_TOO_LOW_TEMP		= BIT(4),
 	MASK_EE_WRITEBOOSTER_EVENT	= BIT(5),
 	MASK_EE_PERFORMANCE_THROTTLING	= BIT(6),
+	MASK_EE_DEV_LVL_EXCEPTION       = BIT(7),
 	MASK_EE_HEALTH_CRITICAL		= BIT(9),
 };
 #define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index e3909cc..5888463 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -968,6 +968,9 @@ enum ufshcd_mcq_opr {
  * @pm_qos_req: PM QoS request handle
  * @pm_qos_enabled: flag to check if pm qos is enabled
  * @critical_health_count: count of critical health exceptions
+ * @dev_lvl_exception_count: count of device level exceptions since last reset
+ * @dev_lvl_exception_id: vendor specific information about the
+ * device level exception event.
  */
 struct ufs_hba {
 	void __iomem *mmio_base;
@@ -1138,6 +1141,8 @@ struct ufs_hba {
 	bool pm_qos_enabled;
 
 	int critical_health_count;
+	atomic_t dev_lvl_exception_count;
+	u64 dev_lvl_exception_id;
 };
 
 /**
-- 
2.7.4



From quic_songchai at quicinc.com  Thu Mar 20 20:26:18 2025
From: quic_songchai at quicinc.com (songchai)
Date: Fri, 21 Mar 2025 11:26:18 +0800
Subject: [PATCH v3 0/7] Provides support for Trigger Generation Unit
In-Reply-To: <CAJ9a7ViFu6tP7wac-6NPOBOCHw2iA+gs6D=D4um-T07Syu-8CA@mail.gmail.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com>
 <CAJ9a7ViFu6tP7wac-6NPOBOCHw2iA+gs6D=D4um-T07Syu-8CA@mail.gmail.com>
Message-ID: <28001d0d-38cc-4507-91c5-1791c74d11ee@quicinc.com>


On 3/7/2025 12:57 AM, Mike Leach wrote:
> Hi,
>
> On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
>> Provide support for the TGU (Trigger Generation Unit), which can be
>> utilized to sense a plurality of signals and create a trigger into
>> the CTI or generate interrupts to processors once the input signal
>> meets the conditions. We can treat the TGU?s workflow as a flowsheet,
>> it has some ?steps? regions for customization. In each step region,
>> we can set the signals that we want with priority in priority_group, set
>> the conditions in each step via condition_decode, and set the resultant
>> action by condition_select. Meanwhile, some TGUs (not all) also provide
>> timer/counter functionality. Based on the characteristics described
>> above, we consider the TGU as a helper in the CoreSight subsystem.
>> Its master device is the TPDM, which can transmit signals from other
>> subsystems, and we reuse the existing ports mechanism to link the TPDM to
>> the connected TGU.
>>
> I do not believe that his component is part of the Coresight subsystem.
>
> 1) It inputs multiple signals from the SoC to process and create an
> trigger event - however, it can do this irrespective of CoreSight
> trace being operational, especially where generating interrupts for
> processors, or triggers for other non-coresight components. It would
> appear that the TPDM can send output to more than just the TDPA which
> generates coresight trace packets - a previously undisclosed feature.

TGU is a part the QPMDA(Qualcomm?Performance Monitoring and

Diagnostics Architecture ) library, and the signals it perceives are 
from TPDM and connected

through hardware. So it? depends on the coresight-tpdm, and will not 
work if the coresight

tpdm is not operational.

>
> 2) The ports mechanism is a generic device tree mechanism, not
> something unique to the Coresight subsystem.

Sure, Mike. As i mentioned above, the signals reach the TGU through 
hardware.So the port

mechanism here is not for the data transmission, but to confirm the 
relationship of the TGU

as a TPDM helper.

>
> 3) The CTI trigger connection will be defined in devicetree under the
> CTI component, as this is the interface between this component and
> coresight.

The TGU is utilized to sense a plurality of signals and create a trigger 
into the CTI.

It should be a trigger in for the targeting CTI. Could we configure the 
targeting CTI's trigger_in

and trigger_out instead of configuring in the devicetree?

>
> As such this seems more like a general performance and debug
> component, with optional inputs to the coresight trigger mechanisms,
> rather than being a coresight component itself. Other SoCs have
> non-coresight component inputs to CTIs. For example the PL011 serial
> device on Juno has a signal into one of the system CTIs.

In addition to above, the TGU also have the coresight management 
registers in its register region

which is a character of coresight component.

Based on these clarification, could we consider it as a coresight 
component?
>
>> Here is a detailed example to explain how to use the TGU:
>>
>> In this example, the TGU is configured to use 2 conditions, 2 steps, and
>> the timer. The goal is to look for one of two patterns which are generated
>> from TPDM, giving priority to one, and then generate a trigger once the
>> timer reaches a certain value. In other words, two conditions are used
>> for the first step to look for the two patterns, where the one with the
>> highest priority is used in the first condition. Then, in the second step,
>> the timer is enabled and set to be compared to the given value at each
>> clock cycle. These steps are better shown below.
>>
>>
>>              |-----------------|
>>              |                 |
>>              |       TPDM      |
>>              |                 |
>>              |-----------------|
>>                       |
>>                       |
>>    --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ------
>>    |                  |                                                 |
>>    |                  |                          |--------------------| |
>>    |    |---- --->    |                          |  Go to next steps  | |
>>    |    |             |                |--- ---> |  Enable timer      | |
>>    |    |             v                |         |                    | |
>>    |    |    |-----------------|       |         |--------------------| |
>>    |    |    |                 |  Yes  |                    |           |
>>    |    |    |   inputs==0xB   | ----->|                    | <-------- |
>>    |    |    |                 |       |                    |      No | |
>>    | No |    |-----------------|       |                    v         | |
>>    |    |             |                |          |-----------------| | |
>>    |    |             |                |          |                 | | |
>>    |    |             |                |          |      timer>=3   |-- |
>>    |    |             v                |          |                 |   |
>>    |    |    |-----------------|       |          |-----------------|   |
>>    |    |    |                 |  Yes  |                    |           |
>>    |    |--- |   inputs==0xA   | ----->|                    | Yes       |
>>    |         |                 |                            |           |
>>    |         |-----------------|                            v           |
>>    |                                              |-----------------|   |
>>    |                                              |                 |   |
>>    |                                              |      Trigger    |   |
>>    |                                              |                 |   |
>>    |                                              |-----------------|   |
>>    |  TGU                                                   |           |
>>    |--- --- --- --- --- --- --- --- --- --- --- --- --- --- |--- --- -- |
>>                                                             |
>>                                                             v
>>                                                    |-----------------|
>>                                                    |The controllers  |
>>                                                    |which will use   |
>>                                                    |triggers further |
>>                                                    |-----------------|
>>
>> steps:
>>         1. Reset TGU /*it will disable tgu and reset dataset*/
>>         - echo 1 > /sys/bus/coresight/devices/<tgu-name>/reset_tgu
>>
>>         2. Set the pattern match for priority0 to 0xA = 0b1010 and for
>>            priority 1 to 0xB = 0b1011.
>>         - echo 0x11113232 > /sys/bus/coresight/devices/<tgu-name>/step0_priority0/reg0
>>         - echo 0x11113233 > /sys/bus/coresight/devices/<tgu-name>/step0_priority1/reg0
>>
>>         Note:
>>              Bit distribution diagram for each priority register
>>      |-------------------------------------------------------------------|
>>      |   Bits          |       Field Nam   |    Description              |
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |     29:28       |   SEL_BIT7_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |     25:24       |   SEL_BIT6_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |     21:20       |   SEL_BIT5_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |     17:16       |   SEL_BIT4_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |     13:12       |   SEL_BIT3_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |      9:8        |   SEL_BIT2_TYPE2  | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |      5:4        |  SEL_BIT1_TYPE2   | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>      |                 |                   | 00 = bypass for OR output   |
>>      |      1:0        |  SEL_BIT0_TYPE2   | 01 = bypass for AND output  |
>>      |                 |                   | 10 = sense input '0' is true|
>>      |                 |                   | 11 = sense input '1' is true|
>>      |-------------------------------------------------------------------|
>>          These bits are used to identify the signals we want to sense, with
>>          a maximum signal number of 140. For example, to sense the signal
>>          0xA (binary 1010), we set the value of bits 0 to 13 to 3232, which
>>          represents 1010. The remaining bits are set to 1, as we want to use
>>          AND gate to summarize all the signals we want to sense here. For
>>          rising or falling edge detection of any input to the priority, set
>>          the remaining bits to 0 to use an OR gate.
>>
>>         3. look for the pattern for priority_i i=0,1.
>>         - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg0
>>         - echo 0x30 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg1
>>
>>      |-------------------------------------------------------------------------------|
>>      |   Bits          |    Field Nam        |            Description                |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |For each decoded condition, this       |
>>      |      24         |       NOT           |inverts the output. If the condition   |
>>      |                 |                     |decodes to true, and the NOT field     |
>>      |                 |                     |is '1', then the output is NOT true.   |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from the associated|
>>      |      21         |  BC0_COMP_ACTIVE    |comparator will be actively included in|
>>      |                 |                     |the decoding of this particular        |
>>      |                 |                     |condition.                             |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from the associated|
>>      |                 |                     |comparator will need to be 1 to affect |
>>      |      20         |   BC0_COMP_HIGH     |the decoding of this condition.        |
>>      |                 |                     |Conversely, a '0' here requires a '0'  |
>>      |                 |                     |from the comparator                    |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from the associated|
>>      |      17         |                     |comparator will be actively included in|
>>      |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
>>      |                 |                     |condition.                             |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from the associated|
>>      |                 |                     |comparator will need to be 1 to affect |
>>      |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
>>      |                 |                     |condition.Conversely, a 0 here         |
>>      |                 |                     |requires a '0' from the comparator     |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from Priority_n    |
>>      |                 |                     |OR logic will be actively              |
>>      |     4n+3        | Priority_n_OR_ACTIVE|included in the decoding of            |
>>      |                 |    (n=0,1,2,3)      |this particular condition.             |
>>      |                 |                     |                                       |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from Priority_n    |
>>      |                 |                     |will need to be '1' to affect the      |
>>      |     4n+2        |  Priority_n_OR_HIGH |decoding of this particular            |
>>      |                 |    (n=0,1,2,3)      |condition. Conversely, a '0' here      |
>>      |                 |                     |requires a '0' from Priority_n OR logic|
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from Priority_n    |
>>      |                 |                     |AND logic will be actively             |
>>      |     4n+1        |Priority_n_AND_ACTIVE|included in the decoding of this       |
>>      |                 |  (n=0,1,2,3)        |particular condition.                  |
>>      |                 |                     |                                       |
>>      |-------------------------------------------------------------------------------|
>>      |                 |                     |When '1' the output from Priority_n    |
>>      |                 |                     |AND logic will need to be '1' to       |
>>      |      4n         | Priority_n_AND_HIGH |affect the decoding of this            |
>>      |                 |   (n=0,1,2,3)       |particular condition. Conversely,      |
>>      |                 |                     |a '0' here requires a '0' from         |
>>      |                 |                     |Priority_n AND logic.                  |
>>      |-------------------------------------------------------------------------------|
>>          Since we use `priority_0` and `priority_1` with an AND output in step 2, we set `0x3`
>>          and `0x30` here to activate them.
>>
>>         4. Set NEXT_STEP = 1 and TC0_ENABLE = 1 so that when the conditions
>>            are met then the next step will be step 1 and the timer will be enabled.
>>         - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg0
>>         - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg1
>>
>>          |-----------------------------------------------------------------------------|
>>          |   Bits          |       Field Nam   |            Description                |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This field defines the next step the   |
>>          |    18:17        |     NEXT_STEP     |TGU will 'goto' for the associated     |
>>          |                 |                   |Condition and Step.                    |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |For each possible output trigger       |
>>          |    13           |     TRIGGER       |available, set a '1' if you want       |
>>          |                 |                   |the trigger to go active for the       |
>>          |                 |                   |associated condition and Step.         |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will cause BC0 to increment if the|
>>          |    9            |     BC0_INC       |associated Condition is decoded for    |
>>          |                 |                   |this step.                             |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will cause BC0 to decrement if the|
>>          |    8            |     BC0_DEC       |associated Condition is decoded for    |
>>          |                 |                   |this step.                             |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will clear BC0 count value to 0 if|
>>          |    7            |     BC0_CLEAR     |the associated Condition is decoded    |
>>          |                 |                   |for this step.                         |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will cause TC0 to increment until |
>>          |    3            |     TC0_ENABLE    |paused or cleared if the associated    |
>>          |                 |                   |Condition is decoded for this step.    |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will cause TC0 to pause until     |
>>          |    2            |     TC0_PAUSE     |enabled if the associated Condition    |
>>          |                 |                   |is decoded for this step.              |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will clear TC0 count value to 0   |
>>          |    1            |     TC0_CLEAR     |if the associated Condition is         |
>>          |                 |                   |decoded for this step.                 |
>>          |-----------------------------------------------------------------------------|
>>          |                 |                   |This will set the done signal to the   |
>>          |    0            |     DONE          |TGU FSM if the associated Condition    |
>>          |                 |                   |is decoded for this step.              |
>>          |-----------------------------------------------------------------------------|
>>          Based on the distribution diagram, we set `0x20008` for `priority0` and `priority1` to
>>          achieve "jump to step 1 and enable TC0" once the signal is sensed.
>>
>>         5. activate the timer comparison for this step.
>>         -  echo 0x30000  > /sys/bus/coresight/devices/<tgu-name>/step1_condition_decode/reg0
>>
>>          |-------------------------------------------------------------------------------|
>>          |                 |                     |When '1' the output from the associated|
>>          |      17         |                     |comparator will be actively included in|
>>          |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
>>          |                 |                     |condition.                             |
>>          |-------------------------------------------------------------------------------|
>>          |                 |                     |When '1' the output from the associated|
>>          |                 |                     |comparator will need to be 1 to affect |
>>          |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
>>          |                 |                     |condition.Conversely, a 0 here         |
>>          |                 |                     |requires a '0' from the comparator     |
>>          |-------------------------------------------------------------------------------|
>>          Accroding to the decode distribution diagram , we give 0x30000 here to set 16th&17th bit
>>          to enable timer comparison.
>>
>>         6. Set the NEXT_STEP = 0 and TC0_PAUSE = 1 and TC0_CLEAR = 1 once the timer
>>            has reached the given value.
>>         - echo 0x6 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/reg0
>>
>>         7. Enable Trigger 0 for TGU when the condition 0 is met in step1,
>>            i.e. when the timer reaches 3.
>>         - echo 0x2000 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/default
>>
>>          Note:
>>              1. 'default' register allows for establishing the resultant action for
>>              the default condition
>>
>>              2. Trigger:For each possible output trigger available from
>>              the Design document, there are three triggers: interrupts, CTI,
>>              and Cross-TGU mapping.All three triggers can occur, but
>>              the choice of which trigger to use depends on the user's
>>              needs.
>>
>>         8. Compare the timer to 3 in step 1.
>>         - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step1_timer/reg0
>>
>>         9. enale tgu
>>         - echo 1 > /sys/bus/coresight/devices/<tgu-name>/enable_tgu
>>
> If this is version 3 - where is the list of differences from versions 1 - 2?
My bad. Will add the previous change log in the next version.
>
>> Songwei Chai (7):
>>    dt-bindings: arm: Add support for Coresight TGU trace
>>    coresight: Add coresight TGU driver
>>    coresight-tgu: Add signal priority support
>>    coresight-tgu: Add TGU decode support
>>    coresight-tgu: add support to configure next action
>>    coresight-tgu: add timer/counter functionality for TGU
>>    coresight-tgu: add reset node to initialize
>>
>>   .../testing/sysfs-bus-coresight-devices-tgu   |  51 ++
>>   .../bindings/arm/qcom,coresight-tgu.yaml      | 135 ++++
>>   drivers/hwtracing/coresight/Kconfig           |  11 +
>>   drivers/hwtracing/coresight/Makefile          |   1 +
>>   drivers/hwtracing/coresight/coresight-tgu.c   | 669 ++++++++++++++++++
>>   drivers/hwtracing/coresight/coresight-tgu.h   | 242 +++++++
>>   6 files changed, 1109 insertions(+)
>>   create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
>>   create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
>>   create mode 100644 drivers/hwtracing/coresight/coresight-tgu.c
>>   create mode 100644 drivers/hwtracing/coresight/coresight-tgu.h
>>
> Regards
>
>
> Mike
>
> --
> Mike Leach
> Principal Engineer, ARM Ltd.
> Manchester Design Centre. UK


From dsimic at manjaro.org  Thu Mar 20 20:28:49 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Fri, 21 Mar 2025 04:28:49 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from RK3588J SoC dtsi
Message-ID: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>

The differences in the vendor-approved CPU and GPU OPPs for the standard
Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J variant [2]
come from the latter, presumably, supporting an extended temperature range
that's usually associated with industrial applications, despite the two SoC
variant datasheets specifying the same upper limit for the allowed ambient
temperature for both variants.  However, the lower temperature limit is
specified much lower for the RK3588J variant. [1][2]

To be on the safe side and to ensure maximum longevity of the RK3588J SoCs,
only the CPU and GPU OPPs that are declared by the vendor to be always safe
for this SoC variant may be provided.  As explained by the vendor [3] and
according to its datasheet, [2] the RK3588J variant can actually run safely
at higher CPU and GPU OPPs as well, but only when not enjoying the assumed
extended temperature range that the RK3588J, as an SoC variant targeted
specifically at industrial applications, is made (or binned) for.

Thus, only the CPU and GPU OPPs that are specified by the vendor to be safe
throughout the entire RK3588J's extended temperature range may be provided,
while anyone who actually can ensure that their RK3588J-based board is
never going to run within the extended temperature range, may probably
safely apply a DT overlay that adds the higher CPU and GPU OPPs.  As we
obviously can't know what will be the runtime temperature conditions for
a particular board, we may provide only the always-safe OPPs.

With all this and the downstream RK3588(J) DT definitions [4][5] in mind,
let's delete the RK3588J CPU and GPU OPPs that are not considered belonging
to the normal operation mode for this SoC variant.  To quote the RK3588J
datasheet [2], "normal mode means the chipset works under safety voltage
and frequency;  for the industrial environment, highly recommend to keep in
normal mode, the lifetime is reasonably guaranteed", while "overdrive mode
brings higher frequency, and the voltage will increase accordingly;  under
the overdrive mode for a long time, the chipset may shorten the lifetime,
especially in high temperature condition".

To sum up the RK3588J datasheet [2] and the vendor-provided DTs, [4][5]
the maximum allowed CPU core and GPU frequencies are as follows:

   IP core    | Normal mode | Overdrive mode
  ------------+-------------+----------------
   Cortex-A55 |   1,296 MHz |      1,704 MHz
   Cortex-A76 |   1,608 MHz |      2,016 MHz
   GPU        |     700 MHz |        850 MHz

Unfortunately, when it comes to the actual voltages for the RK3588J CPU and
GPU OPPs, there's a discrepancy between the RK3588J datasheet [2] and the
downstream kernel code. [4][5]  The RK3588J datasheet states that "the max.
working voltage of CPU/GPU/NPU is 0.75 V under the normal mode", while the
downstream kernel code actually allows voltage ranges that go up to 0.95 V,
which is still within the voltage range allowed by the datasheet.  However,
the RK3588J datasheet also tells us to "strictly refer to the software
configuration of SDK and the hardware reference design", so let's embrace
the voltage ranges provided by the downstream kernel code, which also
prevents the undesirable theoretical outcome of ending up with no usable
OPPs on a particular board, as a result of the board's voltage regulator(s)
being unable to deliver the exact voltages, for whatever reason.

The above-described voltage ranges for the RK3588J CPU OPPs remain taken
from the downstream kernel code [4][5] by picking the highest, worst-bin
values, which ensure that all RK3588J bins will work reliably.  Yes, with
some power inevitably wasted as unnecessarily generated heat, but the
reliability is paramount, together with the longevity.  This deficiency
may be revisited separately at some point in the future.

The provided RK3588J CPU OPPs follow the slightly debatable "provide only
the highest-frequency OPP from the same-voltage group" approach that's been
established earlier, [6] as a result of the "same-voltage, lower-frequency"
OPPs being considered inefficient from the IPA governor's standpoint, which
may also be revisited separately at some point in the future.

[1] https://wiki.friendlyelec.com/wiki/images/e/ee/Rockchip_RK3588_Datasheet_V1.6-20231016.pdf
[2] https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2403201054_Rockchip-RK3588J_C22364189.pdf
[3] https://lore.kernel.org/linux-rockchip/e55125ed-64fb-455e-b1e4-cebe2cf006e4 at cherry.de/T/#u
[4] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
[5] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
[6] https://lore.kernel.org/all/20240229-rk-dts-additions-v3-5-6afe8473a631 at gmail.com/

Fixes: 667885a68658 ("arm64: dts: rockchip: Add OPP data for CPU cores on RK3588j")
Fixes: a7b2070505a2 ("arm64: dts: rockchip: Split GPU OPPs of RK3588 and RK3588j")
Cc: stable at vger.kernel.org
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: Alexey Charkov <alchark at gmail.com>
Helped-by: Quentin Schulz <quentin.schulz at cherry.de>
Signed-off-by: Dragan Simic <dsimic at manjaro.org>
---
 arch/arm64/boot/dts/rockchip/rk3588j.dtsi | 53 ++++++++---------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
index bce72bac4503..3045cb3bd68c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
@@ -11,74 +11,59 @@ cluster0_opp_table: opp-table-cluster0 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-1416000000 {
-			opp-hz = /bits/ 64 <1416000000>;
+		opp-1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <750000 750000 950000>;
 			clock-latency-ns = <40000>;
 			opp-suspend;
 		};
-		opp-1608000000 {
-			opp-hz = /bits/ 64 <1608000000>;
-			opp-microvolt = <887500 887500 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-1704000000 {
-			opp-hz = /bits/ 64 <1704000000>;
-			opp-microvolt = <937500 937500 950000>;
+		opp-1296000000 {
+			opp-hz = /bits/ 64 <1296000000>;
+			opp-microvolt = <775000 775000 950000>;
 			clock-latency-ns = <40000>;
 		};
 	};
 
 	cluster1_opp_table: opp-table-cluster1 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
+		opp-1200000000{
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <750000 750000 950000>;
+			clock-latency-ns = <40000>;
+		};
 		opp-1416000000 {
 			opp-hz = /bits/ 64 <1416000000>;
-			opp-microvolt = <750000 750000 950000>;
+			opp-microvolt = <762500 762500 950000>;
 			clock-latency-ns = <40000>;
 		};
 		opp-1608000000 {
 			opp-hz = /bits/ 64 <1608000000>;
 			opp-microvolt = <787500 787500 950000>;
 			clock-latency-ns = <40000>;
 		};
-		opp-1800000000 {
-			opp-hz = /bits/ 64 <1800000000>;
-			opp-microvolt = <875000 875000 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-2016000000 {
-			opp-hz = /bits/ 64 <2016000000>;
-			opp-microvolt = <950000 950000 950000>;
-			clock-latency-ns = <40000>;
-		};
 	};
 
 	cluster2_opp_table: opp-table-cluster2 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
+		opp-1200000000{
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <750000 750000 950000>;
+			clock-latency-ns = <40000>;
+		};
 		opp-1416000000 {
 			opp-hz = /bits/ 64 <1416000000>;
-			opp-microvolt = <750000 750000 950000>;
+			opp-microvolt = <762500 762500 950000>;
 			clock-latency-ns = <40000>;
 		};
 		opp-1608000000 {
 			opp-hz = /bits/ 64 <1608000000>;
 			opp-microvolt = <787500 787500 950000>;
 			clock-latency-ns = <40000>;
 		};
-		opp-1800000000 {
-			opp-hz = /bits/ 64 <1800000000>;
-			opp-microvolt = <875000 875000 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-2016000000 {
-			opp-hz = /bits/ 64 <2016000000>;
-			opp-microvolt = <950000 950000 950000>;
-			clock-latency-ns = <40000>;
-		};
 	};
 
 	gpu_opp_table: opp-table {
@@ -104,10 +89,6 @@ opp-700000000 {
 			opp-hz = /bits/ 64 <700000000>;
 			opp-microvolt = <750000 750000 850000>;
 		};
-		opp-850000000 {
-			opp-hz = /bits/ 64 <800000000>;
-			opp-microvolt = <787500 787500 850000>;
-		};
 	};
 };
 


From dsimic at manjaro.org  Thu Mar 20 20:37:16 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Fri, 21 Mar 2025 04:37:16 +0100
Subject: [PATCH v5 7/8] arm64: dts: rockchip: Add OPP data for CPU cores
 on RK3588j
In-Reply-To: <80c7d9fcdd270df2c61fbd61eec44d70@manjaro.org>
References: <20240617-rk-dts-additions-v5-0-c1f5f3267f1e@gmail.com>
 <a56b59a21dc3c21192fe45197eee4865@manjaro.org>
 <2cf3889741f84584d8f23a4407fed08e@manjaro.org> <3271211.5fSG56mABF@phil>
 <80c7d9fcdd270df2c61fbd61eec44d70@manjaro.org>
Message-ID: <4432e7f5dd9cb75584fb36e1f52497aa@manjaro.org>

Hello all,

On 2025-03-13 20:43, Dragan Simic wrote:
> On 2025-03-13 20:00, Heiko Stuebner wrote:
>> Am Donnerstag, 13. M?rz 2025, 11:42:17 MEZ schrieb Dragan Simic:
>>> On 2025-03-12 11:34, Dragan Simic wrote:
>>> Just as a note, everything above (and even a bit more) is confirmed
>>> and clearly described in the publicly available RK3588J datasheet,
>>> which I'll provide as a reference in my upcoming patch.
>> 
>> so just to reiterate my stance, in mainline I really only want 
>> frequencies
>> that are not possibly influencing the lifetime of the chip.
>> 
>> It doesn't even matter about the variant we're talking about being
>> industrial :-) . When someone is using mainline I want them to be
>> reasonable assured that we don't have stuff in here that may affect
>> the lifetime of their board.
>> 
>> All gambling on performance for possible lifetime reduction people
>> can do on their own ... for example with a dt-overlay ;-) .
>> 
>> So TL;DR, I agree to both Quentin and Dragan
> 
> Thanks!  Indeed, we must provide only the OPPs that are declared
> by the manufacturer to be always safe for the particular SoC
> variant.  The RK3588J is actually a good example, because it, in
> theory, can run safely at higher OPPs as well, but only when not
> enjoying the extended temperature range that the RK3588J, as an
> SoC variant targeted at industrial applications, is specifically
> made (or binned) for.
> 
> Thus, we must support only the RK3588J OPPs that are declared to
> be safe throughout the entire extended temperature range, while
> anyone who actually can assure that their RK3588J-based board is
> never going to run within the extended temperature range, probably
> may safely apply an overlay that adds the higher OPPs.  As we
> obviously can't know what will be the temperature conditions, we
> may provide only the lower OPPs that are always safe.
> 
> I'll finish the patch and send it over tomorrow or so...  I still
> need to go through the changes once again, to make 100% sure I've
> missed nothing, and that I haven't included anything extraneous. :)

For future reference and for anyone interested, below is the link
to the above-mentioned patch.

https://lore.kernel.org/linux-rockchip/f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic at manjaro.org/T/#u


From anshuman.khandual at arm.com  Thu Mar 20 20:37:18 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Fri, 21 Mar 2025 09:07:18 +0530
Subject: [PATCH 1/2] mm/ptdump: Split note_page() into level specific
 callbacks
In-Reply-To: <20250317061818.16244-2-anshuman.khandual@arm.com>
References: <20250317061818.16244-1-anshuman.khandual@arm.com>
 <20250317061818.16244-2-anshuman.khandual@arm.com>
Message-ID: <6f88d4a7-4b22-4601-a651-029cb343d93b@arm.com>



On 3/17/25 11:48, Anshuman Khandual wrote:
> Last argument passed down in note_page() is u64 assuming pxd_val() returned
> value (all page table levels) is 64 bit - which might not be the case going
> ahead when D128 page tables is enabled on arm64 platform. Besides pxd_val()
> is very platform specific and its type should not be assumed in generic MM.
> 
> Split note_page() into individual page table level specific callbacks which
> accepts corresponding pxd_t argument instead and then subscribing platforms
> just derive pxd_val() from the entries as required and proceed as earlier.
> 
> Also add a note_page_flush() callback for flushing the last page table page
> that was being handled earlier via level = -1.

Does this look good OR is there any concern OR an alternate approach ?

> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will at kernel.org>
> Cc: Madhavan Srinivasan <maddy at linux.ibm.com>
> Cc: Nicholas Piggin <npiggin at gmail.com>
> Cc: Paul Walmsley <paul.walmsley at sifive.com>
> Cc: Palmer Dabbelt <palmer at dabbelt.com>
> Cc: Gerald Schaefer <gerald.schaefer at linux.ibm.com>
> Cc: Heiko Carstens <hca at linux.ibm.com>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: Andrew Morton <akpm at linux-foundation.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Cc: linuxppc-dev at lists.ozlabs.org
> Cc: linux-riscv at lists.infradead.org
> Cc: linux-s390 at vger.kernel.org
> Cc: linux-mm at kvack.org
> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
> ---
>  arch/arm64/include/asm/ptdump.h | 16 +++++++++--
>  arch/arm64/mm/ptdump.c          | 48 ++++++++++++++++++++++++++++++---
>  arch/powerpc/mm/ptdump/ptdump.c | 46 +++++++++++++++++++++++++++++--
>  arch/riscv/mm/ptdump.c          | 46 +++++++++++++++++++++++++++++--
>  arch/s390/mm/dump_pagetables.c  | 46 +++++++++++++++++++++++++++++--
>  arch/x86/mm/dump_pagetables.c   | 39 ++++++++++++++++++++++++++-
>  include/linux/ptdump.h          |  9 ++++---
>  mm/ptdump.c                     | 42 ++++++++++++++++++++++-------
>  8 files changed, 267 insertions(+), 25 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
> index 6cf4aae05219..e5da9ce8a515 100644
> --- a/arch/arm64/include/asm/ptdump.h
> +++ b/arch/arm64/include/asm/ptdump.h
> @@ -59,7 +59,13 @@ struct ptdump_pg_state {
>  
>  void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
>  void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> -	       u64 val);
> +	       pteval_t val);
> +void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte);
> +void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
> +void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud);
> +void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
> +void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
> +void note_page_flush(struct ptdump_state *st);
>  #ifdef CONFIG_PTDUMP_DEBUGFS
>  #define EFI_RUNTIME_MAP_END	DEFAULT_MAP_WINDOW_64
>  void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
> @@ -69,7 +75,13 @@ static inline void ptdump_debugfs_register(struct ptdump_info *info,
>  #endif /* CONFIG_PTDUMP_DEBUGFS */
>  #else
>  static inline void note_page(struct ptdump_state *pt_st, unsigned long addr,
> -			     int level, u64 val) { }
> +			     int level, pteval_t val) { }
> +static inline void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte) { }
> +static inline void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd) { }
> +static inline void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud) { }
> +static inline void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d) { }
> +static inline void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd) { }
> +static inline void note_page_flush(struct ptdump_state *st) { }
>  #endif /* CONFIG_PTDUMP_CORE */
>  
>  #endif /* __ASM_PTDUMP_H */
> diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
> index 688fbe0271ca..fd1610b4fd15 100644
> --- a/arch/arm64/mm/ptdump.c
> +++ b/arch/arm64/mm/ptdump.c
> @@ -189,7 +189,7 @@ static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr)
>  }
>  
>  void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> -	       u64 val)
> +	       pteval_t val)
>  {
>  	struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
>  	struct ptdump_pg_level *pg_level = st->pg_level;
> @@ -251,6 +251,38 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
>  
>  }
>  
> +void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
> +{
> +	note_page(pt_st, addr, 4, pte_val(pte));
> +}
> +
> +void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
> +{
> +	note_page(pt_st, addr, 3, pmd_val(pmd));
> +}
> +
> +void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
> +{
> +	note_page(pt_st, addr, 2, pud_val(pud));
> +}
> +
> +void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
> +{
> +	note_page(pt_st, addr, 1, p4d_val(p4d));
> +}
> +
> +void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
> +{
> +	note_page(pt_st, addr, 0, pgd_val(pgd));
> +}
> +
> +void note_page_flush(struct ptdump_state *pt_st)
> +{
> +	pte_t pte_zero = {0};
> +
> +	note_page(pt_st, 0, -1, pte_val(pte_zero));
> +}
> +
>  void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
>  {
>  	unsigned long end = ~0UL;
> @@ -266,7 +298,12 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
>  		.pg_level = &kernel_pg_levels[0],
>  		.level = -1,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]){
>  				{info->base_addr, end},
>  				{0, 0}
> @@ -303,7 +340,12 @@ bool ptdump_check_wx(void)
>  		.level = -1,
>  		.check_wx = true,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]) {
>  				{_PAGE_OFFSET(vabits_actual), ~0UL},
>  				{0, 0}
> diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
> index 9dc239967b77..b2358d794855 100644
> --- a/arch/powerpc/mm/ptdump/ptdump.c
> +++ b/arch/powerpc/mm/ptdump/ptdump.c
> @@ -298,6 +298,38 @@ static void populate_markers(void)
>  #endif
>  }
>  
> +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
> +{
> +	note_page(pt_st, addr, 4, pte_val(pte));
> +}
> +
> +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
> +{
> +	note_page(pt_st, addr, 3, pmd_val(pmd));
> +}
> +
> +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
> +{
> +	note_page(pt_st, addr, 2, pud_val(pud));
> +}
> +
> +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
> +{
> +	note_page(pt_st, addr, 1, p4d_val(p4d));
> +}
> +
> +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
> +{
> +	note_page(pt_st, addr, 0, pgd_val(pgd));
> +}
> +
> +static void note_page_flush(struct ptdump_state *pt_st)
> +{
> +	pte_t pte_zero = {0};
> +
> +	note_page(pt_st, 0, -1, pte_val(pte_zero));
> +}
> +
>  static int ptdump_show(struct seq_file *m, void *v)
>  {
>  	struct pg_state st = {
> @@ -305,7 +337,12 @@ static int ptdump_show(struct seq_file *m, void *v)
>  		.marker = address_markers,
>  		.level = -1,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = ptdump_range,
>  		}
>  	};
> @@ -338,7 +375,12 @@ bool ptdump_check_wx(void)
>  		.level = -1,
>  		.check_wx = true,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = ptdump_range,
>  		}
>  	};
> diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
> index 9d5f657a251b..32922550a50a 100644
> --- a/arch/riscv/mm/ptdump.c
> +++ b/arch/riscv/mm/ptdump.c
> @@ -318,6 +318,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr,
>  	}
>  }
>  
> +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
> +{
> +	note_page(pt_st, addr, 4, pte_val(pte));
> +}
> +
> +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
> +{
> +	note_page(pt_st, addr, 3, pmd_val(pmd));
> +}
> +
> +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
> +{
> +	note_page(pt_st, addr, 2, pud_val(pud));
> +}
> +
> +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
> +{
> +	note_page(pt_st, addr, 1, p4d_val(p4d));
> +}
> +
> +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
> +{
> +	note_page(pt_st, addr, 0, pgd_val(pgd));
> +}
> +
> +static void note_page_flush(struct ptdump_state *pt_st)
> +{
> +	pte_t pte_zero = {0};
> +
> +	note_page(pt_st, 0, -1, pte_val(pte_zero));
> +}
> +
>  static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
>  {
>  	struct pg_state st = {
> @@ -325,7 +357,12 @@ static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
>  		.marker = pinfo->markers,
>  		.level = -1,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]) {
>  				{pinfo->base_addr, pinfo->end},
>  				{0, 0}
> @@ -347,7 +384,12 @@ bool ptdump_check_wx(void)
>  		.level = -1,
>  		.check_wx = true,
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]) {
>  				{KERN_VIRT_START, ULONG_MAX},
>  				{0, 0}
> diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
> index fa54f3bc0c8d..e7cc52542f71 100644
> --- a/arch/s390/mm/dump_pagetables.c
> +++ b/arch/s390/mm/dump_pagetables.c
> @@ -145,11 +145,48 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
>  	}
>  }
>  
> +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
> +{
> +	note_page(pt_st, addr, 4, pte_val(pte));
> +}
> +
> +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
> +{
> +	note_page(pt_st, addr, 3, pmd_val(pmd));
> +}
> +
> +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
> +{
> +	note_page(pt_st, addr, 2, pud_val(pud));
> +}
> +
> +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
> +{
> +	note_page(pt_st, addr, 1, p4d_val(p4d));
> +}
> +
> +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
> +{
> +	note_page(pt_st, addr, 0, pgd_val(pgd));
> +}
> +
> +static void note_page_flush(struct ptdump_state *pt_st)
> +{
> +	pte_t pte_zero = {0};
> +
> +	note_page(pt_st, 0, -1, pte_val(pte_zero));
> +}
> +
>  bool ptdump_check_wx(void)
>  {
>  	struct pg_state st = {
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]) {
>  				{.start = 0, .end = max_addr},
>  				{.start = 0, .end = 0},
> @@ -188,7 +225,12 @@ static int ptdump_show(struct seq_file *m, void *v)
>  {
>  	struct pg_state st = {
>  		.ptdump = {
> -			.note_page = note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.range = (struct ptdump_range[]) {
>  				{.start = 0, .end = max_addr},
>  				{.start = 0, .end = 0},
> diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
> index 89079ea73e65..2e1c2d006ace 100644
> --- a/arch/x86/mm/dump_pagetables.c
> +++ b/arch/x86/mm/dump_pagetables.c
> @@ -362,6 +362,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
>  	}
>  }
>  
> +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte)
> +{
> +	note_page(pt_st, addr, 4, pte_val(pte));
> +}
> +
> +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd)
> +{
> +	note_page(pt_st, addr, 3, pmd_val(pmd));
> +}
> +
> +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud)
> +{
> +	note_page(pt_st, addr, 2, pud_val(pud));
> +}
> +
> +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d)
> +{
> +	note_page(pt_st, addr, 1, p4d_val(p4d));
> +}
> +
> +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
> +{
> +	note_page(pt_st, addr, 0, pgd_val(pgd));
> +}
> +
> +static void note_page_flush(struct ptdump_state *pt_st)
> +{
> +	pte_t pte_zero = {0};
> +
> +	note_page(pt_st, 0, -1, pte_val(pte_zero));
> +}
> +
>  bool ptdump_walk_pgd_level_core(struct seq_file *m,
>  				struct mm_struct *mm, pgd_t *pgd,
>  				bool checkwx, bool dmesg)
> @@ -378,7 +410,12 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m,
>  
>  	struct pg_state st = {
>  		.ptdump = {
> -			.note_page	= note_page,
> +			.note_page_pte = note_page_pte,
> +			.note_page_pmd = note_page_pmd,
> +			.note_page_pud = note_page_pud,
> +			.note_page_p4d = note_page_p4d,
> +			.note_page_pgd = note_page_pgd,
> +			.note_page_flush = note_page_flush,
>  			.effective_prot = effective_prot,
>  			.range		= ptdump_ranges
>  		},
> diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h
> index 8dbd51ea8626..1c1eb1fae199 100644
> --- a/include/linux/ptdump.h
> +++ b/include/linux/ptdump.h
> @@ -11,9 +11,12 @@ struct ptdump_range {
>  };
>  
>  struct ptdump_state {
> -	/* level is 0:PGD to 4:PTE, or -1 if unknown */
> -	void (*note_page)(struct ptdump_state *st, unsigned long addr,
> -			  int level, u64 val);
> +	void (*note_page_pte)(struct ptdump_state *st, unsigned long addr, pte_t pte);
> +	void (*note_page_pmd)(struct ptdump_state *st, unsigned long addr, pmd_t pmd);
> +	void (*note_page_pud)(struct ptdump_state *st, unsigned long addr, pud_t pud);
> +	void (*note_page_p4d)(struct ptdump_state *st, unsigned long addr, p4d_t p4d);
> +	void (*note_page_pgd)(struct ptdump_state *st, unsigned long addr, pgd_t pgd);
> +	void (*note_page_flush)(struct ptdump_state *st);
>  	void (*effective_prot)(struct ptdump_state *st, int level, u64 val);
>  	const struct ptdump_range *range;
>  };
> diff --git a/mm/ptdump.c b/mm/ptdump.c
> index 106e1d66e9f9..706cfc19439b 100644
> --- a/mm/ptdump.c
> +++ b/mm/ptdump.c
> @@ -18,7 +18,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk,
>  {
>  	struct ptdump_state *st = walk->private;
>  
> -	st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0]));
> +	st->note_page_pte(st, addr, kasan_early_shadow_pte[0]);
>  
>  	walk->action = ACTION_CONTINUE;
>  
> @@ -42,7 +42,7 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr,
>  		st->effective_prot(st, 0, pgd_val(val));
>  
>  	if (pgd_leaf(val)) {
> -		st->note_page(st, addr, 0, pgd_val(val));
> +		st->note_page_pgd(st, addr, val);
>  		walk->action = ACTION_CONTINUE;
>  	}
>  
> @@ -65,7 +65,7 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr,
>  		st->effective_prot(st, 1, p4d_val(val));
>  
>  	if (p4d_leaf(val)) {
> -		st->note_page(st, addr, 1, p4d_val(val));
> +		st->note_page_p4d(st, addr, val);
>  		walk->action = ACTION_CONTINUE;
>  	}
>  
> @@ -88,7 +88,7 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr,
>  		st->effective_prot(st, 2, pud_val(val));
>  
>  	if (pud_leaf(val)) {
> -		st->note_page(st, addr, 2, pud_val(val));
> +		st->note_page_pud(st, addr, val);
>  		walk->action = ACTION_CONTINUE;
>  	}
>  
> @@ -109,7 +109,7 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr,
>  	if (st->effective_prot)
>  		st->effective_prot(st, 3, pmd_val(val));
>  	if (pmd_leaf(val)) {
> -		st->note_page(st, addr, 3, pmd_val(val));
> +		st->note_page_pmd(st, addr, val);
>  		walk->action = ACTION_CONTINUE;
>  	}
>  
> @@ -125,7 +125,7 @@ static int ptdump_pte_entry(pte_t *pte, unsigned long addr,
>  	if (st->effective_prot)
>  		st->effective_prot(st, 4, pte_val(val));
>  
> -	st->note_page(st, addr, 4, pte_val(val));
> +	st->note_page_pte(st, addr, val);
>  
>  	return 0;
>  }
> @@ -134,9 +134,31 @@ static int ptdump_hole(unsigned long addr, unsigned long next,
>  		       int depth, struct mm_walk *walk)
>  {
>  	struct ptdump_state *st = walk->private;
> -
> -	st->note_page(st, addr, depth, 0);
> -
> +	pte_t pte_zero = {0};
> +	pmd_t pmd_zero = {0};
> +	pud_t pud_zero = {0};
> +	p4d_t p4d_zero = {0};
> +	pgd_t pgd_zero = {0};
> +
> +	switch (depth) {
> +	case 4:
> +		st->note_page_pte(st, addr, pte_zero);
> +		break;
> +	case 3:
> +		st->note_page_pmd(st, addr, pmd_zero);
> +		break;
> +	case 2:
> +		st->note_page_pud(st, addr, pud_zero);
> +		break;
> +	case 1:
> +		st->note_page_p4d(st, addr, p4d_zero);
> +		break;
> +	case 0:
> +		st->note_page_pgd(st, addr, pgd_zero);
> +		break;
> +	default:
> +		break;
> +	}
>  	return 0;
>  }
>  
> @@ -162,7 +184,7 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
>  	mmap_write_unlock(mm);
>  
>  	/* Flush out the last page */
> -	st->note_page(st, 0, -1, 0);
> +	st->note_page_flush(st);
>  }
>  
>  static int check_wx_show(struct seq_file *m, void *v)


From cki-project at redhat.com  Thu Mar 20 21:33:03 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 21 Mar 2025 04:33:03 -0000
Subject: =?utf-8?b?4pyF?= PASS (MISSED 9 of 41): Test report for for-kernelci
 (6.14.0-rc7, upstream-arm-next, cc8f5087)
Message-ID: <61845.125032100330501992@us-mta-629.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK
              Test: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: drm/panthor: Clean up FW version information display

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1727289952

Tests that were not ran because of internal issues:
    Boot test [aarch64]
    CKI/restraint [aarch64]
    machineinfo [aarch64]
    Reboot test [aarch64]
    SELinux Custom Module Setup [aarch64]
    Storage - blktests - throtl [aarch64]
    Storage - blktests - ublk [aarch64]
    stress: stress-ng - cpu-cache [aarch64]
    stress: stress-ng - memory [aarch64]


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From sfr at canb.auug.org.au  Thu Mar 20 21:38:00 2025
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Fri, 21 Mar 2025 15:38:00 +1100
Subject: linux-next: duplicate patches in the devicetree tree
Message-ID: <20250321153800.639f03c5@canb.auug.org.au>

Hi all,

The following commits are also in the arm-soc tree as different commits
(but the same patches):

  a78f7a337bc7 ("docs: process: maintainer-soc-clean-dts: linux-next is decisive")
  b31cc6af1bb1 ("docs: dt: submitting-patches: Document sending DTS patches")

These are commits

  a42d2d53a6d7 ("docs: process: maintainer-soc-clean-dts: linux-next is decisive")
  d98d35d99e0f ("docs: dt: submitting-patches: Document sending DTS patches")

in the arm-soc tree.

-- 
Cheers,
Stephen Rothwell
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/72208a1e/attachment.sig>

From viresh.kumar at linaro.org  Thu Mar 20 21:56:24 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Fri, 21 Mar 2025 10:26:24 +0530
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
 <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
Message-ID: <20250321045624.mwm2mnkqeow5uids@vireshk-i7>

On 20-03-25, 08:22, Chun-Jen Tseng (???) wrote:
> The struct mtk_cpu_dvfs_info instance is per-policy and the reg_lock is
> also in this structure. when I have two "policy-0" and "policy-6" use
> the same mtk_cpufreq_set_target() function but the info->reg_lock?
> is from 2 instance(policy-0 and policy-6). when the policy-0 and
> policy-6 call set_target target, the mutex_lock is locked by per-
> policy. So, I change to global lock avoid per-policy lock.

Yes, that's what you are doing. I am asking why a global lock is required here ?
I think the per-policy lock is all you need.

-- 
viresh


From viresh.kumar at linaro.org  Thu Mar 20 21:59:38 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Fri, 21 Mar 2025 10:29:38 +0530
Subject: [PATCH v3 2/3] cpufreq: mediatek: Add CPUFREQ_ASYNC_NOTIFICATION
 flag
In-Reply-To: <21e1b622c2968a5549b2ff37e4ba329a557968b6.camel@mediatek.com>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
 <20250214074353.1169864-3-chun-jen.tseng@mediatek.com>
 <20250219054543.4xt4tixsauwoqpst@vireshk-i7>
 <21e1b622c2968a5549b2ff37e4ba329a557968b6.camel@mediatek.com>
Message-ID: <20250321045938.6gnmtlbdcx2i6gmw@vireshk-i7>

On 20-03-25, 08:34, Chun-Jen Tseng (???) wrote:
> For CCI and ARMPLL in different driver, I need to change ARMPLL first
> then use cpufreq notify CCI driver. it can avoid CCI driver get wrong
> ARMPLL frequency and choose WRONG frequency.

That flag is only required if mtk_cpufreq_set_target() isn't able to complete
the freq transition. Which isn't the case here. I don't think your patch is
correct.

-- 
viresh


From Chun-Jen.Tseng at mediatek.com  Thu Mar 20 22:32:06 2025
From: Chun-Jen.Tseng at mediatek.com (=?utf-8?B?Q2h1bi1KZW4gVHNlbmcgKOabvuS/iuS7gSk=?=)
Date: Fri, 21 Mar 2025 05:32:06 +0000
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <20250321045624.mwm2mnkqeow5uids@vireshk-i7>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
	 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
	 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
	 <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
	 <20250321045624.mwm2mnkqeow5uids@vireshk-i7>
Message-ID: <2a73b5ca35692c8ffa68c9ff0df73e24a592967d.camel@mediatek.com>

Hi viresh,

I add a global lock related to the CCI driver.

This is because the CCI needs to obtain the frequencies of policy-0 and
policy-6 to determine its own frequency.

If policy-0 and policy-6 are set simultaneously, it may cause the CCI
to select the wrong frequency.

Therefore, I hope to change the setting flow to the following:
   policy-0 or policy-6 -> set frequency -> CCI receives notification -
> set CCI frequency

BRs,

Mark Tseng

On Fri, 2025-03-21 at 10:26 +0530, Viresh Kumar wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 20-03-25, 08:22, Chun-Jen Tseng (???) wrote:
> > The struct mtk_cpu_dvfs_info instance is per-policy and the
> > reg_lock is
> > also in this structure. when I have two "policy-0" and "policy-6"
> > use
> > the same mtk_cpufreq_set_target() function but the info->reg_lock
> > is from 2 instance(policy-0 and policy-6). when the policy-0 and
> > policy-6 call set_target target, the mutex_lock is locked by per-
> > policy. So, I change to global lock avoid per-policy lock.
> 
> Yes, that's what you are doing. I am asking why a global lock is
> required here ?
> I think the per-policy lock is all you need.
> 
> --
> viresh


From wthai at nvidia.com  Thu Mar 20 22:27:12 2025
From: wthai at nvidia.com (Willie Thai)
Date: Fri, 21 Mar 2025 05:27:12 +0000
Subject: [PATCH v3 2/2] dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
In-Reply-To: <585c2b050a44f4009b3a61cab69f800c88a0cf5e.camel@codeconstruct.com.au>
References: <585c2b050a44f4009b3a61cab69f800c88a0cf5e.camel@codeconstruct.com.au>
Message-ID: <20250321052712.104446-1-wthai@nvidia.com>

> Hi Willie,
> 
> On Thu, 2025-03-20 at 16:46 +0000, Willie Thai wrote:
>> This patch adds a binding for GB200NVL BMC.
>> 
>> The GB200NVL BMC is an Aspeed Ast2600 based BMC for Nvidia Blackwell
>> GB200NVL platform.
>> Reference to Ast2600 SOC [1].
>> Reference to Blackwell GB200NVL Platform [2].
>> 
>> Co-developed-by: Mars Yang <maryang at nvidia.com>
>> Signed-off-by: Mars Yang <maryang at nvidia.com>
>> Link: https://www.aspeedtech.com/server_ast2600/ [1]
>> Link:
>> https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
>> Signed-off-by: Willie Thai <wthai at nvidia.com>
>> ---
>>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>>  1 file changed, 1 insertion(+)
>> 
>> diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> index 01333ac111fb..a3736f134130 100644
>> --- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> +++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
>> @@ -98,6 +98,7 @@ properties:
>>                - inventec,starscream-bmc
>>                - inventec,transformer-bmc
>>                - jabil,rbp-bmc
>> +              - nvidia,gb200nvl-bmc
>>                - qcom,dc-scm-v1-bmc
>>                - quanta,s6q-bmc
>>                - ufispace,ncplite-bmc
> 
> Please order this patch first in your series, before the devicetree.
> 
> Andrew

Thanks Andrew for the feedback, will order the patches in v4.


From Sunny.Shen at mediatek.com  Thu Mar 20 22:45:18 2025
From: Sunny.Shen at mediatek.com (=?utf-8?B?U3VubnkgU2hlbiAo5rKI5aeN5aeNKQ==?=)
Date: Fri, 21 Mar 2025 05:45:18 +0000
Subject: [PATCH 1/5] dt-bindings: display: mediatek: mdp-rsz: Add rules
 for MT8196
In-Reply-To: <20250319-footnote-trusting-230e509bed07@spud>
References: <20250211025317.399534-1-sunny.shen@mediatek.com>
	 <20250211025317.399534-2-sunny.shen@mediatek.com>
	 <20250211-feed-shed-4b32f146cc54@spud>
	 <029f9fd7ab898769a7ae627b160e1dce446ccc9e.camel@mediatek.com>
	 <20250224-dreamland-tactile-bdb58daf6060@spud>
	 <76a6fc25a09dfddb55fdaf0a9d7dcf9a6129b00f.camel@mediatek.com>
	 <20250319-footnote-trusting-230e509bed07@spud>
Message-ID: <d2a680db6d9f4e9547b2ce8e4e0cb502de35149c.camel@mediatek.com>

On Wed, 2025-03-19 at 20:00 +0000, Conor Dooley wrote:
> On Tue, Mar 18, 2025 at 03:14:07AM +0000, Sunny Shen (???) wrote:
> > On Mon, 2025-02-24 at 19:01 +0000, Conor Dooley wrote:
> > > On Sun, Feb 23, 2025 at 05:49:45PM +0000, Sunny Shen (???) wrote:
> > > > On Tue, 2025-02-11 at 17:54 +0000, Conor Dooley wrote:
> > > > > On Tue, Feb 11, 2025 at 10:52:50AM +0800, Sunny Shen wrote:
> > > > > > Add MDP-RSZ hardware description for MediaTek MT8196 SoC
> > > 
> > > > > > +examples:
> > > > > > +? - |
> > > > > > +??? soc {
> > > > > > +??????? #address-cells = <2>;
> > > > > > +??????? #size-cells = <2>;
> > > > > > +
> > > > > > +??????? disp_mdp_rsz0: disp-mdp-rsz0 at 321a0000 {
> > > > > 
> > > > > And "disp-mdp-rsz0" isn't anything close to a generic node
> > > > > name.
> > > > 
> > > > Will modify "disp-mdp-rsz0 at 321a0000" to "mdp-rsz at 321a0000"
> > > 
> > > I don't think that's an improvement. Hint: full words would be a
> > > good
> > > place to start
> > 
> > ?
> > Hi Conor,
> > 
> > About full words,?
> > Do you mean words like this??
> > multimedia-display-path-resizer?
> > or mdp-resizer?
> 
> These are both improvements on what you've got right now.

Okay~
I'll use mdp-resizer for this


> 
> > We found that "mdp-rsz" this kind of word is used at
> > https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/mediatek/mt8183.dtsi
> > 
> > I'm not sure what will be better.
> > Can you provide more detailed suggestion about this naming?


From Hailong.Fan at mediatek.com  Thu Mar 20 22:51:22 2025
From: Hailong.Fan at mediatek.com (=?utf-8?B?SGFpbG9uZyBGYW4gKOiMg+a1t+m+mSk=?=)
Date: Fri, 21 Mar 2025 05:51:22 +0000
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <20250320-cocky-adventurous-rooster-be2abd@krzk-bin>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
	 <20250320031753.13669-2-hailong.fan@mediatek.com>
	 <20250320-cocky-adventurous-rooster-be2abd@krzk-bin>
Message-ID: <e369f6ec539454ad7d4f30389fec4ae58d1482ae.camel@mediatek.com>

On Thu, 2025-03-20 at 08:52 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Thu, Mar 20, 2025 at 11:17:24AM +0800, hailong.fan wrote:
> > +
> > +void mt8196_sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
> > +{
> > +     /* set RUNSTALL to stop core */
> > +     snd_sof_dsp_update_bits(sdev, DSP_REG_BAR,
> > ADSP_HIFI_RUNSTALL,
> > +                             RUNSTALL, RUNSTALL);
> > +
> > +     /* assert core reset */
> > +     snd_sof_dsp_update_bits(sdev, DSP_REG_BAR,
> > ADSP_CFGREG_SW_RSTN,
> > +                             SW_RSTN_C0 | SW_DBG_RSTN_C0,
> > +                             SW_RSTN_C0 | SW_DBG_RSTN_C0);
> > +}
> > +
> 
> Drop stray blank line.
OK, will fix in v2, thx.
> 
> > diff --git a/sound/soc/sof/mediatek/mt8196/mt8196.c
> > b/sound/soc/sof/mediatek/mt8196/mt8196.c
> > new file mode 100644
> > index 000000000000..364069ce9954
> > --- /dev/null
> > +++ b/sound/soc/sof/mediatek/mt8196/mt8196.c
> > @@ -0,0 +1,650 @@
> > +// SPDX-License-Identifier: GPL-2.0
> 
> Look here
OK, will fix in v2, thx.
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
> 
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + * Author: Hailong Fan <hailong.fan at mediatek.com>
> > + */
> 
> ...
> 
> > +
> > +static const struct of_device_id sof_of_mt8196_ids[] = {
> > +     { .compatible = "mediatek,mt8196-dsp", .data =
> > &sof_of_mt8196_desc},
> 
> Bindings are before users.
Will change patch order in v2, thx.
> 
> > +     { }
> > +};
> > +MODULE_DEVICE_TABLE(of, sof_of_mt8196_ids);
> > +
> > +/* DT driver definition */
> > +static struct platform_driver snd_sof_of_mt8196_driver = {
> > +     .probe = sof_of_probe,
> > +     .remove = sof_of_remove,
> > +     .shutdown = sof_of_shutdown,
> > +     .driver = {
> > +     .name = "sof-audio-of-mt8196",
> > +             .pm = &sof_of_pm,
> > +             .of_match_table = sof_of_mt8196_ids,
> > +     },
> > +};
> > +module_platform_driver(snd_sof_of_mt8196_driver);
> > +
> > +MODULE_LICENSE("Dual BSD/GPL");
> 
> And here Hm? Don't fake the licensing.
Will fix in v2, thx.
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-
Clause) */
> 
> > +MODULE_DESCRIPTION("SOF support for MT8196 platforms");
> > +MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
> 
> Is this correct?
> 
> 
> Best regards,
> Krzysztof
> 

From viresh.kumar at linaro.org  Thu Mar 20 23:01:48 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Fri, 21 Mar 2025 11:31:48 +0530
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <2a73b5ca35692c8ffa68c9ff0df73e24a592967d.camel@mediatek.com>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
 <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
 <20250321045624.mwm2mnkqeow5uids@vireshk-i7>
 <2a73b5ca35692c8ffa68c9ff0df73e24a592967d.camel@mediatek.com>
Message-ID: <20250321060148.adhxjexpnm4dkpnt@vireshk-i7>

On 21-03-25, 05:32, Chun-Jen Tseng (???) wrote:
> I add a global lock related to the CCI driver.
> 
> This is because the CCI needs to obtain the frequencies of policy-0 and
> policy-6 to determine its own frequency.
> 
> If policy-0 and policy-6 are set simultaneously, it may cause the CCI
> to select the wrong frequency.
> 
> Therefore, I hope to change the setting flow to the following:
>    policy-0 or policy-6 -> set frequency -> CCI receives notification -
> set CCI frequency

Can you please point to the code where this race exists ? I am not
sure I fully understand it as of now. If the race is present in
another driver, CCI ?, then shouldn't it be fixed there instead ?

-- 
viresh


From lkp at intel.com  Thu Mar 20 23:12:55 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 14:12:55 +0800
Subject: [net-next PATCH v13 10/14] mfd: an8855: Add support for Airoha
 AN8855 Switch MFD
In-Reply-To: <20250315154407.26304-11-ansuelsmth@gmail.com>
References: <20250315154407.26304-11-ansuelsmth@gmail.com>
Message-ID: <202503211428.H4VdWHco-lkp@intel.com>

Hi Christian,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Marangi/dt-bindings-nvmem-Document-support-for-Airoha-AN8855-Switch-EFUSE/20250315-235040
base:   net-next/main
patch link:    https://lore.kernel.org/r/20250315154407.26304-11-ansuelsmth%40gmail.com
patch subject: [net-next PATCH v13 10/14] mfd: an8855: Add support for Airoha AN8855 Switch MFD
config: i386-randconfig-006-20250321 (https://download.01.org/0day-ci/archive/20250321/202503211428.H4VdWHco-lkp at intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250321/202503211428.H4VdWHco-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503211428.H4VdWHco-lkp at intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/mfd/airoha-an8855.o: in function `an8855_core_probe':
>> drivers/mfd/airoha-an8855.c:376: undefined reference to `devm_mdio_regmap_init'


vim +376 drivers/mfd/airoha-an8855.c

   352	
   353	static int an8855_core_probe(struct mdio_device *mdiodev)
   354	{
   355		struct regmap *regmap, *regmap_phy;
   356		struct device *dev = &mdiodev->dev;
   357		struct an8855_core_priv *priv;
   358		struct gpio_desc *reset_gpio;
   359		u32 val;
   360		int ret;
   361	
   362		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
   363		if (!priv)
   364			return -ENOMEM;
   365	
   366		priv->bus = mdiodev->bus;
   367		priv->switch_addr = mdiodev->addr;
   368		/* No DMA for mdiobus, mute warning for DMA mask not set */
   369		dev->dma_mask = &dev->coherent_dma_mask;
   370	
   371		regmap = devm_regmap_init(dev, NULL, priv, &an8855_regmap_config);
   372		if (IS_ERR(regmap))
   373			return dev_err_probe(dev, PTR_ERR(regmap),
   374					     "regmap initialization failed\n");
   375	
 > 376		regmap_phy = devm_mdio_regmap_init(dev, priv, &an8855_regmap_phy_config);
   377		if (IS_ERR(regmap_phy))
   378			return dev_err_probe(dev, PTR_ERR(regmap_phy),
   379					     "regmap phy initialization failed\n");
   380	
   381		reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
   382		if (IS_ERR(reset_gpio))
   383			return PTR_ERR(reset_gpio);
   384	
   385		if (reset_gpio) {
   386			usleep_range(100000, 150000);
   387			gpiod_set_value_cansleep(reset_gpio, 0);
   388			usleep_range(100000, 150000);
   389			gpiod_set_value_cansleep(reset_gpio, 1);
   390	
   391			/* Poll HWTRAP reg to wait for Switch to fully Init */
   392			ret = regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val,
   393						       val, 20, 200000);
   394			if (ret)
   395				return ret;
   396		}
   397	
   398		ret = an8855_read_switch_id(dev, regmap);
   399		if (ret)
   400			return ret;
   401	
   402		/* Release global PHY power down */
   403		ret = regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0);
   404		if (ret)
   405			return ret;
   406	
   407		return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_core_childs,
   408					    ARRAY_SIZE(an8855_core_childs), NULL, 0,
   409					    NULL);
   410	}
   411	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From Hailong.Fan at mediatek.com  Thu Mar 20 23:19:28 2025
From: Hailong.Fan at mediatek.com (=?utf-8?B?SGFpbG9uZyBGYW4gKOiMg+a1t+m+mSk=?=)
Date: Fri, 21 Mar 2025 06:19:28 +0000
Subject: [PATCH 2/2] dt-bindings: dsp: mediatek: add mt8196 dsp document
In-Reply-To: <20250320-divergent-soft-bird-bcd938@krzk-bin>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
	 <20250320031753.13669-3-hailong.fan@mediatek.com>
	 <20250320-divergent-soft-bird-bcd938@krzk-bin>
Message-ID: <a72988212d0d95bfe76eb9c53bbdb8c57c989377.camel@mediatek.com>

On Thu, 2025-03-20 at 08:49 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Thu, Mar 20, 2025 at 11:17:25AM +0800, hailong.fan wrote:
> > This patch adds mt8196 dsp document. The dsp is used for Sound Open
> > Firmware driver node. It includes registers,  clocks, memory
> > regions,
> > and mailbox for dsp.
> > 
> > Signed-off-by: hailong.fan <hailong.fan at mediatek.com>
> 
> Don't use login as full name, but proper Latin-alphabet transcription
> or
> original name in UTF.
> 
> This cannot be tested due to dependency, so limited review.
Will fix in v2, thx.
> 
> > ---
> >  .../bindings/dsp/mediatek,mt8196-dsp.yaml     | 96
> > +++++++++++++++++++
> 
> Don't grow dsp directory. Either this is remoteproc or some sound
> component, so place it accordingly.
This is a reference to the approach used in a previous MediaTek
project:

https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/Documentation/devicetree/bindings/dsp
Do we need to move all the files under the DSP directory to the sound
directory?
> 
> >  1 file changed, 96 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/dsp/mediatek,mt8196-dsp.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/dsp/mediatek,mt8196-
> > dsp.yaml b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-
> > dsp.yaml
> > new file mode 100644
> > index 000000000000..62bcd97bd0f4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/dsp/mediatek,mt8196-
> > dsp.yaml
> > @@ -0,0 +1,96 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: 
> > https://urldefense.com/v3/__http://devicetree.org/schemas/dsp/mediatek,mt8196-dsp.yaml*__;Iw!!CTRNKA9wMg0ARbw!j4BSCn2ciKI2gdoQgLFTB0YUey5u6HieRa6NvWQvaF7X_mEEyHhCIslrFYGBOYEbWLaE2J5kDORlxRI$
> > +$schema: 
> > https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!j4BSCn2ciKI2gdoQgLFTB0YUey5u6HieRa6NvWQvaF7X_mEEyHhCIslrFYGBOYEbWLaE2J5k8T-XN8U$
> > +
> > +title: Mediatek mt8196 DSP core
> > +
> > +maintainers:
> > +  - Hailong Fan <hailong.fan at mediatek.com>
> > +
> > +description: |
> 
> Do not need '|' unless you need to preserve formatting.
Will update in v2, thx.
> 
> > +  Some boards from mt8196 contain a DSP core used for
> 
> Boards or MT8196? If boards, how is this related to SoC in the first
> place? Thus wrong compatible.
> 
> > +  advanced pre- and post- audio processing.
> > +
> > +properties:
> > +  compatible:
> > +    const: mediatek,mt8196-dsp
> 
> If this is part of the SoC, then wrong description.
Sure, it will be updated in V2 as follows: 
MediaTek mt8196 SoC contains a DSP core used for
advanced pre- and post- audio processing.
> 
> > +
> > +  reg:
> > +    items:
> > +      - description: Address and size of the DSP Cfg registers
> 
> s/Address and size of the//
> 
> Write concise and accurate description. This cannot be anything else,
> so
> no need to state obvious.
Will update in v2, thx.
> 
> > +      - description: Address and size of the DSP SRAM
> > +      - description: Address and size of the DSP secure registers
> > +      - description: Address and size of the DSP bus registers
> > +
> > +  reg-names:
> > +    items:
> > +      - const: cfg
> > +      - const: sram
> > +      - const: sec
> > +      - const: bus
> > +
> > +  clocks:
> > +    items:
> > +      - description: mux for dsp clock
> > +      - description: 26M clock
> > +      - description: ADSP PLL clock
> > +
> > +  clock-names:
> > +    items:
> > +      - const: adsp_sel
> > +      - const: clk26m
> > +      - const: adsppll
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +  mboxes:
> > +    items:
> > +      - description: mailbox for receiving audio DSP requests.
> > +      - description: mailbox for transmitting requests to audio
> > DSP.
> > +
> > +  mbox-names:
> > +    items:
> > +      - const: rx
> > +      - const: tx
> > +
> > +  memory-region:
> > +    items:
> > +      - description: dma buffer between host and DSP.
> > +      - description: DSP system memory.
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reg-names
> > +  - clocks
> > +  - clock-names
> > +  - power-domains
> > +  - mbox-names
> > +  - mboxes
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/mt8196-clk.h>
> > +    #include <dt-bindings/power/mt8196-power.h>
> > +    adsp: adsp at 1a000000 {
> 
> Drop unused label
Will update in v2, thx.
> 
> > +        compatible = "mediatek,mt8196-dsp";
> > +        reg = <0x1a000000 0x5000>,
> > +              <0x1a210000 0x80000>,
> > +              <0x1a345000 0x300>,
> > +              <0x1a00f000 0x1000>;
> > +        reg-names = "cfg", "sram", "sec", "bus";
> > +        power-domains = <&scpsys
> > MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT>;
> > +        clocks = <&cksys_clk CLK_CK_ADSP_SEL>,
> > +                 <&cksys_clk CLK_CK_TCK_26M_MX9>,
> > +                 <&cksys_clk CLK_CK_ADSPPLL>;
> > +        clock-names = "adsp_sel",
> > +                      "clk26m",
> > +                      "adsppll";
> > +        mbox-names = "rx", "tx";
> > +        mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
> 
> Reverse order of mboxes and mbox-names properties. xxx-names follows
> the
> xxx.
Will update in v2, thx.
> 
> Best regards,
> Krzysztof
> M

From akihiko.odaki at daynix.com  Thu Mar 20 23:20:49 2025
From: akihiko.odaki at daynix.com (Akihiko Odaki)
Date: Fri, 21 Mar 2025 15:20:49 +0900
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <86cyebmxo7.wl-maz@kernel.org>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
 <Z9pze3J2_zrTk_yC@linux.dev>
 <e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
 <86plidmjwh.wl-maz@kernel.org>
 <bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
 <86o6xxmg87.wl-maz@kernel.org>
 <aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
 <86msdhmemw.wl-maz@kernel.org>
 <cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
 <86ldt0n9w1.wl-maz@kernel.org> <Z9sSMJAlf7cQ5viu@linux.dev>
 <0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
 <86iko4m5i4.wl-maz@kernel.org>
 <ba9cd6d2-1ee5-478a-8102-42b4dac411ce@daynix.com>
 <86cyebmxo7.wl-maz@kernel.org>
Message-ID: <54cb5388-e278-41de-be29-d578cc5c37c5@daynix.com>

On 2025/03/21 2:14, Marc Zyngier wrote:
> On Thu, 20 Mar 2025 09:52:59 +0000,
> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>
>> On 2025/03/20 18:10, Marc Zyngier wrote:
>>> On Thu, 20 Mar 2025 06:03:35 +0000,
>>> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>>>
>>>> On 2025/03/20 3:51, Oliver Upton wrote:
>>>>> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
>>>>>> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
>>>>>>> What about setting the flag automatically when a user fails to pin
>>>>>>> vCPUs to CPUs that are covered by one PMU? There would be no change if
>>>>>>> a user correctly pins vCPUs as it is. Otherwise, they will see a
>>>>>>> correct feature set advertised to the guest and the cycle counter
>>>>>>> working.
>>>>>>
>>>>>> How do you know that the affinity is "correct"? VCPU affinity can be
>>>>>> changed at any time. I, for one, do not want my VMs to change
>>>>>> behaviour because I let the vcpus bounce around as the scheduler sees
>>>>>> fit.
>>>>
>>>> Checking the affinity when picking the default PMU; the vCPU affinity
>>>> is the only thing that rules the choice of the default PMU even now.
>>>>
>>>> Perhaps we may model the API as follows: introduce another "composite"
>>>> PMU that works on any core but only exposes the cycle counter. Robust
>>>> VMMs will choose it or one of hardware PMUs with
>>>> KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according
>>>> to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If
>>>> the affinity is covered by one hardware PMU, that PMU will be chosen
>>>> as the default. The "composite" PMU will be the default otherwise.
>>>
>>> This makes no sense to me. A VCPU is always affine to a PMU, because
>>> we do not support configurations where only some CPUs have a PMU. This
>>> is an all-or-nothing situation.
>>
>> At least isn't it fine to have the composite PMU with a new value for
>> KVM_ARM_VCPU_PMU_V3_SET_PMU?
> 
> Not sure KVM_ARM_VCPU_PMU_V3_SET_PMU is the right hook (it takes a PMU
> 'type', which is under control of the perf subsystem). But if we can
> find a value that is guaranteed to be unique, why not.
> 
>>> More importantly, you keep suggesting the same "new default", and I
>>> keep saying NO.
>>>
>>> My position is clear: if you want a *new* behaviour, you *must* add a
>>> new flag that the VMM explicitly provides to enable this CC-only PMU.
>>> No change in default behaviour at all.
>>>
>>> I'm not going to move from that.
>>
>> Why not? It will not break anything guaranteed to work in the past.
> 
> It doesn't have to be guaranteed. It just has to *exist*. That's the
> Linux ABI for you.
> 
>> Currently KVM only guarantees that the emulated PMU correctly counts
>> only when
>> 1) the vCPU affinity is contained by one PMU and
>> 2) it will not expand
>>
>> Breaking these conditions will make the behavior of the emulated PMU
>> undefined. Now I'm proposing to remove 1).
> 
> And I'm saying no to that. I'm also getting tired of arguing the same
> point on and on.
> 
> We currently have two different behaviours:
> 
> - either you explicitly set a PMU, and the affinity of this PMU
>    constraints the affinity of the vcpus. The vcpus are not allowed to
>    run outside of this affinity. Everything counts all the time.
> 
> - or you don't explicitly set a PMU, and a default PMU will be picked
>    from the current affinity of the first vcpu. Your vcpus will be able
>    to run anywhere, but the virtual PMU will *only* count when the
>    vcpus are affine to the default PMU. When the vcpus are not affine
>    to default PMU, *nothing* counts.
> 
> These two behaviours are ABI. They are not changing. They don't get
> relaxed, they don't get tightened, they stay just as they are,
> forever.

Is the latter one is really ABI? I see it as part of behaviors that are 
undefined and not included in ABI for the following reasons:

1) It depends on the scheduler behavior, which cannot be ABI.

2) It provides a broken PMU so the proposed behavioral change is similar 
a bug fix though I call it a undefined behavior instead of a bug as it 
is explicitly told that there is no assurance that the PMU works in such 
a scenario.

3) The userspace could not have relied on it so the "no regressions" 
rule cannot be applied here; how can anyone have a userspace that relies 
on a kernel behavior that depends on scheduling?

But for 3), Oliver raised a concern for the guest compatibility so I'd 
like to hear an explanation for that concern.

> 
> You want a *third* behaviour, go ahead. Define it the way you want.
> But the behaviours described above will stay unchanged.> > I'm looking forward to your patches implementing it, but I am also
> done arguing on it.

I understand the discussion is tiring but I want to know the reasoning 
behind such a design decision before sending an RFC patch to a VMM 
(QEMU) so that I can explain them why it is necessary in turn.

Regards,
Akihiko Odaki

> 
> 	M.
> 



From Hailong.Fan at mediatek.com  Thu Mar 20 23:25:53 2025
From: Hailong.Fan at mediatek.com (=?utf-8?B?SGFpbG9uZyBGYW4gKOiMg+a1t+m+mSk=?=)
Date: Fri, 21 Mar 2025 06:25:53 +0000
Subject: [PATCH 1/2] ASoC: SOF: MediaTek: Add mt8196 hardware support
In-Reply-To: <816dd6ea-0e5f-4d8f-a5eb-99d0670e0d43@collabora.com>
References: <20250320031753.13669-1-hailong.fan@mediatek.com>
	 <20250320031753.13669-2-hailong.fan@mediatek.com>
	 <816dd6ea-0e5f-4d8f-a5eb-99d0670e0d43@collabora.com>
Message-ID: <4453bb45cdb0553639846e8be2c51c57565ea90f.camel@mediatek.com>

On Thu, 2025-03-20 at 12:57 +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 20/03/25 04:17, hailong.fan ha scritto:
> > Add support of SOF on MediaTek mt8196 SoC.
> > MT8196 has a Cadence HiFi-5 DSP core that is responsible for
> > running the
> > operating system and application programs. The IPC communication
> > between
> > the AP and DSP is based on shared DRAM and mailbox interrupt.
> > 
> > Signed-off-by: hailong.fan <hailong.fan at mediatek.com>
> 
> Hello Hailong,
> 
> after seeing this series, I acknowledged that the functions that were
> duplicated
> between MT8188 and MT8195 are, in reality, common between more than
> just those,
> as they are the same in your submission for MT8196.
> 
> Therefore, I've send a commit that commonizes those, reducing useless
> code
> duplication.
> 
> Can you please rebase your series on top of [1]?
> 
> Thanks,
> Angelo
> 
> [1]:
> 
https://lore.kernel.org/all/20250320115300.137410-1-angelogioacchino.delregno at collabora.com/
OK, I will rewrite, test ASAP, and then submit the v2 version, thanks a
lot.
> 

From changyuanl at google.com  Thu Mar 20 23:33:56 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Thu, 20 Mar 2025 23:33:56 -0700
Subject: [PATCH v5 16/16] Documentation: add documentation for KHO
In-Reply-To: <87wmcj69sg.fsf@trenco.lwn.net>
References: <87wmcj69sg.fsf@trenco.lwn.net>
Message-ID: <20250321063356.381646-1-changyuanl@google.com>

Hi Jonathan,

On Thu, Mar 20, 2025 at 08:45:03 -0600, Jonathan Corbet <corbet at lwn.net> wrote:
> Changyuan Lyu <changyuanl at google.com> writes:
>
> > From: Alexander Graf <graf at amazon.com>
> >
> > With KHO in place, let's add documentation that describes what it is and
> > how to use it.
> >
> > Signed-off-by: Alexander Graf <graf at amazon.com>
> > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> > ---
> >  .../admin-guide/kernel-parameters.txt         |  25 ++++
> >  Documentation/kho/concepts.rst                |  70 +++++++++++
> >  Documentation/kho/fdt.rst                     |  62 +++++++++
> >  Documentation/kho/index.rst                   |  14 +++
> >  Documentation/kho/usage.rst                   | 118 ++++++++++++++++++
> >  Documentation/subsystem-apis.rst              |   1 +
> >  MAINTAINERS                                   |   1 +
> >  7 files changed, 291 insertions(+)
> >  create mode 100644 Documentation/kho/concepts.rst
> >  create mode 100644 Documentation/kho/fdt.rst
> >  create mode 100644 Documentation/kho/index.rst
> >  create mode 100644 Documentation/kho/usage.rst
>
> I will ask again: please let's not create another top-level docs
> directory for this...?  It looks like it belongs in the admin guide to
> me.

Thanks for review the patch! Sure I will move usage.rst to
Documentation/admin-guide in the next version.

However, I think concepts.rst and fdt.rst are not not end-user oriented,
but for kernel developers of other subsystems to use KHO API (I also plan
to include the kernel-doc generated from kernel/kexec_handover.c and
include/linux/kexec_handover.h here in the next version).
Should Documentation/core-api be a better choice?

Best,
Changyuan


From quic_zhenhuah at quicinc.com  Fri Mar 21 00:00:19 2025
From: quic_zhenhuah at quicinc.com (Zhenhua Huang)
Date: Fri, 21 Mar 2025 15:00:19 +0800
Subject: [PATCH] arm64: mm: Correct the update of max_pfn
Message-ID: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>

Hotplugged memory can be smaller than the original memory. For example,
on my target:

root at genericarmv8:~# cat /sys/kernel/debug/memblock/memory
   0: 0x0000000064005000..0x0000000064023fff    0 NOMAP
   1: 0x0000000064400000..0x00000000647fffff    0 NOMAP
   2: 0x0000000068000000..0x000000006fffffff    0 DRV_MNG
   3: 0x0000000088800000..0x0000000094ffefff    0 NONE
   4: 0x0000000094fff000..0x0000000094ffffff    0 NOMAP
max_pfn will affect read_page_owner. Therefore, it should first compare and
then select the larger value for max_pfn.

Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug")
Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
---
 arch/arm64/mm/mmu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 1dfe1a8efdbe..310ff75891ef 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size,
 		__remove_pgd_mapping(swapper_pg_dir,
 				     __phys_to_virt(start), size);
 	else {
-		max_pfn = PFN_UP(start + size);
+		/* Address of hotplugged memory can be smaller */
+		max_pfn = max(max_pfn, PFN_UP(start + size));
 		max_low_pfn = max_pfn;
 	}
 
-- 
2.25.1



From jpoimboe at kernel.org  Fri Mar 21 00:11:55 2025
From: jpoimboe at kernel.org (Josh Poimboeuf)
Date: Fri, 21 Mar 2025 00:11:55 -0700
Subject: [PATCH v3 1/2] arm64: Implement arch_stack_walk_reliable
In-Reply-To: <20250320171559.3423224-2-song@kernel.org>
References: <20250320171559.3423224-1-song@kernel.org>
 <20250320171559.3423224-2-song@kernel.org>
Message-ID: <etrj2xdtc6djnwtwlghymlu4c3gg5wnyg3qqfdiod4g6hjgzzi@yxj6no3stqjv>

On Thu, Mar 20, 2025 at 10:15:58AM -0700, Song Liu wrote:
> With proper exception boundary detection, it is possible to implment
> arch_stack_walk_reliable without sframe.
> 
> Note that, arch_stack_walk_reliable does not guarantee getting reliable
> stack in all scenarios. Instead, it can reliably detect when the stack
> trace is not reliable, which is enough to provide reliable livepatching.
> 
> Signed-off-by: Song Liu <song at kernel.org>

Reviewed-by: Josh Poimboeuf <jpoimboe at kernel.org>

-- 
Josh


From praan at google.com  Fri Mar 21 00:18:15 2025
From: praan at google.com (Pranjal Shrivastava)
Date: Fri, 21 Mar 2025 07:18:15 +0000
Subject: [PATCH] iommu: Split out and tidy up Arm Kconfig
In-Reply-To: <a614ec86ba78c09cd16e348f633f6bb38793391f.1742480488.git.robin.murphy@arm.com>
References: <a614ec86ba78c09cd16e348f633f6bb38793391f.1742480488.git.robin.murphy@arm.com>
Message-ID: <Z90St0D6hyphtOID@google.com>

On Thu, Mar 20, 2025 at 02:21:28PM +0000, Robin Murphy wrote:
> There are quite a lot of options for the Arm drivers, still all buried
> in the top-level Kconfig. For ease of use and consistency with all the
> other subdirectories, break these out into drivers/arm. For similar
> clarity and self-consistency, also tweak the ARM_SMMU sub-options to use
> "if" instead of "depends", to match ARM_SMMU_V3. Lastly also clean up
> the slightly messy description of ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT as
> highlighted by Geert - by now we really shouldn't need commentary on
> v4.x kernel behaviour anyway - and downgrade it to EXPERT as the first
> step in the 6-year-old threat to remove it entirely.
> 
> Cc: Geert Uytterhoeven <geert+renesas at glider.be>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/iommu/Kconfig     | 157 +-------------------------------------
>  drivers/iommu/arm/Kconfig | 144 ++++++++++++++++++++++++++++++++++
>  2 files changed, 145 insertions(+), 156 deletions(-)
>  create mode 100644 drivers/iommu/arm/Kconfig
> 

Thanks for this! It looks good.
I was able to toggle configs and build for arm64.

> +
> +config QCOM_IOMMUa
Nit: I don't have much context but:

1. Shall this be in .../arm/Kconfig? Is this an custom
implementation of some arm-smmu version? If yes, then maybe we can
update the help string while at it?

> +	# Note: iommu drivers cannot (yet?) be built as modules

2. I don't think this is true now? Shall we remove this comment?

> +	bool "Qualcomm IOMMU Support"
> +	depends on ARCH_QCOM || COMPILE_TEST
> +	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
> +	select QCOM_SCM
> +	select IOMMU_API
> +	select IOMMU_IO_PGTABLE_LPAE
> +	select ARM_DMA_USE_IOMMU
> +	help
> +	  Support for IOMMU on certain Qualcomm SoCs.
> 

With the above nits:

Reviewed-by: Pranjal Shrivastava <praan at google.com>

Thanks,
Praan


From linus.walleij at linaro.org  Fri Mar 21 00:24:36 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Fri, 21 Mar 2025 08:24:36 +0100
Subject: [PATCH v3] arm: rust: Enable Rust support for ARMv7
In-Reply-To: <20250123-rfl-arm32-v3-1-8f13623d42c5@gmail.com>
References: <20250123-rfl-arm32-v3-1-8f13623d42c5@gmail.com>
Message-ID: <CACRpkdYF0sVB2-qgy=GzETSR3+2sagVQPGdunDQDJrn8KqJorA@mail.gmail.com>

Hi Christian,

thanks for your patch!

Sorry for being late to the show. I missed this very nice patch
that was actually on my personal TODO but I have to much
to do and also I'm not smart with Rust, but I'm a big supporter.

On Thu, Jan 23, 2025 at 11:40?PM Christian Schrefl
<chrisi.schrefl at gmail.com> wrote:

> +       select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7

Nothing in the patch series really explains this restriction, so it
should be in the commit message. Arnd mentions some atomics
etc, but we really need to know exactly why this is in the patch.

I'm a bit surprised by this since the rustc LLVM backend nowadays
support all old ARM ISAs. I would have expected:

select HAVE_RUST if AEABI

Ideally this should work on any ARM core, but it's fair to require
EABI.

The big reason: I think we want to be able to use Rust in kernel
core components sooner than ARMv5 goes away from the kernel.

If testing is the only issue, I can provide testing on ARMv4, v5,
ARMv5 BE etc, just tell me how to test. (But I guess it's more than
that...)

Yours,
Linus Walleij


From m-malladi at ti.com  Fri Mar 21 01:13:10 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Fri, 21 Mar 2025 13:43:10 +0530
Subject: [PATCH net-next v2 0/3] Bug fixes from XDP and perout series
Message-ID: <20250321081313.37112-1-m-malladi@ti.com>

This patch series consists of bug fixes from the features which recently
got merged into net-next, and haven't been merged to net tree yet.

Patch 2/3 and 3/3 are bug fixes reported by Dan Carpenter
<dan.carpenter at linaro.org> using Smatch static checker.

Meghana Malladi (3):
  net: ti: prueth: Fix kernel warning while bringing down network
    interface
  net: ti: prueth: Fix possible NULL pointer dereference inside
    emac_xmit_xdp_frame()
  net: ti: icss-iep: Fix possible NULL pointer dereference for perout
    request

 drivers/net/ethernet/ti/icssg/icss_iep.c     | 4 ++++
 drivers/net/ethernet/ti/icssg/icssg_common.c | 9 ++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)


base-commit: 6f13bec53a48c7120dc6dc358cacea13251a471f
-- 
2.43.0



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:01 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:01 +0800
Subject: [PATCH v6 00/10] ARM: dts: aspeed: catalina: Update DTS to support
 Catalina PVT hardware
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>

Update the DTS file for the Catalina platform based on the PVT hardware
changes.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
Changes in v6:
- Rename the fan controller nodes with appropriate name
- Link to v5: https://lore.kernel.org/r/20250320-potin-catalina-dts-update-20250102-v5-0-e161be6583a7 at gmail.com

Changes in v5:
- Revise CBC FRU eeprom i2c bus and address
- Add MCTP support for backend NIC monitoring via PLDM over MCTP
- Link to v4: https://lore.kernel.org/r/20250320-potin-catalina-dts-update-20250102-v4-0-7c34b8139014 at gmail.com

Changes in v4:
- Split a single commit into multiple smaller commits to reduce complexity.
- Add `multi-master` into i2c12 & i2c13  
- Link to v3: https://lore.kernel.org/r/20250114-potin-catalina-dts-update-20250102-v3-1-14981744b2fe at gmail.com

Changes in v3:
- Remove delta_brick nodes due to compatible string not supported
- Link to v2: https://lore.kernel.org/r/20250113-potin-catalina-dts-update-20250102-v2-1-1725117fe7a9 at gmail.com

Changes in v2:
- Add delta_brick nodes to support PDB brick board
- Link to v1: https://lore.kernel.org/r/20250103-potin-catalina-dts-update-20250102-v1-1-b0b7a523c968 at gmail.com

---
Potin Lai (10):
      ARM: dts: aspeed: catalina: Add IO Mezz board thermal sensor nodes
      ARM: dts: aspeed: catalina: Add Front IO board remote thermal sensor
      ARM: dts: aspeed: catalina: Add MP5990 power sensor node
      ARM: dts: aspeed: catalina: Add fan controller support
      ARM: dts: aspeed: catalina: Add second source fan controller support
      ARM: dts: aspeed: catalina: Add second source HSC node support
      ARM: dts: aspeed: catalina: Remove INA238 and INA230 nodes
      ARM: dts: aspeed: catalina: Enable multi-master on additional I2C buses
      ARM: dts: aspeed: catalina: Update CBC FRU EEPROM I2C bus and address
      ARM: dts: aspeed: catalina: Enable MCTP support for NIC management

 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 197 +++++++++++++++------
 1 file changed, 144 insertions(+), 53 deletions(-)
---
base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
change-id: 20250102-potin-catalina-dts-update-20250102-914b06a4bdba

Best regards,
-- 
Potin Lai <potin.lai.pt at gmail.com>



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:02 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:02 +0800
Subject: [PATCH v6 01/10] ARM: dts: aspeed: catalina: Add IO Mezz board
 thermal sensor nodes
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-1-4bd85efeb9b4@gmail.com>

Add thermal sensor nodes for the IO Mezzanine (IO Mezz) board in the
Catalina platform device tree. These nodes enable temperature monitoring
for the backend NIC, improving thermal management and monitoring
capabilities.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index c151984289bc..d5d99a945ee4 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -198,6 +198,12 @@ i2c0mux0ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB0 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -208,6 +214,12 @@ i2c0mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB0 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux0ch3: i2c at 3 {
 			#address-cells = <1>;
@@ -299,6 +311,12 @@ i2c0mux3ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+
+			// IOB1 NIC0 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch1: i2c at 1 {
 			#address-cells = <1>;
@@ -309,6 +327,12 @@ i2c0mux3ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+
+			// IOB1 NIC1 TEMP
+			temperature-sensor at 1f {
+				compatible = "ti,tmp421";
+				reg = <0x1f>;
+			};
 		};
 		i2c0mux3ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:03 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:03 +0800
Subject: [PATCH v6 02/10] ARM: dts: aspeed: catalina: Add Front IO board
 remote thermal sensor
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-2-4bd85efeb9b4@gmail.com>

Add a remote thermal sensor node for the Front IO board in the Catalina
platform device tree. This sensor enables monitoring of the inlet
temperature.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index d5d99a945ee4..307af99e833c 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -544,6 +544,12 @@ temperature-sensor at 4b {
 				compatible = "ti,tmp75";
 				reg = <0x4b>;
 			};
+
+			// FIO REMOTE TEMP SENSOR
+			temperature-sensor at 4f {
+				compatible = "ti,tmp75";
+				reg = <0x4f>;
+			};
 		};
 	};
 };

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:04 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:04 +0800
Subject: [PATCH v6 03/10] ARM: dts: aspeed: catalina: Add MP5990 power
 sensor node
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-3-4bd85efeb9b4@gmail.com>

Add a device tree node for the MP5990 power sensor to enable monitoring of
the P12V supplying power to the fans.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 307af99e833c..f5f47245796a 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -428,6 +428,10 @@ i2c1mux0ch0: i2c at 0 {
 			#size-cells = <0>;
 			reg = <0x0>;
 
+			power-sensor at 22 {
+				compatible = "mps,mp5990";
+				reg = <0x22>;
+			};
 			power-sensor at 41 {
 				compatible = "ti,ina238";
 				reg = <0x41>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:05 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:05 +0800
Subject: [PATCH v6 04/10] ARM: dts: aspeed: catalina: Add fan controller
 support
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-4-4bd85efeb9b4@gmail.com>

Add device tree nodes for the MAX31790 fan controllers on the Power
Distribution Board (PDB). These nodes enable fan speed control and
monitoring, improving thermal management and system reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index f5f47245796a..792b739b1103 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -466,6 +466,15 @@ i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x2>;
+
+			fanctl0: fan-controller at 21{
+				compatible = "maxim,max31790";
+				reg = <0x21>;
+			};
+			fanctl1: fan-controller at 27{
+				compatible = "maxim,max31790";
+				reg = <0x27>;
+			};
 		};
 		i2c1mux0ch3: i2c at 3 {
 			#address-cells = <1>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:06 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:06 +0800
Subject: [PATCH v6 05/10] ARM: dts: aspeed: catalina: Add second source fan
 controller support
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-5-4bd85efeb9b4@gmail.com>

Add device tree nodes for the NCT7363 fan controllers on the second-source
Power Distribution Board (PDB).

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 792b739b1103..f0c8aca152e7 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -467,6 +467,82 @@ i2c1mux0ch2: i2c at 2 {
 			#size-cells = <0>;
 			reg = <0x2>;
 
+			fanctl2: fan-controller at 1 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x01>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&fanctl2 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&fanctl2 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&fanctl2 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&fanctl2 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&fanctl2 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&fanctl2 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&fanctl2 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&fanctl2 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
+			fanctl3: fan-controller at 2 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x02>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&fanctl3 0 40000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+				fan-11 {
+					pwms = <&fanctl3 0 40000>;
+					tach-ch = /bits/ 8 <0x0b>;
+				};
+				fan-10 {
+					pwms = <&fanctl3 4 40000>;
+					tach-ch = /bits/ 8 <0x0a>;
+				};
+				fan-13 {
+					pwms = <&fanctl3 4 40000>;
+					tach-ch = /bits/ 8 <0x0d>;
+				};
+				fan-15 {
+					pwms = <&fanctl3 6 40000>;
+					tach-ch = /bits/ 8 <0x0f>;
+				};
+				fan-1 {
+					pwms = <&fanctl3 6 40000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+				fan-0 {
+					pwms = <&fanctl3 10 40000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+				fan-3 {
+					pwms = <&fanctl3 10 40000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
 			fanctl0: fan-controller at 21{
 				compatible = "maxim,max31790";
 				reg = <0x21>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:07 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:07 +0800
Subject: [PATCH v6 06/10] ARM: dts: aspeed: catalina: Add second source HSC
 node support
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-6-4bd85efeb9b4@gmail.com>

Add device tree nodes for the XDP710 Hot-Swap Controller (HSC) to support
the Power Distribution Board (PDB) with a second-source configuration.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index f0c8aca152e7..306931c08cb0 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -562,6 +562,14 @@ i2c1mux0ch4: i2c at 4 {
 			#size-cells = <0>;
 			reg = <0x4>;
 
+			power-monitor at 13 {
+				compatible = "infineon,xdp710";
+				reg = <0x13>;
+			};
+			power-monitor at 1c {
+				compatible = "infineon,xdp710";
+				reg = <0x1c>;
+			};
 			power-monitor at 42 {
 				compatible = "lltc,ltc4287";
 				reg = <0x42>;

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:08 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:08 +0800
Subject: [PATCH v6 07/10] ARM: dts: aspeed: catalina: Remove INA238 and
 INA230 nodes
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-7-4bd85efeb9b4@gmail.com>

Remove INA238 and INA230 power sensor nodes from the device tree (DTS) due
to incompatibility with the second-source ISL28022, which shares the same
I2C address.

Move the driver probe to userspace to handle sensor dynamically.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 .../dts/aspeed/aspeed-bmc-facebook-catalina.dts    | 45 ----------------------
 1 file changed, 45 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 306931c08cb0..6702be32918e 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -432,35 +432,11 @@ power-sensor at 22 {
 				compatible = "mps,mp5990";
 				reg = <0x22>;
 			};
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 42 {
-				compatible = "ti,ina238";
-				reg = <0x42>;
-				shunt-resistor = <500>;
-			};
-			power-sensor at 44 {
-				compatible = "ti,ina238";
-				reg = <0x44>;
-				shunt-resistor = <500>;
-			};
 		};
 		i2c1mux0ch1: i2c at 1 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x1>;
-
-			power-sensor at 41 {
-				compatible = "ti,ina238";
-				reg = <0x41>;
-			};
-			power-sensor at 43 {
-				compatible = "ti,ina238";
-				reg = <0x43>;
-			};
 		};
 		i2c1mux0ch2: i2c at 2 {
 			#address-cells = <1>;
@@ -753,27 +729,6 @@ i2c5mux0ch7: i2c at 7 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <7>;
-
-			power-sensor at 40 {
-				compatible = "ti,ina230";
-				reg = <0x40>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 41 {
-				compatible = "ti,ina230";
-				reg = <0x41>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 44 {
-				compatible = "ti,ina230";
-				reg = <0x44>;
-				shunt-resistor = <2000>;
-			};
-			power-sensor at 45 {
-				compatible = "ti,ina230";
-				reg = <0x45>;
-				shunt-resistor = <2000>;
-			};
 		};
 	};
 };

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:10 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:10 +0800
Subject: [PATCH v6 09/10] ARM: dts: aspeed: catalina: Update CBC FRU EEPROM
 I2C bus and address
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-9-4bd85efeb9b4@gmail.com>

Revise the I2C bus and address for the Cable Backplane Cartridge (CBC)
FRU EEPROM in the Catalina device tree.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 2dbb65db9250..a6a2dd725266 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -822,6 +822,12 @@ eeprom at 50 {
 		compatible = "atmel,24c64";
 		reg = <0x50>;
 	};
+
+	// Secondary CBC FRU EEPROM
+	eeprom at 54 {
+		compatible = "atmel,24c02";
+		reg = <0x54>;
+	};
 };
 
 &i2c13 {
@@ -834,18 +840,12 @@ eeprom at 50 {
 		reg = <0x50>;
 	};
 
-	// Left CBC FRU EEPROM
+	// Primary CBC FRU EEPROM
 	eeprom at 54 {
 		compatible = "atmel,24c02";
 		reg = <0x54>;
 	};
 
-	// Right CBC FRU EEPROM
-	eeprom at 55 {
-		compatible = "atmel,24c02";
-		reg = <0x55>;
-	};
-
 	// HMC FRU EEPROM
 	eeprom at 57 {
 		compatible = "atmel,24c02";

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:09 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:09 +0800
Subject: [PATCH v6 08/10] ARM: dts: aspeed: catalina: Enable multi-master
 on additional I2C buses
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-8-4bd85efeb9b4@gmail.com>

Update the device tree to enable `multi-master` mode on I2C buses shared
between the host BMC and the NV module with HMC. This ensures proper bus
arbitration and coordination in multi-master environments, preventing
communication conflicts and improving reliability.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index 6702be32918e..2dbb65db9250 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -815,6 +815,7 @@ ssif-bmc at 10 {
 
 &i2c12 {
 	status = "okay";
+	multi-master;
 
 	// Module 1 FRU EEPROM
 	eeprom at 50 {
@@ -825,6 +826,7 @@ eeprom at 50 {
 
 &i2c13 {
 	status = "okay";
+	multi-master;
 
 	// Module 0 FRU EEPROM
 	eeprom at 50 {

-- 
2.31.1



From potin.lai.pt at gmail.com  Fri Mar 21 00:26:11 2025
From: potin.lai.pt at gmail.com (Potin Lai)
Date: Fri, 21 Mar 2025 15:26:11 +0800
Subject: [PATCH v6 10/10] ARM: dts: aspeed: catalina: Enable MCTP support
 for NIC management
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <20250321-potin-catalina-dts-update-20250102-v6-10-4bd85efeb9b4@gmail.com>

Add the `mctp-controller` property and MCTP nodes to enable support for
backend NIC management via PLDM over MCTP.

Signed-off-by: Potin Lai <potin.lai.pt at gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
index a6a2dd725266..5fb67ad2d777 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts
@@ -186,18 +186,23 @@ flash at 1 {
 
 &i2c0 {
 	status = "okay";
+	multi-master;
+	mctp at 10 {
+		compatible = "mctp-i2c-controller";
+		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+	};
 
 	i2c-mux at 71 {
 		compatible = "nxp,pca9546";
 		reg = <0x71>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		i2c-mux-idle-disconnect;
 
 		i2c0mux0ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+			mctp-controller;
 
 			// IOB0 NIC0 TEMP
 			temperature-sensor at 1f {
@@ -214,6 +219,7 @@ i2c0mux0ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+			mctp-controller;
 
 			// IOB0 NIC1 TEMP
 			temperature-sensor at 1f {
@@ -305,12 +311,12 @@ i2c-mux at 75 {
 		reg = <0x75>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		i2c-mux-idle-disconnect;
 
 		i2c0mux3ch0: i2c at 0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
+			mctp-controller;
 
 			// IOB1 NIC0 TEMP
 			temperature-sensor at 1f {
@@ -327,6 +333,7 @@ i2c0mux3ch2: i2c at 2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
+			mctp-controller;
 
 			// IOB1 NIC1 TEMP
 			temperature-sensor at 1f {

-- 
2.31.1



From m.szyprowski at samsung.com  Fri Mar 21 00:35:09 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Fri, 21 Mar 2025 08:35:09 +0100
Subject: [Patch v2] media: s5p-mfc: Support for handling
 RET_ENC_BUFFER_FULL interrupt
In-Reply-To: <20250305055308.111300-2-aakarsh.jain@samsung.com>
References: <20250305055308.111300-1-aakarsh.jain@samsung.com>
	<CGME20250305055908epcas5p222e192cc21512ac178543445184a2519@epcas5p2.samsung.com>
	<20250305055308.111300-2-aakarsh.jain@samsung.com>
Message-ID: <33f85cd5-8387-4358-b2d4-29f8877a7e2e@samsung.com>

On 05.03.2025 06:53, Aakarsh Jain wrote:
> When output encoded buffer size provided by userspace
> is insufficient with current encoding parameters, it
> leads to RET_ENC_BUFFER_FULL interrupt which was not
> handled in IRQ handler.
>
> On handling of RET_ENC_BUFFER_FULL interrupt leads to
> NAL_ABORT command from host to risc which in turn leads
> to RET_NAL_ABORT interrupt. On receiving RET_NAL_ABORT
> driver clears workbit and VB2 queues for cleaner closing
> of MFC instance.
>
> When user encounters "Call on DQBUF after unrecoverable
> error", userspace should close fd and restart with larger
> output encoder buffer size.
>
> Signed-off-by: Aakarsh Jain <aakarsh.jain at samsung.com>
Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>
> ---
> changelog:
> v1->v2
> Patch link: https://patchwork.kernel.org/project/linux-media/patch/20250228065952.14375-1-aakarsh.jain at samsung.com/
> Fixed build errors reported by Media CI robot.
>   .../media/platform/samsung/s5p-mfc/regs-mfc-v6.h   |  1 +
>   drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c   | 14 ++++++++++++++
>   .../platform/samsung/s5p-mfc/s5p_mfc_common.h      |  1 +
>   .../platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c      |  5 +++++
>   4 files changed, 21 insertions(+)
>
> diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
> index fa49fe580e1a..075a58b50b8c 100644
> --- a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
> +++ b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
> @@ -45,6 +45,7 @@
>   #define S5P_FIMV_H2R_CMD_WAKEUP_V6		8
>   #define S5P_FIMV_CH_LAST_FRAME_V6		9
>   #define S5P_FIMV_H2R_CMD_FLUSH_V6		10
> +#define S5P_FIMV_H2R_CMD_NAL_ABORT_V6		11
>   /* RMVME: REALLOC used? */
>   #define S5P_FIMV_CH_FRAME_START_REALLOC_V6	5
>   
> diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
> index 5f80931f056d..e764cab2485c 100644
> --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
> @@ -739,6 +739,20 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
>   		ctx->state = MFCINST_RUNNING;
>   		goto irq_cleanup_hw;
>   
> +	case S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET:
> +		ctx->state = MFCINST_NAL_ABORT;
> +		s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> +		set_work_bit(ctx);
> +		WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
> +		s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
> +		break;
> +
> +	case S5P_MFC_R2H_CMD_NAL_ABORT_RET:
> +		ctx->state = MFCINST_ERROR;
> +		s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
> +		s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
> +		goto irq_cleanup_hw;
> +
>   	default:
>   		mfc_debug(2, "Unknown int reason\n");
>   		s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
> diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
> index 3cc2a4f5c40a..86c316c1ff8f 100644
> --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
> @@ -141,6 +141,7 @@ enum s5p_mfc_inst_state {
>   	MFCINST_RES_CHANGE_INIT,
>   	MFCINST_RES_CHANGE_FLUSH,
>   	MFCINST_RES_CHANGE_END,
> +	MFCINST_NAL_ABORT,
>   };
>   
>   /*
> diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
> index 4cf12f33d706..356adfddcfcf 100644
> --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
> +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
> @@ -2229,6 +2229,11 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
>   		case MFCINST_HEAD_PRODUCED:
>   			ret = s5p_mfc_run_init_enc_buffers(ctx);
>   			break;
> +		case MFCINST_NAL_ABORT:
> +			mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
> +			s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc,
> +					dev, S5P_FIMV_H2R_CMD_NAL_ABORT_V6, NULL);
> +			break;
>   		default:
>   			ret = -EAGAIN;
>   		}

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From krzk at kernel.org  Fri Mar 21 00:36:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 08:36:53 +0100
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for
 PCIe3
In-Reply-To: <20250320055502.274849-2-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com>
Message-ID: <694b6638-92b2-4ac0-a175-bd29aea6cba9@kernel.org>

On 20/03/2025 06:55, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Enable the pwrctrl driver, which is utilized to manage the power supplies
> of the devices connected to the PCI slots. This ensures that the voltage
> rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
> on/off if they are described under PCIe port device tree node.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>  arch/arm64/configs/defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 85ec2fba1..de86d1121 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
>  CONFIG_PCI_ENDPOINT=y
>  CONFIG_PCI_ENDPOINT_CONFIGFS=y
>  CONFIG_PCI_EPF_TEST=m
> +CONFIG_PCI_PWRCTL_SLOT=y
Bartosz,

Wasn't the intention to select it the same way as PCI_PWRCTL_PWRSEQ is
selected?

Best regards,
Krzysztof


From yangyicong at huawei.com  Fri Mar 21 00:38:44 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:44 +0800
Subject: [PATCH v2 6/8] drivers/perf: hisi: Support PMUs with no interrupt
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-7-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

We'll have PMUs don't have an interrupt to indicate the counter
overflow, but the Uncore PMU core assume all the PMUs have
interrupt. So handle this case in the core. The existing PMUs
won't be affected.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_pmu.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index ef058b1dd509..a449651f79c9 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -510,7 +510,9 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
 			return 0;
 
 		hisi_pmu->on_cpu = cpumask_local_spread(0, dev_to_node(hisi_pmu->dev));
-		WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(hisi_pmu->on_cpu)));
+		if (hisi_pmu->irq > 0)
+			WARN_ON(irq_set_affinity(hisi_pmu->irq,
+						 cpumask_of(hisi_pmu->on_cpu)));
 		return 0;
 	}
 
@@ -525,7 +527,8 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
 	hisi_pmu->on_cpu = cpu;
 
 	/* Overflow interrupt also should use the same CPU */
-	WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu)));
+	if (hisi_pmu->irq > 0)
+		WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu)));
 
 	return 0;
 }
@@ -560,7 +563,9 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
 	perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target);
 	/* Use this CPU for event counting */
 	hisi_pmu->on_cpu = target;
-	WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target)));
+
+	if (hisi_pmu->irq > 0)
+		WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target)));
 
 	return 0;
 }
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:38 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:38 +0800
Subject: [PATCH v2 0/8] General updates and two new drivers for HiSilicon Uncore PMU
Message-ID: <20250321073846.23507-1-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Support new version of DDRC/SLLC PMU identified with updated ACPI HID and
register definition. In order to support this, we do a preliminary refactor
to initialize device of each version by using driver data of each HID
rather than checking the version. This will also make the driver easier to
maintain and extend, since only the HID specific information along
with the new HID will be added to support the new version without touching
the common logic.

Two new Uncore PMU drivers is also added to support the monitoring the
events of the system bus (by NoC PMU) and the DVM opertaions (by MN PMU).

Change since v1:
- Fold patch which extending the struct hisi_pmu_dev_info into its user
- Use bit shift rather than bit mask for SLLC PMU registers configuration
- Address other comments by Jonathan, thanks
Link: https://lore.kernel.org/linux-arm-kernel/20250218092000.41641-1-yangyicong at huawei.com/

Junhao He (6):
  drivers/perf: hisi: Simplify the probe process for each DDRC version
  drivers/perf: hisi: Add support for HiSilicon DDRC v3 PMU driver
  drivers/perf: hisi: Use ACPI driver_data to retrieve SLLC PMU
    information
  drivers/perf: hisi: Add support for HiSilicon SLLC v3 PMU driver
  drivers/perf: hisi: Relax the event number check of v2 PMUs
  drivers/perf: hisi: Add support for HiSilicon MN PMU driver

Yicong Yang (2):
  drivers/perf: hisi: Support PMUs with no interrupt
  drivers/perf: hisi: Add support for HiSilicon NoC PMU

 Documentation/admin-guide/perf/hisi-pmu.rst   |  11 +
 drivers/perf/hisilicon/Makefile               |   3 +-
 drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 354 ++++++++--------
 drivers/perf/hisilicon/hisi_uncore_hha_pmu.c  |   6 +-
 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c   | 355 ++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c  | 392 ++++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_pa_pmu.c   |   2 +-
 drivers/perf/hisilicon/hisi_uncore_pmu.c      |  11 +-
 drivers/perf/hisilicon/hisi_uncore_pmu.h      |   2 +
 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 220 +++++++---
 10 files changed, 1098 insertions(+), 258 deletions(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c

-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:41 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:41 +0800
Subject: [PATCH v2 3/8] drivers/perf: hisi: Use ACPI driver_data to retrieve SLLC PMU information
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-4-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

Make use of struct acpi_device_id::driver_data for version specific
information rather than judge the version register. This will help
to simplify the probe process and also a bit easier for extension.

Factor out SLLC register definition to struct hisi_sllc_pmu_regs.
No functional changes intended.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 178 ++++++++++++------
 1 file changed, 118 insertions(+), 60 deletions(-)

diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index dbd079016fc4..79327639ec17 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -41,6 +41,7 @@
 #define SLLC_SRCID_CMD_SHIFT		1
 #define SLLC_SRCID_MSK_SHIFT		12
 #define SLLC_NR_EVENTS			0x80
+#define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
 
 HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0);
 HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_max, config1, 21, 11);
@@ -48,6 +49,23 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
 HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
 
+struct hisi_sllc_pmu_regs {
+	u32 int_mask;
+	u32 int_clear;
+	u32 int_status;
+	u32 perf_ctrl;
+	u32 srcid_ctrl;
+	u32 srcid_cmd_shift;
+	u32 srcid_mask_shift;
+	u32 tgtid_ctrl;
+	u32 tgtid_min_shift;
+	u32 tgtid_max_shift;
+	u32 event_ctrl;
+	u32 event_type0;
+	u32 version;
+	u32 event_cnt0;
+};
+
 static bool tgtid_is_valid(u32 max, u32 min)
 {
 	return max > 0 && max >= min;
@@ -56,96 +74,104 @@ static bool tgtid_is_valid(u32 max, u32 min)
 static void hisi_sllc_pmu_enable_tracetag(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 tt_en = hisi_get_tracetag_en(event);
 
 	if (tt_en) {
 		u32 val;
 
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val |= SLLC_TRACETAG_EN | SLLC_FILT_EN;
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
 static void hisi_sllc_pmu_disable_tracetag(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 tt_en = hisi_get_tracetag_en(event);
 
 	if (tt_en) {
 		u32 val;
 
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val &= ~(SLLC_TRACETAG_EN | SLLC_FILT_EN);
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
 static void hisi_sllc_pmu_config_tgtid(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 min = hisi_get_tgtid_min(event);
 	u32 max = hisi_get_tgtid_max(event);
 
 	if (tgtid_is_valid(max, min)) {
-		u32 val = (max << SLLC_TGTID_MAX_SHIFT) | (min << SLLC_TGTID_MIN_SHIFT);
+		u32 val = (max << regs->tgtid_max_shift) |
+			  (min << regs->tgtid_min_shift);
 
-		writel(val, sllc_pmu->base + SLLC_TGTID_CTRL);
+		writel(val, sllc_pmu->base + regs->tgtid_ctrl);
 		/* Enable the tgtid */
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val |= SLLC_TGTID_EN | SLLC_FILT_EN;
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
 static void hisi_sllc_pmu_clear_tgtid(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 min = hisi_get_tgtid_min(event);
 	u32 max = hisi_get_tgtid_max(event);
 
 	if (tgtid_is_valid(max, min)) {
 		u32 val;
 
-		writel(SLLC_TGTID_NONE, sllc_pmu->base + SLLC_TGTID_CTRL);
+		writel(SLLC_TGTID_NONE, sllc_pmu->base + regs->tgtid_ctrl);
 		/* Disable the tgtid */
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val &= ~(SLLC_TGTID_EN | SLLC_FILT_EN);
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
 static void hisi_sllc_pmu_config_srcid(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 cmd = hisi_get_srcid_cmd(event);
 
 	if (cmd) {
 		u32 val, msk;
 
 		msk = hisi_get_srcid_msk(event);
-		val = (cmd << SLLC_SRCID_CMD_SHIFT) | (msk << SLLC_SRCID_MSK_SHIFT);
-		writel(val, sllc_pmu->base + SLLC_SRCID_CTRL);
+		val = (cmd << regs->srcid_cmd_shift) |
+		      (msk << regs->srcid_mask_shift);
+		writel(val, sllc_pmu->base + regs->srcid_ctrl);
 		/* Enable the srcid */
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val |= SLLC_SRCID_EN | SLLC_FILT_EN;
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
 static void hisi_sllc_pmu_clear_srcid(struct perf_event *event)
 {
 	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 cmd = hisi_get_srcid_cmd(event);
 
 	if (cmd) {
 		u32 val;
 
-		writel(SLLC_SRCID_NONE, sllc_pmu->base + SLLC_SRCID_CTRL);
+		writel(SLLC_SRCID_NONE, sllc_pmu->base + regs->srcid_ctrl);
 		/* Disable the srcid */
-		val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+		val = readl(sllc_pmu->base + regs->perf_ctrl);
 		val &= ~(SLLC_SRCID_EN | SLLC_FILT_EN);
-		writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+		writel(val, sllc_pmu->base + regs->perf_ctrl);
 	}
 }
 
@@ -167,29 +193,27 @@ static void hisi_sllc_pmu_clear_filter(struct perf_event *event)
 	}
 }
 
-static u32 hisi_sllc_pmu_get_counter_offset(int idx)
-{
-	return (SLLC_EVENT_CNT0_L + idx * 8);
-}
-
 static u64 hisi_sllc_pmu_read_counter(struct hisi_pmu *sllc_pmu,
 				      struct hw_perf_event *hwc)
 {
-	return readq(sllc_pmu->base +
-		     hisi_sllc_pmu_get_counter_offset(hwc->idx));
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
+
+	return readq(sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx));
 }
 
 static void hisi_sllc_pmu_write_counter(struct hisi_pmu *sllc_pmu,
 					struct hw_perf_event *hwc, u64 val)
 {
-	writeq(val, sllc_pmu->base +
-	       hisi_sllc_pmu_get_counter_offset(hwc->idx));
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
+
+	writeq(val, sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx));
 }
 
 static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx,
 				       u32 type)
 {
-	u32 reg, reg_idx, shift, val;
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
+	u32 reg, val;
 
 	/*
 	 * Select the appropriate event select register(SLLC_EVENT_TYPE0/1).
@@ -198,96 +222,98 @@ static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx,
 	 * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
 	 * SLLC_EVENT_TYPE1 is chosen.
 	 */
-	reg = SLLC_EVENT_TYPE0 + (idx / 4) * 4;
-	reg_idx = idx % 4;
-	shift = 8 * reg_idx;
+	reg = regs->event_type0 + (idx / 4) * 4;
 
 	/* Write event code to SLLC_EVENT_TYPEx Register */
 	val = readl(sllc_pmu->base + reg);
-	val &= ~(SLLC_EVTYPE_MASK << shift);
-	val |= (type << shift);
+	val &= ~(SLLC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx));
+	val |= (type << HISI_PMU_EVTYPE_SHIFT(idx));
 	writel(val, sllc_pmu->base + reg);
 }
 
 static void hisi_sllc_pmu_start_counters(struct hisi_pmu *sllc_pmu)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+	val = readl(sllc_pmu->base + regs->perf_ctrl);
 	val |= SLLC_PERF_CTRL_EN;
-	writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+	writel(val, sllc_pmu->base + regs->perf_ctrl);
 }
 
 static void hisi_sllc_pmu_stop_counters(struct hisi_pmu *sllc_pmu)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+	val = readl(sllc_pmu->base + regs->perf_ctrl);
 	val &= ~(SLLC_PERF_CTRL_EN);
-	writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+	writel(val, sllc_pmu->base + regs->perf_ctrl);
 }
 
 static void hisi_sllc_pmu_enable_counter(struct hisi_pmu *sllc_pmu,
 					 struct hw_perf_event *hwc)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_EVENT_CTRL);
-	val |= 1 << hwc->idx;
-	writel(val, sllc_pmu->base + SLLC_EVENT_CTRL);
+	val = readl(sllc_pmu->base + regs->event_ctrl);
+	val |= BIT_ULL(hwc->idx);
+	writel(val, sllc_pmu->base + regs->event_ctrl);
 }
 
 static void hisi_sllc_pmu_disable_counter(struct hisi_pmu *sllc_pmu,
 					  struct hw_perf_event *hwc)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_EVENT_CTRL);
-	val &= ~(1 << hwc->idx);
-	writel(val, sllc_pmu->base + SLLC_EVENT_CTRL);
+	val = readl(sllc_pmu->base + regs->event_ctrl);
+	val &= ~BIT_ULL(hwc->idx);
+	writel(val, sllc_pmu->base + regs->event_ctrl);
 }
 
 static void hisi_sllc_pmu_enable_counter_int(struct hisi_pmu *sllc_pmu,
 					     struct hw_perf_event *hwc)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_INT_MASK);
-	/* Write 0 to enable interrupt */
-	val &= ~(1 << hwc->idx);
-	writel(val, sllc_pmu->base + SLLC_INT_MASK);
+	val = readl(sllc_pmu->base + regs->int_mask);
+	val &= ~BIT_ULL(hwc->idx);
+	writel(val, sllc_pmu->base + regs->int_mask);
 }
 
 static void hisi_sllc_pmu_disable_counter_int(struct hisi_pmu *sllc_pmu,
 					      struct hw_perf_event *hwc)
 {
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(sllc_pmu->base + SLLC_INT_MASK);
-	/* Write 1 to mask interrupt */
-	val |= 1 << hwc->idx;
-	writel(val, sllc_pmu->base + SLLC_INT_MASK);
+	val = readl(sllc_pmu->base + regs->int_mask);
+	val |= BIT_ULL(hwc->idx);
+	writel(val, sllc_pmu->base + regs->int_mask);
 }
 
 static u32 hisi_sllc_pmu_get_int_status(struct hisi_pmu *sllc_pmu)
 {
-	return readl(sllc_pmu->base + SLLC_INT_STATUS);
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
+
+	return readl(sllc_pmu->base + regs->int_status);
 }
 
 static void hisi_sllc_pmu_clear_int_status(struct hisi_pmu *sllc_pmu, int idx)
 {
-	writel(1 << idx, sllc_pmu->base + SLLC_INT_CLEAR);
-}
+	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 
-static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = {
-	{ "HISI0263", },
-	{}
-};
-MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match);
+	writel(BIT_ULL(idx), sllc_pmu->base + regs->int_clear);
+}
 
 static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
 				   struct hisi_pmu *sllc_pmu)
 {
+	struct hisi_sllc_pmu_regs *regs;
+
 	hisi_uncore_pmu_init_topology(sllc_pmu, &pdev->dev);
 
 	/*
@@ -304,13 +330,18 @@ static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	sllc_pmu->dev_info = device_get_match_data(&pdev->dev);
+	if (!sllc_pmu->dev_info)
+		return -ENODEV;
+
 	sllc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(sllc_pmu->base)) {
 		dev_err(&pdev->dev, "ioremap failed for sllc_pmu resource.\n");
 		return PTR_ERR(sllc_pmu->base);
 	}
 
-	sllc_pmu->identifier = readl(sllc_pmu->base + SLLC_VERSION);
+	regs = sllc_pmu->dev_info->private;
+	sllc_pmu->identifier = readl(sllc_pmu->base + regs->version);
 
 	return 0;
 }
@@ -352,6 +383,27 @@ static const struct attribute_group *hisi_sllc_pmu_v2_attr_groups[] = {
 	NULL
 };
 
+static struct hisi_sllc_pmu_regs hisi_sllc_v2_pmu_regs = {
+	.int_mask = SLLC_INT_MASK,
+	.int_clear = SLLC_INT_CLEAR,
+	.int_status = SLLC_INT_STATUS,
+	.perf_ctrl = SLLC_PERF_CTRL,
+	.srcid_ctrl = SLLC_SRCID_CTRL,
+	.srcid_cmd_shift = SLLC_SRCID_CMD_SHIFT,
+	.srcid_mask_shift = SLLC_SRCID_MSK_SHIFT,
+	.tgtid_ctrl = SLLC_TGTID_CTRL,
+	.tgtid_min_shift = SLLC_TGTID_MIN_SHIFT,
+	.tgtid_max_shift = SLLC_TGTID_MAX_SHIFT,
+	.event_ctrl = SLLC_EVENT_CTRL,
+	.event_type0 = SLLC_EVENT_TYPE0,
+	.version = SLLC_VERSION,
+	.event_cnt0 = SLLC_EVENT_CNT0_L,
+};
+
+static const struct hisi_pmu_dev_info hisi_sllc_v2 = {
+	.private = &hisi_sllc_v2_pmu_regs,
+};
+
 static const struct hisi_uncore_ops hisi_uncore_sllc_ops = {
 	.write_evtype		= hisi_sllc_pmu_write_evtype,
 	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
@@ -443,6 +495,12 @@ static void hisi_sllc_pmu_remove(struct platform_device *pdev)
 					    &sllc_pmu->node);
 }
 
+static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = {
+	{ "HISI0263", (kernel_ulong_t)&hisi_sllc_v2 },
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match);
+
 static struct platform_driver hisi_sllc_pmu_driver = {
 	.driver = {
 		.name = "hisi_sllc_pmu",
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:42 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:42 +0800
Subject: [PATCH v2 4/8] drivers/perf: hisi: Add support for HiSilicon SLLC v3 PMU driver
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-5-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

SLLC v3 PMU has the following changes compared to previous version:
a) update the register layout
b) update the definition of SRCID_CTRL and TGTID_CTRL registers.
   To be compatible with v2, we use maximum width (11 bits)
   and mask the extra length for themselves.
c) remove latency events (driver does not need to be adapted).

SLLC v3 PMU is identified with HID HISI0264.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 40 +++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 79327639ec17..852114cfe3bf 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -28,6 +28,18 @@
 #define SLLC_VERSION			0x1cf0
 #define SLLC_EVENT_CNT0_L		0x1d00
 
+/* SLLC registers definition in v3 */
+#define SLLC_V3_INT_MASK		0x6834
+#define SLLC_V3_INT_STATUS		0x6838
+#define SLLC_V3_INT_CLEAR		0x683c
+#define SLLC_V3_VERSION			0x6c00
+#define SLLC_V3_PERF_CTRL		0x6d00
+#define SLLC_V3_SRCID_CTRL		0x6d04
+#define SLLC_V3_TGTID_CTRL		0x6d08
+#define SLLC_V3_EVENT_CTRL		0x6d14
+#define SLLC_V3_EVENT_TYPE0		0x6d18
+#define SLLC_V3_EVENT_CNT0_L		0x6e00
+
 #define SLLC_EVTYPE_MASK		0xff
 #define SLLC_PERF_CTRL_EN		BIT(0)
 #define SLLC_FILT_EN			BIT(1)
@@ -40,6 +52,12 @@
 #define SLLC_TGTID_MAX_SHIFT		12
 #define SLLC_SRCID_CMD_SHIFT		1
 #define SLLC_SRCID_MSK_SHIFT		12
+
+#define SLLC_V3_TGTID_MIN_SHIFT		1
+#define SLLC_V3_TGTID_MAX_SHIFT		10
+#define SLLC_V3_SRCID_CMD_SHIFT		1
+#define SLLC_V3_SRCID_MSK_SHIFT		10
+
 #define SLLC_NR_EVENTS			0x80
 #define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
 
@@ -404,6 +422,27 @@ static const struct hisi_pmu_dev_info hisi_sllc_v2 = {
 	.private = &hisi_sllc_v2_pmu_regs,
 };
 
+static struct hisi_sllc_pmu_regs hisi_sllc_v3_pmu_regs = {
+	.int_mask = SLLC_V3_INT_MASK,
+	.int_clear = SLLC_V3_INT_CLEAR,
+	.int_status = SLLC_V3_INT_STATUS,
+	.perf_ctrl = SLLC_V3_PERF_CTRL,
+	.srcid_ctrl = SLLC_V3_SRCID_CTRL,
+	.srcid_cmd_shift = SLLC_V3_SRCID_CMD_SHIFT,
+	.srcid_mask_shift = SLLC_V3_SRCID_MSK_SHIFT,
+	.tgtid_ctrl = SLLC_V3_TGTID_CTRL,
+	.tgtid_min_shift = SLLC_V3_TGTID_MIN_SHIFT,
+	.tgtid_max_shift = SLLC_V3_TGTID_MAX_SHIFT,
+	.event_ctrl = SLLC_V3_EVENT_CTRL,
+	.event_type0 = SLLC_V3_EVENT_TYPE0,
+	.version = SLLC_V3_VERSION,
+	.event_cnt0 = SLLC_V3_EVENT_CNT0_L,
+};
+
+static const struct hisi_pmu_dev_info hisi_sllc_v3 = {
+	.private = &hisi_sllc_v3_pmu_regs,
+};
+
 static const struct hisi_uncore_ops hisi_uncore_sllc_ops = {
 	.write_evtype		= hisi_sllc_pmu_write_evtype,
 	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
@@ -497,6 +536,7 @@ static void hisi_sllc_pmu_remove(struct platform_device *pdev)
 
 static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = {
 	{ "HISI0263", (kernel_ulong_t)&hisi_sllc_v2 },
+	{ "HISI0264", (kernel_ulong_t)&hisi_sllc_v3 },
 	{}
 };
 MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match);
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:45 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:45 +0800
Subject: [PATCH v2 7/8] drivers/perf: hisi: Add support for HiSilicon NoC PMU
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-8-yangyicong@huawei.com>

From: Yicong Yang <yangyicong at hisilicon.com>

Adds the support for HiSilicon NoC (Network on Chip) PMU which
will be used to monitor the events on the system bus. The PMU
device will be named after the SCL ID (either Super CPU cluster
or Super IO cluster) and the index ID, just similar to other
HiSilicon Uncore PMUs. Below PMU formats are provided besides
the event:

- ch: the transaction channel (data, request, response, etc) which
  can be used to filter the counting.
- tt_en: tracetag filtering enable. Just as other HiSilicon Uncore
  PMUs the NoC PMU supports only counting the transactions with
  tracetag.

The NoC PMU doesn't have an interrupt to indicate the overflow.
However we have a 64 bit counter which is large enough and it's
nearly impossible to overflow.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 Documentation/admin-guide/perf/hisi-pmu.rst  |  11 +
 drivers/perf/hisilicon/Makefile              |   3 +-
 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c | 392 +++++++++++++++++++
 3 files changed, 405 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c

diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
index 48992a0b8e94..6f0ea4f641cc 100644
--- a/Documentation/admin-guide/perf/hisi-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pmu.rst
@@ -112,6 +112,17 @@ uring channel. It is 2 bits. Some important codes are as follows:
 - 2'b00: default value, count the events which sent to the both uring and
   uring_ext channel;
 
+6. ch: NoC PMU supports filtering the event counts of certain transaction
+channel with this option. The current supported channels are as follows:
+
+- 3'b010: Request channel
+- 3'b100: Snoop channel
+- 3'b110: Response channel
+- 3'b111: Data channel
+
+7. tt_en: NoC PMU supports counting only transactions that have tracetag set
+if this option is set. See the 2nd list for more information about tracetag.
+
 Users could configure IDs to count data come from specific CCL/ICL, by setting
 srcid_cmd & srcid_msk, and data desitined for specific CCL/ICL by setting
 tgtid_cmd & tgtid_msk. A set bit in srcid_msk/tgtid_msk means the PMU will not
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 48dcc8381ea7..dcec8f39719d 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
 			  hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
-			  hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o
+			  hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o \
+			  hisi_uncore_noc_pmu.o
 
 obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
 obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
new file mode 100644
index 000000000000..36333fe79257
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for HiSilicon Uncore NoC (Network on Chip) PMU device
+ *
+ * Copyright (c) 2025 HiSilicon Technologies Co., Ltd.
+ * Author: Yicong Yang <yangyicong at hisilicon.com>
+ */
+#include <linux/bitops.h>
+#include <linux/cpuhotplug.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/sysfs.h>
+
+#include "hisi_uncore_pmu.h"
+
+#define NOC_PMU_VERSION			0x1e00
+#define NOC_PMU_GLOBAL_CTRL		0x1e04
+#define   NOC_PMU_GLOBAL_CTRL_PMU_EN	BIT(0)
+#define   NOC_PMU_GLOBAL_CTRL_TT_EN	BIT(1)
+#define NOC_PMU_CNT_INFO		0x1e08
+#define   NOC_PMU_CNT_INFO_OVERFLOW(n)	BIT(n)
+#define NOC_PMU_EVENT_CTRL(n)		(0x1e20 + 4 * (n))
+#define   NOC_PMU_EVENT_CTRL_TYPE	GENMASK(4, 0)
+/*
+ * Note channel of 0x0 will reset the counter value, so don't do it before
+ * we read out the counter.
+ */
+#define   NOC_PMU_EVENT_CTRL_CHANNEL	GENMASK(10, 8)
+#define   NOC_PMU_EVENT_CTRL_EN		BIT(11)
+#define NOC_PMU_EVENT_COUNTER(n)	(0x1e80 + 8 * (n))
+
+#define NOC_PMU_NR_COUNTERS		4
+#define NOC_PMU_COUNTER_BITS		64
+
+#define NOC_PMU_CH_DEFAULT	0x7
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(ch, config1, 2, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_en, config1, 3, 3);
+
+/* Dynamic CPU hotplug state used by this PMU driver */
+static enum cpuhp_state hisi_noc_pmu_cpuhp_state;
+
+/*
+ * Tracetag filtering is not per event and all the events should keep
+ * the consistence. Return true if the new comer doesn't match the
+ * tracetag filtering configuration of the current scheduled events.
+ */
+static bool hisi_noc_pmu_check_global_filter(struct perf_event *curr,
+					     struct perf_event *new)
+{
+	return hisi_get_tt_en(curr) == hisi_get_tt_en(new);
+}
+
+static void hisi_noc_pmu_write_evtype(struct hisi_pmu *noc_pmu, int idx, u32 type)
+{
+	u32 reg;
+
+	reg = readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(idx));
+	reg &= ~NOC_PMU_EVENT_CTRL_TYPE;
+	reg |= FIELD_PREP(NOC_PMU_EVENT_CTRL_TYPE, type);
+	writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(idx));
+}
+
+static int hisi_noc_pmu_get_event_idx(struct perf_event *event)
+{
+	struct hisi_pmu *noc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_pmu_hwevents *pmu_events = &noc_pmu->pmu_events;
+	int cur_idx;
+
+	cur_idx = find_first_bit(pmu_events->used_mask, noc_pmu->num_counters);
+	if (cur_idx != noc_pmu->num_counters &&
+	    !hisi_noc_pmu_check_global_filter(pmu_events->hw_events[cur_idx], event))
+		return -EAGAIN;
+
+	return hisi_uncore_pmu_get_event_idx(event);
+}
+
+static u64 hisi_noc_pmu_read_counter(struct hisi_pmu *noc_pmu,
+				     struct hw_perf_event *hwc)
+{
+	return readq(noc_pmu->base + NOC_PMU_EVENT_COUNTER(hwc->idx));
+}
+
+static void hisi_noc_pmu_write_counter(struct hisi_pmu *noc_pmu,
+				       struct hw_perf_event *hwc, u64 val)
+{
+	writeq(val, noc_pmu->base + NOC_PMU_EVENT_COUNTER(hwc->idx));
+}
+
+static void hisi_noc_pmu_enable_counter(struct hisi_pmu *noc_pmu,
+					struct hw_perf_event *hwc)
+{
+	u32 reg;
+
+	reg = readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+	reg |= NOC_PMU_EVENT_CTRL_EN;
+	writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+}
+
+static void hisi_noc_pmu_disable_counter(struct hisi_pmu *noc_pmu,
+					 struct hw_perf_event *hwc)
+{
+	u32 reg;
+
+	reg = readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+	reg &= ~NOC_PMU_EVENT_CTRL_EN;
+	writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+}
+
+static void hisi_noc_pmu_enable_counter_int(struct hisi_pmu *noc_pmu,
+					    struct hw_perf_event *hwc)
+{
+	/* We don't support interrupt, so a stub here. */
+}
+
+static void hisi_noc_pmu_disable_counter_int(struct hisi_pmu *noc_pmu,
+					     struct hw_perf_event *hwc)
+{
+}
+
+static void hisi_noc_pmu_start_counters(struct hisi_pmu *noc_pmu)
+{
+	u32 reg;
+
+	reg = readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+	reg |= NOC_PMU_GLOBAL_CTRL_PMU_EN;
+	writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+}
+
+static void hisi_noc_pmu_stop_counters(struct hisi_pmu *noc_pmu)
+{
+	u32 reg;
+
+	reg = readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+	reg &= ~NOC_PMU_GLOBAL_CTRL_PMU_EN;
+	writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+}
+
+static u32 hisi_noc_pmu_get_int_status(struct hisi_pmu *noc_pmu)
+{
+	return readl(noc_pmu->base + NOC_PMU_CNT_INFO);
+}
+
+static void hisi_noc_pmu_clear_int_status(struct hisi_pmu *noc_pmu, int idx)
+{
+	writel(~NOC_PMU_CNT_INFO_OVERFLOW(idx), noc_pmu->base + NOC_PMU_CNT_INFO);
+}
+
+static void hisi_noc_pmu_enable_filter(struct perf_event *event)
+{
+	struct hisi_pmu *noc_pmu = to_hisi_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	u32 tt_en = hisi_get_tt_en(event);
+	u32 ch = hisi_get_ch(event);
+	u32 reg;
+
+	if (!ch)
+		ch = NOC_PMU_CH_DEFAULT;
+
+	reg = readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+	reg &= ~NOC_PMU_EVENT_CTRL_CHANNEL;
+	reg |= FIELD_PREP(NOC_PMU_EVENT_CTRL_CHANNEL, ch);
+	writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx));
+
+	/*
+	 * Since tracetag filter applies to all the counters, don't touch it
+	 * if user doesn't specify it explicitly.
+	 */
+	if (tt_en) {
+		reg = readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+		reg |= NOC_PMU_GLOBAL_CTRL_TT_EN;
+		writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+	}
+}
+
+static void hisi_noc_pmu_disable_filter(struct perf_event *event)
+{
+	struct hisi_pmu *noc_pmu = to_hisi_pmu(event->pmu);
+	u32 tt_en = hisi_get_tt_en(event);
+	u32 reg;
+
+	/*
+	 * If we're not the last counter, don't touch the global tracetag
+	 * configuration.
+	 */
+	if (bitmap_weight(noc_pmu->pmu_events.used_mask, noc_pmu->num_counters) > 1)
+		return;
+
+	if (tt_en) {
+		reg = readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+		reg &= ~NOC_PMU_GLOBAL_CTRL_TT_EN;
+		writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL);
+	}
+}
+
+static const struct hisi_uncore_ops hisi_uncore_noc_ops = {
+	.write_evtype		= hisi_noc_pmu_write_evtype,
+	.get_event_idx		= hisi_noc_pmu_get_event_idx,
+	.read_counter		= hisi_noc_pmu_read_counter,
+	.write_counter		= hisi_noc_pmu_write_counter,
+	.enable_counter		= hisi_noc_pmu_enable_counter,
+	.disable_counter	= hisi_noc_pmu_disable_counter,
+	.enable_counter_int	= hisi_noc_pmu_enable_counter_int,
+	.disable_counter_int	= hisi_noc_pmu_disable_counter_int,
+	.start_counters		= hisi_noc_pmu_start_counters,
+	.stop_counters		= hisi_noc_pmu_stop_counters,
+	.get_int_status		= hisi_noc_pmu_get_int_status,
+	.clear_int_status	= hisi_noc_pmu_clear_int_status,
+	.enable_filter		= hisi_noc_pmu_enable_filter,
+	.disable_filter		= hisi_noc_pmu_disable_filter,
+};
+
+static struct attribute *hisi_noc_pmu_format_attrs[] = {
+	HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+	HISI_PMU_FORMAT_ATTR(ch, "config1:0-2"),
+	HISI_PMU_FORMAT_ATTR(tt_en, "config1:3"),
+	NULL
+};
+
+static const struct attribute_group hisi_noc_pmu_format_group = {
+	.name = "format",
+	.attrs = hisi_noc_pmu_format_attrs,
+};
+
+static struct attribute *hisi_noc_pmu_events_attrs[] = {
+	HISI_PMU_EVENT_ATTR(cycles, 0x0e),
+	/* Flux on/off the ring */
+	HISI_PMU_EVENT_ATTR(ingress_flow_sum, 0x1a),
+	HISI_PMU_EVENT_ATTR(egress_flow_sum, 0x17),
+	/* Buffer full duration on/off the ring */
+	HISI_PMU_EVENT_ATTR(ingress_buf_full, 0x19),
+	HISI_PMU_EVENT_ATTR(egress_buf_full, 0x12),
+	/* Failure packets count on/off the ring */
+	HISI_PMU_EVENT_ATTR(cw_ingress_fail, 0x01),
+	HISI_PMU_EVENT_ATTR(cc_ingress_fail, 0x09),
+	HISI_PMU_EVENT_ATTR(cw_egress_fail, 0x03),
+	HISI_PMU_EVENT_ATTR(cc_egress_fail, 0x0b),
+	/* Flux of the ring */
+	HISI_PMU_EVENT_ATTR(cw_main_flow_sum, 0x05),
+	HISI_PMU_EVENT_ATTR(cc_main_flow_sum, 0x0d),
+	NULL
+};
+
+static const struct attribute_group hisi_noc_pmu_events_group = {
+	.name = "events",
+	.attrs = hisi_noc_pmu_events_attrs,
+};
+
+static const struct attribute_group *hisi_noc_pmu_attr_groups[] = {
+	&hisi_noc_pmu_format_group,
+	&hisi_noc_pmu_events_group,
+	&hisi_pmu_cpumask_attr_group,
+	&hisi_pmu_identifier_group,
+	NULL
+};
+
+static int hisi_noc_pmu_dev_init(struct platform_device *pdev, struct hisi_pmu *noc_pmu)
+{
+	hisi_uncore_pmu_init_topology(noc_pmu, &pdev->dev);
+
+	if (noc_pmu->topo.scl_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL, "failed to get scl-id\n");
+
+	if (noc_pmu->topo.index_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL, "failed to get idx-id\n");
+
+	if (noc_pmu->topo.sub_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL, "failed to get sub-id\n");
+
+	noc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(noc_pmu->base))
+		return dev_err_probe(&pdev->dev, PTR_ERR(noc_pmu->base),
+				     "fail to remap io memory\n");
+
+	noc_pmu->on_cpu = -1;
+	noc_pmu->dev = &pdev->dev;
+	noc_pmu->ops = &hisi_uncore_noc_ops;
+	noc_pmu->pmu_events.attr_groups = hisi_noc_pmu_attr_groups;
+	noc_pmu->num_counters = NOC_PMU_NR_COUNTERS;
+	noc_pmu->counter_bits = NOC_PMU_COUNTER_BITS;
+	noc_pmu->check_event = NOC_PMU_EVENT_CTRL_TYPE;
+	noc_pmu->identifier = readl(noc_pmu->base + NOC_PMU_VERSION);
+	return 0;
+}
+
+static void hisi_noc_pmu_remove_cpuhp_instance(void *hotplug_node)
+{
+	cpuhp_state_remove_instance_nocalls(hisi_noc_pmu_cpuhp_state, hotplug_node);
+}
+
+static void hisi_noc_pmu_unregister_pmu(void *pmu)
+{
+	perf_pmu_unregister(pmu);
+}
+
+static int hisi_noc_pmu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hisi_pmu *noc_pmu;
+	char *name;
+	int ret;
+
+	noc_pmu = devm_kzalloc(dev, sizeof(*noc_pmu), GFP_KERNEL);
+	if (!noc_pmu)
+		return -ENOMEM;
+
+	/*
+	 * HiSilicon Uncore PMU framework needs to get common hisi_pmu device
+	 * from device's drvdata.
+	 */
+	platform_set_drvdata(pdev, noc_pmu);
+
+	ret = hisi_noc_pmu_dev_init(pdev, noc_pmu);
+	if (ret)
+		return ret;
+
+	ret = cpuhp_state_add_instance(hisi_noc_pmu_cpuhp_state, &noc_pmu->node);
+	if (ret)
+		return dev_err_probe(dev, ret, "Fail to register cpuhp instance\n");
+
+	ret = devm_add_action_or_reset(dev, hisi_noc_pmu_remove_cpuhp_instance,
+				       &noc_pmu->node);
+	if (ret)
+		return ret;
+
+	hisi_pmu_init(noc_pmu, THIS_MODULE);
+
+	name = devm_kasprintf(dev, GFP_KERNEL, "hisi_scl%d_noc%d_%d",
+			      noc_pmu->topo.scl_id, noc_pmu->topo.index_id,
+			      noc_pmu->topo.sub_id);
+	if (!name)
+		return -ENOMEM;
+
+	ret = perf_pmu_register(&noc_pmu->pmu, name, -1);
+	if (ret)
+		return dev_err_probe(dev, ret, "Fail to register PMU\n");
+
+	return devm_add_action_or_reset(dev, hisi_noc_pmu_unregister_pmu,
+					&noc_pmu->pmu);
+}
+
+const struct acpi_device_id hisi_noc_pmu_ids[] = {
+	{ "HISI04E0", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_noc_pmu_ids);
+
+static struct platform_driver hisi_noc_pmu_driver = {
+	.driver = {
+		.name = "hisi_noc_pmu",
+		.acpi_match_table = hisi_noc_pmu_ids,
+		.suppress_bind_attrs = true,
+	},
+	.probe = hisi_noc_pmu_probe,
+};
+
+static int __init hisi_noc_pmu_module_init(void)
+{
+	int ret;
+
+	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/noc:online",
+				      hisi_uncore_pmu_online_cpu,
+				      hisi_uncore_pmu_offline_cpu);
+	if (ret < 0) {
+		pr_err("hisi_noc_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
+		return ret;
+	}
+	hisi_noc_pmu_cpuhp_state = ret;
+
+	ret = platform_driver_register(&hisi_noc_pmu_driver);
+	if (ret)
+		cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
+
+	return ret;
+}
+module_init(hisi_noc_pmu_module_init);
+
+static void __exit hisi_noc_pmu_module_exit(void)
+{
+	platform_driver_unregister(&hisi_noc_pmu_driver);
+	cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
+}
+module_exit(hisi_noc_pmu_module_exit);
+
+MODULE_IMPORT_NS("HISI_PMU");
+MODULE_DESCRIPTION("HiSilicon SoC Uncore NoC PMU driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yicong Yang <yangyicong at hisilicon.com>");
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:40 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:40 +0800
Subject: [PATCH v2 2/8] drivers/perf: hisi: Add support for HiSilicon DDRC v3 PMU driver
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-3-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

HiSilicon DDRC v3 PMU has the different interrupt register offset
compared to the v2. Add device information of v3 PMU with ACPI
HID HISI0235.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 7e3c2436e96b..26eaa6d20c00 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -43,6 +43,11 @@
 #define DDRC_V2_EVENT_TYPE	0xe74
 #define DDRC_V2_PERF_CTRL	0xeA0
 
+/* DDRC interrupt registers definition in v3 */
+#define DDRC_V3_INT_MASK	0x534
+#define DDRC_V3_INT_STATUS	0x538
+#define DDRC_V3_INT_CLEAR	0x53C
+
 /* DDRC has 8-counters */
 #define DDRC_NR_COUNTERS	0x8
 #define DDRC_V1_PERF_CTRL_EN	0x2
@@ -460,9 +465,28 @@ static const struct hisi_pmu_dev_info hisi_ddrc_v2 = {
 	.private = &hisi_ddrc_v2_pmu_regs,
 };
 
+static struct hisi_ddrc_pmu_regs hisi_ddrc_v3_pmu_regs = {
+	.event_cnt = DDRC_V2_EVENT_CNT,
+	.event_ctrl = DDRC_V2_EVENT_CTRL,
+	.event_type = DDRC_V2_EVENT_TYPE,
+	.perf_ctrl = DDRC_V2_PERF_CTRL,
+	.perf_ctrl_en = DDRC_V2_PERF_CTRL_EN,
+	.int_mask = DDRC_V3_INT_MASK,
+	.int_clear = DDRC_V3_INT_CLEAR,
+	.int_status = DDRC_V3_INT_STATUS,
+};
+
+static const struct hisi_pmu_dev_info hisi_ddrc_v3 = {
+	.counter_bits = 48,
+	.check_event = DDRC_V2_NR_EVENTS,
+	.attr_groups = hisi_ddrc_pmu_v2_attr_groups,
+	.private = &hisi_ddrc_v3_pmu_regs,
+};
+
 static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
 	{ "HISI0233", (kernel_ulong_t)&hisi_ddrc_v1 },
 	{ "HISI0234", (kernel_ulong_t)&hisi_ddrc_v2 },
+	{ "HISI0235", (kernel_ulong_t)&hisi_ddrc_v3 },
 	{}
 };
 MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match);
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:39 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:39 +0800
Subject: [PATCH v2 1/8] drivers/perf: hisi: Simplify the probe process for each DDRC version
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-2-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

Version 1 and 2 of DDRC PMU also use different HID. Make use of
struct acpi_device_id::driver_data for version specific information
rather than judge the version register. This will help to
simplify the probe process and also a bit easier for extension.

In order to support this extend struct hisi_pmu_dev_info for version
specific counter bits and event range.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 328 ++++++++----------
 drivers/perf/hisilicon/hisi_uncore_pmu.h      |   2 +
 2 files changed, 142 insertions(+), 188 deletions(-)

diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 7e490f8868f2..7e3c2436e96b 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -50,6 +50,10 @@
 #define DDRC_V1_NR_EVENTS	0x7
 #define DDRC_V2_NR_EVENTS	0x90
 
+#define DDRC_EVENT_CNTn(base, n)	((base) + (n) * 8)
+#define DDRC_EVENT_TYPEn(base, n)	((base) + (n) * 4)
+#define DDRC_UNIMPLEMENTED_REG		GENMASK(31, 0)
+
 /*
  * For PMU v1, there are eight-events and every event has been mapped
  * to fixed-purpose counters which register offset is not consistent.
@@ -63,47 +67,37 @@ static const u32 ddrc_reg_off[] = {
 	DDRC_PRE_CMD, DDRC_ACT_CMD, DDRC_RNK_CHG, DDRC_RW_CHG
 };
 
-/*
- * Select the counter register offset using the counter index.
- * In PMU v1, there are no programmable counter, the count
- * is read form the statistics counter register itself.
- */
-static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx)
-{
-	return ddrc_reg_off[cntr_idx];
-}
-
-static u32 hisi_ddrc_pmu_v2_get_counter_offset(int cntr_idx)
-{
-	return DDRC_V2_EVENT_CNT + cntr_idx * 8;
-}
+struct hisi_ddrc_pmu_regs {
+	u32 event_cnt;
+	u32 event_ctrl;
+	u32 event_type;
+	u32 perf_ctrl;
+	u32 perf_ctrl_en;
+	u32 int_mask;
+	u32 int_clear;
+	u32 int_status;
+};
 
-static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu,
+static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu,
 				      struct hw_perf_event *hwc)
 {
-	return readl(ddrc_pmu->base +
-		     hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx));
-}
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 
-static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu,
-					struct hw_perf_event *hwc, u64 val)
-{
-	writel((u32)val,
-	       ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx));
-}
+	if (regs->event_cnt == DDRC_UNIMPLEMENTED_REG)
+		return readl(ddrc_pmu->base + ddrc_reg_off[hwc->idx]);
 
-static u64 hisi_ddrc_pmu_v2_read_counter(struct hisi_pmu *ddrc_pmu,
-					 struct hw_perf_event *hwc)
-{
-	return readq(ddrc_pmu->base +
-		     hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx));
+	return readq(ddrc_pmu->base + DDRC_EVENT_CNTn(regs->event_cnt, hwc->idx));
 }
 
-static void hisi_ddrc_pmu_v2_write_counter(struct hisi_pmu *ddrc_pmu,
-					   struct hw_perf_event *hwc, u64 val)
+static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu,
+					struct hw_perf_event *hwc, u64 val)
 {
-	writeq(val,
-	       ddrc_pmu->base + hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx));
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
+
+	if (regs->event_cnt == DDRC_UNIMPLEMENTED_REG)
+		writel((u32)val, ddrc_pmu->base + ddrc_reg_off[hwc->idx]);
+	else
+		writeq(val, ddrc_pmu->base + DDRC_EVENT_CNTn(regs->event_cnt, hwc->idx));
 }
 
 /*
@@ -114,54 +108,12 @@ static void hisi_ddrc_pmu_v2_write_counter(struct hisi_pmu *ddrc_pmu,
 static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *ddrc_pmu, int idx,
 				       u32 type)
 {
-	u32 offset;
-
-	if (ddrc_pmu->identifier >= HISI_PMU_V2) {
-		offset = DDRC_V2_EVENT_TYPE + 4 * idx;
-		writel(type, ddrc_pmu->base + offset);
-	}
-}
-
-static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu)
-{
-	u32 val;
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 
-	/* Set perf_enable in DDRC_PERF_CTRL to start event counting */
-	val = readl(ddrc_pmu->base + DDRC_PERF_CTRL);
-	val |= DDRC_V1_PERF_CTRL_EN;
-	writel(val, ddrc_pmu->base + DDRC_PERF_CTRL);
-}
+	if (regs->event_type == DDRC_UNIMPLEMENTED_REG)
+		return;
 
-static void hisi_ddrc_pmu_v1_stop_counters(struct hisi_pmu *ddrc_pmu)
-{
-	u32 val;
-
-	/* Clear perf_enable in DDRC_PERF_CTRL to stop event counting */
-	val = readl(ddrc_pmu->base + DDRC_PERF_CTRL);
-	val &= ~DDRC_V1_PERF_CTRL_EN;
-	writel(val, ddrc_pmu->base + DDRC_PERF_CTRL);
-}
-
-static void hisi_ddrc_pmu_v1_enable_counter(struct hisi_pmu *ddrc_pmu,
-					    struct hw_perf_event *hwc)
-{
-	u32 val;
-
-	/* Set counter index(event code) in DDRC_EVENT_CTRL register */
-	val = readl(ddrc_pmu->base + DDRC_EVENT_CTRL);
-	val |= (1 << GET_DDRC_EVENTID(hwc));
-	writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL);
-}
-
-static void hisi_ddrc_pmu_v1_disable_counter(struct hisi_pmu *ddrc_pmu,
-					     struct hw_perf_event *hwc)
-{
-	u32 val;
-
-	/* Clear counter index(event code) in DDRC_EVENT_CTRL register */
-	val = readl(ddrc_pmu->base + DDRC_EVENT_CTRL);
-	val &= ~(1 << GET_DDRC_EVENTID(hwc));
-	writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL);
+	writel(type, ddrc_pmu->base + DDRC_EVENT_TYPEn(regs->event_type, idx));
 }
 
 static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event)
@@ -180,120 +132,96 @@ static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event)
 	return idx;
 }
 
-static int hisi_ddrc_pmu_v2_get_event_idx(struct perf_event *event)
+static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event)
 {
+	struct hisi_pmu *ddrc_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
+
+	if (regs->event_type == DDRC_UNIMPLEMENTED_REG)
+		return hisi_ddrc_pmu_v1_get_event_idx(event);
+
 	return hisi_uncore_pmu_get_event_idx(event);
 }
 
-static void hisi_ddrc_pmu_v2_start_counters(struct hisi_pmu *ddrc_pmu)
+static void hisi_ddrc_pmu_start_counters(struct hisi_pmu *ddrc_pmu)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL);
-	val |= DDRC_V2_PERF_CTRL_EN;
-	writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+	val = readl(ddrc_pmu->base + regs->perf_ctrl);
+	val |= regs->perf_ctrl_en;
+	writel(val, ddrc_pmu->base + regs->perf_ctrl);
 }
 
-static void hisi_ddrc_pmu_v2_stop_counters(struct hisi_pmu *ddrc_pmu)
+static void hisi_ddrc_pmu_stop_counters(struct hisi_pmu *ddrc_pmu)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL);
-	val &= ~DDRC_V2_PERF_CTRL_EN;
-	writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+	val = readl(ddrc_pmu->base + regs->perf_ctrl);
+	val &= ~regs->perf_ctrl_en;
+	writel(val, ddrc_pmu->base + regs->perf_ctrl);
 }
 
-static void hisi_ddrc_pmu_v2_enable_counter(struct hisi_pmu *ddrc_pmu,
+static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu,
 					    struct hw_perf_event *hwc)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
-	val |= 1 << hwc->idx;
-	writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
+	val = readl(ddrc_pmu->base + regs->event_ctrl);
+	val |= BIT_ULL(hwc->idx);
+	writel(val, ddrc_pmu->base + regs->event_ctrl);
 }
 
-static void hisi_ddrc_pmu_v2_disable_counter(struct hisi_pmu *ddrc_pmu,
+static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu,
 					     struct hw_perf_event *hwc)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
-	val &= ~(1 << hwc->idx);
-	writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
-}
-
-static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu,
-						struct hw_perf_event *hwc)
-{
-	u32 val;
-
-	/* Write 0 to enable interrupt */
-	val = readl(ddrc_pmu->base + DDRC_INT_MASK);
-	val &= ~(1 << hwc->idx);
-	writel(val, ddrc_pmu->base + DDRC_INT_MASK);
-}
-
-static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu,
-						 struct hw_perf_event *hwc)
-{
-	u32 val;
-
-	/* Write 1 to mask interrupt */
-	val = readl(ddrc_pmu->base + DDRC_INT_MASK);
-	val |= 1 << hwc->idx;
-	writel(val, ddrc_pmu->base + DDRC_INT_MASK);
+	val = readl(ddrc_pmu->base + regs->event_ctrl);
+	val &= ~BIT_ULL(hwc->idx);
+	writel(val, ddrc_pmu->base + regs->event_ctrl);
 }
 
-static void hisi_ddrc_pmu_v2_enable_counter_int(struct hisi_pmu *ddrc_pmu,
-						struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu,
+					     struct hw_perf_event *hwc)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK);
-	val &= ~(1 << hwc->idx);
-	writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK);
+	val = readl(ddrc_pmu->base + regs->int_mask);
+	val &= ~BIT_ULL(hwc->idx);
+	writel(val, ddrc_pmu->base + regs->int_mask);
 }
 
-static void hisi_ddrc_pmu_v2_disable_counter_int(struct hisi_pmu *ddrc_pmu,
-						struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu,
+					      struct hw_perf_event *hwc)
 {
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 	u32 val;
 
-	val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK);
-	val |= 1 << hwc->idx;
-	writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK);
+	val = readl(ddrc_pmu->base + regs->int_mask);
+	val |= BIT_ULL(hwc->idx);
+	writel(val, ddrc_pmu->base + regs->int_mask);
 }
 
-static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu)
+static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu)
 {
-	return readl(ddrc_pmu->base + DDRC_INT_STATUS);
-}
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 
-static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu,
-					      int idx)
-{
-	writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR);
+	return readl(ddrc_pmu->base + regs->int_status);
 }
 
-static u32 hisi_ddrc_pmu_v2_get_int_status(struct hisi_pmu *ddrc_pmu)
+static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu,
+					   int idx)
 {
-	return readl(ddrc_pmu->base + DDRC_V2_INT_STATUS);
-}
+	struct hisi_ddrc_pmu_regs *regs = ddrc_pmu->dev_info->private;
 
-static void hisi_ddrc_pmu_v2_clear_int_status(struct hisi_pmu *ddrc_pmu,
-					      int idx)
-{
-	writel(1 << idx, ddrc_pmu->base + DDRC_V2_INT_CLEAR);
+	writel(1 << idx, ddrc_pmu->base + regs->int_clear);
 }
 
-static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
-	{ "HISI0233", },
-	{ "HISI0234", },
-	{}
-};
-MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match);
-
 static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
 				   struct hisi_pmu *ddrc_pmu)
 {
@@ -314,6 +242,10 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	ddrc_pmu->dev_info = device_get_match_data(&pdev->dev);
+	if (!ddrc_pmu->dev_info)
+		return -ENODEV;
+
 	ddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(ddrc_pmu->base)) {
 		dev_err(&pdev->dev, "ioremap failed for ddrc_pmu resource\n");
@@ -396,34 +328,19 @@ static const struct attribute_group *hisi_ddrc_pmu_v2_attr_groups[] = {
 	NULL
 };
 
-static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = {
+static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = {
 	.write_evtype           = hisi_ddrc_pmu_write_evtype,
-	.get_event_idx		= hisi_ddrc_pmu_v1_get_event_idx,
-	.start_counters		= hisi_ddrc_pmu_v1_start_counters,
-	.stop_counters		= hisi_ddrc_pmu_v1_stop_counters,
-	.enable_counter		= hisi_ddrc_pmu_v1_enable_counter,
-	.disable_counter	= hisi_ddrc_pmu_v1_disable_counter,
-	.enable_counter_int	= hisi_ddrc_pmu_v1_enable_counter_int,
-	.disable_counter_int	= hisi_ddrc_pmu_v1_disable_counter_int,
-	.write_counter		= hisi_ddrc_pmu_v1_write_counter,
-	.read_counter		= hisi_ddrc_pmu_v1_read_counter,
-	.get_int_status		= hisi_ddrc_pmu_v1_get_int_status,
-	.clear_int_status	= hisi_ddrc_pmu_v1_clear_int_status,
-};
-
-static const struct hisi_uncore_ops hisi_uncore_ddrc_v2_ops = {
-	.write_evtype           = hisi_ddrc_pmu_write_evtype,
-	.get_event_idx		= hisi_ddrc_pmu_v2_get_event_idx,
-	.start_counters		= hisi_ddrc_pmu_v2_start_counters,
-	.stop_counters		= hisi_ddrc_pmu_v2_stop_counters,
-	.enable_counter		= hisi_ddrc_pmu_v2_enable_counter,
-	.disable_counter	= hisi_ddrc_pmu_v2_disable_counter,
-	.enable_counter_int	= hisi_ddrc_pmu_v2_enable_counter_int,
-	.disable_counter_int	= hisi_ddrc_pmu_v2_disable_counter_int,
-	.write_counter		= hisi_ddrc_pmu_v2_write_counter,
-	.read_counter		= hisi_ddrc_pmu_v2_read_counter,
-	.get_int_status		= hisi_ddrc_pmu_v2_get_int_status,
-	.clear_int_status	= hisi_ddrc_pmu_v2_clear_int_status,
+	.get_event_idx		= hisi_ddrc_pmu_get_event_idx,
+	.start_counters		= hisi_ddrc_pmu_start_counters,
+	.stop_counters		= hisi_ddrc_pmu_stop_counters,
+	.enable_counter		= hisi_ddrc_pmu_enable_counter,
+	.disable_counter	= hisi_ddrc_pmu_disable_counter,
+	.enable_counter_int	= hisi_ddrc_pmu_enable_counter_int,
+	.disable_counter_int	= hisi_ddrc_pmu_disable_counter_int,
+	.write_counter		= hisi_ddrc_pmu_write_counter,
+	.read_counter		= hisi_ddrc_pmu_read_counter,
+	.get_int_status		= hisi_ddrc_pmu_get_int_status,
+	.clear_int_status	= hisi_ddrc_pmu_clear_int_status,
 };
 
 static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
@@ -439,18 +356,10 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
 	if (ret)
 		return ret;
 
-	if (ddrc_pmu->identifier >= HISI_PMU_V2) {
-		ddrc_pmu->counter_bits = 48;
-		ddrc_pmu->check_event = DDRC_V2_NR_EVENTS;
-		ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v2_attr_groups;
-		ddrc_pmu->ops = &hisi_uncore_ddrc_v2_ops;
-	} else {
-		ddrc_pmu->counter_bits = 32;
-		ddrc_pmu->check_event = DDRC_V1_NR_EVENTS;
-		ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v1_attr_groups;
-		ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops;
-	}
-
+	ddrc_pmu->pmu_events.attr_groups = ddrc_pmu->dev_info->attr_groups;
+	ddrc_pmu->counter_bits = ddrc_pmu->dev_info->counter_bits;
+	ddrc_pmu->check_event = ddrc_pmu->dev_info->check_event;
+	ddrc_pmu->ops = &hisi_uncore_ddrc_ops;
 	ddrc_pmu->num_counters = DDRC_NR_COUNTERS;
 	ddrc_pmu->dev = &pdev->dev;
 	ddrc_pmu->on_cpu = -1;
@@ -515,6 +424,49 @@ static void hisi_ddrc_pmu_remove(struct platform_device *pdev)
 					    &ddrc_pmu->node);
 }
 
+static struct hisi_ddrc_pmu_regs hisi_ddrc_v1_pmu_regs = {
+	.event_cnt = DDRC_UNIMPLEMENTED_REG,
+	.event_ctrl = DDRC_EVENT_CTRL,
+	.event_type = DDRC_UNIMPLEMENTED_REG,
+	.perf_ctrl = DDRC_PERF_CTRL,
+	.perf_ctrl_en = DDRC_V1_PERF_CTRL_EN,
+	.int_mask = DDRC_INT_MASK,
+	.int_clear = DDRC_INT_CLEAR,
+	.int_status = DDRC_INT_STATUS,
+};
+
+static const struct hisi_pmu_dev_info hisi_ddrc_v1 = {
+	.counter_bits = 32,
+	.check_event = DDRC_V1_NR_EVENTS,
+	.attr_groups = hisi_ddrc_pmu_v1_attr_groups,
+	.private = &hisi_ddrc_v1_pmu_regs,
+};
+
+static struct hisi_ddrc_pmu_regs hisi_ddrc_v2_pmu_regs = {
+	.event_cnt = DDRC_V2_EVENT_CNT,
+	.event_ctrl = DDRC_V2_EVENT_CTRL,
+	.event_type = DDRC_V2_EVENT_TYPE,
+	.perf_ctrl = DDRC_V2_PERF_CTRL,
+	.perf_ctrl_en = DDRC_V2_PERF_CTRL_EN,
+	.int_mask = DDRC_V2_INT_MASK,
+	.int_clear = DDRC_V2_INT_CLEAR,
+	.int_status = DDRC_V2_INT_STATUS,
+};
+
+static const struct hisi_pmu_dev_info hisi_ddrc_v2 = {
+	.counter_bits = 48,
+	.check_event = DDRC_V2_NR_EVENTS,
+	.attr_groups = hisi_ddrc_pmu_v2_attr_groups,
+	.private = &hisi_ddrc_v2_pmu_regs,
+};
+
+static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
+	{ "HISI0233", (kernel_ulong_t)&hisi_ddrc_v1 },
+	{ "HISI0234", (kernel_ulong_t)&hisi_ddrc_v2 },
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match);
+
 static struct platform_driver hisi_ddrc_pmu_driver = {
 	.driver = {
 		.name = "hisi_ddrc_pmu",
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index f4fed2544877..777675838b80 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -72,6 +72,8 @@ struct hisi_uncore_ops {
 struct hisi_pmu_dev_info {
 	const char *name;
 	const struct attribute_group **attr_groups;
+	u32 counter_bits;
+	u32 check_event;
 	void *private;
 };
 
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:46 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:46 +0800
Subject: [PATCH v2 8/8] drivers/perf: hisi: Add support for HiSilicon MN PMU driver
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-9-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

MN (Miscellaneous Node) is a hybrid node in ARM CHI. It broadcasts the
following two types of requests: DVM operations and PCIe configuration.
MN PMU devices exist on both SCCL and SICL, so we named the MN pmu
driver after SCL (Super cluster) ID.
The MN PMU driver using the HiSilicon uncore PMU framework. And only
the event parameter is supported.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/Makefile             |   2 +-
 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c | 355 ++++++++++++++++++++
 2 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c

diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index dcec8f39719d..186be3d02238 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
 			  hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
 			  hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o \
-			  hisi_uncore_noc_pmu.o
+			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
 
 obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
 obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
new file mode 100644
index 000000000000..bf9b326e40cf
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
@@ -0,0 +1,355 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SoC MN uncore Hardware event counters support
+ *
+ * Copyright (c) 2025 HiSilicon Technologies Co., Ltd.
+ */
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* Dynamic CPU hotplug state used by MN PMU */
+static enum cpuhp_state hisi_mn_pmu_online;
+
+/* MN register definition */
+#define HISI_MN_DYNAMIC_CTRL		0x400
+#define   HISI_MN_DYNAMIC_CTRL_EN	BIT(0)
+#define HISI_MN_PERF_CTRL_REG		0x408
+#define   HISI_MN_PERF_CTRL_EN		BIT(6)
+#define HISI_MN_INT_MASK_REG		0x800
+#define HISI_MN_INT_STATUS_REG		0x808
+#define HISI_MN_INT_CLEAR_REG		0x80C
+#define HISI_MN_EVENT_CTRL_REG		0x1C00
+#define HISI_MN_VERSION_REG		0x1C04
+#define HISI_MN_EVTYPE_REGn(n)		(0x1d00 + (n) * 4)
+#define   HISI_MN_EVTYPE_MASK		GENMASK(7, 0)
+#define HISI_MN_CNTR_REGn(n)		(0x1e00 + (n) * 8)
+
+#define HISI_MN_NR_COUNTERS		4
+#define HISI_MN_COUNTER_BITS		48
+#define HISI_MN_TIMEOUT_US		500U
+
+/*
+ * Each event request takes a certain amount of time to complete. If
+ * we counting the latency related event, we need to wait for the all
+ * requests complete. Otherwise, the value of counter is slightly larger.
+ */
+static void hisi_mn_pmu_counter_flush(struct hisi_pmu *mn_pmu)
+{
+	int ret;
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_DYNAMIC_CTRL);
+	val |= HISI_MN_DYNAMIC_CTRL_EN;
+	writel(val, mn_pmu->base + HISI_MN_DYNAMIC_CTRL);
+
+	ret = readl_poll_timeout_atomic(mn_pmu->base + HISI_MN_DYNAMIC_CTRL,
+					val, !(val & HISI_MN_DYNAMIC_CTRL_EN),
+					1, HISI_MN_TIMEOUT_US);
+	if (ret)
+		dev_warn(mn_pmu->dev, "Counter flush timeout\n");
+}
+
+static u64 hisi_mn_pmu_read_counter(struct hisi_pmu *mn_pmu,
+				    struct hw_perf_event *hwc)
+{
+	return readq(mn_pmu->base + HISI_MN_CNTR_REGn(hwc->idx));
+}
+
+static void hisi_mn_pmu_write_counter(struct hisi_pmu *mn_pmu,
+				      struct hw_perf_event *hwc, u64 val)
+{
+	writeq(val, mn_pmu->base + HISI_MN_CNTR_REGn(hwc->idx));
+}
+
+static void hisi_mn_pmu_write_evtype(struct hisi_pmu *mn_pmu, int idx, u32 type)
+{
+	u32 val;
+
+	/*
+	 * Select the appropriate event select register.
+	 * There are 2 32-bit event select registers for the
+	 * 8 hardware counters, each event code is 8-bit wide.
+	 */
+	val = readl(mn_pmu->base + HISI_MN_EVTYPE_REGn(idx / 4));
+	val &= ~(HISI_MN_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx));
+	val |= (type << HISI_PMU_EVTYPE_SHIFT(idx));
+	writel(val, mn_pmu->base + HISI_MN_EVTYPE_REGn(idx / 4));
+}
+
+static void hisi_mn_pmu_start_counters(struct hisi_pmu *mn_pmu)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_PERF_CTRL_REG);
+	val |= HISI_MN_PERF_CTRL_EN;
+	writel(val, mn_pmu->base + HISI_MN_PERF_CTRL_REG);
+}
+
+static void hisi_mn_pmu_stop_counters(struct hisi_pmu *mn_pmu)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_PERF_CTRL_REG);
+	val &= ~HISI_MN_PERF_CTRL_EN;
+	writel(val, mn_pmu->base + HISI_MN_PERF_CTRL_REG);
+
+	hisi_mn_pmu_counter_flush(mn_pmu);
+}
+
+static void hisi_mn_pmu_enable_counter(struct hisi_pmu *mn_pmu,
+				       struct hw_perf_event *hwc)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_EVENT_CTRL_REG);
+	val |= BIT(hwc->idx);
+	writel(val, mn_pmu->base + HISI_MN_EVENT_CTRL_REG);
+}
+
+static void hisi_mn_pmu_disable_counter(struct hisi_pmu *mn_pmu,
+					struct hw_perf_event *hwc)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_EVENT_CTRL_REG);
+	val &= ~BIT(hwc->idx);
+	writel(val, mn_pmu->base + HISI_MN_EVENT_CTRL_REG);
+}
+
+static void hisi_mn_pmu_enable_counter_int(struct hisi_pmu *mn_pmu,
+					   struct hw_perf_event *hwc)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_INT_MASK_REG);
+	val &= ~BIT(hwc->idx);
+	writel(val, mn_pmu->base + HISI_MN_INT_MASK_REG);
+}
+
+static void hisi_mn_pmu_disable_counter_int(struct hisi_pmu *mn_pmu,
+					    struct hw_perf_event *hwc)
+{
+	u32 val;
+
+	val = readl(mn_pmu->base + HISI_MN_INT_MASK_REG);
+	val |= BIT(hwc->idx);
+	writel(val, mn_pmu->base + HISI_MN_INT_MASK_REG);
+}
+
+static u32 hisi_mn_pmu_get_int_status(struct hisi_pmu *mn_pmu)
+{
+	return readl(mn_pmu->base + HISI_MN_INT_STATUS_REG);
+}
+
+static void hisi_mn_pmu_clear_int_status(struct hisi_pmu *mn_pmu, int idx)
+{
+	writel(BIT(idx), mn_pmu->base + HISI_MN_INT_CLEAR_REG);
+}
+
+static struct attribute *hisi_mn_pmu_format_attr[] = {
+	HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+	NULL
+};
+
+static const struct attribute_group hisi_mn_pmu_format_group = {
+	.name = "format",
+	.attrs = hisi_mn_pmu_format_attr,
+};
+
+static struct attribute *hisi_mn_pmu_events_attr[] = {
+	HISI_PMU_EVENT_ATTR(req_eobarrier_num,		0x00),
+	HISI_PMU_EVENT_ATTR(req_ecbarrier_num,		0x01),
+	HISI_PMU_EVENT_ATTR(req_dvmop_num,		0x02),
+	HISI_PMU_EVENT_ATTR(req_dvmsync_num,		0x03),
+	HISI_PMU_EVENT_ATTR(req_retry_num,		0x04),
+	HISI_PMU_EVENT_ATTR(req_writenosnp_num,		0x05),
+	HISI_PMU_EVENT_ATTR(req_readnosnp_num,		0x06),
+	HISI_PMU_EVENT_ATTR(snp_dvm_num,		0x07),
+	HISI_PMU_EVENT_ATTR(snp_dvmsync_num,		0x08),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvm_num,		0x09),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_num,	0x0A),
+	HISI_PMU_EVENT_ATTR(mn_req_dvm_num,		0x0B),
+	HISI_PMU_EVENT_ATTR(mn_req_dvmsync_num,		0x0C),
+	HISI_PMU_EVENT_ATTR(pa_req_dvm_num,		0x0D),
+	HISI_PMU_EVENT_ATTR(pa_req_dvmsync_num,		0x0E),
+	HISI_PMU_EVENT_ATTR(snp_dvm_latency,		0x80),
+	HISI_PMU_EVENT_ATTR(snp_dvmsync_latency,	0x81),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvm_latency,	0x82),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_latency,	0x83),
+	HISI_PMU_EVENT_ATTR(mn_req_dvm_latency,		0x84),
+	HISI_PMU_EVENT_ATTR(mn_req_dvmsync_latency,	0x85),
+	HISI_PMU_EVENT_ATTR(pa_req_dvm_latency,		0x86),
+	HISI_PMU_EVENT_ATTR(pa_req_dvmsync_latency,	0x87),
+	NULL
+};
+
+static const struct attribute_group hisi_mn_pmu_events_group = {
+	.name = "events",
+	.attrs = hisi_mn_pmu_events_attr,
+};
+
+static const struct attribute_group *hisi_mn_pmu_attr_groups[] = {
+	&hisi_mn_pmu_format_group,
+	&hisi_mn_pmu_events_group,
+	&hisi_pmu_cpumask_attr_group,
+	&hisi_pmu_identifier_group,
+	NULL
+};
+
+static const struct hisi_uncore_ops hisi_uncore_mn_ops = {
+	.write_evtype		= hisi_mn_pmu_write_evtype,
+	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
+	.start_counters		= hisi_mn_pmu_start_counters,
+	.stop_counters		= hisi_mn_pmu_stop_counters,
+	.enable_counter		= hisi_mn_pmu_enable_counter,
+	.disable_counter	= hisi_mn_pmu_disable_counter,
+	.enable_counter_int	= hisi_mn_pmu_enable_counter_int,
+	.disable_counter_int	= hisi_mn_pmu_disable_counter_int,
+	.write_counter		= hisi_mn_pmu_write_counter,
+	.read_counter		= hisi_mn_pmu_read_counter,
+	.get_int_status		= hisi_mn_pmu_get_int_status,
+	.clear_int_status	= hisi_mn_pmu_clear_int_status,
+};
+
+static int hisi_mn_pmu_dev_init(struct platform_device *pdev,
+				struct hisi_pmu *mn_pmu)
+{
+	int ret;
+
+	hisi_uncore_pmu_init_topology(mn_pmu, &pdev->dev);
+
+	if (mn_pmu->topo.scl_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL,
+				     "Failed to read MN scl id\n");
+
+	if (mn_pmu->topo.index_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL,
+				     "Failed to read MN index id\n");
+
+	mn_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(mn_pmu->base))
+		return dev_err_probe(&pdev->dev, PTR_ERR(mn_pmu->base),
+				     "Failed to ioremap resource\n");
+
+	ret = hisi_uncore_pmu_init_irq(mn_pmu, pdev);
+	if (ret)
+		return ret;
+
+	mn_pmu->on_cpu = -1;
+	mn_pmu->dev = &pdev->dev;
+	mn_pmu->ops = &hisi_uncore_mn_ops;
+	mn_pmu->pmu_events.attr_groups = hisi_mn_pmu_attr_groups;
+	mn_pmu->check_event = HISI_MN_EVTYPE_MASK;
+	mn_pmu->num_counters = HISI_MN_NR_COUNTERS;
+	mn_pmu->counter_bits = HISI_MN_COUNTER_BITS;
+	mn_pmu->identifier = readl(mn_pmu->base + HISI_MN_VERSION_REG);
+	return 0;
+}
+
+static void hisi_mn_pmu_remove_cpuhp(void *hotplug_node)
+{
+	cpuhp_state_remove_instance_nocalls(hisi_mn_pmu_online, hotplug_node);
+}
+
+static void hisi_mn_pmu_unregister(void *pmu)
+{
+	perf_pmu_unregister(pmu);
+}
+
+static int hisi_mn_pmu_probe(struct platform_device *pdev)
+{
+	struct hisi_pmu *mn_pmu;
+	char *name;
+	int ret;
+
+	mn_pmu = devm_kzalloc(&pdev->dev, sizeof(*mn_pmu), GFP_KERNEL);
+	if (!mn_pmu)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mn_pmu);
+
+	ret = hisi_mn_pmu_dev_init(pdev, mn_pmu);
+	if (ret)
+		return ret;
+
+	name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_scl%d_mn%d",
+				mn_pmu->topo.scl_id, mn_pmu->topo.index_id);
+	if (!name)
+		return -ENOMEM;
+
+	ret = cpuhp_state_add_instance(hisi_mn_pmu_online, &mn_pmu->node);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Failed to register cpu hotplug\n");
+
+	ret = devm_add_action_or_reset(&pdev->dev, hisi_mn_pmu_remove_cpuhp, &mn_pmu->node);
+	if (ret)
+		return ret;
+
+	hisi_pmu_init(mn_pmu, THIS_MODULE);
+
+	ret = perf_pmu_register(&mn_pmu->pmu, name, -1);
+	if (ret)
+		return dev_err_probe(mn_pmu->dev, ret, "Failed to register MN PMU\n");
+
+	return devm_add_action_or_reset(&pdev->dev, hisi_mn_pmu_unregister, &mn_pmu->pmu);
+}
+
+static const struct acpi_device_id hisi_mn_pmu_acpi_match[] = {
+	{ "HISI0222", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_mn_pmu_acpi_match);
+
+static struct platform_driver hisi_mn_pmu_driver = {
+	.driver = {
+		.name = "hisi_mn_pmu",
+		.acpi_match_table = hisi_mn_pmu_acpi_match,
+		/*
+		 * We have not worked out a safe bind/unbind process,
+		 * Forcefully unbinding during sampling will lead to a
+		 * kernel panic, so this is not supported yet.
+		 */
+		.suppress_bind_attrs = true,
+	},
+	.probe = hisi_mn_pmu_probe,
+};
+
+static int __init hisi_mn_pmu_module_init(void)
+{
+	int ret;
+
+	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/mn:online",
+				      hisi_uncore_pmu_online_cpu,
+				      hisi_uncore_pmu_offline_cpu);
+	if (ret < 0) {
+		pr_err("hisi_mn_pmu: Failed to setup MN PMU hotplug: %d\n", ret);
+		return ret;
+	}
+	hisi_mn_pmu_online = ret;
+
+	ret = platform_driver_register(&hisi_mn_pmu_driver);
+	if (ret)
+		cpuhp_remove_multi_state(hisi_mn_pmu_online);
+
+	return ret;
+}
+module_init(hisi_mn_pmu_module_init);
+
+static void __exit hisi_mn_pmu_module_exit(void)
+{
+	platform_driver_unregister(&hisi_mn_pmu_driver);
+	cpuhp_remove_multi_state(hisi_mn_pmu_online);
+}
+module_exit(hisi_mn_pmu_module_exit);
+
+MODULE_IMPORT_NS("HISI_PMU");
+MODULE_DESCRIPTION("HiSilicon SoC MN uncore PMU driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Junhao He <hejunhao3 at huawei.com>");
-- 
2.24.0



From yangyicong at huawei.com  Fri Mar 21 00:38:43 2025
From: yangyicong at huawei.com (Yicong Yang)
Date: Fri, 21 Mar 2025 15:38:43 +0800
Subject: [PATCH v2 5/8] drivers/perf: hisi: Relax the event number check of v2 PMUs
In-Reply-To: <20250321073846.23507-1-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
Message-ID: <20250321073846.23507-6-yangyicong@huawei.com>

From: Junhao He <hejunhao3 at huawei.com>

The supported event number range of each Uncore PMUs is provided by
each driver in hisi_pmu::check_event and out of range events
will be rejected. A later version with expanded event number range
needs to register the PMU with updated hisi_pmu::check_event
even if it's the only update, which means the expanded events
cannot be used unless the driver's updated. However the unsupported
events won't be counted by the hardware so we can relax the event
number check to allow the use the expanded events.

Signed-off-by: Junhao He <hejunhao3 at huawei.com>
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
---
 drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +-
 drivers/perf/hisilicon/hisi_uncore_hha_pmu.c  | 6 +++---
 drivers/perf/hisilicon/hisi_uncore_pa_pmu.c   | 2 +-
 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 26eaa6d20c00..21c494881ca0 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -53,7 +53,7 @@
 #define DDRC_V1_PERF_CTRL_EN	0x2
 #define DDRC_V2_PERF_CTRL_EN	0x1
 #define DDRC_V1_NR_EVENTS	0x7
-#define DDRC_V2_NR_EVENTS	0x90
+#define DDRC_V2_NR_EVENTS	0xFF
 
 #define DDRC_EVENT_CNTn(base, n)	((base) + (n) * 8)
 #define DDRC_EVENT_TYPEn(base, n)	((base) + (n) * 4)
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index ca609db86046..97cfaa586a87 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -47,9 +47,9 @@
 #define HHA_SRCID_CMD		GENMASK(16, 6)
 #define HHA_SRCID_MSK		GENMASK(30, 20)
 #define HHA_DATSRC_SKT_EN	BIT(23)
-#define HHA_EVTYPE_NONE		0xff
+#define HHA_EVTYPE_MASK		GENMASK(7, 0)
 #define HHA_V1_NR_EVENT		0x65
-#define HHA_V2_NR_EVENT		0xCE
+#define HHA_V2_NR_EVENT		0xFF
 
 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 10, 0);
 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 21, 11);
@@ -197,7 +197,7 @@ static void hisi_hha_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
 
 	/* Write event code to HHA_EVENT_TYPEx register */
 	val = readl(hha_pmu->base + reg);
-	val &= ~(HHA_EVTYPE_NONE << shift);
+	val &= ~(HHA_EVTYPE_MASK << shift);
 	val |= (type << shift);
 	writel(val, hha_pmu->base + reg);
 }
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index a0142684e379..80108c63cb60 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -440,7 +440,7 @@ static int hisi_pa_pmu_dev_probe(struct platform_device *pdev,
 	pa_pmu->pmu_events.attr_groups = pa_pmu->dev_info->attr_groups;
 	pa_pmu->num_counters = PA_NR_COUNTERS;
 	pa_pmu->ops = &hisi_uncore_pa_ops;
-	pa_pmu->check_event = 0xB0;
+	pa_pmu->check_event = PA_EVTYPE_MASK;
 	pa_pmu->counter_bits = 64;
 	pa_pmu->dev = &pdev->dev;
 	pa_pmu->on_cpu = -1;
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 852114cfe3bf..cd32d606df05 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -58,7 +58,7 @@
 #define SLLC_V3_SRCID_CMD_SHIFT		1
 #define SLLC_V3_SRCID_MSK_SHIFT		10
 
-#define SLLC_NR_EVENTS			0x80
+#define SLLC_NR_EVENTS			0xff
 #define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
 
 HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0);
-- 
2.24.0



From krzk at kernel.org  Fri Mar 21 00:39:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 08:39:07 +0100
Subject: [PATCH v1 3/3] arm64: dts: qcom: x1e80100-qcp: Add power control
 and sideband signals for PCIe3
In-Reply-To: <20250320055502.274849-4-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-4-quic_wenbyao@quicinc.com>
Message-ID: <8379e009-9619-4c2b-986a-8ccb9ebaa083@kernel.org>

On 20/03/2025 06:55, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Add perst, wake and clkreq sideband signals and required regulators in
> PCIe3 controller and PHY device tree node. Describe the voltage rails of
> the x8 PCI slots for PCIe3 port.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
>  1 file changed, 119 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> index 28086a2bc..9cd313802 100644
> --- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> +++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
> @@ -318,6 +318,48 @@ vreg_wcn_3p3: regulator-wcn-3p3 {
>  		regulator-boot-on;
>  	};
>  
> +	vreg_pcie_12v: regulator-pcie_12v {

Don't send the downstream code.

Underscore are not allowed in node names plus:

Please use name for all fixed regulators which matches current format
recommendation: 'regulator-[0-9]v[0-9]'

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml?h=v6.11-rc1#n46

Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar 21 00:44:21 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 08:44:21 +0100
Subject: [PATCH v3 1/2] ARM: dts: aspeed: Add device tree for Nvidia's
 GB200NVL BMC
In-Reply-To: <20250320164633.101331-2-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
 <20250320164633.101331-2-wthai@nvidia.com>
Message-ID: <5127f2e7-cb38-4103-8799-551fdedd8152@kernel.org>

On 20/03/2025 17:46, Willie Thai wrote:
> +
> +	leds {
> +		compatible = "gpio-leds";
> +		led-0 {
> +			label = "uid_led";
> +			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
> +		};
> +		led-1 {
> +			label = "fault_led";
> +			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
> +		};
> +		led-2 {
> +			label = "power_led";
> +			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
> +		};
> +

You still have stray blank lines in few places.

> +	};
> +
> +	buttons {
> +		button-power {
> +			label = "power-btn";
> +			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
> +		};
> +		button-uid {
> +			label = "uid-btn";
> +			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +};
> +

...

> +/*
> + * Enable USB port A as device (via the virtual hub) to host
> + */
> +&vhub {
> +	status = "okay";
> +	pinctrl-names = "default";
> +	/*
> +	 * Uncomment below line to enable internal EHCI controller
> +	 * Current config uses xHCI Port1
> +	 */

Comment makes no sense.

> +};
> +
> +&video {
> +	status = "okay";
> +	memory-region = <&video_engine_memory>;
> +};
> +

...

> +&gpio0 {
> +	gpio-line-names =
> +		/*A0-A7*/ "", "", "", "", "", "", "", "",
> +		/*B0-B7*/ "", "", "", "", "", "", "", "",
> +		/*C0-C7*/ "SGPIO_I2C_MUX_SEL-O", "", "", "", "", "", "", "",
> +		/*D0-D7*/ "", "", "", "UART1_MUX_SEL-O", "", "FPGA_PEX_RST_L-O", "", "",
> +		/*E0-E7*/ "RTL8221_PHY_RST_L-O", "RTL8211_PHY_INT_L-I",	"", "UART3_MUX_SEL-O",
> +					"", "", "", "SGPIO_BMC_EN-O",
> +		/*F0-F7*/ "", "", "", "", "", "", "", "",
> +		/*G0-G7*/ "", "", "", "", "", "", "", "",
> +		/*H0-H7*/ "", "", "", "", "", "", "", "",
> +		/*I0-I7*/ "", "", "", "", "", "QSPI2_RST_L-O", "GLOBAL_WP_BMC-O", "BMC_DDR4_TEN-O",
> +		/*J0-J7*/ "", "", "", "", "", "", "", "",
> +		/*K0-K7*/ "", "", "", "", "", "", "", "",
> +		/*L0-L7*/ "", "", "", "", "", "", "", "",
> +		/*M0-M7*/ "PCIE_EP_RST_EN-O", "BMC_FRU_WP-O", "HMC_RESET_L-O", "STBY_POWER_EN-O",
> +					"STBY_POWER_PG-I", "PCIE_EP_RST_L-O", "", "",
> +		/*N0-N7*/ "", "", "", "", "", "", "", "",
> +		/*O0-O7*/ "", "", "", "", "", "", "", "",
> +		/*P0-P7*/ "", "", "", "", "", "", "", "",
> +		/*Q0-Q7*/ "", "", "", "", "", "", "", "",
> +		/*R0-R7*/ "", "", "", "", "", "", "", "",
> +		/*S0-S7*/ "", "", "", "", "", "", "", "",
> +		/*T0-T7*/ "", "", "", "", "", "", "", "",
> +		/*U0-U7*/ "", "", "", "", "", "", "", "",
> +		/*V0-V7*/ "AP_EROT_REQ-O", "EROT_AP_GNT-I", "", "","PCB_TEMP_ALERT-I", "","", "",
> +		/*W0-W7*/ "", "", "", "", "", "", "", "",
> +		/*X0-X7*/ "", "", "TPM_MUX_SEL-O", "", "", "", "", "",
> +		/*Y0-Y7*/ "", "", "", "EMMC_RST-O", "","", "", "",
> +		/*Z0-Z7*/ "BMC_READY-O","", "", "", "", "", "", "";
> +};
> +
> +&gpio1 {
> +	/* 36 1.8V GPIOs */
> +	gpio-line-names =
> +		/*A0-A7*/ "", "", "", "", "", "", "", "",
> +		/*B0-B7*/ "", "", "", "", "", "", "IO_EXPANDER_INT_L-I","",
> +		/*C0-C7*/ "", "", "", "", "", "", "", "",
> +		/*D0-D7*/ "", "", "", "", "", "", "SPI_HOST_TPM_RST_L-O", "SPI_BMC_FPGA_INT_L-I",
> +		/*E0-E7*/ "", "", "", "", "", "", "", "";
> +};
> +
> +// EMMC group that excludes WP pin
> +&pinctrl {
> +	pinctrl_emmcg5_default: emmcg5_default {

No underscores in node names.

> +		function = "EMMC";
> +		groups = "EMMCG5";
> +	};
> +};


Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar 21 00:59:36 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 08:59:36 +0100
Subject: [PATCH v5 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <DU7PR04MB111631E2E5B074A306033D001FFD92@DU7PR04MB11163.eurprd04.prod.outlook.com>
References: <20250318085444.3459380-1-florin.leotescu@oss.nxp.com>
 <20250318085444.3459380-2-florin.leotescu@oss.nxp.com>
 <20250319-optimistic-positive-peacock-cc26b1@krzk-bin>
 <DU7PR04MB111631E2E5B074A306033D001FFD92@DU7PR04MB11163.eurprd04.prod.outlook.com>
Message-ID: <b99eee70-5231-43fe-bff8-db92d78153e7@kernel.org>

On 19/03/2025 12:54, Florin Leotescu (OSS) wrote:

>> No blank line here. Use existing code as template. If you find such code, share so we can fix it.
> 
> Thanks!   I will remove it.
> 
> Identified similar blank line on the following dt-binding files:
> 
> 1 adi,ad741x.yaml
> 2 adi,adm1275.yaml
> 3 adi,ltc2991.yaml
> 4 maxim,max20730.yaml
> 5 maxim,max6639.yaml
> 6 maxim,max6650.yaml
> 7 nuvoton,nct6775.yaml
> 8 nuvoton,nct7363.yaml
> 9 nuvoton,nct7802.yaml
> 10 ti,adc128d818.yaml
> 11 ti,ads7828.yaml
> 12 ti,ina2xx.yaml
> 13 ti,lm87.yaml
> 14 ti,tmp513.yaml
> 15 ti,tps23861.yaml
> 16 winbond,w83781d.yaml

Oh, that's quite a lot. Thanks, I'll fix them.


Best regards,
Krzysztof


From m-malladi at ti.com  Fri Mar 21 01:01:29 2025
From: m-malladi at ti.com (Malladi, Meghana)
Date: Fri, 21 Mar 2025 13:31:29 +0530
Subject: [PATCH net-next 1/3] net: ti: prueth: Fix kernel warning while
 bringing down network interface
In-Reply-To: <20250320125349.GN280585@kernel.org>
References: <20250317101551.1005706-1-m-malladi@ti.com>
 <20250317101551.1005706-2-m-malladi@ti.com>
 <20250320125349.GN280585@kernel.org>
Message-ID: <48519536-6756-4d3d-9bb1-09197248df36@ti.com>

Hi Simon,
Thanks for reviewing the patch series.

On 3/20/2025 6:23 PM, Simon Horman wrote:
> On Mon, Mar 17, 2025 at 03:45:48PM +0530, Meghana Malladi wrote:
>> During network interface initialization, the NIC driver needs to register
>> its Rx queue with the XDP, to ensure the incoming XDP buffer carries a
>> pointer reference to this info and is stored inside xdp_rxq_info.
>>
>> While this struct isn't tied to XDP prog, if there are any changes in
>> Rx queue, the NIC driver needs to stop the Rx queue by unregistering
>> with XDP before purging and reallocating memory. Drop page_pool destroy
>> during Rx channel reset and this is already handled by XDP during
>> xdp_rxq_info_unreg (Rx queue unregister), failing to do will cause the
>> following warning:
>>
>> [  271.494611] ------------[ cut here ]------------
>> [  271.494629] WARNING: CPU: 0 PID: 2453 at /net/core/page_pool.c:1108 0xffff8000808d5f60
> 
> I think it would be nice to include a bit more of the stack trace here.
> 

Sure, I will attach a link to the warning logs in v2.

>>
>> Fixes: 46eeb90f03e0 ("net: ti: icssg-prueth: Use page_pool API for RX buffer allocation")
>> Signed-off-by: Meghana Malladi <m-malladi at ti.com>
> 
> It is a shame that we now have more asymmetry regarding
> the allocation of the pool and unwind on error prueth_prepare_rx_chan().
> 
> But if I see things correctly the freeing of the pool via
> xdp_rxq_info_unreg() is unconditional. And with that in mind
> I agree the approach taken by this patch makes sense.
> 

Agreed on the asymmetry part, but I am not quite convinced on why 
xdp_rxq_info_unreg() is freeing the pool unconditionally, when the 
driver is the one which is allocating the pool. If xdp_rxq_info_unreg() 
is freeing it, then shouldn't xdp_rxq_info_reg() be allocating it ?

> Reviewed-by: Simon Horman <horms at kernel.org>
> 
> ...



From krzk at kernel.org  Fri Mar 21 01:10:44 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 09:10:44 +0100
Subject: [PATCH v4 02/18] dt-bindings: gpu: img: Add BXS-4-64 devicetree
 bindings
In-Reply-To: <20250320-sets-bxs-4-64-patch-v1-v4-2-d987cf4ca439@imgtec.com>
References: <20250320-sets-bxs-4-64-patch-v1-v4-0-d987cf4ca439@imgtec.com>
 <20250320-sets-bxs-4-64-patch-v1-v4-2-d987cf4ca439@imgtec.com>
Message-ID: <20250321-liberal-muskox-of-reputation-edd6c0@krzk-bin>

On Thu, Mar 20, 2025 at 11:32:12AM +0000, Matt Coster wrote:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: img,img-bxs-4-64
> +    then:
> +      properties:
> +        power-domains:
> +          minItems: 2
> +        power-domain-names:
> +          minItems: 2
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            anyOf:

Instead: enum

> +              - const: ti,am62-gpu
> +              - const: ti,j721s2-gpu

Best regards,
Krzysztof



From m-malladi at ti.com  Fri Mar 21 01:13:11 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Fri, 21 Mar 2025 13:43:11 +0530
Subject: [PATCH net-next v2 1/3] net: ti: prueth: Fix kernel warning while bringing down network interface
In-Reply-To: <20250321081313.37112-1-m-malladi@ti.com>
References: <20250321081313.37112-1-m-malladi@ti.com>
Message-ID: <20250321081313.37112-2-m-malladi@ti.com>

During network interface initialization, the NIC driver needs to register
its Rx queue with the XDP, to ensure the incoming XDP buffer carries a
pointer reference to this info and is stored inside xdp_rxq_info.

While this struct isn't tied to XDP prog, if there are any changes in
Rx queue, the NIC driver needs to stop the Rx queue by unregistering
with XDP before purging and reallocating memory. Drop page_pool destroy
during Rx channel reset as this is already handled by XDP during
xdp_rxq_info_unreg (Rx queue unregister), failing to do will cause the
following warning:

warning logs: https://gist.github.com/MeghanaMalladiTI/eb627e5dc8de24e42d7d46572c13e576

Fixes: 46eeb90f03e0 ("net: ti: icssg-prueth: Use page_pool API for RX buffer allocation")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Simon Horman <horms at kernel.org>
---

Changes from v1(v2-v1):
- Included more trace logs for the warning
- Collected RB tag from Simon Horman <horms at kernel.org>

 drivers/net/ethernet/ti/icssg/icssg_common.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index df5da7a98abf..afa01c22dee8 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -1216,9 +1216,6 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
 					  prueth_rx_cleanup, !!i);
 	if (disable)
 		k3_udma_glue_disable_rx_chn(chn->rx_chn);
-
-	page_pool_destroy(chn->pg_pool);
-	chn->pg_pool = NULL;
 }
 EXPORT_SYMBOL_GPL(prueth_reset_rx_chan);
 
-- 
2.43.0



From m-malladi at ti.com  Fri Mar 21 01:13:12 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Fri, 21 Mar 2025 13:43:12 +0530
Subject: [PATCH net-next v2 2/3] net: ti: prueth: Fix possible NULL pointer dereference inside emac_xmit_xdp_frame()
In-Reply-To: <20250321081313.37112-1-m-malladi@ti.com>
References: <20250321081313.37112-1-m-malladi@ti.com>
Message-ID: <20250321081313.37112-3-m-malladi@ti.com>

There is an error check inside emac_xmit_xdp_frame() function which
is called when the driver wants to transmit XDP frame, to check if
the allocated tx descriptor is NULL, if true to exit and return
ICSSG_XDP_CONSUMED implying failure in transmission.

In this case trying to free a descriptor which is NULL will result
in kernel crash due to NULL pointer dereference. Fix this error handling
and increase netdev tx_dropped stats in the caller of this function
if the function returns ICSSG_XDP_CONSUMED.

Fixes: 62aa3246f462 ("net: ti: icssg-prueth: Add XDP support")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Simon Horman <horms at kernel.org>
---

Changes from v1(v2-v1):
- Collected RB tag from Simon Horman <horms at kernel.org>

 drivers/net/ethernet/ti/icssg/icssg_common.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index afa01c22dee8..f0224576b95f 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -584,7 +584,7 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
 	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
 	if (!first_desc) {
 		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
-		goto drop_free_descs;	/* drop */
+		return ICSSG_XDP_CONSUMED;	/* drop */
 	}
 
 	if (page) { /* already DMA mapped by page_pool */
@@ -672,8 +672,10 @@ static u32 emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
 
 		q_idx = smp_processor_id() % emac->tx_ch_num;
 		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
-		if (result == ICSSG_XDP_CONSUMED)
+		if (result == ICSSG_XDP_CONSUMED) {
+			ndev->stats.tx_dropped++;
 			goto drop;
+		}
 
 		dev_sw_netstats_rx_add(ndev, xdpf->len);
 		return result;
-- 
2.43.0



From m-malladi at ti.com  Fri Mar 21 01:13:13 2025
From: m-malladi at ti.com (Meghana Malladi)
Date: Fri, 21 Mar 2025 13:43:13 +0530
Subject: [PATCH net-next v2 3/3] net: ti: icss-iep: Fix possible NULL pointer dereference for perout request
In-Reply-To: <20250321081313.37112-1-m-malladi@ti.com>
References: <20250321081313.37112-1-m-malladi@ti.com>
Message-ID: <20250321081313.37112-4-m-malladi@ti.com>

Whenever there is a perout request from the user application,
kernel receives req structure containing the configuration info
for that req. Add NULL pointer handling for perout request if
that req struct points to NULL.

Fixes: e5b456a14215 ("net: ti: icss-iep: Add pwidth configuration for perout signal")
Signed-off-by: Meghana Malladi <m-malladi at ti.com>
Reviewed-by: Simon Horman <horms at kernel.org>
---

Changes from v1(v2-v1):
- Collected RB tag from Simon Horman <horms at kernel.org>

 drivers/net/ethernet/ti/icssg/icss_iep.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index b4a34c57b7b4..aeebdc4c121e 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -498,6 +498,10 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
 {
 	int ret = 0;
 
+	/* Return error if the req is NULL */
+	if (!req)
+		return -EINVAL;
+
 	/* Reject requests with unsupported flags */
 	if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
 			  PTP_PEROUT_PHASE))
-- 
2.43.0



From ioana.ciornei at nxp.com  Fri Mar 21 01:16:49 2025
From: ioana.ciornei at nxp.com (Ioana Ciornei)
Date: Fri, 21 Mar 2025 10:16:49 +0200
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <20241115152055.279732-1-linux@treblig.org>
References: <20241115152055.279732-1-linux@treblig.org>
Message-ID: <jz2ci3idg7kabbfunyzklolsgc4d3yla2oatma7nxodfvgqnp6@2yzm3yti5ljz>

On Fri, Nov 15, 2024 at 03:20:55PM +0000, linux at treblig.org wrote:
> From: "Dr. David Alan Gilbert" <linux at treblig.org>
> 
> fsl_mc_allocator_driver_exit() was added explicitly by
> commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> but was never used.
> 
> Remove it.
> 
> fsl_mc_portal_reset() was added in 2015 by
> commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> but was never used.
> 
> Remove it.
> 
> fsl_mc_portal_reset() was the only caller of dpmcp_reset().
> 
> Remove it.
> 
> Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>

Acked-by: Ioana Ciornei <ioana.ciornei at nxp.com>



From arnaud.pouliquen at foss.st.com  Fri Mar 21 01:22:30 2025
From: arnaud.pouliquen at foss.st.com (Arnaud POULIQUEN)
Date: Fri, 21 Mar 2025 09:22:30 +0100
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use
 of_reserved_mem_region_* functions for "memory-region"
In-Reply-To: <CAL_JsqJZkEpx26=ro_y8hHA2x1Zm6z_SFOQHjQ-WzUa-gy+s0w@mail.gmail.com>
References: <20250317232426.952188-1-robh@kernel.org>
 <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com>
 <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
 <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com>
 <CAL_JsqJZkEpx26=ro_y8hHA2x1Zm6z_SFOQHjQ-WzUa-gy+s0w@mail.gmail.com>
Message-ID: <4eddc37b-5164-453a-9b7f-c4331a7d6243@foss.st.com>



On 3/20/25 19:02, Rob Herring wrote:
> On Thu, Mar 20, 2025 at 4:23?AM Arnaud POULIQUEN
> <arnaud.pouliquen at foss.st.com> wrote:
>>
>>
>>
>> On 3/20/25 00:04, Rob Herring wrote:
>>> On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
>>> <arnaud.pouliquen at foss.st.com> wrote:
>>>>
>>>> Hello Rob,
>>>>
>>>> On 3/18/25 00:24, Rob Herring (Arm) wrote:
>>>>> Use the newly added of_reserved_mem_region_to_resource() and
>>>>> of_reserved_mem_region_count() functions to handle "memory-region"
>>>>> properties.
>>>>>
>>>>> The error handling is a bit different in some cases. Often
>>>>> "memory-region" is optional, so failed lookup is not an error. But then
>>>>> an error in of_reserved_mem_lookup() is treated as an error. However,
>>>>> that distinction is not really important. Either the region is available
>>>>> and usable or it is not. So now, it is just
>>>>> of_reserved_mem_region_to_resource() which is checked for an error.
>>>>>
>>>>> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
>>>>> ---
>>>>> For v6.16
>>>>>
>>>
>>> [...]
>>>
>>>>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
>>>>> index b02b36a3f515..9d2bd8904c49 100644
>>>>> --- a/drivers/remoteproc/stm32_rproc.c
>>>>> +++ b/drivers/remoteproc/stm32_rproc.c
>>>>> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>>>>>  {
>>>>>       struct device *dev = rproc->dev.parent;
>>>>>       struct device_node *np = dev->of_node;
>>>>> -     struct of_phandle_iterator it;
>>>>>       struct rproc_mem_entry *mem;
>>>>> -     struct reserved_mem *rmem;
>>>>>       u64 da;
>>>>> -     int index = 0;
>>>>> +     int index = 0, mr = 0;
>>>>>
>>>>>       /* Register associated reserved memory regions */
>>>>> -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
>>>>> -     while (of_phandle_iterator_next(&it) == 0) {
>>>>> -             rmem = of_reserved_mem_lookup(it.node);
>>>>> -             if (!rmem) {
>>>>> -                     of_node_put(it.node);
>>>>> -                     dev_err(dev, "unable to acquire memory-region\n");
>>>>> -                     return -EINVAL;
>>>>> -             }
>>>>> +     while (1) {
>>>>> +             struct resource res;
>>>>> +             int ret;
>>>>> +
>>>>> +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
>>>>> +             if (ret)
>>>>> +                     return 0;
>>>>>
>>>>> -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
>>>>> -                     of_node_put(it.node);
>>>>> -                     dev_err(dev, "memory region not valid %pa\n",
>>>>> -                             &rmem->base);
>>>>> +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
>>>>> +                     dev_err(dev, "memory region not valid %pR\n", &res);
>>>>>                       return -EINVAL;
>>>>>               }
>>>>>
>>>>>               /*  No need to map vdev buffer */
>>>>> -             if (strcmp(it.node->name, "vdev0buffer")) {
>>>>> +             if (strcmp(res.name, "vdev0buffer")) {
>>>>
>>>> I tested your patches
>>>
>>> Thank you.
>>>
>>>> The update introduces a regression here. The strcmp function never returns 0.
>>>> Indeed, it.node->name stores the memory region label "vdev0buffer," while
>>>> res.name stores the memory region name "vdev0buffer at 10042000."
>>>>
>>>> Several remoteproc drivers may face the same issue as they embed similar code.
>>>
>>> Indeed. I confused myself because node 'name' is without the
>>> unit-address, but this is using the full name. I've replaced the
>>> strcmp's with strstarts() to address this. I've updated my branch with
>>> the changes.
>>
>> This is not enough as the remoteproc core function rproc_find_carveout_by_name()
>> also compares the memory names. With the following additional fix, it is working
>> on my STM32MP15-DK board.
>>
>> @@ -309,11 +309,11 @@ rproc_find_carveout_by_name(struct rproc *rproc, const
>> char *name, ...)
>>         vsnprintf(_name, sizeof(_name), name, args);
>>         va_end(args);
>>
>>         list_for_each_entry(carveout, &rproc->carveouts, node) {
>>                 /* Compare carveout and requested names */
>> -               if (!strcmp(carveout->name, _name)) {
>> +               if (strstarts(carveout->name, _name)) {
>>                         mem = carveout;
>>                         break;
>>                 }
>>         }
>>
>> I just wonder if would not be more suitable to address this using the
>> "memory-region-names" field.
> 
> That would be better as you shouldn't really care what a provider node
> name is where-as "memory-region-names" is meaningful to the driver.
> 
>>
>> The drawback is that we would break compatibility with legacy boards...
> 
> So not an option.

> 
> I think I'll have to fix this within the reserved mem code storing the
> name or do something like the diff below. I'd like to avoid the
> former. Using the original device_node.name is also problematic
> because I want to get rid of it. We redundantly store the node name
> with and without the unit-address. There's a lot of places like this
> one where we hand out the pointer with no lifetime.
> 
> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> index 1e949694d365..cdee87c6ffe0 100644
> --- a/drivers/remoteproc/stm32_rproc.c
> +++ b/drivers/remoteproc/stm32_rproc.c
> @@ -239,7 +239,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>                                                    resource_size(&res), da,
>                                                    stm32_rproc_mem_alloc,
>                                                    stm32_rproc_mem_release,
> -                                                  res.name);
> +                                                  "%.*s",
> strchrnul(res.name, '@') - res.name, res.name);
> 
>                         if (mem)
>                                 rproc_coredump_add_segment(rproc, da,
> @@ -249,7 +249,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
>                         mem = rproc_of_resm_mem_entry_init(dev, index,
>                                                            resource_size(&res),
>                                                            res.start,
> -                                                          res.name);
> +                                                          "vdev0buffer");
>                 }
> 
>                 if (!mem) {


That's work on my side.
Could we have an OF helper to retrieve the name from the full name?

Thanks,
Arnaud


From arnd at arndb.de  Fri Mar 21 01:40:31 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 09:40:31 +0100
Subject: [soc:soc/drivers 20/24] ERROR: modpost: "__ffsdi2"
 [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
In-Reply-To: <202503211029.DnQpqsJs-lkp@intel.com>
References: <202503211029.DnQpqsJs-lkp@intel.com>
Message-ID: <927105f8-4aa8-4579-ac2e-bce4bce12b1e@app.fastmail.com>

On Fri, Mar 21, 2025, at 03:41, kernel test robot wrote:
> Hi Marek,
>
> First bad commit (maybe != root cause):
>
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git 
> soc/drivers
> head:   ba8755ab541fc629948233125db870d4dbf00a75
> commit: ee7f8ed72990f28657b5bf598e695fcf4633f4ed [20/24] platform: 
> cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
> config: sh-allmodconfig 
> (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/config)
> compiler: sh4-linux-gcc (GCC) 14.2.0
> reproduce (this is a W=1 build): 
> (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new 
> version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: 
> https://lore.kernel.org/oe-kbuild-all/202503211029.DnQpqsJs-lkp at intel.com/
>
> All errors (new ones prefixed by >>, old ones prefixed by <<):
>
> ERROR: modpost: "__delay" [drivers/net/mdio/mdio-cavium.ko] undefined!
> ERROR: modpost: "devm_of_clk_add_hw_provider" 
> [drivers/media/i2c/tc358746.ko] undefined!
> ERROR: modpost: "devm_clk_hw_register" [drivers/media/i2c/tc358746.ko] 
> undefined!
> ERROR: modpost: "of_clk_hw_simple_get" [drivers/media/i2c/tc358746.ko] 
> undefined!
>>> ERROR: modpost: "__ffsdi2" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!

This comes from __bf_shf(spec) in omnia_mcu_request_irq().

As far as I can tell, this is not your problem but in the
SH architecture missing one of the libgcc functions that are
called by gcc.

Since this is only for compile-testing sh allmodconfig, and
that is already broken because of other bugs, I'm not going
to care either.

Adding the linux-sh list to Cc, it would be nice to get a clean
build again. All four problems should be trivial to address,
and some of these have been broken for many years.

      Arnd


From arnd at arndb.de  Fri Mar 21 01:53:01 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 09:53:01 +0100
Subject: [soc:soc/drivers 22/24] drivers/platform/cznic/turris-signing-key.c:25:55:
 warning: omitting the parameter name in a function definition is a C2x
 extension
In-Reply-To: <202503211042.Uf5Ln7hI-lkp@intel.com>
References: <202503211042.Uf5Ln7hI-lkp@intel.com>
Message-ID: <e4c87dd0-1648-4453-9a0a-f38f0045cac9@app.fastmail.com>

On Fri, Mar 21, 2025, at 03:41, kernel test robot wrote:

> If you fix the issue in a separate patch/commit (i.e. not just a new 
> version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp at intel.com>
> | Closes: 
> https://lore.kernel.org/oe-kbuild-all/202503211042.Uf5Ln7hI-lkp at intel.com/
>
> All warnings (new ones prefixed by >>):
>
>>> drivers/platform/cznic/turris-signing-key.c:25:55: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
>       25 | static int turris_signing_key_instantiate(struct key *, 
> struct key_preparsed_payload *)
>          |                                                       ^
>    drivers/platform/cznic/turris-signing-key.c:25:87: warning: omitting 
> the parameter name in a function definition is a C2x extension 
> [-Wc2x-extensions]
>       25 | static int turris_signing_key_instantiate(struct key *, 
> struct key_preparsed_payload *)
>          |                                                              
>                          ^
>    2 warnings generated.

I've added a fix for this to the tree now. I was surprised that clang
warns about it but gcc does not, and apparently this was changed with
gcc-12 no longer warning about it.

     Arnd


From arnd at arndb.de  Fri Mar 21 01:55:17 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 09:55:17 +0100
Subject: linux-next: duplicate patches in the devicetree tree
In-Reply-To: <20250321153800.639f03c5@canb.auug.org.au>
References: <20250321153800.639f03c5@canb.auug.org.au>
Message-ID: <1eda0df7-a797-43b9-b3d0-3d1855b58e38@app.fastmail.com>

On Fri, Mar 21, 2025, at 05:38, Stephen Rothwell wrote:
> Hi all,
>
> The following commits are also in the arm-soc tree as different commits
> (but the same patches):
>
>   a78f7a337bc7 ("docs: process: maintainer-soc-clean-dts: linux-next is 
> decisive")
>   b31cc6af1bb1 ("docs: dt: submitting-patches: Document sending DTS 
> patches")
>
> These are commits
>
>   a42d2d53a6d7 ("docs: process: maintainer-soc-clean-dts: linux-next is 
> decisive")
>   d98d35d99e0f ("docs: dt: submitting-patches: Document sending DTS 
> patches")
>
> in the arm-soc tree.

My mistake, I saw them in the patchwork backlog and applied them.

I dropped them again now as they were still on the top of my branch.

    Arnd


From ot_cathy.xu at mediatek.com  Fri Mar 21 01:39:12 2025
From: ot_cathy.xu at mediatek.com (Cathy Xu)
Date: Fri, 21 Mar 2025 16:39:12 +0800
Subject: [PATCH v5 1/3] dt-bindings: pinctrl: mediatek: Add support for mt8196
In-Reply-To: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
Message-ID: <20250321084142.18563-2-ot_cathy.xu@mediatek.com>

Add the new binding document for pinctrl on MediaTek mt8196.

Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>
---
 .../pinctrl/mediatek,mt8196-pinctrl.yaml      | 223 ++++++++++++++++++
 1 file changed, 223 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/mediatek,mt8196-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8196-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8196-pinctrl.yaml
new file mode 100644
index 000000000000..d863cb7a301a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8196-pinctrl.yaml
@@ -0,0 +1,223 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/mediatek,mt8196-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT8196 Pin Controller
+
+maintainers:
+  - Lei Xue <lei.xue at mediatek.com>
+  - Cathy Xu <ot_cathy.xu at mediatek.com>
+
+description:
+  The MediaTek's MT8196 Pin controller is used to control SoC pins.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-pinctrl
+
+  gpio-controller: true
+
+  '#gpio-cells':
+    description:
+      Number of cells in GPIO specifier, should be two. The first cell is the
+      pin number, the second cell is used to specify optional parameters which
+      are defined in <dt-bindings/gpio/gpio.h>.
+    const: 2
+
+  gpio-ranges:
+    maxItems: 1
+
+  gpio-line-names: true
+
+  reg:
+    items:
+      - description: gpio registers base address
+      - description: rt group io configuration registers base address
+      - description: rm1 group io configuration registers base address
+      - description: rm2 group io configuration registers base address
+      - description: rb group io configuration registers base address
+      - description: bm1 group io configuration registers base address
+      - description: bm2 group io configuration registers base address
+      - description: bm3 group io configuration registers base address
+      - description: lt group io configuration registers base address
+      - description: lm1 group io configuration registers base address
+      - description: lm2 group io configuration registers base address
+      - description: lb1 group io configuration registers base address
+      - description: lb2 group io configuration registers base address
+      - description: tm1 group io configuration registers base address
+      - description: tm2 group io configuration registers base address
+      - description: tm3 group io configuration registers base address
+
+  reg-names:
+    items:
+      - const: iocfg0
+      - const: iocfg_rt
+      - const: iocfg_rm1
+      - const: iocfg_rm2
+      - const: iocfg_rb
+      - const: iocfg_bm1
+      - const: iocfg_bm2
+      - const: iocfg_bm3
+      - const: iocfg_lt
+      - const: iocfg_lm1
+      - const: iocfg_lm2
+      - const: iocfg_lb1
+      - const: iocfg_lb2
+      - const: iocfg_tm1
+      - const: iocfg_tm2
+      - const: iocfg_tm3
+
+  interrupt-controller: true
+
+  '#interrupt-cells':
+    const: 2
+
+  interrupts:
+    description: The interrupt outputs to sysirq.
+    maxItems: 1
+
+# PIN CONFIGURATION NODES
+patternProperties:
+  '-pins$':
+    type: object
+    additionalProperties: false
+
+    patternProperties:
+      '^pins':
+        type: object
+        $ref: /schemas/pinctrl/pincfg-node.yaml
+        additionalProperties: false
+        description:
+          A pinctrl node should contain at least one subnode representing the
+          pinctrl groups available on the machine. Each subnode will list the
+          pins it needs, and how they should be configured, with regard to muxer
+          configuration, pullups, drive strength, input enable/disable and input
+          schmitt.
+
+        properties:
+          pinmux:
+            description:
+              Integer array, represents gpio pin number and mux setting.
+              Supported pin number and mux varies for different SoCs, and are
+              defined as macros in arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
+              directly, for this SoC.
+
+          drive-strength:
+            enum: [2, 4, 6, 8, 10, 12, 14, 16]
+
+          bias-pull-down:
+            oneOf:
+              - type: boolean
+              - enum: [100, 101, 102, 103]
+                description: mt8196 pull down PUPD/R0/R1 type define value.
+              - enum: [75000, 5000]
+                description: mt8196 pull down RSEL type si unit value(ohm).
+            description: |
+              For pull down type is normal, it doesn't need add R1R0 define
+              and resistance value.
+              For pull down type is PUPD/R0/R1 type, it can add R1R0 define to
+              set different resistance. It can support "MTK_PUPD_SET_R1R0_00" &
+              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
+              "MTK_PUPD_SET_R1R0_11" define in mt8196.
+              For pull down type is PD/RSEL, it can add resistance value(ohm)
+              to set different resistance by identifying property
+              "mediatek,rsel-resistance-in-si-unit". It can support resistance
+              value(ohm) "75000" & "5000" in mt8196.
+
+          bias-pull-up:
+            oneOf:
+              - type: boolean
+              - enum: [100, 101, 102, 103]
+                description: mt8196 pull up PUPD/R0/R1 type define value.
+              - enum: [1000, 1500, 2000, 3000, 4000, 5000, 75000]
+                description: mt8196 pull up RSEL type si unit value(ohm).
+            description: |
+              For pull up type is normal, it don't need add R1R0 define
+              and resistance value.
+              For pull up type is PUPD/R0/R1 type, it can add R1R0 define to
+              set different resistance. It can support "MTK_PUPD_SET_R1R0_00" &
+              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
+              "MTK_PUPD_SET_R1R0_11" define in mt8196.
+              For pull up type is PU/RSEL, it can add resistance value(ohm)
+              to set different resistance by identifying property
+              "mediatek,rsel-resistance-in-si-unit". It can support resistance
+              value(ohm) "1000" & "1500" & "2000" & "3000" & "4000" & "5000" &
+              "75000" in mt8196.
+
+          bias-disable: true
+
+          output-high: true
+
+          output-low: true
+
+          input-enable: true
+
+          input-disable: true
+
+          input-schmitt-enable: true
+
+          input-schmitt-disable: true
+
+        required:
+          - pinmux
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-controller
+  - '#interrupt-cells'
+  - gpio-controller
+  - '#gpio-cells'
+  - gpio-ranges
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/pinctrl/mt65xx.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #define PINMUX_GPIO99__FUNC_SCL0 (MTK_PIN_NO(99) | 1)
+    #define PINMUX_GPIO100__FUNC_SDA0 (MTK_PIN_NO(100) | 1)
+
+    pio: pinctrl at 10005000 {
+        compatible = "mediatek,mt8196-pinctrl";
+        reg = <0x1002d000 0x1000>,
+              <0x12000000 0x1000>,
+              <0x12020000 0x1000>,
+              <0x12040000 0x1000>,
+              <0x12060000 0x1000>,
+              <0x12820000 0x1000>,
+              <0x12840000 0x1000>,
+              <0x12860000 0x1000>,
+              <0x13000000 0x1000>,
+              <0x13020000 0x1000>,
+              <0x13040000 0x1000>,
+              <0x130f0000 0x1000>,
+              <0x13110000 0x1000>,
+              <0x13800000 0x1000>,
+              <0x13820000 0x1000>,
+              <0x13860000 0x1000>;
+        reg-names = "iocfg0", "iocfg_rt",
+                    "iocfg_rm1", "iocfg_rm2", "iocfg_rb",
+                    "iocfg_bm1", "iocfg_bm2", "iocfg_bm3",
+                    "iocfg_lt", "iocfg_lm1", "iocfg_lm2",
+                    "iocfg_lb1", "iocfg_lb2", "iocfg_tm1",
+                    "iocfg_tm2", "iocfg_tm3";
+        gpio-controller;
+        #gpio-cells = <2>;
+        gpio-ranges = <&pio 0 0 271>;
+        interrupt-controller;
+        interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH 0>;
+        #interrupt-cells = <2>;
+
+        i2c0-pins {
+            pins {
+                pinmux = <PINMUX_GPIO99__FUNC_SCL0>,
+                         <PINMUX_GPIO100__FUNC_SDA0>;
+                bias-disable;
+            };
+        };
+    };
-- 
2.45.2



From ot_cathy.xu at mediatek.com  Fri Mar 21 01:39:13 2025
From: ot_cathy.xu at mediatek.com (Cathy Xu)
Date: Fri, 21 Mar 2025 16:39:13 +0800
Subject: [PATCH v5 2/3] arm64: dts: mediatek: mt8196: Add pinmux macro header file
In-Reply-To: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
Message-ID: <20250321084142.18563-3-ot_cathy.xu@mediatek.com>

Add the pinctrl header file on MediaTek mt8196.

Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h | 1574 +++++++++++++++++
 1 file changed, 1574 insertions(+)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h

diff --git a/arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
new file mode 100644
index 000000000000..2d49eda5853e
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
@@ -0,0 +1,1574 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (C) 2025 Mediatek Inc.
+ * Author: Guodong Liu <guodong.liu at mediatek.com>
+ *         Lei Xue <lei.xue at mediatek.com>
+ *         Cathy Xu <ot_cathy.xu at mediatek.com>
+ */
+
+#ifndef __MT8196_PINFUNC_H
+#define __MT8196_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define PINMUX_GPIO0__FUNC_DMIC1_CLK (MTK_PIN_NO(0) | 1)
+#define PINMUX_GPIO0__FUNC_SPI3_A_MO (MTK_PIN_NO(0) | 3)
+#define PINMUX_GPIO0__FUNC_FMI2S_B_LRCK (MTK_PIN_NO(0) | 4)
+#define PINMUX_GPIO0__FUNC_SCP_DMIC1_CLK (MTK_PIN_NO(0) | 5)
+#define PINMUX_GPIO0__FUNC_TP_GPIO14_AO (MTK_PIN_NO(0) | 6)
+
+#define PINMUX_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define PINMUX_GPIO1__FUNC_DMIC1_DAT (MTK_PIN_NO(1) | 1)
+#define PINMUX_GPIO1__FUNC_SRCLKENAI1 (MTK_PIN_NO(1) | 2)
+#define PINMUX_GPIO1__FUNC_SPI3_A_MI (MTK_PIN_NO(1) | 3)
+#define PINMUX_GPIO1__FUNC_FMI2S_B_DI (MTK_PIN_NO(1) | 4)
+#define PINMUX_GPIO1__FUNC_SCP_DMIC1_DAT (MTK_PIN_NO(1) | 5)
+#define PINMUX_GPIO1__FUNC_TP_GPIO15_AO (MTK_PIN_NO(1) | 6)
+
+#define PINMUX_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define PINMUX_GPIO2__FUNC_PWM_VLP (MTK_PIN_NO(2) | 1)
+#define PINMUX_GPIO2__FUNC_DSI_HSYNC (MTK_PIN_NO(2) | 2)
+#define PINMUX_GPIO2__FUNC_RG_TSFDC_LDO_EN (MTK_PIN_NO(2) | 5)
+#define PINMUX_GPIO2__FUNC_TP_GPIO8_AO (MTK_PIN_NO(2) | 6)
+
+#define PINMUX_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define PINMUX_GPIO3__FUNC_MD_INT0 (MTK_PIN_NO(3) | 1)
+#define PINMUX_GPIO3__FUNC_DSI1_HSYNC (MTK_PIN_NO(3) | 2)
+#define PINMUX_GPIO3__FUNC_DA_TSFDC_LDO_MODE (MTK_PIN_NO(3) | 5)
+#define PINMUX_GPIO3__FUNC_TP_GPIO9_AO (MTK_PIN_NO(3) | 6)
+
+#define PINMUX_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define PINMUX_GPIO4__FUNC_DISP_PWM1 (MTK_PIN_NO(4) | 1)
+#define PINMUX_GPIO4__FUNC_MD32_0_GPIO0 (MTK_PIN_NO(4) | 2)
+
+#define PINMUX_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define PINMUX_GPIO5__FUNC_LCM1_RST (MTK_PIN_NO(5) | 1)
+#define PINMUX_GPIO5__FUNC_SPI7_A_CLK (MTK_PIN_NO(5) | 2)
+
+#define PINMUX_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define PINMUX_GPIO6__FUNC_DSI1_TE (MTK_PIN_NO(6) | 1)
+#define PINMUX_GPIO6__FUNC_SPI7_A_CSB (MTK_PIN_NO(6) | 2)
+
+#define PINMUX_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define PINMUX_GPIO7__FUNC_SPI7_A_MO (MTK_PIN_NO(7) | 2)
+#define PINMUX_GPIO7__FUNC_GPS_PPS0 (MTK_PIN_NO(7) | 3)
+
+#define PINMUX_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define PINMUX_GPIO8__FUNC_SPI7_A_MI (MTK_PIN_NO(8) | 2)
+#define PINMUX_GPIO8__FUNC_EDP_TX_HPD (MTK_PIN_NO(8) | 3)
+
+#define PINMUX_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define PINMUX_GPIO9__FUNC_I2SIN1_LRCK (MTK_PIN_NO(9) | 3)
+#define PINMUX_GPIO9__FUNC_RG_TSFDC_LDO_REFSEL0 (MTK_PIN_NO(9) | 7)
+
+#define PINMUX_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define PINMUX_GPIO10__FUNC_I2SOUT1_DO (MTK_PIN_NO(10) | 3)
+#define PINMUX_GPIO10__FUNC_RG_TSFDC_LDO_REFSEL1 (MTK_PIN_NO(10) | 7)
+
+#define PINMUX_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define PINMUX_GPIO11__FUNC_FMI2S_B_BCK (MTK_PIN_NO(11) | 4)
+#define PINMUX_GPIO11__FUNC_DBG_MON_A30 (MTK_PIN_NO(11) | 7)
+
+#define PINMUX_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define PINMUX_GPIO12__FUNC_I2SIN1_DI_B (MTK_PIN_NO(12) | 3)
+
+#define PINMUX_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define PINMUX_GPIO13__FUNC_EDP_TX_HPD (MTK_PIN_NO(13) | 1)
+#define PINMUX_GPIO13__FUNC_GPS_PPS1 (MTK_PIN_NO(13) | 2)
+
+#define PINMUX_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define PINMUX_GPIO14__FUNC_SRCLKENA2 (MTK_PIN_NO(14) | 1)
+#define PINMUX_GPIO14__FUNC_DSI2_TE (MTK_PIN_NO(14) | 2)
+#define PINMUX_GPIO14__FUNC_SPMI_P_TRIG_FLAG (MTK_PIN_NO(14) | 3)
+#define PINMUX_GPIO14__FUNC_MD_INT3 (MTK_PIN_NO(14) | 5)
+#define PINMUX_GPIO14__FUNC_TP_GPIO8_AO (MTK_PIN_NO(14) | 6)
+
+#define PINMUX_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define PINMUX_GPIO15__FUNC_SRCLKENAI0 (MTK_PIN_NO(15) | 1)
+#define PINMUX_GPIO15__FUNC_SPMI_M_TRIG_FLAG (MTK_PIN_NO(15) | 2)
+#define PINMUX_GPIO15__FUNC_UCTS0 (MTK_PIN_NO(15) | 3)
+#define PINMUX_GPIO15__FUNC_MD_INT4 (MTK_PIN_NO(15) | 4)
+#define PINMUX_GPIO15__FUNC_I2SOUT2_DO (MTK_PIN_NO(15) | 5)
+#define PINMUX_GPIO15__FUNC_TP_GPIO9_AO (MTK_PIN_NO(15) | 6)
+
+#define PINMUX_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define PINMUX_GPIO16__FUNC_SRCLKENAI1 (MTK_PIN_NO(16) | 1)
+#define PINMUX_GPIO16__FUNC_DP_TX_HPD (MTK_PIN_NO(16) | 2)
+#define PINMUX_GPIO16__FUNC_URTS0 (MTK_PIN_NO(16) | 3)
+#define PINMUX_GPIO16__FUNC_GPS_L5_ELNA_EN (MTK_PIN_NO(16) | 4)
+#define PINMUX_GPIO16__FUNC_KPROW2 (MTK_PIN_NO(16) | 5)
+#define PINMUX_GPIO16__FUNC_TP_GPIO10_AO (MTK_PIN_NO(16) | 6)
+
+#define PINMUX_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define PINMUX_GPIO17__FUNC_MD_INT0 (MTK_PIN_NO(17) | 1)
+#define PINMUX_GPIO17__FUNC_DP_OC_EN (MTK_PIN_NO(17) | 2)
+#define PINMUX_GPIO17__FUNC_UCTS1 (MTK_PIN_NO(17) | 3)
+#define PINMUX_GPIO17__FUNC_MD_NTN_URXD1 (MTK_PIN_NO(17) | 4)
+#define PINMUX_GPIO17__FUNC_KPCOL2 (MTK_PIN_NO(17) | 5)
+#define PINMUX_GPIO17__FUNC_TP_GPIO11_AO (MTK_PIN_NO(17) | 6)
+
+#define PINMUX_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define PINMUX_GPIO18__FUNC_DMIC1_CLK (MTK_PIN_NO(18) | 1)
+#define PINMUX_GPIO18__FUNC_DP_RAUX_SBU1 (MTK_PIN_NO(18) | 2)
+#define PINMUX_GPIO18__FUNC_URTS1 (MTK_PIN_NO(18) | 3)
+#define PINMUX_GPIO18__FUNC_MD_NTN_UTXD1 (MTK_PIN_NO(18) | 4)
+#define PINMUX_GPIO18__FUNC_I2SIN2_DI (MTK_PIN_NO(18) | 5)
+#define PINMUX_GPIO18__FUNC_TP_UTXD_GNSS_VLP (MTK_PIN_NO(18) | 6)
+
+#define PINMUX_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define PINMUX_GPIO19__FUNC_DMIC1_DAT (MTK_PIN_NO(19) | 1)
+#define PINMUX_GPIO19__FUNC_DP_RAUX_SBU2 (MTK_PIN_NO(19) | 2)
+#define PINMUX_GPIO19__FUNC_CONN_TCXOENA_REQ (MTK_PIN_NO(19) | 3)
+#define PINMUX_GPIO19__FUNC_CLKM3_A (MTK_PIN_NO(19) | 4)
+#define PINMUX_GPIO19__FUNC_I2SIN2_BCK (MTK_PIN_NO(19) | 5)
+#define PINMUX_GPIO19__FUNC_TP_URXD_GNSS_VLP (MTK_PIN_NO(19) | 6)
+
+#define PINMUX_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define PINMUX_GPIO20__FUNC_IDDIG (MTK_PIN_NO(20) | 1)
+#define PINMUX_GPIO20__FUNC_LCM2_RST (MTK_PIN_NO(20) | 2)
+#define PINMUX_GPIO20__FUNC_GPS_PPS1 (MTK_PIN_NO(20) | 3)
+#define PINMUX_GPIO20__FUNC_CLKM2_A (MTK_PIN_NO(20) | 4)
+
+#define PINMUX_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define PINMUX_GPIO21__FUNC_BPI_BUS11 (MTK_PIN_NO(21) | 1)
+#define PINMUX_GPIO21__FUNC_PCIE_PERSTN_1P (MTK_PIN_NO(21) | 2)
+#define PINMUX_GPIO21__FUNC_DSI1_TE (MTK_PIN_NO(21) | 3)
+#define PINMUX_GPIO21__FUNC_DMIC_CLK (MTK_PIN_NO(21) | 4)
+#define PINMUX_GPIO21__FUNC_SCP_DMIC_CLK (MTK_PIN_NO(21) | 5)
+
+#define PINMUX_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define PINMUX_GPIO22__FUNC_BPI_BUS12 (MTK_PIN_NO(22) | 1)
+#define PINMUX_GPIO22__FUNC_PCIE_CLKREQN_1P (MTK_PIN_NO(22) | 2)
+#define PINMUX_GPIO22__FUNC_DSI2_TE (MTK_PIN_NO(22) | 3)
+#define PINMUX_GPIO22__FUNC_DMIC_DAT (MTK_PIN_NO(22) | 4)
+#define PINMUX_GPIO22__FUNC_SCP_DMIC_DAT (MTK_PIN_NO(22) | 5)
+
+#define PINMUX_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define PINMUX_GPIO23__FUNC_BPI_BUS13 (MTK_PIN_NO(23) | 1)
+#define PINMUX_GPIO23__FUNC_PCIE_WAKEN_1P (MTK_PIN_NO(23) | 2)
+#define PINMUX_GPIO23__FUNC_DSI3_TE (MTK_PIN_NO(23) | 3)
+#define PINMUX_GPIO23__FUNC_DMIC1_CLK (MTK_PIN_NO(23) | 4)
+#define PINMUX_GPIO23__FUNC_SCP_DMIC1_CLK (MTK_PIN_NO(23) | 5)
+
+#define PINMUX_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define PINMUX_GPIO24__FUNC_BPI_BUS14 (MTK_PIN_NO(24) | 1)
+#define PINMUX_GPIO24__FUNC_LCM1_RST (MTK_PIN_NO(24) | 2)
+#define PINMUX_GPIO24__FUNC_AGPS_SYNC (MTK_PIN_NO(24) | 3)
+#define PINMUX_GPIO24__FUNC_DMIC1_DAT (MTK_PIN_NO(24) | 4)
+#define PINMUX_GPIO24__FUNC_SCP_DMIC1_DAT (MTK_PIN_NO(24) | 5)
+#define PINMUX_GPIO24__FUNC_DISP_PWM1 (MTK_PIN_NO(24) | 6)
+
+#define PINMUX_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define PINMUX_GPIO25__FUNC_BPI_BUS15 (MTK_PIN_NO(25) | 1)
+#define PINMUX_GPIO25__FUNC_LCM2_RST (MTK_PIN_NO(25) | 2)
+#define PINMUX_GPIO25__FUNC_SRCLKENAI1 (MTK_PIN_NO(25) | 3)
+#define PINMUX_GPIO25__FUNC_DMIC2_CLK (MTK_PIN_NO(25) | 4)
+#define PINMUX_GPIO25__FUNC_DISP_PWM2 (MTK_PIN_NO(25) | 6)
+
+#define PINMUX_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define PINMUX_GPIO26__FUNC_BPI_BUS16 (MTK_PIN_NO(26) | 1)
+#define PINMUX_GPIO26__FUNC_LCM3_RST (MTK_PIN_NO(26) | 2)
+#define PINMUX_GPIO26__FUNC_DMIC2_DAT (MTK_PIN_NO(26) | 4)
+#define PINMUX_GPIO26__FUNC_DISP_PWM3 (MTK_PIN_NO(26) | 6)
+
+#define PINMUX_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define PINMUX_GPIO27__FUNC_BPI_BUS17 (MTK_PIN_NO(27) | 1)
+#define PINMUX_GPIO27__FUNC_UTXD4 (MTK_PIN_NO(27) | 2)
+#define PINMUX_GPIO27__FUNC_DISP_PWM4 (MTK_PIN_NO(27) | 6)
+#define PINMUX_GPIO27__FUNC_DBG_MON_A20 (MTK_PIN_NO(27) | 7)
+
+#define PINMUX_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define PINMUX_GPIO28__FUNC_BPI_BUS18 (MTK_PIN_NO(28) | 1)
+#define PINMUX_GPIO28__FUNC_URXD4 (MTK_PIN_NO(28) | 2)
+#define PINMUX_GPIO28__FUNC_SPI2_A_MI (MTK_PIN_NO(28) | 3)
+#define PINMUX_GPIO28__FUNC_CLKM0_A (MTK_PIN_NO(28) | 4)
+#define PINMUX_GPIO28__FUNC_DBG_MON_A21 (MTK_PIN_NO(28) | 7)
+
+#define PINMUX_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define PINMUX_GPIO29__FUNC_BPI_BUS19 (MTK_PIN_NO(29) | 1)
+#define PINMUX_GPIO29__FUNC_MD_NTN_UTXD1 (MTK_PIN_NO(29) | 2)
+#define PINMUX_GPIO29__FUNC_SPI2_A_MO (MTK_PIN_NO(29) | 3)
+#define PINMUX_GPIO29__FUNC_CLKM1_A (MTK_PIN_NO(29) | 4)
+#define PINMUX_GPIO29__FUNC_UCTS4 (MTK_PIN_NO(29) | 6)
+#define PINMUX_GPIO29__FUNC_DBG_MON_A17 (MTK_PIN_NO(29) | 7)
+
+#define PINMUX_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define PINMUX_GPIO30__FUNC_BPI_BUS20 (MTK_PIN_NO(30) | 1)
+#define PINMUX_GPIO30__FUNC_MD_NTN_URXD1 (MTK_PIN_NO(30) | 2)
+#define PINMUX_GPIO30__FUNC_SPI2_A_CLK (MTK_PIN_NO(30) | 3)
+#define PINMUX_GPIO30__FUNC_CLKM2_A (MTK_PIN_NO(30) | 4)
+#define PINMUX_GPIO30__FUNC_DSI3_HSYNC (MTK_PIN_NO(30) | 5)
+#define PINMUX_GPIO30__FUNC_URTS4 (MTK_PIN_NO(30) | 6)
+#define PINMUX_GPIO30__FUNC_DBG_MON_A18 (MTK_PIN_NO(30) | 7)
+
+#define PINMUX_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define PINMUX_GPIO31__FUNC_BPI_BUS21 (MTK_PIN_NO(31) | 1)
+#define PINMUX_GPIO31__FUNC_SPI2_A_CSB (MTK_PIN_NO(31) | 3)
+#define PINMUX_GPIO31__FUNC_CLKM3_A (MTK_PIN_NO(31) | 4)
+#define PINMUX_GPIO31__FUNC_EDP_TX_HPD (MTK_PIN_NO(31) | 6)
+#define PINMUX_GPIO31__FUNC_DBG_MON_A19 (MTK_PIN_NO(31) | 7)
+
+#define PINMUX_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define PINMUX_GPIO32__FUNC_LCM4_RST (MTK_PIN_NO(32) | 1)
+#define PINMUX_GPIO32__FUNC_DP_TX_HPD (MTK_PIN_NO(32) | 2)
+#define PINMUX_GPIO32__FUNC_SSPM_JTAG_TCK_VLP (MTK_PIN_NO(32) | 3)
+#define PINMUX_GPIO32__FUNC_ADSP_JTAG0_TCK (MTK_PIN_NO(32) | 4)
+#define PINMUX_GPIO32__FUNC_SCP_JTAG0_TCK_VLP (MTK_PIN_NO(32) | 5)
+#define PINMUX_GPIO32__FUNC_SPU0_TCK (MTK_PIN_NO(32) | 6)
+#define PINMUX_GPIO32__FUNC_IO_JTAG_TCK (MTK_PIN_NO(32) | 7)
+
+#define PINMUX_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define PINMUX_GPIO33__FUNC_DSI4_TE (MTK_PIN_NO(33) | 1)
+#define PINMUX_GPIO33__FUNC_DP_OC_EN (MTK_PIN_NO(33) | 2)
+#define PINMUX_GPIO33__FUNC_SSPM_JTAG_TRSTN_VLP (MTK_PIN_NO(33) | 3)
+#define PINMUX_GPIO33__FUNC_ADSP_JTAG0_TRSTN (MTK_PIN_NO(33) | 4)
+#define PINMUX_GPIO33__FUNC_SCP_JTAG0_TRSTN_VLP (MTK_PIN_NO(33) | 5)
+#define PINMUX_GPIO33__FUNC_SPU0_NTRST (MTK_PIN_NO(33) | 6)
+#define PINMUX_GPIO33__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(33) | 7)
+
+#define PINMUX_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define PINMUX_GPIO34__FUNC_UCTS5 (MTK_PIN_NO(34) | 1)
+#define PINMUX_GPIO34__FUNC_DP_RAUX_SBU1 (MTK_PIN_NO(34) | 2)
+#define PINMUX_GPIO34__FUNC_SSPM_JTAG_TDI_VLP (MTK_PIN_NO(34) | 3)
+#define PINMUX_GPIO34__FUNC_ADSP_JTAG0_TDI (MTK_PIN_NO(34) | 4)
+#define PINMUX_GPIO34__FUNC_SCP_JTAG0_TDI_VLP (MTK_PIN_NO(34) | 5)
+#define PINMUX_GPIO34__FUNC_SPU0_TDI (MTK_PIN_NO(34) | 6)
+#define PINMUX_GPIO34__FUNC_IO_JTAG_TDI (MTK_PIN_NO(34) | 7)
+
+#define PINMUX_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define PINMUX_GPIO35__FUNC_URTS5 (MTK_PIN_NO(35) | 1)
+#define PINMUX_GPIO35__FUNC_DP_RAUX_SBU2 (MTK_PIN_NO(35) | 2)
+#define PINMUX_GPIO35__FUNC_SSPM_JTAG_TDO_VLP (MTK_PIN_NO(35) | 3)
+#define PINMUX_GPIO35__FUNC_ADSP_JTAG0_TDO (MTK_PIN_NO(35) | 4)
+#define PINMUX_GPIO35__FUNC_SCP_JTAG0_TDO_VLP (MTK_PIN_NO(35) | 5)
+#define PINMUX_GPIO35__FUNC_SPU0_TDO (MTK_PIN_NO(35) | 6)
+#define PINMUX_GPIO35__FUNC_IO_JTAG_TDO (MTK_PIN_NO(35) | 7)
+
+#define PINMUX_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define PINMUX_GPIO36__FUNC_UTXD5 (MTK_PIN_NO(36) | 1)
+#define PINMUX_GPIO36__FUNC_SSPM_JTAG_TMS_VLP (MTK_PIN_NO(36) | 3)
+#define PINMUX_GPIO36__FUNC_ADSP_JTAG0_TMS (MTK_PIN_NO(36) | 4)
+#define PINMUX_GPIO36__FUNC_SCP_JTAG0_TMS_VLP (MTK_PIN_NO(36) | 5)
+#define PINMUX_GPIO36__FUNC_SPU0_TMS (MTK_PIN_NO(36) | 6)
+#define PINMUX_GPIO36__FUNC_IO_JTAG_TMS (MTK_PIN_NO(36) | 7)
+
+#define PINMUX_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define PINMUX_GPIO37__FUNC_URXD5 (MTK_PIN_NO(37) | 1)
+#define PINMUX_GPIO37__FUNC_MD_INT3 (MTK_PIN_NO(37) | 3)
+#define PINMUX_GPIO37__FUNC_CLKM0_B (MTK_PIN_NO(37) | 4)
+#define PINMUX_GPIO37__FUNC_TP_GPIO5_AO (MTK_PIN_NO(37) | 5)
+#define PINMUX_GPIO37__FUNC_SPU0_UTX (MTK_PIN_NO(37) | 6)
+#define PINMUX_GPIO37__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(37) | 7)
+
+#define PINMUX_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define PINMUX_GPIO38__FUNC_SPMI_P_TRIG_FLAG (MTK_PIN_NO(38) | 2)
+#define PINMUX_GPIO38__FUNC_MD_INT4 (MTK_PIN_NO(38) | 3)
+#define PINMUX_GPIO38__FUNC_CLKM1_B (MTK_PIN_NO(38) | 4)
+#define PINMUX_GPIO38__FUNC_TP_GPIO6_AO (MTK_PIN_NO(38) | 5)
+#define PINMUX_GPIO38__FUNC_SPU0_URX (MTK_PIN_NO(38) | 6)
+#define PINMUX_GPIO38__FUNC_DAP_MD32_SWD (MTK_PIN_NO(38) | 7)
+
+#define PINMUX_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define PINMUX_GPIO39__FUNC_I2S_MCK0 (MTK_PIN_NO(39) | 1)
+#define PINMUX_GPIO39__FUNC_GPS_PPS0 (MTK_PIN_NO(39) | 3)
+#define PINMUX_GPIO39__FUNC_CONN_TCXOENA_REQ (MTK_PIN_NO(39) | 4)
+#define PINMUX_GPIO39__FUNC_DBG_MON_B12 (MTK_PIN_NO(39) | 7)
+
+#define PINMUX_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define PINMUX_GPIO40__FUNC_I2SIN6_0_BCK (MTK_PIN_NO(40) | 1)
+#define PINMUX_GPIO40__FUNC_SPI4_B_CLK (MTK_PIN_NO(40) | 3)
+#define PINMUX_GPIO40__FUNC_UCTS2 (MTK_PIN_NO(40) | 4)
+#define PINMUX_GPIO40__FUNC_CCU1_UTXD (MTK_PIN_NO(40) | 5)
+#define PINMUX_GPIO40__FUNC_DBG_MON_B13 (MTK_PIN_NO(40) | 7)
+
+#define PINMUX_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define PINMUX_GPIO41__FUNC_I2SIN6_0_LRCK (MTK_PIN_NO(41) | 1)
+#define PINMUX_GPIO41__FUNC_SPI4_B_CSB (MTK_PIN_NO(41) | 3)
+#define PINMUX_GPIO41__FUNC_URTS2 (MTK_PIN_NO(41) | 4)
+#define PINMUX_GPIO41__FUNC_CCU1_URXD (MTK_PIN_NO(41) | 5)
+#define PINMUX_GPIO41__FUNC_DBG_MON_B14 (MTK_PIN_NO(41) | 7)
+
+#define PINMUX_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define PINMUX_GPIO42__FUNC_I2SIN6_0_DI (MTK_PIN_NO(42) | 1)
+#define PINMUX_GPIO42__FUNC_SPI4_B_MI (MTK_PIN_NO(42) | 3)
+#define PINMUX_GPIO42__FUNC_URXD2 (MTK_PIN_NO(42) | 4)
+#define PINMUX_GPIO42__FUNC_CCU1_URTS (MTK_PIN_NO(42) | 5)
+#define PINMUX_GPIO42__FUNC_MD32_0_RXD (MTK_PIN_NO(42) | 6)
+#define PINMUX_GPIO42__FUNC_DBG_MON_B15 (MTK_PIN_NO(42) | 7)
+
+#define PINMUX_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define PINMUX_GPIO43__FUNC_I2SOUT6_0_DO (MTK_PIN_NO(43) | 1)
+#define PINMUX_GPIO43__FUNC_SPI4_B_MO (MTK_PIN_NO(43) | 3)
+#define PINMUX_GPIO43__FUNC_UTXD2 (MTK_PIN_NO(43) | 4)
+#define PINMUX_GPIO43__FUNC_CCU1_UCTS (MTK_PIN_NO(43) | 5)
+#define PINMUX_GPIO43__FUNC_MD32_0_TXD (MTK_PIN_NO(43) | 6)
+#define PINMUX_GPIO43__FUNC_DBG_MON_B16 (MTK_PIN_NO(43) | 7)
+
+#define PINMUX_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define PINMUX_GPIO44__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(44) | 1)
+#define PINMUX_GPIO44__FUNC_SPI3_A_CLK (MTK_PIN_NO(44) | 3)
+#define PINMUX_GPIO44__FUNC_TP_GPIO10_AO (MTK_PIN_NO(44) | 6)
+
+#define PINMUX_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define PINMUX_GPIO45__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(45) | 1)
+#define PINMUX_GPIO45__FUNC_DSI2_HSYNC (MTK_PIN_NO(45) | 2)
+#define PINMUX_GPIO45__FUNC_SPI3_A_CSB (MTK_PIN_NO(45) | 3)
+#define PINMUX_GPIO45__FUNC_PWM_VLP (MTK_PIN_NO(45) | 4)
+#define PINMUX_GPIO45__FUNC_TP_GPIO11_AO (MTK_PIN_NO(45) | 6)
+
+#define PINMUX_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define PINMUX_GPIO46__FUNC_SCP_SCL4 (MTK_PIN_NO(46) | 1)
+#define PINMUX_GPIO46__FUNC_PWM_VLP (MTK_PIN_NO(46) | 2)
+#define PINMUX_GPIO46__FUNC_SCP_ILDO_DTEST1_VLP (MTK_PIN_NO(46) | 4)
+#define PINMUX_GPIO46__FUNC_UFS_MPHY_SCL (MTK_PIN_NO(46) | 5)
+#define PINMUX_GPIO46__FUNC_TP_GPIO0_AO (MTK_PIN_NO(46) | 6)
+
+#define PINMUX_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define PINMUX_GPIO47__FUNC_SCP_SDA4 (MTK_PIN_NO(47) | 1)
+#define PINMUX_GPIO47__FUNC_SCP_ILDO_DTEST2_VLP (MTK_PIN_NO(47) | 4)
+#define PINMUX_GPIO47__FUNC_UFS_MPHY_SDA (MTK_PIN_NO(47) | 5)
+#define PINMUX_GPIO47__FUNC_TP_GPIO1_AO (MTK_PIN_NO(47) | 6)
+
+#define PINMUX_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define PINMUX_GPIO48__FUNC_SCP_SCL5 (MTK_PIN_NO(48) | 1)
+#define PINMUX_GPIO48__FUNC_PWM_VLP (MTK_PIN_NO(48) | 2)
+#define PINMUX_GPIO48__FUNC_CCU0_UTXD (MTK_PIN_NO(48) | 3)
+#define PINMUX_GPIO48__FUNC_SCP_ILDO_DTEST3_VLP (MTK_PIN_NO(48) | 4)
+#define PINMUX_GPIO48__FUNC_TP_GPIO2_AO (MTK_PIN_NO(48) | 6)
+
+#define PINMUX_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define PINMUX_GPIO49__FUNC_SCP_SDA5 (MTK_PIN_NO(49) | 1)
+#define PINMUX_GPIO49__FUNC_CCU0_URXD (MTK_PIN_NO(49) | 3)
+#define PINMUX_GPIO49__FUNC_SCP_ILDO_DTEST4_VLP (MTK_PIN_NO(49) | 4)
+#define PINMUX_GPIO49__FUNC_TP_GPIO3_AO (MTK_PIN_NO(49) | 6)
+
+#define PINMUX_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define PINMUX_GPIO50__FUNC_SCP_SCL6 (MTK_PIN_NO(50) | 1)
+#define PINMUX_GPIO50__FUNC_PWM_VLP (MTK_PIN_NO(50) | 2)
+#define PINMUX_GPIO50__FUNC_CCU0_URTS (MTK_PIN_NO(50) | 3)
+#define PINMUX_GPIO50__FUNC_DSI_HSYNC (MTK_PIN_NO(50) | 4)
+#define PINMUX_GPIO50__FUNC_TP_GPIO4_AO (MTK_PIN_NO(50) | 6)
+
+#define PINMUX_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define PINMUX_GPIO51__FUNC_SCP_SDA6 (MTK_PIN_NO(51) | 1)
+#define PINMUX_GPIO51__FUNC_CCU0_UCTS (MTK_PIN_NO(51) | 3)
+#define PINMUX_GPIO51__FUNC_DSI1_HSYNC (MTK_PIN_NO(51) | 4)
+#define PINMUX_GPIO51__FUNC_TP_GPIO5_AO (MTK_PIN_NO(51) | 6)
+
+#define PINMUX_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define PINMUX_GPIO52__FUNC_SCP_SCL1 (MTK_PIN_NO(52) | 1)
+#define PINMUX_GPIO52__FUNC_TDM_DATA2 (MTK_PIN_NO(52) | 3)
+
+#define PINMUX_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define PINMUX_GPIO53__FUNC_SCP_SDA1 (MTK_PIN_NO(53) | 1)
+#define PINMUX_GPIO53__FUNC_TDM_DATA3 (MTK_PIN_NO(53) | 3)
+
+#define PINMUX_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define PINMUX_GPIO54__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(54) | 1)
+#define PINMUX_GPIO54__FUNC_TDM_MCK (MTK_PIN_NO(54) | 3)
+
+#define PINMUX_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define PINMUX_GPIO55__FUNC_AUD_CLK_MISO (MTK_PIN_NO(55) | 1)
+#define PINMUX_GPIO55__FUNC_I2SOUT2_BCK (MTK_PIN_NO(55) | 2)
+#define PINMUX_GPIO55__FUNC_TDM_BCK (MTK_PIN_NO(55) | 3)
+
+#define PINMUX_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define PINMUX_GPIO56__FUNC_AUD_DAT_MOSI0 (MTK_PIN_NO(56) | 1)
+#define PINMUX_GPIO56__FUNC_I2SOUT2_LRCK (MTK_PIN_NO(56) | 2)
+#define PINMUX_GPIO56__FUNC_TDM_LRCK (MTK_PIN_NO(56) | 3)
+
+#define PINMUX_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define PINMUX_GPIO57__FUNC_AUD_DAT_MOSI1 (MTK_PIN_NO(57) | 1)
+#define PINMUX_GPIO57__FUNC_I2SOUT2_DO (MTK_PIN_NO(57) | 2)
+#define PINMUX_GPIO57__FUNC_TDM_DATA0 (MTK_PIN_NO(57) | 3)
+
+#define PINMUX_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define PINMUX_GPIO58__FUNC_AUD_DAT_MISO0 (MTK_PIN_NO(58) | 1)
+#define PINMUX_GPIO58__FUNC_TDM_DATA1 (MTK_PIN_NO(58) | 3)
+
+#define PINMUX_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define PINMUX_GPIO59__FUNC_AUD_DAT_MISO1 (MTK_PIN_NO(59) | 1)
+#define PINMUX_GPIO59__FUNC_I2SIN1_BCK (MTK_PIN_NO(59) | 3)
+
+#define PINMUX_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define PINMUX_GPIO60__FUNC_KPCOL0 (MTK_PIN_NO(60) | 1)
+#define PINMUX_GPIO60__FUNC_TP_GPIO13_AO (MTK_PIN_NO(60) | 6)
+
+#define PINMUX_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define PINMUX_GPIO61__FUNC_MCU_M_PMIC_POC_I (MTK_PIN_NO(61) | 1)
+
+#define PINMUX_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define PINMUX_GPIO62__FUNC_MCU_B_PMIC_POC_I (MTK_PIN_NO(62) | 1)
+
+#define PINMUX_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define PINMUX_GPIO63__FUNC_MFG_PMIC_POC_I (MTK_PIN_NO(63) | 1)
+
+#define PINMUX_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define PINMUX_GPIO64__FUNC_PRE_UVLO (MTK_PIN_NO(64) | 1)
+
+#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define PINMUX_GPIO65__FUNC_DPM2PMIC (MTK_PIN_NO(65) | 1)
+#define PINMUX_GPIO65__FUNC_SRCLKENA1 (MTK_PIN_NO(65) | 2)
+
+#define PINMUX_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define PINMUX_GPIO66__FUNC_WATCHDOG (MTK_PIN_NO(66) | 1)
+
+#define PINMUX_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define PINMUX_GPIO67__FUNC_SRCLKENA0 (MTK_PIN_NO(67) | 1)
+
+#define PINMUX_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define PINMUX_GPIO68__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(68) | 1)
+
+#define PINMUX_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define PINMUX_GPIO69__FUNC_RTC32K_CK (MTK_PIN_NO(69) | 1)
+
+#define PINMUX_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define PINMUX_GPIO70__FUNC_CMFLASH0 (MTK_PIN_NO(70) | 1)
+
+#define PINMUX_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+
+#define PINMUX_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+
+#define PINMUX_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+
+#define PINMUX_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define PINMUX_GPIO74__FUNC_DCXO_FPM_LPM (MTK_PIN_NO(74) | 1)
+
+#define PINMUX_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define PINMUX_GPIO75__FUNC_SPMI_M_SCL (MTK_PIN_NO(75) | 1)
+
+#define PINMUX_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define PINMUX_GPIO76__FUNC_SPMI_M_SDA (MTK_PIN_NO(76) | 1)
+
+#define PINMUX_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define PINMUX_GPIO77__FUNC_SPMI_P_SCL (MTK_PIN_NO(77) | 1)
+
+#define PINMUX_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define PINMUX_GPIO78__FUNC_SPMI_P_SDA (MTK_PIN_NO(78) | 1)
+
+#define PINMUX_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define PINMUX_GPIO79__FUNC_CMMCLK0 (MTK_PIN_NO(79) | 1)
+#define PINMUX_GPIO79__FUNC_MD_INT4 (MTK_PIN_NO(79) | 2)
+
+#define PINMUX_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define PINMUX_GPIO80__FUNC_CMMCLK1 (MTK_PIN_NO(80) | 1)
+
+#define PINMUX_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define PINMUX_GPIO81__FUNC_SCP_SPI0_CK (MTK_PIN_NO(81) | 1)
+#define PINMUX_GPIO81__FUNC_SPI6_B_CLK (MTK_PIN_NO(81) | 2)
+#define PINMUX_GPIO81__FUNC_PWM_VLP (MTK_PIN_NO(81) | 3)
+#define PINMUX_GPIO81__FUNC_I2SOUT5_BCK (MTK_PIN_NO(81) | 4)
+#define PINMUX_GPIO81__FUNC_TP_GPIO0_AO (MTK_PIN_NO(81) | 6)
+
+#define PINMUX_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define PINMUX_GPIO82__FUNC_SCP_SPI0_CS (MTK_PIN_NO(82) | 1)
+#define PINMUX_GPIO82__FUNC_SPI6_B_CSB (MTK_PIN_NO(82) | 2)
+#define PINMUX_GPIO82__FUNC_I2SOUT5_LRCK (MTK_PIN_NO(82) | 4)
+#define PINMUX_GPIO82__FUNC_TP_GPIO1_AO (MTK_PIN_NO(82) | 6)
+
+#define PINMUX_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define PINMUX_GPIO83__FUNC_SCP_SPI0_MO (MTK_PIN_NO(83) | 1)
+#define PINMUX_GPIO83__FUNC_SPI6_B_MO (MTK_PIN_NO(83) | 2)
+#define PINMUX_GPIO83__FUNC_I2SOUT5_DATA0 (MTK_PIN_NO(83) | 4)
+#define PINMUX_GPIO83__FUNC_TP_GPIO2_AO (MTK_PIN_NO(83) | 6)
+
+#define PINMUX_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define PINMUX_GPIO84__FUNC_SCP_SPI0_MI (MTK_PIN_NO(84) | 1)
+#define PINMUX_GPIO84__FUNC_SPI6_B_MI (MTK_PIN_NO(84) | 2)
+#define PINMUX_GPIO84__FUNC_I2SOUT5_DATA1 (MTK_PIN_NO(84) | 4)
+#define PINMUX_GPIO84__FUNC_TP_GPIO3_AO (MTK_PIN_NO(84) | 6)
+
+#define PINMUX_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define PINMUX_GPIO85__FUNC_SCP_SPI1_CK (MTK_PIN_NO(85) | 1)
+#define PINMUX_GPIO85__FUNC_SPI7_B_CLK (MTK_PIN_NO(85) | 2)
+#define PINMUX_GPIO85__FUNC_I2SIN5_DATA0 (MTK_PIN_NO(85) | 4)
+#define PINMUX_GPIO85__FUNC_PWM_VLP (MTK_PIN_NO(85) | 5)
+#define PINMUX_GPIO85__FUNC_TP_GPIO4_AO (MTK_PIN_NO(85) | 6)
+
+#define PINMUX_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define PINMUX_GPIO86__FUNC_SCP_SPI1_CS (MTK_PIN_NO(86) | 1)
+#define PINMUX_GPIO86__FUNC_SPI7_B_CSB (MTK_PIN_NO(86) | 2)
+#define PINMUX_GPIO86__FUNC_I2SIN5_DATA1 (MTK_PIN_NO(86) | 4)
+#define PINMUX_GPIO86__FUNC_TP_GPIO5_AO (MTK_PIN_NO(86) | 6)
+
+#define PINMUX_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define PINMUX_GPIO87__FUNC_SCP_SPI1_MO (MTK_PIN_NO(87) | 1)
+#define PINMUX_GPIO87__FUNC_SPI7_B_MO (MTK_PIN_NO(87) | 2)
+#define PINMUX_GPIO87__FUNC_I2SIN5_BCK (MTK_PIN_NO(87) | 4)
+#define PINMUX_GPIO87__FUNC_TP_GPIO6_AO (MTK_PIN_NO(87) | 6)
+
+#define PINMUX_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define PINMUX_GPIO88__FUNC_SCP_SPI1_MI (MTK_PIN_NO(88) | 1)
+#define PINMUX_GPIO88__FUNC_SPI7_B_MI (MTK_PIN_NO(88) | 2)
+#define PINMUX_GPIO88__FUNC_I2SIN5_LRCK (MTK_PIN_NO(88) | 4)
+#define PINMUX_GPIO88__FUNC_TP_GPIO7_AO (MTK_PIN_NO(88) | 6)
+
+#define PINMUX_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define PINMUX_GPIO89__FUNC_DSI_TE (MTK_PIN_NO(89) | 1)
+#define PINMUX_GPIO89__FUNC_DSI1_TE (MTK_PIN_NO(89) | 2)
+#define PINMUX_GPIO89__FUNC_DBG_MON_B30 (MTK_PIN_NO(89) | 7)
+
+#define PINMUX_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define PINMUX_GPIO90__FUNC_LCM_RST (MTK_PIN_NO(90) | 1)
+#define PINMUX_GPIO90__FUNC_LCM1_RST (MTK_PIN_NO(90) | 2)
+#define PINMUX_GPIO90__FUNC_DBG_MON_B31 (MTK_PIN_NO(90) | 7)
+
+#define PINMUX_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define PINMUX_GPIO91__FUNC_CMFLASH2 (MTK_PIN_NO(91) | 1)
+#define PINMUX_GPIO91__FUNC_SF_D0 (MTK_PIN_NO(91) | 2)
+#define PINMUX_GPIO91__FUNC_SRCLKENAI1 (MTK_PIN_NO(91) | 3)
+#define PINMUX_GPIO91__FUNC_KPCOL2 (MTK_PIN_NO(91) | 5)
+#define PINMUX_GPIO91__FUNC_TP_GPIO11_AO (MTK_PIN_NO(91) | 6)
+
+#define PINMUX_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define PINMUX_GPIO92__FUNC_CMFLASH3 (MTK_PIN_NO(92) | 1)
+#define PINMUX_GPIO92__FUNC_SF_D1 (MTK_PIN_NO(92) | 2)
+#define PINMUX_GPIO92__FUNC_DISP_PWM1 (MTK_PIN_NO(92) | 4)
+#define PINMUX_GPIO92__FUNC_TP_GPIO12_AO (MTK_PIN_NO(92) | 6)
+
+#define PINMUX_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define PINMUX_GPIO93__FUNC_CMFLASH1 (MTK_PIN_NO(93) | 1)
+#define PINMUX_GPIO93__FUNC_SF_D2 (MTK_PIN_NO(93) | 2)
+#define PINMUX_GPIO93__FUNC_SRCLKENAI0 (MTK_PIN_NO(93) | 3)
+#define PINMUX_GPIO93__FUNC_KPROW2 (MTK_PIN_NO(93) | 5)
+#define PINMUX_GPIO93__FUNC_TP_GPIO13_AO (MTK_PIN_NO(93) | 6)
+
+#define PINMUX_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define PINMUX_GPIO94__FUNC_I2S_MCK1 (MTK_PIN_NO(94) | 1)
+#define PINMUX_GPIO94__FUNC_SF_D3 (MTK_PIN_NO(94) | 2)
+#define PINMUX_GPIO94__FUNC_MD32_0_GPIO0 (MTK_PIN_NO(94) | 4)
+#define PINMUX_GPIO94__FUNC_CLKM0_A (MTK_PIN_NO(94) | 5)
+#define PINMUX_GPIO94__FUNC_TP_GPIO14_AO (MTK_PIN_NO(94) | 6)
+#define PINMUX_GPIO94__FUNC_DBG_MON_B18 (MTK_PIN_NO(94) | 7)
+
+#define PINMUX_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define PINMUX_GPIO95__FUNC_I2SIN1_BCK (MTK_PIN_NO(95) | 1)
+#define PINMUX_GPIO95__FUNC_I2SIN4_BCK (MTK_PIN_NO(95) | 2)
+#define PINMUX_GPIO95__FUNC_SPI6_A_CLK (MTK_PIN_NO(95) | 3)
+#define PINMUX_GPIO95__FUNC_MD32_1_GPIO0 (MTK_PIN_NO(95) | 4)
+#define PINMUX_GPIO95__FUNC_CLKM1_A (MTK_PIN_NO(95) | 5)
+#define PINMUX_GPIO95__FUNC_TP_GPIO15_AO (MTK_PIN_NO(95) | 6)
+#define PINMUX_GPIO95__FUNC_DBG_MON_B19 (MTK_PIN_NO(95) | 7)
+
+#define PINMUX_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define PINMUX_GPIO96__FUNC_I2SIN1_LRCK (MTK_PIN_NO(96) | 1)
+#define PINMUX_GPIO96__FUNC_I2SIN4_LRCK (MTK_PIN_NO(96) | 2)
+#define PINMUX_GPIO96__FUNC_SPI6_A_CSB (MTK_PIN_NO(96) | 3)
+#define PINMUX_GPIO96__FUNC_MD32_2_GPIO0 (MTK_PIN_NO(96) | 4)
+#define PINMUX_GPIO96__FUNC_CLKM2_A (MTK_PIN_NO(96) | 5)
+#define PINMUX_GPIO96__FUNC_DBG_MON_B20 (MTK_PIN_NO(96) | 7)
+
+#define PINMUX_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define PINMUX_GPIO97__FUNC_I2SIN1_DI_A (MTK_PIN_NO(97) | 1)
+#define PINMUX_GPIO97__FUNC_I2SIN4_DATA0 (MTK_PIN_NO(97) | 2)
+#define PINMUX_GPIO97__FUNC_SPI6_A_MO (MTK_PIN_NO(97) | 3)
+#define PINMUX_GPIO97__FUNC_MD32_3_GPIO0 (MTK_PIN_NO(97) | 4)
+#define PINMUX_GPIO97__FUNC_CLKM3_A (MTK_PIN_NO(97) | 5)
+#define PINMUX_GPIO97__FUNC_DBG_MON_B21 (MTK_PIN_NO(97) | 7)
+
+#define PINMUX_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define PINMUX_GPIO98__FUNC_I2SOUT1_DO (MTK_PIN_NO(98) | 1)
+#define PINMUX_GPIO98__FUNC_I2SOUT4_DATA0 (MTK_PIN_NO(98) | 2)
+#define PINMUX_GPIO98__FUNC_SPI6_A_MI (MTK_PIN_NO(98) | 3)
+#define PINMUX_GPIO98__FUNC_DBG_MON_B22 (MTK_PIN_NO(98) | 7)
+
+#define PINMUX_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define PINMUX_GPIO99__FUNC_SCL0 (MTK_PIN_NO(99) | 1)
+#define PINMUX_GPIO99__FUNC_LCM2_RST (MTK_PIN_NO(99) | 2)
+#define PINMUX_GPIO99__FUNC_AUD_DAC_26M_CLK (MTK_PIN_NO(99) | 3)
+#define PINMUX_GPIO99__FUNC_SPU0_SCL (MTK_PIN_NO(99) | 4)
+#define PINMUX_GPIO99__FUNC_DBG_MON_B24 (MTK_PIN_NO(99) | 7)
+
+#define PINMUX_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define PINMUX_GPIO100__FUNC_SDA0 (MTK_PIN_NO(100) | 1)
+#define PINMUX_GPIO100__FUNC_DSI2_TE (MTK_PIN_NO(100) | 2)
+#define PINMUX_GPIO100__FUNC_SPU0_SDA (MTK_PIN_NO(100) | 4)
+#define PINMUX_GPIO100__FUNC_DBG_MON_B25 (MTK_PIN_NO(100) | 7)
+
+#define PINMUX_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define PINMUX_GPIO101__FUNC_SCL10 (MTK_PIN_NO(101) | 1)
+#define PINMUX_GPIO101__FUNC_SF_CS (MTK_PIN_NO(101) | 2)
+#define PINMUX_GPIO101__FUNC_SCP_DMIC1_CLK (MTK_PIN_NO(101) | 3)
+#define PINMUX_GPIO101__FUNC_I2SIN5_DATA2 (MTK_PIN_NO(101) | 4)
+#define PINMUX_GPIO101__FUNC_SCP_SCL_OIS (MTK_PIN_NO(101) | 5)
+#define PINMUX_GPIO101__FUNC_TP_GPIO10_AO (MTK_PIN_NO(101) | 6)
+#define PINMUX_GPIO101__FUNC_DBG_MON_B28 (MTK_PIN_NO(101) | 7)
+
+#define PINMUX_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define PINMUX_GPIO102__FUNC_SDA10 (MTK_PIN_NO(102) | 1)
+#define PINMUX_GPIO102__FUNC_SF_CK (MTK_PIN_NO(102) | 2)
+#define PINMUX_GPIO102__FUNC_SCP_DMIC1_DAT (MTK_PIN_NO(102) | 3)
+#define PINMUX_GPIO102__FUNC_I2SIN5_DATA3 (MTK_PIN_NO(102) | 4)
+#define PINMUX_GPIO102__FUNC_SCP_SDA_OIS (MTK_PIN_NO(102) | 5)
+#define PINMUX_GPIO102__FUNC_TP_GPIO11_AO (MTK_PIN_NO(102) | 6)
+#define PINMUX_GPIO102__FUNC_DBG_MON_B29 (MTK_PIN_NO(102) | 7)
+
+#define PINMUX_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define PINMUX_GPIO103__FUNC_DISP_PWM (MTK_PIN_NO(103) | 1)
+#define PINMUX_GPIO103__FUNC_DSI1_TE (MTK_PIN_NO(103) | 2)
+#define PINMUX_GPIO103__FUNC_I2S_MCK0 (MTK_PIN_NO(103) | 5)
+#define PINMUX_GPIO103__FUNC_DBG_MON_B23 (MTK_PIN_NO(103) | 7)
+
+#define PINMUX_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define PINMUX_GPIO104__FUNC_SCL6 (MTK_PIN_NO(104) | 1)
+#define PINMUX_GPIO104__FUNC_SPU1_SCL (MTK_PIN_NO(104) | 2)
+#define PINMUX_GPIO104__FUNC_AUD_DAC_26M_CLK (MTK_PIN_NO(104) | 3)
+#define PINMUX_GPIO104__FUNC_USB_DRVVBUS_2P (MTK_PIN_NO(104) | 4)
+#define PINMUX_GPIO104__FUNC_I2S_MCK1 (MTK_PIN_NO(104) | 5)
+#define PINMUX_GPIO104__FUNC_IDDIG_2P (MTK_PIN_NO(104) | 6)
+#define PINMUX_GPIO104__FUNC_DBG_MON_B26 (MTK_PIN_NO(104) | 7)
+
+#define PINMUX_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define PINMUX_GPIO105__FUNC_SDA6 (MTK_PIN_NO(105) | 1)
+#define PINMUX_GPIO105__FUNC_SPU1_SDA (MTK_PIN_NO(105) | 2)
+#define PINMUX_GPIO105__FUNC_DISP_PWM2 (MTK_PIN_NO(105) | 3)
+#define PINMUX_GPIO105__FUNC_VBUSVALID_2P (MTK_PIN_NO(105) | 4)
+#define PINMUX_GPIO105__FUNC_I2S_MCK2 (MTK_PIN_NO(105) | 5)
+#define PINMUX_GPIO105__FUNC_VBUSVALID_3P (MTK_PIN_NO(105) | 6)
+#define PINMUX_GPIO105__FUNC_DBG_MON_B27 (MTK_PIN_NO(105) | 7)
+
+#define PINMUX_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define PINMUX_GPIO106__FUNC_SCP_SPI3_CK (MTK_PIN_NO(106) | 1)
+#define PINMUX_GPIO106__FUNC_SPI3_B_CLK (MTK_PIN_NO(106) | 2)
+#define PINMUX_GPIO106__FUNC_MD_UTXD0 (MTK_PIN_NO(106) | 3)
+#define PINMUX_GPIO106__FUNC_TP_UTXD1_VLP (MTK_PIN_NO(106) | 4)
+#define PINMUX_GPIO106__FUNC_CONN_BG_GPS_MCU_UART0_TXD (MTK_PIN_NO(106) | 5)
+#define PINMUX_GPIO106__FUNC_TP_GPIO6_AO (MTK_PIN_NO(106) | 6)
+#define PINMUX_GPIO106__FUNC_DBG_MON_B0 (MTK_PIN_NO(106) | 7)
+
+#define PINMUX_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define PINMUX_GPIO107__FUNC_SCP_SPI3_CS (MTK_PIN_NO(107) | 1)
+#define PINMUX_GPIO107__FUNC_SPI3_B_CSB (MTK_PIN_NO(107) | 2)
+#define PINMUX_GPIO107__FUNC_MD_URXD0 (MTK_PIN_NO(107) | 3)
+#define PINMUX_GPIO107__FUNC_TP_URXD1_VLP (MTK_PIN_NO(107) | 4)
+#define PINMUX_GPIO107__FUNC_CONN_BG_GPS_MCU_UART0_RXD (MTK_PIN_NO(107) | 5)
+#define PINMUX_GPIO107__FUNC_TP_GPIO7_AO (MTK_PIN_NO(107) | 6)
+#define PINMUX_GPIO107__FUNC_DBG_MON_B1 (MTK_PIN_NO(107) | 7)
+
+#define PINMUX_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define PINMUX_GPIO108__FUNC_SCP_SPI3_MO (MTK_PIN_NO(108) | 1)
+#define PINMUX_GPIO108__FUNC_SPI3_B_MO (MTK_PIN_NO(108) | 2)
+#define PINMUX_GPIO108__FUNC_MD_UTXD1 (MTK_PIN_NO(108) | 3)
+#define PINMUX_GPIO108__FUNC_MD32PCM_UTXD_AO_VLP (MTK_PIN_NO(108) | 4)
+#define PINMUX_GPIO108__FUNC_CONN_BG_GPS_MCU_UART1_TXD (MTK_PIN_NO(108) | 5)
+#define PINMUX_GPIO108__FUNC_TP_GPIO8_AO (MTK_PIN_NO(108) | 6)
+#define PINMUX_GPIO108__FUNC_DBG_MON_B2 (MTK_PIN_NO(108) | 7)
+
+#define PINMUX_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define PINMUX_GPIO109__FUNC_SCP_SPI3_MI (MTK_PIN_NO(109) | 1)
+#define PINMUX_GPIO109__FUNC_SPI3_B_MI (MTK_PIN_NO(109) | 2)
+#define PINMUX_GPIO109__FUNC_MD_URXD1 (MTK_PIN_NO(109) | 3)
+#define PINMUX_GPIO109__FUNC_MD32PCM_URXD_AO_VLP (MTK_PIN_NO(109) | 4)
+#define PINMUX_GPIO109__FUNC_CONN_BG_GPS_MCU_UART1_RXD (MTK_PIN_NO(109) | 5)
+#define PINMUX_GPIO109__FUNC_TP_GPIO9_AO (MTK_PIN_NO(109) | 6)
+#define PINMUX_GPIO109__FUNC_DBG_MON_B3 (MTK_PIN_NO(109) | 7)
+
+#define PINMUX_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define PINMUX_GPIO110__FUNC_SPI1_CLK (MTK_PIN_NO(110) | 1)
+#define PINMUX_GPIO110__FUNC_PWM_0 (MTK_PIN_NO(110) | 2)
+#define PINMUX_GPIO110__FUNC_MD_UCTS0 (MTK_PIN_NO(110) | 3)
+#define PINMUX_GPIO110__FUNC_TP_UCTS1_VLP (MTK_PIN_NO(110) | 4)
+#define PINMUX_GPIO110__FUNC_SPU0_GPIO_O (MTK_PIN_NO(110) | 6)
+#define PINMUX_GPIO110__FUNC_DBG_MON_B4 (MTK_PIN_NO(110) | 7)
+
+#define PINMUX_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define PINMUX_GPIO111__FUNC_SPI1_CSB (MTK_PIN_NO(111) | 1)
+#define PINMUX_GPIO111__FUNC_PWM_1 (MTK_PIN_NO(111) | 2)
+#define PINMUX_GPIO111__FUNC_MD_URTS0 (MTK_PIN_NO(111) | 3)
+#define PINMUX_GPIO111__FUNC_TP_URTS1_VLP (MTK_PIN_NO(111) | 4)
+#define PINMUX_GPIO111__FUNC_SPU0_GPIO_I (MTK_PIN_NO(111) | 6)
+#define PINMUX_GPIO111__FUNC_DBG_MON_B5 (MTK_PIN_NO(111) | 7)
+
+#define PINMUX_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define PINMUX_GPIO112__FUNC_SPI1_MO (MTK_PIN_NO(112) | 1)
+#define PINMUX_GPIO112__FUNC_PWM_2 (MTK_PIN_NO(112) | 2)
+#define PINMUX_GPIO112__FUNC_MD_UCTS1 (MTK_PIN_NO(112) | 3)
+#define PINMUX_GPIO112__FUNC_SPU1_GPIO_O (MTK_PIN_NO(112) | 6)
+#define PINMUX_GPIO112__FUNC_DBG_MON_B6 (MTK_PIN_NO(112) | 7)
+
+#define PINMUX_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define PINMUX_GPIO113__FUNC_SPI1_MI (MTK_PIN_NO(113) | 1)
+#define PINMUX_GPIO113__FUNC_PWM_3 (MTK_PIN_NO(113) | 2)
+#define PINMUX_GPIO113__FUNC_MD_URTS1 (MTK_PIN_NO(113) | 3)
+#define PINMUX_GPIO113__FUNC_SPU1_GPIO_I (MTK_PIN_NO(113) | 6)
+#define PINMUX_GPIO113__FUNC_DBG_MON_B7 (MTK_PIN_NO(113) | 7)
+
+#define PINMUX_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define PINMUX_GPIO114__FUNC_SPI0_SPU_CLK (MTK_PIN_NO(114) | 1)
+#define PINMUX_GPIO114__FUNC_SPI4_A_CLK (MTK_PIN_NO(114) | 2)
+#define PINMUX_GPIO114__FUNC_CONN_BG_GPS_MCU_DBG_UART_TXD (MTK_PIN_NO(114) | 5)
+#define PINMUX_GPIO114__FUNC_DBG_MON_B8 (MTK_PIN_NO(114) | 7)
+
+#define PINMUX_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define PINMUX_GPIO115__FUNC_SPI0_SPU_CSB (MTK_PIN_NO(115) | 1)
+#define PINMUX_GPIO115__FUNC_SPI4_A_CSB (MTK_PIN_NO(115) | 2)
+#define PINMUX_GPIO115__FUNC_DBG_MON_B9 (MTK_PIN_NO(115) | 7)
+
+#define PINMUX_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define PINMUX_GPIO116__FUNC_SPI0_SPU_MO (MTK_PIN_NO(116) | 1)
+#define PINMUX_GPIO116__FUNC_SPI4_A_MO (MTK_PIN_NO(116) | 2)
+#define PINMUX_GPIO116__FUNC_LCM1_RST (MTK_PIN_NO(116) | 3)
+#define PINMUX_GPIO116__FUNC_DBG_MON_B10 (MTK_PIN_NO(116) | 7)
+
+#define PINMUX_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define PINMUX_GPIO117__FUNC_SPI0_SPU_MI (MTK_PIN_NO(117) | 1)
+#define PINMUX_GPIO117__FUNC_SPI4_A_MI (MTK_PIN_NO(117) | 2)
+#define PINMUX_GPIO117__FUNC_DSI1_TE (MTK_PIN_NO(117) | 3)
+#define PINMUX_GPIO117__FUNC_DBG_MON_B11 (MTK_PIN_NO(117) | 7)
+
+#define PINMUX_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define PINMUX_GPIO118__FUNC_SPI5_CLK (MTK_PIN_NO(118) | 1)
+#define PINMUX_GPIO118__FUNC_USB_DRVVBUS (MTK_PIN_NO(118) | 2)
+#define PINMUX_GPIO118__FUNC_DP_TX_HPD (MTK_PIN_NO(118) | 3)
+#define PINMUX_GPIO118__FUNC_AD_ILDO_DTEST0 (MTK_PIN_NO(118) | 4)
+
+#define PINMUX_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define PINMUX_GPIO119__FUNC_SPI5_CSB (MTK_PIN_NO(119) | 1)
+#define PINMUX_GPIO119__FUNC_VBUSVALID (MTK_PIN_NO(119) | 2)
+#define PINMUX_GPIO119__FUNC_DP_OC_EN (MTK_PIN_NO(119) | 3)
+#define PINMUX_GPIO119__FUNC_AD_ILDO_DTEST1 (MTK_PIN_NO(119) | 4)
+
+#define PINMUX_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define PINMUX_GPIO120__FUNC_SPI5_MO (MTK_PIN_NO(120) | 1)
+#define PINMUX_GPIO120__FUNC_LCM2_RST (MTK_PIN_NO(120) | 2)
+#define PINMUX_GPIO120__FUNC_DP_RAUX_SBU1 (MTK_PIN_NO(120) | 3)
+#define PINMUX_GPIO120__FUNC_AD_ILDO_DTEST2 (MTK_PIN_NO(120) | 4)
+#define PINMUX_GPIO120__FUNC_IDDIG_3P (MTK_PIN_NO(120) | 6)
+
+#define PINMUX_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define PINMUX_GPIO121__FUNC_SPI5_MI (MTK_PIN_NO(121) | 1)
+#define PINMUX_GPIO121__FUNC_DSI2_TE (MTK_PIN_NO(121) | 2)
+#define PINMUX_GPIO121__FUNC_DP_RAUX_SBU2 (MTK_PIN_NO(121) | 3)
+#define PINMUX_GPIO121__FUNC_AD_ILDO_DTEST3 (MTK_PIN_NO(121) | 4)
+#define PINMUX_GPIO121__FUNC_USB_DRVVBUS_3P (MTK_PIN_NO(121) | 6)
+#define PINMUX_GPIO121__FUNC_DBG_MON_B17 (MTK_PIN_NO(121) | 7)
+
+#define PINMUX_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define PINMUX_GPIO122__FUNC_AP_GOOD (MTK_PIN_NO(122) | 1)
+#define PINMUX_GPIO122__FUNC_CONN_TCXOENA_REQ (MTK_PIN_NO(122) | 2)
+
+#define PINMUX_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define PINMUX_GPIO123__FUNC_SCL3 (MTK_PIN_NO(123) | 1)
+#define PINMUX_GPIO123__FUNC_I2SIN2_LRCK (MTK_PIN_NO(123) | 5)
+#define PINMUX_GPIO123__FUNC_TP_UTXD_MD_VCORE (MTK_PIN_NO(123) | 6)
+
+#define PINMUX_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define PINMUX_GPIO124__FUNC_SDA3 (MTK_PIN_NO(124) | 1)
+#define PINMUX_GPIO124__FUNC_TP_URXD_MD_VCORE (MTK_PIN_NO(124) | 6)
+
+#define PINMUX_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define PINMUX_GPIO125__FUNC_MSDC1_CLK (MTK_PIN_NO(125) | 1)
+#define PINMUX_GPIO125__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(125) | 2)
+#define PINMUX_GPIO125__FUNC_HFRP_JTAG0_TCK (MTK_PIN_NO(125) | 3)
+#define PINMUX_GPIO125__FUNC_UDI_TCK (MTK_PIN_NO(125) | 4)
+#define PINMUX_GPIO125__FUNC_CONN_BGF_DSP_L1_JCK (MTK_PIN_NO(125) | 5)
+#define PINMUX_GPIO125__FUNC_SCP_JTAG_LITTLE_TCK_VLP (MTK_PIN_NO(125) | 6)
+#define PINMUX_GPIO125__FUNC_JTCK2_SEL1 (MTK_PIN_NO(125) | 7)
+
+#define PINMUX_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define PINMUX_GPIO126__FUNC_MSDC1_CMD (MTK_PIN_NO(126) | 1)
+#define PINMUX_GPIO126__FUNC_HFRP_JTAG0_TMS (MTK_PIN_NO(126) | 3)
+#define PINMUX_GPIO126__FUNC_UDI_TMS (MTK_PIN_NO(126) | 4)
+#define PINMUX_GPIO126__FUNC_CONN_BGF_DSP_L1_JMS (MTK_PIN_NO(126) | 5)
+#define PINMUX_GPIO126__FUNC_SCP_JTAG_LITTLE_TMS_VLP (MTK_PIN_NO(126) | 6)
+#define PINMUX_GPIO126__FUNC_JTMS2_SEL1 (MTK_PIN_NO(126) | 7)
+
+#define PINMUX_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define PINMUX_GPIO127__FUNC_MSDC1_DAT0 (MTK_PIN_NO(127) | 1)
+#define PINMUX_GPIO127__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(127) | 2)
+#define PINMUX_GPIO127__FUNC_HFRP_JTAG0_TDI (MTK_PIN_NO(127) | 3)
+#define PINMUX_GPIO127__FUNC_UDI_TDI_0 (MTK_PIN_NO(127) | 4)
+#define PINMUX_GPIO127__FUNC_CONN_BGF_DSP_L1_JDI (MTK_PIN_NO(127) | 5)
+#define PINMUX_GPIO127__FUNC_SCP_JTAG_LITTLE_TDI_VLP (MTK_PIN_NO(127) | 6)
+#define PINMUX_GPIO127__FUNC_JTDI2_SEL1 (MTK_PIN_NO(127) | 7)
+
+#define PINMUX_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define PINMUX_GPIO128__FUNC_MSDC1_DAT1 (MTK_PIN_NO(128) | 1)
+#define PINMUX_GPIO128__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(128) | 2)
+#define PINMUX_GPIO128__FUNC_HFRP_JTAG0_TDO (MTK_PIN_NO(128) | 3)
+#define PINMUX_GPIO128__FUNC_UDI_TDO_0 (MTK_PIN_NO(128) | 4)
+#define PINMUX_GPIO128__FUNC_CONN_BGF_DSP_L1_JDO (MTK_PIN_NO(128) | 5)
+#define PINMUX_GPIO128__FUNC_SCP_JTAG_LITTLE_TDO_VLP (MTK_PIN_NO(128) | 6)
+#define PINMUX_GPIO128__FUNC_JTDO2_SEL1 (MTK_PIN_NO(128) | 7)
+
+#define PINMUX_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define PINMUX_GPIO129__FUNC_MSDC1_DAT2 (MTK_PIN_NO(129) | 1)
+#define PINMUX_GPIO129__FUNC_DSI2_HSYNC (MTK_PIN_NO(129) | 2)
+#define PINMUX_GPIO129__FUNC_HFRP_JTAG0_TRSTN (MTK_PIN_NO(129) | 3)
+#define PINMUX_GPIO129__FUNC_UDI_NTRST (MTK_PIN_NO(129) | 4)
+#define PINMUX_GPIO129__FUNC_SCP_JTAG_LITTLE_TRSTN_VLP (MTK_PIN_NO(129) | 6)
+#define PINMUX_GPIO129__FUNC_JTRSTN2_SEL1 (MTK_PIN_NO(129) | 7)
+
+#define PINMUX_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define PINMUX_GPIO130__FUNC_MSDC1_DAT3 (MTK_PIN_NO(130) | 1)
+#define PINMUX_GPIO130__FUNC_DSI3_HSYNC (MTK_PIN_NO(130) | 2)
+#define PINMUX_GPIO130__FUNC_CONN_BGF_DSP_L1_JINTP (MTK_PIN_NO(130) | 5)
+
+#define PINMUX_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define PINMUX_GPIO131__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(131) | 1)
+#define PINMUX_GPIO131__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(131) | 2)
+#define PINMUX_GPIO131__FUNC_MCUPM_JTAG_TDI (MTK_PIN_NO(131) | 3)
+#define PINMUX_GPIO131__FUNC_CLKM0_A (MTK_PIN_NO(131) | 4)
+#define PINMUX_GPIO131__FUNC_CONN_BGF_DSP_L5_JDI (MTK_PIN_NO(131) | 5)
+#define PINMUX_GPIO131__FUNC_TSFDC_SCK (MTK_PIN_NO(131) | 6)
+#define PINMUX_GPIO131__FUNC_SCP_JTAG0_TDI_VCORE (MTK_PIN_NO(131) | 7)
+
+#define PINMUX_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define PINMUX_GPIO132__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(132) | 1)
+#define PINMUX_GPIO132__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(132) | 2)
+#define PINMUX_GPIO132__FUNC_MCUPM_JTAG_TMS (MTK_PIN_NO(132) | 3)
+#define PINMUX_GPIO132__FUNC_CLKM1_B (MTK_PIN_NO(132) | 4)
+#define PINMUX_GPIO132__FUNC_CONN_BGF_DSP_L5_JMS (MTK_PIN_NO(132) | 5)
+#define PINMUX_GPIO132__FUNC_TSFDC_SDI (MTK_PIN_NO(132) | 6)
+#define PINMUX_GPIO132__FUNC_SCP_JTAG0_TMS_VCORE (MTK_PIN_NO(132) | 7)
+
+#define PINMUX_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define PINMUX_GPIO133__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(133) | 1)
+#define PINMUX_GPIO133__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(133) | 2)
+#define PINMUX_GPIO133__FUNC_MCUPM_JTAG_TDO (MTK_PIN_NO(133) | 3)
+#define PINMUX_GPIO133__FUNC_CONN_BGF_DSP_L5_JDO (MTK_PIN_NO(133) | 5)
+#define PINMUX_GPIO133__FUNC_TSFDC_SCF (MTK_PIN_NO(133) | 6)
+#define PINMUX_GPIO133__FUNC_SCP_JTAG0_TDO_VCORE (MTK_PIN_NO(133) | 7)
+
+#define PINMUX_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define PINMUX_GPIO134__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(134) | 1)
+#define PINMUX_GPIO134__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(134) | 2)
+#define PINMUX_GPIO134__FUNC_TSFDC_26M (MTK_PIN_NO(134) | 6)
+
+#define PINMUX_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
+#define PINMUX_GPIO135__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(135) | 1)
+#define PINMUX_GPIO135__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(135) | 2)
+#define PINMUX_GPIO135__FUNC_MCUPM_JTAG_TCK (MTK_PIN_NO(135) | 3)
+#define PINMUX_GPIO135__FUNC_CONN_BGF_DSP_L5_JCK (MTK_PIN_NO(135) | 5)
+#define PINMUX_GPIO135__FUNC_TSFDC_SDO (MTK_PIN_NO(135) | 6)
+#define PINMUX_GPIO135__FUNC_SCP_JTAG0_TCK_VCORE (MTK_PIN_NO(135) | 7)
+
+#define PINMUX_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
+#define PINMUX_GPIO136__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(136) | 1)
+#define PINMUX_GPIO136__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(136) | 2)
+#define PINMUX_GPIO136__FUNC_MCUPM_JTAG_TRSTN (MTK_PIN_NO(136) | 3)
+#define PINMUX_GPIO136__FUNC_CONN_BGF_DSP_L5_JINTP (MTK_PIN_NO(136) | 5)
+#define PINMUX_GPIO136__FUNC_TSFDC_FOUT (MTK_PIN_NO(136) | 6)
+#define PINMUX_GPIO136__FUNC_SCP_JTAG0_TRSTN_VCORE (MTK_PIN_NO(136) | 7)
+
+#define PINMUX_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
+#define PINMUX_GPIO137__FUNC_MIPI0_D_SCLK (MTK_PIN_NO(137) | 1)
+#define PINMUX_GPIO137__FUNC_BPI_BUS16 (MTK_PIN_NO(137) | 2)
+#define PINMUX_GPIO137__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(137) | 4)
+#define PINMUX_GPIO137__FUNC_SPM_JTAG_TRSTN_VCORE (MTK_PIN_NO(137) | 6)
+#define PINMUX_GPIO137__FUNC_DBG_MON_A0 (MTK_PIN_NO(137) | 7)
+
+#define PINMUX_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
+#define PINMUX_GPIO138__FUNC_MIPI0_D_SDATA (MTK_PIN_NO(138) | 1)
+#define PINMUX_GPIO138__FUNC_BPI_BUS17 (MTK_PIN_NO(138) | 2)
+#define PINMUX_GPIO138__FUNC_PCM0_LRCK (MTK_PIN_NO(138) | 4)
+#define PINMUX_GPIO138__FUNC_SPM_JTAG_TCK_VCORE (MTK_PIN_NO(138) | 6)
+#define PINMUX_GPIO138__FUNC_DBG_MON_A1 (MTK_PIN_NO(138) | 7)
+
+#define PINMUX_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
+#define PINMUX_GPIO139__FUNC_MIPI1_D_SCLK (MTK_PIN_NO(139) | 1)
+#define PINMUX_GPIO139__FUNC_BPI_BUS18 (MTK_PIN_NO(139) | 2)
+#define PINMUX_GPIO139__FUNC_MD_GPS_BLANK (MTK_PIN_NO(139) | 4)
+#define PINMUX_GPIO139__FUNC_SPM_JTAG_TMS_VCORE (MTK_PIN_NO(139) | 6)
+#define PINMUX_GPIO139__FUNC_DBG_MON_A2 (MTK_PIN_NO(139) | 7)
+
+#define PINMUX_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
+#define PINMUX_GPIO140__FUNC_MIPI1_D_SDATA (MTK_PIN_NO(140) | 1)
+#define PINMUX_GPIO140__FUNC_BPI_BUS19 (MTK_PIN_NO(140) | 2)
+#define PINMUX_GPIO140__FUNC_MD_URXD1_CONN (MTK_PIN_NO(140) | 4)
+#define PINMUX_GPIO140__FUNC_SPM_JTAG_TDO_VCORE (MTK_PIN_NO(140) | 6)
+#define PINMUX_GPIO140__FUNC_DBG_MON_A3 (MTK_PIN_NO(140) | 7)
+
+#define PINMUX_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
+#define PINMUX_GPIO141__FUNC_MIPI2_D_SCLK (MTK_PIN_NO(141) | 1)
+#define PINMUX_GPIO141__FUNC_BPI_BUS20 (MTK_PIN_NO(141) | 2)
+#define PINMUX_GPIO141__FUNC_MD_UTXD1_CONN (MTK_PIN_NO(141) | 4)
+#define PINMUX_GPIO141__FUNC_SPM_JTAG_TDI_VCORE (MTK_PIN_NO(141) | 6)
+#define PINMUX_GPIO141__FUNC_DBG_MON_A4 (MTK_PIN_NO(141) | 7)
+
+#define PINMUX_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
+#define PINMUX_GPIO142__FUNC_MIPI2_D_SDATA (MTK_PIN_NO(142) | 1)
+#define PINMUX_GPIO142__FUNC_BPI_BUS21 (MTK_PIN_NO(142) | 2)
+#define PINMUX_GPIO142__FUNC_SSPM_JTAG_TRSTN_VCORE (MTK_PIN_NO(142) | 6)
+#define PINMUX_GPIO142__FUNC_DBG_MON_A5 (MTK_PIN_NO(142) | 7)
+
+#define PINMUX_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0)
+#define PINMUX_GPIO143__FUNC_MIPI3_D_SCLK (MTK_PIN_NO(143) | 1)
+#define PINMUX_GPIO143__FUNC_BPI_BUS22 (MTK_PIN_NO(143) | 2)
+#define PINMUX_GPIO143__FUNC_TP_UTXD_GNSS_VLP (MTK_PIN_NO(143) | 4)
+#define PINMUX_GPIO143__FUNC_MD_UTXD1_CONN (MTK_PIN_NO(143) | 5)
+#define PINMUX_GPIO143__FUNC_SSPM_JTAG_TCK_VCORE (MTK_PIN_NO(143) | 6)
+
+#define PINMUX_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0)
+#define PINMUX_GPIO144__FUNC_MIPI3_D_SDATA (MTK_PIN_NO(144) | 1)
+#define PINMUX_GPIO144__FUNC_BPI_BUS23 (MTK_PIN_NO(144) | 2)
+#define PINMUX_GPIO144__FUNC_TP_URXD_GNSS_VLP (MTK_PIN_NO(144) | 4)
+#define PINMUX_GPIO144__FUNC_MD_URXD1_CONN (MTK_PIN_NO(144) | 5)
+#define PINMUX_GPIO144__FUNC_SSPM_JTAG_TMS_VCORE (MTK_PIN_NO(144) | 6)
+
+#define PINMUX_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0)
+#define PINMUX_GPIO145__FUNC_BPI_BUS0 (MTK_PIN_NO(145) | 1)
+#define PINMUX_GPIO145__FUNC_PCIE_WAKEN_1P (MTK_PIN_NO(145) | 4)
+#define PINMUX_GPIO145__FUNC_SSPM_JTAG_TDO_VCORE (MTK_PIN_NO(145) | 6)
+#define PINMUX_GPIO145__FUNC_DBG_MON_A10 (MTK_PIN_NO(145) | 7)
+
+#define PINMUX_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0)
+#define PINMUX_GPIO146__FUNC_BPI_BUS1 (MTK_PIN_NO(146) | 1)
+#define PINMUX_GPIO146__FUNC_PCIE_PERSTN_1P (MTK_PIN_NO(146) | 4)
+#define PINMUX_GPIO146__FUNC_SSPM_JTAG_TDI_VCORE (MTK_PIN_NO(146) | 6)
+#define PINMUX_GPIO146__FUNC_DBG_MON_A11 (MTK_PIN_NO(146) | 7)
+
+#define PINMUX_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0)
+#define PINMUX_GPIO147__FUNC_BPI_BUS2 (MTK_PIN_NO(147) | 1)
+#define PINMUX_GPIO147__FUNC_AUD_DAC_26M_CLK (MTK_PIN_NO(147) | 2)
+#define PINMUX_GPIO147__FUNC_PCIE_CLKREQN_1P (MTK_PIN_NO(147) | 4)
+#define PINMUX_GPIO147__FUNC_SCP_JTAG_LITTLE_TRSTN_VCORE (MTK_PIN_NO(147) | 6)
+#define PINMUX_GPIO147__FUNC_DBG_MON_A12 (MTK_PIN_NO(147) | 7)
+
+#define PINMUX_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0)
+#define PINMUX_GPIO148__FUNC_BPI_BUS3 (MTK_PIN_NO(148) | 1)
+#define PINMUX_GPIO148__FUNC_AUD_DAC_26M_CLK (MTK_PIN_NO(148) | 2)
+#define PINMUX_GPIO148__FUNC_TP_UTXD_MD_VLP (MTK_PIN_NO(148) | 4)
+#define PINMUX_GPIO148__FUNC_TP_GPIO0_AO (MTK_PIN_NO(148) | 5)
+#define PINMUX_GPIO148__FUNC_SCP_JTAG_LITTLE_TCK_VCORE (MTK_PIN_NO(148) | 6)
+#define PINMUX_GPIO148__FUNC_DBG_MON_A13 (MTK_PIN_NO(148) | 7)
+
+#define PINMUX_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0)
+#define PINMUX_GPIO149__FUNC_BPI_BUS4 (MTK_PIN_NO(149) | 1)
+#define PINMUX_GPIO149__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(149) | 2)
+#define PINMUX_GPIO149__FUNC_TP_URXD_MD_VLP (MTK_PIN_NO(149) | 4)
+#define PINMUX_GPIO149__FUNC_TP_GPIO1_AO (MTK_PIN_NO(149) | 5)
+#define PINMUX_GPIO149__FUNC_SCP_JTAG_LITTLE_TMS_VCORE (MTK_PIN_NO(149) | 6)
+#define PINMUX_GPIO149__FUNC_DBG_MON_A14 (MTK_PIN_NO(149) | 7)
+
+#define PINMUX_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0)
+#define PINMUX_GPIO150__FUNC_BPI_BUS5 (MTK_PIN_NO(150) | 1)
+#define PINMUX_GPIO150__FUNC_GPS_PPS0 (MTK_PIN_NO(150) | 2)
+#define PINMUX_GPIO150__FUNC_TP_GPIO2_AO (MTK_PIN_NO(150) | 5)
+#define PINMUX_GPIO150__FUNC_SCP_JTAG_LITTLE_TDO_VCORE (MTK_PIN_NO(150) | 6)
+#define PINMUX_GPIO150__FUNC_DBG_MON_A15 (MTK_PIN_NO(150) | 7)
+
+#define PINMUX_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0)
+#define PINMUX_GPIO151__FUNC_BPI_BUS6 (MTK_PIN_NO(151) | 1)
+#define PINMUX_GPIO151__FUNC_GPS_PPS1 (MTK_PIN_NO(151) | 2)
+#define PINMUX_GPIO151__FUNC_TP_GPIO3_AO (MTK_PIN_NO(151) | 5)
+#define PINMUX_GPIO151__FUNC_SCP_JTAG_LITTLE_TDI_VCORE (MTK_PIN_NO(151) | 6)
+
+#define PINMUX_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0)
+#define PINMUX_GPIO152__FUNC_BPI_BUS7 (MTK_PIN_NO(152) | 1)
+#define PINMUX_GPIO152__FUNC_EDP_TX_HPD (MTK_PIN_NO(152) | 2)
+#define PINMUX_GPIO152__FUNC_AGPS_SYNC (MTK_PIN_NO(152) | 5)
+#define PINMUX_GPIO152__FUNC_SSPM_UTXD_AO_VCORE (MTK_PIN_NO(152) | 6)
+
+#define PINMUX_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0)
+#define PINMUX_GPIO153__FUNC_MD_UCNT_A_TGL (MTK_PIN_NO(153) | 1)
+#define PINMUX_GPIO153__FUNC_TP_URTS1_VCORE (MTK_PIN_NO(153) | 6)
+#define PINMUX_GPIO153__FUNC_DBG_MON_A8 (MTK_PIN_NO(153) | 7)
+
+#define PINMUX_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0)
+#define PINMUX_GPIO154__FUNC_DIGRF_IRQ (MTK_PIN_NO(154) | 1)
+#define PINMUX_GPIO154__FUNC_TP_UCTS1_VCORE (MTK_PIN_NO(154) | 6)
+#define PINMUX_GPIO154__FUNC_DBG_MON_A9 (MTK_PIN_NO(154) | 7)
+
+#define PINMUX_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0)
+#define PINMUX_GPIO155__FUNC_MIPI_M_SCLK (MTK_PIN_NO(155) | 1)
+#define PINMUX_GPIO155__FUNC_UCTS2 (MTK_PIN_NO(155) | 4)
+#define PINMUX_GPIO155__FUNC_TP_UTXD_CONSYS_VCORE (MTK_PIN_NO(155) | 6)
+#define PINMUX_GPIO155__FUNC_DBG_MON_A6 (MTK_PIN_NO(155) | 7)
+
+#define PINMUX_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0)
+#define PINMUX_GPIO156__FUNC_MIPI_M_SDATA (MTK_PIN_NO(156) | 1)
+#define PINMUX_GPIO156__FUNC_URTS2 (MTK_PIN_NO(156) | 4)
+#define PINMUX_GPIO156__FUNC_TP_URXD_CONSYS_VCORE (MTK_PIN_NO(156) | 6)
+#define PINMUX_GPIO156__FUNC_DBG_MON_A7 (MTK_PIN_NO(156) | 7)
+
+#define PINMUX_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0)
+#define PINMUX_GPIO157__FUNC_BPI_BUS8 (MTK_PIN_NO(157) | 1)
+#define PINMUX_GPIO157__FUNC_UTXD2 (MTK_PIN_NO(157) | 4)
+#define PINMUX_GPIO157__FUNC_CLKM0_A (MTK_PIN_NO(157) | 5)
+#define PINMUX_GPIO157__FUNC_SSPM_URXD_AO_VCORE (MTK_PIN_NO(157) | 6)
+#define PINMUX_GPIO157__FUNC_DBG_MON_A16 (MTK_PIN_NO(157) | 7)
+
+#define PINMUX_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0)
+#define PINMUX_GPIO158__FUNC_BPI_BUS9 (MTK_PIN_NO(158) | 1)
+#define PINMUX_GPIO158__FUNC_URXD2 (MTK_PIN_NO(158) | 4)
+#define PINMUX_GPIO158__FUNC_CLKM1_A (MTK_PIN_NO(158) | 5)
+#define PINMUX_GPIO158__FUNC_TP_UTXD1_VCORE (MTK_PIN_NO(158) | 6)
+
+#define PINMUX_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0)
+#define PINMUX_GPIO159__FUNC_BPI_BUS10 (MTK_PIN_NO(159) | 1)
+#define PINMUX_GPIO159__FUNC_MD_INT0 (MTK_PIN_NO(159) | 2)
+#define PINMUX_GPIO159__FUNC_SRCLKENAI1 (MTK_PIN_NO(159) | 3)
+#define PINMUX_GPIO159__FUNC_CLKM2_A (MTK_PIN_NO(159) | 5)
+#define PINMUX_GPIO159__FUNC_TP_URXD1_VCORE (MTK_PIN_NO(159) | 6)
+
+#define PINMUX_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0)
+#define PINMUX_GPIO160__FUNC_UTXD0 (MTK_PIN_NO(160) | 1)
+#define PINMUX_GPIO160__FUNC_MD_UTXD1 (MTK_PIN_NO(160) | 2)
+#define PINMUX_GPIO160__FUNC_MBISTREADEN_TRIGGER (MTK_PIN_NO(160) | 5)
+#define PINMUX_GPIO160__FUNC_CONN_BG_GPS_MCU_DBG_UART_TXD (MTK_PIN_NO(160) | 6)
+
+#define PINMUX_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0)
+#define PINMUX_GPIO161__FUNC_URXD0 (MTK_PIN_NO(161) | 1)
+#define PINMUX_GPIO161__FUNC_MD_URXD1 (MTK_PIN_NO(161) | 2)
+#define PINMUX_GPIO161__FUNC_MBISTWRITEEN_TRIGGER (MTK_PIN_NO(161) | 5)
+
+#define PINMUX_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0)
+#define PINMUX_GPIO162__FUNC_UTXD1 (MTK_PIN_NO(162) | 1)
+#define PINMUX_GPIO162__FUNC_MD_UTXD0 (MTK_PIN_NO(162) | 2)
+#define PINMUX_GPIO162__FUNC_TP_UTXD1_VLP (MTK_PIN_NO(162) | 3)
+#define PINMUX_GPIO162__FUNC_ADSP_UTXD0 (MTK_PIN_NO(162) | 4)
+#define PINMUX_GPIO162__FUNC_SSPM_UTXD_AO_VLP (MTK_PIN_NO(162) | 5)
+#define PINMUX_GPIO162__FUNC_HFRP_UTXD1 (MTK_PIN_NO(162) | 6)
+
+#define PINMUX_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0)
+#define PINMUX_GPIO163__FUNC_URXD1 (MTK_PIN_NO(163) | 1)
+#define PINMUX_GPIO163__FUNC_MD_URXD0 (MTK_PIN_NO(163) | 2)
+#define PINMUX_GPIO163__FUNC_TP_URXD1_VLP (MTK_PIN_NO(163) | 3)
+#define PINMUX_GPIO163__FUNC_ADSP_URXD0 (MTK_PIN_NO(163) | 4)
+#define PINMUX_GPIO163__FUNC_SSPM_URXD_AO_VLP (MTK_PIN_NO(163) | 5)
+#define PINMUX_GPIO163__FUNC_HFRP_URXD1 (MTK_PIN_NO(163) | 6)
+
+#define PINMUX_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0)
+#define PINMUX_GPIO164__FUNC_SCP_SCL0 (MTK_PIN_NO(164) | 1)
+#define PINMUX_GPIO164__FUNC_TP_GPIO0_AO (MTK_PIN_NO(164) | 6)
+#define PINMUX_GPIO164__FUNC_DBG_MON_A22 (MTK_PIN_NO(164) | 7)
+
+#define PINMUX_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0)
+#define PINMUX_GPIO165__FUNC_SCP_SDA0 (MTK_PIN_NO(165) | 1)
+#define PINMUX_GPIO165__FUNC_TP_GPIO1_AO (MTK_PIN_NO(165) | 6)
+#define PINMUX_GPIO165__FUNC_DBG_MON_A23 (MTK_PIN_NO(165) | 7)
+
+#define PINMUX_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0)
+#define PINMUX_GPIO166__FUNC_SCP_SCL2 (MTK_PIN_NO(166) | 1)
+#define PINMUX_GPIO166__FUNC_TP_GPIO2_AO (MTK_PIN_NO(166) | 6)
+#define PINMUX_GPIO166__FUNC_DBG_MON_A24 (MTK_PIN_NO(166) | 7)
+
+#define PINMUX_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0)
+#define PINMUX_GPIO167__FUNC_SCP_SDA2 (MTK_PIN_NO(167) | 1)
+#define PINMUX_GPIO167__FUNC_TP_GPIO3_AO (MTK_PIN_NO(167) | 6)
+#define PINMUX_GPIO167__FUNC_DBG_MON_A25 (MTK_PIN_NO(167) | 7)
+
+#define PINMUX_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0)
+#define PINMUX_GPIO168__FUNC_SCP_SPI2_CK (MTK_PIN_NO(168) | 1)
+#define PINMUX_GPIO168__FUNC_SPI2_B_CLK (MTK_PIN_NO(168) | 2)
+#define PINMUX_GPIO168__FUNC_PWM_VLP (MTK_PIN_NO(168) | 3)
+#define PINMUX_GPIO168__FUNC_SCP_SCL2 (MTK_PIN_NO(168) | 4)
+#define PINMUX_GPIO168__FUNC_DBG_MON_A26 (MTK_PIN_NO(168) | 7)
+
+#define PINMUX_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0)
+#define PINMUX_GPIO169__FUNC_SCP_SPI2_CS (MTK_PIN_NO(169) | 1)
+#define PINMUX_GPIO169__FUNC_SPI2_B_CSB (MTK_PIN_NO(169) | 2)
+#define PINMUX_GPIO169__FUNC_DBG_MON_A27 (MTK_PIN_NO(169) | 7)
+
+#define PINMUX_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0)
+#define PINMUX_GPIO170__FUNC_SCP_SPI2_MO (MTK_PIN_NO(170) | 1)
+#define PINMUX_GPIO170__FUNC_SPI2_B_MO (MTK_PIN_NO(170) | 2)
+#define PINMUX_GPIO170__FUNC_SCP_SDA2 (MTK_PIN_NO(170) | 4)
+#define PINMUX_GPIO170__FUNC_DBG_MON_A28 (MTK_PIN_NO(170) | 7)
+
+#define PINMUX_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0)
+#define PINMUX_GPIO171__FUNC_SCP_SPI2_MI (MTK_PIN_NO(171) | 1)
+#define PINMUX_GPIO171__FUNC_SPI2_B_MI (MTK_PIN_NO(171) | 2)
+#define PINMUX_GPIO171__FUNC_DBG_MON_A29 (MTK_PIN_NO(171) | 7)
+
+#define PINMUX_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0)
+#define PINMUX_GPIO172__FUNC_CONN_TCXOENA_REQ (MTK_PIN_NO(172) | 1)
+
+#define PINMUX_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0)
+#define PINMUX_GPIO173__FUNC_CMFLASH3 (MTK_PIN_NO(173) | 1)
+#define PINMUX_GPIO173__FUNC_PWM_3 (MTK_PIN_NO(173) | 2)
+#define PINMUX_GPIO173__FUNC_MD_GPS_L5_BLANK (MTK_PIN_NO(173) | 3)
+#define PINMUX_GPIO173__FUNC_CLKM1_A (MTK_PIN_NO(173) | 4)
+#define PINMUX_GPIO173__FUNC_DBG_MON_A31 (MTK_PIN_NO(173) | 7)
+
+#define PINMUX_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0)
+#define PINMUX_GPIO174__FUNC_CMFLASH0 (MTK_PIN_NO(174) | 1)
+#define PINMUX_GPIO174__FUNC_PWM_0 (MTK_PIN_NO(174) | 2)
+#define PINMUX_GPIO174__FUNC_VBUSVALID_1P (MTK_PIN_NO(174) | 3)
+#define PINMUX_GPIO174__FUNC_MD32_2_RXD (MTK_PIN_NO(174) | 4)
+#define PINMUX_GPIO174__FUNC_DISP_PWM3 (MTK_PIN_NO(174) | 5)
+
+#define PINMUX_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0)
+#define PINMUX_GPIO175__FUNC_CMFLASH1 (MTK_PIN_NO(175) | 1)
+#define PINMUX_GPIO175__FUNC_PWM_1 (MTK_PIN_NO(175) | 2)
+#define PINMUX_GPIO175__FUNC_EDP_TX_HPD (MTK_PIN_NO(175) | 3)
+#define PINMUX_GPIO175__FUNC_MD32_2_TXD (MTK_PIN_NO(175) | 4)
+#define PINMUX_GPIO175__FUNC_DISP_PWM4 (MTK_PIN_NO(175) | 5)
+
+#define PINMUX_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0)
+#define PINMUX_GPIO176__FUNC_SCL5 (MTK_PIN_NO(176) | 1)
+#define PINMUX_GPIO176__FUNC_LCM3_RST (MTK_PIN_NO(176) | 2)
+#define PINMUX_GPIO176__FUNC_MD_URXD1_CONN (MTK_PIN_NO(176) | 4)
+#define PINMUX_GPIO176__FUNC_TP_UTXD_GNSS_VCORE (MTK_PIN_NO(176) | 6)
+
+#define PINMUX_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0)
+#define PINMUX_GPIO177__FUNC_SDA5 (MTK_PIN_NO(177) | 1)
+#define PINMUX_GPIO177__FUNC_DSI3_TE (MTK_PIN_NO(177) | 2)
+#define PINMUX_GPIO177__FUNC_MD_UTXD1_CONN (MTK_PIN_NO(177) | 4)
+#define PINMUX_GPIO177__FUNC_TP_URXD_GNSS_VCORE (MTK_PIN_NO(177) | 6)
+
+#define PINMUX_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0)
+#define PINMUX_GPIO178__FUNC_DMIC_CLK (MTK_PIN_NO(178) | 1)
+#define PINMUX_GPIO178__FUNC_SCP_DMIC_CLK (MTK_PIN_NO(178) | 2)
+#define PINMUX_GPIO178__FUNC_SRCLKENAI0 (MTK_PIN_NO(178) | 3)
+#define PINMUX_GPIO178__FUNC_CLKM2_B (MTK_PIN_NO(178) | 4)
+#define PINMUX_GPIO178__FUNC_TP_GPIO7_AO (MTK_PIN_NO(178) | 5)
+#define PINMUX_GPIO178__FUNC_SPU1_UTX (MTK_PIN_NO(178) | 6)
+#define PINMUX_GPIO178__FUNC_DAP_SONIC_SWCK (MTK_PIN_NO(178) | 7)
+
+#define PINMUX_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0)
+#define PINMUX_GPIO179__FUNC_DMIC_DAT (MTK_PIN_NO(179) | 1)
+#define PINMUX_GPIO179__FUNC_SCP_DMIC_DAT (MTK_PIN_NO(179) | 2)
+#define PINMUX_GPIO179__FUNC_SRCLKENAI1 (MTK_PIN_NO(179) | 3)
+#define PINMUX_GPIO179__FUNC_CLKM3_B (MTK_PIN_NO(179) | 4)
+#define PINMUX_GPIO179__FUNC_TP_GPIO8_AO (MTK_PIN_NO(179) | 5)
+#define PINMUX_GPIO179__FUNC_SPU1_URX (MTK_PIN_NO(179) | 6)
+#define PINMUX_GPIO179__FUNC_DAP_SONIC_SWD (MTK_PIN_NO(179) | 7)
+
+#define PINMUX_GPIO180__FUNC_GPIO180 (MTK_PIN_NO(180) | 0)
+#define PINMUX_GPIO180__FUNC_IDDIG_1P (MTK_PIN_NO(180) | 1)
+#define PINMUX_GPIO180__FUNC_CMVREF0 (MTK_PIN_NO(180) | 2)
+#define PINMUX_GPIO180__FUNC_GPS_PPS1 (MTK_PIN_NO(180) | 3)
+#define PINMUX_GPIO180__FUNC_GPS_L5_ELNA_EN (MTK_PIN_NO(180) | 4)
+#define PINMUX_GPIO180__FUNC_DISP_PWM1 (MTK_PIN_NO(180) | 5)
+
+#define PINMUX_GPIO181__FUNC_GPIO181 (MTK_PIN_NO(181) | 0)
+#define PINMUX_GPIO181__FUNC_USB_DRVVBUS_1P (MTK_PIN_NO(181) | 1)
+#define PINMUX_GPIO181__FUNC_CMVREF1 (MTK_PIN_NO(181) | 2)
+#define PINMUX_GPIO181__FUNC_MFG_EB_JTAG_TRSTN (MTK_PIN_NO(181) | 3)
+#define PINMUX_GPIO181__FUNC_ADSP_JTAG1_TRSTN (MTK_PIN_NO(181) | 4)
+#define PINMUX_GPIO181__FUNC_HFRP_JTAG1_TRSTN (MTK_PIN_NO(181) | 5)
+#define PINMUX_GPIO181__FUNC_SPU1_NTRST (MTK_PIN_NO(181) | 6)
+#define PINMUX_GPIO181__FUNC_CONN_BG_GPS_MCU_TRST_B (MTK_PIN_NO(181) | 7)
+
+#define PINMUX_GPIO182__FUNC_GPIO182 (MTK_PIN_NO(182) | 0)
+#define PINMUX_GPIO182__FUNC_SCL11 (MTK_PIN_NO(182) | 1)
+#define PINMUX_GPIO182__FUNC_CMVREF2 (MTK_PIN_NO(182) | 2)
+#define PINMUX_GPIO182__FUNC_MFG_EB_JTAG_TCK (MTK_PIN_NO(182) | 3)
+#define PINMUX_GPIO182__FUNC_ADSP_JTAG1_TCK (MTK_PIN_NO(182) | 4)
+#define PINMUX_GPIO182__FUNC_HFRP_JTAG1_TCK (MTK_PIN_NO(182) | 5)
+#define PINMUX_GPIO182__FUNC_SPU1_TCK (MTK_PIN_NO(182) | 6)
+#define PINMUX_GPIO182__FUNC_CONN_BG_GPS_MCU_TCK (MTK_PIN_NO(182) | 7)
+
+#define PINMUX_GPIO183__FUNC_GPIO183 (MTK_PIN_NO(183) | 0)
+#define PINMUX_GPIO183__FUNC_SDA11 (MTK_PIN_NO(183) | 1)
+#define PINMUX_GPIO183__FUNC_CMVREF3 (MTK_PIN_NO(183) | 2)
+#define PINMUX_GPIO183__FUNC_MFG_EB_JTAG_TMS (MTK_PIN_NO(183) | 3)
+#define PINMUX_GPIO183__FUNC_ADSP_JTAG1_TMS (MTK_PIN_NO(183) | 4)
+#define PINMUX_GPIO183__FUNC_HFRP_JTAG1_TMS (MTK_PIN_NO(183) | 5)
+#define PINMUX_GPIO183__FUNC_SPU1_TMS (MTK_PIN_NO(183) | 6)
+#define PINMUX_GPIO183__FUNC_CONN_BG_GPS_MCU_TMS (MTK_PIN_NO(183) | 7)
+
+#define PINMUX_GPIO184__FUNC_GPIO184 (MTK_PIN_NO(184) | 0)
+#define PINMUX_GPIO184__FUNC_SCL12 (MTK_PIN_NO(184) | 1)
+#define PINMUX_GPIO184__FUNC_CMVREF4 (MTK_PIN_NO(184) | 2)
+#define PINMUX_GPIO184__FUNC_MFG_EB_JTAG_TDO (MTK_PIN_NO(184) | 3)
+#define PINMUX_GPIO184__FUNC_ADSP_JTAG1_TDO (MTK_PIN_NO(184) | 4)
+#define PINMUX_GPIO184__FUNC_HFRP_JTAG1_TDO (MTK_PIN_NO(184) | 5)
+#define PINMUX_GPIO184__FUNC_SPU1_TDO (MTK_PIN_NO(184) | 6)
+#define PINMUX_GPIO184__FUNC_CONN_BG_GPS_MCU_TDO (MTK_PIN_NO(184) | 7)
+
+#define PINMUX_GPIO185__FUNC_GPIO185 (MTK_PIN_NO(185) | 0)
+#define PINMUX_GPIO185__FUNC_SDA12 (MTK_PIN_NO(185) | 1)
+#define PINMUX_GPIO185__FUNC_CMVREF5 (MTK_PIN_NO(185) | 2)
+#define PINMUX_GPIO185__FUNC_MFG_EB_JTAG_TDI (MTK_PIN_NO(185) | 3)
+#define PINMUX_GPIO185__FUNC_ADSP_JTAG1_TDI (MTK_PIN_NO(185) | 4)
+#define PINMUX_GPIO185__FUNC_HFRP_JTAG1_TDI (MTK_PIN_NO(185) | 5)
+#define PINMUX_GPIO185__FUNC_SPU1_TDI (MTK_PIN_NO(185) | 6)
+#define PINMUX_GPIO185__FUNC_CONN_BG_GPS_MCU_TDI (MTK_PIN_NO(185) | 7)
+
+#define PINMUX_GPIO186__FUNC_GPIO186 (MTK_PIN_NO(186) | 0)
+#define PINMUX_GPIO186__FUNC_MD_GPS_L1_BLANK (MTK_PIN_NO(186) | 1)
+#define PINMUX_GPIO186__FUNC_PMSR_SMAP (MTK_PIN_NO(186) | 2)
+#define PINMUX_GPIO186__FUNC_TP_GPIO2_AO (MTK_PIN_NO(186) | 3)
+
+#define PINMUX_GPIO187__FUNC_GPIO187 (MTK_PIN_NO(187) | 0)
+#define PINMUX_GPIO187__FUNC_MD_GPS_L5_BLANK (MTK_PIN_NO(187) | 1)
+#define PINMUX_GPIO187__FUNC_TP_GPIO4_AO (MTK_PIN_NO(187) | 3)
+
+#define PINMUX_GPIO188__FUNC_GPIO188 (MTK_PIN_NO(188) | 0)
+#define PINMUX_GPIO188__FUNC_SCL2 (MTK_PIN_NO(188) | 1)
+#define PINMUX_GPIO188__FUNC_SCP_SCL8 (MTK_PIN_NO(188) | 2)
+
+#define PINMUX_GPIO189__FUNC_GPIO189 (MTK_PIN_NO(189) | 0)
+#define PINMUX_GPIO189__FUNC_SDA2 (MTK_PIN_NO(189) | 1)
+#define PINMUX_GPIO189__FUNC_SCP_SDA8 (MTK_PIN_NO(189) | 2)
+
+#define PINMUX_GPIO190__FUNC_GPIO190 (MTK_PIN_NO(190) | 0)
+#define PINMUX_GPIO190__FUNC_SCL4 (MTK_PIN_NO(190) | 1)
+#define PINMUX_GPIO190__FUNC_SCP_SCL9 (MTK_PIN_NO(190) | 2)
+#define PINMUX_GPIO190__FUNC_UDI_TDI_6 (MTK_PIN_NO(190) | 6)
+
+#define PINMUX_GPIO191__FUNC_GPIO191 (MTK_PIN_NO(191) | 0)
+#define PINMUX_GPIO191__FUNC_SDA4 (MTK_PIN_NO(191) | 1)
+#define PINMUX_GPIO191__FUNC_SCP_SDA9 (MTK_PIN_NO(191) | 2)
+#define PINMUX_GPIO191__FUNC_UDI_TDI_7 (MTK_PIN_NO(191) | 6)
+
+#define PINMUX_GPIO192__FUNC_GPIO192 (MTK_PIN_NO(192) | 0)
+#define PINMUX_GPIO192__FUNC_CMMCLK2 (MTK_PIN_NO(192) | 1)
+#define PINMUX_GPIO192__FUNC_MD32_3_RXD (MTK_PIN_NO(192) | 4)
+
+#define PINMUX_GPIO193__FUNC_GPIO193 (MTK_PIN_NO(193) | 0)
+#define PINMUX_GPIO193__FUNC_CLKM0_B (MTK_PIN_NO(193) | 3)
+#define PINMUX_GPIO193__FUNC_MD32_3_TXD (MTK_PIN_NO(193) | 4)
+#define PINMUX_GPIO193__FUNC_UDI_TDO_7 (MTK_PIN_NO(193) | 6)
+
+#define PINMUX_GPIO194__FUNC_GPIO194 (MTK_PIN_NO(194) | 0)
+#define PINMUX_GPIO194__FUNC_SCL7 (MTK_PIN_NO(194) | 1)
+#define PINMUX_GPIO194__FUNC_MD32_3_GPIO0 (MTK_PIN_NO(194) | 2)
+#define PINMUX_GPIO194__FUNC_CLKM2_B (MTK_PIN_NO(194) | 3)
+#define PINMUX_GPIO194__FUNC_UDI_TDI_2 (MTK_PIN_NO(194) | 6)
+
+#define PINMUX_GPIO195__FUNC_GPIO195 (MTK_PIN_NO(195) | 0)
+#define PINMUX_GPIO195__FUNC_SDA7 (MTK_PIN_NO(195) | 1)
+#define PINMUX_GPIO195__FUNC_CLKM3_B (MTK_PIN_NO(195) | 3)
+#define PINMUX_GPIO195__FUNC_UDI_TDI_3 (MTK_PIN_NO(195) | 6)
+
+#define PINMUX_GPIO196__FUNC_GPIO196 (MTK_PIN_NO(196) | 0)
+#define PINMUX_GPIO196__FUNC_CMMCLK3 (MTK_PIN_NO(196) | 1)
+
+#define PINMUX_GPIO197__FUNC_GPIO197 (MTK_PIN_NO(197) | 0)
+#define PINMUX_GPIO197__FUNC_CLKM1_B (MTK_PIN_NO(197) | 3)
+#define PINMUX_GPIO197__FUNC_UDI_TDI_1 (MTK_PIN_NO(197) | 6)
+
+#define PINMUX_GPIO198__FUNC_GPIO198 (MTK_PIN_NO(198) | 0)
+#define PINMUX_GPIO198__FUNC_SCL8 (MTK_PIN_NO(198) | 1)
+#define PINMUX_GPIO198__FUNC_UDI_TDI_4 (MTK_PIN_NO(198) | 6)
+
+#define PINMUX_GPIO199__FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define PINMUX_GPIO199__FUNC_SDA8 (MTK_PIN_NO(199) | 1)
+#define PINMUX_GPIO199__FUNC_UDI_TDI_5 (MTK_PIN_NO(199) | 6)
+
+#define PINMUX_GPIO200__FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define PINMUX_GPIO200__FUNC_SCL1 (MTK_PIN_NO(200) | 1)
+
+#define PINMUX_GPIO201__FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define PINMUX_GPIO201__FUNC_SDA1 (MTK_PIN_NO(201) | 1)
+#define PINMUX_GPIO201__FUNC_TSFDC_BG_COMP (MTK_PIN_NO(201) | 7)
+
+#define PINMUX_GPIO202__FUNC_GPIO202 (MTK_PIN_NO(202) | 0)
+#define PINMUX_GPIO202__FUNC_SCL9 (MTK_PIN_NO(202) | 1)
+#define PINMUX_GPIO202__FUNC_SCP_SCL7 (MTK_PIN_NO(202) | 2)
+#define PINMUX_GPIO202__FUNC_TP_GPIO15_AO (MTK_PIN_NO(202) | 6)
+
+#define PINMUX_GPIO203__FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
+#define PINMUX_GPIO203__FUNC_SDA9 (MTK_PIN_NO(203) | 1)
+#define PINMUX_GPIO203__FUNC_SCP_SDA7 (MTK_PIN_NO(203) | 2)
+#define PINMUX_GPIO203__FUNC_TP_GPIO9_AO (MTK_PIN_NO(203) | 6)
+
+#define PINMUX_GPIO204__FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
+#define PINMUX_GPIO204__FUNC_SCL13 (MTK_PIN_NO(204) | 1)
+#define PINMUX_GPIO204__FUNC_CMVREF6 (MTK_PIN_NO(204) | 2)
+#define PINMUX_GPIO204__FUNC_GPS_L1_ELNA_EN (MTK_PIN_NO(204) | 3)
+#define PINMUX_GPIO204__FUNC_CLKM2_B (MTK_PIN_NO(204) | 5)
+#define PINMUX_GPIO204__FUNC_TP_GPIO12_AO (MTK_PIN_NO(204) | 6)
+
+#define PINMUX_GPIO205__FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
+#define PINMUX_GPIO205__FUNC_SDA13 (MTK_PIN_NO(205) | 1)
+#define PINMUX_GPIO205__FUNC_CMVREF7 (MTK_PIN_NO(205) | 2)
+#define PINMUX_GPIO205__FUNC_GPS_L5_ELNA_EN (MTK_PIN_NO(205) | 3)
+#define PINMUX_GPIO205__FUNC_CLKM3_B (MTK_PIN_NO(205) | 5)
+#define PINMUX_GPIO205__FUNC_TP_GPIO13_AO (MTK_PIN_NO(205) | 6)
+
+#define PINMUX_GPIO206__FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
+#define PINMUX_GPIO206__FUNC_MD32_2_GPIO0 (MTK_PIN_NO(206) | 2)
+#define PINMUX_GPIO206__FUNC_VBUSVALID (MTK_PIN_NO(206) | 5)
+#define PINMUX_GPIO206__FUNC_UDI_TDO_3 (MTK_PIN_NO(206) | 6)
+
+#define PINMUX_GPIO207__FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
+#define PINMUX_GPIO207__FUNC_PCIE_WAKEN_2P (MTK_PIN_NO(207) | 1)
+#define PINMUX_GPIO207__FUNC_PMSR_SMAP_MAX (MTK_PIN_NO(207) | 2)
+#define PINMUX_GPIO207__FUNC_FMI2S_A_BCK (MTK_PIN_NO(207) | 4)
+#define PINMUX_GPIO207__FUNC_UDI_TDO_4 (MTK_PIN_NO(207) | 6)
+
+#define PINMUX_GPIO208__FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
+#define PINMUX_GPIO208__FUNC_PCIE_CLKREQN_2P (MTK_PIN_NO(208) | 1)
+#define PINMUX_GPIO208__FUNC_PMSR_SMAP_MAX_W (MTK_PIN_NO(208) | 2)
+#define PINMUX_GPIO208__FUNC_FMI2S_A_LRCK (MTK_PIN_NO(208) | 4)
+#define PINMUX_GPIO208__FUNC_CLKM0_B (MTK_PIN_NO(208) | 5)
+#define PINMUX_GPIO208__FUNC_UDI_TDO_5 (MTK_PIN_NO(208) | 6)
+
+#define PINMUX_GPIO209__FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
+#define PINMUX_GPIO209__FUNC_PCIE_PERSTN_2P (MTK_PIN_NO(209) | 1)
+#define PINMUX_GPIO209__FUNC_PMSR_SMAP (MTK_PIN_NO(209) | 2)
+#define PINMUX_GPIO209__FUNC_FMI2S_A_DI (MTK_PIN_NO(209) | 4)
+#define PINMUX_GPIO209__FUNC_CLKM1_B (MTK_PIN_NO(209) | 5)
+#define PINMUX_GPIO209__FUNC_UDI_TDO_6 (MTK_PIN_NO(209) | 6)
+
+#define PINMUX_GPIO210__FUNC_GPIO210 (MTK_PIN_NO(210) | 0)
+#define PINMUX_GPIO210__FUNC_CMMCLK4 (MTK_PIN_NO(210) | 1)
+
+#define PINMUX_GPIO211__FUNC_GPIO211 (MTK_PIN_NO(211) | 0)
+#define PINMUX_GPIO211__FUNC_CMMCLK5 (MTK_PIN_NO(211) | 1)
+#define PINMUX_GPIO211__FUNC_CONN_TCXOENA_REQ (MTK_PIN_NO(211) | 2)
+
+#define PINMUX_GPIO212__FUNC_GPIO212 (MTK_PIN_NO(212) | 0)
+#define PINMUX_GPIO212__FUNC_CMMCLK6 (MTK_PIN_NO(212) | 1)
+#define PINMUX_GPIO212__FUNC_TP_GPIO10_AO (MTK_PIN_NO(212) | 2)
+#define PINMUX_GPIO212__FUNC_IDDIG (MTK_PIN_NO(212) | 5)
+#define PINMUX_GPIO212__FUNC_UDI_TDO_1 (MTK_PIN_NO(212) | 6)
+
+#define PINMUX_GPIO213__FUNC_GPIO213 (MTK_PIN_NO(213) | 0)
+#define PINMUX_GPIO213__FUNC_CMMCLK7 (MTK_PIN_NO(213) | 1)
+#define PINMUX_GPIO213__FUNC_TP_GPIO11_AO (MTK_PIN_NO(213) | 2)
+#define PINMUX_GPIO213__FUNC_USB_DRVVBUS (MTK_PIN_NO(213) | 5)
+#define PINMUX_GPIO213__FUNC_UDI_TDO_2 (MTK_PIN_NO(213) | 6)
+
+#define PINMUX_GPIO214__FUNC_GPIO214 (MTK_PIN_NO(214) | 0)
+#define PINMUX_GPIO214__FUNC_SCP_SCL3 (MTK_PIN_NO(214) | 1)
+#define PINMUX_GPIO214__FUNC_SDA14_E1 (MTK_PIN_NO(214) | 2)
+#define PINMUX_GPIO214__FUNC_SCL14_E2 (MTK_PIN_NO(214) | 2)
+#define PINMUX_GPIO214__FUNC_GBE1_MDC (MTK_PIN_NO(214) | 6)
+#define PINMUX_GPIO214__FUNC_GBE0_MDC (MTK_PIN_NO(214) | 7)
+
+#define PINMUX_GPIO215__FUNC_GPIO215 (MTK_PIN_NO(215) | 0)
+#define PINMUX_GPIO215__FUNC_SCP_SDA3 (MTK_PIN_NO(215) | 1)
+#define PINMUX_GPIO215__FUNC_SCL14_E1 (MTK_PIN_NO(215) | 2)
+#define PINMUX_GPIO215__FUNC_SDA14_E2 (MTK_PIN_NO(215) | 2)
+#define PINMUX_GPIO215__FUNC_GBE1_MDIO (MTK_PIN_NO(215) | 6)
+#define PINMUX_GPIO215__FUNC_GBE0_MDIO (MTK_PIN_NO(215) | 7)
+
+#define PINMUX_GPIO216__FUNC_GPIO216 (MTK_PIN_NO(216) | 0)
+#define PINMUX_GPIO216__FUNC_GPS_PPS0 (MTK_PIN_NO(216) | 1)
+
+#define PINMUX_GPIO217__FUNC_GPIO217 (MTK_PIN_NO(217) | 0)
+#define PINMUX_GPIO217__FUNC_KPROW0 (MTK_PIN_NO(217) | 1)
+#define PINMUX_GPIO217__FUNC_TP_GPIO12_AO (MTK_PIN_NO(217) | 6)
+
+#define PINMUX_GPIO218__FUNC_GPIO218 (MTK_PIN_NO(218) | 0)
+#define PINMUX_GPIO218__FUNC_KPROW1 (MTK_PIN_NO(218) | 1)
+#define PINMUX_GPIO218__FUNC_SPI0_WP (MTK_PIN_NO(218) | 2)
+#define PINMUX_GPIO218__FUNC_MBISTREADEN_TRIGGER (MTK_PIN_NO(218) | 3)
+#define PINMUX_GPIO218__FUNC_GPS_L5_ELNA_EN (MTK_PIN_NO(218) | 5)
+#define PINMUX_GPIO218__FUNC_TP_GPIO14_AO (MTK_PIN_NO(218) | 6)
+
+#define PINMUX_GPIO219__FUNC_GPIO219 (MTK_PIN_NO(219) | 0)
+#define PINMUX_GPIO219__FUNC_KPCOL1 (MTK_PIN_NO(219) | 1)
+#define PINMUX_GPIO219__FUNC_SPI0_HOLD (MTK_PIN_NO(219) | 2)
+#define PINMUX_GPIO219__FUNC_MBISTWRITEEN_TRIGGER (MTK_PIN_NO(219) | 3)
+#define PINMUX_GPIO219__FUNC_SPMI_M_TRIG_FLAG (MTK_PIN_NO(219) | 4)
+#define PINMUX_GPIO219__FUNC_GPS_L1_ELNA_EN (MTK_PIN_NO(219) | 5)
+#define PINMUX_GPIO219__FUNC_SPM_JTAG_TRSTN_VLP (MTK_PIN_NO(219) | 6)
+#define PINMUX_GPIO219__FUNC_JTRSTN_SEL1 (MTK_PIN_NO(219) | 7)
+
+#define PINMUX_GPIO220__FUNC_GPIO220 (MTK_PIN_NO(220) | 0)
+#define PINMUX_GPIO220__FUNC_SPI0_CLK (MTK_PIN_NO(220) | 1)
+#define PINMUX_GPIO220__FUNC_SPM_JTAG_TCK_VLP (MTK_PIN_NO(220) | 6)
+#define PINMUX_GPIO220__FUNC_JTCK_SEL1 (MTK_PIN_NO(220) | 7)
+
+#define PINMUX_GPIO221__FUNC_GPIO221 (MTK_PIN_NO(221) | 0)
+#define PINMUX_GPIO221__FUNC_SPI0_CSB (MTK_PIN_NO(221) | 1)
+#define PINMUX_GPIO221__FUNC_SPM_JTAG_TMS_VLP (MTK_PIN_NO(221) | 6)
+#define PINMUX_GPIO221__FUNC_JTMS_SEL1 (MTK_PIN_NO(221) | 7)
+
+#define PINMUX_GPIO222__FUNC_GPIO222 (MTK_PIN_NO(222) | 0)
+#define PINMUX_GPIO222__FUNC_SPI0_MO (MTK_PIN_NO(222) | 1)
+#define PINMUX_GPIO222__FUNC_SCP_SCL7 (MTK_PIN_NO(222) | 2)
+#define PINMUX_GPIO222__FUNC_SPM_JTAG_TDO_VLP (MTK_PIN_NO(222) | 6)
+#define PINMUX_GPIO222__FUNC_JTDO_SEL1 (MTK_PIN_NO(222) | 7)
+
+#define PINMUX_GPIO223__FUNC_GPIO223 (MTK_PIN_NO(223) | 0)
+#define PINMUX_GPIO223__FUNC_SPI0_MI (MTK_PIN_NO(223) | 1)
+#define PINMUX_GPIO223__FUNC_SCP_SDA7 (MTK_PIN_NO(223) | 2)
+#define PINMUX_GPIO223__FUNC_SPM_JTAG_TDI_VLP (MTK_PIN_NO(223) | 6)
+#define PINMUX_GPIO223__FUNC_JTDI_SEL1 (MTK_PIN_NO(223) | 7)
+
+#define PINMUX_GPIO224__FUNC_GPIO224 (MTK_PIN_NO(224) | 0)
+#define PINMUX_GPIO224__FUNC_MSDC2_CLK (MTK_PIN_NO(224) | 1)
+#define PINMUX_GPIO224__FUNC_DMIC2_CLK (MTK_PIN_NO(224) | 2)
+#define PINMUX_GPIO224__FUNC_GBE0_AUX_PPS0 (MTK_PIN_NO(224) | 3)
+#define PINMUX_GPIO224__FUNC_GBE0_TXER (MTK_PIN_NO(224) | 4)
+#define PINMUX_GPIO224__FUNC_GBE1_TXER (MTK_PIN_NO(224) | 5)
+#define PINMUX_GPIO224__FUNC_GBE1_AUX_PPS0 (MTK_PIN_NO(224) | 6)
+#define PINMUX_GPIO224__FUNC_MD32_1_TXD (MTK_PIN_NO(224) | 7)
+
+#define PINMUX_GPIO225__FUNC_GPIO225 (MTK_PIN_NO(225) | 0)
+#define PINMUX_GPIO225__FUNC_MSDC2_CMD (MTK_PIN_NO(225) | 1)
+#define PINMUX_GPIO225__FUNC_DMIC2_DAT (MTK_PIN_NO(225) | 2)
+#define PINMUX_GPIO225__FUNC_GBE0_AUX_PPS1 (MTK_PIN_NO(225) | 3)
+#define PINMUX_GPIO225__FUNC_GBE0_RXER (MTK_PIN_NO(225) | 4)
+#define PINMUX_GPIO225__FUNC_GBE1_RXER (MTK_PIN_NO(225) | 5)
+#define PINMUX_GPIO225__FUNC_GBE1_AUX_PPS1 (MTK_PIN_NO(225) | 6)
+#define PINMUX_GPIO225__FUNC_MD32_1_RXD (MTK_PIN_NO(225) | 7)
+
+#define PINMUX_GPIO226__FUNC_GPIO226 (MTK_PIN_NO(226) | 0)
+#define PINMUX_GPIO226__FUNC_MSDC2_DAT0 (MTK_PIN_NO(226) | 1)
+#define PINMUX_GPIO226__FUNC_I2SIN3_BCK (MTK_PIN_NO(226) | 2)
+#define PINMUX_GPIO226__FUNC_GBE0_AUX_PPS2 (MTK_PIN_NO(226) | 3)
+#define PINMUX_GPIO226__FUNC_GBE0_COL (MTK_PIN_NO(226) | 4)
+#define PINMUX_GPIO226__FUNC_GBE1_COL (MTK_PIN_NO(226) | 5)
+#define PINMUX_GPIO226__FUNC_GBE1_AUX_PPS2 (MTK_PIN_NO(226) | 6)
+#define PINMUX_GPIO226__FUNC_GBE1_MDC (MTK_PIN_NO(226) | 7)
+
+#define PINMUX_GPIO227__FUNC_GPIO227 (MTK_PIN_NO(227) | 0)
+#define PINMUX_GPIO227__FUNC_MSDC2_DAT1 (MTK_PIN_NO(227) | 1)
+#define PINMUX_GPIO227__FUNC_I2SIN3_LRCK (MTK_PIN_NO(227) | 2)
+#define PINMUX_GPIO227__FUNC_GBE0_AUX_PPS3 (MTK_PIN_NO(227) | 3)
+#define PINMUX_GPIO227__FUNC_GBE0_INTR (MTK_PIN_NO(227) | 4)
+#define PINMUX_GPIO227__FUNC_GBE1_INTR (MTK_PIN_NO(227) | 5)
+#define PINMUX_GPIO227__FUNC_GBE1_AUX_PPS3 (MTK_PIN_NO(227) | 6)
+#define PINMUX_GPIO227__FUNC_GBE1_MDIO (MTK_PIN_NO(227) | 7)
+
+#define PINMUX_GPIO228__FUNC_GPIO228 (MTK_PIN_NO(228) | 0)
+#define PINMUX_GPIO228__FUNC_MSDC2_DAT2 (MTK_PIN_NO(228) | 1)
+#define PINMUX_GPIO228__FUNC_I2SIN3_DI (MTK_PIN_NO(228) | 2)
+#define PINMUX_GPIO228__FUNC_GBE0_MDC (MTK_PIN_NO(228) | 3)
+#define PINMUX_GPIO228__FUNC_GBE1_MDC (MTK_PIN_NO(228) | 4)
+#define PINMUX_GPIO228__FUNC_CONN_BG_GPS_MCU_AICE_TCKC (MTK_PIN_NO(228) | 5)
+
+#define PINMUX_GPIO229__FUNC_GPIO229 (MTK_PIN_NO(229) | 0)
+#define PINMUX_GPIO229__FUNC_MSDC2_DAT3 (MTK_PIN_NO(229) | 1)
+#define PINMUX_GPIO229__FUNC_I2SOUT3_DO (MTK_PIN_NO(229) | 2)
+#define PINMUX_GPIO229__FUNC_GBE0_MDIO (MTK_PIN_NO(229) | 3)
+#define PINMUX_GPIO229__FUNC_GBE1_MDIO (MTK_PIN_NO(229) | 4)
+#define PINMUX_GPIO229__FUNC_CONN_BG_GPS_MCU_AICE_TMSC (MTK_PIN_NO(229) | 5)
+#define PINMUX_GPIO229__FUNC_AVB_CLK2 (MTK_PIN_NO(229) | 7)
+
+#define PINMUX_GPIO230__FUNC_GPIO230 (MTK_PIN_NO(230) | 0)
+#define PINMUX_GPIO230__FUNC_CONN_TOP_CLK (MTK_PIN_NO(230) | 1)
+
+#define PINMUX_GPIO231__FUNC_GPIO231 (MTK_PIN_NO(231) | 0)
+#define PINMUX_GPIO231__FUNC_CONN_TOP_DATA (MTK_PIN_NO(231) | 1)
+
+#define PINMUX_GPIO232__FUNC_GPIO232 (MTK_PIN_NO(232) | 0)
+#define PINMUX_GPIO232__FUNC_CONN_HRST_B (MTK_PIN_NO(232) | 1)
+
+#define PINMUX_GPIO233__FUNC_GPIO233 (MTK_PIN_NO(233) | 0)
+#define PINMUX_GPIO233__FUNC_I2SIN0_BCK (MTK_PIN_NO(233) | 1)
+
+#define PINMUX_GPIO234__FUNC_GPIO234 (MTK_PIN_NO(234) | 0)
+#define PINMUX_GPIO234__FUNC_I2SIN0_LRCK (MTK_PIN_NO(234) | 1)
+
+#define PINMUX_GPIO235__FUNC_GPIO235 (MTK_PIN_NO(235) | 0)
+#define PINMUX_GPIO235__FUNC_I2SIN0_DI (MTK_PIN_NO(235) | 1)
+
+#define PINMUX_GPIO236__FUNC_GPIO236 (MTK_PIN_NO(236) | 0)
+#define PINMUX_GPIO236__FUNC_I2SOUT0_DO (MTK_PIN_NO(236) | 1)
+
+#define PINMUX_GPIO237__FUNC_GPIO237 (MTK_PIN_NO(237) | 0)
+#define PINMUX_GPIO237__FUNC_CONN_UARTHUB_UART_TX (MTK_PIN_NO(237) | 1)
+#define PINMUX_GPIO237__FUNC_UTXD3 (MTK_PIN_NO(237) | 3)
+
+#define PINMUX_GPIO238__FUNC_GPIO238 (MTK_PIN_NO(238) | 0)
+#define PINMUX_GPIO238__FUNC_CONN_UARTHUB_UART_RX (MTK_PIN_NO(238) | 1)
+#define PINMUX_GPIO238__FUNC_URXD3 (MTK_PIN_NO(238) | 3)
+
+#define PINMUX_GPIO239__FUNC_GPIO239 (MTK_PIN_NO(239) | 0)
+#define PINMUX_GPIO239__FUNC_TP_UTXD_CONSYS_VLP (MTK_PIN_NO(239) | 1)
+#define PINMUX_GPIO239__FUNC_TP_URXD_CONSYS_VLP (MTK_PIN_NO(239) | 2)
+
+#define PINMUX_GPIO240__FUNC_GPIO240 (MTK_PIN_NO(240) | 0)
+#define PINMUX_GPIO240__FUNC_TP_URXD_CONSYS_VLP (MTK_PIN_NO(240) | 1)
+#define PINMUX_GPIO240__FUNC_TP_UTXD_CONSYS_VLP (MTK_PIN_NO(240) | 2)
+
+#define PINMUX_GPIO241__FUNC_GPIO241 (MTK_PIN_NO(241) | 0)
+#define PINMUX_GPIO241__FUNC_PCIE_PERSTN (MTK_PIN_NO(241) | 1)
+
+#define PINMUX_GPIO242__FUNC_GPIO242 (MTK_PIN_NO(242) | 0)
+#define PINMUX_GPIO242__FUNC_PCIE_WAKEN (MTK_PIN_NO(242) | 1)
+
+#define PINMUX_GPIO243__FUNC_GPIO243 (MTK_PIN_NO(243) | 0)
+#define PINMUX_GPIO243__FUNC_PCIE_CLKREQN (MTK_PIN_NO(243) | 1)
+
+#define PINMUX_GPIO244__FUNC_GPIO244 (MTK_PIN_NO(244) | 0)
+#define PINMUX_GPIO244__FUNC_CONN_RST (MTK_PIN_NO(244) | 1)
+
+#define PINMUX_GPIO245__FUNC_GPIO245 (MTK_PIN_NO(245) | 0)
+
+#define PINMUX_GPIO246__FUNC_GPIO246 (MTK_PIN_NO(246) | 0)
+#define PINMUX_GPIO246__FUNC_CONN_PTA_TXD0 (MTK_PIN_NO(246) | 1)
+
+#define PINMUX_GPIO247__FUNC_GPIO247 (MTK_PIN_NO(247) | 0)
+#define PINMUX_GPIO247__FUNC_CONN_PTA_RXD0 (MTK_PIN_NO(247) | 1)
+
+#define PINMUX_GPIO248__FUNC_GPIO248 (MTK_PIN_NO(248) | 0)
+#define PINMUX_GPIO248__FUNC_UCTS3 (MTK_PIN_NO(248) | 3)
+
+#define PINMUX_GPIO249__FUNC_GPIO249 (MTK_PIN_NO(249) | 0)
+#define PINMUX_GPIO249__FUNC_URTS3 (MTK_PIN_NO(249) | 3)
+
+#define PINMUX_GPIO250__FUNC_GPIO250 (MTK_PIN_NO(250) | 0)
+
+#define PINMUX_GPIO251__FUNC_GPIO251 (MTK_PIN_NO(251) | 0)
+#define PINMUX_GPIO251__FUNC_IDDIG_1P (MTK_PIN_NO(251) | 1)
+
+#define PINMUX_GPIO252__FUNC_GPIO252 (MTK_PIN_NO(252) | 0)
+#define PINMUX_GPIO252__FUNC_USB_DRVVBUS_1P (MTK_PIN_NO(252) | 1)
+
+#define PINMUX_GPIO253__FUNC_GPIO253 (MTK_PIN_NO(253) | 0)
+#define PINMUX_GPIO253__FUNC_VBUSVALID_1P (MTK_PIN_NO(253) | 1)
+
+#define PINMUX_GPIO254__FUNC_GPIO254 (MTK_PIN_NO(254) | 0)
+#define PINMUX_GPIO254__FUNC_IDDIG_2P (MTK_PIN_NO(254) | 1)
+
+#define PINMUX_GPIO255__FUNC_GPIO255 (MTK_PIN_NO(255) | 0)
+#define PINMUX_GPIO255__FUNC_USB_DRVVBUS_2P (MTK_PIN_NO(255) | 1)
+
+#define PINMUX_GPIO256__FUNC_GPIO256 (MTK_PIN_NO(256) | 0)
+#define PINMUX_GPIO256__FUNC_VBUSVALID_2P (MTK_PIN_NO(256) | 1)
+
+#define PINMUX_GPIO257__FUNC_GPIO257 (MTK_PIN_NO(257) | 0)
+#define PINMUX_GPIO257__FUNC_VBUSVALID_3P (MTK_PIN_NO(257) | 1)
+
+#define PINMUX_GPIO258__FUNC_GPIO258 (MTK_PIN_NO(258) | 0)
+#define PINMUX_GPIO258__FUNC_AVB_CLK1 (MTK_PIN_NO(258) | 7)
+
+#define PINMUX_GPIO259__FUNC_GPIO259 (MTK_PIN_NO(259) | 0)
+#define PINMUX_GPIO259__FUNC_GBE0_TXD0 (MTK_PIN_NO(259) | 1)
+#define PINMUX_GPIO259__FUNC_GBE1_TXD0 (MTK_PIN_NO(259) | 2)
+
+#define PINMUX_GPIO260__FUNC_GPIO260 (MTK_PIN_NO(260) | 0)
+#define PINMUX_GPIO260__FUNC_GBE0_TXD1 (MTK_PIN_NO(260) | 1)
+#define PINMUX_GPIO260__FUNC_GBE1_TXD1 (MTK_PIN_NO(260) | 2)
+
+#define PINMUX_GPIO261__FUNC_GPIO261 (MTK_PIN_NO(261) | 0)
+#define PINMUX_GPIO261__FUNC_GBE0_TXC (MTK_PIN_NO(261) | 1)
+#define PINMUX_GPIO261__FUNC_GBE1_TXC (MTK_PIN_NO(261) | 2)
+
+#define PINMUX_GPIO262__FUNC_GPIO262 (MTK_PIN_NO(262) | 0)
+#define PINMUX_GPIO262__FUNC_GBE0_TXEN (MTK_PIN_NO(262) | 1)
+#define PINMUX_GPIO262__FUNC_GBE1_TXEN (MTK_PIN_NO(262) | 2)
+
+#define PINMUX_GPIO263__FUNC_GPIO263 (MTK_PIN_NO(263) | 0)
+#define PINMUX_GPIO263__FUNC_GBE0_RXD0 (MTK_PIN_NO(263) | 1)
+#define PINMUX_GPIO263__FUNC_GBE1_RXD0 (MTK_PIN_NO(263) | 2)
+#define PINMUX_GPIO263__FUNC_GBE0_AUX_PPS0 (MTK_PIN_NO(263) | 3)
+
+#define PINMUX_GPIO264__FUNC_GPIO264 (MTK_PIN_NO(264) | 0)
+#define PINMUX_GPIO264__FUNC_GBE0_RXD1 (MTK_PIN_NO(264) | 1)
+#define PINMUX_GPIO264__FUNC_GBE1_RXD1 (MTK_PIN_NO(264) | 2)
+#define PINMUX_GPIO264__FUNC_GBE0_AUX_PPS1 (MTK_PIN_NO(264) | 3)
+
+#define PINMUX_GPIO265__FUNC_GPIO265 (MTK_PIN_NO(265) | 0)
+#define PINMUX_GPIO265__FUNC_GBE0_RXC (MTK_PIN_NO(265) | 1)
+#define PINMUX_GPIO265__FUNC_GBE1_RXC (MTK_PIN_NO(265) | 2)
+#define PINMUX_GPIO265__FUNC_GBE0_AUX_PPS2 (MTK_PIN_NO(265) | 3)
+
+#define PINMUX_GPIO266__FUNC_GPIO266 (MTK_PIN_NO(266) | 0)
+#define PINMUX_GPIO266__FUNC_GBE0_RXDV (MTK_PIN_NO(266) | 1)
+#define PINMUX_GPIO266__FUNC_GBE1_RXDV (MTK_PIN_NO(266) | 2)
+#define PINMUX_GPIO266__FUNC_GBE0_AUX_PPS3 (MTK_PIN_NO(266) | 3)
+
+#define PINMUX_GPIO267__FUNC_GPIO267 (MTK_PIN_NO(267) | 0)
+#define PINMUX_GPIO267__FUNC_GBE0_TXD2 (MTK_PIN_NO(267) | 1)
+#define PINMUX_GPIO267__FUNC_GBE1_TXD2 (MTK_PIN_NO(267) | 2)
+#define PINMUX_GPIO267__FUNC_GBE0_RXER (MTK_PIN_NO(267) | 3)
+#define PINMUX_GPIO267__FUNC_GBE1_RXER (MTK_PIN_NO(267) | 4)
+
+#define PINMUX_GPIO268__FUNC_GPIO268 (MTK_PIN_NO(268) | 0)
+#define PINMUX_GPIO268__FUNC_GBE0_TXD3 (MTK_PIN_NO(268) | 1)
+#define PINMUX_GPIO268__FUNC_GBE1_TXD3 (MTK_PIN_NO(268) | 2)
+
+#define PINMUX_GPIO269__FUNC_GPIO269 (MTK_PIN_NO(269) | 0)
+#define PINMUX_GPIO269__FUNC_GBE0_RXD2 (MTK_PIN_NO(269) | 1)
+#define PINMUX_GPIO269__FUNC_GBE1_RXD2 (MTK_PIN_NO(269) | 2)
+#define PINMUX_GPIO269__FUNC_GBE0_MDC (MTK_PIN_NO(269) | 3)
+
+#define PINMUX_GPIO270__FUNC_GPIO270 (MTK_PIN_NO(270) | 0)
+#define PINMUX_GPIO270__FUNC_GBE0_RXD3 (MTK_PIN_NO(270) | 1)
+#define PINMUX_GPIO270__FUNC_GBE1_RXD3 (MTK_PIN_NO(270) | 2)
+#define PINMUX_GPIO270__FUNC_GBE0_MDIO (MTK_PIN_NO(270) | 3)
+
+#endif /* __MT8196_PINFUNC_H */
-- 
2.45.2



From arnd at arndb.de  Fri Mar 21 02:00:59 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 10:00:59 +0100
Subject: [PATCH v4 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <20250305053823.2048217-7-peter.chen@cixtech.com>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-7-peter.chen@cixtech.com>
Message-ID: <59619096-bfb2-428c-a4f5-2dfb031d126c@app.fastmail.com>

On Wed, Mar 5, 2025, at 06:38, Peter Chen wrote:
> +ARM/CIX SKY ARM ARCHITECTURE
> +M:     Peter Chen <peter.chen at cixtech.com>
> +M:     Fugang Duan <fugang.duan at cixtech.com>
> +R:     CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
> +L:     linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> +S:     Maintained
> +F:     Documentation/devicetree/bindings/arm/cix.yaml
> +F:     arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> +F:     arch/arm64/boot/dts/cix/sky1.dtsi
> +

Looks good to me. You can also add a regex keyword entry such as

K:       \bcix\b

to match any filenames that have 'cix' as a whole word.

    Arnd


From maz at kernel.org  Fri Mar 21 02:04:00 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 21 Mar 2025 09:04:00 +0000
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <Z9vmeTj68LmwinPD@nchen-desktop>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
	<20250305053823.2048217-6-peter.chen@cixtech.com>
	<86frj8m4be.wl-maz@kernel.org>
	<Z9vmeTj68LmwinPD@nchen-desktop>
Message-ID: <86bjtun4an.wl-maz@kernel.org>

On Thu, 20 Mar 2025 09:57:13 +0000,
Peter Chen <peter.chen at cixtech.com> wrote:
> 
> On 25-03-20 09:36:37, Marc Zyngier wrote:
> > Peter Chen <peter.chen at cixtech.com> wrote:
> > >
> > > +     pmu-a520 {
> > > +             compatible = "arm,cortex-a520-pmu";
> > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> > > +     };
> > > +
> > > +     pmu-a720 {
> > > +             compatible = "arm,cortex-a720-pmu";
> > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> > > +     };
> > > +
> > > +     pmu-spe {
> > > +             compatible = "arm,statistical-profiling-extension-v1";
> > > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
> > > +     };
> > 
> > SPE should follow the same model as the PMU, as each CPU has its own
> > SPE implementation, exposing different micro-architectural details.
> > 
> 
> Hi Marc,
> 
> Thanks for your reply. But there is only one compatible string
> "statistical-profiling-extension-v1" at drivers/perf/arm_spe_pmu.c,
> how could differentiate pmu-spe-a720 and pmu-spe-a520, do I need
> to change arm_spe_pmu.c as well?

I don't think there is a need to have different compatible. The driver
can probe which CPU this is on, and work out the implemented
subfeatures from the PMSIDR_EL1 register. New compatible strings are
better avoided when there is a way to probe/discover the HW (and in
most cases, there is).

Note that this equally applies to TRBE, which also explicitly deals
with interrupt partitioning and yet only has a single compatible.
Please consider adding TRBE support when you repost this series.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From ot_cathy.xu at mediatek.com  Fri Mar 21 01:39:11 2025
From: ot_cathy.xu at mediatek.com (Cathy Xu)
Date: Fri, 21 Mar 2025 16:39:11 +0800
Subject: [PATCH v5 0/3] pinctrl: mediatek: Add pinctrl driver on mt8196
Message-ID: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>

Changes in v5:
- Remove header file to fix dt-binding check error.
- Add /* sentinel */ in pinctrl-mt8196.c.

Changes in v4:
- Add rsel-resistence-in-si-unit and remove RSEL macro magic
  number in mediatek,mt8196-pinctrl.yaml.
- Add values in SI units option to |struct mtk_pin_soc| in
  pinctrl-mt8196.c.
- Move pinmux macro header file to arch/arm64/boot/dts/mediatek.

Changes in v3:
- Remove drive-strength-microamp & rsel-resistence-in-si-unit
  related description in mediatek,mt8196-pinctrl.yaml.
- Use pm_sleep_ptr() in pinctrl-mt8196.c to fix build error.

Changes in v2:
- Fix driver file's coding style.
- Add pinctrl binding document.

Cathy Xu (3):
  dt-bindings: pinctrl: mediatek: Add support for mt8196
  arm64: dts: mediatek: mt8196: Add pinmux macro header file
  pinctrl: mediatek: Add pinctrl driver on mt8196

 .../pinctrl/mediatek,mt8196-pinctrl.yaml      |  223 ++
 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h | 1574 ++++++++++
 drivers/pinctrl/mediatek/Kconfig              |   12 +
 drivers/pinctrl/mediatek/Makefile             |    1 +
 drivers/pinctrl/mediatek/pinctrl-mt8196.c     | 1859 +++++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-mt8196.h | 2789 +++++++++++++++++
 6 files changed, 6458 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/mediatek,mt8196-pinctrl.yaml
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt8196.c
 create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt8196.h

-- 
2.45.2



From lkp at intel.com  Fri Mar 21 02:06:04 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 17:06:04 +0800
Subject: [soc:soc/drivers 20/24] undefined reference to `__ffsdi2'
Message-ID: <202503211748.QH9oyt9m-lkp@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
head:   ba8755ab541fc629948233125db870d4dbf00a75
commit: ee7f8ed72990f28657b5bf598e695fcf4633f4ed [20/24] platform: cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20250321/202503211748.QH9oyt9m-lkp at intel.com/config)
compiler: alpha-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250321/202503211748.QH9oyt9m-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503211748.QH9oyt9m-lkp at intel.com/

All errors (new ones prefixed by >>):

   alpha-linux-ld: drivers/platform/cznic/turris-omnia-mcu-gpio.o: in function `omnia_mcu_request_irq':
>> (.text+0x2660): undefined reference to `__ffsdi2'
>> alpha-linux-ld: (.text+0x2668): undefined reference to `__ffsdi2'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From amergnat at baylibre.com  Fri Mar 21 02:19:41 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Fri, 21 Mar 2025 10:19:41 +0100
Subject: [PATCH v8 2/3] drm/panel: startek-kd070fhfid015: add another init
 step
In-Reply-To: <d70b62f8-e24e-4a10-8c6b-18d2e19f1337@collabora.com>
References: <20231023-display-support-v8-0-c2dd7b0fb2bd@baylibre.com>
 <20231023-display-support-v8-2-c2dd7b0fb2bd@baylibre.com>
 <d70b62f8-e24e-4a10-8c6b-18d2e19f1337@collabora.com>
Message-ID: <fb72f1f5-dc94-4e33-a20c-d46a081091bc@baylibre.com>

Hi Angelo,
Thanks for the fast feedback :)

On 20/03/2025 13:37, AngeloGioacchino Del Regno wrote:
> Il 20/03/25 09:48, Alexandre Mergnat ha scritto:
>> Currently, the panel set power, set gpio and enable the display link
>> in stk_panel_prepare, pointed by drm_panel_funcs.prepare, called by
>> panel_bridge_atomic_pre_enable, pointed by
>> drm_bridge_funcs.atomic_pre_enable. According to the drm_bridge.h,
>> atomic_pre_enable must not enable the display link
>>
>> Since the DSI driver is properly inited by the DRM, the panel try to
>> communicate with the panel before DSI is powered on.
>>
> 
> The panel driver shall still be able to send commands in the .prepare() callback
> and if this is not happening anymore... well, there's a problem!

Sorry I don't think so, according to that def:
	/**
	 * @pre_enable:
	 *
	 * This callback should enable the bridge. It is called right before
	 * the preceding element in the display pipe is enabled. If the
	 * preceding element is a bridge this means it's called before that
	 * bridge's @pre_enable function. If the preceding element is a
	 * &drm_encoder it's called right before the encoder's
	 * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
	 * &drm_encoder_helper_funcs.dpms hook.
	 *
	 * The display pipe (i.e. clocks and timing signals) feeding this bridge
	 * will not yet be running when this callback is called. The bridge must
	 * not enable the display link feeding the next bridge in the chain (if
	 * there is one) when this callback is called.
	 *
	 * The @pre_enable callback is optional.
	 *
	 * NOTE:
	 *
	 * This is deprecated, do not use!
	 * New drivers shall use &drm_bridge_funcs.atomic_pre_enable.
	 */
	void (*pre_enable)(struct drm_bridge *bridge);

	/**
	 * @enable:
	 *
	 * This callback should enable the bridge. It is called right after
	 * the preceding element in the display pipe is enabled. If the
	 * preceding element is a bridge this means it's called after that
	 * bridge's @enable function. If the preceding element is a
	 * &drm_encoder it's called right after the encoder's
	 * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
	 * &drm_encoder_helper_funcs.dpms hook.
	 *
	 * The bridge can assume that the display pipe (i.e. clocks and timing
	 * signals) feeding it is running when this callback is called. This
	 * callback must enable the display link feeding the next bridge in the
	 * chain if there is one.
	 *
	 * The @enable callback is optional.
	 *
	 * NOTE:
	 *
	 * This is deprecated, do not use!
	 * New drivers shall use &drm_bridge_funcs.atomic_enable.
	 */
	void (*enable)(struct drm_bridge *bridge);

=> "The bridge must not enable the display link feeding the next bridge in the
=> chain (if there is one) when this callback is called."

Additionally, you ask for something impossible because here is the init order
fixed by the framework:

[   10.753139] panel_bridge_atomic_pre_enable
[   10.963505] mtk_dsi_bridge_atomic_pre_enable
[   10.963518] mtk_dsi_bridge_atomic_enable
[   10.963527] panel_bridge_atomic_enable
[   10.963532] drm_panel_enable

If panel want to use the DSI link in panel_bridge_atomic_pre_enable, nothing
will happen and  you will get a timeout.

So, IMHO, this patch make sense.

> 
>> To solve that, use stk_panel_enable to enable the display link because
>> it's called after the mtk_dsi_bridge_atomic_pre_enable which is power
>> on the DSI.
>>
>> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
>> ---
>> ? .../gpu/drm/panel/panel-startek-kd070fhfid015.c??? | 25 +++++++++++++---------
>> ? 1 file changed, 15 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c 
>> b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
>> index c0c95355b7435..bc3c4038bf4f5 100644
>> --- a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
>> +++ b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
>> @@ -135,19 +135,9 @@ static int stk_panel_prepare(struct drm_panel *panel)
>> ????? gpiod_set_value(stk->enable_gpio, 1);
>> ????? mdelay(20);
>> ????? gpiod_set_value(stk->reset_gpio, 1);
>> -??? mdelay(10);
>> -??? ret = stk_panel_init(stk);
>> -??? if (ret < 0)
>> -??????? goto poweroff;
> 
> Also, you're moving both init and set_display_on to the enable callback...
> this is suboptimal.
> 
> You should do the DrIC setup in .prepare() (can include SLEEP OUT), and then you
> should have a .enable() callback that calls DISP ON, a .disable() callback that
> calls DISP OFF, and .unprepare() that turns everything off.

This is not what I understand from the pre_enable's definition above, and also
the function call order by the framework. :)

> 
> Cheers,
> Angelo
> 
>> -
>> -??? ret = stk_panel_on(stk);
>> -??? if (ret < 0)
>> -??????? goto poweroff;
>> ????? return 0;
>> -poweroff:
>> -??? regulator_disable(stk->supplies[POWER].consumer);
>> ? iovccoff:
>> ????? regulator_disable(stk->supplies[IOVCC].consumer);
>> ????? gpiod_set_value(stk->reset_gpio, 0);
>> @@ -156,6 +146,20 @@ static int stk_panel_prepare(struct drm_panel *panel)
>> ????? return ret;
>> ? }
>> +static int stk_panel_enable(struct drm_panel *panel)
>> +{
>> +??? struct stk_panel *stk = to_stk_panel(panel);
>> +??? int ret;
>> +
>> +??? ret = stk_panel_init(stk);
>> +??? if (ret < 0)
>> +??????? return ret;
>> +
>> +??? ret = stk_panel_on(stk);
>> +
>> +??? return ret;
>> +}
>> +
>> ? static const struct drm_display_mode default_mode = {
>> ????????? .clock = 163204,
>> ????????? .hdisplay = 1200,
>> @@ -239,6 +243,7 @@ drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
>> ? }
>> ? static const struct drm_panel_funcs stk_panel_funcs = {
>> +??? .enable = stk_panel_enable,
>> ????? .unprepare = stk_panel_unprepare,
>> ????? .prepare = stk_panel_prepare,
>> ????? .get_modes = stk_panel_get_modes,
>>
> 
> 
> 

-- 
Regards,
Alexandre


From krzk at kernel.org  Fri Mar 21 02:25:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 10:25:34 +0100
Subject: [PATCH] arm64: dts: amlogic: a4: fix dtb compilation warning
 issues
In-Reply-To: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
References: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
Message-ID: <e21f3e39-573d-4391-885a-2df7c2598d80@kernel.org>

On 21/03/2025 03:23, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> 
> When use command 'make ARCH=arm64 dtbs_check W=1' to compile dtb,
> a warning message appears.
> "Warning (simple_bus_reg): /soc/bus at fe000000/pinctrl:
> missing or empty reg/ranges property"
> 
> Add the unit address to the pinctrl node to fix it.
> 
> Fixes: ce78f679e08c ("arm64: dts: amlogic: a4: add pinctrl node")
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>  arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 102 +++++++++++++++-------------
>  1 file changed, 55 insertions(+), 47 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> index fa80fa365f13..582e0043024b 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> @@ -51,87 +51,52 @@ pwrc: power-controller {
>  };
>  
>  &apb {
> -	gpio_intc: interrupt-controller at 4080 {
> -		compatible = "amlogic,a4-gpio-intc",
> -			     "amlogic,meson-gpio-intc";
> -		reg = <0x0 0x4080 0x0 0x20>;
> -		interrupt-controller;
> -		#interrupt-cells = <2>;
> -		amlogic,channel-interrupts =
> -			<10 11 12 13 14 15 16 17 18 19 20 21>;
> -	};
> -
> -	gpio_ao_intc: interrupt-controller at 8e72c {
> -		compatible = "amlogic,a4-gpio-ao-intc",
> -			     "amlogic,meson-gpio-intc";
> -		reg = <0x0 0x8e72c 0x0 0x0c>;
> -		interrupt-controller;
> -		#interrupt-cells = <2>;
> -		amlogic,channel-interrupts = <140 141>;
> -	};


Not related to the change you described in commit msg.


Best regards,
Krzysztof


From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:36 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:36 +0800
Subject: [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-8-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

Refactor SOF settings by adding mtk_mutex_get_output_comp_sof()
and extracting SOF logic from mtk_mutex_add_comp()
and mtk_mutex_remove_comp().

- Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
  for SOF settings.
- Reused the switch case for SOF IDs.
- Separated MOD and SOF logic.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c       | 121 +++++++++++++++----------
 include/linux/soc/mediatek/mtk-mutex.h |   4 +
 2 files changed, 79 insertions(+), 46 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index aaa965d4b050..c026ac0e6969 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -853,43 +853,84 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
 
-void mtk_mutex_add_comp(struct mtk_mutex *mutex,
-			enum mtk_ddp_comp_id id)
+static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
 {
-	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
-						 mutex[mutex->id]);
-	unsigned int reg;
-	unsigned int sof_id;
-	unsigned int offset;
-
-	WARN_ON(&mtx->mutex[mutex->id] != mutex);
-
 	switch (id) {
 	case DDP_COMPONENT_DSI0:
-		sof_id = MUTEX_SOF_DSI0;
-		break;
+		return MUTEX_SOF_DSI0;
 	case DDP_COMPONENT_DSI1:
-		sof_id = MUTEX_SOF_DSI0;
-		break;
+		return MUTEX_SOF_DSI1;
 	case DDP_COMPONENT_DSI2:
-		sof_id = MUTEX_SOF_DSI2;
-		break;
+		return MUTEX_SOF_DSI2;
 	case DDP_COMPONENT_DSI3:
-		sof_id = MUTEX_SOF_DSI3;
-		break;
+		return MUTEX_SOF_DSI3;
 	case DDP_COMPONENT_DPI0:
-		sof_id = MUTEX_SOF_DPI0;
-		break;
+		return MUTEX_SOF_DPI0;
 	case DDP_COMPONENT_DPI1:
-		sof_id = MUTEX_SOF_DPI1;
-		break;
+		return MUTEX_SOF_DPI1;
 	case DDP_COMPONENT_DP_INTF0:
-		sof_id = MUTEX_SOF_DP_INTF0;
-		break;
+		return MUTEX_SOF_DP_INTF0;
 	case DDP_COMPONENT_DP_INTF1:
-		sof_id = MUTEX_SOF_DP_INTF1;
-		break;
+		return MUTEX_SOF_DP_INTF1;
 	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	unsigned int offset;
+
+	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
+		return;
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
+
+	writel_relaxed(mtx->data->mutex_sof[sof_id],
+		       mtx->regs + offset);
+}
+EXPORT_SYMBOL_GPL(mtk_mutex_add_comp_sof);
+
+void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	unsigned int reg;
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	unsigned int offset;
+
+	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
+		return;
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
+	reg = readl_relaxed(mtx->regs + offset);
+	reg &= ~(1 << mtx->data->mutex_sof[id]);
+
+	writel_relaxed(reg, mtx->regs + offset);
+}
+EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp_sof);
+
+void mtk_mutex_add_comp(struct mtk_mutex *mutex,
+			enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	unsigned int reg;
+	unsigned int offset;
+	bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	if (!is_output_comp) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -902,12 +943,10 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 			reg |= 1 << (mtx->data->mutex_mod[id] - 32);
 			writel_relaxed(reg, mtx->regs + offset);
 		}
-		return;
 	}
 
-	writel_relaxed(mtx->data->mutex_sof[sof_id],
-		       mtx->regs +
-		       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
+	if (is_output_comp)
+		mtk_mutex_add_comp_sof(mutex, id);
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
 
@@ -918,24 +957,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 						 mutex[mutex->id]);
 	unsigned int reg;
 	unsigned int offset;
+	bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	switch (id) {
-	case DDP_COMPONENT_DSI0:
-	case DDP_COMPONENT_DSI1:
-	case DDP_COMPONENT_DSI2:
-	case DDP_COMPONENT_DSI3:
-	case DDP_COMPONENT_DPI0:
-	case DDP_COMPONENT_DPI1:
-	case DDP_COMPONENT_DP_INTF0:
-	case DDP_COMPONENT_DP_INTF1:
-		writel_relaxed(MUTEX_SOF_SINGLE_MODE,
-			       mtx->regs +
-			       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
-						  mutex->id));
-		break;
-	default:
+	if (!is_output_comp) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -948,8 +974,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 			reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
 			writel_relaxed(reg, mtx->regs + offset);
 		}
-		break;
 	}
+
+	if (is_output_comp)
+		mtk_mutex_remove_comp_sof(mutex, id);
+
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
 
diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h
index 635218e3ac68..515e2d8bfc90 100644
--- a/include/linux/soc/mediatek/mtk-mutex.h
+++ b/include/linux/soc/mediatek/mtk-mutex.h
@@ -69,6 +69,10 @@ enum mtk_mutex_sof_index {
 
 struct mtk_mutex *mtk_mutex_get(struct device *dev);
 int mtk_mutex_prepare(struct mtk_mutex *mutex);
+void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex,
+			    enum mtk_ddp_comp_id id);
+void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex,
+			       enum mtk_ddp_comp_id id);
 void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 			enum mtk_ddp_comp_id id);
 void mtk_mutex_enable(struct mtk_mutex *mutex);
-- 
2.45.2



From krzk at kernel.org  Fri Mar 21 03:13:33 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 11:13:33 +0100
Subject: [PATCH 1/2] spi: dt-bindings: st,stm32mp25-ospi: Make "resets" a
 required property
In-Reply-To: <20250321-upstream_ospi_required_resets-v1-1-9aa4702e3ae2@foss.st.com>
References: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
 <20250321-upstream_ospi_required_resets-v1-1-9aa4702e3ae2@foss.st.com>
Message-ID: <688c619d-0e20-496a-ae24-d62ab34f93ab@kernel.org>

On 21/03/2025 10:44, Patrice Chotard wrote:
> Make "resets" a required property.

Please explain why. This is technically an ABI break, so you please
provide explanation what sort of issue is being fixed.

> 
> Fixes: bed97e35786a ("dt-bindings: spi: Add STM32 OSPI controller")
> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
> ---
>  Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
>  1 file changed, 1 insertion(+)


Best regards,
Krzysztof


From patrice.chotard at foss.st.com  Fri Mar 21 02:32:21 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:21 +0100
Subject: [PATCH v6 1/7] MAINTAINERS: add entry for STM32 OCTO MEMORY
 MANAGER driver
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-1-37bbcab43439@foss.st.com>

Add myself as STM32 OCTO MEMORY MANAGER maintainer.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5b7e1f9c30f3e45fb85b0d0f58b56db84d986061..830245c8d583c422e869dfe4b5a184faaf52b559 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22766,6 +22766,12 @@ L:	linux-i2c at vger.kernel.org
 S:	Maintained
 F:	drivers/i2c/busses/i2c-stm32*
 
+ST STM32 OCTO MEMORY MANAGER
+M:	Patrice Chotard <patrice.chotard at foss.st.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
+F:	drivers/memory/stm32_omm.c
+
 ST STM32 SPI DRIVER
 M:	Alain Volmat <alain.volmat at foss.st.com>
 L:	linux-spi at vger.kernel.org

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:23 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:23 +0100
Subject: [PATCH v6 3/7] memory: Add STM32 Octo Memory Manager driver
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-3-37bbcab43439@foss.st.com>

Octo Memory Manager driver (OMM) manages:
  - the muxing between 2 OSPI busses and 2 output ports.
    There are 4 possible muxing configurations:
      - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
        output is on port 2
      - OSPI1 and OSPI2 are multiplexed over the same output port 1
      - swapped mode (no multiplexing), OSPI1 output is on port 2,
        OSPI2 output is on port 1
      - OSPI1 and OSPI2 are multiplexed over the same output port 2
  - the split of the memory area shared between the 2 OSPI instances.
  - chip select selection override.
  - the time between 2 transactions in multiplexed mode.
  - check firewall access.

Signed-off-by: Christophe Kerello <christophe.kerello at foss.st.com>
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 drivers/memory/Kconfig     |  17 ++
 drivers/memory/Makefile    |   1 +
 drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 492 insertions(+)

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c82d8d8a16eaf154c247c0dbb9aff428b7c81402..3a0703fbfee7d1a9467cc74821604d3861fb1de0 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -225,6 +225,23 @@ config STM32_FMC2_EBI
 	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
 	  SOCs containing the FMC2 External Bus Interface.
 
+config STM32_OMM
+	tristate "STM32 Octo Memory Manager"
+	depends on SPI_STM32_OSPI || COMPILE_TEST
+	help
+	  This driver manages the muxing between the 2 OSPI busses and
+	  the 2 output ports. There are 4 possible muxing configurations:
+	  - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
+	       output is on port 2
+	  - OSPI1 and OSPI2 are multiplexed over the same output port 1
+	  - swapped mode (no multiplexing), OSPI1 output is on port 2,
+	       OSPI2 output is on port 1
+	  - OSPI1 and OSPI2 are multiplexed over the same output port 2
+	  It also manages :
+	    - the split of the memory area shared between the 2 OSPI instances.
+	    - chip select selection override.
+	    - the time between 2 transactions in multiplexed mode.
+
 source "drivers/memory/samsung/Kconfig"
 source "drivers/memory/tegra/Kconfig"
 
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index d2e6ca9abbe0231c14284e3818ce734c618f83d0..c1959661bf63775bdded6dcbe87b732883c26135 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_DA8XX_DDRCTL)	+= da8xx-ddrctl.o
 obj-$(CONFIG_PL353_SMC)		+= pl353-smc.o
 obj-$(CONFIG_RENESAS_RPCIF)	+= renesas-rpc-if.o
 obj-$(CONFIG_STM32_FMC2_EBI)	+= stm32-fmc2-ebi.o
+obj-$(CONFIG_STM32_OMM)		+= stm32_omm.o
 
 obj-$(CONFIG_SAMSUNG_MC)	+= samsung/
 obj-$(CONFIG_TEGRA_MC)		+= tegra/
diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a7029e2cb6d770b25339d79e5714f376acefeef
--- /dev/null
+++ b/drivers/memory/stm32_omm.c
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
+ * Author(s): Patrice Chotard <patrice.chotard at foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bus/stm32_firewall_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define OMM_CR			0
+#define CR_MUXEN		BIT(0)
+#define CR_MUXENMODE_MASK	GENMASK(1, 0)
+#define CR_CSSEL_OVR_EN		BIT(4)
+#define CR_CSSEL_OVR_MASK	GENMASK(6, 5)
+#define CR_REQ2ACK_MASK		GENMASK(23, 16)
+
+#define OMM_CHILD_NB		2
+#define OMM_CLK_NB		3
+
+struct stm32_omm {
+	struct resource *mm_res;
+	struct clk_bulk_data clk_bulk[OMM_CLK_NB];
+	void __iomem *io_base;
+	u32 cr;
+	u8 nb_child;
+	bool restore_omm;
+};
+
+static int stm32_omm_set_amcr(struct device *dev, bool set)
+{
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+	resource_size_t mm_ospi2_size = 0;
+	static const char * const mm_name[] = { "ospi1", "ospi2" };
+	struct regmap *syscfg_regmap;
+	struct device_node *node;
+	struct resource res, res1;
+	u32 amcr_base, amcr_mask;
+	int ret, idx;
+	unsigned int i, amcr, read_amcr;
+
+	for (i = 0; i < omm->nb_child; i++) {
+		idx = of_property_match_string(dev->of_node,
+					       "memory-region-names",
+					       mm_name[i]);
+		if (idx < 0)
+			continue;
+
+		/* res1 only used on second loop iteration */
+		res1.start = res.start;
+		res1.end = res.end;
+
+		node = of_parse_phandle(dev->of_node, "memory-region", idx);
+		if (!node)
+			continue;
+
+		ret = of_address_to_resource(node, 0, &res);
+		if (ret) {
+			dev_err(dev, "unable to resolve memory region\n");
+			return ret;
+		}
+
+		/* check that memory region fits inside OMM memory map area */
+		if (!resource_contains(omm->mm_res, &res)) {
+			dev_err(dev, "%s doesn't fit inside OMM memory map area\n",
+				mm_name[i]);
+			dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res);
+
+			return -EFAULT;
+		}
+
+		if (i == 1) {
+			mm_ospi2_size = resource_size(&res);
+
+			/* check that OMM memory region 1 doesn't overlap memory region 2 */
+			if (resource_overlaps(&res, &res1)) {
+				dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
+					mm_name[0], mm_name[1]);
+				dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
+
+				return -EFAULT;
+			}
+		}
+	}
+
+	syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
+	if (IS_ERR(syscfg_regmap))
+		return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
+				     "Failed to get st,syscfg-amcr property\n");
+
+	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
+					 &amcr_base);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
+					 &amcr_mask);
+	if (ret)
+		return ret;
+
+	amcr = mm_ospi2_size / SZ_64M;
+
+	if (set)
+		regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
+
+	/* read AMCR and check coherency with memory-map areas defined in DT */
+	regmap_read(syscfg_regmap, amcr_base, &read_amcr);
+	read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
+
+	if (amcr != read_amcr) {
+		dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int stm32_omm_toggle_child_clock(struct device *dev, bool enable)
+{
+	/* As there is only 2 children, remember first child in case of error */
+	struct clk *first_child_clk = NULL;
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+	u8 i;
+	int ret;
+
+	for (i = 0; i < omm->nb_child; i++) {
+		if (enable) {
+			ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk);
+			if (ret) {
+				if (first_child_clk)
+					clk_disable_unprepare(first_child_clk);
+
+				dev_err(dev, "Can not enable clock\n");
+				return ret;
+			}
+		} else {
+			clk_disable_unprepare(omm->clk_bulk[i + 1].clk);
+		}
+
+		first_child_clk = omm->clk_bulk[i + 1].clk;
+	}
+
+	return 0;
+}
+
+static int stm32_omm_disable_child(struct device *dev)
+{
+	static const char * const resets_name[] = {"ospi1", "ospi2"};
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+	struct reset_control *reset;
+	int ret;
+	u8 i;
+
+	ret = stm32_omm_toggle_child_clock(dev, true);
+	if (!ret)
+		return ret;
+
+	for (i = 0; i < omm->nb_child; i++) {
+		reset = reset_control_get_exclusive(dev, resets_name[i]);
+		if (IS_ERR(reset)) {
+			dev_err(dev, "Can't get %s reset\n", resets_name[i]);
+			return PTR_ERR(reset);
+		};
+
+		/* reset OSPI to ensure CR_EN bit is set to 0 */
+		reset_control_assert(reset);
+		udelay(2);
+		reset_control_deassert(reset);
+
+		reset_control_put(reset);
+	}
+
+	return stm32_omm_toggle_child_clock(dev, false);
+}
+
+static int stm32_omm_configure(struct device *dev)
+{
+	static const char * const clocks_name[] = {"omm", "ospi1", "ospi2"};
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+	unsigned long clk_rate_max = 0;
+	u32 mux = 0;
+	u32 cssel_ovr = 0;
+	u32 req2ack = 0;
+	struct reset_control *rstc;
+	unsigned long clk_rate;
+	int ret;
+	u8 i;
+
+	for (i = 0; i < OMM_CLK_NB; i++)
+		omm->clk_bulk[i].id = clocks_name[i];
+
+	/* retrieve OMM, OSPI1 and OSPI2 clocks */
+	ret = devm_clk_bulk_get(dev, OMM_CLK_NB, omm->clk_bulk);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get OMM/OSPI's clocks\n");
+
+	/* Ensure both OSPI instance are disabled before configuring OMM */
+	ret = stm32_omm_disable_child(dev);
+	if (ret)
+		return ret;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0)
+		return ret;
+
+	/* parse children's clock */
+	for (i = 1; i <= omm->nb_child; i++) {
+		clk_rate = clk_get_rate(omm->clk_bulk[i].clk);
+		if (!clk_rate) {
+			dev_err(dev, "Invalid clock rate\n");
+			goto err_clk_disable;
+		}
+
+		if (clk_rate > clk_rate_max)
+			clk_rate_max = clk_rate;
+	}
+
+	rstc = devm_reset_control_get_exclusive(dev, "omm");
+	if (IS_ERR(rstc))
+		return dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
+
+	reset_control_assert(rstc);
+	udelay(2);
+	reset_control_deassert(rstc);
+
+	omm->cr = readl_relaxed(omm->io_base + OMM_CR);
+	/* optional */
+	ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
+	if (!ret) {
+		if (mux & CR_MUXEN) {
+			ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
+						   &req2ack);
+			if (!ret && !req2ack) {
+				req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
+
+				if (req2ack > 256)
+					req2ack = 256;
+			}
+
+			req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
+
+			omm->cr &= ~CR_REQ2ACK_MASK;
+			omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
+
+			/*
+			 * If the mux is enabled, the 2 OSPI clocks have to be
+			 * always enabled
+			 */
+			ret = stm32_omm_toggle_child_clock(dev, true);
+			if (ret)
+				goto err_clk_disable;
+		}
+
+		omm->cr &= ~CR_MUXENMODE_MASK;
+		omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
+	}
+
+	/* optional */
+	ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
+	if (!ret) {
+		omm->cr &= ~CR_CSSEL_OVR_MASK;
+		omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
+		omm->cr |= CR_CSSEL_OVR_EN;
+	}
+
+	omm->restore_omm = true;
+	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
+
+	ret = stm32_omm_set_amcr(dev, true);
+
+err_clk_disable:
+	pm_runtime_put_sync_suspend(dev);
+
+	return ret;
+}
+
+static int stm32_omm_check_access(struct device_node *np)
+{
+	struct stm32_firewall firewall;
+	int ret;
+
+	ret = stm32_firewall_get_firewall(np, &firewall, 1);
+	if (ret)
+		return ret;
+
+	return stm32_firewall_grant_access(&firewall);
+}
+
+static int stm32_omm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	u8 child_access_granted = 0;
+	struct stm32_omm *omm;
+	int ret;
+
+	omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
+	if (!omm)
+		return -ENOMEM;
+
+	omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
+	if (IS_ERR(omm->io_base))
+		return PTR_ERR(omm->io_base);
+
+	omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
+	if (IS_ERR(omm->mm_res))
+		return PTR_ERR(omm->mm_res);
+
+	/* check child's access */
+	for_each_child_of_node_scoped(dev->of_node, child) {
+		if (omm->nb_child >= OMM_CHILD_NB) {
+			dev_err(dev, "Bad DT, found too much children\n");
+			return -E2BIG;
+		}
+
+		if (!of_device_is_compatible(child, "st,stm32mp25-omi"))
+			return -EINVAL;
+
+		ret = stm32_omm_check_access(child);
+		if (ret < 0 && ret != -EACCES)
+			return ret;
+
+		if (!ret)
+			child_access_granted++;
+
+		omm->nb_child++;
+	}
+
+	if (omm->nb_child != OMM_CHILD_NB)
+		return -EINVAL;
+
+	platform_set_drvdata(pdev, omm);
+
+	pm_runtime_enable(dev);
+
+	/* check if OMM's resource access is granted */
+	ret = stm32_omm_check_access(dev->of_node);
+	if (ret < 0 && ret != -EACCES)
+		goto error;
+
+	if (!ret && child_access_granted == OMM_CHILD_NB) {
+		ret = stm32_omm_configure(dev);
+		if (ret)
+			goto error;
+	} else {
+		dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
+		/*
+		 * AMCR can't be set, so check if current value is coherent
+		 * with memory-map areas defined in DT
+		 */
+		ret = stm32_omm_set_amcr(dev, false);
+		if (ret)
+			goto error;
+	}
+
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret) {
+		dev_err(dev, "Failed to create Octo Memory Manager child\n");
+		of_platform_depopulate(dev);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	return ret;
+
+error:
+	pm_runtime_disable(dev);
+
+	return ret;
+
+}
+
+static void stm32_omm_remove(struct platform_device *pdev)
+{
+	struct stm32_omm *omm = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(&pdev->dev);
+	if (omm->cr & CR_MUXEN)
+		stm32_omm_toggle_child_clock(&pdev->dev, false);
+
+	pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id stm32_omm_of_match[] = {
+	{ .compatible = "st,stm32mp25-omm", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
+
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
+{
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(omm->clk_bulk[0].clk);
+
+	return 0;
+}
+
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
+{
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(omm->clk_bulk[0].clk);
+}
+
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
+{
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+
+	if (omm->restore_omm && omm->cr & CR_MUXEN)
+		stm32_omm_toggle_child_clock(dev, false);
+
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int __maybe_unused stm32_omm_resume(struct device *dev)
+{
+	struct stm32_omm *omm = dev_get_drvdata(dev);
+	int ret;
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (!omm->restore_omm)
+		return 0;
+
+	/* Ensure both OSPI instance are disabled before configuring OMM */
+	ret = stm32_omm_disable_child(dev);
+	if (ret)
+		return ret;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0)
+		return ret;
+
+	writel_relaxed(omm->cr, omm->io_base + OMM_CR);
+	ret = stm32_omm_set_amcr(dev, true);
+	pm_runtime_put_sync_suspend(dev);
+	if (ret)
+		return ret;
+
+	if (omm->cr & CR_MUXEN)
+		ret = stm32_omm_toggle_child_clock(dev, true);
+
+	return ret;
+}
+
+static const struct dev_pm_ops stm32_omm_pm_ops = {
+	SET_RUNTIME_PM_OPS(stm32_omm_runtime_suspend,
+			   stm32_omm_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(stm32_omm_suspend, stm32_omm_resume)
+};
+
+static struct platform_driver stm32_omm_driver = {
+	.probe	= stm32_omm_probe,
+	.remove = stm32_omm_remove,
+	.driver	= {
+		.name = "stm32-omm",
+		.of_match_table = stm32_omm_of_match,
+		.pm = &stm32_omm_pm_ops,
+	},
+};
+module_platform_driver(stm32_omm_driver);
+
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
+MODULE_LICENSE("GPL");

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:22 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:22 +0100
Subject: [PATCH v6 2/7] dt-bindings: memory-controllers: Add STM32 Octo
 Memory Manager controller
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-2-37bbcab43439@foss.st.com>

Add bindings for STM32 Octo Memory Manager (OMM) controller.

OMM manages:
  - the muxing between 2 OSPI busses and 2 output ports.
    There are 4 possible muxing configurations:
      - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
        output is on port 2
      - OSPI1 and OSPI2 are multiplexed over the same output port 1
      - swapped mode (no multiplexing), OSPI1 output is on port 2,
        OSPI2 output is on port 1
      - OSPI1 and OSPI2 are multiplexed over the same output port 2
  - the split of the memory area shared between the 2 OSPI instances.
  - chip select selection override.
  - the time between 2 transactions in multiplexed mode.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 .../memory-controllers/st,stm32mp25-omm.yaml       | 227 +++++++++++++++++++++
 1 file changed, 227 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2f8fa7569009369ebd077e4c6f4ab409a91838a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
@@ -0,0 +1,227 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/st,stm32mp25-omm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STM32 Octo Memory Manager (OMM)
+
+maintainers:
+  - Patrice Chotard <patrice.chotard at foss.st.com>
+
+description: |
+  The STM32 Octo Memory Manager is a low-level interface that enables an
+  efficient OCTOSPI pin assignment with a full I/O matrix (before alternate
+  function map) and multiplex of single/dual/quad/octal SPI interfaces over
+  the same bus. It Supports up to:
+    - Two single/dual/quad/octal SPI interfaces
+    - Two ports for pin assignment
+
+properties:
+  compatible:
+    const: st,stm32mp25-omm
+
+  "#address-cells":
+    const: 2
+
+  "#size-cells":
+    const: 1
+
+  ranges:
+    description: |
+      Reflects the memory layout with four integer values per OSPI instance.
+      Format:
+      <chip-select> 0 <registers base address> <size>
+    minItems: 2
+    maxItems: 2
+
+  reg:
+    items:
+      - description: OMM registers
+      - description: OMM memory map area
+
+  reg-names:
+    items:
+      - const: regs
+      - const: memory_map
+
+  memory-region:
+    description: |
+      Memory region shared between the 2 OCTOSPI instance.
+      One or two phandle to a node describing a memory mapped region
+      depending of child number.
+    minItems: 1
+    maxItems: 2
+
+  memory-region-names:
+    description: |
+      OCTOSPI instance's name to which memory region is associated
+    items:
+      enum: [ospi1, ospi2]
+    minItems: 1
+    maxItems: 2
+
+  clocks:
+    minItems: 3
+    maxItems: 3
+
+  clock-names:
+    items:
+      enum: [omm, ospi1, ospi2]
+    minItems: 3
+    maxItems: 3
+
+  resets:
+    minItems: 3
+    maxItems: 3
+
+  reset-names:
+    items:
+      enum: [omm, ospi1, ospi2]
+    minItems: 3
+    maxItems: 3
+
+  access-controllers:
+    maxItems: 1
+
+  st,syscfg-amcr:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: |
+      The Address Mapping Control Register (AMCR) is used to split the 256MB
+      memory map area shared between the 2 OSPI instance. The Octo Memory
+      Manager sets the AMCR depending of the memory-region configuration.
+      The memory split bitmask description is:
+        - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped
+        - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes)
+        - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes)
+        - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes)
+        - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes)
+    items:
+      - description: phandle to syscfg
+      - description: register offset within syscfg
+      - description: register bitmask for memory split
+
+  st,omm-req2ack-ns:
+    description: |
+      In multiplexed mode (MUXEN = 1), this field defines the time in
+      nanoseconds between two transactions.
+    default: 0
+
+  st,omm-cssel-ovr:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Configure the chip select selector override for the 2 OCTOSPIs.
+      - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
+      - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
+      - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
+      - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
+    minimum: 0
+    maximum: 3
+    default: 0
+
+  st,omm-mux:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports.
+      - 0: direct mode
+      - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
+      - 2: swapped mode
+      - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
+    minimum: 0
+    maximum: 3
+    default: 0
+
+  power-domains:
+    maxItems: 1
+
+patternProperties:
+  ^spi@[a-f0-9]+$:
+    type: object
+    $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
+    description: Required spi child node
+
+required:
+  - compatible
+  - reg
+  - "#address-cells"
+  - "#size-cells"
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - st,syscfg-amcr
+  - ranges
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/st,stm32mp25-rcc.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/reset/st,stm32mp25-rcc.h>
+    ommanager at 40500000 {
+      compatible = "st,stm32mp25-omm";
+      reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
+      reg-names = "regs", "memory_map";
+      ranges = <0 0 0x40430000 0x400>,
+               <1 0 0x40440000 0x400>;
+      memory-region = <&mm_ospi1>, <&mm_ospi2>;
+      memory-region-names = "ospi1", "ospi2";
+      pinctrl-0 = <&ospi_port1_clk_pins_a
+                   &ospi_port1_io03_pins_a
+                   &ospi_port1_cs0_pins_a>;
+      pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
+                   &ospi_port1_io03_sleep_pins_a
+                   &ospi_port1_cs0_sleep_pins_a>;
+      pinctrl-names = "default", "sleep";
+      clocks = <&rcc CK_BUS_OSPIIOM>,
+               <&scmi_clk CK_SCMI_OSPI1>,
+               <&scmi_clk CK_SCMI_OSPI2>;
+      clock-names = "omm", "ospi1", "ospi2";
+      resets = <&rcc OSPIIOM_R>,
+               <&scmi_reset RST_SCMI_OSPI1>,
+               <&scmi_reset RST_SCMI_OSPI2>;
+      reset-names = "omm", "ospi1", "ospi2";
+      access-controllers = <&rifsc 111>;
+      power-domains = <&CLUSTER_PD>;
+      #address-cells = <2>;
+      #size-cells = <1>;
+      st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
+      st,omm-req2ack-ns = <0>;
+      st,omm-mux = <0>;
+      st,omm-cssel-ovr = <0>;
+
+      spi at 40430000 {
+        compatible = "st,stm32mp25-ospi";
+        reg = <0 0 0x400>;
+        memory-region = <&mm_ospi1>;
+        interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+        dmas = <&hpdma 2 0x62 0x00003121 0x0>,
+               <&hpdma 2 0x42 0x00003112 0x0>;
+        dma-names = "tx", "rx";
+        clocks = <&scmi_clk CK_SCMI_OSPI1>;
+        resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
+        access-controllers = <&rifsc 74>;
+        power-domains = <&CLUSTER_PD>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        st,syscfg-dlyb = <&syscfg 0x1000>;
+      };
+
+      spi at 40440000 {
+        compatible = "st,stm32mp25-ospi";
+        reg = <1 0 0x400>;
+        memory-region = <&mm_ospi1>;
+        interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+        dmas = <&hpdma 3 0x62 0x00003121 0x0>,
+               <&hpdma 3 0x42 0x00003112 0x0>;
+        dma-names = "tx", "rx";
+        clocks = <&scmi_clk CK_KER_OSPI2>;
+        resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>;
+        access-controllers = <&rifsc 75>;
+        power-domains = <&CLUSTER_PD>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        st,syscfg-dlyb = <&syscfg 0x1000>;
+      };
+    };

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:27 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:27 +0100
Subject: [PATCH v6 7/7] arm64: defconfig: Enable STM32 Octo Memory Manager
 and OcstoSPI driver
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-7-37bbcab43439@foss.st.com>

Enable STM32 OctoSPI driver.
Enable STM32 Octo Memory Manager (OMM) driver which is needed
for OSPI usage on STM32MP257F-EV1 board.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index bde1287ad9a7a1341162b817873eb651bb310d52..3674d9138bae6deba19c0d13586aa6e1de6750c5 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -580,6 +580,7 @@ CONFIG_SPI_QUP=y
 CONFIG_SPI_QCOM_GENI=m
 CONFIG_SPI_S3C64XX=y
 CONFIG_SPI_SH_MSIOF=m
+CONFIG_SPI_STM32_OSPI=m
 CONFIG_SPI_SUN6I=y
 CONFIG_SPI_TEGRA210_QUAD=m
 CONFIG_SPI_TEGRA114=m
@@ -1518,6 +1519,7 @@ CONFIG_EXTCON_USB_GPIO=y
 CONFIG_EXTCON_USBC_CROS_EC=y
 CONFIG_FSL_IFC=y
 CONFIG_RENESAS_RPCIF=m
+CONFIG_STM32_OMM=m
 CONFIG_IIO=y
 CONFIG_EXYNOS_ADC=y
 CONFIG_IMX8QXP_ADC=m

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:25 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:25 +0100
Subject: [PATCH v6 5/7] arm64: dts: st: Add ospi port1 pinctrl entries in
 stm32mp25-pinctrl.dtsi
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-5-37bbcab43439@foss.st.com>

Add pinctrl entry related to OSPI's port1 in stm32mp25-pinctrl.dtsi

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
index 8fdd5f020425d53eefa724de9c23ec0ca211ab7f..cf5be316de2613e7d7050374c9a57fd95020d715 100644
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
@@ -101,6 +101,57 @@ pins2 {
 		};
 	};
 
+	ospi_port1_clk_pins_a: ospi-port1-clk-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 0, AF10)>; /* OSPI1_CLK */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <2>;
+		};
+	};
+
+	ospi_port1_clk_sleep_pins_a: ospi-port1-clk-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 0, ANALOG)>; /* OSPI1_CLK */
+		};
+	};
+
+	ospi_port1_cs0_pins_a: ospi-port1-cs0-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 3, AF10)>; /* OSPI_NCS0 */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	ospi_port1_cs0_sleep_pins_a: ospi-port1-cs0-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 3, ANALOG)>; /* OSPI_NCS0 */
+		};
+	};
+
+	ospi_port1_io03_pins_a: ospi-port1-io03-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 4, AF10)>, /* OSPI_IO0 */
+				 <STM32_PINMUX('D', 5, AF10)>, /* OSPI_IO1 */
+				 <STM32_PINMUX('D', 6, AF10)>, /* OSPI_IO2 */
+				 <STM32_PINMUX('D', 7, AF10)>; /* OSPI_IO3 */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	ospi_port1_io03_sleep_pins_a: ospi-port1-io03-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* OSPI_IO0 */
+				 <STM32_PINMUX('D', 5, ANALOG)>, /* OSPI_IO1 */
+				 <STM32_PINMUX('D', 6, ANALOG)>, /* OSPI_IO2 */
+				 <STM32_PINMUX('D', 7, ANALOG)>; /* OSPI_IO3 */
+		};
+	};
+
 	sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:20 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:20 +0100
Subject: [PATCH v6 0/7] Add STM32MP25 SPI NOR support
Message-ID: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>

This series adds SPI NOR support for STM32MP25 SoCs from STMicroelectronics.

On STM32MP25 SoCs family, an Octo Memory Manager block manages the muxing,
the memory area split, the chip select override and the time constraint
between its 2 Octo SPI children.

Due to these depedencies, this series adds support for:
  - Octo Memory Manager driver.
  - Octo SPI driver.
  - yaml schema for Octo Memory Manager and Octo SPI drivers.

The device tree files adds Octo Memory Manager and its 2 associated Octo
SPI chidren in stm32mp251.dtsi and adds SPI NOR support in stm32mp257f-ev1
board.
    
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>

Changes in v6:
  - Update MAINTAINERS file.
  - Remove previous patch 1/8 and 2/8, merged by Mark Brown in spi git tree.
  - Fix Signed-off-by order for patch 3.
  - OMM driver:
    - Add dev_err_probe() in error path.
    - Rename stm32_omm_enable_child_clock() to stm32_omm_toggle_child_clock().
    - Reorder initialised/non-initialized variable in stm32_omm_configure()
          and stm32_omm_probe().
    - Move pm_runtime_disable() calls from stm32_omm_configure() to
      stm32_omm_probe().
    - Update children's clocks and reset management.
    - Use of_platform_populate() to probe children.
    - Add missing pm_runtime_disable().
    - Remove useless stm32_omm_check_access's first parameter.
  - Update OMM's dt-bindings by adding OSPI's clocks and resets.
  - Update stm32mp251.dtsi by adding OSPI's clock and reset in OMM's node.

Changes in v5:
  - Add Reviewed-by Krzysztof Kozlowski for patch 1 and 3.

Changes in v4:
  - Add default value requested by Krzysztof for st,omm-req2ack-ns,
    st,omm-cssel-ovr and st,omm-mux properties in st,stm32mp25-omm.yaml
  - Remove constraint in free form test for st,omm-mux property.
  - Fix drivers/memory/Kconfig by replacing TEST_COMPILE_ by COMPILE_TEST.
  - Fix SPDX-License-Identifier for stm32-omm.c.
  - Fix Kernel test robot by fixing dev_err() format in stm32-omm.c.
  - Add missing pm_runtime_disable() in the error handling path in
    stm32-omm.c.
  - Replace an int by an unsigned int in stm32-omm.c
  - Remove uneeded "," after terminator in stm32-omm.c.
  - Update cover letter description to explain dependecies between
Octo Memory Manager and its 2 Octo SPI children.

Changes in v3:
  - Squash defconfig patches 8 and 9.
  - Update STM32 Octo Memory Manager controller bindings.
  - Rename st,stm32-omm.yaml to st,stm32mp25-omm.yaml.
  - Update STM32 OSPI controller bindings.
  - Reorder DT properties in .dtsi and .dts files.
  - Replace devm_reset_control_get_optional() by
    devm_reset_control_get_optional_exclusive() in stm32_omm.c.
  - Reintroduce region-memory-names management in stm32_omm.c.
  - Rename stm32_ospi_tx_poll() and stm32_ospi_tx() to respectively to
    stm32_ospi_poll() and stm32_ospi_xfer() in spi-stm32-ospi.c.
  - Set SPI_CONTROLLER_HALF_DUPLEX in controller flags in spi-stm32-ospi.c.

Changes in v2:
  - Move STM32 Octo Memory Manager controller driver and bindings from
    misc to memory-controllers.
  - Update STM32 OSPI controller bindings.
  - Update STM32 Octo Memory Manager controller bindings.
  - Update STM32 Octo Memory Manager driver to match bindings update.
  - Update DT to match bindings update.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
Patrice Chotard (7):
      MAINTAINERS: add entry for STM32 OCTO MEMORY MANAGER driver
      dt-bindings: memory-controllers: Add STM32 Octo Memory Manager controller
      memory: Add STM32 Octo Memory Manager driver
      arm64: dts: st: Add OMM node on stm32mp251
      arm64: dts: st: Add ospi port1 pinctrl entries in stm32mp25-pinctrl.dtsi
      arm64: dts: st: Add SPI NOR flash support on stm32mp257f-ev1 board
      arm64: defconfig: Enable STM32 Octo Memory Manager and OcstoSPI driver

 .../memory-controllers/st,stm32mp25-omm.yaml       | 227 ++++++++++
 MAINTAINERS                                        |   6 +
 arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi      |  51 +++
 arch/arm64/boot/dts/st/stm32mp251.dtsi             |  54 +++
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts         |  32 ++
 arch/arm64/configs/defconfig                       |   2 +
 drivers/memory/Kconfig                             |  17 +
 drivers/memory/Makefile                            |   1 +
 drivers/memory/stm32_omm.c                         | 474 +++++++++++++++++++++
 9 files changed, 864 insertions(+)
---
base-commit: 88424abd55ab36c3565898a656589a0a25ecd92f
change-id: 20250320-upstream_ospi_v6-d432a8172105

Best regards,
-- 
Patrice Chotard <patrice.chotard at foss.st.com>



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:26 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:26 +0100
Subject: [PATCH v6 6/7] arm64: dts: st: Add SPI NOR flash support on
 stm32mp257f-ev1 board
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-6-37bbcab43439@foss.st.com>

Add SPI NOR flash nor support on stm32mp257f-ev1 board.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 ++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1f837770654eee6c970208fef6edc..76970c15e04387383097874a814f42e867fc94b6 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -80,6 +80,11 @@ fw at 80000000 {
 			reg = <0x0 0x80000000 0x0 0x4000000>;
 			no-map;
 		};
+
+		mm_ospi1: mm-ospi at 60000000 {
+			reg = <0x0 0x60000000 0x0 0x10000000>;
+			no-map;
+		};
 	};
 };
 
@@ -190,6 +195,33 @@ &i2c8 {
 	status = "disabled";
 };
 
+&ommanager {
+	memory-region = <&mm_ospi1>;
+	pinctrl-0 = <&ospi_port1_clk_pins_a
+		     &ospi_port1_io03_pins_a
+		     &ospi_port1_cs0_pins_a>;
+	pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
+		     &ospi_port1_io03_sleep_pins_a
+		     &ospi_port1_cs0_sleep_pins_a>;
+	pinctrl-names = "default", "sleep";
+	status = "okay";
+
+	spi at 40430000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		memory-region = <&mm_ospi1>;
+		status = "okay";
+
+		flash0: flash at 0 {
+			compatible = "jedec,spi-nor";
+			reg = <0>;
+			spi-rx-bus-width = <4>;
+			spi-tx-bus-width = <4>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:32:24 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:32:24 +0100
Subject: [PATCH v6 4/7] arm64: dts: st: Add OMM node on stm32mp251
In-Reply-To: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
Message-ID: <20250321-upstream_ospi_v6-v6-4-37bbcab43439@foss.st.com>

Add Octo Memory Manager (OMM) entry on stm32mp251 and its two
OSPI instance.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 54 ++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008c5b736ba75f5210d0eddb5b43489..d1f30c76b41d68f5d7da7998b0edbceb93ce4a12 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -768,6 +768,60 @@ rng: rng at 42020000 {
 				status = "disabled";
 			};
 
+			ommanager: ommanager at 40500000 {
+				compatible = "st,stm32mp25-omm";
+				reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
+				reg-names = "regs", "memory_map";
+				ranges = <0 0 0x40430000 0x400>,
+					 <1 0 0x40440000 0x400>;
+				clocks = <&rcc CK_BUS_OSPIIOM>,
+					 <&scmi_clk CK_SCMI_OSPI1>,
+					 <&scmi_clk CK_SCMI_OSPI2>;
+				clock-names = "omm", "ospi1", "ospi2";
+				resets = <&rcc OSPIIOM_R>,
+					 <&scmi_reset RST_SCMI_OSPI1>,
+					 <&scmi_reset RST_SCMI_OSPI2>;
+				reset-names = "omm", "ospi1", "ospi2";
+				access-controllers = <&rifsc 111>;
+				power-domains = <&CLUSTER_PD>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
+				status = "disabled";
+
+				ospi1: spi at 40430000 {
+					compatible = "st,stm32mp25-ospi";
+					reg = <0 0 0x400>;
+					interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&hpdma 2 0x62 0x00003121>,
+					       <&hpdma 2 0x42 0x00003112>;
+					dma-names = "tx", "rx";
+					clocks = <&scmi_clk CK_SCMI_OSPI1>;
+					resets = <&scmi_reset RST_SCMI_OSPI1>,
+						 <&scmi_reset RST_SCMI_OSPI1DLL>;
+					access-controllers = <&rifsc 74>;
+					power-domains = <&CLUSTER_PD>;
+					st,syscfg-dlyb = <&syscfg 0x1000>;
+					status = "disabled";
+				};
+
+				ospi2: spi at 40440000 {
+					compatible = "st,stm32mp25-ospi";
+					reg = <1 0 0x400>;
+					interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&hpdma 3 0x62 0x00003121>,
+					       <&hpdma 3 0x42 0x00003112>;
+					dma-names = "tx", "rx";
+					clocks = <&scmi_clk CK_SCMI_OSPI2>;
+					resets = <&scmi_reset RST_SCMI_OSPI2>,
+						 <&scmi_reset RST_SCMI_OSPI2DLL>;
+					access-controllers = <&rifsc 75>;
+					power-domains = <&CLUSTER_PD>;
+					st,syscfg-dlyb = <&syscfg 0x1400>;
+					status = "disabled";
+				};
+			};
+
 			spi8: spi at 46020000 {
 				#address-cells = <1>;
 				#size-cells = <0>;

-- 
2.25.1



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:29 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:29 +0800
Subject: [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196
Message-ID: <20250321093435.94835-1-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

This patch series adds support for the MediaTek MT8196 SoC's display
subsystem in the DRM driver.

Changes in v2:
- add support for MT8196's new hardware components (EXDMA, BLENDER, 
  OUTPROC) following the previous MTK OVL software architecture.
- reuse mtk_ovl drivers in MediaTek DRM display to support the new 
  MT8196 SoC.
- implement support for multiple mmsys instances within a single 
  mediatek-drm driver, improving flexibility and scalability.
- refactor existing components (mutex, OVL) to accommodate the new 
  architecture and improve code reusability.
- update component matching, binding logic, and data structures to 
  support the new multi-mmsys design.

Nancy Lin (10):
  soc: mediatek: add mmsys support for MT8196
  soc: mediatek: mutex: refactor SOF settings for output components
  soc: mediatek: mutex: add mutex support for MT8196
  drm/mediatek: Refine OVL format convert API and export to public
  drm/mediatek: add EXDMA support for MT8196
  drm/mediatek: add BLENDER support for MT8196
  drm/mediatek: add OUTPROC support for MT8196
  drm/mediatek: add ovlsys_adaptor support for MT8196
  drm/mediatek: Add support for multiple mmsys in the one mediatek-drm
    driver
  drm/mediatek: Add support for MT8196 multiple mmsys

Paul-pl Chen (5):
  dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
  dt-bindings: soc: mediatek: add mutex yaml for MT8196
  dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  dt-bindings: display: mediatek: add BLENDER yaml for MT8196
  dt-bindings: display: mediatek: add OUTPROC yaml for MT8196

 .../bindings/arm/mediatek/mediatek,mmsys.yaml |   5 +
 .../display/mediatek/mediatek,blender.yaml    |  48 ++
 .../display/mediatek/mediatek,outproc.yaml    |  54 ++
 .../bindings/dma/mediatek,exdma.yaml          |  70 ++
 .../bindings/soc/mediatek/mediatek,mutex.yaml |   2 +
 drivers/gpu/drm/mediatek/Makefile             |   4 +
 drivers/gpu/drm/mediatek/mtk_crtc.c           | 342 ++++++--
 drivers/gpu/drm/mediatek/mtk_crtc.h           |   6 +-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       | 133 +--
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   6 +
 drivers/gpu/drm/mediatek/mtk_disp_blender.c   | 276 ++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h   |  18 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  67 ++
 drivers/gpu/drm/mediatek/mtk_disp_exdma.c     | 372 ++++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.c   | 242 ++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.h   |  22 +
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c       | 158 ++--
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h       |  16 +
 .../drm/mediatek/mtk_disp_ovlsys_adaptor.c    | 797 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        | 281 +++++-
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |  28 +-
 drivers/soc/mediatek/mt8196-mmsys.h           | 451 ++++++++++
 drivers/soc/mediatek/mtk-mmsys.c              | 203 ++++-
 drivers/soc/mediatek/mtk-mmsys.h              |  18 +
 drivers/soc/mediatek/mtk-mutex.c              | 257 +++++-
 include/linux/soc/mediatek/mtk-mmsys.h        |  60 ++
 include/linux/soc/mediatek/mtk-mutex.h        |   4 +
 27 files changed, 3675 insertions(+), 265 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
 create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
 create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h

-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:30 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:30 +0800
Subject: [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-2-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

In previous SoCs, a single HW pipeline was an independent mmsys,
which included the OVL module, PQ module, and display interface
module.

In the 8196, to increase the flexibility of pipeline connection
and control, the OVL module on a single HW pipeline was separated
into two mmsys, namely ovlsys0 and ovlsys1. The PQ module was also
separated into a dispsys0, and the display interface module was
separated into a dispsys1. Additionally, display power-related
settings are controlled through vdiso-ao.

For example:
The primary path and external path of the display both use
ovlsys0 -> dispsys0 -> dispsys1, forming a pipeline.

The third path of the display uses ovlsys1 -> dispsys0 -> dispsys1,
forming another pipeline.

Therefore, the 8196 needs to add 5 compatible string to support
mmsys for MT8196.

Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 .../devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml     | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
index 3f4262e93c78..5f244a8f6a47 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -39,6 +39,11 @@ properties:
               - mediatek,mt8195-vdosys1
               - mediatek,mt8195-vppsys0
               - mediatek,mt8195-vppsys1
+              - mediatek,mt8196-dispsys0
+              - mediatek,mt8196-dispsys1
+              - mediatek,mt8196-ovlsys0
+              - mediatek,mt8196-ovlsys1
+              - mediatek,mt8196-vdisp-ao
               - mediatek,mt8365-mmsys
           - const: syscon
 
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:31 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:31 +0800
Subject: [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-3-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

Add compatible string to support mutex for MT8196.

Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/mediatek,mutex.yaml        | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
index a10326a9683d..1be4e139a8b5 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
@@ -36,6 +36,7 @@ properties:
       - mediatek,mt8188-vpp-mutex
       - mediatek,mt8192-disp-mutex
       - mediatek,mt8195-disp-mutex
+      - mediatek,mt8196-disp-mutex
       - mediatek,mt8195-vpp-mutex
       - mediatek,mt8365-disp-mutex
 
@@ -87,6 +88,7 @@ allOf:
               - mediatek,mt8186-mdp3-mutex
               - mediatek,mt8192-disp-mutex
               - mediatek,mt8195-disp-mutex
+              - mediatek,mt8196-disp-mutex
     then:
       required:
         - clocks
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:32 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:32 +0800
Subject: [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-4-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

Add mediatek,exdma.yaml to support EXDMA for MT8196.
The MediaTek display overlap extended DMA engine, namely
OVL_EXDMA or EXDMA, primarily functions as a DMA engine
for reading data from DRAM with various DRAM footprints
and data formats.

Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 .../bindings/dma/mediatek,exdma.yaml          | 70 +++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml

diff --git a/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
new file mode 100644
index 000000000000..de7f8283bb48
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/mediatek,exdma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek display overlap extended DMA engine
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu at kernel.org>
+  - Philipp Zabel <p.zabel at pengutronix.de>
+
+description:
+  The MediaTek display overlap extended DMA engine, namely OVL_EXDMA or EXDMA,
+  primarily functions as a DMA engine for reading data from DRAM with various
+  DRAM footprints and data formats. For input sources in certain color formats
+  and color domains, OVL_EXDMA also includes a color transfer function
+  to process pixels into a consistent color domain.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-exdma
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  mediatek,larb:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: |
+      A phandle to the local arbiters node in the current SoCs.
+      Refer to bindings/memory-controllers/mediatek,smi-larb.yaml.
+
+  iommus:
+    maxItems: 1
+
+  '#dma-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - mediatek,larb
+
+additionalProperties: false
+
+examples:
+  - |
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        disp_ovl0_exdma2: dma-controller at 32850000 {
+            compatible = "mediatek,mt8196-exdma";
+            reg = <0 0x32850000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 13>;
+            power-domains = <&hfrpsys 12>;
+            mediatek,larb = <&smi_larb0>;
+            iommus = <&mm_smmu 144>;
+            #dma-cells = <1>;
+        };
+    };
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:33 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:33 +0800
Subject: [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-5-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

Add mediatek,blender.yaml to support BLENDER for MT8196.
MediaTek display overlap blender, namely OVL_BLENDER or BLENDER,
executes the alpha blending function for overlapping layers
from different sources.

Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 .../display/mediatek/mediatek,blender.yaml    | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
new file mode 100644
index 000000000000..23e274a49228
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,blender.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Display Overlap Blender
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu at kernel.org>
+  - Philipp Zabel <p.zabel at pengutronix.de>
+
+description:
+  MediaTek display overlap blender, namely OVL_BLENDER or BLENDER,
+  executes the alpha blending function for overlapping layers
+  from different sources. This is the primary function of the
+  overlapping system.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-blender
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        disp_ovl0_blender0: blender at 328d0000 {
+            compatible = "mediatek,mt8196-blender";
+            reg = <0 0x328d0000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 29>;
+        };
+    };
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:34 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:34 +0800
Subject: [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-6-paul-pl.chen@mediatek.com>

From: Paul-pl Chen <paul-pl.chen at mediatek.com>

Add mediate,outproc.yaml to support OUTPROC for MT8196.
MediaTek display overlap output processor, namely OVL_OUTPROC
or OUTPROC,handles the post-stage of pixel processing in the
overlapping procedure.

Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 .../display/mediatek/mediatek,outproc.yaml    | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
new file mode 100644
index 000000000000..f42e9abc1436
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,outproc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek display overlap output processor
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu at kernel.org>
+  - Philipp Zabel <p.zabel at pengutronix.de>
+
+description: |
+  MediaTek display overlap output processor, namely OVL_OUTPROC or OUTPROC,
+  handles the post-stage of pixel processing in the overlapping procedure.
+  OVL_OUTPROC manages pixels for gamma correction and ensures that pixel
+  values are within the correct range.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-outproc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        disp_ovl0_outproc0: outproc at 32970000 {
+            compatible = "mediatek,mt8196-outproc";
+            reg = <0 0x32970000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 49>;
+            interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH 0>;
+        };
+    };
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:35 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:35 +0800
Subject: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-7-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

1. Defining driver data and adding compatible string
for different subsystems
(DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
2. Adding functions to control top clocks and ddp clocks.
3. Updating the probe function to initialize clocks and
enable runtime PM if its node has the power-domains property.
4. Adding functions to configure ddp components and
set default configurations.
5. Adding the routing table for each mmsys in MT8196.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/soc/mediatek/mt8196-mmsys.h    | 451 +++++++++++++++++++++++++
 drivers/soc/mediatek/mtk-mmsys.c       | 203 ++++++++++-
 drivers/soc/mediatek/mtk-mmsys.h       |  18 +
 include/linux/soc/mediatek/mtk-mmsys.h |  60 ++++
 4 files changed, 731 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h

diff --git a/drivers/soc/mediatek/mt8196-mmsys.h b/drivers/soc/mediatek/mt8196-mmsys.h
new file mode 100644
index 000000000000..ff841ae9939a
--- /dev/null
+++ b/drivers/soc/mediatek/mt8196-mmsys.h
@@ -0,0 +1,451 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Nancy Lin <nancy.lin at mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8196_MMSYS_H
+#define __SOC_MEDIATEK_MT8196_MMSYS_H
+
+/* DISPSYS1 */
+#define MT8196_COMP_OUT_CB6_MOUT_EN			0xd30
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0		BIT(0)
+#define MT8196_COMP_OUT_CB7_MOUT_EN			0xd38
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1		BIT(1)
+#define MT8196_COMP_OUT_CB8_MOUT_EN			0xd40
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2		BIT(2)
+#define MT8196_MERGE_OUT_CB0_MOUT_EN			0xdcc
+#define MT8196_DISP_COMP_OUT_CB_TO_DVO0				BIT(9)
+#define MT8196_MERGE_OUT_CB1_MOUT_EN			0xdd4
+#define MT8196_MERGE_OUT_CB2_MOUT_EN			0xddc
+#define MT8196_DISP_COMP_OUT_CB_TO_DSI0				BIT(0)
+#define MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0			BIT(10)
+#define MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1			BIT(11)
+#define MT8196_SPLITTER_IN_CB1_MOUT_EN			0xeac
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9		BIT(5)
+#define MT8196_SPLITTER_IN_CB2_MOUT_EN			0xeb4
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10		BIT(6)
+#define MT8196_SPLITTER_IN_CB3_MOUT_EN			0xebc
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11		BIT(7)
+#define MT8196_SPLITTER_OUT_CB9_MOUT_EN			0xf64
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6		BIT(10)
+#define MT8196_SPLITTER_OUT_CB10_MOUT_EN		0xf6c
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7		BIT(11)
+#define MT8196_SPLITTER_OUT_CB11_MOUT_EN		0xf74
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8		BIT(12)
+#define MT8196_OVL_RSZ_IN_CB2_MOUT_EN			0xf70
+#define MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3		BIT(1)
+
+/* OVLSYS */
+#define MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN		0xe10
+#define MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN		0xe20
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0		BIT(0)
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1		BIT(1)
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC2		BIT(2)
+#define MT8196_OVL_EXDMA_OUT_CB2_MOUT_EN		0xe60
+#define MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN		0xe68
+#define MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN		0xe70
+#define MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN		0xe78
+#define MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN		0xe80
+#define MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN		0xe88
+#define MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN		0xe90
+#define MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN		0xe98
+#define MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN		0xea0
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1		BIT(2)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2		BIT(3)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3		BIT(4)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4		BIT(5)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5		BIT(6)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6		BIT(7)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7		BIT(8)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8		BIT(9)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER9		BIT(10)
+#define MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN		0xf10
+#define MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN		0xf14
+#define MT8196_OVL_OUTPROC_OUT_CB2_MOUT_EN		0xf18
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5		BIT(0)
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6		BIT(1)
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY7		BIT(2)
+
+/* DISPSYS0 */
+#define MT8196_PANEL_COMP_OUT_CB1_MOUT_EN		0xd84
+#define MT8196_DISP_TO_DLO_RELAY1				BIT(1)
+#define MT8196_PANEL_COMP_OUT_CB2_MOUT_EN		0xd88
+#define MT8196_DISP_TO_DLO_RELAY2				BIT(2)
+#define MT8196_PANEL_COMP_OUT_CB3_MOUT_EN		0xd8c
+#define MT8196_DISP_TO_DLO_RELAY3				BIT(3)
+#define MT8196_PQ_IN_CB0_MOUT_EN			0xdd0
+#define MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6				BIT(2)
+
+#define MT8196_PQ_IN_CB1_MOUT_EN			0xdd4
+#define MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7				BIT(3)
+#define MT8196_PQ_IN_CB8_MOUT_EN			0xdf0
+#define MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8				BIT(4)
+#define MT8196_PQ_OUT_CB6_MOUT_EN			0xe54
+#define MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1		BIT(1)
+#define MT8196_PQ_OUT_CB7_MOUT_EN			0xe58
+#define MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2		BIT(2)
+#define MT8196_PQ_OUT_CB8_MOUT_EN			0xe5c
+#define MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3		BIT(3)
+
+/* OVLSYS config */
+#define MT8196_OVL_INT_MERGE				0x008
+#define MT8196_OVL_DL_OUT_RELAY5_SIZE			0x29c
+#define MT8196_OVL_DL_OUT_RELAY6_SIZE			0x2a0
+#define MT8196_OVLSYS_GCE_EVENT_SEL			0x408
+#define MT8196_OVLSYS_BYPASS_MUX_SHADOW			0xca0
+#define MT8196_OVLSYS_CB_CON				0xcac
+#define MT8196_CB_BYPASS_MUX_SHADOW				(0xff << 16)
+#define MT8196_EVENT_GCE_EN					(BIT(0) | BIT(1))
+
+/* DISPSYS config */
+#define MT8196_DISP0_DLI_RELAY0				0x200
+#define MT8196_DISP0_DLI_RELAY1				0x204
+#define MT8196_DISP0_DLI_RELAY8				0x220
+#define MT8196_DISP0_DLO_RELAY1				0x268
+#define MT8196_DISP0_DLO_RELAY2				0x26c
+#define MT8196_DISP0_DLO_RELAY3				0x270
+#define MT8196_DLI_RELAY_1T2P					BIT(30)
+#define MT8196_DISP0_BYPASS_MUX_SHADOW			0xc30
+#define MT8196_BYPASS_MUX_SHADOW				BIT(0)
+#define MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW			(0xff << 16)
+
+/* DISPSYS1 config */
+#define MT8196_DISP1_INT_MERGE				0x008
+#define MT8196_DISP1_DLI_RELAY21			0x204
+#define MT8196_DISP1_DLI_RELAY22			0x208
+#define MT8196_DISP1_DLI_RELAY23			0x20c
+#define MT8196_DISP1_GCE_FRAME_DONE_SEL0		0xa10
+#define MT8196_DISP1_GCE_FRAME_DONE_SEL1		0xa14
+#define MT8196_FRAME_DONE_DVO					25
+#define MT8196_FRAME_DONE_DP_INTF0				41
+#define MT8196_DISP1_BYPASS_MUX_SHADOW			0xcf8
+
+/* VDISP_AO config */
+#define MT8196_VDISP_AO_REG_INTEN			0x000
+#define MT8196_CPU_INTEN					BIT(0)
+#define MT8196_CPU_INT_MERGE					BIT(4)
+#define MT8196_VDISP_AO_REG_INT_SEL_G0			0x020
+#define MT8196_VDISP_AO_REG_INT_SEL_G1			0x024
+#define MT8196_VDISP_AO_REG_INT_SEL_G2			0x028
+#define MT8196_VDISP_AO_REG_INT_SEL_G3			0x02c
+#define MT8196_VDISP_AO_REG_INT_SEL_G4			0x030
+#define MT8196_VDISP_AO_REG_INT_SEL_G5			0x034
+#define MT8196_VDISP_AO_REG_INT_SEL_G6			0x038
+#define MT8196_IRQ_TABLE_OVL0_OUTPROC0				(0xa6) /* GIC 450 */
+#define MT8196_IRQ_TABLE_OVL0_OUTPROC1				(0xa7) /* GIC 451 */
+#define MT8196_IRQ_TABLE_OVL1_OUTPROC0				(0xd6) /* GIC 452 */
+#define MT8196_IRQ_TABLE_DSI0					(0x35) /* GIC 453 */
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_ovl0_async_comp_table[] = {
+	{DDP_COMPONENT_OVL0_DLO_ASYNC5, 0, MT8196_OVL_DL_OUT_RELAY5_SIZE, GENMASK(29, 0)},
+	{DDP_COMPONENT_OVL0_DLO_ASYNC6, 1, MT8196_OVL_DL_OUT_RELAY6_SIZE, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_ovl1_async_comp_table[] = {
+	{DDP_COMPONENT_OVL1_DLO_ASYNC5, 0, MT8196_OVL_DL_OUT_RELAY5_SIZE, GENMASK(29, 0)},
+	{DDP_COMPONENT_OVL1_DLO_ASYNC6, 1, MT8196_OVL_DL_OUT_RELAY6_SIZE, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_disp0_async_comp_table[] = {
+	{DDP_COMPONENT_DLI_ASYNC0, 0, MT8196_DISP0_DLI_RELAY0, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC1, 1, MT8196_DISP0_DLI_RELAY1, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC8, 2, MT8196_DISP0_DLI_RELAY8, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC1, 3, MT8196_DISP0_DLO_RELAY1, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC2, 4, MT8196_DISP0_DLO_RELAY2, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC3, 5, MT8196_DISP0_DLO_RELAY3, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_disp1_async_comp_table[] = {
+	{DDP_COMPONENT_DLI_ASYNC21, 0, MT8196_DISP1_DLI_RELAY21, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC22, 1, MT8196_DISP1_DLI_RELAY22, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC23, 2, MT8196_DISP1_DLI_RELAY23, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_vdisp_ao_default_table[] = {
+	{MT8196_VDISP_AO_REG_INTEN, MT8196_CPU_INTEN, MT8196_CPU_INT_MERGE | MT8196_CPU_INTEN},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL0_OUTPROC0, GENMASK(7, 0)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL0_OUTPROC1 << 8, GENMASK(15, 8)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL1_OUTPROC0 << 16, GENMASK(23, 16)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_DSI0 << 24, GENMASK(31, 24)}
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_ovl0_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_OVL_INT_MERGE, 0, BIT(0)},
+	{MT8196_OVLSYS_BYPASS_MUX_SHADOW,
+	 MT8196_BYPASS_MUX_SHADOW, MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_OVLSYS_CB_CON, MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW,
+	 MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_disp0_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_DISP0_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_DISP0_DLI_RELAY0, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLI_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLI_RELAY8, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY2, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY3, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_disp1_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_DISP1_INT_MERGE, 0, BIT(0)},
+	{MT8196_DISP1_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_DISP1_DLI_RELAY21, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_DLI_RELAY22, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_DLI_RELAY23, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_GCE_FRAME_DONE_SEL0, MT8196_FRAME_DONE_DVO, GENMASK(5, 0)},
+	{MT8196_DISP1_GCE_FRAME_DONE_SEL1, MT8196_FRAME_DONE_DP_INTF0, GENMASK(5, 0)},
+};
+
+static const struct mtk_mmsys_routes mmsys_mt8196_ovl0_routing_table[] = {
+	{
+		DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_OVL0_BLENDER1,
+		MT8196_OVL_RSZ_IN_CB2_MOUT_EN, MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3,
+		MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_OVL0_BLENDER1,
+		MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA3, DDP_COMPONENT_OVL0_BLENDER2,
+		MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA4, DDP_COMPONENT_OVL0_BLENDER3,
+		MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA5, DDP_COMPONENT_OVL0_BLENDER4,
+		MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA6, DDP_COMPONENT_OVL0_BLENDER5,
+		MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA7, DDP_COMPONENT_OVL0_BLENDER6,
+		MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA8, DDP_COMPONENT_OVL0_BLENDER7,
+		MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7
+	}, {
+		DDP_COMPONENT_OVL0_EXDMA9, DDP_COMPONENT_OVL0_BLENDER8,
+		MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8
+	}, {
+		DDP_COMPONENT_OVL0_BLENDER4, DDP_COMPONENT_OVL0_OUTPROC0,
+		MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0,
+		MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0
+	}, {
+		DDP_COMPONENT_OVL0_BLENDER8, DDP_COMPONENT_OVL0_OUTPROC1,
+		MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1,
+		MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1
+	}, {
+		DDP_COMPONENT_OVL0_OUTPROC0, DDP_COMPONENT_OVL0_DLO_ASYNC5,
+		MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN, MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5,
+		MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5
+	}, {
+		DDP_COMPONENT_OVL0_OUTPROC1, DDP_COMPONENT_OVL0_DLO_ASYNC6,
+		MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN, MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6,
+		MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6
+	}
+};
+
+static const struct mtk_mmsys_routes mmsys_mt8196_ovl1_routing_table[] = {
+	{
+		DDP_COMPONENT_OVL1_EXDMA2, DDP_COMPONENT_OVL1_BLENDER1,
+		MT8196_OVL_RSZ_IN_CB2_MOUT_EN, MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3,
+		MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA2, DDP_COMPONENT_OVL1_BLENDER1,
+		MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA3, DDP_COMPONENT_OVL1_BLENDER2,
+		MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA4, DDP_COMPONENT_OVL1_BLENDER3,
+		MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA5, DDP_COMPONENT_OVL1_BLENDER4,
+		MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA6, DDP_COMPONENT_OVL1_BLENDER5,
+		MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA7, DDP_COMPONENT_OVL1_BLENDER6,
+		MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA8, DDP_COMPONENT_OVL1_BLENDER7,
+		MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7
+	}, {
+		DDP_COMPONENT_OVL1_EXDMA9, DDP_COMPONENT_OVL1_BLENDER8,
+		MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8,
+		MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8
+	}, {
+		DDP_COMPONENT_OVL1_BLENDER4, DDP_COMPONENT_OVL1_OUTPROC0,
+		MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0,
+		MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0
+	}, {
+		DDP_COMPONENT_OVL1_BLENDER8, DDP_COMPONENT_OVL1_OUTPROC1,
+		MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1,
+		MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1
+	}, {
+		DDP_COMPONENT_OVL1_OUTPROC0, DDP_COMPONENT_OVL1_DLO_ASYNC5,
+		MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN, MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5,
+		MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5
+	}, {
+		DDP_COMPONENT_OVL1_OUTPROC1, DDP_COMPONENT_OVL1_DLO_ASYNC6,
+		MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN, MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6,
+		MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6
+	}
+};
+
+/*
+ * main: DLI_ASYNC0-> PQ_IN_CB0 -> PQ_OUT_CB6 -> PANEL_COMP_OUT_CB1 -> DLO_ASYNC1
+ * ext:  DLI_ASYNC1-> PQ_IN_CB1 -> PQ_OUT_CB7 -> PANEL_COMP_OUT_CB2 -> DLO_ASYNC2
+ */
+static const struct mtk_mmsys_routes mmsys_mt8196_disp0_routing_table[] = {
+	{
+		DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_DLO_ASYNC1,
+		MT8196_PQ_IN_CB0_MOUT_EN, MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6,
+		MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6
+	}, {
+		DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_DLO_ASYNC1,
+		MT8196_PQ_OUT_CB6_MOUT_EN, MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1,
+		MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1
+	}, {
+		DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_DLO_ASYNC1,
+		MT8196_PANEL_COMP_OUT_CB1_MOUT_EN, MT8196_DISP_TO_DLO_RELAY1,
+		MT8196_DISP_TO_DLO_RELAY1
+	}, {
+		DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_DLO_ASYNC2,
+		MT8196_PQ_IN_CB1_MOUT_EN, MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7,
+		MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7
+	}, {
+		DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_DLO_ASYNC2,
+		MT8196_PQ_OUT_CB7_MOUT_EN, MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2,
+		MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2
+	}, {
+		DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_DLO_ASYNC2,
+		MT8196_PANEL_COMP_OUT_CB2_MOUT_EN, MT8196_DISP_TO_DLO_RELAY2,
+		MT8196_DISP_TO_DLO_RELAY2
+	}, {
+		DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_DLO_ASYNC3,
+		MT8196_PQ_IN_CB8_MOUT_EN, MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8,
+		MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8
+	}, {
+		DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_DLO_ASYNC3,
+		MT8196_PQ_OUT_CB8_MOUT_EN, MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3,
+		MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3
+	}, {
+		DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_DLO_ASYNC3,
+		MT8196_PANEL_COMP_OUT_CB3_MOUT_EN, MT8196_DISP_TO_DLO_RELAY3,
+		MT8196_DISP_TO_DLO_RELAY3
+	}
+};
+
+/*
+ * main: DLI_ASYNC21-> SPLITTER_IN_CB1-> SPLITTER_OUT_CB9-> COMP_OUT_CB6-> MERGE_OUT_CB0 -> DVO
+ * ext: DLI_ASYNC22-> SPLITTER_IN_CB2-> SPLITTER_OUT_CB10-> COMP_OUT_CB7-> MERGE_OUT_CB1 -> DP_INTF0
+ */
+static const struct mtk_mmsys_routes mmsys_mt8196_disp1_routing_table[] = {
+	{
+		DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+		MT8196_SPLITTER_IN_CB1_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9,
+		MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9
+	}, {
+		DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+		MT8196_SPLITTER_OUT_CB9_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6,
+		MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6
+	}, {
+		DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+		MT8196_COMP_OUT_CB6_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0,
+		MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0
+	}, {
+		DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+		MT8196_MERGE_OUT_CB0_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+		MT8196_DISP_COMP_OUT_CB_TO_DVO0
+	}, {
+		DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+		MT8196_SPLITTER_IN_CB2_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10,
+		MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10
+	}, {
+		DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+		MT8196_SPLITTER_OUT_CB10_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7,
+		MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7
+	}, {
+		DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+		MT8196_COMP_OUT_CB7_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1,
+		MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1
+	}, {
+		DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+		MT8196_MERGE_OUT_CB1_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0,
+		MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+		MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+		MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+		MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+		MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+		MT8196_DISP_COMP_OUT_CB_TO_DVO0
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+		MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+		MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+		MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+		MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1,
+		MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DSI0,
+		MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DSI0,
+		MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DSI0,
+		MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2
+	}, {
+		DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DSI0,
+		MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DSI0,
+		MT8196_DISP_COMP_OUT_CB_TO_DSI0
+	}
+};
+#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index bb4639ca0b8c..1d3ca4f9f237 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -4,12 +4,14 @@
  * Author: James Liao <jamesjj.liao at mediatek.com>
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/reset-controller.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 
@@ -21,6 +23,7 @@
 #include "mt8188-mmsys.h"
 #include "mt8192-mmsys.h"
 #include "mt8195-mmsys.h"
+#include "mt8196-mmsys.h"
 #include "mt8365-mmsys.h"
 
 #define MMSYS_SW_RESET_PER_REG 32
@@ -144,6 +147,54 @@ static const struct mtk_mmsys_driver_data mt8195_vppsys1_driver_data = {
 	.is_vppsys = true,
 };
 
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+	.clk_driver = "clk-mt8196-disp0",
+	.routes = mmsys_mt8196_disp0_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp0_routing_table),
+	.async_info = mmsys_mt8196_disp0_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp0_async_comp_table),
+	.def_config = mmsys_mt8196_disp0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp0_default_table),
+	.num_top_clk = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+	.clk_driver = "clk-mt8196-disp1",
+	.routes = mmsys_mt8196_disp1_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp1_routing_table),
+	.async_info = mmsys_mt8196_disp1_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp1_async_comp_table),
+	.def_config = mmsys_mt8196_disp1_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp1_default_table),
+	.num_top_clk = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+	.clk_driver = "clk-mt8196-ovl0",
+	.routes = mmsys_mt8196_ovl0_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl0_routing_table),
+	.async_info = mmsys_mt8196_ovl0_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl0_async_comp_table),
+	.def_config = mmsys_mt8196_ovl0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+	.clk_driver = "clk-mt8196-ovl1",
+	.routes = mmsys_mt8196_ovl1_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl1_routing_table),
+	.async_info = mmsys_mt8196_ovl1_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl1_async_comp_table),
+	.def_config = mmsys_mt8196_ovl0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
+};
+
+static const struct mtk_mmsys_driver_data mt8196_vdisp_ao_driver_data = {
+	.clk_driver = "clk-mt8196-vdisp_ao",
+	.def_config = mmsys_mt8196_vdisp_ao_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_vdisp_ao_default_table),
+};
+
 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
 	.clk_driver = "clk-mt8365-mm",
 	.routes = mt8365_mmsys_routing_table,
@@ -158,6 +209,9 @@ struct mtk_mmsys {
 	spinlock_t lock; /* protects mmsys_sw_rst_b reg */
 	struct reset_controller_dev rcdev;
 	struct cmdq_client_reg cmdq_base;
+	struct clk **async_clk;
+	int num_async_clk;
+	struct clk **top_clk;
 };
 
 static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val,
@@ -180,6 +234,99 @@ static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask,
 	writel_relaxed(tmp, mmsys->regs + offset);
 }
 
+int mtk_mmsys_top_clk_enable(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	int ret, i;
+
+	if (!mmsys->data->num_top_clk)
+		return 0;
+
+	for (i = 0; i < mmsys->data->num_top_clk; i++)
+		ret = clk_prepare_enable(mmsys->top_clk[i]);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_enable);
+
+void mtk_mmsys_top_clk_disable(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < mmsys->data->num_top_clk; i++)
+		clk_disable_unprepare(mmsys->top_clk[i]);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_disable);
+
+int mtk_mmsys_ddp_clk_enable(struct device *dev, enum mtk_ddp_comp_id comp_id)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+
+	int i;
+
+	if (!mmsys->data->num_async_info)
+		return 0;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			return clk_prepare_enable(mmsys->async_clk[async[i].index]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_enable);
+
+void mtk_mmsys_ddp_clk_disable(struct device *dev, enum mtk_ddp_comp_id comp_id)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+	int i;
+
+	if (!mmsys->data->num_async_info)
+		return;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			clk_disable_unprepare(mmsys->async_clk[async[i].index]);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_disable);
+
+void mtk_mmsys_ddp_config(struct device *dev, enum mtk_ddp_comp_id comp_id,
+			  int width, int height, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+	int i;
+
+	if (!mmsys->data->num_async_info)
+		return;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			break;
+
+	if (i == mmsys->data->num_async_info)
+		return;
+
+	mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
+			      height << 16 | width, cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_config);
+
+void mtk_mmsys_default_config(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_default *def_config = mmsys->data->def_config;
+	int i;
+
+	if (!mmsys->data->num_def_config)
+		return;
+
+	for (i = 0; i < mmsys->data->num_def_config; i++)
+		mtk_mmsys_update_bits(mmsys, def_config[i].offset, def_config[i].mask,
+				      def_config[i].val, NULL);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_default_config);
+
 void mtk_mmsys_ddp_connect(struct device *dev,
 			   enum mtk_ddp_comp_id cur,
 			   enum mtk_ddp_comp_id next)
@@ -390,7 +537,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 	struct platform_device *clks;
 	struct platform_device *drm;
 	struct mtk_mmsys *mmsys;
-	int ret;
+	int ret, i;
 
 	mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL);
 	if (!mmsys)
@@ -432,6 +579,49 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 		return PTR_ERR(clks);
 	mmsys->clks_pdev = clks;
 
+	if (mmsys->data->num_top_clk) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(dev->of_node, "top");
+		if (!node) {
+			dev_err(&pdev->dev, "Couldn't find top node\n");
+			return -EINVAL;
+		}
+
+		mmsys->top_clk = devm_kmalloc_array(dev, mmsys->data->num_top_clk,
+						    sizeof(*mmsys->top_clk), GFP_KERNEL);
+		if (!mmsys->top_clk)
+			return -ENOMEM;
+
+		for (i = 0; i < mmsys->data->num_top_clk; i++) {
+			mmsys->top_clk[i] = of_clk_get(node, i);
+			if (IS_ERR(mmsys->top_clk[i]))
+				return PTR_ERR(mmsys->top_clk[i]);
+		}
+	}
+
+	if (mmsys->data->num_async_info) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(dev->of_node, "async");
+		if (!node) {
+			dev_err(&pdev->dev, "Couldn't find async node\n");
+			return -EINVAL;
+		}
+
+		mmsys->async_clk = devm_kmalloc_array(dev, mmsys->data->num_async_info,
+						      sizeof(*mmsys->async_clk), GFP_KERNEL);
+		if (!mmsys->async_clk)
+			return -ENOMEM;
+		mmsys->num_async_clk = mmsys->data->num_async_info;
+
+		for (i = 0; i < mmsys->num_async_clk; i++) {
+			mmsys->async_clk[i] = of_clk_get(node, i);
+			if (IS_ERR(mmsys->async_clk[i]))
+				return PTR_ERR(mmsys->async_clk[i]);
+		}
+	}
+
 	if (mmsys->data->is_vppsys)
 		goto out_probe_done;
 
@@ -443,6 +633,9 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 	}
 	mmsys->drm_pdev = drm;
 
+	if (of_property_present(dev->of_node, "power-domains"))
+		pm_runtime_enable(dev);
+
 out_probe_done:
 	return 0;
 }
@@ -453,6 +646,9 @@ static void mtk_mmsys_remove(struct platform_device *pdev)
 
 	platform_device_unregister(mmsys->drm_pdev);
 	platform_device_unregister(mmsys->clks_pdev);
+
+	if (of_property_present(pdev->dev.of_node, "power-domains"))
+		pm_runtime_disable(&pdev->dev);
 }
 
 static const struct of_device_id of_match_mtk_mmsys[] = {
@@ -476,6 +672,11 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
 	{ .compatible = "mediatek,mt8195-vdosys1", .data = &mt8195_vdosys1_driver_data },
 	{ .compatible = "mediatek,mt8195-vppsys0", .data = &mt8195_vppsys0_driver_data },
 	{ .compatible = "mediatek,mt8195-vppsys1", .data = &mt8195_vppsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-dispsys0", .data = &mt8196_dispsys0_driver_data },
+	{ .compatible = "mediatek,mt8196-dispsys1", .data = &mt8196_dispsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-ovlsys0", .data = &mt8196_ovlsys0_driver_data },
+	{ .compatible = "mediatek,mt8196-ovlsys1", .data = &mt8196_ovlsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-vdisp-ao", .data = &mt8196_vdisp_ao_driver_data },
 	{ .compatible = "mediatek,mt8365-mmsys", .data = &mt8365_mmsys_driver_data },
 	{ /* sentinel */ }
 };
diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h
index fe628d5f5198..bbc03ef5b025 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ -102,6 +102,19 @@ struct mtk_mmsys_routes {
 	u32 val;
 };
 
+struct mtk_mmsys_async_info {
+	u32 comp_id;
+	u32 index;
+	u32 offset;
+	u32 mask;
+};
+
+struct mtk_mmsys_default {
+	u32 offset;
+	u32 val;
+	u32 mask;
+};
+
 /**
  * struct mtk_mmsys_driver_data - Settings of the mmsys
  * @clk_driver: Clock driver name that the mmsys is using
@@ -139,6 +152,11 @@ struct mtk_mmsys_driver_data {
 	const u32 num_resets;
 	const bool is_vppsys;
 	const u8 vsync_len;
+	const struct mtk_mmsys_async_info *async_info;
+	const unsigned int num_async_info;
+	const struct mtk_mmsys_default *def_config;
+	const unsigned int num_def_config;
+	const unsigned int num_top_clk;
 };
 
 /*
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h
index 4885b065b849..4a0b10567581 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -29,6 +29,15 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_COLOR1,
 	DDP_COMPONENT_DITHER0,
 	DDP_COMPONENT_DITHER1,
+	DDP_COMPONENT_DLI_ASYNC0,
+	DDP_COMPONENT_DLI_ASYNC1,
+	DDP_COMPONENT_DLI_ASYNC8,
+	DDP_COMPONENT_DLI_ASYNC21,
+	DDP_COMPONENT_DLI_ASYNC22,
+	DDP_COMPONENT_DLI_ASYNC23,
+	DDP_COMPONENT_DLO_ASYNC1,
+	DDP_COMPONENT_DLO_ASYNC2,
+	DDP_COMPONENT_DLO_ASYNC3,
 	DDP_COMPONENT_DP_INTF0,
 	DDP_COMPONENT_DP_INTF1,
 	DDP_COMPONENT_DPI0,
@@ -39,6 +48,7 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_DSI1,
 	DDP_COMPONENT_DSI2,
 	DDP_COMPONENT_DSI3,
+	DDP_COMPONENT_DVO0,
 	DDP_COMPONENT_ETHDR_MIXER,
 	DDP_COMPONENT_GAMMA,
 	DDP_COMPONENT_MDP_RDMA0,
@@ -58,10 +68,52 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_OD0,
 	DDP_COMPONENT_OD1,
 	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_OVL0_BLENDER1,
+	DDP_COMPONENT_OVL0_BLENDER2,
+	DDP_COMPONENT_OVL0_BLENDER3,
+	DDP_COMPONENT_OVL0_BLENDER4,
+	DDP_COMPONENT_OVL0_BLENDER5,
+	DDP_COMPONENT_OVL0_BLENDER6,
+	DDP_COMPONENT_OVL0_BLENDER7,
+	DDP_COMPONENT_OVL0_BLENDER8,
+	DDP_COMPONENT_OVL0_BLENDER9,
+	DDP_COMPONENT_OVL0_DLO_ASYNC5,
+	DDP_COMPONENT_OVL0_DLO_ASYNC6,
+	DDP_COMPONENT_OVL0_EXDMA2,
+	DDP_COMPONENT_OVL0_EXDMA3,
+	DDP_COMPONENT_OVL0_EXDMA4,
+	DDP_COMPONENT_OVL0_EXDMA5,
+	DDP_COMPONENT_OVL0_EXDMA6,
+	DDP_COMPONENT_OVL0_EXDMA7,
+	DDP_COMPONENT_OVL0_EXDMA8,
+	DDP_COMPONENT_OVL0_EXDMA9,
+	DDP_COMPONENT_OVL0_OUTPROC0,
+	DDP_COMPONENT_OVL0_OUTPROC1,
 	DDP_COMPONENT_OVL_2L0,
 	DDP_COMPONENT_OVL_2L1,
 	DDP_COMPONENT_OVL_2L2,
 	DDP_COMPONENT_OVL1,
+	DDP_COMPONENT_OVL1_BLENDER1,
+	DDP_COMPONENT_OVL1_BLENDER2,
+	DDP_COMPONENT_OVL1_BLENDER3,
+	DDP_COMPONENT_OVL1_BLENDER4,
+	DDP_COMPONENT_OVL1_BLENDER5,
+	DDP_COMPONENT_OVL1_BLENDER6,
+	DDP_COMPONENT_OVL1_BLENDER7,
+	DDP_COMPONENT_OVL1_BLENDER8,
+	DDP_COMPONENT_OVL1_BLENDER9,
+	DDP_COMPONENT_OVL1_DLO_ASYNC5,
+	DDP_COMPONENT_OVL1_DLO_ASYNC6,
+	DDP_COMPONENT_OVL1_EXDMA2,
+	DDP_COMPONENT_OVL1_EXDMA3,
+	DDP_COMPONENT_OVL1_EXDMA4,
+	DDP_COMPONENT_OVL1_EXDMA5,
+	DDP_COMPONENT_OVL1_EXDMA6,
+	DDP_COMPONENT_OVL1_EXDMA7,
+	DDP_COMPONENT_OVL1_EXDMA8,
+	DDP_COMPONENT_OVL1_EXDMA9,
+	DDP_COMPONENT_OVL1_OUTPROC0,
+	DDP_COMPONENT_OVL1_OUTPROC1,
 	DDP_COMPONENT_PADDING0,
 	DDP_COMPONENT_PADDING1,
 	DDP_COMPONENT_PADDING2,
@@ -84,6 +136,14 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_ID_MAX,
 };
 
+int mtk_mmsys_top_clk_enable(struct device *dev);
+void mtk_mmsys_top_clk_disable(struct device *dev);
+int mtk_mmsys_ddp_clk_enable(struct device *dev, enum mtk_ddp_comp_id comp_id);
+void mtk_mmsys_ddp_clk_disable(struct device *dev, enum mtk_ddp_comp_id comp_id);
+void mtk_mmsys_ddp_config(struct device *dev, enum mtk_ddp_comp_id comp_id,
+			  int width, int height, struct cmdq_pkt *cmdq_pkt);
+void mtk_mmsys_default_config(struct device *dev);
+
 void mtk_mmsys_ddp_connect(struct device *dev,
 			   enum mtk_ddp_comp_id cur,
 			   enum mtk_ddp_comp_id next);
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:37 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:37 +0800
Subject: [PATCH v2 08/15] soc: mediatek: mutex: add mutex support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-9-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

Add mutex support for the main and external displays in MT8196:
- Introduce a new DVO0 output component for the new mutex
  settings of MT8196.
- Add a need_sof_mof flag to configure both SOF and MOD settings
  for the output component.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c | 140 ++++++++++++++++++++++++++++++-
 1 file changed, 138 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index c026ac0e6969..f51d1cb5ad1e 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -19,6 +19,7 @@
 #define MT2701_MUTEX0_SOF0			0x30
 #define MT8183_MUTEX0_MOD0			0x30
 #define MT8183_MUTEX0_SOF0			0x2c
+#define MT8196_MUTEX0_MOD0			0x34
 
 #define DISP_REG_MUTEX_EN(n)			(0x20 + 0x20 * (n))
 #define DISP_REG_MUTEX(n)			(0x24 + 0x20 * (n))
@@ -237,6 +238,47 @@
 #define MT8195_MUTEX_MOD_MDP_WROT2             32
 #define MT8195_MUTEX_MOD_MDP_WROT3             33
 
+/* OVLSYS */
+#define MT8196_MUTEX_MOD0_OVL_EXDMA2		2
+#define MT8196_MUTEX_MOD0_OVL_EXDMA3		3
+#define MT8196_MUTEX_MOD0_OVL_EXDMA4		4
+#define MT8196_MUTEX_MOD0_OVL_EXDMA5		5
+#define MT8196_MUTEX_MOD0_OVL_EXDMA6		6
+#define MT8196_MUTEX_MOD0_OVL_EXDMA7		7
+#define MT8196_MUTEX_MOD0_OVL_EXDMA8		8
+#define MT8196_MUTEX_MOD0_OVL_EXDMA9		9
+#define MT8196_MUTEX_MOD0_OVL_BLENDER1		11
+#define MT8196_MUTEX_MOD0_OVL_BLENDER2		12
+#define MT8196_MUTEX_MOD0_OVL_BLENDER3		13
+#define MT8196_MUTEX_MOD0_OVL_BLENDER4		14
+#define MT8196_MUTEX_MOD0_OVL_BLENDER5		15
+#define MT8196_MUTEX_MOD0_OVL_BLENDER6		16
+#define MT8196_MUTEX_MOD0_OVL_BLENDER7		17
+#define MT8196_MUTEX_MOD0_OVL_BLENDER8		18
+#define MT8196_MUTEX_MOD0_OVL_BLENDER9		19
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC0		20
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC1		21
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC2		22
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5	(32 + 16)
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6	(32 + 17)
+
+/* DISP0 */
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0	16
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1	17
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8	24
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1	(32 + 1)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2	(32 + 2)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3	(32 + 3)
+
+/* DISP1 */
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21	1
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22	2
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23	3
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF0	13
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF1	14
+#define MT8196_MUTEX_MOD0_DISP1_DSI0		23
+#define MT8196_MUTEX_MOD0_DISP1_DVO		29
+
 #define MT8365_MUTEX_MOD_DISP_OVL0		7
 #define MT8365_MUTEX_MOD_DISP_OVL0_2L		8
 #define MT8365_MUTEX_MOD_DISP_RDMA0		9
@@ -297,6 +339,12 @@
 #define MT8195_MUTEX_SOF_DP_INTF1		4
 #define MT8195_MUTEX_SOF_DPI0			6 /* for HDMI_TX */
 #define MT8195_MUTEX_SOF_DPI1			5 /* for digital video out */
+#define MT8196_MUTEX_SOF_DSI0			1
+#define MT8196_MUTEX_SOF_DSI1			2
+#define MT8196_MUTEX_SOF_DSI2			4
+#define MT8196_MUTEX_SOF_DPI0			5
+#define MT8196_MUTEX_SOF_DPI1			6
+#define MT8196_MUTEX_SOF_DVO0			7
 
 #define MT8183_MUTEX_EOF_DSI0			(MT8183_MUTEX_SOF_DSI0 << 6)
 #define MT8183_MUTEX_EOF_DPI0			(MT8183_MUTEX_SOF_DPI0 << 6)
@@ -310,6 +358,12 @@
 #define MT8195_MUTEX_EOF_DP_INTF1		(MT8195_MUTEX_SOF_DP_INTF1 << 7)
 #define MT8195_MUTEX_EOF_DPI0			(MT8195_MUTEX_SOF_DPI0 << 7)
 #define MT8195_MUTEX_EOF_DPI1			(MT8195_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DSI0			(MT8196_MUTEX_SOF_DSI0 << 7)
+#define MT8196_MUTEX_EOF_DSI1			(MT8196_MUTEX_SOF_DSI1 << 7)
+#define MT8196_MUTEX_EOF_DSI2			(MT8196_MUTEX_SOF_DSI2 << 7)
+#define MT8196_MUTEX_EOF_DPI0			(MT8196_MUTEX_SOF_DPI0 << 7)
+#define MT8196_MUTEX_EOF_DPI1			(MT8196_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DVO0			(MT8196_MUTEX_SOF_DVO0 << 7)
 
 struct mtk_mutex {
 	u8 id;
@@ -326,6 +380,7 @@ enum mtk_mutex_sof_id {
 	MUTEX_SOF_DSI3,
 	MUTEX_SOF_DP_INTF0,
 	MUTEX_SOF_DP_INTF1,
+	MUTEX_SOF_DVO0,
 	DDP_MUTEX_SOF_MAX,
 };
 
@@ -336,6 +391,7 @@ struct mtk_mutex_data {
 	const u16 mutex_mod_reg;
 	const u16 mutex_sof_reg;
 	const bool no_clk;
+	const bool need_sof_mod;
 };
 
 struct mtk_mutex_ctx {
@@ -625,6 +681,64 @@ static const u8 mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
 	[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
 };
 
+static const u8 mt8196_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_OVL0_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+	[DDP_COMPONENT_OVL0_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+	[DDP_COMPONENT_OVL0_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+	[DDP_COMPONENT_OVL0_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+	[DDP_COMPONENT_OVL0_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+	[DDP_COMPONENT_OVL0_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+	[DDP_COMPONENT_OVL0_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+	[DDP_COMPONENT_OVL0_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+	[DDP_COMPONENT_OVL0_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+	[DDP_COMPONENT_OVL0_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+	[DDP_COMPONENT_OVL0_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+	[DDP_COMPONENT_OVL0_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+	[DDP_COMPONENT_OVL0_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+	[DDP_COMPONENT_OVL0_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+	[DDP_COMPONENT_OVL0_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+	[DDP_COMPONENT_OVL0_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+	[DDP_COMPONENT_OVL0_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+	[DDP_COMPONENT_OVL0_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+	[DDP_COMPONENT_OVL0_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+	[DDP_COMPONENT_OVL1_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+	[DDP_COMPONENT_OVL1_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+	[DDP_COMPONENT_OVL1_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+	[DDP_COMPONENT_OVL1_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+	[DDP_COMPONENT_OVL1_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+	[DDP_COMPONENT_OVL1_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+	[DDP_COMPONENT_OVL1_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+	[DDP_COMPONENT_OVL1_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+	[DDP_COMPONENT_OVL1_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+	[DDP_COMPONENT_OVL1_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+	[DDP_COMPONENT_OVL1_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+	[DDP_COMPONENT_OVL1_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+	[DDP_COMPONENT_OVL1_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+	[DDP_COMPONENT_OVL1_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+	[DDP_COMPONENT_OVL1_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+	[DDP_COMPONENT_OVL1_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+	[DDP_COMPONENT_OVL1_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+	[DDP_COMPONENT_OVL1_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+	[DDP_COMPONENT_OVL1_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+	[DDP_COMPONENT_OVL1_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+	[DDP_COMPONENT_DLI_ASYNC0] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0,
+	[DDP_COMPONENT_DLI_ASYNC1] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1,
+	[DDP_COMPONENT_DLI_ASYNC8] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8,
+	[DDP_COMPONENT_DLO_ASYNC1] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1,
+	[DDP_COMPONENT_DLO_ASYNC2] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2,
+	[DDP_COMPONENT_DLO_ASYNC3] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3,
+	[DDP_COMPONENT_DLI_ASYNC21] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21,
+	[DDP_COMPONENT_DLI_ASYNC22] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22,
+	[DDP_COMPONENT_DLI_ASYNC23] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23,
+	[DDP_COMPONENT_DVO0] = MT8196_MUTEX_MOD0_DISP1_DVO,
+	[DDP_COMPONENT_DP_INTF0] = MT8196_MUTEX_MOD0_DISP1_DP_INTF0,
+	[DDP_COMPONENT_DP_INTF1] = MT8196_MUTEX_MOD0_DISP1_DP_INTF1,
+	[DDP_COMPONENT_DSI0] = MT8196_MUTEX_MOD0_DISP1_DSI0,
+};
+
 static const u8 mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
 	[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
@@ -710,6 +824,17 @@ static const u16 mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
 		MT8195_MUTEX_SOF_DP_INTF1 | MT8195_MUTEX_EOF_DP_INTF1,
 };
 
+static const u16 mt8196_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+	[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
+	[MUTEX_SOF_DSI0] = MT8196_MUTEX_SOF_DSI0 | MT8196_MUTEX_EOF_DSI0,
+	[MUTEX_SOF_DSI1] = MT8196_MUTEX_SOF_DSI1 | MT8196_MUTEX_EOF_DSI1,
+	[MUTEX_SOF_DP_INTF0] =
+		MT8196_MUTEX_SOF_DPI0 | MT8196_MUTEX_EOF_DPI0,
+	[MUTEX_SOF_DP_INTF1] =
+		MT8196_MUTEX_SOF_DPI1 | MT8196_MUTEX_EOF_DPI1,
+	[MUTEX_SOF_DVO0] = MT8196_MUTEX_SOF_DVO0 | MT8196_MUTEX_EOF_DVO0,
+};
+
 static const struct mtk_mutex_data mt2701_mutex_driver_data = {
 	.mutex_mod = mt2701_mutex_mod,
 	.mutex_sof = mt2712_mutex_sof,
@@ -803,6 +928,14 @@ static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
 	.mutex_table_mod = mt8195_mutex_table_mod,
 };
 
+static const struct mtk_mutex_data mt8196_mutex_driver_data = {
+	.mutex_mod = mt8196_mutex_mod,
+	.mutex_sof = mt8196_mutex_sof,
+	.mutex_mod_reg = MT8196_MUTEX0_MOD0,
+	.mutex_sof_reg = MT2701_MUTEX0_SOF0,
+	.need_sof_mod = true,
+};
+
 static const struct mtk_mutex_data mt8365_mutex_driver_data = {
 	.mutex_mod = mt8365_mutex_mod,
 	.mutex_sof = mt8183_mutex_sof,
@@ -872,6 +1005,8 @@ static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
 		return MUTEX_SOF_DP_INTF0;
 	case DDP_COMPONENT_DP_INTF1:
 		return MUTEX_SOF_DP_INTF1;
+	case DDP_COMPONENT_DVO0:
+		return MUTEX_SOF_DVO0;
 	default:
 		break;
 	}
@@ -930,7 +1065,7 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (!is_output_comp) {
+	if (!is_output_comp || mtx->data->need_sof_mod) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -961,7 +1096,7 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (!is_output_comp) {
+	if (!is_output_comp || mtx->data->need_sof_mod) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -1169,6 +1304,7 @@ static const struct of_device_id mutex_driver_dt_match[] = {
 	{ .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
 	{ .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
 	{ .compatible = "mediatek,mt8195-vpp-mutex",  .data = &mt8195_vpp_mutex_driver_data },
+	{ .compatible = "mediatek,mt8196-disp-mutex", .data = &mt8196_mutex_driver_data },
 	{ .compatible = "mediatek,mt8365-disp-mutex", .data = &mt8365_mutex_driver_data },
 	{ /* sentinel */ },
 };
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:38 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:38 +0800
Subject: [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-10-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

Refine OVL format convert API and export to public.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 158 ++++++++++++++++--------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  16 +++
 2 files changed, 122 insertions(+), 52 deletions(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index d0581c4e3c99..e2b125a717c6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -18,6 +18,7 @@
 #include "mtk_crtc.h"
 #include "mtk_ddp_comp.h"
 #include "mtk_disp_drv.h"
+#include "mtk_disp_ovl.h"
 #include "mtk_drm_drv.h"
 
 #define DISP_REG_OVL_INTEN			0x0004
@@ -62,22 +63,15 @@
 /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
 #define OVL_CON_RGB_SWAP	BIT(25)
 
-#define OVL_CON_CLRFMT_RGB	(1 << 12)
-#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
-#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
-#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_UYVY	(4 << 12)
-#define OVL_CON_CLRFMT_YUYV	(5 << 12)
-#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
-#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
-#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
-#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					0 : OVL_CON_CLRFMT_RGB)
-#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					OVL_CON_CLRFMT_RGB : 0)
+#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
+#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
+#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
+#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
+#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
+#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
+#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
+#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
+
 #define	OVL_CON_AEN		BIT(8)
 #define	OVL_CON_ALPHA		0xff
 #define	OVL_CON_VIRT_FLIP	BIT(9)
@@ -85,7 +79,7 @@
 
 #define OVL_COLOR_ALPHA		GENMASK(31, 24)
 
-static inline bool is_10bit_rgb(u32 fmt)
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
 {
 	switch (fmt) {
 	case DRM_FORMAT_XRGB2101010:
@@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
 	if (!ovl->data->supports_clrfmt_ext)
 		return;
 
-	if (is_10bit_rgb(format))
+	if (mtk_ovl_is_10bit_rgb(format))
 		bit_depth = OVL_CON_CLRFMT_10_BIT;
 
 	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
@@ -394,10 +388,26 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
-					struct mtk_plane_state *state)
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
+{
+	if (!state->base.fb)
+		return false;
+
+	/*
+	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
+	 * for XRGB format, otherwise OVL will still read the value from memory.
+	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
+	 * affect the result. Therefore we use !has_alpha as the condition.
+	 */
+
+	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
+		return true;
+
+	return false;
+}
+
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
 {
-	unsigned int fmt = state->pending.format;
 	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
 
 	/*
@@ -412,52 +422,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
 	 * will get an error return from drm_plane_create_blend_mode_property() and
 	 * state->base.pixel_blend_mode should not be used.
 	 */
-	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
 		blend_mode = state->base.pixel_blend_mode;
 
+	return blend_mode;
+}
+
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
+{
+	unsigned int con = 0;
+	bool need_byte_swap = false, need_rgb_swap = false;
+
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+		need_byte_swap = true;	/* RGB565 -> BGR565 */
+	break;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+		need_byte_swap = true;	/* RGB888 -> BGR888 */
+	break;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 	case DRM_FORMAT_RGBX1010102:
 	case DRM_FORMAT_RGBA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_RGBA8888 :
-		       OVL_CON_CLRFMT_PRGBA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
+		}
+	break;
 	case DRM_FORMAT_BGRX8888:
 	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_BGRA8888 :
-		       OVL_CON_CLRFMT_PBGRA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+		}
+	break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ARGB8888 :
-		       OVL_CON_CLRFMT_PARGB8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+		else
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+	break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ABGR8888 :
-		       OVL_CON_CLRFMT_PABGR8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
+		}
+	break;
 	case DRM_FORMAT_UYVY:
-		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
+	break;
 	case DRM_FORMAT_YUYV:
-		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
+	break;
 	}
+
+	if (color_convert)
+		con |= OVL_CON_MTX_YUV_TO_RGB;
+
+	if (need_byte_swap)
+		con |= byte_swap;
+
+	if (need_rgb_swap)
+		con |= rgb_swap;
+
+	return con;
 }
 
 static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
@@ -495,7 +555,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 	unsigned int rotation = pending->rotation;
 	unsigned int offset = (pending->y << 16) | pending->x;
 	unsigned int src_size = (pending->height << 16) | pending->width;
-	unsigned int blend_mode = state->base.pixel_blend_mode;
+	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);
 	unsigned int ignore_pixel_alpha = 0;
 	unsigned int con;
 
@@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = mtk_ovl_fmt_convert(ovl, state);
+	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
+				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
 	if (state->base.fb) {
 		con |= state->base.alpha & OVL_CON_ALPHA;
 
@@ -512,17 +573,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		 * For blend_modes supported SoCs, always enable alpha blending.
 		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
 		 */
-		if (blend_mode || state->base.fb->format->has_alpha)
+		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)
 			con |= OVL_CON_AEN;
-
-		/*
-		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
-		 * for XRGB format, otherwise OVL will still read the value from memory.
-		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
-		 * affect the result. Therefore we use !has_alpha as the condition.
-		 */
-		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
-			ignore_pixel_alpha = OVL_CONST_BLEND;
 	}
 
 	/*
@@ -548,6 +600,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 
 	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
 			      DISP_REG_OVL_CON(idx));
+
+	ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
 	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
 			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
 	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
new file mode 100644
index 000000000000..9bd5dc62d626
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OVL_H__
+#define __MTK_DISP_OVL_H__
+
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
+
+#endif
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:39 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:39 +0800
Subject: [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-11-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

EXDMA is a DMA engine for reading data from DRAM with
various DRAM footprints and data formats. For input
sources in certain color formats and color domains,
EXDMA also includes a color transfer function to
process pixels into a consistent color domain.
New Add: 6320385 Fix RG16 and refine RG24

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/Makefile         |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c   |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h   |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h   |   9 +
 drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c    |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h    |   1 +
 7 files changed, 386 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 32a2ed6c0cfe..db92f4fb353d 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
 		  mtk_disp_aal.o \
 		  mtk_disp_ccorr.o \
 		  mtk_disp_color.o \
+		  mtk_disp_exdma.o \
 		  mtk_disp_gamma.o \
 		  mtk_disp_merge.o \
 		  mtk_disp_ovl.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index edc6417639e6..3e0739d8e6f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DP_INTF] = "dp-intf",
 	[MTK_DPI] = "dpi",
 	[MTK_DSI] = "dsi",
+	[MTK_OVL_EXDMA] = "exdma",
 };
 
 struct mtk_ddp_comp_match {
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 39720b27f4e9..86dc0ee3924c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
 	MTK_DPI,
 	MTK_DP_INTF,
 	MTK_DSI,
+	MTK_OVL_EXDMA,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 04217a36939c..4e3d2510bef5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev, unsigned int w,
 		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
 void mtk_color_start(struct device *dev);
 
+int mtk_disp_exdma_clk_enable(struct device *dev);
+void mtk_disp_exdma_clk_disable(struct device *dev);
+void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
+				 struct cmdq_pkt *cmdq_pkt);
+const u32 *mtk_disp_exdma_get_formats(struct device *dev);
+size_t mtk_disp_exdma_get_num_formats(struct device *dev);
+
 void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
 			   unsigned int bpc, unsigned int cfg,
 			   unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
new file mode 100644
index 000000000000..d4f7021f98d7
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#include "mtk_disp_drv.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_ovl.h"
+
+#define DISP_REG_OVL_EXDMA_EN_CON		0xc
+#define OVL_EXDMA_OP_8BIT_MODE				BIT(4)
+#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ON			BIT(8)
+#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ON			BIT(10)
+#define DISP_REG_OVL_EXDMA_DATAPATH_CON		0x014
+#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN		BIT(0)
+#define OVL_EXDMA_DATAPATH_CON_GCLAST_EN		BIT(24)
+#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN		BIT(25)
+#define DISP_REG_OVL_EXDMA_EN			0x020
+#define OVL_EXDMA_EN					BIT(0)
+#define DISP_REG_OVL_EXDMA_RST			0x024
+#define OVL_EXDMA_RST					BIT(0)
+#define DISP_REG_OVL_EXDMA_ROI_SIZE		0x030
+#define DISP_REG_OVL_EXDMA_L0_EN		0x040
+#define OVL_EXDMA_L0_EN					BIT(0)
+#define DISP_REG_OVL_EXDMA_OFFSET		0x044
+#define DISP_REG_OVL_EXDMA_SRC_SIZE		0x048
+#define DISP_REG_OVL_EXDMA_L0_CLRFMT		0x050
+#define OVL_EXDMA_CON_FLD_CLRFMT			GENMASK(3, 0)
+#define OVL_EXDMA_CON_CLRFMT_MAN			BIT(4)
+#define OVL_EXDMA_CON_FLD_CLRFMT_NB			GENMASK(9, 8)
+#define OVL_EXDMA_CON_CLRFMT_NB_10_BIT			BIT(8)
+#define OVL_EXDMA_CON_BYTE_SWAP				BIT(16)
+#define OVL_EXDMA_CON_RGB_SWAP				BIT(17)
+#define DISP_REG_OVL_EXDMA_RDMA0_CTRL		0x100
+#define OVL_EXDMA_RDMA0_EN				BIT(0)
+#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON1	0x1f4
+#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN		BIT(28)
+#define OVL_EXDMA_RDMA_BURST_CON1_DDR_EN		BIT(30)
+#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN		BIT(31)
+#define DISP_REG_OVL_EXDMA_DUMMY_REG		0x200
+#define OVL_EXDMA_EXT_DDR_EN_OPT			BIT(2)
+#define OVL_EXDMA_FORCE_EXT_DDR_EN			BIT(3)
+#define DISP_REG_OVL_EXDMA_GDRDY_PRD		0x208
+#define DISP_REG_OVL_EXDMA_PITCH_MSB		0x2f0
+#define DISP_REG_OVL_EXDMA_PITCH		0x2f4
+#define OVL_EXDMA_L0_SRC_PITCH				GENMASK(15, 0)
+#define OVL_EXDMA_L0_CONST_BLD				BIT(28)
+#define OVL_EXDMA_L0_SRC_PITCH_MASK			GENMASK(15, 0)
+#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT		0x2fc
+#define OVL_EXDMA_RDMA0_L0_VCSEL			BIT(5)
+#define OVL_EXDMA_RDMA0_HDR_L0_VCSEL			BIT(21)
+#define DISP_REG_OVL_EXDMA_CON			0x300
+#define OVL_EXDMA_CON_FLD_INT_MTX_SEL			GENMASK(19, 16)
+#define OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB		(6 << 16)
+#define OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB		(7 << 16)
+#define OVL_EXDMA_CON_INT_MTX_EN			BIT(27)
+#define DISP_REG_OVL_EXDMA_ADDR			0xf40
+#define DISP_REG_OVL_EXDMA_MOUT			0xff0
+#define OVL_EXDMA_MOUT_OUT_DATA				BIT(0)
+#define OVL_EXDMA_MOUT_BGCLR_OUT			BIT(1)
+
+static const u32 formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_RGBX1010102,
+	DRM_FORMAT_RGBA1010102,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_BGRX1010102,
+	DRM_FORMAT_BGRA1010102,
+};
+
+struct mtk_disp_exdma {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct cmdq_client_reg	cmdq_reg;
+	struct device		*larb;
+};
+
+static unsigned int  mtk_disp_exdma_color_convert(unsigned int color_encoding)
+{
+	switch (color_encoding) {
+	default:
+	case DRM_COLOR_YCBCR_BT709:
+		return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
+	case DRM_COLOR_YCBCR_BT601:
+		return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
+	}
+}
+
+void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+	unsigned int value = 0, mask = 0;
+
+	value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
+	mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
+	       OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
+	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RDMA_BURST_CON1, mask);
+	/*
+	 * The dummy register is used in the configuration of the EXDMA engine to
+	 * write commands to DRAM, ensuring that data transfers occur normally.
+	 */
+	value = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
+	mask = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
+	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
+
+	value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
+		OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
+		OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
+	mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
+	       OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
+	       OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
+	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
+
+	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT, &priv->cmdq_reg,
+			   priv->regs, DISP_REG_OVL_EXDMA_MOUT,
+			   OVL_EXDMA_MOUT_BGCLR_OUT | OVL_EXDMA_MOUT_OUT_DATA);
+
+	mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_GDRDY_PRD);
+
+	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_L0_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
+
+	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
+}
+
+void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
+}
+
+void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
+				 struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+	struct mtk_plane_pending_state *pending = &state->pending;
+	const struct drm_format_info *fmt_info = drm_format_info(pending->format);
+	unsigned int align_width = 0;
+	bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
+	unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
+							 BIT(DRM_MODE_BLEND_PREMULTI) |
+							 BIT(DRM_MODE_BLEND_COVERAGE) |
+							 BIT(DRM_MODE_BLEND_PIXEL_NONE));
+	unsigned int val = 0;
+	unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
+				   OVL_EXDMA_CON_BYTE_SWAP |
+				   OVL_EXDMA_CON_CLRFMT_MAN |
+				   OVL_EXDMA_CON_FLD_CLRFMT |
+				   OVL_EXDMA_CON_FLD_CLRFMT_NB;
+
+	if (!pending->enable) {
+		mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+				   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+		mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+				   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
+		return;
+	}
+
+	/* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
+	align_width = ALIGN_DOWN(pending->width, 2);
+
+	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+		      priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
+
+	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+		      priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
+	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+		      priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
+
+	mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg,
+			   priv->regs, DISP_REG_OVL_EXDMA_PITCH, OVL_EXDMA_L0_SRC_PITCH_MASK);
+	mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);
+
+	val = mtk_disp_exdma_color_convert(pending->color_encoding);
+	if (csc_enable)
+		val |= OVL_EXDMA_CON_INT_MTX_EN;
+	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_CON,
+			   OVL_EXDMA_CON_FLD_INT_MTX_SEL | OVL_EXDMA_CON_INT_MTX_EN);
+
+	val = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
+				  OVL_EXDMA_CON_CLRFMT_MAN, OVL_EXDMA_CON_BYTE_SWAP,
+				  OVL_EXDMA_CON_RGB_SWAP);
+	if (mtk_ovl_is_10bit_rgb(pending->format))
+		val |= OVL_EXDMA_CON_CLRFMT_NB_10_BIT;
+	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_L0_CLRFMT, clrfmt_mask);
+
+	val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON | OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
+		OVL_EXDMA_OP_8BIT_MODE;
+	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_EN_CON, val);
+
+	val = OVL_EXDMA_RDMA0_L0_VCSEL | OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
+	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
+
+	val = pending->pitch;
+	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+		val |= OVL_EXDMA_L0_CONST_BLD;
+	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_PITCH,
+			   OVL_EXDMA_L0_CONST_BLD | OVL_EXDMA_L0_SRC_PITCH);
+}
+
+const u32 *mtk_disp_exdma_get_formats(struct device *dev)
+{
+	return formats;
+}
+
+size_t mtk_disp_exdma_get_num_formats(struct device *dev)
+{
+	return ARRAY_SIZE(formats);
+}
+
+int mtk_disp_exdma_clk_enable(struct device *dev)
+{
+	struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(exdma->clk);
+}
+
+void mtk_disp_exdma_clk_disable(struct device *dev)
+{
+	struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(exdma->clk);
+}
+
+static int mtk_disp_exdma_bind(struct device *dev, struct device *master,
+			       void *data)
+{
+	return 0;
+}
+
+static void mtk_disp_exdma_unbind(struct device *dev, struct device *master,
+				  void *data)
+{
+}
+
+static const struct component_ops mtk_disp_exdma_component_ops = {
+	.bind	= mtk_disp_exdma_bind,
+	.unbind = mtk_disp_exdma_unbind,
+};
+
+static int mtk_disp_exdma_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct platform_device *larb_pdev = NULL;
+	struct device_node *larb_node = NULL;
+	struct resource *res;
+	struct mtk_disp_exdma *priv;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->regs)) {
+		dev_err(dev, "failed to ioremap exdma\n");
+		return PTR_ERR(priv->regs);
+	}
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get exdma clk\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	larb_node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
+	if (larb_node) {
+		larb_pdev = of_find_device_by_node(larb_node);
+		if (larb_pdev)
+			priv->larb = &larb_pdev->dev;
+		of_node_put(larb_node);
+	}
+
+	if (!priv->larb) {
+		dev_dbg(dev, "not find larb dev");
+		return -EPROBE_DEFER;
+	}
+	device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+	if (ret)
+		dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+	platform_set_drvdata(pdev, priv);
+
+	pm_runtime_enable(dev);
+
+	ret = component_add(dev, &mtk_disp_exdma_component_ops);
+	if (ret != 0) {
+		pm_runtime_disable(dev);
+		dev_err(dev, "Failed to add component: %d\n", ret);
+	}
+	return ret;
+}
+
+static void mtk_disp_exdma_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
+	pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-exdma", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
+
+struct platform_driver mtk_disp_exdma_driver = {
+	.probe = mtk_disp_exdma_probe,
+	.remove = mtk_disp_exdma_remove,
+	.driver = {
+		.name = "mediatek-disp-exdma",
+		.owner = THIS_MODULE,
+		.of_match_table = mtk_disp_exdma_driver_dt_match,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Exdma Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 74158b9d6503..bb7306a942ff 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1276,6 +1276,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_aal_driver,
 	&mtk_disp_ccorr_driver,
 	&mtk_disp_color_driver,
+	&mtk_disp_exdma_driver,
 	&mtk_disp_gamma_driver,
 	&mtk_disp_merge_driver,
 	&mtk_disp_ovl_adaptor_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 675cdc90a440..898a75898775 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -72,6 +72,7 @@ struct mtk_drm_private {
 extern struct platform_driver mtk_disp_aal_driver;
 extern struct platform_driver mtk_disp_ccorr_driver;
 extern struct platform_driver mtk_disp_color_driver;
+extern struct platform_driver mtk_disp_exdma_driver;
 extern struct platform_driver mtk_disp_gamma_driver;
 extern struct platform_driver mtk_disp_merge_driver;
 extern struct platform_driver mtk_disp_ovl_adaptor_driver;
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:40 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:40 +0800
Subject: [PATCH v2 11/15] drm/mediatek: add BLENDER support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-12-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

BLENDER executes the alpha blending function for overlapping
layers from different sources, which is the primary function
of the overlapping system.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>

---
 drivers/gpu/drm/mediatek/Makefile           |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c     |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h     |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_blender.c | 276 ++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h |  18 ++
 drivers/gpu/drm/mediatek/mtk_disp_drv.h     |  12 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |   1 +
 8 files changed, 311 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index db92f4fb353d..a7b9ebe27f68 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -3,6 +3,7 @@
 mediatek-drm-y := mtk_crtc.o \
 		  mtk_ddp_comp.o \
 		  mtk_disp_aal.o \
+		  mtk_disp_blender.o \
 		  mtk_disp_ccorr.o \
 		  mtk_disp_color.o \
 		  mtk_disp_exdma.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 3e0739d8e6f1..e65c6df987f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DP_INTF] = "dp-intf",
 	[MTK_DPI] = "dpi",
 	[MTK_DSI] = "dsi",
+	[MTK_OVL_BLENDER] = "blender",
 	[MTK_OVL_EXDMA] = "exdma",
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 86dc0ee3924c..075ba5683f93 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
 	MTK_DPI,
 	MTK_DP_INTF,
 	MTK_DSI,
+	MTK_OVL_BLENDER,
 	MTK_OVL_EXDMA,
 	MTK_DDP_COMP_TYPE_MAX,
 };
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
new file mode 100644
index 000000000000..32c9e3d463a4
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include "mtk_disp_drv.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_blender.h"
+#include "mtk_disp_ovl.h"
+
+#define OVL_BLD_ALPHA					0xff
+#define DISP_REG_OVL_BLD_DATAPATH_CON			0x010
+#define OVL_BLD_BGCLR_IN_SEL					BIT(0)
+#define OVL_BLD_BGCLR_OUT_TO_PROC				BIT(4)
+#define OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER				BIT(5)
+
+#define DISP_REG_OVL_BLD_EN				0x020
+#define OVL_BLD_EN						BIT(0)
+#define OVL_BLD_FORCE_RELAY_MODE				BIT(4)
+#define OVL_BLD_RELAY_MODE					BIT(5)
+#define DISP_REG_OVL_BLD_RST				0x024
+#define OVL_BLD_RST						BIT(0)
+#define DISP_REG_OVL_BLD_SHADOW_CTRL			0x028
+#define OVL_BLD_BYPASS_SHADOW					BIT(2)
+#define DISP_REG_OVL_BLD_BGCLR_BALCK			0xff000000
+#define DISP_REG_OVL_BLD_ROI_SIZE			0x030
+#define DISP_REG_OVL_BLD_L_EN				0x040
+#define OVL_BLD_L_EN						BIT(0)
+#define DISP_REG_OVL_BLD_OFFSET				0x044
+#define DISP_REG_OVL_BLD_SRC_SIZE			0x048
+#define DISP_REG_OVL_BLD_L0_CLRFMT			0x050
+#define OVL_BLD_CON_FLD_CLRFMT					GENMASK(3, 0)
+#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
+#define OVL_BLD_CON_FLD_CLRFMT_NB				GENMASK(9, 8)
+#define OVL_BLD_CON_CLRFMT_NB_10_BIT				BIT(8)
+#define OVL_BLD_CON_BYTE_SWAP					BIT(16)
+#define OVL_BLD_CON_RGB_SWAP					BIT(17)
+#define DISP_REG_OVL_BLD_BGCLR_CLR			0x104
+#define DISP_REG_OVL_BLD_L_CON2				0x200
+#define OVL_BLD_L_ALPHA						GENMASK(7, 0)
+#define OVL_BLD_L_ALPHA_EN					BIT(12)
+#define DISP_REG_OVL_BLD_L0_PITCH			0x208
+#define OVL_BLD_L0_CONST					BIT(24)
+#define DISP_REG_OVL_BLD_L0_CLR				0x20c
+#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
+#define OVL_BLD_L0_SRC_PITCH					GENMASK(15, 0)
+#define DISP_REG_OVL_BLD_PITCH				0x2f4
+
+struct mtk_disp_blender {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct cmdq_client_reg	cmdq_reg;
+};
+
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+				   struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+	struct mtk_plane_pending_state *pending = &state->pending;
+	unsigned int align_width = ALIGN_DOWN(pending->width, 2);
+	unsigned int alpha;
+	unsigned int clrfmt;
+	unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
+							 BIT(DRM_MODE_BLEND_PREMULTI) |
+							 BIT(DRM_MODE_BLEND_COVERAGE) |
+							 BIT(DRM_MODE_BLEND_PIXEL_NONE));
+	unsigned int ignore_pixel_alpha = 0;
+
+	if (!pending->enable) {
+		mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+		return;
+	}
+
+	mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_OFFSET);
+
+	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+		      priv->regs, DISP_REG_OVL_BLD_SRC_SIZE);
+
+	clrfmt = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
+				     OVL_BLD_CON_CLRFMT_MAN, OVL_BLD_CON_BYTE_SWAP,
+				     OVL_BLD_CON_RGB_SWAP);
+	clrfmt |= mtk_ovl_is_10bit_rgb(pending->format) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0;
+	mtk_ddp_write_mask(cmdq_pkt, clrfmt, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_L0_CLRFMT, OVL_BLD_CON_CLRFMT_MAN |
+			   OVL_BLD_CON_RGB_SWAP |  OVL_BLD_CON_BYTE_SWAP |
+			   OVL_BLD_CON_FLD_CLRFMT | OVL_BLD_CON_FLD_CLRFMT_NB);
+
+	alpha = (OVL_BLD_ALPHA & (state->base.alpha >> 8)) |
+		OVL_BLD_L_ALPHA_EN;
+
+	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+		ignore_pixel_alpha = OVL_BLD_L0_CONST;
+
+	mtk_ddp_write_mask(cmdq_pkt, pending->pitch | ignore_pixel_alpha,
+			   &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_PITCH, OVL_BLD_L0_CONST | OVL_BLD_L0_SRC_PITCH);
+
+	mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
+
+	mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+}
+
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, bool most_top,
+			     bool most_bottom, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+	u32 datapath;
+
+	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_ROI_SIZE);
+	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_BGCLR_CLR);
+	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_L0_CLR);
+
+	if (most_top)
+		datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
+	else
+		datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
+	/*
+	 * The primary input is from EXDMA and the second input
+	 * is optionally from another blender
+	 */
+	if (!most_bottom)
+		datapath |= OVL_BLD_BGCLR_IN_SEL;
+
+	mtk_ddp_write_mask(cmdq_pkt, datapath,
+			   &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
+			   OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
+			   OVL_BLD_BGCLR_IN_SEL);
+}
+
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+	unsigned int tmp;
+
+	tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+	tmp = tmp | OVL_BLD_BYPASS_SHADOW;
+	writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+}
+
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+}
+
+int mtk_disp_blender_clk_enable(struct device *dev)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_blender_clk_disable(struct device *dev)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(priv->clk);
+}
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev)
+{
+	return BIT(DRM_MODE_BLEND_PREMULTI) |
+	       BIT(DRM_MODE_BLEND_COVERAGE) |
+	       BIT(DRM_MODE_BLEND_PIXEL_NONE);
+}
+
+static int mtk_disp_blender_bind(struct device *dev, struct device *master,
+				 void *data)
+{
+	return 0;
+}
+
+static void mtk_disp_blender_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_blender_component_ops = {
+	.bind	= mtk_disp_blender_bind,
+	.unbind = mtk_disp_blender_unbind,
+};
+
+static int mtk_disp_blender_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct mtk_disp_blender *priv;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->regs)) {
+		dev_err(dev, "failed to ioremap blender\n");
+		return PTR_ERR(priv->regs);
+	}
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get blender clk\n");
+		return PTR_ERR(priv->clk);
+	}
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+	if (ret)
+		dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+	platform_set_drvdata(pdev, priv);
+
+	ret = component_add(dev, &mtk_disp_blender_component_ops);
+	if (ret)
+		dev_notice(dev, "Failed to add component: %d\n", ret);
+
+	return ret;
+}
+
+static void mtk_disp_blender_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_blender_component_ops);
+}
+
+static const struct of_device_id mtk_disp_blender_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-blender"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_blender_driver_dt_match);
+
+struct platform_driver mtk_disp_blender_driver = {
+	.probe		= mtk_disp_blender_probe,
+	.remove		= mtk_disp_blender_remove,
+	.driver		= {
+		.name	= "mediatek-disp-blender",
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_disp_blender_driver_dt_match,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Blender Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.h b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
new file mode 100644
index 000000000000..be60a0f8de40
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_BLENDER_H__
+#define __MTK_DISP_BLENDER_H__
+
+enum mtk_disp_blender_layer {
+	FIRST_BLENDER,
+	LAST_BLENDER,
+	SINGLE_BLENDER,
+	OTHERS,
+	BLENDER_LAYER_MAX,
+};
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev);
+#endif // __MTK_DISP_BLENDER_H__
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 4e3d2510bef5..39e3af1e2b16 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -9,6 +9,7 @@
 #include <linux/soc/mediatek/mtk-cmdq.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 #include <linux/soc/mediatek/mtk-mutex.h>
+#include "mtk_disp_blender.h"
 #include "mtk_mdp_rdma.h"
 #include "mtk_plane.h"
 
@@ -39,6 +40,17 @@ void mtk_color_config(struct device *dev, unsigned int w,
 		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
 void mtk_color_start(struct device *dev);
 
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+int mtk_disp_blender_clk_enable(struct device *dev);
+void mtk_disp_blender_clk_disable(struct device *dev);
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, bool most_top, bool most_bottom,
+			     struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+				   struct cmdq_pkt *cmdq_pkt);
+
 int mtk_disp_exdma_clk_enable(struct device *dev);
 void mtk_disp_exdma_clk_disable(struct device *dev);
 void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index bb7306a942ff..7a14f45d5f97 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1274,6 +1274,7 @@ static struct platform_driver mtk_drm_platform_driver = {
 
 static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_aal_driver,
+	&mtk_disp_blender_driver,
 	&mtk_disp_ccorr_driver,
 	&mtk_disp_color_driver,
 	&mtk_disp_exdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 898a75898775..89178de1478f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -70,6 +70,7 @@ struct mtk_drm_private {
 };
 
 extern struct platform_driver mtk_disp_aal_driver;
+extern struct platform_driver mtk_disp_blender_driver;
 extern struct platform_driver mtk_disp_ccorr_driver;
 extern struct platform_driver mtk_disp_color_driver;
 extern struct platform_driver mtk_disp_exdma_driver;
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:41 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:41 +0800
Subject: [PATCH v2 12/15] drm/mediatek: add OUTPROC support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-13-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

OUTPROC handles the post-stage of pixel processing in
the overlapping procedure.OUTPROC manages pixels for
gamma correction and ensures that pixel values are
within the correct range.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/Makefile           |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c     |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h     |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h     |  14 ++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 242 ++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.h |  22 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |   1 +
 8 files changed, 283 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index a7b9ebe27f68..9546bc6b7b2e 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -10,6 +10,7 @@ mediatek-drm-y := mtk_crtc.o \
 		  mtk_disp_gamma.o \
 		  mtk_disp_merge.o \
 		  mtk_disp_ovl.o \
+		  mtk_disp_outproc.o \
 		  mtk_disp_ovl_adaptor.o \
 		  mtk_disp_rdma.o \
 		  mtk_drm_drv.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index e65c6df987f2..cc780744f060 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -447,6 +447,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DSI] = "dsi",
 	[MTK_OVL_BLENDER] = "blender",
 	[MTK_OVL_EXDMA] = "exdma",
+	[MTK_OVL_OUTPROC] = "outproc",
 };
 
 struct mtk_ddp_comp_match {
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 075ba5683f93..b33d3289b8b6 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -45,6 +45,7 @@ enum mtk_ddp_comp_type {
 	MTK_DSI,
 	MTK_OVL_BLENDER,
 	MTK_OVL_EXDMA,
+	MTK_OVL_OUTPROC,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 39e3af1e2b16..3c519a662074 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -64,6 +64,20 @@ void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
 			   unsigned int bpc, unsigned int cfg,
 			   unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
 
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+					 void (*vblank_cb)(void *),
+					 void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+
 void mtk_dpi_start(struct device *dev);
 void mtk_dpi_stop(struct device *dev);
 unsigned int mtk_dpi_encoder_index(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
new file mode 100644
index 000000000000..a7c6d1982bca
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_outproc.h"
+
+#define DISP_REG_OVL_OUTPROC_INTEN				0x004
+#define OVL_OUTPROC_FME_CPL_INTEN					BIT(1)
+#define DISP_REG_OVL_OUTPROC_INTSTA				0x008
+#define DISP_REG_OVL_OUTPROC_DATAPATH_CON			0x010
+#define OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP				BIT(26)
+
+#define DISP_REG_OVL_OUTPROC_EN					0x020
+#define OVL_OUTPROC_OVL_EN						BIT(0)
+#define DISP_REG_OVL_OUTPROC_RST				0x024
+#define OVL_OUTPROC_RST							BIT(0)
+#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL			0x028
+#define OVL_OUTPROC_BYPASS_SHADOW					BIT(2)
+#define DISP_REG_OVL_OUTPROC_ROI_SIZE				0x030
+
+struct mtk_disp_outproc {
+	void __iomem		*regs;
+	struct clk		*clk;
+	void			(*vblank_cb)(void *data);
+	void			*vblank_cb_data;
+	int			irq;
+	struct cmdq_client_reg	cmdq_reg;
+};
+
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+					 void (*vblank_cb)(void *),
+					 void *vblank_cb_data)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	priv->vblank_cb = vblank_cb;
+	priv->vblank_cb_data = vblank_cb_data;
+}
+
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	priv->vblank_cb = NULL;
+	priv->vblank_cb_data = NULL;
+}
+
+void mtk_disp_outproc_enable_vblank(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
+}
+
+void mtk_disp_outproc_disable_vblank(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
+}
+
+static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void *dev_id)
+{
+	struct mtk_disp_outproc *priv = dev_id;
+	u32 val;
+
+	val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+	if (!val)
+		return IRQ_NONE;
+
+	writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+
+	if (priv->vblank_cb)
+		priv->vblank_cb(priv->vblank_cb_data);
+
+	return IRQ_HANDLED;
+}
+
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+
+	//move mtk_ddp_write_mask to mtk_ddp_write
+	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_OUTPROC_ROI_SIZE);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP,
+			   &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_OUTPROC_DATAPATH_CON,
+			   OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
+}
+
+void mtk_disp_outproc_start(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+	unsigned int tmp;
+
+	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+	tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
+	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+
+	mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_OUTPROC_INTSTA);
+	mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+}
+
+void mtk_disp_outproc_stop(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+	mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+}
+
+int mtk_disp_outproc_clk_enable(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_outproc_clk_disable(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(priv->clk);
+}
+
+static int mtk_disp_outproc_bind(struct device *dev, struct device *master,
+				 void *data)
+{
+	return 0;
+}
+
+static void mtk_disp_outproc_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_outproc_component_ops = {
+	.bind	= mtk_disp_outproc_bind,
+	.unbind = mtk_disp_outproc_unbind,
+};
+
+static int mtk_disp_outproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_disp_outproc *priv;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->regs))
+		return dev_err_probe(dev, PTR_ERR(priv->regs), "failed to ioremap outproc\n");
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get outproc clk\n");
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+	if (ret)
+		dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+
+	if (of_property_read_u32_index(dev->of_node, "interrupts", 0, &ret)) {
+		dev_dbg(dev, "interrupts not defined\n");
+	} else {
+		priv->irq = platform_get_irq(pdev, 0);
+		if (priv->irq < 0)
+			priv->irq = 0;
+
+		if (priv->irq) {
+			ret = devm_request_irq(dev, priv->irq, mtk_disp_outproc_irq_handler,
+					       IRQF_TRIGGER_NONE, dev_name(dev), priv);
+			if (ret < 0) {
+				dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
+				return ret;
+			}
+		}
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	ret = component_add(dev, &mtk_disp_outproc_component_ops);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add component\n");
+
+	return ret;
+}
+
+static void mtk_disp_outproc_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_outproc_component_ops);
+}
+
+static const struct of_device_id mtk_disp_outproc_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-outproc"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_outproc_driver_dt_match);
+
+struct platform_driver mtk_disp_outproc_driver = {
+	.probe		= mtk_disp_outproc_probe,
+	.remove		= mtk_disp_outproc_remove,
+	.driver		= {
+		.name	= "mediatek-disp-outproc",
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_disp_outproc_driver_dt_match,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Output processing Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.h b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
new file mode 100644
index 000000000000..abb101979521
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OUTPROC_H__
+#define __MTK_DISP_OUTPROC_H__
+
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+					 void (*vblank_cb)(void *),
+					 void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 7a14f45d5f97..f7b9c7a982a7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1280,6 +1280,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_exdma_driver,
 	&mtk_disp_gamma_driver,
 	&mtk_disp_merge_driver,
+	&mtk_disp_outproc_driver,
 	&mtk_disp_ovl_adaptor_driver,
 	&mtk_disp_ovl_driver,
 	&mtk_disp_rdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 89178de1478f..c4717c37b0f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -76,6 +76,7 @@ extern struct platform_driver mtk_disp_color_driver;
 extern struct platform_driver mtk_disp_exdma_driver;
 extern struct platform_driver mtk_disp_gamma_driver;
 extern struct platform_driver mtk_disp_merge_driver;
+extern struct platform_driver mtk_disp_outproc_driver;
 extern struct platform_driver mtk_disp_ovl_adaptor_driver;
 extern struct platform_driver mtk_disp_ovl_driver;
 extern struct platform_driver mtk_disp_rdma_driver;
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:42 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:42 +0800
Subject: [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor support for MT8196
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-14-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

Ovlsys_adaptor is an encapsulated module designed to
simplify the DRM control flow. This module is composed
of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
Two EXDMAs merge into one layer, allowing the module
to support 20 layers for 3 display paths.
Ovlsys_adaptor driver is integrated within the
mtk_ddp_comp framework.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/Makefile             |   1 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       |  28 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  32 +
 .../drm/mediatek/mtk_disp_ovlsys_adaptor.c    | 797 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  73 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |  11 +-
 7 files changed, 942 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 9546bc6b7b2e..dedf50860d3f 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
 		  mtk_disp_exdma.o \
 		  mtk_disp_gamma.o \
 		  mtk_disp_merge.o \
+		  mtk_disp_ovlsys_adaptor.o \
 		  mtk_disp_ovl.o \
 		  mtk_disp_outproc.o \
 		  mtk_disp_ovl_adaptor.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index cc780744f060..c96e027359ac 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -368,6 +368,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
 	.get_num_formats = mtk_ovl_get_num_formats,
 };
 
+static const struct mtk_ddp_comp_funcs ddp_ovlsys_adaptor = {
+	.power_on = mtk_ovlsys_adaptor_power_on,
+	.power_off = mtk_ovlsys_adaptor_power_off,
+	.clk_enable = mtk_ovlsys_adaptor_clk_enable,
+	.clk_disable = mtk_ovlsys_adaptor_clk_disable,
+	.config = mtk_ovlsys_adaptor_config,
+	.start = mtk_ovlsys_adaptor_start,
+	.stop = mtk_ovlsys_adaptor_stop,
+	.layer_check = mtk_ovlsys_adaptor_layer_check,
+	.layer_nr = mtk_ovlsys_adaptor_layer_nr,
+	.layer_config = mtk_ovlsys_adaptor_layer_config,
+	.register_vblank_cb = mtk_ovlsys_adaptor_register_vblank_cb,
+	.unregister_vblank_cb = mtk_ovlsys_adaptor_unregister_vblank_cb,
+	.enable_vblank = mtk_ovlsys_adaptor_enable_vblank,
+	.disable_vblank = mtk_ovlsys_adaptor_disable_vblank,
+	.dma_dev_get = mtk_ovlsys_adaptor_dma_dev_get,
+	.connect = mtk_ovlsys_adaptor_connect,
+	.disconnect = mtk_ovlsys_adaptor_disconnect,
+	.add = mtk_ovlsys_adaptor_add_comp,
+	.remove = mtk_ovlsys_adaptor_remove_comp,
+	.get_blend_modes = mtk_ovlsys_adaptor_get_blend_modes,
+	.get_formats = mtk_ovlsys_adaptor_get_formats,
+	.get_num_formats = mtk_ovlsys_adaptor_get_num_formats,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_postmask = {
 	.clk_enable = mtk_ddp_clk_enable,
 	.clk_disable = mtk_ddp_clk_disable,
@@ -437,6 +462,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_OVL] = "ovl",
 	[MTK_DISP_OVL_2L] = "ovl-2l",
 	[MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
+	[MTK_DISP_OVLSYS_ADAPTOR] = "ovlsys_adaptor",
 	[MTK_DISP_POSTMASK] = "postmask",
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_RDMA] = "rdma",
@@ -469,6 +495,8 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_DPI0]		= { MTK_DPI,			0, &ddp_dpi },
 	[DDP_COMPONENT_DPI1]		= { MTK_DPI,			1, &ddp_dpi },
 	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= { MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DSC0]		= { MTK_DISP_DSC,		0, &ddp_dsc },
 	[DDP_COMPONENT_DSC1]		= { MTK_DISP_DSC,		1, &ddp_dsc },
 	[DDP_COMPONENT_DSI0]		= { MTK_DSI,			0, &ddp_dsi },
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index b33d3289b8b6..ef64ce7a071f 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -33,6 +33,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_MUTEX,
 	MTK_DISP_OD,
 	MTK_DISP_OVL,
+	MTK_DISP_OVLSYS_ADAPTOR,
 	MTK_DISP_OVL_2L,
 	MTK_DISP_OVL_ADAPTOR,
 	MTK_DISP_POSTMASK,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 3c519a662074..1ff8c4593fc1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -174,6 +174,38 @@ size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
 enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
 						const struct drm_display_mode *mode);
 
+int mtk_ovlsys_adaptor_power_on(struct device *dev);
+void mtk_ovlsys_adaptor_power_off(struct device *dev);
+void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev,
+				unsigned int next);
+void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
+				   unsigned int next);
+int mtk_ovlsys_adaptor_clk_enable(struct device *dev);
+void mtk_ovlsys_adaptor_clk_disable(struct device *dev);
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+			       unsigned int h, unsigned int vrefresh,
+			       unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
+				     struct mtk_plane_state *state,
+				     struct cmdq_pkt *cmdq_pkt);
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+				   unsigned int idx,
+				   struct mtk_plane_state *mtk_state);
+void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
+					   void *vblank_cb_data);
+void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev);
+void mtk_ovlsys_adaptor_enable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_disable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_start(struct device *dev);
+void mtk_ovlsys_adaptor_stop(struct device *dev);
+unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev);
+struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev);
+u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev);
+const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev);
+size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev);
+
 void mtk_rdma_bypass_shadow(struct device *dev);
 int mtk_rdma_clk_enable(struct device *dev);
 void mtk_rdma_clk_disable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
new file mode 100644
index 000000000000..04cb555bd77b
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
@@ -0,0 +1,797 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_of.h>
+#include <drm/drm_print.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+#include <linux/soc/mediatek/mtk-mutex.h>
+
+#include "mtk_disp_blender.h"
+#include "mtk_disp_drv.h"
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include "mtk_drm_drv.h"
+
+#define OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE 8191
+
+enum mtk_ovlsys_adaptor_comp_type {
+	OVLSYS_ADAPTOR_TYPE_EXDMA = 0,
+	OVLSYS_ADAPTOR_TYPE_BLENDER,
+	OVLSYS_ADAPTOR_TYPE_OUTPROC,
+	OVLSYS_ADAPTOR_TYPE_NUM,
+};
+
+enum mtk_ovlsys_adaptor_comp_id {
+	OVLSYS_ADAPTOR_EXDMA0,
+	OVLSYS_ADAPTOR_EXDMA1,
+	OVLSYS_ADAPTOR_EXDMA2,
+	OVLSYS_ADAPTOR_EXDMA3,
+	OVLSYS_ADAPTOR_EXDMA4,
+	OVLSYS_ADAPTOR_EXDMA5,
+	OVLSYS_ADAPTOR_EXDMA6,
+	OVLSYS_ADAPTOR_EXDMA7,
+	OVLSYS_ADAPTOR_EXDMA8,
+	OVLSYS_ADAPTOR_EXDMA9,
+	OVLSYS_ADAPTOR_EXDMA10,
+	OVLSYS_ADAPTOR_EXDMA11,
+	OVLSYS_ADAPTOR_EXDMA12,
+	OVLSYS_ADAPTOR_EXDMA13,
+	OVLSYS_ADAPTOR_EXDMA14,
+	OVLSYS_ADAPTOR_EXDMA15,
+	OVLSYS_ADAPTOR_EXDMA16,
+	OVLSYS_ADAPTOR_EXDMA17,
+	OVLSYS_ADAPTOR_EXDMA18,
+	OVLSYS_ADAPTOR_EXDMA19,
+	OVLSYS_ADAPTOR_BLENDER0,
+	OVLSYS_ADAPTOR_BLENDER1,
+	OVLSYS_ADAPTOR_BLENDER2,
+	OVLSYS_ADAPTOR_BLENDER3,
+	OVLSYS_ADAPTOR_BLENDER4,
+	OVLSYS_ADAPTOR_BLENDER5,
+	OVLSYS_ADAPTOR_BLENDER6,
+	OVLSYS_ADAPTOR_BLENDER7,
+	OVLSYS_ADAPTOR_BLENDER8,
+	OVLSYS_ADAPTOR_BLENDER9,
+	OVLSYS_ADAPTOR_BLENDER10,
+	OVLSYS_ADAPTOR_BLENDER11,
+	OVLSYS_ADAPTOR_BLENDER12,
+	OVLSYS_ADAPTOR_BLENDER13,
+	OVLSYS_ADAPTOR_BLENDER14,
+	OVLSYS_ADAPTOR_BLENDER15,
+	OVLSYS_ADAPTOR_BLENDER16,
+	OVLSYS_ADAPTOR_BLENDER17,
+	OVLSYS_ADAPTOR_BLENDER18,
+	OVLSYS_ADAPTOR_BLENDER19,
+	OVLSYS_ADAPTOR_OUTPROC0,
+	OVLSYS_ADAPTOR_OUTPROC1,
+	OVLSYS_ADAPTOR_OUTPROC2,
+	OVLSYS_ADAPTOR_OUTPROC3,
+	OVLSYS_ADAPTOR_OUTPROC4,
+	OVLSYS_ADAPTOR_OUTPROC5,
+	OVLSYS_ADAPTOR_OUTPROC6,
+	OVLSYS_ADAPTOR_OUTPROC7,
+	OVLSYS_ADAPTOR_OUTPROC8,
+	OVLSYS_ADAPTOR_OUTPROC9,
+	OVLSYS_ADAPTOR_OUTPROC10,
+	OVLSYS_ADAPTOR_OUTPROC11,
+	OVLSYS_ADAPTOR_ID_MAX
+};
+
+struct ovlsys_adaptor_comp_match {
+	enum mtk_ovlsys_adaptor_comp_type type;
+	int alias_id;
+	enum mtk_ddp_comp_id comp_id;
+};
+
+struct mtk_disp_ovlsys_adaptor {
+	struct device *ovl_adaptor_comp[OVLSYS_ADAPTOR_ID_MAX];
+	struct device *mmsys_dev;
+	const unsigned int *path;
+	unsigned int path_size;
+	unsigned int layer_nr;
+	bool children_bound;
+	unsigned int max_size;
+};
+
+static const char * const private_comp_stem[OVLSYS_ADAPTOR_TYPE_NUM] = {
+	[OVLSYS_ADAPTOR_TYPE_EXDMA]	= "exdma",
+	[OVLSYS_ADAPTOR_TYPE_BLENDER]	= "blender",
+	[OVLSYS_ADAPTOR_TYPE_OUTPROC]	= "outproc",
+};
+
+static const struct ovlsys_adaptor_comp_match comp_matches[OVLSYS_ADAPTOR_ID_MAX] = {
+	[OVLSYS_ADAPTOR_EXDMA0]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 0, DDP_COMPONENT_ID_MAX},
+	[OVLSYS_ADAPTOR_EXDMA1]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 1, DDP_COMPONENT_ID_MAX},
+	[OVLSYS_ADAPTOR_EXDMA2]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 2, DDP_COMPONENT_OVL0_EXDMA2},
+	[OVLSYS_ADAPTOR_EXDMA3]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 3, DDP_COMPONENT_OVL0_EXDMA3},
+	[OVLSYS_ADAPTOR_EXDMA4]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 4, DDP_COMPONENT_OVL0_EXDMA4},
+	[OVLSYS_ADAPTOR_EXDMA5]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 5, DDP_COMPONENT_OVL0_EXDMA5},
+	[OVLSYS_ADAPTOR_EXDMA6]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 6, DDP_COMPONENT_OVL0_EXDMA6},
+	[OVLSYS_ADAPTOR_EXDMA7]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 7, DDP_COMPONENT_OVL0_EXDMA7},
+	[OVLSYS_ADAPTOR_EXDMA8]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 8, DDP_COMPONENT_OVL0_EXDMA8},
+	[OVLSYS_ADAPTOR_EXDMA9]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 9, DDP_COMPONENT_OVL0_EXDMA9},
+	[OVLSYS_ADAPTOR_EXDMA12]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 12, DDP_COMPONENT_OVL1_EXDMA2},
+	[OVLSYS_ADAPTOR_EXDMA13]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 13, DDP_COMPONENT_OVL1_EXDMA3},
+	[OVLSYS_ADAPTOR_EXDMA14]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 14, DDP_COMPONENT_OVL1_EXDMA4},
+	[OVLSYS_ADAPTOR_EXDMA15]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 15, DDP_COMPONENT_OVL1_EXDMA5},
+	[OVLSYS_ADAPTOR_EXDMA16]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 16, DDP_COMPONENT_OVL1_EXDMA6},
+	[OVLSYS_ADAPTOR_EXDMA17]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 17, DDP_COMPONENT_OVL1_EXDMA7},
+	[OVLSYS_ADAPTOR_EXDMA18]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 18, DDP_COMPONENT_OVL1_EXDMA8},
+	[OVLSYS_ADAPTOR_EXDMA19]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 19, DDP_COMPONENT_OVL1_EXDMA9},
+	[OVLSYS_ADAPTOR_BLENDER1] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 1, DDP_COMPONENT_OVL0_BLENDER1},
+	[OVLSYS_ADAPTOR_BLENDER2] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 2, DDP_COMPONENT_OVL0_BLENDER2},
+	[OVLSYS_ADAPTOR_BLENDER3] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 3, DDP_COMPONENT_OVL0_BLENDER3},
+	[OVLSYS_ADAPTOR_BLENDER4] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 4, DDP_COMPONENT_OVL0_BLENDER4},
+	[OVLSYS_ADAPTOR_BLENDER5] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 5, DDP_COMPONENT_OVL0_BLENDER5},
+	[OVLSYS_ADAPTOR_BLENDER6] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 6, DDP_COMPONENT_OVL0_BLENDER6},
+	[OVLSYS_ADAPTOR_BLENDER7] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 7, DDP_COMPONENT_OVL0_BLENDER7},
+	[OVLSYS_ADAPTOR_BLENDER8] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 8, DDP_COMPONENT_OVL0_BLENDER8},
+	[OVLSYS_ADAPTOR_BLENDER9] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 9, DDP_COMPONENT_OVL0_BLENDER9},
+	[OVLSYS_ADAPTOR_BLENDER11] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 11, DDP_COMPONENT_OVL1_BLENDER1},
+	[OVLSYS_ADAPTOR_BLENDER12] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 12, DDP_COMPONENT_OVL1_BLENDER2},
+	[OVLSYS_ADAPTOR_BLENDER13] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 13, DDP_COMPONENT_OVL1_BLENDER3},
+	[OVLSYS_ADAPTOR_BLENDER14] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 14, DDP_COMPONENT_OVL1_BLENDER4},
+	[OVLSYS_ADAPTOR_BLENDER15] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 15, DDP_COMPONENT_OVL1_BLENDER5},
+	[OVLSYS_ADAPTOR_BLENDER16] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 16, DDP_COMPONENT_OVL1_BLENDER6},
+	[OVLSYS_ADAPTOR_BLENDER17] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 17, DDP_COMPONENT_OVL1_BLENDER7},
+	[OVLSYS_ADAPTOR_BLENDER18] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 18, DDP_COMPONENT_OVL1_BLENDER8},
+	[OVLSYS_ADAPTOR_BLENDER19] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 19, DDP_COMPONENT_OVL1_BLENDER9},
+	[OVLSYS_ADAPTOR_OUTPROC0] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 0, DDP_COMPONENT_OVL0_OUTPROC0},
+	[OVLSYS_ADAPTOR_OUTPROC1] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 1, DDP_COMPONENT_OVL0_OUTPROC1},
+	[OVLSYS_ADAPTOR_OUTPROC6] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 6, DDP_COMPONENT_OVL1_OUTPROC0},
+};
+
+static const unsigned int mt8196_mtk_ovl_main[] = {
+	OVLSYS_ADAPTOR_EXDMA2,
+	OVLSYS_ADAPTOR_BLENDER1,
+	OVLSYS_ADAPTOR_EXDMA3,
+	OVLSYS_ADAPTOR_BLENDER2,
+	OVLSYS_ADAPTOR_EXDMA4,
+	OVLSYS_ADAPTOR_BLENDER3,
+	OVLSYS_ADAPTOR_EXDMA5,
+	OVLSYS_ADAPTOR_BLENDER4,
+	OVLSYS_ADAPTOR_OUTPROC0,
+};
+
+static const unsigned int mt8196_mtk_ovl_ext[] = {
+	OVLSYS_ADAPTOR_EXDMA6,
+	OVLSYS_ADAPTOR_BLENDER5,
+	OVLSYS_ADAPTOR_EXDMA7,
+	OVLSYS_ADAPTOR_BLENDER6,
+	OVLSYS_ADAPTOR_EXDMA8,
+	OVLSYS_ADAPTOR_BLENDER7,
+	OVLSYS_ADAPTOR_EXDMA9,
+	OVLSYS_ADAPTOR_BLENDER8,
+	OVLSYS_ADAPTOR_OUTPROC1,
+};
+
+static const unsigned int mt8196_mtk_ovl_third[] = {
+	OVLSYS_ADAPTOR_EXDMA12,
+	OVLSYS_ADAPTOR_BLENDER11,
+	OVLSYS_ADAPTOR_EXDMA13,
+	OVLSYS_ADAPTOR_BLENDER12,
+	OVLSYS_ADAPTOR_EXDMA14,
+	OVLSYS_ADAPTOR_BLENDER13,
+	OVLSYS_ADAPTOR_EXDMA15,
+	OVLSYS_ADAPTOR_BLENDER14,
+	OVLSYS_ADAPTOR_OUTPROC6,
+};
+
+static enum mtk_ovlsys_adaptor_comp_type get_type(enum mtk_ovlsys_adaptor_comp_id id)
+{
+	return comp_matches[id].type;
+}
+
+static enum mtk_ddp_comp_id get_ddp_comp_id(enum mtk_ovlsys_adaptor_comp_id id)
+{
+	return comp_matches[id].comp_id;
+}
+
+static struct device *get_comp_by_type_idx(struct device *dev,
+					   enum mtk_ovlsys_adaptor_comp_type type,
+					   unsigned int idx)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+	int count = 0;
+
+	for (i = 0; i < priv->path_size; i++) {
+		if (get_type(priv->path[i]) == type) {
+			if (count == idx)
+				return priv->ovl_adaptor_comp[priv->path[i]];
+			count++;
+		}
+	}
+	return NULL;
+}
+
+int mtk_ovlsys_adaptor_power_on(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+		comp = priv->ovl_adaptor_comp[i];
+
+		if (!comp)
+			continue;
+
+		if (get_type(i) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+			continue;
+
+		ret = pm_runtime_get_sync(comp);
+		if (ret < 0) {
+			dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
+			goto pwr_err;
+		}
+	}
+
+	return ret;
+pwr_err:
+	while (--i >= 0) {
+		comp = priv->ovl_adaptor_comp[i];
+		if (!comp)
+			continue;
+		if (get_type(i) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+			continue;
+		pm_runtime_put(priv->ovl_adaptor_comp[i]);
+	}
+
+	return ret;
+}
+
+void mtk_ovlsys_adaptor_power_off(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int i;
+
+	for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+		comp = priv->ovl_adaptor_comp[i];
+
+		if (!comp)
+			continue;
+
+		if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			pm_runtime_put(comp);
+	}
+}
+
+void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
+				     struct mtk_plane_state *state,
+				     struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_plane_pending_state *pending = &state->pending;
+	struct device *exdma;
+	struct device *blender;
+	unsigned int align_width = 0;
+	const struct drm_format_info *fmt_info = drm_format_info(pending->format);
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	DRM_DEV_DEBUG_DRIVER(dev, "idx:%d enable:%d fmt:0x%x addr:0x%pad fb_w:%d {%d,%d,%d,%d}\n",
+			     idx, pending->enable, pending->format,
+			     &pending->addr, (pending->pitch / fmt_info->cpp[0]),
+			     pending->x, pending->y, pending->width, pending->height);
+
+	exdma = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_EXDMA, idx);
+	if (!exdma) {
+		dev_err(dev, "%s: exdma%d comp not found\n", __func__, idx);
+		return;
+	}
+	blender = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
+	if (!blender) {
+		dev_err(dev, "%s: blender%d comp not found\n", __func__, idx);
+		return;
+	}
+
+	/* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
+	align_width = ALIGN_DOWN(pending->width, 2);
+
+	if (pending->height == 0 || align_width == 0 ||
+	    pending->x > priv->max_size || pending->y > priv->max_size) {
+		pending->enable = false;
+		mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
+		mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+		return;
+	}
+
+	mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
+
+	mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+
+	mtk_disp_exdma_start(exdma, cmdq_pkt);
+	mtk_disp_blender_start(blender, cmdq_pkt);
+}
+
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+			       unsigned int h, unsigned int vrefresh,
+			       unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+	int blender_idx = 0;
+	bool most_top;
+	bool most_bottom;
+
+	for (i = 0; i < priv->path_size; i++) {
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+			blender_idx++;
+
+			if (priv->layer_nr == 1) {
+				most_top    = true;	/*SINGLE_BLENDER;*/
+				most_bottom = false;	/*blender is LAST_BLENDER*/
+			} else if (blender_idx == 1) {
+				most_top    = false;	/* NON-SINGLE LAYER */
+				most_bottom = true;	/* FIRST LAYER */
+			} else if (blender_idx == priv->layer_nr) {
+				most_top    = true;	/* NON-SINGLE LAYER */
+				most_bottom = false;	/* LAST LAYER */
+			} else {
+				most_top = false;	/* NON-SINGLE LAYER */
+				most_bottom = false;	/* OTHER LAYER */
+			}
+
+			mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+						vrefresh, bpc, most_top, most_bottom, cmdq_pkt);
+		} else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_OUTPROC) {
+			mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+						vrefresh, bpc, cmdq_pkt);
+		}
+	}
+}
+
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+				   unsigned int idx,
+				   struct mtk_plane_state *mtk_state)
+{
+	struct drm_plane_state *state = &mtk_state->base;
+
+	/* Check if any unsupported rotation is set */
+	if (state->rotation & ~DRM_MODE_ROTATE_0)
+		return -EINVAL;
+
+	return 0;
+}
+
+void mtk_ovlsys_adaptor_start(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		else
+			mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);
+	}
+}
+
+void mtk_ovlsys_adaptor_stop(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		else
+			mtk_disp_outproc_stop(priv->ovl_adaptor_comp[priv->path[i]]);
+	}
+}
+
+int mtk_ovlsys_adaptor_clk_enable(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+		comp = priv->ovl_adaptor_comp[i];
+
+		if (!comp)
+			continue;
+
+		if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			ret = mtk_disp_exdma_clk_enable(comp);
+		else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			ret = mtk_disp_blender_clk_enable(comp);
+		else
+			ret = mtk_disp_outproc_clk_enable(comp);
+
+		if (ret) {
+			dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
+			goto clk_err;
+		}
+	}
+
+	return ret;
+
+clk_err:
+	while (--i >= 0) {
+		comp = priv->ovl_adaptor_comp[i];
+		if (!comp)
+			continue;
+		if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_clk_disable(comp);
+		else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_clk_disable(comp);
+		else
+			mtk_disp_outproc_clk_disable(comp);
+	}
+	i = OVLSYS_ADAPTOR_ID_MAX;
+
+	return ret;
+}
+
+void mtk_ovlsys_adaptor_clk_disable(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int i;
+
+	for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+		comp = priv->ovl_adaptor_comp[i];
+
+		if (!comp)
+			continue;
+
+		if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_clk_disable(comp);
+		else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_clk_disable(comp);
+		else
+			mtk_disp_outproc_clk_disable(comp);
+	}
+}
+
+unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return priv->layer_nr;
+}
+
+struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return priv->ovl_adaptor_comp[priv->path[0]];
+}
+
+void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
+					   void *vblank_cb_data)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_register_vblank_cb(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]],
+					    vblank_cb, vblank_cb_data);
+}
+
+void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp = priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]];
+
+	mtk_disp_outproc_unregister_vblank_cb(comp);
+}
+
+void mtk_ovlsys_adaptor_enable_vblank(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_enable_vblank(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]]);
+}
+
+void mtk_ovlsys_adaptor_disable_vblank(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_disable_vblank(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]]);
+}
+
+u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++)
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+			comp = priv->ovl_adaptor_comp[priv->path[i]];
+			return mtk_disp_blender_get_blend_modes(comp);
+		}
+
+	return 0;
+}
+
+const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return mtk_disp_exdma_get_formats(priv->ovl_adaptor_comp[priv->path[0]]);
+}
+
+size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return mtk_disp_exdma_get_num_formats(priv->ovl_adaptor_comp[priv->path[0]]);
+}
+
+void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++)
+		mtk_mutex_add_comp(mutex, get_ddp_comp_id(priv->path[i]));
+}
+
+void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++)
+		mtk_mutex_remove_comp(mutex, get_ddp_comp_id(priv->path[i]));
+}
+
+void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev, unsigned int next)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size - 1; i++)
+		mtk_mmsys_ddp_connect(mmsys_dev, get_ddp_comp_id(priv->path[i]),
+				      get_ddp_comp_id(priv->path[i + 1]));
+
+	mtk_mmsys_ddp_connect(mmsys_dev, get_ddp_comp_id(priv->path[i]), next);
+}
+
+void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev, unsigned int next)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size - 1; i++)
+		mtk_mmsys_ddp_disconnect(mmsys_dev, get_ddp_comp_id(priv->path[i]),
+					 get_ddp_comp_id(priv->path[i + 1]));
+
+	mtk_mmsys_ddp_disconnect(mmsys_dev, get_ddp_comp_id(priv->path[i]), next);
+}
+
+static int ovlsys_adaptor_comp_get_id(struct device *dev, struct device_node *node,
+				      enum mtk_ovlsys_adaptor_comp_type type,
+				      enum mtk_ddp_comp_id *comp_id)
+{
+	int alias_id = of_alias_get_id(node, private_comp_stem[type]);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(comp_matches); i++)
+		if (comp_matches[i].type == type &&
+		    comp_matches[i].alias_id == alias_id) {
+			*comp_id = comp_matches[i].comp_id;
+			return i;
+		}
+	dev_warn(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id);
+	return -EINVAL;
+}
+
+static const struct of_device_id mtk_ovlsys_adaptor_comp_dt_ids[] = {
+	{
+		.compatible = "mediatek,mt8196-exdma",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_EXDMA,
+	}, {
+		.compatible = "mediatek,mt8196-blender",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_BLENDER,
+	}, {
+		.compatible = "mediatek,mt8196-outproc",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_OUTPROC,
+	},
+	{},
+};
+
+static int ovlsys_adaptor_comp_init(struct device *dev, struct component_match **match)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device_node *node, *parent;
+	struct platform_device *comp_pdev;
+	int i;
+
+	parent = dev->parent->parent->of_node->parent;
+
+	for_each_child_of_node(parent, node) {
+		const struct of_device_id *of_id;
+		enum mtk_ovlsys_adaptor_comp_type type;
+		enum mtk_ddp_comp_id comp_id;
+		int id;
+		bool found = false;
+
+		of_id = of_match_node(mtk_ovlsys_adaptor_comp_dt_ids, node);
+		if (!of_id)
+			continue;
+
+		if (!of_device_is_available(node)) {
+			dev_dbg(dev, "Skipping disabled component %pOF\n",
+				node);
+			continue;
+		}
+
+		type = (enum mtk_ovlsys_adaptor_comp_type)(uintptr_t)of_id->data;
+		id = ovlsys_adaptor_comp_get_id(dev, node, type, &comp_id);
+		if (id < 0) {
+			dev_warn(dev, "Skipping unknown component %pOF\n",
+				 node);
+			continue;
+		}
+
+		for (i = 0; i < priv->path_size; i++)
+			if (priv->path[i] == id)
+				found = true;
+
+		if (!found)
+			continue;
+
+		comp_pdev = of_find_device_by_node(node);
+		if (!comp_pdev)
+			return -EPROBE_DEFER;
+
+		priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
+
+		drm_of_component_match_add(dev, match, component_compare_of, node);
+		dev_dbg(dev, "Adding component match for %pOF\n", node);
+	}
+
+	if (!*match) {
+		dev_err(dev, "No match device for ovlsys_adaptor\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int mtk_disp_ovlsys_adaptor_comp_bind(struct device *dev, struct device *master,
+					     void *data)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	if (!priv->children_bound)
+		return -EPROBE_DEFER;
+
+	return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_comp_unbind(struct device *dev, struct device *master,
+						void *data)
+{
+}
+
+static const struct component_ops mtk_disp_ovlsys_adaptor_comp_ops = {
+	.bind	= mtk_disp_ovlsys_adaptor_comp_bind,
+	.unbind = mtk_disp_ovlsys_adaptor_comp_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int ret, i;
+	unsigned int layer_nr = 0;
+
+	ret = component_bind_all(dev, priv->mmsys_dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "component_bind_all failed!\n");
+
+	priv->children_bound = true;
+
+	for (i = 0; i < priv->path_size; i++)
+		if (comp_matches[priv->path[i]].type == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			layer_nr++;
+	priv->layer_nr = layer_nr;
+
+	return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_master_unbind(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	priv->children_bound = false;
+}
+
+static const struct component_master_ops mtk_disp_ovlsys_adaptor_master_ops = {
+	.bind		= mtk_disp_ovlsys_adaptor_master_bind,
+	.unbind		= mtk_disp_ovlsys_adaptor_master_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_probe(struct platform_device *pdev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv;
+	struct device *dev = &pdev->dev;
+	struct component_match *match = NULL;
+	struct mtk_ovlsys_platform_data *ovlsys_priv; //mtk_drm_ovlsys_private
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	ovlsys_priv = pdev->dev.platform_data;
+	priv->mmsys_dev = ovlsys_priv->mmsys_dev;
+	priv->max_size = OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE;
+
+	if (ovlsys_priv->use_path == CRTC_MAIN) {
+		priv->path = mt8196_mtk_ovl_main;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
+	} else if (ovlsys_priv->use_path == CRTC_EXT) {
+		priv->path = mt8196_mtk_ovl_ext;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
+	} else if (ovlsys_priv->use_path == CRTC_THIRD) {
+		priv->path = mt8196_mtk_ovl_third;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_third);
+	}
+
+	ret = ovlsys_adaptor_comp_init(dev, &match);
+	if (ret < 0)
+		return ret;
+
+	component_master_add_with_match(dev, &mtk_disp_ovlsys_adaptor_master_ops, match);
+
+	pm_runtime_enable(dev);
+
+	ret = component_add(dev, &mtk_disp_ovlsys_adaptor_comp_ops);
+	if (ret != 0) {
+		pm_runtime_disable(dev);
+		dev_err(dev, "Failed to add component: %d\n", ret);
+	}
+
+	return ret;
+}
+
+static void mtk_disp_ovlsys_adaptor_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &mtk_disp_ovlsys_adaptor_master_ops);
+	pm_runtime_disable(&pdev->dev);
+}
+
+struct platform_driver mtk_disp_ovlsys_adaptor_driver = {
+	.probe		= mtk_disp_ovlsys_adaptor_probe,
+	.remove		= mtk_disp_ovlsys_adaptor_remove,
+	.driver		= {
+		.name	= "mediatek-disp-ovlsys-adaptor",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin at mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Ovlsys Adaptor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index f7b9c7a982a7..0639201e2e92 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -457,6 +457,27 @@ static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id
 	return false;
 }
 
+static int mtk_drm_mmsys_comp_in_path(struct mtk_drm_private *private, int comp_id)
+{
+	const struct mtk_mmsys_driver_data *drv_data = private->data;
+	int i;
+
+	if (drv_data->main_path)
+		for (i = 0; i < drv_data->main_len; i++)
+			if (drv_data->main_path[i] == comp_id)
+				return CRTC_MAIN;
+	if (drv_data->ext_path)
+		for (i = 0; i < drv_data->ext_len; i++)
+			if (drv_data->ext_path[i] == comp_id)
+				return CRTC_EXT;
+	if (drv_data->third_path)
+		for (i = 0; i < drv_data->third_len; i++)
+			if (drv_data->third_path[i] == comp_id)
+				return CRTC_THIRD;
+
+	return -EINVAL;
+}
+
 static int mtk_drm_kms_init(struct drm_device *drm)
 {
 	struct mtk_drm_private *private = drm->dev_private;
@@ -1122,6 +1143,57 @@ static int mtk_drm_probe(struct platform_device *pdev)
 		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
 	}
 
+	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0)) {
+		struct mtk_ovlsys_platform_data ovlsys_priv;
+
+		ovlsys_priv.mmsys_dev = private->mmsys_dev;
+		ovlsys_priv.use_path =
+		mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
+		ovl_adaptor =
+			platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+						      PLATFORM_DEVID_AUTO,
+						      (void *)&ovlsys_priv,
+						      sizeof(struct mtk_ovlsys_platform_data));
+		private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0].dev = &ovl_adaptor->dev;
+		mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0],
+				  DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
+		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+	}
+
+	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1)) {
+		struct mtk_ovlsys_platform_data ovlsys_priv; //mtk_drm_ovlsys_private
+
+		ovlsys_priv.mmsys_dev = private->mmsys_dev;
+		ovlsys_priv.use_path =
+		mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
+		ovl_adaptor =
+			platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+						      PLATFORM_DEVID_AUTO,
+						      (void *)&ovlsys_priv,
+						      sizeof(struct mtk_ovlsys_platform_data));
+		private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1].dev = &ovl_adaptor->dev;
+		mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1],
+				  DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
+		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+	}
+
+	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2)) {
+		struct mtk_ovlsys_platform_data ovlsys_priv;
+
+		ovlsys_priv.mmsys_dev = private->mmsys_dev;
+		ovlsys_priv.use_path =
+			mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+		ovl_adaptor =
+			platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+						      PLATFORM_DEVID_AUTO,
+						      (void *)&ovlsys_priv,
+						      sizeof(struct  mtk_ovlsys_platform_data));
+		private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2].dev = &ovl_adaptor->dev;
+		mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2],
+				  DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+	}
+
 	/* Iterate over sibling DISP function blocks */
 	for_each_child_of_node(phandle->parent, node) {
 		enum mtk_ddp_comp_type comp_type;
@@ -1283,6 +1355,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_outproc_driver,
 	&mtk_disp_ovl_adaptor_driver,
 	&mtk_disp_ovl_driver,
+	&mtk_disp_ovlsys_adaptor_driver,
 	&mtk_disp_rdma_driver,
 	&mtk_dpi_driver,
 	&mtk_drm_platform_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index c4717c37b0f1..6e9ed9837c5b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -11,7 +11,9 @@
 
 #define MAX_CONNECTOR	2
 #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
 
 enum mtk_crtc_path {
 	CRTC_MAIN,
@@ -69,6 +71,12 @@ struct mtk_drm_private {
 	struct mtk_drm_private **all_drm_private;
 };
 
+struct mtk_ovlsys_platform_data {//mtk_drm_ovlsys_private
+	struct device *mmsys_dev;
+	struct device *mutex_dev;
+	unsigned int use_path;
+};
+
 extern struct platform_driver mtk_disp_aal_driver;
 extern struct platform_driver mtk_disp_blender_driver;
 extern struct platform_driver mtk_disp_ccorr_driver;
@@ -79,6 +87,7 @@ extern struct platform_driver mtk_disp_merge_driver;
 extern struct platform_driver mtk_disp_outproc_driver;
 extern struct platform_driver mtk_disp_ovl_adaptor_driver;
 extern struct platform_driver mtk_disp_ovl_driver;
+extern struct platform_driver mtk_disp_ovlsys_adaptor_driver;
 extern struct platform_driver mtk_disp_rdma_driver;
 extern struct platform_driver mtk_dpi_driver;
 extern struct platform_driver mtk_dsi_driver;
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:43 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:43 +0800
Subject: [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-15-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

To support multiple mmsys instances in the one mediatek-drm instance,
providing improved flexibility and scalability by the following changes:

1. Add DDP_COMPONENT_DRM_OVLSYS_ADAPTOR* to probe the
  ovlsys_adaptor drivers and support different mmsys composition.
2. Added new component types MTK_DISP_VIRTUAL to support the
  routing to virtual display components.
3. Added and adjusted the existed structure or interface to extend
  the support of multiple mmsys instances.
4. Modified the component matching and binding logic to support
  multiple mmsys instances.

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_crtc.c     | 342 +++++++++++++++++++-----
 drivers/gpu/drm/mediatek/mtk_crtc.h     |   6 +-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 102 +++----
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  86 +++---
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  16 +-
 6 files changed, 392 insertions(+), 162 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index 8f6fba4217ec..4f91ffdd08ae 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -58,13 +58,17 @@ struct mtk_crtc {
 	wait_queue_head_t		cb_blocking_queue;
 #endif
 
-	struct device			*mmsys_dev;
+	struct device			*mmsys_dev[MAX_MMSYS];
 	struct device			*dma_dev;
-	struct mtk_mutex		*mutex;
+	struct device			*vdisp_ao_dev;
+	struct mtk_mutex		*mutex[MAX_MMSYS];
 	unsigned int			ddp_comp_nr;
 	struct mtk_ddp_comp		**ddp_comp;
+	enum mtk_drm_mmsys		*ddp_comp_sys;
+	bool				exist[MAX_MMSYS];
 	unsigned int			num_conn_routes;
 	const struct mtk_drm_route	*conn_routes;
+	enum mtk_drm_mmsys		conn_routes_sys;
 
 	/* lock for display hardware access */
 	struct mutex			hw_lock;
@@ -82,6 +86,11 @@ struct mtk_crtc_state {
 	unsigned int			pending_vrefresh;
 };
 
+struct mtk_crtc_comp_info {
+	enum mtk_drm_mmsys sys;
+	unsigned int comp_id;
+};
+
 static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
 {
 	return container_of(c, struct mtk_crtc, base);
@@ -130,7 +139,10 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	int i;
 
-	mtk_mutex_put(mtk_crtc->mutex);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->mutex[i])
+			mtk_mutex_put(mtk_crtc->mutex[i]);
+
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	if (mtk_crtc->cmdq_client.chan) {
 		cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
@@ -228,7 +240,14 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
 	int i;
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		enum mtk_drm_mmsys mmsys;
+
 		ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+			mmsys = mtk_crtc->ddp_comp_sys[i];
+			ret = mtk_mmsys_ddp_clk_enable(mtk_crtc->mmsys_dev[mmsys],
+						       mtk_crtc->ddp_comp[i]->id);
+		}
 		if (ret) {
 			DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
 			goto err;
@@ -237,17 +256,28 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
 
 	return 0;
 err:
-	while (--i >= 0)
+	while (--i >= 0) {
 		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL)
+			mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+						  mtk_crtc->ddp_comp[i]->id);
+	}
 	return ret;
 }
 
 static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
 {
 	int i;
+	enum mtk_drm_mmsys mmsys;
 
-	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+			mmsys = mtk_crtc->ddp_comp_sys[i];
+			mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mmsys],
+						  mtk_crtc->ddp_comp[i]->id);
+		}
+	}
 }
 
 static
@@ -340,7 +370,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 	struct drm_connector_list_iter conn_iter;
 	unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
 	int ret;
-	int i;
+	int i, j;
+	enum mtk_drm_mmsys mmsys;
 
 	if (WARN_ON(!crtc->state))
 		return -EINVAL;
@@ -370,10 +401,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		return ret;
 	}
 
-	ret = mtk_mutex_prepare(mtk_crtc->mutex);
-	if (ret < 0) {
-		DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
-		goto err_pm_runtime_put;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_top_clk_enable(mtk_crtc->mmsys_dev[i]);
+
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
+			continue;
+		ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
+		if (ret < 0) {
+			DRM_ERROR("Failed to enable mmsys%d mutex clock: %d\n", i, ret);
+			goto err_pm_runtime_put;
+		}
 	}
 
 	ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
@@ -382,19 +421,36 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		goto err_mutex_unprepare;
 	}
 
+	if (mtk_crtc->vdisp_ao_dev)
+		mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
+
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_default_config(mtk_crtc->mmsys_dev[i]);
+
 	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev[mmsys],
 					  mtk_crtc->ddp_comp[i + 1]->id))
-			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
+			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev[mmsys],
 					      mtk_crtc->ddp_comp[i]->id,
 					      mtk_crtc->ddp_comp[i + 1]->id);
-		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_add_comp(mtk_crtc->mutex,
+		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+			mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
 					   mtk_crtc->ddp_comp[i]->id);
 	}
-	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-		mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
-	mtk_mutex_enable(mtk_crtc->mutex);
+	mmsys = mtk_crtc->ddp_comp_sys[i];
+	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+		mtk_mutex_add_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+	/* Need to set sof source for all mmsys mutexes in this crtc */
+	for (j = 0; j < MAX_MMSYS; j++)
+		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+			mtk_mutex_add_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_enable(mtk_crtc->mutex[i]);
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
@@ -402,7 +458,11 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		if (i == 1)
 			mtk_ddp_comp_bgclr_in_on(comp);
 
-		mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
+		if (mtk_ddp_comp_get_type(comp->id) == MTK_DISP_VIRTUAL)
+			mtk_mmsys_ddp_config(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+					     comp->id, width, height, NULL);
+		else
+			mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
 		mtk_ddp_comp_start(comp);
 	}
 
@@ -426,7 +486,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 	return 0;
 
 err_mutex_unprepare:
-	mtk_mutex_unprepare(mtk_crtc->mutex);
+	while (--i >= 0)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
 err_pm_runtime_put:
 	pm_runtime_put(crtc->dev->dev);
 	return ret;
@@ -437,7 +500,8 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
 	struct drm_device *drm = mtk_crtc->base.dev;
 	struct drm_crtc *crtc = &mtk_crtc->base;
 	unsigned long flags;
-	int i;
+	int i, j;
+	enum mtk_drm_mmsys mmsys;
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
@@ -445,27 +509,47 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
 			mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
 	}
 
-	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
-		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_remove_comp(mtk_crtc->mutex,
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+			mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
 					      mtk_crtc->ddp_comp[i]->id);
-	mtk_mutex_disable(mtk_crtc->mutex);
+	}
 	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-		if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
-					     mtk_crtc->ddp_comp[i + 1]->id))
-			mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
-						 mtk_crtc->ddp_comp[i]->id,
-						 mtk_crtc->ddp_comp[i + 1]->id);
-		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_remove_comp(mtk_crtc->mutex,
+		struct mtk_ddp_comp *comp;
+		unsigned int curr, next;
+
+		comp = mtk_crtc->ddp_comp[i];
+		curr = mtk_crtc->ddp_comp[i]->id;
+		next = mtk_crtc->ddp_comp[i + 1]->id;
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_disconnect(comp, mtk_crtc->mmsys_dev[mmsys], next))
+			mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev[mmsys], curr, next);
+		if (!mtk_ddp_comp_remove(comp, mtk_crtc->mutex[mmsys]))
+			mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
 					      mtk_crtc->ddp_comp[i]->id);
+
 	}
-	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-		mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+
+	mmsys = mtk_crtc->ddp_comp_sys[i];
+	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+		mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+	/* Need to remove sof source for all mmsys mutexes in this crtc */
+	for (j = 0; j < MAX_MMSYS; j++)
+		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+			mtk_mutex_remove_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
 	mtk_crtc_ddp_clk_disable(mtk_crtc);
-	mtk_mutex_unprepare(mtk_crtc->mutex);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
 
-	pm_runtime_put(drm->dev);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_top_clk_disable(mtk_crtc->mmsys_dev[i]);
+
+	pm_runtime_put_sync(drm->dev);
 
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -589,9 +673,15 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
 		mtk_crtc->pending_async_planes = true;
 
 	if (priv->data->shadow_register) {
-		mtk_mutex_acquire(mtk_crtc->mutex);
+		for (i = 0; i < MAX_MMSYS; i++)
+			if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+				mtk_mutex_acquire(mtk_crtc->mutex[i]);
+
 		mtk_crtc_ddp_config(crtc, NULL);
-		mtk_mutex_release(mtk_crtc->mutex);
+
+		for (i = 0; i < MAX_MMSYS; i++)
+			if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+				mtk_mutex_release(mtk_crtc->mutex[i]);
 	}
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	if (mtk_crtc->cmdq_client.chan) {
@@ -675,6 +765,7 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 {
 	int crtc_index = drm_crtc_index(crtc);
 	int i;
+	unsigned int mmsys;
 	struct device *dev;
 	struct drm_crtc_state *crtc_state = state->crtcs[crtc_index].new_state;
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -687,7 +778,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 	if (!mtk_crtc->num_conn_routes)
 		return;
 
-	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[crtc_index];
+	mmsys = mtk_crtc->conn_routes_sys;
+	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[mmsys];
 	dev = priv->dev;
 
 	dev_dbg(dev, "connector change:%d, encoder mask:0x%x for crtc:%d\n",
@@ -700,6 +792,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 		if (comp->encoder_index >= 0 &&
 		    (encoder_mask & BIT(comp->encoder_index))) {
 			mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr - 1] = comp;
+			mtk_crtc->ddp_comp_sys[mtk_crtc->ddp_comp_nr - 1] = mmsys;
+			mtk_crtc->exist[mmsys] = true;
 			dev_dbg(dev, "Add comp_id: %d at path index %d\n",
 				comp->id, mtk_crtc->ddp_comp_nr - 1);
 			break;
@@ -736,9 +830,31 @@ static void mtk_crtc_atomic_enable(struct drm_crtc *crtc,
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 	int ret;
+	int i, j;
+	int mmsys_cnt = 0;
 
 	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mmsys_cnt++;
+
+	if (mmsys_cnt > 1) {
+		for (i = 0; i < MAX_MMSYS; i++) {
+			if (!mtk_crtc->exist[i])
+				continue;
+			ret = pm_runtime_resume_and_get(mtk_crtc->mmsys_dev[i]);
+			if (ret < 0) {
+				DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+					      "Failed to enable power domain: %d\n", ret);
+				for (j = i - 1; j >= 0; j--)
+					if (mtk_crtc->exist[i])
+						pm_runtime_put(mtk_crtc->mmsys_dev[j]);
+				return;
+			}
+		}
+	}
+
 	ret = mtk_ddp_comp_power_on(comp);
 	if (ret < 0) {
 		DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
@@ -762,7 +878,8 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-	int i;
+	int i, ret;
+	int mmsys_cnt = 0;
 
 	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 	if (!mtk_crtc->enabled)
@@ -794,6 +911,22 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
 	mtk_crtc_ddp_hw_fini(mtk_crtc);
 	mtk_ddp_comp_power_off(comp);
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mmsys_cnt++;
+
+	if (mmsys_cnt > 1) {
+		for (i = 0; i < MAX_MMSYS; i++) {
+			if (mtk_crtc->exist[i]) {
+				ret = pm_runtime_put(mtk_crtc->mmsys_dev[i]);
+				if (ret < 0)
+					DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+						      "Failed to disable power domain: %d\n",
+						      ret);
+			}
+		}
+	}
+
 	mtk_crtc->enabled = false;
 }
 
@@ -953,49 +1086,108 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
 	return mtk_crtc->dma_dev;
 }
 
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
-		    unsigned int path_len, int priv_data_index,
-		    const struct mtk_drm_route *conn_routes,
-		    unsigned int num_conn_routes)
+int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path path_sel)
 {
 	struct mtk_drm_private *priv = drm_dev->dev_private;
 	struct device *dev = drm_dev->dev;
 	struct mtk_crtc *mtk_crtc;
 	unsigned int num_comp_planes = 0;
 	int ret;
-	int i;
+	int i, j, k;
 	bool has_ctm = false;
 	uint gamma_lut_size = 0;
 	struct drm_crtc *tmp;
 	int crtc_i = 0;
-
-	if (!path)
-		return 0;
-
-	priv = priv->all_drm_private[priv_data_index];
+	struct mtk_drm_private *subsys_priv;
+	struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
+	unsigned int path_len = 0;
+	const struct mtk_drm_route *conn_routes = NULL;
+	unsigned int num_conn_routes = 0;
+	enum mtk_drm_mmsys conn_mmsys;
 
 	drm_for_each_crtc(tmp, drm_dev)
 		crtc_i++;
 
+	for (j = 0; j < priv->data->mmsys_dev_num; j++) {
+		for (k = 0; k < MAX_MMSYS; k++) {
+			const unsigned int *subsys_path;
+			unsigned int subsys_path_len = 0;
+			unsigned int order = 0;
+
+			subsys_priv = priv->all_drm_private[k];
+			if (!subsys_priv)
+				continue;
+
+			if (path_sel == CRTC_MAIN) {
+				subsys_path = subsys_priv->data->main_path;
+				subsys_path_len = subsys_priv->data->main_len;
+				order = subsys_priv->data->main_order;
+			} else if (path_sel == CRTC_EXT) {
+				subsys_path = subsys_priv->data->ext_path;
+				subsys_path_len = subsys_priv->data->ext_len;
+				order = subsys_priv->data->ext_order;
+			} else if (path_sel == CRTC_THIRD) {
+				subsys_path = subsys_priv->data->third_path;
+				subsys_path_len = subsys_priv->data->third_len;
+				order = subsys_priv->data->third_order;
+			}
+
+			if (subsys_priv->data->num_conn_routes) {
+				conn_routes = subsys_priv->data->conn_routes;
+				num_conn_routes = subsys_priv->data->num_conn_routes;
+				conn_mmsys = subsys_priv->data->mmsys_id;
+			}
+
+			if (j != order)
+				continue;
+			if (!subsys_path_len)
+				continue;
+
+			for (i = 0; i < subsys_path_len; i++) {
+				path[path_len].sys = subsys_priv->data->mmsys_id;
+				path[path_len].comp_id = subsys_path[i];
+				path_len++;
+			}
+		}
+	}
+
+	if (!path_len)
+		return 0;
+
+	if (num_conn_routes) {
+		for (i = 0; i < num_conn_routes; i++)
+			if (conn_routes->crtc_id == crtc_i)
+				break;
+		if (i == num_conn_routes) {
+			num_conn_routes = 0;
+			conn_routes = NULL;
+		}
+	}
+
 	for (i = 0; i < path_len; i++) {
-		enum mtk_ddp_comp_id comp_id = path[i];
+		enum mtk_ddp_comp_id comp_id = path[i].comp_id;
 		struct device_node *node;
 		struct mtk_ddp_comp *comp;
 
+		priv = priv->all_drm_private[path[i].sys];
 		node = priv->comp_node[comp_id];
 		comp = &priv->ddp_comp[comp_id];
 
 		/* Not all drm components have a DTS device node, such as ovl_adaptor,
 		 * which is the drm bring up sub driver
 		 */
-		if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+		if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 &&
+		    mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
 			dev_info(dev,
 				"Not creating crtc %d because component %d is disabled or missing\n",
 				crtc_i, comp_id);
 			return 0;
 		}
 
-		if (!comp->dev) {
+		if (!comp->dev && mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
 			dev_err(dev, "Component %pOF not initialized\n", node);
 			return -ENODEV;
 		}
@@ -1005,7 +1197,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	if (!mtk_crtc)
 		return -ENOMEM;
 
-	mtk_crtc->mmsys_dev = priv->mmsys_dev;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (priv->all_drm_private[i])
+			mtk_crtc->mmsys_dev[i] = priv->all_drm_private[i]->mmsys_dev;
 	mtk_crtc->ddp_comp_nr = path_len;
 	mtk_crtc->ddp_comp = devm_kcalloc(dev,
 					  mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
@@ -1014,19 +1208,36 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	if (!mtk_crtc->ddp_comp)
 		return -ENOMEM;
 
-	mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
-	if (IS_ERR(mtk_crtc->mutex)) {
-		ret = PTR_ERR(mtk_crtc->mutex);
-		dev_err(dev, "Failed to get mutex: %d\n", ret);
-		return ret;
+	mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr +
+						    (conn_routes ? 1 : 0),
+						    sizeof(*mtk_crtc->ddp_comp_sys), GFP_KERNEL);
+	if (!mtk_crtc->ddp_comp_sys)
+		return -ENOMEM;
+
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!priv->all_drm_private[i])
+			continue;
+
+		priv = priv->all_drm_private[i];
+		mtk_crtc->mutex[i] = mtk_mutex_get(priv->mutex_dev);
+		if (IS_ERR(mtk_crtc->mutex[i])) {
+			ret = PTR_ERR(mtk_crtc->mutex[i]);
+			dev_err(dev, "Failed to get mutex: %d\n", ret);
+			return ret;
+		}
 	}
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
-		unsigned int comp_id = path[i];
+		unsigned int comp_id = path[i].comp_id;
 		struct mtk_ddp_comp *comp;
 
+		priv = priv->all_drm_private[path[i].sys];
 		comp = &priv->ddp_comp[comp_id];
+		if (mtk_ddp_comp_get_type(comp_id) == MTK_DISP_VIRTUAL)
+			comp->id = comp_id;
 		mtk_crtc->ddp_comp[i] = comp;
+		mtk_crtc->ddp_comp_sys[i] = path[i].sys;
+		mtk_crtc->exist[path[i].sys] = true;
 
 		if (comp->funcs) {
 			if (comp->funcs->gamma_set && comp->funcs->gamma_get_lut_size) {
@@ -1063,8 +1274,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	 * In the case of ovl_adaptor sub driver, it needs to use the
 	 * dma_dev_get function to get representative dma dev.
 	 */
-	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
+	priv = priv->all_drm_private[path[0].sys];
+	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0].comp_id]);
 
+	mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
 	ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
 	if (ret < 0)
 		return ret;
@@ -1077,7 +1290,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	i = priv->mbox_index++;
-	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
+	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev[priv->data->mmsys_id];
 	mtk_crtc->cmdq_client.client.tx_block = false;
 	mtk_crtc->cmdq_client.client.knows_txdone = true;
 	mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
@@ -1117,6 +1330,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 #endif
 
 	if (conn_routes) {
+		priv = priv->all_drm_private[conn_mmsys];
 		for (i = 0; i < num_conn_routes; i++) {
 			unsigned int comp_id = conn_routes[i].route_ddp;
 			struct device_node *node = priv->comp_node[comp_id];
@@ -1133,6 +1347,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 			mtk_ddp_comp_encoder_index_set(&priv->ddp_comp[comp_id]);
 		}
 
+		mtk_crtc->conn_routes_sys = conn_mmsys;
 		mtk_crtc->num_conn_routes = num_conn_routes;
 		mtk_crtc->conn_routes = conn_routes;
 
@@ -1140,5 +1355,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 		mtk_crtc->ddp_comp_nr++;
 	}
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			device_link_add(mtk_crtc->base.dev->dev,
+					priv->all_drm_private[i]->mutex_dev, 0);
+
 	return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h b/drivers/gpu/drm/mediatek/mtk_crtc.h
index 388e900b6f4d..255f2823d17a 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
@@ -15,10 +15,8 @@
 #define MTK_MIN_BPC	3
 
 void mtk_crtc_commit(struct drm_crtc *crtc);
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
-		    unsigned int path_len, int priv_data_index,
-		    const struct mtk_drm_route *conn_routes,
-		    unsigned int num_conn_routes);
+int mtk_crtc_create(struct drm_device *drm_dev,
+		    enum mtk_crtc_path path_sel);
 int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
 			 struct mtk_plane_state *state);
 void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index c96e027359ac..6628f5cd732a 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -467,6 +467,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_RDMA] = "rdma",
 	[MTK_DISP_UFOE] = "ufoe",
+	[MTK_DISP_VIRTUAL] = "virtual",
 	[MTK_DISP_WDMA] = "wdma",
 	[MTK_DP_INTF] = "dp-intf",
 	[MTK_DPI] = "dpi",
@@ -490,6 +491,15 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_COLOR0]		= { MTK_DISP_COLOR,		0, &ddp_color },
 	[DDP_COMPONENT_COLOR1]		= { MTK_DISP_COLOR,		1, &ddp_color },
 	[DDP_COMPONENT_DITHER0]		= { MTK_DISP_DITHER,		0, &ddp_dither },
+	[DDP_COMPONENT_DLI_ASYNC0]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC1]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC8]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC21]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC22]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC23]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC1]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC2]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC3]      = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_DP_INTF0]	= { MTK_DP_INTF,		0, &ddp_dpi },
 	[DDP_COMPONENT_DP_INTF1]	= { MTK_DP_INTF,		1, &ddp_dpi },
 	[DDP_COMPONENT_DPI0]		= { MTK_DPI,			0, &ddp_dpi },
@@ -497,6 +507,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= { MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
 	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = { MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DSC0]		= { MTK_DISP_DSC,		0, &ddp_dsc },
 	[DDP_COMPONENT_DSC1]		= { MTK_DISP_DSC,		1, &ddp_dsc },
 	[DDP_COMPONENT_DSI0]		= { MTK_DSI,			0, &ddp_dsi },
@@ -513,7 +524,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_OD0]		= { MTK_DISP_OD,		0, &ddp_od },
 	[DDP_COMPONENT_OD1]		= { MTK_DISP_OD,		1, &ddp_od },
 	[DDP_COMPONENT_OVL0]		= { MTK_DISP_OVL,		0, &ddp_ovl },
+	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_OVL1]		= { MTK_DISP_OVL,		1, &ddp_ovl },
+	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_OVL_2L0]		= { MTK_DISP_OVL_2L,		0, &ddp_ovl },
 	[DDP_COMPONENT_OVL_2L1]		= { MTK_DISP_OVL_2L,		1, &ddp_ovl },
 	[DDP_COMPONENT_OVL_2L2]		= { MTK_DISP_OVL_2L,		2, &ddp_ovl },
@@ -564,27 +578,6 @@ static int mtk_ddp_comp_find_in_route(struct device *dev,
 	return -ENODEV;
 }
 
-static bool mtk_ddp_path_available(const unsigned int *path,
-				   unsigned int path_len,
-				   struct device_node **comp_node)
-{
-	unsigned int i;
-
-	if (!path || !path_len)
-		return false;
-
-	for (i = 0U; i < path_len; i++) {
-		/* OVL_ADAPTOR doesn't have a device node */
-		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
-			continue;
-
-		if (!comp_node[path[i]])
-			return false;
-	}
-
-	return true;
-}
-
 int mtk_ddp_comp_get_id(struct device_node *node,
 			enum mtk_ddp_comp_type comp_type)
 {
@@ -600,53 +593,36 @@ int mtk_ddp_comp_get_id(struct device_node *node,
 	return -EINVAL;
 }
 
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
+{
+	return mtk_ddp_matches[comp_id].type;
+}
+
 int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
 {
 	struct mtk_drm_private *private = drm->dev_private;
-	const struct mtk_mmsys_driver_data *data;
-	struct mtk_drm_private *priv_n;
-	int i = 0, j;
 	int ret;
 
-	for (j = 0; j < private->data->mmsys_dev_num; j++) {
-		priv_n = private->all_drm_private[j];
-		data = priv_n->data;
-
-		if (mtk_ddp_path_available(data->main_path, data->main_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->main_path,
-					      data->main_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
-
-		if (mtk_ddp_path_available(data->ext_path, data->ext_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->ext_path,
-					      data->ext_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
-
-		if (mtk_ddp_path_available(data->third_path, data->third_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->third_path,
-					      data->third_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
-	}
-
-	ret = mtk_ddp_comp_find_in_route(dev,
-					 private->data->conn_routes,
-					 private->data->num_conn_routes,
-					 private->ddp_comp);
-
-	if (ret < 0)
-		DRM_INFO("Failed to find comp in ddp table, ret = %d\n", ret);
+	if (mtk_ddp_comp_find(dev,
+			      private->data->main_path,
+			      private->data->main_len,
+			      private->ddp_comp))
+		ret = BIT(0);
+	else if (mtk_ddp_comp_find(dev,
+				   private->data->ext_path,
+				   private->data->ext_len,
+				   private->ddp_comp))
+		ret = BIT(1);
+	else if (mtk_ddp_comp_find(dev,
+				   private->data->third_path,
+				   private->data->third_len,
+				   private->ddp_comp))
+		ret = BIT(2);
+	else
+		ret = mtk_ddp_comp_find_in_route(dev,
+						 private->data->conn_routes,
+						 private->data->num_conn_routes,
+						 private->ddp_comp);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index ef64ce7a071f..badb42bd4f7c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_PWM,
 	MTK_DISP_RDMA,
 	MTK_DISP_UFOE,
+	MTK_DISP_VIRTUAL,
 	MTK_DISP_WDMA,
 	MTK_DPI,
 	MTK_DP_INTF,
@@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
 	MTK_OVL_BLENDER,
 	MTK_OVL_EXDMA,
 	MTK_OVL_OUTPROC,
+	MTK_VDISP_AO,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 0639201e2e92..b9c6a2a657ea 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -374,7 +374,7 @@ static int mtk_drm_match(struct device *dev, const void *data)
 static bool mtk_drm_get_all_drm_priv(struct device *dev)
 {
 	struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
-	struct mtk_drm_private *all_drm_priv[MAX_CRTC];
+	struct mtk_drm_private *all_drm_priv[MAX_MMSYS] = {NULL};
 	struct mtk_drm_private *temp_drm_priv;
 	struct device_node *phandle = dev->parent->of_node;
 	const struct of_device_id *of_id;
@@ -402,26 +402,22 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
 		if (!temp_drm_priv)
 			continue;
 
-		if (temp_drm_priv->data->main_len)
-			all_drm_priv[CRTC_MAIN] = temp_drm_priv;
-		else if (temp_drm_priv->data->ext_len)
-			all_drm_priv[CRTC_EXT] = temp_drm_priv;
-		else if (temp_drm_priv->data->third_len)
-			all_drm_priv[CRTC_THIRD] = temp_drm_priv;
+		all_drm_priv[temp_drm_priv->data->mmsys_id] = temp_drm_priv;
 
 		if (temp_drm_priv->mtk_drm_bound)
 			cnt++;
 
-		if (cnt == MAX_CRTC) {
+		if (cnt == temp_drm_priv->data->mmsys_dev_num) {
 			of_node_put(node);
 			break;
 		}
 	}
 
 	if (drm_priv->data->mmsys_dev_num == cnt) {
-		for (i = 0; i < cnt; i++)
-			for (j = 0; j < cnt; j++)
-				all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
+		for (i = 0; i < MAX_MMSYS; i++)
+			for (j = 0; j < MAX_MMSYS; j++)
+				if (all_drm_priv[j])
+					all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
 
 		return true;
 	}
@@ -506,7 +502,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
 	drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
 
-	for (i = 0; i < private->data->mmsys_dev_num; i++) {
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!private->all_drm_private[i])
+			continue;
+
 		drm->dev_private = private->all_drm_private[i];
 		ret = component_bind_all(private->all_drm_private[i]->dev, drm);
 		if (ret)
@@ -529,8 +528,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	 *    third path.
 	 */
 	for (i = 0; i < MAX_CRTC; i++) {
-		for (j = 0; j < private->data->mmsys_dev_num; j++) {
+		for (j = 0; j < MAX_MMSYS; j++) {
 			priv_n = private->all_drm_private[j];
+			if (!priv_n)
+				continue;
 
 			if (priv_n->data->max_width)
 				drm->mode_config.max_width = priv_n->data->max_width;
@@ -542,28 +543,23 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 				drm->mode_config.min_height = priv_n->data->min_height;
 
 			if (i == CRTC_MAIN && priv_n->data->main_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->main_path,
-						      priv_n->data->main_len, j,
-						      priv_n->data->conn_routes,
-						      priv_n->data->num_conn_routes);
+				ret = mtk_crtc_create(drm, CRTC_MAIN);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			} else if (i == CRTC_EXT && priv_n->data->ext_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->ext_path,
-						      priv_n->data->ext_len, j, NULL, 0);
+				ret = mtk_crtc_create(drm, CRTC_EXT);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			} else if (i == CRTC_THIRD && priv_n->data->third_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->third_path,
-						      priv_n->data->third_len, j, NULL, 0);
+				ret = mtk_crtc_create(drm, CRTC_THIRD);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			}
 		}
 	}
@@ -582,8 +578,9 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 		goto err_component_unbind;
 	}
 
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		private->all_drm_private[i]->dma_dev = dma_dev;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			private->all_drm_private[i]->dma_dev = dma_dev;
 
 	/*
 	 * Configure the DMA segment size to make sure we get contiguous IOVA
@@ -601,11 +598,13 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	return 0;
 
 err_component_unbind:
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		component_unbind_all(private->all_drm_private[i]->dev, drm);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			component_unbind_all(private->all_drm_private[i]->dev, drm);
 put_mutex_dev:
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		put_device(private->all_drm_private[i]->mutex_dev);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			put_device(private->all_drm_private[i]->mutex_dev);
 
 	return ret;
 }
@@ -669,6 +668,19 @@ static int mtk_drm_bind(struct device *dev)
 	}
 
 	private->mutex_dev = &pdev->dev;
+
+	if (private->vdisp_ao_node) {
+		pdev = of_find_device_by_node(private->vdisp_ao_node);
+		if (!pdev) {
+			dev_err(dev, "Waiting for vdisp_ao device %pOF\n",
+				private->vdisp_ao_node);
+			of_node_put(private->mutex_node);
+			of_node_put(private->vdisp_ao_node);
+			return -EPROBE_DEFER;
+		}
+		private->vdisp_ao_dev = &pdev->dev;
+	}
+
 	private->mtk_drm_bound = true;
 	private->dev = dev;
 
@@ -681,8 +693,9 @@ static int mtk_drm_bind(struct device *dev)
 
 	private->drm_master = true;
 	drm->dev_private = private;
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		private->all_drm_private[i]->drm = drm;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			private->all_drm_private[i]->drm = drm;
 
 	ret = mtk_drm_kms_init(drm);
 	if (ret < 0)
@@ -1125,7 +1138,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 		private->data = mtk_drm_data;
 	}
 
-	private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
+	private->all_drm_private = devm_kmalloc_array(dev, MAX_MMSYS,
 						      sizeof(*private->all_drm_private),
 						      GFP_KERNEL);
 	if (!private->all_drm_private)
@@ -1220,6 +1233,12 @@ static int mtk_drm_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (comp_type == MTK_VDISP_AO) {
+			private->vdisp_ao_node = of_node_get(node);
+			dev_dbg(dev, "get vdisp_ao node");
+			continue;
+		}
+
 		comp_id = mtk_ddp_comp_get_id(node, comp_type);
 		if (comp_id < 0) {
 			dev_warn(dev, "Skipping unknown component %pOF\n",
@@ -1295,6 +1314,7 @@ static void mtk_drm_remove(struct platform_device *pdev)
 	component_master_del(&pdev->dev, &mtk_drm_ops);
 	pm_runtime_disable(&pdev->dev);
 	of_node_put(private->mutex_node);
+	of_node_put(private->vdisp_ao_node);
 	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
 		of_node_put(private->comp_node[i]);
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 6e9ed9837c5b..6a6d689345b1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -13,7 +13,8 @@
 #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
 #define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
 #define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 + 1)
 
 enum mtk_crtc_path {
 	CRTC_MAIN,
@@ -22,6 +23,14 @@ enum mtk_crtc_path {
 	MAX_CRTC,
 };
 
+enum mtk_drm_mmsys {
+	DISPSYS0,
+	DISPSYS1,
+	OVLSYS0,
+	OVLSYS1,
+	MAX_MMSYS,
+};
+
 struct device;
 struct device_node;
 struct drm_crtc;
@@ -38,10 +47,13 @@ struct mtk_drm_route {
 struct mtk_mmsys_driver_data {
 	const unsigned int *main_path;
 	unsigned int main_len;
+	unsigned int main_order;
 	const unsigned int *ext_path;
 	unsigned int ext_len;
+	unsigned int ext_order;
 	const unsigned int *third_path;
 	unsigned int third_len;
+	unsigned int third_order;
 	const struct mtk_drm_route *conn_routes;
 	unsigned int num_conn_routes;
 
@@ -63,6 +75,8 @@ struct mtk_drm_private {
 	struct device_node *mutex_node;
 	struct device *mutex_dev;
 	struct device *mmsys_dev;
+	struct device_node *vdisp_ao_node;
+	struct device *vdisp_ao_dev;
 	struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
 	struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
 	struct mtk_mmsys_driver_data *data;
-- 
2.45.2



From paul-pl.chen at mediatek.com  Fri Mar 21 02:33:44 2025
From: paul-pl.chen at mediatek.com (paul-pl.chen)
Date: Fri, 21 Mar 2025 17:33:44 +0800
Subject: [PATCH v2 15/15] drm/mediatek: Add support for MT8196 multiple mmsys
In-Reply-To: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
Message-ID: <20250321093435.94835-16-paul-pl.chen@mediatek.com>

From: Nancy Lin <nancy.lin at mediatek.com>

Add code to support MT8196 SOC Multi MMSYS Driver

Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 119 ++++++++++++++++++++++++-
 1 file changed, 115 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b9c6a2a657ea..70a7e6d06d4f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -193,6 +193,10 @@ static const struct mtk_drm_route mt8188_mtk_ddp_main_routes[] = {
 	{0, DDP_COMPONENT_DSI0},
 };
 
+static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
+	{2, DDP_COMPONENT_DSI0},
+};
+
 static const unsigned int mt8192_mtk_ddp_main[] = {
 	DDP_COMPONENT_OVL0,
 	DDP_COMPONENT_OVL_2L0,
@@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[] = {
 	DDP_COMPONENT_DP_INTF1,
 };
 
+static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
+	DDP_COMPONENT_OVL0_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_main[] = {
+	DDP_COMPONENT_DLI_ASYNC0,
+	DDP_COMPONENT_DLO_ASYNC1,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_main[] = {
+	DDP_COMPONENT_DLI_ASYNC21,
+	DDP_COMPONENT_DVO0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl0_ext[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1,
+	DDP_COMPONENT_OVL0_DLO_ASYNC6,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_ext[] = {
+	DDP_COMPONENT_DLI_ASYNC1,
+	DDP_COMPONENT_DLO_ASYNC2,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_ext[] = {
+	DDP_COMPONENT_DLI_ASYNC22,
+	DDP_COMPONENT_DP_INTF0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl1_third[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2,
+	DDP_COMPONENT_OVL1_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_third[] = {
+	DDP_COMPONENT_DLI_ASYNC8,
+	DDP_COMPONENT_DLO_ASYNC3,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_third[] = {
+	DDP_COMPONENT_DLI_ASYNC23,
+};
+
 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
 	.main_path = mt2701_mtk_ddp_main,
 	.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -327,8 +375,65 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
 	.min_height = 1,
 };
 
-static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
-	.mmsys_dev_num = 1,
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+	.main_path = mt8196_mtk_ddp_disp0_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_main),
+	.main_order = 1,
+	.ext_path = mt8196_mtk_ddp_disp0_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_ext),
+	.ext_order = 1,
+	.third_path = mt8196_mtk_ddp_disp0_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_third),
+	.third_order = 1,
+	.mmsys_id = DISPSYS0,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+	.main_path = mt8196_mtk_ddp_disp1_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_main),
+	.main_order = 2,
+	.ext_path = mt8196_mtk_ddp_disp1_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_ext),
+	.ext_order = 2,
+	.third_path = mt8196_mtk_ddp_disp1_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_third),
+	.conn_routes = mt8196_mtk_ddp_routes,
+	.num_conn_routes = ARRAY_SIZE(mt8196_mtk_ddp_routes),
+	.third_order = 2,
+	.mmsys_id = DISPSYS1,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+	.main_path = mt8196_mtk_ddp_ovl0_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_main),
+	.main_order = 0,
+	.ext_path = mt8196_mtk_ddp_ovl0_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_ext),
+	.ext_order = 0,
+	.mmsys_id = OVLSYS0,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+	.third_path = mt8196_mtk_ddp_ovl1_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl1_third),
+	.third_order = 0,
+	.mmsys_id = OVLSYS1,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
 };
 
 static const struct of_device_id mtk_drm_of_ids[] = {
@@ -358,8 +463,14 @@ static const struct of_device_id mtk_drm_of_ids[] = {
 	  .data = &mt8195_vdosys0_driver_data},
 	{ .compatible = "mediatek,mt8195-vdosys1",
 	  .data = &mt8195_vdosys1_driver_data},
-	{ .compatible = "mediatek,mt8365-mmsys",
-	  .data = &mt8365_mmsys_driver_data},
+	{ .compatible = "mediatek,mt8196-dispsys0",
+	  .data = &mt8196_dispsys0_driver_data},
+	{ .compatible = "mediatek,mt8196-dispsys1",
+	  .data = &mt8196_dispsys1_driver_data},
+	{ .compatible = "mediatek,mt8196-ovlsys0",
+	  .data = &mt8196_ovlsys0_driver_data},
+	{ .compatible = "mediatek,mt8196-ovlsys1",
+	  .data = &mt8196_ovlsys1_driver_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
-- 
2.45.2



From geert at linux-m68k.org  Fri Mar 21 02:36:34 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 21 Mar 2025 10:36:34 +0100
Subject: [soc:soc/drivers 20/24] ERROR: modpost: "__ffsdi2"
 [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
In-Reply-To: <927105f8-4aa8-4579-ac2e-bce4bce12b1e@app.fastmail.com>
References: <202503211029.DnQpqsJs-lkp@intel.com> <927105f8-4aa8-4579-ac2e-bce4bce12b1e@app.fastmail.com>
Message-ID: <CAMuHMdUeynpmUUmZPViEBttANFmEhpjFn0wqNc1wQB6wRbd0rQ@mail.gmail.com>

Hi Arnd,

On Fri, 21 Mar 2025 at 09:41, Arnd Bergmann <arnd at arndb.de> wrote:
> On Fri, Mar 21, 2025, at 03:41, kernel test robot wrote:
> > First bad commit (maybe != root cause):
> >
> > tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git
> > soc/drivers
> > head:   ba8755ab541fc629948233125db870d4dbf00a75
> > commit: ee7f8ed72990f28657b5bf598e695fcf4633f4ed [20/24] platform:
> > cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
> > config: sh-allmodconfig
> > (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/config)
> > compiler: sh4-linux-gcc (GCC) 14.2.0
> > reproduce (this is a W=1 build):
> > (https://download.01.org/0day-ci/archive/20250321/202503211029.DnQpqsJs-lkp at intel.com/reproduce)
> >
> > If you fix the issue in a separate patch/commit (i.e. not just a new
> > version of
> > the same patch/commit), kindly add following tags
> > | Reported-by: kernel test robot <lkp at intel.com>
> > | Closes:
> > https://lore.kernel.org/oe-kbuild-all/202503211029.DnQpqsJs-lkp at intel.com/
> >
> > All errors (new ones prefixed by >>, old ones prefixed by <<):
> >
> > ERROR: modpost: "__delay" [drivers/net/mdio/mdio-cavium.ko] undefined!

Bug in driver (must not use __delay() directly).

> > ERROR: modpost: "devm_of_clk_add_hw_provider"
> > [drivers/media/i2c/tc358746.ko] undefined!
> > ERROR: modpost: "devm_clk_hw_register" [drivers/media/i2c/tc358746.ko]
> > undefined!
> > ERROR: modpost: "of_clk_hw_simple_get" [drivers/media/i2c/tc358746.ko]
> > undefined!

Missing dependencies for driver.

> >>> ERROR: modpost: "__ffsdi2" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
>
> This comes from __bf_shf(spec) in omnia_mcu_request_irq().
>
> As far as I can tell, this is not your problem but in the
> SH architecture missing one of the libgcc functions that are
> called by gcc.
>
> Since this is only for compile-testing sh allmodconfig, and
> that is already broken because of other bugs, I'm not going
> to care either.
>
> Adding the linux-sh list to Cc, it would be nice to get a clean
> build again. All four problems should be trivial to address,
> and some of these have been broken for many years.

So one SH-specific issue to fix...

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From neil.armstrong at linaro.org  Fri Mar 21 02:37:57 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Fri, 21 Mar 2025 10:37:57 +0100
Subject: [PATCH] arm64: dts: amlogic: a4: fix dtb compilation warning
 issues
In-Reply-To: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
References: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
Message-ID: <5caa550a-ffdf-477d-92f4-a3222b7fba29@linaro.org>

Hi,

On 21/03/2025 03:23, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
> 
> When use command 'make ARCH=arm64 dtbs_check W=1' to compile dtb,
> a warning message appears.
> "Warning (simple_bus_reg): /soc/bus at fe000000/pinctrl:
> missing or empty reg/ranges property"
> 
> Add the unit address to the pinctrl node to fix it.

I've delayed the pinctrl to next release so plase rebase
the commit on top of https://web.git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/log/?h=for-next
and fix the warnings here, and make sure DTBS_CHECK still passes.

Neil

> 
> Fixes: ce78f679e08c ("arm64: dts: amlogic: a4: add pinctrl node")
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 102 +++++++++++++++-------------
>   1 file changed, 55 insertions(+), 47 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> index fa80fa365f13..582e0043024b 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> @@ -51,87 +51,52 @@ pwrc: power-controller {
>   };
>   
>   &apb {
> -	gpio_intc: interrupt-controller at 4080 {
> -		compatible = "amlogic,a4-gpio-intc",
> -			     "amlogic,meson-gpio-intc";
> -		reg = <0x0 0x4080 0x0 0x20>;
> -		interrupt-controller;
> -		#interrupt-cells = <2>;
> -		amlogic,channel-interrupts =
> -			<10 11 12 13 14 15 16 17 18 19 20 21>;
> -	};
> -
> -	gpio_ao_intc: interrupt-controller at 8e72c {
> -		compatible = "amlogic,a4-gpio-ao-intc",
> -			     "amlogic,meson-gpio-intc";
> -		reg = <0x0 0x8e72c 0x0 0x0c>;
> -		interrupt-controller;
> -		#interrupt-cells = <2>;
> -		amlogic,channel-interrupts = <140 141>;
> -	};
> -
> -	periphs_pinctrl: pinctrl {
> +	periphs_pinctrl: pinctrl at 4000 {
>   		compatible = "amlogic,pinctrl-a4";
>   		#address-cells = <2>;
>   		#size-cells = <2>;
> -		ranges;
> +		ranges = <0x0 0x0 0x0 0x4000 0x0 0x280>;
>   
> -		gpiox: gpio at 4100 {
> -			reg = <0 0x4100 0 0x40>, <0 0x400c 0 0xc>;
> +		gpiox: gpio at 100 {
> +			reg = <0 0x100 0 0x40>, <0 0xc 0 0xc>;
>   			reg-names = "gpio", "mux";
>   			gpio-controller;
>   			#gpio-cells = <2>;
>   			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_X<<8) 18>;
>   		};
>   
> -		gpiot: gpio at 4140 {
> -			reg = <0 0x4140 0 0x40>, <0 0x402c 0 0xc>;
> +		gpiot: gpio at 140 {
> +			reg = <0 0x140 0 0x40>, <0 0x2c 0 0xc>;
>   			reg-names = "gpio", "mux";
>   			gpio-controller;
>   			#gpio-cells = <2>;
>   			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_T<<8) 23>;
>   		};
>   
> -		gpiod: gpio at 4180 {
> -			reg = <0 0x4180 0 0x40>, <0 0x4040 0 0x8>;
> +		gpiod: gpio at 180 {
> +			reg = <0 0x180 0 0x40>, <0 0x40 0 0x8>;
>   			reg-names = "gpio", "mux";
>   			gpio-controller;
>   			#gpio-cells = <2>;
>   			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_D<<8) 16>;
>   		};
>   
> -		gpioe: gpio at 41c0 {
> -			reg = <0 0x41c0 0 0x40>, <0 0x4048 0 0x4>;
> +		gpioe: gpio at 1c0 {
> +			reg = <0 0x1c0 0 0x40>, <0 0x48 0 0x4>;
>   			reg-names = "gpio", "mux";
>   			gpio-controller;
>   			#gpio-cells = <2>;
>   			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_E<<8) 2>;
>   		};
>   
> -		gpiob: gpio at 4240 {
> -			reg = <0 0x4240 0 0x40>, <0 0x4000 0 0x8>;
> +		gpiob: gpio at 240 {
> +			reg = <0 0x240 0 0x40>, <0 0 0 0x8>;
>   			reg-names = "gpio", "mux";
>   			gpio-controller;
>   			#gpio-cells = <2>;
>   			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_B<<8) 14>;
>   		};
>   
> -		gpioao: gpio at 8e704 {
> -			reg = <0 0x8e704 0 0x16>, <0 0x8e700 0 0x4>;
> -			reg-names = "gpio", "mux";
> -			gpio-controller;
> -			#gpio-cells = <2>;
> -			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_AO<<8) 7>;
> -		};
> -
> -		test_n: gpio at 8e744 {
> -			reg = <0 0x8e744 0 0x20>;
> -			reg-names = "gpio";
> -			gpio-controller;
> -			#gpio-cells = <2>;
> -			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
> -		};
> -
>   		func-uart-a {
>   			uart_a_default: group-uart-a-pins1 {
>   				pinmux = <AML_PINMUX(AMLOGIC_GPIO_X, 11, 1)>,
> @@ -186,4 +151,47 @@ uart_e_default: group-uart-e-pins {
>   			};
>   		};
>   	};
> +
> +	gpio_intc: interrupt-controller at 4080 {
> +		compatible = "amlogic,a4-gpio-intc",
> +			     "amlogic,meson-gpio-intc";
> +		reg = <0x0 0x4080 0x0 0x20>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		amlogic,channel-interrupts =
> +			<10 11 12 13 14 15 16 17 18 19 20 21>;
> +	};
> +
> +	ao_pinctrl: pinctrl at 8e700 {
> +		compatible = "amlogic,pinctrl-a4";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges = <0x0 0x0 0x0 0x8e700 0x0 0x80>;
> +
> +		gpioao: gpio at 4 {
> +			reg = <0 0x4 0 0x16>, <0 0 0 0x4>;
> +			reg-names = "gpio", "mux";
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_AO<<8) 7>;
> +		};
> +
> +		test_n: gpio at 44 {
> +			reg = <0 0x44 0 0x20>;
> +			reg-names = "gpio";
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
> +		};
> +	};
> +
> +	gpio_ao_intc: interrupt-controller at 8e72c {
> +		compatible = "amlogic,a4-gpio-ao-intc",
> +			     "amlogic,meson-gpio-intc";
> +		reg = <0x0 0x8e72c 0x0 0x0c>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		amlogic,channel-interrupts = <140 141>;
> +	};
> +
>   };
> 
> ---
> base-commit: 73a143e436311183186ab4b365a84c662f2c9651
> change-id: 20250317-fix-a4-pinctrl-node-9babfd44e085
> 
> Best regards,



From Jonathan.Cameron at huawei.com  Fri Mar 21 02:38:25 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Fri, 21 Mar 2025 09:38:25 +0000
Subject: [RFC PATCH 3/6] cache: coherency device class
In-Reply-To: <2025032013-venus-request-b026@gregkh>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
	<20250320174118.39173-4-Jonathan.Cameron@huawei.com>
	<2025032013-venus-request-b026@gregkh>
Message-ID: <20250321093825.00004d6b@huawei.com>

On Thu, 20 Mar 2025 14:12:15 -0700
Greg KH <gregkh at linuxfoundation.org> wrote:

> On Thu, Mar 20, 2025 at 05:41:15PM +0000, Jonathan Cameron wrote:
> > --- a/drivers/cache/Kconfig
> > +++ b/drivers/cache/Kconfig
> > @@ -1,6 +1,12 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  menu "Cache Drivers"
> >  
> > +config CACHE_COHERENCY_CLASS
> > +	bool "Cache coherency control class"  
> 
> Why can't this be a module?  And why would anyone want to turn it off?

If you don't have the hardware you won't want the infrastructure.
I'll add a note.  If you do have the hardware and don't have memory subsystems
that need to use it (maybe no CXL hardware for instance and that's the only
user on a particular platform).

> 
> > +	help
> > +	  Class to which coherency control drivers register allowing core kernel
> > +	  subsystems to issue invalidations and similar coherency operations.  
> 
> What "core kernel subsystems".

I'll expand on that.  Memory hotplug related stuff (currently CXL and NVDIMM)
but the thing is more general that that.

> 
> > +
> >  config AX45MP_L2_CACHE
> >  	bool "Andes Technology AX45MP L2 Cache controller"
> >  	depends on RISCV  
> 
> Shouldn't all of these now depend on CACHE_COHERENCY_CLASS?

Nope. They are unrelated existing cache related drivers.   The question
to Conor is whether he minds me putting this in the existing directory
and to others on whether it's a good idea.

> 
> > diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
> > index 55c5e851034d..b72b20f4248f 100644
> > --- a/drivers/cache/Makefile
> > +++ b/drivers/cache/Makefile
> > @@ -3,3 +3,5 @@
> >  obj-$(CONFIG_AX45MP_L2_CACHE)		+= ax45mp_cache.o
> >  obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
> >  obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
> > +
> > +obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o  
> 
> Why the blank line?

To separate existing stuff that happens to be cache related from this new
class.  Kind of camping in a directory because seemed silly to have
drivers/cache and drivers/cache_coherency


> 
> > diff --git a/drivers/cache/coherency_core.c b/drivers/cache/coherency_core.c
> > new file mode 100644
> > index 000000000000..52cb4ceae00c
> > --- /dev/null
> > +++ b/drivers/cache/coherency_core.c
> > @@ -0,0 +1,130 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Class to manage OS controlled coherency agents within the system.
> > + * Specifically to enable operations such as write back and invalidate.
> > + *
> > + * Copyright: Huawei 2025
> > + * Some elements based on fwctl class as an example of a modern
> > + * lightweight class.
> > + */
> > +
> > +#include <linux/cache_coherency.h>
> > +#include <linux/container_of.h>
> > +#include <linux/idr.h>
> > +#include <linux/fs.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +
> > +#include <asm/cacheflush.h>
> > +
> > +static DEFINE_IDA(cache_coherency_ida);
> > +
> > +static void cache_coherency_device_release(struct device *device)
> > +{
> > +	struct cache_coherency_device *ccd =
> > +		container_of(device, struct cache_coherency_device, dev);
> > +
> > +	ida_free(&cache_coherency_ida, ccd->id);
> > +}
> > +
> > +static struct class cache_coherency_class = {
> > +	.name = "cache_coherency",
> > +	.dev_release = cache_coherency_device_release,
> > +};
> > +
> > +static int cache_inval_one(struct device *dev, void *data)
> > +{
> > +	struct cache_coherency_device *ccd =
> > +		container_of(dev, struct cache_coherency_device, dev);
> > +
> > +	if (!ccd->ops)
> > +		return -EINVAL;
> > +
> > +	return ccd->ops->wbinv(ccd, data);
> > +}
> > +
> > +static int cache_inval_done_one(struct device *dev, void *data)
> > +{
> > +	struct cache_coherency_device *ccd =
> > +		container_of(dev, struct cache_coherency_device, dev);
> > +	if (!ccd->ops)
> > +		return -EINVAL;
> > +
> > +	return ccd->ops->done(ccd);
> > +}
> > +
> > +static int cache_invalidate_memregion(int res_desc,
> > +				      phys_addr_t addr, size_t size)
> > +{
> > +	int ret;
> > +	struct cc_inval_params params = {
> > +		.addr = addr,
> > +		.size = size,
> > +	};
> > +
> > +	ret = class_for_each_device(&cache_coherency_class, NULL, &params,
> > +				    cache_inval_one);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return class_for_each_device(&cache_coherency_class, NULL, NULL,
> > +				     cache_inval_done_one);
> > +}
> > +
> > +static const struct system_cache_flush_method cache_flush_method = {
> > +	.invalidate_memregion = cache_invalidate_memregion,
> > +};
> > +
> > +struct cache_coherency_device *
> > +_cache_coherency_alloc_device(struct device *parent,
> > +			      const struct coherency_ops *ops, size_t size)
> > +{
> > +
> > +	if (!ops || !ops->wbinv)
> > +		return NULL;
> > +
> > +	struct cache_coherency_device *ccd __free(kfree) = kzalloc(size, GFP_KERNEL);
> > +
> > +	if (!ccd)
> > +		return NULL;
> > +
> > +	ccd->dev.class = &cache_coherency_class;
> > +	ccd->dev.parent = parent;
> > +	ccd->ops = ops;
> > +	ccd->id = ida_alloc(&cache_coherency_ida, GFP_KERNEL);
> > +
> > +	if (dev_set_name(&ccd->dev, "cache_coherency%d", ccd->id))
> > +		return NULL;
> > +
> > + 	device_initialize(&ccd->dev);
> > +
> > +	return_ptr(ccd);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(_cache_coherency_alloc_device, "CACHE_COHERENCY");
> > +
> > +int cache_coherency_device_register(struct cache_coherency_device *ccd)
> > +{
> > +	return device_add(&ccd->dev);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cache_coherency_device_register, "CACHE_COHERENCY");
> > +
> > +void cache_coherency_device_unregister(struct cache_coherency_device *ccd)
> > +{
> > +	device_del(&ccd->dev);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cache_coherency_device_unregister, "CACHE_COHERENCY");
> > +
> > +static int __init cache_coherency_init(void)
> > +{
> > +	int ret;
> > +
> > +	ret = class_register(&cache_coherency_class);
> > +	if (ret)
> > +		return ret;
> > +
> > +	//TODO: generalize
> > +	arm64_set_sys_cache_flush_method(&cache_flush_method);  
> 
> I'm guessing this will blow up the build on non-x86 builds :)

Yup. That's a TODO That needs fixing.

> 
> > +struct cache_coherency_device {
> > +	struct device dev;
> > +	const struct coherency_ops *ops;
> > +	int id;
> > +};  
> 
> Classes are normally for user/kernel apis, what is this going to be used
> for?  I don't see any new user/kernel apis happening, so why do you need
> a struct device to be created?

I'm kind of expecting to grow some userspace ABI around a few things but
indeed there isn't any yet.  Stuff that has been suggested is:
* Descriptive stuff useful for performance estimation.
* Cache locking - as kind of the opposite of flushes.
* Maybe more direct user interfaces to control it (I'm wary of that though).

Mostly thought, the idea was  avoid rolling my own similar registration
infrastructure for this case.  Absolutely can do a subsystem without
a class if that seems to be the way to go. It'll be a little more complex
though.

Thanks,

Jonathan

> 
> thanks,
> 
> greg k-h
> 



From krzk at kernel.org  Fri Mar 21 02:40:56 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 21 Mar 2025 10:40:56 +0100
Subject: [PATCH v3 2/2] dt-bindings: arm: aspeed: add Nvidia's GB200NVL
 BMC
In-Reply-To: <20250320164633.101331-3-wthai@nvidia.com>
References: <20250320164633.101331-1-wthai@nvidia.com>
 <20250320164633.101331-3-wthai@nvidia.com>
Message-ID: <20250321-romantic-gentle-octopus-4aacd4@krzk-bin>

On Thu, Mar 20, 2025 at 04:46:33PM +0000, Willie Thai wrote:
> This patch adds a binding for GB200NVL BMC.

Please do not use "This commit/patch/change", but imperative mood. See
longer explanation here:
https://elixir.bootlin.com/linux/v5.17.1/source/Documentation/process/submitting-patches.rst#L95

> 
> The GB200NVL BMC is an Aspeed Ast2600 based BMC for Nvidia Blackwell GB200NVL platform.

Please wrap commit message according to Linux coding style / submission
process (neither too early nor over the limit):
https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597

Usually this is just one line. Commit msgs should be concise. "Add
binding for foo bar, an baz based board for making frubies".

Best regards,
Krzysztof



From brgl at bgdev.pl  Fri Mar 21 02:43:16 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Fri, 21 Mar 2025 10:43:16 +0100
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for PCIe3
In-Reply-To: <694b6638-92b2-4ac0-a175-bd29aea6cba9@kernel.org>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com> <694b6638-92b2-4ac0-a175-bd29aea6cba9@kernel.org>
Message-ID: <CAMRc=MfZrRp=VuEOLuMY_04JdyRrD+joGL56LwRFQ-+D-8Z_6w@mail.gmail.com>

On Fri, Mar 21, 2025 at 8:37?AM Krzysztof Kozlowski <krzk at kernel.org> wrote:
>
> On 20/03/2025 06:55, Wenbin Yao wrote:
> > From: Qiang Yu <quic_qianyu at quicinc.com>
> >
> > Enable the pwrctrl driver, which is utilized to manage the power supplies
> > of the devices connected to the PCI slots. This ensures that the voltage
> > rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
> > on/off if they are described under PCIe port device tree node.
> >
> > Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> > Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> > ---
> >  arch/arm64/configs/defconfig | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index 85ec2fba1..de86d1121 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
> >  CONFIG_PCI_ENDPOINT=y
> >  CONFIG_PCI_ENDPOINT_CONFIGFS=y
> >  CONFIG_PCI_EPF_TEST=m
> > +CONFIG_PCI_PWRCTL_SLOT=y
> Bartosz,
>
> Wasn't the intention to select it the same way as PCI_PWRCTL_PWRSEQ is
> selected?
>
> Best regards,
> Krzysztof
>

For sure. I would expect there to be something like:

select PCI_PWRCTL_SLOT if ARCH_QCOM

in Kconfig and nothing in defconfig.

Bartosz


From patrice.chotard at foss.st.com  Fri Mar 21 02:44:07 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:44:07 +0100
Subject: [PATCH 2/2] spi: spi-stm32-ospi: Make "resets" a required property
In-Reply-To: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
References: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
Message-ID: <20250321-upstream_ospi_required_resets-v1-2-9aa4702e3ae2@foss.st.com>

On some STM32MP2 SoCs, an Octo Memory Manager is embedded and
need to retrieve OSPI's reset to perform its own initialization.
Make "resets" property mandatory.

Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 drivers/spi/spi-stm32-ospi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index d4f413c8c3ce1a51d2302602d46c7605a8bbc605..d3839a4dacf9f2eb95bafad9f7a8538ce2bb3598 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -804,7 +804,7 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
 		return ret;
 	}
 
-	ospi->rstc = devm_reset_control_array_get_optional_exclusive(dev);
+	ospi->rstc = devm_reset_control_array_get_exclusive(dev);
 	if (IS_ERR(ospi->rstc))
 		return dev_err_probe(dev, PTR_ERR(ospi->rstc),
 				     "Can't get reset\n");

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:44:06 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:44:06 +0100
Subject: [PATCH 1/2] spi: dt-bindings: st,stm32mp25-ospi: Make "resets" a
 required property
In-Reply-To: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
References: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
Message-ID: <20250321-upstream_ospi_required_resets-v1-1-9aa4702e3ae2@foss.st.com>

Make "resets" a required property.

Fixes: bed97e35786a ("dt-bindings: spi: Add STM32 OSPI controller")
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml b/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
index 5f276f27dc4c1fd2056f129cafc1005eaee8008f..272bc308726b2dfdf3ec80740d70e0fd1bfc4fea 100644
--- a/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
+++ b/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
@@ -68,6 +68,7 @@ required:
   - compatible
   - reg
   - clocks
+  - resets
   - interrupts
   - st,syscfg-dlyb
 

-- 
2.25.1



From patrice.chotard at foss.st.com  Fri Mar 21 02:44:05 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Fri, 21 Mar 2025 10:44:05 +0100
Subject: [PATCH 0/2] spi: spi-stm32-ospi: dt-bindings fixes
Message-ID: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>

Make "resets" property mandatory.
Update spi-stm32-ospi driver and dt-bindings accordingly.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
Patrice Chotard (2):
      spi: dt-bindings: st,stm32mp25-ospi: Make "resets" a required property
      spi: spi-stm32-ospi: Make "resets" a required property

 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
 drivers/spi/spi-stm32-ospi.c                                 | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
---
base-commit: e94bd4ec45ac156616da285a0bf03056cd7430fc
change-id: 20250321-upstream_ospi_required_resets-34a8b17611b6

Best regards,
-- 
Patrice Chotard <patrice.chotard at foss.st.com>



From xianwei.zhao at amlogic.com  Fri Mar 21 02:49:42 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Fri, 21 Mar 2025 17:49:42 +0800
Subject: [PATCH] arm64: dts: amlogic: a4: fix dtb compilation warning
 issues
In-Reply-To: <5caa550a-ffdf-477d-92f4-a3222b7fba29@linaro.org>
References: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
 <5caa550a-ffdf-477d-92f4-a3222b7fba29@linaro.org>
Message-ID: <f2a69024-8c6a-4be4-888f-e37403a51700@amlogic.com>

Hi, Neil
    Thanks for your advice.

On 2025/3/21 17:37, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> On 21/03/2025 03:23, Xianwei Zhao via B4 Relay wrote:
>> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>
>> When use command 'make ARCH=arm64 dtbs_check W=1' to compile dtb,
>> a warning message appears.
>> "Warning (simple_bus_reg): /soc/bus at fe000000/pinctrl:
>> missing or empty reg/ranges property"
>>
>> Add the unit address to the pinctrl node to fix it.
> 
> I've delayed the pinctrl to next release so plase rebase
> the commit on top of 
> https://web.git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/log/?h=for-next
> and fix the warnings here, and make sure DTBS_CHECK still passes.
> 

Will do.

> Neil
> 
>>
>> Fixes: ce78f679e08c ("arm64: dts: amlogic: a4: add pinctrl node")
>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>> ---
>> ? arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 102 
>> +++++++++++++++-------------
>> ? 1 file changed, 55 insertions(+), 47 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi 
>> b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> index fa80fa365f13..582e0043024b 100644
>> --- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> @@ -51,87 +51,52 @@ pwrc: power-controller {
>> ? };
>>
>> ? &apb {
>> -???? gpio_intc: interrupt-controller at 4080 {
>> -???????????? compatible = "amlogic,a4-gpio-intc",
>> -????????????????????????? "amlogic,meson-gpio-intc";
>> -???????????? reg = <0x0 0x4080 0x0 0x20>;
>> -???????????? interrupt-controller;
>> -???????????? #interrupt-cells = <2>;
>> -???????????? amlogic,channel-interrupts =
>> -???????????????????? <10 11 12 13 14 15 16 17 18 19 20 21>;
>> -???? };
>> -
>> -???? gpio_ao_intc: interrupt-controller at 8e72c {
>> -???????????? compatible = "amlogic,a4-gpio-ao-intc",
>> -????????????????????????? "amlogic,meson-gpio-intc";
>> -???????????? reg = <0x0 0x8e72c 0x0 0x0c>;
>> -???????????? interrupt-controller;
>> -???????????? #interrupt-cells = <2>;
>> -???????????? amlogic,channel-interrupts = <140 141>;
>> -???? };
>> -
>> -???? periphs_pinctrl: pinctrl {
>> +???? periphs_pinctrl: pinctrl at 4000 {
>> ????????????? compatible = "amlogic,pinctrl-a4";
>> ????????????? #address-cells = <2>;
>> ????????????? #size-cells = <2>;
>> -???????????? ranges;
>> +???????????? ranges = <0x0 0x0 0x0 0x4000 0x0 0x280>;
>>
>> -???????????? gpiox: gpio at 4100 {
>> -???????????????????? reg = <0 0x4100 0 0x40>, <0 0x400c 0 0xc>;
>> +???????????? gpiox: gpio at 100 {
>> +???????????????????? reg = <0 0x100 0 0x40>, <0 0xc 0 0xc>;
>> ????????????????????? reg-names = "gpio", "mux";
>> ????????????????????? gpio-controller;
>> ????????????????????? #gpio-cells = <2>;
>> ????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_X<<8) 18>;
>> ????????????? };
>>
>> -???????????? gpiot: gpio at 4140 {
>> -???????????????????? reg = <0 0x4140 0 0x40>, <0 0x402c 0 0xc>;
>> +???????????? gpiot: gpio at 140 {
>> +???????????????????? reg = <0 0x140 0 0x40>, <0 0x2c 0 0xc>;
>> ????????????????????? reg-names = "gpio", "mux";
>> ????????????????????? gpio-controller;
>> ????????????????????? #gpio-cells = <2>;
>> ????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_T<<8) 23>;
>> ????????????? };
>>
>> -???????????? gpiod: gpio at 4180 {
>> -???????????????????? reg = <0 0x4180 0 0x40>, <0 0x4040 0 0x8>;
>> +???????????? gpiod: gpio at 180 {
>> +???????????????????? reg = <0 0x180 0 0x40>, <0 0x40 0 0x8>;
>> ????????????????????? reg-names = "gpio", "mux";
>> ????????????????????? gpio-controller;
>> ????????????????????? #gpio-cells = <2>;
>> ????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_D<<8) 16>;
>> ????????????? };
>>
>> -???????????? gpioe: gpio at 41c0 {
>> -???????????????????? reg = <0 0x41c0 0 0x40>, <0 0x4048 0 0x4>;
>> +???????????? gpioe: gpio at 1c0 {
>> +???????????????????? reg = <0 0x1c0 0 0x40>, <0 0x48 0 0x4>;
>> ????????????????????? reg-names = "gpio", "mux";
>> ????????????????????? gpio-controller;
>> ????????????????????? #gpio-cells = <2>;
>> ????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_E<<8) 2>;
>> ????????????? };
>>
>> -???????????? gpiob: gpio at 4240 {
>> -???????????????????? reg = <0 0x4240 0 0x40>, <0 0x4000 0 0x8>;
>> +???????????? gpiob: gpio at 240 {
>> +???????????????????? reg = <0 0x240 0 0x40>, <0 0 0 0x8>;
>> ????????????????????? reg-names = "gpio", "mux";
>> ????????????????????? gpio-controller;
>> ????????????????????? #gpio-cells = <2>;
>> ????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_B<<8) 14>;
>> ????????????? };
>>
>> -???????????? gpioao: gpio at 8e704 {
>> -???????????????????? reg = <0 0x8e704 0 0x16>, <0 0x8e700 0 0x4>;
>> -???????????????????? reg-names = "gpio", "mux";
>> -???????????????????? gpio-controller;
>> -???????????????????? #gpio-cells = <2>;
>> -???????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_AO<<8) 7>;
>> -???????????? };
>> -
>> -???????????? test_n: gpio at 8e744 {
>> -???????????????????? reg = <0 0x8e744 0 0x20>;
>> -???????????????????? reg-names = "gpio";
>> -???????????????????? gpio-controller;
>> -???????????????????? #gpio-cells = <2>;
>> -???????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_TEST_N<<8) 1>;
>> -???????????? };
>> -
>> ????????????? func-uart-a {
>> ????????????????????? uart_a_default: group-uart-a-pins1 {
>> ????????????????????????????? pinmux = <AML_PINMUX(AMLOGIC_GPIO_X, 11, 
>> 1)>,
>> @@ -186,4 +151,47 @@ uart_e_default: group-uart-e-pins {
>> ????????????????????? };
>> ????????????? };
>> ????? };
>> +
>> +???? gpio_intc: interrupt-controller at 4080 {
>> +???????????? compatible = "amlogic,a4-gpio-intc",
>> +????????????????????????? "amlogic,meson-gpio-intc";
>> +???????????? reg = <0x0 0x4080 0x0 0x20>;
>> +???????????? interrupt-controller;
>> +???????????? #interrupt-cells = <2>;
>> +???????????? amlogic,channel-interrupts =
>> +???????????????????? <10 11 12 13 14 15 16 17 18 19 20 21>;
>> +???? };
>> +
>> +???? ao_pinctrl: pinctrl at 8e700 {
>> +???????????? compatible = "amlogic,pinctrl-a4";
>> +???????????? #address-cells = <2>;
>> +???????????? #size-cells = <2>;
>> +???????????? ranges = <0x0 0x0 0x0 0x8e700 0x0 0x80>;
>> +
>> +???????????? gpioao: gpio at 4 {
>> +???????????????????? reg = <0 0x4 0 0x16>, <0 0 0 0x4>;
>> +???????????????????? reg-names = "gpio", "mux";
>> +???????????????????? gpio-controller;
>> +???????????????????? #gpio-cells = <2>;
>> +???????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_AO<<8) 7>;
>> +???????????? };
>> +
>> +???????????? test_n: gpio at 44 {
>> +???????????????????? reg = <0 0x44 0 0x20>;
>> +???????????????????? reg-names = "gpio";
>> +???????????????????? gpio-controller;
>> +???????????????????? #gpio-cells = <2>;
>> +???????????????????? gpio-ranges = <&periphs_pinctrl 0 
>> (AMLOGIC_GPIO_TEST_N<<8) 1>;
>> +???????????? };
>> +???? };
>> +
>> +???? gpio_ao_intc: interrupt-controller at 8e72c {
>> +???????????? compatible = "amlogic,a4-gpio-ao-intc",
>> +????????????????????????? "amlogic,meson-gpio-intc";
>> +???????????? reg = <0x0 0x8e72c 0x0 0x0c>;
>> +???????????? interrupt-controller;
>> +???????????? #interrupt-cells = <2>;
>> +???????????? amlogic,channel-interrupts = <140 141>;
>> +???? };
>> +
>> ? };
>>
>> ---
>> base-commit: 73a143e436311183186ab4b365a84c662f2c9651
>> change-id: 20250317-fix-a4-pinctrl-node-9babfd44e085
>>
>> Best regards,
> 


From lkp at intel.com  Fri Mar 21 02:52:03 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 21 Mar 2025 17:52:03 +0800
Subject: [soc:amlogic/dt64] BUILD SUCCESS
 67c2799bf11fd0f1323579dead240bfda5b6a3b6
Message-ID: <202503211756.oeUukz8l-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git amlogic/dt64
branch HEAD: 67c2799bf11fd0f1323579dead240bfda5b6a3b6  arm64: dts: Add gpio_intc node for Amlogic A5 SoCs

elapsed time: 1446m

configs tested: 11
configs skipped: 184

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
arc    randconfig-001-20250321    gcc-13.3.0
arc    randconfig-002-20250321    gcc-11.5.0
arm    randconfig-001-20250321    clang-19
arm    randconfig-002-20250321    gcc-9.3.0
arm    randconfig-003-20250321    gcc-5.5.0
arm    randconfig-004-20250321    clang-21
arm64             allmodconfig    clang-19
arm64  randconfig-001-20250321    gcc-5.5.0
arm64  randconfig-002-20250321    gcc-5.5.0
arm64  randconfig-003-20250321    clang-20
arm64  randconfig-004-20250321    clang-21

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From quentin.schulz at cherry.de  Fri Mar 21 02:53:58 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Fri, 21 Mar 2025 10:53:58 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
Message-ID: <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>

Hi Dragan,

On 3/21/25 4:28 AM, Dragan Simic wrote:
> The differences in the vendor-approved CPU and GPU OPPs for the standard
> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J variant [2]
> come from the latter, presumably, supporting an extended temperature range
> that's usually associated with industrial applications, despite the two SoC
> variant datasheets specifying the same upper limit for the allowed ambient
> temperature for both variants.  However, the lower temperature limit is

RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended 
Operating Conditions, Table 3-2, Ambient Operating Temperature.

> specified much lower for the RK3588J variant. [1][2]
> 
> To be on the safe side and to ensure maximum longevity of the RK3588J SoCs,
> only the CPU and GPU OPPs that are declared by the vendor to be always safe
> for this SoC variant may be provided.  As explained by the vendor [3] and
> according to its datasheet, [2] the RK3588J variant can actually run safely
> at higher CPU and GPU OPPs as well, but only when not enjoying the assumed
> extended temperature range that the RK3588J, as an SoC variant targeted

"only when not enjoying the assumed extended temperature range" is 
extrapolated by me/us and not confirmed by Rockchip themselves. I've 
asked for a statement on what "industrial environment" they specify in 
the Normal Mode explanation means since it's the only time they use the 
term. I've yet to receive an answer. The only thing Rockchip in their 
datasheet is that the overdrive mode will shorten lifetime when used for 
a long time, especially in high temperature conditions. It's not clear 
whether we can use the overdrive mode even within the RK3588 typical 
range of operation.

> specifically at industrial applications, is made (or binned) for.
> 
> Thus, only the CPU and GPU OPPs that are specified by the vendor to be safe
> throughout the entire RK3588J's extended temperature range may be provided,
> while anyone who actually can ensure that their RK3588J-based board is
> never going to run within the extended temperature range, may probably
> safely apply a DT overlay that adds the higher CPU and GPU OPPs.  As we

Wouldn't say "safely" here, Rockchip still says that running overdrive 
mode for a long time may shorten lifetime... that followed by 
"especially in high temperature condition" doesn't mean that operating 
the RK3588J within the RK3588 typical range is safe to do.

> obviously can't know what will be the runtime temperature conditions for
> a particular board, we may provide only the always-safe OPPs.
> 
> With all this and the downstream RK3588(J) DT definitions [4][5] in mind,
> let's delete the RK3588J CPU and GPU OPPs that are not considered belonging
> to the normal operation mode for this SoC variant.  To quote the RK3588J
> datasheet [2], "normal mode means the chipset works under safety voltage
> and frequency;  for the industrial environment, highly recommend to keep in
> normal mode, the lifetime is reasonably guaranteed", while "overdrive mode
> brings higher frequency, and the voltage will increase accordingly;  under
> the overdrive mode for a long time, the chipset may shorten the lifetime,
> especially in high temperature condition".
> 
> To sum up the RK3588J datasheet [2] and the vendor-provided DTs, [4][5]
> the maximum allowed CPU core and GPU frequencies are as follows:
> 
>     IP core    | Normal mode | Overdrive mode
>    ------------+-------------+----------------
>     Cortex-A55 |   1,296 MHz |      1,704 MHz
>     Cortex-A76 |   1,608 MHz |      2,016 MHz
>     GPU        |     700 MHz |        850 MHz
> 

The NPU too is impacted by this, so maybe list it anyway here? Even if 
we don't support it right now and don't have OPPs for it.

> Unfortunately, when it comes to the actual voltages for the RK3588J CPU and
> GPU OPPs, there's a discrepancy between the RK3588J datasheet [2] and the
> downstream kernel code. [4][5]  The RK3588J datasheet states that "the max.
> working voltage of CPU/GPU/NPU is 0.75 V under the normal mode", while the
> downstream kernel code actually allows voltage ranges that go up to 0.95 V,
> which is still within the voltage range allowed by the datasheet.  However,
> the RK3588J datasheet also tells us to "strictly refer to the software
> configuration of SDK and the hardware reference design", so let's embrace
> the voltage ranges provided by the downstream kernel code, which also
> prevents the undesirable theoretical outcome of ending up with no usable
> OPPs on a particular board, as a result of the board's voltage regulator(s)
> being unable to deliver the exact voltages, for whatever reason.
> 
> The above-described voltage ranges for the RK3588J CPU OPPs remain taken
> from the downstream kernel code [4][5] by picking the highest, worst-bin
> values, which ensure that all RK3588J bins will work reliably.  Yes, with
> some power inevitably wasted as unnecessarily generated heat, but the
> reliability is paramount, together with the longevity.  This deficiency
> may be revisited separately at some point in the future.
> 
> The provided RK3588J CPU OPPs follow the slightly debatable "provide only
> the highest-frequency OPP from the same-voltage group" approach that's been

Interesting that we went for a different strategy for the GPU OPPs :)

> established earlier, [6] as a result of the "same-voltage, lower-frequency"
> OPPs being considered inefficient from the IPA governor's standpoint, which
> may also be revisited separately at some point in the future.
> 
> [1] https://wiki.friendlyelec.com/wiki/images/e/ee/Rockchip_RK3588_Datasheet_V1.6-20231016.pdf
> [2] https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2403201054_Rockchip-RK3588J_C22364189.pdf
> [3] https://lore.kernel.org/linux-rockchip/e55125ed-64fb-455e-b1e4-cebe2cf006e4 at cherry.de/T/#u
> [4] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
> [5] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
> [6] https://lore.kernel.org/all/20240229-rk-dts-additions-v3-5-6afe8473a631 at gmail.com/
> 
> Fixes: 667885a68658 ("arm64: dts: rockchip: Add OPP data for CPU cores on RK3588j")
> Fixes: a7b2070505a2 ("arm64: dts: rockchip: Split GPU OPPs of RK3588 and RK3588j")
> Cc: stable at vger.kernel.org
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: Alexey Charkov <alchark at gmail.com>
> Helped-by: Quentin Schulz <quentin.schulz at cherry.de>

Reported-by/Suggested-by?

I don't see Helped-by in 
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes

I see 2496b2aaacf137250f4ca449f465e2cadaabb0e8 got the Helped-by 
replaced by a Suggested-by for example, but I see other patches with 
Helped-by... if that is a standard trailer for kernel patches, then 
maybe we should add it to that doc?

> Signed-off-by: Dragan Simic <dsimic at manjaro.org>
> ---
>   arch/arm64/boot/dts/rockchip/rk3588j.dtsi | 53 ++++++++---------------
>   1 file changed, 17 insertions(+), 36 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
> index bce72bac4503..3045cb3bd68c 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
> @@ -11,74 +11,59 @@ cluster0_opp_table: opp-table-cluster0 {
>   		compatible = "operating-points-v2";
>   		opp-shared;
>   
> -		opp-1416000000 {
> -			opp-hz = /bits/ 64 <1416000000>;
> +		opp-1200000000 {
> +			opp-hz = /bits/ 64 <1200000000>;
>   			opp-microvolt = <750000 750000 950000>;
>   			clock-latency-ns = <40000>;
>   			opp-suspend;
>   		};
> -		opp-1608000000 {
> -			opp-hz = /bits/ 64 <1608000000>;
> -			opp-microvolt = <887500 887500 950000>;
> -			clock-latency-ns = <40000>;
> -		};
> -		opp-1704000000 {
> -			opp-hz = /bits/ 64 <1704000000>;
> -			opp-microvolt = <937500 937500 950000>;
> +		opp-1296000000 {
> +			opp-hz = /bits/ 64 <1296000000>;
> +			opp-microvolt = <775000 775000 950000>;

Got tricked by this one.

In the Rockchip vendor kernel, the opp-microvolt is 750000 750000 
950000, so the same as CPU OPP 1.2GHz. However, the opp-microvolt-L1 and 
L0 are higher than that. Only a couple of the OPPs in vendor kernel 
actually have opp-microvolt-L* higher than opp-microvolt, that is a 
noteworthy oddity for anyone reviewing this patch :)

Anyway, that is correct, we take the highest voltage among all defined 
opp-microvolt* properties.

I only have comments on the commit log, the diff is fine so:

Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>

Thanks!
Quentin


From mripard at kernel.org  Fri Mar 21 02:54:55 2025
From: mripard at kernel.org (Maxime Ripard)
Date: Fri, 21 Mar 2025 09:54:55 +0000
Subject: [PATCH v8 2/5] drm/bridge: add support for refcounting
In-Reply-To: <20250320-drm-bridge-refcount-v8-2-b3ddaa9f1368@bootlin.com>
References: <20250320-drm-bridge-refcount-v8-2-b3ddaa9f1368@bootlin.com>
Message-ID: <400466cd3c229ea6c6cb25e2a58cee27@kernel.org>

On Thu, 20 Mar 2025 16:42:11 +0100, Luca Ceresoli wrote:
> DRM bridges are currently considered as a fixed element of a DRM card, and
> thus their lifetime is assumed to extend for as long as the card
> exists. New use cases, such as hot-pluggable hardware with video bridges,
> require DRM bridges to be added to and removed from a DRM card without
> tearing the card down. This is possible for connectors already (used by DP
> 
> [ ... ]

Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks!
Maxime


From xianwei.zhao at amlogic.com  Fri Mar 21 02:58:01 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Fri, 21 Mar 2025 17:58:01 +0800
Subject: [PATCH] arm64: dts: amlogic: a4: fix dtb compilation warning
 issues
In-Reply-To: <e21f3e39-573d-4391-885a-2df7c2598d80@kernel.org>
References: <20250321-fix-a4-pinctrl-node-v1-1-5719f9f09932@amlogic.com>
 <e21f3e39-573d-4391-885a-2df7c2598d80@kernel.org>
Message-ID: <f5756484-fb93-447c-a6aa-a76f518e3b48@amlogic.com>

Hi Krzysztof,
     Thanks for your reply.

On 2025/3/21 17:25, Krzysztof Kozlowski wrote:
> [ EXTERNAL EMAIL ]
> 
> On 21/03/2025 03:23, Xianwei Zhao via B4 Relay wrote:
>> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>
>> When use command 'make ARCH=arm64 dtbs_check W=1' to compile dtb,
>> a warning message appears.
>> "Warning (simple_bus_reg): /soc/bus at fe000000/pinctrl:
>> missing or empty reg/ranges property"
>>
>> Add the unit address to the pinctrl node to fix it.
>>
>> Fixes: ce78f679e08c ("arm64: dts: amlogic: a4: add pinctrl node")
>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>> ---
>>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi | 102 +++++++++++++++-------------
>>   1 file changed, 55 insertions(+), 47 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> index fa80fa365f13..582e0043024b 100644
>> --- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
>> @@ -51,87 +51,52 @@ pwrc: power-controller {
>>   };
>>
>>   &apb {
>> -     gpio_intc: interrupt-controller at 4080 {
>> -             compatible = "amlogic,a4-gpio-intc",
>> -                          "amlogic,meson-gpio-intc";
>> -             reg = <0x0 0x4080 0x0 0x20>;
>> -             interrupt-controller;
>> -             #interrupt-cells = <2>;
>> -             amlogic,channel-interrupts =
>> -                     <10 11 12 13 14 15 16 17 18 19 20 21>;
>> -     };
>> -
>> -     gpio_ao_intc: interrupt-controller at 8e72c {
>> -             compatible = "amlogic,a4-gpio-ao-intc",
>> -                          "amlogic,meson-gpio-intc";
>> -             reg = <0x0 0x8e72c 0x0 0x0c>;
>> -             interrupt-controller;
>> -             #interrupt-cells = <2>;
>> -             amlogic,channel-interrupts = <140 141>;
>> -     };
> 
> 
> Not related to the change you described in commit msg.
> 

I will add the corresponding description in commit msg.

> 
> Best regards,
> Krzysztof


From peter.chen at cixtech.com  Fri Mar 21 03:31:55 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Fri, 21 Mar 2025 18:31:55 +0800
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts
 support
In-Reply-To: <86bjtun4an.wl-maz@kernel.org>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
 <20250305053823.2048217-6-peter.chen@cixtech.com>
 <86frj8m4be.wl-maz@kernel.org>
 <Z9vmeTj68LmwinPD@nchen-desktop>
 <86bjtun4an.wl-maz@kernel.org>
Message-ID: <Z91AG0lH1JNN7NHq@nchen-desktop>

On 25-03-21 09:04:00, Marc Zyngier wrote:
> > On 25-03-20 09:36:37, Marc Zyngier wrote:
> > > Peter Chen <peter.chen at cixtech.com> wrote:
> > > >
> > > > +     pmu-a520 {
> > > > +             compatible = "arm,cortex-a520-pmu";
> > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> > > > +     };
> > > > +
> > > > +     pmu-a720 {
> > > > +             compatible = "arm,cortex-a720-pmu";
> > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> > > > +     };
> > > > +
> > > > +     pmu-spe {
> > > > +             compatible = "arm,statistical-profiling-extension-v1";
> > > > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
> > > > +     };
> > >
> > > SPE should follow the same model as the PMU, as each CPU has its own
> > > SPE implementation, exposing different micro-architectural details.
> > >
> >
> > Hi Marc,
> >
> > Thanks for your reply. But there is only one compatible string
> > "statistical-profiling-extension-v1" at drivers/perf/arm_spe_pmu.c,
> > how could differentiate pmu-spe-a720 and pmu-spe-a520, do I need
> > to change arm_spe_pmu.c as well?
> 
> I don't think there is a need to have different compatible. The driver
> can probe which CPU this is on, and work out the implemented
> subfeatures from the PMSIDR_EL1 register. New compatible strings are
> better avoided when there is a way to probe/discover the HW (and in
> most cases, there is).
> 
> Note that this equally applies to TRBE, which also explicitly deals
> with interrupt partitioning and yet only has a single compatible.
> Please consider adding TRBE support when you repost this series.
> 

Hi Marc,

Thanks for your comment, we need to discuss it internally. Since it
is very initial dts support for CIX sky1 SoC, I will delete pmu-spe
support at this time, and add better support for it when adding
more components next time.

-- 

Best regards,
Peter


From maxime.chevallier at bootlin.com  Fri Mar 21 03:35:01 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri, 21 Mar 2025 11:35:01 +0100
Subject: [PATCH net-next] net: stmmac: Call xpcs_config_eee_mult_fact() only when xpcs is present
Message-ID: <20250321103502.1303539-1-maxime.chevallier@bootlin.com>

Some dwmac variants such as dwmac_socfpga don't use xpcs but lynx_pcs.

Don't call xpcs_config_eee_mult_fact() in this case, as this causes a
crash at init :

 Unable to handle kernel NULL pointer dereference at virtual address 00000039 when write

 [...]

 Call trace:
  xpcs_config_eee_mult_fact from stmmac_pcs_setup+0x40/0x10c
  stmmac_pcs_setup from stmmac_dvr_probe+0xc0c/0x1244
  stmmac_dvr_probe from socfpga_dwmac_probe+0x130/0x1bc
  socfpga_dwmac_probe from platform_probe+0x5c/0xb0

Fixes: 060fb27060e8 ("net: stmmac: call xpcs_config_eee_mult_fact()")
Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
This targets net-next as the blamed commit is also still in net-next.

 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 7c0a4046bbe3..836f2848dfeb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -524,7 +524,8 @@ int stmmac_pcs_setup(struct net_device *ndev)
 	if (ret)
 		return dev_err_probe(priv->device, ret, "No xPCS found\n");
 
-	xpcs_config_eee_mult_fact(xpcs, priv->plat->mult_fact_100ns);
+	if (xpcs)
+		xpcs_config_eee_mult_fact(xpcs, priv->plat->mult_fact_100ns);
 
 	priv->hw->xpcs = xpcs;
 
-- 
2.48.1



From linux at armlinux.org.uk  Fri Mar 21 03:40:30 2025
From: linux at armlinux.org.uk (Russell King (Oracle))
Date: Fri, 21 Mar 2025 10:40:30 +0000
Subject: [PATCH net-next] net: stmmac: Call xpcs_config_eee_mult_fact()
 only when xpcs is present
In-Reply-To: <20250321103502.1303539-1-maxime.chevallier@bootlin.com>
References: <20250321103502.1303539-1-maxime.chevallier@bootlin.com>
Message-ID: <Z91CHjqVc0-BmTPX@shell.armlinux.org.uk>

On Fri, Mar 21, 2025 at 11:35:01AM +0100, Maxime Chevallier wrote:
> Some dwmac variants such as dwmac_socfpga don't use xpcs but lynx_pcs.
> 
> Don't call xpcs_config_eee_mult_fact() in this case, as this causes a
> crash at init :
> 
>  Unable to handle kernel NULL pointer dereference at virtual address 00000039 when write
> 
>  [...]
> 
>  Call trace:
>   xpcs_config_eee_mult_fact from stmmac_pcs_setup+0x40/0x10c
>   stmmac_pcs_setup from stmmac_dvr_probe+0xc0c/0x1244
>   stmmac_dvr_probe from socfpga_dwmac_probe+0x130/0x1bc
>   socfpga_dwmac_probe from platform_probe+0x5c/0xb0
> 
> Fixes: 060fb27060e8 ("net: stmmac: call xpcs_config_eee_mult_fact()")
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>

Yes, I had noticed that but haven't had time to patch it, so thanks for
submitting the patch. However, I think the code structure could be
better in this function. Let's get the bug fixed, so:

Reviewed-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


From arnd at arndb.de  Fri Mar 21 03:41:59 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 11:41:59 +0100
Subject: [soc:soc/drivers 20/24] ERROR: modpost: "__ffsdi2"
 [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
In-Reply-To: <CAMuHMdUeynpmUUmZPViEBttANFmEhpjFn0wqNc1wQB6wRbd0rQ@mail.gmail.com>
References: <202503211029.DnQpqsJs-lkp@intel.com>
 <927105f8-4aa8-4579-ac2e-bce4bce12b1e@app.fastmail.com>
 <CAMuHMdUeynpmUUmZPViEBttANFmEhpjFn0wqNc1wQB6wRbd0rQ@mail.gmail.com>
Message-ID: <86813d50-d4c2-4220-a5a8-2a264b37f7d4@app.fastmail.com>

On Fri, Mar 21, 2025, at 10:36, Geert Uytterhoeven wrote:
>> >
>> > ERROR: modpost: "__delay" [drivers/net/mdio/mdio-cavium.ko] undefined!
>
> Bug in driver (must not use __delay() directly).
>
>> > ERROR: modpost: "devm_of_clk_add_hw_provider"
>> > [drivers/media/i2c/tc358746.ko] undefined!
>> > ERROR: modpost: "devm_clk_hw_register" [drivers/media/i2c/tc358746.ko]
>> > undefined!
>> > ERROR: modpost: "of_clk_hw_simple_get" [drivers/media/i2c/tc358746.ko]
>> > undefined!
>
> Missing dependencies for driver.

Agreed, but both of these only break the build on sh because
the architecture code is different from the others. It's obviously
best to fix these in the drivers, I just wouldn't expect the
driver maintainers to care unless someone sends them a patch/

>> >>> ERROR: modpost: "__ffsdi2" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined!
>>
>> This comes from __bf_shf(spec) in omnia_mcu_request_irq().
>>
>> As far as I can tell, this is not your problem but in the
>> SH architecture missing one of the libgcc functions that are
>> called by gcc.
>>
>> Since this is only for compile-testing sh allmodconfig, and
>> that is already broken because of other bugs, I'm not going
>> to care either.
>>
>> Adding the linux-sh list to Cc, it would be nice to get a clean
>> build again. All four problems should be trivial to address,
>> and some of these have been broken for many years.
>
> So one SH-specific issue to fix...

There is also the missing clone3 syscall that has been
causing a warning for many years.

      Arnd


From maz at kernel.org  Fri Mar 21 03:59:47 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 21 Mar 2025 10:59:47 +0000
Subject: [PATCH RFC] KVM: arm64: PMU: Use multiple host PMUs
In-Reply-To: <54cb5388-e278-41de-be29-d578cc5c37c5@daynix.com>
References: <20250319-hybrid-v1-1-4d1ada10e705@daynix.com>
	<Z9pze3J2_zrTk_yC@linux.dev>
	<e8324d9d-3756-41cf-a102-28572e302368@daynix.com>
	<86plidmjwh.wl-maz@kernel.org>
	<bd681ec6-0b4c-47d9-8a4a-b7324c0883a6@daynix.com>
	<86o6xxmg87.wl-maz@kernel.org>
	<aabd71eb-286b-475c-a30e-d5cf5c4f2769@daynix.com>
	<86msdhmemw.wl-maz@kernel.org>
	<cd7b4528-34a3-4d87-9711-acc2c2e6f6e1@daynix.com>
	<86ldt0n9w1.wl-maz@kernel.org>
	<Z9sSMJAlf7cQ5viu@linux.dev>
	<0d84bc94-1c65-4737-a2eb-aa7f96a7d1e0@daynix.com>
	<86iko4m5i4.wl-maz@kernel.org>
	<ba9cd6d2-1ee5-478a-8102-42b4dac411ce@daynix.com>
	<86cyebmxo7.wl-maz@kernel.org>
	<54cb5388-e278-41de-be29-d578cc5c37c5@daynix.com>
Message-ID: <86a59emyxo.wl-maz@kernel.org>

On Fri, 21 Mar 2025 06:20:49 +0000,
Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> 
> On 2025/03/21 2:14, Marc Zyngier wrote:
> > On Thu, 20 Mar 2025 09:52:59 +0000,
> > Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >> 
> >> On 2025/03/20 18:10, Marc Zyngier wrote:
> >>> On Thu, 20 Mar 2025 06:03:35 +0000,
> >>> Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >>>> 
> >>>> On 2025/03/20 3:51, Oliver Upton wrote:
> >>>>> On Wed, Mar 19, 2025 at 06:38:38PM +0000, Marc Zyngier wrote:
> >>>>>> On Wed, 19 Mar 2025 11:51:21 +0000, Akihiko Odaki <akihiko.odaki at daynix.com> wrote:
> >>>>>>> What about setting the flag automatically when a user fails to pin
> >>>>>>> vCPUs to CPUs that are covered by one PMU? There would be no change if
> >>>>>>> a user correctly pins vCPUs as it is. Otherwise, they will see a
> >>>>>>> correct feature set advertised to the guest and the cycle counter
> >>>>>>> working.
> >>>>>> 
> >>>>>> How do you know that the affinity is "correct"? VCPU affinity can be
> >>>>>> changed at any time. I, for one, do not want my VMs to change
> >>>>>> behaviour because I let the vcpus bounce around as the scheduler sees
> >>>>>> fit.
> >>>> 
> >>>> Checking the affinity when picking the default PMU; the vCPU affinity
> >>>> is the only thing that rules the choice of the default PMU even now.
> >>>> 
> >>>> Perhaps we may model the API as follows: introduce another "composite"
> >>>> PMU that works on any core but only exposes the cycle counter. Robust
> >>>> VMMs will choose it or one of hardware PMUs with
> >>>> KVM_ARM_VCPU_PMU_V3_SET_PMU. KVM will choose the default PMU according
> >>>> to the vCPU affinity at the point of KVM_ARM_VCPU_INIT otherwise. If
> >>>> the affinity is covered by one hardware PMU, that PMU will be chosen
> >>>> as the default. The "composite" PMU will be the default otherwise.
> >>> 
> >>> This makes no sense to me. A VCPU is always affine to a PMU, because
> >>> we do not support configurations where only some CPUs have a PMU. This
> >>> is an all-or-nothing situation.
> >> 
> >> At least isn't it fine to have the composite PMU with a new value for
> >> KVM_ARM_VCPU_PMU_V3_SET_PMU?
> > 
> > Not sure KVM_ARM_VCPU_PMU_V3_SET_PMU is the right hook (it takes a PMU
> > 'type', which is under control of the perf subsystem). But if we can
> > find a value that is guaranteed to be unique, why not.
> > 
> >>> More importantly, you keep suggesting the same "new default", and I
> >>> keep saying NO.
> >>> 
> >>> My position is clear: if you want a *new* behaviour, you *must* add a
> >>> new flag that the VMM explicitly provides to enable this CC-only PMU.
> >>> No change in default behaviour at all.
> >>> 
> >>> I'm not going to move from that.
> >> 
> >> Why not? It will not break anything guaranteed to work in the past.
> > 
> > It doesn't have to be guaranteed. It just has to *exist*. That's the
> > Linux ABI for you.
> > 
> >> Currently KVM only guarantees that the emulated PMU correctly counts
> >> only when
> >> 1) the vCPU affinity is contained by one PMU and
> >> 2) it will not expand
> >> 
> >> Breaking these conditions will make the behavior of the emulated PMU
> >> undefined. Now I'm proposing to remove 1).
> > 
> > And I'm saying no to that. I'm also getting tired of arguing the same
> > point on and on.
> > 
> > We currently have two different behaviours:
> > 
> > - either you explicitly set a PMU, and the affinity of this PMU
> >    constraints the affinity of the vcpus. The vcpus are not allowed to
> >    run outside of this affinity. Everything counts all the time.
> > 
> > - or you don't explicitly set a PMU, and a default PMU will be picked
> >    from the current affinity of the first vcpu. Your vcpus will be able
> >    to run anywhere, but the virtual PMU will *only* count when the
> >    vcpus are affine to the default PMU. When the vcpus are not affine
> >    to default PMU, *nothing* counts.
> > 
> > These two behaviours are ABI. They are not changing. They don't get
> > relaxed, they don't get tightened, they stay just as they are,
> > forever.
> 
> Is the latter one is really ABI? I see it as part of behaviors that
> are undefined and not included in ABI for the following reasons:
> 
> 1) It depends on the scheduler behavior, which cannot be ABI.

You're wrong. The task affinity is under complete control of
userspace. sched_setaffinity(2) is your friend.

> 2) It provides a broken PMU so the proposed behavioral change is
> similar a bug fix though I call it a undefined behavior instead of a
> bug as it is explicitly told that there is no assurance that the PMU
> works in such a scenario.

Call it undefined behaviour if you want, I call it ABI. This is how
the PMU has been handled on KVM/arm64 for the past 10 years, and the
fact that you (and I) don't like it doesn't make it less of an
existing behaviour that must be preserved.

> 3) The userspace could not have relied on it so the "no regressions"
> rule cannot be applied here; how can anyone have a userspace that
> relies on a kernel behavior that depends on scheduling?

Of course it has. Read the above.

Even more, I contend that your approach is just wrong. You want to
make random events count at random times, which is even worse. We can
at least pretend that the PMU hasn't recorded anything (which is true)
rather than saying "oh look, the cycle counter has ticked but we
didn't execute any instruction -- WTF were we doing?".

That approach is far worse than what we have today.

Let me give you an example:

- I have an asymmetric system with two types of CPUs (any odd
  big-little nonsense)

- I statically place my vcpus on physical CPUs so that only some vcpus
  are effectively generating events by using my knowledge of the
  "default PMU" behaviour.

- I perform system-wide profiling inside the guest with the full
  knowledge that only the vcpus I'm interested in will affect the
  event counts. This is deterministic.

- I can move vcpus around as I see fit to capture new counter sets
  with the same guarantees.

Your "count random stuff at random times on random CPUs" breaks this.

Is this a contrived example? Of course it is. Do we know for sure that
nobody in their right mind would do this? No, because we don't have a
mandate to decide what people can or cannot do with a behaviour that
has been established for that long.

> But for 3), Oliver raised a concern for the guest compatibility so I'd
> like to hear an explanation for that concern.

I've given it above, and in my reply to Oliver as well.

> > You want a *third* behaviour, go ahead. Define it the way you want.
> > But the behaviours described above will stay unchanged.
> > I'm looking forward to your patches implementing it, but I am also
> > done arguing on it.
> 
> I understand the discussion is tiring but I want to know the reasoning
> behind such a design decision before sending an RFC patch to a VMM
> (QEMU) so that I can explain them why it is necessary in turn.

But that's *again* where you got things completely wrong:

<allcaps>
  This is not a design decision, this is how things have always worked
  and we cannot break previous behaviours. This is unfortunate, but
  that's how the Linux kernel works.
</allcaps>

The only "design decision" is that we don't change established
behaviours, explicit or implicit. If you want to implement something
that matches this requirement, go ahead and post patches. I'll gladly
review them. If you cannot abide by this rule, then please stop
wasting your time (and mine).

Feel free to relay this to the QEMU folks who, in my experience, very
much value the notion of ABI and the preservation of existing
behaviours.

Now, that's my last email on this thread. Do no bother replying.

	M. (pretty annoyed)

-- 
Without deviation from the norm, progress is not possible.


From maz at kernel.org  Fri Mar 21 04:01:47 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 21 Mar 2025 11:01:47 +0000
Subject: [PATCH v4 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <Z91AG0lH1JNN7NHq@nchen-desktop>
References: <20250305053823.2048217-1-peter.chen@cixtech.com>
	<20250305053823.2048217-6-peter.chen@cixtech.com>
	<86frj8m4be.wl-maz@kernel.org>
	<Z9vmeTj68LmwinPD@nchen-desktop>
	<86bjtun4an.wl-maz@kernel.org>
	<Z91AG0lH1JNN7NHq@nchen-desktop>
Message-ID: <868qoymyuc.wl-maz@kernel.org>

On Fri, 21 Mar 2025 10:31:55 +0000,
Peter Chen <peter.chen at cixtech.com> wrote:
> 
> On 25-03-21 09:04:00, Marc Zyngier wrote:
> > > On 25-03-20 09:36:37, Marc Zyngier wrote:
> > > > Peter Chen <peter.chen at cixtech.com> wrote:
> > > > >
> > > > > +     pmu-a520 {
> > > > > +             compatible = "arm,cortex-a520-pmu";
> > > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> > > > > +     };
> > > > > +
> > > > > +     pmu-a720 {
> > > > > +             compatible = "arm,cortex-a720-pmu";
> > > > > +             interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> > > > > +     };
> > > > > +
> > > > > +     pmu-spe {
> > > > > +             compatible = "arm,statistical-profiling-extension-v1";
> > > > > +             interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_LOW 0>;
> > > > > +     };
> > > >
> > > > SPE should follow the same model as the PMU, as each CPU has its own
> > > > SPE implementation, exposing different micro-architectural details.
> > > >
> > >
> > > Hi Marc,
> > >
> > > Thanks for your reply. But there is only one compatible string
> > > "statistical-profiling-extension-v1" at drivers/perf/arm_spe_pmu.c,
> > > how could differentiate pmu-spe-a720 and pmu-spe-a520, do I need
> > > to change arm_spe_pmu.c as well?
> > 
> > I don't think there is a need to have different compatible. The driver
> > can probe which CPU this is on, and work out the implemented
> > subfeatures from the PMSIDR_EL1 register. New compatible strings are
> > better avoided when there is a way to probe/discover the HW (and in
> > most cases, there is).
> > 
> > Note that this equally applies to TRBE, which also explicitly deals
> > with interrupt partitioning and yet only has a single compatible.
> > Please consider adding TRBE support when you repost this series.
> > 
> 
> Hi Marc,
> 
> Thanks for your comment, we need to discuss it internally. Since it
> is very initial dts support for CIX sky1 SoC, I will delete pmu-spe
> support at this time, and add better support for it when adding
> more components next time.

And therefore making this machine even less useful than it already is?

<s> I think this is a great plan. </s>

	M.

-- 
Without deviation from the norm, progress is not possible.


From suzuki.poulose at arm.com  Fri Mar 21 04:02:02 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 21 Mar 2025 11:02:02 +0000
Subject: [PATCH v3 1/7] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <20250320-james-coresight-claim-tags-v3-1-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
 <20250320-james-coresight-claim-tags-v3-1-d3145c153820@linaro.org>
Message-ID: <3bbf8aee-7b84-405a-8a3f-648c74196c2c@arm.com>

On 20/03/2025 14:34, James Clark wrote:
> The self hosted claim tag will be reset on device probe in a later
> commit. We'll want to do this before coresight_register() is called so
> won't have a coresight_device and have to use cs_access instead.
> 
> Also make them public and create locked and unlocked versions for
> later use.
> 
> These look functions look like they set the whole tags register as one
> value, but they only set and clear the self hosted bit using a SET/CLR
> bits mechanism so also rename the functions to reflect this better.
> 
> Reviewed-by: Leo Yan <leo.yan at arm.com>
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>   drivers/hwtracing/coresight/coresight-core.c | 27 +++++++++++++++++++--------
>   include/linux/coresight.h                    |  3 ++-
>   2 files changed, 21 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index fb43ef6a3b1f..8471aefeac76 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -144,19 +144,30 @@ static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
>   	return coresight_read_claim_tags(csdev) != 0;
>   }
>   
> -static inline void coresight_set_claim_tags(struct coresight_device *csdev)
> +static inline void coresight_set_self_claim_tag(struct coresight_device *csdev)

nit: For consistency, this should be renamed to _unlocked ?

Rest looks fine to me

Suzuki


>   {
>   	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>   				     CORESIGHT_CLAIMSET);
>   	isb();
>   }
>   
> -static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
> +void coresight_clear_self_claim_tag(struct csdev_access *csa)
>   {
> -	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> +	if (csa->io_mem)
> +		CS_UNLOCK(csa->base);
> +	coresight_clear_self_claim_tag_unlocked(csa);
> +	if (csa->io_mem)
> +		CS_LOCK(csa->base);
> +}
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
> +
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
> +{
> +	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>   				     CORESIGHT_CLAIMCLR);
>   	isb();
>   }
> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
>   
>   /*
>    * coresight_claim_device_unlocked : Claim the device for self-hosted usage
> @@ -176,11 +187,11 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
>   	if (coresight_is_claimed_any(csdev))
>   		return -EBUSY;
>   
> -	coresight_set_claim_tags(csdev);
> +	coresight_set_self_claim_tag(csdev);
>   	if (coresight_is_claimed_self_hosted(csdev))
>   		return 0;
> -	/* There was a race setting the tags, clean up and fail */
> -	coresight_clear_claim_tags(csdev);
> +	/* There was a race setting the tag, clean up and fail */
> +	coresight_clear_self_claim_tag_unlocked(&csdev->access);
>   	return -EBUSY;
>   }
>   EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
> @@ -201,7 +212,7 @@ int coresight_claim_device(struct coresight_device *csdev)
>   EXPORT_SYMBOL_GPL(coresight_claim_device);
>   
>   /*
> - * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
> + * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
>    * Called with CS_UNLOCKed for the component.
>    */
>   void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
> @@ -211,7 +222,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>   		return;
>   
>   	if (coresight_is_claimed_self_hosted(csdev))
> -		coresight_clear_claim_tags(csdev);
> +		coresight_clear_self_claim_tag_unlocked(&csdev->access);
>   	else
>   		/*
>   		 * The external agent may have not honoured our claim
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index d79a242b271d..00134a80d358 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
>   
>   extern int coresight_claim_device(struct coresight_device *csdev);
>   extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
> -
> +void coresight_clear_self_claim_tag(struct csdev_access *csa);
> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
>   extern void coresight_disclaim_device(struct coresight_device *csdev);
>   extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
>   extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
> 



From Jonathan.Cameron at huawei.com  Fri Mar 21 04:13:18 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Fri, 21 Mar 2025 11:13:18 +0000
Subject: [PATCH v2 3/8] drivers/perf: hisi: Use ACPI driver_data to
 retrieve SLLC PMU information
In-Reply-To: <20250321073846.23507-4-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
	<20250321073846.23507-4-yangyicong@huawei.com>
Message-ID: <20250321111318.0000455e@huawei.com>

On Fri, 21 Mar 2025 15:38:41 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> Make use of struct acpi_device_id::driver_data for version specific
> information rather than judge the version register. This will help
> to simplify the probe process and also a bit easier for extension.
> 
> Factor out SLLC register definition to struct hisi_sllc_pmu_regs.
> No functional changes intended.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
LGTM
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>


From Jonathan.Cameron at huawei.com  Fri Mar 21 04:14:20 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Fri, 21 Mar 2025 11:14:20 +0000
Subject: [PATCH v2 5/8] drivers/perf: hisi: Relax the event number check
 of v2 PMUs
In-Reply-To: <20250321073846.23507-6-yangyicong@huawei.com>
References: <20250321073846.23507-1-yangyicong@huawei.com>
	<20250321073846.23507-6-yangyicong@huawei.com>
Message-ID: <20250321111420.00003182@huawei.com>

On Fri, 21 Mar 2025 15:38:43 +0800
Yicong Yang <yangyicong at huawei.com> wrote:

> From: Junhao He <hejunhao3 at huawei.com>
> 
> The supported event number range of each Uncore PMUs is provided by
> each driver in hisi_pmu::check_event and out of range events
> will be rejected. A later version with expanded event number range
> needs to register the PMU with updated hisi_pmu::check_event
> even if it's the only update, which means the expanded events
> cannot be used unless the driver's updated. However the unsupported
> events won't be counted by the hardware so we can relax the event
> number check to allow the use the expanded events.
> 
> Signed-off-by: Junhao He <hejunhao3 at huawei.com>
> Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron at huawei.com>


From goran.radni at gmail.com  Fri Mar 21 04:18:18 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Fri, 21 Mar 2025 12:18:18 +0100
Subject: [PATCH v2 3/4] dt-bindings: arm: stm32: Document Ultratronik's Fly board DT binding
In-Reply-To: <20250321111821.361419-1-goran.radni@gmail.com>
References: <20250321111821.361419-1-goran.radni@gmail.com>
Message-ID: <20250321111821.361419-4-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

This commit documents ultra-fly-sbc devicetree binding based on
STM32MP157 SoC.

Signed-off-by: Goran Ra?enovi? <gradenovic at ultratronik.de>
---
 Documentation/devicetree/bindings/arm/stm32/stm32.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index b6c56d4ce6b9..c1cb54ffb210 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -175,6 +175,11 @@ properties:
           - const: phytec,phycore-stm32mp157c-som
           - const: st,stm32mp157
 
+      - description: Ultratronik STM32MP1 SBC based Boards
+        items:
+          - const: ultratronik,stm32mp157c-ultra-fly-sbc
+          - const: st,stm32mp157
+
       - description: ST STM32MP257 based Boards
         items:
           - enum:
-- 
2.43.0



From goran.radni at gmail.com  Fri Mar 21 04:18:19 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Fri, 21 Mar 2025 12:18:19 +0100
Subject: [PATCH v2 4/4] ARM: dts: stm32: add initial support for stm32mp157-ultra-fly-sbc board
In-Reply-To: <20250321111821.361419-1-goran.radni@gmail.com>
References: <20250321111821.361419-1-goran.radni@gmail.com>
Message-ID: <20250321111821.361419-5-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

Add support for Ultratronik's stm32mp157c fly board. This board embeds
a STM32MP157c SOC and 1GB of DDR3. Several connections are available on
this boards: 2*USB2.0, 1*USB2.0 MiniUSB, Debug UART, 1*UART, 1*USART,
SDcard, RJ45, ...

This patch enables basic support for a kernel boot - SD-card or eMMC.

Signed-off-by: Goran Ra?enovi? <gradenovic at ultratronik.de>
---
 arch/arm/boot/dts/st/Makefile                 |    3 +-
 .../boot/dts/st/stm32mp157c-ultra-fly-sbc.dts | 1155 +++++++++++++++++
 2 files changed, 1157 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts

diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile
index b7d5d305cbbe..270d1c699e1a 100644
--- a/arch/arm/boot/dts/st/Makefile
+++ b/arch/arm/boot/dts/st/Makefile
@@ -66,7 +66,8 @@ dtb-$(CONFIG_ARCH_STM32) += \
 	stm32mp157c-lxa-tac-gen2.dtb \
 	stm32mp157c-odyssey.dtb \
 	stm32mp157c-osd32mp1-red.dtb \
-	stm32mp157c-phycore-stm32mp1-3.dtb
+	stm32mp157c-phycore-stm32mp1-3.dtb \
+	stm32mp157c-ultra-fly-sbc.dtb
 dtb-$(CONFIG_ARCH_U8500) += \
 	ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
diff --git a/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
new file mode 100644
index 000000000000..1778f5a527ba
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
@@ -0,0 +1,1155 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) Ultratronik GmbH 2024-2025 - All Rights Reserved
+ */
+
+/dts-v1/;
+#include "stm32mp157.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "STM STM32MP15x Ultratronik MMI_A7 board";
+	compatible = "ultratronik,stm32mp157c-ultra-fly-sbc", "st,stm32mp157";
+
+	aliases {
+		ethernet0 = &ethernet0;
+		serial0 = &uart4;
+		serial1 = &uart5;
+		serial2 = &uart7;
+		serial3 = &usart1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at c0000000 {
+		device_type = "memory";
+		reg = <0xC0000000 0x40000000>;
+	};
+
+	usb_otg_vbus: regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpioh 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		retram: retram at 38000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x38000000 0x10000>;
+			no-map;
+		};
+
+		mcuram: mcuram at 30000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x30000000 0x40000>;
+			no-map;
+		};
+
+		mcuram2: mcuram2 at 10000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10000000 0x40000>;
+			no-map;
+		};
+
+		vdev0vring0: vdev0vring0 at 10040000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10040000 0x2000>;
+			no-map;
+		};
+
+		vdev0vring1: vdev0vring1 at 10042000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10042000 0x2000>;
+			no-map;
+		};
+
+		vdev0buffer: vdev0buffer at 10044000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10044000 0x4000>;
+			no-map;
+		};
+
+		gpu_reserved: gpu at f8000000 {
+			reg = <0xf8000000 0x8000000>;
+			no-map;
+		};
+	};
+
+	leds: leds {
+		compatible = "gpio-leds";
+
+		led0{
+			label = "buzzer";
+			gpios = <&gpiof 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "none";
+		};
+
+		led1 {
+			label = "led1";
+			gpios = <&gpioa 12 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led2 {
+			label = "led2";
+			gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led3 {
+			label = "led3";
+			gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+
+		key-1 {
+			label = "KEY1";
+			gpios = <&gpiod 1 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <2>;
+		};
+
+		key-2 {
+			label = "KEY2";
+			gpios = <&gpiod 7 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <3>;
+		};
+	};
+};
+
+&adc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc1_ux_ain_pins_a>;
+	vdd-supply = <&vdd>;
+	vdda-supply = <&vdd>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	adc1: adc at 0 {
+		st,min-sample-time-nsecs = <5000>;
+		st,adc-channels = <0 1 6 13>; /* ANA0 ANA1 PF12 PC3 */
+		status = "okay";
+	};
+
+	adc2: adc at 100 {
+		st,adc-channels = <0 1 12>; /* ANA0 ANA1 INT_TEMP*/
+		st,min-sample-time-nsecs = <10000>;
+		status = "okay";
+
+		channel at 12 {
+			reg = <12>;  /* Channel 12 = internal temperature sensor */
+			label = "internal_temp";
+		};
+	};
+};
+
+&dac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dac_ux_ch1_pins_a &dac_ux_ch2_pins_a>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	dac1: dac at 1 {
+		status = "okay";
+	};
+
+	dac2: dac at 2 {
+		status = "okay";
+	};
+};
+
+&dts {
+	compatible = "st,stm32-thermal";
+	status = "okay";
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_ux_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_ux_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii-id";
+	max-speed = <1000>;
+	phy-handle = <&phy1>;
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy1: ethernet-phy at 1 {
+			reg = <1>;
+			interrupt-parent = <&gpiod>;
+			interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+};
+
+&gpioa {
+	gpio-line-names =
+	"#PMIC_IRQ", "", "", "", "DAC1", "DAC2", "", "",
+	"", "", "OTG_ID", "TIM1_4", "#LED1", "#LED2", "#LED3", "";
+};
+
+&gpiob {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioc {
+	gpio-line-names =
+	"#AMP_SD", "", "", "ANA5", "", "", "", "",
+	"", "", "", "", "", "PMIC_WAKEUP", "", "";
+};
+
+&gpiod {
+	gpio-line-names =
+	"#G_INT", "#TASTER1", "", "", "GPIO1", "GPIO2", "", "#TASTER2",
+	"", "", "", "", "", "", "TIM4_3", "TIM4_4";
+};
+
+&gpioe {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "PWM2", "", "", "", "", "";
+};
+
+&gpiof {
+	gpio-line-names =
+	"#SD1_CD", "SD1_WP", "BUZZER", "#DISP_POW", "BKL_POW", "#CAM_RES", "", "",
+	"", "TIM17_1N", "", "CAM_PWDN", "ANA6", "ENA_USB", "", "";
+};
+
+&gpiog {
+	gpio-line-names =
+	"#ESP_RES", "#ESP_BOOT", "GPIO3", "GPIO4", "", "", "", "",
+	"", "#TOUCH_IRQ", "", "", "", "", "", "#PCAP_RES";
+};
+
+&gpioh {
+	gpio-line-names =
+	"", "CAM_LED", "", "USB_OTG_PWR", "", "USB_OTG_OC", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioi {
+	gpio-line-names =
+	"BKL_PWM", "", "", "", "", "", "", "",
+	"#SPI_CS0", "", "", "#SPI_CS1", "", "", "", "";
+};
+
+&gpioj {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpiok {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioz {
+	gpio-line-names =
+	"", "", "", "#SPI_CS2", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c1_ux_pins_a>;
+	pinctrl-1 = <&i2c1_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <100>;
+	i2c-scl-falling-time-ns = <7>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	rtc at 32 {
+		compatible = "epson,rx8900";
+		reg = <0x32>;
+		epson,vdet-disable;
+		trickle-diode-disable;
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c4_ux_pins_a>;
+	pinctrl-1 = <&i2c4_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	pmic: pmic at 33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupts-extended = <&exti 0 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				st,mask-reset;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <0>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <750000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO4 0>;
+			};
+
+			v1v8: ldo6 {
+				regulator-name = "v1v8";
+				regulator-min-microvolt = <1600000>;/* offset +200 mv ??? */
+				regulator-max-microvolt = <1600000>;/* real 1800000 */
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO6 0>;
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+			};
+
+			bst_out: boost {
+				regulator-name = "bst_out";
+				interrupts = <IT_OCP_BOOST 0>;
+			};
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+				interrupts = <IT_OCP_OTG 0>;
+				regulator-active-discharge = <1>;
+			 };
+
+			 vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				interrupts = <IT_OCP_SWOUT 0>;
+				regulator-active-discharge = <1>;
+			 };
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&m_can2 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&m_can2_ux_pins_a>;
+	pinctrl-1 = <&m_can2_ux_sleep_pins_a>;
+	status = "okay";
+};
+
+&pinctrl {
+
+	adc1_ux_ain_pins_a: adc1-ux-ain-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F',12, ANALOG)>, /* ADC1 in6 */
+				 <STM32_PINMUX('C', 3, ANALOG)>; /* ADC2 in13 */
+		};
+	};
+
+	dac_ux_ch1_pins_a: dac-ux-ch1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 4, ANALOG)>;
+		};
+	};
+
+	dac_ux_ch2_pins_a: dac-ux-ch2-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_a: rgmii-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, AF11)>; /* ETH_RGMII_TX_CTL */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <2>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('H', 7, AF11)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins4 {
+			pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_sleep_a: rgmii-ux-sleep-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+				 <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+				 <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
+				 <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
+		};
+	};
+
+	i2c1_ux_pins_a: i2c1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c1_ux_pins_sleep_a: i2c1-1 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, ANALOG)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
+		};
+	};
+
+	m_can2_ux_pins_a: m-can2-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN1_TX */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN1_RX */
+			bias-disable;
+		};
+	};
+
+	m_can2_ux_sleep_pins_a: m-can2-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 6, ANALOG)>, /* CAN1_TX */
+				 <STM32_PINMUX('B', 5, ANALOG)>; /* CAN1_RX */
+		};
+	};
+	pwm1_ux_pins_a: pwm1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, AF1)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, AF1)>; /* TIM1_CH2N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm1_ux_sleep_pins_a: pwm1-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, ANALOG)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, ANALOG)>; /* TIM1_CH2N */
+		};
+	};
+
+	pwm4_ux_pins_a: pwm4-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, AF2)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, AF2)>; /* TIM4_CH4 */
+			bias-disable;
+		};
+	};
+
+	pwm4_ux_sleep_pins_a: pwm4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, ANALOG)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, ANALOG)>; /* TIM4_CH4 */
+		};
+	};
+
+	pwm5_ux_pins_a: pwm5-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, AF2)>; /* TIM5_CH4 */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm5_ux_sleep_pins_a: pwm5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, ANALOG)>; /* TIM5_CH4 */
+		};
+	};
+
+	pwm17_ux_pins_a: pwm17-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, AF1)>; /* TIM17_CH1N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm17_ux_sleep_pins_a: pwm17-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, ANALOG)>; /* TIM17_CH1N */
+		};
+	};
+
+	qspi_bk1_ux_pins_a: qspi-bk1-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, AF9)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B',10, AF9)>; /* QSPI_BK1_NCS */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+	};
+
+	qspi_bk1_ux_sleep_pins_a: qspi-bk1-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, ANALOG)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, ANALOG)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, ANALOG)>, /* QSPI_BK1_IO3 */
+				 <STM32_PINMUX('B',10, ANALOG)>; /* QSPI_BK1_NCS */
+		};
+	};
+
+	qspi_clk_ux_pins_a: qspi-clk_ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, AF9)>; /* QSPI_CLK */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <3>;
+		};
+	};
+
+	qspi_clk_ux_sleep_pins_a: qspi-clk-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, ANALOG)>; /* QSPI_CLK */
+		};
+	};
+
+	sai2a_ux_pins_a: sai2a-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, AF10)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, AF10)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, AF10)>; /* SAI2_MCLK_A */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sai2a_ux_sleep_pins_a: sai2a-1 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, ANALOG)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, ANALOG)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, ANALOG)>; /* SAI2_MCLK_A */
+		};
+	};
+
+	sdmmc1_ux_b4_pins_a: sdmmc1-ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C',10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C',11, AF12)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_od_pins_a: sdmmc1-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, AF12)>; /* SDMMC1_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+				 <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+		};
+	};
+
+	sdmmc2_ux_b4_pins_a: sdmmc2-ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_od_pins_a: sdmmc2-ux-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_sleep_pins_a: sdmmc2-ux-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
+				<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
+		};
+	};
+
+	sdmmc2_ux_d47_pins_a: sdmmc2-ux-d47-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_d47_sleep_pins_a: sdmmc2-ux-d47-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
+		};
+	};
+
+	uart4_ux_pins_a: uart4-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+	};
+
+	uart4_ux_idle_pins_a: uart4-ux-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+		};
+
+	uart4_ux_sleep_pins_a: uart4-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
+				<STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */
+		};
+	};
+
+	uart5_ux_pins_a: uart5-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX */
+			bias-disable;
+		};
+	};
+
+	uart5_ux_idle_pins_a: uart5-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>; /* UART5_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX*/
+			bias-disable;
+		};
+	};
+
+	uart5_ux_sleep_pins_a: uart5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>, /* UART5_TX */
+				 <STM32_PINMUX('B', 12, ANALOG)>; /* UART5_RX */
+		};
+	};
+
+	uart7_ux_pins_a: uart7-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+	};
+
+	uart7_ux_idle_pins_a: uart7-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-disable;
+		};
+	};
+
+	uart7_ux_sleep_pins_a: uart7-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>, /* USART7_RTS/DE */
+				 <STM32_PINMUX('E', 7, ANALOG)>; /* USART7_RX */
+		};
+	};
+};
+
+&pinctrl_z {
+
+	i2c4_ux_pins_a: i2c4-ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c4_ux_pins_sleep_a: i2c4-1 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
+		};
+	};
+
+	spi1_ux_pins_a: spi1-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
+			bias-disable;
+		};
+	};
+
+	spi1_ux_sleep_pins_a: spi1-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 0, ANALOG)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 1, ANALOG)>, /* SPI1_MISO */
+				<STM32_PINMUX('Z', 2, ANALOG)>; /* SPI1_MOSI */
+		};
+	};
+};
+
+&pwr_regulators {
+	vdd-supply = <&vdd>;
+	vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&qspi {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&qspi_clk_ux_pins_a &qspi_bk1_ux_pins_a>;
+	pinctrl-1 = <&qspi_clk_ux_sleep_pins_a &qspi_bk1_ux_sleep_pins_a>;
+	reg = <0x58003000 0x1000>, <0x70000000 0x1000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	flash0: flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <133000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&sdmmc1 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc1_ux_b4_pins_a>;
+	pinctrl-1 = <&sdmmc1_ux_b4_od_pins_a>;
+	pinctrl-2 = <&sdmmc1_ux_b4_sleep_pins_a>;
+	broken-cd;
+	st,neg-edge;
+	bus-width = <4>;
+	vmmc-supply = <&v3v3>;
+	no-1-8-v;
+	status = "okay";
+};
+
+&sdmmc2 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc2_ux_b4_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-1 = <&sdmmc2_ux_b4_od_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-2 = <&sdmmc2_ux_b4_sleep_pins_a &sdmmc2_ux_d47_sleep_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,neg-edge;
+	bus-width = <8>;
+	vmmc-supply = <&v3v3>;
+	vqmmc-supply = <&v3v3>;
+	mmc-ddr-3_3v;
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&spi1_ux_pins_a>;
+	pinctrl-1 = <&spi1_ux_sleep_pins_a>;
+	status = "okay";
+	cs-gpios = <&gpioi 8 0>, <&gpioi 11 0>, <&gpioz 3 0>;
+
+	flash: flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&timers1 {
+	/* spare dmas for other usage */
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm {
+		pinctrl-0 = <&pwm1_ux_pins_a>;
+		pinctrl-1 = <&pwm1_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 0 {
+		status = "okay";
+	};
+};
+
+&timers4 {
+	dmas = <&dmamux1 31 0x400 0x5>;
+	dma-names = "ch3";
+	status = "okay";
+
+	pwm4_4: pwm {
+		pinctrl-0 = <&pwm4_ux_pins_a>;
+		pinctrl-1 = <&pwm4_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+};
+
+&timers5 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm5_4: pwm {
+		pinctrl-0 = <&pwm5_ux_pins_a>;
+		pinctrl-1 = <&pwm5_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 4 {
+		status = "okay";
+	};
+};
+
+&timers17 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm17_4: pwm {
+		pinctrl-0 = <&pwm17_ux_pins_a>;
+		pinctrl-1 = <&pwm17_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 16 {
+		status = "okay";
+	};
+};
+
+&uart4 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
+	pinctrl-0 = <&uart4_ux_pins_a>;
+	pinctrl-1 = <&uart4_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart4_ux_idle_pins_a>;
+	pinctrl-3 = <&uart4_ux_pins_a>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart5_ux_pins_a>;
+	pinctrl-1 = <&uart5_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart5_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&uart7 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart7_ux_pins_a>;
+	pinctrl-1 = <&uart7_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart7_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&usart1 {
+	/*Muxing happens in uboot*/
+	status = "okay";
+};
+
+&usbh_ehci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbh_ohci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbotg_hs {
+	phys = <&usbphyc_port1 0>;
+	phy-names = "usb2-phy";
+	vbus-supply = <&usb_otg_vbus>;
+	status = "okay";
+};
+
+&usbphyc {
+	status = "okay";
+};
+
+&usbphyc_port0 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&usbphyc_port1 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&vrefbuf {
+	regulator-min-microvolt = <2500000>;
+	regulator-max-microvolt = <2500000>;
+	vdda-supply = <&vdd>;
+	status = "okay";
+};
-- 
2.43.0



From robin.murphy at arm.com  Fri Mar 21 04:35:30 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 21 Mar 2025 11:35:30 +0000
Subject: [PATCH] iommu: Split out and tidy up Arm Kconfig
In-Reply-To: <Z90St0D6hyphtOID@google.com>
References: <a614ec86ba78c09cd16e348f633f6bb38793391f.1742480488.git.robin.murphy@arm.com>
 <Z90St0D6hyphtOID@google.com>
Message-ID: <fe800f66-ed99-49ed-8010-67702ab4542d@arm.com>

On 2025-03-21 7:18 am, Pranjal Shrivastava wrote:
> On Thu, Mar 20, 2025 at 02:21:28PM +0000, Robin Murphy wrote:
>> There are quite a lot of options for the Arm drivers, still all buried
>> in the top-level Kconfig. For ease of use and consistency with all the
>> other subdirectories, break these out into drivers/arm. For similar
>> clarity and self-consistency, also tweak the ARM_SMMU sub-options to use
>> "if" instead of "depends", to match ARM_SMMU_V3. Lastly also clean up
>> the slightly messy description of ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT as
>> highlighted by Geert - by now we really shouldn't need commentary on
>> v4.x kernel behaviour anyway - and downgrade it to EXPERT as the first
>> step in the 6-year-old threat to remove it entirely.
>>
>> Cc: Geert Uytterhoeven <geert+renesas at glider.be>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>   drivers/iommu/Kconfig     | 157 +-------------------------------------
>>   drivers/iommu/arm/Kconfig | 144 ++++++++++++++++++++++++++++++++++
>>   2 files changed, 145 insertions(+), 156 deletions(-)
>>   create mode 100644 drivers/iommu/arm/Kconfig
>>
> 
> Thanks for this! It looks good.
> I was able to toggle configs and build for arm64.
> 
>> +
>> +config QCOM_IOMMUa
> Nit: I don't have much context but:
> 
> 1. Shall this be in .../arm/Kconfig?

Yes, it represents arm/arm-smmu/qcom-iommu.c

> Is this an custom
> implementation of some arm-smmu version? If yes, then maybe we can
> update the help string while at it?

It's based on driving preconfigured SMMU S1 contexts individually, but 
with Qualcomm-specific bindings and usage flavour, hence why it lives 
next to arm-smmu to share code, but remains its own distinct thing.

>> +	# Note: iommu drivers cannot (yet?) be built as modules
> 
> 2. I don't think this is true now? Shall we remove this comment?

Indeed it's out of date now, but I see that in itself still serving some 
purpose as an indicator that nobody's yet looked to see if this driver 
*could* be made modular, so I chose to leave it as-is.

>> +	bool "Qualcomm IOMMU Support"
>> +	depends on ARCH_QCOM || COMPILE_TEST
>> +	depends on !GENERIC_ATOMIC64	# for IOMMU_IO_PGTABLE_LPAE
>> +	select QCOM_SCM
>> +	select IOMMU_API
>> +	select IOMMU_IO_PGTABLE_LPAE
>> +	select ARM_DMA_USE_IOMMU
>> +	help
>> +	  Support for IOMMU on certain Qualcomm SoCs.
>>
> 
> With the above nits:
> 
> Reviewed-by: Pranjal Shrivastava <praan at google.com>

Thanks!

Robin.


From david at redhat.com  Fri Mar 21 04:37:10 2025
From: david at redhat.com (David Hildenbrand)
Date: Fri, 21 Mar 2025 12:37:10 +0100
Subject: [PATCH v3 0/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
Message-ID: <20250321113713.204682-1-david@redhat.com>

Based on mm/unstable.

Currently, uprobe_write_opcode() implements COW-breaking manually, which is
really far from ideal. Further, there is interest in supporting uprobes on
hugetlb pages [1], and leaving at least the COW-breaking to the core will
make this much easier.

Also, I think the current code doesn't really handle some things
properly (see patch #3) when replacing/zapping pages.

Let's rewrite it, to leave COW-breaking to the fault handler, and handle
registration/unregistration by temporarily unmapping the anonymous page,
modifying it, and mapping it again. We still have to implement
zapping of anonymous pages ourselves, unfortunately.

We could look into not performing the temporary unmapping if we can
perform the write atomically, which would likely also make adding hugetlb
support a lot easier. But, limited (e.g., only PMD/PUD) hugetlb support
could be added on top of this with some tweaking.

Note that we now won't have to allocate another anonymous folio when
unregistering (which will be beneficial for hugetlb as well), we can simply
modify the already-mapped one from the registration (if any). When
registering a uprobe, we'll first trigger a ptrace-like write fault to
break COW, to then modify the already-mapped page.

Briefly sanity tested with perf probes and with the bpf uprobes
selftest.

v2 -> v3:
* Fix missing folio_put()

v1 -> v2:
* "kernel/events/uprobes: uprobe_write_opcode() rewrite"
 -> hold GUP reference longer so we can see if the page is still
    mapped when performing the folio_walk
 -> Move anon-folio check
 -> Reshuffle / cleanup some related things

RFC -> v1:
* Use folio_walk and simplify the logic

Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Andrii Nakryiko <andrii.nakryiko at gmail.com>
Cc: Matthew Wilcox <willy at infradead.org>
Cc: Russell King <linux at armlinux.org.uk>
Cc: Masami Hiramatsu <mhiramat at kernel.org>
Cc: Oleg Nesterov <oleg at redhat.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: Arnaldo Carvalho de Melo <acme at kernel.org>
Cc: Namhyung Kim <namhyung at kernel.org>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Alexander Shishkin <alexander.shishkin at linux.intel.com>
Cc: Jiri Olsa <jolsa at kernel.org>
Cc: Ian Rogers <irogers at google.com>
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: "Liang, Kan" <kan.liang at linux.intel.com>
Cc: Tong Tiangen <tongtiangen at huawei.com>

[1] https://lkml.kernel.org/r/ZiK50qob9yl5e0Xz at bender.morinfr.org

David Hildenbrand (3):
  kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
  kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and
    uprobe_write_opcode()
  kernel/events/uprobes: uprobe_write_opcode() rewrite

 arch/arm/probes/uprobes/core.c |   4 +-
 include/linux/uprobes.h        |   6 +-
 kernel/events/uprobes.c        | 357 +++++++++++++++++----------------
 3 files changed, 187 insertions(+), 180 deletions(-)


base-commit: a150906197a12c7b0f3f5efd844443bf98453efa
-- 
2.48.1



From david at redhat.com  Fri Mar 21 04:37:11 2025
From: david at redhat.com (David Hildenbrand)
Date: Fri, 21 Mar 2025 12:37:11 +0100
Subject: [PATCH v3 1/3] kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
In-Reply-To: <20250321113713.204682-1-david@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
Message-ID: <20250321113713.204682-2-david@redhat.com>

... and remove the "MM" argument from install_breakpoint(), because it
can easily be derived from the VMA.

Acked-by: Oleg Nesterov <oleg at redhat.com>
Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 5d6f3d9d29f44..259038d099819 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1134,10 +1134,10 @@ static bool filter_chain(struct uprobe *uprobe, struct mm_struct *mm)
 	return ret;
 }
 
-static int
-install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
-			struct vm_area_struct *vma, unsigned long vaddr)
+static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	bool first_uprobe;
 	int ret;
 
@@ -1162,9 +1162,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
-static int
-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
+static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
+	struct mm_struct *mm = vma->vm_mm;
+
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
 	return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
@@ -1296,10 +1298,10 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 		if (is_register) {
 			/* consult only the "caller", new consumer. */
 			if (consumer_filter(new, mm))
-				err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+				err = install_breakpoint(uprobe, vma, info->vaddr);
 		} else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
 			if (!filter_chain(uprobe, mm))
-				err |= remove_breakpoint(uprobe, mm, info->vaddr);
+				err |= remove_breakpoint(uprobe, vma, info->vaddr);
 		}
 
  unlock:
@@ -1472,7 +1474,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
 			continue;
 
 		vaddr = offset_to_vaddr(vma, uprobe->offset);
-		err |= remove_breakpoint(uprobe, mm, vaddr);
+		err |= remove_breakpoint(uprobe, vma, vaddr);
 	}
 	mmap_read_unlock(mm);
 
@@ -1610,7 +1612,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 		if (!fatal_signal_pending(current) &&
 		    filter_chain(uprobe, vma->vm_mm)) {
 			unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
-			install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
+			install_breakpoint(uprobe, vma, vaddr);
 		}
 		put_uprobe(uprobe);
 	}
-- 
2.48.1



From david at redhat.com  Fri Mar 21 04:37:12 2025
From: david at redhat.com (David Hildenbrand)
Date: Fri, 21 Mar 2025 12:37:12 +0100
Subject: [PATCH v3 2/3] kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and uprobe_write_opcode()
In-Reply-To: <20250321113713.204682-1-david@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
Message-ID: <20250321113713.204682-3-david@redhat.com>

We already have the VMA, no need to look it up using
get_user_page_vma_remote(). We can now switch to
get_user_pages_remote().

Acked-by: Oleg Nesterov <oleg at redhat.com>
Signed-off-by: David Hildenbrand <david at redhat.com>
---
 arch/arm/probes/uprobes/core.c |  4 ++--
 include/linux/uprobes.h        |  6 +++---
 kernel/events/uprobes.c        | 33 +++++++++++++++++----------------
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c
index f5f790c6e5f89..885e0c5e8c20d 100644
--- a/arch/arm/probes/uprobes/core.c
+++ b/arch/arm/probes/uprobes/core.c
@@ -26,10 +26,10 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
 		(UPROBE_SWBP_ARM_INSN & 0x0fffffff);
 }
 
-int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+int set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
 	     unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 		   __opcode_to_mem_arm(auprobe->bpinsn));
 }
 
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index b1df7d792fa16..288a42cc40baa 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -185,13 +185,13 @@ struct uprobes_state {
 };
 
 extern void __init uprobes_init(void);
-extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
-extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+extern int set_swbp(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
+extern int set_orig_insn(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
 extern bool is_swbp_insn(uprobe_opcode_t *insn);
 extern bool is_trap_insn(uprobe_opcode_t *insn);
 extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
 extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
-extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
+extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t);
 extern struct uprobe *uprobe_register(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister_nosync(struct uprobe *uprobe, struct uprobe_consumer *uc);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 259038d099819..ac17c16f65d63 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -474,19 +474,19 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  *
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
-int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-			unsigned long vaddr, uprobe_opcode_t opcode)
+int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr, uprobe_opcode_t opcode)
 {
+	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
 	struct page *old_page, *new_page;
-	struct vm_area_struct *vma;
 	int ret, is_register, ref_ctr_updated = 0;
 	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
@@ -498,9 +498,9 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 	if (is_register)
 		gup_flags |= FOLL_SPLIT_PMD;
 	/* Read the page with vaddr into memory */
-	old_page = get_user_page_vma_remote(mm, vaddr, gup_flags, &vma);
-	if (IS_ERR(old_page))
-		return PTR_ERR(old_page);
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
+	if (ret != 1)
+		return ret;
 
 	ret = verify_opcode(old_page, vaddr, &opcode);
 	if (ret <= 0)
@@ -590,30 +590,31 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, store the breakpoint instruction at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+		unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+	return uprobe_write_opcode(auprobe, vma, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
  * set_orig_insn - Restore the original instruction.
- * @mm: the probed process address space.
+ * @vma: the probed virtual memory area.
  * @auprobe: arch specific probepoint information.
  * @vaddr: the virtual address to insert the opcode.
  *
  * For mm @mm, restore the original opcode (opcode) at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-int __weak
-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+int __weak set_orig_insn(struct arch_uprobe *auprobe,
+		struct vm_area_struct *vma, unsigned long vaddr)
 {
-	return uprobe_write_opcode(auprobe, mm, vaddr,
+	return uprobe_write_opcode(auprobe, vma, vaddr,
 			*(uprobe_opcode_t *)&auprobe->insn);
 }
 
@@ -1153,7 +1154,7 @@ static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	if (first_uprobe)
 		set_bit(MMF_HAS_UPROBES, &mm->flags);
 
-	ret = set_swbp(&uprobe->arch, mm, vaddr);
+	ret = set_swbp(&uprobe->arch, vma, vaddr);
 	if (!ret)
 		clear_bit(MMF_RECALC_UPROBES, &mm->flags);
 	else if (first_uprobe)
@@ -1168,7 +1169,7 @@ static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 
 	set_bit(MMF_RECALC_UPROBES, &mm->flags);
-	return set_orig_insn(&uprobe->arch, mm, vaddr);
+	return set_orig_insn(&uprobe->arch, vma, vaddr);
 }
 
 struct map_info {
-- 
2.48.1



From lee at kernel.org  Fri Mar 21 04:32:14 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 21 Mar 2025 11:32:14 +0000
Subject: (subset) [PATCH v3 01/21] dt-bindings: mfd: syscon: add
 microchip,sama7d65-ddr3phy
In-Reply-To: <c5d602b7d4c29333013ef3f75544c2eb7e4b8dab.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <c5d602b7d4c29333013ef3f75544c2eb7e4b8dab.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <174255673486.2091509.9339030316768600844.b4-ty@kernel.org>

On Thu, 27 Feb 2025 08:51:48 -0700, Ryan.Wanner at microchip.com wrote:
> Add SAMA7D65 DDR3phy compatible to DT bindings documentation
> 
> 

Applied, thanks!

[01/21] dt-bindings: mfd: syscon: add microchip,sama7d65-ddr3phy
        commit: 2b4d2bdc07a152b3869f7888f64f37d4b09ae58e

--
Lee Jones [???]



From lee at kernel.org  Fri Mar 21 04:32:50 2025
From: lee at kernel.org (Lee Jones)
Date: Fri, 21 Mar 2025 11:32:50 +0000
Subject: (subset) [PATCH v3 02/21] dt-bindings: mfd: syscon: add
 microchip,sama7d65-sfrbu
In-Reply-To: <92543fcff4ab35e770b01d4c15d45cc5d55833f4.1740671156.git.Ryan.Wanner@microchip.com>
References: <cover.1740671156.git.Ryan.Wanner@microchip.com>
 <92543fcff4ab35e770b01d4c15d45cc5d55833f4.1740671156.git.Ryan.Wanner@microchip.com>
Message-ID: <174255677015.2092266.3581610195037077485.b4-ty@kernel.org>

On Thu, 27 Feb 2025 08:51:49 -0700, Ryan.Wanner at microchip.com wrote:
> Add SAMA7D65 SFRBU compatible string to DT bindings documentation
> 
> 

Applied, thanks!

[02/21] dt-bindings: mfd: syscon: add microchip,sama7d65-sfrbu
        commit: 7e3ff6785039796728a515ea6e07378823e71be1

--
Lee Jones [???]



From david at redhat.com  Fri Mar 21 04:37:13 2025
From: david at redhat.com (David Hildenbrand)
Date: Fri, 21 Mar 2025 12:37:13 +0100
Subject: [PATCH v3 3/3] kernel/events/uprobes: uprobe_write_opcode() rewrite
In-Reply-To: <20250321113713.204682-1-david@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
Message-ID: <20250321113713.204682-4-david@redhat.com>

uprobe_write_opcode() does some pretty low-level things that really, it
shouldn't be doing: for example, manually breaking COW by allocating
anonymous folios and replacing mapped pages.

Further, it does seem to do some shaky things: for example, writing to
possible COW-shared anonymous pages or zapping anonymous pages that might
be pinned. We're also not taking care of uffd, uffd-wp, softdirty ...
although rather corner cases here. Let's just get it right like ordinary
ptrace writes would.

Let's rewrite the code, leaving COW-breaking to core-MM, triggered by
FOLL_FORCE|FOLL_WRITE (note that the code was already using FOLL_FORCE).

We'll use GUP to lookup/faultin the page and break COW if required. Then,
we'll walk the page tables using a folio_walk to perform our page
modification atomically by temporarily unmap the PTE + flushing the TLB.

Likely, we could avoid the temporary unmap in case we can just
atomically write the instruction, but that will be a separate project.

Unfortunately, we still have to implement the zapping logic manually,
because we only want to zap in specific circumstances (e.g., page
content identical).

Note that we can now handle large folios (compound pages) and the shared
zeropage just fine, so drop these checks.

Acked-by: Oleg Nesterov <oleg at redhat.com>
Signed-off-by: David Hildenbrand <david at redhat.com>
---
 kernel/events/uprobes.c | 312 ++++++++++++++++++++--------------------
 1 file changed, 158 insertions(+), 154 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ac17c16f65d63..f098e8a4f24ee 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -29,6 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/srcu.h>
 #include <linux/oom.h>          /* check_stable_address_space */
+#include <linux/pagewalk.h>
 
 #include <linux/uprobes.h>
 
@@ -151,91 +152,6 @@ static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
 	return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
 }
 
-/**
- * __replace_page - replace page in vma by new page.
- * based on replace_page in mm/ksm.c
- *
- * @vma:      vma that holds the pte pointing to page
- * @addr:     address the old @page is mapped at
- * @old_page: the page we are replacing by new_page
- * @new_page: the modified page we replace page by
- *
- * If @new_page is NULL, only unmap @old_page.
- *
- * Returns 0 on success, negative error code otherwise.
- */
-static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
-				struct page *old_page, struct page *new_page)
-{
-	struct folio *old_folio = page_folio(old_page);
-	struct folio *new_folio;
-	struct mm_struct *mm = vma->vm_mm;
-	DEFINE_FOLIO_VMA_WALK(pvmw, old_folio, vma, addr, 0);
-	int err;
-	struct mmu_notifier_range range;
-	pte_t pte;
-
-	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, addr,
-				addr + PAGE_SIZE);
-
-	if (new_page) {
-		new_folio = page_folio(new_page);
-		err = mem_cgroup_charge(new_folio, vma->vm_mm, GFP_KERNEL);
-		if (err)
-			return err;
-	}
-
-	/* For folio_free_swap() below */
-	folio_lock(old_folio);
-
-	mmu_notifier_invalidate_range_start(&range);
-	err = -EAGAIN;
-	if (!page_vma_mapped_walk(&pvmw))
-		goto unlock;
-	VM_BUG_ON_PAGE(addr != pvmw.address, old_page);
-	pte = ptep_get(pvmw.pte);
-
-	/*
-	 * Handle PFN swap PTES, such as device-exclusive ones, that actually
-	 * map pages: simply trigger GUP again to fix it up.
-	 */
-	if (unlikely(!pte_present(pte))) {
-		page_vma_mapped_walk_done(&pvmw);
-		goto unlock;
-	}
-
-	if (new_page) {
-		folio_get(new_folio);
-		folio_add_new_anon_rmap(new_folio, vma, addr, RMAP_EXCLUSIVE);
-		folio_add_lru_vma(new_folio, vma);
-	} else
-		/* no new page, just dec_mm_counter for old_page */
-		dec_mm_counter(mm, MM_ANONPAGES);
-
-	if (!folio_test_anon(old_folio)) {
-		dec_mm_counter(mm, mm_counter_file(old_folio));
-		inc_mm_counter(mm, MM_ANONPAGES);
-	}
-
-	flush_cache_page(vma, addr, pte_pfn(pte));
-	ptep_clear_flush(vma, addr, pvmw.pte);
-	if (new_page)
-		set_pte_at(mm, addr, pvmw.pte,
-			   mk_pte(new_page, vma->vm_page_prot));
-
-	folio_remove_rmap_pte(old_folio, old_page, vma);
-	if (!folio_mapped(old_folio))
-		folio_free_swap(old_folio);
-	page_vma_mapped_walk_done(&pvmw);
-	folio_put(old_folio);
-
-	err = 0;
- unlock:
-	mmu_notifier_invalidate_range_end(&range);
-	folio_unlock(old_folio);
-	return err;
-}
-
 /**
  * is_swbp_insn - check if instruction is breakpoint instruction.
  * @insn: instruction to be checked.
@@ -463,6 +379,95 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
 	return ret;
 }
 
+static bool orig_page_is_identical(struct vm_area_struct *vma,
+		unsigned long vaddr, struct page *page, bool *pmd_mappable)
+{
+	const pgoff_t index = vaddr_to_offset(vma, vaddr) >> PAGE_SHIFT;
+	struct folio *orig_folio = filemap_get_folio(vma->vm_file->f_mapping,
+						    index);
+	struct page *orig_page;
+	bool identical;
+
+	if (IS_ERR(orig_folio))
+		return false;
+	orig_page = folio_file_page(orig_folio, index);
+
+	*pmd_mappable = folio_test_pmd_mappable(orig_folio);
+	identical = folio_test_uptodate(orig_folio) &&
+		    pages_identical(page, orig_page);
+	folio_put(orig_folio);
+	return identical;
+}
+
+static int __uprobe_write_opcode(struct vm_area_struct *vma,
+		struct folio_walk *fw, struct folio *folio,
+		unsigned long opcode_vaddr, uprobe_opcode_t opcode)
+{
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
+	const bool is_register = !!is_swbp_insn(&opcode);
+	bool pmd_mappable;
+
+	/* For now, we'll only handle PTE-mapped folios. */
+	if (fw->level != FW_LEVEL_PTE)
+		return -EFAULT;
+
+	/*
+	 * See can_follow_write_pte(): we'd actually prefer a writable PTE here,
+	 * but the VMA might not be writable.
+	 */
+	if (!pte_write(fw->pte)) {
+		if (!PageAnonExclusive(fw->page))
+			return -EFAULT;
+		if (unlikely(userfaultfd_pte_wp(vma, fw->pte)))
+			return -EFAULT;
+		/* SOFTDIRTY is handled via pte_mkdirty() below. */
+	}
+
+	/*
+	 * We'll temporarily unmap the page and flush the TLB, such that we can
+	 * modify the page atomically.
+	 */
+	flush_cache_page(vma, vaddr, pte_pfn(fw->pte));
+	fw->pte = ptep_clear_flush(vma, vaddr, fw->ptep);
+	copy_to_page(fw->page, opcode_vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+
+	/*
+	 * When unregistering, we may only zap a PTE if uffd is disabled and
+	 * there are no unexpected folio references ...
+	 */
+	if (is_register || userfaultfd_missing(vma) ||
+	    (folio_ref_count(folio) != folio_mapcount(folio) + 1 +
+	     folio_test_swapcache(folio) * folio_nr_pages(folio)))
+		goto remap;
+
+	/*
+	 * ... and the mapped page is identical to the original page that
+	 * would get faulted in on next access.
+	 */
+	if (!orig_page_is_identical(vma, vaddr, fw->page, &pmd_mappable))
+		goto remap;
+
+	dec_mm_counter(vma->vm_mm, MM_ANONPAGES);
+	folio_remove_rmap_pte(folio, fw->page, vma);
+	if (!folio_mapped(folio) && folio_test_swapcache(folio) &&
+	     folio_trylock(folio)) {
+		folio_free_swap(folio);
+		folio_unlock(folio);
+	}
+	folio_put(folio);
+
+	return pmd_mappable;
+remap:
+	/*
+	 * Make sure that our copy_to_page() changes become visible before the
+	 * set_pte_at() write.
+	 */
+	smp_wmb();
+	/* We modified the page. Make sure to mark the PTE dirty. */
+	set_pte_at(vma->vm_mm, vaddr, fw->ptep, pte_mkdirty(fw->pte));
+	return 0;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
@@ -475,116 +480,115 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
  * uprobe_write_opcode - write the opcode at a given virtual address.
  * @auprobe: arch specific probepoint information.
  * @vma: the probed virtual memory area.
- * @vaddr: the virtual address to store the opcode.
- * @opcode: opcode to be written at @vaddr.
+ * @opcode_vaddr: the virtual address to store the opcode.
+ * @opcode: opcode to be written at @opcode_vaddr.
  *
  * Called with mm->mmap_lock held for read or write.
  * Return 0 (success) or a negative errno.
  */
 int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
-		unsigned long vaddr, uprobe_opcode_t opcode)
+		const unsigned long opcode_vaddr, uprobe_opcode_t opcode)
 {
+	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
 	struct mm_struct *mm = vma->vm_mm;
 	struct uprobe *uprobe;
-	struct page *old_page, *new_page;
 	int ret, is_register, ref_ctr_updated = 0;
-	bool orig_page_huge = false;
 	unsigned int gup_flags = FOLL_FORCE;
+	struct mmu_notifier_range range;
+	struct folio_walk fw;
+	struct folio *folio;
+	struct page *page;
 
 	is_register = is_swbp_insn(&opcode);
 	uprobe = container_of(auprobe, struct uprobe, arch);
 
-retry:
+	if (WARN_ON_ONCE(!is_cow_mapping(vma->vm_flags)))
+		return -EINVAL;
+
+	/*
+	 * When registering, we have to break COW to get an exclusive anonymous
+	 * page that we can safely modify. Use FOLL_WRITE to trigger a write
+	 * fault if required. When unregistering, we might be lucky and the
+	 * anon page is already gone. So defer write faults until really
+	 * required. Use FOLL_SPLIT_PMD, because __uprobe_write_opcode()
+	 * cannot deal with PMDs yet.
+	 */
 	if (is_register)
-		gup_flags |= FOLL_SPLIT_PMD;
-	/* Read the page with vaddr into memory */
-	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
-	if (ret != 1)
-		return ret;
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
 
-	ret = verify_opcode(old_page, vaddr, &opcode);
+retry:
+	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &page, NULL);
 	if (ret <= 0)
-		goto put_old;
-
-	if (is_zero_page(old_page)) {
-		ret = -EINVAL;
-		goto put_old;
-	}
+		goto out;
+	folio = page_folio(page);
 
-	if (WARN(!is_register && PageCompound(old_page),
-		 "uprobe unregister should never work on compound page\n")) {
-		ret = -EINVAL;
-		goto put_old;
+	ret = verify_opcode(page, opcode_vaddr, &opcode);
+	if (ret <= 0) {
+		folio_put(folio);
+		goto out;
 	}
 
 	/* We are going to replace instruction, update ref_ctr. */
 	if (!ref_ctr_updated && uprobe->ref_ctr_offset) {
 		ret = update_ref_ctr(uprobe, mm, is_register ? 1 : -1);
-		if (ret)
-			goto put_old;
+		if (ret) {
+			folio_put(folio);
+			goto out;
+		}
 
 		ref_ctr_updated = 1;
 	}
 
 	ret = 0;
-	if (!is_register && !PageAnon(old_page))
-		goto put_old;
-
-	ret = anon_vma_prepare(vma);
-	if (ret)
-		goto put_old;
-
-	ret = -ENOMEM;
-	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
-	if (!new_page)
-		goto put_old;
-
-	__SetPageUptodate(new_page);
-	copy_highpage(new_page, old_page);
-	copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+	if (unlikely(!folio_test_anon(folio))) {
+		VM_WARN_ON_ONCE(is_register);
+		folio_put(folio);
+		goto out;
+	}
 
 	if (!is_register) {
-		struct page *orig_page;
-		pgoff_t index;
-
-		VM_BUG_ON_PAGE(!PageAnon(old_page), old_page);
-
-		index = vaddr_to_offset(vma, vaddr & PAGE_MASK) >> PAGE_SHIFT;
-		orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
-					  index);
-
-		if (orig_page) {
-			if (PageUptodate(orig_page) &&
-			    pages_identical(new_page, orig_page)) {
-				/* let go new_page */
-				put_page(new_page);
-				new_page = NULL;
-
-				if (PageCompound(orig_page))
-					orig_page_huge = true;
-			}
-			put_page(orig_page);
-		}
+		/*
+		 * In the common case, we'll be able to zap the page when
+		 * unregistering. So trigger MMU notifiers now, as we won't
+		 * be able to do it under PTL.
+		 */
+		mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
+					vaddr, vaddr + PAGE_SIZE);
+		mmu_notifier_invalidate_range_start(&range);
+	}
+
+	ret = -EAGAIN;
+	/* Walk the page tables again, to perform the actual update. */
+	if (folio_walk_start(&fw, vma, vaddr, 0)) {
+		if (fw.page == page)
+			ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr, opcode);
+		folio_walk_end(&fw, vma);
 	}
 
-	ret = __replace_page(vma, vaddr & PAGE_MASK, old_page, new_page);
-	if (new_page)
-		put_page(new_page);
-put_old:
-	put_page(old_page);
+	if (!is_register)
+		mmu_notifier_invalidate_range_end(&range);
 
-	if (unlikely(ret == -EAGAIN))
+	folio_put(folio);
+	switch (ret) {
+	case -EFAULT:
+		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
+		fallthrough;
+	case -EAGAIN:
 		goto retry;
+	default:
+		break;
+	}
 
+out:
 	/* Revert back reference counter if instruction update failed. */
-	if (ret && is_register && ref_ctr_updated)
+	if (ret < 0 && is_register && ref_ctr_updated)
 		update_ref_ctr(uprobe, mm, -1);
 
 	/* try collapse pmd for compound page */
-	if (!ret && orig_page_huge)
+	if (ret > 0)
 		collapse_pte_mapped_thp(mm, vaddr, false);
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 /**
-- 
2.48.1



From sudeep.holla at arm.com  Fri Mar 21 04:57:00 2025
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 21 Mar 2025 11:57:00 +0000
Subject: [PATCH] firmware: arm_ffa: Skip Rx buffer ownership release if not acquired
Message-ID: <20250321115700.3525197-1-sudeep.holla@arm.com>

Completion of the FFA_PARTITION_INFO_GET ABI transfers the ownership of
the caller?s Rx buffer from the producer(typically partition mnager) to
the consumer(this driver/OS). FFA_RX_RELEASE transfers the ownership
from the consumer back to the producer.

However, when we set the flag to just return the count of partitions
deployed in the system corresponding to the specified UUID while
invoking FFA_PARTITION_INFO_GET, the Rx buffer ownership shouldn't be
transferred to this driver. We must be able to skip transferring back
the ownership to the partition manager when we request just to get the
count of the partitions as the buffers are not acquired in this case.

Firmware may return FFA_RET_DENIED or other error for the ffa_rx_release()
in such cases.

Fixes: bb1be7498500 ("firmware: arm_ffa: Add v1.1 get_partition_info support")
Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/firmware/arm_ffa/driver.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2c2ec3c35f15..dce448687e28 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -280,7 +280,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
 			memcpy(buffer + idx, drv_info->rx_buffer + idx * sz,
 			       buf_sz);
 
-	ffa_rx_release();
+	if (!(flags & PARTITION_INFO_GET_RETURN_COUNT_ONLY))
+		ffa_rx_release();
 
 	mutex_unlock(&drv_info->rx_lock);
 
-- 
2.34.1



From suzuki.poulose at arm.com  Fri Mar 21 05:10:47 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 21 Mar 2025 12:10:47 +0000
Subject: [PATCH v3 2/7] coresight: Only check bottom two claim bits
In-Reply-To: <20250320-james-coresight-claim-tags-v3-2-d3145c153820@linaro.org>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
 <20250320-james-coresight-claim-tags-v3-2-d3145c153820@linaro.org>
Message-ID: <40e30ec8-a7ea-46b9-b687-aa7efa8cf0e1@arm.com>

On 20/03/2025 14:34, James Clark wrote:
> The use of the whole register and == could break the claim mechanism if
> any of the other bits are used in the future. The referenced doc "PSCI -
> ARM DEN 0022D" also says to only read and clear the bottom two bits.
> 
> Use FIELD_GET() to extract only the relevant part.
> 
> Reviewed-by: Leo Yan <leo.yan at arm.com>
> Signed-off-by: James Clark <james.clark at linaro.org>
> ---
>   drivers/hwtracing/coresight/coresight-core.c | 3 ++-
>   drivers/hwtracing/coresight/coresight-priv.h | 1 +
>   2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 8471aefeac76..26d149a4c579 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -131,7 +131,8 @@ coresight_find_out_connection(struct coresight_device *csdev,
>   
>   static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
>   {
> -	return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
> +	return FIELD_GET(CORESIGHT_CLAIM_MASK,
> +			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
>   }
>   
>   static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 82644aff8d2b..38bb4e8b50ef 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -35,6 +35,7 @@ extern const struct device_type coresight_dev_type[];
>    * Coresight device CLAIM protocol.
>    * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
>    */
> +#define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
>   #define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)

I am checking with the Arm CoreSight architects on this. This is
problematic, if another agent is assigned, say BIT(2) and we wouldn't
forward compatible.

Suzuki


>   
>   #define TIMEOUT_US		100
> 



From m.szyprowski at samsung.com  Fri Mar 21 05:15:09 2025
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Fri, 21 Mar 2025 13:15:09 +0100
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <d6cd5e64-e2c0-4c6e-9c89-ce8b3e0a4a5b@arm.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
	<e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
	<CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
	<9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
	<417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
	<bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
	<016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
	<b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>
	<cdc333e4-25bb-4171-9f6e-01f1de947db3@samsung.com>
	<d6cd5e64-e2c0-4c6e-9c89-ce8b3e0a4a5b@arm.com>
Message-ID: <ace3a01f-4700-4455-ada3-0f88fc8ea4cd@samsung.com>

On 17.03.2025 19:22, Robin Murphy wrote:
> On 17/03/2025 7:37 am, Marek Szyprowski wrote:
>> On 13.03.2025 15:12, Robin Murphy wrote:
>>> On 2025-03-13 1:06 pm, Robin Murphy wrote:
>>>> On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
>>>>> On 13.03.2025 12:01, Robin Murphy wrote:
>>>>>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>>>>>> [...]
>>>>>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>>>>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my
>>>>>>> tests I
>>>>>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>>>>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>>>>>> relevant kernel log:
>>>>>>
>>>>>> ...and the bug-flushing-out begins!
>>>>>>
>>>>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>>>>> 00000000000003e8
>>>>>>> Mem abort info:
>>>>>>> ??? ? ESR = 0x0000000096000004
>>>>>>> ??? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>>>>> ??? ? SET = 0, FnV = 0
>>>>>>> ??? ? EA = 0, S1PTW = 0
>>>>>>> ??? ? FSC = 0x04: level 0 translation fault
>>>>>>> Data abort info:
>>>>>>> ??? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>>>>> ??? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>>>>> ??? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>>>>> [00000000000003e8] user address but active_mm is swapper
>>>>>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>>>>>> Modules linked in:
>>>>>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>>>>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>>>>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>>>> pc : devm_kmalloc+0x2c/0x114
>>>>>>> lr : rk_iommu_of_xlate+0x30/0x90
>>>>>>> ...
>>>>>>> Call trace:
>>>>>>> ??? ?devm_kmalloc+0x2c/0x114 (P)
>>>>>>> ??? ?rk_iommu_of_xlate+0x30/0x90
>>>>>>
>>>>>> Yeah, looks like this is doing something a bit questionable which
>>>>>> can't
>>>>>> work properly. TBH the whole dma_dev thing could probably be
>>>>>> cleaned up
>>>>>> now that we have proper instances, but for now does this work?
>>>>>
>>>>> Yes, this patch fixes the problem I've observed.
>>>>>
>>>>> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>>
>>>>> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver
>>>>> and
>>>>> I doubt it can be cleaned up.
>>>>
>>>> On the contrary I suspect they both can - it all dates back to when
>>>> we had the single global platform bus iommu_ops and the SoC drivers
>>>> were forced to bodge their own notion of multiple instances, but with
>>>> the modern core code, ops are always called via a valid IOMMU
>>>> instance or domain, so in principle it should always be possible to
>>>> get at an appropriate IOMMU device now. IIRC it was mostly about
>>>> allocating and DMA-mapping the pagetables in domain_alloc, where the
>>>> private notion of instances didn't have enough information, but
>>>> domain_alloc_paging solves that.
>>>
>>> Bah, in fact I think I am going to have to do that now, since although
>>> it doesn't crash, rk_domain_alloc_paging() will also be failing for
>>> the same reason. Time to find a PSU for the RK3399 board, I guess...
>>>
>>> (Or maybe just move the dma_dev assignment earlier to match Exynos?)
>>
>> Well I just found that Exynos IOMMU is also broken on some on my test
>> boards. It looks that the runtime pm links are somehow not correctly
>> established. I will try to analyze this later in the afternoon.
>
> Hmm, I tried to get an Odroid-XU3 up and running, but it seems unable 
> to boot my original 6.14-rc3-based branch - even with the IOMMU driver 
> disabled, it's consistently dying somewhere near (or just after) init 
> with what looks like some catastrophic memory corruption issue - very 
> occasionally it's managed to print the first line of various different 
> panics.
>
> Before that point though, with the IOMMU driver enabled it does appear 
> to show signs of working OK:
>
> [??? 0.649703] exynos-sysmmu 14650000.sysmmu: hardware version: 3.3
> [??? 0.654220] platform 14450000.mixer: Adding to iommu group 1
> ...
> [??? 2.680920] exynos-mixer 14450000.mixer: 
> exynos_iommu_attach_device: Attached IOMMU with pgtable 0x42924000
> ...
> [??? 5.196674] exynos-mixer 14450000.mixer: 
> exynos_iommu_identity_attach: Restored IOMMU to IDENTITY from pgtable 
> 0x42924000
> [??? 5.207091] exynos-mixer 14450000.mixer: 
> exynos_iommu_attach_device: Attached IOMMU with pgtable 0x42884000
>
>
> The multi-instance stuff in probe/release does look a bit suspect, 
> however - seems like the second instance probe would overwrite the 
> first instance's links, and then there would be a double-del() if the 
> device were ever actually released again? I may have made that much 
> more likely to happen, but I suspect it was already possible with 
> async driver probe...

That is really strange. My Odroid XU3 boots fine from commit 
bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path"), 
although the IOMMU seems not to be working correctly. I've tested this 
with 14450000.mixer device (one need to attach HDMI cable to get it 
activated) and it looks that the video data are not being read from 
memory at all (the lack of VSYNC is reported, no IOMMU fault). However, 
from time to time, everything initializes and works properly.

It looks that this is somehow related to the different IOMMU/DMA-mapping 
glue code, as the other boards (ARM64 based) with exactly the same 
Exynos IOMMU driver always work fine. I've tried to figure out what 
actually happens, but so far I didn't get anything for sure. Disabling 
the call to dev->bus->dma_configure(dev) from iommu_init_device() seems 
to be fixing this, but this is almost equal to the revert of the 
$subject patch. I don't get why calling it in iommu_init_device() causes 
problems. It also doesn't look that this is anyhow related to the 
multi-instance stuff, as the same happens if I only leave a single 
exynos-sysmmu instance and its client (only 14450000.mixer device in the 
system).

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From arnd at arndb.de  Fri Mar 21 05:28:43 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 13:28:43 +0100
Subject: [PATCH v4 4/4] arm: defconfig: drop RT_GROUP_SCHED=y from
 bcm2835/tegra/omap2plus
In-Reply-To: <t2dustbykx2qd24wazjeiw5hch5nwr6z2ewmaf4srg6r2grwrf@rdw47chzkef2>
References: <20250115-fix-riscv-rt_group_sched-v4-0-607606fe73a5@coelacanthus.name>
 <20250115-fix-riscv-rt_group_sched-v4-4-607606fe73a5@coelacanthus.name>
 <t2dustbykx2qd24wazjeiw5hch5nwr6z2ewmaf4srg6r2grwrf@rdw47chzkef2>
Message-ID: <5fd4f314-e570-4b37-b7c2-af5b4bc85a39@app.fastmail.com>

On Thu, Mar 6, 2025, at 20:19, Thierry Reding wrote:
> On Wed, Jan 15, 2025 at 04:41:23AM +0800, Celeste Liu wrote:
>> ---
>>  arch/arm/configs/bcm2835_defconfig   | 1 -
>>  arch/arm/configs/omap2plus_defconfig | 1 -
>>  arch/arm/configs/tegra_defconfig     | 1 -
>>  3 files changed, 3 deletions(-)
>
> Hi Arnd,
>
> is this something that you could pick up? I think so far only the RISC-V
> patch was picked up, but nobody seems to feel responsible for the ARM
> patch here.

I've merged it now after going through stuff in my inbox. It's
generally ok for patches like this one to be forwarded to
soc at lists.linux.dev where they end up in patchwork for me to apply,
in case you don't want it to get lost.

     Arnd


From jasonhell19 at gmail.com  Fri Mar 21 05:37:31 2025
From: jasonhell19 at gmail.com (Jason Hsu)
Date: Fri, 21 Mar 2025 20:37:31 +0800
Subject: [PATCH v6 2/2] ARM: dts: aspeed: ventura: add Meta Ventura BMC
In-Reply-To: <20250321123731.1373596-1-jason-hsu@quantatw.com>
References: <20250321123731.1373596-1-jason-hsu@quantatw.com>
Message-ID: <20250321123731.1373596-3-jason-hsu@quantatw.com>

Add Linux device tree related to Meta(Facebook) Ventura specific devices connected to BMC(AST2600) SoC.
Add subject prefix for the patch.

Signed-off-by: Jason Hsu <jason-hsu at quantatw.com>
---
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-facebook-ventura.dts    | 1399 +++++++++++++++++
 2 files changed, 1400 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..e07666d902fb 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -28,6 +28,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-bmc-facebook-minerva.dtb \
 	aspeed-bmc-facebook-minipack.dtb \
 	aspeed-bmc-facebook-tiogapass.dtb \
+	aspeed-bmc-facebook-ventura.dtb \
 	aspeed-bmc-facebook-wedge40.dtb \
 	aspeed-bmc-facebook-wedge100.dtb \
 	aspeed-bmc-facebook-wedge400.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts
new file mode 100644
index 000000000000..9882a7d154cc
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts
@@ -0,0 +1,1399 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2023 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+	model = "Facebook ventura RMC";
+	compatible = "facebook,ventura-rmc", "aspeed,ast2600";
+
+	aliases {
+		serial4 = &uart5;
+		i2c16 = &i2c3mux0ch3;
+		i2c17 = &i2c3mux0ch4;
+		i2c18 = &i2c3mux0ch5;
+		i2c19 = &i2c3mux0ch6;
+		i2c20 = &i2c3mux0ch0;
+		i2c21 = &i2c3mux0ch1;
+		i2c22 = &i2c3mux0ch2;
+		i2c23 = &i2c3mux0ch7;
+		i2c24 = &i2c0mux0ch0;
+		i2c25 = &i2c0mux0ch1;
+		i2c26 = &i2c0mux0ch2;
+		i2c27 = &i2c0mux0ch3;
+		i2c28 = &i2c0mux0ch4;
+		i2c29 = &i2c0mux0ch5;
+		i2c30 = &i2c0mux0ch6;
+		i2c31 = &i2c0mux0ch7;
+		i2c32 = &i2c1mux0ch0;
+		i2c33 = &i2c1mux0ch1;
+		i2c34 = &i2c1mux0ch2;
+		i2c35 = &i2c1mux0ch3;
+		i2c36 = &i2c1mux0ch4;
+		i2c37 = &i2c1mux0ch5;
+		i2c38 = &i2c1mux0ch6;
+		i2c39 = &i2c1mux0ch7;
+		i2c40 = &i2c2mux0ch0;
+		i2c41 = &i2c2mux0ch1;
+		i2c42 = &i2c2mux0ch2;
+		i2c43 = &i2c2mux0ch3;
+		i2c44 = &i2c2mux0ch4;
+		i2c45 = &i2c2mux0ch5;
+		i2c46 = &i2c2mux0ch6;
+		i2c47 = &i2c2mux0ch7;
+	};
+
+	chosen {
+		stdout-path = "serial4:57600n8";
+	};
+
+	iio-hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
+			      <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
+			      <&adc1 2>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0 {
+			label = "bmc_heartbeat_amber";
+			gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-1 {
+			label = "fp_id_amber";
+			default-state = "off";
+			gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
+		};
+
+		led-2 {
+			label = "bmc_ready_noled";
+			default-state = "on";
+			gpios = <&gpio0 ASPEED_GPIO(B, 3) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>;
+		};
+
+		led-3 {
+			label = "power_blue";
+			default-state = "off";
+			gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
+		};
+
+		led-4 {
+			label = "compute1_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g5_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-5 {
+			label = "compute1_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 15 GPIO_ACTIVE_LOW>;
+		};
+
+		led-6 {
+			label = "compute1_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 14 GPIO_ACTIVE_LOW>;
+		};
+
+		led-7 {
+			label = "compute2_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		led-8 {
+			label = "compute2_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 10 GPIO_ACTIVE_LOW>;
+		};
+
+		led-9 {
+			label = "compute2_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 9 GPIO_ACTIVE_LOW>;
+		};
+
+		led-10 {
+			label = "compute3_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led-11 {
+			label = "compute3_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		led-12 {
+			label = "compute3_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-13 {
+			label = "compute4_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-14 {
+			label = "compute4_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-15 {
+			label = "compute4_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 15 GPIO_ACTIVE_LOW>;
+		};
+
+		led-16 {
+			label = "compute5_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 14 GPIO_ACTIVE_LOW>;
+		};
+
+		led-17 {
+			label = "compute5_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 13 GPIO_ACTIVE_LOW>;
+		};
+
+		led-18 {
+			label = "compute5_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 12 GPIO_ACTIVE_LOW>;
+		};
+
+		led-19 {
+			label = "compute6_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		led-20 {
+			label = "compute6_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-21 {
+			label = "compute6_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-22 {
+			label = "compute7_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-23 {
+			label = "compute7_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led-24 {
+			label = "compute7_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led-25 {
+			label = "compute8_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 13 GPIO_ACTIVE_LOW>;
+		};
+
+		led-26 {
+			label = "compute8_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 12 GPIO_ACTIVE_LOW>;
+		};
+
+		led-27 {
+			label = "compute8_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		led-28 {
+			label = "nvs1_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 10 GPIO_ACTIVE_LOW>;
+		};
+
+		led-29 {
+			label = "nvs1_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 9 GPIO_ACTIVE_LOW>;
+		};
+
+		led-30 {
+			label = "nvs1_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led-31 {
+			label = "nvs2_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led-32 {
+			label = "nvs2_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led-33 {
+			label = "nvs2_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-34 {
+			label = "nvs3_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-35 {
+			label = "nvs3_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 15 GPIO_ACTIVE_LOW>;
+		};
+
+		led-36 {
+			label = "nvs3_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g4_gpio 14 GPIO_ACTIVE_LOW>;
+		};
+
+		led-37 {
+			label = "nvs4_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 9 GPIO_ACTIVE_LOW>;
+		};
+
+		led-38 {
+			label = "nvs4_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led-39 {
+			label = "nvs4_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		led-40 {
+			label = "nvs5_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-41 {
+			label = "nvs5_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-42 {
+			label = "nvs5_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-43 {
+			label = "nvs6_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 15 GPIO_ACTIVE_LOW>;
+		};
+
+		led-44 {
+			label = "nvs6_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 14 GPIO_ACTIVE_LOW>;
+		};
+
+		led-45 {
+			label = "nvs6_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 13 GPIO_ACTIVE_LOW>;
+		};
+
+		led-46 {
+			label = "nvs7_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 12 GPIO_ACTIVE_LOW>;
+		};
+
+		led-47 {
+			label = "nvs7_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		led-48 {
+			label = "nvs7_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g3_gpio 10 GPIO_ACTIVE_LOW>;
+		};
+
+		led-49 {
+			label = "nvs8_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-50 {
+			label = "nvs8_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-51 {
+			label = "nvs8_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led-52 {
+			label = "nvs9_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led-53 {
+			label = "nvs9_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-54 {
+			label = "nvs9_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-55 {
+			label = "compute9_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		led-56 {
+			label = "compute9_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 10 GPIO_ACTIVE_LOW>;
+		};
+
+		led-57 {
+			label = "compute9_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 9 GPIO_ACTIVE_LOW>;
+		};
+
+		led-58 {
+			label = "compute10_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led-59 {
+			label = "compute10_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		led-60 {
+			label = "compute10_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-61 {
+			label = "compute11_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-62 {
+			label = "compute11_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-63 {
+			label = "compute11_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 15 GPIO_ACTIVE_LOW>;
+		};
+
+		led-64 {
+			label = "compute12_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 14 GPIO_ACTIVE_LOW>;
+		};
+
+		led-65 {
+			label = "compute12_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 13 GPIO_ACTIVE_LOW>;
+		};
+
+		led-66 {
+			label = "compute12_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g6_gpio 12 GPIO_ACTIVE_LOW>;
+		};
+
+		led-67 {
+			label = "compute13_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 7 GPIO_ACTIVE_LOW>;
+		};
+
+		led-68 {
+			label = "compute13_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-69 {
+			label = "compute13_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-70 {
+			label = "compute14_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-71 {
+			label = "compute14_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led-72 {
+			label = "compute14_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led-73 {
+			label = "compute15_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 13 GPIO_ACTIVE_LOW>;
+		};
+
+		led-74 {
+			label = "compute15_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 12 GPIO_ACTIVE_LOW>;
+		};
+
+		led-75 {
+			label = "compute15_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		led-76 {
+			label = "compute16_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 10 GPIO_ACTIVE_LOW>;
+		};
+
+		led-77 {
+			label = "compute16_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 9 GPIO_ACTIVE_LOW>;
+		};
+
+		led-78 {
+			label = "compute16_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g2_gpio 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led-79 {
+			label = "compute17_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-80 {
+			label = "compute17_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-81 {
+			label = "compute17_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led-82 {
+			label = "compute18_led_switch";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led-83 {
+			label = "compute18_led_blue";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-84 {
+			label = "compute18_led_amber";
+			default-state = "off";
+			gpios = <&tray_leds_g1_gpio 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+    p1v8_bmc_aux: regulator-p1v8-bmc-aux {
+		compatible = "regulator-fixed";
+		regulator-name = "p1v8_bmc_aux";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	p2v5_bmc_aux: regulator-p2v5-bmc-aux {
+		compatible = "regulator-fixed";
+		regulator-name = "p2v5_bmc_aux";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+    spi1_gpio: spi {
+		compatible = "spi-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
+		mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
+		miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>;
+		cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
+		num-chipselects = <1>;
+
+		tpm at 0 {
+			compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+			spi-max-frequency = <33000000>;
+			reg = <0>;
+		};
+	};
+};
+
+&adc0 {
+	vref-supply = <&p1v8_bmc_aux>;
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
+		&pinctrl_adc2_default &pinctrl_adc3_default
+		&pinctrl_adc4_default &pinctrl_adc5_default
+		&pinctrl_adc6_default &pinctrl_adc7_default>;
+
+};
+
+&adc1 {
+	vref-supply = <&p2v5_bmc_aux>;
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc10_default>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&fmc {
+	status = "okay";
+	flash at 0 {
+		status = "okay";
+		m25p,fast-read;
+		label = "bmc";
+		spi-max-frequency = <50000000>;
+#include "openbmc-flash-layout-128.dtsi"
+	};
+	flash at 1 {
+		status = "okay";
+		m25p,fast-read;
+		label = "alt-bmc";
+		spi-max-frequency = <50000000>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c0mux0ch0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c0mux0ch1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c0mux0ch2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c0mux0ch3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c0mux0ch4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c0mux0ch5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c0mux0ch6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c0mux0ch7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c1mux0ch0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c1mux0ch1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c1mux0ch2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c1mux0ch3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c1mux0ch4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c1mux0ch5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c1mux0ch6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c1mux0ch7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c2mux0ch0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c2mux0ch1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c2mux0ch2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c2mux0ch3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c2mux0ch4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c2mux0ch5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c2mux0ch6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c2mux0ch7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c3 {
+	status = "okay";
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c3mux0ch0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c3mux0ch1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c3mux0ch2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c3mux0ch3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			// Fan Board 0 FRU
+			eeprom at 56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+
+			fan_leds_g1_gpio: gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			adc at 1f {
+				compatible = "ti,adc128d818";
+				reg = <0x1f>;
+				ti,mode = /bits/ 8 <1>;
+			};
+
+			adc at 35 {
+				compatible = "maxim,max11617";
+				reg = <0x35>;
+			};
+		};
+
+		i2c3mux0ch4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			// Fan Board 1 FRU
+			eeprom at 56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+
+			gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			adc at 1f {
+				compatible = "ti,adc128d818";
+				reg = <0x1f>;
+				ti,mode = /bits/ 8 <1>;
+			};
+
+			adc at 35 {
+				compatible = "maxim,max11617";
+				reg = <0x35>;
+			};
+		};
+
+		i2c3mux0ch5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			hwmon: hwmon at 23 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x23>;
+				#pwm-cells = <2>;
+
+				//fan 0 IL
+				fan-0 {
+					pwms = <&hwmon 0 20000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+
+				//fan 0 OL
+				fan-1 {
+					pwms = <&hwmon 0 20000>;
+					tach-ch = /bits/ 8 <0x0B>;
+				};
+
+				//fan 1 IL
+				fan-2 {
+					pwms = <&hwmon 4 20000>;
+					tach-ch = /bits/ 8 <0x0A>;
+				};
+
+				//fan 1 OL
+				fan-3 {
+					pwms = <&hwmon 4 20000>;
+					tach-ch = /bits/ 8 <0x0D>;
+				};
+
+				//fan 2 IL
+				fan-4 {
+					pwms = <&hwmon 6 20000>;
+					tach-ch = /bits/ 8 <0x0F>;
+				};
+
+				//fan 2 OL
+				fan-5 {
+					pwms = <&hwmon 6 20000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+
+				//fan 3 IL
+				fan-6 {
+					pwms = <&hwmon 10 20000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+
+				//fan 3 OL
+				fan-7 {
+					pwms = <&hwmon 10 20000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
+		};
+
+		i2c3mux0ch6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			// REAR-IO Board FRU
+			eeprom at 56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c3mux0ch7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c4 {
+	status = "okay";
+};
+
+&i2c5 {
+	status = "okay";
+
+    // VR TEMP U399
+	temperature-sensor at 4c {
+		compatible = "ti,tmp75";
+		reg = <0x4c>;
+	};
+    // VR TEMP U397
+	temperature-sensor at 4d {
+		compatible = "ti,tmp75";
+		reg = <0x4d>;
+	};
+    // BRICK TEMP U398
+	temperature-sensor at 4e {
+		compatible = "ti,tmp75";
+		reg = <0x4e>;
+	};
+
+	temperature-sensor at 4f {
+		compatible = "ti,tmp75";
+		reg = <0x4f>;
+	};
+    // RMC FRU
+	eeprom at 54 {
+		compatible = "atmel,24c128";
+		reg = <0x54>;
+	};
+};
+
+&i2c6 {
+	status = "okay";
+
+	gpio at 20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio at 22 {
+		compatible = "nxp,pca9555";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	rtc at 51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&i2c7 {
+	status = "okay";
+};
+
+&i2c9 {
+	status = "okay";
+
+    // SCM TEMP SENSOR
+	temperature-sensor at 4b {
+		compatible = "ti,tmp75";
+		reg = <0x4b>;
+	};
+
+    // SCM FRU EEPROM
+	eeprom at 50 {
+		compatible = "atmel,24c128";
+		reg = <0x50>;
+	};
+
+    // BSM FRU EEPROM
+	eeprom at 56 {
+		compatible = "atmel,24c64";
+		reg = <0x56>;
+	};
+};
+
+&i2c10 {
+	status = "okay";
+
+	power-monitor at 14 {
+		compatible = "infineon,xdp710";
+		reg = <0x14>;
+	};
+
+	power-monitor at 44 {
+		compatible = "lltc,ltc4286";
+		reg = <0x44>;
+	};
+};
+
+&i2c14 {
+	status = "okay";
+};
+
+&i2c15 {
+	status = "okay";
+
+	tray_leds_g1_gpio: gpio at 20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tray_leds_g2_gpio: gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tray_leds_g3_gpio: gpio at 22 {
+		compatible = "nxp,pca9555";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tray_leds_g4_gpio: gpio at 24 {
+		compatible = "nxp,pca9555";
+		reg = <0x24>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tray_leds_g5_gpio: gpio at 25 {
+		compatible = "nxp,pca9555";
+		reg = <0x25>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tray_leds_g6_gpio: gpio at 26 {
+		compatible = "nxp,pca9555";
+		reg = <0x26>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+    // LED Board FRU
+	eeprom at 56 {
+		compatible = "atmel,24c128";
+		reg = <0x56>;
+	};
+};
+
+&mdio0 {
+	status = "okay";
+};
+
+&mac3 {
+	status = "okay";
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii4_default>;
+	fixed-link {
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&gpio0 {
+	gpio-line-names =
+	/*A0-A7*/	"","","","","","","","",
+	/*B0-B7*/	"BATTERY_DETECT","","","BMC_READY","","","","",
+	/*C0-C7*/	"","","","","","","","",
+	/*D0-D7*/	"","","","","","","","",
+	/*E0-E7*/	"","","","","","","","",
+	/*F0-F7*/	"","","","","","","","",
+	/*G0-G7*/	"","","","","","","","",
+	/*H0-H7*/	"","","","","","","","",
+	/*I0-I7*/	"","","","","","","","",
+	/*J0-J7*/	"","","","","","","","",
+	/*K0-K7*/	"","","","","","","","",
+	/*L0-L7*/	"","","","","","","","",
+	/*M0-M7*/	"","","","","","","","",
+	/*N0-N7*/	"","","","","","","","",
+	/*O0-O7*/	"","","","","","","","USBDBG_IPMI_EN_L",
+	/*P0-P7*/	"","","","","","","","",
+	/*Q0-Q7*/	"","","","","","FM_MDIO_SW_SEL","","",
+	/*R0-R7*/	"","","","","","","","",
+	/*S0-S7*/	"","","","","","","","",
+	/*T0-T7*/	"","","","","","","","",
+	/*U0-U7*/	"","","","","","","","",
+	/*V0-V7*/	"","","","","","","","",
+	/*W0-W7*/	"","","","","","","","",
+	/*X0-X7*/	"","","","","","","","",
+	/*Y0-Y7*/	"","","","","","","","",
+	/*Z0-Z7*/	"","","","","","","","";
+};
+
+&sgpiom0 {
+	status = "okay";
+	ngpios = <128>;
+	bus-frequency = <2000000>;
+};
+
+&sgpiom0 {
+	gpio-line-names =
+    /*"input pin","output pin"*/
+	/*A0 - A7*/
+	"power-chassis-good","power-chassis-control",
+	"host0-ready","WATER_VALVE_CLOSED_N",
+	"","FM_MDIO_SW_SEL_PLD",
+	"","FM_88E6393X_BIN_UPDATE_EN_N",
+	"","",
+	"","",
+	"","",
+	"","",
+    /*B0 - B7*/
+	"IT_STOP_PUMP_SPARE_2","",
+	"IT_STOP_PUMP_2","",
+	"IT_STOP_PUMP_SPARE","",
+	"IT_STOP_PUMP","",
+	"RPU_2_READY_SPARE_PLD_R","",
+	"RPU_2_READY_PLD_R","",
+	"RPU_READY_SPARE_PLD_R","",
+	"RPU_READY_PLD_R","",
+    /*C0 - C7*/
+	"wAALC_RPU_READY","",
+	"LEAK0_DETECT","",
+	"LEAK1_DETECT","",
+	"LEAK2_DETECT","",
+	"PRSNT_COMPUTE_TRAY1_N","",
+	"PRSNT_COMPUTE_TRAY2_N","",
+	"PRSNT_COMPUTE_TRAY3_N","",
+	"PRSNT_COMPUTE_TRAY4_N","",
+	/*D0 - D7*/
+	"PRSNT_COMPUTE_TRAY5_N","",
+	"PRSNT_COMPUTE_TRAY6_N","",
+	"PRSNT_COMPUTE_TRAY7_N","",
+	"PRSNT_COMPUTE_TRAY8_N","",
+	"PRSNT_NVS_TRAY1_N","",
+	"PRSNT_NVS_TRAY2_N","",
+	"PRSNT_COMPUTE_TRAY11_N","",
+	"PRSNT_COMPUTE_TRAY12_N","",
+	/*E0 - E7*/
+	"PRSNT_COMPUTE_TRAY13_N","",
+	"PRSNT_COMPUTE_TRAY14_N","",
+	"PRSNT_COMPUTE_TRAY15_N","",
+	"PRSNT_COMPUTE_TRAY16_N","",
+	"PRSNT_COMPUTE_TRAY17_N","",
+	"PRSNT_COMPUTE_TRAY18_N","",
+	"PRSNT_NVS_TRAY3_N","",
+	"PRSNT_NVS_TRAY4_N","",
+	/*F0 - F7*/
+	"PRSNT_NVS_TRAY5_N","",
+	"PRSNT_NVS_TRAY6_N","",
+	"PRSNT_NVS_TRAY7_N","",
+	"PRSNT_NVS_TRAY8_N","",
+	"PRSNT_NVS_TRAY9_N","",
+	"PRSNT_COMPUTE_TRAY9_N","",
+	"PRSNT_COMPUTE_TRAY10_N","",
+	"SMALL_LEAK_COMPUTE_TRAY1_N","",
+	/*G0 - G7*/
+	"SMALL_LEAK_COMPUTE_TRAY2_N","",
+	"SMALL_LEAK_COMPUTE_TRAY3_N","",
+	"SMALL_LEAK_COMPUTE_TRAY4_N","",
+	"SMALL_LEAK_COMPUTE_TRAY5_N","",
+	"SMALL_LEAK_COMPUTE_TRAY6_N","",
+	"SMALL_LEAK_COMPUTE_TRAY7_N","",
+	"SMALL_LEAK_COMPUTE_TRAY8_N","",
+	"SMALL_LEAK_NVS_TRAY1_N","",
+	/*H0 - H7*/
+	"SMALL_LEAK_NVS_TRAY2_N","",
+	"SMALL_LEAK_COMPUTE_TRAY11_N","",
+	"SMALL_LEAK_COMPUTE_TRAY12_N","",
+	"SMALL_LEAK_COMPUTE_TRAY13_N","",
+	"SMALL_LEAK_COMPUTE_TRAY14_N","",
+	"SMALL_LEAK_COMPUTE_TRAY15_N","",
+	"SMALL_LEAK_COMPUTE_TRAY16_N","",
+	"SMALL_LEAK_COMPUTE_TRAY17_N","",
+	/*I0 - I7*/
+	"SMALL_LEAK_COMPUTE_TRAY18_N","",
+	"SMALL_LEAK_NVS_TRAY3_N","",
+	"SMALL_LEAK_NVS_TRAY4_N","",
+	"SMALL_LEAK_NVS_TRAY5_N","",
+	"SMALL_LEAK_NVS_TRAY6_N","",
+	"SMALL_LEAK_NVS_TRAY7_N","",
+	"SMALL_LEAK_NVS_TRAY8_N","",
+	"SMALL_LEAK_NVS_TRAY9_N","",
+	/*J0 - J7*/
+	"SMALL_LEAK_COMPUTE_TRAY9_N","",
+	"SMALL_LEAK_COMPUTE_TRAY10_N","",
+	"PWRGD_COMPUTE_TRAY1_N","",
+	"PWRGD_COMPUTE_TRAY2_N","",
+	"PWRGD_COMPUTE_TRAY3_N","",
+	"PWRGD_COMPUTE_TRAY4_N","",
+	"PWRGD_COMPUTE_TRAY5_N","",
+	"PWRGD_COMPUTE_TRAY6_N","",
+	/*K0 - K7*/
+	"PWRGD_COMPUTE_TRAY7_N","",
+	"PWRGD_COMPUTE_TRAY8_N","",
+	"PWRGD_NVS_TRAY1_PWROK_N","",
+	"PWRGD_NVS_TRAY2_PWROK_N","",
+	"PWRGD_COMPUTE_TRAY11_N","",
+	"PWRGD_COMPUTE_TRAY12_N","",
+	"PWRGD_COMPUTE_TRAY13_N","",
+	"PWRGD_COMPUTE_TRAY14_N","",
+	/*L0 - L7*/
+	"PWRGD_COMPUTE_TRAY15_N","",
+	"PWRGD_COMPUTE_TRAY16_N","",
+	"PWRGD_COMPUTE_TRAY17_N","",
+	"PWRGD_COMPUTE_TRAY18_N","",
+	"PWRGD_NVS_TRAY3_PWROK_N","",
+	"PWRGD_NVS_TRAY4_PWROK_N","",
+	"PWRGD_NVS_TRAY5_PWROK_N","",
+	"PWRGD_NVS_TRAY6_PWROK_N","",
+	/*M0 - M7*/
+	"PWRGD_NVS_TRAY7_PWROK_N","",
+	"PWRGD_NVS_TRAY8_PWROK_N","",
+	"PWRGD_NVS_TRAY9_PWROK_N","",
+	"PWRGD_COMPUTE_TRAY9_N","",
+	"PWRGD_COMPUTE_TRAY10_N","",
+	"LEAK_DETECT_COMPUTE_TRAY1_N","",
+	"LEAK_DETECT_COMPUTE_TRAY2_N","",
+	"LEAK_DETECT_COMPUTE_TRAY3_N","",
+	/*N0 - N7*/
+	"LEAK_DETECT_COMPUTE_TRAY4_N","",
+	"LEAK_DETECT_COMPUTE_TRAY5_N","",
+	"LEAK_DETECT_COMPUTE_TRAY6_N","",
+	"LEAK_DETECT_COMPUTE_TRAY7_N","",
+	"LEAK_DETECT_COMPUTE_TRAY8_N","",
+	"LEAK_DETECT_NVS_TRAY1_N","",
+	"LEAK_DETECT_NVS_TRAY2_N","",
+	"LEAK_DETECT_COMPUTE_TRAY11_N","",
+	/*O0 - O7*/
+	"LEAK_DETECT_COMPUTE_TRAY12_N","",
+	"LEAK_DETECT_COMPUTE_TRAY13_N","",
+	"LEAK_DETECT_COMPUTE_TRAY14_N","",
+	"LEAK_DETECT_COMPUTE_TRAY15_N","",
+	"LEAK_DETECT_COMPUTE_TRAY16_N","",
+	"LEAK_DETECT_COMPUTE_TRAY17_N","",
+	"LEAK_DETECT_COMPUTE_TRAY18_N","",
+	"LEAK_DETECT_NVS_TRAY3_N","",
+	/*P0 - P7*/
+	"LEAK_DETECT_NVS_TRAY4_N","",
+	"LEAK_DETECT_NVS_TRAY5_N","",
+	"LEAK_DETECT_NVS_TRAY6_N","",
+	"LEAK_DETECT_NVS_TRAY7_N","",
+	"LEAK_DETECT_NVS_TRAY8_N","",
+	"LEAK_DETECT_NVS_TRAY9_N","",
+	"LEAK_DETECT_COMPUTE_TRAY9_N","",
+	"LEAK_DETECT_COMPUTE_TRAY10_N","";
+};
+
+&wdt1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdtrst1_default>;
+	aspeed,reset-type = "soc";
+	aspeed,external-signal;
+	aspeed,ext-push-pull;
+	aspeed,ext-active-high;
+	aspeed,ext-pulse-duration = <256>;
+};
--
2.34.1



From jasonhell19 at gmail.com  Fri Mar 21 05:37:29 2025
From: jasonhell19 at gmail.com (Jason Hsu)
Date: Fri, 21 Mar 2025 20:37:29 +0800
Subject: [PATCH v5 0/2] Add Meta(Facebook) Ventura BMC(AST2600)
Message-ID: <20250321123731.1373596-1-jason-hsu@quantatw.com>

Add Linux device tree entry related to Meta(Facebook) Ventura specific
devices connected to BMC(AST2600) SoC.

---
v1:
    1. Create ventura dts file.
    2. Add commit msg.
    3. Use format-patch to generate patch.
    4. Add subject prefixes matching the subsystem.
---
v2:
    1. Modify email content.
---
v3:
    1. Add mail list.
---
v4:
    1. Apply git send-email --thread option.
    2. Sort nodes in the dts alphanumerically.
---
v5:
    1. Run scripts/checkpatch.pl and fix reported warnings.
    2. Remove unnecessary 88E6393X CONFIG FRU.
---
v6:
    1. Add a new stage for the DTS change.
    2. Run scripts/checkpatch.pl and fix reported error.
    3. Fix the issue in a separate patch.
---
Signed-off-by: Jason-Hsu <jasonhell19 at gmail.com>

Jason Hsu (2):
  dt-bindings: arm: aspeed: add Meta Ventura board
  ARM: dts: aspeed: ventura: add Meta Ventura BMC

 .../bindings/arm/aspeed/aspeed.yaml           |    1 +
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-facebook-ventura.dts    | 1399 +++++++++++++++++
 3 files changed, 1401 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts


base-commit: b3ee1e4609512dfff642a96b34d7e5dfcdc92d05
-- 
2.34.1



From jasonhell19 at gmail.com  Fri Mar 21 05:37:30 2025
From: jasonhell19 at gmail.com (Jason Hsu)
Date: Fri, 21 Mar 2025 20:37:30 +0800
Subject: [PATCH v6 1/2] dt-bindings: arm: aspeed: add Meta Ventura board
In-Reply-To: <20250321123731.1373596-1-jason-hsu@quantatw.com>
References: <20250321123731.1373596-1-jason-hsu@quantatw.com>
Message-ID: <20250321123731.1373596-2-jason-hsu@quantatw.com>

Document the new compatibles used on Meta Ventura.
Add subject prefix for the patch.

Signed-off-by: Jason Hsu <jason-hsu at quantatw.com>
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 01333ac111fb..a86b411df9a5 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -87,6 +87,7 @@ properties:
               - facebook,greatlakes-bmc
               - facebook,harma-bmc
               - facebook,minerva-cmc
+              - facebook,ventura-rmc
               - facebook,yosemite4-bmc
               - ibm,blueridge-bmc
               - ibm,everest-bmc
--
2.34.1



From suzuki.poulose at arm.com  Fri Mar 21 05:42:17 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri, 21 Mar 2025 12:42:17 +0000
Subject: [PATCH v3 1/7] coresight: Convert tag clear function to take a
 struct cs_access
In-Reply-To: <3bbf8aee-7b84-405a-8a3f-648c74196c2c@arm.com>
References: <20250320-james-coresight-claim-tags-v3-0-d3145c153820@linaro.org>
 <20250320-james-coresight-claim-tags-v3-1-d3145c153820@linaro.org>
 <3bbf8aee-7b84-405a-8a3f-648c74196c2c@arm.com>
Message-ID: <2d3fb704-172c-4632-9e95-02bbfb8c0f90@arm.com>

On 21/03/2025 11:02, Suzuki K Poulose wrote:
> On 20/03/2025 14:34, James Clark wrote:
>> The self hosted claim tag will be reset on device probe in a later
>> commit. We'll want to do this before coresight_register() is called so
>> won't have a coresight_device and have to use cs_access instead.
>>
>> Also make them public and create locked and unlocked versions for
>> later use.
>>
>> These look functions look like they set the whole tags register as one
>> value, but they only set and clear the self hosted bit using a SET/CLR
>> bits mechanism so also rename the functions to reflect this better.
>>
>> Reviewed-by: Leo Yan <leo.yan at arm.com>
>> Signed-off-by: James Clark <james.clark at linaro.org>
>> ---
>> ? drivers/hwtracing/coresight/coresight-core.c | 27 ++++++++++++++++++ 
>> +--------
>> ? include/linux/coresight.h??????????????????? |? 3 ++-
>> ? 2 files changed, 21 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index fb43ef6a3b1f..8471aefeac76 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -144,19 +144,30 @@ static inline bool 
>> coresight_is_claimed_any(struct coresight_device *csdev)
>> ????? return coresight_read_claim_tags(csdev) != 0;
>> ? }
>> -static inline void coresight_set_claim_tags(struct coresight_device 
>> *csdev)
>> +static inline void coresight_set_self_claim_tag(struct 
>> coresight_device *csdev)
> 
> nit: For consistency, this should be renamed to _unlocked ?
> 

minor nit on the subject;

s/cs_access/csdev_access/

Suzuki


> 

Rest looks fine to me
> 
> Suzuki
> 
> 
>> ? {
>> ????? csdev_access_relaxed_write32(&csdev->access, 
>> CORESIGHT_CLAIM_SELF_HOSTED,
>> ?????????????????????? CORESIGHT_CLAIMSET);
>> ????? isb();
>> ? }
>> -static inline void coresight_clear_claim_tags(struct coresight_device 
>> *csdev)
>> +void coresight_clear_self_claim_tag(struct csdev_access *csa)
>> ? {
>> -??? csdev_access_relaxed_write32(&csdev->access, 
>> CORESIGHT_CLAIM_SELF_HOSTED,
>> +??? if (csa->io_mem)
>> +??????? CS_UNLOCK(csa->base);
>> +??? coresight_clear_self_claim_tag_unlocked(csa);
>> +??? if (csa->io_mem)
>> +??????? CS_LOCK(csa->base);
>> +}
>> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
>> +
>> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
>> +{
>> +??? csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
>> ?????????????????????? CORESIGHT_CLAIMCLR);
>> ????? isb();
>> ? }
>> +EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
>> ? /*
>> ?? * coresight_claim_device_unlocked : Claim the device for self- 
>> hosted usage
>> @@ -176,11 +187,11 @@ int coresight_claim_device_unlocked(struct 
>> coresight_device *csdev)
>> ????? if (coresight_is_claimed_any(csdev))
>> ????????? return -EBUSY;
>> -??? coresight_set_claim_tags(csdev);
>> +??? coresight_set_self_claim_tag(csdev);
>> ????? if (coresight_is_claimed_self_hosted(csdev))
>> ????????? return 0;
>> -??? /* There was a race setting the tags, clean up and fail */
>> -??? coresight_clear_claim_tags(csdev);
>> +??? /* There was a race setting the tag, clean up and fail */
>> +??? coresight_clear_self_claim_tag_unlocked(&csdev->access);
>> ????? return -EBUSY;
>> ? }
>> ? EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
>> @@ -201,7 +212,7 @@ int coresight_claim_device(struct coresight_device 
>> *csdev)
>> ? EXPORT_SYMBOL_GPL(coresight_claim_device);
>> ? /*
>> - * coresight_disclaim_device_unlocked : Clear the claim tags for the 
>> device.
>> + * coresight_disclaim_device_unlocked : Clear the claim tag for the 
>> device.
>> ?? * Called with CS_UNLOCKed for the component.
>> ?? */
>> ? void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
>> @@ -211,7 +222,7 @@ void coresight_disclaim_device_unlocked(struct 
>> coresight_device *csdev)
>> ????????? return;
>> ????? if (coresight_is_claimed_self_hosted(csdev))
>> -??????? coresight_clear_claim_tags(csdev);
>> +??????? coresight_clear_self_claim_tag_unlocked(&csdev->access);
>> ????? else
>> ????????? /*
>> ?????????? * The external agent may have not honoured our claim
>> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
>> index d79a242b271d..00134a80d358 100644
>> --- a/include/linux/coresight.h
>> +++ b/include/linux/coresight.h
>> @@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct 
>> csdev_access *csa, u32 offset,
>> ? extern int coresight_claim_device(struct coresight_device *csdev);
>> ? extern int coresight_claim_device_unlocked(struct coresight_device 
>> *csdev);
>> -
>> +void coresight_clear_self_claim_tag(struct csdev_access *csa);
>> +void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
>> ? extern void coresight_disclaim_device(struct coresight_device *csdev);
>> ? extern void coresight_disclaim_device_unlocked(struct 
>> coresight_device *csdev);
>> ? extern char *coresight_alloc_device_name(struct coresight_dev_list 
>> *devs,
>>
> 



From andre.przywara at arm.com  Fri Mar 21 05:57:32 2025
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 21 Mar 2025 12:57:32 +0000
Subject: Fast model boot failure with Linux next-20250312
In-Reply-To: <CA+G9fYuw_jXCz07Dsk46QXQr3+y5-NfkC30ZNh+XmyeWgibQhA@mail.gmail.com>
References: <CA+G9fYvPu+MQKhYyPZSSDpAn-zhRGmeHQ8hJksT_cdDdxfbB-g@mail.gmail.com>
	<Z9ra3I2axii2HRVb@J2N7QTR9R3>
	<CA+G9fYuw_jXCz07Dsk46QXQr3+y5-NfkC30ZNh+XmyeWgibQhA@mail.gmail.com>
Message-ID: <20250321125732.6def5eca@donnerap.manchester.arm.com>

On Thu, 20 Mar 2025 16:03:32 +0530
Naresh Kamboju <naresh.kamboju at linaro.org> wrote:

Hi,

> On Wed, 19 Mar 2025 at 20:25, Mark Rutland <mark.rutland at arm.com> wrote:
> >
> > On Wed, Mar 19, 2025 at 08:07:47PM +0530, Naresh Kamboju wrote:  
> > > Regressions on the arm64 Fast Model (FVP-AEMvA) caused boot failures starting
> > > with Linux next-20250312 and persisting through next-20250319.
> > >
> > > First seen on the next-20250312
> > >  Good: next-20250311
> > >  Bad:  next-20250312 .. next-20250319
> > >
> > > Regressions found on FVP:
> > >  - boot
> > >
> > > Regression Analysis:
> > >  - New regression? Yes
> > >  - Reproducible? Yes
> > >
> > > Boot regression: Fast model boot failure with Linux next-20250312
> > > Reported-by: Linux Kernel Functional Testing <lkft at linaro.org>
> > >
> > > Anders bisected this to this commit id,
> > >
> > > # first bad commit:
> > >   [858c7bfcb35e1100b58bb63c9f562d86e09418d9]
> > >   arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9
> > >
> > > NOTE:
> > >   LKFT is currently running FVP Fast Models version 11.24.
> > >   Planned upgrade to the Fast Models version 11.28 in this sprint.  
> >
> > What firmware (and version therof) are you running within the model?  
> 
> Fast Models [11.24.11 (Nov 29 2023)]
> Booting Trusted Firmware
> BL1: v2.9(release):v2.9.0
> BL2: v2.9(release):v2.9.0
> BL31: v2.9(release):v2.9.0
> UEFI firmware (version  built at 22:31:25 on May 26 2023)
> UEFI v2.70 (EDK II, 0x00010000)
> 
> We need to update the firmware version at our end.

Oh yes, please, v2.9.0 is quite old by now, especially for a moving target
like the FVP, and when enabling new architecture features.
FWIW, after Anshuman pointed me the problem, I made a patch for TF-A to
enable PMUv3p9:
https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/35884
You would need that for this Linux commit here to work.
FEAT_FGT2 should be enabled already by default for the FVP.

Please feel free to leave a comment at the TF-A gerrit, stating that you
need the patch, that should accelerate the upstream process.

Cheers,
Andre

> > For example, if the EL3 firmware lacks support for FEAT_FGT2 or
> > FEAT_PMUv3p9, the kernel will trap to EL3 early during boot and die.
> >
> > It would be really helpful if you could capture that in the report in
> > future.
> >
> > Mark.
> >  
> > >
> > > ## Boot log
> > >   <No crash log on the console>
> > >
> > > ## Source
> > > * Kernel version: 6.14.0-rc7
> > > * Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
> > > * Git sha: ff7f9b199e3f4cc7d61df5a9a26a7cbb5c1492e6
> > > * Git describe: next-20250319
> > > * Project details:
> > > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319
> > > * DUT: arm64 Fast Model (FVP-AEMvA)
> > > * Toolchains: gcc-13 and clang-20
> > >
> > > ## Build
> > > * Build log: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/log
> > > * Build history:
> > > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675685/suite/boot/test/gcc-13-lkftconfig/history/
> > > * Build details:
> > > https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20250319/testrun/27675691/suite/boot/test/gcc-13-lkftconfig/
> > > * Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/
> > > * Kernel config:
> > > https://storage.tuxsuite.com/public/linaro/lkft/builds/2uX2EtC2pQdmVZ7ccoyhoi01Yy0/config
> > >
> > > --
> > > Linaro LKFT
> > > https://lkft.linaro.org
> > >  
> 
> - Naresh
> 



From ldearquer at gmail.com  Fri Mar 21 05:57:53 2025
From: ldearquer at gmail.com (Luis de Arquer)
Date: Fri, 21 Mar 2025 13:57:53 +0100
Subject: [PATCH] spi-rockchip: Fix register out of bounds access
Message-ID: <365ccddfba110549202b3520f4401a6a936e82a8.camel@gmail.com>

From: Luis de Arquer <luis.dearquer at inertim.com>

Do not write native chip select stuff for GPIO chip selects.
GPIOs can be numbered much higher than native CS.
Also, it makes no sense.

Signed-off-by: Luis de Arquer <luis.dearquer at inertim.com>
---
 drivers/spi/spi-rockchip.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1bc012fce..1a6381de6 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -547,7 +547,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs,
 	cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
 	if (spi->mode & SPI_LSB_FIRST)
 		cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
-	if (spi->mode & SPI_CS_HIGH)
+	if ((spi->mode & SPI_CS_HIGH) && !(spi_get_csgpiod(spi, 0)))
 		cr0 |= BIT(spi_get_chipselect(spi, 0)) << CR0_SOI_OFFSET;
 
 	if (xfer->rx_buf && xfer->tx_buf)
-- 
2.43.0




From olsajiri at gmail.com  Fri Mar 21 06:05:01 2025
From: olsajiri at gmail.com (Jiri Olsa)
Date: Fri, 21 Mar 2025 14:05:01 +0100
Subject: [PATCH v3 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250321113713.204682-4-david@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
 <20250321113713.204682-4-david@redhat.com>
Message-ID: <Z91j_UwNhi2DQB3N@krava>

On Fri, Mar 21, 2025 at 12:37:13PM +0100, David Hildenbrand wrote:

SNIP

> +static int __uprobe_write_opcode(struct vm_area_struct *vma,
> +		struct folio_walk *fw, struct folio *folio,
> +		unsigned long opcode_vaddr, uprobe_opcode_t opcode)
> +{
> +	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
> +	const bool is_register = !!is_swbp_insn(&opcode);
> +	bool pmd_mappable;
> +
> +	/* For now, we'll only handle PTE-mapped folios. */
> +	if (fw->level != FW_LEVEL_PTE)
> +		return -EFAULT;
> +
> +	/*
> +	 * See can_follow_write_pte(): we'd actually prefer a writable PTE here,
> +	 * but the VMA might not be writable.
> +	 */
> +	if (!pte_write(fw->pte)) {
> +		if (!PageAnonExclusive(fw->page))
> +			return -EFAULT;
> +		if (unlikely(userfaultfd_pte_wp(vma, fw->pte)))
> +			return -EFAULT;
> +		/* SOFTDIRTY is handled via pte_mkdirty() below. */
> +	}
> +
> +	/*
> +	 * We'll temporarily unmap the page and flush the TLB, such that we can
> +	 * modify the page atomically.
> +	 */
> +	flush_cache_page(vma, vaddr, pte_pfn(fw->pte));
> +	fw->pte = ptep_clear_flush(vma, vaddr, fw->ptep);
> +	copy_to_page(fw->page, opcode_vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
> +
> +	/*
> +	 * When unregistering, we may only zap a PTE if uffd is disabled and
> +	 * there are no unexpected folio references ...
> +	 */
> +	if (is_register || userfaultfd_missing(vma) ||
> +	    (folio_ref_count(folio) != folio_mapcount(folio) + 1 +
> +	     folio_test_swapcache(folio) * folio_nr_pages(folio)))
> +		goto remap;
> +
> +	/*
> +	 * ... and the mapped page is identical to the original page that
> +	 * would get faulted in on next access.
> +	 */
> +	if (!orig_page_is_identical(vma, vaddr, fw->page, &pmd_mappable))
> +		goto remap;
> +
> +	dec_mm_counter(vma->vm_mm, MM_ANONPAGES);
> +	folio_remove_rmap_pte(folio, fw->page, vma);
> +	if (!folio_mapped(folio) && folio_test_swapcache(folio) &&
> +	     folio_trylock(folio)) {
> +		folio_free_swap(folio);
> +		folio_unlock(folio);
> +	}
> +	folio_put(folio);

hi,
it's probably ok and I'm missing something, but why do we call folio_put
in here, I'd think it's done by folio_put call in uprobe_write_opcode

thanks,
jirka


> +
> +	return pmd_mappable;
> +remap:
> +	/*
> +	 * Make sure that our copy_to_page() changes become visible before the
> +	 * set_pte_at() write.
> +	 */
> +	smp_wmb();
> +	/* We modified the page. Make sure to mark the PTE dirty. */
> +	set_pte_at(vma->vm_mm, vaddr, fw->ptep, pte_mkdirty(fw->pte));
> +	return 0;
> +}
> +
>  /*
>   * NOTE:
>   * Expect the breakpoint instruction to be the smallest size instruction for
> @@ -475,116 +480,115 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
>   * uprobe_write_opcode - write the opcode at a given virtual address.
>   * @auprobe: arch specific probepoint information.
>   * @vma: the probed virtual memory area.
> - * @vaddr: the virtual address to store the opcode.
> - * @opcode: opcode to be written at @vaddr.
> + * @opcode_vaddr: the virtual address to store the opcode.
> + * @opcode: opcode to be written at @opcode_vaddr.
>   *
>   * Called with mm->mmap_lock held for read or write.
>   * Return 0 (success) or a negative errno.
>   */
>  int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
> -		unsigned long vaddr, uprobe_opcode_t opcode)
> +		const unsigned long opcode_vaddr, uprobe_opcode_t opcode)
>  {
> +	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
>  	struct mm_struct *mm = vma->vm_mm;
>  	struct uprobe *uprobe;
> -	struct page *old_page, *new_page;
>  	int ret, is_register, ref_ctr_updated = 0;
> -	bool orig_page_huge = false;
>  	unsigned int gup_flags = FOLL_FORCE;
> +	struct mmu_notifier_range range;
> +	struct folio_walk fw;
> +	struct folio *folio;
> +	struct page *page;
>  
>  	is_register = is_swbp_insn(&opcode);
>  	uprobe = container_of(auprobe, struct uprobe, arch);
>  
> -retry:
> +	if (WARN_ON_ONCE(!is_cow_mapping(vma->vm_flags)))
> +		return -EINVAL;
> +
> +	/*
> +	 * When registering, we have to break COW to get an exclusive anonymous
> +	 * page that we can safely modify. Use FOLL_WRITE to trigger a write
> +	 * fault if required. When unregistering, we might be lucky and the
> +	 * anon page is already gone. So defer write faults until really
> +	 * required. Use FOLL_SPLIT_PMD, because __uprobe_write_opcode()
> +	 * cannot deal with PMDs yet.
> +	 */
>  	if (is_register)
> -		gup_flags |= FOLL_SPLIT_PMD;
> -	/* Read the page with vaddr into memory */
> -	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
> -	if (ret != 1)
> -		return ret;
> +		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
>  
> -	ret = verify_opcode(old_page, vaddr, &opcode);
> +retry:
> +	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &page, NULL);
>  	if (ret <= 0)
> -		goto put_old;
> -
> -	if (is_zero_page(old_page)) {
> -		ret = -EINVAL;
> -		goto put_old;
> -	}
> +		goto out;
> +	folio = page_folio(page);
>  
> -	if (WARN(!is_register && PageCompound(old_page),
> -		 "uprobe unregister should never work on compound page\n")) {
> -		ret = -EINVAL;
> -		goto put_old;
> +	ret = verify_opcode(page, opcode_vaddr, &opcode);
> +	if (ret <= 0) {
> +		folio_put(folio);
> +		goto out;
>  	}
>  
>  	/* We are going to replace instruction, update ref_ctr. */
>  	if (!ref_ctr_updated && uprobe->ref_ctr_offset) {
>  		ret = update_ref_ctr(uprobe, mm, is_register ? 1 : -1);
> -		if (ret)
> -			goto put_old;
> +		if (ret) {
> +			folio_put(folio);
> +			goto out;
> +		}
>  
>  		ref_ctr_updated = 1;
>  	}
>  
>  	ret = 0;
> -	if (!is_register && !PageAnon(old_page))
> -		goto put_old;
> -
> -	ret = anon_vma_prepare(vma);
> -	if (ret)
> -		goto put_old;
> -
> -	ret = -ENOMEM;
> -	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
> -	if (!new_page)
> -		goto put_old;
> -
> -	__SetPageUptodate(new_page);
> -	copy_highpage(new_page, old_page);
> -	copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
> +	if (unlikely(!folio_test_anon(folio))) {
> +		VM_WARN_ON_ONCE(is_register);
> +		folio_put(folio);
> +		goto out;
> +	}
>  
>  	if (!is_register) {
> -		struct page *orig_page;
> -		pgoff_t index;
> -
> -		VM_BUG_ON_PAGE(!PageAnon(old_page), old_page);
> -
> -		index = vaddr_to_offset(vma, vaddr & PAGE_MASK) >> PAGE_SHIFT;
> -		orig_page = find_get_page(vma->vm_file->f_inode->i_mapping,
> -					  index);
> -
> -		if (orig_page) {
> -			if (PageUptodate(orig_page) &&
> -			    pages_identical(new_page, orig_page)) {
> -				/* let go new_page */
> -				put_page(new_page);
> -				new_page = NULL;
> -
> -				if (PageCompound(orig_page))
> -					orig_page_huge = true;
> -			}
> -			put_page(orig_page);
> -		}
> +		/*
> +		 * In the common case, we'll be able to zap the page when
> +		 * unregistering. So trigger MMU notifiers now, as we won't
> +		 * be able to do it under PTL.
> +		 */
> +		mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
> +					vaddr, vaddr + PAGE_SIZE);
> +		mmu_notifier_invalidate_range_start(&range);
> +	}
> +
> +	ret = -EAGAIN;
> +	/* Walk the page tables again, to perform the actual update. */
> +	if (folio_walk_start(&fw, vma, vaddr, 0)) {
> +		if (fw.page == page)
> +			ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr, opcode);
> +		folio_walk_end(&fw, vma);
>  	}
>  
> -	ret = __replace_page(vma, vaddr & PAGE_MASK, old_page, new_page);
> -	if (new_page)
> -		put_page(new_page);
> -put_old:
> -	put_page(old_page);
> +	if (!is_register)
> +		mmu_notifier_invalidate_range_end(&range);
>  
> -	if (unlikely(ret == -EAGAIN))
> +	folio_put(folio);
> +	switch (ret) {
> +	case -EFAULT:
> +		gup_flags |= FOLL_WRITE | FOLL_SPLIT_PMD;
> +		fallthrough;
> +	case -EAGAIN:
>  		goto retry;
> +	default:
> +		break;
> +	}
>  
> +out:
>  	/* Revert back reference counter if instruction update failed. */
> -	if (ret && is_register && ref_ctr_updated)
> +	if (ret < 0 && is_register && ref_ctr_updated)
>  		update_ref_ctr(uprobe, mm, -1);
>  
>  	/* try collapse pmd for compound page */
> -	if (!ret && orig_page_huge)
> +	if (ret > 0)
>  		collapse_pte_mapped_thp(mm, vaddr, false);
>  
> -	return ret;
> +	return ret < 0 ? ret : 0;
>  }
>  
>  /**
> -- 
> 2.48.1
> 


From alexghiti at rivosinc.com  Fri Mar 21 06:06:26 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:26 +0100
Subject: [PATCH v5 0/9] Merge arm64/riscv hugetlbfs contpte support
Message-ID: <20250321130635.227011-1-alexghiti@rivosinc.com>

This patchset intends to merge the contiguous ptes hugetlbfs implementation
of arm64 and riscv.

Both arm64 and riscv support the use of contiguous ptes to map pages that
are larger than the default page table size, respectively called contpte
and svnapot.

The riscv implementation differs from the arm64's in that the LSBs of the
pfn of a svnapot pte are used to store the size of the mapping, allowing
for future sizes to be added (for now only 64KB is supported). That's an
issue for the core mm code which expects to find the *real* pfn a pte points
to. Patch 1 fixes that by always returning svnapot ptes with the real pfn
and restores the size of the mapping when it is written to a page table.

The following patches are just merges of the 2 different implementations
that currently exist in arm64 and riscv which are very similar. It paves
the way to the reuse of the recent contpte THP work by Ryan [1] to avoid
reimplementing the same in riscv.

This patchset was tested by running the libhugetlbfs testsuite with 64KB
and 2MB pages on both architectures (on a 4KB base page size arm64 kernel).

[1] https://lore.kernel.org/linux-arm-kernel/20240215103205.2607016-1-ryan.roberts at arm.com/

v4: https://lore.kernel.org/linux-riscv/20250127093530.19548-1-alexghiti at rivosinc.com/
v3: https://lore.kernel.org/all/20240802151430.99114-1-alexghiti at rivosinc.com/
v2: https://lore.kernel.org/linux-riscv/20240508113419.18620-1-alexghiti at rivosinc.com/
v1: https://lore.kernel.org/linux-riscv/20240301091455.246686-1-alexghiti at rivosinc.com/

Changes in v5:
  - Fix "int i" unused variable in patch 2 (as reported by PW)
  - Fix !svnapot build
  - Fix arch_make_huge_pte() which returned a real napot pte
  - Make __ptep_get(), ptep_get_and_clear() and __set_ptes() napot aware to
    avoid leaking real napot pfns to core mm
  - Fix arch_contpte_get_num_contig() that used to always try to get the
    mapping size from the ptep, which does not work if the ptep comes the core mm
  - Rebase on top of 6.14-rc7 + fix for
    huge_ptep_get_and_clear()/huge_pte_clear()
    https://lore.kernel.org/linux-riscv/20250317072551.572169-1-alexghiti at rivosinc.com/

Changes in v4:
  - Rebase on top of 6.13

Changes in v3:
  - Split set_ptes and ptep_get into internal and external API (Ryan)
  - Rename ARCH_HAS_CONTPTE into ARCH_WANT_GENERAL_HUGETLB_CONTPTE so that
    we split hugetlb functions from contpte functions (actually riscv contpte
    functions to support THP will come into another series) (Ryan)
  - Rebase on top of 6.11-rc1

Changes in v2:
  - Rebase on top of 6.9-rc3

Alexandre Ghiti (9):
  riscv: Safely remove huge_pte_offset() when manipulating NAPOT ptes
  riscv: Restore the pfn in a NAPOT pte when manipulated by core mm code
  mm: Use common huge_ptep_get() function for riscv/arm64
  mm: Use common set_huge_pte_at() function for riscv/arm64
  mm: Use common huge_pte_clear() function for riscv/arm64
  mm: Use common huge_ptep_get_and_clear() function for riscv/arm64
  mm: Use common huge_ptep_set_access_flags() function for riscv/arm64
  mm: Use common huge_ptep_set_wrprotect() function for riscv/arm64
  mm: Use common huge_ptep_clear_flush() function for riscv/arm64

 arch/arm64/Kconfig                  |   1 +
 arch/arm64/include/asm/hugetlb.h    |  22 +--
 arch/arm64/include/asm/pgtable.h    |  68 ++++++-
 arch/arm64/mm/hugetlbpage.c         | 294 +---------------------------
 arch/riscv/Kconfig                  |   1 +
 arch/riscv/include/asm/hugetlb.h    |  36 +---
 arch/riscv/include/asm/pgtable-64.h |  11 ++
 arch/riscv/include/asm/pgtable.h    | 222 ++++++++++++++++++---
 arch/riscv/mm/hugetlbpage.c         | 243 +----------------------
 arch/riscv/mm/pgtable.c             |   6 +-
 include/linux/hugetlb_contpte.h     |  39 ++++
 mm/Kconfig                          |   3 +
 mm/Makefile                         |   1 +
 mm/hugetlb_contpte.c                | 258 ++++++++++++++++++++++++
 14 files changed, 583 insertions(+), 622 deletions(-)
 create mode 100644 include/linux/hugetlb_contpte.h
 create mode 100644 mm/hugetlb_contpte.c

-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:27 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:27 +0100
Subject: [PATCH v5 1/9] riscv: Safely remove huge_pte_offset() when manipulating NAPOT ptes
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-2-alexghiti@rivosinc.com>

The pte_t pointer is expected to point to the first entry of the NAPOT
mapping so no need to use huge_pte_offset(), similarly to what is done
in arm64.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/riscv/mm/hugetlbpage.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 375dd96bb4a0..3192ad804279 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -287,7 +287,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 
 	order = napot_cont_order(pte);
 	pte_num = napot_pte_num(order);
-	ptep = huge_pte_offset(mm, addr, napot_cont_size(order));
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
 
 	if (pte_dirty(orig_pte))
@@ -334,7 +333,6 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 
 	order = napot_cont_order(pte);
 	pte_num = napot_pte_num(order);
-	ptep = huge_pte_offset(mm, addr, napot_cont_size(order));
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
 
 	orig_pte = pte_wrprotect(orig_pte);
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:28 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:28 +0100
Subject: [PATCH v5 2/9] riscv: Restore the pfn in a NAPOT pte when manipulated by core mm code
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-3-alexghiti@rivosinc.com>

The core mm code expects to be able to extract the pfn from a pte. NAPOT
mappings work differently since its ptes actually point to the first pfn
of the mapping, the other bits being used to encode the size of the
mapping.

So modify ptep_get() so that it returns a pte value that contains the
*real* pfn (which is then different from what the HW expects) and right
before storing the ptes to the page table, reset the pfn LSBs to the
size of the mapping.

And make sure that all NAPOT mappings are set using set_ptes().

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/riscv/include/asm/pgtable-64.h |  11 ++
 arch/riscv/include/asm/pgtable.h    | 155 ++++++++++++++++++++++++----
 arch/riscv/mm/hugetlbpage.c         |  15 ++-
 3 files changed, 152 insertions(+), 29 deletions(-)

diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
index 0897dd99ab8d..cddbe426f618 100644
--- a/arch/riscv/include/asm/pgtable-64.h
+++ b/arch/riscv/include/asm/pgtable-64.h
@@ -104,6 +104,17 @@ enum napot_cont_order {
 #define napot_cont_mask(order)	(~(napot_cont_size(order) - 1UL))
 #define napot_pte_num(order)	BIT(order)
 
+static inline bool is_napot_order(unsigned int order)
+{
+	unsigned int napot_order;
+
+	for_each_napot_order(napot_order)
+		if (order == napot_order)
+			return true;
+
+	return false;
+}
+
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
 #define HUGE_MAX_HSTATE		(2 + (NAPOT_ORDER_MAX - NAPOT_CONT_ORDER_BASE))
 #else
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 050fdc49b5ad..2e62d7e607db 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -296,6 +296,17 @@ static inline unsigned long pte_napot(pte_t pte)
 	return pte_val(pte) & _PAGE_NAPOT;
 }
 
+#define pte_valid_napot(pte)	(pte_present(pte) && pte_napot(pte))
+
+/*
+ * contpte is what we expose to the core mm code, this is not exactly a napot
+ * mapping since the size is not encoded in the pfn yet.
+ */
+static inline pte_t pte_mkcont(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_NAPOT);
+}
+
 static inline pte_t pte_mknapot(pte_t pte, unsigned int order)
 {
 	int pos = order - 1 + _PAGE_PFN_SHIFT;
@@ -305,6 +316,12 @@ static inline pte_t pte_mknapot(pte_t pte, unsigned int order)
 	return __pte((pte_val(pte) & napot_mask) | napot_bit | _PAGE_NAPOT);
 }
 
+/* pte at entry must *not* encode the mapping size in the pfn LSBs. */
+static inline pte_t pte_clear_napot(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_NAPOT);
+}
+
 #else
 
 static __always_inline bool has_svnapot(void) { return false; }
@@ -314,17 +331,24 @@ static inline unsigned long pte_napot(pte_t pte)
 	return 0;
 }
 
+static inline pte_t pte_clear_napot(pte_t pte)
+{
+	return pte;
+}
+
+static inline pte_t pte_mknapot(pte_t pte, unsigned int order)
+{
+	return pte;
+}
+
+#define pte_valid_napot(pte)	false
+
 #endif /* CONFIG_RISCV_ISA_SVNAPOT */
 
 /* Yields the page frame number (PFN) of a page table entry */
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	unsigned long res  = __page_val_to_pfn(pte_val(pte));
-
-	if (has_svnapot() && pte_napot(pte))
-		res = res & (res - 1UL);
-
-	return res;
+	return __page_val_to_pfn(pte_val(pte));
 }
 
 #define pte_page(x)     pfn_to_page(pte_pfn(x))
@@ -559,8 +583,13 @@ static inline void __set_pte_at(struct mm_struct *mm, pte_t *ptep, pte_t pteval)
 
 #define PFN_PTE_SHIFT		_PAGE_PFN_SHIFT
 
-static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
-		pte_t *ptep, pte_t pteval, unsigned int nr)
+static inline pte_t ___ptep_get(pte_t *ptep)
+{
+	return READ_ONCE(*ptep);
+}
+
+static inline void ___set_ptes(struct mm_struct *mm, unsigned long addr,
+			       pte_t *ptep, pte_t pteval, unsigned int nr)
 {
 	page_table_check_ptes_set(mm, ptep, pteval, nr);
 
@@ -569,10 +598,13 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
 		if (--nr == 0)
 			break;
 		ptep++;
+
+		if (unlikely(pte_valid_napot(pteval)))
+			continue;
+
 		pte_val(pteval) += 1 << _PAGE_PFN_SHIFT;
 	}
 }
-#define set_ptes set_ptes
 
 static inline void pte_clear(struct mm_struct *mm,
 	unsigned long addr, pte_t *ptep)
@@ -587,17 +619,6 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre
 extern int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long address,
 				     pte_t *ptep);
 
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pte_t *ptep)
-{
-	pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
-
-	page_table_check_pte_clear(mm, pte);
-
-	return pte;
-}
-
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 static inline void ptep_set_wrprotect(struct mm_struct *mm,
 				      unsigned long address, pte_t *ptep)
@@ -627,6 +648,100 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
 	return ptep_test_and_clear_young(vma, address, ptep);
 }
 
+#ifdef CONFIG_RISCV_ISA_SVNAPOT
+static inline pte_t pte_napot_clear_pfn(pte_t *ptep, pte_t pte)
+{
+	/*
+	 * The pte we load has the N bit set and the size of the mapping in
+	 * the pfn LSBs: keep the N bit and replace the mapping size with
+	 * the *real* pfn since the core mm code expects to find it there.
+	 * The mapping size will be reset just before being written to the
+	 * page table in set_ptes().
+	 */
+	if (unlikely(pte_valid_napot(pte))) {
+		unsigned int order = napot_cont_order(pte);
+		int pos = order - 1 + _PAGE_PFN_SHIFT;
+		unsigned long napot_mask = ~GENMASK(pos, _PAGE_PFN_SHIFT);
+		pte_t *orig_ptep = PTR_ALIGN_DOWN(ptep, sizeof(*ptep) * napot_pte_num(order));
+
+		pte = __pte((pte_val(pte) & napot_mask) + ((ptep - orig_ptep) << _PAGE_PFN_SHIFT));
+	}
+
+	return pte;
+}
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+				       unsigned long address, pte_t *ptep)
+{
+	pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+
+	pte = pte_napot_clear_pfn(ptep, pte);
+
+	page_table_check_pte_clear(mm, pte);
+
+	return pte;
+}
+
+static inline pte_t __ptep_get(pte_t *ptep)
+{
+	pte_t pte = ___ptep_get(ptep);
+
+	return pte_napot_clear_pfn(ptep, pte);
+}
+
+static inline void __set_ptes(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval, unsigned int nr)
+{
+	if (unlikely(pte_valid_napot(pteval))) {
+		unsigned int order = ilog2(nr);
+
+		if (!is_napot_order(order)) {
+			/*
+			 * Something's weird, we are given a NAPOT pte but the
+			 * size of the mapping is not a known NAPOT mapping
+			 * size, so clear the NAPOT bit and map this without
+			 * NAPOT support: core mm only manipulates pte with the
+			 * real pfn so we know the pte is valid without the N
+			 * bit.
+			 */
+			pr_err("Incorrect NAPOT mapping, resetting.\n");
+			pteval = pte_clear_napot(pteval);
+		} else {
+			/*
+			 * NAPOT ptes that arrive here only have the N bit set
+			 * and their pfn does not contain the mapping size, so
+			 * set that here.
+			 */
+			pteval = pte_mknapot(pteval, order);
+		}
+	}
+
+	___set_ptes(mm, addr, ptep, pteval, nr);
+}
+
+#define ptep_get			__ptep_get
+#define set_ptes			__set_ptes
+#define set_contptes(mm, addr, ptep, pte, nr, pgsize)			\
+			set_ptes(mm, addr, ptep, pte, nr)
+#else
+#define ptep_get			___ptep_get
+#define __ptep_get			___ptep_get
+#define set_ptes			___set_ptes
+#define __set_ptes			___set_ptes
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+				       unsigned long address, pte_t *ptep)
+{
+	pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+
+	page_table_check_pte_clear(mm, pte);
+
+	return pte;
+}
+#endif /* CONFIG_RISCV_ISA_SVNAPOT */
+
 #define pgprot_nx pgprot_nx
 static inline pgprot_t pgprot_nx(pgprot_t _prot)
 {
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 3192ad804279..60b7e738b31a 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -190,7 +190,7 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 
 	for_each_napot_order(order) {
 		if (shift == napot_cont_shift(order)) {
-			entry = pte_mknapot(entry, order);
+			entry = pte_mkcont(entry);
 			break;
 		}
 	}
@@ -267,8 +267,7 @@ void set_huge_pte_at(struct mm_struct *mm,
 
 	clear_flush(mm, addr, ptep, pgsize, pte_num);
 
-	for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
-		set_pte_at(mm, addr, ptep, pte);
+	set_ptes(mm, addr, ptep, pte, pte_num);
 }
 
 int huge_ptep_set_access_flags(struct vm_area_struct *vma,
@@ -280,7 +279,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long order;
 	pte_t orig_pte;
-	int i, pte_num;
+	int pte_num;
 
 	if (!pte_napot(pte))
 		return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
@@ -295,8 +294,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 	if (pte_young(orig_pte))
 		pte = pte_mkyoung(pte);
 
-	for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++)
-		set_pte_at(mm, addr, ptep, pte);
+	set_ptes(mm, addr, ptep, pte, pte_num);
 
 	return true;
 }
@@ -324,7 +322,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 	pte_t pte = ptep_get(ptep);
 	unsigned long order;
 	pte_t orig_pte;
-	int i, pte_num;
+	int pte_num;
 
 	if (!pte_napot(pte)) {
 		ptep_set_wrprotect(mm, addr, ptep);
@@ -337,8 +335,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 
 	orig_pte = pte_wrprotect(orig_pte);
 
-	for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++)
-		set_pte_at(mm, addr, ptep, orig_pte);
+	set_ptes(mm, addr, ptep, orig_pte, pte_num);
 }
 
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:29 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:29 +0100
Subject: [PATCH v5 3/9] mm: Use common huge_ptep_get() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-4-alexghiti@rivosinc.com>

After some adjustments, both architectures have the same implementation
so move it to the generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/Kconfig               |  1 +
 arch/arm64/include/asm/hugetlb.h |  3 +-
 arch/arm64/include/asm/pgtable.h | 57 +++++++++++++++++++++++++--
 arch/arm64/mm/hugetlbpage.c      | 66 ++------------------------------
 arch/riscv/Kconfig               |  1 +
 arch/riscv/include/asm/hugetlb.h |  6 +--
 arch/riscv/include/asm/pgtable.h | 45 ++++++++++++++++++++++
 arch/riscv/mm/hugetlbpage.c      | 62 +++---------------------------
 include/linux/hugetlb_contpte.h  | 12 ++++++
 mm/Kconfig                       |  3 ++
 mm/Makefile                      |  1 +
 mm/hugetlb_contpte.c             | 32 ++++++++++++++++
 12 files changed, 161 insertions(+), 128 deletions(-)
 create mode 100644 include/linux/hugetlb_contpte.h
 create mode 100644 mm/hugetlb_contpte.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..5a1e1bc73c15 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -113,6 +113,7 @@ config ARM64
 	select ARCH_WANT_DEFAULT_BPF_JIT
 	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
 	select ARCH_WANT_FRAME_POINTERS
+	select ARCH_WANT_GENERAL_HUGETLB_CONTPTE
 	select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
 	select ARCH_WANT_LD_ORPHAN_WARN
 	select ARCH_WANTS_EXECMEM_LATE
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 07fbf5bf85a7..0604e01dca97 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -13,6 +13,7 @@
 #include <asm/cacheflush.h>
 #include <asm/mte.h>
 #include <asm/page.h>
+#include <linux/hugetlb_contpte.h>
 
 #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
 #define arch_hugetlb_migration_supported arch_hugetlb_migration_supported
@@ -53,8 +54,6 @@ extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 #define __HAVE_ARCH_HUGE_PTE_CLEAR
 extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 			   pte_t *ptep, unsigned long sz);
-#define __HAVE_ARCH_HUGE_PTEP_GET
-extern pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
 
 void __init arm64_hugetlb_cma_reserve(void);
 
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 0b2a2ad1b9e8..af8156929c1d 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -420,9 +420,10 @@ static inline pte_t pte_advance_pfn(pte_t pte, unsigned long nr)
 	return pfn_pte(pte_pfn(pte) + nr, pte_pgprot(pte));
 }
 
-static inline void __set_ptes(struct mm_struct *mm,
-			      unsigned long __always_unused addr,
-			      pte_t *ptep, pte_t pte, unsigned int nr)
+static inline void ___set_ptes(struct mm_struct *mm,
+			       unsigned long __always_unused addr,
+			       pte_t *ptep, pte_t pte, unsigned int nr,
+			       size_t pgsize)
 {
 	page_table_check_ptes_set(mm, ptep, pte, nr);
 	__sync_cache_and_tags(pte, nr);
@@ -433,10 +434,15 @@ static inline void __set_ptes(struct mm_struct *mm,
 		if (--nr == 0)
 			break;
 		ptep++;
-		pte = pte_advance_pfn(pte, 1);
+		pte = pte_advance_pfn(pte, pgsize >> PAGE_SHIFT);
 	}
 }
 
+#define __set_ptes(mm, addr, ptep, pte, nr)				\
+			___set_ptes(mm, addr, ptep, pte, nr, PAGE_SIZE)
+
+#define set_contptes	___set_ptes
+
 /*
  * Hugetlb definitions.
  */
@@ -1825,6 +1831,49 @@ static inline void clear_young_dirty_ptes(struct vm_area_struct *vma,
 
 #endif /* CONFIG_ARM64_CONTPTE */
 
+static inline bool __hugetlb_valid_size(unsigned long size)
+{
+	switch (size) {
+#ifndef __PAGETABLE_PMD_FOLDED
+	case PUD_SIZE:
+		return pud_sect_supported();
+#endif
+	case CONT_PMD_SIZE:
+	case PMD_SIZE:
+	case CONT_PTE_SIZE:
+		return true;
+	}
+
+	return false;
+}
+
+static inline int arch_contpte_get_num_contig(pte_t *ptep,
+					      unsigned long size,
+					      size_t *pgsize)
+{
+	int contig_ptes = 1;
+
+	if (pgsize)
+		*pgsize = size;
+
+	switch (size) {
+	case CONT_PMD_SIZE:
+		if (pgsize)
+			*pgsize = PMD_SIZE;
+		contig_ptes = CONT_PMDS;
+		break;
+	case CONT_PTE_SIZE:
+		if (pgsize)
+			*pgsize = PAGE_SIZE;
+		contig_ptes = CONT_PTES;
+		break;
+	default:
+		WARN_ON(!__hugetlb_valid_size(size));
+	}
+
+	return contig_ptes;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_PGTABLE_H */
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index b3a7fafe8892..60a2bb7575c1 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -49,22 +49,6 @@ void __init arm64_hugetlb_cma_reserve(void)
 }
 #endif /* CONFIG_CMA */
 
-static bool __hugetlb_valid_size(unsigned long size)
-{
-	switch (size) {
-#ifndef __PAGETABLE_PMD_FOLDED
-	case PUD_SIZE:
-		return pud_sect_supported();
-#endif
-	case CONT_PMD_SIZE:
-	case PMD_SIZE:
-	case CONT_PTE_SIZE:
-		return true;
-	}
-
-	return false;
-}
-
 #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
 bool arch_hugetlb_migration_supported(struct hstate *h)
 {
@@ -98,50 +82,6 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
 	return CONT_PTES;
 }
 
-static inline int num_contig_ptes(unsigned long size, size_t *pgsize)
-{
-	int contig_ptes = 1;
-
-	*pgsize = size;
-
-	switch (size) {
-	case CONT_PMD_SIZE:
-		*pgsize = PMD_SIZE;
-		contig_ptes = CONT_PMDS;
-		break;
-	case CONT_PTE_SIZE:
-		*pgsize = PAGE_SIZE;
-		contig_ptes = CONT_PTES;
-		break;
-	default:
-		WARN_ON(!__hugetlb_valid_size(size));
-	}
-
-	return contig_ptes;
-}
-
-pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	int ncontig, i;
-	size_t pgsize;
-	pte_t orig_pte = __ptep_get(ptep);
-
-	if (!pte_present(orig_pte) || !pte_cont(orig_pte))
-		return orig_pte;
-
-	ncontig = num_contig_ptes(page_size(pte_page(orig_pte)), &pgsize);
-	for (i = 0; i < ncontig; i++, ptep++) {
-		pte_t pte = __ptep_get(ptep);
-
-		if (pte_dirty(pte))
-			orig_pte = pte_mkdirty(orig_pte);
-
-		if (pte_young(pte))
-			orig_pte = pte_mkyoung(orig_pte);
-	}
-	return orig_pte;
-}
-
 /*
  * Changing some bits of contiguous entries requires us to follow a
  * Break-Before-Make approach, breaking the whole contiguous set
@@ -221,7 +161,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	unsigned long pfn, dpfn;
 	pgprot_t hugeprot;
 
-	ncontig = num_contig_ptes(sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
 
 	if (!pte_present(pte)) {
 		for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
@@ -382,7 +322,7 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 	int i, ncontig;
 	size_t pgsize;
 
-	ncontig = num_contig_ptes(sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
 
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
 		__pte_clear(mm, addr, ptep);
@@ -394,7 +334,7 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 	int ncontig;
 	size_t pgsize;
 
-	ncontig = num_contig_ptes(sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
 	return get_clear_contig(mm, addr, ptep, pgsize, ncontig);
 }
 
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 7612c52e9b1e..2a5b2a9f2816 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -79,6 +79,7 @@ config RISCV
 	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_WANT_GENERAL_HUGETLB if !RISCV_ISA_SVNAPOT
+	select ARCH_WANT_GENERAL_HUGETLB_CONTPTE if RISCV_ISA_SVNAPOT
 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
 	select ARCH_WANT_LD_ORPHAN_WARN if !XIP_KERNEL
 	select ARCH_WANT_OPTIMIZE_DAX_VMEMMAP
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 446126497768..69393346ade0 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -4,6 +4,9 @@
 
 #include <asm/cacheflush.h>
 #include <asm/page.h>
+#ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB_CONTPTE
+#include <linux/hugetlb_contpte.h>
+#endif
 
 static inline void arch_clear_hugetlb_flags(struct folio *folio)
 {
@@ -44,9 +47,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 			       unsigned long addr, pte_t *ptep,
 			       pte_t pte, int dirty);
 
-#define __HAVE_ARCH_HUGE_PTEP_GET
-pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
 
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 2e62d7e607db..286fe1a32ded 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -296,6 +296,8 @@ static inline unsigned long pte_napot(pte_t pte)
 	return pte_val(pte) & _PAGE_NAPOT;
 }
 
+#define pte_cont		pte_napot
+
 #define pte_valid_napot(pte)	(pte_present(pte) && pte_napot(pte))
 
 /*
@@ -606,6 +608,49 @@ static inline void ___set_ptes(struct mm_struct *mm, unsigned long addr,
 	}
 }
 
+#ifdef CONFIG_RISCV_ISA_SVNAPOT
+/*
+ * Some hugetlb functions can be called on !present ptes, so we must use the
+ * size parameter when it is passed.
+ */
+static inline int arch_contpte_get_num_contig(pte_t *ptep, unsigned long size,
+					      size_t *pgsize)
+{
+	unsigned long hugepage_shift;
+	pte_t __pte;
+
+	if (size) {
+		if (size >= PGDIR_SIZE)
+			hugepage_shift = PGDIR_SHIFT;
+		else if (size >= P4D_SIZE)
+			hugepage_shift = P4D_SHIFT;
+		else if (size >= PUD_SIZE)
+			hugepage_shift = PUD_SHIFT;
+		else if (size >= PMD_SIZE)
+			hugepage_shift = PMD_SHIFT;
+		else
+			hugepage_shift = PAGE_SHIFT;
+	} else {
+		/*
+		 * We must read the raw value of the pte to get the size of
+		 * the mapping
+		 */
+		__pte = ___ptep_get(ptep);
+
+		/* Make sure __pte is not a swap entry */
+		BUG_ON(!pte_valid_napot(__pte));
+
+		hugepage_shift = PAGE_SHIFT;
+		size = napot_cont_size(napot_cont_order(__pte));
+	}
+
+	if (pgsize)
+		*pgsize = BIT(hugepage_shift);
+
+	return size >> hugepage_shift;
+}
+#endif
+
 static inline void pte_clear(struct mm_struct *mm,
 	unsigned long addr, pte_t *ptep)
 {
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 60b7e738b31a..b9eb6b7b214d 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -3,30 +3,6 @@
 #include <linux/err.h>
 
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
-pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	unsigned long pte_num;
-	int i;
-	pte_t orig_pte = ptep_get(ptep);
-
-	if (!pte_present(orig_pte) || !pte_napot(orig_pte))
-		return orig_pte;
-
-	pte_num = napot_pte_num(napot_cont_order(orig_pte));
-
-	for (i = 0; i < pte_num; i++, ptep++) {
-		pte_t pte = ptep_get(ptep);
-
-		if (pte_dirty(pte))
-			orig_pte = pte_mkdirty(orig_pte);
-
-		if (pte_young(pte))
-			orig_pte = pte_mkyoung(orig_pte);
-	}
-
-	return orig_pte;
-}
-
 pte_t *huge_pte_alloc(struct mm_struct *mm,
 		      struct vm_area_struct *vma,
 		      unsigned long addr,
@@ -215,26 +191,6 @@ static void clear_flush(struct mm_struct *mm,
 	flush_tlb_range(&vma, saddr, addr);
 }
 
-static int num_contig_ptes_from_size(unsigned long sz, size_t *pgsize)
-{
-	unsigned long hugepage_shift;
-
-	if (sz >= PGDIR_SIZE)
-		hugepage_shift = PGDIR_SHIFT;
-	else if (sz >= P4D_SIZE)
-		hugepage_shift = P4D_SHIFT;
-	else if (sz >= PUD_SIZE)
-		hugepage_shift = PUD_SHIFT;
-	else if (sz >= PMD_SIZE)
-		hugepage_shift = PMD_SHIFT;
-	else
-		hugepage_shift = PAGE_SHIFT;
-
-	*pgsize = 1 << hugepage_shift;
-
-	return sz >> hugepage_shift;
-}
-
 /*
  * When dealing with NAPOT mappings, the privileged specification indicates that
  * "if an update needs to be made, the OS generally should first mark all of the
@@ -252,7 +208,7 @@ void set_huge_pte_at(struct mm_struct *mm,
 	size_t pgsize;
 	int i, pte_num;
 
-	pte_num = num_contig_ptes_from_size(sz, &pgsize);
+	pte_num = arch_contpte_get_num_contig(ptep, sz, &pgsize);
 
 	if (!pte_present(pte)) {
 		for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
@@ -277,15 +233,13 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 			       int dirty)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	unsigned long order;
 	pte_t orig_pte;
 	int pte_num;
 
 	if (!pte_napot(pte))
 		return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
 
-	order = napot_cont_order(pte);
-	pte_num = napot_pte_num(order);
+	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
 
 	if (pte_dirty(orig_pte))
@@ -303,14 +257,13 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 			      unsigned long addr,
 			      pte_t *ptep, unsigned long sz)
 {
-	size_t pgsize;
 	pte_t orig_pte = ptep_get(ptep);
 	int pte_num;
 
 	if (!pte_napot(orig_pte))
 		return ptep_get_and_clear(mm, addr, ptep);
 
-	pte_num = num_contig_ptes_from_size(sz, &pgsize);
+	pte_num = arch_contpte_get_num_contig(ptep, sz, NULL);
 
 	return get_clear_contig(mm, addr, ptep, pte_num);
 }
@@ -320,7 +273,6 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     pte_t *ptep)
 {
 	pte_t pte = ptep_get(ptep);
-	unsigned long order;
 	pte_t orig_pte;
 	int pte_num;
 
@@ -329,8 +281,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 		return;
 	}
 
-	order = napot_cont_order(pte);
-	pte_num = napot_pte_num(order);
+	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
 
 	orig_pte = pte_wrprotect(orig_pte);
@@ -348,7 +299,7 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 	if (!pte_napot(pte))
 		return ptep_clear_flush(vma, addr, ptep);
 
-	pte_num = napot_pte_num(napot_cont_order(pte));
+	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
 
 	return get_clear_contig_flush(vma->vm_mm, addr, ptep, pte_num);
 }
@@ -367,8 +318,7 @@ void huge_pte_clear(struct mm_struct *mm,
 		return;
 	}
 
-	pte_num = num_contig_ptes_from_size(sz, &pgsize);
-
+	pte_num = arch_contpte_get_num_contig(ptep, sz, &pgsize);
 	for (i = 0; i < pte_num; i++, addr += pgsize, ptep++)
 		pte_clear(mm, addr, ptep);
 }
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
new file mode 100644
index 000000000000..2ea17e4fe36b
--- /dev/null
+++ b/include/linux/hugetlb_contpte.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 Rivos Inc.
+ */
+
+#ifndef _LINUX_HUGETLB_CONTPTE_H
+#define _LINUX_HUGETLB_CONTPTE_H
+
+#define __HAVE_ARCH_HUGE_PTEP_GET
+extern pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+
+#endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/Kconfig b/mm/Kconfig
index 1b501db06417..f9d3f3d49f3e 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -853,6 +853,9 @@ config NOMMU_INITIAL_TRIM_EXCESS
 config ARCH_WANT_GENERAL_HUGETLB
 	bool
 
+config ARCH_WANT_GENERAL_HUGETLB_CONTPTE
+	bool
+
 config ARCH_WANTS_THP_SWAP
 	def_bool n
 
diff --git a/mm/Makefile b/mm/Makefile
index 850386a67b3e..76e8b995f551 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_MIGRATION) += migrate.o
 obj-$(CONFIG_NUMA) += memory-tiers.o
 obj-$(CONFIG_DEVICE_MIGRATION) += migrate_device.o
 obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o khugepaged.o
+obj-$(CONFIG_ARCH_WANT_GENERAL_HUGETLB_CONTPTE) += hugetlb_contpte.o
 obj-$(CONFIG_PAGE_COUNTER) += page_counter.o
 obj-$(CONFIG_MEMCG_V1) += memcontrol-v1.o
 obj-$(CONFIG_MEMCG) += memcontrol.o vmpressure.o
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
new file mode 100644
index 000000000000..500d0b96a680
--- /dev/null
+++ b/mm/hugetlb_contpte.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2025 Rivos Inc.
+ */
+
+#include <linux/pgtable.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	int ncontig, i;
+	pte_t orig_pte = __ptep_get(ptep);
+
+	if (!pte_present(orig_pte) || !pte_cont(orig_pte))
+		return orig_pte;
+
+	ncontig = arch_contpte_get_num_contig(ptep,
+					      page_size(pte_page(orig_pte)),
+					      NULL);
+
+	for (i = 0; i < ncontig; i++, ptep++) {
+		pte_t pte = __ptep_get(ptep);
+
+		if (pte_dirty(pte))
+			orig_pte = pte_mkdirty(orig_pte);
+
+		if (pte_young(pte))
+			orig_pte = pte_mkyoung(orig_pte);
+	}
+	return orig_pte;
+}
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:30 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:30 +0100
Subject: [PATCH v5 4/9] mm: Use common set_huge_pte_at() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-5-alexghiti@rivosinc.com>

After some adjustments, both architectures have the same implementation
so move it to the generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  3 --
 arch/arm64/mm/hugetlbpage.c      | 56 --------------------------------
 arch/riscv/include/asm/hugetlb.h |  5 ---
 arch/riscv/include/asm/pgtable.h | 13 ++++----
 arch/riscv/mm/hugetlbpage.c      | 50 ----------------------------
 include/linux/hugetlb_contpte.h  |  5 +++
 mm/hugetlb_contpte.c             | 56 ++++++++++++++++++++++++++++++++
 7 files changed, 68 insertions(+), 120 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 0604e01dca97..cfdc04e11585 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -35,9 +35,6 @@ static inline void arch_clear_hugetlb_flags(struct folio *folio)
 
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
-#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
-extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-			    pte_t *ptep, pte_t pte, unsigned long sz);
 #define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
 extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 				      unsigned long addr, pte_t *ptep,
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 60a2bb7575c1..6feb90ed2e7d 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -128,62 +128,6 @@ static pte_t get_clear_contig_flush(struct mm_struct *mm,
 	return orig_pte;
 }
 
-/*
- * Changing some bits of contiguous entries requires us to follow a
- * Break-Before-Make approach, breaking the whole contiguous set
- * before we can change any entries. See ARM DDI 0487A.k_iss10775,
- * "Misprogramming of the Contiguous bit", page D4-1762.
- *
- * This helper performs the break step for use cases where the
- * original pte is not needed.
- */
-static void clear_flush(struct mm_struct *mm,
-			     unsigned long addr,
-			     pte_t *ptep,
-			     unsigned long pgsize,
-			     unsigned long ncontig)
-{
-	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
-	unsigned long i, saddr = addr;
-
-	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
-		__ptep_get_and_clear(mm, addr, ptep);
-
-	flush_tlb_range(&vma, saddr, addr);
-}
-
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-			    pte_t *ptep, pte_t pte, unsigned long sz)
-{
-	size_t pgsize;
-	int i;
-	int ncontig;
-	unsigned long pfn, dpfn;
-	pgprot_t hugeprot;
-
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
-
-	if (!pte_present(pte)) {
-		for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
-			__set_ptes(mm, addr, ptep, pte, 1);
-		return;
-	}
-
-	if (!pte_cont(pte)) {
-		__set_ptes(mm, addr, ptep, pte, 1);
-		return;
-	}
-
-	pfn = pte_pfn(pte);
-	dpfn = pgsize >> PAGE_SHIFT;
-	hugeprot = pte_pgprot(pte);
-
-	clear_flush(mm, addr, ptep, pgsize, ncontig);
-
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
-}
-
 pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
 		      unsigned long addr, unsigned long sz)
 {
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 69393346ade0..7049a17b819d 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -24,11 +24,6 @@ bool arch_hugetlb_migration_supported(struct hstate *h);
 void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 		    pte_t *ptep, unsigned long sz);
 
-#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
-void set_huge_pte_at(struct mm_struct *mm,
-		     unsigned long addr, pte_t *ptep, pte_t pte,
-		     unsigned long sz);
-
 #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 			      unsigned long addr, pte_t *ptep,
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 286fe1a32ded..5b34b3c9c0f9 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -715,9 +715,8 @@ static inline pte_t pte_napot_clear_pfn(pte_t *ptep, pte_t pte)
 	return pte;
 }
 
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pte_t *ptep)
+static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
+					 unsigned long address, pte_t *ptep)
 {
 	pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
 
@@ -775,9 +774,8 @@ static inline void __set_ptes(struct mm_struct *mm, unsigned long addr,
 #define set_ptes			___set_ptes
 #define __set_ptes			___set_ptes
 
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pte_t *ptep)
+static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
+					 unsigned long address, pte_t *ptep)
 {
 	pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
 
@@ -787,6 +785,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 }
 #endif /* CONFIG_RISCV_ISA_SVNAPOT */
 
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define ptep_get_and_clear	__ptep_get_and_clear
+
 #define pgprot_nx pgprot_nx
 static inline pgprot_t pgprot_nx(pgprot_t _prot)
 {
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index b9eb6b7b214d..75faeacc8138 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -176,56 +176,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-static void clear_flush(struct mm_struct *mm,
-			unsigned long addr,
-			pte_t *ptep,
-			unsigned long pgsize,
-			unsigned long ncontig)
-{
-	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
-	unsigned long i, saddr = addr;
-
-	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
-		ptep_get_and_clear(mm, addr, ptep);
-
-	flush_tlb_range(&vma, saddr, addr);
-}
-
-/*
- * When dealing with NAPOT mappings, the privileged specification indicates that
- * "if an update needs to be made, the OS generally should first mark all of the
- * PTEs invalid, then issue SFENCE.VMA instruction(s) covering all 4 KiB regions
- * within the range, [...] then update the PTE(s), as described in Section
- * 4.2.1.". That's the equivalent of the Break-Before-Make approach used by
- * arm64.
- */
-void set_huge_pte_at(struct mm_struct *mm,
-		     unsigned long addr,
-		     pte_t *ptep,
-		     pte_t pte,
-		     unsigned long sz)
-{
-	size_t pgsize;
-	int i, pte_num;
-
-	pte_num = arch_contpte_get_num_contig(ptep, sz, &pgsize);
-
-	if (!pte_present(pte)) {
-		for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
-			set_ptes(mm, addr, ptep, pte, 1);
-		return;
-	}
-
-	if (!pte_napot(pte)) {
-		set_ptes(mm, addr, ptep, pte, 1);
-		return;
-	}
-
-	clear_flush(mm, addr, ptep, pgsize, pte_num);
-
-	set_ptes(mm, addr, ptep, pte, pte_num);
-}
-
 int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 			       unsigned long addr,
 			       pte_t *ptep,
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index 2ea17e4fe36b..135b68bd09ca 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -9,4 +9,9 @@
 #define __HAVE_ARCH_HUGE_PTEP_GET
 extern pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
 
+#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
+extern void set_huge_pte_at(struct mm_struct *mm,
+			    unsigned long addr, pte_t *ptep, pte_t pte,
+			    unsigned long sz);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index 500d0b96a680..cbf93ffcd882 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -30,3 +30,59 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 	}
 	return orig_pte;
 }
+
+/*
+ * ARM64: Changing some bits of contiguous entries requires us to follow a
+ * Break-Before-Make approach, breaking the whole contiguous set
+ * before we can change any entries. See ARM DDI 0487A.k_iss10775,
+ * "Misprogramming of the Contiguous bit", page D4-1762.
+ *
+ * RISCV: When dealing with NAPOT mappings, the privileged specification
+ * indicates that "if an update needs to be made, the OS generally should first
+ * mark all of the PTEs invalid, then issue SFENCE.VMA instruction(s) covering
+ * all 4 KiB regions within the range, [...] then update the PTE(s), as
+ * described in Section 4.2.1.". That's the equivalent of the Break-Before-Make
+ * approach used by arm64.
+ *
+ * This helper performs the break step for use cases where the
+ * original pte is not needed.
+ */
+static void clear_flush(struct mm_struct *mm,
+			unsigned long addr,
+			pte_t *ptep,
+			unsigned long pgsize,
+			unsigned long ncontig)
+{
+	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+	unsigned long i, saddr = addr;
+
+	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
+		__ptep_get_and_clear(mm, addr, ptep);
+
+	flush_tlb_range(&vma, saddr, addr);
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t pte, unsigned long sz)
+{
+	size_t pgsize;
+	int i;
+	int ncontig;
+
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+
+	if (!pte_present(pte)) {
+		for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
+			__set_ptes(mm, addr, ptep, pte, 1);
+		return;
+	}
+
+	if (!pte_cont(pte)) {
+		__set_ptes(mm, addr, ptep, pte, 1);
+		return;
+	}
+
+	clear_flush(mm, addr, ptep, pgsize, ncontig);
+
+	set_contptes(mm, addr, ptep, pte, ncontig, pgsize);
+}
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:31 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:31 +0100
Subject: [PATCH v5 5/9] mm: Use common huge_pte_clear() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-6-alexghiti@rivosinc.com>

Both architectures have the same implementation so move it to generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  3 ---
 arch/arm64/mm/hugetlbpage.c      | 12 ------------
 arch/riscv/include/asm/hugetlb.h |  4 ----
 arch/riscv/include/asm/pgtable.h |  5 +++--
 arch/riscv/mm/hugetlbpage.c      | 19 -------------------
 include/linux/hugetlb_contpte.h  |  4 ++++
 mm/hugetlb_contpte.c             | 12 ++++++++++++
 7 files changed, 19 insertions(+), 40 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index cfdc04e11585..ed75631ad63c 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -48,9 +48,6 @@ extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
 #define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
 extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 				   unsigned long addr, pte_t *ptep);
-#define __HAVE_ARCH_HUGE_PTE_CLEAR
-extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
-			   pte_t *ptep, unsigned long sz);
 
 void __init arm64_hugetlb_cma_reserve(void);
 
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 6feb90ed2e7d..99728b02a3ca 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -260,18 +260,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
-		    pte_t *ptep, unsigned long sz)
-{
-	int i, ncontig;
-	size_t pgsize;
-
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
-
-	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
-		__pte_clear(mm, addr, ptep);
-}
-
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep, unsigned long sz)
 {
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 7049a17b819d..467bc30c2153 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -20,10 +20,6 @@ bool arch_hugetlb_migration_supported(struct hstate *h);
 #endif
 
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
-#define __HAVE_ARCH_HUGE_PTE_CLEAR
-void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
-		    pte_t *ptep, unsigned long sz);
-
 #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 			      unsigned long addr, pte_t *ptep,
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 5b34b3c9c0f9..72d3592454d3 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -651,8 +651,8 @@ static inline int arch_contpte_get_num_contig(pte_t *ptep, unsigned long size,
 }
 #endif
 
-static inline void pte_clear(struct mm_struct *mm,
-	unsigned long addr, pte_t *ptep)
+static inline void __pte_clear(struct mm_struct *mm,
+			       unsigned long addr, pte_t *ptep)
 {
 	__set_pte_at(mm, ptep, __pte(0));
 }
@@ -787,6 +787,7 @@ static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
 
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define ptep_get_and_clear	__ptep_get_and_clear
+#define pte_clear		__pte_clear
 
 #define pgprot_nx pgprot_nx
 static inline pgprot_t pgprot_nx(pgprot_t _prot)
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 75faeacc8138..fe82284c3dc4 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -254,25 +254,6 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 	return get_clear_contig_flush(vma->vm_mm, addr, ptep, pte_num);
 }
 
-void huge_pte_clear(struct mm_struct *mm,
-		    unsigned long addr,
-		    pte_t *ptep,
-		    unsigned long sz)
-{
-	size_t pgsize;
-	pte_t pte = ptep_get(ptep);
-	int i, pte_num;
-
-	if (!pte_napot(pte)) {
-		pte_clear(mm, addr, ptep);
-		return;
-	}
-
-	pte_num = arch_contpte_get_num_contig(ptep, sz, &pgsize);
-	for (i = 0; i < pte_num; i++, addr += pgsize, ptep++)
-		pte_clear(mm, addr, ptep);
-}
-
 static bool is_napot_size(unsigned long size)
 {
 	unsigned long order;
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index 135b68bd09ca..e6aa9befa78c 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -14,4 +14,8 @@ extern void set_huge_pte_at(struct mm_struct *mm,
 			    unsigned long addr, pte_t *ptep, pte_t pte,
 			    unsigned long sz);
 
+#define __HAVE_ARCH_HUGE_PTE_CLEAR
+extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+			   pte_t *ptep, unsigned long sz);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index cbf93ffcd882..e881b302dd63 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -86,3 +86,15 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 
 	set_contptes(mm, addr, ptep, pte, ncontig, pgsize);
 }
+
+void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+		    pte_t *ptep, unsigned long sz)
+{
+	int i, ncontig;
+	size_t pgsize;
+
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+
+	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
+		__pte_clear(mm, addr, ptep);
+}
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:33 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:33 +0100
Subject: [PATCH v5 7/9] mm: Use common huge_ptep_set_access_flags() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-8-alexghiti@rivosinc.com>

Both architectures have almost the same implementation:
__cont_access_flags_changed() is also correct on riscv and brings the
same benefits (ie don't do anything if the flags are unchanged).

As in the previous commit, get_clear_contig_flush() is duplicated in both
the arch and the generic codes, it will be removed from the arch code when
the last reference there gets moved to the generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  4 --
 arch/arm64/include/asm/pgtable.h | 15 +++++-
 arch/arm64/mm/hugetlbpage.c      | 69 +--------------------------
 arch/riscv/include/asm/hugetlb.h |  5 --
 arch/riscv/include/asm/pgtable.h | 11 +++--
 arch/riscv/mm/hugetlbpage.c      | 32 ++-----------
 arch/riscv/mm/pgtable.c          |  6 +--
 include/linux/hugetlb_contpte.h  |  5 ++
 mm/hugetlb_contpte.c             | 81 ++++++++++++++++++++++++++++++--
 9 files changed, 110 insertions(+), 118 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 9b1c25775bea..29a9dac52cef 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -35,10 +35,6 @@ static inline void arch_clear_hugetlb_flags(struct folio *folio)
 
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
-#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
-extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-				      unsigned long addr, pte_t *ptep,
-				      pte_t pte, int dirty);
 #define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
 extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
 				    unsigned long addr, pte_t *ptep);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index af8156929c1d..9b5c57e56691 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -1847,12 +1847,23 @@ static inline bool __hugetlb_valid_size(unsigned long size)
 	return false;
 }
 
-static inline int arch_contpte_get_num_contig(pte_t *ptep,
-					      unsigned long size,
+extern int find_num_contig(struct mm_struct *mm, unsigned long addr,
+			   pte_t *ptep, size_t *pgsize);
+
+static inline int arch_contpte_get_num_contig(struct mm_struct *mm,
+					      unsigned long addr,
+					      pte_t *ptep, unsigned long size,
 					      size_t *pgsize)
 {
 	int contig_ptes = 1;
 
+	/*
+	 * If the size is not passed, we need to go through the page table to
+	 * find out the number of contiguous ptes.
+	 */
+	if (size == 0)
+		return find_num_contig(mm, addr, ptep, pgsize);
+
 	if (pgsize)
 		*pgsize = size;
 
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 62a66ce2b2fe..03cb757f7935 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -63,8 +63,8 @@ bool arch_hugetlb_migration_supported(struct hstate *h)
 }
 #endif
 
-static int find_num_contig(struct mm_struct *mm, unsigned long addr,
-			   pte_t *ptep, size_t *pgsize)
+int find_num_contig(struct mm_struct *mm, unsigned long addr,
+		    pte_t *ptep, size_t *pgsize)
 {
 	pgd_t *pgdp = pgd_offset(mm, addr);
 	p4d_t *p4dp;
@@ -260,71 +260,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-/*
- * huge_ptep_set_access_flags will update access flags (dirty, accesssed)
- * and write permission.
- *
- * For a contiguous huge pte range we need to check whether or not write
- * permission has to change only on the first pte in the set. Then for
- * all the contiguous ptes we need to check whether or not there is a
- * discrepancy between dirty or young.
- */
-static int __cont_access_flags_changed(pte_t *ptep, pte_t pte, int ncontig)
-{
-	int i;
-
-	if (pte_write(pte) != pte_write(__ptep_get(ptep)))
-		return 1;
-
-	for (i = 0; i < ncontig; i++) {
-		pte_t orig_pte = __ptep_get(ptep + i);
-
-		if (pte_dirty(pte) != pte_dirty(orig_pte))
-			return 1;
-
-		if (pte_young(pte) != pte_young(orig_pte))
-			return 1;
-	}
-
-	return 0;
-}
-
-int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-			       unsigned long addr, pte_t *ptep,
-			       pte_t pte, int dirty)
-{
-	int ncontig, i;
-	size_t pgsize = 0;
-	unsigned long pfn = pte_pfn(pte), dpfn;
-	struct mm_struct *mm = vma->vm_mm;
-	pgprot_t hugeprot;
-	pte_t orig_pte;
-
-	if (!pte_cont(pte))
-		return __ptep_set_access_flags(vma, addr, ptep, pte, dirty);
-
-	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
-	dpfn = pgsize >> PAGE_SHIFT;
-
-	if (!__cont_access_flags_changed(ptep, pte, ncontig))
-		return 0;
-
-	orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
-
-	/* Make sure we don't lose the dirty or young state */
-	if (pte_dirty(orig_pte))
-		pte = pte_mkdirty(pte);
-
-	if (pte_young(orig_pte))
-		pte = pte_mkyoung(pte);
-
-	hugeprot = pte_pgprot(pte);
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
-
-	return 1;
-}
-
 void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     unsigned long addr, pte_t *ptep)
 {
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 0fbb6b19df79..bf533c2cef84 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -28,11 +28,6 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     unsigned long addr, pte_t *ptep);
 
-#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
-int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-			       unsigned long addr, pte_t *ptep,
-			       pte_t pte, int dirty);
-
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
 
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 72d3592454d3..081385e0d10a 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -613,7 +613,9 @@ static inline void ___set_ptes(struct mm_struct *mm, unsigned long addr,
  * Some hugetlb functions can be called on !present ptes, so we must use the
  * size parameter when it is passed.
  */
-static inline int arch_contpte_get_num_contig(pte_t *ptep, unsigned long size,
+static inline int arch_contpte_get_num_contig(struct mm_struct *mm,
+					      unsigned long addr,
+					      pte_t *ptep, unsigned long size,
 					      size_t *pgsize)
 {
 	unsigned long hugepage_shift;
@@ -657,9 +659,8 @@ static inline void __pte_clear(struct mm_struct *mm,
 	__set_pte_at(mm, ptep, __pte(0));
 }
 
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS	/* defined in mm/pgtable.c */
-extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
-				 pte_t *ptep, pte_t entry, int dirty);
+extern int __ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+				   pte_t *ptep, pte_t entry, int dirty);
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG	/* defined in mm/pgtable.c */
 extern int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long address,
 				     pte_t *ptep);
@@ -788,6 +789,8 @@ static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define ptep_get_and_clear	__ptep_get_and_clear
 #define pte_clear		__pte_clear
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags	__ptep_set_access_flags
 
 #define pgprot_nx pgprot_nx
 static inline pgprot_t pgprot_nx(pgprot_t _prot)
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 87168123d4a2..b2046f4bd445 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -176,33 +176,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-			       unsigned long addr,
-			       pte_t *ptep,
-			       pte_t pte,
-			       int dirty)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	pte_t orig_pte;
-	int pte_num;
-
-	if (!pte_napot(pte))
-		return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
-
-	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
-	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
-
-	if (pte_dirty(orig_pte))
-		pte = pte_mkdirty(pte);
-
-	if (pte_young(orig_pte))
-		pte = pte_mkyoung(pte);
-
-	set_ptes(mm, addr, ptep, pte, pte_num);
-
-	return true;
-}
-
 void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     unsigned long addr,
 			     pte_t *ptep)
@@ -216,7 +189,8 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 		return;
 	}
 
-	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
+	pte_num = arch_contpte_get_num_contig(mm, addr, ptep, 0, NULL);
+
 	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
 
 	orig_pte = pte_wrprotect(orig_pte);
@@ -234,7 +208,7 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 	if (!pte_napot(pte))
 		return ptep_clear_flush(vma, addr, ptep);
 
-	pte_num = arch_contpte_get_num_contig(ptep, 0, NULL);
+	pte_num = arch_contpte_get_num_contig(vma->vm_mm, addr, ptep, 0, NULL);
 
 	return get_clear_contig_flush(vma->vm_mm, addr, ptep, pte_num);
 }
diff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c
index 4ae67324f992..af8b3769a349 100644
--- a/arch/riscv/mm/pgtable.c
+++ b/arch/riscv/mm/pgtable.c
@@ -5,9 +5,9 @@
 #include <linux/kernel.h>
 #include <linux/pgtable.h>
 
-int ptep_set_access_flags(struct vm_area_struct *vma,
-			  unsigned long address, pte_t *ptep,
-			  pte_t entry, int dirty)
+int __ptep_set_access_flags(struct vm_area_struct *vma,
+			    unsigned long address, pte_t *ptep,
+			    pte_t entry, int dirty)
 {
 	asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
 		 : : : : svvptc);
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index 1c8f46ff95ea..e129578f6500 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -23,4 +23,9 @@ extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 				     unsigned long addr, pte_t *ptep,
 				     unsigned long sz);
 
+#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
+extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+				      unsigned long addr, pte_t *ptep,
+				      pte_t pte, int dirty);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index 82f49eb79ffb..b4c409d11195 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -15,7 +15,7 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 	if (!pte_present(orig_pte) || !pte_cont(orig_pte))
 		return orig_pte;
 
-	ncontig = arch_contpte_get_num_contig(ptep,
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep,
 					      page_size(pte_page(orig_pte)),
 					      NULL);
 
@@ -69,7 +69,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	int i;
 	int ncontig;
 
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep, sz, &pgsize);
 
 	if (!pte_present(pte)) {
 		for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
@@ -93,7 +93,7 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 	int i, ncontig;
 	size_t pgsize;
 
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep, sz, &pgsize);
 
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
 		__pte_clear(mm, addr, ptep);
@@ -145,7 +145,80 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 	int ncontig;
 	size_t pgsize;
 
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep, sz, &pgsize);
 
 	return get_clear_contig(mm, addr, ptep, pgsize, ncontig);
 }
+
+/*
+ * huge_ptep_set_access_flags will update access flags (dirty, accesssed)
+ * and write permission.
+ *
+ * For a contiguous huge pte range we need to check whether or not write
+ * permission has to change only on the first pte in the set. Then for
+ * all the contiguous ptes we need to check whether or not there is a
+ * discrepancy between dirty or young.
+ */
+static int __cont_access_flags_changed(pte_t *ptep, pte_t pte, int ncontig)
+{
+	int i;
+
+	if (pte_write(pte) != pte_write(__ptep_get(ptep)))
+		return 1;
+
+	for (i = 0; i < ncontig; i++) {
+		pte_t orig_pte = __ptep_get(ptep + i);
+
+		if (pte_dirty(pte) != pte_dirty(orig_pte))
+			return 1;
+
+		if (pte_young(pte) != pte_young(orig_pte))
+			return 1;
+	}
+
+	return 0;
+}
+
+static pte_t get_clear_contig_flush(struct mm_struct *mm,
+				    unsigned long addr,
+				    pte_t *ptep,
+				    unsigned long pgsize,
+				    unsigned long ncontig)
+{
+	pte_t orig_pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+
+	flush_tlb_range(&vma, addr, addr + (pgsize * ncontig));
+	return orig_pte;
+}
+
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+			       unsigned long addr, pte_t *ptep,
+			       pte_t pte, int dirty)
+{
+	int ncontig;
+	size_t pgsize = 0;
+	struct mm_struct *mm = vma->vm_mm;
+	pte_t orig_pte;
+
+	if (!pte_cont(pte))
+		return __ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+
+	ncontig = arch_contpte_get_num_contig(vma->vm_mm, addr, ptep, 0, &pgsize);
+
+	if (!__cont_access_flags_changed(ptep, pte, ncontig))
+		return 0;
+
+	orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
+
+	/* Make sure we don't lose the dirty or young state */
+	if (pte_dirty(orig_pte))
+		pte = pte_mkdirty(pte);
+
+	if (pte_young(orig_pte))
+		pte = pte_mkyoung(pte);
+
+	set_contptes(mm, addr, ptep, pte, ncontig, pgsize);
+
+	return 1;
+}
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:34 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:34 +0100
Subject: [PATCH v5 8/9] mm: Use common huge_ptep_set_wrprotect() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-9-alexghiti@rivosinc.com>

After some adjustments, both architectures have the same implementation
so move it to the generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  3 ---
 arch/arm64/mm/hugetlbpage.c      | 27 ---------------------------
 arch/riscv/include/asm/hugetlb.h |  4 ----
 arch/riscv/include/asm/pgtable.h |  7 ++++---
 arch/riscv/mm/hugetlbpage.c      | 22 ----------------------
 include/linux/hugetlb_contpte.h  |  4 ++++
 mm/hugetlb_contpte.c             | 20 ++++++++++++++++++++
 7 files changed, 28 insertions(+), 59 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 29a9dac52cef..f568467e8ba2 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -35,9 +35,6 @@ static inline void arch_clear_hugetlb_flags(struct folio *folio)
 
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
-#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
-extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
-				    unsigned long addr, pte_t *ptep);
 #define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
 extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 				   unsigned long addr, pte_t *ptep);
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 03cb757f7935..17f1ed34356d 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -260,33 +260,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-void huge_ptep_set_wrprotect(struct mm_struct *mm,
-			     unsigned long addr, pte_t *ptep)
-{
-	unsigned long pfn, dpfn;
-	pgprot_t hugeprot;
-	int ncontig, i;
-	size_t pgsize;
-	pte_t pte;
-
-	if (!pte_cont(__ptep_get(ptep))) {
-		__ptep_set_wrprotect(mm, addr, ptep);
-		return;
-	}
-
-	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
-	dpfn = pgsize >> PAGE_SHIFT;
-
-	pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
-	pte = pte_wrprotect(pte);
-
-	hugeprot = pte_pgprot(pte);
-	pfn = pte_pfn(pte);
-
-	for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-		__set_ptes(mm, addr, ptep, pfn_pte(pfn, hugeprot), 1);
-}
-
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 			    unsigned long addr, pte_t *ptep)
 {
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index bf533c2cef84..4c692dd82779 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -24,10 +24,6 @@ bool arch_hugetlb_migration_supported(struct hstate *h);
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 			    unsigned long addr, pte_t *ptep);
 
-#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
-void huge_ptep_set_wrprotect(struct mm_struct *mm,
-			     unsigned long addr, pte_t *ptep);
-
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
 
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 081385e0d10a..c41b49948ee9 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -665,9 +665,8 @@ extern int __ptep_set_access_flags(struct vm_area_struct *vma, unsigned long add
 extern int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long address,
 				     pte_t *ptep);
 
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(struct mm_struct *mm,
-				      unsigned long address, pte_t *ptep)
+static inline void __ptep_set_wrprotect(struct mm_struct *mm,
+					unsigned long address, pte_t *ptep)
 {
 	atomic_long_and(~(unsigned long)_PAGE_WRITE, (atomic_long_t *)ptep);
 }
@@ -791,6 +790,8 @@ static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
 #define pte_clear		__pte_clear
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags	__ptep_set_access_flags
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define ptep_set_wrprotect	__ptep_set_wrprotect
 
 #define pgprot_nx pgprot_nx
 static inline pgprot_t pgprot_nx(pgprot_t _prot)
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index b2046f4bd445..db13f7bcdd54 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -176,28 +176,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-void huge_ptep_set_wrprotect(struct mm_struct *mm,
-			     unsigned long addr,
-			     pte_t *ptep)
-{
-	pte_t pte = ptep_get(ptep);
-	pte_t orig_pte;
-	int pte_num;
-
-	if (!pte_napot(pte)) {
-		ptep_set_wrprotect(mm, addr, ptep);
-		return;
-	}
-
-	pte_num = arch_contpte_get_num_contig(mm, addr, ptep, 0, NULL);
-
-	orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num);
-
-	orig_pte = pte_wrprotect(orig_pte);
-
-	set_ptes(mm, addr, ptep, orig_pte, pte_num);
-}
-
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 			    unsigned long addr,
 			    pte_t *ptep)
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index e129578f6500..9ec8792a2f4d 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -28,4 +28,8 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 				      unsigned long addr, pte_t *ptep,
 				      pte_t pte, int dirty);
 
+#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
+extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
+				    unsigned long addr, pte_t *ptep);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index b4c409d11195..629878765081 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -222,3 +222,23 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 
 	return 1;
 }
+
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+			     unsigned long addr, pte_t *ptep)
+{
+	int ncontig;
+	size_t pgsize;
+	pte_t pte;
+
+	if (!pte_cont(__ptep_get(ptep))) {
+		__ptep_set_wrprotect(mm, addr, ptep);
+		return;
+	}
+
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep, 0, &pgsize);
+
+	pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
+	pte = pte_wrprotect(pte);
+
+	set_contptes(mm, addr, ptep, pte, ncontig, pgsize);
+}
-- 
2.39.2



From robh at kernel.org  Fri Mar 21 06:14:44 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 21 Mar 2025 08:14:44 -0500
Subject: [Linux-stm32] [PATCH 3/3] remoteproc: Use of_reserved_mem_region_*
 functions for "memory-region"
In-Reply-To: <4eddc37b-5164-453a-9b7f-c4331a7d6243@foss.st.com>
References: <20250317232426.952188-1-robh@kernel.org> <20250317232426.952188-4-robh@kernel.org>
 <26e72cb2-c355-4c40-bb98-fc0ff267bf4f@foss.st.com> <CAL_Jsq+7ZhMWgbFDvPB+3BG7YfiS9PweybOGNY3r=d40RbGHJA@mail.gmail.com>
 <130d61a8-6f03-46dc-94ca-f098bc09babc@foss.st.com> <CAL_JsqJZkEpx26=ro_y8hHA2x1Zm6z_SFOQHjQ-WzUa-gy+s0w@mail.gmail.com>
 <4eddc37b-5164-453a-9b7f-c4331a7d6243@foss.st.com>
Message-ID: <CAL_Jsq+pNGObRJs9tFgHQbC8kCVm=myt+syQSLJVaO8D2GWHCQ@mail.gmail.com>

On Fri, Mar 21, 2025 at 3:25?AM Arnaud POULIQUEN
<arnaud.pouliquen at foss.st.com> wrote:
>
>
>
> On 3/20/25 19:02, Rob Herring wrote:
> > On Thu, Mar 20, 2025 at 4:23?AM Arnaud POULIQUEN
> > <arnaud.pouliquen at foss.st.com> wrote:
> >>
> >>
> >>
> >> On 3/20/25 00:04, Rob Herring wrote:
> >>> On Wed, Mar 19, 2025 at 10:26?AM Arnaud POULIQUEN
> >>> <arnaud.pouliquen at foss.st.com> wrote:
> >>>>
> >>>> Hello Rob,
> >>>>
> >>>> On 3/18/25 00:24, Rob Herring (Arm) wrote:
> >>>>> Use the newly added of_reserved_mem_region_to_resource() and
> >>>>> of_reserved_mem_region_count() functions to handle "memory-region"
> >>>>> properties.
> >>>>>
> >>>>> The error handling is a bit different in some cases. Often
> >>>>> "memory-region" is optional, so failed lookup is not an error. But then
> >>>>> an error in of_reserved_mem_lookup() is treated as an error. However,
> >>>>> that distinction is not really important. Either the region is available
> >>>>> and usable or it is not. So now, it is just
> >>>>> of_reserved_mem_region_to_resource() which is checked for an error.
> >>>>>
> >>>>> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> >>>>> ---
> >>>>> For v6.16
> >>>>>
> >>>
> >>> [...]
> >>>
> >>>>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> >>>>> index b02b36a3f515..9d2bd8904c49 100644
> >>>>> --- a/drivers/remoteproc/stm32_rproc.c
> >>>>> +++ b/drivers/remoteproc/stm32_rproc.c
> >>>>> @@ -213,52 +213,46 @@ static int stm32_rproc_prepare(struct rproc *rproc)
> >>>>>  {
> >>>>>       struct device *dev = rproc->dev.parent;
> >>>>>       struct device_node *np = dev->of_node;
> >>>>> -     struct of_phandle_iterator it;
> >>>>>       struct rproc_mem_entry *mem;
> >>>>> -     struct reserved_mem *rmem;
> >>>>>       u64 da;
> >>>>> -     int index = 0;
> >>>>> +     int index = 0, mr = 0;
> >>>>>
> >>>>>       /* Register associated reserved memory regions */
> >>>>> -     of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
> >>>>> -     while (of_phandle_iterator_next(&it) == 0) {
> >>>>> -             rmem = of_reserved_mem_lookup(it.node);
> >>>>> -             if (!rmem) {
> >>>>> -                     of_node_put(it.node);
> >>>>> -                     dev_err(dev, "unable to acquire memory-region\n");
> >>>>> -                     return -EINVAL;
> >>>>> -             }
> >>>>> +     while (1) {
> >>>>> +             struct resource res;
> >>>>> +             int ret;
> >>>>> +
> >>>>> +             ret = of_reserved_mem_region_to_resource(np, mr++, &res);
> >>>>> +             if (ret)
> >>>>> +                     return 0;
> >>>>>
> >>>>> -             if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
> >>>>> -                     of_node_put(it.node);
> >>>>> -                     dev_err(dev, "memory region not valid %pa\n",
> >>>>> -                             &rmem->base);
> >>>>> +             if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) {
> >>>>> +                     dev_err(dev, "memory region not valid %pR\n", &res);
> >>>>>                       return -EINVAL;
> >>>>>               }
> >>>>>
> >>>>>               /*  No need to map vdev buffer */
> >>>>> -             if (strcmp(it.node->name, "vdev0buffer")) {
> >>>>> +             if (strcmp(res.name, "vdev0buffer")) {
> >>>>
> >>>> I tested your patches
> >>>
> >>> Thank you.
> >>>
> >>>> The update introduces a regression here. The strcmp function never returns 0.
> >>>> Indeed, it.node->name stores the memory region label "vdev0buffer," while
> >>>> res.name stores the memory region name "vdev0buffer at 10042000."
> >>>>
> >>>> Several remoteproc drivers may face the same issue as they embed similar code.
> >>>
> >>> Indeed. I confused myself because node 'name' is without the
> >>> unit-address, but this is using the full name. I've replaced the
> >>> strcmp's with strstarts() to address this. I've updated my branch with
> >>> the changes.
> >>
> >> This is not enough as the remoteproc core function rproc_find_carveout_by_name()
> >> also compares the memory names. With the following additional fix, it is working
> >> on my STM32MP15-DK board.
> >>
> >> @@ -309,11 +309,11 @@ rproc_find_carveout_by_name(struct rproc *rproc, const
> >> char *name, ...)
> >>         vsnprintf(_name, sizeof(_name), name, args);
> >>         va_end(args);
> >>
> >>         list_for_each_entry(carveout, &rproc->carveouts, node) {
> >>                 /* Compare carveout and requested names */
> >> -               if (!strcmp(carveout->name, _name)) {
> >> +               if (strstarts(carveout->name, _name)) {
> >>                         mem = carveout;
> >>                         break;
> >>                 }
> >>         }
> >>
> >> I just wonder if would not be more suitable to address this using the
> >> "memory-region-names" field.
> >
> > That would be better as you shouldn't really care what a provider node
> > name is where-as "memory-region-names" is meaningful to the driver.
> >
> >>
> >> The drawback is that we would break compatibility with legacy boards...
> >
> > So not an option.
>
> >
> > I think I'll have to fix this within the reserved mem code storing the
> > name or do something like the diff below. I'd like to avoid the
> > former. Using the original device_node.name is also problematic
> > because I want to get rid of it. We redundantly store the node name
> > with and without the unit-address. There's a lot of places like this
> > one where we hand out the pointer with no lifetime.
> >
> > diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
> > index 1e949694d365..cdee87c6ffe0 100644
> > --- a/drivers/remoteproc/stm32_rproc.c
> > +++ b/drivers/remoteproc/stm32_rproc.c
> > @@ -239,7 +239,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
> >                                                    resource_size(&res), da,
> >                                                    stm32_rproc_mem_alloc,
> >                                                    stm32_rproc_mem_release,
> > -                                                  res.name);
> > +                                                  "%.*s",
> > strchrnul(res.name, '@') - res.name, res.name);
> >
> >                         if (mem)
> >                                 rproc_coredump_add_segment(rproc, da,
> > @@ -249,7 +249,7 @@ static int stm32_rproc_prepare(struct rproc *rproc)
> >                         mem = rproc_of_resm_mem_entry_init(dev, index,
> >                                                            resource_size(&res),
> >                                                            res.start,
> > -                                                          res.name);
> > +                                                          "vdev0buffer");
> >                 }
> >
> >                 if (!mem) {
>
>
> That's work on my side.
> Could we have an OF helper to retrieve the name from the full name?

That would be: sprintf(buf, "%pOFn", node);

The problem here is we don't have the device_node pointer. The only
way I see to make the above prettier is perhaps a define.

Rob


From alexghiti at rivosinc.com  Fri Mar 21 06:06:35 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:35 +0100
Subject: [PATCH v5 9/9] mm: Use common huge_ptep_clear_flush() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-10-alexghiti@rivosinc.com>

After some adjustments, both architectures have the same implementation
so move it to the generic code.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  3 --
 arch/arm64/mm/hugetlbpage.c      | 60 --------------------------------
 arch/riscv/include/asm/hugetlb.h |  7 +---
 arch/riscv/mm/hugetlbpage.c      | 54 ----------------------------
 include/linux/hugetlb_contpte.h  |  4 +++
 mm/hugetlb_contpte.c             | 14 ++++++++
 6 files changed, 19 insertions(+), 123 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index f568467e8ba2..368600764127 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -35,9 +35,6 @@ static inline void arch_clear_hugetlb_flags(struct folio *folio)
 
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
-#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
-extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
-				   unsigned long addr, pte_t *ptep);
 
 void __init arm64_hugetlb_cma_reserve(void);
 
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 17f1ed34356d..08316cf4b104 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -82,52 +82,6 @@ int find_num_contig(struct mm_struct *mm, unsigned long addr,
 	return CONT_PTES;
 }
 
-/*
- * Changing some bits of contiguous entries requires us to follow a
- * Break-Before-Make approach, breaking the whole contiguous set
- * before we can change any entries. See ARM DDI 0487A.k_iss10775,
- * "Misprogramming of the Contiguous bit", page D4-1762.
- *
- * This helper performs the break step.
- */
-static pte_t get_clear_contig(struct mm_struct *mm,
-			     unsigned long addr,
-			     pte_t *ptep,
-			     unsigned long pgsize,
-			     unsigned long ncontig)
-{
-	pte_t pte, tmp_pte;
-	bool present;
-
-	pte = __ptep_get_and_clear(mm, addr, ptep);
-	present = pte_present(pte);
-	while (--ncontig) {
-		ptep++;
-		addr += pgsize;
-		tmp_pte = __ptep_get_and_clear(mm, addr, ptep);
-		if (present) {
-			if (pte_dirty(tmp_pte))
-				pte = pte_mkdirty(pte);
-			if (pte_young(tmp_pte))
-				pte = pte_mkyoung(pte);
-		}
-	}
-	return pte;
-}
-
-static pte_t get_clear_contig_flush(struct mm_struct *mm,
-				    unsigned long addr,
-				    pte_t *ptep,
-				    unsigned long pgsize,
-				    unsigned long ncontig)
-{
-	pte_t orig_pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
-	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
-
-	flush_tlb_range(&vma, addr, addr + (pgsize * ncontig));
-	return orig_pte;
-}
-
 pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
 		      unsigned long addr, unsigned long sz)
 {
@@ -260,20 +214,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
-			    unsigned long addr, pte_t *ptep)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	size_t pgsize;
-	int ncontig;
-
-	if (!pte_cont(__ptep_get(ptep)))
-		return ptep_clear_flush(vma, addr, ptep);
-
-	ncontig = find_num_contig(mm, addr, ptep, &pgsize);
-	return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
-}
-
 static int __init hugetlbpage_init(void)
 {
 	/*
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 4c692dd82779..63c7e4fa342a 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -20,14 +20,9 @@ bool arch_hugetlb_migration_supported(struct hstate *h);
 #endif
 
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
-#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
-pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
-			    unsigned long addr, pte_t *ptep);
-
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 #define arch_make_huge_pte arch_make_huge_pte
-
-#endif /*CONFIG_RISCV_ISA_SVNAPOT*/
+#endif /* CONFIG_RISCV_ISA_SVNAPOT */
 
 #include <asm-generic/hugetlb.h>
 
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index db13f7bcdd54..a6176415432a 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -121,45 +121,6 @@ unsigned long hugetlb_mask_last_page(struct hstate *h)
 	return 0UL;
 }
 
-static pte_t get_clear_contig(struct mm_struct *mm,
-			      unsigned long addr,
-			      pte_t *ptep,
-			      unsigned long ncontig)
-{
-	pte_t pte, tmp_pte;
-	bool present;
-
-	pte = ptep_get_and_clear(mm, addr, ptep);
-	present = pte_present(pte);
-	while (--ncontig) {
-		ptep++;
-		addr += PAGE_SIZE;
-		tmp_pte = ptep_get_and_clear(mm, addr, ptep);
-		if (present) {
-			if (pte_dirty(tmp_pte))
-				pte = pte_mkdirty(pte);
-			if (pte_young(tmp_pte))
-				pte = pte_mkyoung(pte);
-		}
-	}
-	return pte;
-}
-
-static pte_t get_clear_contig_flush(struct mm_struct *mm,
-				    unsigned long addr,
-				    pte_t *ptep,
-				    unsigned long pte_num)
-{
-	pte_t orig_pte = get_clear_contig(mm, addr, ptep, pte_num);
-	struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
-	bool valid = !pte_none(orig_pte);
-
-	if (valid)
-		flush_tlb_range(&vma, addr, addr + (PAGE_SIZE * pte_num));
-
-	return orig_pte;
-}
-
 pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 {
 	unsigned long order;
@@ -176,21 +137,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
-			    unsigned long addr,
-			    pte_t *ptep)
-{
-	pte_t pte = ptep_get(ptep);
-	int pte_num;
-
-	if (!pte_napot(pte))
-		return ptep_clear_flush(vma, addr, ptep);
-
-	pte_num = arch_contpte_get_num_contig(vma->vm_mm, addr, ptep, 0, NULL);
-
-	return get_clear_contig_flush(vma->vm_mm, addr, ptep, pte_num);
-}
-
 static bool is_napot_size(unsigned long size)
 {
 	unsigned long order;
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index 9ec8792a2f4d..e217a3412b13 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -32,4 +32,8 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
 				    unsigned long addr, pte_t *ptep);
 
+#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
+extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
+				   unsigned long addr, pte_t *ptep);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index 629878765081..1dc211d6fbe1 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -242,3 +242,17 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 
 	set_contptes(mm, addr, ptep, pte, ncontig, pgsize);
 }
+
+pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
+			    unsigned long addr, pte_t *ptep)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	size_t pgsize;
+	int ncontig;
+
+	if (!pte_cont(__ptep_get(ptep)))
+		return ptep_clear_flush(vma, addr, ptep);
+
+	ncontig = arch_contpte_get_num_contig(mm, addr, ptep, 0, &pgsize);
+	return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
+}
-- 
2.39.2



From alexghiti at rivosinc.com  Fri Mar 21 06:06:32 2025
From: alexghiti at rivosinc.com (Alexandre Ghiti)
Date: Fri, 21 Mar 2025 14:06:32 +0100
Subject: [PATCH v5 6/9] mm: Use common huge_ptep_get_and_clear() function for riscv/arm64
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <20250321130635.227011-7-alexghiti@rivosinc.com>

After some adjustments, both architectures have the same implementation
so move it to the generic code.

Note that get_clear_contig() function is duplicated in the generic and
the arm64 code because it is still used by some arm64 functions that
will, in the next commits, be moved to the generic code. Once all have
been moved, the arm64 version will be removed.

Signed-off-by: Alexandre Ghiti <alexghiti at rivosinc.com>
---
 arch/arm64/include/asm/hugetlb.h |  3 --
 arch/arm64/mm/hugetlbpage.c      | 10 -------
 arch/riscv/include/asm/hugetlb.h |  5 ----
 arch/riscv/mm/hugetlbpage.c      | 15 ----------
 include/linux/hugetlb_contpte.h  |  5 ++++
 mm/hugetlb_contpte.c             | 51 ++++++++++++++++++++++++++++++++
 6 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index ed75631ad63c..9b1c25775bea 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -39,9 +39,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
 extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 				      unsigned long addr, pte_t *ptep,
 				      pte_t pte, int dirty);
-#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
-extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-				     pte_t *ptep, unsigned long sz);
 #define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
 extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
 				    unsigned long addr, pte_t *ptep);
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 99728b02a3ca..62a66ce2b2fe 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -260,16 +260,6 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
 	return entry;
 }
 
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep, unsigned long sz)
-{
-	int ncontig;
-	size_t pgsize;
-
-	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
-	return get_clear_contig(mm, addr, ptep, pgsize, ncontig);
-}
-
 /*
  * huge_ptep_set_access_flags will update access flags (dirty, accesssed)
  * and write permission.
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 467bc30c2153..0fbb6b19df79 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -20,11 +20,6 @@ bool arch_hugetlb_migration_supported(struct hstate *h);
 #endif
 
 #ifdef CONFIG_RISCV_ISA_SVNAPOT
-#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
-			      unsigned long addr, pte_t *ptep,
-			      unsigned long sz);
-
 #define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 			    unsigned long addr, pte_t *ptep);
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index fe82284c3dc4..87168123d4a2 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -203,21 +203,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 	return true;
 }
 
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
-			      unsigned long addr,
-			      pte_t *ptep, unsigned long sz)
-{
-	pte_t orig_pte = ptep_get(ptep);
-	int pte_num;
-
-	if (!pte_napot(orig_pte))
-		return ptep_get_and_clear(mm, addr, ptep);
-
-	pte_num = arch_contpte_get_num_contig(ptep, sz, NULL);
-
-	return get_clear_contig(mm, addr, ptep, pte_num);
-}
-
 void huge_ptep_set_wrprotect(struct mm_struct *mm,
 			     unsigned long addr,
 			     pte_t *ptep)
diff --git a/include/linux/hugetlb_contpte.h b/include/linux/hugetlb_contpte.h
index e6aa9befa78c..1c8f46ff95ea 100644
--- a/include/linux/hugetlb_contpte.h
+++ b/include/linux/hugetlb_contpte.h
@@ -18,4 +18,9 @@ extern void set_huge_pte_at(struct mm_struct *mm,
 extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 			   pte_t *ptep, unsigned long sz);
 
+#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
+extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+				     unsigned long addr, pte_t *ptep,
+				     unsigned long sz);
+
 #endif /* _LINUX_HUGETLB_CONTPTE_H */
diff --git a/mm/hugetlb_contpte.c b/mm/hugetlb_contpte.c
index e881b302dd63..82f49eb79ffb 100644
--- a/mm/hugetlb_contpte.c
+++ b/mm/hugetlb_contpte.c
@@ -98,3 +98,54 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
 	for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
 		__pte_clear(mm, addr, ptep);
 }
+
+/*
+ * ARM: Changing some bits of contiguous entries requires us to follow a
+ * Break-Before-Make approach, breaking the whole contiguous set
+ * before we can change any entries. See ARM DDI 0487A.k_iss10775,
+ * "Misprogramming of the Contiguous bit", page D4-1762.
+ *
+ * RISCV: When dealing with NAPOT mappings, the privileged specification
+ * indicates that "if an update needs to be made, the OS generally should first
+ * mark all of the PTEs invalid, then issue SFENCE.VMA instruction(s) covering
+ * all 4 KiB regions within the range, [...] then update the PTE(s), as
+ * described in Section 4.2.1.". That's the equivalent of the Break-Before-Make
+ * approach used by arm64.
+ *
+ * This helper performs the break step.
+ */
+static pte_t get_clear_contig(struct mm_struct *mm,
+			     unsigned long addr,
+			     pte_t *ptep,
+			     unsigned long pgsize,
+			     unsigned long ncontig)
+{
+	pte_t pte, tmp_pte;
+	bool present;
+
+	pte = __ptep_get_and_clear(mm, addr, ptep);
+	present = pte_present(pte);
+	while (--ncontig) {
+		ptep++;
+		addr += pgsize;
+		tmp_pte = __ptep_get_and_clear(mm, addr, ptep);
+		if (present) {
+			if (pte_dirty(tmp_pte))
+				pte = pte_mkdirty(pte);
+			if (pte_young(tmp_pte))
+				pte = pte_mkyoung(pte);
+		}
+	}
+	return pte;
+}
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+			      unsigned long addr, pte_t *ptep, unsigned long sz)
+{
+	int ncontig;
+	size_t pgsize;
+
+	ncontig = arch_contpte_get_num_contig(ptep, sz, &pgsize);
+
+	return get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+}
-- 
2.39.2



From david at redhat.com  Fri Mar 21 06:17:12 2025
From: david at redhat.com (David Hildenbrand)
Date: Fri, 21 Mar 2025 14:17:12 +0100
Subject: [PATCH v3 3/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <Z91j_UwNhi2DQB3N@krava>
References: <20250321113713.204682-1-david@redhat.com>
 <20250321113713.204682-4-david@redhat.com> <Z91j_UwNhi2DQB3N@krava>
Message-ID: <69256f08-1d1c-45ac-945a-495ef4ffc558@redhat.com>

On 21.03.25 14:05, Jiri Olsa wrote:
> On Fri, Mar 21, 2025 at 12:37:13PM +0100, David Hildenbrand wrote:
> 
> SNIP
> 
>> +static int __uprobe_write_opcode(struct vm_area_struct *vma,
>> +		struct folio_walk *fw, struct folio *folio,
>> +		unsigned long opcode_vaddr, uprobe_opcode_t opcode)
>> +{
>> +	const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
>> +	const bool is_register = !!is_swbp_insn(&opcode);
>> +	bool pmd_mappable;
>> +
>> +	/* For now, we'll only handle PTE-mapped folios. */
>> +	if (fw->level != FW_LEVEL_PTE)
>> +		return -EFAULT;
>> +
>> +	/*
>> +	 * See can_follow_write_pte(): we'd actually prefer a writable PTE here,
>> +	 * but the VMA might not be writable.
>> +	 */
>> +	if (!pte_write(fw->pte)) {
>> +		if (!PageAnonExclusive(fw->page))
>> +			return -EFAULT;
>> +		if (unlikely(userfaultfd_pte_wp(vma, fw->pte)))
>> +			return -EFAULT;
>> +		/* SOFTDIRTY is handled via pte_mkdirty() below. */
>> +	}
>> +
>> +	/*
>> +	 * We'll temporarily unmap the page and flush the TLB, such that we can
>> +	 * modify the page atomically.
>> +	 */
>> +	flush_cache_page(vma, vaddr, pte_pfn(fw->pte));
>> +	fw->pte = ptep_clear_flush(vma, vaddr, fw->ptep);
>> +	copy_to_page(fw->page, opcode_vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
>> +
>> +	/*
>> +	 * When unregistering, we may only zap a PTE if uffd is disabled and
>> +	 * there are no unexpected folio references ...
>> +	 */
>> +	if (is_register || userfaultfd_missing(vma) ||
>> +	    (folio_ref_count(folio) != folio_mapcount(folio) + 1 +
>> +	     folio_test_swapcache(folio) * folio_nr_pages(folio)))
>> +		goto remap;
>> +
>> +	/*
>> +	 * ... and the mapped page is identical to the original page that
>> +	 * would get faulted in on next access.
>> +	 */
>> +	if (!orig_page_is_identical(vma, vaddr, fw->page, &pmd_mappable))
>> +		goto remap;
>> +
>> +	dec_mm_counter(vma->vm_mm, MM_ANONPAGES);
>> +	folio_remove_rmap_pte(folio, fw->page, vma);
>> +	if (!folio_mapped(folio) && folio_test_swapcache(folio) &&
>> +	     folio_trylock(folio)) {
>> +		folio_free_swap(folio);
>> +		folio_unlock(folio);
>> +	}
>> +	folio_put(folio);
> 
> hi,
> it's probably ok and I'm missing something, but why do we call folio_put
> in here, I'd think it's done by folio_put call in uprobe_write_opcode

Hi!

We're zapping a page table mapping mapping (folio_remove_rmap_pte()), so 
we have to drop that reference.

That's the folio_put(old_folio) in the old __replace_page().

Thanks!

-- 
Cheers,

David / dhildenb



From jgg at nvidia.com  Fri Mar 21 06:34:47 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Fri, 21 Mar 2025 10:34:47 -0300
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation
 helpers
In-Reply-To: <20250320015551.2157511-8-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-8-changyuanl@google.com>
Message-ID: <20250321133447.GA251739@nvidia.com>

On Wed, Mar 19, 2025 at 06:55:42PM -0700, Changyuan Lyu wrote:
> From: Alexander Graf <graf at amazon.com>
> 
> Add the core infrastructure to generate Kexec HandOver metadata. Kexec
> HandOver is a mechanism that allows Linux to preserve state - arbitrary
> properties as well as memory locations - across kexec.
> 
> It does so using 2 concepts:
> 
>   1) State Tree - Every KHO kexec carries a state tree that describes the
>      state of the system. The state tree is represented as hash-tables.
>      Device drivers can add/remove their data into/from the state tree at
>      system runtime. On kexec, the tree is converted to FDT (flattened
>      device tree).

Why are we changing this? I much prefered the idea of having recursive
FDTs than this notion copying eveything into tables then out into FDT?
Now that we have the preserved pages mechanism there is a pretty
direct path to doing recursive FDT.

I feel like this patch is premature, it should come later in the
project along with a stronger justification for this approach.

IHMO keep things simple for this series, just the very basics.

> +int register_kho_notifier(struct notifier_block *nb)
> +{
> +	return blocking_notifier_chain_register(&kho_out.chain_head, nb);
> +}
> +EXPORT_SYMBOL_GPL(register_kho_notifier);

And another different set of notifiers? :(

> +static int kho_finalize(void)
> +{
> +	int err = 0;
> +	void *fdt;
> +
> +	fdt = kvmalloc(kho_out.fdt_max, GFP_KERNEL);
> +	if (!fdt)
> +		return -ENOMEM;

We go to all the trouble of keeping track of stuff in dynamic hashes
but still can't automatically size the fdt and keep the dumb uapi to
have the user say? :( :(

Jason


From oleg at redhat.com  Fri Mar 21 06:34:01 2025
From: oleg at redhat.com (Oleg Nesterov)
Date: Fri, 21 Mar 2025 14:34:01 +0100
Subject: [PATCH v3 0/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250321113713.204682-1-david@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
Message-ID: <20250321133401.GB4776@redhat.com>

On 03/21, David Hildenbrand wrote:
>
> Based on mm/unstable.

which has another fix from David in __replace_page() plus the fix from
Tong in uprobe_write_opcode().

So, Andrew, could you take this series as well? Peter, will you agree?

> Currently, uprobe_write_opcode() implements COW-breaking manually, which is
> really far from ideal.

It was never ideal, but today it is simply horrible ;)
Thanks again for your work.

Oleg.



From corbet at lwn.net  Fri Mar 21 06:46:51 2025
From: corbet at lwn.net (Jonathan Corbet)
Date: Fri, 21 Mar 2025 07:46:51 -0600
Subject: [PATCH v5 16/16] Documentation: add documentation for KHO
In-Reply-To: <20250321063356.381646-1-changyuanl@google.com>
References: <87wmcj69sg.fsf@trenco.lwn.net>
 <20250321063356.381646-1-changyuanl@google.com>
Message-ID: <87frj6o5ro.fsf@trenco.lwn.net>

Changyuan Lyu <changyuanl at google.com> writes:

> However, I think concepts.rst and fdt.rst are not not end-user oriented,
> but for kernel developers of other subsystems to use KHO API (I also plan
> to include the kernel-doc generated from kernel/kexec_handover.c and
> include/linux/kexec_handover.h here in the next version).
> Should Documentation/core-api be a better choice?

Yes, I think it would be.

Thanks,

jon


From jgg at nvidia.com  Fri Mar 21 06:46:29 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Fri, 21 Mar 2025 10:46:29 -0300
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <20250320015551.2157511-10-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-10-changyuanl@google.com>
Message-ID: <20250321134629.GA252045@nvidia.com>

On Wed, Mar 19, 2025 at 06:55:44PM -0700, Changyuan Lyu wrote:
> +/**
> + * kho_preserve_folio - preserve a folio across KHO.
> + * @folio: folio to preserve
> + *
> + * Records that the entire folio is preserved across KHO. The order
> + * will be preserved as well.
> + *
> + * Return: 0 on success, error code on failure
> + */
> +int kho_preserve_folio(struct folio *folio)
> +{
> +	unsigned long pfn = folio_pfn(folio);
> +	unsigned int order = folio_order(folio);
> +	int err;
> +
> +	if (!kho_enable)
> +		return -EOPNOTSUPP;
> +
> +	down_read(&kho_out.tree_lock);
> +	if (kho_out.fdt) {

What is the lock and fdt test for?

I'm getting the feeling that probably kho_preserve_folio() and the
like should accept some kind of 
'struct kho_serialization *' and then we don't need this to prove we
are within a valid serialization window. It could pass the pointer
through the notifiers

The global variables in this series are sort of ugly..

We want this to be fast, so try hard to avoid a lock..

> +void *kho_restore_phys(phys_addr_t phys, size_t size)
> +{
> +	unsigned long start_pfn, end_pfn, pfn;
> +	void *va = __va(phys);
> +
> +	start_pfn = PFN_DOWN(phys);
> +	end_pfn = PFN_UP(phys + size);
> +
> +	for (pfn = start_pfn; pfn < end_pfn; pfn++) {
> +		struct page *page = pfn_to_online_page(pfn);
> +
> +		if (!page)
> +			return NULL;
> +		kho_restore_page(page);
> +	}
> +
> +	return va;
> +}
> +EXPORT_SYMBOL_GPL(kho_restore_phys);

What do you imagine this is used for? I'm not sure what value there is
in returning a void *? How does the caller "free" this?


> +#define KHOSER_PTR(type)          \
> +	union {                   \
> +		phys_addr_t phys; \
> +		type ptr;         \
> +	}
> +#define KHOSER_STORE_PTR(dest, val)                 \
> +	({                                          \
> +		(dest).phys = virt_to_phys(val);    \
> +		typecheck(typeof((dest).ptr), val); \
> +	})
> +#define KHOSER_LOAD_PTR(src) \
> +	((src).phys ? (typeof((src).ptr))(phys_to_virt((src).phys)) : NULL)

I had imagined these macros would be in a header and usably by drivers
that also want to use structs to carry information.

> +static void deserialize_bitmap(unsigned int order,
> +			       struct khoser_mem_bitmap_ptr *elm)
> +{
> +	struct kho_mem_phys_bits *bitmap = KHOSER_LOAD_PTR(elm->bitmap);
> +	unsigned long bit;
> +
> +	for_each_set_bit(bit, bitmap->preserve, PRESERVE_BITS) {
> +		int sz = 1 << (order + PAGE_SHIFT);
> +		phys_addr_t phys =
> +			elm->phys_start + (bit << (order + PAGE_SHIFT));
> +		struct page *page = phys_to_page(phys);
> +
> +		memblock_reserve(phys, sz);
> +		memblock_reserved_mark_noinit(phys, sz);

Mike asked about this earlier, is it work combining runs of set bits
to increase sz? Or is this sort of temporary pending something better
that doesn't rely on memblock_reserve?

> +		page->private = order;

Can't just set the page order directly? Why use private?

> @@ -829,6 +1305,10 @@ static __init int kho_init(void)
>  
>  	kho_out.root.name = "";

?

>  	err = kho_add_string_prop(&kho_out.root, "compatible", "kho-v1");
> +	err |= kho_add_prop(&kho_out.preserved_memory, "metadata",
> +			    &kho_out.first_chunk_phys, sizeof(phys_addr_t));

metedata doesn't fee like a great a better name..

Please also document all the FDT schema thoroughly!

There should be yaml files just like in the normal DT case defining
all of this. This level of documentation and stability was one of the
selling reasons why FDT is being used here!

Jason


From jgg at nvidia.com  Fri Mar 21 06:48:54 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Fri, 21 Mar 2025 10:48:54 -0300
Subject: [PATCH v5 10/16] kexec: add KHO support to kexec file loads
In-Reply-To: <20250320015551.2157511-11-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-11-changyuanl@google.com>
Message-ID: <20250321134854.GB252045@nvidia.com>

On Wed, Mar 19, 2025 at 06:55:45PM -0700, Changyuan Lyu wrote:
> +int kho_copy_fdt(struct kimage *image)
> +{
> +	int err = 0;
> +	void *fdt;
> +
> +	if (!kho_enable || !image->file_mode)
> +		return 0;
> +
> +	if (!kho_out.fdt) {
> +		err = kho_finalize();
> +		kho_out_update_debugfs_fdt();
> +		if (err)
> +			return err;
> +	}
> +
> +	fdt = kimage_map_segment(image, image->kho.fdt->mem,
> +				 PAGE_ALIGN(kho_out.fdt_max));
> +	if (!fdt) {
> +		pr_err("failed to vmap fdt ksegment in kimage\n");
> +		return -ENOMEM;
> +	}

I continue to think this copying is kind of pointless.

I liked the point where we could get the FDT blob into userspace and
validate it ie through debugfs.

But as a way to actually do the kexec, I think you should not copy but
preserve the memory holding FDT using the new preservation mechanism
and simply put a 16 byte size/length on the image to refer to it.

This would clean up the special hard coded memblock reserve to
preserve the FDT memory too as normal preservation would take care fo
it.

Now that this is all in the kernel it seems like there is no reason to
do the copying version any more.

Jason


From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:53 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:53 +0200
Subject: [PATCH v3 09/10] phy: phy-snps-eusb2: add support for exynos2200
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-10-ivo.ivanov.ivanov1@gmail.com>

The Exynos2200 SoC reuses the Synopsis eUSB2 PHY IP, alongside an
external repeater, for USB 2.0. Add support for it to the existing
driver, while keeping in mind that it requires enabled more than the
reference clock.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 drivers/phy/Kconfig          |   2 +-
 drivers/phy/phy-snps-eusb2.c | 162 ++++++++++++++++++++++++++++++++++-
 2 files changed, 159 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 11c166204..58c911e1b 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -45,7 +45,7 @@ config PHY_PISTACHIO_USB
 
 config PHY_SNPS_EUSB2
 	tristate "SNPS eUSB2 PHY Driver"
-	depends on OF && (ARCH_QCOM || COMPILE_TEST)
+	depends on OF && (ARCH_EXYNOS || ARCH_QCOM || COMPILE_TEST)
 	select GENERIC_PHY
 	help
 	  Enable support for the USB high-speed SNPS eUSB2 phy on select
diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index 4ca11860a..951f58119 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -13,6 +13,39 @@
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 
+#define EXYNOS_USB_PHY_HS_PHY_CTRL_RST	(0x0)
+#define USB_PHY_RST_MASK		GENMASK(1, 0)
+#define UTMI_PORT_RST_MASK		GENMASK(5, 4)
+
+#define EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON	(0x4)
+#define RPTR_MODE			BIT(10)
+#define FSEL_20_MHZ_VAL			(0x1)
+#define FSEL_24_MHZ_VAL			(0x2)
+#define FSEL_26_MHZ_VAL			(0x3)
+#define FSEL_48_MHZ_VAL			(0x2)
+
+#define EXYNOS_USB_PHY_CFG_PLLCFG0	(0x8)
+#define PHY_CFG_PLL_FB_DIV_19_8_MASK	GENMASK(19, 8)
+#define DIV_19_8_19_2_MHZ_VAL		(0x170)
+#define DIV_19_8_20_MHZ_VAL		(0x160)
+#define DIV_19_8_24_MHZ_VAL		(0x120)
+#define DIV_19_8_26_MHZ_VAL		(0x107)
+#define DIV_19_8_48_MHZ_VAL		(0x120)
+
+#define EXYNOS_USB_PHY_CFG_PLLCFG1	(0xc)
+#define EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK	GENMASK(11, 8)
+#define EXYNOS_DIV_11_8_19_2_MHZ_VAL	(0x0)
+#define EXYNOS_DIV_11_8_20_MHZ_VAL	(0x0)
+#define EXYNOS_DIV_11_8_24_MHZ_VAL	(0x0)
+#define EXYNOS_DIV_11_8_26_MHZ_VAL	(0x0)
+#define EXYNOS_DIV_11_8_48_MHZ_VAL	(0x1)
+
+#define EXYNOS_PHY_CFG_TX		(0x14)
+#define EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK	GENMASK(2, 1)
+
+#define EXYNOS_USB_PHY_UTMI_TESTSE	(0x20)
+#define TEST_IDDQ			BIT(6)
+
 #define QCOM_USB_PHY_UTMI_CTRL0		(0x3c)
 #define SLEEPM				BIT(0)
 #define OPMODE_MASK			GENMASK(4, 3)
@@ -123,6 +156,8 @@ static const char * const eusb2_hsphy_vreg_names[] = {
 
 struct snps_eusb2_phy_drvdata {
 	int (*phy_init)(struct phy *p);
+	const char * const *clk_names;
+	int num_clks;
 };
 
 struct snps_eusb2_hsphy {
@@ -130,6 +165,7 @@ struct snps_eusb2_hsphy {
 	void __iomem *base;
 
 	struct clk *ref_clk;
+	struct clk_bulk_data *clks;
 	struct reset_control *phy_reset;
 
 	struct regulator_bulk_data vregs[EUSB2_NUM_VREGS];
@@ -199,6 +235,46 @@ struct snps_eusb2_ref_clk {
 	u32 div_11_8_val;
 };
 
+static const struct snps_eusb2_ref_clk exynos_eusb2_ref_clk[] = {
+	{ 19200000, FSEL_19_2_MHZ_VAL, DIV_19_8_19_2_MHZ_VAL, EXYNOS_DIV_11_8_19_2_MHZ_VAL },
+	{ 20000000, FSEL_20_MHZ_VAL, DIV_19_8_20_MHZ_VAL, EXYNOS_DIV_11_8_20_MHZ_VAL },
+	{ 24000000, FSEL_24_MHZ_VAL, DIV_19_8_24_MHZ_VAL, EXYNOS_DIV_11_8_24_MHZ_VAL },
+	{ 26000000, FSEL_26_MHZ_VAL, DIV_19_8_26_MHZ_VAL, EXYNOS_DIV_11_8_26_MHZ_VAL },
+	{ 48000000, FSEL_48_MHZ_VAL, DIV_19_8_48_MHZ_VAL, EXYNOS_DIV_11_8_48_MHZ_VAL },
+};
+
+static int exynos_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
+{
+	const struct snps_eusb2_ref_clk *config = NULL;
+	unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk);
+
+	for (int i = 0; i < ARRAY_SIZE(exynos_eusb2_ref_clk); i++) {
+		if (exynos_eusb2_ref_clk[i].freq == ref_clk_freq) {
+			config = &exynos_eusb2_ref_clk[i];
+			break;
+		}
+	}
+
+	if (!config) {
+		dev_err(&phy->phy->dev, "unsupported ref_clk_freq:%lu\n", ref_clk_freq);
+		return -EINVAL;
+	}
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
+				    FSEL_MASK,
+				    FIELD_PREP(FSEL_MASK, config->fsel_val));
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_CFG_PLLCFG0,
+				    PHY_CFG_PLL_FB_DIV_19_8_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_FB_DIV_19_8_MASK,
+					       config->div_7_0_val));
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_CFG_PLLCFG1,
+				    EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK,
+				    config->div_11_8_val);
+	return 0;
+}
+
 static const struct snps_eusb2_ref_clk qcom_eusb2_ref_clk[] = {
 	{ 19200000, FSEL_19_2_MHZ_VAL, DIV_7_0_19_2_MHZ_VAL, DIV_11_8_19_2_MHZ_VAL },
 	{ 38400000, FSEL_38_4_MHZ_VAL, DIV_7_0_38_4_MHZ_VAL, DIV_11_8_38_4_MHZ_VAL },
@@ -239,6 +315,55 @@ static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
 	return 0;
 }
 
+static int exynos_snps_eusb2_hsphy_init(struct phy *p)
+{
+	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
+	int ret;
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
+				    USB_PHY_RST_MASK | UTMI_PORT_RST_MASK,
+				    USB_PHY_RST_MASK | UTMI_PORT_RST_MASK);
+	fsleep(50); /* required after holding phy in reset */
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
+				    RPTR_MODE, RPTR_MODE);
+
+	/* update ref_clk related registers */
+	ret = exynos_eusb2_ref_clk_init(phy);
+	if (ret)
+		return ret;
+
+	/* default parameter: tx fsls-vref */
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_PHY_CFG_TX,
+				    EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK,
+				    FIELD_PREP(EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK, 0x0));
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_UTMI_TESTSE,
+				    TEST_IDDQ, 0);
+	fsleep(10); /* required after releasing test_iddq */
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
+				    USB_PHY_RST_MASK, 0);
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
+				    PHY_ENABLE, PHY_ENABLE);
+
+	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
+				    UTMI_PORT_RST_MASK, 0);
+
+	return 0;
+}
+
+static const char * const exynos_eusb2_hsphy_clock_names[] = {
+	"ref", "bus", "ctrl",
+};
+
+static const struct snps_eusb2_phy_drvdata exynos2200_snps_eusb2_phy = {
+	.phy_init	= exynos_snps_eusb2_hsphy_init,
+	.clk_names	= exynos_eusb2_hsphy_clock_names,
+	.num_clks	= ARRAY_SIZE(exynos_eusb2_hsphy_clock_names),
+};
+
 static int qcom_snps_eusb2_hsphy_init(struct phy *p)
 {
 	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
@@ -315,8 +440,14 @@ static int qcom_snps_eusb2_hsphy_init(struct phy *p)
 	return 0;
 }
 
+static const char * const qcom_eusb2_hsphy_clock_names[] = {
+	"ref",
+};
+
 static const struct snps_eusb2_phy_drvdata sm8550_snps_eusb2_phy = {
 	.phy_init	= qcom_snps_eusb2_hsphy_init,
+	.clk_names      = qcom_eusb2_hsphy_clock_names,
+	.num_clks       = ARRAY_SIZE(qcom_eusb2_hsphy_clock_names),
 };
 
 static int snps_eusb2_hsphy_init(struct phy *p)
@@ -334,7 +465,7 @@ static int snps_eusb2_hsphy_init(struct phy *p)
 		goto disable_vreg;
 	}
 
-	ret = clk_prepare_enable(phy->ref_clk);
+	ret = clk_bulk_prepare_enable(phy->data->num_clks, phy->clks);
 	if (ret) {
 		dev_err(&p->dev, "failed to enable ref clock, %d\n", ret);
 		goto disable_vreg;
@@ -361,7 +492,7 @@ static int snps_eusb2_hsphy_init(struct phy *p)
 	return 0;
 
 disable_ref_clk:
-	clk_disable_unprepare(phy->ref_clk);
+	clk_bulk_disable_unprepare(phy->data->num_clks, phy->clks);
 
 disable_vreg:
 	regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs);
@@ -417,8 +548,28 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 	if (IS_ERR(phy->phy_reset))
 		return PTR_ERR(phy->phy_reset);
 
-	phy->ref_clk = devm_clk_get(dev, "ref");
-	if (IS_ERR(phy->ref_clk))
+	phy->clks = devm_kcalloc(dev, phy->data->num_clks, sizeof(*phy->clks),
+				 GFP_KERNEL);
+	if (!phy->clks)
+		return -ENOMEM;
+
+	for (int i = 0; i < phy->data->num_clks; ++i)
+		phy->clks[i].id = phy->data->clk_names[i];
+
+	ret = devm_clk_bulk_get(dev, phy->data->num_clks, phy->clks);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to get phy clock(s)\n");
+
+	phy->ref_clk = NULL;
+	for (int i = 0; i < phy->data->num_clks; ++i) {
+		if (!strcmp(phy->clks[i].id, "ref")) {
+			phy->ref_clk = phy->clks[i].clk;
+			break;
+		}
+	}
+
+	if (IS_ERR_OR_NULL(phy->ref_clk))
 		return dev_err_probe(dev, PTR_ERR(phy->ref_clk),
 				     "failed to get ref clk\n");
 
@@ -458,6 +609,9 @@ static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
 	{
 		.compatible = "qcom,sm8550-snps-eusb2-phy",
 		.data = &sm8550_snps_eusb2_phy,
+	}, {
+		.compatible = "samsung,exynos2200-snps-eusb2-phy",
+		.data = &exynos2200_snps_eusb2_phy,
 	}, { },
 };
 MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:54 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:54 +0200
Subject: [PATCH v3 10/10] phy: exynos5-usbdrd: support Exynos USBDRD 3.2 4nm controller
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-11-ivo.ivanov.ivanov1@gmail.com>

Add support for the Exynos USB 3.2 DRD 4nm controller. It's used in
recent 4nm SoCs like Exynos2200 and Exynos2400.

This device consists of 3 underlying and independent phys: SEC link
control phy, Synopsys eUSB 2.0 and Synopsys USBDP/SS combophy. Unlike
older device designs, where the internal phy blocks were all IP of
Samsung, Synopsys phys are present. This means that the link controller
is now mapped differently to account for missing bits and registers.
The Synopsys phys also have separate register bases.

As there are non-SEC PHYs present now, it doesn't make much sense to
implement them in this driver. They are expected to be configured
by external drivers, so pass phandles to them. USBDRD3.2 link controller
set up is still required beforehand.

This commit adds the necessary changes for USB HS to work. USB SS and
DisplayPort are out of scope in this commit and will be introduced
in the future.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 drivers/phy/samsung/phy-exynos5-usbdrd.c    | 227 ++++++++++++++++++--
 include/linux/soc/samsung/exynos-regs-pmu.h |   3 +
 2 files changed, 215 insertions(+), 15 deletions(-)

diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index c421b495e..f85b22a7a 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -34,6 +34,21 @@
 #define EXYNOS5_FSEL_26MHZ		0x6
 #define EXYNOS5_FSEL_50MHZ		0x7
 
+/* USB 3.2 DRD 4nm PHY link controller registers */
+#define EXYNOS2200_DRD_CLKRST			0x0c
+#define EXYNOS2200_CLKRST_LINK_PCLK_SEL		BIT(1)
+
+#define EXYNOS2200_DRD_UTMI			0x10
+#define EXYNOS2200_UTMI_FORCE_VBUSVALID		BIT(1)
+#define EXYNOS2200_UTMI_FORCE_BVALID		BIT(0)
+
+#define EXYNOS2200_DRD_HSP_MISC			0x114
+#define HSP_MISC_SET_REQ_IN2			BIT(4)
+#define HSP_MISC_RES_TUNE			GENMASK(1, 0)
+#define RES_TUNE_PHY1_PHY2			0x1
+#define RES_TUNE_PHY1				0x2
+#define RES_TUNE_PHY2				0x3
+
 /* Exynos5: USB 3.0 DRD PHY registers */
 #define EXYNOS5_DRD_LINKSYSTEM			0x04
 #define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)
@@ -383,6 +398,7 @@ struct exynos5_usbdrd_phy_drvdata {
  * @clks: clocks for register access
  * @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required)
  * @drv_data: pointer to SoC level driver data structure
+ * @hs_phy: pointer to non-Samsung IP high-speed phy controller
  * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
  *	    instances each with its 'phy' and 'phy_cfg'.
  * @extrefclk: frequency select settings when using 'separate
@@ -397,6 +413,7 @@ struct exynos5_usbdrd_phy {
 	struct clk_bulk_data *clks;
 	struct clk_bulk_data *core_clks;
 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
+	struct phy *hs_phy;
 	struct phy_usb_instance {
 		struct phy *phy;
 		u32 index;
@@ -1049,6 +1066,149 @@ static const struct phy_ops exynos5_usbdrd_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static void exynos2200_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+	/* Configure non-Samsung IP PHY, responsible for UTMI */
+	phy_init(phy_drd->hs_phy);
+}
+
+static void exynos2200_usbdrd_link_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+	void __iomem *regs_base = phy_drd->reg_phy;
+	u32 reg;
+
+	/*
+	 * Disable HWACG (hardware auto clock gating control). This will force
+	 * QACTIVE signal in Q-Channel interface to HIGH level, to make sure
+	 * the PHY clock is not gated by the hardware.
+	 */
+	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);
+	reg |= LINKCTRL_FORCE_QACT;
+	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
+
+	/* De-assert link reset */
+	reg = readl(regs_base + EXYNOS2200_DRD_CLKRST);
+	reg &= ~CLKRST_LINK_SW_RST;
+	writel(reg, regs_base + EXYNOS2200_DRD_CLKRST);
+
+	/* Set link VBUS Valid */
+	reg = readl(regs_base + EXYNOS2200_DRD_UTMI);
+	reg |= EXYNOS2200_UTMI_FORCE_BVALID | EXYNOS2200_UTMI_FORCE_VBUSVALID;
+	writel(reg, regs_base + EXYNOS2200_DRD_UTMI);
+}
+
+static void
+exynos2200_usbdrd_link_attach_detach_pipe3_phy(struct phy_usb_instance *inst)
+{
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+	void __iomem *regs_base = phy_drd->reg_phy;
+	u32 reg;
+
+	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);
+	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
+		/* force pipe3 signal for link */
+		reg &= ~LINKCTRL_FORCE_PHYSTATUS;
+		reg |= LINKCTRL_FORCE_PIPE_EN | LINKCTRL_FORCE_RXELECIDLE;
+	} else {
+		/* disable forcing pipe interface */
+		reg &= ~LINKCTRL_FORCE_PIPE_EN;
+	}
+	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
+
+	reg = readl(regs_base + EXYNOS2200_DRD_HSP_MISC);
+	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
+		/* calibrate only eUSB phy */
+		reg |= FIELD_PREP(HSP_MISC_RES_TUNE, RES_TUNE_PHY1);
+		reg |= HSP_MISC_SET_REQ_IN2;
+	} else {
+		/* calibrate for dual phy */
+		reg |= FIELD_PREP(HSP_MISC_RES_TUNE, RES_TUNE_PHY1_PHY2);
+		reg &= ~HSP_MISC_SET_REQ_IN2;
+	}
+	writel(reg, regs_base + EXYNOS2200_DRD_HSP_MISC);
+
+	reg = readl(regs_base + EXYNOS2200_DRD_CLKRST);
+	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
+		reg &= ~EXYNOS2200_CLKRST_LINK_PCLK_SEL;
+	else
+		reg |= EXYNOS2200_CLKRST_LINK_PCLK_SEL;
+
+	writel(reg, regs_base + EXYNOS2200_DRD_CLKRST);
+}
+
+static int exynos2200_usbdrd_phy_init(struct phy *phy)
+{
+	struct phy_usb_instance *inst = phy_get_drvdata(phy);
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+	int ret;
+
+	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
+		/* Power-on PHY ... */
+		ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,
+					    phy_drd->regulators);
+		if (ret) {
+			dev_err(phy_drd->dev,
+				"Failed to enable PHY regulator(s)\n");
+			return ret;
+		}
+	}
+	/*
+	 * ... and ungate power via PMU. Without this here, we get an SError
+	 * trying to access PMA registers
+	 */
+	exynos5_usbdrd_phy_isol(inst, false);
+
+	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
+	if (ret)
+		return ret;
+
+	/* Set up the link controller */
+	exynos2200_usbdrd_link_init(phy_drd);
+
+	/* UTMI or PIPE3 link preparation */
+	exynos2200_usbdrd_link_attach_detach_pipe3_phy(inst);
+
+	/* UTMI or PIPE3 specific init */
+	inst->phy_cfg->phy_init(phy_drd);
+
+	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
+
+	return 0;
+}
+
+static int exynos2200_usbdrd_phy_exit(struct phy *phy)
+{
+	struct phy_usb_instance *inst = phy_get_drvdata(phy);
+	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+	void __iomem *regs_base = phy_drd->reg_phy;
+	u32 reg;
+	int ret;
+
+	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
+	if (ret)
+		return ret;
+
+	reg = readl(regs_base + EXYNOS2200_DRD_UTMI);
+	reg &= ~(EXYNOS2200_UTMI_FORCE_BVALID | EXYNOS2200_UTMI_FORCE_VBUSVALID);
+	writel(reg, regs_base + EXYNOS2200_DRD_UTMI);
+
+	reg = readl(regs_base + EXYNOS2200_DRD_CLKRST);
+	reg |= CLKRST_LINK_SW_RST;
+	writel(reg, regs_base + EXYNOS2200_DRD_CLKRST);
+
+	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
+
+	exynos5_usbdrd_phy_isol(inst, true);
+	return regulator_bulk_disable(phy_drd->drv_data->n_regulators,
+				      phy_drd->regulators);
+}
+
+static const struct phy_ops exynos2200_usbdrd_phy_ops = {
+	.init		= exynos2200_usbdrd_phy_init,
+	.exit		= exynos2200_usbdrd_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
 static void
 exynos5_usbdrd_usb_v3p1_pipe_override(struct exynos5_usbdrd_phy *phy_drd)
 {
@@ -1350,27 +1510,37 @@ static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
 		return dev_err_probe(phy_drd->dev, ret,
 				     "failed to get phy core clock(s)\n");
 
-	ref_clk = NULL;
-	for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) {
-		if (!strcmp(phy_drd->core_clks[i].id, "ref")) {
-			ref_clk = phy_drd->core_clks[i].clk;
-			break;
+	if (phy_drd->drv_data->n_core_clks) {
+		ref_clk = NULL;
+		for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) {
+			if (!strcmp(phy_drd->core_clks[i].id, "ref")) {
+				ref_clk = phy_drd->core_clks[i].clk;
+				break;
+			}
 		}
+		if (!ref_clk)
+			return dev_err_probe(phy_drd->dev, -ENODEV,
+					     "failed to find phy reference clock\n");
+
+		ref_rate = clk_get_rate(ref_clk);
+		ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+		if (ret)
+			return dev_err_probe(phy_drd->dev, ret,
+					     "clock rate (%ld) not supported\n",
+					     ref_rate);
 	}
-	if (!ref_clk)
-		return dev_err_probe(phy_drd->dev, -ENODEV,
-				     "failed to find phy reference clock\n");
-
-	ref_rate = clk_get_rate(ref_clk);
-	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
-	if (ret)
-		return dev_err_probe(phy_drd->dev, ret,
-				     "clock rate (%ld) not supported\n",
-				     ref_rate);
 
 	return 0;
 }
 
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos2200[] = {
+	{
+		.id		= EXYNOS5_DRDPHY_UTMI,
+		.phy_isol	= exynos5_usbdrd_phy_isol,
+		.phy_init	= exynos2200_usbdrd_utmi_init,
+	},
+};
+
 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
@@ -1410,6 +1580,19 @@ static const char * const exynos5_regulator_names[] = {
 	"vbus", "vbus-boost",
 };
 
+static const struct exynos5_usbdrd_phy_drvdata exynos2200_usb32drd_phy = {
+	.phy_cfg		= phy_cfg_exynos2200,
+	.phy_ops		= &exynos2200_usbdrd_phy_ops,
+	.pmu_offset_usbdrd0_phy	= EXYNOS2200_PHY_CTRL_USB20,
+	.clk_names		= exynos5_clk_names,
+	.n_clks			= ARRAY_SIZE(exynos5_clk_names),
+	/* clocks and regulators are specific to the underlying PHY blocks */
+	.core_clk_names		= NULL,
+	.n_core_clks		= 0,
+	.regulator_names	= NULL,
+	.n_regulators		= 0,
+};
+
 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.phy_ops		= &exynos5_usbdrd_phy_ops,
@@ -1651,6 +1834,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
 	{
 		.compatible = "google,gs101-usb31drd-phy",
 		.data = &gs101_usbd31rd_phy
+	}, {
+		.compatible = "samsung,exynos2200-usb32drd-phy",
+		.data = &exynos2200_usb32drd_phy,
 	}, {
 		.compatible = "samsung,exynos5250-usbdrd-phy",
 		.data = &exynos5250_usbdrd_phy
@@ -1719,6 +1905,17 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 			return PTR_ERR(phy_drd->reg_phy);
 	}
 
+	/*
+	 * USB32DRD 4nm controller implements Synopsys eUSB2.0 PHY
+	 * and Synopsys SS/USBDP COMBOPHY, managed by external code.
+	 */
+	if (of_property_present(dev->of_node, "phy-names")) {
+		phy_drd->hs_phy = devm_of_phy_get(dev, dev->of_node, "hs");
+		if (IS_ERR(phy_drd->hs_phy))
+			return dev_err_probe(dev, PTR_ERR(phy_drd->hs_phy),
+					     "failed to get hs_phy\n");
+	}
+
 	ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
 	if (ret)
 		return ret;
diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h
index ce1a3790d..b77187ba5 100644
--- a/include/linux/soc/samsung/exynos-regs-pmu.h
+++ b/include/linux/soc/samsung/exynos-regs-pmu.h
@@ -185,6 +185,9 @@
 /* Only for S5Pv210 */
 #define S5PV210_EINT_WAKEUP_MASK	0xC004
 
+/* Only for Exynos2200 */
+#define EXYNOS2200_PHY_CTRL_USB20	0x72C
+
 /* Only for Exynos4210 */
 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR	0x1154
 #define S5P_CMU_RESET_LCD1_LOWPWR	0x1174
-- 
2.43.0



From mike.leach at linaro.org  Fri Mar 21 07:00:10 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 21 Mar 2025 14:00:10 +0000
Subject: [PATCH v3 0/7] Provides support for Trigger Generation Unit
In-Reply-To: <28001d0d-38cc-4507-91c5-1791c74d11ee@quicinc.com>
References: <20250227092640.2666894-1-quic_songchai@quicinc.com>
 <CAJ9a7ViFu6tP7wac-6NPOBOCHw2iA+gs6D=D4um-T07Syu-8CA@mail.gmail.com> <28001d0d-38cc-4507-91c5-1791c74d11ee@quicinc.com>
Message-ID: <CAJ9a7VjwKUgS-9gbpi--9+d6uvE4O8w+U4K+4t31Zo8BhoBSKg@mail.gmail.com>

Hi,


On Fri, 21 Mar 2025 at 03:26, songchai <quic_songchai at quicinc.com> wrote:
>
>
> On 3/7/2025 12:57 AM, Mike Leach wrote:
> > Hi,
> >
> > On Thu, 27 Feb 2025 at 09:27, songchai <quic_songchai at quicinc.com> wrote:
> >> Provide support for the TGU (Trigger Generation Unit), which can be
> >> utilized to sense a plurality of signals and create a trigger into
> >> the CTI or generate interrupts to processors once the input signal
> >> meets the conditions. We can treat the TGU?s workflow as a flowsheet,
> >> it has some ?steps? regions for customization. In each step region,
> >> we can set the signals that we want with priority in priority_group, set
> >> the conditions in each step via condition_decode, and set the resultant
> >> action by condition_select. Meanwhile, some TGUs (not all) also provide
> >> timer/counter functionality. Based on the characteristics described
> >> above, we consider the TGU as a helper in the CoreSight subsystem.
> >> Its master device is the TPDM, which can transmit signals from other
> >> subsystems, and we reuse the existing ports mechanism to link the TPDM to
> >> the connected TGU.
> >>
> > I do not believe that his component is part of the Coresight subsystem.
> >
> > 1) It inputs multiple signals from the SoC to process and create an
> > trigger event - however, it can do this irrespective of CoreSight
> > trace being operational, especially where generating interrupts for
> > processors, or triggers for other non-coresight components. It would
> > appear that the TPDM can send output to more than just the TDPA which
> > generates coresight trace packets - a previously undisclosed feature.
>
> TGU is a part the QPMDA(Qualcomm Performance Monitoring and
>
> Diagnostics Architecture ) library, and the signals it perceives are
> from TPDM and connected
>
> through hardware. So it  depends on the coresight-tpdm, and will not
> work if the coresight
>
> tpdm is not operational.
>

As I understand it from reading many of the patches for this and other
of the components,
the QPMDA is a proprietary network of monitoring components across your SoCs,
that can have an endpoint that generates CoreSight trace (from the TPDA).

The nature of this network has not been specified - but it does seem
that the TDPM can output to more than one device - perhaps some sort
of internal bus runs between all the QPMDA devices.

Is it possible that the TDPM can be programmed to output to the TGU,
without trace being generated from the TPDA?

If you enable just the TPDM and TGU, can you program the TGU to output
triggers to CPU and other none-coresight devices, as implied in the
binding descriptions?


> >
> > 2) The ports mechanism is a generic device tree mechanism, not
> > something unique to the Coresight subsystem.
>
> Sure, Mike. As i mentioned above, the signals reach the TGU through
> hardware.So the port
>
> mechanism here is not for the data transmission, but to confirm the
> relationship of the TGU
>
> as a TPDM helper.
>
> >
> > 3) The CTI trigger connection will be defined in devicetree under the
> > CTI component, as this is the interface between this component and
> > coresight.
>
> The TGU is utilized to sense a plurality of signals and create a trigger
> into the CTI.
>
> It should be a trigger in for the targeting CTI. Could we configure the
> targeting CTI's trigger_in
>
> and trigger_out instead of configuring in the devicetree?
>

You would need to make additional device tree entries in the relevant
CTI for the input trigger from the TGU for the CTI driver to correctly
display the source of the trigger.

> >
> > As such this seems more like a general performance and debug
> > component, with optional inputs to the coresight trigger mechanisms,
> > rather than being a coresight component itself. Other SoCs have
> > non-coresight component inputs to CTIs. For example the PL011 serial
> > device on Juno has a signal into one of the system CTIs.
>
> In addition to above, the TGU also have the coresight management
> registers in its register region
>
> which is a character of coresight component.
>

These registers are not exposed in sysfs by your driver, nor are the
values known, so it is difficult to know if they correctly follow the
CoreSight 3.0 Architecture specification - ARM IHI 0029F; which
defines the identification and discovery requirements that all
CoreSight components must follow.

These appear to be missing from your other devices listed in the
coresight driver area - something we appear to have overlooked in
previous driver reviews.

The CTI / ETM and other ARM component coresight drivers all have a
sysfs "mgmt" section that exposes these management registers.

As I mentioned in my comments to the bindings in patch 1 - the
Coresight visible component architecture and ID registers should be
used to discover and identify the capabilities of components, such as
in this case the number of steps/timers/triggers/priorities - and not
need these values to be defined in the device tree. In this way, we
remove the possibility of errors in a device tree leading to driver
failure.

Regards


Mike

> Based on these clarification, could we consider it as a coresight
> component?
> >
> >> Here is a detailed example to explain how to use the TGU:
> >>
> >> In this example, the TGU is configured to use 2 conditions, 2 steps, and
> >> the timer. The goal is to look for one of two patterns which are generated
> >> from TPDM, giving priority to one, and then generate a trigger once the
> >> timer reaches a certain value. In other words, two conditions are used
> >> for the first step to look for the two patterns, where the one with the
> >> highest priority is used in the first condition. Then, in the second step,
> >> the timer is enabled and set to be compared to the given value at each
> >> clock cycle. These steps are better shown below.
> >>
> >>
> >>              |-----------------|
> >>              |                 |
> >>              |       TPDM      |
> >>              |                 |
> >>              |-----------------|
> >>                       |
> >>                       |
> >>    --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ------
> >>    |                  |                                                 |
> >>    |                  |                          |--------------------| |
> >>    |    |---- --->    |                          |  Go to next steps  | |
> >>    |    |             |                |--- ---> |  Enable timer      | |
> >>    |    |             v                |         |                    | |
> >>    |    |    |-----------------|       |         |--------------------| |
> >>    |    |    |                 |  Yes  |                    |           |
> >>    |    |    |   inputs==0xB   | ----->|                    | <-------- |
> >>    |    |    |                 |       |                    |      No | |
> >>    | No |    |-----------------|       |                    v         | |
> >>    |    |             |                |          |-----------------| | |
> >>    |    |             |                |          |                 | | |
> >>    |    |             |                |          |      timer>=3   |-- |
> >>    |    |             v                |          |                 |   |
> >>    |    |    |-----------------|       |          |-----------------|   |
> >>    |    |    |                 |  Yes  |                    |           |
> >>    |    |--- |   inputs==0xA   | ----->|                    | Yes       |
> >>    |         |                 |                            |           |
> >>    |         |-----------------|                            v           |
> >>    |                                              |-----------------|   |
> >>    |                                              |                 |   |
> >>    |                                              |      Trigger    |   |
> >>    |                                              |                 |   |
> >>    |                                              |-----------------|   |
> >>    |  TGU                                                   |           |
> >>    |--- --- --- --- --- --- --- --- --- --- --- --- --- --- |--- --- -- |
> >>                                                             |
> >>                                                             v
> >>                                                    |-----------------|
> >>                                                    |The controllers  |
> >>                                                    |which will use   |
> >>                                                    |triggers further |
> >>                                                    |-----------------|
> >>
> >> steps:
> >>         1. Reset TGU /*it will disable tgu and reset dataset*/
> >>         - echo 1 > /sys/bus/coresight/devices/<tgu-name>/reset_tgu
> >>
> >>         2. Set the pattern match for priority0 to 0xA = 0b1010 and for
> >>            priority 1 to 0xB = 0b1011.
> >>         - echo 0x11113232 > /sys/bus/coresight/devices/<tgu-name>/step0_priority0/reg0
> >>         - echo 0x11113233 > /sys/bus/coresight/devices/<tgu-name>/step0_priority1/reg0
> >>
> >>         Note:
> >>              Bit distribution diagram for each priority register
> >>      |-------------------------------------------------------------------|
> >>      |   Bits          |       Field Nam   |    Description              |
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |     29:28       |   SEL_BIT7_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |     25:24       |   SEL_BIT6_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |     21:20       |   SEL_BIT5_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |     17:16       |   SEL_BIT4_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |     13:12       |   SEL_BIT3_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |      9:8        |   SEL_BIT2_TYPE2  | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |      5:4        |  SEL_BIT1_TYPE2   | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>      |                 |                   | 00 = bypass for OR output   |
> >>      |      1:0        |  SEL_BIT0_TYPE2   | 01 = bypass for AND output  |
> >>      |                 |                   | 10 = sense input '0' is true|
> >>      |                 |                   | 11 = sense input '1' is true|
> >>      |-------------------------------------------------------------------|
> >>          These bits are used to identify the signals we want to sense, with
> >>          a maximum signal number of 140. For example, to sense the signal
> >>          0xA (binary 1010), we set the value of bits 0 to 13 to 3232, which
> >>          represents 1010. The remaining bits are set to 1, as we want to use
> >>          AND gate to summarize all the signals we want to sense here. For
> >>          rising or falling edge detection of any input to the priority, set
> >>          the remaining bits to 0 to use an OR gate.
> >>
> >>         3. look for the pattern for priority_i i=0,1.
> >>         - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg0
> >>         - echo 0x30 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_decode/reg1
> >>
> >>      |-------------------------------------------------------------------------------|
> >>      |   Bits          |    Field Nam        |            Description                |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |For each decoded condition, this       |
> >>      |      24         |       NOT           |inverts the output. If the condition   |
> >>      |                 |                     |decodes to true, and the NOT field     |
> >>      |                 |                     |is '1', then the output is NOT true.   |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from the associated|
> >>      |      21         |  BC0_COMP_ACTIVE    |comparator will be actively included in|
> >>      |                 |                     |the decoding of this particular        |
> >>      |                 |                     |condition.                             |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from the associated|
> >>      |                 |                     |comparator will need to be 1 to affect |
> >>      |      20         |   BC0_COMP_HIGH     |the decoding of this condition.        |
> >>      |                 |                     |Conversely, a '0' here requires a '0'  |
> >>      |                 |                     |from the comparator                    |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from the associated|
> >>      |      17         |                     |comparator will be actively included in|
> >>      |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
> >>      |                 |                     |condition.                             |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from the associated|
> >>      |                 |                     |comparator will need to be 1 to affect |
> >>      |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
> >>      |                 |                     |condition.Conversely, a 0 here         |
> >>      |                 |                     |requires a '0' from the comparator     |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from Priority_n    |
> >>      |                 |                     |OR logic will be actively              |
> >>      |     4n+3        | Priority_n_OR_ACTIVE|included in the decoding of            |
> >>      |                 |    (n=0,1,2,3)      |this particular condition.             |
> >>      |                 |                     |                                       |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from Priority_n    |
> >>      |                 |                     |will need to be '1' to affect the      |
> >>      |     4n+2        |  Priority_n_OR_HIGH |decoding of this particular            |
> >>      |                 |    (n=0,1,2,3)      |condition. Conversely, a '0' here      |
> >>      |                 |                     |requires a '0' from Priority_n OR logic|
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from Priority_n    |
> >>      |                 |                     |AND logic will be actively             |
> >>      |     4n+1        |Priority_n_AND_ACTIVE|included in the decoding of this       |
> >>      |                 |  (n=0,1,2,3)        |particular condition.                  |
> >>      |                 |                     |                                       |
> >>      |-------------------------------------------------------------------------------|
> >>      |                 |                     |When '1' the output from Priority_n    |
> >>      |                 |                     |AND logic will need to be '1' to       |
> >>      |      4n         | Priority_n_AND_HIGH |affect the decoding of this            |
> >>      |                 |   (n=0,1,2,3)       |particular condition. Conversely,      |
> >>      |                 |                     |a '0' here requires a '0' from         |
> >>      |                 |                     |Priority_n AND logic.                  |
> >>      |-------------------------------------------------------------------------------|
> >>          Since we use `priority_0` and `priority_1` with an AND output in step 2, we set `0x3`
> >>          and `0x30` here to activate them.
> >>
> >>         4. Set NEXT_STEP = 1 and TC0_ENABLE = 1 so that when the conditions
> >>            are met then the next step will be step 1 and the timer will be enabled.
> >>         - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg0
> >>         - echo 0x20008 > /sys/bus/coresight/devices/<tgu-name>/step0_condition_select/reg1
> >>
> >>          |-----------------------------------------------------------------------------|
> >>          |   Bits          |       Field Nam   |            Description                |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This field defines the next step the   |
> >>          |    18:17        |     NEXT_STEP     |TGU will 'goto' for the associated     |
> >>          |                 |                   |Condition and Step.                    |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |For each possible output trigger       |
> >>          |    13           |     TRIGGER       |available, set a '1' if you want       |
> >>          |                 |                   |the trigger to go active for the       |
> >>          |                 |                   |associated condition and Step.         |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will cause BC0 to increment if the|
> >>          |    9            |     BC0_INC       |associated Condition is decoded for    |
> >>          |                 |                   |this step.                             |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will cause BC0 to decrement if the|
> >>          |    8            |     BC0_DEC       |associated Condition is decoded for    |
> >>          |                 |                   |this step.                             |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will clear BC0 count value to 0 if|
> >>          |    7            |     BC0_CLEAR     |the associated Condition is decoded    |
> >>          |                 |                   |for this step.                         |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will cause TC0 to increment until |
> >>          |    3            |     TC0_ENABLE    |paused or cleared if the associated    |
> >>          |                 |                   |Condition is decoded for this step.    |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will cause TC0 to pause until     |
> >>          |    2            |     TC0_PAUSE     |enabled if the associated Condition    |
> >>          |                 |                   |is decoded for this step.              |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will clear TC0 count value to 0   |
> >>          |    1            |     TC0_CLEAR     |if the associated Condition is         |
> >>          |                 |                   |decoded for this step.                 |
> >>          |-----------------------------------------------------------------------------|
> >>          |                 |                   |This will set the done signal to the   |
> >>          |    0            |     DONE          |TGU FSM if the associated Condition    |
> >>          |                 |                   |is decoded for this step.              |
> >>          |-----------------------------------------------------------------------------|
> >>          Based on the distribution diagram, we set `0x20008` for `priority0` and `priority1` to
> >>          achieve "jump to step 1 and enable TC0" once the signal is sensed.
> >>
> >>         5. activate the timer comparison for this step.
> >>         -  echo 0x30000  > /sys/bus/coresight/devices/<tgu-name>/step1_condition_decode/reg0
> >>
> >>          |-------------------------------------------------------------------------------|
> >>          |                 |                     |When '1' the output from the associated|
> >>          |      17         |                     |comparator will be actively included in|
> >>          |                 |  TC0_COMP_ACTIVE    |the decoding of this particular        |
> >>          |                 |                     |condition.                             |
> >>          |-------------------------------------------------------------------------------|
> >>          |                 |                     |When '1' the output from the associated|
> >>          |                 |                     |comparator will need to be 1 to affect |
> >>          |      16         |  TC0_COMP_HIGH      |the decoding of this particular        |
> >>          |                 |                     |condition.Conversely, a 0 here         |
> >>          |                 |                     |requires a '0' from the comparator     |
> >>          |-------------------------------------------------------------------------------|
> >>          Accroding to the decode distribution diagram , we give 0x30000 here to set 16th&17th bit
> >>          to enable timer comparison.
> >>
> >>         6. Set the NEXT_STEP = 0 and TC0_PAUSE = 1 and TC0_CLEAR = 1 once the timer
> >>            has reached the given value.
> >>         - echo 0x6 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/reg0
> >>
> >>         7. Enable Trigger 0 for TGU when the condition 0 is met in step1,
> >>            i.e. when the timer reaches 3.
> >>         - echo 0x2000 > /sys/bus/coresight/devices/<tgu-name>/step1_condition_select/default
> >>
> >>          Note:
> >>              1. 'default' register allows for establishing the resultant action for
> >>              the default condition
> >>
> >>              2. Trigger:For each possible output trigger available from
> >>              the Design document, there are three triggers: interrupts, CTI,
> >>              and Cross-TGU mapping.All three triggers can occur, but
> >>              the choice of which trigger to use depends on the user's
> >>              needs.
> >>
> >>         8. Compare the timer to 3 in step 1.
> >>         - echo 0x3 > /sys/bus/coresight/devices/<tgu-name>/step1_timer/reg0
> >>
> >>         9. enale tgu
> >>         - echo 1 > /sys/bus/coresight/devices/<tgu-name>/enable_tgu
> >>
> > If this is version 3 - where is the list of differences from versions 1 - 2?
> My bad. Will add the previous change log in the next version.
> >
> >> Songwei Chai (7):
> >>    dt-bindings: arm: Add support for Coresight TGU trace
> >>    coresight: Add coresight TGU driver
> >>    coresight-tgu: Add signal priority support
> >>    coresight-tgu: Add TGU decode support
> >>    coresight-tgu: add support to configure next action
> >>    coresight-tgu: add timer/counter functionality for TGU
> >>    coresight-tgu: add reset node to initialize
> >>
> >>   .../testing/sysfs-bus-coresight-devices-tgu   |  51 ++
> >>   .../bindings/arm/qcom,coresight-tgu.yaml      | 135 ++++
> >>   drivers/hwtracing/coresight/Kconfig           |  11 +
> >>   drivers/hwtracing/coresight/Makefile          |   1 +
> >>   drivers/hwtracing/coresight/coresight-tgu.c   | 669 ++++++++++++++++++
> >>   drivers/hwtracing/coresight/coresight-tgu.h   | 242 +++++++
> >>   6 files changed, 1109 insertions(+)
> >>   create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu
> >>   create mode 100644 Documentation/devicetree/bindings/arm/qcom,coresight-tgu.yaml
> >>   create mode 100644 drivers/hwtracing/coresight/coresight-tgu.c
> >>   create mode 100644 drivers/hwtracing/coresight/coresight-tgu.h
> >>
> > Regards
> >
> >
> > Mike
> >
> > --
> > Mike Leach
> > Principal Engineer, ARM Ltd.
> > Manchester Design Centre. UK



--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From robh at kernel.org  Fri Mar 21 07:02:00 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 21 Mar 2025 09:02:00 -0500
Subject: [PATCH v6 2/7] dt-bindings: memory-controllers: Add STM32 Octo
 Memory Manager controller
In-Reply-To: <20250321-upstream_ospi_v6-v6-2-37bbcab43439@foss.st.com>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
 <20250321-upstream_ospi_v6-v6-2-37bbcab43439@foss.st.com>
Message-ID: <20250321140200.GA3192411-robh@kernel.org>

On Fri, Mar 21, 2025 at 10:32:22AM +0100, Patrice Chotard wrote:
> Add bindings for STM32 Octo Memory Manager (OMM) controller.
> 
> OMM manages:
>   - the muxing between 2 OSPI busses and 2 output ports.
>     There are 4 possible muxing configurations:
>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>         output is on port 2
>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>         OSPI2 output is on port 1
>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>   - the split of the memory area shared between the 2 OSPI instances.
>   - chip select selection override.
>   - the time between 2 transactions in multiplexed mode.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
> ---
>  .../memory-controllers/st,stm32mp25-omm.yaml       | 227 +++++++++++++++++++++
>  1 file changed, 227 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..2f8fa7569009369ebd077e4c6f4ab409a91838a5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
> @@ -0,0 +1,227 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/memory-controllers/st,stm32mp25-omm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: STM32 Octo Memory Manager (OMM)
> +
> +maintainers:
> +  - Patrice Chotard <patrice.chotard at foss.st.com>
> +
> +description: |
> +  The STM32 Octo Memory Manager is a low-level interface that enables an
> +  efficient OCTOSPI pin assignment with a full I/O matrix (before alternate
> +  function map) and multiplex of single/dual/quad/octal SPI interfaces over
> +  the same bus. It Supports up to:
> +    - Two single/dual/quad/octal SPI interfaces
> +    - Two ports for pin assignment
> +
> +properties:
> +  compatible:
> +    const: st,stm32mp25-omm
> +
> +  "#address-cells":
> +    const: 2
> +
> +  "#size-cells":
> +    const: 1
> +
> +  ranges:
> +    description: |
> +      Reflects the memory layout with four integer values per OSPI instance.

You say 4 here...

> +      Format:
> +      <chip-select> 0 <registers base address> <size>
> +    minItems: 2
> +    maxItems: 2

And 2 here. I'm confused. From the example it doesn't look like you are 
using ranges correctly. If you are parsing it yourself, that's wrong. 
More below.

> +
> +  reg:
> +    items:
> +      - description: OMM registers
> +      - description: OMM memory map area
> +
> +  reg-names:
> +    items:
> +      - const: regs
> +      - const: memory_map
> +
> +  memory-region:
> +    description: |
> +      Memory region shared between the 2 OCTOSPI instance.
> +      One or two phandle to a node describing a memory mapped region
> +      depending of child number.
> +    minItems: 1
> +    maxItems: 2
> +
> +  memory-region-names:
> +    description: |

Don't need '|'.

> +      OCTOSPI instance's name to which memory region is associated

That doesn't really tell me anything.

> +    items:
> +      enum: [ospi1, ospi2]
> +    minItems: 1
> +    maxItems: 2
> +
> +  clocks:
> +    minItems: 3
> +    maxItems: 3
> +
> +  clock-names:
> +    items:
> +      enum: [omm, ospi1, ospi2]

Define the order.

> +    minItems: 3
> +    maxItems: 3
> +
> +  resets:
> +    minItems: 3
> +    maxItems: 3
> +
> +  reset-names:
> +    items:
> +      enum: [omm, ospi1, ospi2]

Define the order.

> +    minItems: 3
> +    maxItems: 3
> +
> +  access-controllers:
> +    maxItems: 1
> +
> +  st,syscfg-amcr:
> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      The Address Mapping Control Register (AMCR) is used to split the 256MB
> +      memory map area shared between the 2 OSPI instance. The Octo Memory
> +      Manager sets the AMCR depending of the memory-region configuration.
> +      The memory split bitmask description is:
> +        - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped
> +        - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes)
> +        - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes)
> +        - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes)
> +        - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes)
> +    items:
> +      - description: phandle to syscfg
> +      - description: register offset within syscfg
> +      - description: register bitmask for memory split
> +
> +  st,omm-req2ack-ns:
> +    description: |

Don't need '|'.

> +      In multiplexed mode (MUXEN = 1), this field defines the time in
> +      nanoseconds between two transactions.
> +    default: 0
> +
> +  st,omm-cssel-ovr:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Configure the chip select selector override for the 2 OCTOSPIs.
> +      - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
> +      - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
> +      - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
> +      - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
> +    minimum: 0
> +    maximum: 3
> +    default: 0
> +
> +  st,omm-mux:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports.
> +      - 0: direct mode
> +      - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
> +      - 2: swapped mode
> +      - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
> +    minimum: 0
> +    maximum: 3
> +    default: 0
> +
> +  power-domains:
> +    maxItems: 1
> +
> +patternProperties:
> +  ^spi@[a-f0-9]+$:
> +    type: object
> +    $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
> +    description: Required spi child node
> +
> +required:
> +  - compatible
> +  - reg
> +  - "#address-cells"
> +  - "#size-cells"
> +  - clocks
> +  - clock-names
> +  - resets
> +  - reset-names
> +  - st,syscfg-amcr
> +  - ranges
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/st,stm32mp25-rcc.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/reset/st,stm32mp25-rcc.h>
> +    ommanager at 40500000 {
> +      compatible = "st,stm32mp25-omm";
> +      reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
> +      reg-names = "regs", "memory_map";
> +      ranges = <0 0 0x40430000 0x400>,
> +               <1 0 0x40440000 0x400>;

> +      #address-cells = <2>;
> +      #size-cells = <1>;
> +

> +      spi at 40430000 {

ranges is okay, but the unit-address is wrong here. It should be based 
on reg below. So 'spi at 0' or 'spi at 0,0' since chip select is a distinct 
field. It's up to you, but you need to define the format in the schema.

> +        compatible = "st,stm32mp25-ospi";
> +        reg = <0 0 0x400>;
> +        memory-region = <&mm_ospi1>;
> +        interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
> +        dmas = <&hpdma 2 0x62 0x00003121 0x0>,
> +               <&hpdma 2 0x42 0x00003112 0x0>;
> +        dma-names = "tx", "rx";
> +        clocks = <&scmi_clk CK_SCMI_OSPI1>;
> +        resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
> +        access-controllers = <&rifsc 74>;
> +        power-domains = <&CLUSTER_PD>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        st,syscfg-dlyb = <&syscfg 0x1000>;
> +      };
> +
> +      spi at 40440000 {

spi at 1,0

> +        compatible = "st,stm32mp25-ospi";
> +        reg = <1 0 0x400>;
> +        memory-region = <&mm_ospi1>;
> +        interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
> +        dmas = <&hpdma 3 0x62 0x00003121 0x0>,
> +               <&hpdma 3 0x42 0x00003112 0x0>;
> +        dma-names = "tx", "rx";
> +        clocks = <&scmi_clk CK_KER_OSPI2>;
> +        resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>;
> +        access-controllers = <&rifsc 75>;
> +        power-domains = <&CLUSTER_PD>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        st,syscfg-dlyb = <&syscfg 0x1000>;
> +      };
> +    };
> 
> -- 
> 2.25.1
> 


From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 07:15:34 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 16:15:34 +0200
Subject: [PATCH v3 03/10] phy: move phy-qcom-snps-eusb2 out of its vendor
 sub-directory
In-Reply-To: <20250321135854.1431375-4-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-4-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <vzlylhf5r5xy4ip4hkcolt3iye4stiabzxc4jwdzenbhll45ct@hx5gwpzrd33y>

On Fri, Mar 21, 2025 at 03:58:47PM +0200, Ivaylo Ivanov wrote:
> As not only Qualcomm, but also Samsung is using the Synopsys eUSB2 IP
> (albeit with a different register layout) in their newer SoCs, move the
> driver out of its vendor sub-directory and rename it to phy-snps-eusb2.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Please fix the order of the tags. SoB should come after Suggested-by
(and usually it is the last one).

> ---
>  drivers/phy/Kconfig                                      | 8 ++++++++
>  drivers/phy/Makefile                                     | 1 +
>  .../{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} | 0
>  drivers/phy/qualcomm/Kconfig                             | 9 ---------
>  drivers/phy/qualcomm/Makefile                            | 1 -
>  5 files changed, 9 insertions(+), 10 deletions(-)
>  rename drivers/phy/{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} (100%)

With that fixed:


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>


-- 
With best wishes
Dmitry


From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:17:25 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:17:25 +0200
Subject: [PATCH v3 03/10] phy: move phy-qcom-snps-eusb2 out of its vendor
 sub-directory
In-Reply-To: <vzlylhf5r5xy4ip4hkcolt3iye4stiabzxc4jwdzenbhll45ct@hx5gwpzrd33y>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-4-ivo.ivanov.ivanov1@gmail.com>
 <vzlylhf5r5xy4ip4hkcolt3iye4stiabzxc4jwdzenbhll45ct@hx5gwpzrd33y>
Message-ID: <782c2211-aa75-43b1-995a-2c93d75d75e7@gmail.com>

On 3/21/25 16:15, Dmitry Baryshkov wrote:
> On Fri, Mar 21, 2025 at 03:58:47PM +0200, Ivaylo Ivanov wrote:
>> As not only Qualcomm, but also Samsung is using the Synopsys eUSB2 IP
>> (albeit with a different register layout) in their newer SoCs, move the
>> driver out of its vendor sub-directory and rename it to phy-snps-eusb2.
>>
>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>> Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Please fix the order of the tags. SoB should come after Suggested-by
> (and usually it is the last one).

Hm? I haven't had issues with SoB at the top in the past.

>
>> ---
>>  drivers/phy/Kconfig                                      | 8 ++++++++
>>  drivers/phy/Makefile                                     | 1 +
>>  .../{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} | 0
>>  drivers/phy/qualcomm/Kconfig                             | 9 ---------
>>  drivers/phy/qualcomm/Makefile                            | 1 -
>>  5 files changed, 9 insertions(+), 10 deletions(-)
>>  rename drivers/phy/{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} (100%)
> With that fixed:
>
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

Thanks!

Best regards,
Ivaylo

>
>



From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 07:17:23 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 16:17:23 +0200
Subject: [PATCH v3 04/10] phy: phy-snps-eusb2: refactor constructs names
In-Reply-To: <20250321135854.1431375-5-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-5-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <ftscdayi4uegv4bfzckytfrg44vi6f5wlvlhjqsh5nmgumrjx4@ur6rgxj5ixsj>

On Fri, Mar 21, 2025 at 03:58:48PM +0200, Ivaylo Ivanov wrote:
> As the driver now resides outside the phy subdirectory under a different
> name, refactor all definitions, structures and functions to explicitly
> specify what code is Qualcomm-specific and what is not.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  drivers/phy/phy-snps-eusb2.c | 256 +++++++++++++++++------------------
>  1 file changed, 128 insertions(+), 128 deletions(-)
> 


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>


>  
> -module_platform_driver(qcom_snps_eusb2_hsphy_driver);
> -MODULE_DESCRIPTION("Qualcomm SNPS eUSB2 HS PHY driver");
> +module_platform_driver(snps_eusb2_hsphy_driver);
> +MODULE_DESCRIPTION("SNPS eUSB2 HS PHY driver");

Nit: Synopsys

>  MODULE_LICENSE("GPL");
> -- 
> 2.43.0
> 

-- 
With best wishes
Dmitry


From simona.vetter at ffwll.ch  Fri Mar 21 07:24:36 2025
From: simona.vetter at ffwll.ch (Simona Vetter)
Date: Fri, 21 Mar 2025 15:24:36 +0100
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
Message-ID: <Z912pMazVwHKLi72@phenom.ffwll.local>

On Fri, Mar 14, 2025 at 07:23:16PM -0400, Alyssa Rosenzweig wrote:
> This adds the UAPI for the Asahi driver targeting the GPU in the Apple
> M1 and M2 series systems on chip. The UAPI design is based on other
> modern Vulkan-capable drivers, including Xe and Panthor. Memory
> management is based on explicit VM management. Synchronization is
> exclusively explicit sync.
> 
> This UAPI is validated against our open source Mesa stack, which is
> fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
> Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
> VM_BIND mechanism.
> 
> This patch adds the standalone UAPI header. It is implemented by an open
> source DRM driver written in Rust. We fully intend to upstream this
> driver when possible. However, as a production graphics driver, it
> depends on a significant number of Rust abstractions that will take a
> long time to upstream. In the mean time, our userspace is upstream in
> Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
> yet reviewed and merged in the upstream kernel. Although we ship a
> patched Mesa in Fedora Asahi Remix, any containers shipping upstream
> Mesa builds are broken for our users, including upstream Flatpak and
> Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
> and virglrenderer, which complicates bisects.
> 
> The intention in sending out this patch is for this UAPI to be
> thoroughly reviewed. Once we as the DRM community are satisfied with the
> UAPI, this header lands signifying that the UAPI is stable and must only
> be evolved in backwards-compatible ways; it will be the UAPI implemented
> in the DRM driver that eventually lands upstream. That promise lets us
> enable upstream Mesa, solving all these issues while the upstream Rust
> abstractions are developed.
> 
> https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v3 contains
> the DRM driver implementing this proposed UAPI.
> 
> https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains
> the Mesa patches to implement this proposed UAPI. It is mirrored at
> https://github.com/alyssarosenzweig/mesa/tree/agx-uapi-v3 to allow
> continued review during upcoming gitlab.freedesktop.org downtime.
> 
> That Linux and Mesa branch together give a complete graphics/compute
> stack on top of this UAPI.
> 
> Co-developed-by: Asahi Lina <lina at asahilina.net>
> Signed-off-by: Asahi Lina <lina at asahilina.net>
> Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>

Since this is a deparature from our usual requirement that all pieces
should be ready before landing anything we had discussion whether this is
an acceptable one-off exception for special circumstance. Thanks a lot to
Alyssa for driving this. The very much summarized consensus is that due to
rust this is a special case, and because the userspace is in upstream mesa
and lead by people who know what they're doing and have been around for
years, it should all work out. As a stand-in for that discussion:

Acked-by: Simona Vetter <simona.vetter at ffwll.ch>

But Dave&me very much do not want to make this a recurring thing, please
don't try :-)

Cheers, Sima

> ---
> Changes in v3:
> - Merge load/store/partial fields for depth/stencil as discussed with
>   Faith. This shrinks the submit a lot with little loss of
>   functionality. There's maaaybe a use case for splitting out depth load
>   base (only) later. But it's easier to add uAPI than remove it!
> - Make usc_exec_base per-queue instead of per-command. No use case for
>   doing it finer grained, and this shrinks the submits and simplifies
>   userspace handling.
> - Improve descriptions.
> - Reorder/shrink fields to remove padding.
> - Use full names for vdm/cdm_ctrl_stream_base
> - Link to v2: https://lore.kernel.org/r/20250313-agx-uapi-v2-1-59cc53a59ea3 at rosenzweig.io
> 
> Changes in v2:
> - Flatten submits. Previously, the submit ioctl pointed to an array of
>   command structures, which each pointed to separate payload structures,
>   which pointed to attachment structures. This is a lot of indirection,
>   which complicates greatly virtgpu. In the new approach, the submit
>   ioctl points to a single contiguous blob of plain-old-data, no CPU
>   pointers, copied from userspace in one go and suitable as virtgpu wire
>   protocol.
> - Remove vm_page_size, userspace has to hardcode it anyway.
> - Turn random #defines into enums for better kernel doc, etc.
> - Improve comments, particularly around barriers[].
> - Rename various flags/fields to better match canonical names when known
>   (a lot of the names are pulled from the drivers/gpu/drm/imagination,
>   naturally).
> - Drop unnecessary encoder_id, cmd_id handles.
> - Fix padding in submit ioctl (thanks Ryan).
> - Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io
> ---
>  Documentation/gpu/driver-uapi.rst |    5 +
>  MAINTAINERS                       |    1 +
>  include/uapi/drm/asahi_drm.h      | 1123 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 1129 insertions(+)
> 
> diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
> index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
> --- a/Documentation/gpu/driver-uapi.rst
> +++ b/Documentation/gpu/driver-uapi.rst
> @@ -27,3 +27,8 @@ drm/xe uAPI
>  ===========
>  
>  .. kernel-doc:: include/uapi/drm/xe_drm.h
> +
> +drm/asahi uAPI
> +================
> +
> +.. kernel-doc:: include/uapi/drm/asahi_drm.h
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2256,6 +2256,7 @@ F:	drivers/watchdog/apple_wdt.c
>  F:	include/dt-bindings/interrupt-controller/apple-aic.h
>  F:	include/dt-bindings/pinctrl/apple.h
>  F:	include/linux/soc/apple/*
> +F:	include/uapi/drm/asahi_drm.h
>  
>  ARM/ARTPEC MACHINE SUPPORT
>  M:	Jesper Nilsson <jesper.nilsson at axis.com>
> diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..8954e71f0592c09c84da1b0783d973e0637b5559
> --- /dev/null
> +++ b/include/uapi/drm/asahi_drm.h
> @@ -0,0 +1,1123 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright (C) The Asahi Linux Contributors
> + * Copyright (C) 2018-2023 Collabora Ltd.
> + * Copyright (C) 2014-2018 Broadcom
> + */
> +#ifndef _ASAHI_DRM_H_
> +#define _ASAHI_DRM_H_
> +
> +#include "drm.h"
> +
> +#if defined(__cplusplus)
> +extern "C" {
> +#endif
> +
> +/**
> + * DOC: Introduction to the Asahi UAPI
> + *
> + * This documentation describes the Asahi IOCTLs.
> + *
> + * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
> + * from Panthor):
> + *
> + * - Structures must be aligned on 64-bit/8-byte. If the object is not
> + *   naturally aligned, a padding field must be added.
> + * - Fields must be explicitly aligned to their natural type alignment with
> + *   pad[0..N] fields.
> + * - All padding fields will be checked by the driver to make sure they are
> + *   zeroed.
> + * - Flags can be added, but not removed/replaced.
> + * - New fields can be added to the main structures (the structures
> + *   directly passed to the ioctl). Those fields can be added at the end of
> + *   the structure, or replace existing padding fields. Any new field being
> + *   added must preserve the behavior that existed before those fields were
> + *   added when a value of zero is passed.
> + * - New fields can be added to indirect objects (objects pointed by the
> + *   main structure), iff those objects are passed a size to reflect the
> + *   size known by the userspace driver (see
> + *   drm_asahi_command::cmd_buffer_size).
> + * - If the kernel driver is too old to know some fields, those will be
> + *   ignored if zero, and otherwise rejected (and so will be zero on output).
> + * - If userspace is too old to know some fields, those will be zeroed
> + *   (input) before the structure is parsed by the kernel driver.
> + * - Each new flag/field addition must come with a driver version update so
> + *   the userspace driver doesn't have to trial and error to know which
> + *   flags are supported.
> + * - Structures should not contain unions, as this would defeat the
> + *   extensibility of such structures.
> + * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
> + *   at the end of the drm_asahi_ioctl_id enum.
> + */
> +
> +/**
> + * enum drm_asahi_ioctl_id - IOCTL IDs
> + *
> + * Place new ioctls at the end, don't re-order, don't replace or remove entries.
> + *
> + * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
> + * definitions instead.
> + */
> +enum drm_asahi_ioctl_id {
> +	/** @DRM_ASAHI_GET_PARAMS: Query device properties. */
> +	DRM_ASAHI_GET_PARAMS = 0,
> +
> +	/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
> +	DRM_ASAHI_VM_CREATE,
> +
> +	/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
> +	DRM_ASAHI_VM_DESTROY,
> +
> +	/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
> +	DRM_ASAHI_GEM_CREATE,
> +
> +	/**
> +	 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
> +	 * given GEM handle.
> +	 */
> +	DRM_ASAHI_GEM_MMAP_OFFSET,
> +
> +	/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
> +	DRM_ASAHI_GEM_BIND,
> +
> +	/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
> +	DRM_ASAHI_QUEUE_CREATE,
> +
> +	/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
> +	DRM_ASAHI_QUEUE_DESTROY,
> +
> +	/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
> +	DRM_ASAHI_SUBMIT,
> +
> +	/** @DRM_ASAHI_GET_TIME: Query device time. */
> +	DRM_ASAHI_GET_TIME,
> +
> +	/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
> +	DRM_ASAHI_GEM_BIND_OBJECT,
> +};
> +
> +#define DRM_ASAHI_MAX_CLUSTERS	64
> +
> +/**
> + * struct drm_asahi_params_global - Global parameters.
> + *
> + * This struct may be queried by drm_asahi_get_params.
> + */
> +struct drm_asahi_params_global {
> +	/** @features: Feature bits from drm_asahi_feature */
> +	__u64 features;
> +
> +	/** @gpu_generation: GPU generation, e.g. 13 for G13G */
> +	__u32 gpu_generation;
> +
> +	/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
> +	__u32 gpu_variant;
> +
> +	/**
> +	 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
> +	 * 0x21 for 'C1'
> +	 */
> +	__u32 gpu_revision;
> +
> +	/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
> +	__u32 chip_id;
> +
> +	/** @num_dies: Number of dies in the SoC */
> +	__u32 num_dies;
> +
> +	/** @num_clusters_total: Number of GPU clusters (across all dies) */
> +	__u32 num_clusters_total;
> +
> +	/**
> +	 * @num_cores_per_cluster: Number of logical cores per cluster
> +	 * (including inactive/nonexistent)
> +	 */
> +	__u32 num_cores_per_cluster;
> +
> +	/** @num_frags_per_cluster: Number of frags per cluster */
> +	__u32 num_frags_per_cluster;
> +
> +	/** @num_gps_per_cluster: Number of GPs per cluster */
> +	__u32 num_gps_per_cluster;
> +
> +	/** @max_power_mw: Maximum GPU power consumption */
> +	__u32 max_power_mw;
> +
> +	/** @core_masks: Bitmask of present/enabled cores per cluster */
> +	__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
> +
> +	/** @timer_frequency_hz: Clock frequency for timestamps */
> +	__u64 timer_frequency_hz;
> +
> +	/** @min_frequency_khz: Minimum GPU core clock frequency */
> +	__u32 min_frequency_khz;
> +
> +	/** @max_frequency_khz: Maximum GPU core clock frequency */
> +	__u32 max_frequency_khz;
> +
> +	/** @vm_user_start: VM user range start VMA */
> +	__u64 vm_user_start;
> +
> +	/** @vm_user_end: VM user range end VMA */
> +	__u64 vm_user_end;
> +
> +	/**
> +	 * @vm_kernel_min_size: Minimum kernel VMA window size within user
> +	 * range
> +	 */
> +	__u64 vm_kernel_min_size;
> +
> +	/**
> +	 * @max_commands_per_submission: Maximum number of supported commands
> +	 * per submission
> +	 */
> +	__u32 max_commands_per_submission;
> +
> +	/**
> +	 * @max_attachments: Maximum number of drm_asahi_attachment's per
> +	 * command
> +	 */
> +	__u32 max_attachments;
> +
> +	/**
> +	 * @firmware_version: GPU firmware version, as 4 integers
> +	 */
> +	__u32 firmware_version[4];
> +
> +	/**
> +	 * @user_timestamp_frequency_hz: Timebase frequency for user timestamps
> +	 */
> +	__u64 user_timestamp_frequency_hz;
> +};
> +
> +/**
> + * enum drm_asahi_feature - Feature bits
> + *
> + * This covers only features that userspace cannot infer from the architecture
> + * version. Most features don't need to be here.
> + */
> +enum drm_asahi_feature {
> +	/**
> +	 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
> +	 * loads of unmapped memory will return zero. Shader stores to unmapped
> +	 * memory will be silently discarded. Note that only shader load/store
> +	 * is affected. Other hardware units are not affected, notably including
> +	 * texture sampling.
> +	 */
> +	DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
> +};
> +
> +/**
> + * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
> + */
> +struct drm_asahi_get_params {
> +	/** @param_group: Parameter group to fetch (MBZ) */
> +	__u32 param_group;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +
> +	/** @pointer: User pointer to write parameter struct */
> +	__u64 pointer;
> +
> +	/** @size: Size of user buffer, max size supported on return */
> +	__u64 size;
> +};
> +
> +/**
> + * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
> + */
> +struct drm_asahi_vm_create {
> +	/** @kernel_start: Start of the kernel-reserved address range */
> +	__u64 kernel_start;
> +
> +	/** @kernel_end: End of the kernel-reserved address range */
> +	__u64 kernel_end;
> +
> +	/** @vm_id: Returned VM ID */
> +	__u32 vm_id;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
> + */
> +struct drm_asahi_vm_destroy {
> +	/** @vm_id: VM ID to be destroyed */
> +	__u32 vm_id;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * enum drm_asahi_gem_flags - Flags for GEM creation
> + */
> +enum drm_asahi_gem_flags {
> +	/**
> +	 * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
> +	 *
> +	 * Map as writeback instead of write-combine. This optimizes for CPU
> +	 * reads.
> +	 */
> +	DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
> +
> +	/**
> +	 * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
> +	 */
> +	DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
> +};
> +
> +/**
> + * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
> + */
> +struct drm_asahi_gem_create {
> +	/** @size: Size of the BO */
> +	__u64 size;
> +
> +	/** @flags: Combination of drm_asahi_gem_flags flags. */
> +	__u32 flags;
> +
> +	/**
> +	 * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
> +	 */
> +	__u32 vm_id;
> +
> +	/** @handle: Returned GEM handle for the BO */
> +	__u32 handle;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_gem_mmap_offset - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
> + */
> +struct drm_asahi_gem_mmap_offset {
> +	/** @handle: Handle for the object being mapped. */
> +	__u32 handle;
> +
> +	/** @flags: Must be zero */
> +	__u32 flags;
> +
> +	/** @offset: The fake offset to use for subsequent mmap call */
> +	__u64 offset;
> +};
> +
> +/**
> + * enum drm_asahi_bind_op - Bind operation
> + */
> +enum drm_asahi_bind_op {
> +	/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
> +	DRM_ASAHI_BIND_OP_BIND = 0,
> +
> +	/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
> +	DRM_ASAHI_BIND_OP_UNBIND = 1,
> +
> +	/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */
> +	DRM_ASAHI_BIND_OP_UNBIND_ALL = 2,
> +};
> +
> +/**
> + * enum drm_asahi_bind_flags - Flags for GEM binding
> + */
> +enum drm_asahi_bind_flags {
> +	/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
> +	DRM_ASAHI_BIND_READ = (1L << 0),
> +
> +	/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
> +	DRM_ASAHI_BIND_WRITE = (1L << 1),
> +
> +	/**
> +	 * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
> +	 * across the VA range.
> +	 *
> +	 * This is useful to fill a VA range with scratch pages or zero pages.
> +	 * It is intended as a mechanism to accelerate sparse.
> +	 */
> +	DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
> +};
> +
> +/**
> + * struct drm_asahi_gem_bind - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_BIND
> + */
> +struct drm_asahi_gem_bind {
> +	/** @op: Bind operation (enum drm_asahi_bind_op) */
> +	__u32 op;
> +
> +	/** @flags: Combination of drm_asahi_bind_flags flags. */
> +	__u32 flags;
> +
> +	/** @handle: GEM object to bind/unbind (BIND or UNBIND_ALL) */
> +	__u32 handle;
> +
> +	/** @vm_id: The ID of the VM to operate on */
> +	__u32 vm_id;
> +
> +	/** @offset: Offset into the object (BIND only) */
> +	__u64 offset;
> +
> +	/**
> +	 * @range: Number of bytes to bind/unbind to addr (BIND or UNBIND only)
> +	 */
> +	__u64 range;
> +
> +	/** @addr: Address to bind to (BIND or UNBIND only) */
> +	__u64 addr;
> +};
> +
> +/**
> + * enum drm_asahi_bind_object_op - Special object bind operation
> + */
> +enum drm_asahi_bind_object_op {
> +	/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
> +	DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
> +
> +	/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
> +	DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
> +};
> +
> +/**
> + * enum drm_asahi_bind_object_flags - Special object bind flags
> + */
> +enum drm_asahi_bind_object_flags {
> +	/**
> +	 * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
> +	 * buffer.
> +	 */
> +	DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
> +};
> +
> +/**
> + * struct drm_asahi_gem_bind_object - Arguments passed to
> + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
> + */
> +struct drm_asahi_gem_bind_object {
> +	/** @op: Bind operation (enum drm_asahi_bind_object_op) */
> +	__u32 op;
> +
> +	/** @flags: Combination of drm_asahi_bind_object_flags flags. */
> +	__u32 flags;
> +
> +	/** @handle: GEM object to bind/unbind (BIND) */
> +	__u32 handle;
> +
> +	/** @vm_id: The ID of the VM to operate on (MBZ currently) */
> +	__u32 vm_id;
> +
> +	/** @offset: Offset into the object (BIND only) */
> +	__u64 offset;
> +
> +	/** @range: Number of bytes to bind/unbind (BIND only) */
> +	__u64 range;
> +
> +	/** @object_handle: Object handle (out for BIND, in for UNBIND) */
> +	__u32 object_handle;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * enum drm_asahi_cmd_type - Command type
> + */
> +enum drm_asahi_cmd_type {
> +	/**
> +	 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
> +	 * subqueue. Combined vertex and fragment operation.
> +	 *
> +	 * Followed by a @drm_asahi_cmd_render payload.
> +	 */
> +	DRM_ASAHI_CMD_RENDER = 0,
> +
> +	/**
> +	 * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
> +	 *
> +	 * Followed by a @drm_asahi_cmd_compute payload.
> +	 */
> +	DRM_ASAHI_CMD_COMPUTE = 1,
> +
> +	/**
> +	 * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
> +	 * attachments for subsequent vertex shaders in the same submit.
> +	 *
> +	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
> +	 */
> +	DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
> +
> +	/**
> +	 * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
> +	 * attachments for subsequent fragment shaders in the same submit.
> +	 *
> +	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
> +	 */
> +	DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
> +
> +	/**
> +	 * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
> +	 * attachments for subsequent compute shaders in the same submit.
> +	 *
> +	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
> +	 */
> +	DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
> +};
> +
> +/**
> + * enum drm_asahi_queue_cap - Queue capabilities
> + */
> +enum drm_asahi_queue_cap {
> +	/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
> +	DRM_ASAHI_QUEUE_CAP_RENDER	= (1UL << DRM_ASAHI_CMD_RENDER),
> +
> +	/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
> +	DRM_ASAHI_QUEUE_CAP_COMPUTE	= (1UL << DRM_ASAHI_CMD_COMPUTE),
> +};
> +
> +/**
> + * struct drm_asahi_queue_create - Arguments passed to
> + * DRM_IOCTL_ASAHI_QUEUE_CREATE
> + */
> +struct drm_asahi_queue_create {
> +	/** @flags: MBZ */
> +	__u32 flags;
> +
> +	/** @vm_id: The ID of the VM this queue is bound to */
> +	__u32 vm_id;
> +
> +	/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
> +	__u32 queue_caps;
> +
> +	/** @priority: Queue priority, 0-3 */
> +	__u32 priority;
> +
> +	/** @queue_id: The returned queue ID */
> +	__u32 queue_id;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +
> +	/**
> +	 * @usc_exec_base: GPU base address for all USC binaries (shaders) on
> +	 * this queue. USC addresses are 32-bit relative to this 64-bit base.
> +	 *
> +	 * This sets the following registers on all queue commands:
> +	 *
> +	 *	USC_EXEC_BASE_TA  (vertex)
> +	 *	USC_EXEC_BASE_ISP (fragment)
> +	 *	USC_EXEC_BASE_CP  (compute)
> +	 *
> +	 * While the hardware lets us configure these independently per command,
> +	 * we do not have a use case for this. Instead, we expect userspace to
> +	 * fix a 4GiB VA carveout for USC memory and pass its base address here.
> +	 */
> +	__u64 usc_exec_base;
> +};
> +
> +/**
> + * struct drm_asahi_queue_destroy - Arguments passed to
> + * DRM_IOCTL_ASAHI_QUEUE_DESTROY
> + */
> +struct drm_asahi_queue_destroy {
> +	/** @queue_id: The queue ID to be destroyed */
> +	__u32 queue_id;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * enum drm_asahi_sync_type - Sync item type
> + */
> +enum drm_asahi_sync_type {
> +	/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
> +	DRM_ASAHI_SYNC_SYNCOBJ = 0,
> +
> +	/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
> +	DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
> +};
> +
> +/**
> + * struct drm_asahi_sync - Sync item
> + */
> +struct drm_asahi_sync {
> +	/** @sync_type: One of drm_asahi_sync_type */
> +	__u32 sync_type;
> +
> +	/** @handle: The sync object handle */
> +	__u32 handle;
> +
> +	/** @timeline_value: Timeline value for timeline sync objects */
> +	__u64 timeline_value;
> +};
> +
> +/**
> + * enum drm_asahi_subqueue - Subqueue within a queue
> + */
> +enum drm_asahi_subqueue {
> +	/** @DRM_ASAHI_SUBQUEUE_RENDER: Render subqueue */
> +	DRM_ASAHI_SUBQUEUE_RENDER = 0,
> +
> +	/** @DRM_ASAHI_SUBQUEUE_COMPUTE: Compute subqueue */
> +	DRM_ASAHI_SUBQUEUE_COMPUTE = 1,
> +
> +	/**
> +	 * @DRM_ASAHI_SUBQUEUE_COUNT: Queue count, must remain multiple of 2
> +	 * for struct alignment
> +	 */
> +	DRM_ASAHI_SUBQUEUE_COUNT = 2,
> +};
> +
> +/**
> + * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
> + *
> + * This special value may be passed in to drm_asahi_command::barriers[] to
> + * indicate that the respective subqueue should not wait on any previous work.
> + */
> +#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
> +
> +/**
> + * struct drm_asahi_cmd_header - Top level command structure
> + */
> +struct drm_asahi_cmd_header {
> +	/** @cmd_type: One of drm_asahi_cmd_type */
> +	__u16 cmd_type;
> +
> +	/**
> +	 * @size: Size of this command, not including this header.
> +	 *
> +	 * For hardware commands, this enables extensibility of commands without
> +	 * requiring extra command types.  Passing a command that is shorter
> +	 * than expected is explicitly allowed for backwards-compatability.
> +	 * Truncated fields will be zeroed.
> +	 *
> +	 * For the synthetic attachment setting commands, this implicitly
> +	 * encodes the number of attachments. These commands take multiple
> +	 * fixed-size @drm_asahi_attachment structures as their payload, so size
> +	 * equals number of attachments * sizeof(struct drm_asahi_attachment).
> +	 */
> +	__u16 size;
> +
> +	/**
> +	 * @barriers: Array of command indices per subqueue to wait on.
> +	 *
> +	 * Barriers are indices relative to the beginning of a given submit. A
> +	 * barrier of 0 waits on commands submitted to the subqueue in previous
> +	 * submit ioctls. A barrier of N waits on N previous commands on the
> +	 * subqueue within the current submit ioctl. As a special case, passing
> +	 * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the
> +	 * subqueue.
> +	 *
> +	 * Examples:
> +	 *
> +	 *   (0, 0): This waits on all previous work.
> +	 *
> +	 *   (NONE, 0): This waits on previously submitted compute commands but
> +	 *   does not wait on any render commands.
> +	 *
> +	 *   (1, NONE): This waits on the first render command in the submit.
> +	 *   This only makes sense if there are multiple render commands in the
> +	 *   same submit.
> +	 *
> +	 * Barriers only make sense for hardware commands. Synthetic software
> +	 * commands to set attachments must pass (NONE, NONE) here.
> +	 */
> +	__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT];
> +};
> +
> +/**
> + * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
> + */
> +struct drm_asahi_submit {
> +	/**
> +	 * @in_syncs: An optional array of drm_asahi_sync to wait on before
> +	 * starting this job.
> +	 */
> +	__u64 in_syncs;
> +
> +	/**
> +	 * @out_syncs: An optional array of drm_asahi_sync objects to signal
> +	 * upon completion.
> +	 */
> +	__u64 out_syncs;
> +
> +	/**
> +	 * @cmdbuf: Pointer to the command buffer to submit.
> +	 *
> +	 * This is a flat command buffer. By design, it contains no CPU
> +	 * pointers, which makes it suitable for a virtgpu wire protocol without
> +	 * requiring any serializing/deserializing step.
> +	 *
> +	 * It consists of a series of commands. Each command begins with a
> +	 * fixed-size @drm_asahi_cmd_header and is followed by a variable-length
> +	 * payload according to the type and size in the header.
> +	 */
> +	__u64 cmdbuf;
> +
> +	/** @flags: Flags for command submission (MBZ) */
> +	__u32 flags;
> +
> +	/** @queue_id: The queue ID to be submitted to */
> +	__u32 queue_id;
> +
> +	/**
> +	 * @in_sync_count: Number of sync objects to wait on before starting
> +	 * this job.
> +	 */
> +	__u32 in_sync_count;
> +
> +	/**
> +	 * @out_sync_count: Number of sync objects to signal upon completion of
> +	 * this job.
> +	 */
> +	__u32 out_sync_count;
> +
> +	/** @cmdbuf_size: Command buffer size in bytes */
> +	__u32 cmdbuf_size;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +};
> +
> +/**
> + * struct drm_asahi_attachment - Describe an "attachment".
> + *
> + * Attachments are any memory written by shaders, notably including render
> + * target attachments written by the end-of-tile program. This is purely a hint
> + * about the accessed memory regions. It is optional to specify, which is
> + * fortunate as it cannot be specified precisely with bindless access anyway.
> + * But where possible, it's probably a good idea for userspace to include these
> + * hints, forwarded to the firmware.
> + */
> +struct drm_asahi_attachment {
> +	/** @pointer: Base address of the attachment */
> +	__u64 pointer;
> +
> +	/** @size: Size of the attachment in bytes */
> +	__u64 size;
> +
> +	/** @pad: MBZ */
> +	__u32 pad;
> +
> +	/** @flags: MBZ */
> +	__u32 flags;
> +};
> +
> +enum drm_asahi_render_flags {
> +	/**
> +	 * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
> +	 * memory.
> +	 */
> +	DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0),
> +
> +	/**
> +	 * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
> +	 * This must be set when clearing render targets.
> +	 */
> +	DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1),
> +
> +	/**
> +	 * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
> +	 * cluster (on multicluster GPUs)
> +	 *
> +	 * This harms performance but can workaround certain sync/coherency
> +	 * bugs, and therefore is useful for debugging.
> +	 */
> +	DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2),
> +
> +	/**
> +	 * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
> +	 *
> +	 * Graphics specifications contain two alternate formulas for depth
> +	 * bias, a float formula used with floating-point depth buffers and an
> +	 * integer formula using with unorm depth buffers. This flag specifies
> +	 * that the integer formula should be used. If omitted, the float
> +	 * formula is used instead.
> +	 *
> +	 * This corresponds to bit 18 of the relevant hardware control register,
> +	 * so we match that here for efficiency.
> +	 */
> +	DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18),
> +};
> +
> +/**
> + * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
> + *
> + * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit.
> + * There are three hardware registers for each field respectively for loads,
> + * stores, and partial renders. In practice, it makes sense to set all to the
> + * same values, except in exceptional cases not yet implemented in userspace, so
> + * we do not duplicate here for simplicity/efficiency.
> + */
> +struct drm_asahi_zls_buffer {
> +	/** @base: Base address of the buffer */
> +	__u64 base;
> +
> +	/**
> +	 * @comp_base: If the load buffer is compressed, address of the
> +	 * compression metadata section.
> +	 */
> +	__u64 comp_base;
> +
> +	/**
> +	 * @stride: If layered rendering is enabled, the number of bytes
> +	 * between each layer of the buffer.
> +	 */
> +	__u32 stride;
> +
> +	/**
> +	 * @comp_stride: If layered rendering is enabled, the number of bytes
> +	 * between each layer of the compression metadata.
> +	 */
> +	__u32 comp_stride;
> +};
> +
> +/**
> + * struct drm_asahi_timestamp - Describe a timestamp write.
> + *
> + * The firmware can optionally write the GPU timestamp at render pass
> + * granularities, but it needs to be mapped specially via
> + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
> + * write as a handle-offset pair, rather than a GPU address like normal.
> + */
> +struct drm_asahi_timestamp {
> +	/**
> +	 * @handle: Handle of the timestamp buffer, or 0 to skip this
> +	 * timestamp. If nonzero, this must equal the value returned in
> +	 * drm_asahi_gem_bind_object::object_handle.
> +	 */
> +	__u32 handle;
> +
> +	/** @offset: Offset to write into the timestamp buffer */
> +	__u32 offset;
> +};
> +
> +/**
> + * struct drm_asahi_timestamps - Describe timestamp writes.
> + *
> + * Each operation that can be timestamped, can be timestamped at the start and
> + * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
> + * together into drm_asahi_timestamps.
> + */
> +struct drm_asahi_timestamps {
> +	/** @start: Timestamp recorded at the start of the operation */
> +	struct drm_asahi_timestamp start;
> +
> +	/** @end: Timestamp recorded at the end of the operation */
> +	struct drm_asahi_timestamp end;
> +};
> +
> +/**
> + * struct drm_asahi_helper_program - Describe helper program configuration.
> + *
> + * The helper program is a compute-like kernel required for various hardware
> + * functionality. Its most important role is dynamically allocating
> + * scratch/stack memory for individual subgroups, by partitioning a static
> + * allocation shared for the whole device. It is supplied by userspace via
> + * drm_asahi_helper_program and internally dispatched by the hardware as needed.
> + */
> +struct drm_asahi_helper_program {
> +	/**
> +	 * @binary: USC address to the helper program binary. This is a tagged
> +	 * pointer with configuration in the bottom bits.
> +	 */
> +	__u32 binary;
> +
> +	/** @cfg: Configuration bits for the helper program. */
> +	__u32 cfg;
> +
> +	/**
> +	 * @data: Data passed to the helper program. This value is not
> +	 * interpreted by the kernel, firmware, or hardware in any way. It is
> +	 * simply a sideband for userspace, set with the submit ioctl and read
> +	 * via special registers inside the helper program.
> +	 *
> +	 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
> +	 * actual arguments, which presumably don't fit in 64-bits.
> +	 */
> +	__u64 data;
> +};
> +
> +/**
> + * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
> + *
> + * The background and end-of-tile programs are dispatched by the hardware at the
> + * beginning and end of rendering. As the hardware "tilebuffer" is simply local
> + * memory, these programs are necessary to implement API-level render targets.
> + * The fragment-like background program is responsible for loading either the
> + * clear colour or the existing render target contents, while the compute-like
> + * end-of-tile program stores the tilebuffer contents to memory.
> + */
> +struct drm_asahi_bg_eot {
> +	/**
> +	 * @usc: USC address of the hardware USC words binding resources
> +	 * (including images and uniforms) and the program itself. Note this is
> +	 * an additional layer of indirection compared to the helper program,
> +	 * avoiding the need for a sideband for data. This is a tagged pointer
> +	 * with additional configuration in the bottom bits.
> +	 */
> +	__u32 usc;
> +
> +	/**
> +	 * @rsrc_spec: Resource specifier for the program. This is a packed
> +	 * hardware data structure describing the required number of registers,
> +	 * uniforms, bound textures, and bound samplers.
> +	 */
> +	__u32 rsrc_spec;
> +};
> +
> +/**
> + * struct drm_asahi_cmd_render - Command to submit 3D
> + *
> + * This command submits a single render pass. The hardware control stream may
> + * include many draws and subpasses, but within the command, the framebuffer
> + * dimensions and attachments are fixed.
> + *
> + * The hardware requires the firmware to set a large number of Control Registers
> + * setting up state at render pass granularity before each command rendering 3D.
> + * The firmware bundles this state into data structures. Unfortunately, we
> + * cannot expose either any of that directly to userspace, because the
> + * kernel-firmware ABI is not stable. Although we can guarantee the firmware
> + * updates in tandem with the kernel, we cannot break old userspace when
> + * upgrading the firmware and kernel. Therefore, we need to abstract well the
> + * data structures to avoid tying our hands with future firmwares.
> + *
> + * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
> + * control registers, marshalled via the firmware interface.
> + *
> + * The framebuffer/tilebuffer dimensions are also specified here. In addition to
> + * being passed to the firmware/hardware, the kernel requires these dimensions
> + * to calculate various essential tiling-related data structures. It is
> + * unfortunate that our submits are heavier than on vendors with saner
> + * hardware-software interfaces. The upshot is all of this information is
> + * readily available to userspace with all current APIs.
> + *
> + * It looks odd - but it's not overly burdensome and it ensures we can remain
> + * compatible with old userspace.
> + */
> +struct drm_asahi_cmd_render {
> +	/** @flags: Combination of drm_asahi_render_flags flags. */
> +	__u32 flags;
> +
> +	/**
> +	 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
> +	 * depth/stencil width/height, which may differ from the framebuffer
> +	 * width/height.
> +	 */
> +	__u32 isp_zls_pixels;
> +
> +	/**
> +	 * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU
> +	 * address to the beginning of the VDM control stream.
> +	 */
> +	__u64 vdm_ctrl_stream_base;
> +
> +	/** @vertex_helper: Helper program used for the vertex shader */
> +	struct drm_asahi_helper_program vertex_helper;
> +
> +	/** @fragment_helper: Helper program used for the fragment shader */
> +	struct drm_asahi_helper_program fragment_helper;
> +
> +	/**
> +	 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
> +	 * array of scissor descriptors indexed in the render pass.
> +	 */
> +	__u64 isp_scissor_base;
> +
> +	/**
> +	 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
> +	 * array of depth bias values indexed in the render pass.
> +	 */
> +	__u64 isp_dbias_base;
> +
> +	/**
> +	 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
> +	 * array of occlusion query results written by the render pass.
> +	 */
> +	__u64 isp_oclqry_base;
> +
> +	/** @depth: Depth buffer */
> +	struct drm_asahi_zls_buffer depth;
> +
> +	/** @stencil: Stencil buffer */
> +	struct drm_asahi_zls_buffer stencil;
> +
> +	/** @zls_ctrl: ZLS_CTRL register value */
> +	__u64 zls_ctrl;
> +
> +	/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
> +	__u64 ppp_multisamplectl;
> +
> +	/**
> +	 * @sampler_heap: Base address of the sampler heap. This heap is used
> +	 * for both vertex shaders and fragment shaders. The registers are
> +	 * per-stage, but there is no known use case for separate heaps.
> +	 */
> +	__u64 sampler_heap;
> +
> +	/** @ppp_ctrl: PPP_CTRL register value */
> +	__u32 ppp_ctrl;
> +
> +	/** @width_px: Framebuffer width in pixels */
> +	__u16 width_px;
> +
> +	/** @height_px: Framebuffer height in pixels */
> +	__u16 height_px;
> +
> +	/** @layers: Number of layers in the framebuffer */
> +	__u16 layers;
> +
> +	/** @sampler_count: Number of samplers in the sampler heap. */
> +	__u16 sampler_count;
> +
> +	/** @utile_width_px: Width of a logical tilebuffer tile in pixels */
> +	__u8 utile_width_px;
> +
> +	/** @utile_height_px: Height of a logical tilebuffer tile in pixels */
> +	__u8 utile_height_px;
> +
> +	/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
> +	__u8 samples;
> +
> +	/** @sample_size_B: # of bytes in the tilebuffer required per sample. */
> +	__u8 sample_size_B;
> +
> +	/**
> +	 * @isp_merge_upper_x: 32-bit float used in the hardware triangle
> +	 * merging. Calculate as: tan(60 deg) * width.
> +	 *
> +	 * Making these values UAPI avoids requiring floating-point calculations
> +	 * in the kernel in the hot path.
> +	 */
> +	__u32 isp_merge_upper_x;
> +
> +	/**
> +	 * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height.
> +	 * See @isp_merge_upper_x.
> +	 */
> +	__u32 isp_merge_upper_y;
> +
> +	/** @bg: Background program run for each tile at the start */
> +	struct drm_asahi_bg_eot bg;
> +
> +	/** @eot: End-of-tile program ran for each tile at the end */
> +	struct drm_asahi_bg_eot eot;
> +
> +	/**
> +	 * @partial_bg: Background program ran at the start of each tile when
> +	 * resuming the render pass during a partial render.
> +	 */
> +	struct drm_asahi_bg_eot partial_bg;
> +
> +	/**
> +	 * @partial_eot: End-of-tile program ran at the end of each tile when
> +	 * pausing the render pass during a partial render.
> +	 */
> +	struct drm_asahi_bg_eot partial_eot;
> +
> +	/**
> +	 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
> +	 * buffer clear value, encoded in the depth buffer's format: either a
> +	 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
> +	 */
> +	__u32 isp_bgobjdepth;
> +
> +	/**
> +	 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
> +	 * contain the stencil buffer clear value.
> +	 */
> +	__u32 isp_bgobjvals;
> +
> +	/** @ts_vtx: Timestamps for the vertex portion of the render */
> +	struct drm_asahi_timestamps ts_vtx;
> +
> +	/** @ts_frag: Timestamps for the fragment portion of the render */
> +	struct drm_asahi_timestamps ts_frag;
> +};
> +
> +/**
> + * struct drm_asahi_cmd_compute - Command to submit compute
> + *
> + * This command submits a control stream consisting of compute dispatches. There
> + * is essentially no limit on how many compute dispatches may be included in a
> + * single compute command, although timestamps are at command granularity.
> + */
> +struct drm_asahi_cmd_compute {
> +	/** @flags: MBZ */
> +	__u32 flags;
> +
> +	/** @sampler_count: Number of samplers in the sampler heap. */
> +	__u32 sampler_count;
> +
> +	/**
> +	 * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU
> +	 * address to the beginning of the CDM control stream.
> +	 */
> +	__u64 cdm_ctrl_stream_base;
> +
> +	/**
> +	 * @cdm_ctrl_stream_end: GPU base address to the end of the hardware
> +	 * control stream. Note this only considers the first contiguous segment
> +	 * of the control stream, as the stream might jump elsewhere.
> +	 */
> +	__u64 cdm_ctrl_stream_end;
> +
> +	/** @sampler_heap: Base address of the sampler heap. */
> +	__u64 sampler_heap;
> +
> +	/** @helper: Helper program used for this compute shader */
> +	struct drm_asahi_helper_program helper;
> +
> +	/** @ts: Timestamps for the compute command */
> +	struct drm_asahi_timestamps ts;
> +};
> +
> +/**
> + * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
> + */
> +struct drm_asahi_get_time {
> +	/** @flags: MBZ. */
> +	__u64 flags;
> +
> +	/** @gpu_timestamp: On return, the current GPU timestamp */
> +	__u64 gpu_timestamp;
> +};
> +
> +/**
> + * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
> + * @__access: Access type. Must be R, W or RW.
> + * @__id: One of the DRM_ASAHI_xxx id.
> + * @__type: Suffix of the type being passed to the IOCTL.
> + *
> + * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
> + * values instead.
> + *
> + * Return: An IOCTL number to be passed to ioctl() from userspace.
> + */
> +#define DRM_IOCTL_ASAHI(__access, __id, __type) \
> +	DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
> +			   struct drm_asahi_ ## __type)
> +
> +/* Note: this is an enum so that it can be resolved by Rust bindgen. */
> +enum {
> +	DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
> +	DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
> +	DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
> +	DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
> +	DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
> +	DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
> +	DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
> +	DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
> +	DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
> +	DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
> +	DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
> +};
> +
> +#if defined(__cplusplus)
> +}
> +#endif
> +
> +#endif /* _ASAHI_DRM_H_ */
> 
> ---
> base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
> change-id: 20250307-agx-uapi-930579437f19
> 
> Best regards,
> -- 
> Alyssa Rosenzweig <alyssa at rosenzweig.io>
> 

-- 
Simona Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From florin.leotescu at oss.nxp.com  Fri Mar 21 07:33:05 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Fri, 21 Mar 2025 16:33:05 +0200
Subject: [PATCH v6 0/3] Add OF support for Microchip emc2305 fan controller
Message-ID: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

This patch series add initial OF support for Microchip emc2305 fan controller.

Changes since v5:
- Corrected blank line as recommended by Krzysztof Kozlowski.
- Removed pwms property from required list as Guenter Roeck suggested.
  The pwms should not be mandatory as the driver works fine with defaults settings.

Changes since v4:
- Corrected quotes to have a consistent definition.
- Corrected DTS coding style as recommended by Krzysztof Kozlowski.
- Updated pwms phandle to include pwm frequency, pwm polarity and pwm output,
  as recommended by Guenter Roeck and skipped the pwm channel as recommended by Krzysztof Kozlowski.
- Documented the pwms args in #pwm-cells description.
- Updated pwms phandle in dt-binding example to include pwm frequency and 
  use PWM_POLARITY_INVERTED macro to inverse the PWM polarity. 

Changes since v3:
- Removed thermal_cooling_device_register_fail label since is no longer needed
  and replaced goto with imediate return, as recommended by Guenter Roeck. 
- Redefined compatible property in dt-binding, as recommended by Frank Li.
- Updated driver of compatible list.
- Renamed node name in the dt-binding example, as recommended by Connor Dooley.
- Corrected dt-binding commit subject.
- Added dt-binding fan descriptions and $ref to fan schema, 
  as Connor Dooley & Krzysztof Kozlowski recommended.
  Used similar as on maxim,max6639 and nuvoton,nct7363. 
- Updated dt-binding example.

Changes since v2:
- Removed the introduction of new properties for now and we only 
  enable basic OF support.
- Link to previous version: 
  https://lore.kernel.org/linux-arm-kernel/20250219133221.2641041-3-florin.leotescu at oss.nxp.com/T/


Florin Leotescu (3):
  dt-bindings: hwmon: Add Microchip emc2305 support
  hwmon: emc2305: Add OF support
  hwmon: emc2305: Use devm_thermal_of_cooling_device_register

 .../bindings/hwmon/microchip,emc2305.yaml     | 110 ++++++++++++++++++
 drivers/hwmon/emc2305.c                       |  38 ++----
 2 files changed, 120 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

-- 
2.34.1



From florin.leotescu at oss.nxp.com  Fri Mar 21 07:33:06 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Fri, 21 Mar 2025 16:33:06 +0200
Subject: [PATCH v6 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250321143308.4008623-2-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce yaml schema for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/hwmon/microchip,emc2305.yaml     | 110 ++++++++++++++++++
 1 file changed, 110 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
new file mode 100644
index 000000000000..79081c116274
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip EMC2305 SMBus compliant PWM fan controller
+
+maintainers:
+  - Michael Shych <michaelsh at nvidia.com>
+
+description:
+  Microchip EMC2301/2/3/5 pwm controller which supports
+  up to five programmable fan control circuits.
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - microchip,emc2305
+      - items:
+          - enum:
+              - microchip,emc2303
+              - microchip,emc2302
+              - microchip,emc2301
+          - const: microchip,emc2305
+
+  reg:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  '#pwm-cells':
+    const: 3
+    description: |
+      Number of cells in a PWM specifier.
+      - cell 0: The PWM frequency
+      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
+      - cell 2: The PWM output config:
+           - 0 (Open-Drain)
+           - 1 (Push-Pull)
+
+patternProperties:
+  '^fan@[0-4]$':
+    $ref: fan-common.yaml#
+    unevaluatedProperties: false
+    properties:
+      reg:
+        description:
+          The fan number used to determine the associated PWM channel.
+
+    required:
+      - reg
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/pwm/pwm.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        fan_controller: fan-controller at 2f {
+            compatible = "microchip,emc2305";
+            reg = <0x2f>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            #pwm-cells = <3>;
+
+            fan at 0 {
+                reg = <0x0>;
+                pwms = <&fan_controller 26000 PWM_POLARITY_INVERTED 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 1 {
+                reg = <0x1>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 2 {
+                reg = <0x2>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 3 {
+                reg = <0x3>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+
+            fan at 4 {
+                reg = <0x4>;
+                pwms = <&fan_controller 26000 0 1>;
+                #cooling-cells = <2>;
+            };
+        };
+    };
+...
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Fri Mar 21 07:33:08 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Fri, 21 Mar 2025 16:33:08 +0200
Subject: [PATCH v6 3/3] hwmon: emc2305: Use devm_thermal_of_cooling_device_register
In-Reply-To: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250321143308.4008623-4-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Prepare the emc2305 driver to use configuration from Device Tree nodes.
Switch to devm_thermal_of_cooling_device_register to simplify the
cleanup procedure, allowing the removal of emc2305_unset_tz and
emc2305_remove, which are no longer needed.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/hwmon/emc2305.c | 33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index f8a4c76fcadd..234c54956a4b 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -112,8 +112,6 @@ static char *emc2305_fan_name[] = {
 	"emc2305_fan5",
 };
 
-static void emc2305_unset_tz(struct device *dev);
-
 static int emc2305_get_max_channel(const struct emc2305_data *data)
 {
 	return data->pwm_num;
@@ -293,8 +291,9 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
 	pwm = data->pwm_min[cdev_idx];
 
 	data->cdev_data[cdev_idx].cdev =
-		thermal_cooling_device_register(emc2305_fan_name[idx], data,
-						&emc2305_cooling_ops);
+		devm_thermal_of_cooling_device_register(dev, dev->of_node,
+							emc2305_fan_name[idx], data,
+							&emc2305_cooling_ops);
 
 	if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
 		dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
@@ -332,24 +331,9 @@ static int emc2305_set_tz(struct device *dev)
 	for (i = 0; i < data->pwm_num; i++) {
 		ret = emc2305_set_single_tz(dev, i + 1);
 		if (ret)
-			goto thermal_cooling_device_register_fail;
+			return ret;
 	}
 	return 0;
-
-thermal_cooling_device_register_fail:
-	emc2305_unset_tz(dev);
-	return ret;
-}
-
-static void emc2305_unset_tz(struct device *dev)
-{
-	struct emc2305_data *data = dev_get_drvdata(dev);
-	int i;
-
-	/* Unregister cooling device. */
-	for (i = 0; i < EMC2305_PWM_MAX; i++)
-		if (data->cdev_data[i].cdev)
-			thermal_cooling_device_unregister(data->cdev_data[i].cdev);
 }
 
 static umode_t
@@ -599,14 +583,6 @@ static int emc2305_probe(struct i2c_client *client)
 	return 0;
 }
 
-static void emc2305_remove(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-
-	if (IS_REACHABLE(CONFIG_THERMAL))
-		emc2305_unset_tz(dev);
-}
-
 static const struct of_device_id of_emc2305_match_table[] = {
 	{ .compatible = "microchip,emc2305", },
 	{},
@@ -619,7 +595,6 @@ static struct i2c_driver emc2305_driver = {
 		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
-	.remove	  = emc2305_remove,
 	.id_table = emc2305_ids,
 };
 
-- 
2.34.1



From florin.leotescu at oss.nxp.com  Fri Mar 21 07:33:07 2025
From: florin.leotescu at oss.nxp.com (florin.leotescu at oss.nxp.com)
Date: Fri, 21 Mar 2025 16:33:07 +0200
Subject: [PATCH v6 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
Message-ID: <20250321143308.4008623-3-florin.leotescu@oss.nxp.com>

From: Florin Leotescu <florin.leotescu at nxp.com>

Introduce OF support for Microchip emc2305 pwm fan controller.

Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
---
 drivers/hwmon/emc2305.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 4d39fbd83769..f8a4c76fcadd 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -607,9 +607,16 @@ static void emc2305_remove(struct i2c_client *client)
 		emc2305_unset_tz(dev);
 }
 
+static const struct of_device_id of_emc2305_match_table[] = {
+	{ .compatible = "microchip,emc2305", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_emc2305_match_table);
+
 static struct i2c_driver emc2305_driver = {
 	.driver = {
 		.name = "emc2305",
+		.of_match_table = of_emc2305_match_table,
 	},
 	.probe = emc2305_probe,
 	.remove	  = emc2305_remove,
-- 
2.34.1



From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 07:31:55 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 16:31:55 +0200
Subject: [PATCH v3 05/10] phy: phy-snps-eusb2: split phy init code
In-Reply-To: <20250321135854.1431375-6-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-6-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <7v3xkvldjnpqakrndwl6wb6vdsl3idbirlhddpqhwtt3ddadzr@kjafi3updcsb>

On Fri, Mar 21, 2025 at 03:58:49PM +0200, Ivaylo Ivanov wrote:
> The current phy init consists of hardware power-up, as well as
> QCOM-specific eUSB2 init code. Split it into two parts, to make room
> for such non-QCOM init code.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  drivers/phy/phy-snps-eusb2.c | 96 +++++++++++++++++++++++-------------
>  1 file changed, 63 insertions(+), 33 deletions(-)
> 
> @@ -378,6 +401,11 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>  	if (!phy)
>  		return -ENOMEM;
>  
> +	drv_data = of_device_get_match_data(dev);
> +	if (!drv_data)
> +		return -EINVAL;
> +	phy->data = drv_data;

Nit and completely bikeshedding, but this looks simpler:

	phy->data = of_device_get_match_data(dev);
	if (!phy->data)
		return -EINVAL;


Anyway:

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>


> +
>  	phy->base = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(phy->base))
>  		return PTR_ERR(phy->base);
> @@ -424,8 +452,10 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
> -	{ .compatible = "qcom,sm8550-snps-eusb2-phy", },
> -	{ },
> +	{
> +		.compatible = "qcom,sm8550-snps-eusb2-phy",
> +		.data = &sm8550_snps_eusb2_phy,
> +	}, { },
>  };
>  MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
>  
> -- 
> 2.43.0
> 

-- 
With best wishes
Dmitry


From dan.carpenter at linaro.org  Fri Mar 21 07:32:53 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 17:32:53 +0300
Subject: [PATCH] KVM: selftests: Fix a couple "prio" signedness bugs
Message-ID: <ca579322-dc9d-4300-bd74-7e9240e930c7@stanley.mountain>

There is an assert which relies on "prio" to be signed.

	GUEST_ASSERT(prio >= 0);

Change the type from uint32_t to int.

Fixes: 728fcc46d2c2 ("KVM: selftests: aarch64: Add test for restoring active IRQs")
Fixes: 0ad3ff4a6adc ("KVM: selftests: aarch64: Add preemption tests in vgic_irq")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
---
 tools/testing/selftests/kvm/arm64/vgic_irq.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
index f4ac28d53747..e89c0fc5eef3 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
@@ -294,7 +294,8 @@ static void guest_restore_active(struct test_args *args,
 		uint32_t first_intid, uint32_t num,
 		kvm_inject_cmd cmd)
 {
-	uint32_t prio, intid, ap1r;
+	uint32_t intid, ap1r;
+	int prio;
 	int i;
 
 	/*
@@ -362,7 +363,8 @@ static void test_inject_preemption(struct test_args *args,
 		uint32_t first_intid, int num,
 		kvm_inject_cmd cmd)
 {
-	uint32_t intid, prio, step = KVM_PRIO_STEPS;
+	uint32_t intid, step = KVM_PRIO_STEPS;
+	int prio;
 	int i;
 
 	/* Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs
-- 
2.47.2



From neil.armstrong at linaro.org  Fri Mar 21 07:34:57 2025
From: neil.armstrong at linaro.org (neil.armstrong at linaro.org)
Date: Fri, 21 Mar 2025 15:34:57 +0100
Subject: [PATCH v3 05/10] phy: phy-snps-eusb2: split phy init code
In-Reply-To: <7v3xkvldjnpqakrndwl6wb6vdsl3idbirlhddpqhwtt3ddadzr@kjafi3updcsb>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-6-ivo.ivanov.ivanov1@gmail.com>
 <7v3xkvldjnpqakrndwl6wb6vdsl3idbirlhddpqhwtt3ddadzr@kjafi3updcsb>
Message-ID: <2b572981-7e63-4052-8186-4ba17f530cca@linaro.org>

On 21/03/2025 15:31, Dmitry Baryshkov wrote:
> On Fri, Mar 21, 2025 at 03:58:49PM +0200, Ivaylo Ivanov wrote:
>> The current phy init consists of hardware power-up, as well as
>> QCOM-specific eUSB2 init code. Split it into two parts, to make room
>> for such non-QCOM init code.
>>
>> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
>> ---
>>   drivers/phy/phy-snps-eusb2.c | 96 +++++++++++++++++++++++-------------
>>   1 file changed, 63 insertions(+), 33 deletions(-)
>>
>> @@ -378,6 +401,11 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>>   	if (!phy)
>>   		return -ENOMEM;
>>   
>> +	drv_data = of_device_get_match_data(dev);
>> +	if (!drv_data)
>> +		return -EINVAL;
>> +	phy->data = drv_data;
> 
> Nit and completely bikeshedding, but this looks simpler:
> 
> 	phy->data = of_device_get_match_data(dev);
> 	if (!phy->data)
> 		return -EINVAL;

Please use device_get_match_data() instead.

Neil

> 
> 
> Anyway:
> 
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>
> 
> 
>> +
>>   	phy->base = devm_platform_ioremap_resource(pdev, 0);
>>   	if (IS_ERR(phy->base))
>>   		return PTR_ERR(phy->base);
>> @@ -424,8 +452,10 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
>>   }
>>   
>>   static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
>> -	{ .compatible = "qcom,sm8550-snps-eusb2-phy", },
>> -	{ },
>> +	{
>> +		.compatible = "qcom,sm8550-snps-eusb2-phy",
>> +		.data = &sm8550_snps_eusb2_phy,
>> +	}, { },
>>   };
>>   MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
>>   
>> -- 
>> 2.43.0
>>
> 



From dan.carpenter at linaro.org  Fri Mar 21 07:35:35 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 17:35:35 +0300
Subject: [PATCH] wifi: mt76: mt7996: remove duplicate check in
 mt7996_mcu_sta_mld_setup_tlv()
Message-ID: <fde7246b-08a2-4c2f-b2dc-c3fd0e6b300b@stanley.mountain>

The "msta_link" pointer has two NULL checks.  Delete the second check.

Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index ddd555942c73..03539e20f5c5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2242,9 +2242,6 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 		if (!link)
 			continue;
 
-		if (!msta_link)
-			continue;
-
 		mld_setup_link->wcid = cpu_to_le16(msta_link->wcid.idx);
 		mld_setup_link->bss_idx = link->mt76.idx;
 		mld_setup_link++;
-- 
2.47.2



From dan.carpenter at linaro.org  Fri Mar 21 07:35:40 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 17:35:40 +0300
Subject: [PATCH next] wifi: mt76: mt7925: Fix logical vs bitwise typo
Message-ID: <d323a443-4e81-4064-8563-b62274b53ef4@stanley.mountain>

This was supposed to be & instead of &&.

Fixes: f0317215b367 ("wifi: mt76: mt7925: add EHT control support based on the CLC data")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/net/wireless/mediatek/mt76/mt7925/init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
index 63cb08f4d87c..79639be0d29a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
@@ -89,7 +89,7 @@ void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2)
 		}
 
 		/* Check the last one */
-		if (rule->flag && BIT(0))
+		if (rule->flag & BIT(0))
 			break;
 
 		pos += sizeof(*rule);
-- 
2.47.2



From dan.carpenter at linaro.org  Fri Mar 21 07:36:14 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 17:36:14 +0300
Subject: [PATCH next] phy: rockchip-samsung-dcphy: Add missing assignment
Message-ID: <e64265a4-9543-4728-a49f-ea910fccef7c@stanley.mountain>

The "ret = " was accidentally dropped so the error handling doesn't work.

Fixes: b2a1a2ae7818 ("phy: rockchip: Add Samsung MIPI D-/C-PHY driver")
Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index 08c78c1bafc9..28a052e17366 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -1653,7 +1653,7 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
 		return ret;
 	}
 
-	clk_prepare_enable(samsung->ref_clk);
+	ret = clk_prepare_enable(samsung->ref_clk);
 	if (ret) {
 		dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret);
 		clk_disable_unprepare(samsung->pclk);
-- 
2.47.2



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:40:14 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:40:14 +0200
Subject: [PATCH v2 0/2] usb: dwc3: exynos: add support for Exynos2200 variant
Message-ID: <20250321144016.1434848-1-ivo.ivanov.ivanov1@gmail.com>

Hey folks,

This patchset adds support for the Exynos 2200 to the exynos-dwc3 glue
code. It takes one clock - the link_aclk, and the dwc3 refclk is passed
to the dwc3 subnode, as with gs101.

Best regards,
Ivaylo

Changes in v2:
- add sob and r-b tags
- drop minitems from binding patch

Ivaylo Ivanov (2):
  dt-bindings: usb: samsung,exynos-dwc3: add exynos2200 compatible
  usb: dwc3: exynos: add support for Exynos2200 variant

 .../bindings/usb/samsung,exynos-dwc3.yaml          | 14 ++++++++++++++
 drivers/usb/dwc3/dwc3-exynos.c                     |  9 +++++++++
 2 files changed, 23 insertions(+)

-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:40:15 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:40:15 +0200
Subject: [PATCH v2 1/2] dt-bindings: usb: samsung,exynos-dwc3: add exynos2200 compatible
In-Reply-To: <20250321144016.1434848-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321144016.1434848-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321144016.1434848-2-ivo.ivanov.ivanov1@gmail.com>

The Exynos2200 SoC has a DWC3 compatible USB controller and can reuse
the existing Exynos glue. Update the dt schema to include the
samsung,exynos2200-dwusb3 compatible for it.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/usb/samsung,exynos-dwc3.yaml          | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
index 2b3430ceb..679088c91 100644
--- a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
@@ -13,6 +13,7 @@ properties:
   compatible:
     enum:
       - google,gs101-dwusb3
+      - samsung,exynos2200-dwusb3
       - samsung,exynos5250-dwusb3
       - samsung,exynos5433-dwusb3
       - samsung,exynos7-dwusb3
@@ -73,6 +74,19 @@ allOf:
             - const: link_aclk
             - const: link_pclk
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos2200-dwusb3
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names:
+          items:
+            - const: link_aclk
+
   - if:
       properties:
         compatible:
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:40:16 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:40:16 +0200
Subject: [PATCH v2 2/2] usb: dwc3: exynos: add support for Exynos2200 variant
In-Reply-To: <20250321144016.1434848-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321144016.1434848-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321144016.1434848-3-ivo.ivanov.ivanov1@gmail.com>

Add Exynos2200 compatible string and associated driver data. This SoC
requires a Link interface AXI clock.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
---
 drivers/usb/dwc3/dwc3-exynos.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index f5d963fae..aa22265c7 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -145,6 +145,12 @@ static void dwc3_exynos_remove(struct platform_device *pdev)
 	regulator_disable(exynos->vdd10);
 }
 
+static const struct dwc3_exynos_driverdata exynos2200_drvdata = {
+	.clk_names = { "link_aclk" },
+	.num_clks = 1,
+	.suspend_clk_idx = -1,
+};
+
 static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
 	.clk_names = { "usbdrd30" },
 	.num_clks = 1,
@@ -177,6 +183,9 @@ static const struct dwc3_exynos_driverdata gs101_drvdata = {
 
 static const struct of_device_id exynos_dwc3_match[] = {
 	{
+		.compatible = "samsung,exynos2200-dwusb3",
+		.data = &exynos2200_drvdata,
+	}, {
 		.compatible = "samsung,exynos5250-dwusb3",
 		.data = &exynos5250_drvdata,
 	}, {
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:48:01 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:48:01 +0200
Subject: [PATCH v3 0/2] usb: dwc3: exynos: add support for Exynos2200 variant
Message-ID: <20250321144804.1435502-1-ivo.ivanov.ivanov1@gmail.com>

Hey folks,

This patchset adds support for the Exynos 2200 to the exynos-dwc3 glue
code. It takes one clock - the link_aclk, and the dwc3 refclk is passed
to the dwc3 subnode, as with gs101.

Best regards,
Ivaylo

Changes in v3:
- fix partial r-b tag from the dt bindings commit message

Changes in v2:
- add sob and r-b tags
- drop minitems from binding patch

Ivaylo Ivanov (2):
  dt-bindings: usb: samsung,exynos-dwc3: add exynos2200 compatible
  usb: dwc3: exynos: add support for Exynos2200 variant

 .../bindings/usb/samsung,exynos-dwc3.yaml          | 14 ++++++++++++++
 drivers/usb/dwc3/dwc3-exynos.c                     |  9 +++++++++
 2 files changed, 23 insertions(+)

-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:48:02 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:48:02 +0200
Subject: [PATCH v3 1/2] dt-bindings: usb: samsung,exynos-dwc3: add exynos2200 compatible
In-Reply-To: <20250321144804.1435502-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321144804.1435502-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321144804.1435502-2-ivo.ivanov.ivanov1@gmail.com>

The Exynos2200 SoC has a DWC3 compatible USB controller and can reuse
the existing Exynos glue. Update the dt schema to include the
samsung,exynos2200-dwusb3 compatible for it.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/usb/samsung,exynos-dwc3.yaml          | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
index 2b3430ceb..679088c91 100644
--- a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
@@ -13,6 +13,7 @@ properties:
   compatible:
     enum:
       - google,gs101-dwusb3
+      - samsung,exynos2200-dwusb3
       - samsung,exynos5250-dwusb3
       - samsung,exynos5433-dwusb3
       - samsung,exynos7-dwusb3
@@ -73,6 +74,19 @@ allOf:
             - const: link_aclk
             - const: link_pclk
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos2200-dwusb3
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names:
+          items:
+            - const: link_aclk
+
   - if:
       properties:
         compatible:
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:44 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:44 +0200
Subject: [PATCH v3 00/10] phy: samsung: add Exynos2200 SNPS eUSB2 driver
Message-ID: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>

Hey folks,

This patchset adds Exynos2200 support to the existing eUSB2 phy driver,
as well as USBDRD support for that SoC.

The SoC features the same (as far as I can tell from comparing code)
USBDRD 3.2 4nm block that Exynos2400 has, hence the common denominator.
It consists of a SEC USB link controller, Synopsys eUSB2 and Synopsys
USBDP combophy, which are independent underlying hardware blocks of
the USBDRD controller.

In the vendor kernel, everything is handled in the usbdrd controller
driver, with helpers for underlying hardware block functions outside it.
Clocks and regulators are specified and enabled in one node, which makes
it difficult to separate what clocks and regulators go where without
access to schematics or TRMs. The following gates are defined for USB:

CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_USBSUBCTL_APB_PCLK
CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_USBDPPHY_CTRL_PCLK
CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_USBDPPHY_TCA_APB_CLK

CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_USBLINK_ACLK
CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_USB32DRD_REF_CLK_40

CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_EUSB_CTRL_PCLK
CLK_BLK_HSI0_UID_USB32DRD_IPCLKPORT_I_EUSB_APB_CLK
CLK_BLK_HSI0_UID_AS_APB_EUSBPHY_HSI0_IPCLKPORT_PCLKM
CLK_BLK_HSI0_UID_RSTNSYNC_CLK_HSI0_EUSB_IPCLKPORT_CLK

The vendor kernel specifies 4 regulators, 2 of which are for eUSB
and the other 2 for the repeater. The rest of the PHYs and the dwc3
controller are on a single power domain (hsi0), so they're most likely
sharing power rails.

As Qualcomm is also using the eUSB2 IP, the approach taken here is to
rename the driver so that it can be used by other SoC vendors as well
while keeping compatibles SoC-vendor prefixed (different vendors have
different implementations of the IP with different register maps),
add support for exynos2200 in it and implement support for exynos2200
in the existing exynos5-usbdrd driver (with link controller init).

A new USBDP driver will be added later on, so that super-speed can be
configured.

Bindings have been tested:

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4 dt_binding_check DT_SCHEMA_FILES="Documentation/devicetree/bindings/phy/snps,eusb2-phy.yaml"
  CHKDT   ./Documentation/devicetree/bindings
  LINT    ./Documentation/devicetree/bindings
  DTC [C] Documentation/devicetree/bindings/phy/snps,eusb2-phy.example.dtb

Best regards,
Ivaylo

Changes in v3:
USBCON changes:
- drop the driver and introduce it all in existing exynos5-usbdrd driver
EUSB2 changes:
- split changes into multiple commits with clear diff
- add a commit to do table-based lookup for refclk
- clean up here and there
- correct the cover letter according to my new knowledge of how the
  hardware functions
- change commit message of the optional repeater patch

Changes in v2:
USBCON changes:
- drop unused header includes
- sanitize the binding
- proper init and exit power management
- shorten some variables
- unrelax reads and writes
- update commit description
- remodel to take other phys
- drop specified regulators as these are for the repeater
- make the kconfig description better
- general cleanup
EUSB2 changes:
- merge the previous separate driver into the qualcomm one
- drop the previous model of taking usbcon phandle

Ivaylo Ivanov (10):
  dt-bindings: phy: add exynos2200 eusb2 phy support
  dt-bindings: phy: samsung,usb3-drd-phy: add exynos2200 support
  phy: move phy-qcom-snps-eusb2 out of its vendor sub-directory
  phy: phy-snps-eusb2: refactor constructs names
  phy: phy-snps-eusb2: split phy init code
  phy: phy-snps-eusb2: make repeater optional
  phy: phy-snps-eusb2: make reset control optional
  phy: phy-snps-eusb2: refactor reference clock init
  phy: phy-snps-eusb2: add support for exynos2200
  phy: exynos5-usbdrd: support Exynos USBDRD 3.2 4nm controller

 .../bindings/phy/samsung,usb3-drd-phy.yaml    |  38 +-
 ...nps-eusb2-phy.yaml => snps,eusb2-phy.yaml} |  62 +-
 drivers/phy/Kconfig                           |   8 +
 drivers/phy/Makefile                          |   1 +
 drivers/phy/phy-snps-eusb2.c                  | 629 ++++++++++++++++++
 drivers/phy/qualcomm/Kconfig                  |   9 -
 drivers/phy/qualcomm/Makefile                 |   1 -
 drivers/phy/qualcomm/phy-qcom-snps-eusb2.c    | 442 ------------
 drivers/phy/samsung/phy-exynos5-usbdrd.c      | 227 ++++++-
 include/linux/soc/samsung/exynos-regs-pmu.h   |   3 +
 10 files changed, 941 insertions(+), 479 deletions(-)
 rename Documentation/devicetree/bindings/phy/{qcom,snps-eusb2-phy.yaml => snps,eusb2-phy.yaml} (59%)
 create mode 100644 drivers/phy/phy-snps-eusb2.c
 delete mode 100644 drivers/phy/qualcomm/phy-qcom-snps-eusb2.c

-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:45 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:45 +0200
Subject: [PATCH v3 01/10] dt-bindings: phy: add exynos2200 eusb2 phy support
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-2-ivo.ivanov.ivanov1@gmail.com>

As Samsung has been using the same Synopsys eUSB2 IP in Exynos2200,
albeit with a different register layout, rename qcom,snps-eusb2-phy
to snps,eusb2-phy and drop mentions of it being only for Qualcomm SoCs
in the binding description. Document the exynos2200 eUSB2 compatible.
Unlike the currently documented Qualcomm SoCs, it doesn't provide
reset lines for reset control and uses more clocks.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 ...nps-eusb2-phy.yaml => snps,eusb2-phy.yaml} | 62 ++++++++++++++++---
 1 file changed, 54 insertions(+), 8 deletions(-)
 rename Documentation/devicetree/bindings/phy/{qcom,snps-eusb2-phy.yaml => snps,eusb2-phy.yaml} (59%)

diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/snps,eusb2-phy.yaml
similarity index 59%
rename from Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
rename to Documentation/devicetree/bindings/phy/snps,eusb2-phy.yaml
index 142b3c883..87f2c6756 100644
--- a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/snps,eusb2-phy.yaml
@@ -1,16 +1,16 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/phy/qcom,snps-eusb2-phy.yaml#
+$id: http://devicetree.org/schemas/phy/snps,eusb2-phy.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm SNPS eUSB2 phy controller
+title: SNPS eUSB2 phy controller
 
 maintainers:
   - Abel Vesa <abel.vesa at linaro.org>
 
 description:
-  eUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
+  eUSB2 controller supports LS/FS/HS usb connectivity.
 
 properties:
   compatible:
@@ -23,6 +23,7 @@ properties:
               - qcom,x1e80100-snps-eusb2-phy
           - const: qcom,sm8550-snps-eusb2-phy
       - const: qcom,sm8550-snps-eusb2-phy
+      - const: samsung,exynos2200-snps-eusb2-phy
 
   reg:
     maxItems: 1
@@ -31,12 +32,12 @@ properties:
     const: 0
 
   clocks:
-    items:
-      - description: ref
+    minItems: 1
+    maxItems: 3
 
   clock-names:
-    items:
-      - const: ref
+    minItems: 1
+    maxItems: 3
 
   resets:
     maxItems: 1
@@ -62,7 +63,52 @@ required:
   - clock-names
   - vdd-supply
   - vdda12-supply
-  - resets
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sm8550-snps-eusb2-phy
+
+    then:
+      properties:
+        reg:
+          maxItems: 1
+
+        clocks:
+          items:
+            - description: ref
+
+        clock-names:
+          items:
+            - const: ref
+
+      required:
+        - resets
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - samsung,exynos2200-snps-eusb2-phy
+
+    then:
+      properties:
+
+        clocks:
+          items:
+            - description: Reference clock
+            - description: Bus (APB) clock
+            - description: Control clock
+
+        clock-names:
+          items:
+            - const: ref
+            - const: bus
+            - const: ctrl
 
 additionalProperties: false
 
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:46 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:46 +0200
Subject: [PATCH v3 02/10] dt-bindings: phy: samsung,usb3-drd-phy: add exynos2200 support
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-3-ivo.ivanov.ivanov1@gmail.com>

Document support for Exynos2200. As the USBDRD 3.2 4nm controller
consists of Synopsys eUSB2.0 phy and USBDP/SS combophy, which will
be handled by external drivers, define only the bus clocked used
by the link controller.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 .../bindings/phy/samsung,usb3-drd-phy.yaml    | 38 +++++++++++++++++--
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
index 16321cdd4..819e4afe6 100644
--- a/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
@@ -26,6 +26,7 @@ properties:
   compatible:
     enum:
       - google,gs101-usb31drd-phy
+      - samsung,exynos2200-usb32drd-phy
       - samsung,exynos5250-usbdrd-phy
       - samsung,exynos5420-usbdrd-phy
       - samsung,exynos5433-usbdrd-phy
@@ -33,24 +34,32 @@ properties:
       - samsung,exynos850-usbdrd-phy
 
   clocks:
-    minItems: 2
+    minItems: 1
     maxItems: 5
 
   clock-names:
-    minItems: 2
+    minItems: 1
     maxItems: 5
     description: |
-      At least two clocks::
+      Typically two clocks::
         - Main PHY clock (same as USB DRD controller i.e. DWC3 IP clock), used
           for register access.
         - PHY reference clock (usually crystal clock), used for PHY operations,
           associated by phy name. It is used to determine bit values for clock
           settings register.  For Exynos5420 this is given as 'sclk_usbphy30'
-          in the CMU.
+          in the CMU. It's not needed for Exynos2200.
 
   "#phy-cells":
     const: 1
 
+  phys:
+    maxItems: 1
+    description:
+      Phandle to USBDRD-underlying high-speed PHY
+
+  phy-names:
+    const: hs
+
   port:
     $ref: /schemas/graph.yaml#/properties/port
     description:
@@ -137,6 +146,27 @@ allOf:
         - vdda-usbdp-supply
         - vddh-usbdp-supply
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - samsung,exynos2200-usb32drd-phy
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names:
+          items:
+            - const: phy
+        reg:
+          maxItems: 1
+        reg-names:
+          maxItems: 1
+      required:
+        - phys
+        - phy-names
+
   - if:
       properties:
         compatible:
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:47 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:47 +0200
Subject: [PATCH v3 03/10] phy: move phy-qcom-snps-eusb2 out of its vendor sub-directory
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-4-ivo.ivanov.ivanov1@gmail.com>

As not only Qualcomm, but also Samsung is using the Synopsys eUSB2 IP
(albeit with a different register layout) in their newer SoCs, move the
driver out of its vendor sub-directory and rename it to phy-snps-eusb2.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 drivers/phy/Kconfig                                      | 8 ++++++++
 drivers/phy/Makefile                                     | 1 +
 .../{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} | 0
 drivers/phy/qualcomm/Kconfig                             | 9 ---------
 drivers/phy/qualcomm/Makefile                            | 1 -
 5 files changed, 9 insertions(+), 10 deletions(-)
 rename drivers/phy/{qualcomm/phy-qcom-snps-eusb2.c => phy-snps-eusb2.c} (100%)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d58efe99..11c166204 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -43,6 +43,14 @@ config PHY_PISTACHIO_USB
 	help
 	  Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
 
+config PHY_SNPS_EUSB2
+	tristate "SNPS eUSB2 PHY Driver"
+	depends on OF && (ARCH_QCOM || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable support for the USB high-speed SNPS eUSB2 phy on select
+	  SoCs. The PHY is usually paired with a Synopsys DWC3 USB controller.
+
 config PHY_XGENE
 	tristate "APM X-Gene 15Gbps PHY support"
 	depends on HAS_IOMEM && OF && (ARCH_XGENE || COMPILE_TEST)
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e281442ac..c670a8dac 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_PHY_CAN_TRANSCEIVER)	+= phy-can-transceiver.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
+obj-$(CONFIG_PHY_SNPS_EUSB2)		+= phy-snps-eusb2.o
 obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
 obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
 obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
diff --git a/drivers/phy/qualcomm/phy-qcom-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
similarity index 100%
rename from drivers/phy/qualcomm/phy-qcom-snps-eusb2.c
rename to drivers/phy/phy-snps-eusb2.c
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 846f8c995..914547068 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -125,15 +125,6 @@ config PHY_QCOM_QUSB2
 	  PHY which is usually paired with either the ChipIdea or Synopsys DWC3
 	  USB IPs on MSM SOCs.
 
-config PHY_QCOM_SNPS_EUSB2
-	tristate "Qualcomm SNPS eUSB2 PHY Driver"
-	depends on OF && (ARCH_QCOM || COMPILE_TEST)
-	select GENERIC_PHY
-	help
-	  Enable support for the USB high-speed SNPS eUSB2 phy on Qualcomm
-	  chipsets. The PHY is paired with a Synopsys DWC3 USB controller
-	  on Qualcomm SOCs.
-
 config PHY_QCOM_EUSB2_REPEATER
 	tristate "Qualcomm SNPS eUSB2 Repeater Driver"
 	depends on OF && (ARCH_QCOM || COMPILE_TEST)
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index eb60e950a..2121e92df 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_PHY_QCOM_QMP_USB)		+= phy-qcom-qmp-usb.o
 obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY)	+= phy-qcom-qmp-usb-legacy.o
 
 obj-$(CONFIG_PHY_QCOM_QUSB2)		+= phy-qcom-qusb2.o
-obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2)	+= phy-qcom-snps-eusb2.o
 obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER)	+= phy-qcom-eusb2-repeater.o
 obj-$(CONFIG_PHY_QCOM_USB_HS) 		+= phy-qcom-usb-hs.o
 obj-$(CONFIG_PHY_QCOM_USB_HSIC) 	+= phy-qcom-usb-hsic.o
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:48 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:48 +0200
Subject: [PATCH v3 04/10] phy: phy-snps-eusb2: refactor constructs names
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-5-ivo.ivanov.ivanov1@gmail.com>

As the driver now resides outside the phy subdirectory under a different
name, refactor all definitions, structures and functions to explicitly
specify what code is Qualcomm-specific and what is not.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 drivers/phy/phy-snps-eusb2.c | 256 +++++++++++++++++------------------
 1 file changed, 128 insertions(+), 128 deletions(-)

diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index 1484691a4..405278c18 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -13,15 +13,15 @@
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 
-#define USB_PHY_UTMI_CTRL0		(0x3c)
+#define QCOM_USB_PHY_UTMI_CTRL0		(0x3c)
 #define SLEEPM				BIT(0)
 #define OPMODE_MASK			GENMASK(4, 3)
 #define OPMODE_NONDRIVING		BIT(3)
 
-#define USB_PHY_UTMI_CTRL5		(0x50)
+#define QCOM_USB_PHY_UTMI_CTRL5		(0x50)
 #define POR				BIT(1)
 
-#define USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
+#define QCOM_USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
 #define PHY_ENABLE			BIT(0)
 #define SIDDQ_SEL			BIT(1)
 #define SIDDQ				BIT(2)
@@ -30,15 +30,15 @@
 #define FSEL_19_2_MHZ_VAL		(0x0)
 #define FSEL_38_4_MHZ_VAL		(0x4)
 
-#define USB_PHY_CFG_CTRL_1		(0x58)
+#define QCOM_USB_PHY_CFG_CTRL_1		(0x58)
 #define PHY_CFG_PLL_CPBIAS_CNTRL_MASK	GENMASK(7, 1)
 
-#define USB_PHY_CFG_CTRL_2		(0x5c)
+#define QCOM_USB_PHY_CFG_CTRL_2		(0x5c)
 #define PHY_CFG_PLL_FB_DIV_7_0_MASK	GENMASK(7, 0)
 #define DIV_7_0_19_2_MHZ_VAL		(0x90)
 #define DIV_7_0_38_4_MHZ_VAL		(0xc8)
 
-#define USB_PHY_CFG_CTRL_3		(0x60)
+#define QCOM_USB_PHY_CFG_CTRL_3		(0x60)
 #define PHY_CFG_PLL_FB_DIV_11_8_MASK	GENMASK(3, 0)
 #define DIV_11_8_19_2_MHZ_VAL		(0x1)
 #define DIV_11_8_38_4_MHZ_VAL		(0x0)
@@ -46,73 +46,73 @@
 #define PHY_CFG_PLL_REF_DIV		GENMASK(7, 4)
 #define PLL_REF_DIV_VAL			(0x0)
 
-#define USB_PHY_HS_PHY_CTRL2		(0x64)
+#define QCOM_USB_PHY_HS_PHY_CTRL2	(0x64)
 #define VBUSVLDEXT0			BIT(0)
 #define USB2_SUSPEND_N			BIT(2)
 #define USB2_SUSPEND_N_SEL		BIT(3)
 #define VBUS_DET_EXT_SEL		BIT(4)
 
-#define USB_PHY_CFG_CTRL_4		(0x68)
+#define QCOM_USB_PHY_CFG_CTRL_4		(0x68)
 #define PHY_CFG_PLL_GMP_CNTRL_MASK	GENMASK(1, 0)
 #define PHY_CFG_PLL_INT_CNTRL_MASK	GENMASK(7, 2)
 
-#define USB_PHY_CFG_CTRL_5		(0x6c)
+#define QCOM_USB_PHY_CFG_CTRL_5		(0x6c)
 #define PHY_CFG_PLL_PROP_CNTRL_MASK	GENMASK(4, 0)
 #define PHY_CFG_PLL_VREF_TUNE_MASK	GENMASK(7, 6)
 
-#define USB_PHY_CFG_CTRL_6		(0x70)
+#define QCOM_USB_PHY_CFG_CTRL_6		(0x70)
 #define PHY_CFG_PLL_VCO_CNTRL_MASK	GENMASK(2, 0)
 
-#define USB_PHY_CFG_CTRL_7		(0x74)
+#define QCOM_USB_PHY_CFG_CTRL_7		(0x74)
 
-#define USB_PHY_CFG_CTRL_8		(0x78)
+#define QCOM_USB_PHY_CFG_CTRL_8		(0x78)
 #define PHY_CFG_TX_FSLS_VREF_TUNE_MASK	GENMASK(1, 0)
 #define PHY_CFG_TX_FSLS_VREG_BYPASS	BIT(2)
 #define PHY_CFG_TX_HS_VREF_TUNE_MASK	GENMASK(5, 3)
 #define PHY_CFG_TX_HS_XV_TUNE_MASK	GENMASK(7, 6)
 
-#define USB_PHY_CFG_CTRL_9		(0x7c)
+#define QCOM_USB_PHY_CFG_CTRL_9		(0x7c)
 #define PHY_CFG_TX_PREEMP_TUNE_MASK	GENMASK(2, 0)
 #define PHY_CFG_TX_RES_TUNE_MASK	GENMASK(4, 3)
 #define PHY_CFG_TX_RISE_TUNE_MASK	GENMASK(6, 5)
 #define PHY_CFG_RCAL_BYPASS		BIT(7)
 
-#define USB_PHY_CFG_CTRL_10		(0x80)
+#define QCOM_USB_PHY_CFG_CTRL_10	(0x80)
 
-#define USB_PHY_CFG0			(0x94)
+#define QCOM_USB_PHY_CFG0		(0x94)
 #define DATAPATH_CTRL_OVERRIDE_EN	BIT(0)
 #define CMN_CTRL_OVERRIDE_EN		BIT(1)
 
-#define UTMI_PHY_CMN_CTRL0		(0x98)
+#define QCOM_UTMI_PHY_CMN_CTRL0		(0x98)
 #define TESTBURNIN			BIT(6)
 
-#define USB_PHY_FSEL_SEL		(0xb8)
+#define QCOM_USB_PHY_FSEL_SEL		(0xb8)
 #define FSEL_SEL			BIT(0)
 
-#define USB_PHY_APB_ACCESS_CMD		(0x130)
+#define QCOM_USB_PHY_APB_ACCESS_CMD	(0x130)
 #define RW_ACCESS			BIT(0)
 #define APB_START_CMD			BIT(1)
 #define APB_LOGIC_RESET			BIT(2)
 
-#define USB_PHY_APB_ACCESS_STATUS	(0x134)
+#define QCOM_USB_PHY_APB_ACCESS_STATUS	(0x134)
 #define ACCESS_DONE			BIT(0)
 #define TIMED_OUT			BIT(1)
 #define ACCESS_ERROR			BIT(2)
 #define ACCESS_IN_PROGRESS		BIT(3)
 
-#define USB_PHY_APB_ADDRESS		(0x138)
+#define QCOM_USB_PHY_APB_ADDRESS	(0x138)
 #define APB_REG_ADDR_MASK		GENMASK(7, 0)
 
-#define USB_PHY_APB_WRDATA_LSB		(0x13c)
+#define QCOM_USB_PHY_APB_WRDATA_LSB	(0x13c)
 #define APB_REG_WRDATA_7_0_MASK		GENMASK(3, 0)
 
-#define USB_PHY_APB_WRDATA_MSB		(0x140)
+#define QCOM_USB_PHY_APB_WRDATA_MSB	(0x140)
 #define APB_REG_WRDATA_15_8_MASK	GENMASK(7, 4)
 
-#define USB_PHY_APB_RDDATA_LSB		(0x144)
+#define QCOM_USB_PHY_APB_RDDATA_LSB	(0x144)
 #define APB_REG_RDDATA_7_0_MASK		GENMASK(3, 0)
 
-#define USB_PHY_APB_RDDATA_MSB		(0x148)
+#define QCOM_USB_PHY_APB_RDDATA_MSB	(0x148)
 #define APB_REG_RDDATA_15_8_MASK	GENMASK(7, 4)
 
 static const char * const eusb2_hsphy_vreg_names[] = {
@@ -121,7 +121,7 @@ static const char * const eusb2_hsphy_vreg_names[] = {
 
 #define EUSB2_NUM_VREGS		ARRAY_SIZE(eusb2_hsphy_vreg_names)
 
-struct qcom_snps_eusb2_hsphy {
+struct snps_eusb2_hsphy {
 	struct phy *phy;
 	void __iomem *base;
 
@@ -135,17 +135,17 @@ struct qcom_snps_eusb2_hsphy {
 	struct phy *repeater;
 };
 
-static int qcom_snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode)
+static int snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode)
 {
-	struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p);
+	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
 
 	phy->mode = mode;
 
 	return phy_set_mode_ext(phy->repeater, mode, submode);
 }
 
-static void qcom_snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset,
-					     u32 mask, u32 val)
+static void snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset,
+					u32 mask, u32 val)
 {
 	u32 reg;
 
@@ -158,65 +158,65 @@ static void qcom_snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset,
 	readl_relaxed(base + offset);
 }
 
-static void qcom_eusb2_default_parameters(struct qcom_snps_eusb2_hsphy *phy)
+static void qcom_eusb2_default_parameters(struct snps_eusb2_hsphy *phy)
 {
 	/* default parameters: tx pre-emphasis */
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9,
-					 PHY_CFG_TX_PREEMP_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
+				    PHY_CFG_TX_PREEMP_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0));
 
 	/* tx rise/fall time */
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9,
-					 PHY_CFG_TX_RISE_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
+				    PHY_CFG_TX_RISE_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2));
 
 	/* source impedance adjustment */
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_9,
-					 PHY_CFG_TX_RES_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
+				    PHY_CFG_TX_RES_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1));
 
 	/* dc voltage level adjustement */
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8,
-					 PHY_CFG_TX_HS_VREF_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_8,
+				    PHY_CFG_TX_HS_VREF_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3));
 
 	/* transmitter HS crossover adjustement */
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_8,
-					 PHY_CFG_TX_HS_XV_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_8,
+				    PHY_CFG_TX_HS_XV_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0));
 }
 
-static int qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_hsphy *phy)
+static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
 {
 	unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk);
 
 	switch (ref_clk_freq) {
 	case 19200000:
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0,
-						 FSEL_MASK,
-						 FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL));
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+					    FSEL_MASK,
+					    FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL));
 
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2,
-						 PHY_CFG_PLL_FB_DIV_7_0_MASK,
-						 DIV_7_0_19_2_MHZ_VAL);
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
+					    PHY_CFG_PLL_FB_DIV_7_0_MASK,
+					    DIV_7_0_19_2_MHZ_VAL);
 
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3,
-						 PHY_CFG_PLL_FB_DIV_11_8_MASK,
-						 DIV_11_8_19_2_MHZ_VAL);
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
+					    PHY_CFG_PLL_FB_DIV_11_8_MASK,
+					    DIV_11_8_19_2_MHZ_VAL);
 		break;
 
 	case 38400000:
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0,
-						 FSEL_MASK,
-						 FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL));
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+					    FSEL_MASK,
+					    FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL));
 
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_2,
-						 PHY_CFG_PLL_FB_DIV_7_0_MASK,
-						 DIV_7_0_38_4_MHZ_VAL);
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
+					    PHY_CFG_PLL_FB_DIV_7_0_MASK,
+					    DIV_7_0_38_4_MHZ_VAL);
 
-		qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3,
-						 PHY_CFG_PLL_FB_DIV_11_8_MASK,
-						 DIV_11_8_38_4_MHZ_VAL);
+		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
+					    PHY_CFG_PLL_FB_DIV_11_8_MASK,
+					    DIV_11_8_38_4_MHZ_VAL);
 		break;
 
 	default:
@@ -224,15 +224,15 @@ static int qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_hsphy *phy)
 		return -EINVAL;
 	}
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_3,
-					 PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
+				    PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL);
 
 	return 0;
 }
 
-static int qcom_snps_eusb2_hsphy_init(struct phy *p)
+static int snps_eusb2_hsphy_init(struct phy *p)
 {
-	struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p);
+	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
 	int ret;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs);
@@ -265,73 +265,73 @@ static int qcom_snps_eusb2_hsphy_init(struct phy *p)
 		goto disable_ref_clk;
 	}
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG0,
-					 CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG0,
+				    CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, POR);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL5, POR, POR);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0,
-					 PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+				    PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_APB_ACCESS_CMD,
-					 APB_LOGIC_RESET, APB_LOGIC_RESET);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_APB_ACCESS_CMD,
+				    APB_LOGIC_RESET, APB_LOGIC_RESET);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_FSEL_SEL,
-					 FSEL_SEL, FSEL_SEL);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_FSEL_SEL,
+				    FSEL_SEL, FSEL_SEL);
 
 	/* update ref_clk related registers */
 	ret = qcom_eusb2_ref_clk_init(phy);
 	if (ret)
-		goto disable_ref_clk;
+		return ret;
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_1,
-					 PHY_CFG_PLL_CPBIAS_CNTRL_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x1));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_1,
+				    PHY_CFG_PLL_CPBIAS_CNTRL_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x1));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4,
-					 PHY_CFG_PLL_INT_CNTRL_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_4,
+				    PHY_CFG_PLL_INT_CNTRL_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_4,
-					 PHY_CFG_PLL_GMP_CNTRL_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_4,
+				    PHY_CFG_PLL_GMP_CNTRL_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5,
-					 PHY_CFG_PLL_PROP_CNTRL_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_5,
+				    PHY_CFG_PLL_PROP_CNTRL_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_6,
-					 PHY_CFG_PLL_VCO_CNTRL_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_6,
+				    PHY_CFG_PLL_VCO_CNTRL_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_CFG_CTRL_5,
-					 PHY_CFG_PLL_VREF_TUNE_MASK,
-					 FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1));
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_5,
+				    PHY_CFG_PLL_VREF_TUNE_MASK,
+				    FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1));
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2,
-					 VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
+				    VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL);
 
 	/* set default parameters */
 	qcom_eusb2_default_parameters(phy);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2,
-					 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
-					 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
+				    USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
+				    USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0,
-					 SIDDQ_SEL, SIDDQ_SEL);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+				    SIDDQ_SEL, SIDDQ_SEL);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL_COMMON0,
-					 SIDDQ, 0);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+				    SIDDQ, 0);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_UTMI_CTRL5, POR, 0);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL5, POR, 0);
 
-	qcom_snps_eusb2_hsphy_write_mask(phy->base, USB_PHY_HS_PHY_CTRL2,
-					 USB2_SUSPEND_N_SEL, 0);
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
+				    USB2_SUSPEND_N_SEL, 0);
 
 	return 0;
 
@@ -344,9 +344,9 @@ static int qcom_snps_eusb2_hsphy_init(struct phy *p)
 	return ret;
 }
 
-static int qcom_snps_eusb2_hsphy_exit(struct phy *p)
+static int snps_eusb2_hsphy_exit(struct phy *p)
 {
-	struct qcom_snps_eusb2_hsphy *phy = phy_get_drvdata(p);
+	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
 
 	clk_disable_unprepare(phy->ref_clk);
 
@@ -357,18 +357,18 @@ static int qcom_snps_eusb2_hsphy_exit(struct phy *p)
 	return 0;
 }
 
-static const struct phy_ops qcom_snps_eusb2_hsphy_ops = {
-	.init		= qcom_snps_eusb2_hsphy_init,
-	.exit		= qcom_snps_eusb2_hsphy_exit,
-	.set_mode	= qcom_snps_eusb2_hsphy_set_mode,
+static const struct phy_ops snps_eusb2_hsphy_ops = {
+	.init		= snps_eusb2_hsphy_init,
+	.exit		= snps_eusb2_hsphy_exit,
+	.set_mode	= snps_eusb2_hsphy_set_mode,
 	.owner		= THIS_MODULE,
 };
 
-static int qcom_snps_eusb2_hsphy_probe(struct platform_device *pdev)
+static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct qcom_snps_eusb2_hsphy *phy;
+	struct snps_eusb2_hsphy *phy;
 	struct phy_provider *phy_provider;
 	struct phy *generic_phy;
 	int ret, i;
@@ -405,7 +405,7 @@ static int qcom_snps_eusb2_hsphy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(phy->repeater),
 				     "failed to get repeater\n");
 
-	generic_phy = devm_phy_create(dev, NULL, &qcom_snps_eusb2_hsphy_ops);
+	generic_phy = devm_phy_create(dev, NULL, &snps_eusb2_hsphy_ops);
 	if (IS_ERR(generic_phy)) {
 		dev_err(dev, "failed to create phy %d\n", ret);
 		return PTR_ERR(generic_phy);
@@ -418,25 +418,25 @@ static int qcom_snps_eusb2_hsphy_probe(struct platform_device *pdev)
 	if (IS_ERR(phy_provider))
 		return PTR_ERR(phy_provider);
 
-	dev_info(dev, "Registered Qcom-eUSB2 phy\n");
+	dev_info(dev, "Registered Snps-eUSB2 phy\n");
 
 	return 0;
 }
 
-static const struct of_device_id qcom_snps_eusb2_hsphy_of_match_table[] = {
+static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
 	{ .compatible = "qcom,sm8550-snps-eusb2-phy", },
 	{ },
 };
-MODULE_DEVICE_TABLE(of, qcom_snps_eusb2_hsphy_of_match_table);
+MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
 
-static struct platform_driver qcom_snps_eusb2_hsphy_driver = {
-	.probe		= qcom_snps_eusb2_hsphy_probe,
+static struct platform_driver snps_eusb2_hsphy_driver = {
+	.probe		= snps_eusb2_hsphy_probe,
 	.driver = {
-		.name	= "qcom-snps-eusb2-hsphy",
-		.of_match_table = qcom_snps_eusb2_hsphy_of_match_table,
+		.name	= "snps-eusb2-hsphy",
+		.of_match_table = snps_eusb2_hsphy_of_match_table,
 	},
 };
 
-module_platform_driver(qcom_snps_eusb2_hsphy_driver);
-MODULE_DESCRIPTION("Qualcomm SNPS eUSB2 HS PHY driver");
+module_platform_driver(snps_eusb2_hsphy_driver);
+MODULE_DESCRIPTION("SNPS eUSB2 HS PHY driver");
 MODULE_LICENSE("GPL");
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:49 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:49 +0200
Subject: [PATCH v3 05/10] phy: phy-snps-eusb2: split phy init code
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-6-ivo.ivanov.ivanov1@gmail.com>

The current phy init consists of hardware power-up, as well as
QCOM-specific eUSB2 init code. Split it into two parts, to make room
for such non-QCOM init code.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 drivers/phy/phy-snps-eusb2.c | 96 +++++++++++++++++++++++-------------
 1 file changed, 63 insertions(+), 33 deletions(-)

diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index 405278c18..fa878389f 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -121,6 +121,10 @@ static const char * const eusb2_hsphy_vreg_names[] = {
 
 #define EUSB2_NUM_VREGS		ARRAY_SIZE(eusb2_hsphy_vreg_names)
 
+struct snps_eusb2_phy_drvdata {
+	int (*phy_init)(struct phy *p);
+};
+
 struct snps_eusb2_hsphy {
 	struct phy *phy;
 	void __iomem *base;
@@ -133,6 +137,8 @@ struct snps_eusb2_hsphy {
 	enum phy_mode mode;
 
 	struct phy *repeater;
+
+	const struct snps_eusb2_phy_drvdata *data;
 };
 
 static int snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode)
@@ -230,41 +236,11 @@ static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
 	return 0;
 }
 
-static int snps_eusb2_hsphy_init(struct phy *p)
+static int qcom_snps_eusb2_hsphy_init(struct phy *p)
 {
 	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
 	int ret;
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs);
-	if (ret)
-		return ret;
-
-	ret = phy_init(phy->repeater);
-	if (ret) {
-		dev_err(&p->dev, "repeater init failed. %d\n", ret);
-		goto disable_vreg;
-	}
-
-	ret = clk_prepare_enable(phy->ref_clk);
-	if (ret) {
-		dev_err(&p->dev, "failed to enable ref clock, %d\n", ret);
-		goto disable_vreg;
-	}
-
-	ret = reset_control_assert(phy->phy_reset);
-	if (ret) {
-		dev_err(&p->dev, "failed to assert phy_reset, %d\n", ret);
-		goto disable_ref_clk;
-	}
-
-	usleep_range(100, 150);
-
-	ret = reset_control_deassert(phy->phy_reset);
-	if (ret) {
-		dev_err(&p->dev, "failed to de-assert phy_reset, %d\n", ret);
-		goto disable_ref_clk;
-	}
-
 	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG0,
 				    CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN);
 
@@ -334,6 +310,52 @@ static int snps_eusb2_hsphy_init(struct phy *p)
 				    USB2_SUSPEND_N_SEL, 0);
 
 	return 0;
+}
+
+static const struct snps_eusb2_phy_drvdata sm8550_snps_eusb2_phy = {
+	.phy_init	= qcom_snps_eusb2_hsphy_init,
+};
+
+static int snps_eusb2_hsphy_init(struct phy *p)
+{
+	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs);
+	if (ret)
+		return ret;
+
+	ret = phy_init(phy->repeater);
+	if (ret) {
+		dev_err(&p->dev, "repeater init failed. %d\n", ret);
+		goto disable_vreg;
+	}
+
+	ret = clk_prepare_enable(phy->ref_clk);
+	if (ret) {
+		dev_err(&p->dev, "failed to enable ref clock, %d\n", ret);
+		goto disable_vreg;
+	}
+
+	ret = reset_control_assert(phy->phy_reset);
+	if (ret) {
+		dev_err(&p->dev, "failed to assert phy_reset, %d\n", ret);
+		goto disable_ref_clk;
+	}
+
+	usleep_range(100, 150);
+
+	ret = reset_control_deassert(phy->phy_reset);
+	if (ret) {
+		dev_err(&p->dev, "failed to de-assert phy_reset, %d\n", ret);
+		goto disable_ref_clk;
+	}
+
+	ret = phy->data->phy_init(p);
+	if (ret)
+		goto disable_ref_clk;
+
+	return 0;
 
 disable_ref_clk:
 	clk_disable_unprepare(phy->ref_clk);
@@ -371,6 +393,7 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 	struct snps_eusb2_hsphy *phy;
 	struct phy_provider *phy_provider;
 	struct phy *generic_phy;
+	const struct snps_eusb2_phy_drvdata *drv_data;
 	int ret, i;
 	int num;
 
@@ -378,6 +401,11 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 	if (!phy)
 		return -ENOMEM;
 
+	drv_data = of_device_get_match_data(dev);
+	if (!drv_data)
+		return -EINVAL;
+	phy->data = drv_data;
+
 	phy->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(phy->base))
 		return PTR_ERR(phy->base);
@@ -424,8 +452,10 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
-	{ .compatible = "qcom,sm8550-snps-eusb2-phy", },
-	{ },
+	{
+		.compatible = "qcom,sm8550-snps-eusb2-phy",
+		.data = &sm8550_snps_eusb2_phy,
+	}, { },
 };
 MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
 
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:50 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:50 +0200
Subject: [PATCH v3 06/10] phy: phy-snps-eusb2: make repeater optional
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-7-ivo.ivanov.ivanov1@gmail.com>

As described in the device tree bindings, it's not necessary for the
SNPS eUSB2 phy to be connected to a repeater. In configurations where
there are such instances, the driver probing fails and the usb
controller does not work.

Make the repeater optional to avoid that, which also lets us use
the eUSB2 phy when it's connected to a repeater that is not configurable
by the kernel (for example it's missing a driver), as long as it has
been configured beforehand (usually by the bootloader).

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Acked-by: Neil Armstrong <neil.armstrong at linaro.org>
---
 drivers/phy/phy-snps-eusb2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index fa878389f..8ccd432a0 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -428,7 +428,7 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, ret,
 				     "failed to get regulator supplies\n");
 
-	phy->repeater = devm_of_phy_get_by_index(dev, np, 0);
+	phy->repeater = devm_of_phy_optional_get(dev, np, 0);
 	if (IS_ERR(phy->repeater))
 		return dev_err_probe(dev, PTR_ERR(phy->repeater),
 				     "failed to get repeater\n");
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:51 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:51 +0200
Subject: [PATCH v3 07/10] phy: phy-snps-eusb2: make reset control optional
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-8-ivo.ivanov.ivanov1@gmail.com>

Not all SoCs expose the reset line controls to the kernel, so make them
optional.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
 drivers/phy/phy-snps-eusb2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index 8ccd432a0..1e7e75bbc 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -410,7 +410,7 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
 	if (IS_ERR(phy->base))
 		return PTR_ERR(phy->base);
 
-	phy->phy_reset = devm_reset_control_get_exclusive(dev, NULL);
+	phy->phy_reset = devm_reset_control_get_optional_exclusive(dev, NULL);
 	if (IS_ERR(phy->phy_reset))
 		return PTR_ERR(phy->phy_reset);
 
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 06:58:52 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 15:58:52 +0200
Subject: [PATCH v3 08/10] phy: phy-snps-eusb2: refactor reference clock init
In-Reply-To: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321135854.1431375-9-ivo.ivanov.ivanov1@gmail.com>

Instead of matching frequencies with a switch and case, introduce
a table-based lookup. This improves readability, reduces redundancy,
and makes it easier to extend support for additional frequencies in
the future.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 drivers/phy/phy-snps-eusb2.c | 61 +++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 29 deletions(-)

diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c
index 1e7e75bbc..4ca11860a 100644
--- a/drivers/phy/phy-snps-eusb2.c
+++ b/drivers/phy/phy-snps-eusb2.c
@@ -192,44 +192,47 @@ static void qcom_eusb2_default_parameters(struct snps_eusb2_hsphy *phy)
 				    FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0));
 }
 
+struct snps_eusb2_ref_clk {
+	unsigned long freq;
+	u32 fsel_val;
+	u32 div_7_0_val;
+	u32 div_11_8_val;
+};
+
+static const struct snps_eusb2_ref_clk qcom_eusb2_ref_clk[] = {
+	{ 19200000, FSEL_19_2_MHZ_VAL, DIV_7_0_19_2_MHZ_VAL, DIV_11_8_19_2_MHZ_VAL },
+	{ 38400000, FSEL_38_4_MHZ_VAL, DIV_7_0_38_4_MHZ_VAL, DIV_11_8_38_4_MHZ_VAL },
+};
+
 static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
 {
+	const struct snps_eusb2_ref_clk *config = NULL;
 	unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk);
 
-	switch (ref_clk_freq) {
-	case 19200000:
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
-					    FSEL_MASK,
-					    FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL));
-
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
-					    PHY_CFG_PLL_FB_DIV_7_0_MASK,
-					    DIV_7_0_19_2_MHZ_VAL);
-
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
-					    PHY_CFG_PLL_FB_DIV_11_8_MASK,
-					    DIV_11_8_19_2_MHZ_VAL);
-		break;
-
-	case 38400000:
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
-					    FSEL_MASK,
-					    FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL));
-
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
-					    PHY_CFG_PLL_FB_DIV_7_0_MASK,
-					    DIV_7_0_38_4_MHZ_VAL);
-
-		snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
-					    PHY_CFG_PLL_FB_DIV_11_8_MASK,
-					    DIV_11_8_38_4_MHZ_VAL);
-		break;
+	for (int i = 0; i < ARRAY_SIZE(qcom_eusb2_ref_clk); i++) {
+		if (qcom_eusb2_ref_clk[i].freq == ref_clk_freq) {
+			config = &qcom_eusb2_ref_clk[i];
+			break;
+		}
+	}
 
-	default:
+	if (!config) {
 		dev_err(&phy->phy->dev, "unsupported ref_clk_freq:%lu\n", ref_clk_freq);
 		return -EINVAL;
 	}
 
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
+				    FSEL_MASK,
+				    FIELD_PREP(FSEL_MASK, config->fsel_val));
+
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
+				    PHY_CFG_PLL_FB_DIV_7_0_MASK,
+				    config->div_7_0_val);
+
+	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
+				    PHY_CFG_PLL_FB_DIV_11_8_MASK,
+				    config->div_11_8_val);
+
 	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
 				    PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL);
 
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:48:03 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:48:03 +0200
Subject: [PATCH v3 2/2] usb: dwc3: exynos: add support for Exynos2200 variant
In-Reply-To: <20250321144804.1435502-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321144804.1435502-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321144804.1435502-3-ivo.ivanov.ivanov1@gmail.com>

Add Exynos2200 compatible string and associated driver data. This SoC
requires a Link interface AXI clock.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
---
 drivers/usb/dwc3/dwc3-exynos.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index f5d963fae..aa22265c7 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -145,6 +145,12 @@ static void dwc3_exynos_remove(struct platform_device *pdev)
 	regulator_disable(exynos->vdd10);
 }
 
+static const struct dwc3_exynos_driverdata exynos2200_drvdata = {
+	.clk_names = { "link_aclk" },
+	.num_clks = 1,
+	.suspend_clk_idx = -1,
+};
+
 static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
 	.clk_names = { "usbdrd30" },
 	.num_clks = 1,
@@ -177,6 +183,9 @@ static const struct dwc3_exynos_driverdata gs101_drvdata = {
 
 static const struct of_device_id exynos_dwc3_match[] = {
 	{
+		.compatible = "samsung,exynos2200-dwusb3",
+		.data = &exynos2200_drvdata,
+	}, {
 		.compatible = "samsung,exynos5250-dwusb3",
 		.data = &exynos5250_drvdata,
 	}, {
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:55:54 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:55:54 +0200
Subject: [PATCH v3 2/4] arm64: dts: exynos: add initial support for exynos2200 SoC
In-Reply-To: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321145556.1436201-3-ivo.ivanov.ivanov1@gmail.com>

Exynos 2200 SoC is an ARMv8 mobile SoC found in the Samsung Galaxy S22
(r0s), S22+ (g0s), S22 Ultra (b0s) Add minimal support for that SoC,
including psci, pmu, chipid, architecture timer and mct, pinctrl,
clocks and usb.

The devices using this SoC suffer from an issue caused by the stock
Samsung bootloader, as it doesn't configure CNTFRQ_EL0. Hence it's
needed to hardcode the adequate frequency in the timer node,
otherwise the kernel panics.

Further platform support will be added over time.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 .../boot/dts/exynos/exynos2200-pinctrl.dtsi   | 1765 +++++++++++++++++
 arch/arm64/boot/dts/exynos/exynos2200.dtsi    |  561 ++++++
 2 files changed, 2326 insertions(+)
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200-pinctrl.dtsi
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200.dtsi

diff --git a/arch/arm64/boot/dts/exynos/exynos2200-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos2200-pinctrl.dtsi
new file mode 100644
index 000000000..f618ff290
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos2200-pinctrl.dtsi
@@ -0,0 +1,1765 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung's Exynos 2200 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2025, Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "exynos-pinctrl.h"
+
+&pinctrl_alive {
+	gpa0: gpa0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpa1: gpa1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpa2: gpa2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpa3: gpa3-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpa4: gpa4-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpq0: gpq0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpq1: gpq1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpq2: gpq2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	bt_hostwake: bt-hostwake-pins {
+		samsung,pins = "gpa0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_F>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+	};
+
+	uart1_bus: uart1-bus-pins {
+		samsung,pins = "gpq0-3", "gpq0-2", "gpq0-1", "gpq0-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+	};
+
+	wlan_host_wake: wlan-host-wake-pins {
+		samsung,pins = "gpa0-2";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_F>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+	};
+};
+
+&pinctrl_cmgp {
+	gpm0: gpm0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm1: gpm1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm2: gpm2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm3: gpm3-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm4: gpm4-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm5: gpm5-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm6: gpm6-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm7: gpm7-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm8: gpm8-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm9: gpm9-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm10: gpm10-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm11: gpm11-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm12: gpm12-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm13: gpm13-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm14: gpm14-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm15: gpm15-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm16: gpm16-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm17: gpm17-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm20: gpm20-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm21: gpm21-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm22: gpm22-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm23: gpm23-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	gpm24: gpm24-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH 0>;
+	};
+
+	hsi2c24_bus: hsi2c24-bus-pins {
+		samsung,pins = "gpm0-0", "gpm0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c25_bus: hsi2c25-bus-pins {
+		samsung,pins = "gpm1-0", "gpm1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c26_bus: hsi2c26-bus-pins {
+		samsung,pins = "gpm2-0", "gpm2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c27_bus: hsi2c27-bus-pins {
+		samsung,pins = "gpm3-0", "gpm3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c28_bus: hsi2c28-bus-pins {
+		samsung,pins = "gpm4-0", "gpm4-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c29_bus: hsi2c29-bus-pins {
+		samsung,pins = "gpm5-0", "gpm5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c30_bus: hsi2c30-bus-pins {
+		samsung,pins = "gpm6-0", "gpm6-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c31_bus: hsi2c31-bus-pins {
+		samsung,pins = "gpm7-0", "gpm7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c32_bus: hsi2c32-bus-pins {
+		samsung,pins = "gpm8-0", "gpm8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c33_bus: hsi2c33-bus-pins {
+		samsung,pins = "gpm9-0", "gpm9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c34_bus: hsi2c34-bus-pins {
+		samsung,pins = "gpm10-0", "gpm10-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c35_bus: hsi2c35-bus-pins {
+		samsung,pins = "gpm11-0", "gpm11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c36_bus: hsi2c36-bus-pins {
+		samsung,pins = "gpm12-0", "gpm12-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c37_bus: hsi2c37-bus-pins {
+		samsung,pins = "gpm13-0", "gpm13-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c38_bus: hsi2c38-bus-pins {
+		samsung,pins = "gpm23-0", "gpm24-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi12_bus: spi12-bus-pins {
+		samsung,pins = "gpm0-0", "gpm0-1", "gpm1-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi12_cs: spi12-cs-pins {
+		samsung,pins = "gpm1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi12_cs_func: spi12-cs-func-pins {
+		samsung,pins = "gpm1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi13_bus: spi13-bus-pins {
+		samsung,pins = "gpm2-0", "gpm2-1", "gpm3-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi13_cs: spi13-cs-pins {
+		samsung,pins = "gpm3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi13_cs_func: spi13-cs-func-pins {
+		samsung,pins = "gpm3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi14_bus: spi14-bus-pins {
+		samsung,pins = "gpm4-0", "gpm4-1", "gpm5-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi14_cs: spi14-cs-pins {
+		samsung,pins = "gpm5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi14_cs_func: spi14-cs-func-pins {
+		samsung,pins = "gpm5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi15_bus: spi15-bus-pins {
+		samsung,pins = "gpm6-0", "gpm6-1", "gpm7-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi15_cs: spi15-cs-pins {
+		samsung,pins = "gpm7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi15_cs_func: spi15-cs-func-pins {
+		samsung,pins = "gpm7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi16_bus: spi16-bus-pins {
+		samsung,pins = "gpm8-0", "gpm8-1", "gpm9-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi16_cs: spi16-cs-pins {
+		samsung,pins = "gpm9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi16_cs_func: spi16-cs-func-pins {
+		samsung,pins = "gpm9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi17_bus: spi17-bus-pins {
+		samsung,pins = "gpm10-0", "gpm10-1", "gpm11-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi17_cs: spi17-cs-pins {
+		samsung,pins = "gpm11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi17_cs_func: spi17-cs-func-pins {
+		samsung,pins = "gpm11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi18_bus: spi18-bus-pins {
+		samsung,pins = "gpm12-0", "gpm12-1", "gpm13-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi18_cs: spi18-cs-pins {
+		samsung,pins = "gpm13-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi18_cs_func: spi18-cs-func-pins {
+		samsung,pins = "gpm13-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	uart14_bus_single: uart14-bus-single-pins {
+		samsung,pins = "gpm0-0", "gpm0-1", "gpm2-0", "gpm2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart14_bus_dual: uart14-bus-dual-pins {
+		samsung,pins = "gpm0-0", "gpm0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart15_bus_single: uart15-bus-single-pins {
+		samsung,pins = "gpm3-0", "gpm3-1", "gpm4-0", "gpm4-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart15_bus_dual: uart15-bus-dual-pins {
+		samsung,pins = "gpm3-0", "gpm3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart16_bus_single: uart16-bus-single-pins {
+		samsung,pins = "gpm5-0", "gpm5-1", "gpm6-0", "gpm6-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart16_bus_dual: uart16-bus-dual-pins {
+		samsung,pins = "gpm5-0", "gpm5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart17_bus_single: uart17-bus-single-pins {
+		samsung,pins = "gpm7-0", "gpm7-1", "gpm8-0", "gpm8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart17_bus_dual: uart17-bus-dual-pins {
+		samsung,pins = "gpm7-0", "gpm7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart18_bus_single: uart18-bus-single-pins {
+		samsung,pins = "gpm8-0", "gpm8-1", "gpm9-0", "gpm9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart18_bus_dual: uart18-bus-dual-pins {
+		samsung,pins = "gpm8-0", "gpm8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart19_bus_single: uart19-bus-single-pins {
+		samsung,pins = "gpm10-0", "gpm10-1", "gpm11-0", "gpm11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart19_bus_dual: uart19-bus-dual-pins {
+		samsung,pins = "gpm12-0", "gpm12-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart20_bus_single: uart20-bus-single-pins {
+		samsung,pins = "gpm13-0", "gpm13-1", "gpm14-0", "gpm14-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart20_bus_dual: uart20-bus-dual-pins {
+		samsung,pins = "gpm13-0", "gpm13-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+};
+
+&pinctrl_hsi1 {
+	gpf0: gpf0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	pcie0_clkreq: pcie0-clkreq-pins {
+		samsung,pins = "gpf0-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_UP>;
+	};
+
+	pcie0_perst: pcie0-perst-pins {
+		samsung,pins = "gpf0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+	};
+
+	pcie1_clkreq: pcie1-clkreq-pins {
+		samsung,pins = "gpf0-2";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_UP>;
+	};
+
+	pcie1_perst: pcie1-perst-pins {
+		samsung,pins = "gpf0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+	};
+};
+
+&pinctrl_hsi1ufs {
+	gpf2: gpf2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	ufs_rst_n: ufs-rst-n-pins {
+		samsung,pins = "gpf2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	ufs_refclk_out: ufs-refclk-out-pins {
+		samsung,pins = "gpf2-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV3>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+	};
+};
+
+&pinctrl_peric0 {
+	gpb0: gpb0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpb1: gpb1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpb2: gpb2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpb3: gpb3-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc0: gpc0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc1: gpc1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc2: gpc2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg1: gpg1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg2: gpg2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp4: gpp4-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	aud_i2s0_bus: aud-i2s0-bus-pins {
+		samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	aud_i2s1_bus: aud-i2s1-bus-pins {
+		samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	aud_i2s2_bus: aud-i2s2-bus-pins {
+		samsung,pins = "gpb2-0", "gpb2-1", "gpb2-2", "gpb2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	aud_i2s3_bus: aud-i2s3-bus-pins {
+		samsung,pins = "gpb3-0", "gpb3-1", "gpb3-2", "gpb3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	aud_i2s3_pci: aud-i2s3-pci-pins {
+		samsung,pins = "gpb3-0", "gpb3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	aud_dsd_bus: aud-dsd-bus-pins {
+		samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	decon_0_te: decon-0-te-pins {
+		samsung,pins = "gpg2-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_F>;
+	};
+
+	hsi2c8_bus: hsi2c8-bus-pins {
+		samsung,pins = "gpp4-0", "gpp4-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c9_bus: hsi2c9-bus-pins {
+		samsung,pins = "gpp4-2", "gpp4-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c0_bus: i3c0-bus-pins {
+		samsung,pins = "gpc0-0", "gpc0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c1_bus: i3c1-bus-pins {
+		samsung,pins = "gpc1-0", "gpc1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c2_bus: i3c2-bus-pins {
+		samsung,pins = "gpc2-0", "gpc2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	spi4_bus: spi4-bus-pins {
+		samsung,pins = "gpp4-2", "gpp4-1", "gpp4-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi4_cs: spi4-cs-pins {
+		samsung,pins = "gpp4-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi4_cs_func: spi4-cs-func-pins {
+		samsung,pins = "gpp4-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	uart6_bus_single: uart6-bus-single-pins {
+		samsung,pins = "gpp4-0", "gpp4-1", "gpp4-2", "gpp4-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart6_bus_dual: uart6-bus-dual-pins {
+		samsung,pins = "gpp4-0", "gpp4-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+};
+
+&pinctrl_peric1 {
+	gpp7: gpp7-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp8: gpp8-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp9: gpp9-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp10: gpp10-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	hsi2c14_bus: hsi2c14-bus-pins {
+		samsung,pins = "gpp7-0", "gpp7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c15_bus: hsi2c15-bus-pins {
+		samsung,pins = "gpp7-2", "gpp7-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c16_bus: hsi2c16-bus-pins {
+		samsung,pins = "gpp8-0", "gpp8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c17_bus: hsi2c17-bus-pins {
+		samsung,pins = "gpp8-2", "gpp8-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c18_bus: hsi2c18-bus-pins {
+		samsung,pins = "gpp9-0", "gpp9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c19_bus: hsi2c19-bus-pins {
+		samsung,pins = "gpp9-2", "gpp9-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c20_bus: hsi2c20-bus-pins {
+		samsung,pins = "gpp10-0", "gpp10-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c21_bus: hsi2c21-bus-pins {
+		samsung,pins = "gpp10-2", "gpp10-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi7_bus: spi7-bus-pins {
+		samsung,pins = "gpp7-2", "gpp7-1", "gpp7-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi7_cs: spi7-cs-pins {
+		samsung,pins = "gpp7-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi7_cs_func: spi7-cs-func-pins {
+		samsung,pins = "gpp7-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi8_bus: spi8-bus-pins {
+		samsung,pins = "gpp8-2", "gpp8-1", "gpp8-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi8_cs: spi8-cs-pins {
+		samsung,pins = "gpp8-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi8_cs_func: spi8-cs-func-pins {
+		samsung,pins = "gpp8-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi9_bus: spi9-bus-pins {
+		samsung,pins = "gpp9-2", "gpp9-1", "gpp9-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi9_cs: spi9-cs-pins {
+		samsung,pins = "gpp9-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi9_cs_func: spi9-cs-func-pins {
+		samsung,pins = "gpp9-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi10_bus: spi10-bus-pins {
+		samsung,pins = "gpp10-2", "gpp10-1", "gpp10-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi10_cs: spi10-cs-pins {
+		samsung,pins = "gpp10-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi10_cs_func: spi10-cs-func-pins {
+		samsung,pins = "gpp10-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	uart9_bus_single: uart9-bus-single-pins {
+		samsung,pins = "gpp7-3", "gpp7-2", "gpp7-1", "gpp7-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart9_bus_dual: uart9-bus-dual-pins {
+		samsung,pins = "gpp7-0", "gpp7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart10_bus_single: uart10-bus-single-pins {
+		samsung,pins = "gpp8-3", "gpp8-2", "gpp8-1", "gpp8-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart10_bus_dual: uart10-bus-dual-pins {
+		samsung,pins = "gpp8-0", "gpp8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart11_bus_single: uart11-bus-single-pins {
+		samsung,pins = "gpp9-3", "gpp9-2", "gpp9-1", "gpp9-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart11_bus_dual: uart11-bus-dual-pins {
+		samsung,pins = "gpp9-0", "gpp9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart12_bus_single: uart12-bus-single-pins {
+		samsung,pins = "gpp10-3", "gpp10-2", "gpp10-1", "gpp10-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart12_bus_dual: uart12-bus-dual-pins {
+		samsung,pins = "gpp10-0", "gpp10-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+};
+
+&pinctrl_peric2 {
+	gpc3: gpc3-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc4: gpc4-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc5: gpc5-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc6: gpc6-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc7: gpc7-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc8: gpc8-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc9: gpc9-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg0: gpg0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp0: gpp0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp1: gpp1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp2: gpp2-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp3: gpp3-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp5: gpp5-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp6: gpp6-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp11: gpp11-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	hsi2c0_bus: hsi2c0-bus-pins {
+		samsung,pins = "gpp0-0", "gpp0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c1_bus: hsi2c1-bus-pins {
+		samsung,pins = "gpp0-2", "gpp0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c2_bus: hsi2c2-bus-pins {
+		samsung,pins = "gpp1-0", "gpp1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c3_bus: hsi2c3-bus-pins {
+		samsung,pins = "gpp1-2", "gpp1-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c4_bus: hsi2c4-bus-pins {
+		samsung,pins = "gpp2-0", "gpp2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c5_bus: hsi2c5-bus-pins {
+		samsung,pins = "gpp2-2", "gpp2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c6_bus: hsi2c6-bus-pins {
+		samsung,pins = "gpp3-0", "gpp3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c7_bus: hsi2c7-bus-pins {
+		samsung,pins = "gpp3-2", "gpp3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c10_bus: hsi2c10-bus-pins {
+		samsung,pins = "gpp5-0", "gpp5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c11_bus: hsi2c11-bus-pins {
+		samsung,pins = "gpp5-2", "gpp5-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c12_bus: hsi2c12-bus-pins {
+		samsung,pins = "gpp6-0", "gpp6-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c13_bus: hsi2c13-bus-pins {
+		samsung,pins = "gpp6-2", "gpp6-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi2c22_bus: hsi2c22-bus-pins {
+		samsung,pins = "gpp11-0", "gpp11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c3_bus: i3c3-bus-pins {
+		samsung,pins = "gpc3-0", "gpc3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c4_bus: i3c4-bus-pins {
+		samsung,pins = "gpc4-0", "gpc4-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c5_bus: i3c5-bus-pins {
+		samsung,pins = "gpc5-0", "gpc5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	i3c6_bus: i3c6-bus-pins {
+		samsung,pins = "gpc6-0", "gpc6-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c7_bus: i3c7-bus-pins {
+		samsung,pins = "gpc7-0", "gpc7-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c8_bus: i3c8-bus-pins {
+		samsung,pins = "gpc8-0", "gpc8-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c9_bus: i3c9-bus-pins {
+		samsung,pins = "gpc9-0", "gpc9-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+		samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	i3c10_bus: i3c10-bus-pins {
+		samsung,pins = "gpp2-2", "gpp2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	i3c11_bus: i3c11-bus-pins {
+		samsung,pins = "gpp3-2", "gpp3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	hsi223_bus: hsi2c23-bus-pins {
+		samsung,pins = "gpp11-2", "gpp11-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi0_bus: spi0-bus-pins {
+		samsung,pins = "gpp0-2", "gpp0-1", "gpp0-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi0_cs: spi0-cs-pins {
+		samsung,pins = "gpp0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi0_cs_func: spi0-cs-func-pins {
+		samsung,pins = "gpp0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi1_bus: spi1-bus-pins {
+		samsung,pins = "gpp1-2", "gpp1-1", "gpp1-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi1_cs: spi1-cs-pins {
+		samsung,pins = "gpp1-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi1_cs_func: spi1-cs-func-pins {
+		samsung,pins = "gpp1-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi2_bus: spi2-bus-pins {
+		samsung,pins = "gpp2-2", "gpp2-1", "gpp2-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi2_cs: spi2-cs-pins {
+		samsung,pins = "gpp2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi2_cs_func: spi2-cs-func-pins {
+		samsung,pins = "gpp2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi3_bus: spi3-bus-pins {
+		samsung,pins = "gpp3-2", "gpp3-1", "gpp3-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi3_cs: spi3-cs-pins {
+		samsung,pins = "gpp3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi3_cs_func: spi3-cs-func-pins {
+		samsung,pins = "gpp3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi5_bus: spi5-bus-pins {
+		samsung,pins = "gpp5-2", "gpp5-1", "gpp5-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi5_cs: spi5-cs-pins {
+		samsung,pins = "gpp5-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi5_cs_func: spi5-cs-func-pins {
+		samsung,pins = "gpp5-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi6_bus: spi6-bus-pins {
+		samsung,pins = "gpp6-2", "gpp6-1", "gpp6-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi6_cs: spi6-cs-pins {
+		samsung,pins = "gpp6-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi6_cs_func: spi6-cs-func-pins {
+		samsung,pins = "gpp6-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi11_bus: spi11-bus-pins {
+		samsung,pins = "gpp11-2", "gpp11-1", "gpp11-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi11_cs: spi11-cs-pins {
+		samsung,pins = "gpp11-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	spi11_cs_func: spi11-cs-func-pins {
+		samsung,pins = "gpp11-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+	};
+
+	uart0_bus_single: uart0-bus-single-pins {
+		samsung,pins = "gpg0-2", "gpg0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+	};
+
+	uart2_bus_single: uart2-bus-single-pins {
+		samsung,pins = "gpp0-0", "gpp0-1", "gpp0-2", "gpp0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart2_bus_dual: uart2-bus-dual-pins {
+		samsung,pins = "gpp0-0", "gpp0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart3_bus_single: uart3-bus-single-pins {
+		samsung,pins = "gpp1-0", "gpp1-1", "gpp1-2", "gpp1-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart3_bus_dual: uart3-bus-dual-pins {
+		samsung,pins = "gpp1-0", "gpp1-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart4_bus_single: uart4-bus-single-pins {
+		samsung,pins = "gpp2-0", "gpp2-1", "gpp2-2", "gpp2-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart4_bus_dual: uart4-bus-dual-pins {
+		samsung,pins = "gpp2-0", "gpp2-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart5_bus_single: uart5-bus-single-pins {
+		samsung,pins = "gpp3-0", "gpp3-1", "gpp3-2", "gpp3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart5_bus_dual: uart5-bus-dual-pins {
+		samsung,pins = "gpp3-0", "gpp3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart7_bus_single: uart7-bus-single-pins {
+		samsung,pins = "gpp5-0", "gpp5-1", "gpp5-2", "gpp5-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart7_bus_dual: uart7-bus-dual-pins {
+		samsung,pins = "gpp5-0", "gpp5-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart8_bus_single: uart8-bus-single-pins {
+		samsung,pins = "gpp6-3", "gpp6-2", "gpp6-1", "gpp6-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart8_bus_dual: uart8-bus-dual-pins {
+		samsung,pins = "gpp6-0", "gpp6-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart13_bus_single: uart13-bus-single-pins {
+		samsung,pins = "gpp11-3", "gpp11-2", "gpp11-1", "gpp11-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
+	uart13_bus_dual: uart13-bus-dual-pins {
+		samsung,pins = "gpp11-0", "gpp11-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+};
+
+&pinctrl_ufs {
+	gpf1: gpf1-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
+&pinctrl_vts {
+	gpv0: gpv0-gpio-bank {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	amic_pdm0_bus: amic-pdm0-bus-pins {
+		samsung,pins = "gpv0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	amic_pdm1_bus: amic-pdm1-bus-pins {
+		samsung,pins = "gpv0-4";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	amic_pdm2_bus: amic-pdm2-bus-pins {
+		samsung,pins = "gpv0-5";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_bus_clk0: dmic-bus-clk0-pins {
+		samsung,pins = "gpv0-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_bus_clk1: dmic-bus-clk1-pins {
+		samsung,pins = "gpv0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_bus_clk2: dmic-bus-clk2-pins {
+		samsung,pins = "gpv0-2";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_pdm0_bus: dmic-pdm0-bus-pins {
+		samsung,pins = "gpv0-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_pdm1_bus: dmic-pdm1-bus-pins {
+		samsung,pins = "gpv0-4";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+
+	dmic_pdm2_bus: dmic-pdm2-bus-pins {
+		samsung,pins = "gpv0-5";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+	};
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos2200.dtsi b/arch/arm64/boot/dts/exynos/exynos2200.dtsi
new file mode 100644
index 000000000..151d4b08b
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos2200.dtsi
@@ -0,0 +1,561 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung's Exynos 2200 SoC device tree source
+ *
+ * Copyright (c) 2025, Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
+ */
+
+#include <dt-bindings/clock/samsung,exynos2200-cmu.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "samsung,exynos2200";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	interrupt-parent = <&gic>;
+
+	aliases {
+		pinctrl0 = &pinctrl_alive;
+		pinctrl1 = &pinctrl_cmgp;
+		pinctrl2 = &pinctrl_hsi1;
+		pinctrl3 = &pinctrl_ufs;
+		pinctrl4 = &pinctrl_hsi1ufs;
+		pinctrl5 = &pinctrl_peric0;
+		pinctrl6 = &pinctrl_peric1;
+		pinctrl7 = &pinctrl_peric2;
+		pinctrl8 = &pinctrl_vts;
+	};
+
+	xtcxo: clock-1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "oscclk";
+	};
+
+	ext_26m: clock-2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "ext-26m";
+	};
+
+	ext_200m: clock-3 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "ext-200m";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+
+				core1 {
+					cpu = <&cpu1>;
+				};
+
+				core2 {
+					cpu = <&cpu2>;
+				};
+
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+
+				core1 {
+					cpu = <&cpu5>;
+				};
+
+				core2 {
+					cpu = <&cpu6>;
+				};
+			};
+
+			cluster2 {
+				core0 {
+					cpu = <&cpu7>;
+				};
+			};
+		};
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0>;
+			capacity-dmips-mhz = <260>;
+			dynamic-power-coefficient = <189>;
+			enable-method = "psci";
+			cpu-idle-states = <&little_cpu_sleep>;
+		};
+
+		cpu1: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x100>;
+			capacity-dmips-mhz = <260>;
+			dynamic-power-coefficient = <189>;
+			enable-method = "psci";
+			cpu-idle-states = <&little_cpu_sleep>;
+		};
+
+		cpu2: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x200>;
+			capacity-dmips-mhz = <260>;
+			dynamic-power-coefficient = <189>;
+			enable-method = "psci";
+			cpu-idle-states = <&little_cpu_sleep>;
+		};
+
+		cpu3: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a510";
+			reg = <0x300>;
+			capacity-dmips-mhz = <260>;
+			dynamic-power-coefficient = <189>;
+			enable-method = "psci";
+			cpu-idle-states = <&little_cpu_sleep>;
+		};
+
+		cpu4: cpu at 400 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a710";
+			reg = <0x400>;
+			capacity-dmips-mhz = <380>;
+			dynamic-power-coefficient = <560>;
+			enable-method = "psci";
+			cpu-idle-states = <&big_cpu_sleep>;
+		};
+
+		cpu5: cpu at 500 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a710";
+			reg = <0x500>;
+			capacity-dmips-mhz = <380>;
+			dynamic-power-coefficient = <560>;
+			enable-method = "psci";
+			cpu-idle-states = <&big_cpu_sleep>;
+		};
+
+		cpu6: cpu at 600 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a710";
+			reg = <0x600>;
+			capacity-dmips-mhz = <380>;
+			dynamic-power-coefficient = <560>;
+			enable-method = "psci";
+			cpu-idle-states = <&big_cpu_sleep>;
+		};
+
+		cpu7: cpu at 700 {
+			device_type = "cpu";
+			compatible = "arm,cortex-x2";
+			reg = <0x700>;
+			capacity-dmips-mhz = <488>;
+			dynamic-power-coefficient = <765>;
+			enable-method = "psci";
+			cpu-idle-states = <&prime_cpu_sleep>;
+		};
+
+		idle-states {
+			entry-method = "psci";
+
+			little_cpu_sleep: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				idle-state-name = "c2";
+				entry-latency-us = <70>;
+				exit-latency-us = <170>;
+				min-residency-us = <2000>;
+				arm,psci-suspend-param = <0x10000>;
+			};
+
+			big_cpu_sleep: cpu-sleep-1 {
+				compatible = "arm,idle-state";
+				idle-state-name = "c2";
+				entry-latency-us = <235>;
+				exit-latency-us = <220>;
+				min-residency-us = <3500>;
+				arm,psci-suspend-param = <0x10000>;
+			};
+
+			prime_cpu_sleep: cpu-sleep-2 {
+				compatible = "arm,idle-state";
+				idle-state-name = "c2";
+				entry-latency-us = <150>;
+				exit-latency-us = <190>;
+				min-residency-us = <2500>;
+				arm,psci-suspend-param = <0x10000>;
+			};
+		};
+	};
+
+	pmu-a510 {
+		compatible = "arm,cortex-a510-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_cluster0>;
+	};
+
+	pmu-a710 {
+		compatible = "arm,cortex-a710-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_cluster1>;
+	};
+
+	pmu-x2 {
+		compatible = "arm,cortex-x2-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_cluster2>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		ranges;
+
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		chipid at 10000000 {
+			compatible = "samsung,exynos2200-chipid",
+				     "samsung,exynos850-chipid";
+			reg = <0x0 0x10000000 0x0 0x24>;
+		};
+
+		cmu_peris: clock-controller at 10020000 {
+			compatible = "samsung,exynos2200-cmu-peris";
+			reg = <0x0 0x10020000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&cmu_top CLK_DOUT_TCXO_DIV3>,
+				 <&cmu_top CLK_DOUT_CMU_PERIS_NOC>,
+				 <&cmu_top CLK_DOUT_CMU_PERIS_GIC>;
+			clock-names = "tcxo_div3",
+				      "noc",
+				      "gic";
+		};
+
+		mct_peris: timer at 10040000 {
+			compatible = "samsung,exynos2200-mct-peris",
+				     "samsung,exynos4210-mct";
+			reg = <0x0 0x10040000 0x0 0x800>;
+			clocks = <&cmu_top CLK_DOUT_TCXO_DIV3>, <&cmu_peris CLK_MOUT_PERIS_GIC>;
+			clock-names = "fin_pll", "mct";
+			interrupts = <GIC_SPI 943 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 944 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 945 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 946 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 947 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 948 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 949 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 950 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 951 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 952 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 953 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 954 IRQ_TYPE_LEVEL_HIGH 0>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller at 10200000 {
+			compatible = "arm,gic-v3";
+			reg = <0x0 0x10200000 0x0 0x10000>,     /* GICD */
+			      <0x0 0x10240000 0x0 0x200000>;    /* GICR * 8 */
+
+			#interrupt-cells = <4>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+
+			ppi-partitions {
+				ppi_cluster0: interrupt-partition-0 {
+					affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
+				};
+
+				ppi_cluster1: interrupt-partition-1 {
+					affinity = <&cpu4 &cpu5 &cpu6>;
+				};
+
+				ppi_cluster2: interrupt-partition-2 {
+					affinity = <&cpu7>;
+				};
+			};
+		};
+
+		cmu_peric0: clock-controller at 10400000 {
+			compatible = "samsung,exynos2200-cmu-peric0";
+			reg = <0x0 0x10400000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC0_NOC>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC0_IP0>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC0_IP1>;
+			clock-names = "oscclk", "noc", "ip0", "ip1";
+		};
+
+		syscon_peric0: syscon at 10420000 {
+			compatible = "samsung,exynos2200-peric0-sysreg", "syscon";
+			reg = <0x0 0x10420000 0x0 0x2000>;
+		};
+
+		pinctrl_peric0: pinctrl at 10430000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x10430000 0x0 0x1000>;
+		};
+
+		cmu_peric1: clock-controller at 10700000 {
+			compatible = "samsung,exynos2200-cmu-peric1";
+			reg = <0x0 0x10700000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC1_NOC>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC1_IP0>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC1_IP1>;
+			clock-names = "oscclk", "noc", "ip0", "ip1";
+		};
+
+		syscon_peric1: syscon at 10720000 {
+			compatible = "samsung,exynos2200-peric1-sysreg", "syscon";
+			reg = <0x0 0x10720000 0x0 0x2000>;
+		};
+
+		pinctrl_peric1: pinctrl at 10730000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x10730000 0x0 0x1000>;
+		};
+
+		cmu_hsi0: clock-controller at 10a00000 {
+			compatible = "samsung,exynos2200-cmu-hsi0";
+			reg = <0x0 0x10a00000 0x0 0x8000>;
+			#clock-cells = <1>;
+		};
+
+		usb32drd: phy at 10aa0000 {
+			compatible = "samsung,exynos2200-usb32drd-phy";
+			reg = <0x0 0x10aa0000 0x0 0x10000>;
+
+			clocks = <&cmu_hsi0 CLK_MOUT_HSI0_NOC>;
+			clock-names = "phy";
+
+			#phy-cells = <1>;
+			phys = <&usb_hsphy>;
+			phy-names = "hs";
+
+			samsung,pmu-syscon = <&pmu_system_controller>;
+
+			status = "disabled";
+		};
+
+		usb_hsphy: phy at 10ab0000 {
+			compatible = "samsung,exynos2200-snps-eusb2-phy";
+			reg = <0x0 0x10ab0000 0x0 0x10000>;
+
+			clocks = <&cmu_hsi0 CLK_MOUT_HSI0_USB32DRD>,
+				 <&cmu_hsi0 CLK_MOUT_HSI0_NOC>,
+				 <&cmu_hsi0 CLK_DOUT_DIV_CLK_HSI0_EUSB>;
+			clock-names = "ref", "bus", "ctrl";
+
+			#phy-cells = <0>;
+
+			status = "disabled";
+		};
+
+		usb: usb at 10b00000 {
+			compatible = "samsung,exynos2200-dwusb3";
+			ranges = <0x0 0x0 0x10b00000 0x10000>;
+
+			clocks = <&cmu_hsi0 CLK_MOUT_HSI0_NOC>;
+			clock-names = "link_aclk";
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			status = "disabled";
+
+			usb_dwc3: usb at 0 {
+				compatible = "snps,dwc3";
+				reg = <0x0 0x10000>;
+
+				clocks = <&cmu_hsi0 CLK_MOUT_HSI0_USB32DRD>;
+				clock-names = "ref";
+
+				interrupts = <GIC_SPI 485 IRQ_TYPE_LEVEL_HIGH 0>;
+
+				phys = <&usb32drd 0>;
+				phy-names = "usb2-phy";
+
+				snps,dis-u2-freeclk-exists-quirk;
+				snps,gfladj-refclk-lpm-sel-quirk;
+				snps,has-lpm-erratum;
+				snps,quirk-frame-length-adjustment = <0x20>;
+				snps,usb3_lpm_capable;
+			};
+		};
+
+		cmu_ufs: clock-controller at 11000000 {
+			compatible = "samsung,exynos2200-cmu-ufs";
+			reg = <0x0 0x11000000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_UFS_NOC>,
+				 <&cmu_top CLK_MOUT_CMU_UFS_MMC_CARD>,
+				 <&cmu_top CLK_DOUT_CMU_UFS_UFS_EMBD>;
+			clock-names = "oscclk", "noc", "mmc", "ufs";
+		};
+
+		syscon_ufs: syscon at 11020000 {
+			compatible = "samsung,exynos2200-ufs-sysreg", "syscon";
+			reg = <0x0 0x11020000 0x0 0x2000>;
+		};
+
+		pinctrl_ufs: pinctrl at 11040000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x11040000 0x0 0x1000>;
+		};
+
+		pinctrl_hsi1ufs: pinctrl at 11060000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x11060000 0x0 0x1000>;
+		};
+
+		pinctrl_hsi1: pinctrl at 11240000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x11240000 0x0 0x1000>;
+		};
+
+		cmu_peric2: clock-controller at 11c00000 {
+			compatible = "samsung,exynos2200-cmu-peric2";
+			reg = <0x0 0x11c00000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC2_NOC>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC2_IP0>,
+				 <&cmu_top CLK_DOUT_CMU_PERIC2_IP1>;
+			clock-names = "oscclk", "noc", "ip0", "ip1";
+		};
+
+		syscon_peric2: syscon at 11c20000 {
+			compatible = "samsung,exynos2200-peric2-sysreg", "syscon";
+			reg = <0x0 0x11c20000 0x0 0x4000>;
+		};
+
+		pinctrl_peric2: pinctrl at 11c30000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x11c30000 0x0 0x1000>;
+		};
+
+		cmu_cmgp: clock-controller at 14e00000 {
+			compatible = "samsung,exynos2200-cmu-cmgp";
+			reg = <0x0 0x14e00000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_alive CLK_DOUT_ALIVE_CMGP_NOC>,
+				 <&cmu_alive CLK_DOUT_ALIVE_CMGP_PERI>;
+			clock-names = "oscclk", "noc", "peri";
+		};
+
+		syscon_cmgp: syscon at 14e20000 {
+			compatible = "samsung,exynos2200-cmgp-sysreg", "syscon";
+			reg = <0x0 0x14e20000 0x0 0x2000>;
+		};
+
+		pinctrl_cmgp: pinctrl at 14e30000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x14e30000 0x0 0x1000>;
+
+			wakeup-interrupt-controller {
+				compatible = "samsung,exynos2200-wakeup-eint",
+					     "samsung,exynos850-wakeup-eint",
+					     "samsung,exynos7-wakeup-eint";
+			};
+		};
+
+		cmu_vts: clock-controller at 15300000 {
+			compatible = "samsung,exynos2200-cmu-vts";
+			reg = <0x0 0x15300000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_VTS_DMIC>;
+			clock-names = "oscclk", "dmic";
+		};
+
+		pinctrl_vts: pinctrl at 15320000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x15320000 0x0 0x1000>;
+		};
+
+		cmu_alive: clock-controller at 15800000 {
+			compatible = "samsung,exynos2200-cmu-alive";
+			reg = <0x0 0x15800000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>,
+				 <&cmu_top CLK_DOUT_CMU_ALIVE_NOC>;
+			clock-names = "oscclk", "noc";
+		};
+
+		pinctrl_alive: pinctrl at 15850000 {
+			compatible = "samsung,exynos2200-pinctrl";
+			reg = <0x0 0x15850000 0x0 0x1000>;
+
+			wakeup-interrupt-controller {
+				compatible = "samsung,exynos2200-wakeup-eint",
+					     "samsung,exynos850-wakeup-eint",
+					     "samsung,exynos7-wakeup-eint";
+			};
+		};
+
+		pmu_system_controller: system-controller at 15860000 {
+			compatible = "samsung,exynos2200-pmu",
+				     "samsung,exynos7-pmu", "syscon";
+			reg = <0x0 0x15860000 0x0 0x10000>;
+
+			reboot: syscon-reboot {
+				compatible = "syscon-reboot";
+				offset = <0x3c00>; /* SYSTEM_CONFIGURATION */
+				mask = <0x2>; /* SWRESET_SYSTEM */
+				value = <0x2>; /* reset value */
+			};
+		};
+
+		cmu_top: clock-controller at 1a320000 {
+			compatible = "samsung,exynos2200-cmu-top";
+			reg = <0x0 0x1a320000 0x0 0x8000>;
+			#clock-cells = <1>;
+
+			clocks = <&xtcxo>;
+			clock-names = "oscclk";
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
+		/*
+		 * Non-updatable, broken stock Samsung bootloader does not
+		 * configure CNTFRQ_EL0
+		 */
+		clock-frequency = <25600000>;
+	};
+};
+
+#include "exynos2200-pinctrl.dtsi"
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:55:56 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:55:56 +0200
Subject: [PATCH v3 4/4] MAINTAINERS: add entry for Samsung Exynos2200 SoC
In-Reply-To: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321145556.1436201-5-ivo.ivanov.ivanov1@gmail.com>

Add maintainers entry for the Samsung Exynos2200 SoC based platforms.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e4f5d8f68..f3ef6f862 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20937,6 +20937,16 @@ B:	mailto:linux-samsung-soc at vger.kernel.org
 F:	Documentation/devicetree/bindings/sound/samsung*
 F:	sound/soc/samsung/
 
+SAMSUNG EXYNOS2200 SoC SUPPORT
+M:	Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+L:	linux-samsung-soc at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/clock/samsung,exynos2200-cmu.yaml
+F:	arch/arm64/boot/dts/exynos/exynos2200*
+F:	drivers/clk/samsung/clk-exynos2200.c
+F:	include/dt-bindings/clock/samsung,exynos2200-cmu.h
+
 SAMSUNG EXYNOS850 SoC SUPPORT
 M:	Sam Protsenko <semen.protsenko at linaro.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:55:52 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:55:52 +0200
Subject: [PATCH v3 0/4] arm64: dts: exynos: add initial support for Samsung Galaxy S22+
Message-ID: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>

Hey folks,

This patchset adds device tree files for Exynos 2200 and Samsung
Galaxy S22+.

Exynos 2200 SoC is an ARMv8 mobile SoC found in the Samsung Galaxy S22
(r0s), S22+ (g0s), S22 Ultra (b0s) Add minimal support for that SoC,
including psci, pmu, chipid, architecture timer and mct, pinctrl,
clocks and usb.

The devices using this SoC suffer from an issue caused by the stock
Samsung bootloader, as it doesn't configure CNTFRQ_EL0. Hence it's
needed to hardcode the adequate frequency in the timer node,
otherwise the kernel panics.

Another issue is that cpu2 and cpu3 fail to come up consistently, which
leads to a hang later in the boot process. As A510 cores are clustered
by two, it makes sense for both of these cpus to fail if there is a
power issue. Disable them until the problem is figured out.

Samsung Galaxy S22+ (SM-S906B), codenamed g0s, is a mobile phone from
2022. It features 8GB RAM, 128/256GB UFS 3.1, Exynos 2200 SoC and a
1080x2340 Dynamic AMOLED display.

Further platform support will be added over time.

I expect [1], [2] and [3] to be merged in next before this patchset
because it depends on the aforementioned series for drivers and device
tree bindings.

Best regards,
Ivaylo

Changes in v3:
- account for the usbdrd changes in the exynos2200 soc dtsi
- drop usbcon driver from the MAINTAINERS patch

Changes in v2:
- mention the board codename in the first patch's commit message
- make all reg values hex in device trees
- reorder usb_con above usb_dwc3
- drop regulators for usb_con
- remodel usb_con_phy to take usb_hsphy phandle
- include MAINTAINERS patch in this patchset

[1] https://lore.kernel.org/all/20250321135854.1431375-1-ivo.ivanov.ivanov1 at gmail.com/
[2] https://lore.kernel.org/all/20250215123922.163630-1-ivo.ivanov.ivanov1 at gmail.com/
[3] https://lore.kernel.org/all/20250321144804.1435502-1-ivo.ivanov.ivanov1 at gmail.com/

Ivaylo Ivanov (4):
  dt-bindings: arm: samsung: document g0s board binding
  arm64: dts: exynos: add initial support for exynos2200 SoC
  arm64: dts: exynos: add initial support for Samsung Galaxy S22+
  MAINTAINERS: add entry for Samsung Exynos2200 SoC

 .../bindings/arm/samsung/samsung-boards.yaml  |    6 +
 MAINTAINERS                                   |   10 +
 arch/arm64/boot/dts/exynos/Makefile           |    1 +
 arch/arm64/boot/dts/exynos/exynos2200-g0s.dts |  175 ++
 .../boot/dts/exynos/exynos2200-pinctrl.dtsi   | 1765 +++++++++++++++++
 arch/arm64/boot/dts/exynos/exynos2200.dtsi    |  561 ++++++
 6 files changed, 2518 insertions(+)
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200-g0s.dts
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200-pinctrl.dtsi
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200.dtsi

-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:55:53 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:55:53 +0200
Subject: [PATCH v3 1/4] dt-bindings: arm: samsung: document g0s board binding
In-Reply-To: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321145556.1436201-2-ivo.ivanov.ivanov1@gmail.com>

Add binding for the Samsung Galaxy S22+ (SM-S906B) board, codenamed G0S,
which is based on the Samsung Exynos2200 SoC.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 .../devicetree/bindings/arm/samsung/samsung-boards.yaml     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
index fab29f95d..bb3f6a0e1 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
@@ -45,6 +45,12 @@ properties:
           - const: samsung,aries
           - const: samsung,s5pv210
 
+      - description: Exynos2200 based boards
+        items:
+          - enum:
+              - samsung,g0s                     # Samsung Galaxy S22+ (SM-S906B)
+          - const: samsung,exynos2200
+
       - description: Exynos3250 based boards
         items:
           - enum:
-- 
2.43.0



From ivo.ivanov.ivanov1 at gmail.com  Fri Mar 21 07:55:55 2025
From: ivo.ivanov.ivanov1 at gmail.com (Ivaylo Ivanov)
Date: Fri, 21 Mar 2025 16:55:55 +0200
Subject: [PATCH v3 3/4] arm64: dts: exynos: add initial support for Samsung Galaxy S22+
In-Reply-To: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
References: <20250321145556.1436201-1-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250321145556.1436201-4-ivo.ivanov.ivanov1@gmail.com>

Samsung Galaxy S22+ (SM-S906B), codenamed g0s, is a mobile phone from
2022. It features 8GB RAM, 128/256GB UFS 3.1, Exynos 2200 SoC and a
1080x2340 Dynamic AMOLED display.

This device has an issue where cpu2 and cpu3 fail to come up
consistently, which leads to a hang later in the boot process. Disable
them until the problem is figured out.

This initial device tree configures simple-framebuffer, volume-up key and
usb.

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
---
 arch/arm64/boot/dts/exynos/Makefile           |   1 +
 arch/arm64/boot/dts/exynos/exynos2200-g0s.dts | 175 ++++++++++++++++++
 2 files changed, 176 insertions(+)
 create mode 100644 arch/arm64/boot/dts/exynos/exynos2200-g0s.dts

diff --git a/arch/arm64/boot/dts/exynos/Makefile b/arch/arm64/boot/dts/exynos/Makefile
index f6f4bc650..235b9def4 100644
--- a/arch/arm64/boot/dts/exynos/Makefile
+++ b/arch/arm64/boot/dts/exynos/Makefile
@@ -2,6 +2,7 @@
 subdir-y += google
 
 dtb-$(CONFIG_ARCH_EXYNOS) += \
+	exynos2200-g0s.dtb		\
 	exynos5433-tm2.dtb		\
 	exynos5433-tm2e.dtb		\
 	exynos7-espresso.dtb		\
diff --git a/arch/arm64/boot/dts/exynos/exynos2200-g0s.dts b/arch/arm64/boot/dts/exynos/exynos2200-g0s.dts
new file mode 100644
index 000000000..6d346fab6
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos2200-g0s.dts
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung Galaxy S22+ (g0s/SM-S906B) device tree source
+ *
+ * Copyright (c) 2025, Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
+ */
+
+/dts-v1/;
+#include "exynos2200.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Samsung Galaxy S22+ (SM-S906B)";
+	compatible = "samsung,g0s", "samsung,exynos2200";
+	chassis-type = "handset";
+
+	chosen {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		framebuffer: framebuffer {
+			compatible = "simple-framebuffer";
+			memory-region = <&cont_splash_mem>;
+			width = <1080>;
+			height = <2340>;
+			stride = <(1080 * 4)>;
+			format = "a8r8g8b8";
+		};
+	};
+
+	/*
+	 * RTC clock (XrtcXTI); external, must be 32.768 kHz.
+	 *
+	 * TODO: Remove this once RTC clock is implemented properly as part of
+	 *       PMIC driver.
+	 */
+	rtcclk: clock-rtcclk {
+		compatible = "fixed-clock";
+		clock-output-names = "rtcclk";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	/*
+	 * cpu2 and cpu3 fail to come up consistently, which leads
+	 * to a hang later in the boot process.
+	 *
+	 * Disable them until the issue is figured out.
+	 */
+	cpus {
+		/delete-node/ cpu at 200;
+		/delete-node/ cpu at 300;
+
+		cpu-map {
+			cluster0 {
+				/delete-node/ core2;
+				/delete-node/ core3;
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		pinctrl-0 = <&key_volup>;
+		pinctrl-names = "default";
+
+		volup-key {
+			label = "Volume Up";
+			linux,code = <KEY_VOLUMEUP>;
+			gpios = <&gpa3 0 GPIO_ACTIVE_LOW>;
+			wakeup-source;
+		};
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>,
+		      <0x8 0x80000000 0x1 0x7e000000>;
+	};
+
+	/* TODO: Remove this once PMIC is implemented  */
+	reg_dummy: regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "dummy_reg";
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cont_splash_mem: framebuffer at f6200000 {
+			reg = <0x0 0xf6200000 0x0 (1080 * 2340 * 4)>;
+			no-map;
+		};
+
+		debug_kinfo_reserved: debug-kinfo-reserved at fcfff000 {
+			reg = <0x0 0xfcfff000 0x0 0x1000>;
+			no-map;
+		};
+
+		log_itmon: log-itmon at fffe0000 {
+			reg = <0x0 0xfffe0000 0x0 0x20000>;
+			no-map;
+		};
+	};
+};
+
+&cmu_hsi0 {
+	clocks = <&xtcxo>,
+		 <&rtcclk>,
+		 <&cmu_top CLK_DOUT_CMU_HSI0_NOC>,
+		 <&cmu_top CLK_DOUT_CMU_HSI0_DPGTC>,
+		 <&cmu_top CLK_DOUT_CMU_HSI0_DPOSC>,
+		 <&cmu_top CLK_DOUT_CMU_HSI0_USB32DRD>;
+	clock-names = "oscclk", "rtcclk", "noc", "dpgtc", "dposc", "usb";
+};
+
+&ext_26m {
+	clock-frequency = <26000000>;
+};
+
+&ext_200m {
+	clock-frequency = <200000000>;
+};
+
+&mct_peris {
+	status = "okay";
+};
+
+&pinctrl_alive {
+	key_volup: key-volup-pins {
+		samsung,pins = "gpa3-0";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_F>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+	};
+};
+
+&ppi_cluster0 {
+	affinity = <&cpu0 &cpu1>;
+};
+
+&usb {
+	/* TODO: Replace these once PMIC is implemented  */
+	vdd10-supply = <&reg_dummy>;
+	vdd33-supply = <&reg_dummy>;
+	status = "okay";
+};
+
+&usb32drd {
+	status = "okay";
+};
+
+&usb_dwc3 {
+	dr_mode = "otg";
+	usb-role-switch;
+	role-switch-default-mode = "peripheral";
+	maximum-speed = "high-speed";
+};
+
+&usb_hsphy {
+	/* TODO: Replace these once PMIC is implemented  */
+	vdda12-supply = <&reg_dummy>;
+	vdd-supply = <&reg_dummy>;
+	status = "okay";
+};
+
+&xtcxo {
+	clock-frequency = <76800000>;
+};
-- 
2.43.0



From robh at kernel.org  Fri Mar 21 08:05:32 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 21 Mar 2025 10:05:32 -0500
Subject: [PATCH v5 0/2] Add Meta(Facebook) Ventura BMC(AST2600)
In-Reply-To: <20250321123731.1373596-1-jason-hsu@quantatw.com>
References: <20250321123731.1373596-1-jason-hsu@quantatw.com>
Message-ID: <174256796315.3336760.12396122805182974784.robh@kernel.org>


On Fri, 21 Mar 2025 20:37:29 +0800, Jason Hsu wrote:
> Add Linux device tree entry related to Meta(Facebook) Ventura specific
> devices connected to BMC(AST2600) SoC.
> 
> ---
> v1:
>     1. Create ventura dts file.
>     2. Add commit msg.
>     3. Use format-patch to generate patch.
>     4. Add subject prefixes matching the subsystem.
> ---
> v2:
>     1. Modify email content.
> ---
> v3:
>     1. Add mail list.
> ---
> v4:
>     1. Apply git send-email --thread option.
>     2. Sort nodes in the dts alphanumerically.
> ---
> v5:
>     1. Run scripts/checkpatch.pl and fix reported warnings.
>     2. Remove unnecessary 88E6393X CONFIG FRU.
> ---
> v6:
>     1. Add a new stage for the DTS change.
>     2. Run scripts/checkpatch.pl and fix reported error.
>     3. Fix the issue in a separate patch.
> ---
> Signed-off-by: Jason-Hsu <jasonhell19 at gmail.com>
> 
> Jason Hsu (2):
>   dt-bindings: arm: aspeed: add Meta Ventura board
>   ARM: dts: aspeed: ventura: add Meta Ventura BMC
> 
>  .../bindings/arm/aspeed/aspeed.yaml           |    1 +
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-facebook-ventura.dts    | 1399 +++++++++++++++++
>  3 files changed, 1401 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dts
> 
> 
> base-commit: b3ee1e4609512dfff642a96b34d7e5dfcdc92d05
> --
> 2.34.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250321123731.1373596-1-jason-hsu at quantatw.com:

arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/video at 1e700000: failed to match any schema with compatible: ['aspeed,ast2600-video-engine']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura.dtb: /ahb/apb/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']
arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-e3c256d4i.dtb: /ahb/apb/pwm-tacho-controller at 1e786000: failed to match any schema with compatible: ['aspeed,ast2500-pwm-tacho']







From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 08:13:29 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 17:13:29 +0200
Subject: [PATCH v3 06/10] phy: phy-snps-eusb2: make repeater optional
In-Reply-To: <20250321135854.1431375-7-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-7-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <m6uabp57a2kskyspnrz65frcf7dqkljmdeffupqkcni5qbgya7@cwmdcac5eh52>

On Fri, Mar 21, 2025 at 03:58:50PM +0200, Ivaylo Ivanov wrote:
> As described in the device tree bindings, it's not necessary for the
> SNPS eUSB2 phy to be connected to a repeater. In configurations where
> there are such instances, the driver probing fails and the usb
> controller does not work.
> 
> Make the repeater optional to avoid that, which also lets us use
> the eUSB2 phy when it's connected to a repeater that is not configurable
> by the kernel (for example it's missing a driver), as long as it has
> been configured beforehand (usually by the bootloader).
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> Acked-by: Neil Armstrong <neil.armstrong at linaro.org>
> ---
>  drivers/phy/phy-snps-eusb2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

-- 
With best wishes
Dmitry


From mathis.foerst at mt.com  Fri Mar 21 08:06:14 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 21 Mar 2025 16:06:14 +0100
Subject: [PATCH v4 0/1] media: imx: csi: Parse link configuration from fw_node
Message-ID: <20250321150615.381112-1-mathis.foerst@mt.com>

Hi,

this patch fixes the imx-media-csi driver to work with camera drivers that
do not implement the subdev-pad-operation "get_mbus_format".

Changelog:
v3 -> v4:
- Determine the expected mbus_type based on the link topology. If the
  parallel port is used, try to parse the endpoint as V4L2_MBUS_PARALLEL
  and as V4L2_MBUS_BT656.

v2 -> v3:
- Factor out the function "csi_parse_upstream_fw_link_config" for better
  readability.

v1 -> v2:
- No changes (I submitted the wrong patch. I'm sorry for that)

It's the follow up of this discussion:
https://lore.kernel.org/linux-media/Z8AoA6WjbXQufqR6 at kekkonen.localdomain/

I tested the changes successfully on an i.MX6DL with an MT9M114 and an
MT9V032 camera. They both use the parallel camera interface.
Sadly, I don't have the hardware to test with a MIPI CSI-2 camera.

Best regards,
Mathis Foerst


Mathis Foerst (1):
  media: imx: csi: Parse link configuration from fw_node

 drivers/staging/media/imx/imx-media-csi.c | 62 +++++++++++++++++++++--
 1 file changed, 58 insertions(+), 4 deletions(-)


base-commit: ac9c34d1e45a4c25174ced4fc0cfc33ff3ed08c7
-- 
2.34.1



From mathis.foerst at mt.com  Fri Mar 21 08:06:15 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 21 Mar 2025 16:06:15 +0100
Subject: [PATCH v4 1/1] media: imx: csi: Parse link configuration from fw_node
In-Reply-To: <20250321150615.381112-1-mathis.foerst@mt.com>
References: <20250321150615.381112-1-mathis.foerst@mt.com>
Message-ID: <20250321150615.381112-2-mathis.foerst@mt.com>

The imx-media-csi driver requires upstream camera drivers to implement
the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
implement this function are not usable on the i.MX6.

The docs for get_mbus_config [1] say:
@get_mbus_config: get the media bus configuration of a remote sub-device.
            The media bus configuration is usually retrieved from the
            firmware interface at sub-device probe time, immediately
            applied to the hardware and eventually adjusted by the
            driver.

Currently, the imx-media-csi driver is not incorporating the information
from the firmware interface and therefore relies on the implementation of
get_mbus_config by the camera driver.

To be compatible with camera drivers not implementing get_mbus_config
(which is the usual case), use the bus information from the fw interface:

The camera does not necessarily has a direct media bus link to the CSI as
the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
between them on the media pipeline.
The CSI driver already implements the functionality to find the connected
camera sub-device to call get_mbus_config on it.

At this point the driver is modified as follows:
In the case that get_mbus_config is not implemented by the upstream
camera, try to get its endpoint configuration from the firmware interface
usign v4l2_fwnode_endpoint_parse.
For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
configuration.
For all other mbus_types, return an error.

Note that parsing the mbus_config from the fw interface is not done during
probing because the camera that's connected to the CSI can change based on
the selected input of the video-mux at runtime.

[0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
[1] include/media/v4l2-subdev.h - line 814

Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
---
 drivers/staging/media/imx/imx-media-csi.c | 62 +++++++++++++++++++++--
 1 file changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 3edbc57be2ca..bb5437d9c033 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -158,6 +158,50 @@ static inline bool requires_passthrough(struct v4l2_mbus_config *mbus_cfg,
 		 infmt->code != MEDIA_BUS_FMT_YUYV8_2X8);
 }
 
+static int csi_parse_upstream_fw_link_config(struct csi_priv *priv,
+					     struct v4l2_subdev *remote_sd,
+					     struct v4l2_mbus_config *mbus_cfg)
+{
+	struct fwnode_handle *ep_node;
+	struct v4l2_fwnode_endpoint ep = { .bus_type = mbus_cfg->type };
+	int ret;
+
+	ep_node = fwnode_graph_get_endpoint_by_id(dev_fwnode(remote_sd->dev),
+						  0, 0,
+						  FWNODE_GRAPH_ENDPOINT_NEXT);
+	if (!ep_node)
+		return -ENOTCONN;
+
+	ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
+	/*
+	 * Retry with V4L2_MBUS_BT656 if parsing fails with V4L2_MBUS_PARALLEL
+	 * as the parallel interface supports both MBUS types.
+	 */
+	if (ret == -ENXIO && mbus_cfg->type == V4L2_MBUS_PARALLEL) {
+		ep.bus_type = V4L2_MBUS_BT656;
+		ret = v4l2_fwnode_endpoint_parse(ep_node, &ep);
+	}
+	fwnode_handle_put(ep_node);
+	if (ret)
+		return ret;
+
+	switch (ep.bus_type) {
+	case V4L2_MBUS_PARALLEL:
+	case V4L2_MBUS_BT656:
+		mbus_cfg->bus.parallel = ep.bus.parallel;
+		break;
+	case V4L2_MBUS_CSI2_DPHY:
+		mbus_cfg->bus.mipi_csi2 = ep.bus.mipi_csi2;
+		break;
+	default:
+		v4l2_err(&priv->sd, "Unsupported mbus_type: %i\n",
+			 ep.bus_type);
+		return -EINVAL;
+	}
+	mbus_cfg->type = ep.bus_type;
+	return 0;
+}
+
 /*
  * Queries the media bus config of the upstream entity that provides data to
  * the CSI. This will either be the entity directly upstream from the CSI-2
@@ -175,6 +219,7 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 		return -EPIPE;
 
 	sd = priv->src_sd;
+	mbus_cfg->type = V4L2_MBUS_CSI2_DPHY;
 
 	switch (sd->grp_id) {
 	case IMX_MEDIA_GRP_ID_CSI_MUX:
@@ -186,8 +231,14 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 		sd = imx_media_pipeline_subdev(&sd->entity,
 					       IMX_MEDIA_GRP_ID_CSI2,
 					       true);
-		if (IS_ERR(sd))
+		if (IS_ERR(sd)) {
 			sd = priv->src_sd;
+			/*
+			 * If the CSI-2 receiver is not on the path, the
+			 * parallel port is in use.
+			 */
+			mbus_cfg->type = V4L2_MBUS_PARALLEL;
+		}
 		break;
 	case IMX_MEDIA_GRP_ID_CSI2:
 		break;
@@ -211,9 +262,12 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
 	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
 			       remote_pad->index, mbus_cfg);
 	if (ret == -ENOIOCTLCMD)
-		v4l2_err(&priv->sd,
-			 "entity %s does not implement get_mbus_config()\n",
-			 remote_pad->entity->name);
+		/*
+		 * If the upstream sd does not implement get_mbus_config,
+		 * try to parse the link configuration from its fw_node
+		 */
+		ret = csi_parse_upstream_fw_link_config(priv, remote_sd,
+							mbus_cfg);
 
 	return ret;
 }
-- 
2.34.1



From mathis.foerst at mt.com  Fri Mar 21 08:28:23 2025
From: mathis.foerst at mt.com (Mathis Foerst)
Date: Fri, 21 Mar 2025 16:28:23 +0100
Subject: [PATCH v1 1/1] media: imx: csi: Parse link configuration from
 fw_node
In-Reply-To: <Z9RP5K59sZwuphIc@valkosipuli.retiisi.eu>
References: <20250305113802.897087-1-mathis.foerst@mt.com>
 <20250305113802.897087-2-mathis.foerst@mt.com>
 <Z8nOTrjEW_OYBGlq@valkosipuli.retiisi.eu>
 <84aa2d87-d7f1-46c9-b28d-6f0e9a78788d@stanley.mountain>
 <Z8oQCuqKVH225lPw@valkosipuli.retiisi.eu>
 <Z8r21Z2HthBwGDSq@mt.com>
 <Z86-AFnPQ2wXKidi@valkosipuli.retiisi.eu>
 <Z9RKllMJ0Duac83Y@mt.com>
 <Z9RP5K59sZwuphIc@valkosipuli.retiisi.eu>
Message-ID: <Z92Fl+85ZpJmRL0F@mt.com>

Hi Sakari

On Fri, Mar 14, 2025 at 03:48:52PM +0000, Sakari Ailus wrote:
> Hi Mathis,
> 
> On Fri, Mar 14, 2025 at 04:26:14PM +0100, Mathis Foerst wrote:
> > On Mon, Mar 10, 2025 at 10:25:04AM +0000, Sakari Ailus wrote:
> > Hi Sakari,
> > 
> > > Hi Mathis,
> > > 
> > > On Fri, Mar 07, 2025 at 02:38:29PM +0100, Mathis Foerst wrote:
> > > > Hi Sakari, Hi Dan,
> > > > 
> > > > thanks a lot for your feedback.
> > > > 
> > > > On Thu, Mar 06, 2025 at 09:13:46PM +0000, Sakari Ailus wrote:
> > > > > Hi Dan,
> > > > > 
> > > > > On Thu, Mar 06, 2025 at 10:07:20PM +0300, Dan Carpenter wrote:
> > > > > > On Thu, Mar 06, 2025 at 04:33:18PM +0000, Sakari Ailus wrote:
> > > > > > > Hi Mathis,
> > > > > > > 
> > > > > > > Thanks for the patch.
> > > > > > > 
> > > > > > > On Wed, Mar 05, 2025 at 12:38:02PM +0100, Mathis Foerst wrote:
> > > > > > > > The imx-media-csi driver requires upstream camera drivers to implement
> > > > > > > > the subdev-pad-op "get_mbus_config" [0]. Camera drivers that don't
> > > > > > > > implement this function are not usable on the i.MX6.
> > > > > > > > 
> > > > > > > > The docs for get_mbus_config [1] say:
> > > > > > > > @get_mbus_config: get the media bus configuration of a remote sub-device.
> > > > > > > >             The media bus configuration is usually retrieved from the
> > > > > > > >             firmware interface at sub-device probe time, immediately
> > > > > > > >             applied to the hardware and eventually adjusted by the
> > > > > > > >             driver.
> > > > > > > > 
> > > > > > > > Currently, the imx-media-csi driver is not incorporating the information
> > > > > > > > from the firmware interface and therefore relies on the implementation of
> > > > > > > > get_mbus_config by the camera driver.
> > > > > > > > 
> > > > > > > > To be compatible with camera drivers not implementing get_mbus_config
> > > > > > > > (which is the usual case), use the bus information from the fw interface:
> > > > > > > > 
> > > > > > > > The camera does not necessarily has a direct media bus link to the CSI as
> > > > > > > > the video-mux and/or the MIPI CSI-2 receiver of the i.MX6 might be in
> > > > > > > > between them on the media pipeline.
> > > > > > > > The CSI driver already implements the functionality to find the connected
> > > > > > > > camera sub-device to call get_mbus_config on it.
> > > > > > > > 
> > > > > > > > At this point the driver is modified as follows:
> > > > > > > > In the case that get_mbus_config is not implemented by the upstream
> > > > > > > > camera, try to get its endpoint configuration from the firmware interface
> > > > > > > > usign v4l2_fwnode_endpoint_parse.
> > > > > > > > For the supported mbus_types (V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656 and
> > > > > > > > V4L2_MBUS_CSI2_DPHY), extract the mbus_config from the endpoint
> > > > > > > > configuration.
> > > > > > > > For all other mbus_types, return an error.
> > > > > > > > 
> > > > > > > > Note that parsing the mbus_config from the fw interface is not done during
> > > > > > > > probing because the camera that's connected to the CSI can change based on
> > > > > > > > the selected input of the video-mux at runtime.
> > > > > > > > 
> > > > > > > > [0] drivers/staging/media/imx/imx-media-csi.c - line 211..216
> > > > > > > > [1] include/media/v4l2-subdev.h - line 814
> > > > > > > > 
> > > > > > > > Signed-off-by: Mathis Foerst <mathis.foerst at mt.com>
> > > > > > > > ---
> > > > > > > >  drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++---
> > > > > > > >  1 file changed, 32 insertions(+), 4 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > > index 3edbc57be2ca..394a9321a10b 100644
> > > > > > > > --- a/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > > +++ b/drivers/staging/media/imx/imx-media-csi.c
> > > > > > > > @@ -169,6 +169,8 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > > > >  {
> > > > > > > >  	struct v4l2_subdev *sd, *remote_sd;
> > > > > > > >  	struct media_pad *remote_pad;
> > > > > > > > +	struct fwnode_handle *ep_node;
> > > > > > > > +	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
> > > > > > > 
> > > > > > > Are there any defaults in DT bindings (other than 0's)? Also initialising a
> > > > > > > field to zero this way is redundant, just use {}.
> > > > > > > 
> > > > > > 
> > > > > > I was going to respond in much the same way.  This is equivalen to:
> > > > > > 
> > > > > > struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_UNKNOWN };
> > > > > 
> > > > > Thinking about this in a context of parsing the endpoint, in fact the
> > > > > bus_type should be specified. Presumably the hardware is D-PHY, so the
> > > > > correct value would be V4L2_MBUS_CSI2_DPHY. This way
> > > > > v4l2_fwnode_endpoint_parse() doesn't need to guess.
> > > > 
> > > > I think we must use "bus_type = V4L2_MBUS_UNKNOWN" here:
> > > > 
> > > > The i.MX6 has two types of camera interfaces: Parallel and MIPI CSI-2.
> > > > They are connected either directly or via a video-mux to the CSIs
> > > > (See IMX6DQRM.pdf - Figure 9-3 for the connection diagram)
> > > > 
> > > > Pre-defining V4L2_MBUS_CSI2_DPHY here would let
> > > > v4l2_fwnode_endpoint_parse() fail if the camera uses the parallel bus.
> > > > 
> > > > We could distinguish between MIPI CSI-2 and Parallel input by checking
> > > > the grp_id of the upstream device like it's already done in
> > > > csi_get_upstream_mbus_config().
> > > > But for the Parallel case we still can't know if we should set bus_type
> > > > to V4L2_MBUS_PARALLEL or to V4L2_MBUS_BT656 - the i.MX6 supports both
> > > > formats on the parallel interface.
> > > > 
> > > > That's why I would argue that v4l2_fwnode_endpoint_parse() must figure
> > > > out the bus_type from the fw node.
> > > 
> > > Right, nowadays you can indeed do this -- it wasn't a long ago when you
> > > couldn't. I presume the bindings do specify the bus-type property is
> > > mandatory? Where are the bindings btw.?
> > > 
> > 
> > From my understanding, it's not even required to set the bus-type as 
> > v4l2_fwnode_endpoint_parse() will try to parse the endpoint first as a
> > CSI-2 bus and in case of failure as a Parallel bus if the bus-type is
> > unknown (see drivers/media/v4l2-core/v4l2-fwnode.c#L493).
> 
> It only exists for compatibility with old drivers. Do not add new users for
> this code.
> 
> > 
> > About the bindings:
> > 
> > There are bindings for the MIPI CSI-2 receiver:
> > Documentation/devicetree/bindings/media/imx.txt
> > I think here it's not necessary to make the bus-type property mandatory
> > as the imx6-mipi-csi2 driver enforces V4L2_MBUS_CSI2_DPHY anyhow
> > (see drivers/staging/media/imx/imx6-mipi-csi2.c#L677).
> 
> That seems to document a CSI-2 to parallel bridge, with support for four
> virtual channels. I'd suppose you parse the ports knowing which interface
> they use.

Yes, the video-mux has 5 input channels: 4 for the virtual MIPI channels
and one for the parallel port.
I now used this to determine the port type before parsing the endpoint.
If the parallel port is used, I must try to parse the endpoint as
V4L2_MBUS_PARALLEL and as V4L2_MBUS_BT656 because both formats are
possible on this port.

I submitted an updated version of the patch.

> 
> > 
> > For the case of a camera with parallel bus, the camera endpoint is
> > connected to a video-mux and not directly to the CSI. Therefore, we cannot
> > make the bus-type property mandatory on this endpoint as it this wouldn't
> > apply to other use-cases of video-mux.
> > 
> > > > 
> > > > > 
> > > > > > 
> > > > > > > >  	int ret;
> > > > > > > >  
> > > > > > > >  	if (!priv->src_sd)
> > > > > > > > @@ -210,11 +212,37 @@ static int csi_get_upstream_mbus_config(struct csi_priv *priv,
> > > > > > > >  
> > > > > > > >  	ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
> > > > > > > >  			       remote_pad->index, mbus_cfg);
> > > > > > > > -	if (ret == -ENOIOCTLCMD)
> > > > > > > > -		v4l2_err(&priv->sd,
> > > > > > > > -			 "entity %s does not implement get_mbus_config()\n",
> > > > > > > > -			 remote_pad->entity->name);
> > > > > > > > +	if (ret == -ENOIOCTLCMD) {
> > > > > > > 
> > > > > > > 	if (!ret)
> > > > > > > 		return 0;
> > > > > > > 
> > > > > > > And you can unindent the rest.
> > > > > > 
> > > > > > I was going to say this too but then I thought actually this needs to
> > > > > > be:
> > > > > > 
> > > > > > 	if (ret != -ENOIOCTLCMD)
> > > > > > 		return ret;
> > > > > > 
> > > > > > Which is weird.  Better to break all the new code into a separate
> > > > > > helper function.
> > > > > > 
> > > > > > 	if (ret == -ENOIOCTLCMD)
> > > > > > 		ret = parse_fw_link_config_stuff();
> > > > > > 
> > > > > > 	return ret;
> > > > 
> > > > Good point. I factored out a helper function as suggested.
> > > > 
> > > > > 
> > > > > Indeed. get_mbus_config() presumably wouldn't return an error but
> > > > > correctness is usually a good idea.
> > > > > 
> > > 
> 
> -- 
> Regards,
> 
> Sakari Ailus

Best regards,
Mathis Foerst


From jbrunet at baylibre.com  Fri Mar 21 08:46:10 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 21 Mar 2025 16:46:10 +0100
Subject: [PATCH 2/3] clk: amlogic: drop clk_regmap tables
In-Reply-To: <5109de7fe1a1a8467118daf80c7b7f8a.sboyd@kernel.org> (Stephen
	Boyd's message of "Thu, 27 Feb 2025 14:55:00 -0800")
References: <20241220-amlogic-clk-drop-clk-regmap-tables-v1-0-96dd657cbfbd@baylibre.com>
	<20241220-amlogic-clk-drop-clk-regmap-tables-v1-2-96dd657cbfbd@baylibre.com>
	<9f1d69ebe1ddce5dfc170e986c9213f2.sboyd@kernel.org>
	<1ja5cp8f87.fsf@starbuckisacylon.baylibre.com>
	<88fe909ab182d1f17f6ef18161c7f064.sboyd@kernel.org>
	<1jfrlwb69r.fsf@starbuckisacylon.baylibre.com>
	<ed20c67e7d1a91d7fd8b921f156f56fb.sboyd@kernel.org>
	<1jmsg2adgu.fsf@starbuckisacylon.baylibre.com>
	<697b634770d789ef8ff0e05cec9465f5.sboyd@kernel.org>
	<1j4j205ark.fsf@starbuckisacylon.baylibre.com>
	<5109de7fe1a1a8467118daf80c7b7f8a.sboyd@kernel.org>
Message-ID: <1j7c4i2xq5.fsf@starbuckisacylon.baylibre.com>

On Thu 27 Feb 2025 at 14:55, Stephen Boyd <sboyd at kernel.org> wrote:

> Quoting Jerome Brunet (2025-01-15 07:58:55)
>> 
>> I'd like to register controller init hook to apply on all the clocks of
>> a particular type. The reason to do that is to drop the big clk_regmap
>> table that are a pain to maintain (in addition to be ugly). I hoped it
>> would also save a bit of memory.
>> 
>> The solutions we've been discussing so far feels like we are moving
>> around the problem, recreating the memory saved somewhere else,
>> perhaps in a more complicated way. I'd like to find something more
>> convinient to use, which does not scale the memory used with the number
>> of clock registered. The point is not a different hook for clk_hw after
>> all.
>
> What are the goals?
>
>  1. Drop clk_regmap table

That my first goal

>  2. Reduce memory

Would be nice

>  3. ??
>
>> 
>> Here is an idea, how about list of hook identified by ops and controller ?
>> 
>> The node would look like this
>> 
>> struct clk_type_init_node {
>>        struct list_head         entry;
>>        
>>        struct device_node       *of_node;
>>        struct device            *dev;
>>        const struct clk_ops     *ops;
>> 
>>        int (*init_hook)(struct clk_hw *hw);
>> };
>> 
>> The change would be minimal in core CCF, just searching the list for a
>> match in clk_register. On most platform the list would be empty so there
>> is virtually no penalty when it is not used.
>> 
>> From the controller, the usage would be very simple, just calling a
>> function before registering the clocks, something like:
>> 
>> int clk_type_register_dev_hook(struct device *dev,
>>                                const struct clk_ops *ops,
>>                                int (*init_hook)(struct clk_hw *hw))
>> 
>> or the 'of_node' equivalent.
>
> Why can't we register the clk at the same time? I don't understand why
> we want to search a list to match something up to what could be another
> argument to the clk registration API. Isn't this the same as 
>
>  clk_hw_register_data(struct device *dev, struct clk_hw *hw, const struct clk_register_data *data)
>
> Why is that hard to maintain? Is that because the clk driver is
> registering various different types of clks and it wants to do different
> stuff depending on the type of clk?

Exactly

> Why wouldn't wrapping the clk_ops
> in another struct and then using container_of to find the custom clk_ops
> not work there?

For this particular problem, it still does not scale well. There is more
than 20 different ops (and counting) for that clock type. Those would
need to be duplicated for each different way to get the regmap. That's
really not ideal

Side note: That's very interesting idea for another topic I'd like
address someday - not having all clock as global, but the just static data.
That would be a nice way to attach an allocator.

>
>> 
>> I admit this is heavily inspired by how devres works :) but it does solve
>> the early clock controller problem and does not scale with the number of
>> clock registered.
>> 
>
> I don't know if devres is a good model. It's about tracking allocations
> and things to undo later, not really to track things to do when called
> initially.

My point was more the decoupling it allows.
Maybe it is me being too picky, but what I'm trying to do is related to the
clock type, so it bothers me when it scales with the number of instances
instead of the type.

More generally, something devres-like allows to register an attribute
and link it to a group. Then the group members come and just pick what
they need. Whatever manages the attribute does not have to track
them. That is pretty much aligned with what I'm trying to do.

-- 
Jerome


From jeff.hugo at oss.qualcomm.com  Fri Mar 21 08:48:04 2025
From: jeff.hugo at oss.qualcomm.com (Jeff Hugo)
Date: Fri, 21 Mar 2025 09:48:04 -0600
Subject: [PATCH v2 4/7] accel/rocket: Add a new driver for Rockchip's NPU
In-Reply-To: <20250225-6-10-rocket-v2-4-d4dbcfafc141@tomeuvizoso.net>
References: <20250225-6-10-rocket-v2-0-d4dbcfafc141@tomeuvizoso.net>
 <20250225-6-10-rocket-v2-4-d4dbcfafc141@tomeuvizoso.net>
Message-ID: <f96b313a-fa0d-45d6-b358-8d2da40a9b95@oss.qualcomm.com>

On 2/25/2025 12:55 AM, Tomeu Vizoso wrote:
>   
> diff --git a/Documentation/accel/rocket/index.rst b/Documentation/accel/rocket/index.rst
> new file mode 100644
> index 0000000000000000000000000000000000000000..ad33194dec0325d0dab362768fd349e8dc286970
> --- /dev/null
> +++ b/Documentation/accel/rocket/index.rst
> @@ -0,0 +1,19 @@
> +.. SPDX-License-Identifier: GPL-2.0-only
> +
> +=====================================
> + accel/rocket Rockchip NPU driver
> +=====================================
> +
> +The accel/rocket driver supports the Neural Processing Units (NPUs) inside some Rockchip SoCs such as the RK3588. Rockchip calls it RKNN and sometimes RKNPU.
> +
> +This NPU is closely based on the NVDLA IP released by NVIDIA as open hardware in 2018, along with open source kernel and userspace drivers.
> +
> +The frontend unit in Rockchip's NPU though is completely different from that in the open source IP, so this kernel driver is specific to Rockchip's version.
> +
> +The hardware is described in chapter 36 in the RK3588 TRM.
> +
> +This driver just powers the hardware on and off, allocates and maps buffers to the device and submits jobs to the frontend unit. Everything else is done in userspace, as a Gallium driver that is part of the Mesa3D project.

Nit: name the specific Gallium driver here?

> diff --git a/drivers/accel/rocket/Kconfig b/drivers/accel/rocket/Kconfig
> new file mode 100644
> index 0000000000000000000000000000000000000000..83a401129ab2dc2847ccc30c6364e8802f43648d
> --- /dev/null
> +++ b/drivers/accel/rocket/Kconfig
> @@ -0,0 +1,25 @@
> +# SPDX-License-Identifier: GPL-2.0

I'm curious, is there a specific reason for "GPL-2.0"?  This tag is 
depreciated and everywhere else in the accel subsystem "GPL-2.0-only" is 
used.

Same comment for the Makefile and everything else in this patch.

> +
> +config DRM_ACCEL_ROCKET
> +       tristate "Rocket (support for Rockchip NPUs)"
> +       depends on DRM
> +       depends on ARM64 || COMPILE_TEST
> +       depends on MMU
> +       select DRM_SCHED
> +       select IOMMU_SUPPORT
> +       select IOMMU_IO_PGTABLE_LPAE
> +       select DRM_GEM_SHMEM_HELPER
> +       help
> +	  Choose this option if you have a Rockchip SoC that contains a
> +	  compatible Neural Processing Unit (NPU), such as the RK3588. Called by
> +	  Rockchip either RKNN or RKNPU, it accelerates inference of neural
> +	  networks.
> +
> +	  The interface exposed to userspace is described in
> +	  include/uapi/drm/rocket_accel.h and is used by the userspace driver in
> +	  Mesa3D.

Nit: name the specific Mesa driver here?

> +
> +	  If unsure, say N.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called rocket.
> diff --git a/drivers/accel/rocket/rocket_core.c b/drivers/accel/rocket/rocket_core.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..09d966c826b5b1090a18cb24b3aa4aba286a12d4
> --- /dev/null
> +++ b/drivers/accel/rocket/rocket_core.c
> @@ -0,0 +1,71 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright 2024 Tomeu Vizoso <tomeu at tomeuvizoso.net> */
> +
> +#include <linux/clk.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>

This list of includes seems insufficient. You use PTR_ERR but don't have 
the include for it (linux/err.h). Same for dev_err/dev_info. I'm 
guessing this comment applies elsewhere.

> +#include "rocket_core.h"
> +#include "rocket_registers.h"
> +
> +static int rocket_clk_init(struct rocket_core *core)
> +{
> +	struct device *dev = core->dev;
> +	int err;
> +
> +	core->a_clk = devm_clk_get(dev, "aclk");
> +	if (IS_ERR(core->a_clk)) {
> +		err = PTR_ERR(core->a_clk);
> +		dev_err(dev, "devm_clk_get_enabled failed %d for core %d\n", err, core->index);

Do you think it would be useful to mention "aclk" in the message? Seems 
like if this or the hclk get fails, you won't know just from the kernel log.

> +		return err;
> +	}
> +
> +	core->h_clk = devm_clk_get(dev, "hclk");
> +	if (IS_ERR(core->h_clk)) {
> +		err = PTR_ERR(core->h_clk);
> +		dev_err(dev, "devm_clk_get_enabled failed %d for core %d\n", err, core->index);
> +		clk_disable_unprepare(core->a_clk);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int rocket_core_init(struct rocket_core *core)
> +{
> +	struct device *dev = core->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	uint32_t version;
> +	int err = 0;
> +
> +	err = rocket_clk_init(core);
> +	if (err) {
> +		dev_err(dev, "clk init failed %d\n", err);

This feels redundant since rocket_clk_init() already printed an error 
message with more details.

> +		return err;
> +	}
> +
> +	core->iomem = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(core->iomem))
> +		return PTR_ERR(core->iomem);
> +
> +	pm_runtime_use_autosuspend(dev);
> +	pm_runtime_set_autosuspend_delay(dev, 50); /* ~3 frames */

Frames? That feels like a rendering term, but this driver is not doing 
rendering, right? Is there a better way to describe this?

> +	pm_runtime_enable(dev);
> +
> +	err = pm_runtime_get_sync(dev);
> +
> +	version = rocket_read(core, REG_PC_VERSION);
> +	version += rocket_read(core, REG_PC_VERSION_NUM) & 0xffff;
> +
> +	pm_runtime_mark_last_busy(dev);
> +	pm_runtime_put_autosuspend(dev);
> +
> +	dev_info(dev, "Rockchip NPU core %d version: %d\n", core->index, version);
> +
> +	return 0;
> +}
> +
> diff --git a/drivers/accel/rocket/rocket_device.c b/drivers/accel/rocket/rocket_device.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..ce3b533f15c1011d8a7a23dd8132e907cc334c58
> --- /dev/null
> +++ b/drivers/accel/rocket/rocket_device.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright 2024 Tomeu Vizoso <tomeu at tomeuvizoso.net> */
> +
> +#include <linux/clk.h>
> +
> +#include "rocket_device.h"
> +
> +int rocket_device_init(struct rocket_device *rdev)
> +{
> +	struct device *dev = rdev->cores[0].dev;
> +	int err;
> +
> +	rdev->clk_npu = devm_clk_get(dev, "npu");
> +	rdev->pclk = devm_clk_get(dev, "pclk");

Are these optional? It would appear that error handling is missing.

> +
> +	/* Initialize core 0 (top) */
> +	err = rocket_core_init(&rdev->cores[0]);
> +	if (err) {
> +		rocket_device_fini(rdev);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +static void rocket_drm_unbind(struct device *dev)
> +{
> +	struct rocket_device *rdev = dev_get_drvdata(dev);
> +	struct drm_device *ddev = &rdev->ddev;
> +
> +	drm_dev_unregister(ddev);

You allocated this with devm, shouldn't that make this unnecessary?

> +
> +	component_unbind_all(dev, rdev);
> +
> +	rocket_device_fini(rdev);
> +}


From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 08:53:01 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 17:53:01 +0200
Subject: [PATCH v3 08/10] phy: phy-snps-eusb2: refactor reference clock
 init
In-Reply-To: <20250321135854.1431375-9-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-9-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <vphiep5kvusrsyv76a3hdnkso35isoe76uy5hx2vm33tix7yxl@4qh6sk3xe3nu>

On Fri, Mar 21, 2025 at 03:58:52PM +0200, Ivaylo Ivanov wrote:
> Instead of matching frequencies with a switch and case, introduce
> a table-based lookup. This improves readability, reduces redundancy,
> and makes it easier to extend support for additional frequencies in
> the future.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  drivers/phy/phy-snps-eusb2.c | 61 +++++++++++++++++++-----------------
>  1 file changed, 32 insertions(+), 29 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

-- 
With best wishes
Dmitry


From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 08:53:38 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 17:53:38 +0200
Subject: [PATCH v3 09/10] phy: phy-snps-eusb2: add support for exynos2200
In-Reply-To: <20250321135854.1431375-10-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-10-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <wwvjm4576r437tf2thbqseca5fobedgrhjk52iegwz5qnlhfv4@pnsl3pvsefwq>

On Fri, Mar 21, 2025 at 03:58:53PM +0200, Ivaylo Ivanov wrote:
> The Exynos2200 SoC reuses the Synopsis eUSB2 PHY IP, alongside an
> external repeater, for USB 2.0. Add support for it to the existing
> driver, while keeping in mind that it requires enabled more than the
> reference clock.
> 
> Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1 at gmail.com>
> ---
>  drivers/phy/Kconfig          |   2 +-
>  drivers/phy/phy-snps-eusb2.c | 162 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 159 insertions(+), 5 deletions(-)
> 

Acked-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

-- 
With best wishes
Dmitry


From jbrunet at baylibre.com  Fri Mar 21 08:55:14 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 21 Mar 2025 16:55:14 +0100
Subject: [PATCH 2/3] clk: amlogic: drop clk_regmap tables
In-Reply-To: <1j7c4i2xq5.fsf@starbuckisacylon.baylibre.com> (Jerome Brunet's
	message of "Fri, 21 Mar 2025 16:46:10 +0100")
References: <20241220-amlogic-clk-drop-clk-regmap-tables-v1-0-96dd657cbfbd@baylibre.com>
	<20241220-amlogic-clk-drop-clk-regmap-tables-v1-2-96dd657cbfbd@baylibre.com>
	<9f1d69ebe1ddce5dfc170e986c9213f2.sboyd@kernel.org>
	<1ja5cp8f87.fsf@starbuckisacylon.baylibre.com>
	<88fe909ab182d1f17f6ef18161c7f064.sboyd@kernel.org>
	<1jfrlwb69r.fsf@starbuckisacylon.baylibre.com>
	<ed20c67e7d1a91d7fd8b921f156f56fb.sboyd@kernel.org>
	<1jmsg2adgu.fsf@starbuckisacylon.baylibre.com>
	<697b634770d789ef8ff0e05cec9465f5.sboyd@kernel.org>
	<1j4j205ark.fsf@starbuckisacylon.baylibre.com>
	<5109de7fe1a1a8467118daf80c7b7f8a.sboyd@kernel.org>
	<1j7c4i2xq5.fsf@starbuckisacylon.baylibre.com>
Message-ID: <1j1puq2xb1.fsf@starbuckisacylon.baylibre.com>

On Fri 21 Mar 2025 at 16:46, Jerome Brunet <jbrunet at baylibre.com> wrote:

>>> 
>>> I admit this is heavily inspired by how devres works :) but it does solve
>>> the early clock controller problem and does not scale with the number of
>>> clock registered.
>>> 
>>
>> I don't know if devres is a good model. It's about tracking allocations
>> and things to undo later, not really to track things to do when called
>> initially.
>
> My point was more the decoupling it allows.
> Maybe it is me being too picky, but what I'm trying to do is related to the
> clock type, so it bothers me when it scales with the number of instances
> instead of the type.
>
> More generally, something devres-like allows to register an attribute
> and link it to a group. Then the group members come and just pick what
> they need. Whatever manages the attribute does not have to track
> them. That is pretty much aligned with what I'm trying to do.

Just to be clear, this idea is meant to live in /drivers/clk/meson, for
a start a least, not as something generic.

-- 
Jerome


From lorenzo at kernel.org  Fri Mar 21 08:52:36 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 21 Mar 2025 16:52:36 +0100
Subject: [PATCH] wifi: mt76: mt7996: remove duplicate check in
 mt7996_mcu_sta_mld_setup_tlv()
In-Reply-To: <fde7246b-08a2-4c2f-b2dc-c3fd0e6b300b@stanley.mountain>
References: <fde7246b-08a2-4c2f-b2dc-c3fd0e6b300b@stanley.mountain>
Message-ID: <Z92LRBMxyz4pS7my@lore-desk>

> The "msta_link" pointer has two NULL checks.  Delete the second check.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
>  drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 ---
>  1 file changed, 3 deletions(-)
> 

Acked-by: Lorenzo Bianconi <lorenzo at kernel.org>

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index ddd555942c73..03539e20f5c5 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -2242,9 +2242,6 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
>  		if (!link)
>  			continue;
>  
> -		if (!msta_link)
> -			continue;
> -
>  		mld_setup_link->wcid = cpu_to_le16(msta_link->wcid.idx);
>  		mld_setup_link->bss_idx = link->mt76.idx;
>  		mld_setup_link++;
> -- 
> 2.47.2
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/7c25a7b2/attachment.sig>

From quic_jhugo at quicinc.com  Fri Mar 21 08:56:22 2025
From: quic_jhugo at quicinc.com (Jeffrey Hugo)
Date: Fri, 21 Mar 2025 09:56:22 -0600
Subject: [PATCH v2 5/7] accel/rocket: Add IOCTL for BO creation
In-Reply-To: <20250225-6-10-rocket-v2-5-d4dbcfafc141@tomeuvizoso.net>
References: <20250225-6-10-rocket-v2-0-d4dbcfafc141@tomeuvizoso.net>
 <20250225-6-10-rocket-v2-5-d4dbcfafc141@tomeuvizoso.net>
Message-ID: <24721e4c-ea9e-4405-81f8-084b3ce8b138@quicinc.com>

On 2/25/2025 12:55 AM, Tomeu Vizoso wrote:
> +/**
> + * rocket_gem_create_object - Implementation of driver->gem_create_object.
> + * @dev: DRM device
> + * @size: Size in bytes of the memory the object will reference
> + *
> + * This lets the GEM helpers allocate object structs for us, and keep
> + * our BO stats correct.
> + */

I would expect that this would throw a warning when making the kernel 
documentation since you are not describing the return value.




From jeff.hugo at oss.qualcomm.com  Fri Mar 21 09:09:05 2025
From: jeff.hugo at oss.qualcomm.com (Jeff Hugo)
Date: Fri, 21 Mar 2025 10:09:05 -0600
Subject: [PATCH v2 6/7] accel/rocket: Add job submission IOCTL
In-Reply-To: <20250225-6-10-rocket-v2-6-d4dbcfafc141@tomeuvizoso.net>
References: <20250225-6-10-rocket-v2-0-d4dbcfafc141@tomeuvizoso.net>
 <20250225-6-10-rocket-v2-6-d4dbcfafc141@tomeuvizoso.net>
Message-ID: <4d617199-191c-47d9-a0f1-5bf9c149d09d@oss.qualcomm.com>

On 2/25/2025 12:55 AM, Tomeu Vizoso wrote:
> +/**
> + * struct drm_rocket_task - A task to be run on the NPU
> + *
> + * A task is the smallest unit of work that can be run on the NPU.
> + */
> +struct drm_rocket_task {
> +	/** DMA address to NPU mapping of register command buffer */
> +	__u64 regcmd;
> +
> +	/** Number of commands in the register command buffer */
> +	__u32 regcmd_count;
> +};
> +
> +/**
> + * struct drm_rocket_job - A job to be run on the NPU
> + *
> + * The kernel will schedule the execution of this job taking into account its
> + * dependencies with other jobs. All tasks in the same job will be executed
> + * sequentially on the same core, to benefit from memory residency in SRAM.
> + */
> +struct drm_rocket_job {
> +	/** Pointer to an array of struct drm_rocket_task. */
> +	__u64 tasks;
> +
> +	/** Pointer to a u32 array of the BOs that are read by the job. */
> +	__u64 in_bo_handles;
> +
> +	/** Pointer to a u32 array of the BOs that are written to by the job. */
> +	__u64 out_bo_handles;
> +
> +	/** Number of tasks passed in. */
> +	__u32 task_count;
> +
> +	/** Number of input BO handles passed in (size is that times 4). */
> +	__u32 in_bo_handle_count;
> +
> +	/** Number of output BO handles passed in (size is that times 4). */
> +	__u32 out_bo_handle_count;
> +};
> +
> +/**
> + * struct drm_rocket_submit - ioctl argument for submitting commands to the NPU.
> + *
> + * The kernel will schedule the execution of these jobs in dependency order.
> + */
> +struct drm_rocket_submit {
> +	/** Pointer to an array of struct drm_rocket_job. */
> +	__u64 jobs;
> +
> +	/** Number of jobs passed in. */
> +	__u32 job_count;
> +};

These 3 structs will be different sizes in 32-bit env vs 64-bit env. Yes 
the driver depends on ARM64, but compat (32-bit userspace with 64-bit 
kernel) is still possible. They should all be padded out to 64-bit 
alignment.  When you do that, you should specify that the padding must 
be zero, and check for that in the driver so that you have the option to 
use the padding in the future.


From quic_jhugo at quicinc.com  Fri Mar 21 09:15:25 2025
From: quic_jhugo at quicinc.com (Jeffrey Hugo)
Date: Fri, 21 Mar 2025 10:15:25 -0600
Subject: [PATCH v2 7/7] accel/rocket: Add IOCTLs for synchronizing memory
 accesses
In-Reply-To: <20250225-6-10-rocket-v2-7-d4dbcfafc141@tomeuvizoso.net>
References: <20250225-6-10-rocket-v2-0-d4dbcfafc141@tomeuvizoso.net>
 <20250225-6-10-rocket-v2-7-d4dbcfafc141@tomeuvizoso.net>
Message-ID: <6cf7d790-57a8-40b9-b5b0-dedfce78d074@quicinc.com>

On 2/25/2025 12:55 AM, Tomeu Vizoso wrote:
> +int rocket_ioctl_fini_bo(struct drm_device *dev, void *data, struct drm_file *file)
> +{
> +	struct drm_rocket_fini_bo *args = data;
> +	struct drm_gem_object *gem_obj;
> +	struct rocket_gem_object *rkt_obj;
> +	struct drm_gem_shmem_object *shmem_obj;
> +	struct rocket_device *rdev = to_rocket_device(dev);
> +
> +	gem_obj = drm_gem_object_lookup(file, args->handle);
> +	if (!gem_obj)
> +		return -ENOENT;
> +
> +	rkt_obj = to_rocket_bo(gem_obj);
> +	shmem_obj = &rkt_obj->base;
> +
> +	WARN_ON(rkt_obj->last_cpu_prep_op == 0);
> +
> +	for (unsigned int core = 1; core < rdev->num_cores; core++) {
> +		dma_sync_sgtable_for_device(rdev->cores[core].dev, shmem_obj->sgt,
> +					    rocket_op_to_dma_dir(rkt_obj->last_cpu_prep_op));
> +	}
> +
> +	rkt_obj->last_cpu_prep_op = 0;
> +
> +	drm_gem_object_put(gem_obj);
> +
> +	return 0;
> +}

flags must be 0, and you must check that here. You do not appear to be 
doing that. Otherwise, userspace may put a value in flags, which is 
ignored now, but later when you define flags for a purpose, existing 
userspace will be broken - a uapi violation.


From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 09:24:28 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 18:24:28 +0200
Subject: [PATCH v6 08/14] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz
 unit conversion overhead
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-8-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
 <20250318-phy-sam-hdptx-bpc-v6-8-8cb1678e7663@collabora.com>
Message-ID: <8eba44d0-1f4d-44df-a13f-994bd766dd31@oss.qualcomm.com>

On 18/03/2025 14:35, Cristian Ciocaltea wrote:
> The ropll_tmds_cfg table used to identify the configuration params for
> the supported rates expects the search key, i.e. bit_rate member of
> struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
> Hz).  This requires multiple conversions between these units being
> performed at runtime.
> 
> Improve implementation clarity and efficiency by consistently using the
> Hz unit throughout driver's internal data structures and functions.
> Also rename the rather misleading struct member.
> 
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>   drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++++------------
>   1 file changed, 39 insertions(+), 40 deletions(-)

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

-- 
With best wishes
Dmitry


From bvanassche at acm.org  Fri Mar 21 09:31:54 2025
From: bvanassche at acm.org (Bart Van Assche)
Date: Fri, 21 Mar 2025 09:31:54 -0700
Subject: [PATCH v4 1/1] scsi: ufs: core: add device level exception
 support
In-Reply-To: <4370b3a3b5a5675bb3e75aaa48a273674c159339.1742526978.git.quic_nguyenb@quicinc.com>
References: <4370b3a3b5a5675bb3e75aaa48a273674c159339.1742526978.git.quic_nguyenb@quicinc.com>
Message-ID: <6cc97521-aba1-439b-9c06-a5a06adea498@acm.org>

On 3/20/25 8:18 PM, Bao D. Nguyen wrote:
> The ufs device JEDEC specification version 4.1 adds support for the
> device level exception events. To support this new device level
> exception feature, expose two new sysfs nodes below to provide
> the user space access to the device level exception information.
> /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_count
> /sys/bus/platform/drivers/ufshcd/*/device_lvl_exception_id
> 
> The device_lvl_exception_count sysfs node reports the number of
> device level exceptions that have occurred since the last time
> this variable is reset. Writing a value of 0 will reset it.
> The device_lvl_exception_id reports the exception ID which is the
> qDeviceLevelExceptionID attribute of the device JEDEC specifications
> version 4.1 and later. The user space application can query these
> sysfs nodes to get more information about the device level exception.

Reviewed-by: Bart Van Assche <bvanassche at acm.org>


From helgaas at kernel.org  Fri Mar 21 09:32:40 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri, 21 Mar 2025 11:32:40 -0500
Subject: [PATCH v2 07/57] irqdomain: pci: Switch to of_fwnode_handle()
In-Reply-To: <20250319092951.37667-8-jirislaby@kernel.org>
Message-ID: <20250321163240.GA1130095@bhelgaas>

On Wed, Mar 19, 2025 at 10:29:00AM +0100, Jiri Slaby (SUSE) wrote:
> of_node_to_fwnode() is irqdomain's reimplementation of the "officially"
> defined of_fwnode_handle(). The former is in the process of being
> removed, so use the latter instead.

I'm fine with these and happy to apply via the PCI tree, but it sounds
like you're planning a v3 with a few updates, so I'll hold off for
now:

https://lore.kernel.org/r/4bc0e1ca-a523-424a-8759-59e353317fba at kernel.org


From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 09:31:08 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 18:31:08 +0200
Subject: [PATCH v6 13/14] phy: rockchip: samsung-hdptx: Optimize internal
 rate handling
In-Reply-To: <20250318-phy-sam-hdptx-bpc-v6-13-8cb1678e7663@collabora.com>
References: <20250318-phy-sam-hdptx-bpc-v6-0-8cb1678e7663@collabora.com>
 <20250318-phy-sam-hdptx-bpc-v6-13-8cb1678e7663@collabora.com>
Message-ID: <f3be50ff-53cd-4e8c-ade1-af8e4f2e1960@oss.qualcomm.com>

On 18/03/2025 14:35, Cristian Ciocaltea wrote:
> Drop the rate parameter from a bunch of internal helpers and, instead,
> make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
> data.
> 
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea at collabora.com>
> ---
>   drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 47 +++++++++++------------
>   1 file changed, 23 insertions(+), 24 deletions(-)

Acked-by: Dmitry Baryshkov <dmitry.baryshkov at oss.qualcomm.com>

-- 
With best wishes
Dmitry


From pabeni at redhat.com  Fri Mar 21 09:31:17 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Fri, 21 Mar 2025 17:31:17 +0100
Subject: [PATCH net-next v3 1/7] net: ethtool: netlink: Allow
 per-netdevice DUMP operations
In-Reply-To: <20250313182647.250007-2-maxime.chevallier@bootlin.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
 <20250313182647.250007-2-maxime.chevallier@bootlin.com>
Message-ID: <c4e5bd2f-6216-4f74-b677-46c79343eb21@redhat.com>

On 3/13/25 7:26 PM, Maxime Chevallier wrote:
> We have a number of netlink commands in the ethnl family that may have
> multiple objects to dump even for a single net_device, including :
> 
>  - PLCA, PSE-PD, phy: one message per PHY device
>  - tsinfo: one message per timestamp source (netdev + phys)
>  - rss: One per RSS context
> 
> To get this behaviour, these netlink commands need to roll a custom
> ->dumpit().
> 
> To prepare making per-netdev DUMP more generic in ethnl, introduce a
> member in the ethnl ops to indicate if a given command may allow
> pernetdev DUMPs (also referred to as filtered DUMPs).
> 
> Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> ---
>  net/ethtool/netlink.c | 45 +++++++++++++++++++++++++++++--------------
>  net/ethtool/netlink.h |  2 ++
>  2 files changed, 33 insertions(+), 14 deletions(-)
> 
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index a163d40c6431..7adede5e4ff1 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -587,21 +587,38 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
>  	int ret = 0;
>  
>  	rcu_read_lock();

Maintain the RCU read lock here is IMHO confusing...

> -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> -		dev_hold(dev);
> +	if (ctx->req_info->dev) {
> +		dev = ctx->req_info->dev;

.. as this is refcounted.

I suggest to move the rcu_read_lock inside the if.


>  		rcu_read_unlock();
> +		/* Filtered DUMP request targeted to a single netdev. We already
> +		 * hold a ref to the netdev from ->start()
> +		 */
> +		ret = ethnl_default_dump_one(skb, dev, ctx,
> +					     genl_info_dump(cb));
> +		rcu_read_lock();
> +		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
>  
> -		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
> +		if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
> +			ret = skb->len;
>  
> -		rcu_read_lock();
> -		dev_put(dev);
> +	} else {
> +		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> +			dev_hold(dev);
> +			rcu_read_unlock();
> +
> +			ret = ethnl_default_dump_one(skb, dev, ctx,
> +						     genl_info_dump(cb));
> +
> +			rcu_read_lock();
> +			dev_put(dev);
>  
> -		if (ret < 0 && ret != -EOPNOTSUPP) {
> -			if (likely(skb->len))
> -				ret = skb->len;
> -			break;
> +			if (ret < 0 && ret != -EOPNOTSUPP) {
> +				if (likely(skb->len))
> +					ret = skb->len;

IMHO a bit too many levels of indentation. It's possibly better to move
this code in a separate helper.

Thanks,

Paolo



From dan.carpenter at linaro.org  Fri Mar 21 09:36:44 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 19:36:44 +0300
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <20250320201914.48159-1-qasdev00@gmail.com>
References: <20250320201914.48159-1-qasdev00@gmail.com>
Message-ID: <46a714fb-8a14-4d24-a0a6-a22cc9d45768@stanley.mountain>

On Thu, Mar 20, 2025 at 08:19:14PM +0000, Qasim Ijaz wrote:
> If link_conf_dereference_protected() or mt7996_vif_link() 
> or link_sta_dereference_protected() fail the code jumps to
> the error_unlink label and returns ret which is uninitialised.
> 
> Fix this by setting err before jumping to error_unlink.
> 
> Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
> Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 91c64e3a0860..78f7f1fc867e 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
>  			continue;

What about if the list is empty or we hit this continue on every link?

regards,
dan carpenter

>  
>  		link_conf = link_conf_dereference_protected(vif, link_id);
> -		if (!link_conf)
> +		if (!link_conf) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
>  
>  		link = mt7996_vif_link(dev, vif, link_id);
> -		if (!link)
> +		if (!link) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
>  
>  		link_sta = link_sta_dereference_protected(sta, link_id);
> -		if (!link_sta)
> +		if (!link_sta) {
> +			err = -EINVAL
>  			goto error_unlink;
> +		}
>  
>  		err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
>  					       link_id);
> -- 
> 2.39.5
> 


From mike.leach at linaro.org  Fri Mar 21 09:40:53 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Fri, 21 Mar 2025 16:40:53 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com> <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
 <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
Message-ID: <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>

Hi

On Fri, 14 Mar 2025 at 15:25, Yeo Reum Yun <YeoReum.Yun at arm.com> wrote:
>
> Hi, Mike.
>
> > >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> > >  }
> > >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> > >
> > > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > > +{
> > > +       if (enable)
> > > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > > +
> >
> > Not sure why we have an "enable" parameter here - it completely
> > changes the meaning of the function - with no comment at the start.
>
> Sorry. But what I intended is to distinguish
>     - activation of config
>     - enable of activated config.
> Because, current coresight doesn't grab the module reference on enable of activate config,
> But It grabs that reference only in activation.
> That's why I used to "enable" parameter to distinguish this
> while I integrate with module_owner count.
>
> > >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> > >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > > -                       atomic_dec(&config_desc->active_cnt);
> > >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > > -                       cscfg_owner_put(config_desc->load_owner);
> > > +                       cscfg_config_desc_put(config_desc);
> > >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> > >                         break;
> > >                 }
> > > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > >                                      unsigned long cfg_hash, int preset)
> > >  {
> > >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > > -       const struct cscfg_config_desc *config_desc;
> > > +       struct cscfg_config_desc *config_desc;
> > >         unsigned long flags;
> > >         int err = 0;
> > >
> > > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> > >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > >                 config_desc = config_csdev_item->config_desc;
> > > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > > +                               cscfg_config_desc_get(config_desc, true)) {
> > >
> > This obfuscates the logic of the comparisons without good reason. With
> > the true parameter, the function does no "get" operation but just
> > replicates the logic being replaced - checking the active_cnt is
> > non-zero.
> >
> > Restore this to the original logic to make it readable again
>
> It's not a replicates of comparsion logic, but if true,

sorry - missed that point .

> It get the reference of active_cnt but not get module reference.
> The fundemental fault in the UAF becase of just "atomic_read()"
> so, it should hold reference in here.
>
> So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
> I think there're two way to modfiy.
>
>     1. cscfg_config_desc_get()/put() always grab/drop the module count.
>     2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
>         with cscfg_owner_get()/put()
>
> Any thougt?
>
> Thanks!
>
>

The get and put functions are asymmetrical w.r.t. owner.

The put will put owner if active count decrements to 0,
The get if not on enable path will put owner unconditionally.

This means that the caller has to work out the correct input conditions.

Might be better if:-

get_desc()
{
    if (! desc->refcnt) {
       if (!get_owner())
           return false;
   }
   desc->refcnt++;
    return true;
}

put_desc()
{
   desc->refcnt--;
  if (! desc->refcnt)
    put_owner()
}

and then change the enable_active_cfg matching logic to

if ( (desc->refcnt) && (desc->hash == hash) && get_desc()) {
     < set active cfg>
}



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From andre.draszik at linaro.org  Fri Mar 21 09:40:56 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 21 Mar 2025 16:40:56 +0000
Subject: [PATCH 0/2] firmware: exynos-acpm: allow use during system
 shutdown
Message-ID: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>

One user of this ACPM driver is a PMIC driver that needs to communicate
with the PMIC during late system shutdown and at that time we are not
allowed to sleep anymore.

This series address this by switching the code to using udelay() in the
specific case of system shutdown. This approach was inspired by I2C's
i2c_in_atomic_xfer_mode(), which has to deal with a similar corner
case.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Andr? Draszik (2):
      firmware: exynos-acpm: use ktime APIs for timeout detection
      firmware: exynos-acpm: allow use during system shutdown

 drivers/firmware/samsung/exynos-acpm.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)
---
base-commit: c4d4884b67802c41fd67399747165d65c770621a
change-id: 20250321-acpm-atomic-033775b051ef

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Fri Mar 21 09:40:57 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 21 Mar 2025 16:40:57 +0000
Subject: [PATCH 1/2] firmware: exynos-acpm: use ktime APIs for timeout
 detection
In-Reply-To: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
References: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
Message-ID: <20250321-acpm-atomic-v1-1-fb887bde7e61@linaro.org>

acpm_dequeue_by_polling() uses a loop counter and assumes that each
iteration of the loop takes 20us. It may take longer, though, because
usleep_range() may sleep a different amount.

Switch to using ktime_get() / ktime_after() to detect the timeout
condition more reliably.

This change also makes the code easier to follow and it allows us to
adjust the sleep without having to adjust the loop counter exit
condition. This will come in useful in a follow-up patch that changes
the delays.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/firmware/samsung/exynos-acpm.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..d7ed6b77a957af5db5beba7deecce13ac7b30fd2 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -32,8 +32,7 @@
 
 #define ACPM_PROTOCOL_SEQNUM		GENMASK(21, 16)
 
-/* The unit of counter is 20 us. 5000 * 20 = 100 ms */
-#define ACPM_POLL_TIMEOUT		5000
+#define ACPM_POLL_TIMEOUT_US		(100 * USEC_PER_MSEC)
 #define ACPM_TX_TIMEOUT_US		500000
 
 #define ACPM_GS101_INITDATA_BASE	0xa000
@@ -284,12 +283,13 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 				   const struct acpm_xfer *xfer)
 {
 	struct device *dev = achan->acpm->dev;
-	unsigned int cnt_20us = 0;
+	ktime_t timeout;
 	u32 seqnum;
 	int ret;
 
 	seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
 
+	timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
 	do {
 		ret = acpm_get_rx(achan, xfer);
 		if (ret)
@@ -300,11 +300,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 
 		/* Determined experimentally. */
 		usleep_range(20, 30);
-		cnt_20us++;
-	} while (cnt_20us < ACPM_POLL_TIMEOUT);
+	} while (!ktime_after(ktime_get(), timeout));
 
-	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx, cnt_20us = %d.\n",
-		achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us);
+	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
+		achan->id, seqnum, achan->bitmap_seqnum[0]);
 
 	return -ETIME;
 }

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Fri Mar 21 09:40:58 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Fri, 21 Mar 2025 16:40:58 +0000
Subject: [PATCH 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
References: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
Message-ID: <20250321-acpm-atomic-v1-2-fb887bde7e61@linaro.org>

We need to access the PMIC during late system shutdown and at that time
we are not allowed to sleep anymore.

To make this case work, detect this condition and use busy waiting via
udelay() instead of usleep_range() in that situation.

The code isn't switched over to udelay() unconditionally so as to not
waste resources during normal operation. acpm_may_sleep() was heavily
inspired by the I2C subsystem's i2c_in_atomic_xfer_mode().

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
udelay(10) causes a checkpatch warning (it suggests to use
usleep_range() instead for usec >= 10), but that's exactly what we can
not do.
Reducing the udelay to be smaller will generally cause the loop to be
iterated more than once, which I wanted to avoid.
I could reflow the code to hide the actual value from checkpatch, e.g.
with the help of a local variable if that is preferred to ignoring the
checkpatch warning.
---
 drivers/firmware/samsung/exynos-acpm.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index d7ed6b77a957af5db5beba7deecce13ac7b30fd2..33cde6e88e2c0773fdd36c80927c77d3bcb44135 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -15,6 +15,8 @@
 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/irqflags.h>
+#include <linux/kernel.h>
 #include <linux/mailbox/exynos-message.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
@@ -24,6 +26,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/preempt.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -272,6 +275,17 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
 	return 0;
 }
 
+/*
+ * When ACPM transfers happen very late, e.g. to access a PMIC when powering
+ * down, we can not sleep. We do want to sleep in the normal case, though, to
+ * avoid wasting CPU cycles!
+ */
+static bool acpm_may_sleep(void)
+{
+	return system_state <= SYSTEM_RUNNING ||
+		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
+}
+
 /**
  * acpm_dequeue_by_polling() - RX dequeue by polling.
  * @achan:	ACPM channel info.
@@ -299,7 +313,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 			return 0;
 
 		/* Determined experimentally. */
-		usleep_range(20, 30);
+		if (!acpm_may_sleep())
+			udelay(10);
+		else
+			usleep_range(20, 30);
 	} while (!ktime_after(ktime_get(), timeout));
 
 	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",

-- 
2.49.0.395.g12beb8f557-goog



From catalin.marinas at arm.com  Fri Mar 21 09:40:31 2025
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 21 Mar 2025 16:40:31 +0000
Subject: [PATCH] arm64: mm: Correct the update of max_pfn
In-Reply-To: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
References: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
Message-ID: <Z92Wf8SDt8lzFs7F@arm.com>

On Fri, Mar 21, 2025 at 03:00:19PM +0800, Zhenhua Huang wrote:
> Hotplugged memory can be smaller than the original memory. For example,
> on my target:
> 
> root at genericarmv8:~# cat /sys/kernel/debug/memblock/memory
>    0: 0x0000000064005000..0x0000000064023fff    0 NOMAP
>    1: 0x0000000064400000..0x00000000647fffff    0 NOMAP
>    2: 0x0000000068000000..0x000000006fffffff    0 DRV_MNG
>    3: 0x0000000088800000..0x0000000094ffefff    0 NONE
>    4: 0x0000000094fff000..0x0000000094ffffff    0 NOMAP
> max_pfn will affect read_page_owner. Therefore, it should first compare and
> then select the larger value for max_pfn.
> 
> Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug")
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
> ---
>  arch/arm64/mm/mmu.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 1dfe1a8efdbe..310ff75891ef 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  		__remove_pgd_mapping(swapper_pg_dir,
>  				     __phys_to_virt(start), size);
>  	else {
> -		max_pfn = PFN_UP(start + size);
> +		/* Address of hotplugged memory can be smaller */
> +		max_pfn = max(max_pfn, PFN_UP(start + size));
>  		max_low_pfn = max_pfn;
>  	}

I think this makes sense and also matches what x86 does. I'll queue it
at -rc1 as a fix.

Thanks.

-- 
Catalin


From robin.murphy at arm.com  Fri Mar 21 09:48:46 2025
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 21 Mar 2025 16:48:46 +0000
Subject: [PATCH v2 4/4] iommu: Get DT/ACPI parsing into the proper probe
 path
In-Reply-To: <ace3a01f-4700-4455-ada3-0f88fc8ea4cd@samsung.com>
References: <cover.1740753261.git.robin.murphy@arm.com>
 <e3b191e6fd6ca9a1e84c5e5e40044faf97abb874.1740753261.git.robin.murphy@arm.com>
 <CGME20250313095633eucas1p29cb55f2504b4bcf67c16b3bd3fa9b8cd@eucas1p2.samsung.com>
 <9b358d68-332e-404e-9a75-740297f7b28d@samsung.com>
 <417d6f59-0d78-4e81-ad0b-e06846f786b0@arm.com>
 <bf2adf5d-1432-4bb7-846c-e1bcfa84858b@samsung.com>
 <016bb7ca-f0d3-464e-ac74-46e6f78e90d7@arm.com>
 <b63ff6b4-9dc3-42ea-8b87-d4fdead8d0eb@arm.com>
 <cdc333e4-25bb-4171-9f6e-01f1de947db3@samsung.com>
 <d6cd5e64-e2c0-4c6e-9c89-ce8b3e0a4a5b@arm.com>
 <ace3a01f-4700-4455-ada3-0f88fc8ea4cd@samsung.com>
Message-ID: <135390b1-c0c5-4595-a3f3-1fb376473872@arm.com>

On 21/03/2025 12:15 pm, Marek Szyprowski wrote:
> On 17.03.2025 19:22, Robin Murphy wrote:
>> On 17/03/2025 7:37 am, Marek Szyprowski wrote:
>>> On 13.03.2025 15:12, Robin Murphy wrote:
>>>> On 2025-03-13 1:06 pm, Robin Murphy wrote:
>>>>> On 2025-03-13 12:23 pm, Marek Szyprowski wrote:
>>>>>> On 13.03.2025 12:01, Robin Murphy wrote:
>>>>>>> On 2025-03-13 9:56 am, Marek Szyprowski wrote:
>>>>>>> [...]
>>>>>>>> This patch landed in yesterday's linux-next as commit bcb81ac6ae3c
>>>>>>>> ("iommu: Get DT/ACPI parsing into the proper probe path"). In my
>>>>>>>> tests I
>>>>>>>> found it breaks booting of ARM64 RK3568-based Odroid-M1 board
>>>>>>>> (arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts). Here is the
>>>>>>>> relevant kernel log:
>>>>>>>
>>>>>>> ...and the bug-flushing-out begins!
>>>>>>>
>>>>>>>> Unable to handle kernel NULL pointer dereference at virtual address
>>>>>>>> 00000000000003e8
>>>>>>>> Mem abort info:
>>>>>>>>  ??? ? ESR = 0x0000000096000004
>>>>>>>>  ??? ? EC = 0x25: DABT (current EL), IL = 32 bits
>>>>>>>>  ??? ? SET = 0, FnV = 0
>>>>>>>>  ??? ? EA = 0, S1PTW = 0
>>>>>>>>  ??? ? FSC = 0x04: level 0 translation fault
>>>>>>>> Data abort info:
>>>>>>>>  ??? ? ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
>>>>>>>>  ??? ? CM = 0, WnR = 0, TnD = 0, TagAccess = 0
>>>>>>>>  ??? ? GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>>>>>>>> [00000000000003e8] user address but active_mm is swapper
>>>>>>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>>>>>>> Modules linked in:
>>>>>>>> CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc3+ #15533
>>>>>>>> Hardware name: Hardkernel ODROID-M1 (DT)
>>>>>>>> pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>>>>> pc : devm_kmalloc+0x2c/0x114
>>>>>>>> lr : rk_iommu_of_xlate+0x30/0x90
>>>>>>>> ...
>>>>>>>> Call trace:
>>>>>>>>  ??? ?devm_kmalloc+0x2c/0x114 (P)
>>>>>>>>  ??? ?rk_iommu_of_xlate+0x30/0x90
>>>>>>>
>>>>>>> Yeah, looks like this is doing something a bit questionable which
>>>>>>> can't
>>>>>>> work properly. TBH the whole dma_dev thing could probably be
>>>>>>> cleaned up
>>>>>>> now that we have proper instances, but for now does this work?
>>>>>>
>>>>>> Yes, this patch fixes the problem I've observed.
>>>>>>
>>>>>> Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>>>
>>>>>> BTW, this dma_dev idea has been borrowed from my exynos_iommu driver
>>>>>> and
>>>>>> I doubt it can be cleaned up.
>>>>>
>>>>> On the contrary I suspect they both can - it all dates back to when
>>>>> we had the single global platform bus iommu_ops and the SoC drivers
>>>>> were forced to bodge their own notion of multiple instances, but with
>>>>> the modern core code, ops are always called via a valid IOMMU
>>>>> instance or domain, so in principle it should always be possible to
>>>>> get at an appropriate IOMMU device now. IIRC it was mostly about
>>>>> allocating and DMA-mapping the pagetables in domain_alloc, where the
>>>>> private notion of instances didn't have enough information, but
>>>>> domain_alloc_paging solves that.
>>>>
>>>> Bah, in fact I think I am going to have to do that now, since although
>>>> it doesn't crash, rk_domain_alloc_paging() will also be failing for
>>>> the same reason. Time to find a PSU for the RK3399 board, I guess...
>>>>
>>>> (Or maybe just move the dma_dev assignment earlier to match Exynos?)
>>>
>>> Well I just found that Exynos IOMMU is also broken on some on my test
>>> boards. It looks that the runtime pm links are somehow not correctly
>>> established. I will try to analyze this later in the afternoon.
>>
>> Hmm, I tried to get an Odroid-XU3 up and running, but it seems unable
>> to boot my original 6.14-rc3-based branch - even with the IOMMU driver
>> disabled, it's consistently dying somewhere near (or just after) init
>> with what looks like some catastrophic memory corruption issue - very
>> occasionally it's managed to print the first line of various different
>> panics.
>>
>> Before that point though, with the IOMMU driver enabled it does appear
>> to show signs of working OK:
>>
>> [??? 0.649703] exynos-sysmmu 14650000.sysmmu: hardware version: 3.3
>> [??? 0.654220] platform 14450000.mixer: Adding to iommu group 1
>> ...
>> [??? 2.680920] exynos-mixer 14450000.mixer:
>> exynos_iommu_attach_device: Attached IOMMU with pgtable 0x42924000
>> ...
>> [??? 5.196674] exynos-mixer 14450000.mixer:
>> exynos_iommu_identity_attach: Restored IOMMU to IDENTITY from pgtable
>> 0x42924000
>> [??? 5.207091] exynos-mixer 14450000.mixer:
>> exynos_iommu_attach_device: Attached IOMMU with pgtable 0x42884000
>>
>>
>> The multi-instance stuff in probe/release does look a bit suspect,
>> however - seems like the second instance probe would overwrite the
>> first instance's links, and then there would be a double-del() if the
>> device were ever actually released again? I may have made that much
>> more likely to happen, but I suspect it was already possible with
>> async driver probe...
> 
> That is really strange. My Odroid XU3 boots fine from commit
> bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path"),
> although the IOMMU seems not to be working correctly. I've tested this
> with 14450000.mixer device (one need to attach HDMI cable to get it
> activated) and it looks that the video data are not being read from
> memory at all (the lack of VSYNC is reported, no IOMMU fault). However,
> from time to time, everything initializes and works properly.

Urgh, seems my mistake was assuming exynos_defconfig was the right thing 
to begin from - bcb81ac6ae3c with that still dies in the same way (this 
time I saw a hint of spin_bug() being hit...), however a 
multi_v7_defconfig build does get to userspace OK again with no obvious 
signs of distress:

[root at alarm ~]# grep -Hr . /sys/kernel/iommu_groups/*/type
/sys/kernel/iommu_groups/0/type:identity
/sys/kernel/iommu_groups/1/type:identity
/sys/kernel/iommu_groups/10/type:identity
/sys/kernel/iommu_groups/2/type:identity
/sys/kernel/iommu_groups/3/type:identity
/sys/kernel/iommu_groups/4/type:identity
/sys/kernel/iommu_groups/5/type:identity
/sys/kernel/iommu_groups/6/type:identity
/sys/kernel/iommu_groups/7/type:identity
/sys/kernel/iommu_groups/8/type:identity
/sys/kernel/iommu_groups/9/type:identity

Annoyingly I do have an adapter for the fiddly micro-HDMI, but it's at 
home :(

> It looks that this is somehow related to the different IOMMU/DMA-mapping
> glue code, as the other boards (ARM64 based) with exactly the same
> Exynos IOMMU driver always work fine. I've tried to figure out what
> actually happens, but so far I didn't get anything for sure. Disabling
> the call to dev->bus->dma_configure(dev) from iommu_init_device() seems
> to be fixing this, but this is almost equal to the revert of the
> $subject patch. I don't get why calling it in iommu_init_device() causes
> problems. It also doesn't look that this is anyhow related to the
> multi-instance stuff, as the same happens if I only leave a single
> exynos-sysmmu instance and its client (only 14450000.mixer device in the
> system).

On a hunch I stuck a print in exynos_iommu_probe_device(), and it looks 
like in fact device_link_add() isn't getting called at all, and indeed 
your symptoms do sound like they could be explained by the IOMMU not 
being reliably resumed... lemme stare at exynos_iommu_of_xlate() a bit 
longer...

Thanks,
Robin.


From linux at roeck-us.net  Fri Mar 21 10:05:55 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 21 Mar 2025 10:05:55 -0700
Subject: [PATCH v4 10/14] s390: Add support for suppressing warning
 backtraces
In-Reply-To: <20250313114329.284104-11-acarmina@redhat.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-11-acarmina@redhat.com>
Message-ID: <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>

On 3/13/25 04:43, Alessandro Carminati wrote:
> From: Guenter Roeck <linux at roeck-us.net>
> 
> Add name of functions triggering warning backtraces to the __bug_table
> object section to enable support for suppressing WARNING backtraces.
> 
> To limit image size impact, the pointer to the function name is only added
> to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
> CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
> parameter is replaced with a (dummy) NULL parameter to avoid an image size
> increase due to unused __func__ entries (this is necessary because
> __func__ is not a define but a virtual variable).
> 
> Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
> Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
> Cc: Heiko Carstens <hca at linux.ibm.com>
> Cc: Vasily Gorbik <gor at linux.ibm.com>
> Cc: Alexander Gordeev <agordeev at linux.ibm.com>
> Signed-off-by: Guenter Roeck <linux at roeck-us.net>
> Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
> ---
>   arch/s390/include/asm/bug.h | 17 ++++++++++++++---
>   1 file changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
> index c500d45fb465..44d4e9f24ae0 100644
> --- a/arch/s390/include/asm/bug.h
> +++ b/arch/s390/include/asm/bug.h
> @@ -8,6 +8,15 @@
>   
>   #ifdef CONFIG_DEBUG_BUGVERBOSE
>   
> +#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
> +# define HAVE_BUG_FUNCTION
> +# define __BUG_FUNC_PTR	"	.long	%0-.\n"
> +# define __BUG_FUNC	__func__

gcc 7.5.0 on s390 barfs; it doesn't like the use of "__func__" with "%0-."

drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c: In function 'anx_dp_aux_transfer':
././include/linux/compiler_types.h:492:20: warning: asm operand 0 probably doesn't match constraints

I was unable to find an alternate constraint that the compiler would accept.

I don't know if the same problem is seen with older compilers on other architectures,
or if the problem is relevant in the first place.

gcc 10.3.0 and later do not have this problem. I also tried s390 builds with gcc 9.4
and 9.5 but they both crash for unrelated reasons.

If this is a concern, the best idea I have is to make KUNIT_SUPPRESS_BACKTRACE
depend on, say,
	depends on CC_IS_CLANG || (CC_IS_GCC && GCC_VERSION >= 100300)

A more complex solution might be to define an architecture flag such
as HAVE_SUPPRESS_BACKTRACE, make that conditional on the gcc version
for s390 only, and make KUNIT_SUPPRESS_BACKTRACE depend on it.

Guenter



From maz at kernel.org  Fri Mar 21 10:04:22 2025
From: maz at kernel.org (Marc Zyngier)
Date: Fri, 21 Mar 2025 17:04:22 +0000
Subject: [PATCH] KVM: selftests: Fix a couple "prio" signedness bugs
In-Reply-To: <ca579322-dc9d-4300-bd74-7e9240e930c7@stanley.mountain>
References: <ca579322-dc9d-4300-bd74-7e9240e930c7@stanley.mountain>
Message-ID: <87cyeaqprd.wl-maz@kernel.org>

Hey Dan,

On Fri, 21 Mar 2025 14:32:53 +0000,
Dan Carpenter <dan.carpenter at linaro.org> wrote:
> 
> There is an assert which relies on "prio" to be signed.
> 
> 	GUEST_ASSERT(prio >= 0);
> 
> Change the type from uint32_t to int.
> 
> Fixes: 728fcc46d2c2 ("KVM: selftests: aarch64: Add test for restoring active IRQs")
> Fixes: 0ad3ff4a6adc ("KVM: selftests: aarch64: Add preemption tests in vgic_irq")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>
> ---
> ---
>  tools/testing/selftests/kvm/arm64/vgic_irq.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
> index f4ac28d53747..e89c0fc5eef3 100644
> --- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
> +++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
> @@ -294,7 +294,8 @@ static void guest_restore_active(struct test_args *args,
>  		uint32_t first_intid, uint32_t num,
>  		kvm_inject_cmd cmd)
>  {
> -	uint32_t prio, intid, ap1r;
> +	uint32_t intid, ap1r;
> +	int prio;
>  	int i;
>  
>  	/*
> @@ -362,7 +363,8 @@ static void test_inject_preemption(struct test_args *args,
>  		uint32_t first_intid, int num,
>  		kvm_inject_cmd cmd)
>  {
> -	uint32_t intid, prio, step = KVM_PRIO_STEPS;
> +	uint32_t intid, step = KVM_PRIO_STEPS;
> +	int prio;
>  	int i;
>  
>  	/* Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs

I think this is going in the wrong direction. A GIC priority is an
unsigned 8bit value as per the architecture definition.

So the type used by the test the first place looks wrong (it is too
wide), and the assertion is pointless.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From yury.norov at gmail.com  Fri Mar 21 10:05:18 2025
From: yury.norov at gmail.com (Yury Norov)
Date: Fri, 21 Mar 2025 13:05:18 -0400
Subject: [PATCH v4 3/8] bits: introduce fixed-type genmasks
In-Reply-To: <1aba17f1-0cd2-429c-8338-28387ec16314@arm.com>
References: <20250305-fixed-type-genmasks-v4-0-1873dcdf6723@wanadoo.fr>
 <20250305-fixed-type-genmasks-v4-3-1873dcdf6723@wanadoo.fr>
 <Z8hsRJvpjYoqh9RG@thinkpad>
 <Z9oiEkQEcHhA0a80@thinkpad>
 <5cbaefa8-e51f-415f-a9b3-4841e69bb3fa@arm.com>
 <1aba17f1-0cd2-429c-8338-28387ec16314@arm.com>
Message-ID: <Z92cThxAyXu9JJdk@thinkpad>

On Wed, Mar 19, 2025 at 09:43:06AM +0530, Anshuman Khandual wrote:
> 
> 
> On 3/19/25 09:04, Anshuman Khandual wrote:
> > On 3/19/25 07:16, Yury Norov wrote:
> >> + Catalin Marinas, ARM maillist
> >>
> >> Hi Catalin and everyone,
> > 
> > Hello Yury,
> > 
> >>
> >> Anshuman Khandual asked me to merge GENMASK_U128() saying it's
> >> important for ARM to stabilize API. While it's a dead code, I
> >> accepted his patch as he promised to add users shortly.
> >>
> >> Now it's more than half a year since that. There's no users,
> >> and no feedback from Anshuman.
> > 
> > My apologies to have missed your email earlier. Please find response
> > for the earlier email below as well.
> > 
> >>
> >> Can you please tell if you still need the macro? I don't want to
> >> undercut your development, but if you don't need 128-bit genmasks
> >> there's no reason to have a dead code in the uapi.
> > 
> > The code base specifically using GENMASK_U128() has not been posted
> > upstream (probably in next couple of months or so) till now, except
> > the following patch which has been not been merged and still under
> > review and development.
> > 
> > https://lore.kernel.org/lkml/20240801054436.612024-1-anshuman.khandual at arm.com/
> > 
> >>
> >> Thanks,
> >> Yury
> >>
> >> On Wed, Mar 05, 2025 at 10:22:47AM -0500, Yury Norov wrote:
> >>> + Anshuman Khandual <anshuman.khandual at arm.com>
> >>>
> >>> Anshuman,
> >>>
> >>> I merged your GENMASK_U128() because you said it's important for your
> >>> projects, and that it will get used in the kernel soon.
> >>>
> >>> Now it's in the kernel for more than 6 month, but no users were added.
> >>> Can you clarify if you still need it, and if so why it's not used?
> > 
> > We would need it but although the code using GENMASK_U128() has not been
> > posted upstream.
> > 
> >>>
> >>> As you see, people add another fixed-types GENMASK() macros, and their
> >>> implementation differ from GENMASK_U128().
> > 
> > I will take a look. Is GENMASK_U128() being problematic for the this new
> > scheme ?
> > 
> >>>
> >>> My second concern is that __GENMASK_U128() is declared in uapi, while
> >>> the general understanding for other fixed-type genmasks is that they
> >>> are not exported to users. Do you need this macro to be exported to
> >>> userspace? Can you show how and where it is used there?
> > 
> > No, not atleast right now.

Ok, thanks.

> > These were moved into uapi subsequently via the following commit.
> > 
> > 21a3a3d015aee ("tools headers: Synchronize {uapi/}linux/bits.h with the kernel sources")
> > 
> > But in general GENMASK_U128() is needed for generating 128 bit page table
> > entries, related flags and masks whether in kernel or in user space for
> > writing kernel test cases etc.
> 
> In the commit 947697c6f0f7 ("uapi: Define GENMASK_U128"), GENMASK_U128() gets defined
> using __GENMASK_U128() which in turn calls __BIT128() - both of which are defined in
> UAPI headers inside (include/uapi/linux/). 
> 
> Just wondering - are you suggesting to move these helpers from include/uapi/linux/ to
> include/linux/bits.h instead ?

Vincent is working on fixed-width GENMASK_Uxx() based on GENMASK_TYPE().

https://lore.kernel.org/lkml/20250308-fixed-type-genmasks-v6-0-f59315e73c29 at wanadoo.fr/T/

The series adds a general GENMASK_TYPE() in the linux/bits.h. I'd like
all fixed-widh genmasks to be based on it. The implementation doesn't
allow to move GENMASK_TYPE() the to uapi easily.

There was a discussion regarding that, and for now the general understanding
is that userspace doesn't need GENMASK_Uxx().

Are your proposed tests based on the in-kernel tools/ ? If so, linux/bits.h
will be available for you.

Vincent,

Can you please experiment with moving GENMASK_U128() to linux/bits.h
and switching it to GENMASK_TYPE()-based implementation?

If it works, we can do it after merging of GENMASK_TYPE() and
ancestors.

Thanks,
Yury


From heiko at sntech.de  Fri Mar 21 10:08:26 2025
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 21 Mar 2025 18:08:26 +0100
Subject: [PATCH next] phy: rockchip-samsung-dcphy: Add missing assignment
In-Reply-To: <e64265a4-9543-4728-a49f-ea910fccef7c@stanley.mountain>
References: <e64265a4-9543-4728-a49f-ea910fccef7c@stanley.mountain>
Message-ID: <2181342.OBFZWjSADL@phil>

Hey Dan,

Am Freitag, 21. M?rz 2025, 15:36:14 MEZ schrieb Dan Carpenter:
> The "ret = " was accidentally dropped so the error handling doesn't work.
> 
> Fixes: b2a1a2ae7818 ("phy: rockchip: Add Samsung MIPI D-/C-PHY driver")
> Signed-off-by: Dan Carpenter <dan.carpenter at linaro.org>

oh darn ... thanks so much for catching that

Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> ---
>  drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
> index 08c78c1bafc9..28a052e17366 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
> @@ -1653,7 +1653,7 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
>  		return ret;
>  	}
>  
> -	clk_prepare_enable(samsung->ref_clk);
> +	ret = clk_prepare_enable(samsung->ref_clk);
>  	if (ret) {
>  		dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret);
>  		clk_disable_unprepare(samsung->pclk);
> 






From lorenzo at kernel.org  Fri Mar 21 10:14:49 2025
From: lorenzo at kernel.org (Lorenzo Bianconi)
Date: Fri, 21 Mar 2025 18:14:49 +0100
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <46a714fb-8a14-4d24-a0a6-a22cc9d45768@stanley.mountain>
References: <20250320201914.48159-1-qasdev00@gmail.com>
 <46a714fb-8a14-4d24-a0a6-a22cc9d45768@stanley.mountain>
Message-ID: <Z92eiVIFIUOFKXj_@lore-desk>

> On Thu, Mar 20, 2025 at 08:19:14PM +0000, Qasim Ijaz wrote:
> > If link_conf_dereference_protected() or mt7996_vif_link() 
> > or link_sta_dereference_protected() fail the code jumps to
> > the error_unlink label and returns ret which is uninitialised.
> > 
> > Fix this by setting err before jumping to error_unlink.
> > 
> > Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
> > Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > index 91c64e3a0860..78f7f1fc867e 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
> >  			continue;
> 
> What about if the list is empty or we hit this continue on every link?

we will return 0 and I guess that's fine, agree?

Regards,
Lorenzo

> 
> regards,
> dan carpenter
> 
> >  
> >  		link_conf = link_conf_dereference_protected(vif, link_id);
> > -		if (!link_conf)
> > +		if (!link_conf) {
> > +			err = -EINVAL;
> >  			goto error_unlink;
> > +		}
> >  
> >  		link = mt7996_vif_link(dev, vif, link_id);
> > -		if (!link)
> > +		if (!link) {
> > +			err = -EINVAL;
> >  			goto error_unlink;
> > +		}
> >  
> >  		link_sta = link_sta_dereference_protected(sta, link_id);
> > -		if (!link_sta)
> > +		if (!link_sta) {
> > +			err = -EINVAL
> >  			goto error_unlink;
> > +		}
> >  
> >  		err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
> >  					       link_id);
> > -- 
> > 2.39.5
> > 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/5a0a50c4/attachment.sig>

From dmitry.baryshkov at oss.qualcomm.com  Fri Mar 21 10:19:41 2025
From: dmitry.baryshkov at oss.qualcomm.com (Dmitry Baryshkov)
Date: Fri, 21 Mar 2025 19:19:41 +0200
Subject: [PATCH v1 2/3] arm64: dts: qcom: x1e80100: add bus topology for
 PCIe domain 3
In-Reply-To: <20250320055502.274849-3-quic_wenbyao@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-3-quic_wenbyao@quicinc.com>
Message-ID: <hgvfxxjvquh3tn543ae44o3lie3pwld5snbewy2lxcrtgd4raa@eyfm57omt3ge>

On Thu, Mar 20, 2025 at 01:55:01PM +0800, Wenbin Yao wrote:
> From: Qiang Yu <quic_qianyu at quicinc.com>
> 
> Add pcie3port node to represent the PCIe bridge of PCIe3 so that PCI slot
> voltage rails can be described under this node in the board's dts.
> 
> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> index 46b79fce9..32e8d400a 100644
> --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
> @@ -3287,6 +3287,16 @@ opp-128000000 {
>  					opp-peak-kBps = <15753000 1>;
>  				};
>  			};
> +			pcie3port: pcie at 0 {

Empty line between nodes, please.

> +				device_type = "pci";
> +				compatible = "pciclass,0604";
> +				reg = <0x0 0x0 0x0 0x0 0x0>;
> +				bus-range = <0x01 0xff>;
> +
> +				#address-cells = <3>;
> +				#size-cells = <2>;
> +				ranges;
> +			};
>  		};
>  
>  		pcie3_phy: phy at 1be0000 {
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


From arnd at arndb.de  Fri Mar 21 10:33:19 2025
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 21 Mar 2025 18:33:19 +0100
Subject: [PATCH v4 10/14] s390: Add support for suppressing warning backtraces
In-Reply-To: <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-11-acarmina@redhat.com>
 <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>
Message-ID: <a6f90bdb-8459-4d33-8874-7e724bd22d9f@app.fastmail.com>

On Fri, Mar 21, 2025, at 18:05, Guenter Roeck wrote:
> On 3/13/25 04:43, Alessandro Carminati wrote:
>
> gcc 10.3.0 and later do not have this problem. I also tried s390 builds 
> with gcc 9.4
> and 9.5 but they both crash for unrelated reasons.
>
> If this is a concern, the best idea I have is to make KUNIT_SUPPRESS_BACKTRACE
> depend on, say,
> 	depends on CC_IS_CLANG || (CC_IS_GCC && GCC_VERSION >= 100300)
>
> A more complex solution might be to define an architecture flag such
> as HAVE_SUPPRESS_BACKTRACE, make that conditional on the gcc version
> for s390 only, and make KUNIT_SUPPRESS_BACKTRACE depend on it.

That is probably fine, there are very few users on s390 that build
their own kernels, and they likely all have modern compilers anyway.

I should still send a patch to raise the minimum compiler version to
gcc-8.1, but unfortunately that is not enough here.

     Arnd


From dan.carpenter at linaro.org  Fri Mar 21 10:35:25 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Fri, 21 Mar 2025 20:35:25 +0300
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <Z92eiVIFIUOFKXj_@lore-desk>
References: <20250320201914.48159-1-qasdev00@gmail.com>
 <46a714fb-8a14-4d24-a0a6-a22cc9d45768@stanley.mountain>
 <Z92eiVIFIUOFKXj_@lore-desk>
Message-ID: <356de8c6-b3a2-4f7c-9737-011a91c4bdfd@stanley.mountain>

On Fri, Mar 21, 2025 at 06:14:49PM +0100, Lorenzo Bianconi wrote:
> > On Thu, Mar 20, 2025 at 08:19:14PM +0000, Qasim Ijaz wrote:
> > > If link_conf_dereference_protected() or mt7996_vif_link() 
> > > or link_sta_dereference_protected() fail the code jumps to
> > > the error_unlink label and returns ret which is uninitialised.
> > > 
> > > Fix this by setting err before jumping to error_unlink.
> > > 
> > > Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
> > > Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> > > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > > ---
> > >  drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
> > >  1 file changed, 9 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > > index 91c64e3a0860..78f7f1fc867e 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > > @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
> > >  			continue;
> > 
> > What about if the list is empty or we hit this continue on every link?
> 
> we will return 0 and I guess that's fine, agree?
> 

Fine by me?

regards,
dan carpenter



From maxime.chevallier at bootlin.com  Fri Mar 21 10:41:34 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Fri, 21 Mar 2025 18:41:34 +0100
Subject: [PATCH net-next v3 1/7] net: ethtool: netlink: Allow
 per-netdevice DUMP operations
In-Reply-To: <c4e5bd2f-6216-4f74-b677-46c79343eb21@redhat.com>
References: <20250313182647.250007-1-maxime.chevallier@bootlin.com>
	<20250313182647.250007-2-maxime.chevallier@bootlin.com>
	<c4e5bd2f-6216-4f74-b677-46c79343eb21@redhat.com>
Message-ID: <20250321184134.22311370@fedora.home>

On Fri, 21 Mar 2025 17:31:17 +0100
Paolo Abeni <pabeni at redhat.com> wrote:

> On 3/13/25 7:26 PM, Maxime Chevallier wrote:
> > We have a number of netlink commands in the ethnl family that may have
> > multiple objects to dump even for a single net_device, including :
> > 
> >  - PLCA, PSE-PD, phy: one message per PHY device
> >  - tsinfo: one message per timestamp source (netdev + phys)
> >  - rss: One per RSS context
> > 
> > To get this behaviour, these netlink commands need to roll a custom  
> > ->dumpit().  
> > 
> > To prepare making per-netdev DUMP more generic in ethnl, introduce a
> > member in the ethnl ops to indicate if a given command may allow
> > pernetdev DUMPs (also referred to as filtered DUMPs).
> > 
> > Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
> > ---
> >  net/ethtool/netlink.c | 45 +++++++++++++++++++++++++++++--------------
> >  net/ethtool/netlink.h |  2 ++
> >  2 files changed, 33 insertions(+), 14 deletions(-)
> > 
> > diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> > index a163d40c6431..7adede5e4ff1 100644
> > --- a/net/ethtool/netlink.c
> > +++ b/net/ethtool/netlink.c
> > @@ -587,21 +587,38 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
> >  	int ret = 0;
> >  
> >  	rcu_read_lock();  
> 
> Maintain the RCU read lock here is IMHO confusing...
> 
> > -	for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> > -		dev_hold(dev);
> > +	if (ctx->req_info->dev) {
> > +		dev = ctx->req_info->dev;  
> 
> .. as this is refcounted.
> 
> I suggest to move the rcu_read_lock inside the if.

Indeed, maybe not the best place indeed. I'll address that, thanks for
pointing this out

> 
> >  		rcu_read_unlock();
> > +		/* Filtered DUMP request targeted to a single netdev. We already
> > +		 * hold a ref to the netdev from ->start()
> > +		 */
> > +		ret = ethnl_default_dump_one(skb, dev, ctx,
> > +					     genl_info_dump(cb));
> > +		rcu_read_lock();
> > +		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
> >  
> > -		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
> > +		if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
> > +			ret = skb->len;
> >  
> > -		rcu_read_lock();
> > -		dev_put(dev);
> > +	} else {
> > +		for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
> > +			dev_hold(dev);
> > +			rcu_read_unlock();
> > +
> > +			ret = ethnl_default_dump_one(skb, dev, ctx,
> > +						     genl_info_dump(cb));
> > +
> > +			rcu_read_lock();
> > +			dev_put(dev);
> >  
> > -		if (ret < 0 && ret != -EOPNOTSUPP) {
> > -			if (likely(skb->len))
> > -				ret = skb->len;
> > -			break;
> > +			if (ret < 0 && ret != -EOPNOTSUPP) {
> > +				if (likely(skb->len))
> > +					ret = skb->len;  
> 
> IMHO a bit too many levels of indentation. It's possibly better to move
> this code in a separate helper.

That's true, not the prettiest piece of that patch. I'll refactor this
better then.

Thanks for the review,

Maxime


From lkp at intel.com  Fri Mar 21 10:50:48 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 01:50:48 +0800
Subject: [soc:for-next] BUILD SUCCESS
 f7dd075de68de8a2536e50c2de434d1c12366155
Message-ID: <202503220139.jFG63sHA-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
branch HEAD: f7dd075de68de8a2536e50c2de434d1c12366155  Merge branch 'soc/drivers' into for-next

elapsed time: 1446m

configs tested: 92
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                            allyesconfig    gcc-14.2.0
arc                              allmodconfig    gcc-14.2.0
arc                              allyesconfig    gcc-14.2.0
arc                   randconfig-001-20250321    gcc-13.3.0
arc                   randconfig-002-20250321    gcc-11.5.0
arm                              allmodconfig    gcc-14.2.0
arm                              allyesconfig    gcc-14.2.0
arm                   randconfig-001-20250321    clang-19
arm                   randconfig-002-20250321    gcc-9.3.0
arm                   randconfig-003-20250321    gcc-5.5.0
arm                   randconfig-004-20250321    clang-21
arm64                            allmodconfig    clang-19
arm64                 randconfig-001-20250321    gcc-5.5.0
arm64                 randconfig-002-20250321    gcc-5.5.0
arm64                 randconfig-003-20250321    clang-20
arm64                 randconfig-004-20250321    clang-21
csky                  randconfig-001-20250321    gcc-13.3.0
csky                  randconfig-002-20250321    gcc-13.3.0
hexagon                          allmodconfig    clang-17
hexagon                          allyesconfig    clang-21
hexagon               randconfig-001-20250321    clang-21
hexagon               randconfig-002-20250321    clang-16
i386                             allmodconfig    gcc-12
i386                              allnoconfig    gcc-12
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250321    clang-20
i386        buildonly-randconfig-002-20250321    clang-20
i386        buildonly-randconfig-003-20250321    clang-20
i386        buildonly-randconfig-004-20250321    clang-20
i386        buildonly-randconfig-005-20250321    clang-20
i386        buildonly-randconfig-006-20250321    clang-20
i386                                defconfig    clang-20
loongarch                        allmodconfig    gcc-14.2.0
loongarch             randconfig-001-20250321    gcc-14.2.0
loongarch             randconfig-002-20250321    gcc-14.2.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
microblaze                       allmodconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
microblaze                       allyesconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250321    gcc-13.3.0
nios2                 randconfig-002-20250321    gcc-7.5.0
openrisc                         allyesconfig    gcc-14.2.0
parisc                           allmodconfig    gcc-14.2.0
parisc                           allyesconfig    gcc-14.2.0
parisc                randconfig-001-20250321    gcc-8.5.0
parisc                randconfig-002-20250321    gcc-6.5.0
powerpc                          allmodconfig    gcc-14.2.0
powerpc                          allyesconfig    clang-21
powerpc               randconfig-001-20250321    clang-21
powerpc               randconfig-002-20250321    gcc-7.5.0
powerpc               randconfig-003-20250321    gcc-7.5.0
powerpc64             randconfig-001-20250321    gcc-5.5.0
powerpc64             randconfig-002-20250321    clang-16
powerpc64             randconfig-003-20250321    gcc-7.5.0
riscv                            allmodconfig    clang-21
riscv                            allyesconfig    clang-16
riscv                 randconfig-001-20250321    clang-21
riscv                 randconfig-002-20250321    clang-21
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250321    clang-16
s390                  randconfig-002-20250321    gcc-8.5.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250321    gcc-7.5.0
sh                    randconfig-002-20250321    gcc-7.5.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250321    gcc-12.4.0
sparc                 randconfig-002-20250321    gcc-6.5.0
sparc64               randconfig-001-20250321    gcc-10.5.0
sparc64               randconfig-002-20250321    gcc-6.5.0
um                               allmodconfig    clang-19
um                               allyesconfig    gcc-12
um                    randconfig-001-20250321    gcc-12
um                    randconfig-002-20250321    gcc-12
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250321    clang-20
x86_64      buildonly-randconfig-002-20250321    clang-20
x86_64      buildonly-randconfig-003-20250321    gcc-12
x86_64      buildonly-randconfig-004-20250321    clang-20
x86_64      buildonly-randconfig-005-20250321    clang-20
x86_64      buildonly-randconfig-006-20250321    clang-20
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250321    gcc-6.5.0
xtensa                randconfig-002-20250321    gcc-10.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From patchwork-bot+netdevbpf at kernel.org  Fri Mar 21 10:50:33 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Fri, 21 Mar 2025 17:50:33 +0000
Subject: [PATCH] net: airoha: fix CONFIG_DEBUG_FS check
In-Reply-To: <20250314155009.4114308-1-arnd@kernel.org>
References: <20250314155009.4114308-1-arnd@kernel.org>
Message-ID: <174257943352.2572031.8416368231944213281.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni at redhat.com>:

On Fri, 14 Mar 2025 16:49:59 +0100 you wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> The #if check causes a build failure when CONFIG_DEBUG_FS is turned
> off:
> 
> In file included from drivers/net/ethernet/airoha/airoha_eth.c:17:
> drivers/net/ethernet/airoha/airoha_eth.h:543:5: error: "CONFIG_DEBUG_FS" is not defined, evaluates to 0 [-Werror=undef]
>   543 | #if CONFIG_DEBUG_FS
>       |     ^~~~~~~~~~~~~~~
> 
> [...]

Here is the summary with links:
  - net: airoha: fix CONFIG_DEBUG_FS check
    https://git.kernel.org/netdev/net-next/c/08d0185e36ad

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From christophe.leroy at csgroup.eu  Fri Mar 21 10:24:22 2025
From: christophe.leroy at csgroup.eu (Christophe Leroy)
Date: Fri, 21 Mar 2025 18:24:22 +0100
Subject: [PATCH v5 0/9] Merge arm64/riscv hugetlbfs contpte support
In-Reply-To: <20250321130635.227011-1-alexghiti@rivosinc.com>
References: <20250321130635.227011-1-alexghiti@rivosinc.com>
Message-ID: <1b0d0513-9d18-4603-91e9-20af36334145@csgroup.eu>



Le 21/03/2025 ? 14:06, Alexandre Ghiti a ?crit?:
> This patchset intends to merge the contiguous ptes hugetlbfs implementation
> of arm64 and riscv.

Can we also add powerpc in the dance ?

powerpc also use contiguous PTEs allthough there is not (yet) a special 
name for it:
- b250c8c08c79 powerpc/8xx: Manage 512k huge pages as standard pages
- e47168f3d1b1 powerpc/8xx: Support 16k hugepages with 4k pages

powerpc also use configuous PMDs/PUDs for larger hugepages:
- 57fb15c32f4f ("powerpc/64s: use contiguous PMD/PUD instead of HUGEPD")
- 7c44202e3609 ("powerpc/e500: use contiguous PMD instead of hugepd")
- 0549e7666373 ("powerpc/8xx: rework support for 8M pages using 
contiguous PTE entries")

Christophe

> 
> Both arm64 and riscv support the use of contiguous ptes to map pages that
> are larger than the default page table size, respectively called contpte
> and svnapot.
> 
> The riscv implementation differs from the arm64's in that the LSBs of the
> pfn of a svnapot pte are used to store the size of the mapping, allowing
> for future sizes to be added (for now only 64KB is supported). That's an
> issue for the core mm code which expects to find the *real* pfn a pte points
> to. Patch 1 fixes that by always returning svnapot ptes with the real pfn
> and restores the size of the mapping when it is written to a page table.
> 
> The following patches are just merges of the 2 different implementations
> that currently exist in arm64 and riscv which are very similar. It paves
> the way to the reuse of the recent contpte THP work by Ryan [1] to avoid
> reimplementing the same in riscv.
> 
> This patchset was tested by running the libhugetlbfs testsuite with 64KB
> and 2MB pages on both architectures (on a 4KB base page size arm64 kernel).
> 
> [1] https://lore.kernel.org/linux-arm-kernel/20240215103205.2607016-1-ryan.roberts at arm.com/
> 
> v4: https://lore.kernel.org/linux-riscv/20250127093530.19548-1-alexghiti at rivosinc.com/
> v3: https://lore.kernel.org/all/20240802151430.99114-1-alexghiti at rivosinc.com/
> v2: https://lore.kernel.org/linux-riscv/20240508113419.18620-1-alexghiti at rivosinc.com/
> v1: https://lore.kernel.org/linux-riscv/20240301091455.246686-1-alexghiti at rivosinc.com/
> 
> Changes in v5:
>    - Fix "int i" unused variable in patch 2 (as reported by PW)
>    - Fix !svnapot build
>    - Fix arch_make_huge_pte() which returned a real napot pte
>    - Make __ptep_get(), ptep_get_and_clear() and __set_ptes() napot aware to
>      avoid leaking real napot pfns to core mm
>    - Fix arch_contpte_get_num_contig() that used to always try to get the
>      mapping size from the ptep, which does not work if the ptep comes the core mm
>    - Rebase on top of 6.14-rc7 + fix for
>      huge_ptep_get_and_clear()/huge_pte_clear()
>      https://lore.kernel.org/linux-riscv/20250317072551.572169-1-alexghiti at rivosinc.com/
> 
> Changes in v4:
>    - Rebase on top of 6.13
> 
> Changes in v3:
>    - Split set_ptes and ptep_get into internal and external API (Ryan)
>    - Rename ARCH_HAS_CONTPTE into ARCH_WANT_GENERAL_HUGETLB_CONTPTE so that
>      we split hugetlb functions from contpte functions (actually riscv contpte
>      functions to support THP will come into another series) (Ryan)
>    - Rebase on top of 6.11-rc1
> 
> Changes in v2:
>    - Rebase on top of 6.9-rc3
> 
> Alexandre Ghiti (9):
>    riscv: Safely remove huge_pte_offset() when manipulating NAPOT ptes
>    riscv: Restore the pfn in a NAPOT pte when manipulated by core mm code
>    mm: Use common huge_ptep_get() function for riscv/arm64
>    mm: Use common set_huge_pte_at() function for riscv/arm64
>    mm: Use common huge_pte_clear() function for riscv/arm64
>    mm: Use common huge_ptep_get_and_clear() function for riscv/arm64
>    mm: Use common huge_ptep_set_access_flags() function for riscv/arm64
>    mm: Use common huge_ptep_set_wrprotect() function for riscv/arm64
>    mm: Use common huge_ptep_clear_flush() function for riscv/arm64
> 
>   arch/arm64/Kconfig                  |   1 +
>   arch/arm64/include/asm/hugetlb.h    |  22 +--
>   arch/arm64/include/asm/pgtable.h    |  68 ++++++-
>   arch/arm64/mm/hugetlbpage.c         | 294 +---------------------------
>   arch/riscv/Kconfig                  |   1 +
>   arch/riscv/include/asm/hugetlb.h    |  36 +---
>   arch/riscv/include/asm/pgtable-64.h |  11 ++
>   arch/riscv/include/asm/pgtable.h    | 222 ++++++++++++++++++---
>   arch/riscv/mm/hugetlbpage.c         | 243 +----------------------
>   arch/riscv/mm/pgtable.c             |   6 +-
>   include/linux/hugetlb_contpte.h     |  39 ++++
>   mm/Kconfig                          |   3 +
>   mm/Makefile                         |   1 +
>   mm/hugetlb_contpte.c                | 258 ++++++++++++++++++++++++
>   14 files changed, 583 insertions(+), 622 deletions(-)
>   create mode 100644 include/linux/hugetlb_contpte.h
>   create mode 100644 mm/hugetlb_contpte.c
> 



From jbrunet at baylibre.com  Fri Mar 21 10:53:49 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 21 Mar 2025 18:53:49 +0100
Subject: [PATCH v3 1/4] clk: add a clk_hw helpers to get the clock
 device or device_node
In-Reply-To: <508a5ee6c6b365e8d9cdefd5a9eec769.sboyd@kernel.org> (Stephen
	Boyd's message of "Wed, 26 Feb 2025 17:01:05 -0800")
References: <20250120-amlogic-clk-drop-clk-regmap-tables-v3-0-126244146947@baylibre.com>
	<20250120-amlogic-clk-drop-clk-regmap-tables-v3-1-126244146947@baylibre.com>
	<508a5ee6c6b365e8d9cdefd5a9eec769.sboyd@kernel.org>
Message-ID: <1jv7s21d8y.fsf@starbuckisacylon.baylibre.com>

On Wed 26 Feb 2025 at 17:01, Stephen Boyd <sboyd at kernel.org> wrote:


>> +static void clk_hw_get_of_node_test(struct kunit *test)
>> +{
>> +       struct device_node *np;
>> +       struct clk_hw *hw;
>> +
>> +       hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL);
>> +       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
>> +
>> +       np = of_find_compatible_node(NULL, NULL, "test,clk-dummy-device");
>> +       hw->init = CLK_HW_INIT_NO_PARENT("test_get_of_node",
>> +                                        &clk_dummy_rate_ops, 0);
>> +       of_node_put_kunit(test, np);
>> +
>> +       KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, hw));
>
> The stuff before the expectation should likely go to the init function.
> Or it can use the genparams stuff so we can set some struct members to
> indicate if the pointer should be NULL or not and then twist through the
> code a couple times.
>

I'm trying to address all your comments but I'm starting to wonder if
this isn't going a bit too far ? The functions tested are one line
returns. Is it really worth all this ?

I do understand the idea for things that actually do something, such as
reparenting, setting rates or what not ... But this ? It feels like a
lot of test code for very little added value, don't you think ?

-- 
Jerome


From pabeni at redhat.com  Fri Mar 21 11:18:15 2025
From: pabeni at redhat.com (Paolo Abeni)
Date: Fri, 21 Mar 2025 19:18:15 +0100
Subject: [PATCH net-next v2] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <Z9WV4mNwG04JRbZg@lore-desk>
References: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>
 <b647d3c2-171e-43ea-9329-ea37093f5dec@lunn.ch> <Z9WV4mNwG04JRbZg@lore-desk>
Message-ID: <2d39033d-0303-48d0-98d3-49d63fba5563@redhat.com>

On 3/15/25 3:59 PM, Lorenzo Bianconi wrote:
>>> Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
>>> routine.
>>
>> A more interesting question is, why do you see an invalid port? Is the
>> hardware broken? Something not correctly configured? Are you just
>> papering over the crack?
>>
>>> -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
>>> +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
>>> +					struct airoha_foe_entry *hwe,
>>>  					struct net_device *dev, int type,
>>>  					struct airoha_flow_data *data,
>>>  					int l4proto)
>>> @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
>>>  	if (dev) {
>>>  		struct airoha_gdm_port *port = netdev_priv(dev);
>>
>> If port is invalid, is dev also invalid? And if dev is invalid, could
>> dereferencing it to get priv cause an opps?
> 
> I do not think this is a hw problem. Running bidirectional high load traffic,
> I got the sporadic crash reported above. In particular, netfilter runs
> airoha_ppe_flow_offload_replace() providing the egress net_device pointer used
> in airoha_ppe_foe_entry_prepare(). Debugging with gdb, I discovered the system
> crashes dereferencing port pointer in airoha_ppe_foe_entry_prepare() (even if
> dev pointer is not NULL). Adding this sanity check makes the system stable.
> Please note a similar check is available even in mtk driver [0].

I agree with Andrew, you need a better understanding of the root cause.
This really looks like papering over some deeper issue.

AFAICS 'dev' is fetched from the airoha driver itself a few lines
before. Possibly you should double check that code.

Thanks,

Paolo



From luca.ceresoli at bootlin.com  Fri Mar 21 11:21:32 2025
From: luca.ceresoli at bootlin.com (Luca Ceresoli)
Date: Fri, 21 Mar 2025 19:21:32 +0100
Subject: [PATCH v8 2/5] drm/bridge: add support for refcounting
In-Reply-To: <400466cd3c229ea6c6cb25e2a58cee27@kernel.org>
References: <20250320-drm-bridge-refcount-v8-2-b3ddaa9f1368@bootlin.com>
	<400466cd3c229ea6c6cb25e2a58cee27@kernel.org>
Message-ID: <20250321192132.211893ec@booty>

Hello Maxime,

On Fri, 21 Mar 2025 09:54:55 +0000
"Maxime Ripard" <mripard at kernel.org> wrote:

> On Thu, 20 Mar 2025 16:42:11 +0100, Luca Ceresoli wrote:
> > DRM bridges are currently considered as a fixed element of a DRM card, and
> > thus their lifetime is assumed to extend for as long as the card
> > exists. New use cases, such as hot-pluggable hardware with video bridges,
> > require DRM bridges to be added to and removed from a DRM card without
> > tearing the card down. This is possible for connectors already (used by DP
> > 
> > [ ... ]  
> 
> Reviewed-by: Maxime Ripard <mripard at kernel.org>

Thanks a lot for reviewing!

I noticed you haven't replied on patch 3. Being a change you had
suggested, I was wondering whether haven't noticed that. If you are OK
with that patch, the entire series would have a R-by, which would be
great to unlock all the work depending on this series.

Luca

-- 
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From lkp at intel.com  Fri Mar 21 11:30:51 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 02:30:51 +0800
Subject: [soc:soc/drivers 24/26]
 drivers/platform/cznic/turris-signing-key.c:25:50: error: parameter name
 omitted
Message-ID: <202503220206.LHWsolYc-lkp@intel.com>

Hi Marek,

First bad commit (maybe != root cause):

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
head:   cf2ae5e5b68b06b4c8bceb42d46fa311e6db9a60
commit: ba8755ab541fc629948233125db870d4dbf00a75 [24/26] firmware: turris-mox-rwtm: Add support for ECDSA signatures with HW private key
config: arm-randconfig-002-20250322 (https://download.01.org/0day-ci/archive/20250322/202503220206.LHWsolYc-lkp at intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250322/202503220206.LHWsolYc-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503220206.LHWsolYc-lkp at intel.com/

Note: the soc/soc/drivers HEAD cf2ae5e5b68b06b4c8bceb42d46fa311e6db9a60 builds fine.
      It only hurts bisectability.

All errors (new ones prefixed by >>):

   drivers/platform/cznic/turris-signing-key.c: In function 'turris_signing_key_instantiate':
>> drivers/platform/cznic/turris-signing-key.c:25:50: error: parameter name omitted
    static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
                                                     ^~~
   drivers/platform/cznic/turris-signing-key.c:25:64: error: parameter name omitted
    static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
                                                                   ^~~~~~~~~~~~~~~~~~~~~


vim +25 drivers/platform/cznic/turris-signing-key.c

0b28b7080ef5a32 Marek Beh?n 2025-02-04  24  
0b28b7080ef5a32 Marek Beh?n 2025-02-04 @25  static int turris_signing_key_instantiate(struct key *, struct key_preparsed_payload *)
0b28b7080ef5a32 Marek Beh?n 2025-02-04  26  {
0b28b7080ef5a32 Marek Beh?n 2025-02-04  27  	return 0;
0b28b7080ef5a32 Marek Beh?n 2025-02-04  28  }
0b28b7080ef5a32 Marek Beh?n 2025-02-04  29  

:::::: The code at line 25 was first introduced by commit
:::::: 0b28b7080ef5a323c3afa3860c3d45d627629830 platform: cznic: Add keyctl helpers for Turris platform

:::::: TO: Marek Beh?n <kabel at kernel.org>
:::::: CC: Arnd Bergmann <arnd at arndb.de>

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From namhyung at kernel.org  Fri Mar 21 11:30:07 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Fri, 21 Mar 2025 11:30:07 -0700
Subject: [PATCH v7 00/14] perf: Support multiple system call tables in
 the build
In-Reply-To: <20250319050741.269828-1-irogers@google.com>
References: <20250319050741.269828-1-irogers@google.com>
Message-ID: <174258180770.163787.17026526140964969734.b4-ty@kernel.org>

On Tue, 18 Mar 2025 22:07:27 -0700, Ian Rogers wrote:
> This work builds on the clean up of system call tables and removal of
> libaudit by Charlie Jenkins <charlie at rivosinc.com>.
> 
> The system call table in perf trace is used to map system call numbers
> to names and vice versa. Prior to these changes, a single table
> matching the perf binary's build was present. The table would be
> incorrect if tracing say a 32-bit binary from a 64-bit version of
> perf, the names and numbers wouldn't match.
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From namhyung at kernel.org  Fri Mar 21 11:30:08 2025
From: namhyung at kernel.org (Namhyung Kim)
Date: Fri, 21 Mar 2025 11:30:08 -0700
Subject: [PATCH 0/2] perf vendor events arm64: AmpereOne/AmpereOneX:
 Add a new errata and fix metrics calculations
In-Reply-To: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
References: <20250313201559.11332-1-ilkka@os.amperecomputing.com>
Message-ID: <174258180865.163787.7449214813728278320.b4-ty@kernel.org>

On Thu, 13 Mar 2025 20:15:57 +0000, Ilkka Koskinen wrote:
> Add an errata reference to a impacted event and fix metrics calculation
> caused by a scaling issue.
> 
> Ilkka Koskinen (2):
>   perf vendor events arm64: AmpereOne/AmpereOneX: Mark LD_RETIRED
>     impacted by errata
>   perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung




From lorenzo.bianconi at redhat.com  Fri Mar 21 11:30:36 2025
From: lorenzo.bianconi at redhat.com (Lorenzo Bianconi)
Date: Fri, 21 Mar 2025 19:30:36 +0100
Subject: [PATCH net-next v2] net: airoha: Validate egress gdm port in
 airoha_ppe_foe_entry_prepare()
In-Reply-To: <2d39033d-0303-48d0-98d3-49d63fba5563@redhat.com>
References: <20250315-airoha-flowtable-null-ptr-fix-v2-1-94b923d30234@kernel.org>
 <b647d3c2-171e-43ea-9329-ea37093f5dec@lunn.ch>
 <Z9WV4mNwG04JRbZg@lore-desk>
 <2d39033d-0303-48d0-98d3-49d63fba5563@redhat.com>
Message-ID: <Z92wTGu_Sp9VnqPf@lore-desk>

> On 3/15/25 3:59 PM, Lorenzo Bianconi wrote:
> >>> Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare
> >>> routine.
> >>
> >> A more interesting question is, why do you see an invalid port? Is the
> >> hardware broken? Something not correctly configured? Are you just
> >> papering over the crack?
> >>
> >>> -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> >>> +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> >>> +					struct airoha_foe_entry *hwe,
> >>>  					struct net_device *dev, int type,
> >>>  					struct airoha_flow_data *data,
> >>>  					int l4proto)
> >>> @@ -224,6 +225,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
> >>>  	if (dev) {
> >>>  		struct airoha_gdm_port *port = netdev_priv(dev);
> >>
> >> If port is invalid, is dev also invalid? And if dev is invalid, could
> >> dereferencing it to get priv cause an opps?
> > 
> > I do not think this is a hw problem. Running bidirectional high load traffic,
> > I got the sporadic crash reported above. In particular, netfilter runs
> > airoha_ppe_flow_offload_replace() providing the egress net_device pointer used
> > in airoha_ppe_foe_entry_prepare(). Debugging with gdb, I discovered the system
> > crashes dereferencing port pointer in airoha_ppe_foe_entry_prepare() (even if
> > dev pointer is not NULL). Adding this sanity check makes the system stable.
> > Please note a similar check is available even in mtk driver [0].
> 
> I agree with Andrew, you need a better understanding of the root cause.
> This really looks like papering over some deeper issue.
> 
> AFAICS 'dev' is fetched from the airoha driver itself a few lines
> before. Possibly you should double check that code.

Are you referring to airoha_get_dsa_port() routine?
I think dev pointer in airoha_ppe_foe_entry_prepare() is not strictly
necessary a device from a driver itself since it is an egress device
and the flowtable can contain even a wlan or a vlan device. In this
case airoha_get_dsa_port() will just return the original device pointer
and we can't assume priv pointer points to a airoha_gdm_port struct.
Agree?

Regards,
Lorenzo

> 
> Thanks,
> 
> Paolo
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/80a12bde/attachment.sig>

From nunodasneves at linux.microsoft.com  Fri Mar 21 12:12:35 2025
From: nunodasneves at linux.microsoft.com (Nuno Das Neves)
Date: Fri, 21 Mar 2025 12:12:35 -0700
Subject: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
In-Reply-To: <SN6PR02MB4157E630EC520DC487139372D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
References: <1741980536-3865-1-git-send-email-nunodasneves@linux.microsoft.com>
 <1741980536-3865-2-git-send-email-nunodasneves@linux.microsoft.com>
 <SN6PR02MB4157E630EC520DC487139372D4DE2@SN6PR02MB4157.namprd02.prod.outlook.com>
Message-ID: <7bc80505-686e-40db-b3bf-dd2f846ea66c@linux.microsoft.com>

On 3/18/2025 11:01 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves at linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
>>
>> Introduce hv_status_printk() macros as a convenience to log hypercall
>> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
>> value and also as a string, which saves some time while debugging.
>>
>> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
>> use it for hv_result_to_string() and hv_result_to_errno().
>>
>> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
>> irqdomain.c hypercalls to aid debugging in the root partition.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves at linux.microsoft.com>
>> Reviewed-by: Stanislav Kinsburskii <skinsburskii at linux.microsoft.com>
>> ---
>>  arch/x86/hyperv/irqdomain.c    |   6 +-
>>  drivers/hv/hv_common.c         | 129 ++++++++++++++++++++++++---------
>>  drivers/hv/hv_proc.c           |  10 +--
>>  drivers/iommu/hyperv-iommu.c   |   4 +-
>>  include/asm-generic/mshyperv.h |  13 ++++
>>  5 files changed, 118 insertions(+), 44 deletions(-)
>>
> 
> [snip]
>  
>> +
>> +struct hv_status_info {
>> +	char *string;
>> +	int errno;
>> +	u16 code;
>> +};
>> +
>> +/*
>> + * Note on the errno mappings:
>> + * A failed hypercall is usually only recoverable (or loggable) near
>> + * the call site where the HV_STATUS_* code is known. So the errno
>> + * it gets converted to is not too useful further up the stack.
>> + * Provide a few mappings that could be useful, and revert to -EIO
>> + * as a fallback.
>> + */
>> +static const struct hv_status_info hv_status_infos[] = {
>> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
>> +	_STATUS_INFO(HV_STATUS_SUCCESS,				0),
>> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_PARAMETER,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_ACCESS_DENIED,			-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_OPERATION_DENIED,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE,	-EIO),
>> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY,		-ENOMEM),
>> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_VP_INDEX,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_NOT_FOUND,			-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_PORT_ID,			-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_VP_STATE,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_NO_RESOURCES,			-EIO),
>> +	_STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED,	-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EINVAL),
>> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_OPERATION_FAILED,		-EIO),
>> +	_STATUS_INFO(HV_STATUS_TIME_OUT,			-EIO),
>> +	_STATUS_INFO(HV_STATUS_CALL_PENDING,			-EIO),
>> +	_STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,		-EIO),
>> +#undef _STATUS_INFO
>> +};
>> +
>> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
>> +{
>> +	int i;
>> +	u16 code = hv_result(hv_status);
>> +
>> +	for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
>> +		const struct hv_status_info *info = &hv_status_infos[i];
>> +
>> +		if (info->code == code)
>> +			return info;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +/* Convert a hypercall result into a linux-friendly error code. */
>> +int hv_result_to_errno(u64 status)
>> +{
>> +	const struct hv_status_info *info;
>> +
>> +	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
>> +	if (unlikely(status == U64_MAX))
>> +		return -EOPNOTSUPP;
>> +
>> +	info = find_hv_status_info(status);
>> +	if (info)
>> +		return info->errno;
>> +
>> +	return -EIO;
>> +}
>> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
>> +
>> +const char *hv_result_to_string(u64 status)
>> +{
>> +	const struct hv_status_info *info;
>> +
>> +	if (unlikely(status == U64_MAX))
>> +		return "Hypercall page missing!";
>> +
>> +	info = find_hv_status_info(status);
>> +	if (info)
>> +		return info->string;
>> +
>> +	return "Unknown";
>> +}
>> +EXPORT_SYMBOL_GPL(hv_result_to_string);
> 
> I think the table-driven approach worked out pretty well. But here's a version that
> is even more compact, and avoids the duplicate testing for U64_MAX and having
> to special case both U64_MAX and not finding a match:
> 
> +
> +struct hv_status_info {
> +	char *string;
> +	int errno;
> +	int code;
> +};
> +
> +/*
> + * Note on the errno mappings:
> + * A failed hypercall is usually only recoverable (or loggable) near
> + * the call site where the HV_STATUS_* code is known. So the errno
> + * it gets converted to is not too useful further up the stack.
> + * Provide a few mappings that could be useful, and revert to -EIO
> + * as a fallback.
> + */
> +static const struct hv_status_info hv_status_infos[] = {
> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> +	_STATUS_INFO(HV_STATUS_SUCCESS,				0),
> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARAMETER,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_ACCESS_DENIED,			-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_OPERATION_DENIED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY,		-EIO),
> +	_STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE,	-EIO),
> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY,		-ENOMEM),
> +	_STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_VP_INDEX,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_NOT_FOUND,			-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_PORT_ID,			-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS,		-EIO),
> +	_STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_VP_STATE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_NO_RESOURCES,			-EIO),
> +	_STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED,	-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EINVAL),
> +	_STATUS_INFO(HV_STATUS_INVALID_LP_INDEX,		-EIO),
> +	_STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE,		-EIO),
> +	_STATUS_INFO(HV_STATUS_OPERATION_FAILED,		-EIO),
> +	_STATUS_INFO(HV_STATUS_TIME_OUT,			-EIO),
> +	_STATUS_INFO(HV_STATUS_CALL_PENDING,			-EIO),
> +	_STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,		-EIO),
> +	{"Hypercall page missing!", -EOPNOTSUPP, -1}, /* code -1 is "no hypercall page" */
> +	{"Unknown", -EIO, -2},  /* code -2 is "Not found" entry; must be last */
> +#undef _STATUS_INFO
> +};
> +
> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> +{
> +	int i, code;
> +	const struct hv_status_info *info;
> +
> +	/* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> +	if (unlikely(hv_status == U64_MAX))
> +		code = -1;
> +	else
> +		code = hv_result(hv_status);
> +
> +	for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> +		info = &hv_status_infos[i];
> +		if (info->code == code || info->code == -2)
> +			break;
> +	}
> +
> +	return info;
> +}
> +
> +/* Convert a hypercall result into a linux-friendly error code. */
> +int hv_result_to_errno(u64 status)
> +{
> +	return find_hv_status_info(status)->errno;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> +
> +const char *hv_result_to_string(u64 status)
> +{
> +	return find_hv_status_info(status)->string;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_string);
> 
> It could be even more compact by exporting find_hv_status_info() and
> letting  hv_result_to_errno() and hv_result_to_string() be #defines to
> find_hv_status_info()->errno and find_hv_status_info()->string,
> respectively.
> 
> Note that in struct hv_status_info, the "code" field is defined as "int"
> instead of "u16" so that it can contain sentinel values -1 and -2 that
> won't overlap with HV_STATUS_* values.
> 
Played around with this some more.

I like your idea of making it more compact by dealing with U64_MAX and
unknown in find_hv_status_info(), however I'm not as keen on putting
these cases in the array and iterating over the whole array when they
could just be static constants or inline struct initializers. See below.

I also like the idea of making hv_result_to_*() functions into simple
macros and exporting find_hv_status_info(). However, if it gets used
elsewhere it makes more sense if the returned hv_status_info for the
"Unknown" case contains the actual status code instead of replacing
that information with -2, so then I'd want to return it by value
instead of pointer:

+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (status), (errno) }
+       _STATUS_INFO(HV_STATUS_SUCCESS,                         0),
<snip>
+       _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED,             -EIO),
+#undef _STATUS_INFO
+};
+
+struct hv_status_info hv_get_status_info(u64 hv_status)
+{
+       int i;
+       const struct hv_status_info *info;
+       u16 code = hv_result(hv_status);
+       struct hv_status_info ret = {"Unknown", code, -EIO};
+
+       if (hv_status == U64_MAX)
+               ret = (struct hv_status_info){"Hypercall page missing!", -1,
+                                             -EOPNOTSUPP};
+       else
+               for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+                       info = &hv_status_infos[i];
+                       if (info->code == code) {
+                               ret = *info;
+                               break;
+                       }
+               }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(hv_get_status_info);

and in mshyperv.h:

+#define hv_result_to_string(hv_status) hv_get_status_info(hv_status).string
+#define hv_result_to_errno(hv_status) hv_get_status_info(hv_status).errno
+
+struct hv_status_info {
+       char *string;
+       int code;
+       int errno;
+};
+
+struct hv_status_info hv_get_status_info(u64 hv_status);

Note also I switched the order of code and errno in hv_status_info,
mainly because I think the struct initializers for "Unknown" and
"Hypercall page missing!" are more readable with that order:
{string, code, errno}

Do you see any problems with the above?

> Anyway, just a suggestion. The current code works from what I can
> see.
Thanks, it's not a bad idea at all to make it as compact and readable
as possible on the first try, but not a big loss either way.

Thanks
Nuno

> 
> Michael



From cki-project at redhat.com  Fri Mar 21 13:02:05 2025
From: cki-project at redhat.com (cki-project at redhat.com)
Date: Fri, 21 Mar 2025 20:02:05 -0000
Subject: =?utf-8?b?4pyF?= PASS: Test report for for-kernelci (6.14.0-rc7,
 upstream-arm-next, a2392f33)
Message-ID: <51435.125032116020802862@us-mta-517.us.mimecast.lan>

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK
              Test: OK

Tested-by: CKI Project <cki-project at redhat.com>

Kernel information:
    Commit message: drm/panthor: Clean up FW version information display

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:1728800306


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



From marex at denx.de  Fri Mar 21 12:37:58 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 20:37:58 +0100
Subject: [PATCH 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <Z8XFCv6ku6mG1_x5@e110455-lin.cambridge.arm.com>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-10-marex@denx.de> <2153305.bB369e8A3T@steina-w>
 <4a27b6bf-aca8-4f29-9561-609a42eb81a0@denx.de>
 <Z8XFCv6ku6mG1_x5@e110455-lin.cambridge.arm.com>
Message-ID: <6034b024-381c-4fed-9d97-ad7d5d293112@denx.de>

On 3/3/25 4:04 PM, Liviu Dudau wrote:

[...]

>>>> +			#reset-cells = <1>;
>>>> +			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
>>>> +			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
>>>> +			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
>>>> +			assigned-clock-rates = <133333333>;
>>>> +			power-domains = <&scmi_devpd IMX95_PD_GPU>;
>>>> +			status = "disabled";
>>>> +		};
>>>> +
>>>> +		gpu: gpu at 4d900000 {
>>>> +			compatible = "fsl,imx95-mali", "arm,mali-valhall-csf";
>>>> +			reg = <0 0x4d900000 0 0x480000>;
>>>> +			clocks = <&scmi_clk IMX95_CLK_GPU>;
>>>
>>> There is also IMX95_CLK_GPUAPB. Is this only required for the rese control above?
>>
>> I think I have to describe those clock here too, possibly as 'coregroup'
>> clock ?
> 
> The 'coregroup' clock does indeed control the MMU and L2$ blocks as well as the AXI interface,
> so if that is indeed a separate external clock source it should be defined. Could it be why
> you're seeing issues with L2$ resume on the fast reset path?
Sorry for the delayed reply.

I did define these clock, they are enabled, but the L2 reset problem is 
still present .


From marex at denx.de  Fri Mar 21 12:54:26 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 20:54:26 +0100
Subject: [PATCH 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <20250303133523.2c5153ed@collabora.com>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-7-marex@denx.de>
 <Z8GY0nWXOxCKF-XL@e110455-lin.cambridge.arm.com>
 <fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
 <Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>
 <20250303133523.2c5153ed@collabora.com>
Message-ID: <d19fa0b9-b07b-46cf-aa3f-3c2e65fecd67@denx.de>

On 3/3/25 1:35 PM, Boris Brezillon wrote:

Hi,

>> This looks like it has been part of a R50 release of the DDK, which is recent
>> enough to consider it up-to-date. The issues you're seeing with fast resume are
>> probably due to some integration issues or other quirks.
>>
>> Boris has the most recent experience with playing with fast resume, maybe
>> he can share some tips on where to add messages in Panthor to try to debug
>> your problem.
> 
> If you end up with fast_reset=true, that means the FW claims it entered
> a suspend state from which is can resume quickly (fast-reset), and in
> that case, we're only supposed to power on the L2 block at resume time
> AFAIK. If there's a component that can tell us more, it's probably the
> FW, unfortunately, it doesn't tell us much through the FW interface,
> especially if it's not booting properly. Do you hit this error [1]
> without this patch, and if you do, what's the status reported there?
> 
> [1]https://elixir.bootlin.com/linux/v6.14-rc4/source/drivers/gpu/drm/panthor/panthor_fw.c#L1051

Sorry for the late reply. I get the following, so I think the status is 
"fatal" ?

panthor 4d900000.gpu: [drm] clock rate = 1000000000
panthor 4d900000.gpu: EM: created perf domain
panthor 4d900000.gpu: [drm] mali-g310 id 0xac74 major 0x0 minor 0x0 
status 0x1
panthor 4d900000.gpu: [drm] Features: L2:0x7110306 Tiler:0x809 Mem:0x1 
MMU:0x2830 AS:0xff
panthor 4d900000.gpu: [drm] shader_present=0x1 l2_present=0x1 
tiler_present=0x1
panthor 4d900000.gpu: [drm] Firmware protected mode entry not be 
supported, ignoring
panthor 4d900000.gpu: [drm] Firmware git sha: 
8e5cfcfec20cc8aff8509d37e72babc935d34a3b
panthor 4d900000.gpu: [drm] CSF FW using interface v1.1.0, Features 0x0 
Instrumentation features 0x71
[drm] Initialized panthor 1.3.0 for 4d900000.gpu on minor 0
panthor 4d900000.gpu: [drm] *ERROR* Failed to boot MCU (status=fatal)
panthor 4d900000.gpu: [drm] *ERROR* FW fast reset failed
panthor 4d900000.gpu: [drm] *ERROR* Fast reset failed, trying a slow reset
panthor 4d900000.gpu: [drm] *ERROR* Failed to boot MCU (status=fatal)
panthor 4d900000.gpu: [drm] *ERROR* FW slow reset failed


From marex at denx.de  Fri Mar 21 13:00:43 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:00:43 +0100
Subject: [PATCH 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <20250303134250.5ba726fc@collabora.com>
References: <20250227170012.124768-1-marex@denx.de>
 <20250227170012.124768-7-marex@denx.de>
 <Z8GY0nWXOxCKF-XL@e110455-lin.cambridge.arm.com>
 <fa88c1c1-89ba-4a10-bd57-0819d7740c0a@denx.de>
 <Z8Wb05rmGW0ORnJB@e110455-lin.cambridge.arm.com>
 <20250303133523.2c5153ed@collabora.com>
 <20250303134250.5ba726fc@collabora.com>
Message-ID: <12a0c285-8f1a-4014-9253-0129a3a6ba21@denx.de>

On 3/3/25 1:42 PM, Boris Brezillon wrote:

Hi,

>>> This looks like it has been part of a R50 release of the DDK, which is recent
>>> enough to consider it up-to-date. The issues you're seeing with fast resume are
>>> probably due to some integration issues or other quirks.
>>>
>>> Boris has the most recent experience with playing with fast resume, maybe
>>> he can share some tips on where to add messages in Panthor to try to debug
>>> your problem.
>>
>> If you end up with fast_reset=true, that means the FW claims it entered
>> a suspend state from which is can resume quickly (fast-reset), and in
>> that case, we're only supposed to power on the L2 block at resume time
>> AFAIK.
> 
> Can you try deasserting the reset lines at probe time and keeping them
> deasserted until the device is removed instead of re-asserting at
> suspend time? If that doesn't work, try doing the same with power
> domains.
I'm afraid either of this makes no difference, no.

I'll at least send a V2 now, so others can use the latest state of my work.


From marex at denx.de  Fri Mar 21 13:05:50 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:50 +0100
Subject: [PATCH v2 0/9] arm64: dts: imx95: Add support for Mali G310 GPU
Message-ID: <20250321200625.132494-1-marex@denx.de>

The instance of the GPU populated in i.MX95 is the G310.
Add support for the GPUMIX reset via simple-reset driver,
add reset and multiple power domains support into panthor
GPU driver, add iMX95 GPU support into panthor driver and
describe the iMX95 GPU in imx95.dtsi DT.

Marek Vasut (9):
  dt-bindings: reset: imx95-gpu-blk-ctrl: Document Freescale i.MX95 GPU
    reset
  reset: simple: Add support for Freescale i.MX95 GPU reset
  dt-bindings: gpu: mali-valhall-csf: Document optional reset
  drm/panthor: Implement optional reset
  drm/panthor: Implement support for multiple power domains
  drm/panthor: Reset GPU after L2 cache power off
  dt-bindings: gpu: mali-valhall-csf: Document i.MX95 support
  drm/panthor: Add i.MX95 support
  arm64: dts: imx95: Describe Mali G310 GPU

 .../bindings/gpu/arm,mali-valhall-csf.yaml    | 12 +++
 .../reset/nxp,imx95-gpu-blk-ctrl.yaml         | 49 ++++++++++++
 arch/arm64/boot/dts/freescale/imx95.dtsi      | 58 ++++++++++++++
 drivers/gpu/drm/panthor/panthor_device.c      | 75 +++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_device.h      |  8 ++
 drivers/gpu/drm/panthor/panthor_drv.c         |  1 +
 drivers/gpu/drm/panthor/panthor_gpu.c         | 12 +--
 drivers/reset/Kconfig                         |  8 ++
 drivers/reset/reset-simple.c                  |  9 +++
 9 files changed, 227 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml

---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org

-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:51 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:51 +0100
Subject: [PATCH v2 1/9] dt-bindings: reset: imx95-gpu-blk-ctrl: Document Freescale i.MX95 GPU reset
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-2-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 does require
release from reset by writing into a single GPUMIX block controller
GPURESET register bit 0. Document support for this reset register.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Fix dt_binding_check errors in example, temporarily use fixed
      numbers to refer to IMX95_CLK_GPUAPB clock and IMX95_PD_GPU
      power-domain
    - Drop trailing pipe after description:
    - Drop leading dash before const in compatible:
    - Switch from fsl, to nxp, vendor prefix
---
 .../reset/nxp,imx95-gpu-blk-ctrl.yaml         | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml

diff --git a/Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml b/Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml
new file mode 100644
index 0000000000000..ca841db20d35b
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/nxp,imx95-gpu-blk-ctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX95 GPU Block Controller
+
+maintainers:
+  - Marek Vasut <marex at denx.de>
+
+description:
+  This reset controller is a block of ad-hoc debug registers, one of
+  which is a single-bit GPU reset.
+
+properties:
+  compatible:
+    const: nxp,imx95-gpu-blk-ctrl
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  '#reset-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - '#reset-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    reset-controller at 4d810000 {
+        compatible = "nxp,imx95-gpu-blk-ctrl";
+        reg = <0x4d810000 0xc>;
+        clocks = <&clk 83>;
+        power-domains = <&scmi_devpd 14>;
+        #reset-cells = <1>;
+    };
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:52 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:52 +0100
Subject: [PATCH v2 2/9] reset: simple: Add support for Freescale i.MX95 GPU reset
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-3-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 does require
release from reset by writing into a single GPUMIX block controller
GPURESET register bit 0. Implement support for this reset register.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Set nr_resets=1 to limit the amount of resets to single bit
    - Switch from fsl, to nxp, vendor prefix
    - Add RESET_IMX95_GPU Kconfig symbol to select this reset driver
      on MX9
---
 drivers/reset/Kconfig        | 8 ++++++++
 drivers/reset/reset-simple.c | 9 +++++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 99f6f9784e686..0b48e76fd0aab 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -249,12 +249,20 @@ config RESET_SIMPLE
 	   - Altera SoCFPGAs
 	   - ASPEED BMC SoCs
 	   - Bitmain BM1880 SoC
+	   - NXP i.MX95 GPU
 	   - Realtek SoCs
 	   - RCC reset controller in STM32 MCUs
 	   - Allwinner SoCs
 	   - SiFive FU740 SoCs
 	   - Sophgo SoCs
 
+config RESET_IMX95_GPU
+	bool "NXP i.MX95 GPU Reset Driver" if COMPILE_TEST && !SOC_IMX9
+	default SOC_IMX9
+	select RESET_SIMPLE
+	help
+	  This enables the reset driver for i.MX95 GPU.
+
 config RESET_SOCFPGA
 	bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
 	default ARM && ARCH_INTEL_SOCFPGA
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index 2760678398308..64aeda8f76b75 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -133,9 +133,18 @@ static const struct reset_simple_devdata reset_simple_active_low = {
 	.status_active_low = true,
 };
 
+static const struct reset_simple_devdata reset_simple_fsl_imx95_gpu_blk_ctrl = {
+	.reg_offset = 0x8,
+	.active_low = true,
+	.nr_resets = 1,
+	.status_active_low = true,
+};
+
 static const struct of_device_id reset_simple_dt_ids[] = {
 	{ .compatible = "altr,stratix10-rst-mgr",
 		.data = &reset_simple_socfpga },
+	{ .compatible = "nxp,imx95-gpu-blk-ctrl",
+		.data = &reset_simple_fsl_imx95_gpu_blk_ctrl },
 	{ .compatible = "st,stm32-rcc", },
 	{ .compatible = "allwinner,sun6i-a31-clock-reset",
 		.data = &reset_simple_active_low },
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:53 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:53 +0100
Subject: [PATCH v2 3/9] dt-bindings: gpu: mali-valhall-csf: Document optional reset
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-4-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 does require
release from reset by writing into a single GPUMIX block controller
GPURESET register bit 0. Document support for one optional reset.

Acked-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Add RB from Frank
    - Add AB from Rob
---
 .../devicetree/bindings/gpu/arm,mali-valhall-csf.yaml          | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
index a5b4e00217587..0efa06822a543 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
@@ -61,6 +61,9 @@ properties:
     minItems: 1
     maxItems: 5
 
+  resets:
+    maxItems: 1
+
   sram-supply: true
 
   "#cooling-cells":
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:54 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:54 +0100
Subject: [PATCH v2 4/9] drm/panthor: Implement optional reset
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-5-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 does require
release from reset by writing into a single GPUMIX block controller
GPURESET register bit 0. Implement support for one optional reset.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: Drop the select RESET_SIMPLE from Kconfig
---
 drivers/gpu/drm/panthor/panthor_device.c | 23 +++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_device.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index a9da1d1eeb707..51ee9cae94504 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -64,6 +64,17 @@ static int panthor_clk_init(struct panthor_device *ptdev)
 	return 0;
 }
 
+static int panthor_reset_init(struct panthor_device *ptdev)
+{
+	ptdev->resets = devm_reset_control_get_optional_exclusive_deasserted(ptdev->base.dev, NULL);
+	if (IS_ERR(ptdev->resets))
+		return dev_err_probe(ptdev->base.dev,
+				     PTR_ERR(ptdev->resets),
+				     "get reset failed");
+
+	return 0;
+}
+
 void panthor_device_unplug(struct panthor_device *ptdev)
 {
 	/* This function can be called from two different path: the reset work
@@ -217,6 +228,10 @@ int panthor_device_init(struct panthor_device *ptdev)
 	if (ret)
 		return ret;
 
+	ret = panthor_reset_init(ptdev);
+	if (ret)
+		return ret;
+
 	ret = panthor_devfreq_init(ptdev);
 	if (ret)
 		return ret;
@@ -470,6 +485,10 @@ int panthor_device_resume(struct device *dev)
 	if (ret)
 		goto err_disable_stacks_clk;
 
+	ret = reset_control_deassert(ptdev->resets);
+	if (ret)
+		goto err_disable_coregroup_clk;
+
 	panthor_devfreq_resume(ptdev);
 
 	if (panthor_device_is_initialized(ptdev) &&
@@ -512,6 +531,9 @@ int panthor_device_resume(struct device *dev)
 
 err_suspend_devfreq:
 	panthor_devfreq_suspend(ptdev);
+	reset_control_assert(ptdev->resets);
+
+err_disable_coregroup_clk:
 	clk_disable_unprepare(ptdev->clks.coregroup);
 
 err_disable_stacks_clk:
@@ -563,6 +585,7 @@ int panthor_device_suspend(struct device *dev)
 
 	panthor_devfreq_suspend(ptdev);
 
+	reset_control_assert(ptdev->resets);
 	clk_disable_unprepare(ptdev->clks.coregroup);
 	clk_disable_unprepare(ptdev->clks.stacks);
 	clk_disable_unprepare(ptdev->clks.core);
diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
index da6574021664b..fea3a05778e2e 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -111,6 +111,9 @@ struct panthor_device {
 		struct clk *coregroup;
 	} clks;
 
+	/** @resets: GPU reset. */
+	struct reset_control *resets;
+
 	/** @coherent: True if the CPU/GPU are memory coherent. */
 	bool coherent;
 
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:55 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:55 +0100
Subject: [PATCH v2 5/9] drm/panthor: Implement support for multiple power domains
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-6-marex@denx.de>

The driver code power domain binding to driver instances only works
for single power domain, in case there are multiple power domains,
it is necessary to explicitly attach via dev_pm_domain_attach*().
As DT bindings list support for up to 5 power domains, add support
for attaching them all. This is useful on Freescale i.MX95 which
does have two power domains.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: Exit from panthor_genpd_init() on any pm_domain_attach_by_id() failure
---
 drivers/gpu/drm/panthor/panthor_device.c | 52 ++++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_device.h |  5 +++
 2 files changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 51ee9cae94504..8aa79c6d157e1 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -75,6 +75,54 @@ static int panthor_reset_init(struct panthor_device *ptdev)
 	return 0;
 }
 
+/* Generic power domain handling code, see drivers/gpu/drm/tiny/simpledrm.c */
+static void panthor_detach_genpd(void *res)
+{
+	struct panthor_device *ptdev = res;
+	int i;
+
+	if (ptdev->pwr_dom_count <= 1)
+		return;
+
+	for (i = ptdev->pwr_dom_count - 1; i >= 0; i--)
+		dev_pm_domain_detach(ptdev->pwr_dom_devs[i], true);
+}
+
+static int panthor_genpd_init(struct panthor_device *ptdev)
+{
+	struct device *dev = ptdev->base.dev;
+	int i;
+
+	ptdev->pwr_dom_count = of_count_phandle_with_args(dev->of_node, "power-domains",
+							  "#power-domain-cells");
+	/*
+	 * Single power-domain devices are handled by driver core nothing to do
+	 * here. The same for device nodes without "power-domains" property.
+	 */
+	if (ptdev->pwr_dom_count <= 1)
+		return 0;
+
+	if (ptdev->pwr_dom_count > ARRAY_SIZE(ptdev->pwr_dom_devs)) {
+		drm_warn(&ptdev->base, "Too many power domains (%d) for this device\n",
+			 ptdev->pwr_dom_count);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ptdev->pwr_dom_count; i++) {
+		ptdev->pwr_dom_devs[i] = dev_pm_domain_attach_by_id(dev, i);
+		if (!IS_ERR(ptdev->pwr_dom_devs[i]))
+			continue;
+
+		/* Missing dependency, try again. */
+		panthor_detach_genpd(ptdev);
+		return dev_err_probe(ptdev->base.dev,
+				     PTR_ERR(ptdev->pwr_dom_devs[i]),
+				     "pm_domain_attach_by_id(%u) failed\n", i);
+	}
+
+	return devm_add_action_or_reset(dev, panthor_detach_genpd, ptdev);
+}
+
 void panthor_device_unplug(struct panthor_device *ptdev)
 {
 	/* This function can be called from two different path: the reset work
@@ -232,6 +280,10 @@ int panthor_device_init(struct panthor_device *ptdev)
 	if (ret)
 		return ret;
 
+	ret = panthor_genpd_init(ptdev);
+	if (ret)
+		return ret;
+
 	ret = panthor_devfreq_init(ptdev);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
index fea3a05778e2e..7fb65447253e9 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -114,6 +114,11 @@ struct panthor_device {
 	/** @resets: GPU reset. */
 	struct reset_control *resets;
 
+	/** @pwr_dom_count: Power domain count */
+	int pwr_dom_count;
+	/** @pwr_dom_dev: Power domain devices */
+	struct device *pwr_dom_devs[5];
+
 	/** @coherent: True if the CPU/GPU are memory coherent. */
 	bool coherent;
 
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:56 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:56 +0100
Subject: [PATCH v2 6/9] drm/panthor: Reset GPU after L2 cache power off
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-7-marex@denx.de>

This seems necessary on Freescale i.MX95 Mali G310 to reliably resume
from runtime PM suspend. Without this, if only the L2 is powered down
on RPM entry, the GPU gets stuck and does not indicate the firmware is
booted after RPM resume.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: No change
---
 drivers/gpu/drm/panthor/panthor_gpu.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index 671049020afaa..0f07ef7d9aea7 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -470,11 +470,12 @@ int panthor_gpu_soft_reset(struct panthor_device *ptdev)
  */
 void panthor_gpu_suspend(struct panthor_device *ptdev)
 {
-	/* On a fast reset, simply power down the L2. */
-	if (!ptdev->reset.fast)
-		panthor_gpu_soft_reset(ptdev);
-	else
-		panthor_gpu_power_off(ptdev, L2, 1, 20000);
+	/*
+	 * Power off the L2 and soft reset the GPU, that makes
+	 * iMX95 Mali G310 resume without firmware boot timeout.
+	 */
+	panthor_gpu_power_off(ptdev, L2, 1, 20000);
+	panthor_gpu_soft_reset(ptdev);
 
 	panthor_gpu_irq_suspend(&ptdev->gpu->irq);
 }
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:57 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:57 +0100
Subject: [PATCH v2 7/9] dt-bindings: gpu: mali-valhall-csf: Document i.MX95 support
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-8-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 is the
Mali G310, document support for this variant.

Reviewed-by: Alexander Stein <alexander.stein at ew.tq-group.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Add RB from Frank and Alexander
    - Make resets: mandatory on i.MX95
    - Switch from fsl, to nxp, vendor prefix
---
 .../devicetree/bindings/gpu/arm,mali-valhall-csf.yaml    | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
index 0efa06822a543..485609de54eac 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
@@ -18,6 +18,7 @@ properties:
     oneOf:
       - items:
           - enum:
+              - nxp,imx95-mali            # G310
               - rockchip,rk3588-mali
           - const: arm,mali-valhall-csf   # Mali Valhall GPU model/revision is fully discoverable
 
@@ -111,6 +112,14 @@ allOf:
         power-domains:
           maxItems: 1
         power-domain-names: false
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: nxp,imx95-mali
+    then:
+      required:
+        - resets
 
 examples:
   - |
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:59 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:59 +0100
Subject: [PATCH v2 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-10-marex@denx.de>

The instance of the GPU populated in i.MX95 is the G310,
describe this GPU in the DT. Include description of the
GPUMIX block controller, which can be operated as a simple
reset. Include dummy GPU voltage regulator and OPP tables.

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Drop regulator-{always,boot}-on from fixed-gpu-reg regulator
    - Keep the GPU and GPUMIX always enabled
    - Switch from fsl, to nxp, vendor prefix
    - Fix opp_table to opp-table
    - Describe IMX95_CLK_GPUAPB as coregroup clock
    - Sort interrupts by their names to match bindings
---
 arch/arm64/boot/dts/freescale/imx95.dtsi | 58 ++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index 9bb26b466a061..3acdbd7fd4eee 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -249,6 +249,35 @@ dummy: clock-dummy {
 		clock-output-names = "dummy";
 	};
 
+	gpu_fixed_reg: fixed-gpu-reg {
+		compatible = "regulator-fixed";
+		regulator-min-microvolt = <920000>;
+		regulator-max-microvolt = <920000>;
+		regulator-name = "vdd_gpu";
+	};
+
+	gpu_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-hz-real = /bits/ 64 <500000000>;
+			opp-microvolt = <920000>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-hz-real = /bits/ 64 <800000000>;
+			opp-microvolt = <920000>;
+		};
+
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-hz-real = /bits/ 64 <1000000000>;
+			opp-microvolt = <920000>;
+		};
+	};
+
 	clk_ext1: clock-ext1 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -1890,6 +1919,35 @@ netc_emdio: mdio at 0,0 {
 			};
 		};
 
+		gpu_blk_ctrl: reset-controller at 4d810000 {
+			compatible = "nxp,imx95-gpu-blk-ctrl";
+			reg = <0x0 0x4d810000 0x0 0xc>;
+			#reset-cells = <1>;
+			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
+			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
+			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
+			assigned-clock-rates = <133333333>;
+			power-domains = <&scmi_devpd IMX95_PD_GPU>;
+		};
+
+		gpu: gpu at 4d900000 {
+			compatible = "nxp,imx95-mali", "arm,mali-valhall-csf";
+			reg = <0 0x4d900000 0 0x480000>;
+			clocks = <&scmi_clk IMX95_CLK_GPU>, <&scmi_clk IMX95_CLK_GPUAPB>;
+			clock-names = "core", "coregroup";
+			interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "job", "mmu", "gpu";
+			mali-supply = <&gpu_fixed_reg>;
+			operating-points-v2 = <&gpu_opp_table>;
+			power-domains = <&scmi_devpd IMX95_PD_GPU>, <&scmi_perf IMX95_PERF_GPU>;
+			power-domain-names = "mix", "perf";
+			resets = <&gpu_blk_ctrl 0>;
+			#cooling-cells = <2>;
+			dynamic-power-coefficient = <1013>;
+		};
+
 		ddr-pmu at 4e090dc0 {
 			compatible = "fsl,imx95-ddr-pmu", "fsl,imx93-ddr-pmu";
 			reg = <0x0 0x4e090dc0 0x0 0x200>;
-- 
2.47.2



From marex at denx.de  Fri Mar 21 13:05:58 2025
From: marex at denx.de (Marek Vasut)
Date: Fri, 21 Mar 2025 21:05:58 +0100
Subject: [PATCH v2 8/9] drm/panthor: Add i.MX95 support
In-Reply-To: <20250321200625.132494-1-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
Message-ID: <20250321200625.132494-9-marex@denx.de>

The instance of the GPU populated in Freescale i.MX95 is the
Mali G310, add support for this variant.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Boris Brezillon <boris.brezillon at collabora.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: David Airlie <airlied at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Liviu Dudau <liviu.dudau at arm.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Philipp Zabel <p.zabel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Sebastian Reichel <sre at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Simona Vetter <simona at ffwll.ch>
Cc: Steven Price <steven.price at arm.com>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
---
V2: - Add RB from Frank
    - Switch from fsl, to nxp, vendor prefix
    - Fix up GPU_MODEL(g310, 0, 0) to GPU_MODEL(g310, 10, 4)
    - Remove code comments about MX95 and G310
---
 drivers/gpu/drm/panthor/panthor_drv.c | 1 +
 drivers/gpu/drm/panthor/panthor_gpu.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index 06fe46e320738..299ec8bafdd17 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1591,6 +1591,7 @@ static struct attribute *panthor_attrs[] = {
 ATTRIBUTE_GROUPS(panthor);
 
 static const struct of_device_id dt_match[] = {
+	{ .compatible = "nxp,imx95-mali" },
 	{ .compatible = "rockchip,rk3588-mali" },
 	{ .compatible = "arm,mali-valhall-csf" },
 	{}
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index 0f07ef7d9aea7..59fc1cacefcfe 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -67,6 +67,7 @@ struct panthor_model {
 }
 
 static const struct panthor_model gpu_models[] = {
+	GPU_MODEL(g310, 10, 4),
 	GPU_MODEL(g610, 10, 7),
 	{},
 };
-- 
2.47.2



From bvanassche at acm.org  Fri Mar 21 13:10:14 2025
From: bvanassche at acm.org (Bart Van Assche)
Date: Fri, 21 Mar 2025 13:10:14 -0700
Subject: [PATCH v2 0/7] ufs-exynos stability fixes for gs101
In-Reply-To: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
References: <20250319-exynos-ufs-stability-fixes-v2-0-96722cc2ba1b@linaro.org>
Message-ID: <8d5fd977-b600-492c-b888-2318130f46ec@acm.org>

On 3/19/25 8:30 AM, Peter Griffin wrote:
> This series fixes several stability issues with the upstream ufs-exynos
> driver, specifically for the gs101 SoC found in Pixel 6.
> 
> The main fix is regarding the IO cache coherency setting and ensuring
> that it is correctly applied depending on if the dma-coherent property
> is specified in device tree. This fixes the UFS stability issues on gs101
> and I would imagine will also fix issues on exynosauto platform that
> seems to have similar iocc shareability bits.
> 
> Additionally the phy reference counting is fixed which allows module
> load/unload to work reliably and keeps the phy state machine in sync
> with the controller glue driver.

Although these patches are somewhat outside my area of expertise, the
patches look good to me, hence:

Reviewed-by: Bart Van Assche <bvanassche at acm.org>


From acarmina at redhat.com  Fri Mar 21 14:05:42 2025
From: acarmina at redhat.com (Alessandro Carminati)
Date: Fri, 21 Mar 2025 22:05:42 +0100
Subject: [PATCH v4 10/14] s390: Add support for suppressing warning backtraces
In-Reply-To: <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>
References: <20250313114329.284104-1-acarmina@redhat.com> <20250313114329.284104-11-acarmina@redhat.com>
 <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>
Message-ID: <CAGegRW4GinPmsav5=VBfjXBKy4cUEs5FWv-ixXODk7ajZ69vYg@mail.gmail.com>

Hello Guenter,
Sorry for being late to the party.

On Fri, Mar 21, 2025 at 6:06?PM Guenter Roeck <linux at roeck-us.net> wrote:
>
> On 3/13/25 04:43, Alessandro Carminati wrote:
> > From: Guenter Roeck <linux at roeck-us.net>
> >
> > Add name of functions triggering warning backtraces to the __bug_table
> > object section to enable support for suppressing WARNING backtraces.
> >
> > To limit image size impact, the pointer to the function name is only added
> > to the __bug_table section if both CONFIG_KUNIT_SUPPRESS_BACKTRACE and
> > CONFIG_DEBUG_BUGVERBOSE are enabled. Otherwise, the __func__ assembly
> > parameter is replaced with a (dummy) NULL parameter to avoid an image size
> > increase due to unused __func__ entries (this is necessary because
> > __func__ is not a define but a virtual variable).
> >
> > Tested-by: Linux Kernel Functional Testing <lkft at linaro.org>
> > Acked-by: Dan Carpenter <dan.carpenter at linaro.org>
> > Cc: Heiko Carstens <hca at linux.ibm.com>
> > Cc: Vasily Gorbik <gor at linux.ibm.com>
> > Cc: Alexander Gordeev <agordeev at linux.ibm.com>
> > Signed-off-by: Guenter Roeck <linux at roeck-us.net>
> > Signed-off-by: Alessandro Carminati <acarmina at redhat.com>
> > ---
> >   arch/s390/include/asm/bug.h | 17 ++++++++++++++---
> >   1 file changed, 14 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
> > index c500d45fb465..44d4e9f24ae0 100644
> > --- a/arch/s390/include/asm/bug.h
> > +++ b/arch/s390/include/asm/bug.h
> > @@ -8,6 +8,15 @@
> >
> >   #ifdef CONFIG_DEBUG_BUGVERBOSE
> >
> > +#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
> > +# define HAVE_BUG_FUNCTION
> > +# define __BUG_FUNC_PTR      "       .long   %0-.\n"
> > +# define __BUG_FUNC  __func__
>
> gcc 7.5.0 on s390 barfs; it doesn't like the use of "__func__" with "%0-."
>
> drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c: In function 'anx_dp_aux_transfer':
> ././include/linux/compiler_types.h:492:20: warning: asm operand 0 probably doesn't match constraints
>
> I was unable to find an alternate constraint that the compiler would accept.
>
> I don't know if the same problem is seen with older compilers on other architectures,
> or if the problem is relevant in the first place.
>
> gcc 10.3.0 and later do not have this problem. I also tried s390 builds with gcc 9.4
> and 9.5 but they both crash for unrelated reasons.
>
> If this is a concern, the best idea I have is to make KUNIT_SUPPRESS_BACKTRACE
> depend on, say,
>         depends on CC_IS_CLANG || (CC_IS_GCC && GCC_VERSION >= 100300)
>
> A more complex solution might be to define an architecture flag such
> as HAVE_SUPPRESS_BACKTRACE, make that conditional on the gcc version
> for s390 only, and make KUNIT_SUPPRESS_BACKTRACE depend on it.

I've spent some time trying to better define the problem.
Although it may seem trivial, the old compiler simply doesn't work?I
believe the issue is a bit more complex.

So, let me share some code and then comment on it.
$ cat bug-s390.c
#include "bug_entry.h"
#define asm_inline asm __inline
# define __BUG_FUNC_PTR " .long %0-.\n"
# define __BUG_FUNC __func__
#define __EMIT_BUG(x) do { \
asm_inline volatile( \
"0: mc 0,0\n" \
".section .rodata.str,\"aMS\", at progbits,1\n" \
"1: .asciz \""__FILE__"\"\n" \
".previous\n" \
".section __bug_table,\"aw\"\n" \
"2: .long 0b-.\n" \
" .long 1b-.\n" \
__BUG_FUNC_PTR \
" .short %1,%2\n" \
" .org 2b+%3\n" \
".previous\n" \
: : "i" (__BUG_FUNC), \
    "i" (__LINE__), \
    "i" (x), \
    "i" (sizeof(struct bug_entry))); \
} while (0)

#define BUG() do { \
__EMIT_BUG(0); \
} while (0)

void f1(){
BUG();
}
void f2(){
BUG();
}
int main() {
BUG();
        f1();
        f2();
return 0;
}
$ # This is a stripped version of the s390x code for bug
$ ~/x-tools/s390x-ibm-linux-gnu_14/bin/s390x-ibm-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=/home/alessandro/x-tools/s390x-ibm-linux-gnu_14/bin/s390x-ibm-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/home/alessandro/x-tools/s390x-ibm-linux-gnu_14/bin/../libexec/gcc/s390x-ibm-linux-gnu/14.2.0/lto-wrapper
Target: s390x-ibm-linux-gnu
Configured with:
/home/alessandro/src/s390x-toolchain/.build/s390x-ibm-linux-gnu/src/gcc/configure
--build=x86_64-build_pc-linux-gnu --host=x86_64-build_pc-linux-gnu
--target=s390x-ibm-linux-gnu
--prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu
--exec_prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu
--with-sysroot=/home/alessandro/x-tools/s390x-ibm-linux-gnu/s390x-ibm-linux-gnu/sysroot
--enable-languages=c,c++ --with-pkgversion='crosstool-NG
1.27.0.18_7458341' --enable-__cxa_atexit --disable-libmudflap
--disable-libgomp --disable-libssp --disable-libquadmath
--disable-libquadmath-support --disable-libsanitizer --disable-libmpx
--with-gmp=/home/alessandro/src/s390x-toolchain/.build/s390x-ibm-linux-gnu/buildtools
--with-mpfr=/home/alessandro/src/s390x-toolchain/.build/s390x-ibm-linux-gnu/buildtools
--with-mpc=/home/alessandro/src/s390x-toolchain/.build/s390x-ibm-linux-gnu/buildtools
--with-isl=/home/alessandro/src/s390x-toolchain/.build/s390x-ibm-linux-gnu/buildtools
--enable-lto --enable-threads=posix --enable-target-optspace
--disable-plugin --disable-nls --disable-multilib
--with-local-prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu/s390x-ibm-linux-gnu/sysroot
--enable-long-long
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.0 (crosstool-NG 1.27.0.18_7458341)
$ ~/x-tools/s390x-ibm-linux-gnu_14/bin/s390x-ibm-linux-gnu-gcc -S -m64
bug-s390.c
$ ~/x-tools/s390x-ibm-linux-gnu_14/bin/s390x-ibm-linux-gnu-gcc -S -m64
-fPIC bug-s390.c
$ ~/x-tools/s390x-ibm-linux-gnu/bin/s390x-ibm-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=/home/alessandro/x-tools/s390x-ibm-linux-gnu/bin/s390x-ibm-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/home/alessandro/x-tools/s390x-ibm-linux-gnu/libexec/gcc/s390x-ibm-linux-gnu/7.5.0/lto-wrapper
Target: s390x-ibm-linux-gnu
Configured with:
/home/alessandro/src/cross-s390/.build/s390x-ibm-linux-gnu/src/gcc/configure
--build=x86_64-build_pc-linux-gnu --host=x86_64-build_pc-linux-gnu
--target=s390x-ibm-linux-gnu
--prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu
--exec_prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu
--with-sysroot=/home/alessandro/x-tools/s390x-ibm-linux-gnu/s390x-ibm-linux-gnu/sysroot
--enable-languages=c --with-pkgversion='crosstool-NG
1.27.0.18_7458341' --enable-__cxa_atexit --disable-tm-clone-registry
--disable-libmudflap --disable-libgomp --disable-libssp
--disable-libquadmath --disable-libquadmath-support
--disable-libsanitizer --disable-libmpx --disable-libstdcxx-verbose
--with-gmp=/home/alessandro/src/cross-s390/.build/s390x-ibm-linux-gnu/buildtools
--with-mpfr=/home/alessandro/src/cross-s390/.build/s390x-ibm-linux-gnu/buildtools
--with-mpc=/home/alessandro/src/cross-s390/.build/s390x-ibm-linux-gnu/buildtools
--with-isl=/home/alessandro/src/cross-s390/.build/s390x-ibm-linux-gnu/buildtools
--enable-lto --without-zstd --enable-threads=posix
--enable-target-optspace --disable-plugin --disable-nls
--disable-multilib
--with-local-prefix=/home/alessandro/x-tools/s390x-ibm-linux-gnu/s390x-ibm-linux-gnu/sysroot
--enable-long-long
Thread model: posix
gcc version 7.5.0 (crosstool-NG 1.27.0.18_7458341)
$ ~/x-tools/s390x-ibm-linux-gnu/bin/s390x-ibm-linux-gnu-gcc  -S -m64 bug-s390.c
$ ~/x-tools/s390x-ibm-linux-gnu/bin/s390x-ibm-linux-gnu-gcc  -S -m64
-fPIC bug-s390.c
bug-s390.c: In function 'f1':
bug-s390.c:2:20: warning: asm operand 0 probably doesn't match constraints
 #define asm_inline asm __inline
                    ^
bug-s390.c:6:2: note: in expansion of macro 'asm_inline'
  asm_inline volatile(     \
  ^~~~~~~~~~
bug-s390.c:25:2: note: in expansion of macro '__EMIT_BUG'
  __EMIT_BUG(0);     \
  ^~~~~~~~~~
bug-s390.c:29:2: note: in expansion of macro 'BUG'
  BUG();
  ^~~
bug-s390.c:2:20: error: impossible constraint in 'asm'
 #define asm_inline asm __inline
                    ^
bug-s390.c:6:2: note: in expansion of macro 'asm_inline'
  asm_inline volatile(     \
  ^~~~~~~~~~
bug-s390.c:25:2: note: in expansion of macro '__EMIT_BUG'
  __EMIT_BUG(0);     \
  ^~~~~~~~~~
bug-s390.c:29:2: note: in expansion of macro 'BUG'
  BUG();
  ^~~
bug-s390.c: In function 'f2':
bug-s390.c:2:20: warning: asm operand 0 probably doesn't match constraints
 #define asm_inline asm __inline
                    ^
bug-s390.c:6:2: note: in expansion of macro 'asm_inline'
  asm_inline volatile(     \
  ^~~~~~~~~~
bug-s390.c:25:2: note: in expansion of macro '__EMIT_BUG'
  __EMIT_BUG(0);     \
  ^~~~~~~~~~
bug-s390.c:32:2: note: in expansion of macro 'BUG'
  BUG();
  ^~~
bug-s390.c: In function 'main':
bug-s390.c:2:20: warning: asm operand 0 probably doesn't match constraints
 #define asm_inline asm __inline
                    ^
bug-s390.c:6:2: note: in expansion of macro 'asm_inline'
  asm_inline volatile(     \
  ^~~~~~~~~~
bug-s390.c:25:2: note: in expansion of macro '__EMIT_BUG'
  __EMIT_BUG(0);     \
  ^~~~~~~~~~
bug-s390.c:35:2: note: in expansion of macro 'BUG'
  BUG();
  ^~~
$ cat linux-6.14-rc7/arch/s390/Makefile| grep "fPIC"
KBUILD_AFLAGS_MODULE += -fPIC
KBUILD_CFLAGS_MODULE += -fPIC
KBUILD_CFLAGS += -fPIC

As you can see, the problem is not that the compiler itself doesn't
work, but rather that -fPIC introduces some complications.
__func__ is a compile-time constant, but this holds true only for
traditionally linked code.
When compiling position-independent code, this assumption no longer applies.

GCC makes significant efforts to handle this, and for several
architectures, it manages to solve the problem.
However, this is not universally the case.
Additionally, -fPIC is not widely used in kernel code... I have only
seen it used for VDSO, the x86 boot piggyback decompressor, PowerPC
boot, and the s390x architecture.

That said, GCC has been mitigating this issue, allowing us to treat a
non-compile-time constant as if it were one.
A proof of this is that, at least since GCC 11, the s390x version of
GCC is able to build this code.
Before that... certainly in GCC 7.5 it couldn't.

A simple fix would be to restrict usage to GCC versions greater than
11 for s390.

The real concern is that we have a latent issue that could be
triggered by changes in build settings, as "feature" support varies
across GCC versions and architectures.
For example, while x86_64 at version 14 seems to work both with and
without -fPIC, this is not the case for AArch64, where enabling -fPIC
causes failures even in version 14.

I'm currently working on a long-term fix for this.

>
> Guenter
>


-- 
---
Alessandro



From robh at kernel.org  Fri Mar 21 14:23:57 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 21 Mar 2025 16:23:57 -0500
Subject: [PATCH] media: dt-bindings: mediatek,vcodec-encoder: Drop
 assigned-clock properties
In-Reply-To: <20250317214621.794674-1-robh@kernel.org>
References: <20250317214621.794674-1-robh@kernel.org>
Message-ID: <174259221258.4077511.5846925634356953161.robh@kernel.org>


On Mon, 17 Mar 2025 16:46:20 -0500, Rob Herring (Arm) wrote:
> The assigned-clock properties are always allowed on nodes with
> 'clocks' and generally not required. Additionally the mt8183 doesn't
> define them, so they must not be required in that case.
> 
> Signed-off-by: Rob Herring (Arm) <robh at kernel.org>
> ---
>  .../devicetree/bindings/media/mediatek,vcodec-encoder.yaml  | 6 ------
>  1 file changed, 6 deletions(-)
> 

Applied, thanks!



From Thinh.Nguyen at synopsys.com  Fri Mar 21 14:24:20 2025
From: Thinh.Nguyen at synopsys.com (Thinh Nguyen)
Date: Fri, 21 Mar 2025 21:24:20 +0000
Subject: [PATCH] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <a9812897-2c79-4a1c-9431-c6f184233a57@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.323aeebd-1577-4c21-85a6-ff9262fb6cb7@emailsignatures365.codetwo.com>
 <20250314155706.31058-1-mike.looijmans@topic.nl>
 <20250314211411.l5taj5nysvcalfyz@synopsys.com>
 <8ee2ce74-dc6b-463a-ba95-ad25669a1179@topic.nl>
 <20250318001211.tnjwfckt5j4fbvjf@synopsys.com>
 <a9812897-2c79-4a1c-9431-c6f184233a57@topic.nl>
Message-ID: <20250321212419.fhyj4rcx4emte6qm@synopsys.com>

On Tue, Mar 18, 2025, Mike Looijmans wrote:
> On 18-03-2025 01:12, Thinh Nguyen wrote:
> > On Mon, Mar 17, 2025, Mike Looijmans wrote:
> > > On 14-03-2025 22:14, Thinh Nguyen wrote:
> > > > On Fri, Mar 14, 2025, Mike Looijmans wrote:
> > > > > Set the gpio to "high" on acquisition, instead of acquiring it in low
> > > > > state and then immediately setting it high again. This prevents a
> > > > > short "spike" on the reset signal.
> > > > How does this affect the current programming flow beside preventing a
> > > > spike to the reset signal?
> > > I don't understand your question. What "programming flow" are you referring
> > > to?
> > It's not obvious to me if this is an error in Xilinx documentation, the
> > driver issue, or whether this is found through experiment. Since I don't
> > have the info of this platform, it would help to know where the source
> > of error is so we can document this in the code or change-log.
> 
> It's a bug in the driver, found through code inspection.
> 
> The reset GPIO here is to control the reset signal to an external, usually
> ULPI PHY, chip. This external chip is not part of the Xilinx hardware.
> 
> > > The reset sequence was just plain wrong, the issue is almost the same as the
> > Do we need a fix tag and add to stable then?
> 
> That would be appropriate I think.
> 
> 
> > 
> > > one described in this commit:
> > > e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"
> > > 
> > > Note that I see this high-low-high-low double reset toggle in many Xilinx
> > > software drivers, they seem to teach that at the Xilinx academy or so.
> > > 
> > > 
> > > > > Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> > > > > ---
> > > > > 
> > > > >    drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
> > > > >    1 file changed, 1 insertion(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> > > > > index a33a42ba0249..a159a511483b 100644
> > > > > --- a/drivers/usb/dwc3/dwc3-xilinx.c
> > > > > +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> > > > > @@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
> > > > >    skip_usb3_phy:
> > > > >    	/* ulpi reset via gpio-modepin or gpio-framework driver */
> > > > > -	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > > > +	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> > > > >    	if (IS_ERR(reset_gpio)) {
> > > > >    		return dev_err_probe(dev, PTR_ERR(reset_gpio),
> > > > >    				     "Failed to request reset GPIO\n");
> > > > > @@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
> > > > >    	if (reset_gpio) {
> > > > >    		/* Toggle ulpi to reset the phy. */
> > > > Does the comment above still apply?
> > > Now you mention it, the comment never made any sense anyway.
> > > 
> > Then can we remove it?
> 
> Removing would be better, yes. I'll make a v2 patch.
> 
> 
> > > > > -		gpiod_set_value_cansleep(reset_gpio, 1);
> > > > >    		usleep_range(5000, 10000);
> > > > Do we still need this usleep_range here?
> > > Yes, this is the "reset active" time.
> > > 
> > But why do we need 2 calls to usleep_range? From just looking at this
> > here, it appears that the first was intended for the removed
> > gpiod_set_value_cansleep(reset_gpio, 1). If this "reset active" time is
> > needed irrespective of the existent reset_gpio, then shouldn't it be set
> > outside of this if statement?
> 
> It helps to see the whole thing instead of just the patch.
> 
> If I omit error handling and comments then the original code reads:
> 
> ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> ??????? if (reset_gpio) {
> ??????????????? gpiod_set_value_cansleep(reset_gpio, 1);
> ??????????????? usleep_range(5000, 10000);
> ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
> ??????????????? usleep_range(5000, 10000);
> ??????? }
> 
> So the gpio is acquired in a LOW state and then, without delay, is set to a
> high state again. This causes the "spike" I'm mentioning here. The correct
> procedure is to acquire it in the HIGH state immediately, so the sequence
> becomes:
> 
> ??????? reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> ??????? if (reset_gpio) {
> ??????????????? usleep_range(5000, 10000);
> ??????????????? gpiod_set_value_cansleep(reset_gpio, 0);
> ??????????????? usleep_range(5000, 10000);
> ??????? }
> 
> This patch does exactly that.
> 

Ah, that makes sense. Thanks for the explaination.

BR,
Thinh

From Thinh.Nguyen at synopsys.com  Fri Mar 21 14:27:33 2025
From: Thinh.Nguyen at synopsys.com (Thinh Nguyen)
Date: Fri, 21 Mar 2025 21:27:33 +0000
Subject: [PATCH v2] usb: dwc3: xilinx: Prevent spike in reset signal
In-Reply-To: <20250318064518.9320-1-mike.looijmans@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.92a20336-7677-4cd7-9893-b0e0da853ba9@emailsignatures365.codetwo.com>
 <20250318064518.9320-1-mike.looijmans@topic.nl>
Message-ID: <20250321212731.65xizpwjo2p6vc6f@synopsys.com>

On Tue, Mar 18, 2025, Mike Looijmans wrote:
> The "reset" GPIO controls the RESET signal to an external, usually
> ULPI PHY, chip. The original code path acquires the signal in LOW
> state, and then immediately asserts it HIGH again, if the reset
> signal defaulted to asserted, there'd be a short "spike" before the
> reset.
> 
> Here is what happens depending on the pre-existing state of the reset
> signal:
> Reset (previously asserted):   ~~~|_|~~~~|_______
> Reset (previously deasserted): _____|~~~~|_______
>                                   ^ ^    ^
>                                   A B    C
> 
> At point A, the low going transition is because the reset line is
> requested using GPIOD_OUT_LOW. If the line is successfully requested,
> the first thing we do is set it high _without_ any delay. This is
> point B. So, a glitch occurs between A and B.
> 
> Requesting the line using GPIOD_OUT_HIGH eliminates the A and B
> transitions. Instead we get:
> 
> Reset (previously asserted)  : ~~~~~~~~~~|______
> Reset (previously deasserted): ____|~~~~~|______
>                                    ^     ^
>                                    A     C
> 
> Where A and C are the points described above in the code. Point B
> has been eliminated.
> 
> The issue was found during code inspection.
> 
> Also remove the cryptic "toggle ulpi .." comment.
> 
> Fixes: ca05b38252d7 ("usb: dwc3: xilinx: Add gpio-reset support")

May want to add stable tag also?

> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> ---
> 
> Changes in v2:
> Add "Fixes" tag
> Remove "toggle ulpi" comment
> Extend comment to explain what is happening in detail
> 
>  drivers/usb/dwc3/dwc3-xilinx.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 

In any case,

Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>

Thanks,
Thinh

From robh at kernel.org  Fri Mar 21 14:31:12 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 21 Mar 2025 16:31:12 -0500
Subject: [PATCH v6 1/2] dt-bindings: arm: aspeed: add Meta Ventura board
In-Reply-To: <20250321123731.1373596-2-jason-hsu@quantatw.com>
References: <20250321123731.1373596-1-jason-hsu@quantatw.com>
 <20250321123731.1373596-2-jason-hsu@quantatw.com>
Message-ID: <20250321213112.GA4137938-robh@kernel.org>

On Fri, Mar 21, 2025 at 08:37:30PM +0800, Jason Hsu wrote:
> Document the new compatibles used on Meta Ventura.
> Add subject prefix for the patch.
> 
> Signed-off-by: Jason Hsu <jason-hsu at quantatw.com>

The author and Sob don't match. You need to fix your git author to your 
quantatw.com address.

> ---
>  Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> index 01333ac111fb..a86b411df9a5 100644
> --- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> +++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
> @@ -87,6 +87,7 @@ properties:
>                - facebook,greatlakes-bmc
>                - facebook,harma-bmc
>                - facebook,minerva-cmc
> +              - facebook,ventura-rmc
>                - facebook,yosemite4-bmc
>                - ibm,blueridge-bmc
>                - ibm,everest-bmc
> --
> 2.34.1
> 


From robh at kernel.org  Fri Mar 21 14:35:22 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 21 Mar 2025 16:35:22 -0500
Subject: [PATCH v6 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250321143308.4008623-2-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
 <20250321143308.4008623-2-florin.leotescu@oss.nxp.com>
Message-ID: <20250321213522.GA4149883-robh@kernel.org>

On Fri, Mar 21, 2025 at 04:33:06PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../bindings/hwmon/microchip,emc2305.yaml     | 110 ++++++++++++++++++
>  1 file changed, 110 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> new file mode 100644
> index 000000000000..79081c116274
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> @@ -0,0 +1,110 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/hwmon/microchip,emc2305.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip EMC2305 SMBus compliant PWM fan controller
> +
> +maintainers:
> +  - Michael Shych <michaelsh at nvidia.com>
> +
> +description:
> +  Microchip EMC2301/2/3/5 pwm controller which supports
> +  up to five programmable fan control circuits.

Fix wrapping to wrap at 80.

> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - enum:
> +          - microchip,emc2305
> +      - items:
> +          - enum:
> +              - microchip,emc2303
> +              - microchip,emc2302
> +              - microchip,emc2301
> +          - const: microchip,emc2305
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  '#pwm-cells':
> +    const: 3
> +    description: |
> +      Number of cells in a PWM specifier.
> +      - cell 0: The PWM frequency
> +      - cell 1: The PWM polarity: 0 or PWM_POLARITY_INVERTED
> +      - cell 2: The PWM output config:
> +           - 0 (Open-Drain)
> +           - 1 (Push-Pull)
> +
> +patternProperties:
> +  '^fan@[0-4]$':
> +    $ref: fan-common.yaml#
> +    unevaluatedProperties: false
> +    properties:
> +      reg:
> +        description:
> +          The fan number used to determine the associated PWM channel.

           maxItems: 1

With that,

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>


From robh at kernel.org  Fri Mar 21 14:40:00 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 21 Mar 2025 16:40:00 -0500
Subject: [PATCH v2 1/9] dt-bindings: reset: imx95-gpu-blk-ctrl: Document
 Freescale i.MX95 GPU reset
In-Reply-To: <20250321200625.132494-2-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-2-marex@denx.de>
Message-ID: <174259137507.3955133.798395163716870826.robh@kernel.org>


On Fri, 21 Mar 2025 21:05:51 +0100, Marek Vasut wrote:
> The instance of the GPU populated in Freescale i.MX95 does require
> release from reset by writing into a single GPUMIX block controller
> GPURESET register bit 0. Document support for this reset register.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: David Airlie <airlied at gmail.com>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Liviu Dudau <liviu.dudau at arm.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Maxime Ripard <mripard at kernel.org>
> Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
> Cc: Philipp Zabel <p.zabel at pengutronix.de>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Sebastian Reichel <sre at kernel.org>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Simona Vetter <simona at ffwll.ch>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Thomas Zimmermann <tzimmermann at suse.de>
> Cc: devicetree at vger.kernel.org
> Cc: dri-devel at lists.freedesktop.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> V2: - Fix dt_binding_check errors in example, temporarily use fixed
>       numbers to refer to IMX95_CLK_GPUAPB clock and IMX95_PD_GPU
>       power-domain
>     - Drop trailing pipe after description:
>     - Drop leading dash before const in compatible:
>     - Switch from fsl, to nxp, vendor prefix
> ---
>  .../reset/nxp,imx95-gpu-blk-ctrl.yaml         | 49 +++++++++++++++++++
>  1 file changed, 49 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/nxp,imx95-gpu-blk-ctrl.yaml
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Fri Mar 21 14:50:50 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Fri, 21 Mar 2025 16:50:50 -0500
Subject: [PATCH 1/3] dt-bindings: memory: mediatek: Add mt8196 support
In-Reply-To: <20250320073625.25225-2-xueqi.zhang@mediatek.com>
References: <20250320073625.25225-1-xueqi.zhang@mediatek.com>
 <20250320073625.25225-2-xueqi.zhang@mediatek.com>
Message-ID: <174259384769.4178048.13773796481091254405.robh@kernel.org>


On Thu, 20 Mar 2025 15:36:16 +0800, Xueqi Zhang wrote:
> Add mt8196 smi support in the bindings.
> Since mt8196 has more than 32 SMI larbs, update 'mediatek,larb-id'
> maximum to 63.
> 
> Signed-off-by: Xueqi Zhang <xueqi.zhang at mediatek.com>
> ---
>  .../mediatek,smi-common.yaml                  |   4 +-
>  .../memory-controllers/mediatek,smi-larb.yaml |   4 +-
>  .../dt-bindings/memory/mt8196-memory-port.h   | 460 ++++++++++++++++++
>  include/dt-bindings/memory/mtk-memory-port.h  |   4 +-
>  4 files changed, 468 insertions(+), 4 deletions(-)
>  create mode 100644 include/dt-bindings/memory/mt8196-memory-port.h
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From conor at kernel.org  Fri Mar 21 15:32:15 2025
From: conor at kernel.org (Conor Dooley)
Date: Fri, 21 Mar 2025 22:32:15 +0000
Subject: [RFC PATCH 0/6] Cache coherency management subsystem
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
Message-ID: <20250321-failing-squatted-37a88909bde2@spud>

On Thu, Mar 20, 2025 at 05:41:12PM +0000, Jonathan Cameron wrote:
> Note that I've only a vague idea of who will care about this
> so please do +CC others as needed.
> 
> On x86 there is the much loved WBINVD instruction that causes a write back
> and invalidate of all caches in the system. It is expensive but it is
> necessary in a few corner cases. These are cases where the contents of
> Physical Memory may change without any writes from the host. Whilst there
> are a few reasons this might happen, the one I care about here is when
> we are adding or removing mappings on CXL. So typically going from
> there being actual memory at a host Physical Address to nothing there
> (reads as zero, writes dropped) or visa-versa. That involves the
> reprogramming of address decoders (HDM Decoders); in the near future
> it may also include the device offering dynamic capacity extents. The
> thing that makes it very hard to handle with CPU flushes is that the
> instructions are normally VA based and not guaranteed to reach beyond
> the Point of Coherence or similar. You might be able to (ab)use
> various flush operations intended to ensure persistence memory but
> in general they don't work either.
> 
> So on other architectures such as ARM64 we have no instruction similar to
> WBINVD but we may have device interfaces in the system that provide a way
> to ensure a PA range undergoes the write back and invalidate action. This
> RFC is to find a way to support those cache maintenance device interfaces.
> The ones I know about are much more flexible than WBINVD, allowing
> invalidation of particular PA ranges, or a much richer set of flush types
> (not supported yet as not needed for upstream use cases).
> 
> To illustrate how a solution might work, I've taken both a HiSilicon
> design (slight quirk as registers overlap with existing PMU driver)
> and more controversially a firmware interface proposal from ARM
> (wrapped up in made up ACPI) that was dropped from the released spec
> but for which the alpha spec is still available.
> 
> Why drivers/cache?
> - Mainly because it exists and smells like a reasonable place.
> - Conor, you are maintainer for this currently do you mind us putting this
>   stuff in there?

drivers/cache was just something to put the cache controller drivers we
have on RISC-V that implement the various arch_dma*() callbacks in
non-standard ways that made more sense than drivers/soc/<soc vendor>
since the controllers are IP provided by CPU vendors. There's only
two drivers here now, but I am aware of another two non-standard CMO
mechanisms if the silicon with them so there'll likely be more in the
future :) I'm only really maintainer of it to avoid it being another
thing for Palmer to look after :)

I've only skimmed this for now, but I think it is reasonable to put them
here. Maybe my skim is showing, but it would not surprise me to see a
driver providing both non-standard arch_dma*() callbacks as well as
dealing with CXL mappings via this new class on RISC-V in the future..
Either way, I think it'd probably be a good idea to add ?you? as a
co-maintainer if the directory is going to be used for your proposed
interface/drivers, for what I hope is an obvious reason!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250321/ed825755/attachment.sig>

From robh at kernel.org  Fri Mar 21 15:37:34 2025
From: robh at kernel.org (Rob Herring)
Date: Fri, 21 Mar 2025 17:37:34 -0500
Subject: [PATCH v2 03/11] dt-bindings: clock: en7523: add Documentation
 for Airoha AN7581 SCU SSR
In-Reply-To: <20250320130054.4804-4-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
 <20250320130054.4804-4-ansuelsmth@gmail.com>
Message-ID: <20250321223734.GA6837-robh@kernel.org>

On Thu, Mar 20, 2025 at 02:00:26PM +0100, Christian Marangi wrote:
> The Airoha AN7581 SoC have in the SCU register space particular
> address that control how some peripheral are configured.
> 
> These are toggeled in the System Status Register and are used to
> toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> or setup port for PCIe mode or Ethrnet mode (HSGMII/USXGMII).
> 
> Modes are mutually exclusive and selecting one mode cause the
> other feature to not work (example a mode in USB 3.0 cause PCIe
> port 2 to not work) This depends also on what is physically
> connected to the Hardware and needs to correctly reflect the
> System Status Register bits.
> 
> Special care is needed for PCIe port 0 in 2 line mode that
> requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> mode.
> 
> Expose these configuration as an enum of strings in the SCU node and
> also add dt-bindings header to reference each serdes port in DT.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/clock/airoha,en7523-scu.yaml     | 101 ++++++++++++++++--
>  MAINTAINERS                                   |   7 ++
>  include/dt-bindings/soc/airoha,scu-ssr.h      |  11 ++
>  3 files changed, 110 insertions(+), 9 deletions(-)
>  create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
> index fe2c5c1baf43..637ce0e06619 100644
> --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
> +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
> @@ -9,6 +9,7 @@ title: EN7523 Clock
>  maintainers:
>    - Felix Fietkau <nbd at nbd.name>
>    - John Crispin <nbd at nbd.name>
> +  - Christian Marangi <ansuelsmth at gmail.com>
>  
>  description: |
>    This node defines the System Control Unit of the EN7523 SoC,
> @@ -26,6 +27,23 @@ description: |
>  
>    The clocks are provided inside a system controller node.
>  
> +  The System Control Unit may also set different mode for the Serdes ports
> +  present on the SoC.
> +
> +  These are toggeled in the System Status Register and are used to
> +  toggle Serdes port for USB 3.0 mode or HSGMII, USB 3.0 mode or PCIe2
> +  or setup port for PCIe mode or Ethernet mode (HSGMII/USXGMII).
> +
> +  Modes are mutually exclusive and selecting one mode cause the
> +  other feature to not work (example a mode in USB 3.0 cause PCIe
> +  port 2 to not work) This depends also on what is physically
> +  connected to the Hardware and needs to correctly reflect the
> +  System Status Register bits.
> +
> +  Special care is needed for PCIe port 0 in 2 line mode that
> +  requires both WiFi1 and WiFi2 Serdes port set to PCIe0 2 Line
> +  mode.
> +
>  properties:
>    compatible:
>      items:
> @@ -49,6 +67,40 @@ properties:
>      description: ID of the controller reset line
>      const: 1
>  
> +  airoha,serdes-wifi1:
> +    description: Configure the WiFi1 Serdes port
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum:
> +      - pcie0_x2
> +      - pcie0_x1
> +      - ethernet
> +    default: pcie0_x1
> +
> +  airoha,serdes-wifi2:
> +    description: Configure the WiFi2 Serdes port
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum:
> +      - pcie0_x2
> +      - pcie1_x1
> +      - ethernet
> +    default: pcie1_x1
> +
> +  airoha,serdes-usb1:
> +    description: Configure the USB1 Serdes port
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum:
> +      - usb3
> +      - ethernet
> +    default: usb3
> +
> +  airoha,serdes-usb2:
> +    description: Configure the USB2 Serdes port
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum:
> +      - usb3
> +      - pcie2_x1
> +    default: usb3

Couldn't you make this a phy provider and use the mode flags in the 
phy cells?

> +
>  required:
>    - compatible
>    - reg
> @@ -64,6 +116,12 @@ allOf:
>          reg:
>            minItems: 2
>  
> +        airoha,serdes-wifi1: false
> +        airoha,serdes-wifi2: false
> +
> +        airoha,serdes-usb1: false
> +        airoha,serdes-usb2: false
> +
>          '#reset-cells': false
>  
>    - if:
> @@ -75,6 +133,24 @@ allOf:
>          reg:
>            maxItems: 1
>  
> +  - if:
> +      properties:
> +        airoha,serdes-wifi1:
> +          const: pcie0_x2

This is also true if airoha,serdes-wifi1 is not present. Probably not 
what you intended.

> +    then:
> +      properties:
> +        airoha,serdes-wifi2:
> +          const: pcie0_x2
> +
> +  - if:
> +      properties:
> +        airoha,serdes-wifi2:
> +          const: pcie0_x2
> +    then:
> +      properties:
> +        airoha,serdes-wifi1:
> +          const: pcie0_x2
> +
>  additionalProperties: false


From jeremy.linton at arm.com  Fri Mar 21 16:43:23 2025
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Fri, 21 Mar 2025 18:43:23 -0500
Subject: [PATCH 3/7] arm64: uaccess: Add additional userspace GCS
 accessors
In-Reply-To: <50a0920d-3e3d-4e96-b68a-a7a0d78c3695@sirena.org.uk>
References: <20250318204841.373116-1-jeremy.linton@arm.com>
 <20250318204841.373116-4-jeremy.linton@arm.com>
 <50a0920d-3e3d-4e96-b68a-a7a0d78c3695@sirena.org.uk>
Message-ID: <e8ada81d-0e10-412b-8792-035bc63113a6@arm.com>

Hi,

On 3/19/25 8:24 AM, Mark Brown wrote:
> On Tue, Mar 18, 2025 at 03:48:37PM -0500, Jeremy Linton wrote:
> 
>> +static inline u64 load_user_gcs(unsigned long __user *addr, int *err)
>> +{
>> +	unsigned long ret;
>> +	u64 load;
>> +
>> +	if (!access_ok((char __user *)addr, sizeof(load))) {
>> +		*err = -EFAULT;
>> +		return 0;
>> +	}
>> +
>> +	gcsb_dsync();
>> +	ret = copy_from_user(&load, addr, sizeof(load));
>> +	if (ret != 0)
>> +		*err = ret;
>> +	return load;
>> +}
> 
> A GCS load done by the hardware will verify that we are loading from GCS
> memory (the accesses are marked as AccessType_GCS in the pseudocode
> which is then validated in for example S1CheckPermissions()).  Sadly
> there's no equivalent of GCSSTR so we'd need to do the permission check
> ourselves to match this behaviour.

Right, except that if I grab the VMA as a placeholder for the page, 
check to see if its a VM_SHADOW_STACK under any of 
map_read_lock()/lock_vma_under_rcu()/etc and then perform the access, 
the resulting possible fault will have problems with vma locking. 
Otherwise there ends up being a few different races that at the moment 
I've not yet figured out how to fix without making a big mess. For 
example, we can reduce that possible window, by reading the 
value/locking and checking shadow stack state/dropping the 
lock/rereading the value, or some other construct but it seems pointless 
because the suggested problem is that we might be creating a way to 
bypass some of the shadow stack security. In which case, leaving a 
little race is likely the same as leaving it wide open.


Otherwise, maybe we can ignore the problem, or just refuse to allow 
probes on 'RET' instructions which seems to be the main problematic 
case. Although, given we don't really know if GCS is enabled until the 
probe is hit, SIGSEG'ing the target process is a big hammer.

Ignoring it might be a valid option. I guess it could to be one of those 
"if the user puts a uprobe on a RET some of the shadow stack security is 
reduced" footguns. If an attacker can also manipulate the address space 
in a way to exploit it then its probably game over anyway. Ideally, the 
kernel would warn on this, but per the conversation around patch 6/7 
that seems to be off the table.














From linux at roeck-us.net  Fri Mar 21 17:00:31 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 21 Mar 2025 17:00:31 -0700
Subject: [PATCH v6 1/3] dt-bindings: hwmon: Add Microchip emc2305 support
In-Reply-To: <20250321143308.4008623-2-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
 <20250321143308.4008623-2-florin.leotescu@oss.nxp.com>
Message-ID: <cf20e703-5770-4bfa-bb5a-a1f5f03f56c0@roeck-us.net>

On Fri, Mar 21, 2025 at 04:33:06PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce yaml schema for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Reviewed-by: Rob Herring (Arm) <robh at kernel.org>

Applied, after making the changes requested by Rob.

Thanks,
Guenter


From linux at roeck-us.net  Fri Mar 21 17:07:16 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 21 Mar 2025 17:07:16 -0700
Subject: [PATCH v6 2/3] hwmon: emc2305: Add OF support
In-Reply-To: <20250321143308.4008623-3-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
 <20250321143308.4008623-3-florin.leotescu@oss.nxp.com>
Message-ID: <b1dcabc3-0bc8-402d-9b28-8bb561d489d2@roeck-us.net>

On Fri, Mar 21, 2025 at 04:33:07PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Introduce OF support for Microchip emc2305 pwm fan controller.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>

Applied.

Thanks,
Guenter


From linux at roeck-us.net  Fri Mar 21 17:07:57 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 21 Mar 2025 17:07:57 -0700
Subject: [PATCH v6 3/3] hwmon: emc2305: Use
 devm_thermal_of_cooling_device_register
In-Reply-To: <20250321143308.4008623-4-florin.leotescu@oss.nxp.com>
References: <20250321143308.4008623-1-florin.leotescu@oss.nxp.com>
 <20250321143308.4008623-4-florin.leotescu@oss.nxp.com>
Message-ID: <f9982a05-5104-426d-b9ac-de4b5c4d465e@roeck-us.net>

On Fri, Mar 21, 2025 at 04:33:08PM +0200, florin.leotescu at oss.nxp.com wrote:
> From: Florin Leotescu <florin.leotescu at nxp.com>
> 
> Prepare the emc2305 driver to use configuration from Device Tree nodes.
> Switch to devm_thermal_of_cooling_device_register to simplify the
> cleanup procedure, allowing the removal of emc2305_unset_tz and
> emc2305_remove, which are no longer needed.
> 
> Signed-off-by: Florin Leotescu <florin.leotescu at nxp.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>

Applied.

Thanks,
Guenter


From richard.xnu.clark at gmail.com  Fri Mar 21 20:20:36 2025
From: richard.xnu.clark at gmail.com (richard clark)
Date: Sat, 22 Mar 2025 11:20:36 +0800
Subject: hrtimer precision issue/question??
Message-ID: <CAJNi4rPaPeVWzBve6Toi8hhrxP6GROAGRug7+c3zg1crDeOt7Q@mail.gmail.com>

With diff below under the 'cyclictest -a 0 -t 1 -m -p99' trigger from
the arm64-based linux box, the interval is 1000us and the arch_timer
in the system is: arch_timer: cp15 timer(s) running at 31.25MHz
(phys).  1tick = 32ns for the arch timer, I am not sure if those
durations less than 1000us are expected?

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 11c704bfd4fb..691d1fe6e944 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -2036,14 +2036,25 @@ int nanosleep_copyout(struct restart_block
*restart, struct timespec64 *ts)
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum
hrtimer_mode mode)
 {
        struct restart_block *restart;
+       ktime_t t0, t1;
+       int c0, c1;
+       bool hit = !strncmp(current->comm, "cyclictest", 10);

        do {
+               if (hit) {
+                       c0 = smp_processor_id();
+                       t0 = ktime_get();
+               }
                set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
                hrtimer_sleeper_start_expires(t, mode);

                if (likely(t->task))
                        schedule();
-
+               if (hit) {
+                       t1 = ktime_get();
+                       c1 = smp_processor_id();
+                       pr_info("[%2d-%2d]t0=%lld,t1=%lld,d=%lld
us\n", c0, c1, t0, t1, ktime_to_us(ktime_sub(t1, t0)));
+               }
                hrtimer_cancel(&t->timer);
                mode = HRTIMER_MODE_ABS;

Part of the real output:
[  165.555795] [ 0- 0]t0=165550399226,t1=165551394303,d=995 us
[  165.556802] [ 0- 0]t0=165551398751,t1=165552400997,d=1002 us
[  165.557797] [ 0- 0]t0=165552415141,t1=165553396106,d=980 us
[  165.558794] [ 0- 0]t0=165553402090,t1=165554394160,d=992 us
[  165.559794] [ 0- 0]t0=165554398832,t1=165555393941,d=995 us
[  165.559995] [ 6- 5]t0=165545533151,t1=165555594519,d=10061 us
[  165.560802] [ 0- 0]t0=165555398485,t1=165556400795,d=1002 us
[  165.561796] [ 0- 0]t0=165556415259,t1=165557395457,d=980 us
[  165.562794] [ 0- 0]t0=165557401601,t1=165558394086,d=992 us
[  165.563794] [ 0- 0]t0=165558398694,t1=165559393996,d=995 us
[  165.564802] [ 0- 0]t0=165559398188,t1=165560400785,d=1002 us
[  165.565796] [ 0- 0]t0=165560414673,t1=165561395671,d=980 us
[  165.566794] [ 0- 0]t0=165561402327,t1=165562394108,d=991 us
[  165.567794] [ 0- 0]t0=165562399068,t1=165563393890,d=994 us
[  165.568802] [ 0- 0]t0=165563399362,t1=165564401640,d=1002 us
[  165.569796] [ 0- 0]t0=165564413640,t1=165565395885,d=982 us
[  165.570104] [ 5- 6]t0=165555639767,t1=165565703087,d=10063 us
[  165.570795] [ 0- 0]t0=165565401421,t1=165566394739,d=993 us
[  165.571794] [ 0- 0]t0=165566400531,t1=165567393816,d=993 us
[  165.572799] [ 0- 0]t0=165567399800,t1=165568398270,d=998 us
[  165.573798] [ 0- 0]t0=165568412702,t1=165569398115,d=985 us
[  165.574794] [ 0- 0]t0=165569404451,t1=165570394249,d=989 us
[  165.575794] [ 0- 0]t0=165570399145,t1=165571393838,d=994 us
[  165.576801] [ 0- 0]t0=165571398606,t1=165572400276,d=1001 us
[  165.577796] [ 0- 0]t0=165572414260,t1=165573395417,d=981 us
[  165.578794] [ 0- 0]t0=165573401561,t1=165574394015,d=992 us
[  165.579794] [ 0- 0]t0=165574398975,t1=165575393957,d=994 us
[  165.580208] [ 6- 5]t0=165565749263,t1=165575807879,d=10058 us
[  165.580801] [ 0- 0]t0=165575398405,t1=165576399978,d=1001 us

Thanks


From ot_chhao.chang at mediatek.com  Fri Mar 21 20:22:55 2025
From: ot_chhao.chang at mediatek.com (=?utf-8?B?Q2hoYW8gQ2hhbmcgKOW4uOa1qSk=?=)
Date: Sat, 22 Mar 2025 03:22:55 +0000
Subject: [PATCH v4 0/3] Add EINT support for multiple addresses
In-Reply-To: <CACRpkdYSNMV2jymbHaxRp-PmzbbkEJ_eUcT20whYw3gdhEGOGg@mail.gmail.com>
References: <20250225140732.21557-1-ot_chhao.chang@mediatek.com>
	 <CACRpkdYSNMV2jymbHaxRp-PmzbbkEJ_eUcT20whYw3gdhEGOGg@mail.gmail.com>
Message-ID: <94250d48cbb9750ad9cdfff1ddf9d60c3b70a6f1.camel@mediatek.com>

On Fri, 2025-03-14 at 10:58 +0100, Linus Walleij wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Hi Hao,
> 
> thanks for your patches!
> 
> On Tue, Feb 25, 2025 at 3:07?PM Hao Chang <
> ot_chhao.chang at mediatek.com> wrote:
> 
> > This patch depends on
> > [v3,2/2] pinctrl: mediatek: add mt8196 driver
> > [v3,1/2] dt-bindings: pinctrl: mediatek: add support for mt8196
> > 
> > Please also accept this patch together with [1]
> > to avoid build and dt binding check error.
> > [1]
> > https://urldefense.com/v3/__https://patchwork.kernel.org/project/linux-mediatek/list/?series=&submitter=215008&state=&q=v3&archive=&delegate=__;!!CTRNKA9wMg0ARbw!gUMnwvZLiv7PLfBynupfezUYGOwSWFXcCubh-tJn4vobCnaiSRRXRgakWcQBdoQ8s0VNcBoQUpuFFhlLgtJb-OArDwfJKcQ$
> 
> Since the dependence series is not finished I can't apply these
> patches either, do you want to send an independent version of these
> patches so we merge them *first* since they seem finished?
> 
> Then the mt8196 series can rebase on your patches in v6.15-rc1
> instead.
> 
> Just send a version based on v6.14-rc1 and I will apply it.

Thanks for your suggestion, I will fix this.

> 
> Yours,
> Linus Walleij

From lkp at intel.com  Fri Mar 21 20:43:40 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 11:43:40 +0800
Subject: [arm-platforms:arm64/tlbi-range-hacks 12/17]
 drivers/pci/controller/pcie-apple.c:460:40: error: implicit declaration of
 function 'FIELD_PREP'
Message-ID: <202503221117.9esJe5iq-lkp@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git arm64/tlbi-range-hacks
head:   89a08aa9682594d44c11df1b6e168e38bdb7f0c3
commit: b2817638e680079b58e1bf67c6d9fa1d5f48b636 [12/17] PCI: apple: Add T602x PCIe support
config: csky-allmodconfig (https://download.01.org/0day-ci/archive/20250322/202503221117.9esJe5iq-lkp at intel.com/config)
compiler: csky-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250322/202503221117.9esJe5iq-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503221117.9esJe5iq-lkp at intel.com/

All errors (new ones prefixed by >>):

   drivers/pci/controller/pcie-apple.c: In function 'apple_pcie_port_setup_irq':
>> drivers/pci/controller/pcie-apple.c:460:40: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
     460 |                         writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) |
         |                                        ^~~~~~~~~~


vim +/FIELD_PREP +460 drivers/pci/controller/pcie-apple.c

   423	
   424	static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
   425	{
   426		struct fwnode_handle *fwnode = &port->np->fwnode;
   427		struct apple_pcie *pcie = port->pcie;
   428		unsigned int irq;
   429		u32 val = 0;
   430	
   431		/* FIXME: consider moving each interrupt under each port */
   432		irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)),
   433					   port->idx);
   434		if (!irq)
   435			return -ENXIO;
   436	
   437		port->domain = irq_domain_create_linear(fwnode, 32,
   438							&apple_port_irq_domain_ops,
   439							port);
   440		if (!port->domain)
   441			return -ENOMEM;
   442	
   443		/* Disable all interrupts */
   444		writel_relaxed(~0, port->base + PORT_INTMSK);
   445		writel_relaxed(~0, port->base + PORT_INTSTAT);
   446		writel_relaxed(~0, port->base + PORT_LINKCMDSTS);
   447	
   448		irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port);
   449	
   450		/* Configure MSI base address */
   451		BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR));
   452		writel_relaxed(lower_32_bits(DOORBELL_ADDR),
   453			       port->base + pcie->hw->port_msiaddr);
   454		if (pcie->hw->port_msiaddr_hi)
   455			writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi);
   456	
   457		/* Enable MSIs, shared between all ports */
   458		if (pcie->hw->port_msimap) {
   459			for (int i = 0; i < pcie->nvecs; i++)
 > 460				writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) |
   461					       PORT_MSIMAP_ENABLE,
   462					       port->base + pcie->hw->port_msimap + 4 * i);
   463		} else {
   464			writel_relaxed(0, port->base + PORT_MSIBASE);
   465			val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT;
   466		}
   467	
   468		writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG);
   469		return 0;
   470	}
   471	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From justin.he at arm.com  Fri Mar 21 20:51:15 2025
From: justin.he at arm.com (Jia He)
Date: Sat, 22 Mar 2025 03:51:15 +0000
Subject: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when KVM is not initialised
Message-ID: <20250322035115.118048-1-justin.he@arm.com>

Currently, `kvm_host_pmu_init()` does not check if KVM has been
successfully initialized before proceeding. This can lead to unintended
behavior if the function is called in an environment where KVM is not
available, e.g., kernel is landed in EL1.

Signed-off-by: Jia He <justin.he at arm.com>
---
 arch/arm64/kvm/pmu.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
index 7169c1a24dd6..e39c48d12b81 100644
--- a/arch/arm64/kvm/pmu.c
+++ b/arch/arm64/kvm/pmu.c
@@ -227,6 +227,13 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
 {
 	struct arm_pmu_entry *entry;
 
+	/*
+	 * Prevent unintended behavior where KVM is not available or not
+	 * successfully initialised, e.g., kernel is landed in EL1.
+	 */
+	if (!is_kvm_arm_initialised())
+		return;
+
 	/*
 	 * Check the sanitised PMU version for the system, as KVM does not
 	 * support implementations where PMUv3 exists on a subset of CPUs.
-- 
2.34.1



From ot_chhao.chang at mediatek.com  Fri Mar 21 20:52:27 2025
From: ot_chhao.chang at mediatek.com (Hao Chang)
Date: Sat, 22 Mar 2025 11:52:27 +0800
Subject: [PATCH v5 0/1] Add EINT support for multiple addresses
Message-ID: <20250322035307.4811-1-ot_chhao.chang@mediatek.com>

v5 changes:
1)Upload common code and remove irrelevant ones
2)Add pin list to find eint number

v4 changes:
1)Add err statement for exception handling
2)Add check for invalid pins
3)Use defined eint pins

v3 changes:
1)Add error judgment

v2 changes:
1)Remove instance structure
2)Modify the way to obtain eint address

Hao Chang (1):
  pinctrl: mediatek: Add EINT support for multiple addresses

 drivers/pinctrl/mediatek/mtk-eint.c           | 313 +++++++++++-------
 drivers/pinctrl/mediatek/mtk-eint.h           |  23 +-
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  |  37 ++-
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.h  |   1 +
 drivers/pinctrl/mediatek/pinctrl-paris.h      |   7 +
 5 files changed, 254 insertions(+), 127 deletions(-)

-- 
2.46.0



From ot_chhao.chang at mediatek.com  Fri Mar 21 20:52:28 2025
From: ot_chhao.chang at mediatek.com (Hao Chang)
Date: Sat, 22 Mar 2025 11:52:28 +0800
Subject: [PATCH v5 1/1] pinctrl: mediatek: Add EINT support for multiple addresses
In-Reply-To: <20250322035307.4811-1-ot_chhao.chang@mediatek.com>
References: <20250322035307.4811-1-ot_chhao.chang@mediatek.com>
Message-ID: <20250322035307.4811-2-ot_chhao.chang@mediatek.com>

For flexible routing, eint will be divided into 5 bases,
and it will obtain the operation address through the pins array.

Signed-off-by: Hao Chang <ot_chhao.chang at mediatek.com>
Signed-off-by: Qingliang Li <qingliang.li at mediatek.com>
---
 drivers/pinctrl/mediatek/mtk-eint.c           | 313 +++++++++++-------
 drivers/pinctrl/mediatek/mtk-eint.h           |  23 +-
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  |  37 ++-
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.h  |   1 +
 drivers/pinctrl/mediatek/pinctrl-paris.h      |   7 +
 5 files changed, 254 insertions(+), 127 deletions(-)

diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index 27f0a54e12bf..ced4ee509b5b 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -1,11 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2014-2018 MediaTek Inc.
+// Copyright (c) 2014-2025 MediaTek Inc.
 
 /*
  * Library for MediaTek External Interrupt Support
  *
  * Author: Maoguang Meng <maoguang.meng at mediatek.com>
  *	   Sean Wang <sean.wang at mediatek.com>
+ *	   Hao Chang <ot_chhao.chang at mediatek.com>
+ *	   Qingliang Li <qingliang.li at mediatek.com>
  *
  */
 
@@ -20,6 +22,7 @@
 #include <linux/platform_device.h>
 
 #include "mtk-eint.h"
+#include "pinctrl-mtk-common-v2.h"
 
 #define MTK_EINT_EDGE_SENSITIVE           0
 #define MTK_EINT_LEVEL_SENSITIVE          1
@@ -68,13 +71,11 @@ static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
 					 unsigned int eint_num,
 					 unsigned int offset)
 {
-	unsigned int eint_base = 0;
+	unsigned int idx = eint->pins[eint_num].index;
+	unsigned int inst = eint->pins[eint_num].instance;
 	void __iomem *reg;
 
-	if (eint_num >= eint->hw->ap_num)
-		eint_base = eint->hw->ap_num;
-
-	reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
+	reg = eint->base[inst] + offset + (idx / 32 * 4);
 
 	return reg;
 }
@@ -83,7 +84,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
 					     unsigned int eint_num)
 {
 	unsigned int sens;
-	unsigned int bit = BIT(eint_num % 32);
+	unsigned int bit = BIT(eint->pins[eint_num].index % 32);
 	void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
 						eint->regs->sens);
 
@@ -92,7 +93,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
 	else
 		sens = MTK_EINT_EDGE_SENSITIVE;
 
-	if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
+	if (eint->pins[eint_num].debounce && sens != MTK_EINT_EDGE_SENSITIVE)
 		return 1;
 	else
 		return 0;
@@ -102,9 +103,9 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
 {
 	int start_level, curr_level;
 	unsigned int reg_offset;
-	u32 mask = BIT(hwirq & 0x1f);
-	u32 port = (hwirq >> 5) & eint->hw->port_mask;
-	void __iomem *reg = eint->base + (port << 2);
+	unsigned int mask = BIT(eint->pins[hwirq].index & 0x1f);
+	unsigned int port = (eint->pins[hwirq].index >> 5) & eint->hw->port_mask;
+	void __iomem *reg = eint->base[eint->pins[hwirq].instance] + (port << 2);
 
 	curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
 
@@ -126,11 +127,13 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
 static void mtk_eint_mask(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
+	unsigned int idx = eint->pins[d->hwirq].index;
+	unsigned int inst = eint->pins[d->hwirq].instance;
+	unsigned int mask = BIT(idx & 0x1f);
 	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
 						eint->regs->mask_set);
 
-	eint->cur_mask[d->hwirq >> 5] &= ~mask;
+	eint->cur_mask[inst][idx >> 5] &= ~mask;
 
 	writel(mask, reg);
 }
@@ -138,22 +141,24 @@ static void mtk_eint_mask(struct irq_data *d)
 static void mtk_eint_unmask(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
+	unsigned int idx = eint->pins[d->hwirq].index;
+	unsigned int inst = eint->pins[d->hwirq].instance;
+	unsigned int mask = BIT(idx & 0x1f);
 	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
 						eint->regs->mask_clr);
 
-	eint->cur_mask[d->hwirq >> 5] |= mask;
+	eint->cur_mask[inst][idx >> 5] |= mask;
 
 	writel(mask, reg);
 
-	if (eint->dual_edge[d->hwirq])
+	if (eint->pins[d->hwirq].dual_edge)
 		mtk_eint_flip_edge(eint, d->hwirq);
 }
 
 static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
 				      unsigned int eint_num)
 {
-	unsigned int bit = BIT(eint_num % 32);
+	unsigned int bit = BIT(eint->pins[eint_num].index % 32);
 	void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
 						eint->regs->mask);
 
@@ -163,7 +168,7 @@ static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
 static void mtk_eint_ack(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
+	unsigned int mask = BIT(eint->pins[d->hwirq].index & 0x1f);
 	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
 						eint->regs->ack);
 
@@ -174,7 +179,7 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
 	bool masked;
-	u32 mask = BIT(d->hwirq & 0x1f);
+	unsigned int mask = BIT(eint->pins[d->hwirq].index & 0x1f);
 	void __iomem *reg;
 
 	if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
@@ -186,9 +191,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 	}
 
 	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		eint->dual_edge[d->hwirq] = 1;
+		eint->pins[d->hwirq].dual_edge = 1;
 	else
-		eint->dual_edge[d->hwirq] = 0;
+		eint->pins[d->hwirq].dual_edge = 0;
 
 	if (!mtk_eint_get_mask(eint, d->hwirq)) {
 		mtk_eint_mask(d);
@@ -223,27 +228,32 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	int shift = d->hwirq & 0x1f;
-	int reg = d->hwirq >> 5;
+	unsigned int idx = eint->pins[d->hwirq].index;
+	unsigned int inst = eint->pins[d->hwirq].instance;
+	unsigned int shift = idx & 0x1f;
+	unsigned int port = idx >> 5;
 
 	if (on)
-		eint->wake_mask[reg] |= BIT(shift);
+		eint->wake_mask[inst][port] |= BIT(shift);
 	else
-		eint->wake_mask[reg] &= ~BIT(shift);
+		eint->wake_mask[inst][port] &= ~BIT(shift);
 
 	return 0;
 }
 
 static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
-				     void __iomem *base, u32 *buf)
+				     void __iomem *base, unsigned int **buf)
 {
-	int port;
+	int inst, port, port_num;
 	void __iomem *reg;
 
-	for (port = 0; port < eint->hw->ports; port++) {
-		reg = base + (port << 2);
-		writel_relaxed(~buf[port], reg + eint->regs->mask_set);
-		writel_relaxed(buf[port], reg + eint->regs->mask_clr);
+	for (inst = 0; inst < eint->nbase; inst++) {
+		port_num = DIV_ROUND_UP(eint->base_pin_num[inst], 32);
+		for (port = 0; port < port_num; port++) {
+			reg = eint->base[inst] + (port << 2);
+			writel_relaxed(~buf[inst][port], reg + eint->regs->mask_set);
+			writel_relaxed(buf[inst][port], reg + eint->regs->mask_clr);
+		}
 	}
 }
 
@@ -303,15 +313,18 @@ static struct irq_chip mtk_eint_irq_chip = {
 
 static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
 {
-	void __iomem *dom_en = eint->base + eint->regs->dom_en;
-	void __iomem *mask_set = eint->base + eint->regs->mask_set;
-	unsigned int i;
-
-	for (i = 0; i < eint->hw->ap_num; i += 32) {
-		writel(0xffffffff, dom_en);
-		writel(0xffffffff, mask_set);
-		dom_en += 4;
-		mask_set += 4;
+	void __iomem *dom_reg, *mask_reg;
+	unsigned int i, j;
+
+	for (i = 0; i < eint->nbase; i++) {
+		dom_reg = eint->base[i] + eint->regs->dom_en;
+		mask_reg = eint->base[i] + eint->regs->mask_set;
+		for (j = 0; j < eint->base_pin_num[i]; j += 32) {
+			writel(0xffffffff, dom_reg);
+			writel(0xffffffff, mask_reg);
+			dom_reg += 4;
+			mask_reg += 4;
+		}
 	}
 
 	return 0;
@@ -322,14 +335,16 @@ mtk_eint_debounce_process(struct mtk_eint *eint, int index)
 {
 	unsigned int rst, ctrl_offset;
 	unsigned int bit, dbnc;
+	unsigned int inst = eint->pins[index].instance;
+	unsigned int idx = eint->pins[index].index;
 
-	ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
-	dbnc = readl(eint->base + ctrl_offset);
-	bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
+	ctrl_offset = (idx / 4) * 4 + eint->regs->dbnc_ctrl;
+	dbnc = readl(eint->base[inst] + ctrl_offset);
+	bit = MTK_EINT_DBNC_SET_EN << ((idx % 4) * 8);
 	if ((bit & dbnc) > 0) {
-		ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
-		rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
-		writel(rst, eint->base + ctrl_offset);
+		ctrl_offset = (idx / 4) * 4 + eint->regs->dbnc_set;
+		rst = MTK_EINT_DBNC_RST_BIT << ((idx % 4) * 8);
+		writel(rst, eint->base[inst] + ctrl_offset);
 	}
 }
 
@@ -337,65 +352,68 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct mtk_eint *eint = irq_desc_get_handler_data(desc);
-	unsigned int status, eint_num;
-	int offset, mask_offset, index;
-	void __iomem *reg =  mtk_eint_get_offset(eint, 0, eint->regs->stat);
+	unsigned int i, j, port, status, shift, mask, eint_num;
+	void __iomem *reg;
 	int dual_edge, start_level, curr_level;
 
 	chained_irq_enter(chip, desc);
-	for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
-	     reg += 4) {
-		status = readl(reg);
-		while (status) {
-			offset = __ffs(status);
-			mask_offset = eint_num >> 5;
-			index = eint_num + offset;
-			status &= ~BIT(offset);
-
-			/*
-			 * If we get an interrupt on pin that was only required
-			 * for wake (but no real interrupt requested), mask the
-			 * interrupt (as would mtk_eint_resume do anyway later
-			 * in the resume sequence).
-			 */
-			if (eint->wake_mask[mask_offset] & BIT(offset) &&
-			    !(eint->cur_mask[mask_offset] & BIT(offset))) {
-				writel_relaxed(BIT(offset), reg -
-					eint->regs->stat +
-					eint->regs->mask_set);
-			}
-
-			dual_edge = eint->dual_edge[index];
-			if (dual_edge) {
-				/*
-				 * Clear soft-irq in case we raised it last
-				 * time.
-				 */
-				writel(BIT(offset), reg - eint->regs->stat +
-				       eint->regs->soft_clr);
-
-				start_level =
-				eint->gpio_xlate->get_gpio_state(eint->pctl,
-								 index);
-			}
-
-			generic_handle_domain_irq(eint->domain, index);
-
-			if (dual_edge) {
-				curr_level = mtk_eint_flip_edge(eint, index);
+	for (i = 0; i < eint->nbase; i++) {
+		for (j = 0; j < eint->base_pin_num[i]; j += 32) {
+			port = j >> 5;
+			status = readl(eint->base[i] + port * 4 + eint->regs->stat);
+			while (status) {
+				shift = __ffs(status);
+				status &= ~BIT(shift);
+				mask = BIT(shift);
+				eint_num = eint->pin_list[i][shift + j];
 
 				/*
-				 * If level changed, we might lost one edge
-				 * interrupt, raised it through soft-irq.
+				 * If we get an interrupt on pin that was only required
+				 * for wake (but no real interrupt requested), mask the
+				 * interrupt (as would mtk_eint_resume do anyway later
+				 * in the resume sequence).
 				 */
-				if (start_level != curr_level)
-					writel(BIT(offset), reg -
-					       eint->regs->stat +
-					       eint->regs->soft_set);
+				if (eint->wake_mask[i][port] & mask &&
+				    !(eint->cur_mask[i][port] & mask)) {
+					reg = mtk_eint_get_offset(eint, eint_num,
+								  eint->regs->mask_set);
+					writel_relaxed(mask, reg);
+				}
+
+				dual_edge = eint->pins[eint_num].dual_edge;
+				if (dual_edge) {
+					/*
+					 * Clear soft-irq in case we raised it last
+					 * time.
+					 */
+					reg = mtk_eint_get_offset(eint, eint_num,
+								  eint->regs->soft_clr);
+					writel(mask, reg);
+
+					start_level =
+					eint->gpio_xlate->get_gpio_state(eint->pctl,
+									 eint_num);
+				}
+
+				generic_handle_domain_irq(eint->domain, eint_num);
+
+				if (dual_edge) {
+					curr_level = mtk_eint_flip_edge(eint, eint_num);
+
+					/*
+					 * If level changed, we might lost one edge
+					 * interrupt, raised it through soft-irq.
+					 */
+					if (start_level != curr_level) {
+						reg = mtk_eint_get_offset(eint, eint_num,
+									  eint->regs->soft_set);
+						writel(mask, reg);
+					}
+				}
+
+				if (eint->pins[eint_num].debounce)
+					mtk_eint_debounce_process(eint, eint_num);
 			}
-
-			if (index < eint->hw->db_cnt)
-				mtk_eint_debounce_process(eint, index);
 		}
 	}
 	chained_irq_exit(chip, desc);
@@ -423,6 +441,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 	int virq, eint_offset;
 	unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
 		     dbnc;
+	unsigned int inst = eint->pins[eint_num].instance;
+	unsigned int idx = eint->pins[eint_num].index;
 	struct irq_data *d;
 
 	if (!eint->hw->db_time)
@@ -432,8 +452,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 	eint_offset = (eint_num % 4) * 8;
 	d = irq_get_irq_data(virq);
 
-	set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
-	clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
+	set_offset = (idx / 4) * 4 + eint->regs->dbnc_set;
+	clr_offset = (idx / 4) * 4 + eint->regs->dbnc_clr;
 
 	if (!mtk_eint_can_en_debounce(eint, eint_num))
 		return -EINVAL;
@@ -454,12 +474,12 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 	}
 
 	clr_bit = 0xff << eint_offset;
-	writel(clr_bit, eint->base + clr_offset);
+	writel(clr_bit, eint->base[inst] + clr_offset);
 
 	bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
 		eint_offset;
 	rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
-	writel(rst | bit, eint->base + set_offset);
+	writel(rst | bit, eint->base[inst] + set_offset);
 
 	/*
 	 * Delay a while (more than 2T) to wait for hw debounce counter reset
@@ -487,32 +507,69 @@ EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
 
 int mtk_eint_do_init(struct mtk_eint *eint)
 {
-	int i;
+	unsigned int size, i, port, inst = 0;
+	struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;
 
 	/* If clients don't assign a specific regs, let's use generic one */
 	if (!eint->regs)
 		eint->regs = &mtk_generic_eint_regs;
 
-	eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
-				       sizeof(*eint->wake_mask), GFP_KERNEL);
-	if (!eint->wake_mask)
+	eint->base_pin_num = devm_kmalloc_array(eint->dev, eint->nbase, sizeof(u16),
+						GFP_KERNEL | __GFP_ZERO);
+	if (!eint->base_pin_num)
 		return -ENOMEM;
 
-	eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
-				      sizeof(*eint->cur_mask), GFP_KERNEL);
-	if (!eint->cur_mask)
-		return -ENOMEM;
+	if (eint->nbase == 1) {
+		size = eint->hw->ap_num * sizeof(struct mtk_eint_pin);
+		eint->pins = devm_kmalloc(eint->dev, size, GFP_KERNEL);
+		if (!eint->pins)
+			goto err_pins;
+
+		eint->base_pin_num[inst] = eint->hw->ap_num;
+		for (i = 0; i < eint->hw->ap_num; i++) {
+			eint->pins[i].instance = inst;
+			eint->pins[i].index = i;
+			eint->pins[i].debounce = (i < eint->hw->db_cnt) ? 1 : 0;
+		}
+	}
 
-	eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
-				       sizeof(int), GFP_KERNEL);
-	if (!eint->dual_edge)
-		return -ENOMEM;
+	if (hw && hw->soc && hw->soc->eint_pin) {
+		eint->pins = hw->soc->eint_pin;
+		for (i = 0; i < eint->hw->ap_num; i++) {
+			inst = eint->pins[i].instance;
+			if (inst >= eint->nbase)
+				continue;
+			eint->base_pin_num[inst]++;
+		}
+	}
+
+	eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
+	if (!eint->pin_list)
+		goto err_pin_list;
+
+	eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+	if (!eint->wake_mask)
+		goto err_wake_mask;
+
+	eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+	if (!eint->cur_mask)
+		goto err_cur_mask;
+
+	for (i = 0; i < eint->nbase; i++) {
+		eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16),
+						 GFP_KERNEL);
+		port = DIV_ROUND_UP(eint->base_pin_num[i], 32);
+		eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
+		eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
+		if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i])
+			goto err_eint;
+	}
 
 	eint->domain = irq_domain_add_linear(eint->dev->of_node,
 					     eint->hw->ap_num,
 					     &irq_domain_simple_ops, NULL);
 	if (!eint->domain)
-		return -ENOMEM;
+		goto err_eint;
 
 	if (eint->hw->db_time) {
 		for (i = 0; i < MTK_EINT_DBNC_MAX; i++)
@@ -523,8 +580,11 @@ int mtk_eint_do_init(struct mtk_eint *eint)
 
 	mtk_eint_hw_init(eint);
 	for (i = 0; i < eint->hw->ap_num; i++) {
+		inst = eint->pins[i].instance;
+		if (inst >= eint->nbase)
+			continue;
+		eint->pin_list[inst][eint->pins[i].index] = i;
 		int virq = irq_create_mapping(eint->domain, i);
-
 		irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
 					 handle_level_irq);
 		irq_set_chip_data(virq, eint);
@@ -534,6 +594,27 @@ int mtk_eint_do_init(struct mtk_eint *eint)
 					 eint);
 
 	return 0;
+
+err_eint:
+	for (i = 0; i < eint->nbase; i++) {
+		if (eint->cur_mask[i])
+			devm_kfree(eint->dev, eint->cur_mask[i]);
+		if (eint->wake_mask[i])
+			devm_kfree(eint->dev, eint->wake_mask[i]);
+		if (eint->pin_list[i])
+			devm_kfree(eint->dev, eint->pin_list[i]);
+	}
+	devm_kfree(eint->dev, eint->cur_mask);
+err_cur_mask:
+	devm_kfree(eint->dev, eint->wake_mask);
+err_wake_mask:
+	devm_kfree(eint->dev, eint->pin_list);
+err_pin_list:
+	if (eint->nbase == 1)
+		devm_kfree(eint->dev, eint->pins);
+err_pins:
+	devm_kfree(eint->dev, eint->base_pin_num);
+	return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(mtk_eint_do_init);
 
diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h
index 6139b16cd225..f7f58cca0d5e 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.h
+++ b/drivers/pinctrl/mediatek/mtk-eint.h
@@ -1,10 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2014-2018 MediaTek Inc.
+ * Copyright (C) 2014-2025 MediaTek Inc.
  *
  * Author: Maoguang Meng <maoguang.meng at mediatek.com>
  *	   Sean Wang <sean.wang at mediatek.com>
- *
+ *	   Hao Chang <ot_chhao.chang at mediatek.com>
+ *	   Qingliang Li <qingliang.li at mediatek.com>
  */
 #ifndef __MTK_EINT_H
 #define __MTK_EINT_H
@@ -40,6 +41,14 @@ struct mtk_eint_hw {
 	const unsigned int *db_time;
 };
 
+struct mtk_eint_pin {
+	u16 number;
+	u8 instance;
+	u8 index;
+	bool debounce;
+	bool dual_edge;
+};
+
 extern const unsigned int debounce_time_mt2701[];
 extern const unsigned int debounce_time_mt6765[];
 extern const unsigned int debounce_time_mt6795[];
@@ -56,17 +65,21 @@ struct mtk_eint_xt {
 
 struct mtk_eint {
 	struct device *dev;
-	void __iomem *base;
+	void __iomem **base;
+	u8 nbase;
+	u16 *base_pin_num;
 	struct irq_domain *domain;
 	int irq;
 
 	int *dual_edge;
-	u32 *wake_mask;
-	u32 *cur_mask;
+	u16 **pin_list;
+	u32 **wake_mask;
+	u32 **cur_mask;
 
 	/* Used to fit into various EINT device */
 	const struct mtk_eint_hw *hw;
 	const struct mtk_eint_regs *regs;
+	struct mtk_eint_pin *pins;
 	u16 num_db_time;
 
 	/* Used to fit into various pinctrl device */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 00e95682b9f8..d1556b75d9ef 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 
 #include "mtk-eint.h"
@@ -367,7 +368,7 @@ static const struct mtk_eint_xt mtk_eint_xt = {
 int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	int ret;
+	int ret, i, j, count_reg_names;
 
 	if (!IS_ENABLED(CONFIG_EINT_MTK))
 		return 0;
@@ -379,10 +380,24 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
 	if (!hw->eint)
 		return -ENOMEM;
 
-	hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
-	if (IS_ERR(hw->eint->base)) {
-		ret = PTR_ERR(hw->eint->base);
-		goto err_free_eint;
+	count_reg_names = of_property_count_strings(np, "reg-names");
+	if (count_reg_names < hw->soc->nbase_names)
+		return -EINVAL;
+
+	hw->eint->nbase = count_reg_names - hw->soc->nbase_names;
+	hw->eint->base = devm_kmalloc_array(&pdev->dev, hw->eint->nbase,
+					    sizeof(*hw->eint->base), GFP_KERNEL | __GFP_ZERO);
+	if (!hw->eint->base) {
+		ret = -ENOMEM;
+		goto err_free_base;
+	}
+
+	for (i = hw->soc->nbase_names, j = 0; i < count_reg_names; i++, j++) {
+		hw->eint->base[j] = of_iomap(np, i);
+		if (IS_ERR(hw->eint->base[j])) {
+			ret = PTR_ERR(hw->eint->base[j]);
+			goto err_free_eint;
+		}
 	}
 
 	hw->eint->irq = irq_of_parse_and_map(np, 0);
@@ -401,9 +416,19 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
 	hw->eint->pctl = hw;
 	hw->eint->gpio_xlate = &mtk_eint_xt;
 
-	return mtk_eint_do_init(hw->eint);
+	ret = mtk_eint_do_init(hw->eint);
+	if (ret)
+		goto err_free_eint;
+
+	return 0;
 
 err_free_eint:
+	for (j = 0; j < hw->eint->nbase; j++) {
+		if (hw->eint->base[j])
+			iounmap(hw->eint->base[j]);
+	}
+	devm_kfree(hw->dev, hw->eint->base);
+err_free_base:
 	devm_kfree(hw->dev, hw->eint);
 	hw->eint = NULL;
 	return ret;
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
index 9c271dc2b521..36d2898037dd 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
@@ -242,6 +242,7 @@ struct mtk_pin_soc {
 	unsigned int			nfuncs;
 	const struct mtk_eint_regs	*eint_regs;
 	const struct mtk_eint_hw	*eint_hw;
+	struct mtk_eint_pin		*eint_pin;
 
 	/* Specific parameters per SoC */
 	u8				gpio_m;
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h
index 948ce126aa0c..d8c1822662fc 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.h
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.h
@@ -49,6 +49,13 @@
 			__VA_ARGS__, { } },				\
 	}
 
+#define MTK_EINT_PIN(_number, _instance, _index, _debounce) {	\
+		.number = _number,				\
+		.instance = _instance,				\
+		.index = _index,				\
+		.debounce = _debounce,				\
+	}
+
 #define PINCTRL_PIN_GROUP(_name_, id)							\
 	{										\
 		.grp = PINCTRL_PINGROUP(_name_,id##_pins, ARRAY_SIZE(id##_pins)),	\
-- 
2.46.0



From lkp at intel.com  Fri Mar 21 21:25:12 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 12:25:12 +0800
Subject: [PATCH 1/1] arm64: dts: rockchip: rk3568: Move PCIe3 MSI to use
 GIC ITS
In-Reply-To: <20250308093008.568437-2-amadeus@jmu.edu.cn>
References: <20250308093008.568437-2-amadeus@jmu.edu.cn>
Message-ID: <202503221203.7E0Oa0zG-lkp@intel.com>

Hi Chukun,

kernel test robot noticed the following build errors:

[auto build test ERROR on rockchip/for-next]
[also build test ERROR on linus/master v6.14-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chukun-Pan/arm64-dts-rockchip-rk3568-Move-PCIe3-MSI-to-use-GIC-ITS/20250308-173422
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
patch link:    https://lore.kernel.org/r/20250308093008.568437-2-amadeus%40jmu.edu.cn
patch subject: [PATCH 1/1] arm64: dts: rockchip: rk3568: Move PCIe3 MSI to use GIC ITS
config: arm64-randconfig-r071-20250321 (https://download.01.org/0day-ci/archive/20250322/202503221203.7E0Oa0zG-lkp at intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250322/202503221203.7E0Oa0zG-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503221203.7E0Oa0zG-lkp at intel.com/

All errors (new ones prefixed by >>):

   also defined at arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts:597.10-605.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi:368.10-373.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts:518.10-522.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts:273.10-279.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts:75.10-80.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts:103.10-110.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts:503.10-509.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts:361.10-369.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts:551.10-556.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
   also defined at arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts:133.10-140.3
>> ERROR: Input tree has errors, aborting (use -f to force output)
..

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From david at redhat.com  Fri Mar 21 22:18:26 2025
From: david at redhat.com (David Hildenbrand)
Date: Sat, 22 Mar 2025 06:18:26 +0100
Subject: [PATCH] arm64: mm: Correct the update of max_pfn
In-Reply-To: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
References: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
Message-ID: <f5e08406-c5f6-4d51-b2aa-44cef2386de8@redhat.com>

On 21.03.25 08:00, Zhenhua Huang wrote:
> Hotplugged memory can be smaller than the original memory. For example,
> on my target:
> 
> root at genericarmv8:~# cat /sys/kernel/debug/memblock/memory
>     0: 0x0000000064005000..0x0000000064023fff    0 NOMAP
>     1: 0x0000000064400000..0x00000000647fffff    0 NOMAP
>     2: 0x0000000068000000..0x000000006fffffff    0 DRV_MNG
>     3: 0x0000000088800000..0x0000000094ffefff    0 NONE
>     4: 0x0000000094fff000..0x0000000094ffffff    0 NOMAP
> max_pfn will affect read_page_owner. Therefore, it should first compare and
> then select the larger value for max_pfn.
> 
> Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug")
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
> ---
>   arch/arm64/mm/mmu.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 1dfe1a8efdbe..310ff75891ef 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size,
>   		__remove_pgd_mapping(swapper_pg_dir,
>   				     __phys_to_virt(start), size);
>   	else {
> -		max_pfn = PFN_UP(start + size);
> +		/* Address of hotplugged memory can be smaller */
> +		max_pfn = max(max_pfn, PFN_UP(start + size));
>   		max_low_pfn = max_pfn;
>   	}
>   

Acked-by: David Hildenbrand <david at redhat.com>


-- 
Cheers,

David / dhildenb



From jernej.skrabec at gmail.com  Sat Mar 22 00:38:39 2025
From: jernej.skrabec at gmail.com (Jernej =?UTF-8?B?xaBrcmFiZWM=?=)
Date: Sat, 22 Mar 2025 08:38:39 +0100
Subject: [PATCH] cpufreq: sun50i: prevent out-of-bounds access
In-Reply-To: <20250320155557.211211-1-andre.przywara@arm.com>
References: <20250320155557.211211-1-andre.przywara@arm.com>
Message-ID: <2772067.mvXUDI8C0e@jernej-laptop>

Dne ?etrtek, 20. marec 2025 ob 16:55:57 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> A KASAN enabled kernel reports an out-of-bounds access when handling the
> nvmem cell in the sun50i cpufreq driver:
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in sun50i_cpufreq_nvmem_probe+0x180/0x3d4
> Read of size 4 at addr ffff000006bf31e0 by task kworker/u16:1/38
> 
> This is because the DT specifies the nvmem cell as covering only two
> bytes, but we use a u32 pointer to read the value. DTs for other SoCs
> indeed specify 4 bytes, so we cannot just shorten the variable to a u16.
> 
> Fortunately nvmem_cell_read() allows to return the length of the nvmem
> cell, in bytes, so we can use that information to only access the valid
> portion of the data.
> To cover multiple cell sizes, use memcpy() to copy the information into a
> zeroed u32 buffer, then also make sure we always read the data in little
> endian fashion, as this is how the data is stored in the SID efuses.
> 
> Fixes: 6cc4bcceff9a ("cpufreq: sun50i: Refactor speed bin decoding")
> Reported-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Thanks for fixing that!

Reviewed-by: Jernej ?krabec <jernej.skrabec at gmail.com>

Best regards,
Jernej




From lkp at intel.com  Sat Mar 22 02:16:20 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 17:16:20 +0800
Subject: [soc:soc/dt] BUILD SUCCESS
 b82310b5729ef3ca0aefdc0cf0c575d52f227235
Message-ID: <202503221714.21cZEHAr-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/dt
branch HEAD: b82310b5729ef3ca0aefdc0cf0c575d52f227235  Merge tag 'amlogic-arm-dt-for-v6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux into soc/dt

elapsed time: 1446m

configs tested: 114
configs skipped: 3

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-14.2.0
alpha                            allyesconfig    gcc-14.2.0
arc                              allmodconfig    gcc-14.2.0
arc                               allnoconfig    gcc-14.2.0
arc                              allyesconfig    gcc-14.2.0
arc                   randconfig-001-20250321    gcc-13.3.0
arc                   randconfig-002-20250321    gcc-11.5.0
arm                              allmodconfig    gcc-14.2.0
arm                               allnoconfig    clang-21
arm                              allyesconfig    gcc-14.2.0
arm                   randconfig-001-20250321    clang-19
arm                   randconfig-002-20250321    gcc-9.3.0
arm                   randconfig-003-20250321    gcc-5.5.0
arm                   randconfig-004-20250321    clang-21
arm                    vt8500_v6_v7_defconfig    gcc-14.2.0
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-14.2.0
arm64                 randconfig-001-20250321    gcc-5.5.0
arm64                 randconfig-002-20250321    gcc-5.5.0
arm64                 randconfig-003-20250321    clang-20
arm64                 randconfig-004-20250321    clang-21
csky                              allnoconfig    gcc-14.2.0
csky                  randconfig-001-20250321    gcc-13.3.0
csky                  randconfig-002-20250321    gcc-13.3.0
hexagon                          allmodconfig    clang-17
hexagon                           allnoconfig    clang-21
hexagon                          allyesconfig    clang-21
hexagon               randconfig-001-20250321    clang-21
hexagon               randconfig-002-20250321    clang-16
i386                             allmodconfig    gcc-12
i386                              allnoconfig    gcc-12
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250321    clang-20
i386        buildonly-randconfig-002-20250321    clang-20
i386        buildonly-randconfig-003-20250321    clang-20
i386        buildonly-randconfig-004-20250321    clang-20
i386        buildonly-randconfig-005-20250321    clang-20
i386        buildonly-randconfig-006-20250321    clang-20
i386                                defconfig    clang-20
loongarch                        allmodconfig    gcc-14.2.0
loongarch                         allnoconfig    gcc-14.2.0
loongarch             randconfig-001-20250321    gcc-14.2.0
loongarch             randconfig-002-20250321    gcc-14.2.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
m68k                       bvme6000_defconfig    gcc-14.2.0
m68k                        mvme147_defconfig    gcc-14.2.0
microblaze                       allmodconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
microblaze                       allyesconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250321    gcc-13.3.0
nios2                 randconfig-002-20250321    gcc-7.5.0
openrisc                          allnoconfig    gcc-14.2.0
openrisc                         allyesconfig    gcc-14.2.0
openrisc                            defconfig    gcc-14.2.0
parisc                           allmodconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                           allyesconfig    gcc-14.2.0
parisc                              defconfig    gcc-14.2.0
parisc                randconfig-001-20250321    gcc-8.5.0
parisc                randconfig-002-20250321    gcc-6.5.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc                          allyesconfig    clang-21
powerpc                 mpc8313_rdb_defconfig    gcc-14.2.0
powerpc                 mpc837x_rdb_defconfig    gcc-14.2.0
powerpc               randconfig-001-20250321    clang-21
powerpc               randconfig-002-20250321    gcc-7.5.0
powerpc               randconfig-003-20250321    gcc-7.5.0
powerpc64             randconfig-001-20250321    gcc-5.5.0
powerpc64             randconfig-002-20250321    clang-16
powerpc64             randconfig-003-20250321    gcc-7.5.0
riscv                            allmodconfig    clang-21
riscv                             allnoconfig    gcc-14.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    clang-21
riscv                 randconfig-001-20250321    clang-21
riscv                 randconfig-002-20250321    clang-21
s390                             allmodconfig    clang-18
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250321    clang-16
s390                  randconfig-002-20250321    gcc-8.5.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                                  defconfig    gcc-14.2.0
sh                    randconfig-001-20250321    gcc-7.5.0
sh                    randconfig-002-20250321    gcc-7.5.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250321    gcc-12.4.0
sparc                 randconfig-002-20250321    gcc-6.5.0
sparc64               randconfig-001-20250321    gcc-10.5.0
sparc64               randconfig-002-20250321    gcc-6.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-21
um                               allyesconfig    gcc-12
um                    randconfig-001-20250321    gcc-12
um                    randconfig-002-20250321    gcc-12
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250321    clang-20
x86_64      buildonly-randconfig-002-20250321    clang-20
x86_64      buildonly-randconfig-003-20250321    gcc-12
x86_64      buildonly-randconfig-004-20250321    clang-20
x86_64      buildonly-randconfig-005-20250321    clang-20
x86_64      buildonly-randconfig-006-20250321    clang-20
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250321    gcc-6.5.0
xtensa                randconfig-002-20250321    gcc-10.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From Markus.Elfring at web.de  Sat Mar 22 03:01:18 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 11:01:18 +0100
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <20250320201914.48159-1-qasdev00@gmail.com>
References: <20250320201914.48159-1-qasdev00@gmail.com>
Message-ID: <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>

?
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
>  			continue;
>
>  		link_conf = link_conf_dereference_protected(vif, link_id);
> -		if (!link_conf)
> +		if (!link_conf) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
>
>  		link = mt7996_vif_link(dev, vif, link_id);
> -		if (!link)
> +		if (!link) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
?

I suggest to avoid such repeated error code assignments.
Can an additional label be applied instead for this purpose?

Regards,
Markus


From maz at kernel.org  Sat Mar 22 03:07:44 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 22 Mar 2025 10:07:44 +0000
Subject: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when KVM is not initialised
In-Reply-To: <20250322035115.118048-1-justin.he@arm.com>
References: <20250322035115.118048-1-justin.he@arm.com>
Message-ID: <867c4hml8v.wl-maz@kernel.org>

On Sat, 22 Mar 2025 03:51:15 +0000,
Jia He <justin.he at arm.com> wrote:
> 
> Currently, `kvm_host_pmu_init()` does not check if KVM has been
> successfully initialized before proceeding. This can lead to unintended
> behavior if the function is called in an environment where KVM is not

Which unintended behaviour? Other than the pointless allocation of a
tiny amount of memory? Does anything really go wrong?

> available, e.g., kernel is landed in EL1.

s/landed in/booted from/

> 
> Signed-off-by: Jia He <justin.he at arm.com>
> ---
>  arch/arm64/kvm/pmu.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
> index 7169c1a24dd6..e39c48d12b81 100644
> --- a/arch/arm64/kvm/pmu.c
> +++ b/arch/arm64/kvm/pmu.c
> @@ -227,6 +227,13 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)

Huh:

maz at valley-girl:~/hot-poop/arm-platforms$ git grep -l kvm_host_pmu_init
arch/arm64/kvm/pmu-emul.c
drivers/perf/arm_pmu.c
include/linux/perf/arm_pmu.h

Amusingly, arch/arm64/kvm/pmu.c is nowhere to be seen in this list.
I have no idea what this patch applies to, but that's neither 6.13,
the current upstream, nor kvmarm/next.

>  {
>  	struct arm_pmu_entry *entry;
>  
> +	/*
> +	 * Prevent unintended behavior where KVM is not available or not
> +	 * successfully initialised, e.g., kernel is landed in EL1.

Same comment here.

> +	 */
> +	if (!is_kvm_arm_initialised())

This is definitely the wrong thing to check for, as it relies on the
probe ordering between the PMU drivers and KVM. Relying on that is not
acceptable.

If you're worried about a kernel booted at EL1, then check for that.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From dan.carpenter at linaro.org  Sat Mar 22 03:19:42 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Sat, 22 Mar 2025 13:19:42 +0300
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>
References: <20250320201914.48159-1-qasdev00@gmail.com>
 <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>
Message-ID: <8b342640-f4e7-45a1-a6d4-471e687bbbc7@stanley.mountain>

On Sat, Mar 22, 2025 at 11:01:18AM +0100, Markus Elfring wrote:
> ?
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
> >  			continue;
> >
> >  		link_conf = link_conf_dereference_protected(vif, link_id);
> > -		if (!link_conf)
> > +		if (!link_conf) {
> > +			err = -EINVAL;
> >  			goto error_unlink;
> > +		}
> >
> >  		link = mt7996_vif_link(dev, vif, link_id);
> > -		if (!link)
> > +		if (!link) {
> > +			err = -EINVAL;
> >  			goto error_unlink;
> > +		}
> ?
> 
> I suggest to avoid such repeated error code assignments.
> Can an additional label be applied instead for this purpose?

Maintainers get the final vote but generally when someone is doing
the work they get to decide.

I would say that generally the way that Qasim did it is normally
more readable and more future proof.

regards
dan carpenter


From johannes at sipsolutions.net  Sat Mar 22 03:20:34 2025
From: johannes at sipsolutions.net (Johannes Berg)
Date: Sat, 22 Mar 2025 11:20:34 +0100
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>
References: <20250320201914.48159-1-qasdev00@gmail.com>
	 <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>
Message-ID: <631977c57b2236edfefb8db7a28885ff6888c823.camel@sipsolutions.net>

On Sat, 2025-03-22 at 11:01 +0100, Markus Elfring wrote:
> 
> I suggest to avoid such repeated error code assignments.
> Can an additional label be applied instead for this purpose?
> 

Please stop your "suggestions" on this list. None have really been
helpful.

johannes


From sven at svenpeter.dev  Sat Mar 22 03:25:44 2025
From: sven at svenpeter.dev (Sven Peter)
Date: Sat, 22 Mar 2025 11:25:44 +0100
Subject: [PATCH 2/4] i2c: pasemi: Improve error recovery
In-Reply-To: <mp77oombs4xgr6sjj44ne7muybfrwejgehzv5xupeanh6udui3@ymgfesctindh>
References: <20250222-pasemi-fixes-v1-0-d7ea33d50c5e@svenpeter.dev>
 <20250222-pasemi-fixes-v1-2-d7ea33d50c5e@svenpeter.dev>
 <mp77oombs4xgr6sjj44ne7muybfrwejgehzv5xupeanh6udui3@ymgfesctindh>
Message-ID: <3a849f4d-2cea-458a-9045-b2ae98d4293d@app.fastmail.com>

Hi Andi,

Thanks for the review! Will send a v2 after -rc1 is out.

On Thu, Mar 20, 2025, at 01:17, Andi Shyti wrote:
> Hi Sven,
>
> On Sat, Feb 22, 2025 at 01:38:34PM +0000, Sven Peter via B4 Relay wrote:
>> The hardware (supposedly) has a 25ms timeout for clock stretching
>> and the driver uses 100ms which should be plenty.
>
> Can we add this lines as a comment to the define you are adding?

Sure.

>
>> The error
>> reocvery itself is however lacking.
>
> ...
>
>> -static void pasemi_smb_clear(struct pasemi_smbus *smbus)
>> +static int pasemi_smb_clear(struct pasemi_smbus *smbus)
>>  {
>>  	unsigned int status;
>> +	int timeout = TRANSFER_TIMEOUT_MS;
>>  
>>  	status = reg_read(smbus, REG_SMSTA);
>> +
>> +	/* First wait for the bus to go idle */
>> +	while ((status & (SMSTA_XIP | SMSTA_JAM)) && timeout--) {
>> +		msleep(1);
>
> Please, use usleep_range for 1 millisecond timeout.

Ack.

>
>> +		status = reg_read(smbus, REG_SMSTA);
>> +	}
>
> You could use here readx_poll_timeout() here.

Yup, that should work.

>
>> +
>> +	if (timeout < 0) {
>> +		dev_warn(smbus->dev, "Bus is still stuck (status 0x%08x)\n", status);
>
> if it's an error, please use an error.

Ack.

>
>> +		return -EIO;
>> +	}
>> +
>> +	/* If any badness happened or there is data in the FIFOs, reset the FIFOs */
>> +	if ((status & (SMSTA_MRNE | SMSTA_JMD | SMSTA_MTO | SMSTA_TOM | SMSTA_MTN | SMSTA_MTA)) ||
>> +		!(status & SMSTA_MTE))
>
> Please, fixe the alignment here.

Ok.

>
>> +		pasemi_reset(smbus);
>> +
>> +	/* Clear the flags */
>>  	reg_write(smbus, REG_SMSTA, status);
>> +
>> +	return 0;
>>  }
>>  
>>  static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
>>  {
>> -	int timeout = 100;
>> +	int timeout = TRANSFER_TIMEOUT_MS;
>>  	unsigned int status;
>>  
>>  	if (smbus->use_irq) {
>>  		reinit_completion(&smbus->irq_completion);
>> -		reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
>> -		wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100));
>> +		/* XEN should be set when a transaction terminates, whether due to error or not */
>> +		reg_write(smbus, REG_IMASK, SMSTA_XEN);
>> +		wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(timeout));
>
> what happens if the timeout expires?

I think that can only happen if the hardware is seriously broken because
it's always supposed to set XEN. I'll make sure to catch that case in v2
though and print a separate error message similar to how the polling case
below is taken care of right now.

>
>>  		reg_write(smbus, REG_IMASK, 0);
>>  		status = reg_read(smbus, REG_SMSTA);
>>  	} else {
>
> ...
>
>>  	struct pasemi_smbus *smbus = adapter->algo_data;
>>  	int ret, i;
>>  
>> -	pasemi_smb_clear(smbus);
>> +	if (pasemi_smb_clear(smbus))
>> +		return -EIO;
>
> Can we use
>
> 	ret = ...
> 	if (ret)
> 		return ret;
>
> This way we return whatever comes from pasemi_smb_clear().
>
>>  
>>  	ret = 0;
>
> This way we can remove this line, as well.

Sure, will do both for v2.



Thanks,


Sven



From Markus.Elfring at web.de  Sat Mar 22 03:43:09 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 11:43:09 +0100
Subject: wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <631977c57b2236edfefb8db7a28885ff6888c823.camel@sipsolutions.net>
References: <20250320201914.48159-1-qasdev00@gmail.com>
 <061ebbe3-557b-46d7-acb8-308ae87105dd@web.de>
 <631977c57b2236edfefb8db7a28885ff6888c823.camel@sipsolutions.net>
Message-ID: <68543b3c-2004-43e8-999c-a6579b6aeb23@web.de>

>> I suggest to avoid such repeated error code assignments.
>> Can an additional label be applied instead for this purpose?
>
> Please stop your "suggestions" on this list. None have really been
> helpful.
It seems that you care less then for the avoidance of duplicate source code
also for affected error/exception handling.

Regards,
Markus


From qasdev00 at gmail.com  Sat Mar 22 03:50:52 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sat, 22 Mar 2025 10:50:52 +0000
Subject: [PATCH] wifi: mt76: mt7996: avoid NULL pointer dereference in mt7996_set_monitor()
Message-ID: <20250322105052.19136-1-qasdev00@gmail.com>

The function mt7996_set_monitor() dereferences phy before 
the NULL sanity check.

Fix this to avoid NULL pointer dereference by moving the 
dereference after the check.

Fixes: 69d54ce7491d ("wifi: mt76: mt7996: switch to single multi-radio wiphy")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 91c64e3a0860..66575698aef1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -414,11 +414,13 @@ static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)
 
 static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled)
 {
-	struct mt7996_dev *dev = phy->dev;
+	struct mt7996_dev *dev;
 
 	if (!phy)
 		return;
 
+	dev = phy->dev;
+	
 	if (enabled == !(phy->rxfilter & MT_WF_RFCR_DROP_OTHER_UC))
 		return;
 
-- 
2.39.5



From qasdev00 at gmail.com  Sat Mar 22 04:13:54 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sat, 22 Mar 2025 11:13:54 +0000
Subject: [PATCH] wifi: mt76: mt7996: avoid null deref in mt7996_stop_phy()
Message-ID: <20250322111354.23800-1-qasdev00@gmail.com>

In mt7996_stop_phy() the mt7996_phy structure is 
dereferenced before the null sanity check which could 
lead to a null deref.

Fix by moving the dereference operation after the 
sanity check.

Fixes: 69d54ce7491d ("wifi: mt76: mt7996: switch to single multi-radio wiphy")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 66575698aef1..88e013577c0d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -68,11 +68,13 @@ static int mt7996_start(struct ieee80211_hw *hw)
 
 static void mt7996_stop_phy(struct mt7996_phy *phy)
 {
-	struct mt7996_dev *dev = phy->dev;
+	struct mt7996_dev *dev;
 
 	if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
 		return;
 
+	dev = phy->dev;
+
 	cancel_delayed_work_sync(&phy->mt76->mac_work);
 
 	mutex_lock(&dev->mt76.mutex);
-- 
2.39.5



From daniel.lezcano at linaro.org  Sat Mar 22 04:39:20 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Sat, 22 Mar 2025 12:39:20 +0100
Subject: s32 architecture upstream tree
Message-ID: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>


Hi,

the MAINTAINER file does not give the information about the location of 
the repository for the s32.

Where is the repo to base the work on ? Especially the device tree

Thanks in advance

   -- Daniel


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog



From Markus.Elfring at web.de  Sat Mar 22 04:44:51 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 12:44:51 +0100
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <20250320201914.48159-1-qasdev00@gmail.com>
References: <20250320201914.48159-1-qasdev00@gmail.com>
Message-ID: <3bef0804-83ca-44e1-87da-db5b777d68cb@web.de>

> If link_conf_dereference_protected() or mt7996_vif_link()
> or link_sta_dereference_protected() fail the code jumps to

                                      call failed?


> the error_unlink label and returns ret which is uninitialised.

                                     a value from a local variable
                                     which was not initialised properly?


Can the summary phrase be improved also another bit?

Regards,
Markus


From mailhol.vincent at wanadoo.fr  Sat Mar 22 04:46:52 2025
From: mailhol.vincent at wanadoo.fr (Vincent Mailhol)
Date: Sat, 22 Mar 2025 20:46:52 +0900
Subject: [PATCH v4 3/8] bits: introduce fixed-type genmasks
In-Reply-To: <Z92cThxAyXu9JJdk@thinkpad>
References: <20250305-fixed-type-genmasks-v4-0-1873dcdf6723@wanadoo.fr>
 <20250305-fixed-type-genmasks-v4-3-1873dcdf6723@wanadoo.fr>
 <Z8hsRJvpjYoqh9RG@thinkpad> <Z9oiEkQEcHhA0a80@thinkpad>
 <5cbaefa8-e51f-415f-a9b3-4841e69bb3fa@arm.com>
 <1aba17f1-0cd2-429c-8338-28387ec16314@arm.com> <Z92cThxAyXu9JJdk@thinkpad>
Message-ID: <5d2af209-46bd-4a40-b82f-7772ed0b825d@wanadoo.fr>

On 22/03/2025 at 02:05, Yury Norov wrote:
> On Wed, Mar 19, 2025 at 09:43:06AM +0530, Anshuman Khandual wrote:
>> 
>> 
>> On 3/19/25 09:04, Anshuman Khandual wrote:
>>> On 3/19/25 07:16, Yury Norov wrote:
>>>> + Catalin Marinas, ARM maillist

(...)

>>> These were moved into uapi subsequently via the following 
>>> commit.
>>> 
>>> 21a3a3d015aee ("tools headers: Synchronize {uapi/}linux/bits.h 
>>> with the kernel sources")
>>> 
>>> But in general GENMASK_U128() is needed for generating 128 bit 
>>> page table entries, related flags and masks whether in kernel or
>>> in user space for writing kernel test cases etc.
>> 
>> In the commit 947697c6f0f7 ("uapi: Define GENMASK_U128"), 
>> GENMASK_U128() gets defined using __GENMASK_U128() which in turn 
>> calls __BIT128() - both of which are defined in UAPI headers 
>> inside (include/uapi/linux/).
>> 
>> Just wondering - are you suggesting to move these helpers from 
>> include/uapi/linux/ to include/linux/bits.h instead ?
> 
> Vincent is working on fixed-width GENMASK_Uxx() based on 
> GENMASK_TYPE().
> 
> https://lore.kernel.org/lkml/20250308-fixed-type-genmasks-v6-0- 
> f59315e73c29 at wanadoo.fr/T/
> 
> The series adds a general GENMASK_TYPE() in the linux/bits.h. I'd 
> like all fixed-widh genmasks to be based on it. The implementation 
> doesn't allow to move GENMASK_TYPE() the to uapi easily.
> 
> There was a discussion regarding that, and for now the general 
> understanding is that userspace doesn't need GENMASK_Uxx().
> 
> Are your proposed tests based on the in-kernel tools/ ? If so, 
> linux/ bits.h will be available for you.
> 
> Vincent,
> 
> Can you please experiment with moving GENMASK_U128() to linux/ 
> bits.h and switching it to GENMASK_TYPE()-based implementation?
> 
> If it works, we can do it after merging of GENMASK_TYPE() and 
> ancestors.

I sent the new version with the split as you asked in a separate message.

I switched GENMASK_U128() from using __GENMASK_U128() to using
GENMASK_TYPE() in this patch of the second series:

https://lore.kernel.org/all/20250322-consolidate-genmask-
v1-2-54bfd36c5643 at wanadoo.fr/

After this, the genmask_u128_test() unit tests from lib/test_bits.c are
all green, so this looks good. Note that because it is not yet used,
there isn't much more things to test aside from that unit test.

To be precise, I am not yet *moving* it. For now, I decoupled
GENMASK_U128() from __GENMASK_U128(). To complete the move, all what is
left is to remove __GENMASK_U128() from the uapi. To be honest, I am not
keen on touching either of the uapi or the asm variants myself. But, if
my work gets merged, that last step should be easy for you.



On a side note, at first glance, I was disturbed by the current
__GENMASK_U128() implementation:

  #define __GENMASK_U128(h, l) \
  	((_BIT128((h)) << 1) - (_BIT128(l)))

If calling __GENMASK_U128(127, x), the macro does a:

  _BIT128(127) << 1

which expands to:

  (unsigned __int128)1 << 127 << 1

So, while (unsigned __int128)1 << 128 is an undefined behaviour, doing
it in two steps: << 127 and << 1 is well defined and gives zero. Then,
when doing the subtraction, the unsigned integer wraparound restores the
most significant bits making things go back to normal.


The same applies to all the other variants. If doing:

  #define GENMASK_TYPE(t, h, l)				\
  	((t)(GENMASK_INPUT_CHECK(h, l) +		\
  	     (((t)1 << (h) << 1) - ((t)1 << (l)))))

The unit tests pass for everything and you even still get the warning if
h is out of bound.

But then, bloat-o-meter (x86_64, defconfig, GCC 12.4.1) shows a small
increase:

  Total: Before=22723482, After=22724586, chg +0.00%

So, probably not worth the change anyway. I am keeping the current version.


Yours sincerely,
Vincent Mailhol


From jonas.gorski at gmail.com  Sat Mar 22 04:51:57 2025
From: jonas.gorski at gmail.com (Jonas Gorski)
Date: Sat, 22 Mar 2025 12:51:57 +0100
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in mt7996_mac_sta_add_links
In-Reply-To: <20250320201914.48159-1-qasdev00@gmail.com>
References: <20250320201914.48159-1-qasdev00@gmail.com>
Message-ID: <CAOiHx==UCeMQpywQJCLPQqipEW0tK9youRxdR5+_T1LuGp_EHA@mail.gmail.com>

Hi,

On Thu, Mar 20, 2025 at 9:19?PM Qasim Ijaz <qasdev00 at gmail.com> wrote:
>
> If link_conf_dereference_protected() or mt7996_vif_link()
> or link_sta_dereference_protected() fail the code jumps to
> the error_unlink label and returns ret which is uninitialised.
>
> Fix this by setting err before jumping to error_unlink.
>
> Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
> Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 91c64e3a0860..78f7f1fc867e 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
>                         continue;
>
>                 link_conf = link_conf_dereference_protected(vif, link_id);
> -               if (!link_conf)
> +               if (!link_conf) {
> +                       err = -EINVAL;
>                         goto error_unlink;
> +               }
>
>                 link = mt7996_vif_link(dev, vif, link_id);
> -               if (!link)
> +               if (!link) {
> +                       err = -EINVAL;
>                         goto error_unlink;
> +               }
>
>                 link_sta = link_sta_dereference_protected(sta, link_id);
> -               if (!link_sta)
> +               if (!link_sta) {
> +                       err = -EINVAL

You are missing a semicolon at the end of the line.

To also do some bike shedding, you could initialize err (with 0 or
-EINVAL), and then change the err return to return err ? : -EINVAL;.
But your way has an explicit error code assigned to each failure, even
if it is always the same. So I won't claim my suggestion is better.

Best regards,
Jonas


From lkp at intel.com  Sat Mar 22 05:00:48 2025
From: lkp at intel.com (kernel test robot)
Date: Sat, 22 Mar 2025 20:00:48 +0800
Subject: [soc:soc/drivers] BUILD REGRESSION
 cf2ae5e5b68b06b4c8bceb42d46fa311e6db9a60
Message-ID: <202503222040.UjFfXpC9-lkp@intel.com>

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/drivers
branch HEAD: cf2ae5e5b68b06b4c8bceb42d46fa311e6db9a60  Merge tag 'soc_fsl-6.15-1' of https://github.com/chleroy/linux into soc/drivers

Error/Warning (recently discovered and may have been fixed):

    turris-omnia-mcu-gpio.c:(.text+0x1596): undefined reference to `__ffsdi2'

Error/Warning ids grouped by kconfigs:

recent_errors
|-- alpha-allyesconfig
|   |-- (.text):undefined-reference-to-__ffsdi2
|   `-- alpha-linux-ld:(.text):undefined-reference-to-__ffsdi2
|-- arm-allmodconfig
|   `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined
|-- i386-allmodconfig
|   `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined
|-- i386-allyesconfig
|   `-- turris-omnia-mcu-gpio.c:(.text):undefined-reference-to-__ffsdi2
|-- m68k-allmodconfig
|   `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined
|-- m68k-allyesconfig
|   `-- turris-omnia-mcu-gpio.c:(.text):undefined-reference-to-__ffsdi2
|-- parisc-allmodconfig
|   `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined
|-- sh-allmodconfig
|   `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined
|-- sh-allyesconfig
|   `-- (.text):undefined-reference-to-__ffsdi2
`-- sparc-allmodconfig
    `-- ERROR:__ffsdi2-drivers-platform-cznic-turris-omnia-mcu.ko-undefined

elapsed time: 1448m

configs tested: 113
configs skipped: 2

tested configs:
alpha                             allnoconfig    gcc-14.2.0
alpha                            allyesconfig    gcc-14.2.0
arc                              allmodconfig    gcc-14.2.0
arc                               allnoconfig    gcc-14.2.0
arc                              allyesconfig    gcc-14.2.0
arc                   randconfig-001-20250321    gcc-13.3.0
arc                   randconfig-002-20250321    gcc-11.5.0
arm                              allmodconfig    gcc-14.2.0
arm                               allnoconfig    clang-21
arm                              allyesconfig    gcc-14.2.0
arm                          exynos_defconfig    clang-21
arm                   randconfig-001-20250321    clang-19
arm                   randconfig-002-20250321    gcc-9.3.0
arm                   randconfig-003-20250321    gcc-5.5.0
arm                   randconfig-004-20250321    clang-21
arm                    vt8500_v6_v7_defconfig    gcc-14.2.0
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-14.2.0
arm64                 randconfig-001-20250321    gcc-5.5.0
arm64                 randconfig-002-20250321    gcc-5.5.0
arm64                 randconfig-003-20250321    clang-20
arm64                 randconfig-004-20250321    clang-21
csky                              allnoconfig    gcc-14.2.0
csky                  randconfig-001-20250321    gcc-13.3.0
csky                  randconfig-002-20250321    gcc-13.3.0
hexagon                          allmodconfig    clang-17
hexagon                           allnoconfig    clang-21
hexagon                          allyesconfig    clang-21
hexagon               randconfig-001-20250321    clang-21
hexagon               randconfig-002-20250321    clang-16
i386                             allmodconfig    gcc-12
i386                              allnoconfig    gcc-12
i386                             allyesconfig    gcc-12
i386        buildonly-randconfig-001-20250321    clang-20
i386        buildonly-randconfig-002-20250321    clang-20
i386        buildonly-randconfig-003-20250321    clang-20
i386        buildonly-randconfig-004-20250321    clang-20
i386        buildonly-randconfig-005-20250321    clang-20
i386        buildonly-randconfig-006-20250321    clang-20
i386                                defconfig    clang-20
loongarch                        allmodconfig    gcc-14.2.0
loongarch                         allnoconfig    gcc-14.2.0
loongarch             randconfig-001-20250321    gcc-14.2.0
loongarch             randconfig-002-20250321    gcc-14.2.0
m68k                             allmodconfig    gcc-14.2.0
m68k                              allnoconfig    gcc-14.2.0
m68k                             allyesconfig    gcc-14.2.0
m68k                       bvme6000_defconfig    gcc-14.2.0
m68k                        mvme147_defconfig    gcc-14.2.0
microblaze                        allnoconfig    gcc-14.2.0
mips                              allnoconfig    gcc-14.2.0
mips                      bmips_stb_defconfig    clang-21
nios2                             allnoconfig    gcc-14.2.0
nios2                 randconfig-001-20250321    gcc-13.3.0
nios2                 randconfig-002-20250321    gcc-7.5.0
openrisc                          allnoconfig    gcc-14.2.0
openrisc                         allyesconfig    gcc-14.2.0
openrisc                            defconfig    gcc-14.2.0
parisc                           allmodconfig    gcc-14.2.0
parisc                            allnoconfig    gcc-14.2.0
parisc                           allyesconfig    gcc-14.2.0
parisc                              defconfig    gcc-14.2.0
parisc                randconfig-001-20250321    gcc-8.5.0
parisc                randconfig-002-20250321    gcc-6.5.0
powerpc                          allmodconfig    gcc-14.2.0
powerpc                           allnoconfig    gcc-14.2.0
powerpc                          allyesconfig    clang-21
powerpc                 mpc8313_rdb_defconfig    gcc-14.2.0
powerpc               randconfig-001-20250321    clang-21
powerpc               randconfig-002-20250321    gcc-7.5.0
powerpc               randconfig-003-20250321    gcc-7.5.0
powerpc64             randconfig-001-20250321    gcc-5.5.0
powerpc64             randconfig-002-20250321    clang-16
powerpc64             randconfig-003-20250321    gcc-7.5.0
riscv                            allmodconfig    clang-21
riscv                             allnoconfig    gcc-14.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    clang-21
riscv                 randconfig-001-20250321    clang-21
riscv                 randconfig-002-20250321    clang-21
s390                             allmodconfig    clang-18
s390                              allnoconfig    clang-15
s390                             allyesconfig    gcc-14.2.0
s390                  randconfig-001-20250321    clang-16
s390                  randconfig-002-20250321    gcc-8.5.0
sh                               allmodconfig    gcc-14.2.0
sh                                allnoconfig    gcc-14.2.0
sh                               allyesconfig    gcc-14.2.0
sh                    randconfig-001-20250321    gcc-7.5.0
sh                    randconfig-002-20250321    gcc-7.5.0
sparc                            allmodconfig    gcc-14.2.0
sparc                             allnoconfig    gcc-14.2.0
sparc                 randconfig-001-20250321    gcc-12.4.0
sparc                 randconfig-002-20250321    gcc-6.5.0
sparc64               randconfig-001-20250321    gcc-10.5.0
sparc64               randconfig-002-20250321    gcc-6.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-21
um                               allyesconfig    gcc-12
um                    randconfig-001-20250321    gcc-12
um                    randconfig-002-20250321    gcc-12
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250321    clang-20
x86_64      buildonly-randconfig-002-20250321    clang-20
x86_64      buildonly-randconfig-003-20250321    gcc-12
x86_64      buildonly-randconfig-004-20250321    clang-20
x86_64      buildonly-randconfig-005-20250321    clang-20
x86_64      buildonly-randconfig-006-20250321    clang-20
x86_64                              defconfig    gcc-11
xtensa                            allnoconfig    gcc-14.2.0
xtensa                randconfig-001-20250321    gcc-6.5.0
xtensa                randconfig-002-20250321    gcc-10.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From andy.shevchenko at gmail.com  Sat Mar 22 06:23:01 2025
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Sat, 22 Mar 2025 15:23:01 +0200
Subject: [PATCH 1/4] i2c: pasemi: Add registers bits and switch to BIT()
In-Reply-To: <rjvak3c2k5a64jw4ef23i5uptg4zzl3u7lqszqbg56l4hqms77@hrkn5eydxwiy>
References: <20250222-pasemi-fixes-v1-0-d7ea33d50c5e@svenpeter.dev>
 <20250222-pasemi-fixes-v1-1-d7ea33d50c5e@svenpeter.dev>
 <rjvak3c2k5a64jw4ef23i5uptg4zzl3u7lqszqbg56l4hqms77@hrkn5eydxwiy>
Message-ID: <Z965tVhC5jxy1kqZ@surfacebook.localdomain>

Thu, Mar 20, 2025 at 01:23:25AM +0100, Andi Shyti kirjoitti:
> Hi Sven,
> 
> On Sat, Feb 22, 2025 at 01:38:33PM +0000, Sven Peter via B4 Relay wrote:
> > From: Sven Peter <sven at svenpeter.dev>
> > 
> > Add the missing register bits to the defines and also switch
> > those to use the BIT macro which is much more readable than
> > using hardcoded masks
> > 
> > Co-developed-by: Hector Martin <marcan at marcan.st>
> > Signed-off-by: Hector Martin <marcan at marcan.st>
> > Signed-off-by: Sven Peter <sven at svenpeter.dev>
> 
> Just this patch merged to i2c/i2c-host.

This needs an update as well. The proper header for BIT() et al. is bits.h.
bitfield.h is for FIELD_*() et al.

-- 
With Best Regards,
Andy Shevchenko




From andersson at kernel.org  Sat Mar 22 06:34:50 2025
From: andersson at kernel.org (Bjorn Andersson)
Date: Sat, 22 Mar 2025 08:34:50 -0500
Subject: [GIT PULL] Qualcomm clock updates for v6.15
Message-ID: <20250322133453.2723879-1-andersson@kernel.org>


The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:

  Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-clk-for-6.15

for you to fetch changes up to 9bf3684e0f7e65298ff844fd81e6dc5105c67354:

  clk: qcom: Add NSS clock Controller driver for IPQ9574 (2025-03-17 10:11:45 -0500)

----------------------------------------------------------------
Qualcomm clock updates for v6.15

Support is introduced for associating GDSCs with multiple power-domains,
in order to handle the cases where both (some form of) CX and MX needs
to be voted for.

New support for IPQ9574 NSS clock controller, QCS8300 GPU and video
clock controllers are added, as is RPM clocks for SDM429. LPASS resets
are added for QCM6490.

Branch clock halt halt check is corrected for clocks with voted halt
state.

SM8250 camera clocks are moved to rcg2_shared_ops, to make sure they are
parked when disabled. Missing SDCC resets are added for SDM660. SM8750
global clock controller regmap is adjusted to not trigger a security
violation if the regmap is dumped.

On SM8650 USB GDSCs are moved to retain the state during power down.

The GPU AHB clock and display XO clock are removed from Linux's control
for X Elite, as they shouldn't be managed by the OS.

A few smaller improvements and corrections to the GDSC implementation.

UART frequencies for IPQ5424 are corrected to fix issues with UART flow
control, SDCC apps frequency table is corrected to make the SDCC clock
tick at the expected frequency. IPQ5018 global clock controller is being
allowed to be built on Arm32 as well.

----------------------------------------------------------------
Ajit Pandey (1):
      clk: qcom: clk-branch: Fix invert halt status bit check for votable clocks

Alexey Minnekhanov (3):
      dt-bindings: clock: gcc-sdm660: Add missing SDCC resets
      dt-bindings: clock: gcc-sdm660: Add missing SDCC resets
      clk: qcom: gcc-sdm660: Add missing SDCC block resets

Barnab?s Cz?m?n (1):
      clk: qcom: mmcc-sdm660: fix stuck video_subcore0 clock

Bjorn Andersson (4):
      Merge branch '20250212-sdm429-rpm-v1-1-0a24ac19a478 at mainlining.org' into clk-for-6.15
      Merge branch '20250203063427.358327-2-alexeymin at postmarketos.org' into clk-for-6.15
      Merge branch '20250109-qcs8300-mm-patches-new-v4-0-63e8ac268b02 at quicinc.com' into clk-for-6.15
      Merge branch '20250313110359.242491-1-quic_mmanikan at quicinc.com' into clk-for-6.15

Bryan O'Donoghue (4):
      clk: qcom: gdsc: Release pm subdomains in reverse add order
      clk: qcom: gdsc: Capture pm_genpd_add_subdomain result code
      clk: qcom: common: Add support for power-domain attachment
      clk: qcom: Support attaching GDSCs to multiple parents

Daniil Titov (2):
      dt-bindings: clock: qcom,rpmcc: Add SDM429
      clk: qcom: smd-rpm: Add clocks for SDM429

Devi Priya (4):
      dt-bindings: clock: gcc-ipq9574: Add definition for GPLL0_OUT_AUX
      dt-bindings: clock: Add ipq9574 NSSCC clock and reset definitions
      clk: qcom: gcc-ipq9574: Add support for gpll0_out_aux clock
      clk: qcom: Add NSS clock Controller driver for IPQ9574

Imran Shaik (5):
      dt-bindings: clock: qcom: Add GPU clocks for QCS8300
      dt-bindings: clock: qcom: Add CAMCC clocks for QCS8300
      dt-bindings: clock: qcom: Add QCS8300 video clock controller
      clk: qcom: Add support for GPU Clock Controller on QCS8300
      clk: qcom: Add support for Video Clock Controller on QCS8300

Jordan Crouse (1):
      clk: qcom: camcc-sm8250: Use clk_rcg2_shared_ops for some RCGs

Karl Chan (1):
      clk: qcom: ipq5018: allow it to be bulid on arm32

Konrad Dybcio (1):
      clk: qcom: gcc-x1e80100: Unregister GCC_GPU_CFG_AHB_CLK/GCC_DISP_XO_CLK

Krzysztof Kozlowski (8):
      clk: qcom: clk-alpha-pll: Do not use random stack value for recalc rate
      clk: qcom: Drop unused header includes
      clk: qcom: Add missing header includes
      clk: qcom: dispcc-sm8750: Allow dumping regmap
      clk: qcom: camcc: Constify 'struct qcom_cc_desc'
      clk: qcom: dispcc: Constify 'struct qcom_cc_desc'
      clk: qcom: gpucc: Constify 'struct qcom_cc_desc'
      clk: qcom: videocc: Constify 'struct qcom_cc_desc'

Manikanta Mylavarapu (2):
      clk: qcom: ipq5424: fix software and hardware flow control error of UART
      drivers: clk: qcom: ipq5424: fix the freq table of sdcc1_apps clock

Neil Armstrong (1):
      clk: qcom: gcc-sm8650: Do not turn off USB GDSCs during gdsc_disable()

Taniya Das (4):
      clk: qcom: gdsc: Set retain_ff before moving to HW CTRL
      clk: qcom: gdsc: Update the status poll timeout for GDSC
      dt-bindings: clock: qcom: Add compatible for QCM6490 boards
      clk: qcom: lpassaudiocc-sc7280: Add support for LPASS resets for QCM6490

Vladimir Lypak (1):
      clk: qcom: gcc-msm8953: fix stuck venus0_core0 clock

Vladimir Zapolskiy (2):
      dt-bindings: clock: qcom: sm8450-camcc: Remove qcom,x1e80100-camcc leftover
      dt-bindings: clock: qcom,x1e80100-camcc: Fix the list of required-opps

 .../devicetree/bindings/clock/qcom,gpucc.yaml      |    3 +
 .../bindings/clock/qcom,ipq9574-nsscc.yaml         |   98 +
 .../devicetree/bindings/clock/qcom,rpmcc.yaml      |    2 +
 .../bindings/clock/qcom,sa8775p-camcc.yaml         |    6 +-
 .../bindings/clock/qcom,sa8775p-videocc.yaml       |    1 +
 .../bindings/clock/qcom,sc7280-lpasscorecc.yaml    |    5 +-
 .../bindings/clock/qcom,sm8450-camcc.yaml          |    1 -
 .../bindings/clock/qcom,x1e80100-camcc.yaml        |    9 +-
 drivers/clk/qcom/Kconfig                           |    9 +-
 drivers/clk/qcom/Makefile                          |    1 +
 drivers/clk/qcom/camcc-sa8775p.c                   |    3 +-
 drivers/clk/qcom/camcc-sc7180.c                    |    2 +-
 drivers/clk/qcom/camcc-sc7280.c                    |    2 +-
 drivers/clk/qcom/camcc-sc8280xp.c                  |    2 +-
 drivers/clk/qcom/camcc-sdm845.c                    |    1 +
 drivers/clk/qcom/camcc-sm4450.c                    |    3 +-
 drivers/clk/qcom/camcc-sm6350.c                    |    1 +
 drivers/clk/qcom/camcc-sm7150.c                    |    1 -
 drivers/clk/qcom/camcc-sm8150.c                    |    4 +-
 drivers/clk/qcom/camcc-sm8250.c                    |   58 +-
 drivers/clk/qcom/camcc-sm8550.c                    |    2 +-
 drivers/clk/qcom/camcc-sm8650.c                    |    2 +-
 drivers/clk/qcom/clk-alpha-pll.c                   |   52 +-
 drivers/clk/qcom/clk-branch.c                      |    4 +-
 drivers/clk/qcom/clk-smd-rpm.c                     |   32 +
 drivers/clk/qcom/common.c                          |    6 +
 drivers/clk/qcom/dispcc-qcm2290.c                  |    3 +-
 drivers/clk/qcom/dispcc-sc7180.c                   |    1 +
 drivers/clk/qcom/dispcc-sc7280.c                   |    1 +
 drivers/clk/qcom/dispcc-sc8280xp.c                 |    7 +-
 drivers/clk/qcom/dispcc-sdm845.c                   |    2 +-
 drivers/clk/qcom/dispcc-sm4450.c                   |    3 +-
 drivers/clk/qcom/dispcc-sm6115.c                   |    3 +-
 drivers/clk/qcom/dispcc-sm6125.c                   |    1 +
 drivers/clk/qcom/dispcc-sm6350.c                   |    1 +
 drivers/clk/qcom/dispcc-sm6375.c                   |    1 +
 drivers/clk/qcom/dispcc-sm7150.c                   |    1 -
 drivers/clk/qcom/dispcc-sm8250.c                   |    2 +-
 drivers/clk/qcom/dispcc-sm8450.c                   |    5 +-
 drivers/clk/qcom/dispcc-sm8550.c                   |    5 +-
 drivers/clk/qcom/dispcc-sm8750.c                   |    4 +-
 drivers/clk/qcom/dispcc0-sa8775p.c                 |    3 +-
 drivers/clk/qcom/dispcc1-sa8775p.c                 |    3 +-
 drivers/clk/qcom/gcc-ipq5424.c                     |   24 +-
 drivers/clk/qcom/gcc-ipq9574.c                     |   15 +
 drivers/clk/qcom/gcc-msm8953.c                     |    2 +-
 drivers/clk/qcom/gcc-msm8960.c                     |    1 -
 drivers/clk/qcom/gcc-msm8974.c                     |    1 -
 drivers/clk/qcom/gcc-sdm660.c                      |    2 +
 drivers/clk/qcom/gcc-sm8650.c                      |    4 +-
 drivers/clk/qcom/gcc-x1e80100.c                    |   30 -
 drivers/clk/qcom/gdsc.c                            |   98 +-
 drivers/clk/qcom/gdsc.h                            |    1 +
 drivers/clk/qcom/gpucc-msm8998.c                   |    3 +-
 drivers/clk/qcom/gpucc-sa8775p.c                   |   49 +-
 drivers/clk/qcom/gpucc-sar2130p.c                  |    1 +
 drivers/clk/qcom/gpucc-sc7180.c                    |    1 +
 drivers/clk/qcom/gpucc-sc7280.c                    |    1 +
 drivers/clk/qcom/gpucc-sc8280xp.c                  |    3 +-
 drivers/clk/qcom/gpucc-sdm660.c                    |    5 +-
 drivers/clk/qcom/gpucc-sdm845.c                    |    1 +
 drivers/clk/qcom/gpucc-sm4450.c                    |    1 -
 drivers/clk/qcom/gpucc-sm6350.c                    |    1 +
 drivers/clk/qcom/gpucc-sm8150.c                    |    1 +
 drivers/clk/qcom/gpucc-sm8250.c                    |    1 +
 drivers/clk/qcom/gpucc-sm8350.c                    |    2 +-
 drivers/clk/qcom/gpucc-x1p42100.c                  |    2 +-
 drivers/clk/qcom/kpss-xcc.c                        |    1 -
 drivers/clk/qcom/krait-cc.c                        |    1 -
 drivers/clk/qcom/lpassaudiocc-sc7280.c             |   23 +-
 drivers/clk/qcom/lpasscc-sdm845.c                  |    1 -
 drivers/clk/qcom/lpasscorecc-sc7180.c              |    1 -
 drivers/clk/qcom/lpasscorecc-sc7280.c              |    1 -
 drivers/clk/qcom/mmcc-apq8084.c                    |    2 +-
 drivers/clk/qcom/mmcc-msm8960.c                    |    4 +-
 drivers/clk/qcom/mmcc-msm8974.c                    |    2 +-
 drivers/clk/qcom/mmcc-msm8994.c                    |    3 +-
 drivers/clk/qcom/mmcc-msm8996.c                    |    4 +-
 drivers/clk/qcom/mmcc-msm8998.c                    |    3 +-
 drivers/clk/qcom/mmcc-sdm660.c                     |    8 +-
 drivers/clk/qcom/nsscc-ipq9574.c                   | 3110 ++++++++++++++++++++
 drivers/clk/qcom/videocc-sa8775p.c                 |   10 +-
 drivers/clk/qcom/videocc-sm8350.c                  |    2 +-
 drivers/clk/qcom/videocc-sm8450.c                  |    2 +-
 drivers/clk/qcom/videocc-sm8550.c                  |    2 +-
 include/dt-bindings/clock/qcom,gcc-sdm660.h        |    2 +
 include/dt-bindings/clock/qcom,ipq9574-gcc.h       |    1 +
 include/dt-bindings/clock/qcom,ipq9574-nsscc.h     |  152 +
 include/dt-bindings/clock/qcom,qcs8300-camcc.h     |   16 +
 include/dt-bindings/clock/qcom,qcs8300-gpucc.h     |   17 +
 include/dt-bindings/clock/qcom,rpmcc.h             |    4 +
 include/dt-bindings/reset/qcom,ipq9574-nsscc.h     |  134 +
 92 files changed, 3913 insertions(+), 199 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml
 create mode 100644 drivers/clk/qcom/nsscc-ipq9574.c
 create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h
 create mode 100644 include/dt-bindings/clock/qcom,qcs8300-camcc.h
 create mode 100644 include/dt-bindings/clock/qcom,qcs8300-gpucc.h
 create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h


From Markus.Elfring at web.de  Sat Mar 22 06:40:05 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 14:40:05 +0100
Subject: [PATCH] wifi: mt76: mt7996: avoid NULL pointer dereference in
 mt7996_set_monitor()
In-Reply-To: <20250322105052.19136-1-qasdev00@gmail.com>
References: <20250322105052.19136-1-qasdev00@gmail.com>
Message-ID: <52071c76-dd06-4b11-bb79-a5e0c28b94ca@web.de>

> The function mt7996_set_monitor() dereferences phy before
> the NULL sanity check.
>
> Fix this to avoid NULL pointer dereference by moving the
> dereference after the check.

Were any known source code analysis tools involved for this software improvement?

Regards,
Markus


From Justin.He at arm.com  Sat Mar 22 06:54:17 2025
From: Justin.He at arm.com (Justin He)
Date: Sat, 22 Mar 2025 13:54:17 +0000
Subject: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when KVM is
 not initialised
In-Reply-To: <867c4hml8v.wl-maz@kernel.org>
References: <20250322035115.118048-1-justin.he@arm.com>
 <867c4hml8v.wl-maz@kernel.org>
Message-ID: <GV2PR08MB920679CA30617D465B69D79DF7DA2@GV2PR08MB9206.eurprd08.prod.outlook.com>

Hi Marc,

> -----Original Message-----
> From: Marc Zyngier <maz at kernel.org>
> Sent: Saturday, March 22, 2025 6:08 PM
> To: Justin He <Justin.He at arm.com>
> Cc: Oliver Upton <oliver.upton at linux.dev>; linux-arm-
> kernel at lists.infradead.org; kvmarm at lists.linux.dev; Joey Gouly
> <Joey.Gouly at arm.com>; Suzuki Poulose <Suzuki.Poulose at arm.com>;
> Zenghui Yu <yuzenghui at huawei.com>; Catalin Marinas
> <Catalin.Marinas at arm.com>; Will Deacon <will at kernel.org>; linux-
> kernel at vger.kernel.org
> Subject: Re: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when
> KVM is not initialised
> 
> On Sat, 22 Mar 2025 03:51:15 +0000,
> Jia He <justin.he at arm.com> wrote:
> >
> > Currently, `kvm_host_pmu_init()` does not check if KVM has been
> > successfully initialized before proceeding. This can lead to
> > unintended behavior if the function is called in an environment where
> > KVM is not
> 
> Which unintended behaviour? Other than the pointless allocation of a tiny
> amount of memory? Does anything really go wrong?
> 
Sorry for the confusion --- I should explain more clearly.
I noticed the usage of host_data_ptr in Colton Lewis's RFC patch [1]. After
applying the patch, the guest VM fails to boot.Upon investigating the root
cause, I found that host_data_ptr can trigger a kernel panic if KVM is not
initialized.

[1] https://patchwork.kernel.org/project/kvm/patch/20250213180317.3205285-6-coltonlewis at google.com/
> > available, e.g., kernel is landed in EL1.
> 
> s/landed in/booted from/
> 
> >
> > Signed-off-by: Jia He <justin.he at arm.com>
> > ---
> >  arch/arm64/kvm/pmu.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c index
> > 7169c1a24dd6..e39c48d12b81 100644
> > --- a/arch/arm64/kvm/pmu.c
> > +++ b/arch/arm64/kvm/pmu.c
> > @@ -227,6 +227,13 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
> 
> Huh:
> 
> maz at valley-girl:~/hot-poop/arm-platforms$ git grep -l kvm_host_pmu_init
> arch/arm64/kvm/pmu-emul.c drivers/perf/arm_pmu.c
> include/linux/perf/arm_pmu.h
> 
> Amusingly, arch/arm64/kvm/pmu.c is nowhere to be seen in this list.
> I have no idea what this patch applies to, but that's neither 6.13, the current
> upstream, nor kvmarm/next.
Sorry for the mistake, the patch is based on Colton Lewis's series.
I?ll need to respin it if you're interested in the fix ?

> >  {
> >  	struct arm_pmu_entry *entry;
> >
> > +	/*
> > +	 * Prevent unintended behavior where KVM is not available or not
> > +	 * successfully initialised, e.g., kernel is landed in EL1.
> 
> Same comment here.
> 
> > +	 */
> > +	if (!is_kvm_arm_initialised())
> 
> This is definitely the wrong thing to check for, as it relies on the probe
> ordering between the PMU drivers and KVM. Relying on that is not
> acceptable.
> 
Indeed, would is_hyp_mode_available() be a proper replacement for
is_kvm_arm_initialised() here?
Or should we add a prevention condition in host_data_ptr instead?

> If you're worried about a kernel booted at EL1, then check for that.
> 

--- 
Cheers,
Justin He(Jia He)



From Markus.Elfring at web.de  Sat Mar 22 06:54:52 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 14:54:52 +0100
Subject: [PATCH] wifi: mt76: mt7996: avoid null deref in mt7996_stop_phy()
In-Reply-To: <20250322111354.23800-1-qasdev00@gmail.com>
References: <20250322111354.23800-1-qasdev00@gmail.com>
Message-ID: <d220d52e-f656-4d4c-bf28-1ab40879c93e@web.de>

> In mt7996_stop_phy() the mt7996_phy structure is
> dereferenced before the null sanity check which could
> lead to a null deref.
>
> Fix by moving the dereference operation after the
> sanity check.

* You may occasionally put more than 53 characters into text lines
  of such a change description.

* Would you like to use the term ?null pointer dereference? consistently?

* Were any known source code analysis tools involved also for
  this software improvement?


Regards,
Markus


From qasdev00 at gmail.com  Sat Mar 22 07:19:10 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sat, 22 Mar 2025 14:19:10 +0000
Subject: [PATCH] wifi: mt76: mt7996: avoid potential null deref in mt7996_get_et_stats()
Message-ID: <20250322141910.4461-1-qasdev00@gmail.com>

Ensure phy->mib is only accessed after the null sanity check for phy
otherwise the code may trigger a potential null deref.

Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 88e013577c0d..19391966ee3e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1875,7 +1875,7 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw,
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
-	struct mt76_mib_stats *mib = &phy->mib;
+	struct mt76_mib_stats *mib;
 	struct mt76_ethtool_worker_info wi = {
 		.data = data,
 		.idx = mvif->deflink.mt76.idx,
@@ -1886,6 +1886,8 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw,
 	if (!phy)
 		return;
 
+	mib = &phy->mib;
+	
 	mutex_lock(&dev->mt76.mutex);
 
 	mt7996_mac_update_stats(phy);
-- 
2.39.5



From maz at kernel.org  Sat Mar 22 07:21:55 2025
From: maz at kernel.org (Marc Zyngier)
Date: Sat, 22 Mar 2025 14:21:55 +0000
Subject: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when KVM is not initialised
In-Reply-To: <GV2PR08MB920679CA30617D465B69D79DF7DA2@GV2PR08MB9206.eurprd08.prod.outlook.com>
References: <20250322035115.118048-1-justin.he@arm.com>
	<867c4hml8v.wl-maz@kernel.org>
	<GV2PR08MB920679CA30617D465B69D79DF7DA2@GV2PR08MB9206.eurprd08.prod.outlook.com>
Message-ID: <87bjttqh6k.wl-maz@kernel.org>

On Sat, 22 Mar 2025 13:54:17 +0000,
Justin He <Justin.He at arm.com> wrote:
> 
> Hi Marc,
> 
> > -----Original Message-----
> > From: Marc Zyngier <maz at kernel.org>
> > Sent: Saturday, March 22, 2025 6:08 PM
> > To: Justin He <Justin.He at arm.com>
> > Cc: Oliver Upton <oliver.upton at linux.dev>; linux-arm-
> > kernel at lists.infradead.org; kvmarm at lists.linux.dev; Joey Gouly
> > <Joey.Gouly at arm.com>; Suzuki Poulose <Suzuki.Poulose at arm.com>;
> > Zenghui Yu <yuzenghui at huawei.com>; Catalin Marinas
> > <Catalin.Marinas at arm.com>; Will Deacon <will at kernel.org>; linux-
> > kernel at vger.kernel.org
> > Subject: Re: [PATCH] KVM: arm64: pmu: Avoid initializing KVM PMU when
> > KVM is not initialised
> > 
> > On Sat, 22 Mar 2025 03:51:15 +0000,
> > Jia He <justin.he at arm.com> wrote:
> > >
> > > Currently, `kvm_host_pmu_init()` does not check if KVM has been
> > > successfully initialized before proceeding. This can lead to
> > > unintended behavior if the function is called in an environment where
> > > KVM is not
> > 
> > Which unintended behaviour? Other than the pointless allocation of a tiny
> > amount of memory? Does anything really go wrong?
> > 
> Sorry for the confusion --- I should explain more clearly.
> I noticed the usage of host_data_ptr in Colton Lewis's RFC patch [1]. After
> applying the patch, the guest VM fails to boot.Upon investigating the root
> cause, I found that host_data_ptr can trigger a kernel panic if KVM is not
> initialized.

How relevant is this for upstream?

> 
> [1] https://patchwork.kernel.org/project/kvm/patch/20250213180317.3205285-6-coltonlewis at google.com/
> > > available, e.g., kernel is landed in EL1.
> > 
> > s/landed in/booted from/
> > 
> > >
> > > Signed-off-by: Jia He <justin.he at arm.com>
> > > ---
> > >  arch/arm64/kvm/pmu.c | 7 +++++++
> > >  1 file changed, 7 insertions(+)
> > >
> > > diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c index
> > > 7169c1a24dd6..e39c48d12b81 100644
> > > --- a/arch/arm64/kvm/pmu.c
> > > +++ b/arch/arm64/kvm/pmu.c
> > > @@ -227,6 +227,13 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
> > 
> > Huh:
> > 
> > maz at valley-girl:~/hot-poop/arm-platforms$ git grep -l kvm_host_pmu_init
> > arch/arm64/kvm/pmu-emul.c drivers/perf/arm_pmu.c
> > include/linux/perf/arm_pmu.h
> > 
> > Amusingly, arch/arm64/kvm/pmu.c is nowhere to be seen in this list.
> > I have no idea what this patch applies to, but that's neither 6.13, the current
> > upstream, nor kvmarm/next.
> Sorry for the mistake, the patch is based on Colton Lewis's series.
> I?ll need to respin it if you're interested in the fix ?

I'm interested in a patch if:

- the patch applies to an upstream or a kvmarm tag
- the patch fixes *something* in the upstream code
- the commit message accurately describes the problem

Otherwise, no, thank you.

> > >  {
> > >  	struct arm_pmu_entry *entry;
> > >
> > > +	/*
> > > +	 * Prevent unintended behavior where KVM is not available or not
> > > +	 * successfully initialised, e.g., kernel is landed in EL1.
> > 
> > Same comment here.
> > 
> > > +	 */
> > > +	if (!is_kvm_arm_initialised())
> > 
> > This is definitely the wrong thing to check for, as it relies on the probe
> > ordering between the PMU drivers and KVM. Relying on that is not
> > acceptable.
> > 
> Indeed, would is_hyp_mode_available() be a proper replacement for
> is_kvm_arm_initialised() here?

Looks more appropriate, at least for upstream.
> Or should we add a prevention condition in host_data_ptr instead?

I can't comment about a series that I haven't reviewed and that is not
yet targeting upstream. But using host_data_ptr() from outside of KVM
is plain wrong, as it falls into the same trap as above. Checking for
random init flags is not going to help with that.

Instead of posting random patches that make no sense for upstream, why
don't you instead reply to Colton's series outlining your concerns and
findings? It sounds to me like a more useful way to make progress.

	M.

-- 
Without deviation from the norm, progress is not possible.


From linux at roeck-us.net  Sat Mar 22 07:33:27 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Sat, 22 Mar 2025 07:33:27 -0700
Subject: [PATCH v2 08/12] lib/crc_kunit.c: add KUnit test suite for CRC
 library functions
In-Reply-To: <20241202012056.209768-9-ebiggers@kernel.org>
References: <20241202012056.209768-1-ebiggers@kernel.org>
 <20241202012056.209768-9-ebiggers@kernel.org>
Message-ID: <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net>

Hi,

On Sun, Dec 01, 2024 at 05:20:52PM -0800, Eric Biggers wrote:
> From: Eric Biggers <ebiggers at google.com>
> 
> Add a KUnit test suite for the crc16, crc_t10dif, crc32_le, crc32_be,
> crc32c, and crc64_be library functions.  It avoids code duplication by
> sharing most logic among all CRC variants.  The test suite includes:
> 
> - Differential fuzz test of each CRC function against a simple
>   bit-at-a-time reference implementation.
> - Test for CRC combination, when implemented by a CRC variant.
> - Optional benchmark of each CRC function with various data lengths.
> 
> This is intended as a replacement for crc32test and crc16_kunit, as well
> as a new test for CRC variants which didn't previously have a test.
> 
> Reviewed-by: Ard Biesheuvel <ardb at kernel.org>
> Reviewed-by: Martin K. Petersen <martin.petersen at oracle.com>
> Cc: Vinicius Peixoto <vpeixoto at lkcamp.dev>
> Signed-off-by: Eric Biggers <ebiggers at google.com>
> ---
...
> +
> +		nosimd = rand32() % 8 == 0;
> +
> +		/*
> +		 * Compute the CRC, and verify that it equals the CRC computed
> +		 * by a simple bit-at-a-time reference implementation.
> +		 */
> +		expected_crc = crc_ref(v, init_crc, &test_buffer[offset], len);
> +		if (nosimd)
> +			local_irq_disable();
> +		actual_crc = v->func(init_crc, &test_buffer[offset], len);
> +		if (nosimd)
> +			local_irq_enable();

This triggers a traceback on some arm systems.

[    7.810000]     ok 2 crc16_benchmark # SKIP not enabled
[    7.810000] ------------[ cut here ]------------
[    7.810000] WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
[    7.810000] Modules linked in:
[    7.810000] CPU: 0 UID: 0 PID: 1145 Comm: kunit_try_catch Tainted: G                 N 6.14.0-rc7-00196-g88d324e69ea9 #1
[    7.810000] Tainted: [N]=TEST
[    7.810000] Hardware name: NPCM7XX Chip family
[    7.810000] Call trace:
[    7.810000]  unwind_backtrace from show_stack+0x10/0x14
[    7.810000]  show_stack from dump_stack_lvl+0x7c/0xac
[    7.810000]  dump_stack_lvl from __warn+0x7c/0x1b8
[    7.810000]  __warn from warn_slowpath_fmt+0x19c/0x1a4
[    7.810000]  warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
[    7.810000]  __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
[    7.810000]  crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
[    7.810000]  crc_t10dif_wrapper from crc_main_test+0x178/0x360
[    7.810000]  crc_main_test from kunit_try_run_case+0x78/0x1e0
[    7.810000]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
[    7.810000]  kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
[    7.810000]  kthread from ret_from_fork+0x14/0x28
[    7.810000] Exception stack(0xe3651fb0 to 0xe3651ff8)
[    7.810000] 1fa0:                                     00000000 00000000 00000000 00000000
[    7.810000] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    7.810000] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[    7.810000] irq event stamp: 29
[    7.810000] hardirqs last  enabled at (27): [<c037875c>] __local_bh_enable_ip+0xb4/0x194
[    7.810000] hardirqs last disabled at (28): [<c0b09684>] crc_main_test+0x2e4/0x360
[    7.810000] softirqs last  enabled at (26): [<c032a3ac>] kernel_neon_end+0x0/0x1c
[    7.810000] softirqs last disabled at (29): [<c032a3c8>] kernel_neon_begin+0x0/0x70
[    7.810000] ---[ end trace 0000000000000000 ]---
[    8.050000]     # crc_t10dif_test: pass:1 fail:0 skip:0 total:1

kernel_neon_end() calls local_bh_enable() which apparently conflicts with
the local_irq_disable() in above code.

Guenter


From Markus.Elfring at web.de  Sat Mar 22 07:55:49 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 22 Mar 2025 15:55:49 +0100
Subject: [PATCH] wifi: mt76: mt7996: avoid potential null deref in
 mt7996_get_et_stats()
In-Reply-To: <20250322141910.4461-1-qasdev00@gmail.com>
References: <20250322141910.4461-1-qasdev00@gmail.com>
Message-ID: <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>

> Ensure phy->mib is only accessed after the null sanity check for phy
> otherwise the code may trigger a potential null deref.

* Would you like to use the term ?null pointer dereference? consistently?

* Were any known source code analysis tools involved also for
  this software improvement?


?
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
?
> @@ -1886,6 +1886,8 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw,
>  	if (!phy)
>  		return;
>
> +	mib = &phy->mib;
> +
>  	mutex_lock(&dev->mt76.mutex);
>
>  	mt7996_mac_update_stats(phy);

I suggest to move such an assignment statement directly before the place
where this variable is used finally.

Regards,
Markus


From abrahamadekunle50 at gmail.com  Sat Mar 22 08:36:53 2025
From: abrahamadekunle50 at gmail.com (Abraham Samuel Adekunle)
Date: Sat, 22 Mar 2025 16:36:53 +0100
Subject: [PATCH v2] staging: bcm2835-camera: Modify function call formatting
Message-ID: <Z97ZFURPvDcTkjjf@HP-650>

The line is a function call which ends with an opening parenthesis
thereby not adhering to the Linux kernel coding style.

Modify the function call to include parameters on the same line as
the opening parenthesis to improve readability and consistency while
adhering to Linux coding styles.

Reported by checkpatch:

CHECK: Lines should not end with '('

Signed-off-by: Abraham Samuel Adekunle <abrahamadekunle50 at gmail.com>
---
Changes in v2:
	- Add more patch recipients.

 .../vc04_services/bcm2835-camera/controls.c        | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/vc04_services/bcm2835-camera/controls.c b/drivers/staging/vc04_services/bcm2835-camera/controls.c
index 6bce45925bf1..e670226f1edf 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
@@ -533,17 +533,15 @@ static int ctrl_set_image_effect(struct bcm2835_mmal_dev *dev,

 		control = &dev->component[COMP_CAMERA]->control;

-		ret = vchiq_mmal_port_parameter_set(
-				dev->instance, control,
-				MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
-				&imagefx, sizeof(imagefx));
+		ret = vchiq_mmal_port_parameter_set(dev->instance, control,
+						    MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
+						    &imagefx, sizeof(imagefx));
 		if (ret)
 			goto exit;

-		ret = vchiq_mmal_port_parameter_set(
-				dev->instance, control,
-				MMAL_PARAMETER_COLOUR_EFFECT,
-				&dev->colourfx, sizeof(dev->colourfx));
+		ret = vchiq_mmal_port_parameter_set(dev->instance, control,
+						    MMAL_PARAMETER_COLOUR_EFFECT,
+						    &dev->colourfx, sizeof(dev->colourfx));
 	}

 exit:
--
2.34.1



From johannes at sipsolutions.net  Sat Mar 22 08:54:41 2025
From: johannes at sipsolutions.net (Johannes Berg)
Date: Sat, 22 Mar 2025 16:54:41 +0100
Subject: [PATCH] wifi: mt76: mt7996: avoid potential null deref in
 mt7996_get_et_stats()
In-Reply-To: <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
References: <20250322141910.4461-1-qasdev00@gmail.com>
	 <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
Message-ID: <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>

On Sat, 2025-03-22 at 15:55 +0100, Markus Elfring wrote:
> > Ensure phy->mib is only accessed after the null sanity check for phy
> > otherwise the code may trigger a potential null deref.
> 
> * Would you like to use the term ?null pointer dereference? consistently?
> 
> * Were any known source code analysis tools involved also for
> ??this software improvement?
> 

Do you really have to double down? STOP. You're just wasting everyone's
time.

johannes


From wiagn233 at outlook.com  Sat Mar 22 09:32:35 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Sun, 23 Mar 2025 00:32:35 +0800
Subject: [PATCH v3] mt76: mt7915: wed: find rx token by physical address
Message-ID: <TYCPR01MB8437AFFB5560D622C8EB017B98DA2@TYCPR01MB8437.jpnprd01.prod.outlook.com>

The token id in RxDMAD may be incorrect when it is not the last frame
due to WED HW bug. Lookup correct token id by physical address in sdp0.

Downstream patch link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/737340322ab22b138fd200e020d61ffdbe3e36a9/autobuild/autobuild_5.4_mac80211_release/mt7988_wifi7_mac80211_mlo/package/kernel/mt76/patches/0062-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch

Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
---
Changes since v1:
 - Reordered code sequence to reversed Xmas tree order
 - Renamed some variables
Changes since v2:
 - Assigning true to variable "found" instead of 1
---
 drivers/net/wireless/mediatek/mt76/dma.c | 26 +++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 844af16ee5513..d5649c52c669a 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -445,8 +445,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
 
 	if (mt76_queue_is_wed_rx(q)) {
 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
-		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
+		struct mt76_txwi_cache *t;
+		bool found = false;
+		u32 id;
+
+		if (*more) {
+			spin_lock_bh(&dev->rx_token_lock);
+
+			idr_for_each_entry(&dev->rx_token, t, id) {
+				if (t->dma_addr == le32_to_cpu(desc->buf0)) {
+					token = id;
+					found = true;
+
+					/* Write correct id back to DMA*/
+					u32p_replace_bits(&buf1, id,
+							  MT_DMA_CTL_TOKEN);
+					WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+					break;
+				}
+			}
+
+			spin_unlock_bh(&dev->rx_token_lock);
+			if (!found)
+				return NULL;
+		}
 
+		t = mt76_rx_token_release(dev, token);
 		if (!t)
 			return NULL;
 
-- 
2.49.0



From wiagn233 at outlook.com  Sat Mar 22 09:34:24 2025
From: wiagn233 at outlook.com (Shengyu Qu)
Date: Sun, 23 Mar 2025 00:34:24 +0800
Subject: [PATCH v10] wifi: mt76: mt7915: add wds support when wed is
 enabled
In-Reply-To: <TYCPR01MB84376878FE505F773182062B98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
References: <TYCPR01MB84376878FE505F773182062B98D12@TYCPR01MB8437.jpnprd01.prod.outlook.com>
Message-ID: <TYCPR01MB84373C301DD3430A00E9779D98DA2@TYCPR01MB8437.jpnprd01.prod.outlook.com>

Hi Felix,

Do you think this patch is ok?

Best regards,
Shengyu

? 2025/3/11 13:29, Shengyu Qu ??:
> The current WED only supports 256 wcid, whereas mt7986 can support up to
> 512 entries, so firmware provides a rule to get sta_info by DA when wcid
> is set to 0x3ff by txd. Also, WED provides a register to overwrite txd
> wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set
> to 0xff by host driver.
> 
> However, firmware is unable to get sta_info from DA as DA != RA for
> 4addr cases, so firmware and wifi host driver both use wcid (256 - 271)
> and (768 ~ 783) for sync up to get correct sta_info.
> 
> Currently WDS+WED config is completely broken on MT7986/7981 devices if
> without this patch.
> 
> Tested-by: Sujuan Chen <sujuan.chen at mediatek.com>
> Co-developed-by: Bo Jiao <bo.jiao at mediatek.com>
> Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
> Signed-off-by: Sujuan Chen <sujuan.chen at mediatek.com>
> Signed-off-by: Shengyu Qu <wiagn233 at outlook.com>
> ---
> Changes since v1:
>   - Drop duplicate setting in mmio
>   - Reduce the patch size by redefining mt76_wcid_alloc
> Changes since v2:
>   - Rework wds wcid getting flow
> Changes since v3:
>   - Rebase to next-20240703
>   - Sync with downstream patch
> Changes since v4:
>   - Rebase to next-20240802
> Changes since v5:
>   - Fixed build test error reported by robot
>   - Rebase to next-20240805
> Changes since v6:
>   - Fix potential race conditions on tx/rx packets during the transition
>   - Rebase to Felix's newest codebase
> Changes since v7:
>   - Fix build fail
> Changes since v8:
>   - Changed code as Shih advised
> Changes since v9:
>   - Changed code as Shih advised
>   - Moved mt76_wcid_alloc to mt76.h
> ---
>   drivers/net/wireless/mediatek/mt76/mt76.h     | 15 ++++++
>   .../net/wireless/mediatek/mt76/mt7915/main.c  | 53 +++++++++++++++++--
>   .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 18 +++++--
>   .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  1 +
>   drivers/net/wireless/mediatek/mt76/util.c     | 37 +++++++++++--
>   drivers/net/wireless/mediatek/mt76/util.h     |  2 +-
>   6 files changed, 115 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 132148f7b107..f9f11ce1f3fc 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -28,6 +28,9 @@
>   
>   #define MT76_TOKEN_FREE_THR	64
>   
> +#define MT76_WED_WDS_MIN    256
> +#define MT76_WED_WDS_MAX    272
> +
>   #define MT_QFLAG_WED_RING	GENMASK(1, 0)
>   #define MT_QFLAG_WED_TYPE	GENMASK(4, 2)
>   #define MT_QFLAG_WED		BIT(5)
> @@ -73,6 +76,12 @@ enum mt76_wed_type {
>   	MT76_WED_RRO_Q_IND,
>   };
>   
> +enum mt76_wed_state {
> +	MT76_WED_DEFAULT,
> +	MT76_WED_ACTIVE,
> +	MT76_WED_WDS_ACTIVE,
> +};
> +
>   struct mt76_bus_ops {
>   	u32 (*rr)(struct mt76_dev *dev, u32 offset);
>   	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
> @@ -1165,6 +1174,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev);
>   int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>   			  struct net_device *netdev, enum tc_setup_type type,
>   			  void *type_data);
> +
> +static inline int mt76_wcid_alloc(u32 *mask, int size)
> +{
> +	return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT);
> +}
> +
>   #ifdef CONFIG_NET_MEDIATEK_SOC_WED
>   u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
>   int mt76_wed_offload_enable(struct mtk_wed_device *wed);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> index 3aa31c5cefa6..fcbf4f971026 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>   	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
>   	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
>   	bool ext_phy = mvif->phy != &dev->phy;
> +	u8 flags = MT76_WED_DEFAULT;
>   	int idx;
>   
> -	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> +	    !is_mt7915(&dev->mt76)) {
> +		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
> +		       MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
> +	}
> +
> +	idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
>   	if (idx < 0)
>   		return -ENOSPC;
>   
> @@ -1271,6 +1278,11 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>   {
>   	struct mt7915_dev *dev = mt7915_hw_dev(hw);
>   	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
> +	int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
> +	struct ieee80211_sta *pre_sta;
> +	struct mt7915_sta *pre_msta;
> +	u8 flags = MT76_WED_DEFAULT;
> +	int tmp_idx;
>   
>   	if (enabled)
>   		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
> @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
>   	if (!msta->wcid.sta)
>   		return;
>   
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> +	    !is_mt7915(&dev->mt76) &&
> +	    (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
> +		pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO);
> +		if (!pre_sta)
> +			goto error_alloc;
> +		pre_msta = (struct mt7915_sta *)pre_sta->drv_priv;
> +
> +		flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
> +			MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
> +
> +		tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags);
> +		if (tmp_idx < 0)
> +			goto error_wcid;
> +		pre_msta->wcid.idx = (u16)tmp_idx;
> +		mt7915_mac_sta_add(&dev->mt76, vif, pre_sta);
> +		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid);
> +
> +		tmp_idx = msta->wcid.idx;
> +		msta->wcid.idx = pre_msta->wcid.idx;
> +		pre_msta->wcid.idx = (u16)tmp_idx;
> +		rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL);
> +
> +		synchronize_rcu();
> +		mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta);
> +
> +error_wcid:
> +		kfree(pre_sta);
> +	}
> +
> +error_alloc:
>   	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
>   }
>   
> @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
>   	if (!mtk_wed_device_active(wed))
>   		return -ENODEV;
>   
> -	if (msta->wcid.idx > 0xff)
> +	if (msta->wcid.idx > MT7915_WTBL_STA)
>   		return -EIO;
>   
>   	path->type = DEV_PATH_MTK_WDMA;
>   	path->dev = ctx->dev;
>   	path->mtk_wdma.wdma_idx = wed->wdma_idx;
>   	path->mtk_wdma.bss = mvif->mt76.idx;
> -	path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
>   	path->mtk_wdma.queue = phy != &dev->phy;
> +	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ||
> +	    is_mt7915(&dev->mt76))
> +		path->mtk_wdma.wcid = msta->wcid.idx;
> +	else
> +		path->mtk_wdma.wcid = 0x3ff;
>   
>   	ctx->dev = NULL;
>   
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> index 9d790f234e82..191f966c3f32 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> @@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
>   
>   	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
>   
> -	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> -	     is_mt7915(&dev->mt76)) ||
> -	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
> -		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
> +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
> +	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
> +		if (is_mt7915(&dev->mt76) ||
> +		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
> +						0, 0, 0);
> +		else
> +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
> +						MCU_WA_PARAM_WED_VERSION,
> +						dev->mt76.mmio.wed.rev_id, 0);
> +		if (ret)
> +			return ret;
> +	}
> +#endif
>   
>   	ret = mt7915_mcu_set_mwds(dev, 1);
>   	if (ret)
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> index 49476a4182fd..c3dd0cb4a5d3 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> @@ -278,6 +278,7 @@ enum {
>   	MCU_WA_PARAM_PDMA_RX = 0x04,
>   	MCU_WA_PARAM_CPU_UTIL = 0x0b,
>   	MCU_WA_PARAM_RED = 0x0e,
> +	MCU_WA_PARAM_WED_VERSION = 0x32,
>   	MCU_WA_PARAM_RED_SETTING = 0x40,
>   };
>   
> diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
> index 95b3dc96e4c4..e80bef2b33a1 100644
> --- a/drivers/net/wireless/mediatek/mt76/util.c
> +++ b/drivers/net/wireless/mediatek/mt76/util.c
> @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
>   }
>   EXPORT_SYMBOL_GPL(____mt76_poll_msec);
>   
> -int mt76_wcid_alloc(u32 *mask, int size)
> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag)
>   {
> +	int max = MT76_WED_WDS_MAX;
> +	int min = MT76_WED_WDS_MIN;
>   	int i, idx = 0, cur;
>   
>   	for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
> @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size)
>   
>   		idx--;
>   		cur = i * 32 + idx;
> -		if (cur >= size)
> +
> +		switch (flag) {
> +		case MT76_WED_ACTIVE:
> +			if (cur >= min && cur < max)
> +				continue;
> +
> +			if (cur >= size) {
> +				u32 end = max - min - 1;
> +
> +				i = min / 32;
> +				idx = ffs(~mask[i] & GENMASK(end, 0));
> +				if (!idx)
> +					goto error;
> +				idx--;
> +				cur = min + idx;
> +			}
> +
>   			break;
> +		case MT76_WED_WDS_ACTIVE:
> +			if (cur < min)
> +				continue;
> +			if (cur >= max)
> +				goto error;
> +
> +			break;
> +		default:
> +			if (cur >= size)
> +				goto error;
> +			break;
> +		}
>   
>   		mask[i] |= BIT(idx);
>   		return cur;
>   	}
>   
> +error:
>   	return -1;
>   }
> -EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
> +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc);
>   
>   int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
>   {
> diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
> index 260965dde94c..fe95a847182e 100644
> --- a/drivers/net/wireless/mediatek/mt76/util.h
> +++ b/drivers/net/wireless/mediatek/mt76/util.h
> @@ -27,7 +27,7 @@ enum {
>   #define MT76_INCR(_var, _size) \
>   	(_var = (((_var) + 1) % (_size)))
>   
> -int mt76_wcid_alloc(u32 *mask, int size);
> +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags);
>   
>   static inline void
>   mt76_wcid_mask_set(u32 *mask, int idx)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE3520CC91929C8E7.asc
Type: application/pgp-keys
Size: 6868 bytes
Desc: OpenPGP public key
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250323/da79581a/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250323/da79581a/attachment.sig>

From adrian.larumbe at collabora.com  Sat Mar 22 11:30:13 2025
From: adrian.larumbe at collabora.com (Adrian Larumbe)
Date: Sat, 22 Mar 2025 18:30:13 +0000
Subject: [PATCH v4 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250317145245.910566-2-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
 <20250317145245.910566-2-ariel.dalessandro@collabora.com>
Message-ID: <7qixyvz7ll7sk53vqys74kncf6advxcuctfymmve7msygekygg@vwxzowjwm5bz>

On 17.03.2025 11:52, Ariel D'Alessandro wrote:
> Panfrost does not support uncached mappings, so flag them properly. Also
> flag the pages that are mapped as response to a page fault as cached.
>
> Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> Reviewed-by: Steven Price <steven.price at arm.com>

Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index b91019cd5acb1..9e6f198ef5c1b 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
>  	struct drm_gem_object *obj = &shmem->base;
>  	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
>  	struct sg_table *sgt;
> -	int prot = IOMMU_READ | IOMMU_WRITE;
> +	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
>
>  	if (WARN_ON(mapping->active))
>  		return 0;
> @@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
>  		goto err_map;
>
>  	mmu_map_sg(pfdev, bomapping->mmu, addr,
> -		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
> +		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
>
>  	bomapping->active = true;
>  	bo->heap_rss_size += SZ_2M;
> --
> 2.47.2


Adrian Larumbe


From adrian.larumbe at collabora.com  Sat Mar 22 11:31:03 2025
From: adrian.larumbe at collabora.com (Adrian Larumbe)
Date: Sat, 22 Mar 2025 18:31:03 +0000
Subject: [PATCH v4 2/6] drm/panfrost: Use
 GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250317145245.910566-3-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
 <20250317145245.910566-3-ariel.dalessandro@collabora.com>
Message-ID: <ebm6kwkhyiql2kh3ekyfpyvchs3mbnbq26ssvpkttxjuw5meo2@gqggqnosvou6>

On 17.03.2025 11:52, Ariel D'Alessandro wrote:
> As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
> which makes code easier to read and reuse.
>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
> Reviewed-by: Steven Price <steven.price at arm.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
>  drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
>  2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 9e6f198ef5c1b..294f86b3c25e7 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
>
>  struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  {
> +	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
> +	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
>  	struct panfrost_mmu *mmu;
>
>  	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
> @@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>
>  	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
>  		.pgsize_bitmap	= SZ_4K | SZ_2M,
> -		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
> -		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
> +		.ias		= va_bits,
> +		.oas		= pa_bits,
>  		.coherent_walk	= pfdev->coherent,
>  		.tlb		= &mmu_tlb_ops,
>  		.iommu_dev	= pfdev->dev,
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index c7bba476ab3f3..b5f279a19a084 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -16,6 +16,8 @@
>  #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
>
>  #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
> +#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
> +#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
>  #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
>  #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
>
> --
> 2.47.2


Adrian Larumbe


From adrian.larumbe at collabora.com  Sat Mar 22 11:37:15 2025
From: adrian.larumbe at collabora.com (Adrian Larumbe)
Date: Sat, 22 Mar 2025 18:37:15 +0000
Subject: [PATCH v4 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature
 flag on Bifrost models
In-Reply-To: <20250317145245.910566-4-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
 <20250317145245.910566-4-ariel.dalessandro@collabora.com>
Message-ID: <rocdajh3msvq2mesaftg4garbdxl4qn77kxpqhwn4pv2wncc45@x7iejre6y3kb>

On 17.03.2025 11:52, Ariel D'Alessandro wrote:
> Set this feature flag on all Mali Bifrost platforms as the MMU supports
> AARCH64 4K page table format.
>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
> Reviewed-by: Steven Price <steven.price at arm.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>

Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>

> ---
>  drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
> index 7ed0cd3ea2d4c..52f9d69f6db9d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_features.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_features.h
> @@ -54,6 +54,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>
>  #define hw_features_g72 (\
> @@ -64,6 +65,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>
>  #define hw_features_g51 hw_features_g72
> @@ -77,6 +79,7 @@ enum panfrost_hw_feature {
>  	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
>  	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
>  	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
> +	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
>  	BIT_ULL(HW_FEATURE_COHERENCY_REG))
>
>  #define hw_features_g76 (\
> --
> 2.47.2


Adrian Larumbe


From csokas.bence at prolan.hu  Sat Mar 22 11:46:07 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Sat, 22 Mar 2025 19:46:07 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250311180254.149484-1-csokas.bence@prolan.hu>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
Message-ID: <f0a82f7a-806e-4dde-a870-f5d76df61984@prolan.hu>

Hi all,

On 2025. 03. 11. 19:02, Bence Cs?k?s wrote:
> Clean up error handling by using devm functions
> and dev_err_probe(). This should make it easier
> to add new code, as we can eliminate the "goto
> ladder" in probe().
> 
> Suggested-by: Chen-Yu Tsai <wens at kernel.org>
> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Acked-by: Chen-Yu Tsai <wens at csie.org>
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>

So, will this be merged for the MW of 6.15? I just looked at the history 
of this patch, and there haven't been any major changes since v1, which 
was sent on 8 Dec last year. Despite this, it didn't make it into 6.14, 
probably because it was forgot amid the MW rush, so now I'm anxious as 
to whether it will happen again.

Bence



From adrian.larumbe at collabora.com  Sat Mar 22 11:48:12 2025
From: adrian.larumbe at collabora.com (Adrian Larumbe)
Date: Sat, 22 Mar 2025 18:48:12 +0000
Subject: [PATCH v4 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <20250317145245.910566-5-ariel.dalessandro@collabora.com>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
 <20250317145245.910566-5-ariel.dalessandro@collabora.com>
Message-ID: <5hl2ahnxeunqebenguxjwwie6ura3lxknu766xthov2m4qvsot@imrrfqftlmv4>

On 17.03.2025 11:52, Ariel D'Alessandro wrote:
> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
> Address Extension", which in Linux we've called "mali_lpae".
>
> This commit adds support for conditionally enabling AARCH64_4K page
> table format. To achieve that, a "GPU optional quirks" field was added
> to `struct panfrost_features` with the related flag.
>
> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
> the HW_FEATURE_AARCH64_MMU feature flag present.
>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
> ---
>  drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>  drivers/gpu/drm/panfrost/panfrost_mmu.c    | 140 +++++++++++++++++++--
>  drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 +++++
>  3 files changed, 183 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> index cffcb0ac7c111..ad95f2ed31d9a 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
>  	GPU_PM_VREG_OFF,
>  };
>
> +/**
> + * enum panfrost_gpu_quirks - GPU optional quirks
> + * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
> + */
> +enum panfrost_gpu_quirks {
> +	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
> +};
> +
>  struct panfrost_features {
>  	u16 id;
>  	u16 revision;
> @@ -95,6 +103,9 @@ struct panfrost_compatible {
>
>  	/* Allowed PM features */
>  	u8 pm_features;
> +
> +	/* GPU configuration quirks */
> +	u8 gpu_quirks;
>  };
>
>  struct panfrost_device {
> @@ -162,6 +173,11 @@ struct panfrost_mmu {
>  	int as;
>  	atomic_t as_count;
>  	struct list_head list;
> +	struct {
> +		u64 transtab;
> +		u64 memattr;
> +		u64 transcfg;
> +	} cfg;
>  };
>
>  struct panfrost_engine_usage {
> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> index 294f86b3c25e7..506f42ccfd5fc 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
> @@ -26,6 +26,48 @@
>  #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
>  #define mmu_read(dev, reg) readl(dev->iomem + reg)
>
> +static u64 mair_to_memattr(u64 mair, bool coherent)
> +{
> +	u64 memattr = 0;
> +	u32 i;
> +
> +	for (i = 0; i < 8; i++) {
> +		u8 in_attr = mair >> (8 * i), out_attr;
> +		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
> +
> +		/* For caching to be enabled, inner and outer caching policy
> +		 * have to be both write-back, if one of them is write-through
> +		 * or non-cacheable, we just choose non-cacheable. Device
> +		 * memory is also translated to non-cacheable.
> +		 */
> +		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
> +				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
> +		} else {
> +			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
> +				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
> +			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
> +			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
> +			 * to Mali's internal-shareable mode. As per the Mali
> +			 * Spec, inner and outer-shareable modes aren't allowed
> +			 * for WB memory when coherency is disabled.
> +			 * Use SH_CPU_INNER mode when coherency is enabled, so
> +			 * that SH_IS actually maps to the standard definition of
> +			 * inner-shareable.
> +			 */
> +			if (!coherent)
> +				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
> +			else
> +				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
> +		}
> +
> +		memattr |= (u64)out_attr << (8 * i);
> +	}
> +
> +	return memattr;
> +}
> +
>  static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
>  {
>  	int ret;
> @@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
>  static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
>  	int as_nr = mmu->as;
> -	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
> -	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
> -	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
> +	u64 transtab = mmu->cfg.transtab;
> +	u64 memattr = mmu->cfg.memattr;
> +	u64 transcfg = mmu->cfg.transcfg;
>
>  	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
>
> @@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
>
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
> +
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>  }
>
> @@ -152,9 +197,67 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
>  	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
>  	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
>
> +	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
> +	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
> +
>  	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
>  }
>
> +static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +
> +	/* TODO: The following fields are duplicated between the MMU and Page
> +	 * Table config structs. Ideally, should be kept in one place.
> +	 */
> +	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
> +	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
> +	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
> +
> +	return 0;
> +}
> +
> +static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
> +{
> +	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
> +				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
> +		return -EINVAL;
> +
> +	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> +
> +	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
> +					   pgtbl_cfg->coherent_walk);
> +
> +	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
> +			    AS_TRANSCFG_PTW_RA |
> +			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
> +			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
> +	if (pgtbl_cfg->coherent_walk)
> +		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
> +
> +	return 0;
> +}
> +
> +static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
> +				  enum io_pgtable_fmt fmt)
> +{
> +	struct panfrost_device *pfdev = mmu->pfdev;
> +
> +	switch (fmt) {
> +	case ARM_64_LPAE_S1:
> +		return mmu_cfg_init_aarch64_4k(mmu);
> +	case ARM_MALI_LPAE:
> +		return mmu_cfg_init_mali_lpae(mmu);
> +	default:
> +		/* This should never happen */
> +		drm_WARN(pfdev->ddev, "Invalid pgtable format");

I think there's a '1' missing here before the string literal.
Other than that,

Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>

> +		return -EINVAL;
> +	}
> +}
> +
>  u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
>  {
>  	int as;
> @@ -618,6 +721,19 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
>  	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
>  	struct panfrost_mmu *mmu;
> +	enum io_pgtable_fmt fmt;
> +	int ret;
> +
> +	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
> +		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
> +			dev_err_once(pfdev->dev,
> +				     "AARCH64_4K page table not supported\n");
> +			return ERR_PTR(-EINVAL);
> +		}
> +		fmt = ARM_64_LPAE_S1;
> +	} else {
> +		fmt = ARM_MALI_LPAE;
> +	}
>
>  	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
>  	if (!mmu)
> @@ -642,16 +758,26 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
>  		.iommu_dev	= pfdev->dev,
>  	};
>
> -	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
> -					      mmu);
> +	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
>  	if (!mmu->pgtbl_ops) {
> -		kfree(mmu);
> -		return ERR_PTR(-EINVAL);
> +		ret = -EINVAL;
> +		goto err_free_mmu;
>  	}
>
> +	ret = panfrost_mmu_cfg_init(mmu, fmt);
> +	if (ret)
> +		goto err_free_io_pgtable;
> +
>  	kref_init(&mmu->refcount);
>
>  	return mmu;
> +
> +err_free_io_pgtable:
> +	free_io_pgtable_ops(mmu->pgtbl_ops);
> +
> +err_free_mmu:
> +	kfree(mmu);
> +	return ERR_PTR(ret);
>  }
>
>  static const char *access_type_name(struct panfrost_device *pfdev,
> diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
> index b5f279a19a084..2b8f1617b8369 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_regs.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
> @@ -301,6 +301,17 @@
>  #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
>  #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
>  #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
> +#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
> +							 ((w) ? BIT(0) : 0) | \
> +							 ((r) ? BIT(1) : 0))
> +#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
> +#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
> +#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
> +#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
> +#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
>  #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
>  #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
>  #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
> @@ -311,6 +322,24 @@
>  /* Additional Bifrost AS registers */
>  #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
>  #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
> +#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
> +#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
> +#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
> +#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
> +#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
> +#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
> +#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
> +#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
> +#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
> +#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
> +#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
> +#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
> +#define   AS_TRANSCFG_PTW_RA				BIT(30)
> +#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
> +#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
> +#define   AS_TRANSCFG_WXN				BIT(35)
> +#define   AS_TRANSCFG_XREADABLE				BIT(36)
>  #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
>  #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
>
> @@ -326,6 +355,11 @@
>  #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
>  #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
>
> +/*
> + * Begin AARCH64_4K MMU TRANSTAB register values
> + */
> +#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
> +
>  #define AS_STATUS_AS_ACTIVE			0x01
>
>  #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
> --
> 2.47.2


Adrian Larumbe


From rppt at kernel.org  Sat Mar 22 12:12:26 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Sat, 22 Mar 2025 15:12:26 -0400
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <20250321134629.GA252045@nvidia.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-10-changyuanl@google.com>
 <20250321134629.GA252045@nvidia.com>
Message-ID: <Z98Lmo50h5RboFXq@kernel.org>

On Fri, Mar 21, 2025 at 10:46:29AM -0300, Jason Gunthorpe wrote:
> On Wed, Mar 19, 2025 at 06:55:44PM -0700, Changyuan Lyu wrote:
> >
> > +static void deserialize_bitmap(unsigned int order,
> > +			       struct khoser_mem_bitmap_ptr *elm)
> > +{
> > +	struct kho_mem_phys_bits *bitmap = KHOSER_LOAD_PTR(elm->bitmap);
> > +	unsigned long bit;
> > +
> > +	for_each_set_bit(bit, bitmap->preserve, PRESERVE_BITS) {
> > +		int sz = 1 << (order + PAGE_SHIFT);
> > +		phys_addr_t phys =
> > +			elm->phys_start + (bit << (order + PAGE_SHIFT));
> > +		struct page *page = phys_to_page(phys);
> > +
> > +		memblock_reserve(phys, sz);
> > +		memblock_reserved_mark_noinit(phys, sz);
> 
> Mike asked about this earlier, is it work combining runs of set bits
> to increase sz? Or is this sort of temporary pending something better
> that doesn't rely on memblock_reserve?

This hunk actually came from me. I decided to keep it simple for now and
check what are the alternatives, like moving away from memblock_reserve(),
adding a maple_tree or even something else.

> > +		page->private = order;
> 
> Can't just set the page order directly? Why use private?

Setting the order means recreating the folio the way prep_compound_page()
does. I think it's better to postpone it until the folio is requested. This
way it might run after SMP is enabled. Besides, when we start allocating
folios separately from struct page, initializing it here would be a real
issue.
 
> Jason

-- 
Sincerely yours,
Mike.


From christophe.jaillet at wanadoo.fr  Sat Mar 22 12:13:21 2025
From: christophe.jaillet at wanadoo.fr (Christophe JAILLET)
Date: Sat, 22 Mar 2025 20:13:21 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250311180254.149484-1-csokas.bence@prolan.hu>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
Message-ID: <e4249f3c-ca05-4fc7-b367-6ce280d0d749@wanadoo.fr>

Le 11/03/2025 ? 19:02, Bence Cs?k?s a ?crit?:
> Clean up error handling by using devm functions
> and dev_err_probe(). This should make it easier
> to add new code, as we can eliminate the "goto
> ladder" in probe().
> 
> Suggested-by: Chen-Yu Tsai <wens at kernel.org>
> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Acked-by: Chen-Yu Tsai <wens at csie.org>
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
> ---
> 
> Notes:
>      Changes in v2:
>      * rebase on current next
>      Changes in v3:
>      * rebase on current next
>      * collect Jernej's tag
>      Changes in v4:
>      * rebase on current next
>      * collect Chen-Yu's tag
> 
>   drivers/dma/sun4i-dma.c | 31 ++++++-------------------------
>   1 file changed, 6 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
> index 24796aaaddfa..b10639720efd 100644
> --- a/drivers/dma/sun4i-dma.c
> +++ b/drivers/dma/sun4i-dma.c
> @@ -1249,10 +1249,9 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   	if (priv->irq < 0)
>   		return priv->irq;
>   
> -	priv->clk = devm_clk_get(&pdev->dev, NULL);
> +	priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
>   	if (IS_ERR(priv->clk)) {
> -		dev_err(&pdev->dev, "No clock specified\n");
> -		return PTR_ERR(priv->clk);
> +		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "Couldn't start the clock");

Why removing the trailing \n everywhere?

Any reference esxplaing why it is correct?

CJ

>   	}
>   
>   	if (priv->cfg->has_reset) {
> @@ -1328,12 +1327,6 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   		vchan_init(&vchan->vc, &priv->slave);
>   	}
>   
> -	ret = clk_prepare_enable(priv->clk);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Couldn't enable the clock\n");
> -		return ret;
> -	}
> -
>   	/*
>   	 * Make sure the IRQs are all disabled and accounted for. The bootloader
>   	 * likes to leave these dirty
> @@ -1344,32 +1337,23 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   	ret = devm_request_irq(&pdev->dev, priv->irq, sun4i_dma_interrupt,
>   			       0, dev_name(&pdev->dev), priv);
>   	if (ret) {
> -		dev_err(&pdev->dev, "Cannot request IRQ\n");
> -		goto err_clk_disable;
> +		return dev_err_probe(&pdev->dev, ret, "Cannot request IRQ");
>   	}
>   
> -	ret = dma_async_device_register(&priv->slave);
> +	ret = dmaenginem_async_device_register(&priv->slave);
>   	if (ret) {
> -		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
> -		goto err_clk_disable;
> +		return dev_err_probe(&pdev->dev, ret, "Failed to register DMA engine device");
>   	}
>   
>   	ret = of_dma_controller_register(pdev->dev.of_node, sun4i_dma_of_xlate,
>   					 priv);
>   	if (ret) {
> -		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
> -		goto err_dma_unregister;
> +		return dev_err_probe(&pdev->dev, ret, "Failed to register translation function");
>   	}
>   
>   	dev_dbg(&pdev->dev, "Successfully probed SUN4I_DMA\n");
>   
>   	return 0;
> -
> -err_dma_unregister:
> -	dma_async_device_unregister(&priv->slave);
> -err_clk_disable:
> -	clk_disable_unprepare(priv->clk);
> -	return ret;
>   }
>   
>   static void sun4i_dma_remove(struct platform_device *pdev)
> @@ -1380,9 +1364,6 @@ static void sun4i_dma_remove(struct platform_device *pdev)
>   	disable_irq(priv->irq);
>   
>   	of_dma_controller_free(pdev->dev.of_node);
> -	dma_async_device_unregister(&priv->slave);
> -
> -	clk_disable_unprepare(priv->clk);
>   }
>   
>   static struct sun4i_dma_config sun4i_a10_dma_cfg = {



From csokas.bence at prolan.hu  Sat Mar 22 12:35:44 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Sat, 22 Mar 2025 20:35:44 +0100
Subject: [PATCH v4] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <e4249f3c-ca05-4fc7-b367-6ce280d0d749@wanadoo.fr>
References: <20250311180254.149484-1-csokas.bence@prolan.hu>
 <e4249f3c-ca05-4fc7-b367-6ce280d0d749@wanadoo.fr>
Message-ID: <2da00161-723b-438a-9f70-1729312ec819@prolan.hu>

Hi,

On 2025. 03. 22. 20:13, Christophe JAILLET wrote:
> Le 11/03/2025 ? 19:02, Bence Cs?k?s a ?crit?:
>> Clean up error handling by using devm functions
>> and dev_err_probe(). This should make it easier
>> to add new code, as we can eliminate the "goto
>> ladder" in probe().
>>
>> Suggested-by: Chen-Yu Tsai <wens at kernel.org>
>> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
>> Acked-by: Chen-Yu Tsai <wens at csie.org>
>> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
>> ---
>>
>> Notes:
>> ???? Changes in v2:
>> ???? * rebase on current next
>> ???? Changes in v3:
>> ???? * rebase on current next
>> ???? * collect Jernej's tag
>> ???? Changes in v4:
>> ???? * rebase on current next
>> ???? * collect Chen-Yu's tag
>>
>> ? drivers/dma/sun4i-dma.c | 31 ++++++-------------------------
>> ? 1 file changed, 6 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
>> index 24796aaaddfa..b10639720efd 100644
>> --- a/drivers/dma/sun4i-dma.c
>> +++ b/drivers/dma/sun4i-dma.c
>> @@ -1249,10 +1249,9 @@ static int sun4i_dma_probe(struct 
>> platform_device *pdev)
>> ????? if (priv->irq < 0)
>> ????????? return priv->irq;
>> -??? priv->clk = devm_clk_get(&pdev->dev, NULL);
>> +??? priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
>> ????? if (IS_ERR(priv->clk)) {
>> -??????? dev_err(&pdev->dev, "No clock specified\n");
>> -??????? return PTR_ERR(priv->clk);
>> +??????? return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), 
>> "Couldn't start the clock");
> 
> Why removing the trailing \n everywhere?
> 
> Any reference esxplaing why it is correct?
> 
> CJ

Well, printk() will add a newline unless LOG_CONT is used. However, 
while looking up this feature, it seems that the consensus is to keep 
the `\n`s, even though they are not strictly needed anymore. I'll update 
this.

Bence



From csokas.bence at prolan.hu  Sat Mar 22 12:36:40 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Sat, 22 Mar 2025 20:36:40 +0100
Subject: [PATCH v5] dma-engine: sun4i: Use devm functions in probe()
Message-ID: <20250322193640.246382-2-csokas.bence@prolan.hu>

Clean up error handling by using devm functions and dev_err_probe(). This
should make it easier to add new code, as we can eliminate the "goto
ladder" in probe().

Suggested-by: Chen-Yu Tsai <wens at kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Chen-Yu Tsai <wens at csie.org>
Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    Changes in v2:
    * rebase on current next
    Changes in v3:
    * rebase on current next
    * collect Jernej's tag
    Changes in v4:
    * rebase on current next
    * collect Chen-Yu's tag
    Changes in v5:
    * reformat msg to 75 cols
    * keep `\n`s in error messages

 drivers/dma/sun4i-dma.c | 31 ++++++-------------------------
 1 file changed, 6 insertions(+), 25 deletions(-)

diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 24796aaaddfa..59ecebfc8eed 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1249,10 +1249,9 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 	if (priv->irq < 0)
 		return priv->irq;
 
-	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(priv->clk)) {
-		dev_err(&pdev->dev, "No clock specified\n");
-		return PTR_ERR(priv->clk);
+		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "Couldn't start the clock\n");
 	}
 
 	if (priv->cfg->has_reset) {
@@ -1328,12 +1327,6 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 		vchan_init(&vchan->vc, &priv->slave);
 	}
 
-	ret = clk_prepare_enable(priv->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Couldn't enable the clock\n");
-		return ret;
-	}
-
 	/*
 	 * Make sure the IRQs are all disabled and accounted for. The bootloader
 	 * likes to leave these dirty
@@ -1344,32 +1337,23 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 	ret = devm_request_irq(&pdev->dev, priv->irq, sun4i_dma_interrupt,
 			       0, dev_name(&pdev->dev), priv);
 	if (ret) {
-		dev_err(&pdev->dev, "Cannot request IRQ\n");
-		goto err_clk_disable;
+		return dev_err_probe(&pdev->dev, ret, "Cannot request IRQ\n");
 	}
 
-	ret = dma_async_device_register(&priv->slave);
+	ret = dmaenginem_async_device_register(&priv->slave);
 	if (ret) {
-		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
-		goto err_clk_disable;
+		return dev_err_probe(&pdev->dev, ret, "Failed to register DMA engine device\n");
 	}
 
 	ret = of_dma_controller_register(pdev->dev.of_node, sun4i_dma_of_xlate,
 					 priv);
 	if (ret) {
-		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
-		goto err_dma_unregister;
+		return dev_err_probe(&pdev->dev, ret, "Failed to register translation function\n");
 	}
 
 	dev_dbg(&pdev->dev, "Successfully probed SUN4I_DMA\n");
 
 	return 0;
-
-err_dma_unregister:
-	dma_async_device_unregister(&priv->slave);
-err_clk_disable:
-	clk_disable_unprepare(priv->clk);
-	return ret;
 }
 
 static void sun4i_dma_remove(struct platform_device *pdev)
@@ -1380,9 +1364,6 @@ static void sun4i_dma_remove(struct platform_device *pdev)
 	disable_irq(priv->irq);
 
 	of_dma_controller_free(pdev->dev.of_node);
-	dma_async_device_unregister(&priv->slave);
-
-	clk_disable_unprepare(priv->clk);
 }
 
 static struct sun4i_dma_config sun4i_a10_dma_cfg = {
-- 
2.49.0




From tglx at linutronix.de  Sat Mar 22 14:04:01 2025
From: tglx at linutronix.de (Thomas Gleixner)
Date: Sat, 22 Mar 2025 22:04:01 +0100
Subject: hrtimer precision issue/question??
In-Reply-To: <CAJNi4rPaPeVWzBve6Toi8hhrxP6GROAGRug7+c3zg1crDeOt7Q@mail.gmail.com>
References: <CAJNi4rPaPeVWzBve6Toi8hhrxP6GROAGRug7+c3zg1crDeOt7Q@mail.gmail.com>
Message-ID: <875xk022wu.ffs@tglx>

On Sat, Mar 22 2025 at 11:20, richard clark wrote:
> With diff below under the 'cyclictest -a 0 -t 1 -m -p99' trigger from
> the arm64-based linux box, the interval is 1000us and the arch_timer
> in the system is: arch_timer: cp15 timer(s) running at 31.25MHz
> (phys).  1tick = 32ns for the arch timer, I am not sure if those
> durations less than 1000us are expected?

With your method of measurement yes. There is a german saying, which
describes this. It roughly translates to:

   "Who measures a lot, might measure a lot of garbage."

But it accurately describes, what you are measuring here. You do:

    t1 = ktime_get();
    arm_timer(T);
    schedule();
    t2 = ktime_get();

and then look at t2 - t1. That only tells you how long the task actually
slept. But that's ignoring the most important information here:

    arm_timer(T);

cyclictest uses:

           clock_nanosleep(clockid, ABSTIME, &T);

and T is maintained in absolute time on a periodic time line.

    T = starttime + N * interval;

So the only interesting information here is at which time the task
returns from schedule(), i.e. you want to look at:

        t2 - T

Why? Because that gives you the latency of the wakeup. That's what
cyclictest is looking at in user space:

           clock_nanosleep(... &T);
           clock_gettime(..., &T2);
           latency = T2 - T;

Now what you are looking at is the time at which the cyclictest task
comes back into the kernel to sleep, which is obviously

           t1 = T[N] + latency[N-1] + execution_time;

But the timer is armed for T[N], so your t2 is:

           t2 = T[N] + latency[N];

You surely can do the remaining math and map that to the output:

> [  165.555795] [ 0- 0]t0=165550399226,t1=165551394303,d=995 us
> [  165.556802] [ 0- 0]t0=165551398751,t1=165552400997,d=1002 us

Right?

Thanks,

        tglx


From christophe.jaillet at wanadoo.fr  Sat Mar 22 14:37:55 2025
From: christophe.jaillet at wanadoo.fr (Christophe JAILLET)
Date: Sat, 22 Mar 2025 22:37:55 +0100
Subject: [PATCH v5] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250322193640.246382-2-csokas.bence@prolan.hu>
References: <20250322193640.246382-2-csokas.bence@prolan.hu>
Message-ID: <071b4cf6-df18-4232-b2ae-6b8bee48899d@wanadoo.fr>

Le 22/03/2025 ? 20:36, Bence Cs?k?s a ?crit?:
> Clean up error handling by using devm functions and dev_err_probe(). This
> should make it easier to add new code, as we can eliminate the "goto
> ladder" in probe().
> 
> Suggested-by: Chen-Yu Tsai <wens at kernel.org>
> Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Acked-by: Chen-Yu Tsai <wens at csie.org>
> Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
> ---
> 
> Notes:
>      Changes in v2:
>      * rebase on current next
>      Changes in v3:
>      * rebase on current next
>      * collect Jernej's tag
>      Changes in v4:
>      * rebase on current next
>      * collect Chen-Yu's tag
>      Changes in v5:
>      * reformat msg to 75 cols
>      * keep `\n`s in error messages
> 
>   drivers/dma/sun4i-dma.c | 31 ++++++-------------------------
>   1 file changed, 6 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
> index 24796aaaddfa..59ecebfc8eed 100644
> --- a/drivers/dma/sun4i-dma.c
> +++ b/drivers/dma/sun4i-dma.c
> @@ -1249,10 +1249,9 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   	if (priv->irq < 0)
>   		return priv->irq;
>   
> -	priv->clk = devm_clk_get(&pdev->dev, NULL);
> +	priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
>   	if (IS_ERR(priv->clk)) {
> -		dev_err(&pdev->dev, "No clock specified\n");
> -		return PTR_ERR(priv->clk);
> +		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "Couldn't start the clock\n");

I think that it would be better to keep the message on another line, to 
avoid too long lines.

>   	}

In several places, now {} around a single statement looks unneeded.

CJ

>   
>   	if (priv->cfg->has_reset) {
> @@ -1328,12 +1327,6 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   		vchan_init(&vchan->vc, &priv->slave);
>   	}
>   
> -	ret = clk_prepare_enable(priv->clk);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Couldn't enable the clock\n");
> -		return ret;
> -	}
> -
>   	/*
>   	 * Make sure the IRQs are all disabled and accounted for. The bootloader
>   	 * likes to leave these dirty
> @@ -1344,32 +1337,23 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>   	ret = devm_request_irq(&pdev->dev, priv->irq, sun4i_dma_interrupt,
>   			       0, dev_name(&pdev->dev), priv);
>   	if (ret) {
> -		dev_err(&pdev->dev, "Cannot request IRQ\n");
> -		goto err_clk_disable;
> +		return dev_err_probe(&pdev->dev, ret, "Cannot request IRQ\n");
>   	}
>   
> -	ret = dma_async_device_register(&priv->slave);
> +	ret = dmaenginem_async_device_register(&priv->slave);
>   	if (ret) {
> -		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
> -		goto err_clk_disable;
> +		return dev_err_probe(&pdev->dev, ret, "Failed to register DMA engine device\n");
>   	}
>   
>   	ret = of_dma_controller_register(pdev->dev.of_node, sun4i_dma_of_xlate,
>   					 priv);
>   	if (ret) {
> -		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
> -		goto err_dma_unregister;
> +		return dev_err_probe(&pdev->dev, ret, "Failed to register translation function\n");
>   	}
>   
>   	dev_dbg(&pdev->dev, "Successfully probed SUN4I_DMA\n");
>   
>   	return 0;
> -
> -err_dma_unregister:
> -	dma_async_device_unregister(&priv->slave);
> -err_clk_disable:
> -	clk_disable_unprepare(priv->clk);
> -	return ret;
>   }
>   
>   static void sun4i_dma_remove(struct platform_device *pdev)
> @@ -1380,9 +1364,6 @@ static void sun4i_dma_remove(struct platform_device *pdev)
>   	disable_irq(priv->irq);
>   
>   	of_dma_controller_free(pdev->dev.of_node);
> -	dma_async_device_unregister(&priv->slave);
> -
> -	clk_disable_unprepare(priv->clk);
>   }
>   
>   static struct sun4i_dma_config sun4i_a10_dma_cfg = {



From qasdev00 at gmail.com  Sat Mar 22 15:51:22 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sat, 22 Mar 2025 22:51:22 +0000
Subject: [PATCH] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <CAOiHx==UCeMQpywQJCLPQqipEW0tK9youRxdR5+_T1LuGp_EHA@mail.gmail.com>
References: <20250320201914.48159-1-qasdev00@gmail.com>
 <CAOiHx==UCeMQpywQJCLPQqipEW0tK9youRxdR5+_T1LuGp_EHA@mail.gmail.com>
Message-ID: <Z98-6kXoYdSaFtVR@qasdev.system>

On Sat, Mar 22, 2025 at 12:51:57PM +0100, Jonas Gorski wrote:
> Hi,
> 
> On Thu, Mar 20, 2025 at 9:19?PM Qasim Ijaz <qasdev00 at gmail.com> wrote:
> >
> > If link_conf_dereference_protected() or mt7996_vif_link()
> > or link_sta_dereference_protected() fail the code jumps to
> > the error_unlink label and returns ret which is uninitialised.
> >
> > Fix this by setting err before jumping to error_unlink.
> >
> > Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
> > Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > index 91c64e3a0860..78f7f1fc867e 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> > @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
> >                         continue;
> >
> >                 link_conf = link_conf_dereference_protected(vif, link_id);
> > -               if (!link_conf)
> > +               if (!link_conf) {
> > +                       err = -EINVAL;
> >                         goto error_unlink;
> > +               }
> >
> >                 link = mt7996_vif_link(dev, vif, link_id);
> > -               if (!link)
> > +               if (!link) {
> > +                       err = -EINVAL;
> >                         goto error_unlink;
> > +               }
> >
> >                 link_sta = link_sta_dereference_protected(sta, link_id);
> > -               if (!link_sta)
> > +               if (!link_sta) {
> > +                       err = -EINVAL
> 
> You are missing a semicolon at the end of the line.
> 

Good spot! not sure how that happened but I will resend a v2 patch.

> To also do some bike shedding, you could initialize err (with 0 or
> -EINVAL), and then change the err return to return err ? : -EINVAL;.
> But your way has an explicit error code assigned to each failure, even
> if it is always the same. So I won't claim my suggestion is better.
> 

Thanks for the suggestion, I think this could work however I think my 
current approach is more a bit more readable, so I will leave it as is.

Thanks,
Qasim

> Best regards,
> Jonas


From qasdev00 at gmail.com  Sat Mar 22 16:01:37 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sat, 22 Mar 2025 23:01:37 +0000
Subject: [PATCH v2] wifi: mt76: mt7996: prevent uninit return in mt7996_mac_sta_add_links
Message-ID: <20250322230137.28164-1-qasdev00@gmail.com>

If link_conf_dereference_protected() or mt7996_vif_link()
or link_sta_dereference_protected() fail the code jumps to
the error_unlink label and returns ret which is uninitialised.

Fix this by setting err before jumping to error_unlink.
 
Fixes: c7e4fc362443 ("wifi: mt76: mt7996: Update mt7996_mcu_add_sta to MLO support")
Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
v2:
- Added missing semi-colon as pointed out by Jonas Gorski

 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 91c64e3a0860..70823bbb165c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			continue;
 
 		link_conf = link_conf_dereference_protected(vif, link_id);
-		if (!link_conf)
+		if (!link_conf) {
+			err = -EINVAL;
 			goto error_unlink;
+		}
 
 		link = mt7996_vif_link(dev, vif, link_id);
-		if (!link)
+		if (!link) {
+			err = -EINVAL;
 			goto error_unlink;
+		}
 
 		link_sta = link_sta_dereference_protected(sta, link_id);
-		if (!link_sta)
+		if (!link_sta) {
+			err = -EINVAL;
 			goto error_unlink;
+		}
 
 		err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
 					       link_id);
-- 
2.39.5



From menglong8.dong at gmail.com  Sat Mar 22 20:51:41 2025
From: menglong8.dong at gmail.com (Menglong Dong)
Date: Sun, 23 Mar 2025 11:51:41 +0800
Subject: [PATCH v4 1/4] x86/ibt: factor out cfi and fineibt offset
In-Reply-To: <CADxym3YMeAPpc+ozM2E7yW1qpB_arKJiDyAcRs8pW8sRqJZOZw@mail.gmail.com>
References: <20250303132837.498938-1-dongml2@chinatelecom.cn>
 <20250303132837.498938-2-dongml2@chinatelecom.cn> <20250303165454.GB11590@noisy.programming.kicks-ass.net>
 <CADxym3aVtKx_mh7aZyZfk27gEiA_TX6VSAvtK+YDNBtuk_HigA@mail.gmail.com>
 <20250304053853.GA7099@noisy.programming.kicks-ass.net> <20250304061635.GA29480@noisy.programming.kicks-ass.net>
 <CADxym3bS_6jpGC3vLAAyD20GsR+QZofQw0_GgKT8nN3c-HqG-g@mail.gmail.com>
 <20250304094220.GC11590@noisy.programming.kicks-ass.net> <6F9EF5C3-4CAE-4C5E-B70E-F73462AC7CA0@zytor.com>
 <CADxym3busXZKtX=+FY_xnYw7e1CKp5AiHSasZGjVJTdeCZao-g@mail.gmail.com>
 <20250305100306.4685333a@gandalf.local.home> <CADxym3ZB_eQny=-aO4AwrHiwT264NXitdKwjRUYrnGJ2tH=Qwg@mail.gmail.com>
 <CAADnVQJ0_+Hij=kf9eVPX_ZND=2=uDHaYPWvv1x-WmR5sZRSmA@mail.gmail.com> <CADxym3YMeAPpc+ozM2E7yW1qpB_arKJiDyAcRs8pW8sRqJZOZw@mail.gmail.com>
Message-ID: <CADxym3aRTo0GfhfTKKxbig+QmrGfiBGoqs-Rtr6y_WFzNpgmgw@mail.gmail.com>

On Thu, Mar 6, 2025 at 4:50?PM Menglong Dong <menglong8.dong at gmail.com> wrote:
>
> On Thu, Mar 6, 2025 at 11:39?AM Alexei Starovoitov
> <alexei.starovoitov at gmail.com> wrote:
> >
> > On Wed, Mar 5, 2025 at 6:59?PM Menglong Dong <menglong8.dong at gmail.com> wrote:
> > >
> > > I'm not sure if it works. However, indirect call is also used
> > > in function graph, so we still have better performance. Isn't it?
> > >
> > > Let me have a look at the code of the function graph first :/
> >
> > Menglong,
> >
> > Function graph infra isn't going to help.
> > "call foo" isn't a problem either.
> >
> > But we have to step back.
> > per-function metadata is an optimization and feels like
> > we're doing a premature optimization here without collecting
> > performance numbers first.
> >
> > Let's implement multi-fentry with generic get_metadata_by_ip() first.
> > get_metadata_by_ip() will be a hashtable in such a case and
> > then we can compare its performance when it's implemented as
> > a direct lookup from ip-4 (this patch) vs hash table
> > (that does 'ip' to 'metadata' lookup).
>
> Hi, Alexei
>
> You are right, I should do such a performance comparison.
>
> >
> > If/when we decide to do this per-function metadata we can also
> > punt to generic hashtable for cfi, IBT, FineIBT, etc configs.
> > When mitigations are enabled the performance suffers anyway,
> > so hashtable lookup vs direct ip-4 lookup won't make much difference.
> > So we can enable per-function metadata only on non-mitigation configs
> > when FUNCTION_ALIGNMENT=16.
> > There will be some number of bytes available before every function
> > and if we can tell gcc/llvm to leave at least 5 bytes there
> > the growth of vmlinux .text will be within a noise.

Hi, Alexei

I have finished the demo of the tracing multi-link recently.
The code is not ready to be sent out, as it's very very ugly
for now, and I did some performance testing.

The test case is very simple. I defined a function "kfunc_md_test",
and called it 10000000 times in "do_kfunc_md_test". And I will
attach my empty bpf program of attach type BPF_FENTRY_MULTI
to it. Following is the code of the test case:

-----------------------------------------kernel
part--------------------------------
int kfunc_md_test_result = 0;
noinline void kfunc_md_test(int a)
{
    kfunc_md_test_result = a;
}

int noinline
do_kfunc_md_test(const struct ctl_table *table, int write,
                void *buffer, size_t *lenp, loff_t *ppos)
{
    u64 start, interval;
    int i;

    start = ktime_get_boottime_ns();
    for (i = 0; i < 10000000; i++)
        kfunc_md_test(i);

    interval = ktime_get_boottime_ns() - start;
    pr_info("%llu.%llums\n",
        interval / 1000000, interval % 1000000);

    return 0;
}

---------------------------------------bpf
part-----------------------------------------
SEC("fentry.multi/kfunc_md_test")
int BPF_PROG(fentry_manual_nop)
{
    return 0;
}
------------------------------------bpf part
end-------------------------------------

I did the testing for BPF_FENTRY, BPF_FENTRY_MULTI and
BPF_KPROBE_MULTI, and following is the results:

Without any bpf:
--------------------------------------------------------------------------------------
9.234677ms
9.486119ms
9.310059ms
9.468227ms
9.217295ms
9.500406ms
9.292606ms
9.530492ms
9.268741ms
9.513371ms

BPF_FENTRY:
----------------------------------------------------------------------------------------
80.800800ms
79.746338ms
83.292012ms
80.324835ms
84.25841ms
81.67250ms
81.21824ms
80.415886ms
79.910556ms
80.427809ms

BPF_FENTRY_MULTI with function padding:
---------------------------------------------------------------------------------------
120.457336ms
117.854154ms
118.888287ms
119.726011ms
117.52847ms
117.463910ms
119.212126ms
118.722216ms
118.843222ms
119.166079ms

It seems that the overhead of BPF_FENTRY_MULTI is more
that BPF_FENTRY. I'm not sure if it is because of the "indirect
call". However, it's not what we want to discuss today, so let's
focus on the performance of the function metadata basing on
"function padding" and "hash table".

Generally speaking, the overhead of the BPF_FENTRY_MULTI
with the hash table has a linear relation. The hash table that I
used is exactly the same to the filter_hash that ftrace uses, and
the array length is 1024. I didn't do that statistics basing on the
function number, but the hash table looking up count, as I find
that the hash is not random enough some times. However, we
can compute the kernel function number if we image the hash
is random enough.

BPF_FENTRY_MULTI with hash table:
----------------------------------------------------------------------------------
1(1k)                    16(32k)
--------------------    --------------------
124.950881ms    235.24341ms
124.171226ms    232.20816ms
123.969627ms    232.212086ms
125.803975ms    230.935175ms
124.256777ms    230.906713ms
124.314095ms    234.551623ms
124.165637ms    231.435496ms
124.488003ms    230.936458ms
125.571929ms    230.753203ms
124.168110ms    234.679152ms

(The 1 and 16 above means that the hash lookup times is
1 and 16, 1k and 32k means the corresponding kernel function
count that we trace.)

According to my testing, the hash table will have a slight overhead
if the kernel functions that we trace are no more than 5k. And
I think this is the most use case, according to the people who are
interested in tracing multi-link. When the function count up to 32k,
the overhead is obvious.

According to my research, the kprobe-multi/fprobe also based on
the hash table, which will lookup the callback ops with the function
address in a hash table, and the overhead is heavy too. And I alse
did the kprobe-multi performance. I run the test case
"kprobe_multi_bench_attach/kernel", and do the "kfunc_md_test"
meanwhile, just like what I did for BPF_FENTRY_MULTI:

BPF_KPROBE_MULTI:
-----------------------------------------------------------------------------------
36895.985224ms
37002.298075ms
30150.774087ms

The kernel function count is 55239 in the kprobe-multi testing.
I'm not sure if there is something wrong with my testing, but
the overhead looks heavy.

So I think maybe it works to fallback to the hash table if
CFI/FINEIBT/... are enabled? I would be appreciated to
hear some advice here.

(BTW, I removed most CCs to reduce the noise :/)

Thanks!
Menglong Dong

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------

Following is the bpf global trampoline(x86, demo and ugly):
---------------------------------------------------------------------------------
#define FUNC_ARGS_SIZE        (6 * 8)
#define FUNC_ARGS_OFFSET    (-8 - FUNC_ARGS_SIZE)
#define FUNC_ARGS_1        (FUNC_ARGS_OFFSET + 0 * 8)
#define FUNC_ARGS_2        (FUNC_ARGS_OFFSET + 1 * 8)
#define FUNC_ARGS_3        (FUNC_ARGS_OFFSET + 2 * 8)
#define FUNC_ARGS_4        (FUNC_ARGS_OFFSET + 3 * 8)
#define FUNC_ARGS_5        (FUNC_ARGS_OFFSET + 4 * 8)
#define FUNC_ARGS_6        (FUNC_ARGS_OFFSET + 5 * 8)

/* the args count, rbp - 8 * 8 */
#define FUNC_ARGS_COUNT_OFFSET    (FUNC_ARGS_OFFSET - 1 * 8)
#define FUNC_ORIGIN_IP        (FUNC_ARGS_OFFSET - 2 * 8) /* -9 * 8 */
#define RBX_OFFSET        (FUNC_ARGS_OFFSET - 3 * 8)

/* bpf_tramp_run_ctx, rbp - BPF_RUN_CTX_OFFSET */
#define BPF_RUN_CTX_OFFSET    (RBX_OFFSET - BPF_TRAMP_RUN_CTX_SIZE)
#define KFUNC_MD_OFFSET        (BPF_RUN_CTX_OFFSET - 1 * 8)
#define STACK_SIZE        (-1 * KFUNC_MD_OFFSET)

.macro tramp_restore_regs
    movq FUNC_ARGS_1(%rbp), %rdi
    movq FUNC_ARGS_2(%rbp), %rsi
    movq FUNC_ARGS_3(%rbp), %rdx
    movq FUNC_ARGS_4(%rbp), %rcx
    movq FUNC_ARGS_5(%rbp), %r8
    movq FUNC_ARGS_6(%rbp), %r9
    .endm

SYM_FUNC_START(bpf_global_caller)
    pushq %rbp
    movq %rsp, %rbp
    subq $STACK_SIZE, %rsp

    /* save the args to stack, only regs is supported for now */
    movq %rdi, FUNC_ARGS_1(%rbp)
    movq %rsi, FUNC_ARGS_2(%rbp)
    movq %rdx, FUNC_ARGS_3(%rbp)
    movq %rcx, FUNC_ARGS_4(%rbp)
    movq %r8, FUNC_ARGS_5(%rbp)
    movq %r9, FUNC_ARGS_6(%rbp)

    /* save the rbx, rbp - 9 * 8 */
    movq %rbx, RBX_OFFSET(%rbp)

    /* get the function address */
    movq 8(%rbp), %rdi
    /* subq $(4+5), %rdi */
    /* save the function ip */
    movq %rdi, FUNC_ORIGIN_IP(%rbp)

    call kfunc_md_find
    cmpq $0, %rax
    jz out
    /* kfunc_md, keep it in %rcx */
    movq %rax, %rcx

    /* fentry bpf prog */
    cmpq $0, KFUNC_MD_FENTRY(%rcx)
    jz out

    /* load fentry bpf prog to the 1st arg */
    movq KFUNC_MD_FENTRY(%rcx), %rdi
    /* load the pointer of tramp_run_ctx to the 2nd arg */
    leaq BPF_RUN_CTX_OFFSET(%rbp), %rsi
    /* save the bpf cookie to the tramp_run_ctx */
    movq KFUNC_MD_COOKIE(%rcx), %rax
    movq %rax, BPF_COOKIE_OFFSET(%rsi)
    call __bpf_prog_enter_recur
    /* save the start time to rbx */
    movq %rax, %rbx

    /* load fentry JITed prog to rax */
    movq BPF_FUNC_OFFSET(%rdi), %rax
    /* load func args array to the 1st arg */
    leaq FUNC_ARGS_OFFSET(%rbp), %rdi

    /* load and call the JITed bpf func */
    call *%rax

    /* load bpf prog to the 1st arg */
    movq KFUNC_MD_FENTRY(%rcx), %rdi
    /* load the rbx(start time) to the 2nd arg */
    movq %rbx, %rsi
    /* load the pointer of tramp_run_ctx to the 3rd arg */
    leaq BPF_RUN_CTX_OFFSET(%rbp), %rdx
    call __bpf_prog_exit_recur
out:
    tramp_restore_regs

    movq RBX_OFFSET(%rbp), %rbx
    addq $STACK_SIZE, %rsp
    popq %rbp
    RET

SYM_FUNC_END(bpf_global_caller)
STACK_FRAME_NON_STANDARD_FP(bpf_global_caller)

>
> Sounds great! It's so different to make the per-function metadata
> work in all the cases. Especially, we can't implement it in arm64
> if CFI_CLANG is enabled. And the fallbacking to the hash table makes
> it much easier in these cases.
>
> >
> > So let's figure out the design of multi-fenty first with a hashtable
> > for metadata and decide next steps afterwards.
>
> Ok, I'll develop a version for fentry multi-link with both hashtable
> and function metadata, and do some performance testing. Thank
> you for your advice :/
>
> Thanks!
> Menglong Dong


From Markus.Elfring at web.de  Sun Mar 23 01:30:21 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sun, 23 Mar 2025 09:30:21 +0100
Subject: [PATCH v5] dma-engine: sun4i: Use devm functions in probe()
In-Reply-To: <20250322193640.246382-2-csokas.bence@prolan.hu>
References: <20250322193640.246382-2-csokas.bence@prolan.hu>
Message-ID: <352b3fb3-0acd-44bf-8f69-cf72b5d27e67@web.de>

> Clean up ? and dev_err_probe(). ?
I find it more reasonable to offer such a change in a separate update step.
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14-rc7#n81


Will it be clearer to mention also the function name ?sun4i_dma_probe?
in the summary phrases?

Regards,
Markus


From dsimic at manjaro.org  Sun Mar 23 03:19:56 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Sun, 23 Mar 2025 11:19:56 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
Message-ID: <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>

Hello Quentin,

Thanks for your comments!  Please see some responses below.

On 2025-03-21 10:53, Quentin Schulz wrote:
> On 3/21/25 4:28 AM, Dragan Simic wrote:
>> The differences in the vendor-approved CPU and GPU OPPs for the 
>> standard
>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>> variant [2]
>> come from the latter, presumably, supporting an extended temperature 
>> range
>> that's usually associated with industrial applications, despite the 
>> two SoC
>> variant datasheets specifying the same upper limit for the allowed 
>> ambient
>> temperature for both variants.  However, the lower temperature limit 
>> is
> 
> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
> Operating Conditions, Table 3-2, Ambient Operating Temperature.

Indeed, which is why I specifically wrote "specifying the same upper
limit", because having a lower negative temperature limit could hardly
put the RK3588J in danger of overheating or running hotter. :)

>> specified much lower for the RK3588J variant. [1][2]
>> 
>> To be on the safe side and to ensure maximum longevity of the RK3588J 
>> SoCs,
>> only the CPU and GPU OPPs that are declared by the vendor to be always 
>> safe
>> for this SoC variant may be provided.  As explained by the vendor [3] 
>> and
>> according to its datasheet, [2] the RK3588J variant can actually run 
>> safely
>> at higher CPU and GPU OPPs as well, but only when not enjoying the 
>> assumed
>> extended temperature range that the RK3588J, as an SoC variant 
>> targeted
> 
> "only when not enjoying the assumed extended temperature range" is
> extrapolated by me/us and not confirmed by Rockchip themselves. I've
> asked for a statement on what "industrial environment" they specify in
> the Normal Mode explanation means since it's the only time they use
> the term. I've yet to receive an answer. The only thing Rockchip in
> their datasheet is that the overdrive mode will shorten lifetime when
> used for a long time, especially in high temperature conditions. It's
> not clear whether we can use the overdrive mode even within the RK3588
> typical range of operation.

True.  I'll see to rephrase the patch description a bit in the v2,
to avoid this kind of speculation.  I mean, perhaps the speculation
is right, but it hasn't been confirmed officially by Rockchip.

>> specifically at industrial applications, is made (or binned) for.
>> 
>> Thus, only the CPU and GPU OPPs that are specified by the vendor to be 
>> safe
>> throughout the entire RK3588J's extended temperature range may be 
>> provided,
>> while anyone who actually can ensure that their RK3588J-based board is
>> never going to run within the extended temperature range, may probably
>> safely apply a DT overlay that adds the higher CPU and GPU OPPs.  As 
>> we
> 
> Wouldn't say "safely" here, Rockchip still says that running overdrive
> mode for a long time may shorten lifetime... that followed by
> "especially in high temperature condition" doesn't mean that operating
> the RK3588J within the RK3588 typical range is safe to do.

Also true, and I'll also try to address that in the v2.

>> obviously can't know what will be the runtime temperature conditions 
>> for
>> a particular board, we may provide only the always-safe OPPs.
>> 
>> With all this and the downstream RK3588(J) DT definitions [4][5] in 
>> mind,
>> let's delete the RK3588J CPU and GPU OPPs that are not considered 
>> belonging
>> to the normal operation mode for this SoC variant.  To quote the 
>> RK3588J
>> datasheet [2], "normal mode means the chipset works under safety 
>> voltage
>> and frequency;  for the industrial environment, highly recommend to 
>> keep in
>> normal mode, the lifetime is reasonably guaranteed", while "overdrive 
>> mode
>> brings higher frequency, and the voltage will increase accordingly;  
>> under
>> the overdrive mode for a long time, the chipset may shorten the 
>> lifetime,
>> especially in high temperature condition".
>> 
>> To sum up the RK3588J datasheet [2] and the vendor-provided DTs, 
>> [4][5]
>> the maximum allowed CPU core and GPU frequencies are as follows:
>> 
>>     IP core    | Normal mode | Overdrive mode
>>    ------------+-------------+----------------
>>     Cortex-A55 |   1,296 MHz |      1,704 MHz
>>     Cortex-A76 |   1,608 MHz |      2,016 MHz
>>     GPU        |     700 MHz |        850 MHz
>> 
> 
> The NPU too is impacted by this, so maybe list it anyway here? Even if
> we don't support it right now and don't have OPPs for it.

Agreed, will add in the v2.  Having all that information in a single
place can only be helpful.

>> Unfortunately, when it comes to the actual voltages for the RK3588J 
>> CPU and
>> GPU OPPs, there's a discrepancy between the RK3588J datasheet [2] and 
>> the
>> downstream kernel code. [4][5]  The RK3588J datasheet states that "the 
>> max.
>> working voltage of CPU/GPU/NPU is 0.75 V under the normal mode", while 
>> the
>> downstream kernel code actually allows voltage ranges that go up to 
>> 0.95 V,
>> which is still within the voltage range allowed by the datasheet.  
>> However,
>> the RK3588J datasheet also tells us to "strictly refer to the software
>> configuration of SDK and the hardware reference design", so let's 
>> embrace
>> the voltage ranges provided by the downstream kernel code, which also
>> prevents the undesirable theoretical outcome of ending up with no 
>> usable
>> OPPs on a particular board, as a result of the board's voltage 
>> regulator(s)
>> being unable to deliver the exact voltages, for whatever reason.
>> 
>> The above-described voltage ranges for the RK3588J CPU OPPs remain 
>> taken
>> from the downstream kernel code [4][5] by picking the highest, 
>> worst-bin
>> values, which ensure that all RK3588J bins will work reliably.  Yes, 
>> with
>> some power inevitably wasted as unnecessarily generated heat, but the
>> reliability is paramount, together with the longevity.  This 
>> deficiency
>> may be revisited separately at some point in the future.
>> 
>> The provided RK3588J CPU OPPs follow the slightly debatable "provide 
>> only
>> the highest-frequency OPP from the same-voltage group" approach that's 
>> been
> 
> Interesting that we went for a different strategy for the GPU OPPs :)

Good point, and I'm fully aware of that. :)  Actually, I'm rather
sure that omitting the additional CPU OPPs does no good to us, but
I didn't want to argue about that when they were dropped originally,
before I can have some hard numbers to prove it in a repeatable way.

>> established earlier, [6] as a result of the "same-voltage, 
>> lower-frequency"
>> OPPs being considered inefficient from the IPA governor's standpoint, 
>> which
>> may also be revisited separately at some point in the future.
>> 
>> [1] 
>> https://wiki.friendlyelec.com/wiki/images/e/ee/Rockchip_RK3588_Datasheet_V1.6-20231016.pdf
>> [2] 
>> https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2403201054_Rockchip-RK3588J_C22364189.pdf
>> [3] 
>> https://lore.kernel.org/linux-rockchip/e55125ed-64fb-455e-b1e4-cebe2cf006e4 at cherry.de/T/#u
>> [4] 
>> https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
>> [5] 
>> https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
>> [6] 
>> https://lore.kernel.org/all/20240229-rk-dts-additions-v3-5-6afe8473a631 at gmail.com/
>> 
>> Fixes: 667885a68658 ("arm64: dts: rockchip: Add OPP data for CPU cores 
>> on RK3588j")
>> Fixes: a7b2070505a2 ("arm64: dts: rockchip: Split GPU OPPs of RK3588 
>> and RK3588j")
>> Cc: stable at vger.kernel.org
>> Cc: Heiko Stuebner <heiko at sntech.de>
>> Cc: Alexey Charkov <alchark at gmail.com>
>> Helped-by: Quentin Schulz <quentin.schulz at cherry.de>
> 
> Reported-by/Suggested-by?
> 
> I don't see Helped-by in
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes
> 
> I see 2496b2aaacf137250f4ca449f465e2cadaabb0e8 got the Helped-by
> replaced by a Suggested-by for example, but I see other patches with
> Helped-by... if that is a standard trailer for kernel patches, then
> maybe we should add it to that doc?

Actually, I already tried to get the Helped-by tag added to the
kernel documentation, by submitting a small patch series. [*]
Unfortunately, it got rejected. :/

However, Heiko accepts Helped-by tags and nobody higher up the
tree seems to complain, so we should be fine. :)  It isn't the
case with all maintainers, though.

[*] 
https://lore.kernel.org/all/cover.1730874296.git.dsimic at manjaro.org/T/#u

>> Signed-off-by: Dragan Simic <dsimic at manjaro.org>
>> ---
>>   arch/arm64/boot/dts/rockchip/rk3588j.dtsi | 53 
>> ++++++++---------------
>>   1 file changed, 17 insertions(+), 36 deletions(-)
>> 
>> diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi 
>> b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
>> index bce72bac4503..3045cb3bd68c 100644
>> --- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
>> +++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
>> @@ -11,74 +11,59 @@ cluster0_opp_table: opp-table-cluster0 {
>>   		compatible = "operating-points-v2";
>>   		opp-shared;
>>   -		opp-1416000000 {
>> -			opp-hz = /bits/ 64 <1416000000>;
>> +		opp-1200000000 {
>> +			opp-hz = /bits/ 64 <1200000000>;
>>   			opp-microvolt = <750000 750000 950000>;
>>   			clock-latency-ns = <40000>;
>>   			opp-suspend;
>>   		};
>> -		opp-1608000000 {
>> -			opp-hz = /bits/ 64 <1608000000>;
>> -			opp-microvolt = <887500 887500 950000>;
>> -			clock-latency-ns = <40000>;
>> -		};
>> -		opp-1704000000 {
>> -			opp-hz = /bits/ 64 <1704000000>;
>> -			opp-microvolt = <937500 937500 950000>;
>> +		opp-1296000000 {
>> +			opp-hz = /bits/ 64 <1296000000>;
>> +			opp-microvolt = <775000 775000 950000>;
> 
> Got tricked by this one.
> 
> In the Rockchip vendor kernel, the opp-microvolt is 750000 750000
> 950000, so the same as CPU OPP 1.2GHz. However, the opp-microvolt-L1
> and L0 are higher than that. Only a couple of the OPPs in vendor
> kernel actually have opp-microvolt-L* higher than opp-microvolt, that
> is a noteworthy oddity for anyone reviewing this patch :)
> 
> Anyway, that is correct, we take the highest voltage among all defined
> opp-microvolt* properties.

Indeed, and I also almost got tricked by the same OPP. :)

> I only have comments on the commit log, the diff is fine so:
> 
> Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>

Thanks once again for your detailed review! :)


From kw at linux.com  Sun Mar 23 04:39:14 2025
From: kw at linux.com (Krzysztof Wilczynski)
Date: Sun, 23 Mar 2025 20:39:14 +0900
Subject: [PATCH v8 03/13] dt-bindings: pci: Add common schema for devices
 accessible through PCI BARs
In-Reply-To: <096ab7addb39e498e28ac2526c07157cc9327c42.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
 <096ab7addb39e498e28ac2526c07157cc9327c42.1742418429.git.andrea.porta@suse.com>
Message-ID: <20250323113914.GC1902347@rocinante>

Hello,

> Common YAML schema for devices that exports internal peripherals through
> PCI BARs. The BARs are exposed as simple-buses through which the
> peripherals can be accessed.
> 
> This is not intended to be used as a standalone binding, but should be
> included by device specific bindings.

Applied to dt-bindings, thank you!

	Krzysztof


From kw at linux.com  Sun Mar 23 04:49:45 2025
From: kw at linux.com (Krzysztof Wilczynski)
Date: Sun, 23 Mar 2025 20:49:45 +0900
Subject: [PATCH v8 08/13] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <3fbc487bc0e4b855ffbee8ed62cfb6bf3b0592e8.1742418429.git.andrea.porta@suse.com>
References: <cover.1742418429.git.andrea.porta@suse.com>
 <3fbc487bc0e4b855ffbee8ed62cfb6bf3b0592e8.1742418429.git.andrea.porta@suse.com>
Message-ID: <20250323114945.GD1902347@rocinante>

Hello,

Thank you for sending new version.  Appreciated.

> +	case IRQ_TYPE_LEVEL_HIGH:
> +		dev_dbg(&rp1->pdev->dev, "MSIX IACK EN for irq %u\n", hwirq);
> +		msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
> +		rp1->level_triggered_irq[hwirq] = true;

[...]
> +		if (!irq) {
> +			dev_err(&pdev->dev, "Failed to create irq mapping\n");
> +			err = -EINVAL;
> +			goto err_unregister_interrupts;
> +		}

A small nitpick: "IRQ" in both of the above.  Not a blocker, though, so
feel free to ignore this feedback.

	Krzysztof


From kw at linux.com  Sun Mar 23 04:56:02 2025
From: kw at linux.com (Krzysztof Wilczynski)
Date: Sun, 23 Mar 2025 20:56:02 +0900
Subject: [PATCH v7 08/11] misc: rp1: RaspberryPi RP1 misc driver
In-Reply-To: <Z9lA31gBjpIRHm6y@apocalypse>
References: <cover.1738963156.git.andrea.porta@suse.com>
 <d1362766e3e966f78591129de918046a4b892c18.1738963156.git.andrea.porta@suse.com>
 <20250314083730.GC234496@rocinante>
 <Z9lA31gBjpIRHm6y@apocalypse>
Message-ID: <20250323115602.GE1902347@rocinante>

Hello,

[...]
> > Or, something like this over this the function name.  Perhaps exposing
> > error code could be useful to the end user? If so then something like this:
> > 
> >   return dev_err_probe(&pdev->dev, err,
> > 		       "Failed to allocate MSI-X vectors, err=%d\n", err);
> 
> dev_err_probe() should already print the err code, no need to add it.

Ahh...

I did a copy-paste of the code from above purely for illustration, sorry
for the confusion here!

> > Here and other errors where appropriate.
> 
> I've changed dev_err() to dev_err_probe() in cases where the error code
> is not evident (i.e. hardcoded) from the source.

Makes sense.

> Thank you so much for your review!

Pleasure!  Thank you for all the work here!

	Krzysztof


From james.dutton at gmail.com  Sun Mar 23 04:59:45 2025
From: james.dutton at gmail.com (James Dutton)
Date: Sun, 23 Mar 2025 11:59:45 +0000
Subject: [PATCH] wifi: mt76: mt7996: avoid potential null deref in mt7996_get_et_stats()
In-Reply-To: <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>
References: <20250322141910.4461-1-qasdev00@gmail.com> <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
 <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>
Message-ID: <CAAMvbhGrJ9b3Aab9+2a5zmvEgf0GZFmHLCC7Hud+egUE28voHQ@mail.gmail.com>

As a security side note in relation to the following patch:
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 66575698aef1..88e013577c0d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -68,11 +68,13 @@ static int mt7996_start(struct ieee80211_hw *hw)

 static void mt7996_stop_phy(struct mt7996_phy *phy)
 {
-       struct mt7996_dev *dev = phy->dev;
+       struct mt7996_dev *dev;

        if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
                return;

+       dev = phy->dev;
+
        cancel_delayed_work_sync(&phy->mt76->mac_work);

        mutex_lock(&dev->mt76.mutex);



Prior to that patch, the code looks like this:
static void mt7996_stop_phy(struct mt7996_phy *phy)
 {
       struct mt7996_dev *dev = phy->dev;

        if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
                return;


The compiler will completely remove the !phy check entirely because of
the use above it, so it being present in the source code is completely
bogus.
If one actually needs a !phy check to be present in the compiled code,
one must arrange it as per the patch above.

The fact that the !phy check is in the source code, implies to me that
someone, in the past, thought it was necessary, but I think an opinion
could be taken that it is there to obfuscate a security vulnerability.

Kind Regards

James


From devnull+j.ne.posteo.net at kernel.org  Sun Mar 23 05:37:49 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 23 Mar 2025 13:37:49 +0100
Subject: [PATCH 0/3] Board support for Fernsehfee 3.0
Message-ID: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>

Fernsehfee[1] ("TV fairy") is a family of set-top boxes marketed as
ad-blocking appliances. This patchset adds board support in the form of
a device tree for the third generation, Fernsehfee 3.0.

[1]: https://fernsehfee.de/ (German), https://www.telefairy.com/ (English)

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
J. Neusch?fer (3):
      dt-bindings: vendor-prefixes: Add TC Unterhaltungselektronik AG
      dt-bindings: arm: amlogic: Add TCU Fernsehfee 3.0 board
      ARM: dts: amlogic: Add TCU Fernsehfee 3.0

 Documentation/devicetree/bindings/arm/amlogic.yaml |   1 +
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 arch/arm/boot/dts/amlogic/Makefile                 |   1 +
 arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts   | 219 +++++++++++++++++++++
 arch/arm/boot/dts/amlogic/meson8.dtsi              |  18 ++
 5 files changed, 241 insertions(+)
---
base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
change-id: 20250315-fernsehfee-b5aef930ca7e

Best regards,
-- 
J. Neusch?fer <j.ne at posteo.net>




From devnull+j.ne.posteo.net at kernel.org  Sun Mar 23 05:37:51 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 23 Mar 2025 13:37:51 +0100
Subject: [PATCH 2/3] dt-bindings: arm: amlogic: Add TCU Fernsehfee 3.0
 board
In-Reply-To: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
Message-ID: <20250323-fernsehfee-v1-2-2621341cd37a@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

Fernsehfee ("TV fairy") 3.0 is a set-top box with HDMI input and output
ports. It originally ran Android 4.4 and a Linux 3.10 kernel.

  https://fernsehfee.de/  (German)
  https://telefairy.com/  (English)

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 0647851ae1f55a27bfb148252532bcf15ca905bf..f6f045528da32cf4625b30da59262ca21da860e6 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -27,6 +27,7 @@ properties:
         items:
           - enum:
               - minix,neo-x8
+              - tcu,fernsehfee3
           - const: amlogic,meson8
 
       - description: Boards with the Amlogic Meson8m2 SoC

-- 
2.48.0.rc1.219.gb6b6757d772




From kw at linux.com  Sun Mar 23 05:38:03 2025
From: kw at linux.com (Krzysztof =?utf-8?Q?Wilczy=C5=84ski?=)
Date: Sun, 23 Mar 2025 21:38:03 +0900
Subject: [PATCH][next] PCI: brcmstb: make const read-only arrays static
In-Reply-To: <20250317143456.477901-1-colin.i.king@gmail.com>
References: <20250317143456.477901-1-colin.i.king@gmail.com>
Message-ID: <20250323123803.GG1902347@rocinante>

Hello,

> Don't populate the const read-only arrays data and regs on the stack at
> run time, instead make them static.

Applied to controller/brcmstb, thank you!

	Krzysztof


From devnull+j.ne.posteo.net at kernel.org  Sun Mar 23 05:37:50 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 23 Mar 2025 13:37:50 +0100
Subject: [PATCH 1/3] dt-bindings: vendor-prefixes: Add TC
 Unterhaltungselektronik AG
In-Reply-To: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
Message-ID: <20250323-fernsehfee-v1-1-2621341cd37a@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

TC Unterhaltungselektronik is the company behind Fernsehfee branded
set-top boxes.

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 5079ca6ce1d1e9e2b52312439e4b1d48b262200c..0019f6131bbfc11ba55f5a15a238825abf665aaf 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1484,6 +1484,8 @@ patternProperties:
     description: Toby Churchill Ltd.
   "^tcs,.*":
     description: Shenzhen City Tang Cheng Technology Co., Ltd.
+  "^tcu,.*":
+    description: TC Unterhaltungselektronik AG
   "^tdo,.*":
     description: Shangai Top Display Optoelectronics Co., Ltd
   "^team-source-display,.*":

-- 
2.48.0.rc1.219.gb6b6757d772




From devnull+j.ne.posteo.net at kernel.org  Sun Mar 23 05:37:52 2025
From: devnull+j.ne.posteo.net at kernel.org (=?utf-8?q?J=2E_Neusch=C3=A4fer_via_B4_Relay?=)
Date: Sun, 23 Mar 2025 13:37:52 +0100
Subject: [PATCH 3/3] ARM: dts: amlogic: Add TCU Fernsehfee 3.0
In-Reply-To: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
Message-ID: <20250323-fernsehfee-v1-3-2621341cd37a@posteo.net>

From: "J. Neusch?fer" <j.ne at posteo.net>

Fernsehfee[1] ("TV fairy") 3.0 is a set-top box with HDMI input and
output ports. It originally ran Android 4.4 and a Linux 3.10 kernel.

The following features are tested and known to work:

- Ethernet
- Power LED (switching between green and red)
- Power button
- eMMC
- SD Card
- USB
- Wifi

The following features are untested or not working:

- HDMI input and output
- Infrared remote control input and output

[1]: https://fernsehfee.de/ (German), https://telefairy.com/ (English)

Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
---
 arch/arm/boot/dts/amlogic/Makefile               |   1 +
 arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts | 219 +++++++++++++++++++++++
 arch/arm/boot/dts/amlogic/meson8.dtsi            |  18 ++
 3 files changed, 238 insertions(+)

diff --git a/arch/arm/boot/dts/amlogic/Makefile b/arch/arm/boot/dts/amlogic/Makefile
index 504c533b1173298ec7f45099888d88b2fb74b978..3c8a1e88b386cd7fb9b5f41f47d7ff78fe7eeacc 100644
--- a/arch/arm/boot/dts/amlogic/Makefile
+++ b/arch/arm/boot/dts/amlogic/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 dtb-$(CONFIG_MACH_MESON8) += \
 	meson8-minix-neo-x8.dtb \
+	meson8-fernsehfee3.dtb \
 	meson8b-ec100.dtb \
 	meson8b-mxq.dtb \
 	meson8b-odroidc1.dtb \
diff --git a/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts b/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts
new file mode 100644
index 0000000000000000000000000000000000000000..47507316ac4a56f2bcf84ad0446a06ea9fe890cd
--- /dev/null
+++ b/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+// Copyright (C) 2025 J. Neusch?fer <j.ne at posteo.net>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+
+#include "meson8.dtsi"
+
+/ {
+	model = "Fernsehfee 3.0";
+	compatible = "tcu,fernsehfee3", "amlogic,meson8";
+
+	aliases {
+		serial0 = &uart_AO;
+		gpiochip0 = &gpio;
+		gpiochip1 = &gpio_ao;
+		i2c0 = &i2c_AO;
+		i2c1 = &i2c_B;
+		mmc0 = &sdhc;
+		mmc1 = &sdio;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;  /* 1 GiB */
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys-polled";
+		poll-interval = <100>;
+
+		power-button {
+			label = "Power button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0 {
+			/*
+			 * The power LED can be turned red, otherwise it is green.
+			 */
+			gpios = <&gpio_ao GPIO_TEST_N GPIO_ACTIVE_LOW>;
+			function = LED_FUNCTION_POWER;
+			color = <LED_COLOR_ID_RED>;
+		};
+	};
+
+	vcc_5v: regulator-5v {
+		/* 5V rail, always on as long as the system is running */
+		compatible = "regulator-fixed";
+		regulator-name = "5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	vcc_3v3: regulator-3v3 {
+		/* Chipown AP2420 step-down converter */
+		compatible = "regulator-fixed";
+		regulator-name = "3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_5v>;
+	};
+
+	vcc_1v8: regulator-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_3v3>;
+	};
+
+	wifi_3v3: regulator-wifi {
+		compatible = "regulator-fixed";
+		regulator-name = "3.3V-WIFI";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_3v3>;
+		gpio = <&gpio GPIOX_11 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+	phy-mode = "rmii";
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy at 0 {
+			/* IC Plus IP101A (0x02430c54) */
+			reg = <0>;
+
+			reset-assert-us = <10000>;
+			reset-deassert-us = <10000>;
+			reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&i2c_AO {
+	status = "okay";
+	pinctrl-0 = <&i2c_ao_pins>;
+	pinctrl-names = "default";
+
+	pmic at 32 {
+		compatible = "ricoh,rn5t618";
+		reg = <0x32>;
+		system-power-controller;
+	};
+
+	eeprom at 50 {
+		/* Fairchild FM24C08A */
+		compatible = "atmel,24c08";
+		reg = <0x50>;
+		pagesize = <16>;
+		wp-gpios = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>;
+		num-addresses = <4>;
+	};
+};
+
+&i2c_B {
+	status = "okay";
+	pinctrl-0 = <&i2c_b_pins>;
+	pinctrl-names = "default";
+
+	/* TODO: SiI9293 HDMI receiver @ 0x39 */
+};
+
+&sdhc {
+	status = "okay";
+	pinctrl-0 = <&sdxc_c_pins>;
+	pinctrl-names = "default";
+
+	/* eMMC */
+	bus-width = <8>;
+	max-frequency = <100000000>;
+
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	no-sdio;
+
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vcc_1v8>;
+};
+
+&sdio {
+	status = "okay";
+	pinctrl-0 = <&sd_b_pins>;
+
+	/* SD card */
+	sd_card_slot: slot at 1 {
+		compatible = "mmc-slot";
+		reg = <1>;
+		status = "okay";
+
+		bus-width = <4>;
+		cap-mmc-highspeed;
+		cap-sd-highspeed;
+		disable-wp;
+
+		cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
+
+		vmmc-supply = <&vcc_3v3>;
+	};
+};
+
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+	/*
+	 * This bus features a Realtek RTL8188 2.4GHz WiFi module, with a
+	 * 3.3V supply voltage that must be enabled before use.
+	 */
+	vbus-supply = <&wifi_3v3>;
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&ir_receiver {
+	status = "okay";
+	pinctrl-0 = <&ir_recv_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm/boot/dts/amlogic/meson8.dtsi b/arch/arm/boot/dts/amlogic/meson8.dtsi
index 9ff142d9fe3f4576fdd3230a966c8a6250870de7..300eccbfc0071ce10290be1c496132ac6b6a4dbc 100644
--- a/arch/arm/boot/dts/amlogic/meson8.dtsi
+++ b/arch/arm/boot/dts/amlogic/meson8.dtsi
@@ -477,6 +477,14 @@ gpio: bank at 80 {
 			gpio-ranges = <&pinctrl_cbus 0 0 120>;
 		};
 
+		i2c_b_pins: i2c-b {
+			mux {
+				groups = "i2c_sda_b", "i2c_sck_b";
+				function = "i2c_b";
+				bias-disable;
+			};
+		};
+
 		sd_a_pins: sd-a {
 			mux {
 				groups = "sd_d0_a", "sd_d1_a", "sd_d2_a",
@@ -522,6 +530,16 @@ mux {
 			};
 		};
 
+		sdxc_c_pins: sdxc-c {
+			mux {
+				groups = "sdxc_d0_c", "sdxc_d13_c",
+					"sdxc_clk_c", "sdxc_cmd_c",
+					"sdxc_d47_c";
+				function = "sdxc_c";
+				bias_pull_up;
+			};
+		};
+
 		spdif_out_pins: spdif-out {
 			mux {
 				groups = "spdif_out";

-- 
2.48.0.rc1.219.gb6b6757d772




From ardb at kernel.org  Sun Mar 23 08:35:29 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Sun, 23 Mar 2025 16:35:29 +0100
Subject: [PATCH v2 08/12] lib/crc_kunit.c: add KUnit test suite for CRC
 library functions
In-Reply-To: <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net>
References: <20241202012056.209768-1-ebiggers@kernel.org> <20241202012056.209768-9-ebiggers@kernel.org>
 <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net>
Message-ID: <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>

On Sat, 22 Mar 2025 at 15:33, Guenter Roeck <linux at roeck-us.net> wrote:
>
> Hi,
>
> On Sun, Dec 01, 2024 at 05:20:52PM -0800, Eric Biggers wrote:
> > From: Eric Biggers <ebiggers at google.com>
> >
> > Add a KUnit test suite for the crc16, crc_t10dif, crc32_le, crc32_be,
> > crc32c, and crc64_be library functions.  It avoids code duplication by
> > sharing most logic among all CRC variants.  The test suite includes:
> >
> > - Differential fuzz test of each CRC function against a simple
> >   bit-at-a-time reference implementation.
> > - Test for CRC combination, when implemented by a CRC variant.
> > - Optional benchmark of each CRC function with various data lengths.
> >
> > This is intended as a replacement for crc32test and crc16_kunit, as well
> > as a new test for CRC variants which didn't previously have a test.
> >
> > Reviewed-by: Ard Biesheuvel <ardb at kernel.org>
> > Reviewed-by: Martin K. Petersen <martin.petersen at oracle.com>
> > Cc: Vinicius Peixoto <vpeixoto at lkcamp.dev>
> > Signed-off-by: Eric Biggers <ebiggers at google.com>
> > ---
> ...
> > +
> > +             nosimd = rand32() % 8 == 0;
> > +
> > +             /*
> > +              * Compute the CRC, and verify that it equals the CRC computed
> > +              * by a simple bit-at-a-time reference implementation.
> > +              */
> > +             expected_crc = crc_ref(v, init_crc, &test_buffer[offset], len);
> > +             if (nosimd)
> > +                     local_irq_disable();
> > +             actual_crc = v->func(init_crc, &test_buffer[offset], len);
> > +             if (nosimd)
> > +                     local_irq_enable();
>
> This triggers a traceback on some arm systems.
>
> [    7.810000]     ok 2 crc16_benchmark # SKIP not enabled
> [    7.810000] ------------[ cut here ]------------
> [    7.810000] WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
> [    7.810000] Modules linked in:
> [    7.810000] CPU: 0 UID: 0 PID: 1145 Comm: kunit_try_catch Tainted: G                 N 6.14.0-rc7-00196-g88d324e69ea9 #1
> [    7.810000] Tainted: [N]=TEST
> [    7.810000] Hardware name: NPCM7XX Chip family
> [    7.810000] Call trace:
> [    7.810000]  unwind_backtrace from show_stack+0x10/0x14
> [    7.810000]  show_stack from dump_stack_lvl+0x7c/0xac
> [    7.810000]  dump_stack_lvl from __warn+0x7c/0x1b8
> [    7.810000]  __warn from warn_slowpath_fmt+0x19c/0x1a4
> [    7.810000]  warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
> [    7.810000]  __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
> [    7.810000]  crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
> [    7.810000]  crc_t10dif_wrapper from crc_main_test+0x178/0x360
> [    7.810000]  crc_main_test from kunit_try_run_case+0x78/0x1e0
> [    7.810000]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
> [    7.810000]  kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
> [    7.810000]  kthread from ret_from_fork+0x14/0x28
> [    7.810000] Exception stack(0xe3651fb0 to 0xe3651ff8)
> [    7.810000] 1fa0:                                     00000000 00000000 00000000 00000000
> [    7.810000] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [    7.810000] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [    7.810000] irq event stamp: 29
> [    7.810000] hardirqs last  enabled at (27): [<c037875c>] __local_bh_enable_ip+0xb4/0x194
> [    7.810000] hardirqs last disabled at (28): [<c0b09684>] crc_main_test+0x2e4/0x360
> [    7.810000] softirqs last  enabled at (26): [<c032a3ac>] kernel_neon_end+0x0/0x1c
> [    7.810000] softirqs last disabled at (29): [<c032a3c8>] kernel_neon_begin+0x0/0x70
> [    7.810000] ---[ end trace 0000000000000000 ]---
> [    8.050000]     # crc_t10dif_test: pass:1 fail:0 skip:0 total:1
>
> kernel_neon_end() calls local_bh_enable() which apparently conflicts with
> the local_irq_disable() in above code.
>

This seems to be an oversight on my part. Can you try the below please?

diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
index 82191dbd7e78..56ddbd3c4997 100644
--- a/arch/arm/include/asm/simd.h
+++ b/arch/arm/include/asm/simd.h
@@ -4,5 +4,6 @@

 static __must_check inline bool may_use_simd(void)
 {
-       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
+       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
+              !in_hardirq() && !irqs_disabled();
 }

However, this test code also appears to assume that SIMD is forbidden
on any architecture when IRQs are disabled, but this not guaranteed.


From linux at roeck-us.net  Sun Mar 23 09:18:58 2025
From: linux at roeck-us.net (Guenter Roeck)
Date: Sun, 23 Mar 2025 09:18:58 -0700
Subject: [PATCH v2 08/12] lib/crc_kunit.c: add KUnit test suite for CRC
 library functions
In-Reply-To: <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>
References: <20241202012056.209768-1-ebiggers@kernel.org>
 <20241202012056.209768-9-ebiggers@kernel.org>
 <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net>
 <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>
Message-ID: <22812c03-1b64-4e1c-b260-cddc14ea3e8f@roeck-us.net>

On 3/23/25 08:35, Ard Biesheuvel wrote:
[ ... ]
>> kernel_neon_end() calls local_bh_enable() which apparently conflicts with
>> the local_irq_disable() in above code.
>>
> 
> This seems to be an oversight on my part. Can you try the below please?
> 
> diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
> index 82191dbd7e78..56ddbd3c4997 100644
> --- a/arch/arm/include/asm/simd.h
> +++ b/arch/arm/include/asm/simd.h
> @@ -4,5 +4,6 @@
> 
>   static __must_check inline bool may_use_simd(void)
>   {
> -       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
> +       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
> +              !in_hardirq() && !irqs_disabled();
>   }
> 
Yes, that fixes the problem.

Thanks,
Guenter



From ebiggers at kernel.org  Sun Mar 23 10:12:43 2025
From: ebiggers at kernel.org (Eric Biggers)
Date: Sun, 23 Mar 2025 10:12:43 -0700
Subject: [PATCH v2 08/12] lib/crc_kunit.c: add KUnit test suite for CRC
 library functions
In-Reply-To: <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>
References: <20241202012056.209768-1-ebiggers@kernel.org>
 <20241202012056.209768-9-ebiggers@kernel.org>
 <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net>
 <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>
Message-ID: <20250323171243.GA852@quark.localdomain>

On Sun, Mar 23, 2025 at 04:35:29PM +0100, Ard Biesheuvel wrote:
> On Sat, 22 Mar 2025 at 15:33, Guenter Roeck <linux at roeck-us.net> wrote:
> >
> > Hi,
> >
> > On Sun, Dec 01, 2024 at 05:20:52PM -0800, Eric Biggers wrote:
> > > From: Eric Biggers <ebiggers at google.com>
> > >
> > > Add a KUnit test suite for the crc16, crc_t10dif, crc32_le, crc32_be,
> > > crc32c, and crc64_be library functions.  It avoids code duplication by
> > > sharing most logic among all CRC variants.  The test suite includes:
> > >
> > > - Differential fuzz test of each CRC function against a simple
> > >   bit-at-a-time reference implementation.
> > > - Test for CRC combination, when implemented by a CRC variant.
> > > - Optional benchmark of each CRC function with various data lengths.
> > >
> > > This is intended as a replacement for crc32test and crc16_kunit, as well
> > > as a new test for CRC variants which didn't previously have a test.
> > >
> > > Reviewed-by: Ard Biesheuvel <ardb at kernel.org>
> > > Reviewed-by: Martin K. Petersen <martin.petersen at oracle.com>
> > > Cc: Vinicius Peixoto <vpeixoto at lkcamp.dev>
> > > Signed-off-by: Eric Biggers <ebiggers at google.com>
> > > ---
> > ...
> > > +
> > > +             nosimd = rand32() % 8 == 0;
> > > +
> > > +             /*
> > > +              * Compute the CRC, and verify that it equals the CRC computed
> > > +              * by a simple bit-at-a-time reference implementation.
> > > +              */
> > > +             expected_crc = crc_ref(v, init_crc, &test_buffer[offset], len);
> > > +             if (nosimd)
> > > +                     local_irq_disable();
> > > +             actual_crc = v->func(init_crc, &test_buffer[offset], len);
> > > +             if (nosimd)
> > > +                     local_irq_enable();
> >
> > This triggers a traceback on some arm systems.
> >
> > [    7.810000]     ok 2 crc16_benchmark # SKIP not enabled
> > [    7.810000] ------------[ cut here ]------------
> > [    7.810000] WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
> > [    7.810000] Modules linked in:
> > [    7.810000] CPU: 0 UID: 0 PID: 1145 Comm: kunit_try_catch Tainted: G                 N 6.14.0-rc7-00196-g88d324e69ea9 #1
> > [    7.810000] Tainted: [N]=TEST
> > [    7.810000] Hardware name: NPCM7XX Chip family
> > [    7.810000] Call trace:
> > [    7.810000]  unwind_backtrace from show_stack+0x10/0x14
> > [    7.810000]  show_stack from dump_stack_lvl+0x7c/0xac
> > [    7.810000]  dump_stack_lvl from __warn+0x7c/0x1b8
> > [    7.810000]  __warn from warn_slowpath_fmt+0x19c/0x1a4
> > [    7.810000]  warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
> > [    7.810000]  __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
> > [    7.810000]  crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
> > [    7.810000]  crc_t10dif_wrapper from crc_main_test+0x178/0x360
> > [    7.810000]  crc_main_test from kunit_try_run_case+0x78/0x1e0
> > [    7.810000]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
> > [    7.810000]  kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
> > [    7.810000]  kthread from ret_from_fork+0x14/0x28
> > [    7.810000] Exception stack(0xe3651fb0 to 0xe3651ff8)
> > [    7.810000] 1fa0:                                     00000000 00000000 00000000 00000000
> > [    7.810000] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > [    7.810000] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> > [    7.810000] irq event stamp: 29
> > [    7.810000] hardirqs last  enabled at (27): [<c037875c>] __local_bh_enable_ip+0xb4/0x194
> > [    7.810000] hardirqs last disabled at (28): [<c0b09684>] crc_main_test+0x2e4/0x360
> > [    7.810000] softirqs last  enabled at (26): [<c032a3ac>] kernel_neon_end+0x0/0x1c
> > [    7.810000] softirqs last disabled at (29): [<c032a3c8>] kernel_neon_begin+0x0/0x70
> > [    7.810000] ---[ end trace 0000000000000000 ]---
> > [    8.050000]     # crc_t10dif_test: pass:1 fail:0 skip:0 total:1
> >
> > kernel_neon_end() calls local_bh_enable() which apparently conflicts with
> > the local_irq_disable() in above code.
> >
> 
> This seems to be an oversight on my part. Can you try the below please?
> 
> diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
> index 82191dbd7e78..56ddbd3c4997 100644
> --- a/arch/arm/include/asm/simd.h
> +++ b/arch/arm/include/asm/simd.h
> @@ -4,5 +4,6 @@
> 
>  static __must_check inline bool may_use_simd(void)
>  {
> -       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
> +       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
> +              !in_hardirq() && !irqs_disabled();
>  }

Thanks Ard, you beat me to it.  Yes, may_use_simd() needs to be consistent with
kernel_neon_begin().  On x86 there is a case where the equivalent function is
expected to work when irqs_disabled(), but if there is no such case on arm this
fix looks good.  Can you send it out as a formal patch?  Presumably for the arm
maintainer to pick up.

> However, this test code also appears to assume that SIMD is forbidden
> on any architecture when IRQs are disabled, but this not guaranteed.

Yes, to reliably test the no-SIMD code paths, I need to finish refactoring the
crypto_simd_disabled_for_test stuff to be disentangled from the crypto subsystem
so that crc_kunit.c can use it.  It's on my list of things to do, and I'm
planning to get it done in 6.16.  Disabling hardirqs is just a trick to get
there more easily on some architectures.  But as this shows it's a useful test
to have anyway, so we'll want to keep that too.  The CRC functions need to work
in any context, and any context that we can easily test we should do so.

- Eric


From j.ne at posteo.net  Sun Mar 23 10:31:32 2025
From: j.ne at posteo.net (=?utf-8?Q?J=2E_Neusch=C3=A4fer?=)
Date: Sun, 23 Mar 2025 17:31:32 +0000
Subject: HDMI output (Re: [PATCH 3/3] ARM: dts: amlogic: Add TCU Fernsehfee
 3.0)
In-Reply-To: <20250323-fernsehfee-v1-3-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
 <20250323-fernsehfee-v1-3-2621341cd37a@posteo.net>
Message-ID: <Z-BFdMfqVCX4T3NB@probook>

On Sun, Mar 23, 2025 at 01:37:52PM +0100, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> Fernsehfee[1] ("TV fairy") 3.0 is a set-top box with HDMI input and
> output ports. It originally ran Android 4.4 and a Linux 3.10 kernel.
> 
> The following features are tested and known to work:
> 
> - Ethernet
> - Power LED (switching between green and red)
> - Power button
> - eMMC
> - SD Card
> - USB
> - Wifi
> 
> The following features are untested or not working:
> 
> - HDMI input and output
> - Infrared remote control input and output

FWIW, with Martin Blumenstingl's meson-mx-integration-6.13-20250112
branch, HDMI output works (albeit not at all resolutions).


Best regards,
J. Neusch?fer


From Markus.Elfring at web.de  Sun Mar 23 10:30:53 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sun, 23 Mar 2025 18:30:53 +0100
Subject: [PATCH v2] wifi: mt76: mt7996: prevent uninit return in
 mt7996_mac_sta_add_links
In-Reply-To: <20250322230137.28164-1-qasdev00@gmail.com>
References: <20250322230137.28164-1-qasdev00@gmail.com>
Message-ID: <6a45eb0a-01e2-4316-bbee-93bdd490cfb5@web.de>

?
> or link_sta_dereference_protected() fail the code jumps to
> the error_unlink label and returns ret which is uninitialised.
?

* Would you like to avoid typos in such a change description?

* Can any background information become more relevant for the usage of
  source code analysis tools?

* Can the summary phrase be improved also another bit?


?
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -998,16 +998,22 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
>  			continue;
>
>  		link_conf = link_conf_dereference_protected(vif, link_id);
> -		if (!link_conf)
> +		if (!link_conf) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
>
>  		link = mt7996_vif_link(dev, vif, link_id);
> -		if (!link)
> +		if (!link) {
> +			err = -EINVAL;
>  			goto error_unlink;
> +		}
?

Can software development interests evolve in ways which might make the avoidance
of duplicate source code more feasible also for affected error/exception handling?

Regards,
Markus


From krzk at kernel.org  Sun Mar 23 10:31:17 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 23 Mar 2025 18:31:17 +0100
Subject: [PATCH 1/3] dt-bindings: vendor-prefixes: Add TC
 Unterhaltungselektronik AG
In-Reply-To: <20250323-fernsehfee-v1-1-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
 <20250323-fernsehfee-v1-1-2621341cd37a@posteo.net>
Message-ID: <9a98186c-fc70-459e-a20f-02c45cb7c3cd@kernel.org>

On 23/03/2025 13:37, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> TC Unterhaltungselektronik is the company behind Fernsehfee branded
> set-top boxes.
> 
> Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
> ---

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From krzk at kernel.org  Sun Mar 23 10:31:41 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 23 Mar 2025 18:31:41 +0100
Subject: [PATCH 2/3] dt-bindings: arm: amlogic: Add TCU Fernsehfee 3.0
 board
In-Reply-To: <20250323-fernsehfee-v1-2-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
 <20250323-fernsehfee-v1-2-2621341cd37a@posteo.net>
Message-ID: <2842b994-6970-4f31-9a9a-ff8dd1e9b212@kernel.org>

On 23/03/2025 13:37, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> Fernsehfee ("TV fairy") 3.0 is a set-top box with HDMI input and output
> ports. It originally ran Android 4.4 and a Linux 3.10 kernel.
> 
>   https://fernsehfee.de/  (German)
>   https://telefairy.com/  (English)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From ardb at kernel.org  Sun Mar 23 11:17:14 2025
From: ardb at kernel.org (Ard Biesheuvel)
Date: Sun, 23 Mar 2025 19:17:14 +0100
Subject: [PATCH v2 08/12] lib/crc_kunit.c: add KUnit test suite for CRC
 library functions
In-Reply-To: <20250323171243.GA852@quark.localdomain>
References: <20241202012056.209768-1-ebiggers@kernel.org> <20241202012056.209768-9-ebiggers@kernel.org>
 <389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net> <CAMj1kXHAktbQ-605wfqXCWtn8bP-yEv8sYKWAykajeAX2m1hEA@mail.gmail.com>
 <20250323171243.GA852@quark.localdomain>
Message-ID: <CAMj1kXGMtpMuiJqwWVuWDhRrb-dXC30Fj0vu0vU=O6-gGR0FWg@mail.gmail.com>

On Sun, 23 Mar 2025 at 18:12, Eric Biggers <ebiggers at kernel.org> wrote:
>
> On Sun, Mar 23, 2025 at 04:35:29PM +0100, Ard Biesheuvel wrote:
> > On Sat, 22 Mar 2025 at 15:33, Guenter Roeck <linux at roeck-us.net> wrote:
> > >
> > > Hi,
> > >
> > > On Sun, Dec 01, 2024 at 05:20:52PM -0800, Eric Biggers wrote:
> > > > From: Eric Biggers <ebiggers at google.com>
> > > >
> > > > Add a KUnit test suite for the crc16, crc_t10dif, crc32_le, crc32_be,
> > > > crc32c, and crc64_be library functions.  It avoids code duplication by
> > > > sharing most logic among all CRC variants.  The test suite includes:
> > > >
> > > > - Differential fuzz test of each CRC function against a simple
> > > >   bit-at-a-time reference implementation.
> > > > - Test for CRC combination, when implemented by a CRC variant.
> > > > - Optional benchmark of each CRC function with various data lengths.
> > > >
> > > > This is intended as a replacement for crc32test and crc16_kunit, as well
> > > > as a new test for CRC variants which didn't previously have a test.
> > > >
> > > > Reviewed-by: Ard Biesheuvel <ardb at kernel.org>
> > > > Reviewed-by: Martin K. Petersen <martin.petersen at oracle.com>
> > > > Cc: Vinicius Peixoto <vpeixoto at lkcamp.dev>
> > > > Signed-off-by: Eric Biggers <ebiggers at google.com>
> > > > ---
> > > ...
> > > > +
> > > > +             nosimd = rand32() % 8 == 0;
> > > > +
> > > > +             /*
> > > > +              * Compute the CRC, and verify that it equals the CRC computed
> > > > +              * by a simple bit-at-a-time reference implementation.
> > > > +              */
> > > > +             expected_crc = crc_ref(v, init_crc, &test_buffer[offset], len);
> > > > +             if (nosimd)
> > > > +                     local_irq_disable();
> > > > +             actual_crc = v->func(init_crc, &test_buffer[offset], len);
> > > > +             if (nosimd)
> > > > +                     local_irq_enable();
> > >
> > > This triggers a traceback on some arm systems.
> > >
> > > [    7.810000]     ok 2 crc16_benchmark # SKIP not enabled
> > > [    7.810000] ------------[ cut here ]------------
> > > [    7.810000] WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
> > > [    7.810000] Modules linked in:
> > > [    7.810000] CPU: 0 UID: 0 PID: 1145 Comm: kunit_try_catch Tainted: G                 N 6.14.0-rc7-00196-g88d324e69ea9 #1
> > > [    7.810000] Tainted: [N]=TEST
> > > [    7.810000] Hardware name: NPCM7XX Chip family
> > > [    7.810000] Call trace:
> > > [    7.810000]  unwind_backtrace from show_stack+0x10/0x14
> > > [    7.810000]  show_stack from dump_stack_lvl+0x7c/0xac
> > > [    7.810000]  dump_stack_lvl from __warn+0x7c/0x1b8
> > > [    7.810000]  __warn from warn_slowpath_fmt+0x19c/0x1a4
> > > [    7.810000]  warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
> > > [    7.810000]  __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
> > > [    7.810000]  crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
> > > [    7.810000]  crc_t10dif_wrapper from crc_main_test+0x178/0x360
> > > [    7.810000]  crc_main_test from kunit_try_run_case+0x78/0x1e0
> > > [    7.810000]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
> > > [    7.810000]  kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
> > > [    7.810000]  kthread from ret_from_fork+0x14/0x28
> > > [    7.810000] Exception stack(0xe3651fb0 to 0xe3651ff8)
> > > [    7.810000] 1fa0:                                     00000000 00000000 00000000 00000000
> > > [    7.810000] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > > [    7.810000] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> > > [    7.810000] irq event stamp: 29
> > > [    7.810000] hardirqs last  enabled at (27): [<c037875c>] __local_bh_enable_ip+0xb4/0x194
> > > [    7.810000] hardirqs last disabled at (28): [<c0b09684>] crc_main_test+0x2e4/0x360
> > > [    7.810000] softirqs last  enabled at (26): [<c032a3ac>] kernel_neon_end+0x0/0x1c
> > > [    7.810000] softirqs last disabled at (29): [<c032a3c8>] kernel_neon_begin+0x0/0x70
> > > [    7.810000] ---[ end trace 0000000000000000 ]---
> > > [    8.050000]     # crc_t10dif_test: pass:1 fail:0 skip:0 total:1
> > >
> > > kernel_neon_end() calls local_bh_enable() which apparently conflicts with
> > > the local_irq_disable() in above code.
> > >
> >
> > This seems to be an oversight on my part. Can you try the below please?
> >
> > diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
> > index 82191dbd7e78..56ddbd3c4997 100644
> > --- a/arch/arm/include/asm/simd.h
> > +++ b/arch/arm/include/asm/simd.h
> > @@ -4,5 +4,6 @@
> >
> >  static __must_check inline bool may_use_simd(void)
> >  {
> > -       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
> > +       return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
> > +              !in_hardirq() && !irqs_disabled();
> >  }
>
> Thanks Ard, you beat me to it.  Yes, may_use_simd() needs to be consistent with
> kernel_neon_begin().  On x86 there is a case where the equivalent function is
> expected to work when irqs_disabled(), but if there is no such case on arm this
> fix looks good.  Can you send it out as a formal patch?  Presumably for the arm
> maintainer to pick up.
>

Sure.

On other architectures, we might just turn this logic around, and only
disable softirqs when IRQs are enabled, as otherwise, there is no
need: we don't care about whether or not IRQs are disabled, only the
softirq plumbing that we need to call into does, and no softirqs can
be delivered over the back of a hard IRQ when those are disabled to
begin with.

> > However, this test code also appears to assume that SIMD is forbidden
> > on any architecture when IRQs are disabled, but this not guaranteed.
>
> Yes, to reliably test the no-SIMD code paths, I need to finish refactoring the
> crypto_simd_disabled_for_test stuff to be disentangled from the crypto subsystem
> so that crc_kunit.c can use it.  It's on my list of things to do, and I'm
> planning to get it done in 6.16.  Disabling hardirqs is just a trick to get
> there more easily on some architectures.  But as this shows it's a useful test
> to have anyway, so we'll want to keep that too.  The CRC functions need to work
> in any context, and any context that we can easily test we should do so.
>

Sounds good.


From jgg at nvidia.com  Sun Mar 23 11:55:52 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Sun, 23 Mar 2025 15:55:52 -0300
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <Z98Lmo50h5RboFXq@kernel.org>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-10-changyuanl@google.com>
 <20250321134629.GA252045@nvidia.com>
 <Z98Lmo50h5RboFXq@kernel.org>
Message-ID: <Z+BZOKSpyPA1Pyu+@nvidia.com>

On Sat, Mar 22, 2025 at 03:12:26PM -0400, Mike Rapoport wrote:
> This hunk actually came from me. I decided to keep it simple for now and
> check what are the alternatives, like moving away from memblock_reserve(),
> adding a maple_tree or even something else.

Okat, makes sense to me
 
> > > +		page->private = order;
> > 
> > Can't just set the page order directly? Why use private?
> 
> Setting the order means recreating the folio the way prep_compound_page()
> does. I think it's better to postpone it until the folio is requested. This
> way it might run after SMP is enabled. 

I see, that makes sense, but also it could stil use page->order..

> Besides, when we start allocating
> folios separately from struct page, initializing it here would be a real
> issue.

Yes, but also we wouldn't have page->private to make it work.. Somehow
anything we want to carry over would have to become encoded in the
memdesc directly.

I think this supports my remark someplace else that any user of this
that wants to preserve per-page data should do it on its own somehow
as an add-on-top?

Jason


From changyuanl at google.com  Sun Mar 23 12:02:04 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Sun, 23 Mar 2025 12:02:04 -0700
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation helpers
In-Reply-To: <20250321133447.GA251739@nvidia.com>
References: <20250321133447.GA251739@nvidia.com>
Message-ID: <20250323190204.742672-1-changyuanl@google.com>

Hi Jason, thanks for reviewing the patchset!

On Fri, Mar 21, 2025 at 10:34:47 -0300, Jason Gunthorpe <jgg at nvidia.com> wrote:
> On Wed, Mar 19, 2025 at 06:55:42PM -0700, Changyuan Lyu wrote:
> > From: Alexander Graf <graf at amazon.com>
> >
> > Add the core infrastructure to generate Kexec HandOver metadata. Kexec
> > HandOver is a mechanism that allows Linux to preserve state - arbitrary
> > properties as well as memory locations - across kexec.
> >
> > It does so using 2 concepts:
> >
> >   1) State Tree - Every KHO kexec carries a state tree that describes the
> >      state of the system. The state tree is represented as hash-tables.
> >      Device drivers can add/remove their data into/from the state tree at
> >      system runtime. On kexec, the tree is converted to FDT (flattened
> >      device tree).
>
> Why are we changing this? I much prefered the idea of having recursive
> FDTs than this notion copying eveything into tables then out into FDT?
> Now that we have the preserved pages mechanism there is a pretty
> direct path to doing recursive FDT.

We are not copying data into the hashtables, instead the hashtables only
record the address and size of the data to be serialized into FDT.
The idea is similar to recording preserved folios in xarray
and then serialize it to linked pages.

> I feel like this patch is premature, it should come later in the
> project along with a stronger justification for this approach.
>
> IHMO keep things simple for this series, just the very basics.

The main purpose of using hashtables is to enable KHO users to save
data to KHO at any time, not just at the time of activate/finalize KHO
through sysfs/debugfs. For example, FDBox can save the data into KHO
tree once a new fd is saved to KHO. Also, using hashtables allows KHO
users to add data to KHO concurrently, while with notifiers, KHO users'
callbacks are executed serially.

Regarding the suggestion of recursive FDT, I feel like it is already
doable with this patchset, or even with Mike's V4 patch. A KHO user can
just allocates a buffer, serialize all its states to the buffer using
libfdt (or even using other binary formats), save the address of the
buffer to KHO's tree, and finally register the buffer's underlying
pages/folios with kho_preserve_folio().

> > +int register_kho_notifier(struct notifier_block *nb)
> > +{
> > +	return blocking_notifier_chain_register(&kho_out.chain_head, nb);
> > +}
> > +EXPORT_SYMBOL_GPL(register_kho_notifier);
>
> And another different set of notifiers? :(

I changed the semantics of the notifiers. In Mike's V4, the KHO notifier
is to pass the fdt pointer to KHO users to push data into the blob. In
this patchset, it notifies KHO users about the last chance for saving
data to KHO.

It is not necessary for every KHO user to register a
notifier, as they can use the helper functions to save data to KHO tree
anytime (but before the KHO tree is converted and frozen). For example,
FDBox would not need a notifier if it saves data to KHO tree immediately
once an FD is registered to it.

However, some KHO users may still want to add data just before kexec,
so I kept the notifiers and allow KHO users to get notified when the
state tree hashtables are about to be frozen and converted to FDT.

> > +static int kho_finalize(void)
> > +{
> > +	int err = 0;
> > +	void *fdt;
> > +
> > +	fdt = kvmalloc(kho_out.fdt_max, GFP_KERNEL);
> > +	if (!fdt)
> > +		return -ENOMEM;
>
> We go to all the trouble of keeping track of stuff in dynamic hashes
> but still can't automatically size the fdt and keep the dumb uapi to
> have the user say? :( :(

The reason of keeping fdt_max in the this patchset is to simplify the
support of kexec_file_load().

We want to be able to do kexec_file_load()
first and then do KHO activation/finalization to move kexec_file_load()
out of the blackout window. At the time of kexec_file_load(), we need to
pass the KHO FDT address to the new kernel's setup data (x86) or
devicetree (arm), but KHO FDT is not generated yet. The simple solution
used in this patchset is to reserve a ksegment of size fdt_max and pass
the address of that ksegment to the new kernel. The final FDT is copied
to that ksegment in kernel_kexec().
The extra benefit of this solution is the reserved ksegment is
physically contiguous.

To completely remove fdt_max, I am considering the idea in [1]. At the
time of kexec_file_load(), we pass the address of an anchor page to
the new kernel, and the anchor page will later be fulfilled with the
physical addresses of the pages containing the FDT blob. Multiple
anchor pages can be linked together. The FDT blob pages can be physically
noncontiguous.

[1] https://lore.kernel.org/all/CA+CK2bBBX+HgD0HLj-AyTScM59F2wXq11BEPgejPMHoEwqj+_Q at mail.gmail.com/

Best,
Changyuan


From changyuanl at google.com  Sun Mar 23 12:07:58 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Sun, 23 Mar 2025 12:07:58 -0700
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory preservation
In-Reply-To: <20250321134629.GA252045@nvidia.com>
References: <20250321134629.GA252045@nvidia.com>
Message-ID: <20250323190758.743798-1-changyuanl@google.com>

On Fri, Mar 21, 2025 at 10:46:29 -0300, Jason Gunthorpe <jgg at nvidia.com> wrote:
> On Wed, Mar 19, 2025 at 06:55:44PM -0700, Changyuan Lyu wrote:
> > +/**
> > + * kho_preserve_folio - preserve a folio across KHO.
> > + * @folio: folio to preserve
> > + *
> > + * Records that the entire folio is preserved across KHO. The order
> > + * will be preserved as well.
> > + *
> > + * Return: 0 on success, error code on failure
> > + */
> > +int kho_preserve_folio(struct folio *folio)
> > +{
> > +	unsigned long pfn = folio_pfn(folio);
> > +	unsigned int order = folio_order(folio);
> > +	int err;
> > +
> > +	if (!kho_enable)
> > +		return -EOPNOTSUPP;
> > +
> > +	down_read(&kho_out.tree_lock);
> > +	if (kho_out.fdt) {
>
> What is the lock and fdt test for?

It is to avoid the competition between the following 2 operations,
- converting the hashtables and mem traker to FDT,
- adding new data to hashtable/mem tracker.
Please also see function kho_finalize() in the previous patch
"kexec: add Kexec HandOver (KHO) generation helpers" [1].

The function kho_finalize() iterates over all the hashtables and
the mem tracker. We want to make sure that during the iterations,
no new data is added to the hashtables and mem tracker.

Also if FDT is generated, the mem tracker then has been serialized
to linked pages, so we return -EBUSY to prevent more data from
being added to the mem tracker.

> I'm getting the feeling that probably kho_preserve_folio() and the
> like should accept some kind of
> 'struct kho_serialization *' and then we don't need this to prove we
> are within a valid serialization window. It could pass the pointer
> through the notifiers

If we use notifiers, callbacks have to be done serially.

> The global variables in this series are sort of ugly..
>
> We want this to be fast, so try hard to avoid a lock..

In most cases we only need read lock. Different KHO users can adding
data into their own subnodes in parallel.
We only need a write lock if
- 2 KHO users register subnodes to the KHO root node at the same time
- KHO root tree is about to be converted to FDT.

> > +void *kho_restore_phys(phys_addr_t phys, size_t size)
> > +{
> > +	unsigned long start_pfn, end_pfn, pfn;
> > +	void *va = __va(phys);
> > +
> > +	start_pfn = PFN_DOWN(phys);
> > +	end_pfn = PFN_UP(phys + size);
> > +
> > +	for (pfn = start_pfn; pfn < end_pfn; pfn++) {
> > +		struct page *page = pfn_to_online_page(pfn);
> > +
> > +		if (!page)
> > +			return NULL;
> > +		kho_restore_page(page);
> > +	}
> > +
> > +	return va;
> > +}
> > +EXPORT_SYMBOL_GPL(kho_restore_phys);
>
> What do you imagine this is used for? I'm not sure what value there is
> in returning a void *? How does the caller "free" this?

This function is also from Mike :)

I suppose some KHO users may still
preserve memory using memory ranges (instead of folio). In the restoring
stage they need a helper to setup the pages of reserved memory ranges.
A void * is returned so the KHO user can access the memory
contents through the virtual address.
I guess the caller can free the ranges by free_pages()?

It makes sense to return nothing and let caller to call `__va`
if they want. Then the function signature looks more symmetric to
`kho_preserve_phys`.

> > +#define KHOSER_PTR(type)          \
> > +	union {                   \
> > +		phys_addr_t phys; \
> > +		type ptr;         \
> > +	}
> > +#define KHOSER_STORE_PTR(dest, val)                 \
> > +	({                                          \
> > +		(dest).phys = virt_to_phys(val);    \
> > +		typecheck(typeof((dest).ptr), val); \
> > +	})
> > +#define KHOSER_LOAD_PTR(src) \
> > +	((src).phys ? (typeof((src).ptr))(phys_to_virt((src).phys)) : NULL)
>
> I had imagined these macros would be in a header and usably by drivers
> that also want to use structs to carry information.
>

OK I will move them to the header file in the next version.

> > [...]
> > @@ -829,6 +1305,10 @@ static __init int kho_init(void)
> >
> >  	kho_out.root.name = "";
>
> ?

Set the root node name to an empty string since fdt_begin_node
calls strlen on the node name.

It is equivalent to `err = fdt_begin_node(fdt, "")` in kho_serialize()
of Mike's V4 patch [2].

> >  	err = kho_add_string_prop(&kho_out.root, "compatible", "kho-v1");
> > +	err |= kho_add_prop(&kho_out.preserved_memory, "metadata",
> > +			    &kho_out.first_chunk_phys, sizeof(phys_addr_t));
>
> metedata doesn't fee like a great a better name..
>
> Please also document all the FDT schema thoroughly!
>
> There should be yaml files just like in the normal DT case defining
> all of this. This level of documentation and stability was one of the
> selling reasons why FDT is being used here!

YAML files were dropped because we think it may take a while for our
schema to be near stable. So we start from some simple plain text. We
can add some prop and node docs (that are considered stable at this point)
back to YAML in the next version.

[1] https://lore.kernel.org/all/20250320015551.2157511-8-changyuanl at google.com/
[2] https://lore.kernel.org/all/20250206132754.2596694-6-rppt at kernel.org/

Best,
Changyuan


From johan.korsnes at gmail.com  Sun Mar 23 12:12:39 2025
From: johan.korsnes at gmail.com (Johan Korsnes)
Date: Sun, 23 Mar 2025 20:12:39 +0100
Subject: [PATCH] arch: arm: defconfig: Drop obsolete CONFIG_NET_CLS_TCINDEX
Message-ID: <20250323191239.114181-1-johan.korsnes@gmail.com>

This option was removed from the Kconfig in commit
8c710f75256b ("net/sched: Retire tcindex classifier") but it was not
removed from the defconfigs.

Fixes: 8c710f75256b ("net/sched: Retire tcindex classifier")
Signed-off-by: Johan Korsnes <johan.korsnes at gmail.com>
Cc: Russell King <linux at armlinux.org.uk>
---
 arch/arm/configs/ixp4xx_defconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index 3cb995b9616a..9c7e55384386 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -75,7 +75,6 @@ CONFIG_NET_SCH_TBF=m
 CONFIG_NET_SCH_GRED=m
 CONFIG_NET_SCH_DSMARK=m
 CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_FW=m
 CONFIG_NET_CLS_U32=m
-- 
2.49.0



From alyssa at rosenzweig.io  Sun Mar 23 12:42:55 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 15:42:55 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
Message-ID: <Z-BkP2Kt0NYKJwfC@blossom>

> I'm good with this. There's a slim possibility that upstream may
> evolve in ways that make the current UAPI tricky to implement.
> However, given that it's based on prior art from the nouveau, Intel,
> and panfrost teams and that you've been shipping it in production for
> a while, I think that possibility is pretty remote.

Yeah, I'm not too worried about that... the uAPI isn't being designed
around the kernel driver, so unless we're deprecating GEM or something
we should be good!

>  > +????/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */ 
>  > +????DRM_ASAHI_GEM_BIND, 
> 
> I was about to complain about the GEM_BIND name but I actually prefer
> it. Given that it binds a single GEM object to a given range in a
> given VM, I think it makes sense to have it be an option on the GEM
> object. If and when you implement a bind queue, you can use VM_BIND
> for the new multi-bind ioctl and that will be an operation on the VM
> that says "bind all this stuff, here's some fences to know when."

Sounds good.

>  > +????/** @vm_user_start: VM user range start VMA */ 
>  > +????__u64 vm_user_start; 
>  > + 
>  > +????/** @vm_user_end: VM user range end VMA */ 
>  > +????__u64 vm_user_end; 
> 
> Does this have to be chosen by the kernel? Are there fixed addresses chosen by the firmware which need to be respected? Or is this just the range of valid GPU addresses? I also see kernel start/end being passed in at VM creation. I'm confused. At the very least, this needs a much better comment than the one above.

Added a bunch of comments in v4.

>  > +????/** 
>  > +???? * @vm_kernel_min_size: Minimum kernel VMA window size within user 
>  > +???? * range 
>  > +???? */ 
>  > +????__u64 vm_kernel_min_size; 

>  > +????/** 
>  > +???? * @max_commands_per_submission: Maximum number of supported commands 
>  > +???? * per submission 
>  > +???? */ 
>  > +????__u32 max_commands_per_submission; 
> 
> Pain. But we have this in nouveau as well, so...

This mirrors firmware limits. Either we have to split in userspace or
kernelspace. And at least if we split in userspace, there are no
surprises about where oversynchronization happens.

>  > +????/** 
>  > +???? * @firmware_version: GPU firmware version, as 4 integers 
>  > +???? */ 
>  > +????__u32 firmware_version[4]; 
> 
> There's a part of me that's like "This should never matter. You shouldn't expose that detail to userspace!" but let's be real...

TBH, I agree. If we need it for something later we can revisit but by
design this should never matter and current Mesa doesn't do anything
with it anyway.

Dropped in v4.

>  > + 
>  > +????/** 
>  > +???? * @user_timestamp_frequency_hz: Timebase frequency for user timestamps 
>  > +???? */ 
>  > +????__u64 user_timestamp_frequency_hz; 
> 
> Why is this different? What are user timestamps and how are they different from GPU timestamps?

I've added comments in v4 to clarify.

This does raise the question of, maybe drm_asahi_get_time should be
returning time in nanoseconds instead? I'm tempted to make that change
in v4. That would let us get rid of one of the parameters.

In practice the firmware-written "user" timestamps are themselves in
nanoseconds but we don't want to make that uAPI. We can't scale those in
the kernel (what if we write timestamps and then immediately
vkCmdCopyQuery them? We don't want to force a CPU roundtrip/stall just
for that.)

The kernel-read timestamps on current systems are from a 24MHz SoC-wide
reference clock, which both the GPU and CPU share. We can scale these in
the kernel to nanos, which is what userspace does itself currently.
Kind of bikeshed territory but meh?

>  > +????/** 
>  > +???? * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader 
>  > +???? * loads of unmapped memory will return zero. Shader stores to unmapped 
>  > +???? * memory will be silently discarded. Note that only shader load/store 
>  > +???? * is affected. Other hardware units are not affected, notably including 
>  > +???? * texture sampling. 
>  > +???? */ 
>  > +????DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0, 
>  > +}; 
> 
> This makes me a little nervous. Why isn't this a bit you can set on VM creation? If it's something that's chosen by the kernel and which userspace can query but not change, that seems problematic from a backwards compatiblity PoV.

As far as we know, the fault control register must be set during GPU
initialization and cannot be changed once we're booted. So, we can
override it only via a kernel command line parameter.

macOS enables soft fault in all production builds. We do too these days,
but we have a kernel cmdline flag to disable soft fault / enable hard
faults to aid debugging.

Mesa queries this parameter to determine whether it can speculate
aggressively loads out of control (CAN_SPECULATE) -- it can with
production Asahi systems but not when I'm running CTS on my dev box.

Maybe more problematically, Mesa also currently gates sparseBuffer on
this flag, although I'm probably going to rewrite the sparse buffer
implementation in the coming months to avoid that dependence for various
reasons.

Should I avoid releasing an upstream Mesa with sparseBuffer advertised
until the dependence is dropped, to avoid a theoretical uAPI break if we
wanted to change this policy later? (where the regression is "old Mesas
in containers lose sparseBuffer/FL12").


From jonas at kwiboo.se  Sun Mar 23 14:04:32 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 23 Mar 2025 22:04:32 +0100
Subject: [PATCH 2/3] arm64: dts: rockchip: Add DMA controller for RK3528
In-Reply-To: <20250318100010.2253408-3-amadeus@jmu.edu.cn>
References: <20250318100010.2253408-1-amadeus@jmu.edu.cn>
 <20250318100010.2253408-3-amadeus@jmu.edu.cn>
Message-ID: <201122ca-74d1-4938-9940-7da051896da9@kwiboo.se>

Hi Chukun,

On 2025-03-18 11:00, Chukun Pan wrote:
> Add DMA controller dt node for RK3528 SoC.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 7f1ffd6003f5..ad77e0ef70f2 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -493,6 +493,24 @@ sdhci: mmc at ffbf0000 {
>  			status = "disabled";
>  		};
>  
> +		dmac: dma-controller at ffd60000 {
> +			compatible = "arm,pl330", "arm,primecell";
> +			reg = <0x0 0xffd60000 0x0 0x4000>;
> +			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> +			arm,pl330-periph-burst;
> +			clocks = <&cru ACLK_DMAC>;
> +			clock-names = "apb_pclk";

nitpick:

Please move the clock related props before interrupts to keep prop order
consistent in the rk3528.dtsi-file. See [1] for preferred prop order.

[1] https://docs.kernel.org/devicetree/bindings/dts-coding-style.html#order-of-properties-in-device-node

Regards,
Jonas

> +			#dma-cells = <1>;
> +		};
> +
>  		pinctrl: pinctrl {
>  			compatible = "rockchip,rk3528-pinctrl";
>  			rockchip,grf = <&ioc_grf>;



From jonas at kwiboo.se  Sun Mar 23 14:17:06 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 23 Mar 2025 22:17:06 +0100
Subject: [PATCH v2 2/2] arm64: dts: rockchip: Enable regulators for Radxa
 E20C
In-Reply-To: <20250318120003.2340652-3-amadeus@jmu.edu.cn>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
 <20250318120003.2340652-3-amadeus@jmu.edu.cn>
Message-ID: <432b6705-4d97-4d47-bbc2-196f9b84da05@kwiboo.se>

Hi Chukun,

On 2025-03-18 13:00, Chukun Pan wrote:
> Enable pwm and fixed regulators for Radxa E20C. The pwm regulator is
> used to power the CPU and GPU. Note that the LPDDR4 voltage is 1.1V.
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  .../boot/dts/rockchip/rk3528-radxa-e20c.dts   | 72 +++++++++++++++++++
>  1 file changed, 72 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> index 57a446b5cbd6..159b55aa970d 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
> @@ -100,6 +100,16 @@ vcc_3v3: regulator-3v3-vcc {
>  		vin-supply = <&vcc5v0_sys>;
>  	};
>  
> +	vcc_ddr: regulator-vcc-ddr {

Since we know the voltage for this regulator please name the node
regulator-1v1-vcc-ddr and place it above the regulator-1v8 to keep node
order by node name (not label name).

> +		compatible = "regulator-fixed";
> +		regulator-name = "vcc_ddr";
> +		regulator-always-on;
> +		regulator-boot-on;
> +		regulator-min-microvolt = <1100000>;
> +		regulator-max-microvolt = <1100000>;
> +		vin-supply = <&vcc5v0_sys>;
> +	};
> +
>  	vcc5v0_sys: regulator-5v0-vcc-sys {
>  		compatible = "regulator-fixed";
>  		regulator-name = "vcc5v0_sys";
> @@ -108,6 +118,56 @@ vcc5v0_sys: regulator-5v0-vcc-sys {
>  		regulator-min-microvolt = <5000000>;
>  		regulator-max-microvolt = <5000000>;
>  	};
> +
> +	vdd_0v9: regulator-0v9-vdd {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vdd_0v9";
> +		regulator-always-on;
> +		regulator-boot-on;
> +		regulator-min-microvolt = <900000>;
> +		regulator-max-microvolt = <900000>;
> +		vin-supply = <&vcc5v0_sys>;
> +	};

This node is out of node name order, please place it before the
regulator-1v1-vcc-ddr node.

> +
> +	vdd_arm: regulator-vdd-arm {
> +		compatible = "pwm-regulator";

Suggest we add the pinctrl props here instead:

 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm1m0_pins>;

> +		pwms = <&pwm1 0 5000 1>;

This should use the PWM_POLARITY_INVERTED flag not 1.

Will require include of dt-bindings/pwm/pwm.h.

> +		pwm-supply = <&vcc5v0_sys>;
> +		regulator-name = "vdd_arm";
> +		regulator-always-on;
> +		regulator-boot-on;
> +		regulator-min-microvolt = <746000>;
> +		regulator-max-microvolt = <1201000>;
> +		regulator-settling-time-up-us = <250>;
> +	};
> +
> +	vdd_logic: regulator-vdd-logic {
> +		compatible = "pwm-regulator";

Same here, suggest we add the pinctrl props here instead:

 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm2m0_pins>;

> +		pwms = <&pwm2 0 5000 1>;

Same here, this should use the PWM_POLARITY_INVERTED flag not 1.

> +		pwm-supply = <&vcc5v0_sys>;
> +		regulator-name = "vdd_logic";
> +		regulator-always-on;
> +		regulator-boot-on;
> +		regulator-min-microvolt = <705000>;
> +		regulator-max-microvolt = <1006000>;
> +		regulator-settling-time-up-us = <250>;
> +	};
> +};
> +
> +&cpu0 {
> +	cpu-supply = <&vdd_arm>;
> +};
> +
> +&cpu1 {
> +	cpu-supply = <&vdd_arm>;
> +};
> +
> +&cpu2 {
> +	cpu-supply = <&vdd_arm>;
> +};
> +
> +&cpu3 {
> +	cpu-supply = <&vdd_arm>;
>  };
>  
>  &pinctrl {
> @@ -132,6 +192,18 @@ wan_led_g: wan-led-g {
>  	};
>  };
>  
> +&pwm1 {
> +	pinctrl-0 = <&pwm1m0_pins>;
> +	pinctrl-names = "default";

For consistency please put the pinctrl-names before the pinctrl-X props.
And as stated above, I suggest we move this to the regulator node.

> +	status = "okay";
> +};
> +
> +&pwm2 {
> +	pinctrl-0 = <&pwm2m0_pins>;
> +	pinctrl-names = "default";

Same here.

Regards,
Jonas

> +	status = "okay";
> +};
> +
>  &saradc {
>  	vref-supply = <&vcc_1v8>;
>  	status = "okay";



From alyssa at rosenzweig.io  Sun Mar 23 14:18:49 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 17:18:49 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
 <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
Message-ID: <Z-B6uc7EEAdBPXmt@blossom>

>  >  > +/** 
>  >  > + * enum drm_asahi_bind_op - Bind operation 
>  >  > + */ 
>  >  > +enum drm_asahi_bind_op { 
>  >  > +????/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */ 
>  >  > +????DRM_ASAHI_BIND_OP_BIND = 0, 
>  >  > + 
>  >  > +????/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */ 
>  >  > +????DRM_ASAHI_BIND_OP_UNBIND = 1, 
>  >  > + 
>  >  > +????/** @DRM_ASAHI_BIND_OP_UNBIND_ALL: Unbind all mappings of a given BO */ 
>  >  > +????DRM_ASAHI_BIND_OP_UNBIND_ALL = 2, 
> 
> Do you use this? We don't have it in nouveau and NVK gets by fine. Or does the asahi kernel do something where it expects you to unbind everything before the buffer is really destroyed? I think I remember talking to Lina about this a while ago but I don't remember the details.

We do not use it and I don't know why it's here either. In fact,
drm/asahi does an unbind_all equivalently when closing a GEM
handle, so should be definitely ok without.

Dropped in v4, thanks.

>  >  > +????/** 
>  >  > +???? * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly 
>  >  > +???? * across the VA range. 
>  >  > +???? * 
>  >  > +???? * This is useful to fill a VA range with scratch pages or zero pages. 
>  >  > +???? * It is intended as a mechanism to accelerate sparse. 
>  >  > +???? */ 
>  >  > +????DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2), 
> 
> Does this require the BO to be a single page? If so, does it require offset==0? Or does it just take whatever page is at the specified offset?

I believe the intention is that it takes whatever page is at the
specified offset and just maps that a bunch of times. HK doesn't use
this yet though it probably should (this was added to help reduce
overhead when emulating sparse with scratch/zero pages, which is still
very new functionality in hk).

Accelerating this properly involves GPUVM patches - although even without
that, moving the loop into the kernel so it's only a single ioctl
(user-kernel roundtrip) seems worth keeping the flag for.

Added comments in v4.

>  >  > +????/** @object_handle: Object handle (out for BIND, in for UNBIND) */ 
>  >  > +????__u32 object_handle; 
> 
> How is this different from the GEM handle? I mean, I know it's different, but What is this handle for? Just a thing we can pass in later?

Yes, this is just a handle that's passed with the submit, see the
comment in drm_asahi_timestamp.

>  >  > +????/** @priority: Queue priority, 0-3 */ 
>  >  > +????__u32 priority; 
> 
> Is one of these priorities REALTIME and only usable by privileged apps? If so, maybe document that and/or have an enum?

Added an enum, thanks.

I haven't actually implemented the priority check because that means
even more rust bindings, and I don't think it's actually a uAPI
regression to tighten the permissions later now that I've documented
that we may do so.

>  >  > +????/** 
>  >  > +???? * @usc_exec_base: GPU base address for all USC binaries (shaders) on 
>  >  > +???? * this queue. USC addresses are 32-bit relative to this 64-bit base. 
>  >  > +???? * 
>  >  > +???? * This sets the following registers on all queue commands: 
>  >  > +???? * 
>  >  > +???? *????USC_EXEC_BASE_TA  (vertex) 
>  >  > +???? *????USC_EXEC_BASE_ISP (fragment) 
>  >  > +???? *????USC_EXEC_BASE_CP  (compute) 
>  >  > +???? * 
>  >  > +???? * While the hardware lets us configure these independently per command, 
>  >  > +???? * we do not have a use case for this. Instead, we expect userspace to 
>  >  > +???? * fix a 4GiB VA carveout for USC memory and pass its base address here. 
>  >  > +???? */ 
>  >  > +????__u64 usc_exec_base; 
> 
> I mean, you could have a command for this or or something but meh. That can be an extension on top of the current UAPI later if it's ever needed.

Yep, and I really cannot fathom a use case for doing this at
finer-than-queue granularity.

>  >  > +????/** 
>  >  > +???? * @barriers: Array of command indices per subqueue to wait on. 
>  >  > +???? * 
>  >  > +???? * Barriers are indices relative to the beginning of a given submit. A 
>  >  > +???? * barrier of 0 waits on commands submitted to the subqueue in previous 
>  >  > +???? * submit ioctls. A barrier of N waits on N previous commands on the 
>  >  > +???? * subqueue within the current submit ioctl. As a special case, passing 
>  >  > +???? * @DRM_ASAHI_BARRIER_NONE avoids waiting on any commands in the 
>  >  > +???? * subqueue. 
>  >  > +???? * 
>  >  > +???? * Examples: 
>  >  > +???? * 
>  >  > +???? *   (0, 0): This waits on all previous work. 
>  >  > +???? * 
>  >  > +???? *   (NONE, 0): This waits on previously submitted compute commands but 
>  >  > +???? *   does not wait on any render commands. 
>  >  > +???? * 
>  >  > +???? *   (1, NONE): This waits on the first render command in the submit. 
>  >  > +???? *   This only makes sense if there are multiple render commands in the 
>  >  > +???? *   same submit. 
>  >  > +???? * 
>  >  > +???? * Barriers only make sense for hardware commands. Synthetic software 
>  >  > +???? * commands to set attachments must pass (NONE, NONE) here. 
>  >  > +???? */ 
>  >  > +????__u16 barriers[DRM_ASAHI_SUBQUEUE_COUNT]; 
> 
> I'm not sure how good of an idea this is. You said in the comment above that SUBQUEUE_COUNT must be a power of 2. However, once you use it to size an array in the command header, it can never change ever. I'm not sure what to do about that. The command header being 8B is kinda nice... But also, will we ever need more than 2? I'd hate to have to change the size of the header.
> 
> Another option would be to potentially have a barrier command which would then be extensible but that sounds kinda annoying.

I think the mistake here is making this an array instead of just
`vdm_barrier`, `cdm_barrier` fields. It will never be not-2, at least
not without such large hardware changes that we'd be due for a refresh
of this uAPI anyway.

I don't love the idea of the extra command, adds a lot more
complexity/overhead for a hard-to-fathom theoretical future hw issue
(that we could address with a drm_asahi_cmd_header_m7 if we
need that.)

Addressed in v4.

>  >  > +/** 
>  >  > + * struct drm_asahi_timestamp - Describe a timestamp write. 
>  >  > + * 
>  >  > + * The firmware can optionally write the GPU timestamp at render pass 
>  >  > + * granularities, but it needs to be mapped specially via 
>  >  > + * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to 
>  >  > + * write as a handle-offset pair, rather than a GPU address like normal. 
> 
> Given that this struct is embedded in other structs, it might be worth a comment saying it can never be extended without breaking those structs.

Done (for each of the places mentioned).

>  >  > +struct drm_asahi_helper_program { 
>  >  > +????/** 
>  >  > +???? * @binary: USC address to the helper program binary. This is a tagged 
>  >  > +???? * pointer with configuration in the bottom bits. 
>  >  > +???? */ 
>  >  > +????__u32 binary; 
>  >  > + 
>  >  > +????/** @cfg: Configuration bits for the helper program. */ 
>  >  > +????__u32 cfg; 
> 
> There's configuratin bits here and in the binary pointer abov?

Yes. Not sure what the different bits mean exactly. My guess is that the
binary pointer is tagged as "enable the helper prog?".

The one known @cfg bit is when the helper program is needed within a
preamble shader, i.e. if the preamble spills.

> Woo! I made it to the end. I think that's all for now. I mostly asked a lot of questions.

Hooray! Thank you so much for reviewing!


From alyssa at rosenzweig.io  Sun Mar 23 14:44:23 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 17:44:23 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
 <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
Message-ID: <Z-CAtz-D-CslvABE@blossom>

>  >  > +struct drm_asahi_queue_create { 
>  >  > +????/** @flags: MBZ */ 
>  >  > +????__u32 flags; 
>  >  > + 
>  >  > +????/** @vm_id: The ID of the VM this queue is bound to */ 
>  >  > +????__u32 vm_id; 
>  >  > + 
>  >  > +????/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */ 
>  >  > +????__u32 queue_caps; 
>  >  > + 
>  >  > +????/** @priority: Queue priority, 0-3 */ 
>  >  > +????__u32 priority; 
> 
> Is one of these priorities REALTIME and only usable by privileged apps? If so, maybe document that and/or have an enum?

Actually, I've reserved realtime&high but always deny right now to make
sure Mesa doesn't assume it can use them, then we can relax in the
future once the kernel permission gating is there. (Needs rust
bindings.)


From jonas at kwiboo.se  Sun Mar 23 14:49:04 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 23 Mar 2025 22:49:04 +0100
Subject: [PATCH 1/1] arm64: dts: rockchip: rk3528: Add CPU frequency
 scaling support
In-Reply-To: <20250320100002.332720-2-amadeus@jmu.edu.cn>
References: <20250320100002.332720-1-amadeus@jmu.edu.cn>
 <20250320100002.332720-2-amadeus@jmu.edu.cn>
Message-ID: <bcedff66-26e4-4630-88cd-6ab9fbcf5598@kwiboo.se>

Hi Chukun,

On 2025-03-20 11:00, Chukun Pan wrote:
> By default, the CPUs on RK3528 operates at 1.5GHz. Add CPU frequency and
> voltage mapping to the device tree to enable dynamic scaling via cpufreq.
> 
> The OPP values come from downstream kernel[1], and voltage is chosen from
> the one that makes the actual frequency close to the displayed frequency.
> 
> [1] https://github.com/rockchip-linux/kernel/blob/develop-5.10/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> 
> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
> ---
>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 64 ++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> index 621fc19ac0b3..9dae18c3c770 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
> @@ -61,6 +61,7 @@ cpu0: cpu at 0 {
>  			device_type = "cpu";
>  			enable-method = "psci";
>  			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			operating-points-v2 = <&cpu0_opp_table>;
>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -69,6 +70,7 @@ cpu1: cpu at 1 {
>  			device_type = "cpu";
>  			enable-method = "psci";
>  			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			operating-points-v2 = <&cpu0_opp_table>;
>  		};
>  
>  		cpu2: cpu at 2 {
> @@ -77,6 +79,7 @@ cpu2: cpu at 2 {
>  			device_type = "cpu";
>  			enable-method = "psci";
>  			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			operating-points-v2 = <&cpu0_opp_table>;
>  		};
>  
>  		cpu3: cpu at 3 {
> @@ -85,6 +88,7 @@ cpu3: cpu at 3 {
>  			device_type = "cpu";
>  			enable-method = "psci";
>  			clocks = <&scmi_clk SCMI_CLK_CPU>;
> +			operating-points-v2 = <&cpu0_opp_table>;
>  		};
>  	};
>  
> @@ -103,6 +107,66 @@ scmi_clk: protocol at 14 {
>  		};
>  	};
>  
> +	cpu0_opp_table: opp-table-0 {

nitpick:

There is only one cpu cluster on this SoC, I suggest we name this node
opp-table-cpu with a cpu_opp_table label.

For a forthcoming GPU series I named the node opp-table-gpu with a
gpu_opp_table label.

> +		compatible = "operating-points-v2";
> +		opp-shared;
> +
> +		opp-408000000 {
> +			opp-hz = /bits/ 64 <408000000>;
> +			opp-microvolt = <825000 825000 1100000>;
> +			clock-latency-ns = <40000>;
> +			opp-suspend;
> +		};
> +
> +		opp-600000000 {
> +			opp-hz = /bits/ 64 <600000000>;
> +			opp-microvolt = <825000 825000 1100000>;
> +			clock-latency-ns = <40000>;
> +		};

Both 408 and 600 MHz freq will use a normal PLL and based on the vendor
opp-table there are chip variants that presumably require 875000
microvolt.

Because of this 875000 is the lowest microvolt we should use in the
entire table, to ensure all chip variants can run stable.

Dragan is working on a chip binning project to help improve opp voltage
selection based on chip quality. Hopefully that project will result in
something that can also be used for RK3528 in the future.

> +
> +		opp-816000000 {
> +			opp-hz = /bits/ 64 <816000000>;
> +			opp-microvolt = <825000 825000 1100000>;
> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-1008000000 {
> +			opp-hz = /bits/ 64 <1008000000>;
> +			opp-microvolt = <850000 850000 1100000>;
> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-1200000000 {
> +			opp-hz = /bits/ 64 <1200000000>;
> +			opp-microvolt = <850000 850000 1100000>;

For remaining freq TF-A will use PVTPLL and configure an osc ring length,
then the voltage supplied in opp and chip quality will determine/limit
the real cpu clock speed.

This means that the voltage used is less important when it comes to
stability. However, we should keep 875000 as the lowest microvolt for
all opp above.

The voltage for remaining opp does not matter, historically mainline
picks the highest voltage from vendor tree to ensure stability. With the
use of PVTPLL that should not really be an issue, and we could pick
voltages that will give closest speed for majority of users.

> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-1416000000 {
> +			opp-hz = /bits/ 64 <1416000000>;
> +			opp-microvolt = <925000 925000 1100000>;
> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-1608000000 {
> +			opp-hz = /bits/ 64 <1608000000>;
> +			opp-microvolt = <975000 975000 1100000>;
> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-1800000000 {
> +			opp-hz = /bits/ 64 <1800000000>;
> +			opp-microvolt = <1037500 1037500 1100000>;
> +			clock-latency-ns = <40000>;
> +		};
> +
> +		opp-2016000000 {
> +			opp-hz = /bits/ 64 <2016000000>;
> +			opp-microvolt = <1100000 1100000 1100000>;

This looks good, we should not go above the highest voltage used in
vendor tree.

A DT overlay can be used if a user wants to use board optimized voltages.

Regards,
Jonas

> +			clock-latency-ns = <40000>;
> +		};
> +	};
> +
>  	psci {
>  		compatible = "arm,psci-1.0", "arm,psci-0.2";
>  		method = "smc";



From jonas at kwiboo.se  Sun Mar 23 15:03:46 2025
From: jonas at kwiboo.se (Jonas Karlman)
Date: Sun, 23 Mar 2025 23:03:46 +0100
Subject: [PATCH v2 1/2] arm64: dts: rockchip: Add pwm nodes for RK3528
In-Reply-To: <0f0a35ba-d85d-49eb-92dd-7bc17358aeaf@kwiboo.se>
References: <20250318120003.2340652-1-amadeus@jmu.edu.cn>
 <20250318120003.2340652-2-amadeus@jmu.edu.cn>
 <0d638134-0c0d-4918-af47-e23d2ead3bf3@kwiboo.se> <2499436.jE0xQCEvom@phil>
 <0f0a35ba-d85d-49eb-92dd-7bc17358aeaf@kwiboo.se>
Message-ID: <364bed4f-4ae1-48d5-ae6e-369668456d8e@kwiboo.se>

On 2025-03-20 08:02, Jonas Karlman wrote:
> On 2025-03-20 00:47, Heiko Stuebner wrote:
>> Am Donnerstag, 20. M?rz 2025, 00:26:14 MEZ schrieb Jonas Karlman:
>>> Hi Chukun,
>>>
>>> On 2025-03-18 13:00, Chukun Pan wrote:
>>>> Add pwm nodes for RK3528. The PWM core on RK3528 is the same as
>>>> RK3328, but the driver does not support interrupts yet.
>>>
>>> The device tree should describe the hardware, not what the driver
>>> support, so interrupts should probably be included.
>>>
>>> However, looking closer at TRM for i.e. RK3328, RK3568 and RK3588 it
>>> look like the following description is not a true description of the
>>> hardware.
>>>
>>> Each PWM controller seem to support 4 channels, here (and for older RK
>>> SoCs) we instead describe each channel and not the controller.
>>
>> Yep, that is something that did go wrong in the very early days.
>> And all other Rockchip socs also have the same issue - even back
>> to the rk3066.
> 
> I see, look like the PWM has evolved something like following:
> 
> - The controller has always been 1 controller for 4 channels
> - Initial versions only had 2 regs for interrupt outside of the 4x
>   0x10 reg space, one for each channel
> - FIFO was introduced for channel 3
> - Interrupts for FIFO was introduced (in RK3399 or earlier)
> - Additional features/regs was introduced (in PX30 or earlier)
> - PWM_VERSION_ID = 0x02120b34 is used (in RK3308 and later)
> 
>>
>> So yes, at some point we should overhaul the thing.
>>
>> But I think this is more involved, as right now everything is aimed
>> at the current single-channel status quo.
> 
> I did a quick and dirty change in driver to use npwms = 4, and that was
> a rather trivial change, see top commit at [1]. Minimum required change
> in U-Boot also look to be very trivial.

I did a quick test on U-Boot and are preparing a series to add support
for multiple channels in U-Boot, see [2] for an early version that
should hit U-Boot ML in a day or two.

Found some other other issues when digging in the U-Boot pwm-regulator
code so ended up with a bigger series than anticipated, only the last
patch is related to preparation for multiple channels in rk-pwm driver.

[2] https://source.denx.de/u-boot/contributors/kwiboo/u-boot/-/commits/pwm-regulator

Regards,
Jonas

> 
>   cat /sys/kernel/debug/pwm
>   0: platform/ffa90000.pwm, 4 PWM devices
>    pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
>    pwm-1   (regulator-vdd-arm   ): requested enabled period: 5000 ns duty: 2250 ns polarity: inverse
>    pwm-2   (regulator-vdd-logic ): requested enabled period: 5000 ns duty: 2800 ns polarity: inverse
>    pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
> 
> Not really seeing any reason not to describe these PWM controllers more
> correctly, we need to start somewhere.
> 
> However, I have no idea on how to deal with historic and wrong bindings.
> Driver could possible check if resource space is above 0x10 size and state
> of PWM_VERSION_ID.
> 
>   PWM_VERSION_ID  0x005c  W  0x02120b34  PWM Version ID Register  
> 
> [1] https://github.com/Kwiboo/linux-rockchip/commits/next-20250319-rk3528/
> 
> Regards,
> Jonas
> 
>>
>>
>> Heiko
>>
>>
>>> Maybe something like following would better represent the hardware:
>>>
>>> 	pwm0: pwm at ffa90000 {
>>> 		compatible = "rockchip,rk3528-pwm";
>>> 		reg = <0x0 0xffa90000 0x0 0x10000>;
>>> 		clocks = <&cru CLK_PWM0>, <&cru PCLK_PWM0>;
>>> 		clock-names = "pwm", "pclk";
>>> 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
>>> 			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
>>> 	};
>>>
>>> 	pwm1: pwm at ffa98000 {
>>> 		compatible = "rockchip,rk3528-pwm";
>>> 		reg = <0x0 0xffa98000 0x0 0x10000>;
>>> 		clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
>>> 		clock-names = "pwm", "pclk";
>>> 		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
>>> 			     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
>>> 	};
>>>
>>> Regards,
>>> Jonas
>>>
>>>>
>>>> Signed-off-by: Chukun Pan <amadeus at jmu.edu.cn>
>>>> ---
>>>>  arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++
>>>>  1 file changed, 80 insertions(+)
>>>>

[snip]


From alyssa at rosenzweig.io  Sun Mar 23 15:22:19 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 18:22:19 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
 <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
Message-ID: <Z-CJmw9BKteSj1Qx@blossom>

>  >  > +????/** 
>  >  > +???? * @user_timestamp_frequency_hz: Timebase frequency for user timestamps 
>  >  > +???? */ 
>  >  > +????__u64 user_timestamp_frequency_hz; 
>  >  
>  > Why is this different? What are user timestamps and how are they different from GPU timestamps? 

In v4, I've made get_time return nanos which should clarify things.
(Since it hides the SoC clock rate from userspace, leaving only the GPU
firmware clock rate and nanoseconds as the two time rates to worry
about.)


From andre.draszik at linaro.org  Sun Mar 23 15:39:20 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:20 +0000
Subject: [PATCH 04/34] mfd: sec: drop non-existing forward declarations
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-4-d08943702707@linaro.org>

sec_irq_resume() was removed in commit 6445b84abf91 ("mfd: Add s2mps11
irq driver") and sec_irq_exit() in commit 3dc6f4aaafbe ("mfd: sec: Use
devm_mfd_add_devices and devm_regmap_add_irq_chip") while the
prototypes were left. They should be removed.

Do so.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 include/linux/mfd/samsung/core.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index f35314458fd22e43fa13034439406bea17a155c9..b7008b50392ab857751b89e0a05d2c27f6306906 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -72,8 +72,6 @@ struct sec_pmic_dev {
 };
 
 int sec_irq_init(struct sec_pmic_dev *sec_pmic);
-void sec_irq_exit(struct sec_pmic_dev *sec_pmic);
-int sec_irq_resume(struct sec_pmic_dev *sec_pmic);
 
 struct sec_platform_data {
 	struct sec_regulator_data	*regulators;

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:21 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:21 +0000
Subject: [PATCH 05/34] mfd: sec: sort includes alphabetically
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-5-d08943702707@linaro.org>

Sorting headers alphabetically helps locating duplicates, and makes it
easier to figure out where to insert new headers.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-core.c | 14 +++++++-------
 drivers/mfd/sec-irq.c  |  5 ++---
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 3e9b65c988a7f08bf16d3703004a3d60cfcb1c75..e31b3a6fbc8922e04a8bfcb78c85b6dbaf395e37 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -3,16 +3,10 @@
 // Copyright (c) 2012 Samsung Electronics Co., Ltd
 //              http://www.samsung.com
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
 #include <linux/err.h>
-#include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/of.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pm_runtime.h>
-#include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
@@ -23,7 +17,13 @@
 #include <linux/mfd/samsung/s2mps15.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8767.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 
 static const struct mfd_cell s5m8767_devs[] = {
 	{ .name = "s5m8767-pmic", },
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 047fc065fcf17f5bde84143d77a46749111ea5b8..5c0d949aa1a20f5538d8baf7a8aefc1160ffa14c 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -6,9 +6,6 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mps11.h>
@@ -16,6 +13,8 @@
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s2mpu05.h>
 #include <linux/mfd/samsung/s5m8767.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
 
 static const struct regmap_irq s2mps11_irqs[] = {
 	[S2MPS11_IRQ_PWRONF] = {

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:22 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:22 +0000
Subject: [PATCH 06/34] mfd: sec: update includes to add missing and remove
 superfluous ones
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-6-d08943702707@linaro.org>

This driver misses to include some of the respective headers of some of
the APIs used. It also includes headers that aren't needed (e.g. due to
previous driver rework where includes weren't updated).

It is good practice to directly include all headers used, which avoids
implicit dependencies and spurious build breakage if someone rearranged
headers, as this could cause the implicit includes to be dropped.

Include the relevant headers explicitly and drop superfluous ones.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-core.c | 7 +++----
 drivers/mfd/sec-irq.c  | 5 ++++-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index e31b3a6fbc8922e04a8bfcb78c85b6dbaf395e37..b12020c416aa8bf552f3d3b7829f6a38a773f674 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -3,9 +3,9 @@
 // Copyright (c) 2012 Samsung Electronics Co., Ltd
 //              http://www.samsung.com
 
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
@@ -17,13 +17,12 @@
 #include <linux/mfd/samsung/s2mps15.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8767.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
-#include <linux/slab.h>
 
 static const struct mfd_cell s5m8767_devs[] = {
 	{ .name = "s5m8767-pmic", },
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 5c0d949aa1a20f5538d8baf7a8aefc1160ffa14c..3ed2902c3a2634a6ea656d890ecea934053bd192 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -3,7 +3,10 @@
 // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
 //              http://www.samsung.com
 
-#include <linux/device.h>
+#include <linux/array_size.h>
+#include <linux/build_bug.h>
+#include <linux/dev_printk.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/mfd/samsung/core.h>

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:18 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:18 +0000
Subject: [PATCH 02/34] dt-bindings: clock: samsung,s2mps11: add s2mpg10
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-2-d08943702707@linaro.org>

The Samsung S2MPG10 clock controller is similar to the existing clock
controllers supported by this binding. Register offsets / layout are
slightly different, so it needs its own compatible.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
index d5296e6053a1881650b8e8ff2524ea01689b7395..91d455155a606a60ed2006e57709466ae8d72664 100644
--- a/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
+++ b/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
@@ -25,6 +25,7 @@ description: |
 properties:
   compatible:
     enum:
+      - samsung,s2mpg10-clk
       - samsung,s2mps11-clk
       - samsung,s2mps13-clk # S2MPS13 and S2MPS15
       - samsung,s2mps14-clk

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:16 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:16 +0000
Subject: [PATCH 00/34] Samsung S2MPG10 PMIC MFD-based drivers
Message-ID: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>

This series adds initial support for the Samsung S2MPG10 PMIC using the
MFD framework. This is a PMIC for mobile applications and is used on
the Google Pixel 6 and 6 Pro (oriole / raven).

*** dependency note ***

This depends on the Samsung ACPM driver in Linux next, and runtime
depends on some fixes for it:
https://lore.kernel.org/all/20250321-acpm-atomic-v1-0-fb887bde7e61 at linaro.org/
https://lore.kernel.org/all/20250319-acpm-fixes-v2-0-ac2c1bcf322b at linaro.org/

*** dependency note end ***

+++ Kconfig update +++

There is a Kconfig symbol update in this series, because the existing
Samsung S2M driver has been split into core and transport (I2C & ACPM)
parts. CONFIG_MFD_SEC_CORE is now truly a core driver, and
the I2C code that was part of it is now enabled via CONFIG_MFD_SEC_I2C.

This was necessary because unlike the other S2M PMICs, S2MPG10 doesn't
talk via I2C, but via the Samsung ACPM firmware.

+++ Kconfig update end +++

This series must be applied in-order, due to interdependencies of some
of the patches. There are also various cleanup patches to the S2M
drivers. I've kept them ordered as:
  * DT bindings (patches 1 ... 2)
  * EXPORT_SYMBOL ACPM's devm_acpm_get_by_phandle() (patch 3)
  * S2M MFD prep for adding S2MPG10 to MFD core (patches 4 ... 11)
  * S2MPG10 core driver (patch 12)
  * S2M MFD cleanup patches (patches 14 ... 25)
  * S2MPG10 clock driver (patch 26)
  * S2M RTC prep for adding S2MPG10 (patch 27 ... 28)
  * S2MPG10 RTC driver (patch 29)
  * S2M RTC cleanup patches (patches 30 ... 33)

I realise these are many, but since some prep-work was required to be
able to add S2MPG anyway, I wanted to get the cleanup patches in as
well :-) Let me know if I should postpone them to a later date instead.

The S2MPG10 includes buck converters, various LDOs, power meters, RTC,
clock outputs, and additional GPIOs interfaces.

This series adds support in the top-level device driver, and for the
RTC and clock. Importantly, having the RTC driver allows to do a proper
reset of the system. Drivers or driver updates for the other components
will be added in future patches.

This will need a DT update for Oriole / Raven to enable this device. I
will send that out separately.

Cheers,
Andre'

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Andr? Draszik (34):
      dt-bindings: mfd: samsung,s2mps11: add s2mpg10
      dt-bindings: clock: samsung,s2mps11: add s2mpg10
      firmware: exynos-acpm: export devm_acpm_get_by_phandle()
      mfd: sec: drop non-existing forward declarations
      mfd: sec: sort includes alphabetically
      mfd: sec: update includes to add missing and remove superfluous ones
      mfd: sec: move private internal API to internal header
      mfd: sec: fix open parenthesis alignment (of_property_read_bool)
      mfd: sec: slightly rework runtime platform data allocation
      mfd: sec: split into core and transport (i2c) drivers
      defconfigs: rename CONFIG_MFD_SEC_CORE to CONFIG_MFD_SEC_I2C
      mfd: sec: add support for S2MPG10 PMIC
      mfd: sec: merge separate core and irq modules
      mfd: sec: sort struct of_device_id entries and the device type switch
      mfd: sec: use dev_err_probe() where appropriate
      mfd: sec: s2dos05/s2mpu05: use explicit regmap config
      mfd: sec: drop generic regmap config
      mfd: sec: s2dos05: doesn't support interrupts (it seems)
      mfd: sec: don't ignore errors from sec_irq_init()
      mfd: sec: rework platform data and regmap instantiating
      mfd: sec: change device_type to int
      mfd: sec: don't compare against NULL / 0 for errors, use !
      mfd: sec: use sizeof(*var), not sizeof(struct type_of_var)
      mfd: sec: convert to using MFD_CELL macros
      mfd: sec: convert to using REGMAP_IRQ_REG() macros
      clk: s2mps11: add support for S2MPG10 PMIC clock
      rtc: s5m: cache value of platform_get_device_id() during probe
      rtc: s5m: prepare for external regmap
      rtc: s5m: add support for S2MPG10 RTC
      rtc: s5m: fix a typo: peding -> pending
      rtc: s5m: switch to devm_device_init_wakeup
      rtc: s5m: replace regmap_update_bits with regmap_clear/set_bits
      rtc: s5m: replace open-coded read/modify/write registers with regmap helpers
      MAINTAINERS: add myself as reviewer for Samsung S2M MFD

 .../devicetree/bindings/clock/samsung,s2mps11.yaml |   1 +
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   |  34 +-
 MAINTAINERS                                        |   3 +-
 arch/arm/configs/exynos_defconfig                  |   2 +-
 arch/arm/configs/multi_v7_defconfig                |   2 +-
 arch/arm/configs/pxa_defconfig                     |   2 +-
 arch/arm64/configs/defconfig                       |   2 +-
 drivers/clk/clk-s2mps11.c                          |   8 +
 drivers/firmware/samsung/exynos-acpm.c             |   1 +
 drivers/mfd/Kconfig                                |  35 +-
 drivers/mfd/Makefile                               |   5 +-
 drivers/mfd/sec-acpm.c                             | 471 ++++++++++++++++++++
 drivers/mfd/sec-common.c                           | 284 ++++++++++++
 drivers/mfd/sec-core.c                             | 481 ---------------------
 drivers/mfd/sec-core.h                             |  32 ++
 drivers/mfd/sec-i2c.c                              | 259 +++++++++++
 drivers/mfd/sec-irq.c                              | 461 +++++++-------------
 drivers/rtc/rtc-s5m.c                              | 197 ++++++---
 include/linux/mfd/samsung/core.h                   |   7 +-
 include/linux/mfd/samsung/irq.h                    | 103 +++++
 include/linux/mfd/samsung/rtc.h                    |  37 ++
 include/linux/mfd/samsung/s2mpg10.h                | 310 +++++++++++++
 22 files changed, 1872 insertions(+), 865 deletions(-)
---
base-commit: c4d4884b67802c41fd67399747165d65c770621a
change-id: 20250321-s2mpg10-ef5d1ebd3043

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Sun Mar 23 15:39:17 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:17 +0000
Subject: [PATCH 01/34] dt-bindings: mfd: samsung,s2mps11: add s2mpg10
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-1-d08943702707@linaro.org>

The Samsung S2MPG10 PMIC is similar to the existing PMICs supported by
this binding.

It is a Power Management IC for mobile applications with buck
converters, various LDOs, power meters, RTC, clock outputs, and
additional GPIOs interfaces.

Unlike other Samsung PMICs, communication is not via I2C, but via the
Samsung ACPM firmware, it therefore doesn't need a 'reg' property but a
handle to the ACPM firmware node instead.

S2MPG10 can also act as a system power controller allowing
implementation of a true cold-reset of the system.

Support for the other components will be added in subsequent future
patches.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   | 34 ++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
index ac5d0c149796b6a4034b5d4245bfa8be0433cfab..ae8adb80b3af7ec3722c2a5718ad8fddf0a5df34 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
@@ -20,6 +20,7 @@ description: |
 properties:
   compatible:
     enum:
+      - samsung,s2mpg10-pmic
       - samsung,s2mps11-pmic
       - samsung,s2mps13-pmic
       - samsung,s2mps14-pmic
@@ -43,6 +44,12 @@ properties:
     description:
       List of child nodes that specify the regulators.
 
+  exynos,acpm-ipc:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: |
+      Phandle to the ACPM node for when ACPM is used to communicate with the
+      PMIC, rather than I2C.
+
   samsung,s2mps11-acokb-ground:
     description: |
       Indicates that ACOKB pin of S2MPS11 PMIC is connected to the ground so
@@ -58,16 +65,39 @@ properties:
       reset (setting buck voltages to default values).
     type: boolean
 
+  system-power-controller: true
+
   wakeup-source: true
 
 required:
   - compatible
-  - reg
-  - regulators
 
 additionalProperties: false
 
 allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s2mpg10-pmic
+    then:
+      properties:
+        regulators: false
+        samsung,s2mps11-acokb-ground: false
+        samsung,s2mps11-wrstbi-ground: false
+
+      required:
+        - exynos,acpm-ipc
+
+    else:
+      properties:
+        exynos,acpm-ipc: false
+        system-power-controller: false
+
+      required:
+        - reg
+        - regulators
+
   - if:
       properties:
         compatible:

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:19 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:19 +0000
Subject: [PATCH 03/34] firmware: exynos-acpm: export
 devm_acpm_get_by_phandle()
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-3-d08943702707@linaro.org>

The upcoming Samsung S2MPG10 PMIC driver will need this symbol to
communicate with the IC.

Export it.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/firmware/samsung/exynos-acpm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..7525bee4c6715edb964fc770ac9d8b3dd2be2172 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -741,6 +741,7 @@ const struct acpm_handle *devm_acpm_get_by_phandle(struct device *dev,
 
 	return handle;
 }
+EXPORT_SYMBOL_GPL(devm_acpm_get_by_phandle);
 
 static const struct acpm_match_data acpm_gs101 = {
 	.initdata_base = ACPM_GS101_INITDATA_BASE,

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:23 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:23 +0000
Subject: [PATCH 07/34] mfd: sec: move private internal API to internal
 header
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-7-d08943702707@linaro.org>

sec_irq_init() is an internal API for the core driver, and doesn't
belong into the public header.

Due to an upcoming split of the driver into a core and i2c driver,
we'll also be adding more internal APIs, which again shouldn't be in
the public header.

Move it into a new internal include.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 MAINTAINERS                      |  2 +-
 drivers/mfd/sec-core.c           |  1 +
 drivers/mfd/sec-core.h           | 15 +++++++++++++++
 drivers/mfd/sec-irq.c            |  1 +
 include/linux/mfd/samsung/core.h |  2 --
 5 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ebf7fa9a814d2d198fce853f7ff9a01f2bb69f5f..d686e02dc7ccd61e35173df997d2f894ee5ab515 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21351,7 +21351,7 @@ F:	Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml
 F:	Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
 F:	Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml
 F:	drivers/clk/clk-s2mps11.c
-F:	drivers/mfd/sec*.c
+F:	drivers/mfd/sec*.[ch]
 F:	drivers/regulator/s2m*.c
 F:	drivers/regulator/s5m*.c
 F:	drivers/rtc/rtc-s5m.c
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index b12020c416aa8bf552f3d3b7829f6a38a773f674..83693686567df61b5e09f7129dc6b01d69156ff3 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -23,6 +23,7 @@
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include "sec-core.h"
 
 static const struct mfd_cell s5m8767_devs[] = {
 	{ .name = "s5m8767-pmic", },
diff --git a/drivers/mfd/sec-core.h b/drivers/mfd/sec-core.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3fded5f02a0ddc09a9508fd49a5d335f7ad0ee7
--- /dev/null
+++ b/drivers/mfd/sec-core.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *                http://www.samsung.com
+ * Copyright 2025 Linaro Ltd.
+ *
+ * Samsung SxM core driver internal data
+ */
+
+#ifndef __SEC_CORE_INT_H
+#define __SEC_CORE_INT_H
+
+int sec_irq_init(struct sec_pmic_dev *sec_pmic);
+
+#endif /* __SEC_CORE_INT_H */
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 3ed2902c3a2634a6ea656d890ecea934053bd192..4d49bb42bd0d109263f485c8b58e88cdd8d598d9 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -18,6 +18,7 @@
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
+#include "sec-core.h"
 
 static const struct regmap_irq s2mps11_irqs[] = {
 	[S2MPS11_IRQ_PWRONF] = {
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index b7008b50392ab857751b89e0a05d2c27f6306906..8a4e660854bbc955b812b4d61d4a52a0fc2f2899 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -71,8 +71,6 @@ struct sec_pmic_dev {
 	struct regmap_irq_chip_data *irq_data;
 };
 
-int sec_irq_init(struct sec_pmic_dev *sec_pmic);
-
 struct sec_platform_data {
 	struct sec_regulator_data	*regulators;
 	struct sec_opmode_data		*opmode;

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:37 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:37 +0000
Subject: [PATCH 21/34] mfd: sec: change device_type to int
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-21-d08943702707@linaro.org>

Now that sec-i2c doesn't match device type by pointer casting anymore,
we can switch the device type from unsigned long to int easily.

This saves a few bytes in struct sec_pmic_dev due to member alignment.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c         | 8 ++++----
 drivers/mfd/sec-core.h           | 4 ++--
 drivers/mfd/sec-i2c.c            | 2 +-
 drivers/mfd/sec-irq.c            | 5 ++---
 include/linux/mfd/samsung/core.h | 2 +-
 5 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index bec8f93a03f7fd794beade563d73610534cb96b2..48d5c9a23230d0927b9dc610166ae3f8f1aec924 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -129,8 +129,8 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
 	}
 }
 
-int sec_pmic_probe(struct device *dev, unsigned long device_type,
-		   unsigned int irq, struct regmap *regmap,
+int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
+		   struct regmap *regmap,
 		   const struct sec_pmic_probe_data *probedata,
 		   struct i2c_client *client)
 {
@@ -214,7 +214,7 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type,
 		break;
 	default:
 		return dev_err_probe(sec_pmic->dev, -EINVAL,
-				     "Unsupported device type %lu\n",
+				     "Unsupported device type %d\n",
 				     sec_pmic->device_type);
 	}
 	ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
@@ -248,7 +248,7 @@ void sec_pmic_shutdown(struct device *dev)
 		 * ignore the rest.
 		 */
 		dev_warn(sec_pmic->dev,
-			"Unsupported device %lu for manual power off\n",
+			"Unsupported device %d for manual power off\n",
 			sec_pmic->device_type);
 		return;
 	}
diff --git a/drivers/mfd/sec-core.h b/drivers/mfd/sec-core.h
index 58e5b645f377cea5543a215c05957a2c49239a6f..34a801144a47bcdb5472ce5548bcef0fe3f0926f 100644
--- a/drivers/mfd/sec-core.h
+++ b/drivers/mfd/sec-core.h
@@ -21,8 +21,8 @@ struct sec_pmic_probe_data {
 	bool disable_wrstbi;
 };
 
-int sec_pmic_probe(struct device *dev, unsigned long device_type,
-		   unsigned int irq, struct regmap *regmap,
+int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
+		   struct regmap *regmap,
 		   const struct sec_pmic_probe_data *probedata,
 		   struct i2c_client *client);
 void sec_pmic_shutdown(struct device *dev);
diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index 9f33d4569cf73461c57d101f6ca1cf2b75f22b4d..760dd89b62a1639013c9e51b6e1a7376f15ac504 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -27,7 +27,7 @@
 
 struct sec_pmic_i2c_platform_data {
 	const struct regmap_config *regmap_cfg;
-	unsigned long device_type;
+	int device_type;
 };
 
 static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index dc5560a0c496917e847a40295c53e3f762b60998..cf1add30dcd0ff1ad149b483fe40edf82c2b57e1 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -450,10 +450,9 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 {
 	int ret = 0;
-	int type = sec_pmic->device_type;
 	const struct regmap_irq_chip *sec_irq_chip;
 
-	switch (type) {
+	switch (sec_pmic->device_type) {
 	case S5M8767X:
 		sec_irq_chip = &s5m8767_irq_chip;
 		break;
@@ -485,7 +484,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 		break;
 	default:
 		return dev_err_probe(sec_pmic->dev, -EINVAL,
-				     "Unsupported device type %lu\n",
+				     "Unsupported device type %d\n",
 				     sec_pmic->device_type);
 	}
 
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index c1102324172a9b6bd6072b5929a4866d6c9653fa..d785e101fe795a5d8f9cccf4ccc4232437e89416 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -67,7 +67,7 @@ struct sec_pmic_dev {
 	struct regmap *regmap_pmic;
 	struct i2c_client *i2c;
 
-	unsigned long device_type;
+	int device_type;
 	int irq;
 	struct regmap_irq_chip_data *irq_data;
 };

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:38 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:38 +0000
Subject: [PATCH 22/34] mfd: sec: don't compare against NULL / 0 for errors,
 use !
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-22-d08943702707@linaro.org>

Follow general style and use if (!arg) instead of comparing against
NULL.

While at it, drop a useless init in sec-irq.c.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c | 2 +-
 drivers/mfd/sec-irq.c    | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 48d5c9a23230d0927b9dc610166ae3f8f1aec924..90225b683fa083d4df7a20dfaa4f47084051e250 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -140,7 +140,7 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
 	int ret, num_sec_devs;
 
 	sec_pmic = devm_kzalloc(dev, sizeof(struct sec_pmic_dev), GFP_KERNEL);
-	if (sec_pmic == NULL)
+	if (!sec_pmic)
 		return -ENOMEM;
 
 	dev_set_drvdata(dev, sec_pmic);
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index cf1add30dcd0ff1ad149b483fe40edf82c2b57e1..084a40490979058b48640263ff5cdb38765b9ff1 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -449,8 +449,8 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
 
 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 {
-	int ret = 0;
 	const struct regmap_irq_chip *sec_irq_chip;
+	int ret;
 
 	switch (sec_pmic->device_type) {
 	case S5M8767X:
@@ -497,7 +497,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
 				       sec_pmic->irq, IRQF_ONESHOT,
 				       0, sec_irq_chip, &sec_pmic->irq_data);
-	if (ret != 0)
+	if (ret)
 		return dev_err_probe(sec_pmic->dev, ret,
 				     "Failed to add %s IRQ chip\n",
 				     sec_irq_chip->name);

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:39 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:39 +0000
Subject: [PATCH 23/34] mfd: sec: use sizeof(*var), not sizeof(struct
 type_of_var)
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-23-d08943702707@linaro.org>

Using sizeof(*var) is generally preferred over using the size of its
open-coded type when allocating memory.

This helps avoiding bugs when the variable type changes but the memory
allocation isn't updated, and it simplifies renaming of the struct if
ever necessary.

No functional change.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 90225b683fa083d4df7a20dfaa4f47084051e250..5ebc77d7edacbc1b7a3debb9069bb489109d57d7 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -139,7 +139,7 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
 	struct sec_pmic_dev *sec_pmic;
 	int ret, num_sec_devs;
 
-	sec_pmic = devm_kzalloc(dev, sizeof(struct sec_pmic_dev), GFP_KERNEL);
+	sec_pmic = devm_kzalloc(dev, sizeof(*sec_pmic), GFP_KERNEL);
 	if (!sec_pmic)
 		return -ENOMEM;
 

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:40 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:40 +0000
Subject: [PATCH 24/34] mfd: sec: convert to using MFD_CELL macros
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-24-d08943702707@linaro.org>

Use MFD_CELL macro helpers instead of open coding. This makes the code
a bit shorter and more obvious.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c | 57 ++++++++++++++++++------------------------------
 1 file changed, 21 insertions(+), 36 deletions(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 5ebc77d7edacbc1b7a3debb9069bb489109d57d7..77298e92642021679ea1eb95d338907fec098aea 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -23,16 +23,13 @@
 #include "sec-core.h"
 
 static const struct mfd_cell s5m8767_devs[] = {
-	{ .name = "s5m8767-pmic", },
-	{ .name = "s5m-rtc", },
-	{
-		.name = "s5m8767-clk",
-		.of_compatible = "samsung,s5m8767-clk",
-	},
+	MFD_CELL_NAME("s5m8767-pmic"),
+	MFD_CELL_NAME("s5m-rtc"),
+	MFD_CELL_OF("s5m8767-clk", NULL, NULL, 0, 0, "samsung,s5m8767-clk"),
 };
 
 static const struct mfd_cell s2dos05_devs[] = {
-	{ .name = "s2dos05-regulator", },
+	MFD_CELL_NAME("s2dos05-regulator"),
 };
 
 static const struct mfd_cell s2mpg10_devs[] = {
@@ -44,53 +41,41 @@ static const struct mfd_cell s2mpg10_devs[] = {
 };
 
 static const struct mfd_cell s2mps11_devs[] = {
-	{ .name = "s2mps11-regulator", },
-	{ .name = "s2mps14-rtc", },
-	{
-		.name = "s2mps11-clk",
-		.of_compatible = "samsung,s2mps11-clk",
-	},
+	MFD_CELL_NAME("s2mps11-regulator"),
+	MFD_CELL_NAME("s2mps14-rtc"),
+	MFD_CELL_OF("s2mps11-clk", NULL, NULL, 0, 0, "samsung,s2mps11-clk"),
 };
 
 static const struct mfd_cell s2mps13_devs[] = {
-	{ .name = "s2mps13-regulator", },
-	{ .name = "s2mps13-rtc", },
-	{
-		.name = "s2mps13-clk",
-		.of_compatible = "samsung,s2mps13-clk",
-	},
+	MFD_CELL_NAME("s2mps13-regulator"),
+	MFD_CELL_NAME("s2mps13-rtc"),
+	MFD_CELL_OF("s2mps13-clk", NULL, NULL, 0, 0, "samsung,s2mps13-clk"),
 };
 
 static const struct mfd_cell s2mps14_devs[] = {
-	{ .name = "s2mps14-regulator", },
-	{ .name = "s2mps14-rtc", },
-	{
-		.name = "s2mps14-clk",
-		.of_compatible = "samsung,s2mps14-clk",
-	},
+	MFD_CELL_NAME("s2mps14-regulator"),
+	MFD_CELL_NAME("s2mps14-rtc"),
+	MFD_CELL_OF("s2mps14-clk", NULL, NULL, 0, 0, "samsung,s2mps14-clk"),
 };
 
 static const struct mfd_cell s2mps15_devs[] = {
-	{ .name = "s2mps15-regulator", },
-	{ .name = "s2mps15-rtc", },
-	{
-		.name = "s2mps13-clk",
-		.of_compatible = "samsung,s2mps13-clk",
-	},
+	MFD_CELL_NAME("s2mps15-regulator"),
+	MFD_CELL_NAME("s2mps15-rtc"),
+	MFD_CELL_OF("s2mps13-clk", NULL, NULL, 0, 0, "samsung,s2mps13-clk"),
 };
 
 static const struct mfd_cell s2mpa01_devs[] = {
-	{ .name = "s2mpa01-pmic", },
-	{ .name = "s2mps14-rtc", },
+	MFD_CELL_NAME("s2mpa01-pmic"),
+	MFD_CELL_NAME("s2mps14-rtc"),
 };
 
 static const struct mfd_cell s2mpu02_devs[] = {
-	{ .name = "s2mpu02-regulator", },
+	MFD_CELL_NAME("s2mpu02-regulator"),
 };
 
 static const struct mfd_cell s2mpu05_devs[] = {
-	{ .name = "s2mpu05-regulator", },
-	{ .name = "s2mps15-rtc", },
+	MFD_CELL_NAME("s2mpu05-regulator"),
+	MFD_CELL_NAME("s2mps15-rtc"),
 };
 
 static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:41 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:41 +0000
Subject: [PATCH 25/34] mfd: sec: convert to using REGMAP_IRQ_REG() macros
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-25-d08943702707@linaro.org>

Use REGMAP_IRQ_REG macro helpers instead of open coding. This makes the
code a bit shorter and more obvious.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-irq.c | 343 +++++++++++---------------------------------------
 1 file changed, 75 insertions(+), 268 deletions(-)

diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 084a40490979058b48640263ff5cdb38765b9ff1..661b0b2d7b7e3da5df7085f468e6860a63c1016f 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -75,212 +75,68 @@ static const struct regmap_irq s2mpg10_irqs[] = {
 };
 
 static const struct regmap_irq s2mps11_irqs[] = {
-	[S2MPS11_IRQ_PWRONF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONF_MASK,
-	},
-	[S2MPS11_IRQ_PWRONR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONR_MASK,
-	},
-	[S2MPS11_IRQ_JIGONBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBF_MASK,
-	},
-	[S2MPS11_IRQ_JIGONBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBR_MASK,
-	},
-	[S2MPS11_IRQ_ACOKBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBF_MASK,
-	},
-	[S2MPS11_IRQ_ACOKBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBR_MASK,
-	},
-	[S2MPS11_IRQ_PWRON1S] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRON1S_MASK,
-	},
-	[S2MPS11_IRQ_MRB] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_MRB_MASK,
-	},
-	[S2MPS11_IRQ_RTC60S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC60S_MASK,
-	},
-	[S2MPS11_IRQ_RTCA1] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA1_MASK,
-	},
-	[S2MPS11_IRQ_RTCA0] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA0_MASK,
-	},
-	[S2MPS11_IRQ_SMPL] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_SMPL_MASK,
-	},
-	[S2MPS11_IRQ_RTC1S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC1S_MASK,
-	},
-	[S2MPS11_IRQ_WTSR] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_WTSR_MASK,
-	},
-	[S2MPS11_IRQ_INT120C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT120C_MASK,
-	},
-	[S2MPS11_IRQ_INT140C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT140C_MASK,
-	},
+	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
+
+	REGMAP_IRQ_REG(S2MPS11_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
+
+	REGMAP_IRQ_REG(S2MPS11_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
+	REGMAP_IRQ_REG(S2MPS11_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
 };
 
 static const struct regmap_irq s2mps14_irqs[] = {
-	[S2MPS14_IRQ_PWRONF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONF_MASK,
-	},
-	[S2MPS14_IRQ_PWRONR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONR_MASK,
-	},
-	[S2MPS14_IRQ_JIGONBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBF_MASK,
-	},
-	[S2MPS14_IRQ_JIGONBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBR_MASK,
-	},
-	[S2MPS14_IRQ_ACOKBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBF_MASK,
-	},
-	[S2MPS14_IRQ_ACOKBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBR_MASK,
-	},
-	[S2MPS14_IRQ_PWRON1S] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRON1S_MASK,
-	},
-	[S2MPS14_IRQ_MRB] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_MRB_MASK,
-	},
-	[S2MPS14_IRQ_RTC60S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC60S_MASK,
-	},
-	[S2MPS14_IRQ_RTCA1] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA1_MASK,
-	},
-	[S2MPS14_IRQ_RTCA0] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA0_MASK,
-	},
-	[S2MPS14_IRQ_SMPL] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_SMPL_MASK,
-	},
-	[S2MPS14_IRQ_RTC1S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC1S_MASK,
-	},
-	[S2MPS14_IRQ_WTSR] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_WTSR_MASK,
-	},
-	[S2MPS14_IRQ_INT120C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT120C_MASK,
-	},
-	[S2MPS14_IRQ_INT140C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT140C_MASK,
-	},
-	[S2MPS14_IRQ_TSD] = {
-		.reg_offset = 2,
-		.mask = S2MPS14_IRQ_TSD_MASK,
-	},
+	REGMAP_IRQ_REG(S2MPS14_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
+
+	REGMAP_IRQ_REG(S2MPS14_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
+
+	REGMAP_IRQ_REG(S2MPS14_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
+	REGMAP_IRQ_REG(S2MPS14_IRQ_TSD, 2, S2MPS14_IRQ_TSD_MASK),
 };
 
 static const struct regmap_irq s2mpu02_irqs[] = {
-	[S2MPU02_IRQ_PWRONF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONF_MASK,
-	},
-	[S2MPU02_IRQ_PWRONR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRONR_MASK,
-	},
-	[S2MPU02_IRQ_JIGONBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBF_MASK,
-	},
-	[S2MPU02_IRQ_JIGONBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_JIGONBR_MASK,
-	},
-	[S2MPU02_IRQ_ACOKBF] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBF_MASK,
-	},
-	[S2MPU02_IRQ_ACOKBR] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_ACOKBR_MASK,
-	},
-	[S2MPU02_IRQ_PWRON1S] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_PWRON1S_MASK,
-	},
-	[S2MPU02_IRQ_MRB] = {
-		.reg_offset = 0,
-		.mask = S2MPS11_IRQ_MRB_MASK,
-	},
-	[S2MPU02_IRQ_RTC60S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC60S_MASK,
-	},
-	[S2MPU02_IRQ_RTCA1] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA1_MASK,
-	},
-	[S2MPU02_IRQ_RTCA0] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTCA0_MASK,
-	},
-	[S2MPU02_IRQ_SMPL] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_SMPL_MASK,
-	},
-	[S2MPU02_IRQ_RTC1S] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_RTC1S_MASK,
-	},
-	[S2MPU02_IRQ_WTSR] = {
-		.reg_offset = 1,
-		.mask = S2MPS11_IRQ_WTSR_MASK,
-	},
-	[S2MPU02_IRQ_INT120C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT120C_MASK,
-	},
-	[S2MPU02_IRQ_INT140C] = {
-		.reg_offset = 2,
-		.mask = S2MPS11_IRQ_INT140C_MASK,
-	},
-	[S2MPU02_IRQ_TSD] = {
-		.reg_offset = 2,
-		.mask = S2MPS14_IRQ_TSD_MASK,
-	},
+	REGMAP_IRQ_REG(S2MPU02_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
+
+	REGMAP_IRQ_REG(S2MPU02_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
+
+	REGMAP_IRQ_REG(S2MPU02_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
+	REGMAP_IRQ_REG(S2MPU02_IRQ_TSD, 2, S2MPS14_IRQ_TSD_MASK),
 };
 
 static const struct regmap_irq s2mpu05_irqs[] = {
@@ -304,74 +160,25 @@ static const struct regmap_irq s2mpu05_irqs[] = {
 };
 
 static const struct regmap_irq s5m8767_irqs[] = {
-	[S5M8767_IRQ_PWRR] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_PWRR_MASK,
-	},
-	[S5M8767_IRQ_PWRF] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_PWRF_MASK,
-	},
-	[S5M8767_IRQ_PWR1S] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_PWR1S_MASK,
-	},
-	[S5M8767_IRQ_JIGR] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_JIGR_MASK,
-	},
-	[S5M8767_IRQ_JIGF] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_JIGF_MASK,
-	},
-	[S5M8767_IRQ_LOWBAT2] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_LOWBAT2_MASK,
-	},
-	[S5M8767_IRQ_LOWBAT1] = {
-		.reg_offset = 0,
-		.mask = S5M8767_IRQ_LOWBAT1_MASK,
-	},
-	[S5M8767_IRQ_MRB] = {
-		.reg_offset = 1,
-		.mask = S5M8767_IRQ_MRB_MASK,
-	},
-	[S5M8767_IRQ_DVSOK2] = {
-		.reg_offset = 1,
-		.mask = S5M8767_IRQ_DVSOK2_MASK,
-	},
-	[S5M8767_IRQ_DVSOK3] = {
-		.reg_offset = 1,
-		.mask = S5M8767_IRQ_DVSOK3_MASK,
-	},
-	[S5M8767_IRQ_DVSOK4] = {
-		.reg_offset = 1,
-		.mask = S5M8767_IRQ_DVSOK4_MASK,
-	},
-	[S5M8767_IRQ_RTC60S] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_RTC60S_MASK,
-	},
-	[S5M8767_IRQ_RTCA1] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_RTCA1_MASK,
-	},
-	[S5M8767_IRQ_RTCA2] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_RTCA2_MASK,
-	},
-	[S5M8767_IRQ_SMPL] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_SMPL_MASK,
-	},
-	[S5M8767_IRQ_RTC1S] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_RTC1S_MASK,
-	},
-	[S5M8767_IRQ_WTSR] = {
-		.reg_offset = 2,
-		.mask = S5M8767_IRQ_WTSR_MASK,
-	},
+	REGMAP_IRQ_REG(S5M8767_IRQ_PWRR, 0, S5M8767_IRQ_PWRR_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_PWRF, 0, S5M8767_IRQ_PWRF_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_PWR1S, 0, S5M8767_IRQ_PWR1S_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_JIGR, 0, S5M8767_IRQ_JIGR_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_JIGF, 0, S5M8767_IRQ_JIGF_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_LOWBAT2, 0, S5M8767_IRQ_LOWBAT2_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_LOWBAT1, 0, S5M8767_IRQ_LOWBAT1_MASK),
+
+	REGMAP_IRQ_REG(S5M8767_IRQ_MRB, 1, S5M8767_IRQ_MRB_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK2, 1, S5M8767_IRQ_DVSOK2_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK3, 1, S5M8767_IRQ_DVSOK3_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK4, 1, S5M8767_IRQ_DVSOK4_MASK),
+
+	REGMAP_IRQ_REG(S5M8767_IRQ_RTC60S, 2, S5M8767_IRQ_RTC60S_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_RTCA1, 2, S5M8767_IRQ_RTCA1_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_RTCA2, 2, S5M8767_IRQ_RTCA2_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_SMPL, 2, S5M8767_IRQ_SMPL_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_RTC1S, 2, S5M8767_IRQ_RTC1S_MASK),
+	REGMAP_IRQ_REG(S5M8767_IRQ_WTSR, 2, S5M8767_IRQ_WTSR_MASK),
 };
 
 static const struct regmap_irq_chip s2mpg10_irq_chip = {

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:42 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:42 +0000
Subject: [PATCH 26/34] clk: s2mps11: add support for S2MPG10 PMIC clock
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-26-d08943702707@linaro.org>

Add support for Samsung's S2MPG10 PMIC clock, which is similar to the
existing PMIC clocks supported by this driver.

S2MPG10 has three clock outputs @ 32kHz: AP, peri1 and peri2.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/clk/clk-s2mps11.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
index 014db6386624071e173b5b940466301d2596400a..e86a762f80ccd7485a9f2a6f567b81bafe119874 100644
--- a/drivers/clk/clk-s2mps11.c
+++ b/drivers/clk/clk-s2mps11.c
@@ -11,6 +11,7 @@
 #include <linux/regmap.h>
 #include <linux/clk-provider.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/samsung/s2mpg10.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
@@ -138,6 +139,9 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	switch (hwid) {
+	case S2MPG10:
+		s2mps11_reg = S2MPG10_PMIC_RTCBUF;
+		break;
 	case S2MPS11X:
 		s2mps11_reg = S2MPS11_REG_RTC_CTRL;
 		break;
@@ -220,6 +224,7 @@ static void s2mps11_clk_remove(struct platform_device *pdev)
 }
 
 static const struct platform_device_id s2mps11_clk_id[] = {
+	{ "s2mpg10-clk", S2MPG10},
 	{ "s2mps11-clk", S2MPS11X},
 	{ "s2mps13-clk", S2MPS13X},
 	{ "s2mps14-clk", S2MPS14X},
@@ -240,6 +245,9 @@ MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
  */
 static const struct of_device_id s2mps11_dt_match[] __used = {
 	{
+		.compatible = "samsung,s2mpg10-clk",
+		.data = (void *)S2MPG10,
+	}, {
 		.compatible = "samsung,s2mps11-clk",
 		.data = (void *)S2MPS11X,
 	}, {

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:43 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:43 +0000
Subject: [PATCH 27/34] rtc: s5m: cache value of platform_get_device_id()
 during probe
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-27-d08943702707@linaro.org>

platform_get_device_id() is called mulitple times during probe. This
makes the code harder to read than necessary.

Just get the ID once, which also trims the lengths of the lines
involved.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index db5c9b641277213aa1371776c63e2eda3f223465..31bdceac7aa245175a30eb13eaaf1f52f70e22c2 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -637,6 +637,8 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
 static int s5m_rtc_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
+	const struct platform_device_id	* const id =
+		platform_get_device_id(pdev);
 	struct s5m_rtc_info *info;
 	struct i2c_client *i2c;
 	const struct regmap_config *regmap_cfg;
@@ -646,7 +648,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	if (!info)
 		return -ENOMEM;
 
-	switch (platform_get_device_id(pdev)->driver_data) {
+	switch (id->driver_data) {
 	case S2MPS15X:
 		regmap_cfg = &s2mps14_rtc_regmap_config;
 		info->regs = &s2mps15_rtc_regs;
@@ -670,7 +672,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	default:
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "Device type %lu is not supported by RTC driver\n",
-				     platform_get_device_id(pdev)->driver_data);
+				     id_entry->driver_data);
 	}
 
 	i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
@@ -686,7 +688,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
 	info->dev = &pdev->dev;
 	info->s5m87xx = s5m87xx;
-	info->device_type = platform_get_device_id(pdev)->driver_data;
+	info->device_type = id->driver_data;
 
 	if (s5m87xx->irq_data) {
 		info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:44 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:44 +0000
Subject: [PATCH 28/34] rtc: s5m: prepare for external regmap
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-28-d08943702707@linaro.org>

The Samsung S2MPG10 PMIC is not connected via I2C as this driver
assumes, hence this driver's current approach of creating an I2C-based
regmap doesn't work for it, and this driver should use the regmap
provided by the parent (core) driver instead for that PMIC.

To prepare this driver for s2mpg support, restructure the code to only
create a regmap if one isn't provided by the parent.

No functional changes, since the parent doesn't provide a regmap for
any of the PMICs currently supported by this driver. Having this change
separate will simply make the addition of S2MPG10 support more
self-contained, without additional restructuring.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 83 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 31bdceac7aa245175a30eb13eaaf1f52f70e22c2..86ccf666c68059408907c97f2647716ffaad10c6 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -640,51 +640,60 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	const struct platform_device_id	* const id =
 		platform_get_device_id(pdev);
 	struct s5m_rtc_info *info;
-	struct i2c_client *i2c;
-	const struct regmap_config *regmap_cfg;
 	int ret, alarm_irq;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	switch (id->driver_data) {
-	case S2MPS15X:
-		regmap_cfg = &s2mps14_rtc_regmap_config;
-		info->regs = &s2mps15_rtc_regs;
-		alarm_irq = S2MPS14_IRQ_RTCA0;
-		break;
-	case S2MPS14X:
-		regmap_cfg = &s2mps14_rtc_regmap_config;
-		info->regs = &s2mps14_rtc_regs;
-		alarm_irq = S2MPS14_IRQ_RTCA0;
-		break;
-	case S2MPS13X:
-		regmap_cfg = &s2mps14_rtc_regmap_config;
-		info->regs = &s2mps13_rtc_regs;
-		alarm_irq = S2MPS14_IRQ_RTCA0;
-		break;
-	case S5M8767X:
-		regmap_cfg = &s5m_rtc_regmap_config;
-		info->regs = &s5m_rtc_regs;
-		alarm_irq = S5M8767_IRQ_RTCA1;
-		break;
-	default:
-		return dev_err_probe(&pdev->dev, -ENODEV,
-				     "Device type %lu is not supported by RTC driver\n",
-				     id_entry->driver_data);
-	}
+	info->regmap = dev_get_regmap(pdev->dev.parent, "rtc");
+	if (!info->regmap) {
+		const struct regmap_config *regmap_cfg;
+		struct i2c_client *i2c;
 
-	i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
-					RTC_I2C_ADDR);
-	if (IS_ERR(i2c))
-		return dev_err_probe(&pdev->dev, PTR_ERR(i2c),
-				     "Failed to allocate I2C for RTC\n");
+		switch (id->driver_data) {
+		case S2MPS15X:
+			regmap_cfg = &s2mps14_rtc_regmap_config;
+			info->regs = &s2mps15_rtc_regs;
+			alarm_irq = S2MPS14_IRQ_RTCA0;
+			break;
+		case S2MPS14X:
+			regmap_cfg = &s2mps14_rtc_regmap_config;
+			info->regs = &s2mps14_rtc_regs;
+			alarm_irq = S2MPS14_IRQ_RTCA0;
+			break;
+		case S2MPS13X:
+			regmap_cfg = &s2mps14_rtc_regmap_config;
+			info->regs = &s2mps13_rtc_regs;
+			alarm_irq = S2MPS14_IRQ_RTCA0;
+			break;
+		case S5M8767X:
+			regmap_cfg = &s5m_rtc_regmap_config;
+			info->regs = &s5m_rtc_regs;
+			alarm_irq = S5M8767_IRQ_RTCA1;
+			break;
+		default:
+			return dev_err_probe(&pdev->dev, -ENODEV,
+					     "Unsupported device type %lu\n",
+					     id->driver_data);
+		}
 
-	info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
-	if (IS_ERR(info->regmap))
-		return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
-				     "Failed to allocate RTC register map\n");
+		i2c = devm_i2c_new_dummy_device(&pdev->dev,
+						s5m87xx->i2c->adapter,
+						RTC_I2C_ADDR);
+		if (IS_ERR(i2c))
+			return dev_err_probe(&pdev->dev, PTR_ERR(i2c),
+					     "Failed to allocate I2C\n");
+
+		info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
+		if (IS_ERR(info->regmap))
+			return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
+					     "Failed to allocate regmap\n");
+	} else {
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Unsupported device type %lu\n",
+				     id->driver_data);
+	}
 
 	info->dev = &pdev->dev;
 	info->s5m87xx = s5m87xx;

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:45 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:45 +0000
Subject: [PATCH 29/34] rtc: s5m: add support for S2MPG10 RTC
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-29-d08943702707@linaro.org>

Add support for Samsung's S2MPG10 PMIC RTC, which is similar to the
existing PMIC RTCs supported by this driver.

S2MPG10 doesn't use I2C, so we expect the core driver to have created a
regmap for us.

Additionally, it can be used for doing a cold-reset. If requested to do
so (via DT), S2MPG10 is programmed with a watchdog configuration that
will perform a full power cycle upon watchdog expiry.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c           | 60 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/samsung/rtc.h | 37 +++++++++++++++++++++++++
 2 files changed, 97 insertions(+)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 86ccf666c68059408907c97f2647716ffaad10c6..0d8783577bab4f4ebe61050dbd68387d970773bd 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/regmap.h>
+#include <linux/reboot.h>
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/samsung/core.h>
@@ -53,6 +54,7 @@ enum {
  * Device     | Write time | Read time | Write alarm
  * =================================================
  * S5M8767    | UDR + TIME |           | UDR
+ * S2MPG10    | WUDR       | RUDR      | AUDR
  * S2MPS11/14 | WUDR       | RUDR      | WUDR + RUDR
  * S2MPS13    | WUDR       | RUDR      | WUDR + AUDR
  * S2MPS15    | WUDR       | RUDR      | AUDR
@@ -99,6 +101,20 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
 	.write_alarm_udr_mask	= S5M_RTC_UDR_MASK,
 };
 
+/* Register map for S2MPG10 */
+static const struct s5m_rtc_reg_config s2mpg10_rtc_regs = {
+	.regs_count		= 7,
+	.time			= S2MPG10_RTC_SEC,
+	.ctrl			= S2MPG10_RTC_CTRL,
+	.alarm0			= S2MPG10_RTC_A0SEC,
+	.alarm1			= S2MPG10_RTC_A1SEC,
+	.udr_update		= S2MPG10_RTC_UPDATE,
+	.autoclear_udr_mask	= S2MPS15_RTC_WUDR_MASK | S2MPS15_RTC_AUDR_MASK,
+	.read_time_udr_mask	= S2MPS_RTC_RUDR_MASK,
+	.write_time_udr_mask	= S2MPS15_RTC_WUDR_MASK,
+	.write_alarm_udr_mask	= S2MPS15_RTC_AUDR_MASK,
+};
+
 /* Register map for S2MPS13 */
 static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
 	.regs_count		= 7,
@@ -238,6 +254,7 @@ static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
 		ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
 		val &= S5M_ALARM0_STATUS;
 		break;
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -300,6 +317,7 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 	case S5M8767X:
 		data &= ~S5M_RTC_TIME_EN_MASK;
 		break;
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -351,6 +369,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -374,6 +393,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -411,6 +431,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -449,6 +470,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -487,6 +509,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -524,6 +547,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	switch (info->device_type) {
 	case S5M8767X:
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -604,6 +628,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
 		ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
 		break;
 
+	case S2MPG10:
 	case S2MPS15X:
 	case S2MPS14X:
 	case S2MPS13X:
@@ -634,6 +659,25 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
 	return ret;
 }
 
+static int s5m_rtc_restart_s2mpg10(struct sys_off_data *data)
+{
+	struct s5m_rtc_info *info = data->cb_data;
+	int ret;
+
+	if (data->mode != REBOOT_COLD && data->mode != REBOOT_HARD)
+		return NOTIFY_DONE;
+
+	/*
+	 * Arm watchdog with maximum timeout (2 seconds), and perform full reset
+	 * on expiry.
+	 */
+	ret = regmap_set_bits(info->regmap, S2MPG10_RTC_WTSR,
+			      (S2MPG10_WTSR_COLDTIMER | S2MPG10_WTSR_COLDRST
+			       | S2MPG10_WTSR_WTSRT | S2MPG10_WTSR_WTSR_EN));
+
+	return ret ? NOTIFY_BAD : NOTIFY_DONE;
+}
+
 static int s5m_rtc_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
@@ -689,6 +733,9 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 		if (IS_ERR(info->regmap))
 			return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
 					     "Failed to allocate regmap\n");
+	} else if (id->driver_data == S2MPG10) {
+		info->regs = &s2mpg10_rtc_regs;
+		alarm_irq = S2MPG10_IRQ_RTCA0;
 	} else {
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "Unsupported device type %lu\n",
@@ -735,6 +782,18 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 		device_init_wakeup(&pdev->dev, true);
 	}
 
+	if (of_device_is_system_power_controller(pdev->dev.parent->of_node) &&
+	    info->device_type == S2MPG10) {
+		ret = devm_register_sys_off_handler(&pdev->dev,
+						    SYS_OFF_MODE_RESTART,
+						    SYS_OFF_PRIO_HIGH + 1,
+						    s5m_rtc_restart_s2mpg10,
+						    info);
+		if (ret)
+			return dev_err_probe(&pdev->dev, ret,
+				       "Failed to register restart handler\n");
+	}
+
 	return devm_rtc_register_device(info->rtc_dev);
 }
 
@@ -766,6 +825,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
 
 static const struct platform_device_id s5m_rtc_id[] = {
 	{ "s5m-rtc",		S5M8767X },
+	{ "s2mpg10-rtc",	S2MPG10 },
 	{ "s2mps13-rtc",	S2MPS13X },
 	{ "s2mps14-rtc",	S2MPS14X },
 	{ "s2mps15-rtc",	S2MPS15X },
diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h
index 0204decfc9aacbf4bc93d98a256f1d956bbcd19c..51c4239a1fa6f28155711a0756b0e071b010d848 100644
--- a/include/linux/mfd/samsung/rtc.h
+++ b/include/linux/mfd/samsung/rtc.h
@@ -72,6 +72,37 @@ enum s2mps_rtc_reg {
 	S2MPS_RTC_REG_MAX,
 };
 
+enum s2mpg10_rtc_reg {
+	S2MPG10_RTC_CTRL,
+	S2MPG10_RTC_UPDATE,
+	S2MPG10_RTC_SMPL,
+	S2MPG10_RTC_WTSR,
+	S2MPG10_RTC_CAP_SEL,
+	S2MPG10_RTC_MSEC,
+	S2MPG10_RTC_SEC,
+	S2MPG10_RTC_MIN,
+	S2MPG10_RTC_HOUR,
+	S2MPG10_RTC_WEEK,
+	S2MPG10_RTC_DAY,
+	S2MPG10_RTC_MON,
+	S2MPG10_RTC_YEAR,
+	S2MPG10_RTC_A0SEC,
+	S2MPG10_RTC_A0MIN,
+	S2MPG10_RTC_A0HOUR,
+	S2MPG10_RTC_A0WEEK,
+	S2MPG10_RTC_A0DAY,
+	S2MPG10_RTC_A0MON,
+	S2MPG10_RTC_A0YEAR,
+	S2MPG10_RTC_A1SEC,
+	S2MPG10_RTC_A1MIN,
+	S2MPG10_RTC_A1HOUR,
+	S2MPG10_RTC_A1WEEK,
+	S2MPG10_RTC_A1DAY,
+	S2MPG10_RTC_A1MON,
+	S2MPG10_RTC_A1YEAR,
+	S2MPG10_RTC_OSC_CTRL,
+};
+
 #define RTC_I2C_ADDR		(0x0C >> 1)
 
 #define HOUR_12			(1 << 7)
@@ -124,10 +155,16 @@ enum s2mps_rtc_reg {
 #define ALARM_ENABLE_SHIFT	7
 #define ALARM_ENABLE_MASK	(1 << ALARM_ENABLE_SHIFT)
 
+/* WTSR & SMPL registers */
 #define SMPL_ENABLE_SHIFT	7
 #define SMPL_ENABLE_MASK	(1 << SMPL_ENABLE_SHIFT)
 
 #define WTSR_ENABLE_SHIFT	6
 #define WTSR_ENABLE_MASK	(1 << WTSR_ENABLE_SHIFT)
 
+#define S2MPG10_WTSR_COLDTIMER	GENMASK(6, 5)
+#define S2MPG10_WTSR_COLDRST	BIT(4)
+#define S2MPG10_WTSR_WTSRT	GENMASK(3, 1)
+#define S2MPG10_WTSR_WTSR_EN	BIT(0)
+
 #endif /*  __LINUX_MFD_SEC_RTC_H */

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:46 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:46 +0000
Subject: [PATCH 30/34] rtc: s5m: fix a typo: peding -> pending
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-30-d08943702707@linaro.org>

Fix this minor typo, and adjust the a related incorrect alignment to
avoid a checkpatch error.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 0d8783577bab4f4ebe61050dbd68387d970773bd..7b00e65bdd9c25b3426f92355f8ea36e66c3939f 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -243,8 +243,8 @@ static int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
 	return ret;
 }
 
-static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
-		struct rtc_wkalrm *alarm)
+static int s5m_check_pending_alarm_interrupt(struct s5m_rtc_info *info,
+					     struct rtc_wkalrm *alarm)
 {
 	int ret;
 	unsigned int val;
@@ -451,7 +451,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday);
 
-	return s5m_check_peding_alarm_interrupt(info, alrm);
+	return s5m_check_pending_alarm_interrupt(info, alrm);
 }
 
 static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:47 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:47 +0000
Subject: [PATCH 31/34] rtc: s5m: switch to devm_device_init_wakeup
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-31-d08943702707@linaro.org>

To release memory allocated by device_init_wakeup(true), drivers have
to call device_init_wakeup(false) in error paths and unbind.

Switch to the new devres managed version devm_device_init_wakeup() to
plug this memleak.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 7b00e65bdd9c25b3426f92355f8ea36e66c3939f..e8e442c503064eb4e570af5bf7dcff6bfa7f4656 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -779,7 +779,11 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 			return dev_err_probe(&pdev->dev, ret,
 					     "Failed to request alarm IRQ %d\n",
 					     info->irq);
-		device_init_wakeup(&pdev->dev, true);
+
+		ret = devm_device_init_wakeup(&pdev->dev);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret,
+					     "Failed to init wakeup\n");
 	}
 
 	if (of_device_is_system_power_controller(pdev->dev.parent->of_node) &&

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:48 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:48 +0000
Subject: [PATCH 32/34] rtc: s5m: replace regmap_update_bits with
 regmap_clear/set_bits
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-32-d08943702707@linaro.org>

The regmap_clear_bits() and regmap_set_bits() helper macros state the
intention a bit more obviously.

Use those.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index e8e442c503064eb4e570af5bf7dcff6bfa7f4656..fb65a8e439d72d9070751c00f5826a403ac0b416 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -338,8 +338,8 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 
 	/* On S2MPS13 the AUDR is not auto-cleared */
 	if (info->device_type == S2MPS13X)
-		regmap_update_bits(info->regmap, info->regs->udr_update,
-				   S2MPS13_RTC_AUDR_MASK, 0);
+		regmap_clear_bits(info->regmap, info->regs->udr_update,
+				  S2MPS13_RTC_AUDR_MASK);
 
 	return ret;
 }
@@ -351,10 +351,8 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	int ret;
 
 	if (info->regs->read_time_udr_mask) {
-		ret = regmap_update_bits(info->regmap,
-				info->regs->udr_update,
-				info->regs->read_time_udr_mask,
-				info->regs->read_time_udr_mask);
+		ret = regmap_set_bits(info->regmap, info->regs->udr_update,
+				      info->regs->read_time_udr_mask);
 		if (ret) {
 			dev_err(dev,
 				"Failed to prepare registers for time reading: %d\n",

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:49 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:49 +0000
Subject: [PATCH 33/34] rtc: s5m: replace open-coded read/modify/write
 registers with regmap helpers
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-33-d08943702707@linaro.org>

Instead of the open-coded read/modify/write sequence, we can simply use
the regmap helpers regmap_set_bits() and regmap_update_bits()
respectively.

This makes the code easier to read, and avoids extra works in case the
underlying bus supports updating bits via
struct regmap_bus::reg_update_bits() directly (which is the case for
S2MPG10 on gs101 where this driver communicates via ACPM).

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/rtc/rtc-s5m.c | 28 +++++++---------------------
 1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index fb65a8e439d72d9070751c00f5826a403ac0b416..2ad01fb3bc72fe9259a8307584c9cf3a839bd492 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -279,17 +279,9 @@ static int s5m_check_pending_alarm_interrupt(struct s5m_rtc_info *info,
 static int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 {
 	int ret;
-	unsigned int data;
-
-	ret = regmap_read(info->regmap, info->regs->udr_update, &data);
-	if (ret < 0) {
-		dev_err(info->dev, "failed to read update reg(%d)\n", ret);
-		return ret;
-	}
-
-	data |= info->regs->write_time_udr_mask;
 
-	ret = regmap_write(info->regmap, info->regs->udr_update, data);
+	ret = regmap_set_bits(info->regmap, info->regs->udr_update,
+			      info->regs->write_time_udr_mask);
 	if (ret < 0) {
 		dev_err(info->dev, "failed to write update reg(%d)\n", ret);
 		return ret;
@@ -303,19 +295,12 @@ static int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 {
 	int ret;
-	unsigned int data;
-
-	ret = regmap_read(info->regmap, info->regs->udr_update, &data);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read update reg(%d)\n",
-			__func__, ret);
-		return ret;
-	}
+	unsigned int udr_mask;
 
-	data |= info->regs->write_alarm_udr_mask;
+	udr_mask = info->regs->write_alarm_udr_mask;
 	switch (info->device_type) {
 	case S5M8767X:
-		data &= ~S5M_RTC_TIME_EN_MASK;
+		udr_mask |= S5M_RTC_TIME_EN_MASK;
 		break;
 	case S2MPG10:
 	case S2MPS15X:
@@ -327,7 +312,8 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 		return -EINVAL;
 	}
 
-	ret = regmap_write(info->regmap, info->regs->udr_update, data);
+	ret = regmap_update_bits(info->regmap, info->regs->udr_update,
+				 udr_mask, info->regs->write_alarm_udr_mask);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write update reg(%d)\n",
 			__func__, ret);

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:50 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:50 +0000
Subject: [PATCH 34/34] MAINTAINERS: add myself as reviewer for Samsung S2M
 MFD
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-34-d08943702707@linaro.org>

I'm working on a Samsung device which includes this MFD and would like
to be Cc'ed to further contributions and help on reviewing them. Add me
as reviewer.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d686e02dc7ccd61e35173df997d2f894ee5ab515..10945909f5b317a894b6afbeb6bbccd1a691de9d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21341,6 +21341,7 @@ F:	drivers/platform/x86/samsung-laptop.c
 
 SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
 M:	Krzysztof Kozlowski <krzk at kernel.org>
+R:	Andr? Draszik <andre.draszik at linaro.org>
 L:	linux-kernel at vger.kernel.org
 L:	linux-samsung-soc at vger.kernel.org
 S:	Maintained

-- 
2.49.0.395.g12beb8f557-goog



From alyssa at rosenzweig.io  Sun Mar 23 15:41:32 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 18:41:32 -0400
Subject: [PATCH v4] drm: Add UAPI for the Asahi driver
Message-ID: <20250323-agx-uapi-v4-1-12ed2db96737@rosenzweig.io>

This adds the UAPI for the Asahi driver targeting the GPU in the Apple
M1 and M2 series systems on chip. The UAPI design is based on other
modern Vulkan-capable drivers, including Xe and Panthor. Memory
management is based on explicit VM management. Synchronization is
exclusively explicit sync.

This UAPI is validated against our open source Mesa stack, which is
fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and
Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the
VM_BIND mechanism.

This patch adds the standalone UAPI header. It is implemented by an open
source DRM driver written in Rust. We fully intend to upstream this
driver when possible. However, as a production graphics driver, it
depends on a significant number of Rust abstractions that will take a
long time to upstream. In the mean time, our userspace is upstream in
Mesa but is not allowed to probe with upstream Mesa as the UAPI is not
yet reviewed and merged in the upstream kernel. Although we ship a
patched Mesa in Fedora Asahi Remix, any containers shipping upstream
Mesa builds are broken for our users, including upstream Flatpak and
Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa
and virglrenderer, which complicates bisects.

The intention in sending out this patch is for this UAPI to be
thoroughly reviewed. Once we as the DRM community are satisfied with the
UAPI, this header lands signifying that the UAPI is stable and must only
be evolved in backwards-compatible ways; it will be the UAPI implemented
in the DRM driver that eventually lands upstream. That promise lets us
enable upstream Mesa, solving all these issues while the upstream Rust
abstractions are developed.

https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v4 contains
the DRM driver implementing this proposed UAPI.

https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains
the Mesa patches to implement this proposed UAPI.

That Linux and Mesa branch together give a complete graphics/compute
stack on top of this UAPI.

Co-developed-by: Asahi Lina <lina at asahilina.net>
Signed-off-by: Asahi Lina <lina at asahilina.net>
Acked-by: Simona Vetter <simona.vetter at ffwll.ch>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
Changes in v4:
- get_time now returns time in nanoseconds, timer_frequency_hz dropped.
  This hides an extra time domain from userspace for no real downside.
- Added lots more comments answering questions Faith raised in v3
  review.
- Drop firmware_version per discussion.
- Drop UNBIND_ALL, it is unused.
- Switch priority to an enum per discussion.
- Drop drm_asahi_subqueue and instead make barriers separate fields to
  make obvious the extensability situation resolving discusison on v3.

Changes in v3:
- Merge load/store/partial fields for depth/stencil as discussed with
  Faith. This shrinks the submit a lot with little loss of
  functionality. There's maaaybe a use case for splitting out depth load
  base (only) later. But it's easier to add uAPI than remove it!
- Make usc_exec_base per-queue instead of per-command. No use case for
  doing it finer grained, and this shrinks the submits and simplifies
  userspace handling.
- Improve descriptions.
- Reorder/shrink fields to remove padding.
- Use full names for vdm/cdm_ctrl_stream_base
- Link to v2: https://lore.kernel.org/r/20250313-agx-uapi-v2-1-59cc53a59ea3 at rosenzweig.io

Changes in v2:
- Flatten submits. Previously, the submit ioctl pointed to an array of
  command structures, which each pointed to separate payload structures,
  which pointed to attachment structures. This is a lot of indirection,
  which complicates greatly virtgpu. In the new approach, the submit
  ioctl points to a single contiguous blob of plain-old-data, no CPU
  pointers, copied from userspace in one go and suitable as virtgpu wire
  protocol.
- Remove vm_page_size, userspace has to hardcode it anyway.
- Turn random #defines into enums for better kernel doc, etc.
- Improve comments, particularly around barriers[].
- Rename various flags/fields to better match canonical names when known
  (a lot of the names are pulled from the drivers/gpu/drm/imagination,
  naturally).
- Drop unnecessary encoder_id, cmd_id handles.
- Fix padding in submit ioctl (thanks Ryan).
- Link to v1: https://lore.kernel.org/r/20250310-agx-uapi-v1-1-86c80905004e at rosenzweig.io
---
 Documentation/gpu/driver-uapi.rst |    5 +
 MAINTAINERS                       |    1 +
 include/uapi/drm/asahi_drm.h      | 1205 +++++++++++++++++++++++++++++++++++++
 3 files changed, 1211 insertions(+)

diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
index 971cdb4816fc98d80a64d93637481d10c2e79718..1f15a8ca126516c23bd7374cc4aead0dfbbccf67 100644
--- a/Documentation/gpu/driver-uapi.rst
+++ b/Documentation/gpu/driver-uapi.rst
@@ -27,3 +27,8 @@ drm/xe uAPI
 ===========
 
 .. kernel-doc:: include/uapi/drm/xe_drm.h
+
+drm/asahi uAPI
+================
+
+.. kernel-doc:: include/uapi/drm/asahi_drm.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d1050702f681fbd0e4e2d0457b2ba569a64070d9..7f692a935808d4ec82ee741324f8043302dae491 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2256,6 +2256,7 @@ F:	drivers/watchdog/apple_wdt.c
 F:	include/dt-bindings/interrupt-controller/apple-aic.h
 F:	include/dt-bindings/pinctrl/apple.h
 F:	include/linux/soc/apple/*
+F:	include/uapi/drm/asahi_drm.h
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson at axis.com>
diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2f07a12430f170f0fb87f2298a4fddea9e075b7
--- /dev/null
+++ b/include/uapi/drm/asahi_drm.h
@@ -0,0 +1,1205 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) The Asahi Linux Contributors
+ * Copyright (C) 2018-2023 Collabora Ltd.
+ * Copyright (C) 2014-2018 Broadcom
+ */
+#ifndef _ASAHI_DRM_H_
+#define _ASAHI_DRM_H_
+
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * DOC: Introduction to the Asahi UAPI
+ *
+ * This documentation describes the Asahi IOCTLs.
+ *
+ * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
+ * from Panthor):
+ *
+ * - Structures must be aligned on 64-bit/8-byte. If the object is not
+ *   naturally aligned, a padding field must be added.
+ * - Fields must be explicitly aligned to their natural type alignment with
+ *   pad[0..N] fields.
+ * - All padding fields will be checked by the driver to make sure they are
+ *   zeroed.
+ * - Flags can be added, but not removed/replaced.
+ * - New fields can be added to the main structures (the structures
+ *   directly passed to the ioctl). Those fields can be added at the end of
+ *   the structure, or replace existing padding fields. Any new field being
+ *   added must preserve the behavior that existed before those fields were
+ *   added when a value of zero is passed.
+ * - New fields can be added to indirect objects (objects pointed by the
+ *   main structure), iff those objects are passed a size to reflect the
+ *   size known by the userspace driver (see
+ *   drm_asahi_command::cmd_buffer_size).
+ * - If the kernel driver is too old to know some fields, those will be
+ *   ignored if zero, and otherwise rejected (and so will be zero on output).
+ * - If userspace is too old to know some fields, those will be zeroed
+ *   (input) before the structure is parsed by the kernel driver.
+ * - Each new flag/field addition must come with a driver version update so
+ *   the userspace driver doesn't have to trial and error to know which
+ *   flags are supported.
+ * - Structures should not contain unions, as this would defeat the
+ *   extensibility of such structures.
+ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
+ *   at the end of the drm_asahi_ioctl_id enum.
+ */
+
+/**
+ * enum drm_asahi_ioctl_id - IOCTL IDs
+ *
+ * Place new ioctls at the end, don't re-order, don't replace or remove entries.
+ *
+ * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
+ * definitions instead.
+ */
+enum drm_asahi_ioctl_id {
+	/** @DRM_ASAHI_GET_PARAMS: Query device properties. */
+	DRM_ASAHI_GET_PARAMS = 0,
+
+	/** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
+	DRM_ASAHI_VM_CREATE,
+
+	/** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
+	DRM_ASAHI_VM_DESTROY,
+
+	/** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
+	DRM_ASAHI_GEM_CREATE,
+
+	/**
+	 * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
+	 * given GEM handle.
+	 */
+	DRM_ASAHI_GEM_MMAP_OFFSET,
+
+	/** @DRM_ASAHI_GEM_BIND: Bind/unbind memory to a VM. */
+	DRM_ASAHI_GEM_BIND,
+
+	/** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
+	DRM_ASAHI_QUEUE_CREATE,
+
+	/** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
+	DRM_ASAHI_QUEUE_DESTROY,
+
+	/** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
+	DRM_ASAHI_SUBMIT,
+
+	/** @DRM_ASAHI_GET_TIME: Query device time. */
+	DRM_ASAHI_GET_TIME,
+
+	/** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
+	DRM_ASAHI_GEM_BIND_OBJECT,
+};
+
+#define DRM_ASAHI_MAX_CLUSTERS	64
+
+/**
+ * struct drm_asahi_params_global - Global parameters.
+ *
+ * This struct may be queried by drm_asahi_get_params.
+ */
+struct drm_asahi_params_global {
+	/** @features: Feature bits from drm_asahi_feature */
+	__u64 features;
+
+	/** @gpu_generation: GPU generation, e.g. 13 for G13G */
+	__u32 gpu_generation;
+
+	/** @gpu_variant: GPU variant as a character, e.g. 'G' for G13G */
+	__u32 gpu_variant;
+
+	/**
+	 * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
+	 * 0x21 for 'C1'
+	 */
+	__u32 gpu_revision;
+
+	/** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
+	__u32 chip_id;
+
+	/** @num_dies: Number of dies in the SoC */
+	__u32 num_dies;
+
+	/** @num_clusters_total: Number of GPU clusters (across all dies) */
+	__u32 num_clusters_total;
+
+	/**
+	 * @num_cores_per_cluster: Number of logical cores per cluster
+	 * (including inactive/nonexistent)
+	 */
+	__u32 num_cores_per_cluster;
+
+	/** @num_frags_per_cluster: Number of frags per cluster */
+	__u32 num_frags_per_cluster;
+
+	/** @num_gps_per_cluster: Number of GPs per cluster */
+	__u32 num_gps_per_cluster;
+
+	/** @max_power_mw: Maximum GPU power consumption */
+	__u32 max_power_mw;
+
+	/** @core_masks: Bitmask of present/enabled cores per cluster */
+	__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
+
+	/** @min_frequency_khz: Minimum GPU core clock frequency */
+	__u32 min_frequency_khz;
+
+	/** @max_frequency_khz: Maximum GPU core clock frequency */
+	__u32 max_frequency_khz;
+
+	/**
+	 * @vm_user_start: VM user range start VMA. Together with
+	 * @vm_user_end, this defines the window of valid GPU VAs. Userspace is
+	 * expected to subdivide VAs out of this window.
+	 */
+	__u64 vm_user_start;
+
+	/** @vm_user_end: VM user range end VMA */
+	__u64 vm_user_end;
+
+	/**
+	 * @vm_kernel_min_size: Minimum kernel VMA window size within user
+	 * range.
+	 *
+	 * When creating a VM, userspace is required to carve out a section of
+	 * virtual addresses (within the range given by @vm_user_start and
+	 * @vm_user_end). The kernel will allocate various internal structures
+	 * within the specified VA range.
+	 *
+	 * Allowing userspace to choose the VA range for the kernel, rather than
+	 * the kernel reserving VAs and requiring userspace to cope, can assist
+	 * in implementing SVM.
+	 */
+	__u64 vm_kernel_min_size;
+
+	/**
+	 * @max_commands_per_submission: Maximum number of supported commands
+	 * per submission. This mirrors firmware limits. Userspace must split up
+	 * larger command buffers, which may require inserting additional
+	 * barriers explicitly.
+	 */
+	__u32 max_commands_per_submission;
+
+	/**
+	 * @max_attachments: Maximum number of drm_asahi_attachment's per
+	 * command
+	 */
+	__u32 max_attachments;
+
+	/**
+	 * @command_timestamp_frequency_hz: Timebase frequency for timestamps
+	 * written during command exeuction, specified via drm_asahi_timestamp
+	 * structures. As this rate is controlled by the firmware, it is a
+	 * queryable parameter.
+	 *
+	 * Userspace must divide by this frequency to convert timestamps to
+	 * seconds, rather than hardcoding a particular firmware's rate.
+	 */
+	__u64 command_timestamp_frequency_hz;
+};
+
+/**
+ * enum drm_asahi_feature - Feature bits
+ *
+ * This covers only features that userspace cannot infer from the architecture
+ * version. Most features don't need to be here.
+ */
+enum drm_asahi_feature {
+	/**
+	 * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
+	 * loads of unmapped memory will return zero. Shader stores to unmapped
+	 * memory will be silently discarded. Note that only shader load/store
+	 * is affected. Other hardware units are not affected, notably including
+	 * texture sampling.
+	 *
+	 * Soft fault is set when initializing the GPU and cannot be runtime
+	 * toggled. Therefore, it is exposed as a feature bit and not a
+	 * userspace-settable flag on the VM. When soft fault is enabled,
+	 * userspace can speculate memory accesses more aggressively.
+	 */
+	DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
+};
+
+/**
+ * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
+ */
+struct drm_asahi_get_params {
+	/** @param_group: Parameter group to fetch (MBZ) */
+	__u32 param_group;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @pointer: User pointer to write parameter struct */
+	__u64 pointer;
+
+	/** @size: Size of user buffer, max size supported on return */
+	__u64 size;
+};
+
+/**
+ * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
+ */
+struct drm_asahi_vm_create {
+	/**
+	 * @kernel_start: Start of the kernel-reserved address range. See
+	 * drm_asahi_params_global::vm_kernel_min_size.
+	 *
+	 * Both @kernel_start and @kernel_end must be within the range of
+	 * valid VAs given by drm_asahi_params_global::vm_user_start and
+	 * drm_asahi_params_global::vm_user_end. The size of the kernel range
+	 * (@kernel_end - @kernel_start) must be at least
+	 * drm_asahi_params_global::vm_kernel_min_size.
+	 *
+	 * Userspace must not bind any memory on this VM into this reserved
+	 * range, it is for kernel use only.
+	 */
+	__u64 kernel_start;
+
+	/**
+	 * @kernel_end: End of the kernel-reserved address range. See
+	 * @kernel_start.
+	 */
+	__u64 kernel_end;
+
+	/** @vm_id: Returned VM ID */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
+ */
+struct drm_asahi_vm_destroy {
+	/** @vm_id: VM ID to be destroyed */
+	__u32 vm_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_gem_flags - Flags for GEM creation
+ */
+enum drm_asahi_gem_flags {
+	/**
+	 * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
+	 *
+	 * Map as writeback instead of write-combine. This optimizes for CPU
+	 * reads.
+	 */
+	DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
+
+	/**
+	 * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
+	 */
+	DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
+};
+
+/**
+ * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
+ */
+struct drm_asahi_gem_create {
+	/** @size: Size of the BO */
+	__u64 size;
+
+	/** @flags: Combination of drm_asahi_gem_flags flags. */
+	__u32 flags;
+
+	/**
+	 * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
+	 */
+	__u32 vm_id;
+
+	/** @handle: Returned GEM handle for the BO */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_gem_mmap_offset - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
+ */
+struct drm_asahi_gem_mmap_offset {
+	/** @handle: Handle for the object being mapped. */
+	__u32 handle;
+
+	/** @flags: Must be zero */
+	__u32 flags;
+
+	/** @offset: The fake offset to use for subsequent mmap call */
+	__u64 offset;
+};
+
+/**
+ * enum drm_asahi_bind_op - Bind operation
+ */
+enum drm_asahi_bind_op {
+	/** @DRM_ASAHI_BIND_OP_BIND: Bind a BO to a GPU VMA range */
+	DRM_ASAHI_BIND_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OP_UNBIND: Unbind a GPU VMA range */
+	DRM_ASAHI_BIND_OP_UNBIND = 1,
+};
+
+/**
+ * enum drm_asahi_bind_flags - Flags for GEM binding
+ */
+enum drm_asahi_bind_flags {
+	/** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
+	DRM_ASAHI_BIND_READ = (1L << 0),
+
+	/** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
+	DRM_ASAHI_BIND_WRITE = (1L << 1),
+
+	/**
+	 * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
+	 * across the VA range.
+	 *
+	 * This is useful to fill a VA range with scratch pages or zero pages.
+	 * It is intended as a mechanism to accelerate sparse.
+	 */
+	DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
+};
+
+/**
+ * struct drm_asahi_gem_bind - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND
+ */
+struct drm_asahi_gem_bind {
+	/** @op: Bind operation (enum drm_asahi_bind_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind (BIND only) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on */
+	__u32 vm_id;
+
+	/**
+	 * @offset: Offset into the object (BIND only).
+	 *
+	 * For a regular bind, this is the beginning of the region of the GEM
+	 * object to bind.
+	 *
+	 * For a single-page bind, this is the offset to the single page that
+	 * will be repeatedly bound.
+	 *
+	 * Must be page-size aligned.
+	 */
+	__u64 offset;
+
+	/**
+	 * @range: Number of bytes to bind/unbind to addr.
+	 *
+	 * Must be page-size aligned.
+	 */
+	__u64 range;
+
+	/**
+	 * @addr: Address to bind to.
+	 *
+	 * Must be page-size aligned.
+	 */
+	__u64 addr;
+};
+
+/**
+ * enum drm_asahi_bind_object_op - Special object bind operation
+ */
+enum drm_asahi_bind_object_op {
+	/** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
+
+	/** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
+	DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
+};
+
+/**
+ * enum drm_asahi_bind_object_flags - Special object bind flags
+ */
+enum drm_asahi_bind_object_flags {
+	/**
+	 * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
+	 * buffer.
+	 */
+	DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
+};
+
+/**
+ * struct drm_asahi_gem_bind_object - Arguments passed to
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
+ */
+struct drm_asahi_gem_bind_object {
+	/** @op: Bind operation (enum drm_asahi_bind_object_op) */
+	__u32 op;
+
+	/** @flags: Combination of drm_asahi_bind_object_flags flags. */
+	__u32 flags;
+
+	/** @handle: GEM object to bind/unbind (BIND) */
+	__u32 handle;
+
+	/** @vm_id: The ID of the VM to operate on (MBZ currently) */
+	__u32 vm_id;
+
+	/** @offset: Offset into the object (BIND only) */
+	__u64 offset;
+
+	/** @range: Number of bytes to bind/unbind (BIND only) */
+	__u64 range;
+
+	/** @object_handle: Object handle (out for BIND, in for UNBIND) */
+	__u32 object_handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_cmd_type - Command type
+ */
+enum drm_asahi_cmd_type {
+	/**
+	 * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
+	 * subqueue. Combined vertex and fragment operation.
+	 *
+	 * Followed by a @drm_asahi_cmd_render payload.
+	 */
+	DRM_ASAHI_CMD_RENDER = 0,
+
+	/**
+	 * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
+	 *
+	 * Followed by a @drm_asahi_cmd_compute payload.
+	 */
+	DRM_ASAHI_CMD_COMPUTE = 1,
+
+	/**
+	 * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
+	 * attachments for subsequent vertex shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
+
+	/**
+	 * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
+	 * attachments for subsequent fragment shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
+
+	/**
+	 * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
+	 * attachments for subsequent compute shaders in the same submit.
+	 *
+	 * Followed by (possibly multiple) @drm_asahi_attachment payloads.
+	 */
+	DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
+};
+
+/**
+ * enum drm_asahi_queue_cap - Queue capabilities
+ */
+enum drm_asahi_queue_cap {
+	/** @DRM_ASAHI_QUEUE_CAP_RENDER: Supports render commands */
+	DRM_ASAHI_QUEUE_CAP_RENDER	= (1UL << DRM_ASAHI_CMD_RENDER),
+
+	/** @DRM_ASAHI_QUEUE_CAP_COMPUTE: Supports compute commands */
+	DRM_ASAHI_QUEUE_CAP_COMPUTE	= (1UL << DRM_ASAHI_CMD_COMPUTE),
+};
+
+/**
+ * enum drm_asahi_priority - Scheduling queue priority.
+ *
+ * These priorities are forwarded to the firmware to influence firmware
+ * scheduling. The exact policy is ultimately decided by firmware, but
+ * these enums allow userspace to communicate the intentions.
+ */
+enum drm_asahi_priority {
+	/** @DRM_ASAHI_PRIORITY_LOW: Low priority queue. */
+	DRM_ASAHI_PRIORITY_LOW = 0,
+
+	/** @DRM_ASAHI_PRIORITY_MEDIUM: Medium priority queue. */
+	DRM_ASAHI_PRIORITY_MEDIUM = 1,
+
+	/**
+	 * @DRM_ASAHI_PRIORITY_HIGH: High priority queue.
+	 *
+	 * Reserved. Creating a high priority queue already fails currently. In
+	 * the future, this will be supported only with elevated permissions.
+	 */
+	DRM_ASAHI_PRIORITY_HIGH = 2,
+
+	/**
+	 * @DRM_ASAHI_PRIORITY_REALTIME: Realtime priority queue.
+	 *
+	 * Reserved. Creating a high priority queue already fails currently. In
+	 * the future, this will be supported only with elevated permissions.
+	 */
+	DRM_ASAHI_PRIORITY_REALTIME = 3,
+};
+
+/**
+ * struct drm_asahi_queue_create - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_CREATE
+ */
+struct drm_asahi_queue_create {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @vm_id: The ID of the VM this queue is bound to */
+	__u32 vm_id;
+
+	/** @queue_caps: Bitmask of DRM_ASAHI_QUEUE_CAP_* */
+	__u32 queue_caps;
+
+	/** @priority: One of drm_asahi_priority */
+	__u32 priority;
+
+	/** @queue_id: The returned queue ID */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/**
+	 * @usc_exec_base: GPU base address for all USC binaries (shaders) on
+	 * this queue. USC addresses are 32-bit relative to this 64-bit base.
+	 *
+	 * This sets the following registers on all queue commands:
+	 *
+	 *	USC_EXEC_BASE_TA  (vertex)
+	 *	USC_EXEC_BASE_ISP (fragment)
+	 *	USC_EXEC_BASE_CP  (compute)
+	 *
+	 * While the hardware lets us configure these independently per command,
+	 * we do not have a use case for this. Instead, we expect userspace to
+	 * fix a 4GiB VA carveout for USC memory and pass its base address here.
+	 */
+	__u64 usc_exec_base;
+};
+
+/**
+ * struct drm_asahi_queue_destroy - Arguments passed to
+ * DRM_IOCTL_ASAHI_QUEUE_DESTROY
+ */
+struct drm_asahi_queue_destroy {
+	/** @queue_id: The queue ID to be destroyed */
+	__u32 queue_id;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_asahi_sync_type - Sync item type
+ */
+enum drm_asahi_sync_type {
+	/** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
+	DRM_ASAHI_SYNC_SYNCOBJ = 0,
+
+	/** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
+	DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
+};
+
+/**
+ * struct drm_asahi_sync - Sync item
+ */
+struct drm_asahi_sync {
+	/** @sync_type: One of drm_asahi_sync_type */
+	__u32 sync_type;
+
+	/** @handle: The sync object handle */
+	__u32 handle;
+
+	/** @timeline_value: Timeline value for timeline sync objects */
+	__u64 timeline_value;
+};
+
+/**
+ * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
+ *
+ * This special value may be passed in to drm_asahi_command::barriers[] to
+ * indicate that the respective subqueue should not wait on any previous work.
+ */
+#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
+
+/**
+ * struct drm_asahi_cmd_header - Top level command structure
+ *
+ * This struct is core to the command buffer definition and therefore is not
+ * extensible.
+ */
+struct drm_asahi_cmd_header {
+	/** @cmd_type: One of drm_asahi_cmd_type */
+	__u16 cmd_type;
+
+	/**
+	 * @size: Size of this command, not including this header.
+	 *
+	 * For hardware commands, this enables extensibility of commands without
+	 * requiring extra command types.  Passing a command that is shorter
+	 * than expected is explicitly allowed for backwards-compatability.
+	 * Truncated fields will be zeroed.
+	 *
+	 * For the synthetic attachment setting commands, this implicitly
+	 * encodes the number of attachments. These commands take multiple
+	 * fixed-size @drm_asahi_attachment structures as their payload, so size
+	 * equals number of attachments * sizeof(struct drm_asahi_attachment).
+	 */
+	__u16 size;
+
+	/**
+	 * @vdm_barrier: VDM (render) command index to wait on.
+	 *
+	 * Barriers are indices relative to the beginning of a given submit. A
+	 * barrier of 0 waits on commands submitted to the respective subqueue
+	 * in previous submit ioctls. A barrier of N waits on N previous
+	 * commands on the subqueue within the current submit ioctl. As a
+	 * special case, passing @DRM_ASAHI_BARRIER_NONE avoids waiting on any
+	 * commands in the subqueue.
+	 *
+	 * Examples:
+	 *
+	 *   0: This waits on all previous work.
+	 *
+	 *   NONE: This does not wait for anything on this subqueue.
+	 *
+	 *   1: This waits on the first render command in the submit.
+	 *   This only makes sense if there are multiple render commands in the
+	 *   same submit.
+	 *
+	 * Barriers only make sense for hardware commands. Synthetic software
+	 * commands to set attachments must pass NONE here.
+	 */
+	__u16 vdm_barrier;
+
+	/**
+	 * @cdm_barrier: CDM (compute) command index to wait on.
+	 *
+	 * See @vdm_barrier, and substitute VDM/render for CDM/compute.
+	 */
+	__u16 cdm_barrier;
+};
+
+/**
+ * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
+ */
+struct drm_asahi_submit {
+	/**
+	 * @in_syncs: An optional array of drm_asahi_sync to wait on before
+	 * starting this job.
+	 */
+	__u64 in_syncs;
+
+	/**
+	 * @out_syncs: An optional array of drm_asahi_sync objects to signal
+	 * upon completion.
+	 */
+	__u64 out_syncs;
+
+	/**
+	 * @cmdbuf: Pointer to the command buffer to submit.
+	 *
+	 * This is a flat command buffer. By design, it contains no CPU
+	 * pointers, which makes it suitable for a virtgpu wire protocol without
+	 * requiring any serializing/deserializing step.
+	 *
+	 * It consists of a series of commands. Each command begins with a
+	 * fixed-size @drm_asahi_cmd_header and is followed by a variable-length
+	 * payload according to the type and size in the header.
+	 *
+	 * The combined count of "real" hardware commands must be nonzero and at
+	 * most drm_asahi_params_global::max_commands_per_submission.
+	 */
+	__u64 cmdbuf;
+
+	/** @flags: Flags for command submission (MBZ) */
+	__u32 flags;
+
+	/** @queue_id: The queue ID to be submitted to */
+	__u32 queue_id;
+
+	/**
+	 * @in_sync_count: Number of sync objects to wait on before starting
+	 * this job.
+	 */
+	__u32 in_sync_count;
+
+	/**
+	 * @out_sync_count: Number of sync objects to signal upon completion of
+	 * this job.
+	 */
+	__u32 out_sync_count;
+
+	/** @cmdbuf_size: Command buffer size in bytes */
+	__u32 cmdbuf_size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_asahi_attachment - Describe an "attachment".
+ *
+ * Attachments are any memory written by shaders, notably including render
+ * target attachments written by the end-of-tile program. This is purely a hint
+ * about the accessed memory regions. It is optional to specify, which is
+ * fortunate as it cannot be specified precisely with bindless access anyway.
+ * But where possible, it's probably a good idea for userspace to include these
+ * hints, forwarded to the firmware.
+ *
+ * This struct is implicitly sized and therefore is not extensible.
+ */
+struct drm_asahi_attachment {
+	/** @pointer: Base address of the attachment */
+	__u64 pointer;
+
+	/** @size: Size of the attachment in bytes */
+	__u64 size;
+
+	/** @pad: MBZ */
+	__u32 pad;
+
+	/** @flags: MBZ */
+	__u32 flags;
+};
+
+enum drm_asahi_render_flags {
+	/**
+	 * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
+	 * memory.
+	 */
+	DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0),
+
+	/**
+	 * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
+	 * This must be set when clearing render targets.
+	 */
+	DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1),
+
+	/**
+	 * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
+	 * cluster (on multicluster GPUs)
+	 *
+	 * This harms performance but can workaround certain sync/coherency
+	 * bugs, and therefore is useful for debugging.
+	 */
+	DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2),
+
+	/**
+	 * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
+	 *
+	 * Graphics specifications contain two alternate formulas for depth
+	 * bias, a float formula used with floating-point depth buffers and an
+	 * integer formula using with unorm depth buffers. This flag specifies
+	 * that the integer formula should be used. If omitted, the float
+	 * formula is used instead.
+	 *
+	 * This corresponds to bit 18 of the relevant hardware control register,
+	 * so we match that here for efficiency.
+	 */
+	DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18),
+};
+
+/**
+ * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
+ *
+ * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit.
+ * There are three hardware registers for each field respectively for loads,
+ * stores, and partial renders. In practice, it makes sense to set all to the
+ * same values, except in exceptional cases not yet implemented in userspace, so
+ * we do not duplicate here for simplicity/efficiency.
+ */
+struct drm_asahi_zls_buffer {
+	/** @base: Base address of the buffer */
+	__u64 base;
+
+	/**
+	 * @comp_base: If the load buffer is compressed, address of the
+	 * compression metadata section.
+	 */
+	__u64 comp_base;
+
+	/**
+	 * @stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the buffer.
+	 */
+	__u32 stride;
+
+	/**
+	 * @comp_stride: If layered rendering is enabled, the number of bytes
+	 * between each layer of the compression metadata.
+	 */
+	__u32 comp_stride;
+};
+
+/**
+ * struct drm_asahi_timestamp - Describe a timestamp write.
+ *
+ * The firmware can optionally write the GPU timestamp at render pass
+ * granularities, but it needs to be mapped specially via
+ * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
+ * write as a handle-offset pair, rather than a GPU address like normal.
+ *
+ * This struct is embedded in other structs and therefore is not extensible.
+ */
+struct drm_asahi_timestamp {
+	/**
+	 * @handle: Handle of the timestamp buffer, or 0 to skip this
+	 * timestamp. If nonzero, this must equal the value returned in
+	 * drm_asahi_gem_bind_object::object_handle.
+	 */
+	__u32 handle;
+
+	/** @offset: Offset to write into the timestamp buffer */
+	__u32 offset;
+};
+
+/**
+ * struct drm_asahi_timestamps - Describe timestamp writes.
+ *
+ * Each operation that can be timestamped, can be timestamped at the start and
+ * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
+ * together into drm_asahi_timestamps.
+ *
+ * This struct is embedded in other structs and therefore is not extensible.
+ */
+struct drm_asahi_timestamps {
+	/** @start: Timestamp recorded at the start of the operation */
+	struct drm_asahi_timestamp start;
+
+	/** @end: Timestamp recorded at the end of the operation */
+	struct drm_asahi_timestamp end;
+};
+
+/**
+ * struct drm_asahi_helper_program - Describe helper program configuration.
+ *
+ * The helper program is a compute-like kernel required for various hardware
+ * functionality. Its most important role is dynamically allocating
+ * scratch/stack memory for individual subgroups, by partitioning a static
+ * allocation shared for the whole device. It is supplied by userspace via
+ * drm_asahi_helper_program and internally dispatched by the hardware as needed.
+ *
+ * This struct is embedded in other structs and therefore is not extensible.
+ */
+struct drm_asahi_helper_program {
+	/**
+	 * @binary: USC address to the helper program binary. This is a tagged
+	 * pointer with configuration in the bottom bits.
+	 */
+	__u32 binary;
+
+	/** @cfg: Configuration bits for the helper program. */
+	__u32 cfg;
+
+	/**
+	 * @data: Data passed to the helper program. This value is not
+	 * interpreted by the kernel, firmware, or hardware in any way. It is
+	 * simply a sideband for userspace, set with the submit ioctl and read
+	 * via special registers inside the helper program.
+	 *
+	 * In practice, userspace will pass a 64-bit GPU VA here pointing to the
+	 * actual arguments, which presumably don't fit in 64-bits.
+	 */
+	__u64 data;
+};
+
+/**
+ * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
+ *
+ * The background and end-of-tile programs are dispatched by the hardware at the
+ * beginning and end of rendering. As the hardware "tilebuffer" is simply local
+ * memory, these programs are necessary to implement API-level render targets.
+ * The fragment-like background program is responsible for loading either the
+ * clear colour or the existing render target contents, while the compute-like
+ * end-of-tile program stores the tilebuffer contents to memory.
+ *
+ * This struct is embedded in other structs and therefore is not extensible.
+ */
+struct drm_asahi_bg_eot {
+	/**
+	 * @usc: USC address of the hardware USC words binding resources
+	 * (including images and uniforms) and the program itself. Note this is
+	 * an additional layer of indirection compared to the helper program,
+	 * avoiding the need for a sideband for data. This is a tagged pointer
+	 * with additional configuration in the bottom bits.
+	 */
+	__u32 usc;
+
+	/**
+	 * @rsrc_spec: Resource specifier for the program. This is a packed
+	 * hardware data structure describing the required number of registers,
+	 * uniforms, bound textures, and bound samplers.
+	 */
+	__u32 rsrc_spec;
+};
+
+/**
+ * struct drm_asahi_cmd_render - Command to submit 3D
+ *
+ * This command submits a single render pass. The hardware control stream may
+ * include many draws and subpasses, but within the command, the framebuffer
+ * dimensions and attachments are fixed.
+ *
+ * The hardware requires the firmware to set a large number of Control Registers
+ * setting up state at render pass granularity before each command rendering 3D.
+ * The firmware bundles this state into data structures. Unfortunately, we
+ * cannot expose either any of that directly to userspace, because the
+ * kernel-firmware ABI is not stable. Although we can guarantee the firmware
+ * updates in tandem with the kernel, we cannot break old userspace when
+ * upgrading the firmware and kernel. Therefore, we need to abstract well the
+ * data structures to avoid tying our hands with future firmwares.
+ *
+ * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
+ * control registers, marshalled via the firmware interface.
+ *
+ * The framebuffer/tilebuffer dimensions are also specified here. In addition to
+ * being passed to the firmware/hardware, the kernel requires these dimensions
+ * to calculate various essential tiling-related data structures. It is
+ * unfortunate that our submits are heavier than on vendors with saner
+ * hardware-software interfaces. The upshot is all of this information is
+ * readily available to userspace with all current APIs.
+ *
+ * It looks odd - but it's not overly burdensome and it ensures we can remain
+ * compatible with old userspace.
+ */
+struct drm_asahi_cmd_render {
+	/** @flags: Combination of drm_asahi_render_flags flags. */
+	__u32 flags;
+
+	/**
+	 * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
+	 * depth/stencil width/height, which may differ from the framebuffer
+	 * width/height.
+	 */
+	__u32 isp_zls_pixels;
+
+	/**
+	 * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU
+	 * address to the beginning of the VDM control stream.
+	 */
+	__u64 vdm_ctrl_stream_base;
+
+	/** @vertex_helper: Helper program used for the vertex shader */
+	struct drm_asahi_helper_program vertex_helper;
+
+	/** @fragment_helper: Helper program used for the fragment shader */
+	struct drm_asahi_helper_program fragment_helper;
+
+	/**
+	 * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
+	 * array of scissor descriptors indexed in the render pass.
+	 */
+	__u64 isp_scissor_base;
+
+	/**
+	 * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
+	 * array of depth bias values indexed in the render pass.
+	 */
+	__u64 isp_dbias_base;
+
+	/**
+	 * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
+	 * array of occlusion query results written by the render pass.
+	 */
+	__u64 isp_oclqry_base;
+
+	/** @depth: Depth buffer */
+	struct drm_asahi_zls_buffer depth;
+
+	/** @stencil: Stencil buffer */
+	struct drm_asahi_zls_buffer stencil;
+
+	/** @zls_ctrl: ZLS_CTRL register value */
+	__u64 zls_ctrl;
+
+	/** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
+	__u64 ppp_multisamplectl;
+
+	/**
+	 * @sampler_heap: Base address of the sampler heap. This heap is used
+	 * for both vertex shaders and fragment shaders. The registers are
+	 * per-stage, but there is no known use case for separate heaps.
+	 */
+	__u64 sampler_heap;
+
+	/** @ppp_ctrl: PPP_CTRL register value */
+	__u32 ppp_ctrl;
+
+	/** @width_px: Framebuffer width in pixels */
+	__u16 width_px;
+
+	/** @height_px: Framebuffer height in pixels */
+	__u16 height_px;
+
+	/** @layers: Number of layers in the framebuffer */
+	__u16 layers;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u16 sampler_count;
+
+	/** @utile_width_px: Width of a logical tilebuffer tile in pixels */
+	__u8 utile_width_px;
+
+	/** @utile_height_px: Height of a logical tilebuffer tile in pixels */
+	__u8 utile_height_px;
+
+	/** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
+	__u8 samples;
+
+	/** @sample_size_B: # of bytes in the tilebuffer required per sample. */
+	__u8 sample_size_B;
+
+	/**
+	 * @isp_merge_upper_x: 32-bit float used in the hardware triangle
+	 * merging. Calculate as: tan(60 deg) * width.
+	 *
+	 * Making these values UAPI avoids requiring floating-point calculations
+	 * in the kernel in the hot path.
+	 */
+	__u32 isp_merge_upper_x;
+
+	/**
+	 * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height.
+	 * See @isp_merge_upper_x.
+	 */
+	__u32 isp_merge_upper_y;
+
+	/** @bg: Background program run for each tile at the start */
+	struct drm_asahi_bg_eot bg;
+
+	/** @eot: End-of-tile program ran for each tile at the end */
+	struct drm_asahi_bg_eot eot;
+
+	/**
+	 * @partial_bg: Background program ran at the start of each tile when
+	 * resuming the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_bg;
+
+	/**
+	 * @partial_eot: End-of-tile program ran at the end of each tile when
+	 * pausing the render pass during a partial render.
+	 */
+	struct drm_asahi_bg_eot partial_eot;
+
+	/**
+	 * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
+	 * buffer clear value, encoded in the depth buffer's format: either a
+	 * 32-bit float or a 16-bit unorm (with upper bits zeroed).
+	 */
+	__u32 isp_bgobjdepth;
+
+	/**
+	 * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
+	 * contain the stencil buffer clear value.
+	 */
+	__u32 isp_bgobjvals;
+
+	/** @ts_vtx: Timestamps for the vertex portion of the render */
+	struct drm_asahi_timestamps ts_vtx;
+
+	/** @ts_frag: Timestamps for the fragment portion of the render */
+	struct drm_asahi_timestamps ts_frag;
+};
+
+/**
+ * struct drm_asahi_cmd_compute - Command to submit compute
+ *
+ * This command submits a control stream consisting of compute dispatches. There
+ * is essentially no limit on how many compute dispatches may be included in a
+ * single compute command, although timestamps are at command granularity.
+ */
+struct drm_asahi_cmd_compute {
+	/** @flags: MBZ */
+	__u32 flags;
+
+	/** @sampler_count: Number of samplers in the sampler heap. */
+	__u32 sampler_count;
+
+	/**
+	 * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU
+	 * address to the beginning of the CDM control stream.
+	 */
+	__u64 cdm_ctrl_stream_base;
+
+	/**
+	 * @cdm_ctrl_stream_end: GPU base address to the end of the hardware
+	 * control stream. Note this only considers the first contiguous segment
+	 * of the control stream, as the stream might jump elsewhere.
+	 */
+	__u64 cdm_ctrl_stream_end;
+
+	/** @sampler_heap: Base address of the sampler heap. */
+	__u64 sampler_heap;
+
+	/** @helper: Helper program used for this compute command */
+	struct drm_asahi_helper_program helper;
+
+	/** @ts: Timestamps for the compute command */
+	struct drm_asahi_timestamps ts;
+};
+
+/**
+ * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
+ */
+struct drm_asahi_get_time {
+	/** @flags: MBZ. */
+	__u64 flags;
+
+	/** @gpu_timestamp: On return, the GPU timestamp in nanoseconds. */
+	__u64 gpu_timestamp;
+};
+
+/**
+ * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
+ * @__access: Access type. Must be R, W or RW.
+ * @__id: One of the DRM_ASAHI_xxx id.
+ * @__type: Suffix of the type being passed to the IOCTL.
+ *
+ * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
+ * values instead.
+ *
+ * Return: An IOCTL number to be passed to ioctl() from userspace.
+ */
+#define DRM_IOCTL_ASAHI(__access, __id, __type) \
+	DRM_IO ## __access(DRM_COMMAND_BASE + DRM_ASAHI_ ## __id, \
+			   struct drm_asahi_ ## __type)
+
+/* Note: this is an enum so that it can be resolved by Rust bindgen. */
+enum {
+	DRM_IOCTL_ASAHI_GET_PARAMS       = DRM_IOCTL_ASAHI(WR, GET_PARAMS, get_params),
+	DRM_IOCTL_ASAHI_VM_CREATE        = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
+	DRM_IOCTL_ASAHI_VM_DESTROY       = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
+	DRM_IOCTL_ASAHI_GEM_CREATE       = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
+	DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET  = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
+	DRM_IOCTL_ASAHI_GEM_BIND         = DRM_IOCTL_ASAHI(W, GEM_BIND, gem_bind),
+	DRM_IOCTL_ASAHI_QUEUE_CREATE     = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
+	DRM_IOCTL_ASAHI_QUEUE_DESTROY    = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
+	DRM_IOCTL_ASAHI_SUBMIT           = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
+	DRM_IOCTL_ASAHI_GET_TIME         = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
+	DRM_IOCTL_ASAHI_GEM_BIND_OBJECT  = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _ASAHI_DRM_H_ */

---
base-commit: 0ed1356af8f629ae807963b7db4e501e3b580bc2
change-id: 20250307-agx-uapi-930579437f19

Best regards,
-- 
Alyssa Rosenzweig <alyssa at rosenzweig.io>



From andre.draszik at linaro.org  Sun Mar 23 15:39:24 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:24 +0000
Subject: [PATCH 08/34] mfd: sec: fix open parenthesis alignment
 (of_property_read_bool)
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-8-d08943702707@linaro.org>

As a preparation for adding support for Samsung's S2MPG10, which is
connected via SPEEDY / ACPM rather than I2C, we're going to split out
(move) all I2C-specific driver code into its own kernel module, and
create a (common) core transport-agnostic kernel module.

That move of code would highlight some unexpected alignment which
checkpatch would complain about. To avoid that, address the error now,
before the split, to keep the amount of unrelated changes to a minimum
when actually doing the split.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-core.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 83693686567df61b5e09f7129dc6b01d69156ff3..b931f66f366571d93ce59c301265fe1c9550b37d 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -276,10 +276,12 @@ sec_pmic_i2c_parse_dt_pdata(struct device *dev)
 	if (!pd)
 		return ERR_PTR(-ENOMEM);
 
-	pd->manual_poweroff = of_property_read_bool(dev->of_node,
-						"samsung,s2mps11-acokb-ground");
-	pd->disable_wrstbi = of_property_read_bool(dev->of_node,
-						"samsung,s2mps11-wrstbi-ground");
+	pd->manual_poweroff =
+		of_property_read_bool(dev->of_node,
+				      "samsung,s2mps11-acokb-ground");
+	pd->disable_wrstbi =
+		of_property_read_bool(dev->of_node,
+				      "samsung,s2mps11-wrstbi-ground");
 	return pd;
 }
 

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:25 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:25 +0000
Subject: [PATCH 09/34] mfd: sec: slightly rework runtime platform data
 allocation
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-9-d08943702707@linaro.org>

As a preparation for adding support for Samsung's S2MPG10, which is
connected via SPEEDY / ACPM rather than I2C, we're going to split out
(move) all I2C-specific driver code into its own kernel module, and
create a (common) core transport-agnostic kernel module.

Transport drivers will have to do device tree parsing, and the core
driver will allocate its own additional memory as needed.

In preparation for that change, separate out runtime platform data
allocation from device tree parsing.

Having this change will create less churn in the upcoming split of the
transport-specific parts.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-core.c | 30 ++++++++++++------------------
 1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index b931f66f366571d93ce59c301265fe1c9550b37d..9c514f4b5f853ec2b4e234c578935ffad145cd4b 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -262,27 +262,16 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
  * Only the common platform data elements for s5m8767 are parsed here from the
  * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
  * others have to parse their own platform data elements from device tree.
- *
- * The s5m8767 platform data structure is instantiated here and the drivers for
- * the sub-modules need not instantiate another instance while parsing their
- * platform data.
  */
-static struct sec_platform_data *
-sec_pmic_i2c_parse_dt_pdata(struct device *dev)
+static void sec_pmic_i2c_parse_dt_pdata(struct device *dev,
+					struct sec_platform_data *pd)
 {
-	struct sec_platform_data *pd;
-
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd)
-		return ERR_PTR(-ENOMEM);
-
 	pd->manual_poweroff =
 		of_property_read_bool(dev->of_node,
 				      "samsung,s2mps11-acokb-ground");
 	pd->disable_wrstbi =
 		of_property_read_bool(dev->of_node,
 				      "samsung,s2mps11-wrstbi-ground");
-	return pd;
 }
 
 static int sec_pmic_probe(struct i2c_client *i2c)
@@ -303,11 +292,16 @@ static int sec_pmic_probe(struct i2c_client *i2c)
 	sec_pmic->i2c = i2c;
 	sec_pmic->irq = i2c->irq;
 
-	pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);
-	if (IS_ERR(pdata)) {
-		ret = PTR_ERR(pdata);
-		return ret;
-	}
+	/*
+	 * The s5m8767 platform data structure is instantiated here and the
+	 * drivers for the sub-modules need not instantiate another instance
+	 * while parsing their platform data.
+	 */
+	pdata = devm_kzalloc(sec_pmic->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev, pdata);
 
 	sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev);
 	sec_pmic->pdata = pdata;

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:26 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:26 +0000
Subject: [PATCH 10/34] mfd: sec: split into core and transport (i2c)
 drivers
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-10-d08943702707@linaro.org>

As a preparation for adding support for Samsung's S2MPG10, which is
connected via SPEEDY / ACPM rather than I2C, split out (move) all
I2C-specific driver code into its own kernel module, sec-i2c, and
make the existing sec-core module be just the transport-agnostic core
driver kernel module.

Also add myself to MODULE_AUTHOR() and update file headers due to that
and all the follow-up rework.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

--
Note: checkpatch complains about missing help for MFD_SEC_I2C here, but
that's a false-positive due to patch context.
It also suggests to update MAINTAINERS, but the new file is covered
already due to using a wildcard.
---
 drivers/mfd/Kconfig    |  18 ++--
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/sec-core.c | 268 +++++++------------------------------------------
 drivers/mfd/sec-core.h |  17 ++++
 drivers/mfd/sec-i2c.c  | 252 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 316 insertions(+), 240 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 205918c826334981587c4179bb00481c336ab8d5..9cce9a632827a38d6e4396167aa3b0391f273e97 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1316,21 +1316,25 @@ config MFD_RN5T618
 	  functionality of the device.
 
 config MFD_SEC_CORE
-	tristate "Samsung Electronics PMIC Series Support"
+	tristate
+	select MFD_CORE
+	select REGMAP_IRQ
+
+config MFD_SEC_I2C
+	tristate "Samsung Electronics S2MPA/S2MPS1X/S2MPU/S5M series PMICs"
 	depends on I2C=y
 	depends on OF
-	select MFD_CORE
+	select MFD_SEC_CORE
 	select REGMAP_I2C
-	select REGMAP_IRQ
 	help
-	  Support for the Samsung Electronics PMIC devices coming
-	  usually along with Samsung Exynos SoC chipset.
+	  Support for the Samsung Electronics PMIC devices with I2C interface
+	  coming usually along with Samsung Exynos SoC chipset.
 	  This driver provides common support for accessing the device,
 	  additional drivers must be enabled in order to use the functionality
-	  of the device
+	  of the device.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called sec-core.
+	  module will be called sec-i2c.
 	  Have in mind that important core drivers (like regulators) depend
 	  on this driver so building this as a module might require proper
 	  initial ramdisk or might not boot up as well in certain scenarios.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 320a431b4aa11e8d4d99740dfa16267a83cb417d..ca9efff5780a7c818ca6cfe017c0f897ca70b449 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -233,6 +233,7 @@ obj-$(CONFIG_MFD_RK8XX_I2C)	+= rk8xx-i2c.o
 obj-$(CONFIG_MFD_RK8XX_SPI)	+= rk8xx-spi.o
 obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_SEC_I2C)	+= sec-i2c.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_MFD_VEXPRESS_SYSREG)	+= vexpress-sysreg.o
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 9c514f4b5f853ec2b4e234c578935ffad145cd4b..e81da34cf6795beca5f660fb46eefa4b5f8957d1 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -1,25 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0+
-//
-// Copyright (c) 2012 Samsung Electronics Co., Ltd
-//              http://www.samsung.com
+/*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *                http://www.samsung.com
+ * Copyright 2025 Linaro Ltd.
+ *
+ * Samsung SxM core driver
+ */
 
 #include <linux/device.h>
 #include <linux/err.h>
-#include <linux/i2c.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
-#include <linux/mfd/samsung/s2mpa01.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
-#include <linux/mfd/samsung/s2mps14.h>
-#include <linux/mfd/samsung/s2mps15.h>
-#include <linux/mfd/samsung/s2mpu02.h>
-#include <linux/mfd/samsung/s5m8767.h>
-#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -88,144 +85,6 @@ static const struct mfd_cell s2mpu05_devs[] = {
 	{ .name = "s2mps15-rtc", },
 };
 
-static const struct of_device_id sec_dt_match[] = {
-	{
-		.compatible = "samsung,s5m8767-pmic",
-		.data = (void *)S5M8767X,
-	}, {
-		.compatible = "samsung,s2dos05",
-		.data = (void *)S2DOS05,
-	}, {
-		.compatible = "samsung,s2mps11-pmic",
-		.data = (void *)S2MPS11X,
-	}, {
-		.compatible = "samsung,s2mps13-pmic",
-		.data = (void *)S2MPS13X,
-	}, {
-		.compatible = "samsung,s2mps14-pmic",
-		.data = (void *)S2MPS14X,
-	}, {
-		.compatible = "samsung,s2mps15-pmic",
-		.data = (void *)S2MPS15X,
-	}, {
-		.compatible = "samsung,s2mpa01-pmic",
-		.data = (void *)S2MPA01,
-	}, {
-		.compatible = "samsung,s2mpu02-pmic",
-		.data = (void *)S2MPU02,
-	}, {
-		.compatible = "samsung,s2mpu05-pmic",
-		.data = (void *)S2MPU05,
-	}, {
-		/* Sentinel */
-	},
-};
-MODULE_DEVICE_TABLE(of, sec_dt_match);
-
-static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
-{
-	switch (reg) {
-	case S2MPA01_REG_INT1M:
-	case S2MPA01_REG_INT2M:
-	case S2MPA01_REG_INT3M:
-		return false;
-	default:
-		return true;
-	}
-}
-
-static bool s2mps11_volatile(struct device *dev, unsigned int reg)
-{
-	switch (reg) {
-	case S2MPS11_REG_INT1M:
-	case S2MPS11_REG_INT2M:
-	case S2MPS11_REG_INT3M:
-		return false;
-	default:
-		return true;
-	}
-}
-
-static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
-{
-	switch (reg) {
-	case S2MPU02_REG_INT1M:
-	case S2MPU02_REG_INT2M:
-	case S2MPU02_REG_INT3M:
-		return false;
-	default:
-		return true;
-	}
-}
-
-static const struct regmap_config sec_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
-static const struct regmap_config s2mpa01_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPA01_REG_LDO_OVCB4,
-	.volatile_reg = s2mpa01_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s2mps11_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPS11_REG_L38CTRL,
-	.volatile_reg = s2mps11_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s2mps13_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPS13_REG_LDODSCH5,
-	.volatile_reg = s2mps11_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s2mps14_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPS14_REG_LDODSCH3,
-	.volatile_reg = s2mps11_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s2mps15_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPS15_REG_LDODSCH4,
-	.volatile_reg = s2mps11_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s2mpu02_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S2MPU02_REG_DVSDATA,
-	.volatile_reg = s2mpu02_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
-static const struct regmap_config s5m8767_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = S5M8767_REG_LDO28CTRL,
-	.volatile_reg = s2mps11_volatile,
-	.cache_type = REGCACHE_FLAT,
-};
-
 static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
 {
 	unsigned int val;
@@ -258,87 +117,40 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
 	}
 }
 
-/*
- * Only the common platform data elements for s5m8767 are parsed here from the
- * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
- * others have to parse their own platform data elements from device tree.
- */
-static void sec_pmic_i2c_parse_dt_pdata(struct device *dev,
-					struct sec_platform_data *pd)
+int sec_pmic_probe(struct device *dev, unsigned long device_type,
+		   unsigned int irq, struct regmap *regmap,
+		   const struct sec_pmic_probe_data *probedata,
+		   struct i2c_client *client)
 {
-	pd->manual_poweroff =
-		of_property_read_bool(dev->of_node,
-				      "samsung,s2mps11-acokb-ground");
-	pd->disable_wrstbi =
-		of_property_read_bool(dev->of_node,
-				      "samsung,s2mps11-wrstbi-ground");
-}
-
-static int sec_pmic_probe(struct i2c_client *i2c)
-{
-	const struct regmap_config *regmap;
 	struct sec_platform_data *pdata;
 	const struct mfd_cell *sec_devs;
 	struct sec_pmic_dev *sec_pmic;
 	int ret, num_sec_devs;
 
-	sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
-				GFP_KERNEL);
+	sec_pmic = devm_kzalloc(dev, sizeof(struct sec_pmic_dev), GFP_KERNEL);
 	if (sec_pmic == NULL)
 		return -ENOMEM;
 
-	i2c_set_clientdata(i2c, sec_pmic);
-	sec_pmic->dev = &i2c->dev;
-	sec_pmic->i2c = i2c;
-	sec_pmic->irq = i2c->irq;
+	dev_set_drvdata(dev, sec_pmic);
+	sec_pmic->dev = dev;
+	sec_pmic->device_type = device_type;
+	sec_pmic->irq = irq;
+	sec_pmic->regmap_pmic = regmap;
+	sec_pmic->i2c = client;
 
 	/*
 	 * The s5m8767 platform data structure is instantiated here and the
 	 * drivers for the sub-modules need not instantiate another instance
 	 * while parsing their platform data.
 	 */
-	pdata = devm_kzalloc(sec_pmic->dev, sizeof(*pdata), GFP_KERNEL);
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev, pdata);
-
-	sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev);
 	sec_pmic->pdata = pdata;
-
-	switch (sec_pmic->device_type) {
-	case S2MPA01:
-		regmap = &s2mpa01_regmap_config;
-		break;
-	case S2MPS11X:
-		regmap = &s2mps11_regmap_config;
-		break;
-	case S2MPS13X:
-		regmap = &s2mps13_regmap_config;
-		break;
-	case S2MPS14X:
-		regmap = &s2mps14_regmap_config;
-		break;
-	case S2MPS15X:
-		regmap = &s2mps15_regmap_config;
-		break;
-	case S5M8767X:
-		regmap = &s5m8767_regmap_config;
-		break;
-	case S2MPU02:
-		regmap = &s2mpu02_regmap_config;
-		break;
-	default:
-		regmap = &sec_regmap_config;
-		break;
-	}
-
-	sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);
-	if (IS_ERR(sec_pmic->regmap_pmic)) {
-		ret = PTR_ERR(sec_pmic->regmap_pmic);
-		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-			ret);
-		return ret;
+	if (probedata) {
+		pdata->manual_poweroff = probedata->manual_poweroff;
+		pdata->disable_wrstbi = probedata->disable_wrstbi;
 	}
 
 	sec_irq_init(sec_pmic);
@@ -383,9 +195,9 @@ static int sec_pmic_probe(struct i2c_client *i2c)
 		num_sec_devs = ARRAY_SIZE(s2mpu05_devs);
 		break;
 	default:
-		dev_err(&i2c->dev, "Unsupported device type (%lu)\n",
+		dev_err(sec_pmic->dev, "Unsupported device type %lu\n",
 			sec_pmic->device_type);
-		return -ENODEV;
+		return -EINVAL;
 	}
 	ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
 				   NULL, 0, NULL);
@@ -397,10 +209,11 @@ static int sec_pmic_probe(struct i2c_client *i2c)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(sec_pmic_probe);
 
-static void sec_pmic_shutdown(struct i2c_client *i2c)
+void sec_pmic_shutdown(struct device *dev)
 {
-	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+	struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
 	unsigned int reg, mask;
 
 	if (!sec_pmic->pdata->manual_poweroff)
@@ -424,11 +237,11 @@ static void sec_pmic_shutdown(struct i2c_client *i2c)
 
 	regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
 }
+EXPORT_SYMBOL_GPL(sec_pmic_shutdown);
 
 static int sec_pmic_suspend(struct device *dev)
 {
-	struct i2c_client *i2c = to_i2c_client(dev);
-	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+	struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
 
 	if (device_may_wakeup(dev))
 		enable_irq_wake(sec_pmic->irq);
@@ -448,8 +261,7 @@ static int sec_pmic_suspend(struct device *dev)
 
 static int sec_pmic_resume(struct device *dev)
 {
-	struct i2c_client *i2c = to_i2c_client(dev);
-	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+	struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
 
 	if (device_may_wakeup(dev))
 		disable_irq_wake(sec_pmic->irq);
@@ -458,20 +270,10 @@ static int sec_pmic_resume(struct device *dev)
 	return 0;
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops,
-				sec_pmic_suspend, sec_pmic_resume);
-
-static struct i2c_driver sec_pmic_driver = {
-	.driver = {
-		   .name = "sec_pmic",
-		   .pm = pm_sleep_ptr(&sec_pmic_pm_ops),
-		   .of_match_table = sec_dt_match,
-	},
-	.probe = sec_pmic_probe,
-	.shutdown = sec_pmic_shutdown,
-};
-module_i2c_driver(sec_pmic_driver);
+DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
+EXPORT_SYMBOL_GPL(sec_pmic_pm_ops);
 
+MODULE_AUTHOR("Andr? Draszik <andre.draszik at linaro.org>");
 MODULE_AUTHOR("Sangbeom Kim <sbkim73 at samsung.com>");
-MODULE_DESCRIPTION("Core support for the S5M MFD");
+MODULE_DESCRIPTION("Core driver for the Samsung S5M");
 MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/sec-core.h b/drivers/mfd/sec-core.h
index b3fded5f02a0ddc09a9508fd49a5d335f7ad0ee7..58e5b645f377cea5543a215c05957a2c49239a6f 100644
--- a/drivers/mfd/sec-core.h
+++ b/drivers/mfd/sec-core.h
@@ -10,6 +10,23 @@
 #ifndef __SEC_CORE_INT_H
 #define __SEC_CORE_INT_H
 
+struct i2c_client;
+
+extern const struct dev_pm_ops sec_pmic_pm_ops;
+
+struct sec_pmic_probe_data {
+	/* Whether or not manually set PWRHOLD to low during shutdown. */
+	bool manual_poweroff;
+	/* Disable the WRSTBI (buck voltage warm reset) when probing? */
+	bool disable_wrstbi;
+};
+
+int sec_pmic_probe(struct device *dev, unsigned long device_type,
+		   unsigned int irq, struct regmap *regmap,
+		   const struct sec_pmic_probe_data *probedata,
+		   struct i2c_client *client);
+void sec_pmic_shutdown(struct device *dev);
+
 int sec_irq_init(struct sec_pmic_dev *sec_pmic);
 
 #endif /* __SEC_CORE_INT_H */
diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..803a46e657a5a1a639014d442941c0cdc60556a5
--- /dev/null
+++ b/drivers/mfd/sec-i2c.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *                http://www.samsung.com
+ * Copyright 2025 Linaro Ltd.
+ *
+ * Samsung SxM I2C driver
+ */
+
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mpa01.h>
+#include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
+#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mps15.h>
+#include <linux/mfd/samsung/s2mpu02.h>
+#include <linux/mfd/samsung/s5m8767.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include "sec-core.h"
+
+static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPA01_REG_INT1M:
+	case S2MPA01_REG_INT2M:
+	case S2MPA01_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static bool s2mps11_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPS11_REG_INT1M:
+	case S2MPS11_REG_INT2M:
+	case S2MPS11_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPU02_REG_INT1M:
+	case S2MPU02_REG_INT2M:
+	case S2MPU02_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static const struct regmap_config sec_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static const struct regmap_config s2mpa01_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPA01_REG_LDO_OVCB4,
+	.volatile_reg = s2mpa01_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s2mps11_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPS11_REG_L38CTRL,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s2mps13_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPS13_REG_LDODSCH5,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s2mps14_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPS14_REG_LDODSCH3,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s2mps15_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPS15_REG_LDODSCH4,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s2mpu02_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPU02_REG_DVSDATA,
+	.volatile_reg = s2mpu02_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_config s5m8767_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S5M8767_REG_LDO28CTRL,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+/*
+ * Only the common platform data elements for s5m8767 are parsed here from the
+ * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
+ * others have to parse their own platform data elements from device tree.
+ */
+static void
+sec_pmic_i2c_parse_dt_pdata(struct device *dev,
+			    struct sec_pmic_probe_data *pd)
+{
+	pd->manual_poweroff =
+		of_property_read_bool(dev->of_node,
+				      "samsung,s2mps11-acokb-ground");
+	pd->disable_wrstbi =
+		of_property_read_bool(dev->of_node,
+				      "samsung,s2mps11-wrstbi-ground");
+}
+
+static int sec_pmic_i2c_probe(struct i2c_client *client)
+{
+	struct sec_pmic_probe_data probedata;
+	const struct regmap_config *regmap;
+	unsigned long device_type;
+	struct regmap *regmap_pmic;
+	int ret;
+
+	sec_pmic_i2c_parse_dt_pdata(&client->dev, &probedata);
+
+	device_type = (unsigned long)of_device_get_match_data(&client->dev);
+
+	switch (device_type) {
+	case S2MPA01:
+		regmap = &s2mpa01_regmap_config;
+		break;
+	case S2MPS11X:
+		regmap = &s2mps11_regmap_config;
+		break;
+	case S2MPS13X:
+		regmap = &s2mps13_regmap_config;
+		break;
+	case S2MPS14X:
+		regmap = &s2mps14_regmap_config;
+		break;
+	case S2MPS15X:
+		regmap = &s2mps15_regmap_config;
+		break;
+	case S5M8767X:
+		regmap = &s5m8767_regmap_config;
+		break;
+	case S2MPU02:
+		regmap = &s2mpu02_regmap_config;
+		break;
+	default:
+		regmap = &sec_regmap_config;
+		break;
+	}
+
+	regmap_pmic = devm_regmap_init_i2c(client, regmap);
+	if (IS_ERR(regmap_pmic)) {
+		ret = PTR_ERR(regmap_pmic);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	return sec_pmic_probe(&client->dev, device_type, client->irq,
+			      regmap_pmic, &probedata, client);
+}
+
+static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
+{
+	sec_pmic_shutdown(&i2c->dev);
+}
+
+static const struct of_device_id sec_pmic_i2c_of_match[] = {
+	{
+		.compatible = "samsung,s5m8767-pmic",
+		.data = (void *)S5M8767X,
+	}, {
+		.compatible = "samsung,s2dos05",
+		.data = (void *)S2DOS05,
+	}, {
+		.compatible = "samsung,s2mps11-pmic",
+		.data = (void *)S2MPS11X,
+	}, {
+		.compatible = "samsung,s2mps13-pmic",
+		.data = (void *)S2MPS13X,
+	}, {
+		.compatible = "samsung,s2mps14-pmic",
+		.data = (void *)S2MPS14X,
+	}, {
+		.compatible = "samsung,s2mps15-pmic",
+		.data = (void *)S2MPS15X,
+	}, {
+		.compatible = "samsung,s2mpa01-pmic",
+		.data = (void *)S2MPA01,
+	}, {
+		.compatible = "samsung,s2mpu02-pmic",
+		.data = (void *)S2MPU02,
+	}, {
+		.compatible = "samsung,s2mpu05-pmic",
+		.data = (void *)S2MPU05,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
+
+static struct i2c_driver sec_pmic_i2c_driver = {
+	.driver = {
+		.name = "sec-pmic-i2c",
+		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
+		.of_match_table = sec_pmic_i2c_of_match,
+	},
+	.probe = sec_pmic_i2c_probe,
+	.shutdown = sec_pmic_i2c_shutdown,
+};
+module_i2c_driver(sec_pmic_i2c_driver);
+
+MODULE_AUTHOR("Andr? Draszik <andre.draszik at linaro.org>");
+MODULE_AUTHOR("Sangbeom Kim <sbkim73 at samsung.com>");
+MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
+MODULE_LICENSE("GPL");

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:27 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:27 +0000
Subject: [PATCH 11/34] defconfigs: rename CONFIG_MFD_SEC_CORE to
 CONFIG_MFD_SEC_I2C
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-11-d08943702707@linaro.org>

We are adding support for Samsung PMICs that aren't using I2C and
therefore had to rename the Kconfig symbol.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 arch/arm/configs/exynos_defconfig   | 2 +-
 arch/arm/configs/multi_v7_defconfig | 2 +-
 arch/arm/configs/pxa_defconfig      | 2 +-
 arch/arm64/configs/defconfig        | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 7ad48fdda1dac69a4a9612eabb573729bed7b3a6..251f45be6c14af59263373f21b27b15f42ec7f61 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -167,7 +167,7 @@ CONFIG_MFD_MAX77686=y
 CONFIG_MFD_MAX77693=y
 CONFIG_MFD_MAX8997=y
 CONFIG_MFD_MAX8998=y
-CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_SEC_I2C=y
 CONFIG_MFD_STMPE=y
 CONFIG_STMPE_I2C=y
 CONFIG_MFD_TPS65090=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index ad037c175fdb0ec8601c9b3607aca0c0e5f3c145..7d06ac5369b1a2f325462f2cf5b54fe22061ca77 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -612,7 +612,7 @@ CONFIG_MFD_QCOM_RPM=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_RK8XX_I2C=y
 CONFIG_MFD_RN5T618=y
-CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_SEC_I2C=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index de0ac8f521d7612704ce327e9ac16ab9e999f3d3..064e79baf20da809c9ab1f1fa18282aaba11a41f 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -335,7 +335,7 @@ CONFIG_MFD_MAX77693=y
 CONFIG_MFD_MAX8907=m
 CONFIG_EZX_PCAP=y
 CONFIG_UCB1400_CORE=m
-CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_SEC_I2C=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
 CONFIG_MFD_TPS6586X=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index e8dfbe22db68d9aa24df5af0786a2eeb8f33bf3c..cc4dc330cfe82d11ca0c4c9ba8cac4b14decdeab 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -769,7 +769,7 @@ CONFIG_MFD_MT6397=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_RK8XX_I2C=y
 CONFIG_MFD_RK8XX_SPI=y
-CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_SEC_I2C=y
 CONFIG_MFD_SL28CPLD=y
 CONFIG_RZ_MTU3=y
 CONFIG_MFD_TI_AM335X_TSCADC=m

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:29 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:29 +0000
Subject: [PATCH 13/34] mfd: sec: merge separate core and irq modules
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-13-d08943702707@linaro.org>

There is no reason to have these two kernel modules separate. Having
them merged into one kernel module also slightly reduces memory
consumption and module load times a little.

mapped size (lsmod):
         before:             after:
    sec_core   20480    sec_core   24576
    sec_irq    16384
    ----------------
    total      36864

Section sizes (size -A):
         before:             after:
    sec_core    6780    sec_core   13239
    sec_irq     8046
    ----------------
    Total      14826

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
Checkpatch suggests to update MAINTAINERS, but the new file is covered
already due to using a wildcard.
---
 drivers/mfd/Makefile                     | 3 ++-
 drivers/mfd/{sec-core.c => sec-common.c} | 2 ++
 drivers/mfd/sec-irq.c                    | 8 --------
 3 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8a8c678134a9721c7f78e432ddd0df33b2b0de69..67fac46c8eeb9c7b4429e8a496a1d7d40d2b7b31 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -232,7 +232,8 @@ obj-$(CONFIG_MFD_RK8XX)		+= rk8xx-core.o
 obj-$(CONFIG_MFD_RK8XX_I2C)	+= rk8xx-i2c.o
 obj-$(CONFIG_MFD_RK8XX_SPI)	+= rk8xx-spi.o
 obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
-obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
+sec-core-objs			:= sec-common.o sec-irq.o
+obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o
 obj-$(CONFIG_MFD_SEC_ACPM)	+= sec-acpm.o
 obj-$(CONFIG_MFD_SEC_I2C)	+= sec-i2c.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-common.c
similarity index 98%
rename from drivers/mfd/sec-core.c
rename to drivers/mfd/sec-common.c
index 27f5036ffa1009304147755c91d00be333dd206a..fcf7668efd3215ad70d81916ede249ed5f9d45ae 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-common.c
@@ -290,6 +290,8 @@ DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
 EXPORT_SYMBOL_GPL(sec_pmic_pm_ops);
 
 MODULE_AUTHOR("Andr? Draszik <andre.draszik at linaro.org>");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi at samsung.com>");
+MODULE_AUTHOR("Krzysztof Kozlowski <krzk at kernel.org>");
 MODULE_AUTHOR("Sangbeom Kim <sbkim73 at samsung.com>");
 MODULE_DESCRIPTION("Core driver for the Samsung S5M");
 MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index bf86281401ac6ff05c90c2d71c84744709ed79cb..4afac3aa0a582994bf04c41768c1c788c54ee2e9 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -6,7 +6,6 @@
 #include <linux/array_size.h>
 #include <linux/build_bug.h>
 #include <linux/dev_printk.h>
-#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/mfd/samsung/core.h>
@@ -510,10 +509,3 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(sec_irq_init);
-
-MODULE_AUTHOR("Sangbeom Kim <sbkim73 at samsung.com>");
-MODULE_AUTHOR("Chanwoo Choi <cw00.choi at samsung.com>");
-MODULE_AUTHOR("Krzysztof Kozlowski <krzk at kernel.org>");
-MODULE_DESCRIPTION("Interrupt support for the S5M MFD");
-MODULE_LICENSE("GPL");

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:28 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:28 +0000
Subject: [PATCH 12/34] mfd: sec: add support for S2MPG10 PMIC
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-12-d08943702707@linaro.org>

Add support for Samsung's S2MPG10 PMIC, which is a Power Management IC
for mobile applications with buck converters, various LDOs, power
meters, RTC, clock outputs, and additional GPIOs interfaces.

Contrary to existing Samsung S2M series PMICs supported, communication
is not via I2C, but via the Samsung ACPM firmware.

This commit adds the core driver.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
Checkpatch suggests to update MAINTAINERS, but the new file is covered
already due to using a wildcard.
---
 drivers/mfd/Kconfig                 |  17 ++
 drivers/mfd/Makefile                |   1 +
 drivers/mfd/sec-acpm.c              | 471 ++++++++++++++++++++++++++++++++++++
 drivers/mfd/sec-core.c              |  16 ++
 drivers/mfd/sec-irq.c               |  68 ++++++
 include/linux/mfd/samsung/core.h    |   1 +
 include/linux/mfd/samsung/irq.h     | 103 ++++++++
 include/linux/mfd/samsung/s2mpg10.h | 310 ++++++++++++++++++++++++
 8 files changed, 987 insertions(+)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 9cce9a632827a38d6e4396167aa3b0391f273e97..a154be6e2d44e41608e0a297e0915a84ebbb66cc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1320,6 +1320,23 @@ config MFD_SEC_CORE
 	select MFD_CORE
 	select REGMAP_IRQ
 
+config MFD_SEC_ACPM
+	tristate "Samsung Electronics S2MPG1x PMICs"
+	depends on EXYNOS_ACPM_PROTOCOL
+	depends on OF
+	select MFD_SEC_CORE
+	help
+	  Support for the Samsung Electronics PMICs with ACPM interface.
+	  This is a Power Management IC for mobile applications with buck
+	  converters, various LDOs, power meters, RTC, clock outputs, and
+	  additional GPIOs interfaces.
+	  This driver provides common support for accessing the device;
+	  additional drivers must be enabled in order to use the functionality
+	  of the device.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called sec-acpm.
+
 config MFD_SEC_I2C
 	tristate "Samsung Electronics S2MPA/S2MPS1X/S2MPU/S5M series PMICs"
 	depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ca9efff5780a7c818ca6cfe017c0f897ca70b449..8a8c678134a9721c7f78e432ddd0df33b2b0de69 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -233,6 +233,7 @@ obj-$(CONFIG_MFD_RK8XX_I2C)	+= rk8xx-i2c.o
 obj-$(CONFIG_MFD_RK8XX_SPI)	+= rk8xx-spi.o
 obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_SEC_ACPM)	+= sec-acpm.o
 obj-$(CONFIG_MFD_SEC_I2C)	+= sec-i2c.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d5b3f412cc22dcf3bc1680a54dcf263a65882c2
--- /dev/null
+++ b/drivers/mfd/sec-acpm.c
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright 2020 Google Inc
+// Copyright 2025 Linaro Ltd.
+//
+// Samsung S2MPG1x ACPM driver
+
+#include <linux/array_size.h>
+#include <linux/device.h>
+#include <linux/firmware/samsung/exynos-acpm-protocol.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mpg10.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include "sec-core.h"
+
+#define ACPM_MAX_BULK_DATA   8
+
+struct sec_pmic_acpm_platform_data {
+	int device_type;
+
+	unsigned int acpm_chan_id;
+	u8 speedy_channel;
+
+	const struct regmap_config *regmap_cfg_common;
+	const struct regmap_config *regmap_cfg_pmic;
+	const struct regmap_config *regmap_cfg_rtc;
+	const struct regmap_config *regmap_cfg_meter;
+};
+
+static const struct regmap_range s2mpg10_common_registers[] = {
+	regmap_reg_range(0x00, 0x02),
+	regmap_reg_range(0x0a, 0x0c),
+	regmap_reg_range(0x1a, 0x2a),
+	regmap_reg_range(0x33, 0x3f),
+	regmap_reg_range(0x57, 0x7f),
+};
+
+static const struct regmap_range s2mpg10_common_ro_registers[] = {
+	regmap_reg_range(0x00, 0x01),
+	regmap_reg_range(0x28, 0x2a),
+	regmap_reg_range(0x33, 0x3f),
+	regmap_reg_range(0x57, 0x7f),
+};
+
+static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = {
+	regmap_reg_range(0x00, 0x00), /* CHIP_ID_M */
+	regmap_reg_range(0x02, 0x02), /* INT_MASK */
+	regmap_reg_range(0x0a, 0x0c), /* speedy control */
+};
+
+static const struct regmap_range s2mpg10_common_precious_registers[] = {
+	regmap_reg_range(0x01, 0x01), /* INT */
+};
+
+static const struct regmap_access_table s2mpg10_common_wr_table = {
+	.yes_ranges = s2mpg10_common_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
+	.no_ranges = s2mpg10_common_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg10_common_rd_table = {
+	.yes_ranges = s2mpg10_common_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
+};
+
+static const struct regmap_access_table s2mpg10_common_volatile_table = {
+	.no_ranges = s2mpg10_common_nonvolatile_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_nonvolatile_registers),
+};
+
+static const struct regmap_access_table s2mpg10_common_precious_table = {
+	.yes_ranges = s2mpg10_common_precious_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_precious_registers),
+};
+
+static const struct regmap_config s2mpg10_regmap_config_common = {
+	.name = "common",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0x7f,
+	.wr_table = &s2mpg10_common_wr_table,
+	.rd_table = &s2mpg10_common_rd_table,
+	.volatile_table = &s2mpg10_common_volatile_table,
+	.precious_table = &s2mpg10_common_precious_table,
+	.num_reg_defaults_raw = 0x7f + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_range s2mpg10_pmic_registers[] = {
+	regmap_reg_range(0x00, 0xf6),
+};
+
+static const struct regmap_range s2mpg10_pmic_ro_registers[] = {
+	regmap_reg_range(0x00, 0x05), /* INTx */
+	regmap_reg_range(0x0c, 0x0f), /* STATUSx PWRONSRC OFFSRC */
+	regmap_reg_range(0xc7, 0xc7), /* GPIO input */
+};
+
+static const struct regmap_range s2mpg10_pmic_nonvolatile_registers[] = {
+	regmap_reg_range(0x06, 0x0b), /* INTxM */
+};
+
+static const struct regmap_range s2mpg10_pmic_precious_registers[] = {
+	regmap_reg_range(0x00, 0x05), /* INTx */
+};
+
+static const struct regmap_access_table s2mpg10_pmic_wr_table = {
+	.yes_ranges = s2mpg10_pmic_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
+	.no_ranges = s2mpg10_pmic_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg10_pmic_rd_table = {
+	.yes_ranges = s2mpg10_pmic_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
+};
+
+static const struct regmap_access_table s2mpg10_pmic_volatile_table = {
+	.no_ranges = s2mpg10_pmic_nonvolatile_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_nonvolatile_registers),
+};
+
+static const struct regmap_access_table s2mpg10_pmic_precious_table = {
+	.yes_ranges = s2mpg10_pmic_precious_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_precious_registers),
+};
+
+static const struct regmap_config s2mpg10_regmap_config_pmic = {
+	.name = "pmic",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xf6,
+	.wr_table = &s2mpg10_pmic_wr_table,
+	.rd_table = &s2mpg10_pmic_rd_table,
+	.volatile_table = &s2mpg10_pmic_volatile_table,
+	.precious_table = &s2mpg10_pmic_precious_table,
+	.num_reg_defaults_raw = 0xf6 + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_range s2mpg10_rtc_registers[] = {
+	regmap_reg_range(0x00, 0x2b),
+};
+
+static const struct regmap_range s2mpg10_volatile_registers[] = {
+	regmap_reg_range(0x01, 0x01), /* RTC_UPDATE */
+	regmap_reg_range(0x05, 0x0c), /* time / date */
+};
+
+static const struct regmap_access_table s2mpg10_rtc_wr_table = {
+	.yes_ranges = s2mpg10_rtc_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers),
+	/* no r/o registers in RTC block  */
+};
+
+static const struct regmap_access_table s2mpg10_rtc_rd_table = {
+	.yes_ranges = s2mpg10_rtc_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers),
+};
+
+static const struct regmap_access_table s2mpg10_rtc_volatile_table = {
+	.yes_ranges = s2mpg10_volatile_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_volatile_registers),
+};
+
+static const struct regmap_config s2mpg10_regmap_config_rtc = {
+	.name = "rtc",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.max_register = 0x2b,
+	.wr_table = &s2mpg10_rtc_wr_table,
+	.rd_table = &s2mpg10_rtc_rd_table,
+	.volatile_table = &s2mpg10_rtc_volatile_table,
+	.num_reg_defaults_raw = 0x2b + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_range s2mpg10_meter_registers[] = {
+	regmap_reg_range(0x00, 0x21), /* meter config */
+	regmap_reg_range(0x40, 0x8a), /* meter data */
+	regmap_reg_range(0xee, 0xee),
+	regmap_reg_range(0xf1, 0xf1),
+};
+
+static const struct regmap_range s2mpg10_meter_ro_registers[] = {
+	regmap_reg_range(0x40, 0x8a),
+};
+
+static const struct regmap_access_table s2mpg10_meter_wr_table = {
+	.yes_ranges = s2mpg10_meter_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
+	.no_ranges = s2mpg10_meter_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg10_meter_rd_table = {
+	.yes_ranges = s2mpg10_meter_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
+};
+
+static const struct regmap_access_table s2mpg10_meter_volatile_table = {
+	.yes_ranges = s2mpg10_meter_ro_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
+};
+
+static const struct regmap_config s2mpg10_regmap_config_meter = {
+	.name = "meter",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.max_register = 0xf1,
+	.wr_table = &s2mpg10_meter_wr_table,
+	.rd_table = &s2mpg10_meter_rd_table,
+	.volatile_table = &s2mpg10_meter_volatile_table,
+	.num_reg_defaults_raw = 0xf1 + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+struct sec_acpm_shared_bus_context {
+	const struct acpm_handle *acpm;
+	unsigned int acpm_chan_id;
+	u8 speedy_channel;
+};
+
+struct sec_acpm_bus_context {
+	struct sec_acpm_shared_bus_context *shared;
+	u8 type;
+#define SEC_ACPM_TYPE_COMMON  0x00
+#define SEC_ACPM_TYPE_PMIC    0x01
+#define SEC_ACPM_TYPE_RTC     0x02
+#define SEC_ACPM_TYPE_METER   0x0a
+#define SEC_ACPM_TYPE_WLWP    0x0b
+#define SEC_ACPM_TYPE_TRIM    0x0f
+};
+
+static int sec_acpm_bus_write(void *context, const void *data, size_t count)
+{
+	struct sec_acpm_bus_context *ctx = context;
+	const struct acpm_handle *acpm = ctx->shared->acpm;
+	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
+	u8 reg;
+
+	if (count < 2 || count > (ACPM_MAX_BULK_DATA + 1))
+		return -EINVAL;
+
+	reg = *(u8 *)data;
+	++data;
+	--count;
+
+	return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id,
+				    ctx->type, reg,
+				    ctx->shared->speedy_channel, count, data);
+}
+
+static int sec_acpm_bus_read(void *context, const void *reg_buf,
+			     size_t reg_size, void *val_buf,
+			     size_t val_size)
+{
+	struct sec_acpm_bus_context *ctx = context;
+	const struct acpm_handle *acpm = ctx->shared->acpm;
+	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
+	u8 reg;
+
+	if (reg_size != 1 || !val_size || val_size > ACPM_MAX_BULK_DATA)
+		return -EINVAL;
+
+	reg = *(u8 *)reg_buf;
+
+	return pmic_ops->bulk_read(acpm, ctx->shared->acpm_chan_id,
+				   ctx->type, reg,
+				   ctx->shared->speedy_channel,
+				   val_size, val_buf);
+}
+
+static int sec_acpm_bus_reg_update_bits(void *context, unsigned int reg,
+					unsigned int mask, unsigned int val)
+{
+	struct sec_acpm_bus_context *ctx = context;
+	const struct acpm_handle *acpm = ctx->shared->acpm;
+	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
+
+	return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id,
+				    ctx->type, reg & 0xff,
+				    ctx->shared->speedy_channel,
+				    val, mask);
+}
+
+static const struct regmap_bus sec_pmic_acpm_regmap_bus = {
+	.write = sec_acpm_bus_write,
+	.read = sec_acpm_bus_read,
+	.reg_update_bits = sec_acpm_bus_reg_update_bits,
+	.max_raw_read = ACPM_MAX_BULK_DATA,
+	.max_raw_write = ACPM_MAX_BULK_DATA,
+};
+
+static struct regmap *
+sec_pmic_acpm_regmap_init(struct device *dev,
+			  struct sec_acpm_shared_bus_context *shared_ctx,
+			  u8 type, const struct regmap_config *cfg,
+			  bool do_attach)
+{
+	struct sec_acpm_bus_context *ctx;
+	struct regmap *regmap;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ctx->shared = shared_ctx;
+	ctx->type = type;
+
+	regmap = devm_regmap_init(dev, &sec_pmic_acpm_regmap_bus, ctx, cfg);
+	if (IS_ERR(regmap))
+		return ERR_PTR(dev_err_probe(dev, PTR_ERR(regmap),
+					     "regmap init (%s) failed\n",
+					     cfg->name));
+
+	if (do_attach) {
+		int ret;
+
+		ret = regmap_attach_dev(dev, regmap, cfg);
+		if (ret)
+			return ERR_PTR(dev_err_probe(dev, ret,
+						     "regmap attach (%s) failed\n",
+						     cfg->name));
+	}
+
+	return regmap;
+}
+
+static void sec_acpm_mask_common_irqs(void *regmap_common)
+{
+	/* Mask all interrupts from 'common' block on shutdown */
+	regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK,
+		     S2MPG10_COMMON_INT_SRC_MASK);
+}
+
+static int sec_pmic_acpm_probe(struct platform_device *pdev)
+{
+	const struct sec_pmic_acpm_platform_data *data;
+	struct sec_acpm_shared_bus_context *shared_ctx;
+	const struct acpm_handle *acpm;
+	struct regmap *regmap_common, *regmap_pmic, *regmap;
+	struct device *dev;
+	int ret, irq;
+
+	dev = &pdev->dev;
+
+	data = device_get_match_data(dev);
+	if (!data)
+		return dev_err_probe(dev, -ENODEV,
+				     "Unsupported device type\n");
+
+	acpm = devm_acpm_get_by_phandle(dev, "exynos,acpm-ipc");
+	if (IS_ERR(acpm))
+		return dev_err_probe(dev, PTR_ERR(acpm),
+				     "Failed to get acpm\n");
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	shared_ctx = devm_kzalloc(dev, sizeof(*shared_ctx), GFP_KERNEL);
+	if (!shared_ctx)
+		return -ENOMEM;
+
+	shared_ctx->acpm = acpm;
+	shared_ctx->acpm_chan_id = data->acpm_chan_id;
+	shared_ctx->speedy_channel = data->speedy_channel;
+
+	regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx,
+						  SEC_ACPM_TYPE_COMMON,
+						  data->regmap_cfg_common,
+						  false);
+	if (IS_ERR(regmap_common))
+		return PTR_ERR(regmap_common);
+
+	/* Mask all interrupts from 'common' block, until successful init */
+	ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK,
+			   S2MPG10_COMMON_INT_SRC_MASK);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to mask common block interrupts\n");
+
+	regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx,
+						SEC_ACPM_TYPE_PMIC,
+						data->regmap_cfg_pmic,
+						false);
+	if (IS_ERR(regmap_pmic))
+		return PTR_ERR(regmap_pmic);
+
+	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_ACPM_TYPE_RTC,
+					   data->regmap_cfg_rtc, true);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_ACPM_TYPE_METER,
+					   data->regmap_cfg_meter, true);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ret = sec_pmic_probe(dev, data->device_type, irq, regmap_pmic,
+			     NULL, NULL);
+	if (ret)
+		return ret;
+
+	if (device_property_read_bool(dev, "wakeup-source"))
+		devm_device_init_wakeup(dev);
+
+	/*
+	 * Unmask PMIC interrupt from 'common' block, now that everything is in
+	 * place.
+	 */
+	ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
+				S2MPG10_COMMON_INT_SRC_PMIC);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to unmask PMIC interrupt\n");
+
+	ret = devm_add_action_or_reset(dev, sec_acpm_mask_common_irqs,
+				       regmap_common);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void sec_pmic_acpm_shutdown(struct platform_device *pdev)
+{
+	sec_pmic_shutdown(&pdev->dev);
+}
+
+static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
+	.device_type = S2MPG10,
+	.acpm_chan_id = 2,
+	.speedy_channel = 0,
+	.regmap_cfg_common = &s2mpg10_regmap_config_common,
+	.regmap_cfg_pmic = &s2mpg10_regmap_config_pmic,
+	.regmap_cfg_rtc = &s2mpg10_regmap_config_rtc,
+	.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
+};
+
+static const struct of_device_id sec_pmic_acpm_of_match[] = {
+	{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
+
+static struct platform_driver sec_pmic_acpm_driver = {
+	.driver = {
+		.name = "sec-pmic-acpm",
+		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
+		.of_match_table = sec_pmic_acpm_of_match,
+	},
+	.probe = sec_pmic_acpm_probe,
+	.shutdown = sec_pmic_acpm_shutdown,
+};
+module_platform_driver(sec_pmic_acpm_driver);
+
+MODULE_AUTHOR("Andr? Draszik <andre.draszik at linaro.org>");
+MODULE_DESCRIPTION("ACPM driver for the Samsung S2MPG1x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index e81da34cf6795beca5f660fb46eefa4b5f8957d1..27f5036ffa1009304147755c91d00be333dd206a 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -35,6 +35,14 @@ static const struct mfd_cell s2dos05_devs[] = {
 	{ .name = "s2dos05-regulator", },
 };
 
+static const struct mfd_cell s2mpg10_devs[] = {
+	MFD_CELL_NAME("s2mpg10-meter"),
+	MFD_CELL_NAME("s2mpg10-regulator"),
+	MFD_CELL_NAME("s2mpg10-rtc"),
+	MFD_CELL_OF("s2mpg10-clk", NULL, NULL, 0, 0, "samsung,s2mpg10-clk"),
+	MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),
+};
+
 static const struct mfd_cell s2mps11_devs[] = {
 	{ .name = "s2mps11-regulator", },
 	{ .name = "s2mps14-rtc", },
@@ -89,6 +97,10 @@ static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
 {
 	unsigned int val;
 
+	/* For s2mpg1x, the revision is in a different regmap */
+	if (sec_pmic->device_type == S2MPG10)
+		return;
+
 	/* For each device type, the REG_ID is always the first register */
 	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
 		dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
@@ -170,6 +182,10 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type,
 		sec_devs = s2mpa01_devs;
 		num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
 		break;
+	case S2MPG10:
+		sec_devs = s2mpg10_devs;
+		num_sec_devs = ARRAY_SIZE(s2mpg10_devs);
+		break;
 	case S2MPS11X:
 		sec_devs = s2mps11_devs;
 		num_sec_devs = ARRAY_SIZE(s2mps11_devs);
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 4d49bb42bd0d109263f485c8b58e88cdd8d598d9..bf86281401ac6ff05c90c2d71c84744709ed79cb 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
+#include <linux/mfd/samsung/s2mpg10.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
@@ -20,6 +21,60 @@
 #include <linux/regmap.h>
 #include "sec-core.h"
 
+static const struct regmap_irq s2mpg10_irqs[] = {
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBR, 0, S2MPG10_IRQ_JIGONBR_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBF, 0, S2MPG10_IRQ_ACOKBF_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBR, 0, S2MPG10_IRQ_ACOKBR_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRON1S, 0, S2MPG10_IRQ_PWRON1S_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_MRB, 0, S2MPG10_IRQ_MRB_MASK),
+
+	REGMAP_IRQ_REG(S2MPG10_IRQ_RTC60S, 1, S2MPG10_IRQ_RTC60S_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA1, 1, S2MPG10_IRQ_RTCA1_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA0, 1, S2MPG10_IRQ_RTCA0_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_RTC1S, 1, S2MPG10_IRQ_RTC1S_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_COLDRST, 1, S2MPG10_IRQ_WTSR_COLDRST_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR, 1, S2MPG10_IRQ_WTSR_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_WRST, 1, S2MPG10_IRQ_WRST_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL, 1, S2MPG10_IRQ_SMPL_MASK),
+
+	REGMAP_IRQ_REG(S2MPG10_IRQ_120C, 2, S2MPG10_IRQ_INT120C_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_140C, 2, S2MPG10_IRQ_INT140C_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_TSD, 2, S2MPG10_IRQ_TSD_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT1, 2, S2MPG10_IRQ_PIF_TIMEOUT1_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT2, 2, S2MPG10_IRQ_PIF_TIMEOUT2_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_PARITY_ERR, 2, S2MPG10_IRQ_SPD_PARITY_ERR_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_ABNORMAL_STOP, 2, S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PMETER_OVERF, 2, S2MPG10_IRQ_PMETER_OVERF_MASK),
+
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B1M, 3, S2MPG10_IRQ_OCP_B1M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B2M, 3, S2MPG10_IRQ_OCP_B2M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B3M, 3, S2MPG10_IRQ_OCP_B3M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B4M, 3, S2MPG10_IRQ_OCP_B4M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B5M, 3, S2MPG10_IRQ_OCP_B5M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B6M, 3, S2MPG10_IRQ_OCP_B6M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B7M, 3, S2MPG10_IRQ_OCP_B7M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B8M, 3, S2MPG10_IRQ_OCP_B8M_MASK),
+
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B9M, 4, S2MPG10_IRQ_OCP_B9M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B10M, 4, S2MPG10_IRQ_OCP_B10M_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_WLWP_ACC, 4, S2MPG10_IRQ_WLWP_ACC_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL_TIMEOUT, 4, S2MPG10_IRQ_SMPL_TIMEOUT_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_TIMEOUT, 4, S2MPG10_IRQ_WTSR_TIMEOUT_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_SRP_PKT_RST, 4, S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK),
+
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH0, 5, S2MPG10_IRQ_PWR_WARN_CH0_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH1, 5, S2MPG10_IRQ_PWR_WARN_CH1_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH2, 5, S2MPG10_IRQ_PWR_WARN_CH2_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH3, 5, S2MPG10_IRQ_PWR_WARN_CH3_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH4, 5, S2MPG10_IRQ_PWR_WARN_CH4_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH5, 5, S2MPG10_IRQ_PWR_WARN_CH5_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH6, 5, S2MPG10_IRQ_PWR_WARN_CH6_MASK),
+	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH7, 5, S2MPG10_IRQ_PWR_WARN_CH7_MASK),
+};
+
 static const struct regmap_irq s2mps11_irqs[] = {
 	[S2MPS11_IRQ_PWRONF] = {
 		.reg_offset = 0,
@@ -320,6 +375,16 @@ static const struct regmap_irq s5m8767_irqs[] = {
 	},
 };
 
+static const struct regmap_irq_chip s2mpg10_irq_chip = {
+	.name = "s2mpg10",
+	.irqs = s2mpg10_irqs,
+	.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
+	.num_regs = 6,
+	.status_base = S2MPG10_PMIC_INT1,
+	.mask_base = S2MPG10_PMIC_INT1M,
+	/* all interrupt sources are read-to-clear */
+};
+
 static const struct regmap_irq_chip s2mps11_irq_chip = {
 	.name = "s2mps11",
 	.irqs = s2mps11_irqs,
@@ -402,6 +467,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 	case S2MPA01:
 		sec_irq_chip = &s2mps14_irq_chip;
 		break;
+	case S2MPG10:
+		sec_irq_chip = &s2mpg10_irq_chip;
+		break;
 	case S2MPS11X:
 		sec_irq_chip = &s2mps11_irq_chip;
 		break;
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 8a4e660854bbc955b812b4d61d4a52a0fc2f2899..c1102324172a9b6bd6072b5929a4866d6c9653fa 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -39,6 +39,7 @@ enum sec_device_type {
 	S5M8767X,
 	S2DOS05,
 	S2MPA01,
+	S2MPG10,
 	S2MPS11X,
 	S2MPS13X,
 	S2MPS14X,
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index 978f7af66f74842c4f8dd62c0f58a7a45aba7c34..b4805cbd949bd605004bd88cf361109d1cbbc3bf 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -57,6 +57,109 @@ enum s2mpa01_irq {
 #define S2MPA01_IRQ_B24_TSD_MASK	(1 << 4)
 #define S2MPA01_IRQ_B35_TSD_MASK	(1 << 5)
 
+enum s2mpg10_irq {
+	/* PMIC */
+	S2MPG10_IRQ_PWRONF,
+	S2MPG10_IRQ_PWRONR,
+	S2MPG10_IRQ_JIGONBF,
+	S2MPG10_IRQ_JIGONBR,
+	S2MPG10_IRQ_ACOKBF,
+	S2MPG10_IRQ_ACOKBR,
+	S2MPG10_IRQ_PWRON1S,
+	S2MPG10_IRQ_MRB,
+#define S2MPG10_IRQ_PWRONF_MASK		BIT(0)
+#define S2MPG10_IRQ_PWRONR_MASK		BIT(1)
+#define S2MPG10_IRQ_JIGONBF_MASK	BIT(2)
+#define S2MPG10_IRQ_JIGONBR_MASK	BIT(3)
+#define S2MPG10_IRQ_ACOKBF_MASK		BIT(4)
+#define S2MPG10_IRQ_ACOKBR_MASK		BIT(5)
+#define S2MPG10_IRQ_PWRON1S_MASK	BIT(6)
+#define S2MPG10_IRQ_MRB_MASK		BIT(7)
+
+	S2MPG10_IRQ_RTC60S,
+	S2MPG10_IRQ_RTCA1,
+	S2MPG10_IRQ_RTCA0,
+	S2MPG10_IRQ_RTC1S,
+	S2MPG10_IRQ_WTSR_COLDRST,
+	S2MPG10_IRQ_WTSR,
+	S2MPG10_IRQ_WRST,
+	S2MPG10_IRQ_SMPL,
+#define S2MPG10_IRQ_RTC60S_MASK		BIT(0)
+#define S2MPG10_IRQ_RTCA1_MASK		BIT(1)
+#define S2MPG10_IRQ_RTCA0_MASK		BIT(2)
+#define S2MPG10_IRQ_RTC1S_MASK		BIT(3)
+#define S2MPG10_IRQ_WTSR_COLDRST_MASK	BIT(4)
+#define S2MPG10_IRQ_WTSR_MASK		BIT(5)
+#define S2MPG10_IRQ_WRST_MASK		BIT(6)
+#define S2MPG10_IRQ_SMPL_MASK		BIT(7)
+
+	S2MPG10_IRQ_120C,
+	S2MPG10_IRQ_140C,
+	S2MPG10_IRQ_TSD,
+	S2MPG10_IRQ_PIF_TIMEOUT1,
+	S2MPG10_IRQ_PIF_TIMEOUT2,
+	S2MPG10_IRQ_SPD_PARITY_ERR,
+	S2MPG10_IRQ_SPD_ABNORMAL_STOP,
+	S2MPG10_IRQ_PMETER_OVERF,
+#define S2MPG10_IRQ_INT120C_MASK		BIT(0)
+#define S2MPG10_IRQ_INT140C_MASK		BIT(1)
+#define S2MPG10_IRQ_TSD_MASK			BIT(2)
+#define S2MPG10_IRQ_PIF_TIMEOUT1_MASK		BIT(3)
+#define S2MPG10_IRQ_PIF_TIMEOUT2_MASK		BIT(4)
+#define S2MPG10_IRQ_SPD_PARITY_ERR_MASK		BIT(5)
+#define S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK	BIT(6)
+#define S2MPG10_IRQ_PMETER_OVERF_MASK		BIT(7)
+
+	S2MPG10_IRQ_OCP_B1M,
+	S2MPG10_IRQ_OCP_B2M,
+	S2MPG10_IRQ_OCP_B3M,
+	S2MPG10_IRQ_OCP_B4M,
+	S2MPG10_IRQ_OCP_B5M,
+	S2MPG10_IRQ_OCP_B6M,
+	S2MPG10_IRQ_OCP_B7M,
+	S2MPG10_IRQ_OCP_B8M,
+#define S2MPG10_IRQ_OCP_B1M_MASK	BIT(0)
+#define S2MPG10_IRQ_OCP_B2M_MASK	BIT(1)
+#define S2MPG10_IRQ_OCP_B3M_MASK	BIT(2)
+#define S2MPG10_IRQ_OCP_B4M_MASK	BIT(3)
+#define S2MPG10_IRQ_OCP_B5M_MASK	BIT(4)
+#define S2MPG10_IRQ_OCP_B6M_MASK	BIT(5)
+#define S2MPG10_IRQ_OCP_B7M_MASK	BIT(6)
+#define S2MPG10_IRQ_OCP_B8M_MASK	BIT(7)
+
+	S2MPG10_IRQ_OCP_B9M,
+	S2MPG10_IRQ_OCP_B10M,
+	S2MPG10_IRQ_WLWP_ACC,
+	S2MPG10_IRQ_SMPL_TIMEOUT,
+	S2MPG10_IRQ_WTSR_TIMEOUT,
+	S2MPG10_IRQ_SPD_SRP_PKT_RST,
+#define S2MPG10_IRQ_OCP_B9M_MASK		BIT(0)
+#define S2MPG10_IRQ_OCP_B10M_MASK		BIT(1)
+#define S2MPG10_IRQ_WLWP_ACC_MASK		BIT(2)
+#define S2MPG10_IRQ_SMPL_TIMEOUT_MASK		BIT(5)
+#define S2MPG10_IRQ_WTSR_TIMEOUT_MASK		BIT(6)
+#define S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK	BIT(7)
+
+	S2MPG10_IRQ_PWR_WARN_CH0,
+	S2MPG10_IRQ_PWR_WARN_CH1,
+	S2MPG10_IRQ_PWR_WARN_CH2,
+	S2MPG10_IRQ_PWR_WARN_CH3,
+	S2MPG10_IRQ_PWR_WARN_CH4,
+	S2MPG10_IRQ_PWR_WARN_CH5,
+	S2MPG10_IRQ_PWR_WARN_CH6,
+	S2MPG10_IRQ_PWR_WARN_CH7,
+#define S2MPG10_IRQ_PWR_WARN_CH0_MASK	BIT(0)
+#define S2MPG10_IRQ_PWR_WARN_CH1_MASK	BIT(1)
+#define S2MPG10_IRQ_PWR_WARN_CH2_MASK	BIT(2)
+#define S2MPG10_IRQ_PWR_WARN_CH3_MASK	BIT(3)
+#define S2MPG10_IRQ_PWR_WARN_CH4_MASK	BIT(4)
+#define S2MPG10_IRQ_PWR_WARN_CH5_MASK	BIT(5)
+#define S2MPG10_IRQ_PWR_WARN_CH6_MASK	BIT(6)
+#define S2MPG10_IRQ_PWR_WARN_CH7_MASK	BIT(7)
+
+	S2MPG10_IRQ_NR,
+};
+
 enum s2mps11_irq {
 	S2MPS11_IRQ_PWRONF,
 	S2MPS11_IRQ_PWRONR,
diff --git a/include/linux/mfd/samsung/s2mpg10.h b/include/linux/mfd/samsung/s2mpg10.h
new file mode 100644
index 0000000000000000000000000000000000000000..471def422d00c2592e6875b1eff00a4c1be7b09f
--- /dev/null
+++ b/include/linux/mfd/samsung/s2mpg10.h
@@ -0,0 +1,310 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2015 Samsung Electronics
+ * Copyright 2020 Google Inc
+ * Copyright 2025 Linaro Ltd.
+ */
+
+#ifndef __LINUX_MFD_S2MPG10_H
+#define __LINUX_MFD_S2MPG10_H
+
+/* Common registers (type 0x000) */
+enum s2mpg10_common_reg {
+	S2MPG10_COMMON_CHIPID,
+	S2MPG10_COMMON_INT,
+	S2MPG10_COMMON_INT_MASK,
+#define S2MPG10_COMMON_INT_SRC_MASK   GENMASK(7, 0)
+#define S2MPG10_COMMON_INT_SRC_PMIC   BIT(0)
+};
+
+/* PMIC registers (type 0x100) */
+enum s2mpg10_pmic_reg {
+	S2MPG10_PMIC_INT1,
+	S2MPG10_PMIC_INT2,
+	S2MPG10_PMIC_INT3,
+	S2MPG10_PMIC_INT4,
+	S2MPG10_PMIC_INT5,
+	S2MPG10_PMIC_INT6,
+	S2MPG10_PMIC_INT1M,
+	S2MPG10_PMIC_INT2M,
+	S2MPG10_PMIC_INT3M,
+	S2MPG10_PMIC_INT4M,
+	S2MPG10_PMIC_INT5M,
+	S2MPG10_PMIC_INT6M,
+	S2MPG10_PMIC_STATUS1,
+	S2MPG10_PMIC_STATUS2,
+	S2MPG10_PMIC_PWRONSRC,
+	S2MPG10_PMIC_OFFSRC,
+	S2MPG10_PMIC_BU_CHG,
+	S2MPG10_PMIC_RTCBUF,
+	S2MPG10_PMIC_COMMON_CTRL1,
+	S2MPG10_PMIC_COMMON_CTRL2,
+	S2MPG10_PMIC_COMMON_CTRL3,
+	S2MPG10_PMIC_COMMON_CTRL4,
+	S2MPG10_PMIC_SMPL_WARN_CTRL,
+	S2MPG10_PMIC_MIMICKING_CTRL,
+	S2MPG10_PMIC_B1M_CTRL,
+	S2MPG10_PMIC_B1M_OUT1,
+	S2MPG10_PMIC_B1M_OUT2,
+	S2MPG10_PMIC_B2M_CTRL,
+	S2MPG10_PMIC_B2M_OUT1,
+	S2MPG10_PMIC_B2M_OUT2,
+	S2MPG10_PMIC_B3M_CTRL,
+	S2MPG10_PMIC_B3M_OUT1,
+	S2MPG10_PMIC_B3M_OUT2,
+	S2MPG10_PMIC_B4M_CTRL,
+	S2MPG10_PMIC_B4M_OUT1,
+	S2MPG10_PMIC_B4M_OUT2,
+	S2MPG10_PMIC_B5M_CTRL,
+	S2MPG10_PMIC_B5M_OUT1,
+	S2MPG10_PMIC_B5M_OUT2,
+	S2MPG10_PMIC_B6M_CTRL,
+	S2MPG10_PMIC_B6M_OUT1,
+	S2MPG10_PMIC_B6M_OUT2,
+	S2MPG10_PMIC_B7M_CTRL,
+	S2MPG10_PMIC_B7M_OUT1,
+	S2MPG10_PMIC_B7M_OUT2,
+	S2MPG10_PMIC_B8M_CTRL,
+	S2MPG10_PMIC_B8M_OUT1,
+	S2MPG10_PMIC_B8M_OUT2,
+	S2MPG10_PMIC_B9M_CTRL,
+	S2MPG10_PMIC_B9M_OUT1,
+	S2MPG10_PMIC_B9M_OUT2,
+	S2MPG10_PMIC_B10M_CTRL,
+	S2MPG10_PMIC_B10M_OUT1,
+	S2MPG10_PMIC_B10M_OUT2,
+	S2MPG10_PMIC_L1M_CTRL,
+	S2MPG10_PMIC_L2M_CTRL,
+	S2MPG10_PMIC_L3M_CTRL,
+	S2MPG10_PMIC_L4M_CTRL,
+	S2MPG10_PMIC_L5M_CTRL,
+	S2MPG10_PMIC_L6M_CTRL,
+	S2MPG10_PMIC_L7M_CTRL,
+	S2MPG10_PMIC_L8M_CTRL,
+	S2MPG10_PMIC_L9M_CTRL,
+	S2MPG10_PMIC_L10M_CTRL,
+	S2MPG10_PMIC_L11M_CTRL1,
+	S2MPG10_PMIC_L11M_CTRL2,
+	S2MPG10_PMIC_L12M_CTRL1,
+	S2MPG10_PMIC_L12M_CTRL2,
+	S2MPG10_PMIC_L13M_CTRL1,
+	S2MPG10_PMIC_L13M_CTRL2,
+	S2MPG10_PMIC_L14M_CTRL,
+	S2MPG10_PMIC_L15M_CTRL1,
+	S2MPG10_PMIC_L15M_CTRL2,
+	S2MPG10_PMIC_L16M_CTRL,
+	S2MPG10_PMIC_L17M_CTRL,
+	S2MPG10_PMIC_L18M_CTRL,
+	S2MPG10_PMIC_L19M_CTRL,
+	S2MPG10_PMIC_L20M_CTRL,
+	S2MPG10_PMIC_L21M_CTRL,
+	S2MPG10_PMIC_L22M_CTRL,
+	S2MPG10_PMIC_L23M_CTRL,
+	S2MPG10_PMIC_L24M_CTRL,
+	S2MPG10_PMIC_L25M_CTRL,
+	S2MPG10_PMIC_L26M_CTRL,
+	S2MPG10_PMIC_L27M_CTRL,
+	S2MPG10_PMIC_L28M_CTRL,
+	S2MPG10_PMIC_L29M_CTRL,
+	S2MPG10_PMIC_L30M_CTRL,
+	S2MPG10_PMIC_L31M_CTRL,
+	S2MPG10_PMIC_LDO_CTRL1,
+	S2MPG10_PMIC_LDO_CTRL2,
+	S2MPG10_PMIC_LDO_DSCH1,
+	S2MPG10_PMIC_LDO_DSCH2,
+	S2MPG10_PMIC_LDO_DSCH3,
+	S2MPG10_PMIC_LDO_DSCH4,
+	S2MPG10_PMIC_LDO_BUCK7M_HLIMIT,
+	S2MPG10_PMIC_LDO_BUCK7M_LLIMIT,
+	S2MPG10_PMIC_LDO_LDO21M_HLIMIT,
+	S2MPG10_PMIC_LDO_LDO21M_LLIMIT,
+	S2MPG10_PMIC_LDO_LDO11M_HLIMIT,
+	S2MPG10_PMIC_DVS_RAMP1,
+	S2MPG10_PMIC_DVS_RAMP2,
+	S2MPG10_PMIC_DVS_RAMP3,
+	S2MPG10_PMIC_DVS_RAMP4,
+	S2MPG10_PMIC_DVS_RAMP5,
+	S2MPG10_PMIC_DVS_RAMP6,
+	S2MPG10_PMIC_DCTRLSEL7 = 0xc6,
+	S2MPG10_PMIC_GPIO_CTRL1,
+	S2MPG10_PMIC_GPIO_CTRL2,
+	S2MPG10_PMIC_GPIO_CTRL3,
+	S2MPG10_PMIC_GPIO_CTRL4,
+	S2MPG10_PMIC_GPIO_CTRL5,
+	S2MPG10_PMIC_GPIO_CTRL6,
+	S2MPG10_PMIC_GPIO_CTRL7,
+	S2MPG10_PMIC_B2M_OCP_WARN,
+	S2MPG10_PMIC_B3M_OCP_WARN = 0xd2,
+	S2MPG10_PMIC_B10M_OCP_WARN = 0xd6,
+	S2MPG10_PMIC_B2M_SOFT_OCP_WARN = 0xda,
+	S2MPG10_PMIC_B3M_SOFT_OCP_WARN = 0xde,
+	S2MPG10_PMIC_B10M_SOFT_OCP_WARN = 0xe2,
+	S2MPG10_PMIC_BUCK_OCP_CTRL1 = 0xea,
+	S2MPG10_PMIC_BUCK_OCP_CTRL2,
+	S2MPG10_PMIC_BUCK_OCP_CTRL3,
+	S2MPG10_PMIC_BUCK_OCP_CTRL4,
+	S2MPG10_PMIC_BUCK_OCP_CTRL5,
+};
+
+/* Meter registers (type 0xa00) */
+enum s2mpg10_meter_reg {
+	S2MPG10_METER_CTRL1,
+	S2MPG10_METER_CTRL2,
+	S2MPG10_METER_CTRL3,
+	S2MPG10_METER_CTRL4,
+	S2MPG10_METER_BUCKEN1,
+	S2MPG10_METER_BUCKEN2,
+	S2MPG10_METER_MUXSEL0,
+	S2MPG10_METER_MUXSEL1,
+	S2MPG10_METER_MUXSEL2,
+	S2MPG10_METER_MUXSEL3,
+	S2MPG10_METER_MUXSEL4,
+	S2MPG10_METER_MUXSEL5,
+	S2MPG10_METER_MUXSEL6,
+	S2MPG10_METER_MUXSEL7,
+	S2MPG10_METER_LPF_C0_0,
+	S2MPG10_METER_LPF_C0_1,
+	S2MPG10_METER_LPF_C0_2,
+	S2MPG10_METER_LPF_C0_3,
+	S2MPG10_METER_LPF_C0_4,
+	S2MPG10_METER_LPF_C0_5,
+	S2MPG10_METER_LPF_C0_6,
+	S2MPG10_METER_LPF_C0_7,
+	S2MPG10_METER_PWR_WARN0,
+	S2MPG10_METER_PWR_WARN1,
+	S2MPG10_METER_PWR_WARN2,
+	S2MPG10_METER_PWR_WARN3,
+	S2MPG10_METER_PWR_WARN4,
+	S2MPG10_METER_PWR_WARN5,
+	S2MPG10_METER_PWR_WARN6,
+	S2MPG10_METER_PWR_WARN7,
+	S2MPG10_METER_PWR_HYS1,
+	S2MPG10_METER_PWR_HYS2,
+	S2MPG10_METER_PWR_HYS3,
+	S2MPG10_METER_PWR_HYS4,
+	S2MPG10_METER_ACC_DATA_CH0_1 = 0x40,
+	S2MPG10_METER_ACC_DATA_CH0_2,
+	S2MPG10_METER_ACC_DATA_CH0_3,
+	S2MPG10_METER_ACC_DATA_CH0_4,
+	S2MPG10_METER_ACC_DATA_CH0_5,
+	S2MPG10_METER_ACC_DATA_CH0_6,
+	S2MPG10_METER_ACC_DATA_CH1_1,
+	S2MPG10_METER_ACC_DATA_CH1_2,
+	S2MPG10_METER_ACC_DATA_CH1_3,
+	S2MPG10_METER_ACC_DATA_CH1_4,
+	S2MPG10_METER_ACC_DATA_CH1_5,
+	S2MPG10_METER_ACC_DATA_CH1_6,
+	S2MPG10_METER_ACC_DATA_CH2_1,
+	S2MPG10_METER_ACC_DATA_CH2_2,
+	S2MPG10_METER_ACC_DATA_CH2_3,
+	S2MPG10_METER_ACC_DATA_CH2_4,
+	S2MPG10_METER_ACC_DATA_CH2_5,
+	S2MPG10_METER_ACC_DATA_CH2_6,
+	S2MPG10_METER_ACC_DATA_CH3_1,
+	S2MPG10_METER_ACC_DATA_CH3_2,
+	S2MPG10_METER_ACC_DATA_CH3_3,
+	S2MPG10_METER_ACC_DATA_CH3_4,
+	S2MPG10_METER_ACC_DATA_CH3_5,
+	S2MPG10_METER_ACC_DATA_CH3_6,
+	S2MPG10_METER_ACC_DATA_CH4_1,
+	S2MPG10_METER_ACC_DATA_CH4_2,
+	S2MPG10_METER_ACC_DATA_CH4_3,
+	S2MPG10_METER_ACC_DATA_CH4_4,
+	S2MPG10_METER_ACC_DATA_CH4_5,
+	S2MPG10_METER_ACC_DATA_CH4_6,
+	S2MPG10_METER_ACC_DATA_CH5_1,
+	S2MPG10_METER_ACC_DATA_CH5_2,
+	S2MPG10_METER_ACC_DATA_CH5_3,
+	S2MPG10_METER_ACC_DATA_CH5_4,
+	S2MPG10_METER_ACC_DATA_CH5_5,
+	S2MPG10_METER_ACC_DATA_CH5_6,
+	S2MPG10_METER_ACC_DATA_CH6_1,
+	S2MPG10_METER_ACC_DATA_CH6_2,
+	S2MPG10_METER_ACC_DATA_CH6_3,
+	S2MPG10_METER_ACC_DATA_CH6_4,
+	S2MPG10_METER_ACC_DATA_CH6_5,
+	S2MPG10_METER_ACC_DATA_CH6_6,
+	S2MPG10_METER_ACC_DATA_CH7_1,
+	S2MPG10_METER_ACC_DATA_CH7_2,
+	S2MPG10_METER_ACC_DATA_CH7_3,
+	S2MPG10_METER_ACC_DATA_CH7_4,
+	S2MPG10_METER_ACC_DATA_CH7_5,
+	S2MPG10_METER_ACC_DATA_CH7_6,
+	S2MPG10_METER_ACC_COUNT_1,
+	S2MPG10_METER_ACC_COUNT_2,
+	S2MPG10_METER_ACC_COUNT_3,
+	S2MPG10_METER_LPF_DATA_CH0_1,
+	S2MPG10_METER_LPF_DATA_CH0_2,
+	S2MPG10_METER_LPF_DATA_CH0_3,
+	S2MPG10_METER_LPF_DATA_CH1_1,
+	S2MPG10_METER_LPF_DATA_CH1_2,
+	S2MPG10_METER_LPF_DATA_CH1_3,
+	S2MPG10_METER_LPF_DATA_CH2_1,
+	S2MPG10_METER_LPF_DATA_CH2_2,
+	S2MPG10_METER_LPF_DATA_CH2_3,
+	S2MPG10_METER_LPF_DATA_CH3_1,
+	S2MPG10_METER_LPF_DATA_CH3_2,
+	S2MPG10_METER_LPF_DATA_CH3_3,
+	S2MPG10_METER_LPF_DATA_CH4_1,
+	S2MPG10_METER_LPF_DATA_CH4_2,
+	S2MPG10_METER_LPF_DATA_CH4_3,
+	S2MPG10_METER_LPF_DATA_CH5_1,
+	S2MPG10_METER_LPF_DATA_CH5_2,
+	S2MPG10_METER_LPF_DATA_CH5_3,
+	S2MPG10_METER_LPF_DATA_CH6_1,
+	S2MPG10_METER_LPF_DATA_CH6_2,
+	S2MPG10_METER_LPF_DATA_CH6_3,
+	S2MPG10_METER_LPF_DATA_CH7_1,
+	S2MPG10_METER_LPF_DATA_CH7_2,
+	S2MPG10_METER_LPF_DATA_CH7_3,
+	S2MPG10_METER_DSM_TRIM_OFFSET = 0xee,
+	S2MPG10_METER_BUCK_METER_TRIM3 = 0xf1,
+};
+
+/* S2MPG10 regulator IDs */
+enum s2mpg10_regulators {
+	S2MPG10_LDO1,
+	S2MPG10_LDO2,
+	S2MPG10_LDO3,
+	S2MPG10_LDO4,
+	S2MPG10_LDO5,
+	S2MPG10_LDO6,
+	S2MPG10_LDO7,
+	S2MPG10_LDO8,
+	S2MPG10_LDO9,
+	S2MPG10_LDO10,
+	S2MPG10_LDO11,
+	S2MPG10_LDO12,
+	S2MPG10_LDO13,
+	S2MPG10_LDO14,
+	S2MPG10_LDO15,
+	S2MPG10_LDO16,
+	S2MPG10_LDO17,
+	S2MPG10_LDO18,
+	S2MPG10_LDO19,
+	S2MPG10_LDO20,
+	S2MPG10_LDO21,
+	S2MPG10_LDO22,
+	S2MPG10_LDO23,
+	S2MPG10_LDO24,
+	S2MPG10_LDO25,
+	S2MPG10_LDO26,
+	S2MPG10_LDO27,
+	S2MPG10_LDO28,
+	S2MPG10_LDO29,
+	S2MPG10_LDO30,
+	S2MPG10_LDO31,
+	S2MPG10_BUCK1,
+	S2MPG10_BUCK2,
+	S2MPG10_BUCK3,
+	S2MPG10_BUCK4,
+	S2MPG10_BUCK5,
+	S2MPG10_BUCK6,
+	S2MPG10_BUCK7,
+	S2MPG10_BUCK8,
+	S2MPG10_BUCK9,
+	S2MPG10_BUCK10,
+	S2MPG10_REGULATOR_MAX,
+};
+
+#endif /* __LINUX_MFD_S2MPG10_H */

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:30 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:30 +0000
Subject: [PATCH 14/34] mfd: sec: sort struct of_device_id entries and the
 device type switch
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-14-d08943702707@linaro.org>

Sort struct of_device_id entries and the device type switch in _probe()
alphabetically, which makes it easier to find the right place where to
insert new entries in the future.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-i2c.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index 803a46e657a5a1a639014d442941c0cdc60556a5..ba0efb30877bf668fed7476a5e247e0dd4095806 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -174,12 +174,12 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 	case S2MPS15X:
 		regmap = &s2mps15_regmap_config;
 		break;
-	case S5M8767X:
-		regmap = &s5m8767_regmap_config;
-		break;
 	case S2MPU02:
 		regmap = &s2mpu02_regmap_config;
 		break;
+	case S5M8767X:
+		regmap = &s5m8767_regmap_config;
+		break;
 	default:
 		regmap = &sec_regmap_config;
 		break;
@@ -204,11 +204,11 @@ static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
 
 static const struct of_device_id sec_pmic_i2c_of_match[] = {
 	{
-		.compatible = "samsung,s5m8767-pmic",
-		.data = (void *)S5M8767X,
-	}, {
 		.compatible = "samsung,s2dos05",
 		.data = (void *)S2DOS05,
+	}, {
+		.compatible = "samsung,s2mpa01-pmic",
+		.data = (void *)S2MPA01,
 	}, {
 		.compatible = "samsung,s2mps11-pmic",
 		.data = (void *)S2MPS11X,
@@ -221,15 +221,15 @@ static const struct of_device_id sec_pmic_i2c_of_match[] = {
 	}, {
 		.compatible = "samsung,s2mps15-pmic",
 		.data = (void *)S2MPS15X,
-	}, {
-		.compatible = "samsung,s2mpa01-pmic",
-		.data = (void *)S2MPA01,
 	}, {
 		.compatible = "samsung,s2mpu02-pmic",
 		.data = (void *)S2MPU02,
 	}, {
 		.compatible = "samsung,s2mpu05-pmic",
 		.data = (void *)S2MPU05,
+	}, {
+		.compatible = "samsung,s5m8767-pmic",
+		.data = (void *)S5M8767X,
 	},
 	{ },
 };

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:31 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:31 +0000
Subject: [PATCH 15/34] mfd: sec: use dev_err_probe() where appropriate
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-15-d08943702707@linaro.org>

dev_err_probe() exists to simplify code and harmonise error messages,
there's no reason not to use it here.

While at it, harmonise some error messages.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c |  6 +++---
 drivers/mfd/sec-i2c.c    | 10 +++-------
 drivers/mfd/sec-irq.c    | 14 +++++++-------
 3 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index fcf7668efd3215ad70d81916ede249ed5f9d45ae..5e084e2c389ea6d509393be93f7e2d39a795a60c 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -211,9 +211,9 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type,
 		num_sec_devs = ARRAY_SIZE(s2mpu05_devs);
 		break;
 	default:
-		dev_err(sec_pmic->dev, "Unsupported device type %lu\n",
-			sec_pmic->device_type);
-		return -EINVAL;
+		return dev_err_probe(sec_pmic->dev, -EINVAL,
+				     "Unsupported device type %lu\n",
+				     sec_pmic->device_type);
 	}
 	ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
 				   NULL, 0, NULL);
diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index ba0efb30877bf668fed7476a5e247e0dd4095806..ce1e5af9215a305fbb55157ae4e7bfb9aace86b8 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -152,7 +152,6 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 	const struct regmap_config *regmap;
 	unsigned long device_type;
 	struct regmap *regmap_pmic;
-	int ret;
 
 	sec_pmic_i2c_parse_dt_pdata(&client->dev, &probedata);
 
@@ -186,12 +185,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 	}
 
 	regmap_pmic = devm_regmap_init_i2c(client, regmap);
-	if (IS_ERR(regmap_pmic)) {
-		ret = PTR_ERR(regmap_pmic);
-		dev_err(&client->dev, "Failed to allocate register map: %d\n",
-			ret);
-		return ret;
-	}
+	if (IS_ERR(regmap_pmic))
+		return dev_err_probe(&client->dev, PTR_ERR(regmap_pmic),
+				     "regmap init failed\n");
 
 	return sec_pmic_probe(&client->dev, device_type, client->irq,
 			      regmap_pmic, &probedata, client);
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 4afac3aa0a582994bf04c41768c1c788c54ee2e9..d05c8b66c35f2a1356d7c641484404628870ed42 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -488,18 +488,18 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 		sec_irq_chip = &s2mpu05_irq_chip;
 		break;
 	default:
-		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
-			sec_pmic->device_type);
-		return -EINVAL;
+		return dev_err_probe(sec_pmic->dev, -EINVAL,
+				     "Unsupported device type %lu\n",
+				     sec_pmic->device_type);
 	}
 
 	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
 				       sec_pmic->irq, IRQF_ONESHOT,
 				       0, sec_irq_chip, &sec_pmic->irq_data);
-	if (ret != 0) {
-		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
-		return ret;
-	}
+	if (ret != 0)
+		return dev_err_probe(sec_pmic->dev, ret,
+				     "Failed to add %s IRQ chip\n",
+				     sec_irq_chip->name);
 
 	/*
 	 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:32 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:32 +0000
Subject: [PATCH 16/34] mfd: sec: s2dos05/s2mpu05: use explicit regmap
 config
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-16-d08943702707@linaro.org>

When support for PMICs without compatibles was removed in
commit f736d2c0caa8 ("mfd: sec: Remove PMICs without compatibles"),
sec_regmap_config effectively became an orphan, because S5M8763X was
the only user left of it before removal, using the default: case of the
switch statement.

When s2dos05 and s2mpu05 support was added in commit bf231e5febcf
("mfd: sec-core: Add support for the Samsung s2dos05") and commit
ed33479b7beb ("mfd: sec: Add support for S2MPU05 PMIC"), they ended up
using that orphaned regmap_config in a non-obvious way due to the
default: case of the device type switch matching statement taking
effect again.

To make things more obvious, and to help the reader of this code while
reasoning about what the intention might be here, and to ensure future
additions to support new devices in this driver don't forget to add a
regmap config, add an explicit regmap config for these two devices, so
that we can ultimately remove the generic regmap config.

Note that this commit doesn't fix the issue that s2dos05_regmap_config
ands2mpu05_regmap_config really are incomplete, but I have no
documentation on them.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-i2c.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index ce1e5af9215a305fbb55157ae4e7bfb9aace86b8..3912baa5c2f918b7ad345e2bbbbe4daf2e49ca6d 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -66,6 +66,11 @@ static const struct regmap_config sec_regmap_config = {
 	.val_bits = 8,
 };
 
+static const struct regmap_config s2dos05_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
 static const struct regmap_config s2mpa01_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -120,6 +125,11 @@ static const struct regmap_config s2mpu02_regmap_config = {
 	.cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config s2mpu05_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
 static const struct regmap_config s5m8767_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -158,6 +168,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 	device_type = (unsigned long)of_device_get_match_data(&client->dev);
 
 	switch (device_type) {
+	case S2DOS05:
+		regmap = &s2dos05_regmap_config;
+		break;
 	case S2MPA01:
 		regmap = &s2mpa01_regmap_config;
 		break;
@@ -176,6 +189,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 	case S2MPU02:
 		regmap = &s2mpu02_regmap_config;
 		break;
+	case S2MPU05:
+		regmap = &s2mpu05_regmap_config;
+		break;
 	case S5M8767X:
 		regmap = &s5m8767_regmap_config;
 		break;

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:33 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:33 +0000
Subject: [PATCH 17/34] mfd: sec: drop generic regmap config
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-17-d08943702707@linaro.org>

When support for PMICs without compatibles was removed in
commit f736d2c0caa8 ("mfd: sec: Remove PMICs without compatibles"),
sec_regmap_config effectively became an orphan, because S5M8763X was
the only user left of it before removal, using the default: case of the
switch statement.

Subsequently, the accidental new users have been updated, so
sec_regmap_config is an orphan again, and can and should be removed
from the code. Doing so will also ensure future additions to support
new devices in this driver don't forget to add a regmap config.

Drop this fallback regmap config.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-i2c.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index 3912baa5c2f918b7ad345e2bbbbe4daf2e49ca6d..1bdd6ea36fcd9f56ea5ec1159a87723f4c09a0bd 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -61,11 +61,6 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
 	}
 }
 
-static const struct regmap_config sec_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
 static const struct regmap_config s2dos05_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -196,8 +191,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client)
 		regmap = &s5m8767_regmap_config;
 		break;
 	default:
-		regmap = &sec_regmap_config;
-		break;
+		return dev_err_probe(&client->dev, -ENODEV,
+				     "Unsupported device type %lu\n",
+				     device_type);
 	}
 
 	regmap_pmic = devm_regmap_init_i2c(client, regmap);

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:34 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:34 +0000
Subject: [PATCH 18/34] mfd: sec: s2dos05: doesn't support interrupts (it
 seems)
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-18-d08943702707@linaro.org>

The commit bf231e5febcf ("mfd: sec-core: Add support for the Samsung
s2dos05") adding s2dos05 support didn't add anything related to IRQ
support, so I assume this works without IRQs.

Rather than printing a warning message in sec_irq_init() due to the
missing IRQ number, or returning an error due to a missing irq chip
regmap, just return early explicitly.

This will become particularly important once errors from sec_irq_init()
aren't ignored anymore in an upcoming patch and helps the reader of
this code while reasoning about what the intention might be here.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-irq.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index d05c8b66c35f2a1356d7c641484404628870ed42..dc5560a0c496917e847a40295c53e3f762b60998 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -453,16 +453,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 	int type = sec_pmic->device_type;
 	const struct regmap_irq_chip *sec_irq_chip;
 
-	if (!sec_pmic->irq) {
-		dev_warn(sec_pmic->dev,
-			 "No interrupt specified, no interrupts\n");
-		return 0;
-	}
-
 	switch (type) {
 	case S5M8767X:
 		sec_irq_chip = &s5m8767_irq_chip;
 		break;
+	case S2DOS05:
+		return 0;
 	case S2MPA01:
 		sec_irq_chip = &s2mps14_irq_chip;
 		break;
@@ -493,6 +489,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 				     sec_pmic->device_type);
 	}
 
+	if (!sec_pmic->irq) {
+		dev_warn(sec_pmic->dev,
+			 "No interrupt specified, no interrupts\n");
+		return 0;
+	}
+
 	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
 				       sec_pmic->irq, IRQF_ONESHOT,
 				       0, sec_irq_chip, &sec_pmic->irq_data);

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:35 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:35 +0000
Subject: [PATCH 19/34] mfd: sec: don't ignore errors from sec_irq_init()
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-19-d08943702707@linaro.org>

sec_irq_init() can fail, we shouldn't continue and ignore the error in
that case, but actually error out.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-common.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 5e084e2c389ea6d509393be93f7e2d39a795a60c..bec8f93a03f7fd794beade563d73610534cb96b2 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -165,7 +165,9 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type,
 		pdata->disable_wrstbi = probedata->disable_wrstbi;
 	}
 
-	sec_irq_init(sec_pmic);
+	ret = sec_irq_init(sec_pmic);
+	if (ret)
+		return ret;
 
 	pm_runtime_set_active(sec_pmic->dev);
 

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Sun Mar 23 15:39:36 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Sun, 23 Mar 2025 22:39:36 +0000
Subject: [PATCH 20/34] mfd: sec: rework platform data and regmap
 instantiating
In-Reply-To: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
Message-ID: <20250323-s2mpg10-v1-20-d08943702707@linaro.org>

Instead of a large open-coded switch statement, just add both regmap
config and device type to the OF match data. This allows us to have all
related information in one place, and avoids a long switch() statement.

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
 drivers/mfd/sec-i2c.c | 137 +++++++++++++++++++++++++-------------------------
 1 file changed, 68 insertions(+), 69 deletions(-)

diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index 1bdd6ea36fcd9f56ea5ec1159a87723f4c09a0bd..9f33d4569cf73461c57d101f6ca1cf2b75f22b4d 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -20,11 +20,16 @@
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
 #include <linux/pm.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include "sec-core.h"
 
+struct sec_pmic_i2c_platform_data {
+	const struct regmap_config *regmap_cfg;
+	unsigned long device_type;
+};
+
 static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -153,55 +158,23 @@ sec_pmic_i2c_parse_dt_pdata(struct device *dev,
 
 static int sec_pmic_i2c_probe(struct i2c_client *client)
 {
+	const struct sec_pmic_i2c_platform_data *pdata;
 	struct sec_pmic_probe_data probedata;
-	const struct regmap_config *regmap;
-	unsigned long device_type;
 	struct regmap *regmap_pmic;
 
-	sec_pmic_i2c_parse_dt_pdata(&client->dev, &probedata);
-
-	device_type = (unsigned long)of_device_get_match_data(&client->dev);
-
-	switch (device_type) {
-	case S2DOS05:
-		regmap = &s2dos05_regmap_config;
-		break;
-	case S2MPA01:
-		regmap = &s2mpa01_regmap_config;
-		break;
-	case S2MPS11X:
-		regmap = &s2mps11_regmap_config;
-		break;
-	case S2MPS13X:
-		regmap = &s2mps13_regmap_config;
-		break;
-	case S2MPS14X:
-		regmap = &s2mps14_regmap_config;
-		break;
-	case S2MPS15X:
-		regmap = &s2mps15_regmap_config;
-		break;
-	case S2MPU02:
-		regmap = &s2mpu02_regmap_config;
-		break;
-	case S2MPU05:
-		regmap = &s2mpu05_regmap_config;
-		break;
-	case S5M8767X:
-		regmap = &s5m8767_regmap_config;
-		break;
-	default:
+	pdata = device_get_match_data(&client->dev);
+	if (!pdata)
 		return dev_err_probe(&client->dev, -ENODEV,
-				     "Unsupported device type %lu\n",
-				     device_type);
-	}
+				     "Unsupported device type\n");
 
-	regmap_pmic = devm_regmap_init_i2c(client, regmap);
+	sec_pmic_i2c_parse_dt_pdata(&client->dev, &probedata);
+
+	regmap_pmic = devm_regmap_init_i2c(client, pdata->regmap_cfg);
 	if (IS_ERR(regmap_pmic))
 		return dev_err_probe(&client->dev, PTR_ERR(regmap_pmic),
 				     "regmap init failed\n");
 
-	return sec_pmic_probe(&client->dev, device_type, client->irq,
+	return sec_pmic_probe(&client->dev, pdata->device_type, client->irq,
 			      regmap_pmic, &probedata, client);
 }
 
@@ -210,35 +183,61 @@ static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
 	sec_pmic_shutdown(&i2c->dev);
 }
 
+static const struct sec_pmic_i2c_platform_data s2dos05_data = {
+	.regmap_cfg = &s2dos05_regmap_config,
+	.device_type = S2DOS05
+};
+
+static const struct sec_pmic_i2c_platform_data s2mpa01_data = {
+	.regmap_cfg = &s2mpa01_regmap_config,
+	.device_type = S2MPA01,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mps11_data = {
+	.regmap_cfg = &s2mps11_regmap_config,
+	.device_type = S2MPS11X,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mps13_data = {
+	.regmap_cfg = &s2mps13_regmap_config,
+	.device_type = S2MPS13X,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mps14_data = {
+	.regmap_cfg = &s2mps14_regmap_config,
+	.device_type = S2MPS14X,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mps15_data = {
+	.regmap_cfg = &s2mps15_regmap_config,
+	.device_type = S2MPS15X,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mpu02_data = {
+	.regmap_cfg = &s2mpu02_regmap_config,
+	.device_type = S2MPU02,
+};
+
+static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
+	.regmap_cfg = &s2mpu05_regmap_config,
+	.device_type = S2MPU05,
+};
+
+static const struct sec_pmic_i2c_platform_data s5m8767_data = {
+	.regmap_cfg = &s5m8767_regmap_config,
+	.device_type = S5M8767X,
+};
+
 static const struct of_device_id sec_pmic_i2c_of_match[] = {
-	{
-		.compatible = "samsung,s2dos05",
-		.data = (void *)S2DOS05,
-	}, {
-		.compatible = "samsung,s2mpa01-pmic",
-		.data = (void *)S2MPA01,
-	}, {
-		.compatible = "samsung,s2mps11-pmic",
-		.data = (void *)S2MPS11X,
-	}, {
-		.compatible = "samsung,s2mps13-pmic",
-		.data = (void *)S2MPS13X,
-	}, {
-		.compatible = "samsung,s2mps14-pmic",
-		.data = (void *)S2MPS14X,
-	}, {
-		.compatible = "samsung,s2mps15-pmic",
-		.data = (void *)S2MPS15X,
-	}, {
-		.compatible = "samsung,s2mpu02-pmic",
-		.data = (void *)S2MPU02,
-	}, {
-		.compatible = "samsung,s2mpu05-pmic",
-		.data = (void *)S2MPU05,
-	}, {
-		.compatible = "samsung,s5m8767-pmic",
-		.data = (void *)S5M8767X,
-	},
+	{ .compatible = "samsung,s2dos05", .data = &s2dos05_data, },
+	{ .compatible = "samsung,s2mpa01-pmic", .data = &s2mpa01_data, },
+	{ .compatible = "samsung,s2mps11-pmic", .data = &s2mps11_data, },
+	{ .compatible = "samsung,s2mps13-pmic", .data = &s2mps13_data, },
+	{ .compatible = "samsung,s2mps14-pmic", .data = &s2mps15_data, },
+	{ .compatible = "samsung,s2mps15-pmic", .data = &s2mps15_data, },
+	{ .compatible = "samsung,s2mpu02-pmic", .data = &s2mpu02_data, },
+	{ .compatible = "samsung,s2mpu05-pmic", .data = &s2mpu05_data, },
+	{ .compatible = "samsung,s5m8767-pmic", .data = &s5m8767_data, },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);

-- 
2.49.0.395.g12beb8f557-goog



From alyssa at rosenzweig.io  Sun Mar 23 15:48:18 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Sun, 23 Mar 2025 18:48:18 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <Z912pMazVwHKLi72@phenom.ffwll.local>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <Z912pMazVwHKLi72@phenom.ffwll.local>
Message-ID: <Z-CPspG_Cy-f-MKe@blossom>

> Since this is a deparature from our usual requirement that all pieces
> should be ready before landing anything we had discussion whether this is
> an acceptable one-off exception for special circumstance. Thanks a lot to
> Alyssa for driving this. The very much summarized consensus is that due to
> rust this is a special case, and because the userspace is in upstream mesa
> and lead by people who know what they're doing and have been around for
> years, it should all work out. As a stand-in for that discussion:
> 
> Acked-by: Simona Vetter <simona.vetter at ffwll.ch>
> 
> But Dave&me very much do not want to make this a recurring thing, please
> don't try :-)

Thanks for the ack :)


From daniel.almeida at collabora.com  Sun Mar 23 17:20:28 2025
From: daniel.almeida at collabora.com (Daniel Almeida)
Date: Sun, 23 Mar 2025 21:20:28 -0300
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <Z-B6uc7EEAdBPXmt@blossom>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
 <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
 <Z-B6uc7EEAdBPXmt@blossom>
Message-ID: <260D98E1-7204-4535-A84F-D55A4527FF7E@collabora.com>

Hi Alyssa,

> 
>>>> +    /** 
>>>> +     * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly 
>>>> +     * across the VA range. 
>>>> +     * 
>>>> +     * This is useful to fill a VA range with scratch pages or zero pages. 
>>>> +     * It is intended as a mechanism to accelerate sparse. 
>>>> +     */ 
>>>> +    DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
>> 
>> Does this require the BO to be a single page? If so, does it require offset==0? Or does it just take whatever page is at the specified offset?
> 
> I believe the intention is that it takes whatever page is at the
> specified offset and just maps that a bunch of times. HK doesn't use
> this yet though it probably should (this was added to help reduce
> overhead when emulating sparse with scratch/zero pages, which is still
> very new functionality in hk).
> 
> Accelerating this properly involves GPUVM patches - although even without
> that, moving the loop into the kernel so it's only a single ioctl
> (user-kernel roundtrip) seems worth keeping the flag for.

FYI: I will be posting a patch for the GPUVM abstraction soon.

? Daniel

From victor.liu at nxp.com  Sun Mar 23 19:39:28 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Mon, 24 Mar 2025 10:39:28 +0800
Subject: [PATCH 1/2] drm/bridge: imx8qxp-ldb: cleanup return value
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-1-f139d768b92c@bootlin.com>
Message-ID: <72b7caf2-5943-49b5-acb4-43b2353992e9@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> 'ret' can only be 0 at this point, being preceded by a 'if (ret) return
> ret;'. So return 0 for clarity.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied to misc/kernel.git (drm-misc-next).
Thanks!

-- 
Regards,
Liu Ying


From victor.liu at nxp.com  Sun Mar 23 19:41:12 2025
From: victor.liu at nxp.com (Liu Ying)
Date: Mon, 24 Mar 2025 10:41:12 +0800
Subject: [PATCH 2/2] drm/bridge: fsl-ldb: make warning message more
 informative
In-Reply-To: <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
References: <20250306-drm-two-ldb-improvements-v1-0-f139d768b92c@bootlin.com>
 <20250306-drm-two-ldb-improvements-v1-2-f139d768b92c@bootlin.com>
Message-ID: <7d46525f-6060-4f1b-934f-abded0a7b791@nxp.com>

On 03/07/2025, Luca Ceresoli wrote:
> This warning notifies a clock was set to an inaccurate value. Modify the
> string to also show the clock name.
> 
> While doing that also rewrap the entire function call.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli at bootlin.com>
> ---
>  drivers/gpu/drm/bridge/fsl-ldb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Applied to misc/kernel.git (drm-misc-next).
Thanks!

-- 
Regards,
Liu Ying


From ck.hu at mediatek.com  Sun Mar 23 19:45:33 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 24 Mar 2025 02:45:33 +0000
Subject: [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA yaml
 for MT8196
In-Reply-To: <20250321093435.94835-4-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-4-paul-pl.chen@mediatek.com>
Message-ID: <990774c68015d73fee297d12992d7c3e6421cc71.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen at mediatek.com>
> 
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
> The MediaTek display overlap extended DMA engine, namely
> OVL_EXDMA or EXDMA, primarily functions as a DMA engine
> for reading data from DRAM with various DRAM footprints
> and data formats.
> 
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>  .../bindings/dma/mediatek,exdma.yaml          | 70 +++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> 
> diff --git a/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> new file mode 100644
> index 000000000000..de7f8283bb48
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/dma/mediatek,exdma.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jPw1nejo$ 
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jr1jxJoQ$ 
> +
> +title: MediaTek display overlap extended DMA engine
> +
> +maintainers:
> +  - Chun-Kuang Hu <chunkuang.hu at kernel.org>
> +  - Philipp Zabel <p.zabel at pengutronix.de>
> +
> +description:
> +  The MediaTek display overlap extended DMA engine, namely OVL_EXDMA or EXDMA,
> +  primarily functions as a DMA engine for reading data from DRAM with various
> +  DRAM footprints and data formats. For input sources in certain color formats
> +  and color domains, OVL_EXDMA also includes a color transfer function
> +  to process pixels into a consistent color domain.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8196-exdma
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  mediatek,larb:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: |
> +      A phandle to the local arbiters node in the current SoCs.
> +      Refer to bindings/memory-controllers/mediatek,smi-larb.yaml.
> +
> +  iommus:
> +    maxItems: 1
> +
> +  '#dma-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - power-domains
> +  - mediatek,larb
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        disp_ovl0_exdma2: dma-controller at 32850000 {
> +            compatible = "mediatek,mt8196-exdma";
> +            reg = <0 0x32850000 0 0x1000>;
> +            clocks = <&ovlsys_config_clk 13>;
> +            power-domains = <&hfrpsys 12>;
> +            mediatek,larb = <&smi_larb0>;

larb is controlled by iommu, and exdma has already point to iommu.
OVL also not point to larb, so it's not necessary to point to larb here.

Regards,
CK

> +            iommus = <&mm_smmu 144>;
> +            #dma-cells = <1>;
> +        };
> +    };


From ck.hu at mediatek.com  Sun Mar 23 20:00:10 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 24 Mar 2025 03:00:10 +0000
Subject: [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196
In-Reply-To: <20250321093435.94835-11-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-11-paul-pl.chen@mediatek.com>
Message-ID: <9e0c4c80b5caaf168e99b8cd8ca74958eaac3aa9.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> EXDMA is a DMA engine for reading data from DRAM with
> various DRAM footprints and data formats. For input
> sources in certain color formats and color domains,
> EXDMA also includes a color transfer function to
> process pixels into a consistent color domain.
> New Add: 6320385 Fix RG16 and refine RG24
> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/Makefile         |   1 +
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.c   |   1 +
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.h   |   1 +
>  drivers/gpu/drm/mediatek/mtk_disp_drv.h   |   9 +
>  drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c    |   1 +
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h    |   1 +
>  7 files changed, 386 insertions(+)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> 
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index 32a2ed6c0cfe..db92f4fb353d 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
>  		  mtk_disp_aal.o \
>  		  mtk_disp_ccorr.o \
>  		  mtk_disp_color.o \
> +		  mtk_disp_exdma.o \
>  		  mtk_disp_gamma.o \
>  		  mtk_disp_merge.o \
>  		  mtk_disp_ovl.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index edc6417639e6..3e0739d8e6f1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
>  	[MTK_DP_INTF] = "dp-intf",
>  	[MTK_DPI] = "dpi",
>  	[MTK_DSI] = "dsi",
> +	[MTK_OVL_EXDMA] = "exdma",
>  };
>  
>  struct mtk_ddp_comp_match {
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 39720b27f4e9..86dc0ee3924c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
>  	MTK_DPI,
>  	MTK_DP_INTF,
>  	MTK_DSI,
> +	MTK_OVL_EXDMA,
>  	MTK_DDP_COMP_TYPE_MAX,
>  };
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 04217a36939c..4e3d2510bef5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev, unsigned int w,
>  		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
>  void mtk_color_start(struct device *dev);
>  
> +int mtk_disp_exdma_clk_enable(struct device *dev);
> +void mtk_disp_exdma_clk_disable(struct device *dev);
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> +				 struct cmdq_pkt *cmdq_pkt);
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev);
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev);
> +
>  void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
>  			   unsigned int bpc, unsigned int cfg,
>  			   unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> new file mode 100644
> index 000000000000..d4f7021f98d7
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_blend.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_ovl.h"
> +
> +#define DISP_REG_OVL_EXDMA_EN_CON		0xc
> +#define OVL_EXDMA_OP_8BIT_MODE				BIT(4)
> +#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ON			BIT(8)
> +#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ON			BIT(10)
> +#define DISP_REG_OVL_EXDMA_DATAPATH_CON		0x014
> +#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN		BIT(0)
> +#define OVL_EXDMA_DATAPATH_CON_GCLAST_EN		BIT(24)
> +#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN		BIT(25)
> +#define DISP_REG_OVL_EXDMA_EN			0x020
> +#define OVL_EXDMA_EN					BIT(0)
> +#define DISP_REG_OVL_EXDMA_RST			0x024
> +#define OVL_EXDMA_RST					BIT(0)
> +#define DISP_REG_OVL_EXDMA_ROI_SIZE		0x030
> +#define DISP_REG_OVL_EXDMA_L0_EN		0x040
> +#define OVL_EXDMA_L0_EN					BIT(0)
> +#define DISP_REG_OVL_EXDMA_OFFSET		0x044

DISP_REG_OVL_EXDMA_OFFSET is useless, so drop it.

> +#define DISP_REG_OVL_EXDMA_SRC_SIZE		0x048
> +#define DISP_REG_OVL_EXDMA_L0_CLRFMT		0x050
> +#define OVL_EXDMA_CON_FLD_CLRFMT			GENMASK(3, 0)
> +#define OVL_EXDMA_CON_CLRFMT_MAN			BIT(4)
> +#define OVL_EXDMA_CON_FLD_CLRFMT_NB			GENMASK(9, 8)
> +#define OVL_EXDMA_CON_CLRFMT_NB_10_BIT			BIT(8)
> +#define OVL_EXDMA_CON_BYTE_SWAP				BIT(16)
> +#define OVL_EXDMA_CON_RGB_SWAP				BIT(17)
> +#define DISP_REG_OVL_EXDMA_RDMA0_CTRL		0x100
> +#define OVL_EXDMA_RDMA0_EN				BIT(0)
> +#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON1	0x1f4
> +#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN		BIT(28)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_EN		BIT(30)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN		BIT(31)
> +#define DISP_REG_OVL_EXDMA_DUMMY_REG		0x200
> +#define OVL_EXDMA_EXT_DDR_EN_OPT			BIT(2)
> +#define OVL_EXDMA_FORCE_EXT_DDR_EN			BIT(3)
> +#define DISP_REG_OVL_EXDMA_GDRDY_PRD		0x208
> +#define DISP_REG_OVL_EXDMA_PITCH_MSB		0x2f0
> +#define DISP_REG_OVL_EXDMA_PITCH		0x2f4
> +#define OVL_EXDMA_L0_SRC_PITCH				GENMASK(15, 0)
> +#define OVL_EXDMA_L0_CONST_BLD				BIT(28)
> +#define OVL_EXDMA_L0_SRC_PITCH_MASK			GENMASK(15, 0)
> +#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT		0x2fc
> +#define OVL_EXDMA_RDMA0_L0_VCSEL			BIT(5)
> +#define OVL_EXDMA_RDMA0_HDR_L0_VCSEL			BIT(21)
> +#define DISP_REG_OVL_EXDMA_CON			0x300
> +#define OVL_EXDMA_CON_FLD_INT_MTX_SEL			GENMASK(19, 16)
> +#define OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB		(6 << 16)
> +#define OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB		(7 << 16)
> +#define OVL_EXDMA_CON_INT_MTX_EN			BIT(27)
> +#define DISP_REG_OVL_EXDMA_ADDR			0xf40
> +#define DISP_REG_OVL_EXDMA_MOUT			0xff0
> +#define OVL_EXDMA_MOUT_OUT_DATA				BIT(0)

OVL_EXDMA_MOUT_OUT_DATA is useless, so drop it.

> +#define OVL_EXDMA_MOUT_BGCLR_OUT			BIT(1)
> +
> +static const u32 formats[] = {
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_BGRX8888,
> +	DRM_FORMAT_BGRA8888,
> +	DRM_FORMAT_ABGR8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_RGBX8888,
> +	DRM_FORMAT_RGBA8888,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_BGR888,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_BGR565,

In this version, you add BGR565. If mt8195 also support BGR565, add BGR565 to mt8195_formats[] and merge these two array.

> +	DRM_FORMAT_UYVY,
> +	DRM_FORMAT_YUYV,
> +	DRM_FORMAT_XRGB2101010,
> +	DRM_FORMAT_ARGB2101010,
> +	DRM_FORMAT_RGBX1010102,
> +	DRM_FORMAT_RGBA1010102,
> +	DRM_FORMAT_XBGR2101010,
> +	DRM_FORMAT_ABGR2101010,
> +	DRM_FORMAT_BGRX1010102,
> +	DRM_FORMAT_BGRA1010102,
> +};
> +
> +struct mtk_disp_exdma {
> +	void __iomem		*regs;
> +	struct clk		*clk;
> +	struct cmdq_client_reg	cmdq_reg;
> +	struct device		*larb;
> +};
> +
> +static unsigned int  mtk_disp_exdma_color_convert(unsigned int color_encoding)
> +{
> +	switch (color_encoding) {
> +	default:
> +	case DRM_COLOR_YCBCR_BT709:
> +		return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
> +	case DRM_COLOR_YCBCR_BT601:
> +		return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
> +	}
> +}
> +
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +	unsigned int value = 0, mask = 0;

It's not necessary to initialize these variable.

> +
> +	value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
> +	mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
> +	       OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;

It seems that you clear OVL_EXDMA_RDMA_BURST_CON1_DDR_EN. Describe why you clear it.

> +	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_RDMA_BURST_CON1, mask);
> +	/*
> +	 * The dummy register is used in the configuration of the EXDMA engine to
> +	 * write commands to DRAM, ensuring that data transfers occur normally.

EXDMA would write data into DRAM? Describe more clear so I could understand this.

> +	 */
> +	value = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
> +	mask = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;

mask is identical to value, so just use value.

> +	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
> +
> +	value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> +		OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> +		OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> +	mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> +	       OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> +	       OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> +	mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT, &priv->cmdq_reg,
> +			   priv->regs, DISP_REG_OVL_EXDMA_MOUT,
> +			   OVL_EXDMA_MOUT_BGCLR_OUT | OVL_EXDMA_MOUT_OUT_DATA);
> +
> +	mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_GDRDY_PRD);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);

EXDMA has layer config function, and RDMA would enable/disable by layer, so move OVL_EXDMA_RDMA0_EN config to layer config function.

> +	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_L0_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);

EXDMA has layer config function, and L0 would enable/disable by layer, so move OVL_EXDMA_L0_EN config to layer config function.

> +
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> +}
> +
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> +}
> +
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> +				 struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +	struct mtk_plane_pending_state *pending = &state->pending;
> +	const struct drm_format_info *fmt_info = drm_format_info(pending->format);
> +	unsigned int align_width = 0;
> +	bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
> +	unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> +							 BIT(DRM_MODE_BLEND_PREMULTI) |
> +							 BIT(DRM_MODE_BLEND_COVERAGE) |
> +							 BIT(DRM_MODE_BLEND_PIXEL_NONE));
> +	unsigned int val = 0;

It's not necessary to initialize val.

> +	unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
> +				   OVL_EXDMA_CON_BYTE_SWAP |
> +				   OVL_EXDMA_CON_CLRFMT_MAN |
> +				   OVL_EXDMA_CON_FLD_CLRFMT |
> +				   OVL_EXDMA_CON_FLD_CLRFMT_NB;
> +
> +	if (!pending->enable) {
> +		mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +				   DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> +		mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +				   DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> +		return;
> +	}
> +
> +	/* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
> +	align_width = ALIGN_DOWN(pending->width, 2);

If width is 101, change width to 100 would get correct display output?

> +
> +	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> +		      priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
> +
> +	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> +		      priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
> +	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> +		      priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);

Why do you duplicate DISP_REG_OVL_EXDMA_SRC_SIZE register setting?

> +
> +	mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg,
> +			   priv->regs, DISP_REG_OVL_EXDMA_PITCH, OVL_EXDMA_L0_SRC_PITCH_MASK);
> +	mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);

Symbolize 0xf.

> +
> +	val = mtk_disp_exdma_color_convert(pending->color_encoding);
> +	if (csc_enable)
> +		val |= OVL_EXDMA_CON_INT_MTX_EN;
> +	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_CON,
> +			   OVL_EXDMA_CON_FLD_INT_MTX_SEL | OVL_EXDMA_CON_INT_MTX_EN);

You have no way to disable csc.
If first frame is YUV format, you enable csc.
And second frame is RGB, you does not disable csc, so RGB would do csc and display incorrect result.

> +
> +	val = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
> +				  OVL_EXDMA_CON_CLRFMT_MAN, OVL_EXDMA_CON_BYTE_SWAP,
> +				  OVL_EXDMA_CON_RGB_SWAP);
> +	if (mtk_ovl_is_10bit_rgb(pending->format))
> +		val |= OVL_EXDMA_CON_CLRFMT_NB_10_BIT;
> +	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_L0_CLRFMT, clrfmt_mask);
> +
> +	val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON | OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |

Does CK_ON mean clock on? If so, where do you turn off the clock?

> +		OVL_EXDMA_OP_8BIT_MODE;
> +	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_EN_CON, val);
> +
> +	val = OVL_EXDMA_RDMA0_L0_VCSEL | OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
> +	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
> +
> +	val = pending->pitch;
> +	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> +		val |= OVL_EXDMA_L0_CONST_BLD;
> +	mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_PITCH,
> +			   OVL_EXDMA_L0_CONST_BLD | OVL_EXDMA_L0_SRC_PITCH);
> +}
> +
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev)
> +{
> +	return formats;
> +}
> +
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev)
> +{
> +	return ARRAY_SIZE(formats);
> +}
> +
> +int mtk_disp_exdma_clk_enable(struct device *dev)
> +{
> +	struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> +	return clk_prepare_enable(exdma->clk);
> +}
> +
> +void mtk_disp_exdma_clk_disable(struct device *dev)
> +{
> +	struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(exdma->clk);
> +}
> +
> +static int mtk_disp_exdma_bind(struct device *dev, struct device *master,
> +			       void *data)
> +{
> +	return 0;
> +}
> +
> +static void mtk_disp_exdma_unbind(struct device *dev, struct device *master,
> +				  void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_exdma_component_ops = {
> +	.bind	= mtk_disp_exdma_bind,
> +	.unbind = mtk_disp_exdma_unbind,
> +};
> +
> +static int mtk_disp_exdma_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct platform_device *larb_pdev = NULL;
> +	struct device_node *larb_node = NULL;
> +	struct resource *res;
> +	struct mtk_disp_exdma *priv;
> +	int ret = 0;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	priv->regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(priv->regs)) {
> +		dev_err(dev, "failed to ioremap exdma\n");
> +		return PTR_ERR(priv->regs);
> +	}
> +
> +	priv->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(priv->clk)) {
> +		dev_err(dev, "failed to get exdma clk\n");
> +		return PTR_ERR(priv->clk);
> +	}
> +
> +	larb_node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
> +	if (larb_node) {
> +		larb_pdev = of_find_device_by_node(larb_node);
> +		if (larb_pdev)
> +			priv->larb = &larb_pdev->dev;
> +		of_node_put(larb_node);
> +	}
> +
> +	if (!priv->larb) {
> +		dev_dbg(dev, "not find larb dev");
> +		return -EPROBE_DEFER;
> +	}
> +	device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);

You does not define cmdq client reg in binding document, so it seems this series depend on some cmdq series.
Add the dependency information in cover letter.

> +	if (ret)
> +		dev_dbg(dev, "No mediatek,gce-client-reg\n");
> +#endif
> +	platform_set_drvdata(pdev, priv);
> +
> +	pm_runtime_enable(dev);
> +
> +	ret = component_add(dev, &mtk_disp_exdma_component_ops);
> +	if (ret != 0) {
> +		pm_runtime_disable(dev);
> +		dev_err(dev, "Failed to add component: %d\n", ret);
> +	}
> +	return ret;
> +}
> +
> +static void mtk_disp_exdma_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
> +	pm_runtime_disable(&pdev->dev);
> +}
> +
> +static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
> +	{ .compatible = "mediatek,mt8196-exdma", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
> +
> +struct platform_driver mtk_disp_exdma_driver = {
> +	.probe = mtk_disp_exdma_probe,
> +	.remove = mtk_disp_exdma_remove,
> +	.driver = {
> +		.name = "mediatek-disp-exdma",
> +		.owner = THIS_MODULE,
> +		.of_match_table = mtk_disp_exdma_driver_dt_match,
> +	},
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin at mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Exdma Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 74158b9d6503..bb7306a942ff 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1276,6 +1276,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
>  	&mtk_disp_aal_driver,
>  	&mtk_disp_ccorr_driver,
>  	&mtk_disp_color_driver,
> +	&mtk_disp_exdma_driver,
>  	&mtk_disp_gamma_driver,
>  	&mtk_disp_merge_driver,
>  	&mtk_disp_ovl_adaptor_driver,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 675cdc90a440..898a75898775 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -72,6 +72,7 @@ struct mtk_drm_private {
>  extern struct platform_driver mtk_disp_aal_driver;
>  extern struct platform_driver mtk_disp_ccorr_driver;
>  extern struct platform_driver mtk_disp_color_driver;
> +extern struct platform_driver mtk_disp_exdma_driver;
>  extern struct platform_driver mtk_disp_gamma_driver;
>  extern struct platform_driver mtk_disp_merge_driver;
>  extern struct platform_driver mtk_disp_ovl_adaptor_driver;


From justin.he at arm.com  Sun Mar 23 19:34:50 2025
From: justin.he at arm.com (Jia He)
Date: Mon, 24 Mar 2025 02:34:50 +0000
Subject: [PATCH v2] KVM: arm64: Skip the KVM pmu initialization when hyp is unavailable
Message-ID: <20250324023450.109312-1-justin.he@arm.com>

When Hyp mode is unavailable (e.g., the kernel boots from EL1), skip the
unnecessary KVM pmu initialization.

Signed-off-by: Jia He <justin.he at arm.com>
---
v2: 
 - Utilize is_hyp_mode_available() for improved accuracy when detecting the
 guest VM case, as it accounts for scenarios where the kernel boots from EL1.

 arch/arm64/kvm/pmu-emul.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 6c5950b9ceac..81b1a84ee1b3 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -779,6 +779,13 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
 {
 	struct arm_pmu_entry *entry;
 
+	/*
+	 * When Hyp mode is unavailable (e.g., the kernel boots from EL1),
+	 * skip the unnecessary KVM PMU initialization.
+	 */
+	if (!is_hyp_mode_available())
+		return;
+
 	/*
 	 * Check the sanitised PMU version for the system, as KVM does not
 	 * support implementations where PMUv3 exists on a subset of CPUs.
-- 
2.34.1



From Chun-Jen.Tseng at mediatek.com  Sun Mar 23 20:21:05 2025
From: Chun-Jen.Tseng at mediatek.com (=?utf-8?B?Q2h1bi1KZW4gVHNlbmcgKOabvuS/iuS7gSk=?=)
Date: Mon, 24 Mar 2025 03:21:05 +0000
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <20250321060148.adhxjexpnm4dkpnt@vireshk-i7>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
	 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
	 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
	 <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
	 <20250321045624.mwm2mnkqeow5uids@vireshk-i7>
	 <2a73b5ca35692c8ffa68c9ff0df73e24a592967d.camel@mediatek.com>
	 <20250321060148.adhxjexpnm4dkpnt@vireshk-i7>
Message-ID: <e1c2c12bace22d1803d16ecbfb32129518d87157.camel@mediatek.com>

Hi viresh,

I think the best configuration sequence is as follows:
  cpufreq policy -> set frequency -> CCI governor get
CPUFREQ_POSTCHANGE NB -> choose CCI frequency -> set CCI frequency

However, in drivers/devfreq/governor_passive.c#L77,
get_target_freq_with_cpufreq() retrieves the current frequency of each
policy,
and it determines the CCI frequency based on the frequency of each
policy.

But if policy-0 and policy-6 enter simultaneously, the CCI governor
might get an incorrect frequency.

cpufreq policy-0 -> set frequency -> CCI governor get
CPUFREQ_POSTCHANGE NB -> choose CCI frequency -> set CCI frequency
=> during this time, the CCI governor gets policy-0 and policy-6, BUT
policy-6 may change frequency by cpufreq driver at the same time.

Therefore, I want to change it so that only one policy can perform the
set frequency action at a time to avoid CCI running at the wrong
frequency.

BRs,

Mark Tseng

On Fri, 2025-03-21 at 11:31 +0530, Viresh Kumar wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 21-03-25, 05:32, Chun-Jen Tseng (???) wrote:
> > I add a global lock related to the CCI driver.
> > 
> > This is because the CCI needs to obtain the frequencies of policy-0
> > and
> > policy-6 to determine its own frequency.
> > 
> > If policy-0 and policy-6 are set simultaneously, it may cause the
> > CCI
> > to select the wrong frequency.
> > 
> > Therefore, I hope to change the setting flow to the following:
> > ?? policy-0 or policy-6 -> set frequency -> CCI receives
> > notification -
> > set CCI frequency
> 
> Can you please point to the code where this race exists ? I am not
> sure I fully understand it as of now. If the race is present in
> another driver, CCI ?, then shouldn't it be fixed there instead ?
> 
> --
> viresh


From dyoung at redhat.com  Sun Mar 23 21:18:24 2025
From: dyoung at redhat.com (Dave Young)
Date: Mon, 24 Mar 2025 12:18:24 +0800
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <20250320015551.2157511-12-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com> <20250320015551.2157511-12-changyuanl@google.com>
Message-ID: <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>

On Thu, 20 Mar 2025 at 23:05, Changyuan Lyu <changyuanl at google.com> wrote:
>
> From: Alexander Graf <graf at amazon.com>
>
> We have all generic code in place now to support Kexec with KHO. This
> patch adds a config option that depends on architecture support to
> enable KHO support.
>
> Signed-off-by: Alexander Graf <graf at amazon.com>
> Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> ---
>  kernel/Kconfig.kexec | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>
> diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> index 4d111f871951..57db99e758a8 100644
> --- a/kernel/Kconfig.kexec
> +++ b/kernel/Kconfig.kexec
> @@ -95,6 +95,21 @@ config KEXEC_JUMP
>           Jump between original kernel and kexeced kernel and invoke
>           code in physical address mode via KEXEC
>
> +config KEXEC_HANDOVER
> +       bool "kexec handover"
> +       depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
> +       select MEMBLOCK_KHO_SCRATCH
> +       select KEXEC_FILE
> +       select DEBUG_FS
> +       select LIBFDT
> +       select CMA
> +       select XXHASH
> +       help
> +         Allow kexec to hand over state across kernels by generating and
> +         passing additional metadata to the target kernel. This is useful
> +         to keep data or state alive across the kexec. For this to work,
> +         both source and target kernels need to have this option enabled.
> +

Have you tested kdump?  In my mind there are two issues,  one is with
CMA enabled, it could cause kdump crashkernel memory reservation
failures more often due to the fragmented low memory.  Secondly,  in
kdump kernel dump the crazy scratch memory in vmcore is not very
meaningful.  Otherwise I suspect this is not tested under kdump.  If
so please disable this option for kdump.

>  config CRASH_DUMP
>         bool "kernel crash dumps"
>         default ARCH_DEFAULT_CRASH_DUMP
> --
> 2.48.1.711.g2feabab25a-goog
>
>



From anshuman.khandual at arm.com  Sun Mar 23 21:19:38 2025
From: anshuman.khandual at arm.com (Anshuman Khandual)
Date: Mon, 24 Mar 2025 09:49:38 +0530
Subject: [PATCH] arm64: mm: Correct the update of max_pfn
In-Reply-To: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
References: <20250321070019.1271859-1-quic_zhenhuah@quicinc.com>
Message-ID: <48f15771-ed1a-4e30-b825-70ee3c323d37@arm.com>

On 3/21/25 12:30, Zhenhua Huang wrote:
> Hotplugged memory can be smaller than the original memory. For example,
> on my target:
> 
> root at genericarmv8:~# cat /sys/kernel/debug/memblock/memory
>    0: 0x0000000064005000..0x0000000064023fff    0 NOMAP
>    1: 0x0000000064400000..0x00000000647fffff    0 NOMAP
>    2: 0x0000000068000000..0x000000006fffffff    0 DRV_MNG
>    3: 0x0000000088800000..0x0000000094ffefff    0 NONE
>    4: 0x0000000094fff000..0x0000000094ffffff    0 NOMAP
> max_pfn will affect read_page_owner. Therefore, it should first compare and
> then select the larger value for max_pfn.
> 
> Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug")
> Signed-off-by: Zhenhua Huang <quic_zhenhuah at quicinc.com>
> ---
>  arch/arm64/mm/mmu.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 1dfe1a8efdbe..310ff75891ef 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  		__remove_pgd_mapping(swapper_pg_dir,
>  				     __phys_to_virt(start), size);
>  	else {
> -		max_pfn = PFN_UP(start + size);
> +		/* Address of hotplugged memory can be smaller */
> +		max_pfn = max(max_pfn, PFN_UP(start + size));
>  		max_low_pfn = max_pfn;
>  	}
>  

Reviewed-by: Anshuman Khandual <anshuman.khandual at arm.com>


From lkp at intel.com  Sun Mar 23 22:09:59 2025
From: lkp at intel.com (kernel test robot)
Date: Mon, 24 Mar 2025 13:09:59 +0800
Subject: [PATCH 20/34] mfd: sec: rework platform data and regmap
 instantiating
In-Reply-To: <20250323-s2mpg10-v1-20-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-20-d08943702707@linaro.org>
Message-ID: <202503241201.amdeUwuc-lkp@intel.com>

Hi Andr?,

kernel test robot noticed the following build warnings:

[auto build test WARNING on c4d4884b67802c41fd67399747165d65c770621a]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Draszik/dt-bindings-mfd-samsung-s2mps11-add-s2mpg10/20250324-064418
base:   c4d4884b67802c41fd67399747165d65c770621a
patch link:    https://lore.kernel.org/r/20250323-s2mpg10-v1-20-d08943702707%40linaro.org
patch subject: [PATCH 20/34] mfd: sec: rework platform data and regmap instantiating
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20250324/202503241201.amdeUwuc-lkp at intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250324/202503241201.amdeUwuc-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503241201.amdeUwuc-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/mfd/sec-i2c.c:206:48: warning: 's2mps14_data' defined but not used [-Wunused-const-variable=]
     206 | static const struct sec_pmic_i2c_platform_data s2mps14_data = {
         |                                                ^~~~~~~~~~~~


vim +/s2mps14_data +206 drivers/mfd/sec-i2c.c

   205	
 > 206	static const struct sec_pmic_i2c_platform_data s2mps14_data = {
   207		.regmap_cfg = &s2mps14_regmap_config,
   208		.device_type = S2MPS14X,
   209	};
   210	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From viresh.kumar at linaro.org  Sun Mar 23 22:43:33 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Mon, 24 Mar 2025 11:13:33 +0530
Subject: [PATCH v3 1/3] cpufreq: mediatek: using global lock avoid race
 condition
In-Reply-To: <e1c2c12bace22d1803d16ecbfb32129518d87157.camel@mediatek.com>
References: <20250214074353.1169864-1-chun-jen.tseng@mediatek.com>
 <20250214074353.1169864-2-chun-jen.tseng@mediatek.com>
 <20250219054209.erwfp7sgzchaiuds@vireshk-i7>
 <e8337c5eee0cadb797bacf26b00f1ca303c5147f.camel@mediatek.com>
 <20250321045624.mwm2mnkqeow5uids@vireshk-i7>
 <2a73b5ca35692c8ffa68c9ff0df73e24a592967d.camel@mediatek.com>
 <20250321060148.adhxjexpnm4dkpnt@vireshk-i7>
 <e1c2c12bace22d1803d16ecbfb32129518d87157.camel@mediatek.com>
Message-ID: <20250324054333.sgwwksawnybx3lp4@vireshk-i7>

Hi,

Thanks for sharing the details this time, it makes it much clearer
now.

On 24-03-25, 03:21, Chun-Jen Tseng (???) wrote:
> I think the best configuration sequence is as follows:
>   cpufreq policy -> set frequency -> CCI governor get
> CPUFREQ_POSTCHANGE NB -> choose CCI frequency -> set CCI frequency
> 
> However, in drivers/devfreq/governor_passive.c#L77,
> get_target_freq_with_cpufreq() retrieves the current frequency of each
> policy,
> and it determines the CCI frequency based on the frequency of each
> policy.
> 
> But if policy-0 and policy-6 enter simultaneously, the CCI governor
> might get an incorrect frequency.

Yes it may fetch the current frequency (or last known one), but that
shouldn't be a problem as the postchange notification for policy-6
should get called right after and should fix the issue. Right ?

I don't think this is a race and if this requires fixing. clk_get()
for any device, will always return the last configured value, while
the clock might be changing at the same time.

What's important is that you don't get an incorrect frequency (as in
based on intermediate values of registers, etc). Note that the last
configured frequency isn't an incorrect frequency.

> cpufreq policy-0 -> set frequency -> CCI governor get
> CPUFREQ_POSTCHANGE NB -> choose CCI frequency -> set CCI frequency
> => during this time, the CCI governor gets policy-0 and policy-6, BUT
> policy-6 may change frequency by cpufreq driver at the same time.

Sure, and I don't see a problem with that. The issue is there only if
we can reach a state where CCI is left configured in the wrong state.
Which I don't think would happen here as the postchange notifier will
get called again, forcing a switch of frequency again.

-- 
viresh


From viresh.kumar at linaro.org  Sun Mar 23 22:48:05 2025
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Mon, 24 Mar 2025 11:18:05 +0530
Subject: [PATCH] cpufreq: sun50i: prevent out-of-bounds access
In-Reply-To: <2772067.mvXUDI8C0e@jernej-laptop>
References: <20250320155557.211211-1-andre.przywara@arm.com>
 <2772067.mvXUDI8C0e@jernej-laptop>
Message-ID: <20250324054805.3x3nwl4vtvf63rwj@vireshk-i7>

On 22-03-25, 08:38, Jernej ?krabec wrote:
> Dne ?etrtek, 20. marec 2025 ob 16:55:57 Srednjeevropski standardni ?as je Andre Przywara napisal(a):
> > A KASAN enabled kernel reports an out-of-bounds access when handling the
> > nvmem cell in the sun50i cpufreq driver:
> > ==================================================================
> > BUG: KASAN: slab-out-of-bounds in sun50i_cpufreq_nvmem_probe+0x180/0x3d4
> > Read of size 4 at addr ffff000006bf31e0 by task kworker/u16:1/38
> > 
> > This is because the DT specifies the nvmem cell as covering only two
> > bytes, but we use a u32 pointer to read the value. DTs for other SoCs
> > indeed specify 4 bytes, so we cannot just shorten the variable to a u16.
> > 
> > Fortunately nvmem_cell_read() allows to return the length of the nvmem
> > cell, in bytes, so we can use that information to only access the valid
> > portion of the data.
> > To cover multiple cell sizes, use memcpy() to copy the information into a
> > zeroed u32 buffer, then also make sure we always read the data in little
> > endian fashion, as this is how the data is stored in the SID efuses.
> > 
> > Fixes: 6cc4bcceff9a ("cpufreq: sun50i: Refactor speed bin decoding")
> > Reported-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> 
> Thanks for fixing that!
> 
> Reviewed-by: Jernej ?krabec <jernej.skrabec at gmail.com>

Applied. Thanks.

-- 
viresh


From dan.carpenter at linaro.org  Sun Mar 23 22:50:37 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 24 Mar 2025 08:50:37 +0300
Subject: [PATCH] wifi: mt76: mt7996: avoid potential null deref in
 mt7996_get_et_stats()
In-Reply-To: <CAAMvbhGrJ9b3Aab9+2a5zmvEgf0GZFmHLCC7Hud+egUE28voHQ@mail.gmail.com>
References: <20250322141910.4461-1-qasdev00@gmail.com>
 <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
 <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>
 <CAAMvbhGrJ9b3Aab9+2a5zmvEgf0GZFmHLCC7Hud+egUE28voHQ@mail.gmail.com>
Message-ID: <223c7280-443d-49b4-96b2-90472339dcd4@stanley.mountain>

On Sun, Mar 23, 2025 at 11:59:45AM +0000, James Dutton wrote:
> As a security side note in relation to the following patch:
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 66575698aef1..88e013577c0d 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -68,11 +68,13 @@ static int mt7996_start(struct ieee80211_hw *hw)
> 
>  static void mt7996_stop_phy(struct mt7996_phy *phy)
>  {
> -       struct mt7996_dev *dev = phy->dev;
> +       struct mt7996_dev *dev;
> 
>         if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
>                 return;
> 
> +       dev = phy->dev;
> +
>         cancel_delayed_work_sync(&phy->mt76->mac_work);
> 
>         mutex_lock(&dev->mt76.mutex);
> 
> 
> 
> Prior to that patch, the code looks like this:
> static void mt7996_stop_phy(struct mt7996_phy *phy)
>  {
>        struct mt7996_dev *dev = phy->dev;
> 
>         if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
>                 return;
> 
> 
> The compiler will completely remove the !phy check entirely because of
> the use above it, so it being present in the source code is completely
> bogus.

No, in the kernel we use the -fno-delete-null-pointer-checks so the
NULL check will always be there.

Also the "phy" point will never be NULL so the check should be removed.

regards,
dan carpenter

> If one actually needs a !phy check to be present in the compiled code,
> one must arrange it as per the patch above.
> 
> The fact that the !phy check is in the source code, implies to me that
> someone, in the past, thought it was necessary, but I think an opinion
> could be taken that it is there to obfuscate a security vulnerability.
> 
> Kind Regards
> 
> James


From a.vatoropin at crpt.ru  Sun Mar 23 23:15:49 2025
From: a.vatoropin at crpt.ru (=?utf-8?B?0JLQsNGC0L7RgNC+0L/QuNC9INCQ0L3QtNGA0LXQuQ==?=)
Date: Mon, 24 Mar 2025 06:15:49 +0000
Subject: [PATCH] soc: xilinx: vcu: modify the order of devices unregistration
Message-ID: <20250324061543.15150-1-a.vatoropin@crpt.ru>

From: Andrey Vatoropin <a.vatoropin at crpt.ru>

The order of registration of 'struct clk_hw' handles in
xvcu_clk_hw_register_leaf() does not correspond the order of
unregistration performed in xvcu_clk_hw_unregister_leaf().

Clean up the order and replace the duplicate !divider check with a more
appropriate one.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Andrey Vatoropin <a.vatoropin at crpt.ru>
---
 drivers/clk/xilinx/xlnx_vcu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/xilinx/xlnx_vcu.c b/drivers/clk/xilinx/xlnx_vcu.c
index 81501b48412e..e4b08f501958 100644
--- a/drivers/clk/xilinx/xlnx_vcu.c
+++ b/drivers/clk/xilinx/xlnx_vcu.c
@@ -511,11 +511,11 @@ static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
 		return;
 
 	mux = clk_hw_get_parent(divider);
-	clk_hw_unregister_mux(mux);
-	if (!divider)
+	clk_hw_unregister_divider(divider);
+	if (!mux)
 		return;
 
-	clk_hw_unregister_divider(divider);
+	clk_hw_unregister_mux(mux);
 }
 
 static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
-- 
2.43.0

From peter.chen at cixtech.com  Sun Mar 23 23:24:16 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:16 +0800
Subject: [PATCH v5 2/6] dt-bindings: arm: add CIX P1 (SKY1) SoC
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-3-peter.chen@cixtech.com>

Add device tree bindings for CIX P1 (Internal name sky1) Arm SoC,
it consists several SoC models like CP8180, CD8180, etc.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 .../devicetree/bindings/arm/cix.yaml          | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml

diff --git a/Documentation/devicetree/bindings/arm/cix.yaml b/Documentation/devicetree/bindings/arm/cix.yaml
new file mode 100644
index 000000000000..114dab4bc4d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cix.yaml
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/cix.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CIX platforms
+
+maintainers:
+  - Peter Chen <peter.chen at cixtech.com>
+  - Fugang Duan <fugang.duan at cixtech.com>
+
+properties:
+  $nodename:
+    const: '/'
+  compatible:
+    oneOf:
+
+      - description: Radxa Orion O6
+        items:
+          - const: radxa,orion-o6
+          - const: cix,sky1
+
+additionalProperties: true
+
+...
-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:17 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:17 +0800
Subject: [PATCH v5 3/6] arm64: Kconfig: add ARCH_CIX for cix silicons
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-4-peter.chen@cixtech.com>

From: Fugang Duan <fugang.duan at cixtech.com>

Add ARCH_CIX for CIX SoC series support.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 arch/arm64/Kconfig.platforms | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 02f9248f7c84..abe41db9b9b3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -106,6 +106,12 @@ config ARCH_BLAIZE
 	help
 	  This enables support for the Blaize SoC family
 
+config ARCH_CIX
+	bool "Cixtech SoC family"
+	help
+	  This enables support for the Cixtech SoC family,
+	  like P1(sky1).
+
 config ARCH_EXYNOS
 	bool "Samsung Exynos SoC family"
 	select COMMON_CLK_SAMSUNG
-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:20 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:20 +0800
Subject: [PATCH v5 6/6] MAINTAINERS: Add CIX SoC maintainer entry
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-7-peter.chen@cixtech.com>

Using this entry as the maintainers information for CIX SoCs.

Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v5:
- Refine MAINTAINERS for all CIX SoC
- Add T for code tree location
- Add K for Content regex

Changes for v4:
- Add two dts files as maintained files

 MAINTAINERS | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index efee40ea589f..f400e2de573b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2354,6 +2354,17 @@ F:	arch/arm/boot/compressed/misc-ep93xx.h
 F:	arch/arm/mach-ep93xx/
 F:	drivers/iio/adc/ep93xx_adc.c
 
+ARM/CIX SOC SUPPORT
+M:	Peter Chen <peter.chen at cixtech.com>
+M:	Fugang Duan <fugang.duan at cixtech.com>
+R:	CIX Linux Kernel Upstream Group <cix-kernel-upstream at cixtech.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix.git
+F:	Documentation/devicetree/bindings/arm/cix.yaml
+F:	arch/arm64/boot/dts/cix/
+K:	\bcix\b
+
 ARM/CLKDEV SUPPORT
 M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:15 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:15 +0800
Subject: [PATCH v5 1/6] dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-2-peter.chen@cixtech.com>

CIX Technology Group Co., Ltd. is a high performance Arm SoC design
company. Link: https://www.cixtech.com/.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 5079ca6ce1d1..5e76223e4570 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -302,6 +302,8 @@ patternProperties:
     description: Cirrus Logic, Inc.
   "^cisco,.*":
     description: Cisco Systems, Inc.
+  "^cix,.*":
+    description: CIX Technology Group Co., Ltd.
   "^clockwork,.*":
     description: Clockwork Tech LLC
   "^cloos,.*":
-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:14 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:14 +0800
Subject: [PATCH v5 0/6] arm64: Introduce CIX P1 (SKY1) SoC
Message-ID: <20250324062420.360289-1-peter.chen@cixtech.com>

Cixtech P1 (internal name sky1) is high performance generic Armv9 SoC.
Orion O6 is the world's first open source Arm V9 Motherboard built by
Radxa. You could find brief introduction for SoC and related boards at:
https://radxa.com/products/orion/o6#overview

In this series, we add initial SoC and board support for Kernel building.
Patch 1-2: add dt-binding doc for CIX and its sky1 SoC
Patch 3-4: add Arm64 build support
Patch 5: add initial dts support for SoC and Orion O6 board
Patch 6: add MAINTAINERS entry

To run upstream kernel at Orion O6 board, you need to use BIOS
released by Radxa:
https://docs.radxa.com/en/orion/o6/bios/install-bios

Changes for v5:
- Patch 5: Delete pmu-spe node which need to refine, and add it in future
- Patch 6: Refine MAINTAINERS for all CIX SoC and adding code tree location

Changes for v4:
- Move add MAINTAINERS entry patch to the last, and add two dts files entry in it. 
- Add three Krzysztof Kozlowski's Reviewed-by Tags
- For sky1.dtsi, makes below changes:
	- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
	get its handle
	- Remove gic-v3's #redistributor-regions and redistributor-stride properties
	- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
	- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
	- Remove timer's clock frequency due to firmware has already set it

Changes for v3:
- Patch 1: Add Krzysztof Kozlowski's Acked-by Tag
- Patch 2: Add Krzysztof Kozlowski's Reviewed-by Tag
- Patch 6: Fix two dts coding sytle issues

Changes for v2:
- Pass dts build check with below commands:
make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=vendor-prefixes.yaml
make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=arm/cix.yaml
make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
- Re-order the patch set, and move vendor-perfixes to the 1st patch.
- Patch 4: Ordered Kconfig config entry by alpha-numerically
- Patch 5: Corrects the Ack tag's name
- Patch 6: see below.
1) Corrects the SoF tag's name
2) Fix several coding sytle issues
3) move linux,cma node to dts file
4) delete memory node, memory size is passed by firmware
5) delete uart2 node which will be added in future patches
6) Improve for pmu and cpu node to stands for more specific cpu model
7) Improve the timer node and add hypervisor virtual timer irq

Fugang Duan (1):
  arm64: Kconfig: add ARCH_CIX for cix silicons

Peter Chen (5):
  dt-bindings: vendor-prefixes: Add CIX Technology Group Co., Ltd.
  dt-bindings: arm: add CIX P1 (SKY1) SoC
  arm64: defconfig: Enable CIX SoC
  arm64: dts: cix: add initial CIX P1(SKY1) dts support
  MAINTAINERS: Add CIX SoC maintainer entry

 .../devicetree/bindings/arm/cix.yaml          |  26 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |  11 +
 arch/arm64/Kconfig.platforms                  |   6 +
 arch/arm64/boot/dts/Makefile                  |   1 +
 arch/arm64/boot/dts/cix/Makefile              |   2 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |  26 +++
 arch/arm64/boot/dts/cix/sky1.dtsi             | 217 ++++++++++++++++++
 arch/arm64/configs/defconfig                  |   1 +
 9 files changed, 292 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cix.yaml
 create mode 100644 arch/arm64/boot/dts/cix/Makefile
 create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
 create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi

-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:18 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:18 +0800
Subject: [PATCH v5 4/6] arm64: defconfig: Enable CIX SoC
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-5-peter.chen@cixtech.com>

Enable CIX SoC support at ARM64 defconfig

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index cb7da4415599..1dd46d200401 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -45,6 +45,7 @@ CONFIG_ARCH_BCMBCA=y
 CONFIG_ARCH_BRCMSTB=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_ARCH_BLAIZE=y
+CONFIG_ARCH_CIX=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_ARCH_SPARX5=y
 CONFIG_ARCH_K3=y
-- 
2.25.1



From peter.chen at cixtech.com  Sun Mar 23 23:24:19 2025
From: peter.chen at cixtech.com (Peter Chen)
Date: Mon, 24 Mar 2025 14:24:19 +0800
Subject: [PATCH v5 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <20250324062420.360289-1-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
Message-ID: <20250324062420.360289-6-peter.chen@cixtech.com>

CIX SKY1 SoC is high performance Armv9 SoC designed by Cixtech,
and Orion O6 is open source motherboard launched by Radxa.
See below for detail:
https://docs.radxa.com/en/orion/o6/getting-started/introduction

In this commit, it only adds limited components for running initramfs
at Orion O6.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Acked-by: Fugang Duan <fugang.duan at cixtech.com>
Signed-off-by: Peter Chen <peter.chen at cixtech.com>
---
Changes for v5:
- Delete pmu-spe node which need to refine, and add it in future

Changes for v4:
- Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
get its handle
- Remove gic-v3's #redistributor-regions and redistributor-stride properties
- Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
- Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
- Remove timer's clock frequency due to firmware has already set it
- Add Krzysztof Kozlowski's reviewed-by

Changes for v3:
- Fix two dts coding sytle issues 

Changes for v2:
- Corrects the SoF tag's name
- Fix several coding sytle issues
- move linux,cma node to dts file
- delete memory node, memory size is passed by firmware
- delete uart2 node which will be added in future patches
- Improve for pmu and cpu node to stands for more specific cpu model
- Improve the timer node and add hypervisor virtual timer irq
- Pass "make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb"

 arch/arm64/boot/dts/Makefile              |   1 +
 arch/arm64/boot/dts/cix/Makefile          |   2 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts |  26 +++
 arch/arm64/boot/dts/cix/sky1.dtsi         | 217 ++++++++++++++++++++++
 4 files changed, 246 insertions(+)
 create mode 100644 arch/arm64/boot/dts/cix/Makefile
 create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
 create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 79b73a21ddc2..8e7ccd0027bd 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -13,6 +13,7 @@ subdir-y += bitmain
 subdir-y += blaize
 subdir-y += broadcom
 subdir-y += cavium
+subdir-y += cix
 subdir-y += exynos
 subdir-y += freescale
 subdir-y += hisilicon
diff --git a/arch/arm64/boot/dts/cix/Makefile b/arch/arm64/boot/dts/cix/Makefile
new file mode 100644
index 000000000000..ed3713982012
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_CIX) += sky1-orion-o6.dtb
diff --git a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
new file mode 100644
index 000000000000..78f4fcd87216
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2025 Cix Technology Group Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "sky1.dtsi"
+/ {
+	model = "Radxa Orion O6";
+	compatible = "radxa,orion-o6", "cix,sky1";
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x0 0x28000000>;
+			linux,cma-default;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
new file mode 100644
index 000000000000..5bfeeea454e0
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/sky1.dtsi
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2025 Cix Technology Group Co., Ltd.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu1: cpu at 100 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu2: cpu at 200 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x200>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu3: cpu at 300 {
+			compatible = "arm,cortex-a520";
+			enable-method = "psci";
+			reg = <0x0 0x300>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <403>;
+		};
+
+		cpu4: cpu at 400 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x400>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu5: cpu at 500 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x500>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu6: cpu at 600 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x600>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu7: cpu at 700 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x700>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu8: cpu at 800 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x800>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu9: cpu at 900 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0x900>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu10: cpu at a00 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0xa00>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu11: cpu at b00 {
+			compatible = "arm,cortex-a720";
+			enable-method = "psci";
+			reg = <0x0 0xb00>;
+			device_type = "cpu";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+				core4 {
+					cpu = <&cpu4>;
+				};
+				core5 {
+					cpu = <&cpu5>;
+				};
+				core6 {
+					cpu = <&cpu6>;
+				};
+				core7 {
+					cpu = <&cpu7>;
+				};
+				core8 {
+					cpu = <&cpu8>;
+				};
+				core9 {
+					cpu = <&cpu9>;
+				};
+				core10 {
+					cpu = <&cpu10>;
+				};
+				core11 {
+					cpu = <&cpu11>;
+				};
+			};
+		};
+	};
+
+	pmu-a520 {
+		compatible = "arm,cortex-a520-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
+	};
+
+	pmu-a720 {
+		compatible = "arm,cortex-a720-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	soc at 0 {
+		compatible = "simple-bus";
+		ranges = <0 0 0 0 0x20 0>;
+		dma-ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		gic: interrupt-controller at e010000 {
+			compatible = "arm,gic-v3";
+			reg = <0x0 0x0e010000 0 0x10000>,	/* GICD */
+			      <0x0 0x0e090000 0 0x300000>;       /* GICR * 12 */
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW 0>;
+			#interrupt-cells = <4>;
+			interrupt-controller;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			gic_its: msi-controller at e050000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x0e050000 0x0 0x30000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+
+			ppi-partitions {
+				ppi_partition0: interrupt-partition-0 {
+					affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
+				};
+
+				ppi_partition1: interrupt-partition-1 {
+					affinity = <&cpu4 &cpu5 &cpu6 &cpu7 &cpu8 &cpu9 &cpu10 &cpu11>;
+				};
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 12 IRQ_TYPE_LEVEL_LOW 0>;
+	};
+};
-- 
2.25.1



From hongxing.zhu at nxp.com  Sun Mar 23 23:26:44 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:44 +0800
Subject: [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
In-Reply-To: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
Message-ID: <20250324062647.1891896-3-hongxing.zhu@nxp.com>

Beside the power-on reset, add the cold reset toggle for i.MX95 PCIe.

Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 31 +++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index aa5c3f235995..0f42ab63f5ad 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -71,6 +71,9 @@
 #define IMX95_SID_MASK				GENMASK(5, 0)
 #define IMX95_MAX_LUT				32
 
+#define IMX95_PCIE_RST_CTRL			0x3010
+#define IMX95_PCIE_COLD_RST			BIT(0)
+
 #define to_imx_pcie(x)	dev_get_drvdata((x)->dev)
 
 enum imx_pcie_variants {
@@ -773,6 +776,32 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
 	return 0;
 }
 
+static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
+{
+	if (assert) {
+		/*
+		 * From i.MX95 PCIe PHY perspective, the COLD reset toggle
+		 * should be complete after power-up by the following sequence.
+		 *                 > 10us(at power-up)
+		 *                 > 10ns(warm reset)
+		 *               |<------------>|
+		 *                ______________
+		 * phy_reset ____/              \________________
+		 *                                   ____________
+		 * ref_clk_en_______________________/
+		 * Toggle COLD reset aligned with this sequence for i.MX95 PCIe.
+		 */
+		regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
+				   IMX95_PCIE_COLD_RST, IMX95_PCIE_COLD_RST);
+		udelay(15);
+		regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
+				   IMX95_PCIE_COLD_RST, 0);
+		udelay(10);
+	}
+
+	return 0;
+}
+
 static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
 {
 	reset_control_assert(imx_pcie->pciephy_reset);
@@ -1762,6 +1791,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 		.ltssm_mask = IMX95_PCIE_LTSSM_EN,
 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+		.core_reset = imx95_pcie_core_reset,
 		.init_phy = imx95_pcie_init_phy,
 	},
 	[IMX8MQ_EP] = {
@@ -1815,6 +1845,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
 		.init_phy = imx95_pcie_init_phy,
+		.core_reset = imx95_pcie_core_reset,
 		.epc_features = &imx95_pcie_epc_features,
 		.mode = DW_PCIE_EP_TYPE,
 	},
-- 
2.37.1



From hongxing.zhu at nxp.com  Sun Mar 23 23:26:45 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:45 +0800
Subject: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready
In-Reply-To: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
Message-ID: <20250324062647.1891896-4-hongxing.zhu@nxp.com>

Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23
Ready Through Beacon or PERST# De-assertion

When the auxiliary power is not available, the controller cannot exit
from L23 Ready with beacon or PERST# de-assertion when main power is not
removed.

Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.

Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 0f42ab63f5ad..52aa8bd66cde 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -48,6 +48,8 @@
 #define IMX95_PCIE_SS_RW_REG_0			0xf0
 #define IMX95_PCIE_REF_CLKEN			BIT(23)
 #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
+#define IMX95_PCIE_SS_RW_REG_1			0xf4
+#define IMX95_PCIE_SYS_AUX_PWR_DET		BIT(31)
 
 #define IMX95_PE0_GEN_CTRL_1			0x1050
 #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0)
@@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
 
 static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
 {
+	/*
+	 * Workaround for ERR051624: The Controller Without Vaux Cannot
+	 * Exit L23 Ready Through Beacon or PERST# De-assertion
+	 *
+	 * When the auxiliary power is not available, the controller
+	 * cannot exit from L23 Ready with beacon or PERST# de-assertion
+	 * when main power is not removed.
+	 *
+	 * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
+	 */
+	regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
+			IMX95_PCIE_SYS_AUX_PWR_DET, IMX95_PCIE_SYS_AUX_PWR_DET);
+
 	regmap_update_bits(imx_pcie->iomuxc_gpr,
 			IMX95_PCIE_SS_RW_REG_0,
 			IMX95_PCIE_PHY_CR_PARA_SEL,
-- 
2.37.1



From hongxing.zhu at nxp.com  Sun Mar 23 23:26:46 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:46 +0800
Subject: [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN
In-Reply-To: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
Message-ID: <20250324062647.1891896-5-hongxing.zhu@nxp.com>

Workaround for ERR051586: Compliance with 8GT/s Receiver Impedance ECN.

The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is 1 which
makes receiver non-compliant with the ZRX-DC parameter for 2.5 GT/s when
operating at 8 GT/s or higher. It causes unnecessary timeout in L1.

Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.

Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 29 +++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 52aa8bd66cde..dda3eed99bb8 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -131,6 +131,7 @@ struct imx_pcie_drvdata {
 	int (*init_phy)(struct imx_pcie *pcie);
 	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
 	int (*core_reset)(struct imx_pcie *pcie, bool assert);
+	void (*post_config)(struct imx_pcie *pcie);
 	const struct dw_pcie_host_ops *ops;
 };
 
@@ -1158,6 +1159,29 @@ static void imx_pcie_disable_device(struct pci_host_bridge *bridge,
 	imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev));
 }
 
+static void imx95_pcie_post_config(struct imx_pcie *imx_pcie)
+{
+	u32 val;
+	struct dw_pcie *pci = imx_pcie->pci;
+
+	/*
+	 * Workaround for ERR051586: Compliance with 8GT/s Receiver
+	 * Impedance ECN
+	 *
+	 * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is
+	 * 1 which makes receiver non-compliant with the ZRX-DC
+	 * parameter for 2.5 GT/s when operating at 8 GT/s or higher. It
+	 * causes unnecessary timeout in L1.
+	 *
+	 * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
+	 */
+	dw_pcie_dbi_ro_wr_en(pci);
+	val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
+	val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
+	dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
+	dw_pcie_dbi_ro_wr_dis(pci);
+}
+
 static int imx_pcie_host_init(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -1222,6 +1246,9 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
 
 	imx_setup_phy_mpll(imx_pcie);
 
+	if (imx_pcie->drvdata->post_config)
+		imx_pcie->drvdata->post_config(imx_pcie);
+
 	return 0;
 
 err_phy_off:
@@ -1808,6 +1835,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
 		.core_reset = imx95_pcie_core_reset,
 		.init_phy = imx95_pcie_init_phy,
+		.post_config = imx95_pcie_post_config,
 	},
 	[IMX8MQ_EP] = {
 		.variant = IMX8MQ_EP,
@@ -1863,6 +1891,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 		.core_reset = imx95_pcie_core_reset,
 		.epc_features = &imx95_pcie_epc_features,
 		.mode = DW_PCIE_EP_TYPE,
+		.post_config = imx95_pcie_post_config,
 	},
 };
 
-- 
2.37.1



From hongxing.zhu at nxp.com  Sun Mar 23 23:26:47 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:47 +0800
Subject: [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe
In-Reply-To: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
Message-ID: <20250324062647.1891896-6-hongxing.zhu@nxp.com>

LUT(look up table) setting would be lost during PCIe suspend on i.MX95.

To let i.MX95 PCIe PM work fine, save and restore the LUT setting in
suspend and resume operations.

Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 46 +++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index dda3eed99bb8..a3a032cbaa3c 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -135,6 +135,11 @@ struct imx_pcie_drvdata {
 	const struct dw_pcie_host_ops *ops;
 };
 
+struct imx_lut_data {
+	u32 data1;
+	u32 data2;
+};
+
 struct imx_pcie {
 	struct dw_pcie		*pci;
 	struct gpio_desc	*reset_gpiod;
@@ -154,6 +159,8 @@ struct imx_pcie {
 	struct regulator	*vph;
 	void __iomem		*phy_base;
 
+	/* LUT data for pcie */
+	struct imx_lut_data	luts[IMX95_MAX_LUT];
 	/* power domain for pcie */
 	struct device		*pd_pcie;
 	/* power domain for pcie phy */
@@ -1468,6 +1475,41 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
 	}
 }
 
+static void imx_pcie_lut_save_restore(struct imx_pcie *imx_pcie, bool save)
+{
+	int i;
+	u32 data1, data2;
+
+	for (i = 0; i < IMX95_MAX_LUT; i++) {
+		if (save) {
+			regmap_write(imx_pcie->iomuxc_gpr,
+				     IMX95_PE0_LUT_ACSCTRL,
+				     IMX95_PEO_LUT_RWA | i);
+			regmap_read(imx_pcie->iomuxc_gpr,
+				    IMX95_PE0_LUT_DATA1, &data1);
+			regmap_read(imx_pcie->iomuxc_gpr,
+				    IMX95_PE0_LUT_DATA2, &data2);
+			if (data1 & IMX95_PE0_LUT_VLD) {
+				imx_pcie->luts[i].data1 = data1;
+				imx_pcie->luts[i].data2 = data2;
+			} else {
+				imx_pcie->luts[i].data1 = 0;
+				imx_pcie->luts[i].data2 = 0;
+			}
+		} else {
+			if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0)
+				continue;
+
+			regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1,
+				     imx_pcie->luts[i].data1);
+			regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2,
+				     imx_pcie->luts[i].data2);
+			regmap_write(imx_pcie->iomuxc_gpr,
+				     IMX95_PE0_LUT_ACSCTRL, i);
+		}
+	}
+}
+
 static int imx_pcie_suspend_noirq(struct device *dev)
 {
 	struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
@@ -1476,6 +1518,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)
 		return 0;
 
 	imx_pcie_msi_save_restore(imx_pcie, true);
+	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+		imx_pcie_lut_save_restore(imx_pcie, true);
 	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
 		/*
 		 * The minimum for a workaround would be to set PERST# and to
@@ -1520,6 +1564,8 @@ static int imx_pcie_resume_noirq(struct device *dev)
 		if (ret)
 			return ret;
 	}
+	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+		imx_pcie_lut_save_restore(imx_pcie, false);
 	imx_pcie_msi_save_restore(imx_pcie, false);
 
 	return 0;
-- 
2.37.1



From daniel.lezcano at linaro.org  Sun Mar 23 23:43:19 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 24 Mar 2025 07:43:19 +0100
Subject: s32 architecture upstream tree
In-Reply-To: <fa9d57de-9eb3-d317-3d39-3940248ca17a@oss.nxp.com>
References: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>
 <fa9d57de-9eb3-d317-3d39-3940248ca17a@oss.nxp.com>
Message-ID: <c16c69eb-a5c6-4b3e-a849-3b1719d26dc7@linaro.org>

On 24/03/2025 07:27, Ghennadi Procopciuc wrote:
> On 3/22/2025 1:39 PM, Daniel Lezcano wrote:
>>
>> Hi,
>>
>> the MAINTAINER file does not give the information about the location of
>> the repository for the s32.
>>
>> Where is the repo to base the work on ? Especially the device tree
>>
>> Thanks in advance
>>
>>  ? -- Daniel
>>
>>
> 
> Hi Daniel,
> 
> Shawn Guo's tree should be used for the device tree patches. Please
> refer to the 'ARM/FREESCALE IMX / MXC ARM ARCHITECTURE' entry in the
> MAINTAINERS file.

Thanks for the pointer.

I don't see the SCMI clock bindings. Who is taking care of that ?


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From ghennadi.procopciuc at oss.nxp.com  Sun Mar 23 23:48:41 2025
From: ghennadi.procopciuc at oss.nxp.com (Ghennadi Procopciuc)
Date: Mon, 24 Mar 2025 08:48:41 +0200
Subject: s32 architecture upstream tree
In-Reply-To: <c16c69eb-a5c6-4b3e-a849-3b1719d26dc7@linaro.org>
References: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>
 <fa9d57de-9eb3-d317-3d39-3940248ca17a@oss.nxp.com>
 <c16c69eb-a5c6-4b3e-a849-3b1719d26dc7@linaro.org>
Message-ID: <7139ce39-c089-5932-4d99-93e9dcc7d321@oss.nxp.com>

On 3/24/2025 8:43 AM, Daniel Lezcano wrote:
> On 24/03/2025 07:27, Ghennadi Procopciuc wrote:
>> On 3/22/2025 1:39 PM, Daniel Lezcano wrote:
>>>
>>> Hi,
>>>
>>> the MAINTAINER file does not give the information about the location of
>>> the repository for the s32.
>>>
>>> Where is the repo to base the work on ? Especially the device tree
>>>
>>> Thanks in advance
>>>
>>> ?? -- Daniel
>>>
>>>
>>
>> Hi Daniel,
>>
>> Shawn Guo's tree should be used for the device tree patches. Please
>> refer to the 'ARM/FREESCALE IMX / MXC ARM ARCHITECTURE' entry in the
>> MAINTAINERS file.
> 
> Thanks for the pointer.
> 
> I don't see the SCMI clock bindings. Who is taking care of that ?
> 
> 

Hi,

If you're referring to a header in 'include/dt-bindings', it does not
exist. The feedback was to use raw numbers [0], making the header
unnecessary.

[0]
https://lore.kernel.org/linux-arm-kernel/20240121-statutory-endurance-6d03d7e734c9 at spud/

-- 
Regards,
Ghennadi



From quic_wenbyao at quicinc.com  Sun Mar 23 23:51:16 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 14:51:16 +0800
Subject: [PATCH v1 2/3] arm64: dts: qcom: x1e80100: add bus topology for
 PCIe domain 3
In-Reply-To: <7dc8700f-0d53-45f5-bfff-2bec71c7053e@linaro.org>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <U9NTFHDe_r-uUozJFJGmc7VpxMDx39onKby4M3B_sy0jJ2fr7-iXkS801m2slu8PXanf7Y7faBxuZ8fzWiKxTg==@protonmail.internalid>
 <20250320055502.274849-3-quic_wenbyao@quicinc.com>
 <7dc8700f-0d53-45f5-bfff-2bec71c7053e@linaro.org>
Message-ID: <f4cc9d3e-0079-47a4-bee7-32221b37df65@quicinc.com>

On 3/21/2025 6:06 AM, Bryan O'Donoghue wrote:
> On 20/03/2025 05:55, Wenbin Yao wrote:
>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>
>> Add pcie3port node to represent the PCIe bridge of PCIe3 so that PCI 
>> slot
>> voltage rails can be described under this node in the board's dts.
>>
>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>> ---
>> ? arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++++++
>> ? 1 file changed, 10 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi 
>> b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> index 46b79fce9..32e8d400a 100644
>> --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> @@ -3287,6 +3287,16 @@ opp-128000000 {
>> ????????????????????? opp-peak-kBps = <15753000 1>;
>> ????????????????? };
>> ????????????? };
>> +??????????? pcie3port: pcie at 0 { 
>
> Missing newline, please check your dtb checks.

Will fix in the next version.

>
>
>> +??????????????? device_type = "pci";
>> +??????????????? compatible = "pciclass,0604";
>> +??????????????? reg = <0x0 0x0 0x0 0x0 0x0>;
>> +??????????????? bus-range = <0x01 0xff>;
>> +
>> +??????????????? #address-cells = <3>;
>> +??????????????? #size-cells = <2>;
>> +??????????????? ranges;
>> +??????????? };
>> ????????? };
>
> Why is pice3port the only port to be enabled ?
>
> What about the other ports ?

Only PCIe3 requires PCI slot power driver to power on its slots, other
ports don?t need it.

>> ????????? pcie3_phy: phy at 1be0000 {
>> -- 
>> 2.34.1
>>
>>
>
> ---
> bod

-- 
With best wishes
Wenbin



From yong.liang.choong at linux.intel.com  Sun Mar 23 23:27:42 2025
From: yong.liang.choong at linux.intel.com (Choong Yong Liang)
Date: Mon, 24 Mar 2025 14:27:42 +0800
Subject: [PATCH net-next v1 1/1] stmmac: intel: interface switching support for RPL-P platform
Message-ID: <20250324062742.462771-1-yong.liang.choong@linux.intel.com>

Based on the patch series [1], the enablement of interface switching for
RPL-P will use the same handling as ADL-N.

Link: https://patchwork.kernel.org/project/netdevbpf/cover/20250227121522.1802832-1-yong.liang.choong at linux.intel.com/ [1]

Signed-off-by: Choong Yong Liang <yong.liang.choong at linux.intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 5910571a954f..c8bb9265bbb4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -1437,7 +1437,7 @@ static const struct pci_device_id intel_eth_pci_id_table[] = {
 	{ PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_0, &adls_sgmii1g_phy0_info) },
 	{ PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_1, &adls_sgmii1g_phy1_info) },
 	{ PCI_DEVICE_DATA(INTEL, ADLN_SGMII1G, &adln_sgmii1g_phy0_info) },
-	{ PCI_DEVICE_DATA(INTEL, RPLP_SGMII1G, &tgl_sgmii1g_phy0_info) },
+	{ PCI_DEVICE_DATA(INTEL, RPLP_SGMII1G, &adln_sgmii1g_phy0_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, intel_eth_pci_id_table);
-- 
2.34.1



From ghennadi.procopciuc at oss.nxp.com  Sun Mar 23 23:27:57 2025
From: ghennadi.procopciuc at oss.nxp.com (Ghennadi Procopciuc)
Date: Mon, 24 Mar 2025 08:27:57 +0200
Subject: s32 architecture upstream tree
In-Reply-To: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>
References: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>
Message-ID: <fa9d57de-9eb3-d317-3d39-3940248ca17a@oss.nxp.com>

On 3/22/2025 1:39 PM, Daniel Lezcano wrote:
> 
> Hi,
> 
> the MAINTAINER file does not give the information about the location of
> the repository for the s32.
> 
> Where is the repo to base the work on ? Especially the device tree
> 
> Thanks in advance
> 
> ? -- Daniel
> 
> 

Hi Daniel,

Shawn Guo's tree should be used for the device tree patches. Please
refer to the 'ARM/FREESCALE IMX / MXC ARM ARCHITECTURE' entry in the
MAINTAINERS file.

-- 
Regards,
Ghennadi



From hongxing.zhu at nxp.com  Sun Mar 23 23:26:42 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:42 +0800
Subject: [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe
Message-ID: <20250324062647.1891896-1-hongxing.zhu@nxp.com>

Add some enhancements for i.MX95 PCIe.
- Refine the link procedure to speed up link training.
- Add two ERRATA SW workarounds of i.MX95 PCIe.
- Beside Power On reset, add COLD reset for i.MX95 PCIe.
- Save/retore the LUT table in supend/resume callbacks.

[PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not
[PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
[PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23
[PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s
[PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95

drivers/pci/controller/dwc/pci-imx6.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 135 insertions(+), 20 deletions(-)




From hongxing.zhu at nxp.com  Sun Mar 23 23:26:43 2025
From: hongxing.zhu at nxp.com (Richard Zhu)
Date: Mon, 24 Mar 2025 14:26:43 +0800
Subject: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required
In-Reply-To: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
Message-ID: <20250324062647.1891896-2-hongxing.zhu@nxp.com>

The current link setup procedure is more like one workaround to detect
the device behind PCIe switches on some i.MX6 platforms.

To describe more accurately, change the flag name from
IMX_PCIE_FLAG_IMX_SPEED_CHANGE to IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.

Then, start PCIe link directly when this flag is not set on i.MX7 or
later paltforms to simple and speed up link training.

Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c1f7904e3600..aa5c3f235995 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -91,7 +91,7 @@ enum imx_pcie_variants {
 };
 
 #define IMX_PCIE_FLAG_IMX_PHY			BIT(0)
-#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE		BIT(1)
+#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND	BIT(1)
 #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)
 #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3)
 #define IMX_PCIE_FLAG_HAS_APP_RESET		BIT(4)
@@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
 	u32 tmp;
 	int ret;
 
+	if (!(imx_pcie->drvdata->flags &
+	    IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
+		imx_pcie_ltssm_enable(dev);
+		return 0;
+	}
+
 	/*
 	 * Force Gen1 operation when starting the link.  In case the link is
 	 * started in Gen2 mode, there is a possibility the devices on the
@@ -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
 		dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
 		dw_pcie_dbi_ro_wr_dis(pci);
 
-		if (imx_pcie->drvdata->flags &
-		    IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
-
-			/*
-			 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
-			 * from i.MX6 family when no link speed transition
-			 * occurs and we go Gen1 -> yep, Gen1. The difference
-			 * is that, in such case, it will not be cleared by HW
-			 * which will cause the following code to report false
-			 * failure.
-			 */
-			ret = imx_pcie_wait_for_speed_change(imx_pcie);
-			if (ret) {
-				dev_err(dev, "Failed to bring link up!\n");
-				goto err_reset_phy;
-			}
+		ret = imx_pcie_wait_for_speed_change(imx_pcie);
+		if (ret) {
+			dev_err(dev, "Failed to bring link up!\n");
+			goto err_reset_phy;
 		}
 
 		/* Make sure link training is finished as well! */
@@ -1665,7 +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 	[IMX6Q] = {
 		.variant = IMX6Q,
 		.flags = IMX_PCIE_FLAG_IMX_PHY |
-			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
 			 IMX_PCIE_FLAG_BROKEN_SUSPEND |
 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
 		.dbi_length = 0x200,
@@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 	[IMX6SX] = {
 		.variant = IMX6SX,
 		.flags = IMX_PCIE_FLAG_IMX_PHY |
-			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
 		.gpr = "fsl,imx6q-iomuxc-gpr",
 		.ltssm_off = IOMUXC_GPR12,
@@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
 	[IMX6QP] = {
 		.variant = IMX6QP,
 		.flags = IMX_PCIE_FLAG_IMX_PHY |
-			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
 		.dbi_length = 0x200,
 		.gpr = "fsl,imx6q-iomuxc-gpr",
-- 
2.37.1



From quic_wenbyao at quicinc.com  Sun Mar 23 23:55:57 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 14:55:57 +0800
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for
 PCIe3
In-Reply-To: <fff943a6-4322-43d0-9821-08375bc5376c@linaro.org>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <zqBb_94gbwLzHgbAiLqgbuGg9wmeV1jUxHOsMXDdZToeTtRrtUimm8ra7GB48DXWU-ZOvC5mO8EY0uvxz46ISg==@protonmail.internalid>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com>
 <fff943a6-4322-43d0-9821-08375bc5376c@linaro.org>
Message-ID: <6964f197-07c8-469c-b4e5-710a099752b4@quicinc.com>

On 3/21/2025 6:01 AM, Bryan O'Donoghue wrote:
> On 20/03/2025 05:55, Wenbin Yao wrote:
>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>
>> Enable the pwrctrl driver, which is utilized to manage the power 
>> supplies
>> of the devices connected to the PCI slots. This ensures that the voltage
>> rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
>> on/off if they are described under PCIe port device tree node.
>>
>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>> ---
>> ? arch/arm64/configs/defconfig | 1 +
>> ? 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
>> index 85ec2fba1..de86d1121 100644
>> --- a/arch/arm64/configs/defconfig
>> +++ b/arch/arm64/configs/defconfig
>> @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
>> ? CONFIG_PCI_ENDPOINT=y
>> ? CONFIG_PCI_ENDPOINT_CONFIGFS=y
>> ? CONFIG_PCI_EPF_TEST=m
>> +CONFIG_PCI_PWRCTL_SLOT=y
>> ? CONFIG_DEVTMPFS=y
>> ? CONFIG_DEVTMPFS_MOUNT=y
>> ? CONFIG_FW_LOADER_USER_HELPER=y
>> -- 
>> 2.34.1
>>
>>
>
> PCI_PWRCTL_SLOT is a tristate symbol why be a "y" instead of an "m" 
> i.e. compile this into the kernel instead of having it be a module ?

It can be compiled as module if this is preferred.

>
> ---
> bod

-- 
With best wishes
Wenbin



From neil.armstrong at linaro.org  Sun Mar 23 23:59:48 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 24 Mar 2025 07:59:48 +0100
Subject: [PATCH 3/3] ARM: dts: amlogic: Add TCU Fernsehfee 3.0
In-Reply-To: <20250323-fernsehfee-v1-3-2621341cd37a@posteo.net>
References: <20250323-fernsehfee-v1-0-2621341cd37a@posteo.net>
 <20250323-fernsehfee-v1-3-2621341cd37a@posteo.net>
Message-ID: <c3f84f77-dc2c-447e-99cf-dedb20a2f93a@linaro.org>

On 23/03/2025 13:37, J. Neusch?fer via B4 Relay wrote:
> From: "J. Neusch?fer" <j.ne at posteo.net>
> 
> Fernsehfee[1] ("TV fairy") 3.0 is a set-top box with HDMI input and
> output ports. It originally ran Android 4.4 and a Linux 3.10 kernel.
> 
> The following features are tested and known to work:
> 
> - Ethernet
> - Power LED (switching between green and red)
> - Power button
> - eMMC
> - SD Card
> - USB
> - Wifi
> 
> The following features are untested or not working:
> 
> - HDMI input and output
> - Infrared remote control input and output
> 
> [1]: https://fernsehfee.de/ (German), https://telefairy.com/ (English)
> 
> Signed-off-by: J. Neusch?fer <j.ne at posteo.net>
> ---
>   arch/arm/boot/dts/amlogic/Makefile               |   1 +
>   arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts | 219 +++++++++++++++++++++++
>   arch/arm/boot/dts/amlogic/meson8.dtsi            |  18 ++
>   3 files changed, 238 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/amlogic/Makefile b/arch/arm/boot/dts/amlogic/Makefile
> index 504c533b1173298ec7f45099888d88b2fb74b978..3c8a1e88b386cd7fb9b5f41f47d7ff78fe7eeacc 100644
> --- a/arch/arm/boot/dts/amlogic/Makefile
> +++ b/arch/arm/boot/dts/amlogic/Makefile
> @@ -1,6 +1,7 @@
>   # SPDX-License-Identifier: GPL-2.0
>   dtb-$(CONFIG_MACH_MESON8) += \
>   	meson8-minix-neo-x8.dtb \
> +	meson8-fernsehfee3.dtb \
>   	meson8b-ec100.dtb \
>   	meson8b-mxq.dtb \
>   	meson8b-odroidc1.dtb \
> diff --git a/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts b/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts
> new file mode 100644
> index 0000000000000000000000000000000000000000..47507316ac4a56f2bcf84ad0446a06ea9fe890cd
> --- /dev/null
> +++ b/arch/arm/boot/dts/amlogic/meson8-fernsehfee3.dts
> @@ -0,0 +1,219 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +// Copyright (C) 2025 J. Neusch?fer <j.ne at posteo.net>
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/linux-event-codes.h>
> +#include <dt-bindings/leds/common.h>
> +
> +#include "meson8.dtsi"
> +
> +/ {
> +	model = "Fernsehfee 3.0";
> +	compatible = "tcu,fernsehfee3", "amlogic,meson8";
> +
> +	aliases {
> +		serial0 = &uart_AO;
> +		gpiochip0 = &gpio;
> +		gpiochip1 = &gpio_ao;
> +		i2c0 = &i2c_AO;
> +		i2c1 = &i2c_B;
> +		mmc0 = &sdhc;
> +		mmc1 = &sdio;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	memory at 0 {
> +		device_type = "memory";
> +		reg = <0x0 0x40000000>;  /* 1 GiB */
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys-polled";
> +		poll-interval = <100>;
> +
> +		power-button {
> +			label = "Power button";
> +			linux,code = <KEY_POWER>;
> +			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	leds {
> +		compatible = "gpio-leds";
> +
> +		led-0 {
> +			/*
> +			 * The power LED can be turned red, otherwise it is green.
> +			 */
> +			gpios = <&gpio_ao GPIO_TEST_N GPIO_ACTIVE_LOW>;
> +			function = LED_FUNCTION_POWER;
> +			color = <LED_COLOR_ID_RED>;
> +		};
> +	};
> +
> +	vcc_5v: regulator-5v {
> +		/* 5V rail, always on as long as the system is running */
> +		compatible = "regulator-fixed";
> +		regulator-name = "5V";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +		regulator-always-on;
> +	};
> +
> +	vcc_3v3: regulator-3v3 {
> +		/* Chipown AP2420 step-down converter */
> +		compatible = "regulator-fixed";
> +		regulator-name = "3.3V";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		vin-supply = <&vcc_5v>;
> +	};
> +
> +	vcc_1v8: regulator-1v8 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "1.8V";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +		vin-supply = <&vcc_3v3>;
> +	};
> +
> +	wifi_3v3: regulator-wifi {
> +		compatible = "regulator-fixed";
> +		regulator-name = "3.3V-WIFI";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		vin-supply = <&vcc_3v3>;
> +		gpio = <&gpio GPIOX_11 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +	};
> +};
> +
> +&ethmac {
> +	status = "okay";
> +	pinctrl-0 = <&eth_pins>;
> +	pinctrl-names = "default";
> +	phy-handle = <&eth_phy0>;
> +	phy-mode = "rmii";
> +
> +	mdio {
> +		compatible = "snps,dwmac-mdio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		eth_phy0: ethernet-phy at 0 {
> +			/* IC Plus IP101A (0x02430c54) */
> +			reg = <0>;
> +
> +			reset-assert-us = <10000>;
> +			reset-deassert-us = <10000>;
> +			reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +};
> +
> +&i2c_AO {
> +	status = "okay";
> +	pinctrl-0 = <&i2c_ao_pins>;
> +	pinctrl-names = "default";
> +
> +	pmic at 32 {
> +		compatible = "ricoh,rn5t618";
> +		reg = <0x32>;
> +		system-power-controller;
> +	};
> +
> +	eeprom at 50 {
> +		/* Fairchild FM24C08A */
> +		compatible = "atmel,24c08";
> +		reg = <0x50>;
> +		pagesize = <16>;
> +		wp-gpios = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>;
> +		num-addresses = <4>;
> +	};
> +};
> +
> +&i2c_B {
> +	status = "okay";
> +	pinctrl-0 = <&i2c_b_pins>;
> +	pinctrl-names = "default";
> +
> +	/* TODO: SiI9293 HDMI receiver @ 0x39 */
> +};
> +
> +&sdhc {
> +	status = "okay";
> +	pinctrl-0 = <&sdxc_c_pins>;
> +	pinctrl-names = "default";
> +
> +	/* eMMC */
> +	bus-width = <8>;
> +	max-frequency = <100000000>;
> +
> +	disable-wp;
> +	cap-mmc-highspeed;
> +	mmc-hs200-1_8v;
> +	no-sdio;
> +
> +	vmmc-supply = <&vcc_3v3>;
> +	vqmmc-supply = <&vcc_1v8>;
> +};
> +
> +&sdio {
> +	status = "okay";
> +	pinctrl-0 = <&sd_b_pins>;
> +
> +	/* SD card */
> +	sd_card_slot: slot at 1 {

Small NIT: no need to for a label here

> +		compatible = "mmc-slot";
> +		reg = <1>;
> +		status = "okay";
> +
> +		bus-width = <4>;
> +		cap-mmc-highspeed;
> +		cap-sd-highspeed;
> +		disable-wp;
> +
> +		cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
> +
> +		vmmc-supply = <&vcc_3v3>;
> +	};
> +};
> +
> +&uart_AO {
> +	status = "okay";
> +	pinctrl-0 = <&uart_ao_a_pins>;
> +	pinctrl-names = "default";
> +};
> +
> +&usb0 {
> +	status = "okay";
> +};
> +
> +&usb0_phy {
> +	status = "okay";
> +};
> +
> +&usb1 {
> +	status = "okay";
> +	dr_mode = "host";
> +	/*
> +	 * This bus features a Realtek RTL8188 2.4GHz WiFi module, with a
> +	 * 3.3V supply voltage that must be enabled before use.
> +	 */
> +	vbus-supply = <&wifi_3v3>;
> +};
> +
> +&usb1_phy {
> +	status = "okay";
> +};
> +
> +&ir_receiver {
> +	status = "okay";
> +	pinctrl-0 = <&ir_recv_pins>;
> +	pinctrl-names = "default";
> +};
> diff --git a/arch/arm/boot/dts/amlogic/meson8.dtsi b/arch/arm/boot/dts/amlogic/meson8.dtsi
> index 9ff142d9fe3f4576fdd3230a966c8a6250870de7..300eccbfc0071ce10290be1c496132ac6b6a4dbc 100644
> --- a/arch/arm/boot/dts/amlogic/meson8.dtsi
> +++ b/arch/arm/boot/dts/amlogic/meson8.dtsi
> @@ -477,6 +477,14 @@ gpio: bank at 80 {
>   			gpio-ranges = <&pinctrl_cbus 0 0 120>;
>   		};
>   
> +		i2c_b_pins: i2c-b {
> +			mux {
> +				groups = "i2c_sda_b", "i2c_sck_b";
> +				function = "i2c_b";
> +				bias-disable;
> +			};
> +		};
> +
>   		sd_a_pins: sd-a {
>   			mux {
>   				groups = "sd_d0_a", "sd_d1_a", "sd_d2_a",
> @@ -522,6 +530,16 @@ mux {
>   			};
>   		};
>   
> +		sdxc_c_pins: sdxc-c {
> +			mux {
> +				groups = "sdxc_d0_c", "sdxc_d13_c",
> +					"sdxc_clk_c", "sdxc_cmd_c",
> +					"sdxc_d47_c";
> +				function = "sdxc_c";
> +				bias_pull_up;
> +			};
> +		};
> +
>   		spdif_out_pins: spdif-out {
>   			mux {
>   				groups = "spdif_out";
> 

Apart that:
Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>

Thanks !
Neil


From neil.armstrong at linaro.org  Mon Mar 24 00:02:55 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 24 Mar 2025 08:02:55 +0100
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for
 xiaomi-aquaman/Mi TV Stick
In-Reply-To: <20250319190150.31529-4-funderscore@postmarketos.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
 <20250319190150.31529-4-funderscore@postmarketos.org>
Message-ID: <f36875c5-73bb-4bf8-a59f-5df30043bbbe@linaro.org>

On 19/03/2025 20:01, Ferass El Hafidi wrote:
> Xiaomi Mi TV Stick is a small Amlogic-based Android TV stick released in
> 2020.  It is known as `xiaomi-aquaman` internally.  Specifications:
>   * Amlogic S805Y SoC
>   * Android TV 9, upgradable to Android TV 10
>   * 8 GB eMMC
>   * 1 GB of RAM
>   * Wi-Fi + Bluetooth
> 
> The devicetree is based on p241's DT, with some changes to better match
> the Mi TV Stick:
>   * there is no Ethernet port, no IR, no CVBS connector on the stick
>   * a white LED is present
>   * adjust memory to have 1 GB of RAM available
> 
> Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
> ---
>   arch/arm64/boot/dts/amlogic/Makefile          |   1 +
>   .../meson-gxl-s805y-xiaomi-aquaman.dts        | 292 ++++++++++++++++++
>   .../boot/dts/amlogic/meson-gxl-s805y.dtsi     |  10 +
>   3 files changed, 303 insertions(+)
>   create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
>   create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
> 
> diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
> index 2fbda8419..0921707f1 100644
> --- a/arch/arm64/boot/dts/amlogic/Makefile
> +++ b/arch/arm64/boot/dts/amlogic/Makefile
> @@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-hub.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-libretech-ac.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-p241.dtb
> +dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805y-xiaomi-aquaman.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-libretech-pc.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-kii-pro.dtb
>   dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
> new file mode 100644
> index 000000000..42c692017
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2025 Ferass El Hafidi <funderscore at postmarketos.org>
> + * Heavily based on meson-gxl-s805x-p241.dtb:
> + *  - Copyright (c) 2018 BayLibre, SAS.
> + *    Author: Neil Armstrong <narmstrong at baylibre.com>
> + *    Author: Jerome Brunet <jbrunet at baylibre.com>
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/input/input.h>
> +#include <dt-bindings/leds/common.h>
> +#include <dt-bindings/sound/meson-aiu.h>
> +
> +#include "meson-gxl-s805y.dtsi"
> +
> +/ {
> +	compatible = "xiaomi,aquaman", "amlogic,s805y", "amlogic,meson-gxl";
> +	model = "Xiaomi Mi TV Stick (aquaman)";
> +
> +	aliases {
> +		serial0 = &uart_AO;
> +		serial1 = &uart_A;
> +	};
> +
> +	au2: analog-amplifier {
> +		compatible = "simple-audio-amplifier";
> +		sound-name-prefix = "AU2";
> +		VCC-supply = <&vcc_5v>;
> +		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	emmc_pwrseq: emmc-pwrseq {
> +		compatible = "mmc-pwrseq-emmc";
> +		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
> +	};
> +
> +	hdmi-connector {
> +		compatible = "hdmi-connector";
> +		type = "a";
> +
> +		port {
> +			hdmi_connector_in: endpoint {
> +				remote-endpoint = <&hdmi_tx_tmds_out>;
> +			};
> +		};
> +	};
> +
> +	leds {
> +		compatible = "gpio-leds";
> +
> +		led-white {
> +			color = <LED_COLOR_ID_WHITE>;
> +			function = LED_FUNCTION_POWER;
> +			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
> +			default-state = "on";
> +			panic-indicator;
> +		};
> +	};
> +
> +	memory at 0 {
> +		device_type = "memory";
> +		reg = <0x0 0x0 0x0 0x40000000>;
> +	};
> +
> +	vddio_boot: regulator-vddio-boot {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VDDIO_BOOT";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +	};
> +
> +	vddao_3v3: regulator-vddao-3v3 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VDDAO_3V3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +	};
> +
> +	vddio_ao18: regulator-vddio-ao18 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VDDIO_AO18";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +	};
> +
> +	vcc_3v3: regulator-vcc-3v3 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VCC_3V3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +	};
> +
> +	vcc_5v: regulator-vcc-5v {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VCC_5V";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +	};
> +
> +	emmc_pwrseq: emmc-pwrseq {
> +		compatible = "mmc-pwrseq-emmc";
> +		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
> +	};
> +
> +	wifi32k: wifi32k {
> +		compatible = "pwm-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
> +	};
> +
> +	sdio_pwrseq: sdio-pwrseq {
> +		compatible = "mmc-pwrseq-simple";
> +		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
> +		clocks = <&wifi32k>;
> +		clock-names = "ext_clock";
> +	};
> +
> +	sound {
> +		compatible = "amlogic,gx-sound-card";
> +		model = "XIAOMI-AQUAMAN";
> +		audio-aux-devs = <&au2>;
> +		audio-widgets = "Line", "Lineout";
> +		audio-routing = "AU2 INL", "ACODEC LOLN",
> +				"AU2 INR", "ACODEC LORN",
> +				"Lineout", "AU2 OUTL",
> +				"Lineout", "AU2 OUTR";
> +		clocks = <&clkc CLKID_MPLL0>,
> +			 <&clkc CLKID_MPLL1>,
> +			 <&clkc CLKID_MPLL2>;
> +
> +		assigned-clocks = <&clkc CLKID_MPLL0>,
> +				  <&clkc CLKID_MPLL1>,
> +				  <&clkc CLKID_MPLL2>;
> +		assigned-clock-parents = <0>, <0>, <0>;
> +		assigned-clock-rates = <294912000>,
> +				       <270950400>,
> +				       <393216000>;
> +
> +		dai-link-0 {
> +			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
> +		};
> +
> +		dai-link-1 {
> +			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
> +			dai-format = "i2s";
> +			mclk-fs = <256>;
> +
> +			codec-0 {
> +				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
> +			};
> +
> +			codec-1 {
> +				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
> +			};
> +		};
> +
> +		dai-link-2 {
> +			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
> +
> +			codec-0 {
> +				sound-dai = <&hdmi_tx>;
> +			};
> +		};
> +
> +		dai-link-3 {
> +			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
> +
> +			codec-0 {
> +				sound-dai = <&acodec>;
> +			};
> +		};
> +	};
> +};
> +
> +&acodec {
> +	AVDD-supply = <&vddio_ao18>;
> +	status = "okay";
> +};
> +
> +&aiu {
> +	status = "okay";
> +};
> +
> +&cec_AO {
> +	status = "okay";
> +	pinctrl-0 = <&ao_cec_pins>;
> +	pinctrl-names = "default";
> +	hdmi-phandle = <&hdmi_tx>;
> +};
> +
> +&hdmi_tx {
> +	status = "okay";
> +	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
> +	pinctrl-names = "default";
> +	hdmi-supply = <&vcc_5v>;
> +};
> +
> +&hdmi_tx_tmds_port {
> +	hdmi_tx_tmds_out: endpoint {
> +		remote-endpoint = <&hdmi_connector_in>;
> +	};
> +};
> +
> +&saradc {
> +	status = "okay";
> +	vref-supply = <&vddio_ao18>;
> +};
> +
> +/* Wireless SDIO Module (Amlogic W155S1 / Realtek RTL8821CS) */
> +&sd_emmc_b {
> +	status = "okay";
> +	pinctrl-0 = <&sdio_pins>;
> +	pinctrl-1 = <&sdio_clk_gate_pins>;
> +	pinctrl-names = "default", "clk-gate";
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	bus-width = <4>;
> +	cap-sd-highspeed;
> +	max-frequency = <50000000>;
> +
> +	non-removable;
> +	disable-wp;
> +
> +	/* WiFi firmware requires power to be kept while in suspend */
> +	keep-power-in-suspend;
> +
> +	mmc-pwrseq = <&sdio_pwrseq>;
> +
> +	vmmc-supply = <&vddao_3v3>;
> +	vqmmc-supply = <&vddio_boot>;
> +
> +	sdio: wifi at 1 {
> +		reg = <1>;
> +	}
> +};
> +
> +/* eMMC */
> +&sd_emmc_c {
> +	status = "okay";
> +	pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
> +	pinctrl-1 = <&emmc_clk_gate_pins>;
> +	pinctrl-names = "default", "clk-gate";
> +
> +	bus-width = <8>;
> +	cap-mmc-highspeed;
> +	max-frequency = <200000000>;
> +	non-removable;
> +	disable-wp;
> +	mmc-ddr-1_8v;
> +	mmc-hs200-1_8v;
> +
> +	mmc-pwrseq = <&emmc_pwrseq>;
> +	vmmc-supply = <&vcc_3v3>;
> +	vqmmc-supply = <&vddio_boot>;
> +};
> +
> +&pwm_ef {
> +	status = "okay";
> +	pinctrl-0 = <&pwm_e_pins>;
> +	pinctrl-names = "default";
> +};
> +
> +/*
> + * This is connected to the Bluetooth module
> + * Note: There's no driver for the Bluetooth module of some variants yet.
> + */
> +&uart_A {
> +	status = "okay";
> +	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
> +	pinctrl-names = "default";
> +	uart-has-rtscts;
> +};
> +
> +&uart_AO {
> +	status = "okay";
> +	pinctrl-0 = <&uart_ao_a_pins>;
> +	pinctrl-names = "default";
> +};
> +
> +&usb {
> +	status = "okay";
> +	dr_mode = "otg";
> +	vbus-supply = <&vcc_5v>;
> +};
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
> new file mode 100644
> index 000000000..49b29b71f
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805y.dtsi
> @@ -0,0 +1,10 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2025 Ferass El Hafidi <funderscore at postmarketos.org>
> + */
> +
> +#include "meson-gxl-s805x.dtsi"
> +
> +/ {
> +	compatible = "amlogic,s805y", "amlogic,meson-gxl";
> +};

I get:
Error: arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts:243.1-2 syntax error
FATAL ERROR: Unable to parse input tree

whil building, could you fix that ?

Neil


From neil.armstrong at linaro.org  Mon Mar 24 00:03:48 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 24 Mar 2025 08:03:48 +0100
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for
 xiaomi-aquaman/Mi TV Stick
In-Reply-To: <CAFBinCArRO-F59tOv9m27f+DV+qhy69OGUunGOAbDdfOdd5_Xg@mail.gmail.com>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
 <20250319190150.31529-4-funderscore@postmarketos.org>
 <CAFBinCArRO-F59tOv9m27f+DV+qhy69OGUunGOAbDdfOdd5_Xg@mail.gmail.com>
Message-ID: <88dbbf6e-7886-4261-ac46-55738156a5fb@linaro.org>

On 19/03/2025 23:36, Martin Blumenstingl wrote:
> Hello,
> 
> thanks for your contribution and sorry for the late reply!
> 
> On Wed, Mar 19, 2025 at 8:02?PM Ferass El Hafidi
> <funderscore at postmarketos.org> wrote:
> [...]
>> +       au2: analog-amplifier {
>> +               compatible = "simple-audio-amplifier";
>> +               sound-name-prefix = "AU2";
>> +               VCC-supply = <&vcc_5v>;
>> +               enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
>> +       };
> I couldn't find any pictures online that show an analog audio output
> (typically a 3.5mm socket).
> Can you confirm that this is really present?
> 
> [...]
>> +       sound {
>> +               compatible = "amlogic,gx-sound-card";
>> +               model = "XIAOMI-AQUAMAN";
>> +               audio-aux-devs = <&au2>;
>> +               audio-widgets = "Line", "Lineout";
>> +               audio-routing = "AU2 INL", "ACODEC LOLN",
>> +                               "AU2 INR", "ACODEC LORN",
>> +                               "Lineout", "AU2 OUTL",
>> +                               "Lineout", "AU2 OUTR";
> If there's no analog audio in/out then this section can be cleaned up
> as well - together with the references to acodec in the dai-links
> below.
> 
> [...]
>> +/* Wireless SDIO Module (Amlogic W155S1 / Realtek RTL8821CS) */
>> +&sd_emmc_b {
> question to Neil: since we know that there's two board variants out
> there (with different wifi chipsets) - are dt overlays down the road
> enough (to enable Bluetooth / wifi - depending on the chipset or board
> revision) or do we need to split the whole .dts?

Perhaps yes

Neil

> 
> 
> Best regards,
> Martin



From daniel.lezcano at linaro.org  Mon Mar 24 00:05:37 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 24 Mar 2025 08:05:37 +0100
Subject: s32 architecture upstream tree
In-Reply-To: <7139ce39-c089-5932-4d99-93e9dcc7d321@oss.nxp.com>
References: <2f686d68-4852-4aff-a551-51e8515de6e7@linaro.org>
 <fa9d57de-9eb3-d317-3d39-3940248ca17a@oss.nxp.com>
 <c16c69eb-a5c6-4b3e-a849-3b1719d26dc7@linaro.org>
 <7139ce39-c089-5932-4d99-93e9dcc7d321@oss.nxp.com>
Message-ID: <2da5156e-a793-4c97-a1f2-1d0daed2dc7d@linaro.org>

On 24/03/2025 07:48, Ghennadi Procopciuc wrote:
> On 3/24/2025 8:43 AM, Daniel Lezcano wrote:
>> On 24/03/2025 07:27, Ghennadi Procopciuc wrote:
>>> On 3/22/2025 1:39 PM, Daniel Lezcano wrote:
>>>>
>>>> Hi,
>>>>
>>>> the MAINTAINER file does not give the information about the location of
>>>> the repository for the s32.
>>>>
>>>> Where is the repo to base the work on ? Especially the device tree
>>>>
>>>> Thanks in advance
>>>>
>>>>  ?? -- Daniel
>>>>
>>>>
>>>
>>> Hi Daniel,
>>>
>>> Shawn Guo's tree should be used for the device tree patches. Please
>>> refer to the 'ARM/FREESCALE IMX / MXC ARM ARCHITECTURE' entry in the
>>> MAINTAINERS file.
>>
>> Thanks for the pointer.
>>
>> I don't see the SCMI clock bindings. Who is taking care of that ?
>>
>>
> 
> Hi,
> 
> If you're referring to a header in 'include/dt-bindings', it does not
> exist. The feedback was to use raw numbers [0], making the header
> unnecessary.

Great, even simpler !


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From neil.armstrong at linaro.org  Mon Mar 24 00:06:39 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 24 Mar 2025 08:06:39 +0100
Subject: [PATCH v5 2/3] arm64: dts: amlogic: Add A4 Reset Controller
In-Reply-To: <20250320-a4-a5-reset-v5-2-296f83bf733d@amlogic.com>
References: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
 <20250320-a4-a5-reset-v5-2-296f83bf733d@amlogic.com>
Message-ID: <e01d48c6-287b-476a-b5ca-de670375561d@linaro.org>

On 20/03/2025 10:42, Kelvin Zhang via B4 Relay wrote:
> From: Zelong Dong <zelong.dong at amlogic.com>
> 
> Add the device node and related header file for Amlogic
> A4 reset controller.
> 
> Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
> Link: https://lore.kernel.org/r/20240918074211.8067-3-zelong.dong at amlogic.com
> Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h | 93 ++++++++++++++++++++++++++
>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi    |  8 +++
>   2 files changed, 101 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..f6a4c90bab3cf7cfaa3c98c522bed5e455b73bd3
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4-reset.h
> @@ -0,0 +1,93 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
> + */
> +
> +#ifndef __DTS_AMLOGIC_A4_RESET_H
> +#define __DTS_AMLOGIC_A4_RESET_H
> +
> +/* RESET0 */
> +/*						0-3 */
> +#define RESET_USB				4
> +/*						5-6*/
> +#define RESET_U2PHY22				7
> +#define RESET_USBPHY20				8
> +#define RESET_U2PHY21				9
> +#define RESET_USB2DRD				10
> +#define RESET_U2H				11
> +#define RESET_LED_CTRL				12
> +/*						13-31 */
> +
> +/* RESET1 */
> +#define RESET_AUDIO				32
> +#define RESET_AUDIO_VAD				33
> +/*						34*/
> +#define RESET_DDR_APB				35
> +#define RESET_DDR				36
> +#define RESET_VOUT_VENC				37
> +#define RESET_VOUT				38
> +/*						39-47 */
> +#define RESET_ETHERNET				48
> +/*						49-63 */
> +
> +/* RESET2 */
> +#define RESET_DEVICE_MMC_ARB			64
> +#define RESET_IRCTRL				65
> +/*						66*/
> +#define RESET_TS_PLL				67
> +/*						68-72*/
> +#define RESET_SPICC_0				73
> +#define RESET_SPICC_1				74
> +/*						75-79*/
> +#define RESET_MSR_CLK				80
> +/*						81*/
> +#define RESET_SAR_ADC				82
> +/*						83-87*/
> +#define RESET_ACODEC				88
> +/*						89-90*/
> +#define RESET_WATCHDOG				91
> +/*						92-95*/
> +
> +/* RESET3 */
> +/*						96-127 */
> +
> +/* RESET4 */
> +/*						128-131 */
> +#define RESET_PWM_AB				132
> +#define RESET_PWM_CD				133
> +#define RESET_PWM_EF				134
> +#define RESET_PWM_GH				135
> +/*						136-137*/
> +#define RESET_UART_A				138
> +#define RESET_UART_B				139
> +/*						140*/
> +#define RESET_UART_D				141
> +#define RESET_UART_E				142
> +/*						143-144*/
> +#define RESET_I2C_M_A				145
> +#define RESET_I2C_M_B				146
> +#define RESET_I2C_M_C				147
> +#define RESET_I2C_M_D				148
> +/*						149-151*/
> +#define RESET_SDEMMC_A				152
> +/*						153*/
> +#define RESET_SDEMMC_C				154
> +/*						155-159*/
> +
> +/* RESET5 */
> +/*						160-175*/
> +#define RESET_BRG_AO_NIC_SYS			176
> +/*						177*/
> +#define RESET_BRG_AO_NIC_MAIN			178
> +#define RESET_BRG_AO_NIC_AUDIO			179
> +/*						180-183*/
> +#define RESET_BRG_AO_NIC_ALL			184
> +/*						185*/
> +#define RESET_BRG_NIC_SDIO			186
> +#define RESET_BRG_NIC_EMMC			187
> +#define RESET_BRG_NIC_DSU			188
> +#define RESET_BRG_NIC_CLK81			189
> +#define RESET_BRG_NIC_MAIN			190
> +#define RESET_BRG_NIC_ALL			191
> +
> +#endif
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> index fa80fa365f13c4a93f5577f78bf2b3369cb91cb8..6537153b3026af1bf9d1df0a196619b716553cde 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
> @@ -4,6 +4,7 @@
>    */
>   
>   #include "amlogic-a4-common.dtsi"
> +#include "amlogic-a4-reset.h"
>   #include <dt-bindings/power/amlogic,a4-pwrc.h>
>   #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
>   / {
> @@ -51,6 +52,13 @@ pwrc: power-controller {
>   };
>   
>   &apb {
> +	reset: reset-controller at 2000 {
> +		compatible = "amlogic,a4-reset",
> +			     "amlogic,meson-s4-reset";
> +		reg = <0x0 0x2000 0x0 0x98>;
> +		#reset-cells = <1>;
> +	};
> +
>   	gpio_intc: interrupt-controller at 4080 {
>   		compatible = "amlogic,a4-gpio-intc",
>   			     "amlogic,meson-gpio-intc";
> 

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From neil.armstrong at linaro.org  Mon Mar 24 00:06:47 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Mon, 24 Mar 2025 08:06:47 +0100
Subject: [PATCH v5 3/3] arm64: dts: amlogic: Add A5 Reset Controller
In-Reply-To: <20250320-a4-a5-reset-v5-3-296f83bf733d@amlogic.com>
References: <20250320-a4-a5-reset-v5-0-296f83bf733d@amlogic.com>
 <20250320-a4-a5-reset-v5-3-296f83bf733d@amlogic.com>
Message-ID: <3ca650ec-d0f2-453b-9770-5e5bbe7a75f0@linaro.org>

On 20/03/2025 10:42, Kelvin Zhang via B4 Relay wrote:
> From: Zelong Dong <zelong.dong at amlogic.com>
> 
> Add the device node and related header file for Amlogic
> A5 reset controller.
> 
> Signed-off-by: Zelong Dong <zelong.dong at amlogic.com>
> Link: https://lore.kernel.org/r/20240918074211.8067-4-zelong.dong at amlogic.com
> Signed-off-by: Kelvin Zhang <kelvin.zhang at amlogic.com>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h | 95 ++++++++++++++++++++++++++
>   arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi    |  8 +++
>   2 files changed, 103 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..cdf0f515962097c606e4c53badb19df7d21606ec
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a5-reset.h
> @@ -0,0 +1,95 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
> + */
> +
> +#ifndef __DTS_AMLOGIC_A5_RESET_H
> +#define __DTS_AMLOGIC_A5_RESET_H
> +
> +/* RESET0 */
> +/*						0-3 */
> +#define RESET_USB				4
> +/*						5-7 */
> +#define RESET_USBPHY20				8
> +/*						9 */
> +#define RESET_USB2DRD				10
> +/*						11-31 */
> +
> +/* RESET1 */
> +#define RESET_AUDIO				32
> +#define RESET_AUDIO_VAD				33
> +/*                                              34 */
> +#define RESET_DDR_APB				35
> +#define RESET_DDR				36
> +/*						37-40 */
> +#define RESET_DSPA_DEBUG			41
> +/*                                              42 */
> +#define RESET_DSPA				43
> +/*						44-46 */
> +#define RESET_NNA				47
> +#define RESET_ETHERNET				48
> +/*						49-63 */
> +
> +/* RESET2 */
> +#define RESET_ABUS_ARB				64
> +#define RESET_IRCTRL				65
> +/*						66 */
> +#define RESET_TS_PLL				67
> +/*						68-72 */
> +#define RESET_SPICC_0				73
> +#define RESET_SPICC_1				74
> +#define RESET_RSA				75
> +
> +/*						76-79 */
> +#define RESET_MSR_CLK				80
> +#define RESET_SPIFC				81
> +#define RESET_SAR_ADC				82
> +/*						83-90 */
> +#define RESET_WATCHDOG				91
> +/*						92-95 */
> +
> +/* RESET3 */
> +/*						96-127 */
> +
> +/* RESET4 */
> +#define RESET_RTC				128
> +/*						129-131 */
> +#define RESET_PWM_AB				132
> +#define RESET_PWM_CD				133
> +#define RESET_PWM_EF				134
> +#define RESET_PWM_GH				135
> +/*						104-105 */
> +#define RESET_UART_A				138
> +#define RESET_UART_B				139
> +#define RESET_UART_C				140
> +#define RESET_UART_D				141
> +#define RESET_UART_E				142
> +/*						143*/
> +#define RESET_I2C_S_A				144
> +#define RESET_I2C_M_A				145
> +#define RESET_I2C_M_B				146
> +#define RESET_I2C_M_C				147
> +#define RESET_I2C_M_D				148
> +/*						149-151 */
> +#define RESET_SDEMMC_A				152
> +/*						153 */
> +#define RESET_SDEMMC_C				154
> +/*						155-159*/
> +
> +/* RESET5 */
> +/*						160-175 */
> +#define RESET_BRG_AO_NIC_SYS			176
> +#define RESET_BRG_AO_NIC_DSPA			177
> +#define RESET_BRG_AO_NIC_MAIN			178
> +#define RESET_BRG_AO_NIC_AUDIO			179
> +/*						180-183 */
> +#define RESET_BRG_AO_NIC_ALL			184
> +#define RESET_BRG_NIC_NNA			185
> +#define RESET_BRG_NIC_SDIO			186
> +#define RESET_BRG_NIC_EMMC			187
> +#define RESET_BRG_NIC_DSU			188
> +#define RESET_BRG_NIC_SYSCLK			189
> +#define RESET_BRG_NIC_MAIN			190
> +#define RESET_BRG_NIC_ALL			191
> +
> +#endif
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
> index 32ed1776891bc7d1befd01a76c76048631606f5a..b1da8cbaa25a1844312a23bc39eb876df3c60df5 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
> @@ -4,6 +4,7 @@
>    */
>   
>   #include "amlogic-a4-common.dtsi"
> +#include "amlogic-a5-reset.h"
>   #include <dt-bindings/power/amlogic,a5-pwrc.h>
>   / {
>   	cpus {
> @@ -50,6 +51,13 @@ pwrc: power-controller {
>   };
>   
>   &apb {
> +	reset: reset-controller at 2000 {
> +		compatible = "amlogic,a5-reset",
> +			     "amlogic,meson-s4-reset";
> +		reg = <0x0 0x2000 0x0 0x98>;
> +		#reset-cells = <1>;
> +	};
> +
>   	gpio_intc: interrupt-controller at 4080 {
>   		compatible = "amlogic,a5-gpio-intc",
>   			     "amlogic,meson-gpio-intc";
> 

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From quic_wenbyao at quicinc.com  Mon Mar 24 00:09:54 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 15:09:54 +0800
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for
 PCIe3
In-Reply-To: <CAMRc=MfZrRp=VuEOLuMY_04JdyRrD+joGL56LwRFQ-+D-8Z_6w@mail.gmail.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com>
 <694b6638-92b2-4ac0-a175-bd29aea6cba9@kernel.org>
 <CAMRc=MfZrRp=VuEOLuMY_04JdyRrD+joGL56LwRFQ-+D-8Z_6w@mail.gmail.com>
Message-ID: <9ea8fe39-b818-403b-bd69-815e58eb2949@quicinc.com>

On 3/21/2025 5:43 PM, Bartosz Golaszewski wrote:
> On Fri, Mar 21, 2025 at 8:37?AM Krzysztof Kozlowski <krzk at kernel.org> wrote:
>> On 20/03/2025 06:55, Wenbin Yao wrote:
>>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>>
>>> Enable the pwrctrl driver, which is utilized to manage the power supplies
>>> of the devices connected to the PCI slots. This ensures that the voltage
>>> rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
>>> on/off if they are described under PCIe port device tree node.
>>>
>>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>>> ---
>>>   arch/arm64/configs/defconfig | 1 +
>>>   1 file changed, 1 insertion(+)
>>>
>>> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
>>> index 85ec2fba1..de86d1121 100644
>>> --- a/arch/arm64/configs/defconfig
>>> +++ b/arch/arm64/configs/defconfig
>>> @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
>>>   CONFIG_PCI_ENDPOINT=y
>>>   CONFIG_PCI_ENDPOINT_CONFIGFS=y
>>>   CONFIG_PCI_EPF_TEST=m
>>> +CONFIG_PCI_PWRCTL_SLOT=y
>> Bartosz,
>>
>> Wasn't the intention to select it the same way as PCI_PWRCTL_PWRSEQ is
>> selected?
>>
>> Best regards,
>> Krzysztof
>>
> For sure. I would expect there to be something like:
>
> select PCI_PWRCTL_SLOT if ARCH_QCOM
>
> in Kconfig and nothing in defconfig.
>
> Bartosz

IIUC, pci slot power driver is a common driver that could be used by all DT
based platform.

-- 
With best wishes
Wenbin



From alexander.stein at ew.tq-group.com  Mon Mar 24 00:10:59 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 24 Mar 2025 08:10:59 +0100
Subject: [PATCH 1/2] arm64: dts: imx8mp-tqma8mpql-mba8mp-ras314: Add LVDS device tree overlay
Message-ID: <20250324071102.23765-1-alexander.stein@ew.tq-group.com>

From: Martin Schmiedel <Martin.Schmiedel at tq-group.com>

This adds an overlay for the supported LVDS display tianma tm070jvhg33.
The LVDS interface is the same as for MBa8MPxL so the already existing
overlay can be reused on this platform.

Signed-off-by: Martin Schmiedel <Martin.Schmiedel at tq-group.com>
Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 arch/arm64/boot/dts/freescale/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index b6d3fe26d6212..d7ac8dda4bde5 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -247,8 +247,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-pcie-ep.dtb
 
 imx8mp-tqma8mpql-mba8mpxl-lvds-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo
 imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtbo
+imx8mp-tqma8mpql-mba8mp-ras314-lvds-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo
 dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-lvds.dtb
 
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb
-- 
2.43.0



From alexander.stein at ew.tq-group.com  Mon Mar 24 00:11:00 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 24 Mar 2025 08:11:00 +0100
Subject: [PATCH 2/2] arm64: dts: imx8mp-tqma8mpql-mba8mp-ras314: Add Raspberry Pi Camera V2 overlay
In-Reply-To: <20250324071102.23765-1-alexander.stein@ew.tq-group.com>
References: <20250324071102.23765-1-alexander.stein@ew.tq-group.com>
Message-ID: <20250324071102.23765-2-alexander.stein@ew.tq-group.com>

This overlay configures IMX219 MIPI-CSI-2 camera attached to ISP1.
Also add additional overlay both using LVDS display and camera.

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
 arch/arm64/boot/dts/freescale/Makefile        |   4 +
 ...imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtso | 107 ++++++++++++++++++
 2 files changed, 111 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtso

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index d7ac8dda4bde5..b5cd2efd260cb 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -247,10 +247,14 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-pcie-ep.dtb
 
 imx8mp-tqma8mpql-mba8mpxl-lvds-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo
 imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtbo
+imx8mp-tqma8mpql-mba8mp-ras314-imx219-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtbo
 imx8mp-tqma8mpql-mba8mp-ras314-lvds-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo
+imx8mp-tqma8mpql-mba8mp-ras314-lvds-imx219-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtbo
 dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-lvds.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-lvds-imx219.dtb
 
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtso
new file mode 100644
index 0000000000000..0bc96d242f33f
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtso
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2022-2025 TQ-Systems GmbH <linux at ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/video-interfaces.h>
+
+#include "imx8mp-pinfunc.h"
+
+&{/} {
+	/*
+	 * The three camera regulators are controlled by a single GPIO. Declare
+	 * a single regulator for the three supplies.
+	 */
+	reg_cam: regulator-cam {
+		compatible = "regulator-fixed";
+		regulator-name = "reg_cam";
+		/* pad muxing already done in gpio2grp */
+		gpio = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&reg_vcc_3v3>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	cam24m: cam24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "cam24m";
+	};
+};
+
+&i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	camera at 1a {
+		compatible = "sony,imx219";
+		reg = <0x10>;
+		clocks = <&cam24m>;
+		VANA-supply = <&reg_cam>;
+		VDIG-supply = <&reg_cam>;
+		VDDL-supply = <&reg_cam>;
+		orientation = <2>;
+		rotation = <0>;
+
+		port {
+			sony_imx219: endpoint {
+				remote-endpoint = <&imx8mp_mipi_csi_in>;
+				clock-lanes = <0>;
+				clock-noncontinuous;
+				data-lanes = <1 2>;
+				link-frequencies = /bits/ 64 <456000000>;
+			};
+		};
+	};
+};
+
+&isi_0 {
+	status = "disabled";
+
+	ports {
+		port at 0 {
+			/delete-node/ endpoint;
+		};
+	};
+};
+
+&isp_0 {
+	status = "okay";
+
+	ports {
+		port at 1 {
+			isp0_in: endpoint {
+				bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
+				remote-endpoint = <&mipi_csi_0_out>;
+			};
+		};
+	};
+};
+
+&mipi_csi_0 {
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			imx8mp_mipi_csi_in: endpoint {
+				remote-endpoint = <&sony_imx219>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&mipi_csi_0_out {
+	remote-endpoint = <&isp0_in>;
+};
-- 
2.43.0



From quic_wenbyao at quicinc.com  Mon Mar 24 00:11:58 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 15:11:58 +0800
Subject: [PATCH v1 2/3] arm64: dts: qcom: x1e80100: add bus topology for
 PCIe domain 3
In-Reply-To: <hgvfxxjvquh3tn543ae44o3lie3pwld5snbewy2lxcrtgd4raa@eyfm57omt3ge>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-3-quic_wenbyao@quicinc.com>
 <hgvfxxjvquh3tn543ae44o3lie3pwld5snbewy2lxcrtgd4raa@eyfm57omt3ge>
Message-ID: <0df07b23-4821-4b7d-85d8-dfaa7516fbc4@quicinc.com>

On 3/22/2025 1:19 AM, Dmitry Baryshkov wrote:
> On Thu, Mar 20, 2025 at 01:55:01PM +0800, Wenbin Yao wrote:
>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>
>> Add pcie3port node to represent the PCIe bridge of PCIe3 so that PCI slot
>> voltage rails can be described under this node in the board's dts.
>>
>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>> ---
>>   arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++++++
>>   1 file changed, 10 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> index 46b79fce9..32e8d400a 100644
>> --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
>> @@ -3287,6 +3287,16 @@ opp-128000000 {
>>   					opp-peak-kBps = <15753000 1>;
>>   				};
>>   			};
>> +			pcie3port: pcie at 0 {
> Empty line between nodes, please.

Will fix in the next version.

>
>> +				device_type = "pci";
>> +				compatible = "pciclass,0604";
>> +				reg = <0x0 0x0 0x0 0x0 0x0>;
>> +				bus-range = <0x01 0xff>;
>> +
>> +				#address-cells = <3>;
>> +				#size-cells = <2>;
>> +				ranges;
>> +			};
>>   		};
>>   
>>   		pcie3_phy: phy at 1be0000 {
>> -- 
>> 2.34.1
>>
-- 
With best wishes
Wenbin



From mazziesaccount at gmail.com  Mon Mar 24 00:12:17 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 24 Mar 2025 09:12:17 +0200
Subject: [PATCH v10 0/8] Support ROHM BD79124 ADC
Message-ID: <cover.1742560649.git.mazziesaccount@gmail.com>

Support ROHM BD79124 ADC.

This series adds also couple of IIO ADC helper functions for parsing the
channel information from the device tree. There are also new helpers
included for iterating and counting firmware child nodes with a specific
name.

The rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.

There has been some discussion about how useful these ADC helpers are,
and whether they should support also differential and single ended channel
configurations. This version does not include support for those - with the
benefit of reduced complexity and easier to use API.

NOTE: The rzg2l_adc and the sun20i-gpadc are untested as I lack of relevant
HW. They have been compile tested only.

The ROHM BD79124 ADC itself is quite usual stuff. 12-bit, 8-channel ADC
with threshold monitoring.

Except that:
 - each ADC input pin can be configured as a general purpose output.
 - manually starting an ADC conversion and reading the result would
   require the I2C _master_ to do clock stretching(!) for the duration
   of the conversion... Let's just say this is not well supported.
 - IC supports 'autonomous measurement mode' and storing latest results
   to the result registers. This mode is used by the driver due to the
   "peculiar" I2C when doing manual reads.

Furthermore, the ADC uses this continuous autonomous measuring,
and the IC keeps producing new 'out of window' IRQs if measurements are
out of window - the driver disables the event for 1 seconds when sending
it to user. This prevents generating storm of events

Revision history:
v9 => v10:
 BD79124 driver fixes as suggested by Andy:
   - Use regmap_assign_bits()
   - dont change the mask for caller in bd79124gpo_set_multiple()
   - styling

v8 => v9:
 - Drop the gianfar and the thp7312 drivers from the series to limit the
   review noise and to simplify the merging. They can be submitted later
   as separate changes.
 - Drop the fwnode_for_each_available_named_child() as suggested by
   Sakari.
 - BD79124 driver styling and fixes

v7 => v8:
  property helpers:
    - Fix the example in fwnode_get_named_child_node_count() documentation
      to use the fwnode_get_named_child_node_count() and not the
      device_get_named_child_node_count()
    - Fix the rest of the new macro's indentiations
  adc helpers:
    - Treat 0 ADC channels as an error in
      devm_iio_adc_device_alloc_chaninfo_se().
  rzg2l_adc / sun20i-gpadc:
    - Drop zero channels check from the ADC drivers using
      devm_iio_adc_device_alloc_chaninfo_se()
  BD79124:
    - Use unsigned for regmap values
    - Commit message fine tuning
    - Check devm_mutex_init() return value
    - Handle 'ALL pins as ADC or GPO' cleanly in BD79124 driver
    - BD79124 styling / typofixes

v6 => v7:
 - Inline device_get_named_child_node_count()
 - Fix kernel-doc for fwnode_get_named_child_node_count()
 - Minor styling fixes
 More accurate changelog in individual patches.

v5 => v6:
 - Drop applied patch
 - Add *_for_each_named_child_* iterators
 - Add a patch converting the thp7312 driver to use the new helper
 - Styling and minor things pointed by reviewers

v4 => v5: Fixes as per various review comments. Most notably:
 - Drop the patch making the TI's ADC driver to respect device tree.
 - Add (RFC) patch converting gianfar driver to use new name child-node
   counting API as suggested by Andy.
 - Add fwnode_get_child_node_count_named() as suggested by Rob.
 - rebase to v6.14-rc5
 More accurate changelog in individual patches.

v3 => v4:
 - Drop the ADC helper support for differential channels
 - Drop the ADC helper for getting only channel IDs by fwnode.
 - "Promote" the function counting the number of child nodes with a
   specific name to the property.h (As suggested by Jonathan).
 - Add ADC helpers to a namespace.
 - Rebase on v6.14-rc3
 - More minor changes described in individual patches.

v2 => v3:
 - Restrict BD79124 channel numbers as suggested by Conor and add
   Conor's Reviewed-by tag.
 - Support differential and single-ended inputs
 - Convert couple of existing drivers to use the added ADC helpers
 - Minor fixes based on reviews
Link to v2:
https://lore.kernel.org/all/cover.1738761899.git.mazziesaccount at gmail.com/

RFC v1 => v2:
 - Drop MFD and pinmux.
 - Automatically re-enable events after 1 second.
 - Export fwnode parsing helpers for finding the ADC channels.

---

Matti Vaittinen (8):
  dt-bindings: ROHM BD79124 ADC/GPO
  property: Add functions to iterate named child
  iio: adc: add helpers for parsing ADC nodes
  iio: adc: rzg2l_adc: Use adc-helpers
  iio: adc: sun20i-gpadc: Use adc-helpers
  iio: adc: Support ROHM BD79124 ADC
  MAINTAINERS: Add IIO ADC helpers
  MAINTAINERS: Add ROHM BD79124 ADC/GPO

 .../bindings/iio/adc/rohm,bd79124.yaml        |  114 ++
 MAINTAINERS                                   |   12 +
 drivers/base/property.c                       |   27 +
 drivers/iio/adc/Kconfig                       |   17 +
 drivers/iio/adc/Makefile                      |    3 +
 drivers/iio/adc/industrialio-adc.c            |   82 ++
 drivers/iio/adc/rohm-bd79124.c                | 1147 +++++++++++++++++
 drivers/iio/adc/rzg2l_adc.c                   |   39 +-
 drivers/iio/adc/sun20i-gpadc-iio.c            |   39 +-
 include/linux/iio/adc-helpers.h               |   27 +
 include/linux/property.h                      |   20 +
 11 files changed, 1479 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 drivers/iio/adc/rohm-bd79124.c
 create mode 100644 include/linux/iio/adc-helpers.h


base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
-- 
2.49.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/b30c709d/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 24 00:12:50 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 24 Mar 2025 09:12:50 +0200
Subject: [PATCH v10 2/8] property: Add functions to iterate named child
In-Reply-To: <cover.1742560649.git.mazziesaccount@gmail.com>
References: <cover.1742560649.git.mazziesaccount@gmail.com>
Message-ID: <2767173b7b18e974c0bac244688214bd3863ff06.1742560649.git.mazziesaccount@gmail.com>

There are a few use-cases where child nodes with a specific name need to
be parsed. Code like:

fwnode_for_each_child_node()
	if (fwnode_name_eq())
		...

can be found from a various drivers/subsystems. Adding a macro for this
can simplify things a bit.

In a few cases the data from the found nodes is later added to an array,
which is allocated based on the number of found nodes. One example of
such use is the IIO subsystem's ADC channel nodes, where the relevant
nodes are named as channel[@N].

Add helpers for iterating and counting device's sub-nodes with certain
name instead of open-coding this in every user.

Suggested-by: Jonathan Cameron <jic23 at kernel.org>
Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
Reviewed-by: Marcelo Schmitt <marcelo.schmitt1 at gmail.com>
---
Revision history:
v9 =>
 - No changes
v8 => v9:
 - Drop the fwnode_for_each_available_named_child_node() as suggested
   by Sakari during v8 review:
   https://lore.kernel.org/all/Z9mQPJwnKAkPHriT at kekkonen.localdomain/
v7 => v8:
 - Fix the example in fwnode_get_named_child_node_count() documentation
   to use the fwnode_get_named_child_node_count() and not the
   device_get_named_child_node_count()
 - Fix the rest of the new macro's indentiations
v6 => v7:
 - Improve kerneldoc
 - Inline device_get_named_child_node_count() and change it to call
   fwnode_get_named_child_node_count() inside
 - Fix indentiation of the new macros
v5 => v6:
 - Add helpers to also iterate through the nodes.
v4 => v5:
 - Use given name instead of string 'channel' when counting the nodes
 - Add also fwnode_get_child_node_count_named() as suggested by Rob.
v3 => v4:
 - New patch as suggested by Jonathan, see discussion in:
https://lore.kernel.org/lkml/20250223161338.5c896280 at jic23-huawei/
---
 drivers/base/property.c  | 27 +++++++++++++++++++++++++++
 include/linux/property.h | 20 ++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index c1392743df9c..f42f32ff45fc 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -945,6 +945,33 @@ unsigned int device_get_child_node_count(const struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_child_node_count);
 
+/**
+ * fwnode_get_named_child_node_count - number of child nodes with given name
+ * @fwnode: Node which child nodes are counted.
+ * @name: String to match child node name against.
+ *
+ * Scan child nodes and count all the nodes with a specific name. Potential
+ * 'number' -ending after the 'at sign' for scanned names is ignored.
+ * E.g.::
+ *   fwnode_get_named_child_node_count(fwnode, "channel");
+ * would match all the nodes::
+ *   channel { }, channel at 0 {}, channel at 0xabba {}...
+ *
+ * Return: the number of child nodes with a matching name for a given device.
+ */
+unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
+					       const char *name)
+{
+	struct fwnode_handle *child;
+	unsigned int count = 0;
+
+	fwnode_for_each_named_child_node(fwnode, child, name)
+		count++;
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_named_child_node_count);
+
 bool device_dma_supported(const struct device *dev)
 {
 	return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
diff --git a/include/linux/property.h b/include/linux/property.h
index e214ecd241eb..3e83babac0b0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -167,6 +167,10 @@ struct fwnode_handle *fwnode_get_next_available_child_node(
 	for (child = fwnode_get_next_child_node(fwnode, NULL); child;	\
 	     child = fwnode_get_next_child_node(fwnode, child))
 
+#define fwnode_for_each_named_child_node(fwnode, child, name)		\
+	fwnode_for_each_child_node(fwnode, child)			\
+		if (!fwnode_name_eq(child, name)) { } else
+
 #define fwnode_for_each_available_child_node(fwnode, child)		       \
 	for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
 	     child = fwnode_get_next_available_child_node(fwnode, child))
@@ -178,11 +182,19 @@ struct fwnode_handle *device_get_next_child_node(const struct device *dev,
 	for (child = device_get_next_child_node(dev, NULL); child;	\
 	     child = device_get_next_child_node(dev, child))
 
+#define device_for_each_named_child_node(dev, child, name)		\
+	device_for_each_child_node(dev, child)				\
+		if (!fwnode_name_eq(child, name)) { } else
+
 #define device_for_each_child_node_scoped(dev, child)			\
 	for (struct fwnode_handle *child __free(fwnode_handle) =	\
 		device_get_next_child_node(dev, NULL);			\
 	     child; child = device_get_next_child_node(dev, child))
 
+#define device_for_each_named_child_node_scoped(dev, child, name)	\
+	device_for_each_child_node_scoped(dev, child)			\
+		if (!fwnode_name_eq(child, name)) { } else
+
 struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
 						  const char *childname);
 struct fwnode_handle *device_get_named_child_node(const struct device *dev,
@@ -210,6 +222,14 @@ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
 
 unsigned int device_get_child_node_count(const struct device *dev);
 
+unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
+					       const char *name);
+static inline unsigned int device_get_named_child_node_count(const struct device *dev,
+							     const char *name)
+{
+	return fwnode_get_named_child_node_count(dev_fwnode(dev), name);
+}
+
 static inline int device_property_read_u8(const struct device *dev,
 					  const char *propname, u8 *val)
 {
-- 
2.49.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/e0b0c425/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 24 00:13:03 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 24 Mar 2025 09:13:03 +0200
Subject: [PATCH v10 3/8] iio: adc: add helpers for parsing ADC nodes
In-Reply-To: <cover.1742560649.git.mazziesaccount@gmail.com>
References: <cover.1742560649.git.mazziesaccount@gmail.com>
Message-ID: <f1d8b3e15237947738912c0d297b3e1e21d8b03e.1742560649.git.mazziesaccount@gmail.com>

There are ADC ICs which may have some of the AIN pins usable for other
functions. These ICs may have some of the AIN pins wired so that they
should not be used for ADC.

(Preferred?) way for marking pins which can be used as ADC inputs is to
add corresponding channels at N nodes in the device tree as described in
the ADC binding yaml.

Add couple of helper functions which can be used to retrieve the channel
information from the device node.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

---
Revision history:
v8 =>
 - No changes
v7 => v8:
 devm_iio_adc_device_alloc_chaninfo_se():
 - Treat all negative values for the max ID as 'don't care'
 - Return -ENOENT instead of '0' if no channels were found.
v5 => v6:
 - Adapt to changed fwnode helper names
 - Fix spelling
v4 => v5:
 - Inline iio_adc_device_num_channels()
 - Fix Indenting function parameters
 - Combine the max channel ID checks.
v3 => v4:
 - Drop diff-channel support
 - Drop iio_adc_device_channels_by_property()
 - Add IIO_DEVICE namespace
 - Move industrialio-adc.o to top of the Makefile
 - Some styling as suggested by Andy
 - Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
 - Support differential and single-ended channels
 - Rename iio_adc_device_get_channels() as
   iio_adc_device_channels_by_property()
 - Improve spelling
 - Drop support for cases where DT comes from parent device's node
 - Decrease loop indent by reverting node name check conditions
 - Don't set 'chan->indexed' by number of channels to keep the
   interface consistent no matter how many channels are connected.
 - Fix ID range check and related comment
RFC v1 => v2:
 - New patch
---
 drivers/iio/adc/Kconfig            |  3 ++
 drivers/iio/adc/Makefile           |  2 +
 drivers/iio/adc/industrialio-adc.c | 82 ++++++++++++++++++++++++++++++
 include/linux/iio/adc-helpers.h    | 27 ++++++++++
 4 files changed, 114 insertions(+)
 create mode 100644 drivers/iio/adc/industrialio-adc.c
 create mode 100644 include/linux/iio/adc-helpers.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 849c90203071..37b70a65da6f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -6,6 +6,9 @@
 
 menu "Analog to digital converters"
 
+config IIO_ADC_HELPER
+	tristate
+
 config AB8500_GPADC
 	bool "ST-Ericsson AB8500 GPADC driver"
 	depends on AB8500_CORE && REGULATOR_AB8500
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ee19afba62b7..1c410f483029 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -3,6 +3,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
+
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c
new file mode 100644
index 000000000000..b4057230e749
--- /dev/null
+++ b/drivers/iio/adc/industrialio-adc.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Helpers for parsing common ADC information from a firmware node.
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include <linux/iio/adc-helpers.h>
+#include <linux/iio/iio.h>
+
+/**
+ * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC
+ *
+ * Scan the device node for single-ended ADC channel information. Channel ID is
+ * expected to be found from the "reg" property. Allocate and populate the
+ * iio_chan_spec structure corresponding to channels that are found. The memory
+ * for iio_chan_spec structure will be freed upon device detach.
+ *
+ * @dev:		Pointer to the ADC device.
+ * @template:		Template iio_chan_spec from which the fields of all
+ *			found and allocated channels are initialized.
+ * @max_chan_id:	Maximum value of a channel ID. Use negative value if no
+ *			checking is required.
+ * @cs:			Location where pointer to allocated iio_chan_spec
+ *			should be stored.
+ *
+ * Return:	Number of found channels on success. Negative value to indicate
+ *		failure. Specifically, -ENOENT if no channel nodes were found.
+ */
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs)
+{
+	struct iio_chan_spec *chan_array, *chan;
+	int num_chan, ret;
+
+	num_chan = iio_adc_device_num_channels(dev);
+	if (num_chan < 0)
+		return num_chan;
+
+	if (!num_chan)
+		return -ENOENT;
+
+	chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array),
+				  GFP_KERNEL);
+	if (!chan_array)
+		return -ENOMEM;
+
+	chan = &chan_array[0];
+
+	device_for_each_named_child_node_scoped(dev, child, "channel") {
+		u32 ch;
+
+		ret = fwnode_property_read_u32(child, "reg", &ch);
+		if (ret)
+			return ret;
+
+		if (max_chan_id >= 0 && ch > max_chan_id)
+			return -ERANGE;
+
+		*chan = *template;
+		chan->channel = ch;
+		chan++;
+	}
+
+	*cs = chan_array;
+
+	return num_chan;
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount at gmail.com>");
+MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers");
diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h
new file mode 100644
index 000000000000..56b092a2a4c4
--- /dev/null
+++ b/include/linux/iio/adc-helpers.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * The industrial I/O ADC firmware property parsing helpers
+ *
+ * Copyright (c) 2025 Matti Vaittinen <mazziesaccount at gmail.com>
+ */
+
+#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_
+#define _INDUSTRIAL_IO_ADC_HELPERS_H_
+
+#include <linux/property.h>
+
+struct device;
+struct iio_chan_spec;
+
+static inline int iio_adc_device_num_channels(struct device *dev)
+{
+	return device_get_named_child_node_count(dev, "channel");
+}
+
+int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev,
+					  const struct iio_chan_spec *template,
+					  int max_chan_id,
+					  struct iio_chan_spec **cs);
+
+#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
-- 
2.49.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/06764872/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 24 00:13:28 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 24 Mar 2025 09:13:28 +0200
Subject: [PATCH v10 5/8] iio: adc: sun20i-gpadc: Use adc-helpers
In-Reply-To: <cover.1742560649.git.mazziesaccount@gmail.com>
References: <cover.1742560649.git.mazziesaccount@gmail.com>
Message-ID: <e367a803c0d625e60c9fca16c55a25eee06b5a89.1742560649.git.mazziesaccount@gmail.com>

The new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to
help drivers avoid open-coding the for_each_node -loop for getting the
channel IDs. The helper provides standard way to detect the ADC channel
nodes (by the node name), and a standard way to convert the "reg"
-properties to channel identification numbers, used in the struct
iio_chan_spec. Furthermore, the helper can optionally check the found
channel IDs are smaller than given maximum. This is useful for callers
which later use the IDs for example for indexing a channel data array.

The original driver treated all found child nodes as channel nodes. The
new helper requires channel nodes to be named channel[@N]. This should
help avoid problems with devices which may contain also other but ADC
child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible
string didn't reveal any in-tree .dts with channel nodes named
otherwise. Also, same grep shows all the in-tree .dts seem to have
channel IDs between 0..num of channels.

Use the new helper.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

---
NOTE: This change now drops a print "no channel children" which used to
be printed if no channel nodes were found. It also changes the return
value from -ENODEV to -ENOENT.

Revision history:
v8 =>
 - No changes
v7 => v8:
 - drop explicit "no channels check". It is now done inside the
   devm_iio_adc_device_alloc_chaninfo_se().
v6 => v7:
 - Fix function name in the commit message
v5 => v6:
 - Commit message typofix
v4 => v5:
 - Drop the diff-channel stuff from the commit message
v3 => v4:
 - Adapt to 'drop diff-channel support' changes to ADC-helpers
 - select ADC helpers in the Kconfig
v2 => v3:
 - New patch

I picked the sun20i-gpadc in this series because it has a straightforward
approach for populating the struct iio_chan_spec. Everything else except
the .channel can use 'template'-data.

This makes the sun20i-gpadc well suited to be an example user of this new
helper. I hope this patch helps to evaluate whether these helpers are worth
the hassle.

The change is compile tested only!! Testing before applying is highly
appreciated (as always!). Also, even though I tried to audit the dts
files for the reg-properties in the channel nodes, use of references
didn't make it easy. I can't guarantee I didn't miss anything.
---
 drivers/iio/adc/Kconfig            |  1 +
 drivers/iio/adc/sun20i-gpadc-iio.c | 39 +++++++++++-------------------
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e4933de0c366..0993008a1586 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC
 config SUN20I_GPADC
 	tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
 	depends on ARCH_SUNXI || COMPILE_TEST
+	select IIO_ADC_HELPER
 	help
 	  Say yes here to build support for Allwinner (D1, T113, T507 and R329)
 	  SoCs GPADC. This ADC provides up to 16 channels.
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 136b8d9c294f..2428ea69d676 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/reset.h>
 
+#include <linux/iio/adc-helpers.h>
 #include <linux/iio/iio.h>
 
 #define SUN20I_GPADC_DRIVER_NAME	"sun20i-gpadc"
@@ -149,36 +150,23 @@ static void sun20i_gpadc_reset_assert(void *data)
 	reset_control_assert(rst);
 }
 
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+	.type = IIO_VOLTAGE,
+	.indexed = 1,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
 static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
 				       struct device *dev)
 {
-	unsigned int channel;
-	int num_channels, i, ret;
+	int num_channels;
 	struct iio_chan_spec *channels;
 
-	num_channels = device_get_child_node_count(dev);
-	if (num_channels == 0)
-		return dev_err_probe(dev, -ENODEV, "no channel children\n");
-
-	channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
-				GFP_KERNEL);
-	if (!channels)
-		return -ENOMEM;
-
-	i = 0;
-	device_for_each_child_node_scoped(dev, node) {
-		ret = fwnode_property_read_u32(node, "reg", &channel);
-		if (ret)
-			return dev_err_probe(dev, ret, "invalid channel number\n");
-
-		channels[i].type = IIO_VOLTAGE;
-		channels[i].indexed = 1;
-		channels[i].channel = channel;
-		channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-		channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
-		i++;
-	}
+	num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev,
+				&sun20i_gpadc_chan_template, -1, &channels);
+	if (num_channels < 0)
+		return num_channels;
 
 	indio_dev->channels = channels;
 	indio_dev->num_channels = num_channels;
@@ -271,3 +259,4 @@ module_platform_driver(sun20i_gpadc_driver);
 MODULE_DESCRIPTION("ADC driver for sunxi platforms");
 MODULE_AUTHOR("Maksim Kiselev <bigunclemax at gmail.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DRIVER");
-- 
2.49.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/b82e46f6/attachment.sig>

From mazziesaccount at gmail.com  Mon Mar 24 00:13:56 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Mon, 24 Mar 2025 09:13:56 +0200
Subject: [PATCH v10 7/8] MAINTAINERS: Add IIO ADC helpers
In-Reply-To: <cover.1742560649.git.mazziesaccount@gmail.com>
References: <cover.1742560649.git.mazziesaccount@gmail.com>
Message-ID: <1263c954cfb74223f322a9c31bd57f13d5516680.1742560649.git.mazziesaccount@gmail.com>

Add undersigned as a maintainer for the IIO ADC helpers.

Signed-off-by: Matti Vaittinen <mazziesaccount at gmail.com>
---
Revision history:
v2 =>
 - No changes
RFC v1 => v2:
 - New patch
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8e0736dc2ee0..5b96fb864227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11208,6 +11208,13 @@ L:	linux-media at vger.kernel.org
 S:	Maintained
 F:	drivers/media/rc/iguanair.c
 
+IIO ADC HELPERS
+M:	Matti Vaittinen <mazziesaccount at gmail.com>
+L:	linux-iio at vger.kernel.org
+S:	Maintained
+F:	drivers/iio/adc/industrialio-adc.c
+F:	include/linux/iio/adc-helpers.h
+
 IIO BACKEND FRAMEWORK
 M:	Nuno Sa <nuno.sa at analog.com>
 R:	Olivier Moysan <olivier.moysan at foss.st.com>
-- 
2.49.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/c929f0f8/attachment.sig>

From quic_wenbyao at quicinc.com  Mon Mar 24 00:13:54 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 15:13:54 +0800
Subject: [PATCH v1 3/3] arm64: dts: qcom: x1e80100-qcp: Add power control
 and sideband signals for PCIe3
In-Reply-To: <8379e009-9619-4c2b-986a-8ccb9ebaa083@kernel.org>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-4-quic_wenbyao@quicinc.com>
 <8379e009-9619-4c2b-986a-8ccb9ebaa083@kernel.org>
Message-ID: <7707be54-5b42-42ea-b957-811fc45233c6@quicinc.com>

On 3/21/2025 3:39 PM, Krzysztof Kozlowski wrote:
> On 20/03/2025 06:55, Wenbin Yao wrote:
>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>
>> Add perst, wake and clkreq sideband signals and required regulators in
>> PCIe3 controller and PHY device tree node. Describe the voltage rails of
>> the x8 PCI slots for PCIe3 port.
>>
>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>> ---
>>   arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
>>   1 file changed, 119 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> index 28086a2bc..9cd313802 100644
>> --- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> +++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> @@ -318,6 +318,48 @@ vreg_wcn_3p3: regulator-wcn-3p3 {
>>   		regulator-boot-on;
>>   	};
>>   
>> +	vreg_pcie_12v: regulator-pcie_12v {
> Don't send the downstream code.
>
> Underscore are not allowed in node names plus:
>
> Please use name for all fixed regulators which matches current format
> recommendation: 'regulator-[0-9]v[0-9]'
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml?h=v6.11-rc1#n46
>
> Best regards,
> Krzysztof

Will fix in the next version.

-- 
With best wishes
Wenbin



From krzk at kernel.org  Mon Mar 24 00:21:09 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 08:21:09 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
Message-ID: <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>

On 19/03/2025 12:12, Ryan Chen wrote:
>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>> AST2600-i2cv2
>>
>> On 17/03/2025 10:21, Ryan Chen wrote:
>>>> Neither this.
>>>>
>>>> So it seems you describe already existing and documented I2C, but for
>>>> some reason you want second compatible. The problem is that you do
>>>> not provide reason from the point of view of bindings.
>>>>
>>>> To summarize: what your users want - don't care. Start properly
>>>> describing hardware and your SoC.
>>>
>>> OK, for ast2600 i2c controller have two register mode setting.
>>> One, I call it is old register setting, that is right now i2c-aspeed.c
>>> .compatible = "aspeed,ast2600-i2c-bus", And there have a global register
>> that can set i2c controller as new mode register set.
>>> That I am going to drive. That I post is all register in new an old register list.
>>>
>>> For example,
>>> Global register [2] = 0 => i2c present as old register set Global
>>> register [2] = 1 => i2c present as new register set
>> It's the same device though, so the same compatible.
> 
> Sorry, it is different design, and it share the same register space.
> So that the reason add new compatible "aspeed,ast2600-i2cv2" for this driver.
> It is different register layout.

Which device is described by the existing "aspeed,ast2600-i2c-bus"
compatible? And which device is described by new compatible?



Best regards,
Krzysztof


From quic_wenbyao at quicinc.com  Mon Mar 24 00:21:53 2025
From: quic_wenbyao at quicinc.com (Wenbin Yao (Consultant))
Date: Mon, 24 Mar 2025 15:21:53 +0800
Subject: [PATCH v1 3/3] arm64: dts: qcom: x1e80100-qcp: Add power control
 and sideband signals for PCIe3
In-Reply-To: <54c588be-d630-4901-8885-a042b477f168@linaro.org>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <w7mbnqG7DHPCH6hVoSu4E2p8pV7Rw6uvurlK-CUxF7TYQ53fFyagxmLUCmCTfG0DOUgIQn7GdppXgBlq8Gyv9Q==@protonmail.internalid>
 <20250320055502.274849-4-quic_wenbyao@quicinc.com>
 <54c588be-d630-4901-8885-a042b477f168@linaro.org>
Message-ID: <70db6155-a230-4f9c-a2e1-2c872c87cd39@quicinc.com>

On 3/21/2025 6:08 AM, Bryan O'Donoghue wrote:
> On 20/03/2025 05:55, Wenbin Yao wrote:
>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>
>> Add perst, wake and clkreq sideband signals and required regulators in
>> PCIe3 controller and PHY device tree node. Describe the voltage rails of
>> the x8 PCI slots for PCIe3 port.
>>
>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>> ---
>> ? arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 119 ++++++++++++++++++++++
>> ? 1 file changed, 119 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts 
>> b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> index 28086a2bc..9cd313802 100644
>> --- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> +++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
>> @@ -318,6 +318,48 @@ vreg_wcn_3p3: regulator-wcn-3p3 {
>> ????????? regulator-boot-on;
>> ????? };
>>
>> +??? vreg_pcie_12v: regulator-pcie_12v {
>> +??????? compatible = "regulator-fixed";
>> +
>> +??????? regulator-name = "VREG_PCIE_12V";
>> +??????? regulator-min-microvolt = <12000000>;
>> +??????? regulator-max-microvolt = <12000000>;
>> +
>> +??????? gpio = <&pm8550ve_8_gpios 8 GPIO_ACTIVE_HIGH>;
>> +??????? enable-active-high;
>> +
>> +??????? pinctrl-names = "default";
>> +??????? pinctrl-0 = <&pcie_x8_12v>;
>> +??? };
>> +
>> +??? vreg_pcie_3v3_aux: regulator-pcie_3v3_aux {
>> +??????? compatible = "regulator-fixed";
>> +
>> +??????? regulator-name = "VREG_PCIE_3P3_AUX";
>> +??????? regulator-min-microvolt = <3300000>;
>> +??????? regulator-max-microvolt = <3300000>;
>> +
>> +??????? gpio = <&pmc8380_3_gpios 8 GPIO_ACTIVE_HIGH>;
>> +??????? enable-active-high;
>> +
>> +??????? pinctrl-names = "default";
>> +??????? pinctrl-0 = <&pm_sde7_aux_3p3_en>;
>> +??? };
>> +
>> +??? vreg_pcie_3v3: regulator-pcie_3v3 {
>> +??????? compatible = "regulator-fixed";
>> +
>> +??????? regulator-name = "VREG_PCIE_3P3";
>> +??????? regulator-min-microvolt = <3300000>;
>> +??????? regulator-max-microvolt = <3300000>;
>> +
>> +??????? gpio = <&pmc8380_3_gpios 6 GPIO_ACTIVE_HIGH>;
>> +??????? enable-active-high;
>> +
>> +??????? pinctrl-names = "default";
>> +??????? pinctrl-0 = <&pm_sde7_main_3p3_en>;
>> +};
>> +
>> ????? usb-1-ss0-sbu-mux {
>> ????????? compatible = "onnn,fsusb42", "gpio-sbu-mux";
>>
>> @@ -907,6 +949,60 @@ &mdss_dp3_phy {
>> ????? status = "okay";
>> ? };
>>
>> +&pm8550ve_8_gpios {
>> +??? pcie_x8_12v: pcie-12v-default-state {
>> +??????? pins = "gpio8";
>> +??????? function = "normal";
>> +??????? output-enable;
>> +??????? output-high;
>> +??????? bias-pull-down;
>> +??????? power-source = <0>;
>> +??? };
>> +};
>> +
>> +&pmc8380_3_gpios {
>> +??? pm_sde7_aux_3p3_en: pcie-aux-3p3-default-state {
>> +??????? pins = "gpio8";
>> +??????? function = "normal";
>> +??????? output-enable;
>> +??????? output-high;
>> +??????? bias-pull-down;
>> +??????? power-source = <0>;
>> +??? };
>> +
>> +??? pm_sde7_main_3p3_en: pcie-main-3p3-default-state {
>> +??????? pins = "gpio6";
>> +??????? function = "normal";
>> +??????? output-enable;
>> +??????? output-high;
>> +??????? bias-pull-down;
>> +??????? power-source = <0>;
>> +??? };
>> +};
>> +
>> +&pcie3 {
>> +
>> +??? pinctrl-names = "default";
>> +??? pinctrl-0 = <&pcie3_default>;
>> +??? perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
>> +??? wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
>> +??? status = "okay";
>> +};
>> +
>> +&pcie3_phy {
>> +??? vdda-phy-supply = <&vreg_l3j_0p8>;
>> +??? vdda-pll-supply = <&vreg_l3e_1p2>;
>> +??? vdda-qref-supply = <&vreg_l3c_0p8>;
>> +
>> +??? status = "okay";
>> +};
>> +
>> +&pcie3port {
>> +??? vpcie12v-supply = <&vreg_pcie_12v>;
>> +??? vpcie3v3-supply = <&vreg_pcie_3v3>;
>> +??? vpcie3v3aux-supply = <&vreg_pcie_3v3_aux>;
>> +};
>> +
>> ? &pcie4 {
>> ????? perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>;
>> ????? wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
>> @@ -1118,6 +1214,29 @@ nvme_reg_en: nvme-reg-en-state {
>> ????????? bias-disable;
>> ????? };
>>
>> +??? pcie3_default: pcie3-default-state {
>> +??????? clkreq-n-pins {
>> +??????????? pins = "gpio144";
>> +??????????? function = "pcie3_clk";
>> +??????????? drive-strength = <2>;
>> +??????????? bias-pull-up;
>> +??????? };
>> +
>> +??????? perst-n-pins {
>> +??????????? pins = "gpio143";
>> +??????????? function = "gpio";
>> +??????????? drive-strength = <2>;
>> +??????????? bias-pull-down;
>> +??????? };
>> +
>> +??????? wake-n-pins {
>> +?????????????? pins = "gpio145";
>> +?????????????? function = "gpio";
>> +?????????????? drive-strength = <2>;
>> +?????????????? bias-pull-up;
>> +??????? };
>> +??? };
>> +
>> ????? pcie4_default: pcie4-default-state {
>> ????????? clkreq-n-pins {
>> ????????????? pins = "gpio147";
>> -- 
>> 2.34.1
>>
>>
>
> Recommend breaking this patch into at least two patches @ the and
>
> -> Add power control
> -> Add sideband signals
>
> if your patch title requires an and its usually a good indicator of a 
> place to break that patch into different parts.

Will fix in the next version.

>
> ---
> bod

-- 
With best wishes
Wenbin



From manivannan.sadhasivam at linaro.org  Mon Mar 24 00:23:05 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 12:53:05 +0530
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <20250314064642.fyf3jqylmc6meft7@uda0492258>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
 <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
 <20250313165311.2fj7aus3pcsg4m2c@thinkpad>
 <20250314064642.fyf3jqylmc6meft7@uda0492258>
Message-ID: <hhvst2uvlymcyir5sb5vwd4ezko7yawwp5cnosluaz2hkabcna@ywr4thtjpdps>

On Fri, Mar 14, 2025 at 12:16:42PM +0530, Siddharth Vadapalli wrote:
> On Thu, Mar 13, 2025 at 10:23:11PM +0530, Manivannan Sadhasivam wrote:
> 
> Hello Mani,
> 
> > On Wed, Mar 05, 2025 at 11:20:22AM -0500, Frank Li wrote:
> > 
> > If you want a specific patch to be tested, you can add [PATCH RFT] tag.C
> > 
> > > According to code in drivers/pci/controller/dwc/pci-dra7xx.c
> > > 
> > > dra7xx_pcie_cpu_addr_fixup()
> > > {
> > > 	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
> > > }
> > > 
> > > PCI parent bus trim high 4 bits address to 0. Correct ranges in
> > > target-module at 51000000 to algin hardware behavior, which translate PCIe
> > > outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.
> > > 
> > > Set 'config' and 'addr_space' reg values to 0.
> > > Change parent bus address of downstream I/O and non-prefetchable memory to
> > > 0.
> > > 
> > > Ensure no functional impact on the final address translation result.
> > > 
> > > Prepare for the removal of the driver?s cpu_addr_fixup().
> > > 
> > > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > > ---
> > >  arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
> > >  1 file changed, 9 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > index b709703f6c0d4..9213fdd25330b 100644
> > > --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > @@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
> > >  			#size-cells = <1>;
> > >  			#address-cells = <1>;
> > >  			ranges = <0x51000000 0x51000000 0x3000>,
> > > -				 <0x20000000 0x20000000 0x10000000>;
> > > +				 <0x00000000 0x20000000 0x10000000>;
> > 
> > I'm not able to interpret this properly. So this essentially means that the
> > parent address 0x20000000 is mapped to child address 0x00000000. And the child
> > address is same for other controller as well.
> > 
> > Also, the cpu_addr_fixup() is doing the same by masking out the upper 4 bits. I
> > tried looking into the DRA7 TRM, but it says (ECAM_Param_Base_Addr +
> > 0x20000000) where ECAM_Param_Base_Addr = 0x0000_0000 to 0x0FFF_F000.
> > 
> > I couldn't relate TRM with the cpu_addr_fixup() callback. Can someone from TI
> > shed light on this?
> 
> A "git blame" on the line being modified in dra7.dtsi gives the
> following commit:
> https://github.com/torvalds/linux/commit/c761028ef5e2
> prior to which the ranges is exactly the same as the one being added by
> this patch.
> 
> The cpu_addr_fixup() function was introduced by the following commit:
> https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> with the reason described in
> Section 24.9.4.3.2 PCIe Controller Slave Port
> of the T.R.M. at:
> https://www.ti.com/lit/ug/spruic2d/spruic2d.pdf
> ---------------------------------------------------------------------------
> NOTE:
> The PCIe controller remains fully functional, and able to send transactions
> to, for example, anywhere within the 64-bit PCIe memory space, with the
> appropriate remapping of the 28-bit address by the outbound address
> translation unit (iATU). The limitation is that the total size of addressed
> PCIe regions (in config, memory, IO spaces) must be less than 2^28 bytes.
> ---------------------------------------------------------------------------
> 
> The entire sequence is:
> 0) dra7.dtsi had ranges which match the ranges in the current patch.
> 1) cpu_addr_fixup() was added by
> https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> 2) ranges was updated to <0x20000000 0x20000000 0x10000000> by:
> https://github.com/torvalds/linux/commit/c761028ef5e2
> 3) ranges is being changed back to its original state of "0)" above.
> 

Thanks a lot for the reference.

> cpu_addr_fixup() was introduced to remove the following:
> 	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
> 	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
> in dra7xx_pcie_host_init(). The reason for the above is mentioned in the
> "NOTE" as:
> ---------------------------------------------------------------------------
> The limitation is that the total size of addressed PCIe regions
> (in config, memory, IO spaces) must be less than 2^28 bytes.
> ---------------------------------------------------------------------------
> 

I don't think so. This note is for the *size* of the addressed regions. The
fixup corresponds to the sentence in your above note from TRM:

"able to send transactions to, for example, anywhere within the 64-bit PCIe
memory space, with the appropriate remapping of the 28-bit address by the
outbound address translation unit (iATU)"

I think the limitation is due to the 29-bit address bus width of the PCIe
controller slave port as mentionend in section, 24.9.4.3.2. And that correlates
to the truncation of the upper 4 bits of the IO/CFG/MEM addresses. So even if
the CPU passes address range relative to offset 0, PCIe controller converts it
to 0x20000000/0x30000000 based on the instance.

If my understanding is correct, then commit, c761028ef5e2 should be reverted and
this patch can be applied.

> I am not sure if Frank is accounting for all of this in the current patch
> as well as the dependent patch series associated with removing
> cpu_addr_fixup().
> 
> Regarding testing the series, I unfortunately don't have the hardware so
> I cannot test it.
> 

That's a pity. If TI employee doesn't have access to an upstream supported
platform, then I'm not sure whom we should ask for testing.

Could you please ask around and see if you can get access to one? I'm sure that
the hardware will be available somewhere :)

- Mani

-- 
????????? ????????


From krzk at kernel.org  Mon Mar 24 00:23:13 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 08:23:13 +0100
Subject: [PATCH 1/2] dt-bindings: misc: bist: Add BIST dt-binding for TI
 K3 devices
In-Reply-To: <f39d80fc-3600-4c2c-b09c-980288f86fa2@ti.com>
References: <20241128140825.263216-1-n-francis@ti.com>
 <20241128140825.263216-2-n-francis@ti.com>
 <ho7ktcnbtl7mvamfthqho23co2fc4z7bgjha7pu4wivxm6ndhu@tfbpveonhckz>
 <837d329b-bcdd-4c3b-b508-e916b110ce25@ti.com>
 <e57dfc3e-b702-4803-b776-20c6dbd98fef@kernel.org>
 <8e58b093-1c64-45b9-a9d3-9835a3bbc4fd@ti.com>
 <1da4e402-62f3-4bad-9129-1f5a08148987@kernel.org>
 <f39d80fc-3600-4c2c-b09c-980288f86fa2@ti.com>
Message-ID: <a2397c92-2884-4f4d-b036-808208892af5@kernel.org>

On 19/03/2025 10:02, Neha Malcom Francis wrote:
> Hi Krzysztof,
> 
> On 19/03/25 13:16, Krzysztof Kozlowski wrote:
>> On 13/03/2025 12:14, Neha Malcom Francis wrote:
>>> Hi Krzysztof
>>>
>>> On 29/11/24 14:45, Krzysztof Kozlowski wrote:
>>>> On 29/11/2024 08:43, Neha Malcom Francis wrote:
>>>>>>> +
>>>>>>> +  power-domains:
>>>>>>> +    maxItems: 1
>>>>>>> +
>>>>>>> +  ti,bist-instance:
>>>>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>>>>> +    description:
>>>>>>> +      the BIST instance in the SoC represented as an integer
>>>>>>
>>>>>> No instance indices are allowed. Drop.
>>>>>>
>>>>>
>>>>> Question on this, this is not a property that is driven by software but rather 
>>>>> indicates which register sequences have to be picked up for triggering this test 
>>>>> from this instance. So I don't see how I can workaround this without getting 
>>>>> this number. Or maybe call it ID rather than instance?
>>>>
>>>> I don't understand how the device operates, so what is exactly behind
>>>> some sequences of registers for triggering this test. You described
>>>> property as index or ID of one instance of the block. That's not what we
>>>> want in the binding. That's said maybe other, different hardware
>>>> characteristic is behind, who knows. Or maybe it's about callers... or
>>>> maybe that's not hardware property at all, but runtime OS, who knows.
>>>>
>>>
>>> Sorry for such a late reply, but I was hoping to get more details on
>>> this "ID" and never got back to the thread...
>>>
>>> The best way I can describe is this device (BIST) runs a safety
>>> diagnostic test on a bunch of processors/blocks (let's call them
>>> targets). There's a mapping between the instance of this device and the
>>> targets it will run the test. This ID was essentially letting the BIST
>>> driver know which are these targets.
>>
>>
>> So you want to configure some target? Then this is your property. If you
>> want to configure 'foo' difference in DT, you do not write 'bar'...
>>
> 
> So the difficulty in doing this is, what I mentioned in the earlier
> email just copying it over again:
> 
> "Yet another way would be the BIST points out the targets it controls via
> their phandles in its node... but this approach would trigger the probe

No, it would not. Which part of OF kernel code causes probe ordering
(device links) if some random phandle appears?

> of these targets before the test runs on them. And in hardware, the test
> must run only one before the device is used, else we see indefinite
> behavior."
> 
> Property that has a list of strings (targets) instead of phandles maybe?
> Would that be acceptable?



Best regards,
Krzysztof


From manivannan.sadhasivam at linaro.org  Mon Mar 24 00:25:11 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 12:55:11 +0530
Subject: [PATCH RFC NOT TESTED 0/2] PCI: dra7xx: Try to clean up
 dra7xx_pcie_cpu_addr_fixup()
In-Reply-To: <20250317194539.GA969005@bhelgaas>
References: <20250317184427.7wkcr7jwu53r5jog@thinkpad>
 <20250317194539.GA969005@bhelgaas>
Message-ID: <5lyvmuk7o3nj6xaozyghxnhivwcmx2yisnbhwugklx5u5sutmz@26ta4e5en2mq>

On Mon, Mar 17, 2025 at 02:45:39PM -0500, Bjorn Helgaas wrote:
> On Tue, Mar 18, 2025 at 12:14:27AM +0530, Manivannan Sadhasivam wrote:
> > On Mon, Mar 17, 2025 at 12:30:08PM -0500, Bjorn Helgaas wrote:
> > > On Thu, Mar 13, 2025 at 11:35:21AM +0530, Manivannan Sadhasivam wrote:
> > > > On Wed, Mar 05, 2025 at 11:20:21AM -0500, Frank Li wrote:
> > > > > This patches basic on
> > > > > https://lore.kernel.org/imx/20250128-pci_fixup_addr-v9-0-3c4bb506f665 at nxp.com/
> > > > > 
> > > > > I have not hardware to test.
> > > > > 
> > > > > Look for driver owner, who help test this and start move
> > > > > forward to remove cpu_addr_fixup() work.
> > > > 
> > > > If you remove cpu_addr_fixup() callback, it will break backwards
> > > > compatibility with old DTs.
> > > 
> > > Do you have any pointers to DTs that will be broken?  Or to
> > > commits where they were fixed?
> > 
> > Any patch that fixes issues in DT and then makes the required
> > changes in the driver without accounting for the old DTs will break
> > backwards compatibility.
> 
> Right, I guess the rule is that if we have patches that fix DT issues,
> we should apply them as soon as possible.
> 

Right, and those patches should not break old DTs.

> And later if we ever have confidence that unfixed DTs no longer exist
> (or if we can identify and work around them in the kernel), we can
> remove the .cpu_addr_fixup().
> 

Yeah. Unfortunately, we do not have a fixed deadline or process. Just like
supporting the legacy broken hw, we have to keep supporting the old DTs for some
time and then get rid of them.

- Mani

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Mon Mar 24 00:27:21 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 12:57:21 +0530
Subject: [PATCH PATCH RFC NOT TESTED 1/2] ARM: dts: ti: dra7: Correct
 ranges for PCIe and parent bus nodes
In-Reply-To: <Z9RFJDdnoU+aKwF7@lizhi-Precision-Tower-5810>
References: <20250305-dra-v1-0-8dc6d9a0e1c0@nxp.com>
 <20250305-dra-v1-1-8dc6d9a0e1c0@nxp.com>
 <20250313165311.2fj7aus3pcsg4m2c@thinkpad>
 <20250314064642.fyf3jqylmc6meft7@uda0492258>
 <Z9RFJDdnoU+aKwF7@lizhi-Precision-Tower-5810>
Message-ID: <ahkgq7aujrluhuqbdv2mbn5gjcu6hn4bi3jw4xar52ximyx5pi@mw4v4lzrvtky>

On Fri, Mar 14, 2025 at 11:03:00AM -0400, Frank Li wrote:
> On Fri, Mar 14, 2025 at 12:16:42PM +0530, Siddharth Vadapalli wrote:
> > On Thu, Mar 13, 2025 at 10:23:11PM +0530, Manivannan Sadhasivam wrote:
> >
> > Hello Mani,
> >
> > > On Wed, Mar 05, 2025 at 11:20:22AM -0500, Frank Li wrote:
> > >
> > > If you want a specific patch to be tested, you can add [PATCH RFT] tag.C
> > >
> > > > According to code in drivers/pci/controller/dwc/pci-dra7xx.c
> > > >
> > > > dra7xx_pcie_cpu_addr_fixup()
> > > > {
> > > > 	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  //0x0FFFFFFF
> > > > }
> > > >
> > > > PCI parent bus trim high 4 bits address to 0. Correct ranges in
> > > > target-module at 51000000 to algin hardware behavior, which translate PCIe
> > > > outbound address 0..0x0fff_ffff to 0x2000_0000..0x2fff_ffff.
> > > >
> > > > Set 'config' and 'addr_space' reg values to 0.
> > > > Change parent bus address of downstream I/O and non-prefetchable memory to
> > > > 0.
> > > >
> > > > Ensure no functional impact on the final address translation result.
> > > >
> > > > Prepare for the removal of the driver?s cpu_addr_fixup().
> > > >
> > > > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > > > ---
> > > >  arch/arm/boot/dts/ti/omap/dra7.dtsi | 18 +++++++++---------
> > > >  1 file changed, 9 insertions(+), 9 deletions(-)
> > > >
> > > > diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > > index b709703f6c0d4..9213fdd25330b 100644
> > > > --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > > +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
> > > > @@ -196,7 +196,7 @@ axi0: target-module at 51000000 {
> > > >  			#size-cells = <1>;
> > > >  			#address-cells = <1>;
> > > >  			ranges = <0x51000000 0x51000000 0x3000>,
> > > > -				 <0x20000000 0x20000000 0x10000000>;
> > > > +				 <0x00000000 0x20000000 0x10000000>;
> > >
> > > I'm not able to interpret this properly. So this essentially means that the
> > > parent address 0x20000000 is mapped to child address 0x00000000. And the child
> > > address is same for other controller as well.
> > >
> > > Also, the cpu_addr_fixup() is doing the same by masking out the upper 4 bits. I
> > > tried looking into the DRA7 TRM, but it says (ECAM_Param_Base_Addr +
> > > 0x20000000) where ECAM_Param_Base_Addr = 0x0000_0000 to 0x0FFF_F000.
> > >
> > > I couldn't relate TRM with the cpu_addr_fixup() callback. Can someone from TI
> > > shed light on this?
> >
> > A "git blame" on the line being modified in dra7.dtsi gives the
> > following commit:
> > https://github.com/torvalds/linux/commit/c761028ef5e2
> > prior to which the ranges is exactly the same as the one being added by
> > this patch.
> 
> Okay, original one correct reflect hardware behavior.
> 
> >
> > The cpu_addr_fixup() function was introduced by the following commit:
> > https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> > with the reason described in
> > Section 24.9.4.3.2 PCIe Controller Slave Port
> > of the T.R.M. at:
> > https://www.ti.com/lit/ug/spruic2d/spruic2d.pdf
> > ---------------------------------------------------------------------------
> > NOTE:
> > The PCIe controller remains fully functional, and able to send transactions
> > to, for example, anywhere within the 64-bit PCIe memory space, with the
> > appropriate remapping of the 28-bit address by the outbound address
> > translation unit (iATU). The limitation is that the total size of addressed
> > PCIe regions (in config, memory, IO spaces) must be less than 2^28 bytes.
> > ---------------------------------------------------------------------------
> >
> > The entire sequence is:
> > 0) dra7.dtsi had ranges which match the ranges in the current patch.
> > 1) cpu_addr_fixup() was added by
> > https://github.com/torvalds/linux/commit/2ed6cc71e6f7
> > 2) ranges was updated to <0x20000000 0x20000000 0x10000000> by:
> > https://github.com/torvalds/linux/commit/c761028ef5e2
> 
> Actually this patch is not necessary, with cpu_addr_fixup(), it should
> work with/without c761028ef5e2 change because it just the use CPU physical
> address, the finial result is exact same.
> 
> > 3) ranges is being changed back to its original state of "0)" above.
> >
> > cpu_addr_fixup() was introduced to remove the following:
> > 	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
> > 	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
> > 	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
> > 	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
> > in dra7xx_pcie_host_init(). The reason for the above is mentioned in the
> > "NOTE" as:
> > ---------------------------------------------------------------------------
> > The limitation is that the total size of addressed PCIe regions
> > (in config, memory, IO spaces) must be less than 2^28 bytes.
> > ---------------------------------------------------------------------------
> >
> 
> That is functional equal.
> 
> > I am not sure if Frank is accounting for all of this in the current patch
> > as well as the dependent patch series associated with removing
> > cpu_addr_fixup().
> 
> I have not track back the history. I think before
> https://github.com/torvalds/linux/commit/c761028ef5e2 is correct reflect
> hardware behavor. axi at 0 trim down 4 bits before send to PCI controller.
> 
> The commit message of c761028ef5e2
> 
> "In order to update pcie to probe with ti-sysc and genpd, let's update the
> pcie ranges to not use address 0 for 0x20000000 and 0x30000000. The range
> for 0 is typically used for child devices as the offset from the module
> base. In the following patches, we will update pcie to probe with ti-sysc,
> and the patches become a bit confusing to read compared to other similar
> modules unless we update the ranges first. So let's just use the full
> addresses for ranges for the 0x20000000 and 0x30000000 ranges."
> 
> I think maybe only ti's bus fabric do address translation at that time, and
> DT team and dwc pci driver never consider that before. Now more vendor bus
> fabric do address translation. So needn't every platform driver consider it
> but it require DTB reflect hardware behavor correctly.
> 
> We may revert patch c761028ef5e2 firstly, after some time later, we can
> cleanup cpu_addr_fixup().
> 

I agree. Commit, c761028ef5e2 is not going to break anything afaik (even the
cpu_addr_fixup), but it would be good to get it tested.

> It will be wondful, if someone help test it.
> 

Let's see if Siddharth can come up with some good news.

- Mani

-- 
????????? ????????


From Markus.Elfring at web.de  Mon Mar 24 00:33:39 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Mon, 24 Mar 2025 08:33:39 +0100
Subject: wifi: mt76: mt7996: avoid potential null deref in
 mt7996_get_et_stats()
In-Reply-To: <223c7280-443d-49b4-96b2-90472339dcd4@stanley.mountain>
References: <20250322141910.4461-1-qasdev00@gmail.com>
 <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
 <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>
 <CAAMvbhGrJ9b3Aab9+2a5zmvEgf0GZFmHLCC7Hud+egUE28voHQ@mail.gmail.com>
 <223c7280-443d-49b4-96b2-90472339dcd4@stanley.mountain>
Message-ID: <46a53498-6c20-48fd-b090-02163baefddd@web.de>

> Also the "phy" point will never be NULL so the check should be removed.
How many tools can help to determine such a software aspect with inter-procedural analyses?

Regards,
Markus


From krzk at kernel.org  Mon Mar 24 00:38:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 08:38:34 +0100
Subject: [PATCH v1 1/3] arm64: defconfig: enable PCI Power Control for
 PCIe3
In-Reply-To: <9ea8fe39-b818-403b-bd69-815e58eb2949@quicinc.com>
References: <20250320055502.274849-1-quic_wenbyao@quicinc.com>
 <20250320055502.274849-2-quic_wenbyao@quicinc.com>
 <694b6638-92b2-4ac0-a175-bd29aea6cba9@kernel.org>
 <CAMRc=MfZrRp=VuEOLuMY_04JdyRrD+joGL56LwRFQ-+D-8Z_6w@mail.gmail.com>
 <9ea8fe39-b818-403b-bd69-815e58eb2949@quicinc.com>
Message-ID: <fbd5c153-b73a-4dbc-a923-4e3d3924e748@kernel.org>

On 24/03/2025 08:09, Wenbin Yao (Consultant) wrote:
> On 3/21/2025 5:43 PM, Bartosz Golaszewski wrote:
>> On Fri, Mar 21, 2025 at 8:37?AM Krzysztof Kozlowski <krzk at kernel.org> wrote:
>>> On 20/03/2025 06:55, Wenbin Yao wrote:
>>>> From: Qiang Yu <quic_qianyu at quicinc.com>
>>>>
>>>> Enable the pwrctrl driver, which is utilized to manage the power supplies
>>>> of the devices connected to the PCI slots. This ensures that the voltage
>>>> rails of the x8 PCI slots on the X1E80100 - QCP can be correctly turned
>>>> on/off if they are described under PCIe port device tree node.
>>>>
>>>> Signed-off-by: Qiang Yu <quic_qianyu at quicinc.com>
>>>> Signed-off-by: Wenbin Yao <quic_wenbyao at quicinc.com>
>>>> ---
>>>>   arch/arm64/configs/defconfig | 1 +
>>>>   1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
>>>> index 85ec2fba1..de86d1121 100644
>>>> --- a/arch/arm64/configs/defconfig
>>>> +++ b/arch/arm64/configs/defconfig
>>>> @@ -245,6 +245,7 @@ CONFIG_PCIE_LAYERSCAPE_GEN4=y
>>>>   CONFIG_PCI_ENDPOINT=y
>>>>   CONFIG_PCI_ENDPOINT_CONFIGFS=y
>>>>   CONFIG_PCI_EPF_TEST=m
>>>> +CONFIG_PCI_PWRCTL_SLOT=y
>>> Bartosz,
>>>
>>> Wasn't the intention to select it the same way as PCI_PWRCTL_PWRSEQ is
>>> selected?
>>>
>>> Best regards,
>>> Krzysztof
>>>
>> For sure. I would expect there to be something like:
>>
>> select PCI_PWRCTL_SLOT if ARCH_QCOM
>>
>> in Kconfig and nothing in defconfig.
>>
>> Bartosz
> 
> IIUC, pci slot power driver is a common driver that could be used by all DT
> based platform.


You are not responding to the raised problem.

Best regards,
Krzysztof


From alexander.stein at ew.tq-group.com  Mon Mar 24 00:02:06 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 24 Mar 2025 08:02:06 +0100
Subject: [PATCH v2 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <20250321200625.132494-10-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-10-marex@denx.de>
Message-ID: <6144881.lOV4Wx5bFT@steina-w>

Am Freitag, 21. M?rz 2025, 21:05:59 CET schrieb Marek Vasut:
> The instance of the GPU populated in i.MX95 is the G310,
> describe this GPU in the DT. Include description of the
> GPUMIX block controller, which can be operated as a simple
> reset. Include dummy GPU voltage regulator and OPP tables.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: David Airlie <airlied at gmail.com>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Liviu Dudau <liviu.dudau at arm.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Maxime Ripard <mripard at kernel.org>
> Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
> Cc: Philipp Zabel <p.zabel at pengutronix.de>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Sebastian Reichel <sre at kernel.org>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Simona Vetter <simona at ffwll.ch>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Thomas Zimmermann <tzimmermann at suse.de>
> Cc: devicetree at vger.kernel.org
> Cc: dri-devel at lists.freedesktop.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> V2: - Drop regulator-{always,boot}-on from fixed-gpu-reg regulator
>     - Keep the GPU and GPUMIX always enabled
>     - Switch from fsl, to nxp, vendor prefix
>     - Fix opp_table to opp-table
>     - Describe IMX95_CLK_GPUAPB as coregroup clock
>     - Sort interrupts by their names to match bindings
> ---
>  arch/arm64/boot/dts/freescale/imx95.dtsi | 58 ++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
> index 9bb26b466a061..3acdbd7fd4eee 100644
> --- a/arch/arm64/boot/dts/freescale/imx95.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
> @@ -249,6 +249,35 @@ dummy: clock-dummy {
>  		clock-output-names = "dummy";
>  	};
>  
> +	gpu_fixed_reg: fixed-gpu-reg {
> +		compatible = "regulator-fixed";
> +		regulator-min-microvolt = <920000>;
> +		regulator-max-microvolt = <920000>;
> +		regulator-name = "vdd_gpu";
> +	};
> +
> +	gpu_opp_table: opp-table {
> +		compatible = "operating-points-v2";
> +
> +		opp-500000000 {
> +			opp-hz = /bits/ 64 <500000000>;
> +			opp-hz-real = /bits/ 64 <500000000>;
> +			opp-microvolt = <920000>;
> +		};
> +
> +		opp-800000000 {
> +			opp-hz = /bits/ 64 <800000000>;
> +			opp-hz-real = /bits/ 64 <800000000>;
> +			opp-microvolt = <920000>;
> +		};
> +
> +		opp-1000000000 {
> +			opp-hz = /bits/ 64 <1000000000>;
> +			opp-hz-real = /bits/ 64 <1000000000>;
> +			opp-microvolt = <920000>;
> +		};
> +	};
> +
>  	clk_ext1: clock-ext1 {
>  		compatible = "fixed-clock";
>  		#clock-cells = <0>;
> @@ -1890,6 +1919,35 @@ netc_emdio: mdio at 0,0 {
>  			};
>  		};
>  
> +		gpu_blk_ctrl: reset-controller at 4d810000 {
> +			compatible = "nxp,imx95-gpu-blk-ctrl";
> +			reg = <0x0 0x4d810000 0x0 0xc>;
> +			#reset-cells = <1>;
> +			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> +			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> +			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
> +			assigned-clock-rates = <133333333>;
> +			power-domains = <&scmi_devpd IMX95_PD_GPU>;
> +		};

With the SM release lf-6.12.3-1.0.0 AP does not have any access to
this BLK_CTRL anymore. See [1]

Best regards,
Alexander

[1] https://github.com/nxp-imx/imx-sm/blob/master/sm/doc/rn_cl.md#sm-184-deassert-the-gpu-reset-when-the-gpumix-is-powered-up-rn_detail_sm_184

> +
> +		gpu: gpu at 4d900000 {
> +			compatible = "nxp,imx95-mali", "arm,mali-valhall-csf";
> +			reg = <0 0x4d900000 0 0x480000>;
> +			clocks = <&scmi_clk IMX95_CLK_GPU>, <&scmi_clk IMX95_CLK_GPUAPB>;
> +			clock-names = "core", "coregroup";
> +			interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupt-names = "job", "mmu", "gpu";
> +			mali-supply = <&gpu_fixed_reg>;
> +			operating-points-v2 = <&gpu_opp_table>;
> +			power-domains = <&scmi_devpd IMX95_PD_GPU>, <&scmi_perf IMX95_PERF_GPU>;
> +			power-domain-names = "mix", "perf";
> +			resets = <&gpu_blk_ctrl 0>;
> +			#cooling-cells = <2>;
> +			dynamic-power-coefficient = <1013>;
> +		};
> +
>  		ddr-pmu at 4e090dc0 {
>  			compatible = "fsl,imx95-ddr-pmu", "fsl,imx93-ddr-pmu";
>  			reg = <0x0 0x4e090dc0 0x0 0x200>;
> 


-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From dan.carpenter at linaro.org  Mon Mar 24 00:43:31 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Mon, 24 Mar 2025 10:43:31 +0300
Subject: wifi: mt76: mt7996: avoid potential null deref in
 mt7996_get_et_stats()
In-Reply-To: <46a53498-6c20-48fd-b090-02163baefddd@web.de>
References: <20250322141910.4461-1-qasdev00@gmail.com>
 <d1df5d97-4691-40d4-a6cc-416505f35164@web.de>
 <92d1a410788c54facedec033474046dda6a1a2cc.camel@sipsolutions.net>
 <CAAMvbhGrJ9b3Aab9+2a5zmvEgf0GZFmHLCC7Hud+egUE28voHQ@mail.gmail.com>
 <223c7280-443d-49b4-96b2-90472339dcd4@stanley.mountain>
 <46a53498-6c20-48fd-b090-02163baefddd@web.de>
Message-ID: <d723d5c1-ed17-41b8-9bc4-274fd8e2b615@stanley.mountain>

On Mon, Mar 24, 2025 at 08:33:39AM +0100, Markus Elfring wrote:
> > Also the "phy" point will never be NULL so the check should be removed.
> How many tools can help to determine such a software aspect with
> inter-procedural analyses?
> 

You can just review the code.  There is only one caller.

Btw, it's fine to have unnecessary NULL checks so long as they're done
consistently.  Generally, we prefer people not add unnecessary code,
but if it makes you feel safer, most maintainers aren't going to nit-pick
you about it.  If you are doing the work then you get some say your own
code.

regards,
dan carpenter


From hongxing.zhu at nxp.com  Mon Mar 24 00:48:02 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Mon, 24 Mar 2025 07:48:02 +0000
Subject: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is
 not required
In-Reply-To: <20250324062647.1891896-2-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-2-hongxing.zhu@nxp.com>
Message-ID: <AS8PR04MB8676437B8097EE171631E6EB8CA42@AS8PR04MB8676.eurprd04.prod.outlook.com>


> -----Original Message-----
> From: Hongxing Zhu <hongxing.zhu at nxp.com>
> Sent: 2025?3?24? 14:27
> To: Frank Li <frank.li at nxp.com>; l.stach at pengutronix.de;
> lpieralisi at kernel.org; kw at linux.com; manivannan.sadhasivam at linaro.org;
> robh at kernel.org; bhelgaas at google.com; shawnguo at kernel.org;
> s.hauer at pengutronix.de; kernel at pengutronix.de; festevam at gmail.com
> Cc: linux-pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> imx at lists.linux.dev; linux-kernel at vger.kernel.org; Hongxing Zhu
> <hongxing.zhu at nxp.com>
> Subject: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not
> required
> 
> The current link setup procedure is more like one workaround to detect the
> device behind PCIe switches on some i.MX6 platforms.
> 
> To describe more accurately, change the flag name from
> IMX_PCIE_FLAG_IMX_SPEED_CHANGE to
> IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.
> 
> Then, start PCIe link directly when this flag is not set on i.MX7 or later
> paltforms to simple and speed up link training.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
>  1 file changed, 14 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> b/drivers/pci/controller/dwc/pci-imx6.c
> index c1f7904e3600..aa5c3f235995 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -91,7 +91,7 @@ enum imx_pcie_variants {  };
> 
>  #define IMX_PCIE_FLAG_IMX_PHY			BIT(0)
> -#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE		BIT(1)
> +#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND	BIT(1)
WORDAROUND/s/WORKAROUND
Sorry to find this typo error after patch-set is issued.
Would correct them all in next version.

Best Regards
Richard Zhu
>  #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)
>  #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3)
>  #define IMX_PCIE_FLAG_HAS_APP_RESET		BIT(4)
> @@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
>  	u32 tmp;
>  	int ret;
> 
> +	if (!(imx_pcie->drvdata->flags &
> +	    IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
> +		imx_pcie_ltssm_enable(dev);
> +		return 0;
> +	}
> +
>  	/*
>  	 * Force Gen1 operation when starting the link.  In case the link is
>  	 * started in Gen2 mode, there is a possibility the devices on the @@
> -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
>  		dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL,
> tmp);
>  		dw_pcie_dbi_ro_wr_dis(pci);
> 
> -		if (imx_pcie->drvdata->flags &
> -		    IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
> -
> -			/*
> -			 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
> -			 * from i.MX6 family when no link speed transition
> -			 * occurs and we go Gen1 -> yep, Gen1. The difference
> -			 * is that, in such case, it will not be cleared by HW
> -			 * which will cause the following code to report false
> -			 * failure.
> -			 */
> -			ret = imx_pcie_wait_for_speed_change(imx_pcie);
> -			if (ret) {
> -				dev_err(dev, "Failed to bring link up!\n");
> -				goto err_reset_phy;
> -			}
> +		ret = imx_pcie_wait_for_speed_change(imx_pcie);
> +		if (ret) {
> +			dev_err(dev, "Failed to bring link up!\n");
> +			goto err_reset_phy;
>  		}
> 
>  		/* Make sure link training is finished as well! */ @@ -1665,7
> +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6Q] = {
>  		.variant = IMX6Q,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_BROKEN_SUSPEND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.dbi_length = 0x200,
> @@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6SX] = {
>  		.variant = IMX6SX,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.gpr = "fsl,imx6q-iomuxc-gpr",
>  		.ltssm_off = IOMUXC_GPR12,
> @@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6QP] = {
>  		.variant = IMX6QP,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.dbi_length = 0x200,
>  		.gpr = "fsl,imx6q-iomuxc-gpr",
> --
> 2.37.1


From manivannan.sadhasivam at linaro.org  Mon Mar 24 00:49:47 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 13:19:47 +0530
Subject: [PATCH] pcie-xilinx: Support reset GPIO and wait for link-up
 status
In-Reply-To: <20250314145933.27902-1-mike.looijmans@topic.nl>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.c4ab15e9-561e-402d-bf39-9e852485e4fa@emailsignatures365.codetwo.com>
 <20250314145933.27902-1-mike.looijmans@topic.nl>
Message-ID: <vazbdawfo4jnct4rdokknxwvknespcf33jzrmobsnecbxnrbjn@kbvxvhrow4fn>

On Fri, Mar 14, 2025 at 03:59:02PM +0100, Mike Looijmans wrote:
> Support providing the PERST reset signal through a devicetree binding.

Where is the bindings change?

> Thus the system no longer relies on external components to perform the
> bus reset.
> 

There is a similar series for the CPM controller:
https://lore.kernel.org/linux-pci/20250318092648.2298280-1-sai.krishna.musham at amd.com/

Please take a look for reference.

> When the driver loads, the transceiver may still be in the state of
> setting up a link. Wait for that to complete before continuing. This
> fixes that the PCIe core does not work when loading the PL bitstream
> from userspace. There's only milliseconds between the FPGA boot and the
> core initializing in that case, and the link won't be up yet. The design
> works when the FPGA was programmed in the bootloader, as that will give
> the system hundreds of milliseconds to boot.
> 
> As the PCIe spec mentions about 120 ms time to establish a link, we'll
> allow up to 200ms before giving up.
> 

This should be a separate change/patch.

> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
> ---
> 
>  drivers/pci/controller/pcie-xilinx.c | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
> index 0b534f73a942..cd09deba0ddc 100644
> --- a/drivers/pci/controller/pcie-xilinx.c
> +++ b/drivers/pci/controller/pcie-xilinx.c
> @@ -15,8 +15,10 @@
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
>  #include <linux/init.h>
> +#include <linux/iopoll.h>
>  #include <linux/msi.h>
>  #include <linux/of_address.h>
> +#include <linux/of_gpio.h>
>  #include <linux/of_pci.h>
>  #include <linux/of_platform.h>
>  #include <linux/of_irq.h>
> @@ -126,6 +128,14 @@ static inline bool xilinx_pcie_link_up(struct xilinx_pcie *pcie)
>  		XILINX_PCIE_REG_PSCR_LNKUP) ? 1 : 0;
>  }
>  
> +static int xilinx_pci_wait_link_up(struct xilinx_pcie *pcie)
> +{
> +	u32 val;
> +
> +	return readl_poll_timeout(pcie->reg_base + XILINX_PCIE_REG_PSCR, val,
> +			(val & XILINX_PCIE_REG_PSCR_LNKUP), 2000, 200000);
> +}
> +
>  /**
>   * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
>   * @pcie: PCIe port information
> @@ -492,8 +502,21 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie *pcie)
>  static void xilinx_pcie_init_port(struct xilinx_pcie *pcie)
>  {
>  	struct device *dev = pcie->dev;
> +	struct gpio_desc *perst_gpio;
> +
> +	perst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> +	if (IS_ERR(perst_gpio)) {
> +		dev_err(dev, "gpio request failed: %d\n", PTR_ERR(perst_gpio));
> +		perst_gpio = NULL;

No. If the GPIO is defined in DT and there is a problem in acquiring it, you
should return the error.

> +	}
> +
> +	if (perst_gpio) {

This check is not needed as gpiod_set_value_cansleep() can accept NULL.

- Mani

-- 
????????? ????????


From linus.walleij at linaro.org  Mon Mar 24 00:53:28 2025
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 24 Mar 2025 08:53:28 +0100
Subject: [PATCH v5 1/1] pinctrl: mediatek: Add EINT support for multiple addresses
In-Reply-To: <20250322035307.4811-2-ot_chhao.chang@mediatek.com>
References: <20250322035307.4811-1-ot_chhao.chang@mediatek.com> <20250322035307.4811-2-ot_chhao.chang@mediatek.com>
Message-ID: <CACRpkdZT1GYsZjeRHQqWJmuw5jg-kz7x+53_u8_Y3goyu=uRGw@mail.gmail.com>

On Sat, Mar 22, 2025 at 4:53?AM Hao Chang <ot_chhao.chang at mediatek.com> wrote:

> For flexible routing, eint will be divided into 5 bases,
> and it will obtain the operation address through the pins array.
>
> Signed-off-by: Hao Chang <ot_chhao.chang at mediatek.com>
> Signed-off-by: Qingliang Li <qingliang.li at mediatek.com>

Patch applied as the last pinctrl patch for v6.15!

Thanks for respinning this, I think it will make things easier.

Yours,
Linus Walleij


From krzk at kernel.org  Mon Mar 24 01:03:06 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 09:03:06 +0100
Subject: [PATCH v5 1/3] dt-bindings: pinctrl: mediatek: Add support for
 mt8196
In-Reply-To: <20250321084142.18563-2-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
 <20250321084142.18563-2-ot_cathy.xu@mediatek.com>
Message-ID: <20250324-sly-smart-impala-9fb09e@krzk-bin>

On Fri, Mar 21, 2025 at 04:39:12PM +0800, Cathy Xu wrote:
> +  reg:
> +    items:
> +      - description: gpio registers base address
> +      - description: rt group io configuration registers base address

s/io configuration registers base address/IO/
?

Why repeating so much of redundant information?

> +      - description: rm1 group io configuration registers base address
> +      - description: rm2 group io configuration registers base address
> +      - description: rb group io configuration registers base address
> +      - description: bm1 group io configuration registers base address
> +      - description: bm2 group io configuration registers base address
> +      - description: bm3 group io configuration registers base address
> +      - description: lt group io configuration registers base address
> +      - description: lm1 group io configuration registers base address
> +      - description: lm2 group io configuration registers base address
> +      - description: lb1 group io configuration registers base address
> +      - description: lb2 group io configuration registers base address
> +      - description: tm1 group io configuration registers base address
> +      - description: tm2 group io configuration registers base address
> +      - description: tm3 group io configuration registers base address
> +
> +  reg-names:
> +    items:
> +      - const: iocfg0
> +      - const: iocfg_rt
> +      - const: iocfg_rm1
> +      - const: iocfg_rm2
> +      - const: iocfg_rb
> +      - const: iocfg_bm1
> +      - const: iocfg_bm2
> +      - const: iocfg_bm3
> +      - const: iocfg_lt
> +      - const: iocfg_lm1
> +      - const: iocfg_lm2
> +      - const: iocfg_lb1
> +      - const: iocfg_lb2
> +      - const: iocfg_tm1
> +      - const: iocfg_tm2
> +      - const: iocfg_tm3

Same here, drop iocfg_ prefix everywhere. The first entry becames then
"base" or whatever else meaningful ("0" is not meaningful).


> +
> +  interrupt-controller: true
> +
> +  '#interrupt-cells':
> +    const: 2
> +
> +  interrupts:
> +    description: The interrupt outputs to sysirq.
> +    maxItems: 1
> +
> +# PIN CONFIGURATION NODES
> +patternProperties:
> +  '-pins$':
> +    type: object
> +    additionalProperties: false
> +
> +    patternProperties:
> +      '^pins':
> +        type: object
> +        $ref: /schemas/pinctrl/pincfg-node.yaml
> +        additionalProperties: false
> +        description:
> +          A pinctrl node should contain at least one subnode representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to muxer
> +          configuration, pullups, drive strength, input enable/disable and input
> +          schmitt.
> +
> +        properties:
> +          pinmux:
> +            description:
> +              Integer array, represents gpio pin number and mux setting.
> +              Supported pin number and mux varies for different SoCs, and are
> +              defined as macros in arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
> +              directly, for this SoC.
> +
> +          drive-strength:
> +            enum: [2, 4, 6, 8, 10, 12, 14, 16]
> +
> +          bias-pull-down:
> +            oneOf:
> +              - type: boolean
> +              - enum: [100, 101, 102, 103]
> +                description: mt8196 pull down PUPD/R0/R1 type define value.
> +              - enum: [75000, 5000]
> +                description: mt8196 pull down RSEL type si unit value(ohm).
> +            description: |
> +              For pull down type is normal, it doesn't need add R1R0 define
> +              and resistance value.
> +              For pull down type is PUPD/R0/R1 type, it can add R1R0 define to
> +              set different resistance. It can support "MTK_PUPD_SET_R1R0_00" &
> +              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
> +              "MTK_PUPD_SET_R1R0_11" define in mt8196.
> +              For pull down type is PD/RSEL, it can add resistance value(ohm)
> +              to set different resistance by identifying property
> +              "mediatek,rsel-resistance-in-si-unit". It can support resistance
> +              value(ohm) "75000" & "5000" in mt8196.
> +
> +          bias-pull-up:
> +            oneOf:
> +              - type: boolean
> +              - enum: [100, 101, 102, 103]
> +                description: mt8196 pull up PUPD/R0/R1 type define value.
> +              - enum: [1000, 1500, 2000, 3000, 4000, 5000, 75000]
> +                description: mt8196 pull up RSEL type si unit value(ohm).
> +            description: |
> +              For pull up type is normal, it don't need add R1R0 define
> +              and resistance value.
> +              For pull up type is PUPD/R0/R1 type, it can add R1R0 define to
> +              set different resistance. It can support "MTK_PUPD_SET_R1R0_00" &
> +              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
> +              "MTK_PUPD_SET_R1R0_11" define in mt8196.
> +              For pull up type is PU/RSEL, it can add resistance value(ohm)
> +              to set different resistance by identifying property
> +              "mediatek,rsel-resistance-in-si-unit". It can support resistance
> +              value(ohm) "1000" & "1500" & "2000" & "3000" & "4000" & "5000" &
> +              "75000" in mt8196.
> +
> +          bias-disable: true
> +
> +          output-high: true
> +
> +          output-low: true
> +
> +          input-enable: true
> +
> +          input-disable: true
> +
> +          input-schmitt-enable: true
> +
> +          input-schmitt-disable: true
> +
> +        required:
> +          - pinmux
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - interrupt-controller
> +  - '#interrupt-cells'
> +  - gpio-controller
> +  - '#gpio-cells'
> +  - gpio-ranges

Same order as in properties list. The order here looks correct, so the
properties needs to be fixed.


Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 24 01:03:53 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 09:03:53 +0100
Subject: [PATCH v5 2/3] arm64: dts: mediatek: mt8196: Add pinmux macro
 header file
In-Reply-To: <20250321084142.18563-3-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
 <20250321084142.18563-3-ot_cathy.xu@mediatek.com>
Message-ID: <20250324-cunning-ruby-lorikeet-aac6bf@krzk-bin>

On Fri, Mar 21, 2025 at 04:39:13PM +0800, Cathy Xu wrote:
> Add the pinctrl header file on MediaTek mt8196.
> 
> Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
> Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h | 1574 +++++++++++++++++
>  1 file changed, 1574 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
> 

Where is the change adding the pinctrl nodes to the DTS?

Best regards,
Krzysztof



From ryan_chen at aspeedtech.com  Mon Mar 24 01:30:16 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Mon, 24 Mar 2025 08:30:16 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
Message-ID: <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 19/03/2025 12:12, Ryan Chen wrote:
> >> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >> AST2600-i2cv2
> >>
> >> On 17/03/2025 10:21, Ryan Chen wrote:
> >>>> Neither this.
> >>>>
> >>>> So it seems you describe already existing and documented I2C, but
> >>>> for some reason you want second compatible. The problem is that you
> >>>> do not provide reason from the point of view of bindings.
> >>>>
> >>>> To summarize: what your users want - don't care. Start properly
> >>>> describing hardware and your SoC.
> >>>
> >>> OK, for ast2600 i2c controller have two register mode setting.
> >>> One, I call it is old register setting, that is right now
> >>> i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus", And there have
> >>> a global register
> >> that can set i2c controller as new mode register set.
> >>> That I am going to drive. That I post is all register in new an old register
> list.
> >>>
> >>> For example,
> >>> Global register [2] = 0 => i2c present as old register set Global
> >>> register [2] = 1 => i2c present as new register set
> >> It's the same device though, so the same compatible.
> >
> > Sorry, it is different design, and it share the same register space.
> > So that the reason add new compatible "aspeed,ast2600-i2cv2" for this
> driver.
> > It is different register layout.
> 
> Which device is described by the existing "aspeed,ast2600-i2c-bus"
> compatible? And which device is described by new compatible?
> 
On the AST2600 SoC, there are up to 16 I2C controller instances (I2C1 ~ I2C16).
Each of these controllers is hardwired at the SoC level to use either the legacy register layout or the new v2 register layout.
The mode is selected by a bit in the global register, these represent two different hardware blocks:
"aspeed,ast2600-i2c-bus" describes controllers using the legacy register layout.
"aspeed,ast2600-i2cv2" describes controllers using the new register layout
> 
> 
> Best regards,
> Krzysztof

From ck.hu at mediatek.com  Mon Mar 24 01:33:20 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 24 Mar 2025 08:33:20 +0000
Subject: [PATCH v2 11/15] drm/mediatek: add BLENDER support for MT8196
In-Reply-To: <20250321093435.94835-12-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-12-paul-pl.chen@mediatek.com>
Message-ID: <0daf839388be6861c1d0d02d6167942a57ec8e38.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> BLENDER executes the alpha blending function for overlapping
> layers from different sources, which is the primary function
> of the overlapping system.
> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> 
> ---
>  drivers/gpu/drm/mediatek/Makefile           |   1 +
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.c     |   1 +
>  drivers/gpu/drm/mediatek/mtk_ddp_comp.h     |   1 +
>  drivers/gpu/drm/mediatek/mtk_disp_blender.c | 276 ++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_disp_blender.h |  18 ++
>  drivers/gpu/drm/mediatek/mtk_disp_drv.h     |  12 +
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   1 +
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h      |   1 +
>  8 files changed, 311 insertions(+)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
> 
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index db92f4fb353d..a7b9ebe27f68 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -3,6 +3,7 @@
>  mediatek-drm-y := mtk_crtc.o \
>  		  mtk_ddp_comp.o \
>  		  mtk_disp_aal.o \
> +		  mtk_disp_blender.o \
>  		  mtk_disp_ccorr.o \
>  		  mtk_disp_color.o \
>  		  mtk_disp_exdma.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index 3e0739d8e6f1..e65c6df987f2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
>  	[MTK_DP_INTF] = "dp-intf",
>  	[MTK_DPI] = "dpi",
>  	[MTK_DSI] = "dsi",
> +	[MTK_OVL_BLENDER] = "blender",
>  	[MTK_OVL_EXDMA] = "exdma",
>  };
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 86dc0ee3924c..075ba5683f93 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
>  	MTK_DPI,
>  	MTK_DP_INTF,
>  	MTK_DSI,
> +	MTK_OVL_BLENDER,
>  	MTK_OVL_EXDMA,
>  	MTK_DDP_COMP_TYPE_MAX,
>  };
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> new file mode 100644
> index 000000000000..32c9e3d463a4
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> @@ -0,0 +1,276 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_blend.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +#include <linux/soc/mediatek/mtk-mmsys.h>
> +
> +#include "mtk_crtc.h"
> +#include "mtk_ddp_comp.h"
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_blender.h"
> +#include "mtk_disp_ovl.h"
> +
> +#define OVL_BLD_ALPHA					0xff
> +#define DISP_REG_OVL_BLD_DATAPATH_CON			0x010
> +#define OVL_BLD_BGCLR_IN_SEL					BIT(0)
> +#define OVL_BLD_BGCLR_OUT_TO_PROC				BIT(4)
> +#define OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER				BIT(5)
> +
> +#define DISP_REG_OVL_BLD_EN				0x020
> +#define OVL_BLD_EN						BIT(0)
> +#define OVL_BLD_FORCE_RELAY_MODE				BIT(4)
> +#define OVL_BLD_RELAY_MODE					BIT(5)
> +#define DISP_REG_OVL_BLD_RST				0x024
> +#define OVL_BLD_RST						BIT(0)
> +#define DISP_REG_OVL_BLD_SHADOW_CTRL			0x028
> +#define OVL_BLD_BYPASS_SHADOW					BIT(2)
> +#define DISP_REG_OVL_BLD_BGCLR_BALCK			0xff000000
> +#define DISP_REG_OVL_BLD_ROI_SIZE			0x030
> +#define DISP_REG_OVL_BLD_L_EN				0x040
> +#define OVL_BLD_L_EN						BIT(0)
> +#define DISP_REG_OVL_BLD_OFFSET				0x044
> +#define DISP_REG_OVL_BLD_SRC_SIZE			0x048
> +#define DISP_REG_OVL_BLD_L0_CLRFMT			0x050
> +#define OVL_BLD_CON_FLD_CLRFMT					GENMASK(3, 0)
> +#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
> +#define OVL_BLD_CON_FLD_CLRFMT_NB				GENMASK(9, 8)
> +#define OVL_BLD_CON_CLRFMT_NB_10_BIT				BIT(8)
> +#define OVL_BLD_CON_BYTE_SWAP					BIT(16)
> +#define OVL_BLD_CON_RGB_SWAP					BIT(17)
> +#define DISP_REG_OVL_BLD_BGCLR_CLR			0x104
> +#define DISP_REG_OVL_BLD_L_CON2				0x200
> +#define OVL_BLD_L_ALPHA						GENMASK(7, 0)
> +#define OVL_BLD_L_ALPHA_EN					BIT(12)
> +#define DISP_REG_OVL_BLD_L0_PITCH			0x208

DISP_REG_OVL_BLD_L0_PITCH is useless, so drop it.

> +#define OVL_BLD_L0_CONST					BIT(24)
> +#define DISP_REG_OVL_BLD_L0_CLR				0x20c
> +#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
> +#define OVL_BLD_L0_SRC_PITCH					GENMASK(15, 0)
> +#define DISP_REG_OVL_BLD_PITCH				0x2f4
> +
> +struct mtk_disp_blender {
> +	void __iomem		*regs;
> +	struct clk		*clk;
> +	struct cmdq_client_reg	cmdq_reg;
> +};
> +
> +void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
> +				   struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +	struct mtk_plane_pending_state *pending = &state->pending;
> +	unsigned int align_width = ALIGN_DOWN(pending->width, 2);

If width is 101, changing width to 100 would get correct display output?

> +	unsigned int alpha;
> +	unsigned int clrfmt;
> +	unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> +							 BIT(DRM_MODE_BLEND_PREMULTI) |
> +							 BIT(DRM_MODE_BLEND_COVERAGE) |
> +							 BIT(DRM_MODE_BLEND_PIXEL_NONE));
> +	unsigned int ignore_pixel_alpha = 0;
> +
> +	if (!pending->enable) {
> +		mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> +		return;
> +	}
> +
> +	mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_OFFSET);
> +
> +	mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> +		      priv->regs, DISP_REG_OVL_BLD_SRC_SIZE);
> +
> +	clrfmt = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
> +				     OVL_BLD_CON_CLRFMT_MAN, OVL_BLD_CON_BYTE_SWAP,
> +				     OVL_BLD_CON_RGB_SWAP);
> +	clrfmt |= mtk_ovl_is_10bit_rgb(pending->format) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0;
> +	mtk_ddp_write_mask(cmdq_pkt, clrfmt, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_L0_CLRFMT, OVL_BLD_CON_CLRFMT_MAN |
> +			   OVL_BLD_CON_RGB_SWAP |  OVL_BLD_CON_BYTE_SWAP |
> +			   OVL_BLD_CON_FLD_CLRFMT | OVL_BLD_CON_FLD_CLRFMT_NB);
> +
> +	alpha = (OVL_BLD_ALPHA & (state->base.alpha >> 8)) |
> +		OVL_BLD_L_ALPHA_EN;
> +
> +	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> +		ignore_pixel_alpha = OVL_BLD_L0_CONST;
> +
> +	mtk_ddp_write_mask(cmdq_pkt, pending->pitch | ignore_pixel_alpha,
> +			   &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_PITCH, OVL_BLD_L0_CONST | OVL_BLD_L0_SRC_PITCH);

EXDMA already has pitch function, why BLENDER also has pitch function?
What does BLENDER pitch do?

> +
> +	mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
> +
> +	mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> +}
> +
> +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> +			     unsigned int h, unsigned int vrefresh,
> +			     unsigned int bpc, bool most_top,
> +			     bool most_bottom, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +	u32 datapath;
> +
> +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_ROI_SIZE);
> +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_BGCLR_CLR);
> +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_L0_CLR);

I think I know what is BGLCR_CLR, but what is L0_CLR?

> +
> +	if (most_top)
> +		datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
> +	else
> +		datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
> +	/*
> +	 * The primary input is from EXDMA and the second input
> +	 * is optionally from another blender
> +	 */
> +	if (!most_bottom)
> +		datapath |= OVL_BLD_BGCLR_IN_SEL;
> +
> +	mtk_ddp_write_mask(cmdq_pkt, datapath,
> +			   &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
> +			   OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
> +			   OVL_BLD_BGCLR_IN_SEL);
> +}
> +
> +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +	unsigned int tmp;
> +
> +	tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> +	tmp = tmp | OVL_BLD_BYPASS_SHADOW;
> +	writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> +}
> +
> +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> +	mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);

You already control OVL_BLD_EN in layer config, so it's not necessary to control here.

Regards,
CK

> +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> +}
> +
> 


From kevin.brodsky at arm.com  Mon Mar 24 01:37:56 2025
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon, 24 Mar 2025 09:37:56 +0100
Subject: [PATCH 02/11] mm: Call ctor/dtor for kernel PTEs
In-Reply-To: <20250317141700.3701581-3-kevin.brodsky@arm.com>
References: <20250317141700.3701581-1-kevin.brodsky@arm.com>
 <20250317141700.3701581-3-kevin.brodsky@arm.com>
Message-ID: <efc72f28-0dcb-4811-a20c-73bcdbdf28fb@arm.com>

On 17/03/2025 15:16, Kevin Brodsky wrote:
> diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
> index e164ca66f0f6..3c8ec3bfea44 100644
> --- a/include/asm-generic/pgalloc.h
> +++ b/include/asm-generic/pgalloc.h
> @@ -23,6 +23,11 @@ static inline pte_t *__pte_alloc_one_kernel_noprof(struct mm_struct *mm)
>  
>  	if (!ptdesc)
>  		return NULL;
> +	if (!pagetable_pte_ctor(mm, ptdesc)) {

As reported by the CI [1], this can cause trouble on x86 because dtor
calls are missing in pud_free_pmd_page() and pmd_free_pte_page(). Will
fix in the next version.

- Kevin

[1] https://lore.kernel.org/oe-lkp/202503211612.e11bd73f-lkp at intel.com/


From boris.brezillon at collabora.com  Mon Mar 24 01:43:33 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 24 Mar 2025 09:43:33 +0100
Subject: [PATCH v2 4/9] drm/panthor: Implement optional reset
In-Reply-To: <20250321200625.132494-5-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
	<20250321200625.132494-5-marex@denx.de>
Message-ID: <20250324094333.7afb17a1@collabora.com>

On Fri, 21 Mar 2025 21:05:54 +0100
Marek Vasut <marex at denx.de> wrote:

> The instance of the GPU populated in Freescale i.MX95 does require
> release from reset by writing into a single GPUMIX block controller
> GPURESET register bit 0. Implement support for one optional reset.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: David Airlie <airlied at gmail.com>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Liviu Dudau <liviu.dudau at arm.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Maxime Ripard <mripard at kernel.org>
> Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
> Cc: Philipp Zabel <p.zabel at pengutronix.de>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Sebastian Reichel <sre at kernel.org>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Simona Vetter <simona at ffwll.ch>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Thomas Zimmermann <tzimmermann at suse.de>
> Cc: devicetree at vger.kernel.org
> Cc: dri-devel at lists.freedesktop.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> V2: Drop the select RESET_SIMPLE from Kconfig
> ---
>  drivers/gpu/drm/panthor/panthor_device.c | 23 +++++++++++++++++++++++
>  drivers/gpu/drm/panthor/panthor_device.h |  3 +++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index a9da1d1eeb707..51ee9cae94504 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -64,6 +64,17 @@ static int panthor_clk_init(struct panthor_device *ptdev)
>  	return 0;
>  }
>  
> +static int panthor_reset_init(struct panthor_device *ptdev)
> +{
> +	ptdev->resets = devm_reset_control_get_optional_exclusive_deasserted(ptdev->base.dev, NULL);
> +	if (IS_ERR(ptdev->resets))
> +		return dev_err_probe(ptdev->base.dev,
> +				     PTR_ERR(ptdev->resets),
> +				     "get reset failed");
> +
> +	return 0;
> +}
> +
>  void panthor_device_unplug(struct panthor_device *ptdev)
>  {
>  	/* This function can be called from two different path: the reset work
> @@ -217,6 +228,10 @@ int panthor_device_init(struct panthor_device *ptdev)
>  	if (ret)
>  		return ret;
>  
> +	ret = panthor_reset_init(ptdev);
> +	if (ret)
> +		return ret;
> +
>  	ret = panthor_devfreq_init(ptdev);
>  	if (ret)
>  		return ret;
> @@ -470,6 +485,10 @@ int panthor_device_resume(struct device *dev)
>  	if (ret)
>  		goto err_disable_stacks_clk;
>  
> +	ret = reset_control_deassert(ptdev->resets);
> +	if (ret)
> +		goto err_disable_coregroup_clk;
> +
>  	panthor_devfreq_resume(ptdev);
>  
>  	if (panthor_device_is_initialized(ptdev) &&
> @@ -512,6 +531,9 @@ int panthor_device_resume(struct device *dev)
>  
>  err_suspend_devfreq:
>  	panthor_devfreq_suspend(ptdev);
> +	reset_control_assert(ptdev->resets);
> +
> +err_disable_coregroup_clk:
>  	clk_disable_unprepare(ptdev->clks.coregroup);
>  
>  err_disable_stacks_clk:
> @@ -563,6 +585,7 @@ int panthor_device_suspend(struct device *dev)
>  
>  	panthor_devfreq_suspend(ptdev);
>  
> +	reset_control_assert(ptdev->resets);

Hm, that might be the cause of the fast reset issue (which is a fast
resume more than a fast reset BTW): if you re-assert the reset line on
runtime suspend, I guess this causes a full GPU reset, and the MCU ends
up in a state where it needs a slow reset (all data sections reset to
their initial state). Can you try to move the reset_control_[de]assert
to the unplug/init functions?

>  	clk_disable_unprepare(ptdev->clks.coregroup);
>  	clk_disable_unprepare(ptdev->clks.stacks);
>  	clk_disable_unprepare(ptdev->clks.core);
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index da6574021664b..fea3a05778e2e 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -111,6 +111,9 @@ struct panthor_device {
>  		struct clk *coregroup;
>  	} clks;
>  
> +	/** @resets: GPU reset. */
> +	struct reset_control *resets;
> +
>  	/** @coherent: True if the CPU/GPU are memory coherent. */
>  	bool coherent;
>  



From krzk at kernel.org  Mon Mar 24 01:45:43 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 09:45:43 +0100
Subject: [PATCH v3 01/10] dt-bindings: phy: add exynos2200 eusb2 phy
 support
In-Reply-To: <20250321135854.1431375-2-ivo.ivanov.ivanov1@gmail.com>
References: <20250321135854.1431375-1-ivo.ivanov.ivanov1@gmail.com>
 <20250321135854.1431375-2-ivo.ivanov.ivanov1@gmail.com>
Message-ID: <20250324-important-kangaroo-of-prowess-0d2c30@krzk-bin>

On Fri, Mar 21, 2025 at 03:58:45PM +0200, Ivaylo Ivanov wrote:
>  description:
> -  eUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
> +  eUSB2 controller supports LS/FS/HS usb connectivity.
>  
>  properties:
>    compatible:
> @@ -23,6 +23,7 @@ properties:
>                - qcom,x1e80100-snps-eusb2-phy
>            - const: qcom,sm8550-snps-eusb2-phy
>        - const: qcom,sm8550-snps-eusb2-phy
> +      - const: samsung,exynos2200-snps-eusb2-phy

These two entries is just an enum.

>  
>    reg:
>      maxItems: 1
> @@ -31,12 +32,12 @@ properties:
>      const: 0
>  
>    clocks:
> -    items:
> -      - description: ref
> +    minItems: 1
> +    maxItems: 3

I am still not conviced that creating one schema for these devices
brings benefits. If this is going to be one binding, then keep the list
here with three items and add minItems, so the list is the same for all
variants.

>  
>    clock-names:
> -    items:
> -      - const: ref
> +    minItems: 1
> +    maxItems: 3

Keep the list here with three items and add minItems.


>  
>    resets:
>      maxItems: 1
> @@ -62,7 +63,52 @@ required:
>    - clock-names
>    - vdd-supply
>    - vdda12-supply
> -  - resets
> +
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - qcom,sm8550-snps-eusb2-phy
> +
> +    then:
> +      properties:
> +        reg:
> +          maxItems: 1

Not much improved, my comment is still valid.


> +
> +        clocks:
> +          items:
> +            - description: ref

maxItems: 1

> +
> +        clock-names:
> +          items:
> +            - const: ref

maxItems: 1

> +
> +      required:
> +        - resets
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - samsung,exynos2200-snps-eusb2-phy
> +
> +    then:
> +      properties:
> +

Drop blank line.

and the clocks get here minItems: 3

Best regards,
Krzysztof



From ck.hu at mediatek.com  Mon Mar 24 02:00:01 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Mon, 24 Mar 2025 09:00:01 +0000
Subject: [PATCH v2 12/15] drm/mediatek: add OUTPROC support for MT8196
In-Reply-To: <20250321093435.94835-13-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-13-paul-pl.chen@mediatek.com>
Message-ID: <297be0e3f2b5b9cb4d051cfae6e5f5868c3cb7b8.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> OUTPROC handles the post-stage of pixel processing in
> the overlapping procedure.OUTPROC manages pixels for
> gamma correction and ensures that pixel values are
> within the correct range.
> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---

[snip]

> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> new file mode 100644
> index 000000000000..a7c6d1982bca
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> @@ -0,0 +1,242 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +#include <linux/soc/mediatek/mtk-mmsys.h>
> +
> +#include "mtk_crtc.h"
> +#include "mtk_ddp_comp.h"
> +#include "mtk_drm_drv.h"

Alphabetic order.

> +#include "mtk_disp_outproc.h"
> +
> +#define DISP_REG_OVL_OUTPROC_INTEN				0x004
> +#define OVL_OUTPROC_FME_CPL_INTEN					BIT(1)
> +#define DISP_REG_OVL_OUTPROC_INTSTA				0x008
> +#define DISP_REG_OVL_OUTPROC_DATAPATH_CON			0x010
> +#define OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP				BIT(26)
> +
> +#define DISP_REG_OVL_OUTPROC_EN					0x020
> +#define OVL_OUTPROC_OVL_EN						BIT(0)
> +#define DISP_REG_OVL_OUTPROC_RST				0x024
> +#define OVL_OUTPROC_RST							BIT(0)
> +#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL			0x028
> +#define OVL_OUTPROC_BYPASS_SHADOW					BIT(2)
> +#define DISP_REG_OVL_OUTPROC_ROI_SIZE				0x030
> +
> +struct mtk_disp_outproc {
> +	void __iomem		*regs;
> +	struct clk		*clk;
> +	void			(*vblank_cb)(void *data);
> +	void			*vblank_cb_data;
> +	int			irq;
> +	struct cmdq_client_reg	cmdq_reg;
> +};
> +
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> +					 void (*vblank_cb)(void *),
> +					 void *vblank_cb_data)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	priv->vblank_cb = vblank_cb;
> +	priv->vblank_cb_data = vblank_cb_data;
> +}
> +
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	priv->vblank_cb = NULL;
> +	priv->vblank_cb_data = NULL;
> +}
> +
> +void mtk_disp_outproc_enable_vblank(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +void mtk_disp_outproc_disable_vblank(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void *dev_id)
> +{
> +	struct mtk_disp_outproc *priv = dev_id;
> +	u32 val;
> +
> +	val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> +	if (!val)
> +		return IRQ_NONE;
> +
> +	writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> +
> +	if (priv->vblank_cb)
> +		priv->vblank_cb(priv->vblank_cb_data);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> +			     unsigned int h, unsigned int vrefresh,
> +			     unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> +	//move mtk_ddp_write_mask to mtk_ddp_write

I think this comment is redundant.

> +	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_OUTPROC_ROI_SIZE);
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP,
> +			   &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_OUTPROC_DATAPATH_CON,
> +			   OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
> +}
> +
> +void mtk_disp_outproc_start(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +	unsigned int tmp;
> +
> +	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +	tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> +	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +
> +	mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_OUTPROC_INTSTA);
> +	mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);

Use readl() and writel().

> +}
> +
> +void mtk_disp_outproc_stop(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> +	mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
> +	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);

Use readl() and writel().

> +}
> +
> +




From krzk at kernel.org  Mon Mar 24 02:07:21 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 10:07:21 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
 <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
Message-ID: <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>

On 24/03/2025 09:30, Ryan Chen wrote:
>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>> AST2600-i2cv2
>>
>> On 19/03/2025 12:12, Ryan Chen wrote:
>>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>>>> AST2600-i2cv2
>>>>
>>>> On 17/03/2025 10:21, Ryan Chen wrote:
>>>>>> Neither this.
>>>>>>
>>>>>> So it seems you describe already existing and documented I2C, but
>>>>>> for some reason you want second compatible. The problem is that you
>>>>>> do not provide reason from the point of view of bindings.
>>>>>>
>>>>>> To summarize: what your users want - don't care. Start properly
>>>>>> describing hardware and your SoC.
>>>>>
>>>>> OK, for ast2600 i2c controller have two register mode setting.
>>>>> One, I call it is old register setting, that is right now
>>>>> i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus", And there have
>>>>> a global register
>>>> that can set i2c controller as new mode register set.
>>>>> That I am going to drive. That I post is all register in new an old register
>> list.
>>>>>
>>>>> For example,
>>>>> Global register [2] = 0 => i2c present as old register set Global
>>>>> register [2] = 1 => i2c present as new register set
>>>> It's the same device though, so the same compatible.
>>>
>>> Sorry, it is different design, and it share the same register space.
>>> So that the reason add new compatible "aspeed,ast2600-i2cv2" for this
>> driver.
>>> It is different register layout.
>>
>> Which device is described by the existing "aspeed,ast2600-i2c-bus"
>> compatible? And which device is described by new compatible?
>>
> On the AST2600 SoC, there are up to 16 I2C controller instances (I2C1 ~ I2C16).

So you have 16 same devices.

> Each of these controllers is hardwired at the SoC level to use either the legacy register layout or the new v2 register layout.
> The mode is selected by a bit in the global register, these represent two different hardware blocks:
> "aspeed,ast2600-i2c-bus" describes controllers using the legacy register layout.
> "aspeed,ast2600-i2cv2" describes controllers using the new register layout

Which part of "same device" is not clear? You have one device, one
compatible. Whatever you do with register layout, is already defined by
that compatible. It does not matter that you forgot to implement it in
the Linux kernel.

Best regards,
Krzysztof


From ot_cathy.xu at mediatek.com  Mon Mar 24 02:09:10 2025
From: ot_cathy.xu at mediatek.com (=?utf-8?B?Q2F0aHkgWHUgKOiuuOWNjuWptyk=?=)
Date: Mon, 24 Mar 2025 09:09:10 +0000
Subject: [PATCH v5 1/3] dt-bindings: pinctrl: mediatek: Add support for
 mt8196
In-Reply-To: <20250324-sly-smart-impala-9fb09e@krzk-bin>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
	 <20250321084142.18563-2-ot_cathy.xu@mediatek.com>
	 <20250324-sly-smart-impala-9fb09e@krzk-bin>
Message-ID: <08d775ee699ed258c6a7c0ae3ad3ba5f30037310.camel@mediatek.com>

On Mon, 2025-03-24 at 09:03 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, Mar 21, 2025 at 04:39:12PM +0800, Cathy Xu wrote:
> > +  reg:
> > +    items:
> > +      - description: gpio registers base address
> > +      - description: rt group io configuration registers base
> > address
> 
> s/io configuration registers base address/IO/
> ?
> 
> Why repeating so much of redundant information?

  Thank you for your review.
  All these registers related to different gpio configutations. Should
I delete them?

> 
> > +      - description: rm1 group io configuration registers base
> > address
> > +      - description: rm2 group io configuration registers base
> > address
> > +      - description: rb group io configuration registers base
> > address
> > +      - description: bm1 group io configuration registers base
> > address
> > +      - description: bm2 group io configuration registers base
> > address
> > +      - description: bm3 group io configuration registers base
> > address
> > +      - description: lt group io configuration registers base
> > address
> > +      - description: lm1 group io configuration registers base
> > address
> > +      - description: lm2 group io configuration registers base
> > address
> > +      - description: lb1 group io configuration registers base
> > address
> > +      - description: lb2 group io configuration registers base
> > address
> > +      - description: tm1 group io configuration registers base
> > address
> > +      - description: tm2 group io configuration registers base
> > address
> > +      - description: tm3 group io configuration registers base
> > address
> > +
> > +  reg-names:
> > +    items:
> > +      - const: iocfg0
> > +      - const: iocfg_rt
> > +      - const: iocfg_rm1
> > +      - const: iocfg_rm2
> > +      - const: iocfg_rb
> > +      - const: iocfg_bm1
> > +      - const: iocfg_bm2
> > +      - const: iocfg_bm3
> > +      - const: iocfg_lt
> > +      - const: iocfg_lm1
> > +      - const: iocfg_lm2
> > +      - const: iocfg_lb1
> > +      - const: iocfg_lb2
> > +      - const: iocfg_tm1
> > +      - const: iocfg_tm2
> > +      - const: iocfg_tm3
> 
> Same here, drop iocfg_ prefix everywhere. The first entry becames
> then
> "base" or whatever else meaningful ("0" is not meaningful).

  Ok, it will be fixed in next version.

> 
> 
> > +
> > +  interrupt-controller: true
> > +
> > +  '#interrupt-cells':
> > +    const: 2
> > +
> > +  interrupts:
> > +    description: The interrupt outputs to sysirq.
> > +    maxItems: 1
> > +
> > +# PIN CONFIGURATION NODES
> > +patternProperties:
> > +  '-pins$':
> > +    type: object
> > +    additionalProperties: false
> > +
> > +    patternProperties:
> > +      '^pins':
> > +        type: object
> > +        $ref: /schemas/pinctrl/pincfg-node.yaml
> > +        additionalProperties: false
> > +        description:
> > +          A pinctrl node should contain at least one subnode
> > representing the
> > +          pinctrl groups available on the machine. Each subnode
> > will list the
> > +          pins it needs, and how they should be configured, with
> > regard to muxer
> > +          configuration, pullups, drive strength, input
> > enable/disable and input
> > +          schmitt.
> > +
> > +        properties:
> > +          pinmux:
> > +            description:
> > +              Integer array, represents gpio pin number and mux
> > setting.
> > +              Supported pin number and mux varies for different
> > SoCs, and are
> > +              defined as macros in
> > arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
> > +              directly, for this SoC.
> > +
> > +          drive-strength:
> > +            enum: [2, 4, 6, 8, 10, 12, 14, 16]
> > +
> > +          bias-pull-down:
> > +            oneOf:
> > +              - type: boolean
> > +              - enum: [100, 101, 102, 103]
> > +                description: mt8196 pull down PUPD/R0/R1 type
> > define value.
> > +              - enum: [75000, 5000]
> > +                description: mt8196 pull down RSEL type si unit
> > value(ohm).
> > +            description: |
> > +              For pull down type is normal, it doesn't need add
> > R1R0 define
> > +              and resistance value.
> > +              For pull down type is PUPD/R0/R1 type, it can add
> > R1R0 define to
> > +              set different resistance. It can support
> > "MTK_PUPD_SET_R1R0_00" &
> > +              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
> > +              "MTK_PUPD_SET_R1R0_11" define in mt8196.
> > +              For pull down type is PD/RSEL, it can add resistance
> > value(ohm)
> > +              to set different resistance by identifying property
> > +              "mediatek,rsel-resistance-in-si-unit". It can
> > support resistance
> > +              value(ohm) "75000" & "5000" in mt8196.
> > +
> > +          bias-pull-up:
> > +            oneOf:
> > +              - type: boolean
> > +              - enum: [100, 101, 102, 103]
> > +                description: mt8196 pull up PUPD/R0/R1 type define
> > value.
> > +              - enum: [1000, 1500, 2000, 3000, 4000, 5000, 75000]
> > +                description: mt8196 pull up RSEL type si unit
> > value(ohm).
> > +            description: |
> > +              For pull up type is normal, it don't need add R1R0
> > define
> > +              and resistance value.
> > +              For pull up type is PUPD/R0/R1 type, it can add R1R0
> > define to
> > +              set different resistance. It can support
> > "MTK_PUPD_SET_R1R0_00" &
> > +              "MTK_PUPD_SET_R1R0_01" & "MTK_PUPD_SET_R1R0_10" &
> > +              "MTK_PUPD_SET_R1R0_11" define in mt8196.
> > +              For pull up type is PU/RSEL, it can add resistance
> > value(ohm)
> > +              to set different resistance by identifying property
> > +              "mediatek,rsel-resistance-in-si-unit". It can
> > support resistance
> > +              value(ohm) "1000" & "1500" & "2000" & "3000" &
> > "4000" & "5000" &
> > +              "75000" in mt8196.
> > +
> > +          bias-disable: true
> > +
> > +          output-high: true
> > +
> > +          output-low: true
> > +
> > +          input-enable: true
> > +
> > +          input-disable: true
> > +
> > +          input-schmitt-enable: true
> > +
> > +          input-schmitt-disable: true
> > +
> > +        required:
> > +          - pinmux
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +  - interrupt-controller
> > +  - '#interrupt-cells'
> > +  - gpio-controller
> > +  - '#gpio-cells'
> > +  - gpio-ranges
> 
> Same order as in properties list. The order here looks correct, so
> the
> properties needs to be fixed.

  Ok, it will be fixed in next version.

> 
> 
> Best regards,
> Krzysztof
> 

From ot_cathy.xu at mediatek.com  Mon Mar 24 02:12:09 2025
From: ot_cathy.xu at mediatek.com (=?utf-8?B?Q2F0aHkgWHUgKOiuuOWNjuWptyk=?=)
Date: Mon, 24 Mar 2025 09:12:09 +0000
Subject: [PATCH v5 2/3] arm64: dts: mediatek: mt8196: Add pinmux macro
 header file
In-Reply-To: <20250324-cunning-ruby-lorikeet-aac6bf@krzk-bin>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
	 <20250321084142.18563-3-ot_cathy.xu@mediatek.com>
	 <20250324-cunning-ruby-lorikeet-aac6bf@krzk-bin>
Message-ID: <311cc2b0bb1a6f23e036c2180a6179d6b1dbb4b1.camel@mediatek.com>

On Mon, 2025-03-24 at 09:03 +0100, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, Mar 21, 2025 at 04:39:13PM +0800, Cathy Xu wrote:
> > Add the pinctrl header file on MediaTek mt8196.
> > 
> > Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
> > Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>
> > ---
> >  arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h | 1574
> > +++++++++++++++++
> >  1 file changed, 1574 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/mediatek/mt8196-pinfunc.h
> > 
> 
> Where is the change adding the pinctrl nodes to the DTS?

  The DTS will be sent by someone else later.

> 
> Best regards,
> Krzysztof
> 

From ziniu.wang_1 at nxp.com  Mon Mar 24 02:23:36 2025
From: ziniu.wang_1 at nxp.com (ziniu.wang_1 at nxp.com)
Date: Mon, 24 Mar 2025 17:23:36 +0800
Subject: [PATCH 2/2] mmc: sdhci-esdhc-imx: calclute data timeout value based on clock
Message-ID: <20250324092336.2231385-1-ziniu.wang_1@nxp.com>

From: Luke Wang <ziniu.wang_1 at nxp.com>

Calclute data timeout value based on clock instead of using max value.

Signed-off-by: Luke Wang <ziniu.wang_1 at nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index ff78a7c6a04c..e7316ecff64e 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -31,6 +31,7 @@
 #include "cqhci.h"
 
 #define ESDHC_SYS_CTRL_DTOCV_MASK	GENMASK(19, 16)
+#define ESDHC_SYS_CTRL_DTOCV_SHIFT	16
 #define ESDHC_SYS_CTRL_IPP_RST_N	BIT(23)
 #define	ESDHC_CTRL_D3CD			0x08
 #define ESDHC_BURST_LEN_EN_INCR		(1 << 27)
@@ -1387,12 +1388,16 @@ static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host)
 
 static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+	bool too_big = false;
+	u8 count = sdhci_calc_timeout(host, cmd, &too_big);
 
-	/* use maximum timeout counter */
+	/*
+	 * ESDHC_SYSTEM_CONTROL bit[23] used to control hardware reset
+	 * pin of the card. Write 0 to bit[23] will reset the card.
+	 * Only write DTOCV filed here.
+	 */
 	esdhc_clrset_le(host, ESDHC_SYS_CTRL_DTOCV_MASK,
-			esdhc_is_usdhc(imx_data) ? 0xF0000 : 0xE0000,
+			count << ESDHC_SYS_CTRL_DTOCV_SHIFT,
 			ESDHC_SYSTEM_CONTROL);
 }
 
@@ -1777,6 +1782,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 		 * to distinguish the card type.
 		 */
 		host->mmc_host_ops.init_card = usdhc_init_card;
+
+		host->max_timeout_count = 0xF;
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
-- 
2.34.1



From ziniu.wang_1 at nxp.com  Mon Mar 24 02:22:40 2025
From: ziniu.wang_1 at nxp.com (ziniu.wang_1 at nxp.com)
Date: Mon, 24 Mar 2025 17:22:40 +0800
Subject: [PATCH 1/2] mmc: sdhci: convert sdhci_calc_timeout() to non-static
Message-ID: <20250324092240.2230955-1-ziniu.wang_1@nxp.com>

From: Luke Wang <ziniu.wang_1 at nxp.com>

Export sdhci_calc_timeout() so that it is accessible from platform drivers.

Signed-off-by: Luke Wang <ziniu.wang_1 at nxp.com>
---
 drivers/mmc/host/sdhci.c | 5 +++--
 drivers/mmc/host/sdhci.h | 2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5f91b44891f9..ec99616cc51e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -966,8 +966,8 @@ static void sdhci_calc_sw_timeout(struct sdhci_host *host,
 		host->data_timeout += MMC_CMD_TRANSFER_TIME;
 }
 
-static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
-			     bool *too_big)
+u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
+		      bool *too_big)
 {
 	u8 count;
 	struct mmc_data *data;
@@ -1023,6 +1023,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
 
 	return count;
 }
+EXPORT_SYMBOL_GPL(sdhci_calc_timeout);
 
 static void sdhci_set_transfer_irqs(struct sdhci_host *host)
 {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index cd0e35a80542..71a48899c29b 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -897,5 +897,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode);
 void sdhci_switch_external_dma(struct sdhci_host *host, bool en);
 void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable);
 void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd);
+u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
+		      bool *too_big);
 
 #endif /* __SDHCI_HW_H */
-- 
2.34.1



From quentin.schulz at cherry.de  Mon Mar 24 02:23:03 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Mon, 24 Mar 2025 10:23:03 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
 <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
Message-ID: <2ece5cca-50ea-4ec9-927e-e757c9c10c18@cherry.de>

Hi Dragan,

On 3/23/25 11:19 AM, Dragan Simic wrote:
> Hello Quentin,
> 
> Thanks for your comments!? Please see some responses below.
> 
> On 2025-03-21 10:53, Quentin Schulz wrote:
>> On 3/21/25 4:28 AM, Dragan Simic wrote:
>>> The differences in the vendor-approved CPU and GPU OPPs for the standard
>>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>>> variant [2]
>>> come from the latter, presumably, supporting an extended temperature 
>>> range
>>> that's usually associated with industrial applications, despite the 
>>> two SoC
>>> variant datasheets specifying the same upper limit for the allowed 
>>> ambient
>>> temperature for both variants.? However, the lower temperature limit is
>>
>> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
>> Operating Conditions, Table 3-2, Ambient Operating Temperature.
> 
> Indeed, which is why I specifically wrote "specifying the same upper
> limit", because having a lower negative temperature limit could hardly
> put the RK3588J in danger of overheating or running hotter. :)
> 

"""
despite the two SoC variant datasheets specifying the same upper limit 
for the allowed temperature for both variants
"""

is incorrect. The whole range is different, yes it's only a 5?C 
difference for the upper limit, but they still are different.

>>> specified much lower for the RK3588J variant. [1][2]
>>>
>>> To be on the safe side and to ensure maximum longevity of the RK3588J 
>>> SoCs,
>>> only the CPU and GPU OPPs that are declared by the vendor to be 
>>> always safe
>>> for this SoC variant may be provided.? As explained by the vendor [3] 
>>> and
>>> according to its datasheet, [2] the RK3588J variant can actually run 
>>> safely
>>> at higher CPU and GPU OPPs as well, but only when not enjoying the 
>>> assumed
>>> extended temperature range that the RK3588J, as an SoC variant targeted
>>
>> "only when not enjoying the assumed extended temperature range" is
>> extrapolated by me/us and not confirmed by Rockchip themselves. I've
>> asked for a statement on what "industrial environment" they specify in
>> the Normal Mode explanation means since it's the only time they use
>> the term. I've yet to receive an answer. The only thing Rockchip in
>> their datasheet is that the overdrive mode will shorten lifetime when
>> used for a long time, especially in high temperature conditions. It's
>> not clear whether we can use the overdrive mode even within the RK3588
>> typical range of operation.
> 
> True.? I'll see to rephrase the patch description a bit in the v2,
> to avoid this kind of speculation.? I mean, perhaps the speculation
> is right, but it hasn't been confirmed officially by Rockchip.
> 

Speculation is fine, but it should be worded as such.

[...]

>>> The provided RK3588J CPU OPPs follow the slightly debatable "provide 
>>> only
>>> the highest-frequency OPP from the same-voltage group" approach 
>>> that's been
>>
>> Interesting that we went for a different strategy for the GPU OPPs :)
> 
> Good point, and I'm fully aware of that. :)? Actually, I'm rather
> sure that omitting the additional CPU OPPs does no good to us, but
> I didn't want to argue about that when they were dropped originally,
> before I can have some hard numbers to prove it in a repeatable way.
> 

I assume we'll have some patch in the future with those added and those 
hard numbers you're talking about, so looking forward to seeing it on 
the ML :)

[...]

>>> Helped-by: Quentin Schulz <quentin.schulz at cherry.de>
>>
>> Reported-by/Suggested-by?
>>
>> I don't see Helped-by in
>> https://eur02.safelinks.protection.outlook.com/? 
>> url=https%3A%2F%2Fwww.kernel.org%2Fdoc%2Fhtml%2Flatest%2Fprocess%2Fsubmitting-patches.html%23using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes&data=05%7C02%7Cquentin.schulz%40cherry.de%7Cdc754791b6844506b11c08dd69f444a7%7C5e0e1b5221b54e7b83bb514ec460677e%7C0%7C0%7C638783220330058516%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=4bv9pUh6aSD0GVLJ4Zvuyvox1K0xxwf83KXX86QsvMo%3D&reserved=0
>>
>> I see 2496b2aaacf137250f4ca449f465e2cadaabb0e8 got the Helped-by
>> replaced by a Suggested-by for example, but I see other patches with
>> Helped-by... if that is a standard trailer for kernel patches, then
>> maybe we should add it to that doc?
> 
> Actually, I already tried to get the Helped-by tag added to the
> kernel documentation, by submitting a small patch series. [*]
> Unfortunately, it got rejected. :/
> 
> However, Heiko accepts Helped-by tags and nobody higher up the
> tree seems to complain, so we should be fine. :)? It isn't the
> case with all maintainers, though.
> 
> [*] https://eur02.safelinks.protection.outlook.com/? 
> url=https%3A%2F%2Flore.kernel.org%2Fall%2Fcover.1730874296.git.dsimic%40manjaro.org%2FT%2F%23u&data=05%7C02%7Cquentin.schulz%40cherry.de%7Cdc754791b6844506b11c08dd69f444a7%7C5e0e1b5221b54e7b83bb514ec460677e%7C0%7C0%7C638783220330070422%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3dZgSG%2FBT6f%2Ffqs7D30HvEl18SzqYPwNeUGWBZfMAqM%3D&reserved=0
> 

Are you trying to up the numbers of Helped-by in commit logs to make it 
a reasonable request to add the trailer in the documentation :) ?

Cheers,
Quentin


From krzk at kernel.org  Mon Mar 24 02:33:26 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 10:33:26 +0100
Subject: [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add
 compatible for MT8196
In-Reply-To: <20250321093435.94835-2-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-2-paul-pl.chen@mediatek.com>
Message-ID: <20250324-bipedal-berserk-carp-6eeb5f@krzk-bin>

On Fri, Mar 21, 2025 at 05:33:30PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen at mediatek.com>
> 
> In previous SoCs, a single HW pipeline was an independent mmsys,
> which included the OVL module, PQ module, and display interface
> module.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 24 02:34:03 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 10:34:03 +0100
Subject: [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml for
 MT8196
In-Reply-To: <20250321093435.94835-3-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-3-paul-pl.chen@mediatek.com>
Message-ID: <20250324-amusing-pearl-yak-9d925a@krzk-bin>

On Fri, Mar 21, 2025 at 05:33:31PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen at mediatek.com>
> 
> Add compatible string to support mutex for MT8196.
> 
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>  .../devicetree/bindings/soc/mediatek/mediatek,mutex.yaml        | 2 ++
>  1 file changed, 2 insertions(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From krzk at kernel.org  Mon Mar 24 02:36:35 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 10:36:35 +0100
Subject: [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER
 yaml for MT8196
In-Reply-To: <20250321093435.94835-5-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-5-paul-pl.chen@mediatek.com>
Message-ID: <20250324-vigilant-vagabond-earthworm-b4e2c9@krzk-bin>

On Fri, Mar 21, 2025 at 05:33:33PM +0800, paul-pl.chen wrote:
> +additionalProperties: false
> +
> +examples:
> +  - |
> +

Why did you add here blank line? Random changes happening...

> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        disp_ovl0_blender0: blender at 328d0000 {
> +            compatible = "mediatek,mt8196-blender";
> +            reg = <0 0x328d0000 0 0x1000>;
> +            clocks = <&ovlsys_config_clk 29>;

With fixed code:

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof



From dsimic at manjaro.org  Mon Mar 24 02:36:54 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Mon, 24 Mar 2025 10:36:54 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
 <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
Message-ID: <460503eb831485ede9a49dcf226aef1b@manjaro.org>

Hello Quentin,

On 2025-03-23 11:19, Dragan Simic wrote:
> On 2025-03-21 10:53, Quentin Schulz wrote:
>> On 3/21/25 4:28 AM, Dragan Simic wrote:
>>> The differences in the vendor-approved CPU and GPU OPPs for the 
>>> standard
>>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>>> variant [2]
>>> come from the latter, presumably, supporting an extended temperature 
>>> range
>>> that's usually associated with industrial applications, despite the 
>>> two SoC
>>> variant datasheets specifying the same upper limit for the allowed 
>>> ambient
>>> temperature for both variants.  However, the lower temperature limit 
>>> is
>> 
>> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
>> Operating Conditions, Table 3-2, Ambient Operating Temperature.
> 
> Indeed, which is why I specifically wrote "specifying the same upper
> limit", because having a lower negative temperature limit could hardly
> put the RK3588J in danger of overheating or running hotter. :)

Oh, now I see what you actually wrote above, which I misread a bit
initially...  In fact, the upper ambient temperature limit is the
same for both RK3588J and RK3588, according to the datasheets;  it's
just that the lower temperature limit is much lower for the RK3588J,
which the patch description says.

I'm not sure where did you find the 80 vs. 85 oC difference;  please,
see a couple of screenshots from the datasheets, linked below:

- RK3588 datasheet v1.6 (v1.7 is the same): https://0x0.st/8j1a.png
- RK3588J datasheet v1.1: https://0x0.st/8j1m.png

The v2 of the patch is coming soon, with the patch description improved
according to your suggestions.


From patrice.chotard at foss.st.com  Mon Mar 24 02:40:14 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Mon, 24 Mar 2025 10:40:14 +0100
Subject: [PATCH v2 2/2] spi: spi-stm32-ospi: Make "resets" a required
 property
In-Reply-To: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>
References: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>
Message-ID: <20250324-upstream_ospi_required_resets-v2-2-85a48afcedec@foss.st.com>

On some STM32MP2 SoCs, an Octo Memory Manager is embedded and
need to retrieve OSPI's reset to perform its own initialization.
Make "resets" property mandatory.

Fixes: 79b8a705e26c ("spi: stm32: Add OSPI driver")
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 drivers/spi/spi-stm32-ospi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index d4f413c8c3ce1a51d2302602d46c7605a8bbc605..d3839a4dacf9f2eb95bafad9f7a8538ce2bb3598 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -804,7 +804,7 @@ static int stm32_ospi_get_resources(struct platform_device *pdev)
 		return ret;
 	}
 
-	ospi->rstc = devm_reset_control_array_get_optional_exclusive(dev);
+	ospi->rstc = devm_reset_control_array_get_exclusive(dev);
 	if (IS_ERR(ospi->rstc))
 		return dev_err_probe(dev, PTR_ERR(ospi->rstc),
 				     "Can't get reset\n");

-- 
2.25.1



From patrice.chotard at foss.st.com  Mon Mar 24 02:40:13 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Mon, 24 Mar 2025 10:40:13 +0100
Subject: [PATCH v2 1/2] spi: dt-bindings: st,stm32mp25-ospi: Make "resets"
 a required property
In-Reply-To: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>
References: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>
Message-ID: <20250324-upstream_ospi_required_resets-v2-1-85a48afcedec@foss.st.com>

On STM32MP2x SoC's family, OSPI is child of Octo Memory Manager which
must have asccess to OSPI's reset to ensure its initialization.
Make "resets" a required property.

Fixes: bed97e35786a ("dt-bindings: spi: Add STM32 OSPI controller")
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml b/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
index 5f276f27dc4c1fd2056f129cafc1005eaee8008f..272bc308726b2dfdf3ec80740d70e0fd1bfc4fea 100644
--- a/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
+++ b/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
@@ -68,6 +68,7 @@ required:
   - compatible
   - reg
   - clocks
+  - resets
   - interrupts
   - st,syscfg-dlyb
 

-- 
2.25.1



From patrice.chotard at foss.st.com  Mon Mar 24 02:40:12 2025
From: patrice.chotard at foss.st.com (Patrice Chotard)
Date: Mon, 24 Mar 2025 10:40:12 +0100
Subject: [PATCH v2 0/2] spi: spi-stm32-ospi: dt-bindings fixes
Message-ID: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>

Make "resets" property mandatory.
Update spi-stm32-ospi driver and dt-bindings accordingly.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
Changes in v2:
- Update dt-bindings commit message to explain why OSPI's resets becomes
  a required property.
- Link to v1: https://lore.kernel.org/r/20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2 at foss.st.com

---
Patrice Chotard (2):
      spi: dt-bindings: st,stm32mp25-ospi: Make "resets" a required property
      spi: spi-stm32-ospi: Make "resets" a required property

 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
 drivers/spi/spi-stm32-ospi.c                                 | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
---
base-commit: e94bd4ec45ac156616da285a0bf03056cd7430fc
change-id: 20250321-upstream_ospi_required_resets-34a8b17611b6

Best regards,
-- 
Patrice Chotard <patrice.chotard at foss.st.com>



From phasta at kernel.org  Mon Mar 24 02:29:26 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Mon, 24 Mar 2025 10:29:26 +0100
Subject: [PATCH net-next v4 0/3] stmmac: Several PCI-related improvements
Message-ID: <20250324092928.9482-2-phasta@kernel.org>

Resend of v4, rebased onto net-next due to a merge conflict.

Changes in v4:
  - Add missing full stop. (Yanteng)
  - Move forgotten unused-variable-removes to the appropriate places.
  - Add applicable RB / TB tags

Changes in v3:
  - Several formatting nits (Paolo)
  - Split up patch into a patch series (Yanteng)

Philipp Stanner (3):
  stmmac: loongson: Remove surplus loop
  stmmac: Remove pcim_* functions for driver detach
  stmmac: Replace deprecated PCI functions

 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 27 +++++--------------
 .../net/ethernet/stmicro/stmmac/stmmac_pci.c  | 24 +++++------------
 2 files changed, 12 insertions(+), 39 deletions(-)

-- 
2.48.1



From phasta at kernel.org  Mon Mar 24 02:29:28 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Mon, 24 Mar 2025 10:29:28 +0100
Subject: [PATCH net-next v4 1/3] stmmac: loongson: Remove surplus loop
In-Reply-To: <20250324092928.9482-2-phasta@kernel.org>
References: <20250324092928.9482-2-phasta@kernel.org>
Message-ID: <20250324092928.9482-4-phasta@kernel.org>

loongson_dwmac_probe() contains a loop which doesn't have an effect,
because it tries to call pcim_iomap_regions() with the same parameters
several times. The break statement at the loop's end furthermore ensures
that the loop only runs once anyways.

Remove the surplus loop.

Signed-off-by: Philipp Stanner <phasta at kernel.org>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
Tested-by: Henry Chen <chenx97 at aosc.io>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
---
 .../net/ethernet/stmicro/stmmac/dwmac-loongson.c    | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index f1c62f237e58..7e8495547934 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -536,7 +536,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
 	struct loongson_data *ld;
-	int ret, i;
+	int ret;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -566,14 +566,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	pci_set_master(pdev);
 
 	/* Get the base address of device */
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
-		if (ret)
-			goto err_disable_device;
-		break;
-	}
+	ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
+	if (ret)
+		goto err_disable_device;
 
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
-- 
2.48.1



From phasta at kernel.org  Mon Mar 24 02:29:29 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Mon, 24 Mar 2025 10:29:29 +0100
Subject: [PATCH net-next v4 2/3] stmmac: Remove pcim_* functions for driver detach
In-Reply-To: <20250324092928.9482-2-phasta@kernel.org>
References: <20250324092928.9482-2-phasta@kernel.org>
Message-ID: <20250324092928.9482-5-phasta@kernel.org>

Functions prefixed with "pcim_" are managed devres functions which
perform automatic cleanup once the driver unloads. It is, thus, not
necessary to call any cleanup functions in remove() callbacks.

Remove the pcim_ cleanup function calls in the remove() callbacks.

Signed-off-by: Philipp Stanner <phasta at kernel.org>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Yanteng Si <si.yanteng at linux.dev>
Tested-by: Henry Chen <chenx97 at aosc.io>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c |  8 --------
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c     | 12 +-----------
 2 files changed, 1 insertion(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 7e8495547934..e015e54d9190 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -619,7 +619,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 	struct net_device *ndev = dev_get_drvdata(&pdev->dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct loongson_data *ld;
-	int i;
 
 	ld = priv->plat->bsp_priv;
 	stmmac_dvr_remove(&pdev->dev);
@@ -630,13 +629,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 	if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
 		loongson_dwmac_msi_clear(pdev);
 
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		pcim_iounmap_regions(pdev, BIT(i));
-		break;
-	}
-
 	pci_disable_device(pdev);
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 352b01678c22..1637c8139b9d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -226,21 +226,11 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  * stmmac_pci_remove
  *
  * @pdev: platform device pointer
- * Description: this function calls the main to free the net resources
- * and releases the PCI resources.
+ * Description: this function calls the main to free the net resources.
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
-	int i;
-
 	stmmac_dvr_remove(&pdev->dev);
-
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		pcim_iounmap_regions(pdev, BIT(i));
-		break;
-	}
 }
 
 static int __maybe_unused stmmac_pci_suspend(struct device *dev)
-- 
2.48.1



From phasta at kernel.org  Mon Mar 24 02:29:30 2025
From: phasta at kernel.org (Philipp Stanner)
Date: Mon, 24 Mar 2025 10:29:30 +0100
Subject: [PATCH net-next v4 3/3] stmmac: Replace deprecated PCI functions
In-Reply-To: <20250324092928.9482-2-phasta@kernel.org>
References: <20250324092928.9482-2-phasta@kernel.org>
Message-ID: <20250324092928.9482-6-phasta@kernel.org>

The PCI functions
  - pcim_iomap_regions() and
  - pcim_iomap_table()
have been deprecated.

Replace them with their successor function, pcim_iomap_region().

Make variable declaration order at closeby places comply with reverse
christmas tree order.

Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Reviewed-by: Huacai Chen <chenhuacai at loongson.cn>
Tested-by: Henry Chen <chenx97 at aosc.io>
Signed-off-by: Philipp Stanner <phasta at kernel.org>
Reviewed-by: Jacob Keller <jacob.e.keller at intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c |  8 +++-----
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c     | 12 +++++-------
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index e015e54d9190..1a93787056a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -533,8 +533,8 @@ static int loongson_dwmac_fix_reset(void *priv, void __iomem *ioaddr)
 static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct plat_stmmacenet_data *plat;
+	struct stmmac_resources res = {};
 	struct stmmac_pci_info *info;
-	struct stmmac_resources res;
 	struct loongson_data *ld;
 	int ret;
 
@@ -566,13 +566,11 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	pci_set_master(pdev);
 
 	/* Get the base address of device */
-	ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME);
+	res.addr = pcim_iomap_region(pdev, 0, DRIVER_NAME);
+	ret = PTR_ERR_OR_ZERO(res.addr);
 	if (ret)
 		goto err_disable_device;
 
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[0];
-
 	plat->bsp_priv = ld;
 	plat->setup = loongson_dwmac_setup;
 	plat->fix_soc_reset = loongson_dwmac_fix_reset;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 1637c8139b9d..9c1b54b701f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -155,9 +155,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 {
 	struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
 	struct plat_stmmacenet_data *plat;
-	struct stmmac_resources res;
-	int i;
+	struct stmmac_resources res = {};
 	int ret;
+	int i;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -192,9 +192,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 		if (pci_resource_len(pdev, i) == 0)
 			continue;
-		ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
-		if (ret)
-			return ret;
+		res.addr = pcim_iomap_region(pdev, i, STMMAC_RESOURCE_NAME);
+		if (IS_ERR(res.addr))
+			return PTR_ERR(res.addr);
 		break;
 	}
 
@@ -204,8 +204,6 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		return ret;
 
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[i];
 	res.wol_irq = pdev->irq;
 	res.irq = pdev->irq;
 
-- 
2.48.1



From wsa+renesas at sang-engineering.com  Mon Mar 24 02:44:17 2025
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Mon, 24 Mar 2025 10:44:17 +0100
Subject: [PATCH v4 13/13] arm64: defconfig: Enable Renesas RZ/T2H serial
 SCI
In-Reply-To: <20250306152451.2356762-14-thierry.bultel.yh@bp.renesas.com>
References: <20250306152451.2356762-1-thierry.bultel.yh@bp.renesas.com>
 <20250306152451.2356762-14-thierry.bultel.yh@bp.renesas.com>
Message-ID: <Z-EpcXNXhSZ4zo2N@shikoro>

On Thu, Mar 06, 2025 at 04:24:47PM +0100, Thierry Bultel wrote:
> Selects RZ/T2H (aka r9a09g077) SCI (serial) specific code.
> 
> Signed-off-by: Thierry Bultel <thierry.bultel.yh at bp.renesas.com>

Basically OK, but as said before we need to find a better symbol name.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/a14707c1/attachment.sig>

From dsimic at manjaro.org  Mon Mar 24 02:53:49 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Mon, 24 Mar 2025 10:53:49 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <2ece5cca-50ea-4ec9-927e-e757c9c10c18@cherry.de>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
 <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
 <2ece5cca-50ea-4ec9-927e-e757c9c10c18@cherry.de>
Message-ID: <4d25c9af4380598b35a0d55e7c77ac3d@manjaro.org>

Hello Quentin,

On 2025-03-24 10:23, Quentin Schulz wrote:
> On 3/23/25 11:19 AM, Dragan Simic wrote:
>> On 2025-03-21 10:53, Quentin Schulz wrote:
>>> On 3/21/25 4:28 AM, Dragan Simic wrote:
>>>> The differences in the vendor-approved CPU and GPU OPPs for the 
>>>> standard
>>>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>>>> variant [2]
>>>> come from the latter, presumably, supporting an extended temperature 
>>>> range
>>>> that's usually associated with industrial applications, despite the 
>>>> two SoC
>>>> variant datasheets specifying the same upper limit for the allowed 
>>>> ambient
>>>> temperature for both variants.? However, the lower temperature limit 
>>>> is
>>> 
>>> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
>>> Operating Conditions, Table 3-2, Ambient Operating Temperature.
>> 
>> Indeed, which is why I specifically wrote "specifying the same upper
>> limit", because having a lower negative temperature limit could hardly
>> put the RK3588J in danger of overheating or running hotter. :)
> 
> """
> despite the two SoC variant datasheets specifying the same upper limit
> for the allowed temperature for both variants
> """
> 
> is incorrect. The whole range is different, yes it's only a 5?C
> difference for the upper limit, but they still are different.

I just commented on this separately, with a couple of datasheet
screenshots, before I saw your latest response.  Please, have
a look at that message.

>>>> specified much lower for the RK3588J variant. [1][2]
>>>> 
>>>> To be on the safe side and to ensure maximum longevity of the 
>>>> RK3588J SoCs,
>>>> only the CPU and GPU OPPs that are declared by the vendor to be 
>>>> always safe
>>>> for this SoC variant may be provided.? As explained by the vendor 
>>>> [3] and
>>>> according to its datasheet, [2] the RK3588J variant can actually run 
>>>> safely
>>>> at higher CPU and GPU OPPs as well, but only when not enjoying the 
>>>> assumed
>>>> extended temperature range that the RK3588J, as an SoC variant 
>>>> targeted
>>> 
>>> "only when not enjoying the assumed extended temperature range" is
>>> extrapolated by me/us and not confirmed by Rockchip themselves. I've
>>> asked for a statement on what "industrial environment" they specify 
>>> in
>>> the Normal Mode explanation means since it's the only time they use
>>> the term. I've yet to receive an answer. The only thing Rockchip in
>>> their datasheet is that the overdrive mode will shorten lifetime when
>>> used for a long time, especially in high temperature conditions. It's
>>> not clear whether we can use the overdrive mode even within the 
>>> RK3588
>>> typical range of operation.
>> 
>> True.? I'll see to rephrase the patch description a bit in the v2,
>> to avoid this kind of speculation.? I mean, perhaps the speculation
>> is right, but it hasn't been confirmed officially by Rockchip.
> 
> Speculation is fine, but it should be worded as such.

Agreed, because that's our understanding so far, but it needs
to be explained a bit better.

>>>> The provided RK3588J CPU OPPs follow the slightly debatable "provide 
>>>> only
>>>> the highest-frequency OPP from the same-voltage group" approach 
>>>> that's been
>>> 
>>> Interesting that we went for a different strategy for the GPU OPPs :)
>> 
>> Good point, and I'm fully aware of that. :)? Actually, I'm rather
>> sure that omitting the additional CPU OPPs does no good to us, but
>> I didn't want to argue about that when they were dropped originally,
>> before I can have some hard numbers to prove it in a repeatable way.
> 
> I assume we'll have some patch in the future with those added and
> those hard numbers you're talking about, so looking forward to seeing
> it on the ML :)

Indeed, that's the plan, and there should be even more patches,
which should remove the slightly annoying "xyz OPP is inefficient"
warnings emitted by the IPA governor. :)

>>>> Helped-by: Quentin Schulz <quentin.schulz at cherry.de>
>>> 
>>> Reported-by/Suggested-by?
>>> 
>>> I don't see Helped-by in
>>> https://eur02.safelinks.protection.outlook.com/? 
>>> url=https%3A%2F%2Fwww.kernel.org%2Fdoc%2Fhtml%2Flatest%2Fprocess%2Fsubmitting-patches.html%23using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes&data=05%7C02%7Cquentin.schulz%40cherry.de%7Cdc754791b6844506b11c08dd69f444a7%7C5e0e1b5221b54e7b83bb514ec460677e%7C0%7C0%7C638783220330058516%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=4bv9pUh6aSD0GVLJ4Zvuyvox1K0xxwf83KXX86QsvMo%3D&reserved=0
>>> 
>>> I see 2496b2aaacf137250f4ca449f465e2cadaabb0e8 got the Helped-by
>>> replaced by a Suggested-by for example, but I see other patches with
>>> Helped-by... if that is a standard trailer for kernel patches, then
>>> maybe we should add it to that doc?
>> 
>> Actually, I already tried to get the Helped-by tag added to the
>> kernel documentation, by submitting a small patch series. [*]
>> Unfortunately, it got rejected. :/
>> 
>> However, Heiko accepts Helped-by tags and nobody higher up the
>> tree seems to complain, so we should be fine. :)? It isn't the
>> case with all maintainers, though.
>> 
>> [*] https://eur02.safelinks.protection.outlook.com/? 
>> url=https%3A%2F%2Flore.kernel.org%2Fall%2Fcover.1730874296.git.dsimic%40manjaro.org%2FT%2F%23u&data=05%7C02%7Cquentin.schulz%40cherry.de%7Cdc754791b6844506b11c08dd69f444a7%7C5e0e1b5221b54e7b83bb514ec460677e%7C0%7C0%7C638783220330070422%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3dZgSG%2FBT6f%2Ffqs7D30HvEl18SzqYPwNeUGWBZfMAqM%3D&reserved=0
> 
> Are you trying to up the numbers of Helped-by in commit logs to make
> it a reasonable request to add the trailer in the documentation :) ?

It's just that Helped-by is, to me, of a bit "higher value" than
Suggested-by or Reported-by, because Helped-by means that the
tagged person contributed more to the patch than just suggesting
it or reporting a bug.  In addition, having more Helped-by tags
present in various commits can help a bit with, possibly, making
it officially supported at some point in the future. :)


From daniel.lezcano at linaro.org  Mon Mar 24 03:00:05 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 24 Mar 2025 11:00:05 +0100
Subject: [PATCH 1/2] dt-bindings: NXP System Timer Module
Message-ID: <20250324100008.346009-1-daniel.lezcano@linaro.org>

Add the System Timer Module description found on the NXP s32 platform
and the compatible for the s32g2 variant.

Cc: Ghennadi Procopciuc <ghennadi.procopciuc at oss.nxp.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Cc: Thomas Fossati <thomas.fossati at linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
---
 .../bindings/timer/nxp,stm-timer.yaml         | 59 +++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml

diff --git a/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
new file mode 100644
index 000000000000..41093892c617
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/nxp,stm-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP System Timer Module (STM)
+
+maintainers:
+  - Daniel Lezcano <daniel.lezcano at kernel.org>
+
+description: |
+  The System Timer Module supports commonly required system and
+  application software timing functions. STM includes a 32-bit
+  count-up timer and four 32-bit compare channels with a separate
+  interrupt source for each channel. The timer is driven by the STM
+  module clock divided by an 8-bit prescale value.
+
+properties:
+  compatible:
+    oneOf:
+      - const: nxp,s32g2-stm
+      - items:
+          - const: nxp,s32g2-stm
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: System Timer Module clock
+
+  clock-names:
+    items:
+      - const: stm
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    stm at 4011c000 {
+        compatible = "nxp,s32g2-stm";
+        reg = <0x4011c000 0x3000>;
+        interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clks 0x3b>;
+        clock-names = "stm";
+    };
-- 
2.43.0



From daniel.lezcano at linaro.org  Mon Mar 24 03:00:06 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 24 Mar 2025 11:00:06 +0100
Subject: [PATCH 2/2] clocksource/drivers/nxp-timer: Add the System Timer Module for the s32g platform
In-Reply-To: <20250324100008.346009-1-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
Message-ID: <20250324100008.346009-2-daniel.lezcano@linaro.org>

STM supports commonly required system and application software timing
functions. STM includes a 32-bit count-up timer and four 32-bit
compare channels with a separate interrupt source for each
channel. The timer is driven by the STM module clock divided by an
8-bit prescale value (1 to 256).

STM has the following features:
    ? One 32-bit count-up timer with an 8-bit prescaler
    ? Four 32-bit compare channels
    ? An independent interrupt source for each channel
    ? Ability to stop the timer in Debug mode

The s32g platform is declined into two versions, the s32g2 and the
s32g3. The former has a STM block with 8 timers and the latter has 12
timers.

There is a special STM instance called STM_TS which is dedicated to
the timestamp. The 7th STM instance STM_07 is directly tied to the
STM_TS which means it is not usable as a clockevent.

This driver provides the core code to support both platform but only
the s32g2 is configured. Adding the s32g3 STM support is
straighforward.

The first probed STM is used as a clocksource, the second will be the
broadcast timer and the rest are used as a clockevent with the
affinity set to a CPU. The rating is higher than the ARM architected
timers, so if they are enabled in the kernel configuration, they will
take over and used in place of the architected timers. The plaform
data is used to specify if a clocksource, a broadcast clockevent or a
per-cpu clockevent is desired thus allowing more flexibility in the
future to configure the STMs on the system.

Cc: Thomas Fossati <thomas.fossati at linaro.org>
Co-developed-by: Larisa Grigore <Larisa.Grigore at nxp.com>
Signed-off-by: Larisa Grigore <Larisa.Grigore at nxp.com>
Co-developed-by: Ghennadi Procopciuc <ghennadi.procopciuc at nxp.com>
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc at nxp.com>
Co-developed-by: Daniel Lezcano <daniel.lezcano at linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
---
 drivers/clocksource/Kconfig         |   9 +
 drivers/clocksource/Makefile        |   2 +
 drivers/clocksource/timer-nxp-stm.c | 524 ++++++++++++++++++++++++++++
 3 files changed, 535 insertions(+)
 create mode 100644 drivers/clocksource/timer-nxp-stm.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 487c85259967..e86e327392af 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -763,4 +763,13 @@ config RALINK_TIMER
 	  Enables support for system tick counter present on
 	  Ralink SoCs RT3352 and MT7620.
 
+config NXP_STM_TIMER
+	bool "NXP System Timer Module driver"
+	depends on ARCH_S32 || COMPILE_TEST
+	select CLKSRC_MMIO
+	help
+	  Support for NXP System Timer Module. It will create, in this
+	  order, a clocksource, a broadcast clockevent and a per cpu
+	  clockevent.
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 43ef16a4efa6..c3a92e6b9f94 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -92,3 +92,5 @@ obj-$(CONFIG_GXP_TIMER)			+= timer-gxp.o
 obj-$(CONFIG_CLKSRC_LOONGSON1_PWM)	+= timer-loongson1-pwm.o
 obj-$(CONFIG_EP93XX_TIMER)		+= timer-ep93xx.o
 obj-$(CONFIG_RALINK_TIMER)		+= timer-ralink.o
+obj-$(CONFIG_NXP_STM_TIMER)		+= timer-nxp-stm.o
+
diff --git a/drivers/clocksource/timer-nxp-stm.c b/drivers/clocksource/timer-nxp-stm.c
new file mode 100644
index 000000000000..b67e438487ae
--- /dev/null
+++ b/drivers/clocksource/timer-nxp-stm.c
@@ -0,0 +1,524 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2018,2021-2025 NXP
+ *
+ * NXP System Timer Module:
+ *
+ *  STM supports commonly required system and application software
+ *  timing functions. STM includes a 32-bit count-up timer and four
+ *  32-bit compare channels with a separate interrupt source for each
+ *  channel. The timer is driven by the STM module clock divided by an
+ *  8-bit prescale value (1 to 256). It has ability to stop the timer
+ *  in Debug mode
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sched_clock.h>
+
+/*
+ * Each stm has 4 channels which take 0x10 Bytes register space
+ */
+#define STM_CHANNEL(n)	(0x10 * ((n) + 1))
+
+#define STM_CCR			0x00
+#define STM_CCR_CEN		BIT(0)
+
+#define STM_CIR			0x04
+#define STM_CIR_CIF		BIT(0)
+
+#define STM_CMP			0x08
+
+#define STM_CR			0x00
+#define STM_CR_TEN		BIT(0)
+#define STM_CR_FRZ		BIT(1)
+#define STM_CR_CPS_OFFSET	8u
+#define STM_CR_CPS_MASK		GENMASK(15, STM_CR_CPS_OFFSET)
+#define STM_CR_CPS(x)		(((x) << STM_CR_CPS_OFFSET) & STM_CR_CPS_MASK)
+
+#define STM_CNT			0x04
+
+#define STM_ENABLE_MASK	(STM_CR_FRZ | STM_CR_TEN)
+
+struct stm_clocksource {
+	struct clocksource cs;
+	int counter;
+};
+
+struct stm_clockevent {
+	struct clock_event_device ced;
+	unsigned long delta;
+};
+
+struct stm_timer {
+	void __iomem *base;
+	unsigned long rate;
+	union {
+		struct stm_clocksource scs;
+		struct stm_clockevent sce;
+	};
+};
+
+static DEFINE_PER_CPU(struct stm_timer *, stm_timers);
+
+static struct stm_timer *stm_sched_clock;
+
+/**
+ * struct stm_instances - a set of counter for the STM initialized
+ *
+ * @clocksource: an integer giving the number of initialized clocksource
+ * @clockevent_per_cpu: an integer giving the number of initialized clockevent per cpu
+ * @clockevent_broadcast: an integer giving the number of initialized broadcast clockevent
+ * @features: a set of flag telling what kind of timer to initialize
+ */
+struct stm_instances {
+	int clocksource;
+	int clockevent_per_cpu;
+	int clockevent_broadcast;
+	int features;
+};
+
+#define STM_CLKSRC		BIT(0)
+#define STM_CLKEVT_PER_CPU	BIT(1)
+#define STM_CLKEVT_BROADCAST	BIT(2)
+
+static struct stm_clocksource *cs_to_scs(struct clocksource *cs)
+{
+	return container_of(cs, struct stm_clocksource, cs);
+}
+
+static struct stm_clockevent *ced_to_sced(struct clock_event_device *ced)
+{
+	return container_of(ced, struct stm_clockevent, ced);
+}
+
+static struct stm_timer *cs_to_stm(struct clocksource *cs)
+{
+	struct stm_clocksource *scs = cs_to_scs(cs);
+
+	return container_of(scs, struct stm_timer, scs);
+}
+
+static struct stm_timer *ced_to_stm(struct clock_event_device *ced)
+{
+        struct stm_clockevent *sce = ced_to_sced(ced);
+
+        return container_of(sce, struct stm_timer, sce);
+}
+
+static u64 notrace nxp_stm_read_sched_clock(void)
+{
+	return readl(stm_sched_clock->base + STM_CNT);
+}
+
+static u32 nxp_stm_clocksource_getcnt(struct stm_timer *stm_timer)
+{
+	return readl(stm_timer->base + STM_CNT);
+}
+
+static void nxp_stm_clocksource_setcnt(struct stm_timer *stm_timer, u32 cnt)
+{
+	writel(cnt, stm_timer->base + STM_CNT);
+}
+
+static u64 nxp_stm_clocksource_read(struct clocksource *cs)
+{
+	struct stm_timer *stm_timer = cs_to_stm(cs);
+
+	return (u64)nxp_stm_clocksource_getcnt(stm_timer);
+}
+
+static int nxp_stm_clocksource_enable(struct clocksource *cs)
+{
+	struct stm_timer *stm_timer = cs_to_stm(cs);
+	u32 reg;
+
+	reg = readl(stm_timer->base + STM_CR);
+	reg &= ~STM_CR_CPS_MASK;
+	reg |= STM_ENABLE_MASK;
+
+	writel(reg, stm_timer->base + STM_CR);
+
+	return 0;
+}
+
+static void nxp_stm_clocksource_disable(struct clocksource *cs)
+{
+	struct stm_timer *stm_timer = cs_to_stm(cs);
+	u32 reg;
+
+	reg = readl(stm_timer->base + STM_CR);
+	reg &= ~(STM_CR_CPS_MASK | STM_ENABLE_MASK);
+
+	writel(reg, stm_timer->base + STM_CR);
+}
+
+static void nxp_stm_clocksource_suspend(struct clocksource *cs)
+{
+	struct stm_timer *stm_timer = cs_to_stm(cs);
+
+	nxp_stm_clocksource_disable(cs);
+	stm_timer->scs.counter = nxp_stm_clocksource_getcnt(stm_timer);
+}
+
+static void nxp_stm_clocksource_resume(struct clocksource *cs)
+{
+	struct stm_timer *stm_timer = cs_to_stm(cs);
+
+	nxp_stm_clocksource_setcnt(stm_timer, stm_timer->scs.counter);
+	nxp_stm_clocksource_enable(cs);
+}
+
+static int __init nxp_stm_clocksource_init(struct device *dev, const char *name,
+					   void __iomem *base, struct clk *clk)
+{
+	struct stm_timer *stm_timer;
+	int ret;
+
+	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
+	if (!stm_timer)
+		return -ENOMEM;
+
+	stm_timer->base = base;
+	stm_timer->rate = clk_get_rate(clk);
+
+	stm_timer->scs.cs.name = name;
+	stm_timer->scs.cs.rating = 460;
+	stm_timer->scs.cs.read = nxp_stm_clocksource_read;
+	stm_timer->scs.cs.enable = nxp_stm_clocksource_enable;
+	stm_timer->scs.cs.disable = nxp_stm_clocksource_disable;
+	stm_timer->scs.cs.suspend = nxp_stm_clocksource_suspend;
+	stm_timer->scs.cs.resume = nxp_stm_clocksource_resume;
+	stm_timer->scs.cs.mask = CLOCKSOURCE_MASK(32);
+	stm_timer->scs.cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	ret = clocksource_register_hz(&stm_timer->scs.cs, stm_timer->rate);
+	if (ret)
+		return ret;
+
+	stm_sched_clock = stm_timer;
+
+	sched_clock_register(nxp_stm_read_sched_clock, 32, stm_timer->rate);
+
+	dev_set_drvdata(dev, stm_timer);
+
+	dev_dbg(dev, "Registered clocksource %s\n", name);
+
+	return 0;
+}
+
+static int nxp_stm_clockevent_read_counter(struct stm_timer *stm_timer)
+{
+	return readl(stm_timer->base + STM_CNT);
+}
+
+static void nxp_stm_clockevent_disable(struct stm_timer *stm_timer)
+{
+	/*
+	 * The counter is shared between channels and will continue to
+	 * be incremented. If STM_CMP value is too small, the next event can
+	 * be lost if we don't disable the entire module.
+	 * Disabling the entire module, makes STM not suitable as clocksource.
+	 */
+	writel(0, stm_timer->base + STM_CR);
+	writel(0, stm_timer->base + STM_CHANNEL(0) + STM_CCR);
+}
+
+static void nxp_stm_clockevent_enable(struct stm_timer *stm_timer)
+{
+	u32 reg = readl(stm_timer->base + STM_CR);
+
+	reg &= ~STM_CR_CPS_MASK;
+	reg |= STM_ENABLE_MASK;
+
+	writel(reg, stm_timer->base + STM_CR);
+	writel(STM_CCR_CEN, stm_timer->base + STM_CHANNEL(0) + STM_CCR);
+}
+
+static void nxp_stm_clockevent_irq_clr(struct stm_timer *stm_timer)
+{
+	/* Clear the interrupt */
+	writel(STM_CIR_CIF, stm_timer->base + STM_CHANNEL(0) + STM_CIR);
+}
+
+static void nxp_stm_clockevent_irq_ack(struct stm_timer *stm_timer)
+{
+	u32 val;
+
+	nxp_stm_clockevent_irq_clr(stm_timer);
+
+	/*
+	 * Update STM_CMP value using the counter value
+	 */
+	val = nxp_stm_clockevent_read_counter(stm_timer) + stm_timer->sce.delta;
+
+	writel(val, stm_timer->base + STM_CHANNEL(0) + STM_CMP);
+}
+
+static irqreturn_t nxp_stm_clockevent_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ced = dev_id;
+	struct stm_timer *stm_timer = ced_to_stm(ced);
+
+	nxp_stm_clockevent_irq_ack(stm_timer);
+
+	/*
+	 * stm hardware doesn't support oneshot, it will generate an
+	 * interrupt and start the counter again so software need to
+	 * disable the timer to stop the counter loop in ONESHOT mode.
+	 */
+	if (likely(clockevent_state_oneshot(ced)))
+		nxp_stm_clockevent_disable(stm_timer);
+
+	ced->event_handler(ced);
+
+	return IRQ_HANDLED;
+}
+
+static int nxp_stm_clockevent_shutdown(struct clock_event_device *ced)
+{
+	struct stm_timer *stm_timer = ced_to_stm(ced);
+
+	nxp_stm_clockevent_disable(stm_timer);
+
+	return 0;
+}
+
+static int nxp_stm_clockevent_set_next_event(unsigned long delta, struct clock_event_device *ced)
+{
+	struct stm_timer *stm_timer = ced_to_stm(ced);
+	u32 val;
+
+	nxp_stm_clockevent_disable(stm_timer);
+
+	stm_timer->sce.delta = delta;
+
+	val = nxp_stm_clockevent_read_counter(stm_timer) + delta;
+
+	writel(val, stm_timer->base + STM_CHANNEL(0) + STM_CMP);
+
+	nxp_stm_clockevent_enable(stm_timer);
+
+	return 0;
+}
+
+static int nxp_stm_clockevent_set_periodic(struct clock_event_device *ced)
+{
+	struct stm_timer *stm_timer = ced_to_stm(ced);
+
+        return nxp_stm_clockevent_set_next_event(stm_timer->rate, ced);
+}
+
+static int __init nxp_stm_clockevent_broadcast_init(struct device *dev, const char *name, void __iomem *base,
+						    int irq, struct clk *clk)
+{
+	struct stm_timer *stm_timer;
+	int ret;
+
+	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
+	if (!stm_timer)
+		return -ENOMEM;
+
+	stm_timer->base = base;
+	stm_timer->rate = clk_get_rate(clk);
+
+	stm_timer->sce.ced.name = name;
+	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
+	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
+	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
+	stm_timer->sce.ced.cpumask = cpu_possible_mask;
+	stm_timer->sce.ced.rating = 460;
+	stm_timer->sce.ced.irq = irq;
+
+	nxp_stm_clockevent_irq_clr(stm_timer);
+
+	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
+			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);
+	if (ret) {
+		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
+		return ret;
+	}
+
+	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
+
+	dev_dbg(dev, "Registered broadcast clockevent %s irq=%d\n", name, irq);
+
+	return 0;
+}
+
+static int __init nxp_stm_clockevent_per_cpu_init(struct device *dev, const char *name, void __iomem *base,
+						  int irq, struct clk *clk, int cpu)
+{
+	struct stm_timer *stm_timer;
+	int ret;
+
+	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
+	if (!stm_timer)
+		return -ENOMEM;
+
+	stm_timer->base = base;
+	stm_timer->rate = clk_get_rate(clk);
+
+	stm_timer->sce.ced.name = name;
+	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
+	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
+	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
+	stm_timer->sce.ced.cpumask = cpumask_of(cpu);
+	stm_timer->sce.ced.rating = 460;
+	stm_timer->sce.ced.irq = irq;
+
+	nxp_stm_clockevent_irq_clr(stm_timer);
+
+	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
+			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);
+	if (ret) {
+		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
+		return ret;
+	}
+
+	per_cpu(stm_timers, cpu) = stm_timer;
+
+	dev_dbg(dev, "Initialized per cpu clockevent name=%s, irq=%d, cpu=%d\n", name, irq, cpu);
+
+	return 0;
+}
+
+static int nxp_stm_clockevent_starting_cpu(unsigned int cpu)
+{
+	struct stm_timer *stm_timer = per_cpu(stm_timers, cpu);
+	int ret;
+
+	if (WARN_ON(!stm_timer))
+		return -EFAULT;
+
+	ret = irq_force_affinity(stm_timer->sce.ced.irq, cpumask_of(cpu));
+	if (ret)
+		return ret;
+
+	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
+
+	return 0;
+}
+
+static int __init nxp_stm_timer_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct stm_instances *stm_instances;
+	const char *name = of_node_full_name(np);
+	void __iomem *base;
+	int irq, ret;
+	struct clk *clk;
+
+	stm_instances = (typeof(stm_instances))of_device_get_match_data(dev);
+	if (!stm_instances) {
+		dev_err(dev, "No STM instances associated with a cpu");
+		return -EINVAL;
+	}
+
+	base = devm_of_iomap(dev, np, 0, NULL);
+	if (IS_ERR(base)) {
+		dev_err(dev, "Failed to iomap %pOFn\n", np);
+		return PTR_ERR(base);
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		dev_err(dev, "Failed to parse and map IRQ: %d\n", irq);
+		return -EINVAL;
+	}
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Clock not found\n");
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable STM timer clock: %d\n", ret);
+		return ret;
+	}
+
+	if (!stm_instances->clocksource && (stm_instances->features & STM_CLKSRC)) {
+
+		/*
+		 * First probed STM will be a clocksource
+		 */
+		ret = nxp_stm_clocksource_init(dev, name, base, clk);
+		if (ret)
+			return ret;
+		stm_instances->clocksource++;
+
+	} else if (!stm_instances->clockevent_broadcast &&
+		   (stm_instances->features & STM_CLKEVT_BROADCAST)) {
+
+		/*
+		 * Second probed STM will be a broadcast clockevent
+		 */
+		ret = nxp_stm_clockevent_broadcast_init(dev, name, base, irq, clk);
+		if (ret)
+			return ret;
+		stm_instances->clockevent_broadcast++;
+
+	} else if (stm_instances->clockevent_per_cpu < num_possible_cpus() &&
+		   (stm_instances->features & STM_CLKEVT_PER_CPU)) {
+
+		/*
+		 * Next probed STM will be a per CPU clockevent, until
+		 * we probe as much as we have CPUs available on the
+		 * system, we do a partial initialization
+		 */
+		ret = nxp_stm_clockevent_per_cpu_init(dev, name, base, irq, clk,
+						      stm_instances->clockevent_per_cpu);
+		if (ret)
+			return ret;
+
+		stm_instances->clockevent_per_cpu++;
+
+		/*
+		 * The number of probed STM for per CPU clockevent is
+		 * equal to the number of available CPUs on the
+		 * system. We install the cpu hotplug to finish the
+		 * initialization by registering the clockevents
+		 */
+		if (stm_instances->clockevent_per_cpu == num_possible_cpus()) {
+			ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "STM timer:starting",
+						nxp_stm_clockevent_starting_cpu, NULL);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static struct stm_instances s32g_stm_instances = { .features = STM_CLKSRC | STM_CLKEVT_PER_CPU };
+
+static const struct of_device_id nxp_stm_of_match[] = {
+	{ .compatible = "nxp,s32g2-stm", &s32g_stm_instances },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
+
+static struct platform_driver nxp_stm_probe = {
+	.probe	= nxp_stm_timer_probe,
+	.driver	= {
+		.name = "nxp-stm",
+		.of_match_table = of_match_ptr(nxp_stm_of_match),
+	},
+};
+module_platform_driver(nxp_stm_probe);
+
+MODULE_DESCRIPTION("NXP System Timer Module driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0



From u.kleine-koenig at baylibre.com  Mon Mar 24 03:01:27 2025
From: u.kleine-koenig at baylibre.com (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 24 Mar 2025 11:01:27 +0100
Subject: [PATCH v3 0/2] ARM: dts: socfpga: Add basic support for
 Terrasic's de10-nano
In-Reply-To: <6ae42224-74cf-4d2e-88fb-f766279d3525@kernel.org>
References: <cover.1738600838.git.u.kleine-koenig@baylibre.com>
 <6ae42224-74cf-4d2e-88fb-f766279d3525@kernel.org>
Message-ID: <v7btqobpnuss7rldvrnem3tmznyrd54kks6dcnpwqdhpqysqzq@p3bt6bdztiq4>

Hello,

On Tue, Mar 04, 2025 at 06:46:18AM -0600, Dinh Nguyen wrote:
> On 2/3/25 10:46, Uwe Kleine-K?nig wrote:
> > Hello,
> > 
> > The only change since v2
> > (https://lore.kernel.org/linux-arm-kernel/20250130074553.92023-2-u.kleine-koenig at baylibre.com):
> > is that I added patch 1/2 that is supposed to fix the warning that I
> > failed to notice with the testing I did. Thanks to Krzysztof and Rob for
> > their patience with me. I hope I got it right now.
> > 
> > Best regards
> > Uwe
> > 
> > Uwe Kleine-K?nig (2):
> >    dt-bindings: altera: Add compatible for Terasic's DE10-nano
> >    ARM: dts: socfpga: Add basic support for Terrasic's de10-nano
> > 
> >   .../devicetree/bindings/arm/altera.yaml       |  1 +
> >   arch/arm/boot/dts/intel/socfpga/Makefile      |  1 +
> >   .../socfpga/socfpga_cyclone5_de10nano.dts     | 95 +++++++++++++++++++
> >   3 files changed, 97 insertions(+)
> >   create mode 100644 arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10nano.dts
> > 
> > base-commit: 00f3246adeeacbda0bd0b303604e46eb59c32e6e
> 
> Applied!

Thanks!

I would have expected that patch to pop up on
https://web.git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git/log/?h=socfpga_dts_for_v6.15
in the mean time, but it's not there. Is it still scheduled to go into
mainline?

Having said that, that branch looks really strange. It contains:

	$ git show --format=fuller 2445fc2d7863
	commit 2445fc2d786304c38934199b1f95a9e52be0cec9
	Author:     Linus Torvalds <torvalds at linux-foundation.org>
	AuthorDate: Sun Feb 9 12:45:03 2025 -0800
	Commit:     Dinh Nguyen <dinguyen at kernel.org>
	CommitDate: Wed Feb 19 06:32:34 2025 -0600

	    Linux 6.14-rc2

	diff --git a/Makefile b/Makefile
	index 9e0d63d9d94b..89628e354ca7 100644
	--- a/Makefile
	+++ b/Makefile
	@@ -2,7 +2,7 @@
	 VERSION = 6
	 PATCHLEVEL = 14
	 SUBLEVEL = 0
	-EXTRAVERSION = -rc1
	+EXTRAVERSION = -rc2
	 NAME = Baby Opossum Posse

	 # *DOCUMENTATION*

I assume this is a rebase accident? 

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/e22d196e/attachment.sig>

From ryan_chen at aspeedtech.com  Mon Mar 24 03:01:36 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Mon, 24 Mar 2025 10:01:36 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224055936.1804279-2-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
 <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>
Message-ID: <SI6PR06MB7535BAD19B51A381171A0E64F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 24/03/2025 09:30, Ryan Chen wrote:
> >> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >> AST2600-i2cv2
> >>
> >> On 19/03/2025 12:12, Ryan Chen wrote:
> >>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >>>> AST2600-i2cv2
> >>>>
> >>>> On 17/03/2025 10:21, Ryan Chen wrote:
> >>>>>> Neither this.
> >>>>>>
> >>>>>> So it seems you describe already existing and documented I2C, but
> >>>>>> for some reason you want second compatible. The problem is that
> >>>>>> you do not provide reason from the point of view of bindings.
> >>>>>>
> >>>>>> To summarize: what your users want - don't care. Start properly
> >>>>>> describing hardware and your SoC.
> >>>>>
> >>>>> OK, for ast2600 i2c controller have two register mode setting.
> >>>>> One, I call it is old register setting, that is right now
> >>>>> i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus", And there
> >>>>> have a global register
> >>>> that can set i2c controller as new mode register set.
> >>>>> That I am going to drive. That I post is all register in new an
> >>>>> old register
> >> list.
> >>>>>
> >>>>> For example,
> >>>>> Global register [2] = 0 => i2c present as old register set Global
> >>>>> register [2] = 1 => i2c present as new register set
> >>>> It's the same device though, so the same compatible.
> >>>
> >>> Sorry, it is different design, and it share the same register space.
> >>> So that the reason add new compatible "aspeed,ast2600-i2cv2" for
> >>> this
> >> driver.
> >>> It is different register layout.
> >>
> >> Which device is described by the existing "aspeed,ast2600-i2c-bus"
> >> compatible? And which device is described by new compatible?
> >>
> > On the AST2600 SoC, there are up to 16 I2C controller instances (I2C1 ~
> I2C16).
> 
> So you have 16 same devices.
Yes, one driver instance for 16 i2c device. 
> 
> > Each of these controllers is hardwired at the SoC level to use either the
> legacy register layout or the new v2 register layout.
> > The mode is selected by a bit in the global register, these represent two
> different hardware blocks:
> > "aspeed,ast2600-i2c-bus" describes controllers using the legacy register
> layout.
> > "aspeed,ast2600-i2cv2" describes controllers using the new register
> > layout
> 
> Which part of "same device" is not clear? You have one device, one compatible.
> Whatever you do with register layout, is already defined by that compatible. It
> does not matter that you forgot to implement it in the Linux kernel.

Sorry, I still can't catch your point.
I separated the support into two drivers:
i2c-aspeed.c for legacy layout, compatible "aspeed,ast2600-i2c-bus"
i2c-ast2600.c for the new register set, compatible compatible "aspeed,ast2600-i2cv2"
Do you mean I have integrate into 1 driver at i2c-aspeed.c ? can't be separate two driver?
> 
> Best regards,
> Krzysztof

From quentin.schulz at cherry.de  Mon Mar 24 03:20:46 2025
From: quentin.schulz at cherry.de (Quentin Schulz)
Date: Mon, 24 Mar 2025 11:20:46 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <4d25c9af4380598b35a0d55e7c77ac3d@manjaro.org>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
 <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
 <2ece5cca-50ea-4ec9-927e-e757c9c10c18@cherry.de>
 <4d25c9af4380598b35a0d55e7c77ac3d@manjaro.org>
Message-ID: <170e4d8d-33ca-4c53-9ae7-ca9d674540a9@cherry.de>

Hi Dragan,

On 3/24/25 10:53 AM, Dragan Simic wrote:
> Hello Quentin,
> 
> On 2025-03-24 10:23, Quentin Schulz wrote:
>> On 3/23/25 11:19 AM, Dragan Simic wrote:
>>> On 2025-03-21 10:53, Quentin Schulz wrote:
>>>> On 3/21/25 4:28 AM, Dragan Simic wrote:
>>>>> The differences in the vendor-approved CPU and GPU OPPs for the 
>>>>> standard
>>>>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>>>>> variant [2]
>>>>> come from the latter, presumably, supporting an extended 
>>>>> temperature range
>>>>> that's usually associated with industrial applications, despite the 
>>>>> two SoC
>>>>> variant datasheets specifying the same upper limit for the allowed 
>>>>> ambient
>>>>> temperature for both variants.? However, the lower temperature 
>>>>> limit is
>>>>
>>>> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
>>>> Operating Conditions, Table 3-2, Ambient Operating Temperature.
>>>
>>> Indeed, which is why I specifically wrote "specifying the same upper
>>> limit", because having a lower negative temperature limit could hardly
>>> put the RK3588J in danger of overheating or running hotter. :)
>>
>> """
>> despite the two SoC variant datasheets specifying the same upper limit
>> for the allowed temperature for both variants
>> """
>>
>> is incorrect. The whole range is different, yes it's only a 5?C
>> difference for the upper limit, but they still are different.
> 
> I just commented on this separately, with a couple of datasheet
> screenshots, before I saw your latest response.? Please, have
> a look at that message.
> 

I see, I had a v1.3 datasheet opened:

https://github.com/FanX-Tek/rk3588-TRM-and-Datasheet/blob/master/Rockchip_RK3588_Datasheet_V1.3-20220328.pdf

Interestingly, it seems the RK3588S (still?) has a smaller operating range:

https://www.armboard.cn/download/Rockchip_RK3588S_Datasheet_V1.6-20240821.pdf

Cheers,
Quentin


From patrice.chotard at foss.st.com  Mon Mar 24 03:19:05 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Mon, 24 Mar 2025 11:19:05 +0100
Subject: [PATCH 1/2] spi: dt-bindings: st,stm32mp25-ospi: Make "resets" a
 required property
In-Reply-To: <688c619d-0e20-496a-ae24-d62ab34f93ab@kernel.org>
References: <20250321-upstream_ospi_required_resets-v1-0-9aa4702e3ae2@foss.st.com>
 <20250321-upstream_ospi_required_resets-v1-1-9aa4702e3ae2@foss.st.com>
 <688c619d-0e20-496a-ae24-d62ab34f93ab@kernel.org>
Message-ID: <b99576c5-cc9f-455a-aa58-ce5a0489a5a9@foss.st.com>



On 3/21/25 11:13, Krzysztof Kozlowski wrote:
> On 21/03/2025 10:44, Patrice Chotard wrote:
>> Make "resets" a required property.
> 
> Please explain why. This is technically an ABI break, so you please
> provide explanation what sort of issue is being fixed.

Hi

Right, i will add more details

Thanks
Patrice

> 
>>
>> Fixes: bed97e35786a ("dt-bindings: spi: Add STM32 OSPI controller")
>> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
>> ---
>>  Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml | 1 +
>>  1 file changed, 1 insertion(+)
> 
> 
> Best regards,
> Krzysztof


From dsimic at manjaro.org  Mon Mar 24 03:33:53 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Mon, 24 Mar 2025 11:33:53 +0100
Subject: [PATCH] arm64: dts: rockchip: Remove overdrive-mode OPPs from
 RK3588J SoC dtsi
In-Reply-To: <170e4d8d-33ca-4c53-9ae7-ca9d674540a9@cherry.de>
References: <f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic@manjaro.org>
 <71b7c81b-6a4e-442b-a661-04d63639962a@cherry.de>
 <960c038ad9f7b83fe14d0ded388b42f7@manjaro.org>
 <2ece5cca-50ea-4ec9-927e-e757c9c10c18@cherry.de>
 <4d25c9af4380598b35a0d55e7c77ac3d@manjaro.org>
 <170e4d8d-33ca-4c53-9ae7-ca9d674540a9@cherry.de>
Message-ID: <17b55e889838f2c989bd0efc6528801b@manjaro.org>

On 2025-03-24 11:20, Quentin Schulz wrote:
> On 3/24/25 10:53 AM, Dragan Simic wrote:
>> On 2025-03-24 10:23, Quentin Schulz wrote:
>>> On 3/23/25 11:19 AM, Dragan Simic wrote:
>>>> On 2025-03-21 10:53, Quentin Schulz wrote:
>>>>> On 3/21/25 4:28 AM, Dragan Simic wrote:
>>>>>> The differences in the vendor-approved CPU and GPU OPPs for the 
>>>>>> standard
>>>>>> Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J 
>>>>>> variant [2]
>>>>>> come from the latter, presumably, supporting an extended 
>>>>>> temperature range
>>>>>> that's usually associated with industrial applications, despite 
>>>>>> the two SoC
>>>>>> variant datasheets specifying the same upper limit for the allowed 
>>>>>> ambient
>>>>>> temperature for both variants.? However, the lower temperature 
>>>>>> limit is
>>>>> 
>>>>> RK3588 is rated for 0-80?C, RK3588J for -40-85?C, c.f. Recommended
>>>>> Operating Conditions, Table 3-2, Ambient Operating Temperature.
>>>> 
>>>> Indeed, which is why I specifically wrote "specifying the same upper
>>>> limit", because having a lower negative temperature limit could 
>>>> hardly
>>>> put the RK3588J in danger of overheating or running hotter. :)
>>> 
>>> """
>>> despite the two SoC variant datasheets specifying the same upper 
>>> limit
>>> for the allowed temperature for both variants
>>> """
>>> 
>>> is incorrect. The whole range is different, yes it's only a 5?C
>>> difference for the upper limit, but they still are different.
>> 
>> I just commented on this separately, with a couple of datasheet
>> screenshots, before I saw your latest response.? Please, have
>> a look at that message.
> 
> I see, I had a v1.3 datasheet opened:
> 
> https://github.com/FanX-Tek/rk3588-TRM-and-Datasheet/blob/master/Rockchip_RK3588_Datasheet_V1.3-20220328.pdf

Yup, the v1.6 of the RK3588 datasheet increased the upper ambient
temperature limit from 80 to 85 oC.

> Interestingly, it seems the RK3588S (still?) has a smaller operating 
> range:
> 
> https://www.armboard.cn/download/Rockchip_RK3588S_Datasheet_V1.6-20240821.pdf

Oh, that's quite interesting, I had the v1.5 as the newest version.
The v1.6 of the RK3588S datasheet actually lowered the upper ambient
temperature limit from 85 down to 80 oC.


From andyshrk at 163.com  Mon Mar 24 03:33:28 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 24 Mar 2025 18:33:28 +0800
Subject: [PATCH 2/2] ARM: dts: rockchip: Add ref clk for hdmi
In-Reply-To: <20250324103332.159682-1-andyshrk@163.com>
References: <20250324103332.159682-1-andyshrk@163.com>
Message-ID: <20250324103332.159682-2-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The RK3036 HDMI DDC bus requires it's PHY's reference clock to be
enabled first before normal DDC communication can be carried out.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 arch/arm/boot/dts/rockchip/rk3036.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/rockchip/rk3036.dtsi b/arch/arm/boot/dts/rockchip/rk3036.dtsi
index 6039a0908af1c..22685cd23a708 100644
--- a/arch/arm/boot/dts/rockchip/rk3036.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3036.dtsi
@@ -403,8 +403,8 @@ hdmi: hdmi at 20034000 {
 		compatible = "rockchip,rk3036-inno-hdmi";
 		reg = <0x20034000 0x4000>;
 		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru  PCLK_HDMI>;
-		clock-names = "pclk";
+		clocks = <&cru PCLK_HDMI>, <&cru SCLK_LCDC>;
+		clock-names = "pclk", "ref";
 		pinctrl-names = "default";
 		pinctrl-0 = <&hdmi_ctl>;
 		#sound-dai-cells = <0>;
-- 
2.43.0



From andyshrk at 163.com  Mon Mar 24 03:33:27 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 24 Mar 2025 18:33:27 +0800
Subject: [PATCH 1/2] dt-bindings: display: rockchip,inno-hdmi: Fix ref clk Document of RK3036 compatible
Message-ID: <20250324103332.159682-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

The RK3036 HDMI DDC bus requires it's PHY's reference clock to be enabled
first before normal DDC communication can be carried out.

Therefore, both RK3036 and RK3128 HDMI require two identical clocks.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 .../bindings/display/rockchip/rockchip,inno-hdmi.yaml | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml
index 5b87b0f1963e1..9d1e7f894ea54 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml
@@ -23,13 +23,11 @@ properties:
     maxItems: 1
 
   clocks:
-    minItems: 1
     items:
       - description: The HDMI controller main clock
       - description: The HDMI PHY reference clock
 
   clock-names:
-    minItems: 1
     items:
       - const: pclk
       - const: ref
@@ -87,11 +85,6 @@ allOf:
             const: rockchip,rk3128-inno-hdmi
 
     then:
-      properties:
-        clocks:
-          minItems: 2
-        clock-names:
-          minItems: 2
       required:
         - power-domains
 
@@ -106,8 +99,8 @@ examples:
       compatible = "rockchip,rk3036-inno-hdmi";
       reg = <0x20034000 0x4000>;
       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-      clocks = <&cru  PCLK_HDMI>;
-      clock-names = "pclk";
+      clocks = <&cru PCLK_HDMI>, <&cru SCLK_LCDC>;
+      clock-names = "pclk", "ref";
       pinctrl-names = "default";
       pinctrl-0 = <&hdmi_ctl>;
       #sound-dai-cells = <0>;
-- 
2.43.0



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:06 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:06 +0100
Subject: [PATCH net-next v4 4/8] net: ethtool: netlink: Introduce command-specific dump_one_dev
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-5-maxime.chevallier@bootlin.com>

Prepare more generic ethnl DUMP hanldling, by allowing netlink commands
to register their own dump_one_dev() callback. This avoids having to
roll with a fully custom genl ->dumpit callback, allowing the re-use
of some ethnl plumbing.

Fallback to the default dump_one_dev behaviour when no custom callback
is found.

The command dump context is maintained within the ethnl_dump_ctx, that
we move in netlink.h so that command handlers can access it.

This context can be allocated/freed in new ->dump_start() and
->dump_done() callbacks.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/netlink.c | 61 +++++++++++++++++++++++++------------------
 net/ethtool/netlink.h | 35 +++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 26 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 63ede3638708..0345bffa0678 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -339,24 +339,6 @@ int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
 
 /* GET request helpers */
 
-/**
- * struct ethnl_dump_ctx - context structure for generic dumpit() callback
- * @ops:        request ops of currently processed message type
- * @req_info:   parsed request header of processed request
- * @reply_data: data needed to compose the reply
- * @pos_ifindex: saved iteration position - ifindex
- *
- * These parameters are kept in struct netlink_callback as context preserved
- * between iterations. They are initialized by ethnl_default_start() and used
- * in ethnl_default_dumpit() and ethnl_default_done().
- */
-struct ethnl_dump_ctx {
-	const struct ethnl_request_ops	*ops;
-	struct ethnl_req_info		*req_info;
-	struct ethnl_reply_data		*reply_data;
-	unsigned long			pos_ifindex;
-};
-
 static const struct ethnl_request_ops *
 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_STRSET_GET]	= &ethnl_strset_request_ops,
@@ -540,9 +522,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				      const struct ethnl_dump_ctx *ctx,
-				      const struct genl_info *info)
+static int ethnl_default_dump_one(struct sk_buff *skb,
+				  const struct ethnl_dump_ctx *ctx,
+				  const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -553,15 +535,15 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 	if (!ehdr)
 		return -EMSGSIZE;
 
-	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
 	rtnl_lock();
-	netdev_lock_ops(dev);
+	netdev_lock_ops(ctx->reply_data->dev);
 	ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
-	netdev_unlock_ops(dev);
+	netdev_unlock_ops(ctx->reply_data->dev);
 	rtnl_unlock();
 	if (ret < 0)
 		goto out;
-	ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
+	ret = ethnl_fill_reply_header(skb, ctx->reply_data->dev,
+				      ctx->ops->hdr_attr);
 	if (ret < 0)
 		goto out;
 	ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data);
@@ -569,11 +551,29 @@ static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *de
 out:
 	if (ctx->ops->cleanup_data)
 		ctx->ops->cleanup_data(ctx->reply_data);
-	ctx->reply_data->dev = NULL;
+
 	if (ret < 0)
 		genlmsg_cancel(skb, ehdr);
 	else
 		genlmsg_end(skb, ehdr);
+
+	return ret;
+}
+
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
+{
+	int ret;
+
+	ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
+
+	if (ctx->ops->dump_one_dev)
+		ret = ctx->ops->dump_one_dev(skb, ctx, info);
+	else
+		ret = ethnl_default_dump_one(skb, ctx, info);
+
+	ctx->reply_data->dev = NULL;
 	return ret;
 }
 
@@ -676,6 +676,12 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	ctx->reply_data = reply_data;
 	ctx->pos_ifindex = 0;
 
+	if (ctx->ops->dump_start) {
+		ret = ctx->ops->dump_start(ctx);
+		if (ret)
+			goto free_reply_data;
+	}
+
 	return 0;
 
 free_reply_data:
@@ -691,6 +697,9 @@ static int ethnl_default_done(struct netlink_callback *cb)
 {
 	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
 
+	if (ctx->ops->dump_done)
+		ctx->ops->dump_done(ctx);
+
 	kfree(ctx->reply_data);
 	kfree(ctx->req_info);
 
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 4aaa73282d6a..79fe98190c64 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -307,6 +307,26 @@ struct ethnl_reply_data {
 	struct net_device		*dev;
 };
 
+/**
+ * struct ethnl_dump_ctx - context structure for generic dumpit() callback
+ * @ops:        request ops of currently processed message type
+ * @req_info:   parsed request header of processed request
+ * @reply_data: data needed to compose the reply
+ * @pos_ifindex: saved iteration position - ifindex
+ * @cmd_ctx: command-specific context to maintain across the dump.
+ *
+ * These parameters are kept in struct netlink_callback as context preserved
+ * between iterations. They are initialized by ethnl_default_start() and used
+ * in ethnl_default_dumpit() and ethnl_default_done().
+ */
+struct ethnl_dump_ctx {
+	const struct ethnl_request_ops	*ops;
+	struct ethnl_req_info		*req_info;
+	struct ethnl_reply_data		*reply_data;
+	unsigned long			pos_ifindex;
+	void				*cmd_ctx;
+};
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
@@ -373,6 +393,15 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  *	 - 0 if no configuration has changed
  *	 - 1 if configuration changed and notification should be generated
  *	 - negative errno on errors
+ * @dump_start:
+ *	Optional callback to prepare a dump operation, should there be a need
+ *	to maintain some context across the dump.
+ * @dump_one_dev:
+ *	Optional callback to generate all messages for a given netdev. This
+ *	is relevant only when a request can produce different results for the
+ *	same netdev depending on command-specific attributes.
+ * @dump_done:
+ *	Optional callback to cleanup any context allocated in ->dump_start()
  *
  * Description of variable parts of GET request handling when using the
  * unified infrastructure. When used, a pointer to an instance of this
@@ -409,6 +438,12 @@ struct ethnl_request_ops {
 			    struct genl_info *info);
 	int (*set)(struct ethnl_req_info *req_info,
 		   struct genl_info *info);
+
+	int (*dump_start)(struct ethnl_dump_ctx *ctx);
+	int (*dump_one_dev)(struct sk_buff *skb,
+			    struct ethnl_dump_ctx *ctx,
+			    const struct genl_info *info);
+	void (*dump_done)(struct ethnl_dump_ctx *ctx);
 };
 
 /* request handlers */
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:07 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:07 +0100
Subject: [PATCH net-next v4 5/8] net: ethtool: netlink: Introduce per-phy DUMP helpers
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-6-maxime.chevallier@bootlin.com>

As there are multiple ethnl commands that report messages based on
phy_device information, let's introduce a set of ethnl generic dump
helpers to allow DUMP support for each PHY on a given netdev.

This logic iterates over the phy_link_topology of each netdev (or a
single netdev for filtered DUMP), and call ethnl_default_dump_one() with
the req_info populated with ifindex + phyindex.

This allows re-using all the existing infra for phy-targetting commands
that already use ethnl generic helpers.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/netlink.c | 78 +++++++++++++++++++++++++++++++++++++++++++
 net/ethtool/netlink.h |  6 ++++
 2 files changed, 84 insertions(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 0345bffa0678..171290eaf406 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -560,6 +560,84 @@ static int ethnl_default_dump_one(struct sk_buff *skb,
 	return ret;
 }
 
+/* Specific context for phy-targeting command DUMP operatins. We keep in context
+ * the latest phy_index we dumped, in case of an interrupted DUMP.
+ */
+struct ethnl_dump_ctx_perphy {
+	unsigned long phy_index;
+};
+
+/**
+ * ethnl_dump_start_perphy() - Initialise a dump for PHY cmds
+ * @ctx: Generic ethnl dump context whose cmd_ctx will be initialized
+ *
+ * Initializes a dump context for ethnl commands that may return
+ * one message per PHY on a single netdev.
+ *
+ * Returns: 0 for success, a negative value for errors.
+ */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx;
+
+	dump_ctx = kzalloc(sizeof(*dump_ctx), GFP_KERNEL);
+	if (!dump_ctx)
+		return -ENOMEM;
+
+	ctx->cmd_ctx = dump_ctx;
+
+	return 0;
+}
+
+/**
+ * ethnl_dump_done_perphy() - Releases the per-phy dump context
+ * @ctx: Generic ethnl dump context whose cmd_ctx will be released
+ */
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx)
+{
+	kfree(ctx->cmd_ctx);
+}
+
+/**
+ * ethnl_dump_one_dev_perphy() - Dump all PHY-related messages for one netdev
+ * @skb: skb containing the DUMP result
+ * @ctx: Dump context. Will be kept across the DUMP operation.
+ * @info: Genl receive info
+ *
+ * Some commands are related to PHY devices attached to netdevs. As there may be
+ * multiple PHYs, this DUMP handler will populate the reply with one message per
+ * PHY on a single netdev.
+ *
+ * Returns: 0 for success or when nothing to do, a negative value otherwise.
+ */
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb,
+			      struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info)
+{
+	struct ethnl_dump_ctx_perphy *dump_ctx = ctx->cmd_ctx;
+	struct net_device *dev = ctx->reply_data->dev;
+	struct phy_device_node *pdn;
+	int ret = 0;
+
+	if (!dev->link_topo)
+		return 0;
+
+	xa_for_each_start(&dev->link_topo->phys, dump_ctx->phy_index,
+			  pdn, dump_ctx->phy_index) {
+		ctx->req_info->phy_index = dump_ctx->phy_index;
+
+		/* We can re-use the original dump_one as ->prepare_data in
+		 * commands use ethnl_req_get_phydev(), which gets the PHY from
+		 * what's in req_info
+		 */
+		ret = ethnl_default_dump_one(skb, ctx, info);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
 				      struct ethnl_dump_ctx *ctx,
 				      const struct genl_info *info)
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 79fe98190c64..530a9b5c8b39 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -327,6 +327,12 @@ struct ethnl_dump_ctx {
 	void				*cmd_ctx;
 };
 
+/* Generic callbacks to be used by PHY targeting commands */
+int ethnl_dump_start_perphy(struct ethnl_dump_ctx *ctx);
+int ethnl_dump_one_dev_perphy(struct sk_buff *skb, struct ethnl_dump_ctx *ctx,
+			      const struct genl_info *info);
+void ethnl_dump_done_perphy(struct ethnl_dump_ctx *ctx);
+
 int ethnl_ops_begin(struct net_device *dev);
 void ethnl_ops_complete(struct net_device *dev);
 
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:08 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:08 +0100
Subject: [PATCH net-next v4 6/8] net: ethtool: phy: Convert the PHY_GET command to generic phy dump
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-7-maxime.chevallier@bootlin.com>

Now that we have an infrastructure in ethnl for perphy DUMPs, we can get
rid of the custom ->doit and ->dumpit to deal with PHY listing commands.

As most of the code was custom, this basically means re-writing how we
deal with PHY listing.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/netlink.c |   9 +-
 net/ethtool/netlink.h |   4 -
 net/ethtool/phy.c     | 344 ++++++++++++------------------------------
 3 files changed, 105 insertions(+), 252 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 171290eaf406..217024af68fd 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -382,6 +382,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_MM_SET]		= &ethnl_mm_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_GET]	= &ethnl_tsconfig_request_ops,
 	[ETHTOOL_MSG_TSCONFIG_SET]	= &ethnl_tsconfig_request_ops,
+	[ETHTOOL_MSG_PHY_GET]		= &ethnl_phy_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1381,10 +1382,10 @@ static const struct genl_ops ethtool_genl_ops[] = {
 	},
 	{
 		.cmd	= ETHTOOL_MSG_PHY_GET,
-		.doit	= ethnl_phy_doit,
-		.start	= ethnl_phy_start,
-		.dumpit	= ethnl_phy_dumpit,
-		.done	= ethnl_phy_done,
+		.doit	= ethnl_default_doit,
+		.start	= ethnl_default_start,
+		.dumpit	= ethnl_default_dumpit,
+		.done	= ethnl_default_done,
 		.policy = ethnl_phy_get_policy,
 		.maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1,
 	},
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 530a9b5c8b39..60f16090640f 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -542,10 +542,6 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info);
 int ethnl_rss_dump_start(struct netlink_callback *cb);
 int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_start(struct netlink_callback *cb);
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
-int ethnl_phy_done(struct netlink_callback *cb);
 int ethnl_tsinfo_start(struct netlink_callback *cb);
 int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_tsinfo_done(struct netlink_callback *cb);
diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c
index 1f590e8d75ed..88343fed7366 100644
--- a/net/ethtool/phy.c
+++ b/net/ethtool/phy.c
@@ -12,304 +12,160 @@
 #include <net/netdev_lock.h>
 
 struct phy_req_info {
-	struct ethnl_req_info		base;
-	struct phy_device_node		*pdn;
+	struct ethnl_req_info base;
 };
 
-#define PHY_REQINFO(__req_base) \
-	container_of(__req_base, struct phy_req_info, base)
+struct phy_reply_data {
+	struct ethnl_reply_data	base;
+	u32 phyindex;
+	char *drvname;
+	char *name;
+	unsigned int upstream_type;
+	char *upstream_sfp_name;
+	unsigned int upstream_index;
+	char *downstream_sfp_name;
+};
+
+#define PHY_REPDATA(__reply_base) \
+	container_of(__reply_base, struct phy_reply_data, base)
 
 const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1] = {
 	[ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
-/* Caller holds rtnl */
-static ssize_t
-ethnl_phy_reply_size(const struct ethnl_req_info *req_base,
-		     struct netlink_ext_ack *extack)
+static int phy_reply_size(const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 	size_t size = 0;
 
-	ASSERT_RTNL();
-
 	/* ETHTOOL_A_PHY_INDEX */
 	size += nla_total_size(sizeof(u32));
 
 	/* ETHTOOL_A_DRVNAME */
-	if (phydev->drv)
-		size += nla_total_size(strlen(phydev->drv->name) + 1);
+	if (rep_data->drvname)
+		size += nla_total_size(strlen(rep_data->drvname) + 1);
 
 	/* ETHTOOL_A_NAME */
-	size += nla_total_size(strlen(dev_name(&phydev->mdio.dev)) + 1);
+	size += nla_total_size(strlen(rep_data->name) + 1);
 
 	/* ETHTOOL_A_PHY_UPSTREAM_TYPE */
 	size += nla_total_size(sizeof(u32));
 
-	if (phy_on_sfp(phydev)) {
-		const char *upstream_sfp_name = sfp_get_name(pdn->parent_sfp_bus);
-
-		/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
-		if (upstream_sfp_name)
-			size += nla_total_size(strlen(upstream_sfp_name) + 1);
+	/* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */
+	if (rep_data->upstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->upstream_sfp_name) + 1);
 
-		/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	/* ETHTOOL_A_PHY_UPSTREAM_INDEX */
+	if (rep_data->upstream_index)
 		size += nla_total_size(sizeof(u32));
-	}
 
 	/* ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME */
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
-
-		if (sfp_name)
-			size += nla_total_size(strlen(sfp_name) + 1);
-	}
+	if (rep_data->downstream_sfp_name)
+		size += nla_total_size(strlen(rep_data->downstream_sfp_name) + 1);
 
 	return size;
 }
 
-static int
-ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff *skb)
+static int phy_prepare_data(const struct ethnl_req_info *req_info,
+			    struct ethnl_reply_data *reply_data,
+			    const struct genl_info *info)
 {
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device_node *pdn = req_info->pdn;
-	struct phy_device *phydev = pdn->phy;
-	enum phy_upstream ptype;
+	struct phy_link_topology *topo = reply_data->dev->link_topo;
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
+	struct nlattr **tb = info->attrs;
+	struct phy_device_node *pdn;
+	struct phy_device *phydev;
 
-	ptype = pdn->upstream_type;
+	/* RTNL is held by the caller */
+	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
+				      info->extack);
+	if (IS_ERR_OR_NULL(phydev))
+		return -EOPNOTSUPP;
 
-	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, phydev->phyindex) ||
-	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, dev_name(&phydev->mdio.dev)) ||
-	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, ptype))
-		return -EMSGSIZE;
+	pdn = xa_load(&topo->phys, phydev->phyindex);
+	if (!pdn)
+		return -EOPNOTSUPP;
 
-	if (phydev->drv &&
-	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, phydev->drv->name))
-		return -EMSGSIZE;
+	rep_data->phyindex = phydev->phyindex;
+	rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
+	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+	rep_data->upstream_type = pdn->upstream_type;
 
-	if (ptype == PHY_UPSTREAM_PHY) {
+	if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
 		struct phy_device *upstream = pdn->upstream.phydev;
-		const char *sfp_upstream_name;
-
-		/* Parent index */
-		if (nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX, upstream->phyindex))
-			return -EMSGSIZE;
-
-		if (pdn->parent_sfp_bus) {
-			sfp_upstream_name = sfp_get_name(pdn->parent_sfp_bus);
-			if (sfp_upstream_name &&
-			    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
-					   sfp_upstream_name))
-				return -EMSGSIZE;
-		}
+		rep_data->upstream_index = upstream->phyindex;
 	}
 
-	if (phydev->sfp_bus) {
-		const char *sfp_name = sfp_get_name(phydev->sfp_bus);
+	if (pdn->parent_sfp_bus)
+		rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
+						      GFP_KERNEL);
 
-		if (sfp_name &&
-		    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
-				   sfp_name))
-			return -EMSGSIZE;
-	}
+	if (phydev->sfp_bus)
+		rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
+							GFP_KERNEL);
 
 	return 0;
 }
 
-static int ethnl_phy_parse_request(struct ethnl_req_info *req_base,
-				   struct nlattr **tb,
-				   struct netlink_ext_ack *extack)
+static int phy_fill_reply(struct sk_buff *skb,
+			  const struct ethnl_req_info *req_info,
+			  const struct ethnl_reply_data *reply_data)
 {
-	struct phy_link_topology *topo = req_base->dev->link_topo;
-	struct phy_req_info *req_info = PHY_REQINFO(req_base);
-	struct phy_device *phydev;
-
-	phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PHY_HEADER,
-				      extack);
-	if (!phydev)
-		return 0;
-
-	if (IS_ERR(phydev))
-		return PTR_ERR(phydev);
-
-	if (!topo)
-		return 0;
-
-	req_info->pdn = xa_load(&topo->phys, phydev->phyindex);
-
-	return 0;
-}
-
-int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info)
-{
-	struct phy_req_info req_info = {};
-	struct nlattr **tb = info->attrs;
-	struct sk_buff *rskb;
-	void *reply_payload;
-	int reply_len;
-	int ret;
-
-	ret = ethnl_parse_header_dev_get(&req_info.base,
-					 tb[ETHTOOL_A_PHY_HEADER],
-					 genl_info_net(info), info->extack,
-					 true);
-	if (ret < 0)
-		return ret;
-
-	rtnl_lock();
-	netdev_lock_ops(req_info.base.dev);
-
-	ret = ethnl_phy_parse_request(&req_info.base, tb, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-
-	/* No PHY, return early */
-	if (!req_info.pdn)
-		goto err_unlock;
-
-	ret = ethnl_phy_reply_size(&req_info.base, info->extack);
-	if (ret < 0)
-		goto err_unlock;
-	reply_len = ret + ethnl_reply_header_size();
-
-	rskb = ethnl_reply_init(reply_len, req_info.base.dev,
-				ETHTOOL_MSG_PHY_GET_REPLY,
-				ETHTOOL_A_PHY_HEADER,
-				info, &reply_payload);
-	if (!rskb) {
-		ret = -ENOMEM;
-		goto err_unlock;
-	}
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	ret = ethnl_phy_fill_reply(&req_info.base, rskb);
-	if (ret)
-		goto err_free_msg;
-
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	genlmsg_end(rskb, reply_payload);
-
-	return genlmsg_reply(rskb, info);
-
-err_free_msg:
-	nlmsg_free(rskb);
-err_unlock:
-	netdev_unlock_ops(req_info.base.dev);
-	rtnl_unlock();
-	ethnl_parse_header_dev_put(&req_info.base);
-	return ret;
-}
-
-struct ethnl_phy_dump_ctx {
-	struct phy_req_info	*phy_req_info;
-	unsigned long ifindex;
-	unsigned long phy_index;
-};
-
-int ethnl_phy_start(struct netlink_callback *cb)
-{
-	const struct genl_info *info = genl_info_dump(cb);
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	int ret;
+	if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, rep_data->phyindex) ||
+	    nla_put_string(skb, ETHTOOL_A_PHY_NAME, rep_data->name) ||
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, rep_data->upstream_type))
+		return -EMSGSIZE;
 
-	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+	if (rep_data->drvname &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, rep_data->drvname))
+		return -EMSGSIZE;
 
-	ctx->phy_req_info = kzalloc(sizeof(*ctx->phy_req_info), GFP_KERNEL);
-	if (!ctx->phy_req_info)
-		return -ENOMEM;
+	if (rep_data->upstream_index &&
+	    nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX,
+			rep_data->upstream_index))
+		return -EMSGSIZE;
 
-	ret = ethnl_parse_header_dev_get(&ctx->phy_req_info->base,
-					 info->attrs[ETHTOOL_A_PHY_HEADER],
-					 sock_net(cb->skb->sk), cb->extack,
-					 false);
-	ctx->ifindex = 0;
-	ctx->phy_index = 0;
+	if (rep_data->upstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+			   rep_data->upstream_sfp_name))
+		return -EMSGSIZE;
 
-	if (ret)
-		kfree(ctx->phy_req_info);
+	if (rep_data->downstream_sfp_name &&
+	    nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+			   rep_data->downstream_sfp_name))
+		return -EMSGSIZE;
 
-	return ret;
+	return 0;
 }
 
-int ethnl_phy_done(struct netlink_callback *cb)
+static void phy_cleanup_data(struct ethnl_reply_data *reply_data)
 {
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-
-	if (ctx->phy_req_info->base.dev)
-		ethnl_parse_header_dev_put(&ctx->phy_req_info->base);
-
-	kfree(ctx->phy_req_info);
+	struct phy_reply_data *rep_data = PHY_REPDATA(reply_data);
 
-	return 0;
+	kfree(rep_data->drvname);
+	kfree(rep_data->name);
+	kfree(rep_data->upstream_sfp_name);
+	kfree(rep_data->downstream_sfp_name);
 }
 
-static int ethnl_phy_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
-				  struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct phy_req_info *pri = ctx->phy_req_info;
-	struct phy_device_node *pdn;
-	int ret = 0;
-	void *ehdr;
-
-	if (!dev->link_topo)
-		return 0;
-
-	xa_for_each_start(&dev->link_topo->phys, ctx->phy_index, pdn, ctx->phy_index) {
-		ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_PHY_GET_REPLY);
-		if (!ehdr) {
-			ret = -EMSGSIZE;
-			break;
-		}
-
-		ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_PHY_HEADER);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		pri->pdn = pdn;
-		ret = ethnl_phy_fill_reply(&pri->base, skb);
-		if (ret < 0) {
-			genlmsg_cancel(skb, ehdr);
-			break;
-		}
-
-		genlmsg_end(skb, ehdr);
-	}
+const struct ethnl_request_ops ethnl_phy_request_ops = {
+	.request_cmd		= ETHTOOL_MSG_PHY_GET,
+	.reply_cmd		= ETHTOOL_MSG_PHY_GET_REPLY,
+	.hdr_attr		= ETHTOOL_A_PHY_HEADER,
+	.req_info_size		= sizeof(struct phy_req_info),
+	.reply_data_size	= sizeof(struct phy_reply_data),
 
-	return ret;
-}
+	.prepare_data		= phy_prepare_data,
+	.reply_size		= phy_reply_size,
+	.fill_reply		= phy_fill_reply,
+	.cleanup_data		= phy_cleanup_data,
 
-int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx;
-	struct net *net = sock_net(skb->sk);
-	struct net_device *dev;
-	int ret = 0;
-
-	rtnl_lock();
-
-	if (ctx->phy_req_info->base.dev) {
-		dev = ctx->phy_req_info->base.dev;
-		netdev_lock_ops(dev);
-		ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-		netdev_unlock_ops(dev);
-	} else {
-		for_each_netdev_dump(net, dev, ctx->ifindex) {
-			netdev_lock_ops(dev);
-			ret = ethnl_phy_dump_one_dev(skb, dev, cb);
-			netdev_unlock_ops(dev);
-			if (ret)
-				break;
-
-			ctx->phy_index = 0;
-		}
-	}
-	rtnl_unlock();
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
 
-	return ret;
-}
+	.allow_pernetdev_dump	= true,
+};
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:09 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:09 +0100
Subject: [PATCH net-next v4 7/8] net: ethtool: plca: Use per-PHY DUMP operations
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-8-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PLCA-able PHY on the link.

This is done for both PLCA status and PLCA config.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/plca.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c
index e1f7820a6158..2148ff607561 100644
--- a/net/ethtool/plca.c
+++ b/net/ethtool/plca.c
@@ -191,6 +191,12 @@ const struct ethnl_request_ops ethnl_plca_cfg_request_ops = {
 
 	.set			= ethnl_set_plca,
 	.set_ntf_cmd		= ETHTOOL_MSG_PLCA_NTF,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
 
 // PLCA get status message -------------------------------------------------- //
@@ -268,4 +274,10 @@ const struct ethnl_request_ops ethnl_plca_status_request_ops = {
 	.prepare_data		= plca_get_status_prepare_data,
 	.reply_size		= plca_get_status_reply_size,
 	.fill_reply		= plca_get_status_fill_reply,
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:10 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:10 +0100
Subject: [PATCH net-next v4 8/8] net: ethtool: pse-pd: Use per-PHY DUMP operations
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-9-maxime.chevallier@bootlin.com>

Leverage the per-phy ethnl DUMP helpers in case we have more that one
PSE PHY on the link.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/pse-pd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
index 4f6b99eab2a6..f3d14be8bdd9 100644
--- a/net/ethtool/pse-pd.c
+++ b/net/ethtool/pse-pd.c
@@ -314,4 +314,10 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
 
 	.set			= ethnl_set_pse,
 	/* PSE has no notification */
+
+	.dump_start		= ethnl_dump_start_perphy,
+	.dump_one_dev		= ethnl_dump_one_dev_perphy,
+	.dump_done		= ethnl_dump_done_perphy,
+
+	.allow_pernetdev_dump	= true,
 };
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:02 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:02 +0100
Subject: [PATCH net-next v4 0/8] net: ethtool: Introduce ethnl dump helpers
Message-ID: <20250324104012.367366-1-maxime.chevallier@bootlin.com>

Hi everyone,

This is V4 for the ethnl dump support, allowing better handling of
per-phy dump but also any other dump operation that needs to dump more
than one message per netdev.

Changes in V4:
 - Don't grab rcu_read_lock when we already have a refcounter netdev on
   the filtered dump path (Paolo)
 - Move the dump_all stuff in a dedicated helper (Paolo)
 - Added patch 1 to set the dev in ctx->req_info

Changes in V3:
 - Fixed some typos and xmas tree issues
 - Added a missing check for EOPNOTSUPP in patch 1
 - Added missing kdoc
 - Added missing comments in phy_reply_size

Changes in V2:
 - Rebased on the netdev_lock work by Stanislav and the fixes from Eric
 - Fixed a bissectability issue
 - Fixed kdoc for the new ethnl ops and fields

V1: https://lore.kernel.org/netdev/20250305141938.319282-1-maxime.chevallier at bootlin.com/
V2: https://lore.kernel.org/netdev/20250308155440.267782-1-maxime.chevallier at bootlin.com/
V3: https://lore.kernel.org/netdev/20250313182647.250007-1-maxime.chevallier at bootlin.com/

As of today when using ethnl's default ops, the DUMP requests will
simply perform a GET for each netdev.

That hits limitations for commands that may return multiple messages for
a single netdev, such as :

 - RSS (listing contexts)
 - All PHY-specific commands (PLCA, PSE-PD, phy)
 - tsinfo (one item for the netdev +  one per phy)

 Commands that need a non-default DUMP support have to re-implement
 ->dumpit() themselves, which prevents using most of ethnl's internal
 circuitry.

This series therefore introduces a better support for dump operations in
ethnl.

The patches 1 and 2 introduce the support for filtered DUMPs, where an
ifindex/ifname can be passed in the request header for the DUMP
operation. This is for when we want to dump everything a netdev
supports, but without doing so for every single netdev. ethtool's
"--show-phys ethX" option for example performs a filtered dump.

Patch 3 introduces 3 new ethnl ops : 
 ->dump_start() to initialize a dump context
 ->dump_one_dev(), that can be implemented per-command to dump
 everything on a given netdev
 ->dump_done() to release the context

The default behaviour for dumps remains the same, calling the whole
->doit() path for each netdev.

Patch 4 introduces a set of ->dump_start(), ->dump_one_dev() and
->dump_done() callback implementations that can simply be plugged into
the existing commands that list objects per-phy, making the 
phy-targeting command behaviour more coherent.

Patch 5 uses that new set of helpers to rewrite the phy.c support, which
now uses the regulat ethnl_ops instead of fully custom genl ops. This
one is the hardest to review, sorry about that, I couldn't really manage
to incrementally rework that file :(

Patches 6 and 7 are where the new dump infra shines, adding per-netdev
per-phy dump support for PLCA and PSE-PD.

We could also consider converting tsinfo/tsconfig, rss and tunnels to
these new ->dump_***() operations as well, but that's out of this
series' scope.

Thanks,

Maxime



Maxime Chevallier (8):
  net: ethtool: Set the req_info->dev on DUMP requests for each dev
  net: ethtool: netlink: Allow per-netdevice DUMP operations
  net: ethtool: netlink: Rename ethnl_default_dump_one
  net: ethtool: netlink: Introduce command-specific dump_one_dev
  net: ethtool: netlink: Introduce per-phy DUMP helpers
  net: ethtool: phy: Convert the PHY_GET command to generic phy dump
  net: ethtool: plca: Use per-PHY DUMP operations
  net: ethtool: pse-pd: Use per-PHY DUMP operations

 net/ethtool/netlink.c | 185 ++++++++++++++++++-----
 net/ethtool/netlink.h |  47 +++++-
 net/ethtool/phy.c     | 344 ++++++++++++------------------------------
 net/ethtool/plca.c    |  12 ++
 net/ethtool/pse-pd.c  |   6 +
 5 files changed, 310 insertions(+), 284 deletions(-)

-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:03 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:03 +0100
Subject: [PATCH net-next v4 1/8] net: ethtool: Set the req_info->dev on DUMP requests for each dev
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-2-maxime.chevallier@bootlin.com>

There are a few netlink commands that rely on the req_info->dev field
being populated by ethnl in their ->prepare_data() and ->fill_reply().

For a regular GET request, this will be set by ethnl_default_parse(),
which calls ethnl_parse_header_dev_get().

In the case of a DUMP request, the ->prepare_data() and ->fill_reply()
callbacks will be called with the req_info->dev being NULL, which can
cause discrepancies in the behaviour between GET and DUMP results.

The main impact is that ethnl_req_get_phydev() will not find any
phy_device, impacting :
 - plca
 - pse-pd
 - stats

Some other commands rely on req_info->dev, namely :
 - coalesce in ->fill_reply to look for an irq_moder

Although cable_test and tunnels also rely on req_info->dev being set,
that's not a problem for these commands as :
 - cable_test doesn't support DUMP
 - tunnels rolls its own ->dumpit (and sets dev in the req_info).
 - phy also has its own ->dumpit

All other commands use reply_data->dev (probably the correct way of
doing things) and aren't facing this issue.

Simply set the dev in the req_info context when iterating to dump each
dev.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : New patch (was sent separaltely once)

 net/ethtool/netlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index a163d40c6431..6b1725795435 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -591,6 +591,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 		dev_hold(dev);
 		rcu_read_unlock();
 
+		ctx->req_info->dev = dev;
 		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
 
 		rcu_read_lock();
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:04 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:04 +0100
Subject: [PATCH net-next v4 2/8] net: ethtool: netlink: Allow per-netdevice DUMP operations
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-3-maxime.chevallier@bootlin.com>

We have a number of netlink commands in the ethnl family that may have
multiple objects to dump even for a single net_device, including :

 - PLCA, PSE-PD, phy: one message per PHY device
 - tsinfo: one message per timestamp source (netdev + phys)
 - rss: One per RSS context

To get this behaviour, these netlink commands need to roll a custom
->dumpit().

To prepare making per-netdev DUMP more generic in ethnl, introduce a
member in the ethnl ops to indicate if a given command may allow
pernetdev DUMPs (also referred to as filtered DUMPs).

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4: - Don't hold RCU in the filtered path
    - Move dump_all into a new separate helper

 net/ethtool/netlink.c | 37 ++++++++++++++++++++++++++++++-------
 net/ethtool/netlink.h |  2 ++
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 6b1725795435..31ab89ca0bcc 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -577,9 +577,7 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
 	return ret;
 }
 
-/* Default ->dumpit() handler for GET requests. */
-static int ethnl_default_dumpit(struct sk_buff *skb,
-				struct netlink_callback *cb)
+static int ethnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
 	struct net *net = sock_net(skb->sk);
@@ -609,6 +607,31 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 	return ret;
 }
 
+/* Default ->dumpit() handler for GET requests. */
+static int ethnl_default_dumpit(struct sk_buff *skb,
+				struct netlink_callback *cb)
+{
+	struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
+	int ret;
+
+	if (ctx->req_info->dev) {
+		/* Filtered DUMP request targeted to a single netdev. We already
+		 * hold a ref to the netdev from ->start()
+		 */
+		ret = ethnl_default_dump_one(skb, ctx->req_info->dev, ctx,
+					     genl_info_dump(cb));
+		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
+
+		if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
+			ret = skb->len;
+
+	} else {
+		ret = ethnl_dump_all(skb, cb);
+	}
+
+	return ret;
+}
+
 /* generic ->start() handler for GET requests */
 static int ethnl_default_start(struct netlink_callback *cb)
 {
@@ -636,10 +659,10 @@ static int ethnl_default_start(struct netlink_callback *cb)
 	}
 
 	ret = ethnl_default_parse(req_info, &info->info, ops, false);
-	if (req_info->dev) {
-		/* We ignore device specification in dump requests but as the
-		 * same parser as for non-dump (doit) requests is used, it
-		 * would take reference to the device if it finds one
+	if (req_info->dev && !ops->allow_pernetdev_dump) {
+		/* We ignore device specification in unfiltered dump requests
+		 * but as the same parser as for non-dump (doit) requests is
+		 * used, it would take reference to the device if it finds one
 		 */
 		netdev_put(req_info->dev, &req_info->dev_tracker);
 		req_info->dev = NULL;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index ec6ab5443a6f..4aaa73282d6a 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -331,6 +331,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
  * @req_info_size:    size of request info
  * @reply_data_size:  size of reply data
  * @allow_nodev_do:   allow non-dump request with no device identification
+ * @allow_pernetdev_dump: allow filtering dump requests with ifname/ifindex
  * @set_ntf_cmd:      notification to generate on changes (SET)
  * @parse_request:
  *	Parse request except common header (struct ethnl_req_info). Common
@@ -388,6 +389,7 @@ struct ethnl_request_ops {
 	unsigned int		req_info_size;
 	unsigned int		reply_data_size;
 	bool			allow_nodev_do;
+	bool			allow_pernetdev_dump;
 	u8			set_ntf_cmd;
 
 	int (*parse_request)(struct ethnl_req_info *req_info,
-- 
2.48.1



From maxime.chevallier at bootlin.com  Mon Mar 24 03:40:05 2025
From: maxime.chevallier at bootlin.com (Maxime Chevallier)
Date: Mon, 24 Mar 2025 11:40:05 +0100
Subject: [PATCH net-next v4 3/8] net: ethtool: netlink: Rename ethnl_default_dump_one
In-Reply-To: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
Message-ID: <20250324104012.367366-4-maxime.chevallier@bootlin.com>

As we work on getting more objects out of a per-netdev DUMP, rename
ethnl_default_dump_one() into ethnl_default_dump_one_dev(), making it
explicit that this dumps everything for one netdev.

Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
---
V4 : No changes

 net/ethtool/netlink.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 31ab89ca0bcc..63ede3638708 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -540,9 +540,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
-static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
-				  const struct ethnl_dump_ctx *ctx,
-				  const struct genl_info *info)
+static int ethnl_default_dump_one_dev(struct sk_buff *skb, struct net_device *dev,
+				      const struct ethnl_dump_ctx *ctx,
+				      const struct genl_info *info)
 {
 	void *ehdr;
 	int ret;
@@ -590,7 +590,8 @@ static int ethnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 		rcu_read_unlock();
 
 		ctx->req_info->dev = dev;
-		ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb));
+		ret = ethnl_default_dump_one_dev(skb, dev, ctx,
+						 genl_info_dump(cb));
 
 		rcu_read_lock();
 		dev_put(dev);
@@ -618,8 +619,8 @@ static int ethnl_default_dumpit(struct sk_buff *skb,
 		/* Filtered DUMP request targeted to a single netdev. We already
 		 * hold a ref to the netdev from ->start()
 		 */
-		ret = ethnl_default_dump_one(skb, ctx->req_info->dev, ctx,
-					     genl_info_dump(cb));
+		ret = ethnl_default_dump_one_dev(skb, ctx->req_info->dev, ctx,
+						 genl_info_dump(cb));
 		netdev_put(ctx->req_info->dev, &ctx->req_info->dev_tracker);
 
 		if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
-- 
2.48.1



From hca at linux.ibm.com  Mon Mar 24 03:47:02 2025
From: hca at linux.ibm.com (Heiko Carstens)
Date: Mon, 24 Mar 2025 11:47:02 +0100
Subject: [PATCH v4 10/14] s390: Add support for suppressing warning
 backtraces
In-Reply-To: <CAGegRW4GinPmsav5=VBfjXBKy4cUEs5FWv-ixXODk7ajZ69vYg@mail.gmail.com>
References: <20250313114329.284104-1-acarmina@redhat.com>
 <20250313114329.284104-11-acarmina@redhat.com>
 <b6bb68f0-7e93-4db2-9fe6-f615f06ddeb1@roeck-us.net>
 <CAGegRW4GinPmsav5=VBfjXBKy4cUEs5FWv-ixXODk7ajZ69vYg@mail.gmail.com>
Message-ID: <20250324104702.12139E73-hca@linux.ibm.com>

On Fri, Mar 21, 2025 at 10:05:42PM +0100, Alessandro Carminati wrote:
> > > +#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
> > > +# define HAVE_BUG_FUNCTION
> > > +# define __BUG_FUNC_PTR      "       .long   %0-.\n"
> > > +# define __BUG_FUNC  __func__
> >
> > gcc 7.5.0 on s390 barfs; it doesn't like the use of "__func__" with "%0-."

...

> GCC makes significant efforts to handle this, and for several
> architectures, it manages to solve the problem.
> However, this is not universally the case.
> Additionally, -fPIC is not widely used in kernel code... I have only
> seen it used for VDSO, the x86 boot piggyback decompressor, PowerPC
> boot, and the s390x architecture.
> 
> That said, GCC has been mitigating this issue, allowing us to treat a
> non-compile-time constant as if it were one.
> A proof of this is that, at least since GCC 11, the s390x version of
> GCC is able to build this code.
> Before that... certainly in GCC 7.5 it couldn't.
> 
> A simple fix would be to restrict usage to GCC versions greater than
> 11 for s390.

But please add that dependency only for this new feature for the time
being. Right now I would not like to see that s390 is the only architecture
(besides parisc) which requires a much higher minimum gcc level than every
other architecture. Unless there are specific reasons.


From dsimic at manjaro.org  Mon Mar 24 04:00:43 2025
From: dsimic at manjaro.org (Dragan Simic)
Date: Mon, 24 Mar 2025 12:00:43 +0100
Subject: [PATCH v2] arm64: dts: rockchip: Remove overdrive-mode OPPs from RK3588J SoC dtsi
Message-ID: <eeec0d30d79b019d111b3f0aa2456e69896b2caa.1742813866.git.dsimic@manjaro.org>

The differences in the vendor-approved CPU and GPU OPPs for the standard
Rockchip RK3588 variant [1] and the industrial Rockchip RK3588J variant [2]
come from the latter, presumably, supporting an extended temperature range
that's usually associated with industrial applications, despite the two SoC
variant datasheets specifying the same upper limit for the allowed ambient
temperature for both variants.  However, the lower temperature limit is
specified much lower for the RK3588J variant. [1][2]

To be on the safe side and to ensure maximum longevity of the RK3588J SoCs,
only the CPU and GPU OPPs that are declared by the vendor to be always safe
for this SoC variant may be provided.  As explained by the vendor [3] and
according to the RK3588J datasheet, [2] higher-frequency/higher-voltage
CPU and GPU OPPs can be used as well, but at the risk of reducing the SoC
lifetime expectancy.  Presumably, using the higher OPPs may be safe only
when not enjoying the assumed extended temperature range that the RK3588J,
as an SoC variant targeted specifically at higher-temperature, industrial
applications, is made (or binned) for.

Anyone able to keep their RK3588J-based board outside the above-presumed
extended temperature range at all times, and willing to take the associated
risk of possibly reducing the SoC lifetime expectancy, is free to apply
a DT overlay that adds the higher CPU and GPU OPPs.

With all this and the downstream RK3588(J) DT definitions [4][5] in mind,
let's delete the RK3588J CPU and GPU OPPs that are not considered belonging
to the normal operation mode for this SoC variant.  To quote the RK3588J
datasheet [2], "normal mode means the chipset works under safety voltage
and frequency;  for the industrial environment, highly recommend to keep in
normal mode, the lifetime is reasonably guaranteed", while "overdrive mode
brings higher frequency, and the voltage will increase accordingly;  under
the overdrive mode for a long time, the chipset may shorten the lifetime,
especially in high-temperature condition".

To sum the RK3588J datasheet [2] and the vendor-provided DTs up, [4][5]
the maximum allowed CPU core, GPU and NPU frequencies are as follows:

   IP core    | Normal mode | Overdrive mode
  ------------+-------------+----------------
   Cortex-A55 |   1,296 MHz |      1,704 MHz
   Cortex-A76 |   1,608 MHz |      2,016 MHz
   GPU        |     700 MHz |        850 MHz
   NPU        |     800 MHz |        950 MHz

Unfortunately, when it comes to the actual voltages for the RK3588J CPU and
GPU OPPs, there's a discrepancy between the RK3588J datasheet [2] and the
downstream kernel code. [4][5]  The RK3588J datasheet states that "the max.
working voltage of CPU/GPU/NPU is 0.75 V under the normal mode", while the
downstream kernel code actually allows voltage ranges that go up to 0.95 V,
which is still within the voltage range allowed by the datasheet.  However,
the RK3588J datasheet also tells us to "strictly refer to the software
configuration of SDK and the hardware reference design", so let's embrace
the voltage ranges provided by the downstream kernel code, which also
prevents the undesirable theoretical outcome of ending up with no usable
OPPs on a particular board, as a result of the board's voltage regulator(s)
being unable to deliver the exact voltages, for whatever reason.

The above-described voltage ranges for the RK3588J CPU OPPs remain taken
from the downstream kernel code [4][5] by picking the highest, worst-bin
values, which ensure that all RK3588J bins will work reliably.  Yes, with
some power inevitably wasted as unnecessarily generated heat, but the
reliability is paramount, together with the longevity.  This deficiency
may be revisited separately at some point in the future.

The provided RK3588J CPU OPPs follow the slightly debatable "provide only
the highest-frequency OPP from the same-voltage group" approach that's been
established earlier, [6] as a result of the "same-voltage, lower-frequency"
OPPs being considered inefficient from the IPA governor's standpoint, which
may also be revisited separately at some point in the future.

[1] https://wiki.friendlyelec.com/wiki/images/e/ee/Rockchip_RK3588_Datasheet_V1.6-20231016.pdf
[2] https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2403201054_Rockchip-RK3588J_C22364189.pdf
[3] https://lore.kernel.org/linux-rockchip/e55125ed-64fb-455e-b1e4-cebe2cf006e4 at cherry.de/T/#u
[4] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
[5] https://raw.githubusercontent.com/rockchip-linux/kernel/604cec4004abe5a96c734f2fab7b74809d2d742f/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
[6] https://lore.kernel.org/all/20240229-rk-dts-additions-v3-5-6afe8473a631 at gmail.com/

Fixes: 667885a68658 ("arm64: dts: rockchip: Add OPP data for CPU cores on RK3588j")
Fixes: a7b2070505a2 ("arm64: dts: rockchip: Split GPU OPPs of RK3588 and RK3588j")
Cc: stable at vger.kernel.org
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: Alexey Charkov <alchark at gmail.com>
Helped-by: Quentin Schulz <quentin.schulz at cherry.de>
Reviewed-by: Quentin Schulz <quentin.schulz at cherry.de>
Signed-off-by: Dragan Simic <dsimic at manjaro.org>
---

Notes:
    Changes in v2:
      - Reworded and expanded the patch description a bit, to include some
        more information and to make it more clear what are the implied
        speculations and assumptions, and what are the available official
        statements from Rockchip, as suggested by Quentin [7]
      - Collected Reviewed-by tag from Quentin [7]
    
    Link to v1: https://lore.kernel.org/linux-rockchip/f929da061de35925ea591c969f985430e23c4a7e.1742526811.git.dsimic at manjaro.org/T/#u
    
    [7] https://lore.kernel.org/linux-rockchip/71b7c81b-6a4e-442b-a661-04d63639962a at cherry.de/

 arch/arm64/boot/dts/rockchip/rk3588j.dtsi | 53 ++++++++---------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
index bce72bac4503..3045cb3bd68c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
@@ -11,74 +11,59 @@ cluster0_opp_table: opp-table-cluster0 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-1416000000 {
-			opp-hz = /bits/ 64 <1416000000>;
+		opp-1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <750000 750000 950000>;
 			clock-latency-ns = <40000>;
 			opp-suspend;
 		};
-		opp-1608000000 {
-			opp-hz = /bits/ 64 <1608000000>;
-			opp-microvolt = <887500 887500 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-1704000000 {
-			opp-hz = /bits/ 64 <1704000000>;
-			opp-microvolt = <937500 937500 950000>;
+		opp-1296000000 {
+			opp-hz = /bits/ 64 <1296000000>;
+			opp-microvolt = <775000 775000 950000>;
 			clock-latency-ns = <40000>;
 		};
 	};
 
 	cluster1_opp_table: opp-table-cluster1 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
+		opp-1200000000{
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <750000 750000 950000>;
+			clock-latency-ns = <40000>;
+		};
 		opp-1416000000 {
 			opp-hz = /bits/ 64 <1416000000>;
-			opp-microvolt = <750000 750000 950000>;
+			opp-microvolt = <762500 762500 950000>;
 			clock-latency-ns = <40000>;
 		};
 		opp-1608000000 {
 			opp-hz = /bits/ 64 <1608000000>;
 			opp-microvolt = <787500 787500 950000>;
 			clock-latency-ns = <40000>;
 		};
-		opp-1800000000 {
-			opp-hz = /bits/ 64 <1800000000>;
-			opp-microvolt = <875000 875000 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-2016000000 {
-			opp-hz = /bits/ 64 <2016000000>;
-			opp-microvolt = <950000 950000 950000>;
-			clock-latency-ns = <40000>;
-		};
 	};
 
 	cluster2_opp_table: opp-table-cluster2 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
+		opp-1200000000{
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <750000 750000 950000>;
+			clock-latency-ns = <40000>;
+		};
 		opp-1416000000 {
 			opp-hz = /bits/ 64 <1416000000>;
-			opp-microvolt = <750000 750000 950000>;
+			opp-microvolt = <762500 762500 950000>;
 			clock-latency-ns = <40000>;
 		};
 		opp-1608000000 {
 			opp-hz = /bits/ 64 <1608000000>;
 			opp-microvolt = <787500 787500 950000>;
 			clock-latency-ns = <40000>;
 		};
-		opp-1800000000 {
-			opp-hz = /bits/ 64 <1800000000>;
-			opp-microvolt = <875000 875000 950000>;
-			clock-latency-ns = <40000>;
-		};
-		opp-2016000000 {
-			opp-hz = /bits/ 64 <2016000000>;
-			opp-microvolt = <950000 950000 950000>;
-			clock-latency-ns = <40000>;
-		};
 	};
 
 	gpu_opp_table: opp-table {
@@ -104,10 +89,6 @@ opp-700000000 {
 			opp-hz = /bits/ 64 <700000000>;
 			opp-microvolt = <750000 750000 850000>;
 		};
-		opp-850000000 {
-			opp-hz = /bits/ 64 <800000000>;
-			opp-microvolt = <787500 787500 850000>;
-		};
 	};
 };
 


From funderscore at postmarketos.org  Mon Mar 24 04:00:47 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Mon, 24 Mar 2025 11:00:47 +0000
Subject: [PATCH v5 2/2] arm64: dts: amlogic: add support for
 xiaomi-aquaman/Mi TV Stick
In-Reply-To: <f36875c5-73bb-4bf8-a59f-5df30043bbbe@linaro.org>
References: <20250319190150.31529-2-funderscore@postmarketos.org>
 <20250319190150.31529-4-funderscore@postmarketos.org>
 <f36875c5-73bb-4bf8-a59f-5df30043bbbe@linaro.org>
Message-ID: <D8OG0OI3HO2V.326AQZHJWCBAI@postmarketos.org>

On Mon Mar 24, 2025 at 7:02 AM UTC, Neil Armstrong wrote:
> I get:
> Error: arch/arm64/boot/dts/amlogic/meson-gxl-s805y-xiaomi-aquaman.dts:243.1-2 syntax error
> FATAL ERROR: Unable to parse input tree

Yes, somehow a ";" is missing.

>
> whil building, could you fix that ?
>
> Neil



From krzk at kernel.org  Mon Mar 24 04:10:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 12:10:34 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <SI6PR06MB7535BAD19B51A381171A0E64F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
 <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>
 <SI6PR06MB7535BAD19B51A381171A0E64F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
Message-ID: <8e8aa069-af9f-453f-9bd0-e3dc2eab59ab@kernel.org>

On 24/03/2025 11:01, Ryan Chen wrote:
>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>> AST2600-i2cv2
>>
>> On 24/03/2025 09:30, Ryan Chen wrote:
>>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>>>> AST2600-i2cv2
>>>>
>>>> On 19/03/2025 12:12, Ryan Chen wrote:
>>>>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
>>>>>> AST2600-i2cv2
>>>>>>
>>>>>> On 17/03/2025 10:21, Ryan Chen wrote:
>>>>>>>> Neither this.
>>>>>>>>
>>>>>>>> So it seems you describe already existing and documented I2C, but
>>>>>>>> for some reason you want second compatible. The problem is that
>>>>>>>> you do not provide reason from the point of view of bindings.
>>>>>>>>
>>>>>>>> To summarize: what your users want - don't care. Start properly
>>>>>>>> describing hardware and your SoC.
>>>>>>>
>>>>>>> OK, for ast2600 i2c controller have two register mode setting.
>>>>>>> One, I call it is old register setting, that is right now
>>>>>>> i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus", And there
>>>>>>> have a global register
>>>>>> that can set i2c controller as new mode register set.
>>>>>>> That I am going to drive. That I post is all register in new an
>>>>>>> old register
>>>> list.
>>>>>>>
>>>>>>> For example,
>>>>>>> Global register [2] = 0 => i2c present as old register set Global
>>>>>>> register [2] = 1 => i2c present as new register set
>>>>>> It's the same device though, so the same compatible.
>>>>>
>>>>> Sorry, it is different design, and it share the same register space.
>>>>> So that the reason add new compatible "aspeed,ast2600-i2cv2" for
>>>>> this
>>>> driver.
>>>>> It is different register layout.
>>>>
>>>> Which device is described by the existing "aspeed,ast2600-i2c-bus"
>>>> compatible? And which device is described by new compatible?
>>>>
>>> On the AST2600 SoC, there are up to 16 I2C controller instances (I2C1 ~
>> I2C16).
>>
>> So you have 16 same devices.
> Yes, one driver instance for 16 i2c device. 
>>
>>> Each of these controllers is hardwired at the SoC level to use either the
>> legacy register layout or the new v2 register layout.
>>> The mode is selected by a bit in the global register, these represent two
>> different hardware blocks:
>>> "aspeed,ast2600-i2c-bus" describes controllers using the legacy register
>> layout.
>>> "aspeed,ast2600-i2cv2" describes controllers using the new register
>>> layout
>>
>> Which part of "same device" is not clear? You have one device, one compatible.
>> Whatever you do with register layout, is already defined by that compatible. It
>> does not matter that you forgot to implement it in the Linux kernel.
> 
> Sorry, I still can't catch your point.


I repeated twice "You have one device, one compatible.", provided few
more sentences and if this is still unclear, I don't know what to say more.

> I separated the support into two drivers:

I don't care about your drivers, why are you bringing them here?

> i2c-aspeed.c for legacy layout, compatible "aspeed,ast2600-i2c-bus"
> i2c-ast2600.c for the new register set, compatible compatible "aspeed,ast2600-i2cv2"
> Do you mean I have integrate into 1 driver at i2c-aspeed.c ? can't be separate two driver?

What is this patch about? Bindings. Not drivers. Look at email month ago:

"All this describes driver, not hardware."

Why are you keep bringing here drivers since a month?

Best regards,
Krzysztof


From ukleinek at kernel.org  Mon Mar 24 04:29:41 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 24 Mar 2025 12:29:41 +0100
Subject: [PATCH v4 3/3] pwm: pwm-cadence: Add support for TTC PWM
In-Reply-To: <20250115113556.2832282-4-mubin.sayyed@amd.com>
References: <20250115113556.2832282-1-mubin.sayyed@amd.com>
 <20250115113556.2832282-4-mubin.sayyed@amd.com>
Message-ID: <nwdxbyynffy7kkxdznxrogzqg2r5bje45ywgxa6jj7mcix65ze@dtabj46eut5i>

Hello,

On Wed, Jan 15, 2025 at 05:05:56PM +0530, Mubin Sayyed wrote:
> Cadence TTC timer can be configured as clocksource/clockevent or PWM
> device.Specific TTC device would be configured as PWM device, if
> pwm-cells property is present in the device tree node.
> 
> In case of Zynq, ZynqMP and Versal SoC's, each TTC device has 3
> timers/counters, so maximum 3 PWM channels can be configured for each TTC
> IP instance. Also, output of 0th PWM channel of each TTC device can be
> routed to MIO or EMIO, and output of 2nd and 3rd PWM channel can be
> routed only to EMIO.
> 
> Period for given PWM channel is configured through interval timer and
> duty cycle through match counter.
> 
> Details for cadence TTC IP can be found in Zynq UltraScale+ TRM.
> 
> Signed-off-by: Mubin Sayyed <mubin.sayyed at amd.com>
> ---
> Refer link given below for Zynq UltraScale+ TRM
> https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm

I would prefer to have a link to the TRM in the source file. When I
follow that link today however I only get "The document you are looking
for has been moved or deleted" :-\

> Changes for v4:
>  Configure it as part of TTC clocksource/clockevent driver
>  drivers/clocksource/timer-cadence-ttc.c.
>  Move probe/remove function to timer-cadence-ttc.c.
> Changes for v3:
>  None
> Changes for v2:
>  Use maybe_unused attribute for ttc_pwm_of_match_driver structure
>  Add new function ttc_pwm_set_polarity
>  Removed calls to pwm_get_state
>  Replace DIV_ROUNF_CLOSEST with mul_u64_u64_div_u64
>  Modify ttc_pwm_apply to remove while loop in prescalar logic
>  and avoid glitch
>  Calculate rate in probe and add it to private structure for further
>  Drop ttc_pwm_of_xlate
>  Replace of_clk_get with devm_clk_get_enabled
>  Drop _OFFSET and _MASK from definitions
>  Keep Kconfig and Makefile changes alphabetically sorted
>  Use remove_new instead of remove
>  Document limitations in driver file
> ---
>  drivers/pwm/Kconfig               |  10 +
>  drivers/pwm/Makefile              |   1 +
>  drivers/pwm/pwm-cadence.c         | 323 ++++++++++++++++++++++++++++++
>  include/linux/timer-cadence-ttc.h |  22 +-
>  4 files changed, 355 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/pwm/pwm-cadence.c
> 
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 0915c1e7df16..b418e5d8fa42 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -202,6 +202,16 @@ config PWM_CROS_EC
>  	  PWM driver for exposing a PWM attached to the ChromeOS Embedded
>  	  Controller.
>  
> +config PWM_CADENCE
> +	bool "Cadence TTC PWM driver"

tristate please

> +	depends on CADENCE_TTC_TIMER
> +	help
> +	  Generic PWM framework driver for cadence TTC IP found on
> +          Xilinx Zynq/ZynqMP/Versal SOCs. Each TTC device has 3 PWM
> +          channels. Output of 0th PWM channel of each TTC device can
> +          be routed to MIO or EMIO, and output of 1st and 2nd PWM
> +          channels can be routed only to EMIO.
> +
>  config PWM_DWC_CORE
>  	tristate
>  	depends on HAS_IOMEM
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 9081e0c0e9e0..246380391a63 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_PWM_BCM_KONA)	+= pwm-bcm-kona.o
>  obj-$(CONFIG_PWM_BCM2835)	+= pwm-bcm2835.o
>  obj-$(CONFIG_PWM_BERLIN)	+= pwm-berlin.o
>  obj-$(CONFIG_PWM_BRCMSTB)	+= pwm-brcmstb.o
> +obj-$(CONFIG_PWM_CADENCE)	+= pwm-cadence.o
>  obj-$(CONFIG_PWM_CLK)		+= pwm-clk.o
>  obj-$(CONFIG_PWM_CLPS711X)	+= pwm-clps711x.o
>  obj-$(CONFIG_PWM_CRC)		+= pwm-crc.o
> diff --git a/drivers/pwm/pwm-cadence.c b/drivers/pwm/pwm-cadence.c
> new file mode 100644
> index 000000000000..e7c337fe956b
> --- /dev/null
> +++ b/drivers/pwm/pwm-cadence.c
> @@ -0,0 +1,323 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver to configure cadence TTC timer as PWM
> + * generator
> + *
> + * Limitations:
> + * - When PWM is stopped, timer counter gets stopped immediately. This
> + *   doesn't allow the current PWM period to complete and stops abruptly.
> + * - Disabled PWM emits inactive level.
> + * - When user requests a change in  any parameter of PWM (period/duty cycle/polarity)

s/  / /

> + *   while PWM is in enabled state:
> + *	- PWM is stopped abruptly.
> + *	- Requested parameter is changed.
> + *	- Fresh PWM cycle is started.
> + *
> + * Copyright (C) 2025, Advanced Micro Devices, Inc.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>

I didn't check, but <linux/device.h> is unusual. Do you really need it?

> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/of_address.h>

Also I think this can be dropped.

> +#include <linux/timer-cadence-ttc.h>
> +
> +/**
> + * struct ttc_pwm_priv - Private data for TTC PWM drivers
> + * @chip:	PWM chip structure representing PWM controller
> + * @clk:	TTC input clock
> + * @rate:	TTC input clock rate
> + * @max:	Maximum value of the counters
> + * @base:	Base address of TTC instance
> + */
> +struct ttc_pwm_priv {
> +	struct pwm_chip chip;
> +	struct clk *clk;
> +	unsigned long rate;
> +	u32 max;
> +	void __iomem *base;
> +};
> +
> +static inline u32 ttc_pwm_readl(struct ttc_pwm_priv *priv,
> +				unsigned long offset)
> +{
> +	return readl_relaxed(priv->base + offset);
> +}
> +
> +static inline void ttc_pwm_writel(struct ttc_pwm_priv *priv,
> +				  unsigned long offset,
> +				  unsigned long val)
> +{
> +	writel_relaxed(val, priv->base + offset);
> +}
> +
> +static inline u32 ttc_pwm_ch_readl(struct ttc_pwm_priv *priv,
> +				   unsigned int chnum,
> +				   unsigned long offset)
> +{
> +	unsigned long pwm_ch_offset = offset +
> +				       (TTC_PWM_CHANNEL * chnum);
> +
> +	return ttc_pwm_readl(priv, pwm_ch_offset);
> +}
> +
> +static inline void ttc_pwm_ch_writel(struct ttc_pwm_priv *priv,
> +				     unsigned int chnum,
> +				     unsigned long offset,
> +				     unsigned long val)
> +{
> +	unsigned long pwm_ch_offset = offset +
> +				       (TTC_PWM_CHANNEL * chnum);
> +
> +	ttc_pwm_writel(priv, pwm_ch_offset, val);
> +}
> +
> +static inline struct ttc_pwm_priv *xilinx_pwm_chip_to_priv(struct pwm_chip *chip)

Can you please stick to a single unique function prefix? The involved
prefixes here are ttc_pwm, xilinx_pwm and the driver is called
"cadence". Unifying them all to a single name would be good.

> +{
> +	return pwmchip_get_drvdata(chip);
> +}
> +
> +static void ttc_pwm_enable(struct ttc_pwm_priv *priv, struct pwm_device *pwm)
> +{
> +	u32 ctrl_reg;
> +
> +	ctrl_reg = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= (TTC_CNTR_CTRL_INTR_MODE_EN
> +				 | TTC_CNTR_CTRL_MATCH_MODE_EN | TTC_CNTR_CTRL_RST);
> +	ctrl_reg &= ~(TTC_CNTR_CTRL_DIS | TTC_CNTR_CTRL_WAVE_EN);
> +	ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl_reg);
> +}
> +
> +static void ttc_pwm_disable(struct ttc_pwm_priv *priv, struct pwm_device *pwm)

This function only needs .hwpwm from *pwm. Maybe pass hwpwm as parameter
instead of pwm?

> +{
> +	u32 ctrl_reg;
> +
> +	ctrl_reg = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= TTC_CNTR_CTRL_DIS;
> +
> +	ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl_reg);
> +}
> +
> +static void ttc_pwm_set_polarity(struct ttc_pwm_priv *priv, struct pwm_device *pwm,
> +				 enum pwm_polarity polarity)
> +{
> +	u32 ctrl_reg;
> +
> +	ctrl_reg = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET);
> +
> +	if (polarity == PWM_POLARITY_NORMAL)
> +		ctrl_reg |= TTC_CNTR_CTRL_WAVE_POL;
> +	else
> +		ctrl_reg &= (~TTC_CNTR_CTRL_WAVE_POL);

The parenthesis can be dropped.

> +
> +	ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl_reg);
> +}
> +
> +static void ttc_pwm_set_counters(struct ttc_pwm_priv *priv,
> +				 struct pwm_device *pwm,
> +				 u32 period_cycles,
> +				 u32 duty_cycles)
> +{
> +	/* Set up period */
> +	ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_INTR_VAL_OFFSET, period_cycles);
> +
> +	/* Set up duty cycle */
> +	ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_MATCH_CNT_VAL_OFFSET, duty_cycles);
> +}
> +
> +static void ttc_pwm_set_prescalar(struct ttc_pwm_priv *priv,
> +				  struct pwm_device *pwm,
> +				  u32 div, bool is_enable)
> +{
> +	u32 clk_reg;
> +
> +	if (is_enable) {
> +		/* Set up prescalar */
> +		clk_reg = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET);
> +		clk_reg &= ~TTC_CLK_CNTRL_PSV_MASK;
> +		clk_reg |= (div << TTC_CNTR_CTRL_PRESCALE_SHIFT);
> +		clk_reg |= TTC_CLK_CNTRL_PS_EN;
> +		ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET, clk_reg);
> +	} else {
> +		/* Disable prescalar */
> +		clk_reg = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET);
> +		clk_reg &= ~TTC_CLK_CNTRL_PS_EN;
> +		ttc_pwm_ch_writel(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET, clk_reg);
> +	}
> +}
> +
> +static int ttc_pwm_apply(struct pwm_chip *chip,
> +			 struct pwm_device *pwm,
> +			 const struct pwm_state *state)
> +{
> +	struct ttc_pwm_priv *priv = xilinx_pwm_chip_to_priv(chip);
> +	u64 duty_cycles, period_cycles;
> +	struct pwm_state cstate;
> +	unsigned long rate;
> +	bool flag = false;
> +	u32 div = 0;
> +
> +	cstate = pwm->state;

A pointer would be enough here. No need to copy the whole struct.

> +	if (state->polarity != cstate.polarity) {
> +		if (cstate.enabled)
> +			ttc_pwm_disable(priv, pwm);
> +
> +		ttc_pwm_set_polarity(priv, pwm, state->polarity);
> +	}
> +
> +	rate = priv->rate;
> +
> +	/* Prevent overflow by limiting to the maximum possible period */
> +	period_cycles = min_t(u64, state->period, ULONG_MAX * NSEC_PER_SEC);

ULONG_MAX * NSEC_PER_SEC overflows before it's casted to u64.

> +	period_cycles = mul_u64_u64_div_u64(period_cycles, rate, NSEC_PER_SEC);

mul_u64_u64_div_u64() doesn't overflow if rate <= NSEC_PER_SEC.

> +	if (period_cycles > priv->max) {
> +		/*
> +		 * Prescale frequency to fit requested period cycles within limit.
> +		 * Prescalar divides input clock by 2^(prescale_value + 1). Maximum
> +		 * supported prescalar value is 15.
> +		 */
> +		div = mul_u64_u64_div_u64(state->period, rate, (NSEC_PER_SEC * priv->max));

No parenthesis needed around the 3rd parameter. Can NSEC_PER_SEC *
priv->max overflow? Is it intended that you use state->period here and
don't cap the value first as you did above?

> +		div = order_base_2(div);
> +		if (div)
> +			div -= 1;
> +
> +		if (div > 15)
> +			return -ERANGE;
> +
> +		rate = DIV_ROUND_CLOSEST(rate, BIT(div + 1));
> +		period_cycles = mul_u64_u64_div_u64(state->period, rate,
> +						    NSEC_PER_SEC);

Dividing twice decreases precision. Also rounding to closest looks
wrong. I think this should just be:

	period_cycles = mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC * BIT(div + 1));

Wouldn't it be simpler to just use:

	dif = order_base_2(period_cycles / priv->max);

(modulo correctness)?

> +		flag = true;
> +	}
> +
> +	if (cstate.enabled)
> +		ttc_pwm_disable(priv, pwm);
> +
> +	duty_cycles = mul_u64_u64_div_u64(state->duty_cycle, rate,
> +					  NSEC_PER_SEC);
> +	ttc_pwm_set_counters(priv, pwm, period_cycles, duty_cycles);
> +
> +	ttc_pwm_set_prescalar(priv, pwm, div, flag);
> +
> +	if (state->enabled)
> +		ttc_pwm_enable(priv, pwm);
> +	else
> +		ttc_pwm_disable(priv, pwm);

The hardware is already disabled, so I'd expect that this
ttc_pwm_disable() can be dropped?

> +	return 0;
> +}
> +
> +static int ttc_pwm_get_state(struct pwm_chip *chip,
> +			     struct pwm_device *pwm,
> +			     struct pwm_state *state)
> +{
> +	struct ttc_pwm_priv *priv = xilinx_pwm_chip_to_priv(chip);
> +	u32 value, pres_en, pres = 1;
> +	unsigned long rate;
> +	u64 tmp;
> +
> +	value = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CNT_CNTRL_OFFSET);
> +
> +	if (value & TTC_CNTR_CTRL_WAVE_POL)
> +		state->polarity = PWM_POLARITY_NORMAL;
> +	else
> +		state->polarity = PWM_POLARITY_INVERSED;
> +
> +	if (value & TTC_CNTR_CTRL_DIS)
> +		state->enabled = false;

You can exit early here.

> +	else
> +		state->enabled = true;
> +
> +	rate = priv->rate;
> +
> +	pres_en = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET);
> +	pres_en	&= TTC_CLK_CNTRL_PS_EN;
> +
> +	if (pres_en) {
> +		pres = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_CLK_CNTRL_OFFSET)
> +					& TTC_CLK_CNTRL_PSV_MASK;
> +		pres >>= TTC_CNTR_CTRL_PRESCALE_SHIFT;

		pres = FIELD_GET(...)

> +		/* If prescale is enabled, the count rate is divided by 2^(pres + 1) */
> +		pres = BIT(pres + 1);
> +	}
> +
> +	tmp = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_INTR_VAL_OFFSET);
> +	tmp *= pres;

you can drop `pres = BIT(pres + 1);` above if you use

	tmp <<= pres + 1

here.

> +	state->period = DIV64_U64_ROUND_UP(tmp * NSEC_PER_SEC, rate);

Can this overflow?

> +	tmp = ttc_pwm_ch_readl(priv, pwm->hwpwm, TTC_MATCH_CNT_VAL_OFFSET);
> +	tmp *= pres;
> +	state->duty_cycle = DIV64_U64_ROUND_UP(tmp * NSEC_PER_SEC, rate);
> +
> +	return 0;
> +}
> +
> +static const struct pwm_ops ttc_pwm_ops = {
> +	.apply = ttc_pwm_apply,
> +	.get_state = ttc_pwm_get_state,
> +};
> +
> +int ttc_pwm_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct ttc_pwm_priv *priv;
> +	struct pwm_chip *chip;
> +	u32 timer_width;
> +	int ret;
> +
> +	ret = of_property_read_u32(np, "timer-width", &timer_width);
> +	if (ret)
> +		timer_width = 16;
> +
> +	chip = devm_pwmchip_alloc(dev, TTC_PWM_MAX_CH, sizeof(*priv));
> +	if (IS_ERR(chip))
> +		return PTR_ERR(chip);
> +
> +	priv = xilinx_pwm_chip_to_priv(chip);
> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	priv->max = BIT(timer_width) - 1;
> +
> +	priv->clk = devm_clk_get_enabled(dev, NULL);
> +	if (IS_ERR(priv->clk)) {
> +		return dev_err_probe(dev, PTR_ERR(priv->clk),
> +				     "ERROR: timer input clock not found\n");
> +	}
> +
> +	priv->rate = clk_get_rate(priv->clk);
> +
> +	clk_rate_exclusive_get(priv->clk);

Only call clk_get_rate() after clk_rate_exclusive_get(). Also note there
is a devm variant of clk_rate_exclusive_get().

> +	chip->ops = &ttc_pwm_ops;
> +	chip->npwm = TTC_PWM_MAX_CH;
> +
> +	ret = devm_pwmchip_add(dev, chip);
> +	if (ret) {
> +		clk_rate_exclusive_put(priv->clk);
> +		return dev_err_probe(dev, ret, "Could not register PWM chip\n");
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(ttc_pwm_probe);

Putting these functions in a name space would be great.

> +void ttc_pwm_remove(struct platform_device *pdev)
> +{
> +	struct ttc_pwm_priv *priv = platform_get_drvdata(pdev);
> +
> +	pwmchip_remove(&priv->chip);
> +	clk_rate_exclusive_put(priv->clk);
> +}

Did you test the remove path? Hint: Don't call pwmchip_remove() if you
registered the chip using devm_pwmchip_add() and priv->chip is
uninitialized.

> +EXPORT_SYMBOL_GPL(ttc_pwm_remove);
> +
> +MODULE_AUTHOR("Mubin Sayyed <mubin.sayyed at amd.com>");
> +MODULE_DESCRIPTION("Cadence TTC PWM driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/timer-cadence-ttc.h b/include/linux/timer-cadence-ttc.h
> index d938991371e5..6b6135d0ba0c 100644
> --- a/include/linux/timer-cadence-ttc.h
> +++ b/include/linux/timer-cadence-ttc.h
> @@ -12,13 +12,14 @@
>  #define TTC_CNT_CNTRL_OFFSET            0x0C /* Counter Control Reg, RW */
>  #define TTC_COUNT_VAL_OFFSET            0x18 /* Counter Value Reg, RO */
>  #define TTC_INTR_VAL_OFFSET             0x24 /* Interval Count Reg, RW */
> +#define TTC_MATCH_CNT_VAL_OFFSET        0x30 /* Match Count Reg, RW */

I assume all these constants are register addresses. I'd drop _OFFSET
here. If you want a designator for these, I'd suggest REG or ADDR, but
IMHO plain TTC_MATCH_CNT_VAL is fine.

>  #define TTC_ISR_OFFSET          0x54 /* Interrupt Status Reg, RO */
>  #define TTC_IER_OFFSET          0x60 /* Interrupt Enable Reg, RW */
>  
>  #define TTC_CNT_CNTRL_DISABLE_MASK      0x1
>  
>  #define TTC_CLK_CNTRL_CSRC_MASK         (1 << 5)        /* clock source */
> -#define TTC_CLK_CNTRL_PSV_MASK          0x1e
> +#define TTC_CLK_CNTRL_PSV_MASK		0x1e
>  #define TTC_CLK_CNTRL_PSV_SHIFT         1
>  
>  /*
> @@ -33,3 +34,22 @@
>  
>  #define MAX_F_ERR 50
>  
> +#define TTC_PWM_CHANNEL         0x4

That define is misnamed IMHO. That's the offset between register ranges
for different channels. *Here* _OFFSET is fine.

> +
> +#define TTC_CLK_CNTRL_CSRC              BIT(5)
> +#define TTC_CLK_CNTRL_PS_EN             BIT(0)
> +#define TTC_CNTR_CTRL_DIS               BIT(0)
> +#define TTC_CNTR_CTRL_INTR_MODE_EN      BIT(1)
> +#define TTC_CNTR_CTRL_MATCH_MODE_EN     BIT(3)
> +#define TTC_CNTR_CTRL_RST               BIT(4)
> +#define TTC_CNTR_CTRL_WAVE_EN   BIT(5)
> +#define TTC_CNTR_CTRL_WAVE_POL  BIT(6)
> +#define TTC_CNTR_CTRL_WAVE_POL_SHIFT    6
> +#define TTC_CNTR_CTRL_PRESCALE_SHIFT    1
> +#define TTC_PWM_MAX_CH	3
> +
> +#if defined(CONFIG_PWM_CADENCE)
> +int ttc_pwm_probe(struct platform_device *pdev);
> +void ttc_pwm_remove(struct platform_device *pdev);
> +#endif

No need for the ifdef.

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/8a60cb49/attachment.sig>

From ukleinek at kernel.org  Mon Mar 24 04:40:39 2025
From: ukleinek at kernel.org (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Mon, 24 Mar 2025 12:40:39 +0100
Subject: [PATCH v4 2/3] clocksource: timer-cadence-ttc: Support TTC
 device configured as PWM
In-Reply-To: <20250115113556.2832282-3-mubin.sayyed@amd.com>
References: <20250115113556.2832282-1-mubin.sayyed@amd.com>
 <20250115113556.2832282-3-mubin.sayyed@amd.com>
Message-ID: <hwnhz4yr6vzz3oav4gq7qptejjy3rdwff7iveawaxexf3tbngr@pnrxi6jkpw3k>

On Wed, Jan 15, 2025 at 05:05:55PM +0530, Mubin Sayyed wrote:
> TTC device can act either as clocksource/clockevent or PWM generator,
> it would be decided by pwm-cells property. If pwm-cells property is
> present in TTC node, it would be treated as PWM device, and clocksource
> driver just calls probe function for PWM functionality, so that TTC
> device would be registered with PWM framework.
> 
> Signed-off-by: Mubin Sayyed <mubin.sayyed at amd.com>
> ---
> Changes for v4:
>     - In case of pwm-cells property call probe function for PWM
>       feature instead of returning error.
> Changes for v3:
>     - None
> Changes for v2:
>     - Added comment regarding pwm-cells property
> ---
>  drivers/clocksource/timer-cadence-ttc.c | 34 +++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
> index 2f33d4c40153..c5ecad9332c9 100644
> --- a/drivers/clocksource/timer-cadence-ttc.c
> +++ b/drivers/clocksource/timer-cadence-ttc.c
> @@ -35,6 +35,10 @@
>   * obtained from device tree. The pre-scaler of 32 is used.
>   */
>  
> +struct ttc_timer_config {
> +	bool is_pwm_mode;
> +};
> +
>  /**
>   * struct ttc_timer - This definition defines local timer structure
>   *
> @@ -453,6 +457,7 @@ static int __init ttc_setup_clockevent(struct clk *clk,
>  
>  static int __init ttc_timer_probe(struct platform_device *pdev)
>  {
> +	struct ttc_timer_config *ttc_config;
>  	unsigned int irq;
>  	void __iomem *timer_baseaddr;
>  	struct clk *clk_cs, *clk_ce;
> @@ -461,6 +466,24 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
>  	u32 timer_width = 16;
>  	struct device_node *timer = pdev->dev.of_node;
>  
> +	ttc_config = devm_kzalloc(&pdev->dev, sizeof(*ttc_config), GFP_KERNEL);
> +	if (!ttc_config)
> +		return -ENOMEM;
> +
> +	/*
> +	 * If pwm-cells property is present in TTC node,
> +	 * it would be treated as PWM device.
> +	 */
> +	if (of_property_read_bool(timer, "#pwm-cells")) {
> +		#if defined(CONFIG_PWM_CADENCE)
> +		ttc_config->is_pwm_mode = true;
> +			return ttc_pwm_probe(pdev);

strange indention. Maybe use

	if (IS_REACHABLE(CONFIG_PWM_CADENCE))

This is an unusal way to bind the PWM driver. I'd prefer creation of separate
device in the PWM case. I wonder if it can happen that ttc_pwm_probe() is
called during boot before pwm_init() completed. Or use an auxbus device
to distinguish between timer and pwm?

> +		#else
> +			return -ENODEV;
> +		#endif
> +	}
> +	dev_set_drvdata(&pdev->dev, ttc_config);
> +
>  	if (initialized)
>  		return 0;
>  

Best regards
Uwe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20250324/17d1804d/attachment.sig>

From o451686892 at gmail.com  Mon Mar 24 04:44:16 2025
From: o451686892 at gmail.com (Weizhao Ouyang)
Date: Mon, 24 Mar 2025 19:44:16 +0800
Subject: [PATCH] can: rockchip_canfd: fix broken quirks checks
Message-ID: <20250324114416.10160-1-o451686892@gmail.com>

First get the devtype_data then check quirks.

Fixes: bbdffb341498 ("can: rockchip_canfd: add quirk for broken CAN-FD support")
Signed-off-by: Weizhao Ouyang <o451686892 at gmail.com>
---
 drivers/net/can/rockchip/rockchip_canfd-core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index d9a937ba126c..ac514766d431 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -907,15 +907,16 @@ static int rkcanfd_probe(struct platform_device *pdev)
 	priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 		CAN_CTRLMODE_BERR_REPORTING;
-	if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_CANFD_BROKEN))
-		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
 	priv->can.do_set_mode = rkcanfd_set_mode;
 	priv->can.do_get_berr_counter = rkcanfd_get_berr_counter;
 	priv->ndev = ndev;
 
 	match = device_get_match_data(&pdev->dev);
-	if (match)
+	if (match) {
 		priv->devtype_data = *(struct rkcanfd_devtype_data *)match;
+		if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_CANFD_BROKEN))
+			priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
+	}
 
 	err = can_rx_offload_add_manual(ndev, &priv->offload,
 					RKCANFD_NAPI_WEIGHT);
-- 
2.45.2



From Jonathan.Cameron at huawei.com  Mon Mar 24 05:00:40 2025
From: Jonathan.Cameron at huawei.com (Jonathan Cameron)
Date: Mon, 24 Mar 2025 12:00:40 +0000
Subject: [RFC PATCH 0/6] Cache coherency management subsystem
In-Reply-To: <20250321-failing-squatted-37a88909bde2@spud>
References: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>
	<20250321-failing-squatted-37a88909bde2@spud>
Message-ID: <20250324120040.00003d95@huawei.com>

On Fri, 21 Mar 2025 22:32:15 +0000
Conor Dooley <conor at kernel.org> wrote:

> On Thu, Mar 20, 2025 at 05:41:12PM +0000, Jonathan Cameron wrote:
> > Note that I've only a vague idea of who will care about this
> > so please do +CC others as needed.
> > 
> > On x86 there is the much loved WBINVD instruction that causes a write back
> > and invalidate of all caches in the system. It is expensive but it is
> > necessary in a few corner cases. These are cases where the contents of
> > Physical Memory may change without any writes from the host. Whilst there
> > are a few reasons this might happen, the one I care about here is when
> > we are adding or removing mappings on CXL. So typically going from
> > there being actual memory at a host Physical Address to nothing there
> > (reads as zero, writes dropped) or visa-versa. That involves the
> > reprogramming of address decoders (HDM Decoders); in the near future
> > it may also include the device offering dynamic capacity extents. The
> > thing that makes it very hard to handle with CPU flushes is that the
> > instructions are normally VA based and not guaranteed to reach beyond
> > the Point of Coherence or similar. You might be able to (ab)use
> > various flush operations intended to ensure persistence memory but
> > in general they don't work either.
> > 
> > So on other architectures such as ARM64 we have no instruction similar to
> > WBINVD but we may have device interfaces in the system that provide a way
> > to ensure a PA range undergoes the write back and invalidate action. This
> > RFC is to find a way to support those cache maintenance device interfaces.
> > The ones I know about are much more flexible than WBINVD, allowing
> > invalidation of particular PA ranges, or a much richer set of flush types
> > (not supported yet as not needed for upstream use cases).
> > 
> > To illustrate how a solution might work, I've taken both a HiSilicon
> > design (slight quirk as registers overlap with existing PMU driver)
> > and more controversially a firmware interface proposal from ARM
> > (wrapped up in made up ACPI) that was dropped from the released spec
> > but for which the alpha spec is still available.
> > 
> > Why drivers/cache?
> > - Mainly because it exists and smells like a reasonable place.
> > - Conor, you are maintainer for this currently do you mind us putting this
> >   stuff in there?  
> 
> drivers/cache was just something to put the cache controller drivers we
> have on RISC-V that implement the various arch_dma*() callbacks in
> non-standard ways that made more sense than drivers/soc/<soc vendor>
> since the controllers are IP provided by CPU vendors. There's only
> two drivers here now, but I am aware of another two non-standard CMO
> mechanisms if the silicon with them so there'll likely be more in the
> future :) I'm only really maintainer of it to avoid it being another
> thing for Palmer to look after :)

I suspected as much :)

> 
> I've only skimmed this for now, but I think it is reasonable to put them
> here. Maybe my skim is showing, but it would not surprise me to see a
> driver providing both non-standard arch_dma*() callbacks as well as
> dealing with CXL mappings via this new class on RISC-V in the future..

Absolutely.  The use of an ARM callback was just a place holder for now
(Greg pointed that one out as well as I forgot to mention it in the patch
description!)

I think this will turn out to be at least some subset of implementations
for other architectures unless they decide to go the route of an instruction
(like x86).

> Either way, I think it'd probably be a good idea to add ?you? as a
> co-maintainer if the directory is going to be used for your proposed
> interface/drivers, for what I hope is an obvious reason!

Sure.  That would make sense.

Jonathan
> 



From tudor.ambarus at linaro.org  Mon Mar 24 05:35:41 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 24 Mar 2025 12:35:41 +0000
Subject: [PATCH] firmware: exynos-acpm: check saved RX before bailing out
 on empty RX queue
Message-ID: <20250324-acpm-drained-rx-queue-v1-1-577774335151@linaro.org>

When we're polling for responses and get a response that corresponds to
another request, we save the RX data in order to drain the RX queue.

If the response for the current request is not found in the request's
iteration of the queue, or if the queue is empty, we must check whether
the RX data was saved by a previous request when it drained the RX queue.

We failed to check for already saved responses when the queue was empty,
and requests could time out. Check saved RX before bailing out on empty
RX queue.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Reported-by: Andr? Draszik <andre.draszik at linaro.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus at linaro.org>
---
on top of krzk/for-next
---
 drivers/firmware/samsung/exynos-acpm.c | 44 +++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..15e991b99f5a384a299c1baf6b279fc93244bcf2 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -184,6 +184,29 @@ struct acpm_match_data {
 #define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl)
 #define handle_to_acpm_info(h) container_of(h, struct acpm_info, handle)
 
+/**
+ * acpm_get_saved_rx() - get the response if it was already saved.
+ * @achan:	ACPM channel info.
+ * @xfer:	reference to the transfer to get response for.
+ * @tx_seqnum:	xfer TX sequence number.
+ */
+static void acpm_get_saved_rx(struct acpm_chan *achan,
+			      const struct acpm_xfer *xfer, u32 tx_seqnum)
+{
+	const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
+	u32 rx_seqnum;
+
+	if (!rx_data->response)
+		return;
+
+	rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
+
+	if (rx_seqnum == tx_seqnum) {
+		memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
+		clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
+	}
+}
+
 /**
  * acpm_get_rx() - get response from RX queue.
  * @achan:	ACPM channel info.
@@ -204,15 +227,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
 	rx_front = readl(achan->rx.front);
 	i = readl(achan->rx.rear);
 
-	/* Bail out if RX is empty. */
-	if (i == rx_front)
+	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
+
+	if (i == rx_front) {
+		acpm_get_saved_rx(achan, xfer, tx_seqnum);
 		return 0;
+	}
 
 	base = achan->rx.base;
 	mlen = achan->mlen;
 
-	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
-
 	/* Drain RX queue. */
 	do {
 		/* Read RX seqnum. */
@@ -259,16 +283,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
 	 * If the response was not in this iteration of the queue, check if the
 	 * RX data was previously saved.
 	 */
-	rx_data = &achan->rx_data[tx_seqnum - 1];
-	if (!rx_set && rx_data->response) {
-		rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM,
-				      rx_data->cmd[0]);
-
-		if (rx_seqnum == tx_seqnum) {
-			memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
-			clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
-		}
-	}
+	if (!rx_set)
+		acpm_get_saved_rx(achan, xfer, tx_seqnum);
 
 	return 0;
 }

---
base-commit: f0dbe0d40d08199109cb689849877694a8b91033
change-id: 20250324-acpm-drained-rx-queue-ec316d4cbcdf

Best regards,
-- 
Tudor Ambarus <tudor.ambarus at linaro.org>



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:51:04 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:51:04 +0100
Subject: [PATCH 1/2] dt-bindings: pinctrl: mediatek: Drop unrelated nodes from DTS example
Message-ID: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>

Binding example should not contain other nodes, e.g. consumers of
pinctrl of, because this is completely redundant and adds unnecessary
bloat.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml      | 10 ----------
 .../bindings/pinctrl/mediatek,mt6779-pinctrl.yaml      |  5 -----
 2 files changed, 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
index bccff08a5ba3..5f2808212f39 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
@@ -136,16 +136,6 @@ examples:
         #address-cells = <2>;
         #size-cells = <2>;
 
-        syscfg_pctl_a: syscfg-pctl-a at 10005000 {
-          compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
-          reg = <0 0x10005000 0 0x1000>;
-        };
-
-        syscfg_pctl_b: syscfg-pctl-b at 1020c020 {
-          compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
-          reg = <0 0x1020C020 0 0x1000>;
-        };
-
         pinctrl at 1c20800 {
           compatible = "mediatek,mt8135-pinctrl";
           reg = <0 0x1000B000 0 0x1000>;
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
index 3bbc00df5548..f4bab7a132d3 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
@@ -245,9 +245,4 @@ examples:
                 };
             };
         };
-
-        mmc0 {
-           pinctrl-0 = <&mmc0_pins_default>;
-           pinctrl-names = "default";
-        };
     };
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:51:05 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:51:05 +0100
Subject: [PATCH 2/2] dt-bindings: pinctrl: mediatek: Correct indentation and style in DTS example
In-Reply-To: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>
References: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250324125105.81774-2-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../pinctrl/mediatek,mt65xx-pinctrl.yaml      | 83 +++++++------------
 .../pinctrl/mediatek,mt7622-pinctrl.yaml      | 48 +++++------
 .../pinctrl/mediatek,mt8183-pinctrl.yaml      | 68 +++++++--------
 .../pinctrl/mediatek,mt8192-pinctrl.yaml      | 76 ++++++++---------
 4 files changed, 127 insertions(+), 148 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
index 5f2808212f39..b9680b896f12 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
@@ -137,64 +137,43 @@ examples:
         #size-cells = <2>;
 
         pinctrl at 1c20800 {
-          compatible = "mediatek,mt8135-pinctrl";
-          reg = <0 0x1000B000 0 0x1000>;
-          mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
-          gpio-controller;
-          #gpio-cells = <2>;
-          interrupt-controller;
-          #interrupt-cells = <2>;
-          interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
-              <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
-              <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+            compatible = "mediatek,mt8135-pinctrl";
+            reg = <0 0x1000B000 0 0x1000>;
+            mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+            interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 
-          i2c0_pins_a: i2c0-pins {
-            pins1 {
-              pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
-                <MT8135_PIN_101_SCL0__FUNC_SCL0>;
-              bias-disable;
-            };
-          };
-
-          i2c1_pins_a: i2c1-pins {
-            pins {
-              pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
-                <MT8135_PIN_196_SCL1__FUNC_SCL1>;
-              bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
-            };
-          };
-
-          i2c2_pins_a: i2c2-pins {
-            pins1 {
-              pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
-              bias-pull-down;
+            i2c0_pins_a: i2c0-pins {
+                pins1 {
+                    pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
+                             <MT8135_PIN_101_SCL0__FUNC_SCL0>;
+                    bias-disable;
+                };
             };
 
-            pins2 {
-              pinmux = <MT8135_PIN_49_WATCHDOG__FUNC_GPIO49>;
-              bias-pull-up;
-            };
-          };
-
-          i2c3_pins_a: i2c3-pins {
-            pins1 {
-              pinmux = <MT8135_PIN_40_DAC_CLK__FUNC_GPIO40>,
-                <MT8135_PIN_41_DAC_WS__FUNC_GPIO41>;
-              bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+            i2c1_pins_a: i2c1-pins {
+                pins {
+                    pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
+                             <MT8135_PIN_196_SCL1__FUNC_SCL1>;
+                    bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+                };
             };
 
-            pins2 {
-              pinmux = <MT8135_PIN_35_SCL3__FUNC_SCL3>,
-                <MT8135_PIN_36_SDA3__FUNC_SDA3>;
-              output-low;
-              bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
-            };
+            i2c2_pins_a: i2c2-pins {
+                pins1 {
+                    pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
+                    bias-pull-down;
+                };
 
-            pins3 {
-              pinmux = <MT8135_PIN_57_JTCK__FUNC_GPIO57>,
-                <MT8135_PIN_60_JTDI__FUNC_JTDI>;
-              drive-strength = <32>;
+                pins2 {
+                    pinmux = <MT8135_PIN_49_WATCHDOG__FUNC_GPIO49>;
+                    bias-pull-up;
+                };
             };
-          };
         };
     };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
index d74cae9d4d65..9acca85184fa 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
@@ -366,34 +366,34 @@ examples:
         #size-cells = <2>;
 
         pio: pinctrl at 10211000 {
-          compatible = "mediatek,mt7622-pinctrl";
-          reg = <0 0x10211000 0 0x1000>;
-          gpio-controller;
-          #gpio-cells = <2>;
+            compatible = "mediatek,mt7622-pinctrl";
+            reg = <0 0x10211000 0 0x1000>;
+            gpio-controller;
+            #gpio-cells = <2>;
 
-          pinctrl_eth_default: eth-pins {
-            mux-mdio {
-              groups = "mdc_mdio";
-              function = "eth";
-              drive-strength = <12>;
-            };
+            pinctrl_eth_default: eth-pins {
+                mux-mdio {
+                    groups = "mdc_mdio";
+                    function = "eth";
+                    drive-strength = <12>;
+                };
 
-            mux-gmac2 {
-              groups = "rgmii_via_gmac2";
-              function = "eth";
-              drive-strength = <12>;
-            };
+                mux-gmac2 {
+                    groups = "rgmii_via_gmac2";
+                    function = "eth";
+                    drive-strength = <12>;
+                };
 
-            mux-esw {
-              groups = "esw";
-              function = "eth";
-              drive-strength = <8>;
-            };
+                mux-esw {
+                    groups = "esw";
+                    function = "eth";
+                    drive-strength = <8>;
+                };
 
-            conf-mdio {
-              pins = "MDC";
-              bias-pull-up;
+                conf-mdio {
+                    pins = "MDC";
+                    bias-pull-up;
+                };
             };
-          };
         };
     };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
index 8507bd15f243..464879274cae 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
@@ -195,43 +195,43 @@ examples:
         #size-cells = <2>;
 
         pio: pinctrl at 10005000 {
-          compatible = "mediatek,mt8183-pinctrl";
-          reg = <0 0x10005000 0 0x1000>,
-                <0 0x11f20000 0 0x1000>,
-                <0 0x11e80000 0 0x1000>,
-                <0 0x11e70000 0 0x1000>,
-                <0 0x11e90000 0 0x1000>,
-                <0 0x11d30000 0 0x1000>,
-                <0 0x11d20000 0 0x1000>,
-                <0 0x11c50000 0 0x1000>,
-                <0 0x11f30000 0 0x1000>,
-                <0 0x1000b000 0 0x1000>;
-          reg-names = "iocfg0", "iocfg1", "iocfg2",
-                "iocfg3", "iocfg4", "iocfg5",
-                "iocfg6", "iocfg7", "iocfg8",
-                "eint";
-          gpio-controller;
-          #gpio-cells = <2>;
-          gpio-ranges = <&pio 0 0 192>;
-          interrupt-controller;
-          interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
-          #interrupt-cells = <2>;
+            compatible = "mediatek,mt8183-pinctrl";
+            reg = <0 0x10005000 0 0x1000>,
+                  <0 0x11f20000 0 0x1000>,
+                  <0 0x11e80000 0 0x1000>,
+                  <0 0x11e70000 0 0x1000>,
+                  <0 0x11e90000 0 0x1000>,
+                  <0 0x11d30000 0 0x1000>,
+                  <0 0x11d20000 0 0x1000>,
+                  <0 0x11c50000 0 0x1000>,
+                  <0 0x11f30000 0 0x1000>,
+                  <0 0x1000b000 0 0x1000>;
+            reg-names = "iocfg0", "iocfg1", "iocfg2",
+                  "iocfg3", "iocfg4", "iocfg5",
+                  "iocfg6", "iocfg7", "iocfg8",
+                  "eint";
+            gpio-controller;
+            #gpio-cells = <2>;
+            gpio-ranges = <&pio 0 0 192>;
+            interrupt-controller;
+            interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+            #interrupt-cells = <2>;
 
-          i2c0_pins_a: i2c0-pins {
-            pins1 {
-              pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
-                <PINMUX_GPIO49__FUNC_SDA5>;
-              mediatek,pull-up-adv = <3>;
-              drive-strength-microamp = <1000>;
+            i2c0_pins_a: i2c0-pins {
+                pins1 {
+                  pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
+                           <PINMUX_GPIO49__FUNC_SDA5>;
+                    mediatek,pull-up-adv = <3>;
+                    drive-strength-microamp = <1000>;
+                };
             };
-          };
 
-          i2c1_pins_a: i2c1-pins {
-            pins {
-              pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
-                <PINMUX_GPIO51__FUNC_SDA3>;
-              mediatek,pull-down-adv = <2>;
+            i2c1_pins_a: i2c1-pins {
+                pins {
+                    pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
+                             <PINMUX_GPIO51__FUNC_SDA3>;
+                    mediatek,pull-down-adv = <2>;
+                };
             };
-          };
         };
     };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8192-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8192-pinctrl.yaml
index 1686427eb854..949dcd6fd847 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8192-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8192-pinctrl.yaml
@@ -142,43 +142,43 @@ additionalProperties: false
 
 examples:
   - |
-            #include <dt-bindings/pinctrl/mt8192-pinfunc.h>
-            #include <dt-bindings/interrupt-controller/arm-gic.h>
-            pio: pinctrl at 10005000 {
-                    compatible = "mediatek,mt8192-pinctrl";
-                    reg = <0x10005000 0x1000>,
-                          <0x11c20000 0x1000>,
-                          <0x11d10000 0x1000>,
-                          <0x11d30000 0x1000>,
-                          <0x11d40000 0x1000>,
-                          <0x11e20000 0x1000>,
-                          <0x11e70000 0x1000>,
-                          <0x11ea0000 0x1000>,
-                          <0x11f20000 0x1000>,
-                          <0x11f30000 0x1000>,
-                          <0x1000b000 0x1000>;
-                    reg-names = "iocfg0", "iocfg_rm", "iocfg_bm",
-                          "iocfg_bl", "iocfg_br", "iocfg_lm",
-                          "iocfg_lb", "iocfg_rt", "iocfg_lt",
-                          "iocfg_tl", "eint";
-                    gpio-controller;
-                    #gpio-cells = <2>;
-                    gpio-ranges = <&pio 0 0 220>;
-                    interrupt-controller;
-                    interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH 0>;
-                    #interrupt-cells = <2>;
+    #include <dt-bindings/pinctrl/mt8192-pinfunc.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    pio: pinctrl at 10005000 {
+        compatible = "mediatek,mt8192-pinctrl";
+        reg = <0x10005000 0x1000>,
+              <0x11c20000 0x1000>,
+              <0x11d10000 0x1000>,
+              <0x11d30000 0x1000>,
+              <0x11d40000 0x1000>,
+              <0x11e20000 0x1000>,
+              <0x11e70000 0x1000>,
+              <0x11ea0000 0x1000>,
+              <0x11f20000 0x1000>,
+              <0x11f30000 0x1000>,
+              <0x1000b000 0x1000>;
+        reg-names = "iocfg0", "iocfg_rm", "iocfg_bm",
+              "iocfg_bl", "iocfg_br", "iocfg_lm",
+              "iocfg_lb", "iocfg_rt", "iocfg_lt",
+              "iocfg_tl", "eint";
+        gpio-controller;
+        #gpio-cells = <2>;
+        gpio-ranges = <&pio 0 0 220>;
+        interrupt-controller;
+        interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH 0>;
+        #interrupt-cells = <2>;
 
-                    spi1-default-pins {
-                            pins-cs-mosi-clk {
-                                    pinmux = <PINMUX_GPIO157__FUNC_SPI1_A_CSB>,
-                                             <PINMUX_GPIO159__FUNC_SPI1_A_MO>,
-                                             <PINMUX_GPIO156__FUNC_SPI1_A_CLK>;
-                                    bias-disable;
-                            };
-
-                            pins-miso {
-                                    pinmux = <PINMUX_GPIO158__FUNC_SPI1_A_MI>;
-                                    bias-pull-down;
-                            };
-                    };
+        spi1-default-pins {
+            pins-cs-mosi-clk {
+                pinmux = <PINMUX_GPIO157__FUNC_SPI1_A_CSB>,
+                         <PINMUX_GPIO159__FUNC_SPI1_A_MO>,
+                         <PINMUX_GPIO156__FUNC_SPI1_A_CLK>;
+                bias-disable;
             };
+
+            pins-miso {
+                pinmux = <PINMUX_GPIO158__FUNC_SPI1_A_MI>;
+                bias-pull-down;
+            };
+        };
+    };
-- 
2.43.0



From tudor.ambarus at linaro.org  Mon Mar 24 05:52:01 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 24 Mar 2025 12:52:01 +0000
Subject: [PATCH 1/2] firmware: exynos-acpm: use ktime APIs for timeout
 detection
In-Reply-To: <20250321-acpm-atomic-v1-1-fb887bde7e61@linaro.org>
References: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
 <20250321-acpm-atomic-v1-1-fb887bde7e61@linaro.org>
Message-ID: <ed56c2eb-5bd7-49cf-bf2c-5826e3c42077@linaro.org>



On 3/21/25 4:40 PM, Andr? Draszik wrote:
> acpm_dequeue_by_polling() uses a loop counter and assumes that each
> iteration of the loop takes 20us. It may take longer, though, because
> usleep_range() may sleep a different amount.
> 
> Switch to using ktime_get() / ktime_after() to detect the timeout
> condition more reliably.
> 
> This change also makes the code easier to follow and it allows us to
> adjust the sleep without having to adjust the loop counter exit
> condition. This will come in useful in a follow-up patch that changes
> the delays.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  drivers/firmware/samsung/exynos-acpm.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..d7ed6b77a957af5db5beba7deecce13ac7b30fd2 100644
> --- a/drivers/firmware/samsung/exynos-acpm.c
> +++ b/drivers/firmware/samsung/exynos-acpm.c
> @@ -32,8 +32,7 @@
>  
>  #define ACPM_PROTOCOL_SEQNUM		GENMASK(21, 16)
>  
> -/* The unit of counter is 20 us. 5000 * 20 = 100 ms */
> -#define ACPM_POLL_TIMEOUT		5000
> +#define ACPM_POLL_TIMEOUT_US		(100 * USEC_PER_MSEC)
>  #define ACPM_TX_TIMEOUT_US		500000
>  
>  #define ACPM_GS101_INITDATA_BASE	0xa000
> @@ -284,12 +283,13 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
>  				   const struct acpm_xfer *xfer)
>  {
>  	struct device *dev = achan->acpm->dev;
> -	unsigned int cnt_20us = 0;
> +	ktime_t timeout;

#include <linux/ktime.h>

>  	u32 seqnum;
>  	int ret;
>  
>  	seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
>  
> +	timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
>  	do {
>  		ret = acpm_get_rx(achan, xfer);
>  		if (ret)
> @@ -300,11 +300,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
>  
>  		/* Determined experimentally. */
>  		usleep_range(20, 30);
> -		cnt_20us++;
> -	} while (cnt_20us < ACPM_POLL_TIMEOUT);
> +	} while (!ktime_after(ktime_get(), timeout));

ktime_before()

With these addressed:
Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>


From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:52:01 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:52:01 +0100
Subject: [PATCH 1/2] dt-bindings: PCI: Correct indentation and style in DTS example
Message-ID: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/pci/brcm,stb-pcie.yaml           |  81 +++++++------
 .../bindings/pci/cdns,cdns-pcie-ep.yaml       |  16 +--
 .../bindings/pci/intel,keembay-pcie-ep.yaml   |  26 ++--
 .../bindings/pci/intel,keembay-pcie.yaml      |  38 +++---
 .../bindings/pci/microchip,pcie-host.yaml     |  54 ++++-----
 .../devicetree/bindings/pci/rcar-pci-ep.yaml  |  34 +++---
 .../bindings/pci/rcar-pci-host.yaml           |  46 +++----
 .../bindings/pci/xilinx-versal-cpm.yaml       | 112 +++++++++---------
 8 files changed, 202 insertions(+), 205 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
index 29f0e1eb5096..c4f9674e8695 100644
--- a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
@@ -186,49 +186,48 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
     scb {
-            #address-cells = <2>;
-            #size-cells = <1>;
-            pcie0: pcie at 7d500000 {
-                    compatible = "brcm,bcm2711-pcie";
-                    reg = <0x0 0x7d500000 0x9310>;
-                    device_type = "pci";
-                    #address-cells = <3>;
-                    #size-cells = <2>;
-                    #interrupt-cells = <1>;
-                    interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
-                                 <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
-                    interrupt-names = "pcie", "msi";
-                    interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                    interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH
-                                     0 0 0 2 &gicv2 GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH
-                                     0 0 0 3 &gicv2 GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH
-                                     0 0 0 4 &gicv2 GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+        #address-cells = <2>;
+        #size-cells = <1>;
+        pcie0: pcie at 7d500000 {
+            compatible = "brcm,bcm2711-pcie";
+            reg = <0x0 0x7d500000 0x9310>;
+            device_type = "pci";
+            #address-cells = <3>;
+            #size-cells = <2>;
+            #interrupt-cells = <1>;
+            interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "pcie", "msi";
+            interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+            interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH
+                             0 0 0 2 &gicv2 GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH
+                             0 0 0 3 &gicv2 GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH
+                             0 0 0 4 &gicv2 GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
 
-                    msi-parent = <&pcie0>;
-                    msi-controller;
-                    ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
-                    dma-ranges = <0x42000000 0x1 0x00000000 0x0 0x40000000 0x0 0x80000000>,
-                                 <0x42000000 0x1 0x80000000 0x3 0x00000000 0x0 0x80000000>;
-                    brcm,enable-ssc;
-                    brcm,scb-sizes =  <0x0000000080000000 0x0000000080000000>;
+            msi-parent = <&pcie0>;
+            msi-controller;
+            ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
+            dma-ranges = <0x42000000 0x1 0x00000000 0x0 0x40000000 0x0 0x80000000>,
+                         <0x42000000 0x1 0x80000000 0x3 0x00000000 0x0 0x80000000>;
+            brcm,enable-ssc;
+            brcm,scb-sizes =  <0x0000000080000000 0x0000000080000000>;
 
-                    /* PCIe bridge, Root Port */
-                    pci at 0,0 {
-                            #address-cells = <3>;
-                            #size-cells = <2>;
-                            reg = <0x0 0x0 0x0 0x0 0x0>;
-                            compatible = "pciclass,0604";
-                            device_type = "pci";
-                            vpcie3v3-supply = <&vreg7>;
-                            ranges;
+            /* PCIe bridge, Root Port */
+            pci at 0,0 {
+                #address-cells = <3>;
+                #size-cells = <2>;
+                reg = <0x0 0x0 0x0 0x0 0x0>;
+                compatible = "pciclass,0604";
+                device_type = "pci";
+                vpcie3v3-supply = <&vreg7>;
+                ranges;
 
-                            /* PCIe endpoint */
-                            pci-ep at 0,0 {
-                                    assigned-addresses =
-                                        <0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>;
-                                    reg = <0x0 0x0 0x0 0x0 0x0>;
-                                    compatible = "pci14e4,1688";
-                            };
-                    };
+                /* PCIe endpoint */
+                pci-ep at 0,0 {
+                    assigned-addresses = <0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>;
+                    reg = <0x0 0x0 0x0 0x0 0x0>;
+                    compatible = "pci14e4,1688";
+                };
             };
+        };
     };
diff --git a/Documentation/devicetree/bindings/pci/cdns,cdns-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/cdns,cdns-pcie-ep.yaml
index 98651ab22103..8735293962ee 100644
--- a/Documentation/devicetree/bindings/pci/cdns,cdns-pcie-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/cdns,cdns-pcie-ep.yaml
@@ -37,14 +37,14 @@ examples:
         #size-cells = <2>;
 
         pcie-ep at fc000000 {
-                compatible = "cdns,cdns-pcie-ep";
-                reg = <0x0 0xfc000000 0x0 0x01000000>,
-                      <0x0 0x80000000 0x0 0x40000000>;
-                reg-names = "reg", "mem";
-                cdns,max-outbound-regions = <16>;
-                max-functions = /bits/ 8 <8>;
-                phys = <&pcie_phy0>;
-                phy-names = "pcie-phy";
+            compatible = "cdns,cdns-pcie-ep";
+            reg = <0x0 0xfc000000 0x0 0x01000000>,
+                  <0x0 0x80000000 0x0 0x40000000>;
+            reg-names = "reg", "mem";
+            cdns,max-outbound-regions = <16>;
+            max-functions = /bits/ 8 <8>;
+            phys = <&pcie_phy0>;
+            phy-names = "pcie-phy";
         };
     };
 ...
diff --git a/Documentation/devicetree/bindings/pci/intel,keembay-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/intel,keembay-pcie-ep.yaml
index 730e63fd7669..b19f61ae72fb 100644
--- a/Documentation/devicetree/bindings/pci/intel,keembay-pcie-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/intel,keembay-pcie-ep.yaml
@@ -53,17 +53,17 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/interrupt-controller/irq.h>
     pcie-ep at 37000000 {
-          compatible = "intel,keembay-pcie-ep";
-          reg = <0x37000000 0x00001000>,
-                <0x37100000 0x00001000>,
-                <0x37300000 0x00001000>,
-                <0x36000000 0x01000000>,
-                <0x37800000 0x00000200>;
-          reg-names = "dbi", "dbi2", "atu", "addr_space", "apb";
-          interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 108 IRQ_TYPE_EDGE_RISING>,
-                       <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-          interrupt-names = "pcie", "pcie_ev", "pcie_err", "pcie_mem_access";
-          num-lanes = <2>;
+        compatible = "intel,keembay-pcie-ep";
+        reg = <0x37000000 0x00001000>,
+              <0x37100000 0x00001000>,
+              <0x37300000 0x00001000>,
+              <0x36000000 0x01000000>,
+              <0x37800000 0x00000200>;
+        reg-names = "dbi", "dbi2", "atu", "addr_space", "apb";
+        interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 108 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-names = "pcie", "pcie_ev", "pcie_err", "pcie_mem_access";
+        num-lanes = <2>;
     };
diff --git a/Documentation/devicetree/bindings/pci/intel,keembay-pcie.yaml b/Documentation/devicetree/bindings/pci/intel,keembay-pcie.yaml
index 1fd557504b10..dd71e3d6bf94 100644
--- a/Documentation/devicetree/bindings/pci/intel,keembay-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/intel,keembay-pcie.yaml
@@ -75,23 +75,23 @@ examples:
     #define KEEM_BAY_A53_PCIE
     #define KEEM_BAY_A53_AUX_PCIE
     pcie at 37000000 {
-          compatible = "intel,keembay-pcie";
-          reg = <0x37000000 0x00001000>,
-                <0x37300000 0x00001000>,
-                <0x36e00000 0x00200000>,
-                <0x37800000 0x00000200>;
-          reg-names = "dbi", "atu", "config", "apb";
-          #address-cells = <3>;
-          #size-cells = <2>;
-          device_type = "pci";
-          ranges = <0x02000000 0 0x36000000 0x36000000 0 0x00e00000>;
-          interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
-          interrupt-names = "pcie", "pcie_ev", "pcie_err";
-          clocks = <&scmi_clk KEEM_BAY_A53_PCIE>,
-                   <&scmi_clk KEEM_BAY_A53_AUX_PCIE>;
-          clock-names = "master", "aux";
-          reset-gpios = <&pca2 9 GPIO_ACTIVE_LOW>;
-          num-lanes = <2>;
+        compatible = "intel,keembay-pcie";
+        reg = <0x37000000 0x00001000>,
+              <0x37300000 0x00001000>,
+              <0x36e00000 0x00200000>,
+              <0x37800000 0x00000200>;
+        reg-names = "dbi", "atu", "config", "apb";
+        #address-cells = <3>;
+        #size-cells = <2>;
+        device_type = "pci";
+        ranges = <0x02000000 0 0x36000000 0x36000000 0 0x00e00000>;
+        interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-names = "pcie", "pcie_ev", "pcie_err";
+        clocks = <&scmi_clk KEEM_BAY_A53_PCIE>,
+                 <&scmi_clk KEEM_BAY_A53_AUX_PCIE>;
+        clock-names = "master", "aux";
+        reset-gpios = <&pca2 9 GPIO_ACTIVE_LOW>;
+        num-lanes = <2>;
     };
diff --git a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
index 103574d18dbc..1aadfdee868f 100644
--- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
@@ -65,33 +65,33 @@ unevaluatedProperties: false
 examples:
   - |
     soc {
-            #address-cells = <2>;
+        #address-cells = <2>;
+        #size-cells = <2>;
+        pcie0: pcie at 2030000000 {
+            compatible = "microchip,pcie-host-1.0";
+            reg = <0x0 0x70000000 0x0 0x08000000>,
+                  <0x0 0x43008000 0x0 0x00002000>,
+                  <0x0 0x4300a000 0x0 0x00002000>;
+            reg-names = "cfg", "bridge", "ctrl";
+            device_type = "pci";
+            #address-cells = <3>;
             #size-cells = <2>;
-            pcie0: pcie at 2030000000 {
-                    compatible = "microchip,pcie-host-1.0";
-                    reg = <0x0 0x70000000 0x0 0x08000000>,
-                          <0x0 0x43008000 0x0 0x00002000>,
-                          <0x0 0x4300a000 0x0 0x00002000>;
-                    reg-names = "cfg", "bridge", "ctrl";
-                    device_type = "pci";
-                    #address-cells = <3>;
-                    #size-cells = <2>;
-                    #interrupt-cells = <1>;
-                    interrupts = <119>;
-                    interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                    interrupt-map = <0 0 0 1 &pcie_intc0 0>,
-                                    <0 0 0 2 &pcie_intc0 1>,
-                                    <0 0 0 3 &pcie_intc0 2>,
-                                    <0 0 0 4 &pcie_intc0 3>;
-                    interrupt-parent = <&plic0>;
-                    msi-parent = <&pcie0>;
-                    msi-controller;
-                    bus-range = <0x00 0x7f>;
-                    ranges = <0x03000000 0x0 0x78000000 0x0 0x78000000 0x0 0x04000000>;
-                    pcie_intc0: interrupt-controller {
-                        #address-cells = <0>;
-                        #interrupt-cells = <1>;
-                        interrupt-controller;
-                    };
+            #interrupt-cells = <1>;
+            interrupts = <119>;
+            interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+            interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+                            <0 0 0 2 &pcie_intc0 1>,
+                            <0 0 0 3 &pcie_intc0 2>,
+                            <0 0 0 4 &pcie_intc0 3>;
+            interrupt-parent = <&plic0>;
+            msi-parent = <&pcie0>;
+            msi-controller;
+            bus-range = <0x00 0x7f>;
+            ranges = <0x03000000 0x0 0x78000000 0x0 0x78000000 0x0 0x04000000>;
+            pcie_intc0: interrupt-controller {
+                #address-cells = <0>;
+                #interrupt-cells = <1>;
+                interrupt-controller;
             };
+        };
     };
diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
index 32a3b7665ff5..6b91581c30ae 100644
--- a/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
@@ -73,21 +73,21 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/power/r8a774c0-sysc.h>
 
-     pcie0_ep: pcie-ep at fe000000 {
-            compatible = "renesas,r8a774c0-pcie-ep",
-                         "renesas,rcar-gen3-pcie-ep";
-            reg = <0xfe000000 0x80000>,
-                  <0xfe100000 0x100000>,
-                  <0xfe200000 0x200000>,
-                  <0x30000000 0x8000000>,
-                  <0x38000000 0x8000000>;
-            reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
-            interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-            resets = <&cpg 319>;
-            power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
-            clocks = <&cpg CPG_MOD 319>;
-            clock-names = "pcie";
-            max-functions = /bits/ 8 <1>;
+    pcie0_ep: pcie-ep at fe000000 {
+        compatible = "renesas,r8a774c0-pcie-ep",
+                     "renesas,rcar-gen3-pcie-ep";
+        reg = <0xfe000000 0x80000>,
+              <0xfe100000 0x100000>,
+              <0xfe200000 0x200000>,
+              <0x30000000 0x8000000>,
+              <0x38000000 0x8000000>;
+        reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
+        interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+        resets = <&cpg 319>;
+        power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+        clocks = <&cpg CPG_MOD 319>;
+        clock-names = "pcie";
+        max-functions = /bits/ 8 <1>;
     };
diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
index 666f013e3af8..7896576920aa 100644
--- a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
+++ b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
@@ -113,27 +113,27 @@ examples:
         pcie: pcie at fe000000 {
             compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2";
             reg = <0 0xfe000000 0 0x80000>;
-             #address-cells = <3>;
-             #size-cells = <2>;
-             bus-range = <0x00 0xff>;
-             device_type = "pci";
-             ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000>,
-                      <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>,
-                      <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>,
-                      <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
-             dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>,
-                          <0x42000000 2 0x00000000 2 0x00000000 0 0x40000000>;
-             interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
-                          <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
-                          <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-             #interrupt-cells = <1>;
-             interrupt-map-mask = <0 0 0 0>;
-             interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
-             clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
-             clock-names = "pcie", "pcie_bus";
-             power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
-             resets = <&cpg 319>;
-             vpcie3v3-supply = <&pcie_3v3>;
-             vpcie12v-supply = <&pcie_12v>;
-         };
+            #address-cells = <3>;
+            #size-cells = <2>;
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000>,
+                     <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>,
+                     <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>,
+                     <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+            dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>,
+                         <0x42000000 2 0x00000000 2 0x00000000 0 0x40000000>;
+            interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0>;
+            interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
+            clock-names = "pcie", "pcie_bus";
+            power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
+            resets = <&cpg 319>;
+            vpcie3v3-supply = <&pcie_3v3>;
+            vpcie12v-supply = <&pcie_12v>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
index d674a24c8ccc..9823456addea 100644
--- a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
+++ b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
@@ -76,64 +76,62 @@ unevaluatedProperties: false
 
 examples:
   - |
-
     versal {
-               #address-cells = <2>;
-               #size-cells = <2>;
-               cpm_pcie: pcie at fca10000 {
-                       compatible = "xlnx,versal-cpm-host-1.00";
-                       device_type = "pci";
-                       #address-cells = <3>;
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       interrupts = <0 72 4>;
-                       interrupt-parent = <&gic>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0 0 0 1 &pcie_intc_0 0>,
-                                       <0 0 0 2 &pcie_intc_0 1>,
-                                       <0 0 0 3 &pcie_intc_0 2>,
-                                       <0 0 0 4 &pcie_intc_0 3>;
-                       bus-range = <0x00 0xff>;
-                       ranges = <0x02000000 0x0 0xe0010000 0x0 0xe0010000 0x0 0x10000000>,
-                                <0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
-                       msi-map = <0x0 &its_gic 0x0 0x10000>;
-                       reg = <0x0 0xfca10000 0x0 0x1000>,
-                             <0x6 0x00000000 0x0 0x10000000>;
-                       reg-names = "cpm_slcr", "cfg";
-                       pcie_intc_0: interrupt-controller {
-                               #address-cells = <0>;
-                               #interrupt-cells = <1>;
-                               interrupt-controller;
-                       };
-               };
+        #address-cells = <2>;
+        #size-cells = <2>;
+        pcie at fca10000 {
+            compatible = "xlnx,versal-cpm-host-1.00";
+            device_type = "pci";
+            #address-cells = <3>;
+            #interrupt-cells = <1>;
+            #size-cells = <2>;
+            interrupts = <0 72 4>;
+            interrupt-parent = <&gic>;
+            interrupt-map-mask = <0 0 0 7>;
+            interrupt-map = <0 0 0 1 &pcie_intc_0 0>,
+                            <0 0 0 2 &pcie_intc_0 1>,
+                            <0 0 0 3 &pcie_intc_0 2>,
+                            <0 0 0 4 &pcie_intc_0 3>;
+            bus-range = <0x00 0xff>;
+            ranges = <0x02000000 0x0 0xe0010000 0x0 0xe0010000 0x0 0x10000000>,
+                     <0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
+            msi-map = <0x0 &its_gic 0x0 0x10000>;
+            reg = <0x0 0xfca10000 0x0 0x1000>,
+                  <0x6 0x00000000 0x0 0x10000000>;
+            reg-names = "cpm_slcr", "cfg";
+            pcie_intc_0: interrupt-controller {
+                    #address-cells = <0>;
+                    #interrupt-cells = <1>;
+                    interrupt-controller;
+            };
+        };
 
-               cpm5_pcie: pcie at fcdd0000 {
-                       compatible = "xlnx,versal-cpm5-host";
-                       device_type = "pci";
-                       #address-cells = <3>;
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       interrupts = <0 72 4>;
-                       interrupt-parent = <&gic>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
-                                       <0 0 0 2 &pcie_intc_1 1>,
-                                       <0 0 0 3 &pcie_intc_1 2>,
-                                       <0 0 0 4 &pcie_intc_1 3>;
-                       bus-range = <0x00 0xff>;
-                       ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
-                                <0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
-                       msi-map = <0x0 &its_gic 0x0 0x10000>;
-                       reg = <0x00 0xfcdd0000 0x00 0x1000>,
-                             <0x06 0x00000000 0x00 0x1000000>,
-                             <0x00 0xfce20000 0x00 0x1000000>;
-                       reg-names = "cpm_slcr", "cfg", "cpm_csr";
-
-                       pcie_intc_1: interrupt-controller {
-                               #address-cells = <0>;
-                               #interrupt-cells = <1>;
-                               interrupt-controller;
-                       };
-               };
+        pcie at fcdd0000 {
+            compatible = "xlnx,versal-cpm5-host";
+            device_type = "pci";
+            #address-cells = <3>;
+            #interrupt-cells = <1>;
+            #size-cells = <2>;
+            interrupts = <0 72 4>;
+            interrupt-parent = <&gic>;
+            interrupt-map-mask = <0 0 0 7>;
+            interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
+                            <0 0 0 2 &pcie_intc_1 1>,
+                            <0 0 0 3 &pcie_intc_1 2>,
+                            <0 0 0 4 &pcie_intc_1 3>;
+            bus-range = <0x00 0xff>;
+            ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
+                     <0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
+            msi-map = <0x0 &its_gic 0x0 0x10000>;
+            reg = <0x00 0xfcdd0000 0x00 0x1000>,
+                  <0x06 0x00000000 0x00 0x1000000>,
+                  <0x00 0xfce20000 0x00 0x1000000>;
+            reg-names = "cpm_slcr", "cfg", "cpm_csr";
 
+            pcie_intc_1: interrupt-controller {
+                #address-cells = <0>;
+                #interrupt-cells = <1>;
+                interrupt-controller;
+            };
+        };
     };
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:52:02 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:52:02 +0100
Subject: [PATCH 2/2] dt-bindings: PCI: sifive,fu740-pcie: Fix include placement in DTS example
In-Reply-To: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
References: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250324125202.81986-2-krzysztof.kozlowski@linaro.org>

Coding style and common logic dictates that headers should not be
included in device nodes.  No functional impact.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
index 844fc7142302..d35ff807936b 100644
--- a/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
@@ -81,10 +81,10 @@ unevaluatedProperties: false
 
 examples:
   - |
+    #include <dt-bindings/clock/sifive-fu740-prci.h>
     bus {
         #address-cells = <2>;
         #size-cells = <2>;
-        #include <dt-bindings/clock/sifive-fu740-prci.h>
 
         pcie at e00000000 {
             compatible = "sifive,fu740-pcie";
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:52:14 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:52:14 +0100
Subject: [PATCH] dt-bindings: nvmem: Correct indentation and style in DTS example
Message-ID: <20250324125214.82028-1-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
unused labels.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../devicetree/bindings/nvmem/nvmem.yaml      | 60 +++++++++----------
 .../devicetree/bindings/nvmem/rmem.yaml       | 20 +++----
 .../bindings/nvmem/rockchip-efuse.yaml        | 20 +++----
 3 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
index 4fd015d402ce..c24e3667accd 100644
--- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
@@ -50,43 +50,43 @@ additionalProperties: true
 
 examples:
   - |
-      #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/gpio/gpio.h>
 
-      qfprom: eeprom at 700000 {
-          compatible = "qcom,msm8974-qfprom", "qcom,qfprom";
-          #address-cells = <1>;
-          #size-cells = <1>;
-          reg = <0x00700000 0x100000>;
+    qfprom: eeprom at 700000 {
+        compatible = "qcom,msm8974-qfprom", "qcom,qfprom";
+        #address-cells = <1>;
+        #size-cells = <1>;
+        reg = <0x00700000 0x100000>;
 
-          wp-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+        wp-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
 
-          /* ... */
+        /* ... */
 
-          nvmem-layout {
-              compatible = "fixed-layout";
-              #address-cells = <1>;
-              #size-cells = <1>;
+        nvmem-layout {
+            compatible = "fixed-layout";
+            #address-cells = <1>;
+            #size-cells = <1>;
 
-              /* Data cells */
-              tsens_calibration: calib at 404 {
-                  reg = <0x404 0x10>;
-              };
+            /* Data cells */
+            tsens_calibration: calib at 404 {
+                reg = <0x404 0x10>;
+            };
 
-              tsens_calibration_bckp: calib_bckp at 504 {
-                  reg = <0x504 0x11>;
-                  bits = <6 128>;
-              };
+            tsens_calibration_bckp: calib_bckp at 504 {
+                reg = <0x504 0x11>;
+                bits = <6 128>;
+            };
 
-              pvs_version: pvs-version at 6 {
-                  reg = <0x6 0x2>;
-                  bits = <7 2>;
-              };
+            pvs_version: pvs-version at 6 {
+                reg = <0x6 0x2>;
+                bits = <7 2>;
+            };
 
-              speed_bin: speed-bin at c{
-                  reg = <0xc 0x1>;
-                  bits = <2 3>;
-              };
-          };
-      };
+            speed_bin: speed-bin at c{
+                reg = <0xc 0x1>;
+                bits = <2 3>;
+            };
+        };
+    };
 
 ...
diff --git a/Documentation/devicetree/bindings/nvmem/rmem.yaml b/Documentation/devicetree/bindings/nvmem/rmem.yaml
index 85f9f5de3906..dc714309e7b9 100644
--- a/Documentation/devicetree/bindings/nvmem/rmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rmem.yaml
@@ -38,17 +38,17 @@ unevaluatedProperties: false
 
 examples:
   - |
-        reserved-memory {
-                #address-cells = <1>;
-                #size-cells = <1>;
+    reserved-memory {
+        #address-cells = <1>;
+        #size-cells = <1>;
 
-                blconfig: nvram at 10000000 {
-                        compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
-                        #address-cells = <1>;
-                        #size-cells = <1>;
-                        reg = <0x10000000 0x1000>;
-                        no-map;
-                };
+        nvram at 10000000 {
+            compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
+            #address-cells = <1>;
+            #size-cells = <1>;
+            reg = <0x10000000 0x1000>;
+            no-map;
         };
+    };
 
 ...
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
index b80fd8d1ae5b..aa93ebc41a8e 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
@@ -58,16 +58,16 @@ examples:
   - |
     #include <dt-bindings/clock/rk3288-cru.h>
     efuse: efuse at ffb40000 {
-            compatible = "rockchip,rk3288-efuse";
-            reg = <0xffb40000 0x20>;
-            #address-cells = <1>;
-            #size-cells = <1>;
-            clocks = <&cru PCLK_EFUSE256>;
-            clock-names = "pclk_efuse";
+        compatible = "rockchip,rk3288-efuse";
+        reg = <0xffb40000 0x20>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        clocks = <&cru PCLK_EFUSE256>;
+        clock-names = "pclk_efuse";
 
-            /* Data cells */
-            cpu_leakage: cpu_leakage at 17 {
-                    reg = <0x17 0x1>;
-            };
+        /* Data cells */
+        cpu_leakage at 17 {
+            reg = <0x17 0x1>;
+        };
     };
 ...
-- 
2.43.0



From andyshrk at 163.com  Mon Mar 24 05:52:11 2025
From: andyshrk at 163.com (Andy Yan)
Date: Mon, 24 Mar 2025 20:52:11 +0800
Subject: [PATCH] ARM: dts: rockchip: Add aliases for MMC devices
Message-ID: <20250324125215.160616-1-andyshrk@163.com>

From: Andy Yan <andy.yan at rock-chips.com>

Add aliases for the MMC devices so that after the system starts up,
they will all have fixed device numbers.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 arch/arm/boot/dts/rockchip/rk3036-kylin.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
index 15a8860c7ae47..a2d7ec2729116 100644
--- a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
+++ b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
@@ -8,6 +8,12 @@ / {
 	model = "Rockchip RK3036 KylinBoard";
 	compatible = "rockchip,rk3036-kylin", "rockchip,rk3036";
 
+	aliases {
+		mmc0 = &emmc;
+		mmc1 = &sdmmc;
+		mmc2 = &sdio;
+	};
+
 	chosen {
 		stdout-path = "serial2:115200n8";
 	};
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:52:50 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:52:50 +0100
Subject: [PATCH] dt-bindings: iommu: Correct indentation and style in DTS example
Message-ID: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
unused labels.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../iommu/allwinner,sun50i-h6-iommu.yaml      |  24 ++--
 .../bindings/iommu/arm,smmu-v3.yaml           |  20 ++--
 .../devicetree/bindings/iommu/arm,smmu.yaml   | 104 +++++++++---------
 .../bindings/iommu/mediatek,iommu.yaml        |  18 +--
 .../bindings/iommu/qcom,apq8064-iommu.yaml    |  20 ++--
 5 files changed, 92 insertions(+), 94 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
index a8409db4a3e3..ad51ace9ca09 100644
--- a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
@@ -48,19 +48,19 @@ additionalProperties: false
 
 examples:
   - |
-      #include <dt-bindings/interrupt-controller/arm-gic.h>
-      #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
 
-      #include <dt-bindings/clock/sun50i-h6-ccu.h>
-      #include <dt-bindings/reset/sun50i-h6-ccu.h>
+    #include <dt-bindings/clock/sun50i-h6-ccu.h>
+    #include <dt-bindings/reset/sun50i-h6-ccu.h>
 
-      iommu: iommu at 30f0000 {
-          compatible = "allwinner,sun50i-h6-iommu";
-          reg = <0x030f0000 0x10000>;
-          interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
-          clocks = <&ccu CLK_BUS_IOMMU>;
-          resets = <&ccu RST_BUS_IOMMU>;
-          #iommu-cells = <1>;
-      };
+    iommu at 30f0000 {
+        compatible = "allwinner,sun50i-h6-iommu";
+        reg = <0x030f0000 0x10000>;
+        interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&ccu CLK_BUS_IOMMU>;
+        resets = <&ccu RST_BUS_IOMMU>;
+        #iommu-cells = <1>;
+    };
 
 ...
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
index 75fcf4cb52d9..36b31197c908 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
@@ -82,14 +82,14 @@ examples:
     #include <dt-bindings/interrupt-controller/irq.h>
 
     iommu at 2b400000 {
-            compatible = "arm,smmu-v3";
-            reg = <0x2b400000 0x20000>;
-            interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
-                         <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
-                         <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
-                         <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
-            interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
-            dma-coherent;
-            #iommu-cells = <1>;
-            msi-parent = <&its 0xff0000>;
+        compatible = "arm,smmu-v3";
+        reg = <0x2b400000 0x20000>;
+        interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
+        interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+        dma-coherent;
+        #iommu-cells = <1>;
+        msi-parent = <&its 0xff0000>;
     };
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 7b9d5507d6cc..5b56e4f9d106 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -621,73 +621,71 @@ examples:
   - |+
     /* SMMU with stream matching or stream indexing */
     smmu1: iommu at ba5e0000 {
-            compatible = "arm,smmu-v1";
-            reg = <0xba5e0000 0x10000>;
-            #global-interrupts = <2>;
-            interrupts = <0 32 4>,
-                         <0 33 4>,
-                         <0 34 4>, /* This is the first context interrupt */
-                         <0 35 4>,
-                         <0 36 4>,
-                         <0 37 4>;
-            #iommu-cells = <1>;
+        compatible = "arm,smmu-v1";
+        reg = <0xba5e0000 0x10000>;
+        #global-interrupts = <2>;
+        interrupts = <0 32 4>,
+                     <0 33 4>,
+                     <0 34 4>, /* This is the first context interrupt */
+                     <0 35 4>,
+                     <0 36 4>,
+                     <0 37 4>;
+        #iommu-cells = <1>;
     };
 
     /* device with two stream IDs, 0 and 7 */
     master1 {
-            iommus = <&smmu1 0>,
-                     <&smmu1 7>;
+        iommus = <&smmu1 0>,
+                 <&smmu1 7>;
     };
 
 
     /* SMMU with stream matching */
     smmu2: iommu at ba5f0000 {
-            compatible = "arm,smmu-v1";
-            reg = <0xba5f0000 0x10000>;
-            #global-interrupts = <2>;
-            interrupts = <0 38 4>,
-                         <0 39 4>,
-                         <0 40 4>, /* This is the first context interrupt */
-                         <0 41 4>,
-                         <0 42 4>,
-                         <0 43 4>;
-            #iommu-cells = <2>;
+        compatible = "arm,smmu-v1";
+        reg = <0xba5f0000 0x10000>;
+        #global-interrupts = <2>;
+        interrupts = <0 38 4>,
+                     <0 39 4>,
+                     <0 40 4>, /* This is the first context interrupt */
+                     <0 41 4>,
+                     <0 42 4>,
+                     <0 43 4>;
+        #iommu-cells = <2>;
     };
 
     /* device with stream IDs 0 and 7 */
     master2 {
-            iommus = <&smmu2 0 0>,
-                     <&smmu2 7 0>;
+        iommus = <&smmu2 0 0>,
+                 <&smmu2 7 0>;
     };
 
     /* device with stream IDs 1, 17, 33 and 49 */
     master3 {
-            iommus = <&smmu2 1 0x30>;
+        iommus = <&smmu2 1 0x30>;
     };
 
 
     /* ARM MMU-500 with 10-bit stream ID input configuration */
     smmu3: iommu at ba600000 {
-            compatible = "arm,mmu-500", "arm,smmu-v2";
-            reg = <0xba600000 0x10000>;
-            #global-interrupts = <2>;
-            interrupts = <0 44 4>,
-                         <0 45 4>,
-                         <0 46 4>, /* This is the first context interrupt */
-                         <0 47 4>,
-                         <0 48 4>,
-                         <0 49 4>;
-            #iommu-cells = <1>;
-            /* always ignore appended 5-bit TBU number */
-            stream-match-mask = <0x7c00>;
+        compatible = "arm,mmu-500", "arm,smmu-v2";
+        reg = <0xba600000 0x10000>;
+        #global-interrupts = <2>;
+        interrupts = <0 44 4>,
+                     <0 45 4>,
+                     <0 46 4>, /* This is the first context interrupt */
+                     <0 47 4>,
+                     <0 48 4>,
+                     <0 49 4>;
+        #iommu-cells = <1>;
+        /* always ignore appended 5-bit TBU number */
+        stream-match-mask = <0x7c00>;
     };
 
     bus {
-            /* bus whose child devices emit one unique 10-bit stream
-               ID each, but may master through multiple SMMU TBUs */
-            iommu-map = <0 &smmu3 0 0x400>;
-
-
+        /* bus whose child devices emit one unique 10-bit stream
+           ID each, but may master through multiple SMMU TBUs */
+        iommu-map = <0 &smmu3 0 0x400>;
     };
 
   - |+
@@ -695,17 +693,17 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/interrupt-controller/irq.h>
     smmu4: iommu at d00000 {
-      compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
-      reg = <0xd00000 0x10000>;
+        compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+        reg = <0xd00000 0x10000>;
 
-      #global-interrupts = <1>;
-      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
-             <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
-             <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
-      #iommu-cells = <1>;
-      power-domains = <&mmcc 0>;
+        #global-interrupts = <1>;
+        interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
+        #iommu-cells = <1>;
+        power-domains = <&mmcc 0>;
 
-      clocks = <&mmcc 123>,
-        <&mmcc 124>;
-      clock-names = "bus", "iface";
+        clocks = <&mmcc 123>,
+                 <&mmcc 124>;
+        clock-names = "bus", "iface";
     };
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index ea6b0f5f24de..1eac27893b03 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -218,13 +218,13 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
     iommu: iommu at 10205000 {
-            compatible = "mediatek,mt8173-m4u";
-            reg = <0x10205000 0x1000>;
-            interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
-            clocks = <&infracfg CLK_INFRA_M4U>;
-            clock-names = "bclk";
-            mediatek,infracfg = <&infracfg>;
-            mediatek,larbs = <&larb0>, <&larb1>, <&larb2>,
-                             <&larb3>, <&larb4>, <&larb5>;
-            #iommu-cells = <1>;
+        compatible = "mediatek,mt8173-m4u";
+        reg = <0x10205000 0x1000>;
+        interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
+        clocks = <&infracfg CLK_INFRA_M4U>;
+        clock-names = "bclk";
+        mediatek,infracfg = <&infracfg>;
+        mediatek,larbs = <&larb0>, <&larb1>, <&larb2>,
+                         <&larb3>, <&larb4>, <&larb5>;
+        #iommu-cells = <1>;
     };
diff --git a/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml b/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
index 9f83f851e61a..aaecad32dc9d 100644
--- a/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
@@ -65,14 +65,14 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
     iommu at 7500000 {
-            compatible = "qcom,apq8064-iommu";
-            reg = <0x07500000 0x100000>;
-            interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-            clocks = <&clk SMMU_AHB_CLK>,
-                     <&clk MDP_AXI_CLK>;
-            clock-names = "smmu_pclk",
-                          "iommu_clk";
-            #iommu-cells = <1>;
-            qcom,ncb = <2>;
+        compatible = "qcom,apq8064-iommu";
+        reg = <0x07500000 0x100000>;
+        interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clk SMMU_AHB_CLK>,
+                 <&clk MDP_AXI_CLK>;
+        clock-names = "smmu_pclk",
+                      "iommu_clk";
+        #iommu-cells = <1>;
+        qcom,ncb = <2>;
     };
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:53:12 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:53:12 +0100
Subject: [PATCH 1/2] dt-bindings: iio: Correct indentation and style in DTS example
Message-ID: <20250324125313.82226-1-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/iio/adc/st,stm32-adc.yaml        | 102 +++++++++---------
 1 file changed, 51 insertions(+), 51 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
index ef9dcc365eab..17bb60e18a1c 100644
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
@@ -498,7 +498,7 @@ patternProperties:
 examples:
   - |
     // Example 1: with stm32f429, ADC1, single-ended channel 8
-      adc123: adc at 40012000 {
+    adc123: adc at 40012000 {
         compatible = "st,stm32f4-adc-core";
         reg = <0x40012000 0x400>;
         interrupts = <18>;
@@ -512,28 +512,28 @@ examples:
         #address-cells = <1>;
         #size-cells = <0>;
         adc at 0 {
-          compatible = "st,stm32f4-adc";
-          #io-channel-cells = <1>;
-          reg = <0x0>;
-          clocks = <&rcc 0 168>;
-          interrupt-parent = <&adc123>;
-          interrupts = <0>;
-          st,adc-channels = <8>;
-          dmas = <&dma2 0 0 0x400 0x0>;
-          dma-names = "rx";
-          assigned-resolution-bits = <8>;
+            compatible = "st,stm32f4-adc";
+            #io-channel-cells = <1>;
+            reg = <0x0>;
+            clocks = <&rcc 0 168>;
+            interrupt-parent = <&adc123>;
+            interrupts = <0>;
+            st,adc-channels = <8>;
+            dmas = <&dma2 0 0 0x400 0x0>;
+            dma-names = "rx";
+            assigned-resolution-bits = <8>;
         };
         // ...
         // other adc child nodes follow...
-      };
+    };
 
   - |
     // Example 2: with stm32mp157c to setup ADC1 with:
     // - channels 0 & 1 as single-ended
     // - channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
-      #include <dt-bindings/interrupt-controller/arm-gic.h>
-      #include <dt-bindings/clock/stm32mp1-clks.h>
-      adc12: adc at 48003000 {
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/stm32mp1-clks.h>
+    adc12: adc at 48003000 {
         compatible = "st,stm32mp1-adc-core";
         reg = <0x48003000 0x400>;
         interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
@@ -550,27 +550,27 @@ examples:
         #address-cells = <1>;
         #size-cells = <0>;
         adc at 0 {
-          compatible = "st,stm32mp1-adc";
-          #io-channel-cells = <1>;
-          reg = <0x0>;
-          interrupt-parent = <&adc12>;
-          interrupts = <0>;
-          st,adc-channels = <0 1>;
-          st,adc-diff-channels = <2 6>, <3 7>;
-          st,min-sample-time-nsecs = <5000>;
-          dmas = <&dmamux1 9 0x400 0x05>;
-          dma-names = "rx";
+            compatible = "st,stm32mp1-adc";
+            #io-channel-cells = <1>;
+            reg = <0x0>;
+            interrupt-parent = <&adc12>;
+            interrupts = <0>;
+            st,adc-channels = <0 1>;
+            st,adc-diff-channels = <2 6>, <3 7>;
+            st,min-sample-time-nsecs = <5000>;
+            dmas = <&dmamux1 9 0x400 0x05>;
+            dma-names = "rx";
         };
         // ...
         // other adc child node follow...
-      };
+    };
 
   - |
     // Example 3: with stm32mp157c to setup ADC2 with:
     // - internal channels 13, 14, 15.
-      #include <dt-bindings/interrupt-controller/arm-gic.h>
-      #include <dt-bindings/clock/stm32mp1-clks.h>
-      adc122: adc at 48003000 {
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/stm32mp1-clks.h>
+    adc122: adc at 48003000 {
         compatible = "st,stm32mp1-adc-core";
         reg = <0x48003000 0x400>;
         interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
@@ -587,28 +587,28 @@ examples:
         #address-cells = <1>;
         #size-cells = <0>;
         adc at 100 {
-          compatible = "st,stm32mp1-adc";
-          #io-channel-cells = <1>;
-          reg = <0x100>;
-          interrupts = <1>;
-          #address-cells = <1>;
-          #size-cells = <0>;
-          channel at 13 {
-            reg = <13>;
-            label = "vrefint";
-            st,min-sample-time-ns = <9000>;
-          };
-          channel at 14 {
-            reg = <14>;
-            label = "vddcore";
-            st,min-sample-time-ns = <9000>;
-          };
-          channel at 15 {
-            reg = <15>;
-            label = "vbat";
-            st,min-sample-time-ns = <9000>;
-          };
+            compatible = "st,stm32mp1-adc";
+            #io-channel-cells = <1>;
+            reg = <0x100>;
+            interrupts = <1>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            channel at 13 {
+                reg = <13>;
+                label = "vrefint";
+                st,min-sample-time-ns = <9000>;
+            };
+            channel at 14 {
+                reg = <14>;
+                label = "vddcore";
+                st,min-sample-time-ns = <9000>;
+            };
+            channel at 15 {
+                reg = <15>;
+                label = "vbat";
+                st,min-sample-time-ns = <9000>;
+            };
         };
-      };
+    };
 
 ...
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:53:13 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:53:13 +0100
Subject: [PATCH 2/2] dt-bindings: iio: Use unevaluatedProperties for SPI devices
In-Reply-To: <20250324125313.82226-1-krzysztof.kozlowski@linaro.org>
References: <20250324125313.82226-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250324125313.82226-2-krzysztof.kozlowski@linaro.org>

SPI devices should use unevaluatedProperties:false instead of
additionalProperties:false, to allow any SPI device properties listed in
spi-peripheral-props.yaml.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml      | 2 +-
 Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml      | 2 +-
 Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml      | 2 +-
 .../devicetree/bindings/iio/dac/microchip,mcp4821.yaml          | 2 +-
 Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml     | 2 +-
 Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml    | 2 +-
 .../devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml    | 2 +-
 .../devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml | 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
index 2d2561a52683..547044b8e246 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
@@ -217,7 +217,7 @@ required:
   - reg
   - spi-max-frequency
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
index 33490853497b..1aece3392b77 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
@@ -144,7 +144,7 @@ required:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
index c8c434c10643..3c8e5781e42c 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
@@ -124,7 +124,7 @@ required:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp4821.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp4821.yaml
index 0dc577c33918..26011b5639d8 100644
--- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp4821.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp4821.yaml
@@ -64,7 +64,7 @@ required:
   - reg
   - vdd-supply
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml b/Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml
index 941a49c93943..188b00333dfb 100644
--- a/Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml
@@ -43,7 +43,7 @@ required:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml
index a4c273c7a67f..cf5324de4fd6 100644
--- a/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml
@@ -53,7 +53,7 @@ required:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml b/Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml
index 89977b9f01cf..412c7bcc310f 100644
--- a/Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml
@@ -102,7 +102,7 @@ required:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml
 
-additionalProperties: false
+unevaluatedProperties: false
 
 dependentSchemas:
   honeywell,pmin-pascal:
diff --git a/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml b/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
index 6994b30015bd..c756aa863103 100644
--- a/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
@@ -115,7 +115,7 @@ allOf:
         honeywell,pmin-pascal: false
         honeywell,pmax-pascal: false
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-- 
2.43.0



From krzysztof.kozlowski at linaro.org  Mon Mar 24 05:53:26 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 13:53:26 +0100
Subject: [PATCH] dt-bindings: gpio: Correct indentation and style in DTS example
Message-ID: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>

DTS example in the bindings should be indented with 2- or 4-spaces and
aligned with opening '- |', so correct any differences like 3-spaces or
mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
unused labels.

No functional changes here, but saves some comments during reviews of
new patches built on existing code.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
---
 .../bindings/gpio/atmel,at91rm9200-gpio.yaml  | 16 ++---
 .../bindings/gpio/fairchild,74hc595.yaml      | 20 +++---
 .../devicetree/bindings/gpio/gpio-mxs.yaml    | 70 +++++++++----------
 .../devicetree/bindings/gpio/nxp,pcf8575.yaml | 24 +++----
 .../bindings/gpio/realtek,otto-gpio.yaml      |  8 +--
 .../bindings/gpio/renesas,em-gio.yaml         | 20 +++---
 .../bindings/gpio/renesas,rcar-gpio.yaml      | 24 +++----
 .../devicetree/bindings/gpio/sifive,gpio.yaml |  6 +-
 .../bindings/gpio/toshiba,gpio-visconti.yaml  | 24 +++----
 .../bindings/gpio/xlnx,gpio-xilinx.yaml       | 48 ++++++-------
 10 files changed, 130 insertions(+), 130 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
index 3dd70933ed8e..d810043b56b6 100644
--- a/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
@@ -69,13 +69,13 @@ examples:
     #include <dt-bindings/interrupt-controller/irq.h>
 
     gpio at fffff400 {
-            compatible = "atmel,at91rm9200-gpio";
-            reg = <0xfffff400 0x200>;
-            interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
-            #gpio-cells = <2>;
-            gpio-controller;
-            interrupt-controller;
-            #interrupt-cells = <2>;
-            clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
+        compatible = "atmel,at91rm9200-gpio";
+        reg = <0xfffff400 0x200>;
+        interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
+        #gpio-cells = <2>;
+        gpio-controller;
+        interrupt-controller;
+        #interrupt-cells = <2>;
+        clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
     };
 ...
diff --git a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
index 0e5c22929bde..ab35bcf98101 100644
--- a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
+++ b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
@@ -71,15 +71,15 @@ unevaluatedProperties: false
 examples:
   - |
     spi {
-            #address-cells = <1>;
-            #size-cells = <0>;
+        #address-cells = <1>;
+        #size-cells = <0>;
 
-            gpio5: gpio5 at 0 {
-                    compatible = "fairchild,74hc595";
-                    reg = <0>;
-                    gpio-controller;
-                    #gpio-cells = <2>;
-                    registers-number = <4>;
-                    spi-max-frequency = <100000>;
-            };
+        gpio5 at 0 {
+            compatible = "fairchild,74hc595";
+            reg = <0>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            registers-number = <4>;
+            spi-max-frequency = <100000>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
index 8ff54369d16c..b58e08c8ecd8 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
@@ -84,52 +84,52 @@ examples:
         reg = <0x80018000 0x2000>;
 
         gpio at 0 {
-                compatible = "fsl,imx28-gpio";
-                reg = <0>;
-                interrupts = <127>;
-                gpio-controller;
-                #gpio-cells = <2>;
-                interrupt-controller;
-                #interrupt-cells = <2>;
+            compatible = "fsl,imx28-gpio";
+            reg = <0>;
+            interrupts = <127>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
         };
 
         gpio at 1 {
-                compatible = "fsl,imx28-gpio";
-                reg = <1>;
-                interrupts = <126>;
-                gpio-controller;
-                #gpio-cells = <2>;
-                interrupt-controller;
-                #interrupt-cells = <2>;
+            compatible = "fsl,imx28-gpio";
+            reg = <1>;
+            interrupts = <126>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
         };
 
         gpio at 2 {
-                compatible = "fsl,imx28-gpio";
-                reg = <2>;
-                interrupts = <125>;
-                gpio-controller;
-                #gpio-cells = <2>;
-                interrupt-controller;
-                #interrupt-cells = <2>;
+            compatible = "fsl,imx28-gpio";
+            reg = <2>;
+            interrupts = <125>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
         };
 
         gpio at 3 {
-                compatible = "fsl,imx28-gpio";
-                reg = <3>;
-                interrupts = <124>;
-                gpio-controller;
-                #gpio-cells = <2>;
-                interrupt-controller;
-                #interrupt-cells = <2>;
+            compatible = "fsl,imx28-gpio";
+            reg = <3>;
+            interrupts = <124>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
         };
 
         gpio at 4 {
-                compatible = "fsl,imx28-gpio";
-                reg = <4>;
-                interrupts = <123>;
-                gpio-controller;
-                #gpio-cells = <2>;
-                interrupt-controller;
-                #interrupt-cells = <2>;
+            compatible = "fsl,imx28-gpio";
+            reg = <4>;
+            interrupts = <123>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
         };
     };
diff --git a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
index 8bca574bb66d..5a6ecaa7b44b 100644
--- a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
+++ b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
@@ -128,17 +128,17 @@ additionalProperties: false
 examples:
   - |
     i2c {
-            #address-cells = <1>;
-            #size-cells = <0>;
+        #address-cells = <1>;
+        #size-cells = <0>;
 
-            pcf8575: gpio at 20 {
-                    compatible = "nxp,pcf8575";
-                    reg = <0x20>;
-                    interrupt-parent = <&irqpin2>;
-                    interrupts = <3 0>;
-                    gpio-controller;
-                    #gpio-cells = <2>;
-                    interrupt-controller;
-                    #interrupt-cells = <2>;
-            };
+        gpio at 20 {
+            compatible = "nxp,pcf8575";
+            reg = <0x20>;
+            interrupt-parent = <&irqpin2>;
+            interrupts = <3 0>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
index 39fd959c45d2..728099c65824 100644
--- a/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
@@ -81,7 +81,7 @@ dependencies:
 
 examples:
   - |
-      gpio at 3500 {
+    gpio at 3500 {
         compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
         reg = <0x3500 0x1c>;
         gpio-controller;
@@ -91,9 +91,9 @@ examples:
         #interrupt-cells = <2>;
         interrupt-parent = <&rtlintc>;
         interrupts = <23>;
-      };
+    };
   - |
-      gpio at 3300 {
+    gpio at 3300 {
         compatible = "realtek,rtl9300-gpio", "realtek,otto-gpio";
         reg = <0x3300 0x1c>, <0x3338 0x8>;
         gpio-controller;
@@ -103,6 +103,6 @@ examples:
         #interrupt-cells = <2>;
         interrupt-parent = <&rtlintc>;
         interrupts = <13>;
-      };
+    };
 
 ...
diff --git a/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml b/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
index 8bdef812c87c..49fb8f613ead 100644
--- a/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
+++ b/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
@@ -57,14 +57,14 @@ examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     gpio0: gpio at e0050000 {
-            compatible = "renesas,em-gio";
-            reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
-            interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
-            gpio-controller;
-            #gpio-cells = <2>;
-            gpio-ranges = <&pfc 0 0 32>;
-            ngpios = <32>;
-            interrupt-controller;
-            #interrupt-cells = <2>;
+        compatible = "renesas,em-gio";
+        reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
+        interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+        gpio-controller;
+        #gpio-cells = <2>;
+        gpio-ranges = <&pfc 0 0 32>;
+        ngpios = <32>;
+        interrupt-controller;
+        #interrupt-cells = <2>;
     };
diff --git a/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml b/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
index cc7a950a6030..d32e103a64aa 100644
--- a/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
@@ -138,16 +138,16 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/power/r8a77470-sysc.h>
     gpio3: gpio at e6053000 {
-            compatible = "renesas,gpio-r8a77470", "renesas,rcar-gen2-gpio";
-            reg = <0xe6053000 0x50>;
-            interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
-            clocks = <&cpg CPG_MOD 909>;
-            power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
-            resets = <&cpg 909>;
-            gpio-controller;
-            #gpio-cells = <2>;
-            gpio-ranges = <&pfc 0 96 30>;
-            gpio-reserved-ranges = <17 10>;
-            interrupt-controller;
-            #interrupt-cells = <2>;
+        compatible = "renesas,gpio-r8a77470", "renesas,rcar-gen2-gpio";
+        reg = <0xe6053000 0x50>;
+        interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&cpg CPG_MOD 909>;
+        power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+        resets = <&cpg 909>;
+        gpio-controller;
+        #gpio-cells = <2>;
+        gpio-ranges = <&pfc 0 96 30>;
+        gpio-reserved-ranges = <17 10>;
+        interrupt-controller;
+        #interrupt-cells = <2>;
      };
diff --git a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
index fc095646adea..4bdc201b719e 100644
--- a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
@@ -76,8 +76,8 @@ additionalProperties: false
 
 examples:
   - |
-      #include <dt-bindings/clock/sifive-fu540-prci.h>
-      gpio at 10060000 {
+    #include <dt-bindings/clock/sifive-fu540-prci.h>
+    gpio at 10060000 {
         compatible = "sifive,fu540-c000-gpio", "sifive,gpio0";
         interrupt-parent = <&plic>;
         interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, <14>, <15>, <16>,
@@ -88,6 +88,6 @@ examples:
         #gpio-cells = <2>;
         interrupt-controller;
         #interrupt-cells = <2>;
-      };
+    };
 
 ...
diff --git a/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml b/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
index b085450b527f..712063417bc8 100644
--- a/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
+++ b/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
@@ -48,22 +48,22 @@ additionalProperties: false
 
 examples:
   - |
-      #include <dt-bindings/interrupt-controller/irq.h>
-      #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-      soc {
+    soc {
         #address-cells = <2>;
         #size-cells = <2>;
 
         gpio: gpio at 28020000 {
-          compatible = "toshiba,gpio-tmpv7708";
-          reg = <0 0x28020000 0 0x1000>;
-          #gpio-cells = <0x2>;
-          gpio-ranges = <&pmux 0 0 32>;
-          gpio-controller;
-          interrupt-controller;
-          #interrupt-cells = <2>;
-          interrupt-parent = <&gic>;
+            compatible = "toshiba,gpio-tmpv7708";
+            reg = <0 0x28020000 0 0x1000>;
+            #gpio-cells = <0x2>;
+            gpio-ranges = <&pmux 0 0 32>;
+            gpio-controller;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+            interrupt-parent = <&gic>;
         };
-      };
+    };
 ...
diff --git a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
index d3d8a2e143ed..8fbf12ca067e 100644
--- a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
+++ b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
@@ -126,29 +126,29 @@ examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-        gpio at a0020000 {
-            compatible = "xlnx,xps-gpio-1.00.a";
-            reg = <0xa0020000 0x10000>;
-            #gpio-cells = <2>;
-            #interrupt-cells = <0x2>;
-            clocks = <&zynqmp_clk 71>;
-            gpio-controller;
-            interrupt-controller;
-            interrupt-names = "ip2intc_irpt";
-            interrupt-parent = <&gic>;
-            interrupts = <0 89 4>;
-            xlnx,all-inputs = <0x0>;
-            xlnx,all-inputs-2 = <0x0>;
-            xlnx,all-outputs = <0x0>;
-            xlnx,all-outputs-2 = <0x0>;
-            xlnx,dout-default = <0x0>;
-            xlnx,dout-default-2 = <0x0>;
-            xlnx,gpio-width = <0x20>;
-            xlnx,gpio2-width = <0x20>;
-            xlnx,interrupt-present = <0x1>;
-            xlnx,is-dual = <0x1>;
-            xlnx,tri-default = <0xFFFFFFFF>;
-            xlnx,tri-default-2 = <0xFFFFFFFF>;
-        };
+    gpio at a0020000 {
+        compatible = "xlnx,xps-gpio-1.00.a";
+        reg = <0xa0020000 0x10000>;
+        #gpio-cells = <2>;
+        #interrupt-cells = <0x2>;
+        clocks = <&zynqmp_clk 71>;
+        gpio-controller;
+        interrupt-controller;
+        interrupt-names = "ip2intc_irpt";
+        interrupt-parent = <&gic>;
+        interrupts = <0 89 4>;
+        xlnx,all-inputs = <0x0>;
+        xlnx,all-inputs-2 = <0x0>;
+        xlnx,all-outputs = <0x0>;
+        xlnx,all-outputs-2 = <0x0>;
+        xlnx,dout-default = <0x0>;
+        xlnx,dout-default-2 = <0x0>;
+        xlnx,gpio-width = <0x20>;
+        xlnx,gpio2-width = <0x20>;
+        xlnx,interrupt-present = <0x1>;
+        xlnx,is-dual = <0x1>;
+        xlnx,tri-default = <0xFFFFFFFF>;
+        xlnx,tri-default-2 = <0xFFFFFFFF>;
+    };
 
 ...
-- 
2.43.0



From david at ixit.cz  Mon Mar 24 05:58:55 2025
From: david at ixit.cz (David Heidelberg)
Date: Mon, 24 Mar 2025 13:58:55 +0100
Subject: [PATCH] dt-bindings: iommu: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
References: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
Message-ID: <2cf735da-9f20-4372-8b08-0b40c335ba6b@ixit.cz>

On 24/03/2025 13:52, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>   .../iommu/allwinner,sun50i-h6-iommu.yaml      |  24 ++--
>   .../bindings/iommu/arm,smmu-v3.yaml           |  20 ++--
>   .../devicetree/bindings/iommu/arm,smmu.yaml   | 104 +++++++++---------
>   .../bindings/iommu/mediatek,iommu.yaml        |  18 +--
>   .../bindings/iommu/qcom,apq8064-iommu.yaml    |  20 ++--
>   5 files changed, 92 insertions(+), 94 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
> index a8409db4a3e3..ad51ace9ca09 100644
> --- a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
> @@ -48,19 +48,19 @@ additionalProperties: false
>   
>   examples:
>     - |
> -      #include <dt-bindings/interrupt-controller/arm-gic.h>
> -      #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
>   
> -      #include <dt-bindings/clock/sun50i-h6-ccu.h>
> -      #include <dt-bindings/reset/sun50i-h6-ccu.h>
> +    #include <dt-bindings/clock/sun50i-h6-ccu.h>
> +    #include <dt-bindings/reset/sun50i-h6-ccu.h>
>   
> -      iommu: iommu at 30f0000 {
> -          compatible = "allwinner,sun50i-h6-iommu";
> -          reg = <0x030f0000 0x10000>;
> -          interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> -          clocks = <&ccu CLK_BUS_IOMMU>;
> -          resets = <&ccu RST_BUS_IOMMU>;
> -          #iommu-cells = <1>;
> -      };
> +    iommu at 30f0000 {
> +        compatible = "allwinner,sun50i-h6-iommu";
> +        reg = <0x030f0000 0x10000>;
> +        interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> +        clocks = <&ccu CLK_BUS_IOMMU>;
> +        resets = <&ccu RST_BUS_IOMMU>;
> +        #iommu-cells = <1>;
> +    };
>   
>   ...
> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
> index 75fcf4cb52d9..36b31197c908 100644
> --- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
> @@ -82,14 +82,14 @@ examples:
>       #include <dt-bindings/interrupt-controller/irq.h>
>   
>       iommu at 2b400000 {
> -            compatible = "arm,smmu-v3";
> -            reg = <0x2b400000 0x20000>;
> -            interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
> -                         <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
> -                         <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
> -                         <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
> -            interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
> -            dma-coherent;
> -            #iommu-cells = <1>;
> -            msi-parent = <&its 0xff0000>;
> +        compatible = "arm,smmu-v3";
> +        reg = <0x2b400000 0x20000>;
> +        interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
> +                     <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
> +                     <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
> +                     <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
> +        interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
> +        dma-coherent;
> +        #iommu-cells = <1>;
> +        msi-parent = <&its 0xff0000>;
>       };
> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> index 7b9d5507d6cc..5b56e4f9d106 100644
> --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> @@ -621,73 +621,71 @@ examples:
>     - |+
>       /* SMMU with stream matching or stream indexing */
>       smmu1: iommu at ba5e0000 {
> -            compatible = "arm,smmu-v1";
> -            reg = <0xba5e0000 0x10000>;
> -            #global-interrupts = <2>;
> -            interrupts = <0 32 4>,
> -                         <0 33 4>,
> -                         <0 34 4>, /* This is the first context interrupt */
> -                         <0 35 4>,
> -                         <0 36 4>,
> -                         <0 37 4>;
> -            #iommu-cells = <1>;
> +        compatible = "arm,smmu-v1";
> +        reg = <0xba5e0000 0x10000>;
> +        #global-interrupts = <2>;
> +        interrupts = <0 32 4>,
> +                     <0 33 4>,
> +                     <0 34 4>, /* This is the first context interrupt */
> +                     <0 35 4>,
> +                     <0 36 4>,
> +                     <0 37 4>;
> +        #iommu-cells = <1>;
>       };
>   
>       /* device with two stream IDs, 0 and 7 */
>       master1 {
> -            iommus = <&smmu1 0>,
> -                     <&smmu1 7>;
> +        iommus = <&smmu1 0>,
> +                 <&smmu1 7>;
>       };
>   
>   
>       /* SMMU with stream matching */
>       smmu2: iommu at ba5f0000 {
> -            compatible = "arm,smmu-v1";
> -            reg = <0xba5f0000 0x10000>;
> -            #global-interrupts = <2>;
> -            interrupts = <0 38 4>,
> -                         <0 39 4>,
> -                         <0 40 4>, /* This is the first context interrupt */
> -                         <0 41 4>,
> -                         <0 42 4>,
> -                         <0 43 4>;
> -            #iommu-cells = <2>;
> +        compatible = "arm,smmu-v1";
> +        reg = <0xba5f0000 0x10000>;
> +        #global-interrupts = <2>;
> +        interrupts = <0 38 4>,
> +                     <0 39 4>,
> +                     <0 40 4>, /* This is the first context interrupt */
> +                     <0 41 4>,
> +                     <0 42 4>,
> +                     <0 43 4>;
> +        #iommu-cells = <2>;
>       };
>   
>       /* device with stream IDs 0 and 7 */
>       master2 {
> -            iommus = <&smmu2 0 0>,
> -                     <&smmu2 7 0>;
> +        iommus = <&smmu2 0 0>,
> +                 <&smmu2 7 0>;
>       };
>   
>       /* device with stream IDs 1, 17, 33 and 49 */
>       master3 {
> -            iommus = <&smmu2 1 0x30>;
> +        iommus = <&smmu2 1 0x30>;
>       };
>   
>   
>       /* ARM MMU-500 with 10-bit stream ID input configuration */
>       smmu3: iommu at ba600000 {
> -            compatible = "arm,mmu-500", "arm,smmu-v2";
> -            reg = <0xba600000 0x10000>;
> -            #global-interrupts = <2>;
> -            interrupts = <0 44 4>,
> -                         <0 45 4>,
> -                         <0 46 4>, /* This is the first context interrupt */
> -                         <0 47 4>,
> -                         <0 48 4>,
> -                         <0 49 4>;
> -            #iommu-cells = <1>;
> -            /* always ignore appended 5-bit TBU number */
> -            stream-match-mask = <0x7c00>;
> +        compatible = "arm,mmu-500", "arm,smmu-v2";
> +        reg = <0xba600000 0x10000>;
> +        #global-interrupts = <2>;
> +        interrupts = <0 44 4>,
> +                     <0 45 4>,
> +                     <0 46 4>, /* This is the first context interrupt */
> +                     <0 47 4>,
> +                     <0 48 4>,
> +                     <0 49 4>;

If you want to squash another change,

0 xx 4
to
GIC_SPI xx IRQ_TYPE_LEVEL_HIGH

anyway, with or without:

Reviewed-by: David Heidelberg <david at ixit.cz>

> +        #iommu-cells = <1>;
> +        /* always ignore appended 5-bit TBU number */
> +        stream-match-mask = <0x7c00>;
>       };
>   
>       bus {
> -            /* bus whose child devices emit one unique 10-bit stream
> -               ID each, but may master through multiple SMMU TBUs */
> -            iommu-map = <0 &smmu3 0 0x400>;
> -
> -
> +        /* bus whose child devices emit one unique 10-bit stream
> +           ID each, but may master through multiple SMMU TBUs */
> +        iommu-map = <0 &smmu3 0 0x400>;
>       };
>   
>     - |+
> @@ -695,17 +693,17 @@ examples:
>       #include <dt-bindings/interrupt-controller/arm-gic.h>
>       #include <dt-bindings/interrupt-controller/irq.h>
>       smmu4: iommu at d00000 {
> -      compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
> -      reg = <0xd00000 0x10000>;
> +        compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
> +        reg = <0xd00000 0x10000>;
>   
> -      #global-interrupts = <1>;
> -      interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
> -             <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
> -             <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
> -      #iommu-cells = <1>;
> -      power-domains = <&mmcc 0>;
> +        #global-interrupts = <1>;
> +        interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
> +                     <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
> +                     <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
> +        #iommu-cells = <1>;
> +        power-domains = <&mmcc 0>;
>   
> -      clocks = <&mmcc 123>,
> -        <&mmcc 124>;
> -      clock-names = "bus", "iface";
> +        clocks = <&mmcc 123>,
> +                 <&mmcc 124>;
> +        clock-names = "bus", "iface";
>       };
> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> index ea6b0f5f24de..1eac27893b03 100644
> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> @@ -218,13 +218,13 @@ examples:
>       #include <dt-bindings/interrupt-controller/arm-gic.h>
>   
>       iommu: iommu at 10205000 {
> -            compatible = "mediatek,mt8173-m4u";
> -            reg = <0x10205000 0x1000>;
> -            interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
> -            clocks = <&infracfg CLK_INFRA_M4U>;
> -            clock-names = "bclk";
> -            mediatek,infracfg = <&infracfg>;
> -            mediatek,larbs = <&larb0>, <&larb1>, <&larb2>,
> -                             <&larb3>, <&larb4>, <&larb5>;
> -            #iommu-cells = <1>;
> +        compatible = "mediatek,mt8173-m4u";
> +        reg = <0x10205000 0x1000>;
> +        interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
> +        clocks = <&infracfg CLK_INFRA_M4U>;
> +        clock-names = "bclk";
> +        mediatek,infracfg = <&infracfg>;
> +        mediatek,larbs = <&larb0>, <&larb1>, <&larb2>,
> +                         <&larb3>, <&larb4>, <&larb5>;
> +        #iommu-cells = <1>;
>       };
> diff --git a/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml b/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
> index 9f83f851e61a..aaecad32dc9d 100644
> --- a/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/qcom,apq8064-iommu.yaml
> @@ -65,14 +65,14 @@ examples:
>       #include <dt-bindings/interrupt-controller/arm-gic.h>
>   
>       iommu at 7500000 {
> -            compatible = "qcom,apq8064-iommu";
> -            reg = <0x07500000 0x100000>;
> -            interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
> -                         <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
> -            clocks = <&clk SMMU_AHB_CLK>,
> -                     <&clk MDP_AXI_CLK>;
> -            clock-names = "smmu_pclk",
> -                          "iommu_clk";
> -            #iommu-cells = <1>;
> -            qcom,ncb = <2>;
> +        compatible = "qcom,apq8064-iommu";
> +        reg = <0x07500000 0x100000>;
> +        interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
> +                     <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
> +        clocks = <&clk SMMU_AHB_CLK>,
> +                 <&clk MDP_AXI_CLK>;
> +        clock-names = "smmu_pclk",
> +                      "iommu_clk";
> +        #iommu-cells = <1>;
> +        qcom,ncb = <2>;
>       };

-- 
David Heidelberg



From laurent.pinchart at ideasonboard.com  Mon Mar 24 06:03:05 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Mon, 24 Mar 2025 15:03:05 +0200
Subject: [PATCH] dt-bindings: gpio: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
References: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
Message-ID: <20250324130305.GD5113@pendragon.ideasonboard.com>

Hi Krzysztof,

Thank you for the patch.

On Mon, Mar 24, 2025 at 01:53:26PM +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>

> ---
>  .../bindings/gpio/atmel,at91rm9200-gpio.yaml  | 16 ++---
>  .../bindings/gpio/fairchild,74hc595.yaml      | 20 +++---
>  .../devicetree/bindings/gpio/gpio-mxs.yaml    | 70 +++++++++----------
>  .../devicetree/bindings/gpio/nxp,pcf8575.yaml | 24 +++----
>  .../bindings/gpio/realtek,otto-gpio.yaml      |  8 +--
>  .../bindings/gpio/renesas,em-gio.yaml         | 20 +++---
>  .../bindings/gpio/renesas,rcar-gpio.yaml      | 24 +++----
>  .../devicetree/bindings/gpio/sifive,gpio.yaml |  6 +-
>  .../bindings/gpio/toshiba,gpio-visconti.yaml  | 24 +++----
>  .../bindings/gpio/xlnx,gpio-xilinx.yaml       | 48 ++++++-------
>  10 files changed, 130 insertions(+), 130 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
> index 3dd70933ed8e..d810043b56b6 100644
> --- a/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
> +++ b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
> @@ -69,13 +69,13 @@ examples:
>      #include <dt-bindings/interrupt-controller/irq.h>
>  
>      gpio at fffff400 {
> -            compatible = "atmel,at91rm9200-gpio";
> -            reg = <0xfffff400 0x200>;
> -            interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
> -            #gpio-cells = <2>;
> -            gpio-controller;
> -            interrupt-controller;
> -            #interrupt-cells = <2>;
> -            clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
> +        compatible = "atmel,at91rm9200-gpio";
> +        reg = <0xfffff400 0x200>;
> +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
> +        #gpio-cells = <2>;
> +        gpio-controller;
> +        interrupt-controller;
> +        #interrupt-cells = <2>;
> +        clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
>      };
>  ...
> diff --git a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> index 0e5c22929bde..ab35bcf98101 100644
> --- a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> +++ b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> @@ -71,15 +71,15 @@ unevaluatedProperties: false
>  examples:
>    - |
>      spi {
> -            #address-cells = <1>;
> -            #size-cells = <0>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
>  
> -            gpio5: gpio5 at 0 {
> -                    compatible = "fairchild,74hc595";
> -                    reg = <0>;
> -                    gpio-controller;
> -                    #gpio-cells = <2>;
> -                    registers-number = <4>;
> -                    spi-max-frequency = <100000>;
> -            };
> +        gpio5 at 0 {
> +            compatible = "fairchild,74hc595";
> +            reg = <0>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            registers-number = <4>;
> +            spi-max-frequency = <100000>;
> +        };
>      };
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
> index 8ff54369d16c..b58e08c8ecd8 100644
> --- a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
> +++ b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml
> @@ -84,52 +84,52 @@ examples:
>          reg = <0x80018000 0x2000>;
>  
>          gpio at 0 {
> -                compatible = "fsl,imx28-gpio";
> -                reg = <0>;
> -                interrupts = <127>;
> -                gpio-controller;
> -                #gpio-cells = <2>;
> -                interrupt-controller;
> -                #interrupt-cells = <2>;
> +            compatible = "fsl,imx28-gpio";
> +            reg = <0>;
> +            interrupts = <127>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
>          };
>  
>          gpio at 1 {
> -                compatible = "fsl,imx28-gpio";
> -                reg = <1>;
> -                interrupts = <126>;
> -                gpio-controller;
> -                #gpio-cells = <2>;
> -                interrupt-controller;
> -                #interrupt-cells = <2>;
> +            compatible = "fsl,imx28-gpio";
> +            reg = <1>;
> +            interrupts = <126>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
>          };
>  
>          gpio at 2 {
> -                compatible = "fsl,imx28-gpio";
> -                reg = <2>;
> -                interrupts = <125>;
> -                gpio-controller;
> -                #gpio-cells = <2>;
> -                interrupt-controller;
> -                #interrupt-cells = <2>;
> +            compatible = "fsl,imx28-gpio";
> +            reg = <2>;
> +            interrupts = <125>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
>          };
>  
>          gpio at 3 {
> -                compatible = "fsl,imx28-gpio";
> -                reg = <3>;
> -                interrupts = <124>;
> -                gpio-controller;
> -                #gpio-cells = <2>;
> -                interrupt-controller;
> -                #interrupt-cells = <2>;
> +            compatible = "fsl,imx28-gpio";
> +            reg = <3>;
> +            interrupts = <124>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
>          };
>  
>          gpio at 4 {
> -                compatible = "fsl,imx28-gpio";
> -                reg = <4>;
> -                interrupts = <123>;
> -                gpio-controller;
> -                #gpio-cells = <2>;
> -                interrupt-controller;
> -                #interrupt-cells = <2>;
> +            compatible = "fsl,imx28-gpio";
> +            reg = <4>;
> +            interrupts = <123>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
>          };
>      };
> diff --git a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
> index 8bca574bb66d..5a6ecaa7b44b 100644
> --- a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
> +++ b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
> @@ -128,17 +128,17 @@ additionalProperties: false
>  examples:
>    - |
>      i2c {
> -            #address-cells = <1>;
> -            #size-cells = <0>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
>  
> -            pcf8575: gpio at 20 {
> -                    compatible = "nxp,pcf8575";
> -                    reg = <0x20>;
> -                    interrupt-parent = <&irqpin2>;
> -                    interrupts = <3 0>;
> -                    gpio-controller;
> -                    #gpio-cells = <2>;
> -                    interrupt-controller;
> -                    #interrupt-cells = <2>;
> -            };
> +        gpio at 20 {
> +            compatible = "nxp,pcf8575";
> +            reg = <0x20>;
> +            interrupt-parent = <&irqpin2>;
> +            interrupts = <3 0>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +        };
>      };
> diff --git a/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
> index 39fd959c45d2..728099c65824 100644
> --- a/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
> +++ b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
> @@ -81,7 +81,7 @@ dependencies:
>  
>  examples:
>    - |
> -      gpio at 3500 {
> +    gpio at 3500 {
>          compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
>          reg = <0x3500 0x1c>;
>          gpio-controller;
> @@ -91,9 +91,9 @@ examples:
>          #interrupt-cells = <2>;
>          interrupt-parent = <&rtlintc>;
>          interrupts = <23>;
> -      };
> +    };
>    - |
> -      gpio at 3300 {
> +    gpio at 3300 {
>          compatible = "realtek,rtl9300-gpio", "realtek,otto-gpio";
>          reg = <0x3300 0x1c>, <0x3338 0x8>;
>          gpio-controller;
> @@ -103,6 +103,6 @@ examples:
>          #interrupt-cells = <2>;
>          interrupt-parent = <&rtlintc>;
>          interrupts = <13>;
> -      };
> +    };
>  
>  ...
> diff --git a/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml b/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
> index 8bdef812c87c..49fb8f613ead 100644
> --- a/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
> +++ b/Documentation/devicetree/bindings/gpio/renesas,em-gio.yaml
> @@ -57,14 +57,14 @@ examples:
>    - |
>      #include <dt-bindings/interrupt-controller/arm-gic.h>
>      gpio0: gpio at e0050000 {
> -            compatible = "renesas,em-gio";
> -            reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
> -            interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
> -                         <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
> -            gpio-controller;
> -            #gpio-cells = <2>;
> -            gpio-ranges = <&pfc 0 0 32>;
> -            ngpios = <32>;
> -            interrupt-controller;
> -            #interrupt-cells = <2>;
> +        compatible = "renesas,em-gio";
> +        reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
> +        interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
> +                     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
> +        gpio-controller;
> +        #gpio-cells = <2>;
> +        gpio-ranges = <&pfc 0 0 32>;
> +        ngpios = <32>;
> +        interrupt-controller;
> +        #interrupt-cells = <2>;
>      };
> diff --git a/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml b/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
> index cc7a950a6030..d32e103a64aa 100644
> --- a/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
> +++ b/Documentation/devicetree/bindings/gpio/renesas,rcar-gpio.yaml
> @@ -138,16 +138,16 @@ examples:
>      #include <dt-bindings/interrupt-controller/arm-gic.h>
>      #include <dt-bindings/power/r8a77470-sysc.h>
>      gpio3: gpio at e6053000 {
> -            compatible = "renesas,gpio-r8a77470", "renesas,rcar-gen2-gpio";
> -            reg = <0xe6053000 0x50>;
> -            interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
> -            clocks = <&cpg CPG_MOD 909>;
> -            power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
> -            resets = <&cpg 909>;
> -            gpio-controller;
> -            #gpio-cells = <2>;
> -            gpio-ranges = <&pfc 0 96 30>;
> -            gpio-reserved-ranges = <17 10>;
> -            interrupt-controller;
> -            #interrupt-cells = <2>;
> +        compatible = "renesas,gpio-r8a77470", "renesas,rcar-gen2-gpio";
> +        reg = <0xe6053000 0x50>;
> +        interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
> +        clocks = <&cpg CPG_MOD 909>;
> +        power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
> +        resets = <&cpg 909>;
> +        gpio-controller;
> +        #gpio-cells = <2>;
> +        gpio-ranges = <&pfc 0 96 30>;
> +        gpio-reserved-ranges = <17 10>;
> +        interrupt-controller;
> +        #interrupt-cells = <2>;
>       };
> diff --git a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
> index fc095646adea..4bdc201b719e 100644
> --- a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
> +++ b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
> @@ -76,8 +76,8 @@ additionalProperties: false
>  
>  examples:
>    - |
> -      #include <dt-bindings/clock/sifive-fu540-prci.h>
> -      gpio at 10060000 {
> +    #include <dt-bindings/clock/sifive-fu540-prci.h>
> +    gpio at 10060000 {
>          compatible = "sifive,fu540-c000-gpio", "sifive,gpio0";
>          interrupt-parent = <&plic>;
>          interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, <14>, <15>, <16>,
> @@ -88,6 +88,6 @@ examples:
>          #gpio-cells = <2>;
>          interrupt-controller;
>          #interrupt-cells = <2>;
> -      };
> +    };
>  
>  ...
> diff --git a/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml b/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
> index b085450b527f..712063417bc8 100644
> --- a/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
> +++ b/Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
> @@ -48,22 +48,22 @@ additionalProperties: false
>  
>  examples:
>    - |
> -      #include <dt-bindings/interrupt-controller/irq.h>
> -      #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>  
> -      soc {
> +    soc {
>          #address-cells = <2>;
>          #size-cells = <2>;
>  
>          gpio: gpio at 28020000 {
> -          compatible = "toshiba,gpio-tmpv7708";
> -          reg = <0 0x28020000 0 0x1000>;
> -          #gpio-cells = <0x2>;
> -          gpio-ranges = <&pmux 0 0 32>;
> -          gpio-controller;
> -          interrupt-controller;
> -          #interrupt-cells = <2>;
> -          interrupt-parent = <&gic>;
> +            compatible = "toshiba,gpio-tmpv7708";
> +            reg = <0 0x28020000 0 0x1000>;
> +            #gpio-cells = <0x2>;
> +            gpio-ranges = <&pmux 0 0 32>;
> +            gpio-controller;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +            interrupt-parent = <&gic>;
>          };
> -      };
> +    };
>  ...
> diff --git a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
> index d3d8a2e143ed..8fbf12ca067e 100644
> --- a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
> +++ b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
> @@ -126,29 +126,29 @@ examples:
>    - |
>      #include <dt-bindings/interrupt-controller/arm-gic.h>
>  
> -        gpio at a0020000 {
> -            compatible = "xlnx,xps-gpio-1.00.a";
> -            reg = <0xa0020000 0x10000>;
> -            #gpio-cells = <2>;
> -            #interrupt-cells = <0x2>;
> -            clocks = <&zynqmp_clk 71>;
> -            gpio-controller;
> -            interrupt-controller;
> -            interrupt-names = "ip2intc_irpt";
> -            interrupt-parent = <&gic>;
> -            interrupts = <0 89 4>;
> -            xlnx,all-inputs = <0x0>;
> -            xlnx,all-inputs-2 = <0x0>;
> -            xlnx,all-outputs = <0x0>;
> -            xlnx,all-outputs-2 = <0x0>;
> -            xlnx,dout-default = <0x0>;
> -            xlnx,dout-default-2 = <0x0>;
> -            xlnx,gpio-width = <0x20>;
> -            xlnx,gpio2-width = <0x20>;
> -            xlnx,interrupt-present = <0x1>;
> -            xlnx,is-dual = <0x1>;
> -            xlnx,tri-default = <0xFFFFFFFF>;
> -            xlnx,tri-default-2 = <0xFFFFFFFF>;
> -        };
> +    gpio at a0020000 {
> +        compatible = "xlnx,xps-gpio-1.00.a";
> +        reg = <0xa0020000 0x10000>;
> +        #gpio-cells = <2>;
> +        #interrupt-cells = <0x2>;
> +        clocks = <&zynqmp_clk 71>;
> +        gpio-controller;
> +        interrupt-controller;
> +        interrupt-names = "ip2intc_irpt";
> +        interrupt-parent = <&gic>;
> +        interrupts = <0 89 4>;
> +        xlnx,all-inputs = <0x0>;
> +        xlnx,all-inputs-2 = <0x0>;
> +        xlnx,all-outputs = <0x0>;
> +        xlnx,all-outputs-2 = <0x0>;
> +        xlnx,dout-default = <0x0>;
> +        xlnx,dout-default-2 = <0x0>;
> +        xlnx,gpio-width = <0x20>;
> +        xlnx,gpio2-width = <0x20>;
> +        xlnx,interrupt-present = <0x1>;
> +        xlnx,is-dual = <0x1>;
> +        xlnx,tri-default = <0xFFFFFFFF>;
> +        xlnx,tri-default-2 = <0xFFFFFFFF>;
> +    };
>  
>  ...

-- 
Regards,

Laurent Pinchart


From ilpo.jarvinen at linux.intel.com  Mon Mar 24 06:05:41 2025
From: ilpo.jarvinen at linux.intel.com (=?UTF-8?q?Ilpo=20J=C3=A4rvinen?=)
Date: Mon, 24 Mar 2025 15:05:41 +0200 (EET)
Subject: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround
 is not required
In-Reply-To: <20250324062647.1891896-2-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com> <20250324062647.1891896-2-hongxing.zhu@nxp.com>
Message-ID: <73205114-bdb5-2995-e00a-7df7046ea91d@linux.intel.com>

On Mon, 24 Mar 2025, Richard Zhu wrote:

> The current link setup procedure is more like one workaround to detect
> the device behind PCIe switches on some i.MX6 platforms.
> 
> To describe more accurately, change the flag name from
> IMX_PCIE_FLAG_IMX_SPEED_CHANGE to IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.
> 
> Then, start PCIe link directly when this flag is not set on i.MX7 or
> later paltforms to simple and speed up link training.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
>  1 file changed, 14 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index c1f7904e3600..aa5c3f235995 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -91,7 +91,7 @@ enum imx_pcie_variants {
>  };
>  
>  #define IMX_PCIE_FLAG_IMX_PHY			BIT(0)
> -#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE		BIT(1)
> +#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND	BIT(1)

WORDaround ?? :-)

-- 
 i.

>  #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)
>  #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3)
>  #define IMX_PCIE_FLAG_HAS_APP_RESET		BIT(4)
> @@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
>  	u32 tmp;
>  	int ret;
>  
> +	if (!(imx_pcie->drvdata->flags &
> +	    IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
> +		imx_pcie_ltssm_enable(dev);
> +		return 0;
> +	}
> +
>  	/*
>  	 * Force Gen1 operation when starting the link.  In case the link is
>  	 * started in Gen2 mode, there is a possibility the devices on the
> @@ -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
>  		dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
>  		dw_pcie_dbi_ro_wr_dis(pci);
>  
> -		if (imx_pcie->drvdata->flags &
> -		    IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
> -
> -			/*
> -			 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
> -			 * from i.MX6 family when no link speed transition
> -			 * occurs and we go Gen1 -> yep, Gen1. The difference
> -			 * is that, in such case, it will not be cleared by HW
> -			 * which will cause the following code to report false
> -			 * failure.
> -			 */
> -			ret = imx_pcie_wait_for_speed_change(imx_pcie);
> -			if (ret) {
> -				dev_err(dev, "Failed to bring link up!\n");
> -				goto err_reset_phy;
> -			}
> +		ret = imx_pcie_wait_for_speed_change(imx_pcie);
> +		if (ret) {
> +			dev_err(dev, "Failed to bring link up!\n");
> +			goto err_reset_phy;
>  		}
>  
>  		/* Make sure link training is finished as well! */
> @@ -1665,7 +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6Q] = {
>  		.variant = IMX6Q,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_BROKEN_SUSPEND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.dbi_length = 0x200,
> @@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6SX] = {
>  		.variant = IMX6SX,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.gpr = "fsl,imx6q-iomuxc-gpr",
>  		.ltssm_off = IOMUXC_GPR12,
> @@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  	[IMX6QP] = {
>  		.variant = IMX6QP,
>  		.flags = IMX_PCIE_FLAG_IMX_PHY |
> -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
>  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
>  		.dbi_length = 0x200,
>  		.gpr = "fsl,imx6q-iomuxc-gpr",
> 


From tudor.ambarus at linaro.org  Mon Mar 24 06:23:00 2025
From: tudor.ambarus at linaro.org (Tudor Ambarus)
Date: Mon, 24 Mar 2025 13:23:00 +0000
Subject: [PATCH 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250321-acpm-atomic-v1-2-fb887bde7e61@linaro.org>
References: <20250321-acpm-atomic-v1-0-fb887bde7e61@linaro.org>
 <20250321-acpm-atomic-v1-2-fb887bde7e61@linaro.org>
Message-ID: <9b372589-1c52-4f3d-9f5b-8f729489b545@linaro.org>



On 3/21/25 4:40 PM, Andr? Draszik wrote:
> We need to access the PMIC during late system shutdown and at that time
> we are not allowed to sleep anymore.
> 
> To make this case work, detect this condition and use busy waiting via
> udelay() instead of usleep_range() in that situation.
> 
> The code isn't switched over to udelay() unconditionally so as to not
> waste resources during normal operation. acpm_may_sleep() was heavily
> inspired by the I2C subsystem's i2c_in_atomic_xfer_mode().
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> 
> ---
> udelay(10) causes a checkpatch warning (it suggests to use
> usleep_range() instead for usec >= 10), but that's exactly what we can
> not do.
> Reducing the udelay to be smaller will generally cause the loop to be
> iterated more than once, which I wanted to avoid.
> I could reflow the code to hide the actual value from checkpatch, e.g.
> with the help of a local variable if that is preferred to ignoring the
> checkpatch warning.
> ---
>  drivers/firmware/samsung/exynos-acpm.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> index d7ed6b77a957af5db5beba7deecce13ac7b30fd2..33cde6e88e2c0773fdd36c80927c77d3bcb44135 100644
> --- a/drivers/firmware/samsung/exynos-acpm.c
> +++ b/drivers/firmware/samsung/exynos-acpm.c
> @@ -15,6 +15,8 @@
>  #include <linux/firmware/samsung/exynos-acpm-protocol.h>
>  #include <linux/io.h>
>  #include <linux/iopoll.h>
> +#include <linux/irqflags.h>
> +#include <linux/kernel.h>
>  #include <linux/mailbox/exynos-message.h>
>  #include <linux/mailbox_client.h>
>  #include <linux/module.h>
> @@ -24,6 +26,7 @@
>  #include <linux/of_address.h>
>  #include <linux/of_platform.h>
>  #include <linux/platform_device.h>
> +#include <linux/preempt.h>
>  #include <linux/slab.h>
>  #include <linux/types.h>
>  
> @@ -272,6 +275,17 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
>  	return 0;
>  }
>  
> +/*
> + * When ACPM transfers happen very late, e.g. to access a PMIC when powering
> + * down, we can not sleep. We do want to sleep in the normal case, though, to
> + * avoid wasting CPU cycles!
> + */
> +static bool acpm_may_sleep(void)
> +{
> +	return system_state <= SYSTEM_RUNNING ||
> +		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
> +}
> +
>  /**
>   * acpm_dequeue_by_polling() - RX dequeue by polling.
>   * @achan:	ACPM channel info.
> @@ -299,7 +313,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
>  			return 0;
>  
>  		/* Determined experimentally. */
> -		usleep_range(20, 30);
> +		if (!acpm_may_sleep())
> +			udelay(10);
> +		else
> +			usleep_range(20, 30);
>  	} while (!ktime_after(ktime_get(), timeout));
>  
>  	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
> 



From yeoreum.yun at arm.com  Mon Mar 24 06:17:42 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Mon, 24 Mar 2025 13:17:42 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
 <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
 <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
 <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>
Message-ID: <Z+FbdpQ5wfx2sDjs@e129823.arm.com>

Hi Mike,

> > > >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > > > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> > > >
> > > > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > > > +{
> > > > +       if (enable)
> > > > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > > > +
> > >
> > > Not sure why we have an "enable" parameter here - it completely
> > > changes the meaning of the function - with no comment at the start.
> >
> > Sorry. But what I intended is to distinguish
> >     - activation of config
> >     - enable of activated config.
> > Because, current coresight doesn't grab the module reference on enable of activate config,
> > But It grabs that reference only in activation.
> > That's why I used to "enable" parameter to distinguish this
> > while I integrate with module_owner count.
> >
> > > >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> > > >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > > > -                       atomic_dec(&config_desc->active_cnt);
> > > >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > > > -                       cscfg_owner_put(config_desc->load_owner);
> > > > +                       cscfg_config_desc_put(config_desc);
> > > >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> > > >                         break;
> > > >                 }
> > > > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > >                                      unsigned long cfg_hash, int preset)
> > > >  {
> > > >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > > > -       const struct cscfg_config_desc *config_desc;
> > > > +       struct cscfg_config_desc *config_desc;
> > > >         unsigned long flags;
> > > >         int err = 0;
> > > >
> > > > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> > > >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > > >                 config_desc = config_csdev_item->config_desc;
> > > > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > > > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > > > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > > > +                               cscfg_config_desc_get(config_desc, true)) {
> > > >
> > > This obfuscates the logic of the comparisons without good reason. With
> > > the true parameter, the function does no "get" operation but just
> > > replicates the logic being replaced - checking the active_cnt is
> > > non-zero.
> > >
> > > Restore this to the original logic to make it readable again
> >
> > It's not a replicates of comparsion logic, but if true,
>
> sorry - missed that point .

No worries :) Thanks!

>
> > It get the reference of active_cnt but not get module reference.
> > The fundemental fault in the UAF becase of just "atomic_read()"
> > so, it should hold reference in here.
> >
> > So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
> > I think there're two way to modfiy.
> >
> >     1. cscfg_config_desc_get()/put() always grab/drop the module count.
> >     2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
> >         with cscfg_owner_get()/put()
> >
> > Any thougt?
> >
> > Thanks!
> >
> >
>
> The get and put functions are asymmetrical w.r.t. owner.
>
> The put will put owner if active count decrements to 0,
> The get if not on enable path will put owner unconditionally.
>
> This means that the caller has to work out the correct input conditions.
>
> Might be better if:-
>
> get_desc()
> {
>     if (! desc->refcnt) {
>        if (!get_owner())
>            return false;
>    }
>    desc->refcnt++;
>     return true;
> }
>

I think it could be with atomic_fetch_add(),
although, it changes the order to get reference count
(config_dec->active_cnt, owner) cscfg_mutex will make sure
live of memory for csdev_config while unloading module
and give a change to get result of get_owner.

Thanks for sharing idea ;)

I'll respin it.

> put_desc()
> {
>    desc->refcnt--;
>   if (! desc->refcnt)
>     put_owner()
> }
>
> and then change the enable_active_cfg matching logic to
>
> if ( (desc->refcnt) && (desc->hash == hash) && get_desc()) {
>      < set active cfg>
> }
>
>
>
> --
> Mike Leach
> Principal Engineer, ARM Ltd.
> Manchester Design Centre. UK


From geert at linux-m68k.org  Mon Mar 24 06:25:10 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 24 Mar 2025 14:25:10 +0100
Subject: [PATCH] dt-bindings: gpio: Correct indentation and style in DTS example
In-Reply-To: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
References: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
Message-ID: <CAMuHMdVKFgm_44XXq7Zq8yqosBCQc1CK9dkJoz4nLQ=aDNx-Yg@mail.gmail.com>

On Mon, 24 Mar 2025 at 13:53, Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
>
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From geert at linux-m68k.org  Mon Mar 24 06:27:27 2025
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 24 Mar 2025 14:27:27 +0100
Subject: [PATCH 1/2] dt-bindings: PCI: Correct indentation and style in
 DTS example
In-Reply-To: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
References: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
Message-ID: <CAMuHMdXOND_TJqGckmGVB2jda=xxZmY8C5q-QAzvztcW0yPuMg@mail.gmail.com>

Hi Krzysztof,

Thanks for your patch!

On Mon, 24 Mar 2025 at 13:52, Krzysztof Kozlowski
<krzysztof.kozlowski at linaro.org> wrote:
>
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.

+ While re-indenting, drop unused labels.

> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From patrice.chotard at foss.st.com  Mon Mar 24 06:29:06 2025
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Mon, 24 Mar 2025 14:29:06 +0100
Subject: [PATCH v6 2/7] dt-bindings: memory-controllers: Add STM32 Octo
 Memory Manager controller
In-Reply-To: <20250321140200.GA3192411-robh@kernel.org>
References: <20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com>
 <20250321-upstream_ospi_v6-v6-2-37bbcab43439@foss.st.com>
 <20250321140200.GA3192411-robh@kernel.org>
Message-ID: <322a2687-eae3-44da-adb4-8a6422f690e5@foss.st.com>



On 3/21/25 15:02, Rob Herring wrote:
> On Fri, Mar 21, 2025 at 10:32:22AM +0100, Patrice Chotard wrote:
>> Add bindings for STM32 Octo Memory Manager (OMM) controller.
>>
>> OMM manages:
>>   - the muxing between 2 OSPI busses and 2 output ports.
>>     There are 4 possible muxing configurations:
>>       - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
>>         output is on port 2
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 1
>>       - swapped mode (no multiplexing), OSPI1 output is on port 2,
>>         OSPI2 output is on port 1
>>       - OSPI1 and OSPI2 are multiplexed over the same output port 2
>>   - the split of the memory area shared between the 2 OSPI instances.
>>   - chip select selection override.
>>   - the time between 2 transactions in multiplexed mode.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
>> ---
>>  .../memory-controllers/st,stm32mp25-omm.yaml       | 227 +++++++++++++++++++++
>>  1 file changed, 227 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..2f8fa7569009369ebd077e4c6f4ab409a91838a5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
>> @@ -0,0 +1,227 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/memory-controllers/st,stm32mp25-omm.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: STM32 Octo Memory Manager (OMM)
>> +
>> +maintainers:
>> +  - Patrice Chotard <patrice.chotard at foss.st.com>
>> +
>> +description: |
>> +  The STM32 Octo Memory Manager is a low-level interface that enables an
>> +  efficient OCTOSPI pin assignment with a full I/O matrix (before alternate
>> +  function map) and multiplex of single/dual/quad/octal SPI interfaces over
>> +  the same bus. It Supports up to:
>> +    - Two single/dual/quad/octal SPI interfaces
>> +    - Two ports for pin assignment
>> +
>> +properties:
>> +  compatible:
>> +    const: st,stm32mp25-omm
>> +
>> +  "#address-cells":
>> +    const: 2
>> +
>> +  "#size-cells":
>> +    const: 1
>> +
>> +  ranges:
>> +    description: |
>> +      Reflects the memory layout with four integer values per OSPI instance.
> 
> You say 4 here...

Hi Rob,

Yes, each range is composed by 4 integers: 

ranges = <0 0 0x40430000 0x400>,
         <1 0 0x40440000 0x400>;

And we got 2 ranges entry, one for each OSPI instance.

Maybe to avoid confusion, i can just update the description as following:
+    description: |
+      Reflects the memory layout per OSPI instance.

Is it ok for you ?

> 
>> +      Format:
>> +      <chip-select> 0 <registers base address> <size>
>> +    minItems: 2
>> +    maxItems: 2
> 
> And 2 here. I'm confused. From the example it doesn't look like you are 

see my answer just above.

> using ranges correctly. If you are parsing it yourself, that's wrong. 
> More below.
> 
>> +
>> +  reg:
>> +    items:
>> +      - description: OMM registers
>> +      - description: OMM memory map area
>> +
>> +  reg-names:
>> +    items:
>> +      - const: regs
>> +      - const: memory_map
>> +
>> +  memory-region:
>> +    description: |
>> +      Memory region shared between the 2 OCTOSPI instance.
>> +      One or two phandle to a node describing a memory mapped region
>> +      depending of child number.
>> +    minItems: 1
>> +    maxItems: 2
>> +
>> +  memory-region-names:
>> +    description: |
> 
> Don't need '|'.

Ok

> 
>> +      OCTOSPI instance's name to which memory region is associated
> 
> That doesn't really tell me anything.

We must identify to which OSPI instance the memory region belongs to.
This is needed to configure/check the memory region area split between
these 2 OSPI instance.

Must i update the description ?

> 
>> +    items:
>> +      enum: [ospi1, ospi2]
>> +    minItems: 1
>> +    maxItems: 2
>> +
>> +  clocks:
>> +    minItems: 3
>> +    maxItems: 3
>> +
>> +  clock-names:
>> +    items:
>> +      enum: [omm, ospi1, ospi2]
> 
> Define the order.

Ok, i will update as following:

  clock-names:
    items:
      - const: omm
      - const: ospi1
      - const: ospi2

> 
>> +    minItems: 3
>> +    maxItems: 3
>> +
>> +  resets:
>> +    minItems: 3
>> +    maxItems: 3
>> +
>> +  reset-names:
>> +    items:
>> +      enum: [omm, ospi1, ospi2]
> 
> Define the order.

ok, will update as below:

  reset-names:
    items:
      - const: omm
      - const: ospi1
      - const: ospi2

> 
>> +    minItems: 3
>> +    maxItems: 3
>> +
>> +  access-controllers:
>> +    maxItems: 1
>> +
>> +  st,syscfg-amcr:
>> +    $ref: /schemas/types.yaml#/definitions/phandle-array
>> +    description: |
>> +      The Address Mapping Control Register (AMCR) is used to split the 256MB
>> +      memory map area shared between the 2 OSPI instance. The Octo Memory
>> +      Manager sets the AMCR depending of the memory-region configuration.
>> +      The memory split bitmask description is:
>> +        - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped
>> +        - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes)
>> +        - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes)
>> +        - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes)
>> +        - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes)
>> +    items:
>> +      - description: phandle to syscfg
>> +      - description: register offset within syscfg
>> +      - description: register bitmask for memory split
>> +
>> +  st,omm-req2ack-ns:
>> +    description: |
> 
> Don't need '|'.

ok

> 
>> +      In multiplexed mode (MUXEN = 1), this field defines the time in
>> +      nanoseconds between two transactions.
>> +    default: 0
>> +
>> +  st,omm-cssel-ovr:
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    description: |
>> +      Configure the chip select selector override for the 2 OCTOSPIs.
>> +      - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
>> +      - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
>> +      - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
>> +      - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
>> +    minimum: 0
>> +    maximum: 3
>> +    default: 0
>> +
>> +  st,omm-mux:
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    description: |
>> +      Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports.
>> +      - 0: direct mode
>> +      - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
>> +      - 2: swapped mode
>> +      - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
>> +    minimum: 0
>> +    maximum: 3
>> +    default: 0
>> +
>> +  power-domains:
>> +    maxItems: 1
>> +
>> +patternProperties:
>> +  ^spi@[a-f0-9]+$:

Due to your comments below, schema will be updated as following:
    ^spi@[0-9]:

>> +    type: object
>> +    $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
>> +    description: Required spi child node
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - "#address-cells"
>> +  - "#size-cells"
>> +  - clocks
>> +  - clock-names
>> +  - resets
>> +  - reset-names
>> +  - st,syscfg-amcr
>> +  - ranges
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/clock/st,stm32mp25-rcc.h>
>> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>> +    #include <dt-bindings/reset/st,stm32mp25-rcc.h>
>> +    ommanager at 40500000 {
>> +      compatible = "st,stm32mp25-omm";
>> +      reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
>> +      reg-names = "regs", "memory_map";
>> +      ranges = <0 0 0x40430000 0x400>,
>> +               <1 0 0x40440000 0x400>;
> 
>> +      #address-cells = <2>;
>> +      #size-cells = <1>;
>> +
> 
>> +      spi at 40430000 {
> 
> ranges is okay, but the unit-address is wrong here. It should be based 
> on reg below. So 'spi at 0' or 'spi at 0,0' since chip select is a distinct 
> field. It's up to you, but you need to define the format in the schema.


Ok i will use spi at 0

> 
>> +        compatible = "st,stm32mp25-ospi";
>> +        reg = <0 0 0x400>;
>> +        memory-region = <&mm_ospi1>;
>> +        interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
>> +        dmas = <&hpdma 2 0x62 0x00003121 0x0>,
>> +               <&hpdma 2 0x42 0x00003112 0x0>;
>> +        dma-names = "tx", "rx";
>> +        clocks = <&scmi_clk CK_SCMI_OSPI1>;
>> +        resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
>> +        access-controllers = <&rifsc 74>;
>> +        power-domains = <&CLUSTER_PD>;
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +        st,syscfg-dlyb = <&syscfg 0x1000>;
>> +      };
>> +
>> +      spi at 40440000 {
> 
> spi at 1,0

ok, will use spi at 1

Thanks
Patrice

> 
>> +        compatible = "st,stm32mp25-ospi";
>> +        reg = <1 0 0x400>;
>> +        memory-region = <&mm_ospi1>;
>> +        interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
>> +        dmas = <&hpdma 3 0x62 0x00003121 0x0>,
>> +               <&hpdma 3 0x42 0x00003112 0x0>;
>> +        dma-names = "tx", "rx";
>> +        clocks = <&scmi_clk CK_KER_OSPI2>;
>> +        resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>;
>> +        access-controllers = <&rifsc 75>;
>> +        power-domains = <&CLUSTER_PD>;
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +        st,syscfg-dlyb = <&syscfg 0x1000>;
>> +      };
>> +    };
>>
>> -- 
>> 2.25.1
>>


From mailhol.vincent at wanadoo.fr  Mon Mar 24 06:44:39 2025
From: mailhol.vincent at wanadoo.fr (Vincent Mailhol)
Date: Mon, 24 Mar 2025 22:44:39 +0900
Subject: [PATCH] can: rockchip_canfd: fix broken quirks checks
In-Reply-To: <20250324114416.10160-1-o451686892@gmail.com>
References: <20250324114416.10160-1-o451686892@gmail.com>
Message-ID: <8bd91034-cc4f-435d-86ef-cc76fa0a3612@wanadoo.fr>

Hi Weizhao,

Thanks for the patch.

On 24/03/2025 at 20:44, Weizhao Ouyang wrote:
> First get the devtype_data then check quirks.
> 
> Fixes: bbdffb341498 ("can: rockchip_canfd: add quirk for broken CAN-FD support")
> Signed-off-by: Weizhao Ouyang <o451686892 at gmail.com>

Reviewed-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>



From amergnat at baylibre.com  Mon Mar 24 06:54:08 2025
From: amergnat at baylibre.com (Alexandre Mergnat)
Date: Mon, 24 Mar 2025 14:54:08 +0100
Subject: [PATCH RESEND v2] arm64: dts: mediatek: add mmc2 support for
 mt8365-evk
Message-ID: <20250109-mmc2-support-v2-1-5f660c809610@baylibre.com>

Adds support for the MMC2 interface on the MT8365 EVK board.
It introduces a fixed regulator for the MMC2 VDD33 supply and configures
the MMC2 node with a 4-bit bus width, high-speed capabilities, UHS
modes, and appropriate power supplies. Enabled SDIO IRQ, wakeup source,
and kept power during suspend (to save firmware module) for wireless
chip functionality.

Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
---
Changes in v2:
- Apply alphabetical order to pinctrl property items.
- Improve commit message
- Link to v1: https://lore.kernel.org/r/20250109-mmc2-support-v1-1-9b9d1b1ae35d at baylibre.com
---
 arch/arm64/boot/dts/mediatek/mt8365-evk.dts | 103 +++++++++++++++++++++++++---
 1 file changed, 94 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
index 7d90112a7e274..a87f1b3ed6500 100644
--- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
@@ -53,6 +53,15 @@ memory at 40000000 {
 		reg = <0 0x40000000 0 0xc0000000>;
 	};
 
+	mmc2_vdd33: mmc2_vdd33-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "mmc2_vdd33";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pio 121 0>;
+		enable-active-high;
+	};
+
 	usb_otg_vbus: regulator-0 {
 		compatible = "regulator-fixed";
 		regulator-name = "otg_vbus";
@@ -197,6 +206,28 @@ &mmc1 {
 	status = "okay";
 };
 
+&mmc2 {
+	assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL>;
+	assigned-clocks = <&topckgen CLK_TOP_MSDC50_2_SEL>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cap-sdio-irq;
+	hs400-ds-delay = <0x12012>;
+	keep-power-in-suspend;
+	max-frequency = <200000000>;
+	non-removable;
+	pinctrl-0 = <&mmc2_default_pins>;
+	pinctrl-1 = <&mmc2_uhs_pins>;
+	pinctrl-names = "default", "state_uhs";
+	sd-uhs-sdr104;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	vmmc-supply = <&mmc2_vdd33>;
+	vqmmc-supply = <&mt6357_vcn18_reg>;
+	wakeup-source;
+	status = "okay";
+};
+
 &mt6357_pmic {
 	interrupts-extended = <&pio 145 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-controller;
@@ -324,8 +355,8 @@ cmd-dat-pins {
 				 <MT8365_PIN_94_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
 				 <MT8365_PIN_93_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
 				 <MT8365_PIN_98_MSDC0_CMD__FUNC_MSDC0_CMD>;
-			input-enable;
 			bias-pull-up;
+			input-enable;
 		};
 
 		rst-pins {
@@ -337,8 +368,8 @@ rst-pins {
 	mmc0_uhs_pins: mmc0-uhs-pins {
 		clk-pins {
 			pinmux = <MT8365_PIN_99_MSDC0_CLK__FUNC_MSDC0_CLK>;
-			drive-strength = <MTK_DRIVE_10mA>;
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 
 		cmd-dat-pins {
@@ -351,21 +382,21 @@ cmd-dat-pins {
 				 <MT8365_PIN_94_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
 				 <MT8365_PIN_93_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
 				 <MT8365_PIN_98_MSDC0_CMD__FUNC_MSDC0_CMD>;
-			input-enable;
-			drive-strength = <MTK_DRIVE_10mA>;
 			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+			drive-strength = <MTK_DRIVE_10mA>;
+			input-enable;
 		};
 
 		ds-pins {
 			pinmux = <MT8365_PIN_104_MSDC0_DSL__FUNC_MSDC0_DSL>;
-			drive-strength = <MTK_DRIVE_10mA>;
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 
 		rst-pins {
 			pinmux = <MT8365_PIN_97_MSDC0_RSTB__FUNC_MSDC0_RSTB>;
-			drive-strength = <MTK_DRIVE_10mA>;
 			bias-pull-up;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
@@ -386,16 +417,16 @@ cmd-dat-pins {
 				 <MT8365_PIN_91_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
 				 <MT8365_PIN_92_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
 				 <MT8365_PIN_87_MSDC1_CMD__FUNC_MSDC1_CMD>;
-			input-enable;
 			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+			input-enable;
 		};
 	};
 
 	mmc1_uhs_pins: mmc1-uhs-pins {
 		clk-pins {
 			pinmux = <MT8365_PIN_88_MSDC1_CLK__FUNC_MSDC1_CLK>;
-			drive-strength = <8>;
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <8>;
 		};
 
 		cmd-dat-pins {
@@ -404,9 +435,63 @@ cmd-dat-pins {
 				 <MT8365_PIN_91_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
 				 <MT8365_PIN_92_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
 				 <MT8365_PIN_87_MSDC1_CMD__FUNC_MSDC1_CMD>;
-			input-enable;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
 			drive-strength = <6>;
+			input-enable;
+		};
+	};
+
+	mmc2_default_pins: mmc2-default-pins {
+		clk-pins {
+			pinmux = <MT8365_PIN_81_MSDC2_CLK__FUNC_MSDC2_CLK>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <4>;
+		};
+
+		cmd-dat-pins {
+			pinmux = <MT8365_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+				 <MT8365_PIN_83_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+				 <MT8365_PIN_84_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+				 <MT8365_PIN_85_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
+				 <MT8365_PIN_80_MSDC2_CMD__FUNC_MSDC2_CMD>;
 			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+			drive-strength = <4>;
+			input-enable;
+		};
+
+		sys-en-pins {
+			pinmux = <MT8365_PIN_120_DMIC1_CLK__FUNC_GPIO120>;
+			output-low;
+		};
+	};
+
+	mmc2_uhs_pins: mmc2-uhs-pins {
+		clk-pins {
+			pinmux = <MT8365_PIN_81_MSDC2_CLK__FUNC_MSDC2_CLK>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <8>;
+		};
+
+		cmd-dat-pins {
+			pinmux = <MT8365_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
+				 <MT8365_PIN_83_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
+				 <MT8365_PIN_84_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
+				 <MT8365_PIN_85_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
+				 <MT8365_PIN_80_MSDC2_CMD__FUNC_MSDC2_CMD>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+			drive-strength = <8>;
+			input-enable;
+		};
+
+		ds-pins {
+			pinmux = <MT8365_PIN_86_MSDC2_DSL__FUNC_MSDC2_DSL>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+			drive-strength = <8>;
+		};
+
+		sys-en-pins {
+			pinmux = <MT8365_PIN_120_DMIC1_CLK__FUNC_GPIO120>;
+			output-high;
 		};
 	};
 

---
base-commit: 9d89551994a430b50c4fffcb1e617a057fa76e20
change-id: 20250109-mmc2-support-96b3ea516186

Best regards,
-- 
Alexandre Mergnat <amergnat at baylibre.com>



From claudiu.beznea at tuxon.dev  Mon Mar 24 06:57:00 2025
From: claudiu.beznea at tuxon.dev (Claudiu)
Date: Mon, 24 Mar 2025 15:57:00 +0200
Subject: [PATCH v3 3/4] arm64: dts: renesas: r9a08g045: Add TSU node
In-Reply-To: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
References: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
Message-ID: <20250324135701.179827-4-claudiu.beznea.uj@bp.renesas.com>

From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>

Add TSU node along with thermal zones and keep it enabled in the SoC DTSI.
The temperature reported by the TSU can only be read through channel 8 of
the ADC. Therefore, enable the ADC by default.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
---

Changes in v3:
- none

Changes in v2:
- collected Geert's tag
- adjusted the trip points temperature as suggested in the review
  process
- added cpu_alert1 passive trip point as suggested in the review
  process; along with it changed the trip point nodes and label names

Hi, Geert,

I kept your Rb tag. Please let me know if it should be dropped.

Thank you,
Claudiu

 arch/arm64/boot/dts/renesas/r9a08g045.dtsi    | 49 ++++++++++++++++++-
 .../boot/dts/renesas/rzg3s-smarc-som.dtsi     |  4 --
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
index 0364f89776e6..3f56fff7d9b0 100644
--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
@@ -233,7 +233,6 @@ adc: adc at 10058000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			#io-channel-cells = <1>;
-			status = "disabled";
 
 			channel at 0 {
 				reg = <0>;
@@ -272,6 +271,17 @@ channel at 8 {
 			};
 		};
 
+		tsu: thermal at 10059000 {
+			compatible = "renesas,r9a08g045-tsu";
+			reg = <0 0x10059000 0 0x1000>;
+			clocks = <&cpg CPG_MOD R9A08G045_TSU_PCLK>;
+			resets = <&cpg R9A08G045_TSU_PRESETN>;
+			power-domains = <&cpg>;
+			#thermal-sensor-cells = <0>;
+			io-channels = <&adc 8>;
+			io-channel-names = "tsu";
+		};
+
 		vbattb: clock-controller at 1005c000 {
 			compatible = "renesas,r9a08g045-vbattb";
 			reg = <0 0x1005c000 0 0x1000>;
@@ -717,6 +727,43 @@ timer {
 				  "hyp-virt";
 	};
 
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+			thermal-sensors = <&tsu>;
+			sustainable-power = <423>;
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device = <&cpu0 0 2>;
+					contribution = <1024>;
+				};
+			};
+
+			trips {
+				cpu_crit: cpu-critical {
+					temperature = <110000>;
+					hysteresis = <1000>;
+					type = "critical";
+				};
+
+				cpu_alert1: trip-point1 {
+					temperature = <90000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+
+				cpu_alert0: trip-point0 {
+					temperature = <85000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+	};
+
 	vbattb_xtal: vbattb-xtal {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
index 39845faec894..6f25ab617982 100644
--- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
@@ -84,10 +84,6 @@ x3_clk: x3-clock {
 	};
 };
 
-&adc {
-	status = "okay";
-};
-
 #if SW_CONFIG3 == SW_ON
 &eth0 {
 	pinctrl-0 = <&eth0_pins>;
-- 
2.43.0



From claudiu.beznea at tuxon.dev  Mon Mar 24 06:57:01 2025
From: claudiu.beznea at tuxon.dev (Claudiu)
Date: Mon, 24 Mar 2025 15:57:01 +0200
Subject: [PATCH v3 4/4] arm64: defconfig: Enable RZ/G3S thermal
In-Reply-To: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
References: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
Message-ID: <20250324135701.179827-5-claudiu.beznea.uj@bp.renesas.com>

From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>

Enable the CONFIG_RZG3S_THERMAL flag for the RZ/G3S SoC.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
---

Changes in v3:
- none

Changes in v2:
- collected tags

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5bb8f09422a2..79e566f0d47f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -715,6 +715,7 @@ CONFIG_ROCKCHIP_THERMAL=m
 CONFIG_RCAR_THERMAL=y
 CONFIG_RCAR_GEN3_THERMAL=y
 CONFIG_RZG2L_THERMAL=y
+CONFIG_RZG3S_THERMAL=m
 CONFIG_ARMADA_THERMAL=y
 CONFIG_MTK_THERMAL=m
 CONFIG_MTK_LVTS_THERMAL=m
-- 
2.43.0



From angelogioacchino.delregno at collabora.com  Mon Mar 24 06:59:26 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 14:59:26 +0100
Subject: [PATCH] dt-bindings: iommu: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
References: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
Message-ID: <28135f96-ef99-4347-884d-20e870a3d64a@collabora.com>

Il 24/03/25 13:52, Krzysztof Kozlowski ha scritto:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From claudiu.beznea at tuxon.dev  Mon Mar 24 06:56:57 2025
From: claudiu.beznea at tuxon.dev (Claudiu)
Date: Mon, 24 Mar 2025 15:56:57 +0200
Subject: [PATCH v3 0/4] thermal: renesas: Add support for RZ/G3S
Message-ID: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>

From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>

Hi,

This series adds thermal support for the Renesas RZ/G3S SoC.

Series is organized as follows:
- patches 1-2/4:	add thermal support for RZ/G3S
- patches 3-4/5:	add device tree support

Merge strategy, if any:
- patches 1-2/4 can go through the thermal tree
- patches 3-4/4 can go through the Renesas tree

Thank you,
Claudiu Beznea

Changes in v3:
- drop runtime resume/suspend from the temperature reading function;
  this is not needed as the temperature is read with ADC; this is
  confirmed by the HW team
- use dedicated function to open the devres group in probe; in this
  way the thermal probe code is simpler

Changes in v2:
- dropped the already applied patches
- dropped patch 2/6 from v1 as the devres_open_group()/devres_release_group()
  approach was implemented in this version (similar to what was proposed in
  [1])
- collected tags
- added a passive trip point not bound to any cooling device, as proposed
  in the review process
- decreased the trip points temperature
- convert the temperature to mili degree Celsius before applying the
  computation formula to avoid losing precision
- use int variables (instead of unsigned) for temperature computation

[1] https://lore.kernel.org/all/20250215130849.227812-1-claudiu.beznea.uj at bp.renesas.com/

Claudiu Beznea (4):
  dt-bindings: thermal: r9a08g045-tsu: Document the TSU unit
  thermal: renesas: rzg3s: Add thermal driver for the Renesas RZ/G3S SoC
  arm64: dts: renesas: r9a08g045: Add TSU node
  arm64: defconfig: Enable RZ/G3S thermal

 .../thermal/renesas,r9a08g045-tsu.yaml        |  93 ++++++
 MAINTAINERS                                   |   7 +
 arch/arm64/boot/dts/renesas/r9a08g045.dtsi    |  49 ++-
 .../boot/dts/renesas/rzg3s-smarc-som.dtsi     |   4 -
 arch/arm64/configs/defconfig                  |   1 +
 drivers/thermal/renesas/Kconfig               |   8 +
 drivers/thermal/renesas/Makefile              |   1 +
 drivers/thermal/renesas/rzg3s_thermal.c       | 313 ++++++++++++++++++
 8 files changed, 471 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml
 create mode 100644 drivers/thermal/renesas/rzg3s_thermal.c

-- 
2.43.0



From claudiu.beznea at tuxon.dev  Mon Mar 24 06:56:58 2025
From: claudiu.beznea at tuxon.dev (Claudiu)
Date: Mon, 24 Mar 2025 15:56:58 +0200
Subject: [PATCH v3 1/4] dt-bindings: thermal: r9a08g045-tsu: Document the TSU unit
In-Reply-To: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
References: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
Message-ID: <20250324135701.179827-2-claudiu.beznea.uj@bp.renesas.com>

From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>

The Renesas RZ/G3S SoC includes a Thermal Sensor Unit (TSU) block designed
to measure the junction temperature. The temperature is measured using
the RZ/G3S ADC, with a dedicated ADC channel directly connected to the TSU.
Add documentation for it.

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
---

Changes in v3:
- none

Changes in v2:
- collected tags

 .../thermal/renesas,r9a08g045-tsu.yaml        | 93 +++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml

diff --git a/Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml b/Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml
new file mode 100644
index 000000000000..573e2b9d3752
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/renesas,r9a08g045-tsu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G3S Thermal Sensor Unit
+
+description:
+  The thermal sensor unit (TSU) measures the temperature(Tj) inside
+  the LSI.
+
+maintainers:
+  - Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
+
+$ref: thermal-sensor.yaml#
+
+properties:
+  compatible:
+    const: renesas,r9a08g045-tsu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: TSU module clock
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: TSU module reset
+
+  io-channels:
+    items:
+      - description: ADC channel which reports the TSU temperature
+
+  io-channel-names:
+    items:
+      - const: tsu
+
+  "#thermal-sensor-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - resets
+  - io-channels
+  - io-channel-names
+  - '#thermal-sensor-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/r9a08g045-cpg.h>
+
+    tsu: thermal at 10059000 {
+        compatible = "renesas,r9a08g045-tsu";
+        reg = <0x10059000 0x1000>;
+        clocks = <&cpg CPG_MOD R9A08G045_TSU_PCLK>;
+        resets = <&cpg R9A08G045_TSU_PRESETN>;
+        power-domains = <&cpg>;
+        #thermal-sensor-cells = <0>;
+        io-channels = <&adc 8>;
+        io-channel-names = "tsu";
+    };
+
+    thermal-zones {
+        cpu-thermal {
+            polling-delay-passive = <250>;
+            polling-delay = <1000>;
+            thermal-sensors = <&tsu>;
+
+            trips {
+                sensor_crit: sensor-crit {
+                    temperature = <125000>;
+                    hysteresis = <1000>;
+                    type = "critical";
+                };
+                target: trip-point {
+                    temperature = <100000>;
+                    hysteresis = <1000>;
+                    type = "passive";
+                };
+            };
+        };
+    };
-- 
2.43.0



From claudiu.beznea at tuxon.dev  Mon Mar 24 06:56:59 2025
From: claudiu.beznea at tuxon.dev (Claudiu)
Date: Mon, 24 Mar 2025 15:56:59 +0200
Subject: [PATCH v3 2/4] thermal: renesas: rzg3s: Add thermal driver for the Renesas RZ/G3S SoC
In-Reply-To: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
References: <20250324135701.179827-1-claudiu.beznea.uj@bp.renesas.com>
Message-ID: <20250324135701.179827-3-claudiu.beznea.uj@bp.renesas.com>

From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>

The Renesas RZ/G3S SoC features a Thermal Sensor Unit (TSU) that reports
the junction temperature. The temperature is reported through a dedicated
ADC channel. Add a driver for the Renesas RZ/G3S TSU.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
---

Changes in v3:
- drop the runtime resume/suspend from rzg3s_thermal_get_temp(); this
  is not needed as the temperature is read with ADC
- opened the devres group id in rzg3s_thermal_probe() and rename
  previsouly rzg3s_thermal_probe() to rzg3s_thermal_probe_helper(), to
  have simpler code; this approach was suggested by Jonathan in [1];
  as there is no positive feedback for the generic solution [2] this
  looks currently the best approach

[1] https://lore.kernel.org/all/20250224120608.1769039-2-claudiu.beznea.uj at bp.renesas.com
[2] https://lore.kernel.org/all/20250215130849.227812-1-claudiu.beznea.uj at bp.renesas.com


Changes in v2:
- use a devres group for the devm resources obtained though this
  driver to avoid issue described in [1]; with this dropped the
  following calls:
-- thermal_add_hwmon_sysfs(priv->tz);
-- thermal_of_zone_register(priv->tz);
-- pm_runtime_enable(priv->dev);
  and use devm variants
- used signed variables for temperature computation
- convert to mili degree Celsius before applying the computation formula
  to avoid losing precision

[1] https://lore.kernel.org/all/20250215130849.227812-1-claudiu.beznea.uj at bp.renesas.com/

 MAINTAINERS                             |   7 +
 drivers/thermal/renesas/Kconfig         |   8 +
 drivers/thermal/renesas/Makefile        |   1 +
 drivers/thermal/renesas/rzg3s_thermal.c | 313 ++++++++++++++++++++++++
 4 files changed, 329 insertions(+)
 create mode 100644 drivers/thermal/renesas/rzg3s_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a9b8fa5f032..f3795fbcdcba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20594,6 +20594,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml
 F:	drivers/iio/potentiometer/x9250.c
 
+RENESAS RZ/G3S THERMAL SENSOR UNIT DRIVER
+M:	Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
+L:	linux-pm at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml
+F:	drivers/thermal/renesas/rzg3s_thermal.c
+
 RESET CONTROLLER FRAMEWORK
 M:	Philipp Zabel <p.zabel at pengutronix.de>
 S:	Maintained
diff --git a/drivers/thermal/renesas/Kconfig b/drivers/thermal/renesas/Kconfig
index dcf5fc5ae08e..566478797095 100644
--- a/drivers/thermal/renesas/Kconfig
+++ b/drivers/thermal/renesas/Kconfig
@@ -26,3 +26,11 @@ config RZG2L_THERMAL
 	help
 	  Enable this to plug the RZ/G2L thermal sensor driver into the Linux
 	  thermal framework.
+
+config RZG3S_THERMAL
+	tristate "Renesas RZ/G3S thermal driver"
+	depends on ARCH_R9A08G045 || COMPILE_TEST
+	depends on OF && IIO && RZG2L_ADC
+	help
+	  Enable this to plug the RZ/G3S thermal sensor driver into the Linux
+	  thermal framework.
diff --git a/drivers/thermal/renesas/Makefile b/drivers/thermal/renesas/Makefile
index bf9cb3cb94d6..1feb5ab78827 100644
--- a/drivers/thermal/renesas/Makefile
+++ b/drivers/thermal/renesas/Makefile
@@ -3,3 +3,4 @@
 obj-$(CONFIG_RCAR_GEN3_THERMAL)	+= rcar_gen3_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
 obj-$(CONFIG_RZG2L_THERMAL)	+= rzg2l_thermal.o
+obj-$(CONFIG_RZG3S_THERMAL)	+= rzg3s_thermal.o
diff --git a/drivers/thermal/renesas/rzg3s_thermal.c b/drivers/thermal/renesas/rzg3s_thermal.c
new file mode 100644
index 000000000000..e0bc51943875
--- /dev/null
+++ b/drivers/thermal/renesas/rzg3s_thermal.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G3S TSU Thermal Sensor Driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corporation
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/iio/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/thermal.h>
+#include <linux/units.h>
+
+#include "../thermal_hwmon.h"
+
+#define TSU_SM			0x0
+#define TSU_SM_EN		BIT(0)
+#define TSU_SM_OE		BIT(1)
+#define OTPTSUTRIM_REG(n)	(0x18 + (n) * 0x4)
+#define OTPTSUTRIM_EN_MASK	BIT(31)
+#define OTPTSUTRIM_MASK		GENMASK(11, 0)
+
+#define TSU_READ_STEPS		8
+
+/* Default calibration values, if FUSE values are missing. */
+#define SW_CALIB0_VAL		1297
+#define SW_CALIB1_VAL		751
+
+#define MCELSIUS(temp)		((temp) * MILLIDEGREE_PER_DEGREE)
+
+/**
+ * struct rzg3s_thermal_priv - RZ/G3S thermal private data structure
+ * @base: TSU base address
+ * @dev: device pointer
+ * @tz: thermal zone pointer
+ * @rstc: reset control
+ * @channel: IIO channel to read the TSU
+ * @devres_group_id: devres group for the driver devres resources
+ *		      obtained in probe
+ * @mode: current device mode
+ * @calib0: calibration value
+ * @calib1: calibration value
+ */
+struct rzg3s_thermal_priv {
+	void __iomem *base;
+	struct device *dev;
+	struct thermal_zone_device *tz;
+	struct reset_control *rstc;
+	struct iio_channel *channel;
+	void *devres_group_id;
+	enum thermal_device_mode mode;
+	u16 calib0;
+	u16 calib1;
+};
+
+static int rzg3s_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+	struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz);
+	int ts_code_ave = 0;
+	int ret, val;
+
+	if (priv->mode != THERMAL_DEVICE_ENABLED)
+		return -EAGAIN;
+
+	for (u8 i = 0; i < TSU_READ_STEPS; i++) {
+		ret = iio_read_channel_raw(priv->channel, &val);
+		if (ret < 0)
+			return ret;
+
+		ts_code_ave += val;
+		/*
+		 * According to the HW manual (section 40.4.4 Procedure for Measuring the
+		 * Temperature) we need to wait here at leat 3us.
+		 */
+		usleep_range(5, 10);
+	}
+
+	ret = 0;
+	ts_code_ave = DIV_ROUND_CLOSEST(MCELSIUS(ts_code_ave), TSU_READ_STEPS);
+
+	/*
+	 * According to the HW manual (section 40.4.4 Procedure for Measuring the Temperature)
+	 * the computation formula is as follows:
+	 *
+	 * Tj = (ts_code_ave - priv->calib1) * 165 / (priv->calib0 - priv->calib1) - 40
+	 *
+	 * Convert everything to mili Celsius before applying the formula to avoid
+	 * losing precision.
+	 */
+
+	*temp = DIV_ROUND_CLOSEST((s64)(ts_code_ave - MCELSIUS(priv->calib1)) * MCELSIUS(165),
+				  MCELSIUS(priv->calib0 - priv->calib1)) - MCELSIUS(40);
+
+	/* Report it in mili degrees Celsius and round it up to 0.5 degrees Celsius. */
+	*temp = roundup(*temp, 500);
+
+	return ret;
+}
+
+static void rzg3s_thermal_set_mode(struct rzg3s_thermal_priv *priv,
+				   enum thermal_device_mode mode)
+{
+	struct device *dev = priv->dev;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		return;
+
+	if (mode == THERMAL_DEVICE_DISABLED) {
+		writel(0, priv->base + TSU_SM);
+	} else {
+		writel(TSU_SM_EN, priv->base + TSU_SM);
+		/*
+		 * According to the HW manual (section 40.4.1 Procedure for
+		 * Starting the TSU) we need to wait here 30us or more.
+		 */
+		usleep_range(30, 40);
+
+		writel(TSU_SM_OE | TSU_SM_EN, priv->base + TSU_SM);
+		/*
+		 * According to the HW manual (section 40.4.1 Procedure for
+		 * Starting the TSU) we need to wait here 50us or more.
+		 */
+		usleep_range(50, 60);
+	}
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static int rzg3s_thermal_change_mode(struct thermal_zone_device *tz,
+				     enum thermal_device_mode mode)
+{
+	struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz);
+
+	if (priv->mode == mode)
+		return 0;
+
+	rzg3s_thermal_set_mode(priv, mode);
+	priv->mode = mode;
+
+	return 0;
+}
+
+static const struct thermal_zone_device_ops rzg3s_tz_of_ops = {
+	.get_temp = rzg3s_thermal_get_temp,
+	.change_mode = rzg3s_thermal_change_mode,
+};
+
+static int rzg3s_thermal_read_calib(struct rzg3s_thermal_priv *priv)
+{
+	struct device *dev = priv->dev;
+	u32 val;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		return ret;
+
+	val = readl(priv->base + OTPTSUTRIM_REG(0));
+	if (val & OTPTSUTRIM_EN_MASK)
+		priv->calib0 = FIELD_GET(OTPTSUTRIM_MASK, val);
+	else
+		priv->calib0 = SW_CALIB0_VAL;
+
+	val = readl(priv->base + OTPTSUTRIM_REG(1));
+	if (val & OTPTSUTRIM_EN_MASK)
+		priv->calib1 = FIELD_GET(OTPTSUTRIM_MASK, val);
+	else
+		priv->calib1 = SW_CALIB1_VAL;
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	return 0;
+}
+
+static int rzg3s_thermal_probe_helper(struct platform_device *pdev, void *devres_group_id)
+{
+	struct rzg3s_thermal_priv *priv;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->devres_group_id = devres_group_id;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->channel = devm_iio_channel_get(dev, "tsu");
+	if (IS_ERR(priv->channel))
+		return dev_err_probe(dev, PTR_ERR(priv->channel), "Failed to get IIO channel!\n");
+
+	priv->rstc = devm_reset_control_get_exclusive_deasserted(dev, NULL);
+	if (IS_ERR(priv->rstc))
+		return dev_err_probe(dev, PTR_ERR(priv->rstc), "Failed to get reset!\n");
+
+	priv->dev = dev;
+	priv->mode = THERMAL_DEVICE_DISABLED;
+	platform_set_drvdata(pdev, priv);
+
+	pm_runtime_set_autosuspend_delay(dev, 300);
+	pm_runtime_use_autosuspend(dev);
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n");
+
+	ret = rzg3s_thermal_read_calib(priv);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to read calibration data!\n");
+
+	priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &rzg3s_tz_of_ops);
+	if (IS_ERR(priv->tz))
+		return dev_err_probe(dev, PTR_ERR(priv->tz), "Failed to register thermal zone!\n");
+
+	ret = devm_thermal_add_hwmon_sysfs(dev, priv->tz);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add hwmon sysfs!\n");
+
+	return 0;
+}
+
+static int rzg3s_thermal_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	void *devres_group_id;
+	int ret;
+
+	/*
+	 * Open a devres group to allow using devm_pm_runtime_enable()
+	 * w/o interfeering with dev_pm_genpd_detach() in the platform bus
+	 * remove. Otherwise, durring repeated unbind/bind operations,
+	 * the TSU may be runtime resumed when it is not part of its power
+	 * domain, leading to accessing TSU registers (through
+	 * rzg3s_thermal_change_mode()) without its clocks being enabled
+	 * and its PM domain being turned on.
+	 */
+	devres_group_id = devres_open_group(dev, NULL, GFP_KERNEL);
+	if (!devres_group_id)
+		return -ENOMEM;
+
+	ret = rzg3s_thermal_probe_helper(pdev, devres_group_id);
+	if (ret)
+		devres_release_group(dev, devres_group_id);
+
+	return ret;
+}
+
+static void rzg3s_thermal_remove(struct platform_device *pdev)
+{
+	struct rzg3s_thermal_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	devres_release_group(priv->dev, priv->devres_group_id);
+}
+
+static int rzg3s_thermal_suspend(struct device *dev)
+{
+	struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev);
+
+	rzg3s_thermal_set_mode(priv, THERMAL_DEVICE_DISABLED);
+
+	return reset_control_assert(priv->rstc);
+}
+
+static int rzg3s_thermal_resume(struct device *dev)
+{
+	struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev);
+	int ret;
+
+	ret = reset_control_deassert(priv->rstc);
+	if (ret)
+		return ret;
+
+	if (priv->mode != THERMAL_DEVICE_DISABLED)
+		rzg3s_thermal_set_mode(priv, priv->mode);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rzg3s_thermal_pm_ops = {
+	SYSTEM_SLEEP_PM_OPS(rzg3s_thermal_suspend, rzg3s_thermal_resume)
+};
+
+static const struct of_device_id rzg3s_thermal_dt_ids[] = {
+	{ .compatible = "renesas,r9a08g045-tsu" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzg3s_thermal_dt_ids);
+
+static struct platform_driver rzg3s_thermal_driver = {
+	.driver = {
+		.name = "rzg3s_thermal",
+		.of_match_table = rzg3s_thermal_dt_ids,
+		.pm = pm_ptr(&rzg3s_thermal_pm_ops),
+	},
+	.probe = rzg3s_thermal_probe,
+	.remove = rzg3s_thermal_remove,
+};
+module_platform_driver(rzg3s_thermal_driver);
+
+MODULE_DESCRIPTION("Renesas RZ/G3S Thermal Sensor Unit Driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>");
+MODULE_LICENSE("GPL");
-- 
2.43.0



From yeoreum.yun at arm.com  Mon Mar 24 06:59:08 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Mon, 24 Mar 2025 13:59:08 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
 <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
 <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
 <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>
Message-ID: <Z+FlLDLV9WkGNbj+@e129823.arm.com>

Hi Mike,

Please ignore my foremer mail.. and please see my comments for your
suggestion.

> Hi
>
> On Fri, 14 Mar 2025 at 15:25, Yeo Reum Yun <YeoReum.Yun at arm.com> wrote:
> >
> > Hi, Mike.
> >
> > > >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > > > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> > > >
> > > > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > > > +{
> > > > +       if (enable)
> > > > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > > > +
> > >
> > > Not sure why we have an "enable" parameter here - it completely
> > > changes the meaning of the function - with no comment at the start.
> >
> > Sorry. But what I intended is to distinguish
> >     - activation of config
> >     - enable of activated config.
> > Because, current coresight doesn't grab the module reference on enable of activate config,
> > But It grabs that reference only in activation.
> > That's why I used to "enable" parameter to distinguish this
> > while I integrate with module_owner count.
> >
> > > >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> > > >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > > > -                       atomic_dec(&config_desc->active_cnt);
> > > >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > > > -                       cscfg_owner_put(config_desc->load_owner);
> > > > +                       cscfg_config_desc_put(config_desc);
> > > >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> > > >                         break;
> > > >                 }
> > > > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > >                                      unsigned long cfg_hash, int preset)
> > > >  {
> > > >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > > > -       const struct cscfg_config_desc *config_desc;
> > > > +       struct cscfg_config_desc *config_desc;
> > > >         unsigned long flags;
> > > >         int err = 0;
> > > >
> > > > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> > > >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > > >                 config_desc = config_csdev_item->config_desc;
> > > > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > > > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > > > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > > > +                               cscfg_config_desc_get(config_desc, true)) {
> > > >
> > > This obfuscates the logic of the comparisons without good reason. With
> > > the true parameter, the function does no "get" operation but just
> > > replicates the logic being replaced - checking the active_cnt is
> > > non-zero.
> > >
> > > Restore this to the original logic to make it readable again
> >
> > It's not a replicates of comparsion logic, but if true,
>
> sorry - missed that point .
>
> > It get the reference of active_cnt but not get module reference.
> > The fundemental fault in the UAF becase of just "atomic_read()"
> > so, it should hold reference in here.
> >
> > So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
> > I think there're two way to modfiy.
> >
> >     1. cscfg_config_desc_get()/put() always grab/drop the module count.
> >     2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
> >         with cscfg_owner_get()/put()
> >
> > Any thougt?
> >
> > Thanks!
> >
> >
>
> The get and put functions are asymmetrical w.r.t. owner.
>
> The put will put owner if active count decrements to 0,
> The get if not on enable path will put owner unconditionally.
>
> This means that the caller has to work out the correct input conditions.
>
> Might be better if:-
>
> get_desc()
> {
>     if (! desc->refcnt) {
>        if (!get_owner())
>            return false;
>    }
>    desc->refcnt++;
>     return true;
> }

I think This makes another problem when
it races with _cscfg_deactivate_config().

CPU0                                          CPU1
(sysfs enable)                                load module
                                              cscfg_load_config_sets()
                                              activate config. // sysfs
                                              (sys_active_cnt == 1)

                                              // sysfs
                                              _cscfg_deactivate_config()
                                              (sys_active_cnt == 0)
                                              (config->active_cnt = 0)
...
cscfg_csdev_enable_active_config()
  lock(csdev->cscfg_csdev_lock)
  // here get module reference??
  // even sys_active_cnt == 0 and
  // config->active_cnt == 1.
  get_desc()
  unlock(csdev->cscfg_csdev_lock)


  // access to config_desc which freed
  // while unloading module.
  cfs_csdev_enable_config


Because, the desc->refcnt meaning of zero is different from the context.
   - while activate . it should get module reference if zero.
   - while enable active configuration, if zero, it should be failed.

that means to prevent this race, the core key point is:
   when config->active_cnt == 0, it should be failed in cscfg_csdev_enable_active_config()

Because, according to context the handling the zero reference value is
different, It seems,to integrate the get_desc() interface to handle
above case together without extra arguments (in case of here is
"enable").

If this interface is really ugly and unhappy to you,
I think It should remove get_desc()/put_desc().
although we can add new interface for cscfg_config_desc_get() for enable
path. but it makes people more confused.

So my suggestion is:
   - sustain this patch's contents
   - or remove get_desc()/put_desc() interface but use
     atomic_inc_zero(&config_desc->active_cnt) directly in
     cscfg_csdev_enable_active_config()

Any thougt?

Thanks.


From angelogioacchino.delregno at collabora.com  Mon Mar 24 07:09:24 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 15:09:24 +0100
Subject: [PATCH RESEND v2] arm64: dts: mediatek: add mmc2 support for
 mt8365-evk
In-Reply-To: <20250109-mmc2-support-v2-1-5f660c809610@baylibre.com>
References: <20250109-mmc2-support-v2-1-5f660c809610@baylibre.com>
Message-ID: <ecd8a46e-0f87-498e-8a12-fdeae6f5791d@collabora.com>

Il 24/03/25 14:54, Alexandre Mergnat ha scritto:
> Adds support for the MMC2 interface on the MT8365 EVK board.
> It introduces a fixed regulator for the MMC2 VDD33 supply and configures
> the MMC2 node with a 4-bit bus width, high-speed capabilities, UHS
> modes, and appropriate power supplies. Enabled SDIO IRQ, wakeup source,
> and kept power during suspend (to save firmware module) for wireless
> chip functionality.
> 
> Signed-off-by: Alexandre Mergnat <amergnat at baylibre.com>
> ---
> Changes in v2:
> - Apply alphabetical order to pinctrl property items.
> - Improve commit message
> - Link to v1: https://lore.kernel.org/r/20250109-mmc2-support-v1-1-9b9d1b1ae35d at baylibre.com
> ---
>   arch/arm64/boot/dts/mediatek/mt8365-evk.dts | 103 +++++++++++++++++++++++++---
>   1 file changed, 94 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
> index 7d90112a7e274..a87f1b3ed6500 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
> +++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
> @@ -53,6 +53,15 @@ memory at 40000000 {
>   		reg = <0 0x40000000 0 0xc0000000>;
>   	};
>   
> +	mmc2_vdd33: mmc2_vdd33-regulator {
> +		compatible = "regulator-fixed";
> +		regulator-name = "mmc2_vdd33";

mmc2-vdd33 please

> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		gpio = <&pio 121 0>;
> +		enable-active-high;
> +	};
> +
>   	usb_otg_vbus: regulator-0 {
>   		compatible = "regulator-fixed";
>   		regulator-name = "otg_vbus";
> @@ -197,6 +206,28 @@ &mmc1 {
>   	status = "okay";
>   };
>   
> +&mmc2 {
> +	assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL>;
> +	assigned-clocks = <&topckgen CLK_TOP_MSDC50_2_SEL>;
> +	bus-width = <4>;
> +	cap-sd-highspeed;
> +	cap-sdio-irq;
> +	hs400-ds-delay = <0x12012>;
> +	keep-power-in-suspend;
> +	max-frequency = <200000000>;
> +	non-removable;
> +	pinctrl-0 = <&mmc2_default_pins>;
> +	pinctrl-1 = <&mmc2_uhs_pins>;
> +	pinctrl-names = "default", "state_uhs";
> +	sd-uhs-sdr104;
> +	sd-uhs-sdr25;
> +	sd-uhs-sdr50;
> +	vmmc-supply = <&mmc2_vdd33>;
> +	vqmmc-supply = <&mt6357_vcn18_reg>;
> +	wakeup-source;
> +	status = "okay";
> +};
> +
>   &mt6357_pmic {
>   	interrupts-extended = <&pio 145 IRQ_TYPE_LEVEL_HIGH>;
>   	interrupt-controller;
> @@ -324,8 +355,8 @@ cmd-dat-pins {
>   				 <MT8365_PIN_94_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
>   				 <MT8365_PIN_93_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
>   				 <MT8365_PIN_98_MSDC0_CMD__FUNC_MSDC0_CMD>;
> -			input-enable;
>   			bias-pull-up;
> +			input-enable;

This is a cleanup and goes to a different commit

>   		};
>   
>   		rst-pins {
> @@ -337,8 +368,8 @@ rst-pins {
>   	mmc0_uhs_pins: mmc0-uhs-pins {
>   		clk-pins {
>   			pinmux = <MT8365_PIN_99_MSDC0_CLK__FUNC_MSDC0_CLK>;
> -			drive-strength = <MTK_DRIVE_10mA>;
>   			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
> +			drive-strength = <MTK_DRIVE_10mA>;

While at it, in a cleanup commit, if you could also remove those MTK_DRIVE_xxx and
use just the number that'd be great.

>   		};
>   
>   		cmd-dat-pins {
> @@ -351,21 +382,21 @@ cmd-dat-pins {
>   				 <MT8365_PIN_94_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
>   				 <MT8365_PIN_93_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
>   				 <MT8365_PIN_98_MSDC0_CMD__FUNC_MSDC0_CMD>;
> -			input-enable;
> -			drive-strength = <MTK_DRIVE_10mA>;
>   			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
> +			drive-strength = <MTK_DRIVE_10mA>;
> +			input-enable;
>   		};
>   
>   		ds-pins {
>   			pinmux = <MT8365_PIN_104_MSDC0_DSL__FUNC_MSDC0_DSL>;
> -			drive-strength = <MTK_DRIVE_10mA>;
>   			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
> +			drive-strength = <MTK_DRIVE_10mA>;
>   		};
>   
>   		rst-pins {
>   			pinmux = <MT8365_PIN_97_MSDC0_RSTB__FUNC_MSDC0_RSTB>;
> -			drive-strength = <MTK_DRIVE_10mA>;
>   			bias-pull-up;
> +			drive-strength = <MTK_DRIVE_10mA>;
>   		};
>   	};
>   
> @@ -386,16 +417,16 @@ cmd-dat-pins {
>   				 <MT8365_PIN_91_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
>   				 <MT8365_PIN_92_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
>   				 <MT8365_PIN_87_MSDC1_CMD__FUNC_MSDC1_CMD>;
> -			input-enable;
>   			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
> +			input-enable;
>   		};
>   	};
>   
>   	mmc1_uhs_pins: mmc1-uhs-pins {
>   		clk-pins {
>   			pinmux = <MT8365_PIN_88_MSDC1_CLK__FUNC_MSDC1_CLK>;
> -			drive-strength = <8>;
>   			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
> +			drive-strength = <8>;
>   		};
>   
>   		cmd-dat-pins {
> @@ -404,9 +435,63 @@ cmd-dat-pins {
>   				 <MT8365_PIN_91_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
>   				 <MT8365_PIN_92_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
>   				 <MT8365_PIN_87_MSDC1_CMD__FUNC_MSDC1_CMD>;
> -			input-enable;
> +			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
>   			drive-strength = <6>;
> +			input-enable;
> +		};
> +	};
> +
> +	mmc2_default_pins: mmc2-default-pins {
> +		clk-pins {
> +			pinmux = <MT8365_PIN_81_MSDC2_CLK__FUNC_MSDC2_CLK>;
> +			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
> +			drive-strength = <4>;
> +		};
> +
> +		cmd-dat-pins {
> +			pinmux = <MT8365_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0>,
> +				 <MT8365_PIN_83_MSDC2_DAT1__FUNC_MSDC2_DAT1>,
> +				 <MT8365_PIN_84_MSDC2_DAT2__FUNC_MSDC2_DAT2>,
> +				 <MT8365_PIN_85_MSDC2_DAT3__FUNC_MSDC2_DAT3>,
> +				 <MT8365_PIN_80_MSDC2_CMD__FUNC_MSDC2_CMD>;
>   			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
> +			drive-strength = <4>;
> +			input-enable;
> +		};
> +
> +		sys-en-pins {
> +			pinmux = <MT8365_PIN_120_DMIC1_CLK__FUNC_GPIO120>;

My schematics say that the DMIC1_CLK pin is PERST_N, DMIC_DAT0 is PWR_EN: what's
the intention here?!

In any case, this is not a mmc2 pin, but something else :-)

Cheers,
Angelo



From alyssa at rosenzweig.io  Mon Mar 24 07:10:42 2025
From: alyssa at rosenzweig.io (Alyssa Rosenzweig)
Date: Mon, 24 Mar 2025 10:10:42 -0400
Subject: [PATCH v3] drm: Add UAPI for the Asahi driver
In-Reply-To: <260D98E1-7204-4535-A84F-D55A4527FF7E@collabora.com>
References: <20250314-agx-uapi-v3-1-3abf7e74ea2f@rosenzweig.io>
 <195b507d4b3.b25d0dad175771.7566427576910952468@collabora.com>
 <195b582682b.121ba4d5e219032.3109114844776468245@collabora.com>
 <Z-B6uc7EEAdBPXmt@blossom>
 <260D98E1-7204-4535-A84F-D55A4527FF7E@collabora.com>
Message-ID: <Z-Fn4niI6_Yd06Ze@blossom>

> >>>> +    /** 
> >>>> +     * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly 
> >>>> +     * across the VA range. 
> >>>> +     * 
> >>>> +     * This is useful to fill a VA range with scratch pages or zero pages. 
> >>>> +     * It is intended as a mechanism to accelerate sparse. 
> >>>> +     */ 
> >>>> +    DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 2),
> >> 
> >> Does this require the BO to be a single page? If so, does it require offset==0? Or does it just take whatever page is at the specified offset?
> > 
> > I believe the intention is that it takes whatever page is at the
> > specified offset and just maps that a bunch of times. HK doesn't use
> > this yet though it probably should (this was added to help reduce
> > overhead when emulating sparse with scratch/zero pages, which is still
> > very new functionality in hk).
> > 
> > Accelerating this properly involves GPUVM patches - although even without
> > that, moving the loop into the kernel so it's only a single ioctl
> > (user-kernel roundtrip) seems worth keeping the flag for.
> 
> FYI: I will be posting a patch for the GPUVM abstraction soon.

Great to hear :) Although in this case, I meant that accelerating
DRM_ASAHI_BIND_SINGLE_PAGE requires patches to extend the actual C
implementation of drm/gpuvm, not just the Rust abstraction. Which is a
bit annoying for non-essential functionality with regards to upstreaming
things...


From robh at kernel.org  Mon Mar 24 07:21:23 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 09:21:23 -0500
Subject: [PATCH 1/2] dt-bindings: NXP System Timer Module
In-Reply-To: <20250324100008.346009-1-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
Message-ID: <174282608006.6289.10388719224772938093.robh@kernel.org>


On Mon, 24 Mar 2025 11:00:05 +0100, Daniel Lezcano wrote:
> Add the System Timer Module description found on the NXP s32 platform
> and the compatible for the s32g2 variant.
> 
> Cc: Ghennadi Procopciuc <ghennadi.procopciuc at oss.nxp.com>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Cc: Thomas Fossati <thomas.fossati at linaro.org>
> Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> ---
>  .../bindings/timer/nxp,stm-timer.yaml         | 59 +++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/timer/nxp,stm-timer.example.dtb: stm at 4011c000: compatible: ['nxp,s32g2-stm'] is valid under each of {'items': [{'const': 'nxp,s32g2-stm'}], 'type': 'array', 'minItems': 1, 'maxItems': 1}, {'items': [{'const': 'nxp,s32g2-stm'}], 'type': 'array', 'minItems': 1, 'maxItems': 1}
	from schema $id: http://devicetree.org/schemas/timer/nxp,stm-timer.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250324100008.346009-1-daniel.lezcano at linaro.org

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



From safwanmohammad464 at gmail.com  Mon Mar 24 07:22:08 2025
From: safwanmohammad464 at gmail.com (Dear Customer)
Date: Mon, 24 Mar 2025 07:22:08 -0700 (PDT)
Subject: Orders 7136073104448 is being reviewed.
Message-ID: <67e16a90.170a0220.17133d.e589@mx.google.com>

Subject: Successful Renewal of Your McAfee Subscription for 48 Months

Dear Dear Customer,

We are pleased to announce that the renewal of your McAfee subscription for the year 48 Months has been successfully processed. Thank you for your continued partnership with McAfee. Your loyalty means the world to us.

Renewal Details:

Product Code: 121-nsiz-9980

Service/Product: Operating System Repair & Protect-ABC

Amount Due: USD319.10

Please note that the renewal fee of USD319.10 will be processed within 12 business hours and credited to your account. You will also see this charge reflected on your next billing cycle.

If you have any questions or need further assistance, our customer support team is available to assist you at 888-350-2394.

We are grateful to have you as part of the McAfee community!

Warm regards,
McAfee Inc.
(c) 2025 All rights reserved.

From detlev.casanova at collabora.com  Mon Mar 24 07:32:04 2025
From: detlev.casanova at collabora.com (Detlev Casanova)
Date: Mon, 24 Mar 2025 10:32:04 -0400
Subject: [PATCH] iommu/rockchip: Add flush_iotlb_all ops
In-Reply-To: <9bd56bd6-ce7d-495f-9bb3-ce7f07975f62@arm.com>
References: <20250318152049.14781-1-detlev.casanova@collabora.com>
 <9bd56bd6-ce7d-495f-9bb3-ce7f07975f62@arm.com>
Message-ID: <5003710.31r3eYUQgx@trenzalore>

Hi Robin,
On Tuesday, 18 March 2025 14:40:20 EDT Robin Murphy wrote:
> On 18/03/2025 3:20 pm, Detlev Casanova wrote:
> > From: Jonas Karlman <jonas at kwiboo.se>
> > 
> > On some Rockchip cores (like the vdpu34x video decoder), the IOMMU device
> > is inside the the device that uses it.
> > 
> > The IOMMU device can still be driven by the iommu driver, but when an
> > error occurs in the main device (e.g. a decoding error that resets the
> > decoder), the IOMMU device will also be reseted.
> > In such situation, the IOMMU driver and the hardware are out of sync and
> > IOMMU errors will start popping up.
> > 
> > To avoid that, add a flush_iotlb_all function that will let the main
> > drivers (e.g. rkvdec) tell the IOMMU driver to write all its cached
> > mappings into the IOMMU hardware when such an error occured.
> 
> Eww, this is the exact opposite of what flush_iotlb_all represents, and
> I really don't like the idea of the public IOMMU API being abused for
> inter-driver communication.

I see, so "Synchronously flush all hardware TLBs for this domain" means that it 
is supposed to clear everything that is set in hardware then, right ?

> Please have some kind of proper reset
> notifier mechanism - in fact with runtime PM could you not already
> invoke a suspend/resume cycle via the device links? AFAICS it would also
> work to attach to a different domain then switch back again. Or at worst
> just export a public interface for the other driver to invoke
> rk_iommu_resume() directly.

Thank you for the suggestions. PM runtime is a bit overkill as it can also 
manage power and clocks related to the iommu but also other devices in the 
tree.

I went with an "empty domain" and switching between them works as expected.

> Just don't hide it in something completely
> inappropriate - I mean, consider if someone wants to implement
> IOMMU_CAP_DEFERRED_FLUSH support here in future...

I don't know what that does exactly. As I don't have enough of the picture on 
IOMMU drivers, I'm glad we could find a solution that doesn't change anything 
in the IOMMU tree :)

Regards,
Detlev

> 
> > Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> > Signed-off-by: Detlev Casanova <detlev.casanova at collabora.com>
> > ---
> > 
> >   drivers/iommu/rockchip-iommu.c | 45 ++++++++++++++++++++++++++++++----
> >   1 file changed, 40 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/iommu/rockchip-iommu.c
> > b/drivers/iommu/rockchip-iommu.c index 323cc665c357..7086716cb8fc 100644
> > --- a/drivers/iommu/rockchip-iommu.c
> > +++ b/drivers/iommu/rockchip-iommu.c
> > @@ -899,6 +899,40 @@ static size_t rk_iommu_unmap(struct iommu_domain
> > *domain, unsigned long _iova,> 
> >   	return unmap_size;
> >   
> >   }
> > 
> > +static void rk_iommu_flush_iotlb_all(struct iommu_domain *domain)
> > +{
> > +	struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
> > +	struct list_head *pos;
> > +	unsigned long flags;
> > +	int i, ret;
> > +
> > +	spin_lock_irqsave(&rk_domain->iommus_lock, flags);
> > +	list_for_each(pos, &rk_domain->iommus) {
> > +		struct rk_iommu *iommu = list_entry(pos, struct 
rk_iommu, node);
> > +
> > +		ret = pm_runtime_get_if_in_use(iommu->dev);
> > +		if (!ret || WARN_ON_ONCE(ret < 0))
> > +			continue;
> > +
> > +		if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu-
>clocks)))
> > +			continue;
> > +
> > +		rk_iommu_enable_stall(iommu);
> > +		for (i = 0; i < iommu->num_mmu; i++) {
> > +			rk_iommu_write(iommu->bases[i], 
RK_MMU_DTE_ADDR,
> > +				rk_ops->mk_dtentries(rk_domain-
>dt_dma));
> > +			rk_iommu_base_command(iommu->bases[i], 
RK_MMU_CMD_ZAP_CACHE);
> > +			rk_iommu_write(iommu->bases[i], 
RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
> > +		}
> > +		rk_iommu_enable_paging(iommu);
> > +		rk_iommu_disable_stall(iommu);
> > +
> > +		clk_bulk_disable(iommu->num_clocks, iommu->clocks);
> > +		pm_runtime_put(iommu->dev);
> > +	}
> > +	spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
> > +}
> > +
> > 
> >   static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
> >   {
> >   
> >   	struct rk_iommudata *data = dev_iommu_priv_get(dev);
> > 
> > @@ -1172,11 +1206,12 @@ static const struct iommu_ops rk_iommu_ops = {
> > 
> >   	.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
> >   	.of_xlate = rk_iommu_of_xlate,
> >   	.default_domain_ops = &(const struct iommu_domain_ops) {
> > 
> > -		.attach_dev	= rk_iommu_attach_device,
> > -		.map_pages	= rk_iommu_map,
> > -		.unmap_pages	= rk_iommu_unmap,
> > -		.iova_to_phys	= rk_iommu_iova_to_phys,
> > -		.free		= rk_iommu_domain_free,
> > +		.attach_dev		= rk_iommu_attach_device,
> > +		.map_pages		= rk_iommu_map,
> > +		.unmap_pages		= rk_iommu_unmap,
> > +		.flush_iotlb_all	= rk_iommu_flush_iotlb_all,
> > +		.iova_to_phys		= 
rk_iommu_iova_to_phys,
> > +		.free			= 
rk_iommu_domain_free,
> > 
> >   	}
> >   
> >   };






From krzysztof.kozlowski at linaro.org  Mon Mar 24 07:35:30 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 15:35:30 +0100
Subject: [PATCH 1/2] dt-bindings: NXP System Timer Module
In-Reply-To: <20250324100008.346009-1-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
Message-ID: <7beb5a48-715b-47ac-a908-ca0fa135fd93@linaro.org>

On 24/03/2025 11:00, Daniel Lezcano wrote:
> Add the System Timer Module description found on the NXP s32 platform
> and the compatible for the s32g2 variant.


subject:

dt-bindings: timer: Add NXP .......

> 
> Cc: Ghennadi Procopciuc <ghennadi.procopciuc at oss.nxp.com>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Cc: Thomas Fossati <thomas.fossati at linaro.org>
> Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> ---
>  .../bindings/timer/nxp,stm-timer.yaml         | 59 +++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> 
> diff --git a/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> new file mode 100644
> index 000000000000..41093892c617
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> @@ -0,0 +1,59 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/timer/nxp,stm-timer.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP System Timer Module (STM)
> +
> +maintainers:
> +  - Daniel Lezcano <daniel.lezcano at kernel.org>
> +
> +description: |

Do not need '|' unless you need to preserve formatting.

> +  The System Timer Module supports commonly required system and
> +  application software timing functions. STM includes a 32-bit
> +  count-up timer and four 32-bit compare channels with a separate
> +  interrupt source for each channel. The timer is driven by the STM
> +  module clock divided by an 8-bit prescale value.
> +
> +properties:
> +  compatible:
> +    oneOf:

That's pointless - you have only one.

> +      - const: nxp,s32g2-stm

Keep this

> +      - items:
> +          - const: nxp,s32g2-stm

Drop this and oneOf. Unless you wanted more devices, but then it is
incomplete.

Best regards,
Krzysztof


From manivannan.sadhasivam at linaro.org  Mon Mar 24 07:35:58 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 20:05:58 +0530
Subject: [PATCH v12 00/13] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <brhtmymbntt7dk3bqgcwjb72ai4g2bn4b5emcaxntbizvu4i7f@ulvm37yyl4oq>

On Sat, Mar 15, 2025 at 03:15:35PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
> 
> This is a v12 based on Frank's v11 series.
> 

Mostly looks good to me. But I do have a few comments, that I'll share.

Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

- Mani

> v11 https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-0-01d2313502ab at nxp.com
>     
> Changes from v11:
>   - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init(), before
>     any devicetree-related code
>   - Call devm_pci_epc_create() early in dw_pcie_ep_init(), before any
>     devicetree-related code
>   - Consolidate devicetree-related code in dw_pcie_host_get_resources() and
>     dw_pcie_ep_get_resources()
>   - Integrate dw_pcie_cfg0_setup() into dw_pcie_host_get_resources()
>   - Convert dw_pcie_init_parent_bus_offset() to dw_pcie_parent_bus_offset()
>     which returns the offset rather than setting it internally
>   - Split the debug comparison of devicetree info with .cpu_addr_fixup() to
>     separate patch so we can easily revert it later
>   - Drop "cpu_addr_fixup() usage detected" warning since we always warn
>     about something in that case anyway
> 
> Any comments welcome.
> 
> 
> Bjorn Helgaas (3):
>   PCI: dwc: Consolidate devicetree handling in
>     dw_pcie_host_get_resources()
>   PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init()
>   PCI: dwc: ep: Consolidate devicetree handling in
>     dw_pcie_ep_get_resources()
> 
> Frank Li (10):
>   PCI: dwc: Use resource start as iomap() input in
>     dw_pcie_pme_turn_off()
>   PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
>   PCI: dwc: Call devm_pci_alloc_host_bridge() early in
>     dw_pcie_host_init()
>   PCI: dwc: Add dw_pcie_parent_bus_offset()
>   PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug
>   PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr
>     offset
>   PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU
>     addr offset
>   PCI: dwc: ep: Ensure proper iteration over outbound map windows
>   PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup()
>   PCI: imx6: Remove cpu_addr_fixup()
> 
>  drivers/pci/controller/dwc/pci-imx6.c         | 18 +---
>  .../pci/controller/dwc/pcie-designware-ep.c   | 74 +++++++++++------
>  .../pci/controller/dwc/pcie-designware-host.c | 57 ++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.c  | 82 ++++++++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.h  | 24 +++++-
>  5 files changed, 171 insertions(+), 84 deletions(-)
> 
> -- 
> 2.34.1
> 

-- 
????????? ????????


From robh at kernel.org  Mon Mar 24 07:44:43 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 09:44:43 -0500
Subject: [PATCH 1/2] dt-bindings: NXP System Timer Module
In-Reply-To: <20250324100008.346009-1-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
Message-ID: <20250324144443.GA17721-robh@kernel.org>

On Mon, Mar 24, 2025 at 11:00:05AM +0100, Daniel Lezcano wrote:
> Add the System Timer Module description found on the NXP s32 platform
> and the compatible for the s32g2 variant.
> 
> Cc: Ghennadi Procopciuc <ghennadi.procopciuc at oss.nxp.com>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Cc: Thomas Fossati <thomas.fossati at linaro.org>
> Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> ---
>  .../bindings/timer/nxp,stm-timer.yaml         | 59 +++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> 
> diff --git a/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> new file mode 100644
> index 000000000000..41093892c617
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/nxp,stm-timer.yaml
> @@ -0,0 +1,59 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/timer/nxp,stm-timer.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP System Timer Module (STM)
> +
> +maintainers:
> +  - Daniel Lezcano <daniel.lezcano at kernel.org>
> +
> +description: |

Don't need '|' and wrap at 80 char.

> +  The System Timer Module supports commonly required system and
> +  application software timing functions. STM includes a 32-bit
> +  count-up timer and four 32-bit compare channels with a separate
> +  interrupt source for each channel. The timer is driven by the STM
> +  module clock divided by an 8-bit prescale value.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - const: nxp,s32g2-stm
> +      - items:
> +          - const: nxp,s32g2-stm
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: System Timer Module clock

Just 'maxItems: 1'. The description is rather obvious.

> +
> +  clock-names:
> +    items:
> +      - const: stm

No need for *-names when there is only 1 entry.

> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    stm at 4011c000 {

timer at ...

> +        compatible = "nxp,s32g2-stm";
> +        reg = <0x4011c000 0x3000>;
> +        interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
> +        clocks = <&clks 0x3b>;
> +        clock-names = "stm";
> +    };
> -- 
> 2.43.0
> 


From james.clark at linaro.org  Mon Mar 24 07:52:26 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 24 Mar 2025 14:52:26 +0000
Subject: [RFC PATCH v3 7/8] perf: arm_pmuv3: Keep out of guest counter
 partition
In-Reply-To: <20250213180317.3205285-8-coltonlewis@google.com>
References: <20250213180317.3205285-1-coltonlewis@google.com>
 <20250213180317.3205285-8-coltonlewis@google.com>
Message-ID: <8450a182-5c62-4546-ab91-5d39eb252254@linaro.org>



On 13/02/2025 6:03 pm, Colton Lewis wrote:
> If the PMU is partitioned, keep the driver out of the guest counter
> partition and only use the host counter partition. Partitioning is
> defined by the MDCR_EL2.HPMN register field and saved in
> cpu_pmu->hpmn. The range 0..HPMN-1 is accessible by EL1 and EL0 while
> HPMN..PMCR.N is reserved for EL2.
> 
> Define some macros that take HPMN as an argument and construct
> mutually exclusive bitmaps for testing which partition a particular
> counter is in. Note that despite their different position in the
> bitmap, the cycle and instruction counters are always in the guest
> partition.
> 
> Signed-off-by: Colton Lewis <coltonlewis at google.com>
> ---
>   arch/arm/include/asm/arm_pmuv3.h |  2 +
>   arch/arm64/include/asm/kvm_pmu.h |  5 +++
>   arch/arm64/kvm/pmu-part.c        | 16 +++++++
>   drivers/perf/arm_pmuv3.c         | 73 +++++++++++++++++++++++++++-----
>   include/linux/perf/arm_pmuv3.h   |  8 ++++
>   5 files changed, 94 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h
> index 2ec0e5e83fc9..dadd4ddf51af 100644
> --- a/arch/arm/include/asm/arm_pmuv3.h
> +++ b/arch/arm/include/asm/arm_pmuv3.h
> @@ -227,6 +227,8 @@ static inline bool kvm_set_pmuserenr(u64 val)
>   }
>   
>   static inline void kvm_vcpu_pmu_resync_el0(void) {}
> +static inline void kvm_pmu_host_counters_enable(void) {}
> +static inline void kvm_pmu_host_counters_disable(void) {}
>   
>   /* PMU Version in DFR Register */
>   #define ARMV8_PMU_DFR_VER_NI        0
> diff --git a/arch/arm64/include/asm/kvm_pmu.h b/arch/arm64/include/asm/kvm_pmu.h
> index 174b7f376d95..8f25754fde47 100644
> --- a/arch/arm64/include/asm/kvm_pmu.h
> +++ b/arch/arm64/include/asm/kvm_pmu.h
> @@ -25,6 +25,8 @@ void kvm_host_pmu_init(struct arm_pmu *pmu);
>   u8 kvm_pmu_get_reserved_counters(void);
>   u8 kvm_pmu_hpmn(u8 nr_counters);
>   void kvm_pmu_partition(struct arm_pmu *pmu);
> +void kvm_pmu_host_counters_enable(void);
> +void kvm_pmu_host_counters_disable(void);
>   
>   #else
>   
> @@ -37,6 +39,9 @@ static inline bool kvm_set_pmuserenr(u64 val)
>   static inline void kvm_vcpu_pmu_resync_el0(void) {}
>   static inline void kvm_host_pmu_init(struct arm_pmu *pmu) {}
>   
> +static inline void kvm_pmu_host_counters_enable(void) {}
> +static inline void kvm_pmu_host_counters_disable(void) {}
> +
>   #endif
>   
>   #endif
> diff --git a/arch/arm64/kvm/pmu-part.c b/arch/arm64/kvm/pmu-part.c
> index e74fecc67e37..51da65c678f9 100644
> --- a/arch/arm64/kvm/pmu-part.c
> +++ b/arch/arm64/kvm/pmu-part.c
> @@ -45,3 +45,19 @@ void kvm_pmu_partition(struct arm_pmu *pmu)
>   		pmu->partitioned = false;
>   	}
>   }
> +
> +void kvm_pmu_host_counters_enable(void)
> +{
> +	u64 mdcr = read_sysreg(mdcr_el2);
> +
> +	mdcr |= MDCR_EL2_HPME;
> +	write_sysreg(mdcr, mdcr_el2);
> +}
> +
> +void kvm_pmu_host_counters_disable(void)
> +{
> +	u64 mdcr = read_sysreg(mdcr_el2);
> +
> +	mdcr &= ~MDCR_EL2_HPME;
> +	write_sysreg(mdcr, mdcr_el2);
> +}
> diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
> index 0e360feb3432..442dcff56d5b 100644
> --- a/drivers/perf/arm_pmuv3.c
> +++ b/drivers/perf/arm_pmuv3.c
> @@ -730,15 +730,19 @@ static void armv8pmu_disable_event_irq(struct perf_event *event)
>   	armv8pmu_disable_intens(BIT(event->hw.idx));
>   }
>   
> -static u64 armv8pmu_getreset_flags(void)
> +static u64 armv8pmu_getreset_flags(struct arm_pmu *cpu_pmu)
>   {
>   	u64 value;
>   
>   	/* Read */
>   	value = read_pmovsclr();
>   
> +	if (cpu_pmu->partitioned)
> +		value &= ARMV8_PMU_HOST_CNT_PART(cpu_pmu->hpmn);
> +	else
> +		value &= ARMV8_PMU_OVERFLOWED_MASK;
> +
>   	/* Write to clear flags */
> -	value &= ARMV8_PMU_OVERFLOWED_MASK;
>   	write_pmovsclr(value);
>   
>   	return value;
> @@ -765,6 +769,18 @@ static void armv8pmu_disable_user_access(void)
>   	update_pmuserenr(0);
>   }
>   
> +static bool armv8pmu_is_guest_part(struct arm_pmu *cpu_pmu, u8 idx)
> +{
> +	return cpu_pmu->partitioned &&
> +		(BIT(idx) & ARMV8_PMU_GUEST_CNT_PART(cpu_pmu->hpmn));
> +}
> +
> +static bool armv8pmu_is_host_part(struct arm_pmu *cpu_pmu, u8 idx)
> +{
> +	return !cpu_pmu->partitioned ||
> +		(BIT(idx) & ARMV8_PMU_HOST_CNT_PART(cpu_pmu->hpmn));
> +}
> +
>   static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
>   {
>   	int i;
> @@ -773,6 +789,8 @@ static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
>   	if (is_pmuv3p9(cpu_pmu->pmuver)) {
>   		u64 mask = 0;
>   		for_each_set_bit(i, cpuc->used_mask, ARMPMU_MAX_HWEVENTS) {
> +			if (armv8pmu_is_guest_part(cpu_pmu, i))
> +				continue;

Hi Colton,

Is it possible to keep the guest bits out of used_mask and cntr_mask in 
the first place? Then all these loops don't need to have the logic for 
is_guest_part()/is_host_part().

That leads me to wonder about updating the printout:

  hw perfevents: enabled with armv8_pmuv3_0 PMU driver, 7 (0,8000003f)
    counters available

It might be a bit confusing if that doesn't quite reflect reality anymore.

Thanks
James



From james.clark at linaro.org  Mon Mar 24 07:53:49 2025
From: james.clark at linaro.org (James Clark)
Date: Mon, 24 Mar 2025 14:53:49 +0000
Subject: [RFC PATCH v3 5/8] KVM: arm64: Introduce module param to
 partition the PMU
In-Reply-To: <20250213180317.3205285-6-coltonlewis@google.com>
References: <20250213180317.3205285-1-coltonlewis@google.com>
 <20250213180317.3205285-6-coltonlewis@google.com>
Message-ID: <d018f56a-15c3-4739-b8f4-aea863006765@linaro.org>



On 13/02/2025 6:03 pm, Colton Lewis wrote:
> For PMUv3, the register MDCR_EL2.HPMN partitiones the PMU counters
> into two ranges where counters 0..HPMN-1 are accessible by EL1 and, if
> allowed, EL0 while counters HPMN..N are only accessible by EL2.
> 
> Introduce a module parameter in KVM to set this register. The name
> reserved_host_counters reflects the intent to reserve some counters
> for the host so the guest may eventually be allowed direct access to a
> subset of PMU functionality for increased performance.
> 
> Track HPMN and whether the pmu is partitioned in struct arm_pmu
> because both KVM and the PMUv3 driver will need to know that to handle
> guests correctly.
> 
> Due to the difficulty this feature would create for the driver running
> at EL1 on the host, partitioning is only allowed in VHE mode. Working
> on nVHE mode would require a hypercall for every register access
> because the counters reserved for the host by HPMN are now only
> accessible to EL2.
> 
> The parameter is only configurable at boot time. Making the parameter
> configurable on a running system is dangerous due to the difficulty of
> knowing for sure no counters are in use anywhere so it is safe to
> reporgram HPMN.
> 

Hi Colton,

For some high level feedback for the RFC, it probably makes sense to 
include the other half of the feature at the same time. I think there is 
a risk that it requires something slightly different than what's here 
and there ends up being some churn.

Other than that I think it looks ok apart from some minor code review nits.

I was also thinking about how BRBE interacts with this. Alex has done 
some analysis that finds that it's difficult to use BRBE in guests with 
virtualized counters due to the fact that BRBE freezes on any counter 
overflow, rather than just guest ones. That leaves the guest with branch 
blackout windows in the delay between a host counter overflowing and the 
interrupt being taken and BRBE being restarted.

But with HPMN, BRBE does allow freeze on overflow of only one partition 
or the other (or both, but I don't think we'd want that) e.g.:

  RNXCWF: If EL2 is implemented, a BRBE freeze event occurs when all of
  the following are true:

  * BRBCR_EL1.FZP is 1.
  * Generation of Branch records is not paused.
  * PMOVSCLR_EL0[(MDCR_EL2.HPMN-1):0] is nonzero.
  * The PE is in a BRBE Non-prohibited region.

Unfortunately that means we could only let guests use BRBE with a 
partitioned PMU, which would massively reduce flexibility if hosts have 
to lose counters just so the guest can use BRBE.

I don't know if this is a stupid idea, but instead of having a fixed 
number for the partition, wouldn't it be nice if we could trap and 
increment HPMN on the first guest use of a counter, then decrement it on 
guest exit depending on what's still in use? The host would always 
assign its counters from the top down, and guests go bottom up if they 
want PMU passthrough. Maybe it's too complicated or won't work for 
various reasons, but because of BRBE the counter partitioning changes go 
from an optimization to almost a necessity.

> Signed-off-by: Colton Lewis <coltonlewis at google.com>
> ---
>   arch/arm64/include/asm/kvm_pmu.h |  4 +++
>   arch/arm64/kvm/Makefile          |  2 +-
>   arch/arm64/kvm/debug.c           |  9 ++++--
>   arch/arm64/kvm/pmu-part.c        | 47 ++++++++++++++++++++++++++++++++
>   arch/arm64/kvm/pmu.c             |  2 ++
>   include/linux/perf/arm_pmu.h     |  2 ++
>   6 files changed, 62 insertions(+), 4 deletions(-)
>   create mode 100644 arch/arm64/kvm/pmu-part.c
> 
> diff --git a/arch/arm64/include/asm/kvm_pmu.h b/arch/arm64/include/asm/kvm_pmu.h
> index 613cddbdbdd8..174b7f376d95 100644
> --- a/arch/arm64/include/asm/kvm_pmu.h
> +++ b/arch/arm64/include/asm/kvm_pmu.h
> @@ -22,6 +22,10 @@ bool kvm_set_pmuserenr(u64 val);
>   void kvm_vcpu_pmu_resync_el0(void);
>   void kvm_host_pmu_init(struct arm_pmu *pmu);
>   
> +u8 kvm_pmu_get_reserved_counters(void);
> +u8 kvm_pmu_hpmn(u8 nr_counters);
> +void kvm_pmu_partition(struct arm_pmu *pmu);
> +
>   #else
>   
>   static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) {}
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 3cf7adb2b503..065a6b804c84 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -25,7 +25,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
>   	 vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \
>   	 vgic/vgic-its.o vgic/vgic-debug.o
>   
> -kvm-$(CONFIG_HW_PERF_EVENTS)  += pmu-emul.o pmu.o
> +kvm-$(CONFIG_HW_PERF_EVENTS)  += pmu-emul.o pmu-part.o pmu.o
>   kvm-$(CONFIG_ARM64_PTR_AUTH)  += pauth.o
>   kvm-$(CONFIG_PTDUMP_STAGE2_DEBUGFS) += ptdump.o
>   
> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
> index 7fb1d9e7180f..b5ac5a213877 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -31,15 +31,18 @@
>    */
>   static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
>   {
> +	u8 counters = *host_data_ptr(nr_event_counters);
> +	u8 hpmn = kvm_pmu_hpmn(counters);
> +
>   	preempt_disable();
>   

Would you not need to use vcpu->cpu here to access host_data? The 
preempt_disable() after the access seems suspicious. I think you'll end 
up with the same issue as here:

https://lore.kernel.org/kvmarm/5edb7c69-f548-4651-8b63-1643c5b13dac at linaro.org/

>   	/*
>   	 * This also clears MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK
>   	 * to disable guest access to the profiling and trace buffers
>   	 */
> -	vcpu->arch.mdcr_el2 = FIELD_PREP(MDCR_EL2_HPMN,
> -					 *host_data_ptr(nr_event_counters));
> -	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
> +	vcpu->arch.mdcr_el2 = FIELD_PREP(MDCR_EL2_HPMN, hpmn);
> +	vcpu->arch.mdcr_el2 |= (MDCR_EL2_HPMD |
> +				MDCR_EL2_TPM |
>   				MDCR_EL2_TPMS |
>   				MDCR_EL2_TTRF |
>   				MDCR_EL2_TPMCR |
> diff --git a/arch/arm64/kvm/pmu-part.c b/arch/arm64/kvm/pmu-part.c
> new file mode 100644
> index 000000000000..e74fecc67e37
> --- /dev/null
> +++ b/arch/arm64/kvm/pmu-part.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2025 Google LLC
> + * Author: Colton Lewis <coltonlewis at google.com>
> + */
> +
> +#include <linux/kvm_host.h>
> +#include <linux/perf/arm_pmu.h>
> +
> +#include <asm/kvm_pmu.h>
> +
> +static u8 reserved_host_counters __read_mostly;
> +
> +module_param(reserved_host_counters, byte, 0);
> +MODULE_PARM_DESC(reserved_host_counters,
> +		 "Partition the PMU into host and guest counters");
> +
> +u8 kvm_pmu_get_reserved_counters(void)
> +{
> +	return reserved_host_counters;
> +}
> +
> +u8 kvm_pmu_hpmn(u8 nr_counters)
> +{
> +	if (reserved_host_counters >= nr_counters) {
> +		if (this_cpu_has_cap(ARM64_HAS_HPMN0))
> +			return 0;
> +
> +		return 1;
> +	}
> +
> +	return nr_counters - reserved_host_counters;
> +}
> +
> +void kvm_pmu_partition(struct arm_pmu *pmu)
> +{
> +	u8 nr_counters = *host_data_ptr(nr_event_counters);
> +	u8 hpmn = kvm_pmu_hpmn(nr_counters);
> +
> +	if (hpmn < nr_counters) {
> +		pmu->hpmn = hpmn;
> +		pmu->partitioned = true;

Looks like Rob's point about pmu->partitioned being duplicate data 
stands again. On the previous version you mentioned that saving it was 
to avoid reading PMCR.N, but now it's not based on PMCR.N anymore.

Thanks
James



From andre.draszik at linaro.org  Mon Mar 24 08:34:09 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Mon, 24 Mar 2025 15:34:09 +0000
Subject: [PATCH v2 1/2] firmware: exynos-acpm: use ktime APIs for timeout
 detection
In-Reply-To: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
References: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
Message-ID: <20250324-acpm-atomic-v2-1-7d87746e1765@linaro.org>

acpm_dequeue_by_polling() uses a loop counter and assumes that each
iteration of the loop takes 20us. It may take longer, though, because
usleep_range() may sleep a different amount.

Switch to using ktime_get() / ktime_before() to detect the timeout
condition more reliably.

This change also makes the code easier to follow and it allows us to
adjust the sleep without having to adjust the loop counter exit
condition. This will come in useful in a follow-up patch that changes
the delays.

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
v2:
* add missing ktime.h
* ktime_before() instead of !ktime_after() (Tudor)
---
 drivers/firmware/samsung/exynos-acpm.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..542eaff03f9e39422a8c5345ca75e05c1710a9ee 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -15,6 +15,7 @@
 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/ktime.h>
 #include <linux/mailbox/exynos-message.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
@@ -32,8 +33,7 @@
 
 #define ACPM_PROTOCOL_SEQNUM		GENMASK(21, 16)
 
-/* The unit of counter is 20 us. 5000 * 20 = 100 ms */
-#define ACPM_POLL_TIMEOUT		5000
+#define ACPM_POLL_TIMEOUT_US		(100 * USEC_PER_MSEC)
 #define ACPM_TX_TIMEOUT_US		500000
 
 #define ACPM_GS101_INITDATA_BASE	0xa000
@@ -284,12 +284,13 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 				   const struct acpm_xfer *xfer)
 {
 	struct device *dev = achan->acpm->dev;
-	unsigned int cnt_20us = 0;
+	ktime_t timeout;
 	u32 seqnum;
 	int ret;
 
 	seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
 
+	timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
 	do {
 		ret = acpm_get_rx(achan, xfer);
 		if (ret)
@@ -300,11 +301,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 
 		/* Determined experimentally. */
 		usleep_range(20, 30);
-		cnt_20us++;
-	} while (cnt_20us < ACPM_POLL_TIMEOUT);
+	} while (ktime_before(ktime_get(), timeout));
 
-	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx, cnt_20us = %d.\n",
-		achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us);
+	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
+		achan->id, seqnum, achan->bitmap_seqnum[0]);
 
 	return -ETIME;
 }

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Mon Mar 24 08:34:08 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Mon, 24 Mar 2025 15:34:08 +0000
Subject: [PATCH v2 0/2] firmware: exynos-acpm: allow use during system
 shutdown
Message-ID: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>

One user of this ACPM driver is a PMIC driver that needs to communicate
with the PMIC during late system shutdown [1] and at that time we are
not allowed to sleep anymore.

This series address this by switching the code to using udelay() in the
specific case of system shutdown. This approach was inspired by I2C's
i2c_in_atomic_xfer_mode(), which has to deal with a similar corner
case.

Link: https://lore.kernel.org/all/20250323-s2mpg10-v1-29-d08943702707 at linaro.org/ [1]

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Changes in v2:
- add missing ktime.h include
- switch to ktime_before() instead of !ktime_after()
- add link to user requiring this change to cover letter
- collect Tudor's Rb
- Link to v1: https://lore.kernel.org/r/20250321-acpm-atomic-v1-0-fb887bde7e61 at linaro.org

---
Andr? Draszik (2):
      firmware: exynos-acpm: use ktime APIs for timeout detection
      firmware: exynos-acpm: allow use during system shutdown

 drivers/firmware/samsung/exynos-acpm.c | 35 +++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)
---
base-commit: 9388ec571cb1adba59d1cded2300eeb11827679c
change-id: 20250321-acpm-atomic-033775b051ef

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Mon Mar 24 08:34:10 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Mon, 24 Mar 2025 15:34:10 +0000
Subject: [PATCH v2 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
References: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
Message-ID: <20250324-acpm-atomic-v2-2-7d87746e1765@linaro.org>

We need to access the PMIC during late system shutdown and at that time
we are not allowed to sleep anymore.

To make this case work, detect this condition and use busy waiting via
udelay() instead of usleep_range() in that situation.

The code isn't switched over to udelay() unconditionally so as to not
waste resources during normal operation. acpm_may_sleep() was heavily
inspired by the I2C subsystem's i2c_in_atomic_xfer_mode().

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
udelay(10) causes a checkpatch warning (it suggests to use
usleep_range() instead for usec >= 10), but that's exactly what we can
not do.
Reducing the udelay to be smaller will generally cause the loop to be
iterated more than once, which I wanted to avoid.
I could reflow the code to hide the actual value from checkpatch, e.g.
with the help of a local variable if that is preferred to ignoring the
checkpatch warning.
---
 drivers/firmware/samsung/exynos-acpm.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 542eaff03f9e39422a8c5345ca75e05c1710a9ee..4f65f7ef39b5fdbf5bb10f6ee9ffb78c5e34d8b2 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -15,6 +15,8 @@
 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/irqflags.h>
+#include <linux/kernel.h>
 #include <linux/ktime.h>
 #include <linux/mailbox/exynos-message.h>
 #include <linux/mailbox_client.h>
@@ -25,6 +27,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/preempt.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -273,6 +276,17 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
 	return 0;
 }
 
+/*
+ * When ACPM transfers happen very late, e.g. to access a PMIC when powering
+ * down, we can not sleep. We do want to sleep in the normal case, though, to
+ * avoid wasting CPU cycles!
+ */
+static bool acpm_may_sleep(void)
+{
+	return system_state <= SYSTEM_RUNNING ||
+		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
+}
+
 /**
  * acpm_dequeue_by_polling() - RX dequeue by polling.
  * @achan:	ACPM channel info.
@@ -300,7 +314,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 			return 0;
 
 		/* Determined experimentally. */
-		usleep_range(20, 30);
+		if (!acpm_may_sleep())
+			udelay(10);
+		else
+			usleep_range(20, 30);
 	} while (ktime_before(ktime_get(), timeout));
 
 	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Mon Mar 24 08:47:54 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Mon, 24 Mar 2025 15:47:54 +0000
Subject: [PATCH] firmware: exynos-acpm: check saved RX before bailing
 out on empty RX queue
In-Reply-To: <20250324-acpm-drained-rx-queue-v1-1-577774335151@linaro.org>
References: <20250324-acpm-drained-rx-queue-v1-1-577774335151@linaro.org>
Message-ID: <8c453ce602ab10e09104184fca5310233a9f67e2.camel@linaro.org>

On Mon, 2025-03-24 at 12:35 +0000, Tudor Ambarus wrote:
> When we're polling for responses and get a response that corresponds to
> another request, we save the RX data in order to drain the RX queue.
> 
> If the response for the current request is not found in the request's
> iteration of the queue, or if the queue is empty, we must check whether
> the RX data was saved by a previous request when it drained the RX queue.
> 
> We failed to check for already saved responses when the queue was empty,
> and requests could time out. Check saved RX before bailing out on empty
> RX queue.
> 
> Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
> Reported-by: Andr? Draszik <andre.draszik at linaro.org>
> Signed-off-by: Tudor Ambarus <tudor.ambarus at linaro.org>
> ---
> on top of krzk/for-next
> ---
> ?drivers/firmware/samsung/exynos-acpm.c | 44 +++++++++++++++++++++++-----------
> ?1 file changed, 30 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
> index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..15e991b99f5a384a299c1baf6b279fc93244bcf2 100644
> --- a/drivers/firmware/samsung/exynos-acpm.c
> +++ b/drivers/firmware/samsung/exynos-acpm.c
> @@ -184,6 +184,29 @@ struct acpm_match_data {
> ?#define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl)
> ?#define handle_to_acpm_info(h) container_of(h, struct acpm_info, handle)
> ?
> +/**
> + * acpm_get_saved_rx() - get the response if it was already saved.
> + * @achan:	ACPM channel info.
> + * @xfer:	reference to the transfer to get response for.
> + * @tx_seqnum:	xfer TX sequence number.
> + */
> +static void acpm_get_saved_rx(struct acpm_chan *achan,
> +			????? const struct acpm_xfer *xfer, u32 tx_seqnum)
> +{
> +	const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
> +	u32 rx_seqnum;
> +
> +	if (!rx_data->response)
> +		return;
> +
> +	rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
> +
> +	if (rx_seqnum == tx_seqnum) {

To help the casual reader, maybe add a comment to say that this condition is true
if/when the response was received, and before reception rx_seqnum will be == 0,
because acpm_prepare_xfer() clears it - i.e. it is not ever supposed to be any
arbitrary number. It's kinda implied, but a comment like that would make this
more explicit. If I'm getting this all right.

Other that that;

Reviewed-by: Andr? Draszik <andre.draszik at linaro.org>
Tested-by: Andr? Draszik <andre.draszik at linaro.org>

> +		memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
> +		clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
> +	}
> +}
> +
> ?/**
> ? * acpm_get_rx() - get response from RX queue.
> ? * @achan:	ACPM channel info.
> @@ -204,15 +227,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
> ?	rx_front = readl(achan->rx.front);
> ?	i = readl(achan->rx.rear);
> ?
> -	/* Bail out if RX is empty. */
> -	if (i == rx_front)
> +	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
> +
> +	if (i == rx_front) {
> +		acpm_get_saved_rx(achan, xfer, tx_seqnum);
> ?		return 0;
> +	}
> ?
> ?	base = achan->rx.base;
> ?	mlen = achan->mlen;
> ?
> -	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
> -
> ?	/* Drain RX queue. */
> ?	do {
> ?		/* Read RX seqnum. */
> @@ -259,16 +283,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
> ?	 * If the response was not in this iteration of the queue, check if the
> ?	 * RX data was previously saved.
> ?	 */
> -	rx_data = &achan->rx_data[tx_seqnum - 1];
> -	if (!rx_set && rx_data->response) {
> -		rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM,
> -				????? rx_data->cmd[0]);
> -
> -		if (rx_seqnum == tx_seqnum) {
> -			memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
> -			clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
> -		}
> -	}
> +	if (!rx_set)
> +		acpm_get_saved_rx(achan, xfer, tx_seqnum);
> ?
> ?	return 0;
> ?}
> 
> ---
> base-commit: f0dbe0d40d08199109cb689849877694a8b91033
> change-id: 20250324-acpm-drained-rx-queue-ec316d4cbcdf
> 
> Best regards,



From mike.looijmans at topic.nl  Mon Mar 24 08:46:55 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Mon, 24 Mar 2025 16:46:55 +0100
Subject: [PATCH] pcie-xilinx: Support reset GPIO and wait for link-up
 status
In-Reply-To: <vazbdawfo4jnct4rdokknxwvknespcf33jzrmobsnecbxnrbjn@kbvxvhrow4fn>
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.c4ab15e9-561e-402d-bf39-9e852485e4fa@emailsignatures365.codetwo.com>
 <20250314145933.27902-1-mike.looijmans@topic.nl>
 <vazbdawfo4jnct4rdokknxwvknespcf33jzrmobsnecbxnrbjn@kbvxvhrow4fn>
Message-ID: <0e7637a0-8b8f-4aa7-be46-1e7b8ac07a45@topic.nl>

On 24-03-2025 08:49, Manivannan Sadhasivam wrote:
> On Fri, Mar 14, 2025 at 03:59:02PM +0100, Mike Looijmans wrote:
>> Support providing the PERST reset signal through a devicetree binding.
> Where is the bindings change?

Will add in v2


>> Thus the system no longer relies on external components to perform the
>> bus reset.
>>
> There is a similar series for the CPM controller:
> https://lore.kernel.org/linux-pci/20250318092648.2298280-1-sai.krishna.musham at amd.com/
>
> Please take a look for reference.

Seems similar indeed. (You may have noticed we've actually been using 
this patch for a few years)


>> When the driver loads, the transceiver may still be in the state of
>> setting up a link. Wait for that to complete before continuing. This
>> fixes that the PCIe core does not work when loading the PL bitstream
>> from userspace. There's only milliseconds between the FPGA boot and the
>> core initializing in that case, and the link won't be up yet. The design
>> works when the FPGA was programmed in the bootloader, as that will give
>> the system hundreds of milliseconds to boot.
>>
>> As the PCIe spec mentions about 120 ms time to establish a link, we'll
>> allow up to 200ms before giving up.
>>
> This should be a separate change/patch.

Indeed, this is a separate issue, I'll split it in two parts.


>> Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
>> ---
>>
>>   drivers/pci/controller/pcie-xilinx.c | 25 ++++++++++++++++++++++++-
>>   1 file changed, 24 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
>> index 0b534f73a942..cd09deba0ddc 100644
>> --- a/drivers/pci/controller/pcie-xilinx.c
>> +++ b/drivers/pci/controller/pcie-xilinx.c
>> @@ -15,8 +15,10 @@
>>   #include <linux/irqdomain.h>
>>   #include <linux/kernel.h>
>>   #include <linux/init.h>
>> +#include <linux/iopoll.h>
>>   #include <linux/msi.h>
>>   #include <linux/of_address.h>
>> +#include <linux/of_gpio.h>
>>   #include <linux/of_pci.h>
>>   #include <linux/of_platform.h>
>>   #include <linux/of_irq.h>
>> @@ -126,6 +128,14 @@ static inline bool xilinx_pcie_link_up(struct xilinx_pcie *pcie)
>>   		XILINX_PCIE_REG_PSCR_LNKUP) ? 1 : 0;
>>   }
>>   
>> +static int xilinx_pci_wait_link_up(struct xilinx_pcie *pcie)
>> +{
>> +	u32 val;
>> +
>> +	return readl_poll_timeout(pcie->reg_base + XILINX_PCIE_REG_PSCR, val,
>> +			(val & XILINX_PCIE_REG_PSCR_LNKUP), 2000, 200000);
>> +}
>> +
>>   /**
>>    * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
>>    * @pcie: PCIe port information
>> @@ -492,8 +502,21 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie *pcie)
>>   static void xilinx_pcie_init_port(struct xilinx_pcie *pcie)
>>   {
>>   	struct device *dev = pcie->dev;
>> +	struct gpio_desc *perst_gpio;
>> +
>> +	perst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>> +	if (IS_ERR(perst_gpio)) {
>> +		dev_err(dev, "gpio request failed: %d\n", PTR_ERR(perst_gpio));
>> +		perst_gpio = NULL;
> No. If the GPIO is defined in DT and there is a problem in acquiring it, you
> should return the error.

Agree. And also, this should be moved to probe() so it can handle 
deferred properly.


>> +	}
>> +
>> +	if (perst_gpio) {
> This check is not needed as gpiod_set_value_cansleep() can accept NULL.

The check is to prevent the extra "sleep" calls. If the reset was 
performed externally (some bootloader or POR logic) the sleep calls 
should be skipped.


> - Mani
Thanks for your feedback.

-- 
Mike Looijmans
System Expert

TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl





From robh at kernel.org  Mon Mar 24 08:49:19 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 10:49:19 -0500
Subject: [PATCH v2 07/11] dt-bindings: phy: Add documentation for Airoha
 AN7581 USB PHY
In-Reply-To: <20250320130054.4804-8-ansuelsmth@gmail.com>
References: <20250320130054.4804-1-ansuelsmth@gmail.com>
 <20250320130054.4804-8-ansuelsmth@gmail.com>
Message-ID: <20250324154919.GA101272-robh@kernel.org>

On Thu, Mar 20, 2025 at 02:00:30PM +0100, Christian Marangi wrote:
> Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
> for the USB controller.
> 
> Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> always supported. The USB 3.0 mode is optional and depends on the Serdes
> mode currently configured on the system for the USB port.
> 
> If the airoha,serdes-port property is not declared, it's assumed USB 3.0
> mode is not supported, as the Serdes mode can't be validated.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  .../bindings/phy/airoha,an7581-usb-phy.yaml   | 83 +++++++++++++++++++
>  MAINTAINERS                                   |  7 ++
>  .../dt-bindings/phy/airoha,an7581-usb-phy.h   | 11 +++
>  3 files changed, 101 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
>  create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h
> 
> diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> new file mode 100644
> index 000000000000..39ceaded5d0e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> @@ -0,0 +1,83 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7581 SoC USB PHY
> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth at gmail.com>
> +
> +description: >
> +  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
> +
> +  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
> +  always supported. The USB 3.0 mode is optional and depends on the Serdes
> +  mode currently configured on the system for the USB port.
> +
> +  If the airoha,serdes-port property is not declared, it's assumed USB 3.0
> +  mode is not supported, as the Serdes mode can't be validated.
> +
> +properties:
> +  compatible:
> +    const: airoha,an7581-usb-phy
> +
> +  reg:
> +    maxItems: 1
> +
> +
> +  airoha,usb2-monitor-clk-sel:
> +    description: Describe what oscillator across the available 4
> +      should be selected for USB 2.0 Slew Rate calibration.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3]
> +
> +  airoha,serdes-port:
> +    description: Describe what Serdes Port is attached to the USB 3.0 port.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3]

Since you only have a single value here, does that mean only only one of 
the 2 ports/phys supports USB3?

> +
> +  airoha,scu:
> +    description: Phandle to the SCU node for USB 3.0 Serdes mode validation.
> +    $ref: /schemas/types.yaml#/definitions/phandle

A bit unusual, but you could use the phys binding here instead of these 
2 properties. The phy for the phy...

> +
> +  '#phy-cells':
> +    const: 1

Please add a description of what's in the cell.

> +
> +required:
> +  - compatible
> +  - reg
> +  - airoha,usb2-monitor-clk-sel
> +  - '#phy-cells'
> +
> +dependentRequired:
> +  airoha,serdes-port: [ 'airoha,scu' ]
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/phy/airoha,an7581-usb-phy.h>
> +    #include <dt-bindings/soc/airoha,scu-ssr.h>
> +
> +    phy at 1fac0000 {
> +        compatible = "airoha,an7581-usb-phy";
> +        reg = <0x1fac0000 0x10000>;
> +
> +        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL1>;
> +        airoha,scu = <&scu>;
> +        airoha,serdes-port = <AIROHA_SCU_SERDES_USB1>;
> +
> +        #phy-cells = <1>;
> +    };
> +
> +    phy at 1fae0000 {
> +        compatible = "airoha,an7581-usb-phy";
> +        reg = <0x1fae0000 0x10000>;
> +
> +        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL2>;
> +
> +        #phy-cells = <1>;
> +    };

Drop the 2nd example.

Rob


From robh at kernel.org  Mon Mar 24 09:02:34 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 11:02:34 -0500
Subject: [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC
 yaml for MT8196
In-Reply-To: <20250321093435.94835-6-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-6-paul-pl.chen@mediatek.com>
Message-ID: <20250324160234.GA113887-robh@kernel.org>

On Fri, Mar 21, 2025 at 05:33:34PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen at mediatek.com>
> 
> Add mediate,outproc.yaml to support OUTPROC for MT8196.
> MediaTek display overlap output processor, namely OVL_OUTPROC
> or OUTPROC,handles the post-stage of pixel processing in the
> overlapping procedure.
> 
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>  .../display/mediatek/mediatek,outproc.yaml    | 54 +++++++++++++++++++
>  1 file changed, 54 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
> new file mode 100644
> index 000000000000..f42e9abc1436
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
> @@ -0,0 +1,54 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/mediatek/mediatek,outproc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek display overlap output processor
> +
> +maintainers:
> +  - Chun-Kuang Hu <chunkuang.hu at kernel.org>
> +  - Philipp Zabel <p.zabel at pengutronix.de>
> +
> +description: |

Don't need '|' if no formatting to preserve.

> +  MediaTek display overlap output processor, namely OVL_OUTPROC or OUTPROC,
> +  handles the post-stage of pixel processing in the overlapping procedure.
> +  OVL_OUTPROC manages pixels for gamma correction and ensures that pixel
> +  values are within the correct range.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8196-outproc
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        disp_ovl0_outproc0: outproc at 32970000 {

Drop unused labels.

> +            compatible = "mediatek,mt8196-outproc";
> +            reg = <0 0x32970000 0 0x1000>;
> +            clocks = <&ovlsys_config_clk 49>;
> +            interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH 0>;
> +        };
> +    };
> -- 
> 2.45.2
> 


From yury.norov at gmail.com  Mon Mar 24 09:11:01 2025
From: yury.norov at gmail.com (Yury Norov)
Date: Mon, 24 Mar 2025 12:11:01 -0400
Subject: [PATCH 0/3] bits: Split asm and non-asm GENMASK*() and unify
 definitions
In-Reply-To: <20250322-consolidate-genmask-v1-0-54bfd36c5643@wanadoo.fr>
References: <20250322-consolidate-genmask-v1-0-54bfd36c5643@wanadoo.fr>
Message-ID: <Z-GEFcciqCwxL88W@thinkpad>

+ Anshuman Khandual, Catalin Marinas, linux-arm-kernel at lists.infradead.org

This series moves GENMASK_U128 out of uapi. ARM is the only proposed
user. Add ARM people for visibility.

Thanks,
Yury

On Sat, Mar 22, 2025 at 07:39:35PM +0900, Vincent Mailhol via B4 Relay wrote:
> This is a subset of below series:
> 
>   bits: Fixed-type GENMASK_U*() and BIT_U*()
>   Link: https://lore.kernel.org/r/20250308-fixed-type-genmasks-v6-0-f59315e73c29 at wanadoo.fr
> 
> Yury suggested to split the above series in two steps:
> 
>   #1 Introduce the new fixed type GENMASK_U*()
>   #2 Consolidate the existing GENMASK*()
> 
> This new series is the resulting step #2 following the split.
> 
> And thus, this series consolidate all the non-asm GENMASK*() so that
> they now all depend on GENMASK_TYPE() which was introduced in step #1.
> 
> To do so, I had to split the definition of the asm and non-asm
> GENMASK(). I think this is controversial. So I initially implemented a
> first draft in which both the asm and non-asm version would rely on
> the same helper macro, i.e. adding this:
> 
>   #define __GENMASK_TYPE(t, w, h, l)		\
>   	(((t)~_ULL(0) << (l)) &			\
>   	 ((t)~_ULL(0) >> (w - 1 - (h))))
> 
> to uapi/bits.h. And then, the different GENMASK()s would look like
> this:
> 
>   #define __GENMASK(h, l) __GENMASK_TYPE(unsigned long, __BITS_PER_LONG, h, l)
> 
> and so on.
> 
> I implemented it, and the final result looked quite ugly. Not only do
> we need to manually provide the width each time, the biggest concern
> is that adding this to the uapi is asking for trouble. Who knows how
> people are going to use this? And once it is in the uapi, there is
> virtually no way back.
> 
> Adding to this, that macro can not even be generalized to u128
> integers, whereas after the split, it can.
> 
> And so, after implementing both, the asm and non-asm split seems way
> more clean and I think this is the best compromise.
> 
> Aside from the split, the asm's GENMASK() and GENMASK_ULL() are left
> untouched. While there are some strong incentives to also simplify
> these as pointed by David Laight in this thread:
> 
>   https://lore.kernel.org/all/20250309102312.4ff08576 at pumpkin/
> 
> this series deliberately limit its scope to the non-asm variants.
> 
> Here are the bloat-o-meter stats:
> 
>   $ ./scripts/bloat-o-meter vmlinux_before.o vmlinux_after.o 
>   add/remove: 0/0 grow/shrink: 4/2 up/down: 5/-4 (1)
>   Function                                     old     new   delta
>   intel_psr_invalidate                         666     668      +2
>   mst_stream_compute_config                   1652    1653      +1
>   intel_psr_flush                              977     978      +1
>   intel_dp_compute_link_config                1327    1328      +1
>   cfg80211_inform_bss_data                    5109    5108      -1
>   intel_drrs_activate                          379     376      -3
>   Total: Before=22723481, After=22723482, chg +0.00%
> 
> (done with GCC 12.4.1 on an x86_64 defconfig)
> 
> --
> 2.43.0
> 
> Signed-off-by: Vincent Mailhol <mailhol.vincent at wanadoo.fr>
> ---
> Vincent Mailhol (3):
>       bits: split the definition of the asm and non-asm GENMASK*()
>       bits: unify the non-asm GENMASK*()
>       test_bits: add tests for __GENMASK() and __GENMASK_ULL()
> 
>  include/linux/bits.h | 29 ++++++-----------------------
>  lib/test_bits.c      | 19 +++++++++++++++++++
>  2 files changed, 25 insertions(+), 23 deletions(-)
> ---
> base-commit: e3f42c436d7e0cb432935fe3ae275dd8d9b60f71
> change-id: 20250320-consolidate-genmask-6cd02abadf82
> prerequisite-change-id: 20250228-fixed-type-genmasks-8d1a555f34e8:v7
> prerequisite-patch-id: 572c05165229640db7dd8fe4d53e1a33ee5dd586
> prerequisite-patch-id: c16d122a487f83e2866a9a669259db097ef46a70
> prerequisite-patch-id: 35f115c0f1b327f1516cfc38b3076e07713df6cd
> prerequisite-patch-id: 5fe7058f6ea73b37df75d5c39ad69a4da928058d
> prerequisite-patch-id: 82fb628d052ce9f1efac7f3b61eafb2749f95847
> 
> Best regards,
> -- 
> Vincent Mailhol <mailhol.vincent at wanadoo.fr>
> 


From helgaas at kernel.org  Mon Mar 24 09:08:38 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 24 Mar 2025 11:08:38 -0500
Subject: [PATCH] pcie-xilinx: Support reset GPIO and wait for link-up
 status
In-Reply-To: <0e7637a0-8b8f-4aa7-be46-1e7b8ac07a45@topic.nl>
Message-ID: <20250324160838.GA1251294@bhelgaas>

On Mon, Mar 24, 2025 at 04:46:55PM +0100, Mike Looijmans wrote:
> On 24-03-2025 08:49, Manivannan Sadhasivam wrote:
> > On Fri, Mar 14, 2025 at 03:59:02PM +0100, Mike Looijmans wrote:
> > > Support providing the PERST reset signal through a devicetree binding.

Use "PERST#" to include the polarity and match the spec usage.

> > > As the PCIe spec mentions about 120 ms time to establish a link, we'll
> > > allow up to 200ms before giving up.
> > > 
> > This should be a separate change/patch.
> 
> Indeed, this is a separate issue, I'll split it in two parts.

And please include a specific spec reference, e.g., "PCIe r6.0, sec
x.y.z".


From robh at kernel.org  Mon Mar 24 09:10:14 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 11:10:14 -0500
Subject: [PATCH v2 3/4] dt-bindings: arm: stm32: Document Ultratronik's
 Fly board DT binding
In-Reply-To: <20250321111821.361419-4-goran.radni@gmail.com>
References: <20250321111821.361419-1-goran.radni@gmail.com>
 <20250321111821.361419-4-goran.radni@gmail.com>
Message-ID: <174283261429.162935.4991717491782236222.robh@kernel.org>


On Fri, 21 Mar 2025 12:18:18 +0100, Goran Ra?enovi? wrote:
> From: Goran Ra?enovi? <gradenovic at ultratronik.de>
> 
> This commit documents ultra-fly-sbc devicetree binding based on
> STM32MP157 SoC.
> 
> Signed-off-by: Goran Ra?enovi? <gradenovic at ultratronik.de>
> ---
>  Documentation/devicetree/bindings/arm/stm32/stm32.yaml | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From angelogioacchino.delregno at collabora.com  Mon Mar 24 09:10:41 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 17:10:41 +0100
Subject: [PATCH v5 3/3] pinctrl: mediatek: Add pinctrl driver on mt8196
In-Reply-To: <20250321084142.18563-4-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
 <20250321084142.18563-4-ot_cathy.xu@mediatek.com>
Message-ID: <d4af318b-1bdf-4abd-842d-461a763b79a4@collabora.com>

Il 21/03/25 09:39, Cathy Xu ha scritto:
> From: Guodong Liu <guodong.liu at mediatek.com>
> 
> Add pinctrl driver support for MediaTek Soc mt8196.
> 
> Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
> Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>



From angelogioacchino.delregno at collabora.com  Mon Mar 24 09:10:42 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 17:10:42 +0100
Subject: [PATCH v5 2/3] arm64: dts: mediatek: mt8196: Add pinmux macro
 header file
In-Reply-To: <20250321084142.18563-3-ot_cathy.xu@mediatek.com>
References: <20250321084142.18563-1-ot_cathy.xu@mediatek.com>
 <20250321084142.18563-3-ot_cathy.xu@mediatek.com>
Message-ID: <334d0492-1707-4299-99c0-feacb5954de1@collabora.com>

Il 21/03/25 09:39, Cathy Xu ha scritto:
> Add the pinctrl header file on MediaTek mt8196.
> 
> Signed-off-by: Guodong Liu <guodong.liu at mediatek.com>
> Signed-off-by: Cathy Xu <ot_cathy.xu at mediatek.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>




From mathieu.poirier at linaro.org  Mon Mar 24 09:10:57 2025
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Mon, 24 Mar 2025 10:10:57 -0600
Subject: [PATCH v2] remoteproc: imx_dsp_rproc: Add support for
 DSP-specific features
In-Reply-To: <20250318215007.2109726-1-iuliana.prodan@oss.nxp.com>
References: <20250318215007.2109726-1-iuliana.prodan@oss.nxp.com>
Message-ID: <Z-GEEVMXUysX1Hhu@p14s>

Good day Iuliana,

On Tue, Mar 18, 2025 at 11:50:07PM +0200, Iuliana Prodan (OSS) wrote:
> From: Iuliana Prodan <iuliana.prodan at nxp.com>
> 
> Some DSP firmware requires a FW_READY signal before proceeding, while
> others do not.
> Therefore, add support to handle i.MX DSP-specific features.
> 
> Implement handle_rsc callback to handle resource table parsing and to
> process DSP-specific resource, to determine if waiting is needed.
> 
> Update imx_dsp_rproc_start() to handle this condition accordingly.
> 
> Signed-off-by: Iuliana Prodan <iuliana.prodan at nxp.com>
> ---
> Changes in v2:
> - Reviews from Mathieu Poirier:
>   - Use vendor-specific resource table entry.
>   - Implement resource handler specific to the i.MX DSP.
> - Revise commit message to include recent updates.
> - Link to v1: https://lore.kernel.org/all/20250305123923.514386-1-iuliana.prodan at oss.nxp.com/
> 
>  drivers/remoteproc/imx_dsp_rproc.c | 59 +++++++++++++++++++++++++++++-
>  1 file changed, 57 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
> index b9bb15970966..1729bfbc602e 100644
> --- a/drivers/remoteproc/imx_dsp_rproc.c
> +++ b/drivers/remoteproc/imx_dsp_rproc.c
> @@ -35,9 +35,17 @@ module_param_named(no_mailboxes, no_mailboxes, int, 0644);
>  MODULE_PARM_DESC(no_mailboxes,
>  		 "There is no mailbox between cores, so ignore remote proc reply after start, default is 0 (off).");
>  
> +/* Flag indicating that the remote is up and running */
>  #define REMOTE_IS_READY				BIT(0)
> +/* Flag indicating that the host should wait for a firmware-ready response */
> +#define HOST_WAIT_FW_READY			BIT(1)

Right now the default behavior is to wait for a ready message from the remote
processor.  We need to keep this implementation in order to remain backward
compatible with older firwmare images.  As such the above should be:

#define HOST_DONT_WAIT_FW_READY			BIT(1)

>  #define REMOTE_READY_WAIT_MAX_RETRIES		500
>  
> +/* This flag is set in the DSP resource table's features field to indicate
> + * that the firmware requires the host to wait for a FW_READY response.
> + */
> +#define WAIT_FW_READY				BIT(0)
> +
>  /* att flags */
>  /* DSP own area */
>  #define ATT_OWN					BIT(31)
> @@ -136,6 +144,19 @@ struct imx_dsp_rproc_dcfg {
>  	int (*reset)(struct imx_dsp_rproc *priv);
>  };
>  
> +/**
> + * struct fw_rsc_imx_dsp - i.MX DSP specific info
> + * @len: length of the resource entry
> + * @features: feature flags supported by the i.MX DSP firmware
> + *
> + * This represents a DSP-specific resource in the firmware's
> + * resource table, providing information on supported features.
> + */
> +struct fw_rsc_imx_dsp {
> +	uint32_t len;
> +	uint32_t features;
> +};
> +

This needs a version field and magic number.  Have a look at what Xilinx did for
inspiration [1] (both magic and complement of the magic number).  You will also
need a "__packed" attribute for the structure.

[1].
https://elixir.bootlin.com/linux/v6.14-rc6/source/drivers/remoteproc/xlnx_r5_remoteproc.c#L103

>  static const struct imx_rproc_att imx_dsp_rproc_att_imx8qm[] = {
>  	/* dev addr , sys addr  , size	    , flags */
>  	{ 0x596e8000, 0x556e8000, 0x00008000, ATT_OWN },
> @@ -300,6 +321,39 @@ static int imx_dsp_rproc_ready(struct rproc *rproc)
>  	return -ETIMEDOUT;
>  }
>  
> +/**
> + * imx_dsp_rproc_handle_rsc() - Handle DSP-specific resource table entries
> + * @rproc: remote processor instance
> + * @rsc_type: resource type identifier
> + * @rsc: pointer to the resource entry
> + * @offset: offset of the resource entry
> + * @avail: available space in the resource table
> + *
> + * Parse the DSP-specific resource entry and update flags accordingly.
> + * If the WAIT_FW_READY feature is set, the host must wait for the firmware
> + * to signal readiness before proceeding with execution.
> + *
> + * Return: RSC_HANDLED if processed successfully, RSC_IGNORED otherwise.
> + */
> +static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type,
> +				    void *rsc, int offset, int avail)
> +{
> +	struct imx_dsp_rproc *priv = rproc->priv;
> +	struct fw_rsc_imx_dsp *imx_dsp_rsc = rsc;
> +
> +	if (!imx_dsp_rsc || imx_dsp_rsc->len != sizeof(imx_dsp_rsc->features)) {
> +		priv->flags |= HOST_WAIT_FW_READY;

Unless I am missing something, this way of enforcing the default behavior won't
work because in older images, function imx_dsp_rproc_handle_rsc() will never be
called.

To fix this I suggest renaming HOST_WAIT_FW_READY to
HOST_DONT_WAIT_FOR_FW_READY.  That way the host can skip waiting for a FW ready
message only when it was specifically told to do so.

Thanks,
Mathieu

> +		return RSC_IGNORED;
> +	}
> +
> +	if (imx_dsp_rsc->features & WAIT_FW_READY)
> +		priv->flags |= HOST_WAIT_FW_READY;
> +	else
> +		priv->flags &= ~HOST_WAIT_FW_READY;
> +
> +	return RSC_HANDLED;
> +}
> +
>  /*
>   * Start function for rproc_ops
>   *
> @@ -335,8 +389,8 @@ static int imx_dsp_rproc_start(struct rproc *rproc)
>  
>  	if (ret)
>  		dev_err(dev, "Failed to enable remote core!\n");
> -	else
> -		ret = imx_dsp_rproc_ready(rproc);
> +	else if (priv->flags & HOST_WAIT_FW_READY)
> +		return imx_dsp_rproc_ready(rproc);
>  
>  	return ret;
>  }
> @@ -936,6 +990,7 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
>  	.kick		= imx_dsp_rproc_kick,
>  	.load		= imx_dsp_rproc_elf_load_segments,
>  	.parse_fw	= imx_dsp_rproc_parse_fw,
> +	.handle_rsc	= imx_dsp_rproc_handle_rsc,
>  	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
>  	.sanity_check	= rproc_elf_sanity_check,
>  	.get_boot_addr	= rproc_elf_get_boot_addr,
> -- 
> 2.25.1
> 


From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:52 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:52 -0400
Subject: [PATCH v3 1/5] dt-bindings: bus: add documentation for the IMX AIPSTZ bridge
In-Reply-To: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250324162556.30972-2-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Add documentation for IMX AIPSTZ bridge.

Co-developed-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
---
 .../bindings/bus/fsl,imx8mp-aipstz.yaml       | 107 ++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml

diff --git a/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml b/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
new file mode 100644
index 000000000000..c0427dfcdaca
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bus/fsl,imx8mp-aipstz.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Secure AHB to IP Slave bus (AIPSTZ) bridge
+
+description:
+  The secure AIPS bridge (AIPSTZ) acts as a bridge for AHB masters
+  issuing transactions to IP Slave peripherals. Additionally, this module
+  offers access control configurations meant to restrict which peripherals
+  a master can access.
+
+maintainers:
+  - Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
+
+properties:
+  compatible:
+    const: fsl,imx8mp-aipstz
+
+  reg:
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: bus
+      - const: ac
+
+  power-domains:
+    maxItems: 1
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 1
+
+  "#access-controller-cells":
+    const: 0
+
+  ranges: true
+
+# borrowed from simple-bus.yaml, no additional requirements for children
+patternProperties:
+  "@(0|[1-9a-f][0-9a-f]*)$":
+    type: object
+    additionalProperties: true
+    properties:
+      reg:
+        items:
+          minItems: 2
+          maxItems: 4
+        minItems: 1
+        maxItems: 1024
+      ranges:
+        oneOf:
+          - items:
+              minItems: 3
+              maxItems: 7
+            minItems: 1
+            maxItems: 1024
+          - $ref: /schemas/types.yaml#/definitions/flag
+    anyOf:
+      - required:
+          - reg
+      - required:
+          - ranges
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - power-domains
+  - "#address-cells"
+  - "#size-cells"
+  - "#access-controller-cells"
+  - ranges
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mp-clock.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    bus at 30c00000 {
+        compatible = "fsl,imx8mp-aipstz";
+        reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;
+        reg-names = "bus", "ac";
+        power-domains = <&pgc_audio>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        #access-controller-cells = <0>;
+        ranges;
+
+        dma-controller at 30e00000 {
+            compatible = "fsl,imx8mp-sdma", "fsl,imx8mq-sdma";
+            reg = <0x30e00000 0x10000>;
+            #dma-cells = <3>;
+            clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SDMA3_ROOT>,
+                     <&clk IMX8MP_CLK_AUDIO_ROOT>;
+            clock-names = "ipg", "ahb";
+            interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+            fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+        };
+    };
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:53 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:53 -0400
Subject: [PATCH v3 2/5] dt-bindings: dsp: fsl,dsp: document 'access-controllers' property
In-Reply-To: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250324162556.30972-3-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

Some DSP instances may have their access to certain peripherals
conditioned by a bus access controller such as the one from the
AIPSTZ bridge.

Add the optional 'access-controllers' property, which may be used
in such cases.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
Reviewed-by: Frank Li <Frank.Li at nxp.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 Documentation/devicetree/bindings/dsp/fsl,dsp.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
index b8693e4b4b0d..e610b7636a08 100644
--- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
@@ -91,6 +91,9 @@ properties:
       - const: runstall
       - const: softreset
 
+  access-controllers:
+    maxItems: 1
+
 required:
   - compatible
   - reg
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:54 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:54 -0400
Subject: [PATCH v3 3/5] bus: add driver for IMX AIPSTZ bridge
In-Reply-To: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250324162556.30972-4-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

The secure AHB to IP Slave (AIPSTZ) bus bridge provides access control
configurations meant to restrict access to certain peripherals.
Some of the configurations include:

	1) Marking masters as trusted for R/W. Based on this
	(and the configuration of the accessed peripheral), the bridge
	may choose to abort the R/W transactions issued by certain
	masters.

	2) Allowing/disallowing write accesses to peripherals.

Add driver for this IP. Since there's currently no framework for
access controllers (and since there's currently no need for having
flexibility w.r.t the configurations) all this driver does is it
applies a relaxed, "default" configuration, in which all masters
are trusted for R/W.

Note that some instances of this IP (e.g: AIPSTZ5 on i.MX8MP) may be tied
to a power domain and may lose their configuration when the domain is
powered off. This is why the configuration has to be restored when the
domain is powered on.

Co-developed-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
---
 drivers/bus/Kconfig      |  6 +++
 drivers/bus/Makefile     |  1 +
 drivers/bus/imx-aipstz.c | 92 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/bus/imx-aipstz.c

diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index ff669a8ccad9..fe7600283e70 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -87,6 +87,12 @@ config HISILICON_LPC
 	  Driver to enable I/O access to devices attached to the Low Pin
 	  Count bus on the HiSilicon Hip06/7 SoC.
 
+config IMX_AIPSTZ
+	tristate "Support for IMX Secure AHB to IP Slave bus (AIPSTZ) bridge"
+	depends on ARCH_MXC
+	help
+	  Enable support for IMX AIPSTZ bridge.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index cddd4984d6af..8e693fe8a03a 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_MC_BUS)	+= fsl-mc/
 
 obj-$(CONFIG_BT1_APB)		+= bt1-apb.o
 obj-$(CONFIG_BT1_AXI)		+= bt1-axi.o
+obj-$(CONFIG_IMX_AIPSTZ)	+= imx-aipstz.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_INTEL_IXP4XX_EB)	+= intel-ixp4xx-eb.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
diff --git a/drivers/bus/imx-aipstz.c b/drivers/bus/imx-aipstz.c
new file mode 100644
index 000000000000..538ad89dba30
--- /dev/null
+++ b/drivers/bus/imx-aipstz.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#define IMX_AIPSTZ_MPR0 0x0
+
+struct imx_aipstz_config {
+	u32 mpr0;
+};
+
+static void imx_aipstz_apply_default(void __iomem *base,
+				     const struct imx_aipstz_config *default_cfg)
+{
+	writel(default_cfg->mpr0, base + IMX_AIPSTZ_MPR0);
+}
+
+static int imx_aipstz_probe(struct platform_device *pdev)
+{
+	const struct imx_aipstz_config *default_cfg;
+	void __iomem *base;
+
+	base = devm_platform_ioremap_resource_byname(pdev, "ac");
+	if (IS_ERR(base))
+		return dev_err_probe(&pdev->dev, -ENOMEM,
+				     "failed to get/ioremap AC memory\n");
+
+	default_cfg = of_device_get_match_data(&pdev->dev);
+
+	imx_aipstz_apply_default(base, default_cfg);
+
+	dev_set_drvdata(&pdev->dev, base);
+
+	pm_runtime_set_active(&pdev->dev);
+	devm_pm_runtime_enable(&pdev->dev);
+
+	return devm_of_platform_populate(&pdev->dev);
+}
+
+static int imx_aipstz_runtime_resume(struct device *dev)
+{
+	const struct imx_aipstz_config *default_cfg;
+	void __iomem *base;
+
+	base = dev_get_drvdata(dev);
+	default_cfg = of_device_get_match_data(dev);
+
+	/* restore potentially lost configuration during domain power-off */
+	imx_aipstz_apply_default(base, default_cfg);
+
+	return 0;
+}
+
+static const struct dev_pm_ops imx_aipstz_pm_ops = {
+	RUNTIME_PM_OPS(NULL, imx_aipstz_runtime_resume, NULL)
+	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+};
+
+/*
+ * following configuration is equivalent to:
+ *	masters 0-7 => trusted for R/W + use AHB's HPROT[1] to det. privilege
+ */
+static const struct imx_aipstz_config imx8mp_aipstz_default_cfg = {
+	.mpr0 = 0x77777777,
+};
+
+static const struct of_device_id imx_aipstz_of_ids[] = {
+	{ .compatible = "fsl,imx8mp-aipstz", .data = &imx8mp_aipstz_default_cfg },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, imx_aipstz_of_ids);
+
+static struct platform_driver imx_aipstz_of_driver = {
+	.probe = imx_aipstz_probe,
+	.driver = {
+		.name = "imx-aipstz",
+		.of_match_table = imx_aipstz_of_ids,
+		.pm = pm_ptr(&imx_aipstz_pm_ops),
+	},
+};
+module_platform_driver(imx_aipstz_of_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IMX secure AHB to IP Slave bus (AIPSTZ) bridge driver");
+MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>");
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:55 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:55 -0400
Subject: [PATCH v3 4/5] arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
In-Reply-To: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250324162556.30972-5-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

AIPS5 is actually AIPSTZ5 as it offers some security-related
configurations. Since these configurations need to be applied before
accessing any of the peripherals on the bus, it's better to make AIPSTZ5
be their parent instead of keeping AIPS5 and adding a child node for
AIPSTZ5. Also, because of the security configurations, the address space
of the bus has to be changed to that of the configuration registers.

Finally, since AIPSTZ5 belongs to the AUDIOMIX power domain, add the
missing 'power-domains' property. The domain needs to be powered on before
attempting to configure the security-related registers.

The DT node name is not changed to avoid potential issues with DTs in
which this node is referenced.

Co-developed-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index ce6793b2d57e..ce9f6da1e257 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -1400,10 +1400,13 @@ eqos: ethernet at 30bf0000 {
 		};
 
 		aips5: bus at 30c00000 {
-			compatible = "fsl,aips-bus", "simple-bus";
-			reg = <0x30c00000 0x400000>;
+			compatible = "fsl,imx8mp-aipstz";
+			reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;
+			reg-names = "bus", "ac";
+			power-domains = <&pgc_audio>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#access-controller-cells = <0>;
 			ranges;
 
 			spba-bus at 30c00000 {
-- 
2.34.1



From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:56 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:56 -0400
Subject: [PATCH v3 5/5] arm64: dts: imx8mp: make 'dsp' node depend on 'aips5'
In-Reply-To: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
Message-ID: <20250324162556.30972-6-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

The DSP needs to access peripherals on AIPSTZ5 (to communicate with
the AP using AUDIOMIX MU, for instance). To do so, the security-related
registers of the bridge have to be configured before the DSP is started.
Enforce a dependency on AIPSTZ5 by adding the 'access-controllers'
property to the 'dsp' node.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index ce9f6da1e257..db14e85023a0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -2425,6 +2425,7 @@ dsp: dsp at 3b6e8000 {
 			mboxes = <&mu2 2 0>, <&mu2 2 1>,
 				<&mu2 3 0>, <&mu2 3 1>;
 			memory-region = <&dsp_reserved>;
+			access-controllers = <&aips5>;
 			status = "disabled";
 		};
 	};
-- 
2.34.1



From robh at kernel.org  Mon Mar 24 09:31:56 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 11:31:56 -0500
Subject: [PATCH v2 7/9] dt-bindings: gpu: mali-valhall-csf: Document
 i.MX95 support
In-Reply-To: <20250321200625.132494-8-marex@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-8-marex@denx.de>
Message-ID: <174283391598.303728.5865660880555702267.robh@kernel.org>


On Fri, 21 Mar 2025 21:05:57 +0100, Marek Vasut wrote:
> The instance of the GPU populated in Freescale i.MX95 is the
> Mali G310, document support for this variant.
> 
> Reviewed-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> Reviewed-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: David Airlie <airlied at gmail.com>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Liviu Dudau <liviu.dudau at arm.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Maxime Ripard <mripard at kernel.org>
> Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
> Cc: Philipp Zabel <p.zabel at pengutronix.de>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Sebastian Reichel <sre at kernel.org>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Simona Vetter <simona at ffwll.ch>
> Cc: Steven Price <steven.price at arm.com>
> Cc: Thomas Zimmermann <tzimmermann at suse.de>
> Cc: devicetree at vger.kernel.org
> Cc: dri-devel at lists.freedesktop.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> V2: - Add RB from Frank and Alexander
>     - Make resets: mandatory on i.MX95
>     - Switch from fsl, to nxp, vendor prefix
> ---
>  .../devicetree/bindings/gpu/arm,mali-valhall-csf.yaml    | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From krzysztof.kozlowski at linaro.org  Mon Mar 24 09:28:54 2025
From: krzysztof.kozlowski at linaro.org (Krzysztof Kozlowski)
Date: Mon, 24 Mar 2025 17:28:54 +0100
Subject: [PATCH v2 1/2] spi: dt-bindings: st,stm32mp25-ospi: Make "resets"
 a required property
In-Reply-To: <20250324-upstream_ospi_required_resets-v2-1-85a48afcedec@foss.st.com>
References: <20250324-upstream_ospi_required_resets-v2-0-85a48afcedec@foss.st.com>
 <20250324-upstream_ospi_required_resets-v2-1-85a48afcedec@foss.st.com>
Message-ID: <86a15b6d-6195-4b4a-9820-081f07fd72cc@linaro.org>

On 24/03/2025 10:40, Patrice Chotard wrote:
> On STM32MP2x SoC's family, OSPI is child of Octo Memory Manager which
> must have asccess to OSPI's reset to ensure its initialization.
> Make "resets" a required property.
> 
> Fixes: bed97e35786a ("dt-bindings: spi: Add STM32 OSPI controller")
> Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
> ---

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From jgg at nvidia.com  Mon Mar 24 09:28:53 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 24 Mar 2025 13:28:53 -0300
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation
 helpers
In-Reply-To: <20250323190204.742672-1-changyuanl@google.com>
References: <20250321133447.GA251739@nvidia.com>
 <20250323190204.742672-1-changyuanl@google.com>
Message-ID: <Z+GIRecXeYXiPrYv@nvidia.com>

On Sun, Mar 23, 2025 at 12:02:04PM -0700, Changyuan Lyu wrote:

> > Why are we changing this? I much prefered the idea of having recursive
> > FDTs than this notion copying eveything into tables then out into FDT?
> > Now that we have the preserved pages mechanism there is a pretty
> > direct path to doing recursive FDT.
> 
> We are not copying data into the hashtables, instead the hashtables only
> record the address and size of the data to be serialized into FDT.
> The idea is similar to recording preserved folios in xarray
> and then serialize it to linked pages.

I understand that, I mean you are copying the keys/tree/etc. It
doesn't seem like a good idea idea to me.
 
> > I feel like this patch is premature, it should come later in the
> > project along with a stronger justification for this approach.
> >
> > IHMO keep things simple for this series, just the very basics.
> 
> The main purpose of using hashtables is to enable KHO users to save
> data to KHO at any time, not just at the time of activate/finalize KHO
> through sysfs/debugfs. For example, FDBox can save the data into KHO
> tree once a new fd is saved to KHO. Also, using hashtables allows KHO
> users to add data to KHO concurrently, while with notifiers, KHO users'
> callbacks are executed serially.

This is why I like the recursive FDT scheme. Each serialization
operation can open its own FDT write to it and the close it
sequenatially within its operation without any worries about
concurrency.

The top level just aggregates the FDT blobs (which are in preserved
memory)

To me all this complexity here with the hash table and the copying
makes no sense compared to that. It is all around slower.

> Regarding the suggestion of recursive FDT, I feel like it is already
> doable with this patchset, or even with Mike's V4 patch. 

Of course it is doable, here we are really talk about what is the
right, recommended way to use this system. recurisive FDT is a better
methodology than hash tables

> just allocates a buffer, serialize all its states to the buffer using
> libfdt (or even using other binary formats), save the address of the
> buffer to KHO's tree, and finally register the buffer's underlying
> pages/folios with kho_preserve_folio().

Yes, exactly! I think this is how we should operate this system as a
paradig, not a giant FDT, hash table and so on...

> I changed the semantics of the notifiers. In Mike's V4, the KHO notifier
> is to pass the fdt pointer to KHO users to push data into the blob. In
> this patchset, it notifies KHO users about the last chance for saving
> data to KHO.

I think Mike's semantic makes more sense.. At least I'd want to see an
actual example of someting that wants to do a list minute adjustment
before adding the code.

> However, some KHO users may still want to add data just before kexec,
> so I kept the notifiers and allow KHO users to get notified when the
> state tree hashtables are about to be frozen and converted to FDT.

Let's try not adding API surface that has no present user as much as
possible please. You can shove this into speculative patches that
someone can pick up if they need this semantic
 
> To completely remove fdt_max, I am considering the idea in [1]. At the
> time of kexec_file_load(), we pass the address of an anchor page to
> the new kernel, and the anchor page will later be fulfilled with the
> physical addresses of the pages containing the FDT blob. Multiple
> anchor pages can be linked together. The FDT blob pages can be physically
> noncontiguous.

Yes, this is basically what I suggested too. I think this is much
prefered and doesn't require the wakky uapi.

Except I suggested you just really need a single u64 to point to a
preserved page holding the top level FDT.

With recursive FDT I think we can say that no FDT fragement should
exceed PAGE_SIZE, and things become much simpler, IMHO.

Jason


From laurentiumihalcea111 at gmail.com  Mon Mar 24 09:25:51 2025
From: laurentiumihalcea111 at gmail.com (Laurentiu Mihalcea)
Date: Mon, 24 Mar 2025 12:25:51 -0400
Subject: [PATCH v3 0/5] imx8mp: add support for the IMX AIPSTZ bridge
Message-ID: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>

From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>

The AIPSTZ bridge offers some security-related configurations which can
be used to restrict master access to certain peripherals on the bridge.

Normally, this could be done from a secure environment such as ATF before
Linux boots but the configuration of AIPSTZ5 is lost each time the power
domain is powered off and then powered on. Because of this, it has to be
configured each time the power domain is turned on and before any master
tries to access the peripherals (e.g: AP, CM7, DSP, on i.MX8MP).

The child-parent relationship between the bridge and its peripherals
should guarantee that the bridge is configured before the AP attempts
to access the IPs.

Other masters should use the 'access-controllers' property to enforce
a dependency between their device and the bridge device (see the DSP,
for example).

At the moment, we only want to apply a default, more relaxed
configuration, which is why the number of access controller cells
is 0.

The initial version of the series can be found at [1]. The new version
should provide better management of the device dependencies.

[1]: https://lore.kernel.org/linux-arm-kernel/20241119130726.2761726-1-daniel.baluta at nxp.com/

---
Changes in v3:
* make '#address-cells' and '#size-cells' constants and equal to 1 in the
binding. The bus is 32-bit.
* add child node in the example DT snippet.
* the 'aips5' DT node now contains 2 memory regions: that of the
peripherals accessible via this bridge and that of the access controller.
* link to v2: https://lore.kernel.org/lkml/20250226165314.34205-1-laurentiumihalcea111 at gmail.com/

Changes in v2:
* adress Frank Li's comments
* pick up some A-b/R-b's
* don't use "simple-bus" as the second compatible. As per Krzysztof's
comment, AIPSTZ is not a "simple-bus".
* link to v1: https://lore.kernel.org/lkml/20250221191909.31874-1-laurentiumihalcea111 at gmail.com/
---

Laurentiu Mihalcea (5):
  dt-bindings: bus: add documentation for the IMX AIPSTZ bridge
  dt-bindings: dsp: fsl,dsp: document 'access-controllers' property
  bus: add driver for IMX AIPSTZ bridge
  arm64: dts: imx8mp: convert 'aips5' to 'aipstz5'
  arm64: dts: imx8mp: make 'dsp' node depend on 'aips5'

 .../bindings/bus/fsl,imx8mp-aipstz.yaml       | 107 ++++++++++++++++++
 .../devicetree/bindings/dsp/fsl,dsp.yaml      |   3 +
 arch/arm64/boot/dts/freescale/imx8mp.dtsi     |   8 +-
 drivers/bus/Kconfig                           |   6 +
 drivers/bus/Makefile                          |   1 +
 drivers/bus/imx-aipstz.c                      |  92 +++++++++++++++
 6 files changed, 215 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
 create mode 100644 drivers/bus/imx-aipstz.c

-- 
2.34.1



From mailhol.vincent at wanadoo.fr  Mon Mar 24 09:39:25 2025
From: mailhol.vincent at wanadoo.fr (Vincent Mailhol)
Date: Tue, 25 Mar 2025 01:39:25 +0900
Subject: [PATCH 0/3] bits: Split asm and non-asm GENMASK*() and unify
 definitions
In-Reply-To: <Z-GEFcciqCwxL88W@thinkpad>
References: <20250322-consolidate-genmask-v1-0-54bfd36c5643@wanadoo.fr>
 <Z-GEFcciqCwxL88W@thinkpad>
Message-ID: <1f9ea3e3-e348-46d7-9b15-8c017762b12f@wanadoo.fr>

On 25/03/2025 at 01:11, Yury Norov wrote:
> + Anshuman Khandual, Catalin Marinas, linux-arm-kernel at lists.infradead.org
> 
> This series moves GENMASK_U128 out of uapi. ARM is the only proposed
> user. Add ARM people for visibility.

Actually, not yet. Here, I am decoupling GENMASK_U128() from
__GENMASK_U128(), but I did not touch the uapi.

After this series, __GENMASK_U128() is not used anymore in the kernel,
but I?am not brave enough to remove it myself because there is always a
risk that some userland code somewhere is relying on it?

(...)

Yours sincerely,
Vincent Mailhol



From tony.luck at intel.com  Mon Mar 24 09:54:02 2025
From: tony.luck at intel.com (Luck, Tony)
Date: Mon, 24 Mar 2025 09:54:02 -0700
Subject: [PATCH v13 2/5] arm64: add support for ARCH_HAS_COPY_MC
In-Reply-To: <df40840d-e860-397d-60bd-02f4b2d0b433@huawei.com>
References: <20241209024257.3618492-1-tongtiangen@huawei.com>
 <20241209024257.3618492-3-tongtiangen@huawei.com>
 <Z6zKfvxKnRlyNzkX@arm.com>
 <df40840d-e860-397d-60bd-02f4b2d0b433@huawei.com>
Message-ID: <Z-GOKgBNxKWQ21w4@agluck-desk3>

On Fri, Feb 14, 2025 at 09:44:02AM +0800, Tong Tiangen wrote:
> 
> 
> ? 2025/2/13 0:21, Catalin Marinas ??:
> > (catching up with old threads)
> > 
> > On Mon, Dec 09, 2024 at 10:42:54AM +0800, Tong Tiangen wrote:
> > > For the arm64 kernel, when it processes hardware memory errors for
> > > synchronize notifications(do_sea()), if the errors is consumed within the
> > > kernel, the current processing is panic. However, it is not optimal.
> > > 
> > > Take copy_from/to_user for example, If ld* triggers a memory error, even in
> > > kernel mode, only the associated process is affected. Killing the user
> > > process and isolating the corrupt page is a better choice.
> > 
> > I agree that killing the user process and isolating the page is a better
> > choice but I don't see how the latter happens after this patch. Which
> > page would be isolated?
> 
> The SEA is triggered when the page with hardware error is read. After
> that, the page is isolated in memory_failure() (mf). The processing of
> mf is mentioned in the comments of do_sea().
> 
> /*
>  * APEI claimed this as a firmware-first notification.
>  * Some processing deferred to task_work before ret_to_user().
>  */
> 
> Some processing include mf.
> 
> > 
> > > Add new fixup type EX_TYPE_KACCESS_ERR_ZERO_MEM_ERR to identify insn
> > > that can recover from memory errors triggered by access to kernel memory,
> > > and this fixup type is used in __arch_copy_to_user(), This make the regular
> > > copy_to_user() will handle kernel memory errors.
> > 
> > Is the assumption that the error on accessing kernel memory is
> > transient? There's no way to isolate the kernel page and also no point
> > in isolating the destination page either.
> 
> Yes, it's transient, the kernel page in mf can't be isolated, the
> transient access (ld) of this kernel page is currently expected to kill
> the user-mode process to avoid error spread.
> 
> 
> The SEA processes synchronization errors. Only hardware errors on the
> source page can be detected (Through synchronous ld insn) and processed.
> The destination page cannot be processed.

I've considered the copy_to_user() case as only partially fixable. There
are lots of cases to consider:

1) Many places where drivers copy to user in ioctl(2) calls. 
   Killing the application solves the immediate problem, but if
   the problem with kernel memory is not transient, then you
   may run into it again.

2) Copy from Linux page cache to user for a read(2) system call.
   This one is a candidate for recovery. Might need help from the
   file system code. If the kernel page is a clean copy of data in
   the file system, then drop this page and re-read from storage
   into a new page. Then resume the copy_to_user().
   If the page is modified, then need some file system action to
   somehow mark this range of addresses in the file as lost forever.
   First step in tackling this case is identifying that the source
   address is a page cache page.

3) Probably many other places where the kernel copies to user for
   other system calls. Would need to look at these on a case by case
   basis. Likely most have the same issue as ioctl(2) above.

-Tony


From robh at kernel.org  Mon Mar 24 09:55:33 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 11:55:33 -0500
Subject: [PATCH 01/34] dt-bindings: mfd: samsung,s2mps11: add s2mpg10
In-Reply-To: <20250323-s2mpg10-v1-1-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
 <20250323-s2mpg10-v1-1-d08943702707@linaro.org>
Message-ID: <20250324165533.GA521455-robh@kernel.org>

On Sun, Mar 23, 2025 at 10:39:17PM +0000, Andr? Draszik wrote:
> The Samsung S2MPG10 PMIC is similar to the existing PMICs supported by
> this binding.
> 
> It is a Power Management IC for mobile applications with buck
> converters, various LDOs, power meters, RTC, clock outputs, and
> additional GPIOs interfaces.
> 
> Unlike other Samsung PMICs, communication is not via I2C, but via the
> Samsung ACPM firmware, it therefore doesn't need a 'reg' property but a
> handle to the ACPM firmware node instead.

Can it be a child node of the ACPM node instead?

> 
> S2MPG10 can also act as a system power controller allowing
> implementation of a true cold-reset of the system.
> 
> Support for the other components will be added in subsequent future
> patches.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  .../devicetree/bindings/mfd/samsung,s2mps11.yaml   | 34 ++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> index ac5d0c149796b6a4034b5d4245bfa8be0433cfab..ae8adb80b3af7ec3722c2a5718ad8fddf0a5df34 100644
> --- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> +++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> @@ -20,6 +20,7 @@ description: |
>  properties:
>    compatible:
>      enum:
> +      - samsung,s2mpg10-pmic
>        - samsung,s2mps11-pmic
>        - samsung,s2mps13-pmic
>        - samsung,s2mps14-pmic
> @@ -43,6 +44,12 @@ properties:
>      description:
>        List of child nodes that specify the regulators.
>  
> +  exynos,acpm-ipc:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: |

Don't need '|' if no formatting to preserve.

> +      Phandle to the ACPM node for when ACPM is used to communicate with the
> +      PMIC, rather than I2C.
> +
>    samsung,s2mps11-acokb-ground:
>      description: |
>        Indicates that ACOKB pin of S2MPS11 PMIC is connected to the ground so
> @@ -58,16 +65,39 @@ properties:
>        reset (setting buck voltages to default values).
>      type: boolean
>  
> +  system-power-controller: true
> +
>    wakeup-source: true
>  
>  required:
>    - compatible
> -  - reg
> -  - regulators
>  
>  additionalProperties: false
>  
>  allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,s2mpg10-pmic
> +    then:
> +      properties:
> +        regulators: false
> +        samsung,s2mps11-acokb-ground: false
> +        samsung,s2mps11-wrstbi-ground: false
> +
> +      required:
> +        - exynos,acpm-ipc
> +
> +    else:
> +      properties:
> +        exynos,acpm-ipc: false
> +        system-power-controller: false
> +
> +      required:
> +        - reg
> +        - regulators
> +
>    - if:
>        properties:
>          compatible:
> 
> -- 
> 2.49.0.395.g12beb8f557-goog
> 


From robh at kernel.org  Mon Mar 24 10:01:25 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 12:01:25 -0500
Subject: [PATCH 02/34] dt-bindings: clock: samsung,s2mps11: add s2mpg10
In-Reply-To: <20250323-s2mpg10-v1-2-d08943702707@linaro.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
 <20250323-s2mpg10-v1-2-d08943702707@linaro.org>
Message-ID: <174283568389.583762.1651160249139720114.robh@kernel.org>


On Sun, 23 Mar 2025 22:39:18 +0000, Andr? Draszik wrote:
> The Samsung S2MPG10 clock controller is similar to the existing clock
> controllers supported by this binding. Register offsets / layout are
> slightly different, so it needs its own compatible.
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
>  Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From angelogioacchino.delregno at collabora.com  Mon Mar 24 10:09:37 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 18:09:37 +0100
Subject: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
In-Reply-To: <20250321093435.94835-7-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-7-paul-pl.chen@mediatek.com>
Message-ID: <67337197-abec-450c-b400-ae37a0cd0692@collabora.com>

Il 21/03/25 10:33, paul-pl.chen ha scritto:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> 1. Defining driver data and adding compatible string
> for different subsystems
> (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> 2. Adding functions to control top clocks and ddp clocks.
> 3. Updating the probe function to initialize clocks and
> enable runtime PM if its node has the power-domains property.
> 4. Adding functions to configure ddp components and
> set default configurations.
> 5. Adding the routing table for each mmsys in MT8196.

You need at least two commits for all that you're doing here... and adding MT8196
tables should be the last one.

> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>   drivers/soc/mediatek/mt8196-mmsys.h    | 451 +++++++++++++++++++++++++
>   drivers/soc/mediatek/mtk-mmsys.c       | 203 ++++++++++-
>   drivers/soc/mediatek/mtk-mmsys.h       |  18 +
>   include/linux/soc/mediatek/mtk-mmsys.h |  60 ++++
>   4 files changed, 731 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h
> 
> diff --git a/drivers/soc/mediatek/mt8196-mmsys.h b/drivers/soc/mediatek/mt8196-mmsys.h
> new file mode 100644
> index 000000000000..ff841ae9939a
> --- /dev/null
> +++ b/drivers/soc/mediatek/mt8196-mmsys.h
> @@ -0,0 +1,451 @@

..snip..

> +static const struct mtk_mmsys_default mmsys_mt8196_disp0_default_table[] = {
> +	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
> +	{MT8196_DISP0_BYPASS_MUX_SHADOW,
> +	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
> +	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
> +	{MT8196_DISP0_DLI_RELAY0, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP0_DLI_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP0_DLI_RELAY8, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP0_DLO_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP0_DLO_RELAY2, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP0_DLO_RELAY3, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +};
> +
> +static const struct mtk_mmsys_default mmsys_mt8196_disp1_default_table[] = {
> +	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
> +	{MT8196_DISP1_INT_MERGE, 0, BIT(0)},
> +	{MT8196_DISP1_BYPASS_MUX_SHADOW,
> +	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
> +	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
> +	{MT8196_DISP1_DLI_RELAY21, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP1_DLI_RELAY22, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP1_DLI_RELAY23, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
> +	{MT8196_DISP1_GCE_FRAME_DONE_SEL0, MT8196_FRAME_DONE_DVO, GENMASK(5, 0)},
> +	{MT8196_DISP1_GCE_FRAME_DONE_SEL1, MT8196_FRAME_DONE_DP_INTF0, GENMASK(5, 0)},
> +};
> +
> +static const struct mtk_mmsys_routes mmsys_mt8196_ovl0_routing_table[] = {
> +	{
> +		DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_OVL0_BLENDER1,

There's a new MMSYS_ROUTE macro that was introduced because tables contained
wrong values in multiple instances and in multiple SoCs: please use it here and
for all routing tables.

> +		MT8196_OVL_RSZ_IN_CB2_MOUT_EN, MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3,
> +		MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3

..snip..

> +};
> +#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
> diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
> index bb4639ca0b8c..1d3ca4f9f237 100644
> --- a/drivers/soc/mediatek/mtk-mmsys.c
> +++ b/drivers/soc/mediatek/mtk-mmsys.c
> @@ -4,12 +4,14 @@
>    * Author: James Liao <jamesjj.liao at mediatek.com>
>    */
>   
> +#include <linux/clk.h>
>   #include <linux/delay.h>
>   #include <linux/device.h>
>   #include <linux/io.h>
>   #include <linux/module.h>
>   #include <linux/of.h>
>   #include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
>   #include <linux/reset-controller.h>
>   #include <linux/soc/mediatek/mtk-mmsys.h>
>   
> @@ -21,6 +23,7 @@
>   #include "mt8188-mmsys.h"
>   #include "mt8192-mmsys.h"
>   #include "mt8195-mmsys.h"
> +#include "mt8196-mmsys.h"
>   #include "mt8365-mmsys.h"
>   
>   #define MMSYS_SW_RESET_PER_REG 32
> @@ -144,6 +147,54 @@ static const struct mtk_mmsys_driver_data mt8195_vppsys1_driver_data = {
>   	.is_vppsys = true,
>   };
>   
> +static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
> +	.clk_driver = "clk-mt8196-disp0",
> +	.routes = mmsys_mt8196_disp0_routing_table,
> +	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp0_routing_table),
> +	.async_info = mmsys_mt8196_disp0_async_comp_table,
> +	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp0_async_comp_table),
> +	.def_config = mmsys_mt8196_disp0_default_table,
> +	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp0_default_table),
> +	.num_top_clk = 1,
> +};
> +
> +static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
> +	.clk_driver = "clk-mt8196-disp1",
> +	.routes = mmsys_mt8196_disp1_routing_table,
> +	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp1_routing_table),
> +	.async_info = mmsys_mt8196_disp1_async_comp_table,
> +	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp1_async_comp_table),
> +	.def_config = mmsys_mt8196_disp1_default_table,
> +	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp1_default_table),
> +	.num_top_clk = 1,
> +};
> +
> +static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
> +	.clk_driver = "clk-mt8196-ovl0",
> +	.routes = mmsys_mt8196_ovl0_routing_table,
> +	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl0_routing_table),
> +	.async_info = mmsys_mt8196_ovl0_async_comp_table,
> +	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl0_async_comp_table),
> +	.def_config = mmsys_mt8196_ovl0_default_table,
> +	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
> +};
> +
> +static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
> +	.clk_driver = "clk-mt8196-ovl1",
> +	.routes = mmsys_mt8196_ovl1_routing_table,
> +	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl1_routing_table),
> +	.async_info = mmsys_mt8196_ovl1_async_comp_table,
> +	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl1_async_comp_table),
> +	.def_config = mmsys_mt8196_ovl0_default_table,
> +	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
> +};
> +
> +static const struct mtk_mmsys_driver_data mt8196_vdisp_ao_driver_data = {
> +	.clk_driver = "clk-mt8196-vdisp_ao",
> +	.def_config = mmsys_mt8196_vdisp_ao_default_table,
> +	.num_def_config = ARRAY_SIZE(mmsys_mt8196_vdisp_ao_default_table),
> +};
> +
>   static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
>   	.clk_driver = "clk-mt8365-mm",
>   	.routes = mt8365_mmsys_routing_table,
> @@ -158,6 +209,9 @@ struct mtk_mmsys {
>   	spinlock_t lock; /* protects mmsys_sw_rst_b reg */
>   	struct reset_controller_dev rcdev;
>   	struct cmdq_client_reg cmdq_base;
> +	struct clk **async_clk;
> +	int num_async_clk;
> +	struct clk **top_clk;
>   };
>   
>   static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val,
> @@ -180,6 +234,99 @@ static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask,
>   	writel_relaxed(tmp, mmsys->regs + offset);
>   }
>   
> +int mtk_mmsys_top_clk_enable(struct device *dev)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	int ret, i;
> +
> +	if (!mmsys->data->num_top_clk)
> +		return 0;
> +
> +	for (i = 0; i < mmsys->data->num_top_clk; i++)
> +		ret = clk_prepare_enable(mmsys->top_clk[i]);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_enable);
> +
> +void mtk_mmsys_top_clk_disable(struct device *dev)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	int i;
> +
> +	for (i = 0; i < mmsys->data->num_top_clk; i++)
> +		clk_disable_unprepare(mmsys->top_clk[i]);
> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_disable);
> +
> +int mtk_mmsys_ddp_clk_enable(struct device *dev, enum mtk_ddp_comp_id comp_id)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
> +
> +	int i;
> +
> +	if (!mmsys->data->num_async_info)
> +		return 0;
> +
> +	for (i = 0; i < mmsys->data->num_async_info; i++)
> +		if (comp_id == async[i].comp_id)
> +			return clk_prepare_enable(mmsys->async_clk[async[i].index]);

Why can't you add the clocks in the mediatek-drm nodes and handle enablement in the
drm driver?!

> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_enable);
> +
> +void mtk_mmsys_ddp_clk_disable(struct device *dev, enum mtk_ddp_comp_id comp_id)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
> +	int i;
> +
> +	if (!mmsys->data->num_async_info)
> +		return;
> +
> +	for (i = 0; i < mmsys->data->num_async_info; i++)
> +		if (comp_id == async[i].comp_id)
> +			clk_disable_unprepare(mmsys->async_clk[async[i].index]);
> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_disable);
> +
> +void mtk_mmsys_ddp_config(struct device *dev, enum mtk_ddp_comp_id comp_id,
> +			  int width, int height, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
> +	int i;
> +
> +	if (!mmsys->data->num_async_info)
> +		return;
> +
> +	for (i = 0; i < mmsys->data->num_async_info; i++)
> +		if (comp_id == async[i].comp_id)
> +			break;
> +
> +	if (i == mmsys->data->num_async_info)
> +		return;
> +
> +	mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
> +			      height << 16 | width, cmdq_pkt);

linux/bitfield.h provides macros that you should use for those register fields.

> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_config);
> +
> +void mtk_mmsys_default_config(struct device *dev)
> +{
> +	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
> +	const struct mtk_mmsys_default *def_config = mmsys->data->def_config;
> +	int i;
> +
> +	if (!mmsys->data->num_def_config)
> +		return;
> +
> +	for (i = 0; i < mmsys->data->num_def_config; i++)
> +		mtk_mmsys_update_bits(mmsys, def_config[i].offset, def_config[i].mask,
> +				      def_config[i].val, NULL);
> +}
> +EXPORT_SYMBOL_GPL(mtk_mmsys_default_config);
> +
>   void mtk_mmsys_ddp_connect(struct device *dev,
>   			   enum mtk_ddp_comp_id cur,
>   			   enum mtk_ddp_comp_id next)
> @@ -390,7 +537,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
>   	struct platform_device *clks;
>   	struct platform_device *drm;
>   	struct mtk_mmsys *mmsys;
> -	int ret;
> +	int ret, i;
>   
>   	mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL);
>   	if (!mmsys)
> @@ -432,6 +579,49 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
>   		return PTR_ERR(clks);
>   	mmsys->clks_pdev = clks;
>   
> +	if (mmsys->data->num_top_clk) {
> +		struct device_node *node;
> +
> +		node = of_get_child_by_name(dev->of_node, "top");

No, you can't do that if there's no binding to support that.

> +		if (!node) {
> +			dev_err(&pdev->dev, "Couldn't find top node\n");
> +			return -EINVAL;
> +		}
> +
> +		mmsys->top_clk = devm_kmalloc_array(dev, mmsys->data->num_top_clk,
> +						    sizeof(*mmsys->top_clk), GFP_KERNEL);
> +		if (!mmsys->top_clk)
> +			return -ENOMEM;
> +
> +		for (i = 0; i < mmsys->data->num_top_clk; i++) {
> +			mmsys->top_clk[i] = of_clk_get(node, i);
> +			if (IS_ERR(mmsys->top_clk[i]))
> +				return PTR_ERR(mmsys->top_clk[i]);
> +		}
> +	}
> +
> +	if (mmsys->data->num_async_info) {
> +		struct device_node *node;
> +
> +		node = of_get_child_by_name(dev->of_node, "async");
> +		if (!node) {
> +			dev_err(&pdev->dev, "Couldn't find async node\n");
> +			return -EINVAL;
> +		}
> +

Also this looks like you have children providing only clocks?!
I really need to look at the bindings to decide, but this looks wrong.

Regards,
Angelo




From sebastian.reichel at collabora.com  Mon Mar 24 10:04:25 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:25 +0100
Subject: [PATCH 4/5] arm64: dts: rockchip: add Rock 5B+
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <20250324-rock5bp-for-upstream-v1-4-6217edf15b19@kernel.org>

Add ROCK 5B+, which is an improved version of the ROCK 5B with the
following changes:

 * Memory LPDDR4X -> LPDDR5
 * HDMI input connector size
 * eMMC socket -> onboard
 * M.2 E-Key is replaced by onboard RTL8852BE WLAN/BT
 * M.2 M-Key 1x4 lanes is replaced by 2x2 lanes
 * Added M.2 B-Key for USB connected WWAN modules (untested)
 * Add second camera port (not yet supported in upstream Linux)
 * Add dedicated USB-C port for device power (no impact in DT;
   the existing port has not been changed and the new port is
   handled by CH224D standalone chip)

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
 arch/arm64/boot/dts/rockchip/Makefile              |   1 +
 .../boot/dts/rockchip/rk3588-rock-5b-plus.dts      | 113 +++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 3e8771ef69ba1c1428117cc2ae29b84e13523e21..6525329fcf060aeb89382d184ca4c6c5c1d07088 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -164,6 +164,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5-itx.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b-pcie-ep.dtbo
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b-pcie-srns.dtbo
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b-plus.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-tiger-haikou.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-toybrick-x0.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-turing-rk1.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts
new file mode 100644
index 0000000000000000000000000000000000000000..74c7b6502e4dda4b774f43c704ebaee350703c0d
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3588-rock-5b.dtsi"
+
+/ {
+	model = "Radxa ROCK 5B+";
+	compatible = "radxa,rock-5b-plus", "rockchip,rk3588";
+
+	rfkill-wwan {
+		compatible = "rfkill-gpio";
+		label = "rfkill-m2-wwan";
+		radio-type = "wwan";
+		shutdown-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
+	};
+
+	vcc3v3_4g: regulator-vcc3v3-4g {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+		/* pinctrl for the GPIO is requested by vcc3v3_pcie2x1l0 */
+		regulator-name = "vcc3v3_4g";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <50000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc3v3_wwan_pwr: regulator-vcc3v3-wwan {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wwan_power_en>;
+		regulator-name = "vcc3v3_wwan_pwr";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc3v3_4g>;
+	};
+};
+
+&gpio0 {
+	wwan-disable2-n-hog {
+		gpios = <RK_PB2 GPIO_ACTIVE_LOW>;
+		output-low;
+		line-name = "M.2 B-key W_DISABLE2#";
+		gpio-hog;
+	};
+};
+
+&gpio2 {
+	wwan-reset-n-hog {
+		gpios = <RK_PB3 GPIO_ACTIVE_LOW>;
+		output-low;
+		line-name = "M.2 B-key RESET#";
+		gpio-hog;
+	};
+
+	wwan-wake-n-hog {
+		gpios = <RK_PB2 GPIO_ACTIVE_LOW>;
+		input;
+		line-name = "M.2 B-key WoWWAN#";
+		gpio-hog;
+	};
+};
+
+&pcie30phy {
+	data-lanes = <1 1 2 2>;
+};
+
+&pcie3x2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3x2_rst>;
+	reset-gpios = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+	vpcie3v3-supply = <&vcc3v3_pcie30>;
+	status = "okay";
+};
+
+&pcie3x4 {
+	num-lanes = <2>;
+};
+
+&pinctrl {
+	wwan {
+		wwan_power_en: wwan-pwr-en {
+			rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pcie3 {
+		pcie3x2_rst: pcie3x2-rst {
+			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		vcc5v0_host_en: vcc5v0-host-en {
+			rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&vcc5v0_host {
+	enable-active-high;
+	gpio = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&vcc5v0_host_en>;
+};

-- 
2.47.2



From sebastian.reichel at collabora.com  Mon Mar 24 10:04:23 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:23 +0100
Subject: [PATCH 2/5] arm64: dts: rockchip: move rock 5b to include file
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <20250324-rock5bp-for-upstream-v1-2-6217edf15b19@kernel.org>

Radxa released some more boards, which are based on the original
Rock 5B. Move its board description into an include file to avoid
unnecessary duplication.

NOTE: this should be merged with the previous commit to ensure
bisectability. The rename happens in a separete commit during
development because git does not properly detect the rename when
the original filename is reused in the same commit. This means

1. it's a lot harder to review the changes
2. it's a lot harder to rebase the patch series

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts  | 52 ++++++++++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi | 34 ----------------
 2 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
new file mode 100644
index 0000000000000000000000000000000000000000..9407a7c9910ada1f6c803d2e15785a9cbd9bd655
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3588-rock-5b.dtsi"
+
+/ {
+	model = "Radxa ROCK 5B";
+	compatible = "radxa,rock-5b", "rockchip,rk3588";
+};
+
+&sdio {
+	max-frequency = <200000000>;
+	no-sd;
+	no-mmc;
+	non-removable;
+	bus-width = <4>;
+	cap-sdio-irq;
+	disable-wp;
+	keep-power-in-suspend;
+	wakeup-source;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc3v3_pcie2x1l0>;
+	vqmmc-supply = <&vcc_1v8_s3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdiom0_pins>;
+	status = "okay";
+};
+
+&uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
+	status = "okay";
+};
+
+&pinctrl {
+	usb {
+		vcc5v0_host_en: vcc5v0-host-en {
+			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&vcc5v0_host {
+	enable-active-high;
+	gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&vcc5v0_host_en>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
index d22068475c5dc6cb885f878f3f527a66edf1ba70..dccb8492f9f0632abd96c3dafc723e01491abad5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
@@ -8,9 +8,6 @@
 #include "rk3588.dtsi"
 
 / {
-	model = "Radxa ROCK 5B";
-	compatible = "radxa,rock-5b", "rockchip,rk3588";
-
 	aliases {
 		mmc0 = &sdhci;
 		mmc1 = &sdmmc;
@@ -139,10 +136,6 @@ vcc5v0_host: regulator-vcc5v0-host {
 		regulator-always-on;
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
-		enable-active-high;
-		gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&vcc5v0_host_en>;
 		vin-supply = <&vcc5v0_sys>;
 	};
 
@@ -530,27 +523,6 @@ &sdmmc {
 	status = "okay";
 };
 
-&sdio {
-	max-frequency = <200000000>;
-	no-sd;
-	no-mmc;
-	non-removable;
-	bus-width = <4>;
-	cap-sdio-irq;
-	disable-wp;
-	keep-power-in-suspend;
-	wakeup-source;
-	sd-uhs-sdr12;
-	sd-uhs-sdr25;
-	sd-uhs-sdr50;
-	sd-uhs-sdr104;
-	vmmc-supply = <&vcc3v3_pcie2x1l0>;
-	vqmmc-supply = <&vcc_1v8_s3>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&sdiom0_pins>;
-	status = "okay";
-};
-
 &sfc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&fspim2_pins>;
@@ -565,12 +537,6 @@ flash at 0 {
 	};
 };
 
-&uart6 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
-	status = "okay";
-};
-
 &spi2 {
 	status = "okay";
 	assigned-clocks = <&cru CLK_SPI2>;

-- 
2.47.2



From sebastian.reichel at collabora.com  Mon Mar 24 10:04:22 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:22 +0100
Subject: [PATCH 1/5] arm64: dts: rockchip: move rock 5b to include file
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <20250324-rock5bp-for-upstream-v1-1-6217edf15b19@kernel.org>

Radxa released some more boards, which are based on the original
Rock 5B. Move its board description into an include file to avoid
unnecessary duplication.

NOTE: this should be merged with the following commit to ensure
bisectability. The rename happens in a separete commit during
development because git does not properly detect the rename when
the original filename is reused in the same commit. This means

1. it's a lot harder to review the changes
2. it's a lot harder to rebase the patch series

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
 arch/arm64/boot/dts/rockchip/{rk3588-rock-5b.dts => rk3588-rock-5b.dtsi} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
similarity index 100%
rename from arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
rename to arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi

-- 
2.47.2



From sebastian.reichel at collabora.com  Mon Mar 24 10:04:26 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:26 +0100
Subject: [PATCH 5/5] arm64: dts: rockchip: add USB-C support for ROCK 5B
 and 5B+
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <20250324-rock5bp-for-upstream-v1-5-6217edf15b19@kernel.org>

Add hardware description for the USB-C port in the Radxa ROCK 5 Model
B and B+. This describes the OHCI, EHCI and XHCI USB parts, but not yet
the DisplayPort AltMode, since the bindings for that are not yet upstream.

The fusb302 node is marked with status "fail" on ROCK 5B, since the board
is usually powered through the USB-C port. Handling of errors can result
in hard resets, which removed the bus power for some time resulting in
a board reset.

The main problem right now is that devices are supposed to interact with
the power-supply within 5 seconds after the plug event according to the
USB PD specification. This is more or less impossible to achieve when
the kernel is the first software communicating with the power-supply.

Upstream U-Boot with fusb302 support overrides the status for the
fusb302 node to "okay". That way booting a kernel with the updated DT
on an old U-Boot avoids a reset loop.

This workaround is not needed for the ROCK 5B+, since fusb302 support
landed in U-Boot before the board support gets upstreamed. Apart from
that it also has a dedicated USB-C port with a standalone chip to supply
the board power.

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
 .../boot/dts/rockchip/rk3588-rock-5b-plus.dts      |   4 +
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi   | 137 +++++++++++++++++++++
 2 files changed, 141 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts
index 74c7b6502e4dda4b774f43c704ebaee350703c0d..70339920fd4951dff993a5799ae5db243f07bd6e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dts
@@ -105,6 +105,10 @@ vcc5v0_host_en: vcc5v0-host-en {
 	};
 };
 
+&usbc0 {
+	status = "okay";
+};
+
 &vcc5v0_host {
 	enable-active-high;
 	gpio = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
index dccb8492f9f0632abd96c3dafc723e01491abad5..5e119f167cd8ccbd08ff2a2d4955489730ab85fb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi
@@ -5,6 +5,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/soc/rockchip,vop2.h>
+#include <dt-bindings/usb/pd.h>
 #include "rk3588.dtsi"
 
 / {
@@ -92,6 +93,15 @@ rfkill-bt {
 		shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
 	};
 
+	vcc12v_dcin: regulator-vcc12v-dcin {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc12v_dcin";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+	};
+
 	vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
 		compatible = "regulator-fixed";
 		enable-active-high;
@@ -146,6 +156,19 @@ vcc5v0_sys: regulator-vcc5v0-sys {
 		regulator-boot-on;
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vcc12v_dcin>;
+	};
+
+	vbus5v0_typec: vbus5v0-typec {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vbus5v0_typec_en>;
+		regulator-name = "vbus5v0_typec";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vcc5v0_sys>;
 	};
 
 	vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
@@ -309,6 +332,67 @@ regulator-state-mem {
 	};
 };
 
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4m1_xfer>;
+	status = "okay";
+
+	usbc0: usb-typec at 22 {
+		compatible = "fcs,fusb302";
+		reg = <0x22>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usbc0_int>;
+		vbus-supply = <&vbus5v0_typec>;
+		/*
+		 * When the board is starting to send power-delivery messages
+		 * too late (5 seconds according to the specification), the
+		 * power-supply reacts with a hard-reset. That removes the
+		 * power from VBUS for some time, which resets te whole board.
+		 */
+		status = "fail";
+
+		usb_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			data-role = "dual";
+			power-role = "sink";
+			try-power-role = "sink";
+			op-sink-microwatt = <1000000>;
+			sink-pdos =
+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>,
+				<PDO_VAR(5000, 20000, 5000)>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+					usbc0_role_sw: endpoint {
+						remote-endpoint = <&dwc3_0_role_switch>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+					usbc0_orien_sw: endpoint {
+						remote-endpoint = <&usbdp_phy0_orientation_switch>;
+					};
+				};
+
+				port at 2 {
+					reg = <2>;
+					dp_altmode_mux: endpoint {
+						remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
+					};
+				};
+			};
+		};
+	};
+};
+
 &i2c6 {
 	status = "okay";
 
@@ -486,6 +570,14 @@ usb {
 		vcc5v0_host_en: vcc5v0-host-en {
 			rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
+
+		usbc0_int: usbc0-int {
+			rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		vbus5v0_typec_en: vbus5v0-typec-en {
+			rockchip,pins = <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
 	};
 };
 
@@ -871,6 +963,14 @@ &uart2 {
 	status = "okay";
 };
 
+&u2phy0 {
+	status = "okay";
+};
+
+&u2phy0_otg {
+	status = "okay";
+};
+
 &u2phy1 {
 	status = "okay";
 };
@@ -898,6 +998,29 @@ &u2phy3_host {
 	status = "okay";
 };
 
+&usbdp_phy0 {
+	mode-switch;
+	orientation-switch;
+	sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
+	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usbdp_phy0_orientation_switch: endpoint at 0 {
+			reg = <0>;
+			remote-endpoint = <&usbc0_orien_sw>;
+		};
+
+		usbdp_phy0_dp_altmode_mux: endpoint at 1 {
+			reg = <1>;
+			remote-endpoint = <&dp_altmode_mux>;
+		};
+	};
+};
+
 &usbdp_phy1 {
 	status = "okay";
 };
@@ -910,6 +1033,20 @@ &usb_host0_ohci {
 	status = "okay";
 };
 
+&usb_host0_xhci {
+	usb-role-switch;
+	status = "okay";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dwc3_0_role_switch: endpoint {
+			remote-endpoint = <&usbc0_role_sw>;
+		};
+	};
+};
+
 &usb_host1_ehci {
 	status = "okay";
 };

-- 
2.47.2



From angelogioacchino.delregno at collabora.com  Mon Mar 24 10:12:56 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Mon, 24 Mar 2025 18:12:56 +0100
Subject: [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for
 output components
In-Reply-To: <20250321093435.94835-8-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
 <20250321093435.94835-8-paul-pl.chen@mediatek.com>
Message-ID: <754df305-9767-47be-8f98-4e287c56808e@collabora.com>

Il 21/03/25 10:33, paul-pl.chen ha scritto:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> Refactor SOF settings by adding mtk_mutex_get_output_comp_sof()
> and extracting SOF logic from mtk_mutex_add_comp()
> and mtk_mutex_remove_comp().
> 
> - Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
>    for SOF settings.
> - Reused the switch case for SOF IDs.
> - Separated MOD and SOF logic.
> 

This also needs more than one commit.

The cleanups go in a commit doing only cleanups.

> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>   drivers/soc/mediatek/mtk-mutex.c       | 121 +++++++++++++++----------
>   include/linux/soc/mediatek/mtk-mutex.h |   4 +
>   2 files changed, 79 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
> index aaa965d4b050..c026ac0e6969 100644
> --- a/drivers/soc/mediatek/mtk-mutex.c
> +++ b/drivers/soc/mediatek/mtk-mutex.c
> @@ -853,43 +853,84 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
>   }
>   EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
>   
> -void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> -			enum mtk_ddp_comp_id id)
> +static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
>   {
> -	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
> -						 mutex[mutex->id]);
> -	unsigned int reg;
> -	unsigned int sof_id;
> -	unsigned int offset;
> -
> -	WARN_ON(&mtx->mutex[mutex->id] != mutex);
> -
>   	switch (id) {
>   	case DDP_COMPONENT_DSI0:
> -		sof_id = MUTEX_SOF_DSI0;
> -		break;
> +		return MUTEX_SOF_DSI0;
>   	case DDP_COMPONENT_DSI1:
> -		sof_id = MUTEX_SOF_DSI0;
> -		break;
> +		return MUTEX_SOF_DSI1;
>   	case DDP_COMPONENT_DSI2:
> -		sof_id = MUTEX_SOF_DSI2;
> -		break;
> +		return MUTEX_SOF_DSI2;
>   	case DDP_COMPONENT_DSI3:
> -		sof_id = MUTEX_SOF_DSI3;
> -		break;
> +		return MUTEX_SOF_DSI3;
>   	case DDP_COMPONENT_DPI0:
> -		sof_id = MUTEX_SOF_DPI0;
> -		break;
> +		return MUTEX_SOF_DPI0;
>   	case DDP_COMPONENT_DPI1:
> -		sof_id = MUTEX_SOF_DPI1;
> -		break;
> +		return MUTEX_SOF_DPI1;
>   	case DDP_COMPONENT_DP_INTF0:
> -		sof_id = MUTEX_SOF_DP_INTF0;
> -		break;
> +		return MUTEX_SOF_DP_INTF0;
>   	case DDP_COMPONENT_DP_INTF1:
> -		sof_id = MUTEX_SOF_DP_INTF1;
> -		break;
> +		return MUTEX_SOF_DP_INTF1;
>   	default:
> +		break;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
> +{
> +	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
> +						 mutex[mutex->id]);
> +	int sof_id = mtk_mutex_get_output_comp_sof(id);
> +	unsigned int offset;
> +
> +	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
> +		return;
> +
> +	WARN_ON(&mtx->mutex[mutex->id] != mutex);
> +
> +	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
> +
> +	writel_relaxed(mtx->data->mutex_sof[sof_id],
> +		       mtx->regs + offset);

fits in one line

> +}
> +EXPORT_SYMBOL_GPL(mtk_mutex_add_comp_sof);
> +
> +void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
> +{
> +	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
> +						 mutex[mutex->id]);
> +	unsigned int reg;
> +	int sof_id = mtk_mutex_get_output_comp_sof(id);
> +	unsigned int offset;
> +
> +	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
> +		return;
> +
> +	WARN_ON(&mtx->mutex[mutex->id] != mutex);
> +
> +	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
> +	reg = readl_relaxed(mtx->regs + offset);
> +	reg &= ~(1 << mtx->data->mutex_sof[id]);
> +
> +	writel_relaxed(reg, mtx->regs + offset);
> +}
> +EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp_sof);
> +
> +void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> +			enum mtk_ddp_comp_id id)
> +{
> +	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
> +						 mutex[mutex->id]);
> +	unsigned int reg;
> +	unsigned int offset;
> +	bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
> +
> +	WARN_ON(&mtx->mutex[mutex->id] != mutex);
> +

Looks like you can just do

	if (is_output_comp) {
		mtk_mutex_add_comp_sof(mutex, id);
		return;
	}

	if (mtx->data->mutex_mod[id] < 32) { .....etc

> +	if (!is_output_comp) {
>   		if (mtx->data->mutex_mod[id] < 32) {
>   			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
>   						    mutex->id);
> @@ -902,12 +943,10 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
>   			reg |= 1 << (mtx->data->mutex_mod[id] - 32);
>   			writel_relaxed(reg, mtx->regs + offset);
>   		}
> -		return;
>   	}
>   
> -	writel_relaxed(mtx->data->mutex_sof[sof_id],
> -		       mtx->regs +
> -		       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
> +	if (is_output_comp)
> +		mtk_mutex_add_comp_sof(mutex, id);
>   }
>   EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
>   
> @@ -918,24 +957,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
>   						 mutex[mutex->id]);
>   	unsigned int reg;
>   	unsigned int offset;
> +	bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
>   
>   	WARN_ON(&mtx->mutex[mutex->id] != mutex);
>   
> -	switch (id) {
> -	case DDP_COMPONENT_DSI0:
> -	case DDP_COMPONENT_DSI1:
> -	case DDP_COMPONENT_DSI2:
> -	case DDP_COMPONENT_DSI3:
> -	case DDP_COMPONENT_DPI0:
> -	case DDP_COMPONENT_DPI1:
> -	case DDP_COMPONENT_DP_INTF0:
> -	case DDP_COMPONENT_DP_INTF1:
> -		writel_relaxed(MUTEX_SOF_SINGLE_MODE,
> -			       mtx->regs +
> -			       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
> -						  mutex->id));
> -		break;
> -	default:
> +	if (!is_output_comp) {

same comment as before.

>   		if (mtx->data->mutex_mod[id] < 32) {
>   			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
>   						    mutex->id);
> @@ -948,8 +974,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
>   			reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
>   			writel_relaxed(reg, mtx->regs + offset);
>   		}
> -		break;
>   	}
> +
> +	if (is_output_comp)
> +		mtk_mutex_remove_comp_sof(mutex, id);
> +

Regards,
Angelo




From sebastian.reichel at collabora.com  Mon Mar 24 10:04:24 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:24 +0100
Subject: [PATCH 3/5] dt-bindings: arm: rockchip: Add Radxa ROCK 5B+
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <20250324-rock5bp-for-upstream-v1-3-6217edf15b19@kernel.org>

The Radxa ROCK 5B+ is an improved version of the ROCK 5B.

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
 Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index 650fb833d96ef67ea1bba33c0767777378a38fa7..fe1fe8fe52fa3594a0da8e0263cb46949436a021 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -946,6 +946,11 @@ properties:
           - const: radxa,rock-5b
           - const: rockchip,rk3588
 
+      - description: Radxa ROCK 5B+
+        items:
+          - const: radxa,rock-5b-plus
+          - const: rockchip,rk3588
+
       - description: Radxa ROCK 5C
         items:
           - const: radxa,rock-5c

-- 
2.47.2



From sebastian.reichel at collabora.com  Mon Mar 24 10:04:21 2025
From: sebastian.reichel at collabora.com (Sebastian Reichel)
Date: Mon, 24 Mar 2025 18:04:21 +0100
Subject: [PATCH 0/5] arm64: dts: rockchip: add ROCK 5B+ support
Message-ID: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>

This series adds support for the ROCK 5B+, which (as the name suggests)
is an improved version of the ROCK 5B. It also adds initial USB-C
support for both the ROCK 5B and the 5B+.

Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
---
Sebastian Reichel (5):
      arm64: dts: rockchip: move rock 5b to include file
      arm64: dts: rockchip: move rock 5b to include file
      dt-bindings: arm: rockchip: Add Radxa ROCK 5B+
      arm64: dts: rockchip: add Rock 5B+
      arm64: dts: rockchip: add USB-C support for ROCK 5B and 5B+

 .../devicetree/bindings/arm/rockchip.yaml          |    5 +
 arch/arm64/boot/dts/rockchip/Makefile              |    1 +
 .../boot/dts/rockchip/rk3588-rock-5b-plus.dts      |  117 +++
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts    |  952 +----------------
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi   | 1087 ++++++++++++++++++++
 5 files changed, 1220 insertions(+), 942 deletions(-)
---
base-commit: 76728fe54f547950f73c9dc446beb2e31604abd7
change-id: 20250324-rock5bp-for-upstream-fd85b00b593b

Best regards,
-- 
Sebastian Reichel <sre at kernel.org>



From manivannan.sadhasivam at linaro.org  Mon Mar 24 10:18:23 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 22:48:23 +0530
Subject: [PATCH v12 05/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
In-Reply-To: <20250315201548.858189-6-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-6-helgaas@kernel.org>
Message-ID: <j3qw4zmopulpn3iqq5wsjt6dbs4z3micoeoxkw3354txkx22ml@67ip5sfo6wwd>

On Sat, Mar 15, 2025 at 03:15:40PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
> 
> Return the offset from CPU physical address to the parent bus address of
> the specified element of the devicetree 'reg' property.
> 
> [bhelgaas: return offset, split .cpu_addr_fixup() checking and debug to
> separate patch]
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware.c | 23 ++++++++++++++++++++
>  drivers/pci/controller/dwc/pcie-designware.h |  3 +++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 9d0a5f75effc..0a35e36da703 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -16,6 +16,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/ioport.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
>  #include <linux/platform_device.h>
>  #include <linux/sizes.h>
>  #include <linux/types.h>
> @@ -1105,3 +1106,25 @@ void dw_pcie_setup(struct dw_pcie *pci)
>  
>  	dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
>  }
> +
> +resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> +					  const char *reg_name,
> +					  resource_size_t cpu_phy_addr)
> +{

s/cpu_phy_addr/cpu_phys_addr/g

'phy' usually refers to the physical layer IP block. So 'cpu_phy_addr' sounds
like the address of the CPU PHY.

> +	struct device *dev = pci->dev;
> +	struct device_node *np = dev->of_node;
> +	int index;
> +	u64 reg_addr;
> +
> +	/* Look up reg_name address on parent bus */

'parent bus' is not accurate as the below code checks for the 'reg_name' in
current PCI controller node.

> +	index = of_property_match_string(np, "reg-names", reg_name);
> +
> +	if (index < 0) {
> +		dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);

Both of these callers are checking for the existence of the 'reg_name' property
before calling this API. So this check seems to be redundant (for now).

- Mani

-- 
????????? ????????


From csokas.bence at prolan.hu  Mon Mar 24 10:20:25 2025
From: csokas.bence at prolan.hu (=?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?=)
Date: Mon, 24 Mar 2025 18:20:25 +0100
Subject: [PATCH v6] dma-engine: sun4i: Simplify error handling in probe()
Message-ID: <20250324172026.370253-2-csokas.bence@prolan.hu>

Clean up error handling by using devm functions and dev_err_probe(). This
should make it easier to add new code, as we can eliminate the "goto
ladder" in sun4i_dma_probe().

Suggested-by: Chen-Yu Tsai <wens at kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Chen-Yu Tsai <wens at csie.org>
Signed-off-by: Bence Cs?k?s <csokas.bence at prolan.hu>
---

Notes:
    Changes in v2:
    * rebase on current next
    Changes in v3:
    * rebase on current next
    * collect Jernej's tag
    Changes in v4:
    * rebase on current next
    * collect Chen-Yu's tag
    Changes in v5:
    * reformat msg to 75 cols
    * keep `\n`s in error messages
    Changes in v6:
    * remove redundant braces
    * break lines to stay under 85 cols
    * reword subject and message

 drivers/dma/sun4i-dma.c | 46 ++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 33 deletions(-)

diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 24796aaaddfa..00d2fd38d17f 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1249,11 +1249,10 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 	if (priv->irq < 0)
 		return priv->irq;
 
-	priv->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(priv->clk)) {
-		dev_err(&pdev->dev, "No clock specified\n");
-		return PTR_ERR(priv->clk);
-	}
+	priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk),
+				     "Couldn't start the clock\n");
 
 	if (priv->cfg->has_reset) {
 		priv->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL);
@@ -1328,12 +1327,6 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 		vchan_init(&vchan->vc, &priv->slave);
 	}
 
-	ret = clk_prepare_enable(priv->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Couldn't enable the clock\n");
-		return ret;
-	}
-
 	/*
 	 * Make sure the IRQs are all disabled and accounted for. The bootloader
 	 * likes to leave these dirty
@@ -1343,33 +1336,23 @@ static int sun4i_dma_probe(struct platform_device *pdev)
 
 	ret = devm_request_irq(&pdev->dev, priv->irq, sun4i_dma_interrupt,
 			       0, dev_name(&pdev->dev), priv);
-	if (ret) {
-		dev_err(&pdev->dev, "Cannot request IRQ\n");
-		goto err_clk_disable;
-	}
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Cannot request IRQ\n");
 
-	ret = dma_async_device_register(&priv->slave);
-	if (ret) {
-		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
-		goto err_clk_disable;
-	}
+	ret = dmaenginem_async_device_register(&priv->slave);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "Failed to register DMA engine device\n");
 
 	ret = of_dma_controller_register(pdev->dev.of_node, sun4i_dma_of_xlate,
 					 priv);
-	if (ret) {
-		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
-		goto err_dma_unregister;
-	}
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "Failed to register translation function\n");
 
 	dev_dbg(&pdev->dev, "Successfully probed SUN4I_DMA\n");
 
 	return 0;
-
-err_dma_unregister:
-	dma_async_device_unregister(&priv->slave);
-err_clk_disable:
-	clk_disable_unprepare(priv->clk);
-	return ret;
 }
 
 static void sun4i_dma_remove(struct platform_device *pdev)
@@ -1380,9 +1363,6 @@ static void sun4i_dma_remove(struct platform_device *pdev)
 	disable_irq(priv->irq);
 
 	of_dma_controller_free(pdev->dev.of_node);
-	dma_async_device_unregister(&priv->slave);
-
-	clk_disable_unprepare(priv->clk);
 }
 
 static struct sun4i_dma_config sun4i_a10_dma_cfg = {
-- 
2.49.0




From andre.draszik at linaro.org  Mon Mar 24 10:23:01 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Mon, 24 Mar 2025 17:23:01 +0000
Subject: [PATCH 01/34] dt-bindings: mfd: samsung,s2mps11: add s2mpg10
In-Reply-To: <20250324165533.GA521455-robh@kernel.org>
References: <20250323-s2mpg10-v1-0-d08943702707@linaro.org>
	 <20250323-s2mpg10-v1-1-d08943702707@linaro.org>
	 <20250324165533.GA521455-robh@kernel.org>
Message-ID: <26037d49069309915d6ac3dc4d0aff90175754de.camel@linaro.org>

Hi Rob,

Thanks for your review!

On Mon, 2025-03-24 at 11:55 -0500, Rob Herring wrote:
> On Sun, Mar 23, 2025 at 10:39:17PM +0000, Andr? Draszik wrote:
> > The Samsung S2MPG10 PMIC is similar to the existing PMICs supported by
> > this binding.
> > 
> > It is a Power Management IC for mobile applications with buck
> > converters, various LDOs, power meters, RTC, clock outputs, and
> > additional GPIOs interfaces.
> > 
> > Unlike other Samsung PMICs, communication is not via I2C, but via the
> > Samsung ACPM firmware, it therefore doesn't need a 'reg' property but a
> > handle to the ACPM firmware node instead.
> 
> Can it be a child node of the ACPM node instead?

That should work, I'll do that instead so.

> > 
> > S2MPG10 can also act as a system power controller allowing
> > implementation of a true cold-reset of the system.
> > 
> > Support for the other components will be added in subsequent future
> > patches.
> > 
> > Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> > ---
> > ?.../devicetree/bindings/mfd/samsung,s2mps11.yaml?? | 34 ++++++++++++++++++++--
> > ?1 file changed, 32 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> > index ac5d0c149796b6a4034b5d4245bfa8be0433cfab..ae8adb80b3af7ec3722c2a5718ad8fddf0a5df34 100644
> > --- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> > +++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
> > @@ -20,6 +20,7 @@ description: |
> > ?properties:
> > ?? compatible:
> > ???? enum:
> > +????? - samsung,s2mpg10-pmic
> > ?????? - samsung,s2mps11-pmic
> > ?????? - samsung,s2mps13-pmic
> > ?????? - samsung,s2mps14-pmic
> > @@ -43,6 +44,12 @@ properties:
> > ???? description:
> > ?????? List of child nodes that specify the regulators.
> > ?
> > +? exynos,acpm-ipc:
> > +??? $ref: /schemas/types.yaml#/definitions/phandle
> > +??? description: |
> 
> Don't need '|' if no formatting to preserve.

Oops, yes, sorry.

Cheers,
Andre'

> 
> > +????? Phandle to the ACPM node for when ACPM is used to communicate with the
> > +????? PMIC, rather than I2C.
> > +
> > ?? samsung,s2mps11-acokb-ground:
> > ???? description: |
> > ?????? Indicates that ACOKB pin of S2MPS11 PMIC is connected to the ground so
> > @@ -58,16 +65,39 @@ properties:
> > ?????? reset (setting buck voltages to default values).
> > ???? type: boolean
> > ?
> > +? system-power-controller: true
> > +
> > ?? wakeup-source: true
> > ?
> > ?required:
> > ?? - compatible
> > -? - reg
> > -? - regulators
> > ?
> > ?additionalProperties: false
> > ?
> > ?allOf:
> > +? - if:
> > +????? properties:
> > +??????? compatible:
> > +????????? contains:
> > +??????????? const: samsung,s2mpg10-pmic
> > +??? then:
> > +????? properties:
> > +??????? regulators: false
> > +??????? samsung,s2mps11-acokb-ground: false
> > +??????? samsung,s2mps11-wrstbi-ground: false
> > +
> > +????? required:
> > +??????? - exynos,acpm-ipc
> > +
> > +??? else:
> > +????? properties:
> > +??????? exynos,acpm-ipc: false
> > +??????? system-power-controller: false
> > +
> > +????? required:
> > +??????? - reg
> > +??????? - regulators
> > +
> > ?? - if:
> > ?????? properties:
> > ???????? compatible:
> > 
> > -- 
> > 2.49.0.395.g12beb8f557-goog
> > 


From manivannan.sadhasivam at linaro.org  Mon Mar 24 10:30:24 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 23:00:24 +0530
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <20250315201548.858189-7-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-7-helgaas@kernel.org>
Message-ID: <x2r2xfxrnkihvpoqiamgjmvppverjugp5r4we7lcfpz6jloxzy@7kdfzxiwv2po>

On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> From: Frank Li <Frank.Li at nxp.com>
> 
> dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> is a hard-coded way to get the parent bus address corresponding to a CPU
> physical address.
> 
> Add debug code to compare the address from .cpu_addr_fixup() with the
> address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> redundant and should be removed; if they differ, warn that something is
> wrong with the devicetree.
> 
> If .cpu_addr_fixup() is not implemented, the parent bus address should be
> identical to the CPU physical address because we previously ignored the
> parent bus address from devicetree.  If the devicetree has a different
> parent bus address, warn about it being broken.
> 
> [bhelgaas: split debug to separate patch for easier future revert, commit
> log]
> Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> Signed-off-by: Frank Li <Frank.Li at nxp.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware.c | 26 +++++++++++++++++++-
>  drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++++
>  2 files changed, 38 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 0a35e36da703..985264c88b92 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>  	struct device *dev = pci->dev;
>  	struct device_node *np = dev->of_node;
>  	int index;
> -	u64 reg_addr;
> +	u64 reg_addr, fixup_addr;
> +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
>  
>  	/* Look up reg_name address on parent bus */
>  	index = of_property_match_string(np, "reg-names", reg_name);
> @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
>  
>  	of_property_read_reg(np, index, &reg_addr, NULL);
>  
> +	fixup = pci->ops->cpu_addr_fixup;
> +	if (fixup) {
> +		fixup_addr = fixup(pci, cpu_phy_addr);
> +		if (reg_addr == fixup_addr) {
> +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
> +				 cpu_phy_addr, reg_name, index,
> +				 fixup_addr, fixup);
> +		} else {
> +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> +				 cpu_phy_addr, reg_name,
> +				 index, fixup_addr);
> +			reg_addr = fixup_addr;
> +		}
> +	} else if (!pci->use_parent_dt_ranges) {

Is this check still valid? 'use_parent_dt_ranges' is only used here for
validation. Moreover, if the fixup is not available, we should be able to
safely return 'cpu_phy_addr - reg_addr' unconditionally.

> +		if (reg_addr != cpu_phy_addr) {
> +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> +				 cpu_phy_addr, reg_addr);
> +			return 0;
> +		}
> +	}
> +
> +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> +		 reg_name, cpu_phy_addr - reg_addr);

This info is useless on platforms having no translation between CPU and PCI
controller. The offset will always be 0.

- Mani

-- 
????????? ????????


From manivannan.sadhasivam at linaro.org  Mon Mar 24 10:34:10 2025
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon, 24 Mar 2025 23:04:10 +0530
Subject: [PATCH v12 00/13] PCI: Use device bus range info to cleanup RC
 Host/EP pci_fixup_addr()
In-Reply-To: <20250315201548.858189-1-helgaas@kernel.org>
References: <20250315201548.858189-1-helgaas@kernel.org>
Message-ID: <sffiojhyyu5gc7nx4oe6re53r3ti4nbnkworsxzawkus6ovlsh@3auwqhcpdp3c>

On Sat, Mar 15, 2025 at 03:15:35PM -0500, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas at google.com>
> 
> This is a v12 based on Frank's v11 series.
> 

Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org> #SA8775P-RIDE

- Mani

> v11 https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-0-01d2313502ab at nxp.com
>     
> Changes from v11:
>   - Call devm_pci_alloc_host_bridge() early in dw_pcie_host_init(), before
>     any devicetree-related code
>   - Call devm_pci_epc_create() early in dw_pcie_ep_init(), before any
>     devicetree-related code
>   - Consolidate devicetree-related code in dw_pcie_host_get_resources() and
>     dw_pcie_ep_get_resources()
>   - Integrate dw_pcie_cfg0_setup() into dw_pcie_host_get_resources()
>   - Convert dw_pcie_init_parent_bus_offset() to dw_pcie_parent_bus_offset()
>     which returns the offset rather than setting it internally
>   - Split the debug comparison of devicetree info with .cpu_addr_fixup() to
>     separate patch so we can easily revert it later
>   - Drop "cpu_addr_fixup() usage detected" warning since we always warn
>     about something in that case anyway
> 
> Any comments welcome.
> 
> 
> Bjorn Helgaas (3):
>   PCI: dwc: Consolidate devicetree handling in
>     dw_pcie_host_get_resources()
>   PCI: dwc: ep: Call epc_create() early in dw_pcie_ep_init()
>   PCI: dwc: ep: Consolidate devicetree handling in
>     dw_pcie_ep_get_resources()
> 
> Frank Li (10):
>   PCI: dwc: Use resource start as iomap() input in
>     dw_pcie_pme_turn_off()
>   PCI: dwc: Rename cpu_addr to parent_bus_addr for ATU configuration
>   PCI: dwc: Call devm_pci_alloc_host_bridge() early in
>     dw_pcie_host_init()
>   PCI: dwc: Add dw_pcie_parent_bus_offset()
>   PCI: dwc: Add dw_pcie_parent_bus_offset() checking and debug
>   PCI: dwc: Use devicetree 'reg[config]' to derive CPU -> ATU addr
>     offset
>   PCI: dwc: ep: Use devicetree 'reg[addr_space]' to derive CPU -> ATU
>     addr offset
>   PCI: dwc: ep: Ensure proper iteration over outbound map windows
>   PCI: dwc: Use parent_bus_offset to remove need for .cpu_addr_fixup()
>   PCI: imx6: Remove cpu_addr_fixup()
> 
>  drivers/pci/controller/dwc/pci-imx6.c         | 18 +---
>  .../pci/controller/dwc/pcie-designware-ep.c   | 74 +++++++++++------
>  .../pci/controller/dwc/pcie-designware-host.c | 57 ++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.c  | 82 ++++++++++++++-----
>  drivers/pci/controller/dwc/pcie-designware.h  | 24 +++++-
>  5 files changed, 171 insertions(+), 84 deletions(-)
> 
> -- 
> 2.34.1
> 

-- 
????????? ????????


From Markus.Elfring at web.de  Mon Mar 24 10:55:20 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Mon, 24 Mar 2025 18:55:20 +0100
Subject: [PATCH v6] dma-engine: sun4i: Simplify error handling in probe()
In-Reply-To: <20250324172026.370253-2-csokas.bence@prolan.hu>
References: <20250324172026.370253-2-csokas.bence@prolan.hu>
Message-ID: <92772f63-52c9-4979-9b60-37c8320ca009@web.de>

> Clean up error handling by using devm functions and dev_err_probe().
?

Do any contributors care for a different patch granularity?
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14#n81


Will it be clearer to mention also the function name ?sun4i_dma_probe?
in the summary phrases?

Regards,
Markus


From wthai at nvidia.com  Mon Mar 24 10:59:24 2025
From: wthai at nvidia.com (Willie Thai)
Date: Mon, 24 Mar 2025 17:59:24 +0000
Subject: [PATCH v4 1/3] dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
In-Reply-To: <20250324175926.222473-1-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
Message-ID: <20250324175926.222473-2-wthai@nvidia.com>

Add Nvidia's  GB200NVL BMC board compatible.

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes v3 -> v4:
  - Make the commit message more concise [Krzysztof]
---
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 01333ac111fb..a3736f134130 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -98,6 +98,7 @@ properties:
               - inventec,starscream-bmc
               - inventec,transformer-bmc
               - jabil,rbp-bmc
+              - nvidia,gb200nvl-bmc
               - qcom,dc-scm-v1-bmc
               - quanta,s6q-bmc
               - ufispace,ncplite-bmc
-- 
2.25.1



From wthai at nvidia.com  Mon Mar 24 10:59:23 2025
From: wthai at nvidia.com (Willie Thai)
Date: Mon, 24 Mar 2025 17:59:23 +0000
Subject: [PATCH v4 0/3] Add device tree for Nvidia's GB200NVL BMC
Message-ID: <20250324175926.222473-1-wthai@nvidia.com>

The GB200NVL BMC is an Aspeed Ast2600 based BMC
for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Andrew Lunn <andrew at lunn.ch>
Cc: Rob Herring <robh at kernel.org>
Cc: Paul Menzel <pmenzel at molgen.mpg.de>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Link: https://www.aspeedtech.com/server_ast2600/ [1]
Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes v1 -> v2:
  - Fix the SOB name [Krzysztof]
  - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
  - Fix DTS coding style [Krzysztof]
  - Move pinctrl override to the bottom [Krzysztof]
  - Drop bootargs [Krzysztof]
  - Follow DTS coding style and change naming for leds node [Krzysztof]
  - Change flash 0 status property [Krzysztof]
  - Change the phy-mode to rgmii [Andrew]
  - Remove the max-speed in mac0 [Andrew]
  - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
Changes v2 -> v3:
  - Fix missing new line [Krzysztof]
  - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
  - Fix DTS coding style [Krzysztof]
  - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
  - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
  - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
Changes v3 -> v4:
  - Order binding patch first in the patch set [Andrew Jeffery]
  - Make the commit message more concise [Krzysztof]
  - Remove stray blank lines [Krzysztof]
  - Remove unnecessary comments [Krzysztof]
  - Remove underscore, repalce by dash symbol in node name [Krzysztof]
  - Remove disable-master property in i2c as it is downstream added property [Rob, Andrew Jeffery]
  - Remove #address-cells, #size-cells in nxp,pca9555 and maxim,max31790 as they are no longer defined [Rob, Andrew Jeffery]
---

Willie Thai (3):
  dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
  dt-bindings: pinctrl: aspeed,ast2600-pinctrl
  ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC

 .../bindings/arm/aspeed/aspeed.yaml           |    1 +
 .../pinctrl/aspeed,ast2600-pinctrl.yaml       |    1 +
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1149 +++++++++++++++++
 4 files changed, 1152 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts

-- 
2.25.1



From wthai at nvidia.com  Mon Mar 24 10:59:25 2025
From: wthai at nvidia.com (Willie Thai)
Date: Mon, 24 Mar 2025 17:59:25 +0000
Subject: [PATCH v4 2/3] dt-bindings: pinctrl: aspeed,ast2600-pinctrl
In-Reply-To: <20250324175926.222473-1-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
Message-ID: <20250324175926.222473-3-wthai@nvidia.com>

Add EMMCG5 enum to compatible list of pinctrl binding for emmc enabling.

Cc: Andrew Jeffery <andrew at codeconstruct.com.au>
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
 .../devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
index 80974c46f3ef..cb75e979f5e0 100644
--- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
@@ -276,6 +276,7 @@ additionalProperties:
         - BMCINT
         - EMMCG1
         - EMMCG4
+        - EMMCG5
         - EMMCG8
         - ESPI
         - ESPIALT
-- 
2.25.1



From wthai at nvidia.com  Mon Mar 24 10:59:26 2025
From: wthai at nvidia.com (Willie Thai)
Date: Mon, 24 Mar 2025 17:59:26 +0000
Subject: [PATCH v4 3/3] ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <20250324175926.222473-1-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
Message-ID: <20250324175926.222473-4-wthai@nvidia.com>

The GB200NVL BMC is an Aspeed Ast2600 based BMC
for Nvidia Blackwell GB200NVL platform.
Reference to Ast2600 SOC [1].
Reference to Blackwell GB200NVL Platform [2].

Co-developed-by: Mars Yang <maryang at nvidia.com>
Signed-off-by: Mars Yang <maryang at nvidia.com>
Reviewed-by: Andrew Lunn <andrew at lunn.ch>
Cc: Krzysztof Kozlowski <krzk at kernel.org>
Cc: Rob Herring <robh at kernel.org>
Cc: Paul Menzel <pmenzel at molgen.mpg.de>
Cc: Andrew Jeffery <andrew at codeconstruct.com.au>
Link: https://www.aspeedtech.com/server_ast2600/ [1]
Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
Signed-off-by: Willie Thai <wthai at nvidia.com>
---
Changes v3 -> v4:
  - Remove stray blank lines [Krzysztof]
  - Remove unnecessary comments [Krzysztof]
  - Remove underscore, repalce by dash symbol in node name [Krzysztof]
  - Remove disable-master property in i2c as it is downstream added property [Rob, Andrew Jeffery]
  - Remove #address-cells, #size-cells in nxp,pca9555 and maxim,max31790 as they are no longer defined [Rob, Andrew Jeffery]
---
---
 arch/arm/boot/dts/aspeed/Makefile             |    1 +
 .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1149 +++++++++++++++++
 2 files changed, 1150 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 2e5f4833a073..20fd357a1ee9 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-bmc-lenovo-hr630.dtb \
 	aspeed-bmc-lenovo-hr855xg2.dtb \
 	aspeed-bmc-microsoft-olympus.dtb \
+	aspeed-bmc-nvidia-gb200nvl-bmc.dtb \
 	aspeed-bmc-opp-lanyang.dtb \
 	aspeed-bmc-opp-mowgli.dtb \
 	aspeed-bmc-opp-nicole.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
new file mode 100644
index 000000000000..a3ce8cbc60b5
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
@@ -0,0 +1,1149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "AST2600 GB200NVL BMC";
+	compatible = "nvidia,gb200nvl-bmc", "aspeed,ast2600";
+
+	aliases {
+		serial2 = &uart3;
+		serial4 = &uart5;
+		i2c16   = &imux16;
+		i2c17   = &imux17;
+		i2c18   = &imux18;
+		i2c19   = &imux19;
+		i2c20   = &imux20;
+		i2c21   = &imux21;
+		i2c22   = &imux22;
+		i2c23   = &imux23;
+		i2c24   = &imux24;
+		i2c25   = &imux25;
+		i2c26   = &imux26;
+		i2c27   = &imux27;
+		i2c28   = &imux28;
+		i2c29   = &imux29;
+		i2c30   = &imux30;
+		i2c31   = &imux31;
+		i2c32   = &imux32;
+		i2c33   = &imux33;
+		i2c34   = &imux34;
+		i2c35   = &imux35;
+		i2c36   = &imux36;
+		i2c37   = &imux37;
+		i2c38   = &imux38;
+		i2c39   = &imux39;
+		i2c40	= &e1si2c0;
+		i2c41	= &e1si2c1;
+		i2c42	= &e1si2c2;
+		i2c43	= &e1si2c3;
+		i2c44	= &e1si2c4;
+		i2c45	= &e1si2c5;
+		i2c46	= &e1si2c6;
+		i2c47	= &e1si2c7;
+		i2c48	= &i2c17mux0;
+		i2c49	= &i2c17mux1;
+		i2c50	= &i2c17mux2;
+		i2c51	= &i2c17mux3;
+		i2c52	= &i2c25mux0;
+		i2c53	= &i2c25mux1;
+		i2c54	= &i2c25mux2;
+		i2c55	= &i2c25mux3;
+		i2c56	= &i2c29mux0;
+		i2c57	= &i2c29mux1;
+		i2c58	= &i2c29mux2;
+		i2c59	= &i2c29mux3;
+	};
+
+	chosen {
+		stdout-path = &uart5;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vga_memory: framebuffer at 9f000000 {
+			no-map;
+			reg = <0x9f000000 0x01000000>; /* 16M */
+		};
+
+		ramoops at a0000000 {
+			compatible = "ramoops";
+			reg = <0xa0000000 0x100000>; /* 1MB */
+			record-size = <0x10000>; /* 64KB */
+			max-reason = <2>; /* KMSG_DUMP_OOPS */
+		};
+
+		gfx_memory: framebuffer {
+			size = <0x01000000>;
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+
+		video_engine_memory: jpegbuffer {
+			size = <0x02000000>;	/* 32M */
+			alignment = <0x01000000>;
+			compatible = "shared-dma-pool";
+			reusable;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led-0 {
+			label = "uid_led";
+			gpios = <&sgpiom0 27 GPIO_ACTIVE_LOW>;
+		};
+		led-1 {
+			label = "fault_led";
+			gpios = <&sgpiom0 29 GPIO_ACTIVE_LOW>;
+		};
+		led-2 {
+			label = "power_led";
+			gpios = <&sgpiom0 31 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	buttons {
+		button-power {
+			label = "power-btn";
+			gpio = <&sgpiom0 156 GPIO_ACTIVE_LOW>;
+		};
+		button-uid {
+			label = "uid-btn";
+			gpio = <&sgpiom0 154 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+// Enable Primary flash on FMC for bring up activity
+&fmc {
+	status = "okay";
+	flash at 0 {
+		status = "okay";
+		compatible = "jedec,spi-nor";
+		label = "bmc";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot at 0 {
+				// 896KB
+				reg = <0x0 0xe0000>;
+				label = "u-boot";
+			};
+
+			kernel at 100000 {
+				// 9MB
+				reg = <0x100000 0x900000>;
+				label = "kernel";
+			};
+
+			rofs at a00000 {
+				// 55292KB (extends to end of 64MB SPI - 4KB)
+				reg = <0xa00000 0x35FF000>;
+				label = "rofs";
+			};
+		};
+	};
+};
+
+&spi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi2_default>;
+
+	// Data SPI is 64MB in size
+	flash at 0 {
+		status = "okay";
+		label = "config";
+		spi-max-frequency = <50000000>;
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			u-boot-env at 0 {
+				// 256KB
+				reg = <0x0 0x40000>;
+				label = "u-boot-env";
+			};
+
+			rwfs at 40000 {
+				// 16MB
+				reg = <0x40000 0x1000000>;
+				label = "rwfs";
+			};
+
+			log at 1040000 {
+				// 40MB
+				reg = <0x1040000 0x2800000>;
+				label = "log";
+			};
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart3 {
+	// Enabling SOL
+	status = "okay";
+};
+
+&uart5 {
+	// BMC Debug Console
+	status = "okay";
+};
+
+&uart_routing {
+	status = "okay";
+};
+
+&mac2 {
+	status = "okay";
+	phy-mode = "rmii";
+	use-ncsi;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii3_default>;
+};
+
+// Enable emmc
+&emmc_controller {
+	status = "okay";
+};
+
+&emmc {
+	non-removable;
+	pinctrl-0 = <&pinctrl_emmcg5_default>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	clk-phase-mmc-hs200 = <9>, <225>;
+};
+
+/*
+ * Enable USB port A as device (via the virtual hub) to host
+ */
+&vhub {
+	status = "okay";
+};
+
+&video {
+	status = "okay";
+	memory-region = <&video_engine_memory>;
+};
+
+// USB 2.0 to HMC, on USB Port B
+&ehci1 {
+	status = "okay";
+};
+
+// USB 1.0
+&uhci {
+	status = "okay";
+};
+
+&sgpiom0 {
+	status="okay";
+	ngpios = <128>;
+	gpio-line-names =
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RUN_POWER_FAULT_L-I","SYS_RST_IN_L-O",
+		"RUN_POWER_PG-I","PWR_BRAKE_L-O",
+		"SYS_RST_OUT_L-I","RUN_POWER_EN-O",
+		"L0L1_RST_REQ_OUT_L-I","SHDN_FORCE_L-O",
+		"L2_RST_REQ_OUT_L-I","SHDN_REQ_L-O",
+		"SHDN_OK_L-I","UID_LED_N-O",
+		"BMC_I2C1_FPGA_ALERT_L-I","SYS_FAULT_LED_N-O",
+		"BMC_I2C0_FPGA_ALERT_L-I","PWR_LED_N-O",
+		"FPGA_RSVD_FFU3-I","",
+		"FPGA_RSVD_FFU2-I","",
+		"FPGA_RSVD_FFU1-I","",
+		"FPGA_RSVD_FFU0-I","BMC_I2C_SSIF_ALERT_L-O",
+		"CPU_BOOT_DONE-I","JTAG_MUX_SELECT-O",
+		"SPI_BMC_FPGA_INT_L-I","RTC_CLR_L-O",
+		"THERM_BB_WARN_L-I","UART_MUX_SEL-O",
+		"THERM_BB_OVERT_L-I","",
+		"CPU0_UPHY3_PRSNT1_L-I","IOBRD0_RUN_POWER_EN-O",
+		"CPU0_UPHY3_PRSNT0_L-I","IOBRD1_RUN_POWER_EN-O",
+		"CPU0_UPHY2_PRSNT1_L-I","FPGA_RSVD_FFU4-O",
+		"CPU0_UPHY2_PRSNT0_L-I","FPGA_RSVD_FFU5-O",
+		"CPU0_UPHY1_PRSNT1_L-I","FPGA_RSVD_FFU6-O",
+		"CPU0_UPHY1_PRSNT0_L-I","FPGA_RSVD_FFU7-O",
+		"CPU0_UPHY0_PRSNT1_L-I","RSVD_NV_PLT_DETECT-O",
+		"CPU0_UPHY0_PRSNT0_L-I","SPI1_INT_L-O",
+		"CPU1_UPHY3_PRSNT1_L-I","",
+		"CPU1_UPHY3_PRSNT0_L-I","HMC_EROT_MUX_STATUS",
+		"CPU1_UPHY2_PRSNT1_L-I","",
+		"CPU1_UPHY2_PRSNT0_L-I","",
+		"CPU1_UPHY1_PRSNT1_L-I","",
+		"CPU1_UPHY1_PRSNT0_L-I","",
+		"CPU1_UPHY0_PRSNT1_L-I","",
+		"CPU1_UPHY0_PRSNT0_L-I","",
+		"FAN1_PRESENT_L-I","",
+		"FAN0_PRESENT_L-I","",
+		"","",
+		"IPEX_CABLE_PRSNT_L-I","",
+		"M2_1_PRSNT_L-I","",
+		"M2_0_PRSNT_L-I","",
+		"CPU1_UPHY4_PRSNT1_L-I","",
+		"CPU0_UPHY4_PRSNT0_L-I","",
+		"","",
+		"I2C_RTC_ALERT_L-I","",
+		"FAN7_PRESENT_L-I","",
+		"FAN6_PRESENT_L-I","",
+		"FAN5_PRESENT_L-I","",
+		"FAN4_PRESENT_L-I","",
+		"FAN3_PRESENT_L-I","",
+		"FAN2_PRESENT_L-I","",
+		"IOBRD0_IOX_INT_L-I","",
+		"IOBRD1_PRSNT_L-I","",
+		"IOBRD0_PRSNT_L-I","",
+		"IOBRD1_PWR_GOOD-I","",
+		"IOBRD0_PWR_GOOD-I","",
+		"","",
+		"","",
+		"FAN_FAIL_IN_L-I","",
+		"","",
+		"","",
+		"","",
+		"PDB_CABLE_PRESENT_L-I","",
+		"","",
+		"CHASSIS_PWR_BRK_L-I","",
+		"","",
+		"IOBRD1_IOX_INT_L-I","",
+		"10GBE_SMBALRT_L-I","",
+		"PCIE_WAKE_L-I","",
+		"I2C_M21_ALERT_L-I","",
+		"I2C_M20_ALERT_L-I","",
+		"TRAY_FAST_SHDN_L-I","",
+		"UID_BTN_N-I","",
+		"PWR_BTN_L-I","",
+		"PSU_SMB_ALERT_L-I","",
+		"","",
+		"","",
+		"NODE_LOC_ID[0]-I","",
+		"NODE_LOC_ID[1]-I","",
+		"NODE_LOC_ID[2]-I","",
+		"NODE_LOC_ID[3]-I","",
+		"NODE_LOC_ID[4]-I","",
+		"NODE_LOC_ID[5]-I","",
+		"FAN10_PRESENT_L-I","",
+		"FAN9_PRESENT_L-I","",
+		"FAN8_PRESENT_L-I","",
+		"FPGA1_READY_HMC-I","",
+		"DP_HPD-I","",
+		"HMC_I2C3_FPGA_ALERT_L-I","",
+		"HMC_I2C2_FPGA_ALERT_L-I","",
+		"FPGA0_READY_HMC-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"LEAK_DETECT_ALERT_L-I","",
+		"MOD1_B2B_CABLE_PRESENT_L-I","",
+		"MOD1_CLINK_CABLE_PRESENT_L-I","",
+		"FAN11_PRESENT_L-I","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"RSVD_SGPIO_IN_CRC[0]","RSVD_SGPIO_O_CRC[7]",
+		"RSVD_SGPIO_IN_CRC[1]","RSVD_SGPIO_O_CRC[6]",
+		"RSVD_SGPIO_IN_CRC[2]","RSVD_SGPIO_O_CRC[5]",
+		"RSVD_SGPIO_IN_CRC[3]","RSVD_SGPIO_O_CRC[4]",
+		"RSVD_SGPIO_IN_CRC[4]","RSVD_SGPIO_O_CRC[3]",
+		"RSVD_SGPIO_IN_CRC[5]","RSVD_SGPIO_O_CRC[2]",
+		"RSVD_SGPIO_IN_CRC[6]","RSVD_SGPIO_O_CRC[1]",
+		"RSVD_SGPIO_IN_CRC[7]","RSVD_SGPIO_O_CRC[0]";
+};
+
+// I2C1, SSIF IPMI interface
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	ssif-bmc at 10 {
+		compatible = "ssif-bmc";
+		reg = <0x10>;
+	};
+};
+
+// I2C2
+// BMC_I2C1_FPGA - Secondary FPGA
+// HMC EROT
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C3
+// BMC_I2C0_FPGA - Primary FPGA
+// HMC FRU EEPROM
+&i2c2 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C4
+&i2c3 {
+	status = "disabled";
+};
+
+// I2C5
+// RTC Driver
+// IO Expander
+&i2c4 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	// Module 0, Expander @0x21
+	exp4: gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"RTC_MUX_SEL-O",
+			"PCI_MUX_SEL-O",
+			"TPM_MUX_SEL-O",
+			"FAN_MUX-SEL-O",
+			"SGMII_MUX_SEL-O",
+			"DP_MUX_SEL-O",
+			"UPHY3_USB_SEL-O",
+			"NCSI_MUX_SEL-O",
+			"BMC_PHY_RST-O",
+			"RTC_CLR_L-O",
+			"BMC_12V_CTRL-O",
+			"PS_RUN_IO0_PG-I",
+			"",
+			"",
+			"",
+			"";
+	};
+};
+
+// I2C6
+// Module 0/1 I2C MUX x3
+&i2c5 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+
+	i2c-mux at 71 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+		i2c-mux-idle-disconnect;
+
+		imux16: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux17: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c17mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c17mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c17mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c17mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux18: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux19: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 72 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x72>;
+		i2c-mux-idle-disconnect;
+
+		imux20: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux21: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-line-names =
+					"RST_CX_0_L-O",
+					"RST_CX_1_L-O",
+					"CX0_SSD0_PRSNT_L-I",
+					"CX1_SSD1_PRSNT_L-I",
+					"CX_BOOT_CMPLT_CX0-I",
+					"CX_BOOT_CMPLT_CX1-I",
+					"CX_TWARN_CX0_L-I",
+					"CX_TWARN_CX1_L-I",
+					"CX_OVT_SHDN_CX0-I",
+					"CX_OVT_SHDN_CX1-I",
+					"FNP_L_CX0-O",
+					"FNP_L_CX1-O",
+					"",
+					"MCU_GPIO-I",
+					"MCU_RST_N-O",
+					"MCU_RECOVERY_N-O";
+			};
+		};
+
+		imux22: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux23: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 73 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x73>;
+		i2c-mux-idle-disconnect;
+
+		imux24: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux25: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 70 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x70>;
+				i2c-mux-idle-disconnect;
+
+				i2c25mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c25mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c25mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c25mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux26: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux27: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 75 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		i2c-mux-idle-disconnect;
+
+		imux28: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux29: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 74 {
+				compatible = "nxp,pca9546";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x74>;
+				i2c-mux-idle-disconnect;
+
+				i2c29mux0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c29mux1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c29mux2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c29mux3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		imux30: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux31: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 76 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x76>;
+		i2c-mux-idle-disconnect;
+
+		imux32: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux33: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			gpio at 21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-line-names =
+					"SEC_RST_CX_0_L-O",
+					"SEC_RST_CX_1_L-O",
+					"SEC_CX0_SSD0_PRSNT_L-I",
+					"SEC_CX1_SSD1_PRSNT_L-I",
+					"SEC_CX_BOOT_CMPLT_CX0-I",
+					"SEC_CX_BOOT_CMPLT_CX1-I",
+					"SEC_CX_TWARN_CX0_L-I",
+					"SEC_CX_TWARN_CX1_L-I",
+					"SEC_CX_OVT_SHDN_CX0-I",
+					"SEC_CX_OVT_SHDN_CX1-I",
+					"SEC_FNP_L_CX0-O",
+					"SEC_FNP_L_CX1-O",
+					"",
+					"SEC_MCU_GPIO-I",
+					"SEC_MCU_RST_N-O",
+					"SEC_MCU_RECOVERY_N-O";
+				};
+		};
+
+		imux34: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux35: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		imux36: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		imux37: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		imux38: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		imux39: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C7
+// Module 0/1 Leak Sensors
+// Module 0/1 Fan Controllers
+&i2c6 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	pmic at 12 {
+		compatible = "ti,lm5066i";
+		reg = <0x12>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+
+	pmic at 14 {
+		compatible = "ti,lm5066i";
+		reg = <0x14>;
+		shunt-resistor-micro-ohms = <190>;
+		status = "okay";
+	};
+
+	pwm at 20 {
+		compatible = "maxim,max31790";
+		reg = <0x20>;
+	};
+
+	pwm at 23 {
+		compatible = "maxim,max31790";
+		reg = <0x23>;
+	};
+
+	pwm at 2c {
+		compatible = "maxim,max31790";
+		reg = <0x2c>;
+	};
+
+	pwm at 2f {
+		compatible = "maxim,max31790";
+		reg = <0x2f>;
+	};
+};
+
+// I2C9
+// M.2
+&i2c8 {
+	status = "okay";
+	clock-frequency = <400000>;
+	multi-master;
+};
+
+// I2C10
+// HMC IO Expander
+// Module 0/1 IO Expanders
+&i2c9 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	// Module 0, Expander @0x20
+	exp0: gpio at 20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"FPGA_THERM_OVERT_L-I",
+			"FPGA_READY_BMC-I",
+			"HMC_BMC_DETECT-O",
+			"HMC_PGOOD-O",
+			"",
+			"BMC_STBY_CYCLE-O",
+			"FPGA_EROT_FATAL_ERROR_L-I",
+			"WP_HW_EXT_CTRL_L-O",
+			"EROT_FPGA_RST_L-O",
+			"FPGA_EROT_RECOVERY_L-O",
+			"BMC_EROT_FPGA_SPI_MUX_SEL-O",
+			"USB_HUB_RESET_L-O",
+			"NCSI_CS1_SEL-O",
+			"SGPIO_EN_L-O",
+			"B2B_IOEXP_INT_L-I",
+			"I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// Module 1, Expander @0x21
+	exp1: gpio at 21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"SEC_FPGA_THERM_OVERT_L-I",
+			"SEC_FPGA_READY_BMC-I",
+			"",
+			"",
+			"",
+			"",
+			"SEC_FPGA_EROT_FATAL_ERROR_L-I",
+			"SEC_WP_HW_EXT_CTRL_L-O",
+			"SEC_EROT_FPGA_RST_L-O",
+			"SEC_FPGA_EROT_RECOVERY_L-O",
+			"SEC_BMC_EROT_FPGA_SPI_MUX_SEL-O",
+			"SEC_USB2_HUB_RST_L-O",
+			"",
+			"",
+			"",
+			"SEC_I2C_BUS_MUX_RESET_L-O";
+	};
+
+	// HMC Expander @0x27
+	exp2: gpio at 27 {
+		compatible = "nxp,pca9555";
+		reg = <0x27>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"HMC_PRSNT_L-I",
+			"HMC_READY-I",
+			"HMC_EROT_FATAL_ERROR_L-I",
+			"I2C_MUX_SEL-O",
+			"HMC_EROT_SPI_MUX_SEL-O",
+			"HMC_EROT_RECOVERY_L-O",
+			"HMC_EROT_RST_L-O",
+			"GLOBAL_WP_HMC-O",
+			"FPGA_RST_L-O",
+			"USB2_HUB_RST-O",
+			"CPU_UART_MUX_SEL-O",
+			"",
+			"",
+			"",
+			"",
+			"";
+	};
+
+	// HMC Expander @0x74
+	exp3: gpio at 74 {
+		compatible = "nxp,pca9555";
+		reg = <0x74>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <ASPEED_GPIO(B, 6) IRQ_TYPE_LEVEL_LOW>;
+		gpio-line-names =
+			"IOB_PRSNT_L",
+			"IOB_DP_HPD",
+			"IOX_BMC_RESET",
+			"IOB_IOEXP_INT_L",
+			"IOB_UID_LED_L",
+			"IOB_UID_BTN_L",
+			"IOB_SYS_RST_BTN_L",
+			"IOB_PWR_LED_L",
+			"IOB_PWR_BTN_L",
+			"IOB_PHY_RST",
+			"CPLD_JTAG_MUX_SEL",
+			"",
+			"",
+			"",
+			"",
+			"";
+	};
+};
+
+// I2C11
+// BMC FRU EEPROM
+// BMC Temp Sensor
+&i2c10 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	// BMC FRU EEPROM - 256 bytes
+	eeprom at 50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <8>;
+	};
+};
+
+// I2C12
+&i2c11 {
+	status = "disabled";
+};
+
+// I2C13
+&i2c12 {
+	status = "disabled";
+};
+
+// I2C14
+// Module 0 UPHY3 SMBus
+&i2c13 {
+	status = "disabled";
+};
+
+// I2C15
+// Module 1 UPHY3 SMBus
+&i2c14 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+
+	//E1.S drive slot 0-3
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+// I2C16
+&i2c15 {
+	status = "okay";
+	clock-frequency = <100000>;
+	multi-master;
+
+	//E1.S drive slot 4-7
+	i2c-mux at 77 {
+		compatible = "nxp,pca9546";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x77>;
+		i2c-mux-idle-disconnect;
+
+		e1si2c4: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		e1si2c5: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		e1si2c6: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		e1si2c7: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+	};
+};
+
+&rng {
+	status = "okay";
+};
+
+&gpio0 {
+	gpio-line-names =
+		/*A0-A7*/ "", "", "", "", "", "", "", "",
+		/*B0-B7*/ "", "", "", "", "", "", "", "",
+		/*C0-C7*/ "SGPIO_I2C_MUX_SEL-O", "", "", "", "", "", "", "",
+		/*D0-D7*/ "", "", "", "UART1_MUX_SEL-O", "", "FPGA_PEX_RST_L-O", "", "",
+		/*E0-E7*/ "RTL8221_PHY_RST_L-O", "RTL8211_PHY_INT_L-I",	"", "UART3_MUX_SEL-O",
+					"", "", "", "SGPIO_BMC_EN-O",
+		/*F0-F7*/ "", "", "", "", "", "", "", "",
+		/*G0-G7*/ "", "", "", "", "", "", "", "",
+		/*H0-H7*/ "", "", "", "", "", "", "", "",
+		/*I0-I7*/ "", "", "", "", "", "QSPI2_RST_L-O", "GLOBAL_WP_BMC-O", "BMC_DDR4_TEN-O",
+		/*J0-J7*/ "", "", "", "", "", "", "", "",
+		/*K0-K7*/ "", "", "", "", "", "", "", "",
+		/*L0-L7*/ "", "", "", "", "", "", "", "",
+		/*M0-M7*/ "PCIE_EP_RST_EN-O", "BMC_FRU_WP-O", "HMC_RESET_L-O", "STBY_POWER_EN-O",
+					"STBY_POWER_PG-I", "PCIE_EP_RST_L-O", "", "",
+		/*N0-N7*/ "", "", "", "", "", "", "", "",
+		/*O0-O7*/ "", "", "", "", "", "", "", "",
+		/*P0-P7*/ "", "", "", "", "", "", "", "",
+		/*Q0-Q7*/ "", "", "", "", "", "", "", "",
+		/*R0-R7*/ "", "", "", "", "", "", "", "",
+		/*S0-S7*/ "", "", "", "", "", "", "", "",
+		/*T0-T7*/ "", "", "", "", "", "", "", "",
+		/*U0-U7*/ "", "", "", "", "", "", "", "",
+		/*V0-V7*/ "AP_EROT_REQ-O", "EROT_AP_GNT-I", "", "","PCB_TEMP_ALERT-I", "","", "",
+		/*W0-W7*/ "", "", "", "", "", "", "", "",
+		/*X0-X7*/ "", "", "TPM_MUX_SEL-O", "", "", "", "", "",
+		/*Y0-Y7*/ "", "", "", "EMMC_RST-O", "","", "", "",
+		/*Z0-Z7*/ "BMC_READY-O","", "", "", "", "", "", "";
+};
+
+&gpio1 {
+	/* 36 1.8V GPIOs */
+	gpio-line-names =
+		/*A0-A7*/ "", "", "", "", "", "", "", "",
+		/*B0-B7*/ "", "", "", "", "", "", "IO_EXPANDER_INT_L-I","",
+		/*C0-C7*/ "", "", "", "", "", "", "", "",
+		/*D0-D7*/ "", "", "", "", "", "", "SPI_HOST_TPM_RST_L-O", "SPI_BMC_FPGA_INT_L-I",
+		/*E0-E7*/ "", "", "", "", "", "", "", "";
+};
+
+// EMMC group that excludes WP pin
+&pinctrl {
+	pinctrl_emmcg5_default: emmcg5-default {
+		function = "EMMC";
+		groups = "EMMCG5";
+	};
+};
-- 
2.25.1



From rppt at kernel.org  Mon Mar 24 11:18:34 2025
From: rppt at kernel.org (Mike Rapoport)
Date: Mon, 24 Mar 2025 14:18:34 -0400
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <Z+BZOKSpyPA1Pyu+@nvidia.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-10-changyuanl@google.com>
 <20250321134629.GA252045@nvidia.com>
 <Z98Lmo50h5RboFXq@kernel.org>
 <Z+BZOKSpyPA1Pyu+@nvidia.com>
Message-ID: <Z-Gh-t9xB21UNGU2@kernel.org>

On Sun, Mar 23, 2025 at 03:55:52PM -0300, Jason Gunthorpe wrote:
> On Sat, Mar 22, 2025 at 03:12:26PM -0400, Mike Rapoport wrote:
>  
> > > > +		page->private = order;
> > > 
> > > Can't just set the page order directly? Why use private?
> > 
> > Setting the order means recreating the folio the way prep_compound_page()
> > does. I think it's better to postpone it until the folio is requested. This
> > way it might run after SMP is enabled. 
> 
> I see, that makes sense, but also it could stil use page->order..

But there's no page->order :)
 
> > Besides, when we start allocating
> > folios separately from struct page, initializing it here would be a real
> > issue.
> 
> Yes, but also we wouldn't have page->private to make it work.. Somehow
> anything we want to carry over would have to become encoded in the
> memdesc directly.

This is a problem to solve in 2026 :)

The January update for State of Page [1] talks about 

	reasonable goal to shrink struct page to (approximately): 

	struct page {
	    unsigned long flags;
	    union {
	        struct list_head buddy_list;
	        struct list_head pcp_list;
	        struct {
	            unsigned long memdesc;
	            int _refcount;
	        };
	    };
	    union {
	        unsigned long private;
	        struct {
	            int _folio_mapcount;
	        };
	    };
	};
 
[1] https://lore.kernel.org/linux-mm/Z37pxbkHPbLYnDKn at casper.infradead.org/
 
> Jason

-- 
Sincerely yours,
Mike.


From mike.leach at linaro.org  Mon Mar 24 11:21:39 2025
From: mike.leach at linaro.org (Mike Leach)
Date: Mon, 24 Mar 2025 18:21:39 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <Z+FlLDLV9WkGNbj+@e129823.arm.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com> <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
 <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
 <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com> <Z+FlLDLV9WkGNbj+@e129823.arm.com>
Message-ID: <CAJ9a7VgsBZ6MkgwVjDiOm7rvcy9KVPfPc_PbaRNX7ra8NWGb9Q@mail.gmail.com>

Hi,

On Mon, 24 Mar 2025 at 13:59, Yeoreum Yun <yeoreum.yun at arm.com> wrote:
>
> Hi Mike,
>
> Please ignore my foremer mail.. and please see my comments for your
> suggestion.
>
> > Hi
> >
> > On Fri, 14 Mar 2025 at 15:25, Yeo Reum Yun <YeoReum.Yun at arm.com> wrote:
> > >
> > > Hi, Mike.
> > >
> > > > >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > > > > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> > > > >
> > > > > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > > > > +{
> > > > > +       if (enable)
> > > > > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > > > > +
> > > >
> > > > Not sure why we have an "enable" parameter here - it completely
> > > > changes the meaning of the function - with no comment at the start.
> > >
> > > Sorry. But what I intended is to distinguish
> > >     - activation of config
> > >     - enable of activated config.
> > > Because, current coresight doesn't grab the module reference on enable of activate config,
> > > But It grabs that reference only in activation.
> > > That's why I used to "enable" parameter to distinguish this
> > > while I integrate with module_owner count.
> > >
> > > > >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> > > > >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > > > > -                       atomic_dec(&config_desc->active_cnt);
> > > > >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > > > > -                       cscfg_owner_put(config_desc->load_owner);
> > > > > +                       cscfg_config_desc_put(config_desc);
> > > > >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> > > > >                         break;
> > > > >                 }
> > > > > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > > >                                      unsigned long cfg_hash, int preset)
> > > > >  {
> > > > >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > > > > -       const struct cscfg_config_desc *config_desc;
> > > > > +       struct cscfg_config_desc *config_desc;
> > > > >         unsigned long flags;
> > > > >         int err = 0;
> > > > >
> > > > > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > > >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> > > > >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > > > >                 config_desc = config_csdev_item->config_desc;
> > > > > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > > > > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > > > > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > > > > +                               cscfg_config_desc_get(config_desc, true)) {
> > > > >
> > > > This obfuscates the logic of the comparisons without good reason. With
> > > > the true parameter, the function does no "get" operation but just
> > > > replicates the logic being replaced - checking the active_cnt is
> > > > non-zero.
> > > >
> > > > Restore this to the original logic to make it readable again
> > >
> > > It's not a replicates of comparsion logic, but if true,
> >
> > sorry - missed that point .
> >
> > > It get the reference of active_cnt but not get module reference.
> > > The fundemental fault in the UAF becase of just "atomic_read()"
> > > so, it should hold reference in here.
> > >
> > > So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
> > > I think there're two way to modfiy.
> > >
> > >     1. cscfg_config_desc_get()/put() always grab/drop the module count.
> > >     2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
> > >         with cscfg_owner_get()/put()
> > >
> > > Any thougt?
> > >
> > > Thanks!
> > >
> > >
> >
> > The get and put functions are asymmetrical w.r.t. owner.
> >
> > The put will put owner if active count decrements to 0,
> > The get if not on enable path will put owner unconditionally.
> >
> > This means that the caller has to work out the correct input conditions.
> >
> > Might be better if:-
> >
> > get_desc()
> > {
> >     if (! desc->refcnt) {
> >        if (!get_owner())
> >            return false;
> >    }
> >    desc->refcnt++;
> >     return true;
> > }
>
> I think This makes another problem when
> it races with _cscfg_deactivate_config().
>
> CPU0                                          CPU1
> (sysfs enable)                                load module
>                                               cscfg_load_config_sets()
>                                               activate config. // sysfs
>                                               (sys_active_cnt == 1)
>
>                                               // sysfs
>                                               _cscfg_deactivate_config()
>                                               (sys_active_cnt == 0)
>                                               (config->active_cnt = 0)
> ...
> cscfg_csdev_enable_active_config()
>   lock(csdev->cscfg_csdev_lock)
>   // here get module reference??
>   // even sys_active_cnt == 0 and
>   // config->active_cnt == 1.
>   get_desc()
>   unlock(csdev->cscfg_csdev_lock)
>
>
>   // access to config_desc which freed
>   // while unloading module.
>   cfs_csdev_enable_config
>
>
> Because, the desc->refcnt meaning of zero is different from the context.
>    - while activate . it should get module reference if zero.
>    - while enable active configuration, if zero, it should be failed.
>
> that means to prevent this race, the core key point is:
>    when config->active_cnt == 0, it should be failed in cscfg_csdev_enable_active_config()
>

This is not a failure case, it simple means that this config should
not be activated for this device.
It is possible for a configuration to be active on the system, without
it being active for a particular coresight device.

Having a get/put interface for the config descriptor - which prevents
the config from being unloaded is fine, the key logic here is that we
are searching a list of possible enabled configurations for this
device and taking the necessary action to enable it if we find one -
and there can only ever be a single configuration enabled for a trace
session.

Therefore when the list of loaded configs for a device is > 1, then
all but one is allowed to be active - so the search code will validly
find instances where config->active_cnt == 0.

My objection to the original interface was not the get/put operations
to protect the module from unload, but the fact that the logic
deciding if a config needed to be enabled on the device was hidden
inside the get() operation.
My suggestion is to restore the logic that decides if there is a
config to enable on the device be clear in the enable function itself,
then use get/put as appropriate to prevent module unload.

Regards

Mike


> Because, according to context the handling the zero reference value is
> different, It seems,to integrate the get_desc() interface to handle
> above case together without extra arguments (in case of here is
> "enable").
>
> If this interface is really ugly and unhappy to you,
> I think It should remove get_desc()/put_desc().
> although we can add new interface for cscfg_config_desc_get() for enable
> path. but it makes people more confused.
>
> So my suggestion is:
>    - sustain this patch's contents
>    - or remove get_desc()/put_desc() interface but use
>      atomic_inc_zero(&config_desc->active_cnt) directly in
>      cscfg_csdev_enable_active_config()
>
> Any thougt?
>
> Thanks.



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK


From helgaas at kernel.org  Mon Mar 24 11:28:27 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 24 Mar 2025 13:28:27 -0500
Subject: [PATCH v12 05/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
In-Reply-To: <j3qw4zmopulpn3iqq5wsjt6dbs4z3micoeoxkw3354txkx22ml@67ip5sfo6wwd>
Message-ID: <20250324182827.GA1257218@bhelgaas>

On Mon, Mar 24, 2025 at 10:48:23PM +0530, Manivannan Sadhasivam wrote:
> On Sat, Mar 15, 2025 at 03:15:40PM -0500, Bjorn Helgaas wrote:
> > From: Frank Li <Frank.Li at nxp.com>
> > 
> > Return the offset from CPU physical address to the parent bus address of
> > the specified element of the devicetree 'reg' property.

> > +resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> > +					  const char *reg_name,
> > +					  resource_size_t cpu_phy_addr)
> > +{
> 
> s/cpu_phy_addr/cpu_phys_addr/g

Fixed, thanks!

> > +	struct device *dev = pci->dev;
> > +	struct device_node *np = dev->of_node;
> > +	int index;
> > +	u64 reg_addr;
> > +
> > +	/* Look up reg_name address on parent bus */
> 
> 'parent bus' is not accurate as the below code checks for the 'reg_name' in
> current PCI controller node.

We want the address of "reg_name" on the node's primary side.  We've
been calling that the "parent bus address", I guess because it's the
address on the "parent bus" of the node.

I'm not sure what the best term is for this.  Do you have a
suggestion?

If "parent bus address" is the wrong term, maybe we need to rename
dw_pcie_parent_bus_offset() itself?  

Currently we pass in cpu_phys_addr, but this function doesn't need it
except for the debug code added later.  I would really rather have
something like this in the callers:

  pci->parent_bus_offset = pp->cfg0_base -
      dw_pcie_parent_bus_addr(pci, "config");

because then the offset is computed sort of at the same level where
it's used, and a grep for "cfg0_base" would find both the set and the
use and they would be easy to match up.

> > +	index = of_property_match_string(np, "reg-names", reg_name);
> > +
> > +	if (index < 0) {
> > +		dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
> 
> Both of these callers are checking for the existence of the
> 'reg_name' property before calling this API. So this check seems to
> be redundant (for now).

True, but I don't see a way to enforce the caller checks.  I don't
like the idea of calling of_property_read_reg(np, index, ...) where we
have to look the caller to verify that "index" is valid.

Bjorn


From Frank.li at nxp.com  Mon Mar 24 11:32:58 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 14:32:58 -0400
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <x2r2xfxrnkihvpoqiamgjmvppverjugp5r4we7lcfpz6jloxzy@7kdfzxiwv2po>
References: <20250315201548.858189-1-helgaas@kernel.org>
 <20250315201548.858189-7-helgaas@kernel.org>
 <x2r2xfxrnkihvpoqiamgjmvppverjugp5r4we7lcfpz6jloxzy@7kdfzxiwv2po>
Message-ID: <Z+GlWm4QAkuyb9nI@lizhi-Precision-Tower-5810>

On Mon, Mar 24, 2025 at 11:00:24PM +0530, Manivannan Sadhasivam wrote:
> On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> > From: Frank Li <Frank.Li at nxp.com>
> >
> > dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> > controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> > is a hard-coded way to get the parent bus address corresponding to a CPU
> > physical address.
> >
> > Add debug code to compare the address from .cpu_addr_fixup() with the
> > address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> > redundant and should be removed; if they differ, warn that something is
> > wrong with the devicetree.
> >
> > If .cpu_addr_fixup() is not implemented, the parent bus address should be
> > identical to the CPU physical address because we previously ignored the
> > parent bus address from devicetree.  If the devicetree has a different
> > parent bus address, warn about it being broken.
> >
> > [bhelgaas: split debug to separate patch for easier future revert, commit
> > log]
> > Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> > ---
> >  drivers/pci/controller/dwc/pcie-designware.c | 26 +++++++++++++++++++-
> >  drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++++
> >  2 files changed, 38 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> > index 0a35e36da703..985264c88b92 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >  	struct device *dev = pci->dev;
> >  	struct device_node *np = dev->of_node;
> >  	int index;
> > -	u64 reg_addr;
> > +	u64 reg_addr, fixup_addr;
> > +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
> >
> >  	/* Look up reg_name address on parent bus */
> >  	index = of_property_match_string(np, "reg-names", reg_name);
> > @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >
> >  	of_property_read_reg(np, index, &reg_addr, NULL);
> >
> > +	fixup = pci->ops->cpu_addr_fixup;
> > +	if (fixup) {
> > +		fixup_addr = fixup(pci, cpu_phy_addr);
> > +		if (reg_addr == fixup_addr) {
> > +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
> > +				 cpu_phy_addr, reg_name, index,
> > +				 fixup_addr, fixup);
> > +		} else {
> > +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> > +				 cpu_phy_addr, reg_name,
> > +				 index, fixup_addr);
> > +			reg_addr = fixup_addr;
> > +		}
> > +	} else if (!pci->use_parent_dt_ranges) {
>
> Is this check still valid? 'use_parent_dt_ranges' is only used here for
> validation. Moreover, if the fixup is not available, we should be able to
> safely return 'cpu_phy_addr - reg_addr' unconditionally.

I worry about some platform use fake bus address translation in dtb file.
If none report below warn for some times, we can remove all
use_parent_dt_ranges.

Frank

>
> > +		if (reg_addr != cpu_phy_addr) {
> > +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> > +				 cpu_phy_addr, reg_addr);
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> > +		 reg_name, cpu_phy_addr - reg_addr);
>
> This info is useless on platforms having no translation between CPU and PCI
> controller. The offset will always be 0.
>
> - Mani
>
> --
> ????????? ????????


From kuba at kernel.org  Mon Mar 24 11:34:43 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Mon, 24 Mar 2025 11:34:43 -0700
Subject: [PATCH net v2] net: stmmac: Fix accessing freed irq
 affinity_hint
In-Reply-To: <20250318032424.112067-1-dqfext@gmail.com>
References: <20250318032424.112067-1-dqfext@gmail.com>
Message-ID: <20250324113443.215c036f@kernel.org>

On Tue, 18 Mar 2025 11:24:23 +0800 Qingfang Deng wrote:
> -		cpumask_clear(&cpu_mask);
> -		cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
> -		irq_set_affinity_hint(priv->rx_irq[i], &cpu_mask);
> +		irq_set_affinity_hint(priv->rx_irq[i],
> +				      cpumask_of(i % num_online_cpus()));

This does fix the bug you're targeting, but FWIW num_online_cpus() 
is not great in general. The online CPU mask can be sparse.
You may want to look into finding 'nth' online CPU instead of the naive
modulo as a follow up.


From fvdl at google.com  Mon Mar 24 11:40:43 2025
From: fvdl at google.com (Frank van der Linden)
Date: Mon, 24 Mar 2025 11:40:43 -0700
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation helpers
In-Reply-To: <20250320015551.2157511-8-changyuanl@google.com>
References: <20250320015551.2157511-1-changyuanl@google.com> <20250320015551.2157511-8-changyuanl@google.com>
Message-ID: <CAPTztWbFXajArSN8yKu32eSoR=xsk1CHM_4V7MJ0eQxydFqPUQ@mail.gmail.com>

On Wed, Mar 19, 2025 at 6:56?PM Changyuan Lyu <changyuanl at google.com> wrote:
>
> From: Alexander Graf <graf at amazon.com>
>
> Add the core infrastructure to generate Kexec HandOver metadata. Kexec
> HandOver is a mechanism that allows Linux to preserve state - arbitrary
> properties as well as memory locations - across kexec.
>
> It does so using 2 concepts:
>
>   1) State Tree - Every KHO kexec carries a state tree that describes the
>      state of the system. The state tree is represented as hash-tables.
>      Device drivers can add/remove their data into/from the state tree at
>      system runtime. On kexec, the tree is converted to FDT (flattened
>      device tree).
>
>   2) Scratch Regions - CMA regions that we allocate in the first kernel.
>      CMA gives us the guarantee that no handover pages land in those
>      regions, because handover pages must be at a static physical memory
>      location. We use these regions as the place to load future kexec
>      images so that they won't collide with any handover data.
>
> Signed-off-by: Alexander Graf <graf at amazon.com>
> Co-developed-by: Pratyush Yadav <ptyadav at amazon.de>
> Signed-off-by: Pratyush Yadav <ptyadav at amazon.de>
> Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> ---
>  MAINTAINERS                    |   2 +-
>  include/linux/kexec_handover.h | 109 +++++
>  kernel/Makefile                |   1 +
>  kernel/kexec_handover.c        | 865 +++++++++++++++++++++++++++++++++
>  mm/mm_init.c                   |   8 +
>  5 files changed, 984 insertions(+), 1 deletion(-)
>  create mode 100644 include/linux/kexec_handover.h
>  create mode 100644 kernel/kexec_handover.c
[...]
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index 04441c258b05..757659b7a26b 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -30,6 +30,7 @@
>  #include <linux/crash_dump.h>
>  #include <linux/execmem.h>
>  #include <linux/vmstat.h>
> +#include <linux/kexec_handover.h>
>  #include "internal.h"
>  #include "slab.h"
>  #include "shuffle.h"
> @@ -2661,6 +2662,13 @@ void __init mm_core_init(void)
>         report_meminit();
>         kmsan_init_shadow();
>         stack_depot_early_init();
> +
> +       /*
> +        * KHO memory setup must happen while memblock is still active, but
> +        * as close as possible to buddy initialization
> +        */
> +       kho_memory_init();
> +
>         mem_init();
>         kmem_cache_init();
>         /*


Thanks for the work on this.

Obviously it needs to happen while memblock is still active - but why
as close as possible to buddy initialization?

Ordering is always a sticky issue when it comes to doing things during
boot, of course. In this case, I can see scenarios where code that
runs a little earlier may want to use some preserved memory. The
current requirement in the patch set seems to be "after sparse/page
init", but I'm not sure why it needs to be as close as possibly to
buddy init.

- Frank


From ariel.dalessandro at collabora.com  Mon Mar 24 11:44:03 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:44:03 -0300
Subject: [PATCH v4 4/6] drm/panfrost: Add support for AARCH64_4K page
 table format
In-Reply-To: <5hl2ahnxeunqebenguxjwwie6ura3lxknu766xthov2m4qvsot@imrrfqftlmv4>
References: <20250317145245.910566-1-ariel.dalessandro@collabora.com>
 <20250317145245.910566-5-ariel.dalessandro@collabora.com>
 <5hl2ahnxeunqebenguxjwwie6ura3lxknu766xthov2m4qvsot@imrrfqftlmv4>
Message-ID: <69da05c4-7471-47aa-a72d-b08d9b97e8dc@collabora.com>

Adrian,

On 3/22/25 3:48 PM, Adrian Larumbe wrote:
> On 17.03.2025 11:52, Ariel D'Alessandro wrote:
>> Currently, Panfrost only supports MMU configuration in "LEGACY" (as
>> Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
>> Address Extension", which in Linux we've called "mali_lpae".
>>
>> This commit adds support for conditionally enabling AARCH64_4K page
>> table format. To achieve that, a "GPU optional quirks" field was added
>> to `struct panfrost_features` with the related flag.
>>
>> Note that, in order to enable AARCH64_4K mode, the GPU variant must have
>> the HW_FEATURE_AARCH64_MMU feature flag present.
>>
>> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
>> Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
>> ---
>>   drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
>>   drivers/gpu/drm/panfrost/panfrost_mmu.c    | 140 +++++++++++++++++++--
>>   drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 +++++
>>   3 files changed, 183 insertions(+), 7 deletions(-)

[snip]

>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> index 294f86b3c25e7..506f42ccfd5fc 100644
>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c

[snip]

>> +static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
>> +				  enum io_pgtable_fmt fmt)
>> +{
>> +	struct panfrost_device *pfdev = mmu->pfdev;
>> +
>> +	switch (fmt) {
>> +	case ARM_64_LPAE_S1:
>> +		return mmu_cfg_init_aarch64_4k(mmu);
>> +	case ARM_MALI_LPAE:
>> +		return mmu_cfg_init_mali_lpae(mmu);
>> +	default:
>> +		/* This should never happen */
>> +		drm_WARN(pfdev->ddev, "Invalid pgtable format");
> 
> I think there's a '1' missing here before the string literal.
> Other than that,
> 
> Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>

Fixed, thanks!

Will send v5 right away.

-- 
Ariel D'Alessandro
Software Engineer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK 
Registered in England & Wales, no. 5513718



From patchwork-bot+netdevbpf at kernel.org  Mon Mar 24 11:50:32 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 24 Mar 2025 18:50:32 +0000
Subject: [PATCH net v2] net: stmmac: Fix accessing freed irq affinity_hint
In-Reply-To: <20250318032424.112067-1-dqfext@gmail.com>
References: <20250318032424.112067-1-dqfext@gmail.com>
Message-ID: <174284223202.4131627.8031895461636997073.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Tue, 18 Mar 2025 11:24:23 +0800 you wrote:
> The cpumask should not be a local variable, since its pointer is saved
> to irq_desc and may be accessed from procfs.
> To fix it, use the persistent mask cpumask_of(cpu#).
> 
> Cc: stable at vger.kernel.org
> Fixes: 8deec94c6040 ("net: stmmac: set IRQ affinity hint for multi MSI vectors")
> Signed-off-by: Qingfang Deng <dqfext at gmail.com>
> 
> [...]

Here is the summary with links:
  - [net,v2] net: stmmac: Fix accessing freed irq affinity_hint
    https://git.kernel.org/netdev/net/c/c60d101a226f

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Calculate cptr_el2 traps on activating traps" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-1-3150e3370c40@kernel.org>
Message-ID: <2025032428-eliminate-elope-f7b3@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Calculate cptr_el2 traps on activating traps

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125698-greg=kroah.com at vger.kernel.org Thu Mar 20 17:11:15 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:10 +0000
Subject: KVM: arm64: Calculate cptr_el2 traps on activating traps
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Fuad Tabba <tabba at google.com>,  James Clark <james.clark at linaro.org>
Message-ID: <20250321-stable-sve-6-13-v2-1-3150e3370c40 at kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    1 
 arch/arm64/kvm/arm.c              |    1 
 arch/arm64/kvm/hyp/nvhe/pkvm.c    |   30 ----------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  |   51 +++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 51 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -708,7 +708,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1569,7 +1569,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -31,8 +31,6 @@ static void pvm_init_traps_aa64pfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -62,21 +60,10 @@ static void pvm_init_traps_aa64pfr0(stru
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -106,7 +93,6 @@ static void pvm_init_traps_aa64dfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -133,21 +119,12 @@ static void pvm_init_traps_aa64dfr0(stru
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -198,10 +175,6 @@ static void pvm_init_trap_regs(struct kv
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
@@ -236,7 +209,6 @@ static void pkvm_vcpu_reset_hcr(struct k
  */
 static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 	vcpu->arch.mdcr_el2 = 0;
 
 	pkvm_vcpu_reset_hcr(vcpu);
@@ -693,8 +665,6 @@ unlock:
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_ve
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
+
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Eagerly switch ZCR_EL{1,2}" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-8-3150e3370c40@kernel.org>
Message-ID: <2025032428-pry-drum-e3ab@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Eagerly switch ZCR_EL{1,2}

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-eagerly-switch-zcr_el-1-2.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125705-greg=kroah.com at vger.kernel.org Thu Mar 20 17:13:07 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:17 +0000
Subject: KVM: arm64: Eagerly switch ZCR_EL{1,2}
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-8-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/fpsimd.c                 |   30 ----------------
 arch/arm64/kvm/hyp/entry.S              |    5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h |   59 ++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    9 +---
 arch/arm64/kvm/hyp/nvhe/switch.c        |   33 +++++++++++++++--
 arch/arm64/kvm/hyp/vhe/switch.c         |    4 ++
 6 files changed, 100 insertions(+), 40 deletions(-)

--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,6 +375,65 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -179,7 +180,9 @@ static void handle___kvm_vcpu_run(struct
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -480,12 +483,6 @@ void handle_trap(struct kvm_cpu_context
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kv
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Mark some header functions as inline" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-7-3150e3370c40@kernel.org>
Message-ID: <2025032428-lubricate-antics-55bb@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Mark some header functions as inline

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-mark-some-header-functions-as-inline.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125704-greg=kroah.com at vger.kernel.org Thu Mar 20 17:12:25 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:16 +0000
Subject: KVM: arm64: Mark some header functions as inline
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-7-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -326,7 +326,7 @@ static inline bool __populate_fault_info
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -404,7 +404,7 @@ static void kvm_hyp_save_fpsimd_host(str
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -595,7 +595,7 @@ static bool handle_ampere1_tcr(struct kv
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -615,7 +615,7 @@ static bool kvm_hyp_handle_sysreg(struct
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -624,19 +624,18 @@ static bool kvm_hyp_handle_cp15_32(struc
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Refactor exit handlers" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-6-3150e3370c40@kernel.org>
Message-ID: <2025032428-uncivil-amplify-e3cb@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Refactor exit handlers

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-refactor-exit-handlers.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125703-greg=kroah.com at vger.kernel.org Thu Mar 20 17:12:07 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:15 +0000
Subject: KVM: arm64: Refactor exit handlers
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-6-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -666,23 +666,16 @@ static bool kvm_hyp_handle_dabt_low(stru
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -712,20 +705,9 @@ static inline void synchronize_vcpu_psta
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -755,7 +737,7 @@ static inline bool fixup_guest_exit(stru
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_ex
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_ha
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Remove host FPSIMD saving for non-protected KVM" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-3-3150e3370c40@kernel.org>
Message-ID: <2025032428-bankable-reopen-a827@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove host FPSIMD saving for non-protected KVM

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125700-greg=kroah.com at vger.kernel.org Thu Mar 20 17:11:26 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:12 +0000
Subject: KVM: arm64: Remove host FPSIMD saving for non-protected KVM
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-3-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[CPACR_EL1_ZEN -> CPACR_ELx_ZEN -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h       |   18 ++++--------------
 arch/arm64/kvm/arm.c                    |    8 --------
 arch/arm64/kvm/fpsimd.c                 |    2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h |   25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    8 --------
 7 files changed, 28 insertions(+), 63 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -613,23 +613,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
+	struct cpu_sve_state *sve_state;
 
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2468,14 +2468,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -375,7 +375,28 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -425,7 +446,7 @@ static bool kvm_hyp_handle_fpsimd(struct
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_v
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct k
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-5-3150e3370c40@kernel.org>
Message-ID: <2025032428-raving-turbojet-84c2@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125702-greg=kroah.com at vger.kernel.org Thu Mar 20 17:12:15 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:14 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-5-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   21 ---------------------
 2 files changed, 23 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:28 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:28 -0700
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-4-3150e3370c40@kernel.org>
Message-ID: <2025032428-blunderer-gong-40b5@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125701-greg=kroah.com at vger.kernel.org Thu Mar 20 17:12:02 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:13 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-13-v2-4-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   16 ----------------
 2 files changed, 18 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -902,8 +902,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:56:29 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:56:29 -0700
Subject: Patch "KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state" has been added to the 6.13-stable tree
In-Reply-To: <20250321-stable-sve-6-13-v2-2-3150e3370c40@kernel.org>
Message-ID: <2025032428-traps-smugness-faee@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125699-greg=kroah.com at vger.kernel.org Thu Mar 20 17:11:20 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:10:11 +0000
Subject: KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Eric Auger <eauger at redhat.com>, Wilco Dijkstra <wilco.dijkstra at arm.com>,  Eric Auger <eric.auger at redhat.com>, Florian Weimer <fweimer at redhat.com>,  Fuad Tabba <tabba at google.com>, Jeremy Linton <jeremy.linton at arm.com>,  Paolo Bonzini <pbonzini at redhat.com>
Message-ID: <20250321-stable-sve-6-13-v2-2-3150e3370c40 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kernel/fpsimd.c |   25 -------------------------
 arch/arm64/kvm/fpsimd.c    |   35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1695,31 +1695,6 @@ void fpsimd_signal_preserve_current_stat
 }
 
 /*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
-/*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
  * this function.
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.13/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.13/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.13/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.13/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.13/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.13/regulator-dummy-force-synchronous-probing.patch
queue-6.13/kvm-arm64-refactor-exit-handlers.patch
queue-6.13/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.13/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From ardb+git at google.com  Mon Mar 24 11:59:28 2025
From: ardb+git at google.com (Ard Biesheuvel)
Date: Mon, 24 Mar 2025 19:59:28 +0100
Subject: [PATCH] ARM: Disallow kernel mode NEON when IRQs are disabled
Message-ID: <20250324185927.1024543-2-ardb+git@google.com>

From: Ard Biesheuvel <ardb at kernel.org>

Commit

  c79f81631142 ("ARM: 9283/1: permit non-nested kernel mode NEON in softirq context")

relaxed the rules around the use of SIMD instructions in kernel mode on
ARM, to allow such use when serving a softirq. To avoid having to
preserve/restore kernel mode NEON state when such a softirq is taken,
softirqs are now disabled when using the NEON from task context.

However, the fact that the softirq API does not allow unmasking of
softirqs with interrupts disabled was overlooked, resulting in a WARN()
in some cases, as reported by Guenter:

  WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
  Call trace:
   unwind_backtrace from show_stack+0x10/0x14
   show_stack from dump_stack_lvl+0x7c/0xac
   dump_stack_lvl from __warn+0x7c/0x1b8
   __warn from warn_slowpath_fmt+0x19c/0x1a4
   warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
   __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
   crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
   crc_t10dif_wrapper from crc_main_test+0x178/0x360
   crc_main_test from kunit_try_run_case+0x78/0x1e0
   kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
   kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
   kthread from ret_from_fork+0x14/0x28

While disabling softirqs is not really needed when running with IRQs
disabled (given that the only way a softirq can be delivered
asynchrously is over the back of an IRQ), let's not complicate this
logic more than needed, and simply disallow use of the NEON in kernel
mode when IRQs are disabled.

Another approach might be to only disable and re-enable softirqs if IRQs
are enabled, but other than the test case above, there are no clear use
cases for doing non-trivial arithmetic processing (hence using an
accelerated SIMD implementation) with IRQs disabled.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Link: https://lore.kernel.org/all/389b899f-893c-4855-9e30-d8920a5d6f91 at roeck-us.net
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm/include/asm/simd.h | 3 ++-
 arch/arm/vfp/vfpmodule.c    | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
index 82191dbd7e78..e604a9382960 100644
--- a/arch/arm/include/asm/simd.h
+++ b/arch/arm/include/asm/simd.h
@@ -4,5 +4,6 @@
 
 static __must_check inline bool may_use_simd(void)
 {
-	return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
+	return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq()
+	       && !irqs_disabled();
 }
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 7803d50b90f8..e559ad3cd148 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -877,6 +877,7 @@ void kernel_neon_begin(void)
 	 * the kernel mode NEON register contents never need to be preserved.
 	 */
 	BUG_ON(in_hardirq());
+	BUG_ON(irqs_disabled());
 	cpu = __smp_processor_id();
 
 	fpexc = fmrx(FPEXC) | FPEXC_EN;
-- 
2.49.0.395.g12beb8f557-goog



From ariel.dalessandro at collabora.com  Mon Mar 24 11:57:55 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:57:55 -0300
Subject: [PATCH v5 0/6] drm/panfrost: Add support for AARCH64_4K page table format
Message-ID: <20250324185801.168664-1-ariel.dalessandro@collabora.com>

Hi all,

This is a new iteration on Panfrost support for AARCH64_4K page table
format. The main reason behind this patchset is that MediaTek MT8188 SoC
(ARM Mali-G57 MC3 GPU) constantly faults due to the actual Panfrost cache
configuration.

Currently, Panfrost only supports MMU configuration in "LEGACY" (as Bifrost
calls it) mode, a (modified) version of LPAE "Large Physical Address
Extension", which in Linux we've called "mali_lpae".

This patchset adds support for conditionally enabling AARCH64_4K page table
format. To achieve that, a "GPU optional quirks" field was added to
`struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

The patchset only enables the new format on Mediatek MT8188 and MT8192,
which have been tested on a Mediatek Genio 700 EVK (MT8390) and Mediatek
Genio 1200 EVK (MT8395) boards respectively.

Thanks!

Changes in v5:
* Fixed drm_WARN() in panfrost_mmu_cfg_init().

Changes in v4:
* Fixed panfrost_mmu_cfg_init() return value on warning.

Changes in v3:
* Fixed error handling in panfrost_mmu_ctx_create().

Changes in v2:
* Dropped panfrost_mmu_enable/disable unification.
* Rename gpu_configs as gpu_quirks.
* Added error handling on page table not properly aligned.
* Enabled AARCH64_4K format on MediaTek MT8192 as well.
* Minor fixes.

Changes in v1:
* Added "Set IOMMU_CACHE flag" patch.
* Replaced `panfrost_mmu->enable()` function pointer by `cfg` struct
prepared during init time.
* Made mali_lpae/aarch64_4k name more clear.
* Added GPU_CONFIG_AARCH64_4K flag to enable AARCH64_4K page table
  format.
* Enabled AARCH64_4K mode only on mediatek-mt8188.

Ariel D'Alessandro (6):
  drm/panfrost: Set IOMMU_CACHE flag
  drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
  drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost
    models
  drm/panfrost: Add support for AARCH64_4K page table format
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
  drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192

 drivers/gpu/drm/panfrost/panfrost_device.h   |  16 ++
 drivers/gpu/drm/panfrost/panfrost_drv.c      |   2 +
 drivers/gpu/drm/panfrost/panfrost_features.h |   3 +
 drivers/gpu/drm/panfrost/panfrost_mmu.c      | 150 +++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h     |  36 +++++
 5 files changed, 196 insertions(+), 11 deletions(-)

-- 
2.49.0



From ariel.dalessandro at collabora.com  Mon Mar 24 11:57:56 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:57:56 -0300
Subject: [PATCH v5 1/6] drm/panfrost: Set IOMMU_CACHE flag
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-2-ariel.dalessandro@collabora.com>

Panfrost does not support uncached mappings, so flag them properly. Also
flag the pages that are mapped as response to a page fault as cached.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index b91019cd5acb..9e6f198ef5c1 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -327,7 +327,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 	struct drm_gem_object *obj = &shmem->base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
-	int prot = IOMMU_READ | IOMMU_WRITE;
+	int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE;
 
 	if (WARN_ON(mapping->active))
 		return 0;
@@ -528,7 +528,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
 		goto err_map;
 
 	mmu_map_sg(pfdev, bomapping->mmu, addr,
-		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_CACHE | IOMMU_NOEXEC, sgt);
 
 	bomapping->active = true;
 	bo->heap_rss_size += SZ_2M;
-- 
2.49.0



From ariel.dalessandro at collabora.com  Mon Mar 24 11:57:57 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:57:57 -0300
Subject: [PATCH v5 2/6] drm/panfrost: Use GPU_MMU_FEATURES_VA_BITS/PA_BITS macros
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-3-ariel.dalessandro@collabora.com>

As done in panthor, define and use these GPU_MMU_FEATURES_* macros,
which makes code easier to read and reuse.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_mmu.c  | 6 ++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 9e6f198ef5c1..294f86b3c25e 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -615,6 +615,8 @@ static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
 
 struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 {
+	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
+	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
@@ -633,8 +635,8 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 
 	mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
 		.pgsize_bitmap	= SZ_4K | SZ_2M,
-		.ias		= FIELD_GET(0xff, pfdev->features.mmu_features),
-		.oas		= FIELD_GET(0xff00, pfdev->features.mmu_features),
+		.ias		= va_bits,
+		.oas		= pa_bits,
 		.coherent_walk	= pfdev->coherent,
 		.tlb		= &mmu_tlb_ops,
 		.iommu_dev	= pfdev->dev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index c7bba476ab3f..b5f279a19a08 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -16,6 +16,8 @@
 #define   GROUPS_L2_COHERENT		BIT(0)	/* Cores groups are l2 coherent */
 
 #define GPU_MMU_FEATURES		0x014	/* (RO) MMU features */
+#define  GPU_MMU_FEATURES_VA_BITS(x)	((x) & GENMASK(7, 0))
+#define  GPU_MMU_FEATURES_PA_BITS(x)	(((x) >> 8) & GENMASK(7, 0))
 #define GPU_AS_PRESENT			0x018	/* (RO) Address space slots present */
 #define GPU_JS_PRESENT			0x01C	/* (RO) Job slots present */
 
-- 
2.49.0



From yeoreum.yun at arm.com  Mon Mar 24 12:17:40 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Mon, 24 Mar 2025 19:17:40 +0000
Subject: [PATCH v4] coresight: prevent deactivate active config while enabling the config
Message-ID: <20250324191740.64964-1-yeoreum.yun@arm.com>

While enable active config via cscfg_csdev_enable_active_config(),
active config could be deactivated via configfs' sysfs interface.
This could make UAF issue in below scenario:

CPU0                                          CPU1
(sysfs enable)                                load module
                                              cscfg_load_config_sets()
                                              activate config. // sysfs
                                              (sys_active_cnt == 1)
...
cscfg_csdev_enable_active_config()
  lock(csdev->cscfg_csdev_lock)
  // here load config activate by CPU1
  unlock(csdev->cscfg_csdev_lock)

                                              deactivate config // sysfs
                                              (sys_activec_cnt == 0)
                                              cscfg_unload_config_sets()
                                              unload module

  // access to config_desc which freed
  // while unloading module.
  cfs_csdev_enable_config

To address this, use cscfg_config_desc's active_cnt as a reference count
which will be holded when
    - activate the config.
    - enable the activated config.
and put the module reference when config_active_cnt == 0.

Signed-off-by: Yeoreum Yun <yeoreum.yun at arm.com>
---
Since v3:
  - Remove enable arguments in cscfg_config_desc_get() (from Mike).
  - https://lore.kernel.org/all/20250109171956.3535294-1-yeoreum.yun at arm.com/
---
 .../hwtracing/coresight/coresight-config.h    |  2 +-
 .../coresight/coresight-etm4x-core.c          |  3 ++
 .../hwtracing/coresight/coresight-syscfg.c    | 52 +++++++++++++------
 3 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index b9ebc9fcfb7f..90fd937d3bd8 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
  * @feats_csdev:references to the device features to enable.
  */
 struct cscfg_config_csdev {
-	const struct cscfg_config_desc *config_desc;
+	struct cscfg_config_desc *config_desc;
 	struct coresight_device *csdev;
 	bool enabled;
 	struct list_head node;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e5972f16abff..ef96028fa56b 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1020,6 +1020,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);

 	raw_spin_unlock(&drvdata->spinlock);
+
+	cscfg_csdev_disable_active_config(csdev);
+
 	cpus_read_unlock();

 	/*
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index a70c1454b410..6d8c212ad434 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -391,14 +391,17 @@ static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info)
 static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner)
 {
 	struct cscfg_config_csdev *config_csdev, *tmp;
+	unsigned long flags;

 	if (list_empty(&csdev->config_csdev_list))
 		return;

+	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
 		if (config_csdev->config_desc->load_owner == load_owner)
 			list_del(&config_csdev->node);
 	}
+	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 }

 static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
@@ -867,6 +870,25 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);

+static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc)
+{
+	if (!atomic_fetch_inc(&config_desc->active_cnt)) {
+		/* must ensure that config cannot be unloaded in use */
+		if (unlikely(cscfg_owner_get(config_desc->load_owner))) {
+			atomic_dec(&config_desc->active_cnt);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
+{
+	if (!atomic_dec_return(&config_desc->active_cnt))
+		cscfg_owner_put(config_desc->load_owner);
+}
+
 /*
  * This activate configuration for either perf or sysfs. Perf can have multiple
  * active configs, selected per event, sysfs is limited to one.
@@ -890,22 +912,17 @@ static int _cscfg_activate_config(unsigned long cfg_hash)
 			if (config_desc->available == false)
 				return -EBUSY;

-			/* must ensure that config cannot be unloaded in use */
-			err = cscfg_owner_get(config_desc->load_owner);
-			if (err)
+			if (!cscfg_config_desc_get(config_desc)) {
+				err = -EINVAL;
 				break;
+			}
+
 			/*
 			 * increment the global active count - control changes to
 			 * active configurations
 			 */
 			atomic_inc(&cscfg_mgr->sys_active_cnt);

-			/*
-			 * mark the descriptor as active so enable config on a
-			 * device instance will use it
-			 */
-			atomic_inc(&config_desc->active_cnt);
-
 			err = 0;
 			dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
 			break;
@@ -920,9 +937,8 @@ static void _cscfg_deactivate_config(unsigned long cfg_hash)

 	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
 		if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
-			atomic_dec(&config_desc->active_cnt);
 			atomic_dec(&cscfg_mgr->sys_active_cnt);
-			cscfg_owner_put(config_desc->load_owner);
+			cscfg_config_desc_put(config_desc);
 			dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
 			break;
 		}
@@ -1047,7 +1063,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 				     unsigned long cfg_hash, int preset)
 {
 	struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
-	const struct cscfg_config_desc *config_desc;
+	struct cscfg_config_desc *config_desc;
 	unsigned long flags;
 	int err = 0;

@@ -1062,8 +1078,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 	list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
 		config_desc = config_csdev_item->config_desc;
-		if ((atomic_read(&config_desc->active_cnt)) &&
-		    ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
+		if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
+				cscfg_config_desc_get(config_desc)) {
 			config_csdev_active = config_csdev_item;
 			csdev->active_cscfg_ctxt = (void *)config_csdev_active;
 			break;
@@ -1097,7 +1113,11 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
 				err = -EBUSY;
 			raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 		}
+
+		if (err)
+			cscfg_config_desc_put(config_desc);
 	}
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
@@ -1136,8 +1156,10 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
 	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);

 	/* true if there was an enabled active config */
-	if (config_csdev)
+	if (config_csdev) {
 		cscfg_csdev_disable_config(config_csdev);
+		cscfg_config_desc_put(config_csdev->config_desc);
+	}
 }
 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);

--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



From Frank.li at nxp.com  Mon Mar 24 12:18:56 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 15:18:56 -0400
Subject: [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s
 Receiver Impedance ECN
In-Reply-To: <20250324062647.1891896-5-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-5-hongxing.zhu@nxp.com>
Message-ID: <Z+GwIOBB9MwoKfpf@lizhi-Precision-Tower-5810>

On Mon, Mar 24, 2025 at 02:26:46PM +0800, Richard Zhu wrote:
> Workaround for ERR051586: Compliance with 8GT/s Receiver Impedance ECN.
>
> The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is 1 which
> makes receiver non-compliant with the ZRX-DC parameter for 2.5 GT/s when
> operating at 8 GT/s or higher. It causes unnecessary timeout in L1.
>
> Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
>
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 29 +++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 52aa8bd66cde..dda3eed99bb8 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -131,6 +131,7 @@ struct imx_pcie_drvdata {
>  	int (*init_phy)(struct imx_pcie *pcie);
>  	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
>  	int (*core_reset)(struct imx_pcie *pcie, bool assert);
> +	void (*post_config)(struct imx_pcie *pcie);
>  	const struct dw_pcie_host_ops *ops;
>  };
>
> @@ -1158,6 +1159,29 @@ static void imx_pcie_disable_device(struct pci_host_bridge *bridge,
>  	imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev));
>  }
>
> +static void imx95_pcie_post_config(struct imx_pcie *imx_pcie)

There are already have post_init in dwc dw_pcie_host_ops

struct dw_pcie_host_ops {
        int (*init)(struct dw_pcie_rp *pp);
        void (*deinit)(struct dw_pcie_rp *pp);
        void (*post_init)(struct dw_pcie_rp *pp);
        int (*msi_init)(struct dw_pcie_rp *pp);
        void (*pme_turn_off)(struct dw_pcie_rp *pp);
};

Can you use it directly?

Frank

> +{
> +	u32 val;
> +	struct dw_pcie *pci = imx_pcie->pci;

struct dw_pcie *pci = imx_pcie->pci;
u32 val;

> +
> +	/*
> +	 * Workaround for ERR051586: Compliance with 8GT/s Receiver
> +	 * Impedance ECN
> +	 *
> +	 * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is
> +	 * 1 which makes receiver non-compliant with the ZRX-DC
> +	 * parameter for 2.5 GT/s when operating at 8 GT/s or higher. It
> +	 * causes unnecessary timeout in L1.
> +	 *
> +	 * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
> +	 */
> +	dw_pcie_dbi_ro_wr_en(pci);
> +	val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
> +	val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
> +	dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
> +	dw_pcie_dbi_ro_wr_dis(pci);
> +}
> +
>  static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> @@ -1222,6 +1246,9 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>
>  	imx_setup_phy_mpll(imx_pcie);
>
> +	if (imx_pcie->drvdata->post_config)
> +		imx_pcie->drvdata->post_config(imx_pcie);
> +
>  	return 0;
>
>  err_phy_off:
> @@ -1808,6 +1835,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
>  		.core_reset = imx95_pcie_core_reset,
>  		.init_phy = imx95_pcie_init_phy,
> +		.post_config = imx95_pcie_post_config,
>  	},
>  	[IMX8MQ_EP] = {
>  		.variant = IMX8MQ_EP,
> @@ -1863,6 +1891,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  		.core_reset = imx95_pcie_core_reset,
>  		.epc_features = &imx95_pcie_epc_features,
>  		.mode = DW_PCIE_EP_TYPE,
> +		.post_config = imx95_pcie_post_config,
>  	},
>  };
>
> --
> 2.37.1
>


From ariel.dalessandro at collabora.com  Mon Mar 24 11:57:58 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:57:58 -0300
Subject: [PATCH v5 3/6] drm/panfrost: Set HW_FEATURE_AARCH64_MMU feature flag on Bifrost models
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-4-ariel.dalessandro@collabora.com>

Set this feature flag on all Mali Bifrost platforms as the MMU supports
AARCH64 4K page table format.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Steven Price <steven.price at arm.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_features.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_features.h b/drivers/gpu/drm/panfrost/panfrost_features.h
index 7ed0cd3ea2d4..52f9d69f6db9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_features.h
+++ b/drivers/gpu/drm/panfrost/panfrost_features.h
@@ -54,6 +54,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g72 (\
@@ -64,6 +65,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g51 hw_features_g72
@@ -77,6 +79,7 @@ enum panfrost_hw_feature {
 	BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
 	BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
 	BIT_ULL(HW_FEATURE_IDVS_GROUP_SIZE) | \
+	BIT_ULL(HW_FEATURE_AARCH64_MMU) | \
 	BIT_ULL(HW_FEATURE_COHERENCY_REG))
 
 #define hw_features_g76 (\
-- 
2.49.0



From ariel.dalessandro at collabora.com  Mon Mar 24 11:57:59 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:57:59 -0300
Subject: [PATCH v5 4/6] drm/panfrost: Add support for AARCH64_4K page table format
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-5-ariel.dalessandro@collabora.com>

Currently, Panfrost only supports MMU configuration in "LEGACY" (as
Bifrost calls it) mode, a (modified) version of LPAE "Large Physical
Address Extension", which in Linux we've called "mali_lpae".

This commit adds support for conditionally enabling AARCH64_4K page
table format. To achieve that, a "GPU optional quirks" field was added
to `struct panfrost_features` with the related flag.

Note that, in order to enable AARCH64_4K mode, the GPU variant must have
the HW_FEATURE_AARCH64_MMU feature flag present.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Adri?n Larumbe <adrian.larumbe at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_device.h |  16 +++
 drivers/gpu/drm/panfrost/panfrost_mmu.c    | 140 +++++++++++++++++++--
 drivers/gpu/drm/panfrost/panfrost_regs.h   |  34 +++++
 3 files changed, 183 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index cffcb0ac7c11..ad95f2ed31d9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -42,6 +42,14 @@ enum panfrost_gpu_pm {
 	GPU_PM_VREG_OFF,
 };
 
+/**
+ * enum panfrost_gpu_quirks - GPU optional quirks
+ * @GPU_QUIRK_FORCE_AARCH64_PGTABLE: Use AARCH64_4K page table format
+ */
+enum panfrost_gpu_quirks {
+	GPU_QUIRK_FORCE_AARCH64_PGTABLE,
+};
+
 struct panfrost_features {
 	u16 id;
 	u16 revision;
@@ -95,6 +103,9 @@ struct panfrost_compatible {
 
 	/* Allowed PM features */
 	u8 pm_features;
+
+	/* GPU configuration quirks */
+	u8 gpu_quirks;
 };
 
 struct panfrost_device {
@@ -162,6 +173,11 @@ struct panfrost_mmu {
 	int as;
 	atomic_t as_count;
 	struct list_head list;
+	struct {
+		u64 transtab;
+		u64 memattr;
+		u64 transcfg;
+	} cfg;
 };
 
 struct panfrost_engine_usage {
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 294f86b3c25e..ccf51fd5f9c0 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -26,6 +26,48 @@
 #define mmu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define mmu_read(dev, reg) readl(dev->iomem + reg)
 
+static u64 mair_to_memattr(u64 mair, bool coherent)
+{
+	u64 memattr = 0;
+	u32 i;
+
+	for (i = 0; i < 8; i++) {
+		u8 in_attr = mair >> (8 * i), out_attr;
+		u8 outer = in_attr >> 4, inner = in_attr & 0xf;
+
+		/* For caching to be enabled, inner and outer caching policy
+		 * have to be both write-back, if one of them is write-through
+		 * or non-cacheable, we just choose non-cacheable. Device
+		 * memory is also translated to non-cacheable.
+		 */
+		if (!(outer & 3) || !(outer & 4) || !(inner & 4)) {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC |
+				   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false);
+		} else {
+			out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB |
+				   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2);
+			/* Use SH_MIDGARD_INNER mode when device isn't coherent,
+			 * so SH_IS, which is used when IOMMU_CACHE is set, maps
+			 * to Mali's internal-shareable mode. As per the Mali
+			 * Spec, inner and outer-shareable modes aren't allowed
+			 * for WB memory when coherency is disabled.
+			 * Use SH_CPU_INNER mode when coherency is enabled, so
+			 * that SH_IS actually maps to the standard definition of
+			 * inner-shareable.
+			 */
+			if (!coherent)
+				out_attr |= AS_MEMATTR_AARCH64_SH_MIDGARD_INNER;
+			else
+				out_attr |= AS_MEMATTR_AARCH64_SH_CPU_INNER;
+		}
+
+		memattr |= (u64)out_attr << (8 * i);
+	}
+
+	return memattr;
+}
+
 static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
 {
 	int ret;
@@ -124,9 +166,9 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as_nr = mmu->as;
-	struct io_pgtable_cfg *cfg = &mmu->pgtbl_cfg;
-	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
-	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
+	u64 transtab = mmu->cfg.transtab;
+	u64 memattr = mmu->cfg.memattr;
+	u64 transcfg = mmu->cfg.transcfg;
 
 	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
@@ -139,6 +181,9 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
@@ -152,9 +197,67 @@ static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 	mmu_write(pfdev, AS_MEMATTR_LO(as_nr), 0);
 	mmu_write(pfdev, AS_MEMATTR_HI(as_nr), 0);
 
+	mmu_write(pfdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
+	mmu_write(pfdev, AS_TRANSCFG_HI(as_nr), 0);
+
 	write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
 }
 
+static int mmu_cfg_init_mali_lpae(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+
+	/* TODO: The following fields are duplicated between the MMU and Page
+	 * Table config structs. Ideally, should be kept in one place.
+	 */
+	mmu->cfg.transtab = pgtbl_cfg->arm_mali_lpae_cfg.transtab;
+	mmu->cfg.memattr = pgtbl_cfg->arm_mali_lpae_cfg.memattr;
+	mmu->cfg.transcfg = AS_TRANSCFG_ADRMODE_LEGACY;
+
+	return 0;
+}
+
+static int mmu_cfg_init_aarch64_4k(struct panfrost_mmu *mmu)
+{
+	struct io_pgtable_cfg *pgtbl_cfg = &mmu->pgtbl_cfg;
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	if (drm_WARN_ON(pfdev->ddev, pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
+				     ~AS_TRANSTAB_AARCH64_4K_ADDR_MASK))
+		return -EINVAL;
+
+	mmu->cfg.transtab = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+
+	mmu->cfg.memattr = mair_to_memattr(pgtbl_cfg->arm_lpae_s1_cfg.mair,
+					   pgtbl_cfg->coherent_walk);
+
+	mmu->cfg.transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
+			    AS_TRANSCFG_PTW_RA |
+			    AS_TRANSCFG_ADRMODE_AARCH64_4K |
+			    AS_TRANSCFG_INA_BITS(55 - pgtbl_cfg->ias);
+	if (pgtbl_cfg->coherent_walk)
+		mmu->cfg.transcfg |= AS_TRANSCFG_PTW_SH_OS;
+
+	return 0;
+}
+
+static int panfrost_mmu_cfg_init(struct panfrost_mmu *mmu,
+				  enum io_pgtable_fmt fmt)
+{
+	struct panfrost_device *pfdev = mmu->pfdev;
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		return mmu_cfg_init_aarch64_4k(mmu);
+	case ARM_MALI_LPAE:
+		return mmu_cfg_init_mali_lpae(mmu);
+	default:
+		/* This should never happen */
+		drm_WARN(pfdev->ddev, 1, "Invalid pgtable format");
+		return -EINVAL;
+	}
+}
+
 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
 {
 	int as;
@@ -618,6 +721,19 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 	u32 va_bits = GPU_MMU_FEATURES_VA_BITS(pfdev->features.mmu_features);
 	u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(pfdev->features.mmu_features);
 	struct panfrost_mmu *mmu;
+	enum io_pgtable_fmt fmt;
+	int ret;
+
+	if (pfdev->comp->gpu_quirks & BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE)) {
+		if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_AARCH64_MMU)) {
+			dev_err_once(pfdev->dev,
+				     "AARCH64_4K page table not supported\n");
+			return ERR_PTR(-EINVAL);
+		}
+		fmt = ARM_64_LPAE_S1;
+	} else {
+		fmt = ARM_MALI_LPAE;
+	}
 
 	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
 	if (!mmu)
@@ -642,16 +758,26 @@ struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
 		.iommu_dev	= pfdev->dev,
 	};
 
-	mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
-					      mmu);
+	mmu->pgtbl_ops = alloc_io_pgtable_ops(fmt, &mmu->pgtbl_cfg, mmu);
 	if (!mmu->pgtbl_ops) {
-		kfree(mmu);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto err_free_mmu;
 	}
 
+	ret = panfrost_mmu_cfg_init(mmu, fmt);
+	if (ret)
+		goto err_free_io_pgtable;
+
 	kref_init(&mmu->refcount);
 
 	return mmu;
+
+err_free_io_pgtable:
+	free_io_pgtable_ops(mmu->pgtbl_ops);
+
+err_free_mmu:
+	kfree(mmu);
+	return ERR_PTR(ret);
 }
 
 static const char *access_type_name(struct panfrost_device *pfdev,
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index b5f279a19a08..2b8f1617b836 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -301,6 +301,17 @@
 #define AS_TRANSTAB_HI(as)		(MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_MEMATTR_LO(as)		(MMU_AS(as) + 0x08) /* (RW) Memory attributes for address space n, low word. */
 #define AS_MEMATTR_HI(as)		(MMU_AS(as) + 0x0C) /* (RW) Memory attributes for address space n, high word. */
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
+#define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
+							 ((w) ? BIT(0) : 0) | \
+							 ((r) ? BIT(1) : 0))
+#define   AS_MEMATTR_AARCH64_SH_MIDGARD_INNER		(0 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER		(1 << 4)
+#define   AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH	(2 << 4)
+#define   AS_MEMATTR_AARCH64_SHARED			(0 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
+#define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
+#define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
 #define AS_LOCKADDR_LO(as)		(MMU_AS(as) + 0x10) /* (RW) Lock region address for address space n, low word */
 #define AS_LOCKADDR_HI(as)		(MMU_AS(as) + 0x14) /* (RW) Lock region address for address space n, high word */
 #define AS_COMMAND(as)			(MMU_AS(as) + 0x18) /* (WO) MMU command register for address space n */
@@ -311,6 +322,24 @@
 /* Additional Bifrost AS registers */
 #define AS_TRANSCFG_LO(as)		(MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
 #define AS_TRANSCFG_HI(as)		(MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
+#define   AS_TRANSCFG_ADRMODE_LEGACY			(0 << 0)
+#define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
+#define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
+#define   AS_TRANSCFG_ADRMODE_AARCH64_64K		(8 << 0)
+#define   AS_TRANSCFG_INA_BITS(x)			((x) << 6)
+#define   AS_TRANSCFG_OUTA_BITS(x)			((x) << 14)
+#define   AS_TRANSCFG_SL_CONCAT				BIT(22)
+#define   AS_TRANSCFG_PTW_MEMATTR_NC			(1 << 24)
+#define   AS_TRANSCFG_PTW_MEMATTR_WB			(2 << 24)
+#define   AS_TRANSCFG_PTW_SH_NS				(0 << 28)
+#define   AS_TRANSCFG_PTW_SH_OS				(2 << 28)
+#define   AS_TRANSCFG_PTW_SH_IS				(3 << 28)
+#define   AS_TRANSCFG_PTW_RA				BIT(30)
+#define   AS_TRANSCFG_DISABLE_HIER_AP			BIT(33)
+#define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
+#define   AS_TRANSCFG_WXN				BIT(35)
+#define   AS_TRANSCFG_XREADABLE				BIT(36)
 #define AS_FAULTEXTRA_LO(as)		(MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)		(MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
@@ -326,6 +355,11 @@
 #define AS_TRANSTAB_LPAE_READ_INNER		BIT(2)
 #define AS_TRANSTAB_LPAE_SHARE_OUTER		BIT(4)
 
+/*
+ * Begin AARCH64_4K MMU TRANSTAB register values
+ */
+#define AS_TRANSTAB_AARCH64_4K_ADDR_MASK	0xfffffffffffffff0
+
 #define AS_STATUS_AS_ACTIVE			0x01
 
 #define AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
-- 
2.49.0



From ariel.dalessandro at collabora.com  Mon Mar 24 11:58:00 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:58:00 -0300
Subject: [PATCH v5 5/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8188
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-6-ariel.dalessandro@collabora.com>

MediaTek MT8188 SoC has an ARM Mali-G57 MC3 GPU (Valhall-JM), which
constantly faults with the current panfrost support.

For instance, running `glmark2-es2-drm` benchmark test:
```
[   79.617461] panfrost 13000000.gpu: js fault, js=1, status=JOB_BUS_FAULT, head=0xaadc380, tail=0xaadc380
[   80.119811] panfrost 13000000.gpu: gpu sched timeout, js=0, config=0x7300, status=0x58, head=0xaaca180, tail=0xaaca180, sched_job=000000002fd03ccc
[   80.129083] panfrost 13000000.gpu: Unhandled Page fault in AS0 at VA 0x0000000000000000
[   80.129083] Reason: TODO
[   80.129083] raw fault status: 0x1C2
[   80.129083] decoded fault status: SLAVE FAULT
[   80.129083] exception type 0xC2: TRANSLATION_FAULT_2
[   80.129083] access type 0x1: EXECUTE
[   80.129083] source id 0x0
```

Note that current panfrost mode (Mali LPAE - LEGACY) only allows to
specify write-cache or implementation-defined as the caching policy,
probably not matching the right configuration. As depicted in the source
code:

drivers/iommu/io-pgtable-arm.c:
```
* MEMATTR: Mali has no actual notion of a non-cacheable type, so the
* best we can do is mimic the out-of-tree driver and hope that the
* "implementation-defined caching policy" is good enough...
```

Now that Panfrost supports AARCH64_4K page table format, let's enable it
on Mediatek MT8188 and configure the cache/shareability policies
properly.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 7b7e9f6f6206..21e2f6c8d6be 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -824,6 +824,7 @@ static const struct panfrost_compatible mediatek_mt8188_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
 	.pm_domain_names = mediatek_mt8183_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
-- 
2.49.0



From ariel.dalessandro at collabora.com  Mon Mar 24 11:58:01 2025
From: ariel.dalessandro at collabora.com (Ariel D'Alessandro)
Date: Mon, 24 Mar 2025 15:58:01 -0300
Subject: [PATCH v5 6/6] drm/panfrost: Force AARCH64_4K page table format on MediaTek MT8192
In-Reply-To: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
References: <20250324185801.168664-1-ariel.dalessandro@collabora.com>
Message-ID: <20250324185801.168664-7-ariel.dalessandro@collabora.com>

MediaTek MT8192 SoC has an ARM Mali-G57 MC5 GPU (Valhall-JM). Now that
Panfrost supports AARCH64_4K page table format, let's enable it on this
SoC.

Running glmark2-es2-drm [0] benchmark, reported the same performance
score on both modes Mali LPAE (LEGACY) vs. AARCH64_4K, before and after
this commit. Tested on a Mediatek (MT8395) Genio 1200 EVK board.

[0] https://github.com/glmark2/glmark2

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro at collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/gpu/drm/panfrost/panfrost_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 21e2f6c8d6be..237e6054d0af 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -836,6 +836,7 @@ static const struct panfrost_compatible mediatek_mt8192_data = {
 	.num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains),
 	.pm_domain_names = mediatek_mt8192_pm_domains,
 	.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
+	.gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE),
 };
 
 static const struct of_device_id dt_match[] = {
-- 
2.49.0



From gregkh at linuxfoundation.org  Mon Mar 24 11:59:04 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:04 -0700
Subject: Patch "KVM: arm64: Calculate cptr_el2 traps on activating traps" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-1-417ca2278d18@kernel.org>
Message-ID: <2025032404-phrase-vending-4278@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Calculate cptr_el2 traps on activating traps

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125707-greg=kroah.com at vger.kernel.org Thu Mar 20 17:14:12 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:12:57 +0000
Subject: KVM: arm64: Calculate cptr_el2 traps on activating traps
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Fuad Tabba <tabba at google.com>,  James Clark <james.clark at linaro.org>
Message-ID: <20250321-stable-sve-6-12-v2-1-417ca2278d18 at kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    1 
 arch/arm64/kvm/arm.c              |    1 
 arch/arm64/kvm/hyp/nvhe/pkvm.c    |   29 ---------------------
 arch/arm64/kvm/hyp/nvhe/switch.c  |   51 +++++++++++++++++++++++---------------
 4 files changed, 32 insertions(+), 50 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -697,7 +697,6 @@ struct kvm_vcpu_arch {
 	u64 hcr_el2;
 	u64 hcrx_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1577,7 +1577,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -28,8 +28,6 @@ static void pvm_init_traps_aa64pfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -59,21 +57,10 @@ static void pvm_init_traps_aa64pfr0(stru
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_ELx_ZEN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -103,7 +90,6 @@ static void pvm_init_traps_aa64dfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -130,21 +116,12 @@ static void pvm_init_traps_aa64dfr0(stru
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	/* Trap External Trace */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
 		mdcr_clear |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
 
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -195,10 +172,6 @@ static void pvm_init_trap_regs(struct kv
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 /*
@@ -579,8 +552,6 @@ unlock:
 		return ret;
 	}
 
-	hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu);
-
 	return 0;
 }
 
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,33 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_ve
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu, vcpu->arch.hcr_el2);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~CPACR_ELx_SMEN;
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs()) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
+
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-	if (!guest_owns_fp_regs()) {
-		if (has_hvhe())
-			val &= ~(CPACR_ELx_FPEN | CPACR_ELx_ZEN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs())
+			val |= CPTR_EL2_TZ;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!guest_owns_fp_regs())
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu, vcpu->arch.hcr_el2);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:04 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:04 -0700
Subject: Patch "KVM: arm64: Eagerly switch ZCR_EL{1,2}" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-8-417ca2278d18@kernel.org>
Message-ID: <2025032404-sandfish-congenial-f5c3@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Eagerly switch ZCR_EL{1,2}

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-eagerly-switch-zcr_el-1-2.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 17:13:53 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:13:04 +0000
Subject: KVM: arm64: Eagerly switch ZCR_EL{1,2}
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-8-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/fpsimd.c                 |   30 ----------------
 arch/arm64/kvm/hyp/entry.S              |    5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h |   59 ++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    9 +---
 arch/arm64/kvm/hyp/nvhe/switch.c        |   33 +++++++++++++++--
 arch/arm64/kvm/hyp/vhe/switch.c         |    4 ++
 6 files changed, 100 insertions(+), 40 deletions(-)

--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -136,36 +136,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 	local_irq_save(flags);
 
 	if (guest_owns_fp_regs()) {
-		if (vcpu_has_sve(vcpu)) {
-			u64 zcr = read_sysreg_el1(SYS_ZCR);
-
-			/*
-			 * If the vCPU is in the hyp context then ZCR_EL1 is
-			 * loaded with its vEL2 counterpart.
-			 */
-			__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr;
-
-			/*
-			 * Restore the VL that was saved when bound to the CPU,
-			 * which is the maximum VL for the guest. Because the
-			 * layout of the data when saving the sve state depends
-			 * on the VL, we need to use a consistent (i.e., the
-			 * maximum) VL.
-			 * Note that this means that at guest exit ZCR_EL1 is
-			 * not necessarily the same as on guest entry.
-			 *
-			 * ZCR_EL2 holds the guest hypervisor's VL when running
-			 * a nested guest, which could be smaller than the
-			 * max for the vCPU. Similar to above, we first need to
-			 * switch to a VL consistent with the layout of the
-			 * vCPU's SVE state. KVM support for NV implies VHE, so
-			 * using the ZCR_EL1 alias is safe.
-			 */
-			if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)))
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
 		/*
 		 * Flush (save and invalidate) the fpsimd/sve state so that if
 		 * the host tries to use fpsimd/sve, it's not using stale data
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,6 +344,65 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		/* A guest hypervisor may restrict the effective max VL. */
+		if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))
+			zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
+		else
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu));
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs())
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
 {
 	/*
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -177,7 +178,9 @@ static void handle___kvm_vcpu_run(struct
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -486,12 +489,6 @@ void handle_trap(struct kvm_cpu_context
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		cpacr_clear_set(0, CPACR_ELx_ZEN);
-		isb();
-		sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1,
-				       SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs())
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct
 
 		if (!guest_owns_fp_regs())
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs())
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kv
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -462,6 +462,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * Note that ARM erratum 1165522 requires us to configure both stage 1
 	 * and stage 2 translation for the guest context before we clear
@@ -486,6 +488,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (guest_owns_fp_regs())


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:04 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:04 -0700
Subject: Patch "KVM: arm64: Mark some header functions as inline" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-7-417ca2278d18@kernel.org>
Message-ID: <2025032404-ounce-washbasin-886f@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Mark some header functions as inline

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-mark-some-header-functions-as-inline.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 17:13:50 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:13:03 +0000
Subject: KVM: arm64: Mark some header functions as inline
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-7-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -295,7 +295,7 @@ static inline bool __populate_fault_info
 	return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
 }
 
-static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
@@ -373,7 +373,7 @@ static void kvm_hyp_save_fpsimd_host(str
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -564,7 +564,7 @@ static bool handle_ampere1_tcr(struct kv
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -584,7 +584,7 @@ static bool kvm_hyp_handle_sysreg(struct
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -593,19 +593,18 @@ static bool kvm_hyp_handle_cp15_32(struc
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:05 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:05 -0700
Subject: Patch "KVM: arm64: Remove host FPSIMD saving for non-protected KVM" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-3-417ca2278d18@kernel.org>
Message-ID: <2025032405-pennant-purity-3d7b@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove host FPSIMD saving for non-protected KVM

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125709-greg=kroah.com at vger.kernel.org Thu Mar 20 17:15:04 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:12:59 +0000
Subject: KVM: arm64: Remove host FPSIMD saving for non-protected KVM
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-3-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h       |   18 ++++--------------
 arch/arm64/kvm/arm.c                    |    8 --------
 arch/arm64/kvm/fpsimd.c                 |    2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h |   25 +++++++++++++++++++++++--
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    2 +-
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ----------------------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    8 --------
 7 files changed, 28 insertions(+), 63 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -602,23 +602,13 @@ struct kvm_host_data {
 	struct kvm_cpu_context host_ctxt;
 
 	/*
-	 * All pointers in this union are hyp VA.
+	 * Hyp VA.
 	 * sve_state is only used in pKVM and if system_supports_sve().
 	 */
-	union {
-		struct user_fpsimd_state *fpsimd_state;
-		struct cpu_sve_state *sve_state;
-	};
+	struct cpu_sve_state *sve_state;
 
-	union {
-		/* HYP VA pointer to the host storage for FPMR */
-		u64	*fpmr_ptr;
-		/*
-		 * Used by pKVM only, as it needs to provide storage
-		 * for the host
-		 */
-		u64	fpmr;
-	};
+	/* Used by pKVM only. */
+	u64	fpmr;
 
 	/* Ownership of the FP regs */
 	enum {
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2476,14 +2476,6 @@ static void finalize_init_hyp_mode(void)
 			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
 				kern_hyp_va(sve_state);
 		}
-	} else {
-		for_each_possible_cpu(cpu) {
-			struct user_fpsimd_state *fpsimd_state;
-
-			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
-			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
-				kern_hyp_va(fpsimd_state);
-		}
 	}
 }
 
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -64,8 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
-	*host_data_ptr(fpsimd_state) = NULL;
-	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -344,7 +344,28 @@ static inline void __hyp_sve_save_host(v
 			 true);
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu);
+static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-protected kvm relies on the host restoring its sve state.
+	 * Protected kvm restores the host's sve state as not to reveal that
+	 * fpsimd was used by a guest nor leak upper sve bits.
+	 */
+	if (system_supports_sve()) {
+		__hyp_sve_save_host();
+
+		/* Re-enable SVE traps if not supported for the guest vcpu. */
+		if (!vcpu_has_sve(vcpu))
+			cpacr_clear_set(CPACR_ELx_ZEN, 0);
+
+	} else {
+		__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
+	}
+
+	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
+		*host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR);
+}
+
 
 /*
  * We trap the first access to the FP/SIMD to save the host context and
@@ -394,7 +415,7 @@ static bool kvm_hyp_handle_fpsimd(struct
 	isb();
 
 	/* Write out the host state if it's in the registers */
-	if (host_owns_fp_regs())
+	if (is_protected_kvm_enabled() && host_owns_fp_regs())
 		kvm_hyp_save_fpsimd_host(vcpu);
 
 	/* Restore the guest state */
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -83,7 +83,7 @@ static void fpsimd_sve_sync(struct kvm_v
 	if (system_supports_sve())
 		__hyp_sve_restore_host();
 	else
-		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
+		__fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs));
 
 	if (has_fpmr)
 		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -193,34 +193,6 @@ static bool kvm_handle_pvm_sys64(struct
 		kvm_handle_pvm_sysreg(vcpu, exit_code));
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	/*
-	 * Non-protected kvm relies on the host restoring its sve state.
-	 * Protected kvm restores the host's sve state as not to reveal that
-	 * fpsimd was used by a guest nor leak upper sve bits.
-	 */
-	if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) {
-		__hyp_sve_save_host();
-
-		/* Re-enable SVE traps if not supported for the guest vcpu. */
-		if (!vcpu_has_sve(vcpu))
-			cpacr_clear_set(CPACR_ELx_ZEN, 0);
-
-	} else {
-		__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-	}
-
-	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
-		u64 val = read_sysreg_s(SYS_FPMR);
-
-		if (unlikely(is_protected_kvm_enabled()))
-			*host_data_ptr(fpmr) = val;
-		else
-			**host_data_ptr(fpmr_ptr) = val;
-	}
-}
-
 static const exit_handler_fn hyp_exit_handlers[] = {
 	[0 ... ESR_ELx_EC_MAX]		= NULL,
 	[ESR_ELx_EC_CP15_32]		= kvm_hyp_handle_cp15_32,
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -309,14 +309,6 @@ static bool kvm_hyp_handle_eret(struct k
 	return true;
 }
 
-static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
-{
-	__fpsimd_save_state(*host_data_ptr(fpsimd_state));
-
-	if (kvm_has_fpmr(vcpu->kvm))
-		**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
-}
-
 static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	int ret = -EINVAL;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:05 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:05 -0700
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-5-417ca2278d18@kernel.org>
Message-ID: <2025032405-rumble-backroom-ccb8@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125711-greg=kroah.com at vger.kernel.org Thu Mar 20 17:15:08 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:13:01 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-5-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   21 ---------------------
 2 files changed, 23 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,12 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
-
 	/*
 	 * If normal guests gain SME support, maintain this behavior for pKVM
 	 * guests, which don't support SME.
@@ -141,21 +135,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (guest_owns_fp_regs()) {
 		if (vcpu_has_sve(vcpu)) {
 			u64 zcr = read_sysreg_el1(SYS_ZCR);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:05 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:05 -0700
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-4-417ca2278d18@kernel.org>
Message-ID: <2025032405-dizzy-promotion-0062@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 17:13:41 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:13:00 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-4-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   16 ----------------
 2 files changed, 18 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -891,8 +891,6 @@ struct kvm_vcpu_arch {
 /* Save TRBE context if active  */
 #define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	*host_data_ptr(fp_owner) = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -202,18 +198,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 		 * when needed.
 		 */
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:05 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:05 -0700
Subject: Patch "KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-2-417ca2278d18@kernel.org>
Message-ID: <2025032405-manor-hardhat-8f49@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125708-greg=kroah.com at vger.kernel.org Thu Mar 20 17:14:14 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:12:58 +0000
Subject: KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Eric Auger <eauger at redhat.com>, Wilco Dijkstra <wilco.dijkstra at arm.com>,  Eric Auger <eric.auger at redhat.com>, Florian Weimer <fweimer at redhat.com>,  Fuad Tabba <tabba at google.com>, Jeremy Linton <jeremy.linton at arm.com>,  Paolo Bonzini <pbonzini at redhat.com>
Message-ID: <20250321-stable-sve-6-12-v2-2-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kernel/fpsimd.c |   25 -------------------------
 arch/arm64/kvm/fpsimd.c    |   35 ++++++++++-------------------------
 2 files changed, 10 insertions(+), 50 deletions(-)

--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1695,31 +1695,6 @@ void fpsimd_signal_preserve_current_stat
 }
 
 /*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
-/*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
  * this function.
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -54,16 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
-	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
-	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
+	fpsimd_save_and_flush_cpu_state();
+	*host_data_ptr(fp_owner) = FP_STATE_FREE;
+	*host_data_ptr(fpsimd_state) = NULL;
+	*host_data_ptr(fpmr_ptr) = NULL;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			*host_data_ptr(fp_owner) = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 
 	/*


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Mon Mar 24 11:59:05 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Mon, 24 Mar 2025 11:59:05 -0700
Subject: Patch "KVM: arm64: Refactor exit handlers" has been added to the 6.12-stable tree
In-Reply-To: <20250321-stable-sve-6-12-v2-6-417ca2278d18@kernel.org>
Message-ID: <2025032405-familiar-unifier-5775@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Refactor exit handlers

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-refactor-exit-handlers.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 17:13:47 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:13:02 +0000
Subject: KVM: arm64: Refactor exit handlers
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  Joey Gouly <joey.gouly at arm.com>, Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-12-v2-6-417ca2278d18 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        |   28 ++++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    9 ++++-----
 3 files changed, 26 insertions(+), 41 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -635,23 +635,16 @@ static bool kvm_hyp_handle_dabt_low(stru
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -681,20 +674,9 @@ static inline void synchronize_vcpu_psta
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -724,7 +706,7 @@ static inline bool fixup_guest_exit(stru
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_ex
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
+
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_ha
 	[ESR_ELx_EC_MOPS]		= kvm_hyp_handle_mops,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.12/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.12/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.12/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.12/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.12/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.12/regulator-dummy-force-synchronous-probing.patch
queue-6.12/kvm-arm64-refactor-exit-handlers.patch
queue-6.12/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.12/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From Frank.li at nxp.com  Mon Mar 24 12:00:58 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 15:00:58 -0400
Subject: [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
In-Reply-To: <20250324062647.1891896-3-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-3-hongxing.zhu@nxp.com>
Message-ID: <Z+Gr6gXQWu+E+LQo@lizhi-Precision-Tower-5810>

On Mon, Mar 24, 2025 at 02:26:44PM +0800, Richard Zhu wrote:
> Beside the power-on reset, add the cold reset toggle for i.MX95 PCIe.

Add the code reset toggle for i.MX95 PCIe to align PHY's power on sequency.

>
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 31 +++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index aa5c3f235995..0f42ab63f5ad 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -71,6 +71,9 @@
>  #define IMX95_SID_MASK				GENMASK(5, 0)
>  #define IMX95_MAX_LUT				32
>
> +#define IMX95_PCIE_RST_CTRL			0x3010
> +#define IMX95_PCIE_COLD_RST			BIT(0)
> +
>  #define to_imx_pcie(x)	dev_get_drvdata((x)->dev)
>
>  enum imx_pcie_variants {
> @@ -773,6 +776,32 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
>  	return 0;
>  }
>
> +static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
> +{
> +	if (assert) {
> +		/*
> +		 * From i.MX95 PCIe PHY perspective, the COLD reset toggle
> +		 * should be complete after power-up by the following sequence.
> +		 *                 > 10us(at power-up)
> +		 *                 > 10ns(warm reset)
> +		 *               |<------------>|
> +		 *                ______________
> +		 * phy_reset ____/              \________________
> +		 *                                   ____________
> +		 * ref_clk_en_______________________/
> +		 * Toggle COLD reset aligned with this sequence for i.MX95 PCIe.
> +		 */
> +		regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
> +				   IMX95_PCIE_COLD_RST, IMX95_PCIE_COLD_RST);

regmap_set_bits()

> +		udelay(15);

udelay may not use MMIO. It cause delay time less than 15us. Need read one
register before udelay(15);

> +		regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
> +				   IMX95_PCIE_COLD_RST, 0);

regmap_clr_bits();

Frank

> +		udelay(10);
> +	}
> +
> +	return 0;
> +}
> +
>  static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
>  {
>  	reset_control_assert(imx_pcie->pciephy_reset);
> @@ -1762,6 +1791,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  		.ltssm_mask = IMX95_PCIE_LTSSM_EN,
>  		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
>  		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
> +		.core_reset = imx95_pcie_core_reset,
>  		.init_phy = imx95_pcie_init_phy,
>  	},
>  	[IMX8MQ_EP] = {
> @@ -1815,6 +1845,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
>  		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
>  		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
>  		.init_phy = imx95_pcie_init_phy,
> +		.core_reset = imx95_pcie_core_reset,
>  		.epc_features = &imx95_pcie_epc_features,
>  		.mode = DW_PCIE_EP_TYPE,
>  	},
> --
> 2.37.1
>


From yeoreum.yun at arm.com  Mon Mar 24 12:02:43 2025
From: yeoreum.yun at arm.com (Yeoreum Yun)
Date: Mon, 24 Mar 2025 19:02:43 +0000
Subject: [PATCH v3 1/1] coresight: prevent deactivate active config while
 enabling the config
In-Reply-To: <CAJ9a7VgsBZ6MkgwVjDiOm7rvcy9KVPfPc_PbaRNX7ra8NWGb9Q@mail.gmail.com>
References: <20250109171956.3535294-1-yeoreum.yun@arm.com>
 <CAJ9a7ViuVntYL62q=WYPkFR3++cyufPdKUHm0FUAPyGy76pB_A@mail.gmail.com>
 <GV1PR08MB10521BB7C93822F5124F2D66EFBD22@GV1PR08MB10521.eurprd08.prod.outlook.com>
 <CAJ9a7Vgz+L+UYf8Yqyu9J5hp3AB3WPSKutA4AvR-OFdu8b-dPA@mail.gmail.com>
 <Z+FlLDLV9WkGNbj+@e129823.arm.com>
 <CAJ9a7VgsBZ6MkgwVjDiOm7rvcy9KVPfPc_PbaRNX7ra8NWGb9Q@mail.gmail.com>
Message-ID: <Z+GsU2Elmq14UU81@e129823.arm.com>

Hi Mike,

> Hi,
>
> On Mon, 24 Mar 2025 at 13:59, Yeoreum Yun <yeoreum.yun at arm.com> wrote:
> >
> > Hi Mike,
> >
> > Please ignore my foremer mail.. and please see my comments for your
> > suggestion.
> >
> > > Hi
> > >
> > > On Fri, 14 Mar 2025 at 15:25, Yeo Reum Yun <YeoReum.Yun at arm.com> wrote:
> > > >
> > > > Hi, Mike.
> > > >
> > > > > >  static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
> > > > > > @@ -867,6 +870,28 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
> > > > > >
> > > > > > +static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc, bool enable)
> > > > > > +{
> > > > > > +       if (enable)
> > > > > > +               return atomic_inc_not_zero(&config_desc->active_cnt);
> > > > > > +
> > > > >
> > > > > Not sure why we have an "enable" parameter here - it completely
> > > > > changes the meaning of the function - with no comment at the start.
> > > >
> > > > Sorry. But what I intended is to distinguish
> > > >     - activation of config
> > > >     - enable of activated config.
> > > > Because, current coresight doesn't grab the module reference on enable of activate config,
> > > > But It grabs that reference only in activation.
> > > > That's why I used to "enable" parameter to distinguish this
> > > > while I integrate with module_owner count.
> > > >
> > > > > >         list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
> > > > > >                 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
> > > > > > -                       atomic_dec(&config_desc->active_cnt);
> > > > > >                         atomic_dec(&cscfg_mgr->sys_active_cnt);
> > > > > > -                       cscfg_owner_put(config_desc->load_owner);
> > > > > > +                       cscfg_config_desc_put(config_desc);
> > > > > >                         dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
> > > > > >                         break;
> > > > > >                 }
> > > > > > @@ -1047,7 +1066,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > > > >                                      unsigned long cfg_hash, int preset)
> > > > > >  {
> > > > > >         struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
> > > > > > -       const struct cscfg_config_desc *config_desc;
> > > > > > +       struct cscfg_config_desc *config_desc;
> > > > > >         unsigned long flags;
> > > > > >         int err = 0;
> > > > > >
> > > > > > @@ -1062,8 +1081,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > > > > >         raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> > > > > >         list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > > > > >                 config_desc = config_csdev_item->config_desc;
> > > > > > -               if ((atomic_read(&config_desc->active_cnt)) &&
> > > > > > -                   ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
> > > > > > +               if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
> > > > > > +                               cscfg_config_desc_get(config_desc, true)) {
> > > > > >
> > > > > This obfuscates the logic of the comparisons without good reason. With
> > > > > the true parameter, the function does no "get" operation but just
> > > > > replicates the logic being replaced - checking the active_cnt is
> > > > > non-zero.
> > > > >
> > > > > Restore this to the original logic to make it readable again
> > > >
> > > > It's not a replicates of comparsion logic, but if true,
> > >
> > > sorry - missed that point .
> > >
> > > > It get the reference of active_cnt but not get module reference.
> > > > The fundemental fault in the UAF becase of just "atomic_read()"
> > > > so, it should hold reference in here.
> > > >
> > > > So, If you think the cscfg_config_desc_get()'s parameter makes obfuscation,
> > > > I think there're two way to modfiy.
> > > >
> > > >     1. cscfg_config_desc_get()/put() always grab/drop the module count.
> > > >     2. remove cscfg_config_desc_get()/put() but just use atomic_XXX(&active_cnt) only
> > > >         with cscfg_owner_get()/put()
> > > >
> > > > Any thougt?
> > > >
> > > > Thanks!
> > > >
> > > >
> > >
> > > The get and put functions are asymmetrical w.r.t. owner.
> > >
> > > The put will put owner if active count decrements to 0,
> > > The get if not on enable path will put owner unconditionally.
> > >
> > > This means that the caller has to work out the correct input conditions.
> > >
> > > Might be better if:-
> > >
> > > get_desc()
> > > {
> > >     if (! desc->refcnt) {
> > >        if (!get_owner())
> > >            return false;
> > >    }
> > >    desc->refcnt++;
> > >     return true;
> > > }
> >
> > I think This makes another problem when
> > it races with _cscfg_deactivate_config().
> >
> > CPU0                                          CPU1
> > (sysfs enable)                                load module
> >                                               cscfg_load_config_sets()
> >                                               activate config. // sysfs
> >                                               (sys_active_cnt == 1)
> >
> >                                               // sysfs
> >                                               _cscfg_deactivate_config()
> >                                               (sys_active_cnt == 0)
> >                                               (config->active_cnt = 0)
> > ...
> > cscfg_csdev_enable_active_config()
> >   lock(csdev->cscfg_csdev_lock)
> >   // here get module reference??
> >   // even sys_active_cnt == 0 and
> >   // config->active_cnt == 1.
> >   get_desc()
> >   unlock(csdev->cscfg_csdev_lock)
> >
> >
> >   // access to config_desc which freed
> >   // while unloading module.
> >   cfs_csdev_enable_config
> >
> >
> > Because, the desc->refcnt meaning of zero is different from the context.
> >    - while activate . it should get module reference if zero.
> >    - while enable active configuration, if zero, it should be failed.
> >
> > that means to prevent this race, the core key point is:
> >    when config->active_cnt == 0, it should be failed in cscfg_csdev_enable_active_config()
> >
>
> This is not a failure case, it simple means that this config should
> not be activated for this device.
> It is possible for a configuration to be active on the system, without
> it being active for a particular coresight device.
>
> Having a get/put interface for the config descriptor - which prevents
> the config from being unloaded is fine, the key logic here is that we
> are searching a list of possible enabled configurations for this
> device and taking the necessary action to enable it if we find one -
> and there can only ever be a single configuration enabled for a trace
> session.
>
> Therefore when the list of loaded configs for a device is > 1, then
> all but one is allowed to be active - so the search code will validly
> find instances where config->active_cnt == 0.
>
> My objection to the original interface was not the get/put operations
> to protect the module from unload, but the fact that the logic
> deciding if a config needed to be enabled on the device was hidden
> inside the get() operation.
> My suggestion is to restore the logic that decides if there is a
> config to enable on the device be clear in the enable function itself,
> then use get/put as appropriate to prevent module unload.
>

Make sense. Then I'll respin with the suggestion :)
Thanks for clarification!



From marex at denx.de  Mon Mar 24 12:05:15 2025
From: marex at denx.de (Marek Vasut)
Date: Mon, 24 Mar 2025 20:05:15 +0100
Subject: [PATCH v2 4/9] drm/panthor: Implement optional reset
In-Reply-To: <20250324094333.7afb17a1@collabora.com>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-5-marex@denx.de>
 <20250324094333.7afb17a1@collabora.com>
Message-ID: <22187ae5-7486-416b-b612-53021bfca11e@denx.de>

On 3/24/25 9:43 AM, Boris Brezillon wrote:

[...]

>> @@ -563,6 +585,7 @@ int panthor_device_suspend(struct device *dev)
>>   
>>   	panthor_devfreq_suspend(ptdev);
>>   
>> +	reset_control_assert(ptdev->resets);
> 
> Hm, that might be the cause of the fast reset issue (which is a fast
> resume more than a fast reset BTW): if you re-assert the reset line on
> runtime suspend, I guess this causes a full GPU reset, and the MCU ends
> up in a state where it needs a slow reset (all data sections reset to
> their initial state). Can you try to move the reset_control_[de]assert
> to the unplug/init functions?
The reset on the MX95 is not really a reset, it is clear-only 
set-never-again bit which goes only one way, the "unreset" way, so I 
don't think this has any impact. Also, I commented this out already and 
it made no difference. I will give the second part of our suggestion a 
try in the next few days though, and also try the updated downstream 
firmware blobs (sigh).


From Frank.li at nxp.com  Mon Mar 24 12:14:06 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 15:14:06 -0400
Subject: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit
 L23 ready
In-Reply-To: <20250324062647.1891896-4-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-4-hongxing.zhu@nxp.com>
Message-ID: <Z+Gu/gmioiVJfDV0@lizhi-Precision-Tower-5810>

On Mon, Mar 24, 2025 at 02:26:45PM +0800, Richard Zhu wrote:
> Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23

provide a errata link here.

ERR051624: ...

The words after ERR051624 is descript errata itself, not workaround.

> Ready Through Beacon or PERST# De-assertion
>
> When the auxiliary power is not available, the controller cannot exit
> from L23 Ready with beacon or PERST# de-assertion when main power is not
> removed.
>
> Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
>
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 0f42ab63f5ad..52aa8bd66cde 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -48,6 +48,8 @@
>  #define IMX95_PCIE_SS_RW_REG_0			0xf0
>  #define IMX95_PCIE_REF_CLKEN			BIT(23)
>  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
> +#define IMX95_PCIE_SS_RW_REG_1			0xf4
> +#define IMX95_PCIE_SYS_AUX_PWR_DET		BIT(31)
>
>  #define IMX95_PE0_GEN_CTRL_1			0x1050
>  #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0)
> @@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
>
>  static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
>  {
> +	/*
> +	 * Workaround for ERR051624: The Controller Without Vaux Cannot
> +	 * Exit L23 Ready Through Beacon or PERST# De-assertion
> +	 *
> +	 * When the auxiliary power is not available, the controller
> +	 * cannot exit from L23 Ready with beacon or PERST# de-assertion
> +	 * when main power is not removed.
> +	 *
> +	 * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> +	 */
> +	regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
> +			IMX95_PCIE_SYS_AUX_PWR_DET, IMX95_PCIE_SYS_AUX_PWR_DET);

regmap_set_bits()

Frank
> +
>  	regmap_update_bits(imx_pcie->iomuxc_gpr,
>  			IMX95_PCIE_SS_RW_REG_0,
>  			IMX95_PCIE_PHY_CR_PARA_SEL,
> --
> 2.37.1
>


From Frank.li at nxp.com  Mon Mar 24 12:22:06 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 15:22:06 -0400
Subject: [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for
 i.MX95 PCIe
In-Reply-To: <20250324062647.1891896-6-hongxing.zhu@nxp.com>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-6-hongxing.zhu@nxp.com>
Message-ID: <Z+Gw3g0FfytALdRo@lizhi-Precision-Tower-5810>

On Mon, Mar 24, 2025 at 02:26:47PM +0800, Richard Zhu wrote:
> LUT(look up table) setting would be lost during PCIe suspend on i.MX95.
>
> To let i.MX95 PCIe PM work fine, save and restore the LUT setting in
> suspend and resume operations.
>
> Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 46 +++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index dda3eed99bb8..a3a032cbaa3c 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -135,6 +135,11 @@ struct imx_pcie_drvdata {
>  	const struct dw_pcie_host_ops *ops;
>  };
>
> +struct imx_lut_data {
> +	u32 data1;
> +	u32 data2;
> +};
> +
>  struct imx_pcie {
>  	struct dw_pcie		*pci;
>  	struct gpio_desc	*reset_gpiod;
> @@ -154,6 +159,8 @@ struct imx_pcie {
>  	struct regulator	*vph;
>  	void __iomem		*phy_base;
>
> +	/* LUT data for pcie */
> +	struct imx_lut_data	luts[IMX95_MAX_LUT];
>  	/* power domain for pcie */
>  	struct device		*pd_pcie;
>  	/* power domain for pcie phy */
> @@ -1468,6 +1475,41 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
>  	}
>  }
>
> +static void imx_pcie_lut_save_restore(struct imx_pcie *imx_pcie, bool save)
> +{
> +	int i;
> +	u32 data1, data2;

Reverse Christmas order.

> +
> +	for (i = 0; i < IMX95_MAX_LUT; i++) {
> +		if (save) {
> +			regmap_write(imx_pcie->iomuxc_gpr,
> +				     IMX95_PE0_LUT_ACSCTRL,
> +				     IMX95_PEO_LUT_RWA | i);
> +			regmap_read(imx_pcie->iomuxc_gpr,
> +				    IMX95_PE0_LUT_DATA1, &data1);
> +			regmap_read(imx_pcie->iomuxc_gpr,
> +				    IMX95_PE0_LUT_DATA2, &data2);
> +			if (data1 & IMX95_PE0_LUT_VLD) {
> +				imx_pcie->luts[i].data1 = data1;
> +				imx_pcie->luts[i].data2 = data2;
> +			} else {
> +				imx_pcie->luts[i].data1 = 0;
> +				imx_pcie->luts[i].data2 = 0;
> +			}

Almost no shared part between save and restore. Suggest use two helper
function imx_pcie_lut_save() and imx_pcie_lut_restore().

Frank

> +		} else {
> +			if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0)
> +				continue;
> +
> +			regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1,
> +				     imx_pcie->luts[i].data1);
> +			regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2,
> +				     imx_pcie->luts[i].data2);
> +			regmap_write(imx_pcie->iomuxc_gpr,
> +				     IMX95_PE0_LUT_ACSCTRL, i);
> +		}
> +	}
> +}
> +
>  static int imx_pcie_suspend_noirq(struct device *dev)
>  {
>  	struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
> @@ -1476,6 +1518,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)
>  		return 0;
>
>  	imx_pcie_msi_save_restore(imx_pcie, true);
> +	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> +		imx_pcie_lut_save_restore(imx_pcie, true);
>  	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
>  		/*
>  		 * The minimum for a workaround would be to set PERST# and to
> @@ -1520,6 +1564,8 @@ static int imx_pcie_resume_noirq(struct device *dev)
>  		if (ret)
>  			return ret;
>  	}
> +	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> +		imx_pcie_lut_save_restore(imx_pcie, false);
>  	imx_pcie_msi_save_restore(imx_pcie, false);
>
>  	return 0;
> --
> 2.37.1
>


From pasha.tatashin at soleen.com  Mon Mar 24 12:26:43 2025
From: pasha.tatashin at soleen.com (Pasha Tatashin)
Date: Mon, 24 Mar 2025 15:26:43 -0400
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com> <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
Message-ID: <CA+CK2bC4PM0JnHOUm7qfpQ=wUhwsYQ-hJ12tTK_7pSWgYk+bhg@mail.gmail.com>

On Mon, Mar 24, 2025 at 12:18?AM Dave Young <dyoung at redhat.com> wrote:
>
> On Thu, 20 Mar 2025 at 23:05, Changyuan Lyu <changyuanl at google.com> wrote:
> >
> > From: Alexander Graf <graf at amazon.com>
> >
> > We have all generic code in place now to support Kexec with KHO. This
> > patch adds a config option that depends on architecture support to
> > enable KHO support.
> >
> > Signed-off-by: Alexander Graf <graf at amazon.com>
> > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> > ---
> >  kernel/Kconfig.kexec | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> > index 4d111f871951..57db99e758a8 100644
> > --- a/kernel/Kconfig.kexec
> > +++ b/kernel/Kconfig.kexec
> > @@ -95,6 +95,21 @@ config KEXEC_JUMP
> >           Jump between original kernel and kexeced kernel and invoke
> >           code in physical address mode via KEXEC
> >
> > +config KEXEC_HANDOVER
> > +       bool "kexec handover"
> > +       depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
> > +       select MEMBLOCK_KHO_SCRATCH
> > +       select KEXEC_FILE
> > +       select DEBUG_FS
> > +       select LIBFDT
> > +       select CMA
> > +       select XXHASH
> > +       help
> > +         Allow kexec to hand over state across kernels by generating and
> > +         passing additional metadata to the target kernel. This is useful
> > +         to keep data or state alive across the kexec. For this to work,
> > +         both source and target kernels need to have this option enabled.
> > +
>
> Have you tested kdump?  In my mind there are two issues,  one is with
> CMA enabled, it could cause kdump crashkernel memory reservation
> failures more often due to the fragmented low memory.  Secondly,  in

As I understand cma low memory scratch reservation is needed only to
support some legacy pci devices that cannot use the full 64-bit space.
If so, I am not sure if KHO needs to be supported on machines with
such devices. However, even if we keep it, it should really be small,
so I would not expect that to be a problem for crash kernel memory
reservation.

> kdump kernel dump the crazy scratch memory in vmcore is not very
> meaningful.  Otherwise I suspect this is not tested under kdump.  If
> so please disable this option for kdump.

The scratch memory will appear as regular CMA in the vmcore. The crash
kernel can be kexec loaded only from userland, long after the scratch
memory is converted to CMA.

Pasha


From helgaas at kernel.org  Mon Mar 24 13:04:37 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 24 Mar 2025 15:04:37 -0500
Subject: [PATCH v12 06/13] PCI: dwc: Add dw_pcie_parent_bus_offset()
 checking and debug
In-Reply-To: <x2r2xfxrnkihvpoqiamgjmvppverjugp5r4we7lcfpz6jloxzy@7kdfzxiwv2po>
Message-ID: <20250324200437.GA1257874@bhelgaas>

On Mon, Mar 24, 2025 at 11:00:24PM +0530, Manivannan Sadhasivam wrote:
> On Sat, Mar 15, 2025 at 03:15:41PM -0500, Bjorn Helgaas wrote:
> > From: Frank Li <Frank.Li at nxp.com>
> > 
> > dw_pcie_parent_bus_offset() looks up the parent bus address of a PCI
> > controller 'reg' property in devicetree.  If implemented, .cpu_addr_fixup()
> > is a hard-coded way to get the parent bus address corresponding to a CPU
> > physical address.
> > 
> > Add debug code to compare the address from .cpu_addr_fixup() with the
> > address from devicetree.  If they match, warn that .cpu_addr_fixup() is
> > redundant and should be removed; if they differ, warn that something is
> > wrong with the devicetree.
> > 
> > If .cpu_addr_fixup() is not implemented, the parent bus address should be
> > identical to the CPU physical address because we previously ignored the
> > parent bus address from devicetree.  If the devicetree has a different
> > parent bus address, warn about it being broken.
> > 
> > [bhelgaas: split debug to separate patch for easier future revert, commit
> > log]
> > Link: https://lore.kernel.org/r/20250313-pci_fixup_addr-v11-5-01d2313502ab at nxp.com
> > Signed-off-by: Frank Li <Frank.Li at nxp.com>
> > Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> > ---
> >  drivers/pci/controller/dwc/pcie-designware.c | 26 +++++++++++++++++++-
> >  drivers/pci/controller/dwc/pcie-designware.h | 13 ++++++++++
> >  2 files changed, 38 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> > index 0a35e36da703..985264c88b92 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > @@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >  	struct device *dev = pci->dev;
> >  	struct device_node *np = dev->of_node;
> >  	int index;
> > -	u64 reg_addr;
> > +	u64 reg_addr, fixup_addr;
> > +	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
> >  
> >  	/* Look up reg_name address on parent bus */
> >  	index = of_property_match_string(np, "reg-names", reg_name);
> > @@ -1126,5 +1127,28 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
> >  
> >  	of_property_read_reg(np, index, &reg_addr, NULL);
> >  
> > +	fixup = pci->ops->cpu_addr_fixup;
> > +	if (fixup) {
> > +		fixup_addr = fixup(pci, cpu_phy_addr);
> > +		if (reg_addr == fixup_addr) {
> > +			dev_warn(dev, "%#010llx %s reg[%d] == %#010llx; %ps is redundant\n",
> > +				 cpu_phy_addr, reg_name, index,
> > +				 fixup_addr, fixup);
> > +		} else {
> > +			dev_warn(dev, "%#010llx %s reg[%d] != %#010llx fixed up addr; devicetree is broken\n",
> > +				 cpu_phy_addr, reg_name,
> > +				 index, fixup_addr);
> > +			reg_addr = fixup_addr;
> > +		}
> > +	} else if (!pci->use_parent_dt_ranges) {
> 
> Is this check still valid? 'use_parent_dt_ranges' is only used here for
> validation. Moreover, if the fixup is not available, we should be able to
> safely return 'cpu_phy_addr - reg_addr' unconditionally.

Yes, that's true IF the devicetree has the correct 'ranges'
translation.  This is to avoid breaking platforms with broken
devicetrees.

> > +		if (reg_addr != cpu_phy_addr) {
> > +			dev_warn(dev, "devicetree has incorrect translation; please check parent \"ranges\" property. CPU physical addr %#010llx, parent bus addr %#010llx\n",
> > +				 cpu_phy_addr, reg_addr);
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	dev_info(dev, "%s parent bus offset is %#010llx\n",
> > +		 reg_name, cpu_phy_addr - reg_addr);
> 
> This info is useless on platforms having no translation between CPU and PCI
> controller. The offset will always be 0.

You're right.  This was probably an overzealous message for any
possible issues.

What would you think of the below as a replacement?  It should emit at
most one message, and none for platforms where devicetree describes no
translation and there never was a .cpu_addr_fixup().

It's still pretty aggressive logging, but I'm just concerned about
being able to quickly debug and fix any regressions.  Ideally we can
revert the whole thing eventually.


diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 27b464a405a4..4b442d1aa55b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1114,7 +1114,8 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
 	int index;
-	u64 reg_addr;
+	u64 reg_addr, fixup_addr;
+	u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
 
 	/* Look up reg_name address on parent bus */
 	index = of_property_match_string(np, "reg-names", reg_name);
@@ -1126,5 +1127,42 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
 
 	of_property_read_reg(np, index, &reg_addr, NULL);
 
+	fixup = pci->ops ? pci->ops->cpu_addr_fixup : NULL;
+	if (fixup) {
+		fixup_addr = fixup(pci, cpu_phys_addr);
+		if (reg_addr == fixup_addr) {
+			dev_info(dev, "%s reg[%d] %#010llx == %#010llx == fixup(cpu %#010llx); %ps is redundant with this devicetree\n",
+				 reg_name, index, reg_addr, fixup_addr,
+				 (unsigned long long) cpu_phys_addr, fixup);
+		} else {
+			dev_warn(dev, "%s reg[%d] %#010llx != %#010llx == fixup(cpu %#010llx); devicetree is broken\n",
+				 reg_name, index, reg_addr, fixup_addr,
+				 (unsigned long long) cpu_phys_addr);
+			reg_addr = fixup_addr;
+		}
+
+		return cpu_phys_addr - reg_addr;
+	}
+
+	if (pci->use_parent_dt_ranges) {
+
+		/*
+		 * This platform once had a fixup, presumably because it
+		 * translates between CPU and PCI controller addresses.
+		 * Log a note if devicetree didn't describe a translation.
+		 */
+		if (reg_addr == cpu_phys_addr)
+			dev_info(dev, "%s reg[%d] %#010llx == cpu %#010llx\n; no fixup was ever needed for this devicetree\n",
+				 reg_name, index, reg_addr,
+				 (unsigned long long) cpu_phys_addr);
+	} else {
+		if (reg_addr != cpu_phys_addr) {
+			dev_warn(dev, "%s reg[%d] %#010llx != cpu %#010llx; no fixup and devicetree \"ranges\" is broken, assuming no translation\n",
+				 reg_name, index, reg_addr,
+				 (unsigned long long) cpu_phys_addr);
+			return 0;
+		}
+	}
+
 	return cpu_phys_addr - reg_addr;
 }
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 16548b01347d..f08d2852cfd5 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -465,6 +465,19 @@ struct dw_pcie {
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
 	bool			suspended;
+
+	/*
+	 * If iATU input addresses are offset from CPU physical addresses,
+	 * we previously required .cpu_addr_fixup() to convert them.  We
+	 * now rely on the devicetree instead.  If .cpu_addr_fixup()
+	 * exists, we compare its results with devicetree.
+	 *
+	 * If .cpu_addr_fixup() does not exist, we assume the offset is
+	 * zero and warn if devicetree claims otherwise.  If we know all
+	 * devicetrees correctly describe the offset, set
+	 * use_parent_dt_ranges to true to avoid this warning.
+	 */
+	bool			use_parent_dt_ranges;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)


From jgg at nvidia.com  Mon Mar 24 13:07:36 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 24 Mar 2025 17:07:36 -0300
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <Z-Gh-t9xB21UNGU2@kernel.org>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-10-changyuanl@google.com>
 <20250321134629.GA252045@nvidia.com>
 <Z98Lmo50h5RboFXq@kernel.org>
 <Z+BZOKSpyPA1Pyu+@nvidia.com>
 <Z-Gh-t9xB21UNGU2@kernel.org>
Message-ID: <Z+G7iHUdRZGv1Ose@nvidia.com>

On Mon, Mar 24, 2025 at 02:18:34PM -0400, Mike Rapoport wrote:
> On Sun, Mar 23, 2025 at 03:55:52PM -0300, Jason Gunthorpe wrote:
> > On Sat, Mar 22, 2025 at 03:12:26PM -0400, Mike Rapoport wrote:
> >  
> > > > > +		page->private = order;
> > > > 
> > > > Can't just set the page order directly? Why use private?
> > > 
> > > Setting the order means recreating the folio the way prep_compound_page()
> > > does. I think it's better to postpone it until the folio is requested. This
> > > way it might run after SMP is enabled. 
> > 
> > I see, that makes sense, but also it could stil use page->order..
> 
> But there's no page->order :)

I mean this:

static inline unsigned int folio_order(const struct folio *folio)
{
        if (!folio_test_large(folio))
                return 0;
        return folio->_flags_1 & 0xff;
}
 
> > Yes, but also we wouldn't have page->private to make it work.. Somehow
> > anything we want to carry over would have to become encoded in the
> > memdesc directly.
> 
> This is a problem to solve in 2026 :)

Yes :)

Jason


From robh at kernel.org  Mon Mar 24 13:12:00 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:12:00 -0500
Subject: [PATCH 1/2] dt-bindings: display: rockchip,inno-hdmi: Fix ref
 clk Document of RK3036 compatible
In-Reply-To: <20250324103332.159682-1-andyshrk@163.com>
References: <20250324103332.159682-1-andyshrk@163.com>
Message-ID: <174284712018.797576.18315585486040060273.robh@kernel.org>


On Mon, 24 Mar 2025 18:33:27 +0800, Andy Yan wrote:
> From: Andy Yan <andy.yan at rock-chips.com>
> 
> The RK3036 HDMI DDC bus requires it's PHY's reference clock to be enabled
> first before normal DDC communication can be carried out.
> 
> Therefore, both RK3036 and RK3128 HDMI require two identical clocks.
> 
> Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
> ---
> 
>  .../bindings/display/rockchip/rockchip,inno-hdmi.yaml | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From quic_molvera at quicinc.com  Mon Mar 24 13:18:31 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:31 -0700
Subject: [PATCH v3 03/10] dt-bindings: usb: qcom,dwc3: Add SM8750
 compatible
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-3-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

SM8750 uses the Synopsys DWC3 controller. Add this to the compatibles list
to utilize the DWC3 QCOM and DWC3 core framework.  Other than a revision
bump to DWC3 controller rev2.00a, the controller on SM8750 does not add any
additional vendor specific features compared to previous chipsets.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index 64137c1619a635a5a4f96fc49bd75c5fb757febb..a681208616f3a260086cff5a28dc23d35bd96f9a 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -55,6 +55,7 @@ properties:
           - qcom,sm8450-dwc3
           - qcom,sm8550-dwc3
           - qcom,sm8650-dwc3
+          - qcom,sm8750-dwc3
           - qcom,x1e80100-dwc3
           - qcom,x1e80100-dwc3-mp
       - const: qcom,dwc3
@@ -354,6 +355,7 @@ allOf:
               - qcom,sm8450-dwc3
               - qcom,sm8550-dwc3
               - qcom,sm8650-dwc3
+              - qcom,sm8750-dwc3
     then:
       properties:
         clocks:
@@ -497,6 +499,7 @@ allOf:
               - qcom,sm8450-dwc3
               - qcom,sm8550-dwc3
               - qcom,sm8650-dwc3
+              - qcom,sm8750-dwc3
     then:
       properties:
         interrupts:

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:28 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:28 -0700
Subject: [PATCH v3 00/10] phy: qcom: Introduce USB support for SM8750
Message-ID: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>

Add support for the PHYs and controllers used for USB on SM8750 SoCs.

---
Changes in v3:
- Split platform DTs into separate commits.
- Fixed up M31 eUSB2 PHY driver with feedback received.
- Reordered DT properties based on feedback.
- Rewrote commit message for enabling EUSB driver.
- Link to v2: https://lore.kernel.org/r/20250304-sm8750_usb_master-v2-0-a698a2e68e06 at quicinc.com

Changes in v2:
- Added new QMP PHY register definitions for v8 based QMP phys.
- Made changes to clean up some code in the M31 eUSB2 PHY driver based
on feedback received.
- Added bulk regulator operations in M31 eUSB2 PHY, to ensure that
both the vdd and vdda12 regulators are properly voted for.
- Removed external references to other dt bindings in M31 example for
the DT bindings change.
- Split DT patches between SoC and plaform changes, as well as the
PHY subsystem Kconfig changes when introducing the M31 eUSB2 PHY.
- Added orientation switch and port definitions in the DT changes.EDITME: describe what is new in this series revision.
- Link to v1: https://lore.kernel.org/r/20250113-sm8750_usb_master-v1-0-09afe1dc2524 at quicinc.com

---
Melody Olvera (1):
      arm64: defconfig: Add M31 eUSB2 PHY config for SM8750

Wesley Cheng (9):
      dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Add SM8750 to QMP PHY
      dt-bindings: phy: Add the M31 based eUSB2 PHY bindings
      dt-bindings: usb: qcom,dwc3: Add SM8750 compatible
      phy: qcom: qmp-combo: Add new PHY sequences for SM8750
      phy: qcom: Update description for QCOM based eUSB2 repeater
      phy: qcom: Add M31 based eUSB2 PHY driver
      arm64: dts: qcom: sm8750: Add USB support to SM8750 SoCs
      arm64: dts: qcom: sm8750: Add USB support for SM8750 MTP platform
      arm64: dts: qcom: sm8750: Add USB support for SM8750 QRD platform

 .../bindings/phy/qcom,m31-eusb2-phy.yaml           |  79 ++++++
 .../phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml         |   2 +
 .../devicetree/bindings/usb/qcom,dwc3.yaml         |   3 +
 arch/arm64/boot/dts/qcom/sm8750-mtp.dts            |  24 ++
 arch/arm64/boot/dts/qcom/sm8750-qrd.dts            |  24 ++
 arch/arm64/boot/dts/qcom/sm8750.dtsi               | 166 ++++++++++++
 arch/arm64/configs/defconfig                       |   1 +
 drivers/phy/qualcomm/Kconfig                       |  16 +-
 drivers/phy/qualcomm/Makefile                      |   1 +
 drivers/phy/qualcomm/phy-qcom-m31-eusb2.c          | 297 +++++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c          | 221 +++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h     |  38 +++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h         |  32 +++
 drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h |  64 +++++
 .../phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h    |  68 +++++
 drivers/phy/qualcomm/phy-qcom-qmp.h                |   5 +
 16 files changed, 1038 insertions(+), 3 deletions(-)
---
base-commit: 882a18c2c14fc79adb30fe57a9758283aa20efaa
change-id: 20241223-sm8750_usb_master-f27aed7f6d40

Best regards,
-- 
Melody Olvera <quic_molvera at quicinc.com>



From quic_molvera at quicinc.com  Mon Mar 24 13:18:30 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:30 -0700
Subject: [PATCH v3 02/10] dt-bindings: phy: Add the M31 based eUSB2 PHY
 bindings
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-2-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

On SM8750, the M31 eUSB2 PHY is being used to support USB2. Add the
binding definition for the PHY driver.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 .../bindings/phy/qcom,m31-eusb2-phy.yaml           | 79 ++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c84c62d0e8cbd9fc1c0da6538f49149e5bc7e066
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom,m31-eusb2-phy.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/qcom,m31-eusb2-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm M31 eUSB2 phy
+
+maintainers:
+  - Wesley Cheng <quic_wcheng at quicinc.com>
+
+description:
+  M31 based eUSB2 controller, which supports LS/FS/HS usb connectivity
+  on Qualcomm chipsets.  It is paired with a eUSB2 repeater.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - qcom,sm8750-m31-eusb2-phy
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 0
+
+  clocks:
+    items:
+      - description: reference clock
+
+  clock-names:
+    items:
+      - const: ref
+
+  resets:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+    description:
+      Phandle to eUSB2 repeater
+
+  vdd-supply:
+    description:
+      Phandle to 0.88V regulator supply to PHY digital circuit.
+
+  vdda12-supply:
+    description:
+      Phandle to 1.2V regulator supply to PHY refclk pll block.
+
+required:
+  - compatible
+  - reg
+  - "#phy-cells"
+  - clocks
+  - clock-names
+  - resets
+  - vdd-supply
+  - vdda12-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    usb_1_hsphy: phy at 88e3000 {
+        compatible = "qcom,sm8750-m31-eusb2-phy";
+        reg = <0x88e3000 0x29c>;
+
+        clocks = <&tcsrcc_usb2_clkref_en>;
+        clock-names = "ref";
+
+        resets = <&gcc_qusb2phy_prim_bcr>;
+
+        #phy-cells = <0>;
+
+        vdd-supply = <&vreg_l2d_0p88>;
+        vdda12-supply = <&vreg_l3g_1p2>;
+    };

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:33 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:33 -0700
Subject: [PATCH v3 05/10] phy: qcom: Update description for QCOM based
 eUSB2 repeater
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-5-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

The eUSB2 repeater that exists in the QCOM PMICs are utilized for several
different eUSB2 PHY vendors, such as M31 or Synopsys.  Hence, the wording
needs to be updated to remove associations to a specific vendor.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
---
 drivers/phy/qualcomm/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index c1e0a11ddd76c2056eb2e72a287ece4def2cf5d8..3cfb4c9d3d10dce49bb93b241f9b56c75b934601 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -135,12 +135,12 @@ config PHY_QCOM_SNPS_EUSB2
 	  on Qualcomm SOCs.
 
 config PHY_QCOM_EUSB2_REPEATER
-	tristate "Qualcomm SNPS eUSB2 Repeater Driver"
+	tristate "Qualcomm PMIC eUSB2 Repeater Driver"
 	depends on OF && (ARCH_QCOM || COMPILE_TEST)
 	select GENERIC_PHY
 	help
-	  Enable support for the USB high-speed SNPS eUSB2 repeater on Qualcomm
-	  PMICs. The repeater is paired with a Synopsys eUSB2 Phy
+	  Enable support for the USB high-speed eUSB2 repeater on Qualcomm
+	  PMICs. The repeater can be paired with a Synopsys or M31 eUSB2 Phy
 	  on Qualcomm SOCs.
 
 config PHY_QCOM_M31_USB

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:34 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:34 -0700
Subject: [PATCH v3 06/10] phy: qcom: Add M31 based eUSB2 PHY driver
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-6-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

SM8750 utilizes an eUSB2 PHY from M31.  Add the initialization
sequences to bring it out of reset and into an operational state.  This
differs to the M31 USB driver, in that the M31 eUSB2 driver will
require a connection to an eUSB2 repeater.  This PHY driver will handle
the initialization of the associated eUSB2 repeater when required.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 drivers/phy/qualcomm/Kconfig              |  10 +
 drivers/phy/qualcomm/Makefile             |   1 +
 drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 297 ++++++++++++++++++++++++++++++
 3 files changed, 308 insertions(+)

diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 3cfb4c9d3d10dce49bb93b241f9b56c75b934601..5d55ed0bd198d786d31d5dbee8f32e6fbed875a9 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -167,6 +167,16 @@ config PHY_QCOM_UNIPHY_PCIE_28LP
 	  handles PHY initialization, clock management required after
 	  resetting the hardware and power management.
 
+config PHY_QCOM_M31_EUSB
+	tristate "Qualcomm M31 eUSB2 PHY driver support"
+	depends on USB && (ARCH_QCOM || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable this to support M31 EUSB2 PHY transceivers on Qualcomm
+	  chips with DWC3 USB core. It supports initializing and cleaning
+	  up of the associated USB repeater that is paired with the eUSB2
+	  PHY.
+
 config PHY_QCOM_USB_HS
 	tristate "Qualcomm USB HS PHY module"
 	depends on USB_ULPI_BUS
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index 42038bc30974a376bb2e3749d57d0518a82c35fe..4a5907816c65ec15b85e1fa5d22003ee8e2a3e97 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_PHY_QCOM_EDP)		+= phy-qcom-edp.o
 obj-$(CONFIG_PHY_QCOM_IPQ4019_USB)	+= phy-qcom-ipq4019-usb.o
 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
 obj-$(CONFIG_PHY_QCOM_M31_USB)		+= phy-qcom-m31.o
+obj-$(CONFIG_PHY_QCOM_M31_EUSB)		+= phy-qcom-m31-eusb2.o
 obj-$(CONFIG_PHY_QCOM_PCIE2)		+= phy-qcom-pcie2.o
 
 obj-$(CONFIG_PHY_QCOM_QMP_COMBO)	+= phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
diff --git a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c
new file mode 100644
index 0000000000000000000000000000000000000000..b18aab968122683e2e87287a4b570321d376870a
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <linux/regulator/consumer.h>
+
+#define USB_PHY_UTMI_CTRL0		(0x3c)
+
+#define USB_PHY_UTMI_CTRL5		(0x50)
+
+#define USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
+#define FSEL				GENMASK(6, 4)
+#define FSEL_38_4_MHZ_VAL		(0x6)
+
+#define USB_PHY_HS_PHY_CTRL2		(0x64)
+
+#define USB_PHY_CFG0			(0x94)
+#define USB_PHY_CFG1			(0x154)
+
+#define USB_PHY_FSEL_SEL		(0xb8)
+
+#define USB_PHY_XCFGI_39_32		(0x16c)
+#define USB_PHY_XCFGI_71_64		(0x17c)
+#define USB_PHY_XCFGI_31_24		(0x168)
+#define USB_PHY_XCFGI_7_0		(0x15c)
+
+#define M31_EUSB_PHY_INIT_CFG(o, b, v)	\
+{				\
+	.off = o,		\
+	.mask = b,		\
+	.val = v,		\
+}
+
+struct m31_phy_tbl_entry {
+	u32 off;
+	u32 mask;
+	u32 val;
+};
+
+struct m31_eusb2_priv_data {
+	const struct m31_phy_tbl_entry	*setup_seq;
+	unsigned int			setup_seq_nregs;
+	const struct m31_phy_tbl_entry	*override_seq;
+	unsigned int			override_seq_nregs;
+	const struct m31_phy_tbl_entry	*reset_seq;
+	unsigned int			reset_seq_nregs;
+	unsigned int			fsel;
+};
+
+static const struct m31_phy_tbl_entry m31_eusb2_setup_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG1, BIT(0), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_FSEL_SEL, BIT(0), 1),
+};
+
+static const struct m31_phy_tbl_entry m31_eusb_phy_override_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_39_32, GENMASK(3, 2), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_71_64, GENMASK(3, 0), 7),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_31_24, GENMASK(2, 0), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_XCFGI_7_0, GENMASK(1, 0), 0),
+};
+
+static const struct m31_phy_tbl_entry m31_eusb_phy_reset_tbl[] = {
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(3), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(2), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL0, BIT(0), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, BIT(1), 1),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, BIT(2), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, BIT(1), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL2, BIT(3), 0),
+	M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, BIT(1), 0),
+};
+
+static const struct regulator_bulk_data m31_eusb_phy_vregs[] = {
+	{ .supply = "vdd" },
+	{ .supply = "vdda12" },
+};
+
+#define M31_EUSB_NUM_VREGS		ARRAY_SIZE(m31_eusb_phy_vregs)
+
+struct m31eusb2_phy {
+	struct phy			 *phy;
+	void __iomem			 *base;
+	const struct m31_eusb2_priv_data *data;
+
+	struct regulator_bulk_data	 *vregs;
+	struct clk			 *clk;
+	struct reset_control		 *reset;
+
+	struct phy			 *repeater;
+};
+
+static int m31eusb2_phy_write_readback(void __iomem *base, u32 offset,
+					const u32 mask, u32 val)
+{
+	u32 write_val;
+	u32 tmp;
+
+	tmp = readl_relaxed(base + offset);
+	tmp &= ~mask;
+	write_val = tmp | val;
+
+	writel_relaxed(write_val, base + offset);
+
+	tmp = readl_relaxed(base + offset);
+	tmp &= mask;
+
+	if (tmp != val) {
+		pr_err("write: %x to offset: %x FAILED\n", val, offset);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int m31eusb2_phy_write_sequence(struct m31eusb2_phy *phy,
+				       const struct m31_phy_tbl_entry *tbl,
+				       int num)
+{
+	int i;
+	int ret;
+
+	for (i = 0 ; i < num; i++, tbl++) {
+		dev_dbg(&phy->phy->dev, "Offset:%x BitMask:%x Value:%x",
+			tbl->off, tbl->mask, tbl->val);
+
+		ret = m31eusb2_phy_write_readback(phy->base,
+						   tbl->off, tbl->mask,
+						   tbl->val << __ffs(tbl->mask));
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int m31eusb2_phy_init(struct phy *uphy)
+{
+	struct m31eusb2_phy *phy = phy_get_drvdata(uphy);
+	const struct m31_eusb2_priv_data *data = phy->data;
+	int ret;
+
+	ret = regulator_bulk_enable(M31_EUSB_NUM_VREGS, phy->vregs);
+	if (ret) {
+		dev_err(&uphy->dev, "failed to enable regulator, %d\n", ret);
+		return ret;
+	}
+
+	ret = phy_init(phy->repeater);
+	if (ret) {
+		dev_err(&uphy->dev, "repeater init failed. %d\n", ret);
+		goto disable_vreg;
+	}
+
+	ret = clk_prepare_enable(phy->clk);
+	if (ret) {
+		dev_err(&uphy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+		goto disable_repeater;
+	}
+
+	/* Perform phy reset */
+	reset_control_assert(phy->reset);
+	udelay(5);
+	reset_control_deassert(phy->reset);
+
+	m31eusb2_phy_write_sequence(phy, data->setup_seq, data->setup_seq_nregs);
+	m31eusb2_phy_write_readback(phy->base,
+				     USB_PHY_HS_PHY_CTRL_COMMON0, FSEL,
+				     FIELD_PREP(FSEL, data->fsel));
+	m31eusb2_phy_write_sequence(phy, data->override_seq, data->override_seq_nregs);
+	m31eusb2_phy_write_sequence(phy, data->reset_seq, data->reset_seq_nregs);
+
+	return 0;
+
+disable_repeater:
+	phy_exit(phy->repeater);
+disable_vreg:
+	regulator_bulk_disable(M31_EUSB_NUM_VREGS, phy->vregs);
+
+	return 0;
+}
+
+static int m31eusb2_phy_exit(struct phy *uphy)
+{
+	struct m31eusb2_phy *phy = phy_get_drvdata(uphy);
+
+	clk_disable_unprepare(phy->clk);
+	regulator_bulk_disable(M31_EUSB_NUM_VREGS, phy->vregs);
+	phy_exit(phy->repeater);
+
+	return 0;
+}
+
+static const struct phy_ops m31eusb2_phy_gen_ops = {
+	.init	= m31eusb2_phy_init,
+	.exit	= m31eusb2_phy_exit,
+	.owner	= THIS_MODULE,
+};
+
+static int m31eusb2_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	const struct m31_eusb2_priv_data *data;
+	struct device *dev = &pdev->dev;
+	struct m31eusb2_phy *phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	data = of_device_get_match_data(dev);
+	if (IS_ERR(data))
+		return -EINVAL;
+	phy->data = data;
+
+	phy->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(phy->base))
+		return PTR_ERR(phy->base);
+
+	phy->reset = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(phy->reset))
+		return PTR_ERR(phy->reset);
+
+	phy->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(phy->clk))
+		return dev_err_probe(dev, PTR_ERR(phy->clk),
+				     "failed to get clk\n");
+
+	phy->phy = devm_phy_create(dev, NULL, &m31eusb2_phy_gen_ops);
+	if (IS_ERR(phy->phy))
+		return dev_err_probe(dev, PTR_ERR(phy->phy),
+				     "failed to create phy\n");
+
+	ret = devm_regulator_bulk_get_const(dev, M31_EUSB_NUM_VREGS,
+					    m31_eusb_phy_vregs, &phy->vregs);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				"failed to get regulator supplies\n");
+
+	phy_set_drvdata(phy->phy, phy);
+
+	phy->repeater = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+	if (IS_ERR(phy->repeater))
+		return dev_err_probe(dev, PTR_ERR(phy->repeater),
+				     "failed to get repeater\n");
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (!IS_ERR(phy_provider))
+		dev_info(dev, "Registered M31 USB phy\n");
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct m31_eusb2_priv_data m31_eusb_v1_data = {
+	.setup_seq = m31_eusb2_setup_tbl,
+	.setup_seq_nregs = ARRAY_SIZE(m31_eusb2_setup_tbl),
+	.override_seq = m31_eusb_phy_override_tbl,
+	.override_seq_nregs = ARRAY_SIZE(m31_eusb_phy_override_tbl),
+	.reset_seq = m31_eusb_phy_reset_tbl,
+	.reset_seq_nregs = ARRAY_SIZE(m31_eusb_phy_reset_tbl),
+	.fsel = FSEL_38_4_MHZ_VAL,
+};
+
+static const struct of_device_id m31eusb2_phy_id_table[] = {
+	{ .compatible = "qcom,sm8750-m31-eusb2-phy", .data = &m31_eusb_v1_data },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, m31eusb2_phy_id_table);
+
+static struct platform_driver m31eusb2_phy_driver = {
+	.probe = m31eusb2_phy_probe,
+	.driver = {
+		.name = "qcom-m31eusb2-phy",
+		.of_match_table = m31eusb2_phy_id_table,
+	},
+};
+
+module_platform_driver(m31eusb2_phy_driver);
+
+MODULE_AUTHOR("Wesley Cheng <quic_wcheng at quicinc.com>");
+MODULE_DESCRIPTION("eUSB2 Qualcomm M31 HSPHY driver");
+MODULE_LICENSE("GPL");

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:32 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:32 -0700
Subject: [PATCH v3 04/10] phy: qcom: qmp-combo: Add new PHY sequences for
 SM8750
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-4-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add new register offsets and PHY values for SM8750. Some of the previous
definitions can be leveraged from older PHY versions as offsets within
registers have not changed. This also updates the PHY sequence that is
recommended after running hardware characterization.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c          | 221 +++++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h     |  38 ++++
 drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h         |  32 +++
 drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h |  64 ++++++
 .../phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h    |  68 +++++++
 drivers/phy/qualcomm/phy-qcom-qmp.h                |   5 +
 6 files changed, 428 insertions(+)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index b09fa00e9fe7db8d97b7179ee15d3f07fe578b0c..8b9710a9654ab1acf8419e7f87188cbc98f8714a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -32,6 +32,7 @@
 #include "phy-qcom-qmp-pcs-usb-v4.h"
 #include "phy-qcom-qmp-pcs-usb-v5.h"
 #include "phy-qcom-qmp-pcs-usb-v6.h"
+#include "phy-qcom-qmp-pcs-usb-v8.h"
 
 #include "phy-qcom-qmp-dp-com-v3.h"
 
@@ -212,6 +213,28 @@ static const unsigned int qmp_v6_n4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
 	[QPHY_TX_TRANSCEIVER_BIAS_EN]	= QSERDES_V6_N4_TX_TRANSCEIVER_BIAS_EN,
 };
 
+static const unsigned int qmp_v8_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+	[QPHY_SW_RESET]			= QPHY_V8_PCS_SW_RESET,
+	[QPHY_START_CTRL]		= QPHY_V8_PCS_START_CONTROL,
+	[QPHY_PCS_STATUS]		= QPHY_V8_PCS_PCS_STATUS1,
+	[QPHY_PCS_POWER_DOWN_CONTROL]	= QPHY_V8_PCS_POWER_DOWN_CONTROL,
+
+	/* In PCS_USB */
+	[QPHY_PCS_AUTONOMOUS_MODE_CTRL]	= QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL,
+	[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_CLEAR,
+
+	[QPHY_COM_RESETSM_CNTRL]	= QSERDES_V8_COM_RESETSM_CNTRL,
+	[QPHY_COM_C_READY_STATUS]	= QSERDES_V8_COM_C_READY_STATUS,
+	[QPHY_COM_CMN_STATUS]		= QSERDES_V8_COM_CMN_STATUS,
+	[QPHY_COM_BIAS_EN_CLKBUFLR_EN]	= QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN,
+
+	[QPHY_TX_TX_POL_INV]		= QSERDES_V8_TX_TX_POL_INV,
+	[QPHY_TX_TX_DRV_LVL]		= QSERDES_V8_TX_TX_DRV_LVL,
+	[QPHY_TX_TX_EMP_POST1_LVL]	= QSERDES_V8_TX_TX_EMP_POST1_LVL,
+	[QPHY_TX_HIGHZ_DRVR_EN]		= QSERDES_V8_TX_HIGHZ_DRVR_EN,
+	[QPHY_TX_TRANSCEIVER_BIAS_EN]	= QSERDES_V8_TX_TRANSCEIVER_BIAS_EN,
+};
+
 static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
 	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
@@ -1471,6 +1494,139 @@ static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_EQ_CONFIG5, 0x10),
 };
 
+static const struct qmp_phy_init_tbl sm8750_usb3_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1, 0xc0),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORECLK_DIV_MODE1, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE1, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE1, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE1, 0x55),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE1, 0x75),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_SEL_1, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE1, 0x25),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x5c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x5c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0, 0xc0),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE0, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE0, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE0, 0x1a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE0, 0x41),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE0, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE0, 0x55),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE0, 0x75),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE0, 0x25),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE0, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_BG_TIMER, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_EN_CENTER, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER1, 0x62),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER2, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_BUF_ENABLE, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_EN_SEL, 0x1a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_CFG, 0x14),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_MAP, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORE_CLK_EN, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_CONFIG_1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1, 0xb6),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2, 0x4a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V8_COM_ADDITIONAL_MISC, 0x0c),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_TX, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_RX, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_TX, 0x1f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_1, 0xf5),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_3, 0x11),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_4, 0x31),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_5, 0x5f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_TX_RCV_DETECT_LVL_2, 0x12),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V8_TX_PI_QEC_CTRL, 0x21, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V8_TX_PI_QEC_CTRL, 0x05, 2),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FO_GAIN, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_GAIN, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_PI_CONTROLS, 0x99),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH1, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH2, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN2, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_AUX_DATA_TCOARSE_TFINE, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL1, 0x54),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL2, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_GM_CAL, 0x13),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_LOW, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
+
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_ENABLES, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CNTRL, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_LOW, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH, 0xbf),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH2, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH3, 0xdf),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH4, 0xed),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_LOW, 0x19),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH, 0x09),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH2, 0x91),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH3, 0xb7),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH4, 0xaa),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_EN_TIMER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_DCC_CTRL1, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_VTH_CODE, 0x10),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_CTRL1, 0x14),
+	QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_TRIM, 0x08),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG1, 0xc4),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG2, 0x89),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG3, 0x20),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG6, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_REFGEN_REQ_CONFIG1, 0x21),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RX_SIGDET_LVL, 0x55),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_CDR_RESET_TIME, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG1, 0x88),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG2, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_PCS_TX_RX_CONFIG, 0x0c),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG1, 0x4b),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG5, 0x10),
+};
+
+static const struct qmp_phy_init_tbl sm8750_usb3_pcs_usb_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2, 0x07),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_L, 0x40),
+	QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_H, 0x00),
+};
+
 static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_usb_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
@@ -1781,6 +1937,22 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v5 = {
 	.dp_dp_phy	= 0x2200,
 };
 
+static const struct qmp_combo_offsets qmp_combo_offsets_v8 = {
+	.com		= 0x0000,
+	.txa		= 0x1400,
+	.rxa		= 0x1600,
+	.txb		= 0x1800,
+	.rxb		= 0x1a00,
+	.usb3_serdes	= 0x1000,
+	.usb3_pcs_misc	= 0x1c00,
+	.usb3_pcs	= 0x1e00,
+	.usb3_pcs_usb	= 0x2100,
+	.dp_serdes	= 0x3000,
+	.dp_txa		= 0x3400,
+	.dp_txb		= 0x3800,
+	.dp_dp_phy	= 0x3c00,
+};
+
 static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
 	.offsets		= &qmp_combo_offsets_v3,
 
@@ -2280,6 +2452,51 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
 	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 };
 
+static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
+	.offsets		= &qmp_combo_offsets_v8,
+
+	.serdes_tbl		= sm8750_usb3_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sm8750_usb3_serdes_tbl),
+	.tx_tbl			= sm8750_usb3_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sm8750_usb3_tx_tbl),
+	.rx_tbl			= sm8750_usb3_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sm8750_usb3_rx_tbl),
+	.pcs_tbl		= sm8750_usb3_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sm8750_usb3_pcs_tbl),
+	.pcs_usb_tbl		= sm8750_usb3_pcs_usb_tbl,
+	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8750_usb3_pcs_usb_tbl),
+
+	.dp_serdes_tbl		= qmp_v6_dp_serdes_tbl,
+	.dp_serdes_tbl_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
+	.dp_tx_tbl		= qmp_v6_dp_tx_tbl,
+	.dp_tx_tbl_num		= ARRAY_SIZE(qmp_v6_dp_tx_tbl),
+
+	.serdes_tbl_rbr		= qmp_v6_dp_serdes_tbl_rbr,
+	.serdes_tbl_rbr_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
+	.serdes_tbl_hbr		= qmp_v6_dp_serdes_tbl_hbr,
+	.serdes_tbl_hbr_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
+	.serdes_tbl_hbr2	= qmp_v6_dp_serdes_tbl_hbr2,
+	.serdes_tbl_hbr2_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
+	.serdes_tbl_hbr3	= qmp_v6_dp_serdes_tbl_hbr3,
+	.serdes_tbl_hbr3_num	= ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
+
+	.swing_hbr_rbr		= &qmp_dp_v6_voltage_swing_hbr_rbr,
+	.pre_emphasis_hbr_rbr	= &qmp_dp_v6_pre_emphasis_hbr_rbr,
+	.swing_hbr3_hbr2	= &qmp_dp_v5_voltage_swing_hbr3_hbr2,
+	.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
+
+	.dp_aux_init		= qmp_v4_dp_aux_init,
+	.configure_dp_tx	= qmp_v4_configure_dp_tx,
+	.configure_dp_phy	= qmp_v4_configure_dp_phy,
+	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
+
+	.regs			= qmp_v8_usb3phy_regs_layout,
+	.reset_list		= msm8996_usb3phy_reset_l,
+	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+};
+
 static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
 {
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -3915,6 +4132,10 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
 		.compatible = "qcom,sm8650-qmp-usb3-dp-phy",
 		.data = &sm8650_usb3dpphy_cfg,
 	},
+	{
+		.compatible = "qcom,sm8750-qmp-usb3-dp-phy",
+		.data = &sm8750_usb3dpphy_cfg,
+	},
 	{
 		.compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
 		.data = &x1e80100_usb3dpphy_cfg,
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..89ace8024bc0bde55b5a590f67d906b893c197a1
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v8.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_USB_V8_H_
+#define QCOM_PHY_QMP_PCS_USB_V8_H_
+
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG1		0x00
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_STATUS		0x04
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL		0x08
+#define QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL2		0x0c
+#define QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x10
+#define QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_CLEAR		0x14
+#define QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL		0x18
+#define QPHY_V8_PCS_USB_LFPS_TX_ECSTART			0x1c
+#define QPHY_V8_PCS_USB_LFPS_PER_TIMER_VAL		0x20
+#define QPHY_V8_PCS_USB_LFPS_TX_END_CNT_U3_START	0x24
+#define QPHY_V8_PCS_USB_LFPS_CONFIG1			0x28
+#define QPHY_V8_PCS_USB_RXEQTRAINING_LOCK_TIME		0x2c
+#define QPHY_V8_PCS_USB_RXEQTRAINING_WAIT_TIME		0x30
+#define QPHY_V8_PCS_USB_RXEQTRAINING_CTLE_TIME		0x34
+#define QPHY_V8_PCS_USB_RXEQTRAINING_WAIT_TIME_S2	0x38
+#define QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2	0x3c
+#define QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_L		0x40
+#define QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_H		0x44
+#define QPHY_V8_PCS_USB_ARCVR_DTCT_EN_PERIOD		0x48
+#define QPHY_V8_PCS_USB_ARCVR_DTCT_CM_DLY		0x4c
+#define QPHY_V8_PCS_USB_TXONESZEROS_RUN_LENGTH		0x50
+#define QPHY_V8_PCS_USB_ALFPS_DEGLITCH_VAL		0x54
+#define QPHY_V8_PCS_USB_SIGDET_STARTUP_TIMER_VAL	0x58
+#define QPHY_V8_PCS_USB_TEST_CONTROL			0x5c
+#define QPHY_V8_PCS_USB_RXTERMINATION_DLY_SEL		0x60
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG2		0x64
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG3		0x68
+#define QPHY_V8_PCS_USB_POWER_STATE_CONFIG4		0x6c
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..169fd5de74747c8c9a833a629d8000875168a6ff
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v8.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V8_H_
+#define QCOM_PHY_QMP_PCS_V8_H_
+
+/* Only for QMP V8 PHY - USB/PCIe PCS registers */
+#define QPHY_V8_PCS_SW_RESET			0x000
+#define QPHY_V8_PCS_PCS_STATUS1			0x014
+#define QPHY_V8_PCS_POWER_DOWN_CONTROL		0x040
+#define QPHY_V8_PCS_START_CONTROL		0x044
+#define QPHY_V8_PCS_POWER_STATE_CONFIG1		0x090
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG1		0x0c4
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG2		0x0c8
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG3		0x0cc
+#define QPHY_V8_PCS_LOCK_DETECT_CONFIG6		0x0d8
+#define QPHY_V8_PCS_REFGEN_REQ_CONFIG1		0x0dc
+#define QPHY_V8_PCS_RX_SIGDET_LVL		0x188
+#define QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_L	0x190
+#define QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_H	0x194
+#define QPHY_V8_PCS_RATE_SLEW_CNTRL1		0x198
+#define QPHY_V8_PCS_CDR_RESET_TIME		0x1b0
+#define QPHY_V8_PCS_ALIGN_DETECT_CONFIG1	0x1c0
+#define QPHY_V8_PCS_ALIGN_DETECT_CONFIG2	0x1c4
+#define QPHY_V8_PCS_PCS_TX_RX_CONFIG		0x1d0
+#define QPHY_V8_PCS_EQ_CONFIG1			0x1dc
+#define QPHY_V8_PCS_EQ_CONFIG2			0x1e0
+#define QPHY_V8_PCS_EQ_CONFIG5			0x1ec
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3b2292257bc521cb66562a5b6bfae8dc8c92cc1
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_QSERDES_COM_V8_H_
+#define QCOM_PHY_QMP_QSERDES_COM_V8_H_
+
+/* Only for QMP V8 PHY - QSERDES COM registers */
+#define QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1		0x000
+#define QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1		0x004
+#define QSERDES_V8_COM_SSC_STEP_SIZE3_MODE1		0x008
+#define QSERDES_V8_COM_CP_CTRL_MODE1			0x010
+#define QSERDES_V8_COM_PLL_RCTRL_MODE1			0x014
+#define QSERDES_V8_COM_PLL_CCTRL_MODE1			0x018
+#define QSERDES_V8_COM_CORECLK_DIV_MODE1		0x01c
+#define QSERDES_V8_COM_LOCK_CMP1_MODE1			0x020
+#define QSERDES_V8_COM_LOCK_CMP2_MODE1			0x024
+#define QSERDES_V8_COM_DEC_START_MODE1			0x028
+#define QSERDES_V8_COM_DEC_START_MSB_MODE1		0x02c
+#define QSERDES_V8_COM_DIV_FRAC_START1_MODE1		0x030
+#define QSERDES_V8_COM_DIV_FRAC_START2_MODE1		0x034
+#define QSERDES_V8_COM_DIV_FRAC_START3_MODE1		0x038
+#define QSERDES_V8_COM_HSCLK_SEL_1			0x03c
+#define QSERDES_V8_COM_VCO_TUNE1_MODE1			0x048
+#define QSERDES_V8_COM_VCO_TUNE2_MODE1			0x04c
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1	0x050
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1	0x054
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0	0x058
+#define QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0	0x05c
+#define QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0		0x060
+#define QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0		0x064
+#define QSERDES_V8_COM_CP_CTRL_MODE0			0x070
+#define QSERDES_V8_COM_PLL_RCTRL_MODE0			0x074
+#define QSERDES_V8_COM_PLL_CCTRL_MODE0			0x078
+#define QSERDES_V8_COM_LOCK_CMP1_MODE0			0x080
+#define QSERDES_V8_COM_LOCK_CMP2_MODE0			0x084
+#define QSERDES_V8_COM_DEC_START_MODE0			0x088
+#define QSERDES_V8_COM_DEC_START_MSB_MODE0		0x08c
+#define QSERDES_V8_COM_DIV_FRAC_START1_MODE0		0x090
+#define QSERDES_V8_COM_DIV_FRAC_START2_MODE0		0x094
+#define QSERDES_V8_COM_DIV_FRAC_START3_MODE0		0x098
+#define QSERDES_V8_COM_VCO_TUNE1_MODE0			0x0a8
+#define QSERDES_V8_COM_VCO_TUNE2_MODE0			0x0ac
+#define QSERDES_V8_COM_BG_TIMER				0x0bc
+#define QSERDES_V8_COM_SSC_EN_CENTER			0x0c0
+#define QSERDES_V8_COM_SSC_PER1				0x0cc
+#define QSERDES_V8_COM_SSC_PER2				0x0d0
+#define QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN		0x0dc
+#define QSERDES_V8_COM_SYSCLK_BUF_ENABLE		0x0e8
+#define QSERDES_V8_COM_SYSCLK_EN_SEL			0x110
+#define QSERDES_V8_COM_RESETSM_CNTRL			0x118
+#define QSERDES_V8_COM_LOCK_CMP_CFG			0x124
+#define QSERDES_V8_COM_VCO_TUNE_MAP			0x140
+#define QSERDES_V8_COM_CORE_CLK_EN			0x170
+#define QSERDES_V8_COM_CMN_CONFIG_1			0x174
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1		0x1a4
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2		0x1a8
+#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3		0x1ac
+#define QSERDES_V8_COM_ADDITIONAL_MISC			0x1b4
+#define QSERDES_V8_COM_CMN_STATUS			0x2c8
+#define QSERDES_V8_COM_C_READY_STATUS			0x2f0
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cb8b1708607ab35760fb15f3e524872334d9b40
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v8.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V8_H_
+#define QCOM_PHY_QMP_QSERDES_TXRX_V8_H_
+
+#define QSERDES_V8_TX_TX_EMP_POST1_LVL			0x00c
+#define QSERDES_V8_TX_TX_DRV_LVL			0x014
+#define QSERDES_V8_TX_RES_CODE_LANE_TX			0x034
+#define QSERDES_V8_TX_RES_CODE_LANE_RX			0x038
+#define QSERDES_V8_TX_RES_CODE_LANE_OFFSET_TX		0x03c
+#define QSERDES_V8_TX_RES_CODE_LANE_OFFSET_RX		0x040
+#define QSERDES_V8_TX_TRANSCEIVER_BIAS_EN		0x054
+#define QSERDES_V8_TX_HIGHZ_DRVR_EN			0x058
+#define QSERDES_V8_TX_TX_POL_INV			0x05c
+#define QSERDES_V8_TX_LANE_MODE_1			0x084
+#define QSERDES_V8_TX_LANE_MODE_2			0x088
+#define QSERDES_V8_TX_LANE_MODE_3			0x08c
+#define QSERDES_V8_TX_LANE_MODE_4			0x090
+#define QSERDES_V8_TX_LANE_MODE_5			0x094
+#define QSERDES_V8_TX_RCV_DETECT_LVL_2			0x0a4
+#define QSERDES_V8_TX_PI_QEC_CTRL			0x0e4
+
+#define QSERDES_V8_RX_UCDR_FO_GAIN			0x008
+#define QSERDES_V8_RX_UCDR_SO_GAIN			0x014
+#define QSERDES_V8_RX_UCDR_SVS_FO_GAIN			0x020
+#define QSERDES_V8_RX_UCDR_FASTLOCK_FO_GAIN		0x030
+#define QSERDES_V8_RX_UCDR_SO_SATURATION_AND_ENABLE	0x034
+#define QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_LOW		0x03c
+#define QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_HIGH		0x040
+#define QSERDES_V8_RX_UCDR_PI_CONTROLS			0x044
+#define QSERDES_V8_RX_UCDR_SB2_THRESH1			0x04c
+#define QSERDES_V8_RX_UCDR_SB2_THRESH2			0x050
+#define QSERDES_V8_RX_UCDR_SB2_GAIN1			0x054
+#define QSERDES_V8_RX_UCDR_SB2_GAIN2			0x058
+#define QSERDES_V8_RX_AUX_DATA_TCOARSE_TFINE		0x060
+#define QSERDES_V8_RX_VGA_CAL_CNTRL1			0x0d4
+#define QSERDES_V8_RX_VGA_CAL_CNTRL2			0x0d8
+#define QSERDES_V8_RX_GM_CAL				0x0dc
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL2		0x0ec
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL3		0x0f0
+#define QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL4		0x0f4
+#define QSERDES_V8_RX_RX_IDAC_TSETTLE_LOW		0x0f8
+#define QSERDES_V8_RX_RX_IDAC_TSETTLE_HIGH		0x0fc
+#define QSERDES_V8_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1	0x110
+#define QSERDES_V8_RX_SIGDET_ENABLES			0x118
+#define QSERDES_V8_RX_SIGDET_CNTRL			0x11c
+#define QSERDES_V8_RX_SIGDET_DEGLITCH_CNTRL		0x124
+#define QSERDES_V8_RX_RX_MODE_00_LOW			0x15c
+#define QSERDES_V8_RX_RX_MODE_00_HIGH			0x160
+#define QSERDES_V8_RX_RX_MODE_00_HIGH2			0x164
+#define QSERDES_V8_RX_RX_MODE_00_HIGH3			0x168
+#define QSERDES_V8_RX_RX_MODE_00_HIGH4			0x16c
+#define QSERDES_V8_RX_RX_MODE_01_LOW			0x170
+#define QSERDES_V8_RX_RX_MODE_01_HIGH			0x174
+#define QSERDES_V8_RX_RX_MODE_01_HIGH2			0x178
+#define QSERDES_V8_RX_RX_MODE_01_HIGH3			0x17c
+#define QSERDES_V8_RX_RX_MODE_01_HIGH4			0x180
+#define QSERDES_V8_RX_DFE_EN_TIMER			0x1a0
+#define QSERDES_V8_RX_DFE_CTLE_POST_CAL_OFFSET		0x1a4
+#define QSERDES_V8_RX_DCC_CTRL1				0x1a8
+#define QSERDES_V8_RX_VTH_CODE				0x1b0
+#define QSERDES_V8_RX_SIGDET_CAL_CTRL1			0x1e4
+#define QSERDES_V8_RX_SIGDET_CAL_TRIM			0x1f8
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index d0f41e4aaa855fc3ee088afc833b214277b7e2b0..8148853ff275b0526cb47a158d332af1d74e0abf 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -30,6 +30,9 @@
 #include "phy-qcom-qmp-qserdes-com-v7.h"
 #include "phy-qcom-qmp-qserdes-txrx-v7.h"
 
+#include "phy-qcom-qmp-qserdes-com-v8.h"
+#include "phy-qcom-qmp-qserdes-txrx-v8.h"
+
 #include "phy-qcom-qmp-qserdes-pll.h"
 
 #include "phy-qcom-qmp-pcs-v2.h"
@@ -52,6 +55,8 @@
 
 #include "phy-qcom-qmp-pcs-v7.h"
 
+#include "phy-qcom-qmp-pcs-v8.h"
+
 /* QPHY_SW_RESET bit */
 #define SW_RESET				BIT(0)
 /* QPHY_POWER_DOWN_CONTROL */

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:36 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:36 -0700
Subject: [PATCH v3 08/10] arm64: dts: qcom: sm8750: Add USB support for
 SM8750 MTP platform
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-8-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Enable USB support on SM8750 MTP variants.  The current definition will
start the USB controller in peripheral mode by default until
dependencies are added, such as USB role detection.

Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
index 5d0decd2aa2d0e0849414534cdd504714402458e..3ad417aaaaf46ee007bc4c029fa9e57ac183c075 100644
--- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
@@ -806,3 +806,27 @@ &tlmm {
 &uart7 {
 	status = "okay";
 };
+
+&usb_1 {
+	status = "okay";
+};
+
+&usb_1_dwc3 {
+	dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+	vdd-supply = <&vreg_l2d_0p88>;
+	vdda12-supply = <&vreg_l3g_1p2>;
+
+	phys = <&pmih0108_eusb2_repeater>;
+
+	status = "okay";
+};
+
+&usb_dp_qmpphy {
+	vdda-phy-supply = <&vreg_l3g_1p2>;
+	vdda-pll-supply = <&vreg_l2d_0p88>;
+
+	status = "okay";
+};

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:38 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:38 -0700
Subject: [PATCH v3 10/10] arm64: defconfig: Add M31 eUSB2 PHY config for
 SM8750
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-10-13e096dc88fd@quicinc.com>

The SM8750 SoCs use an eUSB2 PHY driver different from the
already existing M31 USB driver because it requires a connection
to an eUSB2 repeater. Thus, for USB to probe and work properly on
SM8750, enable the additional driver.

Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5bb8f09422a22116781169611482179b10798c14..914881c02cf1d0426f102674437907ed77574462 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1594,6 +1594,7 @@ CONFIG_PHY_QCOM_QUSB2=m
 CONFIG_PHY_QCOM_SNPS_EUSB2=m
 CONFIG_PHY_QCOM_EUSB2_REPEATER=m
 CONFIG_PHY_QCOM_M31_USB=m
+CONFIG_PHY_QCOM_M31_EUSB=m
 CONFIG_PHY_QCOM_USB_HS=m
 CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
 CONFIG_PHY_QCOM_USB_HS_28NM=m

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:37 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:37 -0700
Subject: [PATCH v3 09/10] arm64: dts: qcom: sm8750: Add USB support for
 SM8750 QRD platform
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-9-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Enable USB support on SM8750 QRD variant.  The current definition
will start the USB controller in peripheral mode by default until
dependencies are added, such as USB role detection.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Tested-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8750-qrd.dts | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
index 7f1d5d4e5b2813c59ea9dba2c57bee824f967481..77735ddcc7ab954ac25aad20369fdc8898283d40 100644
--- a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts
@@ -804,3 +804,27 @@ &tlmm {
 &uart7 {
 	status = "okay";
 };
+
+&usb_1 {
+	status = "okay";
+};
+
+&usb_1_dwc3 {
+	dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+	vdd-supply = <&vreg_l2d_0p88>;
+	vdda12-supply = <&vreg_l3g_1p2>;
+
+	phys = <&pmih0108_eusb2_repeater>;
+
+	status = "okay";
+};
+
+&usb_dp_qmpphy {
+	vdda-phy-supply = <&vreg_l3g_1p2>;
+	vdda-pll-supply = <&vreg_l2d_0p88>;
+
+	status = "okay";
+};

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:29 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:29 -0700
Subject: [PATCH v3 01/10] dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy:
 Add SM8750 to QMP PHY
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-1-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add an entry to the compatible field for SM8750 for the QMP combo PHY.
This handles the USB3 path for SM8750.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 .../devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml          | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
index 358a6736a951ca5db7cff7385b3657976a667358..38ce04c35d945d0d8d319191c241920810ee9005 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
@@ -29,6 +29,7 @@ properties:
       - qcom,sm8450-qmp-usb3-dp-phy
       - qcom,sm8550-qmp-usb3-dp-phy
       - qcom,sm8650-qmp-usb3-dp-phy
+      - qcom,sm8750-qmp-usb3-dp-phy
       - qcom,x1e80100-qmp-usb3-dp-phy
 
   reg:
@@ -133,6 +134,7 @@ allOf:
             - qcom,sm6350-qmp-usb3-dp-phy
             - qcom,sm8550-qmp-usb3-dp-phy
             - qcom,sm8650-qmp-usb3-dp-phy
+            - qcom,sm8750-qmp-usb3-dp-phy
             - qcom,x1e80100-qmp-usb3-dp-phy
     then:
       required:

-- 
2.48.1



From quic_molvera at quicinc.com  Mon Mar 24 13:18:35 2025
From: quic_molvera at quicinc.com (Melody Olvera)
Date: Mon, 24 Mar 2025 13:18:35 -0700
Subject: [PATCH v3 07/10] arm64: dts: qcom: sm8750: Add USB support to
 SM8750 SoCs
In-Reply-To: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
References: <20250324-sm8750_usb_master-v3-0-13e096dc88fd@quicinc.com>
Message-ID: <20250324-sm8750_usb_master-v3-7-13e096dc88fd@quicinc.com>

From: Wesley Cheng <quic_wcheng at quicinc.com>

Add the base USB devicetree definitions for SM8750 platforms.  The overall
chipset contains a single DWC3 USB3 controller (rev. 200a), SS QMP PHY
(rev. v8) and M31 eUSB2 PHY.  The major difference for SM8750 is the
transition to using the M31 eUSB2 PHY compared to previous SoCs.

Enable USB support on SM8750 MTP and QRD variants. SM8750 has a QMP combo
PHY for the SSUSB path, and a M31 eUSB2 PHY for the HSUSB path.

Signed-off-by: Wesley Cheng <quic_wcheng at quicinc.com>
Signed-off-by: Melody Olvera <quic_molvera at quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8750.dtsi | 166 +++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi
index 612b99dc3c55495d06b3577531ec6996554bbbb6..9f636f4866dc844820039e5434c2ed788fc3d509 100644
--- a/arch/arm64/boot/dts/qcom/sm8750.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/interconnect/qcom,sm8750-rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
 #include <dt-bindings/power/qcom,rpmhpd.h>
 #include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/soc/qcom,gpr.h>
@@ -2370,6 +2371,171 @@ data-pins {
 			};
 		};
 
+		usb_1_hsphy: phy at 88e3000 {
+			compatible = "qcom,sm8750-m31-eusb2-phy";
+			reg = <0x0 0x88e3000 0x0 0x29c>;
+
+			clocks = <&tcsrcc TCSR_USB2_CLKREF_EN>;
+			clock-names = "ref";
+
+			resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+			#phy-cells = <0>;
+
+			status = "disabled";
+		};
+
+		usb_dp_qmpphy: phy at 88e8000 {
+			compatible = "qcom,sm8750-qmp-usb3-dp-phy";
+			reg = <0x0 0x088e8000 0x0 0x4000>;
+
+			clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+				 <&rpmhcc RPMH_CXO_CLK>,
+				 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+				 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+			clock-names = "aux",
+				      "ref",
+				      "com_aux",
+				      "usb3_pipe";
+
+			resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+				 <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+			reset-names = "phy",
+				      "common";
+
+			power-domains = <&gcc GCC_USB3_PHY_GDSC>;
+
+			#clock-cells = <1>;
+			#phy-cells = <1>;
+
+			orientation-switch;
+
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+
+					usb_dp_qmpphy_out: endpoint {
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+
+					usb_dp_qmpphy_usb_ss_in: endpoint {
+						remote-endpoint = <&usb_1_dwc3_ss>;
+					};
+				};
+
+				port at 2 {
+					reg = <2>;
+
+					usb_dp_qmpphy_dp_in: endpoint {
+					};
+				};
+			};
+		};
+
+		usb_1: usb at a6f8800 {
+			compatible = "qcom,sm8750-dwc3", "qcom,dwc3";
+			reg = <0x0 0x0a6f8800 0x0 0x400>;
+
+			clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+				 <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+				 <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+				 <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+				 <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+				 <&tcsrcc TCSR_USB3_CLKREF_EN>;
+			clock-names = "cfg_noc",
+				      "core",
+				      "iface",
+				      "sleep",
+				      "mock_utmi",
+				      "xo";
+
+			assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+					  <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+			assigned-clock-rates = <19200000>, <200000000>;
+
+			interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+					      <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+					      <&pdc 14 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc 15 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "pwr_event",
+					  "hs_phy_irq",
+					  "dp_hs_phy_irq",
+					  "dm_hs_phy_irq",
+					  "ss_phy_irq";
+
+			power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+			required-opps = <&rpmhpd_opp_nom>;
+
+			resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+			interconnects = <&aggre1_noc MASTER_USB3_0 QCOM_ICC_TAG_ALWAYS
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+					<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+					 &config_noc SLAVE_USB3_0 QCOM_ICC_TAG_ACTIVE_ONLY>;
+			interconnect-names = "usb-ddr", "apps-usb";
+
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			status = "disabled";
+
+			usb_1_dwc3: usb at a600000 {
+				compatible = "snps,dwc3";
+				reg = <0x0 0x0a600000 0x0 0xe000>;
+
+				interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+
+				iommus = <&apps_smmu 0x40 0x0>;
+
+				phys = <&usb_1_hsphy>, <&usb_dp_qmpphy QMP_USB43DP_USB3_PHY>;
+				phy-names = "usb2-phy", "usb3-phy";
+
+				snps,hird-threshold = /bits/ 8 <0x0>;
+				snps,usb2-gadget-lpm-disable;
+				snps,dis_u2_susphy_quirk;
+				snps,dis_enblslpm_quirk;
+				snps,dis-u1-entry-quirk;
+				snps,dis-u2-entry-quirk;
+				snps,is-utmi-l1-suspend;
+				snps,usb3_lpm_capable;
+				snps,usb2-lpm-disable;
+				snps,has-lpm-erratum;
+				tx-fifo-resize;
+
+				dma-coherent;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port at 0 {
+						reg = <0>;
+
+						usb_1_dwc3_hs: endpoint {
+						};
+					};
+
+					port at 1 {
+						reg = <1>;
+
+						usb_1_dwc3_ss: endpoint {
+							remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
+						};
+					};
+				};
+			};
+		};
+
 		pdc: interrupt-controller at b220000 {
 			compatible = "qcom,sm8750-pdc", "qcom,pdc";
 			reg = <0x0 0x0b220000 0x0 0x10000>, <0x0 0x164400f0 0x0 0x64>;

-- 
2.48.1



From robh at kernel.org  Mon Mar 24 13:23:00 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 15:23:00 -0500
Subject: [PATCH 2/2] dt-bindings: pinctrl: mediatek: Correct indentation
 and style in DTS example
In-Reply-To: <20250324125105.81774-2-krzysztof.kozlowski@linaro.org>
References: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>
 <20250324125105.81774-2-krzysztof.kozlowski@linaro.org>
Message-ID: <20250324202300.GA804681-robh@kernel.org>

On Mon, Mar 24, 2025 at 01:51:05PM +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../pinctrl/mediatek,mt65xx-pinctrl.yaml      | 83 +++++++------------
>  .../pinctrl/mediatek,mt7622-pinctrl.yaml      | 48 +++++------
>  .../pinctrl/mediatek,mt8183-pinctrl.yaml      | 68 +++++++--------
>  .../pinctrl/mediatek,mt8192-pinctrl.yaml      | 76 ++++++++---------
>  4 files changed, 127 insertions(+), 148 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> index 5f2808212f39..b9680b896f12 100644
> --- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
> @@ -137,64 +137,43 @@ examples:
>          #size-cells = <2>;
>  
>          pinctrl at 1c20800 {
> -          compatible = "mediatek,mt8135-pinctrl";
> -          reg = <0 0x1000B000 0 0x1000>;
> -          mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
> -          gpio-controller;
> -          #gpio-cells = <2>;
> -          interrupt-controller;
> -          #interrupt-cells = <2>;
> -          interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
> -              <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
> -              <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
> +            compatible = "mediatek,mt8135-pinctrl";
> +            reg = <0 0x1000B000 0 0x1000>;
> +            mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +            interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
> +                         <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
> +                         <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
>  
> -          i2c0_pins_a: i2c0-pins {
> -            pins1 {
> -              pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
> -                <MT8135_PIN_101_SCL0__FUNC_SCL0>;
> -              bias-disable;
> -            };
> -          };
> -
> -          i2c1_pins_a: i2c1-pins {
> -            pins {
> -              pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
> -                <MT8135_PIN_196_SCL1__FUNC_SCL1>;
> -              bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
> -            };
> -          };
> -
> -          i2c2_pins_a: i2c2-pins {
> -            pins1 {
> -              pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
> -              bias-pull-down;
> +            i2c0_pins_a: i2c0-pins {

Perhaps drop the unused labels while you are here. Either way,

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 13:24:05 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:24:05 -0500
Subject: [PATCH] dt-bindings: nvmem: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125214.82028-1-krzysztof.kozlowski@linaro.org>
References: <20250324125214.82028-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174284784448.810985.2720262744540534185.robh@kernel.org>


On Mon, 24 Mar 2025 13:52:14 +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../devicetree/bindings/nvmem/nvmem.yaml      | 60 +++++++++----------
>  .../devicetree/bindings/nvmem/rmem.yaml       | 20 +++----
>  .../bindings/nvmem/rockchip-efuse.yaml        | 20 +++----
>  3 files changed, 50 insertions(+), 50 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 13:28:15 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:28:15 -0500
Subject: [PATCH] dt-bindings: iommu: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
References: <20250324125250.82137-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174284809477.815772.5676101186306641286.robh@kernel.org>


On Mon, 24 Mar 2025 13:52:50 +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../iommu/allwinner,sun50i-h6-iommu.yaml      |  24 ++--
>  .../bindings/iommu/arm,smmu-v3.yaml           |  20 ++--
>  .../devicetree/bindings/iommu/arm,smmu.yaml   | 104 +++++++++---------
>  .../bindings/iommu/mediatek,iommu.yaml        |  18 +--
>  .../bindings/iommu/qcom,apq8064-iommu.yaml    |  20 ++--
>  5 files changed, 92 insertions(+), 94 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 13:31:14 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:31:14 -0500
Subject: [PATCH 2/2] dt-bindings: iio: Use unevaluatedProperties for SPI
 devices
In-Reply-To: <20250324125313.82226-2-krzysztof.kozlowski@linaro.org>
References: <20250324125313.82226-1-krzysztof.kozlowski@linaro.org>
 <20250324125313.82226-2-krzysztof.kozlowski@linaro.org>
Message-ID: <174284827311.819192.14616231717400662961.robh@kernel.org>


On Mon, 24 Mar 2025 13:53:13 +0100, Krzysztof Kozlowski wrote:
> SPI devices should use unevaluatedProperties:false instead of
> additionalProperties:false, to allow any SPI device properties listed in
> spi-peripheral-props.yaml.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml      | 2 +-
>  Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml      | 2 +-
>  Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml      | 2 +-
>  .../devicetree/bindings/iio/dac/microchip,mcp4821.yaml          | 2 +-
>  Documentation/devicetree/bindings/iio/dac/rohm,bd79703.yaml     | 2 +-
>  Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml    | 2 +-
>  .../devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml    | 2 +-
>  .../devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml | 2 +-
>  8 files changed, 8 insertions(+), 8 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 13:18:18 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:18:18 -0500
Subject: [PATCH 1/2] dt-bindings: pinctrl: mediatek: Drop unrelated nodes
 from DTS example
In-Reply-To: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>
References: <20250324125105.81774-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174284749693.804487.17057148980208397199.robh@kernel.org>


On Mon, 24 Mar 2025 13:51:04 +0100, Krzysztof Kozlowski wrote:
> Binding example should not contain other nodes, e.g. consumers of
> pinctrl of, because this is completely redundant and adds unnecessary
> bloat.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml      | 10 ----------
>  .../bindings/pinctrl/mediatek,mt6779-pinctrl.yaml      |  5 -----
>  2 files changed, 15 deletions(-)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 13:31:57 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 15:31:57 -0500
Subject: [PATCH] dt-bindings: gpio: Correct indentation and style in DTS
 example
In-Reply-To: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
References: <20250324125326.82270-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174284830296.819870.8907081146872259608.robh@kernel.org>


On Mon, 24 Mar 2025 13:53:26 +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.  While re-indenting, drop
> unused labels.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../bindings/gpio/atmel,at91rm9200-gpio.yaml  | 16 ++---
>  .../bindings/gpio/fairchild,74hc595.yaml      | 20 +++---
>  .../devicetree/bindings/gpio/gpio-mxs.yaml    | 70 +++++++++----------
>  .../devicetree/bindings/gpio/nxp,pcf8575.yaml | 24 +++----
>  .../bindings/gpio/realtek,otto-gpio.yaml      |  8 +--
>  .../bindings/gpio/renesas,em-gio.yaml         | 20 +++---
>  .../bindings/gpio/renesas,rcar-gpio.yaml      | 24 +++----
>  .../devicetree/bindings/gpio/sifive,gpio.yaml |  6 +-
>  .../bindings/gpio/toshiba,gpio-visconti.yaml  | 24 +++----
>  .../bindings/gpio/xlnx,gpio-xilinx.yaml       | 48 ++++++-------
>  10 files changed, 130 insertions(+), 130 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From patchwork-bot+netdevbpf at kernel.org  Mon Mar 24 13:50:43 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Mon, 24 Mar 2025 20:50:43 +0000
Subject: [PATCH net-next] net: stmmac: Call xpcs_config_eee_mult_fact() only
 when xpcs is present
In-Reply-To: <20250321103502.1303539-1-maxime.chevallier@bootlin.com>
References: <20250321103502.1303539-1-maxime.chevallier@bootlin.com>
Message-ID: <174284944375.4167801.10275229682419761555.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Fri, 21 Mar 2025 11:35:01 +0100 you wrote:
> Some dwmac variants such as dwmac_socfpga don't use xpcs but lynx_pcs.
> 
> Don't call xpcs_config_eee_mult_fact() in this case, as this causes a
> crash at init :
> 
>  Unable to handle kernel NULL pointer dereference at virtual address 00000039 when write
> 
> [...]

Here is the summary with links:
  - [net-next] net: stmmac: Call xpcs_config_eee_mult_fact() only when xpcs is present
    https://git.kernel.org/netdev/net-next/c/53cd6820f5a0

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From arnd at kernel.org  Mon Mar 24 14:33:35 2025
From: arnd at kernel.org (Arnd Bergmann)
Date: Mon, 24 Mar 2025 22:33:35 +0100
Subject: [PATCH] ARM: davinci: always enable CONFIG_ARCH_DAVINCI_DA850
Message-ID: <20250324213340.4129384-1-arnd@kernel.org>

From: Arnd Bergmann <arnd at arndb.de>

A change to the clk driver broke configurations that enable DA830
but not DA850:

arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o: in function `__da850_pll0_of_clk_init_declare':
pll.c:(.init.text+0x30): undefined reference to `of_da850_pll0_init'
arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_id_table+0x14): undefined reference to `da850_pll0_init'
arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_id_table+0x2c): undefined reference to `da850_pll1_init'
arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_of_match+0xc0): undefined reference to `of_da850_pll1_init'
arm-linux-gnueabi-ld: drivers/clk/davinci/psc.o:(.rodata.davinci_psc_id_table+0x14): undefined reference to `da850_psc0_init_data'
arm-linux-gnueabi-ld: drivers/clk/davinci/psc.o:(.rodata.davinci_psc_id_table+0x2c): undefined reference to `da850_psc1_init_data'

Select ARCH_DAVINCI_DA850 unconditionally to ensure the driver can still
build.

Fixes: a31b4dcf188c ("clk: davinci: remove support for da830")
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm/mach-davinci/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 3fa15f342240..8f66de0405d9 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -4,6 +4,7 @@ menuconfig ARCH_DAVINCI
 	bool "TI DaVinci"
 	depends on ARCH_MULTI_V5
 	depends on CPU_LITTLE_ENDIAN
+	select ARCH_DAVINCI_DA850
 	select CPU_ARM926T
 	select DAVINCI_TIMER
 	select ZONE_DMA
-- 
2.39.5



From andrew at codeconstruct.com.au  Mon Mar 24 16:17:34 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 25 Mar 2025 09:47:34 +1030
Subject: [PATCH v6 2/2] ARM: dts: aspeed: ventura: add Meta Ventura BMC
In-Reply-To: <20250321123731.1373596-3-jason-hsu@quantatw.com>
References: <20250321123731.1373596-1-jason-hsu@quantatw.com>
	 <20250321123731.1373596-3-jason-hsu@quantatw.com>
Message-ID: <691f1e8dc34427b0e5bb9d6bf77ede3d76718c6f.camel@codeconstruct.com.au>

On Fri, 2025-03-21 at 20:37 +0800, Jason Hsu wrote:
> 
> +???????????????led-84 {

Lots of LEDs!

> +???????????????????????label = "compute18_led_amber";
> +???????????????????????default-state = "off";
> +???????????????????????gpios = <&tray_leds_g1_gpio 0 GPIO_ACTIVE_LOW>;
> +???????????????};
> +???????};
> +
> +???????memory at 80000000 {
> +???????????????device_type = "memory";
> +???????????????reg = <0x80000000 0x80000000>;
> +???????};
> +
> +??? p1v8_bmc_aux: regulator-p1v8-bmc-aux {

The indentation is broken here and in other places below. Can you
please fix it up?

> +???????????????compatible = "regulator-fixed";
> +???????????????regulator-name = "p1v8_bmc_aux";
> +???????????????regulator-min-microvolt = <1800000>;
> +???????????????regulator-max-microvolt = <1800000>;
> +???????????????regulator-always-on;
> +???????};
> +
> +???????p2v5_bmc_aux: regulator-p2v5-bmc-aux {
> +???????????????compatible = "regulator-fixed";
> +???????????????regulator-name = "p2v5_bmc_aux";
> +???????????????regulator-min-microvolt = <2500000>;
> +???????????????regulator-max-microvolt = <2500000>;
> +???????????????regulator-always-on;
> +???????};
> +
> +??? spi1_gpio: spi {
> +???????????????compatible = "spi-gpio";
> +???????????????#address-cells = <1>;
> +???????????????#size-cells = <0>;
> +
> +???????????????sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
> +???????????????mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
> +???????????????miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>;
> +???????????????cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
> +???????????????num-chipselects = <1>;
> +
> +???????????????tpm at 0 {
> +???????????????????????compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
> +???????????????????????spi-max-frequency = <33000000>;
> +???????????????????????reg = <0>;
> +???????????????};
> +???????};
> +};
> +
> +&adc0 {
> +???????vref-supply = <&p1v8_bmc_aux>;
> +???????status = "okay";
> +
> +???????pinctrl-names = "default";
> +???????pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
> +???????????????&pinctrl_adc2_default &pinctrl_adc3_default
> +???????????????&pinctrl_adc4_default &pinctrl_adc5_default
> +???????????????&pinctrl_adc6_default &pinctrl_adc7_default>;
> +
> +};
> +
> +&adc1 {
> +???????vref-supply = <&p2v5_bmc_aux>;
> +???????status = "okay";
> +
> +???????pinctrl-names = "default";
> +???????pinctrl-0 = <&pinctrl_adc10_default>;
> +};
> +
> +&ehci0 {
> +???????status = "okay";
> +};
> +
> +&ehci1 {
> +???????status = "okay";
> +};
> +
> +&fmc {
> +???????status = "okay";
> +???????flash at 0 {
> +???????????????status = "okay";
> +???????????????m25p,fast-read;
> +???????????????label = "bmc";
> +???????????????spi-max-frequency = <50000000>;
> +#include "openbmc-flash-layout-128.dtsi"
> +???????};
> +???????flash at 1 {
> +???????????????status = "okay";
> +???????????????m25p,fast-read;
> +???????????????label = "alt-bmc";
> +???????????????spi-max-frequency = <50000000>;
> +???????};
> +};
> +
> +&i2c0 {
> +???????status = "okay";
> +
> +???????i2c-mux at 77 {
> +???????????????compatible = "nxp,pca9548";
> +???????????????reg = <0x77>;
> +???????????????#address-cells = <1>;
> +???????????????#size-cells = <0>;
> +
> +???????????????i2c0mux0ch0: i2c at 0 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <0>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch1: i2c at 1 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <1>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch2: i2c at 2 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <2>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch3: i2c at 3 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <3>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch4: i2c at 4 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <4>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch5: i2c at 5 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <5>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch6: i2c at 6 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <6>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c0mux0ch7: i2c at 7 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <7>;
> +???????????????????????status = "okay";
> +???????????????};
> +???????};
> +};
> +
> +&i2c1 {
> +???????status = "okay";
> +
> +???????i2c-mux at 77 {
> +???????????????compatible = "nxp,pca9548";
> +???????????????reg = <0x77>;
> +???????????????#address-cells = <1>;
> +???????????????#size-cells = <0>;
> +
> +???????????????i2c1mux0ch0: i2c at 0 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <0>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch1: i2c at 1 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <1>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch2: i2c at 2 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <2>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch3: i2c at 3 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <3>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch4: i2c at 4 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <4>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch5: i2c at 5 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <5>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch6: i2c at 6 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <6>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c1mux0ch7: i2c at 7 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <7>;
> +???????????????????????status = "okay";
> +???????????????};
> +???????};
> +};
> +
> +&i2c2 {
> +???????status = "okay";
> +
> +???????i2c-mux at 77 {
> +???????????????compatible = "nxp,pca9548";
> +???????????????reg = <0x77>;
> +???????????????#address-cells = <1>;
> +???????????????#size-cells = <0>;
> +
> +???????????????i2c2mux0ch0: i2c at 0 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <0>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch1: i2c at 1 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <1>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch2: i2c at 2 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <2>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch3: i2c at 3 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <3>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch4: i2c at 4 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <4>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch5: i2c at 5 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <5>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch6: i2c at 6 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <6>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c2mux0ch7: i2c at 7 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <7>;
> +???????????????????????status = "okay";
> +???????????????};
> +???????};
> +};
> +
> +&i2c3 {
> +???????status = "okay";
> +
> +???????i2c-mux at 77 {
> +???????????????compatible = "nxp,pca9548";
> +???????????????reg = <0x77>;
> +???????????????#address-cells = <1>;
> +???????????????#size-cells = <0>;
> +
> +???????????????i2c3mux0ch0: i2c at 0 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <0>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c3mux0ch1: i2c at 1 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <1>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c3mux0ch2: i2c at 2 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <2>;
> +???????????????????????status = "okay";
> +???????????????};
> +
> +???????????????i2c3mux0ch3: i2c at 3 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <3>;
> +
> +???????????????????????// Fan Board 0 FRU
> +???????????????????????eeprom at 56 {
> +???????????????????????????????compatible = "atmel,24c128";
> +???????????????????????????????reg = <0x56>;
> +???????????????????????};
> +
> +???????????????????????fan_leds_g1_gpio: gpio at 21 {
> +???????????????????????????????compatible = "nxp,pca9555";
> +???????????????????????????????reg = <0x21>;
> +???????????????????????????????gpio-controller;
> +???????????????????????????????#gpio-cells = <2>;
> +???????????????????????};
> +
> +???????????????????????adc at 1f {
> +???????????????????????????????compatible = "ti,adc128d818";
> +???????????????????????????????reg = <0x1f>;
> +???????????????????????????????ti,mode = /bits/ 8 <1>;
> +???????????????????????};
> +
> +???????????????????????adc at 35 {
> +???????????????????????????????compatible = "maxim,max11617";
> +???????????????????????????????reg = <0x35>;
> +???????????????????????};

(All) nodes should be in increasing order of address, or ordered
alphabetically otherwise:

https://docs.kernel.org/devicetree/bindings/dts-coding-style.html#order-of-nodes

Can you please fix this throughout the patch?

> +???????????????};
> +
> +???????????????i2c3mux0ch4: i2c at 4 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <4>;
> +
> +???????????????????????// Fan Board 1 FRU
> +???????????????????????eeprom at 56 {
> +???????????????????????????????compatible = "atmel,24c128";
> +???????????????????????????????reg = <0x56>;
> +???????????????????????};
> +
> +???????????????????????gpio at 21 {
> +???????????????????????????????compatible = "nxp,pca9555";
> +???????????????????????????????reg = <0x21>;
> +???????????????????????????????gpio-controller;
> +???????????????????????????????#gpio-cells = <2>;
> +???????????????????????};
> +
> +???????????????????????adc at 1f {
> +???????????????????????????????compatible = "ti,adc128d818";
> +???????????????????????????????reg = <0x1f>;
> +???????????????????????????????ti,mode = /bits/ 8 <1>;
> +???????????????????????};
> +
> +???????????????????????adc at 35 {
> +???????????????????????????????compatible = "maxim,max11617";
> +???????????????????????????????reg = <0x35>;
> +???????????????????????};
> +???????????????};
> +
> +???????????????i2c3mux0ch5: i2c at 5 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <5>;
> +
> +???????????????????????hwmon: hwmon at 23 {

I've said elsewhere that I don't think hwmon is the right node name:

https://lore.kernel.org/all/26a1d17c47c5ca6036dd58ac3b953daeec9f5ef8.camel at codeconstruct.com.au/

> +???????????????????????????????compatible = "nuvoton,nct7363";
> +???????????????????????????????reg = <0x23>;
> +???????????????????????????????#pwm-cells = <2>;
> +
> +???????????????????????????????//fan 0 IL
> +???????????????????????????????fan-0 {
> +???????????????????????????????????????pwms = <&hwmon 0 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x09>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 0 OL
> +???????????????????????????????fan-1 {
> +???????????????????????????????????????pwms = <&hwmon 0 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0B>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 1 IL
> +???????????????????????????????fan-2 {
> +???????????????????????????????????????pwms = <&hwmon 4 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0A>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 1 OL
> +???????????????????????????????fan-3 {
> +???????????????????????????????????????pwms = <&hwmon 4 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0D>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 2 IL
> +???????????????????????????????fan-4 {
> +???????????????????????????????????????pwms = <&hwmon 6 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x0F>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 2 OL
> +???????????????????????????????fan-5 {
> +???????????????????????????????????????pwms = <&hwmon 6 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x01>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 3 IL
> +???????????????????????????????fan-6 {
> +???????????????????????????????????????pwms = <&hwmon 10 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x00>;
> +???????????????????????????????};
> +
> +???????????????????????????????//fan 3 OL
> +???????????????????????????????fan-7 {
> +???????????????????????????????????????pwms = <&hwmon 10 20000>;
> +???????????????????????????????????????tach-ch = /bits/ 8 <0x03>;
> +???????????????????????????????};
> +???????????????????????};
> +???????????????};
> +
> +???????????????i2c3mux0ch6: i2c at 6 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <6>;
> +???????????????????????// REAR-IO Board FRU
> +???????????????????????eeprom at 56 {
> +???????????????????????????????compatible = "atmel,24c128";
> +???????????????????????????????reg = <0x56>;
> +???????????????????????};
> +???????????????};
> +
> +???????????????i2c3mux0ch7: i2c at 7 {
> +???????????????????????#address-cells = <1>;
> +???????????????????????#size-cells = <0>;
> +???????????????????????reg = <7>;
> +???????????????????????status = "okay";
> +???????????????};
> +???????};
> +};
> +
> +&i2c4 {
> +???????status = "okay";
> +};
> +
> +&i2c5 {
> +???????status = "okay";
> +
> +??? // VR TEMP U399

Indentation again here and below.

> +???????temperature-sensor at 4c {
> +???????????????compatible = "ti,tmp75";
> +???????????????reg = <0x4c>;
> +???????};
> +??? // VR TEMP U397
> +???????temperature-sensor at 4d {
> +???????????????compatible = "ti,tmp75";
> +???????????????reg = <0x4d>;
> +???????};
> +??? // BRICK TEMP U398
> +???????temperature-sensor at 4e {
> +???????????????compatible = "ti,tmp75";
> +???????????????reg = <0x4e>;
> +???????};
> +
> +???????temperature-sensor at 4f {
> +???????????????compatible = "ti,tmp75";
> +???????????????reg = <0x4f>;
> +???????};
> +??? // RMC FRU
> +???????eeprom at 54 {
> +???????????????compatible = "atmel,24c128";
> +???????????????reg = <0x54>;
> +???????};
> +};
> +
> +&i2c6 {
> +???????status = "okay";
> +
> +???????gpio at 20 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x20>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????gpio at 21 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x21>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????gpio at 22 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x22>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????rtc at 51 {
> +???????????????compatible = "nxp,pcf8563";
> +???????????????reg = <0x51>;
> +???????};
> +};
> +
> +&i2c7 {
> +???????status = "okay";
> +};
> +
> +&i2c9 {
> +???????status = "okay";
> +
> +??? // SCM TEMP SENSOR
> +???????temperature-sensor at 4b {
> +???????????????compatible = "ti,tmp75";
> +???????????????reg = <0x4b>;
> +???????};
> +
> +??? // SCM FRU EEPROM
> +???????eeprom at 50 {
> +???????????????compatible = "atmel,24c128";
> +???????????????reg = <0x50>;
> +???????};
> +
> +??? // BSM FRU EEPROM
> +???????eeprom at 56 {
> +???????????????compatible = "atmel,24c64";
> +???????????????reg = <0x56>;
> +???????};
> +};
> +
> +&i2c10 {
> +???????status = "okay";
> +
> +???????power-monitor at 14 {
> +???????????????compatible = "infineon,xdp710";
> +???????????????reg = <0x14>;
> +???????};
> +
> +???????power-monitor at 44 {
> +???????????????compatible = "lltc,ltc4286";
> +???????????????reg = <0x44>;
> +???????};
> +};
> +
> +&i2c14 {
> +???????status = "okay";
> +};
> +
> +&i2c15 {
> +???????status = "okay";
> +
> +???????tray_leds_g1_gpio: gpio at 20 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x20>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????tray_leds_g2_gpio: gpio at 21 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x21>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????tray_leds_g3_gpio: gpio at 22 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x22>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????tray_leds_g4_gpio: gpio at 24 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x24>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????tray_leds_g5_gpio: gpio at 25 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x25>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +???????tray_leds_g6_gpio: gpio at 26 {
> +???????????????compatible = "nxp,pca9555";
> +???????????????reg = <0x26>;
> +???????????????gpio-controller;
> +???????????????#gpio-cells = <2>;
> +???????};
> +
> +??? // LED Board FRU
> +???????eeprom at 56 {
> +???????????????compatible = "atmel,24c128";
> +???????????????reg = <0x56>;
> +???????};
> +};
> +
> +&mdio0 {
> +???????status = "okay";
> +};
> +
> +&mac3 {

Should probably be ordered before '&mdio0' above :)

Andrew

From sboyd at kernel.org  Mon Mar 24 16:35:56 2025
From: sboyd at kernel.org (Stephen Boyd)
Date: Mon, 24 Mar 2025 16:35:56 -0700
Subject: [GIT PULL] Qualcomm clock updates for v6.15
In-Reply-To: <20250322133453.2723879-1-andersson@kernel.org>
References: <20250322133453.2723879-1-andersson@kernel.org>
Message-ID: <756e17f75d314afc8ce68b727fe2b115@kernel.org>

Quoting Bjorn Andersson (2025-03-22 06:34:50)
> 
> The following changes since commit 2014c95afecee3e76ca4a56956a936e23283f05b:
> 
>   Linux 6.14-rc1 (2025-02-02 15:39:26 -0800)
> 
> are available in the Git repository at:
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git tags/qcom-clk-for-6.15
> 
> for you to fetch changes up to 9bf3684e0f7e65298ff844fd81e6dc5105c67354:
> 
>   clk: qcom: Add NSS clock Controller driver for IPQ9574 (2025-03-17 10:11:45 -0500)
> 
> ----------------------------------------------------------------

Thanks. Pulled into clk-next


From marex at denx.de  Mon Mar 24 16:40:01 2025
From: marex at denx.de (Marek Vasut)
Date: Tue, 25 Mar 2025 00:40:01 +0100
Subject: [PATCH 1/2] dt-bindings: arm: imx: document i.MX 95 Verdin Evaluation Kit (EVK)
Message-ID: <20250324234013.140440-1-marex@denx.de>

Document support for i.MX 95 Verdin Evaluation Kit (EVK), which
used to be the Titan EVK.

Note that the SoM used in this EVK is a derivative SoM from Verdin
line of SoMs, an actual i.MX95 Verdin SoM is under development.

[1] https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95-evaluation-kit

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Alexander Stein <alexander.stein at ew.tq-group.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Francesco Dolcini <francesco.dolcini at toradex.com>
Cc: Frieder Schrempf <frieder.schrempf at kontron.de>
Cc: Hiago De Franco <hiago.franco at toradex.com>
Cc: Joao Goncalves <joao.goncalves at toradex.com>
Cc: Joao Goncalves <jpaulo.silvagoncalves at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Max Merchel <Max.Merchel at ew.tq-group.com>
Cc: Michael Walle <mwalle at kernel.org>
Cc: Peng Fan <peng.fan at nxp.com>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Tim Harvey <tharvey at gateworks.com>
Cc: devicetree at vger.kernel.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 1b90870958a22..30dc200cc1561 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1352,6 +1352,7 @@ properties:
           - enum:
               - fsl,imx95-15x15-evk       # i.MX95 15x15 EVK Board
               - fsl,imx95-19x19-evk       # i.MX95 19x19 EVK Board
+              - toradex,verdin-imx95-19x19-evk  # i.MX95 Verdin Evaluation Kit (EVK)
           - const: fsl,imx95
 
       - description: i.MXRT1050 based Boards
-- 
2.47.2



From marex at denx.de  Mon Mar 24 16:40:02 2025
From: marex at denx.de (Marek Vasut)
Date: Tue, 25 Mar 2025 00:40:02 +0100
Subject: [PATCH 2/2] arm64: dts: freescale: add initial support for i.MX 95 Verdin Evaluation Kit (EVK)
In-Reply-To: <20250324234013.140440-1-marex@denx.de>
References: <20250324234013.140440-1-marex@denx.de>
Message-ID: <20250324234013.140440-2-marex@denx.de>

Add initial support for i.MX 95 Verdin Evaluation Kit (EVK), which
used to be the Titan EVK. Currently supported is lpuart1 as console,
SDHC1/2/3 as storage, WM8904 Audio, USB3.0 and ENETC ethernet RGMII
Gigabit port.

Note that the SoM used in this EVK is a derivative SoM from Verdin
line of SoMs, an actual i.MX95 Verdin SoM is under development.

[1] https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95-evaluation-kit

Signed-off-by: Marek Vasut <marex at denx.de>
---
Cc: Alexander Stein <alexander.stein at ew.tq-group.com>
Cc: Conor Dooley <conor+dt at kernel.org>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Francesco Dolcini <francesco.dolcini at toradex.com>
Cc: Frieder Schrempf <frieder.schrempf at kontron.de>
Cc: Hiago De Franco <hiago.franco at toradex.com>
Cc: Joao Goncalves <joao.goncalves at toradex.com>
Cc: Joao Goncalves <jpaulo.silvagoncalves at gmail.com>
Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
Cc: Max Merchel <Max.Merchel at ew.tq-group.com>
Cc: Michael Walle <mwalle at kernel.org>
Cc: Peng Fan <peng.fan at nxp.com>
Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
Cc: Rob Herring <robh at kernel.org>
Cc: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Tim Harvey <tharvey at gateworks.com>
Cc: devicetree at vger.kernel.org
Cc: imx at lists.linux.dev
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
---
 arch/arm64/boot/dts/freescale/Makefile        |   1 +
 .../dts/freescale/imx95-19x19-verdin-evk.dts  | 697 ++++++++++++++++++
 2 files changed, 698 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx95-19x19-verdin-evk.dts

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index b6d3fe26d6212..e76e3ef863e76 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -303,6 +303,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-verdin-evk.dtb
 
 imx8mm-kontron-dl-dtbs			:= imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
 
diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-verdin-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-verdin-evk.dts
new file mode 100644
index 0000000000000..b34ba23059e1d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-19x19-verdin-evk.dts
@@ -0,0 +1,697 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2023 NXP
+ * Copyright 2025 Marek Vasut <marex at denx.de>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/usb/pd.h>
+#include "imx95.dtsi"
+
+#define FALLING_EDGE			1
+#define RISING_EDGE			2
+
+#define BRD_SM_CTRL_SD3_WAKE		0x8000	/* PCAL6408A-0 */
+#define BRD_SM_CTRL_PCIE1_WAKE		0x8001	/* PCAL6408A-4 */
+#define BRD_SM_CTRL_BT_WAKE		0x8002	/* PCAL6408A-5 */
+#define BRD_SM_CTRL_PCIE2_WAKE		0x8003	/* PCAL6408A-6 */
+#define BRD_SM_CTRL_BUTTON		0x8004	/* PCAL6408A-7 */
+
+/ {
+	model = "i.MX 95 Verdin Evaluation Kit (EVK)";
+	compatible = "toradex,verdin-imx95-19x19-evk",
+		     "fsl,imx95";
+
+	aliases {
+		ethernet0 = &enetc_port0;
+		ethernet1 = &enetc_port1;
+		ethernet2 = &enetc_port2;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		i2c0 = &lpi2c1;
+		i2c1 = &lpi2c2;
+		i2c2 = &lpi2c3;
+		i2c3 = &lpi2c4;
+		i2c4 = &lpi2c5;
+		i2c5 = &lpi2c6;
+		i2c6 = &lpi2c7;
+		i2c7 = &lpi2c8;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		serial0 = &lpuart1;
+	};
+
+	chosen {
+		stdout-path = &lpuart1;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		linux_cma: linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x80000000 0 0x7f000000>;
+			size = <0 0x3c000000>;
+			linux,cma-default;
+			reusable;
+		};
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-max-microvolt = <1800000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-name = "+V1.8_SW";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-name = "+V3.3_SW";
+	};
+
+	reg_m2_pwr: regulator-m2-pwr {
+		compatible = "regulator-fixed";
+		regulator-name = "M.2-power";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio2 4 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_pcie0: regulator-pcie {
+		compatible = "regulator-fixed";
+		regulator-name = "PCIE_WLAN_EN";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&reg_m2_pwr>;
+		gpio = <&i2c7_pcal6524 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usdhc2_vmmc: regulator-usdhc2 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+		regulator-name = "VDD_SD2_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		off-on-delay-us = <12000>;
+	};
+
+	usdhc3_pwrseq: usdhc3-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&i2c7_pcal6524 11 GPIO_ACTIVE_HIGH>;
+	};
+
+	sound-wm8904 {
+		compatible = "fsl,imx-audio-wm8904";
+		model = "wm8904-audio";
+		audio-cpu = <&sai3>;
+		audio-codec = <&wm8904>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"AMIC", "MICBIAS",
+			"IN2L", "AMIC";
+	};
+};
+
+&enetc_port0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enetc0>;
+	phy-handle = <&ethphy0>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&flexspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexspi1>;
+	status = "okay";
+
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flexspi1_reset>;
+		reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <200000000>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+	};
+};
+
+&lpi2c4 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lpi2c4>;
+	status = "okay";
+
+	wm8904: codec at 1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8904";
+		reg = <0x1a>;
+		clocks = <&scmi_clk IMX95_CLK_SAI3>;
+		clock-names = "mclk";
+		AVDD-supply = <&reg_1p8v>;
+		CPVDD-supply = <&reg_1p8v>;
+		DBVDD-supply = <&reg_1p8v>;
+		DCVDD-supply = <&reg_1p8v>;
+		MICVDD-supply = <&reg_1p8v>;
+	};
+};
+
+&lpi2c5 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lpi2c5>;
+	status = "okay";
+};
+
+&lpi2c6 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lpi2c6>;
+	status = "okay";
+};
+
+&lpi2c7 {
+	clock-frequency = <1000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lpi2c7>;
+	status = "okay";
+
+	i2c7_pcal6524: i2c7-gpio at 23 {
+		compatible = "nxp,pcal6524";
+		reg = <0x23>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c7_pcal6524>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	/* Current measurement at SoM 5V power output */
+	hwmon at 41 {
+		compatible = "ti,ina219";
+		reg = <0x41>;
+		shunt-resistor = <10000>;
+	};
+
+	/* Current measurement at Board power input */
+	hwmon at 45 {
+		compatible = "ti,ina219";
+		reg = <0x45>;
+		shunt-resistor = <10000>;
+	};
+
+	eeprom at 50 {
+		compatible = "st,24c02";
+		reg = <0x50>;
+	};
+
+	ptn5110: tcpc at 52 {
+		compatible = "nxp,ptn5110", "tcpci";
+		reg = <0x52>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_typec>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+
+		typec_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			power-role = "dual";
+			data-role = "dual";
+			try-power-role = "sink";
+			source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+			sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
+				     PDO_VAR(5000, 20000, 3000)>;
+			op-sink-microwatt = <15000000>;
+			self-powered;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+
+					typec_con_hs: endpoint {
+						remote-endpoint = <&usb3_data_hs>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+
+					typec_con_ss: endpoint {
+						remote-endpoint = <&usb3_data_ss>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&lpuart1 {
+	/* console */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&mu7 {
+	status = "okay";
+};
+
+&netcmix_blk_ctrl {
+	status = "okay";
+};
+
+&netc_blk_ctrl {
+	status = "okay";
+};
+
+&netc_emdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_emdio>;
+	status = "okay";
+
+	ethphy0: ethernet-phy at 1 {
+		reg = <1>;
+		realtek,clkout-disable;
+	};
+};
+
+&pcie0 {
+	pinctrl-0 = <&pinctrl_pcie0>;
+	pinctrl-names = "default";
+	reset-gpio = <&i2c7_pcal6524 17 GPIO_ACTIVE_LOW>;
+	vpcie-supply = <&reg_pcie0>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-0 = <&pinctrl_pcie1>;
+	pinctrl-names = "default";
+	reset-gpio = <&i2c7_pcal6524 16 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&sai1 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai1>;
+	assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL1>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2>,
+			  <&scmi_clk IMX95_CLK_SAI1>;
+	assigned-clock-parents = <0>, <0>, <0>, <0>,
+				 <&scmi_clk IMX95_CLK_AUDIOPLL1>;
+	assigned-clock-rates = <3932160000>,
+			       <3612672000>, <393216000>,
+			       <361267200>, <12288000>;
+	fsl,sai-mclk-direction-output;
+	status = "okay";
+};
+
+&sai3 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai3>;
+	assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL1>,
+			  <&scmi_clk IMX95_CLK_AUDIOPLL2>,
+			  <&scmi_clk IMX95_CLK_SAI3>;
+	assigned-clock-parents = <0>, <0>, <0>, <0>,
+				 <&scmi_clk IMX95_CLK_AUDIOPLL1>;
+	assigned-clock-rates = <3932160000>,
+			       <3612672000>, <393216000>,
+			       <361267200>, <12288000>;
+	fsl,sai-mclk-direction-output;
+	status = "okay";
+};
+
+&usb3 {
+	status = "okay";
+};
+
+&usb3_dwc3 {
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
+	usb-role-switch;
+	role-switch-default-mode = "peripheral";
+	snps,dis-u1-entry-quirk;
+	snps,dis-u2-entry-quirk;
+	status = "okay";
+
+	port {
+		usb3_data_hs: endpoint {
+			remote-endpoint = <&typec_con_hs>;
+		};
+	};
+};
+
+&usb3_phy {
+	fsl,phy-tx-preemp-amp-tune-microamp = <600>;
+	orientation-switch;
+	status = "okay";
+
+	port {
+		usb3_data_ss: endpoint {
+			remote-endpoint = <&typec_con_ss>;
+		};
+	};
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	pinctrl-3 = <&pinctrl_usdhc1>;
+	bus-width = <8>;
+	non-removable;
+	no-sdio;
+	no-sd;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_usdhc2_vmmc>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	mmc-pwrseq = <&usdhc3_pwrseq>;
+	vmmc-supply = <&reg_pcie0>;
+	bus-width = <4>;
+	keep-power-in-suspend;
+	non-removable;
+	status = "okay";
+};
+
+&scmi_misc {
+	nxp,ctrl-ids = <BRD_SM_CTRL_SD3_WAKE	FALLING_EDGE
+			BRD_SM_CTRL_PCIE1_WAKE	FALLING_EDGE
+			BRD_SM_CTRL_BT_WAKE	FALLING_EDGE
+			BRD_SM_CTRL_PCIE2_WAKE	FALLING_EDGE
+			BRD_SM_CTRL_BUTTON	FALLING_EDGE>;
+};
+
+&wdog3 {
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&scmi_iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_hog: hoggrp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO04__GPIO2_IO_BIT4			0x3fe>;
+	};
+
+	pinctrl_emdio: emdiogrp {
+		fsl,pins =
+			<IMX95_PAD_ENET1_MDC__NETCMIX_TOP_NETC_MDC		0x57e>,
+			<IMX95_PAD_ENET1_MDIO__NETCMIX_TOP_NETC_MDIO		0x97e>;
+	};
+
+	pinctrl_enetc0: enetc0grp {
+		fsl,pins =
+			<IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3	0x57e>,
+			<IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2	0x57e>,
+			<IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1	0x57e>,
+			<IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0	0x57e>,
+			<IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL	0x57e>,
+			<IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK	0x58e>,
+			<IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL	0x57e>,
+			<IMX95_PAD_ENET1_RXC__NETCMIX_TOP_ETH0_RGMII_RX_CLK	0x58e>,
+			<IMX95_PAD_ENET1_RD0__NETCMIX_TOP_ETH0_RGMII_RD0	0x57e>,
+			<IMX95_PAD_ENET1_RD1__NETCMIX_TOP_ETH0_RGMII_RD1	0x57e>,
+			<IMX95_PAD_ENET1_RD2__NETCMIX_TOP_ETH0_RGMII_RD2	0x57e>,
+			<IMX95_PAD_ENET1_RD3__NETCMIX_TOP_ETH0_RGMII_RD3	0x57e>;
+	};
+
+	pinctrl_flexspi1: flexspi1grp {
+		fsl,pins =
+			<IMX95_PAD_XSPI1_SS0_B__FLEXSPI1_A_SS0_B		0x3fe>,
+			<IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK			0x3fe>,
+			<IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS			0x3fe>,
+			<IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA4__FLEXSPI1_A_DATA_BIT4		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA5__FLEXSPI1_A_DATA_BIT5		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA6__FLEXSPI1_A_DATA_BIT6		0x3fe>,
+			<IMX95_PAD_XSPI1_DATA7__FLEXSPI1_A_DATA_BIT7		0x3fe>;
+	};
+
+	pinctrl_flexspi1_reset: flexspi1-reset-grp {
+		fsl,pins =
+			<IMX95_PAD_XSPI1_SS1_B__GPIO5_IO_BIT11			0x3fe>;
+	};
+
+	pinctrl_hp: hpgrp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO11__GPIO2_IO_BIT11			0x31e>;
+	};
+
+	pinctrl_i2c4_pcal6408: i2c4pcal6498grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO18__GPIO2_IO_BIT18			0x31e>;
+	};
+
+	pinctrl_i2c7_pcal6524: i2c7pcal6524grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO36__GPIO5_IO_BIT16			0x31e>;
+	};
+
+	pinctrl_lpi2c4: lpi2c4grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO30__LPI2C4_SDA			0x40000b9e>,
+			<IMX95_PAD_GPIO_IO31__LPI2C4_SCL			0x40000b9e>;
+	};
+
+	pinctrl_lpi2c5: lpi2c5grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO22__LPI2C5_SDA			0x40000b9e>,
+			<IMX95_PAD_GPIO_IO23__LPI2C5_SCL			0x40000b9e>;
+	};
+
+	pinctrl_lpi2c6: lpi2c6grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO02__LPI2C6_SDA			0x40000b9e>,
+			<IMX95_PAD_GPIO_IO03__LPI2C6_SCL			0x40000b9e>;
+	};
+
+	pinctrl_lpi2c7: lpi2c7grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO08__LPI2C7_SDA			0x40000b9e>,
+			<IMX95_PAD_GPIO_IO09__LPI2C7_SCL			0x40000b9e>;
+	};
+
+	pinctrl_pcie0: pcie0grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO32__HSIOMIX_TOP_PCIE1_CLKREQ_B	0x4000031e>;
+	};
+
+	pinctrl_pcie1: pcie1grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO35__HSIOMIX_TOP_PCIE2_CLKREQ_B	0x4000031e>;
+	};
+
+	pinctrl_pcal6416: pcal6416grp {
+		fsl,pins =
+			<IMX95_PAD_CCM_CLKO3__GPIO4_IO_BIT28			0x31e>;
+	};
+
+	pinctrl_pdm: pdmgrp {
+		fsl,pins =
+			<IMX95_PAD_PDM_CLK__AONMIX_TOP_PDM_CLK				0x31e>,
+			<IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_PDM_BIT_STREAM_BIT0	0x31e>;
+	};
+
+	pinctrl_sai1: sai1grp {
+		fsl,pins =
+			<IMX95_PAD_SAI1_RXD0__AONMIX_TOP_SAI1_RX_DATA_BIT0	0x31e>,
+			<IMX95_PAD_SAI1_TXC__AONMIX_TOP_SAI1_TX_BCLK		0x31e>,
+			<IMX95_PAD_SAI1_TXFS__AONMIX_TOP_SAI1_TX_SYNC		0x31e>,
+			<IMX95_PAD_SAI1_TXD0__AONMIX_TOP_SAI1_TX_DATA_BIT0	0x31e>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins =
+			<IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_SAI2_RX_BCLK		0x31e>,
+			<IMX95_PAD_ENET2_MDC__NETCMIX_TOP_SAI2_RX_SYNC		0x31e>,
+			<IMX95_PAD_ENET2_TD3__NETCMIX_TOP_SAI2_RX_DATA_BIT0	0x31e>,
+			<IMX95_PAD_ENET2_TD2__NETCMIX_TOP_SAI2_RX_DATA_BIT1	0x31e>,
+			<IMX95_PAD_ENET2_TXC__NETCMIX_TOP_SAI2_TX_BCLK		0x31e>,
+			<IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_SAI2_TX_SYNC	0x31e>,
+			<IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_SAI2_TX_DATA_BIT0	0x31e>,
+			<IMX95_PAD_ENET2_RXC__NETCMIX_TOP_SAI2_TX_DATA_BIT1	0x31e>,
+			<IMX95_PAD_ENET2_RD0__NETCMIX_TOP_SAI2_TX_DATA_BIT2	0x31e>,
+			<IMX95_PAD_ENET2_RD1__NETCMIX_TOP_SAI2_TX_DATA_BIT3	0x31e>,
+			<IMX95_PAD_ENET2_RD2__NETCMIX_TOP_SAI2_MCLK		0x31e>;
+	};
+
+	pinctrl_sai3: sai3grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO17__SAI3_MCLK			0x31e>,
+			<IMX95_PAD_GPIO_IO16__SAI3_TX_BCLK		0x31e>,
+			<IMX95_PAD_GPIO_IO26__SAI3_TX_SYNC		0x31e>,
+			<IMX95_PAD_GPIO_IO20__SAI3_RX_DATA_BIT0		0x31e>,
+			<IMX95_PAD_GPIO_IO21__SAI3_TX_DATA_BIT0		0x31e>;
+	};
+
+	pinctrl_tpm6: tpm6grp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO19__TPM6_CH2			0x51e>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins =
+			<IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX	0x31e>,
+			<IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX	0x31e>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins =
+			<IMX95_PAD_SD1_CLK__USDHC1_CLK			0x158e>,
+			<IMX95_PAD_SD1_CMD__USDHC1_CMD			0x138e>,
+			<IMX95_PAD_SD1_DATA0__USDHC1_DATA0		0x138e>,
+			<IMX95_PAD_SD1_DATA1__USDHC1_DATA1		0x138e>,
+			<IMX95_PAD_SD1_DATA2__USDHC1_DATA2		0x138e>,
+			<IMX95_PAD_SD1_DATA3__USDHC1_DATA3		0x138e>,
+			<IMX95_PAD_SD1_DATA4__USDHC1_DATA4		0x138e>,
+			<IMX95_PAD_SD1_DATA5__USDHC1_DATA5		0x138e>,
+			<IMX95_PAD_SD1_DATA6__USDHC1_DATA6		0x138e>,
+			<IMX95_PAD_SD1_DATA7__USDHC1_DATA7		0x138e>,
+			<IMX95_PAD_SD1_STROBE__USDHC1_STROBE		0x158e>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+		fsl,pins =
+			<IMX95_PAD_SD1_CLK__USDHC1_CLK			0x158e>,
+			<IMX95_PAD_SD1_CMD__USDHC1_CMD			0x138e>,
+			<IMX95_PAD_SD1_DATA0__USDHC1_DATA0		0x138e>,
+			<IMX95_PAD_SD1_DATA1__USDHC1_DATA1		0x138e>,
+			<IMX95_PAD_SD1_DATA2__USDHC1_DATA2		0x138e>,
+			<IMX95_PAD_SD1_DATA3__USDHC1_DATA3		0x138e>,
+			<IMX95_PAD_SD1_DATA4__USDHC1_DATA4		0x138e>,
+			<IMX95_PAD_SD1_DATA5__USDHC1_DATA5		0x138e>,
+			<IMX95_PAD_SD1_DATA6__USDHC1_DATA6		0x138e>,
+			<IMX95_PAD_SD1_DATA7__USDHC1_DATA7		0x138e>,
+			<IMX95_PAD_SD1_STROBE__USDHC1_STROBE		0x158e>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+		fsl,pins =
+			<IMX95_PAD_SD1_CLK__USDHC1_CLK			0x15fe>,
+			<IMX95_PAD_SD1_CMD__USDHC1_CMD			0x13fe>,
+			<IMX95_PAD_SD1_DATA0__USDHC1_DATA0		0x13fe>,
+			<IMX95_PAD_SD1_DATA1__USDHC1_DATA1		0x13fe>,
+			<IMX95_PAD_SD1_DATA2__USDHC1_DATA2		0x13fe>,
+			<IMX95_PAD_SD1_DATA3__USDHC1_DATA3		0x13fe>,
+			<IMX95_PAD_SD1_DATA4__USDHC1_DATA4		0x13fe>,
+			<IMX95_PAD_SD1_DATA5__USDHC1_DATA5		0x13fe>,
+			<IMX95_PAD_SD1_DATA6__USDHC1_DATA6		0x13fe>,
+			<IMX95_PAD_SD1_DATA7__USDHC1_DATA7		0x13fe>,
+			<IMX95_PAD_SD1_STROBE__USDHC1_STROBE		0x15fe>;
+	};
+
+	pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
+		fsl,pins =
+			<IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7		0x31e>;
+	};
+
+	pinctrl_typec: typecgrp {
+		fsl,pins =
+			<IMX95_PAD_GPIO_IO34__GPIO5_IO_BIT14		0x31e>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+		fsl,pins =
+			<IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0		0x31e>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins =
+			<IMX95_PAD_SD2_CLK__USDHC2_CLK			0x158e>,
+			<IMX95_PAD_SD2_CMD__USDHC2_CMD			0x138e>,
+			<IMX95_PAD_SD2_DATA0__USDHC2_DATA0		0x138e>,
+			<IMX95_PAD_SD2_DATA1__USDHC2_DATA1		0x138e>,
+			<IMX95_PAD_SD2_DATA2__USDHC2_DATA2		0x138e>,
+			<IMX95_PAD_SD2_DATA3__USDHC2_DATA3		0x138e>,
+			<IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins =
+			<IMX95_PAD_SD2_CLK__USDHC2_CLK			0x158e>,
+			<IMX95_PAD_SD2_CMD__USDHC2_CMD			0x138e>,
+			<IMX95_PAD_SD2_DATA0__USDHC2_DATA0		0x138e>,
+			<IMX95_PAD_SD2_DATA1__USDHC2_DATA1		0x138e>,
+			<IMX95_PAD_SD2_DATA2__USDHC2_DATA2		0x138e>,
+			<IMX95_PAD_SD2_DATA3__USDHC2_DATA3		0x138e>,
+			<IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins =
+			<IMX95_PAD_SD2_CLK__USDHC2_CLK			0x15fe>,
+			<IMX95_PAD_SD2_CMD__USDHC2_CMD			0x13fe>,
+			<IMX95_PAD_SD2_DATA0__USDHC2_DATA0		0x13fe>,
+			<IMX95_PAD_SD2_DATA1__USDHC2_DATA1		0x13fe>,
+			<IMX95_PAD_SD2_DATA2__USDHC2_DATA2		0x13fe>,
+			<IMX95_PAD_SD2_DATA3__USDHC2_DATA3		0x13fe>,
+			<IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins =
+			<IMX95_PAD_SD3_CLK__USDHC3_CLK			0x158e>,
+			<IMX95_PAD_SD3_CMD__USDHC3_CMD			0x138e>,
+			<IMX95_PAD_SD3_DATA0__USDHC3_DATA0		0x138e>,
+			<IMX95_PAD_SD3_DATA1__USDHC3_DATA1		0x138e>,
+			<IMX95_PAD_SD3_DATA2__USDHC3_DATA2		0x138e>,
+			<IMX95_PAD_SD3_DATA3__USDHC3_DATA3		0x138e>;
+	};
+};
-- 
2.47.2



From marex at denx.de  Mon Mar 24 16:35:41 2025
From: marex at denx.de (Marek Vasut)
Date: Tue, 25 Mar 2025 00:35:41 +0100
Subject: [PATCH v2 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <6144881.lOV4Wx5bFT@steina-w>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-10-marex@denx.de> <6144881.lOV4Wx5bFT@steina-w>
Message-ID: <e8e9f36a-6d05-425e-a0e5-89689424336d@denx.de>

On 3/24/25 8:02 AM, Alexander Stein wrote:

Hi,

>> @@ -1890,6 +1919,35 @@ netc_emdio: mdio at 0,0 {
>>   			};
>>   		};
>>   
>> +		gpu_blk_ctrl: reset-controller at 4d810000 {
>> +			compatible = "nxp,imx95-gpu-blk-ctrl";
>> +			reg = <0x0 0x4d810000 0x0 0xc>;
>> +			#reset-cells = <1>;
>> +			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
>> +			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
>> +			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
>> +			assigned-clock-rates = <133333333>;
>> +			power-domains = <&scmi_devpd IMX95_PD_GPU>;
>> +		};
> 
> With the SM release lf-6.12.3-1.0.0 AP does not have any access to
> this BLK_CTRL anymore. See [1]
I just built SM 6.12 and it still requires the reset, without reset I 
cannot use the GPU ... or ... which BLK CTRL do you refer to ?


From marex at denx.de  Mon Mar 24 16:37:59 2025
From: marex at denx.de (Marek Vasut)
Date: Tue, 25 Mar 2025 00:37:59 +0100
Subject: [PATCH v2 4/9] drm/panthor: Implement optional reset
In-Reply-To: <20250324094333.7afb17a1@collabora.com>
References: <20250321200625.132494-1-marex@denx.de>
 <20250321200625.132494-5-marex@denx.de>
 <20250324094333.7afb17a1@collabora.com>
Message-ID: <c1de2afb-3559-4fbb-b13b-2373175b420b@denx.de>

On 3/24/25 9:43 AM, Boris Brezillon wrote:

[...]

>> @@ -563,6 +585,7 @@ int panthor_device_suspend(struct device *dev)
>>   
>>   	panthor_devfreq_suspend(ptdev);
>>   
>> +	reset_control_assert(ptdev->resets);
> 
> Hm, that might be the cause of the fast reset issue (which is a fast
> resume more than a fast reset BTW): if you re-assert the reset line on
> runtime suspend, I guess this causes a full GPU reset, and the MCU ends
> up in a state where it needs a slow reset (all data sections reset to
> their initial state). Can you try to move the reset_control_[de]assert
> to the unplug/init functions?
Is it correct to assume , that if I remove all reset_control_assert() 
calls (and keep only the _deassert() calls), the slow resume problem 
should go away too ?


From andrew at codeconstruct.com.au  Mon Mar 24 16:59:06 2025
From: andrew at codeconstruct.com.au (Andrew Jeffery)
Date: Tue, 25 Mar 2025 10:29:06 +1030
Subject: [PATCH v6 00/10] ARM: dts: aspeed: catalina: Update DTS to
 support Catalina PVT hardware
In-Reply-To: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
References: <20250321-potin-catalina-dts-update-20250102-v6-0-4bd85efeb9b4@gmail.com>
Message-ID: <174286074647.923686.7149650911621706997.b4-ty@codeconstruct.com.au>

On Fri, 21 Mar 2025 15:26:01 +0800, Potin Lai wrote:
> Update the DTS file for the Catalina platform based on the PVT hardware
> changes.
> 
> 

Thanks, I've applied this to be picked up through the BMC tree.

--
Andrew Jeffery <andrew at codeconstruct.com.au>



From changyuanl at google.com  Mon Mar 24 17:21:45 2025
From: changyuanl at google.com (Changyuan Lyu)
Date: Mon, 24 Mar 2025 17:21:45 -0700
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation helpers
In-Reply-To: <Z+GIRecXeYXiPrYv@nvidia.com>
References: <Z+GIRecXeYXiPrYv@nvidia.com>
Message-ID: <20250325002145.982402-1-changyuanl@google.com>

Hi Jason,

On Mon, Mar 24, 2025 at 13:28:53 -0300, Jason Gunthorpe <jgg at nvidia.com> wrote:
> [...]
> > > I feel like this patch is premature, it should come later in the
> > > project along with a stronger justification for this approach.
> > >
> > > IHMO keep things simple for this series, just the very basics.
> >
> > The main purpose of using hashtables is to enable KHO users to save
> > data to KHO at any time, not just at the time of activate/finalize KHO
> > through sysfs/debugfs. For example, FDBox can save the data into KHO
> > tree once a new fd is saved to KHO. Also, using hashtables allows KHO
> > users to add data to KHO concurrently, while with notifiers, KHO users'
> > callbacks are executed serially.
>
> This is why I like the recursive FDT scheme. Each serialization
> operation can open its own FDT write to it and the close it
> sequenatially within its operation without any worries about
> concurrency.
>
> The top level just aggregates the FDT blobs (which are in preserved
> memory)
>
> To me all this complexity here with the hash table and the copying
> makes no sense compared to that. It is all around slower.
>
> > Regarding the suggestion of recursive FDT, I feel like it is already
> > doable with this patchset, or even with Mike's V4 patch.
>
> Of course it is doable, here we are really talk about what is the
> right, recommended way to use this system. recurisive FDT is a better
> methodology than hash tables
>
> > just allocates a buffer, serialize all its states to the buffer using
> > libfdt (or even using other binary formats), save the address of the
> > buffer to KHO's tree, and finally register the buffer's underlying
> > pages/folios with kho_preserve_folio().
>
> Yes, exactly! I think this is how we should operate this system as a
> paradig, not a giant FDT, hash table and so on...
>
> [...]
> > To completely remove fdt_max, I am considering the idea in [1]. At the
> > time of kexec_file_load(), we pass the address of an anchor page to
> > the new kernel, and the anchor page will later be fulfilled with the
> > physical addresses of the pages containing the FDT blob. Multiple
> > anchor pages can be linked together. The FDT blob pages can be physically
> > noncontiguous.
>
> Yes, this is basically what I suggested too. I think this is much
> prefered and doesn't require the wakky uapi.
>
> Except I suggested you just really need a single u64 to point to a
> preserved page holding the top level FDT.
>
> With recursive FDT I think we can say that no FDT fragement should
> exceed PAGE_SIZE, and things become much simpler, IMHO.

Thanks for the suggestions! I am a little bit concerned about assuming
every FDT fragment is smaller than PAGE_SIZE. In case a child FDT is
larger than PAGE_SIZE, I would like to turn the single u64 in the parent
FDT into a u64 list to record all the underlying pages of the child FDT.

To be concrete and make sure I understand your suggestions correctly,
I drafted the following design,

Suppose we have 2 KHO users, memblock and gpu at 0x2000000000, the KHO
FDT (top level FDT) would look like the following,

    /dts-v1/;
    / {
            compatible = "kho-v1";
            memblock {
                    kho,recursive-fdt = <0x00 0x40001000>;
            };
            gpu at 0x100000000 {
                    kho,recursive-fdt = <0x00 0x40002000>;
            };
    };

kho,recursive-fdt in "memblock" points to a page containing another
FDT,

    / {
            compatible = "memblock-v1";
            n1 {
                    compatible = "reserve-mem-v1";
                    size = <0x04 0x00>;
                    start = <0xc06b 0x4000000>;
            };
            n2 {
                    compatible = "reserve-mem-v1";
                    size = <0x04 0x00>;
                    start = <0xc067 0x4000000>;
            };
    };

Similarly, "kho,recursive-fdt" in "gpu at 0x2000000000" points to a page
containing another FDT,

    / {
            compatible = "gpu-v1"
            key1 = "v1";
            key2 = "v2";

            node1 {
                    kho,recursive-fdt = <0x00 0x40003000 0x00 0x40005000>;
            }
            node2 {
                    key3 = "v3";
                    key4 = "v4";
            }
    }

and kho,recursive-fdt in "node1" contains 2 non-contagious pages backing
the following large FDT fragment,

    / {
            compatible = "gpu-subnode1-v1";

            key5 = "v5";
            key6 = "v6";
            key7 = "v7";
            key8 = "v8";
            ... // many many keys and small values
    }

In this way we assume that most FDT fragment is smaller than 1 page so
"kho,recursive-fdt" is usually just 1 u64, but we can also handle
larger fragments if that really happens.

I also allow KHO users to add sub nodes in-place, instead of forcing
to create a new FDT fragment for every sub node, if the KHO user is
confident that those subnodes are small enough to fit in the parent
node's page. In this way we do not need to waste a full page for a small
sub node. An example is the "memblock" node above.

Finally, the KHO top level FDT may also be larger than 1 page, this can
be handled using the anchor-page method discussed in the previous mails.

What do you think?

Best,
Changyuan


From dyoung at redhat.com  Mon Mar 24 18:24:02 2025
From: dyoung at redhat.com (Dave Young)
Date: Tue, 25 Mar 2025 09:24:02 +0800
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <CA+CK2bC4PM0JnHOUm7qfpQ=wUhwsYQ-hJ12tTK_7pSWgYk+bhg@mail.gmail.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com> <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
 <CA+CK2bC4PM0JnHOUm7qfpQ=wUhwsYQ-hJ12tTK_7pSWgYk+bhg@mail.gmail.com>
Message-ID: <CALu+AoRL+oHW2vN8nf1wpsG2Ki8d44AABQRCBMd+CE4_XzqRTw@mail.gmail.com>

On Tue, 25 Mar 2025 at 03:27, Pasha Tatashin <pasha.tatashin at soleen.com> wrote:
>
> On Mon, Mar 24, 2025 at 12:18?AM Dave Young <dyoung at redhat.com> wrote:
> >
> > On Thu, 20 Mar 2025 at 23:05, Changyuan Lyu <changyuanl at google.com> wrote:
> > >
> > > From: Alexander Graf <graf at amazon.com>
> > >
> > > We have all generic code in place now to support Kexec with KHO. This
> > > patch adds a config option that depends on architecture support to
> > > enable KHO support.
> > >
> > > Signed-off-by: Alexander Graf <graf at amazon.com>
> > > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> > > ---
> > >  kernel/Kconfig.kexec | 15 +++++++++++++++
> > >  1 file changed, 15 insertions(+)
> > >
> > > diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> > > index 4d111f871951..57db99e758a8 100644
> > > --- a/kernel/Kconfig.kexec
> > > +++ b/kernel/Kconfig.kexec
> > > @@ -95,6 +95,21 @@ config KEXEC_JUMP
> > >           Jump between original kernel and kexeced kernel and invoke
> > >           code in physical address mode via KEXEC
> > >
> > > +config KEXEC_HANDOVER
> > > +       bool "kexec handover"
> > > +       depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
> > > +       select MEMBLOCK_KHO_SCRATCH
> > > +       select KEXEC_FILE
> > > +       select DEBUG_FS
> > > +       select LIBFDT
> > > +       select CMA
> > > +       select XXHASH
> > > +       help
> > > +         Allow kexec to hand over state across kernels by generating and
> > > +         passing additional metadata to the target kernel. This is useful
> > > +         to keep data or state alive across the kexec. For this to work,
> > > +         both source and target kernels need to have this option enabled.
> > > +
> >
> > Have you tested kdump?  In my mind there are two issues,  one is with
> > CMA enabled, it could cause kdump crashkernel memory reservation
> > failures more often due to the fragmented low memory.  Secondly,  in
>
> As I understand cma low memory scratch reservation is needed only to
> support some legacy pci devices that cannot use the full 64-bit space.
> If so, I am not sure if KHO needs to be supported on machines with
> such devices. However, even if we keep it, it should really be small,
> so I would not expect that to be a problem for crash kernel memory
> reservation.

It is not easy to estimate how much of the KHO reserved memory is
needed.  I assume this as a mechanism for all different users, it is
not  predictable.  Also it is not only about the size, but also it
makes the memory fragmented.

>
> > kdump kernel dump the crazy scratch memory in vmcore is not very
> > meaningful.  Otherwise I suspect this is not tested under kdump.  If
> > so please disable this option for kdump.
>
> The scratch memory will appear as regular CMA in the vmcore. The crash
> kernel can be kexec loaded only from userland, long after the scratch
> memory is converted to CMA.

Depending on the reserved size, if big enough it should be excluded in
vmcore dumping.
Otherwise if it is a kdump kernel it should skip the handling of the
KHO passed previous old states.

>
> Pasha
>



From pcc at google.com  Mon Mar 24 18:56:14 2025
From: pcc at google.com (Peter Collingbourne)
Date: Mon, 24 Mar 2025 18:56:14 -0700
Subject: [PATCH v3 1/2] string: Add load_unaligned_zeropad() code path to sized_strscpy()
In-Reply-To: <20250325015617.23455-1-pcc@google.com>
References: <20250325015617.23455-1-pcc@google.com>
Message-ID: <20250325015617.23455-2-pcc@google.com>

The call to read_word_at_a_time() in sized_strscpy() is problematic
with MTE because it may trigger a tag check fault when reading
across a tag granule (16 bytes) boundary. To make this code
MTE compatible, let's start using load_unaligned_zeropad()
on architectures where it is available (i.e. architectures that
define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad()
takes care of page boundaries as well as tag granule boundaries,
also disable the code preventing crossing page boundaries when using
load_unaligned_zeropad().

Signed-off-by: Peter Collingbourne <pcc at google.com>
Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548
Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS")
Cc: stable at vger.kernel.org
---
v2:
- new approach

 lib/string.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/string.c b/lib/string.c
index eb4486ed40d25..b632c71df1a50 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -119,6 +119,7 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
 		return -E2BIG;
 
+#ifndef CONFIG_DCACHE_WORD_ACCESS
 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 	/*
 	 * If src is unaligned, don't cross a page boundary,
@@ -133,12 +134,14 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	/* If src or dest is unaligned, don't do word-at-a-time. */
 	if (((long) dest | (long) src) & (sizeof(long) - 1))
 		max = 0;
+#endif
 #endif
 
 	/*
-	 * read_word_at_a_time() below may read uninitialized bytes after the
-	 * trailing zero and use them in comparisons. Disable this optimization
-	 * under KMSAN to prevent false positive reports.
+	 * load_unaligned_zeropad() or read_word_at_a_time() below may read
+	 * uninitialized bytes after the trailing zero and use them in
+	 * comparisons. Disable this optimization under KMSAN to prevent
+	 * false positive reports.
 	 */
 	if (IS_ENABLED(CONFIG_KMSAN))
 		max = 0;
@@ -146,7 +149,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	while (max >= sizeof(unsigned long)) {
 		unsigned long c, data;
 
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+		c = load_unaligned_zeropad(src+res);
+#else
 		c = read_word_at_a_time(src+res);
+#endif
 		if (has_zero(c, &data, &constants)) {
 			data = prep_zero_mask(c, data, &constants);
 			data = create_zero_mask(data);
-- 
2.49.0.395.g12beb8f557-goog



From pcc at google.com  Mon Mar 24 18:56:13 2025
From: pcc at google.com (Peter Collingbourne)
Date: Mon, 24 Mar 2025 18:56:13 -0700
Subject: [PATCH v3 0/2] string: Add load_unaligned_zeropad() code path to sized_strscpy()
Message-ID: <20250325015617.23455-1-pcc@google.com>

This series fixes an issue where strscpy() would sometimes trigger
a false positive KASAN report with MTE.

v3:
- simplify test case

Peter Collingbourne (1):
  string: Add load_unaligned_zeropad() code path to sized_strscpy()

Vincenzo Frascino (1):
  kasan: Add strscpy() test to trigger tag fault on arm64

 lib/string.c            | 13 ++++++++++---
 mm/kasan/kasan_test_c.c | 13 +++++++++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

-- 
2.49.0.395.g12beb8f557-goog



From pcc at google.com  Mon Mar 24 18:56:15 2025
From: pcc at google.com (Peter Collingbourne)
Date: Mon, 24 Mar 2025 18:56:15 -0700
Subject: [PATCH v3 2/2] kasan: Add strscpy() test to trigger tag fault on arm64
In-Reply-To: <20250325015617.23455-1-pcc@google.com>
References: <20250325015617.23455-1-pcc@google.com>
Message-ID: <20250325015617.23455-3-pcc@google.com>

From: Vincenzo Frascino <vincenzo.frascino at arm.com>

When we invoke strscpy() with a maximum size of N bytes, it assumes
that:
- It can always read N bytes from the source.
- It always write N bytes (zero-padded) to the destination.

On aarch64 with Memory Tagging Extension enabled if we pass an N that is
bigger then the source buffer, it triggers an MTE fault.

Implement a KASAN KUnit test that triggers the issue with the current
implementation of read_word_at_a_time() on aarch64 with MTE enabled.

Cc: Will Deacon <will at kernel.org>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
Co-developed-by: Peter Collingbourne <pcc at google.com>
Signed-off-by: Peter Collingbourne <pcc at google.com>
Link: https://linux-review.googlesource.com/id/If88e396b9e7c058c1a4b5a252274120e77b1898a
---
v3:
- simplify test case

v2:
- rebased
- fixed test failure

 mm/kasan/kasan_test_c.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
index 59d673400085f..b69f66b7eda1d 100644
--- a/mm/kasan/kasan_test_c.c
+++ b/mm/kasan/kasan_test_c.c
@@ -1570,6 +1570,7 @@ static void kasan_memcmp(struct kunit *test)
 static void kasan_strings(struct kunit *test)
 {
 	char *ptr;
+	char *src;
 	size_t size = 24;
 
 	/*
@@ -1581,6 +1582,18 @@ static void kasan_strings(struct kunit *test)
 	ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
 
+	src = kmalloc(KASAN_GRANULE_SIZE, GFP_KERNEL | __GFP_ZERO);
+	strscpy(src, "f0cacc1a0000000", KASAN_GRANULE_SIZE);
+
+	/*
+	 * The expected size does not include the terminator '\0'
+	 * so it is (KASAN_GRANULE_SIZE - 2) ==
+	 * KASAN_GRANULE_SIZE - ("initial removed character" + "\0").
+	 */
+	KUNIT_EXPECT_EQ(test, KASAN_GRANULE_SIZE - 2,
+			strscpy(ptr, src + 1, KASAN_GRANULE_SIZE));
+
+	kfree(src);
 	kfree(ptr);
 
 	/*
-- 
2.49.0.395.g12beb8f557-goog



From jgg at nvidia.com  Mon Mar 24 19:04:01 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 24 Mar 2025 23:04:01 -0300
Subject: [PATCH v5 09/16] kexec: enable KHO support for memory
 preservation
In-Reply-To: <20250323190758.743798-1-changyuanl@google.com>
References: <20250321134629.GA252045@nvidia.com>
 <20250323190758.743798-1-changyuanl@google.com>
Message-ID: <Z+IPEeg7jkjrIB+8@nvidia.com>

On Sun, Mar 23, 2025 at 12:07:58PM -0700, Changyuan Lyu wrote:

> > > +	down_read(&kho_out.tree_lock);
> > > +	if (kho_out.fdt) {
> >
> > What is the lock and fdt test for?
> 
> It is to avoid the competition between the following 2 operations,
> - converting the hashtables and mem traker to FDT,
> - adding new data to hashtable/mem tracker.

I think you should strive to prevent this by code construction at a
higher level.

Do not lock each preserve but lock entire object serializations, operations.

For instance if we do recursive FDT then you'd lock the call that
builds a single FDT page for a single object.

> In most cases we only need read lock. Different KHO users can adding
> data into their own subnodes in parallel.

read locks like this are still quite slow in parallel systems, there
is alot of slow cacheline bouncing as taking a read lock still has to
write to the lock memory.

> > What do you imagine this is used for? I'm not sure what value there is
> > in returning a void *? How does the caller "free" this?
> 
> This function is also from Mike :)
> 
> I suppose some KHO users may still
> preserve memory using memory ranges (instead of folio).

I don't know what that would be, but the folio scheme is all about
preserving memory from the page buddy allocator, I don't know what
this is for or how it would be used.

IMHO split this to its own patch and include it in the series that
would use it.

> I guess the caller can free the ranges by free_pages()?

The folios were not setup right, so no.. And if this is the case then
you'd just get the struct page and convert it to a void * with some
helper function, not implement a whole new function...

> > There should be yaml files just like in the normal DT case defining
> > all of this. This level of documentation and stability was one of the
> > selling reasons why FDT is being used here!
> 
> YAML files were dropped because we think it may take a while for our
> schema to be near stable. So we start from some simple plain text. We
> can add some prop and node docs (that are considered stable at this point)
> back to YAML in the next version.

You need to do something to document what is going on here and show
the full schema with some explanation. It is hard to grasp the full
intention just from the C code.

Jason


From jgg at nvidia.com  Mon Mar 24 19:20:51 2025
From: jgg at nvidia.com (Jason Gunthorpe)
Date: Mon, 24 Mar 2025 23:20:51 -0300
Subject: [PATCH v5 07/16] kexec: add Kexec HandOver (KHO) generation
 helpers
In-Reply-To: <20250325002145.982402-1-changyuanl@google.com>
References: <Z+GIRecXeYXiPrYv@nvidia.com>
 <20250325002145.982402-1-changyuanl@google.com>
Message-ID: <Z+ITA48uRCpMkvGV@nvidia.com>

On Mon, Mar 24, 2025 at 05:21:45PM -0700, Changyuan Lyu wrote:

> Thanks for the suggestions! I am a little bit concerned about assuming
> every FDT fragment is smaller than PAGE_SIZE. In case a child FDT is
> larger than PAGE_SIZE, I would like to turn the single u64 in the parent
> FDT into a u64 list to record all the underlying pages of the child FDT.

Maybe, but I'd suggest leaving some accomodation for this in the API
but not implement it until we see proof it is needed. 4k is alot of
space for a FDT, and if you are doing per-object FDT I don't see
exceeding it.

For instance a vfio, memfd, and iommufd object FDTs would not get
close.

> In this way we assume that most FDT fragment is smaller than 1 page so
> "kho,recursive-fdt" is usually just 1 u64, but we can also handle
> larger fragments if that really happens.

Yes, this is close to what I imagine.

You have to decide if the child FDT top pointers will be stored
directly in parent FDTs like you sketched above, or if they should be
stored in some dedicated allocated and preserved datastructure, like
the memory preservation works. There are some tradeoffs in each
direction..

> I also allow KHO users to add sub nodes in-place, instead of forcing
> to create a new FDT fragment for every sub node, if the KHO user is
> confident that those subnodes are small enough to fit in the parent
> node's page. In this way we do not need to waste a full page for a small
> sub node. An example is the "memblock" node above.

Well, I think that sort of misses the bigger picture. What we want is
to run serialization of everything in parallel. So merging like you
say will complicate that.

Really, I think we will have on the order of 10's of objects to
serialize so I don't really care if they use partial pages if that
makes the serialization faster. As long as the memory is freed once
the live update is done, the waste doesn't matter.

> Finally, the KHO top level FDT may also be larger than 1 page, this can
> be handled using the anchor-page method discussed in the previous mails.

This is one of the trade offs I mentioned. If you inline the objects
as FDT nodes then you have to scale and multi-page a FDT.

If you do a binary-structure like memory preservation then you have to
serialize to something that is inherently scalable and 4k granular.

The 4k FDT limit really only works if you make liberal use of pointers
to binary data. Anything that is not of a predictable size limit would
be in some related binary structure.

So.. I'd probably suggest to think about how to make multi-page FDT
work in the memory description, but not implement it now. When we
reach the point where we know we need multi-page FDT then someone
would have to implement a growable FDT through vmap or something like
that to make it work.

Keep this intial step simple, we clearly don't need more than 4k FDT
at this point and we aren't doing stable kexec-ABI either. So simplify
simplify simplify to get a very thin minimal functionality merged to
put the fdbox step on top of.

Jason


From robh at kernel.org  Mon Mar 24 19:49:46 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 21:49:46 -0500
Subject: [PATCH 3/5] dt-bindings: arm: rockchip: Add Radxa ROCK 5B+
In-Reply-To: <20250324-rock5bp-for-upstream-v1-3-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
 <20250324-rock5bp-for-upstream-v1-3-6217edf15b19@kernel.org>
Message-ID: <20250325024946.GA1544352-robh@kernel.org>

On Mon, Mar 24, 2025 at 06:04:24PM +0100, Sebastian Reichel wrote:
> The Radxa ROCK 5B+ is an improved version of the ROCK 5B.
> 
> Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
> ---
>  Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++
>  1 file changed, 5 insertions(+)

Same patch has already been acked here:

https://lore.kernel.org/all/20241226005845.46473-1-naoki at radxa.com/

> 
> diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
> index 650fb833d96ef67ea1bba33c0767777378a38fa7..fe1fe8fe52fa3594a0da8e0263cb46949436a021 100644
> --- a/Documentation/devicetree/bindings/arm/rockchip.yaml
> +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
> @@ -946,6 +946,11 @@ properties:
>            - const: radxa,rock-5b
>            - const: rockchip,rk3588
>  
> +      - description: Radxa ROCK 5B+
> +        items:
> +          - const: radxa,rock-5b-plus
> +          - const: rockchip,rk3588
> +
>        - description: Radxa ROCK 5C
>          items:
>            - const: radxa,rock-5c
> 
> -- 
> 2.47.2
> 


From ck.hu at mediatek.com  Mon Mar 24 19:57:16 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Tue, 25 Mar 2025 02:57:16 +0000
Subject: [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and
 export to public
In-Reply-To: <20250321093435.94835-10-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-10-paul-pl.chen@mediatek.com>
Message-ID: <da55e0ef9165d18a7af96fb9e2c2d6c2b47c0f1b.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> Refine OVL format convert API and export to public.
> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 158 ++++++++++++++++--------
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  16 +++
>  2 files changed, 122 insertions(+), 52 deletions(-)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index d0581c4e3c99..e2b125a717c6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -18,6 +18,7 @@
>  #include "mtk_crtc.h"
>  #include "mtk_ddp_comp.h"
>  #include "mtk_disp_drv.h"
> +#include "mtk_disp_ovl.h"
>  #include "mtk_drm_drv.h"
>  
>  #define DISP_REG_OVL_INTEN			0x0004
> @@ -62,22 +63,15 @@
>  /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
>  #define OVL_CON_RGB_SWAP	BIT(25)
>  
> -#define OVL_CON_CLRFMT_RGB	(1 << 12)
> -#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
> -#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
> -#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_UYVY	(4 << 12)
> -#define OVL_CON_CLRFMT_YUYV	(5 << 12)
> -#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
> -#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
> -#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
> -#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					0 : OVL_CON_CLRFMT_RGB)
> -#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					OVL_CON_CLRFMT_RGB : 0)
> +#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
> +#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
> +#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
> +#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
> +#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
> +#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
> +#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
> +#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
> +
>  #define	OVL_CON_AEN		BIT(8)
>  #define	OVL_CON_ALPHA		0xff
>  #define	OVL_CON_VIRT_FLIP	BIT(9)
> @@ -85,7 +79,7 @@
>  
>  #define OVL_COLOR_ALPHA		GENMASK(31, 24)
>  
> -static inline bool is_10bit_rgb(u32 fmt)
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
>  {
>  	switch (fmt) {
>  	case DRM_FORMAT_XRGB2101010:
> @@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
>  	if (!ovl->data->supports_clrfmt_ext)
>  		return;
>  
> -	if (is_10bit_rgb(format))
> +	if (mtk_ovl_is_10bit_rgb(format))
>  		bit_depth = OVL_CON_CLRFMT_10_BIT;
>  
>  	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
> @@ -394,10 +388,26 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
>  		      DISP_REG_OVL_RDMA_CTRL(idx));
>  }
>  
> -static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> -					struct mtk_plane_state *state)
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
> +{

This modification is not related to the title, so separate to another patch.

> +	if (!state->base.fb)
> +		return false;
> +
> +	/*
> +	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> +	 * for XRGB format, otherwise OVL will still read the value from memory.
> +	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> +	 * affect the result. Therefore we use !has_alpha as the condition.
> +	 */
> +
> +	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> +		return true;
> +
> +	return false;
> +}
> +
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
>  {
> -	unsigned int fmt = state->pending.format;
>  	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
>  
>  	/*
> @@ -412,52 +422,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
>  	 * will get an error return from drm_plane_create_blend_mode_property() and
>  	 * state->base.pixel_blend_mode should not be used.
>  	 */
> -	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> +	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
>  		blend_mode = state->base.pixel_blend_mode;
>  
> +	return blend_mode;
> +}
> +
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
> +{
> +	unsigned int con = 0;
> +	bool need_byte_swap = false, need_rgb_swap = false;
> +
>  	switch (fmt) {
>  	default:
>  	case DRM_FORMAT_RGB565:
> -		return OVL_CON_CLRFMT_RGB565(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR565:
> -		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB565 -> BGR565 */
> +	break;
>  	case DRM_FORMAT_RGB888:
> -		return OVL_CON_CLRFMT_RGB888(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR888:
> -		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB888 -> BGR888 */
> +	break;
>  	case DRM_FORMAT_RGBX8888:
>  	case DRM_FORMAT_RGBA8888:
>  	case DRM_FORMAT_RGBX1010102:
>  	case DRM_FORMAT_RGBA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_RGBA8888 :
> -		       OVL_CON_CLRFMT_PRGBA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_BGRX8888:
>  	case DRM_FORMAT_BGRA8888:
>  	case DRM_FORMAT_BGRX1010102:
>  	case DRM_FORMAT_BGRA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_BGRA8888 :
> -		       OVL_CON_CLRFMT_PBGRA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_XRGB8888:
>  	case DRM_FORMAT_ARGB8888:
>  	case DRM_FORMAT_XRGB2101010:
>  	case DRM_FORMAT_ARGB2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ARGB8888 :
> -		       OVL_CON_CLRFMT_PARGB8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +		else
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +	break;
>  	case DRM_FORMAT_XBGR8888:
>  	case DRM_FORMAT_ABGR8888:
>  	case DRM_FORMAT_XBGR2101010:
>  	case DRM_FORMAT_ABGR2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ABGR8888 :
> -		       OVL_CON_CLRFMT_PABGR8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_UYVY:
> -		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_YUYV:
> -		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
> +	break;
>  	}
> +
> +	if (color_convert)
> +		con |= OVL_CON_MTX_YUV_TO_RGB;

Only YUV need this. RGB do not need this.

> +
> +	if (need_byte_swap)
> +		con |= byte_swap;
> +
> +	if (need_rgb_swap)
> +		con |= rgb_swap;
> +
> +	return con;
>  }
>  
>  static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
> @@ -495,7 +555,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  	unsigned int rotation = pending->rotation;
>  	unsigned int offset = (pending->y << 16) | pending->x;
>  	unsigned int src_size = (pending->height << 16) | pending->width;
> -	unsigned int blend_mode = state->base.pixel_blend_mode;
> +	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);

This modification is not related to the title, so separate to another patch.

>  	unsigned int ignore_pixel_alpha = 0;
>  	unsigned int con;
>  
> @@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		return;
>  	}
>  
> -	con = mtk_ovl_fmt_convert(ovl, state);
> +	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
> +				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
>  	if (state->base.fb) {
>  		con |= state->base.alpha & OVL_CON_ALPHA;
>  
> @@ -512,17 +573,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		 * For blend_modes supported SoCs, always enable alpha blending.
>  		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
>  		 */
> -		if (blend_mode || state->base.fb->format->has_alpha)
> +		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)

This modification is not related to the title, so separate to another patch.

>  			con |= OVL_CON_AEN;
> -
> -		/*
> -		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> -		 * for XRGB format, otherwise OVL will still read the value from memory.
> -		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> -		 * affect the result. Therefore we use !has_alpha as the condition.
> -		 */
> -		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> -			ignore_pixel_alpha = OVL_CONST_BLEND;
>  	}
>  
>  	/*
> @@ -548,6 +600,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  
>  	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
>  			      DISP_REG_OVL_CON(idx));
> +
> +	ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
>  	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
>  			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
>  	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> new file mode 100644
> index 000000000000..9bd5dc62d626
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OVL_H__
> +#define __MTK_DISP_OVL_H__
> +
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
> +
> +#endif


From Axe.Yang at mediatek.com  Mon Mar 24 19:41:26 2025
From: Axe.Yang at mediatek.com (=?utf-8?B?QXhlIFlhbmcgKOadqOejiik=?=)
Date: Tue, 25 Mar 2025 02:41:26 +0000
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <f8ce830d831aaba0d2748d31f8ba4a9915b7a14e.camel@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
	 <20250306085028.5024-2-axe.yang@mediatek.com>
	 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
	 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
	 <b09f618a-eaf9-4258-ae2d-67eff1cb249f@collabora.com>
	 <f8ce830d831aaba0d2748d31f8ba4a9915b7a14e.camel@mediatek.com>
Message-ID: <52d2f247a3058b96625bcdf5ab370282dfc9fb0e.camel@mediatek.com>

Hi Angelo,

Any comment on this :D 

Regards,
Axe

On Wed, 2025-03-12 at 14:30 +0800, axe.yang wrote:
> On Tue, 2025-03-11 at 10:47 +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 07/03/25 07:59, Axe Yang (??) ha scritto:
> > > On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
> > > > > Add 'mediatek,disable-single-burst' setting. This property
> > > > > can
> > > > > be
> > > > > used to switch bus burst type, from single burst to INCR,
> > > > > which
> > > > > is
> > > > > determined by the bus type within the IP. Some versions of
> > > > > the
> > > > > IP
> > > > > are using AXI bus, thus this switch is necessary as 'single'
> > > > > is
> > > > > not
> > > > > the burst type supported by the bus.
> > > > > 
> > > > > Signed-off-by: Axe Yang <axe.yang at mediatek.com>
> > > > 
> > > > I am mostly sure that this is not something to put in
> > > > devicetree,
> > > > but
> > > > as
> > > > platform data for specific SoC(s), as much as I'm mostly sure
> > > > that
> > > > all of
> > > > the instances of the MSDC IP in one SoC will be *all* using
> > > > either
> > > > single
> > > > or INCR.
> > > 
> > > No, actually MSDC IPs in one SoC are using different versions.
> > > Usually MSDC1 (index from 1) is used as eMMC host, the left hosts
> > > are
> > > used as SD/SDIO hosts. They have similar designs, but there are
> > > still
> > > difference.
> > > 
> > > > 
> > > > So, I think I know the answer but I'll still ask just to be
> > > > extremely
> > > > sure:
> > > > 
> > > > is there any MediaTek SoC that has different IP versions for
> > > > different MSDC
> > > > instances, and that hence require single burst on one instance
> > > > and
> > > > INCR on
> > > > another instance?
> > > 
> > > Yes. Actually every SoC has different IP versions for eMMC and
> > > SD/SDIO
> > > host as I said.
> > > e.g. For MT8168, signel burst bit should be set to 1 for eMMC
> > > Host,
> > > but
> > > 0 for SD/SDIO Host.
> > > 
> > > > 
> > > > And if there is - is there a pattern? Is it always SDIO
> > > > requiring
> > > > INCR or
> > > > always eMMC/SD requiring it?
> > > > 
> > > > 
> > > 
> > > No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
> > > configured base on IP version. There is no binding relationship
> > > between
> > > eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
> > > single, same as SD/SDIO.
> > > 
> > 
> > Okay but if there are different IP versions, and AXI/AHB is
> > determined
> > by the IP version, why aren't you parsing the MAIN_VER/ECO_VER
> > registers of
> > the MSDC IP to check whether to use INCR or SINGLE?
> 
> 
> To address your concerns, I had further discussions with the
> designer.
> Their response was that the bus type and IP version are not bound
> together. This contradicts my previous statements, and I apologize
> for
> that.
> According to the designer's feedback, I must say that the single
> burst
> setting is indeed tied to the IC, but the granularity is such that it
> needs to be set individually for each host.
> Given the large number of ICs Mediatek currently has, adding burst
> type
> information for each host to the driver's compatible structure would
> mean adding hundreds(maybe thousands :() of lines to the driver for
> the
> compatible structures for *all previous SoCs* (currently there are
> only
> 13 compatible structures, and they can be reuse by new SoC). This
> approach seems very cumbersome.
> 
> So I still believe that placing this setting in the DTS is a more
> appropriate approach.
> 
> Regards,
> Axe
> 
> > 
> > Cheers,
> > Angelo
> > 
> > > 
> > > Regards,
> > > Axe
> > > 
> > > 
> > > > 
> > > > > ---
> > > > >    Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8
> > > > > ++++++++
> > > > >    1 file changed, 8 insertions(+)
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/mmc/mtk-
> > > > > sd.yaml
> > > > > b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > > index 0debccbd6519..6076aff0a689 100644
> > > > > --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > > +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> > > > > @@ -100,6 +100,14 @@ properties:
> > > > >        minimum: 0
> > > > >        maximum: 0xffffffff
> > > > > 
> > > > > +  mediatek,disable-single-burst:
> > > > > +    $ref: /schemas/types.yaml#/definitions/flag
> > > > > +    description:
> > > > > +      Burst type setting. For some versions of the IP that
> > > > > do
> > > > > not
> > > > > use
> > > > > +      AHB bus, the burst type need to be switched to INCR.
> > > > > +      If present, use INCR burst type.
> > > > > +      If not present, use single burst type.
> > > > > +
> > > > >      mediatek,hs200-cmd-int-delay:
> > > > >        $ref: /schemas/types.yaml#/definitions/uint32
> > > > >        description:
> > > > 
> > > > 
> > > > 
> > 
> > 

From dyoung at redhat.com  Mon Mar 24 20:07:06 2025
From: dyoung at redhat.com (Dave Young)
Date: Tue, 25 Mar 2025 11:07:06 +0800
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <CALu+AoRL+oHW2vN8nf1wpsG2Ki8d44AABQRCBMd+CE4_XzqRTw@mail.gmail.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com> <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
 <CA+CK2bC4PM0JnHOUm7qfpQ=wUhwsYQ-hJ12tTK_7pSWgYk+bhg@mail.gmail.com> <CALu+AoRL+oHW2vN8nf1wpsG2Ki8d44AABQRCBMd+CE4_XzqRTw@mail.gmail.com>
Message-ID: <CALu+AoSzOixDBHiFdry=RbFGX5Umk5XxLC=BmPKMYW7rCLUxSw@mail.gmail.com>

On Tue, 25 Mar 2025 at 09:24, Dave Young <dyoung at redhat.com> wrote:
>
> On Tue, 25 Mar 2025 at 03:27, Pasha Tatashin <pasha.tatashin at soleen.com> wrote:
> >
> > On Mon, Mar 24, 2025 at 12:18?AM Dave Young <dyoung at redhat.com> wrote:
> > >
> > > On Thu, 20 Mar 2025 at 23:05, Changyuan Lyu <changyuanl at google.com> wrote:
> > > >
> > > > From: Alexander Graf <graf at amazon.com>
> > > >
> > > > We have all generic code in place now to support Kexec with KHO. This
> > > > patch adds a config option that depends on architecture support to
> > > > enable KHO support.
> > > >
> > > > Signed-off-by: Alexander Graf <graf at amazon.com>
> > > > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > > > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > > > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > > > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> > > > ---
> > > >  kernel/Kconfig.kexec | 15 +++++++++++++++
> > > >  1 file changed, 15 insertions(+)
> > > >
> > > > diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> > > > index 4d111f871951..57db99e758a8 100644
> > > > --- a/kernel/Kconfig.kexec
> > > > +++ b/kernel/Kconfig.kexec
> > > > @@ -95,6 +95,21 @@ config KEXEC_JUMP
> > > >           Jump between original kernel and kexeced kernel and invoke
> > > >           code in physical address mode via KEXEC
> > > >
> > > > +config KEXEC_HANDOVER
> > > > +       bool "kexec handover"
> > > > +       depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
> > > > +       select MEMBLOCK_KHO_SCRATCH
> > > > +       select KEXEC_FILE
> > > > +       select DEBUG_FS
> > > > +       select LIBFDT
> > > > +       select CMA
> > > > +       select XXHASH
> > > > +       help
> > > > +         Allow kexec to hand over state across kernels by generating and
> > > > +         passing additional metadata to the target kernel. This is useful
> > > > +         to keep data or state alive across the kexec. For this to work,
> > > > +         both source and target kernels need to have this option enabled.
> > > > +
> > >
> > > Have you tested kdump?  In my mind there are two issues,  one is with
> > > CMA enabled, it could cause kdump crashkernel memory reservation
> > > failures more often due to the fragmented low memory.  Secondly,  in
> >
> > As I understand cma low memory scratch reservation is needed only to
> > support some legacy pci devices that cannot use the full 64-bit space.
> > If so, I am not sure if KHO needs to be supported on machines with
> > such devices. However, even if we keep it, it should really be small,
> > so I would not expect that to be a problem for crash kernel memory
> > reservation.
>
> It is not easy to estimate how much of the KHO reserved memory is
> needed.  I assume this as a mechanism for all different users, it is
> not  predictable.  Also it is not only about the size, but also it
> makes the memory fragmented.
>
> >
> > > kdump kernel dump the crazy scratch memory in vmcore is not very
> > > meaningful.  Otherwise I suspect this is not tested under kdump.  If
> > > so please disable this option for kdump.
> >
> > The scratch memory will appear as regular CMA in the vmcore. The crash
> > kernel can be kexec loaded only from userland, long after the scratch
> > memory is converted to CMA.
>
> Depending on the reserved size, if big enough it should be excluded in
> vmcore dumping.
> Otherwise if it is a kdump kernel it should skip the handling of the
> KHO passed previous old states.

If you do not want to make the KHO conflicts with kdump, then the
above should be handled and well tested.  And then leave to end user
and distribution to determine if they want the both enabled
considering the risk of crashkernel reservation failure.

>
> >
> > Pasha
> >



From robh at kernel.org  Mon Mar 24 20:13:19 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 22:13:19 -0500
Subject: [PATCH v4 0/3] Add device tree for Nvidia's GB200NVL BMC
In-Reply-To: <20250324175926.222473-1-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
Message-ID: <174287235976.1618206.14203259564478820837.robh@kernel.org>


On Mon, 24 Mar 2025 17:59:23 +0000, Willie Thai wrote:
> The GB200NVL BMC is an Aspeed Ast2600 based BMC
> for Nvidia Blackwell GB200NVL platform.
> Reference to Ast2600 SOC [1].
> Reference to Blackwell GB200NVL Platform [2].
> 
> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Cc: Krzysztof Kozlowski <krzk at kernel.org>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Paul Menzel <pmenzel at molgen.mpg.de>
> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
> Link: https://www.aspeedtech.com/server_ast2600/ [1]
> Link: https://nvdam.widen.net/s/wwnsxrhm2w/blackwell-datasheet-3384703 [2]
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---
> Changes v1 -> v2:
>   - Fix the SOB name [Krzysztof]
>   - Fix warnings from scripts/checkpatch.pl run [Krzysztof]
>   - Fix DTS coding style [Krzysztof]
>   - Move pinctrl override to the bottom [Krzysztof]
>   - Drop bootargs [Krzysztof]
>   - Follow DTS coding style and change naming for leds node [Krzysztof]
>   - Change flash 0 status property [Krzysztof]
>   - Change the phy-mode to rgmii [Andrew]
>   - Remove the max-speed in mac0 [Andrew]
>   - Put gpio line name in one line per group of 8 gpios, but keep some b/c they can exceed length limit [Paul]
> Changes v2 -> v3:
>   - Fix missing new line [Krzysztof]
>   - Fix missing binding define, adding it in the patch no.1 of this patch set v3 [Krzysztof, Rob]
>   - Fix DTS coding style [Krzysztof]
>   - Modify nodes name to generic name for: i2c expander pca9546, gpio expander pca9555, power monitor lm5066i, fan controller max31790 [Krzysztof]
>   - Skip mac setting and wait till the delay issue in phy-mode fix from Aspeed SOC vendor side [Andrew]
>   - Remove i2c-scl-clk-low-timeout-us which is Apseed proprietary property [Mars]
> Changes v3 -> v4:
>   - Order binding patch first in the patch set [Andrew Jeffery]
>   - Make the commit message more concise [Krzysztof]
>   - Remove stray blank lines [Krzysztof]
>   - Remove unnecessary comments [Krzysztof]
>   - Remove underscore, repalce by dash symbol in node name [Krzysztof]
>   - Remove disable-master property in i2c as it is downstream added property [Rob, Andrew Jeffery]
>   - Remove #address-cells, #size-cells in nxp,pca9555 and maxim,max31790 as they are no longer defined [Rob, Andrew Jeffery]
> ---
> 
> Willie Thai (3):
>   dt-bindings: arm: aspeed: add Nvidia's GB200NVL BMC
>   dt-bindings: pinctrl: aspeed,ast2600-pinctrl
>   ARM: dts: aspeed: Add device tree for Nvidia's GB200NVL BMC
> 
>  .../bindings/arm/aspeed/aspeed.yaml           |    1 +
>  .../pinctrl/aspeed,ast2600-pinctrl.yaml       |    1 +
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts | 1149 +++++++++++++++++
>  4 files changed, 1152 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts
> 
> --
> 2.25.1
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm/boot/dts/aspeed/' for 20250324175926.222473-1-wthai at nvidia.com:

arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: timer: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/timer/arm,arch_timer.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /sdram at 1e6e0000: failed to match any schema with compatible: ['aspeed,ast2600-sdram-edac', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: bus at 1e600000: compatible: ['aspeed,ast2600-ahbc', 'syscon'] is too long
	from schema $id: http://devicetree.org/schemas/bus/aspeed,ast2600-ahbc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: syscon at 1e6e2000: 'smp-memram at 180' does not match any of the regexes: '^interrupt-controller@[0-9a-f]+$', '^p2a-control@[0-9a-f]+$', '^pinctrl(@[0-9a-f]+)?$', '^silicon-id@[0-9a-f]+$', 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/smp-memram at 180: failed to match any schema with compatible: ['aspeed,ast2600-smpmem']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 560: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic0']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/syscon at 1e6e2000/interrupt-controller at 570: failed to match any schema with compatible: ['aspeed,ast2600-scu-ic1']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e6e0000/display at 1e6e6000: failed to match any schema with compatible: ['aspeed,ast2600-gfx', 'syscon']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9000: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: adc at 1e6e9100: 'interrupts' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/adc/aspeed,ast2600-adc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: crypto at 1e6fa000: 'aspeed,ahbc' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/crypto/aspeed,ast2600-acry.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740100:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: sdc at 1e740000: sdhci at 1e740200:compatible: ['aspeed,ast2600-sdhci', 'sdhci'] is too long
	from schema $id: http://devicetree.org/schemas/mmc/aspeed,sdhci.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/sdc at 1e740000/sdhci at 1e740100: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/sdc at 1e740000/sdhci at 1e740200: failed to match any schema with compatible: ['aspeed,ast2600-sdhci', 'sdhci']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/timer at 1e782000: failed to match any schema with compatible: ['aspeed,ast2600-timer']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: lpc-snoop at 80: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: lpc at 1e789000: reg-io-width: 4 is not of type 'object'
	from schema $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 24: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 28: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 2c: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: kcs at 114: 'clocks' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/lpc at 1e789000/lhc at a0: failed to match any schema with compatible: ['aspeed,ast2600-lhc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e780000/lpc at 1e789000/ibt at 140: failed to match any schema with compatible: ['aspeed,ast2600-ibt-bmc']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b000: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/fsi at 1e79b000: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: fsi at 1e79b100: compatible: ['aspeed,ast2600-fsi-master', 'fsi-master'] is too long
	from schema $id: http://devicetree.org/schemas/fsi/aspeed,ast2600-fsi-master.yaml#
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/fsi at 1e79b100: failed to match any schema with compatible: ['aspeed,ast2600-fsi-master', 'fsi-master']
arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dtb: /ahb/apb at 1e790000/dma-controller at 1e79e000: failed to match any schema with compatible: ['aspeed,ast2600-udma']







From robh at kernel.org  Mon Mar 24 20:13:21 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 22:13:21 -0500
Subject: [PATCH 0/5] arm64: dts: rockchip: add ROCK 5B+ support
In-Reply-To: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
References: <20250324-rock5bp-for-upstream-v1-0-6217edf15b19@kernel.org>
Message-ID: <174287236051.1618248.4100886448951731382.robh@kernel.org>


On Mon, 24 Mar 2025 18:04:21 +0100, Sebastian Reichel wrote:
> This series adds support for the ROCK 5B+, which (as the name suggests)
> is an improved version of the ROCK 5B. It also adds initial USB-C
> support for both the ROCK 5B and the 5B+.
> 
> Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
> ---
> Sebastian Reichel (5):
>       arm64: dts: rockchip: move rock 5b to include file
>       arm64: dts: rockchip: move rock 5b to include file
>       dt-bindings: arm: rockchip: Add Radxa ROCK 5B+
>       arm64: dts: rockchip: add Rock 5B+
>       arm64: dts: rockchip: add USB-C support for ROCK 5B and 5B+
> 
>  .../devicetree/bindings/arm/rockchip.yaml          |    5 +
>  arch/arm64/boot/dts/rockchip/Makefile              |    1 +
>  .../boot/dts/rockchip/rk3588-rock-5b-plus.dts      |  117 +++
>  arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts    |  952 +----------------
>  arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtsi   | 1087 ++++++++++++++++++++
>  5 files changed, 1220 insertions(+), 942 deletions(-)
> ---
> base-commit: 76728fe54f547950f73c9dc446beb2e31604abd7
> change-id: 20250324-rock5bp-for-upstream-fd85b00b593b
> 
> Best regards,
> --
> Sebastian Reichel <sre at kernel.org>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/rockchip/' for 20250324-rock5bp-for-upstream-v1-0-6217edf15b19 at kernel.org:

arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: power-controller: power-domain at 12: Unevaluated properties are not allowed ('domain-supply' was unexpected)
	from schema $id: http://devicetree.org/schemas/power/rockchip,power-controller.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: vop at fdd90000: clocks: [[33, 605], [33, 604], [33, 609], [33, 610], [33, 611], [33, 612], [33, 603], [107], [108]] is too long
	from schema $id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: vop at fdd90000: clock-names: ['aclk', 'hclk', 'dclk_vp0', 'dclk_vp1', 'dclk_vp2', 'dclk_vp3', 'pclk_vop', 'pll_hdmiphy0', 'pll_hdmiphy1'] is too long
	from schema $id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fddb0000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fddb0000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fdde0000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fdde0000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /rng at fe378000: failed to match any schema with compatible: ['rockchip,rk3588-rng']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fe4e0000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fe4e0000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fe4f0000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fe4f0000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fddb8000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fddb8000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: spdif-tx at fdde8000: compatible: 'oneOf' conditional failed, one must be fixed:
	['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif'] is too long
	'rockchip,rk3066-spdif' was expected
	'rockchip,rk3228-spdif' was expected
	'rockchip,rk3328-spdif' was expected
	'rockchip,rk3366-spdif' was expected
	'rockchip,rk3368-spdif' was expected
	'rockchip,rk3399-spdif' was expected
	'rockchip,rk3568-spdif' was expected
	'rockchip,rk3588-spdif' is not one of ['rockchip,rk3128-spdif', 'rockchip,rk3188-spdif', 'rockchip,rk3288-spdif', 'rockchip,rk3308-spdif']
	from schema $id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /spdif-tx at fdde8000: failed to match any schema with compatible: ['rockchip,rk3588-spdif', 'rockchip,rk3568-spdif']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /hdmi_receiver at fdee0000: failed to match any schema with compatible: ['rockchip,rk3588-hdmirx-ctrler', 'snps,dw-hdmi-rx']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b-plus.dtb: /hdmi_receiver at fdee0000: failed to match any schema with compatible: ['rockchip,rk3588-hdmirx-ctrler', 'snps,dw-hdmi-rx']
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dtb: vop at fdd90000: clocks: [[33, 605], [33, 604], [33, 609], [33, 610], [33, 611], [33, 612], [33, 603], [107], [108]] is too long
	from schema $id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#







From robh at kernel.org  Mon Mar 24 20:17:48 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 22:17:48 -0500
Subject: [PATCH 1/2] dt-bindings: PCI: Correct indentation and style in
 DTS example
In-Reply-To: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
References: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
Message-ID: <174287266828.1624468.7570940248858053984.robh@kernel.org>


On Mon, 24 Mar 2025 13:52:01 +0100, Krzysztof Kozlowski wrote:
> DTS example in the bindings should be indented with 2- or 4-spaces and
> aligned with opening '- |', so correct any differences like 3-spaces or
> mixtures 2- and 4-spaces in one binding.
> 
> No functional changes here, but saves some comments during reviews of
> new patches built on existing code.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  .../bindings/pci/brcm,stb-pcie.yaml           |  81 +++++++------
>  .../bindings/pci/cdns,cdns-pcie-ep.yaml       |  16 +--
>  .../bindings/pci/intel,keembay-pcie-ep.yaml   |  26 ++--
>  .../bindings/pci/intel,keembay-pcie.yaml      |  38 +++---
>  .../bindings/pci/microchip,pcie-host.yaml     |  54 ++++-----
>  .../devicetree/bindings/pci/rcar-pci-ep.yaml  |  34 +++---
>  .../bindings/pci/rcar-pci-host.yaml           |  46 +++----
>  .../bindings/pci/xilinx-versal-cpm.yaml       | 112 +++++++++---------
>  8 files changed, 202 insertions(+), 205 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 20:17:57 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 22:17:57 -0500
Subject: [PATCH 2/2] dt-bindings: PCI: sifive,fu740-pcie: Fix include
 placement in DTS example
In-Reply-To: <20250324125202.81986-2-krzysztof.kozlowski@linaro.org>
References: <20250324125202.81986-1-krzysztof.kozlowski@linaro.org>
 <20250324125202.81986-2-krzysztof.kozlowski@linaro.org>
Message-ID: <174287267578.1624713.1754304673947660629.robh@kernel.org>


On Mon, 24 Mar 2025 13:52:02 +0100, Krzysztof Kozlowski wrote:
> Coding style and common logic dictates that headers should not be
> included in device nodes.  No functional impact.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> ---
>  Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Mon Mar 24 20:23:03 2025
From: robh at kernel.org (Rob Herring)
Date: Mon, 24 Mar 2025 22:23:03 -0500
Subject: [PATCH v3 1/5] dt-bindings: bus: add documentation for the IMX
 AIPSTZ bridge
In-Reply-To: <20250324162556.30972-2-laurentiumihalcea111@gmail.com>
References: <20250324162556.30972-1-laurentiumihalcea111@gmail.com>
 <20250324162556.30972-2-laurentiumihalcea111@gmail.com>
Message-ID: <20250325032303.GA1624882-robh@kernel.org>

On Mon, Mar 24, 2025 at 12:25:52PM -0400, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> 
> Add documentation for IMX AIPSTZ bridge.
> 
> Co-developed-by: Daniel Baluta <daniel.baluta at nxp.com>
> Signed-off-by: Daniel Baluta <daniel.baluta at nxp.com>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> ---
>  .../bindings/bus/fsl,imx8mp-aipstz.yaml       | 107 ++++++++++++++++++
>  1 file changed, 107 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
> 
> diff --git a/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml b/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
> new file mode 100644
> index 000000000000..c0427dfcdaca
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/bus/fsl,imx8mp-aipstz.yaml
> @@ -0,0 +1,107 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/bus/fsl,imx8mp-aipstz.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Secure AHB to IP Slave bus (AIPSTZ) bridge
> +
> +description:
> +  The secure AIPS bridge (AIPSTZ) acts as a bridge for AHB masters
> +  issuing transactions to IP Slave peripherals. Additionally, this module
> +  offers access control configurations meant to restrict which peripherals
> +  a master can access.

Wrap at 80 chars.

> +
> +maintainers:
> +  - Laurentiu Mihalcea <laurentiu.mihalcea at nxp.com>
> +
> +properties:
> +  compatible:
> +    const: fsl,imx8mp-aipstz
> +
> +  reg:
> +    maxItems: 2
> +
> +  reg-names:
> +    items:
> +      - const: bus
> +      - const: ac
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  "#address-cells":
> +    const: 1
> +
> +  "#size-cells":
> +    const: 1
> +
> +  "#access-controller-cells":
> +    const: 0

With 0 cells, how do you identify which device it is?

> +
> +  ranges: true
> +
> +# borrowed from simple-bus.yaml, no additional requirements for children
> +patternProperties:
> +  "@(0|[1-9a-f][0-9a-f]*)$":
> +    type: object
> +    additionalProperties: true
> +    properties:
> +      reg:
> +        items:
> +          minItems: 2
> +          maxItems: 4
> +        minItems: 1
> +        maxItems: 1024
> +      ranges:
> +        oneOf:
> +          - items:
> +              minItems: 3
> +              maxItems: 7
> +            minItems: 1
> +            maxItems: 1024
> +          - $ref: /schemas/types.yaml#/definitions/flag
> +    anyOf:
> +      - required:
> +          - reg
> +      - required:
> +          - ranges
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - power-domains
> +  - "#address-cells"
> +  - "#size-cells"
> +  - "#access-controller-cells"
> +  - ranges
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/imx8mp-clock.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    bus at 30c00000 {
> +        compatible = "fsl,imx8mp-aipstz";
> +        reg = <0x30c00000 0x400000>, <0x30df0000 0x10000>;

It doesn't look like you have any registers in the 1st entry, but they 
are child devices? Then you should use ranges and drop it here:

ranges = <0x0 0x30c00000 0x400000>;


> +        reg-names = "bus", "ac";
> +        power-domains = <&pgc_audio>;
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        #access-controller-cells = <0>;
> +        ranges;
> +
> +        dma-controller at 30e00000 {
> +            compatible = "fsl,imx8mp-sdma", "fsl,imx8mq-sdma";
> +            reg = <0x30e00000 0x10000>;
> +            #dma-cells = <3>;
> +            clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SDMA3_ROOT>,
> +                     <&clk IMX8MP_CLK_AUDIO_ROOT>;
> +            clock-names = "ipg", "ahb";
> +            interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
> +            fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";

No 'access-controllers' here?

> +        };
> +    };
> -- 
> 2.34.1
> 


From robh at kernel.org  Mon Mar 24 20:29:11 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Mon, 24 Mar 2025 22:29:11 -0500
Subject: [PATCH 1/2] dt-bindings: arm: imx: document i.MX 95 Verdin
 Evaluation Kit (EVK)
In-Reply-To: <20250324234013.140440-1-marex@denx.de>
References: <20250324234013.140440-1-marex@denx.de>
Message-ID: <174287335084.1637326.11937495835125026079.robh@kernel.org>


On Tue, 25 Mar 2025 00:40:01 +0100, Marek Vasut wrote:
> Document support for i.MX 95 Verdin Evaluation Kit (EVK), which
> used to be the Titan EVK.
> 
> Note that the SoM used in this EVK is a derivative SoM from Verdin
> line of SoMs, an actual i.MX95 Verdin SoM is under development.
> 
> [1] https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95-evaluation-kit
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> ---
> Cc: Alexander Stein <alexander.stein at ew.tq-group.com>
> Cc: Conor Dooley <conor+dt at kernel.org>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Francesco Dolcini <francesco.dolcini at toradex.com>
> Cc: Frieder Schrempf <frieder.schrempf at kontron.de>
> Cc: Hiago De Franco <hiago.franco at toradex.com>
> Cc: Joao Goncalves <joao.goncalves at toradex.com>
> Cc: Joao Goncalves <jpaulo.silvagoncalves at gmail.com>
> Cc: Krzysztof Kozlowski <krzk+dt at kernel.org>
> Cc: Max Merchel <Max.Merchel at ew.tq-group.com>
> Cc: Michael Walle <mwalle at kernel.org>
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Pengutronix Kernel Team <kernel at pengutronix.de>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Tim Harvey <tharvey at gateworks.com>
> Cc: devicetree at vger.kernel.org
> Cc: imx at lists.linux.dev
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> ---
>  Documentation/devicetree/bindings/arm/fsl.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh at kernel.org>



From nichen at iscas.ac.cn  Mon Mar 24 20:28:33 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Tue, 25 Mar 2025 11:28:33 +0800
Subject: [PATCH] ASoC: sun8i-codec: Remove unnecessary NULL check before clk_disable_unprepare()
Message-ID: <20250325032833.604073-1-nichen@iscas.ac.cn>

clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL.
Remove unneeded NULL check for clk here.

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
 sound/soc/sunxi/sun8i-codec.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 8b9eb1a202f7..a27976c375fe 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -274,8 +274,7 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
 	regcache_cache_only(scodec->regmap, true);
 	regcache_mark_dirty(scodec->regmap);
 
-	if (scodec->clk_bus)
-		clk_disable_unprepare(scodec->clk_bus);
+	clk_disable_unprepare(scodec->clk_bus);
 
 	return 0;
 }
-- 
2.25.1



From ck.hu at mediatek.com  Mon Mar 24 20:44:57 2025
From: ck.hu at mediatek.com (=?utf-8?B?Q0sgSHUgKOiDoeS/iuWFiSk=?=)
Date: Tue, 25 Mar 2025 03:44:57 +0000
Subject: [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in
 the one mediatek-drm driver
In-Reply-To: <20250321093435.94835-15-paul-pl.chen@mediatek.com>
References: <20250321093435.94835-1-paul-pl.chen@mediatek.com>
	 <20250321093435.94835-15-paul-pl.chen@mediatek.com>
Message-ID: <6bf9d4b3e060461ec491a3703d7ba952f9c5dceb.camel@mediatek.com>

On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin at mediatek.com>
> 
> To support multiple mmsys instances in the one mediatek-drm instance,
> providing improved flexibility and scalability by the following changes:
> 
> 1. Add DDP_COMPONENT_DRM_OVLSYS_ADAPTOR* to probe the
>   ovlsys_adaptor drivers and support different mmsys composition.
> 2. Added new component types MTK_DISP_VIRTUAL to support the
>   routing to virtual display components.
> 3. Added and adjusted the existed structure or interface to extend
>   the support of multiple mmsys instances.
> 4. Modified the component matching and binding logic to support
>   multiple mmsys instances.
> 
> Signed-off-by: Nancy Lin <nancy.lin at mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen at mediatek.com>
> ---

[snip]

>  
> +enum mtk_drm_mmsys {
> +	DISPSYS0,
> +	DISPSYS1,
> +	OVLSYS0,
> +	OVLSYS1,
> +	MAX_MMSYS,
> +};

Let ovlsys sub driver control OVLSYS0 and OVLSYS1, so mediatek drm driver would not see them and this patch is not necessary.

Regards,
CK



From sumit.garg at kernel.org  Mon Mar 24 22:55:54 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 11:25:54 +0530
Subject: [PATCH v6 03/10] optee: account for direction while converting
 parameters
In-Reply-To: <CAHUa44HY-jZCoDXKnx-f4gBoABRVdh1+6PA1AYHSva9aL=rDAA@mail.gmail.com>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org>
 <Z9K2RQYuXSJc8Y1E@sumit-X1>
 <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com>
 <Z9vfD4UWSrqSTPnP@sumit-X1>
 <CAHUa44HY-jZCoDXKnx-f4gBoABRVdh1+6PA1AYHSva9aL=rDAA@mail.gmail.com>
Message-ID: <Z-JFagmbZBQd0hoM@sumit-X1>

On Thu, Mar 20, 2025 at 02:00:57PM +0100, Jens Wiklander wrote:
> Hi Sumit,
> 
> On Thu, Mar 20, 2025 at 10:25?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> >
> > Hi Jens,
> >
> > On Mon, Mar 17, 2025 at 08:42:01AM +0100, Jens Wiklander wrote:
> > > Hi Sumit,
> > >
> > > On Thu, Mar 13, 2025 at 11:41?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> > > >
> > > > Hi Jens,
> > > >
> > > > On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> > > > > The OP-TEE backend driver has two internal function pointers to convert
> > > > > between the subsystem type struct tee_param and the OP-TEE type struct
> > > > > optee_msg_param.
> > > > >
> > > > > The conversion is done from one of the types to the other, which is then
> > > > > involved in some operation and finally converted back to the original
> > > > > type. When converting to prepare the parameters for the operation, all
> > > > > fields must be taken into account, but then converting back, it's enough
> > > > > to update only out-values and out-sizes. So, an update_out parameter is
> > > > > added to the conversion functions to tell if all or only some fields
> > > > > must be copied.
> > > > >
> > > > > This is needed in a later patch where it might get confusing when
> > > > > converting back in from_msg_param() callback since an allocated
> > > > > restricted SHM can be using the sec_world_id of the used restricted
> > > > > memory pool and that doesn't translate back well.
> > > > >
> > > > > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > > > > ---
> > > > >  drivers/tee/optee/call.c          | 10 ++--
> > > > >  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
> > > > >  drivers/tee/optee/optee_private.h | 42 +++++++++++------
> > > > >  drivers/tee/optee/rpc.c           | 31 +++++++++----
> > > > >  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
> > > > >  5 files changed, 144 insertions(+), 58 deletions(-)
> > > > >
> > > > > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > > > > index 16eb953e14bb..f1533b894726 100644
> > > > > --- a/drivers/tee/optee/call.c
> > > > > +++ b/drivers/tee/optee/call.c
> > > > > @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
> > > > >       export_uuid(msg_arg->params[1].u.octets, &client_uuid);
> > > > >
> > > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> > > > > -                                   arg->num_params, param);
> > > > > +                                   arg->num_params, param,
> > > > > +                                   false /*!update_out*/);
> > > > >       if (rc)
> > > > >               goto out;
> > > > >
> > > > > @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
> > > > >       }
> > > > >
> > > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > > -                                    msg_arg->params + 2)) {
> > > > > +                                    msg_arg->params + 2,
> > > > > +                                    true /*update_out*/)) {
> > > > >               arg->ret = TEEC_ERROR_COMMUNICATION;
> > > > >               arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > > >               /* Close session again to avoid leakage */
> > > > > @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > > >       msg_arg->cancel_id = arg->cancel_id;
> > > > >
> > > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> > > > > -                                   param);
> > > > > +                                   param, false /*!update_out*/);
> > > > >       if (rc)
> > > > >               goto out;
> > > > >
> > > > > @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > > >       }
> > > > >
> > > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > > -                                    msg_arg->params)) {
> > > > > +                                    msg_arg->params, true /*update_out*/)) {
> > > > >               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
> > > > >               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > > >       }
> > > > > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > > > > index 4ca1d5161b82..e4b08cd195f3 100644
> > > > > --- a/drivers/tee/optee/ffa_abi.c
> > > > > +++ b/drivers/tee/optee/ffa_abi.c
> > > > > @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
> > > > >   */
> > > > >
> > > > >  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > > -                                u32 attr, const struct optee_msg_param *mp)
> > > > > +                                u32 attr, const struct optee_msg_param *mp,
> > > > > +                                bool update_out)
> > > > >  {
> > > > >       struct tee_shm *shm = NULL;
> > > > >       u64 offs_high = 0;
> > > > >       u64 offs_low = 0;
> > > > >
> > > > > +     if (update_out) {
> > > > > +             if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> > > > > +                     return;
> > > > > +             goto out;
> > > > > +     }
> > > > > +
> > > > >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> > > > >                 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> > > > > -     p->u.memref.size = mp->u.fmem.size;
> > > > >
> > > > >       if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
> > > > >               shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> > > > > @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > >               offs_high = mp->u.fmem.offs_high;
> > > > >       }
> > > > >       p->u.memref.shm_offs = offs_low | offs_high << 32;
> > > > > +out:
> > > > > +     p->u.memref.size = mp->u.fmem.size;
> > > > >  }
> > > > >
> > > > >  /**
> > > > > @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > >   * @params:  subsystem internal parameter representation
> > > > >   * @num_params:      number of elements in the parameter arrays
> > > > >   * @msg_params:      OPTEE_MSG parameters
> > > > > + * @update_out: update parameter for output only
> > > > >   *
> > > > >   * Returns 0 on success or <0 on failure
> > > > >   */
> > > > >  static int optee_ffa_from_msg_param(struct optee *optee,
> > > > >                                   struct tee_param *params, size_t num_params,
> > > > > -                                 const struct optee_msg_param *msg_params)
> > > > > +                                 const struct optee_msg_param *msg_params,
> > > > > +                                 bool update_out)
> > > > >  {
> > > > >       size_t n;
> > > > >
> > > > > @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > > >
> > > > >               switch (attr) {
> > > > >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > > > > +                     if (update_out)
> > > > > +                             break;
> > > > >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > > >                       memset(&p->u, 0, sizeof(p->u));
> > > > >                       break;
> > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > > > > -                     optee_from_msg_param_value(p, attr, mp);
> > > > > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> > > > >                       break;
> > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
> > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
> > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> > > > > -                     from_msg_param_ffa_mem(optee, p, attr, mp);
> > > > > +                     from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
> > > > >                       break;
> > > > >               default:
> > > > >                       return -EINVAL;
> > > > > @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > > >  }
> > > > >
> > > > >  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > > -                             const struct tee_param *p)
> > > > > +                             const struct tee_param *p, bool update_out)
> > > > >  {
> > > > >       struct tee_shm *shm = p->u.memref.shm;
> > > > >
> > > > > +     if (update_out) {
> > > > > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > > > > +                     return 0;
> > > > > +             goto out;
> > > > > +     }
> > > > > +
> > > > >       mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
> > > > >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> > > > >
> > > > > @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > >               memset(&mp->u, 0, sizeof(mp->u));
> > > > >               mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
> > > > >       }
> > > > > +out:
> > > > >       mp->u.fmem.size = p->u.memref.size;
> > > > >
> > > > >       return 0;
> > > > > @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > >   * @optee:   main service struct
> > > > >   * @msg_params:      OPTEE_MSG parameters
> > > > >   * @num_params:      number of elements in the parameter arrays
> > > > > - * @params:  subsystem itnernal parameter representation
> > > > > + * @params:  subsystem internal parameter representation
> > > > > + * @update_out: update parameter for output only
> > > > >   * Returns 0 on success or <0 on failure
> > > > >   */
> > > > >  static int optee_ffa_to_msg_param(struct optee *optee,
> > > > >                                 struct optee_msg_param *msg_params,
> > > > >                                 size_t num_params,
> > > > > -                               const struct tee_param *params)
> > > > > +                               const struct tee_param *params,
> > > > > +                               bool update_out)
> > > > >  {
> > > > >       size_t n;
> > > > >
> > > > > @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
> > > > >
> > > > >               switch (p->attr) {
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > > > +                     if (update_out)
> > > > > +                             break;
> > > > >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > > >                       memset(&mp->u, 0, sizeof(mp->u));
> > > > >                       break;
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > > > -                     optee_to_msg_param_value(mp, p);
> > > > > +                     optee_to_msg_param_value(mp, p, update_out);
> > > > >                       break;
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > > > -                     if (to_msg_param_ffa_mem(mp, p))
> > > > > +                     if (to_msg_param_ffa_mem(mp, p, update_out))
> > > > >                               return -EINVAL;
> > > > >                       break;
> > > > >               default:
> > > >
> > > > Can we rather handle it as follows to improve code readability and
> > > > maintainence long term? Ditto for all other places.
> > > >
> > > > static int optee_ffa_to_msg_param(struct optee *optee,
> > > >                                   struct optee_msg_param *msg_params,
> > > >                                   size_t num_params,
> > > >                                   const struct tee_param *params,
> > > >                                   bool update_out)
> > > > {
> > > >         size_t n;
> > > >
> > > >         for (n = 0; n < num_params; n++) {
> > > >                 const struct tee_param *p = params + n;
> > > >                 struct optee_msg_param *mp = msg_params + n;
> > > >
> > > >                 if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
> > > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
> > > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
> > > >                     continue;
> > >
> > > You're missing updating the length field for memrefs.
> > >
> >
> > Do we need to update length field for input memrefs when update_out is
> > set? I don't see that happening in your existing patch too.
> 
> I'm sorry, I was unclear. The update_out parameter means only the
> output fields should be updated, not the attribute, offsets, ids, etc.
> That is, the length field for memrefs, and the value fields a, b, c
> for value params. Some of the memrefs aren't translated one-to-one
> with SDP, but the length field can and must be updated.

Isn't it rather better to add another attribute type to handled SDP
special handling?

-Sumit

> 
> Cheers,
> Jens
> 
> >
> > -Sumit
> >
> > > Cheers,
> > > Jens
> > >
> > > >
> > > >                 switch (p->attr) {
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > >                         mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > >                         memset(&mp->u, 0, sizeof(mp->u));
> > > >                         break;
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > >                         optee_to_msg_param_value(mp, p);
> > > >                         break;
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > >                         if (to_msg_param_ffa_mem(mp, p))
> > > >                                 return -EINVAL;
> > > >                         break;
> > > >                 default:
> > > >                         return -EINVAL;
> > > >                 }
> > > >         }
> > > >
> > > >         return 0;
> > > > }
> > > >
> > > > -Sumit


From mazziesaccount at gmail.com  Mon Mar 24 23:06:31 2025
From: mazziesaccount at gmail.com (Matti Vaittinen)
Date: Tue, 25 Mar 2025 08:06:31 +0200
Subject: [PATCH 2/2] dt-bindings: iio: Use unevaluatedProperties for SPI
 devices
In-Reply-To: <20250324125313.82226-2-krzysztof.kozlowski@linaro.org>
References: <20250324125313.82226-1-krzysztof.kozlowski@linaro.org>
 <20250324125313.82226-2-krzysztof.kozlowski@linaro.org>
Message-ID: <007c6e9b-ffcd-42ef-a3f2-4b8fb62e99eb@gmail.com>

On 24/03/2025 14:53, Krzysztof Kozlowski wrote:
> SPI devices should use unevaluatedProperties:false instead of
> additionalProperties:false, to allow any SPI device properties listed in
> spi-peripheral-props.yaml.
> 
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Reviewed-by: Matti Vaittinen <mazziesaccount at gmail.com>

Thanks!!


From sumit.garg at kernel.org  Mon Mar 24 23:20:28 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 11:50:28 +0530
Subject: [PATCH v6 04/10] optee: sync secure world ABI headers
In-Reply-To: <20250305130634.1850178-5-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-5-jens.wiklander@linaro.org>
Message-ID: <Z-JLLHcrt1pwXe7J@sumit-X1>

Hi Jens,

It has taken a bit of time for me to review this patch-set as I am
settling in my new role.

On Wed, Mar 05, 2025 at 02:04:10PM +0100, Jens Wiklander wrote:
> Update the header files describing the secure world ABI, both with and
> without FF-A. The ABI is extended to deal with restricted memory, but as
> usual backward compatible.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/optee_ffa.h | 27 ++++++++++---
>  drivers/tee/optee/optee_msg.h | 65 ++++++++++++++++++++++++++++++--
>  drivers/tee/optee/optee_smc.h | 71 ++++++++++++++++++++++++++++++++++-
>  3 files changed, 154 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
> index 257735ae5b56..7bd037200343 100644
> --- a/drivers/tee/optee/optee_ffa.h
> +++ b/drivers/tee/optee/optee_ffa.h
> @@ -81,7 +81,7 @@
>   *                   as the second MSG arg struct for
>   *                   OPTEE_FFA_YIELDING_CALL_WITH_ARG.
>   *        Bit[31:8]: Reserved (MBZ)
> - * w5:	  Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below,
> + * w5:	  Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_*
>   * w6:	  The maximum secure world notification number
>   * w7:	  Not used (MBZ)
>   */
> @@ -94,6 +94,8 @@
>  #define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF	BIT(1)
>  /* OP-TEE supports probing for RPMB device if needed */
>  #define OPTEE_FFA_SEC_CAP_RPMB_PROBE	BIT(2)
> +/* OP-TEE supports Restricted Memory for secure data path */
> +#define OPTEE_FFA_SEC_CAP_RSTMEM	BIT(3)
>  
>  #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
>  
> @@ -108,7 +110,7 @@
>   *
>   * Return register usage:
>   * w3:    Error code, 0 on success
> - * w4-w7: Note used (MBZ)
> + * w4-w7: Not used (MBZ)
>   */
>  #define OPTEE_FFA_UNREGISTER_SHM	OPTEE_FFA_BLOCKING_CALL(3)
>  
> @@ -119,16 +121,31 @@
>   * Call register usage:
>   * w3:    Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF
>   * w4:	  Notification value to request bottom half processing, should be
> - *	  less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE.
> + *	  less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE
>   * w5-w7: Not used (MBZ)
>   *
>   * Return register usage:
>   * w3:    Error code, 0 on success
> - * w4-w7: Note used (MBZ)
> + * w4-w7: Not used (MBZ)
>   */
>  #define OPTEE_FFA_ENABLE_ASYNC_NOTIF	OPTEE_FFA_BLOCKING_CALL(5)
>  
> -#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64
> +#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE	64
> +
> +/*
> + * Release Restricted memory
> + *
> + * Call register usage:
> + * w3:    Service ID, OPTEE_FFA_RECLAIM_RSTMEM
> + * w4:    Shared memory handle, lower bits
> + * w5:    Shared memory handle, higher bits
> + * w6-w7: Not used (MBZ)
> + *
> + * Return register usage:
> + * w3:    Error code, 0 on success
> + * w4-w7: Note used (MBZ)
> + */
> +#define OPTEE_FFA_RELEASE_RSTMEM	OPTEE_FFA_BLOCKING_CALL(8)
>  
>  /*
>   * Call with struct optee_msg_arg as argument in the supplied shared memory
> diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
> index e8840a82b983..1b558526e7d9 100644
> --- a/drivers/tee/optee/optee_msg.h
> +++ b/drivers/tee/optee/optee_msg.h
> @@ -133,13 +133,13 @@ struct optee_msg_param_rmem {
>  };
>  
>  /**
> - * struct optee_msg_param_fmem - ffa memory reference parameter
> + * struct optee_msg_param_fmem - FF-A memory reference parameter
>   * @offs_lower:	   Lower bits of offset into shared memory reference
>   * @offs_upper:	   Upper bits of offset into shared memory reference
>   * @internal_offs: Internal offset into the first page of shared memory
>   *		   reference
>   * @size:	   Size of the buffer
> - * @global_id:	   Global identifier of Shared memory
> + * @global_id:	   Global identifier of the shared memory
>   */
>  struct optee_msg_param_fmem {
>  	u32 offs_low;
> @@ -165,7 +165,7 @@ struct optee_msg_param_value {
>   * @attr:	attributes
>   * @tmem:	parameter by temporary memory reference
>   * @rmem:	parameter by registered memory reference
> - * @fmem:	parameter by ffa registered memory reference
> + * @fmem:	parameter by FF-A registered memory reference
>   * @value:	parameter by opaque value
>   * @octets:	parameter by octet string
>   *
> @@ -296,6 +296,18 @@ struct optee_msg_arg {
>   */
>  #define OPTEE_MSG_FUNCID_GET_OS_REVISION	0x0001
>  
> +/*
> + * Values used in OPTEE_MSG_CMD_LEND_RSTMEM below
> + * OPTEE_MSG_RSTMEM_RESERVED		Reserved
> + * OPTEE_MSG_RSTMEM_SECURE_VIDEO_PLAY	Secure Video Playback
> + * OPTEE_MSG_RSTMEM_TRUSTED_UI		Trused UI
> + * OPTEE_MSG_RSTMEM_SECURE_VIDEO_RECORD	Secure Video Recording
> + */
> +#define OPTEE_MSG_RSTMEM_RESERVED		0
> +#define OPTEE_MSG_RSTMEM_SECURE_VIDEO_PLAY	1
> +#define OPTEE_MSG_RSTMEM_TRUSTED_UI		2
> +#define OPTEE_MSG_RSTMEM_SECURE_VIDEO_RECORD	3
> +
>  /*
>   * Do a secure call with struct optee_msg_arg as argument
>   * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
> @@ -337,6 +349,49 @@ struct optee_msg_arg {
>   * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is
>   * normal world unable to process asynchronous notifications. Typically
>   * used when the driver is shut down.
> + *
> + * OPTEE_MSG_CMD_LEND_RSTMEM lends restricted memory. The passed normal
> + * physical memory is restricted from normal world access. The memory
> + * should be unmapped prior to this call since it becomes inaccessible
> + * during the request.
> + * Parameters are passed as:
> + * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
> + * [in] param[0].u.value.a		OPTEE_MSG_RSTMEM_* defined above
> + * [in] param[1].attr			OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
> + * [in] param[1].u.tmem.buf_ptr		physical address
> + * [in] param[1].u.tmem.size		size
> + * [in] param[1].u.tmem.shm_ref		holds restricted memory reference
> + *
> + * OPTEE_MSG_CMD_RECLAIM_RSTMEM reclaims a previously lent restricted
> + * memory reference. The physical memory is accessible by the normal world
> + * after this function has return and can be mapped again. The information
> + * is passed as:
> + * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
> + * [in] param[0].u.value.a		holds restricted memory cookie
> + *
> + * OPTEE_MSG_CMD_GET_RSTMEM_CONFIG get configuration for a specific
> + * restricted memory use case. Parameters are passed as:
> + * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INOUT
> + * [in] param[0].value.a		OPTEE_MSG_RSTMEM_*
> + * [in] param[1].attr			OPTEE_MSG_ATTR_TYPE_{R,F}MEM_OUTPUT
> + * [in] param[1].u.{r,f}mem		Buffer or NULL
> + * [in] param[1].u.{r,f}mem.size	Provided size of buffer or 0 for query
> + * output for the restricted use case:
> + * [out] param[0].value.a		Minimal size of SDP memory
> + * [out] param[0].value.b		Required alignment of size and start of
> + *					restricted memory
> + * [out] param[1].{r,f}mem.size		Size of output data
> + * [out] param[1].{r,f}mem		If non-NULL, contains an array of
> + *					uint16_t holding endpoints that
> + *					must be included when lending
> + *					memory for this use case
> + *
> + * OPTEE_MSG_CMD_ASSIGN_RSTMEM assigns use-case to restricted memory
> + * previously lent using the FFA_LEND framework ABI. Parameters are passed
> + * as:
> + * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT
> + * [in] param[0].u.value.a		holds restricted memory cookie
> + * [in] param[0].u.value.b		OPTEE_MSG_RSTMEM_* defined above
>   */
>  #define OPTEE_MSG_CMD_OPEN_SESSION	0
>  #define OPTEE_MSG_CMD_INVOKE_COMMAND	1
> @@ -346,6 +401,10 @@ struct optee_msg_arg {
>  #define OPTEE_MSG_CMD_UNREGISTER_SHM	5
>  #define OPTEE_MSG_CMD_DO_BOTTOM_HALF	6
>  #define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF	7
> +#define OPTEE_MSG_CMD_LEND_RSTMEM	8
> +#define OPTEE_MSG_CMD_RECLAIM_RSTMEM	9
> +#define OPTEE_MSG_CMD_GET_RSTMEM_CONFIG	10
> +#define OPTEE_MSG_CMD_ASSIGN_RSTMEM	11
>  #define OPTEE_MSG_FUNCID_CALL_WITH_ARG	0x0004
>  
>  #endif /* _OPTEE_MSG_H */
> diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
> index 879426300821..abc379ce190c 100644
> --- a/drivers/tee/optee/optee_smc.h
> +++ b/drivers/tee/optee/optee_smc.h
> @@ -264,7 +264,6 @@ struct optee_smc_get_shm_config_result {
>  #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM	BIT(0)
>  /* Secure world can communicate via previously unregistered shared memory */
>  #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM	BIT(1)
> -
>  /*
>   * Secure world supports commands "register/unregister shared memory",
>   * secure world accepts command buffers located in any parts of non-secure RAM
> @@ -280,6 +279,10 @@ struct optee_smc_get_shm_config_result {
>  #define OPTEE_SMC_SEC_CAP_RPC_ARG		BIT(6)
>  /* Secure world supports probing for RPMB device if needed */
>  #define OPTEE_SMC_SEC_CAP_RPMB_PROBE		BIT(7)
> +/* Secure world supports Secure Data Path */
> +#define OPTEE_SMC_SEC_CAP_SDP			BIT(8)
> +/* Secure world supports dynamic restricted memory */
> +#define OPTEE_SMC_SEC_CAP_DYNAMIC_RSTMEM	BIT(9)
>  
>  #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES	9
>  #define OPTEE_SMC_EXCHANGE_CAPABILITIES \
> @@ -451,6 +454,72 @@ struct optee_smc_disable_shm_cache_result {
>  
>  /* See OPTEE_SMC_CALL_WITH_REGD_ARG above */
>  #define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG	19
> +/*
> + * Get Secure Data Path memory config
> + *
> + * Returns the Secure Data Path memory config.
> + *
> + * Call register usage:
> + * a0   SMC Function ID, OPTEE_SMC_GET_SDP_CONFIG
> + * a2-6	Not used, must be zero
> + * a7	Hypervisor Client ID register
> + *
> + * Have config return register usage:
> + * a0	OPTEE_SMC_RETURN_OK
> + * a1	Physical address of start of SDP memory
> + * a2	Size of SDP memory
> + * a3	Not used
> + * a4-7	Preserved
> + *
> + * Not available register usage:
> + * a0	OPTEE_SMC_RETURN_ENOTAVAIL
> + * a1-3 Not used
> + * a4-7	Preserved
> + */
> +#define OPTEE_SMC_FUNCID_GET_SDP_CONFIG		20

Let's have a consistent ABI naming here. I think RSTMEM is more generic
rather than SDP, so let's use same naming convention as we use for FF-A
ABI.

-Sumit

> +#define OPTEE_SMC_GET_SDP_CONFIG \
> +	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SDP_CONFIG)
> +
> +struct optee_smc_get_sdp_config_result {
> +	unsigned long status;
> +	unsigned long start;
> +	unsigned long size;
> +	unsigned long flags;
> +};
> +
> +/*
> + * Get Secure Data Path dynamic memory config
> + *
> + * Returns the Secure Data Path dynamic memory config.
> + *
> + * Call register usage:
> + * a0	SMC Function ID, OPTEE_SMC_GET_DYN_SHM_CONFIG
> + * a2-6	Not used, must be zero
> + * a7	Hypervisor Client ID register
> + *
> + * Have config return register usage:
> + * a0	OPTEE_SMC_RETURN_OK
> + * a1	Minamal size of SDP memory
> + * a2	Required alignment of size and start of registered SDP memory
> + * a3	Not used
> + * a4-7	Preserved
> + *
> + * Not available register usage:
> + * a0	OPTEE_SMC_RETURN_ENOTAVAIL
> + * a1-3 Not used
> + * a4-7	Preserved
> + */
> +
> +#define OPTEE_SMC_FUNCID_GET_DYN_SDP_CONFIG	21
> +#define OPTEE_SMC_GET_DYN_SDP_CONFIG \
> +	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_DYN_SDP_CONFIG)
> +
> +struct optee_smc_get_dyn_sdp_config_result {
> +	unsigned long status;
> +	unsigned long size;
> +	unsigned long align;
> +	unsigned long flags;
> +};
>  
>  /*
>   * Resume from RPC (for example after processing a foreign interrupt)
> -- 
> 2.43.0
> 


From sumit.garg at kernel.org  Mon Mar 24 23:33:34 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 12:03:34 +0530
Subject: [PATCH v6 05/10] tee: implement restricted DMA-heap
In-Reply-To: <20250305130634.1850178-6-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-6-jens.wiklander@linaro.org>
Message-ID: <Z-JOPgcWlpTlskgd@sumit-X1>

Hi Jens,

On Wed, Mar 05, 2025 at 02:04:11PM +0100, Jens Wiklander wrote:
> Implement DMA heap for restricted DMA-buf allocation in the TEE
> subsystem.
> 
> Restricted memory refers to memory buffers behind a hardware enforced
> firewall. It is not accessible to the kernel during normal circumstances
> but rather only accessible to certain hardware IPs or CPUs executing in
> higher or differently privileged mode than the kernel itself. This
> interface allows to allocate and manage such restricted memory buffers
> via interaction with a TEE implementation.
> 
> The restricted memory is allocated for a specific use-case, like Secure
> Video Playback, Trusted UI, or Secure Video Recording where certain
> hardware devices can access the memory.
> 
> The DMA-heaps are enabled explicitly by the TEE backend driver. The TEE
> backend drivers needs to implement restricted memory pool to manage the
> restricted memory.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/Makefile      |   1 +
>  drivers/tee/tee_heap.c    | 470 ++++++++++++++++++++++++++++++++++++++
>  drivers/tee/tee_private.h |   6 +
>  include/linux/tee_core.h  |  62 +++++
>  4 files changed, 539 insertions(+)
>  create mode 100644 drivers/tee/tee_heap.c
> 
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> index 5488cba30bd2..949a6a79fb06 100644
> --- a/drivers/tee/Makefile
> +++ b/drivers/tee/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_TEE) += tee.o
>  tee-objs += tee_core.o
> +tee-objs += tee_heap.o
>  tee-objs += tee_shm.o
>  tee-objs += tee_shm_pool.o
>  obj-$(CONFIG_OPTEE) += optee/
> diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c
> new file mode 100644
> index 000000000000..476ab2e27260
> --- /dev/null
> +++ b/drivers/tee/tee_heap.c
> @@ -0,0 +1,470 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025, Linaro Limited
> + */
> +
> +#include <linux/scatterlist.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-heap.h>
> +#include <linux/genalloc.h>
> +#include <linux/module.h>
> +#include <linux/scatterlist.h>
> +#include <linux/slab.h>
> +#include <linux/tee_core.h>
> +#include <linux/xarray.h>

Lets try to follow alphabetical order here.

> +
> +#include "tee_private.h"
> +
> +struct tee_dma_heap {
> +	struct dma_heap *heap;
> +	enum tee_dma_heap_id id;
> +	struct tee_rstmem_pool *pool;
> +	struct tee_device *teedev;
> +	/* Protects pool and teedev above */
> +	struct mutex mu;
> +};
> +
> +struct tee_heap_buffer {
> +	struct tee_rstmem_pool *pool;
> +	struct tee_device *teedev;
> +	size_t size;
> +	size_t offs;
> +	struct sg_table table;
> +};
> +
> +struct tee_heap_attachment {
> +	struct sg_table table;
> +	struct device *dev;
> +};
> +
> +struct tee_rstmem_static_pool {
> +	struct tee_rstmem_pool pool;
> +	struct gen_pool *gen_pool;
> +	phys_addr_t pa_base;
> +};
> +
> +#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_DMABUF_HEAPS)

Can this dependency rather be better managed via Kconfig?

> +static DEFINE_XARRAY_ALLOC(tee_dma_heap);
> +
> +static int copy_sg_table(struct sg_table *dst, struct sg_table *src)
> +{
> +	struct scatterlist *dst_sg;
> +	struct scatterlist *src_sg;
> +	int ret;
> +	int i;
> +
> +	ret = sg_alloc_table(dst, src->orig_nents, GFP_KERNEL);
> +	if (ret)
> +		return ret;
> +
> +	dst_sg = dst->sgl;
> +	for_each_sgtable_sg(src, src_sg, i) {
> +		sg_set_page(dst_sg, sg_page(src_sg), src_sg->length,
> +			    src_sg->offset);
> +		dst_sg = sg_next(dst_sg);
> +	}
> +
> +	return 0;
> +}
> +
> +static int tee_heap_attach(struct dma_buf *dmabuf,
> +			   struct dma_buf_attachment *attachment)
> +{
> +	struct tee_heap_buffer *buf = dmabuf->priv;
> +	struct tee_heap_attachment *a;
> +	int ret;
> +
> +	a = kzalloc(sizeof(*a), GFP_KERNEL);
> +	if (!a)
> +		return -ENOMEM;
> +
> +	ret = copy_sg_table(&a->table, &buf->table);
> +	if (ret) {
> +		kfree(a);
> +		return ret;
> +	}
> +
> +	a->dev = attachment->dev;
> +	attachment->priv = a;
> +
> +	return 0;
> +}
> +
> +static void tee_heap_detach(struct dma_buf *dmabuf,
> +			    struct dma_buf_attachment *attachment)
> +{
> +	struct tee_heap_attachment *a = attachment->priv;
> +
> +	sg_free_table(&a->table);
> +	kfree(a);
> +}
> +
> +static struct sg_table *
> +tee_heap_map_dma_buf(struct dma_buf_attachment *attachment,
> +		     enum dma_data_direction direction)
> +{
> +	struct tee_heap_attachment *a = attachment->priv;
> +	int ret;
> +
> +	ret = dma_map_sgtable(attachment->dev, &a->table, direction,
> +			      DMA_ATTR_SKIP_CPU_SYNC);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &a->table;
> +}
> +
> +static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
> +				   struct sg_table *table,
> +				   enum dma_data_direction direction)
> +{
> +	struct tee_heap_attachment *a = attachment->priv;
> +
> +	WARN_ON(&a->table != table);
> +
> +	dma_unmap_sgtable(attachment->dev, table, direction,
> +			  DMA_ATTR_SKIP_CPU_SYNC);
> +}
> +
> +static void tee_heap_buf_free(struct dma_buf *dmabuf)
> +{
> +	struct tee_heap_buffer *buf = dmabuf->priv;
> +	struct tee_device *teedev = buf->teedev;
> +
> +	buf->pool->ops->free(buf->pool, &buf->table);
> +	tee_device_put(teedev);
> +}
> +
> +static const struct dma_buf_ops tee_heap_buf_ops = {
> +	.attach = tee_heap_attach,
> +	.detach = tee_heap_detach,
> +	.map_dma_buf = tee_heap_map_dma_buf,
> +	.unmap_dma_buf = tee_heap_unmap_dma_buf,
> +	.release = tee_heap_buf_free,
> +};
> +
> +static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap,
> +					  unsigned long len, u32 fd_flags,
> +					  u64 heap_flags)
> +{
> +	struct tee_dma_heap *h = dma_heap_get_drvdata(heap);
> +	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +	struct tee_device *teedev = NULL;
> +	struct tee_heap_buffer *buf;
> +	struct tee_rstmem_pool *pool;
> +	struct dma_buf *dmabuf;
> +	int rc;
> +
> +	mutex_lock(&h->mu);
> +	if (tee_device_get(h->teedev)) {
> +		teedev = h->teedev;
> +		pool = h->pool;
> +	}
> +	mutex_unlock(&h->mu);
> +
> +	if (!teedev)
> +		return ERR_PTR(-EINVAL);
> +
> +	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
> +	if (!buf) {
> +		dmabuf = ERR_PTR(-ENOMEM);
> +		goto err;
> +	}
> +	buf->size = len;
> +	buf->pool = pool;
> +	buf->teedev = teedev;
> +
> +	rc = pool->ops->alloc(pool, &buf->table, len, &buf->offs);
> +	if (rc) {
> +		dmabuf = ERR_PTR(rc);
> +		goto err_kfree;
> +	}
> +
> +	exp_info.ops = &tee_heap_buf_ops;
> +	exp_info.size = len;
> +	exp_info.priv = buf;
> +	exp_info.flags = fd_flags;
> +	dmabuf = dma_buf_export(&exp_info);
> +	if (IS_ERR(dmabuf))
> +		goto err_rstmem_free;
> +
> +	return dmabuf;
> +
> +err_rstmem_free:
> +	pool->ops->free(pool, &buf->table);
> +err_kfree:
> +	kfree(buf);
> +err:
> +	tee_device_put(h->teedev);
> +	return dmabuf;
> +}
> +
> +static const struct dma_heap_ops tee_dma_heap_ops = {
> +	.allocate = tee_dma_heap_alloc,
> +};
> +
> +static const char *heap_id_2_name(enum tee_dma_heap_id id)
> +{
> +	switch (id) {
> +	case TEE_DMA_HEAP_SECURE_VIDEO_PLAY:
> +		return "restricted,secure-video";
> +	case TEE_DMA_HEAP_TRUSTED_UI:
> +		return "restricted,trusted-ui";
> +	case TEE_DMA_HEAP_SECURE_VIDEO_RECORD:
> +		return "restricted,secure-video-record";
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +static int alloc_dma_heap(struct tee_device *teedev, enum tee_dma_heap_id id,
> +			  struct tee_rstmem_pool *pool)
> +{
> +	struct dma_heap_export_info exp_info = {
> +		.ops = &tee_dma_heap_ops,
> +		.name = heap_id_2_name(id),
> +	};
> +	struct tee_dma_heap *h;
> +	int rc;
> +
> +	if (!exp_info.name)
> +		return -EINVAL;
> +
> +	if (xa_reserve(&tee_dma_heap, id, GFP_KERNEL)) {
> +		if (!xa_load(&tee_dma_heap, id))
> +			return -EEXIST;
> +		return -ENOMEM;
> +	}
> +
> +	h = kzalloc(sizeof(*h), GFP_KERNEL);
> +	if (!h)
> +		return -ENOMEM;
> +	h->id = id;
> +	h->teedev = teedev;
> +	h->pool = pool;
> +	mutex_init(&h->mu);
> +
> +	exp_info.priv = h;
> +	h->heap = dma_heap_add(&exp_info);
> +	if (IS_ERR(h->heap)) {
> +		rc = PTR_ERR(h->heap);
> +		kfree(h);
> +
> +		return rc;
> +	}
> +
> +	/* "can't fail" due to the call to xa_reserve() above */
> +	return WARN(xa_store(&tee_dma_heap, id, h, GFP_KERNEL),
> +		    "xa_store() failed");
> +}
> +
> +int tee_device_register_dma_heap(struct tee_device *teedev,
> +				 enum tee_dma_heap_id id,
> +				 struct tee_rstmem_pool *pool)
> +{
> +	struct tee_dma_heap *h;
> +	int rc;
> +
> +	h = xa_load(&tee_dma_heap, id);
> +	if (h) {
> +		mutex_lock(&h->mu);
> +		if (h->teedev) {
> +			rc = -EBUSY;
> +		} else {
> +			h->teedev = teedev;
> +			h->pool = pool;
> +			rc = 0;
> +		}
> +		mutex_unlock(&h->mu);
> +	} else {
> +		rc = alloc_dma_heap(teedev, id, pool);
> +	}
> +
> +	if (rc)
> +		dev_err(&teedev->dev, "can't register DMA heap id %d (%s)\n",
> +			id, heap_id_2_name(id));
> +
> +	return rc;
> +}
> +
> +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev)
> +{
> +	struct tee_rstmem_pool *pool;
> +	struct tee_dma_heap *h;
> +	u_long i;
> +
> +	xa_for_each(&tee_dma_heap, i, h) {
> +		if (h) {
> +			pool = NULL;
> +			mutex_lock(&h->mu);
> +			if (h->teedev == teedev) {
> +				pool = h->pool;
> +				h->teedev = NULL;
> +				h->pool = NULL;
> +			}
> +			mutex_unlock(&h->mu);
> +			if (pool)
> +				pool->ops->destroy_pool(pool);
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
> +
> +int tee_heap_update_from_dma_buf(struct tee_device *teedev,
> +				 struct dma_buf *dmabuf, size_t *offset,
> +				 struct tee_shm *shm,
> +				 struct tee_shm **parent_shm)
> +{
> +	struct tee_heap_buffer *buf;
> +	int rc;
> +
> +	/* The DMA-buf must be from our heap */
> +	if (dmabuf->ops != &tee_heap_buf_ops)
> +		return -EINVAL;
> +
> +	buf = dmabuf->priv;
> +	/* The buffer must be from the same teedev */
> +	if (buf->teedev != teedev)
> +		return -EINVAL;
> +
> +	shm->size = buf->size;
> +
> +	rc = buf->pool->ops->update_shm(buf->pool, &buf->table, buf->offs, shm,
> +					parent_shm);
> +	if (!rc && *parent_shm)
> +		*offset = buf->offs;
> +
> +	return rc;
> +}
> +#else
> +int tee_device_register_dma_heap(struct tee_device *teedev __always_unused,
> +				 enum tee_dma_heap_id id __always_unused,
> +				 struct tee_rstmem_pool *pool __always_unused)
> +{
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(tee_device_register_dma_heap);
> +
> +void
> +tee_device_unregister_all_dma_heaps(struct tee_device *teedev __always_unused)
> +{
> +}
> +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
> +
> +int tee_heap_update_from_dma_buf(struct tee_device *teedev __always_unused,
> +				 struct dma_buf *dmabuf __always_unused,
> +				 size_t *offset __always_unused,
> +				 struct tee_shm *shm __always_unused,
> +				 struct tee_shm **parent_shm __always_unused)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
> +static struct tee_rstmem_static_pool *
> +to_rstmem_static_pool(struct tee_rstmem_pool *pool)
> +{
> +	return container_of(pool, struct tee_rstmem_static_pool, pool);
> +}
> +
> +static int rstmem_pool_op_static_alloc(struct tee_rstmem_pool *pool,
> +				       struct sg_table *sgt, size_t size,
> +				       size_t *offs)
> +{
> +	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> +	phys_addr_t pa;
> +	int ret;
> +
> +	pa = gen_pool_alloc(stp->gen_pool, size);
> +	if (!pa)
> +		return -ENOMEM;
> +
> +	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
> +	if (ret) {
> +		gen_pool_free(stp->gen_pool, pa, size);
> +		return ret;
> +	}
> +
> +	sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
> +	*offs = pa - stp->pa_base;
> +
> +	return 0;
> +}
> +
> +static void rstmem_pool_op_static_free(struct tee_rstmem_pool *pool,
> +				       struct sg_table *sgt)
> +{
> +	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sgtable_sg(sgt, sg, i)
> +		gen_pool_free(stp->gen_pool, sg_phys(sg), sg->length);
> +	sg_free_table(sgt);
> +}
> +
> +static int rstmem_pool_op_static_update_shm(struct tee_rstmem_pool *pool,
> +					    struct sg_table *sgt, size_t offs,
> +					    struct tee_shm *shm,
> +					    struct tee_shm **parent_shm)
> +{
> +	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> +
> +	shm->paddr = stp->pa_base + offs;
> +	*parent_shm = NULL;
> +
> +	return 0;
> +}
> +
> +static void rstmem_pool_op_static_destroy_pool(struct tee_rstmem_pool *pool)
> +{
> +	struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> +
> +	gen_pool_destroy(stp->gen_pool);
> +	kfree(stp);
> +}
> +
> +static struct tee_rstmem_pool_ops rstmem_pool_ops_static = {
> +	.alloc = rstmem_pool_op_static_alloc,
> +	.free = rstmem_pool_op_static_free,
> +	.update_shm = rstmem_pool_op_static_update_shm,
> +	.destroy_pool = rstmem_pool_op_static_destroy_pool,
> +};
> +
> +struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
> +						     size_t size)
> +{
> +	const size_t page_mask = PAGE_SIZE - 1;
> +	struct tee_rstmem_static_pool *stp;
> +	int rc;
> +
> +	/* Check it's page aligned */
> +	if ((paddr | size) & page_mask)
> +		return ERR_PTR(-EINVAL);
> +
> +	stp = kzalloc(sizeof(*stp), GFP_KERNEL);
> +	if (!stp)
> +		return ERR_PTR(-ENOMEM);
> +
> +	stp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
> +	if (!stp->gen_pool) {
> +		rc = -ENOMEM;
> +		goto err_free;
> +	}
> +
> +	rc = gen_pool_add(stp->gen_pool, paddr, size, -1);
> +	if (rc)
> +		goto err_free_pool;
> +
> +	stp->pool.ops = &rstmem_pool_ops_static;
> +	stp->pa_base = paddr;
> +	return &stp->pool;
> +
> +err_free_pool:
> +	gen_pool_destroy(stp->gen_pool);
> +err_free:
> +	kfree(stp);
> +
> +	return ERR_PTR(rc);
> +}
> +EXPORT_SYMBOL_GPL(tee_rstmem_static_pool_alloc);
> diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> index 9bc50605227c..6c6ff5d5eed2 100644
> --- a/drivers/tee/tee_private.h
> +++ b/drivers/tee/tee_private.h
> @@ -8,6 +8,7 @@
>  #include <linux/cdev.h>
>  #include <linux/completion.h>
>  #include <linux/device.h>
> +#include <linux/dma-buf.h>
>  #include <linux/kref.h>
>  #include <linux/mutex.h>
>  #include <linux/types.h>
> @@ -24,4 +25,9 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
>  struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
>  					  unsigned long addr, size_t length);
>  
> +int tee_heap_update_from_dma_buf(struct tee_device *teedev,
> +				 struct dma_buf *dmabuf, size_t *offset,
> +				 struct tee_shm *shm,
> +				 struct tee_shm **parent_shm);
> +
>  #endif /*TEE_PRIVATE_H*/
> diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
> index a38494d6b5f4..16ef078247ae 100644
> --- a/include/linux/tee_core.h
> +++ b/include/linux/tee_core.h
> @@ -8,9 +8,11 @@
>  
>  #include <linux/cdev.h>
>  #include <linux/device.h>
> +#include <linux/dma-buf.h>
>  #include <linux/idr.h>
>  #include <linux/kref.h>
>  #include <linux/list.h>
> +#include <linux/scatterlist.h>
>  #include <linux/tee.h>
>  #include <linux/tee_drv.h>
>  #include <linux/types.h>
> @@ -30,6 +32,12 @@
>  #define TEE_DEVICE_FLAG_REGISTERED	0x1
>  #define TEE_MAX_DEV_NAME_LEN		32
>  
> +enum tee_dma_heap_id {
> +	TEE_DMA_HEAP_SECURE_VIDEO_PLAY = 1,
> +	TEE_DMA_HEAP_TRUSTED_UI,
> +	TEE_DMA_HEAP_SECURE_VIDEO_RECORD,
> +};
> +
>  /**
>   * struct tee_device - TEE Device representation
>   * @name:	name of device
> @@ -116,6 +124,33 @@ struct tee_desc {
>  	u32 flags;
>  };
>  
> +/**
> + * struct tee_rstmem_pool - restricted memory pool
> + * @ops:		operations
> + *
> + * This is an abstract interface where this struct is expected to be
> + * embedded in another struct specific to the implementation.
> + */
> +struct tee_rstmem_pool {
> +	const struct tee_rstmem_pool_ops *ops;
> +};
> +
> +/**
> + * struct tee_rstmem_pool_ops - restricted memory pool operations
> + * @alloc:		called when allocating restricted memory
> + * @free:		called when freeing restricted memory
> + * @destroy_pool:	called when destroying the pool
> + */
> +struct tee_rstmem_pool_ops {
> +	int (*alloc)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
> +		     size_t size, size_t *offs);
> +	void (*free)(struct tee_rstmem_pool *pool, struct sg_table *sgt);
> +	int (*update_shm)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
> +			  size_t offs, struct tee_shm *shm,
> +			  struct tee_shm **parent_shm);

This API isn't descibed in kdoc comment above. Can you descibe the role
of this API and when it's needed?

-Sumit

> +	void (*destroy_pool)(struct tee_rstmem_pool *pool);
> +};
> +
>  /**
>   * tee_device_alloc() - Allocate a new struct tee_device instance
>   * @teedesc:	Descriptor for this driver
> @@ -154,6 +189,11 @@ int tee_device_register(struct tee_device *teedev);
>   */
>  void tee_device_unregister(struct tee_device *teedev);
>  
> +int tee_device_register_dma_heap(struct tee_device *teedev,
> +				 enum tee_dma_heap_id id,
> +				 struct tee_rstmem_pool *pool);
> +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev);
> +
>  /**
>   * tee_device_set_dev_groups() - Set device attribute groups
>   * @teedev:	Device to register
> @@ -229,6 +269,28 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
>  	pool->ops->destroy_pool(pool);
>  }
>  
> +/**
> + * tee_rstmem_static_pool_alloc() - Create a restricted memory manager
> + * @paddr:	Physical address of start of pool
> + * @size:	Size in bytes of the pool
> + *
> + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> + */
> +struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
> +						     size_t size);
> +
> +/**
> + * tee_rstmem_pool_free() - Free a restricted memory pool
> + * @pool:	The restricted memory pool to free
> + *
> + * There must be no remaining restricted memory allocated from this pool
> + * when this function is called.
> + */
> +static inline void tee_rstmem_pool_free(struct tee_rstmem_pool *pool)
> +{
> +	pool->ops->destroy_pool(pool);
> +}
> +
>  /**
>   * tee_get_drvdata() - Return driver_data pointer
>   * @returns the driver_data pointer supplied to tee_register().
> -- 
> 2.43.0
> 


From sumit.garg at kernel.org  Mon Mar 24 23:50:30 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 12:20:30 +0530
Subject: [PATCH v6 06/10] tee: new ioctl to a register tee_shm from a
 dmabuf file descriptor
In-Reply-To: <20250305130634.1850178-7-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-7-jens.wiklander@linaro.org>
Message-ID: <Z-JSNoALMOoyfOXu@sumit-X1>

Hi Jens,

On Wed, Mar 05, 2025 at 02:04:12PM +0100, Jens Wiklander wrote:
> From: Etienne Carriere <etienne.carriere at linaro.org>
> 
> Enable userspace to create a tee_shm object that refers to a dmabuf
> reference.
> 
> Userspace registers the dmabuf file descriptor as in a tee_shm object.
> The registration is completed with a tee_shm file descriptor returned to
> userspace.
> 
> Userspace is free to close the dmabuf file descriptor now since all the
> resources are now held via the tee_shm object.
> 
> Closing the tee_shm file descriptor will release all resources used by the
> tee_shm object.
> 
> This change only support dmabuf references that relates to physically
> contiguous memory buffers.
> 
> New tee_shm flag to identify tee_shm objects built from a registered
> dmabuf, TEE_SHM_DMA_BUF.
> 
> Signed-off-by: Etienne Carriere <etienne.carriere at linaro.org>
> Signed-off-by: Olivier Masse <olivier.masse at nxp.com>
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/tee_core.c    | 145 ++++++++++++++++++++++++++-----------
>  drivers/tee/tee_private.h |   1 +
>  drivers/tee/tee_shm.c     | 146 ++++++++++++++++++++++++++++++++++++--
>  include/linux/tee_core.h  |   1 +
>  include/linux/tee_drv.h   |  10 +++
>  include/uapi/linux/tee.h  |  29 ++++++++
>  6 files changed, 288 insertions(+), 44 deletions(-)
> 

I am still trying to find if we really need a separate IOCTL to register
DMA heap with TEE subsystem. Can't we initialize tee_shm as a member of
struct tee_heap_buffer in tee_dma_heap_alloc() where the allocation
happens? We can always find a reference back to tee_shm object from DMA
buffer.

-Sumit

> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index 685afcaa3ea1..3a71643766d5 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -353,6 +353,103 @@ tee_ioctl_shm_register(struct tee_context *ctx,
>  	return ret;
>  }
>  
> +static int
> +tee_ioctl_shm_register_fd(struct tee_context *ctx,
> +			  struct tee_ioctl_shm_register_fd_data __user *udata)
> +{
> +	struct tee_ioctl_shm_register_fd_data data;
> +	struct tee_shm *shm;
> +	long ret;
> +
> +	if (copy_from_user(&data, udata, sizeof(data)))
> +		return -EFAULT;
> +
> +	/* Currently no input flags are supported */
> +	if (data.flags)
> +		return -EINVAL;
> +
> +	shm = tee_shm_register_fd(ctx, data.fd);
> +	if (IS_ERR(shm))
> +		return -EINVAL;
> +
> +	data.id = shm->id;
> +	data.flags = shm->flags;
> +	data.size = shm->size;
> +
> +	if (copy_to_user(udata, &data, sizeof(data)))
> +		ret = -EFAULT;
> +	else
> +		ret = tee_shm_get_fd(shm);
> +
> +	/*
> +	 * When user space closes the file descriptor the shared memory
> +	 * should be freed or if tee_shm_get_fd() failed then it will
> +	 * be freed immediately.
> +	 */
> +	tee_shm_put(shm);
> +	return ret;
> +}
> +
> +static int param_from_user_memref(struct tee_context *ctx,
> +				  struct tee_param_memref *memref,
> +				  struct tee_ioctl_param *ip)
> +{
> +	struct tee_shm *shm;
> +	size_t offs = 0;
> +
> +	/*
> +	 * If a NULL pointer is passed to a TA in the TEE,
> +	 * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
> +	 * indicating a NULL memory reference.
> +	 */
> +	if (ip->c != TEE_MEMREF_NULL) {
> +		/*
> +		 * If we fail to get a pointer to a shared
> +		 * memory object (and increase the ref count)
> +		 * from an identifier we return an error. All
> +		 * pointers that has been added in params have
> +		 * an increased ref count. It's the callers
> +		 * responibility to do tee_shm_put() on all
> +		 * resolved pointers.
> +		 */
> +		shm = tee_shm_get_from_id(ctx, ip->c);
> +		if (IS_ERR(shm))
> +			return PTR_ERR(shm);
> +
> +		/*
> +		 * Ensure offset + size does not overflow
> +		 * offset and does not overflow the size of
> +		 * the referred shared memory object.
> +		 */
> +		if ((ip->a + ip->b) < ip->a ||
> +		    (ip->a + ip->b) > shm->size) {
> +			tee_shm_put(shm);
> +			return -EINVAL;
> +		}
> +
> +		if (shm->flags & TEE_SHM_DMA_BUF) {
> +			struct tee_shm *parent_shm;
> +
> +			parent_shm = tee_shm_get_parent_shm(shm, &offs);
> +			if (parent_shm) {
> +				tee_shm_put(shm);
> +				shm = parent_shm;
> +			}
> +		}
> +	} else if (ctx->cap_memref_null) {
> +		/* Pass NULL pointer to OP-TEE */
> +		shm = NULL;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	memref->shm_offs = ip->a + offs;
> +	memref->size = ip->b;
> +	memref->shm = shm;
> +
> +	return 0;
> +}
> +
>  static int params_from_user(struct tee_context *ctx, struct tee_param *params,
>  			    size_t num_params,
>  			    struct tee_ioctl_param __user *uparams)
> @@ -360,8 +457,8 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
>  	size_t n;
>  
>  	for (n = 0; n < num_params; n++) {
> -		struct tee_shm *shm;
>  		struct tee_ioctl_param ip;
> +		int rc;
>  
>  		if (copy_from_user(&ip, uparams + n, sizeof(ip)))
>  			return -EFAULT;
> @@ -384,45 +481,10 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
>  		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> -			/*
> -			 * If a NULL pointer is passed to a TA in the TEE,
> -			 * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
> -			 * indicating a NULL memory reference.
> -			 */
> -			if (ip.c != TEE_MEMREF_NULL) {
> -				/*
> -				 * If we fail to get a pointer to a shared
> -				 * memory object (and increase the ref count)
> -				 * from an identifier we return an error. All
> -				 * pointers that has been added in params have
> -				 * an increased ref count. It's the callers
> -				 * responibility to do tee_shm_put() on all
> -				 * resolved pointers.
> -				 */
> -				shm = tee_shm_get_from_id(ctx, ip.c);
> -				if (IS_ERR(shm))
> -					return PTR_ERR(shm);
> -
> -				/*
> -				 * Ensure offset + size does not overflow
> -				 * offset and does not overflow the size of
> -				 * the referred shared memory object.
> -				 */
> -				if ((ip.a + ip.b) < ip.a ||
> -				    (ip.a + ip.b) > shm->size) {
> -					tee_shm_put(shm);
> -					return -EINVAL;
> -				}
> -			} else if (ctx->cap_memref_null) {
> -				/* Pass NULL pointer to OP-TEE */
> -				shm = NULL;
> -			} else {
> -				return -EINVAL;
> -			}
> -
> -			params[n].u.memref.shm_offs = ip.a;
> -			params[n].u.memref.size = ip.b;
> -			params[n].u.memref.shm = shm;
> +			rc = param_from_user_memref(ctx, &params[n].u.memref,
> +						    &ip);
> +			if (rc)
> +				return rc;
>  			break;
>  		default:
>  			/* Unknown attribute */
> @@ -827,6 +889,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		return tee_ioctl_shm_alloc(ctx, uarg);
>  	case TEE_IOC_SHM_REGISTER:
>  		return tee_ioctl_shm_register(ctx, uarg);
> +	case TEE_IOC_SHM_REGISTER_FD:
> +		return tee_ioctl_shm_register_fd(ctx, uarg);
>  	case TEE_IOC_OPEN_SESSION:
>  		return tee_ioctl_open_session(ctx, uarg);
>  	case TEE_IOC_INVOKE:
> @@ -1288,3 +1352,4 @@ MODULE_AUTHOR("Linaro");
>  MODULE_DESCRIPTION("TEE Driver");
>  MODULE_VERSION("1.0");
>  MODULE_LICENSE("GPL v2");
> +MODULE_IMPORT_NS("DMA_BUF");
> diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> index 6c6ff5d5eed2..aad7f6c7e0f0 100644
> --- a/drivers/tee/tee_private.h
> +++ b/drivers/tee/tee_private.h
> @@ -24,6 +24,7 @@ void teedev_ctx_put(struct tee_context *ctx);
>  struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
>  struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
>  					  unsigned long addr, size_t length);
> +struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs);
>  
>  int tee_heap_update_from_dma_buf(struct tee_device *teedev,
>  				 struct dma_buf *dmabuf, size_t *offset,
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index daf6e5cfd59a..8b79918468b5 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -4,6 +4,7 @@
>   */
>  #include <linux/anon_inodes.h>
>  #include <linux/device.h>
> +#include <linux/dma-buf.h>
>  #include <linux/idr.h>
>  #include <linux/io.h>
>  #include <linux/mm.h>
> @@ -15,6 +16,16 @@
>  #include <linux/highmem.h>
>  #include "tee_private.h"
>  
> +/* extra references appended to shm object for registered shared memory */
> +struct tee_shm_dmabuf_ref {
> +	struct tee_shm shm;
> +	size_t offset;
> +	struct dma_buf *dmabuf;
> +	struct dma_buf_attachment *attach;
> +	struct sg_table *sgt;
> +	struct tee_shm *parent_shm;
> +};
> +
>  static void shm_put_kernel_pages(struct page **pages, size_t page_count)
>  {
>  	size_t n;
> @@ -45,7 +56,23 @@ static void release_registered_pages(struct tee_shm *shm)
>  
>  static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
>  {
> -	if (shm->flags & TEE_SHM_POOL) {
> +	struct tee_shm *parent_shm = NULL;
> +	void *p = shm;
> +
> +	if (shm->flags & TEE_SHM_DMA_BUF) {
> +		struct tee_shm_dmabuf_ref *ref;
> +
> +		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
> +		parent_shm = ref->parent_shm;
> +		p = ref;
> +		if (ref->attach) {
> +			dma_buf_unmap_attachment(ref->attach, ref->sgt,
> +						 DMA_BIDIRECTIONAL);
> +
> +			dma_buf_detach(ref->dmabuf, ref->attach);
> +		}
> +		dma_buf_put(ref->dmabuf);
> +	} else if (shm->flags & TEE_SHM_POOL) {
>  		teedev->pool->ops->free(teedev->pool, shm);
>  	} else if (shm->flags & TEE_SHM_DYNAMIC) {
>  		int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
> @@ -57,9 +84,10 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
>  		release_registered_pages(shm);
>  	}
>  
> -	teedev_ctx_put(shm->ctx);
> +	if (shm->ctx)
> +		teedev_ctx_put(shm->ctx);
>  
> -	kfree(shm);
> +	kfree(p);
>  
>  	tee_device_put(teedev);
>  }
> @@ -169,7 +197,7 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
>   * tee_client_invoke_func(). The memory allocated is later freed with a
>   * call to tee_shm_free().
>   *
> - * @returns a pointer to 'struct tee_shm'
> + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
>   */
>  struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
>  {
> @@ -179,6 +207,116 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
>  }
>  EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
>  
> +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
> +{
> +	struct tee_shm_dmabuf_ref *ref;
> +	int rc;
> +
> +	if (!tee_device_get(ctx->teedev))
> +		return ERR_PTR(-EINVAL);
> +
> +	teedev_ctx_get(ctx);
> +
> +	ref = kzalloc(sizeof(*ref), GFP_KERNEL);
> +	if (!ref) {
> +		rc = -ENOMEM;
> +		goto err_put_tee;
> +	}
> +
> +	refcount_set(&ref->shm.refcount, 1);
> +	ref->shm.ctx = ctx;
> +	ref->shm.id = -1;
> +	ref->shm.flags = TEE_SHM_DMA_BUF;
> +
> +	ref->dmabuf = dma_buf_get(fd);
> +	if (IS_ERR(ref->dmabuf)) {
> +		rc = PTR_ERR(ref->dmabuf);
> +		goto err_kfree_ref;
> +	}
> +
> +	rc = tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf,
> +					  &ref->offset, &ref->shm,
> +					  &ref->parent_shm);
> +	if (!rc)
> +		goto out;
> +	if (rc != -EINVAL)
> +		goto err_put_dmabuf;
> +
> +	ref->attach = dma_buf_attach(ref->dmabuf, &ctx->teedev->dev);
> +	if (IS_ERR(ref->attach)) {
> +		rc = PTR_ERR(ref->attach);
> +		goto err_put_dmabuf;
> +	}
> +
> +	ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
> +	if (IS_ERR(ref->sgt)) {
> +		rc = PTR_ERR(ref->sgt);
> +		goto err_detach;
> +	}
> +
> +	if (sg_nents(ref->sgt->sgl) != 1) {
> +		rc = PTR_ERR(ref->sgt->sgl);
> +		goto err_unmap_attachement;
> +	}
> +
> +	ref->shm.paddr = page_to_phys(sg_page(ref->sgt->sgl));
> +	ref->shm.size = ref->sgt->sgl->length;
> +
> +out:
> +	mutex_lock(&ref->shm.ctx->teedev->mutex);
> +	ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
> +				1, 0, GFP_KERNEL);
> +	mutex_unlock(&ref->shm.ctx->teedev->mutex);
> +	if (ref->shm.id < 0) {
> +		rc = ref->shm.id;
> +		if (ref->attach)
> +			goto err_unmap_attachement;
> +		goto err_put_dmabuf;
> +	}
> +
> +	return &ref->shm;
> +
> +err_unmap_attachement:
> +	dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL);
> +err_detach:
> +	dma_buf_detach(ref->dmabuf, ref->attach);
> +err_put_dmabuf:
> +	dma_buf_put(ref->dmabuf);
> +err_kfree_ref:
> +	kfree(ref);
> +err_put_tee:
> +	teedev_ctx_put(ctx);
> +	tee_device_put(ctx->teedev);
> +
> +	return ERR_PTR(rc);
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_register_fd);
> +
> +struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs)
> +{
> +	struct tee_shm *parent_shm = NULL;
> +
> +	if (shm->flags & TEE_SHM_DMA_BUF) {
> +		struct tee_shm_dmabuf_ref *ref;
> +
> +		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
> +		if (ref->parent_shm) {
> +			/*
> +			 * the shm already has one reference to
> +			 * ref->parent_shm so we should be clear of 0.
> +			 * We're getting another reference since the caller
> +			 * of this function expects to put the returned
> +			 * parent_shm when it's done with it.
> +			 */
> +			parent_shm = ref->parent_shm;
> +			refcount_inc(&parent_shm->refcount);
> +			*offs = ref->offset;
> +		}
> +	}
> +
> +	return parent_shm;
> +}
> +
>  /**
>   * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared
>   *			      kernel buffer
> diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
> index 16ef078247ae..6bd833b6d0e1 100644
> --- a/include/linux/tee_core.h
> +++ b/include/linux/tee_core.h
> @@ -28,6 +28,7 @@
>  #define TEE_SHM_USER_MAPPED	BIT(1)  /* Memory mapped in user space */
>  #define TEE_SHM_POOL		BIT(2)  /* Memory allocated from pool */
>  #define TEE_SHM_PRIV		BIT(3)  /* Memory private to TEE driver */
> +#define TEE_SHM_DMA_BUF		BIT(4)	/* Memory with dma-buf handle */
>  
>  #define TEE_DEVICE_FLAG_REGISTERED	0x1
>  #define TEE_MAX_DEV_NAME_LEN		32
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index a54c203000ed..824f1251de60 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -116,6 +116,16 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
>  struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
>  					    void *addr, size_t length);
>  
> +/**
> + * tee_shm_register_fd() - Register shared memory from file descriptor
> + *
> + * @ctx:	Context that allocates the shared memory
> + * @fd:		Shared memory file descriptor reference
> + *
> + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
> + */
> +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
> +
>  /**
>   * tee_shm_free() - Free shared memory
>   * @shm:	Handle to shared memory to free
> diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
> index d0430bee8292..1f9a4ac2b211 100644
> --- a/include/uapi/linux/tee.h
> +++ b/include/uapi/linux/tee.h
> @@ -118,6 +118,35 @@ struct tee_ioctl_shm_alloc_data {
>  #define TEE_IOC_SHM_ALLOC	_IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
>  				     struct tee_ioctl_shm_alloc_data)
>  
> +/**
> + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
> + * @fd:		[in] File descriptor identifying the shared memory
> + * @size:	[out] Size of shared memory to allocate
> + * @flags:	[in] Flags to/from allocation.
> + * @id:		[out] Identifier of the shared memory
> + *
> + * The flags field should currently be zero as input. Updated by the call
> + * with actual flags as defined by TEE_IOCTL_SHM_* above.
> + * This structure is used as argument for TEE_IOC_SHM_REGISTER_FD below.
> + */
> +struct tee_ioctl_shm_register_fd_data {
> +	__s64 fd;
> +	__u64 size;
> +	__u32 flags;
> +	__s32 id;
> +};
> +
> +/**
> + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
> + *
> + * Returns a file descriptor on success or < 0 on failure
> + *
> + * The returned file descriptor refers to the shared memory object in kernel
> + * land. The shared memory is freed when the descriptor is closed.
> + */
> +#define TEE_IOC_SHM_REGISTER_FD	_IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
> +				     struct tee_ioctl_shm_register_fd_data)
> +
>  /**
>   * struct tee_ioctl_buf_data - Variable sized buffer
>   * @buf_ptr:	[in] A __user pointer to a buffer
> -- 
> 2.43.0
> 


From sumit.garg at kernel.org  Mon Mar 24 23:53:45 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 12:23:45 +0530
Subject: [PATCH v6 07/10] tee: add tee_shm_alloc_cma_phys_mem()
In-Reply-To: <20250305130634.1850178-8-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-8-jens.wiklander@linaro.org>
Message-ID: <Z-JS-Tq_lxGAZfiP@sumit-X1>

Hi Jens,

On Wed, Mar 05, 2025 at 02:04:13PM +0100, Jens Wiklander wrote:
> Add tee_shm_alloc_cma_phys_mem() to allocate a physical memory using
> from the default CMA pool. The memory is represented by a tee_shm object
> using the new flag TEE_SHM_CMA_BUF to identify it as physical memory
> from CMA.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/tee_shm.c    | 55 ++++++++++++++++++++++++++++++++++++++--
>  include/linux/tee_core.h |  4 +++
>  2 files changed, 57 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 8b79918468b5..8d8341f8ebd7 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -3,8 +3,11 @@
>   * Copyright (c) 2015-2017, 2019-2021 Linaro Limited
>   */
>  #include <linux/anon_inodes.h>
> +#include <linux/cma.h>
>  #include <linux/device.h>
>  #include <linux/dma-buf.h>
> +#include <linux/dma-map-ops.h>
> +#include <linux/highmem.h>
>  #include <linux/idr.h>
>  #include <linux/io.h>
>  #include <linux/mm.h>
> @@ -13,7 +16,6 @@
>  #include <linux/tee_core.h>
>  #include <linux/uaccess.h>
>  #include <linux/uio.h>
> -#include <linux/highmem.h>
>  #include "tee_private.h"
>  
>  /* extra references appended to shm object for registered shared memory */
> @@ -59,7 +61,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
>  	struct tee_shm *parent_shm = NULL;
>  	void *p = shm;
>  
> -	if (shm->flags & TEE_SHM_DMA_BUF) {
> +	if (shm->flags & TEE_SHM_CMA_BUF) {
> +#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_CMA)

Can we rather manage this dependency via Kconfig?

> +		struct page *page = phys_to_page(shm->paddr);
> +		struct cma *cma = dev_get_cma_area(&shm->ctx->teedev->dev);
> +
> +		cma_release(cma, page, shm->size / PAGE_SIZE);
> +#endif
> +	} else if (shm->flags & TEE_SHM_DMA_BUF) {
>  		struct tee_shm_dmabuf_ref *ref;
>  
>  		ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
> @@ -341,6 +350,48 @@ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size)
>  }
>  EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf);
>  
> +struct tee_shm *tee_shm_alloc_cma_phys_mem(struct tee_context *ctx,
> +					   size_t page_count, size_t align)
> +{
> +#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_CMA)

Ditto here.

-Sumit

> +	struct tee_device *teedev = ctx->teedev;
> +	struct cma *cma = dev_get_cma_area(&teedev->dev);
> +	struct tee_shm *shm;
> +	struct page *page;
> +
> +	if (!tee_device_get(teedev))
> +		return ERR_PTR(-EINVAL);
> +
> +	page = cma_alloc(cma, page_count, align, true/*no_warn*/);
> +	if (!page)
> +		goto err_put_teedev;
> +
> +	shm = kzalloc(sizeof(*shm), GFP_KERNEL);
> +	if (!shm)
> +		goto err_cma_crelease;
> +
> +	refcount_set(&shm->refcount, 1);
> +	shm->ctx = ctx;
> +	shm->paddr = page_to_phys(page);
> +	shm->size = page_count * PAGE_SIZE;
> +	shm->flags = TEE_SHM_CMA_BUF;
> +
> +	teedev_ctx_get(ctx);
> +
> +	return shm;
> +
> +err_cma_crelease:
> +	cma_release(cma, page, page_count);
> +err_put_teedev:
> +	tee_device_put(teedev);
> +
> +	return ERR_PTR(-ENOMEM);
> +#else
> +	return ERR_PTR(-EINVAL);
> +#endif
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_alloc_cma_phys_mem);
> +
>  int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
>  			     int (*shm_register)(struct tee_context *ctx,
>  						 struct tee_shm *shm,
> diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
> index 6bd833b6d0e1..b6727d9a3556 100644
> --- a/include/linux/tee_core.h
> +++ b/include/linux/tee_core.h
> @@ -29,6 +29,7 @@
>  #define TEE_SHM_POOL		BIT(2)  /* Memory allocated from pool */
>  #define TEE_SHM_PRIV		BIT(3)  /* Memory private to TEE driver */
>  #define TEE_SHM_DMA_BUF		BIT(4)	/* Memory with dma-buf handle */
> +#define TEE_SHM_CMA_BUF		BIT(5)	/* CMA allocated memory */
>  
>  #define TEE_DEVICE_FLAG_REGISTERED	0x1
>  #define TEE_MAX_DEV_NAME_LEN		32
> @@ -307,6 +308,9 @@ void *tee_get_drvdata(struct tee_device *teedev);
>   */
>  struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size);
>  
> +struct tee_shm *tee_shm_alloc_cma_phys_mem(struct tee_context *ctx,
> +					   size_t page_count, size_t align);
> +
>  int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
>  			     int (*shm_register)(struct tee_context *ctx,
>  						 struct tee_shm *shm,
> -- 
> 2.43.0
> 


From bhe at redhat.com  Mon Mar 24 23:57:50 2025
From: bhe at redhat.com (Baoquan He)
Date: Tue, 25 Mar 2025 14:57:50 +0800
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com>
 <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
Message-ID: <Z+JT7kx+sfPqfWFA@MiWiFi-R3L-srv>

On 03/24/25 at 12:18pm, Dave Young wrote:
> On Thu, 20 Mar 2025 at 23:05, Changyuan Lyu <changyuanl at google.com> wrote:
> >
> > From: Alexander Graf <graf at amazon.com>
> >
> > We have all generic code in place now to support Kexec with KHO. This
> > patch adds a config option that depends on architecture support to
> > enable KHO support.
> >
> > Signed-off-by: Alexander Graf <graf at amazon.com>
> > Co-developed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
> > Co-developed-by: Changyuan Lyu <changyuanl at google.com>
> > Signed-off-by: Changyuan Lyu <changyuanl at google.com>
> > ---
> >  kernel/Kconfig.kexec | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> > index 4d111f871951..57db99e758a8 100644
> > --- a/kernel/Kconfig.kexec
> > +++ b/kernel/Kconfig.kexec
> > @@ -95,6 +95,21 @@ config KEXEC_JUMP
> >           Jump between original kernel and kexeced kernel and invoke
> >           code in physical address mode via KEXEC
> >
> > +config KEXEC_HANDOVER
> > +       bool "kexec handover"
> > +       depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
> > +       select MEMBLOCK_KHO_SCRATCH
> > +       select KEXEC_FILE
> > +       select DEBUG_FS
> > +       select LIBFDT
> > +       select CMA
> > +       select XXHASH
> > +       help
> > +         Allow kexec to hand over state across kernels by generating and
> > +         passing additional metadata to the target kernel. This is useful
> > +         to keep data or state alive across the kexec. For this to work,
> > +         both source and target kernels need to have this option enabled.
> > +
> 
> Have you tested kdump?  In my mind there are two issues,  one is with
> CMA enabled, it could cause kdump crashkernel memory reservation
> failures more often due to the fragmented low memory.  Secondly,  in

kho scracth memorys are reserved much later than crashkernel, we may not
need to worry about it.
====================
start_kernel()
  ......
  -->setup_arch(&command_line);
     -->arch_reserve_crashkernel();
  ......
  -->mm_core_init();
     -->kho_memory_init();

> kdump kernel dump the crazy scratch memory in vmcore is not very
> meaningful.  Otherwise I suspect this is not tested under kdump.  If
> so please disable this option for kdump.

Yeah, it's not meaningful to dump out scratch memorys into vmcore. We
may need to dig them out from eflcorehdr. While it's an optimization,
kho scratch is not big relative to the entire system memory. It can be
done in later stage. My personal opinion.



From alexander.stein at ew.tq-group.com  Tue Mar 25 00:00:00 2025
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue, 25 Mar 2025 08:00:00 +0100
Subject: [PATCH v2 9/9] arm64: dts: imx95: Describe Mali G310 GPU
In-Reply-To: <e8e9f36a-6d05-425e-a0e5-89689424336d@denx.de>
References: <20250321200625.132494-1-marex@denx.de> <6144881.lOV4Wx5bFT@steina-w>
 <e8e9f36a-6d05-425e-a0e5-89689424336d@denx.de>
Message-ID: <4643598.LvFx2qVVIh@steina-w>

Hi Marek,

Am Dienstag, 25. M?rz 2025, 00:35:41 CET schrieb Marek Vasut:
> On 3/24/25 8:02 AM, Alexander Stein wrote:
> 
> Hi,
> 
> >> @@ -1890,6 +1919,35 @@ netc_emdio: mdio at 0,0 {
> >>   			};
> >>   		};
> >>   
> >> +		gpu_blk_ctrl: reset-controller at 4d810000 {
> >> +			compatible = "nxp,imx95-gpu-blk-ctrl";
> >> +			reg = <0x0 0x4d810000 0x0 0xc>;
> >> +			#reset-cells = <1>;
> >> +			clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> >> +			assigned-clocks = <&scmi_clk IMX95_CLK_GPUAPB>;
> >> +			assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
> >> +			assigned-clock-rates = <133333333>;
> >> +			power-domains = <&scmi_devpd IMX95_PD_GPU>;
> >> +		};
> > 
> > With the SM release lf-6.12.3-1.0.0 AP does not have any access to
> > this BLK_CTRL anymore. See [1]
> I just built SM 6.12 and it still requires the reset, without reset I 
> cannot use the GPU ... or ... which BLK CTRL do you refer to ?

I'm specifically looking at [1]. AFAIU after that change AP has no access
to BLK_CTRL_GPUMIX. But this is just from looking at the changes.

Best regards
Alexander

[1] https://github.com/nxp-imx/imx-sm/commit/a3e5da9ea51144f513ac3909fa151fa7df394100
-- 
TQ-Systems GmbH | M?hlstra?e 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht M?nchen, HRB 105018
Gesch?ftsf?hrer: Detlef Schneider, R?diger Stahl, Stefan Schneider
http://www.tq-group.com/




From christian.bruel at foss.st.com  Mon Mar 24 23:59:31 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:31 +0100
Subject: [PATCH v5 5/9 RESEND] MAINTAINERS: add entry for ST STM32MP25 PCIe drivers
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-6-christian.bruel@foss.st.com>

Add myself as maintainer of STM32MP25 PCIe host and PCIe endpoint drivers

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 33b9cd11a3a4..d8f2de1a3543 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18108,6 +18108,13 @@ L:	linux-samsung-soc at vger.kernel.org
 S:	Maintained
 F:	drivers/pci/controller/dwc/pci-exynos.c
 
+PCI DRIVER FOR STM32MP25
+M:	Christian Bruel <christian.bruel at foss.st.com>
+L:	linux-pci at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pci/st,stm32-pcie-*.yaml
+F:	drivers/pci/controller/dwc/*stm32*
+
 PCI DRIVER FOR SYNOPSYS DESIGNWARE
 M:	Jingoo Han <jingoohan1 at gmail.com>
 M:	Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:27 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:27 +0100
Subject: [PATCH v5 1/9 RESEND] dt-bindings: PCI: Add STM32MP25 PCIe Root Complex bindings
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-2-christian.bruel@foss.st.com>

Document the bindings for STM32MP25 PCIe Controller configured in
root complex mode with one root port.

Supports 4 INTx and MSI interrupts from the ARM GICv2m controller.

STM32 PCIe may be in a power domain which is the case for the STM32MP25
based boards.

Supports WAKE# from wake-gpios

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/pci/st,stm32-pcie-common.yaml    |  33 ++++++
 .../bindings/pci/st,stm32-pcie-host.yaml      | 112 ++++++++++++++++++
 2 files changed, 145 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml

diff --git a/Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml b/Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml
new file mode 100644
index 000000000000..5adbff259204
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/st,stm32-pcie-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STM32MP25 PCIe RC/EP controller
+
+maintainers:
+  - Christian Bruel <christian.bruel at foss.st.com>
+
+description:
+  STM32MP25 PCIe RC/EP common properties
+
+properties:
+  clocks:
+    maxItems: 1
+    description: PCIe system clock
+
+  resets:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  access-controllers:
+    maxItems: 1
+
+required:
+  - clocks
+  - resets
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml b/Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml
new file mode 100644
index 000000000000..26f852e6f5b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/st,stm32-pcie-host.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STM32MP25 PCIe Root Complex
+
+maintainers:
+  - Christian Bruel <christian.bruel at foss.st.com>
+
+description:
+  PCIe root complex controller based on the Synopsys DesignWare PCIe core.
+
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie.yaml#
+  - $ref: /schemas/pci/st,stm32-pcie-common.yaml#
+
+properties:
+  compatible:
+    const: st,stm32mp25-pcie-rc
+
+  reg:
+    items:
+      - description: Data Bus Interface (DBI) registers.
+      - description: PCIe configuration registers.
+
+  reg-names:
+    items:
+      - const: dbi
+      - const: config
+
+  msi-parent:
+    maxItems: 1
+
+patternProperties:
+  '^pcie@[0-2],0$':
+    type: object
+    $ref: /schemas/pci/pci-pci-bridge.yaml#
+
+    properties:
+      reg:
+        maxItems: 1
+
+      phys:
+        maxItems: 1
+
+      reset-gpios:
+        description: GPIO controlled connection to PERST# signal
+        maxItems: 1
+
+      wake-gpios:
+        description: GPIO used as WAKE# input signal
+        maxItems: 1
+
+    required:
+      - phys
+      - ranges
+
+    unevaluatedProperties: false
+
+required:
+  - interrupt-map
+  - interrupt-map-mask
+  - ranges
+  - dma-ranges
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/st,stm32mp25-rcc.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/phy/phy.h>
+    #include <dt-bindings/reset/st,stm32mp25-rcc.h>
+
+    pcie at 48400000 {
+        compatible = "st,stm32mp25-pcie-rc";
+        device_type = "pci";
+        reg = <0x48400000 0x400000>,
+              <0x10000000 0x10000>;
+        reg-names = "dbi", "config";
+        #interrupt-cells = <1>;
+        interrupt-map-mask = <0 0 0 7>;
+        interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>,
+                        <0 0 0 2 &intc 0 0 GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>,
+                        <0 0 0 3 &intc 0 0 GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+                        <0 0 0 4 &intc 0 0 GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+        #address-cells = <3>;
+        #size-cells = <2>;
+        ranges = <0x01000000 0x0 0x00000000 0x10010000 0x0 0x10000>,
+                 <0x02000000 0x0 0x10020000 0x10020000 0x0 0x7fe0000>,
+                 <0x42000000 0x0 0x18000000 0x18000000 0x0 0x8000000>;
+        dma-ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x80000000>;
+        clocks = <&rcc CK_BUS_PCIE>;
+        resets = <&rcc PCIE_R>;
+        msi-parent = <&v2m0>;
+        access-controllers = <&rifsc 68>;
+        power-domains = <&CLUSTER_PD>;
+
+        pcie at 0,0 {
+          device_type = "pci";
+          reg = <0x0 0x0 0x0 0x0 0x0>;
+          phys = <&combophy PHY_TYPE_PCIE>;
+          wake-gpios = <&gpioh 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+          reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>;
+          #address-cells = <3>;
+          #size-cells = <2>;
+          ranges;
+        };
+    };
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:32 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:32 +0100
Subject: [PATCH v5 6/9 RESEND] arm64: dts: st: add PCIe pinctrl entries in stm32mp25-pinctrl.dtsi
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-7-christian.bruel@foss.st.com>

Add PCIe pinctrl entries in stm32mp25-pinctrl.dtsi
init: forces GPIO to low while probing so CLKREQ is low for
phy_init
default: restore the AFMUX after controller probe

Add Analog pins of PCIe to perform power cycle

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
index 8fdd5f020425..f0d814bc7c60 100644
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
@@ -82,6 +82,26 @@ pins {
 		};
 	};
 
+	pcie_pins_a: pcie-0 {
+		pins {
+			pinmux = <STM32_PINMUX('J', 0, AF4)>;
+			bias-disable;
+		};
+	};
+
+	pcie_init_pins_a: pcie-init-0 {
+		pins {
+			pinmux = <STM32_PINMUX('J', 0, GPIO)>;
+			output-low;
+		};
+	};
+
+	pcie_sleep_pins_a: pcie-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('J', 0, ANALOG)>;
+		};
+	};
+
 	sdmmc1_b4_pins_a: sdmmc1-b4-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:29 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:29 +0100
Subject: [PATCH v5 3/9 RESEND] dt-bindings: PCI: Add STM32MP25 PCIe Endpoint bindings
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-4-christian.bruel@foss.st.com>

STM32MP25 PCIe Controller is based on the DesignWare core configured as
end point mode from the SYSCFG register.

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
---
 .../bindings/pci/st,stm32-pcie-ep.yaml        | 67 +++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml

diff --git a/Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml
new file mode 100644
index 000000000000..fc1bbe19e616
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/st,stm32-pcie-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STM32MP25 PCIe Endpoint
+
+maintainers:
+  - Christian Bruel <christian.bruel at foss.st.com>
+
+description:
+  PCIe endpoint controller based on the Synopsys DesignWare PCIe core.
+
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
+  - $ref: /schemas/pci/st,stm32-pcie-common.yaml#
+
+properties:
+  compatible:
+    const: st,stm32mp25-pcie-ep
+
+  reg:
+    items:
+      - description: Data Bus Interface (DBI) registers.
+      - description: PCIe configuration registers.
+
+  reg-names:
+    items:
+      - const: dbi
+      - const: addr_space
+
+  reset-gpios:
+    description: GPIO controlled connection to PERST# signal
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+
+required:
+  - phys
+  - reset-gpios
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/st,stm32mp25-rcc.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/phy/phy.h>
+    #include <dt-bindings/reset/st,stm32mp25-rcc.h>
+
+    pcie-ep at 48400000 {
+        compatible = "st,stm32mp25-pcie-ep";
+        reg = <0x48400000 0x400000>,
+              <0x10000000 0x8000000>;
+        reg-names = "dbi", "addr_space";
+        clocks = <&rcc CK_BUS_PCIE>;
+        phys = <&combophy PHY_TYPE_PCIE>;
+        resets = <&rcc PCIE_R>;
+        pinctrl-names = "default", "init";
+        pinctrl-0 = <&pcie_pins_a>;
+        pinctrl-1 = <&pcie_init_pins_a>;
+        reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>;
+        access-controllers = <&rifsc 68>;
+        power-domains = <&CLUSTER_PD>;
+    };
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:35 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:35 +0100
Subject: [PATCH v5 9/9 RESEND] arm64: dts: st: Enable PCIe on the stm32mp257f-ev1 board
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-10-christian.bruel@foss.st.com>

Add PCIe RC and EP support on stm32mp257f-ev1 board.
Default to RC mode.

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1..a7646503d6b2 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -225,6 +225,27 @@ scmi_vdd_sdcard: regulator at 23 {
 	};
 };
 
+&pcie_ep {
+	pinctrl-names = "default", "init";
+	pinctrl-0 = <&pcie_pins_a>;
+	pinctrl-1 = <&pcie_init_pins_a>;
+	reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>;
+	status = "disabled";
+};
+
+&pcie_rc {
+	pinctrl-names = "default", "init", "sleep";
+	pinctrl-0 = <&pcie_pins_a>;
+	pinctrl-1 = <&pcie_init_pins_a>;
+	pinctrl-2 = <&pcie_sleep_pins_a>;
+	status = "okay";
+
+	pcie at 0,0 {
+		 reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>;
+		 wake-gpios = <&gpioh 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+	};
+};
+
 &sdmmc1 {
 	pinctrl-names = "default", "opendrain", "sleep";
 	pinctrl-0 = <&sdmmc1_b4_pins_a>;
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:30 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:30 +0100
Subject: [PATCH v5 4/9 RESEND] PCI: stm32: Add PCIe Endpoint support for STM32MP25
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-5-christian.bruel@foss.st.com>

Add driver to configure the STM32MP25 SoC PCIe Gen1 2.5GT/s or Gen2 5GT/s
controller based on the DesignWare PCIe core in endpoint mode.

Uses the common reference clock provided by the host.

The PCIe core_clk receives the pipe0_clk from the ComboPHY as input,
and the ComboPHY PLL must be locked for pipe0_clk to be ready.
Consequently, PCIe core registers cannot be accessed until the ComboPHY is
fully initialised and refclk is enabled and ready.

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 drivers/pci/controller/dwc/Kconfig         |  12 +
 drivers/pci/controller/dwc/Makefile        |   1 +
 drivers/pci/controller/dwc/pcie-stm32-ep.c | 420 +++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-stm32.h    |   1 +
 4 files changed, 434 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32-ep.c

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 0c18879b604c..4a3eb838557c 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -401,6 +401,18 @@ config PCIE_STM32
 	  This driver can also be built as a module. If so, the module
 	  will be called pcie-stm32.
 
+config PCIE_STM32_EP
+	tristate "STMicroelectronics STM32MP25 PCIe Controller (endpoint mode)"
+	depends on ARCH_STM32 || COMPILE_TEST
+	depends on PCI_ENDPOINT
+	select PCIE_DW_EP
+	help
+	  Enables endpoint support for DesignWare core based PCIe controller
+	  found in STM32MP25 SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called pcie-stm32-ep.
+
 config PCI_DRA7XX
 	tristate
 
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 576d99cb3bc5..caebd98f6dd3 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o
 obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o
 obj-$(CONFIG_PCIE_RCAR_GEN4) += pcie-rcar-gen4.o
 obj-$(CONFIG_PCIE_STM32) += pcie-stm32.o
+obj-$(CONFIG_PCIE_STM32_EP) += pcie-stm32-ep.o
 
 # The following drivers are for devices that use the generic ACPI
 # pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/controller/dwc/pcie-stm32-ep.c b/drivers/pci/controller/dwc/pcie-stm32-ep.c
new file mode 100644
index 000000000000..a8e9c5a9b127
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-stm32-ep.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics STM32MP25 PCIe endpoint driver.
+ *
+ * Copyright (C) 2025 STMicroelectronics
+ * Author: Christian Bruel <christian.bruel at foss.st.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include "pcie-designware.h"
+#include "pcie-stm32.h"
+
+enum stm32_pcie_ep_link_status {
+	STM32_PCIE_EP_LINK_DISABLED,
+	STM32_PCIE_EP_LINK_ENABLED,
+};
+
+struct stm32_pcie {
+	struct dw_pcie pci;
+	struct regmap *regmap;
+	struct reset_control *rst;
+	struct phy *phy;
+	struct clk *clk;
+	struct gpio_desc *perst_gpio;
+	enum stm32_pcie_ep_link_status link_status;
+	unsigned int perst_irq;
+};
+
+static void stm32_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	enum pci_barno bar;
+
+	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
+		dw_pcie_ep_reset_bar(pci, bar);
+}
+
+static int stm32_pcie_enable_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+
+	regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+			   STM32MP25_PCIECR_LTSSM_EN,
+			   STM32MP25_PCIECR_LTSSM_EN);
+
+	return dw_pcie_wait_for_link(pci);
+}
+
+static void stm32_pcie_disable_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+
+	regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, STM32MP25_PCIECR_LTSSM_EN, 0);
+}
+
+static int stm32_pcie_start_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+	struct dw_pcie_ep *ep = &pci->ep;
+	int ret;
+
+	if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_ENABLED) {
+		dev_dbg(pci->dev, "Link is already enabled\n");
+		return 0;
+	}
+
+	ret = stm32_pcie_enable_link(pci);
+	if (ret) {
+		dev_err(pci->dev, "PCIe cannot establish link: %d\n", ret);
+		return ret;
+	}
+
+	dw_pcie_ep_linkup(ep);
+
+	stm32_pcie->link_status = STM32_PCIE_EP_LINK_ENABLED;
+
+	enable_irq(stm32_pcie->perst_irq);
+
+	return 0;
+}
+
+static void stm32_pcie_stop_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+
+	if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_DISABLED) {
+		dev_dbg(pci->dev, "Link is already disabled\n");
+		return;
+	}
+
+	disable_irq(stm32_pcie->perst_irq);
+
+	stm32_pcie_disable_link(pci);
+
+	stm32_pcie->link_status = STM32_PCIE_EP_LINK_DISABLED;
+}
+
+static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
+				unsigned int type, u16 interrupt_num)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+	switch (type) {
+	case PCI_IRQ_INTX:
+		return dw_pcie_ep_raise_intx_irq(ep, func_no);
+	case PCI_IRQ_MSI:
+		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
+	default:
+		dev_err(pci->dev, "UNKNOWN IRQ type\n");
+		return -EINVAL;
+	}
+}
+
+static const struct pci_epc_features stm32_pcie_epc_features = {
+	.msi_capable = true,
+	.align = SZ_64K,
+};
+
+static const struct pci_epc_features*
+stm32_pcie_get_features(struct dw_pcie_ep *ep)
+{
+	return &stm32_pcie_epc_features;
+}
+
+static const struct dw_pcie_ep_ops stm32_pcie_ep_ops = {
+	.init = stm32_pcie_ep_init,
+	.raise_irq = stm32_pcie_raise_irq,
+	.get_features = stm32_pcie_get_features,
+};
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+	.start_link = stm32_pcie_start_link,
+	.stop_link = stm32_pcie_stop_link,
+};
+
+static int stm32_pcie_enable_resources(struct stm32_pcie *stm32_pcie)
+{
+	int ret;
+
+	ret = phy_init(stm32_pcie->phy);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(stm32_pcie->clk);
+	if (ret)
+		phy_exit(stm32_pcie->phy);
+
+	return ret;
+}
+
+static void stm32_pcie_disable_resources(struct stm32_pcie *stm32_pcie)
+{
+	clk_disable_unprepare(stm32_pcie->clk);
+
+	phy_exit(stm32_pcie->phy);
+}
+
+static void stm32_pcie_perst_assert(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+	struct device *dev = pci->dev;
+
+	dev_dbg(dev, "PERST asserted by host. Shutting down the PCIe link\n");
+
+	/*
+	 * Do not try to release resources if the PERST# is
+	 * asserted before the link is started.
+	 */
+	if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_DISABLED) {
+		dev_dbg(pci->dev, "Link is already disabled\n");
+		return;
+	}
+
+	stm32_pcie_disable_link(pci);
+
+	stm32_pcie_disable_resources(stm32_pcie);
+
+	pm_runtime_put_sync(dev);
+
+	stm32_pcie->link_status = STM32_PCIE_EP_LINK_DISABLED;
+}
+
+static void stm32_pcie_perst_deassert(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+	struct device *dev = pci->dev;
+	struct dw_pcie_ep *ep = &pci->ep;
+	int ret;
+
+	if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_ENABLED) {
+		dev_dbg(pci->dev, "Link is already enabled\n");
+		return;
+	}
+
+	dev_dbg(dev, "PERST de-asserted by host. Starting link training\n");
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm runtime resume failed: %d\n", ret);
+		return;
+	}
+
+	ret = stm32_pcie_enable_resources(stm32_pcie);
+	if (ret) {
+		dev_err(dev, "Failed to enable resources: %d\n", ret);
+		goto err_pm_put_sync;
+	}
+
+	ret = dw_pcie_ep_init_registers(ep);
+	if (ret) {
+		dev_err(dev, "Failed to complete initialization: %d\n", ret);
+		goto err_disable_resources;
+	}
+
+	pci_epc_init_notify(ep->epc);
+
+	ret = stm32_pcie_enable_link(pci);
+	if (ret) {
+		dev_err(dev, "PCIe Cannot establish link: %d\n", ret);
+		goto err_deinit_notify;
+	}
+
+	stm32_pcie->link_status = STM32_PCIE_EP_LINK_ENABLED;
+
+	return;
+
+err_deinit_notify:
+	pci_epc_deinit_notify(ep->epc);
+
+err_disable_resources:
+	stm32_pcie_disable_resources(stm32_pcie);
+
+err_pm_put_sync:
+	pm_runtime_put_sync(dev);
+}
+
+static irqreturn_t stm32_pcie_ep_perst_irq_thread(int irq, void *data)
+{
+	struct stm32_pcie *stm32_pcie = data;
+	struct dw_pcie *pci = &stm32_pcie->pci;
+	u32 perst;
+
+	perst = gpiod_get_value(stm32_pcie->perst_gpio);
+	if (perst)
+		stm32_pcie_perst_assert(pci);
+	else
+		stm32_pcie_perst_deassert(pci);
+
+	return IRQ_HANDLED;
+}
+
+static int stm32_add_pcie_ep(struct stm32_pcie *stm32_pcie,
+			     struct platform_device *pdev)
+{
+	struct dw_pcie_ep *ep = &stm32_pcie->pci.ep;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm runtime resume failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+				 STM32MP25_PCIECR_TYPE_MASK,
+				 STM32MP25_PCIECR_EP);
+	if (ret) {
+		goto err_pm_put_sync;
+		return ret;
+	}
+
+	reset_control_assert(stm32_pcie->rst);
+	reset_control_deassert(stm32_pcie->rst);
+
+	ep->ops = &stm32_pcie_ep_ops;
+
+	ret = dw_pcie_ep_init(ep);
+	if (ret) {
+		dev_err(dev, "failed to initialize ep: %d\n", ret);
+		goto err_pm_put_sync;
+	}
+
+	ret = stm32_pcie_enable_resources(stm32_pcie);
+	if (ret) {
+		dev_err(dev, "failed to enable resources: %d\n", ret);
+		goto err_ep_deinit;
+	}
+
+	ret = dw_pcie_ep_init_registers(ep);
+	if (ret) {
+		dev_err(dev, "Failed to initialize DWC endpoint registers\n");
+		goto err_disable_resources;
+	}
+
+	pci_epc_init_notify(ep->epc);
+
+	return 0;
+
+err_disable_resources:
+	stm32_pcie_disable_resources(stm32_pcie);
+
+err_ep_deinit:
+	dw_pcie_ep_deinit(ep);
+
+err_pm_put_sync:
+	pm_runtime_put_sync(dev);
+	return ret;
+}
+
+static int stm32_pcie_probe(struct platform_device *pdev)
+{
+	struct stm32_pcie *stm32_pcie;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL);
+	if (!stm32_pcie)
+		return -ENOMEM;
+
+	stm32_pcie->pci.dev = dev;
+	stm32_pcie->pci.ops = &dw_pcie_ops;
+
+	stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg");
+	if (IS_ERR(stm32_pcie->regmap))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap),
+				     "No syscfg specified\n");
+
+	stm32_pcie->phy = devm_phy_get(dev, NULL);
+	if (IS_ERR(stm32_pcie->phy))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy),
+				     "failed to get pcie-phy\n");
+
+	stm32_pcie->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(stm32_pcie->clk))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk),
+				     "Failed to get PCIe clock source\n");
+
+	stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(stm32_pcie->rst))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst),
+				     "Failed to get PCIe reset\n");
+
+	stm32_pcie->perst_gpio = devm_gpiod_get(dev, "reset", GPIOD_IN);
+	if (IS_ERR(stm32_pcie->perst_gpio))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio),
+				     "Failed to get reset GPIO\n");
+
+	ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, stm32_pcie);
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable pm runtime %d\n", ret);
+		return ret;
+	}
+
+	stm32_pcie->perst_irq = gpiod_to_irq(stm32_pcie->perst_gpio);
+
+	/* Will be enabled in start_link when device is initialized. */
+	irq_set_status_flags(stm32_pcie->perst_irq, IRQ_NOAUTOEN);
+
+	ret = devm_request_threaded_irq(dev, stm32_pcie->perst_irq, NULL,
+					stm32_pcie_ep_perst_irq_thread,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					"perst_irq", stm32_pcie);
+	if (ret) {
+		dev_err(dev, "Failed to request PERST IRQ: %d\n", ret);
+		return ret;
+	}
+
+	return stm32_add_pcie_ep(stm32_pcie, pdev);
+}
+
+static void stm32_pcie_remove(struct platform_device *pdev)
+{
+	struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev);
+	struct dw_pcie_ep *ep = &stm32_pcie->pci.ep;
+
+	disable_irq(stm32_pcie->perst_irq);
+
+	dw_pcie_ep_deinit(ep);
+
+	stm32_pcie_disable_resources(stm32_pcie);
+
+	pm_runtime_put_sync(&pdev->dev);
+}
+
+static const struct of_device_id stm32_pcie_ep_of_match[] = {
+	{ .compatible = "st,stm32mp25-pcie-ep" },
+	{},
+};
+
+static struct platform_driver stm32_pcie_ep_driver = {
+	.probe = stm32_pcie_probe,
+	.remove = stm32_pcie_remove,
+	.driver = {
+		.name = "stm32-ep-pcie",
+		.of_match_table = stm32_pcie_ep_of_match,
+	},
+};
+
+module_platform_driver(stm32_pcie_ep_driver);
+
+MODULE_AUTHOR("Christian Bruel <christian.bruel at foss.st.com>");
+MODULE_DESCRIPTION("STM32MP25 PCIe Endpoint Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, stm32_pcie_ep_of_match);
diff --git a/drivers/pci/controller/dwc/pcie-stm32.h b/drivers/pci/controller/dwc/pcie-stm32.h
index 387112c4e42c..09d39f04e469 100644
--- a/drivers/pci/controller/dwc/pcie-stm32.h
+++ b/drivers/pci/controller/dwc/pcie-stm32.h
@@ -9,6 +9,7 @@
 #define to_stm32_pcie(x)	dev_get_drvdata((x)->dev)
 
 #define STM32MP25_PCIECR_TYPE_MASK	GENMASK(11, 8)
+#define STM32MP25_PCIECR_EP		0
 #define STM32MP25_PCIECR_LTSSM_EN	BIT(2)
 #define STM32MP25_PCIECR_RC		BIT(10)
 
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:28 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:28 +0100
Subject: [PATCH v5 2/9 RESEND] PCI: stm32: Add PCIe host support for STM32MP25
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-3-christian.bruel@foss.st.com>

Add driver for the STM32MP25 SoC PCIe Gen1 2.5 GT/s and Gen2 5GT/s
controller based on the DesignWare PCIe core.

Supports MSI via GICv2m, Single Virtual Channel, Single Function

Supports WAKE# GPIO.

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 drivers/pci/controller/dwc/Kconfig      |  12 +
 drivers/pci/controller/dwc/Makefile     |   1 +
 drivers/pci/controller/dwc/pcie-stm32.c | 367 ++++++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-stm32.h |  15 +
 4 files changed, 395 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32.c
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32.h

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index b6d6778b0698..0c18879b604c 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -389,6 +389,18 @@ config PCIE_SPEAR13XX
 	help
 	  Say Y here if you want PCIe support on SPEAr13XX SoCs.
 
+config PCIE_STM32
+	tristate "STMicroelectronics STM32MP25 PCIe Controller (host mode)"
+	depends on ARCH_STM32 || COMPILE_TEST
+	depends on PCI_MSI
+	select PCIE_DW_HOST
+	help
+	  Enables support for the DesignWare core based PCIe host controller
+	  found in STM32MP25 SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called pcie-stm32.
+
 config PCI_DRA7XX
 	tristate
 
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index a8308d9ea986..576d99cb3bc5 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
 obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o
 obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o
 obj-$(CONFIG_PCIE_RCAR_GEN4) += pcie-rcar-gen4.o
+obj-$(CONFIG_PCIE_STM32) += pcie-stm32.o
 
 # The following drivers are for devices that use the generic ACPI
 # pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/controller/dwc/pcie-stm32.c b/drivers/pci/controller/dwc/pcie-stm32.c
new file mode 100644
index 000000000000..3937777d9eb9
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-stm32.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics STM32MP25 PCIe root complex driver.
+ *
+ * Copyright (C) 2025 STMicroelectronics
+ * Author: Christian Bruel <christian.bruel at foss.st.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/pinctrl/devinfo.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include "pcie-designware.h"
+#include "pcie-stm32.h"
+#include "../../pci.h"
+
+struct stm32_pcie {
+	struct dw_pcie pci;
+	struct regmap *regmap;
+	struct reset_control *rst;
+	struct phy *phy;
+	struct clk *clk;
+	struct gpio_desc *perst_gpio;
+	struct gpio_desc *wake_gpio;
+};
+
+static void stm32_pcie_deassert_perst(struct stm32_pcie *stm32_pcie)
+{
+	gpiod_set_value(stm32_pcie->perst_gpio, 0);
+
+	if (stm32_pcie->perst_gpio)
+		msleep(PCIE_T_RRS_READY_MS);
+}
+
+static void stm32_pcie_assert_perst(struct stm32_pcie *stm32_pcie)
+{
+	gpiod_set_value(stm32_pcie->perst_gpio, 1);
+}
+
+static int stm32_pcie_start_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+
+	return regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+				  STM32MP25_PCIECR_LTSSM_EN,
+				  STM32MP25_PCIECR_LTSSM_EN);
+}
+
+static void stm32_pcie_stop_link(struct dw_pcie *pci)
+{
+	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
+
+	regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+			   STM32MP25_PCIECR_LTSSM_EN, 0);
+}
+
+static int stm32_pcie_suspend_noirq(struct device *dev)
+{
+	struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev);
+	int ret;
+
+	ret = dw_pcie_suspend_noirq(&stm32_pcie->pci);
+	if (ret) {
+		stm32_pcie_deassert_perst(stm32_pcie);
+		return ret;
+	}
+
+	stm32_pcie_assert_perst(stm32_pcie);
+
+	clk_disable_unprepare(stm32_pcie->clk);
+
+	if (!device_wakeup_path(dev))
+		phy_exit(stm32_pcie->phy);
+
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int stm32_pcie_resume_noirq(struct device *dev)
+{
+	struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev);
+	int ret;
+
+	/*
+	 * The core clock is gated with CLKREQ# from the COMBOPHY REFCLK,
+	 * thus if no device is present, must force it low with an init pinmux
+	 * to be able to access the DBI registers.
+	 */
+	if (!IS_ERR(dev->pins->init_state))
+		ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state);
+	else
+		ret = pinctrl_pm_select_default_state(dev);
+
+	if (ret) {
+		dev_err(dev, "Failed to activate pinctrl pm state: %d\n", ret);
+		return ret;
+	}
+
+	if (!device_wakeup_path(dev)) {
+		ret = phy_init(stm32_pcie->phy);
+		if (ret) {
+			pinctrl_pm_select_default_state(dev);
+			return ret;
+		}
+	}
+
+	ret = clk_prepare_enable(stm32_pcie->clk);
+	if (ret)
+		goto err_phy_exit;
+
+	stm32_pcie_deassert_perst(stm32_pcie);
+
+	ret = dw_pcie_resume_noirq(&stm32_pcie->pci);
+	if (ret)
+		goto err_disable_clk;
+
+	pinctrl_pm_select_default_state(dev);
+
+	return 0;
+
+err_disable_clk:
+	stm32_pcie_assert_perst(stm32_pcie);
+	clk_disable_unprepare(stm32_pcie->clk);
+
+err_phy_exit:
+	phy_exit(stm32_pcie->phy);
+	pinctrl_pm_select_default_state(dev);
+
+	return ret;
+}
+
+static const struct dev_pm_ops stm32_pcie_pm_ops = {
+	NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pcie_suspend_noirq,
+				  stm32_pcie_resume_noirq)
+};
+
+static const struct dw_pcie_host_ops stm32_pcie_host_ops = {
+};
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+	.start_link = stm32_pcie_start_link,
+	.stop_link = stm32_pcie_stop_link
+};
+
+static int stm32_add_pcie_port(struct stm32_pcie *stm32_pcie,
+			       struct platform_device *pdev)
+{
+	struct device *dev = stm32_pcie->pci.dev;
+	unsigned int wake_irq;
+	int ret;
+
+	/* Start to enable resources with PERST# asserted from GPIO */
+
+	ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE);
+	if (ret)
+		return ret;
+
+	ret = phy_init(stm32_pcie->phy);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+				 STM32MP25_PCIECR_TYPE_MASK,
+				 STM32MP25_PCIECR_RC);
+	if (ret)
+		goto err_phy_exit;
+
+	stm32_pcie_deassert_perst(stm32_pcie);
+
+	if (stm32_pcie->wake_gpio) {
+		wake_irq = gpiod_to_irq(stm32_pcie->wake_gpio);
+		ret = dev_pm_set_dedicated_wake_irq(dev, wake_irq);
+		if (ret) {
+			dev_info(dev, "Failed to enable wake# %d\n", ret);
+			goto err_disable_clk;
+		}
+		irq_set_irq_type(wake_irq, IRQ_TYPE_EDGE_FALLING);
+	}
+
+	return 0;
+
+err_disable_clk:
+	stm32_pcie_assert_perst(stm32_pcie);
+	clk_disable_unprepare(stm32_pcie->clk);
+
+err_phy_exit:
+	phy_exit(stm32_pcie->phy);
+
+	return ret;
+}
+
+static void stm32_remove_pcie_port(struct stm32_pcie *stm32_pcie)
+{
+	stm32_pcie_assert_perst(stm32_pcie);
+
+	phy_exit(stm32_pcie->phy);
+}
+
+static int stm32_pcie_parse_port(struct stm32_pcie *stm32_pcie)
+{
+	struct device *dev = stm32_pcie->pci.dev;
+	struct device_node *root_port;
+
+	root_port = of_get_next_available_child(dev->of_node, NULL);
+
+	stm32_pcie->phy = devm_of_phy_get(dev, root_port, NULL);
+	if (IS_ERR(stm32_pcie->phy)) {
+		of_node_put(root_port);
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy),
+				     "Failed to get pcie-phy\n");
+	}
+
+	stm32_pcie->perst_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port),
+						       "reset", GPIOD_OUT_HIGH, NULL);
+	if (IS_ERR(stm32_pcie->perst_gpio)) {
+		if (PTR_ERR(stm32_pcie->perst_gpio) != -ENOENT) {
+			of_node_put(root_port);
+			return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio),
+					     "Failed to get reset GPIO\n");
+		}
+		stm32_pcie->perst_gpio = NULL;
+	}
+
+	stm32_pcie->wake_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port),
+						      "wake", GPIOD_IN, NULL);
+
+	if (IS_ERR(stm32_pcie->wake_gpio)) {
+		if (PTR_ERR(stm32_pcie->wake_gpio) != -ENOENT) {
+			of_node_put(root_port);
+			return dev_err_probe(dev, PTR_ERR(stm32_pcie->wake_gpio),
+					     "Failed to get wake GPIO\n");
+		}
+		stm32_pcie->wake_gpio = NULL;
+	}
+
+	of_node_put(root_port);
+
+	return 0;
+}
+
+static int stm32_pcie_probe(struct platform_device *pdev)
+{
+	struct stm32_pcie *stm32_pcie;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL);
+	if (!stm32_pcie)
+		return -ENOMEM;
+
+	stm32_pcie->pci.dev = dev;
+	stm32_pcie->pci.ops = &dw_pcie_ops;
+	stm32_pcie->pci.pp.ops = &stm32_pcie_host_ops;
+
+	stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg");
+	if (IS_ERR(stm32_pcie->regmap))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap),
+				     "No syscfg specified\n");
+
+	stm32_pcie->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(stm32_pcie->clk))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk),
+				     "Failed to get PCIe clock source\n");
+
+	stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(stm32_pcie->rst))
+		return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst),
+				     "Failed to get PCIe reset\n");
+
+	ret = stm32_pcie_parse_port(stm32_pcie);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, stm32_pcie);
+
+	ret = pm_runtime_set_active(dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to activate runtime PM %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable runtime PM %d\n", ret);
+		return ret;
+	}
+
+	pm_runtime_get_noresume(dev);
+
+	ret = stm32_add_pcie_port(stm32_pcie, pdev);
+	if (ret) {
+		pm_runtime_put_noidle(&pdev->dev);
+		return ret;
+	}
+
+	reset_control_assert(stm32_pcie->rst);
+	reset_control_deassert(stm32_pcie->rst);
+
+	ret = clk_prepare_enable(stm32_pcie->clk);
+	if (ret) {
+		dev_err(dev, "Core clock enable failed %d\n", ret);
+		goto err_remove_port;
+	}
+
+	ret = dw_pcie_host_init(&stm32_pcie->pci.pp);
+	if (ret)
+		goto err_disable_clk;
+
+	if (stm32_pcie->wake_gpio)
+		device_set_wakeup_capable(dev, true);
+
+	return 0;
+
+err_disable_clk:
+	clk_disable_unprepare(stm32_pcie->clk);
+
+err_remove_port:
+	stm32_remove_pcie_port(stm32_pcie);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	return ret;
+}
+
+static void stm32_pcie_remove(struct platform_device *pdev)
+{
+	struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev);
+	struct dw_pcie_rp *pp = &stm32_pcie->pci.pp;
+
+	if (stm32_pcie->wake_gpio)
+		device_init_wakeup(&pdev->dev, false);
+
+	dw_pcie_host_deinit(pp);
+
+	clk_disable_unprepare(stm32_pcie->clk);
+
+	stm32_remove_pcie_port(stm32_pcie);
+
+	pm_runtime_put_noidle(&pdev->dev);
+}
+
+static const struct of_device_id stm32_pcie_of_match[] = {
+	{ .compatible = "st,stm32mp25-pcie-rc" },
+	{},
+};
+
+static struct platform_driver stm32_pcie_driver = {
+	.probe = stm32_pcie_probe,
+	.remove = stm32_pcie_remove,
+	.driver = {
+		.name = "stm32-pcie",
+		.of_match_table = stm32_pcie_of_match,
+		.pm = &stm32_pcie_pm_ops,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+
+module_platform_driver(stm32_pcie_driver);
+
+MODULE_AUTHOR("Christian Bruel <christian.bruel at foss.st.com>");
+MODULE_DESCRIPTION("STM32MP25 PCIe Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, stm32_pcie_of_match);
diff --git a/drivers/pci/controller/dwc/pcie-stm32.h b/drivers/pci/controller/dwc/pcie-stm32.h
new file mode 100644
index 000000000000..387112c4e42c
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-stm32.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ST PCIe driver definitions for STM32-MP25 SoC
+ *
+ * Copyright (C) 2025 STMicroelectronics - All Rights Reserved
+ * Author: Christian Bruel <christian.bruel at foss.st.com>
+ */
+
+#define to_stm32_pcie(x)	dev_get_drvdata((x)->dev)
+
+#define STM32MP25_PCIECR_TYPE_MASK	GENMASK(11, 8)
+#define STM32MP25_PCIECR_LTSSM_EN	BIT(2)
+#define STM32MP25_PCIECR_RC		BIT(10)
+
+#define SYSCFG_PCIECR			0x6000
-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:34 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:34 +0100
Subject: [PATCH v5 8/9 RESEND] arm64: dts: st: Add PCIe Endpoint mode on stm32mp251
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-9-christian.bruel@foss.st.com>

Add pcie_ep node to support STM32 MP25 PCIe driver based on the
DesignWare PCIe core configured as Endpoint mode

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index a8abb13ab663..fe73161ed0d4 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -909,6 +909,19 @@ stmmac_axi_config_1: stmmac-axi-config {
 				};
 			};
 
+			pcie_ep: pcie-ep at 48400000 {
+				compatible = "st,stm32mp25-pcie-ep";
+				reg = <0x48400000 0x400000>,
+				      <0x10000000 0x8000000>;
+				reg-names = "dbi", "addr_space";
+				clocks = <&rcc CK_BUS_PCIE>;
+				resets = <&rcc PCIE_R>;
+				phys = <&combophy PHY_TYPE_PCIE>;
+				access-controllers = <&rifsc 68>;
+				power-domains = <&CLUSTER_PD>;
+				status = "disabled";
+			};
+
 			pcie_rc: pcie at 48400000 {
 				compatible = "st,stm32mp25-pcie-rc";
 				device_type = "pci";
-- 
2.34.1



From sumit.garg at kernel.org  Tue Mar 25 00:07:15 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 12:37:15 +0530
Subject: [PATCH v6 08/10] optee: support restricted memory allocation
In-Reply-To: <20250305130634.1850178-9-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-9-jens.wiklander@linaro.org>
Message-ID: <Z-JWIyd8cKyXQR0H@sumit-X1>

On Wed, Mar 05, 2025 at 02:04:14PM +0100, Jens Wiklander wrote:
> Add support in the OP-TEE backend driver for restricted memory
> allocation. The support is limited to only the SMC ABI and for secure
> video buffers.
> 
> OP-TEE is probed for the range of restricted physical memory and a
> memory pool allocator is initialized if OP-TEE have support for such
> memory.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/core.c    |  1 +
>  drivers/tee/optee/smc_abi.c | 44 +++++++++++++++++++++++++++++++++++--
>  2 files changed, 43 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index c75fddc83576..c7fd8040480e 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -181,6 +181,7 @@ void optee_remove_common(struct optee *optee)
>  	tee_device_unregister(optee->supp_teedev);
>  	tee_device_unregister(optee->teedev);
>  
> +	tee_device_unregister_all_dma_heaps(optee->teedev);
>  	tee_shm_pool_free(optee->pool);
>  	optee_supp_uninit(&optee->supp);
>  	mutex_destroy(&optee->call_queue.mutex);
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index cfdae266548b..a14ff0b7d3b3 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -1620,6 +1620,41 @@ static inline int optee_load_fw(struct platform_device *pdev,
>  }
>  #endif
>  
> +static int optee_sdp_pool_init(struct optee *optee)
> +{
> +	enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
> +	struct tee_rstmem_pool *pool;
> +	int rc;
> +
> +	if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP) {

Is this SDP capability an ABI yet since we haven't supported it in
upstream kernel? If no then can we rename it as
OPTEE_SMC_SEC_CAP_RSTMEM?

> +		union {
> +			struct arm_smccc_res smccc;
> +			struct optee_smc_get_sdp_config_result result;
> +		} res;
> +
> +		optee->smc.invoke_fn(OPTEE_SMC_GET_SDP_CONFIG, 0, 0, 0, 0, 0, 0,
> +				     0, &res.smccc);
> +		if (res.result.status != OPTEE_SMC_RETURN_OK) {
> +			pr_err("Secure Data Path service not available\n");
> +			return 0;
> +		}
> +
> +		pool = tee_rstmem_static_pool_alloc(res.result.start,
> +						    res.result.size);
> +		if (IS_ERR(pool))
> +			return PTR_ERR(pool);
> +
> +		rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
> +		if (rc)
> +			goto err;
> +	}
> +
> +	return 0;
> +err:
> +	pool->ops->destroy_pool(pool);
> +	return rc;
> +}
> +
>  static int optee_probe(struct platform_device *pdev)
>  {
>  	optee_invoke_fn *invoke_fn;
> @@ -1715,7 +1750,7 @@ static int optee_probe(struct platform_device *pdev)
>  	optee = kzalloc(sizeof(*optee), GFP_KERNEL);
>  	if (!optee) {
>  		rc = -ENOMEM;
> -		goto err_free_pool;
> +		goto err_free_shm_pool;
>  	}
>  
>  	optee->ops = &optee_ops;
> @@ -1788,6 +1823,10 @@ static int optee_probe(struct platform_device *pdev)
>  		pr_info("Asynchronous notifications enabled\n");
>  	}
>  
> +	rc = optee_sdp_pool_init(optee);

s/optee_sdp_pool_init/optee_rstmem_pool_init/

-Sumit

> +	if (rc)
> +		goto err_notif_uninit;
> +
>  	/*
>  	 * Ensure that there are no pre-existing shm objects before enabling
>  	 * the shm cache so that there's no chance of receiving an invalid
> @@ -1823,6 +1862,7 @@ static int optee_probe(struct platform_device *pdev)
>  		optee_disable_shm_cache(optee);
>  	optee_smc_notif_uninit_irq(optee);
>  	optee_unregister_devices();
> +	tee_device_unregister_all_dma_heaps(optee->teedev);
>  err_notif_uninit:
>  	optee_notif_uninit(optee);
>  err_close_ctx:
> @@ -1839,7 +1879,7 @@ static int optee_probe(struct platform_device *pdev)
>  	tee_device_unregister(optee->teedev);
>  err_free_optee:
>  	kfree(optee);
> -err_free_pool:
> +err_free_shm_pool:
>  	tee_shm_pool_free(pool);
>  	if (memremaped_shm)
>  		memunmap(memremaped_shm);
> -- 
> 2.43.0
> 


From krzk at kernel.org  Tue Mar 25 00:17:20 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 08:17:20 +0100
Subject: [PATCH v4 1/3] dt-bindings: arm: aspeed: add Nvidia's GB200NVL
 BMC
In-Reply-To: <20250324175926.222473-2-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
 <20250324175926.222473-2-wthai@nvidia.com>
Message-ID: <99ec033f-7557-49cb-9b73-117ddc63d6d1@kernel.org>

On 24/03/2025 18:59, Willie Thai wrote:
> Add Nvidia's  GB200NVL BMC board compatible.
> 
> Co-developed-by: Mars Yang <maryang at nvidia.com>
> Signed-off-by: Mars Yang <maryang at nvidia.com>
> Cc: Krzysztof Kozlowski <krzk at kernel.org>
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From krzk at kernel.org  Tue Mar 25 00:17:37 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 08:17:37 +0100
Subject: [PATCH v4 2/3] dt-bindings: pinctrl: aspeed,ast2600-pinctrl
In-Reply-To: <20250324175926.222473-3-wthai@nvidia.com>
References: <20250324175926.222473-1-wthai@nvidia.com>
 <20250324175926.222473-3-wthai@nvidia.com>
Message-ID: <5fb97347-927b-44e1-bc0b-ff711d342be4@kernel.org>

On 24/03/2025 18:59, Willie Thai wrote:
> Add EMMCG5 enum to compatible list of pinctrl binding for emmc enabling.
> 
> Cc: Andrew Jeffery <andrew at codeconstruct.com.au>
> Signed-off-by: Willie Thai <wthai at nvidia.com>
> ---

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>

Best regards,
Krzysztof


From mike.looijmans at topic.nl  Tue Mar 25 00:18:25 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Tue, 25 Mar 2025 08:18:25 +0100
Subject: [PATCH v2 1/3] pcie-xilinx: Wait for link-up status during initialization
References: <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.aa50e046-9cb9-4d7e-b920-ce2956412b9d@emailsignatures365.codetwo.com>
Message-ID: <20250325071832.21229-1-mike.looijmans@topic.nl>

When the driver loads, the transceiver may still be in the state of
setting up a link. Wait for that to complete before continuing. This
fixes that the PCIe core does not work when loading the PL bitstream
from userspace. There's only milliseconds between the FPGA boot and the
core initializing in that case, and the link won't be up yet. The design
only worked when the FPGA was programmed in the bootloader, as that will
give the system hundreds of milliseconds to boot.

As the PCIe spec allows up to 100 ms time to establish a link, we'll
allow up to 200ms before giving up.

Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

Changes in v2:
Split into "reset GPIO" and "wait for link" patches
Add timeout explanation

 drivers/pci/controller/pcie-xilinx.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index 0b534f73a942..2e59b91f43e0 100644
--- a/drivers/pci/controller/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
@@ -15,6 +15,7 @@
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/iopoll.h>
 #include <linux/msi.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -126,6 +127,19 @@ static inline bool xilinx_pcie_link_up(struct xilinx_pcie *pcie)
 		XILINX_PCIE_REG_PSCR_LNKUP) ? 1 : 0;
 }
 
+static int xilinx_pci_wait_link_up(struct xilinx_pcie *pcie)
+{
+	u32 val;
+
+	/*
+	 * PCIe r6.0, sec 6.6.1 provides 100ms timeout. Since this is FPGA
+	 * fabric, we're more lenient and allow 200 ms for link training.
+	 */
+	return readl_poll_timeout(pcie->reg_base + XILINX_PCIE_REG_PSCR, val,
+			(val & XILINX_PCIE_REG_PSCR_LNKUP), 2 * USEC_PER_MSEC,
+			200 * USEC_PER_MSEC);
+}
+
 /**
  * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
  * @pcie: PCIe port information
@@ -493,7 +507,7 @@ static void xilinx_pcie_init_port(struct xilinx_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
 
-	if (xilinx_pcie_link_up(pcie))
+	if (!xilinx_pci_wait_link_up(pcie))
 		dev_info(dev, "PCIe Link is UP\n");
 	else
 		dev_info(dev, "PCIe Link is DOWN\n");
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From mike.looijmans at topic.nl  Tue Mar 25 00:18:27 2025
From: mike.looijmans at topic.nl (Mike Looijmans)
Date: Tue, 25 Mar 2025 08:18:27 +0100
Subject: [PATCH v2 3/3] pcie-xilinx: Support reset GPIO for PERST#
In-Reply-To: <20250325071832.21229-1-mike.looijmans@topic.nl>
References: <20250325071832.21229-1-mike.looijmans@topic.nl>
 <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.f2f40822-7953-4b0b-896f-3a325392c185@emailsignatures365.codetwo.com>
Message-ID: <20250325071832.21229-3-mike.looijmans@topic.nl>

Support providing the PERST# reset signal through a devicetree binding.
Thus the system no longer relies on external components to perform the
bus reset.

Signed-off-by: Mike Looijmans <mike.looijmans at topic.nl>
---

Changes in v2:
Split into "reset GPIO" and "wait for link" patches
Handle GPIO defer and/or errors

 drivers/pci/controller/pcie-xilinx.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index 2e59b91f43e0..e191ab95d669 100644
--- a/drivers/pci/controller/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
@@ -18,6 +18,7 @@
 #include <linux/iopoll.h>
 #include <linux/msi.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
@@ -577,11 +578,17 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct xilinx_pcie *pcie;
 	struct pci_host_bridge *bridge;
+	struct gpio_desc *perst_gpio;
 	int err;
 
 	if (!dev->of_node)
 		return -ENODEV;
 
+	perst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(perst_gpio))
+		return dev_err_probe(dev, PTR_ERR(perst_gpio),
+				     "reset-gpios request failed\n");
+
 	bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
 	if (!bridge)
 		return -ENODEV;
@@ -596,6 +603,13 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	if (perst_gpio) {
+		usleep_range(10, 20); /* Assert the reset for ~10 us */
+		gpiod_set_value_cansleep(perst_gpio, 0);
+		/* Initial delay to provide endpoint time to restart */
+		usleep_range(1000, 2000);
+	}
+
 	xilinx_pcie_init_port(pcie);
 
 	err = xilinx_pcie_init_irq_domain(pcie);
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans at topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail


From christophe.leroy at csgroup.eu  Tue Mar 25 00:03:29 2025
From: christophe.leroy at csgroup.eu (Christophe Leroy)
Date: Tue, 25 Mar 2025 08:03:29 +0100
Subject: [PATCH] bus: fsl-mc: Remove deadcode
In-Reply-To: <20241115152055.279732-1-linux@treblig.org>
References: <20241115152055.279732-1-linux@treblig.org>
Message-ID: <174288553818.2234438.11007216946587143383.b4-ty@csgroup.eu>


On Fri, 15 Nov 2024 15:20:55 +0000, linux at treblig.org wrote:
> fsl_mc_allocator_driver_exit() was added explicitly by
> commit 1e8ac83b6caf ("bus: fsl-mc: add fsl_mc_allocator cleanup function")
> but was never used.
> 
> Remove it.
> 
> fsl_mc_portal_reset() was added in 2015 by
> commit 197f4d6a4a00 ("staging: fsl-mc: fsl-mc object allocator driver")
> but was never used.
> 
> [...]

Applied, thanks!

[1/1] bus: fsl-mc: Remove deadcode
      commit: c25951eb7518844fcb7fc9ec58e888731e8c46d0

Best regards,
-- 
Christophe Leroy <christophe.leroy at csgroup.eu>


From ghennadi.procopciuc at oss.nxp.com  Tue Mar 25 00:28:49 2025
From: ghennadi.procopciuc at oss.nxp.com (Ghennadi Procopciuc)
Date: Tue, 25 Mar 2025 09:28:49 +0200
Subject: [PATCH 2/2] clocksource/drivers/nxp-timer: Add the System Timer
 Module for the s32g platform
In-Reply-To: <20250324100008.346009-2-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
 <20250324100008.346009-2-daniel.lezcano@linaro.org>
Message-ID: <d60fca36-0beb-2574-cb82-3969bbfb58a9@oss.nxp.com>

On 3/24/2025 12:00 PM, Daniel Lezcano wrote:
> STM supports commonly required system and application software timing
> functions. STM includes a 32-bit count-up timer and four 32-bit
> compare channels with a separate interrupt source for each
> channel. The timer is driven by the STM module clock divided by an
> 8-bit prescale value (1 to 256).
> 
> STM has the following features:
>     ? One 32-bit count-up timer with an 8-bit prescaler
>     ? Four 32-bit compare channels
>     ? An independent interrupt source for each channel
>     ? Ability to stop the timer in Debug mode
> 
> The s32g platform is declined into two versions, the s32g2 and the
> s32g3. The former has a STM block with 8 timers and the latter has 12
> timers.
> 
> There is a special STM instance called STM_TS which is dedicated to
> the timestamp. The 7th STM instance STM_07 is directly tied to the
> STM_TS which means it is not usable as a clockevent.
> 
> This driver provides the core code to support both platform but only
> the s32g2 is configured. Adding the s32g3 STM support is
> straighforward.
> 
> The first probed STM is used as a clocksource, the second will be the
> broadcast timer and the rest are used as a clockevent with the
> affinity set to a CPU. The rating is higher than the ARM architected
> timers, so if they are enabled in the kernel configuration, they will
> take over and used in place of the architected timers. The plaform
> data is used to specify if a clocksource, a broadcast clockevent or a
> per-cpu clockevent is desired thus allowing more flexibility in the
> future to configure the STMs on the system.
> 
> Cc: Thomas Fossati <thomas.fossati at linaro.org>
> Co-developed-by: Larisa Grigore <Larisa.Grigore at nxp.com>
> Signed-off-by: Larisa Grigore <Larisa.Grigore at nxp.com>
> Co-developed-by: Ghennadi Procopciuc <ghennadi.procopciuc at nxp.com>
> Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc at nxp.com>
> Co-developed-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> ---
>  drivers/clocksource/Kconfig         |   9 +
>  drivers/clocksource/Makefile        |   2 +
>  drivers/clocksource/timer-nxp-stm.c | 524 ++++++++++++++++++++++++++++
>  3 files changed, 535 insertions(+)
>  create mode 100644 drivers/clocksource/timer-nxp-stm.c
> 
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 487c85259967..e86e327392af 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -763,4 +763,13 @@ config RALINK_TIMER
>  	  Enables support for system tick counter present on
>  	  Ralink SoCs RT3352 and MT7620.
>  
> +config NXP_STM_TIMER
> +	bool "NXP System Timer Module driver"
> +	depends on ARCH_S32 || COMPILE_TEST
> +	select CLKSRC_MMIO
> +	help
> +	  Support for NXP System Timer Module. It will create, in this
> +	  order, a clocksource, a broadcast clockevent and a per cpu
> +	  clockevent.
> +
>  endmenu
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 43ef16a4efa6..c3a92e6b9f94 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -92,3 +92,5 @@ obj-$(CONFIG_GXP_TIMER)			+= timer-gxp.o
>  obj-$(CONFIG_CLKSRC_LOONGSON1_PWM)	+= timer-loongson1-pwm.o
>  obj-$(CONFIG_EP93XX_TIMER)		+= timer-ep93xx.o
>  obj-$(CONFIG_RALINK_TIMER)		+= timer-ralink.o
> +obj-$(CONFIG_NXP_STM_TIMER)		+= timer-nxp-stm.o
> +
> diff --git a/drivers/clocksource/timer-nxp-stm.c b/drivers/clocksource/timer-nxp-stm.c
> new file mode 100644
> index 000000000000..b67e438487ae
> --- /dev/null
> +++ b/drivers/clocksource/timer-nxp-stm.c
> @@ -0,0 +1,524 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + * Copyright 2018,2021-2025 NXP
> + *
> + * NXP System Timer Module:
> + *
> + *  STM supports commonly required system and application software
> + *  timing functions. STM includes a 32-bit count-up timer and four
> + *  32-bit compare channels with a separate interrupt source for each
> + *  channel. The timer is driven by the STM module clock divided by an
> + *  8-bit prescale value (1 to 256). It has ability to stop the timer
> + *  in Debug mode
> + *
> + */
> +#include <linux/clk.h>
> +#include <linux/clockchips.h>
> +#include <linux/cpuhotplug.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>

Not needed.

> +#include <linux/of_irq.h>
> +#include <linux/of_device.h>

Not needed.

> +#include <linux/platform_device.h>
> +#include <linux/sched_clock.h>
> +
> +/*
> + * Each stm has 4 channels which take 0x10 Bytes register space
> + */
> +#define STM_CHANNEL(n)	(0x10 * ((n) + 1))
> +
> +#define STM_CCR			0x00
> +#define STM_CCR_CEN		BIT(0)
> +
> +#define STM_CIR			0x04
> +#define STM_CIR_CIF		BIT(0)
> +
> +#define STM_CMP			0x08
> +
> +#define STM_CR			0x00
> +#define STM_CR_TEN		BIT(0)
> +#define STM_CR_FRZ		BIT(1)
> +#define STM_CR_CPS_OFFSET	8u
> +#define STM_CR_CPS_MASK		GENMASK(15, STM_CR_CPS_OFFSET)
> +#define STM_CR_CPS(x)		(((x) << STM_CR_CPS_OFFSET) & STM_CR_CPS_MASK)

STM_CR_CPS(x) seems to be unused.

> +
> +#define STM_CNT			0x04
> +
> +#define STM_ENABLE_MASK	(STM_CR_FRZ | STM_CR_TEN)
> +
> +struct stm_clocksource {
> +	struct clocksource cs;
> +	int counter;
> +};
> +
> +struct stm_clockevent {
> +	struct clock_event_device ced;
> +	unsigned long delta;
> +};
> +
> +struct stm_timer {
> +	void __iomem *base;
> +	unsigned long rate;
> +	union {
> +		struct stm_clocksource scs;
> +		struct stm_clockevent sce;
> +	};
> +};
> +
> +static DEFINE_PER_CPU(struct stm_timer *, stm_timers);
> +
> +static struct stm_timer *stm_sched_clock;
> +
> +/**
> + * struct stm_instances - a set of counter for the STM initialized
> + *
> + * @clocksource: an integer giving the number of initialized clocksource
> + * @clockevent_per_cpu: an integer giving the number of initialized clockevent per cpu
> + * @clockevent_broadcast: an integer giving the number of initialized broadcast clockevent
> + * @features: a set of flag telling what kind of timer to initialize
> + */
> +struct stm_instances {
> +	int clocksource;
> +	int clockevent_per_cpu;
> +	int clockevent_broadcast;
> +	int features;

'unsigned int' instead of 'int' since none of these fields are expected
to contain negative values?

> +};
> +
> +#define STM_CLKSRC		BIT(0)
> +#define STM_CLKEVT_PER_CPU	BIT(1)
> +#define STM_CLKEVT_BROADCAST	BIT(2)
> +
> +static struct stm_clocksource *cs_to_scs(struct clocksource *cs)
> +{
> +	return container_of(cs, struct stm_clocksource, cs);
> +}
> +
> +static struct stm_clockevent *ced_to_sced(struct clock_event_device *ced)
> +{
> +	return container_of(ced, struct stm_clockevent, ced);
> +}
> +
> +static struct stm_timer *cs_to_stm(struct clocksource *cs)
> +{
> +	struct stm_clocksource *scs = cs_to_scs(cs);
> +
> +	return container_of(scs, struct stm_timer, scs);
> +}
> +
> +static struct stm_timer *ced_to_stm(struct clock_event_device *ced)
> +{
> +        struct stm_clockevent *sce = ced_to_sced(ced);
> +
> +        return container_of(sce, struct stm_timer, sce);
> +}
> +
> +static u64 notrace nxp_stm_read_sched_clock(void)
> +{
> +	return readl(stm_sched_clock->base + STM_CNT);
> +}
> +
> +static u32 nxp_stm_clocksource_getcnt(struct stm_timer *stm_timer)
> +{
> +	return readl(stm_timer->base + STM_CNT);
> +}
> +
> +static void nxp_stm_clocksource_setcnt(struct stm_timer *stm_timer, u32 cnt)
> +{
> +	writel(cnt, stm_timer->base + STM_CNT);
> +}
> +
> +static u64 nxp_stm_clocksource_read(struct clocksource *cs)
> +{
> +	struct stm_timer *stm_timer = cs_to_stm(cs);
> +
> +	return (u64)nxp_stm_clocksource_getcnt(stm_timer);
> +}
> +
> +static int nxp_stm_clocksource_enable(struct clocksource *cs)
> +{
> +	struct stm_timer *stm_timer = cs_to_stm(cs);
> +	u32 reg;
> +
> +	reg = readl(stm_timer->base + STM_CR);
> +	reg &= ~STM_CR_CPS_MASK;
> +	reg |= STM_ENABLE_MASK;
> +
> +	writel(reg, stm_timer->base + STM_CR);
> +
> +	return 0;
> +}
> +
> +static void nxp_stm_clocksource_disable(struct clocksource *cs)
> +{
> +	struct stm_timer *stm_timer = cs_to_stm(cs);
> +	u32 reg;
> +
> +	reg = readl(stm_timer->base + STM_CR);
> +	reg &= ~(STM_CR_CPS_MASK | STM_ENABLE_MASK);
> +
> +	writel(reg, stm_timer->base + STM_CR);
> +}
> +
> +static void nxp_stm_clocksource_suspend(struct clocksource *cs)
> +{
> +	struct stm_timer *stm_timer = cs_to_stm(cs);
> +
> +	nxp_stm_clocksource_disable(cs);
> +	stm_timer->scs.counter = nxp_stm_clocksource_getcnt(stm_timer);
> +}
> +
> +static void nxp_stm_clocksource_resume(struct clocksource *cs)
> +{
> +	struct stm_timer *stm_timer = cs_to_stm(cs);
> +
> +	nxp_stm_clocksource_setcnt(stm_timer, stm_timer->scs.counter);
> +	nxp_stm_clocksource_enable(cs);
> +}
> +
> +static int __init nxp_stm_clocksource_init(struct device *dev, const char *name,
> +					   void __iomem *base, struct clk *clk)
> +{
> +	struct stm_timer *stm_timer;
> +	int ret;
> +
> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
> +	if (!stm_timer)
> +		return -ENOMEM;
> +
> +	stm_timer->base = base;
> +	stm_timer->rate = clk_get_rate(clk);
> +
> +	stm_timer->scs.cs.name = name;
> +	stm_timer->scs.cs.rating = 460;
> +	stm_timer->scs.cs.read = nxp_stm_clocksource_read;
> +	stm_timer->scs.cs.enable = nxp_stm_clocksource_enable;
> +	stm_timer->scs.cs.disable = nxp_stm_clocksource_disable;
> +	stm_timer->scs.cs.suspend = nxp_stm_clocksource_suspend;
> +	stm_timer->scs.cs.resume = nxp_stm_clocksource_resume;
> +	stm_timer->scs.cs.mask = CLOCKSOURCE_MASK(32);
> +	stm_timer->scs.cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
> +
> +	ret = clocksource_register_hz(&stm_timer->scs.cs, stm_timer->rate);
> +	if (ret)
> +		return ret;

clocksource_unregister during remove callback for cleanup?

> +
> +	stm_sched_clock = stm_timer;
> +
> +	sched_clock_register(nxp_stm_read_sched_clock, 32, stm_timer->rate);
> +
> +	dev_set_drvdata(dev, stm_timer);

Is this used?

> +
> +	dev_dbg(dev, "Registered clocksource %s\n", name);
> +
> +	return 0;
> +}
> +
> +static int nxp_stm_clockevent_read_counter(struct stm_timer *stm_timer)
> +{
> +	return readl(stm_timer->base + STM_CNT);
> +}
> +
> +static void nxp_stm_clockevent_disable(struct stm_timer *stm_timer)
> +{
> +	/*
> +	 * The counter is shared between channels and will continue to
> +	 * be incremented. If STM_CMP value is too small, the next event can
> +	 * be lost if we don't disable the entire module.
> +	 * Disabling the entire module, makes STM not suitable as clocksource.
> +	 */
> +	writel(0, stm_timer->base + STM_CR);
> +	writel(0, stm_timer->base + STM_CHANNEL(0) + STM_CCR);> +}
> +
> +static void nxp_stm_clockevent_enable(struct stm_timer *stm_timer)
> +{
> +	u32 reg = readl(stm_timer->base + STM_CR);
> +
> +	reg &= ~STM_CR_CPS_MASK;
> +	reg |= STM_ENABLE_MASK;
> +
> +	writel(reg, stm_timer->base + STM_CR);
> +	writel(STM_CCR_CEN, stm_timer->base + STM_CHANNEL(0) + STM_CCR);
> +}
> +
> +static void nxp_stm_clockevent_irq_clr(struct stm_timer *stm_timer)
> +{
> +	/* Clear the interrupt */
> +	writel(STM_CIR_CIF, stm_timer->base + STM_CHANNEL(0) + STM_CIR);
> +}
> +
> +static void nxp_stm_clockevent_irq_ack(struct stm_timer *stm_timer)
> +{
> +	u32 val;
> +
> +	nxp_stm_clockevent_irq_clr(stm_timer);
> +
> +	/*
> +	 * Update STM_CMP value using the counter value
> +	 */
> +	val = nxp_stm_clockevent_read_counter(stm_timer) + stm_timer->sce.delta;
> +
> +	writel(val, stm_timer->base + STM_CHANNEL(0) + STM_CMP);
> +}
> +
> +static irqreturn_t nxp_stm_clockevent_interrupt(int irq, void *dev_id)
> +{
> +	struct clock_event_device *ced = dev_id;
> +	struct stm_timer *stm_timer = ced_to_stm(ced);
> +
> +	nxp_stm_clockevent_irq_ack(stm_timer);
> +
> +	/*
> +	 * stm hardware doesn't support oneshot, it will generate an
> +	 * interrupt and start the counter again so software need to
> +	 * disable the timer to stop the counter loop in ONESHOT mode.
> +	 */
> +	if (likely(clockevent_state_oneshot(ced)))
> +		nxp_stm_clockevent_disable(stm_timer);
> +
> +	ced->event_handler(ced);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int nxp_stm_clockevent_shutdown(struct clock_event_device *ced)
> +{
> +	struct stm_timer *stm_timer = ced_to_stm(ced);
> +
> +	nxp_stm_clockevent_disable(stm_timer);
> +
> +	return 0;
> +}
> +
> +static int nxp_stm_clockevent_set_next_event(unsigned long delta, struct clock_event_device *ced)
> +{
> +	struct stm_timer *stm_timer = ced_to_stm(ced);
> +	u32 val;
> +
> +	nxp_stm_clockevent_disable(stm_timer);

While examining the code base, I came across the
drivers/clocksource/timer-imx-gpt.c file, specifically the
mx1_2_set_next_event function, which includes a protection against
missing events. Using a similar approach would allow us to keep the STM
module enabled while only altering the channel's register state. This
risk can also be mitigated by adjusting min_delta_ns based on tick
frequency.

> +
> +	stm_timer->sce.delta = delta;
> +
> +	val = nxp_stm_clockevent_read_counter(stm_timer) + delta;
> +
> +	writel(val, stm_timer->base + STM_CHANNEL(0) + STM_CMP);
> +
> +	nxp_stm_clockevent_enable(stm_timer);
> +
> +	return 0;
> +}
> +
> +static int nxp_stm_clockevent_set_periodic(struct clock_event_device *ced)
> +{
> +	struct stm_timer *stm_timer = ced_to_stm(ced);
> +
> +        return nxp_stm_clockevent_set_next_event(stm_timer->rate, ced);
> +}
> +
> +static int __init nxp_stm_clockevent_broadcast_init(struct device *dev, const char *name, void __iomem *base,
> +						    int irq, struct clk *clk)
> +{
> +	struct stm_timer *stm_timer;
> +	int ret;
> +
> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
> +	if (!stm_timer)
> +		return -ENOMEM;
> +
> +	stm_timer->base = base;
> +	stm_timer->rate = clk_get_rate(clk);
> +
> +	stm_timer->sce.ced.name = name;
> +	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
> +	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
> +	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
> +	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
> +	stm_timer->sce.ced.cpumask = cpu_possible_mask;
> +	stm_timer->sce.ced.rating = 460;
> +	stm_timer->sce.ced.irq = irq;
> +
> +	nxp_stm_clockevent_irq_clr(stm_timer);
> +
> +	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
> +			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);
> +	if (ret) {
> +		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
> +		return ret;
> +	}
> +
> +	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
> +
> +	dev_dbg(dev, "Registered broadcast clockevent %s irq=%d\n", name, irq);
> +
> +	return 0;
> +}
> +
> +static int __init nxp_stm_clockevent_per_cpu_init(struct device *dev, const char *name, void __iomem *base,
> +						  int irq, struct clk *clk, int cpu)
> +{

This function duplicates a significant portion of the previous one. To
avoid code duplication, it would be beneficial to extract the common
part into a dedicated function.

> +	struct stm_timer *stm_timer;
> +	int ret;
> +
> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
> +	if (!stm_timer)
> +		return -ENOMEM;
> +
> +	stm_timer->base = base;
> +	stm_timer->rate = clk_get_rate(clk);
> +
> +	stm_timer->sce.ced.name = name;
> +	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
> +	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
> +	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
> +	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
> +	stm_timer->sce.ced.cpumask = cpumask_of(cpu);
> +	stm_timer->sce.ced.rating = 460;
> +	stm_timer->sce.ced.irq = irq;
> +
> +	nxp_stm_clockevent_irq_clr(stm_timer);
> +
> +	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
> +			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);

devm_request_irq instead ?

> +	if (ret) {
> +		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
> +		return ret;
> +	}
> +
> +	per_cpu(stm_timers, cpu) = stm_timer;
> +
> +	dev_dbg(dev, "Initialized per cpu clockevent name=%s, irq=%d, cpu=%d\n", name, irq, cpu);
> +
> +	return 0;
> +}
> +
> +static int nxp_stm_clockevent_starting_cpu(unsigned int cpu)
> +{
> +	struct stm_timer *stm_timer = per_cpu(stm_timers, cpu);
> +	int ret;
> +
> +	if (WARN_ON(!stm_timer))
> +		return -EFAULT;
> +
> +	ret = irq_force_affinity(stm_timer->sce.ced.irq, cpumask_of(cpu));
> +	if (ret)
> +		return ret;
> +
> +	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
> +
> +	return 0;
> +}
> +
> +static int __init nxp_stm_timer_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct stm_instances *stm_instances;
> +	const char *name = of_node_full_name(np);
> +	void __iomem *base;
> +	int irq, ret;
> +	struct clk *clk;
> +
> +	stm_instances = (typeof(stm_instances))of_device_get_match_data(dev);
> +	if (!stm_instances) {
> +		dev_err(dev, "No STM instances associated with a cpu");
> +		return -EINVAL;
> +	}
> +
> +	base = devm_of_iomap(dev, np, 0, NULL);
> +	if (IS_ERR(base)) {
> +		dev_err(dev, "Failed to iomap %pOFn\n", np);
> +		return PTR_ERR(base);
> +	}
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (irq <= 0) {
> +		dev_err(dev, "Failed to parse and map IRQ: %d\n", irq);
> +		return -EINVAL;
> +	}

>From commit description:

> The first probed STM is used as a clocksource, the second will be the
> broadcast timer and the rest are used as a clockevent with the
> affinity set to a CPU.

Why is the interrupt mandatory when the node is probed as a clocksource?

> +
> +	clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(clk)) {
> +		dev_err(dev, "Clock not found\n");

Missing irq_dispose_mapping ?

> +		return PTR_ERR(clk);
> +	}
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable STM timer clock: %d\n", ret);
> +		return ret;
> +	}

devm_clk_get_enabled instead of devm_clk_get + clk_prepare_enable ?

> +
> +	if (!stm_instances->clocksource && (stm_instances->features & STM_CLKSRC)) {
> +
> +		/*
> +		 * First probed STM will be a clocksource
> +		 */
> +		ret = nxp_stm_clocksource_init(dev, name, base, clk);
> +		if (ret)
> +			return ret;
> +		stm_instances->clocksource++;
> +
> +	} else if (!stm_instances->clockevent_broadcast &&
> +		   (stm_instances->features & STM_CLKEVT_BROADCAST)) {
> +
> +		/*
> +		 * Second probed STM will be a broadcast clockevent
> +		 */
> +		ret = nxp_stm_clockevent_broadcast_init(dev, name, base, irq, clk);
> +		if (ret)
> +			return ret;
> +		stm_instances->clockevent_broadcast++;
> +
> +	} else if (stm_instances->clockevent_per_cpu < num_possible_cpus() &&
> +		   (stm_instances->features & STM_CLKEVT_PER_CPU)) {
> +
> +		/*
> +		 * Next probed STM will be a per CPU clockevent, until
> +		 * we probe as much as we have CPUs available on the
> +		 * system, we do a partial initialization
> +		 */
> +		ret = nxp_stm_clockevent_per_cpu_init(dev, name, base, irq, clk,
> +						      stm_instances->clockevent_per_cpu);
> +		if (ret)
> +			return ret;
> +
> +		stm_instances->clockevent_per_cpu++;
> +
> +		/*
> +		 * The number of probed STM for per CPU clockevent is
> +		 * equal to the number of available CPUs on the
> +		 * system. We install the cpu hotplug to finish the
> +		 * initialization by registering the clockevents
> +		 */
> +		if (stm_instances->clockevent_per_cpu == num_possible_cpus()) {
> +			ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "STM timer:starting",
> +						nxp_stm_clockevent_starting_cpu, NULL);
> +			if (ret < 0)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static struct stm_instances s32g_stm_instances = { .features = STM_CLKSRC | STM_CLKEVT_PER_CPU };
> +
> +static const struct of_device_id nxp_stm_of_match[] = {
> +	{ .compatible = "nxp,s32g2-stm", &s32g_stm_instances },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
> +
> +static struct platform_driver nxp_stm_probe = {
> +	.probe	= nxp_stm_timer_probe,
> +	.driver	= {
> +		.name = "nxp-stm",
> +		.of_match_table = of_match_ptr(nxp_stm_of_match),
> +	},
> +};
> +module_platform_driver(nxp_stm_probe);
> +
> +MODULE_DESCRIPTION("NXP System Timer Module driver");
> +MODULE_LICENSE("GPL");

-- 
Regards,
Ghennadi



From christian.bruel at foss.st.com  Mon Mar 24 23:59:26 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:26 +0100
Subject: [PATCH v5 0/9 RESEND] Add STM32MP25 PCIe drivers
Message-ID: <20250325065935.908886-1-christian.bruel@foss.st.com>

Changes in v5:
   Address driver comments from Manivanna:
   - Use dw_pcie_{suspend/resume}_noirq instead of private ones.
   - Move dw_pcie_host_init() to probe
   - Add stm32_remove_pcie_port cleanup function
   - Use of_node_put in stm32_pcie_parse_port
   - Remove wakeup-source property
   - Use generic dev_pm_set_dedicated_wake_irq to support wake# irq
   
Changes in v4:
   Address bindings comments Rob Herring
   - Remove phy property form common yaml
   - Remove phy-name property
   - Move wake_gpio and reset_gpio to the host root port
   
Changes in v3:
   Address comments from Manivanna, Rob and Bjorn:
   - Move host wakeup helper to dwc core (Mani)
   - Drop num-lanes=<1> from bindings (Rob)
   - Fix PCI address of I/O region (Mani)
   - Moved PHY to a RC rootport subsection (Bjorn, Mani)
   - Replaced dma-limit quirk by dma-ranges property (Bjorn)
   - Moved out perst assert/deassert from start/stop link (Mani)
   - Drop link_up test optim (Mani)
   - DT and comments rephrasing (Bjorn)
   - Add dts entries now that the combophy entries has landed
   - Drop delaying Configuration Requests

Changes in v2:
   - Fix st,stm32-pcie-common.yaml dt_binding_check	

Changes in v1:
   Address comments from Rob Herring and Bjorn Helgaas:
   - Drop st,limit-mrrs and st,max-payload-size from this patchset
   - Remove single reset and clocks binding names and misc yaml cleanups
   - Split RC/EP common bindings to a separate schema file
   - Use correct PCIE_T_PERST_CLK_US and PCIE_T_RRS_READY_MS defines
   - Use .remove instead of .remove_new
   - Fix bar reset sequence in EP driver
   - Use cleanup blocks for error handling
   - Cosmetic fixes

Christian Bruel (9):
  dt-bindings: PCI: Add STM32MP25 PCIe Root Complex bindings
  PCI: stm32: Add PCIe host support for STM32MP25
  dt-bindings: PCI: Add STM32MP25 PCIe Endpoint bindings
  PCI: stm32: Add PCIe Endpoint support for STM32MP25
  MAINTAINERS: add entry for ST STM32MP25 PCIe drivers
  arm64: dts: st: add PCIe pinctrl entries in stm32mp25-pinctrl.dtsi
  arm64: dts: st: Add PCIe Rootcomplex mode on stm32mp251
  arm64: dts: st: Add PCIe Endpoint mode on stm32mp251
  arm64: dts: st: Enable PCIe on the stm32mp257f-ev1 board

 .../bindings/pci/st,stm32-pcie-common.yaml    |  33 ++
 .../bindings/pci/st,stm32-pcie-ep.yaml        |  67 +++
 .../bindings/pci/st,stm32-pcie-host.yaml      | 112 +++++
 MAINTAINERS                                   |   7 +
 arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi |  20 +
 arch/arm64/boot/dts/st/stm32mp251.dtsi        |  58 ++-
 arch/arm64/boot/dts/st/stm32mp257f-ev1.dts    |  21 +
 drivers/pci/controller/dwc/Kconfig            |  24 +
 drivers/pci/controller/dwc/Makefile           |   2 +
 drivers/pci/controller/dwc/pcie-stm32-ep.c    | 420 ++++++++++++++++++
 drivers/pci/controller/dwc/pcie-stm32.c       | 367 +++++++++++++++
 drivers/pci/controller/dwc/pcie-stm32.h       |  16 +
 12 files changed, 1146 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32-ep.c
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32.c
 create mode 100644 drivers/pci/controller/dwc/pcie-stm32.h

-- 
2.34.1



From christian.bruel at foss.st.com  Mon Mar 24 23:59:33 2025
From: christian.bruel at foss.st.com (Christian Bruel)
Date: Tue, 25 Mar 2025 07:59:33 +0100
Subject: [PATCH v5 7/9 RESEND] arm64: dts: st: Add PCIe Rootcomplex mode on stm32mp251
In-Reply-To: <20250325065935.908886-1-christian.bruel@foss.st.com>
References: <20250325065935.908886-1-christian.bruel@foss.st.com>
Message-ID: <20250325065935.908886-8-christian.bruel@foss.st.com>

Add pcie_rc node to support STM32 MP25 PCIe driver based on the
DesignWare PCIe core configured as Rootcomplex mode

Supports Gen1/Gen2, single lane, MSI interrupts using the ARM GICv2m

Signed-off-by: Christian Bruel <christian.bruel at foss.st.com>
---
 arch/arm64/boot/dts/st/stm32mp251.dtsi | 45 +++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008..a8abb13ab663 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -117,12 +117,20 @@ scmi_vdda18adc: regulator at 7 {
 	intc: interrupt-controller at 4ac00000 {
 		compatible = "arm,cortex-a7-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
+		#address-cells = <2>;
+		#size-cells = <2>;
 		interrupt-controller;
 		reg = <0x0 0x4ac10000 0x0 0x1000>,
 		      <0x0 0x4ac20000 0x0 0x2000>,
 		      <0x0 0x4ac40000 0x0 0x2000>,
 		      <0x0 0x4ac60000 0x0 0x2000>;
+		ranges;
+
+		v2m0: v2m at 48090000 {
+			compatible = "arm,gic-v2m-frame";
+			reg = <0x0 0x48090000 0x0 0x1000>;
+			msi-controller;
+		};
 	};
 
 	psci {
@@ -900,6 +908,41 @@ stmmac_axi_config_1: stmmac-axi-config {
 					snps,wr_osr_lmt = <0x7>;
 				};
 			};
+
+			pcie_rc: pcie at 48400000 {
+				compatible = "st,stm32mp25-pcie-rc";
+				device_type = "pci";
+				reg = <0x48400000 0x400000>,
+				      <0x10000000 0x10000>;
+				reg-names = "dbi", "config";
+				#interrupt-cells = <1>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>,
+						<0 0 0 2 &intc 0 0 GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>,
+						<0 0 0 3 &intc 0 0 GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+						<0 0 0 4 &intc 0 0 GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges = <0x01000000 0x0 0x00000000 0x10010000 0x0 0x10000>,
+					 <0x02000000 0x0 0x10020000 0x10020000 0x0 0x7fe0000>,
+					 <0x42000000 0x0 0x18000000 0x18000000 0x0 0x8000000>;
+				dma-ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x80000000>;
+				clocks = <&rcc CK_BUS_PCIE>;
+				resets = <&rcc PCIE_R>;
+				msi-parent = <&v2m0>;
+				access-controllers = <&rifsc 68>;
+				power-domains = <&CLUSTER_PD>;
+				status = "disabled";
+
+				pcie at 0,0 {
+					device_type = "pci";
+					reg = <0x0 0x0 0x0 0x0 0x0>;
+					phys = <&combophy PHY_TYPE_PCIE>;
+					#address-cells = <3>;
+					#size-cells = <2>;
+					ranges;
+				};
+			};
 		};
 
 		bsec: efuse at 44000000 {
-- 
2.34.1



From krzk at kernel.org  Tue Mar 25 00:30:08 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 08:30:08 +0100
Subject: [PATCH 2/2] clocksource/drivers/nxp-timer: Add the System Timer
 Module for the s32g platform
In-Reply-To: <20250324100008.346009-2-daniel.lezcano@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
 <20250324100008.346009-2-daniel.lezcano@linaro.org>
Message-ID: <bb7e4740-9608-4534-9c19-3ac066e2aa8f@kernel.org>

On 24/03/2025 11:00, Daniel Lezcano wrote:
> +
> +static int __init nxp_stm_clocksource_init(struct device *dev, const char *name,
> +					   void __iomem *base, struct clk *clk)
> +{
> +	struct stm_timer *stm_timer;
> +	int ret;
> +
> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
> +	if (!stm_timer)
> +		return -ENOMEM;
> +
> +	stm_timer->base = base;
> +	stm_timer->rate = clk_get_rate(clk);
> +
> +	stm_timer->scs.cs.name = name;

You are aware that all node names will have exactly the same name? All
of them will be called "timer"?


> +	stm_timer->scs.cs.rating = 460;
> +	stm_timer->scs.cs.read = nxp_stm_clocksource_read;
> +	stm_timer->scs.cs.enable = nxp_stm_clocksource_enable;
> +	stm_timer->scs.cs.disable = nxp_stm_clocksource_disable;
> +	stm_timer->scs.cs.suspend = nxp_stm_clocksource_suspend;
> +	stm_timer->scs.cs.resume = nxp_stm_clocksource_resume;
> +	stm_timer->scs.cs.mask = CLOCKSOURCE_MASK(32);
> +	stm_timer->scs.cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
> +
> +	ret = clocksource_register_hz(&stm_timer->scs.cs, stm_timer->rate);
> +	if (ret)
> +		return ret;
> +
> +	stm_sched_clock = stm_timer;
> +
> +	sched_clock_register(nxp_stm_read_sched_clock, 32, stm_timer->rate);
> +
> +	dev_set_drvdata(dev, stm_timer);
> +
> +	dev_dbg(dev, "Registered clocksource %s\n", name);

Since all names will be the same, this makes little sense in debugging.
I guess you wanted one of the OF printk-formats for full node name.


> +
> +	return 0;
> +}
> +
> +static int nxp_stm_clockevent_read_counter(struct stm_timer *stm_timer)
> +{
> +	return readl(stm_timer->base + STM_CNT);
> +}
> +

...

> +
> +static int __init nxp_stm_timer_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct stm_instances *stm_instances;
> +	const char *name = of_node_full_name(np);
> +	void __iomem *base;
> +	int irq, ret;
> +	struct clk *clk;
> +
> +	stm_instances = (typeof(stm_instances))of_device_get_match_data(dev);

No, you *cannot* drop the const. It's there on purpose. Match data
should be const because it defines per variant differences. That's why
the prototype of of_device_get_match_data() has such return type.
You just want some global singleton, not match data.

> +	if (!stm_instances) {
> +		dev_err(dev, "No STM instances associated with a cpu");
> +		return -EINVAL;
> +	}
> +
> +	base = devm_of_iomap(dev, np, 0, NULL);
> +	if (IS_ERR(base)) {
> +		dev_err(dev, "Failed to iomap %pOFn\n", np);

You need to clean up the downstream code to match upstream. All of these
should be return dev_err_probe().

> +		return PTR_ERR(base);
> +	}
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (irq <= 0) {
> +		dev_err(dev, "Failed to parse and map IRQ: %d\n", irq);
> +		return -EINVAL;
> +	}
> +
> +	clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(clk)) {
> +		dev_err(dev, "Clock not found\n");

And this is clearly incorrect - spamming logs. Syntax is:
return dev_err_probe

> +		return PTR_ERR(clk);
> +	}
> +
> +	ret = clk_prepare_enable(clk);

Drop, devm_clk_get_enabled.

> +	if (ret) {
> +		dev_err(dev, "Failed to enable STM timer clock: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (!stm_instances->clocksource && (stm_instances->features & STM_CLKSRC)) {
> +
> +		/*
> +		 * First probed STM will be a clocksource
> +		 */
> +		ret = nxp_stm_clocksource_init(dev, name, base, clk);
> +		if (ret)
> +			return ret;
> +		stm_instances->clocksource++;

That's racy. Devices can be brought async, ideally. This should be
rather idr or probably entire structure protected with a mutex.

> +
> +	} else if (!stm_instances->clockevent_broadcast &&
> +		   (stm_instances->features & STM_CLKEVT_BROADCAST)) {
> +
> +		/*
> +		 * Second probed STM will be a broadcast clockevent
> +		 */
> +		ret = nxp_stm_clockevent_broadcast_init(dev, name, base, irq, clk);
> +		if (ret)
> +			return ret;
> +		stm_instances->clockevent_broadcast++;
> +
> +	} else if (stm_instances->clockevent_per_cpu < num_possible_cpus() &&
> +		   (stm_instances->features & STM_CLKEVT_PER_CPU)) {
> +
> +		/*
> +		 * Next probed STM will be a per CPU clockevent, until
> +		 * we probe as much as we have CPUs available on the
> +		 * system, we do a partial initialization
> +		 */
> +		ret = nxp_stm_clockevent_per_cpu_init(dev, name, base, irq, clk,
> +						      stm_instances->clockevent_per_cpu);
> +		if (ret)
> +			return ret;
> +
> +		stm_instances->clockevent_per_cpu++;
> +
> +		/*
> +		 * The number of probed STM for per CPU clockevent is
> +		 * equal to the number of available CPUs on the
> +		 * system. We install the cpu hotplug to finish the
> +		 * initialization by registering the clockevents
> +		 */
> +		if (stm_instances->clockevent_per_cpu == num_possible_cpus()) {
> +			ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "STM timer:starting",
> +						nxp_stm_clockevent_starting_cpu, NULL);
> +			if (ret < 0)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static struct stm_instances s32g_stm_instances = { .features = STM_CLKSRC | STM_CLKEVT_PER_CPU };

Missing const. Or misplaced - all file-scope static variables are
declared at the top.

> +
> +static const struct of_device_id nxp_stm_of_match[] = {
> +	{ .compatible = "nxp,s32g2-stm", &s32g_stm_instances },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
> +
> +static struct platform_driver nxp_stm_probe = {
> +	.probe	= nxp_stm_timer_probe,
> +	.driver	= {
> +		.name = "nxp-stm",
> +		.of_match_table = of_match_ptr(nxp_stm_of_match),

Drop of_match_ptr, you have here warnings.

> +	},
> +};
> +module_platform_driver(nxp_stm_probe);
> +
> +MODULE_DESCRIPTION("NXP System Timer Module driver");
> +MODULE_LICENSE("GPL");


Best regards,
Krzysztof


From francesco at dolcini.it  Tue Mar 25 00:39:16 2025
From: francesco at dolcini.it (Francesco Dolcini)
Date: Tue, 25 Mar 2025 08:39:16 +0100
Subject: [PATCH 1/2] dt-bindings: arm: imx: document i.MX 95 Verdin
 Evaluation Kit (EVK)
In-Reply-To: <20250324234013.140440-1-marex@denx.de>
References: <20250324234013.140440-1-marex@denx.de>
Message-ID: <20250325073916.GA4684@francesco-nb>

On Tue, Mar 25, 2025 at 12:40:01AM +0100, Marek Vasut wrote:
> Document support for i.MX 95 Verdin Evaluation Kit (EVK), which
> used to be the Titan EVK.
> 
> Note that the SoM used in this EVK is a derivative SoM from Verdin
> line of SoMs, an actual i.MX95 Verdin SoM is under development.
> 
> [1] https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95-evaluation-kit
> 
> Signed-off-by: Marek Vasut <marex at denx.de>

Reviewed-by: Francesco Dolcini <francesco.dolcini at toradex.com>

Francesco



From sumit.garg at kernel.org  Tue Mar 25 00:41:50 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 13:11:50 +0530
Subject: [PATCH v6 09/10] optee: FF-A: dynamic restricted memory
 allocation
In-Reply-To: <20250305130634.1850178-10-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-10-jens.wiklander@linaro.org>
Message-ID: <Z-JePo6yGlUgrZkw@sumit-X1>

On Wed, Mar 05, 2025 at 02:04:15PM +0100, Jens Wiklander wrote:
> Add support in the OP-TEE backend driver dynamic restricted memory
> allocation with FF-A.
> 
> The restricted memory pools for dynamically allocated restrict memory
> are instantiated when requested by user-space. This instantiation can
> fail if OP-TEE doesn't support the requested use-case of restricted
> memory.
> 
> Restricted memory pools based on a static carveout or dynamic allocation
> can coexist for different use-cases. We use only dynamic allocation with
> FF-A.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/Makefile        |   1 +
>  drivers/tee/optee/ffa_abi.c       | 143 ++++++++++++-
>  drivers/tee/optee/optee_private.h |  13 +-
>  drivers/tee/optee/rstmem.c        | 329 ++++++++++++++++++++++++++++++
>  4 files changed, 483 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/tee/optee/rstmem.c
> 
> diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
> index a6eff388d300..498969fb8e40 100644
> --- a/drivers/tee/optee/Makefile
> +++ b/drivers/tee/optee/Makefile
> @@ -4,6 +4,7 @@ optee-objs += core.o
>  optee-objs += call.o
>  optee-objs += notif.o
>  optee-objs += rpc.o
> +optee-objs += rstmem.o
>  optee-objs += supp.o
>  optee-objs += device.o
>  optee-objs += smc_abi.o
> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index e4b08cd195f3..6a55114232ef 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -672,6 +672,123 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
>  	return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread);
>  }
>  
> +static int do_call_lend_rstmem(struct optee *optee, u64 cookie, u32 use_case)
> +{
> +	struct optee_shm_arg_entry *entry;
> +	struct optee_msg_arg *msg_arg;
> +	struct tee_shm *shm;
> +	u_int offs;
> +	int rc;
> +
> +	msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
> +	if (IS_ERR(msg_arg))
> +		return PTR_ERR(msg_arg);
> +
> +	msg_arg->cmd = OPTEE_MSG_CMD_ASSIGN_RSTMEM;
> +	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> +	msg_arg->params[0].u.value.a = cookie;
> +	msg_arg->params[0].u.value.b = use_case;
> +
> +	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
> +	if (rc)
> +		goto out;
> +	if (msg_arg->ret != TEEC_SUCCESS) {
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +
> +out:
> +	optee_free_msg_arg(optee->ctx, entry, offs);
> +	return rc;
> +}
> +
> +static int optee_ffa_lend_rstmem(struct optee *optee, struct tee_shm *rstmem,
> +				 u16 *end_points, unsigned int ep_count,
> +				 u32 use_case)
> +{
> +	struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
> +	const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
> +	const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
> +	struct ffa_send_direct_data data;
> +	struct ffa_mem_region_attributes *mem_attr;
> +	struct ffa_mem_ops_args args = {
> +		.use_txbuf = true,
> +		.tag = use_case,
> +	};
> +	struct page *page;
> +	struct scatterlist sgl;
> +	unsigned int n;
> +	int rc;
> +
> +	mem_attr = kcalloc(ep_count, sizeof(*mem_attr), GFP_KERNEL);
> +	for (n = 0; n < ep_count; n++) {
> +		mem_attr[n].receiver = end_points[n];
> +		mem_attr[n].attrs = FFA_MEM_RW;
> +	}
> +	args.attrs = mem_attr;
> +	args.nattrs = ep_count;
> +
> +	page = phys_to_page(rstmem->paddr);
> +	sg_init_table(&sgl, 1);
> +	sg_set_page(&sgl, page, rstmem->size, 0);
> +
> +	args.sg = &sgl;
> +	rc = mem_ops->memory_lend(&args);
> +	kfree(mem_attr);
> +	if (rc)
> +		return rc;
> +
> +	rc = do_call_lend_rstmem(optee, args.g_handle, use_case);
> +	if (rc)
> +		goto err_reclaim;
> +
> +	rc = optee_shm_add_ffa_handle(optee, rstmem, args.g_handle);
> +	if (rc)
> +		goto err_unreg;
> +
> +	rstmem->sec_world_id = args.g_handle;
> +
> +	return 0;
> +
> +err_unreg:
> +	data = (struct ffa_send_direct_data){
> +		.data0 = OPTEE_FFA_RELEASE_RSTMEM,
> +		.data1 = (u32)args.g_handle,
> +		.data2 = (u32)(args.g_handle >> 32),
> +	};
> +	msg_ops->sync_send_receive(ffa_dev, &data);
> +err_reclaim:
> +	mem_ops->memory_reclaim(args.g_handle, 0);
> +	return rc;
> +}
> +
> +static int optee_ffa_reclaim_rstmem(struct optee *optee, struct tee_shm *rstmem)
> +{
> +	struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
> +	const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
> +	const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
> +	u64 global_handle = rstmem->sec_world_id;
> +	struct ffa_send_direct_data data = {
> +		.data0 = OPTEE_FFA_RELEASE_RSTMEM,
> +		.data1 = (u32)global_handle,
> +		.data2 = (u32)(global_handle >> 32)
> +	};
> +	int rc;
> +
> +	optee_shm_rem_ffa_handle(optee, global_handle);
> +	rstmem->sec_world_id = 0;
> +
> +	rc = msg_ops->sync_send_receive(ffa_dev, &data);
> +	if (rc)
> +		pr_err("Release SHM id 0x%llx rc %d\n", global_handle, rc);
> +
> +	rc = mem_ops->memory_reclaim(global_handle, 0);
> +	if (rc)
> +		pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
> +
> +	return rc;
> +}
> +
>  /*
>   * 6. Driver initialization
>   *
> @@ -833,6 +950,8 @@ static const struct optee_ops optee_ffa_ops = {
>  	.do_call_with_arg = optee_ffa_do_call_with_arg,
>  	.to_msg_param = optee_ffa_to_msg_param,
>  	.from_msg_param = optee_ffa_from_msg_param,
> +	.lend_rstmem = optee_ffa_lend_rstmem,
> +	.reclaim_rstmem = optee_ffa_reclaim_rstmem,
>  };
>  
>  static void optee_ffa_remove(struct ffa_device *ffa_dev)
> @@ -941,7 +1060,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
>  				  optee->pool, optee);
>  	if (IS_ERR(teedev)) {
>  		rc = PTR_ERR(teedev);
> -		goto err_free_pool;
> +		goto err_free_shm_pool;
>  	}
>  	optee->teedev = teedev;
>  
> @@ -988,6 +1107,24 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
>  			       rc);
>  	}
>  
> +	if (IS_ENABLED(CONFIG_CMA) && !IS_MODULE(CONFIG_OPTEE) &&

The CMA dependency should be managed via Kconfig.

> +	    (sec_caps & OPTEE_FFA_SEC_CAP_RSTMEM)) {
> +		enum tee_dma_heap_id id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
> +		struct tee_rstmem_pool *pool;
> +
> +		pool = optee_rstmem_alloc_cma_pool(optee, id);
> +		if (IS_ERR(pool)) {
> +			rc = PTR_ERR(pool);
> +			goto err_notif_uninit;
> +		}
> +
> +		rc = tee_device_register_dma_heap(optee->teedev, id, pool);
> +		if (rc) {
> +			pool->ops->destroy_pool(pool);
> +			goto err_notif_uninit;
> +		}
> +	}
> +
>  	rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
>  	if (rc)
>  		goto err_unregister_devices;
> @@ -1001,6 +1138,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
>  
>  err_unregister_devices:
>  	optee_unregister_devices();
> +	tee_device_unregister_all_dma_heaps(optee->teedev);
> +err_notif_uninit:
>  	if (optee->ffa.bottom_half_value != U32_MAX)
>  		notif_ops->notify_relinquish(ffa_dev,
>  					     optee->ffa.bottom_half_value);
> @@ -1018,7 +1157,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
>  	tee_device_unregister(optee->supp_teedev);
>  err_unreg_teedev:
>  	tee_device_unregister(optee->teedev);
> -err_free_pool:
> +err_free_shm_pool:
>  	tee_shm_pool_free(pool);
>  err_free_optee:
>  	kfree(optee);
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index 20eda508dbac..faab31ad7c52 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -174,9 +174,14 @@ struct optee;
>   * @do_call_with_arg:	enters OP-TEE in secure world
>   * @to_msg_param:	converts from struct tee_param to OPTEE_MSG parameters
>   * @from_msg_param:	converts from OPTEE_MSG parameters to struct tee_param
> + * @lend_rstmem:	lends physically contiguous memory as restricted
> + *			memory, inaccessible by the kernel
> + * @reclaim_rstmem:	reclaims restricted memory previously lent with
> + *			@lend_rstmem() and makes it accessible by the
> + *			kernel again
>   *
>   * These OPs are only supposed to be used internally in the OP-TEE driver
> - * as a way of abstracting the different methogs of entering OP-TEE in
> + * as a way of abstracting the different methods of entering OP-TEE in
>   * secure world.
>   */
>  struct optee_ops {
> @@ -191,6 +196,10 @@ struct optee_ops {
>  			      size_t num_params,
>  			      const struct optee_msg_param *msg_params,
>  			      bool update_out);
> +	int (*lend_rstmem)(struct optee *optee, struct tee_shm *rstmem,
> +			   u16 *end_points, unsigned int ep_count,
> +			   u32 use_case);
> +	int (*reclaim_rstmem)(struct optee *optee, struct tee_shm *rstmem);
>  };
>  
>  /**
> @@ -285,6 +294,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
>  void optee_supp_init(struct optee_supp *supp);
>  void optee_supp_uninit(struct optee_supp *supp);
>  void optee_supp_release(struct optee_supp *supp);
> +struct tee_rstmem_pool *optee_rstmem_alloc_cma_pool(struct optee *optee,
> +						    enum tee_dma_heap_id id);
>  
>  int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
>  		    struct tee_param *param);
> diff --git a/drivers/tee/optee/rstmem.c b/drivers/tee/optee/rstmem.c
> new file mode 100644
> index 000000000000..ea27769934d4
> --- /dev/null
> +++ b/drivers/tee/optee/rstmem.c
> @@ -0,0 +1,329 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025, Linaro Limited
> + */
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/errno.h>
> +#include <linux/genalloc.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/tee_core.h>
> +#include <linux/types.h>
> +#include "optee_private.h"
> +
> +struct optee_rstmem_cma_pool {
> +	struct tee_rstmem_pool pool;
> +	struct gen_pool *gen_pool;
> +	struct optee *optee;
> +	size_t page_count;
> +	u16 *end_points;
> +	u_int end_point_count;
> +	u_int align;
> +	refcount_t refcount;
> +	u32 use_case;
> +	struct tee_shm *rstmem;
> +	/* Protects when initializing and tearing down this struct */
> +	struct mutex mutex;
> +};
> +
> +static struct optee_rstmem_cma_pool *
> +to_rstmem_cma_pool(struct tee_rstmem_pool *pool)
> +{
> +	return container_of(pool, struct optee_rstmem_cma_pool, pool);
> +}
> +
> +static int init_cma_rstmem(struct optee_rstmem_cma_pool *rp)
> +{
> +	int rc;
> +
> +	rp->rstmem = tee_shm_alloc_cma_phys_mem(rp->optee->ctx, rp->page_count,
> +						rp->align);
> +	if (IS_ERR(rp->rstmem)) {
> +		rc = PTR_ERR(rp->rstmem);
> +		goto err_null_rstmem;
> +	}
> +
> +	/*
> +	 * TODO unmap the memory range since the physical memory will
> +	 * become inaccesible after the lend_rstmem() call.
> +	 */

What's your plan for this TODO? I think we need a CMA allocator here
which can allocate un-mapped memory such that any cache speculation
won't lead to CPU hangs once the memory restriction comes into picture.

> +	rc = rp->optee->ops->lend_rstmem(rp->optee, rp->rstmem, rp->end_points,
> +					 rp->end_point_count, rp->use_case);
> +	if (rc)
> +		goto err_put_shm;
> +	rp->rstmem->flags |= TEE_SHM_DYNAMIC;
> +
> +	rp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
> +	if (!rp->gen_pool) {
> +		rc = -ENOMEM;
> +		goto err_reclaim;
> +	}
> +
> +	rc = gen_pool_add(rp->gen_pool, rp->rstmem->paddr,
> +			  rp->rstmem->size, -1);
> +	if (rc)
> +		goto err_free_pool;
> +
> +	refcount_set(&rp->refcount, 1);
> +	return 0;
> +
> +err_free_pool:
> +	gen_pool_destroy(rp->gen_pool);
> +	rp->gen_pool = NULL;
> +err_reclaim:
> +	rp->optee->ops->reclaim_rstmem(rp->optee, rp->rstmem);
> +err_put_shm:
> +	tee_shm_put(rp->rstmem);
> +err_null_rstmem:
> +	rp->rstmem = NULL;
> +	return rc;
> +}
> +
> +static int get_cma_rstmem(struct optee_rstmem_cma_pool *rp)
> +{
> +	int rc = 0;
> +
> +	if (!refcount_inc_not_zero(&rp->refcount)) {
> +		mutex_lock(&rp->mutex);
> +		if (rp->gen_pool) {
> +			/*
> +			 * Another thread has already initialized the pool
> +			 * before us, or the pool was just about to be torn
> +			 * down. Either way we only need to increase the
> +			 * refcount and we're done.
> +			 */
> +			refcount_inc(&rp->refcount);
> +		} else {
> +			rc = init_cma_rstmem(rp);
> +		}
> +		mutex_unlock(&rp->mutex);
> +	}
> +
> +	return rc;
> +}
> +
> +static void release_cma_rstmem(struct optee_rstmem_cma_pool *rp)
> +{
> +	gen_pool_destroy(rp->gen_pool);
> +	rp->gen_pool = NULL;
> +
> +	rp->optee->ops->reclaim_rstmem(rp->optee, rp->rstmem);
> +	rp->rstmem->flags &= ~TEE_SHM_DYNAMIC;
> +
> +	WARN(refcount_read(&rp->rstmem->refcount) != 1, "Unexpected refcount");
> +	tee_shm_put(rp->rstmem);
> +	rp->rstmem = NULL;
> +}
> +
> +static void put_cma_rstmem(struct optee_rstmem_cma_pool *rp)
> +{
> +	if (refcount_dec_and_test(&rp->refcount)) {
> +		mutex_lock(&rp->mutex);
> +		if (rp->gen_pool)
> +			release_cma_rstmem(rp);
> +		mutex_unlock(&rp->mutex);
> +	}
> +}
> +
> +static int rstmem_pool_op_cma_alloc(struct tee_rstmem_pool *pool,
> +				    struct sg_table *sgt, size_t size,
> +				    size_t *offs)
> +{
> +	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
> +	size_t sz = ALIGN(size, PAGE_SIZE);
> +	phys_addr_t pa;
> +	int rc;
> +
> +	rc = get_cma_rstmem(rp);
> +	if (rc)
> +		return rc;
> +
> +	pa = gen_pool_alloc(rp->gen_pool, sz);
> +	if (!pa) {
> +		rc = -ENOMEM;
> +		goto err_put;
> +	}
> +
> +	rc = sg_alloc_table(sgt, 1, GFP_KERNEL);
> +	if (rc)
> +		goto err_free;
> +
> +	sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
> +	*offs = pa - rp->rstmem->paddr;
> +
> +	return 0;
> +err_free:
> +	gen_pool_free(rp->gen_pool, pa, size);
> +err_put:
> +	put_cma_rstmem(rp);
> +
> +	return rc;
> +}
> +
> +static void rstmem_pool_op_cma_free(struct tee_rstmem_pool *pool,
> +				    struct sg_table *sgt)
> +{
> +	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sgtable_sg(sgt, sg, i)
> +		gen_pool_free(rp->gen_pool, sg_phys(sg), sg->length);
> +	sg_free_table(sgt);
> +	put_cma_rstmem(rp);
> +}
> +
> +static int rstmem_pool_op_cma_update_shm(struct tee_rstmem_pool *pool,
> +					 struct sg_table *sgt, size_t offs,
> +					 struct tee_shm *shm,
> +					 struct tee_shm **parent_shm)
> +{
> +	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
> +
> +	*parent_shm = rp->rstmem;
> +
> +	return 0;
> +}
> +
> +static void pool_op_cma_destroy_pool(struct tee_rstmem_pool *pool)
> +{
> +	struct optee_rstmem_cma_pool *rp = to_rstmem_cma_pool(pool);
> +
> +	mutex_destroy(&rp->mutex);
> +	kfree(rp);
> +}
> +
> +static struct tee_rstmem_pool_ops rstmem_pool_ops_cma = {
> +	.alloc = rstmem_pool_op_cma_alloc,
> +	.free = rstmem_pool_op_cma_free,
> +	.update_shm = rstmem_pool_op_cma_update_shm,
> +	.destroy_pool = pool_op_cma_destroy_pool,
> +};
> +
> +static int get_rstmem_config(struct optee *optee, u32 use_case,
> +			     size_t *min_size, u_int *min_align,
> +			     u16 *end_points, u_int *ep_count)

I guess this end points terminology is specific to FF-A ABI. Is there
any relevance for this in the common APIs?

-Sumit

> +{
> +	struct tee_param params[2] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT,
> +			.u.value.a = use_case,
> +		},
> +		[1] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT,
> +		},
> +	};
> +	struct optee_shm_arg_entry *entry;
> +	struct tee_shm *shm_param = NULL;
> +	struct optee_msg_arg *msg_arg;
> +	struct tee_shm *shm;
> +	u_int offs;
> +	int rc;
> +
> +	if (end_points && *ep_count) {
> +		params[1].u.memref.size = *ep_count * sizeof(*end_points);
> +		shm_param = tee_shm_alloc_priv_buf(optee->ctx,
> +						   params[1].u.memref.size);
> +		if (IS_ERR(shm_param))
> +			return PTR_ERR(shm_param);
> +		params[1].u.memref.shm = shm_param;
> +	}
> +
> +	msg_arg = optee_get_msg_arg(optee->ctx, ARRAY_SIZE(params), &entry,
> +				    &shm, &offs);
> +	if (IS_ERR(msg_arg)) {
> +		rc = PTR_ERR(msg_arg);
> +		goto out_free_shm;
> +	}
> +	msg_arg->cmd = OPTEE_MSG_CMD_GET_RSTMEM_CONFIG;
> +
> +	rc = optee->ops->to_msg_param(optee, msg_arg->params,
> +				      ARRAY_SIZE(params), params,
> +				      false /*!update_out*/);
> +	if (rc)
> +		goto out_free_msg;
> +
> +	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
> +	if (rc)
> +		goto out_free_msg;
> +	if (msg_arg->ret && msg_arg->ret != TEEC_ERROR_SHORT_BUFFER) {
> +		rc = -EINVAL;
> +		goto out_free_msg;
> +	}
> +
> +	rc = optee->ops->from_msg_param(optee, params, ARRAY_SIZE(params),
> +					msg_arg->params, true /*update_out*/);
> +	if (rc)
> +		goto out_free_msg;
> +
> +	if (!msg_arg->ret && end_points &&
> +	    *ep_count < params[1].u.memref.size / sizeof(u16)) {
> +		rc = -EINVAL;
> +		goto out_free_msg;
> +	}
> +
> +	*min_size = params[0].u.value.a;
> +	*min_align = params[0].u.value.b;
> +	*ep_count = params[1].u.memref.size / sizeof(u16);
> +
> +	if (msg_arg->ret == TEEC_ERROR_SHORT_BUFFER) {
> +		rc = -ENOSPC;
> +		goto out_free_msg;
> +	}
> +
> +	if (end_points)
> +		memcpy(end_points, tee_shm_get_va(shm_param, 0),
> +		       params[1].u.memref.size);
> +
> +out_free_msg:
> +	optee_free_msg_arg(optee->ctx, entry, offs);
> +out_free_shm:
> +	if (shm_param)
> +		tee_shm_free(shm_param);
> +	return rc;
> +}
> +
> +struct tee_rstmem_pool *optee_rstmem_alloc_cma_pool(struct optee *optee,
> +						    enum tee_dma_heap_id id)
> +{
> +	struct optee_rstmem_cma_pool *rp;
> +	u32 use_case = id;
> +	size_t min_size;
> +	int rc;
> +
> +	rp = kzalloc(sizeof(*rp), GFP_KERNEL);
> +	if (!rp)
> +		return ERR_PTR(-ENOMEM);
> +	rp->use_case = use_case;
> +
> +	rc = get_rstmem_config(optee, use_case, &min_size, &rp->align, NULL,
> +			       &rp->end_point_count);
> +	if (rc) {
> +		if (rc != -ENOSPC)
> +			goto err;
> +		rp->end_points = kcalloc(rp->end_point_count,
> +					 sizeof(*rp->end_points), GFP_KERNEL);
> +		if (!rp->end_points) {
> +			rc = -ENOMEM;
> +			goto err;
> +		}
> +		rc = get_rstmem_config(optee, use_case, &min_size, &rp->align,
> +				       rp->end_points, &rp->end_point_count);
> +		if (rc)
> +			goto err_kfree_eps;
> +	}
> +
> +	rp->pool.ops = &rstmem_pool_ops_cma;
> +	rp->optee = optee;
> +	rp->page_count = min_size / PAGE_SIZE;
> +	mutex_init(&rp->mutex);
> +
> +	return &rp->pool;
> +
> +err_kfree_eps:
> +	kfree(rp->end_points);
> +err:
> +	kfree(rp);
> +	return ERR_PTR(rc);
> +}
> -- 
> 2.43.0
> 


From boris.brezillon at collabora.com  Tue Mar 25 00:43:49 2025
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 25 Mar 2025 08:43:49 +0100
Subject: [PATCH v2 4/9] drm/panthor: Implement optional reset
In-Reply-To: <c1de2afb-3559-4fbb-b13b-2373175b420b@denx.de>
References: <20250321200625.132494-1-marex@denx.de>
	<20250321200625.132494-5-marex@denx.de>
	<20250324094333.7afb17a1@collabora.com>
	<c1de2afb-3559-4fbb-b13b-2373175b420b@denx.de>
Message-ID: <20250325084349.344a0f11@collabora.com>

On Tue, 25 Mar 2025 00:37:59 +0100
Marek Vasut <marex at denx.de> wrote:

> On 3/24/25 9:43 AM, Boris Brezillon wrote:
> 
> [...]
> 
> >> @@ -563,6 +585,7 @@ int panthor_device_suspend(struct device *dev)
> >>   
> >>   	panthor_devfreq_suspend(ptdev);
> >>   
> >> +	reset_control_assert(ptdev->resets);  
> > 
> > Hm, that might be the cause of the fast reset issue (which is a fast
> > resume more than a fast reset BTW): if you re-assert the reset line on
> > runtime suspend, I guess this causes a full GPU reset, and the MCU ends
> > up in a state where it needs a slow reset (all data sections reset to
> > their initial state). Can you try to move the reset_control_[de]assert
> > to the unplug/init functions?  
> Is it correct to assume , that if I remove all reset_control_assert() 
> calls (and keep only the _deassert() calls), the slow resume problem 
> should go away too ?

Yeah, dropping the _assert()s should do the trick.



From sumit.garg at kernel.org  Tue Mar 25 00:45:35 2025
From: sumit.garg at kernel.org (Sumit Garg)
Date: Tue, 25 Mar 2025 13:15:35 +0530
Subject: [PATCH v6 10/10] optee: smc abi: dynamic restricted memory
 allocation
In-Reply-To: <20250305130634.1850178-11-jens.wiklander@linaro.org>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-11-jens.wiklander@linaro.org>
Message-ID: <Z-JfH7VAm0DTTbVg@sumit-X1>

On Wed, Mar 05, 2025 at 02:04:16PM +0100, Jens Wiklander wrote:
> Add support in the OP-TEE backend driver for dynamic restricted memory
> allocation using the SMC ABI.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> ---
>  drivers/tee/optee/smc_abi.c | 96 +++++++++++++++++++++++++++++++------
>  1 file changed, 81 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index a14ff0b7d3b3..aa574ee6e277 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -1001,6 +1001,69 @@ static int optee_smc_do_call_with_arg(struct tee_context *ctx,
>  	return rc;
>  }
>  
> +static int optee_smc_lend_rstmem(struct optee *optee, struct tee_shm *rstmem,
> +				 u16 *end_points, unsigned int ep_count,
> +				 u32 use_case)
> +{
> +	struct optee_shm_arg_entry *entry;
> +	struct optee_msg_arg *msg_arg;
> +	struct tee_shm *shm;
> +	u_int offs;
> +	int rc;
> +
> +	msg_arg = optee_get_msg_arg(optee->ctx, 2, &entry, &shm, &offs);
> +	if (IS_ERR(msg_arg))
> +		return PTR_ERR(msg_arg);
> +
> +	msg_arg->cmd = OPTEE_MSG_CMD_LEND_RSTMEM;
> +	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> +	msg_arg->params[0].u.value.a = use_case;
> +	msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
> +	msg_arg->params[1].u.tmem.buf_ptr = rstmem->paddr;
> +	msg_arg->params[1].u.tmem.size = rstmem->size;
> +	msg_arg->params[1].u.tmem.shm_ref = (u_long)rstmem;
> +
> +	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
> +	if (rc)
> +		goto out;
> +	if (msg_arg->ret != TEEC_SUCCESS) {
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +	rstmem->sec_world_id = (u_long)rstmem;
> +
> +out:
> +	optee_free_msg_arg(optee->ctx, entry, offs);
> +	return rc;
> +}
> +
> +static int optee_smc_reclaim_rstmem(struct optee *optee, struct tee_shm *rstmem)
> +{
> +	struct optee_shm_arg_entry *entry;
> +	struct optee_msg_arg *msg_arg;
> +	struct tee_shm *shm;
> +	u_int offs;
> +	int rc;
> +
> +	msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
> +	if (IS_ERR(msg_arg))
> +		return PTR_ERR(msg_arg);
> +
> +	msg_arg->cmd = OPTEE_MSG_CMD_RECLAIM_RSTMEM;
> +	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
> +	msg_arg->params[0].u.rmem.shm_ref = (u_long)rstmem;
> +
> +	rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
> +	if (rc)
> +		goto out;
> +	if (msg_arg->ret != TEEC_SUCCESS)
> +		rc = -EINVAL;
> +
> +out:
> +	optee_free_msg_arg(optee->ctx, entry, offs);
> +	return rc;
> +}
> +
>  /*
>   * 5. Asynchronous notification
>   */
> @@ -1252,6 +1315,8 @@ static const struct optee_ops optee_ops = {
>  	.do_call_with_arg = optee_smc_do_call_with_arg,
>  	.to_msg_param = optee_to_msg_param,
>  	.from_msg_param = optee_from_msg_param,
> +	.lend_rstmem = optee_smc_lend_rstmem,
> +	.reclaim_rstmem = optee_smc_reclaim_rstmem,
>  };
>  
>  static int enable_async_notif(optee_invoke_fn *invoke_fn)
> @@ -1622,11 +1687,13 @@ static inline int optee_load_fw(struct platform_device *pdev,
>  
>  static int optee_sdp_pool_init(struct optee *optee)
>  {
> +	bool sdp = optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP;
> +	bool dyn_sdp = optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_RSTMEM;
>  	enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
> -	struct tee_rstmem_pool *pool;
> -	int rc;
> +	struct tee_rstmem_pool *pool = ERR_PTR(-EINVAL);
> +	int rc = -EINVAL;
>  
> -	if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_SDP) {
> +	if (sdp) {
>  		union {
>  			struct arm_smccc_res smccc;
>  			struct optee_smc_get_sdp_config_result result;
> @@ -1634,25 +1701,24 @@ static int optee_sdp_pool_init(struct optee *optee)
>  
>  		optee->smc.invoke_fn(OPTEE_SMC_GET_SDP_CONFIG, 0, 0, 0, 0, 0, 0,
>  				     0, &res.smccc);
> -		if (res.result.status != OPTEE_SMC_RETURN_OK) {
> -			pr_err("Secure Data Path service not available\n");
> -			return 0;
> -		}
> +		if (res.result.status == OPTEE_SMC_RETURN_OK)
> +			pool = tee_rstmem_static_pool_alloc(res.result.start,
> +							    res.result.size);
> +	}
>  
> -		pool = tee_rstmem_static_pool_alloc(res.result.start,
> -						    res.result.size);
> -		if (IS_ERR(pool))
> -			return PTR_ERR(pool);
> +	if (dyn_sdp && IS_ERR(pool))
> +		pool = optee_rstmem_alloc_cma_pool(optee, heap_id);
>  
> +	if (!IS_ERR(pool)) {
>  		rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
>  		if (rc)
> -			goto err;
> +			pool->ops->destroy_pool(pool);
>  	}
>  
> +	if (rc && (sdp || dyn_sdp))
> +		pr_err("Secure Data Path service not available\n");

Rather than an error message we should just use pr_info().

-Sumit

> +
>  	return 0;
> -err:
> -	pool->ops->destroy_pool(pool);
> -	return rc;
>  }
>  
>  static int optee_probe(struct platform_device *pdev)
> -- 
> 2.43.0
> 


From brgl at bgdev.pl  Tue Mar 25 00:46:41 2025
From: brgl at bgdev.pl (Bartosz Golaszewski)
Date: Tue, 25 Mar 2025 08:46:41 +0100
Subject: [PATCH] ARM: davinci: always enable CONFIG_ARCH_DAVINCI_DA850
In-Reply-To: <20250324213340.4129384-1-arnd@kernel.org>
References: <20250324213340.4129384-1-arnd@kernel.org>
Message-ID: <CAMRc=Mc1zPjuU2KAWkq7s=tizDC+EX86DPNoRjUxutL=U_pY_w@mail.gmail.com>

On Mon, Mar 24, 2025 at 10:33?PM Arnd Bergmann <arnd at kernel.org> wrote:
>
> From: Arnd Bergmann <arnd at arndb.de>
>
> A change to the clk driver broke configurations that enable DA830
> but not DA850:
>
> arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o: in function `__da850_pll0_of_clk_init_declare':
> pll.c:(.init.text+0x30): undefined reference to `of_da850_pll0_init'
> arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_id_table+0x14): undefined reference to `da850_pll0_init'
> arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_id_table+0x2c): undefined reference to `da850_pll1_init'
> arm-linux-gnueabi-ld: drivers/clk/davinci/pll.o:(.rodata.davinci_pll_of_match+0xc0): undefined reference to `of_da850_pll1_init'
> arm-linux-gnueabi-ld: drivers/clk/davinci/psc.o:(.rodata.davinci_psc_id_table+0x14): undefined reference to `da850_psc0_init_data'
> arm-linux-gnueabi-ld: drivers/clk/davinci/psc.o:(.rodata.davinci_psc_id_table+0x2c): undefined reference to `da850_psc1_init_data'
>
> Select ARCH_DAVINCI_DA850 unconditionally to ensure the driver can still
> build.
>
> Fixes: a31b4dcf188c ("clk: davinci: remove support for da830")
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  arch/arm/mach-davinci/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
> index 3fa15f342240..8f66de0405d9 100644
> --- a/arch/arm/mach-davinci/Kconfig
> +++ b/arch/arm/mach-davinci/Kconfig
> @@ -4,6 +4,7 @@ menuconfig ARCH_DAVINCI
>         bool "TI DaVinci"
>         depends on ARCH_MULTI_V5
>         depends on CPU_LITTLE_ENDIAN
> +       select ARCH_DAVINCI_DA850
>         select CPU_ARM926T
>         select DAVINCI_TIMER
>         select ZONE_DMA
> --
> 2.39.5
>

Thanks and sorry for the trouble. FYI I want to remove all traces of
da830 during this cycle leaving da850 as the only platform upstream.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski at linaro.org>


From hanchunchao at inspur.com  Tue Mar 25 00:55:03 2025
From: hanchunchao at inspur.com (Charles Han)
Date: Tue, 25 Mar 2025 15:55:03 +0800
Subject: [PATCH] drm/imx: legacy-bridge: fix inconsistent indenting warning
Message-ID: <20250325075503.3852-1-hanchunchao@inspur.com>

Fix below inconsistent indenting smatch warning.
smatch warnings:
drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c:79 devm_imx_drm_legacy_bridge() warn: inconsistent indenting

Signed-off-by: Charles Han <hanchunchao at inspur.com>
---
 drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
index 3ebf0b9866de..55a763045812 100644
--- a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
+++ b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
@@ -76,9 +76,9 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev,
 	imx_bridge->base.ops = DRM_BRIDGE_OP_MODES;
 	imx_bridge->base.type = type;
 
-       ret = devm_drm_bridge_add(dev, &imx_bridge->base);
-       if (ret)
-               return ERR_PTR(ret);
+	ret = devm_drm_bridge_add(dev, &imx_bridge->base);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return &imx_bridge->base;
 }
-- 
2.43.0



From krzk at kernel.org  Tue Mar 25 00:57:25 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 08:57:25 +0100
Subject: [PATCH v2 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250324-acpm-atomic-v2-2-7d87746e1765@linaro.org>
References: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
 <20250324-acpm-atomic-v2-2-7d87746e1765@linaro.org>
Message-ID: <be580155-372f-445b-b9d1-2dc4fbf1c3a1@kernel.org>

On 24/03/2025 16:34, Andr? Draszik wrote:
> +static bool acpm_may_sleep(void)
> +{
> +	return system_state <= SYSTEM_RUNNING ||
> +		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
> +}
> +
>  /**
>   * acpm_dequeue_by_polling() - RX dequeue by polling.
>   * @achan:	ACPM channel info.
> @@ -300,7 +314,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
>  			return 0;
>  
>  		/* Determined experimentally. */
> -		usleep_range(20, 30);
> +		if (!acpm_may_sleep())
> +			udelay(10);
> +		else

... and what do you do if IRQs get disabled exactly in this moment? This
is just racy. You cannot check for a condition and assume it will be
valid for whatever time you want it to be valid.

What happens if system_state is changed to shutdown in this particular
moment? How did you prevent this from happening?

> +			usleep_range(20, 30);
>  	} while (ktime_before(ktime_get(), timeout));
>  
>  	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
> 


Best regards,
Krzysztof


From andre.draszik at linaro.org  Tue Mar 25 01:01:54 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Tue, 25 Mar 2025 08:01:54 +0000
Subject: [PATCH v2 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <be580155-372f-445b-b9d1-2dc4fbf1c3a1@kernel.org>
References: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
	 <20250324-acpm-atomic-v2-2-7d87746e1765@linaro.org>
	 <be580155-372f-445b-b9d1-2dc4fbf1c3a1@kernel.org>
Message-ID: <974ddabee5a2a43b9d32f382ec4b13afab066f1a.camel@linaro.org>

Hi Krzysztof,

On Tue, 2025-03-25 at 08:57 +0100, Krzysztof Kozlowski wrote:
> On 24/03/2025 16:34, Andr? Draszik wrote:
> > +static bool acpm_may_sleep(void)
> > +{
> > +	return system_state <= SYSTEM_RUNNING ||
> > +		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
> > +}
> > +
> > ?/**
> > ? * acpm_dequeue_by_polling() - RX dequeue by polling.
> > ? * @achan:	ACPM channel info.
> > @@ -300,7 +314,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
> > ?			return 0;
> > ?
> > ?		/* Determined experimentally. */
> > -		usleep_range(20, 30);
> > +		if (!acpm_may_sleep())
> > +			udelay(10);
> > +		else
> 
> ... and what do you do if IRQs get disabled exactly in this moment? This
> is just racy. You cannot check for a condition and assume it will be
> valid for whatever time you want it to be valid.
> 
> What happens if system_state is changed to shutdown in this particular
> moment? How did you prevent this from happening?

Yes, and that's also what the I2C subsystem is doing, AFAICS, see
i2c_in_atomic_xfer_mode() and its use. This is to make a very
specific corner case work, similar to I2C which has to deal with
the same issue during shutdown.

Would you have a better suggestion?


Cheers,
Andre'



From krzk at kernel.org  Tue Mar 25 01:07:33 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 09:07:33 +0100
Subject: [PATCH v2 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <974ddabee5a2a43b9d32f382ec4b13afab066f1a.camel@linaro.org>
References: <20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org>
 <20250324-acpm-atomic-v2-2-7d87746e1765@linaro.org>
 <be580155-372f-445b-b9d1-2dc4fbf1c3a1@kernel.org>
 <974ddabee5a2a43b9d32f382ec4b13afab066f1a.camel@linaro.org>
Message-ID: <60732c52-7774-48c6-8ec8-44ae82d86267@kernel.org>

On 25/03/2025 09:01, Andr? Draszik wrote:
> Hi Krzysztof,
> 
> On Tue, 2025-03-25 at 08:57 +0100, Krzysztof Kozlowski wrote:
>> On 24/03/2025 16:34, Andr? Draszik wrote:
>>> +static bool acpm_may_sleep(void)
>>> +{
>>> +	return system_state <= SYSTEM_RUNNING ||
>>> +		(IS_ENABLED(CONFIG_PREEMPT_COUNT) ? preemptible() : !irqs_disabled());
>>> +}
>>> +
>>> ?/**
>>> ? * acpm_dequeue_by_polling() - RX dequeue by polling.
>>> ? * @achan:	ACPM channel info.
>>> @@ -300,7 +314,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
>>> ?			return 0;
>>> ?
>>> ?		/* Determined experimentally. */
>>> -		usleep_range(20, 30);
>>> +		if (!acpm_may_sleep())
>>> +			udelay(10);
>>> +		else
>>
>> ... and what do you do if IRQs get disabled exactly in this moment? This
>> is just racy. You cannot check for a condition and assume it will be
>> valid for whatever time you want it to be valid.
>>
>> What happens if system_state is changed to shutdown in this particular
>> moment? How did you prevent this from happening?
> 
> Yes, and that's also what the I2C subsystem is doing, AFAICS, see
> i2c_in_atomic_xfer_mode() and its use. This is to make a very
> specific corner case work, similar to I2C which has to deal with
> the same issue during shutdown.

But they don't have a choice so they try to do the best to avoid
sleeping. And it is a subsystem, not a driver, which means their
patterns are sometimes special. Drivers should not replicate subsystem
workarounds.

> 
> Would you have a better suggestion?

Yes, you have a choice, you can always use udelay. Driver code is
supposed to be always correct.

Best regards,
Krzysztof


From hongxing.zhu at nxp.com  Tue Mar 25 01:08:04 2025
From: hongxing.zhu at nxp.com (Hongxing Zhu)
Date: Tue, 25 Mar 2025 08:08:04 +0000
Subject: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23
 ready
In-Reply-To: <Z+Gu/gmioiVJfDV0@lizhi-Precision-Tower-5810>
References: <20250324062647.1891896-1-hongxing.zhu@nxp.com>
 <20250324062647.1891896-4-hongxing.zhu@nxp.com>
 <Z+Gu/gmioiVJfDV0@lizhi-Precision-Tower-5810>
Message-ID: <AS8PR04MB86765138FE183551D570AAE58CA72@AS8PR04MB8676.eurprd04.prod.outlook.com>

> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: 2025?3?25? 3:14
> To: Hongxing Zhu <hongxing.zhu at nxp.com>
> Cc: l.stach at pengutronix.de; lpieralisi at kernel.org; kw at linux.com;
> manivannan.sadhasivam at linaro.org; robh at kernel.org;
> bhelgaas at google.com; shawnguo at kernel.org; s.hauer at pengutronix.de;
> kernel at pengutronix.de; festevam at gmail.com; linux-pci at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; imx at lists.linux.dev;
> linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit
> L23 ready
> 
> On Mon, Mar 24, 2025 at 02:26:45PM +0800, Richard Zhu wrote:
> > Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23
> 
> provide a errata link here.
Up to now, I only get the following document updates information.
" This is being converted to Docs update and will be added to init sequence
 in Reference Manual."
Would add the errata link after I find it.
Thanks.

Best Regards
Richard Zhu
> 
> ERR051624: ...
> 
> The words after ERR051624 is descript errata itself, not workaround.
> 
> > Ready Through Beacon or PERST# De-assertion
> >
> > When the auxiliary power is not available, the controller cannot exit
> > from L23 Ready with beacon or PERST# de-assertion when main power is
> > not removed.
> >
> > Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
> > ---
> >  drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index 0f42ab63f5ad..52aa8bd66cde 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -48,6 +48,8 @@
> >  #define IMX95_PCIE_SS_RW_REG_0			0xf0
> >  #define IMX95_PCIE_REF_CLKEN			BIT(23)
> >  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
> > +#define IMX95_PCIE_SS_RW_REG_1			0xf4
> > +#define IMX95_PCIE_SYS_AUX_PWR_DET		BIT(31)
> >
> >  #define IMX95_PE0_GEN_CTRL_1			0x1050
> >  #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0)
> > @@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const
> > struct imx_pcie *imx_pcie)
> >
> >  static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)  {
> > +	/*
> > +	 * Workaround for ERR051624: The Controller Without Vaux Cannot
> > +	 * Exit L23 Ready Through Beacon or PERST# De-assertion
> > +	 *
> > +	 * When the auxiliary power is not available, the controller
> > +	 * cannot exit from L23 Ready with beacon or PERST# de-assertion
> > +	 * when main power is not removed.
> > +	 *
> > +	 * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> > +	 */
> > +	regmap_update_bits(imx_pcie->iomuxc_gpr,
> IMX95_PCIE_SS_RW_REG_1,
> > +			IMX95_PCIE_SYS_AUX_PWR_DET,
> IMX95_PCIE_SYS_AUX_PWR_DET);
> 
> regmap_set_bits()
> 
> Frank
> > +
> >  	regmap_update_bits(imx_pcie->iomuxc_gpr,
> >  			IMX95_PCIE_SS_RW_REG_0,
> >  			IMX95_PCIE_PHY_CR_PARA_SEL,
> > --
> > 2.37.1
> >

From csokas.bence at prolan.hu  Tue Mar 25 01:26:28 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Tue, 25 Mar 2025 09:26:28 +0100
Subject: [PATCH v6] dma-engine: sun4i: Simplify error handling in probe()
In-Reply-To: <92772f63-52c9-4979-9b60-37c8320ca009@web.de>
References: <20250324172026.370253-2-csokas.bence@prolan.hu>
 <92772f63-52c9-4979-9b60-37c8320ca009@web.de>
Message-ID: <7064597b-caf7-42e2-b083-b3531e874200@prolan.hu>

Hi,

On 2025. 03. 24. 18:55, Markus Elfring wrote:
>> Clean up error handling by using devm functions and dev_err_probe().
> ?
> 
> Do any contributors care for a different patch granularity?
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14#n81

I still don't understand why you are so adamant on this. It is just a 
simple refactor patch changing 33 lines, mostly in one function, with no 
logic change. Does it break something in your system? Please explain 
yourself so we can understand your viewpoint better.

> Will it be clearer to mention also the function name ?sun4i_dma_probe?
> in the summary phrases?


I already added it as per your last response, did you not read the message?

On 2025. 03. 24. 18:20, Bence Cs?k?s wrote:
 > Clean up error handling by using devm functions and dev_err_probe(). This
 > should make it easier to add new code, as we can eliminate the "goto
 > ladder" in sun4i_dma_probe().

Bence



From dyoung at redhat.com  Tue Mar 25 01:36:22 2025
From: dyoung at redhat.com (Dave Young)
Date: Tue, 25 Mar 2025 16:36:22 +0800
Subject: [PATCH v5 11/16] kexec: add config option for KHO
In-Reply-To: <Z+JT7kx+sfPqfWFA@MiWiFi-R3L-srv>
References: <20250320015551.2157511-1-changyuanl@google.com>
 <20250320015551.2157511-12-changyuanl@google.com> <CALu+AoS01QJ-H5Vpr378rbx==iRQLG0HajtMCUzDXRO75biCag@mail.gmail.com>
 <Z+JT7kx+sfPqfWFA@MiWiFi-R3L-srv>
Message-ID: <CALu+AoQj+mHECTvbuK8CpUTmOYgx6n2oMFm5kQXtSigL+5Ks2w@mail.gmail.com>

> >
> > Have you tested kdump?  In my mind there are two issues,  one is with
> > CMA enabled, it could cause kdump crashkernel memory reservation
> > failures more often due to the fragmented low memory.  Secondly,  in
>
> kho scracth memorys are reserved much later than crashkernel, we may not
> need to worry about it.
> ====================
> start_kernel()
>   ......
>   -->setup_arch(&command_line);
>      -->arch_reserve_crashkernel();
>   ......
>   -->mm_core_init();
>      -->kho_memory_init();
>
> > kdump kernel dump the crazy scratch memory in vmcore is not very
> > meaningful.  Otherwise I suspect this is not tested under kdump.  If
> > so please disable this option for kdump.

Ok,  it is fine if this is the case, thanks Baoquan for clearing this worry.

But the other concerns are still need to address, eg. KHO use cases
are not good for kdump.
There could be more to think about.
eg. the issues talked in thread:
https://lore.kernel.org/lkml/Z7dc9Cd8KX3b_brB at dwarf.suse.cz/T/



From haibo.chen at nxp.com  Tue Mar 25 01:40:10 2025
From: haibo.chen at nxp.com (Bough Chen)
Date: Tue, 25 Mar 2025 08:40:10 +0000
Subject: [PATCH 2/2] mmc: sdhci-esdhc-imx: calclute data timeout value
 based on clock
In-Reply-To: <20250324092336.2231385-1-ziniu.wang_1@nxp.com>
References: <20250324092336.2231385-1-ziniu.wang_1@nxp.com>
Message-ID: <DU0PR04MB949673D7E71316D001C3872A90A72@DU0PR04MB9496.eurprd04.prod.outlook.com>

> -----Original Message-----
> From: Luke Wang <ziniu.wang_1 at nxp.com>
> Sent: 2025?3?24? 17:24
> To: adrian.hunter at intel.com; ulf.hansson at linaro.org; Bough Chen
> <haibo.chen at nxp.com>
> Cc: shawnguo at kernel.org; s.hauer at pengutronix.de; kernel at pengutronix.de;
> festevam at gmail.com; imx at lists.linux.dev; linux-mmc at vger.kernel.org; dl-S32
> <S32 at nxp.com>; linux-arm-kernel at lists.infradead.org;
> linux-kernel at vger.kernel.org
> Subject: [PATCH 2/2] mmc: sdhci-esdhc-imx: calclute data timeout value based
> on clock
> 
> From: Luke Wang <ziniu.wang_1 at nxp.com>
> 
> Calclute data timeout value based on clock instead of using max value.
> 
> Signed-off-by: Luke Wang <ziniu.wang_1 at nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
> b/drivers/mmc/host/sdhci-esdhc-imx.c
> index ff78a7c6a04c..e7316ecff64e 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -31,6 +31,7 @@
>  #include "cqhci.h"
> 
>  #define ESDHC_SYS_CTRL_DTOCV_MASK	GENMASK(19, 16)
> +#define ESDHC_SYS_CTRL_DTOCV_SHIFT	16
>  #define ESDHC_SYS_CTRL_IPP_RST_N	BIT(23)
>  #define	ESDHC_CTRL_D3CD			0x08
>  #define ESDHC_BURST_LEN_EN_INCR		(1 << 27)
> @@ -1387,12 +1388,16 @@ static unsigned int
> esdhc_get_max_timeout_count(struct sdhci_host *host)
> 
>  static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command
> *cmd)  {
> -	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> -	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +	bool too_big = false;
> +	u8 count = sdhci_calc_timeout(host, cmd, &too_big);
> 
> -	/* use maximum timeout counter */
> +	/*
> +	 * ESDHC_SYSTEM_CONTROL bit[23] used to control hardware reset
> +	 * pin of the card. Write 0 to bit[23] will reset the card.
> +	 * Only write DTOCV filed here.
> +	 */
No need to mention the bit[23] here, this is a bit confuse here.
Just drop the comment here.

Then for this patch:
Reviewed-by: Haibo Chen <haibo.chen at nxp.com>

Regards
Haibo Chen
>  	esdhc_clrset_le(host, ESDHC_SYS_CTRL_DTOCV_MASK,
> -			esdhc_is_usdhc(imx_data) ? 0xF0000 : 0xE0000,
> +			count << ESDHC_SYS_CTRL_DTOCV_SHIFT,
>  			ESDHC_SYSTEM_CONTROL);
>  }
> 
> @@ -1777,6 +1782,8 @@ static int sdhci_esdhc_imx_probe(struct
> platform_device *pdev)
>  		 * to distinguish the card type.
>  		 */
>  		host->mmc_host_ops.init_card = usdhc_init_card;
> +
> +		host->max_timeout_count = 0xF;
>  	}
> 
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> --
> 2.34.1


From daniel.baluta at gmail.com  Tue Mar 25 01:50:42 2025
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Tue, 25 Mar 2025 10:50:42 +0200
Subject: [PATCH 1/2] dt-bindings: arm: imx: document i.MX 95 Verdin
 Evaluation Kit (EVK)
In-Reply-To: <20250324234013.140440-1-marex@denx.de>
References: <20250324234013.140440-1-marex@denx.de>
Message-ID: <CAEnQRZB068dzjLmeoFdPtcX_Wc_Or0idd_J0OKi-UqgD=Lmcaw@mail.gmail.com>

On Tue, Mar 25, 2025 at 1:40?AM Marek Vasut <marex at denx.de> wrote:
>
> Document support for i.MX 95 Verdin Evaluation Kit (EVK), which
> used to be the Titan EVK.
>
> Note that the SoM used in this EVK is a derivative SoM from Verdin
> line of SoMs, an actual i.MX95 Verdin SoM is under development.
>
> [1] https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx95-evaluation-kit
>
> Signed-off-by: Marek Vasut <marex at denx.de>

Reviewed-by: Daniel Baluta <daniel.baluta at nxp.com>


From Markus.Elfring at web.de  Tue Mar 25 01:47:45 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Tue, 25 Mar 2025 09:47:45 +0100
Subject: [v6] dma-engine: sun4i: Simplify error handling in probe()
In-Reply-To: <7064597b-caf7-42e2-b083-b3531e874200@prolan.hu>
References: <20250324172026.370253-2-csokas.bence@prolan.hu>
 <92772f63-52c9-4979-9b60-37c8320ca009@web.de>
 <7064597b-caf7-42e2-b083-b3531e874200@prolan.hu>
Message-ID: <7332ccd2-ebe6-4b9d-a2ae-8f33641e7bd4@web.de>

>>> Clean up error handling by using devm functions and dev_err_probe().
>> ?
>>
>> Do any contributors care for a different patch granularity?
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14#n81
>
> I still don't understand why you are so adamant on this.

There are developers who tend to prefer an other change granularity.


> It is just a simple refactor patch changing 33 lines,

The transformation goal is fine.


> mostly in one function, with no logic change.

Implementation details are probably worth for another look.


> Does it break something in your system? Please explain yourself so we can understand your viewpoint better.

I hope that the understanding can grow also for another bit of refinement.


>> Will it be clearer to mention also the function name ?sun4i_dma_probe?
>> in the summary phrases?
>
> I already added it as per your last response, did you not read the message?
>
> On 2025. 03. 24. 18:20, Bence Cs?k?s wrote:
>> Clean up error handling by using devm functions and dev_err_probe(). This
>> should make it easier to add new code, as we can eliminate the "goto
>> ladder" in sun4i_dma_probe().
Please distinguish better between information from the ?changelog?
and items in a message subject.

Regards,
Markus


From jens.wiklander at linaro.org  Tue Mar 25 01:50:35 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Tue, 25 Mar 2025 09:50:35 +0100
Subject: [PATCH v6 03/10] optee: account for direction while converting parameters
In-Reply-To: <Z-JFagmbZBQd0hoM@sumit-X1>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-4-jens.wiklander@linaro.org> <Z9K2RQYuXSJc8Y1E@sumit-X1>
 <CAHUa44H5Zc_POJ_RWaVd4iFVagRkFaN+8Ajs=19FKboZapbQHw@mail.gmail.com>
 <Z9vfD4UWSrqSTPnP@sumit-X1> <CAHUa44HY-jZCoDXKnx-f4gBoABRVdh1+6PA1AYHSva9aL=rDAA@mail.gmail.com>
 <Z-JFagmbZBQd0hoM@sumit-X1>
Message-ID: <CAHUa44HXHwR1_LbjG6T5OqnafXiS4-kHeKjV9TurGORx3SsprQ@mail.gmail.com>

On Tue, Mar 25, 2025 at 6:56?AM Sumit Garg <sumit.garg at kernel.org> wrote:
>
> On Thu, Mar 20, 2025 at 02:00:57PM +0100, Jens Wiklander wrote:
> > Hi Sumit,
> >
> > On Thu, Mar 20, 2025 at 10:25?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> > >
> > > Hi Jens,
> > >
> > > On Mon, Mar 17, 2025 at 08:42:01AM +0100, Jens Wiklander wrote:
> > > > Hi Sumit,
> > > >
> > > > On Thu, Mar 13, 2025 at 11:41?AM Sumit Garg <sumit.garg at kernel.org> wrote:
> > > > >
> > > > > Hi Jens,
> > > > >
> > > > > On Wed, Mar 05, 2025 at 02:04:09PM +0100, Jens Wiklander wrote:
> > > > > > The OP-TEE backend driver has two internal function pointers to convert
> > > > > > between the subsystem type struct tee_param and the OP-TEE type struct
> > > > > > optee_msg_param.
> > > > > >
> > > > > > The conversion is done from one of the types to the other, which is then
> > > > > > involved in some operation and finally converted back to the original
> > > > > > type. When converting to prepare the parameters for the operation, all
> > > > > > fields must be taken into account, but then converting back, it's enough
> > > > > > to update only out-values and out-sizes. So, an update_out parameter is
> > > > > > added to the conversion functions to tell if all or only some fields
> > > > > > must be copied.
> > > > > >
> > > > > > This is needed in a later patch where it might get confusing when
> > > > > > converting back in from_msg_param() callback since an allocated
> > > > > > restricted SHM can be using the sec_world_id of the used restricted
> > > > > > memory pool and that doesn't translate back well.
> > > > > >
> > > > > > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > > > > > ---
> > > > > >  drivers/tee/optee/call.c          | 10 ++--
> > > > > >  drivers/tee/optee/ffa_abi.c       | 43 +++++++++++++----
> > > > > >  drivers/tee/optee/optee_private.h | 42 +++++++++++------
> > > > > >  drivers/tee/optee/rpc.c           | 31 +++++++++----
> > > > > >  drivers/tee/optee/smc_abi.c       | 76 +++++++++++++++++++++++--------
> > > > > >  5 files changed, 144 insertions(+), 58 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > > > > > index 16eb953e14bb..f1533b894726 100644
> > > > > > --- a/drivers/tee/optee/call.c
> > > > > > +++ b/drivers/tee/optee/call.c
> > > > > > @@ -400,7 +400,8 @@ int optee_open_session(struct tee_context *ctx,
> > > > > >       export_uuid(msg_arg->params[1].u.octets, &client_uuid);
> > > > > >
> > > > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
> > > > > > -                                   arg->num_params, param);
> > > > > > +                                   arg->num_params, param,
> > > > > > +                                   false /*!update_out*/);
> > > > > >       if (rc)
> > > > > >               goto out;
> > > > > >
> > > > > > @@ -427,7 +428,8 @@ int optee_open_session(struct tee_context *ctx,
> > > > > >       }
> > > > > >
> > > > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > > > -                                    msg_arg->params + 2)) {
> > > > > > +                                    msg_arg->params + 2,
> > > > > > +                                    true /*update_out*/)) {
> > > > > >               arg->ret = TEEC_ERROR_COMMUNICATION;
> > > > > >               arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > > > >               /* Close session again to avoid leakage */
> > > > > > @@ -541,7 +543,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > > > >       msg_arg->cancel_id = arg->cancel_id;
> > > > > >
> > > > > >       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
> > > > > > -                                   param);
> > > > > > +                                   param, false /*!update_out*/);
> > > > > >       if (rc)
> > > > > >               goto out;
> > > > > >
> > > > > > @@ -551,7 +553,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
> > > > > >       }
> > > > > >
> > > > > >       if (optee->ops->from_msg_param(optee, param, arg->num_params,
> > > > > > -                                    msg_arg->params)) {
> > > > > > +                                    msg_arg->params, true /*update_out*/)) {
> > > > > >               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
> > > > > >               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
> > > > > >       }
> > > > > > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > > > > > index 4ca1d5161b82..e4b08cd195f3 100644
> > > > > > --- a/drivers/tee/optee/ffa_abi.c
> > > > > > +++ b/drivers/tee/optee/ffa_abi.c
> > > > > > @@ -122,15 +122,21 @@ static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
> > > > > >   */
> > > > > >
> > > > > >  static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > > > -                                u32 attr, const struct optee_msg_param *mp)
> > > > > > +                                u32 attr, const struct optee_msg_param *mp,
> > > > > > +                                bool update_out)
> > > > > >  {
> > > > > >       struct tee_shm *shm = NULL;
> > > > > >       u64 offs_high = 0;
> > > > > >       u64 offs_low = 0;
> > > > > >
> > > > > > +     if (update_out) {
> > > > > > +             if (attr == OPTEE_MSG_ATTR_TYPE_FMEM_INPUT)
> > > > > > +                     return;
> > > > > > +             goto out;
> > > > > > +     }
> > > > > > +
> > > > > >       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
> > > > > >                 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
> > > > > > -     p->u.memref.size = mp->u.fmem.size;
> > > > > >
> > > > > >       if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
> > > > > >               shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
> > > > > > @@ -141,6 +147,8 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > > >               offs_high = mp->u.fmem.offs_high;
> > > > > >       }
> > > > > >       p->u.memref.shm_offs = offs_low | offs_high << 32;
> > > > > > +out:
> > > > > > +     p->u.memref.size = mp->u.fmem.size;
> > > > > >  }
> > > > > >
> > > > > >  /**
> > > > > > @@ -150,12 +158,14 @@ static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
> > > > > >   * @params:  subsystem internal parameter representation
> > > > > >   * @num_params:      number of elements in the parameter arrays
> > > > > >   * @msg_params:      OPTEE_MSG parameters
> > > > > > + * @update_out: update parameter for output only
> > > > > >   *
> > > > > >   * Returns 0 on success or <0 on failure
> > > > > >   */
> > > > > >  static int optee_ffa_from_msg_param(struct optee *optee,
> > > > > >                                   struct tee_param *params, size_t num_params,
> > > > > > -                                 const struct optee_msg_param *msg_params)
> > > > > > +                                 const struct optee_msg_param *msg_params,
> > > > > > +                                 bool update_out)
> > > > > >  {
> > > > > >       size_t n;
> > > > > >
> > > > > > @@ -166,18 +176,20 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > > > >
> > > > > >               switch (attr) {
> > > > > >               case OPTEE_MSG_ATTR_TYPE_NONE:
> > > > > > +                     if (update_out)
> > > > > > +                             break;
> > > > > >                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > > > >                       memset(&p->u, 0, sizeof(p->u));
> > > > > >                       break;
> > > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> > > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> > > > > >               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> > > > > > -                     optee_from_msg_param_value(p, attr, mp);
> > > > > > +                     optee_from_msg_param_value(p, attr, mp, update_out);
> > > > > >                       break;
> > > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
> > > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
> > > > > >               case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
> > > > > > -                     from_msg_param_ffa_mem(optee, p, attr, mp);
> > > > > > +                     from_msg_param_ffa_mem(optee, p, attr, mp, update_out);
> > > > > >                       break;
> > > > > >               default:
> > > > > >                       return -EINVAL;
> > > > > > @@ -188,10 +200,16 @@ static int optee_ffa_from_msg_param(struct optee *optee,
> > > > > >  }
> > > > > >
> > > > > >  static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > > > -                             const struct tee_param *p)
> > > > > > +                             const struct tee_param *p, bool update_out)
> > > > > >  {
> > > > > >       struct tee_shm *shm = p->u.memref.shm;
> > > > > >
> > > > > > +     if (update_out) {
> > > > > > +             if (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
> > > > > > +                     return 0;
> > > > > > +             goto out;
> > > > > > +     }
> > > > > > +
> > > > > >       mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
> > > > > >                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
> > > > > >
> > > > > > @@ -211,6 +229,7 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > > >               memset(&mp->u, 0, sizeof(mp->u));
> > > > > >               mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
> > > > > >       }
> > > > > > +out:
> > > > > >       mp->u.fmem.size = p->u.memref.size;
> > > > > >
> > > > > >       return 0;
> > > > > > @@ -222,13 +241,15 @@ static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
> > > > > >   * @optee:   main service struct
> > > > > >   * @msg_params:      OPTEE_MSG parameters
> > > > > >   * @num_params:      number of elements in the parameter arrays
> > > > > > - * @params:  subsystem itnernal parameter representation
> > > > > > + * @params:  subsystem internal parameter representation
> > > > > > + * @update_out: update parameter for output only
> > > > > >   * Returns 0 on success or <0 on failure
> > > > > >   */
> > > > > >  static int optee_ffa_to_msg_param(struct optee *optee,
> > > > > >                                 struct optee_msg_param *msg_params,
> > > > > >                                 size_t num_params,
> > > > > > -                               const struct tee_param *params)
> > > > > > +                               const struct tee_param *params,
> > > > > > +                               bool update_out)
> > > > > >  {
> > > > > >       size_t n;
> > > > > >
> > > > > > @@ -238,18 +259,20 @@ static int optee_ffa_to_msg_param(struct optee *optee,
> > > > > >
> > > > > >               switch (p->attr) {
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > > > > +                     if (update_out)
> > > > > > +                             break;
> > > > > >                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > > > >                       memset(&mp->u, 0, sizeof(mp->u));
> > > > > >                       break;
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > > > > -                     optee_to_msg_param_value(mp, p);
> > > > > > +                     optee_to_msg_param_value(mp, p, update_out);
> > > > > >                       break;
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > > > > >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > > > > -                     if (to_msg_param_ffa_mem(mp, p))
> > > > > > +                     if (to_msg_param_ffa_mem(mp, p, update_out))
> > > > > >                               return -EINVAL;
> > > > > >                       break;
> > > > > >               default:
> > > > >
> > > > > Can we rather handle it as follows to improve code readability and
> > > > > maintainence long term? Ditto for all other places.
> > > > >
> > > > > static int optee_ffa_to_msg_param(struct optee *optee,
> > > > >                                   struct optee_msg_param *msg_params,
> > > > >                                   size_t num_params,
> > > > >                                   const struct tee_param *params,
> > > > >                                   bool update_out)
> > > > > {
> > > > >         size_t n;
> > > > >
> > > > >         for (n = 0; n < num_params; n++) {
> > > > >                 const struct tee_param *p = params + n;
> > > > >                 struct optee_msg_param *mp = msg_params + n;
> > > > >
> > > > >                 if (update_out && (p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
> > > > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
> > > > >                      p->attr == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT))
> > > > >                     continue;
> > > >
> > > > You're missing updating the length field for memrefs.
> > > >
> > >
> > > Do we need to update length field for input memrefs when update_out is
> > > set? I don't see that happening in your existing patch too.
> >
> > I'm sorry, I was unclear. The update_out parameter means only the
> > output fields should be updated, not the attribute, offsets, ids, etc.
> > That is, the length field for memrefs, and the value fields a, b, c
> > for value params. Some of the memrefs aren't translated one-to-one
> > with SDP, but the length field can and must be updated.
>
> Isn't it rather better to add another attribute type to handled SDP
> special handling?

This isn't special handling, all parameters get the same treatment.
When updating a parameter after it has been used, this is all that
needs to be done, regardless of whether it's an SDP buffer. The
updates we did before this patch were redundant.

This patch was introduced in the v3 of this patch set, but I don't
think it's strictly needed any longer since SDP buffers are allocated
differently now. I think it's nice to only update what's needed when
translating back a parameter (just as in params_to_user() in
drivers/tee/tee_core.c), but if you don't like it, we can drop this
patch.

Cheers,
Jens

>
> -Sumit
>
> >
> > Cheers,
> > Jens
> >
> > >
> > > -Sumit
> > >
> > > > Cheers,
> > > > Jens
> > > >
> > > > >
> > > > >                 switch (p->attr) {
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
> > > > >                         mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
> > > > >                         memset(&mp->u, 0, sizeof(mp->u));
> > > > >                         break;
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
> > > > >                         optee_to_msg_param_value(mp, p);
> > > > >                         break;
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> > > > >                 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > > > >                         if (to_msg_param_ffa_mem(mp, p))
> > > > >                                 return -EINVAL;
> > > > >                         break;
> > > > >                 default:
> > > > >                         return -EINVAL;
> > > > >                 }
> > > > >         }
> > > > >
> > > > >         return 0;
> > > > > }
> > > > >
> > > > > -Sumit


From wens at csie.org  Tue Mar 25 01:56:15 2025
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 25 Mar 2025 16:56:15 +0800
Subject: [PATCH] ASoC: sun8i-codec: Remove unnecessary NULL check before clk_disable_unprepare()
In-Reply-To: <20250325032833.604073-1-nichen@iscas.ac.cn>
References: <20250325032833.604073-1-nichen@iscas.ac.cn>
Message-ID: <CAGb2v65e8Hk7aZ543pEXYKJ9VDs1znuCtaDDdCOfaRKWrT2MdA@mail.gmail.com>

On Tue, Mar 25, 2025 at 11:29?AM Chen Ni <nichen at iscas.ac.cn> wrote:
>
> clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL.
> Remove unneeded NULL check for clk here.

Please also clean up the clk_prepare_enable() call.

ChenYu

> Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
> ---
>  sound/soc/sunxi/sun8i-codec.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
> index 8b9eb1a202f7..a27976c375fe 100644
> --- a/sound/soc/sunxi/sun8i-codec.c
> +++ b/sound/soc/sunxi/sun8i-codec.c
> @@ -274,8 +274,7 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
>         regcache_cache_only(scodec->regmap, true);
>         regcache_mark_dirty(scodec->regmap);
>
> -       if (scodec->clk_bus)
> -               clk_disable_unprepare(scodec->clk_bus);
> +       clk_disable_unprepare(scodec->clk_bus);
>
>         return 0;
>  }
> --
> 2.25.1
>
>


From csokas.bence at prolan.hu  Tue Mar 25 01:58:57 2025
From: csokas.bence at prolan.hu (=?UTF-8?B?Q3PDs2vDoXMgQmVuY2U=?=)
Date: Tue, 25 Mar 2025 09:58:57 +0100
Subject: [v6] dma-engine: sun4i: Simplify error handling in probe()
In-Reply-To: <7332ccd2-ebe6-4b9d-a2ae-8f33641e7bd4@web.de>
References: <20250324172026.370253-2-csokas.bence@prolan.hu>
 <92772f63-52c9-4979-9b60-37c8320ca009@web.de>
 <7064597b-caf7-42e2-b083-b3531e874200@prolan.hu>
 <7332ccd2-ebe6-4b9d-a2ae-8f33641e7bd4@web.de>
Message-ID: <7afcbbee-6261-4b2f-be14-a3076746d53c@prolan.hu>

Hi,

On 2025. 03. 25. 9:47, Markus Elfring wrote:
> Implementation details are probably worth for another look.

What don't you like in the implementation? Let's discuss that then.

>> On 2025. 03. 24. 18:20, Bence Cs?k?s wrote:
>>> Clean up error handling by using devm functions and dev_err_probe(). This
>>> should make it easier to add new code, as we can eliminate the "goto
>>> ladder" in sun4i_dma_probe().
> Please distinguish better between information from the ?changelog?
> and items in a message subject.

What do you mean? The email body will be the commit message.

> Regards,
> Markus

Bence



From karol.bednaszewski at ventrixio.pl  Tue Mar 25 02:05:11 2025
From: karol.bednaszewski at ventrixio.pl (Karol Bednaszewski)
Date: Tue, 25 Mar 2025 09:05:11 GMT
Subject: =?UTF-8?Q?Mniejsze_wydatki_na_samoch=C3=B3d?=
Message-ID: <20250325074500-0.1.19.af9t.0.3oglsr4v1j@ventrixio.pl>

Dzie? dobry!

Czy m?g?bym przedstawi? rozwi?zanie, kt?re umo?liwia monitoring ka?dego auta w czasie rzeczywistym w tym jego pozycj?, zu?ycie paliwa i przebieg?

Dodatkowo nasze narz?dzie minimalizuje koszty utrzymania samochod?w, skraca czas przejazd?w, a tak?e umo?liwia tworzenie planu tras czy dostaw.

Z naszej wiedzy i do?wiadczenia korzysta ju? ponad 49 tys. Klient?w. Monitorujemy 809 000 pojazd?w na ca?ym ?wiecie, co jest nasz? najlepsz? wizyt?wk?.

Bardzo prosz? o e-maila zwrotnego, je?li mogliby?my wsp?lnie om?wi? potencja? wykorzystania takiego rozwi?zania w Pa?stwa firmie.


Pozdrawiam
Karol Bednaszewski


From Markus.Elfring at web.de  Tue Mar 25 02:12:33 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Tue, 25 Mar 2025 10:12:33 +0100
Subject: [v6] dma-engine: sun4i: Simplify error handling in probe()
In-Reply-To: <7afcbbee-6261-4b2f-be14-a3076746d53c@prolan.hu>
References: <20250324172026.370253-2-csokas.bence@prolan.hu>
 <92772f63-52c9-4979-9b60-37c8320ca009@web.de>
 <7064597b-caf7-42e2-b083-b3531e874200@prolan.hu>
 <7332ccd2-ebe6-4b9d-a2ae-8f33641e7bd4@web.de>
 <7afcbbee-6261-4b2f-be14-a3076746d53c@prolan.hu>
Message-ID: <26e36378-d393-4fe1-938a-be8c3db94ede@web.de>

>> Implementation details are probably worth for another look.
>
> What don't you like in the implementation? Let's discuss that then.

I dare to point concerns out also for the development process.


>> Please distinguish better between information from the ?changelog?
>> and items in a message subject.
>
> What do you mean? The email body will be the commit message.
See also:
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.14#n623

Regards,
Markus


From nichen at iscas.ac.cn  Tue Mar 25 02:26:40 2025
From: nichen at iscas.ac.cn (Chen Ni)
Date: Tue, 25 Mar 2025 17:26:40 +0800
Subject: [PATCH v2] ASoC: sun8i-codec: Remove unnecessary NULL check before clk_prepare_enable/clk_disable_unprepare
Message-ID: <20250325092640.996802-1-nichen@iscas.ac.cn>

clk_prepare_enable() and clk_disable_unprepare() already checked
NULL clock parameter.Remove unneeded NULL check for clk here.

Signed-off-by: Chen Ni <nichen at iscas.ac.cn>
---
Changelog:

v1 -> v2:

1. Add clean up for clk_prepare_enable() call.
---
 sound/soc/sunxi/sun8i-codec.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 8b9eb1a202f7..7b3496caa31e 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -248,12 +248,10 @@ static int sun8i_codec_runtime_resume(struct device *dev)
 	struct sun8i_codec *scodec = dev_get_drvdata(dev);
 	int ret;
 
-	if (scodec->clk_bus) {
-		ret = clk_prepare_enable(scodec->clk_bus);
-		if (ret) {
-			dev_err(dev, "Failed to enable the bus clock\n");
-			return ret;
-		}
+	ret = clk_prepare_enable(scodec->clk_bus);
+	if (ret) {
+		dev_err(dev, "Failed to enable the bus clock\n");
+		return ret;
 	}
 
 	regcache_cache_only(scodec->regmap, false);
@@ -274,8 +272,7 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
 	regcache_cache_only(scodec->regmap, true);
 	regcache_mark_dirty(scodec->regmap);
 
-	if (scodec->clk_bus)
-		clk_disable_unprepare(scodec->clk_bus);
+	clk_disable_unprepare(scodec->clk_bus);
 
 	return 0;
 }
-- 
2.25.1



From miko.lenczewski at arm.com  Tue Mar 25 02:36:25 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Tue, 25 Mar 2025 09:36:25 +0000
Subject: [PATCH v5 3/3] arm64/mm: Elide tlbi in contpte_convert() under BBML2
In-Reply-To: <20250325093625.55184-1-miko.lenczewski@arm.com>
References: <20250325093625.55184-1-miko.lenczewski@arm.com>
Message-ID: <20250325093625.55184-4-miko.lenczewski@arm.com>

When converting a region via contpte_convert() to use mTHP, we have two
different goals. We have to mark each entry as contiguous, and we would
like to smear the dirty and young (access) bits across all entries in
the contiguous block. Currently, we do this by first accumulating the
dirty and young bits in the block, using an atomic
__ptep_get_and_clear() and the relevant pte_{dirty,young}() calls,
performing a tlbi, and finally smearing the correct bits across the
block using __set_ptes().

This approach works fine for BBM level 0, but with support for BBM level
2 we are allowed to reorder the tlbi to after setting the pagetable
entries. We expect the time cost of a tlbi to be much greater than the
cost of clearing and resetting the PTEs. As such, this reordering of the
tlbi outside the window where our PTEs are invalid greatly reduces the
duration the PTE are visibly invalid for other threads. This reduces the
likelyhood of a concurrent page walk finding an invalid PTE, reducing
the likelyhood of a fault in other threads, and improving performance
(more so when there are more threads).

Because we support via allowlist only bbml2 implementations that never
raise conflict aborts and instead invalidate the tlb entries
automatically in hardware, we can avoid the final flush altogether.
Avoiding flushes is a win.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
---
 arch/arm64/mm/contpte.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
index 55107d27d3f8..77ed03b30b72 100644
--- a/arch/arm64/mm/contpte.c
+++ b/arch/arm64/mm/contpte.c
@@ -68,7 +68,8 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
 			pte = pte_mkyoung(pte);
 	}
 
-	__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
+	if (!system_supports_bbml2_noabort())
+		__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
 
 	__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
 }
-- 
2.48.1



From miko.lenczewski at arm.com  Tue Mar 25 02:36:22 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Tue, 25 Mar 2025 09:36:22 +0000
Subject: [PATCH v5 0/3] Initial BBML2 support for contpte_convert()
Message-ID: <20250325093625.55184-1-miko.lenczewski@arm.com>

Hi All,

This patch series adds initial support for eliding Break-Before-Make
requirements on systems that support BBML2 and additionally guarantee
to never raise a conflict abort.

This support elides a TLB invalidation in contpte_convert(). This
leads to a 12% improvement when executing a microbenchmark designed
to force the pathological path where contpte_convert() gets called.
This represents an 80% reduction in the cost of calling
contpte_convert().

This series is based on v6.14-rc5 (7eb172143d55).

Notes
======

Patch 1 implements an allow-list of cpus that support BBML2, but with
the additional constraint of never causing TLB conflict aborts. We
settled on this constraint because we will use the feature for kernel
mappings in the future, for which we cannot handle conflict aborts
safely.

Yang Shi has a series at [1] that aims to use BBML2 to enable splitting
the linear map at runtime. This series partially overlaps with it to add
the cpu feature. We believe this series is fully compatible with Yang's
requirements and could go first.

Due to constraints with the current design of the cpufeature framework
and the fact that our has_bbml2_noabort() check relies on both a MIDR
allowlist and the exposed MMFR2 register value, if an implementation
supports our desired BBML2+NOABORT semantics but fails to declare
support for BBML2 via the id_aa64mmfr2.bbm field, the check will fail.

Not declaring base support for BBML2 when supporting BBML2+NOABORT
should be considered an erratum [2], and a workaround can be applied in
__cpuinfo_store_cpu() to patch in support for BBML2 for the sanitised
register view used by SCOPE_SYSTEM. However, SCOPE_LOCAL_CPU bypasses
this sanitised view and reads the MSRs directly by design, and so an
additional workaround can be applied in __read_sysreg_by_encoding()
for the MMFR2 case.

For situations where support for BBML2+NOABORT is claimed by an
implementor and subsequently built into the kernel, but problems later
arise that require user damage control [3], we introduce a kernel
commandline parameter override for disabling all BBML2 support.

[1]:
  https://lore.kernel.org/linux-arm-kernel/20250304222018.615808-1-yang at os.amperecomputing.com/

[2]:
  https://lore.kernel.org/linux-arm-kernel/3bba7adb-392b-4024-984f-b6f0f0f88629 at arm.com/

[3]:
  https://lore.kernel.org/all/0ac0f1f5-e4a0-46ae-8ea0-2eba7e21a7e1 at arm.com/

Changelog
=========

v5:
  - fixup coding style nits
  - document motivation for kernel commandline parameter

v4:
  - https://lore.kernel.org/all/20250319150533.37440-2-miko.lenczewski at arm.com/
  - rebase onto v6.14-rc5
  - switch from arm64 sw feature override to hw feature override
  - reintroduce has_cpuid_feature() check in addition to MIDR check

v3:
  - https://lore.kernel.org/all/20250313104111.24196-2-miko.lenczewski at arm.com/
  - rebase onto v6.14-rc4
  - add arm64.nobbml2 commandline override
  - squash "delay tlbi" and "elide tlbi" patches

v2:
  - https://lore.kernel.org/all/20250228182403.6269-2-miko.lenczewski at arm.com/
  - fix buggy MIDR check to properly account for all boot+late cpus
  - add smmu bbml2 feature check

v1:
  - https://lore.kernel.org/all/20250219143837.44277-3-miko.lenczewski at arm.com/
  - rebase onto v6.14-rc3
  - remove kvm bugfix patches from series
  - strip out conflict abort handler code
  - switch from blocklist to allowlist of bmml2+noabort implementations
  - remove has_cpuid_feature() in favour of MIDR check

rfc-v1:
  - https://lore.kernel.org/all/20241211154611.40395-1-miko.lenczewski at arm.com/
  - https://lore.kernel.org/all/20241211160218.41404-1-miko.lenczewski at arm.com/

Miko?aj Lenczewski (3):
  arm64: Add BBM Level 2 cpu feature
  iommu/arm: Add BBM Level 2 smmu feature
  arm64/mm: Elide tlbi in contpte_convert() under BBML2

 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 19 +++++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  5 ++
 arch/arm64/kernel/cpufeature.c                | 71 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/mm/contpte.c                       |  3 +-
 arch/arm64/tools/cpucaps                      |  1 +
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  3 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  4 ++
 11 files changed, 115 insertions(+), 1 deletion(-)

-- 
2.48.1



From miko.lenczewski at arm.com  Tue Mar 25 02:36:23 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Tue, 25 Mar 2025 09:36:23 +0000
Subject: [PATCH v5 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250325093625.55184-1-miko.lenczewski@arm.com>
References: <20250325093625.55184-1-miko.lenczewski@arm.com>
Message-ID: <20250325093625.55184-2-miko.lenczewski@arm.com>

The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
and this commit adds a dedicated BBML2 cpufeature to test against
support for, as well as a kernel commandline parameter to optionally
disable BBML2 altogether.

This is a system feature as we might have a big.LITTLE architecture
where some cores support BBML2 and some don't, but we want all cores to
be available and BBM to default to level 0 (as opposed to having cores
without BBML2 not coming online).

To support BBML2 in as wide a range of contexts as we can, we want not
only the architectural guarantees that BBML2 makes, but additionally
want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
us having to prove that no recursive faults can be induced in any path
that uses BBML2, allowing its use for arbitrary kernel mappings.
Support detection of such CPUs.

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
---
 .../admin-guide/kernel-parameters.txt         |  3 +
 arch/arm64/Kconfig                            | 19 +++++
 arch/arm64/include/asm/cpucaps.h              |  2 +
 arch/arm64/include/asm/cpufeature.h           |  5 ++
 arch/arm64/kernel/cpufeature.c                | 71 +++++++++++++++++++
 arch/arm64/kernel/pi/idreg-override.c         |  2 +
 arch/arm64/tools/cpucaps                      |  1 +
 7 files changed, 103 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec8..3e4cc917a07e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -453,6 +453,9 @@
 	arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
 			32 bit applications.
 
+	arm64.nobbml2	[ARM64] Unconditionally disable Break-Before-Make Level
+			2 support
+
 	arm64.nobti	[ARM64] Unconditionally disable Branch Target
 			Identification support
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 940343beb3d4..db63e0d83492 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2057,6 +2057,25 @@ config ARM64_TLB_RANGE
 	  The feature introduces new assembly instructions, and they were
 	  support when binutils >= 2.30.
 
+config ARM64_BBML2_NOABORT
+	bool "Enable support for Break-Before-Make Level 2 detection and usage"
+	default y
+	help
+	  FEAT_BBM provides detection of support levels for break-before-make
+	  sequences. If BBM level 2 is supported, some TLB maintenance requirements
+	  can be relaxed to improve performance. We additonally require the
+	  property that the implementation cannot ever raise TLB Conflict Aborts.
+	  Selecting N causes the kernel to fallback to BBM level 0 behaviour
+	  even if the system supports BBM level 2.
+
+	  To enable detection of BBML2 support, and to make use of it, say Y.
+
+	  Detection of and support for BBM level 2 can optionally be overridden
+	  at runtime via the use of the arm64.nobbml2 kernel commandline
+	  parameter. If your system claims support for BBML2, but is unstable
+	  with this option enabled, either say N or make use of the commandline
+	  parameter override to force BBML0.
+
 endmenu # "ARMv8.4 architectural features"
 
 menu "ARMv8.5 architectural features"
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 0b5ca6e0eb09..2d6db33d4e45 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -23,6 +23,8 @@ cpucap_is_possible(const unsigned int cap)
 		return IS_ENABLED(CONFIG_ARM64_PAN);
 	case ARM64_HAS_EPAN:
 		return IS_ENABLED(CONFIG_ARM64_EPAN);
+	case ARM64_HAS_BBML2_NOABORT:
+		return IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT);
 	case ARM64_SVE:
 		return IS_ENABLED(CONFIG_ARM64_SVE);
 	case ARM64_SME:
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e0e4478f5fb5..108ef3fbbc00 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
 	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
 }
 
+static inline bool system_supports_bbml2_noabort(void)
+{
+	return alternative_has_cap_unlikely(ARM64_HAS_BBML2_NOABORT);
+}
+
 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d561cf3b8ac7..832b86fca542 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2176,6 +2176,70 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
 	return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
 }
 
+static bool cpu_has_bbml2_noabort(unsigned int cpu_midr)
+{
+	/*
+	 * We want to allow usage of bbml2 in as wide a range of kernel contexts
+	 * as possible. This list is therefore an allow-list of known-good
+	 * implementations that both support bbml2 and additionally, fulfill the
+	 * extra constraint of never generating TLB conflict aborts when using
+	 * the relaxed bbml2 semantics (such aborts make use of bbml2 in certain
+	 * kernel contexts difficult to prove safe against recursive aborts).
+	 *
+	 * Note that implementations can only be considered "known-good" if their
+	 * implementors attest to the fact that the implementation never raises
+	 * TLBI conflict aborts for bbml2 mapping granularity changes.
+	 */
+	static const struct midr_range supports_bbml2_noabort_list[] = {
+		MIDR_REV_RANGE(MIDR_CORTEX_X4, 0, 3, 0xf),
+		MIDR_REV_RANGE(MIDR_NEOVERSE_V3, 0, 2, 0xf),
+		{}
+	};
+
+	return is_midr_in_range_list(cpu_midr, supports_bbml2_noabort_list);
+}
+
+static inline unsigned int cpu_read_midr(int cpu)
+{
+	WARN_ON_ONCE(!cpu_online(cpu));
+
+	return per_cpu(cpu_data, cpu).reg_midr;
+}
+
+static bool has_bbml2_noabort(const struct arm64_cpu_capabilities *caps, int scope)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_BBML2_NOABORT))
+		return false;
+
+	if (scope & SCOPE_SYSTEM) {
+		int cpu;
+
+		/*
+		 * We are a boot CPU, and must verify that all enumerated boot
+		 * CPUs have MIDR values within our allowlist. Otherwise, we do
+		 * not allow the BBML2 feature to avoid potential faults when
+		 * the insufficient CPUs access memory regions using BBML2
+		 * semantics.
+		 */
+		for_each_online_cpu(cpu) {
+			if (!cpu_has_bbml2_noabort(cpu_read_midr(cpu)))
+				return false;
+		}
+	} else if (scope & SCOPE_LOCAL_CPU) {
+		/*
+		 * We are a hot-plugged CPU, so must only check our MIDR.
+		 * If we have the correct MIDR, but the kernel booted on an
+		 * insufficient CPU, we will not use BBML2 (this is safe). If
+		 * we have an incorrect MIDR, but the kernel booted on a
+		 * sufficient CPU, we will not bring up this CPU.
+		 */
+		if (!cpu_has_bbml2_noabort(read_cpuid_id()))
+			return false;
+	}
+
+	return has_cpuid_feature(caps, scope);
+}
+
 #ifdef CONFIG_ARM64_PAN
 static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
@@ -2926,6 +2990,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.matches = has_cpuid_feature,
 		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
 	},
+	{
+		.desc = "BBM Level 2 without conflict abort",
+		.capability = ARM64_HAS_BBML2_NOABORT,
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.matches = has_bbml2_noabort,
+		ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
+	},
 	{
 		.desc = "52-bit Virtual Addressing for KVM (LPA2)",
 		.capability = ARM64_HAS_LPA2,
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index c6b185b885f7..803a0c99f7b4 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -102,6 +102,7 @@ static const struct ftr_set_desc mmfr2 __prel64_initconst = {
 	.override	= &id_aa64mmfr2_override,
 	.fields		= {
 		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT, mmfr2_varange_filter),
+		FIELD("bbm", ID_AA64MMFR2_EL1_BBM_SHIFT, NULL),
 		{}
 	},
 };
@@ -246,6 +247,7 @@ static const struct {
 	{ "rodata=off",			"arm64_sw.rodataoff=1" },
 	{ "arm64.nolva",		"id_aa64mmfr2.varange=0" },
 	{ "arm64.no32bit_el0",		"id_aa64pfr0.el0=1" },
+	{ "arm64.nobbml2",		"id_aa64mmfr2.bbm=0" },
 };
 
 static int __init parse_hexdigit(const char *p, u64 *v)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1e65f2fb45bd..b03a375e5507 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -14,6 +14,7 @@ HAS_ADDRESS_AUTH_ARCH_QARMA5
 HAS_ADDRESS_AUTH_IMP_DEF
 HAS_AMU_EXTN
 HAS_ARMv8_4_TTL
+HAS_BBML2_NOABORT
 HAS_CACHE_DIC
 HAS_CACHE_IDC
 HAS_CNP
-- 
2.48.1



From miko.lenczewski at arm.com  Tue Mar 25 02:36:24 2025
From: miko.lenczewski at arm.com (=?UTF-8?q?Miko=C5=82aj=20Lenczewski?=)
Date: Tue, 25 Mar 2025 09:36:24 +0000
Subject: [PATCH v5 2/3] iommu/arm: Add BBM Level 2 smmu feature
In-Reply-To: <20250325093625.55184-1-miko.lenczewski@arm.com>
References: <20250325093625.55184-1-miko.lenczewski@arm.com>
Message-ID: <20250325093625.55184-3-miko.lenczewski@arm.com>

For supporting BBM Level 2 for userspace mappings, we want to ensure
that the smmu also supports its own version of BBM Level 2. Luckily, the
smmu spec (IHI 0070G 3.21.1.3) is stricter than the aarch64 spec (DDI
0487K.a D8.16.2), so already guarantees that no aborts are raised when
BBM level 2 is claimed.

Add the feature and testing for it under arm_smmu_sva_supported().

Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>
Reviewed-by: Robin Murphy <robin.murphy at arm.com>
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c     | 3 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h     | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 9ba596430e7c..6ba182572788 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -222,6 +222,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 		feat_mask |= ARM_SMMU_FEAT_VAX;
 	}
 
+	if (system_supports_bbml2_noabort())
+		feat_mask |= ARM_SMMU_FEAT_BBML2;
+
 	if ((smmu->features & feat_mask) != feat_mask)
 		return false;
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 358072b4e293..dcee0bdec924 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4406,6 +4406,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 	if (FIELD_GET(IDR3_RIL, reg))
 		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
 
+	if (FIELD_GET(IDR3_BBML, reg) == IDR3_BBML2)
+		smmu->features |= ARM_SMMU_FEAT_BBML2;
+
 	/* IDR5 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index bd9d7c85576a..85eaf3ab88c2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -60,6 +60,9 @@ struct arm_smmu_device;
 #define ARM_SMMU_IDR3			0xc
 #define IDR3_FWB			(1 << 8)
 #define IDR3_RIL			(1 << 10)
+#define IDR3_BBML			GENMASK(12, 11)
+#define IDR3_BBML1			(1 << 11)
+#define IDR3_BBML2			(2 << 11)
 
 #define ARM_SMMU_IDR5			0x14
 #define IDR5_STALL_MAX			GENMASK(31, 16)
@@ -754,6 +757,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_HA		(1 << 21)
 #define ARM_SMMU_FEAT_HD		(1 << 22)
 #define ARM_SMMU_FEAT_S2FWB		(1 << 23)
+#define ARM_SMMU_FEAT_BBML2		(1 << 24)
 	u32				features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH	(1 << 0)
-- 
2.48.1



From ziniu.wang_1 at nxp.com  Tue Mar 25 02:43:30 2025
From: ziniu.wang_1 at nxp.com (ziniu.wang_1 at nxp.com)
Date: Tue, 25 Mar 2025 17:43:30 +0800
Subject: [PATCH] mmc: host: sdhci-esdhc-imx: save tuning value for the card which keep power in suspend
Message-ID: <20250325094330.2242646-1-ziniu.wang_1@nxp.com>

From: Luke Wang <ziniu.wang_1 at nxp.com>

For some SoCs like imx6ul(l/z) and imx7d, during system PM, usdhc will
totally power off, so the internal tuning status will lost. Here add
save/restore the tuning value for any command after system resume back
when re-tuning hold.

The tipical case is for the SDIO WIFI which contain flag MMC_PM_KEEP_POWER,
it means this device will keep power during system PM. To save power, WIFI
will switch to 1 bit mode, and switch back to 4 bit mode when resume back.
According to spec, tuning command do not support in 1 bit mode. So when
send cmd52 to switch back to 4 bit mode, need to hold re-tuning. But this
cmd52 still need a correct sample point, otherwise will meet command CRC
error, so need to keep the previous tuning value.

Signed-off-by: Luke Wang <ziniu.wang_1 at nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 90 +++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index ff78a7c6a04c..d3ac5f38a9eb 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -81,6 +81,9 @@
 #define  ESDHC_TUNE_CTRL_STEP		1
 #define  ESDHC_TUNE_CTRL_MIN		0
 #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1)
+#define ESDHC_TUNE_CTRL_STATUS_TAP_SEL_PRE_MASK		0x7f000000
+#define ESDHC_TUNE_CTRL_STATUS_TAP_SEL_PRE_SHIFT	24
+#define ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_SHIFT	8
 
 /* strobe dll register */
 #define ESDHC_STROBE_DLL_CTRL		0x70
@@ -235,6 +238,7 @@ struct esdhc_platform_data {
 	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
 	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
 	unsigned int strobe_dll_delay_target;	/* The delay cell for strobe pad (read clock) */
+	unsigned int saved_tuning_delay_cell;	/* save the value of tuning delay cell */
 };
 
 struct esdhc_soc_data {
@@ -1057,7 +1061,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
-	u32 ctrl;
+	u32 ctrl, tuning_ctrl;
 	int ret;
 
 	/* Reset the tuning circuit */
@@ -1071,6 +1075,16 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
 			writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
+			/*
+			 * enable the std tuning just in case it cleared in
+			 * sdhc_esdhc_tuning_restore.
+			 */
+			tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+			if (!(tuning_ctrl & ESDHC_STD_TUNING_EN)) {
+				tuning_ctrl |= ESDHC_STD_TUNING_EN;
+				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
+			}
+
 			ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);
 			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 			ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;
@@ -1149,7 +1163,8 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
 	reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
 			ESDHC_MIX_CTRL_FBCLK_SEL;
 	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
-	writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+	writel(val << ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_SHIFT,
+				host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
 	dev_dbg(mmc_dev(host->mmc),
 		"tuning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n",
 			val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS));
@@ -1569,6 +1584,58 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 	}
 }
 
+static void sdhc_esdhc_tuning_save(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+	u32 reg;
+
+	/*
+	 * SD/eMMC do not need this tuning save because it will re-init
+	 * after system resume back.
+	 * Here save the tuning delay value for SDIO device since it may
+	 * keep power during system PM. And for usdhc, only SDR50 and
+	 * SDR104 mode for SDIO devide need to do tuning, and need to
+	 * save/restore.
+	 */
+	if ((host->timing == MMC_TIMING_UHS_SDR50) ||
+			(host->timing == MMC_TIMING_UHS_SDR104)) {
+		reg = readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+		reg = (reg & ESDHC_TUNE_CTRL_STATUS_TAP_SEL_PRE_MASK) >>
+				ESDHC_TUNE_CTRL_STATUS_TAP_SEL_PRE_SHIFT;
+		imx_data->boarddata.saved_tuning_delay_cell = reg;
+	}
+}
+
+static void sdhc_esdhc_tuning_restore(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+	u32 reg;
+
+	if ((host->timing == MMC_TIMING_UHS_SDR50) ||
+			(host->timing == MMC_TIMING_UHS_SDR104)) {
+		/*
+		 * restore the tuning delay value actually is a
+		 * manual tuning method, so clear the standard
+		 * tuning enable bit here. Will set back this
+		 * ESDHC_STD_TUNING_EN in esdhc_reset_tuning()
+		 * when trigger re-tuning.
+		 */
+		reg = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+		reg &= ~ESDHC_STD_TUNING_EN;
+		writel(reg, host->ioaddr + ESDHC_TUNING_CTRL);
+
+		reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+		reg |= ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL;
+		writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
+
+		writel(imx_data->boarddata.saved_tuning_delay_cell <<
+				ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_SHIFT,
+				host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+	}
+}
+
 static void esdhc_cqe_enable(struct mmc_host *mmc)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -1900,6 +1967,15 @@ static int sdhci_esdhc_suspend(struct device *dev)
 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
 		mmc_retune_needed(host->mmc);
 
+	/*
+	 * For the device need to keep power during system PM, need
+	 * to save the tuning delay value just in case the usdhc
+	 * lost power during system PM.
+	 */
+	if (mmc_card_keep_power(host->mmc) &&
+			(esdhc_is_usdhc(imx_data)))
+		sdhc_esdhc_tuning_save(host);
+
 	ret = sdhci_suspend_host(host);
 	if (ret)
 		return ret;
@@ -1916,6 +1992,8 @@ static int sdhci_esdhc_suspend(struct device *dev)
 static int sdhci_esdhc_resume(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
 	int ret;
 
 	ret = pinctrl_pm_select_default_state(dev);
@@ -1929,6 +2007,14 @@ static int sdhci_esdhc_resume(struct device *dev)
 	if (ret)
 		return ret;
 
+	/*
+	 * restore the saved tuning delay value for the device which keep
+	 * power during system PM.
+	 */
+	if (mmc_card_keep_power(host->mmc) &&
+			(esdhc_is_usdhc(imx_data)))
+		sdhc_esdhc_tuning_restore(host);
+
 	if (host->mmc->caps2 & MMC_CAP2_CQE)
 		ret = cqhci_resume(host->mmc);
 
-- 
2.34.1



From andre.draszik at linaro.org  Tue Mar 25 02:46:06 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 25 Mar 2025 09:46:06 +0000
Subject: [PATCH v3 0/2] firmware: exynos-acpm: allow use during system
 shutdown
Message-ID: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>

One user of this ACPM driver is a PMIC driver that needs to communicate
with the PMIC during late system shutdown [1] and at that time we are
not allowed to sleep anymore.

This series address this by switching the code to using udelay() in the
specific case of system shutdown. This approach was inspired by I2C's
i2c_in_atomic_xfer_mode(), which has to deal with a similar corner
case.

Link: https://lore.kernel.org/all/20250323-s2mpg10-v1-29-d08943702707 at linaro.org/ [1]

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
Changes in v3:
- switch to unconditional udelay() (Krzysztof)
- Link to v2: https://lore.kernel.org/r/20250324-acpm-atomic-v2-0-7d87746e1765 at linaro.org

Changes in v2:
- add missing ktime.h include
- switch to ktime_before() instead of !ktime_after()
- add link to user requiring this change to cover letter
- collect Tudor's Rb
- Link to v1: https://lore.kernel.org/r/20250321-acpm-atomic-v1-0-fb887bde7e61 at linaro.org

---
Andr? Draszik (2):
      firmware: exynos-acpm: use ktime APIs for timeout detection
      firmware: exynos-acpm: allow use during system shutdown

 drivers/firmware/samsung/exynos-acpm.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
---
base-commit: 9388ec571cb1adba59d1cded2300eeb11827679c
change-id: 20250321-acpm-atomic-033775b051ef

Best regards,
-- 
Andr? Draszik <andre.draszik at linaro.org>



From andre.draszik at linaro.org  Tue Mar 25 02:46:07 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 25 Mar 2025 09:46:07 +0000
Subject: [PATCH v3 1/2] firmware: exynos-acpm: use ktime APIs for timeout
 detection
In-Reply-To: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
References: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
Message-ID: <20250325-acpm-atomic-v3-1-c66aae7df925@linaro.org>

acpm_dequeue_by_polling() uses a loop counter and assumes that each
iteration of the loop takes 20us. It may take longer, though, because
usleep_range() may sleep a different amount.

Switch to using ktime_get() / ktime_before() to detect the timeout
condition more reliably.

This change also makes the code easier to follow and it allows us to
adjust the sleep if necessary, without having to adjust the loop
counter exit condition.

Reviewed-by: Tudor Ambarus <tudor.ambarus at linaro.org>
Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>

---
v3:
* slightly reword commit message due to updated patch 2/2

v2:
* add missing ktime.h
* ktime_before() instead of !ktime_after() (Tudor)
---
 drivers/firmware/samsung/exynos-acpm.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index a85b2dbdd9f0d7b1f327f54a0a283e4f32587a98..542eaff03f9e39422a8c5345ca75e05c1710a9ee 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -15,6 +15,7 @@
 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/ktime.h>
 #include <linux/mailbox/exynos-message.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
@@ -32,8 +33,7 @@
 
 #define ACPM_PROTOCOL_SEQNUM		GENMASK(21, 16)
 
-/* The unit of counter is 20 us. 5000 * 20 = 100 ms */
-#define ACPM_POLL_TIMEOUT		5000
+#define ACPM_POLL_TIMEOUT_US		(100 * USEC_PER_MSEC)
 #define ACPM_TX_TIMEOUT_US		500000
 
 #define ACPM_GS101_INITDATA_BASE	0xa000
@@ -284,12 +284,13 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 				   const struct acpm_xfer *xfer)
 {
 	struct device *dev = achan->acpm->dev;
-	unsigned int cnt_20us = 0;
+	ktime_t timeout;
 	u32 seqnum;
 	int ret;
 
 	seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
 
+	timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
 	do {
 		ret = acpm_get_rx(achan, xfer);
 		if (ret)
@@ -300,11 +301,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 
 		/* Determined experimentally. */
 		usleep_range(20, 30);
-		cnt_20us++;
-	} while (cnt_20us < ACPM_POLL_TIMEOUT);
+	} while (ktime_before(ktime_get(), timeout));
 
-	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx, cnt_20us = %d.\n",
-		achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us);
+	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
+		achan->id, seqnum, achan->bitmap_seqnum[0]);
 
 	return -ETIME;
 }

-- 
2.49.0.395.g12beb8f557-goog



From andre.draszik at linaro.org  Tue Mar 25 02:46:08 2025
From: andre.draszik at linaro.org (=?utf-8?q?Andr=C3=A9_Draszik?=)
Date: Tue, 25 Mar 2025 09:46:08 +0000
Subject: [PATCH v3 2/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
References: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
Message-ID: <20250325-acpm-atomic-v3-2-c66aae7df925@linaro.org>

We need to access the PMIC during late system shutdown and at that time
we are not allowed to sleep anymore.

To make this case work, and since we can't detect this case in a
non-racy way, switch to using udelay() unconditionally, instead of
usleep_range().

Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
---
v3:
* use udelay() unconditionally (Krzysztof)
* drop previous Rb tag

udelay(20) causes a checkpatch --strict warning (it suggests to use
usleep_range() instead for usec >= 10), but that's exactly what we can
not do.
Reducing the udelay to be smaller than 10 will generally cause the loop
to be iterated more than once, which I wanted to avoid.
I could reflow the code to hide the actual value from checkpatch, e.g.
with the help of a local variable if that is preferred to ignoring the
checkpatch warning.
---
 drivers/firmware/samsung/exynos-acpm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 542eaff03f9e39422a8c5345ca75e05c1710a9ee..379da420b9eb3fcbca5461bec7e2de6bf0774659 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -300,7 +300,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 			return 0;
 
 		/* Determined experimentally. */
-		usleep_range(20, 30);
+		udelay(20);
 	} while (ktime_before(ktime_get(), timeout));
 
 	dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",

-- 
2.49.0.395.g12beb8f557-goog



From ryan_chen at aspeedtech.com  Tue Mar 25 02:52:04 2025
From: ryan_chen at aspeedtech.com (Ryan Chen)
Date: Tue, 25 Mar 2025 09:52:04 +0000
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <8e8aa069-af9f-453f-9bd0-e3dc2eab59ab@kernel.org>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <20250224-arrogant-adventurous-mackerel-0dc18a@krzk-bin>
 <OS8PR06MB75415E95342F26F576B5CF8AF2C22@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
 <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>
 <SI6PR06MB7535BAD19B51A381171A0E64F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <8e8aa069-af9f-453f-9bd0-e3dc2eab59ab@kernel.org>
Message-ID: <OS8PR06MB7541FD8691B43EA33BDC1D22F2A72@OS8PR06MB7541.apcprd06.prod.outlook.com>

> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> AST2600-i2cv2
> 
> On 24/03/2025 11:01, Ryan Chen wrote:
> >> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >> AST2600-i2cv2
> >>
> >> On 24/03/2025 09:30, Ryan Chen wrote:
> >>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
> >>>> AST2600-i2cv2
> >>>>
> >>>> On 19/03/2025 12:12, Ryan Chen wrote:
> >>>>>> Subject: Re: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support
> >>>>>> for
> >>>>>> AST2600-i2cv2
> >>>>>>
> >>>>>> On 17/03/2025 10:21, Ryan Chen wrote:
> >>>>>>>> Neither this.
> >>>>>>>>
> >>>>>>>> So it seems you describe already existing and documented I2C,
> >>>>>>>> but for some reason you want second compatible. The problem is
> >>>>>>>> that you do not provide reason from the point of view of bindings.
> >>>>>>>>
> >>>>>>>> To summarize: what your users want - don't care. Start properly
> >>>>>>>> describing hardware and your SoC.
> >>>>>>>
> >>>>>>> OK, for ast2600 i2c controller have two register mode setting.
> >>>>>>> One, I call it is old register setting, that is right now
> >>>>>>> i2c-aspeed.c .compatible = "aspeed,ast2600-i2c-bus", And there
> >>>>>>> have a global register
> >>>>>> that can set i2c controller as new mode register set.
> >>>>>>> That I am going to drive. That I post is all register in new an
> >>>>>>> old register
> >>>> list.
> >>>>>>>
> >>>>>>> For example,
> >>>>>>> Global register [2] = 0 => i2c present as old register set
> >>>>>>> Global register [2] = 1 => i2c present as new register set
> >>>>>> It's the same device though, so the same compatible.
> >>>>>
> >>>>> Sorry, it is different design, and it share the same register space.
> >>>>> So that the reason add new compatible "aspeed,ast2600-i2cv2" for
> >>>>> this
> >>>> driver.
> >>>>> It is different register layout.
> >>>>
> >>>> Which device is described by the existing "aspeed,ast2600-i2c-bus"
> >>>> compatible? And which device is described by new compatible?
> >>>>
> >>> On the AST2600 SoC, there are up to 16 I2C controller instances
> >>> (I2C1 ~
> >> I2C16).
> >>
> >> So you have 16 same devices.
> > Yes, one driver instance for 16 i2c device.
> >>
> >>> Each of these controllers is hardwired at the SoC level to use
> >>> either the
> >> legacy register layout or the new v2 register layout.
> >>> The mode is selected by a bit in the global register, these
> >>> represent two
> >> different hardware blocks:
> >>> "aspeed,ast2600-i2c-bus" describes controllers using the legacy
> >>> register
> >> layout.
> >>> "aspeed,ast2600-i2cv2" describes controllers using the new register
> >>> layout
> >>
> >> Which part of "same device" is not clear? You have one device, one
> compatible.
> >> Whatever you do with register layout, is already defined by that
> >> compatible. It does not matter that you forgot to implement it in the Linux
> kernel.
> >
> > Sorry, I still can't catch your point.
> 
> 
> I repeated twice "You have one device, one compatible.", provided few more
> sentences and if this is still unclear, I don't know what to say more.
> 
> > I separated the support into two drivers:
> 
> I don't care about your drivers, why are you bringing them here?
> 
> > i2c-aspeed.c for legacy layout, compatible "aspeed,ast2600-i2c-bus"
> > i2c-ast2600.c for the new register set, compatible compatible
> "aspeed,ast2600-i2cv2"
> > Do you mean I have integrate into 1 driver at i2c-aspeed.c ? can't be
> separate two driver?
> 
> What is this patch about? Bindings. Not drivers. Look at email month ago:
> 
> "All this describes driver, not hardware."
> 
> Why are you keep bringing here drivers since a month?
Let me try to rephrase the reasoning from a hardware point of view:

On AST2600, each I2C controller instance is functionally the same type of device (I2C controller), 
but it can present two different and incompatible register layouts, 
depending on a hardware-controlled configuration (via global register bits that are fixed in production SoCs).
The layouts are not backward-compatible:
Registers are at different offsets. Bit definitions differ.
The programming sequence is not the same.
Because of this incompatibility at the register level, software cannot handle both layouts in a generic way without explicit knowledge of which version is present.
That?s why I proposed a new compatible string ? to represent a hardware-visible difference in register interface, even though the logical function (I2C controller) is the same.


> 
> Best regards,
> Krzysztof

From richard.xnu.clark at gmail.com  Tue Mar 25 02:54:58 2025
From: richard.xnu.clark at gmail.com (richard clark)
Date: Tue, 25 Mar 2025 17:54:58 +0800
Subject: hrtimer precision issue/question??
In-Reply-To: <875xk022wu.ffs@tglx>
References: <CAJNi4rPaPeVWzBve6Toi8hhrxP6GROAGRug7+c3zg1crDeOt7Q@mail.gmail.com>
 <875xk022wu.ffs@tglx>
Message-ID: <CAJNi4rPtsUohpXgD28Bi7K4Y0G=ShgNuUmf1L3E4ze7txj_z0w@mail.gmail.com>

Hi tglx, Thanks for the explanation! I tried run 'cyclictest -a 0 -t 1
-m -p99 -r' to use the relative timer instead of absolute, now the
output of the same diff as:
[   63.824382] [ 0- 0]t0=63816686720,t1=63817689248,d=1002 us
[   63.825387] [ 0- 0]t0=63817691648,t1=63818694144,d=1002 us
[   63.825691] [ 4- 7]t0=63808939136,t1=63818998336,d=10059 us
[   63.826392] [ 0- 0]t0=63818696544,t1=63819699456,d=1002 us
[   63.827402] [ 0- 0]t0=63819704352,t1=63820709120,d=1004 us
[   63.828407] [ 0- 0]t0=63820712448,t1=63821714976,d=1002 us
[   63.829413] [ 0- 0]t0=63821717536,t1=63822720032,d=1002 us
[   63.830417] [ 0- 0]t0=63822722496,t1=63823724928,d=1002 us
[   63.831423] [ 0- 0]t0=63823727264,t1=63824730912,d=1003 us
[   63.832429] [ 0- 0]t0=63824734176,t1=63825736768,d=1002 us
[   63.833434] [ 0- 0]t0=63825739168,t1=63826741568,d=1002 us
[   63.834439] [ 0- 0]t0=63826743904,t1=63827746432,d=1002 us
[   63.835445] [ 0- 0]t0=63827748832,t1=63828752576,d=1003 us
[   63.836164] [ 7- 4]t0=63819412064,t1=63829471328,d=10059 us
[   63.836452] [ 0- 0]t0=63828755936,t1=63829760032,d=1004 us

Now I am wondering if the cyclictest will have the same result using
the relative timer instead of absolute, suppose all the other
conditions are the same?
Also the '-a 0' set affinity to cpu0 and only one timer thread with
'-t 1', don't know why some cyclictest migrate(?) to the other cpus
than cpu0, any comments about this...
Thanks!

On Sun, Mar 23, 2025 at 5:04?AM Thomas Gleixner <tglx at linutronix.de> wrote:
>
> On Sat, Mar 22 2025 at 11:20, richard clark wrote:
> > With diff below under the 'cyclictest -a 0 -t 1 -m -p99' trigger from
> > the arm64-based linux box, the interval is 1000us and the arch_timer
> > in the system is: arch_timer: cp15 timer(s) running at 31.25MHz
> > (phys).  1tick = 32ns for the arch timer, I am not sure if those
> > durations less than 1000us are expected?
>
> With your method of measurement yes. There is a german saying, which
> describes this. It roughly translates to:
>
>    "Who measures a lot, might measure a lot of garbage."
>
> But it accurately describes, what you are measuring here. You do:
>
>     t1 = ktime_get();
>     arm_timer(T);
>     schedule();
>     t2 = ktime_get();
>
> and then look at t2 - t1. That only tells you how long the task actually
> slept. But that's ignoring the most important information here:
>
>     arm_timer(T);
>
> cyclictest uses:
>
>            clock_nanosleep(clockid, ABSTIME, &T);
>
> and T is maintained in absolute time on a periodic time line.
>
>     T = starttime + N * interval;
>
> So the only interesting information here is at which time the task
> returns from schedule(), i.e. you want to look at:
>
>         t2 - T
>
> Why? Because that gives you the latency of the wakeup. That's what
> cyclictest is looking at in user space:
>
>            clock_nanosleep(... &T);
>            clock_gettime(..., &T2);
>            latency = T2 - T;
>
> Now what you are looking at is the time at which the cyclictest task
> comes back into the kernel to sleep, which is obviously
>
>            t1 = T[N] + latency[N-1] + execution_time;
>
> But the timer is armed for T[N], so your t2 is:
>
>            t2 = T[N] + latency[N];
>
> You surely can do the remaining math and map that to the output:
>
> > [  165.555795] [ 0- 0]t0=165550399226,t1=165551394303,d=995 us
> > [  165.556802] [ 0- 0]t0=165551398751,t1=165552400997,d=1002 us
>
> Right?
>
> Thanks,
>
>         tglx


From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:33 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:33 +0100
Subject: [PATCH v16 6/6] remoteproc: stm32: Add support of an OP-TEE TA to load the firmware
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-7-arnaud.pouliquen@foss.st.com>

The new TEE remoteproc driver is used to manage remote firmware in a
secure, trusted context. The 'st,stm32mp1-m4-tee' compatibility is
introduced to delegate the loading of the firmware to the trusted
execution context. In such cases, the firmware should be signed and
adhere to the image format defined by the TEE.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
---
 drivers/remoteproc/stm32_rproc.c | 57 ++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index b1bda314ca85..829dfd440dbf 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -18,6 +18,7 @@
 #include <linux/pm_wakeirq.h>
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
+#include <linux/remoteproc_tee.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -255,6 +256,19 @@ static int stm32_rproc_release(struct rproc *rproc)
 	return 0;
 }
 
+static int stm32_rproc_tee_stop(struct rproc *rproc)
+{
+	int err;
+
+	stm32_rproc_request_shutdown(rproc);
+
+	err = rproc_tee_stop(rproc);
+	if (err)
+		return err;
+
+	return stm32_rproc_release(rproc);
+}
+
 static int stm32_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
@@ -691,8 +705,20 @@ static const struct rproc_ops st_rproc_ops = {
 	.get_boot_addr	= rproc_elf_get_boot_addr,
 };
 
+static const struct rproc_ops st_rproc_tee_ops = {
+	.prepare	= stm32_rproc_prepare,
+	.start		= rproc_tee_start,
+	.stop		= stm32_rproc_tee_stop,
+	.kick		= stm32_rproc_kick,
+	.load		= rproc_tee_load_fw,
+	.parse_fw	= rproc_tee_parse_fw,
+	.find_loaded_rsc_table = rproc_tee_find_loaded_rsc_table,
+	.release_fw	= rproc_tee_release_fw,
+};
+
 static const struct of_device_id stm32_rproc_match[] = {
 	{ .compatible = "st,stm32mp1-m4" },
+	{ .compatible = "st,stm32mp1-m4-tee" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, stm32_rproc_match);
@@ -853,15 +879,36 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 	struct device_node *np = dev->of_node;
 	struct rproc *rproc;
 	unsigned int state;
+	u32 proc_id;
 	int ret;
 
 	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
 
-	rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
-	if (!rproc)
-		return -ENOMEM;
+	if (of_device_is_compatible(np, "st,stm32mp1-m4-tee")) {
+		/*
+		 * Delegate the firmware management to the secure context.
+		 * The firmware loaded has to be signed.
+		 */
+		ret = of_property_read_u32(np, "st,proc-id", &proc_id);
+		if (ret) {
+			dev_err(dev, "failed to read st,rproc-id property\n");
+			return ret;
+		}
+
+		rproc = devm_rproc_alloc(dev, np->name, &st_rproc_tee_ops, NULL, sizeof(*ddata));
+		if (!rproc)
+			return -ENOMEM;
+
+		ret = rproc_tee_register(dev, rproc, proc_id);
+		if (ret)
+			return dev_err_probe(dev, ret,  "signed firmware not supported by TEE\n");
+	} else {
+		rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
+		if (!rproc)
+			return -ENOMEM;
+	}
 
 	ddata = rproc->priv;
 
@@ -913,6 +960,8 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 		dev_pm_clear_wake_irq(dev);
 		device_init_wakeup(dev, false);
 	}
+	rproc_tee_unregister(dev, rproc);
+
 	return ret;
 }
 
@@ -933,6 +982,8 @@ static void stm32_rproc_remove(struct platform_device *pdev)
 		dev_pm_clear_wake_irq(dev);
 		device_init_wakeup(dev, false);
 	}
+
+	rproc_tee_unregister(dev, rproc);
 }
 
 static int stm32_rproc_suspend(struct device *dev)
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:27 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:27 +0100
Subject: [PATCH v16 0/6] Introduction of a remoteproc tee to load signed firmware
Message-ID: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>

Main updates from version V15[1]:
- Removed the rproc_ops:load_fw() operation introduced in the previous version.
- Returned to managing the remoteproc firmware loading in rproc_tee_parse_fw to
  load and authenticate the firmware before getting the resource table.
- Added spinlock and dev_link mechanisms in remoteproc TEE to better manage
  bind/unbind.

More details are available in each patch commit message.

[1] https://lore.kernel.org/linux-remoteproc/20241128084219.2159197-7-arnaud.pouliquen at foss.st.com/T/

Tested-on: commit 0a0ba9924445 ("Linux 6.14-rc7")

Description of the feature:
--------------------------
This series proposes the implementation of a remoteproc tee driver to
communicate with a TEE trusted application responsible for authenticating
and loading the remoteproc firmware image in an Arm secure context.

1) Principle:

The remoteproc tee driver provides services to communicate with the OP-TEE
trusted application running on the Trusted Execution Context (TEE).
The trusted application in TEE manages the remote processor lifecycle:

- authenticating and loading firmware images,
- isolating and securing the remote processor memories,
- supporting multi-firmware (e.g., TF-M + Zephyr on a Cortex-M33),
- managing the start and stop of the firmware by the TEE.

2) Format of the signed image:

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/ta/remoteproc/src/remoteproc_core.c#L18-L57

3) OP-TEE trusted application API:

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/ta/remoteproc/include/ta_remoteproc.h

4) OP-TEE signature script

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/scripts/sign_rproc_fw.py

Example of usage:
sign_rproc_fw.py --in <fw1.elf> --in <fw2.elf> --out <signed_fw.sign> --key ${OP-TEE_PATH}/keys/default.pem


5) Impact on User space Application

No sysfs impact. The user only needs to provide the signed firmware image
instead of the ELF image.


For more information about the implementation, a presentation is available here
(note that the format of the signed image has evolved between the presentation
and the integration in OP-TEE).

https://resources.linaro.org/en/resource/6c5bGvZwUAjX56fvxthxds



Arnaud Pouliquen (6):
  remoteproc: core: Introduce rproc_pa_to_va helper
  remoteproc: Add TEE support
  remoteproc: Introduce release_fw optional operation
  dt-bindings: remoteproc: Add compatibility for TEE support
  remoteproc: stm32: Create sub-functions to request shutdown and
    release
  remoteproc: stm32: Add support of an OP-TEE TA to load the firmware

 .../bindings/remoteproc/st,stm32-rproc.yaml   |  58 +-
 drivers/remoteproc/Kconfig                    |  10 +
 drivers/remoteproc/Makefile                   |   1 +
 drivers/remoteproc/remoteproc_core.c          |  52 ++
 drivers/remoteproc/remoteproc_internal.h      |   6 +
 drivers/remoteproc/remoteproc_tee.c           | 619 ++++++++++++++++++
 drivers/remoteproc/stm32_rproc.c              | 139 +++-
 include/linux/remoteproc.h                    |   4 +
 include/linux/remoteproc_tee.h                |  90 +++
 9 files changed, 935 insertions(+), 44 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_tee.c
 create mode 100644 include/linux/remoteproc_tee.h


base-commit: 0a0ba99244455fea8706c4a53f5f66a45d87905d
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:30 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:30 +0100
Subject: [PATCH v16 3/6] remoteproc: Introduce release_fw optional operation
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-4-arnaud.pouliquen@foss.st.com>

The release_fw operation is the inverse operation of the load, responsible
for releasing the remote processor resources configured from the loading
of the remoteproc firmware (e.g., memories).

The operation is called in the following cases:
 - An error occurs on boot of the remote processor.
 - An error occurs on recovery start of the remote processor.
 - After stopping the remote processor.

This operation is needed for the remoteproc_tee implementation after stop
and on error.
Indeed, as the remoteproc image is loaded when we parse the resource
table, there are many situations where something can go wrong before
the start of the remote processor(resource handling, carveout allocation,
...).

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
---
Updates vs previous version:
- remove the rproc:load_fw() ops introduced in previous version
- remove duplicate call of rproc_release_fw in rproc_fw_boot and rproc_boot
---
 drivers/remoteproc/remoteproc_core.c     | 6 ++++++
 drivers/remoteproc/remoteproc_internal.h | 6 ++++++
 include/linux/remoteproc.h               | 3 +++
 3 files changed, 15 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index f05122b699b7..79317d148651 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1857,6 +1857,8 @@ static int rproc_boot_recovery(struct rproc *rproc)
 
 	/* boot the remote processor up again */
 	ret = rproc_start(rproc, firmware_p);
+	if (ret)
+		rproc_release_fw(rproc);
 
 	release_firmware(firmware_p);
 
@@ -1998,6 +2000,8 @@ int rproc_boot(struct rproc *rproc)
 		}
 
 		ret = rproc_fw_boot(rproc, firmware_p);
+		if (ret)
+			rproc_release_fw(rproc);
 
 		release_firmware(firmware_p);
 	}
@@ -2067,6 +2071,8 @@ int rproc_shutdown(struct rproc *rproc)
 
 	rproc_disable_iommu(rproc);
 
+	rproc_release_fw(rproc);
+
 	/* Free the copy of the resource table */
 	kfree(rproc->cached_table);
 	rproc->cached_table = NULL;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 0cd09e67ac14..c7fb908f8652 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -221,4 +221,10 @@ bool rproc_u64_fit_in_size_t(u64 val)
 	return (val <= (size_t) -1);
 }
 
+static inline void rproc_release_fw(struct rproc *rproc)
+{
+	if (rproc->ops->release_fw)
+		rproc->ops->release_fw(rproc);
+}
+
 #endif /* REMOTEPROC_INTERNAL_H */
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 8fd0d7f63c8e..80128461972b 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -381,6 +381,8 @@ enum rsc_handling_status {
  * @panic:	optional callback to react to system panic, core will delay
  *		panic at least the returned number of milliseconds
  * @coredump:	  collect firmware dump after the subsystem is shutdown
+ * @release_fw:	optional function to release the loaded firmware, called after
+ *              stopping the remote processor or in case of error
  */
 struct rproc_ops {
 	int (*prepare)(struct rproc *rproc);
@@ -403,6 +405,7 @@ struct rproc_ops {
 	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
 	unsigned long (*panic)(struct rproc *rproc);
 	void (*coredump)(struct rproc *rproc);
+	void (*release_fw)(struct rproc *rproc);
 };
 
 /**
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:32 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:32 +0100
Subject: [PATCH v16 5/6] remoteproc: stm32: Create sub-functions to request shutdown and release
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-6-arnaud.pouliquen@foss.st.com>

To prepare for the support of TEE remoteproc, create sub-functions
that can be used in both cases, with and without remoteproc TEE support.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
---
 drivers/remoteproc/stm32_rproc.c | 82 +++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 33 deletions(-)

diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index b02b36a3f515..b1bda314ca85 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -209,6 +209,52 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
 	return -EINVAL;
 }
 
+static void stm32_rproc_request_shutdown(struct rproc *rproc)
+{
+	struct stm32_rproc *ddata = rproc->priv;
+	int err, idx;
+
+	/* Request shutdown of the remote processor */
+	if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) {
+		idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
+		if (idx >= 0 && ddata->mb[idx].chan) {
+			err = mbox_send_message(ddata->mb[idx].chan, "detach");
+			if (err < 0)
+				dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
+		}
+	}
+}
+
+static int stm32_rproc_release(struct rproc *rproc)
+{
+	struct stm32_rproc *ddata = rproc->priv;
+	unsigned int err = 0;
+
+	/* To allow platform Standby power mode, set remote proc Deep Sleep */
+	if (ddata->pdds.map) {
+		err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
+					 ddata->pdds.mask, 1);
+		if (err) {
+			dev_err(&rproc->dev, "failed to set pdds\n");
+			return err;
+		}
+	}
+
+	/* Update coprocessor state to OFF if available */
+	if (ddata->m4_state.map) {
+		err = regmap_update_bits(ddata->m4_state.map,
+					 ddata->m4_state.reg,
+					 ddata->m4_state.mask,
+					 M4_STATE_OFF);
+		if (err) {
+			dev_err(&rproc->dev, "failed to set copro state\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
 static int stm32_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
@@ -519,17 +565,9 @@ static int stm32_rproc_detach(struct rproc *rproc)
 static int stm32_rproc_stop(struct rproc *rproc)
 {
 	struct stm32_rproc *ddata = rproc->priv;
-	int err, idx;
+	int err;
 
-	/* request shutdown of the remote processor */
-	if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) {
-		idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
-		if (idx >= 0 && ddata->mb[idx].chan) {
-			err = mbox_send_message(ddata->mb[idx].chan, "detach");
-			if (err < 0)
-				dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
-		}
-	}
+	stm32_rproc_request_shutdown(rproc);
 
 	err = stm32_rproc_set_hold_boot(rproc, true);
 	if (err)
@@ -541,29 +579,7 @@ static int stm32_rproc_stop(struct rproc *rproc)
 		return err;
 	}
 
-	/* to allow platform Standby power mode, set remote proc Deep Sleep */
-	if (ddata->pdds.map) {
-		err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
-					 ddata->pdds.mask, 1);
-		if (err) {
-			dev_err(&rproc->dev, "failed to set pdds\n");
-			return err;
-		}
-	}
-
-	/* update coprocessor state to OFF if available */
-	if (ddata->m4_state.map) {
-		err = regmap_update_bits(ddata->m4_state.map,
-					 ddata->m4_state.reg,
-					 ddata->m4_state.mask,
-					 M4_STATE_OFF);
-		if (err) {
-			dev_err(&rproc->dev, "failed to set copro state\n");
-			return err;
-		}
-	}
-
-	return 0;
+	return stm32_rproc_release(rproc);
 }
 
 static void stm32_rproc_kick(struct rproc *rproc, int vqid)
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:31 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:31 +0100
Subject: [PATCH v16 4/6] dt-bindings: remoteproc: Add compatibility for TEE support
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-5-arnaud.pouliquen@foss.st.com>

The "st,stm32mp1-m4-tee" compatible is utilized in a system configuration
where the Cortex-M4 firmware is loaded by the Trusted Execution Environment
(TEE).

For instance, this compatible is used in both the Linux and OP-TEE device
trees:
- In OP-TEE, a node is defined in the device tree with the
  "st,stm32mp1-m4-tee" compatible to support signed remoteproc firmware.
  Based on DT properties, the OP-TEE remoteproc framework is initiated to
  expose a trusted application service to authenticate and load the remote
  processor firmware provided by the Linux remoteproc framework, as well
  as to start and stop the remote processor.
- In Linux, when the compatibility is set, the Cortex-M resets should not
  be declared in the device tree. In such a configuration, the reset is
  managed by the OP-TEE remoteproc driver and is no longer accessible from
  the Linux kernel.

Associated with this new compatible, add the "st,proc-id" property to
identify the remote processor. This ID is used to define a unique ID,
common between Linux, U-Boot, and OP-TEE, to identify a coprocessor.
This ID will be used in requests to the OP-TEE remoteproc Trusted
Application to specify the remote processor.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../bindings/remoteproc/st,stm32-rproc.yaml   | 58 ++++++++++++++++---
 1 file changed, 50 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
index 370af61d8f28..409123cd4667 100644
--- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
@@ -16,7 +16,12 @@ maintainers:
 
 properties:
   compatible:
-    const: st,stm32mp1-m4
+    enum:
+      - st,stm32mp1-m4
+      - st,stm32mp1-m4-tee
+    description:
+      Use "st,stm32mp1-m4" for the Cortex-M4 coprocessor management by non-secure context
+      Use "st,stm32mp1-m4-tee" for the Cortex-M4 coprocessor management by secure context
 
   reg:
     description:
@@ -43,6 +48,10 @@ properties:
           - description: The offset of the hold boot setting register
           - description: The field mask of the hold boot
 
+  st,proc-id:
+    description: remote processor identifier
+    $ref: /schemas/types.yaml#/definitions/uint32
+
   st,syscfg-tz:
     deprecated: true
     description:
@@ -142,21 +151,43 @@ properties:
 required:
   - compatible
   - reg
-  - resets
 
 allOf:
   - if:
       properties:
-        reset-names:
-          not:
-            contains:
-              const: hold_boot
+        compatible:
+          contains:
+            const: st,stm32mp1-m4
     then:
+      if:
+        properties:
+          reset-names:
+            not:
+              contains:
+                const: hold_boot
+      then:
+        required:
+          - st,syscfg-holdboot
+      else:
+        properties:
+          st,syscfg-holdboot: false
+        required:
+          - reset-names
       required:
-        - st,syscfg-holdboot
-    else:
+        - resets
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: st,stm32mp1-m4-tee
+    then:
       properties:
         st,syscfg-holdboot: false
+        reset-names: false
+        resets: false
+      required:
+        - st,proc-id
 
 additionalProperties: false
 
@@ -188,5 +219,16 @@ examples:
       st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
       st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>;
     };
+  - |
+    #include <dt-bindings/reset/stm32mp1-resets.h>
+    m4 at 10000000 {
+      compatible = "st,stm32mp1-m4-tee";
+      reg = <0x10000000 0x40000>,
+            <0x30000000 0x40000>,
+            <0x38000000 0x10000>;
+      st,proc-id = <0>;
+      st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
+      st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>;
+    };
 
 ...
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:28 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:28 +0100
Subject: [PATCH v16 1/6] remoteproc: core: Introduce rproc_pa_to_va helper
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-2-arnaud.pouliquen@foss.st.com>

When a resource table is loaded by an external entity such as U-boot or
OP-TEE, we do not necessarily get the device address(da) but the physical
address(pa).
This helper performs similar translation than the rproc_da_to_va()
but based on a physical address.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
---
 drivers/remoteproc/remoteproc_core.c | 46 ++++++++++++++++++++++++++++
 include/linux/remoteproc.h           |  1 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index c2cf0d277729..f05122b699b7 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -230,6 +230,52 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 }
 EXPORT_SYMBOL(rproc_da_to_va);
 
+/**
+ * rproc_pa_to_va() - lookup the kernel virtual address for a physical address of a remoteproc
+ * memory
+ *
+ * @rproc: handle of a remote processor
+ * @pa: remoteproc physical address
+ * @len: length of the memory region @pa is pointing to
+ * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory
+ *
+ * This function is a helper function similar to rproc_da_to_va() but it deals with physical
+ * addresses instead of device addresses.
+ *
+ * Return: a valid kernel address on success or NULL on failure
+ */
+void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem)
+{
+	struct rproc_mem_entry *carveout;
+	void *ptr = NULL;
+
+	list_for_each_entry(carveout, &rproc->carveouts, node) {
+		int offset = pa - carveout->dma;
+
+		/*  Verify that carveout is allocated */
+		if (!carveout->va)
+			continue;
+
+		/* try next carveout if da is too small */
+		if (offset < 0)
+			continue;
+
+		/* try next carveout if da is too large */
+		if (offset + len > carveout->len)
+			continue;
+
+		ptr = carveout->va + offset;
+
+		if (is_iomem)
+			*is_iomem = carveout->is_iomem;
+
+		break;
+	}
+
+	return ptr;
+}
+EXPORT_SYMBOL(rproc_pa_to_va);
+
 /**
  * rproc_find_carveout_by_name() - lookup the carveout region by a name
  * @rproc: handle of a remote processor
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index b4795698d8c2..8fd0d7f63c8e 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -690,6 +690,7 @@ int rproc_detach(struct rproc *rproc);
 int rproc_set_firmware(struct rproc *rproc, const char *fw_name);
 void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
 void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
+void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem);
 
 /* from remoteproc_coredump.c */
 void rproc_coredump_cleanup(struct rproc *rproc);
-- 
2.25.1



From arnaud.pouliquen at foss.st.com  Tue Mar 25 02:58:29 2025
From: arnaud.pouliquen at foss.st.com (Arnaud Pouliquen)
Date: Tue, 25 Mar 2025 10:58:29 +0100
Subject: [PATCH v16 2/6] remoteproc: Add TEE support
In-Reply-To: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
References: <20250325095833.3059895-1-arnaud.pouliquen@foss.st.com>
Message-ID: <20250325095833.3059895-3-arnaud.pouliquen@foss.st.com>

Add a remoteproc TEE (Trusted Execution Environment) driver that will be
probed by the TEE bus. If the associated Trusted application is supported
on the secure part, this driver offers a client interface to load firmware
by the secure part.
This firmware could be authenticated by the secure trusted application.

A specificity of the implementation is that the firmware has to be
authenticated and optionally decrypted to access the resource table.

Consequently, the boot sequence is:

1) rproc_parse_fw --> rproc_tee_parse_fw
   remoteproc TEE:
   - Requests the TEE application to authenticate and load the firmware
     in the remote processor memories.
   - Requests the TEE application for the address of the resource table.
   - Creates a copy of the resource table stored in rproc->cached_table.

2) rproc_load_segments --> rproc_tee_load_fw
   remoteproc TEE:
   - Requests the TEE application to load the firmware. Nothing is done
     at the TEE application as the firmware is already loaded.
   - In case of recovery, the TEE application has to reload the firmware.

3) rproc_tee_get_loaded_rsc_table
   remoteproc TEE requests the TEE application for the address of the
   resource table.

4) rproc_start --> rproc_tee_start
   - Requests the TEE application to start the remote processor.


The shutdown sequence is:

5) rproc_stop --> rproc_tee_stop
   - Requests the TEE application to stop the remote processor.

6) rproc_tee_release_fw
   This function is used to request the TEE application to perform actions
   to return to the initial state on stop or on error during the boot
   sequence.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
---
Updates vs previous version:
- Come back to v13 managing a load in rproc_tee_parse_fw().
- Replace IS_REACHABLE with IS_ENABLED in remoteproc_tee.h, remoteproc_tee
  is not supported as module
- update REMOTEPROC_TEE config description in Kconfig
- manage unbind sequence of the consumer rproc drivers using devlink
- remove TA_RPROC_FW_CMD_GET_COREDUMP as not use ( to be treated in a
  separate thread)
- define a static `rproc_tee_ctx` variable instead of allocating it
- add spinlock to protect `rproc_tee_ctx` accesses.
- add exported function doumentation
---
 drivers/remoteproc/Kconfig          |  10 +
 drivers/remoteproc/Makefile         |   1 +
 drivers/remoteproc/remoteproc_tee.c | 619 ++++++++++++++++++++++++++++
 include/linux/remoteproc_tee.h      |  90 ++++
 4 files changed, 720 insertions(+)
 create mode 100644 drivers/remoteproc/remoteproc_tee.c
 create mode 100644 include/linux/remoteproc_tee.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 83962a114dc9..e39265d249d9 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -23,6 +23,16 @@ config REMOTEPROC_CDEV
 
 	  It's safe to say N if you don't want to use this interface.
 
+config REMOTEPROC_TEE
+	bool "Remoteproc support by a TEE application"
+	depends on OPTEE
+	help
+	  Support a remote processor that is managed by an application running in a Trusted
+	  Execution Environment (TEE). This application is responsible for loading the remote
+	  processor firmware image and managing its lifecycle.
+
+	  It's safe to say N if the remote processor is not managed by a TEE.
+
 config IMX_REMOTEPROC
 	tristate "i.MX remoteproc support"
 	depends on ARCH_MXC
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 5ff4e2fee4ab..f77e0abe8349 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,6 +11,7 @@ remoteproc-y				+= remoteproc_sysfs.o
 remoteproc-y				+= remoteproc_virtio.o
 remoteproc-y				+= remoteproc_elf_loader.o
 obj-$(CONFIG_REMOTEPROC_CDEV)		+= remoteproc_cdev.o
+obj-$(CONFIG_REMOTEPROC_TEE)		+= remoteproc_tee.o
 obj-$(CONFIG_IMX_REMOTEPROC)		+= imx_rproc.o
 obj-$(CONFIG_IMX_DSP_REMOTEPROC)	+= imx_dsp_rproc.o
 obj-$(CONFIG_INGENIC_VPU_RPROC)		+= ingenic_rproc.o
diff --git a/drivers/remoteproc/remoteproc_tee.c b/drivers/remoteproc/remoteproc_tee.c
new file mode 100644
index 000000000000..cf50de7eb952
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_tee.c
@@ -0,0 +1,619 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) STMicroelectronics 2024
+ * Author: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
+ */
+
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/remoteproc_tee.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+
+#define MAX_TEE_PARAM_ARRAY_MEMBER	4
+
+/*
+ * Authentication and load of the firmware image in the remote processor memories by the TEE.
+ * After this step the firmware is loaded in destination memories, which can then be locked to
+ * prevent access by Linux.
+ *
+ * [in]  params[0].value.a:	remote processor identifier
+ * [in]	 params[1].memref:	buffer containing a temporary copy of the signed image to load.
+ */
+#define TA_RPROC_FW_CMD_LOAD_FW		1
+
+/*
+ * Start the remote processor by the TEE
+ *
+ * [in]  params[0].value.a:	remote processor identifier
+ */
+#define TA_RPROC_FW_CMD_START		2
+
+/*
+ * Stop the remote processor by the TEE
+ *
+ * [in]  params[0].value.a:	remote processor identifier
+ */
+#define TA_RPROC_FW_CMD_STOP		3
+
+/*
+ * Return the address of the resource table, or 0 if not found.
+ *
+ * [in]  params[0].value.a:	remote processor identifier
+ * [out]  params[1].value.a:	32bit LSB resource table memory address
+ * [out]  params[1].value.b:	32bit MSB resource table memory address
+ * [out]  params[2].value.a:	32bit LSB resource table memory size
+ * [out]  params[2].value.b:	32bit MSB resource table memory size
+ */
+#define TA_RPROC_FW_CMD_GET_RSC_TABLE	4
+
+/*
+ * Release remote processor firmware images and associated resources.
+ * This command should be used in case an error occurs between the loading of
+ * the firmware images (TA_RPROC_CMD_LOAD_FW) and the starting of the remote
+ * processor (TA_RPROC_CMD_START_FW) or after stopping the remote processor
+ * to release associated resources (TA_RPROC_CMD_STOP_FW).
+ *
+ * [in]  params[0].value.a: Unique 32-bit remote processor identifier
+ */
+#define TA_RPROC_CMD_RELEASE_FW		6
+
+struct rproc_tee_context {
+	struct list_head	sessions;
+	struct tee_context	*tee_ctx;
+	struct device		*dev;
+};
+
+/**
+ * struct rproc_tee - TEE remoteproc structure
+ * @node:		Reference in list
+ * @rproc:		Remoteproc reference
+ * @rproc_id:		Identifier of the target firmware
+ * @session_id:		TEE session identifier
+ */
+struct rproc_tee {
+	struct list_head node;
+	struct rproc *rproc;
+	u32 rproc_id;
+	u32 session_id;
+};
+
+static struct rproc_tee_context rproc_tee_ctx;
+static DEFINE_SPINLOCK(ctx_lock);
+
+static struct rproc_tee *rproc_to_trproc(struct rproc *rproc)
+{
+	struct rproc_tee *trproc;
+
+	list_for_each_entry(trproc, &rproc_tee_ctx.sessions, node)
+		if (trproc->rproc == rproc)
+			return trproc;
+
+	return NULL;
+}
+
+static void rproc_tee_prepare_args(struct rproc_tee *trproc, int cmd,
+				   struct tee_ioctl_invoke_arg *arg,
+				   struct tee_param *param,
+				   unsigned int num_params)
+{
+	memset(arg, 0, sizeof(*arg));
+	memset(param, 0, MAX_TEE_PARAM_ARRAY_MEMBER * sizeof(*param));
+
+	arg->func = cmd;
+	arg->session = trproc->session_id;
+	arg->num_params = num_params + 1;
+
+	param[0] = (struct tee_param) {
+		.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
+		.u.value.a = trproc->rproc_id,
+	};
+}
+
+/**
+ * rproc_tee_release_fw - Release the firmware for a TEE-based remote processor
+ *
+ * This function invokes the TA_RPROC_CMD_RELEASE_FW TEE client function to release the firmware.
+ * It should only be called when the remoteproc state is RPROC_OFFLINE or RPROC_DETACHED.
+ * The function requests the TEE remoteproc application to release the firmware loaded by
+ * rproc_tee_load_fw(). The request is ignored if the rproc state is RPROC_DETACHED as the
+ * remote processor is still running.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ */
+void rproc_tee_release_fw(struct rproc *rproc)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	struct tee_ioctl_invoke_arg arg;
+	int ret;
+
+	if (!rproc_tee_ctx.dev)
+		return;
+
+	if (!trproc)
+		return;
+
+	/*
+	 * If the remote processor state is RPROC_DETACHED, just ignore the
+	 * request, as the remote processor is still running.
+	 */
+	if (rproc->state == RPROC_DETACHED)
+		return;
+
+	if (rproc->state != RPROC_OFFLINE) {
+		dev_err(rproc_tee_ctx.dev, "unexpected rproc state: %d\n", rproc->state);
+		return;
+	}
+
+	rproc_tee_prepare_args(trproc, TA_RPROC_CMD_RELEASE_FW, &arg, param, 0);
+
+	ret = tee_client_invoke_func(rproc_tee_ctx.tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(rproc_tee_ctx.dev,
+			"TA_RPROC_CMD_RELEASE_FW invoke failed TEE err: %#x, ret:%d\n",
+			arg.ret, ret);
+		ret = -EIO;
+	}
+}
+EXPORT_SYMBOL_GPL(rproc_tee_release_fw);
+
+/**
+ * rproc_tee_load_fw - Load firmware from TEE application
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * This function invokes the TA_RPROC_FW_CMD_LOAD_FW TEE client function to load the firmware.
+ * It registers the fw->data as a shared memory region with the TEE, and request the TEE to load
+ * the firmware. This function can be called twice during the remote processor boot, considering
+ * that the TEE application ignores the command if the firmware is already loaded.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * Return: 0 on success, or an error code on failure
+ */
+int rproc_tee_load_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	struct tee_ioctl_invoke_arg arg;
+	struct tee_shm *fw_shm;
+	int ret;
+
+	if (!rproc_tee_ctx.dev)
+		return -ENODEV;
+
+	if (!trproc)
+		return -EINVAL;
+
+	fw_shm = tee_shm_register_kernel_buf(rproc_tee_ctx.tee_ctx, (void *)fw->data, fw->size);
+	if (IS_ERR(fw_shm))
+		return PTR_ERR(fw_shm);
+
+	rproc_tee_prepare_args(trproc, TA_RPROC_FW_CMD_LOAD_FW, &arg, param, 1);
+
+	/* Provide the address of the firmware image */
+	param[1] = (struct tee_param) {
+		.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
+		.u.memref = {
+			.shm = fw_shm,
+			.size = fw->size,
+			.shm_offs = 0,
+		},
+	};
+
+	ret = tee_client_invoke_func(rproc_tee_ctx.tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(rproc_tee_ctx.dev,
+			"TA_RPROC_FW_CMD_LOAD_FW invoke failed TEE err: %#x, ret:%d\n",
+			arg.ret, ret);
+		if (!ret)
+			ret = -EIO;
+	}
+
+	tee_shm_free(fw_shm);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_load_fw);
+
+static int rproc_tee_get_loaded_rsc_table(struct rproc *rproc, phys_addr_t *rsc_pa,
+					  size_t *table_sz)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	struct tee_ioctl_invoke_arg arg;
+	int ret;
+
+	if (!rproc_tee_ctx.dev)
+		return -ENODEV;
+
+	if (!trproc)
+		return -EINVAL;
+
+	rproc_tee_prepare_args(trproc, TA_RPROC_FW_CMD_GET_RSC_TABLE, &arg, param, 2);
+
+	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+	param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+	ret = tee_client_invoke_func(rproc_tee_ctx.tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(rproc_tee_ctx.dev,
+			"TA_RPROC_FW_CMD_GET_RSC_TABLE invoke failed TEE err: %#x, ret:%d\n",
+			arg.ret, ret);
+		return -EIO;
+	}
+
+	*table_sz = param[2].u.value.a;
+
+	if (*table_sz)
+		*rsc_pa = param[1].u.value.a;
+	else
+		*rsc_pa  = 0;
+
+	return 0;
+}
+
+/**
+ * rproc_tee_parse_fw - Get the resource table from TEE application
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * This function retrieves the loaded resource table and creates a cached_table copy. Since the
+ * firmware image is signed and potentially encrypted, the firmware must be loaded first to
+ * access the loaded resource table.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * Return: 0 on success, or an error code on failure
+ */
+int rproc_tee_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	phys_addr_t rsc_table;
+	void __iomem *rsc_va;
+	size_t table_sz;
+	int ret;
+
+	if (!rproc)
+		return -EINVAL;
+
+	/* We need first to Load the firmware, to be able to get the resource table. */
+	ret = rproc_tee_load_fw(rproc, fw);
+	if (ret)
+		return ret;
+
+	ret = rproc_tee_get_loaded_rsc_table(rproc, &rsc_table, &table_sz);
+	if (ret)
+		goto release_fw;
+
+	/*
+	 * We assume here that the memory mapping is the same between the TEE and Linux kernel
+	 * contexts. Else a new TEE remoteproc service could be needed to get a copy of the
+	 * resource table
+	 */
+	rsc_va = ioremap_wc(rsc_table, table_sz);
+	if (!rsc_va) {
+		dev_err(rproc_tee_ctx.dev, "Unable to map memory region: %pa+%zx\n",
+			&rsc_table, table_sz);
+		ret = -ENOMEM;
+		goto release_fw;
+	}
+
+	/*
+	 * Create a copy of the resource table to have the same behavior as the ELF loader.
+	 * This cached table will be used by the remoteproc core after the remoteproc stops
+	 * to free resources and for crash recovery to reapply the settings.
+	 * The cached table will be freed by the remoteproc core.
+	 */
+	rproc->cached_table = kmemdup((__force void *)rsc_va, table_sz, GFP_KERNEL);
+	iounmap(rsc_va);
+
+	if (!rproc->cached_table) {
+		ret = -ENOMEM;
+		goto release_fw;
+	}
+
+	rproc->table_ptr = rproc->cached_table;
+	rproc->table_sz = table_sz;
+
+	return 0;
+
+release_fw:
+	rproc_tee_release_fw(rproc);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_parse_fw);
+
+/**
+ * rproc_tee_find_loaded_rsc_table - Find the loaded resource table loaded by the TEE application
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * This function retrieves the physical address and size of the resource table loaded by the TEE
+ * application.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @fw: Pointer to the firmware structure containing the firmware data and size
+ *
+ * Return:  pointer to the resource table if found, or NULL if not found or size is 0
+ */
+struct resource_table *rproc_tee_find_loaded_rsc_table(struct rproc *rproc,
+						       const struct firmware *fw)
+{
+	phys_addr_t rsc_table;
+	size_t table_sz;
+	int ret;
+
+	ret = rproc_tee_get_loaded_rsc_table(rproc, &rsc_table, &table_sz);
+	if (ret)
+		return NULL;
+
+	rproc->table_sz = table_sz;
+	if (!table_sz)
+		return NULL;
+
+	/*
+	 * At this step the memory area that contains the resource table should have been registered
+	 * by the remote proc platform driver and allocated by rproc_alloc_registered_carveouts().
+	 */
+	return (struct resource_table *)rproc_pa_to_va(rproc, rsc_table, table_sz, NULL);
+}
+EXPORT_SYMBOL_GPL(rproc_tee_find_loaded_rsc_table);
+
+/**
+ * rproc_tee_start - Request the TEE application to start the remote processor
+ *
+ * This function invokes the TA_RPROC_FW_CMD_START command to start the remote processor.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ *
+ * Return: Returns 0 on success, -EINVAL or -EIO on failure
+ */
+int rproc_tee_start(struct rproc *rproc)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	struct tee_ioctl_invoke_arg arg;
+	int ret = 0;
+
+	if (!trproc)
+		return -EINVAL;
+
+	rproc_tee_prepare_args(trproc, TA_RPROC_FW_CMD_START, &arg, param, 0);
+
+	ret = tee_client_invoke_func(rproc_tee_ctx.tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(rproc_tee_ctx.dev,
+			"TA_RPROC_FW_CMD_START invoke failed TEE err: %#x, ret:%d\n", arg.ret, ret);
+		if (!ret)
+			return  -EIO;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_start);
+
+/**
+ * rproc_tee_stop - Request the TEE application to start the remote processor
+ *
+ * This function invokes the TA_RPROC_FW_CMD_STOP command to stop the remote processor.
+ *
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ *
+ * Return: Returns 0 on success, -EINVAL or -EIO on failure
+ */
+int rproc_tee_stop(struct rproc *rproc)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	struct tee_ioctl_invoke_arg arg;
+	int ret;
+
+	if (!trproc)
+		return -EINVAL;
+
+	rproc_tee_prepare_args(trproc, TA_RPROC_FW_CMD_STOP, &arg, param, 0);
+
+	ret = tee_client_invoke_func(rproc_tee_ctx.tee_ctx, &arg, param);
+	if (ret < 0 || arg.ret != 0) {
+		dev_err(rproc_tee_ctx.dev,
+			"TA_RPROC_FW_CMD_STOP invoke failed TEE err: %#x, ret:%d\n", arg.ret, ret);
+		if (!ret)
+			ret = -EIO;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_stop);
+
+static const struct tee_client_device_id rproc_tee_id_table[] = {
+	{UUID_INIT(0x80a4c275, 0x0a47, 0x4905, 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08)},
+	{}
+};
+
+/**
+ * rproc_tee_register - Register a remote processor controlled by a TEE application.
+ *
+ * This function registers a remote processor that will be managed by a TEE application,by opening
+ * a session with the TEE client.
+ *
+ * @dev: Pointer to client rproc device
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ * @rproc_id: ID of the remote processor
+ *
+ * Return: Returns 0 on success, or an error code on failure
+ */
+int rproc_tee_register(struct device *dev, struct rproc *rproc, unsigned int rproc_id)
+{
+	struct tee_param param[MAX_TEE_PARAM_ARRAY_MEMBER];
+	struct tee_ioctl_open_session_arg sess_arg;
+	struct tee_client_device *tee_device;
+	struct rproc_tee *trproc;
+	struct device_link *link;
+	int ret;
+
+	spin_lock(&ctx_lock);
+	/*
+	 * Test if the device has been probed by the TEE bus. In case of failure, we ignore the
+	 * reason. The bus could be not yet probed or the service not available in the secure
+	 * firmware.The assumption in such a case is that the TEE remoteproc is not probed.
+	 */
+	if (!rproc_tee_ctx.dev) {
+		ret =  -EPROBE_DEFER;
+		goto out;
+	}
+
+	trproc =  kzalloc(sizeof(*trproc), GFP_KERNEL);
+	if (!trproc) {
+		ret =  -ENOMEM;
+		goto out;
+	}
+
+	tee_device = to_tee_client_device(rproc_tee_ctx.dev);
+	memset(&sess_arg, 0, sizeof(sess_arg));
+
+	memcpy(sess_arg.uuid, tee_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
+
+	sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
+	sess_arg.num_params = 1;
+
+	param[0] = (struct tee_param) {
+		.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
+		.u.value.a = rproc_id,
+	};
+
+	ret = tee_client_open_session(rproc_tee_ctx.tee_ctx, &sess_arg, param);
+	if (ret < 0 || sess_arg.ret != 0) {
+		dev_err(dev, "tee_client_open_session failed, err: %#x\n", sess_arg.ret);
+		ret = -EINVAL;
+		goto free_tproc;
+	}
+
+	trproc->rproc_id = rproc_id;
+	trproc->session_id = sess_arg.session;
+
+	trproc->rproc = rproc;
+
+	/* Create device link between the rproc device and the TEE device */
+	link = device_link_add(dev, rproc_tee_ctx.dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+	if (!link) {
+		ret = -ENOMEM;
+		goto close_tee;
+	}
+	list_add_tail(&trproc->node, &rproc_tee_ctx.sessions);
+
+	goto out;
+
+close_tee:
+	if (tee_client_close_session(rproc_tee_ctx.tee_ctx, trproc->session_id))
+		dev_err(rproc_tee_ctx.dev, "tee_client_close_session failed\n");
+free_tproc:
+	kfree(trproc);
+out:
+	spin_unlock(&ctx_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_register);
+
+/**
+ * rproc_tee_unregister - Register a remote processor controlled by a TEE application.
+ *
+ * This function unregisters a remote processor previously registered by the rproc_tee_register()
+ * function.
+ *
+ * @dev: Pointer to client rproc device
+ * @rproc: Pointer to the struct rproc representing the remote processor
+ *
+ * Return: Returns 0 on success, or an error code on failure
+ */
+int rproc_tee_unregister(struct device *dev, struct rproc *rproc)
+{
+	struct rproc_tee *trproc = rproc_to_trproc(rproc);
+	int ret;
+
+	if (!trproc)
+		return -EINVAL;
+
+	spin_lock(&ctx_lock);
+
+	ret = tee_client_close_session(rproc_tee_ctx.tee_ctx, trproc->session_id);
+	if (ret < 0)
+		dev_err(rproc_tee_ctx.dev, "tee_client_close_session failed, err: %#x\n", ret);
+
+	spin_unlock(&ctx_lock);
+
+	list_del(&trproc->node);
+	kfree(trproc);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_tee_unregister);
+
+static int rproc_tee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+	/* Today we support only the OP-TEE, could be extend to other tees */
+	return (ver->impl_id == TEE_IMPL_ID_OPTEE);
+}
+
+static int rproc_tee_probe(struct device *dev)
+{
+	struct tee_context *tee_ctx;
+
+	/* Open context with TEE driver */
+	tee_ctx = tee_client_open_context(NULL, rproc_tee_ctx_match, NULL, NULL);
+	if (IS_ERR(tee_ctx))
+		return PTR_ERR(tee_ctx);
+
+	spin_lock(&ctx_lock);
+	rproc_tee_ctx.dev = dev;
+	rproc_tee_ctx.tee_ctx = tee_ctx;
+	INIT_LIST_HEAD(&rproc_tee_ctx.sessions);
+	spin_unlock(&ctx_lock);
+
+	return 0;
+}
+
+static int rproc_tee_remove(struct device *dev)
+{
+	spin_lock(&ctx_lock);
+	tee_client_close_context(rproc_tee_ctx.tee_ctx);
+	rproc_tee_ctx.dev = NULL;
+	rproc_tee_ctx.tee_ctx = NULL;
+	spin_unlock(&ctx_lock);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(tee, rproc_tee_id_table);
+
+static struct tee_client_driver rproc_tee_fw_driver = {
+	.id_table	= rproc_tee_id_table,
+	.driver		= {
+		.name		= KBUILD_MODNAME,
+		.bus		= &tee_bus_type,
+		.probe		= rproc_tee_probe,
+		.remove		= rproc_tee_remove,
+	},
+};
+
+static int __init rproc_tee_fw_mod_init(void)
+{
+	return driver_register(&rproc_tee_fw_driver.driver);
+}
+
+static void __exit rproc_tee_fw_mod_exit(void)
+{
+	driver_unregister(&rproc_tee_fw_driver.driver);
+}
+
+module_init(rproc_tee_fw_mod_init);
+module_exit(rproc_tee_fw_mod_exit);
+
+MODULE_DESCRIPTION(" remote processor TEE module");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/remoteproc_tee.h b/include/linux/remoteproc_tee.h
new file mode 100644
index 000000000000..659bd77a4f12
--- /dev/null
+++ b/include/linux/remoteproc_tee.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright(c) 2024 STMicroelectronics
+ */
+
+#ifndef REMOTEPROC_TEE_H
+#define REMOTEPROC_TEE_H
+
+#include <linux/tee_drv.h>
+#include <linux/firmware.h>
+#include <linux/remoteproc.h>
+
+struct rproc;
+struct rproc_tee;
+
+#if IS_ENABLED(CONFIG_REMOTEPROC_TEE)
+
+int rproc_tee_register(struct device *dev, struct rproc *rproc, unsigned int rproc_id);
+int rproc_tee_unregister(struct device *dev, struct rproc *rproc);
+int rproc_tee_parse_fw(struct rproc *rproc, const struct firmware *fw);
+int rproc_tee_load_fw(struct rproc *rproc, const struct firmware *fw);
+void rproc_tee_release_fw(struct rproc *rproc);
+struct resource_table *rproc_tee_find_loaded_rsc_table(struct rproc *rproc,
+						       const struct firmware *fw);
+int rproc_tee_start(struct rproc *rproc);
+int rproc_tee_stop(struct rproc *rproc);
+
+#else
+
+static inline int rproc_tee_register(struct device *dev, struct rproc *rproc, unsigned int rproc_id)
+{
+	return -ENODEV;
+}
+
+static inline int rproc_tee_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return 0;
+}
+
+static inline int rproc_tee_unregister(struct device *dev, struct rproc *rproc)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return 0;
+}
+
+static inline int rproc_tee_load_fw(struct rproc *rproc,  const struct firmware *fw)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return 0;
+}
+
+static inline int rproc_tee_start(struct rproc *rproc)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return 0;
+}
+
+static inline int rproc_tee_stop(struct rproc *rproc)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return 0;
+}
+
+static inline void rproc_tee_release_fw(struct rproc *rproc)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+}
+
+static inline struct resource_table *
+rproc_tee_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return NULL;
+}
+#endif /* CONFIG_REMOTEPROC_TEE */
+#endif /* REMOTEPROC_TEE_H */
-- 
2.25.1



From andre.draszik at linaro.org  Tue Mar 25 03:15:16 2025
From: andre.draszik at linaro.org (=?ISO-8859-1?Q?Andr=E9?= Draszik)
Date: Tue, 25 Mar 2025 10:15:16 +0000
Subject: [PATCH v3 0/2] firmware: exynos-acpm: allow use during system
 shutdown
In-Reply-To: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
References: <20250325-acpm-atomic-v3-0-c66aae7df925@linaro.org>
Message-ID: <48c082ffbb6eaa75eacbf3c7cbf0e4caec441bfc.camel@linaro.org>

On Tue, 2025-03-25 at 09:46 +0000, Andr? Draszik wrote:
> One user of this ACPM driver is a PMIC driver that needs to communicate
> with the PMIC during late system shutdown [1] and at that time we are
> not allowed to sleep anymore.
> 
> This series address this by switching the code to using udelay() in the
> specific case of system shutdown. This approach was inspired by I2C's
> i2c_in_atomic_xfer_mode(), which has to deal with a similar corner
> case.

Looks like I forgot to update the paragraph here. As of v3, we
now use udelay() unconditionally, instead of the fragile approach
inspired by I2C, as suggested by Krzysztof.

A.

> 
> Link: https://lore.kernel.org/all/20250323-s2mpg10-v1-29-d08943702707 at linaro.org/?[1]
> 
> Signed-off-by: Andr? Draszik <andre.draszik at linaro.org>
> ---
> Changes in v3:
> - switch to unconditional udelay() (Krzysztof)
> - Link to v2: https://lore.kernel.org/r/20250324-acpm-atomic-v2-0-7d87746e1765 at linaro.org
> 
> Changes in v2:
> - add missing ktime.h include
> - switch to ktime_before() instead of !ktime_after()
> - add link to user requiring this change to cover letter
> - collect Tudor's Rb
> - Link to v1: https://lore.kernel.org/r/20250321-acpm-atomic-v1-0-fb887bde7e61 at linaro.org
> 
> ---
> Andr? Draszik (2):
> ????? firmware: exynos-acpm: use ktime APIs for timeout detection
> ????? firmware: exynos-acpm: allow use during system shutdown
> 
> ?drivers/firmware/samsung/exynos-acpm.c | 16 ++++++++--------
> ?1 file changed, 8 insertions(+), 8 deletions(-)
> ---
> base-commit: 9388ec571cb1adba59d1cded2300eeb11827679c
> change-id: 20250321-acpm-atomic-033775b051ef
> 
> Best regards,



From krzk at kernel.org  Tue Mar 25 03:18:41 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 25 Mar 2025 11:18:41 +0100
Subject: [PATCH v16 1/3] dt-bindings: i2c: aspeed: support for
 AST2600-i2cv2
In-Reply-To: <OS8PR06MB7541FD8691B43EA33BDC1D22F2A72@OS8PR06MB7541.apcprd06.prod.outlook.com>
References: <20250224055936.1804279-1-ryan_chen@aspeedtech.com>
 <50327725-f3b8-4a8b-94a2-85afccd2868a@kernel.org>
 <OS8PR06MB7541B0DBC64B3EF6838DFE74F2CD2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <d1b184c5-84c1-4d76-a1d0-a9f37f1e363c@kernel.org>
 <OS8PR06MB7541D1D2E16C5E77037F3BB0F2CB2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <069b9fe4-c54a-4efd-923e-1558c59fe3f4@kernel.org>
 <OS8PR06MB7541C69AB8E6425313DA8606F2DF2@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <677cb075-24ae-45d8-bfb4-9b23fbacc5df@kernel.org>
 <OS8PR06MB7541C3B70B15F45F4824772BF2D92@OS8PR06MB7541.apcprd06.prod.outlook.com>
 <994cb954-f3c4-4a44-800e-9303787c1be9@kernel.org>
 <SI6PR06MB753542037E1D6BBF5CE8D2E7F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <4523caea-3406-4de0-9ab5-424fb7a0a474@kernel.org>
 <SI6PR06MB7535BAD19B51A381171A0E64F2A42@SI6PR06MB7535.apcprd06.prod.outlook.com>
 <8e8aa069-af9f-453f-9bd0-e3dc2eab59ab@kernel.org>
 <OS8PR06MB7541FD8691B43EA33BDC1D22F2A72@OS8PR06MB7541.apcprd06.prod.outlook.com>
Message-ID: <99053328-a117-493e-b5f3-00902669c8e7@kernel.org>

On 25/03/2025 10:52, Ryan Chen wrote:
>>
>>> i2c-aspeed.c for legacy layout, compatible "aspeed,ast2600-i2c-bus"
>>> i2c-ast2600.c for the new register set, compatible compatible
>> "aspeed,ast2600-i2cv2"
>>> Do you mean I have integrate into 1 driver at i2c-aspeed.c ? can't be
>> separate two driver?
>>
>> What is this patch about? Bindings. Not drivers. Look at email month ago:
>>
>> "All this describes driver, not hardware."
>>
>> Why are you keep bringing here drivers since a month?
> Let me try to rephrase the reasoning from a hardware point of view:
> 
> On AST2600, each I2C controller instance is functionally the same type of device (I2C controller), 
> but it can present two different and incompatible register layouts, 
> depending on a hardware-controlled configuration (via global register bits that are fixed in production SoCs).
> The layouts are not backward-compatible:
> Registers are at different offsets. Bit definitions differ.
> The programming sequence is not the same.
> Because of this incompatibility at the register level, software cannot handle both layouts in a generic way without explicit knowledge of which version is present.
> That?s why I proposed a new compatible string ? to represent a hardware-visible difference in register interface, even though the logical function (I2C controller) is the same.

You implied software is set in stone and that's not true. You have a
compatible which says to the software - this device has two programming
interfaces, choose whatever you wish and work with that.

Different compatible would mean the device is different, it changes or
you have compatibility issues.

NONE of these cases are here.

I am done with this topic, because explaining this and other
trivialities to Aspeed takes way too much time, so last opinion:

Your compatible already expressed that there are two interfaces, so your
drivers can just choose whichever they want. If you need to toggle a bit
in system controller, it is fine. If you need different compatible, then
that's a NAK.

Best regards,
Krzysztof


From angelogioacchino.delregno at collabora.com  Tue Mar 25 03:20:48 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 11:20:48 +0100
Subject: [PATCH 1/2] dt-bindings: mmc: mtk-sd: add single burst switch
In-Reply-To: <52d2f247a3058b96625bcdf5ab370282dfc9fb0e.camel@mediatek.com>
References: <20250306085028.5024-1-axe.yang@mediatek.com>
 <20250306085028.5024-2-axe.yang@mediatek.com>
 <3e84fda8-2566-4f18-8ef9-850c84789c34@collabora.com>
 <f84800fac589429157cd84034ef2f4541d3486a7.camel@mediatek.com>
 <b09f618a-eaf9-4258-ae2d-67eff1cb249f@collabora.com>
 <f8ce830d831aaba0d2748d31f8ba4a9915b7a14e.camel@mediatek.com>
 <52d2f247a3058b96625bcdf5ab370282dfc9fb0e.camel@mediatek.com>
Message-ID: <3572d6e2-8950-4937-bed5-624bf5bde7f3@collabora.com>

Il 25/03/25 03:41, Axe Yang (??) ha scritto:
> Hi Angelo,
> 
> Any comment on this :D
> 

Check inline reply below....

> Regards,
> Axe
> 
> On Wed, 2025-03-12 at 14:30 +0800, axe.yang wrote:
>> On Tue, 2025-03-11 at 10:47 +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 07/03/25 07:59, Axe Yang (??) ha scritto:
>>>> On Thu, 2025-03-06 at 10:19 +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 06/03/25 09:48, Axe Yang ha scritto:
>>>>>> Add 'mediatek,disable-single-burst' setting. This property
>>>>>> can
>>>>>> be
>>>>>> used to switch bus burst type, from single burst to INCR,
>>>>>> which
>>>>>> is
>>>>>> determined by the bus type within the IP. Some versions of
>>>>>> the
>>>>>> IP
>>>>>> are using AXI bus, thus this switch is necessary as 'single'
>>>>>> is
>>>>>> not
>>>>>> the burst type supported by the bus.
>>>>>>
>>>>>> Signed-off-by: Axe Yang <axe.yang at mediatek.com>
>>>>>
>>>>> I am mostly sure that this is not something to put in
>>>>> devicetree,
>>>>> but
>>>>> as
>>>>> platform data for specific SoC(s), as much as I'm mostly sure
>>>>> that
>>>>> all of
>>>>> the instances of the MSDC IP in one SoC will be *all* using
>>>>> either
>>>>> single
>>>>> or INCR.
>>>>
>>>> No, actually MSDC IPs in one SoC are using different versions.
>>>> Usually MSDC1 (index from 1) is used as eMMC host, the left hosts
>>>> are
>>>> used as SD/SDIO hosts. They have similar designs, but there are
>>>> still
>>>> difference.
>>>>
>>>>>
>>>>> So, I think I know the answer but I'll still ask just to be
>>>>> extremely
>>>>> sure:
>>>>>
>>>>> is there any MediaTek SoC that has different IP versions for
>>>>> different MSDC
>>>>> instances, and that hence require single burst on one instance
>>>>> and
>>>>> INCR on
>>>>> another instance?
>>>>
>>>> Yes. Actually every SoC has different IP versions for eMMC and
>>>> SD/SDIO
>>>> host as I said.
>>>> e.g. For MT8168, signel burst bit should be set to 1 for eMMC
>>>> Host,
>>>> but
>>>> 0 for SD/SDIO Host.
>>>>
>>>>>
>>>>> And if there is - is there a pattern? Is it always SDIO
>>>>> requiring
>>>>> INCR or
>>>>> always eMMC/SD requiring it?
>>>>>
>>>>>
>>>>
>>>> No, there is no pattern. Both eMMC and SD/SDIO hosts need to be
>>>> configured base on IP version. There is no binding relationship
>>>> between
>>>> eMMC/SD/SDIO and the burst type. eMMC burst type might be INCR or
>>>> single, same as SD/SDIO.
>>>>
>>>
>>> Okay but if there are different IP versions, and AXI/AHB is
>>> determined
>>> by the IP version, why aren't you parsing the MAIN_VER/ECO_VER
>>> registers of
>>> the MSDC IP to check whether to use INCR or SINGLE?
>>
>>
>> To address your concerns, I had further discussions with the
>> designer.
>> Their response was that the bus type and IP version are not bound
>> together. This contradicts my previous statements, and I apologize
>> for
>> that.
>> According to the designer's feedback, I must say that the single
>> burst
>> setting is indeed tied to the IC, but the granularity is such that it
>> needs to be set individually for each host.
>> Given the large number of ICs Mediatek currently has, adding burst
>> type
>> information for each host to the driver's compatible structure would
>> mean adding hundreds(maybe thousands :() of lines to the driver for
>> the
>> compatible structures for *all previous SoCs* (currently there are
>> only
>> 13 compatible structures, and they can be reuse by new SoC). This
>> approach seems very cumbersome.
>>
>> So I still believe that placing this setting in the DTS is a more
>> appropriate approach.
>>

Hello Axe,

sorry for the wait - this email fell through the cracks and I didn't see
it at all, so thank you for the ping.

Unfortunately, I don't think that this would be acceptable from a devicetree and/or
bindings standpoint, but then you don't really need to modify the pdata for all of
the currently supported SoCs to declare false, as false==0, which is the default.

But maybe there's another way out of this.

You said that this modification is done because some controllers are under AXI and
some others are under AHB... I was doing some cleanups to this driver and doing so
made me check a couple of things....

When a MSDC controller is under AXI, there will be configuration for that in other
registers - specifically, I'm wondering if the EMMC50_CFG2 register can be used to
check if we are under an AHB to AXI wrapper or not.

The idea is to read this register (offset 0x21c), [27:24] AXI_SET_LEN contains the
number of beats per burst (from 1 to 16), and also [23:19] AXI_RX_OUTSTANDING_NUM
contains the number of outstanding transfers (1 to 13).

If a controller does not have an AXI2AHB Wrapper, or if it does not use the AXI bus
this register should read zero I think?

Especially the two fields that I mentioned before, those should read zero.

That, especially because the hwaddr for the controllers is anyway and always long
0x1000 - and I think that the extra registers space, on controllers that don't have
the EMMC50 registers (msdc1 and msdc2) should be still reserved to those and never
used for anything else.

Would that detection way work?

If it would, we'd be again autodetecting whether to set or not the AXI single burst
option in the patch bits...without relying on specifying anything manually, not in
the devicetree, and not in the platform data :-)

Cheers,
Angelo

>> Regards,
>> Axe
>>
>>>
>>> Cheers,
>>> Angelo
>>>
>>>>
>>>> Regards,
>>>> Axe
>>>>
>>>>
>>>>>
>>>>>> ---
>>>>>>     Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 8
>>>>>> ++++++++
>>>>>>     1 file changed, 8 insertions(+)
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/mmc/mtk-
>>>>>> sd.yaml
>>>>>> b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>>>>> index 0debccbd6519..6076aff0a689 100644
>>>>>> --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>>>>> +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
>>>>>> @@ -100,6 +100,14 @@ properties:
>>>>>>         minimum: 0
>>>>>>         maximum: 0xffffffff
>>>>>>
>>>>>> +  mediatek,disable-single-burst:
>>>>>> +    $ref: /schemas/types.yaml#/definitions/flag
>>>>>> +    description:
>>>>>> +      Burst type setting. For some versions of the IP that
>>>>>> do
>>>>>> not
>>>>>> use
>>>>>> +      AHB bus, the burst type need to be switched to INCR.
>>>>>> +      If present, use INCR burst type.
>>>>>> +      If not present, use single burst type.
>>>>>> +
>>>>>>       mediatek,hs200-cmd-int-delay:
>>>>>>         $ref: /schemas/types.yaml#/definitions/uint32
>>>>>>         description:
>>>>>
>>>>>
>>>>>
>>>
>>>




From maz at kernel.org  Tue Mar 25 03:26:10 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:10 +0000
Subject: [PATCH v2 13/13] PCI: apple: Add T602x PCIe support
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-14-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

This version of the hardware moved around a bunch of registers, so we
avoid the old compatible for these and introduce register offset
structures to handle the differences.

Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 847cba753d28d..5b85d9497070c 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -124,6 +124,13 @@
 #define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1)
 #define PORT_PREFMEM_ENABLE		0x00994
 
+/* T602x (M2-pro and co) */
+#define PORT_T602X_MSIADDR	0x016c
+#define PORT_T602X_MSIADDR_HI	0x0170
+#define PORT_T602X_PERST	0x082c
+#define PORT_T602X_RID2SID	0x3000
+#define PORT_T602X_MSIMAP	0x3800
+
 #define PORT_MSIMAP_ENABLE	BIT(31)
 #define PORT_MSIMAP_TARGET	GENMASK(7, 0)
 
@@ -158,6 +165,18 @@ static const struct hw_info t8103_hw = {
 	.max_rid2sid		= 64,
 };
 
+static const struct hw_info t602x_hw = {
+	.phy_lane_ctl		= 0,
+	.port_msiaddr		= PORT_T602X_MSIADDR,
+	.port_msiaddr_hi	= PORT_T602X_MSIADDR_HI,
+	.port_refclk		= 0,
+	.port_perst		= PORT_T602X_PERST,
+	.port_rid2sid		= PORT_T602X_RID2SID,
+	.port_msimap		= PORT_T602X_MSIMAP,
+	/* 16 on t602x, guess for autodetect on future HW */
+	.max_rid2sid		= 512,
+};
+
 struct apple_pcie {
 	struct mutex		lock;
 	struct device		*dev;
@@ -425,6 +444,7 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
 	/* Disable all interrupts */
 	writel_relaxed(~0, port->base + PORT_INTMSK);
 	writel_relaxed(~0, port->base + PORT_INTSTAT);
+	writel_relaxed(~0, port->base + PORT_LINKCMDSTS);
 
 	irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port);
 
@@ -865,6 +885,7 @@ static int apple_pcie_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id apple_pcie_of_match[] = {
+	{ .compatible = "apple,t6020-pcie",	.data = &t602x_hw },
 	{ .compatible = "apple,pcie",		.data = &t8103_hw },
 	{ }
 };
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:07 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:07 +0000
Subject: [PATCH v2 10/13] PCI: apple: Drop poll for CORE_RC_PHYIF_STAT_REFCLK
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-11-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

This is checking a core refclk in per-port setup which doesn't make a
lot of sense, and the bootloader needs to have gone through this anyway.

It doesn't work on T602x, so just drop it across the board.

Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 94c49611b74df..c00ec0781fabc 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -475,12 +475,6 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
 	u32 stat;
 	int res;
 
-	res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat,
-					 stat & CORE_RC_PHYIF_STAT_REFCLK,
-					 100, 50000);
-	if (res < 0)
-		return res;
-
 	rmw_set(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
 	rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
 
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:05 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:05 +0000
Subject: [PATCH v2 08/13] PCI: apple: Set only available ports up
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-9-maz@kernel.org>

From: Janne Grunau <j at jannau.net>

Iterating over disabled ports results in of_irq_parse_raw() parsing
the wrong "interrupt-map" entries, as it takes the status of the node
into account.

Switching from for_each_child_of_node() to for_each_available_child_of_node()
solves this issue.

This became apparent after disabling unused PCIe ports in the Apple
Silicon device trees instead of deleting them.

Link: https://lore.kernel.org/asahi/20230214-apple_dts_pcie_disable_unused-v1-0-5ea0d3ddcde3 at jannau.net/
Link: https://lore.kernel.org/asahi/1ea2107a-bb86-8c22-0bbc-82c453ab08ce at linaro.org/
Fixes: 1e33888fbe44 ("PCI: apple: Add initial hardware bring-up")
Cc: stable at vger.kernel.org
Signed-off-by: Janne Grunau <j at jannau.net>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 6271533f1b042..23d9f62bd2ad4 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -747,7 +747,7 @@ static int apple_pcie_init(struct pci_config_window *cfg)
 	struct device_node *of_port;
 	int ret;
 
-	for_each_child_of_node(dev->of_node, of_port) {
+	for_each_available_child_of_node(dev->of_node, of_port) {
 		ret = apple_pcie_setup_port(pcie, of_port);
 		if (ret) {
 			dev_err(dev, "Port %pOF setup fail: %d\n", of_port, ret);
-- 
2.39.2



From mark.kettenis at xs4all.nl  Tue Mar 25 03:50:18 2025
From: mark.kettenis at xs4all.nl (Mark Kettenis)
Date: Tue, 25 Mar 2025 11:50:18 +0100
Subject: [PATCH v2 01/13] dt-bindings: pci: apple,pcie: Add t6020 compatible string
In-Reply-To: <20250325102610.2073863-2-maz@kernel.org> (message from Marc
	Zyngier on Tue, 25 Mar 2025 10:25:58 +0000)
References: <20250325102610.2073863-1-maz@kernel.org> <20250325102610.2073863-2-maz@kernel.org>
Message-ID: <87iknx75at.fsf@bloch.sibelius.xs4all.nl>

> From: Marc Zyngier <maz at kernel.org>
> Date: Tue, 25 Mar 2025 10:25:58 +0000

Hi Marc,

Sorry for not spotting this in the earlier versions, but:

> From: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> 
> t6020 adds some register ranges compared to t8103, so requires
> a new compatible as well as the new PHY registers themselves.
> 
> Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> [maz: added PHY registers]
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  Documentation/devicetree/bindings/pci/apple,pcie.yaml | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/apple,pcie.yaml b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> index c8775f9cb0713..77554899b9420 100644
> --- a/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> @@ -17,6 +17,10 @@ description: |
>    implements its root ports.  But the ATU found on most DesignWare
>    PCIe host bridges is absent.
>  
> +  On systems derived from T602x, the PHY registers are in a region
> +  separate from the port registers. In that case, there is one PHY
> +  register range per port register range.
> +
>    All root ports share a single ECAM space, but separate GPIOs are
>    used to take the PCI devices on those ports out of reset.  Therefore
>    the standard "reset-gpios" and "max-link-speed" properties appear on
> @@ -35,11 +39,12 @@ properties:
>            - apple,t8103-pcie
>            - apple,t8112-pcie
>            - apple,t6000-pcie
> +          - apple,t6020-pcie
>        - const: apple,pcie

Since the T602x PCIe controller has a different register layout, it
isn't compatible with the others, so it should not include the
"apple,pcie" compatible.  The "downstream" device trees for
T602x-based devices do indeed not list "apple,pcie" as a compatible.
So I think this needs to be written as:

  compatible:
    oneOf:
      - items:
          - enum:
              - apple,t8103-pcie
              - apple,t8112-pcie
              - apple,t6000-pcie
          - const: apple,pcie
      - const: apple,t6020-pcie

>  
>    reg:
>      minItems: 3
> -    maxItems: 6
> +    maxItems: 10
>  
>    reg-names:
>      minItems: 3
> @@ -50,6 +55,10 @@ properties:
>        - const: port1
>        - const: port2
>        - const: port3
> +      - const: phy0
> +      - const: phy1
> +      - const: phy2
> +      - const: phy3
>  
>    ranges:
>      minItems: 2
> -- 
> 2.39.2
> 
> 
> 


From maz at kernel.org  Tue Mar 25 03:52:10 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:52:10 +0000
Subject: [PATCH v5 5/6] arm64: dts: cix: add initial CIX P1(SKY1) dts support
In-Reply-To: <20250324062420.360289-6-peter.chen@cixtech.com>
References: <20250324062420.360289-1-peter.chen@cixtech.com>
	<20250324062420.360289-6-peter.chen@cixtech.com>
Message-ID: <865xjxmlgl.wl-maz@kernel.org>

On Mon, 24 Mar 2025 06:24:19 +0000,
Peter Chen <peter.chen at cixtech.com> wrote:
> 
> CIX SKY1 SoC is high performance Armv9 SoC designed by Cixtech,
> and Orion O6 is open source motherboard launched by Radxa.
> See below for detail:
> https://docs.radxa.com/en/orion/o6/getting-started/introduction
> 
> In this commit, it only adds limited components for running initramfs
> at Orion O6.
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
> Acked-by: Fugang Duan <fugang.duan at cixtech.com>
> Signed-off-by: Peter Chen <peter.chen at cixtech.com>
> ---
> Changes for v5:
> - Delete pmu-spe node which need to refine, and add it in future
> 
> Changes for v4:
> - Add ppi-partition entry for gic-v3 node, and let pmu-a520 and pmu-a720's interrupt entry
> get its handle
> - Remove gic-v3's #redistributor-regions and redistributor-stride properties
> - Change gic-v3's #interrupt-cells as 4, and change all interrupt specifiers accordingly
> - Remove "arm,no-tick-in-suspend" for timer due to global counter is at always-on power domain
> - Remove timer's clock frequency due to firmware has already set it
> - Add Krzysztof Kozlowski's reviewed-by
> 
> Changes for v3:
> - Fix two dts coding sytle issues 
> 
> Changes for v2:
> - Corrects the SoF tag's name
> - Fix several coding sytle issues
> - move linux,cma node to dts file
> - delete memory node, memory size is passed by firmware
> - delete uart2 node which will be added in future patches
> - Improve for pmu and cpu node to stands for more specific cpu model
> - Improve the timer node and add hypervisor virtual timer irq
> - Pass "make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb"
> 
>  arch/arm64/boot/dts/Makefile              |   1 +
>  arch/arm64/boot/dts/cix/Makefile          |   2 +
>  arch/arm64/boot/dts/cix/sky1-orion-o6.dts |  26 +++
>  arch/arm64/boot/dts/cix/sky1.dtsi         | 217 ++++++++++++++++++++++
>  4 files changed, 246 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/cix/Makefile
>  create mode 100644 arch/arm64/boot/dts/cix/sky1-orion-o6.dts
>  create mode 100644 arch/arm64/boot/dts/cix/sky1.dtsi
> 
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index 79b73a21ddc2..8e7ccd0027bd 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -13,6 +13,7 @@ subdir-y += bitmain
>  subdir-y += blaize
>  subdir-y += broadcom
>  subdir-y += cavium
> +subdir-y += cix
>  subdir-y += exynos
>  subdir-y += freescale
>  subdir-y += hisilicon
> diff --git a/arch/arm64/boot/dts/cix/Makefile b/arch/arm64/boot/dts/cix/Makefile
> new file mode 100644
> index 000000000000..ed3713982012
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cix/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +dtb-$(CONFIG_ARCH_CIX) += sky1-orion-o6.dtb
> diff --git a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> new file mode 100644
> index 000000000000..78f4fcd87216
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: BSD-3-Clause
> +/*
> + * Copyright 2025 Cix Technology Group Co., Ltd.
> + *
> + */
> +
> +/dts-v1/;
> +
> +#include "sky1.dtsi"
> +/ {
> +	model = "Radxa Orion O6";
> +	compatible = "radxa,orion-o6", "cix,sky1";
> +
> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		linux,cma {
> +			compatible = "shared-dma-pool";
> +			reusable;
> +			size = <0x0 0x28000000>;
> +			linux,cma-default;
> +		};
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
> new file mode 100644
> index 000000000000..5bfeeea454e0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cix/sky1.dtsi
> @@ -0,0 +1,217 @@
> +// SPDX-License-Identifier: BSD-3-Clause
> +/*
> + * Copyright 2025 Cix Technology Group Co., Ltd.
> + *
> + */
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +/ {
> +	interrupt-parent = <&gic>;
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +
> +	cpus {
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu at 0 {
> +			compatible = "arm,cortex-a520";
> +			enable-method = "psci";
> +			reg = <0x0 0x0>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <403>;
> +		};
> +
> +		cpu1: cpu at 100 {
> +			compatible = "arm,cortex-a520";
> +			enable-method = "psci";
> +			reg = <0x0 0x100>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <403>;
> +		};
> +
> +		cpu2: cpu at 200 {
> +			compatible = "arm,cortex-a520";
> +			enable-method = "psci";
> +			reg = <0x0 0x200>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <403>;
> +		};
> +
> +		cpu3: cpu at 300 {
> +			compatible = "arm,cortex-a520";
> +			enable-method = "psci";
> +			reg = <0x0 0x300>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <403>;
> +		};
> +
> +		cpu4: cpu at 400 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x400>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu5: cpu at 500 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x500>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu6: cpu at 600 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x600>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu7: cpu at 700 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x700>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu8: cpu at 800 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x800>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu9: cpu at 900 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0x900>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu10: cpu at a00 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0xa00>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu11: cpu at b00 {
> +			compatible = "arm,cortex-a720";
> +			enable-method = "psci";
> +			reg = <0x0 0xb00>;
> +			device_type = "cpu";
> +			capacity-dmips-mhz = <1024>;
> +		};
> +
> +		cpu-map {
> +			cluster0 {
> +				core0 {
> +					cpu = <&cpu0>;
> +				};
> +				core1 {
> +					cpu = <&cpu1>;
> +				};
> +				core2 {
> +					cpu = <&cpu2>;
> +				};
> +				core3 {
> +					cpu = <&cpu3>;
> +				};
> +				core4 {
> +					cpu = <&cpu4>;
> +				};
> +				core5 {
> +					cpu = <&cpu5>;
> +				};
> +				core6 {
> +					cpu = <&cpu6>;
> +				};
> +				core7 {
> +					cpu = <&cpu7>;
> +				};
> +				core8 {
> +					cpu = <&cpu8>;
> +				};
> +				core9 {
> +					cpu = <&cpu9>;
> +				};
> +				core10 {
> +					cpu = <&cpu10>;
> +				};
> +				core11 {
> +					cpu = <&cpu11>;
> +				};
> +			};
> +		};
> +	};
> +
> +	pmu-a520 {
> +		compatible = "arm,cortex-a520-pmu";
> +		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition0>;
> +	};
> +
> +	pmu-a720 {
> +		compatible = "arm,cortex-a720-pmu";
> +		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_partition1>;
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-1.0";
> +		method = "smc";
> +	};
> +
> +	soc at 0 {
> +		compatible = "simple-bus";
> +		ranges = <0 0 0 0 0x20 0>;
> +		dma-ranges;
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +
> +		gic: interrupt-controller at e010000 {
> +			compatible = "arm,gic-v3";
> +			reg = <0x0 0x0e010000 0 0x10000>,	/* GICD */
> +			      <0x0 0x0e090000 0 0x300000>;       /* GICR * 12 */
> +			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW 0>;
> +			#interrupt-cells = <4>;
> +			interrupt-controller;
> +			#address-cells = <2>;
> +			#size-cells = <2>;
> +			ranges;
> +
> +			gic_its: msi-controller at e050000 {
> +				compatible = "arm,gic-v3-its";
> +				reg = <0x0 0x0e050000 0x0 0x30000>;
> +				msi-controller;
> +				#msi-cells = <1>;
> +			};
> +
> +			ppi-partitions {
> +				ppi_partition0: interrupt-partition-0 {
> +					affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
> +				};
> +
> +				ppi_partition1: interrupt-partition-1 {
> +					affinity = <&cpu4 &cpu5 &cpu6 &cpu7 &cpu8 &cpu9 &cpu10 &cpu11>;
> +				};
> +			};
> +		};
> +	};
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
> +		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
> +			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
> +			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
> +			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>,
> +			     <GIC_PPI 12 IRQ_TYPE_LEVEL_LOW 0>;
> +	};
> +};

I don't think there is anything wrong here, but it is also a pretty
useless DT. There isn't even a UART to interact with the machine and
find out whether it has actually booted.

I reckon this should be part of the initial DT, as this otherwise
serves little purpose.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From daniel.lezcano at linaro.org  Tue Mar 25 03:53:20 2025
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 25 Mar 2025 11:53:20 +0100
Subject: [PATCH 2/2] clocksource/drivers/nxp-timer: Add the System Timer
 Module for the s32g platform
In-Reply-To: <d60fca36-0beb-2574-cb82-3969bbfb58a9@oss.nxp.com>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
 <20250324100008.346009-2-daniel.lezcano@linaro.org>
 <d60fca36-0beb-2574-cb82-3969bbfb58a9@oss.nxp.com>
Message-ID: <8c208e8c-2e1e-430c-916a-dbc6732881b0@linaro.org>


Hi Ghennadi,

thanks for the review


On 25/03/2025 08:28, Ghennadi Procopciuc wrote:

[ ... ]

>> +static int __init nxp_stm_clocksource_init(struct device *dev, const char *name,
>> +					   void __iomem *base, struct clk *clk)
>> +{
>> +	struct stm_timer *stm_timer;
>> +	int ret;
>> +
>> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
>> +	if (!stm_timer)
>> +		return -ENOMEM;
>> +
>> +	stm_timer->base = base;
>> +	stm_timer->rate = clk_get_rate(clk);
>> +
>> +	stm_timer->scs.cs.name = name;
>> +	stm_timer->scs.cs.rating = 460;
>> +	stm_timer->scs.cs.read = nxp_stm_clocksource_read;
>> +	stm_timer->scs.cs.enable = nxp_stm_clocksource_enable;
>> +	stm_timer->scs.cs.disable = nxp_stm_clocksource_disable;
>> +	stm_timer->scs.cs.suspend = nxp_stm_clocksource_suspend;
>> +	stm_timer->scs.cs.resume = nxp_stm_clocksource_resume;
>> +	stm_timer->scs.cs.mask = CLOCKSOURCE_MASK(32);
>> +	stm_timer->scs.cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
>> +
>> +	ret = clocksource_register_hz(&stm_timer->scs.cs, stm_timer->rate);
>> +	if (ret)
>> +		return ret;
> 
> clocksource_unregister during remove callback for cleanup?

Sorry I don't get it :/

There is no cleanup after the clocksource_register_hz() is successful

>> +
>> +	stm_sched_clock = stm_timer;
>> +
>> +	sched_clock_register(nxp_stm_read_sched_clock, 32, stm_timer->rate);
>> +
>> +	dev_set_drvdata(dev, stm_timer);
> 
> Is this used?

Nope, I'll remove it.

>> +
>> +	dev_dbg(dev, "Registered clocksource %s\n", name);
>> +
>> +	return 0;
>> +}

[ ... ]

>> +static int nxp_stm_clockevent_set_next_event(unsigned long delta, struct clock_event_device *ced)
>> +{
>> +	struct stm_timer *stm_timer = ced_to_stm(ced);
>> +	u32 val;
>> +
>> +	nxp_stm_clockevent_disable(stm_timer);
> 
> While examining the code base, I came across the
> drivers/clocksource/timer-imx-gpt.c file, specifically the
> mx1_2_set_next_event function, which includes a protection against
> missing events. Using a similar approach would allow us to keep the STM
> module enabled while only altering the channel's register state. This
> risk can also be mitigated by adjusting min_delta_ns based on tick
> frequency.

How would you validate that ?


>> +	stm_timer->sce.delta = delta;
>> +
>> +	val = nxp_stm_clockevent_read_counter(stm_timer) + delta;
>> +
>> +	writel(val, stm_timer->base + STM_CHANNEL(0) + STM_CMP);
>> +
>> +	nxp_stm_clockevent_enable(stm_timer);
>> +
>> +	return 0;
>> +}
>> +
>> +static int nxp_stm_clockevent_set_periodic(struct clock_event_device *ced)
>> +{
>> +	struct stm_timer *stm_timer = ced_to_stm(ced);
>> +
>> +        return nxp_stm_clockevent_set_next_event(stm_timer->rate, ced);
>> +}
>> +
>> +static int __init nxp_stm_clockevent_broadcast_init(struct device *dev, const char *name, void __iomem *base,
>> +						    int irq, struct clk *clk)
>> +{
>> +	struct stm_timer *stm_timer;
>> +	int ret;
>> +
>> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
>> +	if (!stm_timer)
>> +		return -ENOMEM;
>> +
>> +	stm_timer->base = base;
>> +	stm_timer->rate = clk_get_rate(clk);
>> +
>> +	stm_timer->sce.ced.name = name;
>> +	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
>> +	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
>> +	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
>> +	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
>> +	stm_timer->sce.ced.cpumask = cpu_possible_mask;
>> +	stm_timer->sce.ced.rating = 460;
>> +	stm_timer->sce.ced.irq = irq;
>> +
>> +	nxp_stm_clockevent_irq_clr(stm_timer);
>> +
>> +	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
>> +			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);
>> +	if (ret) {
>> +		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
>> +
>> +	dev_dbg(dev, "Registered broadcast clockevent %s irq=%d\n", name, irq);
>> +
>> +	return 0;
>> +}
>> +
>> +static int __init nxp_stm_clockevent_per_cpu_init(struct device *dev, const char *name, void __iomem *base,
>> +						  int irq, struct clk *clk, int cpu)
>> +{
> 
> This function duplicates a significant portion of the previous one. To
> avoid code duplication, it would be beneficial to extract the common
> part into a dedicated function.

Sure

>> +	struct stm_timer *stm_timer;
>> +	int ret;
>> +
>> +	stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
>> +	if (!stm_timer)
>> +		return -ENOMEM;
>> +
>> +	stm_timer->base = base;
>> +	stm_timer->rate = clk_get_rate(clk);
>> +
>> +	stm_timer->sce.ced.name = name;
>> +	stm_timer->sce.ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
>> +	stm_timer->sce.ced.set_state_shutdown = nxp_stm_clockevent_shutdown;
>> +	stm_timer->sce.ced.set_state_periodic = nxp_stm_clockevent_set_periodic;
>> +	stm_timer->sce.ced.set_next_event = nxp_stm_clockevent_set_next_event;
>> +	stm_timer->sce.ced.cpumask = cpumask_of(cpu);
>> +	stm_timer->sce.ced.rating = 460;
>> +	stm_timer->sce.ced.irq = irq;
>> +
>> +	nxp_stm_clockevent_irq_clr(stm_timer);
>> +
>> +	ret = request_irq(irq, nxp_stm_clockevent_interrupt,
>> +			  IRQF_TIMER | IRQF_NOBALANCING, name, &stm_timer->sce.ced);
> 
> devm_request_irq instead ?

Yes

>> +	if (ret) {
>> +		dev_err(dev, "Unable to allocate interrupt line: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	per_cpu(stm_timers, cpu) = stm_timer;
>> +
>> +	dev_dbg(dev, "Initialized per cpu clockevent name=%s, irq=%d, cpu=%d\n", name, irq, cpu);
>> +
>> +	return 0;
>> +}
>> +
>> +static int nxp_stm_clockevent_starting_cpu(unsigned int cpu)
>> +{
>> +	struct stm_timer *stm_timer = per_cpu(stm_timers, cpu);
>> +	int ret;
>> +
>> +	if (WARN_ON(!stm_timer))
>> +		return -EFAULT;
>> +
>> +	ret = irq_force_affinity(stm_timer->sce.ced.irq, cpumask_of(cpu));
>> +	if (ret)
>> +		return ret;
>> +
>> +	clockevents_config_and_register(&stm_timer->sce.ced, stm_timer->rate, 1, 0xffffffff);
>> +
>> +	return 0;
>> +}
>> +
>> +static int __init nxp_stm_timer_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct device_node *np = dev->of_node;
>> +	struct stm_instances *stm_instances;
>> +	const char *name = of_node_full_name(np);
>> +	void __iomem *base;
>> +	int irq, ret;
>> +	struct clk *clk;
>> +
>> +	stm_instances = (typeof(stm_instances))of_device_get_match_data(dev);
>> +	if (!stm_instances) {
>> +		dev_err(dev, "No STM instances associated with a cpu");
>> +		return -EINVAL;
>> +	}
>> +
>> +	base = devm_of_iomap(dev, np, 0, NULL);
>> +	if (IS_ERR(base)) {
>> +		dev_err(dev, "Failed to iomap %pOFn\n", np);
>> +		return PTR_ERR(base);
>> +	}
>> +
>> +	irq = irq_of_parse_and_map(np, 0);
>> +	if (irq <= 0) {
>> +		dev_err(dev, "Failed to parse and map IRQ: %d\n", irq);
>> +		return -EINVAL;
>> +	}
> 
>  From commit description:
> 
>> The first probed STM is used as a clocksource, the second will be the
>> broadcast timer and the rest are used as a clockevent with the
>> affinity set to a CPU.
> 
> Why is the interrupt mandatory when the node is probed as a clocksource?

It relies on the DT description and it does not hurt to have a 
consistent code path for clockevent / clocksource even if the interrupt 
is not requested for the clocksource later.

>> +
>> +	clk = devm_clk_get(dev, NULL);
>> +	if (IS_ERR(clk)) {
>> +		dev_err(dev, "Clock not found\n");
> 
> Missing irq_dispose_mapping ?

Yeah ...

>> +		return PTR_ERR(clk);
>> +	}
>> +
>> +	ret = clk_prepare_enable(clk);
>> +	if (ret) {
>> +		dev_err(dev, "Failed to enable STM timer clock: %d\n", ret);
>> +		return ret;
>> +	}
> 
> devm_clk_get_enabled instead of devm_clk_get + clk_prepare_enable ?

Yes, good point

>> +
>> +	if (!stm_instances->clocksource && (stm_instances->features & STM_CLKSRC)) {
>> +
>> +		/*
>> +		 * First probed STM will be a clocksource
>> +		 */
>> +		ret = nxp_stm_clocksource_init(dev, name, base, clk);
>> +		if (ret)
>> +			return ret;
>> +		stm_instances->clocksource++;
>> +
>> +	} else if (!stm_instances->clockevent_broadcast &&
>> +		   (stm_instances->features & STM_CLKEVT_BROADCAST)) {
>> +
>> +		/*
>> +		 * Second probed STM will be a broadcast clockevent
>> +		 */
>> +		ret = nxp_stm_clockevent_broadcast_init(dev, name, base, irq, clk);
>> +		if (ret)
>> +			return ret;
>> +		stm_instances->clockevent_broadcast++;
>> +
>> +	} else if (stm_instances->clockevent_per_cpu < num_possible_cpus() &&
>> +		   (stm_instances->features & STM_CLKEVT_PER_CPU)) {
>> +
>> +		/*
>> +		 * Next probed STM will be a per CPU clockevent, until
>> +		 * we probe as much as we have CPUs available on the
>> +		 * system, we do a partial initialization
>> +		 */
>> +		ret = nxp_stm_clockevent_per_cpu_init(dev, name, base, irq, clk,
>> +						      stm_instances->clockevent_per_cpu);
>> +		if (ret)
>> +			return ret;
>> +
>> +		stm_instances->clockevent_per_cpu++;
>> +
>> +		/*
>> +		 * The number of probed STM for per CPU clockevent is
>> +		 * equal to the number of available CPUs on the
>> +		 * system. We install the cpu hotplug to finish the
>> +		 * initialization by registering the clockevents
>> +		 */
>> +		if (stm_instances->clockevent_per_cpu == num_possible_cpus()) {
>> +			ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "STM timer:starting",
>> +						nxp_stm_clockevent_starting_cpu, NULL);
>> +			if (ret < 0)
>> +				return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static struct stm_instances s32g_stm_instances = { .features = STM_CLKSRC | STM_CLKEVT_PER_CPU };
>> +
>> +static const struct of_device_id nxp_stm_of_match[] = {
>> +	{ .compatible = "nxp,s32g2-stm", &s32g_stm_instances },
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
>> +
>> +static struct platform_driver nxp_stm_probe = {
>> +	.probe	= nxp_stm_timer_probe,
>> +	.driver	= {
>> +		.name = "nxp-stm",
>> +		.of_match_table = of_match_ptr(nxp_stm_of_match),
>> +	},
>> +};
>> +module_platform_driver(nxp_stm_probe);
>> +
>> +MODULE_DESCRIPTION("NXP System Timer Module driver");
>> +MODULE_LICENSE("GPL");
> 


-- 
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


From maz at kernel.org  Tue Mar 25 03:26:00 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:00 +0000
Subject: [PATCH v2 03/13] PCI: ecam: Allow cfg->priv to be pre-populated from the root port device
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-4-maz@kernel.org>

In order to decouple ecam config space creation from probing via
pci_host_common_probe(), allow the private pointer to be populated
via the device drvdata pointer.

Crucially, this is set before calling ops->init(), allowing that
particular callback to have access to probe data.

This should have no impact on existing code which ignores the
current value of cfg->priv.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/ecam.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index 260b7de2dbd57..2c5e6446e00ee 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -84,6 +84,8 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 			goto err_exit_iomap;
 	}
 
+	cfg->priv = dev_get_drvdata(dev);
+
 	if (ops->init) {
 		err = ops->init(cfg);
 		if (err)
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:25:57 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:25:57 +0000
Subject: [PATCH v2 00/13] PCI: apple: Add support for t6020
Message-ID: <20250325102610.2073863-1-maz@kernel.org>

As Alyssa didn't have the bandwidth to deal with this series, I have
taken it over. All bugs are therefore mine.

The initial series [1] stated:

"This series adds T6020 support to the Apple PCIe controller. Mostly
 Apple shuffled registers around (presumably to accommodate the larger
 configurations on those machines). So there's a bit of churn here but
 not too much in the way of functional changes."

The biggest change is affecting the ECAM layer, allowing an ECAM
driver to provide its own probe function instead of relying on the
.init() callback to do the work. The ECAM layer can therefore be used
as a library instead of a convoluted driver.

The rest is a mix of bug fixes, cleanups, and required abstraction.

This has been tested on T6020 (M2-Pro mini) and T8102 (M1 mini).

* From v1[1]:

  - Described the PHY registers in the DT binding

  - Extracted a ecam bridge creation helper from the host-common layer

  - Moved probing into its own function instead of pci_host_common_probe()
    
  - Moved host-specific data to the of_device_id[] table

  - Added dynamic allocation of the RID/SID bitmap

  - Fixed latent bug in RC-generated interrupts

  - Renamed reg_info to hw_info

  - Dropped useless max_msimap

  - Dropped code being moved around without justification

  - Re-split some of the patches to follow a more logical progression

  - General cleanup to fit my own taste

[1] https://lore.kernel.org/r/20250211-pcie-t6-v1-0-b60e6d2501bb at rosenzweig.io

Alyssa Rosenzweig (1):
  dt-bindings: pci: apple,pcie: Add t6020 compatible string

Hector Martin (6):
  PCI: apple: Fix missing OF node reference in apple_pcie_setup_port
  PCI: apple: Move port PHY registers to their own reg items
  PCI: apple: Drop poll for CORE_RC_PHYIF_STAT_REFCLK
  PCI: apple: Use gpiod_set_value_cansleep in probe flow
  PCI: apple: Abstract register offsets via a SoC-specific structure
  PCI: apple: Add T602x PCIe support

Janne Grunau (1):
  PCI: apple: Set only available ports up

Marc Zyngier (5):
  PCI: host-generic: Extract an ecam bridge creation helper from
    pci_host_common_probe()
  PCI: ecam: Allow cfg->priv to be pre-populated from the root port
    device
  PCI: apple: Move over to standalone probing
  PCI: apple: Dynamically allocate RID-to_SID bitmap
  PCI: apple: Move away from INTMSK{SET,CLR} for INTx and private
    interrupts

 .../devicetree/bindings/pci/apple,pcie.yaml   |  11 +-
 drivers/pci/controller/pci-host-common.c      |  24 +-
 drivers/pci/controller/pcie-apple.c           | 241 +++++++++++++-----
 drivers/pci/ecam.c                            |   2 +
 include/linux/pci-ecam.h                      |   2 +
 5 files changed, 204 insertions(+), 76 deletions(-)

-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:25:58 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:25:58 +0000
Subject: [PATCH v2 01/13] dt-bindings: pci: apple,pcie: Add t6020 compatible string
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-2-maz@kernel.org>

From: Alyssa Rosenzweig <alyssa at rosenzweig.io>

t6020 adds some register ranges compared to t8103, so requires
a new compatible as well as the new PHY registers themselves.

Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
[maz: added PHY registers]
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 Documentation/devicetree/bindings/pci/apple,pcie.yaml | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/apple,pcie.yaml b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
index c8775f9cb0713..77554899b9420 100644
--- a/Documentation/devicetree/bindings/pci/apple,pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
@@ -17,6 +17,10 @@ description: |
   implements its root ports.  But the ATU found on most DesignWare
   PCIe host bridges is absent.
 
+  On systems derived from T602x, the PHY registers are in a region
+  separate from the port registers. In that case, there is one PHY
+  register range per port register range.
+
   All root ports share a single ECAM space, but separate GPIOs are
   used to take the PCI devices on those ports out of reset.  Therefore
   the standard "reset-gpios" and "max-link-speed" properties appear on
@@ -35,11 +39,12 @@ properties:
           - apple,t8103-pcie
           - apple,t8112-pcie
           - apple,t6000-pcie
+          - apple,t6020-pcie
       - const: apple,pcie
 
   reg:
     minItems: 3
-    maxItems: 6
+    maxItems: 10
 
   reg-names:
     minItems: 3
@@ -50,6 +55,10 @@ properties:
       - const: port1
       - const: port2
       - const: port3
+      - const: phy0
+      - const: phy1
+      - const: phy2
+      - const: phy3
 
   ranges:
     minItems: 2
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:25:59 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:25:59 +0000
Subject: [PATCH v2 02/13] PCI: host-generic: Extract an ecam bridge creation helper from pci_host_common_probe()
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-3-maz@kernel.org>

pci_host_common_probe() is an extremely userful helper, as it
abstracts away most of the gunk that a "mostly-ECAM-compliant"
device driver needs.

However, it is structured as a probe function, meaning that a lot
of the driver-specific setup has to happen in a .init() callback,
after the bridge and config space have been instantiated.

This is a bit awkward, and results in a number of convolutions
that could be avoided if the host-common code was more like
a library.

Introduce a pci_host_common_init() helper that does exactly that,
taking the platform device and a struct pci_ecam_op as parameters.

This can then be called from the probe routine, and a lot of the
code that isn't relevant to PCI setup moved away from the .init()
callback. This also removes the dependency on the device match
data, which is an oddity.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pci-host-common.c | 24 ++++++++++++++++--------
 include/linux/pci-ecam.h                 |  2 ++
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
index f441bfd6f96a8..466a1e6a7ffcd 100644
--- a/drivers/pci/controller/pci-host-common.c
+++ b/drivers/pci/controller/pci-host-common.c
@@ -49,23 +49,17 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
 	return cfg;
 }
 
-int pci_host_common_probe(struct platform_device *pdev)
+int pci_host_common_init(struct platform_device *pdev,
+			 const struct pci_ecam_ops *ops)
 {
 	struct device *dev = &pdev->dev;
 	struct pci_host_bridge *bridge;
 	struct pci_config_window *cfg;
-	const struct pci_ecam_ops *ops;
-
-	ops = of_device_get_match_data(&pdev->dev);
-	if (!ops)
-		return -ENODEV;
 
 	bridge = devm_pci_alloc_host_bridge(dev, 0);
 	if (!bridge)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, bridge);
-
 	of_pci_check_probe_only();
 
 	/* Parse and map our Configuration Space windows */
@@ -73,6 +67,8 @@ int pci_host_common_probe(struct platform_device *pdev)
 	if (IS_ERR(cfg))
 		return PTR_ERR(cfg);
 
+	platform_set_drvdata(pdev, bridge);
+
 	bridge->sysdata = cfg;
 	bridge->ops = (struct pci_ops *)&ops->pci_ops;
 	bridge->enable_device = ops->enable_device;
@@ -81,6 +77,18 @@ int pci_host_common_probe(struct platform_device *pdev)
 
 	return pci_host_probe(bridge);
 }
+EXPORT_SYMBOL_GPL(pci_host_common_init);
+
+int pci_host_common_probe(struct platform_device *pdev)
+{
+	const struct pci_ecam_ops *ops;
+
+	ops = of_device_get_match_data(&pdev->dev);
+	if (!ops)
+		return -ENODEV;
+
+	return pci_host_common_init(pdev, ops);
+}
 EXPORT_SYMBOL_GPL(pci_host_common_probe);
 
 void pci_host_common_remove(struct platform_device *pdev)
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index 3a10f8cfc3ad5..bc2ca2c72ee23 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -97,6 +97,8 @@ extern const struct pci_ecam_ops loongson_pci_ecam_ops; /* Loongson PCIe */
 #if IS_ENABLED(CONFIG_PCI_HOST_COMMON)
 /* for DT-based PCI controllers that support ECAM */
 int pci_host_common_probe(struct platform_device *pdev);
+int pci_host_common_init(struct platform_device *pdev,
+			 const struct pci_ecam_ops *ops);
 void pci_host_common_remove(struct platform_device *pdev);
 #endif
 #endif
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:03 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:03 +0000
Subject: [PATCH v2 06/13] PCI: apple: Move away from INTMSK{SET,CLR} for INTx and private interrupts
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-7-maz@kernel.org>

T602x seems to have dropped the rather useful SET/CLR accessors
to the masking register.

Instead, let's use the mask register directly, and wrap it with
a brand new spinlock. No, this isn't moving in the right direction.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 1f6c55e4b5d68..63ceb5e3debaf 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -142,6 +142,7 @@ struct apple_pcie {
 };
 
 struct apple_pcie_port {
+	raw_spinlock_t		lock;
 	struct apple_pcie	*pcie;
 	struct device_node	*np;
 	void __iomem		*base;
@@ -261,14 +262,16 @@ static void apple_port_irq_mask(struct irq_data *data)
 {
 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data);
 
-	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKSET);
+	guard(raw_spinlock_irqsave)(&port->lock);
+	rmw_set(BIT(data->hwirq), port->base + PORT_INTMSK);
 }
 
 static void apple_port_irq_unmask(struct irq_data *data)
 {
 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data);
 
-	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKCLR);
+	guard(raw_spinlock_irqsave)(&port->lock);
+	rmw_clear(BIT(data->hwirq), port->base + PORT_INTMSK);
 }
 
 static bool hwirq_is_intx(unsigned int hwirq)
@@ -387,7 +390,7 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
 		return -ENOMEM;
 
 	/* Disable all interrupts */
-	writel_relaxed(~0, port->base + PORT_INTMSKSET);
+	writel_relaxed(~0, port->base + PORT_INTMSK);
 	writel_relaxed(~0, port->base + PORT_INTSTAT);
 
 	irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port);
@@ -537,6 +540,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	port->pcie = pcie;
 	port->np = np;
 
+	raw_spin_lock_init(&port->lock);
+
 	port->base = devm_platform_ioremap_resource(platform, port->idx + 2);
 	if (IS_ERR(port->base))
 		return PTR_ERR(port->base);
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:01 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:01 +0000
Subject: [PATCH v2 04/13] PCI: apple: Move over to standalone probing
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-5-maz@kernel.org>

Now that we have the required infrastructure, split the Apple PCIe
setup into two categories:

- stuff that has to do with PCI setup stays in the .init() callback

- stuff that is just driver gunk (such as MSI setup) goes into a
  probe routine, which will eventually call into the host-common
  code

The result is a far more logical setup process.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 54 ++++++++++++++++-------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index a7e51bc1c2fe8..9c3103d0d1174 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -730,35 +730,15 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci
 
 static int apple_pcie_init(struct pci_config_window *cfg)
 {
+	struct apple_pcie *pcie = cfg->priv;
 	struct device *dev = cfg->parent;
-	struct platform_device *platform = to_platform_device(dev);
 	struct device_node *of_port;
-	struct apple_pcie *pcie;
 	int ret;
 
-	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
-	if (!pcie)
-		return -ENOMEM;
-
-	pcie->dev = dev;
-
-	mutex_init(&pcie->lock);
-
-	pcie->base = devm_platform_ioremap_resource(platform, 1);
-	if (IS_ERR(pcie->base))
-		return PTR_ERR(pcie->base);
-
-	cfg->priv = pcie;
-	INIT_LIST_HEAD(&pcie->ports);
-
-	ret = apple_msi_init(pcie);
-	if (ret)
-		return ret;
-
 	for_each_child_of_node(dev->of_node, of_port) {
 		ret = apple_pcie_setup_port(pcie, of_port);
 		if (ret) {
-			dev_err(pcie->dev, "Port %pOF setup fail: %d\n", of_port, ret);
+			dev_err(dev, "Port %pOF setup fail: %d\n", of_port, ret);
 			of_node_put(of_port);
 			return ret;
 		}
@@ -778,14 +758,40 @@ static const struct pci_ecam_ops apple_pcie_cfg_ecam_ops = {
 	}
 };
 
+static int apple_pcie_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct apple_pcie *pcie;
+	int ret;
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	pcie->dev = dev;
+	pcie->base = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(pcie->base))
+		return PTR_ERR(pcie->base);
+
+	mutex_init(&pcie->lock);
+	INIT_LIST_HEAD(&pcie->ports);
+	dev_set_drvdata(dev, pcie);
+
+	ret = apple_msi_init(pcie);
+	if (ret)
+		return ret;
+
+	return pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops);
+}
+
 static const struct of_device_id apple_pcie_of_match[] = {
-	{ .compatible = "apple,pcie", .data = &apple_pcie_cfg_ecam_ops },
+	{ .compatible = "apple,pcie" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, apple_pcie_of_match);
 
 static struct platform_driver apple_pcie_driver = {
-	.probe	= pci_host_common_probe,
+	.probe	= apple_pcie_probe,
 	.driver	= {
 		.name			= "pcie-apple",
 		.of_match_table		= apple_pcie_of_match,
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:02 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:02 +0000
Subject: [PATCH v2 05/13] PCI: apple: Dynamically allocate RID-to_SID bitmap
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-6-maz@kernel.org>

As we move towards supporting SoCs with varying RID-to-SID mapping
capabilities, turn the static SID tracking bitmap into a dynamically
allocated one. The current allocation size is still the same, but
that's about to change.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 9c3103d0d1174..1f6c55e4b5d68 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -147,7 +147,7 @@ struct apple_pcie_port {
 	void __iomem		*base;
 	struct irq_domain	*domain;
 	struct list_head	entry;
-	DECLARE_BITMAP(sid_map, MAX_RID2SID);
+	unsigned long		*sid_map;
 	int			sid_map_sz;
 	int			idx;
 };
@@ -524,6 +524,10 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	if (!port)
 		return -ENOMEM;
 
+	port->sid_map = devm_bitmap_zalloc(pcie->dev, MAX_RID2SID, GFP_KERNEL);
+	if (!port->sid_map)
+		return -ENOMEM;
+
 	ret = of_property_read_u32_index(np, "reg", 0, &idx);
 	if (ret)
 		return ret;
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:04 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:04 +0000
Subject: [PATCH v2 07/13] PCI: apple: Fix missing OF node reference in apple_pcie_setup_port
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-8-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

In the success path, we hang onto a reference to the node, so make sure
to grab one. The caller iterator puts our borrowed reference when we
return.

Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 63ceb5e3debaf..6271533f1b042 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -593,6 +593,9 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	list_add_tail(&port->entry, &pcie->ports);
 	init_completion(&pcie->event);
 
+	/* In the success path, we keep a reference to np around */
+	of_node_get(np);
+
 	ret = apple_pcie_port_register_irqs(port);
 	WARN_ON(ret);
 
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:06 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:06 +0000
Subject: [PATCH v2 09/13] PCI: apple: Move port PHY registers to their own reg items
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-10-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

T602x PCIe cores move these registers around. Instead of hardcoding in
another offset, let's move them into their own reg entries. This matches
what Apple does on macOS device trees too.

Maintains backwards compatibility with old DTs by using the old offsets.

Note that we open code devm_platform_ioremap_resource_byname() to avoid
error messages on older platforms with missing resources in the pcie
node. ("pcie-apple 590000000.pcie: invalid resource (null)" on probe)

Co-developed-by: Janne Grunau <j at jannau.net>
Signed-off-by: Janne Grunau <j at jannau.net>
Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 55 +++++++++++++++++++----------
 1 file changed, 37 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 23d9f62bd2ad4..94c49611b74df 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -39,14 +39,18 @@
 #define   CORE_RC_STAT_READY		BIT(0)
 #define CORE_FABRIC_STAT		0x04000
 #define   CORE_FABRIC_STAT_MASK		0x001F001F
-#define CORE_LANE_CFG(port)		(0x84000 + 0x4000 * (port))
-#define   CORE_LANE_CFG_REFCLK0REQ	BIT(0)
-#define   CORE_LANE_CFG_REFCLK1REQ	BIT(1)
-#define   CORE_LANE_CFG_REFCLK0ACK	BIT(2)
-#define   CORE_LANE_CFG_REFCLK1ACK	BIT(3)
-#define   CORE_LANE_CFG_REFCLKEN	(BIT(9) | BIT(10))
-#define CORE_LANE_CTL(port)		(0x84004 + 0x4000 * (port))
-#define   CORE_LANE_CTL_CFGACC		BIT(15)
+
+#define CORE_PHY_DEFAULT_BASE(port)	(0x84000 + 0x4000 * (port))
+
+#define PHY_LANE_CFG			0x00000
+#define   PHY_LANE_CFG_REFCLK0REQ	BIT(0)
+#define   PHY_LANE_CFG_REFCLK1REQ	BIT(1)
+#define   PHY_LANE_CFG_REFCLK0ACK	BIT(2)
+#define   PHY_LANE_CFG_REFCLK1ACK	BIT(3)
+#define   PHY_LANE_CFG_REFCLKEN		(BIT(9) | BIT(10))
+#define   PHY_LANE_CFG_REFCLKCGEN	(BIT(30) | BIT(31))
+#define PHY_LANE_CTL			0x00004
+#define   PHY_LANE_CTL_CFGACC		BIT(15)
 
 #define PORT_LTSSMCTL			0x00080
 #define   PORT_LTSSMCTL_START		BIT(0)
@@ -146,6 +150,7 @@ struct apple_pcie_port {
 	struct apple_pcie	*pcie;
 	struct device_node	*np;
 	void __iomem		*base;
+	void __iomem		*phy;
 	struct irq_domain	*domain;
 	struct list_head	entry;
 	unsigned long		*sid_map;
@@ -476,26 +481,26 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
 	if (res < 0)
 		return res;
 
-	rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
-	rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx));
+	rmw_set(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
+	rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
 
-	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx),
-					 stat, stat & CORE_LANE_CFG_REFCLK0ACK,
+	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
+					 stat, stat & PHY_LANE_CFG_REFCLK0ACK,
 					 100, 50000);
 	if (res < 0)
 		return res;
 
-	rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx));
-	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx),
-					 stat, stat & CORE_LANE_CFG_REFCLK1ACK,
+	rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG);
+	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
+					 stat, stat & PHY_LANE_CFG_REFCLK1ACK,
 					 100, 50000);
 
 	if (res < 0)
 		return res;
 
-	rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
+	rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
 
-	rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx));
+	rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);
 	rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
 
 	return 0;
@@ -515,6 +520,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	struct platform_device *platform = to_platform_device(pcie->dev);
 	struct apple_pcie_port *port;
 	struct gpio_desc *reset;
+	struct resource *res;
+	char name[16];
 	u32 stat, idx;
 	int ret, i;
 
@@ -542,10 +549,22 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 
 	raw_spin_lock_init(&port->lock);
 
-	port->base = devm_platform_ioremap_resource(platform, port->idx + 2);
+	snprintf(name, sizeof(name), "port%d", port->idx);
+	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name);
+	if (!res)
+		res = platform_get_resource(platform, IORESOURCE_MEM, port->idx + 2);
+
+	port->base = devm_ioremap_resource(&platform->dev, res);
 	if (IS_ERR(port->base))
 		return PTR_ERR(port->base);
 
+	snprintf(name, sizeof(name), "phy%d", port->idx);
+	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name);
+	if (res)
+		port->phy = devm_ioremap_resource(&platform->dev, res);
+	else
+		port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx);
+
 	rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
 
 	/* Assert PERST# before setting up the clock */
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:08 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:08 +0000
Subject: [PATCH v2 11/13] PCI: apple: Use gpiod_set_value_cansleep in probe flow
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-12-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

We're allowed to sleep here, so tell the GPIO core by using
gpiod_set_value_cansleep instead of gpiod_set_value.

Fixes: 1e33888fbe44 ("PCI: apple: Add initial hardware bring-up")
Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index c00ec0781fabc..505adf64bd66d 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -562,7 +562,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
 
 	/* Assert PERST# before setting up the clock */
-	gpiod_set_value(reset, 1);
+	gpiod_set_value_cansleep(reset, 1);
 
 	ret = apple_pcie_setup_refclk(pcie, port);
 	if (ret < 0)
@@ -573,7 +573,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 
 	/* Deassert PERST# */
 	rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
-	gpiod_set_value(reset, 0);
+	gpiod_set_value_cansleep(reset, 0);
 
 	/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
 	msleep(100);
-- 
2.39.2



From maz at kernel.org  Tue Mar 25 03:26:09 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 10:26:09 +0000
Subject: [PATCH v2 12/13] PCI: apple: Abstract register offsets via a SoC-specific structure
In-Reply-To: <20250325102610.2073863-1-maz@kernel.org>
References: <20250325102610.2073863-1-maz@kernel.org>
Message-ID: <20250325102610.2073863-13-maz@kernel.org>

From: Hector Martin <marcan at marcan.st>

Newer versions of the Apple PCIe block have a bunch of small, but
annoying differences.

In order to embrace this diversity of implementations, move the
currently hardcoded offsets into a hw_info structure. Future SoCs
will provide their own structure describing the applicable offsets.

Signed-off-by: Hector Martin <marcan at marcan.st>
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
[maz: split from original patch to only address T8103]
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 drivers/pci/controller/pcie-apple.c | 89 +++++++++++++++++++++++------
 1 file changed, 72 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 505adf64bd66d..847cba753d28d 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -18,6 +18,7 @@
  * Author: Marc Zyngier <maz at kernel.org>
  */
 
+#include <linux/bitfield.h>
 #include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/iopoll.h>
@@ -29,6 +30,7 @@
 #include <linux/of_irq.h>
 #include <linux/pci-ecam.h>
 
+/* T8103 (original M1) and related SoCs */
 #define CORE_RC_PHYIF_CTL		0x00024
 #define   CORE_RC_PHYIF_CTL_RUN		BIT(0)
 #define CORE_RC_PHYIF_STAT		0x00028
@@ -104,7 +106,7 @@
 #define   PORT_REFCLK_CGDIS		BIT(8)
 #define PORT_PERST			0x00814
 #define   PORT_PERST_OFF		BIT(0)
-#define PORT_RID2SID(i16)		(0x00828 + 4 * (i16))
+#define PORT_RID2SID			0x00828
 #define   PORT_RID2SID_VALID		BIT(31)
 #define   PORT_RID2SID_SID_SHIFT	16
 #define   PORT_RID2SID_BUS_SHIFT	8
@@ -122,7 +124,8 @@
 #define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1)
 #define PORT_PREFMEM_ENABLE		0x00994
 
-#define MAX_RID2SID			64
+#define PORT_MSIMAP_ENABLE	BIT(31)
+#define PORT_MSIMAP_TARGET	GENMASK(7, 0)
 
 /*
  * The doorbell address is set to 0xfffff000, which by convention
@@ -133,10 +136,33 @@
  */
 #define DOORBELL_ADDR		CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR
 
+struct hw_info {
+	u32 phy_lane_ctl;
+	u32 port_msiaddr;
+	u32 port_msiaddr_hi;
+	u32 port_refclk;
+	u32 port_perst;
+	u32 port_rid2sid;
+	u32 port_msimap;
+	u32 max_rid2sid;
+};
+
+static const struct hw_info t8103_hw = {
+	.phy_lane_ctl		= PHY_LANE_CTL,
+	.port_msiaddr		= PORT_MSIADDR,
+	.port_msiaddr_hi	= 0,
+	.port_refclk		= PORT_REFCLK,
+	.port_perst		= PORT_PERST,
+	.port_rid2sid		= PORT_RID2SID,
+	.port_msimap		= 0,
+	.max_rid2sid		= 64,
+};
+
 struct apple_pcie {
 	struct mutex		lock;
 	struct device		*dev;
 	void __iomem            *base;
+	const struct hw_info	*hw;
 	struct irq_domain	*domain;
 	unsigned long		*bitmap;
 	struct list_head	ports;
@@ -380,7 +406,9 @@ static void apple_port_irq_handler(struct irq_desc *desc)
 static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
 {
 	struct fwnode_handle *fwnode = &port->np->fwnode;
+	struct apple_pcie *pcie = port->pcie;
 	unsigned int irq;
+	u32 val = 0;
 
 	/* FIXME: consider moving each interrupt under each port */
 	irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)),
@@ -402,13 +430,23 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
 
 	/* Configure MSI base address */
 	BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR));
-	writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR);
+	writel_relaxed(lower_32_bits(DOORBELL_ADDR),
+		       port->base + pcie->hw->port_msiaddr);
+	if (pcie->hw->port_msiaddr_hi)
+		writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi);
 
 	/* Enable MSIs, shared between all ports */
-	writel_relaxed(0, port->base + PORT_MSIBASE);
-	writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) |
-		       PORT_MSICFG_EN, port->base + PORT_MSICFG);
+	if (pcie->hw->port_msimap) {
+		for (int i = 0; i < pcie->nvecs; i++)
+			writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) |
+				       PORT_MSIMAP_ENABLE,
+				       port->base + pcie->hw->port_msimap + 4 * i);
+	} else {
+		writel_relaxed(0, port->base + PORT_MSIBASE);
+		val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT;
+	}
 
+	writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG);
 	return 0;
 }
 
@@ -475,7 +513,9 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
 	u32 stat;
 	int res;
 
-	rmw_set(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
+	if (pcie->hw->phy_lane_ctl)
+		rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
+
 	rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
 
 	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
@@ -492,20 +532,28 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
 	if (res < 0)
 		return res;
 
-	rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + PHY_LANE_CTL);
+	if (pcie->hw->phy_lane_ctl)
+		rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
 
 	rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);
-	rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
+
+	if (pcie->hw->port_refclk)
+		rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk);
 
 	return 0;
 }
 
+static void __iomem *port_rid2sid_addr(struct apple_pcie_port *port, int idx)
+{
+	return port->base + port->pcie->hw->port_rid2sid + 4 * idx;
+}
+
 static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port,
 				    int idx, u32 val)
 {
-	writel_relaxed(val, port->base + PORT_RID2SID(idx));
+	writel_relaxed(val, port_rid2sid_addr(port, idx));
 	/* Read back to ensure completion of the write */
-	return readl_relaxed(port->base + PORT_RID2SID(idx));
+	return readl_relaxed(port_rid2sid_addr(port, idx));
 }
 
 static int apple_pcie_setup_port(struct apple_pcie *pcie,
@@ -528,7 +576,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	if (!port)
 		return -ENOMEM;
 
-	port->sid_map = devm_bitmap_zalloc(pcie->dev, MAX_RID2SID, GFP_KERNEL);
+	port->sid_map = devm_bitmap_zalloc(pcie->dev, pcie->hw->max_rid2sid, GFP_KERNEL);
 	if (!port->sid_map)
 		return -ENOMEM;
 
@@ -572,7 +620,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	usleep_range(100, 200);
 
 	/* Deassert PERST# */
-	rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
+	rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
 	gpiod_set_value_cansleep(reset, 0);
 
 	/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
@@ -585,7 +633,11 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 		return ret;
 	}
 
-	rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
+	if (pcie->hw->port_refclk)
+		rmw_clear(PORT_REFCLK_CGDIS, port->base + pcie->hw->port_refclk);
+	else
+		rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG);
+
 	rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
 
 	ret = apple_pcie_port_setup_irq(port);
@@ -593,7 +645,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 		return ret;
 
 	/* Reset all RID/SID mappings, and check for RAZ/WI registers */
-	for (i = 0; i < MAX_RID2SID; i++) {
+	for (i = 0; i < pcie->hw->max_rid2sid; i++) {
 		if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d)
 			break;
 		apple_pcie_rid2sid_write(port, i, 0);
@@ -741,7 +793,7 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci
 	for_each_set_bit(idx, port->sid_map, port->sid_map_sz) {
 		u32 val;
 
-		val = readl_relaxed(port->base + PORT_RID2SID(idx));
+		val = readl_relaxed(port_rid2sid_addr(port, idx));
 		if ((val & 0xffff) == rid) {
 			apple_pcie_rid2sid_write(port, idx, 0);
 			bitmap_release_region(port->sid_map, idx, 0);
@@ -794,6 +846,9 @@ static int apple_pcie_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	pcie->dev = dev;
+	pcie->hw = of_device_get_match_data(dev);
+	if (!pcie->hw)
+		return -ENODEV;
 	pcie->base = devm_platform_ioremap_resource(pdev, 1);
 	if (IS_ERR(pcie->base))
 		return PTR_ERR(pcie->base);
@@ -810,7 +865,7 @@ static int apple_pcie_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id apple_pcie_of_match[] = {
-	{ .compatible = "apple,pcie" },
+	{ .compatible = "apple,pcie",		.data = &t8103_hw },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, apple_pcie_of_match);
-- 
2.39.2



From peterz at infradead.org  Tue Mar 25 03:53:30 2025
From: peterz at infradead.org (Peter Zijlstra)
Date: Tue, 25 Mar 2025 11:53:30 +0100
Subject: [PATCH v3 0/3] kernel/events/uprobes: uprobe_write_opcode()
 rewrite
In-Reply-To: <20250321133401.GB4776@redhat.com>
References: <20250321113713.204682-1-david@redhat.com>
 <20250321133401.GB4776@redhat.com>
Message-ID: <20250325105330.GI36322@noisy.programming.kicks-ass.net>

On Fri, Mar 21, 2025 at 02:34:01PM +0100, Oleg Nesterov wrote:
> On 03/21, David Hildenbrand wrote:
> >
> > Based on mm/unstable.
> 
> which has another fix from David in __replace_page() plus the fix from
> Tong in uprobe_write_opcode().
> 
> So, Andrew, could you take this series as well? Peter, will you agree?

Yeah,

Acked-by: Peter Zijlstra (Intel) <peterz at infradead.org>


From jens.wiklander at linaro.org  Tue Mar 25 03:55:46 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Tue, 25 Mar 2025 11:55:46 +0100
Subject: [PATCH v6 05/10] tee: implement restricted DMA-heap
In-Reply-To: <Z-JOPgcWlpTlskgd@sumit-X1>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-6-jens.wiklander@linaro.org> <Z-JOPgcWlpTlskgd@sumit-X1>
Message-ID: <CAHUa44GjpHT5Nqo+Ar5jNYNPV-YJQYpLTCf=7oJ1o0VjP-t0nA@mail.gmail.com>

Hi Sumit,

On Tue, Mar 25, 2025 at 7:33?AM Sumit Garg <sumit.garg at kernel.org> wrote:
>
> Hi Jens,
>
> On Wed, Mar 05, 2025 at 02:04:11PM +0100, Jens Wiklander wrote:
> > Implement DMA heap for restricted DMA-buf allocation in the TEE
> > subsystem.
> >
> > Restricted memory refers to memory buffers behind a hardware enforced
> > firewall. It is not accessible to the kernel during normal circumstances
> > but rather only accessible to certain hardware IPs or CPUs executing in
> > higher or differently privileged mode than the kernel itself. This
> > interface allows to allocate and manage such restricted memory buffers
> > via interaction with a TEE implementation.
> >
> > The restricted memory is allocated for a specific use-case, like Secure
> > Video Playback, Trusted UI, or Secure Video Recording where certain
> > hardware devices can access the memory.
> >
> > The DMA-heaps are enabled explicitly by the TEE backend driver. The TEE
> > backend drivers needs to implement restricted memory pool to manage the
> > restricted memory.
> >
> > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > ---
> >  drivers/tee/Makefile      |   1 +
> >  drivers/tee/tee_heap.c    | 470 ++++++++++++++++++++++++++++++++++++++
> >  drivers/tee/tee_private.h |   6 +
> >  include/linux/tee_core.h  |  62 +++++
> >  4 files changed, 539 insertions(+)
> >  create mode 100644 drivers/tee/tee_heap.c
> >
> > diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> > index 5488cba30bd2..949a6a79fb06 100644
> > --- a/drivers/tee/Makefile
> > +++ b/drivers/tee/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  obj-$(CONFIG_TEE) += tee.o
> >  tee-objs += tee_core.o
> > +tee-objs += tee_heap.o
> >  tee-objs += tee_shm.o
> >  tee-objs += tee_shm_pool.o
> >  obj-$(CONFIG_OPTEE) += optee/
> > diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c
> > new file mode 100644
> > index 000000000000..476ab2e27260
> > --- /dev/null
> > +++ b/drivers/tee/tee_heap.c
> > @@ -0,0 +1,470 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2025, Linaro Limited
> > + */
> > +
> > +#include <linux/scatterlist.h>
> > +#include <linux/dma-buf.h>
> > +#include <linux/dma-heap.h>
> > +#include <linux/genalloc.h>
> > +#include <linux/module.h>
> > +#include <linux/scatterlist.h>
> > +#include <linux/slab.h>
> > +#include <linux/tee_core.h>
> > +#include <linux/xarray.h>
>
> Lets try to follow alphabetical order here.

Sure

>
> > +
> > +#include "tee_private.h"
> > +
> > +struct tee_dma_heap {
> > +     struct dma_heap *heap;
> > +     enum tee_dma_heap_id id;
> > +     struct tee_rstmem_pool *pool;
> > +     struct tee_device *teedev;
> > +     /* Protects pool and teedev above */
> > +     struct mutex mu;
> > +};
> > +
> > +struct tee_heap_buffer {
> > +     struct tee_rstmem_pool *pool;
> > +     struct tee_device *teedev;
> > +     size_t size;
> > +     size_t offs;
> > +     struct sg_table table;
> > +};
> > +
> > +struct tee_heap_attachment {
> > +     struct sg_table table;
> > +     struct device *dev;
> > +};
> > +
> > +struct tee_rstmem_static_pool {
> > +     struct tee_rstmem_pool pool;
> > +     struct gen_pool *gen_pool;
> > +     phys_addr_t pa_base;
> > +};
> > +
> > +#if !IS_MODULE(CONFIG_TEE) && IS_ENABLED(CONFIG_DMABUF_HEAPS)
>
> Can this dependency rather be better managed via Kconfig?

This was the easiest yet somewhat flexible solution I could find. If
you have something better, let's use that instead.

>
> > +static DEFINE_XARRAY_ALLOC(tee_dma_heap);
> > +
> > +static int copy_sg_table(struct sg_table *dst, struct sg_table *src)
> > +{
> > +     struct scatterlist *dst_sg;
> > +     struct scatterlist *src_sg;
> > +     int ret;
> > +     int i;
> > +
> > +     ret = sg_alloc_table(dst, src->orig_nents, GFP_KERNEL);
> > +     if (ret)
> > +             return ret;
> > +
> > +     dst_sg = dst->sgl;
> > +     for_each_sgtable_sg(src, src_sg, i) {
> > +             sg_set_page(dst_sg, sg_page(src_sg), src_sg->length,
> > +                         src_sg->offset);
> > +             dst_sg = sg_next(dst_sg);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int tee_heap_attach(struct dma_buf *dmabuf,
> > +                        struct dma_buf_attachment *attachment)
> > +{
> > +     struct tee_heap_buffer *buf = dmabuf->priv;
> > +     struct tee_heap_attachment *a;
> > +     int ret;
> > +
> > +     a = kzalloc(sizeof(*a), GFP_KERNEL);
> > +     if (!a)
> > +             return -ENOMEM;
> > +
> > +     ret = copy_sg_table(&a->table, &buf->table);
> > +     if (ret) {
> > +             kfree(a);
> > +             return ret;
> > +     }
> > +
> > +     a->dev = attachment->dev;
> > +     attachment->priv = a;
> > +
> > +     return 0;
> > +}
> > +
> > +static void tee_heap_detach(struct dma_buf *dmabuf,
> > +                         struct dma_buf_attachment *attachment)
> > +{
> > +     struct tee_heap_attachment *a = attachment->priv;
> > +
> > +     sg_free_table(&a->table);
> > +     kfree(a);
> > +}
> > +
> > +static struct sg_table *
> > +tee_heap_map_dma_buf(struct dma_buf_attachment *attachment,
> > +                  enum dma_data_direction direction)
> > +{
> > +     struct tee_heap_attachment *a = attachment->priv;
> > +     int ret;
> > +
> > +     ret = dma_map_sgtable(attachment->dev, &a->table, direction,
> > +                           DMA_ATTR_SKIP_CPU_SYNC);
> > +     if (ret)
> > +             return ERR_PTR(ret);
> > +
> > +     return &a->table;
> > +}
> > +
> > +static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
> > +                                struct sg_table *table,
> > +                                enum dma_data_direction direction)
> > +{
> > +     struct tee_heap_attachment *a = attachment->priv;
> > +
> > +     WARN_ON(&a->table != table);
> > +
> > +     dma_unmap_sgtable(attachment->dev, table, direction,
> > +                       DMA_ATTR_SKIP_CPU_SYNC);
> > +}
> > +
> > +static void tee_heap_buf_free(struct dma_buf *dmabuf)
> > +{
> > +     struct tee_heap_buffer *buf = dmabuf->priv;
> > +     struct tee_device *teedev = buf->teedev;
> > +
> > +     buf->pool->ops->free(buf->pool, &buf->table);
> > +     tee_device_put(teedev);
> > +}
> > +
> > +static const struct dma_buf_ops tee_heap_buf_ops = {
> > +     .attach = tee_heap_attach,
> > +     .detach = tee_heap_detach,
> > +     .map_dma_buf = tee_heap_map_dma_buf,
> > +     .unmap_dma_buf = tee_heap_unmap_dma_buf,
> > +     .release = tee_heap_buf_free,
> > +};
> > +
> > +static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap,
> > +                                       unsigned long len, u32 fd_flags,
> > +                                       u64 heap_flags)
> > +{
> > +     struct tee_dma_heap *h = dma_heap_get_drvdata(heap);
> > +     DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> > +     struct tee_device *teedev = NULL;
> > +     struct tee_heap_buffer *buf;
> > +     struct tee_rstmem_pool *pool;
> > +     struct dma_buf *dmabuf;
> > +     int rc;
> > +
> > +     mutex_lock(&h->mu);
> > +     if (tee_device_get(h->teedev)) {
> > +             teedev = h->teedev;
> > +             pool = h->pool;
> > +     }
> > +     mutex_unlock(&h->mu);
> > +
> > +     if (!teedev)
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     buf = kzalloc(sizeof(*buf), GFP_KERNEL);
> > +     if (!buf) {
> > +             dmabuf = ERR_PTR(-ENOMEM);
> > +             goto err;
> > +     }
> > +     buf->size = len;
> > +     buf->pool = pool;
> > +     buf->teedev = teedev;
> > +
> > +     rc = pool->ops->alloc(pool, &buf->table, len, &buf->offs);
> > +     if (rc) {
> > +             dmabuf = ERR_PTR(rc);
> > +             goto err_kfree;
> > +     }
> > +
> > +     exp_info.ops = &tee_heap_buf_ops;
> > +     exp_info.size = len;
> > +     exp_info.priv = buf;
> > +     exp_info.flags = fd_flags;
> > +     dmabuf = dma_buf_export(&exp_info);
> > +     if (IS_ERR(dmabuf))
> > +             goto err_rstmem_free;
> > +
> > +     return dmabuf;
> > +
> > +err_rstmem_free:
> > +     pool->ops->free(pool, &buf->table);
> > +err_kfree:
> > +     kfree(buf);
> > +err:
> > +     tee_device_put(h->teedev);
> > +     return dmabuf;
> > +}
> > +
> > +static const struct dma_heap_ops tee_dma_heap_ops = {
> > +     .allocate = tee_dma_heap_alloc,
> > +};
> > +
> > +static const char *heap_id_2_name(enum tee_dma_heap_id id)
> > +{
> > +     switch (id) {
> > +     case TEE_DMA_HEAP_SECURE_VIDEO_PLAY:
> > +             return "restricted,secure-video";
> > +     case TEE_DMA_HEAP_TRUSTED_UI:
> > +             return "restricted,trusted-ui";
> > +     case TEE_DMA_HEAP_SECURE_VIDEO_RECORD:
> > +             return "restricted,secure-video-record";
> > +     default:
> > +             return NULL;
> > +     }
> > +}
> > +
> > +static int alloc_dma_heap(struct tee_device *teedev, enum tee_dma_heap_id id,
> > +                       struct tee_rstmem_pool *pool)
> > +{
> > +     struct dma_heap_export_info exp_info = {
> > +             .ops = &tee_dma_heap_ops,
> > +             .name = heap_id_2_name(id),
> > +     };
> > +     struct tee_dma_heap *h;
> > +     int rc;
> > +
> > +     if (!exp_info.name)
> > +             return -EINVAL;
> > +
> > +     if (xa_reserve(&tee_dma_heap, id, GFP_KERNEL)) {
> > +             if (!xa_load(&tee_dma_heap, id))
> > +                     return -EEXIST;
> > +             return -ENOMEM;
> > +     }
> > +
> > +     h = kzalloc(sizeof(*h), GFP_KERNEL);
> > +     if (!h)
> > +             return -ENOMEM;
> > +     h->id = id;
> > +     h->teedev = teedev;
> > +     h->pool = pool;
> > +     mutex_init(&h->mu);
> > +
> > +     exp_info.priv = h;
> > +     h->heap = dma_heap_add(&exp_info);
> > +     if (IS_ERR(h->heap)) {
> > +             rc = PTR_ERR(h->heap);
> > +             kfree(h);
> > +
> > +             return rc;
> > +     }
> > +
> > +     /* "can't fail" due to the call to xa_reserve() above */
> > +     return WARN(xa_store(&tee_dma_heap, id, h, GFP_KERNEL),
> > +                 "xa_store() failed");
> > +}
> > +
> > +int tee_device_register_dma_heap(struct tee_device *teedev,
> > +                              enum tee_dma_heap_id id,
> > +                              struct tee_rstmem_pool *pool)
> > +{
> > +     struct tee_dma_heap *h;
> > +     int rc;
> > +
> > +     h = xa_load(&tee_dma_heap, id);
> > +     if (h) {
> > +             mutex_lock(&h->mu);
> > +             if (h->teedev) {
> > +                     rc = -EBUSY;
> > +             } else {
> > +                     h->teedev = teedev;
> > +                     h->pool = pool;
> > +                     rc = 0;
> > +             }
> > +             mutex_unlock(&h->mu);
> > +     } else {
> > +             rc = alloc_dma_heap(teedev, id, pool);
> > +     }
> > +
> > +     if (rc)
> > +             dev_err(&teedev->dev, "can't register DMA heap id %d (%s)\n",
> > +                     id, heap_id_2_name(id));
> > +
> > +     return rc;
> > +}
> > +
> > +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev)
> > +{
> > +     struct tee_rstmem_pool *pool;
> > +     struct tee_dma_heap *h;
> > +     u_long i;
> > +
> > +     xa_for_each(&tee_dma_heap, i, h) {
> > +             if (h) {
> > +                     pool = NULL;
> > +                     mutex_lock(&h->mu);
> > +                     if (h->teedev == teedev) {
> > +                             pool = h->pool;
> > +                             h->teedev = NULL;
> > +                             h->pool = NULL;
> > +                     }
> > +                     mutex_unlock(&h->mu);
> > +                     if (pool)
> > +                             pool->ops->destroy_pool(pool);
> > +             }
> > +     }
> > +}
> > +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
> > +
> > +int tee_heap_update_from_dma_buf(struct tee_device *teedev,
> > +                              struct dma_buf *dmabuf, size_t *offset,
> > +                              struct tee_shm *shm,
> > +                              struct tee_shm **parent_shm)
> > +{
> > +     struct tee_heap_buffer *buf;
> > +     int rc;
> > +
> > +     /* The DMA-buf must be from our heap */
> > +     if (dmabuf->ops != &tee_heap_buf_ops)
> > +             return -EINVAL;
> > +
> > +     buf = dmabuf->priv;
> > +     /* The buffer must be from the same teedev */
> > +     if (buf->teedev != teedev)
> > +             return -EINVAL;
> > +
> > +     shm->size = buf->size;
> > +
> > +     rc = buf->pool->ops->update_shm(buf->pool, &buf->table, buf->offs, shm,
> > +                                     parent_shm);
> > +     if (!rc && *parent_shm)
> > +             *offset = buf->offs;
> > +
> > +     return rc;
> > +}
> > +#else
> > +int tee_device_register_dma_heap(struct tee_device *teedev __always_unused,
> > +                              enum tee_dma_heap_id id __always_unused,
> > +                              struct tee_rstmem_pool *pool __always_unused)
> > +{
> > +     return -EINVAL;
> > +}
> > +EXPORT_SYMBOL_GPL(tee_device_register_dma_heap);
> > +
> > +void
> > +tee_device_unregister_all_dma_heaps(struct tee_device *teedev __always_unused)
> > +{
> > +}
> > +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps);
> > +
> > +int tee_heap_update_from_dma_buf(struct tee_device *teedev __always_unused,
> > +                              struct dma_buf *dmabuf __always_unused,
> > +                              size_t *offset __always_unused,
> > +                              struct tee_shm *shm __always_unused,
> > +                              struct tee_shm **parent_shm __always_unused)
> > +{
> > +     return -EINVAL;
> > +}
> > +#endif
> > +
> > +static struct tee_rstmem_static_pool *
> > +to_rstmem_static_pool(struct tee_rstmem_pool *pool)
> > +{
> > +     return container_of(pool, struct tee_rstmem_static_pool, pool);
> > +}
> > +
> > +static int rstmem_pool_op_static_alloc(struct tee_rstmem_pool *pool,
> > +                                    struct sg_table *sgt, size_t size,
> > +                                    size_t *offs)
> > +{
> > +     struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> > +     phys_addr_t pa;
> > +     int ret;
> > +
> > +     pa = gen_pool_alloc(stp->gen_pool, size);
> > +     if (!pa)
> > +             return -ENOMEM;
> > +
> > +     ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
> > +     if (ret) {
> > +             gen_pool_free(stp->gen_pool, pa, size);
> > +             return ret;
> > +     }
> > +
> > +     sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
> > +     *offs = pa - stp->pa_base;
> > +
> > +     return 0;
> > +}
> > +
> > +static void rstmem_pool_op_static_free(struct tee_rstmem_pool *pool,
> > +                                    struct sg_table *sgt)
> > +{
> > +     struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> > +     struct scatterlist *sg;
> > +     int i;
> > +
> > +     for_each_sgtable_sg(sgt, sg, i)
> > +             gen_pool_free(stp->gen_pool, sg_phys(sg), sg->length);
> > +     sg_free_table(sgt);
> > +}
> > +
> > +static int rstmem_pool_op_static_update_shm(struct tee_rstmem_pool *pool,
> > +                                         struct sg_table *sgt, size_t offs,
> > +                                         struct tee_shm *shm,
> > +                                         struct tee_shm **parent_shm)
> > +{
> > +     struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> > +
> > +     shm->paddr = stp->pa_base + offs;
> > +     *parent_shm = NULL;
> > +
> > +     return 0;
> > +}
> > +
> > +static void rstmem_pool_op_static_destroy_pool(struct tee_rstmem_pool *pool)
> > +{
> > +     struct tee_rstmem_static_pool *stp = to_rstmem_static_pool(pool);
> > +
> > +     gen_pool_destroy(stp->gen_pool);
> > +     kfree(stp);
> > +}
> > +
> > +static struct tee_rstmem_pool_ops rstmem_pool_ops_static = {
> > +     .alloc = rstmem_pool_op_static_alloc,
> > +     .free = rstmem_pool_op_static_free,
> > +     .update_shm = rstmem_pool_op_static_update_shm,
> > +     .destroy_pool = rstmem_pool_op_static_destroy_pool,
> > +};
> > +
> > +struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
> > +                                                  size_t size)
> > +{
> > +     const size_t page_mask = PAGE_SIZE - 1;
> > +     struct tee_rstmem_static_pool *stp;
> > +     int rc;
> > +
> > +     /* Check it's page aligned */
> > +     if ((paddr | size) & page_mask)
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     stp = kzalloc(sizeof(*stp), GFP_KERNEL);
> > +     if (!stp)
> > +             return ERR_PTR(-ENOMEM);
> > +
> > +     stp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
> > +     if (!stp->gen_pool) {
> > +             rc = -ENOMEM;
> > +             goto err_free;
> > +     }
> > +
> > +     rc = gen_pool_add(stp->gen_pool, paddr, size, -1);
> > +     if (rc)
> > +             goto err_free_pool;
> > +
> > +     stp->pool.ops = &rstmem_pool_ops_static;
> > +     stp->pa_base = paddr;
> > +     return &stp->pool;
> > +
> > +err_free_pool:
> > +     gen_pool_destroy(stp->gen_pool);
> > +err_free:
> > +     kfree(stp);
> > +
> > +     return ERR_PTR(rc);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_rstmem_static_pool_alloc);
> > diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> > index 9bc50605227c..6c6ff5d5eed2 100644
> > --- a/drivers/tee/tee_private.h
> > +++ b/drivers/tee/tee_private.h
> > @@ -8,6 +8,7 @@
> >  #include <linux/cdev.h>
> >  #include <linux/completion.h>
> >  #include <linux/device.h>
> > +#include <linux/dma-buf.h>
> >  #include <linux/kref.h>
> >  #include <linux/mutex.h>
> >  #include <linux/types.h>
> > @@ -24,4 +25,9 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
> >  struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> >                                         unsigned long addr, size_t length);
> >
> > +int tee_heap_update_from_dma_buf(struct tee_device *teedev,
> > +                              struct dma_buf *dmabuf, size_t *offset,
> > +                              struct tee_shm *shm,
> > +                              struct tee_shm **parent_shm);
> > +
> >  #endif /*TEE_PRIVATE_H*/
> > diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
> > index a38494d6b5f4..16ef078247ae 100644
> > --- a/include/linux/tee_core.h
> > +++ b/include/linux/tee_core.h
> > @@ -8,9 +8,11 @@
> >
> >  #include <linux/cdev.h>
> >  #include <linux/device.h>
> > +#include <linux/dma-buf.h>
> >  #include <linux/idr.h>
> >  #include <linux/kref.h>
> >  #include <linux/list.h>
> > +#include <linux/scatterlist.h>
> >  #include <linux/tee.h>
> >  #include <linux/tee_drv.h>
> >  #include <linux/types.h>
> > @@ -30,6 +32,12 @@
> >  #define TEE_DEVICE_FLAG_REGISTERED   0x1
> >  #define TEE_MAX_DEV_NAME_LEN         32
> >
> > +enum tee_dma_heap_id {
> > +     TEE_DMA_HEAP_SECURE_VIDEO_PLAY = 1,
> > +     TEE_DMA_HEAP_TRUSTED_UI,
> > +     TEE_DMA_HEAP_SECURE_VIDEO_RECORD,
> > +};
> > +
> >  /**
> >   * struct tee_device - TEE Device representation
> >   * @name:    name of device
> > @@ -116,6 +124,33 @@ struct tee_desc {
> >       u32 flags;
> >  };
> >
> > +/**
> > + * struct tee_rstmem_pool - restricted memory pool
> > + * @ops:             operations
> > + *
> > + * This is an abstract interface where this struct is expected to be
> > + * embedded in another struct specific to the implementation.
> > + */
> > +struct tee_rstmem_pool {
> > +     const struct tee_rstmem_pool_ops *ops;
> > +};
> > +
> > +/**
> > + * struct tee_rstmem_pool_ops - restricted memory pool operations
> > + * @alloc:           called when allocating restricted memory
> > + * @free:            called when freeing restricted memory
> > + * @destroy_pool:    called when destroying the pool
> > + */
> > +struct tee_rstmem_pool_ops {
> > +     int (*alloc)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
> > +                  size_t size, size_t *offs);
> > +     void (*free)(struct tee_rstmem_pool *pool, struct sg_table *sgt);
> > +     int (*update_shm)(struct tee_rstmem_pool *pool, struct sg_table *sgt,
> > +                       size_t offs, struct tee_shm *shm,
> > +                       struct tee_shm **parent_shm);
>
> This API isn't descibed in kdoc comment above. Can you descibe the role
> of this API and when it's needed?

Yes, I'll add something.

Cheers,
Jens

>
> -Sumit
>
> > +     void (*destroy_pool)(struct tee_rstmem_pool *pool);
> > +};
> > +
> >  /**
> >   * tee_device_alloc() - Allocate a new struct tee_device instance
> >   * @teedesc: Descriptor for this driver
> > @@ -154,6 +189,11 @@ int tee_device_register(struct tee_device *teedev);
> >   */
> >  void tee_device_unregister(struct tee_device *teedev);
> >
> > +int tee_device_register_dma_heap(struct tee_device *teedev,
> > +                              enum tee_dma_heap_id id,
> > +                              struct tee_rstmem_pool *pool);
> > +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev);
> > +
> >  /**
> >   * tee_device_set_dev_groups() - Set device attribute groups
> >   * @teedev:  Device to register
> > @@ -229,6 +269,28 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> >       pool->ops->destroy_pool(pool);
> >  }
> >
> > +/**
> > + * tee_rstmem_static_pool_alloc() - Create a restricted memory manager
> > + * @paddr:   Physical address of start of pool
> > + * @size:    Size in bytes of the pool
> > + *
> > + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > + */
> > +struct tee_rstmem_pool *tee_rstmem_static_pool_alloc(phys_addr_t paddr,
> > +                                                  size_t size);
> > +
> > +/**
> > + * tee_rstmem_pool_free() - Free a restricted memory pool
> > + * @pool:    The restricted memory pool to free
> > + *
> > + * There must be no remaining restricted memory allocated from this pool
> > + * when this function is called.
> > + */
> > +static inline void tee_rstmem_pool_free(struct tee_rstmem_pool *pool)
> > +{
> > +     pool->ops->destroy_pool(pool);
> > +}
> > +
> >  /**
> >   * tee_get_drvdata() - Return driver_data pointer
> >   * @returns the driver_data pointer supplied to tee_register().
> > --
> > 2.43.0
> >


From kory.maincent at bootlin.com  Tue Mar 25 04:03:05 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Tue, 25 Mar 2025 12:03:05 +0100
Subject: [PATCH net-next v4 1/8] net: ethtool: Set the req_info->dev on
 DUMP requests for each dev
In-Reply-To: <20250324104012.367366-2-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
	<20250324104012.367366-2-maxime.chevallier@bootlin.com>
Message-ID: <20250325120305.0650bb0a@kmaincent-XPS-13-7390>

On Mon, 24 Mar 2025 11:40:03 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> There are a few netlink commands that rely on the req_info->dev field
> being populated by ethnl in their ->prepare_data() and ->fill_reply().
> 
> For a regular GET request, this will be set by ethnl_default_parse(),
> which calls ethnl_parse_header_dev_get().
> 
> In the case of a DUMP request, the ->prepare_data() and ->fill_reply()
> callbacks will be called with the req_info->dev being NULL, which can
> cause discrepancies in the behaviour between GET and DUMP results.
> 
> The main impact is that ethnl_req_get_phydev() will not find any
> phy_device, impacting :
>  - plca
>  - pse-pd
>  - stats
> 
> Some other commands rely on req_info->dev, namely :
>  - coalesce in ->fill_reply to look for an irq_moder
> 
> Although cable_test and tunnels also rely on req_info->dev being set,
> that's not a problem for these commands as :
>  - cable_test doesn't support DUMP
>  - tunnels rolls its own ->dumpit (and sets dev in the req_info).
>  - phy also has its own ->dumpit
> 
> All other commands use reply_data->dev (probably the correct way of
> doing things) and aren't facing this issue.
> 
> Simply set the dev in the req_info context when iterating to dump each
> dev.

Tested-by: Kory Maincent <kory.maincent at bootlin.com>
Reviewed-by: Kory Maincent <kory.maincent at bootlin.com>

Thank you, this fixes the PSE dump!

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From goran.radni at gmail.com  Tue Mar 25 04:04:06 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Tue, 25 Mar 2025 12:04:06 +0100
Subject: [PATCH v3 2/3] dt-bindings: arm: stm32: Document Ultratronik's Fly board DT binding
In-Reply-To: <20250325110409.2323611-1-goran.radni@gmail.com>
References: <20250325110409.2323611-1-goran.radni@gmail.com>
Message-ID: <20250325110409.2323611-3-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

This commit documents ultra-fly-sbc devicetree binding based on
STM32MP157 SoC.

Signed-off-by: Goran Ra?enovi? <goran.radni at gmail.com>
---
 Documentation/devicetree/bindings/arm/stm32/stm32.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index b6c56d4ce6b9..c1cb54ffb210 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -175,6 +175,11 @@ properties:
           - const: phytec,phycore-stm32mp157c-som
           - const: st,stm32mp157
 
+      - description: Ultratronik STM32MP1 SBC based Boards
+        items:
+          - const: ultratronik,stm32mp157c-ultra-fly-sbc
+          - const: st,stm32mp157
+
       - description: ST STM32MP257 based Boards
         items:
           - enum:
-- 
2.43.0



From goran.radni at gmail.com  Tue Mar 25 04:04:07 2025
From: goran.radni at gmail.com (=?UTF-8?q?Goran=20Ra=C4=91enovi=C4=87?=)
Date: Tue, 25 Mar 2025 12:04:07 +0100
Subject: [PATCH v3 3/3] ARM: dts: stm32: add initial support for stm32mp157-ultra-fly-sbc board
In-Reply-To: <20250325110409.2323611-1-goran.radni@gmail.com>
References: <20250325110409.2323611-1-goran.radni@gmail.com>
Message-ID: <20250325110409.2323611-4-goran.radni@gmail.com>

From: Goran Ra?enovi? <gradenovic at ultratronik.de>

Add support for Ultratronik's stm32mp157c fly board. This board embeds
a STM32MP157c SOC and 1GB of DDR3. Several connections are available on
this boards: 2*USB2.0, 1*USB2.0 MiniUSB, Debug UART, 1*UART, 1*USART,
SDcard, RJ45, ...

This patch enables basic support for a kernel boot - SD-card or eMMC.

Signed-off-by: Goran Ra?enovi? <goran.radni at gmail.com>
---
 MAINTAINERS                                   |    6 +
 arch/arm/boot/dts/st/Makefile                 |    3 +-
 .../boot/dts/st/stm32mp157c-ultra-fly-sbc.dts | 1155 +++++++++++++++++
 3 files changed, 1163 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts

diff --git a/MAINTAINERS b/MAINTAINERS
index 3b5fa8436987..11fa9f2f9f55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24341,6 +24341,12 @@ S:	Maintained
 F:	drivers/usb/common/ulpi.c
 F:	include/linux/ulpi/
 
+ULTRATRONIK BOARD SUPPORT
+M:	Goran Ra?enovi? <goran.radni at gmail.com>
+M:	B?rge Str?mpfel <boerge.struempfel at gmail.com>
+S:	Maintained
+F:	arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
+
 UNICODE SUBSYSTEM
 M:	Gabriel Krisman Bertazi <krisman at kernel.org>
 L:	linux-fsdevel at vger.kernel.org
diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile
index b7d5d305cbbe..270d1c699e1a 100644
--- a/arch/arm/boot/dts/st/Makefile
+++ b/arch/arm/boot/dts/st/Makefile
@@ -66,7 +66,8 @@ dtb-$(CONFIG_ARCH_STM32) += \
 	stm32mp157c-lxa-tac-gen2.dtb \
 	stm32mp157c-odyssey.dtb \
 	stm32mp157c-osd32mp1-red.dtb \
-	stm32mp157c-phycore-stm32mp1-3.dtb
+	stm32mp157c-phycore-stm32mp1-3.dtb \
+	stm32mp157c-ultra-fly-sbc.dtb
 dtb-$(CONFIG_ARCH_U8500) += \
 	ste-snowball.dtb \
 	ste-hrefprev60-stuib.dtb \
diff --git a/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
new file mode 100644
index 000000000000..1778f5a527ba
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp157c-ultra-fly-sbc.dts
@@ -0,0 +1,1155 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) Ultratronik GmbH 2024-2025 - All Rights Reserved
+ */
+
+/dts-v1/;
+#include "stm32mp157.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "STM STM32MP15x Ultratronik MMI_A7 board";
+	compatible = "ultratronik,stm32mp157c-ultra-fly-sbc", "st,stm32mp157";
+
+	aliases {
+		ethernet0 = &ethernet0;
+		serial0 = &uart4;
+		serial1 = &uart5;
+		serial2 = &uart7;
+		serial3 = &usart1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at c0000000 {
+		device_type = "memory";
+		reg = <0xC0000000 0x40000000>;
+	};
+
+	usb_otg_vbus: regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpioh 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		retram: retram at 38000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x38000000 0x10000>;
+			no-map;
+		};
+
+		mcuram: mcuram at 30000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x30000000 0x40000>;
+			no-map;
+		};
+
+		mcuram2: mcuram2 at 10000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10000000 0x40000>;
+			no-map;
+		};
+
+		vdev0vring0: vdev0vring0 at 10040000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10040000 0x2000>;
+			no-map;
+		};
+
+		vdev0vring1: vdev0vring1 at 10042000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10042000 0x2000>;
+			no-map;
+		};
+
+		vdev0buffer: vdev0buffer at 10044000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10044000 0x4000>;
+			no-map;
+		};
+
+		gpu_reserved: gpu at f8000000 {
+			reg = <0xf8000000 0x8000000>;
+			no-map;
+		};
+	};
+
+	leds: leds {
+		compatible = "gpio-leds";
+
+		led0{
+			label = "buzzer";
+			gpios = <&gpiof 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "none";
+		};
+
+		led1 {
+			label = "led1";
+			gpios = <&gpioa 12 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led2 {
+			label = "led2";
+			gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led3 {
+			label = "led3";
+			gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+
+		key-1 {
+			label = "KEY1";
+			gpios = <&gpiod 1 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <2>;
+		};
+
+		key-2 {
+			label = "KEY2";
+			gpios = <&gpiod 7 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+			linux,code = <3>;
+		};
+	};
+};
+
+&adc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc1_ux_ain_pins_a>;
+	vdd-supply = <&vdd>;
+	vdda-supply = <&vdd>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	adc1: adc at 0 {
+		st,min-sample-time-nsecs = <5000>;
+		st,adc-channels = <0 1 6 13>; /* ANA0 ANA1 PF12 PC3 */
+		status = "okay";
+	};
+
+	adc2: adc at 100 {
+		st,adc-channels = <0 1 12>; /* ANA0 ANA1 INT_TEMP*/
+		st,min-sample-time-nsecs = <10000>;
+		status = "okay";
+
+		channel at 12 {
+			reg = <12>;  /* Channel 12 = internal temperature sensor */
+			label = "internal_temp";
+		};
+	};
+};
+
+&dac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dac_ux_ch1_pins_a &dac_ux_ch2_pins_a>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+
+	dac1: dac at 1 {
+		status = "okay";
+	};
+
+	dac2: dac at 2 {
+		status = "okay";
+	};
+};
+
+&dts {
+	compatible = "st,stm32-thermal";
+	status = "okay";
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_ux_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_ux_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii-id";
+	max-speed = <1000>;
+	phy-handle = <&phy1>;
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy1: ethernet-phy at 1 {
+			reg = <1>;
+			interrupt-parent = <&gpiod>;
+			interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+};
+
+&gpioa {
+	gpio-line-names =
+	"#PMIC_IRQ", "", "", "", "DAC1", "DAC2", "", "",
+	"", "", "OTG_ID", "TIM1_4", "#LED1", "#LED2", "#LED3", "";
+};
+
+&gpiob {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioc {
+	gpio-line-names =
+	"#AMP_SD", "", "", "ANA5", "", "", "", "",
+	"", "", "", "", "", "PMIC_WAKEUP", "", "";
+};
+
+&gpiod {
+	gpio-line-names =
+	"#G_INT", "#TASTER1", "", "", "GPIO1", "GPIO2", "", "#TASTER2",
+	"", "", "", "", "", "", "TIM4_3", "TIM4_4";
+};
+
+&gpioe {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "PWM2", "", "", "", "", "";
+};
+
+&gpiof {
+	gpio-line-names =
+	"#SD1_CD", "SD1_WP", "BUZZER", "#DISP_POW", "BKL_POW", "#CAM_RES", "", "",
+	"", "TIM17_1N", "", "CAM_PWDN", "ANA6", "ENA_USB", "", "";
+};
+
+&gpiog {
+	gpio-line-names =
+	"#ESP_RES", "#ESP_BOOT", "GPIO3", "GPIO4", "", "", "", "",
+	"", "#TOUCH_IRQ", "", "", "", "", "", "#PCAP_RES";
+};
+
+&gpioh {
+	gpio-line-names =
+	"", "CAM_LED", "", "USB_OTG_PWR", "", "USB_OTG_OC", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioi {
+	gpio-line-names =
+	"BKL_PWM", "", "", "", "", "", "", "",
+	"#SPI_CS0", "", "", "#SPI_CS1", "", "", "", "";
+};
+
+&gpioj {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpiok {
+	gpio-line-names =
+	"", "", "", "", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpioz {
+	gpio-line-names =
+	"", "", "", "#SPI_CS2", "", "", "", "",
+	"", "", "", "", "", "", "", "";
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c1_ux_pins_a>;
+	pinctrl-1 = <&i2c1_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <100>;
+	i2c-scl-falling-time-ns = <7>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	rtc at 32 {
+		compatible = "epson,rx8900";
+		reg = <0x32>;
+		epson,vdet-disable;
+		trickle-diode-disable;
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c4_ux_pins_a>;
+	pinctrl-1 = <&i2c4_ux_pins_sleep_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	pmic: pmic at 33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupts-extended = <&exti 0 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				st,mask-reset;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <0>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <750000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO4 0>;
+			};
+
+			v1v8: ldo6 {
+				regulator-name = "v1v8";
+				regulator-min-microvolt = <1600000>;/* offset +200 mv ??? */
+				regulator-max-microvolt = <1600000>;/* real 1800000 */
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO6 0>;
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+			};
+
+			bst_out: boost {
+				regulator-name = "bst_out";
+				interrupts = <IT_OCP_BOOST 0>;
+			};
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+				interrupts = <IT_OCP_OTG 0>;
+				regulator-active-discharge = <1>;
+			 };
+
+			 vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				interrupts = <IT_OCP_SWOUT 0>;
+				regulator-active-discharge = <1>;
+			 };
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&m_can2 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&m_can2_ux_pins_a>;
+	pinctrl-1 = <&m_can2_ux_sleep_pins_a>;
+	status = "okay";
+};
+
+&pinctrl {
+
+	adc1_ux_ain_pins_a: adc1-ux-ain-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F',12, ANALOG)>, /* ADC1 in6 */
+				 <STM32_PINMUX('C', 3, ANALOG)>; /* ADC2 in13 */
+		};
+	};
+
+	dac_ux_ch1_pins_a: dac-ux-ch1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 4, ANALOG)>;
+		};
+	};
+
+	dac_ux_ch2_pins_a: dac-ux-ch2-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_a: rgmii-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, AF11)>; /* ETH_RGMII_TX_CTL */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <2>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('H', 7, AF11)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins4 {
+			pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	ethernet0_ux_rgmii_pins_sleep_a: rgmii-ux-sleep-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
+				 <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+				 <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+				 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+				 <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+				 <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
+				 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+				 <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+				 <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
+				 <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+				 <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+				 <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
+				 <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
+				 <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
+				 <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
+		};
+	};
+
+	i2c1_ux_pins_a: i2c1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c1_ux_pins_sleep_a: i2c1-1 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 14, ANALOG)>, /* I2C1_SCL */
+				 <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
+		};
+	};
+
+	m_can2_ux_pins_a: m-can2-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN1_TX */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN1_RX */
+			bias-disable;
+		};
+	};
+
+	m_can2_ux_sleep_pins_a: m-can2-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 6, ANALOG)>, /* CAN1_TX */
+				 <STM32_PINMUX('B', 5, ANALOG)>; /* CAN1_RX */
+		};
+	};
+	pwm1_ux_pins_a: pwm1-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, AF1)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, AF1)>; /* TIM1_CH2N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm1_ux_sleep_pins_a: pwm1-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A',11, ANALOG)>, /* TIM1_CH4 */
+				 <STM32_PINMUX('E',10, ANALOG)>; /* TIM1_CH2N */
+		};
+	};
+
+	pwm4_ux_pins_a: pwm4-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, AF2)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, AF2)>; /* TIM4_CH4 */
+			bias-disable;
+		};
+	};
+
+	pwm4_ux_sleep_pins_a: pwm4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('D', 14, ANALOG)>, /* TIM4_CH3 */
+				 <STM32_PINMUX('D', 15, ANALOG)>; /* TIM4_CH4 */
+		};
+	};
+
+	pwm5_ux_pins_a: pwm5-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, AF2)>; /* TIM5_CH4 */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm5_ux_sleep_pins_a: pwm5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 0, ANALOG)>; /* TIM5_CH4 */
+		};
+	};
+
+	pwm17_ux_pins_a: pwm17-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, AF1)>; /* TIM17_CH1N */
+			bias-pull-down;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+	};
+
+	pwm17_ux_sleep_pins_a: pwm17-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 9, ANALOG)>; /* TIM17_CH1N */
+		};
+	};
+
+	qspi_bk1_ux_pins_a: qspi-bk1-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, AF9)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('B',10, AF9)>; /* QSPI_BK1_NCS */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+	};
+
+	qspi_bk1_ux_sleep_pins_a: qspi-bk1-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
+				 <STM32_PINMUX('D',12, ANALOG)>, /* QSPI_BK1_IO1 */
+				 <STM32_PINMUX('F', 7, ANALOG)>, /* QSPI_BK1_IO2 */
+				 <STM32_PINMUX('F', 6, ANALOG)>, /* QSPI_BK1_IO3 */
+				 <STM32_PINMUX('B',10, ANALOG)>; /* QSPI_BK1_NCS */
+		};
+	};
+
+	qspi_clk_ux_pins_a: qspi-clk_ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, AF9)>; /* QSPI_CLK */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <3>;
+		};
+	};
+
+	qspi_clk_ux_sleep_pins_a: qspi-clk-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 7, ANALOG)>; /* QSPI_CLK */
+		};
+	};
+
+	sai2a_ux_pins_a: sai2a-0 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, AF10)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, AF10)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, AF10)>; /* SAI2_MCLK_A */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sai2a_ux_sleep_pins_a: sai2a-1 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */
+				 <STM32_PINMUX('D',11, ANALOG)>, /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, ANALOG)>, /* SAI2_FS_A */
+				 <STM32_PINMUX('E', 0, ANALOG)>; /* SAI2_MCLK_A */
+		};
+	};
+
+	sdmmc1_ux_b4_pins_a: sdmmc1-ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C',10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C',11, AF12)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_od_pins_a: sdmmc1-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, AF12)>; /* SDMMC1_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-disable;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-disable;
+		};
+	};
+
+	sdmmc1_ux_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+				 <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+				 <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+				 <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+				 <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+				 <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+		};
+	};
+
+	sdmmc2_ux_b4_pins_a: sdmmc2-ux-b4-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_od_pins_a: sdmmc2-ux-b4-od-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+			slew-rate = <2>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
+			slew-rate = <1>;
+			drive-open-drain;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_b4_sleep_pins_a: sdmmc2-ux-b4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
+				<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
+				<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
+				<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
+				<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
+				<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
+		};
+	};
+
+	sdmmc2_ux_d47_pins_a: sdmmc2-ux-d47-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-pull-up;
+		};
+	};
+
+	sdmmc2_ux_d47_sleep_pins_a: sdmmc2-ux-d47-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
+				<STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
+				<STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
+				<STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
+		};
+	};
+
+	uart4_ux_pins_a: uart4-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+	};
+
+	uart4_ux_idle_pins_a: uart4-ux-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			bias-disable;
+		};
+		};
+
+	uart4_ux_sleep_pins_a: uart4-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
+				<STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */
+		};
+	};
+
+	uart5_ux_pins_a: uart5-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX */
+			bias-disable;
+		};
+	};
+
+	uart5_ux_idle_pins_a: uart5-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>; /* UART5_TX */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX*/
+			bias-disable;
+		};
+	};
+
+	uart5_ux_sleep_pins_a: uart5-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('B', 13, ANALOG)>, /* UART5_TX */
+				 <STM32_PINMUX('B', 12, ANALOG)>; /* UART5_RX */
+		};
+	};
+
+	uart7_ux_pins_a: uart7-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+			bias-pull-up;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-pull-up;
+		};
+		pins3 {
+			pinmux = <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+	};
+
+	uart7_ux_idle_pins_a: uart7-idle-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>; /* USART7_RTS/DE */
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			bias-disable;
+		};
+	};
+
+	uart7_ux_sleep_pins_a: uart7-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* USART7_TX */
+				 <STM32_PINMUX('E', 9, AF7)>, /* USART7_RTS/DE */
+				 <STM32_PINMUX('E', 7, ANALOG)>; /* USART7_RX */
+		};
+	};
+};
+
+&pinctrl_z {
+
+	i2c4_ux_pins_a: i2c4-ux-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c4_ux_pins_sleep_a: i2c4-1 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
+				<STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
+		};
+	};
+
+	spi1_ux_pins_a: spi1-ux-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <1>;
+		};
+
+		pins2 {
+			pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
+			bias-disable;
+		};
+	};
+
+	spi1_ux_sleep_pins_a: spi1-ux-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 0, ANALOG)>, /* SPI1_SCK */
+				<STM32_PINMUX('Z', 1, ANALOG)>, /* SPI1_MISO */
+				<STM32_PINMUX('Z', 2, ANALOG)>; /* SPI1_MOSI */
+		};
+	};
+};
+
+&pwr_regulators {
+	vdd-supply = <&vdd>;
+	vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&qspi {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&qspi_clk_ux_pins_a &qspi_bk1_ux_pins_a>;
+	pinctrl-1 = <&qspi_clk_ux_sleep_pins_a &qspi_bk1_ux_sleep_pins_a>;
+	reg = <0x58003000 0x1000>, <0x70000000 0x1000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	flash0: flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <133000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&sdmmc1 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc1_ux_b4_pins_a>;
+	pinctrl-1 = <&sdmmc1_ux_b4_od_pins_a>;
+	pinctrl-2 = <&sdmmc1_ux_b4_sleep_pins_a>;
+	broken-cd;
+	st,neg-edge;
+	bus-width = <4>;
+	vmmc-supply = <&v3v3>;
+	no-1-8-v;
+	status = "okay";
+};
+
+&sdmmc2 {
+	pinctrl-names = "default", "opendrain", "sleep";
+	pinctrl-0 = <&sdmmc2_ux_b4_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-1 = <&sdmmc2_ux_b4_od_pins_a &sdmmc2_ux_d47_pins_a>;
+	pinctrl-2 = <&sdmmc2_ux_b4_sleep_pins_a &sdmmc2_ux_d47_sleep_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,neg-edge;
+	bus-width = <8>;
+	vmmc-supply = <&v3v3>;
+	vqmmc-supply = <&v3v3>;
+	mmc-ddr-3_3v;
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&spi1_ux_pins_a>;
+	pinctrl-1 = <&spi1_ux_sleep_pins_a>;
+	status = "okay";
+	cs-gpios = <&gpioi 8 0>, <&gpioi 11 0>, <&gpioz 3 0>;
+
+	flash: flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&timers1 {
+	/* spare dmas for other usage */
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm {
+		pinctrl-0 = <&pwm1_ux_pins_a>;
+		pinctrl-1 = <&pwm1_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 0 {
+		status = "okay";
+	};
+};
+
+&timers4 {
+	dmas = <&dmamux1 31 0x400 0x5>;
+	dma-names = "ch3";
+	status = "okay";
+
+	pwm4_4: pwm {
+		pinctrl-0 = <&pwm4_ux_pins_a>;
+		pinctrl-1 = <&pwm4_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+};
+
+&timers5 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm5_4: pwm {
+		pinctrl-0 = <&pwm5_ux_pins_a>;
+		pinctrl-1 = <&pwm5_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 4 {
+		status = "okay";
+	};
+};
+
+&timers17 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	status = "okay";
+
+	pwm17_4: pwm {
+		pinctrl-0 = <&pwm17_ux_pins_a>;
+		pinctrl-1 = <&pwm17_ux_sleep_pins_a>;
+		pinctrl-names = "default", "sleep";
+		status = "okay";
+	};
+
+	timer at 16 {
+		status = "okay";
+	};
+};
+
+&uart4 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
+	pinctrl-0 = <&uart4_ux_pins_a>;
+	pinctrl-1 = <&uart4_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart4_ux_idle_pins_a>;
+	pinctrl-3 = <&uart4_ux_pins_a>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart5_ux_pins_a>;
+	pinctrl-1 = <&uart5_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart5_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&uart7 {
+	/delete-property/dmas;
+	/delete-property/dma-names;
+	pinctrl-names = "default", "sleep", "idle";
+	pinctrl-0 = <&uart7_ux_pins_a>;
+	pinctrl-1 = <&uart7_ux_sleep_pins_a>;
+	pinctrl-2 = <&uart7_ux_idle_pins_a>;
+	status = "okay";
+};
+
+&usart1 {
+	/*Muxing happens in uboot*/
+	status = "okay";
+};
+
+&usbh_ehci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbh_ohci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbotg_hs {
+	phys = <&usbphyc_port1 0>;
+	phy-names = "usb2-phy";
+	vbus-supply = <&usb_otg_vbus>;
+	status = "okay";
+};
+
+&usbphyc {
+	status = "okay";
+};
+
+&usbphyc_port0 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&usbphyc_port1 {
+	phy-supply = <&vdd_usb>;
+	st,tune-hs-dc-level = <2>;
+	st,enable-fs-rftime-tuning;
+	st,enable-hs-rftime-reduction;
+	st,trim-hs-current = <15>;
+	st,trim-hs-impedance = <1>;
+	st,tune-squelch-level = <3>;
+	st,tune-hs-rx-offset = <2>;
+	st,no-lsfs-sc;
+};
+
+&vrefbuf {
+	regulator-min-microvolt = <2500000>;
+	regulator-max-microvolt = <2500000>;
+	vdda-supply = <&vdd>;
+	status = "okay";
+};
-- 
2.43.0



From suzuki.poulose at arm.com  Tue Mar 25 04:06:37 2025
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 25 Mar 2025 11:06:37 +0000
Subject: [PATCH v5 1/3] arm64: Add BBM Level 2 cpu feature
In-Reply-To: <20250325093625.55184-2-miko.lenczewski@arm.com>
References: <20250325093625.55184-1-miko.lenczewski@arm.com>
 <20250325093625.55184-2-miko.lenczewski@arm.com>
Message-ID: <5e49377e-6a3e-4a48-94c9-db06f13cffe8@arm.com>

On 25/03/2025 09:36, Miko?aj Lenczewski wrote:
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for, as well as a kernel commandline parameter to optionally
> disable BBML2 altogether.
> 
> This is a system feature as we might have a big.LITTLE architecture
> where some cores support BBML2 and some don't, but we want all cores to
> be available and BBM to default to level 0 (as opposed to having cores
> without BBML2 not coming online).
> 
> To support BBML2 in as wide a range of contexts as we can, we want not
> only the architectural guarantees that BBML2 makes, but additionally
> want BBML2 to not create TLB conflict aborts. Not causing aborts avoids
> us having to prove that no recursive faults can be induced in any path
> that uses BBML2, allowing its use for arbitrary kernel mappings.
> Support detection of such CPUs.
> 
> Signed-off-by: Miko?aj Lenczewski <miko.lenczewski at arm.com>

Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>




From angelogioacchino.delregno at collabora.com  Tue Mar 25 04:06:57 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 12:06:57 +0100
Subject: [PATCH 0/4] mmc: mtk-sd: Cleanups for register R/W
Message-ID: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>

This series adds missing register field definitions for the MSDC patch
bit registers and aggregates various register writes into just one,
greatly lowering the amount of register reads and writes especially
during the controller initialization phase, other than the tuning
phases and set_ios for mclk setting.

While this will have a performance gain, that is completely ignorable,
hence this series' only focus is a cleanup and an improvement in the
readability of the register settings (as those now have actual names,
some documenting, and no magic numbers around).

This series brings no functional differences.

AngeloGioacchino Del Regno (4):
  mmc: mtk-sd: Clarify patch bit register initialization and layout
  mmc: mtk-sd: Aggregate writes for MSDC_PATCH_BIT1/2 setup
  mmc: mtk-sd: Do single write in function msdc_new_tx_setting
  mmc: mtk-sd: Aggregate R/W for top_base iospace case where possible

 drivers/mmc/host/mtk-sd.c | 207 ++++++++++++++++++++++++--------------
 1 file changed, 132 insertions(+), 75 deletions(-)

-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Tue Mar 25 04:06:58 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 12:06:58 +0100
Subject: [PATCH 1/4] mmc: mtk-sd: Clarify patch bit register initialization and layout
In-Reply-To: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
References: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
Message-ID: <20250325110701.52623-2-angelogioacchino.delregno@collabora.com>

In preparation for cleaning up the msdc_init_hw register setting
for the patch bit registers, add the necessary definitions for
bits in the MSDC_PATCH_BIT and MSDC_PATCH_BIT1 registers and use
them in place of "magic numbers" writes during initialization.

This commit brings no functional differences.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/mmc/host/mtk-sd.c | 61 +++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 345ea91629e0..04471a7ef078 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -233,7 +234,9 @@
 
 /* MSDC_PATCH_BIT mask */
 #define MSDC_PATCH_BIT_ODDSUPP    BIT(1)	/* RW */
+#define MSDC_PATCH_BIT_DIS_WRMON  BIT(2)	/* RW */
 #define MSDC_PATCH_BIT_RD_DAT_SEL BIT(3)	/* RW */
+#define MSDC_PATCH_BIT_DESCUP_SEL BIT(6)	/* RW */
 #define MSDC_INT_DAT_LATCH_CK_SEL GENMASK(9, 7)
 #define MSDC_CKGEN_MSDC_DLY_SEL   GENMASK(14, 10)
 #define MSDC_PATCH_BIT_IODSSEL    BIT(16)	/* RW */
@@ -246,10 +249,22 @@
 #define MSDC_PATCH_BIT_SPCPUSH    BIT(29)	/* RW */
 #define MSDC_PATCH_BIT_DECRCTMO   BIT(30)	/* RW */
 
-#define MSDC_PATCH_BIT1_CMDTA     GENMASK(5, 3)    /* RW */
+/* MSDC_PATCH_BIT1 mask */
+#define MSDC_PB1_WRDAT_CRC_TACNTR GENMASK(2, 0)     /* RW */
+#define MSDC_PATCH_BIT1_CMDTA     GENMASK(5, 3)     /* RW */
 #define MSDC_PB1_BUSY_CHECK_SEL   BIT(7)    /* RW */
 #define MSDC_PATCH_BIT1_STOP_DLY  GENMASK(11, 8)    /* RW */
-
+#define MSDC_PB1_DDR_CMD_FIX_SEL  BIT(14)           /* RW */
+#define MSDC_PB1_SINGLE_BURST     BIT(16)           /* RW */
+#define MSDC_PB1_RSVD20           GENMASK(18, 17)   /* RW */
+#define MSDC_PB1_AUTO_SYNCST_CLR  BIT(19)           /* RW */
+#define MSDC_PB1_MARK_POP_WATER   BIT(20)           /* RW */
+#define MSDC_PB1_LP_DCM_EN        BIT(21)           /* RW */
+#define MSDC_PB1_RSVD3            BIT(22)           /* RW */
+#define MSDC_PB1_AHB_GDMA_HCLK    BIT(23)           /* RW */
+#define MSDC_PB1_MSDC_CLK_ENFEAT  GENMASK(31, 24)   /* RW */
+
+/* MSDC_PATCH_BIT2 mask */
 #define MSDC_PATCH_BIT2_CFGRESP   BIT(15)   /* RW */
 #define MSDC_PATCH_BIT2_CFGCRCSTS BIT(28)   /* RW */
 #define MSDC_PB2_SUPPORT_64G      BIT(1)    /* RW */
@@ -1816,7 +1831,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
 
 static void msdc_init_hw(struct msdc_host *host)
 {
-	u32 val;
+	u32 val, pb1_val;
 	u32 tune_reg = host->dev_comp->pad_tune_reg;
 	struct mmc_host *mmc = mmc_from_priv(host);
 
@@ -1869,9 +1884,43 @@ static void msdc_init_hw(struct msdc_host *host)
 	}
 	writel(0, host->base + MSDC_IOCON);
 	sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0);
-	writel(0x403c0046, host->base + MSDC_PATCH_BIT);
-	sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
-	writel(0xffff4089, host->base + MSDC_PATCH_BIT1);
+
+	/* Enable odd number support for 8-bit data bus */
+	val = MSDC_PATCH_BIT_ODDSUPP;
+
+	/* Disable SD command register write monitor */
+	val |= MSDC_PATCH_BIT_DIS_WRMON;
+
+	/* Issue transfer done interrupt after GPD update */
+	val |= MSDC_PATCH_BIT_DESCUP_SEL;
+
+	/* Extend R1B busy detection delay (in clock cycles) */
+	val |= FIELD_PREP(MSDC_PATCH_BIT_BUSYDLY, 15);
+
+	/* Enable CRC phase timeout during data write operation */
+	val |= MSDC_PATCH_BIT_DECRCTMO;
+
+	/* Set CKGEN delay to one stage */
+	val |= FIELD_PREP(MSDC_CKGEN_MSDC_DLY_SEL, 1);
+	writel(val, host->base + MSDC_PATCH_BIT);
+
+	/* Set wr data, crc status, cmd response turnaround period for UHS104 */
+	pb1_val = FIELD_PREP(MSDC_PB1_WRDAT_CRC_TACNTR, 1);
+	pb1_val |= FIELD_PREP(MSDC_PATCH_BIT1_CMDTA, 1);
+	pb1_val |= MSDC_PB1_DDR_CMD_FIX_SEL;
+
+	/* Set single burst mode, auto sync state clear, block gap stop clk */
+	pb1_val |= MSDC_PB1_SINGLE_BURST | MSDC_PB1_RSVD20 |
+		   MSDC_PB1_AUTO_SYNCST_CLR | MSDC_PB1_MARK_POP_WATER;
+
+	/* Set low power DCM, use HCLK for GDMA, use MSDC CLK for everything else */
+	pb1_val |= MSDC_PB1_LP_DCM_EN | MSDC_PB1_RSVD3 |
+		   MSDC_PB1_AHB_GDMA_HCLK | MSDC_PB1_MSDC_CLK_ENFEAT;
+
+	/* Enable R1b command busy check */
+	pb1_val |= MSDC_PB1_BUSY_CHECK_SEL;
+	writel(pb1_val, host->base + MSDC_PATCH_BIT1);
+
 	sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
 
 	if (host->dev_comp->stop_clk_fix) {
-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Tue Mar 25 04:06:59 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 12:06:59 +0100
Subject: [PATCH 2/4] mmc: mtk-sd: Aggregate writes for MSDC_PATCH_BIT1/2 setup
In-Reply-To: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
References: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
Message-ID: <20250325110701.52623-3-angelogioacchino.delregno@collabora.com>

Instead of continuously reading and writing to the patch bit 1/2
registers, prepare the final values to write to those and write
just once per register during the setup phase.

This makes the driver slightly smaller and also slightly improves
the execution time of the msdc_init_hw function, called not only
at probe time, but also when resuming from system suspend.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/mmc/host/mtk-sd.c | 85 +++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 40 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 04471a7ef078..dd3f7468d32c 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -1831,7 +1831,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
 
 static void msdc_init_hw(struct msdc_host *host)
 {
-	u32 val, pb1_val;
+	u32 val, pb1_val, pb2_val;
 	u32 tune_reg = host->dev_comp->pad_tune_reg;
 	struct mmc_host *mmc = mmc_from_priv(host);
 
@@ -1885,6 +1885,13 @@ static void msdc_init_hw(struct msdc_host *host)
 	writel(0, host->base + MSDC_IOCON);
 	sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0);
 
+	/*
+	 * Patch bit 0 and 1 are completely rewritten, but for patch bit 2
+	 * defaults are retained and, if necessary, only some bits are fixed
+	 * up: read the PB2 register here for later usage in this function.
+	 */
+	pb2_val = readl(host->base + MSDC_PATCH_BIT2);
+
 	/* Enable odd number support for 8-bit data bus */
 	val = MSDC_PATCH_BIT_ODDSUPP;
 
@@ -1902,6 +1909,8 @@ static void msdc_init_hw(struct msdc_host *host)
 
 	/* Set CKGEN delay to one stage */
 	val |= FIELD_PREP(MSDC_CKGEN_MSDC_DLY_SEL, 1);
+
+	/* First MSDC_PATCH_BIT setup is done: pull the trigger! */
 	writel(val, host->base + MSDC_PATCH_BIT);
 
 	/* Set wr data, crc status, cmd response turnaround period for UHS104 */
@@ -1917,58 +1926,54 @@ static void msdc_init_hw(struct msdc_host *host)
 	pb1_val |= MSDC_PB1_LP_DCM_EN | MSDC_PB1_RSVD3 |
 		   MSDC_PB1_AHB_GDMA_HCLK | MSDC_PB1_MSDC_CLK_ENFEAT;
 
-	/* Enable R1b command busy check */
-	pb1_val |= MSDC_PB1_BUSY_CHECK_SEL;
-	writel(pb1_val, host->base + MSDC_PATCH_BIT1);
-
-	sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
+	/* If needed, enable R1b command busy check at controller init time */
+	if (!host->dev_comp->busy_check)
+		pb1_val |= MSDC_PB1_BUSY_CHECK_SEL;
 
 	if (host->dev_comp->stop_clk_fix) {
 		if (host->dev_comp->stop_dly_sel)
-			sdr_set_field(host->base + MSDC_PATCH_BIT1,
-				      MSDC_PATCH_BIT1_STOP_DLY,
-				      host->dev_comp->stop_dly_sel);
+			pb1_val |= FIELD_PREP(MSDC_PATCH_BIT1_STOP_DLY,
+					      host->dev_comp->stop_dly_sel);
 
-		if (host->dev_comp->pop_en_cnt)
-			sdr_set_field(host->base + MSDC_PATCH_BIT2,
-				      MSDC_PB2_POP_EN_CNT,
-				      host->dev_comp->pop_en_cnt);
+		if (host->dev_comp->pop_en_cnt) {
+			pb2_val &= ~MSDC_PB2_POP_EN_CNT;
+			pb2_val |= FIELD_PREP(MSDC_PB2_POP_EN_CNT,
+					      host->dev_comp->pop_en_cnt);
+		}
 
-		sdr_clr_bits(host->base + SDC_FIFO_CFG,
-			     SDC_FIFO_CFG_WRVALIDSEL);
-		sdr_clr_bits(host->base + SDC_FIFO_CFG,
-			     SDC_FIFO_CFG_RDVALIDSEL);
+		sdr_clr_bits(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_WRVALIDSEL);
+		sdr_clr_bits(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_RDVALIDSEL);
 	}
 
-	if (host->dev_comp->busy_check)
-		sdr_clr_bits(host->base + MSDC_PATCH_BIT1, BIT(7));
-
 	if (host->dev_comp->async_fifo) {
-		sdr_set_field(host->base + MSDC_PATCH_BIT2,
-			      MSDC_PB2_RESPWAIT, 3);
-		if (host->dev_comp->enhance_rx) {
-			if (host->top_base)
-				sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
-					     SDC_RX_ENH_EN);
-			else
-				sdr_set_bits(host->base + SDC_ADV_CFG0,
-					     SDC_RX_ENHANCE_EN);
+		/* Set CMD response timeout multiplier to 65 + (16 * 3) cycles */
+		pb2_val &= ~MSDC_PB2_RESPWAIT;
+		pb2_val |= FIELD_PREP(MSDC_PB2_RESPWAIT, 3);
+
+		/* eMMC4.5: Select async FIFO path for CMD resp and CRC status */
+		pb2_val &= ~MSDC_PATCH_BIT2_CFGRESP;
+		pb2_val |= MSDC_PATCH_BIT2_CFGCRCSTS;
+
+		if (!host->dev_comp->enhance_rx) {
+			/* eMMC4.5: Delay 2T for CMD resp and CRC status EN signals */
+			pb2_val &= ~(MSDC_PB2_RESPSTSENSEL | MSDC_PB2_CRCSTSENSEL);
+			pb2_val |= FIELD_PREP(MSDC_PB2_RESPSTSENSEL, 2);
+			pb2_val |= FIELD_PREP(MSDC_PB2_CRCSTSENSEL, 2);
+		} else if (host->top_base) {
+			sdr_set_bits(host->top_base + EMMC_TOP_CONTROL, SDC_RX_ENH_EN);
 		} else {
-			sdr_set_field(host->base + MSDC_PATCH_BIT2,
-				      MSDC_PB2_RESPSTSENSEL, 2);
-			sdr_set_field(host->base + MSDC_PATCH_BIT2,
-				      MSDC_PB2_CRCSTSENSEL, 2);
+			sdr_set_bits(host->base + SDC_ADV_CFG0, SDC_RX_ENHANCE_EN);
 		}
-		/* use async fifo, then no need tune internal delay */
-		sdr_clr_bits(host->base + MSDC_PATCH_BIT2,
-			     MSDC_PATCH_BIT2_CFGRESP);
-		sdr_set_bits(host->base + MSDC_PATCH_BIT2,
-			     MSDC_PATCH_BIT2_CFGCRCSTS);
 	}
 
 	if (host->dev_comp->support_64g)
-		sdr_set_bits(host->base + MSDC_PATCH_BIT2,
-			     MSDC_PB2_SUPPORT_64G);
+		pb2_val |= MSDC_PB2_SUPPORT_64G;
+
+	/* Patch Bit 1/2 setup is done: pull the trigger! */
+	writel(pb1_val, host->base + MSDC_PATCH_BIT1);
+	writel(pb2_val, host->base + MSDC_PATCH_BIT2);
+	sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
+
 	if (host->dev_comp->data_tune) {
 		if (host->top_base) {
 			sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Tue Mar 25 04:07:00 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 12:07:00 +0100
Subject: [PATCH 3/4] mmc: mtk-sd: Do single write in function msdc_new_tx_setting
In-Reply-To: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
References: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
Message-ID: <20250325110701.52623-4-angelogioacchino.delregno@collabora.com>

Instead of reading and writing the LOOP_TEST_CONTROL register for
each set or cleared bit, read it once, modify the contents in a
local variable, and then write once.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/mmc/host/mtk-sd.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index dd3f7468d32c..e9e84b9a65f0 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -942,15 +942,15 @@ static int msdc_ungate_clock(struct msdc_host *host)
 
 static void msdc_new_tx_setting(struct msdc_host *host)
 {
+	u32 val;
+
 	if (!host->top_base)
 		return;
 
-	sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
-		     TEST_LOOP_DSCLK_MUX_SEL);
-	sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
-		     TEST_LOOP_LATCH_MUX_SEL);
-	sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL,
-		     TEST_HS400_CMD_LOOP_MUX_SEL);
+	val = readl(host->top_base + LOOP_TEST_CONTROL);
+	val |= TEST_LOOP_DSCLK_MUX_SEL;
+	val |= TEST_LOOP_LATCH_MUX_SEL;
+	val &= ~TEST_HS400_CMD_LOOP_MUX_SEL;
 
 	switch (host->timing) {
 	case MMC_TIMING_LEGACY:
@@ -960,19 +960,18 @@ static void msdc_new_tx_setting(struct msdc_host *host)
 	case MMC_TIMING_UHS_SDR25:
 	case MMC_TIMING_UHS_DDR50:
 	case MMC_TIMING_MMC_DDR52:
-		sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL,
-			     LOOP_EN_SEL_CLK);
+		val &= ~LOOP_EN_SEL_CLK;
 		break;
 	case MMC_TIMING_UHS_SDR50:
 	case MMC_TIMING_UHS_SDR104:
 	case MMC_TIMING_MMC_HS200:
 	case MMC_TIMING_MMC_HS400:
-		sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
-			     LOOP_EN_SEL_CLK);
+		val |= LOOP_EN_SEL_CLK;
 		break;
 	default:
 		break;
 	}
+	writel(val, host->top_base + LOOP_TEST_CONTROL);
 }
 
 static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
-- 
2.48.1



From angelogioacchino.delregno at collabora.com  Tue Mar 25 04:07:01 2025
From: angelogioacchino.delregno at collabora.com (AngeloGioacchino Del Regno)
Date: Tue, 25 Mar 2025 12:07:01 +0100
Subject: [PATCH 4/4] mmc: mtk-sd: Aggregate R/W for top_base iospace case where possible
In-Reply-To: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
References: <20250325110701.52623-1-angelogioacchino.delregno@collabora.com>
Message-ID: <20250325110701.52623-5-angelogioacchino.delregno@collabora.com>

In case the controller uses the top_base iospace, most register
read/writes can be changed from multiple RWs to a single read
and a single write.

Where possible, and where it makes sense, aggregate the multiple
reads and writes to just one.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
 drivers/mmc/host/mtk-sd.c | 52 +++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index e9e84b9a65f0..ceeae1aeac94 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -1975,18 +1975,19 @@ static void msdc_init_hw(struct msdc_host *host)
 
 	if (host->dev_comp->data_tune) {
 		if (host->top_base) {
-			sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
-				     PAD_DAT_RD_RXDLY_SEL);
-			sdr_clr_bits(host->top_base + EMMC_TOP_CONTROL,
-				     DATA_K_VALUE_SEL);
-			sdr_set_bits(host->top_base + EMMC_TOP_CMD,
-				     PAD_CMD_RD_RXDLY_SEL);
+			u32 top_ctl_val = readl(host->top_base + EMMC_TOP_CONTROL);
+			u32 top_cmd_val = readl(host->top_base + EMMC_TOP_CMD);
+
+			top_cmd_val |= PAD_CMD_RD_RXDLY_SEL;
+			top_ctl_val |= PAD_DAT_RD_RXDLY_SEL;
+			top_ctl_val &= ~DATA_K_VALUE_SEL;
 			if (host->tuning_step > PAD_DELAY_HALF) {
-				sdr_set_bits(host->top_base + EMMC_TOP_CONTROL,
-					     PAD_DAT_RD_RXDLY2_SEL);
-				sdr_set_bits(host->top_base + EMMC_TOP_CMD,
-					     PAD_CMD_RD_RXDLY2_SEL);
+				top_cmd_val |= PAD_CMD_RD_RXDLY2_SEL;
+				top_ctl_val |= PAD_DAT_RD_RXDLY2_SEL;
 			}
+
+			writel(top_ctl_val, host->top_base + EMMC_TOP_CONTROL);
+			writel(top_cmd_val, host->top_base + EMMC_TOP_CMD);
 		} else {
 			sdr_set_bits(host->base + tune_reg,
 				     MSDC_PAD_TUNE_RD_SEL |
@@ -2196,15 +2197,17 @@ static inline void msdc_set_cmd_delay(struct msdc_host *host, u32 value)
 	u32 tune_reg = host->dev_comp->pad_tune_reg;
 
 	if (host->top_base) {
+		u32 regval = readl(host->top_base + EMMC_TOP_CMD);
+
+		regval &= ~(PAD_CMD_RXDLY | PAD_CMD_RXDLY2);
+
 		if (value < PAD_DELAY_HALF) {
-			sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY, value);
-			sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY2, 0);
+			regval |= FIELD_PREP(PAD_CMD_RXDLY, value);
 		} else {
-			sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY,
-				      PAD_DELAY_HALF - 1);
-			sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY2,
-				      value - PAD_DELAY_HALF);
+			regval |= FIELD_PREP(PAD_CMD_RXDLY, PAD_DELAY_HALF - 1);
+			regval |= FIELD_PREP(PAD_CMD_RXDLY2, value - PAD_DELAY_HALF);
 		}
+		writel(regval, host->top_base + EMMC_TOP_CMD);
 	} else {
 		if (value < PAD_DELAY_HALF) {
 			sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY, value);
@@ -2224,17 +2227,18 @@ static inline void msdc_set_data_delay(struct msdc_host *host, u32 value)
 	u32 tune_reg = host->dev_comp->pad_tune_reg;
 
 	if (host->top_base) {
+		u32 regval = readl(host->top_base + EMMC_TOP_CONTROL);
+
+		regval &= ~(PAD_DAT_RD_RXDLY | PAD_DAT_RD_RXDLY2);
+
 		if (value < PAD_DELAY_HALF) {
-			sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
-				      PAD_DAT_RD_RXDLY, value);
-			sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
-				      PAD_DAT_RD_RXDLY2, 0);
+			regval |= FIELD_PREP(PAD_DAT_RD_RXDLY, value);
+			regval |= FIELD_PREP(PAD_DAT_RD_RXDLY2, value);
 		} else {
-			sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
-				      PAD_DAT_RD_RXDLY, PAD_DELAY_HALF - 1);
-			sdr_set_field(host->top_base + EMMC_TOP_CONTROL,
-				      PAD_DAT_RD_RXDLY2, value - PAD_DELAY_HALF);
+			regval |= FIELD_PREP(PAD_DAT_RD_RXDLY, PAD_DELAY_HALF - 1);
+			regval |= FIELD_PREP(PAD_DAT_RD_RXDLY2, value - PAD_DELAY_HALF);
 		}
+		writel(regval, host->top_base + EMMC_TOP_CONTROL);
 	} else {
 		if (value < PAD_DELAY_HALF) {
 			sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_DATRRDLY, value);
-- 
2.48.1



From maz at kernel.org  Tue Mar 25 04:02:30 2025
From: maz at kernel.org (Marc Zyngier)
Date: Tue, 25 Mar 2025 11:02:30 +0000
Subject: [PATCH v2 01/13] dt-bindings: pci: apple,pcie: Add t6020 compatible string
In-Reply-To: <87iknx75at.fsf@bloch.sibelius.xs4all.nl>
References: <20250325102610.2073863-1-maz@kernel.org>
	<20250325102610.2073863-2-maz@kernel.org>
	<87iknx75at.fsf@bloch.sibelius.xs4all.nl>
Message-ID: <864izhmkzd.wl-maz@kernel.org>

Hi Mark,

On Tue, 25 Mar 2025 10:50:18 +0000,
Mark Kettenis <mark.kettenis at xs4all.nl> wrote:
> 
> > From: Marc Zyngier <maz at kernel.org>
> > Date: Tue, 25 Mar 2025 10:25:58 +0000
> 
> Hi Marc,
> 
> Sorry for not spotting this in the earlier versions, but:

No worries -- I expected issues in that department.

>
> > From: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> > 
> > t6020 adds some register ranges compared to t8103, so requires
> > a new compatible as well as the new PHY registers themselves.
> > 
> > Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
> > [maz: added PHY registers]
> > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > ---
> >  Documentation/devicetree/bindings/pci/apple,pcie.yaml | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/pci/apple,pcie.yaml b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> > index c8775f9cb0713..77554899b9420 100644
> > --- a/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> > +++ b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
> > @@ -17,6 +17,10 @@ description: |
> >    implements its root ports.  But the ATU found on most DesignWare
> >    PCIe host bridges is absent.
> >  
> > +  On systems derived from T602x, the PHY registers are in a region
> > +  separate from the port registers. In that case, there is one PHY
> > +  register range per port register range.
> > +
> >    All root ports share a single ECAM space, but separate GPIOs are
> >    used to take the PCI devices on those ports out of reset.  Therefore
> >    the standard "reset-gpios" and "max-link-speed" properties appear on
> > @@ -35,11 +39,12 @@ properties:
> >            - apple,t8103-pcie
> >            - apple,t8112-pcie
> >            - apple,t6000-pcie
> > +          - apple,t6020-pcie
> >        - const: apple,pcie
> 
> Since the T602x PCIe controller has a different register layout, it
> isn't compatible with the others, so it should not include the
> "apple,pcie" compatible.  The "downstream" device trees for
> T602x-based devices do indeed not list "apple,pcie" as a compatible.
> So I think this needs to be written as:
> 
>   compatible:
>     oneOf:
>       - items:
>           - enum:
>               - apple,t8103-pcie
>               - apple,t8112-pcie
>               - apple,t6000-pcie
>           - const: apple,pcie
>       - const: apple,t6020-pcie

Ah, indeed, that's a good point. Thanks for that.

Whilst I have your attention, how about my question below:

>
> >  
> >    reg:
> >      minItems: 3
> > -    maxItems: 6
> > +    maxItems: 10
> >  
> >    reg-names:
> >      minItems: 3
> > @@ -50,6 +55,10 @@ properties:
> >        - const: port1
> >        - const: port2
> >        - const: port3
> > +      - const: phy0
> > +      - const: phy1
> > +      - const: phy2
> > +      - const: phy3

Do we need to make this t6020 specific?

Obviously, separate PHY registers do not make much sense before t6020,
but I couldn't find a way to describe that. I don't even know if
that's a desirable outcome.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


From jens.wiklander at linaro.org  Tue Mar 25 04:17:20 2025
From: jens.wiklander at linaro.org (Jens Wiklander)
Date: Tue, 25 Mar 2025 12:17:20 +0100
Subject: [PATCH v6 06/10] tee: new ioctl to a register tee_shm from a
 dmabuf file descriptor
In-Reply-To: <Z-JSNoALMOoyfOXu@sumit-X1>
References: <20250305130634.1850178-1-jens.wiklander@linaro.org>
 <20250305130634.1850178-7-jens.wiklander@linaro.org> <Z-JSNoALMOoyfOXu@sumit-X1>
Message-ID: <CAHUa44FMou3O+2MeRtEe+WDjoGdB_3U56Z0RUpFLMFR1ebTkKQ@mail.gmail.com>

Hi Sumit,

On Tue, Mar 25, 2025 at 7:50?AM Sumit Garg <sumit.garg at kernel.org> wrote:
>
> Hi Jens,
>
> On Wed, Mar 05, 2025 at 02:04:12PM +0100, Jens Wiklander wrote:
> > From: Etienne Carriere <etienne.carriere at linaro.org>
> >
> > Enable userspace to create a tee_shm object that refers to a dmabuf
> > reference.
> >
> > Userspace registers the dmabuf file descriptor as in a tee_shm object.
> > The registration is completed with a tee_shm file descriptor returned to
> > userspace.
> >
> > Userspace is free to close the dmabuf file descriptor now since all the
> > resources are now held via the tee_shm object.
> >
> > Closing the tee_shm file descriptor will release all resources used by the
> > tee_shm object.
> >
> > This change only support dmabuf references that relates to physically
> > contiguous memory buffers.
> >
> > New tee_shm flag to identify tee_shm objects built from a registered
> > dmabuf, TEE_SHM_DMA_BUF.
> >
> > Signed-off-by: Etienne Carriere <etienne.carriere at linaro.org>
> > Signed-off-by: Olivier Masse <olivier.masse at nxp.com>
> > Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
> > ---
> >  drivers/tee/tee_core.c    | 145 ++++++++++++++++++++++++++-----------
> >  drivers/tee/tee_private.h |   1 +
> >  drivers/tee/tee_shm.c     | 146 ++++++++++++++++++++++++++++++++++++--
> >  include/linux/tee_core.h  |   1 +
> >  include/linux/tee_drv.h   |  10 +++
> >  include/uapi/linux/tee.h  |  29 ++++++++
> >  6 files changed, 288 insertions(+), 44 deletions(-)
> >
>
> I am still trying to find if we really need a separate IOCTL to register
> DMA heap with TEE subsystem. Can't we initialize tee_shm as a member of
> struct tee_heap_buffer in tee_dma_heap_alloc() where the allocation
> happens?

No, that's not possible since we don't have a tee_context availble so
we can't assign an ID that userspace can use for this shm object.

We could add new attribute types TEE_IOCTL_PARAM_ATTR_TYPE_MEMFD_*,
but it's a bit more complicated than that since we'd also need to
update for the life cycle.


> We can always find a reference back to tee_shm object from DMA
> buffer.

Yes

Cheers,
Jens

>
> -Sumit
>
> > diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> > index 685afcaa3ea1..3a71643766d5 100644
> > --- a/drivers/tee/tee_core.c
> > +++ b/drivers/tee/tee_core.c
> > @@ -353,6 +353,103 @@ tee_ioctl_shm_register(struct tee_context *ctx,
> >       return ret;
> >  }
> >
> > +static int
> > +tee_ioctl_shm_register_fd(struct tee_context *ctx,
> > +                       struct tee_ioctl_shm_register_fd_data __user *udata)
> > +{
> > +     struct tee_ioctl_shm_register_fd_data data;
> > +     struct tee_shm *shm;
> > +     long ret;
> > +
> > +     if (copy_from_user(&data, udata, sizeof(data)))
> > +             return -EFAULT;
> > +
> > +     /* Currently no input flags are supported */
> > +     if (data.flags)
> > +             return -EINVAL;
> > +
> > +     shm = tee_shm_register_fd(ctx, data.fd);
> > +     if (IS_ERR(shm))
> > +             return -EINVAL;
> > +
> > +     data.id = shm->id;
> > +     data.flags = shm->flags;
> > +     data.size = shm->size;
> > +
> > +     if (copy_to_user(udata, &data, sizeof(data)))
> > +             ret = -EFAULT;
> > +     else
> > +             ret = tee_shm_get_fd(shm);
> > +
> > +     /*
> > +      * When user space closes the file descriptor the shared memory
> > +      * should be freed or if tee_shm_get_fd() failed then it will
> > +      * be freed immediately.
> > +      */
> > +     tee_shm_put(shm);
> > +     return ret;
> > +}
> > +
> > +static int param_from_user_memref(struct tee_context *ctx,
> > +                               struct tee_param_memref *memref,
> > +                               struct tee_ioctl_param *ip)
> > +{
> > +     struct tee_shm *shm;
> > +     size_t offs = 0;
> > +
> > +     /*
> > +      * If a NULL pointer is passed to a TA in the TEE,
> > +      * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
> > +      * indicating a NULL memory reference.
> > +      */
> > +     if (ip->c != TEE_MEMREF_NULL) {
> > +             /*
> > +              * If we fail to get a pointer to a shared
> > +              * memory object (and increase the ref count)
> > +              * from an identifier we return an error. All
> > +              * pointers that has been added in params have
> > +              * an increased ref count. It's the callers
> > +              * responibility to do tee_shm_put() on all
> > +              * resolved pointers.
> > +              */
> > +             shm = tee_shm_get_from_id(ctx, ip->c);
> > +             if (IS_ERR(shm))
> > +                     return PTR_ERR(shm);
> > +
> > +             /*
> > +              * Ensure offset + size does not overflow
> > +              * offset and does not overflow the size of
> > +              * the referred shared memory object.
> > +              */
> > +             if ((ip->a + ip->b) < ip->a ||
> > +                 (ip->a + ip->b) > shm->size) {
> > +                     tee_shm_put(shm);
> > +                     return -EINVAL;
> > +             }
> > +
> > +             if (shm->flags & TEE_SHM_DMA_BUF) {
> > +                     struct tee_shm *parent_shm;
> > +
> > +                     parent_shm = tee_shm_get_parent_shm(shm, &offs);
> > +                     if (parent_shm) {
> > +                             tee_shm_put(shm);
> > +                             shm = parent_shm;
> > +                     }
> > +             }
> > +     } else if (ctx->cap_memref_null) {
> > +             /* Pass NULL pointer to OP-TEE */
> > +             shm = NULL;
> > +     } else {
> > +             return -EINVAL;
> > +     }
> > +
> > +     memref->shm_offs = ip->a + offs;
> > +     memref->size = ip->b;
> > +     memref->shm = shm;
> > +
> > +     return 0;
> > +}
> > +
> >  static int params_from_user(struct tee_context *ctx, struct tee_param *params,
> >                           size_t num_params,
> >                           struct tee_ioctl_param __user *uparams)
> > @@ -360,8 +457,8 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
> >       size_t n;
> >
> >       for (n = 0; n < num_params; n++) {
> > -             struct tee_shm *shm;
> >               struct tee_ioctl_param ip;
> > +             int rc;
> >
> >               if (copy_from_user(&ip, uparams + n, sizeof(ip)))
> >                       return -EFAULT;
> > @@ -384,45 +481,10 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params,
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> >               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
> > -                     /*
> > -                      * If a NULL pointer is passed to a TA in the TEE,
> > -                      * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL
> > -                      * indicating a NULL memory reference.
> > -                      */
> > -                     if (ip.c != TEE_MEMREF_NULL) {
> > -                             /*
> > -                              * If we fail to get a pointer to a shared
> > -                              * memory object (and increase the ref count)
> > -                              * from an identifier we return an error. All
> > -                              * pointers that has been added in params have
> > -                              * an increased ref count. It's the callers
> > -                              * responibility to do tee_shm_put() on all
> > -                              * resolved pointers.
> > -                              */
> > -                             shm = tee_shm_get_from_id(ctx, ip.c);
> > -                             if (IS_ERR(shm))
> > -                                     return PTR_ERR(shm);
> > -
> > -                             /*
> > -                              * Ensure offset + size does not overflow
> > -                              * offset and does not overflow the size of
> > -                              * the referred shared memory object.
> > -                              */
> > -                             if ((ip.a + ip.b) < ip.a ||
> > -                                 (ip.a + ip.b) > shm->size) {
> > -                                     tee_shm_put(shm);
> > -                                     return -EINVAL;
> > -                             }
> > -                     } else if (ctx->cap_memref_null) {
> > -                             /* Pass NULL pointer to OP-TEE */
> > -                             shm = NULL;
> > -                     } else {
> > -                             return -EINVAL;
> > -                     }
> > -
> > -                     params[n].u.memref.shm_offs = ip.a;
> > -                     params[n].u.memref.size = ip.b;
> > -                     params[n].u.memref.shm = shm;
> > +                     rc = param_from_user_memref(ctx, &params[n].u.memref,
> > +                                                 &ip);
> > +                     if (rc)
> > +                             return rc;
> >                       break;
> >               default:
> >                       /* Unknown attribute */
> > @@ -827,6 +889,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> >               return tee_ioctl_shm_alloc(ctx, uarg);
> >       case TEE_IOC_SHM_REGISTER:
> >               return tee_ioctl_shm_register(ctx, uarg);
> > +     case TEE_IOC_SHM_REGISTER_FD:
> > +             return tee_ioctl_shm_register_fd(ctx, uarg);
> >       case TEE_IOC_OPEN_SESSION:
> >               return tee_ioctl_open_session(ctx, uarg);
> >       case TEE_IOC_INVOKE:
> > @@ -1288,3 +1352,4 @@ MODULE_AUTHOR("Linaro");
> >  MODULE_DESCRIPTION("TEE Driver");
> >  MODULE_VERSION("1.0");
> >  MODULE_LICENSE("GPL v2");
> > +MODULE_IMPORT_NS("DMA_BUF");
> > diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> > index 6c6ff5d5eed2..aad7f6c7e0f0 100644
> > --- a/drivers/tee/tee_private.h
> > +++ b/drivers/tee/tee_private.h
> > @@ -24,6 +24,7 @@ void teedev_ctx_put(struct tee_context *ctx);
> >  struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
> >  struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> >                                         unsigned long addr, size_t length);
> > +struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs);
> >
> >  int tee_heap_update_from_dma_buf(struct tee_device *teedev,
> >                                struct dma_buf *dmabuf, size_t *offset,
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index daf6e5cfd59a..8b79918468b5 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -4,6 +4,7 @@
> >   */
> >  #include <linux/anon_inodes.h>
> >  #include <linux/device.h>
> > +#include <linux/dma-buf.h>
> >  #include <linux/idr.h>
> >  #include <linux/io.h>
> >  #include <linux/mm.h>
> > @@ -15,6 +16,16 @@
> >  #include <linux/highmem.h>
> >  #include "tee_private.h"
> >
> > +/* extra references appended to shm object for registered shared memory */
> > +struct tee_shm_dmabuf_ref {
> > +     struct tee_shm shm;
> > +     size_t offset;
> > +     struct dma_buf *dmabuf;
> > +     struct dma_buf_attachment *attach;
> > +     struct sg_table *sgt;
> > +     struct tee_shm *parent_shm;
> > +};
> > +
> >  static void shm_put_kernel_pages(struct page **pages, size_t page_count)
> >  {
> >       size_t n;
> > @@ -45,7 +56,23 @@ static void release_registered_pages(struct tee_shm *shm)
> >
> >  static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> >  {
> > -     if (shm->flags & TEE_SHM_POOL) {
> > +     struct tee_shm *parent_shm = NULL;
> > +     void *p = shm;
> > +
> > +     if (shm->flags & TEE_SHM_DMA_BUF) {
> > +             struct tee_shm_dmabuf_ref *ref;
> > +
> > +             ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
> > +             parent_shm = ref->parent_shm;
> > +             p = ref;
> > +             if (ref->attach) {
> > +                     dma_buf_unmap_attachment(ref->attach, ref->sgt,
> > +                                              DMA_BIDIRECTIONAL);
> > +
> > +                     dma_buf_detach(ref->dmabuf, ref->attach);
> > +             }
> > +             dma_buf_put(ref->dmabuf);
> > +     } else if (shm->flags & TEE_SHM_POOL) {
> >               teedev->pool->ops->free(teedev->pool, shm);
> >       } else if (shm->flags & TEE_SHM_DYNAMIC) {
> >               int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
> > @@ -57,9 +84,10 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> >               release_registered_pages(shm);
> >       }
> >
> > -     teedev_ctx_put(shm->ctx);
> > +     if (shm->ctx)
> > +             teedev_ctx_put(shm->ctx);
> >
> > -     kfree(shm);
> > +     kfree(p);
> >
> >       tee_device_put(teedev);
> >  }
> > @@ -169,7 +197,7 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> >   * tee_client_invoke_func(). The memory allocated is later freed with a
> >   * call to tee_shm_free().
> >   *
> > - * @returns a pointer to 'struct tee_shm'
> > + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
> >   */
> >  struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> >  {
> > @@ -179,6 +207,116 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> >  }
> >  EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
> >
> > +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
> > +{
> > +     struct tee_shm_dmabuf_ref *ref;
> > +     int rc;
> > +
> > +     if (!tee_device_get(ctx->teedev))
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     teedev_ctx_get(ctx);
> > +
> > +     ref = kzalloc(sizeof(*ref), GFP_KERNEL);
> > +     if (!ref) {
> > +             rc = -ENOMEM;
> > +             goto err_put_tee;
> > +     }
> > +
> > +     refcount_set(&ref->shm.refcount, 1);
> > +     ref->shm.ctx = ctx;
> > +     ref->shm.id = -1;
> > +     ref->shm.flags = TEE_SHM_DMA_BUF;
> > +
> > +     ref->dmabuf = dma_buf_get(fd);
> > +     if (IS_ERR(ref->dmabuf)) {
> > +             rc = PTR_ERR(ref->dmabuf);
> > +             goto err_kfree_ref;
> > +     }
> > +
> > +     rc = tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf,
> > +                                       &ref->offset, &ref->shm,
> > +                                       &ref->parent_shm);
> > +     if (!rc)
> > +             goto out;
> > +     if (rc != -EINVAL)
> > +             goto err_put_dmabuf;
> > +
> > +     ref->attach = dma_buf_attach(ref->dmabuf, &ctx->teedev->dev);
> > +     if (IS_ERR(ref->attach)) {
> > +             rc = PTR_ERR(ref->attach);
> > +             goto err_put_dmabuf;
> > +     }
> > +
> > +     ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
> > +     if (IS_ERR(ref->sgt)) {
> > +             rc = PTR_ERR(ref->sgt);
> > +             goto err_detach;
> > +     }
> > +
> > +     if (sg_nents(ref->sgt->sgl) != 1) {
> > +             rc = PTR_ERR(ref->sgt->sgl);
> > +             goto err_unmap_attachement;
> > +     }
> > +
> > +     ref->shm.paddr = page_to_phys(sg_page(ref->sgt->sgl));
> > +     ref->shm.size = ref->sgt->sgl->length;
> > +
> > +out:
> > +     mutex_lock(&ref->shm.ctx->teedev->mutex);
> > +     ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
> > +                             1, 0, GFP_KERNEL);
> > +     mutex_unlock(&ref->shm.ctx->teedev->mutex);
> > +     if (ref->shm.id < 0) {
> > +             rc = ref->shm.id;
> > +             if (ref->attach)
> > +                     goto err_unmap_attachement;
> > +             goto err_put_dmabuf;
> > +     }
> > +
> > +     return &ref->shm;
> > +
> > +err_unmap_attachement:
> > +     dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL);
> > +err_detach:
> > +     dma_buf_detach(ref->dmabuf, ref->attach);
> > +err_put_dmabuf:
> > +     dma_buf_put(ref->dmabuf);
> > +err_kfree_ref:
> > +     kfree(ref);
> > +err_put_tee:
> > +     teedev_ctx_put(ctx);
> > +     tee_device_put(ctx->teedev);
> > +
> > +     return ERR_PTR(rc);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_shm_register_fd);
> > +
> > +struct tee_shm *tee_shm_get_parent_shm(struct tee_shm *shm, size_t *offs)
> > +{
> > +     struct tee_shm *parent_shm = NULL;
> > +
> > +     if (shm->flags & TEE_SHM_DMA_BUF) {
> > +             struct tee_shm_dmabuf_ref *ref;
> > +
> > +             ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
> > +             if (ref->parent_shm) {
> > +                     /*
> > +                      * the shm already has one reference to
> > +                      * ref->parent_shm so we should be clear of 0.
> > +                      * We're getting another reference since the caller
> > +                      * of this function expects to put the returned
> > +                      * parent_shm when it's done with it.
> > +                      */
> > +                     parent_shm = ref->parent_shm;
> > +                     refcount_inc(&parent_shm->refcount);
> > +                     *offs = ref->offset;
> > +             }
> > +     }
> > +
> > +     return parent_shm;
> > +}
> > +
> >  /**
> >   * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared
> >   *                         kernel buffer
> > diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
> > index 16ef078247ae..6bd833b6d0e1 100644
> > --- a/include/linux/tee_core.h
> > +++ b/include/linux/tee_core.h
> > @@ -28,6 +28,7 @@
> >  #define TEE_SHM_USER_MAPPED  BIT(1)  /* Memory mapped in user space */
> >  #define TEE_SHM_POOL         BIT(2)  /* Memory allocated from pool */
> >  #define TEE_SHM_PRIV         BIT(3)  /* Memory private to TEE driver */
> > +#define TEE_SHM_DMA_BUF              BIT(4)  /* Memory with dma-buf handle */
> >
> >  #define TEE_DEVICE_FLAG_REGISTERED   0x1
> >  #define TEE_MAX_DEV_NAME_LEN         32
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index a54c203000ed..824f1251de60 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -116,6 +116,16 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> >  struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> >                                           void *addr, size_t length);
> >
> > +/**
> > + * tee_shm_register_fd() - Register shared memory from file descriptor
> > + *
> > + * @ctx:     Context that allocates the shared memory
> > + * @fd:              Shared memory file descriptor reference
> > + *
> > + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
> > + */
> > +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
> > +
> >  /**
> >   * tee_shm_free() - Free shared memory
> >   * @shm:     Handle to shared memory to free
> > diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
> > index d0430bee8292..1f9a4ac2b211 100644
> > --- a/include/uapi/linux/tee.h
> > +++ b/include/uapi/linux/tee.h
> > @@ -118,6 +118,35 @@ struct tee_ioctl_shm_alloc_data {
> >  #define TEE_IOC_SHM_ALLOC    _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
> >                                    struct tee_ioctl_shm_alloc_data)
> >
> > +/**
> > + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
> > + * @fd:              [in] File descriptor identifying the shared memory
> > + * @size:    [out] Size of shared memory to allocate
> > + * @flags:   [in] Flags to/from allocation.
> > + * @id:              [out] Identifier of the shared memory
> > + *
> > + * The flags field should currently be zero as input. Updated by the call
> > + * with actual flags as defined by TEE_IOCTL_SHM_* above.
> > + * This structure is used as argument for TEE_IOC_SHM_REGISTER_FD below.
> > + */
> > +struct tee_ioctl_shm_register_fd_data {
> > +     __s64 fd;
> > +     __u64 size;
> > +     __u32 flags;
> > +     __s32 id;
> > +};
> > +
> > +/**
> > + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
> > + *
> > + * Returns a file descriptor on success or < 0 on failure
> > + *
> > + * The returned file descriptor refers to the shared memory object in kernel
> > + * land. The shared memory is freed when the descriptor is closed.
> > + */
> > +#define TEE_IOC_SHM_REGISTER_FD      _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
> > +                                  struct tee_ioctl_shm_register_fd_data)
> > +
> >  /**
> >   * struct tee_ioctl_buf_data - Variable sized buffer
> >   * @buf_ptr: [in] A __user pointer to a buffer
> > --
> > 2.43.0
> >


From kory.maincent at bootlin.com  Tue Mar 25 04:27:06 2025
From: kory.maincent at bootlin.com (Kory Maincent)
Date: Tue, 25 Mar 2025 12:27:06 +0100
Subject: [PATCH net-next v4 2/8] net: ethtool: netlink: Allow
 per-netdevice DUMP operations
In-Reply-To: <20250324104012.367366-3-maxime.chevallier@bootlin.com>
References: <20250324104012.367366-1-maxime.chevallier@bootlin.com>
	<20250324104012.367366-3-maxime.chevallier@bootlin.com>
Message-ID: <20250325122706.5287774d@kmaincent-XPS-13-7390>

On Mon, 24 Mar 2025 11:40:04 +0100
Maxime Chevallier <maxime.chevallier at bootlin.com> wrote:

> We have a number of netlink commands in the ethnl family that may have
> multiple objects to dump even for a single net_device, including :
> 
>  - PLCA, PSE-PD, phy: one message per PHY device
>  - tsinfo: one message per timestamp source (netdev + phys)
>  - rss: One per RSS context
> 
> To get this behaviour, these netlink commands need to roll a custom
> ->dumpit().  
> 
> To prepare making per-netdev DUMP more generic in ethnl, introduce a
> member in the ethnl ops to indicate if a given command may allow
> pernetdev DUMPs (also referred to as filtered DUMPs).

...

> +
>  /* generic ->start() handler for GET requests */
>  static int ethnl_default_start(struct netlink_callback *cb)
>  {
> @@ -636,10 +659,10 @@ static int ethnl_default_start(struct netlink_callback
> *cb) }
>  
>  	ret = ethnl_default_parse(req_info, &info->info, ops, false);
> -	if (req_info->dev) {
> -		/* We ignore device specification in dump requests but as the
> -		 * same parser as for non-dump (doit) requests is used, it
> -		 * would take reference to the device if it finds one
> +	if (req_info->dev && !ops->allow_pernetdev_dump) {
> +		/* We ignore device specification in unfiltered dump requests
> +		 * but as the same parser as for non-dump (doit) requests is
> +		 * used, it would take reference to the device if it finds

This means the dump will have a different behavior in case of filtered dump
(allow_pernetdev_dump) or standard dump.
The standard dump will drop the interface device so it will dump all interfaces
even if one is specified.
The filtered dump will dump only the specified interface. 
Maybe it would be nice to have the same behavior for the dump for all the
ethtool command.
Even if this change modify the behavior of the dump for all the ethtool commands
it won't be an issue as the filtered dump did not exist before, so I suppose it
won't break anything. IMHO it is safer to do it now than later, if existing
ethtool command adds support for filtered dump.
We should find another way to know the parser is called from dump or doit.

Regards,
-- 
K?ry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Remove host FPSIMD saving for non-protected KVM" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-3-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-quizzical-epilogue-bf3b@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove host FPSIMD saving for non-protected KVM

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125721-greg=kroah.com at vger.kernel.org Thu Mar 20 20:20:22 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:03 +0000
Subject: KVM: arm64: Remove host FPSIMD saving for non-protected KVM
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-3-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ]

Now that the host eagerly saves its own FPSIMD/SVE/SME state,
non-protected KVM never needs to save the host FPSIMD/SVE/SME state,
and the code to do this is never used. Protected KVM still needs to
save/restore the host FPSIMD/SVE state to avoid leaking guest state to
the host (and to avoid revealing to the host whether the guest used
FPSIMD/SVE/SME), and that code needs to be retained.

Remove the unused code and data structures.

To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the
VHE hyp code, the nVHE/hVHE version is moved into the shared switch
header, where it is only invoked when KVM is in protected mode.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h       |    1 -
 arch/arm64/kvm/fpsimd.c                 |    2 --
 arch/arm64/kvm/hyp/include/hyp/switch.h |    4 ----
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |    1 -
 4 files changed, 8 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -535,7 +535,6 @@ struct kvm_vcpu_arch {
 	struct kvm_guest_debug_arch vcpu_debug_state;
 	struct kvm_guest_debug_arch external_debug_state;
 
-	struct user_fpsimd_state *host_fpsimd_state;	/* hyp VA */
 	struct task_struct *parent_task;
 
 	struct {
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -49,8 +49,6 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_
 	if (ret)
 		return ret;
 
-	vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
-
 	/*
 	 * We need to keep current's task_struct pinned until its data has been
 	 * unshared with the hypervisor to make sure it is not re-used by the
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -321,10 +321,6 @@ static bool kvm_hyp_handle_fpsimd(struct
 	}
 	isb();
 
-	/* Write out the host state if it's in the registers */
-	if (vcpu->arch.fp_state == FP_STATE_HOST_OWNED)
-		__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
-
 	/* Restore the guest state */
 	if (sve_guest)
 		__hyp_sve_restore_guest(vcpu);
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -41,7 +41,6 @@ static void flush_hyp_vcpu(struct pkvm_h
 	hyp_vcpu->vcpu.arch.fp_state	= host_vcpu->arch.fp_state;
 
 	hyp_vcpu->vcpu.arch.debug_ptr	= kern_hyp_va(host_vcpu->arch.debug_ptr);
-	hyp_vcpu->vcpu.arch.host_fpsimd_state = host_vcpu->arch.host_fpsimd_state;
 
 	hyp_vcpu->vcpu.arch.vsesr_el2	= host_vcpu->arch.vsesr_el2;
 


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-5-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-stress-kissable-c123@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 20:18:32 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:05 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-5-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic
has historically been broken, and is currently redundant.

This logic was originally introduced in commit:

  861262ab86270206 ("KVM: arm64: Handle SME host state when running guests")

At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when
returning to the host, trapping host access to SME state. Unfortunately,
this was unsafe as the host could take a softirq before calling
kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode
NEON the resulting attempt to save the live FPSIMD/SVE/SME state would
result in a fatal trap.

That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always
saved/restored the host kernel's CPACR_EL1 value, and configured
CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be
trapped.

The issue above was incidentally fixed by commit:

  375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE")

That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01
when returning to the host, permitting host kernel usage of SME,
avoiding the issue described above. At the time, this was not identified
as a fix for commit 861262ab86270206.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SME trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Update for rework of flags storage -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   23 -----------------------
 2 files changed, 25 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -717,8 +717,6 @@ struct kvm_vcpu_arch {
 /* vcpu running in HYP context */
 #define VCPU_HYP_CONTEXT	__vcpu_single_flag(iflags, BIT(7))
 
-/* SME enabled for EL0 */
-#define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
 #define ON_UNSUPPORTED_CPU	__vcpu_single_flag(sflags, BIT(2))
 /* WFIT instruction trapped */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -87,12 +87,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	 */
 	fpsimd_save_and_flush_cpu_state();
 	vcpu->arch.fp_state = FP_STATE_FREE;
-
-	if (system_supports_sme()) {
-		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
-		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
-			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-	}
 }
 
 /*
@@ -157,23 +151,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 
 	local_irq_save(flags);
 
-	/*
-	 * If we have VHE then the Hyp code will reset CPACR_EL1 to
-	 * the default value and we need to reenable SME.
-	 */
-	if (has_vhe() && system_supports_sme()) {
-		/* Also restore EL0 state seen on entry */
-		if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0,
-					 CPACR_EL1_SMEN_EL0EN |
-					 CPACR_EL1_SMEN_EL1EN);
-		else
-			sysreg_clear_set(CPACR_EL1,
-					 CPACR_EL1_SMEN_EL0EN,
-					 CPACR_EL1_SMEN_EL1EN);
-		isb();
-	}
-
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) {
 		if (vcpu_has_sve(vcpu)) {
 			__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-4-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-docile-unknowing-7dec@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 20:18:28 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:04 +0000
Subject: KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-4-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ]

When KVM is in VHE mode, the host kernel tries to save and restore the
configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1)
across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the
configuration may be clobbered by hyp when running a vCPU. This logic is
currently redundant.

The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when
returning to the host, permitting host kernel usage of SVE.

Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME
state, there's no need to save/restore the state of the EL0 SVE trap.
The kernel can safely save/restore state without trapping, as described
above, and will restore userspace state (including trap controls) before
returning to userspace.

Remove the redundant logic.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[Rework for refactoring of where the flags are stored -- broonie]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h |    2 --
 arch/arm64/kvm/fpsimd.c           |   16 ----------------
 2 files changed, 18 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -717,8 +717,6 @@ struct kvm_vcpu_arch {
 /* vcpu running in HYP context */
 #define VCPU_HYP_CONTEXT	__vcpu_single_flag(iflags, BIT(7))
 
-/* SVE enabled for host EL0 */
-#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
 /* SME enabled for EL0 */
 #define HOST_SME_ENABLED	__vcpu_single_flag(sflags, BIT(1))
 /* Physical CPU not in supported_cpus */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -88,10 +88,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	fpsimd_save_and_flush_cpu_state();
 	vcpu->arch.fp_state = FP_STATE_FREE;
 
-	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
-	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
-		vcpu_set_flag(vcpu, HOST_SVE_ENABLED);
-
 	if (system_supports_sme()) {
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
@@ -189,18 +185,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 		}
 
 		fpsimd_save_and_flush_cpu_state();
-	} else if (has_vhe() && system_supports_sve()) {
-		/*
-		 * The FPSIMD/SVE state in the CPU has not been touched, and we
-		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
-		 * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE
-		 * for EL0.  To avoid spurious traps, restore the trap state
-		 * seen by kvm_arch_vcpu_load_fp():
-		 */
-		if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED))
-			sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
-		else
-			sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
 	}
 
 	local_irq_restore(flags);


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-2-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-jingling-scope-be6f@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125720-greg=kroah.com at vger.kernel.org Thu Mar 20 20:18:53 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:02 +0000
Subject: KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Eric Auger <eauger at redhat.com>, Wilco Dijkstra <wilco.dijkstra at arm.com>,  Eric Auger <eric.auger at redhat.com>, Florian Weimer <fweimer at redhat.com>,  Fuad Tabba <tabba at google.com>, Jeremy Linton <jeremy.linton at arm.com>,  Paolo Bonzini <pbonzini at redhat.com>
Message-ID: <20250321-stable-sve-6-6-v1-2-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ]

There are several problems with the way hyp code lazily saves the host's
FPSIMD/SVE state, including:

* Host SVE being discarded unexpectedly due to inconsistent
  configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to
  result in QEMU crashes where SVE is used by memmove(), as reported by
  Eric Auger:

  https://issues.redhat.com/browse/RHEL-68997

* Host SVE state is discarded *after* modification by ptrace, which was an
  unintentional ptrace ABI change introduced with lazy discarding of SVE state.

* The host FPMR value can be discarded when running a non-protected VM,
  where FPMR support is not exposed to a VM, and that VM uses
  FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR
  before unbinding the host's FPSIMD/SVE/SME state, leaving a stale
  value in memory.

Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME
state when loading a vCPU such that KVM does not need to save any of the
host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is
removed and the necessary call to fpsimd_save_and_flush_cpu_state() is
placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr'
should not be used, they are set to NULL; all uses of these will be
removed in subsequent patches.

Historical problems go back at least as far as v5.17, e.g. erroneous
assumptions about TIF_SVE being clear in commit:

  8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving")

... and so this eager save+flush probably needs to be backported to ALL
stable trees.

Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests")
Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch")
Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR")
Reported-by: Eric Auger <eauger at redhat.com>
Reported-by: Wilco Dijkstra <wilco.dijkstra at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Tested-by: Eric Auger <eric.auger at redhat.com>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Florian Weimer <fweimer at redhat.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ Mark: Handle vcpu/host flag conflict ]
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kernel/fpsimd.c |   25 -------------------------
 arch/arm64/kvm/fpsimd.c    |   31 ++++++++-----------------------
 2 files changed, 8 insertions(+), 48 deletions(-)

--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1708,31 +1708,6 @@ void fpsimd_signal_preserve_current_stat
 }
 
 /*
- * Called by KVM when entering the guest.
- */
-void fpsimd_kvm_prepare(void)
-{
-	if (!system_supports_sve())
-		return;
-
-	/*
-	 * KVM does not save host SVE state since we can only enter
-	 * the guest from a syscall so the ABI means that only the
-	 * non-saved SVE state needs to be saved.  If we have left
-	 * SVE enabled for performance reasons then update the task
-	 * state to be FPSIMD only.
-	 */
-	get_cpu_fpsimd_context();
-
-	if (test_and_clear_thread_flag(TIF_SVE)) {
-		sve_to_fpsimd(current);
-		current->thread.fp_type = FP_STATE_FPSIMD;
-	}
-
-	put_cpu_fpsimd_context();
-}
-
-/*
  * Associate current's FPSIMD context with this cpu
  * The caller must have ownership of the cpu FPSIMD context before calling
  * this function.
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -79,14 +79,16 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 	if (!system_supports_fpsimd())
 		return;
 
-	fpsimd_kvm_prepare();
-
 	/*
-	 * We will check TIF_FOREIGN_FPSTATE just before entering the
-	 * guest in kvm_arch_vcpu_ctxflush_fp() and override this to
-	 * FP_STATE_FREE if the flag set.
+	 * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such
+	 * that the host kernel is responsible for restoring this state upon
+	 * return to userspace, and the hyp code doesn't need to save anything.
+	 *
+	 * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures
+	 * that PSTATE.{SM,ZA} == {0,0}.
 	 */
-	vcpu->arch.fp_state = FP_STATE_HOST_OWNED;
+	fpsimd_save_and_flush_cpu_state();
+	vcpu->arch.fp_state = FP_STATE_FREE;
 
 	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
 	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -96,23 +98,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vc
 		vcpu_clear_flag(vcpu, HOST_SME_ENABLED);
 		if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
 			vcpu_set_flag(vcpu, HOST_SME_ENABLED);
-
-		/*
-		 * If PSTATE.SM is enabled then save any pending FP
-		 * state and disable PSTATE.SM. If we leave PSTATE.SM
-		 * enabled and the guest does not enable SME via
-		 * CPACR_EL1.SMEN then operations that should be valid
-		 * may generate SME traps from EL1 to EL1 which we
-		 * can't intercept and which would confuse the guest.
-		 *
-		 * Do the same for PSTATE.ZA in the case where there
-		 * is state in the registers which has not already
-		 * been saved, this is very unlikely to happen.
-		 */
-		if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) {
-			vcpu->arch.fp_state = FP_STATE_FREE;
-			fpsimd_save_and_flush_cpu_state();
-		}
 	}
 }
 


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Mark some header functions as inline" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-7-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-sesame-repent-294b@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Mark some header functions as inline

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-mark-some-header-functions-as-inline.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 20:18:37 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:07 +0000
Subject: KVM: arm64: Mark some header functions as inline
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-7-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ]

The shared hyp switch header has a number of static functions which
might not be used by all files that include the header, and when unused
they will provoke compiler warnings, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function]
|   703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function]
|   682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function]
|   662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function]
|   458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function]
|   329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|       |             ^~~~~~~~~~~~~~~~~~~

Mark these functions as 'inline' to suppress this warning. This
shouldn't result in any functional change.

At the same time, avoid the use of __alias() in the header and alias
kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to
kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest
of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also
marked as 'inline'.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -279,7 +279,7 @@ static inline void __hyp_sve_restore_gue
  * If FP/SIMD is not implemented, handle the trap and inject an undefined
  * instruction exception to the guest. Similarly for trapped SVE accesses.
  */
-static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	bool sve_guest;
 	u8 esr_ec;
@@ -518,7 +518,7 @@ static bool handle_ampere1_tcr(struct kv
 	return true;
 }
 
-static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
 	    handle_tx2_tvm(vcpu))
@@ -541,7 +541,7 @@ static bool kvm_hyp_handle_sysreg(struct
 	return false;
 }
 
-static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
 	    __vgic_v3_perform_cpuif_access(vcpu) == 1)
@@ -550,19 +550,18 @@ static bool kvm_hyp_handle_cp15_32(struc
 	return false;
 }
 
-static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu,
+					       u64 *exit_code)
 {
 	if (!__populate_fault_info(vcpu))
 		return true;
 
 	return false;
 }
-static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
-static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
-	__alias(kvm_hyp_handle_memory_fault);
+#define kvm_hyp_handle_iabt_low		kvm_hyp_handle_memory_fault
+#define kvm_hyp_handle_watchpt_low	kvm_hyp_handle_memory_fault
 
-static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
 	if (kvm_hyp_handle_memory_fault(vcpu, exit_code))
 		return true;


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From ghennadi.procopciuc at oss.nxp.com  Tue Mar 25 04:40:44 2025
From: ghennadi.procopciuc at oss.nxp.com (Ghennadi Procopciuc)
Date: Tue, 25 Mar 2025 13:40:44 +0200
Subject: [PATCH 2/2] clocksource/drivers/nxp-timer: Add the System Timer
 Module for the s32g platform
In-Reply-To: <8c208e8c-2e1e-430c-916a-dbc6732881b0@linaro.org>
References: <20250324100008.346009-1-daniel.lezcano@linaro.org>
 <20250324100008.346009-2-daniel.lezcano@linaro.org>
 <d60fca36-0beb-2574-cb82-3969bbfb58a9@oss.nxp.com>
 <8c208e8c-2e1e-430c-916a-dbc6732881b0@linaro.org>
Message-ID: <065d6f32-3161-8316-bbbd-4da18eef839b@oss.nxp.com>

On 3/25/2025 12:53 PM, Daniel Lezcano wrote:
[ ... ]
>>> +static int __init nxp_stm_clocksource_init(struct device *dev, const
>>> char *name,
>>> +?????????????????????? void __iomem *base, struct clk *clk)
>>> +{
>>> +??? struct stm_timer *stm_timer;
>>> +??? int ret;
>>> +
>>> +??? stm_timer = devm_kzalloc(dev, sizeof(*stm_timer), GFP_KERNEL);
>>> +??? if (!stm_timer)
>>> +??????? return -ENOMEM;
>>> +
>>> +??? stm_timer->base = base;
>>> +??? stm_timer->rate = clk_get_rate(clk);
>>> +
>>> +??? stm_timer->scs.cs.name = name;
>>> +??? stm_timer->scs.cs.rating = 460;
>>> +??? stm_timer->scs.cs.read = nxp_stm_clocksource_read;
>>> +??? stm_timer->scs.cs.enable = nxp_stm_clocksource_enable;
>>> +??? stm_timer->scs.cs.disable = nxp_stm_clocksource_disable;
>>> +??? stm_timer->scs.cs.suspend = nxp_stm_clocksource_suspend;
>>> +??? stm_timer->scs.cs.resume = nxp_stm_clocksource_resume;
>>> +??? stm_timer->scs.cs.mask = CLOCKSOURCE_MASK(32);
>>> +??? stm_timer->scs.cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
>>> +
>>> +??? ret = clocksource_register_hz(&stm_timer->scs.cs, stm_timer->rate);
>>> +??? if (ret)
>>> +??????? return ret;
>>
>> clocksource_unregister during remove callback for cleanup?
> 
> Sorry I don't get it :/
> 
> There is no cleanup after the clocksource_register_hz() is successful
> 

I noticed that other drivers, such as
drivers/clocksource/timer-tegra186.c and
drivers/clocksource/timer-sun5i.c, perform clocksource_unregister during
their platform_driver.remove callback. Shouldn't this apply here as well?

[ ... ]
> 
>>> +static int nxp_stm_clockevent_set_next_event(unsigned long delta,
>>> struct clock_event_device *ced)
>>> +{
>>> +??? struct stm_timer *stm_timer = ced_to_stm(ced);
>>> +??? u32 val;
>>> +
>>> +??? nxp_stm_clockevent_disable(stm_timer);
>>
>> While examining the code base, I came across the
>> drivers/clocksource/timer-imx-gpt.c file, specifically the
>> mx1_2_set_next_event function, which includes a protection against
>> missing events. Using a similar approach would allow us to keep the STM
>> module enabled while only altering the channel's register state. This
>> risk can also be mitigated by adjusting min_delta_ns based on tick
>> frequency.
> 
> How would you validate that ?
> 

How would I validate that this works?

If this is the question, I see that the core performs an auto adjustment
of the minimum delta as part of the clockevents_program_min_delta
function when CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST is enabled.
Initially, I would examine how many times dev->set_next_event() returns
-ETIME. At the end of the function, min_delta_ns should reflect the
actual minimum delta the device can handle.

[ ... ]
>>> +static int __init nxp_stm_timer_probe(struct platform_device *pdev)
>>> +{
>>> +??? struct device *dev = &pdev->dev;
>>> +??? struct device_node *np = dev->of_node;
>>> +??? struct stm_instances *stm_instances;
>>> +??? const char *name = of_node_full_name(np);
>>> +??? void __iomem *base;
>>> +??? int irq, ret;
>>> +??? struct clk *clk;
>>> +
>>> +??? stm_instances =
>>> (typeof(stm_instances))of_device_get_match_data(dev);
>>> +??? if (!stm_instances) {
>>> +??????? dev_err(dev, "No STM instances associated with a cpu");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +
>>> +??? base = devm_of_iomap(dev, np, 0, NULL);
>>> +??? if (IS_ERR(base)) {
>>> +??????? dev_err(dev, "Failed to iomap %pOFn\n", np);
>>> +??????? return PTR_ERR(base);
>>> +??? }
>>> +
>>> +??? irq = irq_of_parse_and_map(np, 0);
>>> +??? if (irq <= 0) {
>>> +??????? dev_err(dev, "Failed to parse and map IRQ: %d\n", irq);
>>> +??????? return -EINVAL;
>>> +??? }
>>
>> ?From commit description:
>>
>>> The first probed STM is used as a clocksource, the second will be the
>>> broadcast timer and the rest are used as a clockevent with the
>>> affinity set to a CPU.
>>
>> Why is the interrupt mandatory when the node is probed as a clocksource?
> 
> It relies on the DT description and it does not hurt to have a
> consistent code path for clockevent / clocksource even if the interrupt
> is not requested for the clocksource later.
> 

If so, in my opinion, it would make sense to use the same STM instance
for both the clocksource and broadcast clockevent, as both functions can
be accommodated within a single STM instance, which will help reduce the
number of STM instances used.

-- 
Regards,
Ghennadi



From gregkh at linuxfoundation.org  Tue Mar 25 04:28:55 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:55 -0400
Subject: Patch "KVM: arm64: Calculate cptr_el2 traps on activating traps" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-1-0b3a6a14ea53@kernel.org>
Message-ID: <2025032555-stingy-unwed-db94@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Calculate cptr_el2 traps on activating traps

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-125719-greg=kroah.com at vger.kernel.org Thu Mar 20 20:19:30 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:01 +0000
Subject: KVM: arm64: Calculate cptr_el2 traps on activating traps
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Fuad Tabba <tabba at google.com>,  James Clark <james.clark at linaro.org>
Message-ID: <20250321-stable-sve-6-6-v1-1-0b3a6a14ea53 at kernel.org>

From: Fuad Tabba <tabba at google.com>

[ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ]

Similar to VHE, calculate the value of cptr_el2 from scratch on
activate traps. This removes the need to store cptr_el2 in every
vcpu structure. Moreover, some traps, such as whether the guest
owns the fp registers, need to be set on every vcpu run.

Reported-by: James Clark <james.clark at linaro.org>
Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch")
Signed-off-by: Fuad Tabba <tabba at google.com>
Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba at google.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h  |    1 
 arch/arm64/kvm/arm.c               |    1 
 arch/arm64/kvm/hyp/nvhe/hyp-main.c |    2 -
 arch/arm64/kvm/hyp/nvhe/pkvm.c     |   27 -------------------
 arch/arm64/kvm/hyp/nvhe/switch.c   |   52 ++++++++++++++++++++++---------------
 5 files changed, 32 insertions(+), 51 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -486,7 +486,6 @@ struct kvm_vcpu_arch {
 	/* Values of trap registers for the guest. */
 	u64 hcr_el2;
 	u64 mdcr_el2;
-	u64 cptr_el2;
 
 	/* Values of trap registers for the host before guest entry. */
 	u64 mdcr_el2_host;
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1309,7 +1309,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init
 	}
 
 	vcpu_reset_hcr(vcpu);
-	vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
 
 	/*
 	 * Handle the "start in power-off" case.
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -36,7 +36,6 @@ static void flush_hyp_vcpu(struct pkvm_h
 
 	hyp_vcpu->vcpu.arch.hcr_el2	= host_vcpu->arch.hcr_el2;
 	hyp_vcpu->vcpu.arch.mdcr_el2	= host_vcpu->arch.mdcr_el2;
-	hyp_vcpu->vcpu.arch.cptr_el2	= host_vcpu->arch.cptr_el2;
 
 	hyp_vcpu->vcpu.arch.iflags	= host_vcpu->arch.iflags;
 	hyp_vcpu->vcpu.arch.fp_state	= host_vcpu->arch.fp_state;
@@ -59,7 +58,6 @@ static void sync_hyp_vcpu(struct pkvm_hy
 	host_vcpu->arch.ctxt		= hyp_vcpu->vcpu.arch.ctxt;
 
 	host_vcpu->arch.hcr_el2		= hyp_vcpu->vcpu.arch.hcr_el2;
-	host_vcpu->arch.cptr_el2	= hyp_vcpu->vcpu.arch.cptr_el2;
 
 	host_vcpu->arch.fault		= hyp_vcpu->vcpu.arch.fault;
 
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -26,8 +26,6 @@ static void pvm_init_traps_aa64pfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
 	u64 hcr_set = HCR_RW;
 	u64 hcr_clear = 0;
-	u64 cptr_set = 0;
-	u64 cptr_clear = 0;
 
 	/* Protected KVM does not support AArch32 guests. */
 	BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
@@ -57,21 +55,10 @@ static void pvm_init_traps_aa64pfr0(stru
 	/* Trap AMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
 		hcr_clear |= HCR_AMVOFFEN;
-		cptr_set |= CPTR_EL2_TAM;
-	}
-
-	/* Trap SVE */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-		if (has_hvhe())
-			cptr_clear |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN;
-		else
-			cptr_set |= CPTR_EL2_TZ;
 	}
 
 	vcpu->arch.hcr_el2 |= hcr_set;
 	vcpu->arch.hcr_el2 &= ~hcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
-	vcpu->arch.cptr_el2 &= ~cptr_clear;
 }
 
 /*
@@ -101,7 +88,6 @@ static void pvm_init_traps_aa64dfr0(stru
 	const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
 	u64 mdcr_set = 0;
 	u64 mdcr_clear = 0;
-	u64 cptr_set = 0;
 
 	/* Trap/constrain PMU */
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
@@ -128,17 +114,8 @@ static void pvm_init_traps_aa64dfr0(stru
 	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
 		mdcr_set |= MDCR_EL2_TTRF;
 
-	/* Trap Trace */
-	if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-		if (has_hvhe())
-			cptr_set |= CPACR_EL1_TTA;
-		else
-			cptr_set |= CPTR_EL2_TTA;
-	}
-
 	vcpu->arch.mdcr_el2 |= mdcr_set;
 	vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-	vcpu->arch.cptr_el2 |= cptr_set;
 }
 
 /*
@@ -189,10 +166,6 @@ static void pvm_init_trap_regs(struct kv
 	/* Clear res0 and set res1 bits to trap potential new features. */
 	vcpu->arch.hcr_el2 &= ~(HCR_RES0);
 	vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
-	if (!has_hvhe()) {
-		vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
-		vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
-	}
 }
 
 /*
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -36,34 +36,46 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_ve
 
 extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
 
-static void __activate_traps(struct kvm_vcpu *vcpu)
+static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
 {
-	u64 val;
+	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
-	___activate_traps(vcpu);
-	__activate_traps_common(vcpu);
+	if (has_hvhe()) {
+		val |= CPACR_ELx_TTA;
 
-	val = vcpu->arch.cptr_el2;
-	val |= CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
-	val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA;
-	if (cpus_have_final_cap(ARM64_SME)) {
-		if (has_hvhe())
-			val &= ~(CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN);
-		else
-			val |= CPTR_EL2_TSM;
-	}
+		if (guest_owns_fp_regs(vcpu)) {
+			val |= CPACR_ELx_FPEN;
+			if (vcpu_has_sve(vcpu))
+				val |= CPACR_ELx_ZEN;
+		}
+	} else {
+		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
+
+		/*
+		 * Always trap SME since it's not supported in KVM.
+		 * TSM is RES1 if SME isn't implemented.
+		 */
+		val |= CPTR_EL2_TSM;
 
-	if (!guest_owns_fp_regs(vcpu)) {
-		if (has_hvhe())
-			val &= ~(CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |
-				 CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN);
-		else
-			val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
+		if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs(vcpu))
+			val |= CPTR_EL2_TZ;
 
-		__activate_traps_fpsimd32(vcpu);
+		if (!guest_owns_fp_regs(vcpu))
+			val |= CPTR_EL2_TFP;
 	}
 
+	if (!guest_owns_fp_regs(vcpu))
+		__activate_traps_fpsimd32(vcpu);
+
 	kvm_write_cptr_el2(val);
+}
+
+static void __activate_traps(struct kvm_vcpu *vcpu)
+{
+	___activate_traps(vcpu);
+	__activate_traps_common(vcpu);
+	__activate_cptr_traps(vcpu);
+
 	write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
 	if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:55 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:55 -0400
Subject: Patch "KVM: arm64: Eagerly switch ZCR_EL{1,2}" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-8-0b3a6a14ea53@kernel.org>
Message-ID: <2025032555-wimp-try-c46c@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Eagerly switch ZCR_EL{1,2}

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-eagerly-switch-zcr_el-1-2.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 20:18:40 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:08 +0000
Subject: KVM: arm64: Eagerly switch ZCR_EL{1,2}
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-8-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ]

In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the
CPU, the host's active SVE VL may differ from the guest's maximum SVE VL:

* For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained
  by the guest hypervisor, which may be less than or equal to that
  guest's maximum VL.

  Note: in this case the value of ZCR_EL1 is immaterial due to E2H.

* For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest,
  which may be less than or greater than the guest's maximum VL.

  Note: in this case hyp code traps host SVE usage and lazily restores
  ZCR_EL2 to the host's maximum VL, which may be greater than the
  guest's maximum VL.

This can be the case between exiting a guest and kvm_arch_vcpu_put_fp().
If a softirq is taken during this period and the softirq handler tries
to use kernel-mode NEON, then the kernel will fail to save the guest's
FPSIMD/SVE state, and will pend a SIGKILL for the current thread.

This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live
FPSIMD/SVE state with the guest's maximum SVE VL, and
fpsimd_save_user_state() verifies that the live SVE VL is as expected
before attempting to save the register state:

| if (WARN_ON(sve_get_vl() != vl)) {
|         force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
|         return;
| }

Fix this and make this a bit easier to reason about by always eagerly
switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this
happening, there's no need to trap host SVE usage, and the nVHE/nVHE
__deactivate_cptr_traps() logic can be simplified to enable host access
to all present FPSIMD/SVE/SME features.

In protected nVHE/hVHE modes, the host's state is always saved/restored
by hyp, and the guest's state is saved prior to exit to the host, so
from the host's PoV the guest never has live FPSIMD/SVE/SME state, and
the host's ZCR_EL1 is never clobbered by hyp.

Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE")
Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Cc: Will Deacon <will at kernel.org>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
[ v6.6 lacks pKVM saving of host SVE state, pull in discovery of maximum
  host VL separately -- broonie ]
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/include/asm/kvm_host.h       |    1 
 arch/arm64/include/asm/kvm_hyp.h        |    1 
 arch/arm64/kvm/fpsimd.c                 |   19 +++++------
 arch/arm64/kvm/hyp/entry.S              |    5 ++
 arch/arm64/kvm/hyp/include/hyp/switch.h |   55 ++++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/hyp-main.c      |   12 +-----
 arch/arm64/kvm/hyp/nvhe/pkvm.c          |    2 +
 arch/arm64/kvm/hyp/nvhe/switch.c        |   33 ++++++++++++++++---
 arch/arm64/kvm/hyp/vhe/switch.c         |    4 ++
 arch/arm64/kvm/reset.c                  |    3 +
 10 files changed, 113 insertions(+), 22 deletions(-)

--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -73,6 +73,7 @@ static inline enum kvm_mode kvm_get_mode
 #endif
 
 extern unsigned int __ro_after_init kvm_sve_max_vl;
+extern unsigned int __ro_after_init kvm_host_sve_max_vl;
 int __init kvm_arm_init_sve(void);
 
 u32 __attribute_const__ kvm_target_cpu(void);
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -145,5 +145,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1
 
 extern unsigned long kvm_nvhe_sym(__icache_flags);
 extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
+extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
 
 #endif /* __ARM64_KVM_HYP_H__ */
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -152,15 +152,16 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcp
 	local_irq_save(flags);
 
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) {
-		if (vcpu_has_sve(vcpu)) {
-			__vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);
-
-			/* Restore the VL that was saved when bound to the CPU */
-			if (!has_vhe())
-				sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1,
-						       SYS_ZCR_EL1);
-		}
-
+		/*
+		 * Flush (save and invalidate) the fpsimd/sve state so that if
+		 * the host tries to use fpsimd/sve, it's not using stale data
+		 * from the guest.
+		 *
+		 * Flushing the state sets the TIF_FOREIGN_FPSTATE bit for the
+		 * context unconditionally, in both nVHE and VHE. This allows
+		 * the kernel to restore the fpsimd/sve state, including ZCR_EL1
+		 * when needed.
+		 */
 		fpsimd_save_and_flush_cpu_state();
 	}
 
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN
 alternative_else_nop_endif
 	mrs	x1, isr_el1
 	cbz	x1,  1f
+
+	// Ensure that __guest_enter() always provides a context
+	// synchronization event so that callers don't need ISBs for anything
+	// that would usually be synchonized by the ERET.
+	isb
 	mov	x0, #ARM_EXCEPTION_IRQ
 	ret
 
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -273,6 +273,61 @@ static inline void __hyp_sve_restore_gue
 	write_sysreg_el1(__vcpu_sys_reg(vcpu, ZCR_EL1), SYS_ZCR);
 }
 
+static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs(vcpu))
+		return;
+
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
+		write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+		zcr_el1 = __vcpu_sys_reg(vcpu, ZCR_EL1);
+		write_sysreg_el1(zcr_el1, SYS_ZCR);
+	}
+}
+
+static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu)
+{
+	u64 zcr_el1, zcr_el2;
+
+	if (!guest_owns_fp_regs(vcpu))
+		return;
+
+	/*
+	 * When the guest owns the FP regs, we know that guest+hyp traps for
+	 * any FPSIMD/SVE/SME features exposed to the guest have been disabled
+	 * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd()
+	 * prior to __guest_entry(). As __guest_entry() guarantees a context
+	 * synchronization event, we don't need an ISB here to avoid taking
+	 * traps for anything that was exposed to the guest.
+	 */
+	if (vcpu_has_sve(vcpu)) {
+		zcr_el1 = read_sysreg_el1(SYS_ZCR);
+		__vcpu_sys_reg(vcpu, ZCR_EL1) = zcr_el1;
+
+		/*
+		 * The guest's state is always saved using the guest's max VL.
+		 * Ensure that the host has the guest's max VL active such that
+		 * the host can save the guest's state lazily, but don't
+		 * artificially restrict the host to the guest's max VL.
+		 */
+		if (has_vhe()) {
+			zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+		} else {
+			zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1;
+			write_sysreg_el2(zcr_el2, SYS_ZCR);
+
+			zcr_el1 = vcpu_sve_max_vq(vcpu) - 1;
+			write_sysreg_el1(zcr_el1, SYS_ZCR);
+		}
+	}
+}
+
 /*
  * We trap the first access to the FP/SIMD to save the host context and
  * restore the guest context lazily.
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -5,6 +5,7 @@
  */
 
 #include <hyp/adjust_pc.h>
+#include <hyp/switch.h>
 
 #include <asm/pgtable-types.h>
 #include <asm/kvm_asm.h>
@@ -95,7 +96,9 @@ static void handle___kvm_vcpu_run(struct
 		pkvm_put_hyp_vcpu(hyp_vcpu);
 	} else {
 		/* The host is fully trusted, run its vCPU directly. */
+		fpsimd_lazy_switch_to_guest(host_vcpu);
 		ret = __kvm_vcpu_run(host_vcpu);
+		fpsimd_lazy_switch_to_host(host_vcpu);
 	}
 
 out:
@@ -416,15 +419,6 @@ void handle_trap(struct kvm_cpu_context
 	case ESR_ELx_EC_SMC64:
 		handle_host_smc(host_ctxt);
 		break;
-	case ESR_ELx_EC_SVE:
-		if (has_hvhe())
-			sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN |
-							CPACR_EL1_ZEN_EL0EN));
-		else
-			sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0);
-		isb();
-		sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
-		break;
 	case ESR_ELx_EC_IABT_LOW:
 	case ESR_ELx_EC_DABT_LOW:
 		handle_host_mem_abort(host_ctxt);
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -18,6 +18,8 @@ unsigned long __icache_flags;
 /* Used by kvm_get_vttbr(). */
 unsigned int kvm_arm_vmid_bits;
 
+unsigned int kvm_host_sve_max_vl;
+
 /*
  * Set trap register values based on features in ID_AA64PFR0.
  */
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -40,6 +40,9 @@ static void __activate_cptr_traps(struct
 {
 	u64 val = CPTR_EL2_TAM;	/* Same bit irrespective of E2H */
 
+	if (!guest_owns_fp_regs(vcpu))
+		__activate_traps_fpsimd32(vcpu);
+
 	if (has_hvhe()) {
 		val |= CPACR_ELx_TTA;
 
@@ -48,6 +51,8 @@ static void __activate_cptr_traps(struct
 			if (vcpu_has_sve(vcpu))
 				val |= CPACR_ELx_ZEN;
 		}
+
+		write_sysreg(val, cpacr_el1);
 	} else {
 		val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1;
 
@@ -62,12 +67,32 @@ static void __activate_cptr_traps(struct
 
 		if (!guest_owns_fp_regs(vcpu))
 			val |= CPTR_EL2_TFP;
+
+		write_sysreg(val, cptr_el2);
 	}
+}
 
-	if (!guest_owns_fp_regs(vcpu))
-		__activate_traps_fpsimd32(vcpu);
+static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu)
+{
+	if (has_hvhe()) {
+		u64 val = CPACR_ELx_FPEN;
+
+		if (cpus_have_final_cap(ARM64_SVE))
+			val |= CPACR_ELx_ZEN;
+		if (cpus_have_final_cap(ARM64_SME))
+			val |= CPACR_ELx_SMEN;
+
+		write_sysreg(val, cpacr_el1);
+	} else {
+		u64 val = CPTR_NVHE_EL2_RES1;
+
+		if (!cpus_have_final_cap(ARM64_SVE))
+			val |= CPTR_EL2_TZ;
+		if (!cpus_have_final_cap(ARM64_SME))
+			val |= CPTR_EL2_TSM;
 
-	kvm_write_cptr_el2(val);
+		write_sysreg(val, cptr_el2);
+	}
 }
 
 static void __activate_traps(struct kvm_vcpu *vcpu)
@@ -120,7 +145,7 @@ static void __deactivate_traps(struct kv
 
 	write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
-	kvm_reset_cptr_el2(vcpu);
+	__deactivate_cptr_traps(vcpu);
 	write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -212,6 +212,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	sysreg_save_host_state_vhe(host_ctxt);
 
+	fpsimd_lazy_switch_to_guest(vcpu);
+
 	/*
 	 * ARM erratum 1165522 requires us to configure both stage 1 and
 	 * stage 2 translation for the guest context before we clear
@@ -247,6 +249,8 @@ static int __kvm_vcpu_run_vhe(struct kvm
 
 	__deactivate_traps(vcpu);
 
+	fpsimd_lazy_switch_to_host(vcpu);
+
 	sysreg_restore_host_state_vhe(host_ctxt);
 
 	if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED)
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -46,11 +46,14 @@ static u32 __ro_after_init kvm_ipa_limit
 				 PSR_AA32_I_BIT | PSR_AA32_F_BIT)
 
 unsigned int __ro_after_init kvm_sve_max_vl;
+unsigned int __ro_after_init kvm_host_sve_max_vl;
 
 int __init kvm_arm_init_sve(void)
 {
 	if (system_supports_sve()) {
 		kvm_sve_max_vl = sve_max_virtualisable_vl();
+		kvm_host_sve_max_vl = sve_max_vl();
+		kvm_nvhe_sym(kvm_host_sve_max_vl) = kvm_host_sve_max_vl;
 
 		/*
 		 * The get_sve_reg()/set_sve_reg() ioctl interface will need


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From gregkh at linuxfoundation.org  Tue Mar 25 04:28:56 2025
From: gregkh at linuxfoundation.org (gregkh at linuxfoundation.org)
Date: Tue, 25 Mar 2025 07:28:56 -0400
Subject: Patch "KVM: arm64: Refactor exit handlers" has been added to the 6.6-stable tree
In-Reply-To: <20250321-stable-sve-6-6-v1-6-0b3a6a14ea53@kernel.org>
Message-ID: <2025032556-rule-crescent-bf76@gregkh>


This is a note to let you know that I've just added the patch titled

    KVM: arm64: Refactor exit handlers

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-arm64-refactor-exit-handlers.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From broonie at kernel.org Thu Mar 20 20:18:34 2025
From: Mark Brown <broonie at kernel.org>
Date: Fri, 21 Mar 2025 00:16:06 +0000
Subject: KVM: arm64: Refactor exit handlers
To: Greg Kroah-Hartman <gregkh at linuxfoundation.org>,  Marc Zyngier <maz at kernel.org>, Oliver Upton <oliver.upton at linux.dev>,  James Morse <james.morse at arm.com>,  Suzuki K Poulose <suzuki.poulose at arm.com>,  Catalin Marinas <catalin.marinas at arm.com>, Will Deacon <will at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org, kvmarm at lists.linux.dev,  linux-kernel at vger.kernel.org, stable at vger.kernel.org,  Mark Brown <broonie at kernel.org>, Mark Rutland <mark.rutland at arm.com>,  Fuad Tabba <tabba at google.com>
Message-ID: <20250321-stable-sve-6-6-v1-6-0b3a6a14ea53 at kernel.org>

From: Mark Rutland <mark.rutland at arm.com>

[ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ]

The hyp exit handling logic is largely shared between VHE and nVHE/hVHE,
with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code
in the header depends on function definitions provided by
arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c
when they include the header.

This is an unusual header dependency, and prevents the use of
arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would
result in compiler warnings regarding missing definitions, e.g.

| In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8:
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined
|   733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
|       |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~
| ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined
|   735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
|       |             ^~~~~~~~~~~~~~~~~

Refactor the logic such that the header doesn't depend on anything from
the C files. There should be no functional change as a result of this
patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Mark Brown <broonie at kernel.org>
Tested-by: Mark Brown <broonie at kernel.org>
Acked-by: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Fuad Tabba <tabba at google.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Oliver Upton <oliver.upton at linux.dev>
Reviewed-by: Oliver Upton <oliver.upton at linux.dev>
Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland at arm.com
Signed-off-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |   30 ++++++------------------------
 arch/arm64/kvm/hyp/nvhe/switch.c        |   27 +++++++++++++++------------
 arch/arm64/kvm/hyp/vhe/switch.c         |    9 ++++-----
 3 files changed, 25 insertions(+), 41 deletions(-)

--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -592,23 +592,16 @@ static bool kvm_hyp_handle_dabt_low(stru
 
 typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
-
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
-
 /*
  * Allow the hypervisor to handle the exit with an exit handler if it has one.
  *
  * Returns true if the hypervisor handled the exit, and control should go back
  * to the guest, or false if it hasn't.
  */
-static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				       const exit_handler_fn *handlers)
 {
-	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
-	exit_handler_fn fn;
-
-	fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
-
+	exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
 	if (fn)
 		return fn(vcpu, exit_code);
 
@@ -638,20 +631,9 @@ static inline void synchronize_vcpu_psta
  * the guest, false when we should restore the host state and return to the
  * main run loop.
  */
-static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
+				      const exit_handler_fn *handlers)
 {
-	/*
-	 * Save PSTATE early so that we can evaluate the vcpu mode
-	 * early on.
-	 */
-	synchronize_vcpu_pstate(vcpu, exit_code);
-
-	/*
-	 * Check whether we want to repaint the state one way or
-	 * another.
-	 */
-	early_exit_filter(vcpu, exit_code);
-
 	if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
 		vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
 
@@ -681,7 +663,7 @@ static inline bool fixup_guest_exit(stru
 		goto exit;
 
 	/* Check if there's an exit handler and allow it to handle the exit. */
-	if (kvm_hyp_handle_exit(vcpu, exit_code))
+	if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
 		goto guest;
 exit:
 	/* Return to the host kernel and handle the exit */
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -225,21 +225,22 @@ static const exit_handler_fn *kvm_get_ex
 	return hyp_exit_handlers;
 }
 
-/*
- * Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
- * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
- * guest from dropping to AArch32 EL0 if implemented by the CPU. If the
- * hypervisor spots a guest in such a state ensure it is handled, and don't
- * trust the host to spot or fix it.  The check below is based on the one in
- * kvm_arch_vcpu_ioctl_run().
- *
- * Returns false if the guest ran in AArch32 when it shouldn't have, and
- * thus should exit to the host, or true if a the guest run loop can continue.
- */
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
+	const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
 	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 
+	synchronize_vcpu_pstate(vcpu, exit_code);
+
+	/*
+	 * Some guests (e.g., protected VMs) are not be allowed to run in
+	 * AArch32.  The ARMv8 architecture does not give the hypervisor a
+	 * mechanism to prevent a guest from dropping to AArch32 EL0 if
+	 * implemented by the CPU. If the hypervisor spots a guest in such a
+	 * state ensure it is handled, and don't trust the host to spot or fix
+	 * it.  The check below is based on the one in
+	 * kvm_arch_vcpu_ioctl_run().
+	 */
 	if (kvm_vm_is_protected(kvm) && vcpu_mode_is_32bit(vcpu)) {
 		/*
 		 * As we have caught the guest red-handed, decide that it isn't
@@ -252,6 +253,8 @@ static void early_exit_filter(struct kvm
 		*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
 		*exit_code |= ARM_EXCEPTION_IL;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, handlers);
 }
 
 /* Switch to the guest for legacy non-VHE systems */
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -172,13 +172,10 @@ static const exit_handler_fn hyp_exit_ha
 	[ESR_ELx_EC_PAC]		= kvm_hyp_handle_ptrauth,
 };
 
-static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
+static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 {
-	return hyp_exit_handlers;
-}
+	synchronize_vcpu_pstate(vcpu, exit_code);
 
-static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
-{
 	/*
 	 * If we were in HYP context on entry, adjust the PSTATE view
 	 * so that the usual helpers work correctly.
@@ -198,6 +195,8 @@ static void early_exit_filter(struct kvm
 		*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
 		*vcpu_cpsr(vcpu) |= mode;
 	}
+
+	return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */


Patches currently in stable-queue which might be from broonie at kernel.org are

queue-6.6/kvm-arm64-calculate-cptr_el2-traps-on-activating-traps.patch
queue-6.6/regulator-check-that-dummy-regulator-has-been-probed-before-using-it.patch
queue-6.6/kvm-arm64-eagerly-switch-zcr_el-1-2.patch
queue-6.6/kvm-arm64-mark-some-header-functions-as-inline.patch
queue-6.6/kvm-arm64-remove-host-fpsimd-saving-for-non-protected-kvm.patch
queue-6.6/regulator-dummy-force-synchronous-probing.patch
queue-6.6/kvm-arm64-refactor-exit-handlers.patch
queue-6.6/kvm-arm64-unconditionally-save-flush-host-fpsimd-sve-sme-state.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.smen.patch
queue-6.6/kvm-arm64-remove-vhe-host-restore-of-cpacr_el1.zen.patch


From kuba at kernel.org  Tue Mar 25 04:41:26 2025
From: kuba at kernel.org (Jakub Kicinski)
Date: Tue, 25 Mar 2025 04:41:26 -0700
Subject: [PATCH net-next v2 4/7] net: octeontx2: Add metadata support
 for xdp mode
In-Reply-To: <20250318-mvneta-xdp-meta-v2-4-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
	<20250318-mvneta-xdp-meta-v2-4-b6075778f61f@kernel.org>
Message-ID: <20250325044126.1c0f9b83@kernel.org>

On Tue, 18 Mar 2025 12:46:08 +0100 Lorenzo Bianconi wrote:
> @@ -1514,13 +1518,14 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
>  
>  	hard_start = (unsigned char *)phys_to_virt(pa);
>  	xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM,
> -			 cqe->sg.seg_size, false);
> +			 cqe->sg.seg_size, true);
>  
>  	act = bpf_prog_run_xdp(prog, &xdp);
>  
>  handle_xdp_verdict:
>  	switch (act) {
>  	case XDP_PASS:
> +		*metasize = xdp.data - xdp.data_meta;
>  		break;
>  	case XDP_TX:
>  		qidx += pfvf->hw.tx_queues;

This one handles ABORT and invalid return codes as PASS not DROP.
That should probably be fixed separately?


From patchwork-bot+netdevbpf at kernel.org  Tue Mar 25 04:50:35 2025
From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org)
Date: Tue, 25 Mar 2025 11:50:35 +0000
Subject: [PATCH net-next v2 0/7] net: xdp: Add missing metadata support for
 some xdp drvs
In-Reply-To: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
References: <20250318-mvneta-xdp-meta-v2-0-b6075778f61f@kernel.org>
Message-ID: <174290343526.531918.1341302638467898392.git-patchwork-notify@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba at kernel.org>:

On Tue, 18 Mar 2025 12:46:04 +0100 you wrote:
> Introduce missing metadata support for some xdp drivers setting metadata
> size building the skb from xdp_buff.
> Please note most of the drivers are just compile tested.
> 
> ---
> Changes in v2:
> - Improve commit logs for each patch specifying xdp headroom size for
>   each modified driver.
> - Link to v1: https://lore.kernel.org/r/20250311-mvneta-xdp-meta-v1-0-36cf1c99790e at kernel.org
> 
> [...]

Here is the summary with links:
  - [net-next,v2,1/7] net: mvneta: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/07b2fbffaaea
  - [net-next,v2,2/7] net: mvpp2: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/9a45e193c88a
  - [net-next,v2,3/7] net: netsec: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/a5fec3c88142
  - [net-next,v2,4/7] net: octeontx2: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/33bfff8fc8ba
  - [net-next,v2,5/7] net: ethernet: mediatek: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/74fb1346bc77
  - [net-next,v2,6/7] net: mana: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/c313d35f60c1
  - [net-next,v2,7/7] net: ti: cpsw: Add metadata support for xdp mode
    https://git.kernel.org/netdev/net-next/c/b3a54be70ca6

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From lukma at denx.de  Tue Mar 25 04:57:31 2025
From: lukma at denx.de (Lukasz Majewski)
Date: Tue, 25 Mar 2025 12:57:31 +0100
Subject: [PATCH 0/5] net: mtip: Add support for MTIP imx287 L2 switch driver
Message-ID: <20250325115736.1732721-1-lukma@denx.de>

This patch series adds support for More Than IP's L2 switch driver embedded
in some NXP's SoCs. This one has been tested on imx287, but is also available
in the vf610.

In the past there has been performed some attempts to upstream this driver:
1. The 4.19-cip based one [1]
2. DSA based one for 5.12 [2] - i.e. the switch itself was treat as a DSA switch
   with NO tag appended.
3. The extension for FEC driver for 5.12 [3] - the trick here was to fully reuse
   FEC when the in-HW switching is disabled. When bridge offloading is enabled,
   the driver uses already configured MAC and PHY to also configure PHY.

All three approaches were not accepted as eligible for upstreaming.

The driver from this series has floowing features:

1. It is fully separated from fec_main - i.e. can be used interchangeable
   with it. To be more specific - one can build them as modules and
   if required switch between them when e.g. bridge offloading is required.

   To be more specific:
	- Use FEC_MAIN: When one needs support for two ETH ports with separate
	  uDMAs used for both and bridging can be realized in SW.

	- Use MTIPL2SW: When it is enough to support two ports with only uDMA0
	  attached to switch and bridging shall be offloaded to HW. 
	
2. This driver uses MTIP's L2 switch internal VLAN feature to provide port
   separation at boot time. Port separation is disabled when bridging is
   required.

3. Example usage:
	Configuration:
	ip link set lan0 up; sleep 1;
	ip link set lan1 up; sleep 1;
	ip link add name br0 type bridge;
	ip link set br0 up; sleep 1;
	ip link set lan0 master br0;
	ip link set lan1 master br0;
	bridge link;
	ip addr add 192.168.2.17/24 dev br0;
	ping -c 5 192.168.2.222

	Removal:
	ip link set br0 down;
	ip link delete br0 type bridge;
	ip link set dev lan1 down
	ip link set dev lan0 down

4. Limitations:
	- Driver enables and disables switch operation with learning and ageing.
	- Missing is the advanced configuration (e.g. adding entries to FBD). This is
	  on purpose, as up till now we didn't had consensus about how the driver
	  shall be added to Linux.
	
Links:
[1] - https://github.com/lmajewski/linux-imx28-l2switch/commits/master
[2] - https://github.com/lmajewski/linux-imx28-l2switch/tree/imx28-v5.12-L2-upstream-RFC_v1
[3] - https://source.denx.de/linux/linux-imx28-l2switch/-/tree/imx28-v5.12-L2-upstream-switchdev-RFC_v1?ref_type=heads



Lukasz Majewski (5):
  MAINTAINERS: Add myself as the MTIP L2 switch maintainer (IMX SoCs:
    imx287)
  dt-bindings: net: Add MTIP L2 switch description
    (fec,mtip-switch.yaml)
  arm: dts: Adjust the 'reg' range for imx287 L2 switch description
  arm: dts: imx287: Provide description for MTIP L2 switch
  net: mtip: The L2 switch driver for imx287

 .../bindings/net/fec,mtip-switch.yaml         |  160 ++
 MAINTAINERS                                   |    7 +
 arch/arm/boot/dts/nxp/mxs/imx28-xea.dts       |   56 +
 arch/arm/boot/dts/nxp/mxs/imx28.dtsi          |    4 +-
 drivers/net/ethernet/freescale/Kconfig        |    1 +
 drivers/net/ethernet/freescale/Makefile       |    1 +
 drivers/net/ethernet/freescale/mtipsw/Kconfig |   10 +
 .../net/ethernet/freescale/mtipsw/Makefile    |    6 +
 .../net/ethernet/freescale/mtipsw/mtipl2sw.c  | 2108 +++++++++++++++++
 .../net/ethernet/freescale/mtipsw/mtipl2sw.h  |  784 ++++++
 .../ethernet/freescale/mtipsw/mtipl2sw_br.c   |  113 +
 .../ethernet/freescale/mtipsw/mtipl2sw_mgnt.c |  434 ++++
 12 files changed, 3682 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/fec,mtip-switch.yaml
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/Kconfig
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/Makefile
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw.h
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw_br.c
 create mode 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw_mgnt.c

-- 
2.39.5



From lukma at denx.de  Tue Mar 25 04:57:33 2025
From: lukma at denx.de (Lukasz Majewski)
Date: Tue, 25 Mar 2025 12:57:33 +0100
Subject: [PATCH 2/5] dt-bindings: net: Add MTIP L2 switch description (fec,mtip-switch.yaml)
In-Reply-To: <20250325115736.1732721-1-lukma@denx.de>
References: <20250325115736.1732721-1-lukma@denx.de>
Message-ID: <20250325115736.1732721-3-lukma@denx.de>

This patch provides description of the MTIP L2 switch available in some
NXP's SOCs - imx287, vf610.

Signed-off-by: Lukasz Majewski <lukma at denx.de>
---
 .../bindings/net/fec,mtip-switch.yaml         | 160 ++++++++++++++++++
 1 file changed, 160 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/fec,mtip-switch.yaml

diff --git a/Documentation/devicetree/bindings/net/fec,mtip-switch.yaml b/Documentation/devicetree/bindings/net/fec,mtip-switch.yaml
new file mode 100644
index 000000000000..cd85385e0f79
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fec,mtip-switch.yaml
@@ -0,0 +1,160 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/fsl,mtip-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale MTIP Level 2 (L2) switch
+
+maintainers:
+  - Lukasz Majewski <lukma at denx.de>
+
+allOf:
+  - $ref: ethernet-controller.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+	  - imx287-mtip-switch
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 3
+
+  clocks:
+    maxItems: 4
+    description:
+      The "ipg", for MAC ipg_clk_s, ipg_clk_mac_s that are for register accessing.
+      The "ahb", for MAC ipg_clk, ipg_clk_mac that are bus clock.
+      The "ptp"(option), for IEEE1588 timer clock that requires the clock.
+      The "enet_out"(option), output clock for external device, like supply clock
+      for PHY. The clock is required if PHY clock source from SOC.
+
+  clock-names:
+    minItems: 4
+    maxItems: 4
+    items:
+      enum:
+	- ipg
+	- ahb
+	- ptp
+	- enet_out
+
+  phy-supply:
+    description:
+      Regulator that powers the Ethernet PHY.
+
+  phy-reset-gpios:
+    deprecated: true
+    description:
+      Should specify the gpio for phy reset.
+
+  phy-reset-duration:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    deprecated: true
+    description:
+      Reset duration in milliseconds.  Should present only if property
+      "phy-reset-gpios" is available.  Missing the property will have the
+      duration be 1 millisecond.  Numbers greater than 1000 are invalid
+      and 1 millisecond will be used instead.
+
+  phy-reset-post-delay:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    deprecated: true
+    description:
+      Post reset delay in milliseconds. If present then a delay of phy-reset-post-delay
+      milliseconds will be observed after the phy-reset-gpios has been toggled.
+      Can be omitted thus no delay is observed. Delay is in range of 1ms to 1000ms.
+      Other delays are invalid.
+
+  mdio:
+    $ref: mdio.yaml#
+    unevaluatedProperties: false
+    description:
+      Specifies the mdio bus in the FEC, used as a container for phy nodes.
+
+  ethernet-ports:
+    type: object
+    additionalProperties: false
+
+    patternProperties:
+      "^port@[0-9a-f]+$":
+	$ref: /schemas/net/ethernet-switch-controller.yaml#
+	unevaluatedProperties: false
+
+	properties:
+	  reg:
+	    description: Switch port number
+
+	required:
+	  - reg
+	  - phy-mode
+	  - phy-handle
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - mdio
+  - ethernet-ports
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    switch at 800f0000 {
+	compatible = "fsl,imx287-mtip-switch";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mac0_pins_a>, <&mac1_pins_a>;
+	phy-supply = <&reg_fec_3v3>;
+	phy-reset-duration = <25>;
+	phy-reset-post-delay = <10>;
+	interrupts = <100>, <101>, <102>;
+	clocks = <&clks 57>, <&clks 57>, <&clks 64>, <&clks 35>;
+	clock-names = "ipg", "ahb", "enet_out", "ptp";
+	status = "okay";
+
+	ethernet-ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mtip_port1: port at 1 {
+			reg = <1>;
+			label = "lan0";
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-mode = "rmii";
+			phy-handle = <&ethphy0>;
+		};
+
+		mtip_port2: port at 2 {
+			reg = <2>;
+			label = "lan1";
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-mode = "rmii";
+			phy-handle = <&ethphy1>;
+		};
+	};
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 0 {
+			reg = <0>;
+			smsc,disable-energy-detect;
+			/* Both PHYs (i.e. 0,1) have the same, single GPIO, */
+			/* line to handle both, their interrupts (AND'ed) */
+			interrupt-parent = <&gpio4>;
+			interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		};
+
+		ethphy1: ethernet-phy at 1 {
+			reg = <1>;
+			smsc,disable-energy-detect;
+			interrupt-parent = <&gpio4>;
+			interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+    };
-- 
2.39.5



From lukma at denx.de  Tue Mar 25 04:57:34 2025
From: lukma at denx.de (Lukasz Majewski)
Date: Tue, 25 Mar 2025 12:57:34 +0100
Subject: [PATCH 3/5] arm: dts: Adjust the 'reg' range for imx287 L2 switch description
In-Reply-To: <20250325115736.1732721-1-lukma@denx.de>
References: <20250325115736.1732721-1-lukma@denx.de>
Message-ID: <20250325115736.1732721-4-lukma@denx.de>

The current range of 'reg' property is too small to allow full control
of the L2 switch on imx287.

As this IP block also uses ENET-MAC blocks for its operation, the address
range for it must be included as well.

Signed-off-by: Lukasz Majewski <lukma at denx.de>
---
 arch/arm/boot/dts/nxp/mxs/imx28.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
index bbea8b77386f..8f2aa32208cf 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
+++ b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
@@ -1321,8 +1321,8 @@ mac1: ethernet at 800f4000 {
 			status = "disabled";
 		};
 
-		eth_switch: switch at 800f8000 {
-			reg = <0x800f8000 0x8000>;
+		eth_switch: switch at 800f0000 {
+			reg = <0x800f0000 0x20000>;
 			status = "disabled";
 		};
 	};
-- 
2.39.5



From lukma at denx.de  Tue Mar 25 04:57:35 2025
From: lukma at denx.de (Lukasz Majewski)
Date: Tue, 25 Mar 2025 12:57:35 +0100
Subject: [PATCH 4/5] arm: dts: imx287: Provide description for MTIP L2 switch
In-Reply-To: <20250325115736.1732721-1-lukma@denx.de>
References: <20250325115736.1732721-1-lukma@denx.de>
Message-ID: <20250325115736.1732721-5-lukma@denx.de>

This description is similar to one supprted with the cpsw_new.c
driver.

It has separated ports and PHYs (connected to mdio bus).

Signed-off-by: Lukasz Majewski <lukma at denx.de>
---
 arch/arm/boot/dts/nxp/mxs/imx28-xea.dts | 56 +++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts b/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
index 6c5e6856648a..e645b086574d 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include<dt-bindings/interrupt-controller/irq.h>
 #include "imx28-lwe.dtsi"
 
 / {
@@ -18,6 +19,61 @@ &can0 {
 	status = "okay";
 };
 
+&eth_switch {
+	compatible = "fsl,imx287-mtip-switch";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mac0_pins_a>, <&mac1_pins_a>;
+	phy-supply = <&reg_fec_3v3>;
+	phy-reset-duration = <25>;
+	phy-reset-post-delay = <10>;
+	interrupts = <100>, <101>, <102>;
+	clocks = <&clks 57>, <&clks 57>, <&clks 64>, <&clks 35>;
+	clock-names = "ipg", "ahb", "enet_out", "ptp";
+	status = "okay";
+
+	ethernet-ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mtip_port1: port at 1 {
+			reg = <1>;
+			label = "lan0";
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-mode = "rmii";
+			phy-handle = <&ethphy0>;
+		};
+
+		mtip_port2: port at 2 {
+			reg = <2>;
+			label = "lan1";
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-mode = "rmii";
+			phy-handle = <&ethphy1>;
+		};
+	};
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 0 {
+			reg = <0>;
+			smsc,disable-energy-detect;
+			/* Both PHYs (i.e. 0,1) have the same, single GPIO, */
+			/* line to handle both, their interrupts (AND'ed) */
+			interrupt-parent = <&gpio4>;
+			interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		};
+
+		ethphy1: ethernet-phy at 1 {
+			reg = <1>;
+			smsc,disable-energy-detect;
+			interrupt-parent = <&gpio4>;
+			interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+};
+
 &i2c1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c1_pins_b>;
-- 
2.39.5



From james.clark at linaro.org  Tue Mar 25 04:58:45 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:45 +0000
Subject: [PATCH v4 0/7] coresight: Clear self hosted claim tag on probe
Message-ID: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>

I've gotten stuck a few times with unusable Coresight after a warm boot
due to lingering claim tags, especially when testing the Coresight
panic patchsets.

This change does some tidy ups, adds some debug messages and clears the
self hosted claim tag on probe. The last two commits are unrelated
tidyups but they touch some of the same functions so to avoid extra
conflicts I'm including them here.

This gets as far as fixing the claim tag issue, but there is some other
state not being cleared on probe that results in the following error.
This can be fixed up as a later change:

  coresight tmc_etf0: timeout while waiting for TMC to be Ready
  coresight tmc_etf0: Failed to enable : TMC is not ready

Changes in v4:
- Add _unlocked() suffix for consistency
- s/cs_access/csdev_access/

- Link to v3: https://lore.kernel.org/r/20250320-james-coresight-claim-tags-v3-0-d3145c153820 at linaro.org

Changes in v3:
- Collapse rename and locked/unlocked addition commits of
  coresight_clear_self_claim_tag() so we don't change the name twice.
- Make coresight_clear_self_claim_tag() a bit more generic by only
  doing UNLOCK for MMIO devices (although there is no use of this right
  now)
- Link to v2: https://lore.kernel.org/r/20250318-james-coresight-claim-tags-v2-0-e9c8a9cde84e at linaro.org

Changes in v2:
 * Revert most of the interface changes, just call
   coresight_clear_self_claim_tag() directly. This is possible because
   we're not doing the read first, so it has fewer knock on effects.
 * Split out the change to add struct cs_access to etm3x
 * Add another warning for racing with external debugger

--
2.34.1

---
James Clark (7):
      coresight: Convert tag clear function to take a struct csdev_access
      coresight: Only check bottom two claim bits
      coresight: Add claim tag warnings and debug messages
      coresight: etm3x: Convert raw base pointer to struct coresight access
      coresight: Clear self hosted claim tag on probe
      coresight: Remove inlines from static function definitions
      coresight: Remove extern from function declarations

 drivers/hwtracing/coresight/coresight-catu.c       | 12 +--
 drivers/hwtracing/coresight/coresight-core.c       | 87 ++++++++++++++--------
 drivers/hwtracing/coresight/coresight-cti-core.c   |  2 +
 drivers/hwtracing/coresight/coresight-etb10.c      |  4 +-
 drivers/hwtracing/coresight/coresight-etm.h        |  6 +-
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 28 +++----
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++-
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 +-
 drivers/hwtracing/coresight/coresight-funnel.c     |  1 +
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++----
 drivers/hwtracing/coresight/coresight-priv.h       | 20 ++---
 drivers/hwtracing/coresight/coresight-replicator.c |  3 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 +-
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  9 ++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++--
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 ++---
 include/linux/coresight.h                          | 40 +++++-----
 19 files changed, 168 insertions(+), 134 deletions(-)
---
base-commit: 5442d22da7dbff3ba8c6720fc6f23ea4934d402d
change-id: 20250317-james-coresight-claim-tags-ae1461f1f5e0

Best regards,
-- 
James Clark <james.clark at linaro.org>



From james.clark at linaro.org  Tue Mar 25 04:58:46 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:46 +0000
Subject: [PATCH v4 1/7] coresight: Convert tag clear function to take a
 struct csdev_access
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-1-dfbd3822b2e5@linaro.org>

The self hosted claim tag will be reset on device probe in a later
commit. We'll want to do this before coresight_register() is called so
won't have a coresight_device and have to use csdev_access instead.

Also make them public and create locked and unlocked versions for
later use.

These look functions look like they set the whole tags register as one
value, but they only set and clear the self hosted bit using a SET/CLR
bits mechanism so also rename the functions to reflect this better.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 33 ++++++++++++++++++----------
 include/linux/coresight.h                    |  3 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index fb43ef6a3b1f..d895815dee1d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -129,34 +129,45 @@ coresight_find_out_connection(struct coresight_device *csdev,
 	return ERR_PTR(-ENODEV);
 }
 
-static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
+static inline u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
 {
 	return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
 }
 
 static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
 {
-	return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
+	return coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
 }
 
 static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
 {
-	return coresight_read_claim_tags(csdev) != 0;
+	return coresight_read_claim_tags_unlocked(csdev) != 0;
 }
 
-static inline void coresight_set_claim_tags(struct coresight_device *csdev)
+static inline void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
 	isb();
 }
 
-static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
+void coresight_clear_self_claim_tag(struct csdev_access *csa)
 {
-	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
+	if (csa->io_mem)
+		CS_UNLOCK(csa->base);
+	coresight_clear_self_claim_tag_unlocked(csa);
+	if (csa->io_mem)
+		CS_LOCK(csa->base);
+}
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
+
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
+{
+	csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMCLR);
 	isb();
 }
+EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
 
 /*
  * coresight_claim_device_unlocked : Claim the device for self-hosted usage
@@ -176,11 +187,11 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev)
 	if (coresight_is_claimed_any(csdev))
 		return -EBUSY;
 
-	coresight_set_claim_tags(csdev);
+	coresight_set_self_claim_tag_unlocked(csdev);
 	if (coresight_is_claimed_self_hosted(csdev))
 		return 0;
-	/* There was a race setting the tags, clean up and fail */
-	coresight_clear_claim_tags(csdev);
+	/* There was a race setting the tag, clean up and fail */
+	coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	return -EBUSY;
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
@@ -201,7 +212,7 @@ int coresight_claim_device(struct coresight_device *csdev)
 EXPORT_SYMBOL_GPL(coresight_claim_device);
 
 /*
- * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
+ * coresight_disclaim_device_unlocked : Clear the claim tag for the device.
  * Called with CS_UNLOCKed for the component.
  */
 void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
@@ -211,7 +222,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		return;
 
 	if (coresight_is_claimed_self_hosted(csdev))
-		coresight_clear_claim_tags(csdev);
+		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
 		 * The external agent may have not honoured our claim
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d79a242b271d..00134a80d358 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -685,7 +685,8 @@ extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
 
 extern int coresight_claim_device(struct coresight_device *csdev);
 extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
-
+void coresight_clear_self_claim_tag(struct csdev_access *csa);
+void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
 extern void coresight_disclaim_device(struct coresight_device *csdev);
 extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
 extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 25 04:58:47 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:47 +0000
Subject: [PATCH v4 2/7] coresight: Only check bottom two claim bits
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-2-dfbd3822b2e5@linaro.org>

The use of the whole register and == could break the claim mechanism if
any of the other bits are used in the future. The referenced doc "PSCI -
ARM DEN 0022D" also says to only read and clear the bottom two bits.

Use FIELD_GET() to extract only the relevant part.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 3 ++-
 drivers/hwtracing/coresight/coresight-priv.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index d895815dee1d..e0638e5de0e0 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -131,7 +131,8 @@ coresight_find_out_connection(struct coresight_device *csdev,
 
 static inline u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
 {
-	return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
+	return FIELD_GET(CORESIGHT_CLAIM_MASK,
+			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
 static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 82644aff8d2b..38bb4e8b50ef 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -35,6 +35,7 @@ extern const struct device_type coresight_dev_type[];
  * Coresight device CLAIM protocol.
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
+#define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
 #define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
 
 #define TIMEOUT_US		100

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 25 04:58:48 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:48 +0000
Subject: [PATCH v4 3/7] coresight: Add claim tag warnings and debug
 messages
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-3-dfbd3822b2e5@linaro.org>

Add a dev_dbg() message so that external debugger conflicts are more
visible. There are multiple reasons for -EBUSY so a message for this
particular one could be helpful. Add errors for and enumerate all the
other cases that are impossible.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c | 51 +++++++++++++++++-----------
 drivers/hwtracing/coresight/coresight-priv.h |  5 ++-
 2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index e0638e5de0e0..33824f4a631d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -135,16 +135,6 @@ static inline u32 coresight_read_claim_tags_unlocked(struct coresight_device *cs
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
-}
-
-static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
-{
-	return coresight_read_claim_tags_unlocked(csdev) != 0;
-}
-
 static inline void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
@@ -182,18 +172,41 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
  */
 int coresight_claim_device_unlocked(struct coresight_device *csdev)
 {
+	int tag;
+	struct csdev_access *csa;
+
 	if (WARN_ON(!csdev))
 		return -EINVAL;
 
-	if (coresight_is_claimed_any(csdev))
+	csa = &csdev->access;
+	tag = coresight_read_claim_tags_unlocked(csdev);
+
+	switch (tag) {
+	case CORESIGHT_CLAIM_FREE:
+		coresight_set_self_claim_tag_unlocked(csdev);
+		if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
+			return 0;
+
+		/* There was a race setting the tag, clean up and fail */
+		coresight_clear_self_claim_tag_unlocked(csa);
+		dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
 		return -EBUSY;
 
-	coresight_set_self_claim_tag_unlocked(csdev);
-	if (coresight_is_claimed_self_hosted(csdev))
-		return 0;
-	/* There was a race setting the tag, clean up and fail */
-	coresight_clear_self_claim_tag_unlocked(&csdev->access);
-	return -EBUSY;
+	case CORESIGHT_CLAIM_EXTERNAL:
+		/* External debug is an expected state, so log and report BUSY */
+		dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
+		return -EBUSY;
+
+	default:
+	case CORESIGHT_CLAIM_SELF_HOSTED:
+	case CORESIGHT_CLAIM_INVALID:
+		/*
+		 * Warn here because we clear a lingering self hosted tag
+		 * on probe, so other tag combinations are impossible.
+		 */
+		dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
+		return -EBUSY;
+	}
 }
 EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
 
@@ -222,7 +235,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 	if (WARN_ON(!csdev))
 		return;
 
-	if (coresight_is_claimed_self_hosted(csdev))
+	if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
 		coresight_clear_self_claim_tag_unlocked(&csdev->access);
 	else
 		/*
@@ -230,7 +243,7 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
 		 * and has manipulated it. Or something else has seriously
 		 * gone wrong in our driver.
 		 */
-		WARN_ON_ONCE(1);
+		dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
 }
 EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
 
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 38bb4e8b50ef..6e8cf55aee0a 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -36,7 +36,10 @@ extern const struct device_type coresight_dev_type[];
  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
  */
 #define CORESIGHT_CLAIM_MASK		GENMASK(1, 0)
-#define CORESIGHT_CLAIM_SELF_HOSTED	BIT(1)
+#define CORESIGHT_CLAIM_FREE		0
+#define CORESIGHT_CLAIM_EXTERNAL	1
+#define CORESIGHT_CLAIM_SELF_HOSTED	2
+#define CORESIGHT_CLAIM_INVALID		3
 
 #define TIMEOUT_US		100
 #define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 25 04:58:49 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:49 +0000
Subject: [PATCH v4 4/7] coresight: etm3x: Convert raw base pointer to
 struct coresight access
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-4-dfbd3822b2e5@linaro.org>

This is so that etm3x can use the new claim tag functions which take a
csa pointer in a later commit.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm.h        |  6 ++---
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 27 +++++++++++-----------
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  8 +++----
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index 171f1384f7c0..1d753cca2943 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -229,7 +229,7 @@ struct etm_config {
  * @config:	structure holding configuration parameters.
  */
 struct etm_drvdata {
-	void __iomem			*base;
+	struct csdev_access		csa;
 	struct clk			*atclk;
 	struct coresight_device		*csdev;
 	spinlock_t			spinlock;
@@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		writel_relaxed(val, drvdata->base + off);
+		writel_relaxed(val, drvdata->csa.base + off);
 	}
 }
 
@@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
 				"invalid CP14 access to ETM reg: %#x", off);
 		}
 	} else {
-		val = readl_relaxed(drvdata->base + off);
+		val = readl_relaxed(drvdata->csa.base + off);
 	}
 
 	return val;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index 8927bfaf3af2..cfd463ac715c 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
 {
 	u32 etmpdcr;
 
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr |= ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 	/* Ensure pwrup completes before subsequent cp14 accesses */
 	mb();
 	isb();
@@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
 	/* Ensure pending cp14 accesses complete before clearing pwrup */
 	mb();
 	isb();
-	etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+	etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
 	etmpdcr &= ~ETMPDCR_PWD_UP;
-	writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+	writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
 }
 
 /**
@@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	rc = coresight_claim_device_unlocked(csdev);
 	if (rc)
@@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
 	etm_clr_prog(drvdata);
 
 done:
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
 		drvdata->cpu, rc);
@@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
 	struct etm_config *config = &drvdata->config;
 	struct coresight_device *csdev = drvdata->csdev;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	etm_set_prog(drvdata);
 
 	/* Read back sequencer and counters for post trace analysis */
@@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	dev_dbg(&drvdata->csdev->dev,
 		"cpu: %d disable smp call done\n", drvdata->cpu);
@@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return;
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* Setting the prog bit disables tracing immediately */
 	etm_set_prog(drvdata);
@@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
 	etm_set_pwrdwn(drvdata);
 	coresight_disclaim_device_unlocked(csdev);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	/*
 	 * perf will release trace ids when _free_aux()
@@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
 	/* Make sure all registers are accessible */
 	etm_os_unlock(drvdata);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	/* First dummy read */
 	(void)etm_readl(drvdata, ETMPDSR);
@@ -766,7 +766,7 @@ static void etm_init_arch_data(void *info)
 
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 }
 
 static int __init etm_hp_setup(void)
@@ -827,8 +827,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	drvdata->base = base;
-	desc.access = CSDEV_ACCESS_IOMEM(base);
+	desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
 
 	spin_lock_init(&drvdata->spinlock);
 
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
index b9006451f515..762109307b86 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
@@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
 
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 
 	val = etm_readl(drvdata, ETMSR);
 
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);
 
@@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
 	pm_runtime_get_sync(dev->parent);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
-	CS_UNLOCK(drvdata->base);
+	CS_UNLOCK(drvdata->csa.base);
 	val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
-	CS_LOCK(drvdata->base);
+	CS_LOCK(drvdata->csa.base);
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	pm_runtime_put(dev->parent);

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 25 04:58:50 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:50 +0000
Subject: [PATCH v4 5/7] coresight: Clear self hosted claim tag on probe
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-5-dfbd3822b2e5@linaro.org>

This can be left behind from a crashed kernel after a kexec so clear it
when probing each device. Clearing the self hosted bit even when claimed
externally is harmless, so do it unconditionally.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 1 +
 drivers/hwtracing/coresight/coresight-cti-core.c   | 2 ++
 drivers/hwtracing/coresight/coresight-etb10.c      | 2 ++
 drivers/hwtracing/coresight/coresight-etm3x-core.c | 1 +
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 ++
 drivers/hwtracing/coresight/coresight-funnel.c     | 1 +
 drivers/hwtracing/coresight/coresight-replicator.c | 1 +
 drivers/hwtracing/coresight/coresight-tmc-core.c   | 1 +
 8 files changed, 11 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index fa170c966bc3..deaacfd875af 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -558,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
 	catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
 	catu_desc.ops = &catu_ops;
 
+	coresight_clear_self_claim_tag(&catu_desc.access);
 	drvdata->csdev = coresight_register(&catu_desc);
 	if (IS_ERR(drvdata->csdev))
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 80f6265e3740..8fb30dd73fd2 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	cti_desc.ops = &cti_ops;
 	cti_desc.groups = drvdata->ctidev.con_groups;
 	cti_desc.dev = dev;
+
+	coresight_clear_self_claim_tag(&cti_desc.access);
 	drvdata->csdev = coresight_register(&cti_desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 7948597d483d..2bfcb669aa84 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 	desc.pdata = pdata;
 	desc.dev = dev;
 	desc.groups = coresight_etb_groups;
+
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev))
 		return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index cfd463ac715c..1c6204e14422 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -764,6 +764,7 @@ static void etm_init_arch_data(void *info)
 	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
+	coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
 	etm_set_pwrdwn(drvdata);
 	etm_clr_pwrup(drvdata);
 	CS_LOCK(drvdata->csa.base);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e5972f16abff..52c9aa56e8b9 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1372,6 +1372,8 @@ static void etm4_init_arch_data(void *info)
 	drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
 	/* NUMCNTR, bits[30:28] number of counters available for tracing */
 	drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
+
+	coresight_clear_self_claim_tag_unlocked(csa);
 	etm4_cs_lock(drvdata, csa);
 	cpu_detect_trace_filtering(drvdata);
 }
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 0541712b2bcb..7249cc356ccb 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
 		drvdata->base = base;
 		desc.groups = coresight_funnel_groups;
 		desc.access = CSDEV_ACCESS_IOMEM(base);
+		coresight_clear_self_claim_tag(&desc.access);
 	}
 
 	dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index ee7ee79f6cf7..b2acd4535c74 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -284,6 +284,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
 	desc.pdata = dev->platform_data;
 	desc.dev = dev;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index a7814e8e657b..a09579eff3fd 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -869,6 +869,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
 	dev->platform_data = pdata;
 	desc.pdata = pdata;
 
+	coresight_clear_self_claim_tag(&desc.access);
 	drvdata->csdev = coresight_register(&desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);

-- 
2.34.1



From james.clark at linaro.org  Tue Mar 25 04:58:51 2025
From: james.clark at linaro.org (James Clark)
Date: Tue, 25 Mar 2025 11:58:51 +0000
Subject: [PATCH v4 6/7] coresight: Remove inlines from static function
 definitions
In-Reply-To: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
References: <20250325-james-coresight-claim-tags-v4-0-dfbd3822b2e5@linaro.org>
Message-ID: <20250325-james-coresight-claim-tags-v4-6-dfbd3822b2e5@linaro.org>

These are all static and in one compilation unit so the inline has no
effect on the binary. Except if FTRACE is enabled, then some functions
which were already not inlined now get the nops added which allows them
to be traced.

Reviewed-by: Leo Yan <leo.yan at arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 drivers/hwtracing/coresight/coresight-catu.c       | 11 +++++----
 drivers/hwtracing/coresight/coresight-core.c       | 14 ++++++------
 drivers/hwtracing/coresight/coresight-etb10.c      |  2 +-
 drivers/hwtracing/coresight/coresight-etm4x-core.c |  8 +++----
 .../hwtracing/coresight/coresight-etm4x-sysfs.c    |  4 ++--
 drivers/hwtracing/coresight/coresight-platform.c   | 26 +++++++++++-----------
 drivers/hwtracing/coresight/coresight-replicator.c |  2 +-
 drivers/hwtracing/coresight/coresight-stm.c        |  6 ++---
 .../coresight/coresight-syscfg-configfs.c          |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  8 +++----
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 16 ++++++-------
 drivers/hwtracing/coresight/coresight-trbe.c       | 18 +++++++--------
 12 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index deaacfd875af..6f411db24a54 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -113,9 +113,8 @@ typedef u64 cate_t;
  * containing the data page pointer for @offset. If @daddrp is not NULL,
  * @daddrp points the DMA address of the beginning of the table.
  */
-static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
-				     unsigned long offset,
-				     dma_addr_t *daddrp)
+static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
+			      dma_addr_t *daddrp)
 {
 	unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
 	unsigned int table_nr, pg_idx, pg_offset;
@@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
 }
 
 #else
-static inline void catu_dump_table(struct tmc_sg_table *catu_table)
+static void catu_dump_table(struct tmc_sg_table *catu_table)
 {
 }
 #endif
 
-static inline cate_t catu_make_entry(dma_addr_t addr)
+static cate_t catu_make_entry(dma_addr_t addr)
 {
 	return addr ? CATU_VALID_ENTRY(addr) : 0;
 }
@@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
 };
 
 
-static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
+static int catu_wait_for_ready(struct catu_drvdata *drvdata)
 {
 	struct csdev_access *csa = &drvdata->csdev->access;
 
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 33824f4a631d..187fa6b1b73d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -129,13 +129,13 @@ coresight_find_out_connection(struct coresight_device *csdev,
 	return ERR_PTR(-ENODEV);
 }
 
-static inline u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
+static u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
 {
 	return FIELD_GET(CORESIGHT_CLAIM_MASK,
 			 csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
 }
 
-static inline void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
+static void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
 {
 	csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
 				     CORESIGHT_CLAIMSET);
@@ -604,7 +604,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
  * Return true in successful case and power up the device.
  * Return false when failed to get reference of module.
  */
-static inline bool coresight_get_ref(struct coresight_device *csdev)
+static bool coresight_get_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -623,7 +623,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
  *
  * @csdev: The coresight device to decrement a reference from.
  */
-static inline void coresight_put_ref(struct coresight_device *csdev)
+static void coresight_put_ref(struct coresight_device *csdev)
 {
 	struct device *dev = csdev->dev.parent;
 
@@ -846,7 +846,7 @@ void coresight_release_path(struct coresight_path *path)
 }
 
 /* return true if the device is a suitable type for a default sink */
-static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
+static bool coresight_is_def_sink_type(struct coresight_device *csdev)
 {
 	/* sink & correct subtype */
 	if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
@@ -1410,8 +1410,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
  *
  * Returns the index of the entry, when found. Otherwise, -ENOENT.
  */
-static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
-					      struct fwnode_handle *fwnode)
+static int coresight_search_device_idx(struct coresight_dev_list *dict,
+				       struct fwnode_handle *fwnode)
 {
 	int i;
 
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 2bfcb669aa84..d5efb085b30d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -95,7 +95,7 @@ struct etb_drvdata {
 static int etb_set_buffer(struct coresight_device *csdev,
 			  struct perf_output_handle *handle);
 
-static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
+static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
 {
 	return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
 }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 52c9aa56e8b9..2ca35ef35f77 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
  *		TRCIDR4.NUMPC > 0b0000 .
  *		TRCSSCSR<n>.PC == 0b1
  */
-static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
+static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
 {
 	return (n < drvdata->nr_ss_cmp) &&
 	       drvdata->nr_pe &&
@@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
 	isb();
 }
 
-static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
+static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
 				      struct c